summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-26 13:57:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-11-02 11:31:01 +0000
commit1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch)
tree8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/third_party/blink
parent21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff)
downloadqtwebengine-chromium-1943b3c2a1dcee36c233724fc4ee7613d71b9cf6.tar.gz
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink')
-rw-r--r--chromium/third_party/blink/DEPS2
-rw-r--r--chromium/third_party/blink/PRESUBMIT.py34
-rwxr-xr-xchromium/third_party/blink/PRESUBMIT_test.py4
-rw-r--r--chromium/third_party/blink/common/BUILD.gn32
-rw-r--r--chromium/third_party/blink/common/DEPS1
-rw-r--r--chromium/third_party/blink/common/OWNERS1
-rw-r--r--chromium/third_party/blink/common/associated_interfaces/associated_interface_provider.cc6
-rw-r--r--chromium/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc1
-rw-r--r--chromium/third_party/blink/common/browser_interface_broker_proxy.cc13
-rw-r--r--chromium/third_party/blink/common/client_hints/client_hints.cc90
-rw-r--r--chromium/third_party/blink/common/client_hints/client_hints_unittest.cc110
-rw-r--r--chromium/third_party/blink/common/client_hints/enabled_client_hints.cc58
-rw-r--r--chromium/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc53
-rw-r--r--chromium/third_party/blink/common/features.cc249
-rw-r--r--chromium/third_party/blink/common/frame/frame_policy.cc20
-rw-r--r--chromium/third_party/blink/common/frame/frame_policy_mojom_traits.cc2
-rw-r--r--chromium/third_party/blink/common/frame/frame_policy_mojom_traits.h4
-rw-r--r--chromium/third_party/blink/common/frame/frame_visual_properties_mojom_traits.cc2
-rw-r--r--chromium/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/common/input/web_coalesced_input_event_mojom_traits.cc4
-rw-r--r--chromium/third_party/blink/common/input/web_gesture_event.cc12
-rw-r--r--chromium/third_party/blink/common/input/web_input_event.cc4
-rw-r--r--chromium/third_party/blink/common/interest_group/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/common/interest_group/OWNERS4
-rw-r--r--chromium/third_party/blink/common/interest_group/interest_group.cc125
-rw-r--r--chromium/third_party/blink/common/interest_group/interest_group_mojom_traits.cc37
-rw-r--r--chromium/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc123
-rw-r--r--chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc1
-rw-r--r--chromium/third_party/blink/common/loader/throttling_url_loader.cc29
-rw-r--r--chromium/third_party/blink/common/loader/throttling_url_loader_unittest.cc25
-rw-r--r--chromium/third_party/blink/common/manifest/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/common/manifest/OWNERS2
-rw-r--r--chromium/third_party/blink/common/manifest/manifest.cc64
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc1
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc156
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_util.cc39
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_util_unittest.cc32
-rw-r--r--chromium/third_party/blink/common/media/watch_time_component_unittest.cc5
-rw-r--r--chromium/third_party/blink/common/media/watch_time_reporter.cc1
-rw-r--r--chromium/third_party/blink/common/mediastream/OWNERS1
-rw-r--r--chromium/third_party/blink/common/messaging/web_message_port.cc8
-rw-r--r--chromium/third_party/blink/common/mime_util/mime_util.cc5
-rw-r--r--chromium/third_party/blink/common/navigation/navigation_params.cc28
-rw-r--r--chromium/third_party/blink/common/navigation/prefetched_signed_exchange_info_mojom_traits.cc27
-rw-r--r--chromium/third_party/blink/common/net/ip_address_space_util.cc74
-rw-r--r--chromium/third_party/blink/common/net/ip_address_space_util_unittest.cc171
-rw-r--r--chromium/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc3
-rw-r--r--chromium/third_party/blink/common/origin_trials/scoped_test_origin_trial_policy.cc53
-rw-r--r--chromium/third_party/blink/common/origin_trials/trial_token.cc22
-rw-r--r--chromium/third_party/blink/common/origin_trials/trial_token_unittest.cc33
-rw-r--r--chromium/third_party/blink/common/origin_trials/trial_token_validator.cc49
-rw-r--r--chromium/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc72
-rw-r--r--chromium/third_party/blink/common/page_state/page_state.cc6
-rw-r--r--chromium/third_party/blink/common/permissions_policy/README.md10
-rw-r--r--chromium/third_party/blink/common/permissions_policy/permissions_policy.cc1
-rw-r--r--chromium/third_party/blink/common/permissions_policy/permissions_policy_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/common/permissions_policy/policy_value.cc14
-rw-r--r--chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector.cc1
-rw-r--r--chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector_unittest.cc2
-rw-r--r--chromium/third_party/blink/common/privacy_budget/identifiability_study_settings.cc47
-rw-r--r--chromium/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc4
-rw-r--r--chromium/third_party/blink/common/privacy_budget/identifiable_token_builder.cc5
-rw-r--r--chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc93
-rw-r--r--chromium/third_party/blink/common/scheme_registry.cc43
-rw-r--r--chromium/third_party/blink/common/security/address_space_feature.cc (renamed from chromium/third_party/blink/renderer/core/loader/address_space_feature.cc)92
-rw-r--r--chromium/third_party/blink/common/security/address_space_feature_unittest.cc (renamed from chromium/third_party/blink/renderer/core/loader/address_space_feature_test.cc)21
-rw-r--r--chromium/third_party/blink/common/storage_key/DIR_METADATA5
-rw-r--r--chromium/third_party/blink/common/storage_key/OWNERS4
-rw-r--r--chromium/third_party/blink/common/storage_key/storage_key.cc90
-rw-r--r--chromium/third_party/blink/common/storage_key/storage_key_mojom_traits.cc31
-rw-r--r--chromium/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc42
-rw-r--r--chromium/third_party/blink/common/storage_key/storage_key_unittest.cc227
-rw-r--r--chromium/third_party/blink/common/switches.cc18
-rw-r--r--chromium/third_party/blink/common/tokens/multi_token_unittest.cc8
-rw-r--r--chromium/third_party/blink/common/unique_name/unique_name_helper.cc2
-rw-r--r--chromium/third_party/blink/common/use_counter/use_counter_feature.cc2
-rw-r--r--chromium/third_party/blink/common/use_counter/use_counter_feature_mojom_traits.cc2
-rw-r--r--chromium/third_party/blink/common/use_counter/use_counter_feature_tracker.cc34
-rw-r--r--chromium/third_party/blink/common/user_agent/user_agent_metadata.cc5
-rw-r--r--chromium/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc1
-rw-r--r--chromium/third_party/blink/common/user_agent/user_agent_mojom_traits.cc4
-rw-r--r--chromium/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc6
-rw-r--r--chromium/third_party/blink/common/widget/screen_info.cc32
-rw-r--r--chromium/third_party/blink/common/widget/screen_info_mojom_traits.cc34
-rw-r--r--chromium/third_party/blink/common/widget/screen_infos.cc36
-rw-r--r--chromium/third_party/blink/common/widget/screen_infos_mojom_traits.cc29
-rw-r--r--chromium/third_party/blink/common/widget/screen_infos_mojom_traits_unittest.cc58
-rw-r--r--chromium/third_party/blink/common/widget/visual_properties.cc3
-rw-r--r--chromium/third_party/blink/common/widget/visual_properties_mojom_traits.cc3
-rw-r--r--chromium/third_party/blink/manual_tests/forms/calendar-picker.html52
-rw-r--r--chromium/third_party/blink/manual_tests/svg-text-selection.svg9
-rw-r--r--chromium/third_party/blink/public/BUILD.gn10
-rw-r--r--chromium/third_party/blink/public/OWNERS1
-rw-r--r--chromium/third_party/blink/public/blink_resources.grd6
-rw-r--r--chromium/third_party/blink/public/common/BUILD.gn15
-rw-r--r--chromium/third_party/blink/public/common/DEPS3
-rw-r--r--chromium/third_party/blink/public/common/associated_interfaces/associated_interface_provider.h7
-rw-r--r--chromium/third_party/blink/public/common/associated_interfaces/associated_interface_registry.h6
-rw-r--r--chromium/third_party/blink/public/common/browser_interface_broker_proxy.h6
-rw-r--r--chromium/third_party/blink/public/common/client_hints/client_hints.h12
-rw-r--r--chromium/third_party/blink/public/common/client_hints/enabled_client_hints.h46
-rw-r--r--chromium/third_party/blink/public/common/context_menu_data/context_menu_data.h1
-rw-r--r--chromium/third_party/blink/public/common/context_menu_data/context_menu_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/public/common/features.h123
-rw-r--r--chromium/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h4
-rw-r--r--chromium/third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h1
-rw-r--r--chromium/third_party/blink/public/common/frame/frame_policy.h27
-rw-r--r--chromium/third_party/blink/public/common/frame/frame_visual_properties.h4
-rw-r--r--chromium/third_party/blink/public/common/frame/frame_visual_properties_mojom_traits.h3
-rw-r--r--chromium/third_party/blink/public/common/input/web_gesture_event.h15
-rw-r--r--chromium/third_party/blink/public/common/input/web_input_event.h6
-rw-r--r--chromium/third_party/blink/public/common/interest_group/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/public/common/interest_group/OWNERS4
-rw-r--r--chromium/third_party/blink/public/common/interest_group/interest_group.h84
-rw-r--r--chromium/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h88
-rw-r--r--chromium/third_party/blink/public/common/loader/loader_constants.h8
-rw-r--r--chromium/third_party/blink/public/common/loader/loading_behavior_flag.h20
-rw-r--r--chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h4
-rw-r--r--chromium/third_party/blink/public/common/loader/throttling_url_loader.h12
-rw-r--r--chromium/third_party/blink/public/common/loader/url_loader_factory_bundle.h14
-rw-r--r--chromium/third_party/blink/public/common/manifest/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/public/common/manifest/OWNERS2
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest.h163
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest_icon_selector.h8
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest_mojom_traits.h197
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest_util.h15
-rw-r--r--chromium/third_party/blink/public/common/media/display_type.h2
-rw-r--r--chromium/third_party/blink/public/common/media/watch_time_component.h7
-rw-r--r--chromium/third_party/blink/public/common/media/watch_time_reporter.h10
-rw-r--r--chromium/third_party/blink/public/common/mediastream/OWNERS1
-rw-r--r--chromium/third_party/blink/public/common/mediastream/media_devices.h1
-rw-r--r--chromium/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/public/common/mediastream/media_stream_request.h1
-rw-r--r--chromium/third_party/blink/public/common/messaging/cloneable_message.h4
-rw-r--r--chromium/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/public/common/messaging/message_port_channel.h1
-rw-r--r--chromium/third_party/blink/public/common/messaging/transferable_message.h5
-rw-r--r--chromium/third_party/blink/public/common/messaging/web_message_port.h4
-rw-r--r--chromium/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h1
-rw-r--r--chromium/third_party/blink/public/common/navigation/impression.h1
-rw-r--r--chromium/third_party/blink/public/common/navigation/impression_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/public/common/navigation/navigation_params.h20
-rw-r--r--chromium/third_party/blink/public/common/navigation/navigation_params_mojom_traits.h28
-rw-r--r--chromium/third_party/blink/public/common/navigation/prefetched_signed_exchange_info_mojom_traits.h32
-rw-r--r--chromium/third_party/blink/public/common/net/ip_address_space_util.h59
-rw-r--r--chromium/third_party/blink/public/common/notifications/notification_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/public/common/origin_trials/origin_trial_policy.h7
-rw-r--r--chromium/third_party/blink/public/common/origin_trials/origin_trial_public_key.h17
-rw-r--r--chromium/third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h31
-rw-r--r--chromium/third_party/blink/public/common/origin_trials/trial_token.h12
-rw-r--r--chromium/third_party/blink/public/common/origin_trials/trial_token_validator.h32
-rw-r--r--chromium/third_party/blink/public/common/page/content_to_visible_time_reporter.h1
-rw-r--r--chromium/third_party/blink/public/common/page_state/page_state.h3
-rw-r--r--chromium/third_party/blink/public/common/permissions_policy/document_policy.h6
-rw-r--r--chromium/third_party/blink/public/common/permissions_policy/permissions_policy.h5
-rw-r--r--chromium/third_party/blink/public/common/permissions_policy/permissions_policy_features.h1
-rw-r--r--chromium/third_party/blink/public/common/permissions_policy/policy_value.h6
-rw-r--r--chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h6
-rw-r--r--chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h14
-rw-r--r--chromium/third_party/blink/public/common/privacy_budget/identifiable_surface.h17
-rw-r--r--chromium/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h4
-rw-r--r--chromium/third_party/blink/public/common/sampling_heap_profiler/OWNERS1
-rw-r--r--chromium/third_party/blink/public/common/scheduler/PRESUBMIT.py3
-rw-r--r--chromium/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h31
-rw-r--r--chromium/third_party/blink/public/common/scheme_registry.h37
-rw-r--r--chromium/third_party/blink/public/common/security/address_space_feature.h (renamed from chromium/third_party/blink/renderer/core/loader/address_space_feature.h)50
-rw-r--r--chromium/third_party/blink/public/common/service_worker/service_worker_loader_helpers.h1
-rw-r--r--chromium/third_party/blink/public/common/sms/webotp_service_outcome.h3
-rw-r--r--chromium/third_party/blink/public/common/storage_key/DIR_METADATA5
-rw-r--r--chromium/third_party/blink/public/common/storage_key/OWNERS4
-rw-r--r--chromium/third_party/blink/public/common/storage_key/storage_key.h111
-rw-r--r--chromium/third_party/blink/public/common/storage_key/storage_key_mojom_traits.h41
-rw-r--r--chromium/third_party/blink/public/common/switches.h3
-rw-r--r--chromium/third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h6
-rw-r--r--chromium/third_party/blink/public/common/tokens/BUILD.gn1
-rw-r--r--chromium/third_party/blink/public/common/tokens/README.md2
-rw-r--r--chromium/third_party/blink/public/common/tokens/multi_token.h4
-rw-r--r--chromium/third_party/blink/public/common/tokens/multi_token_internal.h22
-rw-r--r--chromium/third_party/blink/public/common/tokens/token_mojom_traits_helper.h2
-rw-r--r--chromium/third_party/blink/public/common/tokens/tokens.h28
-rw-r--r--chromium/third_party/blink/public/common/tokens/tokens_mojom_traits.h7
-rw-r--r--chromium/third_party/blink/public/common/unique_name/unique_name_helper.h12
-rw-r--r--chromium/third_party/blink/public/common/use_counter/use_counter_feature_tracker.h12
-rw-r--r--chromium/third_party/blink/public/common/user_agent/user_agent_metadata.h1
-rw-r--r--chromium/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h4
-rw-r--r--chromium/third_party/blink/public/common/web_preferences/web_preferences.h6
-rw-r--r--chromium/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h10
-rw-r--r--chromium/third_party/blink/public/common/widget/device_emulation_params.h6
-rw-r--r--chromium/third_party/blink/public/common/widget/device_emulation_params_mojom_traits.h3
-rw-r--r--chromium/third_party/blink/public/common/widget/screen_info.h121
-rw-r--r--chromium/third_party/blink/public/common/widget/screen_info_mojom_traits.h68
-rw-r--r--chromium/third_party/blink/public/common/widget/screen_infos.h37
-rw-r--r--chromium/third_party/blink/public/common/widget/screen_infos_mojom_traits.h40
-rw-r--r--chromium/third_party/blink/public/common/widget/visual_properties.h11
-rw-r--r--chromium/third_party/blink/public/common/widget/visual_properties_mojom_traits.h8
-rw-r--r--chromium/third_party/blink/public/devtools_protocol/OWNERS1
-rw-r--r--chromium/third_party/blink/public/devtools_protocol/browser_protocol.pdl364
-rw-r--r--chromium/third_party/blink/public/mojom/BUILD.gn99
-rw-r--r--chromium/third_party/blink/public/mojom/ad_tagging/ad_frame.mojom16
-rw-r--r--chromium/third_party/blink/public/mojom/background_sync/OWNERS3
-rw-r--r--chromium/third_party/blink/public/mojom/blob/blob_url_store.mojom22
-rw-r--r--chromium/third_party/blink/public/mojom/choosers/color_chooser.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom73
-rw-r--r--chromium/third_party/blink/public/mojom/clipboard/raw_clipboard.mojom41
-rw-r--r--chromium/third_party/blink/public/mojom/conversions/conversions.mojom35
-rw-r--r--chromium/third_party/blink/public/mojom/cookie_manager/OWNERS4
-rw-r--r--chromium/third_party/blink/public/mojom/cookie_manager/cookie_manager_automation.mojom12
-rw-r--r--chromium/third_party/blink/public/mojom/crash/OWNERS3
-rw-r--r--chromium/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/css/preferred_contrast.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/devtools/inspector_issue.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/dom_storage/dom_storage.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/dom_storage/storage_area.mojom70
-rw-r--r--chromium/third_party/blink/public/mojom/fetch/fetch_api_request.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom5
-rw-r--r--chromium/third_party/blink/public/mojom/file/file_utilities.mojom29
-rw-r--r--chromium/third_party/blink/public/mojom/file_system_access/file_system_access_access_handle_host.mojom29
-rw-r--r--chromium/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom6
-rw-r--r--chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_delegate_host.mojom42
-rw-r--r--chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom21
-rw-r--r--chromium/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/font_unique_name_lookup/OWNERS2
-rw-r--r--chromium/third_party/blink/public/mojom/frame/frame.mojom52
-rw-r--r--chromium/third_party/blink/public/mojom/frame/frame_owner_element_type.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/frame/frame_policy.mojom8
-rw-r--r--chromium/third_party/blink/public/mojom/frame/frame_replication_state.mojom15
-rw-r--r--chromium/third_party/blink/public/mojom/frame/frame_visual_properties.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom22
-rw-r--r--chromium/third_party/blink/public/mojom/handwriting/handwriting.mojom5
-rw-r--r--chromium/third_party/blink/public/mojom/hyphenation/OWNERS3
-rw-r--r--chromium/third_party/blink/public/mojom/input/input_handler.mojom6
-rw-r--r--chromium/third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom11
-rw-r--r--chromium/third_party/blink/public/mojom/interest_group/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/public/mojom/interest_group/OWNERS2
-rw-r--r--chromium/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom22
-rw-r--r--chromium/third_party/blink/public/mojom/leak_detector/leak_detector.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/link_to_text/link_to_text.mojom18
-rw-r--r--chromium/third_party/blink/public/mojom/loader/resource_load_info.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/loader/same_document_navigation_type.mojom17
-rw-r--r--chromium/third_party/blink/public/mojom/manifest/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/public/mojom/manifest/OWNERS2
-rw-r--r--chromium/third_party/blink/public/mojom/manifest/display_mode.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/manifest/manifest.mojom53
-rw-r--r--chromium/third_party/blink/public/mojom/manifest/manifest_observer.mojom5
-rw-r--r--chromium/third_party/blink/public/mojom/mediastream/OWNERS1
-rw-r--r--chromium/third_party/blink/public/mojom/mediastream/media_stream.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/navigation/navigation_params.mojom483
-rw-r--r--chromium/third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom27
-rw-r--r--chromium/third_party/blink/public/mojom/navigation/was_activated_option.mojom19
-rw-r--r--chromium/third_party/blink/public/mojom/optimization_guide/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/public/mojom/optimization_guide/OWNERS7
-rw-r--r--chromium/third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom62
-rw-r--r--chromium/third_party/blink/public/mojom/page/page.mojom18
-rw-r--r--chromium/third_party/blink/public/mojom/page/widget.mojom12
-rw-r--r--chromium/third_party/blink/public/mojom/payments/OWNERS4
-rw-r--r--chromium/third_party/blink/public/mojom/payments/payment_credential.mojom13
-rw-r--r--chromium/third_party/blink/public/mojom/payments/payment_request.mojom19
-rw-r--r--chromium/third_party/blink/public/mojom/performance_manager/v8_detailed_memory_reporter.mojom10
-rw-r--r--chromium/third_party/blink/public/mojom/permissions_policy/PRESUBMIT.py3
-rw-r--r--chromium/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom19
-rw-r--r--chromium/third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom11
-rw-r--r--chromium/third_party/blink/public/mojom/prerender/prerender.mojom22
-rw-r--r--chromium/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom32
-rw-r--r--chromium/third_party/blink/public/mojom/shared_storage/OWNERS (renamed from chromium/third_party/blink/public/mojom/insecure_input/OWNERS)0
-rw-r--r--chromium/third_party/blink/public/mojom/shared_storage/shared_storage.mojom16
-rw-r--r--chromium/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom8
-rw-r--r--chromium/third_party/blink/public/mojom/storage_key/DIR_METADATA5
-rw-r--r--chromium/third_party/blink/public/mojom/storage_key/OWNERS4
-rw-r--r--chromium/third_party/blink/public/mojom/storage_key/storage_key.mojom19
-rw-r--r--chromium/third_party/blink/public/mojom/subapps/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/public/mojom/subapps/OWNERS4
-rw-r--r--chromium/third_party/blink/public/mojom/subapps/sub_apps_provider.mojom24
-rw-r--r--chromium/third_party/blink/public/mojom/tokens/BUILD.gn4
-rw-r--r--chromium/third_party/blink/public/mojom/tokens/tokens.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/use_counter/PRESUBMIT.py3
-rw-r--r--chromium/third_party/blink/public/mojom/use_counter/css_property_id.mojom3
-rw-r--r--chromium/third_party/blink/public/mojom/use_counter/use_counter_feature.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/web_feature/PRESUBMIT.py2
-rw-r--r--chromium/third_party/blink/public/mojom/web_feature/web_feature.mojom81
-rw-r--r--chromium/third_party/blink/public/mojom/webauthn/authenticator.mojom17
-rw-r--r--chromium/third_party/blink/public/mojom/webid/federated_auth_request.mojom16
-rw-r--r--chromium/third_party/blink/public/mojom/webpreferences/web_preferences.mojom6
-rw-r--r--chromium/third_party/blink/public/mojom/webshare/OWNERS1
-rw-r--r--chromium/third_party/blink/public/mojom/websockets/websocket_connector.mojom5
-rw-r--r--chromium/third_party/blink/public/mojom/widget/device_emulation_params.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/widget/screen_info.mojom69
-rw-r--r--chromium/third_party/blink/public/mojom/widget/screen_infos.mojom20
-rw-r--r--chromium/third_party/blink/public/mojom/widget/screen_orientation.mojom16
-rw-r--r--chromium/third_party/blink/public/mojom/widget/visual_properties.mojom12
-rw-r--r--chromium/third_party/blink/public/platform/DEPS2
-rw-r--r--chromium/third_party/blink/public/platform/OWNERS2
-rw-r--r--chromium/third_party/blink/public/platform/TaskTypes.md1
-rw-r--r--chromium/third_party/blink/public/platform/child_url_loader_factory_bundle.h7
-rw-r--r--chromium/third_party/blink/public/platform/input/input_handler_proxy.h13
-rw-r--r--chromium/third_party/blink/public/platform/internet_disconnected_web_url_loader.h2
-rw-r--r--chromium/third_party/blink/public/platform/media/BUILD.gn57
-rw-r--r--chromium/third_party/blink/public/platform/media/DEPS20
-rw-r--r--chromium/third_party/blink/public/platform/media/buffered_data_source_host_impl.h102
-rw-r--r--chromium/third_party/blink/public/platform/media/interval_map.h290
-rw-r--r--chromium/third_party/blink/public/platform/media/key_system_config_selector.h155
-rw-r--r--chromium/third_party/blink/public/platform/media/learning_experiment_helper.h52
-rw-r--r--chromium/third_party/blink/public/platform/media/lru.h96
-rw-r--r--chromium/third_party/blink/public/platform/media/multi_buffer.h388
-rw-r--r--chromium/third_party/blink/public/platform/media/multi_buffer_data_source.h300
-rw-r--r--chromium/third_party/blink/public/platform/media/power_status_helper.h151
-rw-r--r--chromium/third_party/blink/public/platform/media/remote_playback_client_wrapper_impl.h33
-rw-r--r--chromium/third_party/blink/public/platform/media/resource_fetch_context.h27
-rw-r--r--chromium/third_party/blink/public/platform/media/smoothness_helper.h69
-rw-r--r--chromium/third_party/blink/public/platform/media/url_index.h313
-rw-r--r--chromium/third_party/blink/public/platform/media/video_frame_compositor.h296
-rw-r--r--chromium/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h80
-rw-r--r--chromium/third_party/blink/public/platform/media/web_media_player_impl.h1047
-rw-r--r--chromium/third_party/blink/public/platform/media/web_media_player_params.h216
-rw-r--r--chromium/third_party/blink/public/platform/modules/mediastream/OWNERS2
-rw-r--r--chromium/third_party/blink/public/platform/modules/mediastream/secure_display_link_tracker.h8
-rw-r--r--chromium/third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h1
-rw-r--r--chromium/third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h14
-rw-r--r--chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_object_info.h7
-rw-r--r--chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h8
-rw-r--r--chromium/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h6
-rw-r--r--chromium/third_party/blink/public/platform/modules/webrtc/DEPS1
-rw-r--r--chromium/third_party/blink/public/platform/modules/webrtc/OWNERS2
-rw-r--r--chromium/third_party/blink/public/platform/modules/webrtc/webrtc_logging.h27
-rw-r--r--chromium/third_party/blink/public/platform/platform.h40
-rw-r--r--chromium/third_party/blink/public/platform/scheduler/DEPS1
-rw-r--r--chromium/third_party/blink/public/platform/scheduler/web_thread_scheduler.h13
-rw-r--r--chromium/third_party/blink/public/platform/task_type.h7
-rw-r--r--chromium/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h18
-rw-r--r--chromium/third_party/blink/public/platform/web_audio_device.h2
-rw-r--r--chromium/third_party/blink/public/platform/web_audio_source_provider.h2
-rw-r--r--chromium/third_party/blink/public/platform/web_blob_info.h1
-rw-r--r--chromium/third_party/blink/public/platform/web_client_hints_type.h31
-rw-r--r--chromium/third_party/blink/public/platform/web_code_cache_loader.h11
-rw-r--r--chromium/third_party/blink/public/platform/web_content_decryption_module_session.h13
-rw-r--r--chromium/third_party/blink/public/platform/web_content_security_policy_struct.h2
-rw-r--r--chromium/third_party/blink/public/platform/web_content_settings_client.h4
-rw-r--r--chromium/third_party/blink/public/platform/web_font.h2
-rw-r--r--chromium/third_party/blink/public/platform/web_http_load_info.h87
-rw-r--r--chromium/third_party/blink/public/platform/web_impression.h1
-rw-r--r--chromium/third_party/blink/public/platform/web_loader_freeze_mode.h29
-rw-r--r--chromium/third_party/blink/public/platform/web_media_player.h1
-rw-r--r--chromium/third_party/blink/public/platform/web_media_player_client.h6
-rw-r--r--chromium/third_party/blink/public/platform/web_navigation_body_loader.h31
-rw-r--r--chromium/third_party/blink/public/platform/web_resource_request_sender.h12
-rw-r--r--chromium/third_party/blink/public/platform/web_runtime_features.h21
-rw-r--r--chromium/third_party/blink/public/platform/web_scoped_page_pauser.h5
-rw-r--r--chromium/third_party/blink/public/platform/web_theme_engine.h1
-rw-r--r--chromium/third_party/blink/public/platform/web_url_loader.h18
-rw-r--r--chromium/third_party/blink/public/platform/web_url_request.h5
-rw-r--r--chromium/third_party/blink/public/platform/web_url_request_extra_data.h1
-rw-r--r--chromium/third_party/blink/public/platform/web_url_response.h11
-rw-r--r--chromium/third_party/blink/public/platform/web_vector.h3
-rw-r--r--chromium/third_party/blink/public/platform/web_video_frame_submitter.h4
-rw-r--r--chromium/third_party/blink/public/platform/web_worker_fetch_context.h8
-rw-r--r--chromium/third_party/blink/public/platform/webaudiosourceprovider_impl.h9
-rw-r--r--chromium/third_party/blink/public/public_features.gni9
-rw-r--r--chromium/third_party/blink/public/strings/blink_strings.grd3
-rw-r--r--chromium/third_party/blink/public/strings/blink_strings_grd/IDS_AX_DIALOG_MODAL_OPENED.png.sha11
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_af.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_as.xtb2
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_az.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_be.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_bs.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_eu.xtb7
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_gl.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb3
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hy.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_is.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ka.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_kk.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_km.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ky.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_lo.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_mk.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_mn.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb3
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_my.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ne.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_or.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pa.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_si.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sq.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sr-Latn.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb3
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb19
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ur.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_uz.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_zh-HK.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb1
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_zu.xtb1
-rw-r--r--chromium/third_party/blink/public/web/DEPS8
-rw-r--r--chromium/third_party/blink/public/web/OWNERS2
-rw-r--r--chromium/third_party/blink/public/web/modules/autofill/OWNERS1
-rw-r--r--chromium/third_party/blink/public/web/modules/media/audio/fuchsia_audio_device_factory.h12
-rw-r--r--chromium/third_party/blink/public/web/modules/media/audio/web_audio_device_factory.h6
-rw-r--r--chromium/third_party/blink/public/web/modules/media/audio/web_audio_input_ipc_factory.h4
-rw-r--r--chromium/third_party/blink/public/web/modules/media/audio/web_audio_output_ipc_factory.h4
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h6
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h11
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h10
-rw-r--r--chromium/third_party/blink/public/web/web_ax_context.h9
-rw-r--r--chromium/third_party/blink/public/web/web_ax_object.h7
-rw-r--r--chromium/third_party/blink/public/web/web_custom_element.h5
-rw-r--r--chromium/third_party/blink/public/web/web_document.h24
-rw-r--r--chromium/third_party/blink/public/web/web_document_loader.h15
-rw-r--r--chromium/third_party/blink/public/web/web_element.h3
-rw-r--r--chromium/third_party/blink/public/web/web_frame.h6
-rw-r--r--chromium/third_party/blink/public/web/web_image.h4
-rw-r--r--chromium/third_party/blink/public/web/web_local_frame.h27
-rw-r--r--chromium/third_party/blink/public/web/web_local_frame_client.h34
-rw-r--r--chromium/third_party/blink/public/web/web_manifest_manager.h3
-rw-r--r--chromium/third_party/blink/public/web/web_navigation_params.h22
-rw-r--r--chromium/third_party/blink/public/web/web_optimization_guide_hints.h25
-rw-r--r--chromium/third_party/blink/public/web/web_performance.h2
-rw-r--r--chromium/third_party/blink/public/web/web_plugin.h7
-rw-r--r--chromium/third_party/blink/public/web/web_print_preset_options.h31
-rw-r--r--chromium/third_party/blink/public/web/web_remote_frame.h20
-rw-r--r--chromium/third_party/blink/public/web/web_remote_frame_client.h1
-rw-r--r--chromium/third_party/blink/public/web/web_savable_resources_test_support.h1
-rw-r--r--chromium/third_party/blink/public/web/web_security_policy.h12
-rw-r--r--chromium/third_party/blink/public/web/web_settings.h2
-rw-r--r--chromium/third_party/blink/public/web/web_view.h23
-rw-r--r--chromium/third_party/blink/public/web/web_view_client.h8
-rw-r--r--chromium/third_party/blink/public/web/web_widget.h17
-rw-r--r--chromium/third_party/blink/renderer/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/README.md17
-rw-r--r--chromium/third_party/blink/renderer/bindings/BUILD.gn181
-rw-r--r--chromium/third_party/blink/renderer/bindings/IDLCompiler.md28
-rw-r--r--chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md32
-rw-r--r--chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt2
-rw-r--r--chromium/third_party/blink/renderer/bindings/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/bindings/PRESUBMIT.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/bindings.gni47
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/BUILD.gn49
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn200
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc23
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_html_all_collection_custom.cc7
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc17
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_xml_http_request_custom.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.cc26
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/dictionary_helper_for_core.cc10
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/generated.gni231
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc87
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h55
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/idl_types.h136
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/idl_types_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc29
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc56
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/module_record.cc14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/module_record.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/module_record_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc736
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.cc308
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h499
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.cc47
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc64
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.h40
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info_test.cc93
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc12
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_regexp.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.cc10
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc16
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc50
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/source_location.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h50
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc93
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc45
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h18
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.cc516
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h65
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc922
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h444
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc50
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc27
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h13
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc35
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc228
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.h17
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc113
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc208
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h53
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc86
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc27
-rw-r--r--chromium/third_party/blink/renderer/bindings/extensions/v8/BUILD.gn22
-rw-r--r--chromium/third_party/blink/renderer/bindings/generated_in_core.gni50
-rw-r--r--chromium/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni10
-rw-r--r--chromium/third_party/blink/renderer/bindings/generated_in_modules.gni156
-rw-r--r--chromium/third_party/blink/renderer/bindings/idl_in_core.gni8
-rw-r--r--chromium/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni13
-rw-r--r--chromium/third_party/blink/renderer/bindings/idl_in_modules.gni49
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/BUILD.gn173
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn246
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/custom/custom.gni6
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni206
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.cc16
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc55
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc39
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/v8.gni42
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc15
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.h29
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn43
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py136
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/README.md166
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py7
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py233
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/callback_function.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py8
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py15
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py11
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py1674
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py91
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py488
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/package_initializer.py8
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py54
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py16
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/task_queue.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/typedef.py8
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py160
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/code_generator.py265
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py453
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py2
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py109
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py410
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py338
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py112
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py220
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py115
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py291
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py277
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py205
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py1251
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py19
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py144
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_types.py682
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py276
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py119
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py386
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py193
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py339
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/scripts.gni430
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py812
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py125
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py190
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py379
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py30
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py1850
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py641
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_types.py1348
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_union.py198
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py716
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/validate_web_idl.py3
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py1
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py12
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py11
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py75
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py21
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py191
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl725
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl90
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl74
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl137
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl84
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl277
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/constants.cc.tmpl71
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/copyright_block.txt10
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl41
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl78
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cc.tmpl21
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl203
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.h.tmpl46
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl119
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl1256
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl319
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl1058
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl654
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.cc.tmpl118
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.h.tmpl17
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.cc.tmpl112
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.h.tmpl15
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl23
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl121
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/templates.gni32
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/union_container.cc.tmpl238
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/union_container.h.tmpl89
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl59
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/PRESUBMIT.py5
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py4
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl1
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl1
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl4
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/templates/css_value_keywords.h.tmpl3
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py3
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_base.h.tmpl4
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/make_permissions_policy_features_tests.py27
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/element_factory.cc.tmpl10
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/make_names.cc.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/permissions_policy_features.cc.tmpl31
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl1
-rw-r--r--chromium/third_party/blink/renderer/build/win/precompile.h2
-rw-r--r--chromium/third_party/blink/renderer/config.gni37
-rw-r--r--chromium/third_party/blink/renderer/controller/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_initializer.cc15
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_leak_detector.cc16
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_leak_detector.h1
-rw-r--r--chromium/third_party/blink/renderer/controller/memory_usage_monitor_posix.cc2
-rw-r--r--chromium/third_party/blink/renderer/controller/oom_intervention_impl_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.cc45
-rw-r--r--chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/BUILD.gn77
-rw-r--r--chromium/third_party/blink/renderer/core/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/core/OWNERS9
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_context.h5
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h5
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animatable.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animatable.h8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.cc371
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.h48
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_clock.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect.cc142
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect.h14
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect_test.cc50
-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_test.cc677
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test_helpers.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test_helpers.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_time_delta.h3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_timeline.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_timeline.h26
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations.cc186
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations.h11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation.h10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation_update.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h90
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.cc406
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.h30
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.h7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_font_size_interpolation_type.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_font_stretch_interpolation_type.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_animations.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_animations.h63
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_animations_test.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_input.cc70
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_model.h1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.h28
-rw-r--r--chromium/third_party/blink/renderer/core/animation/inert_effect.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_aspect_ratio.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_value.h27
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolated_svg_path_source.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolation.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolation_type.h7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe.h9
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.h10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/animation/length_property_functions.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/pending_animations.h1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/primitive_interpolation.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/property_handle.h12
-rw-r--r--chromium/third_party/blink/renderer/core/animation/sampled_effect.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/sampled_effect.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.h38
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/string_keyframe.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/animation/string_keyframe.h3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/test_data/scale-animation.html3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/test_data/transform-animation-update.html1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/test_data/transform-animation.html3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing.h30
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_calculations.h34
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_input.cc91
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_input.h14
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_input_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/underlying_value_owner.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h5
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.h8
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history.cc560
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history.h71
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_destination.h59
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_destination.idl16
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.h15
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_navigation_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_reload_options.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/app_history_update_current_options.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/build.gni1
-rw-r--r--chromium/third_party/blink/renderer/core/app_history/window_app_history.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/README.md126
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/build.gni2
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h3
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object_item.h16
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer_item.h1
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer_test.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h1
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h50
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc165
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h18
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_task.h1
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc110
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/task_session.h5
-rw-r--r--chromium/third_party/blink/renderer/core/core_idl_files.gni880
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.h28
-rw-r--r--chromium/third_party/blink/renderer/core/css/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/background_color_paint_image_generator.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/basic_shape_functions.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/build.gni10
-rw-r--r--chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.h37
-rw-r--r--chromium/third_party/blink/renderer/core/css/container_query.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/container_query.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/container_query_evaluator.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/css/container_query_evaluator.h46
-rw-r--r--chromium/third_party/blink/renderer/core/css/container_query_evaluator_test.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/css/container_query_test.cc153
-rw-r--r--chromium/third_party/blink/renderer/core/css/counter_style.cc423
-rw-r--r--chromium/third_party/blink/renderer/core/css/counter_style.h36
-rw-r--r--chromium/third_party/blink/renderer/core/css/counter_style_map.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/css/counter_style_map.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/counter_style_map_test.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/css/counter_style_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/css/css.dict2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_container_rule.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_container_rule.h16
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_counter_style_rule.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_counter_value.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc292
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_crossfade_value.h65
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_custom_font_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_custom_ident_value.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h17
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_source.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_gradient_value.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_gradient_value.h14
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.h12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_identifier_value.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_generator_value.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_generator_value.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_value.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_value.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_layout_function_value.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node_test.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_numeric_literal_value.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_value.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_value.h10
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_value_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.h67
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value.h18
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h34
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value_units.json524
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_properties.json5232
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_source_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_value_set.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_value_set.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector.h15
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector_watch_test.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_string_value.h2
-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_sheet.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_component.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_test_helpers.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc168
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.h46
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_unicode_range_value.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h262
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_keywords.json575
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_list.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_color_value.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_color_value.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_hsl.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_hsl.h19
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.h10
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_max.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_min.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.h10
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_product.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_product.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.h7
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.h23
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value_type.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h17
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_rgb.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_rgb.h19
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_rotate.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_rotate.h17
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_scale.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_scale.h19
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_style_image_value_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_style_value.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.h30
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h39
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h18
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map.h12
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/element_rule_collector.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.h14
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_descriptors.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/css/has_argument_match_context.cc205
-rw-r--r--chromium/third_party/blink/renderer/core/css/has_argument_match_context.h215
-rw-r--r--chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.h119
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/mathml.css34
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_names.json52
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_overrides.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc609
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_exp.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_matcher.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_cached.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_cached.h75
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_dynamic.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/at_rule_counter_style_descriptor_parser.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser_test.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/at_rule_names.json53
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css.proto8
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_idioms.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc336
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.h23
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h7
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_property.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_property.h17
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc212
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc117
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registry.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/remote_font_face_source.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.h18
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_data_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_resolve_context.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc213
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h22
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/font_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/match_result.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/match_result_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc92
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc91
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc304
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h14
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h7
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc287
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_feature_set.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_feature_set.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_set.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_checker.cc197
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_checker.h56
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_filter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_query.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_query_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_auto_color.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_color.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.cc127
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.h34
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine_test.cc565
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.h15
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_shorthand_custom.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_recalc.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_recalc.h83
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_recalc_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_request.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule.h62
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule_import.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule_import.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_collection.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_contents.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_traversal_root.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_traversal_root.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/threaded/css_to_length_conversion_data_threaded_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h11
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h13
-rw-r--r--chromium/third_party/blink/renderer/core/document_transition/document_transition.cc115
-rw-r--r--chromium/third_party/blink/renderer/core/document_transition/document_transition.h30
-rw-r--r--chromium/third_party/blink/renderer/core/document_transition/document_transition_origin_trial_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/document_transition/document_transition_prepare_options.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/document_transition/document_transition_supplement.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abort_signal.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abort_signal.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abort_signal.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abstract_range.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abstract_range.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/build.gni1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/child_node.h12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc415
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.h122
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.idl20
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_parser.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_token_list.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element-hot.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.cc308
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.h71
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.idl36
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_rare_data.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_rare_data.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_path.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.h43
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h22
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/named_node_map.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.cc217
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.h30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.idl26
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_list.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_rare_data.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_rare_data.h100
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_traversal.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_traversal.h26
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_traversal_test.cc412
-rw-r--r--chromium/third_party/blink/renderer/core/dom/nth_index_cache.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/dom/parent_node.h12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/parent_node.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/processing_instruction.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pseudo_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range_boundary_point.h13
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/space_split_string.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/space_split_string.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/static_range.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/dom/static_range.h33
-rw-r--r--chromium/third_party/blink/renderer/core/dom/text.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_scope.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/weak_identifier_map.h10
-rw-r--r--chromium/third_party/blink/renderer/core/editing/build.gni4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/caret_display_item_client.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/editing/caret_display_item_client.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc157
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/editing_state.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/set_character_data_command_test.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/smart_replace.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/undo_stack.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/undo_stack.h26
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/undo_step.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/drag_caret.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_behavior.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_utilities.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/editing/element_inner_text.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ephemeral_range.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_caret.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.h8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/edit_context.h8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/text_update_event.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc115
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/kill_ring.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc158
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker.h8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/grammar_marker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.h44
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h48
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/spelling_marker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_replacement_scope.h7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/position.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/position.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/position_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/editing/range_in_flat_tree.h3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_editor.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_template.h12
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/html_interchange.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/set_selection_options.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/set_selection_options.h7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/backspace_state_machine.h7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.h8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.h8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine.h9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_test_util.h11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/substring_util.h11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/substring_util.mm11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/surrounding_text.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/surrounding_text.h12
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_offset_mapping.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_segments.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_segments.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_position_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_paragraph.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/events/event_type_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/events/input_event.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/events/message_event.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory.h8
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_type_names.json513
-rw-r--r--chromium/third_party/blink/renderer/core/events/promise_rejection_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/events/promise_rejection_event_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/events/simulated_event_util.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h8
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.h20
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context.h1
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context_init.h1
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/window_agent_factory.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/DEPS21
-rw-r--r--chromium/third_party/blink/renderer/core/exported/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/test_web_frame_content_dumper.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_content_holder.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.h3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_test.cc59
-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_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test_helper.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_history_item.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_image.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc2439
-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.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h18
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_performance.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_security_policy.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_select_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.h36
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_observer.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_test.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.h3
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/bytes_uploader.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/bytes_uploader_test.cc92
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_header_list_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc153
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h6
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h14
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/global_fetch.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/global_fetch.h17
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/headers.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/headers.h8
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/multipart_parser.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/multipart_parser.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.h13
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.h3
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.h15
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file.h9
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/frame/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/frame/attribution_reporting.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/frame/attribution_reporting.h46
-rw-r--r--chromium/third_party/blink/renderer/core/frame/attribution_reporting.idl14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/attribution_source_params.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/build.gni6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h42
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/conversion_util.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/conversion_util_fuzzer.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/conversion_util_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dactyloscoper.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.h30
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_timer_coordinator.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.h21
-rw-r--r--chromium/third_party/blink/renderer/core/frame/embedded_content_view.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/frame/find_in_page.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.h32
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_console.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_content_as_text.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_content_as_text.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_lifecycle.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_owner.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_view.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_view.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history_util.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.h34
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.cc1378
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.h359
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_client.h22
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.h8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc1264
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h297
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc382
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h62
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.cc316
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.h29
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_id.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_id.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_language.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/opened_frame_tracker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/page_dismissal_scope.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/policy_container.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_dom_window.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_dom_window.h8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.h30
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_view.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/resize_viewport_anchor.h7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/savable_resources.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.cc122
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.h37
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.h16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.json516
-rw-r--r--chromium/third_party/blink/renderer/core/frame/sticky_ad_detector.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ua_data_values.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter_impl.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter_impl.h17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter_impl_test.cc174
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.h13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_test.cc417
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc114
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h35
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_test.cc115
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window.idl24
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_attribution_reporting.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_post_message_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h4
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h5
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix.h10
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.h9
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/build.gni1
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight.h25
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight_registry.cc130
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight_registry.h74
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight_registry.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/highlight/highlight_registry_map_entry.h61
-rw-r--r--chromium/third_party/blink/renderer/core/html/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/build.gni8
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.h23
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc184
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h23
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h89
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h13
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h42
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc163
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h23
-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.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data.h54
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data.idl9
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data_settings.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc98
-rw-r--r--chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/ce_reactions_scope.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h18
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc98
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h34
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h27
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.h26
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h31
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h24
-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_resource_loader.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_chooser.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.h70
-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_local_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_controller.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data.h12
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data_event.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.cc40
-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_field_set_element_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc133
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.h20
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element_test.cc261
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_label_element.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_legend_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_legend_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_options_collection.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc335
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.h36
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.idl2
-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.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/input_type.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/input_type_view.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/listed_element.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/menu_list_inner_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/month_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/month_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/password_input_type_test.cc89
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/radio_button_group_scope.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.css553
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js682
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css531
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.css71
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.js32
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/datetimelocal_picker.js2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js26
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/pickerButton.css71
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js19
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.css54
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.js6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/select_type.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/time_input_type.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/time_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/type_ahead.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/type_ahead.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/validity_state.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/week_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/week_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_all_collection.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_all_collection.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_attribute_names.json52
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_collection.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_details_element.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_dialog_element.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_dialog_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_document.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.cc174
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.h25
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.idl18
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_html_element.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_html_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_marquee_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_or_foreign_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_popup_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_script_element.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_script_element.h16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_view_source_document.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_view_source_document_test.cc138
-rw-r--r--chromium/third_party/blink/renderer/core/html/link_resource.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/link_web_bundle.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/autoplay_policy.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_test_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element_test.cc51
-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_fragment_uri_parser.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_source_attachment.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_frame_callback_requester.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/atomic_html_token.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/background_html_input_stream.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h12
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h12
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc128
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_input_stream.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h28
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h13
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_token.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/literal_buffer.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css263
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/html.css419
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css26
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/win.css119
-rw-r--r--chromium/third_party/blink/renderer/core/html/subresource_redirect_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/track_event.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/track_event.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc89
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h11
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_tokenizer.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc86
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h11
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handling_util.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/input/gesture_manager.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/input/gesture_manager.h25
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager.h11
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_action_util.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager.h1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/console_message_storage.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/console_message_storage.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_session.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_session.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_editor.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_editor.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_patch_support.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspect_tools.h38
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspected_frames.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.h11
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_contrast.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_contrast.h10
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h21
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc195
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h16
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h15
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc236
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h26
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight_test.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_history.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_io_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h9
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h4
-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_media_agent.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h17
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h11
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h18
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h7
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_container.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.h15
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/locale_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/network_resources_data.h9
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/protocol_parser_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/protocol_unittest.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/resolve_node.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/thread_debugger.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_thread_debugger.h5
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h1
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h4
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.h31
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h13
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h2
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc110
-rw-r--r--chromium/third_party/blink/renderer/core/layout/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/api/line_layout_box.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/api/line_layout_item.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h59
-rw-r--r--chromium/third_party/blink/renderer/core/layout/build.gni18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/column_balancer.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/logical_offset.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/logical_rect.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/logical_rect_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/logical_size.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/physical_offset.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/physical_rect_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/physical_size.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/transform_state.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/geometry/transform_state.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid.h103
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc102
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_request.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_result.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_result.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_testing_transform_state.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.cc169
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_counter.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_counter.h2
-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_embedded_content.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_fieldset.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_frame_set.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid.cc208
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid.h33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_item.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_marker_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_media.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_set.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.cc341
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.h132
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory_test.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_test.cc113
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_quote.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_replaced.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc350
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_box_component.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_cell_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_combine.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_fragment.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_fragment.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_test.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.h16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_android.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_android.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.h13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_win.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_video.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_video.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view_test.cc290
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_box.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_text_box_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/root_inline_box.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/list_marker.cc201
-rw-r--r--chromium/third_party/blink/renderer/core/layout/list_marker.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/list_marker_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/list_marker_text.cc971
-rw-r--r--chromium/third_party/blink/renderer/core/layout/list_marker_text.h50
-rw-r--r--chromium/third_party/blink/renderer/core/layout/map_coordinates_test.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/pending_layout_registry.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc405
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm_test.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid_interface.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h54
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator_test.cc119
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc1546
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h190
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc610
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h139
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.cc232
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.h61
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_counter.h43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc277
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h132
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc1414
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc233
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h99
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc325
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h66
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc413
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc357
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc157
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc608
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h47
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc165
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block.h20
-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_block_flow_mixin.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h44
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h36
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc136
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc160
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc192
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h59
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_break_token.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc173
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h191
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h87
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc107
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h35
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc209
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h143
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator_test.cc806
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc181
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h25
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc252
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h121
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc626
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h48
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc556
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h52
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc269
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment_test.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc192
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h72
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment_test.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc436
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.h23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.cc84
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.h26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.cc342
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.h38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/resolved_text_layout_attributes_iterator.h65
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/overflow_model.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc594
-rw-r--r--chromium/third_party/blink/renderer/core/layout/shapes/shape.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_baseline.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_spacing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_autosizer.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_autosizer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_run_constructor.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h13
-rw-r--r--chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/build.gni2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/cookie_jar.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/loader/cookie_jar.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/cookie_jar_unittest.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_load_timing.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_load_timing.h4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.cc308
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.h39
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader_test.cc173
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.h30
-rw-r--r--chromium/third_party/blink/renderer/core/loader/form_submission.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc118
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.h25
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader_types.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/history_item.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/idleness_detector.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/image_loader.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector.h17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector_test.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/loader/loader_factory_for_worker.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/long_task_detector.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h51
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h31
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc381
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_policy.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/loader/no_state_prefetch_client.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/ping_loader.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/loader/ping_loader.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/ping_loader_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/preload_helper.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prerender_handle.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prerender_handle.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prerender_test.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/loader/progress_tracker.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/progress_tracker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc323
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc113
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader_client.h12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h13
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_padded_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json54
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.h8
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.h13
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc197
-rw-r--r--chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h8
-rw-r--r--chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc400
-rw-r--r--chromium/third_party/blink/renderer/core/mobile_metrics/mobile_metrics_test_helpers.h40
-rw-r--r--chromium/third_party/blink/renderer/core/mojo/mojo_handle.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/mojo/mojo_handle.h16
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h16
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.h1
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.h26
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/page/create_window.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_image.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_image.h6
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_image_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_state.h6
-rw-r--r--chromium/third_party/blink/renderer/core/page/focus_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/page/focus_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/page/frame_tree.h5
-rw-r--r--chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.h19
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_animator.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/page/plugin_data.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/page/plugin_data.h10
-rw-r--r--chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h7
-rw-r--r--chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context.h4
-rw-r--r--chromium/third_party/blink/renderer/core/page/scoped_page_pauser.h4
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h4
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc184
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h7
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h12
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h9
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h5
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h8
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc141
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.cc136
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h85
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler_test.cc506
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc443
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h109
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc592
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_adjustment.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_adjustment_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/viewport_description.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/page/viewport_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_border_painter.cc904
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_border_painter.h139
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_decoration_data.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.cc471
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/build.gni6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_path_clipper.cc143
-rw-r--r--chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc320
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/cull_rect_updater.cc147
-rw-r--r--chromium/third_party/blink/renderer/core/paint/cull_rect_updater.h23
-rw-r--r--chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/embedded_object_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/find_paint_offset_needing_update.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/find_properties_needing_update.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fragment_data.h37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.h37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_painter.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/paint/multi_column_set_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc370
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_mathml_painter.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc127
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.h46
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc175
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc353
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.h34
-rw-r--r--chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_properties.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter_base.cc666
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter_base.h63
-rw-r--r--chromium/third_party/blink/renderer/core/paint/outline_painter.cc724
-rw-r--r--chromium/third_party/blink/renderer/core/paint/outline_painter.h33
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h30
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_info.h73
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidator.h10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.cc304
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.h35
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_fragment.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc207
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc446
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc378
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h63
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.h10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc900
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h183
-rw-r--r--chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc206
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_container_painter_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_mask_painter.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_object_painter.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_object_painter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_section_painter.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_decoration_info.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_decoration_info.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_style.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter.h8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter_base.cc251
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter_base.h55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc137
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_default.h2
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/document_policy_fuzzer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser.h1
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/feature_policy_fuzzer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h5
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_attr_fuzzer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json535
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_fuzzer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/probe/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/probe/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.json54
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.pidl2
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/script/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/script/build.gni2
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_script.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/script/detect_javascript_frameworks.cc186
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h1
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map.h11
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map_error.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map_error.h43
-rw-r--r--chromium/third_party/blink/renderer/core/script/js_module_script.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/script/mock_script_element_base.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.h24
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.h13
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map.h1
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script_test.cc195
-rw-r--r--chromium/third_party/blink/renderer/core/script/parsed_specifier.h1
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_import_map.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_import_map.h14
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_element_base.h7
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.h4
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.h34
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_alignment.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_alignment.h2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area.h23
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar.h7
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm8
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mobile.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h6
-rw-r--r--chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/speculation_rules/speculation_rules_origin_trial_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.h27
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_generic_reader.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.h10
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_transformer.h7
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.h1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/style/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/style/basic_shapes.h11
-rw-r--r--chromium/third_party/blink/renderer/core/style/build.gni6
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.cc276
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.h144
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_constants.h95
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json517
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json599
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_test.cc202
-rw-r--r--chromium/third_party/blink/renderer/core/style/content_data.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/style/content_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/fill_layer.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/style/fill_layer.h11
-rw-r--r--chromium/third_party/blink/renderer/core/style/filter_operation.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/style/filter_operation.h44
-rw-r--r--chromium/third_party/blink/renderer/core/style/grid_area.h31
-rw-r--r--chromium/third_party/blink/renderer/core/style/grid_positions_resolver.cc114
-rw-r--r--chromium/third_party/blink/renderer/core/style/grid_positions_resolver.h39
-rw-r--r--chromium/third_party/blink/renderer/core/style/grid_track_list.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/style/grid_track_list.h22
-rw-r--r--chromium/third_party/blink/renderer/core/style/list_style_type_data.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/style/list_style_type_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/named_grid_lines_map.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/quotes_data.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/style/shadow_data.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_base_data.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_base_data.h54
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_cached_data.h5
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_crossfade_image.cc157
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_crossfade_image.h70
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image.h5
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image_set.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image_set.h5
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_generated_image.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_generated_image.h12
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_image.h11
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_pending_image.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_pending_image.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_svg_resource.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_svg_resource.h19
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_variables.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_variables.h1
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_variables_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/priority_queue.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h28
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h20
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_angle.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_href.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_href.h7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_length.h10
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_string.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_string.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_document_extensions.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_enumeration_map.h3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_length_context.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_blender.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_blender.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_consumer.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_string_source.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_resource.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_script_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_script_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_text_content_element.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_transform.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_use_element.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_use_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/iframe-background-attachment-fixed-inner.html2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/trivial-scroller.html17
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.cc341
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.h83
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.h18
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_page_holder.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h12
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.h7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.h27
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.idl9
-rw-r--r--chromium/third_party/blink/renderer/core/testing/intersection_observer_test_helper.h12
-rw-r--r--chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h19
-rw-r--r--chromium/third_party/blink/renderer/core/testing/mock_hyphenation.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/module_test_base.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/testing/module_test_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.h3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/origin_trials_test_global.h25
-rw-r--r--chromium/third_party/blink/renderer/core/testing/origin_trials_test_window.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/page_test_base.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/testing/record_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/record_test.h11
-rw-r--r--chromium/third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sequence_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sequence_test.h5
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_request.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_request.h10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/static_selection.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/union_types_test.cc137
-rw-r--r--chromium/third_party/blink/renderer/core/testing/union_types_test.h24
-rw-r--r--chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc138
-rw-r--r--chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.h1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/background_tracing_helper.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/timing/build.gni4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/dom_window_performance.h4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_counts.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_timing.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_timing.h17
-rw-r--r--chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/timing/memory_info.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.cc121
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.h31
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_mark.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h20
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_timing.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_timing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_user_timing.h1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler.h6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler_group.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler_group.h5
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler_init_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.cc204
-rw-r--r--chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.h84
-rw-r--r--chromium/third_party/blink/renderer/core/timing/time_clamper.h6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.h93
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance_test.cc507
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h22
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/BUILD.gn34
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/array_buffer.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h1
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/array_buffer_view.idl14
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/big_int_64_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/big_uint_64_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/build.gni24
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/data_view.idl31
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h1
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.h8
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.h1
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.cc89
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h149
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h9
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/float32_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/float64_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/int16_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/int32_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/int8_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/shared_array_buffer.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h1
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/uint16_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/uint32_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/uint8_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/uint8_clamped_array.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url.h22
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils.h3
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.h3
-rw-r--r--chromium/third_party/blink/renderer/core/url/url.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/url/url_search_params.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/url/url_search_params.h10
-rw-r--r--chromium/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/cross_thread_global_scope_creation_params_copier.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h8
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.h8
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h7
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_clients.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.h12
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_navigator.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h13
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.h8
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread_test_helper.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h1
-rw-r--r--chromium/third_party/blink/renderer/core/xml/document_xslt.h6
-rw-r--r--chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser_scope.h4
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_expression_node.h4
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_functions.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_parser.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_parser.h5
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_predicate.h4
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_step.h4
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_util.h2
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xslt_processor.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h18
-rw-r--r--chromium/third_party/blink/renderer/extensions/DIR_METADATA5
-rw-r--r--chromium/third_party/blink/renderer/extensions/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/extensions/README.md11
-rw-r--r--chromium/third_party/blink/renderer/extensions/chromeos/BUILD.gn49
-rw-r--r--chromium/third_party/blink/renderer/extensions/chromeos/chromeos.cc13
-rw-r--r--chromium/third_party/blink/renderer/extensions/chromeos/chromeos.h25
-rw-r--r--chromium/third_party/blink/renderer/extensions/chromeos/chromeos.idl7
-rw-r--r--chromium/third_party/blink/renderer/extensions/chromeos/extensions_chromeos_export.h68
-rw-r--r--chromium/third_party/blink/renderer/extensions/extensions.gni57
-rw-r--r--chromium/third_party/blink/renderer/modules/BUILD.gn193
-rw-r--r--chromium/third_party/blink/renderer/modules/DEPS8
-rw-r--r--chromium/third_party/blink/renderer/modules/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc206
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h4
-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_node_object.cc656
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc576
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object.h170
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc790
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h108
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc333
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc102
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc147
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc102
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/DEPS11
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/idls.gni11
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc105
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc104
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h34
-rw-r--r--chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc392
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc53
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc100
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h23
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/app_banner/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/audio_output_devices/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc90
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc131
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc46
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/idls.gni22
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/idls.gni21
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/idls.gni8
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/battery_manager.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/beacon/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc88
-rw-r--r--chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h19
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc60
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc74
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_service_data_map.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/idls.gni30
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/testing/clusterfuzz/PRESUBMIT.py4
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/BUILD.gn6
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/frame_queue.h30
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_test.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc271
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h42
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.cc95
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h15
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator_test.cc77
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.cc67
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor_test.cc122
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_signal.idl15
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc75
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc330
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.cc92
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h83
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc65
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h15
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.cc109
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h44
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink_test.cc244
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.cc164
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h80
-rw-r--r--chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source_test.cc191
-rw-r--r--chromium/third_party/blink/renderer/modules/broadcastchannel/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/buckets/idls.gni15
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache.cc221
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache.h38
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/idls.gni18
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc828
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h230
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_dictionary.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.cc341
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_formatted_text.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.cc66
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc195
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h54
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc222
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h51
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl19
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc170
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_settings.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc104
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h46
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc53
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.h116
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h50
-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/canvas_context_creation_attributes_module.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h15
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/idls.gni35
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_source_union.h17
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.h9
-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_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc168
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h31
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl20
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_item_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc85
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc77
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.h25
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/idls.gni8
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/compute_pressure/compute_pressure_observer.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/compute_pressure/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/contacts_picker/idls.gni15
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/idls.gni19
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/idls.gni25
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_payment_inputs.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc62
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc285
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/idls.gni49
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_key.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/idls.gni19
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc81
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.cc115
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.h101
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn17
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/README.md52
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h63
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc70
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h18
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/idls.gni13
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.pngbin0 -> 33544 bytes
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot7
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.pngbin0 -> 40230 bytes
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot9
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h62
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet_proxy_client.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.cc (renamed from chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc)253
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h100
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition_test.cc (renamed from chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet_test.cc)65
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.cc (renamed from chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.cc)27
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.h (renamed from chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.h)13
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.cc224
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.h63
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.cc45
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_definition.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc101
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h19
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc32
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/ink.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/ink.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/ink.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/delegated_ink/ink_presenter_param.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_rotation_rate.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/idls.gni22
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/README.md5
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/device_posture.cc96
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/device_posture.h60
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/device_posture.idl15
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.h33
-rw-r--r--chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/direct_sockets/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/document_metadata/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/donottrack/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/encoding.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/idls.gni16
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/text_decoder.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc35
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/idls.gni26
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc41
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_media_capability.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/event_target_modules_names.json51
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source_parser_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_ax_context.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_crypto_normalize.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_testing_support.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.h41
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/color_selection_result.idl (renamed from chromium/third_party/blink/renderer/modules/eyedropper/color_select_event_init.idl)4
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc101
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.h43
-rw-r--r--chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h75
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc202
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h63
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc208
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h105
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc71
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_read_write_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.cc325
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.h138
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.idl35
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc101
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc84
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/idls.gni31
-rw-r--r--chromium/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/idls.gni37
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/font_access/font_manager.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/font_access/idls.gni13
-rw-r--r--chromium/third_party/blink/renderer/modules/font_access/navigator_fonts.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/idls.gni22
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/idls.gni14
-rw-r--r--chromium/third_party/blink/renderer/modules/handwriting/handwriting_hints.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/handwriting/idls.gni23
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_device.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_device.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/idls.gni21
-rw-r--r--chromium/third_party/blink/renderer/modules/idle/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/idls.gni13
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc98
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/BUILD.gn21
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h23
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc123
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc193
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_value.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idls.gni30
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h15
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.h143
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h53
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h115
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h50
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.cc (renamed from chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc)75
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h117
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h105
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_unittest.cc (renamed from chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc)61
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.cc (renamed from chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc)166
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.h203
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h127
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.cc (renamed from chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.cc)50
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h95
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h69
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_unittest.cc (renamed from chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl_unittest.cc)28
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/idls.gni10
-rw-r--r--chromium/third_party/blink/renderer/modules/launch/idls.gni10
-rw-r--r--chromium/third_party/blink/renderer/modules/launch/launch_queue.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/launch/launch_queue.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/lock_screen/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/idls.gni19
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_manager.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/managed_device/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/managed_device/navigator_managed.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc184
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h30
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc2582
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc276
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h99
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters_unittest.cc114
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_mixer_manager_test.cc146
-rw-r--r--chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache_test.cc86
-rw-r--r--chromium/third_party/blink/renderer/modules/media/audio/web_audio_output_ipc_factory_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/media/webmediaplayer_util.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/media/webmediaplayer_util_unittest.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/idls.gni22
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc259
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc156
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc48
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc84
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc37
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc126
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc166
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc107
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/resources/mediaControls.css14
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc62
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/idls.gni10
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_opus_encoder.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_pcm_encoder.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/idls.gni13
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/idls.gni18
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_session.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/idls.gni21
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source.cc72
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc94
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/identifiability_metrics.cc321
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/idls.gni43
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/input_device_info.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/local_media_stream_audio_source.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm_unittest.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc346
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_constraints_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc70
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_error_state.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_error_state.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc221
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h19
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc66
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc73
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/mock_encoded_video_frame.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/remote_media_stream_track_adapter.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.cc48
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_request.cc87
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_request.h19
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc75
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/modalclosewatcher/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/modules.gni2
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_idl_files.gni294
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_initializer.cc35
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_initializer.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/native_io/idls.gni19
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/netinfo/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/netinfo/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/idls.gni18
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc60
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_message.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_reader.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_reader.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc202
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_record.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/idls.gni21
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/goods/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/idls.gni52
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.cc83
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn5
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/idls.gni75
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc107
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_configuration.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc99
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.h38
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.h38
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc262
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc187
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc55
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/testing/mock_rtp_sender.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/thermal_resource.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/thermal_uma_listener.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/idls.gni23
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permissions.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/idls.gni20
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc70
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.cc82
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/idls.gni21
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/idls.gni23
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_event.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc52
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc53
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/idls.gni23
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/BUILD.gn5
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/config3.txt9
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium1.html2
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium2.html2
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium3.html2
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/simple4.html4
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.h29
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc425
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h69
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api.dict1
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api_fuzzer.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.proto9
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc59
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc51
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/idls.gni17
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_callback.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_controller.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_controller_init.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_signal.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/window_or_worker_scheduler.idl (renamed from chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.idl)8
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc133
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.h43
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/idls.gni13
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/screen_enumeration.idl23
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/screens.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/screens.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.cc93
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/idls.gni23
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/idls.gni22
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/idls.gni32
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/idls.gni18
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc64
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/BUILD.gn18
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/idls.gni (renamed from chromium/third_party/blink/renderer/modules/breakout_box/idls.gni)11
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.cc217
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.h88
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.idl40
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_run_operation_method_options.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_set_method_options.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc59
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.h41
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.h25
-rw-r--r--chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/OWNERS6
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/idls.gni31
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/srcobject/idls.gni5
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/cached_storage_area.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/cached_storage_area.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/dom_window_storage.cc111
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/dom_window_storage.h20
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_area.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_controller.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/BUILD.gn (renamed from chromium/third_party/blink/renderer/modules/eyedropper/idls.gni)12
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/DIR_METADATA3
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/navigator_sub_apps.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/sub_apps.cc109
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/sub_apps.h38
-rw-r--r--chromium/third_party/blink/renderer/modules/subapps/sub_apps.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/BUILD.gn18
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/2dcf128c70be5016986fa5965a89eb839fd6cc3c1
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/345433f6443349a932caefebc1754a7da500a8851
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/43e53712d966badcd72516f9a9df30486173d8bc1
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/4eba2aa9b6632b032ad9affab48eed570c3a7bec1
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/60aff90a381901bfbb4fd3d1753a5a86878428211
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/97cccba9cd38cd5138376093447ea6382a4df2201
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/b0c2fea6b0fbc79ebcebf728cf1c76d4b35091211
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/d376eb4568f7c9ab01409838be90c31db1a9e7551
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/dc9e31b18d4686a0f8dec64b5602d5a426ab0f441
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/ecac354bd05b4e6328a498c43291ad2e129134fc1
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/idls.gni13
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.cc1064
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.h78
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.idl17
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.cc464
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h83
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.cc390
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.h113
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_fuzzer.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.cc453
-rw-r--r--chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.h192
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/video_rvfc/idls.gni10
-rw-r--r--chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/virtualkeyboard/idls.gni10
-rw-r--r--chromium/third_party/blink/renderer/modules/virtualkeyboard/navigator_virtual_keyboard.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/README.md11
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/idls.gni12
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc39
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc32
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/channel_merger_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/channel_splitter_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/constant_source_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/cpu/arm/oscillator_kernel_neon.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/gain_node.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/idls.gni75
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/BUILD.gn26
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h42
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data.cc390
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data.h29
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_options.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data_init.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc349
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder_config.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/audio_sample_format.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/codec_trace_names.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/color_space_matrix_id.idl18
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl19
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/color_space_range_id.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/color_space_transfer_id.idl23
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.cc150
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/decoder_template_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.cc90
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.cc75
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h25
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_init.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.cc78
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_init.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_metadata.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto15
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc107
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/idls.gni76
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decode_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc108
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external_test.cc75
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/image_track_list.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/latency_mode.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc170
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.h (renamed from chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h)24
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc235
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/plane.cc121
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/plane.h49
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/plane.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/plane_init.idl15
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/plane_layout.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc62
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h43
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_color_primaries.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.cc303
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.h53
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.idl22
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_color_space_init.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.cc366
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl25
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.cc338
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame.cc725
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame.h82
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame.idl41
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_buffer_init.idl25
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_options.idl (renamed from chromium/third_party/blink/renderer/modules/webcodecs/video_frame_read_into_options.idl)8
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.cc59
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.cc95
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h105
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor_test.cc90
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl26
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_region.idl15
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc182
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_matrix_coefficients.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl27
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/video_transfer_characteristics.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database_authorizer.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database_tracker.cc64
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/idls.gni17
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/angle_instanced_arrays.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_blend_min_max.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_float.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_half_float.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_float_blend.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_frag_depth.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_shader_texture_lod.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_texture_norm_16.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/gl_string_query.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/idls.gni91
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_element_index_uint.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_fbo_render_mipmap.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_standard_derivatives.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_texture_float.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_texture_float_linear.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float_linear.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ovr_multiview_2.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc24
-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.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_color_buffer_float.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_depth_texture.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_extension.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_extension.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h91
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl20
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc55
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.h65
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.idl18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_program.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc24
-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.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc207
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h35
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl46
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_texture.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc191
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_callback.h112
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc166
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc71
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc78
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.cc32
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_entry.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl (renamed from chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl)3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc220
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h41
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc170
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc156
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h31
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc142
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h38
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_binding_layout.idl (renamed from chromium/third_party/blink/renderer/modules/webgpu/gpu_limits.idl)7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_descriptor.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_texture_tagged.idl14
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc426
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.h47
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc55
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.cc104
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h90
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.idl36
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.cc126
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc191
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_layout.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/idls.gni109
-rw-r--r--chromium/third_party/blink/renderer/modules/webid/idls.gni9
-rw-r--r--chromium/third_party/blink/renderer/modules/webid/web_id.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/webid/web_id_request_options.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/idls.gni22
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webrtc/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webrtc/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/FILE_TYPES.md2
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/idls.gni7
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc32
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/idls.gni16
-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_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_common_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream_test.cc81
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.cc37
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream_test.cc253
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/idls.gni17
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/receive_stream.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/receive_stream.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/receive_stream.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/test_utils.cc58
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/test_utils.h58
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/web_transport.cc422
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/web_transport.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/web_transport.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webtransport/web_transport_test.cc323
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/idls.gni31
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_device.cc68
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_device.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/worklet/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/idls.gni79
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/type_converters.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_cpu_depth_information.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_cube_map.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.cc102
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_grip_space.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hand.cc119
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hand.h42
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_image_tracking_result.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source_array.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_joint_space.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_joint_space.h18
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_light_probe.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_ray.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_render_state.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session_viewport_scaler.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_space.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_system.cc85
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_system.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_utils.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_utils.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_view.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc58
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/BUILD.gn69
-rw-r--r--chromium/third_party/blink/renderer/platform/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/platform/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/PRESUBMIT.py69
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/animation_utilities.h49
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_delegate.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_filter_animation_curve.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_float_keyframe.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_scroll_offset_animation_curve.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_transform_animation_curve.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_transform_keyframe.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_array.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_bus.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_channel.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_channel.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination_consumer.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_resampler.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_resampler.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_source_provider.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/direct_convolver.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/down_sampler.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/down_sampler.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.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/dynamics_compressor_kernel.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_convolver.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_frame.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_frame.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_database.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_panner.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/panner.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_convolver.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/sinc_resampler.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/stereo_panner.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/up_sampler.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/up_sampler.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dictionary_base.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_context.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc62
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_messages.h64
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_state.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_state.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/name_client.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_forbidden_scope.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_state.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/string_resource.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/to_v8.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_object_constructor.cc3
-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.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_url_null_origin_map.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/color_data.gperf2
-rw-r--r--chromium/third_party/blink/renderer/platform/disk_data_allocator.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/mediastream/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/platform.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/weak_wrapper_resource_load_info_notifier.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_audio_bus.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_audio_device.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_http_body.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_http_load_info.cc121
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc78
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_screen_info_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_string.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_thread_safe_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_request.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_response.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_vector_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/wrapped_resource_request.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/wrapped_resource_response.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/character_range.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/custom_font_data.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_baseline.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_data.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_data_cache.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_face_creation_params.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_family.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_global_context.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_metrics.h69
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_metrics_override.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_performance.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_performance.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_selection_algorithm.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_selector.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/glyph_metrics_map.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm23
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm15
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h16
-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_math_stretch_data.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/variable_axes_names.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/orientation_iterator.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/font_features_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/small_caps_iterator.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/symbols_iterator.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_box.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_point_3d.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_polygon.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_quad.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_quad_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_rect.cc63
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_rect.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_rect_test.cc60
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_rect_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/length.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/length.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/length_functions.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc67
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc83
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc107
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h49
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc100
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_space_profile_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc1071
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h133
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc609
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc80
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc476
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h156
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc509
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_helper.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_cache.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_lab_color_space.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings_builder.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc12
-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.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc12
-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_blend.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_lighting.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc1
-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.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h6
-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/paint_filter_builder.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/generated_image.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/generated_image.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc70
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc86
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc149
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h46
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc180
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h6
-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.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc198
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.h86
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_types.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_types.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.cc140
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h114
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest_unittest.cc441
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.cc110
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.h111
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc64
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_backing.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc156
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc160
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h84
-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.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc648
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc208
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h69
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc98
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc91
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc56
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc69
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc400
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h198
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc1779
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.cc254
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.h76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker_test.cc351
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc177
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc359
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_effectively_invisible.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h16
-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.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/parkable_image.cc205
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/parkable_image.h142
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.cc78
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/parkable_image_test.cc103
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/path.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/path_traversal_state.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/pattern.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/raster_dark_mode_filter_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/rw_buffer.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/rw_buffer.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/rw_buffer_test.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.cc3
-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.cc90
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/stroke_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc56
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.cc270
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h140
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc253
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc178
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc118
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/viz_util.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/viz_util.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc131
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BUILD.gn8
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md9
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S65
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/handle.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/garbage_collected.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/gc_info.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/heap.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/heap_compact.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/member.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/thread_state.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/trace_traits.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/impl/visitor.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.cc125
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_vector_backing.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_local.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state_scopes.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc152
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc48
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc89
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h78
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc43
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc56
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/canvas_memory_dump_provider.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/instance_counters_memory_dump_provider.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc170
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/use_counter.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/json/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_parser.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_parser_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_values.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/BUILD.gn20
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/code_cache_loader.cc118
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/code_cache_loader.h64
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc135
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc59
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_info.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc186
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc476
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc150
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc75
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc83
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h107
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc147
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h77
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc (renamed from chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc)66
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h (renamed from chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h)67
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc162
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h37
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.cc377
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h171
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc355
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc (renamed from chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc)197
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc89
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/frame_request_blocker.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/ftp_directory_listing.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/link_header_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h66
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm105
-rw-r--r--chromium/third_party/blink/renderer/platform/media/BUILD.gn176
-rw-r--r--chromium/third_party/blink/renderer/platform/media/DEPS56
-rw-r--r--chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc182
-rw-r--r--chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl_unittest.cc156
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cache_util.cc129
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cache_util.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cache_util_unittest.cc83
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cdm_result_promise.h120
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.h50
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.cc267
-rw-r--r--chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.h177
-rw-r--r--chromium/third_party/blink/renderer/platform/media/interval_map_unittest.cc275
-rw-r--r--chromium/third_party/blink/renderer/platform/media/key_system_config_selector.cc1112
-rw-r--r--chromium/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc1849
-rw-r--r--chromium/third_party/blink/renderer/platform/media/learning_experiment_helper.cc54
-rw-r--r--chromium/third_party/blink/renderer/platform/media/learning_experiment_helper_unittest.cc141
-rw-r--r--chromium/third_party/blink/renderer/platform/media/lru_unittest.cc235
-rw-r--r--chromium/third_party/blink/renderer/platform/media/multi_buffer.cc572
-rw-r--r--chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc780
-rw-r--r--chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc1880
-rw-r--r--chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.cc252
-rw-r--r--chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.h196
-rw-r--r--chromium/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc609
-rw-r--r--chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.cc108
-rw-r--r--chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.h84
-rw-r--r--chromium/third_party/blink/renderer/platform/media/power_status_helper.cc310
-rw-r--r--chromium/third_party/blink/renderer/platform/media/power_status_helper_unittest.cc440
-rw-r--r--chromium/third_party/blink/renderer/platform/media/remote_playback_client_wrapper_impl.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc576
-rw-r--r--chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h135
-rw-r--r--chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc384
-rw-r--r--chromium/third_party/blink/renderer/platform/media/smoothness_helper.cc240
-rw-r--r--chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc206
-rw-r--r--chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.cc107
-rw-r--r--chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.h82
-rw-r--r--chromium/third_party/blink/renderer/platform/media/text_track_impl.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/media/text_track_impl.h57
-rw-r--r--chromium/third_party/blink/renderer/platform/media/url_index.cc340
-rw-r--r--chromium/third_party/blink/renderer/platform/media/url_index_unittest.cc179
-rw-r--r--chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.cc332
-rw-r--r--chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.h245
-rw-r--r--chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter_unittest.cc935
-rw-r--r--chromium/third_party/blink/renderer/platform/media/video_frame_compositor.cc461
-rw-r--r--chromium/third_party/blink/renderer/platform/media/video_frame_compositor_unittest.cc494
-rw-r--r--chromium/third_party/blink/renderer/platform/media/watch_time_reporter_unittest.cc2398
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.cc173
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h82
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.cc474
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.h104
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc189
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.cc49
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_media_player_impl.cc3914
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_media_player_params.cc70
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_media_source_impl.cc107
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_media_source_impl.h50
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc260
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.h82
-rw-r--r--chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_level_calculator.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc263
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h60
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc351
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc93
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source_test.cc73
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_headers_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote_set_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_set_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/network/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/network/form_data_encoder.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_header_map.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_state_notifier.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_utils.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/host_address_request.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/port_allocator.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/port_allocator.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_api_name.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc165
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h87
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc132
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc83
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.cc136
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc241
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc116
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc322
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc189
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h73
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler_test.cc281
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.cc104
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h57
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler_test.cc196
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/platform.gni1
-rw-r--r--chromium/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5380
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/features.cc81
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/features.h149
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc123
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc659
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h233
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc1073
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc63
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc92
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/web_scheduling_priority.cc (renamed from chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc)31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc329
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h97
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc527
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc92
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc231
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc838
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc89
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc181
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h65
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc264
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc81
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h69
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc239
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h98
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc115
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc124
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/OWNERS9
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/blink_storage_key.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/blink_storage_key.h79
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc144
-rw-r--r--chromium/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc135
-rw-r--r--chromium/third_party/blink/renderer/platform/supplementable.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/compositor_test.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/fuzzed_data_provider.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/image_decode_bench.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.h56
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/url_test_helpers.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/text/bidi_resolver.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/text/bidi_resolver_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/bidi_run_list.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/text/capitalize.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/date_components.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/date_time_format.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc122
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/text/layout_locale.cc36
-rw-r--r--chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc226
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_icu.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_mac.mm10
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_to_script_mapping.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_win.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_win_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/text/mac/hyphenation_mac.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/platform_locale.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/text/platform_locale.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/text/segmented_string.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/segmented_string.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/suffix_tree.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_boundaries.cc71
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_boundaries.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc175
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_run.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_run_iterator.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/text/unicode_range.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/unicode_utilities.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/unicode_utilities_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/timer.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transform_operation.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transform_operations_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc142
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transformation_matrix_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl.cc145
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/referrer.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/referrer.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc53
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/scheme_registry_test.cc103
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin_hash.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc49
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer_test.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc623
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h167
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter_test.cc397
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/track_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_logging.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.cc86
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_unittest.cc67
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/render_frame_metadata_observer_impl_unittest.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/frame_widget.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential_unittest.cc48
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction_unittest.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc82
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_task_list.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/prediction/filter_factory_unittests.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/synchronous_compositor_proxy.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc152
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/widget_base.cc67
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/widget_base.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/widget_base_client.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/date_math.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/decimal.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/deque.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/doubly_linked_list.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/functional.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_map.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_set.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_set_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_table.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/leak_annotations.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_arena.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/scoped_logger.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/shared_buffer.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/stack_util.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/std_lib_extras.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/ascii_ctype.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/atomic_string_table.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/case_folding_hash.h108
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/case_map.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/case_map.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/character_names.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/math_transform.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/math_transform.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/math_transform_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_buffer.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_builder_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_hash.h84
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_hasher.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf16.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_stream.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/unicode.h68
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/unicode_string.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/utf8.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/utf8.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_uchar.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/thread_specific.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading_win.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/tree_node.h212
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/tree_node_test.cc219
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/type_traits_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h3
-rw-r--r--chromium/third_party/blink/tools/blinkpy/PRESUBMIT.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py403
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py17
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/config/builders.json18
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/network_transaction_unittest.py3
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher.py16
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py1
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/web_mock.py14
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/read_checksum_from_png_unittest.py7
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/executive_mock.py18
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py21
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/output_capture.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/platform_info.py17
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/platform_info_unittest.py62
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/system_host_mock.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/system/user_mock.py4
-rwxr-xr-xchromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py90
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checker_unittest.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py16
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py17
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker_unittest.py9
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/png_unittest.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/filter.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/patchreader.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/analyze_baselines.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py6
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/help_command.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/queries.py36
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py3
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py14
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/gerrit.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py74
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py36
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py35
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py56
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py12
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/builder_list.py12
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py26
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py81
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py15
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py44
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py5
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/layout_package/json_results_generator.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_presubmit.py1
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py5
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/merge_results.py72
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/merge_results_unittest.py250
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_configuration.py12
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py32
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures_unittest.py6
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/android_unittest.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py143
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py59
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver_unittest.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py73
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py58
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/factory_unittest.py3
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py64
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt.py43
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt_unittest.py89
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py88
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_mock.py10
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_unittest.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py238
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/win.py17
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/win_unittest.py32
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py10
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py116
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/servers/cli_wrapper.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/servers/wptserve.py33
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/OWNERS1
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/__init__.py14
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders.py65
-rwxr-xr-xchromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders_unittest.py50
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/remove_stale_expectations.py90
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/views/metered_stream_unittest.py7
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/views/printing.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/views/printing_unittest.py5
-rwxr-xr-xchromium/third_party/blink/tools/diff_wpt_results.py107
-rwxr-xr-xchromium/third_party/blink/tools/diff_wpt_results_unittest.py18
-rwxr-xr-xchromium/third_party/blink/tools/merge_web_test_results.py15
-rwxr-xr-xchromium/third_party/blink/tools/remove_stale_expectations.py13
-rwxr-xr-xchromium/third_party/blink/tools/run_bindings_tests.py43
5561 files changed, 145543 insertions, 106666 deletions
diff --git a/chromium/third_party/blink/DEPS b/chromium/third_party/blink/DEPS
index 24154c77662..4c61e4543aa 100644
--- a/chromium/third_party/blink/DEPS
+++ b/chromium/third_party/blink/DEPS
@@ -2,7 +2,7 @@ include_rules = [
"+base/callback.h",
"+base/callback_forward.h",
"+base/callback_helpers.h",
- "+base/memory/checked_ptr.h",
+ "+base/memory/raw_ptr.h",
"+base/trace_event",
"+third_party/perfetto/include/perfetto/tracing",
]
diff --git a/chromium/third_party/blink/PRESUBMIT.py b/chromium/third_party/blink/PRESUBMIT.py
index 2af9d112c37..62395175d85 100644
--- a/chromium/third_party/blink/PRESUBMIT.py
+++ b/chromium/third_party/blink/PRESUBMIT.py
@@ -12,6 +12,8 @@ import inspect
import os
import re
+USE_PYTHON3 = True
+
try:
# pylint: disable=C0103
audit_non_blink_usage = imp.load_source(
@@ -39,9 +41,10 @@ def _CheckForWrongMojomIncludes(input_api, output_api):
return input_api.FilterSourceFile(
path,
files_to_skip=[
- r'third_party/blink/common/',
- r'third_party/blink/public/common',
- r'third_party/blink/renderer/platform/loader/fetch/url_loader',
+ r'.*_test\.(cc|h)$',
+ r'third_party[\\/]blink[\\/]common[\\/]',
+ r'third_party[\\/]blink[\\/]public[\\/]common[\\/]',
+ r'third_party[\\/]blink[\\/]renderer[\\/]platform[\\/]loader[\\/]fetch[\\/]url_loader[\\/]',
])
pattern = input_api.re.compile(r'#include\s+[<"](.+)\.mojom(.*)\.h[>"]')
@@ -62,6 +65,7 @@ def _CheckForWrongMojomIncludes(input_api, output_api):
# the boundary between Blink and non-Blink.
allowed_interfaces = (
'services/network/public/mojom/cross_origin_embedder_policy',
+ 'services/network/public/mojom/early_hints',
'services/network/public/mojom/fetch_api',
'services/network/public/mojom/load_timing_info',
'services/network/public/mojom/url_loader',
@@ -73,6 +77,7 @@ def _CheckForWrongMojomIncludes(input_api, output_api):
'third_party/blink/public/mojom/loader/resource_load_info_notifier',
'third_party/blink/public/mojom/worker/subresource_loader_updater',
'third_party/blink/public/mojom/loader/transferrable_url_loader',
+ 'third_party/blink/public/mojom/loader/code_cache',
'media/mojo/mojom/interface_factory', 'media/mojo/mojom/audio_decoder',
'media/mojo/mojom/video_decoder',
'media/mojo/mojom/media_metrics_provider')
@@ -226,12 +231,35 @@ def _CheckForForbiddenChromiumCode(input_api, output_api):
return results
+def _CheckForDeprecatedFunctions(input_api, output_api):
+ """Checks that Blink does not use deprecated functions."""
+ # TODO(https://crbug.com/1058527) Remove this presubmit once we've finished
+ # the refactor and no callers of `WTF::HashMap::DeprecatedAtOrEmptyValue()` remain.
+ deprecated_re = input_api.re.compile(
+ r'[^/][^/].*\bDeprecatedAtOrEmptyValue\b')
+ errors = input_api.canned_checks._FindNewViolationsOfRule(
+ lambda _, x: not deprecated_re.search(x), input_api, None)
+ errors = [' * %s' % violation for violation in errors]
+ if errors:
+ return [
+ output_api.PresubmitPromptOrNotify(
+ 'WTF::HashMap::DeprecatedAtOrEmptyValue() is deprecated. Please use '
+ 'at() moving forward. Note that at() will crash if the HashMap '
+ 'does not contain the given key, so it is recommended to use '
+ 'find() or Contains() if you are not sure. Please fix the '
+ 'following occurrences before uploading:\n%s' %
+ '\n'.join(errors))
+ ]
+ return []
+
+
def CheckChangeOnUpload(input_api, output_api):
results = []
results.extend(_CommonChecks(input_api, output_api))
results.extend(_CheckStyle(input_api, output_api))
results.extend(_CheckForPrintfDebugging(input_api, output_api))
results.extend(_CheckForForbiddenChromiumCode(input_api, output_api))
+ results.extend(_CheckForDeprecatedFunctions(input_api, output_api))
return results
diff --git a/chromium/third_party/blink/PRESUBMIT_test.py b/chromium/third_party/blink/PRESUBMIT_test.py
index c6af60f62df..9313c83fd44 100755
--- a/chromium/third_party/blink/PRESUBMIT_test.py
+++ b/chromium/third_party/blink/PRESUBMIT_test.py
@@ -145,6 +145,8 @@ class PresubmitTest(unittest.TestCase):
class CxxDependencyTest(unittest.TestCase):
allow_list = [
+ 'base::OnceCallback<void()>',
+ 'base::RepeatingCallback<void()>',
'gfx::ColorSpace',
'gfx::CubicBezier',
'gfx::ICCProfile',
@@ -155,8 +157,6 @@ class CxxDependencyTest(unittest.TestCase):
]
disallow_list = [
'GURL',
- 'base::OnceCallback<void()>',
- 'base::RepeatingCallback<void()>',
'content::RenderFrame',
'gfx::Canvas',
'net::IPEndPoint',
diff --git a/chromium/third_party/blink/common/BUILD.gn b/chromium/third_party/blink/common/BUILD.gn
index 03bcd09f2c5..24d651e9ae4 100644
--- a/chromium/third_party/blink/common/BUILD.gn
+++ b/chromium/third_party/blink/common/BUILD.gn
@@ -78,6 +78,7 @@ source_set("common") {
"cache_storage/cache_storage_utils.cc",
"chrome_debug_urls.cc",
"client_hints/client_hints.cc",
+ "client_hints/enabled_client_hints.cc",
"context_menu_data/context_menu_mojom_traits.cc",
"context_menu_data/context_menu_params_builder.cc",
"context_menu_data/untrustworthy_context_menu_params.cc",
@@ -113,6 +114,8 @@ source_set("common") {
"input/web_mouse_wheel_event.cc",
"input/web_pointer_event.cc",
"input/web_touch_event.cc",
+ "interest_group/interest_group.cc",
+ "interest_group/interest_group_mojom_traits.cc",
"loader/inter_process_time_ticks_converter.cc",
"loader/loader_constants.cc",
"loader/mime_sniffing_throttle.cc",
@@ -150,9 +153,10 @@ source_set("common") {
"native_io/native_io_utils.cc",
"navigation/impression.cc",
"navigation/impression_mojom_traits.cc",
+ "navigation/navigation_params.cc",
"navigation/navigation_policy.cc",
"navigation/navigation_policy_mojom_traits.cc",
- "net/ip_address_space_util.cc",
+ "navigation/prefetched_signed_exchange_info_mojom_traits.cc",
"notifications/notification_mojom_traits.cc",
"notifications/notification_resources.cc",
"notifications/platform_notification_data.cc",
@@ -174,10 +178,14 @@ source_set("common") {
"renderer_preferences/renderer_preferences.cc",
"renderer_preferences/renderer_preferences_mojom_traits.cc",
"scheduler/web_scheduler_tracked_feature.cc",
+ "scheme_registry.cc",
+ "security/address_space_feature.cc",
"service_worker/service_worker_loader_helpers.cc",
"service_worker/service_worker_scope_match.cc",
"service_worker/service_worker_status_code.cc",
"service_worker/service_worker_type_converters.cc",
+ "storage_key/storage_key.cc",
+ "storage_key/storage_key_mojom_traits.cc",
"switches.cc",
"thread_safe_browser_interface_broker_proxy.cc",
"unique_name/unique_name_helper.cc",
@@ -189,10 +197,6 @@ source_set("common") {
"web_preferences/web_preferences.cc",
"web_preferences/web_preferences_mojom_traits.cc",
"widget/device_emulation_params_mojom_traits.cc",
- "widget/screen_info.cc",
- "widget/screen_info_mojom_traits.cc",
- "widget/screen_infos.cc",
- "widget/screen_infos_mojom_traits.cc",
"widget/visual_properties.cc",
"widget/visual_properties_mojom_traits.cc",
]
@@ -224,6 +228,7 @@ source_set("common") {
"//ui/base:base",
"//ui/base/dragdrop/mojom:mojom_shared",
"//ui/display",
+ "//ui/display/mojom",
"//ui/events:events_base",
"//ui/latency/mojom:shared_mojom_traits",
]
@@ -283,12 +288,14 @@ source_set("common_unittests_sources") {
sources = [
"bluetooth/web_bluetooth_device_id_unittest.cc",
"client_hints/client_hints_unittest.cc",
+ "client_hints/enabled_client_hints_unittest.cc",
"device_memory/approximated_device_memory_unittest.cc",
"frame/transient_allow_fullscreen_unittest.cc",
"frame/user_activation_state_unittest.cc",
"indexeddb/indexeddb_key_unittest.cc",
"input/synthetic_web_input_event_builders_unittest.cc",
"input/web_input_event_unittest.cc",
+ "interest_group/interest_group_mojom_traits_test.cc",
"loader/inter_process_time_ticks_converter_unittest.cc",
"loader/mime_sniffing_throttle_unittest.cc",
"loader/referrer_utils_unittest.cc",
@@ -299,7 +306,6 @@ source_set("common_unittests_sources") {
"mediastream/media_devices_unittest.cc",
"messaging/message_port_descriptor_unittest.cc",
"mime_util/mime_util_unittest.cc",
- "net/ip_address_space_util_unittest.cc",
"notifications/notification_mojom_traits_unittest.cc",
"origin_trials/trial_token_unittest.cc",
"origin_trials/trial_token_validator_unittest.cc",
@@ -309,14 +315,16 @@ source_set("common_unittests_sources") {
"permissions_policy/permissions_policy_unittest.cc",
"permissions_policy/policy_value_unittest.cc",
"scheduler/web_scheduler_tracked_feature_unittest.cc",
+ "security/address_space_feature_unittest.cc",
"service_worker/service_worker_scope_match_unittest.cc",
+ "storage_key/storage_key_mojom_traits_unittest.cc",
+ "storage_key/storage_key_unittest.cc",
"test/run_all_unittests.cc",
"tokens/multi_token_unittest.cc",
"tokens/tokens_mojom_traits_unittest.cc",
"unique_name/unique_name_helper_unittest.cc",
"user_agent/user_agent_metadata_unittest.cc",
"web_package/web_package_request_matcher_unittest.cc",
- "widget/screen_infos_mojom_traits_unittest.cc",
]
deps = [
@@ -364,3 +372,13 @@ source_set("common_unittests_sources") {
group("common_unittests_data") {
data = [ "page_state/test_data/" ]
}
+
+static_library("test_support") {
+ testonly = true
+
+ sources = [ "origin_trials/scoped_test_origin_trial_policy.cc" ]
+
+ deps = [ "//third_party/blink/public:test_headers" ]
+
+ visibility = [ "//third_party/blink/public:test_support" ]
+}
diff --git a/chromium/third_party/blink/common/DEPS b/chromium/third_party/blink/common/DEPS
index fbedc360414..81e1c1d54e3 100644
--- a/chromium/third_party/blink/common/DEPS
+++ b/chromium/third_party/blink/common/DEPS
@@ -21,6 +21,7 @@ include_rules = [
"+services/network/public/mojom/parsed_headers.mojom.h",
"+services/network/public/mojom/referrer_policy.mojom.h",
"+services/network/public/mojom/web_sandbox_flags.mojom-shared.h",
+ "+services/network/public/mojom/early_hints.mojom.h",
"+services/network/public/mojom/url_loader.mojom.h",
"+services/network/public/mojom/url_loader_factory.mojom.h",
"+services/network/public/mojom/url_response_head.mojom.h",
diff --git a/chromium/third_party/blink/common/OWNERS b/chromium/third_party/blink/common/OWNERS
index 20eecf76956..c39020ab224 100644
--- a/chromium/third_party/blink/common/OWNERS
+++ b/chromium/third_party/blink/common/OWNERS
@@ -7,7 +7,6 @@ jam@chromium.org
jbroman@chromium.org
kinuko@chromium.org
pfeldman@chromium.org
-tkent@chromium.org
# Any core owner can approve blink finch flags.
per-file features.cc=file://third_party/blink/renderer/core/OWNERS
diff --git a/chromium/third_party/blink/common/associated_interfaces/associated_interface_provider.cc b/chromium/third_party/blink/common/associated_interfaces/associated_interface_provider.cc
index 8193119795d..826f183b6f2 100644
--- a/chromium/third_party/blink/common/associated_interfaces/associated_interface_provider.cc
+++ b/chromium/third_party/blink/common/associated_interfaces/associated_interface_provider.cc
@@ -23,8 +23,10 @@ class AssociatedInterfaceProvider::LocalProvider
remote_.BindNewEndpointAndPassDedicatedReceiver(),
std::move(task_runner));
}
+ LocalProvider(const LocalProvider&) = delete;
+ LocalProvider& operator=(const LocalProvider&) = delete;
- ~LocalProvider() override {}
+ ~LocalProvider() override = default;
void SetBinderForName(const std::string& name, const Binder& binder) {
binders_[name] = binder;
@@ -56,8 +58,6 @@ class AssociatedInterfaceProvider::LocalProvider
mojo::AssociatedReceiver<mojom::AssociatedInterfaceProvider>
associated_interface_provider_receiver_{this};
mojo::AssociatedRemote<mojom::AssociatedInterfaceProvider> remote_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalProvider);
};
AssociatedInterfaceProvider::AssociatedInterfaceProvider(
diff --git a/chromium/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc b/chromium/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc
index 7ba88c0930d..bca469b3e54 100644
--- a/chromium/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc
+++ b/chromium/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
+#include <ostream>
#include <utility>
#include "base/base64.h"
diff --git a/chromium/third_party/blink/common/browser_interface_broker_proxy.cc b/chromium/third_party/blink/common/browser_interface_broker_proxy.cc
index a5712719cf3..7d30a1d55c1 100644
--- a/chromium/third_party/blink/common/browser_interface_broker_proxy.cc
+++ b/chromium/third_party/blink/common/browser_interface_broker_proxy.cc
@@ -3,7 +3,8 @@
// found in the LICENSE file.
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "base/no_destructor.h"
+
+#include "base/macros.h"
#include "base/threading/sequence_local_storage_slot.h"
namespace blink {
@@ -60,17 +61,15 @@ bool BrowserInterfaceBrokerProxy::SetBinderForTesting(
}
BrowserInterfaceBrokerProxy& GetEmptyBrowserInterfaceBroker() {
- static base::NoDestructor<
- base::SequenceLocalStorageSlot<BrowserInterfaceBrokerProxy>>
- proxy_slot;
- if (!proxy_slot->GetValuePointer()) {
- auto& proxy = proxy_slot->GetOrCreateValue();
+ static base::SequenceLocalStorageSlot<BrowserInterfaceBrokerProxy> proxy_slot;
+ if (!proxy_slot.GetValuePointer()) {
+ auto& proxy = proxy_slot.GetOrCreateValue();
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> remote;
ignore_result(remote.InitWithNewPipeAndPassReceiver());
proxy.Bind(std::move(remote), base::ThreadTaskRunnerHandle::Get());
}
- return proxy_slot->GetOrCreateValue();
+ return proxy_slot.GetOrCreateValue();
}
} // namespace blink
diff --git a/chromium/third_party/blink/common/client_hints/client_hints.cc b/chromium/third_party/blink/common/client_hints/client_hints.cc
index 7d195ffcd7e..f8e39c9ed28 100644
--- a/chromium/third_party/blink/common/client_hints/client_hints.cc
+++ b/chromium/third_party/blink/common/client_hints/client_hints.cc
@@ -7,36 +7,35 @@
#include <utility>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
#include "url/origin.h"
namespace blink {
-const char* const kClientHintsHeaderMapping[] = {
- "device-memory",
- "dpr",
- "width",
- "viewport-width",
- "rtt",
- "downlink",
- "ect",
- "sec-ch-lang",
- "sec-ch-ua",
- "sec-ch-ua-arch",
- "sec-ch-ua-platform",
- "sec-ch-ua-model",
- "sec-ch-ua-mobile",
- "sec-ch-ua-full-version",
- "sec-ch-ua-platform-version",
- "sec-ch-prefers-color-scheme",
-};
+const char* const kClientHintsHeaderMapping[] = {"device-memory",
+ "dpr",
+ "width",
+ "viewport-width",
+ "rtt",
+ "downlink",
+ "ect",
+ "sec-ch-lang",
+ "sec-ch-ua",
+ "sec-ch-ua-arch",
+ "sec-ch-ua-platform",
+ "sec-ch-ua-model",
+ "sec-ch-ua-mobile",
+ "sec-ch-ua-full-version",
+ "sec-ch-ua-platform-version",
+ "sec-ch-prefers-color-scheme",
+ "sec-ch-ua-bitness",
+ "sec-ch-ua-reduced"};
const unsigned kClientHintsNumberOfLegacyHints = 4;
@@ -60,6 +59,8 @@ const mojom::PermissionsPolicyFeature kClientHintsPermissionsPolicyMapping[] = {
mojom::PermissionsPolicyFeature::kClientHintUAFullVersion,
mojom::PermissionsPolicyFeature::kClientHintUAPlatformVersion,
mojom::PermissionsPolicyFeature::kClientHintPrefersColorScheme,
+ mojom::PermissionsPolicyFeature::kClientHintUABitness,
+ mojom::PermissionsPolicyFeature::kClientHintUAReduced,
};
const size_t kClientHintsMappingsCount = base::size(kClientHintsHeaderMapping);
@@ -94,46 +95,17 @@ std::string SerializeLangClientHint(const std::string& raw_language_list) {
return result;
}
-absl::optional<std::vector<network::mojom::WebClientHintsType>> FilterAcceptCH(
- absl::optional<std::vector<network::mojom::WebClientHintsType>> in,
- bool permit_lang_hints,
- bool permit_ua_hints,
- bool permit_prefers_color_scheme_hints) {
- if (!in.has_value())
- return absl::nullopt;
-
- std::vector<network::mojom::WebClientHintsType> result;
- for (network::mojom::WebClientHintsType hint : in.value()) {
- // Some hints are supported only conditionally.
- switch (hint) {
- case network::mojom::WebClientHintsType::kLang:
- if (permit_lang_hints)
- result.push_back(hint);
- break;
- case network::mojom::WebClientHintsType::kUA:
- case network::mojom::WebClientHintsType::kUAArch:
- case network::mojom::WebClientHintsType::kUAPlatform:
- case network::mojom::WebClientHintsType::kUAPlatformVersion:
- case network::mojom::WebClientHintsType::kUAModel:
- case network::mojom::WebClientHintsType::kUAMobile:
- case network::mojom::WebClientHintsType::kUAFullVersion:
- if (permit_ua_hints)
- result.push_back(hint);
- break;
- case network::mojom::WebClientHintsType::kPrefersColorScheme:
- if (permit_prefers_color_scheme_hints)
- result.push_back(hint);
- break;
- default:
- result.push_back(hint);
- }
- }
- return absl::make_optional(std::move(result));
-}
-
bool IsClientHintSentByDefault(network::mojom::WebClientHintsType type) {
- return (type == network::mojom::WebClientHintsType::kUA ||
- type == network::mojom::WebClientHintsType::kUAMobile);
+ switch (type) {
+ case network::mojom::WebClientHintsType::kUA:
+ case network::mojom::WebClientHintsType::kUAMobile:
+ return true;
+ case network::mojom::WebClientHintsType::kUAPlatform:
+ return base::FeatureList::IsEnabled(
+ features::kUACHPlatformEnabledByDefault);
+ default:
+ return false;
+ }
}
// Add a list of Client Hints headers to be removed to the output vector, based
diff --git a/chromium/third_party/blink/common/client_hints/client_hints_unittest.cc b/chromium/third_party/blink/common/client_hints/client_hints_unittest.cc
index f32cf38839a..a65ea065ba8 100644
--- a/chromium/third_party/blink/common/client_hints/client_hints_unittest.cc
+++ b/chromium/third_party/blink/common/client_hints/client_hints_unittest.cc
@@ -32,92 +32,6 @@ TEST(ClientHintsTest, SerializeLangClientHint) {
header);
}
-TEST(ClientHintsTest, FilterAcceptCH) {
- EXPECT_FALSE(FilterAcceptCH(absl::nullopt, /*permit_lang_hints=*/true,
- /*permit_ua_hints=*/true,
- /*permit_prefers_color_scheme_hints=*/true)
- .has_value());
-
- absl::optional<std::vector<network::mojom::WebClientHintsType>> result;
-
- result =
- FilterAcceptCH(std::vector<network::mojom::WebClientHintsType>(
- {network::mojom::WebClientHintsType::kDeviceMemory,
- network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kUA}),
- /*permit_lang_hints=*/false,
- /*permit_ua_hints=*/true,
- /*permit_prefers_color_scheme_hints=*/false);
- ASSERT_TRUE(result.has_value());
- EXPECT_THAT(
- result.value(),
- UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
- network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kUA));
-
- result = FilterAcceptCH(
- std::vector<network::mojom::WebClientHintsType>(
- {network::mojom::WebClientHintsType::kDeviceMemory,
- network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kPrefersColorScheme}),
- /*permit_lang_hints=*/false,
- /*permit_ua_hints=*/false,
- /*permit_prefers_color_scheme_hints=*/true);
- ASSERT_TRUE(result.has_value());
- EXPECT_THAT(result.value(),
- UnorderedElementsAre(
- network::mojom::WebClientHintsType::kDeviceMemory,
- network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kPrefersColorScheme));
-
- std::vector<network::mojom::WebClientHintsType> in{
- network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kLang,
- network::mojom::WebClientHintsType::kUA,
- network::mojom::WebClientHintsType::kUAArch,
- network::mojom::WebClientHintsType::kUAPlatform,
- network::mojom::WebClientHintsType::kUAPlatformVersion,
- network::mojom::WebClientHintsType::kUAModel,
- network::mojom::WebClientHintsType::kUAMobile,
- network::mojom::WebClientHintsType::kUAFullVersion,
- network::mojom::WebClientHintsType::kPrefersColorScheme};
-
- result = FilterAcceptCH(in,
- /*permit_lang_hints=*/true,
- /*permit_ua_hints=*/false,
- /*permit_prefers_color_scheme_hints=*/false);
- ASSERT_TRUE(result.has_value());
- EXPECT_THAT(result.value(),
- UnorderedElementsAre(network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kLang));
-
- result = FilterAcceptCH(in,
- /*permit_lang_hints=*/true,
- /*permit_ua_hints=*/true,
- /*permit_prefers_color_scheme_hints=*/true);
- ASSERT_TRUE(result.has_value());
- EXPECT_THAT(result.value(),
- UnorderedElementsAre(
- network::mojom::WebClientHintsType::kRtt,
- network::mojom::WebClientHintsType::kLang,
- network::mojom::WebClientHintsType::kUA,
- network::mojom::WebClientHintsType::kUAArch,
- network::mojom::WebClientHintsType::kUAPlatform,
- network::mojom::WebClientHintsType::kUAPlatformVersion,
- network::mojom::WebClientHintsType::kUAModel,
- network::mojom::WebClientHintsType::kUAMobile,
- network::mojom::WebClientHintsType::kUAFullVersion,
- network::mojom::WebClientHintsType::kPrefersColorScheme));
-
- result = FilterAcceptCH(in,
- /*permit_lang_hints=*/false,
- /*permit_ua_hints=*/false,
- /*permit_prefers_color_scheme_hints=*/false);
- ASSERT_TRUE(result.has_value());
- EXPECT_THAT(result.value(),
- UnorderedElementsAre(network::mojom::WebClientHintsType::kRtt));
-}
-
// Checks that the removed header list doesn't include legacy headers nor the
// on-by-default ones, when the kAllowClientHintsToThirdParty flag is on.
TEST(ClientHintsTest, FindClientHintsToRemoveLegacy) {
@@ -127,11 +41,11 @@ TEST(ClientHintsTest, FindClientHintsToRemoveLegacy) {
std::vector<std::string> removed_headers;
FindClientHintsToRemove(nullptr, GURL(), &removed_headers);
EXPECT_THAT(removed_headers,
- UnorderedElementsAre("rtt", "downlink", "ect", "sec-ch-lang",
- "sec-ch-ua-arch", "sec-ch-ua-platform",
- "sec-ch-ua-model", "sec-ch-ua-full-version",
- "sec-ch-ua-platform-version",
- "sec-ch-prefers-color-scheme"));
+ UnorderedElementsAre(
+ "rtt", "downlink", "ect", "sec-ch-lang", "sec-ch-ua-arch",
+ "sec-ch-ua-model", "sec-ch-ua-full-version",
+ "sec-ch-ua-platform-version", "sec-ch-prefers-color-scheme",
+ "sec-ch-ua-bitness", "sec-ch-ua-reduced"));
}
// Checks that the removed header list includes legacy headers but not the
@@ -142,12 +56,12 @@ TEST(ClientHintsTest, FindClientHintsToRemoveNoLegacy) {
features::kAllowClientHintsToThirdParty);
std::vector<std::string> removed_headers;
FindClientHintsToRemove(nullptr, GURL(), &removed_headers);
- EXPECT_THAT(
- removed_headers,
- UnorderedElementsAre(
- "device-memory", "dpr", "width", "viewport-width", "rtt", "downlink",
- "ect", "sec-ch-lang", "sec-ch-ua-arch", "sec-ch-ua-platform",
- "sec-ch-ua-model", "sec-ch-ua-full-version",
- "sec-ch-ua-platform-version", "sec-ch-prefers-color-scheme"));
+ EXPECT_THAT(removed_headers,
+ UnorderedElementsAre(
+ "device-memory", "dpr", "width", "viewport-width", "rtt",
+ "downlink", "ect", "sec-ch-lang", "sec-ch-ua-arch",
+ "sec-ch-ua-model", "sec-ch-ua-full-version",
+ "sec-ch-ua-platform-version", "sec-ch-prefers-color-scheme",
+ "sec-ch-ua-bitness", "sec-ch-ua-reduced"));
}
} // namespace blink
diff --git a/chromium/third_party/blink/common/client_hints/enabled_client_hints.cc b/chromium/third_party/blink/common/client_hints/enabled_client_hints.cc
new file mode 100644
index 00000000000..59226fd49c3
--- /dev/null
+++ b/chromium/third_party/blink/common/client_hints/enabled_client_hints.cc
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
+
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace blink {
+
+namespace {
+
+using ::network::mojom::WebClientHintsType;
+
+bool IsDisabledByFeature(const WebClientHintsType type) {
+ switch (type) {
+ case WebClientHintsType::kLang:
+ if (!base::FeatureList::IsEnabled(features::kLangClientHintHeader))
+ return true;
+ break;
+ case WebClientHintsType::kUA:
+ case WebClientHintsType::kUAArch:
+ case WebClientHintsType::kUAPlatform:
+ case WebClientHintsType::kUAPlatformVersion:
+ case WebClientHintsType::kUAModel:
+ case WebClientHintsType::kUAMobile:
+ case WebClientHintsType::kUAFullVersion:
+ case WebClientHintsType::kUABitness:
+ if (!base::FeatureList::IsEnabled(features::kUserAgentClientHint))
+ return true;
+ break;
+ case WebClientHintsType::kPrefersColorScheme:
+ if (!base::FeatureList::IsEnabled(
+ features::kPrefersColorSchemeClientHintHeader))
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+} // namespace
+
+bool EnabledClientHints::IsEnabled(const WebClientHintsType type) const {
+ if (IsDisabledByFeature(type)) {
+ return false;
+ }
+ return enabled_types_[static_cast<int>(type)];
+}
+
+void EnabledClientHints::SetIsEnabled(const WebClientHintsType type,
+ const bool should_send) {
+ enabled_types_[static_cast<int>(type)] = should_send;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc b/chromium/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc
new file mode 100644
index 00000000000..77be96a67ac
--- /dev/null
+++ b/chromium/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace blink {
+
+using ::network::mojom::WebClientHintsType;
+
+class EnabledClientHintsTest : public testing::Test {
+ public:
+ EnabledClientHintsTest() {
+ // The UserAgentClientHint feature is enabled, and the LangClientHintHeader
+ // feature is disabled.
+ scoped_feature_list_.InitWithFeatures(
+ /*enabled_features=*/{blink::features::kUserAgentClientHint},
+ /*disabled_features=*/{blink::features::kLangClientHintHeader});
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(EnabledClientHintsTest, EnabledClientHint) {
+ EnabledClientHints hints;
+ hints.SetIsEnabled(WebClientHintsType::kUAFullVersion, true);
+ hints.SetIsEnabled(WebClientHintsType::kRtt, true);
+ EXPECT_TRUE(hints.IsEnabled(WebClientHintsType::kUAFullVersion));
+ EXPECT_TRUE(hints.IsEnabled(WebClientHintsType::kRtt));
+}
+
+TEST_F(EnabledClientHintsTest, DisabledClientHint) {
+ EnabledClientHints hints;
+ hints.SetIsEnabled(WebClientHintsType::kUAFullVersion, false);
+ hints.SetIsEnabled(WebClientHintsType::kRtt, false);
+ EXPECT_FALSE(hints.IsEnabled(WebClientHintsType::kUAFullVersion));
+ EXPECT_FALSE(hints.IsEnabled(WebClientHintsType::kRtt));
+}
+
+TEST_F(EnabledClientHintsTest, EnabledClientHintOnDisabledFeature) {
+ EnabledClientHints hints;
+ // Attempting to enable the lang client hint, but the runtime flag for it is
+ // disabled.
+ hints.SetIsEnabled(WebClientHintsType::kLang, true);
+ EXPECT_FALSE(hints.IsEnabled(WebClientHintsType::kLang));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/features.cc b/chromium/third_party/blink/common/features.cc
index dbb727828b6..be6f237f403 100644
--- a/chromium/third_party/blink/common/features.cc
+++ b/chromium/third_party/blink/common/features.cc
@@ -19,6 +19,10 @@ const base::Feature kBlockingDownloadsInAdFrameWithoutUserActivation{
"BlockingDownloadsInAdFrameWithoutUserActivation",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Support COEP on SharedWorker.
+const base::Feature kCOEPForSharedWorker{"COEPForSharedWorker",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kCOLRV1Fonts{"COLRV1Fonts",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -26,23 +30,15 @@ const base::Feature kCOLRV1Fonts{"COLRV1Fonts",
const base::Feature kCSSContainerQueries{"CSSContainerQueries",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether the Conversion Measurement API infrastructure is enabled.
+const base::Feature kConversionMeasurement{"ConversionMeasurement",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
const base::Feature kGMSCoreEmoji{"GMSCoreEmoji",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Whether the HandwritingRecognition API can be enabled. Disabling this feature
-// disables both the origin trial and the mojo interface. Enabling this feature
-// allows the API to be controlled by origin trial (see web runtime feature
-// `HandwritingRecognition`) and finch (see
-// `kHandwritingRecognitionWebPlatformApiFinch`).
-// TODO (crbug.com/1166910): Remove once the HandwritingRecognition API is more
-// widely available (likely M92).
-const base::Feature kHandwritingRecognitionWebPlatformApi{
- "HandwritingRecognitionWebPlatformApi", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Whether the HandwritingRecognition API can be enabled. Disabling this feature
-// disables both the origin trial and the mojo interface. Defaults to enabled
-// so the feature can be controlled by finch, even when
-// `kHandwritingRecognitionWebPlatformApi` is set from command-line.
+// Whether the HandwritingRecognition API can be enabled by origin trial.
+// Disabling this feature disables both the origin trial and the mojo interface.
const base::Feature kHandwritingRecognitionWebPlatformApiFinch{
"HandwritingRecognitionWebPlatformApiFinch",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -80,7 +76,7 @@ const base::Feature kFreezePurgeMemoryAllPagesFrozen{
"FreezePurgeMemoryAllPagesFrozen", base::FEATURE_DISABLED_BY_DEFAULT};
// Freezes the user-agent as part of https://github.com/WICG/ua-client-hints.
-const base::Feature kFreezeUserAgent{"FreezeUserAgent",
+const base::Feature kReduceUserAgent{"ReduceUserAgent",
base::FEATURE_DISABLED_BY_DEFAULT};
// Enables the frequency capping for detecting overlay popups. Overlay-popups
@@ -124,6 +120,19 @@ const base::Feature kLayoutNGTable{"LayoutNGTable",
const base::Feature kMixedContentAutoupgrade{"AutoupgradeMixedContent",
base::FEATURE_ENABLED_BY_DEFAULT};
+// An experimental replacement for the `User-Agent` header, defined in
+// https://tools.ietf.org/html/draft-west-ua-client-hints.
+const base::Feature kUserAgentClientHint{"UserAgentClientHint",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Experimental handling of accept-language via client hints.
+const base::Feature kLangClientHintHeader{"LangClientHintHeader",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Handle prefers-color-scheme user preference media feature via client hints.
+const base::Feature kPrefersColorSchemeClientHintHeader{
+ "PrefersColorSchemeClientHintHeader", base::FEATURE_ENABLED_BY_DEFAULT};
+
// Used to control the collection of anchor element metrics (crbug.com/856683).
// If kNavigationPredictor is enabled, then metrics of anchor elements
// in the first viewport after the page load and the metrics of the clicked
@@ -139,10 +148,10 @@ const base::Feature kNavigationPredictor {
#endif
};
-// This feature returns empty arrays for navigator.plugins and
-// navigator.mimeTypes. It is disabled for now, due to compat issues.
-const base::Feature kNavigatorPluginsEmpty{"NavigatorPluginsEmpty",
- base::FEATURE_DISABLED_BY_DEFAULT};
+// This feature returns fixed arrays for navigator.plugins and
+// navigator.mimeTypes.
+const base::Feature kNavigatorPluginsFixed{"NavigatorPluginsFixed",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Enable browser-initiated dedicated worker script loading
// (PlzDedicatedWorker). https://crbug.com/906991
@@ -185,14 +194,42 @@ const base::FeatureParam<FencedFramesImplementationType>
FencedFramesImplementationType::kShadowDOM,
&fenced_frame_implementation_types};
-// Enable the prerender2. https://crbug.com/1126305.
-const base::Feature kPrerender2{"Prerender2",
- base::FEATURE_DISABLED_BY_DEFAULT};
+// Enable the shared storage API. This base::Feature directly controls the
+// corresponding runtime enabled feature.
+// https://github.com/pythagoraskitty/shared-storage/blob/main/README.md
+const base::Feature kSharedStorageAPI{"SharedStorageAPI",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+const base::FeatureParam<int>
+ kSharedStorageURLSelectionOperationInputURLSizeLimit{
+ &kSharedStorageAPI, "url_selection_operation_input_url_size_limit", 5};
+
+// Enables the Prerender2 feature: https://crbug.com/1126305
+// Note that default enabling this does not enable the Prerender2 features
+// because kSetOnlyIfOverridden is used for setting WebRuntimeFeatures'
+// Prerender2. To enable this feature, we need to force-enable this feature
+// using chrome://flags/#enable-prerender2 or --enable-features=Prerender2
+// command line or a valid Origin Trial token in the page.
+const base::Feature kPrerender2 {
+ "Prerender2",
+#if defined(OS_ANDROID)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
+const base::Feature kPrerender2MemoryControls{"Prerender2MemoryControls",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+const char kPrerender2MemoryThresholdParamName[] = "memory_threshold_in_mb";
bool IsPrerender2Enabled() {
return base::FeatureList::IsEnabled(blink::features::kPrerender2);
}
+bool IsFencedFramesEnabled() {
+ return base::FeatureList::IsEnabled(blink::features::kFencedFrames);
+}
+
// Enable limiting previews loading hints to specific resource types.
const base::Feature kPreviewsResourceLoadingHintsSpecificResourceTypes{
"PreviewsResourceLoadingHintsSpecificResourceTypes",
@@ -212,21 +249,18 @@ const base::Feature kPurgeRendererMemoryWhenBackgrounded {
#endif
};
-// Enables Raw Clipboard. https://crbug.com/897289.
-const base::Feature kRawClipboard{"RawClipboard",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Kill switch for getCurrentBrowsingContextMedia(), which allows capturing of
-// web content from the tab from which it is called. (crbug.com/1136940)
-const base::Feature kRTCGetCurrentBrowsingContextMedia{
- "RTCGetCurrentBrowsingContextMedia", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Changes the default RTCPeerConnection constructor behavior to use Unified
// Plan as the SDP semantics. When the feature is enabled, Unified Plan is used
// unless the default is overridden (by passing {sdpSemantics:'plan-b'} as the
-// argument).
+// argument). This was shipped in M72.
+// The feature is still used by virtual test suites exercising Plan B.
const base::Feature kRTCUnifiedPlanByDefault{"RTCUnifiedPlanByDefault",
base::FEATURE_ENABLED_BY_DEFAULT};
+// When enabled, throw an exception when an RTCPeerConnection is constructed
+// with {sdpSemantics:"plan-b"} and the Deprecation Trial is not enabled.
+const base::Feature kRTCDisallowPlanBOutsideDeprecationTrial{
+ "RTCDisallowPlanBOutsideDeprecationTrial",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Determines if the SDP attrbute extmap-allow-mixed should be offered by
// default or not. The default value can be overridden by passing
@@ -342,6 +376,10 @@ const base::Feature kTextFragmentAnchor{"TextFragmentAnchor",
const base::Feature kFileHandlingAPI{"FileHandlingAPI",
base::FEATURE_DISABLED_BY_DEFAULT};
+// File handling icons. https://crbug.com/1218213
+const base::Feature kFileHandlingIcons{"FileHandlingIcons",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Allows for synchronous XHR requests during page dismissal
const base::Feature kAllowSyncXHRInPageDismissal{
"AllowSyncXHRInPageDismissal", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -516,12 +554,6 @@ const base::Feature kBlinkCompositorUseDisplayThreadPriority {
#endif
};
-// Ignores cross origin windows in the named property interceptor of Window.
-// https://crbug.com/538562
-const base::Feature kIgnoreCrossOriginWindowWhenNamedAccessOnWindow{
- "IgnoreCrossOriginWindowWhenNamedAccessOnWindow",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Enables redirecting subresources in the page to better compressed and
// optimized versions to provide data savings.
const base::Feature kSubresourceRedirect{"SubresourceRedirect",
@@ -535,7 +567,9 @@ const base::Feature kSubresourceRedirectSrcVideo{
// When enabled, enforces new interoperable semantics for 3D transforms.
// See crbug.com/1008483.
const base::Feature kTransformInterop{"TransformInterop",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kBackfaceVisibilityInterop{
+ "BackfaceVisibilityInterop", base::FEATURE_DISABLED_BY_DEFAULT};
// When enabled, beacons (and friends) have ResourceLoadPriority::kLow,
// not ResourceLoadPriority::kVeryLow.
@@ -609,55 +643,6 @@ const base::FeatureParam<int> kFontPreloadingDelaysRenderingParam{
const base::Feature kKeepScriptResourceAlive{"KeepScriptResourceAlive",
base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kDelayAsyncScriptExecution{
- "DelayAsyncScriptExecution", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::FeatureParam<DelayAsyncScriptDelayType>::Option
- delay_async_script_execution_delay_types[] = {
- {DelayAsyncScriptDelayType::kFinishedParsing, "finished_parsing"},
- {DelayAsyncScriptDelayType::kFirstPaintOrFinishedParsing,
- "first_paint_or_finished_parsing"},
- {DelayAsyncScriptDelayType::kUseOptimizationGuide,
- "use_optimization_guide"}};
-const base::FeatureParam<DelayAsyncScriptDelayType>
- kDelayAsyncScriptExecutionDelayParam{
- &kDelayAsyncScriptExecution, "delay_type",
- DelayAsyncScriptDelayType::kFinishedParsing,
- &delay_async_script_execution_delay_types};
-
-// Feature and parameters for delaying low priority requests behind "important"
-// (either high or medium priority requests). There are two parameters
-// highlighted below.
-const base::Feature kDelayCompetingLowPriorityRequests{
- "DelayCompetingLowPriorityRequests", base::FEATURE_DISABLED_BY_DEFAULT};
-// The delay type: We don't want to delay low priority requests behind
-// "important" requests forever. Rather, it makes sense to have this behavior up
-// *until* some relevant loading milestone, which this parameter specifies.
-const base::FeatureParam<DelayCompetingLowPriorityRequestsDelayType>::Option
- delay_competing_low_priority_requests_delay_types[] = {
- {DelayCompetingLowPriorityRequestsDelayType::kFirstPaint,
- "first_paint"},
- {DelayCompetingLowPriorityRequestsDelayType::kFirstContentfulPaint,
- "first_contentful_paint"},
- {DelayCompetingLowPriorityRequestsDelayType::kAlways, "always"},
- {DelayCompetingLowPriorityRequestsDelayType::kUseOptimizationGuide,
- "use_optimization_guide"}};
-const base::FeatureParam<DelayCompetingLowPriorityRequestsDelayType>
- kDelayCompetingLowPriorityRequestsDelayParam{
- &kDelayCompetingLowPriorityRequests, "until",
- DelayCompetingLowPriorityRequestsDelayType::kFirstContentfulPaint,
- &delay_competing_low_priority_requests_delay_types};
-// The priority threshold: indicates which ResourceLoadPriority should be
-// considered "important", such that low priority requests are delayed behind
-// in-flight "important" requests.
-const base::FeatureParam<DelayCompetingLowPriorityRequestsThreshold>::Option
- delay_competing_low_priority_requests_thresholds[] = {
- {DelayCompetingLowPriorityRequestsThreshold::kMedium, "medium"},
- {DelayCompetingLowPriorityRequestsThreshold::kHigh, "high"}};
-const base::FeatureParam<DelayCompetingLowPriorityRequestsThreshold>
- kDelayCompetingLowPriorityRequestsThresholdParam{
- &kDelayCompetingLowPriorityRequests, "priority_threshold",
- DelayCompetingLowPriorityRequestsThreshold::kHigh,
- &delay_competing_low_priority_requests_thresholds};
// The AppCache feature is a kill-switch for the entire AppCache feature,
// both backend and API. If disabled, then it will turn off the backend and
@@ -770,8 +755,8 @@ bool IsParkableStringsToDiskEnabled() {
const base::Feature kCrOSAutoSelect{"CrOSAutoSelect",
base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kCompositingOptimizations{
- "CompositingOptimizations", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kCLSScrollAnchoring{"CLSScrollAnchoring",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Reduce the amount of information in the default 'referer' header for
// cross-origin requests.
@@ -815,12 +800,27 @@ const base::Feature kLogUnexpectedIPCPostedToBackForwardCachedDocuments{
"LogUnexpectedIPCPostedToBackForwardCachedDocuments",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Enables web apps to request isolated storage.
+const base::Feature kWebAppEnableIsolatedStorage{
+ "WebAppEnableIsolatedStorage", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables the "launch_handler" manifest field for web apps.
+// Explainer: https://github.com/WICG/sw-launch/blob/main/launch_handler.md
+const base::Feature kWebAppEnableLaunchHandler{
+ "WebAppEnableLaunchHandler", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables declarative link capturing in web apps.
// Explainer:
// https://github.com/WICG/sw-launch/blob/master/declarative_link_capturing.md
const base::Feature kWebAppEnableLinkCapturing{
"WebAppEnableLinkCapturing", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables Unique ID feature in web apps. Controls parsing of "id" field in web
+// app manifests. See explainer for more information:
+// https://github.com/philloooo/pwa-unique-id
+const base::Feature kWebAppEnableManifestId{"WebAppEnableManifestId",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls URL handling feature in web apps. Controls parsing of "url_handlers"
// field in web app manifests. See explainer for more information:
// https://github.com/WICG/pwa-url-handler/blob/master/explainer.md
@@ -839,14 +839,8 @@ const base::Feature kWebAppEnableProtocolHandlers{
// manifests. Also controls whether the parsed field is used in browser. See
// incubation spec:
// https://wicg.github.io/manifest-incubations/#note_taking-member
-// TODO(crbug.com/1185678): Enable by default after M92 branches.
const base::Feature kWebAppNoteTaking{"WebAppNoteTaking",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// When enabled NV12 frames on a GPU will be forwarded to libvpx encoders
-// without conversion to I420.
-const base::Feature kWebRtcLibvpxEncodeNV12{"WebRtcLibvpxEncodeNV12",
- base::FEATURE_ENABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Makes network loading tasks unfreezable so that they can be processed while
// the page is frozen.
@@ -897,7 +891,7 @@ const base::Feature kInterestCohortFeaturePolicy{
// Changes the default background color of the Text Fragment from
// bright yellow rgb(255, 255, 0) to light purple rgb(233, 210, 253)
const base::Feature kTextFragmentColorChange{"TextFragmentColorChange",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kDisableDocumentDomainByDefault{
"DisableDocumentDomainByDefault", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -926,9 +920,6 @@ const base::FeatureParam<std::string>
kBackgroundTracingPerformanceMark_AllowList{
&kBackgroundTracingPerformanceMark, "allow_list", ""};
-const base::Feature kCLSM90Improvements{"CLSM90Improvements",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// New compositing algorithm. See renderer/core/paint/README.md.
const base::Feature kCompositeAfterPaint{"CompositeAfterPaint",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -973,5 +964,61 @@ const base::Feature kMinimizeAudioProcessingForUnusedOutput{
"MinimizeAudioProcessingForUnusedOutput",
base::FEATURE_DISABLED_BY_DEFAULT};
+// When <dialog>s are closed, this focuses the "previously focused" element
+// which had focus when the <dialog> was first opened.
+// TODO(crbug.com/649162): Remove DialogFocusNewSpecBehavior after
+// the feature is in stable with no issues.
+const base::Feature kDialogFocusNewSpecBehavior{
+ "DialogFocusNewSpecBehavior", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Makes autofill look across shadow boundaries when collecting form controls to
+// fill.
+const base::Feature kAutofillShadowDOM{"AutofillShadowDOM",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+// Allows read/write of custom formats with unsanitized clipboard content. See
+// crbug.com/106449.
+const base::Feature kClipboardCustomFormats{"ClipboardCustomFormats",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Uses page viewport instead of frame viewport in the Largest Contentful Paint
+// heuristic where images occupying the full viewport are ignored.
+const base::Feature kUsePageViewportInLCP{"UsePageViewportInLCP",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enable `Sec-CH-UA-Platform` client hint and request header to be sent by
+// default
+const base::Feature kUACHPlatformEnabledByDefault{
+ "UACHPlatformEnabledByDefault", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// When enabled, allow dropping alpha on media streams for rendering sinks if
+// other sinks connected do not use alpha.
+const base::Feature kAllowDropAlphaForMediaStream{
+ "AllowDropAlphaForMediaStream", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Enables partitioning of third party storage (IndexedDB, CacheStorage, etc.)
+// by the top level site to reduce fingerprinting.
+const base::Feature kThirdPartyStoragePartitioning{
+ "ThirdPartyStoragePartitioning", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// API that allows installed PWAs to add additional shortcuts by means of
+// installing sub app components.
+const base::Feature kDesktopPWAsSubApps{"DesktopPWAsSubApps",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables reporting all JavaScript frameworks via a manual traversal to detect
+// the properties and attributes required.
+const base::Feature kReportAllJavascriptFrameworks{
+ "ReportAllJavaScriptFrameworks", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Suppresses console errors for CORS problems which report an associated
+// inspector issue anyway.
+const base::Feature kCORSErrorsIssueOnly{"CORSErrorsIssueOnly",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables deprecating warnings (in Issues tab of DevTools) for third party
+// context use of WebSQL (`DOMWindowWebDatabase::openDatabase`).
+const base::Feature kDeprecateThirdPartyContextWebSQL{
+ "DeprecateThirdPartyContextWebSQL", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
} // namespace blink
diff --git a/chromium/third_party/blink/common/frame/frame_policy.cc b/chromium/third_party/blink/common/frame/frame_policy.cc
index c7c691576de..862ddbc66cb 100644
--- a/chromium/third_party/blink/common/frame/frame_policy.cc
+++ b/chromium/third_party/blink/common/frame/frame_policy.cc
@@ -10,21 +10,29 @@ namespace blink {
FramePolicy::FramePolicy()
: sandbox_flags(network::mojom::WebSandboxFlags::kNone),
container_policy({}),
- required_document_policy({}),
- disallow_document_access(false) {}
+ required_document_policy({}) {}
FramePolicy::FramePolicy(
network::mojom::WebSandboxFlags sandbox_flags,
const ParsedPermissionsPolicy& container_policy,
- const DocumentPolicyFeatureState& required_document_policy,
- bool disallow_document_access)
+ const DocumentPolicyFeatureState& required_document_policy)
: sandbox_flags(sandbox_flags),
container_policy(container_policy),
- required_document_policy(required_document_policy),
- disallow_document_access(disallow_document_access) {}
+ required_document_policy(required_document_policy) {}
FramePolicy::FramePolicy(const FramePolicy& lhs) = default;
FramePolicy::~FramePolicy() = default;
+bool operator==(const FramePolicy& lhs, const FramePolicy& rhs) {
+ return (lhs.sandbox_flags == rhs.sandbox_flags) &&
+ (lhs.container_policy == rhs.container_policy) &&
+ (lhs.required_document_policy == rhs.required_document_policy) &&
+ (lhs.is_fenced == rhs.is_fenced);
+}
+
+bool operator!=(const FramePolicy& lhs, const FramePolicy& rhs) {
+ return !(lhs == rhs);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.cc b/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.cc
index 5c4fd3eec44..7d668a3d2f2 100644
--- a/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.cc
+++ b/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.cc
@@ -9,7 +9,7 @@ namespace mojo {
bool StructTraits<blink::mojom::FramePolicyDataView, blink::FramePolicy>::Read(
blink::mojom::FramePolicyDataView in,
blink::FramePolicy* out) {
- out->disallow_document_access = in.disallow_document_access();
+ out->is_fenced = in.is_fenced();
// TODO(chenleihu): Add sanity check on enum values in
// required_document_policy.
diff --git a/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.h b/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.h
index 1f2db5657e0..1519b883be0 100644
--- a/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.h
+++ b/chromium/third_party/blink/common/frame/frame_policy_mojom_traits.h
@@ -16,8 +16,8 @@ template <>
class BLINK_COMMON_EXPORT
StructTraits<blink::mojom::FramePolicyDataView, blink::FramePolicy> {
public:
- static bool disallow_document_access(const blink::FramePolicy& frame_policy) {
- return frame_policy.disallow_document_access;
+ static bool is_fenced(const blink::FramePolicy& frame_policy) {
+ return frame_policy.is_fenced;
}
static const std::vector<blink::ParsedPermissionsPolicyDeclaration>&
diff --git a/chromium/third_party/blink/common/frame/frame_visual_properties_mojom_traits.cc b/chromium/third_party/blink/common/frame/frame_visual_properties_mojom_traits.cc
index c23ddd3efad..834477d2217 100644
--- a/chromium/third_party/blink/common/frame/frame_visual_properties_mojom_traits.cc
+++ b/chromium/third_party/blink/common/frame/frame_visual_properties_mojom_traits.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/public/common/frame/frame_visual_properties_mojom_traits.h"
#include "services/viz/public/mojom/compositing/local_surface_id.mojom.h"
-#include "third_party/blink/public/mojom/widget/screen_info.mojom.h"
+#include "ui/display/mojom/screen_info.mojom.h"
#include "ui/gfx/mojom/display_color_spaces.mojom.h"
namespace mojo {
diff --git a/chromium/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc b/chromium/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc
index ab36fe46f5a..2a8347d4224 100644
--- a/chromium/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc
+++ b/chromium/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/stl_util.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
diff --git a/chromium/third_party/blink/common/input/web_coalesced_input_event_mojom_traits.cc b/chromium/third_party/blink/common/input/web_coalesced_input_event_mojom_traits.cc
index b4fe739b88b..5f0fb5cb55e 100644
--- a/chromium/third_party/blink/common/input/web_coalesced_input_event_mojom_traits.cc
+++ b/chromium/third_party/blink/common/input/web_coalesced_input_event_mojom_traits.cc
@@ -130,6 +130,8 @@ bool StructTraits<blink::mojom::EventDataView,
gesture_event->is_source_touch_event_set_blocking =
gesture_data->is_source_touch_event_set_blocking;
gesture_event->primary_pointer_type = gesture_data->primary_pointer_type;
+ gesture_event->primary_unique_touch_event_id =
+ gesture_data->primary_unique_touch_event_id;
gesture_event->SetSourceDevice(gesture_data->source_device);
gesture_event->unique_touch_event_id = gesture_data->unique_touch_event_id;
@@ -427,6 +429,8 @@ StructTraits<blink::mojom::EventDataView,
gesture_data->is_source_touch_event_set_blocking =
gesture_event->is_source_touch_event_set_blocking;
gesture_data->primary_pointer_type = gesture_event->primary_pointer_type;
+ gesture_data->primary_unique_touch_event_id =
+ gesture_event->primary_unique_touch_event_id;
gesture_data->unique_touch_event_id = gesture_event->unique_touch_event_id;
switch (gesture_event->GetType()) {
default:
diff --git a/chromium/third_party/blink/common/input/web_gesture_event.cc b/chromium/third_party/blink/common/input/web_gesture_event.cc
index f53c0d6213c..933eed5da16 100644
--- a/chromium/third_party/blink/common/input/web_gesture_event.cc
+++ b/chromium/third_party/blink/common/input/web_gesture_event.cc
@@ -96,10 +96,8 @@ void WebGestureEvent::Coalesce(const WebInputEvent& event) {
}
}
-absl::optional<ui::ScrollInputType> WebGestureEvent::GetScrollInputType()
- const {
- if (!IsGestureScroll())
- return absl::nullopt;
+ui::ScrollInputType WebGestureEvent::GetScrollInputType() const {
+ DCHECK(IsGestureScroll());
switch (SourceDevice()) {
case WebGestureDevice::kTouchpad:
return ui::ScrollInputType::kWheel;
@@ -110,8 +108,10 @@ absl::optional<ui::ScrollInputType> WebGestureEvent::GetScrollInputType()
case WebGestureDevice::kScrollbar:
return ui::ScrollInputType::kScrollbar;
case WebGestureDevice::kUninitialized:
- return absl::nullopt;
+ break;
}
+ NOTREACHED();
+ return ui::ScrollInputType::kTouchscreen;
}
float WebGestureEvent::DeltaXInRootFrame() const {
@@ -315,6 +315,8 @@ WebGestureEvent::CoalesceScrollAndPinch(
WebInputEvent::Type::kGestureScrollUpdate, new_event.GetModifiers(),
new_event.TimeStamp(), new_event.SourceDevice());
scroll_event->primary_pointer_type = new_event.primary_pointer_type;
+ scroll_event->primary_unique_touch_event_id =
+ new_event.primary_unique_touch_event_id;
auto pinch_event = std::make_unique<WebGestureEvent>(*scroll_event);
pinch_event->SetType(WebInputEvent::Type::kGesturePinchUpdate);
pinch_event->SetPositionInWidget(
diff --git a/chromium/third_party/blink/common/input/web_input_event.cc b/chromium/third_party/blink/common/input/web_input_event.cc
index e64d8eeffb7..31c8504c372 100644
--- a/chromium/third_party/blink/common/input/web_input_event.cc
+++ b/chromium/third_party/blink/common/input/web_input_event.cc
@@ -12,10 +12,6 @@ constexpr int kButtonModifiers =
WebInputEvent::kForwardButtonDown;
}
-absl::optional<ui::ScrollInputType> WebInputEvent::GetScrollInputType() const {
- return absl::nullopt;
-}
-
WebInputEvent::DispatchType WebInputEvent::MergeDispatchTypes(
DispatchType type_1,
DispatchType type_2) {
diff --git a/chromium/third_party/blink/common/interest_group/DIR_METADATA b/chromium/third_party/blink/common/interest_group/DIR_METADATA
new file mode 100644
index 00000000000..5313345b4ca
--- /dev/null
+++ b/chromium/third_party/blink/common/interest_group/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>InterestGroups"
+}
diff --git a/chromium/third_party/blink/common/interest_group/OWNERS b/chromium/third_party/blink/common/interest_group/OWNERS
new file mode 100644
index 00000000000..563a80e9290
--- /dev/null
+++ b/chromium/third_party/blink/common/interest_group/OWNERS
@@ -0,0 +1,4 @@
+file://third_party/blink/renderer/modules/ad_auction/OWNERS
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/common/interest_group/interest_group.cc b/chromium/third_party/blink/common/interest_group/interest_group.cc
new file mode 100644
index 00000000000..4ec2ab5e95a
--- /dev/null
+++ b/chromium/third_party/blink/common/interest_group/interest_group.cc
@@ -0,0 +1,125 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/interest_group/interest_group.h"
+
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-forward.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+#include "url/url_constants.h"
+
+namespace blink {
+
+namespace {
+
+// Check if `url` can be used as an interest group's ad render URL. Ad URLs can
+// be cross origin, unlike other interest group URLs, but are still restricted
+// to HTTPS with no embedded credentials.
+bool IsUrlAllowedForRenderUrls(const GURL& url) {
+ if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme))
+ return false;
+
+ return !url.has_username() && !url.has_password();
+}
+
+// Check if `url` can be used with the specified interest group for any of
+// script URL, update URL, or realtime data URL. Ad render URLs should be
+// checked with IsUrlAllowedForRenderUrls(), which doesn't have the same-origin
+// check, and allows references.
+bool IsUrlAllowed(const GURL& url, const InterestGroup& group) {
+ if (url::Origin::Create(url) != group.owner)
+ return false;
+
+ return IsUrlAllowedForRenderUrls(url) && !url.has_ref();
+}
+
+} // namespace
+
+InterestGroup::Ad::Ad() = default;
+
+InterestGroup::Ad::Ad(GURL render_url, absl::optional<std::string> metadata)
+ : render_url(std::move(render_url)), metadata(std::move(metadata)) {}
+
+InterestGroup::Ad::~Ad() = default;
+
+bool InterestGroup::Ad::operator==(const Ad& other) const {
+ return render_url == other.render_url && metadata == other.metadata;
+}
+
+InterestGroup::InterestGroup() = default;
+
+InterestGroup::InterestGroup(
+ base::Time expiry,
+ url::Origin owner,
+ std::string name,
+ absl::optional<GURL> bidding_url,
+ absl::optional<GURL> update_url,
+ absl::optional<GURL> trusted_bidding_signals_url,
+ absl::optional<std::vector<std::string>> trusted_bidding_signals_keys,
+ absl::optional<std::string> user_bidding_signals,
+ absl::optional<std::vector<InterestGroup::Ad>> ads)
+ : expiry(expiry),
+ owner(std::move(owner)),
+ name(std::move(name)),
+ bidding_url(std::move(bidding_url)),
+ update_url(std::move(update_url)),
+ trusted_bidding_signals_url(std::move(trusted_bidding_signals_url)),
+ trusted_bidding_signals_keys(std::move(trusted_bidding_signals_keys)),
+ user_bidding_signals(std::move(user_bidding_signals)),
+ ads(std::move(ads)) {}
+
+InterestGroup::~InterestGroup() = default;
+
+// The logic in this method must be kept in sync with ValidateBlinkInterestGroup
+// in blink/renderer/modules/ad_auction/. The tests for this logic are also
+// there, so they can be compared against each other.
+bool InterestGroup::IsValid() const {
+ if (owner.scheme() != url::kHttpsScheme)
+ return false;
+
+ if (bidding_url && !IsUrlAllowed(*bidding_url, *this))
+ return false;
+
+ if (update_url && !IsUrlAllowed(*update_url, *this))
+ return false;
+
+ if (trusted_bidding_signals_url) {
+ if (!IsUrlAllowed(*trusted_bidding_signals_url, *this))
+ return false;
+
+ // `trusted_bidding_signals_url` must not have a query string, since the
+ // query parameter needs to be set as part of running an auction.
+ if (trusted_bidding_signals_url->has_query())
+ return false;
+ }
+
+ if (ads) {
+ for (const auto& ad : ads.value()) {
+ if (!IsUrlAllowedForRenderUrls(ad.render_url))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool InterestGroup::IsEqualForTesting(const InterestGroup& other) const {
+ return std::tie(expiry, owner, name, bidding_url, update_url,
+ trusted_bidding_signals_url, trusted_bidding_signals_keys,
+ user_bidding_signals, ads) ==
+ std::tie(other.expiry, other.owner, other.name, other.bidding_url,
+ other.update_url, other.trusted_bidding_signals_url,
+ other.trusted_bidding_signals_keys,
+ other.user_bidding_signals, other.ads);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/interest_group/interest_group_mojom_traits.cc b/chromium/third_party/blink/common/interest_group/interest_group_mojom_traits.cc
new file mode 100644
index 00000000000..aa1d6d1c539
--- /dev/null
+++ b/chromium/third_party/blink/common/interest_group/interest_group_mojom_traits.cc
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/interest_group/interest_group_mojom_traits.h"
+
+#include "third_party/blink/public/common/interest_group/interest_group.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
+
+namespace mojo {
+
+bool StructTraits<
+ blink::mojom::InterestGroupAdDataView,
+ blink::InterestGroup::Ad>::Read(blink::mojom::InterestGroupAdDataView data,
+ blink::InterestGroup::Ad* out) {
+ if (!data.ReadRenderUrl(&out->render_url) ||
+ !data.ReadMetadata(&out->metadata)) {
+ return false;
+ }
+ return true;
+}
+
+bool StructTraits<blink::mojom::InterestGroupDataView, blink::InterestGroup>::
+ Read(blink::mojom::InterestGroupDataView data, blink::InterestGroup* out) {
+ if (!data.ReadExpiry(&out->expiry) || !data.ReadOwner(&out->owner) ||
+ !data.ReadName(&out->name) || !data.ReadBiddingUrl(&out->bidding_url) ||
+ !data.ReadUpdateUrl(&out->update_url) ||
+ !data.ReadTrustedBiddingSignalsUrl(&out->trusted_bidding_signals_url) ||
+ !data.ReadTrustedBiddingSignalsKeys(&out->trusted_bidding_signals_keys) ||
+ !data.ReadUserBiddingSignals(&out->user_bidding_signals) ||
+ !data.ReadAds(&out->ads)) {
+ return false;
+ }
+ return out->IsValid();
+}
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc b/chromium/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc
new file mode 100644
index 00000000000..9de8d582176
--- /dev/null
+++ b/chromium/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc
@@ -0,0 +1,123 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/interest_group/interest_group_mojom_traits.h"
+
+#include "base/time/time.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/interest_group/interest_group.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace blink {
+
+namespace {
+
+const char kOrigin1[] = "https://origin1.test/";
+const char kOrigin2[] = "https://origin2.test/";
+
+const char kName1[] = "Name 1";
+const char kName2[] = "Name 2";
+
+// Two URLs that share kOrigin1.
+const char kUrl1[] = "https://origin1.test/url1";
+const char kUrl2[] = "https://origin1.test/url2";
+
+// Creates an InterestGroup with an owner and a name,which are mandatory fields.
+InterestGroup CreateInterestGroup() {
+ InterestGroup interest_group;
+ interest_group.owner = url::Origin::Create(GURL(kOrigin1));
+ interest_group.name = kName1;
+ return interest_group;
+}
+
+// SerializesAndDeserializes the provided interest group, expecting
+// deserialization to succeed. Expects the deserialization to succeed, and to be
+// the same as the original group. Also makes sure the input InterestGroup is
+// not equal to the output of CreateInterestGroup(), to verify that
+// IsEqualForTesting() is checking whatever was modified in the input group.
+//
+// Arguments is not const because SerializeAndDeserialize() doesn't take a
+// const input value, as serializing some object types is destructive.
+void SerializeAndDeserializeAndCompare(InterestGroup& interest_group) {
+ ASSERT_FALSE(interest_group.IsEqualForTesting(CreateInterestGroup()));
+
+ InterestGroup interest_group_clone;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<blink::mojom::InterestGroup>(
+ interest_group, interest_group_clone));
+ EXPECT_TRUE(interest_group.IsEqualForTesting(interest_group_clone));
+}
+
+} // namespace
+
+// This file has tests for the deserialization success case. Failure cases are
+// currently tested alongside ValidateBlinkInterestGroup(), since their failure
+// cases should be the same.
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeExpiry) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.expiry = base::Time::Now();
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeOwner) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.owner = url::Origin::Create(GURL(kOrigin2));
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeName) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.name = kName2;
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeBiddingUrl) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.bidding_url = GURL(kUrl1);
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeUpdateUrl) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.update_url = GURL(kUrl1);
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest,
+ SerializeAndDeserializeTrustedBiddingSignalsUrl) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.trusted_bidding_signals_url = GURL(kUrl1);
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest,
+ SerializeAndDeserializeTrustedBiddingSignalsKeys) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.trusted_bidding_signals_keys.emplace();
+ interest_group.trusted_bidding_signals_keys->emplace_back("foo");
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeUserBiddingSignals) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.user_bidding_signals = "[]";
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeAds) {
+ InterestGroup interest_group = CreateInterestGroup();
+ interest_group.ads.emplace();
+ interest_group.ads->emplace_back(
+ InterestGroup::Ad(GURL(kUrl1), /*metadata=*/absl::nullopt));
+ interest_group.ads->emplace_back(
+ InterestGroup::Ad(GURL(kUrl2), /*metadata=*/"[]"));
+ SerializeAndDeserializeAndCompare(interest_group);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc b/chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc
index 2cfb5054fd7..4f55f7cd5b2 100644
--- a/chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc
+++ b/chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_piece.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/mime_sniffer.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/common/loader/mime_sniffing_throttle.h"
diff --git a/chromium/third_party/blink/common/loader/throttling_url_loader.cc b/chromium/third_party/blink/common/loader/throttling_url_loader.cc
index 3234afb3d60..36b320acb66 100644
--- a/chromium/third_party/blink/common/loader/throttling_url_loader.cc
+++ b/chromium/third_party/blink/common/loader/throttling_url_loader.cc
@@ -19,6 +19,7 @@
#include "net/url_request/redirect_util.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace blink {
@@ -105,6 +106,9 @@ class ThrottlingURLLoader::ForwardingThrottleDelegate
ForwardingThrottleDelegate(ThrottlingURLLoader* loader,
URLLoaderThrottle* throttle)
: loader_(loader), throttle_(throttle) {}
+ ForwardingThrottleDelegate(const ForwardingThrottleDelegate&) = delete;
+ ForwardingThrottleDelegate& operator=(const ForwardingThrottleDelegate&) =
+ delete;
~ForwardingThrottleDelegate() override = default;
// URLLoaderThrottle::Delegate:
@@ -234,6 +238,9 @@ class ThrottlingURLLoader::ForwardingThrottleDelegate
owner_->loader_->inside_delegate_calls_++;
}
+ ScopedDelegateCall(const ScopedDelegateCall&) = delete;
+ ScopedDelegateCall& operator=(const ScopedDelegateCall&) = delete;
+
~ScopedDelegateCall() {
// The loader may have been detached and destroyed.
if (owner_->loader_)
@@ -242,13 +249,10 @@ class ThrottlingURLLoader::ForwardingThrottleDelegate
private:
ForwardingThrottleDelegate* const owner_;
- DISALLOW_COPY_AND_ASSIGN(ScopedDelegateCall);
};
ThrottlingURLLoader* loader_;
URLLoaderThrottle* const throttle_;
-
- DISALLOW_COPY_AND_ASSIGN(ForwardingThrottleDelegate);
};
ThrottlingURLLoader::StartInfo::StartInfo(
@@ -326,13 +330,7 @@ void ThrottlingURLLoader::FollowRedirectForcingRestart() {
client_receiver_.reset();
CHECK(throttle_will_redirect_redirect_url_.is_empty());
- for (const std::string& header : removed_headers_) {
- start_info_->url_request.headers.RemoveHeader(header);
- start_info_->url_request.cors_exempt_headers.RemoveHeader(header);
- }
- start_info_->url_request.headers.MergeFrom(modified_headers_);
- start_info_->url_request.cors_exempt_headers.MergeFrom(
- modified_cors_exempt_headers_);
+ UpdateRequestHeaders();
removed_headers_.clear();
modified_headers_.Clear();
@@ -370,6 +368,7 @@ void ThrottlingURLLoader::FollowRedirect(
if (!throttle_will_start_redirect_url_.is_empty()) {
throttle_will_start_redirect_url_ = GURL();
// This is a synthesized redirect, so no need to tell the URLLoader.
+ UpdateRequestHeaders();
StartNow();
return;
}
@@ -1013,6 +1012,16 @@ void ThrottlingURLLoader::UpdateDeferredRequestHeaders(
}
}
+void ThrottlingURLLoader::UpdateRequestHeaders() {
+ for (const std::string& header : removed_headers_) {
+ start_info_->url_request.headers.RemoveHeader(header);
+ start_info_->url_request.cors_exempt_headers.RemoveHeader(header);
+ }
+ start_info_->url_request.headers.MergeFrom(modified_headers_);
+ start_info_->url_request.cors_exempt_headers.MergeFrom(
+ modified_cors_exempt_headers_);
+}
+
void ThrottlingURLLoader::UpdateDeferredResponseHead(
network::mojom::URLResponseHeadPtr new_response_head) {
DCHECK(response_info_);
diff --git a/chromium/third_party/blink/common/loader/throttling_url_loader_unittest.cc b/chromium/third_party/blink/common/loader/throttling_url_loader_unittest.cc
index 9eb310d483c..6e327b053ef 100644
--- a/chromium/third_party/blink/common/loader/throttling_url_loader_unittest.cc
+++ b/chromium/third_party/blink/common/loader/throttling_url_loader_unittest.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/public/common/loader/throttling_url_loader.h"
#include "base/bind.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "base/run_loop.h"
@@ -14,8 +13,10 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
@@ -35,6 +36,8 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
factory_remote_.get());
}
+ TestURLLoaderFactory(const TestURLLoaderFactory&) = delete;
+ TestURLLoaderFactory& operator=(const TestURLLoaderFactory&) = delete;
~TestURLLoaderFactory() override { shared_factory_->Detach(); }
@@ -160,12 +163,13 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
mojo::Remote<network::mojom::URLLoaderClient> client_remote_;
scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> shared_factory_;
OnCreateLoaderAndStartCallback on_create_loader_and_start_callback_;
- DISALLOW_COPY_AND_ASSIGN(TestURLLoaderFactory);
};
class TestURLLoaderClient : public network::mojom::URLLoaderClient {
public:
- TestURLLoaderClient() {}
+ TestURLLoaderClient() = default;
+ TestURLLoaderClient(const TestURLLoaderClient&) = delete;
+ TestURLLoaderClient& operator=(const TestURLLoaderClient&) = delete;
size_t on_received_response_called() const {
return on_received_response_called_;
@@ -229,16 +233,17 @@ class TestURLLoaderClient : public network::mojom::URLLoaderClient {
base::RepeatingClosure on_received_redirect_callback_;
base::OnceClosure on_received_response_callback_;
OnCompleteCallback on_complete_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(TestURLLoaderClient);
};
class TestURLLoaderThrottle : public blink::URLLoaderThrottle {
public:
- TestURLLoaderThrottle() {}
+ TestURLLoaderThrottle() = default;
explicit TestURLLoaderThrottle(base::OnceClosure destruction_notifier)
: destruction_notifier_(std::move(destruction_notifier)) {}
+ TestURLLoaderThrottle(const TestURLLoaderThrottle&) = delete;
+ TestURLLoaderThrottle& operator=(const TestURLLoaderThrottle&) = delete;
+
~TestURLLoaderThrottle() override {
if (destruction_notifier_)
std::move(destruction_notifier_).Run();
@@ -352,13 +357,13 @@ class TestURLLoaderThrottle : public blink::URLLoaderThrottle {
GURL modify_url_in_will_start_;
base::OnceClosure destruction_notifier_;
-
- DISALLOW_COPY_AND_ASSIGN(TestURLLoaderThrottle);
};
class ThrottlingURLLoaderTest : public testing::Test {
public:
- ThrottlingURLLoaderTest() {}
+ ThrottlingURLLoaderTest() = default;
+ ThrottlingURLLoaderTest(const ThrottlingURLLoaderTest&) = delete;
+ ThrottlingURLLoaderTest& operator=(const ThrottlingURLLoaderTest&) = delete;
std::unique_ptr<ThrottlingURLLoader>& loader() { return loader_; }
TestURLLoaderThrottle* throttle() const { return throttle_; }
@@ -403,8 +408,6 @@ class ThrottlingURLLoaderTest : public testing::Test {
TestURLLoaderThrottle* throttle_ = nullptr;
base::WeakPtrFactory<ThrottlingURLLoaderTest> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ThrottlingURLLoaderTest);
};
TEST_F(ThrottlingURLLoaderTest, CancelBeforeStart) {
diff --git a/chromium/third_party/blink/common/manifest/DIR_METADATA b/chromium/third_party/blink/common/manifest/DIR_METADATA
new file mode 100644
index 00000000000..0ff3ed55bf6
--- /dev/null
+++ b/chromium/third_party/blink/common/manifest/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>AppManifest"
+}
diff --git a/chromium/third_party/blink/common/manifest/OWNERS b/chromium/third_party/blink/common/manifest/OWNERS
index aa75e1416ee..20d2acc7931 100644
--- a/chromium/third_party/blink/common/manifest/OWNERS
+++ b/chromium/third_party/blink/common/manifest/OWNERS
@@ -2,5 +2,3 @@ file://third_party/blink/renderer/modules/manifest/OWNERS
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-
-# Component: Blink>AppManifest
diff --git a/chromium/third_party/blink/common/manifest/manifest.cc b/chromium/third_party/blink/common/manifest/manifest.cc
index 9f56bfbdaff..fbf0de75ef9 100644
--- a/chromium/third_party/blink/common/manifest/manifest.cc
+++ b/chromium/third_party/blink/common/manifest/manifest.cc
@@ -14,41 +14,75 @@ Manifest::ImageResource::~ImageResource() = default;
bool Manifest::ImageResource::operator==(
const Manifest::ImageResource& other) const {
- return src == other.src && type == other.type && sizes == other.sizes;
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.src, item.type, item.sizes);
+ };
+ return AsTuple(*this) == AsTuple(other);
}
Manifest::ShortcutItem::ShortcutItem() = default;
Manifest::ShortcutItem::~ShortcutItem() = default;
+bool Manifest::ShortcutItem::operator==(const ShortcutItem& other) const {
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.name, item.short_name, item.description, item.url,
+ item.icons);
+ };
+ return AsTuple(*this) == AsTuple(other);
+}
+
+bool Manifest::FileFilter::operator==(const FileFilter& other) const {
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.name, item.accept);
+ };
+ return AsTuple(*this) == AsTuple(other);
+}
+
Manifest::ShareTargetParams::ShareTargetParams() = default;
Manifest::ShareTargetParams::~ShareTargetParams() = default;
+bool Manifest::ShareTargetParams::operator==(
+ const ShareTargetParams& other) const {
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.title, item.text, item.url, item.files);
+ };
+ return AsTuple(*this) == AsTuple(other);
+}
+
Manifest::ShareTarget::ShareTarget() = default;
Manifest::ShareTarget::~ShareTarget() = default;
+bool Manifest::ShareTarget::operator==(const ShareTarget& other) const {
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.action, item.method, item.enctype, item.params);
+ };
+ return AsTuple(*this) == AsTuple(other);
+}
+
Manifest::RelatedApplication::RelatedApplication() = default;
Manifest::RelatedApplication::~RelatedApplication() = default;
-Manifest::Manifest() = default;
-
-Manifest::Manifest(const Manifest& other) = default;
+bool Manifest::RelatedApplication::operator==(
+ const RelatedApplication& other) const {
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.platform, item.url, item.id);
+ };
+ return AsTuple(*this) == AsTuple(other);
+}
-Manifest::~Manifest() = default;
+bool Manifest::LaunchHandler::operator==(const LaunchHandler& other) const {
+ auto AsTuple = [](const auto& item) {
+ return std::tie(item.route_to, item.navigate_existing_client);
+ };
+ return AsTuple(*this) == AsTuple(other);
+}
-bool Manifest::IsEmpty() const {
- return !name && !short_name && start_url.is_empty() &&
- display == blink::mojom::DisplayMode::kUndefined &&
- display_override.empty() &&
- orientation == device::mojom::ScreenOrientationLockType::DEFAULT &&
- icons.empty() && shortcuts.empty() && !share_target.has_value() &&
- related_applications.empty() && file_handlers.empty() &&
- !prefer_related_applications && !theme_color && !background_color &&
- !gcm_sender_id && scope.is_empty() && protocol_handlers.empty() &&
- url_handlers.empty() && !note_taking.has_value();
+bool Manifest::LaunchHandler::operator!=(const LaunchHandler& other) const {
+ return !(*this == other);
}
} // namespace blink
diff --git a/chromium/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc b/chromium/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc
index 6302d3a98db..41e854f1251 100644
--- a/chromium/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc
@@ -7,7 +7,6 @@
#include <string>
#include <vector>
-#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc b/chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc
index 2399ea0c25f..cadf88bcd85 100644
--- a/chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
#include "url/mojom/url_gurl_mojom_traits.h"
@@ -22,31 +23,6 @@ struct TruncatedString16 {
absl::optional<std::u16string> string;
};
-// This function should be kept in sync with IsHostValidForUrlHandler in
-// manifest_parser.cc.
-bool IsHostValidForUrlHandler(const std::string& host) {
- if (url::HostIsIPAddress(host))
- return true;
-
- const size_t registry_length =
- net::registry_controlled_domains::PermissiveGetHostRegistryLength(
- host,
- // Reject unknown registries (registries that don't have any matches
- // in effective TLD names).
- net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
- // Skip matching private registries that allow external users to
- // specify sub-domains, e.g. glitch.me, as this is allowed.
- net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
-
- // Host cannot be a TLD or invalid.
- if (registry_length == 0 || registry_length == std::string::npos ||
- registry_length >= host.length()) {
- return false;
- }
-
- return true;
-}
-
} // namespace
template <>
@@ -70,82 +46,6 @@ struct StructTraits<mojo_base::mojom::String16DataView, TruncatedString16> {
}
};
-bool StructTraits<blink::mojom::ManifestDataView, ::blink::Manifest>::Read(
- blink::mojom::ManifestDataView data,
- ::blink::Manifest* out) {
- TruncatedString16 string;
- if (!data.ReadName(&string))
- return false;
- out->name = std::move(string.string);
-
- if (!data.ReadShortName(&string))
- return false;
- out->short_name = std::move(string.string);
-
- if (!data.ReadDescription(&string))
- return false;
- out->description = std::move(string.string);
-
- if (!data.ReadGcmSenderId(&string))
- return false;
- out->gcm_sender_id = std::move(string.string);
-
- if (!data.ReadStartUrl(&out->start_url))
- return false;
-
- if (!data.ReadIcons(&out->icons))
- return false;
-
- if (!data.ReadScreenshots(&out->screenshots))
- return false;
-
- if (!data.ReadShortcuts(&out->shortcuts))
- return false;
-
- if (!data.ReadShareTarget(&out->share_target))
- return false;
-
- if (!data.ReadFileHandlers(&out->file_handlers))
- return false;
-
- if (!data.ReadProtocolHandlers(&out->protocol_handlers))
- return false;
-
- if (!data.ReadUrlHandlers(&out->url_handlers))
- return false;
-
- if (!data.ReadNoteTaking(&out->note_taking))
- return false;
-
- if (!data.ReadRelatedApplications(&out->related_applications))
- return false;
-
- out->prefer_related_applications = data.prefer_related_applications();
-
- if (data.has_theme_color())
- out->theme_color = data.theme_color();
-
- if (data.has_background_color())
- out->background_color = data.background_color();
-
- if (!data.ReadDisplay(&out->display))
- return false;
-
- if (!data.ReadDisplayOverride(&out->display_override))
- return false;
-
- if (!data.ReadOrientation(&out->orientation))
- return false;
-
- if (!data.ReadScope(&out->scope))
- return false;
-
- if (!data.ReadCaptureLinks(&out->capture_links))
- return false;
-
- return true;
-}
-
bool StructTraits<blink::mojom::ManifestImageResourceDataView,
::blink::Manifest::ImageResource>::
Read(blink::mojom::ManifestImageResourceDataView data,
@@ -236,22 +136,6 @@ bool StructTraits<blink::mojom::ManifestFileFilterDataView,
return true;
}
-bool StructTraits<blink::mojom::ManifestUrlHandlerDataView,
- ::blink::Manifest::UrlHandler>::
- Read(blink::mojom::ManifestUrlHandlerDataView data,
- ::blink::Manifest::UrlHandler* out) {
- if (!data.ReadOrigin(&out->origin))
- return false;
-
- // Make sure the origin is valid.
- if (!IsHostValidForUrlHandler(out->origin.host()))
- return false;
-
- out->has_origin_wildcard = data.has_origin_wildcard();
-
- return true;
-}
-
bool StructTraits<blink::mojom::ManifestShareTargetParamsDataView,
::blink::Manifest::ShareTargetParams>::
Read(blink::mojom::ManifestShareTargetParamsDataView data,
@@ -291,40 +175,14 @@ bool StructTraits<blink::mojom::ManifestShareTargetDataView,
return data.ReadParams(&out->params);
}
-bool StructTraits<blink::mojom::ManifestFileHandlerDataView,
- ::blink::Manifest::FileHandler>::
- Read(blink::mojom::ManifestFileHandlerDataView data,
- ::blink::Manifest::FileHandler* out) {
- if (!data.ReadAction(&out->action))
- return false;
-
- if (!data.ReadName(&out->name))
- return false;
-
- if (!data.ReadAccept(&out->accept))
- return false;
-
- return true;
-}
-
-bool StructTraits<blink::mojom::ManifestProtocolHandlerDataView,
- ::blink::Manifest::ProtocolHandler>::
- Read(blink::mojom::ManifestProtocolHandlerDataView data,
- ::blink::Manifest::ProtocolHandler* out) {
- if (!data.ReadProtocol(&out->protocol))
- return false;
-
- if (!data.ReadUrl(&out->url))
+bool StructTraits<blink::mojom::ManifestLaunchHandlerDataView,
+ ::blink::Manifest::LaunchHandler>::
+ Read(blink::mojom::ManifestLaunchHandlerDataView data,
+ ::blink::Manifest::LaunchHandler* out) {
+ if (!data.ReadRouteTo(&out->route_to))
return false;
- return true;
-}
-
-bool StructTraits<blink::mojom::ManifestNoteTakingDataView,
- ::blink::Manifest::NoteTaking>::
- Read(blink::mojom::ManifestNoteTakingDataView data,
- ::blink::Manifest::NoteTaking* out) {
- if (!data.ReadNewNoteUrl(&out->new_note_url))
+ if (!data.ReadNavigateExistingClient(&out->navigate_existing_client))
return false;
return true;
diff --git a/chromium/third_party/blink/common/manifest/manifest_util.cc b/chromium/third_party/blink/common/manifest/manifest_util.cc
index 387e18b462c..c65ccd9c396 100644
--- a/chromium/third_party/blink/common/manifest/manifest_util.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_util.cc
@@ -4,12 +4,27 @@
#include "third_party/blink/public/common/manifest/manifest_util.h"
+#include "base/no_destructor.h"
#include "base/strings/string_util.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/capture_links.mojom.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
namespace blink {
+bool IsEmptyManifest(const mojom::Manifest& manifest) {
+ static base::NoDestructor<mojom::ManifestPtr> empty_manifest_ptr_storage;
+ mojom::ManifestPtr& empty_manifest = *empty_manifest_ptr_storage;
+ if (!empty_manifest)
+ empty_manifest = mojom::Manifest::New();
+ return manifest == *empty_manifest;
+}
+
+bool IsEmptyManifest(const mojom::ManifestPtr& manifest) {
+ return !manifest || IsEmptyManifest(*manifest);
+}
+
std::string DisplayModeToString(blink::mojom::DisplayMode display) {
switch (display) {
case blink::mojom::DisplayMode::kUndefined:
@@ -24,6 +39,8 @@ std::string DisplayModeToString(blink::mojom::DisplayMode display) {
return "fullscreen";
case blink::mojom::DisplayMode::kWindowControlsOverlay:
return "window-controls-overlay";
+ case blink::mojom::DisplayMode::kTabbed:
+ return "tabbed";
}
return "";
}
@@ -39,6 +56,8 @@ blink::mojom::DisplayMode DisplayModeFromString(const std::string& display) {
return blink::mojom::DisplayMode::kFullscreen;
if (base::LowerCaseEqualsASCII(display, "window-controls-overlay"))
return blink::mojom::DisplayMode::kWindowControlsOverlay;
+ if (base::LowerCaseEqualsASCII(display, "tabbed"))
+ return blink::mojom::DisplayMode::kTabbed;
return blink::mojom::DisplayMode::kUndefined;
}
@@ -109,4 +128,24 @@ mojom::CaptureLinks CaptureLinksFromString(const std::string& capture_links) {
return mojom::CaptureLinks::kUndefined;
}
+absl::optional<Manifest::LaunchHandler::RouteTo> RouteToFromString(
+ const std::string& route_to) {
+ if (base::LowerCaseEqualsASCII(route_to, "auto"))
+ return Manifest::LaunchHandler::RouteTo::kAuto;
+ if (base::LowerCaseEqualsASCII(route_to, "new-client"))
+ return Manifest::LaunchHandler::RouteTo::kNewClient;
+ if (base::LowerCaseEqualsASCII(route_to, "existing-client"))
+ return Manifest::LaunchHandler::RouteTo::kExistingClient;
+ return absl::nullopt;
+}
+
+absl::optional<Manifest::LaunchHandler::NavigateExistingClient>
+NavigateExistingClientFromString(const std::string& navigate_existing_client) {
+ if (base::LowerCaseEqualsASCII(navigate_existing_client, "always"))
+ return Manifest::LaunchHandler::NavigateExistingClient::kAlways;
+ if (base::LowerCaseEqualsASCII(navigate_existing_client, "never"))
+ return Manifest::LaunchHandler::NavigateExistingClient::kNever;
+ return absl::nullopt;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/common/manifest/manifest_util_unittest.cc b/chromium/third_party/blink/common/manifest/manifest_util_unittest.cc
index 95e66c72259..0ad90a23849 100644
--- a/chromium/third_party/blink/common/manifest/manifest_util_unittest.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_util_unittest.cc
@@ -22,6 +22,7 @@ TEST(ManifestUtilTest, DisplayModeConversions) {
{blink::mojom::DisplayMode::kFullscreen, "fullscreen"},
{blink::mojom::DisplayMode::kWindowControlsOverlay,
"window-controls-overlay"},
+ {blink::mojom::DisplayMode::kTabbed, "tabbed"},
};
for (const ReversibleConversion& conversion : reversible_conversions) {
@@ -98,4 +99,35 @@ TEST(ManifestUtilTest, CaptureLinksFromString) {
CaptureLinksFromString("unknown-value"));
}
+TEST(ManifestUtilTest, RouteToFromString) {
+ using RouteTo = Manifest::LaunchHandler::RouteTo;
+ EXPECT_EQ(absl::nullopt, RouteToFromString(""));
+ EXPECT_EQ(RouteTo::kAuto, RouteToFromString("auto"));
+ EXPECT_EQ(RouteTo::kNewClient, RouteToFromString("new-client"));
+ EXPECT_EQ(RouteTo::kExistingClient, RouteToFromString("existing-client"));
+
+ // Uppercase spelling.
+ EXPECT_EQ(RouteTo::kNewClient, RouteToFromString("NEW-CLIENT"));
+
+ // Unknown value.
+ EXPECT_EQ(absl::nullopt, RouteToFromString("unknown-value"));
+}
+
+TEST(ManifestUtilTest, NavigateExistingClientFromString) {
+ using NavigateExistingClient =
+ Manifest::LaunchHandler::NavigateExistingClient;
+ EXPECT_EQ(absl::nullopt, NavigateExistingClientFromString(""));
+ EXPECT_EQ(NavigateExistingClient::kAlways,
+ NavigateExistingClientFromString("always"));
+ EXPECT_EQ(NavigateExistingClient::kNever,
+ NavigateExistingClientFromString("never"));
+
+ // Uppercase spelling.
+ EXPECT_EQ(NavigateExistingClient::kNever,
+ NavigateExistingClientFromString("NEVER"));
+
+ // Unknown value.
+ EXPECT_EQ(absl::nullopt, NavigateExistingClientFromString("unknown-value"));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/common/media/watch_time_component_unittest.cc b/chromium/third_party/blink/common/media/watch_time_component_unittest.cc
index fa8e1d27c2b..2f79ba9c330 100644
--- a/chromium/third_party/blink/common/media/watch_time_component_unittest.cc
+++ b/chromium/third_party/blink/common/media/watch_time_component_unittest.cc
@@ -35,6 +35,8 @@ class WatchTimeInterceptor : public media::mojom::WatchTimeRecorder {
class WatchTimeComponentTest : public testing::Test {
public:
WatchTimeComponentTest() = default;
+ WatchTimeComponentTest(const WatchTimeComponentTest&) = delete;
+ WatchTimeComponentTest& operator=(const WatchTimeComponentTest&) = delete;
~WatchTimeComponentTest() override = default;
protected:
@@ -55,9 +57,6 @@ class WatchTimeComponentTest : public testing::Test {
// Usage of StrictMock is intentional here. This ensures all mock method calls
// are accounted for in tests.
testing::StrictMock<WatchTimeInterceptor> recorder_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WatchTimeComponentTest);
};
// Components should be key agnostic so just choose an arbitrary key for running
diff --git a/chromium/third_party/blink/common/media/watch_time_reporter.cc b/chromium/third_party/blink/common/media/watch_time_reporter.cc
index b693479d42c..443a53e830a 100644
--- a/chromium/third_party/blink/common/media/watch_time_reporter.cc
+++ b/chromium/third_party/blink/common/media/watch_time_reporter.cc
@@ -7,6 +7,7 @@
#include <numeric>
#include "base/bind.h"
+#include "base/containers/cxx20_erase.h"
#include "base/power_monitor/power_monitor.h"
#include "base/time/time.h"
#include "media/base/pipeline_status.h"
diff --git a/chromium/third_party/blink/common/mediastream/OWNERS b/chromium/third_party/blink/common/mediastream/OWNERS
index 7653ee493bb..b3bb856f7f8 100644
--- a/chromium/third_party/blink/common/mediastream/OWNERS
+++ b/chromium/third_party/blink/common/mediastream/OWNERS
@@ -1,5 +1,4 @@
guidou@chromium.org
-hbos@chromium.org
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/common/messaging/web_message_port.cc b/chromium/third_party/blink/common/messaging/web_message_port.cc
index 98e6c3f7ddb..88adf1bf32a 100644
--- a/chromium/third_party/blink/common/messaging/web_message_port.cc
+++ b/chromium/third_party/blink/common/messaging/web_message_port.cc
@@ -69,6 +69,14 @@ std::pair<WebMessagePort, WebMessagePort> WebMessagePort::CreatePair() {
WebMessagePort(port_pair.TakePort1()));
}
+// static
+WebMessagePort WebMessagePort::Create(MessagePortDescriptor port) {
+ DCHECK(port.IsValid());
+ DCHECK(!port.IsEntangled());
+
+ return WebMessagePort(std::move(port));
+}
+
void WebMessagePort::SetReceiver(
MessageReceiver* receiver,
scoped_refptr<base::SequencedTaskRunner> runner) {
diff --git a/chromium/third_party/blink/common/mime_util/mime_util.cc b/chromium/third_party/blink/common/mime_util/mime_util.cc
index 35d4034ce24..842e7392f34 100644
--- a/chromium/third_party/blink/common/mime_util/mime_util.cc
+++ b/chromium/third_party/blink/common/mime_util/mime_util.cc
@@ -114,6 +114,9 @@ static const char* const kSupportedNonImageTypes[] = {
// Singleton utility class for mime types
class MimeUtil {
public:
+ MimeUtil(const MimeUtil&) = delete;
+ MimeUtil& operator=(const MimeUtil&) = delete;
+
bool IsSupportedImageMimeType(const std::string& mime_type) const;
bool IsSupportedNonImageMimeType(const std::string& mime_type) const;
bool IsUnsupportedTextMimeType(const std::string& mime_type) const;
@@ -133,8 +136,6 @@ class MimeUtil {
MimeTypes non_image_types_;
MimeTypes unsupported_text_types_;
MimeTypes javascript_types_;
-
- DISALLOW_COPY_AND_ASSIGN(MimeUtil);
};
MimeUtil::MimeUtil() {
diff --git a/chromium/third_party/blink/common/navigation/navigation_params.cc b/chromium/third_party/blink/common/navigation/navigation_params.cc
new file mode 100644
index 00000000000..2ef8781299f
--- /dev/null
+++ b/chromium/third_party/blink/common/navigation/navigation_params.cc
@@ -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.
+
+#include "third_party/blink/public/common/navigation/navigation_params.h"
+
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
+
+namespace blink {
+
+mojom::CommonNavigationParamsPtr CreateCommonNavigationParams() {
+ auto common_params = mojom::CommonNavigationParams::New();
+ common_params->referrer = mojom::Referrer::New();
+ common_params->navigation_start = base::TimeTicks::Now();
+ common_params->source_location = network::mojom::SourceLocation::New();
+
+ return common_params;
+}
+
+mojom::CommitNavigationParamsPtr CreateCommitNavigationParams() {
+ auto commit_params = mojom::CommitNavigationParams::New();
+ commit_params->navigation_token = base::UnguessableToken::Create();
+ commit_params->navigation_timing = mojom::NavigationTiming::New();
+
+ return commit_params;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/navigation/prefetched_signed_exchange_info_mojom_traits.cc b/chromium/third_party/blink/common/navigation/prefetched_signed_exchange_info_mojom_traits.cc
new file mode 100644
index 00000000000..52d96bc8975
--- /dev/null
+++ b/chromium/third_party/blink/common/navigation/prefetched_signed_exchange_info_mojom_traits.cc
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/navigation/prefetched_signed_exchange_info_mojom_traits.h"
+
+#include "base/notreached.h"
+
+namespace mojo {
+
+bool StructTraits<blink::mojom::SHA256HashValueDataView, net::SHA256HashValue>::
+ Read(blink::mojom::SHA256HashValueDataView input,
+ net::SHA256HashValue* out) {
+ std::string data;
+ if (!input.ReadData(&data))
+ return false;
+
+ if (data.size() != sizeof(out->data)) {
+ NOTREACHED();
+ return false;
+ }
+
+ memcpy(out->data, data.c_str(), sizeof(out->data));
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/common/net/ip_address_space_util.cc b/chromium/third_party/blink/common/net/ip_address_space_util.cc
deleted file mode 100644
index 156b8453688..00000000000
--- a/chromium/third_party/blink/common/net/ip_address_space_util.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/net/ip_address_space_util.h"
-
-#include "base/logging.h"
-#include "net/base/ip_endpoint.h"
-#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/cpp/ip_address_space_util.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
-#include "url/gurl.h"
-
-namespace blink {
-namespace {
-
-using network::mojom::IPAddressSpace;
-using network::mojom::URLResponseHead;
-
-// Helper for CalculateClientAddressSpace() with the same arguments.
-//
-// If the response was fetched via service workers, returns the last URL in the
-// list. Otherwise returns |request_url|.
-//
-// See: https://fetch.spec.whatwg.org/#concept-response-url-list
-const GURL& ResponseUrl(const GURL& request_url,
- const URLResponseHead* response_head) {
- if (response_head && !response_head->url_list_via_service_worker.empty()) {
- return response_head->url_list_via_service_worker.back();
- }
-
- return request_url;
-}
-
-} // namespace
-
-IPAddressSpace CalculateClientAddressSpace(
- const GURL& url,
- const URLResponseHead* response_head) {
- if (ResponseUrl(url, response_head).SchemeIsFile()) {
- // See: https://wicg.github.io/cors-rfc1918/#file-url.
- return IPAddressSpace::kLocal;
- }
-
- if (!response_head) {
- return IPAddressSpace::kUnknown;
- }
-
- // First, check whether the response forces itself into a public address space
- // as per https://wicg.github.io/cors-rfc1918/#csp.
- DCHECK(response_head->parsed_headers)
- << "CalculateIPAddressSpace() called for URL " << url
- << " with null parsed_headers.";
- if (response_head->parsed_headers &&
- network::ShouldTreatAsPublicAddress(
- response_head->parsed_headers->content_security_policy)) {
- return IPAddressSpace::kPublic;
- }
-
- // Otherwise, calculate the address space via the provided IP address.
- return network::IPEndPointToIPAddressSpace(response_head->remote_endpoint);
-}
-
-IPAddressSpace CalculateResourceAddressSpace(const GURL& url,
- const net::IPEndPoint& endpoint) {
- if (url.SchemeIsFile()) {
- // See: https://wicg.github.io/cors-rfc1918/#file-url.
- return IPAddressSpace::kLocal;
- }
-
- return network::IPEndPointToIPAddressSpace(endpoint);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/common/net/ip_address_space_util_unittest.cc b/chromium/third_party/blink/common/net/ip_address_space_util_unittest.cc
deleted file mode 100644
index 30120d495f1..00000000000
--- a/chromium/third_party/blink/common/net/ip_address_space_util_unittest.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/net/ip_address_space_util.h"
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "services/network/public/cpp/network_switches.h"
-#include "services/network/public/mojom/content_security_policy.mojom.h"
-#include "services/network/public/mojom/parsed_headers.mojom.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace blink {
-namespace {
-
-using net::IPAddress;
-using net::IPEndPoint;
-using network::mojom::ContentSecurityPolicy;
-using network::mojom::IPAddressSpace;
-using network::mojom::ParsedHeaders;
-using network::mojom::URLResponseHead;
-
-IPAddress PublicIPv4Address() {
- return IPAddress(64, 233, 160, 0);
-}
-
-IPAddress PrivateIPv4Address() {
- return IPAddress(192, 168, 1, 1);
-}
-
-TEST(IPAddressSpaceUtilTest, CalculateClientAddressSpaceFileURL) {
- EXPECT_EQ(IPAddressSpace::kLocal,
- CalculateClientAddressSpace(GURL("file:///foo"), nullptr));
-}
-
-TEST(IPAddressSpaceUtilTest,
- CalculateClientAddressSpaceFetchedViaServiceWorkerFromFile) {
- URLResponseHead response_head;
- response_head.url_list_via_service_worker.emplace_back("http://bar.test");
- response_head.url_list_via_service_worker.emplace_back("file:///foo");
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kLocal,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceUtilTest,
- CalculateClientAddressSpaceFetchedViaServiceWorkerFromHttp) {
- URLResponseHead response_head;
- response_head.url_list_via_service_worker.emplace_back("file:///foo");
- response_head.url_list_via_service_worker.emplace_back("http://bar.test");
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceUtilTest,
- CalculateClientAddressSpaceFetchedViaServiceWorkerFromHttpInsteadOfFile) {
- URLResponseHead response_head;
- response_head.url_list_via_service_worker.emplace_back("http://bar.test");
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("file:///foo"), &response_head));
-}
-
-TEST(IPAddressSpaceUtilTest, CalculateClientAddressSpaceNullResponseHead) {
- EXPECT_EQ(IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("http://foo.test"), nullptr));
-}
-
-TEST(IPAddressSpaceUtilTest, CalculateClientAddressSpaceEmptyResponseHead) {
- URLResponseHead response_head;
- response_head.parsed_headers = ParsedHeaders::New();
- EXPECT_EQ(
- IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceUtilTest, CalculateClientAddressSpaceIPAddress) {
- URLResponseHead response_head;
- response_head.remote_endpoint = IPEndPoint(PrivateIPv4Address(), 1234);
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kPrivate,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceUtilTest, CalculateClientAddressSpaceTreatAsPublicAddress) {
- URLResponseHead response_head;
- response_head.remote_endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 1234);
-
- auto csp = ContentSecurityPolicy::New();
- csp->treat_as_public_address = true;
- response_head.parsed_headers = ParsedHeaders::New();
- response_head.parsed_headers->content_security_policy.push_back(
- std::move(csp));
-
- EXPECT_EQ(
- IPAddressSpace::kPublic,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceTest, CalculateClientAddressSpaceOverride) {
- auto& command_line = *base::CommandLine::ForCurrentProcess();
- command_line.AppendSwitchASCII(network::switches::kIpAddressSpaceOverrides,
- "10.2.3.4:80=public,8.8.8.8:8888=private");
-
- URLResponseHead response_head;
- response_head.remote_endpoint = IPEndPoint(IPAddress(10, 2, 3, 4), 80);
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kPublic,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-
- response_head.remote_endpoint = IPEndPoint(IPAddress(8, 8, 8, 8), 8888);
-
- EXPECT_EQ(
- IPAddressSpace::kPrivate,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceTest, CalculateResourceAddressSpaceFileURL) {
- EXPECT_EQ(IPAddressSpace::kLocal,
- CalculateResourceAddressSpace(GURL("file:///foo"), IPEndPoint()));
-}
-
-TEST(IPAddressSpaceTest, CalculateResourceAddressSpaceIPAddress) {
- EXPECT_EQ(
- IPAddressSpace::kLocal,
- CalculateResourceAddressSpace(
- GURL("http://foo.test"), IPEndPoint(IPAddress::IPv4Localhost(), 80)));
- EXPECT_EQ(IPAddressSpace::kPrivate,
- CalculateResourceAddressSpace(
- GURL("http://foo.test"), IPEndPoint(PrivateIPv4Address(), 80)));
- EXPECT_EQ(IPAddressSpace::kPublic,
- CalculateResourceAddressSpace(GURL("http://foo.test"),
- IPEndPoint(PublicIPv4Address(), 80)));
- EXPECT_EQ(
- IPAddressSpace::kUnknown,
- CalculateResourceAddressSpace(GURL("http://foo.test"), IPEndPoint()));
-}
-
-TEST(IPAddressSpaceTest, CalculateResourceAddressSpaceOverride) {
- auto& command_line = *base::CommandLine::ForCurrentProcess();
- command_line.AppendSwitchASCII(network::switches::kIpAddressSpaceOverrides,
- "10.2.3.4:80=public,8.8.8.8:8888=private");
-
- EXPECT_EQ(
- IPAddressSpace::kPublic,
- CalculateResourceAddressSpace(GURL("http://foo.test"),
- IPEndPoint(IPAddress(10, 2, 3, 4), 80)));
- EXPECT_EQ(
- IPAddressSpace::kPrivate,
- CalculateResourceAddressSpace(GURL("http://foo.test"),
- IPEndPoint(IPAddress(8, 8, 8, 8), 8888)));
-}
-
-} // namespace
-} // namespace blink
diff --git a/chromium/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc b/chromium/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc
index fad9cdc5bab..3a584056893 100644
--- a/chromium/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc
+++ b/chromium/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/public/common/notifications/notification_mojom_traits.h"
-#include "base/macros.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
diff --git a/chromium/third_party/blink/common/origin_trials/scoped_test_origin_trial_policy.cc b/chromium/third_party/blink/common/origin_trials/scoped_test_origin_trial_policy.cc
new file mode 100644
index 00000000000..a51e893f495
--- /dev/null
+++ b/chromium/third_party/blink/common/origin_trials/scoped_test_origin_trial_policy.cc
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
+
+#include "base/bind.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+
+namespace blink {
+
+// 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.
+//
+// Private key:
+// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
+// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
+// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 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
+const blink::OriginTrialPublicKey kTestPublicKey = {
+ 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,
+};
+
+bool ScopedTestOriginTrialPolicy::IsOriginTrialsSupported() const {
+ return true;
+}
+
+const std::vector<blink::OriginTrialPublicKey>&
+ScopedTestOriginTrialPolicy::GetPublicKeys() const {
+ return public_keys_;
+}
+
+bool ScopedTestOriginTrialPolicy::IsOriginSecure(const GURL& url) const {
+ return true;
+}
+
+ScopedTestOriginTrialPolicy::ScopedTestOriginTrialPolicy()
+ : public_keys_({kTestPublicKey}) {
+ TrialTokenValidator::SetOriginTrialPolicyGetter(base::BindRepeating(
+ [](OriginTrialPolicy* self) { return self; }, base::Unretained(this)));
+}
+
+ScopedTestOriginTrialPolicy::~ScopedTestOriginTrialPolicy() {
+ TrialTokenValidator::ResetOriginTrialPolicyGetter();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/origin_trials/trial_token.cc b/chromium/third_party/blink/common/origin_trials/trial_token.cc
index 7ce55ba5ef6..5c4884df711 100644
--- a/chromium/third_party/blink/common/origin_trials/trial_token.cc
+++ b/chromium/third_party/blink/common/origin_trials/trial_token.cc
@@ -8,7 +8,6 @@
#include "base/big_endian.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
@@ -67,7 +66,7 @@ TrialToken::~TrialToken() = default;
// static
std::unique_ptr<TrialToken> TrialToken::From(
base::StringPiece token_text,
- base::StringPiece public_key,
+ const OriginTrialPublicKey& public_key,
OriginTrialTokenStatus* out_status) {
DCHECK(out_status);
std::string token_payload;
@@ -108,11 +107,12 @@ OriginTrialTokenStatus TrialToken::IsValid(const url::Origin& origin,
}
// static
-OriginTrialTokenStatus TrialToken::Extract(base::StringPiece token_text,
- base::StringPiece public_key,
- std::string* out_token_payload,
- std::string* out_token_signature,
- uint8_t* out_token_version) {
+OriginTrialTokenStatus TrialToken::Extract(
+ base::StringPiece token_text,
+ const OriginTrialPublicKey& public_key,
+ std::string* out_token_payload,
+ std::string* out_token_signature,
+ uint8_t* out_token_version) {
if (token_text.empty()) {
return OriginTrialTokenStatus::kMalformed;
}
@@ -276,10 +276,7 @@ bool TrialToken::ValidateDate(const base::Time& now) const {
// static
bool TrialToken::ValidateSignature(base::StringPiece signature,
const std::string& data,
- base::StringPiece public_key) {
- // Public key must be 32 bytes long for Ed25519.
- CHECK_EQ(public_key.length(), 32UL);
-
+ const OriginTrialPublicKey& public_key) {
// Signature must be 64 bytes long.
if (signature.length() != 64) {
return false;
@@ -287,8 +284,7 @@ bool TrialToken::ValidateSignature(base::StringPiece signature,
int result = ED25519_verify(
reinterpret_cast<const uint8_t*>(data.data()), data.length(),
- reinterpret_cast<const uint8_t*>(signature.data()),
- reinterpret_cast<const uint8_t*>(public_key.data()));
+ reinterpret_cast<const uint8_t*>(signature.data()), public_key.data());
return (result != 0);
}
diff --git a/chromium/third_party/blink/common/origin_trials/trial_token_unittest.cc b/chromium/third_party/blink/common/origin_trials/trial_token_unittest.cc
index 1cecd950ce2..e56a4c673a6 100644
--- a/chromium/third_party/blink/common/origin_trials/trial_token_unittest.cc
+++ b/chromium/third_party/blink/common/origin_trials/trial_token_unittest.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
@@ -37,7 +37,7 @@ const uint8_t kVersion3 = 3;
// To use this with a real browser, use --origin-trial-public-key with the
// public key, base-64-encoded:
// --origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=
-const uint8_t kTestPublicKey[] = {
+const OriginTrialPublicKey kTestPublicKey = {
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,
@@ -52,7 +52,7 @@ const uint8_t kTestPublicKey[] = {
// 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
// 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
// 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
-const uint8_t kTestPublicKey2[] = {
+const OriginTrialPublicKey kTestPublicKey2 = {
0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
@@ -719,16 +719,12 @@ class TrialTokenTest : public testing::Test {
reinterpret_cast<const char*>(
kSampleThirdPartyUsageSubsetTokenSignature),
base::size(kSampleThirdPartyUsageSubsetTokenSignature))),
- correct_public_key_(
- base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
- base::size(kTestPublicKey))),
- incorrect_public_key_(
- base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey2),
- base::size(kTestPublicKey2))) {}
+ correct_public_key_(kTestPublicKey),
+ incorrect_public_key_(kTestPublicKey2) {}
protected:
OriginTrialTokenStatus Extract(const std::string& token_text,
- base::StringPiece public_key,
+ const OriginTrialPublicKey& public_key,
std::string* token_payload,
std::string* token_signature,
uint8_t* token_version) {
@@ -736,8 +732,9 @@ class TrialTokenTest : public testing::Test {
token_signature, token_version);
}
- OriginTrialTokenStatus ExtractStatusOnly(const std::string& token_text,
- base::StringPiece public_key) {
+ OriginTrialTokenStatus ExtractStatusOnly(
+ const std::string& token_text,
+ const OriginTrialPublicKey& public_key) {
std::string token_payload;
std::string token_signature;
uint8_t token_version;
@@ -762,8 +759,12 @@ class TrialTokenTest : public testing::Test {
return token->ValidateDate(now);
}
- base::StringPiece correct_public_key() { return correct_public_key_; }
- base::StringPiece incorrect_public_key() { return incorrect_public_key_; }
+ const OriginTrialPublicKey& correct_public_key() {
+ return correct_public_key_;
+ }
+ const OriginTrialPublicKey& incorrect_public_key() {
+ return incorrect_public_key_;
+ }
const url::Origin expected_origin_;
const url::Origin expected_subdomain_origin_;
@@ -788,8 +789,8 @@ class TrialTokenTest : public testing::Test {
std::string expected_third_party_usage_subset_signature_;
private:
- base::StringPiece correct_public_key_;
- base::StringPiece incorrect_public_key_;
+ OriginTrialPublicKey correct_public_key_;
+ OriginTrialPublicKey incorrect_public_key_;
};
// Test the extraction of the signed payload from token strings. This includes
diff --git a/chromium/third_party/blink/common/origin_trials/trial_token_validator.cc b/chromium/third_party/blink/common/origin_trials/trial_token_validator.cc
index f34e68ceee3..1bedc492c56 100644
--- a/chromium/third_party/blink/common/origin_trials/trial_token_validator.cc
+++ b/chromium/third_party/blink/common/origin_trials/trial_token_validator.cc
@@ -15,18 +15,22 @@
#include "third_party/blink/public/common/origin_trials/trial_token.h"
#include "third_party/blink/public/common/origin_trials/trial_token_result.h"
+namespace blink {
namespace {
-static base::RepeatingCallback<blink::OriginTrialPolicy*()>& PolicyGetter() {
- static base::NoDestructor<
- base::RepeatingCallback<blink::OriginTrialPolicy*()>>
- policy(base::BindRepeating(
- []() -> blink::OriginTrialPolicy* { return nullptr; }));
+static base::RepeatingCallback<OriginTrialPolicy*()>& PolicyGetter() {
+ static base::NoDestructor<base::RepeatingCallback<OriginTrialPolicy*()>>
+ policy(
+ base::BindRepeating([]() -> OriginTrialPolicy* { return nullptr; }));
return *policy;
}
-} // namespace
-namespace blink {
+bool IsDeprecationTrialPossible() {
+ OriginTrialPolicy* policy = PolicyGetter().Run();
+ return policy && policy->IsOriginTrialsSupported();
+}
+
+} // namespace
TrialTokenValidator::TrialTokenValidator() {}
@@ -38,8 +42,8 @@ void TrialTokenValidator::SetOriginTrialPolicyGetter(
}
void TrialTokenValidator::ResetOriginTrialPolicyGetter() {
- SetOriginTrialPolicyGetter(base::BindRepeating(
- []() -> blink::OriginTrialPolicy* { return nullptr; }));
+ SetOriginTrialPolicyGetter(
+ base::BindRepeating([]() -> OriginTrialPolicy* { return nullptr; }));
}
TrialTokenResult TrialTokenValidator::ValidateToken(
@@ -59,13 +63,13 @@ TrialTokenResult TrialTokenValidator::ValidateToken(
if (!policy || !policy->IsOriginTrialsSupported())
return TrialTokenResult(OriginTrialTokenStatus::kNotSupported);
- std::vector<base::StringPiece> public_keys = policy->GetPublicKeys();
+ std::vector<OriginTrialPublicKey> public_keys = policy->GetPublicKeys();
if (public_keys.size() == 0)
return TrialTokenResult(OriginTrialTokenStatus::kNotSupported);
OriginTrialTokenStatus status;
std::unique_ptr<TrialToken> trial_token;
- for (auto& key : public_keys) {
+ for (OriginTrialPublicKey& key : public_keys) {
trial_token = TrialToken::From(token, key, &status);
if (status == OriginTrialTokenStatus::kSuccess)
break;
@@ -124,13 +128,30 @@ bool TrialTokenValidator::RequestEnablesFeature(
const net::HttpResponseHeaders* response_headers,
base::StringPiece feature_name,
base::Time current_time) const {
- if (!IsTrialPossibleOnOrigin(request_url))
- return false;
+ return IsTrialPossibleOnOrigin(request_url) &&
+ ResponseBearsValidTokenForFeature(request_url, *response_headers,
+ feature_name, current_time);
+}
+bool TrialTokenValidator::RequestEnablesDeprecatedFeature(
+ const GURL& request_url,
+ const net::HttpResponseHeaders* response_headers,
+ base::StringPiece feature_name,
+ base::Time current_time) const {
+ return IsDeprecationTrialPossible() &&
+ ResponseBearsValidTokenForFeature(request_url, *response_headers,
+ feature_name, current_time);
+}
+
+bool TrialTokenValidator::ResponseBearsValidTokenForFeature(
+ const GURL& request_url,
+ const net::HttpResponseHeaders& response_headers,
+ base::StringPiece feature_name,
+ base::Time current_time) const {
url::Origin origin = url::Origin::Create(request_url);
size_t iter = 0;
std::string token;
- while (response_headers->EnumerateHeader(&iter, "Origin-Trial", &token)) {
+ while (response_headers.EnumerateHeader(&iter, "Origin-Trial", &token)) {
TrialTokenResult result = ValidateToken(token, origin, current_time);
// TODO(mek): Log the validation errors to histograms?
if (result.Status() == OriginTrialTokenStatus::kSuccess)
diff --git a/chromium/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc b/chromium/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
index 2e30680e3a0..a52e4365d0d 100644
--- a/chromium/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
+++ b/chromium/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
@@ -6,11 +6,12 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/containers/flat_set.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
@@ -45,26 +46,17 @@ namespace trial_token_validator_unittest {
// 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
// 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
// 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
-const uint8_t kTestPublicKeys[][32] = {
- {
- 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,
- },
- {
- 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
- 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
- 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
- }};
-const int kTestPublicKeysSize = 2;
-
-// The corresponding private key can be found above.
-const uint8_t kTestPublicKeys2[][32] = {{
+const OriginTrialPublicKey kTestPublicKey1 = {
+ 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,
+};
+
+const OriginTrialPublicKey kTestPublicKey2 = {
0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
-}};
-const int kTestPublicKeys2Size = 1;
+};
// This is a good trial token, signed with the above test private key.
// TODO(iclelland): This token expires in 2033. Update it or find a way
@@ -190,7 +182,8 @@ class TestOriginTrialPolicy : public OriginTrialPolicy {
bool IsOriginSecure(const GURL& url) const override {
return url.SchemeIs("https");
}
- std::vector<base::StringPiece> GetPublicKeys() const override {
+ const std::vector<blink::OriginTrialPublicKey>& GetPublicKeys()
+ const override {
return keys_;
}
bool IsFeatureDisabled(base::StringPiece feature) const override {
@@ -202,13 +195,10 @@ class TestOriginTrialPolicy : public OriginTrialPolicy {
}
// Test setup methods
- void SetPublicKeys(const uint8_t keys[][32], const int keys_size) {
- keys_.clear();
- for (int n = 0; n < keys_size; n++) {
- keys_.push_back(base::StringPiece(reinterpret_cast<const char*>(keys[n]),
- base::size(keys[n])));
- }
+ void SetPublicKeys(const std::vector<OriginTrialPublicKey>& keys) {
+ keys_ = keys;
}
+
void DisableFeature(const std::string& feature) {
disabled_features_.insert(feature);
}
@@ -225,7 +215,7 @@ class TestOriginTrialPolicy : public OriginTrialPolicy {
}
private:
- std::vector<base::StringPiece> keys_;
+ std::vector<blink::OriginTrialPublicKey> keys_;
base::flat_set<std::string> disabled_features_;
base::flat_set<std::string> disabled_features_for_user_;
base::flat_set<std::string> disabled_tokens_;
@@ -247,15 +237,15 @@ class TrialTokenValidatorTest : public testing::Test {
TrialTokenValidator::SetOriginTrialPolicyGetter(
base::BindRepeating([](OriginTrialPolicy* policy) { return policy; },
base::Unretained(&policy_)));
- SetPublicKeys(kTestPublicKeys, kTestPublicKeysSize);
+ SetPublicKeys({kTestPublicKey1, kTestPublicKey2});
}
~TrialTokenValidatorTest() override {
TrialTokenValidator::ResetOriginTrialPolicyGetter();
}
- void SetPublicKeys(const uint8_t keys[][32], const int keys_size) {
- policy_.SetPublicKeys(keys, keys_size);
+ void SetPublicKeys(const std::vector<OriginTrialPublicKey> keys) {
+ policy_.SetPublicKeys(keys);
}
void DisableFeature(const std::string& feature) {
@@ -364,7 +354,7 @@ TEST_F(TrialTokenValidatorTest, ValidateExpiredToken) {
}
TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) {
- SetPublicKeys(kTestPublicKeys2, kTestPublicKeys2Size);
+ SetPublicKeys({kTestPublicKey2});
TrialTokenResult result =
validator_.ValidateToken(kSampleToken, appropriate_origin_, Now());
EXPECT_EQ(result.Status(), blink::OriginTrialTokenStatus::kInvalidSignature);
@@ -372,7 +362,7 @@ TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) {
}
TEST_F(TrialTokenValidatorTest, PublicKeyNotAvailable) {
- SetPublicKeys({}, 0);
+ SetPublicKeys({});
TrialTokenResult result =
validator_.ValidateToken(kSampleToken, appropriate_origin_, Now());
EXPECT_EQ(result.Status(), blink::OriginTrialTokenStatus::kNotSupported);
@@ -453,6 +443,13 @@ TEST_F(TrialTokenValidatorTest, ValidateRequestInsecure) {
Now()));
}
+TEST_F(TrialTokenValidatorTest, ValidateRequestForDeprecationInsecure) {
+ response_headers_->AddHeader("Origin-Trial", kInsecureOriginToken);
+ EXPECT_TRUE(validator_.RequestEnablesDeprecatedFeature(
+ GURL(kInsecureOrigin), response_headers_.get(), kAppropriateFeatureName,
+ Now()));
+}
+
TEST_F(TrialTokenValidatorTest, ValidateRequestValidToken) {
response_headers_->AddHeader("Origin-Trial", kSampleToken);
EXPECT_TRUE(validator_.RequestEnablesFeature(GURL(kAppropriateOrigin),
@@ -460,12 +457,25 @@ TEST_F(TrialTokenValidatorTest, ValidateRequestValidToken) {
kAppropriateFeatureName, Now()));
}
+TEST_F(TrialTokenValidatorTest, ValidateRequestForDeprecationValidToken) {
+ response_headers_->AddHeader("Origin-Trial", kSampleToken);
+ EXPECT_TRUE(validator_.RequestEnablesDeprecatedFeature(
+ GURL(kAppropriateOrigin), response_headers_.get(),
+ kAppropriateFeatureName, Now()));
+}
+
TEST_F(TrialTokenValidatorTest, ValidateRequestNoTokens) {
EXPECT_FALSE(validator_.RequestEnablesFeature(
GURL(kAppropriateOrigin), response_headers_.get(),
kAppropriateFeatureName, Now()));
}
+TEST_F(TrialTokenValidatorTest, ValidateRequestForDeprecationNoTokens) {
+ EXPECT_FALSE(validator_.RequestEnablesDeprecatedFeature(
+ GURL(kAppropriateOrigin), response_headers_.get(),
+ kAppropriateFeatureName, Now()));
+}
+
TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaders) {
response_headers_->AddHeader("Origin-Trial", kSampleToken);
response_headers_->AddHeader("Origin-Trial", kExpiredToken);
diff --git a/chromium/third_party/blink/common/page_state/page_state.cc b/chromium/third_party/blink/common/page_state/page_state.cc
index 9d15340e4a1..b1d37c49616 100644
--- a/chromium/third_party/blink/common/page_state/page_state.cc
+++ b/chromium/third_party/blink/common/page_state/page_state.cc
@@ -14,6 +14,7 @@
#include "services/network/public/mojom/referrer_policy.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/page_state/page_state_serialization.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
namespace blink {
namespace {
@@ -180,4 +181,9 @@ PageState::PageState(const std::string& data) : data_(data) {
// DCHECK(IsValid());
}
+void PageState::WriteIntoTrace(perfetto::TracedValue context) const {
+ auto dict = std::move(context).WriteDictionary();
+ dict.Add("data", data_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/common/permissions_policy/README.md b/chromium/third_party/blink/common/permissions_policy/README.md
index 4ef43a85882..85b3babdf88 100644
--- a/chromium/third_party/blink/common/permissions_policy/README.md
+++ b/chromium/third_party/blink/common/permissions_policy/README.md
@@ -1,5 +1,5 @@
## Permissions Policy Guide (Previously Feature Policy)
-Permissions policy is the new name for feature policy with a new HTTP header which uses [structured header](https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html) syntax. Code currently under feature_policy directory in chromium repository has not been renamed yet.
+Permissions policy is the new name for feature policy with a new HTTP header which uses [structured header](https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html) syntax.
### How to add a new feature to permissions policy
@@ -49,7 +49,7 @@ policy is undetermined, consider shipping the feature behind a runtime-enabled f
##### Define new feature
1. Permissions policy features are defined in
-`third_party/blink/renderer/core/feature_policy/feature_policy_features.json5`. Add the new feature,
+`third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5`. Add the new feature,
placing any runtime-enabled feature or origin trial dependencies in its "depends_on" field as
described in the file's comments. This list is used to generate `permissions_policy_helper.cc`.
@@ -76,7 +76,7 @@ See: https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md
##### Write web-platform-tests
To test the new feature with permissions policy, refer to
-`third_party/blink/web_tests/external/wpt/feature-policy/README.md` for
+`third_party/blink/web_tests/external/wpt/permissions-policy/README.md` for
instructions on how to use the permissions policy test framework.
## Document Policy Guide
@@ -102,12 +102,12 @@ policy is undetermined, consider shipping the feature behind a runtime-enabled f
##### Define new feature
1. Document policy features are defined in
-`third_party/blink/renderer/core/feature_policy/document_policy_features.json5`. Add the new feature,
+`third_party/blink/renderer/core/permissions_policy/document_policy_features.json5`. Add the new feature,
placing any runtime-enabled feature or origin trial dependencies in its "depends_on" field as
described in the file's comments.
2. Append the new feature enum with a brief description as well in
-`third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom`
+`third_party/blink/public/mojom/permissions_policy/document_policy_feature.mojom`
##### Integrate the feature behaviour with document policy
The most common way to check if features are enabled is `ExecutionContext::IsFeatureEnabled`.
diff --git a/chromium/third_party/blink/common/permissions_policy/permissions_policy.cc b/chromium/third_party/blink/common/permissions_policy/permissions_policy.cc
index bd5c6cdb463..17fbb4980fe 100644
--- a/chromium/third_party/blink/common/permissions_policy/permissions_policy.cc
+++ b/chromium/third_party/blink/common/permissions_policy/permissions_policy.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
#include "base/containers/contains.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
diff --git a/chromium/third_party/blink/common/permissions_policy/permissions_policy_mojom_traits.h b/chromium/third_party/blink/common/permissions_policy/permissions_policy_mojom_traits.h
index ebdea496edb..9cb374260db 100644
--- a/chromium/third_party/blink/common/permissions_policy/permissions_policy_mojom_traits.h
+++ b/chromium/third_party/blink/common/permissions_policy/permissions_policy_mojom_traits.h
@@ -7,7 +7,6 @@
#include <map>
-#include "base/containers/flat_map.h"
#include "mojo/public/cpp/bindings/enum_traits.h"
#include "third_party/blink/common/permissions_policy/policy_value_mojom_traits.h"
#include "third_party/blink/public/common/common_export.h"
diff --git a/chromium/third_party/blink/common/permissions_policy/policy_value.cc b/chromium/third_party/blink/common/permissions_policy/policy_value.cc
index 84e5b826c11..c2b1e1abdd8 100644
--- a/chromium/third_party/blink/common/permissions_policy/policy_value.cc
+++ b/chromium/third_party/blink/common/permissions_policy/policy_value.cc
@@ -10,6 +10,10 @@ namespace blink {
PolicyValue::PolicyValue() : type_(mojom::PolicyValueType::kNull) {}
+PolicyValue::PolicyValue(const PolicyValue&) = default;
+
+PolicyValue& PolicyValue::operator=(const PolicyValue&) = default;
+
// static
PolicyValue PolicyValue::CreateBool(bool value) {
return PolicyValue(value);
@@ -82,16 +86,6 @@ void PolicyValue::SetIntValue(int32_t int_value) {
int_value_ = int_value;
}
-PolicyValue& PolicyValue::operator=(const PolicyValue& rhs) {
- if (this != &rhs) {
- type_ = rhs.type_;
- bool_value_ = rhs.bool_value_;
- double_value_ = rhs.double_value_;
- int_value_ = rhs.int_value_;
- }
- return *this;
-}
-
bool operator==(const PolicyValue& lhs, const PolicyValue& rhs) {
if (lhs.Type() != rhs.Type())
return false;
diff --git a/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector.cc b/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector.cc
index dfea6e11a47..ad1a0f4c54b 100644
--- a/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector.cc
+++ b/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector.cc
@@ -11,7 +11,6 @@
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/no_destructor.h"
-#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/template_util.h"
#include "base/time/time.h"
diff --git a/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector_unittest.cc b/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector_unittest.cc
index 1ca56b72d71..ebce0d87cfa 100644
--- a/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector_unittest.cc
+++ b/chromium/third_party/blink/common/privacy_budget/aggregating_sample_collector_unittest.cc
@@ -41,8 +41,6 @@ class TestSettingsProvider : public IdentifiabilityStudySettingsProvider {
bool IsAnyTypeOrSurfaceBlocked() const override { return false; }
bool IsSurfaceAllowed(IdentifiableSurface) const override { return true; }
bool IsTypeAllowed(IdentifiableSurface::Type) const override { return true; }
- int SampleRate(IdentifiableSurface) const override { return 1; }
- int SampleRate(IdentifiableSurface::Type) const override { return 1; }
};
} // namespace
diff --git a/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings.cc b/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
index bf93086c55a..e0d664c5a03 100644
--- a/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
+++ b/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
@@ -9,7 +9,6 @@
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/no_destructor.h"
-#include "base/rand_util.h"
#include "base/synchronization/atomic_flag.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -84,42 +83,6 @@ class ThreadsafeSettingsWrapper {
base::AtomicFlag initialized_;
};
-// RandGenerator de-biasing implementation stolen from //base/rand_util.h, and
-// adapted to work with passed-in RNGs.
-template <typename G>
-uint64_t RandGenerator(uint64_t range, G& generator) {
- DCHECK_GT(range, 0u);
- // We must discard random results above this number, as they would
- // make the random generator non-uniform (consider e.g. if
- // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice
- // as likely as a result of 3 or 4).
- uint64_t max_acceptable_value =
- (std::numeric_limits<uint64_t>::max() / range) * range - 1;
-
- uint64_t value;
- do {
- value = generator();
- } while (value > max_acceptable_value);
-
- return value % range;
-}
-
-bool DecideSample(int sample_rate) {
- static base::NoDestructor<base::SequenceLocalStorageSlot<std::mt19937_64>>
- prng;
-
- if (sample_rate == 0)
- return false;
-
- if (sample_rate == 1)
- return true;
-
- if (!prng->GetValuePointer())
- prng->emplace(base::RandUint64());
-
- return RandGenerator(sample_rate, **prng) == 0;
-}
-
} // namespace
IdentifiabilityStudySettingsProvider::~IdentifiabilityStudySettingsProvider() =
@@ -184,18 +147,12 @@ bool IdentifiabilityStudySettings::IsWebFeatureAllowed(
bool IdentifiabilityStudySettings::ShouldSample(
IdentifiableSurface surface) const {
- if (LIKELY(!is_enabled_))
- return false;
-
- return DecideSample(provider_->SampleRate(surface));
+ return IsSurfaceAllowed(surface);
}
bool IdentifiabilityStudySettings::ShouldSample(
IdentifiableSurface::Type type) const {
- if (LIKELY(!is_enabled_))
- return false;
-
- return DecideSample(provider_->SampleRate(type));
+ return IsTypeAllowed(type);
}
} // namespace blink
diff --git a/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc b/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc
index fb181789377..e134197c63b 100644
--- a/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc
+++ b/chromium/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc
@@ -48,10 +48,6 @@ class CountingSettingsProvider : public IdentifiabilityStudySettingsProvider {
return state_->response_for_is_allowed;
}
- int SampleRate(IdentifiableSurface surface) const override { return 1; }
-
- int SampleRate(IdentifiableSurface::Type type) const override { return 1; }
-
private:
CallCounts* state_ = nullptr;
};
diff --git a/chromium/third_party/blink/common/privacy_budget/identifiable_token_builder.cc b/chromium/third_party/blink/common/privacy_budget/identifiable_token_builder.cc
index 210db855a35..f08a18a2d5a 100644
--- a/chromium/third_party/blink/common/privacy_budget/identifiable_token_builder.cc
+++ b/chromium/third_party/blink/common/privacy_budget/identifiable_token_builder.cc
@@ -83,11 +83,6 @@ IdentifiableTokenBuilder& IdentifiableTokenBuilder::AddAtomic(ByteSpan buffer) {
return *this;
}
-IdentifiableTokenBuilder& IdentifiableTokenBuilder::AddToken(
- IdentifiableToken token) {
- return AddValue(token.value_);
-}
-
IdentifiableTokenBuilder::operator IdentifiableToken() const {
return GetToken();
}
diff --git a/chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc b/chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
index c9fbbdd94d4..64ddc811ff9 100644
--- a/chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
+++ b/chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -20,6 +20,8 @@ FeatureNames FeatureToNames(WebSchedulerTrackedFeature feature) {
switch (feature) {
case WebSchedulerTrackedFeature::kWebSocket:
return {"WebSocket", "WebSocket"};
+ case WebSchedulerTrackedFeature::kWebTransport:
+ return {"WebTransport", "WebTransport"};
case WebSchedulerTrackedFeature::kWebRTC:
return {"WebRTC", "WebRTC"};
case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoCache:
@@ -34,18 +36,6 @@ FeatureNames FeatureToNames(WebSchedulerTrackedFeature feature) {
case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoStore:
return {"SubresourceHasCacheControlNoStore",
"subresource has Cache-Control: No-Store"};
- case WebSchedulerTrackedFeature::kPageShowEventListener:
- return {"PageShowEventListener", "onpageshow() event listener"};
- case WebSchedulerTrackedFeature::kPageHideEventListener:
- return {"PageHideEventListener", "onpagehide() event listener"};
- case WebSchedulerTrackedFeature::kBeforeUnloadEventListener:
- return {"BeforeUnloadEventListener", "onbeforeunload() event listener"};
- case WebSchedulerTrackedFeature::kUnloadEventListener:
- return {"UnloadEventListener", "onunload() event listener"};
- case WebSchedulerTrackedFeature::kFreezeEventListener:
- return {"FreezeEventListener", "onfreeze() event listener"};
- case WebSchedulerTrackedFeature::kResumeEventListener:
- return {"ResumeEventListener", "onresume() event listener"};
case WebSchedulerTrackedFeature::kContainsPlugins:
return {"ContainsPlugins", "page contains plugins"};
case WebSchedulerTrackedFeature::kDocumentLoaded:
@@ -67,9 +57,6 @@ FeatureNames FeatureToNames(WebSchedulerTrackedFeature feature) {
case WebSchedulerTrackedFeature::kOutstandingIndexedDBTransaction:
return {"OutstandingIndexedDBTransaction",
"outstanding IndexedDB transaction"};
- case WebSchedulerTrackedFeature::kRequestedGeolocationPermission:
- return {"RequestedGeolocationPermission",
- "requested geolocation permission"};
case WebSchedulerTrackedFeature::kRequestedNotificationsPermission:
return {"RequestedNotificationsPermission",
"requested notifications permission"};
@@ -91,8 +78,6 @@ FeatureNames FeatureToNames(WebSchedulerTrackedFeature feature) {
return {"BroadcastChannel", "requested broadcast channel permission"};
case WebSchedulerTrackedFeature::kIndexedDBConnection:
return {"IndexedDBConnection", "IndexedDB connection present"};
- case WebSchedulerTrackedFeature::kWebVR:
- return {"WebVR", "WebVR"};
case WebSchedulerTrackedFeature::kWebXR:
return {"WebXR", "WebXR"};
case WebSchedulerTrackedFeature::kWebLocks:
@@ -181,53 +166,37 @@ absl::optional<WebSchedulerTrackedFeature> StringToFeature(
}
bool IsFeatureSticky(WebSchedulerTrackedFeature feature) {
- return (FeatureToBit(feature) & StickyFeaturesBitmask()) > 0;
+ return StickyFeatures().Has(feature);
}
-uint64_t StickyFeaturesBitmask() {
- return FeatureToBit(
- WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoStore) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoCache) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoStore) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoCache) |
- FeatureToBit(WebSchedulerTrackedFeature::kPageShowEventListener) |
- FeatureToBit(WebSchedulerTrackedFeature::kPageHideEventListener) |
- FeatureToBit(WebSchedulerTrackedFeature::kBeforeUnloadEventListener) |
- FeatureToBit(WebSchedulerTrackedFeature::kUnloadEventListener) |
- FeatureToBit(WebSchedulerTrackedFeature::kFreezeEventListener) |
- FeatureToBit(WebSchedulerTrackedFeature::kResumeEventListener) |
- FeatureToBit(WebSchedulerTrackedFeature::kContainsPlugins) |
- FeatureToBit(WebSchedulerTrackedFeature::kDocumentLoaded) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kRequestedGeolocationPermission) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kRequestedNotificationsPermission) |
- FeatureToBit(WebSchedulerTrackedFeature::kRequestedMIDIPermission) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kRequestedAudioCapturePermission) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kRequestedVideoCapturePermission) |
- FeatureToBit(WebSchedulerTrackedFeature::
- kRequestedBackForwardCacheBlockedSensors) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission) |
- FeatureToBit(WebSchedulerTrackedFeature::kWebLocks) |
- FeatureToBit(
- WebSchedulerTrackedFeature::kRequestedStorageAccessGrant) |
- FeatureToBit(WebSchedulerTrackedFeature::kWebNfc) |
- FeatureToBit(WebSchedulerTrackedFeature::kWebFileSystem) |
- FeatureToBit(WebSchedulerTrackedFeature::kAppBanner) |
- FeatureToBit(WebSchedulerTrackedFeature::kPrinting) |
- FeatureToBit(WebSchedulerTrackedFeature::kPictureInPicture) |
- FeatureToBit(WebSchedulerTrackedFeature::kIdleManager) |
- FeatureToBit(WebSchedulerTrackedFeature::kPaymentManager) |
- FeatureToBit(WebSchedulerTrackedFeature::kKeyboardLock) |
- FeatureToBit(WebSchedulerTrackedFeature::kWebOTPService) |
- FeatureToBit(WebSchedulerTrackedFeature::kIsolatedWorldScript) |
- FeatureToBit(WebSchedulerTrackedFeature::kInjectedStyleSheet);
+WebSchedulerTrackedFeatures StickyFeatures() {
+ constexpr WebSchedulerTrackedFeatures features = WebSchedulerTrackedFeatures(
+ WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoStore,
+ WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoCache,
+ WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoStore,
+ WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoCache,
+ WebSchedulerTrackedFeature::kContainsPlugins,
+ WebSchedulerTrackedFeature::kDocumentLoaded,
+ WebSchedulerTrackedFeature::kRequestedNotificationsPermission,
+ WebSchedulerTrackedFeature::kRequestedMIDIPermission,
+ WebSchedulerTrackedFeature::kRequestedAudioCapturePermission,
+ WebSchedulerTrackedFeature::kRequestedVideoCapturePermission,
+ WebSchedulerTrackedFeature::kRequestedBackForwardCacheBlockedSensors,
+ WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission,
+ WebSchedulerTrackedFeature::kWebLocks,
+ WebSchedulerTrackedFeature::kRequestedStorageAccessGrant,
+ WebSchedulerTrackedFeature::kWebNfc,
+ WebSchedulerTrackedFeature::kWebFileSystem,
+ WebSchedulerTrackedFeature::kAppBanner,
+ WebSchedulerTrackedFeature::kPrinting,
+ WebSchedulerTrackedFeature::kPictureInPicture,
+ WebSchedulerTrackedFeature::kIdleManager,
+ WebSchedulerTrackedFeature::kPaymentManager,
+ WebSchedulerTrackedFeature::kKeyboardLock,
+ WebSchedulerTrackedFeature::kWebOTPService,
+ WebSchedulerTrackedFeature::kIsolatedWorldScript,
+ WebSchedulerTrackedFeature::kInjectedStyleSheet);
+ return features;
}
} // namespace scheduler
diff --git a/chromium/third_party/blink/common/scheme_registry.cc b/chromium/third_party/blink/common/scheme_registry.cc
new file mode 100644
index 00000000000..21d529ee77f
--- /dev/null
+++ b/chromium/third_party/blink/common/scheme_registry.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/scheme_registry.h"
+
+#include <unordered_set>
+
+#include "base/no_destructor.h"
+#include "base/strings/string_util.h"
+
+namespace blink {
+
+using URLSchemesSet = std::unordered_set<std::string>;
+
+URLSchemesSet& GetMutableExtensionSchemes() {
+ static base::NoDestructor<URLSchemesSet> extension_schemes;
+ return *extension_schemes;
+}
+
+const URLSchemesSet& GetExtensionSchemes() {
+ return GetMutableExtensionSchemes();
+}
+
+void CommonSchemeRegistry::RegisterURLSchemeAsExtension(
+ const std::string& scheme) {
+ DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
+ GetMutableExtensionSchemes().insert(scheme);
+}
+
+void CommonSchemeRegistry::RemoveURLSchemeAsExtensionForTest(
+ const std::string& scheme) {
+ GetMutableExtensionSchemes().erase(scheme);
+}
+
+bool CommonSchemeRegistry::IsExtensionScheme(const std::string& scheme) {
+ if (scheme.empty())
+ return false;
+ DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
+ return GetExtensionSchemes().find(scheme) != GetExtensionSchemes().end();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/address_space_feature.cc b/chromium/third_party/blink/common/security/address_space_feature.cc
index 3fb7df37770..ac9c03f401d 100644
--- a/chromium/third_party/blink/renderer/core/loader/address_space_feature.cc
+++ b/chromium/third_party/blink/common/security/address_space_feature.cc
@@ -28,25 +28,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/core/loader/address_space_feature.h"
+#include "third_party/blink/public/common/security/address_space_feature.h"
#include <tuple>
-#include "services/network/public/cpp/cors/cors_error_status.h"
-#include "services/network/public/mojom/cors.mojom-forward.h"
-#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-forward.h"
-#include "third_party/blink/renderer/core/frame/deprecation.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-
namespace blink {
namespace {
-using AddressSpace = network::mojom::blink::IPAddressSpace;
-using Feature = mojom::blink::WebFeature;
+using AddressSpace = network::mojom::IPAddressSpace;
+using Feature = mojom::WebFeature;
// A key in |kFeatureMap|.
//
@@ -148,23 +138,6 @@ const FeatureEntry* FindFeatureEntry(const FeatureKey& key) {
return nullptr;
}
-// The list of features which should be reported as deprecated.
-constexpr Feature kDeprecatedFeatures[] = {
- Feature::kAddressSpacePublicNonSecureContextEmbeddedPrivate,
- Feature::kAddressSpacePublicNonSecureContextEmbeddedLocal,
- Feature::kAddressSpacePrivateNonSecureContextEmbeddedLocal,
-};
-
-// Returns whether |feature| is deprecated.
-bool IsDeprecated(Feature feature) {
- for (Feature entry : kDeprecatedFeatures) {
- if (feature == entry) {
- return true;
- }
- }
- return false;
-}
-
} // namespace
absl::optional<Feature> AddressSpaceFeature(
@@ -190,63 +163,4 @@ absl::optional<Feature> AddressSpaceFeature(
}
}
-void RecordAddressSpaceFeature(FetchType fetch_type,
- LocalFrame* client_frame,
- const ResourceResponse& response) {
- if (!client_frame) {
- return;
- }
-
- LocalDOMWindow* window = client_frame->DomWindow();
- absl::optional<WebFeature> feature =
- AddressSpaceFeature(fetch_type, window->AddressSpace(),
- window->IsSecureContext(), response.AddressSpace());
- if (!feature.has_value()) {
- return;
- }
-
- // This WebFeature encompasses all private network requests.
- UseCounter::Count(window,
- WebFeature::kMixedContentPrivateHostnameInPublicHostname);
-
- if (IsDeprecated(*feature)) {
- Deprecation::CountDeprecation(window, *feature);
- } else {
- UseCounter::Count(window, *feature);
- }
-}
-
-void RecordAddressSpaceFeature(FetchType fetch_type,
- LocalFrame* client_frame,
- const ResourceError& error) {
- if (!client_frame) {
- return;
- }
-
- absl::optional<network::CorsErrorStatus> status = error.CorsErrorStatus();
- if (!status.has_value() ||
- status->cors_error !=
- network::mojom::CorsError::kInsecurePrivateNetwork) {
- // Not the right kind of error, ignore.
- return;
- }
-
- LocalDOMWindow* window = client_frame->DomWindow();
- absl::optional<WebFeature> feature = AddressSpaceFeature(
- fetch_type, window->AddressSpace(), window->IsSecureContext(),
- status->resource_address_space);
- if (!feature.has_value()) {
- return;
- }
-
- // This WebFeature encompasses all private network requests.
- UseCounter::Count(window,
- WebFeature::kMixedContentPrivateHostnameInPublicHostname);
-
- // Count the feature but do not log it as a deprecation, since its use is
- // forbidden and has resulted in the fetch failing. In other words, the
- // document only *attempted* to use a feature that is no longer available.
- UseCounter::Count(window, *feature);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/address_space_feature_test.cc b/chromium/third_party/blink/common/security/address_space_feature_unittest.cc
index 70fec1513b8..f00299d0996 100644
--- a/chromium/third_party/blink/renderer/core/loader/address_space_feature_test.cc
+++ b/chromium/third_party/blink/common/security/address_space_feature_unittest.cc
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/core/loader/address_space_feature.h"
+#include "third_party/blink/public/common/security/address_space_feature.h"
#include <iosfwd>
#include <string>
@@ -40,8 +40,8 @@
namespace blink {
namespace {
-using AddressSpace = network::mojom::blink::IPAddressSpace;
-using Feature = mojom::blink::WebFeature;
+using AddressSpace = network::mojom::IPAddressSpace;
+using Feature = mojom::WebFeature;
constexpr FetchType kAllFetchTypes[]{
FetchType::kSubresource,
@@ -242,10 +242,11 @@ bool HasMappedFeature(const Input& input) {
}
// This test verifies that AddressSpaceFeature stays in sync with the reference
-// implementation for CORS-RFC1918 address space checks in services/network. In
-// more practical terms, it verifies that AddressSpaceFeature returns a feature
-// (as opposed to nullopt) if and only if the resource address space is less
-// public than the client address space.
+// implementation for Private Network Access address space checks in
+// services/networ. In more practical terms, it verifies that
+// `AddressSpaceFeature()` returns a feature (as opposed to `nullopt`) if and
+// only if the resource address space is less public than the client address
+// space.
TEST(AddressSpaceFeatureTest, ReturnsFeatureIffResourceLessPublic) {
for (const Input& input : AllInputs()) {
SCOPED_TRACE(input);
@@ -263,8 +264,8 @@ TEST(AddressSpaceFeatureTest, ReturnsFeatureIffResourceLessPublic) {
}
}
-// This test verifies that AddressSpaceFeatureForX() maps inputs to
-// features as declared in kFeatureMappings.
+// This test verifies that `AddressSpaceFeature()` maps inputs to features as
+// declared in `kFeatureMappings`.
TEST(AddressSpaceFeatureTest, MapsAllFeaturesCorrectly) {
for (const FeatureMapping& mapping : kFeatureMappings) {
SCOPED_TRACE(mapping.input);
@@ -277,7 +278,7 @@ TEST(AddressSpaceFeatureTest, MapsAllFeaturesCorrectly) {
}
// This test verifies that all inputs that yield a Feature when run through
-// AddressSpaceFeatureForX() are included in kFeatureMappings.
+// `AddressSpaceFeature()` are included in `kFeatureMappings`.
TEST(AddressSpaceFeatureTest, FeatureMappingsAreComplete) {
for (const Input& input : AllInputs()) {
SCOPED_TRACE(input);
diff --git a/chromium/third_party/blink/common/storage_key/DIR_METADATA b/chromium/third_party/blink/common/storage_key/DIR_METADATA
new file mode 100644
index 00000000000..27f133595b6
--- /dev/null
+++ b/chromium/third_party/blink/common/storage_key/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "Blink>Storage"
+}
+
+team_email: "storage-dev@chromium.org" \ No newline at end of file
diff --git a/chromium/third_party/blink/common/storage_key/OWNERS b/chromium/third_party/blink/common/storage_key/OWNERS
new file mode 100644
index 00000000000..aa0085a5596
--- /dev/null
+++ b/chromium/third_party/blink/common/storage_key/OWNERS
@@ -0,0 +1,4 @@
+file://storage/OWNERS
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/third_party/blink/common/storage_key/storage_key.cc b/chromium/third_party/blink/common/storage_key/storage_key.cc
new file mode 100644
index 00000000000..4deb4c399de
--- /dev/null
+++ b/chromium/third_party/blink/common/storage_key/storage_key.cc
@@ -0,0 +1,90 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+
+#include <cctype>
+#include <ostream>
+#include <tuple>
+
+#include "base/feature_list.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/strcat.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+// static
+absl::optional<StorageKey> StorageKey::Deserialize(base::StringPiece in) {
+ // TODO(https://crbug.com/1199077): Figure out how to include `nonce_` in the
+ // serialization.
+ StorageKey result(url::Origin::Create(GURL(in)));
+ return result.origin_.opaque() ? absl::nullopt
+ : absl::make_optional(std::move(result));
+}
+
+// static
+StorageKey StorageKey::CreateFromStringForTesting(const std::string& origin) {
+ absl::optional<StorageKey> result = Deserialize(origin);
+ return result.value_or(StorageKey());
+}
+
+// static
+bool StorageKey::IsThirdPartyStoragePartitioningEnabled() {
+ return base::FeatureList::IsEnabled(features::kThirdPartyStoragePartitioning);
+}
+
+// static
+StorageKey StorageKey::CreateWithNonce(const url::Origin& origin,
+ const base::UnguessableToken& nonce) {
+ DCHECK(!nonce.is_empty());
+ return StorageKey(origin, &nonce);
+}
+
+std::string StorageKey::Serialize() const {
+ // TODO(https://crbug.com/1199077): Figure out how to include `nonce_` in the
+ // serialization.
+ DCHECK(!origin_.opaque());
+ return origin_.GetURL().spec();
+}
+
+std::string StorageKey::SerializeForLocalStorage() const {
+ // TODO(https://crbug.com/1199077): Figure out how to include `nonce_` in the
+ // serialization.
+ DCHECK(!origin_.opaque());
+ return origin_.Serialize();
+}
+
+std::string StorageKey::GetDebugString() const {
+ return base::StrCat(
+ {"{ origin: ", origin_.GetDebugString(),
+ ", nonce: ", nonce_.has_value() ? nonce_->ToString() : "<null>", " }"});
+}
+
+std::string StorageKey::GetMemoryDumpString(size_t max_length) const {
+ std::string memory_dump_str = origin_.Serialize().substr(0, max_length);
+ base::ranges::replace_if(
+ memory_dump_str.begin(), memory_dump_str.end(),
+ [](char c) { return !std::isalnum(static_cast<unsigned char>(c)); }, '_');
+ return memory_dump_str;
+}
+
+bool operator==(const StorageKey& lhs, const StorageKey& rhs) {
+ return std::tie(lhs.origin_, lhs.nonce_) == std::tie(rhs.origin_, rhs.nonce_);
+}
+
+bool operator!=(const StorageKey& lhs, const StorageKey& rhs) {
+ return !(lhs == rhs);
+}
+
+bool operator<(const StorageKey& lhs, const StorageKey& rhs) {
+ return std::tie(lhs.origin_, lhs.nonce_) < std::tie(rhs.origin_, rhs.nonce_);
+}
+
+std::ostream& operator<<(std::ostream& ostream, const StorageKey& sk) {
+ return ostream << sk.GetDebugString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/storage_key/storage_key_mojom_traits.cc b/chromium/third_party/blink/common/storage_key/storage_key_mojom_traits.cc
new file mode 100644
index 00000000000..84af7fbe248
--- /dev/null
+++ b/chromium/third_party/blink/common/storage_key/storage_key_mojom_traits.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/storage_key/storage_key_mojom_traits.h"
+#include "url/mojom/origin_mojom_traits.h"
+
+#include "url/origin.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<blink::mojom::StorageKeyDataView, blink::StorageKey>::Read(
+ blink::mojom::StorageKeyDataView data,
+ blink::StorageKey* out) {
+ url::Origin origin;
+ if (!data.ReadOrigin(&origin))
+ return false;
+
+ absl::optional<base::UnguessableToken> nonce;
+ if (!data.ReadNonce(&nonce))
+ return false;
+
+ if (nonce.has_value())
+ *out = blink::StorageKey::CreateWithNonce(origin, *nonce);
+ else
+ *out = blink::StorageKey(origin);
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc b/chromium/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc
new file mode 100644
index 00000000000..0f7bd4268bf
--- /dev/null
+++ b/chromium/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/storage_key/storage_key_mojom_traits.h"
+
+#include "base/unguessable_token.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+#include "third_party/blink/public/mojom/storage_key/storage_key.mojom.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace blink {
+namespace {
+
+TEST(StorageKeyMojomTraitsTest, SerializeAndDeserialize) {
+ StorageKey test_keys[] = {
+ StorageKey(url::Origin::Create(GURL("https://example.com"))),
+ StorageKey(url::Origin::Create(GURL("http://example.com"))),
+ StorageKey(url::Origin::Create(GURL("https://example.test"))),
+ StorageKey(url::Origin::Create(GURL("https://sub.example.com"))),
+ StorageKey(url::Origin::Create(GURL("http://sub2.example.com"))),
+ StorageKey(url::Origin()),
+ StorageKey::CreateWithNonce(
+ url::Origin::Create(GURL("https://.example.com")),
+ base::UnguessableToken::Create()),
+ StorageKey::CreateWithNonce(url::Origin(),
+ base::UnguessableToken::Create()),
+ };
+
+ for (auto& original : test_keys) {
+ StorageKey copied;
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::StorageKey>(original,
+ copied));
+ EXPECT_EQ(original, copied);
+ }
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/common/storage_key/storage_key_unittest.cc b/chromium/third_party/blink/common/storage_key/storage_key_unittest.cc
new file mode 100644
index 00000000000..f5021375bc7
--- /dev/null
+++ b/chromium/third_party/blink/common/storage_key/storage_key_unittest.cc
@@ -0,0 +1,227 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+
+#include "base/feature_list.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/unguessable_token.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace {
+
+// Opaqueness here is used as a way of checking for "correctly constructed" in
+// most tests.
+//
+// Why not call it IsValid()? Because some tests actually want to check for
+// opaque origins.
+bool IsOpaque(const blink::StorageKey& key) {
+ return key.origin().opaque();
+}
+
+} // namespace
+
+namespace blink {
+
+// Test when a constructed StorageKey object should be considered valid/opaque.
+TEST(StorageKeyTest, ConstructionValidity) {
+ StorageKey empty = StorageKey();
+ EXPECT_TRUE(IsOpaque(empty));
+
+ url::Origin valid_origin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey valid = StorageKey(valid_origin);
+ EXPECT_FALSE(IsOpaque(valid));
+
+ url::Origin invalid_origin =
+ url::Origin::Create(GURL("I'm not a valid URL."));
+ StorageKey invalid = StorageKey(invalid_origin);
+ EXPECT_TRUE(IsOpaque(invalid));
+}
+
+// Test that StorageKeys are/aren't equivalent as expected.
+TEST(StorageKeyTest, Equivalence) {
+ url::Origin origin1 = url::Origin::Create(GURL("https://example.com"));
+ url::Origin origin2 = url::Origin::Create(GURL("https://test.example"));
+ url::Origin origin3 = url::Origin();
+ url::Origin origin4 =
+ url::Origin(); // Creates a different opaque origin than origin3.
+
+ base::UnguessableToken nonce1 = base::UnguessableToken::Create();
+ base::UnguessableToken nonce2 = base::UnguessableToken::Create();
+
+ StorageKey key1_origin1 = StorageKey(origin1);
+ StorageKey key2_origin1 = StorageKey(origin1);
+ StorageKey key3_origin2 = StorageKey(origin2);
+
+ StorageKey key4_origin3 = StorageKey(origin3);
+ StorageKey key5_origin3 = StorageKey(origin3);
+ StorageKey key6_origin4 = StorageKey(origin4);
+ EXPECT_TRUE(IsOpaque(key4_origin3));
+ EXPECT_TRUE(IsOpaque(key5_origin3));
+ EXPECT_TRUE(IsOpaque(key6_origin4));
+
+ StorageKey key7_origin1_nonce1 = StorageKey::CreateWithNonce(origin1, nonce1);
+ StorageKey key8_origin1_nonce1 = StorageKey::CreateWithNonce(origin1, nonce1);
+ StorageKey key9_origin1_nonce2 = StorageKey::CreateWithNonce(origin1, nonce2);
+ StorageKey key10_origin2_nonce1 =
+ StorageKey::CreateWithNonce(origin2, nonce1);
+
+ // All are equivalent to themselves
+ EXPECT_EQ(key1_origin1, key1_origin1);
+ EXPECT_EQ(key2_origin1, key2_origin1);
+ EXPECT_EQ(key3_origin2, key3_origin2);
+ EXPECT_EQ(key4_origin3, key4_origin3);
+ EXPECT_EQ(key5_origin3, key5_origin3);
+ EXPECT_EQ(key6_origin4, key6_origin4);
+ EXPECT_EQ(key7_origin1_nonce1, key7_origin1_nonce1);
+ EXPECT_EQ(key8_origin1_nonce1, key8_origin1_nonce1);
+ EXPECT_EQ(key9_origin1_nonce2, key9_origin1_nonce2);
+ EXPECT_EQ(key10_origin2_nonce1, key10_origin2_nonce1);
+
+ // StorageKeys created from the same origins are equivalent.
+ EXPECT_EQ(key1_origin1, key2_origin1);
+ EXPECT_EQ(key4_origin3, key5_origin3);
+
+ // StorageKeys created from different origins are not equivalent.
+ EXPECT_NE(key1_origin1, key3_origin2);
+ EXPECT_NE(key4_origin3, key6_origin4);
+ EXPECT_NE(key7_origin1_nonce1, key10_origin2_nonce1);
+
+ // StorageKeys created from the same origins and nonces are equivalent.
+ EXPECT_EQ(key7_origin1_nonce1, key8_origin1_nonce1);
+
+ // StorageKeys created from different nonces are not equivalent.
+ EXPECT_NE(key7_origin1_nonce1, key9_origin1_nonce2);
+
+ // StorageKeys created from different origin and different nonces are not
+ // equivalent.
+ EXPECT_NE(key9_origin1_nonce2, key10_origin2_nonce1);
+}
+
+// Test that StorageKeys Serialize to the expected value.
+TEST(StorageKeyTest, Serialize) {
+ struct {
+ const char* origin_str;
+ const char* expected_serialization;
+ } kTestCases[] = {
+ {"https://example.com/", "https://example.com/"},
+ // Trailing slash is added.
+ {"https://example.com", "https://example.com/"},
+ // Subdomains are preserved.
+ {"http://sub.test.example/", "http://sub.test.example/"},
+ // file: origins all serialize to "file:///"
+ {"file:///", "file:///"},
+ {"file:///foo/bar", "file:///"},
+ {"file://example.fileshare.com/foo/bar", "file:///"},
+ };
+
+ for (const auto& test : kTestCases) {
+ SCOPED_TRACE(test.origin_str);
+ StorageKey key(url::Origin::Create(GURL(test.origin_str)));
+ EXPECT_EQ(test.expected_serialization, key.Serialize());
+ }
+}
+
+TEST(StorageKeyTest, SerializeForLocalStorage) {
+ struct {
+ const char* origin_str;
+ const char* expected_serialization;
+ } kTestCases[] = {
+ // Trailing slash is removed.
+ {"https://example.com/", "https://example.com"},
+ {"https://example.com", "https://example.com"},
+ // Subdomains are preserved.
+ {"http://sub.test.example/", "http://sub.test.example"},
+ // file: origins all serialize to "file://"
+ {"file://", "file://"},
+ {"file:///foo/bar", "file://"},
+ {"file://example.fileshare.com/foo/bar", "file://"},
+ };
+
+ for (const auto& test : kTestCases) {
+ SCOPED_TRACE(test.origin_str);
+ StorageKey key(url::Origin::Create(GURL(test.origin_str)));
+ EXPECT_EQ(test.expected_serialization, key.SerializeForLocalStorage());
+ }
+}
+
+// Test that deserialized StorageKeys are valid/opaque as expected.
+TEST(StorageKeyTest, Deserialize) {
+ std::string example = "https://example.com/";
+ std::string test = "https://test.example/";
+ std::string wrong = "I'm not a valid URL.";
+
+ absl::optional<StorageKey> key1 = StorageKey::Deserialize(example);
+ absl::optional<StorageKey> key2 = StorageKey::Deserialize(test);
+ absl::optional<StorageKey> key3 = StorageKey::Deserialize(wrong);
+ absl::optional<StorageKey> key4 = StorageKey::Deserialize(std::string());
+
+ ASSERT_TRUE(key1.has_value());
+ EXPECT_FALSE(IsOpaque(*key1));
+ ASSERT_TRUE(key2.has_value());
+ EXPECT_FALSE(IsOpaque(*key2));
+ EXPECT_FALSE(key3.has_value());
+ EXPECT_FALSE(key4.has_value());
+}
+
+// Test that string -> StorageKey test function performs as expected.
+TEST(StorageKeyTest, CreateFromStringForTesting) {
+ std::string example = "https://example.com/";
+ std::string wrong = "I'm not a valid URL.";
+
+ StorageKey key1 = StorageKey::CreateFromStringForTesting(example);
+ StorageKey key2 = StorageKey::CreateFromStringForTesting(wrong);
+ StorageKey key3 = StorageKey::CreateFromStringForTesting(std::string());
+
+ EXPECT_FALSE(IsOpaque(key1));
+ EXPECT_EQ(key1, StorageKey(url::Origin::Create(GURL(example))));
+ EXPECT_TRUE(IsOpaque(key2));
+ EXPECT_TRUE(IsOpaque(key3));
+}
+
+// Test that a StorageKey, constructed by deserializing another serialized
+// StorageKey, is equivalent to the original.
+TEST(StorageKeyTest, SerializeDeserialize) {
+ const char* kTestCases[] = {"https://example.com", "https://sub.test.example",
+ "file://", "file://example.fileshare.com"};
+
+ for (const char* test : kTestCases) {
+ SCOPED_TRACE(test);
+ url::Origin origin = url::Origin::Create(GURL(test));
+ StorageKey key(origin);
+ std::string key_string = key.Serialize();
+ std::string key_string_for_local_storage = key.SerializeForLocalStorage();
+ absl::optional<StorageKey> key_deserialized =
+ StorageKey::Deserialize(key_string);
+ absl::optional<StorageKey> key_deserialized_from_local_storage =
+ StorageKey::Deserialize(key_string_for_local_storage);
+
+ ASSERT_TRUE(key_deserialized.has_value());
+ ASSERT_TRUE(key_deserialized_from_local_storage.has_value());
+ if (origin.scheme() != "file") {
+ EXPECT_EQ(key, *key_deserialized);
+ EXPECT_EQ(key, *key_deserialized_from_local_storage);
+ } else {
+ // file origins are all collapsed to file:// by serialization.
+ EXPECT_EQ(StorageKey(url::Origin::Create(GURL("file://"))),
+ *key_deserialized);
+ EXPECT_EQ(StorageKey(url::Origin::Create(GURL("file://"))),
+ *key_deserialized_from_local_storage);
+ }
+ }
+}
+
+TEST(StorageKeyTest, IsThirdPartyStoragePartitioningEnabled) {
+ EXPECT_FALSE(StorageKey::IsThirdPartyStoragePartitioningEnabled());
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kThirdPartyStoragePartitioning);
+ EXPECT_TRUE(StorageKey::IsThirdPartyStoragePartitioningEnabled());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/switches.cc b/chromium/third_party/blink/common/switches.cc
index 5cab2344af3..cde05734c6f 100644
--- a/chromium/third_party/blink/common/switches.cc
+++ b/chromium/third_party/blink/common/switches.cc
@@ -113,13 +113,6 @@ const char kMinHeightForGpuRasterTile[] = "min-height-for-gpu-raster-tile";
// signal to dismiss a splash screen.
const char kNetworkQuietTimeout[] = "network-quiet-timeout";
-// Override the default value for the 'passive' field in javascript
-// addEventListener calls. Values are defined as:
-// 'documentonlytrue' to set the default be true only for document level nodes.
-// 'true' to set the default to be true on all nodes (when not specified).
-// 'forcealltrue' to force the value on all nodes.
-const char kPassiveListenersDefault[] = "passive-listeners-default";
-
// Visibly render a border around layout shift rects in the web page to help
// debug and study layout shifts.
const char kShowLayoutShiftRegions[] = "show-layout-shift-regions";
@@ -133,13 +126,10 @@ const char kShowPaintRects[] = "show-paint-rects";
// the platform default is used.
const char kTouchTextSelectionStrategy[] = "touch-selection-strategy";
-// Used to communicate managed policy for the UserAgentClientHint feature.
-// This feature is typically controlled by base::Feature (see
-// renderer/platform/scheduler/common/features.*) but requires an enterprise
-// policy override.
-
-extern const char kUserAgentClientHintDisable[] =
- "user-agent-client-hint-disable";
+// Comma-separated list of origins that can use SharedArrayBuffer without
+// enabling cross-origin isolation.
+const char kSharedArrayBufferAllowedOrigins[] =
+ "shared-array-buffer-allowed-origins";
} // namespace switches
} // namespace blink
diff --git a/chromium/third_party/blink/common/tokens/multi_token_unittest.cc b/chromium/third_party/blink/common/tokens/multi_token_unittest.cc
index 1305e68b3fa..2e2e3535d43 100644
--- a/chromium/third_party/blink/common/tokens/multi_token_unittest.cc
+++ b/chromium/third_party/blink/common/tokens/multi_token_unittest.cc
@@ -6,15 +6,15 @@
#include <algorithm>
+#include "base/types/token_type.h"
#include "base/unguessable_token.h"
-#include "base/util/type_safety/token_type.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
-using FooToken = util::TokenType<class FooTokenTag>;
-using BarToken = util::TokenType<class BarTokenTag>;
-using BazToken = util::TokenType<class BazTokenTag>;
+using FooToken = base::TokenType<class FooTokenTag>;
+using BarToken = base::TokenType<class BarTokenTag>;
+using BazToken = base::TokenType<class BazTokenTag>;
// Test MultiTokenVariantCount.
static_assert(internal::MultiTokenVariantCount<FooToken, BarToken>::kValue == 2,
diff --git a/chromium/third_party/blink/common/unique_name/unique_name_helper.cc b/chromium/third_party/blink/common/unique_name/unique_name_helper.cc
index e3ae497876d..064592f768e 100644
--- a/chromium/third_party/blink/common/unique_name/unique_name_helper.cc
+++ b/chromium/third_party/blink/common/unique_name/unique_name_helper.cc
@@ -8,8 +8,8 @@
#include <utility>
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
diff --git a/chromium/third_party/blink/common/use_counter/use_counter_feature.cc b/chromium/third_party/blink/common/use_counter/use_counter_feature.cc
index 45f9f37b1ed..3ffd8c60019 100644
--- a/chromium/third_party/blink/common/use_counter/use_counter_feature.cc
+++ b/chromium/third_party/blink/common/use_counter/use_counter_feature.cc
@@ -34,6 +34,8 @@ bool UseCounterFeature::IsValid() const {
mojom::CSSSampleId::kMaxValue) +
1;
case mojom::UseCounterFeatureType::kPermissionsPolicyViolationEnforce:
+ case mojom::UseCounterFeatureType::kPermissionsPolicyHeader:
+ case mojom::UseCounterFeatureType::kPermissionsPolicyIframeAttribute:
return value_ < static_cast<UseCounterFeature::EnumValue>(
mojom::PermissionsPolicyFeature::kMaxValue) +
1;
diff --git a/chromium/third_party/blink/common/use_counter/use_counter_feature_mojom_traits.cc b/chromium/third_party/blink/common/use_counter/use_counter_feature_mojom_traits.cc
index 755ee3a9328..2ac239b2f69 100644
--- a/chromium/third_party/blink/common/use_counter/use_counter_feature_mojom_traits.cc
+++ b/chromium/third_party/blink/common/use_counter/use_counter_feature_mojom_traits.cc
@@ -25,6 +25,8 @@ bool IsReservedFeature(const blink::UseCounterFeature& feature) {
blink::mojom::CSSSampleId::kTotalPagesMeasured);
case blink::mojom::UseCounterFeatureType::
kPermissionsPolicyViolationEnforce:
+ case blink::mojom::UseCounterFeatureType::kPermissionsPolicyHeader:
+ case blink::mojom::UseCounterFeatureType::kPermissionsPolicyIframeAttribute:
return feature.value() ==
static_cast<blink::UseCounterFeature::EnumValue>(
blink::mojom::PermissionsPolicyFeature::kNotFound);
diff --git a/chromium/third_party/blink/common/use_counter/use_counter_feature_tracker.cc b/chromium/third_party/blink/common/use_counter/use_counter_feature_tracker.cc
index 899bdce79c9..010fe7ae5f0 100644
--- a/chromium/third_party/blink/common/use_counter/use_counter_feature_tracker.cc
+++ b/chromium/third_party/blink/common/use_counter/use_counter_feature_tracker.cc
@@ -5,6 +5,12 @@
#include "third_party/blink/public/common/use_counter/use_counter_feature_tracker.h"
namespace blink {
+namespace {
+template <size_t N>
+bool BitsetContains(const std::bitset<N>& lhs, const std::bitset<N>& rhs) {
+ return (lhs & rhs) == rhs;
+}
+} // namespace
using FeatureType = mojom::UseCounterFeatureType;
@@ -18,6 +24,10 @@ bool UseCounterFeatureTracker::Test(const UseCounterFeature& feature) const {
return animated_css_properties_.test(feature.value());
case FeatureType::kPermissionsPolicyViolationEnforce:
return violated_permissions_policy_features_.test(feature.value());
+ case FeatureType::kPermissionsPolicyIframeAttribute:
+ return iframe_permissions_policy_features_.test(feature.value());
+ case FeatureType::kPermissionsPolicyHeader:
+ return header_permissions_policy_features_.test(feature.value());
}
}
@@ -49,6 +59,16 @@ std::vector<UseCounterFeature> UseCounterFeatureTracker::GetRecordedFeatures()
if (violated_permissions_policy_features_.test(i))
ret.push_back({FeatureType::kPermissionsPolicyViolationEnforce, i});
}
+
+ for (uint32_t i = 0; i < iframe_permissions_policy_features_.size(); i++) {
+ if (iframe_permissions_policy_features_.test(i))
+ ret.push_back({FeatureType::kPermissionsPolicyIframeAttribute, i});
+ }
+
+ for (uint32_t i = 0; i < header_permissions_policy_features_.size(); i++) {
+ if (header_permissions_policy_features_.test(i))
+ ret.push_back({FeatureType::kPermissionsPolicyHeader, i});
+ }
return ret;
}
@@ -57,6 +77,14 @@ void UseCounterFeatureTracker::ResetForTesting(
Set(feature, false);
}
+bool UseCounterFeatureTracker::ContainsForTesting(
+ const UseCounterFeatureTracker& other) const {
+ return BitsetContains(web_features_, other.web_features_) &&
+ BitsetContains(css_properties_, other.css_properties_) &&
+ BitsetContains(animated_css_properties_,
+ other.animated_css_properties_);
+}
+
void UseCounterFeatureTracker::Set(const UseCounterFeature& feature,
bool value) {
switch (feature.type()) {
@@ -72,6 +100,12 @@ void UseCounterFeatureTracker::Set(const UseCounterFeature& feature,
case FeatureType::kPermissionsPolicyViolationEnforce:
violated_permissions_policy_features_[feature.value()] = value;
break;
+ case FeatureType::kPermissionsPolicyIframeAttribute:
+ iframe_permissions_policy_features_[feature.value()] = value;
+ break;
+ case FeatureType::kPermissionsPolicyHeader:
+ header_permissions_policy_features_[feature.value()] = value;
+ break;
}
}
diff --git a/chromium/third_party/blink/common/user_agent/user_agent_metadata.cc b/chromium/third_party/blink/common/user_agent/user_agent_metadata.cc
index f4fcbcdc54c..466f6556175 100644
--- a/chromium/third_party/blink/common/user_agent/user_agent_metadata.cc
+++ b/chromium/third_party/blink/common/user_agent/user_agent_metadata.cc
@@ -61,6 +61,7 @@ absl::optional<std::string> UserAgentMetadata::Marshal(
out.WriteString(in->architecture);
out.WriteString(in->model);
out.WriteBool(in->mobile);
+ out.WriteString(in->bitness);
return std::string(reinterpret_cast<const char*>(out.data()), out.size());
}
@@ -102,6 +103,8 @@ absl::optional<UserAgentMetadata> UserAgentMetadata::Demarshal(
return absl::nullopt;
if (!in.ReadBool(&out.mobile))
return absl::nullopt;
+ if (!in.ReadString(&out.bitness))
+ return absl::nullopt;
return absl::make_optional(std::move(out));
}
@@ -114,7 +117,7 @@ bool operator==(const UserAgentMetadata& a, const UserAgentMetadata& b) {
a.full_version == b.full_version && a.platform == b.platform &&
a.platform_version == b.platform_version &&
a.architecture == b.architecture && a.model == b.model &&
- a.mobile == b.mobile;
+ a.mobile == b.mobile && a.bitness == b.bitness;
}
bool operator==(const UserAgentOverride& a, const UserAgentOverride& b) {
diff --git a/chromium/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc b/chromium/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc
index 4669b655e82..80b8e63dff3 100644
--- a/chromium/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc
+++ b/chromium/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc
@@ -24,6 +24,7 @@ blink::UserAgentMetadata MakeToEncode() {
to_encode.architecture = "Z80";
to_encode.model = "unofficial";
to_encode.mobile = false;
+ to_encode.bitness = "8";
return to_encode;
}
diff --git a/chromium/third_party/blink/common/user_agent/user_agent_mojom_traits.cc b/chromium/third_party/blink/common/user_agent/user_agent_mojom_traits.cc
index a490f9db089..ed2ebbeeaa6 100644
--- a/chromium/third_party/blink/common/user_agent/user_agent_mojom_traits.cc
+++ b/chromium/third_party/blink/common/user_agent/user_agent_mojom_traits.cc
@@ -53,6 +53,10 @@ bool StructTraits<blink::mojom::UserAgentMetadataDataView,
out->model = string;
out->mobile = data.mobile();
+ if (!data.ReadBitness(&string))
+ return false;
+ out->bitness = string;
+
return true;
}
diff --git a/chromium/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/chromium/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
index ab2d320a407..a264ef99beb 100644
--- a/chromium/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
+++ b/chromium/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
@@ -7,7 +7,6 @@
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
-#include "third_party/blink/public/mojom/widget/screen_info.mojom.h"
#include "url/mojom/url_gurl_mojom_traits.h"
namespace mojo {
@@ -48,7 +47,9 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
&out->low_priority_iframes_threshold) ||
!data.ReadNetworkQualityEstimatorWebHoldback(
&out->network_quality_estimator_web_holdback) ||
- !data.ReadWebAppScope(&out->web_app_scope)
+ !data.ReadWebAppScope(&out->web_app_scope) ||
+ !data.ReadLitepageSubresourceRedirectOrigin(
+ &out->litepage_subresource_redirect_origin)
#if defined(OS_ANDROID)
|| !data.ReadDefaultVideoPosterUrl(&out->default_video_poster_url)
#endif
@@ -99,6 +100,7 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
out->hide_scrollbars = data.hide_scrollbars();
out->accelerated_2d_canvas_enabled = data.accelerated_2d_canvas_enabled();
out->new_canvas_2d_api_enabled = data.new_canvas_2d_api_enabled();
+ out->canvas_2d_layers_enabled = data.canvas_2d_layers_enabled();
out->antialiased_2d_canvas_disabled = data.antialiased_2d_canvas_disabled();
out->antialiased_clips_2d_canvas_enabled =
data.antialiased_clips_2d_canvas_enabled();
diff --git a/chromium/third_party/blink/common/widget/screen_info.cc b/chromium/third_party/blink/common/widget/screen_info.cc
deleted file mode 100644
index 19193bb2e72..00000000000
--- a/chromium/third_party/blink/common/widget/screen_info.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/widget/screen_info.h"
-
-namespace blink {
-
-ScreenInfo::ScreenInfo() = default;
-ScreenInfo::ScreenInfo(const ScreenInfo& other) = default;
-ScreenInfo::~ScreenInfo() = default;
-ScreenInfo& ScreenInfo::operator=(const ScreenInfo& other) = default;
-
-bool ScreenInfo::operator==(const ScreenInfo& other) const {
- return device_scale_factor == other.device_scale_factor &&
- display_color_spaces == other.display_color_spaces &&
- depth == other.depth &&
- depth_per_component == other.depth_per_component &&
- is_monochrome == other.is_monochrome &&
- display_frequency == other.display_frequency && rect == other.rect &&
- available_rect == other.available_rect &&
- orientation_type == other.orientation_type &&
- orientation_angle == other.orientation_angle &&
- is_extended == other.is_extended && is_primary == other.is_primary &&
- is_internal == other.is_internal && display_id == other.display_id;
-}
-
-bool ScreenInfo::operator!=(const ScreenInfo& other) const {
- return !operator==(other);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/common/widget/screen_info_mojom_traits.cc b/chromium/third_party/blink/common/widget/screen_info_mojom_traits.cc
deleted file mode 100644
index 4172b73850a..00000000000
--- a/chromium/third_party/blink/common/widget/screen_info_mojom_traits.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/widget/screen_info_mojom_traits.h"
-
-#include "ui/gfx/geometry/mojom/geometry.mojom.h"
-#include "ui/gfx/mojom/display_color_spaces.mojom.h"
-
-namespace mojo {
-
-bool StructTraits<blink::mojom::ScreenInfoDataView, blink::ScreenInfo>::Read(
- blink::mojom::ScreenInfoDataView data,
- blink::ScreenInfo* out) {
- if (!data.ReadDisplayColorSpaces(&out->display_color_spaces) ||
- !data.ReadRect(&out->rect) ||
- !data.ReadAvailableRect(&out->available_rect))
- return false;
-
- out->device_scale_factor = data.device_scale_factor();
- out->depth = data.depth();
- out->depth_per_component = data.depth_per_component();
- out->is_monochrome = data.is_monochrome();
- out->display_frequency = data.display_frequency();
- out->orientation_type = data.orientation_type();
- out->orientation_angle = data.orientation_angle();
- out->is_extended = data.is_extended();
- out->is_primary = data.is_primary();
- out->is_internal = data.is_internal();
- out->display_id = data.display_id();
- return true;
-}
-
-} // namespace mojo
diff --git a/chromium/third_party/blink/common/widget/screen_infos.cc b/chromium/third_party/blink/common/widget/screen_infos.cc
deleted file mode 100644
index e990f21a27b..00000000000
--- a/chromium/third_party/blink/common/widget/screen_infos.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/widget/screen_infos.h"
-
-namespace blink {
-
-ScreenInfos::ScreenInfos() = default;
-ScreenInfos::ScreenInfos(const ScreenInfo& screen_info)
- : screen_infos{screen_info}, current_display_id(screen_info.display_id) {}
-ScreenInfos::ScreenInfos(const ScreenInfos& other) = default;
-ScreenInfos::~ScreenInfos() = default;
-ScreenInfos& ScreenInfos::operator=(const ScreenInfos& other) = default;
-bool ScreenInfos::operator==(const ScreenInfos& other) const {
- return screen_infos == other.screen_infos &&
- current_display_id == other.current_display_id;
-}
-
-bool ScreenInfos::operator!=(const ScreenInfos& other) const {
- return !operator==(other);
-}
-
-ScreenInfo& ScreenInfos::mutable_current() {
- return const_cast<ScreenInfo&>(
- const_cast<const ScreenInfos*>(this)->current());
-}
-
-const ScreenInfo& ScreenInfos::current() const {
- const auto& current_screen_info = base::ranges::find(
- screen_infos, current_display_id, &ScreenInfo::display_id);
- CHECK(current_screen_info != screen_infos.end());
- return *current_screen_info;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/common/widget/screen_infos_mojom_traits.cc b/chromium/third_party/blink/common/widget/screen_infos_mojom_traits.cc
deleted file mode 100644
index 7e3f9709d15..00000000000
--- a/chromium/third_party/blink/common/widget/screen_infos_mojom_traits.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/widget/screen_infos_mojom_traits.h"
-
-#include "third_party/blink/public/mojom/widget/screen_info.mojom.h"
-
-namespace mojo {
-
-// static
-bool StructTraits<blink::mojom::ScreenInfosDataView, blink::ScreenInfos>::Read(
- blink::mojom::ScreenInfosDataView data,
- blink::ScreenInfos* out) {
- if (!data.ReadScreenInfos(&out->screen_infos))
- return false;
- out->current_display_id = data.current_display_id();
-
- // Ensure ScreenInfo ids are unique and contain the `current_display_id`.
- base::flat_set<int64_t> display_ids;
- display_ids.reserve(out->screen_infos.size());
- for (const auto& screen_info : out->screen_infos) {
- if (!display_ids.insert(screen_info.display_id).second)
- return false;
- }
- return display_ids.find(out->current_display_id) != display_ids.end();
-}
-
-} // namespace mojo
diff --git a/chromium/third_party/blink/common/widget/screen_infos_mojom_traits_unittest.cc b/chromium/third_party/blink/common/widget/screen_infos_mojom_traits_unittest.cc
deleted file mode 100644
index ac08537c10e..00000000000
--- a/chromium/third_party/blink/common/widget/screen_infos_mojom_traits_unittest.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/widget/screen_infos_mojom_traits.h"
-
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/widget/screen_infos.h"
-#include "third_party/blink/public/mojom/widget/screen_infos.mojom.h"
-
-namespace {
-
-using mojo::test::SerializeAndDeserialize;
-
-TEST(StructTraitsTest, ScreenInfosRoundtripValid) {
- blink::ScreenInfos i, o;
- i.screen_infos = {blink::ScreenInfo()};
- EXPECT_EQ(i.current_display_id, i.screen_infos[0].display_id);
- ASSERT_TRUE(SerializeAndDeserialize<blink::mojom::ScreenInfos>(i, o));
- EXPECT_EQ(i, o);
-}
-
-TEST(StructTraitsTest, ScreenInfosMustBeNonEmpty) {
- // These fail; screen_infos must contain at least one element.
- blink::mojom::ScreenInfosPtr i1 = blink::mojom::ScreenInfos::New();
- blink::ScreenInfos i2, o;
- ASSERT_FALSE(SerializeAndDeserialize<blink::mojom::ScreenInfos>(i1, o));
- EXPECT_DEATH(blink::mojom::ScreenInfos::SerializeAsMessage(&i2), "");
-}
-
-TEST(StructTraitsTest, ScreenInfosSelectedDisplayIdMustBePresent) {
- // These fail; current_display_id must match a screen_infos element.
- blink::mojom::ScreenInfosPtr i1 = blink::mojom::ScreenInfos::New();
- blink::ScreenInfos i2, o;
- i1->screen_infos = {blink::ScreenInfo()};
- i1->current_display_id = i1->screen_infos[0].display_id + 123;
- i2.screen_infos = {blink::ScreenInfo()};
- i2.current_display_id = i2.screen_infos[0].display_id + 123;
- EXPECT_NE(i1->current_display_id, i1->screen_infos[0].display_id);
- EXPECT_NE(i2.current_display_id, i2.screen_infos[0].display_id);
- ASSERT_FALSE(SerializeAndDeserialize<blink::mojom::ScreenInfos>(i1, o));
- EXPECT_DEATH(blink::mojom::ScreenInfos::SerializeAsMessage(&i2), "");
-}
-
-TEST(StructTraitsTest, ScreenInfosDisplayIdsMustBeUnique) {
- // These fail; screen_infos must use unique display_id values.
- blink::mojom::ScreenInfosPtr i1 = blink::mojom::ScreenInfos::New();
- blink::ScreenInfos i2, o;
- i1->screen_infos = {blink::ScreenInfo(), blink::ScreenInfo()};
- i2.screen_infos = {blink::ScreenInfo(), blink::ScreenInfo()};
- EXPECT_EQ(i1->screen_infos[0].display_id, i1->screen_infos[1].display_id);
- EXPECT_EQ(i2.screen_infos[0].display_id, i2.screen_infos[1].display_id);
- ASSERT_FALSE(SerializeAndDeserialize<blink::mojom::ScreenInfos>(i1, o));
- EXPECT_DEATH(blink::mojom::ScreenInfos::SerializeAsMessage(&i2), "");
-}
-
-} // namespace
diff --git a/chromium/third_party/blink/common/widget/visual_properties.cc b/chromium/third_party/blink/common/widget/visual_properties.cc
index 433ca5954c9..55932091baf 100644
--- a/chromium/third_party/blink/common/widget/visual_properties.cc
+++ b/chromium/third_party/blink/common/widget/visual_properties.cc
@@ -33,7 +33,8 @@ bool VisualProperties::operator==(const VisualProperties& other) const {
page_scale_factor == other.page_scale_factor &&
compositing_scale_factor == other.compositing_scale_factor &&
root_widget_window_segments == other.root_widget_window_segments &&
- is_pinch_gesture_active == other.is_pinch_gesture_active;
+ is_pinch_gesture_active == other.is_pinch_gesture_active &&
+ window_controls_overlay_rect == other.window_controls_overlay_rect;
}
bool VisualProperties::operator!=(const VisualProperties& other) const {
diff --git a/chromium/third_party/blink/common/widget/visual_properties_mojom_traits.cc b/chromium/third_party/blink/common/widget/visual_properties_mojom_traits.cc
index d378def431a..9676090aadb 100644
--- a/chromium/third_party/blink/common/widget/visual_properties_mojom_traits.cc
+++ b/chromium/third_party/blink/common/widget/visual_properties_mojom_traits.cc
@@ -6,7 +6,7 @@
#include "cc/mojom/browser_controls_params.mojom.h"
#include "services/viz/public/mojom/compositing/local_surface_id.mojom.h"
-#include "third_party/blink/public/mojom/widget/screen_infos.mojom.h"
+#include "ui/display/mojom/screen_infos.mojom.h"
namespace mojo {
@@ -24,6 +24,7 @@ bool StructTraits<
!data.ReadBrowserControlsParams(&out->browser_controls_params) ||
!data.ReadLocalSurfaceId(&out->local_surface_id) ||
!data.ReadRootWidgetWindowSegments(&out->root_widget_window_segments) ||
+ !data.ReadWindowControlsOverlayRect(&out->window_controls_overlay_rect) ||
data.page_scale_factor() <= 0 || data.compositing_scale_factor() <= 0)
return false;
out->auto_resize_enabled = data.auto_resize_enabled();
diff --git a/chromium/third_party/blink/manual_tests/forms/calendar-picker.html b/chromium/third_party/blink/manual_tests/forms/calendar-picker.html
index 002cdf4ddee..39c9e56db2f 100644
--- a/chromium/third_party/blink/manual_tests/forms/calendar-picker.html
+++ b/chromium/third_party/blink/manual_tests/forms/calendar-picker.html
@@ -277,35 +277,33 @@ function createParam() {
}
};
+function includeFile(file, isJs) {
+ const doc = document.getElementsByTagName('iframe')[0].contentDocument;
+ file = '../../renderer/core/html/forms/resources/' + file + '?' + (new Date()).getTime();
+ var element;
+ if (isJs) {
+ element = doc.createElement('script');
+ element.src = file;
+ } else {
+ element = doc.createElement('link');
+ element.rel = 'stylesheet';
+ element.href = file;
+ }
+ doc.head.appendChild(element);
+}
+
function openCalendar() {
var frame = document.getElementsByTagName('iframe')[0];
- var doc = frame.contentDocument;
- doc.documentElement.innerHTML = '<head></head><body><div id=main>Loading...</div></body>';
- var commonCssLink = doc.createElement('link');
- commonCssLink.rel = 'stylesheet';
- commonCssLink.href = '../../renderer/core/html/forms/resources/pickerCommon.css?' + (new Date()).getTime();
- doc.head.appendChild(commonCssLink);
- var buttonCssLink = doc.createElement('link');
- buttonCssLink.rel = 'stylesheet';
- buttonCssLink.href = '../../renderer/core/html/forms/resources/pickerButton.css?' + (new Date()).getTime();
- doc.head.appendChild(buttonCssLink);
- var suggestionPickerCssLink = doc.createElement('link');
- suggestionPickerCssLink.rel = 'stylesheet';
- suggestionPickerCssLink.href = '../../renderer/core/html/forms/resources/suggestionPicker.css?' + (new Date()).getTime();
- doc.head.appendChild(suggestionPickerCssLink);
- var link = doc.createElement('link');
- link.rel = 'stylesheet';
- link.href = '../../renderer/core/html/forms/resources/calendarPicker.css?' + (new Date()).getTime();
- doc.head.appendChild(link);
- var commonJsScript = doc.createElement('script');
- commonJsScript.src = '../../renderer/core/html/forms/resources/pickerCommon.js?' + (new Date()).getTime();
- doc.body.appendChild(commonJsScript);
- var suggestionPickerJsScript = doc.createElement('script');
- suggestionPickerJsScript.src = '../../renderer/core/html/forms/resources/suggestionPicker.js?' + (new Date()).getTime();
- doc.body.appendChild(suggestionPickerJsScript);
- var script = doc.createElement('script');
- script.src = '../../renderer/core/html/forms/resources/calendarPicker.js?' + (new Date()).getTime();
- doc.body.appendChild(script);
+ frame.contentDocument.documentElement.innerHTML = '<head></head><body><div id=main>Loading...</div></body>';
+
+ includeFile('pickerCommon.css', /*isJs=*/false);
+ includeFile('suggestionPicker.css', /*isJs=*/false);
+ includeFile('calendarPicker.css', /*isJs=*/false);
+
+ includeFile('pickerCommon.js', /*isJs=*/true);
+ includeFile('suggestionPicker.js', /*isJs=*/true);
+ includeFile('month_picker.js', /*isJs=*/true);
+ includeFile('calendarPicker.js', /*isJs=*/true);
var pagePopupController = {
setValueAndClosePopup: function(numValue, stringValue) {
diff --git a/chromium/third_party/blink/manual_tests/svg-text-selection.svg b/chromium/third_party/blink/manual_tests/svg-text-selection.svg
deleted file mode 100644
index 4c34d24f97a..00000000000
--- a/chromium/third_party/blink/manual_tests/svg-text-selection.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xhtml="http://www.w3.org/1999/xhtml">
- <text x="0" y="100" fill="black" font-size="32">Selection will be constrained to this line.</text>
- <text x="0" y="200" fill="black" font-size="32">You should be able
- <tspan x="0" y="235">to select multiline here</tspan>
- <tspan x="0" y="270">See bug 12334</tspan>
- </text>
-</svg>
diff --git a/chromium/third_party/blink/public/BUILD.gn b/chromium/third_party/blink/public/BUILD.gn
index 784617ebcae..04a01b50edb 100644
--- a/chromium/third_party/blink/public/BUILD.gn
+++ b/chromium/third_party/blink/public/BUILD.gn
@@ -25,12 +25,16 @@ group("blink") {
"//third_party/blink/renderer/modules",
"//third_party/blink/renderer/platform",
]
+ if (use_blink_extensions_chromeos) {
+ deps += [ "//third_party/blink/renderer/extensions/chromeos" ]
+ }
}
group("test_support") {
testonly = true
public_deps = [
":test_headers",
+ "//third_party/blink/common:test_support",
"//third_party/blink/renderer/core/exported:test_support",
"//third_party/blink/renderer/modules/exported:test_support",
"//third_party/blink/renderer/modules/mediastream:test_support",
@@ -93,6 +97,7 @@ if (is_android) {
source_set("test_headers") {
testonly = true
sources = [
+ "common/origin_trials/scoped_test_origin_trial_policy.h",
"platform/scheduler/test/renderer_scheduler_test_support.h",
"platform/scheduler/test/web_fake_thread_scheduler.h",
"platform/scheduler/test/web_mock_thread_scheduler.h",
@@ -172,7 +177,6 @@ source_set("blink_headers") {
"platform/web_blob_info.h",
"platform/web_cache.h",
"platform/web_callbacks.h",
- "platform/web_client_hints_type.h",
"platform/web_code_cache_loader.h",
"platform/web_common.h",
"platform/web_computed_ax_tree.h",
@@ -213,7 +217,6 @@ source_set("blink_headers") {
"platform/web_graphics_context_3d_provider.h",
"platform/web_http_body.h",
"platform/web_http_header_visitor.h",
- "platform/web_http_load_info.h",
"platform/web_icon_sizes_parser.h",
"platform/web_image_generator.h",
"platform/web_impression.h",
@@ -221,6 +224,7 @@ source_set("blink_headers") {
"platform/web_inband_text_track_client.h",
"platform/web_input_event_result.h",
"platform/web_isolated_world_info.h",
+ "platform/web_loader_freeze_mode.h",
"platform/web_media_key_system_configuration.h",
"platform/web_media_key_system_media_capability.h",
"platform/web_media_player.h",
@@ -355,7 +359,6 @@ source_set("blink_headers") {
"web/web_no_state_prefetch_client.h",
"web/web_node.h",
"web/web_non_composited_widget_client.h",
- "web/web_optimization_guide_hints.h",
"web/web_option_element.h",
"web/web_origin_policy.h",
"web/web_page_popup.h",
@@ -439,6 +442,7 @@ source_set("blink_headers") {
"//services/service_manager/public/cpp",
"//skia",
"//third_party/blink/public/common",
+ "//third_party/blink/public/common:headers",
"//ui/accessibility:ax_base",
"//ui/base/cursor:cursor_base",
"//ui/base/dragdrop/mojom:mojom_shared",
diff --git a/chromium/third_party/blink/public/OWNERS b/chromium/third_party/blink/public/OWNERS
index 3dd00d11db9..f5a02b61e16 100644
--- a/chromium/third_party/blink/public/OWNERS
+++ b/chromium/third_party/blink/public/OWNERS
@@ -14,7 +14,6 @@ kinuko@chromium.org
mkwst@chromium.org
pdr@chromium.org
pfeldman@chromium.org
-rbyers@chromium.org
tkent@chromium.org
# NOTE: keep this in sync with lsc-owners-override@chromium.org owners
diff --git a/chromium/third_party/blink/public/blink_resources.grd b/chromium/third_party/blink/public/blink_resources.grd
index e04f43cae4c..5440815e362 100644
--- a/chromium/third_party/blink/public/blink_resources.grd
+++ b/chromium/third_party/blink/public/blink_resources.grd
@@ -9,7 +9,7 @@
<release seq="1">
<includes>
<!-- GRIT minimizes all CSS and Javascript -->
- <include name="IDR_UASTYLE_HTML_CSS" file="../renderer/core/html/resources/html.css" type="BINDATA" compress="gzip"/>
+ <include name="IDR_UASTYLE_HTML_CSS" file="../renderer/core/html/resources/html.css" flattenhtml="true" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_QUIRKS_CSS" file="../renderer/core/html/resources/quirks.css" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_VIEW_SOURCE_CSS" file="../renderer/core/css/view-source.css" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_THEME_CHROMIUM_ANDROID_CSS" file="../renderer/core/html/resources/android.css" type="BINDATA" compress="gzip"/>
@@ -19,9 +19,7 @@
<include name="IDR_UASTYLE_THEME_MAC_CSS" file="../renderer/core/html/resources/mac.css" type="BINDATA" compress="gzip"/>
</if>
<include name="IDR_UASTYLE_THEME_INPUT_MULTIPLE_FIELDS_CSS" file="../renderer/core/html/resources/input_multiple_fields.css" type="BINDATA" compress="gzip"/>
- <include name="IDR_UASTYLE_THEME_WIN_CSS" file="../renderer/core/html/resources/win.css" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_THEME_WIN_QUIRKS_CSS" file="../renderer/core/html/resources/win_quirks.css" type="BINDATA" compress="gzip"/>
- <include name="IDR_UASTYLE_THEME_CONTROLS_REFRESH_CSS" file="../renderer/core/html/resources/controls_refresh.css" flattenhtml="true" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_THEME_FORCED_COLORS_CSS" file="../renderer/core/html/resources/forced_colors.css" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_POPUP_CSS" file="../renderer/core/css/popup.css" type="BINDATA" compress="gzip"/>
<include name="IDR_UASTYLE_SVG_CSS" file="../renderer/core/css/svg.css" type="BINDATA" compress="gzip"/>
@@ -41,13 +39,11 @@
<include name="IDR_PICKER_COMMON_JS" file="../renderer/core/html/forms/resources/pickerCommon.js" type="BINDATA" compress="gzip"/>
<include name="IDR_PICKER_COMMON_CSS" file="../renderer/core/html/forms/resources/pickerCommon.css" type="BINDATA" compress="gzip"/>
<include name="IDR_CALENDAR_PICKER_CSS" file="../renderer/core/html/forms/resources/calendarPicker.css" type="BINDATA" compress="gzip"/>
- <include name="IDR_CALENDAR_PICKER_REFRESH_CSS" file="../renderer/core/html/forms/resources/calendar_picker_refresh.css" type="BINDATA" compress="gzip"/>
<include name="IDR_CALENDAR_PICKER_JS" file="../renderer/core/html/forms/resources/calendarPicker.js" type="BINDATA" compress="gzip"/>
<include name="IDR_MONTH_PICKER_JS" file="../renderer/core/html/forms/resources/month_picker.js" type="BINDATA" compress="gzip"/>
<include name="IDR_TIME_PICKER_CSS" file="../renderer/core/html/forms/resources/time_picker.css" type="BINDATA" compress="gzip"/>
<include name="IDR_TIME_PICKER_JS" file="../renderer/core/html/forms/resources/time_picker.js" type="BINDATA" compress="gzip"/>
<include name="IDR_DATETIMELOCAL_PICKER_JS" file="../renderer/core/html/forms/resources/datetimelocal_picker.js" type="BINDATA" compress="gzip"/>
- <include name="IDR_PICKER_BUTTON_CSS" file="../renderer/core/html/forms/resources/pickerButton.css" type="BINDATA" compress="gzip"/>
<include name="IDR_SUGGESTION_PICKER_CSS" file="../renderer/core/html/forms/resources/suggestionPicker.css" type="BINDATA" compress="gzip"/>
<include name="IDR_SUGGESTION_PICKER_JS" file="../renderer/core/html/forms/resources/suggestionPicker.js" type="BINDATA" compress="gzip"/>
<include name="IDR_COLOR_PICKER_COMMON_JS" file="../renderer/core/html/forms/resources/color_picker_common.js" type="BINDATA" compress="gzip"/>
diff --git a/chromium/third_party/blink/public/common/BUILD.gn b/chromium/third_party/blink/public/common/BUILD.gn
index 30bea4c2381..dd27f5b0b83 100644
--- a/chromium/third_party/blink/public/common/BUILD.gn
+++ b/chromium/third_party/blink/public/common/BUILD.gn
@@ -51,6 +51,7 @@ source_set("common_export") {
source_set("headers") {
visibility = [
":*",
+ "//android_webview/*",
"//chrome/*",
"//chromecast/*",
"//components/*",
@@ -73,6 +74,7 @@ source_set("headers") {
"cache_storage/cache_storage_utils.h",
"chrome_debug_urls.h",
"client_hints/client_hints.h",
+ "client_hints/enabled_client_hints.h",
"context_menu_data/context_menu_data.h",
"context_menu_data/context_menu_params_builder.h",
"context_menu_data/edit_flags.h",
@@ -120,6 +122,8 @@ source_set("headers") {
"input/web_pointer_properties.h",
"input/web_touch_event.h",
"input/web_touch_point.h",
+ "interest_group/interest_group.h",
+ "interest_group/interest_group_mojom_traits.h",
"loader/http_body_element_type.h",
"loader/inter_process_time_ticks_converter.h",
"loader/loader_constants.h",
@@ -163,15 +167,17 @@ source_set("headers") {
"mobile_metrics/mobile_friendliness.h",
"native_io/native_io_utils.h",
"navigation/impression.h",
+ "navigation/navigation_params.h",
+ "navigation/navigation_params_mojom_traits.h",
"navigation/navigation_policy.h",
"navigation/resource_intercept_policy.h",
- "net/ip_address_space_util.h",
"notifications/notification_constants.h",
"notifications/notification_mojom_traits.h",
"notifications/notification_resources.h",
"notifications/platform_notification_data.h",
"oom_intervention/oom_intervention_types.h",
"origin_trials/origin_trial_policy.h",
+ "origin_trials/origin_trial_public_key.h",
"origin_trials/trial_token.h",
"origin_trials/trial_token_result.h",
"origin_trials/trial_token_validator.h",
@@ -192,6 +198,8 @@ source_set("headers") {
"permissions_policy/policy_value.h",
"renderer_preferences/renderer_preferences.h",
"scheduler/web_scheduler_tracked_feature.h",
+ "scheme_registry.h",
+ "security/address_space_feature.h",
"security/protocol_handler_security_level.h",
"security/security_style.h",
"security_context/insecure_request_policy.h",
@@ -203,6 +211,7 @@ source_set("headers") {
"sms/webotp_constants.h",
"sms/webotp_service_destroyed_reason.h",
"sms/webotp_service_outcome.h",
+ "storage_key/storage_key.h",
"switches.h",
"thread_safe_browser_interface_broker_proxy.h",
"unique_name/unique_name_helper.h",
@@ -214,12 +223,11 @@ source_set("headers") {
"web_package/web_package_request_matcher.h",
"web_preferences/web_preferences.h",
"widget/device_emulation_params.h",
- "widget/screen_info.h",
- "widget/screen_infos.h",
"widget/visual_properties.h",
]
public_deps = [
+ "//base",
"//mojo/public/cpp/bindings",
"//services/metrics/public/cpp:metrics_cpp",
"//services/network/public/cpp:cpp",
@@ -231,6 +239,7 @@ source_set("headers") {
"//third_party/blink/public/mojom:mojom_modules_headers",
"//third_party/blink/public/mojom:mojom_platform_shared",
"//third_party/blink/public/mojom:web_bluetooth_mojo_bindings_headers",
+ "//ui/display/mojom",
"//ui/events:event_constants",
"//ui/events/types:headers",
"//ui/latency",
diff --git a/chromium/third_party/blink/public/common/DEPS b/chromium/third_party/blink/public/common/DEPS
index 85fb0c18917..21cea7fbb1d 100644
--- a/chromium/third_party/blink/public/common/DEPS
+++ b/chromium/third_party/blink/public/common/DEPS
@@ -15,13 +15,16 @@ include_rules = [
"+media",
"+mojo",
"+services/device/public/mojom",
+ "+services/network/public/cpp/resource_request.h",
"+services/network/public/cpp/resource_request_body.h",
"+services/network/public/cpp/shared_url_loader_factory.h",
"+services/network/public/mojom",
"+skia/public/mojom",
"+third_party/blink/public/common",
"+third_party/blink/public/mojom",
+ "+ui/base/clipboard/clipboard_sequence_number_token.h",
"+ui/base/pointer/pointer_device.h",
+ "+ui/base/page_transition_types.h",
"+ui/base/ui_base_types.h",
"+ui/events/event_constants.h",
"+ui/events/types",
diff --git a/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_provider.h b/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_provider.h
index 86b3c447428..111752119d0 100644
--- a/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_provider.h
+++ b/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_provider.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
@@ -51,6 +50,10 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceProvider {
explicit AssociatedInterfaceProvider(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ AssociatedInterfaceProvider(const AssociatedInterfaceProvider&) = delete;
+ AssociatedInterfaceProvider& operator=(const AssociatedInterfaceProvider&) =
+ delete;
+
~AssociatedInterfaceProvider();
// Passes an associated endpoint handle to the remote end to be bound to a
@@ -84,8 +87,6 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceProvider {
std::unique_ptr<LocalProvider> local_provider_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_registry.h b/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_registry.h
index de98489f69e..4c711ae5e6d 100644
--- a/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_registry.h
+++ b/chromium/third_party/blink/public/common/associated_interfaces/associated_interface_registry.h
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
@@ -37,6 +36,9 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceRegistry {
base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>;
AssociatedInterfaceRegistry();
+ AssociatedInterfaceRegistry(const AssociatedInterfaceRegistry&) = delete;
+ AssociatedInterfaceRegistry& operator=(const AssociatedInterfaceRegistry&) =
+ delete;
~AssociatedInterfaceRegistry();
// Adds an interface binder to the registry.
@@ -75,8 +77,6 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceRegistry {
std::map<std::string, Binder> interfaces_;
base::WeakPtrFactory<AssociatedInterfaceRegistry> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceRegistry);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/browser_interface_broker_proxy.h b/chromium/third_party/blink/public/common/browser_interface_broker_proxy.h
index 9590a356d92..f21083b69aa 100644
--- a/chromium/third_party/blink/public/common/browser_interface_broker_proxy.h
+++ b/chromium/third_party/blink/public/common/browser_interface_broker_proxy.h
@@ -18,6 +18,10 @@ namespace blink {
class BLINK_COMMON_EXPORT BrowserInterfaceBrokerProxy {
public:
BrowserInterfaceBrokerProxy() = default;
+ BrowserInterfaceBrokerProxy(const BrowserInterfaceBrokerProxy&) = delete;
+ BrowserInterfaceBrokerProxy& operator=(const BrowserInterfaceBrokerProxy&) =
+ delete;
+
void Bind(mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> broker,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> Reset(
@@ -53,8 +57,6 @@ class BLINK_COMMON_EXPORT BrowserInterfaceBrokerProxy {
std::map<std::string,
base::RepeatingCallback<void(mojo::ScopedMessagePipeHandle)>>;
mutable BinderMap binder_map_for_testing_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserInterfaceBrokerProxy);
};
// Returns an instance of BrowserInterfaceBrokerProxy that is safe to use but is
diff --git a/chromium/third_party/blink/public/common/client_hints/client_hints.h b/chromium/third_party/blink/public/common/client_hints/client_hints.h
index 6843776d477..ea732e8c14c 100644
--- a/chromium/third_party/blink/public/common/client_hints/client_hints.h
+++ b/chromium/third_party/blink/public/common/client_hints/client_hints.h
@@ -50,18 +50,6 @@ BLINK_COMMON_EXPORT extern const size_t kWebEffectiveConnectionTypeMappingCount;
std::string BLINK_COMMON_EXPORT
SerializeLangClientHint(const std::string& raw_language_list);
-// Filters a parsed accept-CH list to exclude clients hints support for which
-// is currently conditional on experiments:
-// Language hints will only be kept if |permit_lang_hints| is true;
-// UA-related ones if |permit_ua_hints| is.
-// Prefers-color-scheme ones if |permit_prefers_color_scheme_hints| is.
-BLINK_COMMON_EXPORT
-absl::optional<std::vector<network::mojom::WebClientHintsType>> FilterAcceptCH(
- absl::optional<std::vector<network::mojom::WebClientHintsType>> in,
- bool permit_lang_hints,
- bool permit_ua_hints,
- bool permit_prefers_color_scheme_hints);
-
// Indicates that a hint is sent by default, regardless of an opt-in.
BLINK_COMMON_EXPORT
bool IsClientHintSentByDefault(network::mojom::WebClientHintsType type);
diff --git a/chromium/third_party/blink/public/common/client_hints/enabled_client_hints.h b/chromium/third_party/blink/public/common/client_hints/enabled_client_hints.h
new file mode 100644
index 00000000000..70fac17a280
--- /dev/null
+++ b/chromium/third_party/blink/public/common/client_hints/enabled_client_hints.h
@@ -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.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_CLIENT_HINTS_ENABLED_CLIENT_HINTS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_CLIENT_HINTS_ENABLED_CLIENT_HINTS_H_
+
+#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+
+// EnabledClientHints stores all the client hints along with whether the hint
+// is enabled or not.
+class BLINK_COMMON_EXPORT EnabledClientHints {
+ public:
+ EnabledClientHints() = default;
+
+ // Returns true if the client hint should be sent on the HTTP request header,
+ // and returns false otherwise. Even if SetIsEnabled() is called on a client
+ // hint, it is still possible that IsEnabled() returns false, if some other
+ // conditions (such as a feature being toggled) indicate the client hint
+ // should not be sent.
+ //
+ // Returns false if `type` is not a valid WebClientHintsType value.
+ bool IsEnabled(network::mojom::WebClientHintsType type) const;
+
+ // Sets the client hint as enabled for sending in an HTTP request header. Even
+ // if the client hint header is set to enabled, it is still possible that
+ // other factors (such as feature toggles) could cause the client hint to not
+ // be sent, and in that case, IsEnabled() would return false.
+ //
+ // If `type` is not a valid WebClientHintsType value, nothing is changed (no
+ // client hints get enabled).
+ void SetIsEnabled(network::mojom::WebClientHintsType type, bool should_send);
+
+ private:
+ std::array<bool,
+ static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) +
+ 1>
+ enabled_types_{};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_CLIENT_HINTS_ENABLED_CLIENT_HINTS_H_
diff --git a/chromium/third_party/blink/public/common/context_menu_data/context_menu_data.h b/chromium/third_party/blink/public/common/context_menu_data/context_menu_data.h
index e13de5cf7d5..d86b2fa2dcf 100644
--- a/chromium/third_party/blink/public/common/context_menu_data/context_menu_data.h
+++ b/chromium/third_party/blink/public/common/context_menu_data/context_menu_data.h
@@ -34,6 +34,7 @@
#include <vector>
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/context_menu_data/menu_item_info.h"
#include "third_party/blink/public/common/input/web_menu_source_type.h"
#include "third_party/blink/public/common/navigation/impression.h"
diff --git a/chromium/third_party/blink/public/common/context_menu_data/context_menu_mojom_traits.h b/chromium/third_party/blink/public/common/context_menu_data/context_menu_mojom_traits.h
index 7a62e47dbde..60fd1775a61 100644
--- a/chromium/third_party/blink/public/common/context_menu_data/context_menu_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/context_menu_data/context_menu_mojom_traits.h
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
diff --git a/chromium/third_party/blink/public/common/features.h b/chromium/third_party/blink/public/common/features.h
index 810be9942f4..c23da05776d 100644
--- a/chromium/third_party/blink/public/common/features.h
+++ b/chromium/third_party/blink/public/common/features.h
@@ -18,12 +18,12 @@ namespace features {
BLINK_COMMON_EXPORT extern const base::Feature
kBlockingDownloadsInAdFrameWithoutUserActivation;
+BLINK_COMMON_EXPORT extern const base::Feature kCOEPForSharedWorker;
BLINK_COMMON_EXPORT extern const base::Feature kCOLRV1Fonts;
BLINK_COMMON_EXPORT extern const base::Feature kCSSContainerQueries;
+BLINK_COMMON_EXPORT extern const base::Feature kConversionMeasurement;
BLINK_COMMON_EXPORT extern const base::Feature kGMSCoreEmoji;
BLINK_COMMON_EXPORT extern const base::Feature
- kHandwritingRecognitionWebPlatformApi;
-BLINK_COMMON_EXPORT extern const base::Feature
kHandwritingRecognitionWebPlatformApiFinch;
BLINK_COMMON_EXPORT extern const base::Feature kPaintHolding;
BLINK_COMMON_EXPORT extern const base::Feature kPaintHoldingCrossOrigin;
@@ -33,7 +33,7 @@ BLINK_COMMON_EXPORT extern const base::Feature kScriptStreaming;
BLINK_COMMON_EXPORT extern const base::Feature kSmallScriptStreaming;
BLINK_COMMON_EXPORT extern const base::Feature kUserLevelMemoryPressureSignal;
BLINK_COMMON_EXPORT extern const base::Feature kFreezePurgeMemoryAllPagesFrozen;
-BLINK_COMMON_EXPORT extern const base::Feature kFreezeUserAgent;
+BLINK_COMMON_EXPORT extern const base::Feature kReduceUserAgent;
BLINK_COMMON_EXPORT extern const base::Feature
kFrequencyCappingForOverlayPopupDetection;
BLINK_COMMON_EXPORT extern const base::Feature
@@ -47,11 +47,16 @@ BLINK_COMMON_EXPORT extern const base::Feature kLayoutNG;
BLINK_COMMON_EXPORT extern const base::Feature kLayoutNGTable;
BLINK_COMMON_EXPORT extern const base::Feature kMixedContentAutoupgrade;
BLINK_COMMON_EXPORT extern const base::Feature kNavigationPredictor;
-BLINK_COMMON_EXPORT extern const base::Feature kNavigatorPluginsEmpty;
+BLINK_COMMON_EXPORT extern const base::Feature kNavigatorPluginsFixed;
BLINK_COMMON_EXPORT extern const base::Feature kPlzDedicatedWorker;
BLINK_COMMON_EXPORT extern const base::Feature kPortals;
BLINK_COMMON_EXPORT extern const base::Feature kPortalsCrossOrigin;
BLINK_COMMON_EXPORT extern const base::Feature kFencedFrames;
+BLINK_COMMON_EXPORT extern const base::Feature kUserAgentClientHint;
+BLINK_COMMON_EXPORT extern const base::Feature kLangClientHintHeader;
+BLINK_COMMON_EXPORT extern const base::Feature
+ kPrefersColorSchemeClientHintHeader;
+
enum class FencedFramesImplementationType {
kShadowDOM,
kMPArch,
@@ -60,20 +65,37 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<
FencedFramesImplementationType>
kFencedFramesImplementationTypeParam;
+BLINK_COMMON_EXPORT extern const base::Feature kSharedStorageAPI;
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+ kSharedStorageURLSelectionOperationInputURLSizeLimit;
+
// Prerender2:
+// Enables the Prerender2 feature: https://crbug.com/1126305
+// But see comments in the .cc file also.
BLINK_COMMON_EXPORT extern const base::Feature kPrerender2;
-
+// Enables restrictions on how much memory is required on a device to use
+// Prerender2. This is a separate feature from kPrerender2 so that the
+// restrictions can be disabled entirely to allow bots to run the tests without
+// needing to explicitly enable Prerender2, which some tests do not want to do
+// because they want to test the default behavior.
+BLINK_COMMON_EXPORT extern const base::Feature kPrerender2MemoryControls;
+// A field trial param that controls how much physical memory is required on a
+// device to use Prerender2. If the device's physical memory does not exceed
+// this value, pages will not be prerendered even when kPrerender2 is enabled.
+BLINK_COMMON_EXPORT extern const char kPrerender2MemoryThresholdParamName[];
// Returns true when Prerender2 feature is enabled.
BLINK_COMMON_EXPORT bool IsPrerender2Enabled();
+// Fenced Frames:
+BLINK_COMMON_EXPORT bool IsFencedFramesEnabled();
+
BLINK_COMMON_EXPORT extern const base::Feature
kPreviewsResourceLoadingHintsSpecificResourceTypes;
BLINK_COMMON_EXPORT extern const base::Feature
kPurgeRendererMemoryWhenBackgrounded;
-BLINK_COMMON_EXPORT extern const base::Feature kRawClipboard;
-BLINK_COMMON_EXPORT extern const base::Feature
- kRTCGetCurrentBrowsingContextMedia;
BLINK_COMMON_EXPORT extern const base::Feature kRTCUnifiedPlanByDefault;
+BLINK_COMMON_EXPORT extern const base::Feature
+ kRTCDisallowPlanBOutsideDeprecationTrial;
BLINK_COMMON_EXPORT extern const base::Feature kRTCOfferExtmapAllowMixed;
BLINK_COMMON_EXPORT extern const base::Feature kRTCGpuCodecSupportWaiter;
BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
@@ -106,6 +128,7 @@ BLINK_COMMON_EXPORT extern const base::Feature kFontAccess;
BLINK_COMMON_EXPORT extern const base::Feature kFontAccessPersistent;
BLINK_COMMON_EXPORT extern const base::Feature kComputePressure;
BLINK_COMMON_EXPORT extern const base::Feature kFileHandlingAPI;
+BLINK_COMMON_EXPORT extern const base::Feature kFileHandlingIcons;
BLINK_COMMON_EXPORT extern const base::Feature kAllowSyncXHRInPageDismissal;
BLINK_COMMON_EXPORT extern const base::Feature kPrefetchPrivacyChanges;
@@ -156,10 +179,8 @@ BLINK_COMMON_EXPORT extern const base::Feature
BLINK_COMMON_EXPORT extern const base::Feature
kBlinkCompositorUseDisplayThreadPriority;
-BLINK_COMMON_EXPORT extern const base::Feature
- kIgnoreCrossOriginWindowWhenNamedAccessOnWindow;
-
BLINK_COMMON_EXPORT extern const base::Feature kTransformInterop;
+BLINK_COMMON_EXPORT extern const base::Feature kBackfaceVisibilityInterop;
BLINK_COMMON_EXPORT extern const base::Feature kSubresourceRedirect;
@@ -193,34 +214,6 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
BLINK_COMMON_EXPORT extern const base::Feature kKeepScriptResourceAlive;
-BLINK_COMMON_EXPORT extern const base::Feature kDelayAsyncScriptExecution;
-enum class DelayAsyncScriptDelayType {
- kFinishedParsing,
- kFirstPaintOrFinishedParsing,
- kUseOptimizationGuide,
-};
-BLINK_COMMON_EXPORT extern const base::FeatureParam<DelayAsyncScriptDelayType>
- kDelayAsyncScriptExecutionDelayParam;
-
-BLINK_COMMON_EXPORT extern const base::Feature
- kDelayCompetingLowPriorityRequests;
-enum class DelayCompetingLowPriorityRequestsDelayType {
- kFirstPaint,
- kFirstContentfulPaint,
- kAlways,
- kUseOptimizationGuide,
-};
-BLINK_COMMON_EXPORT extern const base::FeatureParam<
- DelayCompetingLowPriorityRequestsDelayType>
- kDelayCompetingLowPriorityRequestsDelayParam;
-enum class DelayCompetingLowPriorityRequestsThreshold {
- kMedium,
- kHigh,
-};
-BLINK_COMMON_EXPORT extern const base::FeatureParam<
- DelayCompetingLowPriorityRequestsThreshold>
- kDelayCompetingLowPriorityRequestsThresholdParam;
-
BLINK_COMMON_EXPORT extern const base::Feature kAppCache;
BLINK_COMMON_EXPORT extern const base::Feature kAppCacheRequireOriginTrial;
@@ -305,7 +298,7 @@ BLINK_COMMON_EXPORT bool IsParkableStringsToDiskEnabled();
BLINK_COMMON_EXPORT extern const base::Feature kCrOSAutoSelect;
-BLINK_COMMON_EXPORT extern const base::Feature kCompositingOptimizations;
+BLINK_COMMON_EXPORT extern const base::Feature kCLSScrollAnchoring;
BLINK_COMMON_EXPORT extern const base::Feature kReducedReferrerGranularity;
@@ -329,16 +322,20 @@ BLINK_COMMON_EXPORT extern const base::Feature kPreferCompositingToLCDText;
BLINK_COMMON_EXPORT extern const base::Feature
kLogUnexpectedIPCPostedToBackForwardCachedDocuments;
+BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableIsolatedStorage;
+
+BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableLaunchHandler;
+
BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableLinkCapturing;
+BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableManifestId;
+
BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableUrlHandlers;
BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableProtocolHandlers;
BLINK_COMMON_EXPORT extern const base::Feature kWebAppNoteTaking;
-BLINK_COMMON_EXPORT extern const base::Feature kWebRtcLibvpxEncodeNV12;
-
BLINK_COMMON_EXPORT extern const base::Feature kLoadingTasksUnfreezable;
BLINK_COMMON_EXPORT extern const base::Feature kFreezeWhileKeepActive;
@@ -378,8 +375,6 @@ BLINK_COMMON_EXPORT extern const base::Feature
BLINK_COMMON_EXPORT extern const base::FeatureParam<std::string>
kBackgroundTracingPerformanceMark_AllowList;
-BLINK_COMMON_EXPORT extern const base::Feature kCLSM90Improvements;
-
BLINK_COMMON_EXPORT extern const base::Feature kCompositeAfterPaint;
BLINK_COMMON_EXPORT extern const base::Feature kSanitizerAPI;
@@ -407,6 +402,46 @@ BLINK_COMMON_EXPORT extern const base::Feature kFledgeInterestGroupAPI;
BLINK_COMMON_EXPORT extern const base::Feature
kMinimizeAudioProcessingForUnusedOutput;
+// When <dialog>s are closed, this focuses the "previously focused" element
+// which had focus when the <dialog> was first opened.
+// TODO(crbug.com/649162): Remove DialogFocusNewSpecBehavior after
+// the feature is in stable with no issues.
+BLINK_COMMON_EXPORT extern const base::Feature kDialogFocusNewSpecBehavior;
+
+// Makes autofill look across shadow boundaries when collecting form controls to
+// fill.
+BLINK_COMMON_EXPORT extern const base::Feature kAutofillShadowDOM;
+
+// Allows read/write of custom formats with unsanitized clipboard content. See
+// crbug.com/106449.
+BLINK_COMMON_EXPORT extern const base::Feature kClipboardCustomFormats;
+
+// Uses page viewport instead of frame viewport in the Largest Contentful Paint
+// heuristic where images occupying the full viewport are ignored.
+BLINK_COMMON_EXPORT extern const base::Feature kUsePageViewportInLCP;
+
+// Enable "Sec-CH-UA-Platform" client hint and request header for all requests
+BLINK_COMMON_EXPORT extern const base::Feature kUACHPlatformEnabledByDefault;
+
+// When enabled, allow dropping alpha on media streams for rendering sinks if
+// other sinks connected do not use alpha.
+BLINK_COMMON_EXPORT extern const base::Feature kAllowDropAlphaForMediaStream;
+
+BLINK_COMMON_EXPORT extern const base::Feature kThirdPartyStoragePartitioning;
+
+BLINK_COMMON_EXPORT extern const base::Feature kDesktopPWAsSubApps;
+
+// When enabled, we report all JavaScript frameworks via a manual traversal to
+// detect the properties and attributes required.
+BLINK_COMMON_EXPORT extern const base::Feature kReportAllJavascriptFrameworks;
+
+// Suppresses console errors for CORS problems which report an associated
+// inspector issue anyway.
+BLINK_COMMON_EXPORT extern const base::Feature kCORSErrorsIssueOnly;
+
+BLINK_COMMON_EXPORT extern const base::Feature
+ kDeprecateThirdPartyContextWebSQL;
+
} // namespace features
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h b/chromium/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
index 9950d48d0d5..0fd9ee689f1 100644
--- a/chromium/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
@@ -14,6 +14,10 @@
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
+namespace network {
+class DataElement;
+}
+
namespace mojo {
template <>
diff --git a/chromium/third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h b/chromium/third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h
index 00c50703dcd..ba1e2c43410 100644
--- a/chromium/third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h
+++ b/chromium/third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FONT_UNIQUE_NAME_LOOKUP_FONT_TABLE_MATCHER_H_
#include "base/memory/read_only_shared_memory_region.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/font_unique_name_lookup/font_unique_name_table.pb.h"
diff --git a/chromium/third_party/blink/public/common/frame/frame_policy.h b/chromium/third_party/blink/public/common/frame/frame_policy.h
index 5259285d600..45d8a86bf1d 100644
--- a/chromium/third_party/blink/public/common/frame/frame_policy.h
+++ b/chromium/third_party/blink/public/common/frame/frame_policy.h
@@ -27,8 +27,7 @@ struct BLINK_COMMON_EXPORT FramePolicy {
FramePolicy();
FramePolicy(network::mojom::WebSandboxFlags sandbox_flags,
const ParsedPermissionsPolicy& container_policy,
- const DocumentPolicyFeatureState& required_document_policy,
- bool disallow_document_access = false);
+ const DocumentPolicyFeatureState& required_document_policy);
FramePolicy(const FramePolicy& lhs);
~FramePolicy();
@@ -40,11 +39,29 @@ struct BLINK_COMMON_EXPORT FramePolicy {
// - |required_document_policy| of parent frame
DocumentPolicyFeatureState required_document_policy;
- // Whether or not a frame allows direct script access across frame
- // boundaries.
- bool disallow_document_access = false;
+ // This signals to a frame whether or not it is hosted in a <fencedframe>
+ // element, and therefore should restrict some sensitive Window APIs that
+ // would otherwise grant access to the parent frame, or information about it.
+ //
+ // IMPORTANT NOTE: This is a temporary member that does not align with the
+ // long-term architecture, and will be removed after the <fencedframe>
+ // ShadowDOM-based origin trial, please do not use this for anything else. See
+ // https://docs.google.com/document/d/1ijTZJT3DHQ1ljp4QQe4E4XCCRaYAxmInNzN1SzeJM8s/edit
+ // and crbug.com/1123606. Note that this bit is immutable and cannot
+ // experience transitions, therefore `FramePolicy` is not actually a good
+ // place for this bit to live, and would be best suited to be manually plumbed
+ // through like `TreeScopeType`. However since this bit is temporary, any
+ // plumbing we introduce for it will be thrown away once we migrate to the
+ // long-term MPArch architecture, so we're using `FramePolicy` to avoid
+ // temporarily investing in the manual plumbing that will not stick around.
+ bool is_fenced = false;
};
+bool BLINK_COMMON_EXPORT operator==(const FramePolicy& lhs,
+ const FramePolicy& rhs);
+bool BLINK_COMMON_EXPORT operator!=(const FramePolicy& lhs,
+ const FramePolicy& rhs);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_FRAME_FRAME_POLICY_H_
diff --git a/chromium/third_party/blink/public/common/frame/frame_visual_properties.h b/chromium/third_party/blink/public/common/frame/frame_visual_properties.h
index 9e00399decb..dab8efaa8c1 100644
--- a/chromium/third_party/blink/public/common/frame/frame_visual_properties.h
+++ b/chromium/third_party/blink/public/common/frame/frame_visual_properties.h
@@ -7,7 +7,7 @@
#include "components/viz/common/surfaces/local_surface_id.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
+#include "ui/display/screen_info.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -27,7 +27,7 @@ struct BLINK_COMMON_EXPORT FrameVisualProperties {
// renderer process up to the RenderWidgetHost for a child RenderWidget in
// another renderer process. That RenderWidgetHost would then be responsible
// for passing it along to the child RenderWidget.
- blink::ScreenInfo screen_info;
+ display::ScreenInfo screen_info;
bool auto_resize_enabled = false;
bool is_pinch_gesture_active = false;
uint32_t capture_sequence_number = 0u;
diff --git a/chromium/third_party/blink/public/common/frame/frame_visual_properties_mojom_traits.h b/chromium/third_party/blink/public/common/frame/frame_visual_properties_mojom_traits.h
index 5ec8b143129..613af17f4f9 100644
--- a/chromium/third_party/blink/public/common/frame/frame_visual_properties_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/frame/frame_visual_properties_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_FRAME_FRAME_VISUAL_PROPERTIES_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FRAME_FRAME_VISUAL_PROPERTIES_MOJOM_TRAITS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/frame/frame_visual_properties.h"
#include "third_party/blink/public/mojom/frame/frame_visual_properties.mojom-shared.h"
@@ -15,7 +16,7 @@ template <>
struct BLINK_COMMON_EXPORT
StructTraits<blink::mojom::FrameVisualPropertiesDataView,
blink::FrameVisualProperties> {
- static const blink::ScreenInfo& screen_info(
+ static const display::ScreenInfo& screen_info(
const blink::FrameVisualProperties& r) {
return r.screen_info;
}
diff --git a/chromium/third_party/blink/public/common/input/web_gesture_event.h b/chromium/third_party/blink/public/common/input/web_gesture_event.h
index ef6eefefb09..d88b6ca2ad3 100644
--- a/chromium/third_party/blink/public/common/input/web_gesture_event.h
+++ b/chromium/third_party/blink/public/common/input/web_gesture_event.h
@@ -14,6 +14,7 @@
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_pointer_properties.h"
#include "third_party/blink/public/mojom/input/gesture_event.mojom-shared.h"
+#include "ui/events/types/scroll_input_type.h"
#include "ui/events/types/scroll_types.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/size_f.h"
@@ -31,14 +32,17 @@ class BLINK_COMMON_EXPORT WebGestureEvent : public WebInputEvent {
// The pointer type for the first touch point in the gesture.
WebPointerProperties::PointerType primary_pointer_type =
WebPointerProperties::PointerType::kUnknown;
+ // The unique_touch_event id of the first touch in the gesture sequence
+ uint32_t primary_unique_touch_event_id = 0;
// If the WebGestureEvent has source_device ==
// mojom::GestureDevice::kTouchscreen, this field contains the unique
// identifier for the touch event that released this event at
// TouchDispositionGestureFilter. If the WebGestureEvents was not released
- // through a touch event (e.g. timer-released gesture events or gesture events
- // with source_device != mojom::GestureDevice::kTouchscreen), the field
- // contains 0. See crbug.com/618738.
+ // through a touch event (e.g. synthesized gesture events and pinches
+ // or gesture events with source_device !=
+ // mojom::GestureDevice::kTouchscreen), the field contains 0. See
+ // crbug.com/618738.
uint32_t unique_touch_event_id = 0;
union {
@@ -212,7 +216,10 @@ class BLINK_COMMON_EXPORT WebGestureEvent : public WebInputEvent {
std::unique_ptr<WebInputEvent> Clone() const override;
bool CanCoalesce(const WebInputEvent& event) const override;
void Coalesce(const WebInputEvent& event) override;
- absl::optional<ui::ScrollInputType> GetScrollInputType() const override;
+
+ // Returns the input type of a scroll event. Should not be called on
+ // non-scroll events.
+ ui::ScrollInputType GetScrollInputType() const;
void SetPositionInWidget(const gfx::PointF& point) {
position_in_widget_ = point;
diff --git a/chromium/third_party/blink/public/common/input/web_input_event.h b/chromium/third_party/blink/public/common/input/web_input_event.h
index 6427a5b7164..11210173ab0 100644
--- a/chromium/third_party/blink/public/common/input/web_input_event.h
+++ b/chromium/third_party/blink/public/common/input/web_input_event.h
@@ -37,10 +37,10 @@
#include "base/notreached.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/input/input_event.mojom-shared.h"
#include "ui/events/types/event_type.h"
-#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -332,10 +332,6 @@ class BLINK_COMMON_EXPORT WebInputEvent {
// Merge the current event with attributes from |event|.
virtual void Coalesce(const WebInputEvent& event) = 0;
- // Returns the scroll input type if this is a scroll event; otherwise,
- // returns absl::nullopt.
- virtual absl::optional<ui::ScrollInputType> GetScrollInputType() const;
-
// Convert this WebInputEvent::Type to a ui::EventType. Note that this is
// not a 1:1 relationship. Multiple blink types convert to the same
// ui::EventType and not all types do convert.
diff --git a/chromium/third_party/blink/public/common/interest_group/DIR_METADATA b/chromium/third_party/blink/public/common/interest_group/DIR_METADATA
new file mode 100644
index 00000000000..5313345b4ca
--- /dev/null
+++ b/chromium/third_party/blink/public/common/interest_group/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>InterestGroups"
+}
diff --git a/chromium/third_party/blink/public/common/interest_group/OWNERS b/chromium/third_party/blink/public/common/interest_group/OWNERS
new file mode 100644
index 00000000000..563a80e9290
--- /dev/null
+++ b/chromium/third_party/blink/public/common/interest_group/OWNERS
@@ -0,0 +1,4 @@
+file://third_party/blink/renderer/modules/ad_auction/OWNERS
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/common/interest_group/interest_group.h b/chromium/third_party/blink/public/common/interest_group/interest_group.h
new file mode 100644
index 00000000000..e02e33ad7cc
--- /dev/null
+++ b/chromium/third_party/blink/public/common/interest_group/interest_group.h
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_INTEREST_GROUP_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_INTEREST_GROUP_H_
+
+#include <string>
+#include <vector>
+
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-forward.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace blink {
+
+// Interest group used by FLEDGE auctions. Typemapped to
+// blink::mojom::InterestGroup, primarily so the typemap can include validity
+// checks on the origins of the provided URLs.
+//
+// All URLs and origins must use https, and same origin to `owner`.
+//
+// https://github.com/WICG/turtledove/blob/main/FLEDGE.md#11-joining-interest-groups
+struct BLINK_COMMON_EXPORT InterestGroup {
+ // An advertisement to display for an interest group. Typemapped to
+ // blink::mojom::InterestGroupAd.
+ // https://github.com/WICG/turtledove/blob/main/FLEDGE.md#12-interest-group-attributes
+ struct BLINK_COMMON_EXPORT Ad {
+ Ad();
+ Ad(GURL render_url, absl::optional<std::string> metadata);
+ ~Ad();
+
+ // Must use https.
+ GURL render_url;
+ // Opaque JSON data, passed as an object to auction worklet.
+ absl::optional<std::string> metadata;
+
+ // Only used in tests, but provided as an operator instead of as
+ // IsEqualForTesting() to make it easier to implement InterestGroup's
+ // IsEqualForTesting().
+ bool operator==(const Ad& other) const;
+ };
+
+ InterestGroup();
+
+ // Constructor takes arguments by value. They're unlikely to be independently
+ // useful at the point of construction, so caller can std::move() them when
+ // invoking the constructor.
+ InterestGroup(
+ base::Time expiry,
+ url::Origin owner,
+ std::string name,
+ absl::optional<GURL> bidding_url,
+ absl::optional<GURL> update_url,
+ absl::optional<GURL> trusted_bidding_signals_url,
+ absl::optional<std::vector<std::string>> trusted_bidding_signals_keys,
+ absl::optional<std::string> user_bidding_signals,
+ absl::optional<std::vector<InterestGroup::Ad>> ads);
+
+ ~InterestGroup();
+
+ // Checks for validity. Performs same checks as IsBlinkInterestGroupValid().
+ // Automatically checked when passing InterestGroups over Mojo.
+ bool IsValid() const;
+
+ bool IsEqualForTesting(const InterestGroup& other) const;
+
+ base::Time expiry;
+ url::Origin owner;
+ std::string name;
+ absl::optional<GURL> bidding_url;
+ absl::optional<GURL> update_url;
+ absl::optional<GURL> trusted_bidding_signals_url;
+ absl::optional<std::vector<std::string>> trusted_bidding_signals_keys;
+ absl::optional<std::string> user_bidding_signals;
+ absl::optional<std::vector<InterestGroup::Ad>> ads;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_INTEREST_GROUP_H_
diff --git a/chromium/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h b/chromium/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h
new file mode 100644
index 00000000000..3950b3de07d
--- /dev/null
+++ b/chromium/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h
@@ -0,0 +1,88 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_INTEREST_GROUP_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_INTEREST_GROUP_MOJOM_TRAITS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/interest_group/interest_group.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-forward.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace mojo {
+
+template <>
+struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::InterestGroupAdDataView,
+ blink::InterestGroup::Ad> {
+ static const GURL& render_url(const blink::InterestGroup::Ad& ad) {
+ return ad.render_url;
+ }
+
+ static const absl::optional<std::string>& metadata(
+ const blink::InterestGroup::Ad& ad) {
+ return ad.metadata;
+ }
+
+ static bool Read(blink::mojom::InterestGroupAdDataView data,
+ blink::InterestGroup::Ad* out);
+};
+
+template <>
+struct BLINK_COMMON_EXPORT
+ StructTraits<blink::mojom::InterestGroupDataView, blink::InterestGroup> {
+ static base::Time expiry(const blink::InterestGroup& interest_group) {
+ return interest_group.expiry;
+ }
+
+ static const url::Origin& owner(const blink::InterestGroup& interest_group) {
+ return interest_group.owner;
+ }
+
+ static const std::string& name(const blink::InterestGroup& interest_group) {
+ return interest_group.name;
+ }
+
+ static const absl::optional<GURL>& bidding_url(
+ const blink::InterestGroup& interest_group) {
+ return interest_group.bidding_url;
+ }
+
+ static const absl::optional<GURL>& update_url(
+ const blink::InterestGroup& interest_group) {
+ return interest_group.update_url;
+ }
+
+ static const absl::optional<GURL>& trusted_bidding_signals_url(
+ const blink::InterestGroup& interest_group) {
+ return interest_group.trusted_bidding_signals_url;
+ }
+
+ static const absl::optional<std::vector<std::string>>&
+ trusted_bidding_signals_keys(const blink::InterestGroup& interest_group) {
+ return interest_group.trusted_bidding_signals_keys;
+ }
+
+ static const absl::optional<std::string>& user_bidding_signals(
+ const blink::InterestGroup& interest_group) {
+ return interest_group.user_bidding_signals;
+ }
+
+ static const absl::optional<std::vector<blink::InterestGroup::Ad>>& ads(
+ const blink::InterestGroup& interest_group) {
+ return interest_group.ads;
+ }
+
+ static bool Read(blink::mojom::InterestGroupDataView data,
+ blink::InterestGroup* out);
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_INTEREST_GROUP_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/loader/loader_constants.h b/chromium/third_party/blink/public/common/loader/loader_constants.h
index 9c963abf9ad..3a22f952f0f 100644
--- a/chromium/third_party/blink/public/common/loader/loader_constants.h
+++ b/chromium/third_party/blink/public/common/loader/loader_constants.h
@@ -12,6 +12,14 @@ namespace blink {
// HTTP header set in requests to indicate they should be marked DoNotTrack.
BLINK_COMMON_EXPORT extern const char kDoNotTrackHeader[];
+// These values indicate the load progress constants shared between both
+// //content and //blink.
+//
+// Initial progress value is set to 0.1 to help provide feedback as soon as a
+// load starts.
+constexpr double kInitialLoadProgress = 0.1;
+constexpr double kFinalLoadProgress = 1.0;
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_LOADER_CONSTANTS_H_
diff --git a/chromium/third_party/blink/public/common/loader/loading_behavior_flag.h b/chromium/third_party/blink/public/common/loader/loading_behavior_flag.h
index a9ccfee5661..33101e085c6 100644
--- a/chromium/third_party/blink/public/common/loader/loading_behavior_flag.h
+++ b/chromium/third_party/blink/public/common/loader/loading_behavior_flag.h
@@ -38,7 +38,7 @@ enum LoadingBehaviorFlag {
// Indicates that the page is an AMP document, with <html amp> tag.
kLoadingBehaviorAmpDocumentLoaded = 1 << 7,
// Indicates that the page uses the Next.js JavaScript framework (via a
- // window variable)
+ // window variable).
kLoadingBehaviorNextJSFrameworkUsed = 1 << 8,
// Indicates that an async script was ready to execute before the script
// element's node document has finished parsing.
@@ -46,6 +46,24 @@ enum LoadingBehaviorFlag {
// Indicates that competing low priority requests were delayed. See
// https://crbug.com/1112515 for details.
kLoadingBehaviorCompetingLowPriorityRequestsDelayed = 1 << 10,
+ // Indicates that the page uses the NuxtJS JavaScript framework.
+ kLoadingBehaviorNuxtJSFrameworkUsed = 1 << 11,
+ // Indicates that the page uses the VuePress JavaScript framework.
+ kLoadingBehaviorVuePressFrameworkUsed = 1 << 12,
+ // Indicates that the page uses the Sapper JavaScript framework.
+ kLoadingBehaviorSapperFrameworkUsed = 1 << 13,
+ // Indicates that the page uses the Gatsby JavaScript framework.
+ kLoadingBehaviorGatsbyFrameworkUsed = 1 << 14,
+ // Indicates that the page uses the Angular JavaScript framework.
+ kLoadingBehaviorAngularFrameworkUsed = 1 << 15,
+ // Indicates that the page uses the Vue JavaScript framework.
+ kLoadingBehaviorVueFrameworkUsed = 1 << 16,
+ // Indicates that the page uses the Svelte JavaScript framework.
+ kLoadingBehaviorSvelteFrameworkUsed = 1 << 17,
+ // Indicates that the page uses the Preact JavaScript framework.
+ kLoadingBehaviorPreactFrameworkUsed = 1 << 18,
+ // Indicates that the page uses the React JavaScript framework.
+ kLoadingBehaviorReactFrameworkUsed = 1 << 19,
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h b/chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h
index 7d6c3231894..27346c0fb31 100644
--- a/chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h
+++ b/chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h
@@ -57,6 +57,8 @@ class BLINK_COMMON_EXPORT MimeSniffingURLLoader
: public network::mojom::URLLoaderClient,
public network::mojom::URLLoader {
public:
+ MimeSniffingURLLoader(const MimeSniffingURLLoader&) = delete;
+ MimeSniffingURLLoader& operator=(const MimeSniffingURLLoader&) = delete;
~MimeSniffingURLLoader() override;
// Start waiting for the body.
@@ -151,8 +153,6 @@ class BLINK_COMMON_EXPORT MimeSniffingURLLoader
mojo::ScopedDataPipeProducerHandle body_producer_handle_;
mojo::SimpleWatcher body_consumer_watcher_;
mojo::SimpleWatcher body_producer_watcher_;
-
- DISALLOW_COPY_AND_ASSIGN(MimeSniffingURLLoader);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/loader/throttling_url_loader.h b/chromium/third_party/blink/public/common/loader/throttling_url_loader.h
index 6792179ed60..7234304a795 100644
--- a/chromium/third_party/blink/public/common/loader/throttling_url_loader.h
+++ b/chromium/third_party/blink/public/common/loader/throttling_url_loader.h
@@ -17,6 +17,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
+#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/accept_ch_frame_observer.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -63,6 +64,8 @@ class BLINK_COMMON_EXPORT ThrottlingURLLoader
absl::optional<std::vector<std::string>> cors_exempt_header_list =
absl::nullopt);
+ ThrottlingURLLoader(const ThrottlingURLLoader&) = delete;
+ ThrottlingURLLoader& operator=(const ThrottlingURLLoader&) = delete;
~ThrottlingURLLoader() override;
// Follows a redirect, calling CreateLoaderAndStart() on the factory. This
@@ -182,6 +185,7 @@ class BLINK_COMMON_EXPORT ThrottlingURLLoader
void UpdateDeferredRequestHeaders(
const net::HttpRequestHeaders& modified_request_headers,
const net::HttpRequestHeaders& modified_cors_exempt_request_headers);
+ void UpdateRequestHeaders();
void UpdateDeferredResponseHead(
network::mojom::URLResponseHeadPtr new_response_head);
void PauseReadingBodyFromNet(URLLoaderThrottle* throttle);
@@ -215,15 +219,11 @@ class BLINK_COMMON_EXPORT ThrottlingURLLoader
ThrottleEntry(ThrottlingURLLoader* loader,
std::unique_ptr<URLLoaderThrottle> the_throttle);
ThrottleEntry(ThrottleEntry&& other);
- ~ThrottleEntry();
-
ThrottleEntry& operator=(ThrottleEntry&& other);
+ ~ThrottleEntry();
std::unique_ptr<ForwardingThrottleDelegate> delegate;
std::unique_ptr<URLLoaderThrottle> throttle;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ThrottleEntry);
};
std::vector<ThrottleEntry> throttles_;
@@ -328,8 +328,6 @@ class BLINK_COMMON_EXPORT ThrottlingURLLoader
accept_ch_frame_observers_;
base::WeakPtrFactory<ThrottlingURLLoader> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ThrottlingURLLoader);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle.h b/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle.h
index 863828ea470..eab9f521bbc 100644
--- a/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle.h
+++ b/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle.h
@@ -10,7 +10,6 @@
#include <string>
#include <utility>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -51,6 +50,9 @@ class BLINK_COMMON_EXPORT PendingURLLoaderFactoryBundle
SchemeMap scheme_specific_pending_factories,
OriginMap isolated_world_pending_factories,
bool bypass_redirect_checks);
+ PendingURLLoaderFactoryBundle(const PendingURLLoaderFactoryBundle&) = delete;
+ PendingURLLoaderFactoryBundle& operator=(
+ const PendingURLLoaderFactoryBundle&) = delete;
~PendingURLLoaderFactoryBundle() override;
mojo::PendingRemote<network::mojom::URLLoaderFactory>&
@@ -86,10 +88,13 @@ class BLINK_COMMON_EXPORT PendingURLLoaderFactoryBundle
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_appcache_factory_;
SchemeMap pending_scheme_specific_factories_;
+
+ // TODO(https://crbug.com/1098410): Remove the
+ // `pending_isolated_world_factories_` field once Chrome Platform Apps are
+ // gone.
OriginMap pending_isolated_world_factories_;
- bool bypass_redirect_checks_ = false;
- DISALLOW_COPY_AND_ASSIGN(PendingURLLoaderFactoryBundle);
+ bool bypass_redirect_checks_ = false;
};
// Encapsulates a collection of URLLoaderFactoryPtrs which can be usd to acquire
@@ -167,6 +172,9 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundle
// Map from origin of isolated world to Remote<URLLoaderFactory> for handling
// this isolated world's requests. See also
// PendingURLLoaderFactoryBundle::OriginMap.
+ //
+ // TODO(https://crbug.com/1098410): Remove the `isolated_world_factories_`
+ // field once Chrome Platform Apps are gone.
using OriginMap =
std::map<url::Origin, mojo::Remote<network::mojom::URLLoaderFactory>>;
OriginMap isolated_world_factories_;
diff --git a/chromium/third_party/blink/public/common/manifest/DIR_METADATA b/chromium/third_party/blink/public/common/manifest/DIR_METADATA
new file mode 100644
index 00000000000..0ff3ed55bf6
--- /dev/null
+++ b/chromium/third_party/blink/public/common/manifest/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>AppManifest"
+}
diff --git a/chromium/third_party/blink/public/common/manifest/OWNERS b/chromium/third_party/blink/public/common/manifest/OWNERS
index aa75e1416ee..20d2acc7931 100644
--- a/chromium/third_party/blink/public/common/manifest/OWNERS
+++ b/chromium/third_party/blink/public/common/manifest/OWNERS
@@ -2,5 +2,3 @@ file://third_party/blink/renderer/modules/manifest/OWNERS
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-
-# Component: Blink>AppManifest
diff --git a/chromium/third_party/blink/public/common/manifest/manifest.h b/chromium/third_party/blink/public/common/manifest/manifest.h
index a59f7299bd3..25f6f2b6f16 100644
--- a/chromium/third_party/blink/public/common/manifest/manifest.h
+++ b/chromium/third_party/blink/public/common/manifest/manifest.h
@@ -11,22 +11,17 @@
#include <string>
#include <vector>
-#include "services/device/public/mojom/screen_orientation_lock_types.mojom-shared.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-shared.h"
-#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace blink {
-// The Manifest structure is an internal representation of the Manifest file
-// described in the "Manifest for Web Application" document:
-// http://w3c.github.io/manifest/
-struct BLINK_COMMON_EXPORT Manifest {
+class BLINK_COMMON_EXPORT Manifest {
+ public:
// Structure representing an icon as per the Manifest specification, see:
// https://w3c.github.io/manifest/#dom-imageresource
struct BLINK_COMMON_EXPORT ImageResource {
@@ -61,6 +56,8 @@ struct BLINK_COMMON_EXPORT Manifest {
ShortcutItem();
~ShortcutItem();
+ bool operator==(const ShortcutItem& other) const;
+
std::u16string name;
absl::optional<std::u16string> short_name;
absl::optional<std::u16string> description;
@@ -69,6 +66,8 @@ struct BLINK_COMMON_EXPORT Manifest {
};
struct BLINK_COMMON_EXPORT FileFilter {
+ bool operator==(const FileFilter& other) const;
+
std::u16string name;
std::vector<std::u16string> accept;
};
@@ -78,6 +77,8 @@ struct BLINK_COMMON_EXPORT Manifest {
ShareTargetParams();
~ShareTargetParams();
+ bool operator==(const ShareTargetParams& other) const;
+
absl::optional<std::u16string> title;
absl::optional<std::u16string> text;
absl::optional<std::u16string> url;
@@ -89,6 +90,8 @@ struct BLINK_COMMON_EXPORT Manifest {
ShareTarget();
~ShareTarget();
+ bool operator==(const ShareTarget& other) const;
+
// The URL used for sharing. Query parameters are added to this comprised of
// keys from |params| and values from the shared data.
GURL action;
@@ -102,36 +105,13 @@ struct BLINK_COMMON_EXPORT Manifest {
ShareTargetParams params;
};
- // Structure representing a File Handler.
- struct BLINK_COMMON_EXPORT FileHandler {
- // The URL which will be opened when the file handler is invoked.
- GURL action;
- std::u16string name;
- std::map<std::u16string, std::vector<std::u16string>> accept;
- };
-
- // Structure representing a Protocol Handler.
- struct BLINK_COMMON_EXPORT ProtocolHandler {
- std::u16string protocol;
- GURL url;
- };
-
- struct BLINK_COMMON_EXPORT UrlHandler {
- url::Origin origin;
- bool has_origin_wildcard;
- };
-
- struct BLINK_COMMON_EXPORT NoteTaking {
- // A URL for taking a new note in the web application. If valid, this web
- // application is a note-taking application.
- GURL new_note_url;
- };
-
// Structure representing a related application.
struct BLINK_COMMON_EXPORT RelatedApplication {
RelatedApplication();
~RelatedApplication();
+ bool operator==(const RelatedApplication& other) const;
+
// The platform on which the application can be found. This can be any
// string, and is interpreted by the consumer of the object. Empty if the
// parsing failed.
@@ -147,107 +127,24 @@ struct BLINK_COMMON_EXPORT Manifest {
absl::optional<std::u16string> id;
};
- Manifest();
- Manifest(const Manifest& other);
- ~Manifest();
-
- // Returns whether this Manifest had no attribute set. A newly created
- // Manifest is always empty.
- bool IsEmpty() const;
-
- // Null if the parsing failed or the field was not present.
- absl::optional<std::u16string> name;
-
- // Null if the parsing failed or the field was not present.
- absl::optional<std::u16string> short_name;
-
- // Null if the parsing failed or the field was not present.
- absl::optional<std::u16string> description;
-
- // Empty if the parsing failed or the field was not present.
- GURL start_url;
-
- // Set to DisplayMode::kUndefined if the parsing failed or the field was not
- // present.
- blink::mojom::DisplayMode display = blink::mojom::DisplayMode::kUndefined;
-
- // Empty if the parsing failed, the field was not present, or all the
- // values inside the JSON array were invalid.
- std::vector<blink::mojom::DisplayMode> display_override;
-
- // Set to device::mojom::ScreenOrientationLockType::DEFAULT if the parsing
- // failed or the field was not present.
- device::mojom::ScreenOrientationLockType orientation =
- device::mojom::ScreenOrientationLockType::DEFAULT;
-
- // Empty if the parsing failed, the field was not present, or all the
- // icons inside the JSON array were invalid.
- std::vector<ImageResource> icons;
-
- // Empty if the parsing failed, the field was not present, or all the
- // screenshots inside the JSON array were invalid.
- std::vector<ImageResource> screenshots;
-
- // Empty if the parsing failed, the field was not present, or all the
- // icons inside the JSON array were invalid.
- std::vector<ShortcutItem> shortcuts;
-
- // Null if parsing failed or the field was not present.
- absl::optional<ShareTarget> share_target;
-
- // Empty if parsing failed or the field was not present.
- // TODO(crbug.com/829689): This field is non-standard and part of a Chrome
- // experiment. See:
- // https://github.com/WICG/file-handling/blob/master/explainer.md
- std::vector<FileHandler> file_handlers;
-
- // Empty if parsing failed or the field was not present.
- // TODO(crbug.com/1019239): This is going into the mainline manifest spec,
- // remove the TODO once that PR goes in.
- // The URLProtocolHandler explainer can be found here:
- // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/URLProtocolHandler/explainer.md
- std::vector<ProtocolHandler> protocol_handlers;
-
- // TODO(crbug.com/1072058): This field is non-standard and part of an
- // experiment. See:
- // https://github.com/WICG/pwa-url-handler/blob/master/explainer.md
- // Empty if the parsing failed, the field was not present, empty or all the
- // entries inside the array were invalid.
- std::vector<UrlHandler> url_handlers;
-
- // TODO(crbug.com/1185678): This field is non-standard and part of a manifest
- // incubation. See:
- // https://wicg.github.io/manifest-incubations/index.html#dfn-note_taking
- // Null if parsing failed or the field was not present.
- absl::optional<NoteTaking> note_taking;
-
- // Empty if the parsing failed, the field was not present, empty or all the
- // applications inside the array were invalid. The order of the array
- // indicates the priority of the application to use.
- std::vector<RelatedApplication> related_applications;
-
- // A boolean that is used as a hint for the user agent to say that related
- // applications should be preferred over the web application. False if missing
- // or there is a parsing failure.
- bool prefer_related_applications = false;
-
- // Null if field is not present or parsing failed.
- absl::optional<SkColor> theme_color;
-
- // Null if field is not present or parsing failed.
- absl::optional<SkColor> background_color;
-
- // This is a proprietary extension of the web Manifest, double-check that it
- // is okay to use this entry.
- // Null if parsing failed or the field was not present.
- absl::optional<std::u16string> gcm_sender_id;
-
- // Empty if the parsing failed. Otherwise defaults to the start URL (or
- // document URL if start URL isn't present) with filename, query, and fragment
- // removed.
- GURL scope;
-
- mojom::CaptureLinks capture_links = mojom::CaptureLinks::kUndefined;
+ // This struct replicates ManifestLaunchHandler with an added copy
+ // constructor, this enables containing classes to have a default copy
+ // constructor.
+ // TODO(crbug.com/1236358): Use mojom::blink::ManifestLaunchHandler directly
+ // when it can support copy/move.
+ // See ManifestLaunchHandler for class comments.
+ struct BLINK_COMMON_EXPORT LaunchHandler {
+ using RouteTo = mojom::ManifestLaunchHandler_RouteTo;
+ using NavigateExistingClient =
+ mojom::ManifestLaunchHandler_NavigateExistingClient;
+
+ bool operator==(const LaunchHandler& other) const;
+ bool operator!=(const LaunchHandler& other) const;
+
+ RouteTo route_to = RouteTo::kAuto;
+ NavigateExistingClient navigate_existing_client =
+ NavigateExistingClient::kAlways;
+ };
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/manifest/manifest_icon_selector.h b/chromium/third_party/blink/public/common/manifest/manifest_icon_selector.h
index f72a614c155..27792a029fa 100644
--- a/chromium/third_party/blink/public/common/manifest/manifest_icon_selector.h
+++ b/chromium/third_party/blink/public/common/manifest/manifest_icon_selector.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_ICON_SELECTOR_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_ICON_SELECTOR_H_
-#include "base/macros.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-shared.h"
#include "url/gurl.h"
@@ -17,6 +16,10 @@ namespace blink {
// This follows very basic heuristics -- improvements are welcome.
class BLINK_COMMON_EXPORT ManifestIconSelector {
public:
+ ManifestIconSelector() = delete;
+ ManifestIconSelector(const ManifestIconSelector&) = delete;
+ ManifestIconSelector& operator=(const ManifestIconSelector&) = delete;
+
// Runs the algorithm to find the best matching icon in the icons listed in
// the Manifest. Size is defined in pixels.
//
@@ -40,9 +43,6 @@ class BLINK_COMMON_EXPORT ManifestIconSelector {
int minimum_icon_height_in_px,
float max_width_to_height_ratio,
blink::mojom::ManifestImageResource_Purpose purpose);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ManifestIconSelector);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/manifest/manifest_mojom_traits.h b/chromium/third_party/blink/public/common/manifest/manifest_mojom_traits.h
index 650325729f1..e9779a8015a 100644
--- a/chromium/third_party/blink/public/common/manifest/manifest_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/manifest/manifest_mojom_traits.h
@@ -36,132 +36,6 @@ inline absl::optional<base::StringPiece16> TruncateOptionalString16(
template <>
struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ManifestDataView, ::blink::Manifest> {
- static bool IsNull(const ::blink::Manifest& manifest) {
- return manifest.IsEmpty();
- }
-
- static void SetToNull(::blink::Manifest* manifest) {
- *manifest = ::blink::Manifest();
- }
-
- static absl::optional<base::StringPiece16> name(
- const ::blink::Manifest& manifest) {
- return internal::TruncateOptionalString16(manifest.name);
- }
-
- static absl::optional<base::StringPiece16> short_name(
- const ::blink::Manifest& manifest) {
- return internal::TruncateOptionalString16(manifest.short_name);
- }
-
- static absl::optional<base::StringPiece16> description(
- const ::blink::Manifest& manifest) {
- return internal::TruncateOptionalString16(manifest.description);
- }
-
- static absl::optional<base::StringPiece16> gcm_sender_id(
- const ::blink::Manifest& manifest) {
- return internal::TruncateOptionalString16(manifest.gcm_sender_id);
- }
-
- static const GURL& start_url(const ::blink::Manifest& manifest) {
- return manifest.start_url;
- }
-
- static const GURL& scope(const ::blink::Manifest& manifest) {
- return manifest.scope;
- }
-
- static blink::mojom::DisplayMode display(const ::blink::Manifest& manifest) {
- return manifest.display;
- }
-
- static const std::vector<blink::mojom::DisplayMode> display_override(
- const ::blink::Manifest& manifest) {
- return manifest.display_override;
- }
-
- static device::mojom::ScreenOrientationLockType orientation(
- const ::blink::Manifest& manifest) {
- return manifest.orientation;
- }
-
- static bool has_theme_color(const ::blink::Manifest& m) {
- return m.theme_color.has_value();
- }
-
- static uint32_t theme_color(const ::blink::Manifest& m) {
- return m.theme_color.value_or(0);
- }
-
- static bool has_background_color(const ::blink::Manifest& m) {
- return m.background_color.has_value();
- }
-
- static uint32_t background_color(const ::blink::Manifest& m) {
- return m.background_color.value_or(0);
- }
-
- static const std::vector<::blink::Manifest::ImageResource>& icons(
- const ::blink::Manifest& manifest) {
- return manifest.icons;
- }
-
- static const std::vector<::blink::Manifest::ImageResource>& screenshots(
- const ::blink::Manifest& manifest) {
- return manifest.screenshots;
- }
-
- static const std::vector<::blink::Manifest::ShortcutItem>& shortcuts(
- const ::blink::Manifest& manifest) {
- return manifest.shortcuts;
- }
-
- static const absl::optional<::blink::Manifest::ShareTarget>& share_target(
- const ::blink::Manifest& manifest) {
- return manifest.share_target;
- }
-
- static const std::vector<::blink::Manifest::FileHandler>& file_handlers(
- const ::blink::Manifest& manifest) {
- return manifest.file_handlers;
- }
-
- static const std::vector<::blink::Manifest::ProtocolHandler>&
- protocol_handlers(const ::blink::Manifest& manifest) {
- return manifest.protocol_handlers;
- }
-
- static const std::vector<::blink::Manifest::UrlHandler>& url_handlers(
- const ::blink::Manifest& manifest) {
- return manifest.url_handlers;
- }
-
- static const absl::optional<::blink::Manifest::NoteTaking>& note_taking(
- const ::blink::Manifest& manifest) {
- return manifest.note_taking;
- }
-
- static const std::vector<::blink::Manifest::RelatedApplication>&
- related_applications(const ::blink::Manifest& manifest) {
- return manifest.related_applications;
- }
-
- static bool prefer_related_applications(const ::blink::Manifest& manifest) {
- return manifest.prefer_related_applications;
- }
-
- static blink::mojom::CaptureLinks capture_links(
- const ::blink::Manifest& manifest) {
- return manifest.capture_links;
- }
-
- static bool Read(blink::mojom::ManifestDataView data, ::blink::Manifest* out);
-};
-
-template <>
-struct BLINK_COMMON_EXPORT
StructTraits<blink::mojom::ManifestImageResourceDataView,
::blink::Manifest::ImageResource> {
static const GURL& src(const ::blink::Manifest::ImageResource& icon) {
@@ -266,24 +140,6 @@ struct BLINK_COMMON_EXPORT
template <>
struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ManifestUrlHandlerDataView,
- ::blink::Manifest::UrlHandler> {
- static const url::Origin& origin(
- const ::blink::Manifest::UrlHandler& url_handler) {
- return url_handler.origin;
- }
-
- static bool has_origin_wildcard(
- const ::blink::Manifest::UrlHandler& url_handler) {
- return url_handler.has_origin_wildcard;
- }
-
- static bool Read(blink::mojom::ManifestUrlHandlerDataView data,
- ::blink::Manifest::UrlHandler* out);
-};
-
-template <>
-struct BLINK_COMMON_EXPORT
StructTraits<blink::mojom::ManifestShareTargetParamsDataView,
::blink::Manifest::ShareTargetParams> {
static const absl::optional<base::StringPiece16> text(
@@ -333,52 +189,21 @@ struct BLINK_COMMON_EXPORT
template <>
struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ManifestFileHandlerDataView,
- ::blink::Manifest::FileHandler> {
- static const GURL& action(const ::blink::Manifest::FileHandler& entry) {
- return entry.action;
- }
-
- static const std::u16string& name(
- const ::blink::Manifest::FileHandler& entry) {
- return entry.name;
- }
-
- static const std::map<std::u16string, std::vector<std::u16string>>& accept(
- const ::blink::Manifest::FileHandler& entry) {
- return entry.accept;
- }
-
- static bool Read(blink::mojom::ManifestFileHandlerDataView data,
- ::blink::Manifest::FileHandler* out);
-};
-
-template <>
-struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ManifestProtocolHandlerDataView,
- ::blink::Manifest::ProtocolHandler> {
- static base::StringPiece16 protocol(
- const ::blink::Manifest::ProtocolHandler& protocol) {
- return internal::TruncateString16(protocol.protocol);
- }
- static const GURL& url(const ::blink::Manifest::ProtocolHandler& protocol) {
- return protocol.url;
+ StructTraits<blink::mojom::ManifestLaunchHandlerDataView,
+ ::blink::Manifest::LaunchHandler> {
+ static blink::mojom::ManifestLaunchHandler::RouteTo route_to(
+ const ::blink::Manifest::LaunchHandler& launch_handler) {
+ return launch_handler.route_to;
}
- static bool Read(blink::mojom::ManifestProtocolHandlerDataView data,
- ::blink::Manifest::ProtocolHandler* out);
-};
-template <>
-struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ManifestNoteTakingDataView,
- ::blink::Manifest::NoteTaking> {
- static const GURL new_note_url(
- const ::blink::Manifest::NoteTaking& note_taking) {
- return note_taking.new_note_url;
+ static blink::mojom::ManifestLaunchHandler::NavigateExistingClient
+ navigate_existing_client(
+ const ::blink::Manifest::LaunchHandler& launch_handler) {
+ return launch_handler.navigate_existing_client;
}
- static bool Read(blink::mojom::ManifestNoteTakingDataView data,
- ::blink::Manifest::NoteTaking* out);
+ static bool Read(blink::mojom::ManifestLaunchHandlerDataView data,
+ ::blink::Manifest::LaunchHandler* out);
};
} // namespace mojo
diff --git a/chromium/third_party/blink/public/common/manifest/manifest_util.h b/chromium/third_party/blink/public/common/manifest/manifest_util.h
index 75574774dab..68992ee7eda 100644
--- a/chromium/third_party/blink/public/common/manifest/manifest_util.h
+++ b/chromium/third_party/blink/public/common/manifest/manifest_util.h
@@ -7,13 +7,21 @@
#include <string>
+#include "base/strings/string_piece.h"
#include "services/device/public/mojom/screen_orientation_lock_types.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/capture_links.mojom-forward.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-forward.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
namespace blink {
+// Checks whether the manifest has no fields set.
+BLINK_COMMON_EXPORT bool IsEmptyManifest(const mojom::Manifest& manifest);
+BLINK_COMMON_EXPORT bool IsEmptyManifest(const mojom::ManifestPtr& manifest);
+
// Converts a blink::mojom::DisplayMode to a string. Returns one of
// https://www.w3.org/TR/appmanifest/#dfn-display-modes-values. Return values
// are lowercase. Returns an empty string for DisplayMode::kUndefined.
@@ -52,6 +60,13 @@ WebScreenOrientationLockTypeFromString(const std::string& orientation);
BLINK_COMMON_EXPORT mojom::CaptureLinks CaptureLinksFromString(
const std::string& capture_links);
+BLINK_COMMON_EXPORT absl::optional<Manifest::LaunchHandler::RouteTo>
+RouteToFromString(const std::string& route_to);
+
+BLINK_COMMON_EXPORT
+absl::optional<Manifest::LaunchHandler::NavigateExistingClient>
+NavigateExistingClientFromString(const std::string& navigate_existing_client);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_UTIL_H_
diff --git a/chromium/third_party/blink/public/common/media/display_type.h b/chromium/third_party/blink/public/common/media/display_type.h
index e5f21160f81..2ff0e6f3548 100644
--- a/chromium/third_party/blink/public/common/media/display_type.h
+++ b/chromium/third_party/blink/public/common/media/display_type.h
@@ -7,7 +7,7 @@
namespace blink {
-// TODO(https://crbug.com/1116920): Move back into WebMediaPlayer after
+// TODO(https://crbug.com/1198341): Move back into WebMediaPlayer after
// onion-souping media/blink.
enum class DisplayType {
// Playback is happening inline.
diff --git a/chromium/third_party/blink/public/common/media/watch_time_component.h b/chromium/third_party/blink/public/common/media/watch_time_component.h
index 13e57806514..5b217321912 100644
--- a/chromium/third_party/blink/public/common/media/watch_time_component.h
+++ b/chromium/third_party/blink/public/common/media/watch_time_component.h
@@ -8,7 +8,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "media/base/timestamp_constants.h"
#include "media/base/watch_time_keys.h"
@@ -25,7 +24,7 @@ namespace blink {
// time, flip the actual value, and then start recording from that previous
// finalize time. They may also clear the pending value flip if the value
// changes back to the previous value.
-// TODO(https://crbug.com/1116920): Move to renderer/platform/media once its
+// TODO(https://crbug.com/1198341): Move to renderer/platform/media once its
// dependencies are moved to Blink.
template <typename T>
class WatchTimeComponent {
@@ -52,6 +51,8 @@ class WatchTimeComponent {
ValueToKeyCB value_to_key_cb,
GetMediaTimeCB get_media_time_cb,
media::mojom::WatchTimeRecorder* recorder);
+ WatchTimeComponent(const WatchTimeComponent&) = delete;
+ WatchTimeComponent& operator=(const WatchTimeComponent&) = delete;
~WatchTimeComponent();
// Called when the main WatchTimeReporter timer is started. Reinitializes
@@ -127,8 +128,6 @@ class WatchTimeComponent {
// The last media timestamp seen by RecordWatchTime().
base::TimeDelta last_timestamp_ = media::kNoTimestamp;
-
- DISALLOW_COPY_AND_ASSIGN(WatchTimeComponent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/media/watch_time_reporter.h b/chromium/third_party/blink/public/common/media/watch_time_reporter.h
index f4d10f6b9f1..08cdc7c6d61 100644
--- a/chromium/third_party/blink/public/common/media/watch_time_reporter.h
+++ b/chromium/third_party/blink/public/common/media/watch_time_reporter.h
@@ -25,10 +25,6 @@
#include "ui/gfx/geometry/size.h"
#include "url/origin.h"
-namespace media {
-class WatchTimeReporterTest;
-}
-
namespace blink {
// Class for monitoring and reporting watch time in response to various state
@@ -92,6 +88,8 @@ class BLINK_COMMON_EXPORT WatchTimeReporter : base::PowerStateObserver {
media::mojom::MediaMetricsProvider* provider,
scoped_refptr<base::SequencedTaskRunner> task_runner,
const base::TickClock* tick_clock = nullptr);
+ WatchTimeReporter(const WatchTimeReporter&) = delete;
+ WatchTimeReporter& operator=(const WatchTimeReporter&) = delete;
~WatchTimeReporter() override;
// These methods are used to ensure that watch time is only reported for media
@@ -159,7 +157,7 @@ class BLINK_COMMON_EXPORT WatchTimeReporter : base::PowerStateObserver {
void OnDurationChanged(base::TimeDelta duration);
private:
- friend class media::WatchTimeReporterTest;
+ friend class WatchTimeReporterTest;
// Internal constructor for marking background status.
WatchTimeReporter(media::mojom::PlaybackPropertiesPtr properties,
@@ -265,8 +263,6 @@ class BLINK_COMMON_EXPORT WatchTimeReporter : base::PowerStateObserver {
// Similar to the above, but for muted audio+video watch time. Configured as
// an audio+video WatchTimeReporter with |is_muted_| set to true.
std::unique_ptr<WatchTimeReporter> muted_reporter_;
-
- DISALLOW_COPY_AND_ASSIGN(WatchTimeReporter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/mediastream/OWNERS b/chromium/third_party/blink/public/common/mediastream/OWNERS
index 7653ee493bb..b3bb856f7f8 100644
--- a/chromium/third_party/blink/public/common/mediastream/OWNERS
+++ b/chromium/third_party/blink/public/common/mediastream/OWNERS
@@ -1,5 +1,4 @@
guidou@chromium.org
-hbos@chromium.org
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/common/mediastream/media_devices.h b/chromium/third_party/blink/public/common/mediastream/media_devices.h
index b0cba2acbe4..a106fe86598 100644
--- a/chromium/third_party/blink/public/common/mediastream/media_devices.h
+++ b/chromium/third_party/blink/public/common/mediastream/media_devices.h
@@ -10,7 +10,6 @@
#include "media/base/video_facing.h"
#include "media/capture/video/video_capture_device_descriptor.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-shared.h"
diff --git a/chromium/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h b/chromium/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
index d4751ec0af9..ab3ec1469b8 100644
--- a/chromium/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MEDIASTREAM_MEDIA_STREAM_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MEDIASTREAM_MEDIA_STREAM_MOJOM_TRAITS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/mediastream/media_stream_controls.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
diff --git a/chromium/third_party/blink/public/common/mediastream/media_stream_request.h b/chromium/third_party/blink/public/common/mediastream/media_stream_request.h
index 1eaed249395..14cf0eab04e 100644
--- a/chromium/third_party/blink/public/common/mediastream/media_stream_request.h
+++ b/chromium/third_party/blink/public/common/mediastream/media_stream_request.h
@@ -16,6 +16,7 @@
#include "media/base/video_facing.h"
#include "media/capture/video/video_capture_device_descriptor.h"
#include "media/mojo/mojom/display_media_information.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
diff --git a/chromium/third_party/blink/public/common/messaging/cloneable_message.h b/chromium/third_party/blink/public/common/messaging/cloneable_message.h
index 50567433d92..ec8d584bc4c 100644
--- a/chromium/third_party/blink/public/common/messaging/cloneable_message.h
+++ b/chromium/third_party/blink/public/common/messaging/cloneable_message.h
@@ -8,7 +8,6 @@
#include <vector>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -74,9 +73,6 @@ struct BLINK_COMMON_EXPORT CloneableMessage {
// FileSystemDirectoryHandles.
std::vector<mojo::PendingRemote<mojom::FileSystemAccessTransferToken>>
file_system_access_tokens;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CloneableMessage);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h b/chromium/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
index a6220196a91..c6f90ddc757 100644
--- a/chromium/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
@@ -7,6 +7,7 @@
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/messaging/cloneable_message.h"
#include "third_party/blink/public/mojom/messaging/cloneable_message.mojom.h"
#include "url/mojom/origin_mojom_traits.h"
diff --git a/chromium/third_party/blink/public/common/messaging/message_port_channel.h b/chromium/third_party/blink/public/common/messaging/message_port_channel.h
index d8895b7b45e..27f0fc44ea7 100644
--- a/chromium/third_party/blink/public/common/messaging/message_port_channel.h
+++ b/chromium/third_party/blink/public/common/messaging/message_port_channel.h
@@ -7,7 +7,6 @@
#include <vector>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/common_export.h"
diff --git a/chromium/third_party/blink/public/common/messaging/transferable_message.h b/chromium/third_party/blink/public/common/messaging/transferable_message.h
index 37b25997ea4..0a56d58625f 100644
--- a/chromium/third_party/blink/public/common/messaging/transferable_message.h
+++ b/chromium/third_party/blink/public/common/messaging/transferable_message.h
@@ -7,8 +7,6 @@
#include <vector>
-#include "base/containers/span.h"
-#include "base/macros.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/messaging/cloneable_message.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
@@ -42,9 +40,6 @@ struct BLINK_COMMON_EXPORT TransferableMessage : public CloneableMessage {
// Whether payment request capability is delegated to the destination frame.
bool delegate_payment_request = false;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TransferableMessage);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/messaging/web_message_port.h b/chromium/third_party/blink/public/common/messaging/web_message_port.h
index 713e217c7a3..43b8469f62c 100644
--- a/chromium/third_party/blink/public/common/messaging/web_message_port.h
+++ b/chromium/third_party/blink/public/common/messaging/web_message_port.h
@@ -83,6 +83,10 @@ class BLINK_COMMON_EXPORT WebMessagePort : public mojo::MessageReceiver {
// are conjugates of each other.
static std::pair<WebMessagePort, WebMessagePort> CreatePair();
+ // Wraps one end of a message channel. |port|'s mojo pipe must
+ // be paired, valid and not entangled.
+ static WebMessagePort Create(MessagePortDescriptor port);
+
// Sets a message receiver for this message port. Once bound any incoming
// messages to this port will be routed to the provided |receiver| with
// callbacks invoked on the provided |runner|. Note that if you set a receiver
diff --git a/chromium/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h b/chromium/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h
index 9b83e20b6bd..cb62777931d 100644
--- a/chromium/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h
+++ b/chromium/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h
@@ -15,6 +15,7 @@ namespace blink {
struct BLINK_COMMON_EXPORT MobileFriendliness {
MobileFriendliness() = default;
MobileFriendliness(const MobileFriendliness&) = default;
+ MobileFriendliness& operator=(const MobileFriendliness&) = default;
bool operator==(const MobileFriendliness& other) const;
bool operator!=(const MobileFriendliness& other) const {
diff --git a/chromium/third_party/blink/public/common/navigation/impression.h b/chromium/third_party/blink/public/common/navigation/impression.h
index 8935c867d3e..9072c957023 100644
--- a/chromium/third_party/blink/public/common/navigation/impression.h
+++ b/chromium/third_party/blink/public/common/navigation/impression.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "url/origin.h"
diff --git a/chromium/third_party/blink/public/common/navigation/impression_mojom_traits.h b/chromium/third_party/blink/public/common/navigation/impression_mojom_traits.h
index 9ae2781918e..3884149d919 100644
--- a/chromium/third_party/blink/public/common/navigation/impression_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/navigation/impression_mojom_traits.h
@@ -8,6 +8,7 @@
#include "build/build_config.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/navigation/impression.h"
#include "third_party/blink/public/mojom/conversions/conversions.mojom.h"
diff --git a/chromium/third_party/blink/public/common/navigation/navigation_params.h b/chromium/third_party/blink/public/common/navigation/navigation_params.h
new file mode 100644
index 00000000000..226f6122cbe
--- /dev/null
+++ b/chromium/third_party/blink/public/common/navigation/navigation_params.h
@@ -0,0 +1,20 @@
+// 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_PUBLIC_COMMON_NAVIGATION_NAVIGATION_PARAMS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_NAVIGATION_PARAMS_H_
+
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
+
+namespace blink {
+
+BLINK_COMMON_EXPORT mojom::CommonNavigationParamsPtr
+CreateCommonNavigationParams();
+BLINK_COMMON_EXPORT mojom::CommitNavigationParamsPtr
+CreateCommitNavigationParams();
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_NAVIGATION_PARAMS_H_
diff --git a/chromium/third_party/blink/public/common/navigation/navigation_params_mojom_traits.h b/chromium/third_party/blink/public/common/navigation/navigation_params_mojom_traits.h
new file mode 100644
index 00000000000..52495538edc
--- /dev/null
+++ b/chromium/third_party/blink/public/common/navigation/navigation_params_mojom_traits.h
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_NAVIGATION_PARAMS_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_NAVIGATION_PARAMS_MOJOM_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/clone_traits.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
+#include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom.h"
+
+namespace mojo {
+
+template <>
+struct CloneTraits<blink::mojom::PrefetchedSignedExchangeInfoPtr, true> {
+ static blink::mojom::PrefetchedSignedExchangeInfoPtr Clone(
+ const blink::mojom::PrefetchedSignedExchangeInfoPtr& input) {
+ return blink::mojom::PrefetchedSignedExchangeInfo::New(
+ mojo::Clone(input->outer_url), mojo::Clone(input->header_integrity),
+ mojo::Clone(input->inner_url), mojo::Clone(input->inner_response),
+ mojo::PendingRemote<network::mojom::URLLoaderFactory>());
+ }
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_NAVIGATION_PARAMS_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/navigation/prefetched_signed_exchange_info_mojom_traits.h b/chromium/third_party/blink/public/common/navigation/prefetched_signed_exchange_info_mojom_traits.h
new file mode 100644
index 00000000000..493b3c2e947
--- /dev/null
+++ b/chromium/third_party/blink/public/common/navigation/prefetched_signed_exchange_info_mojom_traits.h
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_PREFETCHED_SIGNED_EXCHANGE_INFO_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_PREFETCHED_SIGNED_EXCHANGE_INFO_MOJOM_TRAITS_H_
+
+#include <string>
+
+#include "mojo/public/cpp/base/byte_string_mojom_traits.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "net/base/hash_value.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct BLINK_COMMON_EXPORT
+ StructTraits<blink::mojom::SHA256HashValueDataView, net::SHA256HashValue> {
+ static const std::string data(const net::SHA256HashValue& value) {
+ return std::string(reinterpret_cast<const char*>(value.data),
+ sizeof(value.data));
+ }
+
+ static bool Read(blink::mojom::SHA256HashValueDataView input,
+ net::SHA256HashValue* out);
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_PREFETCHED_SIGNED_EXCHANGE_INFO_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/net/ip_address_space_util.h b/chromium/third_party/blink/public/common/net/ip_address_space_util.h
deleted file mode 100644
index 8521f73a81d..00000000000
--- a/chromium/third_party/blink/public/common/net/ip_address_space_util.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_NET_IP_ADDRESS_SPACE_UTIL_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_NET_IP_ADDRESS_SPACE_UTIL_H_
-
-#include "services/network/public/mojom/ip_address_space.mojom.h"
-#include "services/network/public/mojom/url_response_head.mojom-forward.h"
-#include "third_party/blink/public/common/common_export.h"
-
-class GURL;
-
-namespace net {
-
-class IPEndPoint;
-
-} // namespace net
-
-namespace blink {
-
-// Given a request URL and response information, this function calculates the
-// IPAddressSpace which should be associated with documents or worker global
-// scopes (collectively: request clients) instantiated from this resource.
-//
-// |response_head| may be nullptr. Caller retains ownership. If not nullptr,
-// then |response_head->parsed_headers| must be populated with the result of
-// parsing |response->headers|.
-//
-// WARNING: This function is defined here for proximity with related code and
-// the data structures involved. However since it deals with higher-level
-// concepts too (documents and worker global scopes), it should probably only be
-// used at the content/ layer or above.
-//
-// See: https://wicg.github.io/cors-rfc1918/#address-space
-//
-// TODO(https://crbug.com/1134601): This implementation treats requests that
-// don't use a URL loader (`about:blank`), as well as requests whose IP address
-// is invalid (`about:srcdoc`, `blob:`, etc.) as `kUnknown`. This is incorrect.
-// We'll eventually want to make sure we inherit from the client's creator
-// in some cases), but safe, as `kUnknown` is treated the same as `kPublic`.
-network::mojom::IPAddressSpace BLINK_COMMON_EXPORT CalculateClientAddressSpace(
- const GURL& url,
- const network::mojom::URLResponseHead* response_head);
-
-// Given a response URL and the IP endpoint the requested resource was fetched
-// from, this function calculates the IPAddressSpace of the requested resource.
-//
-// As opposed to CalculateClientAddressSpace(), this function is used to
-// determine the address space of the *target* of a fetch, for comparison with
-// that of the client of the fetch.
-//
-// See: https://wicg.github.io/cors-rfc1918/#integration-fetch
-network::mojom::IPAddressSpace BLINK_COMMON_EXPORT
-CalculateResourceAddressSpace(const GURL& url, const net::IPEndPoint& endpoint);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_NET_IP_ADDRESS_SPACE_UTIL_H_
diff --git a/chromium/third_party/blink/public/common/notifications/notification_mojom_traits.h b/chromium/third_party/blink/public/common/notifications/notification_mojom_traits.h
index 878a5d0a5f7..9d1128f4371 100644
--- a/chromium/third_party/blink/public/common/notifications/notification_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/notifications/notification_mojom_traits.h
@@ -12,6 +12,7 @@
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "skia/public/mojom/bitmap_skbitmap_mojom_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/notifications/notification_resources.h"
#include "third_party/blink/public/common/notifications/platform_notification_data.h"
diff --git a/chromium/third_party/blink/public/common/origin_trials/origin_trial_policy.h b/chromium/third_party/blink/public/common/origin_trials/origin_trial_policy.h
index 879cea4267f..0073107f254 100644
--- a/chromium/third_party/blink/public/common/origin_trials/origin_trial_policy.h
+++ b/chromium/third_party/blink/public/common/origin_trials/origin_trial_policy.h
@@ -5,7 +5,10 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_ORIGIN_TRIAL_POLICY_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_ORIGIN_TRIAL_POLICY_H_
+#include <vector>
+
#include "base/strings/string_piece.h"
+#include "third_party/blink/public/common/origin_trials/origin_trial_public_key.h"
#include "url/gurl.h"
namespace blink {
@@ -17,9 +20,7 @@ class OriginTrialPolicy {
virtual ~OriginTrialPolicy() = default;
virtual bool IsOriginTrialsSupported() const { return false; }
- virtual std::vector<base::StringPiece> GetPublicKeys() const {
- return std::vector<base::StringPiece>();
- }
+ virtual const std::vector<OriginTrialPublicKey>& GetPublicKeys() const = 0;
virtual bool IsFeatureDisabled(base::StringPiece feature) const {
return false;
}
diff --git a/chromium/third_party/blink/public/common/origin_trials/origin_trial_public_key.h b/chromium/third_party/blink/public/common/origin_trials/origin_trial_public_key.h
new file mode 100644
index 00000000000..c63049b1749
--- /dev/null
+++ b/chromium/third_party/blink/public/common/origin_trials/origin_trial_public_key.h
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_ORIGIN_TRIAL_PUBLIC_KEY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_ORIGIN_TRIAL_PUBLIC_KEY_H_
+
+#include <array>
+
+namespace blink {
+
+// Public key must be 32 bytes long for Ed25519.
+using OriginTrialPublicKey = std::array<uint8_t, 32>;
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_ORIGIN_TRIAL_PUBLIC_KEY_H_
diff --git a/chromium/third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h b/chromium/third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h
new file mode 100644
index 00000000000..9b065579e59
--- /dev/null
+++ b/chromium/third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_SCOPED_TEST_ORIGIN_TRIAL_POLICY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_SCOPED_TEST_ORIGIN_TRIAL_POLICY_H_
+
+#include <vector>
+
+#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
+
+namespace blink {
+
+// This class overrides the `OriginTrialPolicy` in `TrialTokenValidator`
+// to use the test public key when the instance is in scope.
+class ScopedTestOriginTrialPolicy : public OriginTrialPolicy {
+ public:
+ ScopedTestOriginTrialPolicy();
+ ~ScopedTestOriginTrialPolicy() override;
+
+ bool IsOriginTrialsSupported() const override;
+ const std::vector<OriginTrialPublicKey>& GetPublicKeys() const override;
+ bool IsOriginSecure(const GURL& url) const override;
+
+ private:
+ std::vector<OriginTrialPublicKey> public_keys_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_TRIALS_SCOPED_TEST_ORIGIN_TRIAL_POLICY_H_
diff --git a/chromium/third_party/blink/public/common/origin_trials/trial_token.h b/chromium/third_party/blink/public/common/origin_trials/trial_token.h
index bce527410fa..43ba2fd14ba 100644
--- a/chromium/third_party/blink/public/common/origin_trials/trial_token.h
+++ b/chromium/third_party/blink/public/common/origin_trials/trial_token.h
@@ -11,6 +11,7 @@
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/origin_trials/origin_trial_public_key.h"
#include "url/origin.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
@@ -61,9 +62,10 @@ class BLINK_COMMON_EXPORT TrialToken {
// appropriate for a given origin / feature. It only means that it is
// correctly formatted and signed by the supplied public key, and can be
// parsed.
- static std::unique_ptr<TrialToken> From(base::StringPiece token_text,
- base::StringPiece public_key,
- OriginTrialTokenStatus* out_status);
+ static std::unique_ptr<TrialToken> From(
+ base::StringPiece token_text,
+ const OriginTrialPublicKey& public_key,
+ OriginTrialTokenStatus* out_status);
// Returns success if this token is appropriate for use by the given origin
// and has not yet expired. Otherwise, the return value indicates why the
@@ -102,7 +104,7 @@ class BLINK_COMMON_EXPORT TrialToken {
// wrong with the string, and |out_token_payload|, |out_token_signature| and
// |out_token_version| are unchanged.
static OriginTrialTokenStatus Extract(base::StringPiece token_text,
- base::StringPiece public_key,
+ const OriginTrialPublicKey& public_key,
std::string* out_token_payload,
std::string* out_token_signature,
uint8_t* out_token_version);
@@ -118,7 +120,7 @@ class BLINK_COMMON_EXPORT TrialToken {
static bool ValidateSignature(base::StringPiece signature_text,
const std::string& data,
- base::StringPiece public_key);
+ const OriginTrialPublicKey& public_key);
private:
TrialToken(const url::Origin& origin,
diff --git a/chromium/third_party/blink/public/common/origin_trials/trial_token_validator.h b/chromium/third_party/blink/public/common/origin_trials/trial_token_validator.h
index 3d3c2201979..e100d5e73e0 100644
--- a/chromium/third_party/blink/public/common/origin_trials/trial_token_validator.h
+++ b/chromium/third_party/blink/public/common/origin_trials/trial_token_validator.h
@@ -57,15 +57,38 @@ class BLINK_COMMON_EXPORT TrialTokenValidator {
const url::Origin* third_party_origin,
base::Time current_time) const;
+ // |request| must not be nullptr.
+ // NOTE: This is not currently used, but remains here for future trials.
bool RequestEnablesFeature(const net::URLRequest* request,
base::StringPiece feature_name,
base::Time current_time) const;
+ // Returns whether the given response for the given URL enable the named
+ // Origin or Deprecation Trial at the given time.
+ //
+ // |response_headers| must not be nullptr.
bool RequestEnablesFeature(const GURL& request_url,
const net::HttpResponseHeaders* response_headers,
base::StringPiece feature_name,
base::Time current_time) const;
+ // Similar to |RequestEnablesFeature()|, but for Deprecation Trials that may
+ // be enabled on insecure origins.
+ //
+ // For Origin Trials (as opposed to Deprecation Trials) or Deprecation Trials
+ // that are enabled exclusively on secure origins, use
+ // |RequestEnablesFeature()| instead.
+ //
+ // Functionally, the only difference is that this can return true even if
+ // |request_url|'s origin is not secure.
+ //
+ // |response_headers| must not be nullptr.
+ bool RequestEnablesDeprecatedFeature(
+ const GURL& request_url,
+ const net::HttpResponseHeaders* response_headers,
+ base::StringPiece feature_name,
+ base::Time current_time) const;
+
// Returns all valid tokens in |headers|.
std::unique_ptr<FeatureToTokensMap> GetValidTokensFromHeaders(
const url::Origin& origin,
@@ -84,6 +107,15 @@ class BLINK_COMMON_EXPORT TrialTokenValidator {
static void ResetOriginTrialPolicyGetter();
static bool IsTrialPossibleOnOrigin(const GURL& url);
+
+ private:
+ // Helper for |RequestEnablesFeature()| and
+ // |RequestEnablesDeprecatedFeature()|.
+ bool ResponseBearsValidTokenForFeature(
+ const GURL& request_url,
+ const net::HttpResponseHeaders& response_headers,
+ base::StringPiece feature_name,
+ base::Time current_time) const;
}; // class TrialTokenValidator
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/page/content_to_visible_time_reporter.h b/chromium/third_party/blink/public/common/page/content_to_visible_time_reporter.h
index 71030e0180d..adec43c5ba3 100644
--- a/chromium/third_party/blink/public/common/page/content_to_visible_time_reporter.h
+++ b/chromium/third_party/blink/public/common/page/content_to_visible_time_reporter.h
@@ -8,7 +8,6 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom.h"
diff --git a/chromium/third_party/blink/public/common/page_state/page_state.h b/chromium/third_party/blink/public/common/page_state/page_state.h
index d4ff9d64853..d885072ccdd 100644
--- a/chromium/third_party/blink/public/common/page_state/page_state.h
+++ b/chromium/third_party/blink/public/common/page_state/page_state.h
@@ -9,6 +9,7 @@
#include <vector>
#include "third_party/blink/public/common/common_export.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
class GURL;
@@ -59,6 +60,8 @@ class BLINK_COMMON_EXPORT PageState {
return !(this->Equals(other));
}
+ void WriteIntoTrace(perfetto::TracedValue context) const;
+
private:
PageState(const std::string& data);
diff --git a/chromium/third_party/blink/public/common/permissions_policy/document_policy.h b/chromium/third_party/blink/public/common/permissions_policy/document_policy.h
index eccbca75fe3..86f0f3e63ad 100644
--- a/chromium/third_party/blink/public/common/permissions_policy/document_policy.h
+++ b/chromium/third_party/blink/public/common/permissions_policy/document_policy.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/permissions_policy/document_policy_features.h"
#include "third_party/blink/public/common/permissions_policy/policy_value.h"
@@ -78,6 +77,9 @@ class BLINK_COMMON_EXPORT DocumentPolicy {
static std::unique_ptr<DocumentPolicy> CopyStateFrom(const DocumentPolicy*);
+ DocumentPolicy(const DocumentPolicy&) = delete;
+ DocumentPolicy& operator=(const DocumentPolicy&) = delete;
+
// Returns true if the feature is unrestricted (has its default value for the
// platform)
bool IsFeatureEnabled(mojom::DocumentPolicyFeature feature) const;
@@ -139,8 +141,6 @@ class BLINK_COMMON_EXPORT DocumentPolicy {
internal_feature_state_;
FeatureEndpointMap endpoint_map_;
-
- DISALLOW_COPY_AND_ASSIGN(DocumentPolicy);
};
bool inline operator==(const DocumentPolicy::ParsedDocumentPolicy& lhs,
diff --git a/chromium/third_party/blink/public/common/permissions_policy/permissions_policy.h b/chromium/third_party/blink/public/common/permissions_policy/permissions_policy.h
index 68caa8aa5a4..786b76046a6 100644
--- a/chromium/third_party/blink/public/common/permissions_policy/permissions_policy.h
+++ b/chromium/third_party/blink/public/common/permissions_policy/permissions_policy.h
@@ -8,7 +8,6 @@
#include <map>
#include <vector>
-#include "base/macros.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy_features.h"
@@ -169,6 +168,8 @@ class BLINK_COMMON_EXPORT PermissionsPolicy {
bool matches_opaque_src_{false};
};
+ PermissionsPolicy(const PermissionsPolicy&) = delete;
+ PermissionsPolicy& operator=(const PermissionsPolicy&) = delete;
~PermissionsPolicy();
static std::unique_ptr<PermissionsPolicy> CreateFromParentPolicy(
@@ -245,8 +246,6 @@ class BLINK_COMMON_EXPORT PermissionsPolicy {
PermissionsPolicyFeatureState inherited_policies_;
const PermissionsPolicyFeatureList& feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(PermissionsPolicy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/permissions_policy/permissions_policy_features.h b/chromium/third_party/blink/public/common/permissions_policy/permissions_policy_features.h
index 13de708d1f7..999b004e125 100644
--- a/chromium/third_party/blink/public/common/permissions_policy/permissions_policy_features.h
+++ b/chromium/third_party/blink/public/common/permissions_policy/permissions_policy_features.h
@@ -7,7 +7,6 @@
#include <map>
-#include "base/containers/flat_map.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-forward.h"
diff --git a/chromium/third_party/blink/public/common/permissions_policy/policy_value.h b/chromium/third_party/blink/public/common/permissions_policy/policy_value.h
index 2f05ec4deb8..f6edcf5295a 100644
--- a/chromium/third_party/blink/public/common/permissions_policy/policy_value.h
+++ b/chromium/third_party/blink/public/common/permissions_policy/policy_value.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PERMISSIONS_POLICY_POLICY_VALUE_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PERMISSIONS_POLICY_POLICY_VALUE_H_
-#include "base/macros.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/permissions_policy/policy_value.mojom-shared.h"
@@ -21,6 +20,8 @@ namespace blink {
class BLINK_COMMON_EXPORT PolicyValue {
public:
PolicyValue();
+ PolicyValue(const PolicyValue&);
+ PolicyValue& operator=(const PolicyValue&);
static PolicyValue CreateBool(bool);
static PolicyValue CreateDecDouble(double);
@@ -46,9 +47,6 @@ class BLINK_COMMON_EXPORT PolicyValue {
void SetDoubleValue(double double_value);
void SetIntValue(int32_t int_value);
- // Operater overrides
- PolicyValue& operator=(const PolicyValue& rhs);
-
void SetToMax();
void SetToMin();
diff --git a/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h b/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
index adbd6882756..503c87d5601 100644
--- a/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
+++ b/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
@@ -63,16 +63,14 @@ class BLINK_COMMON_EXPORT IdentifiabilityStudySettings {
// true, it doesn't return false at any point after. The converse is not true.
bool IsActive() const;
- // Returns true if |surface| is allowed to be sampled. Be sure to check
- // ShouldSample before actually collecting a sample.
+ // Returns true if |surface| is allowed.
//
// Will always return false if IsActive() is false. I.e. If the study is
// inactive, all surfaces are considered to be blocked. Hence it is sufficient
// to call this function directly instead of calling IsActive() before it.
bool IsSurfaceAllowed(IdentifiableSurface surface) const;
- // Returns true if |type| is allowed to be sampled. Be sure to check
- // ShouldSample before actually collecting a sample.
+ // Returns true if |type| is allowed.
//
// Will always return false if IsActive() is false. I.e. If the study is
// inactive, all surface types are considered to be blocked. Hence it is
diff --git a/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h b/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
index 2ac98fdaee2..1aa41a66676 100644
--- a/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
+++ b/chromium/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
@@ -26,25 +26,15 @@ class BLINK_COMMON_EXPORT IdentifiabilityStudySettingsProvider {
// Only meaningful if IsActive() returns true.
virtual bool IsAnyTypeOrSurfaceBlocked() const = 0;
- // Returns true if the given surface is allowed to be sampled.
+ // Returns true if the given surface should be sampled.
//
// If IsActive() is false, this method will not be called.
virtual bool IsSurfaceAllowed(IdentifiableSurface surface) const = 0;
- // Returns true if the given surface type is allowed to be sampled.
+ // Returns true if the given surface type should be sampled.
//
// If IsActive() is false, this method will not be called.
virtual bool IsTypeAllowed(IdentifiableSurface::Type type) const = 0;
-
- // Returns the sample rate of the given surface.
- //
- // If IsActive() is false, this method will return 0.
- virtual int SampleRate(IdentifiableSurface surface) const = 0;
-
- // Returns the sample rate of the given surface type.
- //
- // If IsActive() is false, this method will return 0.
- virtual int SampleRate(IdentifiableSurface::Type type) const = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/privacy_budget/identifiable_surface.h b/chromium/third_party/blink/public/common/privacy_budget/identifiable_surface.h
index 0b7740fcfa1..b6a8422f7b2 100644
--- a/chromium/third_party/blink/public/common/privacy_budget/identifiable_surface.h
+++ b/chromium/third_party/blink/public/common/privacy_budget/identifiable_surface.h
@@ -98,11 +98,7 @@ class IdentifiableSurface {
// [1]: //blink/public/mojom/web_feature/web_feature.mojom
kWebFeature = 1,
- // Represents a readback of a canvas. Input is the
- // CanvasRenderingContextType.
- //
- // Was 2 before change to paint op serialization.
- kCanvasReadback = 33,
+ // Reserved 2.
// Represents loading a font locally based on a name lookup that is allowed
// to match either a unique name or a family name. This occurs when a
@@ -216,7 +212,7 @@ class IdentifiableSurface {
// Represents a media query being tested. Input is combination of property
// name and the target value. Output is the result --- true or false.
- kMediaQuery = 28,
+ kMediaQuery_DEPRECATED = 28,
// Represents loading a font locally. Input is the PostScript name.
kLocalFontLoadPostScriptName = 29,
@@ -229,6 +225,8 @@ class IdentifiableSurface {
// (audio or video).
kRtcRtpReceiverGetCapabilities = 32,
+ // Reserved 33.
+
// Metadata that is not reported by the client. Different from
// kReservedInternal in that the inputs are not required to be defined in
// `ukm.xml`.
@@ -238,6 +236,13 @@ class IdentifiableSurface {
// analysis.
kReservedMetadata = 34,
+ // Represents a readback of a canvas. Input is the
+ // CanvasRenderingContextType.
+ //
+ // Was 2 before change to paint op serialization, then 33 before removing
+ // paint op serialization and using only direct canvas2d instrumentation.
+ kCanvasReadback = 35,
+
// We can use values up to and including |kMax|.
kMax = (1 << kTypeBits) - 1
};
diff --git a/chromium/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h b/chromium/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h
index 2eeea7ea673..e1d3e1e9370 100644
--- a/chromium/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h
+++ b/chromium/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h
@@ -85,7 +85,9 @@ class BLINK_COMMON_EXPORT IdentifiableTokenBuilder {
// when |token| is computed in parallel in order to preserve the ordering of
// values that were seen in a concurrent sequence that cannot be
// deterministically interleaved into the primary stream.
- IdentifiableTokenBuilder& AddToken(IdentifiableToken token);
+ IdentifiableTokenBuilder& AddToken(IdentifiableToken token) {
+ return AddValue(token.value_);
+ }
// Helper for feeding primitive types by value efficiently. Anything more
// complicated than that should be passed in as a base::span<const uint8_t>.
diff --git a/chromium/third_party/blink/public/common/sampling_heap_profiler/OWNERS b/chromium/third_party/blink/public/common/sampling_heap_profiler/OWNERS
deleted file mode 100644
index 87c96616bcd..00000000000
--- a/chromium/third_party/blink/public/common/sampling_heap_profiler/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-alph@chromium.org
diff --git a/chromium/third_party/blink/public/common/scheduler/PRESUBMIT.py b/chromium/third_party/blink/public/common/scheduler/PRESUBMIT.py
index 364176ceb2d..c2be81c4142 100644
--- a/chromium/third_party/blink/public/common/scheduler/PRESUBMIT.py
+++ b/chromium/third_party/blink/public/common/scheduler/PRESUBMIT.py
@@ -8,6 +8,9 @@ for more details about the presubmit API built into gcl.
"""
+USE_PYTHON3 = True
+
+
def _RunUmaHistogramChecks(input_api, output_api): # pylint: disable=C0103
import sys
diff --git a/chromium/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h b/chromium/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
index 7dfafc917c1..9918b052711 100644
--- a/chromium/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
+++ b/chromium/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <string>
+#include "base/containers/enum_set.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
@@ -20,6 +21,7 @@ namespace scheduler {
// Please keep in sync with WebSchedulerTrackedFeature in
// tools/metrics/histograms/enums.xml. These values should not be renumbered.
enum class WebSchedulerTrackedFeature : uint32_t {
+ kMinValue = 0,
kWebSocket = 0,
kWebRTC = 1,
@@ -30,12 +32,13 @@ enum class WebSchedulerTrackedFeature : uint32_t {
kSubresourceHasCacheControlNoCache = 4,
kSubresourceHasCacheControlNoStore = 5,
- kPageShowEventListener = 6,
- kPageHideEventListener = 7,
- kBeforeUnloadEventListener = 8,
- kUnloadEventListener = 9,
- kFreezeEventListener = 10,
- kResumeEventListener = 11,
+ // These are unused.
+ // kPageShowEventListener = 6,
+ // kPageHideEventListener = 7,
+ // kBeforeUnloadEventListener = 8,
+ // kUnloadEventListener = 9,
+ // kFreezeEventListener = 10,
+ // kResumeEventListener = 11,
kContainsPlugins = 12,
kDocumentLoaded = 13,
@@ -54,7 +57,7 @@ enum class WebSchedulerTrackedFeature : uint32_t {
// Whether the page tried to request a permission regardless of the outcome.
// TODO(altimin): Track this more accurately depending on the data.
// See permission.mojom for more details.
- kRequestedGeolocationPermission = 19,
+ // kRequestedGeolocationPermission = 19, // No longer blocking.
kRequestedNotificationsPermission = 20,
kRequestedMIDIPermission = 21,
kRequestedAudioCapturePermission = 22,
@@ -69,7 +72,7 @@ enum class WebSchedulerTrackedFeature : uint32_t {
kIndexedDBConnection = 28,
// kWebGL = 29. Removed after implementing WebGL support.
- kWebVR = 30,
+ // kWebVR = 30. The entire feature has been deleted.
kWebXR = 31,
kSharedWorker = 32,
@@ -103,11 +106,17 @@ enum class WebSchedulerTrackedFeature : uint32_t {
kIsolatedWorldScript = 54,
kInjectedStyleSheet = 55,
kMediaSessionImplOnServiceCreated = 56,
+ kWebTransport = 57,
// NB: This enum is used in a bitmask, so kMaxValue must be less than 64.
- kMaxValue = kMediaSessionImplOnServiceCreated,
+ kMaxValue = kWebTransport,
};
+using WebSchedulerTrackedFeatures =
+ base::EnumSet<WebSchedulerTrackedFeature,
+ WebSchedulerTrackedFeature::kMinValue,
+ WebSchedulerTrackedFeature::kMaxValue>;
+
static_assert(static_cast<uint32_t>(WebSchedulerTrackedFeature::kMaxValue) < 64,
"This enum is used in a bitmask, so the values should fit into a"
"64-bit integer");
@@ -128,8 +137,8 @@ BLINK_COMMON_EXPORT constexpr uint64_t FeatureToBit(
// lifetime of the page.
BLINK_COMMON_EXPORT bool IsFeatureSticky(WebSchedulerTrackedFeature feature);
-// All the sticky features in bitmask form.
-BLINK_COMMON_EXPORT uint64_t StickyFeaturesBitmask();
+// All the sticky features.
+BLINK_COMMON_EXPORT WebSchedulerTrackedFeatures StickyFeatures();
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/scheme_registry.h b/chromium/third_party/blink/public/common/scheme_registry.h
new file mode 100644
index 00000000000..7ce8ce4534b
--- /dev/null
+++ b/chromium/third_party/blink/public/common/scheme_registry.h
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEME_REGISTRY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEME_REGISTRY_H_
+
+#include <string>
+
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+
+// Scheme registry interface that can be used both in the browser and renderer
+// processes. See blink::SchemeRegistry for the methods that are only needed
+// in renderers. Use url::SchemeRegistry for more generic and lower-layer
+// interfaces that can live in //url layer.
+//
+// "This registry is not thread-safe, registering or removing schemes need to be
+// done before multi-thread access to the registry start to happen, or entire
+// access to this registry must be done on the single thread. Typically, it is
+// expected that Register* methods are called by RegisterContentSchemes during
+// the process initialization, and Remove* methods are only called by tests."
+//
+// TODO (jfernandez): Add DCHECKs to ensure mutable access is done before the
+// threads are created.
+class BLINK_COMMON_EXPORT CommonSchemeRegistry {
+ public:
+ // Schemes that represent browser extensions.
+ static void RegisterURLSchemeAsExtension(const std::string& scheme);
+ static void RemoveURLSchemeAsExtensionForTest(const std::string& scheme);
+ static bool IsExtensionScheme(const std::string& scheme);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEME_REGISTRY_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/address_space_feature.h b/chromium/third_party/blink/public/common/security/address_space_feature.h
index db7c6f59966..43e8da4b197 100644
--- a/chromium/third_party/blink/renderer/core/loader/address_space_feature.h
+++ b/chromium/third_party/blink/public/common/security/address_space_feature.h
@@ -28,20 +28,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_ADDRESS_SPACE_FEATURE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_ADDRESS_SPACE_FEATURE_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SECURITY_ADDRESS_SPACE_FEATURE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SECURITY_ADDRESS_SPACE_FEATURE_H_
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
-#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
namespace blink {
-class LocalFrame;
-class ResourceError;
-class ResourceResponse;
-
// Describes a type of fetch for the purposes of categorizing feature use.
enum class FetchType {
// A document fetching a subresource (image, script, etc.).
@@ -58,33 +54,17 @@ enum class FetchType {
// |fetch_type| describes the fetch itself.
//
// |client_is_secure_context| specifies whether the client execution context is
-// a secure context, as defined in
-// https://html.spec.whatwg.org/multipage/webappapis.html#secure-context.
-//
-// Returns nullopt if the load is not a private network request, as defined in
-// https://wicg.github.io/cors-rfc1918/#private-network-request.
-absl::optional<mojom::blink::WebFeature> CORE_EXPORT AddressSpaceFeature(
- FetchType fetch_type,
- network::mojom::blink::IPAddressSpace client_address_space,
- bool client_is_secure_context,
- network::mojom::blink::IPAddressSpace response_address_space);
-
-// Increments the correct kAddressSpace* WebFeature UseCounter corresponding to
-// the given |client_frame| performing a fetch of type |fetch_type| and
-// receiving the given |response|.
+// a secure context, as defined in:
+// https://html.spec.whatwg.org/multipage/webappapis.html#secure-context
//
-// Does nothing if |client_frame| is nullptr.
-void RecordAddressSpaceFeature(FetchType fetch_type,
- LocalFrame* client_frame,
- const ResourceResponse& response);
-
-// Same as above, for cases where the fetch failed.
-// Does nothing if the fetch failed due to an error other than a failed Private
-// Network Access check.
-void RecordAddressSpaceFeature(FetchType fetch_type,
- LocalFrame* client_frame,
- const ResourceError& error);
+// Returns nullopt if the load is not a private network request, as defined in:
+// https://wicg.github.io/private-network-access/#private-network-request
+absl::optional<mojom::WebFeature> BLINK_COMMON_EXPORT
+AddressSpaceFeature(FetchType fetch_type,
+ network::mojom::IPAddressSpace client_address_space,
+ bool client_is_secure_context,
+ network::mojom::IPAddressSpace response_address_space);
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_ADDRESS_SPACE_FEATURE_H_
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_SECURITY_ADDRESS_SPACE_FEATURE_H_
diff --git a/chromium/third_party/blink/public/common/service_worker/service_worker_loader_helpers.h b/chromium/third_party/blink/public/common/service_worker/service_worker_loader_helpers.h
index 0594b57cb21..ec96cbace73 100644
--- a/chromium/third_party/blink/public/common/service_worker/service_worker_loader_helpers.h
+++ b/chromium/third_party/blink/public/common/service_worker/service_worker_loader_helpers.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SERVICE_WORKER_SERVICE_WORKER_LOADER_HELPERS_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SERVICE_WORKER_SERVICE_WORKER_LOADER_HELPERS_H_
-#include "base/containers/flat_map.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/redirect_info.h"
diff --git a/chromium/third_party/blink/public/common/sms/webotp_service_outcome.h b/chromium/third_party/blink/public/common/sms/webotp_service_outcome.h
index d9effc337fc..7912094dcec 100644
--- a/chromium/third_party/blink/public/common/sms/webotp_service_outcome.h
+++ b/chromium/third_party/blink/public/common/sms/webotp_service_outcome.h
@@ -19,7 +19,8 @@ enum class WebOTPServiceOutcome {
kTimeout = 5,
kUserCancelled = 6,
kBackendNotAvailable = 7,
- kMaxValue = kBackendNotAvailable
+ kCrossDeviceFailure = 8,
+ kMaxValue = kCrossDeviceFailure
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/storage_key/DIR_METADATA b/chromium/third_party/blink/public/common/storage_key/DIR_METADATA
new file mode 100644
index 00000000000..27f133595b6
--- /dev/null
+++ b/chromium/third_party/blink/public/common/storage_key/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "Blink>Storage"
+}
+
+team_email: "storage-dev@chromium.org" \ No newline at end of file
diff --git a/chromium/third_party/blink/public/common/storage_key/OWNERS b/chromium/third_party/blink/public/common/storage_key/OWNERS
new file mode 100644
index 00000000000..aa0085a5596
--- /dev/null
+++ b/chromium/third_party/blink/public/common/storage_key/OWNERS
@@ -0,0 +1,4 @@
+file://storage/OWNERS
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/third_party/blink/public/common/storage_key/storage_key.h b/chromium/third_party/blink/public/common/storage_key/storage_key.h
new file mode 100644
index 00000000000..8cbd73360c5
--- /dev/null
+++ b/chromium/third_party/blink/public/common/storage_key/storage_key.h
@@ -0,0 +1,111 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_STORAGE_KEY_STORAGE_KEY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_STORAGE_KEY_STORAGE_KEY_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "base/unguessable_token.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "url/origin.h"
+
+namespace blink {
+
+// A class representing the key that Storage APIs use to key their storage on.
+//
+// At the moment, StorageKey contains an origin and an optional nonce. The
+// top-frame site will be added later in order to implement a finer storage
+// partitioning. Using the nonce is still unsupported since serialization and
+// deserialization don't take it into account. For more details on the overall
+// design, see
+// https://docs.google.com/document/d/1xd6MXcUhfnZqIe5dt2CTyCn6gEZ7nOezAEWS0W9hwbQ/edit.
+class BLINK_COMMON_EXPORT StorageKey {
+ public:
+ StorageKey() = default;
+ explicit StorageKey(const url::Origin& origin)
+ : StorageKey(origin, nullptr) {}
+
+ static StorageKey CreateWithNonce(const url::Origin& origin,
+ const base::UnguessableToken& nonce);
+
+ // Copyable and Moveable.
+ StorageKey(const StorageKey& other) = default;
+ StorageKey& operator=(const StorageKey& other) = default;
+ StorageKey(StorageKey&& other) = default;
+ StorageKey& operator=(StorageKey&& other) = default;
+
+ ~StorageKey() = default;
+
+ // Returns a newly constructed StorageKey from, a previously serialized, `in`.
+ // If `in` is invalid then the return value will be nullopt. If this returns a
+ // non-nullopt value, it will be a valid, non-opaque StorageKey. A
+ // deserialized StorageKey will be equivalent to the StorageKey that was
+ // initially serialized.
+ //
+ // Can be called on the output of either Serialize() or
+ // SerializeForLocalStorage(), as it can handle both formats.
+ static absl::optional<StorageKey> Deserialize(base::StringPiece in);
+
+ // Transforms a string into a StorageKey if possible (and an opaque StorageKey
+ // if not). Currently calls Deserialize, but this may change in future.
+ // For use in tests only.
+ static StorageKey CreateFromStringForTesting(const std::string& origin);
+
+ // Returns true if ThirdPartyStoragePartitioning feature flag is enabled.
+ static bool IsThirdPartyStoragePartitioningEnabled();
+
+ // Serializes the `StorageKey` into a string.
+ // This function will return the spec url of the underlying Origin. Do not
+ // call if `this` is opaque.
+ std::string Serialize() const;
+
+ // Serializes into a string in the format used for localStorage (without
+ // trailing slashes). Prefer Serialize() for uses other than localStorage. Do
+ // not call if `this` is opaque.
+ std::string SerializeForLocalStorage() const;
+
+ const url::Origin& origin() const { return origin_; }
+
+ const absl::optional<base::UnguessableToken>& nonce() const { return nonce_; }
+
+ std::string GetDebugString() const;
+
+ // Provides a concise string representation suitable for memory dumps.
+ // Limits the length to `max_length` chars and strips special characters.
+ std::string GetMemoryDumpString(size_t max_length) const;
+
+ private:
+ StorageKey(const url::Origin& origin, const base::UnguessableToken* nonce)
+ : origin_(origin),
+ nonce_(nonce ? absl::make_optional(*nonce) : absl::nullopt) {}
+
+ BLINK_COMMON_EXPORT
+ friend bool operator==(const StorageKey& lhs, const StorageKey& rhs);
+
+ BLINK_COMMON_EXPORT
+ friend bool operator!=(const StorageKey& lhs, const StorageKey& rhs);
+
+ // Allows StorageKey to be used as a key in STL (for example, a std::set or
+ // std::map).
+ BLINK_COMMON_EXPORT
+ friend bool operator<(const StorageKey& lhs, const StorageKey& rhs);
+
+ url::Origin origin_;
+
+ // An optional nonce, forcing a partitioned storage from anything else. Used
+ // by anonymous iframes:
+ // https://github.com/camillelamy/explainers/blob/master/anonymous_iframes.md
+ absl::optional<base::UnguessableToken> nonce_;
+};
+
+BLINK_COMMON_EXPORT
+std::ostream& operator<<(std::ostream& ostream, const StorageKey& sk);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_STORAGE_KEY_STORAGE_KEY_H_
diff --git a/chromium/third_party/blink/public/common/storage_key/storage_key_mojom_traits.h b/chromium/third_party/blink/public/common/storage_key/storage_key_mojom_traits.h
new file mode 100644
index 00000000000..0507b7f926d
--- /dev/null
+++ b/chromium/third_party/blink/public/common/storage_key/storage_key_mojom_traits.h
@@ -0,0 +1,41 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_STORAGE_KEY_STORAGE_KEY_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_STORAGE_KEY_STORAGE_KEY_MOJOM_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+#include "third_party/blink/public/mojom/storage_key/storage_key.mojom.h"
+
+namespace base {
+class UnguessableToken;
+} // namespace base
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace mojo {
+
+template <>
+class BLINK_COMMON_EXPORT
+ StructTraits<blink::mojom::StorageKeyDataView, blink::StorageKey> {
+ public:
+ static const url::Origin& origin(const blink::StorageKey& key) {
+ return key.origin();
+ }
+
+ static const absl::optional<base::UnguessableToken>& nonce(
+ const blink::StorageKey& key) {
+ return key.nonce();
+ }
+
+ static bool Read(blink::mojom::StorageKeyDataView data,
+ blink::StorageKey* out);
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_STORAGE_KEY_STORAGE_KEY_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/switches.h b/chromium/third_party/blink/public/common/switches.h
index 3fdeba2c4d5..6f743b23564 100644
--- a/chromium/third_party/blink/public/common/switches.h
+++ b/chromium/third_party/blink/public/common/switches.h
@@ -43,12 +43,11 @@ BLINK_COMMON_EXPORT extern const char kMaxUntiledLayerHeight[];
BLINK_COMMON_EXPORT extern const char kMaxUntiledLayerWidth[];
BLINK_COMMON_EXPORT extern const char kMinHeightForGpuRasterTile[];
BLINK_COMMON_EXPORT extern const char kNetworkQuietTimeout[];
-BLINK_COMMON_EXPORT extern const char kPassiveListenersDefault[];
BLINK_COMMON_EXPORT extern const char kShowLayoutShiftRegions[];
BLINK_COMMON_EXPORT extern const char kShowPaintRects[];
BLINK_COMMON_EXPORT extern const char kTouchTextSelectionStrategy[];
+BLINK_COMMON_EXPORT extern const char kSharedArrayBufferAllowedOrigins[];
-BLINK_COMMON_EXPORT extern const char kUserAgentClientHintDisable[];
} // namespace switches
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h b/chromium/third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h
index e90633b5548..e189c6842b1 100644
--- a/chromium/third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h
+++ b/chromium/third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h
@@ -23,6 +23,10 @@ class BLINK_COMMON_EXPORT ThreadSafeBrowserInterfaceBrokerProxy
: public base::RefCountedThreadSafe<ThreadSafeBrowserInterfaceBrokerProxy> {
public:
ThreadSafeBrowserInterfaceBrokerProxy();
+ ThreadSafeBrowserInterfaceBrokerProxy(
+ const ThreadSafeBrowserInterfaceBrokerProxy&) = delete;
+ ThreadSafeBrowserInterfaceBrokerProxy& operator=(
+ const ThreadSafeBrowserInterfaceBrokerProxy&) = delete;
// Asks the browser to bind the given receiver. If a non-null testing override
// was set by |SetBinderForTesting()|, the request will be intercepted by that
@@ -51,8 +55,6 @@ class BLINK_COMMON_EXPORT ThreadSafeBrowserInterfaceBrokerProxy
base::Lock binder_map_lock_;
std::map<std::string, Binder> binder_map_for_testing_
GUARDED_BY(binder_map_lock_);
-
- DISALLOW_COPY_AND_ASSIGN(ThreadSafeBrowserInterfaceBrokerProxy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/tokens/BUILD.gn b/chromium/third_party/blink/public/common/tokens/BUILD.gn
index b198ad40814..f38a11f6ce1 100644
--- a/chromium/third_party/blink/public/common/tokens/BUILD.gn
+++ b/chromium/third_party/blink/public/common/tokens/BUILD.gn
@@ -20,5 +20,6 @@ source_set("tokens_headers") {
"//mojo/public/cpp/system",
"//mojo/public/mojom/base",
"//third_party/blink/public/common:common_export",
+ "//ui/base/clipboard:clipboard",
]
}
diff --git a/chromium/third_party/blink/public/common/tokens/README.md b/chromium/third_party/blink/public/common/tokens/README.md
index c8bd024d359..dbc55df2ef4 100644
--- a/chromium/third_party/blink/public/common/tokens/README.md
+++ b/chromium/third_party/blink/public/common/tokens/README.md
@@ -3,7 +3,7 @@
## Overview
This directory contains strongly-typed wrappers (using
-[`util::TokenType<...>`](/base/util/type_safety/token_type.h)) of
+[`base::TokenType<...>`](/base/types/token_type.h)) of
[`base::UnguessableToken`](/base/unguessable_token.h)
for tokens that are commonly passed between browsers and renderers. The strong
typing is to prevent type confusion as these tokens are passed around. To support
diff --git a/chromium/third_party/blink/public/common/tokens/multi_token.h b/chromium/third_party/blink/public/common/tokens/multi_token.h
index 7b00b3284c0..a776baa0bd3 100644
--- a/chromium/third_party/blink/public/common/tokens/multi_token.h
+++ b/chromium/third_party/blink/public/common/tokens/multi_token.h
@@ -18,7 +18,7 @@
namespace blink {
// Defines MultiToken, which is effectively a variant over 2 or more
-// instances of util::TokenType.
+// instances of base::TokenType.
//
// A MultiToken<..> emulates a token like interface. When default constructed
// it will construct itself as an instance of |TokenVariant0|. Additionally it
@@ -34,7 +34,7 @@ namespace blink {
//
// A variant must have at least 2 valid input types, but can have arbitrarily
// many. They must all be distinct, and they must all be instances of
-// util::TokenType.
+// base::TokenType.
template <typename TokenVariant0,
typename TokenVariant1,
typename... TokenVariants>
diff --git a/chromium/third_party/blink/public/common/tokens/multi_token_internal.h b/chromium/third_party/blink/public/common/tokens/multi_token_internal.h
index 8c2f7f37ca1..9a3dcec5b24 100644
--- a/chromium/third_party/blink/public/common/tokens/multi_token_internal.h
+++ b/chromium/third_party/blink/public/common/tokens/multi_token_internal.h
@@ -12,8 +12,8 @@
#include <cstring>
#include <type_traits>
+#include "base/types/token_type.h"
#include "base/unguessable_token.h"
-#include "base/util/type_safety/token_type.h"
namespace blink {
@@ -46,7 +46,7 @@ struct MultiTokenVariantCount<> {
////////////////////////////////////////////////////////////////////////////////
// MultiTokenVariantIsTokenType
//
-// Ensures if a QueryType is a a util::TokenType<>.
+// Ensures if a QueryType is a a base::TokenType<>.
// Default case.
template <typename QueryType>
@@ -54,9 +54,9 @@ struct MultiTokenVariantIsTokenType {
static constexpr bool kValue = false;
};
-// Specialization for util::TokenType<>.
+// Specialization for base::TokenType<>.
template <typename TokenTypeTag>
-struct MultiTokenVariantIsTokenType<::util::TokenType<TokenTypeTag>> {
+struct MultiTokenVariantIsTokenType<::base::TokenType<TokenTypeTag>> {
static constexpr bool kValue = true;
// We expect an identical layout, which allows us to reinterpret_cast between
@@ -64,19 +64,19 @@ struct MultiTokenVariantIsTokenType<::util::TokenType<TokenTypeTag>> {
// we can check whether or not the compiler is sane (and if the behaviour is
// safe) at compile-time.
static_assert(
- sizeof(::util::TokenType<TokenTypeTag>) ==
+ sizeof(::base::TokenType<TokenTypeTag>) ==
sizeof(::base::UnguessableToken),
- "util::TokenType must have the same sizeof as base::UnguessableToken");
+ "base::TokenType must have the same sizeof as base::UnguessableToken");
static_assert(
- alignof(::util::TokenType<TokenTypeTag>) ==
+ alignof(::base::TokenType<TokenTypeTag>) ==
alignof(::base::UnguessableToken),
- "util::TokenType must have the same alignof as base::UnguessableToken");
+ "base::TokenType must have the same alignof as base::UnguessableToken");
};
////////////////////////////////////////////////////////////////////////////////
// MultiTokenAllVariantsAreTokenType
//
-// Ensures that all variants are of type util::TokenType.
+// Ensures that all variants are of type base::TokenType.
template <typename... VariantTypes>
struct MultiTokenAllVariantsAreTokenType;
@@ -187,11 +187,11 @@ class MultiTokenBase {
using AnyRepeated = internal::MultiTokenAnyTypeRepeated<TokenVariants...>;
static_assert(!AnyRepeated::kValue, "input types must not be repeated");
- // Ensures that all variants are instances of util::TokenType.
+ // Ensures that all variants are instances of base::TokenType.
using AllVariantsAreTokenType =
internal::MultiTokenAllVariantsAreTokenType<TokenVariants...>;
static_assert(AllVariantsAreTokenType::kValue,
- "input types must be instances of util::TokenType");
+ "input types must be instances of base::TokenType");
// Counts the number of variants.
using VariantCount = internal::MultiTokenVariantCount<TokenVariants...>;
diff --git a/chromium/third_party/blink/public/common/tokens/token_mojom_traits_helper.h b/chromium/third_party/blink/public/common/tokens/token_mojom_traits_helper.h
index 50b6fc9a381..0f5ee10a35c 100644
--- a/chromium/third_party/blink/public/common/tokens/token_mojom_traits_helper.h
+++ b/chromium/third_party/blink/public/common/tokens/token_mojom_traits_helper.h
@@ -11,7 +11,7 @@ namespace blink {
// Defines Mojo StructTraits that convert between the given |MojomDataViewType|
// and the given |TokenType|. It is assumed that TokenType is an instance of
-// util::TokenType<...> and that MojomDataViewType is a simple mojom struct
+// base::TokenType<...> and that MojomDataViewType is a simple mojom struct
// containing only a "base.mojom.UnguessableToken value" field.
template <typename MojomDataViewType, typename TokenType>
struct TokenMojomTraitsHelper {
diff --git a/chromium/third_party/blink/public/common/tokens/tokens.h b/chromium/third_party/blink/public/common/tokens/tokens.h
index fad917f3f00..f353ba4c6d9 100644
--- a/chromium/third_party/blink/public/common/tokens/tokens.h
+++ b/chromium/third_party/blink/public/common/tokens/tokens.h
@@ -5,8 +5,9 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_
-#include "base/util/type_safety/token_type.h"
+#include "base/types/token_type.h"
#include "third_party/blink/public/common/tokens/multi_token.h"
+#include "ui/base/clipboard/clipboard_sequence_number_token.h"
namespace blink {
@@ -26,14 +27,14 @@ namespace blink {
// Uniquely identifies a blink::LocalFrame / blink::WebLocalFrame /
// content::RenderFrame in a renderer process, and its content::RenderFrameHost
// counterpart in the browser.
-using LocalFrameToken = util::TokenType<class LocalFrameTokenTypeMarker>;
+using LocalFrameToken = base::TokenType<class LocalFrameTokenTypeMarker>;
// Uniquely identifies a blink::RemoteFrame / blink::WebRemoteFrame /
// content::RenderFrameProxy in a renderer process, and its
// content::RenderFrameProxyHost counterpart in the browser. There can be
// multiple RemoteFrames corresponding to a single LocalFrame, and each token
// will be distinct.
-using RemoteFrameToken = util::TokenType<class RemoteFrameTokenTypeMarker>;
+using RemoteFrameToken = base::TokenType<class RemoteFrameTokenTypeMarker>;
// Can represent either type of FrameToken.
using FrameToken = MultiToken<LocalFrameToken, RemoteFrameToken>;
@@ -44,15 +45,15 @@ using FrameToken = MultiToken<LocalFrameToken, RemoteFrameToken>;
// Identifies a blink::DedicatedWorkerGlobalScope in the renderer and a
// content::DedicatedWorkerHost in the browser.
using DedicatedWorkerToken =
- util::TokenType<class DedicatedWorkerTokenTypeMarker>;
+ base::TokenType<class DedicatedWorkerTokenTypeMarker>;
// Identifies a blink::ServiceWorkerGlobalScope in the renderer and a
// content::ServiceWorkerVersion in the browser.
-using ServiceWorkerToken = util::TokenType<class ServiceWorkerTokenTypeMarker>;
+using ServiceWorkerToken = base::TokenType<class ServiceWorkerTokenTypeMarker>;
// Identifies a blink::SharedWorkerGlobalScope in the renderer and a
// content::SharedWorkerHost in the browser.
-using SharedWorkerToken = util::TokenType<class SharedWorkerTokenTypeMarker>;
+using SharedWorkerToken = base::TokenType<class SharedWorkerTokenTypeMarker>;
// Can represent any type of WorkerToken.
using WorkerToken =
@@ -63,16 +64,16 @@ using WorkerToken =
// Identifies an animation worklet.
using AnimationWorkletToken =
- util::TokenType<class AnimationWorkletTokenTypeMarker>;
+ base::TokenType<class AnimationWorkletTokenTypeMarker>;
// Identifies an audio worklet.
-using AudioWorkletToken = util::TokenType<class AudioWorkletTokenTypeMarker>;
+using AudioWorkletToken = base::TokenType<class AudioWorkletTokenTypeMarker>;
// Identifies a layout worklet.
-using LayoutWorkletToken = util::TokenType<class LayoutWorkletTokenTypeMarker>;
+using LayoutWorkletToken = base::TokenType<class LayoutWorkletTokenTypeMarker>;
// Identifies a paint worklet.
-using PaintWorkletToken = util::TokenType<class PaintWorkletTokenTypeMarker>;
+using PaintWorkletToken = base::TokenType<class PaintWorkletTokenTypeMarker>;
// Can represent any type of WorkletToken.
using WorkletToken = MultiToken<AnimationWorkletToken,
@@ -102,10 +103,13 @@ using ExecutionContextToken = MultiToken<LocalFrameToken,
// Identifies a blink::PortalContents / blink::HTMLPortalElement in the
// renderer process, and a content::Portal in the browser process.
-using PortalToken = util::TokenType<class PortalTokenTypeMarker>;
+using PortalToken = base::TokenType<class PortalTokenTypeMarker>;
// Identifies a v8::Context / blink::ScriptState.
-using V8ContextToken = util::TokenType<class V8ContextTokenTypeMarker>;
+using V8ContextToken = base::TokenType<class V8ContextTokenTypeMarker>;
+
+// Identifies a unique clipboard state.
+using ClipboardSequenceNumberToken = ui::ClipboardSequenceNumberToken;
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/tokens/tokens_mojom_traits.h b/chromium/third_party/blink/public/common/tokens/tokens_mojom_traits.h
index aa038987be1..22a38727ec5 100644
--- a/chromium/third_party/blink/public/common/tokens/tokens_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/tokens/tokens_mojom_traits.h
@@ -177,6 +177,13 @@ struct StructTraits<blink::mojom::V8ContextTokenDataView, blink::V8ContextToken>
: public blink::TokenMojomTraitsHelper<blink::mojom::V8ContextTokenDataView,
blink::V8ContextToken> {};
+template <>
+struct StructTraits<blink::mojom::ClipboardSequenceNumberTokenDataView,
+ blink::ClipboardSequenceNumberToken>
+ : public blink::TokenMojomTraitsHelper<
+ blink::mojom::ClipboardSequenceNumberTokenDataView,
+ blink::ClipboardSequenceNumberToken> {};
+
} // namespace mojo
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/unique_name/unique_name_helper.h b/chromium/third_party/blink/public/common/unique_name/unique_name_helper.h
index 7b235371e71..f420e3d0d2c 100644
--- a/chromium/third_party/blink/public/common/unique_name/unique_name_helper.h
+++ b/chromium/third_party/blink/public/common/unique_name/unique_name_helper.h
@@ -8,7 +8,6 @@
#include <string>
#include <vector>
-#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "third_party/blink/public/common/common_export.h"
@@ -71,7 +70,9 @@ class BLINK_COMMON_EXPORT UniqueNameHelper {
// ExplodedFrameState.
class BLINK_COMMON_EXPORT FrameAdapter {
public:
- FrameAdapter() {}
+ FrameAdapter() = default;
+ FrameAdapter(const FrameAdapter&) = delete;
+ FrameAdapter& operator=(const FrameAdapter&) = delete;
virtual ~FrameAdapter();
virtual bool IsMainFrame() const = 0;
@@ -102,9 +103,6 @@ class BLINK_COMMON_EXPORT UniqueNameHelper {
// Returns a vector of ints representing the child index of each frame in
// the chain from this frame to the root.
virtual std::vector<int> GetFramePosition(BeginPoint begin_point) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FrameAdapter);
};
struct Replacement {
@@ -115,6 +113,8 @@ class BLINK_COMMON_EXPORT UniqueNameHelper {
};
explicit UniqueNameHelper(FrameAdapter* frame);
+ UniqueNameHelper(const UniqueNameHelper&) = delete;
+ UniqueNameHelper& operator=(const UniqueNameHelper&) = delete;
~UniqueNameHelper();
// Returns the generated unique name.
@@ -197,8 +197,6 @@ class BLINK_COMMON_EXPORT UniqueNameHelper {
FrameAdapter* const frame_;
std::string unique_name_;
bool frozen_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(UniqueNameHelper);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/use_counter/use_counter_feature_tracker.h b/chromium/third_party/blink/public/common/use_counter/use_counter_feature_tracker.h
index 6b14221eecf..51e2600854f 100644
--- a/chromium/third_party/blink/public/common/use_counter/use_counter_feature_tracker.h
+++ b/chromium/third_party/blink/public/common/use_counter/use_counter_feature_tracker.h
@@ -24,6 +24,10 @@ class BLINK_COMMON_EXPORT UseCounterFeatureTracker {
void ResetForTesting(const UseCounterFeature&);
+ // Returns whether all recorded features in `other` are also recorded
+ // in `this`.
+ bool ContainsForTesting(const UseCounterFeatureTracker& other) const;
+
private:
void Set(const UseCounterFeature&, bool);
@@ -37,6 +41,14 @@ class BLINK_COMMON_EXPORT UseCounterFeatureTracker {
std::bitset<static_cast<size_t>(mojom::PermissionsPolicyFeature::kMaxValue) +
1>
violated_permissions_policy_features_;
+ std::bitset<static_cast<size_t>(
+ blink::mojom::PermissionsPolicyFeature::kMaxValue) +
+ 1>
+ iframe_permissions_policy_features_;
+ std::bitset<static_cast<size_t>(
+ blink::mojom::PermissionsPolicyFeature::kMaxValue) +
+ 1>
+ header_permissions_policy_features_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/user_agent/user_agent_metadata.h b/chromium/third_party/blink/public/common/user_agent/user_agent_metadata.h
index 4b5baa5bed5..945581761a5 100644
--- a/chromium/third_party/blink/public/common/user_agent/user_agent_metadata.h
+++ b/chromium/third_party/blink/public/common/user_agent/user_agent_metadata.h
@@ -47,6 +47,7 @@ struct BLINK_COMMON_EXPORT UserAgentMetadata {
std::string architecture;
std::string model;
bool mobile = false;
+ std::string bitness;
};
// Used when customizing the sent User-Agent and Sec-CH-UA-* for
diff --git a/chromium/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h b/chromium/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h
index ec09bc7834e..f9bbd2c83d9 100644
--- a/chromium/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h
@@ -63,6 +63,10 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::UserAgentMetadataDataView,
return data.mobile;
}
+ static const std::string& bitness(const ::blink::UserAgentMetadata& data) {
+ return data.bitness;
+ }
+
static bool Read(blink::mojom::UserAgentMetadataDataView data,
::blink::UserAgentMetadata* out);
};
diff --git a/chromium/third_party/blink/public/common/web_preferences/web_preferences.h b/chromium/third_party/blink/public/common/web_preferences/web_preferences.h
index 84736bea7ac..4517bf43c1b 100644
--- a/chromium/third_party/blink/public/common/web_preferences/web_preferences.h
+++ b/chromium/third_party/blink/public/common/web_preferences/web_preferences.h
@@ -17,6 +17,7 @@
#include "third_party/blink/public/mojom/v8_cache_options.mojom-forward.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-shared.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace blink {
@@ -96,6 +97,7 @@ struct BLINK_COMMON_EXPORT WebPreferences {
bool webgl_errors_to_console_enabled;
bool hide_scrollbars;
bool accelerated_2d_canvas_enabled;
+ bool canvas_2d_layers_enabled = false;
bool new_canvas_2d_api_enabled;
bool antialiased_2d_canvas_disabled;
bool antialiased_clips_2d_canvas_enabled;
@@ -352,6 +354,10 @@ struct BLINK_COMMON_EXPORT WebPreferences {
// change depending on the enterprise policy if the platform supports it.
bool webxr_immersive_ar_allowed = true;
+ // LitePage origin the subresources such as images should be redirected to
+ // when the kSubresourceRedirect feature is enabled.
+ url::Origin litepage_subresource_redirect_origin;
+
// We try to keep the default values the same as the default values in
// chrome, except for the cases where it would require lots of extra work for
// the embedder to use the same default value.
diff --git a/chromium/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/chromium/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
index 90a2bb1a13a..9dbbb581a88 100644
--- a/chromium/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
@@ -233,6 +233,11 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
return r.new_canvas_2d_api_enabled;
}
+ static bool canvas_2d_layers_enabled(
+ const blink::web_pref::WebPreferences& r) {
+ return r.canvas_2d_layers_enabled;
+ }
+
static bool antialiased_2d_canvas_disabled(
const blink::web_pref::WebPreferences& r) {
return r.antialiased_2d_canvas_disabled;
@@ -767,6 +772,11 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
return r.webxr_immersive_ar_allowed;
}
+ static const url::Origin& litepage_subresource_redirect_origin(
+ const blink::web_pref::WebPreferences& r) {
+ return r.litepage_subresource_redirect_origin;
+ }
+
static bool Read(blink::mojom::WebPreferencesDataView r,
blink::web_pref::WebPreferences* out);
};
diff --git a/chromium/third_party/blink/public/common/widget/device_emulation_params.h b/chromium/third_party/blink/public/common/widget/device_emulation_params.h
index 74e7eb4db73..3f59d680ae9 100644
--- a/chromium/third_party/blink/public/common/widget/device_emulation_params.h
+++ b/chromium/third_party/blink/public/common/widget/device_emulation_params.h
@@ -7,7 +7,7 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/widget/device_emulation_params.mojom-shared.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-shared.h"
+#include "ui/display/mojom/screen_orientation.mojom.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
@@ -49,8 +49,8 @@ struct DeviceEmulationParams {
// Optional screen orientation type, with mojom::ScreenOrientation::kUndefined
// value meaning no emulation necessary.
- mojom::ScreenOrientation screen_orientation_type =
- mojom::ScreenOrientation::kUndefined;
+ display::mojom::ScreenOrientation screen_orientation_type =
+ display::mojom::ScreenOrientation::kUndefined;
// Screen orientation angle, used together with screenOrientationType.
uint32_t screen_orientation_angle = 0;
diff --git a/chromium/third_party/blink/public/common/widget/device_emulation_params_mojom_traits.h b/chromium/third_party/blink/public/common/widget/device_emulation_params_mojom_traits.h
index 7f36e82f5ad..426e0702f53 100644
--- a/chromium/third_party/blink/public/common/widget/device_emulation_params_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/widget/device_emulation_params_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_DEVICE_EMULATION_PARAMS_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_DEVICE_EMULATION_PARAMS_MOJOM_TRAITS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/widget/device_emulation_params.h"
#include "third_party/blink/public/mojom/widget/device_emulation_params.mojom-shared.h"
@@ -48,7 +49,7 @@ struct BLINK_COMMON_EXPORT
return r.viewport_scale;
}
- static blink::mojom::ScreenOrientation screen_orientation_type(
+ static display::mojom::ScreenOrientation screen_orientation_type(
const blink::DeviceEmulationParams& r) {
return r.screen_orientation_type;
}
diff --git a/chromium/third_party/blink/public/common/widget/screen_info.h b/chromium/third_party/blink/public/common/widget/screen_info.h
deleted file mode 100644
index 8de6811a4b7..00000000000
--- a/chromium/third_party/blink/public/common/widget/screen_info.h
+++ /dev/null
@@ -1,121 +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_PUBLIC_COMMON_WIDGET_SCREEN_INFO_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFO_H_
-
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-shared.h"
-#include "ui/gfx/display_color_spaces.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace blink {
-
-// This structure roughly parallels display::Display. It may be desirable to
-// deprecate derived counterparts of ui/display types; see crbug.com/1208469.
-struct BLINK_COMMON_EXPORT ScreenInfo {
- // Device scale factor. Specifies the ratio between physical and logical
- // pixels.
- float device_scale_factor = 1.f;
-
- // The color spaces used by output display for various content types.
- gfx::DisplayColorSpaces display_color_spaces;
-
- // The screen depth in bits per pixel.
- int depth = 0;
-
- // The bits per colour component. This assumes that the colours are balanced
- // equally.
- int depth_per_component = 0;
-
- // This can be true for black and white printers
- bool is_monochrome = false;
-
- // The display frequency in Hz of the monitor. Set to 0 if it fails in the
- // monitor frequency query.
- int display_frequency = 0;
-
- // This is set from the rcMonitor member of MONITORINFOEX, to whit:
- // "A RECT structure that specifies the display monitor rectangle,
- // expressed in virtual-screen coordinates. Note that if the monitor
- // is not the primary display monitor, some of the rectangle's
- // coordinates may be negative values."
- gfx::Rect rect;
-
- // This is set from the rcWork member of MONITORINFOEX, to whit:
- // "A RECT structure that specifies the work area rectangle of the
- // display monitor that can be used by applications, expressed in
- // virtual-screen coordinates. Windows uses this rectangle to
- // maximize an application on the monitor. The rest of the area in
- // rcMonitor contains system windows such as the task bar and side
- // bars. Note that if the monitor is not the primary display monitor,
- // some of the rectangle's coordinates may be negative values".
- gfx::Rect available_rect;
-
- // This is the orientation 'type' or 'name', as in landscape-primary or
- // portrait-secondary for examples.
- // See public/mojom/screen_orientation.mojom for the full list.
- mojom::ScreenOrientation orientation_type =
- mojom::ScreenOrientation::kUndefined;
-
- // This is the orientation angle of the displayed content in degrees.
- // It is the opposite of the physical rotation.
- // TODO(crbug.com/840189): we should use an enum rather than a number here.
- uint16_t orientation_angle = 0;
-
- // Proposed: https://github.com/webscreens/window-placement
- // Whether this Screen is part of a multi-screen extended visual workspace.
- bool is_extended = false;
-
- // Proposed: https://github.com/webscreens/window-placement
- // Whether this screen is designated as the 'primary' screen by the OS
- // (otherwise it is a 'secondary' screen).
- bool is_primary = false;
-
- // Proposed: https://github.com/webscreens/window-placement
- // Whether this screen is an 'internal' panel built into the device, like a
- // laptop display (otherwise it is 'external', like a wired monitor).
- bool is_internal = false;
-
- // Not web-exposed; the display::Display::id(), for internal tracking only.
- static constexpr int64_t kInvalidDisplayId = -1;
- int64_t display_id = kInvalidDisplayId;
-
- ScreenInfo();
- ScreenInfo(const ScreenInfo& other);
- ~ScreenInfo();
- ScreenInfo& operator=(const ScreenInfo& other);
- bool operator==(const ScreenInfo& other) const;
- bool operator!=(const ScreenInfo& other) const;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFO_H_
diff --git a/chromium/third_party/blink/public/common/widget/screen_info_mojom_traits.h b/chromium/third_party/blink/public/common/widget/screen_info_mojom_traits.h
deleted file mode 100644
index 9835ab595a4..00000000000
--- a/chromium/third_party/blink/public/common/widget/screen_info_mojom_traits.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFO_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFO_MOJOM_TRAITS_H_
-
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
-#include "third_party/blink/public/mojom/widget/screen_info.mojom-shared.h"
-
-namespace mojo {
-
-template <>
-struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ScreenInfoDataView, blink::ScreenInfo> {
- static float device_scale_factor(const blink::ScreenInfo& r) {
- return r.device_scale_factor;
- }
-
- static const gfx::DisplayColorSpaces& display_color_spaces(
- const blink::ScreenInfo& r) {
- return r.display_color_spaces;
- }
-
- static int depth(const blink::ScreenInfo& r) { return r.depth; }
-
- static int depth_per_component(const blink::ScreenInfo& r) {
- return r.depth_per_component;
- }
-
- static bool is_monochrome(const blink::ScreenInfo& r) {
- return r.is_monochrome;
- }
-
- static int display_frequency(const blink::ScreenInfo& r) {
- return r.display_frequency;
- }
-
- static const gfx::Rect& rect(const blink::ScreenInfo& r) { return r.rect; }
-
- static const gfx::Rect& available_rect(const blink::ScreenInfo& r) {
- return r.available_rect;
- }
-
- static blink::mojom::ScreenOrientation orientation_type(
- const blink::ScreenInfo& r) {
- return r.orientation_type;
- }
-
- static uint16_t orientation_angle(const blink::ScreenInfo& r) {
- return r.orientation_angle;
- }
-
- static bool is_extended(const blink::ScreenInfo& r) { return r.is_extended; }
-
- static bool is_primary(const blink::ScreenInfo& r) { return r.is_primary; }
-
- static bool is_internal(const blink::ScreenInfo& r) { return r.is_internal; }
-
- static int64_t display_id(const blink::ScreenInfo& r) { return r.display_id; }
-
- static bool Read(blink::mojom::ScreenInfoDataView r, blink::ScreenInfo* out);
-};
-
-} // namespace mojo
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFO_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/widget/screen_infos.h b/chromium/third_party/blink/public/common/widget/screen_infos.h
deleted file mode 100644
index e7df265125d..00000000000
--- a/chromium/third_party/blink/public/common/widget/screen_infos.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFOS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFOS_H_
-
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
-
-namespace blink {
-
-// Information about a set of screens that are relevant to a particular widget.
-// This includes an id for the screen currently showing the widget.
-// This structure roughly parallels display::DisplayList. It may be desirable to
-// deprecate derived counterparts of ui/display types; see crbug.com/1208469.
-struct BLINK_COMMON_EXPORT ScreenInfos {
- ScreenInfos();
- explicit ScreenInfos(const ScreenInfo& screen_info);
- ScreenInfos(const ScreenInfos& other);
- ~ScreenInfos();
- ScreenInfos& operator=(const ScreenInfos& other);
- bool operator==(const ScreenInfos& other) const;
- bool operator!=(const ScreenInfos& other) const;
-
- // Helpers to access the current ScreenInfo element.
- ScreenInfo& mutable_current();
- const ScreenInfo& current() const;
-
- std::vector<ScreenInfo> screen_infos;
- // The display_id of the current ScreenInfo in `screen_infos`.
- int64_t current_display_id = ScreenInfo::kInvalidDisplayId;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFOS_H_
diff --git a/chromium/third_party/blink/public/common/widget/screen_infos_mojom_traits.h b/chromium/third_party/blink/public/common/widget/screen_infos_mojom_traits.h
deleted file mode 100644
index 3994809c140..00000000000
--- a/chromium/third_party/blink/public/common/widget/screen_infos_mojom_traits.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFOS_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFOS_MOJOM_TRAITS_H_
-
-#include "base/containers/flat_set.h"
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/widget/screen_infos.h"
-#include "third_party/blink/public/mojom/widget/screen_infos.mojom-shared.h"
-
-namespace mojo {
-
-template <>
-struct BLINK_COMMON_EXPORT
- StructTraits<blink::mojom::ScreenInfosDataView, blink::ScreenInfos> {
- static const std::vector<blink::ScreenInfo>& screen_infos(
- const blink::ScreenInfos& r) {
- // Ensure ScreenInfo ids are unique and contain `current_display_id`.
- base::flat_set<int64_t> display_ids;
- display_ids.reserve(r.screen_infos.size());
- for (const blink::ScreenInfo& screen_info : r.screen_infos)
- CHECK(display_ids.insert(screen_info.display_id).second);
- CHECK(display_ids.find(r.current_display_id) != display_ids.end());
- return r.screen_infos;
- }
-
- static int64_t current_display_id(const blink::ScreenInfos& r) {
- // One `r.screen_infos` item must have a matching `display_id`; see above.
- return r.current_display_id;
- }
-
- static bool Read(blink::mojom::ScreenInfosDataView r,
- blink::ScreenInfos* out);
-};
-
-} // namespace mojo
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_SCREEN_INFOS_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/public/common/widget/visual_properties.h b/chromium/third_party/blink/public/common/widget/visual_properties.h
index 23d572b2f80..0113ec3c074 100644
--- a/chromium/third_party/blink/public/common/widget/visual_properties.h
+++ b/chromium/third_party/blink/public/common/widget/visual_properties.h
@@ -9,8 +9,8 @@
#include "components/viz/common/surfaces/local_surface_id.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/widget/screen_infos.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
+#include "ui/display/screen_infos.h"
#include "ui/gfx/geometry/size.h"
namespace blink {
@@ -51,7 +51,7 @@ namespace blink {
struct BLINK_COMMON_EXPORT VisualProperties {
// Info about all screens, including the one currently showing the widget.
- ScreenInfos screen_infos;
+ display::ScreenInfos screen_infos;
// Whether or not blink should be in auto-resize mode.
bool auto_resize_enabled = false;
@@ -128,6 +128,13 @@ struct BLINK_COMMON_EXPORT VisualProperties {
// main frame's renderer, and needs to be shared with subframes.
bool is_pinch_gesture_active = false;
+ // The rect of the Windows Control Overlay, which contains system UX
+ // affordances (e.g. close), for installed desktop Progress Web Apps (PWAs),
+ // if the app specifies the 'window-controls-overlay' DisplayMode in its
+ // manifest. This is only valid and to be consumed by the outermost main
+ // frame.
+ gfx::Rect window_controls_overlay_rect;
+
VisualProperties();
VisualProperties(const VisualProperties& other);
~VisualProperties();
diff --git a/chromium/third_party/blink/public/common/widget/visual_properties_mojom_traits.h b/chromium/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
index 361681df591..f4a4c3e5b87 100644
--- a/chromium/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_VISUAL_PROPERTIES_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_VISUAL_PROPERTIES_MOJOM_TRAITS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/widget/visual_properties.h"
#include "third_party/blink/public/mojom/widget/visual_properties.mojom-shared.h"
@@ -14,7 +15,7 @@ namespace mojo {
template <>
struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::VisualPropertiesDataView,
blink::VisualProperties> {
- static const blink::ScreenInfos& screen_infos(
+ static const display::ScreenInfos& screen_infos(
const blink::VisualProperties& r) {
return r.screen_infos;
}
@@ -97,6 +98,11 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::VisualPropertiesDataView,
return r.is_pinch_gesture_active;
}
+ static const gfx::Rect& window_controls_overlay_rect(
+ const blink::VisualProperties& r) {
+ return r.window_controls_overlay_rect;
+ }
+
static bool Read(blink::mojom::VisualPropertiesDataView r,
blink::VisualProperties* out);
};
diff --git a/chromium/third_party/blink/public/devtools_protocol/OWNERS b/chromium/third_party/blink/public/devtools_protocol/OWNERS
index 59258791722..30b2e7e7918 100644
--- a/chromium/third_party/blink/public/devtools_protocol/OWNERS
+++ b/chromium/third_party/blink/public/devtools_protocol/OWNERS
@@ -1,4 +1,3 @@
-alph@chromium.org
caseq@chromium.org
dgozman@chromium.org
pfeldman@chromium.org
diff --git a/chromium/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/chromium/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index bd3f53df761..c5c5726a4bc 100644
--- a/chromium/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/chromium/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -209,6 +209,9 @@ experimental domain Accessibility
# The maximum depth at which descendants of the root node should be retrieved.
# If omitted, the full tree is returned.
optional integer max_depth
+ # The frame for whose document the AX tree should be retrieved.
+ # If omited, the root frame is used.
+ optional Page.FrameId frameId
returns
array of AXNode nodes
@@ -217,6 +220,9 @@ experimental domain Accessibility
experimental command getChildAXNodes
parameters
AXNodeId id
+ # The frame in whose document the node resides.
+ # If omitted, the root frame is used.
+ optional Page.FrameId frameId
returns
array of AXNode nodes
@@ -509,6 +515,8 @@ experimental domain Audits
ExcludeSameSiteNoneInsecure
ExcludeSameSiteLax
ExcludeSameSiteStrict
+ ExcludeInvalidSameParty
+ ExcludeSamePartyCrossPartyContext
type SameSiteCookieWarningReason extends string
enum
@@ -531,7 +539,12 @@ experimental domain Audits
# information without the cookie.
type SameSiteCookieIssueDetails extends object
properties
- AffectedCookie cookie
+ # If AffectedCookie is not set then rawCookieLine contains the raw
+ # Set-Cookie header string. This hints at a problem where the
+ # cookie line is syntactically or semantically malformed in a way
+ # that no valid cookie could be created.
+ optional AffectedCookie cookie
+ optional string rawCookieLine
array of SameSiteCookieWarningReason cookieWarningReasons
array of SameSiteCookieExclusionReason cookieExclusionReasons
# Optionally identifies the site-for-cookies and the cookie url, which
@@ -751,6 +764,13 @@ experimental domain Audits
string url
optional SourceCodeLocation location
+ type WasmCrossOriginModuleSharingIssueDetails extends object
+ properties
+ string wasmModuleUrl
+ string sourceOrigin
+ string targetOrigin
+ boolean isWarning
+
# A unique identifier for the type of issue. Each type may use one of the
# optional fields in InspectorIssueDetails to convey more specific
# information about the kind of issue.
@@ -768,6 +788,7 @@ experimental domain Audits
AttributionReportingIssue
QuirksModeIssue
NavigatorUserAgentIssue
+ WasmCrossOriginModuleSharingIssue
# This struct holds a list of optional fields with additional information
# specific to the kind of issue. When adding a new issue code, please also
@@ -786,12 +807,20 @@ experimental domain Audits
optional AttributionReportingIssueDetails attributionReportingIssueDetails
optional QuirksModeIssueDetails quirksModeIssueDetails
optional NavigatorUserAgentIssueDetails navigatorUserAgentIssueDetails
+ optional WasmCrossOriginModuleSharingIssueDetails wasmCrossOriginModuleSharingIssue
+
+ # A unique id for a DevTools inspector issue. Allows other entities (e.g.
+ # exceptions, CDP message, console messages, etc.) to reference an issue.
+ type IssueId extends string
# An inspector issue reported from the back-end.
type InspectorIssue extends object
properties
InspectorIssueCode code
InspectorIssueDetails details
+ # A unique id for this issue. May be omitted if no other entity (e.g.
+ # exception, CDP message, etc.) is referencing this issue.
+ optional IssueId issueId
# Returns the response body and size if it were re-encoded with the specified settings. Only
# applies to images.
@@ -1256,7 +1285,9 @@ experimental domain CSS
StyleSheetId styleSheetId
# Owner frame identifier.
Page.FrameId frameId
- # Stylesheet resource URL.
+ # Stylesheet resource URL. Empty if this is a constructed stylesheet created using
+ # new CSSStyleSheet() (but non-empty if this is a constructed sylesheet imported
+ # as a CSS module script).
string sourceURL
# URL of source map associated with the stylesheet (if any).
optional string sourceMapURL
@@ -1278,7 +1309,8 @@ experimental domain CSS
# <link> element's stylesheets become mutable only if DevTools modifies them.
# Constructed stylesheets (new CSSStyleSheet()) are mutable immediately after creation.
boolean isMutable
- # Whether this stylesheet is a constructed stylesheet (created using new CSSStyleSheet()).
+ # True if this stylesheet is created through new CSSStyleSheet() or imported as a
+ # CSS module script.
boolean isConstructed
# Line offset of the stylesheet within the resource (zero based).
number startLine
@@ -1306,6 +1338,9 @@ experimental domain CSS
# Media list array (for rules involving media queries). The array enumerates media queries
# starting with the innermost one, going outwards.
optional array of CSSMedia media
+ # Container query list array (for rules involving container queries).
+ # The array enumerates container queries starting with the innermost one, going outwards.
+ experimental optional array of CSSContainerQuery containerQueries
# CSS coverage information.
type RuleUsage extends object
@@ -1429,6 +1464,19 @@ experimental domain CSS
# Computed length of media query expression (if applicable).
optional number computedLength
+ # CSS container query rule descriptor.
+ experimental type CSSContainerQuery extends object
+ properties
+ # Container query text.
+ string text
+ # The associated rule header range in the enclosing stylesheet (if
+ # available).
+ optional SourceRange range
+ # Identifier of the stylesheet containing this object (if exists).
+ optional StyleSheetId styleSheetId
+ # Optional name for the container.
+ optional string name
+
# Information about amount of glyphs that were rendered with given font.
type PlatformFontUsage extends object
properties
@@ -1675,6 +1723,16 @@ experimental domain CSS
# The resulting CSS media rule after modification.
CSSMedia media
+ # Modifies the expression of a container query.
+ experimental command setContainerQueryText
+ parameters
+ StyleSheetId styleSheetId
+ SourceRange range
+ string text
+ returns
+ # The resulting CSS container query rule after modification.
+ CSSContainerQuery containerQuery
+
# Modifies the rule selector.
command setRuleSelector
parameters
@@ -1955,6 +2013,7 @@ domain DOM
target-text
spelling-error
grammar-error
+ highlight
first-line-inherited
scrollbar
scrollbar-thumb
@@ -2572,6 +2631,27 @@ domain DOM
# Id of the node at given coordinates, only when enabled and requested document.
optional NodeId nodeId
+ # Returns the container of the given node based on container query conditions.
+ # If containerName is given, it will find the nearest container with a matching name;
+ # otherwise it will find the nearest container regardless of its container name.
+ experimental command getContainerForNode
+ parameters
+ NodeId nodeId
+ optional string containerName
+ returns
+ # The container node for the given node, or null if not found.
+ optional NodeId nodeId
+
+ # Returns the descendants of a container query container that have
+ # container queries against this container.
+ experimental command getQueryingDescendantsForContainer
+ parameters
+ # Id of the container node to find querying descendants from.
+ NodeId nodeId
+ returns
+ # Descendant nodes with container queries against the given container.
+ array of NodeId nodeIds
+
# Fired when `Element`'s attribute is modified.
event attributeModified
parameters
@@ -2987,6 +3067,8 @@ experimental domain DOMSnapshot
optional array of integer parentIndex
# `Node`'s nodeType.
optional array of integer nodeType
+ # Type of the shadow root the `Node` is in. String values are equal to the `ShadowRootType` enum.
+ optional RareStringData shadowRootType
# `Node`'s nodeName.
optional array of StringIndex nodeName
# `Node`'s nodeValue.
@@ -3879,6 +3961,8 @@ domain Input
experimental type DragData extends object
properties
array of DragDataItem items
+ # List of filenames that should be included when dropping
+ optional array of string files
# Bit field representing allowed drag operations. Copy = 1, Link = 2, Move = 16
integer dragOperationsMask
@@ -3953,6 +4037,22 @@ domain Input
# The text to insert.
string text
+ # This method sets the current candidate text for ime.
+ # Use imeCommitComposition to commit the final text.
+ # Use imeSetComposition with empty string as text to cancel composition.
+ experimental command imeSetComposition
+ parameters
+ # The text to insert
+ string text
+ # selection start
+ integer selectionStart
+ # selection end
+ integer selectionEnd
+ # replacement start
+ optional integer replacementStart
+ # replacement end
+ optional integer replacementEnd
+
# Dispatches a mouse event to the page.
command dispatchMouseEvent
parameters
@@ -4685,6 +4785,9 @@ domain Network
# Set for requests when the TrustToken API is used. Contains the parameters
# passed by the developer (e.g. via "fetch") as understood by the backend.
experimental optional TrustTokenParams trustTokenParams
+ # True if this resource request is considered to be the 'same site' as the
+ # request correspondinfg to the main frame.
+ experimental optional boolean isSameSite
# Details of a signed certificate timestamp (SCT).
type SignedCertificateTimestamp extends object
@@ -4839,14 +4942,14 @@ domain Network
string statusText
# HTTP response headers.
Headers headers
- # HTTP response headers text.
- optional string headersText
+ # HTTP response headers text. This has been replaced by the headers in Network.responseReceivedExtraInfo.
+ deprecated optional string headersText
# Resource mimeType as determined by the browser.
string mimeType
# Refined HTTP request headers that were actually transmitted over the network.
optional Headers requestHeaders
- # HTTP request headers text.
- optional string requestHeadersText
+ # HTTP request headers text. This has been replaced by the headers in Network.requestWillBeSentExtraInfo.
+ deprecated optional string requestHeadersText
# Specifies whether physical connection was actually reused for this request.
boolean connectionReused
# Physical connection id that was actually used for this request.
@@ -5513,14 +5616,6 @@ domain Network
# Cookies to be set.
array of CookieParam cookies
- # For testing.
- experimental command setDataSizeLimitsForTest
- parameters
- # Maximum total buffer size.
- integer maxTotalSize
- # Maximum per-resource size.
- integer maxResourceSize
-
# Specifies whether to always send extra HTTP headers with the requests from this page.
command setExtraHTTPHeaders
parameters
@@ -5864,6 +5959,10 @@ domain Network
# The IP address space of the resource. The address space can only be determined once the transport
# established the connection, so we can't send it in `requestWillBeSentExtraInfo`.
IPAddressSpace resourceIPAddressSpace
+ # The status code of the response. This is useful in cases the request failed and no responseReceived
+ # event is triggered, which is the case for, e.g., CORS errors. This is also the correct status code
+ # for cached requests, where the status in responseReceived is a 200 and this will be 304.
+ integer statusCode
# Raw response header text as it was received over the wire. The raw text may not always be
# available, such as in the case of HTTP/2 or QUIC.
optional string headersText
@@ -5898,6 +5997,50 @@ domain Network
# The number of obtained Trust Tokens on a successful "Issuance" operation.
optional integer issuedTokenCount
+ # Fired once when parsing the .wbn file has succeeded.
+ # The event contains the information about the web bundle contents.
+ experimental event subresourceWebBundleMetadataReceived
+ parameters
+ # Request identifier. Used to match this information to another event.
+ RequestId requestId
+ # A list of URLs of resources in the subresource Web Bundle.
+ array of string urls
+
+ # Fired once when parsing the .wbn file has failed.
+ experimental event subresourceWebBundleMetadataError
+ parameters
+ # Request identifier. Used to match this information to another event.
+ RequestId requestId
+ # Error message
+ string errorMessage
+
+ # Fired when handling requests for resources within a .wbn file.
+ # Note: this will only be fired for resources that are requested by the webpage.
+ experimental event subresourceWebBundleInnerResponseParsed
+ parameters
+ # Request identifier of the subresource request
+ RequestId innerRequestId
+ # URL of the subresource resource.
+ string innerRequestURL
+ # Bundle request identifier. Used to match this information to another event.
+ # This made be absent in case when the instrumentation was enabled only
+ # after webbundle was parsed.
+ optional RequestId bundleRequestId
+
+ # Fired when request for resources within a .wbn file failed.
+ experimental event subresourceWebBundleInnerResponseError
+ parameters
+ # Request identifier of the subresource request
+ RequestId innerRequestId
+ # URL of the subresource resource.
+ string innerRequestURL
+ # Error message
+ string errorMessage
+ # Bundle request identifier. Used to match this information to another event.
+ # This made be absent in case when the instrumentation was enabled only
+ # after webbundle was parsed.
+ optional RequestId bundleRequestId
+
experimental type CrossOriginOpenerPolicyValue extends string
enum
SameOrigin
@@ -5915,7 +6058,7 @@ domain Network
experimental type CrossOriginEmbedderPolicyValue extends string
enum
None
- CorsOrCredentialless
+ Credentialless
RequireCorp
experimental type CrossOriginEmbedderPolicyStatus extends object
@@ -5961,8 +6104,9 @@ domain Network
# Fetches the resource and returns the content.
experimental command loadNetworkResource
parameters
- # Frame id to get the resource for.
- Page.FrameId frameId
+ # Frame id to get the resource for. Mandatory for frame targets, and
+ # should be omitted for worker targets.
+ optional Page.FrameId frameId
# URL of the resource to get content for.
string url
# Options for the request.
@@ -6121,6 +6265,8 @@ experimental domain Overlay
optional FlexItemHighlightConfig flexItemHighlightConfig
# The contrast algorithm to use for the contrast ratio (default: aa).
optional ContrastAlgorithm contrastAlgorithm
+ # The container query container highlight configuration (default: all transparent).
+ optional ContainerQueryContainerHighlightConfig containerQueryContainerHighlightConfig
type ColorFormat extends string
enum
@@ -6171,6 +6317,20 @@ experimental domain Overlay
# The content box highlight outline color (default: transparent).
optional DOM.RGBA outlineColor
+ type ContainerQueryHighlightConfig extends object
+ properties
+ # A descriptor for the highlight appearance of container query containers.
+ ContainerQueryContainerHighlightConfig containerQueryContainerHighlightConfig
+ # Identifier of the container node to highlight.
+ DOM.NodeId nodeId
+
+ type ContainerQueryContainerHighlightConfig extends object
+ properties
+ # The style of the container border.
+ optional LineStyle containerBorder
+ # The style of the descendants' borders.
+ optional LineStyle descendantBorder
+
type InspectMode extends string
enum
searchForNode
@@ -6224,7 +6384,10 @@ experimental domain Overlay
command hideHighlight
# Highlights owner element of the frame with given id.
- command highlightFrame
+ # Deprecated: Doesn't work reliablity and cannot be fixed due to process
+ # separatation (the owner node might be in a different process). Determine
+ # the owner node in the client and use highlightNode.
+ deprecated command highlightFrame
parameters
# Identifier of the frame to highlight.
Page.FrameId frameId
@@ -6336,6 +6499,11 @@ experimental domain Overlay
# An array of node identifiers and descriptors for the highlight appearance.
array of ScrollSnapHighlightConfig scrollSnapHighlightConfigs
+ command setShowContainerQueryOverlays
+ parameters
+ # An array of node identifiers and descriptors for the highlight appearance.
+ array of ContainerQueryHighlightConfig containerQueryHighlightConfigs
+
# Requests that backend shows paint rectangles
command setShowPaintRects
parameters
@@ -6418,6 +6586,18 @@ domain Page
# This frame is the root of an ad frame.
root
+ experimental type AdFrameExplanation extends string
+ enum
+ ParentIsAd
+ CreatedByAdScript
+ MatchedBlockingRule
+
+ # Indicates whether a frame has been identified as an ad and why.
+ experimental type AdFrameStatus extends object
+ properties
+ AdFrameType adFrameType
+ optional array of AdFrameExplanation explanations
+
# Indicates whether the frame is a secure context and why it is the case.
experimental type SecureContextType extends string
enum
@@ -6465,11 +6645,13 @@ domain Page
ch-rtt
ch-ua
ch-ua-arch
+ ch-ua-bitness
ch-ua-platform
ch-ua-model
ch-ua-mobile
ch-ua-full-version
ch-ua-platform-version
+ ch-ua-reduced
ch-viewport-width
ch-width
clipboard-read
@@ -6586,7 +6768,7 @@ domain Page
# Frame unique identifier.
FrameId id
# Parent frame identifier.
- optional string parentId
+ optional FrameId parentId
# Identifier of the loader associated with this frame.
Network.LoaderId loaderId
# Frame's name as specified in the tag.
@@ -6606,8 +6788,8 @@ domain Page
string mimeType
# If the frame failed to load, this contains the URL that could not be loaded. Note that unlike url above, this URL may contain a fragment.
experimental optional string unreachableUrl
- # Indicates whether this frame was tagged as an ad.
- experimental optional AdFrameType adFrameType
+ # Indicates whether this frame was tagged as an ad and why.
+ experimental optional AdFrameStatus adFrameStatus
# Indicates whether the main document is a secure context and explains why that is the case.
experimental SecureContextType secureContextType
# Indicates whether this is a cross origin isolated context.
@@ -6890,6 +7072,7 @@ domain Page
optional enum format
jpeg
png
+ webp
# Compression quality from range [0..100] (jpeg only).
optional integer quality
# Capture the screenshot of a given region only.
@@ -7188,6 +7371,13 @@ domain Page
returns
array of PermissionsPolicyFeatureState states
+ # Get Origin Trials on given frame.
+ experimental command getOriginTrials
+ parameters
+ FrameId frameId
+ returns
+ array of OriginTrial originTrials
+
# Overrides the values of device screen dimensions (window.screen.width, window.screen.height,
# window.innerWidth, window.innerHeight, and "device-width"/"device-height"-related CSS media
# query results).
@@ -7556,6 +7746,132 @@ domain Page
string name
Network.MonotonicTime timestamp
+ # List of not restored reasons for back-forward cache.
+ experimental type BackForwardCacheNotRestoredReason extends string
+ enum
+ NotMainFrame
+ BackForwardCacheDisabled
+ RelatedActiveContentsExist
+ HTTPStatusNotOK
+ SchemeNotHTTPOrHTTPS
+ Loading
+ WasGrantedMediaAccess
+ DisableForRenderFrameHostCalled
+ DomainNotAllowed
+ HTTPMethodNotGET
+ SubframeIsNavigating
+ Timeout
+ CacheLimit
+ JavaScriptExecution
+ RendererProcessKilled
+ RendererProcessCrashed
+ GrantedMediaStreamAccess
+ SchedulerTrackedFeatureUsed
+ ConflictingBrowsingInstance
+ CacheFlushed
+ ServiceWorkerVersionActivation
+ SessionRestored
+ ServiceWorkerPostMessage
+ EnteredBackForwardCacheBeforeServiceWorkerHostAdded
+ RenderFrameHostReused_SameSite
+ RenderFrameHostReused_CrossSite
+ ServiceWorkerClaim
+ IgnoreEventAndEvict
+ HaveInnerContents
+ TimeoutPuttingInCache
+ BackForwardCacheDisabledByLowMemory
+ BackForwardCacheDisabledByCommandLine
+ NetworkRequestDatapipeDrainedAsBytesConsumer
+ NetworkRequestRedirected
+ NetworkRequestTimeout
+ NetworkExceedsBufferLimit
+ NavigationCancelledWhileRestoring
+ NotMostRecentNavigationEntry
+ BackForwardCacheDisabledForPrerender
+ UserAgentOverrideDiffers
+ ForegroundCacheLimit
+ BrowsingInstanceNotSwapped
+ BackForwardCacheDisabledForDelegate
+ OptInUnloadHeaderNotPresent
+ UnloadHandlerExistsInSubFrame
+ ServiceWorkerUnregistration
+ CacheControlNoStore
+ CacheControlNoStoreCookieModified
+ CacheControlNoStoreHTTPOnlyCookieModified
+ NoResponseHead
+ Unknown
+ ActivationNavigationsDisallowedForBug1234857
+ #Blocklisted features
+ WebSocket
+ WebTransport
+ WebRTC
+ MainResourceHasCacheControlNoStore
+ MainResourceHasCacheControlNoCache
+ SubresourceHasCacheControlNoStore
+ SubresourceHasCacheControlNoCache
+ ContainsPlugins
+ DocumentLoaded
+ DedicatedWorkerOrWorklet
+ OutstandingNetworkRequestOthers
+ OutstandingIndexedDBTransaction
+ RequestedNotificationsPermission
+ RequestedMIDIPermission
+ RequestedAudioCapturePermission
+ RequestedVideoCapturePermission
+ RequestedBackForwardCacheBlockedSensors
+ RequestedBackgroundWorkPermission
+ BroadcastChannel
+ IndexedDBConnection
+ WebXR
+ SharedWorker
+ WebLocks
+ WebHID
+ WebShare
+ RequestedStorageAccessGrant
+ WebNfc
+ WebFileSystem
+ OutstandingNetworkRequestFetch
+ OutstandingNetworkRequestXHR
+ AppBanner
+ Printing
+ WebDatabase
+ PictureInPicture
+ Portal
+ SpeechRecognizer
+ IdleManager
+ PaymentManager
+ SpeechSynthesis
+ KeyboardLock
+ WebOTPService
+ OutstandingNetworkRequestDirectSocket
+ IsolatedWorldScript
+ InjectedStyleSheet
+ # Disabled for render frame host reasons
+ MediaSessionImplOnServiceCreated
+ SecurityHandler
+ WebAuthenticationAPI
+ FileChooser
+ Serial
+ FileSystemAccess
+ MediaDevicesDispatcherHost
+ WebBluetooth
+ WebUSB
+ MediaSession
+
+ # Types of not restored reasons for back-forward cache.
+ experimental type BackForwardCacheNotRestoredReasonType extends string
+ enum
+ SupportPending
+ PageSupportNeeded
+ Circumstantial
+
+ experimental type BackForwardCacheNotRestoredExplanation extends object
+ properties
+ # Type of the reason
+ BackForwardCacheNotRestoredReasonType type
+ # Not restored reason
+ BackForwardCacheNotRestoredReason reason
+
# Fired for failed bfcache history navigations if BackForwardCache feature is enabled. Do
# not assume any ordering with the Page.frameNavigated event. This event is fired only for
# main-frame history navigation where the document changes (non-same-document navigations),
@@ -7566,6 +7882,8 @@ domain Page
Network.LoaderId loaderId
# The frame id of the associated frame.
FrameId frameId
+ # Array of reasons why the page could not be cached. This must not be empty.
+ array of BackForwardCacheNotRestoredExplanation notRestoredExplanations
event loadEventFired
parameters
@@ -8867,6 +9185,8 @@ domain Fetch
optional binary postData
# If set, overrides the request headers.
optional array of HeaderEntry headers
+ # If set, overrides response interception behavior for this request.
+ experimental optional boolean interceptResponse
# Continues a request supplying authChallengeResponse following authRequired event.
command continueWithAuth
diff --git a/chromium/third_party/blink/public/mojom/BUILD.gn b/chromium/third_party/blink/public/mojom/BUILD.gn
index 8104656d31e..930e6eea75a 100644
--- a/chromium/third_party/blink/public/mojom/BUILD.gn
+++ b/chromium/third_party/blink/public/mojom/BUILD.gn
@@ -23,7 +23,6 @@ mojom("mojom_platform") {
generate_java = true
sources = [
"ad_tagging/ad_evidence.mojom",
- "ad_tagging/ad_frame.mojom",
"app_banner/app_banner.mojom",
"appcache/appcache.mojom",
"appcache/appcache_info.mojom",
@@ -41,12 +40,12 @@ mojom("mojom_platform") {
"choosers/file_chooser.mojom",
"choosers/popup_menu.mojom",
"clipboard/clipboard.mojom",
- "clipboard/raw_clipboard.mojom",
"commit_result/commit_result.mojom",
"compute_pressure/compute_pressure.mojom",
"content_index/content_index.mojom",
"context_menu/context_menu.mojom",
"conversions/conversions.mojom",
+ "cookie_manager/cookie_manager_automation.mojom",
"cookie_store/cookie_store.mojom",
"crash/crash_memory_metrics_reporter.mojom",
"credentialmanager/credential_manager.mojom",
@@ -65,9 +64,11 @@ mojom("mojom_platform") {
"fetch/fetch_api_request.mojom",
"fetch/fetch_api_response.mojom",
"file/file_utilities.mojom",
+ "file_system_access/file_system_access_access_handle_host.mojom",
"file_system_access/file_system_access_data_transfer_token.mojom",
"file_system_access/file_system_access_directory_handle.mojom",
"file_system_access/file_system_access_error.mojom",
+ "file_system_access/file_system_access_file_delegate_host.mojom",
"file_system_access/file_system_access_file_handle.mojom",
"file_system_access/file_system_access_file_writer.mojom",
"file_system_access/file_system_access_manager.mojom",
@@ -88,7 +89,6 @@ mojom("mojom_platform") {
"input/pointer_lock_result.mojom",
"input/scroll_direction.mojom",
"input/touch_event.mojom",
- "insecure_input/insecure_input_service.mojom",
"interest_group/ad_auction_service.mojom",
"interest_group/interest_group_types.mojom",
"interest_group/restricted_interest_group_store.mojom",
@@ -105,6 +105,7 @@ mojom("mojom_platform") {
"loader/request_context_frame_type.mojom",
"loader/resource_load_info.mojom",
"loader/resource_load_info_notifier.mojom",
+ "loader/same_document_navigation_type.mojom",
"loader/transferrable_url_loader.mojom",
"loader/url_loader_factory_bundle.mojom",
"locks/lock_manager.mojom",
@@ -124,10 +125,11 @@ mojom("mojom_platform") {
"modal_close_watcher/modal_close_listener.mojom",
"native_io/native_io.mojom",
"navigation/navigation_policy.mojom",
+ "navigation/prefetched_signed_exchange_info.mojom",
+ "navigation/was_activated_option.mojom",
"notifications/notification.mojom",
"notifications/notification_service.mojom",
"oom_intervention/oom_intervention.mojom",
- "optimization_guide/optimization_guide.mojom",
"page/display_cutout.mojom",
"page/drag.mojom",
"page/page.mojom",
@@ -136,7 +138,6 @@ mojom("mojom_platform") {
"page/widget.mojom",
"page_state/page_state.mojom",
"payments/payment_app.mojom",
- "payments/payment_credential.mojom",
"peerconnection/peer_connection_tracker.mojom",
"performance_manager/v8_detailed_memory_reporter.mojom",
"permissions/permission.mojom",
@@ -158,7 +159,6 @@ mojom("mojom_platform") {
"renderer_preference_watcher.mojom",
"renderer_preferences.mojom",
"reporting/reporting.mojom",
- "screen_enumeration/screen_enumeration.mojom",
"scroll/scroll_enums.mojom",
"scroll/scroll_into_view_params.mojom",
"scroll/scrollbar_mode.mojom",
@@ -176,6 +176,7 @@ mojom("mojom_platform") {
"service_worker/service_worker_stream_handle.mojom",
"service_worker/service_worker_worker_client.mojom",
"service_worker/service_worker_worker_client_registry.mojom",
+ "shared_storage/shared_storage.mojom",
"site_engagement/site_engagement.mojom",
"sms/webotp_service.mojom",
"speculation_rules/speculation_rules.mojom",
@@ -186,6 +187,8 @@ mojom("mojom_platform") {
"speech/speech_recognizer.mojom",
"speech/speech_synthesis.mojom",
"storage_access/storage_access_automation.mojom",
+ "storage_key/storage_key.mojom",
+ "subapps/sub_apps_provider.mojom",
"timing/performance_mark_or_measure.mojom",
"timing/resource_timing.mojom",
"timing/worker_timing_container.mojom",
@@ -203,9 +206,6 @@ mojom("mojom_platform") {
"websockets/websocket_connector.mojom",
"webtransport/web_transport_connector.mojom",
"widget/device_emulation_params.mojom",
- "widget/screen_info.mojom",
- "widget/screen_infos.mojom",
- "widget/screen_orientation.mojom",
"widget/visual_properties.mojom",
"window_features/window_features.mojom",
"worker/dedicated_worker_host.mojom",
@@ -394,28 +394,6 @@ mojom("mojom_platform") {
{
types = [
{
- mojom = "blink.mojom.ScreenInfo"
- cpp = "::blink::ScreenInfo"
- },
- ]
- traits_headers = [
- "//third_party/blink/public/common/widget/screen_info_mojom_traits.h",
- ]
- },
- {
- types = [
- {
- mojom = "blink.mojom.ScreenInfos"
- cpp = "::blink::ScreenInfos"
- },
- ]
- traits_headers = [
- "//third_party/blink/public/common/widget/screen_infos_mojom_traits.h",
- ]
- },
- {
- types = [
- {
mojom = "blink.mojom.VisualProperties"
cpp = "::blink::VisualProperties"
},
@@ -497,6 +475,15 @@ mojom("mojom_platform") {
]
traits_headers = [ "//third_party/blink/public/common/frame/frame_ad_evidence_mojom_traits.h" ]
},
+ {
+ types = [
+ {
+ mojom = "blink.mojom.SHA256HashValue"
+ cpp = "::net::SHA256HashValue"
+ },
+ ]
+ traits_headers = [ "//third_party/blink/public/common/navigation/prefetched_signed_exchange_info_mojom_traits.h" ]
+ },
]
cpp_typemaps = [
{
@@ -568,17 +555,36 @@ mojom("mojom_platform") {
{
types = [
{
- mojom = "blink.mojom.Manifest"
- cpp = "::blink::Manifest"
- nullable_is_same_type = true
+ mojom = "blink.mojom.InterestGroup"
+ cpp = "::blink::InterestGroup"
},
-
+ ]
+ traits_headers = [ "//third_party/blink/public/common/interest_group/interest_group_mojom_traits.h" ]
+ traits_public_deps = [ "//url/mojom:mojom_traits" ]
+ },
+ {
+ types = [
+ {
+ mojom = "blink.mojom.InterestGroupAd"
+ cpp = "::blink::InterestGroup::Ad"
+ },
+ ]
+ traits_headers = [ "//third_party/blink/public/common/interest_group/interest_group_mojom_traits.h" ]
+ traits_public_deps = [ "//url/mojom:mojom_traits" ]
+ },
+ {
+ types = [
{
mojom = "blink.mojom.ManifestImageResource"
cpp = "::blink::Manifest::ImageResource"
},
{
+ mojom = "blink.mojom.ManifestLaunchHandler"
+ cpp = "::blink::Manifest::LaunchHandler"
+ },
+
+ {
mojom = "blink.mojom.ManifestRelatedApplication"
cpp = "::blink::Manifest::RelatedApplication"
},
@@ -743,6 +749,7 @@ mojom("android_mojo_bindings") {
"installedapp/installed_app_provider.mojom",
"installedapp/related_application.mojom",
"mediasession/media_session.mojom",
+ "payments/payment_credential.mojom",
"payments/payment_handler_host.mojom",
"payments/payment_request.mojom",
"webauthn/authenticator.mojom",
@@ -832,6 +839,15 @@ mojom("android_mojo_bindings") {
"//device/fido",
]
},
+ {
+ types = [
+ {
+ mojom = "blink.mojom.StorageKey"
+ cpp = "::blink::StorageKey"
+ },
+ ]
+ traits_headers = [ "//third_party/blink/public/common/storage_key/storage_key_mojom_traits.h" ]
+ },
]
blink_cpp_typemaps = [
@@ -845,6 +861,15 @@ mojom("android_mojo_bindings") {
]
traits_headers = [ "//third_party/blink/renderer/platform/blob/serialized_blob_mojom_traits.h" ]
},
+ {
+ types = [
+ {
+ mojom = "blink.mojom.StorageKey"
+ cpp = "::blink::BlinkStorageKey"
+ },
+ ]
+ traits_headers = [ "//third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h" ]
+ },
]
export_class_attribute = "BLINK_COMMON_EXPORT"
@@ -886,6 +911,9 @@ mojom("mojom_core") {
"messaging/transferable_message.mojom",
"messaging/user_activation_snapshot.mojom",
+ # Depends on frame_policy.mojom.
+ "navigation/navigation_params.mojom",
+
# Depends on transferable_message.mojom.
"portal/portal.mojom",
@@ -928,6 +956,7 @@ mojom("mojom_core") {
"//skia/public/mojom",
"//third_party/blink/public/mojom/service_worker:storage",
"//ui/base/mojom",
+ "//ui/display/mojom",
"//ui/gfx/geometry/mojom",
"//ui/gfx/range/mojom",
"//url/mojom:url_mojom_gurl",
diff --git a/chromium/third_party/blink/public/mojom/ad_tagging/ad_frame.mojom b/chromium/third_party/blink/public/mojom/ad_tagging/ad_frame.mojom
deleted file mode 100644
index efa9971a6a0..00000000000
--- a/chromium/third_party/blink/public/mojom/ad_tagging/ad_frame.mojom
+++ /dev/null
@@ -1,16 +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.
-
-module blink.mojom;
-
-// Enumeration of ad frame types.
-enum AdFrameType {
- // Frame is not an ad.
- kNonAd,
- // Frame is an ad whose parent frame is an ad.
- kChildAd,
- // Frame is an ad whose parent frame is not an ad.
- kRootAd
-};
-
diff --git a/chromium/third_party/blink/public/mojom/background_sync/OWNERS b/chromium/third_party/blink/public/mojom/background_sync/OWNERS
index 502de83d471..1e3120be359 100644
--- a/chromium/third_party/blink/public/mojom/background_sync/OWNERS
+++ b/chromium/third_party/blink/public/mojom/background_sync/OWNERS
@@ -1,6 +1,5 @@
-iclelland@chromium.org
-jkarlin@chromium.org
peter@chromium.org
+rayankans@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/blob/blob_url_store.mojom b/chromium/third_party/blink/public/mojom/blob/blob_url_store.mojom
index ca0fa77b394..d8f99d14ad1 100644
--- a/chromium/third_party/blink/public/mojom/blob/blob_url_store.mojom
+++ b/chromium/third_party/blink/public/mojom/blob/blob_url_store.mojom
@@ -16,13 +16,20 @@ interface BlobURLStore {
// all URLs registered through it will be revoked.
// TODO(kinuko,mek): This should probably create and return a new blob: URL rather
// than letting the caller in the renderer provide one.
- [Sync] Register(pending_remote<blink.mojom.Blob> blob, url.mojom.Url url) => ();
+ [Sync] Register(
+ pending_remote<blink.mojom.Blob> blob,
+ url.mojom.Url url,
+ // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ mojo_base.mojom.UnguessableToken unsafe_agent_cluster_id) => ();
// Revokes a public Blob URL.
Revoke(url.mojom.Url url);
// Resolves a public Blob URL.
- Resolve(url.mojom.Url url) => (pending_remote<blink.mojom.Blob>? blob);
+ Resolve(url.mojom.Url url) => (
+ pending_remote<blink.mojom.Blob>? blob,
+ // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ mojo_base.mojom.UnguessableToken? unsafe_agent_cluster_id);
// Resolves a public Blob URL to a URLLoaderFactory that can only load the
// specified URL. The reason the API is shaped like this rather than just
@@ -32,14 +39,19 @@ interface BlobURLStore {
// also be kept alive, so it is possible to start loading the blob long after
// both the blob URL and all other references to the blob have been dropped.
ResolveAsURLLoaderFactory(
- url.mojom.Url url,
- pending_receiver<network.mojom.URLLoaderFactory> factory);
+ url.mojom.Url url,
+ pending_receiver<network.mojom.URLLoaderFactory> factory) => (
+ // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ mojo_base.mojom.UnguessableToken? unsafe_agent_cluster_id);
// Resolves a public Blob URL into a BlobURLToken. The BlobURLToken can be
// used by the browser process to securely look up the blob a URL used to
// refer to, even after the URL is revoked.
// As long as the token is alive, the resolved blob will also be kept alive.
- ResolveForNavigation(url.mojom.Url url, pending_receiver<BlobURLToken> token);
+ ResolveForNavigation(url.mojom.Url url,
+ pending_receiver<BlobURLToken> token) => (
+ // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ mojo_base.mojom.UnguessableToken? unsafe_agent_cluster_id);
};
// A token representing a Blob URL. The browser process can use this to look up
diff --git a/chromium/third_party/blink/public/mojom/choosers/color_chooser.mojom b/chromium/third_party/blink/public/mojom/choosers/color_chooser.mojom
index 07c445c306b..04b928ebbf6 100644
--- a/chromium/third_party/blink/public/mojom/choosers/color_chooser.mojom
+++ b/chromium/third_party/blink/public/mojom/choosers/color_chooser.mojom
@@ -11,6 +11,7 @@ struct ColorSuggestion {
// A ColorChooser window is shown for <input type="color">.
interface ColorChooserFactory {
+ [EnableIf=is_android]
OpenColorChooser(
pending_receiver<ColorChooser> chooser,
pending_remote<ColorChooserClient> client,
diff --git a/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom b/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom
index 2565555d753..b67ee00a71a 100644
--- a/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom
+++ b/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom
@@ -4,11 +4,12 @@
module blink.mojom;
-import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/big_buffer.mojom";
import "mojo/public/mojom/base/big_string.mojom";
+import "mojo/public/mojom/base/string16.mojom";
import "skia/public/mojom/bitmap.mojom";
import "third_party/blink/public/mojom/data_transfer/data_transfer.mojom";
+import "third_party/blink/public/mojom/tokens/tokens.mojom";
import "url/mojom/url.mojom";
enum ClipboardFormat {
@@ -35,13 +36,49 @@ struct ClipboardFiles {
string? file_system_id;
};
-// Allows communication with the system clipboard.
+// Implemented by the browser to allow the renderer to use the system clipboard.
// Individual operations are atomic, but successive operations are not.
// Therefore, it's possible that one may see text available from
// ReadAvailableTypes(), but that a subsequent ReadText() may then fail.
+//
+// Security and Privacy Model:
+// Native: Operating systems (OS's) generally provide clipboard access as-is to
+// native applications (including Chrome), trusting that users who install these
+// applications trust the apps' clipboard use to be safe. This means both
+// formats and payloads read/written by native applications are used by OS's
+// as-is. Native applications also often trust other native applications
+// in this manner, and may have existing vulnerabilities that untrusted content
+// (ex. from the web) could potentially exploit.
+//
+// Web: As browsers and users view web content as untrusted by default, the
+// browser must limit and secure web content from interaction with the OS, that
+// has a more trusted security model, and vice versa.
+//
+// Security: Content written to the clipboard should generally be sanitized
+// to protect insecure / out-of-date decoders in native applications from
+// malicious, untrusted, web-originated content. For example, PNG images should
+// be sanitized due to PNG vulnerabilities that may exist in native decoders.
+// Native applications tend to not be sandboxed, have lower update rates, and
+// have higher levels of system permissions than web applications, so failure
+// to properly sanitize may lead to sandbox escapes and remote code execution.
+//
+// Privacy: Content read from the clipboard should generally sanitize any
+// content that users may not reasonably expect to be on their clipboard.
+// Failure to do so may lead to users leaking sensitive information,
+// that may for example be held in metadata.
interface ClipboardHost {
+ // Conservative limits to maximum format name and data sizes, to avoid
+ // potential attacks with long strings. These limits are only applied to
+ // unsanitized custom formats. The size limit includes the null terminator.
+ const uint32 kMaxFormatSize = 1024;
+ const uint32 kMaxDataSize = 1073741824; // 1 GB, or 1 << 30
+
+ // Returns a token which uniquely identifies clipboard state.
+ // This can be used to version the data on the clipboard and determine
+ // whether it has changed.
[Sync]
- GetSequenceNumber(ClipboardBuffer buffer) => (uint64 result);
+ GetSequenceNumber(ClipboardBuffer buffer) =>
+ (blink.mojom.ClipboardSequenceNumberToken result);
[Sync]
IsFormatAvailable(ClipboardFormat format,
@@ -67,6 +104,12 @@ interface ClipboardHost {
[Sync]
ReadRtf(ClipboardBuffer buffer) => (mojo_base.mojom.BigString result);
+ // Read an image from the OS clipboard, returning the PNG-encoded bytes if
+ // there is an image, or an empty buffer otherwise.
+ [Sync]
+ ReadPng(ClipboardBuffer buffer) => (mojo_base.mojom.BigBuffer png);
+
+ // TODO(crbug.com/1223849): Transition call sites to ReadPng, then remove.
[Sync]
ReadImage(ClipboardBuffer buffer) => (skia.mojom.BitmapN32? image);
@@ -85,6 +128,22 @@ interface ClipboardHost {
ReadCustomData(ClipboardBuffer buffer, mojo_base.mojom.String16 type) =>
(mojo_base.mojom.BigString16 result);
+ // Reads both unsanitized custom formats & standard
+ // formats(such as text/html).
+ // `format_types` contains the list of all available custom & standard
+ // formats.
+ [Sync]
+ ReadAvailableCustomAndStandardFormats() =>
+ (array<mojo_base.mojom.String16> format_types);
+
+ // Reads an unsanitized custom format from the clipboard.
+ // `format` contains the custom format name.
+ // Returns the data from the clipboard corresponding to the `format`.
+ // Returns empty `data` if the `format` is not available in the clipboard.
+ [Sync]
+ ReadUnsanitizedCustomFormat(mojo_base.mojom.String16 format) =>
+ (mojo_base.mojom.BigBuffer data);
+
// Writing to the clipboard via mojo is a two-phase operation. First, the
// sender sends the different types of data it'd like to write to the
// receiver. Then, it sends a commit message to commit the data to the system
@@ -111,6 +170,14 @@ interface ClipboardHost {
WriteImage(skia.mojom.BitmapN32 image);
+ // Writes an unsanitized custom format to the clipboard.
+ // `format` contains the name of the custom format and `data` contains the
+ // unsanitized payload provided by the web authors.
+ // There can only be 100 custom formats per write operation and it will be
+ // registered when the web authors request for a custom format.
+ WriteUnsanitizedCustomFormat(mojo_base.mojom.String16 format,
+ mojo_base.mojom.BigBuffer data);
+
CommitWrite();
[EnableIf=is_mac]
diff --git a/chromium/third_party/blink/public/mojom/clipboard/raw_clipboard.mojom b/chromium/third_party/blink/public/mojom/clipboard/raw_clipboard.mojom
deleted file mode 100644
index 90958fffca5..00000000000
--- a/chromium/third_party/blink/public/mojom/clipboard/raw_clipboard.mojom
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-import "mojo/public/mojom/base/string16.mojom";
-import "mojo/public/mojom/base/big_buffer.mojom";
-
-// RawClipboardHost allows "raw", unmodified, and unsanitized communication with
-// the system clipboard, and can pass platform-specific clipboard payloads.
-//
-// Individual operations are atomic, but successive operations are not.
-// Therefore, it's possible that one may see a format available from
-// ReadAvailableFormatNames(), but that a subsequent Read() may then fail.
-//
-// The RawClipboardHost mojo connection enforces that interactions aren't done
-// without permission by only binding if permission is granted, and
-// automatically unbinding if permission is revoked.
-// (It won't automatically re-bind if permission is re-granted afterwards).
-//
-// Please be careful about endpoints that use this interface, as unsanitized
-// content reaching the platform clipboard may lead to remote code execution.
-interface RawClipboardHost {
- // Conservative limits to maximum format name and data sizes, to avoid
- // potential attacks with long strings.
- const int32 kMaxFormatSize = 1024;
- const int32 kMaxDataSize = 1073741824; // 1 GB, or 1 << 30
-
- // Reads unsanitized/raw platform-specific types.
- ReadAvailableFormatNames() => (array<mojo_base.mojom.String16> raw_types);
-
- // Reads unsanitized/raw data from the platform.
- Read(mojo_base.mojom.String16 format) => (mojo_base.mojom.BigBuffer data);
-
- // Writes unsanitized/raw data from renderer.
- Write(mojo_base.mojom.String16 format, mojo_base.mojom.BigBuffer data);
-
- // Writes must call CommitWrite for changes to reach the underlying platform.
- CommitWrite();
-};
diff --git a/chromium/third_party/blink/public/mojom/conversions/conversions.mojom b/chromium/third_party/blink/public/mojom/conversions/conversions.mojom
index 146e46f4c2f..2b2d6e744ee 100644
--- a/chromium/third_party/blink/public/mojom/conversions/conversions.mojom
+++ b/chromium/third_party/blink/public/mojom/conversions/conversions.mojom
@@ -7,6 +7,10 @@ module blink.mojom;
import "mojo/public/mojom/base/time.mojom";
import "url/mojom/origin.mojom";
+struct DedupKey {
+ int64 value;
+};
+
struct Conversion {
// Origin of the conversion registration redirect.
url.mojom.Origin reporting_origin;
@@ -18,6 +22,14 @@ struct Conversion {
// Event source trigger data specified in conversion redirect. 0 is used as a
// default if none is provided.
uint64 event_source_trigger_data = 0;
+
+ // Priority specified in conversion redirect. 0 is used as a default if none
+ // is provided.
+ int64 priority = 0;
+
+ // Key specified in conversion redirect for deduplication against existing
+ // conversions with the same source.
+ DedupKey? dedup_key;
};
// Mojo struct to represent blink::Impression native struct.
@@ -43,6 +55,24 @@ struct Impression {
int64 priority = 0;
};
+// Errors that can result from trying to register an impression.
+// TODO(crbug.com/1202170): In the future, this may be returned from the
+// RegisterImpression method below, so that errors from the ConversionHost can
+// be propagated to registerAttributionSource calls in JS.
+enum RegisterImpressionError {
+ // The permission policy doesn't allow use of the attribution reporting API.
+ kNotAllowed,
+ // The frame's context is not secure.
+ kInsecureContext,
+ // The attributionDestination parameter doesn't have a secure origin.
+ kInsecureAttributionDestination,
+ // The attributionReportTo parameter doesn't have a secure origin.
+ kInsecureAttributionReportTo,
+ // The attributionSourceEventId parameter isn't parsable as an unsigned
+ // 64-bit base-10 integer.
+ kInvalidAttributionSourceEventId,
+};
+
// Sent from renderer to browser process when a resource request matching the
// .well-known conversion registration path is intercepted.
interface ConversionHost {
@@ -52,7 +82,8 @@ interface ConversionHost {
RegisterConversion(Conversion conversion);
// Registers an impression. Triggered by the registerattributionsource
- // attribute being added to an anchor element alongside other API attributes.
- // These impressions are not associated with a browser navigation.
+ // attribute being added to an anchor element alongside other API attributes,
+ // or by the registerAttributionSource JS method. These impressions are not
+ // associated with a browser navigation.
RegisterImpression(Impression impression);
};
diff --git a/chromium/third_party/blink/public/mojom/cookie_manager/OWNERS b/chromium/third_party/blink/public/mojom/cookie_manager/OWNERS
new file mode 100644
index 00000000000..3d3624734b5
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/cookie_manager/OWNERS
@@ -0,0 +1,4 @@
+file://net/cookies/OWNERS
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/cookie_manager/cookie_manager_automation.mojom b/chromium/third_party/blink/public/mojom/cookie_manager/cookie_manager_automation.mojom
new file mode 100644
index 00000000000..e3e1f5d335d
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/cookie_manager/cookie_manager_automation.mojom
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.test.mojom;
+
+// Provides a way for tests to modify all cookies where needed.
+interface CookieManagerAutomation {
+ // Delete all cookies for the url of the calling frame.
+ // See https://w3c.github.io/webdriver/#delete-all-cookies
+ DeleteAllCookies() => ();
+};
diff --git a/chromium/third_party/blink/public/mojom/crash/OWNERS b/chromium/third_party/blink/public/mojom/crash/OWNERS
index faea83280c9..08850f42120 100644
--- a/chromium/third_party/blink/public/mojom/crash/OWNERS
+++ b/chromium/third_party/blink/public/mojom/crash/OWNERS
@@ -1,5 +1,2 @@
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
-
-yuzus@chromium.org
-
diff --git a/chromium/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom b/chromium/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom
index 952102ff78f..4fbfdd5b57b 100644
--- a/chromium/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom
+++ b/chromium/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom
@@ -47,6 +47,7 @@ enum CredentialManagerError {
BAD_RELYING_PARTY_ID,
CANNOT_READ_AND_WRITE_LARGE_BLOB,
INVALID_ALLOW_CREDENTIALS_FOR_LARGE_BLOB,
+ FAILED_TO_SAVE_CREDENTIAL_ID_FOR_PAYMENT_EXTENSION,
UNKNOWN
};
diff --git a/chromium/third_party/blink/public/mojom/css/preferred_contrast.mojom b/chromium/third_party/blink/public/mojom/css/preferred_contrast.mojom
index 7af64860294..b47fff63182 100644
--- a/chromium/third_party/blink/public/mojom/css/preferred_contrast.mojom
+++ b/chromium/third_party/blink/public/mojom/css/preferred_contrast.mojom
@@ -9,4 +9,5 @@ enum PreferredContrast {
kMore,
kLess,
kNoPreference,
+ kCustom,
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/public/mojom/devtools/inspector_issue.mojom b/chromium/third_party/blink/public/mojom/devtools/inspector_issue.mojom
index 777e60829cb..9da985049c8 100644
--- a/chromium/third_party/blink/public/mojom/devtools/inspector_issue.mojom
+++ b/chromium/third_party/blink/public/mojom/devtools/inspector_issue.mojom
@@ -8,6 +8,7 @@ import "url/mojom/url.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/blocked_by_response_reason.mojom";
import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
// A code that uniquely identifies an issue. This type should be descriptive
// enough for the front-end to provide a clear description of the issue.
@@ -183,6 +184,7 @@ struct InspectorIssueDetails {
TrustedWebActivityIssueDetails? twa_issue_details;
HeavyAdIssueDetails? heavy_ad_issue_details;
LowTextContrastIssue? low_text_contrast_details;
+ mojo_base.mojom.UnguessableToken? issue_id;
};
struct InspectorIssueInfo {
diff --git a/chromium/third_party/blink/public/mojom/dom_storage/dom_storage.mojom b/chromium/third_party/blink/public/mojom/dom_storage/dom_storage.mojom
index fbfc309ddaf..3b3bea5db5e 100644
--- a/chromium/third_party/blink/public/mojom/dom_storage/dom_storage.mojom
+++ b/chromium/third_party/blink/public/mojom/dom_storage/dom_storage.mojom
@@ -23,7 +23,7 @@ interface DomStorageProvider {
// interface and a corresponding DomStorageClient interface pointing back at the
// renderer.
interface DomStorage {
- // Binds to a StorageArea interface for Local Storage within |origin|, which
+ // Binds to a StorageArea interface for Local Storage within `origin`, which
// must be validated by the browser to ensure the renderer is allowed to
// access that origin's data.
OpenLocalStorage(url.mojom.Origin origin,
diff --git a/chromium/third_party/blink/public/mojom/dom_storage/storage_area.mojom b/chromium/third_party/blink/public/mojom/dom_storage/storage_area.mojom
index c9f9124eb6f..adbb73ef9c5 100644
--- a/chromium/third_party/blink/public/mojom/dom_storage/storage_area.mojom
+++ b/chromium/third_party/blink/public/mojom/dom_storage/storage_area.mojom
@@ -8,33 +8,33 @@ module blink.mojom;
//
// NOTE: When used for Local Storage, all of the events defined here may be
// received by an observer. Session Storage observers will ONLY ever observe
-// |AllDeleted()| messages, and only in response to browser-initiated storage
+// `AllDeleted()` messages, and only in response to browser-initiated storage
// removal. This is because every Session Storage area is effectively owned by
// a single client and there is no need to incur IPC overhead by repeating the
// client's changes back to itself.
interface StorageAreaObserver {
- // Notifies the observer that a key's value was changed. If |old_value| is
+ // Notifies the observer that a key's value was changed. If `old_value` is
// null, the key was newly added and had no previous value stored.
KeyChanged(array<uint8> key, array<uint8> new_value, array<uint8>? old_value,
string source);
// Notifies the observer that a requested key change failed. This is generally
- // only of interest to the client corresponding to |source| which attempted to
+ // only of interest to the client corresponding to `source` which attempted to
// change the key (e.g. to roll back a cache update).
KeyChangeFailed(array<uint8> key, string source);
- // Notifies the observer that a key was deleted. |old_value| may be null if
+ // Notifies the observer that a key was deleted. `old_value` may be null if
// the deleted key didn't have an entry prior to this call.
KeyDeleted(array<uint8> key, array<uint8>? old_value, string source);
- // Notifies the observer that all keys were deleted. |was_nonempty| indicates
+ // Notifies the observer that all keys were deleted. `was_nonempty` indicates
// whether the StorageArea had at least one key-value stored at when the
- // corresponding |DeleteAll()| call was received.
+ // corresponding `DeleteAll()` call was received.
AllDeleted(bool was_nonempty, string source);
- // Tells the client if it should send the old values for the key on |Put()|
- // and |Delete()| calls for sending notifications. Clients should assume they
- // need to send these values unless this method is called with |false| at some
+ // Tells the client if it should send the old values for the key on `Put()`
+ // and `Delete()` calls for sending notifications. Clients should assume they
+ // need to send these values unless this method is called with `false` at some
// point.
ShouldSendOldValueOnMutations(bool value);
};
@@ -60,68 +60,68 @@ interface StorageArea {
// Adds an observer to monitor changes to the StorageArea. Note that no
// guarantees can be made about exactly when this observer will start
- // observing events. For example, a |Put()| immediately before or after this
- // |AddObserver()| call may or may not result in a corresponding
- // |KeyChanged()| event on the observer.
+ // observing events. For example, a `Put()` immediately before or after this
+ // `AddObserver()` call may or may not result in a corresponding
+ // `KeyChanged()` event on the observer.
//
// In order to properly synchronize observed events against known storage
- // state, callers must use |GetAll()| or |DeleteAll()| and pass an observer
+ // state, callers must use `GetAll()` or `DeleteAll()` and pass an observer
// to those methods.
AddObserver(pending_remote<StorageAreaObserver> observer);
- // Set the database entry for |key| to |value|.
- // Takes an optional |client_old_value| (see ShouldSendOldValueOnMutations()):
+ // Set the database entry for `key` to `value`.
+ // Takes an optional `client_old_value` (see ShouldSendOldValueOnMutations()):
// 1. If the client is notified to not send old value on mutations
- // |client_old_value| is unused and can be nullopt.
+ // `client_old_value` is unused and can be nullopt.
// 2. If the client is notified to send old values or not notified at all,
- // |client_old_value| must be filled in with old value of the |key|, or
- // nullopt if |key| was not present in database. This value is used to send
+ // `client_old_value` must be filled in with old value of the `key`, or
+ // nullopt if `key` was not present in database. This value is used to send
// notifications to StorageArea(s).
- // Returns |true| on success or |false| on failure.
+ // Returns `true` on success or `false` on failure.
//
// Note that a successful reply should not be treated as an indication that
- // the value stored at |key| is |value|: it is possible for the reply to be
+ // the value stored at `key` is `value`: it is possible for the reply to be
// received after some other client has already modified the key again.
// Clients interested in maintaining a consistent local cache of the stored
// contents should rely only on sequential StorageAreaObserver events from
- // an observer bound via |GetAll()| or |DeleteAll()|.
+ // an observer bound via `GetAll()` or `DeleteAll()`.
Put(array<uint8> key, array<uint8> value, array<uint8>? client_old_value,
string source)
=> (bool success);
- // Remove the database entry (if any) for |key|.
- // Takes an optional |client_old_value| (see ShouldSendOldValueOnMutations()):
+ // Remove the database entry (if any) for `key`.
+ // Takes an optional `client_old_value` (see ShouldSendOldValueOnMutations()):
// 1. If the client is notified to not send old value on mutations,
- // |client_old_value| is unused and can be nullopt.
+ // `client_old_value` is unused and can be nullopt.
// 2. If the client is notified to send old values or not notified at all,
- // |client_old_value| must be filled in with old value of the |key|, or
- // nullopt if |key| was not present in database. This value is used to send
+ // `client_old_value` must be filled in with old value of the `key`, or
+ // nullopt if `key` was not present in database. This value is used to send
// notifications to StorageAreaObserver(s).
//
- // TODO(https://crbug.com/1000959): Remove the |success| reply argument. This
+ // TODO(https://crbug.com/1000959): Remove the `success` reply argument. This
// call always succeeds.
//
// Note that a successful reply should not be treated as an indication that
- // the value for |key| is still empty: it is possible for the reply to be
+ // the value for `key` is still empty: it is possible for the reply to be
// received after some other client has already added the key again. Clients
// interested in maintaining a consistent local cache of the stored contents
// should rely only on sequential StorageAreaObserver events from an observer
- // bound via |GetAll()| or |DeleteAll()|.
+ // bound via `GetAll()` or `DeleteAll()`.
Delete(array<uint8> key, array<uint8>? client_old_value, string source)
=> (bool success);
- // Removes all entries. If |new_observer| is non-null, it will be added to
+ // Removes all entries. If `new_observer` is non-null, it will be added to
// the StorageArea's set of observers immediately BEFORE broadcasting the
- // corresponding |AllDeleted()| event, such that |new_observer|'s receiver
- // will always receive that |AllDeleted()| as its first observed event.
+ // corresponding `AllDeleted()` event, such that `new_observer`'s receiver
+ // will always receive that `AllDeleted()` as its first observed event.
//
- // TODO(https://crbug.com/1000959): Remove the |success| reply argument. This
+ // TODO(https://crbug.com/1000959): Remove the `success` reply argument. This
// call always succeeds.
DeleteAll(string source, pending_remote<StorageAreaObserver>? new_observer)
=> (bool success);
- // [DEPRECATED] Returns the value of the |key| only if values are
- // stored in the internal in-memory cache. Fails if the |key| does not exist
+ // [DEPRECATED] Returns the value of the `key` only if values are
+ // stored in the internal in-memory cache. Fails if the `key` does not exist
// or if values are not required to be stored in the cache.
// TODO(ssid): Remove this function, crbug.com/764127.
Get(array<uint8> key) => (bool success, array<uint8> value);
diff --git a/chromium/third_party/blink/public/mojom/fetch/fetch_api_request.mojom b/chromium/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
index 57287aebced..8e30381eef6 100644
--- a/chromium/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
+++ b/chromium/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
@@ -9,6 +9,7 @@ import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/network/public/mojom/chunked_data_pipe_getter.mojom";
import "services/network/public/mojom/fetch_api.mojom";
+import "services/network/public/mojom/request_priority.mojom";
import "services/network/public/mojom/url_request.mojom";
import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
import "third_party/blink/public/mojom/loader/request_context_frame_type.mojom";
diff --git a/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom b/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom
index 7d169ec828f..a65b71f0a7f 100644
--- a/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom
+++ b/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom
@@ -104,4 +104,9 @@ struct FetchAPIResponse {
// Information related to an authentication challenge from the response, if
// there was one.
network.mojom.AuthChallengeInfo? auth_challenge_info;
+
+ // The request's |includeCredentials| value from the "HTTP-network fetch"
+ // algorithm.
+ // See: https://fetch.spec.whatwg.org/#concept-http-network-fetch
+ bool request_include_credentials = true;
};
diff --git a/chromium/third_party/blink/public/mojom/file/file_utilities.mojom b/chromium/third_party/blink/public/mojom/file/file_utilities.mojom
index a894971b79b..4f564a4ecca 100644
--- a/chromium/third_party/blink/public/mojom/file/file_utilities.mojom
+++ b/chromium/third_party/blink/public/mojom/file/file_utilities.mojom
@@ -4,6 +4,7 @@
module blink.mojom;
+import "mojo/public/mojom/base/file.mojom";
import "mojo/public/mojom/base/file_info.mojom";
import "mojo/public/mojom/base/file_path.mojom";
@@ -12,4 +13,32 @@ interface FileUtilitiesHost {
[Sync]
GetFileInfo(mojo_base.mojom.FilePath path) => (
mojo_base.mojom.FileInfo? result);
+
+ // Extends or truncates a previously opened file on macOS < 10.15.
+ //
+ // `result` is true if base::File::SetLength() succeeded, otherwise false.
+ //
+ // Calls ReportBadMessage() on macOS 10.15+. Disabled on other OSes.
+ //
+ // This call is a workaround for a sandboxing limitation in macOS < 10.15 that
+ // results in ftruncate() to fail when called from (sandboxed) renderers.
+ // On modern macOS versions, the renderer calls ftruncate() directly instead
+ // of using this call. The sandboxing issue is discussed at
+ // https://crbug.com/1084565.
+ //
+ // The rendererer passes the file handle to the backend. This could have been
+ // avoided by having NativeIOFileHost always store a dup()ed handle for the
+ // file. This alternative was rejected in order to avoid reasoning about the
+ // effects of having multiple file handles pointing to the same file.
+ //
+ // A compromised renderer may use this call with an arbitrary file handle.
+ // This is not considered a significant attack surface because renderers on
+ // macOS 10.15+ and all other OSes are able to call ftruncate() on any file
+ // handle they have.
+ //
+ // By the same reasoning above (renderers on most OSes can call ftruncate()
+ // directly), this call returns unsanitized base::File::Error information.
+ [EnableIf=is_mac]
+ SetLength(mojo_base.mojom.File backing_file, int64 length) =>
+ (mojo_base.mojom.File backing_file, bool result);
};
diff --git a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_access_handle_host.mojom b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_access_handle_host.mojom
new file mode 100644
index 00000000000..1caaf94de30
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_access_handle_host.mojom
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+// Exclusive lock for an AccessHandle created by the renderer.
+//
+// The interface is consumed by Blink in the renderer process. The interface is
+// currently implemented in the browser process, and will eventually move to the
+// Storage Service.
+//
+// This interface currently serves as a lock. The renderer gets exclusive access
+// to the associated file while it keeps this interface's mojo pipe open.
+interface FileSystemAccessAccessHandleHost {
+ // Promises to the browser that the file and AccessHandle were closed. This
+ // allows the browser to release the exclusive write lock held on the owning
+ // FileSystemFileHandle.
+ //
+ // Well-behaved renderers will call this method after closing the associated
+ // file descriptor received by the
+ // FileSystemAccessFileHandle.OpenAccessHandle().
+ //
+ // A compromised renderer may lie and call this method without closing its
+ // corresponding file descriptor. This may allow it to observe writes from
+ // other renderers to the same (origin-scoped) file, so no cross-origin data
+ // would be leaked.
+ Close() => ();
+};
diff --git a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom
index 26d3b6663e1..8dfa4790857 100644
--- a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom
+++ b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom
@@ -66,6 +66,12 @@ interface FileSystemAccessDirectoryHandle {
// Returns all the direct children of this directory.
GetEntries(pending_remote<FileSystemAccessDirectoryEntriesListener> listener);
+ // Deletes the directory represented by this handle.
+ // To delete recursively, set |recurse| to true.
+ // Returns an error if the directory does not exist or is not empty and
+ // |recurse| is not specified.
+ Remove(bool recurse) => (FileSystemAccessError result);
+
// Deletes an entry which is a child of this directory.
// To delete recursively, set |recurse| to true.
RemoveEntry(string basename, bool recurse) => (FileSystemAccessError result);
diff --git a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_delegate_host.mojom b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_delegate_host.mojom
new file mode 100644
index 00000000000..f4a9afb4b26
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_delegate_host.mojom
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "mojo/public/mojom/base/big_buffer.mojom";
+import "mojo/public/mojom/base/file_error.mojom";
+
+// Routes file operations to the browser to interact with an in-memory file.
+// Used by a SyncAccessHandle in incognito mode, which creates an in-memory file
+// for the Origin-Private File System.
+// Methods are sync or async as appropriate to match the web-exposed
+// behavior of the corresponding methods of the SyncAccessHandle.
+interface FileSystemAccessFileDelegateHost {
+ // Read up to `bytes_to_read` from the associated file starting at `offset`.
+ // If the read is successful, returns a buffer with the read data, the number
+ // of bytes read (which may be less than the length of `data`), and an `error`
+ // of `base::File::Error::FILE_OK`.
+ // `data` is null and `bytes_to_read` is 0 if the read fails.
+ [Sync]
+ Read(uint64 offset, uint64 bytes_to_read) => (mojo_base.mojom.BigBuffer? data,
+ mojo_base.mojom.FileError error,
+ int32 bytes_read);
+
+ // Writes `data` to the associated file starting at `offset`.
+ // Returns the number of bytes written and a file error, which is
+ // `base::File::Error::FILE_OK` if the write completed successfully.
+ [Sync]
+ Write(uint64 offset, handle<data_pipe_consumer> data) =>
+ (mojo_base.mojom.FileError error, int32 bytes_written);
+
+ // Returns the `length` of the associated file and a file error, which is
+ // `base::File::Error::FILE_OK` if the operation completed successfully.
+ // The returned length of the file will never be more than the max int64.
+ GetLength() => (mojo_base.mojom.FileError error, uint64 length);
+
+ // Truncates a file to `length`. If `length` is larger than the file size, the
+ // file will be extended with null bytes.
+ // Returns whether the operation completed successfully.
+ SetLength(uint64 length) => (bool success);
+};
diff --git a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom
index 7a497133fc4..c9bef9e6b7f 100644
--- a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom
+++ b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom
@@ -5,13 +5,25 @@
module blink.mojom;
import "mojo/public/mojom/base/file_info.mojom";
+import "mojo/public/mojom/base/file.mojom";
import "third_party/blink/public/mojom/blob/blob.mojom";
import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
+import "third_party/blink/public/mojom/file_system_access/file_system_access_access_handle_host.mojom";
import "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom";
+import "third_party/blink/public/mojom/file_system_access/file_system_access_file_delegate_host.mojom";
import "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom";
import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom";
import "third_party/blink/public/mojom/permissions/permission_status.mojom";
+// Representation of a file for an AccessHandle.
+// `regular_file` is an OS-level file which provides direct read/write access.
+// 'incognito_file_delegate' is used only in Incognito mode. It routes all file
+// operations to the browser.
+union FileSystemAccessAccessHandleFile {
+ mojo_base.mojom.File regular_file;
+ pending_remote<FileSystemAccessFileDelegateHost> incognito_file_delegate;
+};
+
// This interface represents a handle to a directory in the File System Access
// API.
interface FileSystemAccessFileHandle {
@@ -29,6 +41,15 @@ interface FileSystemAccessFileHandle {
CreateFileWriter(bool keep_existing_data, bool auto_close) => (
FileSystemAccessError result, pending_remote<FileSystemAccessFileWriter>? writer);
+ // Deletes the file represented by this handle.
+ // Returns an error if the file does not exist.
+ Remove() => (FileSystemAccessError result);
+
+ // Returns a file object and an access handle host. The file can be used to
+ // initiate file operations from the renderer. The access handle host acts as
+ // an exclusive write lock while the mojo pipe remains open.
+ OpenAccessHandle() => (FileSystemAccessError result, FileSystemAccessAccessHandleFile? file, pending_remote<FileSystemAccessAccessHandleHost>? access_handle_host);
+
// Returns true if |other| represents the same file on disk as this handle.
IsSameEntry(pending_remote<FileSystemAccessTransferToken> other) =>
(FileSystemAccessError result, bool is_same);
diff --git a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom
index d4315ee1b2e..7a41689fb17 100644
--- a/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom
+++ b/chromium/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom
@@ -49,7 +49,9 @@ struct SaveFilePickerOptions {
string suggested_name;
};
-struct DirectoryPickerOptions {};
+struct DirectoryPickerOptions {
+ bool request_writable;
+};
// Encapsulation of data from the FilePickerOptions idl spec:
// https://wicg.github.io/file-system-access/#dictdef-filepickeroptions.
diff --git a/chromium/third_party/blink/public/mojom/font_unique_name_lookup/OWNERS b/chromium/third_party/blink/public/mojom/font_unique_name_lookup/OWNERS
index 78efc30ac24..08850f42120 100644
--- a/chromium/third_party/blink/public/mojom/font_unique_name_lookup/OWNERS
+++ b/chromium/third_party/blink/public/mojom/font_unique_name_lookup/OWNERS
@@ -1,4 +1,2 @@
-drott@chromium.org
-
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/frame/frame.mojom b/chromium/third_party/blink/public/mojom/frame/frame.mojom
index 3bb95982889..6c67cc92fb0 100644
--- a/chromium/third_party/blink/public/mojom/frame/frame.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/frame.mojom
@@ -21,13 +21,13 @@ import "services/network/public/mojom/url_request.mojom";
import "services/network/public/mojom/web_sandbox_flags.mojom";
import "services/viz/public/mojom/compositing/frame_sink_id.mojom";
import "skia/public/mojom/skcolor.mojom";
-import "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom";
import "third_party/blink/public/mojom/blob/blob.mojom";
import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
import "third_party/blink/public/mojom/messaging/transferable_message.mojom";
import "third_party/blink/public/mojom/choosers/popup_menu.mojom";
import "third_party/blink/public/mojom/context_menu/context_menu.mojom";
import "third_party/blink/public/mojom/conversions/conversions.mojom";
+import "third_party/blink/public/mojom/css/preferred_color_scheme.mojom";
import "third_party/blink/public/mojom/devtools/console_message.mojom";
import "third_party/blink/public/mojom/devtools/devtools_agent.mojom";
import "third_party/blink/public/mojom/devtools/inspector_issue.mojom";
@@ -128,6 +128,9 @@ struct DownloadURLParams {
// Whether the download is from context menu.
bool is_context_menu_save = false;
+
+ // True when the download was preceded by a recent gesture from the user.
+ bool has_user_gesture = false;
};
// Actions browser can ask renderer to perform on a Plugin.
@@ -350,6 +353,19 @@ interface LocalFrameHost {
// of a user action.
GoToEntryAtOffset(int32 offset, bool has_user_gesture);
+ // Tells the browser to navigate back or forward in session history to the
+ // history entry associated with |key|. |key| is a renderer-generated random
+ // UUID, per
+ // https://wicg.github.io/app-history/#session-history-entry-app-history-key
+ //
+ // The key is only used to trigger a back/forward navigation, so it is
+ // fundamentally similar to |offset| in GoToEntryAtOffset(). However,
+ // appHistory also requires that |key| match a FrameNavigationEntry in this
+ // frame, and that the target FNE is contiguously same-origin and
+ // same-site-instance with the current FNE, so navigating via this
+ // function is more restrictive than GoToEntryAtOffset().
+ NavigateToAppHistoryKey(string key, bool has_user_gesture);
+
// Changes the title for the page in the UI when the page is navigated or the
// title changes. Sent for top-level frames. This can be null when loading an
// initial empty document (and in some tests).
@@ -497,11 +513,12 @@ interface LocalFrameHost {
blink.mojom.FrameToken child_frame_token,
blink.mojom.FramePolicy frame_policy);
- // Notifies the browser that the frame changed the 'csp' attribute
- // of one of its child frames.
- DidChangeCSPAttribute(
+ // Notifies the browser that one of the iframe attributes tracked by the
+ // browser process changed.
+ DidChangeIframeAttributes(
blink.mojom.FrameToken child_frame_token,
- network.mojom.ContentSecurityPolicy? parsed_csp_attribute);
+ network.mojom.ContentSecurityPolicy? parsed_csp_attribute,
+ bool anonymous);
// Sent by the renderer to request a paint preview of a subframe. |clip_rect|
// is the size of the frame in it's parent. |guid| is an an identifier for
@@ -542,9 +559,9 @@ interface LocalFrameHost {
// navigation.
FrameSizeChanged(gfx.mojom.Size size);
- // Used when a prerendered page is activated. Notifies the browser that the
- // document in this frame dispatched the prerenderingchange event.
- DidActivateForPrerendering();
+ // Notifies the frame that the document preferred color scheme has changed
+ // due to DevTools media emulation.
+ DidUpdatePreferredColorScheme(PreferredColorScheme preferred_color_scheme);
};
// Implemented in Blink, this interface defines frame-specific methods that will
@@ -797,11 +814,6 @@ interface LocalFrame {
bool had_redirect,
network.mojom.SourceLocation? source_location);
- // Sent to a prerendered frame to inform it that it is being activated.
- // The document in the frame updates `document.prerendering` and dispatches
- // the prerenderingchange event.
- ActivateForPrerendering();
-
// Returns a DevToolsAgent interface for this frame, used for
// remote debugging. See DevToolsAgent for details.
// Returned DevToolsAgent must be associated with navigation control,
@@ -991,9 +1003,9 @@ interface RemoteFrame {
SetReplicatedOrigin(url.mojom.Origin origin,
bool is_potentially_trustworthy_unique_origin);
- // Update the replicated ad frame type. Used when the frame is determined to
- // be an ad frame.
- SetReplicatedAdFrameType(blink.mojom.AdFrameType ad_frame_type);
+ // Update the replicated ad status. Used when the frame is tagged or untagged
+ // as an ad frame by Ad Tagging.
+ SetReplicatedIsAdSubframe(bool is_ad_subframe);
// Sets the replicated name and unique name for the frame. Used when the
// name of a frame changes.
@@ -1194,10 +1206,6 @@ interface LocalMainFrame {
UpdateBrowserControlsState(cc.mojom.BrowserControlsState constraints,
cc.mojom.BrowserControlsState current,
bool animate);
-
- // Notify renderer that the window controls overlay has changed size or
- // visibility.
- UpdateWindowControlsOverlay(gfx.mojom.Rect window_controls_overlay_rect);
};
// Implemented in Blink, this interface defines remote main-frame-specific
@@ -1258,6 +1266,10 @@ interface LocalMainFrameHost {
// This corresponds to the window.resizeTo() and window.moveTo() APIs, and the browser
// may ignore this message.
SetWindowRect(gfx.mojom.Rect bounds) => ();
+
+ // Sent once a paint happens after the first non empty layout. In other words,
+ // after the frame has painted something.
+ DidFirstVisuallyNonEmptyPaint();
};
// Implemented in Browser, this interface defines remote-main-frame-specific
diff --git a/chromium/third_party/blink/public/mojom/frame/frame_owner_element_type.mojom b/chromium/third_party/blink/public/mojom/frame/frame_owner_element_type.mojom
index c5863d7de82..5fd15eeca31 100644
--- a/chromium/third_party/blink/public/mojom/frame/frame_owner_element_type.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/frame_owner_element_type.mojom
@@ -15,4 +15,5 @@ enum FrameOwnerElementType {
kEmbed,
kFrame,
kPortal,
+ kFencedframe,
};
diff --git a/chromium/third_party/blink/public/mojom/frame/frame_policy.mojom b/chromium/third_party/blink/public/mojom/frame/frame_policy.mojom
index 13e00234e2b..f4f5c1125bf 100644
--- a/chromium/third_party/blink/public/mojom/frame/frame_policy.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/frame_policy.mojom
@@ -18,5 +18,11 @@ struct FramePolicy {
network.mojom.WebSandboxFlags sandbox_flags;
array<blink.mojom.ParsedPermissionsPolicyDeclaration> container_policy;
map<blink.mojom.DocumentPolicyFeature, blink.mojom.PolicyValue> required_document_policy;
- bool disallow_document_access = false;
+
+ // IMPORTANT NOTE: This is a temporary member that does not align with the
+ // long-term architecture, and will be removed after the <fencedframe>
+ // ShadowDOM-based origin trial, please do not use this for anything else. See
+ // https://docs.google.com/document/d/1ijTZJT3DHQ1ljp4QQe4E4XCCRaYAxmInNzN1SzeJM8s/edit
+ // and crbug.com/1123606.
+ bool is_fenced = false;
};
diff --git a/chromium/third_party/blink/public/mojom/frame/frame_replication_state.mojom b/chromium/third_party/blink/public/mojom/frame/frame_replication_state.mojom
index 482fde33f5c..774781d0e20 100644
--- a/chromium/third_party/blink/public/mojom/frame/frame_replication_state.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/frame_replication_state.mojom
@@ -5,7 +5,6 @@
module blink.mojom;
import "services/network/public/mojom/web_sandbox_flags.mojom";
-import "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom";
import "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom";
import "third_party/blink/public/mojom/frame/frame_policy.mojom";
import "third_party/blink/public/mojom/frame/tree_scope_type.mojom";
@@ -80,14 +79,6 @@ struct FrameReplicationState {
// frame.
blink.mojom.FramePolicy frame_policy;
- // Whether the frame is in a document tree or a shadow tree, per the Shadow
- // DOM spec: https://w3c.github.io/webcomponents/spec/shadow/
- // Note: This should really be const, as it can never change once a frame is
- // created. However, making it const makes it a pain to embed into IPC message
- // params: having a const member implicitly deletes the copy assignment
- // operator.
- blink.mojom.TreeScopeType scope = blink.mojom.TreeScopeType.kDocument;
-
// The insecure request policy that a frame's current document is enforcing.
// Updates are immediately sent to all frame proxies when frames live in
// different processes.
@@ -111,8 +102,6 @@ struct FrameReplicationState {
// long as a the frame has staying on the same eTLD+1.
bool has_received_user_gesture_before_nav = false;
- // Whether this frame is an ad frame. Once a frame becomes an ad, it stays as
- // an ad throughout its lifetime, even if it later navigates to a non-ad
- // document.
- blink.mojom.AdFrameType ad_frame_type = blink.mojom.AdFrameType.kNonAd;
+ // Whether this frame is an ad frame.
+ bool is_ad_subframe = false;
};
diff --git a/chromium/third_party/blink/public/mojom/frame/frame_visual_properties.mojom b/chromium/third_party/blink/public/mojom/frame/frame_visual_properties.mojom
index 50a280236e1..4ba9457fbee 100644
--- a/chromium/third_party/blink/public/mojom/frame/frame_visual_properties.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/frame_visual_properties.mojom
@@ -6,13 +6,13 @@ module blink.mojom;
import "cc/mojom/browser_controls_params.mojom";
import "services/viz/public/mojom/compositing/local_surface_id.mojom";
-import "third_party/blink/public/mojom/widget/screen_info.mojom";
+import "ui/display/mojom/screen_info.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
// See public/common/frame/frame_visual_properties.h
struct FrameVisualProperties {
// Information about the screen (dpi, depth, etc..).
- ScreenInfo screen_info;
+ display.mojom.ScreenInfo screen_info;
// Whether or not blink should be in auto-resize mode.
bool auto_resize_enabled;
diff --git a/chromium/third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom b/chromium/third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom
index a0ccec07af7..90bae508418 100644
--- a/chromium/third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom
+++ b/chromium/third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom
@@ -5,6 +5,8 @@
module blink.mojom;
import "services/viz/public/mojom/compositing/compositor_frame_sink.mojom";
+import "services/viz/public/mojom/compositing/frame_sink_bundle.mojom";
+import "services/viz/public/mojom/compositing/frame_sink_bundle_id.mojom";
import "services/viz/public/mojom/compositing/frame_sink_id.mojom";
import "services/viz/public/mojom/compositing/surface_info.mojom";
import "services/viz/public/mojom/compositing/local_surface_id.mojom";
@@ -35,12 +37,32 @@ interface EmbeddedFrameSinkProvider {
viz.mojom.FrameSinkId frame_sink_id,
pending_remote<EmbeddedFrameSinkClient> client);
+ // Registers a bundle of frame sinks identified by `bundle_id`. The
+ // FrameSinkBundle and FrameSinkBundleClient endpoints are used to perform
+ // batched communication between Viz and the client, regarding any of the
+ // frame sinks included in the bundle. See CreateBundledCompositorFrameSink()
+ // below.
+ RegisterEmbeddedFrameSinkBundle(
+ viz.mojom.FrameSinkId parent_frame_sink_id,
+ viz.mojom.FrameSinkBundleId bundle_id,
+ pending_receiver<viz.mojom.FrameSinkBundle> receiver,
+ pending_remote<viz.mojom.FrameSinkBundleClient> client);
+
// Create a CompositorFrameSink for |frame_sink_id|. This must happen after
// calling RegisterEmbeddedFrameSink() for |frame_sink_id|.
CreateCompositorFrameSink(viz.mojom.FrameSinkId frame_sink_id,
pending_remote<viz.mojom.CompositorFrameSinkClient> client,
pending_receiver<viz.mojom.CompositorFrameSink> sink);
+ // Similar to above, but the frame sink can also be controlled by the
+ // corresponding FrameSinkBundle interface. See
+ // RegisterEmbeddedFrameSinkBundle() above.
+ CreateBundledCompositorFrameSink(
+ viz.mojom.FrameSinkId frame_sink_id,
+ viz.mojom.FrameSinkBundleId bundle_id,
+ pending_remote<viz.mojom.CompositorFrameSinkClient> client,
+ pending_receiver<viz.mojom.CompositorFrameSink> sink);
+
// Create CompositorFrameSink directly in a single call (instead of going
// through both function above).
CreateSimpleCompositorFrameSink(viz.mojom.FrameSinkId parent_frame_sink_id,
diff --git a/chromium/third_party/blink/public/mojom/handwriting/handwriting.mojom b/chromium/third_party/blink/public/mojom/handwriting/handwriting.mojom
index 6b137fa6ea7..b52714c1166 100644
--- a/chromium/third_party/blink/public/mojom/handwriting/handwriting.mojom
+++ b/chromium/third_party/blink/public/mojom/handwriting/handwriting.mojom
@@ -95,7 +95,10 @@ struct HandwritingHints {
// previously recognized, or were given as the writing context (e.g.
// "Write your name here:"). This is the linguistic context to help
// disambiguate the handwriting (e.g. “Hello world” vs. “Hello word”).
- string text_context;
+ // This could be null if the application doesn't or can't provide context. It
+ // could be the empty string if a text field is empty, e.g. the beginning of
+ // input.
+ string? text_context;
// The maximum number of alternative predictions to generate.
uint32 alternatives;
};
diff --git a/chromium/third_party/blink/public/mojom/hyphenation/OWNERS b/chromium/third_party/blink/public/mojom/hyphenation/OWNERS
index 185a39dc647..b89602e4a0e 100644
--- a/chromium/third_party/blink/public/mojom/hyphenation/OWNERS
+++ b/chromium/third_party/blink/public/mojom/hyphenation/OWNERS
@@ -1,7 +1,4 @@
-eae@chromium.org
-drott@chromium.org
kojii@chromium.org
-szager@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/input/input_handler.mojom b/chromium/third_party/blink/public/mojom/input/input_handler.mojom
index e615a7d95b6..1b103098047 100644
--- a/chromium/third_party/blink/public/mojom/input/input_handler.mojom
+++ b/chromium/third_party/blink/public/mojom/input/input_handler.mojom
@@ -132,6 +132,7 @@ struct GestureData {
blink.mojom.GestureDevice source_device;
bool is_source_touch_event_set_blocking;
ui.mojom.EventPointerType primary_pointer_type;
+ int32 primary_unique_touch_event_id;
int32 unique_touch_event_id;
gfx.mojom.Size? contact_size;
ScrollData? scroll_data;
@@ -362,12 +363,14 @@ interface WidgetInputHandler {
CursorVisibilityChanged(bool visible);
// This message sends a string being composed with an input method.
+ // Note, the response is specifically for Devtools to learn about completion
ImeSetComposition(mojo_base.mojom.String16 text,
array<ui.mojom.ImeTextSpan> ime_text_spans,
- gfx.mojom.Range range, int32 start, int32 end);
+ gfx.mojom.Range range, int32 start, int32 end) => ();
// This message deletes the current composition, inserts specified text, and
// moves the cursor.
+ // Note, the response is specifically for Devtools to learn about completion
ImeCommitText(mojo_base.mojom.String16 text,
array<ui.mojom.ImeTextSpan> ime_text_spans,
gfx.mojom.Range range, int32 relative_cursor_position) => ();
@@ -424,4 +427,3 @@ interface WidgetInputHandler {
GetFrameWidgetInputHandler(
pending_associated_receiver<FrameWidgetInputHandler> interface_request);
};
-
diff --git a/chromium/third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom b/chromium/third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom
deleted file mode 100644
index 3ee3591c643..00000000000
--- a/chromium/third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom
+++ /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.
-
-module blink.mojom;
-
-// InsecureInputService receives per-frame notifications about insecure input
-// operations (e.g. editing of any fields) on the page.
-interface InsecureInputService {
- DidEditFieldInInsecureContext();
-};
diff --git a/chromium/third_party/blink/public/mojom/interest_group/DIR_METADATA b/chromium/third_party/blink/public/mojom/interest_group/DIR_METADATA
new file mode 100644
index 00000000000..5313345b4ca
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/interest_group/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>InterestGroups"
+}
diff --git a/chromium/third_party/blink/public/mojom/interest_group/OWNERS b/chromium/third_party/blink/public/mojom/interest_group/OWNERS
index 08850f42120..1848d76c900 100644
--- a/chromium/third_party/blink/public/mojom/interest_group/OWNERS
+++ b/chromium/third_party/blink/public/mojom/interest_group/OWNERS
@@ -1,2 +1,4 @@
+file://third_party/blink/renderer/modules/ad_auction/OWNERS
+
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom b/chromium/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom
index 0e6bf0e0893..eacbb1f7393 100644
--- a/chromium/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom
+++ b/chromium/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom
@@ -12,15 +12,25 @@ import "url/mojom/url.mojom";
// to the renderer on a per-frame basis.
// https://github.com/WICG/turtledove/blob/main/FLEDGE.md
interface RestrictedInterestGroupStore {
- // "Merges" interest group information from `group` with information already
- // stored by the browser process by overwriting the fields provided in
- // `group`. The browser verifies that the owner origin matches that of the
- // frame's origin (in the future, a mechanism will allow delegating to other
- // origins). The caller cannot observe the status or results of this
- // operation.
+ // Requests that the browser process create or overwrite persisted interest
+ // group keyed by `owner` and `name` with information from `group`. The
+ // browser verifies that the owner origin matches that of the frame's origin
+ // (in the future, a mechanism will allow delegating to other origins). The
+ // caller cannot observe the status or results of this operation.
JoinInterestGroup(InterestGroup group);
// Deletes the interest group stored in the browser as indicated by the
// (`origin`, `name`) tuple. `origin` must use https.
LeaveInterestGroup(url.mojom.Origin owner, string name);
+
+ // Requests the browser update stored interest groups owned by the current
+ // frame's origin *only* (interest groups not owned by the frame origin aren't
+ // modified) using the last `update_url` registered for each owned interest
+ // group. JSON is downloaded from each interest group's URL, parsed safely
+ // using //services/data_decoder/public/cpp/data_decoder.h, and the interest
+ // group store is updated. Unlike the JoinInterestGroup() operation, this
+ // operation doesn't clear fields that weren't present in the server JSON
+ // response. The JSON `name`, `owner`, `userBiddingSignals` and other unknown
+ // fields will be ignored.
+ UpdateAdInterestGroups();
};
diff --git a/chromium/third_party/blink/public/mojom/leak_detector/leak_detector.mojom b/chromium/third_party/blink/public/mojom/leak_detector/leak_detector.mojom
index bdfb0082b2a..e0818f0c1d3 100644
--- a/chromium/third_party/blink/public/mojom/leak_detector/leak_detector.mojom
+++ b/chromium/third_party/blink/public/mojom/leak_detector/leak_detector.mojom
@@ -23,5 +23,7 @@ struct LeakDetectionResult {
// performs a garbage collection in Blink's managed heaps
// before reporting various Blink's objects counters.
interface LeakDetector {
- PerformLeakDetection() => (LeakDetectionResult result);
+ // The result may be empty because e.g. workers were still running and
+ // leak detection was not able to terminate them.
+ PerformLeakDetection() => (LeakDetectionResult? result);
};
diff --git a/chromium/third_party/blink/public/mojom/link_to_text/link_to_text.mojom b/chromium/third_party/blink/public/mojom/link_to_text/link_to_text.mojom
index 319b69364b9..ffecbad3c2c 100644
--- a/chromium/third_party/blink/public/mojom/link_to_text/link_to_text.mojom
+++ b/chromium/third_party/blink/public/mojom/link_to_text/link_to_text.mojom
@@ -8,17 +8,20 @@ module blink.mojom;
import "ui/gfx/geometry/mojom/geometry.mojom";
// TextFragmentReceiver is used for requesting renderer to perform text fragment
-// operations on the main frame, mainly generating and removing fragments.
-// Implemented in renderer.
+// operations on the frame that interacts with the link-to-text/shared-highlighting
+// feature, mainly generating and removing fragments. A text fragment receiver is
+// associated with exactly one frame but a frame will only create its receiver
+// lazily when needed.
interface TextFragmentReceiver {
- // Cancel text fragment generation if any active.
+ // Cancel text fragment generation if in progress.
Cancel();
- // Request text fragment selector according to
- // https://github.com/WICG/scroll-to-text-fragment#proposed-solution.
+ // Request that the receiver generate a text fragment selector based on the
+ // currently selected text on the page. See also:
+ // https://github.com/WICG/scroll-to-text-fragment.
RequestSelector() => (string selector);
- // Dismiss all text fragments from the current main frame at the time the
+ // Dismiss all text fragments from this frame at the time the
// context menu was invoked.
RemoveFragments();
@@ -28,6 +31,7 @@ interface TextFragmentReceiver {
// Request text fragment selectors for existing highlights.
GetExistingSelectors() => (array<string> selectors);
- // Request the first text fragment rectangle relative to the viewport
+ // Request the bounding rectangle, relative to the viewport, of the first
+ // found match. Returns an empty rectangle if no matches are found.
ExtractFirstFragmentRect() => (gfx.mojom.Rect bounds);
};
diff --git a/chromium/third_party/blink/public/mojom/loader/resource_load_info.mojom b/chromium/third_party/blink/public/mojom/loader/resource_load_info.mojom
index edb1cdcfc16..565e3ade303 100644
--- a/chromium/third_party/blink/public/mojom/loader/resource_load_info.mojom
+++ b/chromium/third_party/blink/public/mojom/loader/resource_load_info.mojom
@@ -4,12 +4,12 @@
module blink.mojom;
+import "services/network/public/mojom/fetch_api.mojom";
import "services/network/public/mojom/ip_address.mojom";
import "services/network/public/mojom/ip_endpoint.mojom";
import "services/network/public/mojom/load_timing_info.mojom";
import "services/network/public/mojom/network_param.mojom";
-import "services/network/public/mojom/url_request.mojom";
-import "services/network/public/mojom/fetch_api.mojom";
+import "services/network/public/mojom/request_priority.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
diff --git a/chromium/third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom b/chromium/third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom
index 667649e0c55..76d7a92f37f 100644
--- a/chromium/third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom
+++ b/chromium/third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom
@@ -6,6 +6,7 @@ module blink.mojom;
import "services/network/public/mojom/fetch_api.mojom";
import "services/network/public/mojom/url_loader.mojom";
+import "services/network/public/mojom/url_loader_completion_status.mojom";
import "services/network/public/mojom/url_request.mojom";
import "services/network/public/mojom/url_response_head.mojom";
import "third_party/blink/public/mojom/loader/resource_load_info.mojom";
diff --git a/chromium/third_party/blink/public/mojom/loader/same_document_navigation_type.mojom b/chromium/third_party/blink/public/mojom/loader/same_document_navigation_type.mojom
new file mode 100644
index 00000000000..1a269fd21bd
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/loader/same_document_navigation_type.mojom
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+// Enumerates the types of same document navigation as relevant to logic in the
+// browser process
+enum SameDocumentNavigationType {
+ // Navigating to a fragment in the page, e.g. location.hash = "#foo"
+ kFragment = 0,
+ // Navigating with window.history
+ kHistoryApi = 1,
+ // Navigating with AppHistoryNavigateEvent.respondWith()
+ kAppHistoryRespondWith = 2,
+};
+
diff --git a/chromium/third_party/blink/public/mojom/manifest/DIR_METADATA b/chromium/third_party/blink/public/mojom/manifest/DIR_METADATA
new file mode 100644
index 00000000000..0ff3ed55bf6
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/manifest/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>AppManifest"
+}
diff --git a/chromium/third_party/blink/public/mojom/manifest/OWNERS b/chromium/third_party/blink/public/mojom/manifest/OWNERS
index dfbf2000104..6465b1c894e 100644
--- a/chromium/third_party/blink/public/mojom/manifest/OWNERS
+++ b/chromium/third_party/blink/public/mojom/manifest/OWNERS
@@ -2,5 +2,3 @@ file://third_party/blink/renderer/modules/manifest/OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
-
-# Component: Blink>AppManifest
diff --git a/chromium/third_party/blink/public/mojom/manifest/display_mode.mojom b/chromium/third_party/blink/public/mojom/manifest/display_mode.mojom
index d619fed9e3f..a6362525acf 100644
--- a/chromium/third_party/blink/public/mojom/manifest/display_mode.mojom
+++ b/chromium/third_party/blink/public/mojom/manifest/display_mode.mojom
@@ -25,6 +25,10 @@ enum DisplayMode {
// https://github.com/WICG/window-controls-overlay/blob/master/explainer.md.
kWindowControlsOverlay,
+ // This is a non-standard value intended for use in the "display_override"
+ // field of the web app manifest: https://github.com/w3c/manifest/issues/737
+ kTabbed,
+
/**
* This enum is persisted to logs, and therefore is append-only and should not be reordered.
*/
diff --git a/chromium/third_party/blink/public/mojom/manifest/manifest.mojom b/chromium/third_party/blink/public/mojom/manifest/manifest.mojom
index a7b00cd2173..e8257ffc860 100644
--- a/chromium/third_party/blink/public/mojom/manifest/manifest.mojom
+++ b/chromium/third_party/blink/public/mojom/manifest/manifest.mojom
@@ -16,6 +16,8 @@ import "url/mojom/origin.mojom";
// The Manifest structure is an internal representation of the Manifest file
// described in the "Manifest for Web Application" document:
// http://w3c.github.io/manifest/
+// All fields will be their default constructed values (optional types nullopt)
+// if the manifest failed to parse.
[JavaClassName="WebManifest"]
struct Manifest {
mojo_base.mojom.String16? name;
@@ -24,6 +26,9 @@ struct Manifest {
mojo_base.mojom.String16? description;
+ // Defaults to start_url with origin stripped when id field is not present.
+ mojo_base.mojom.String16? id;
+
url.mojom.Url start_url;
DisplayMode display;
@@ -42,16 +47,19 @@ struct Manifest {
// TODO(crbug.com/829689): This field is non-standard and part of a Chrome
// experiment. See:
- // https://github.com/WICG/file-handling/blob/master/explainer.md
+ // https://github.com/WICG/file-handling/blob/main/explainer.md
// As such, this field should not be exposed by default.
array<ManifestFileHandler> file_handlers;
// TODO(crbug.com/1019239): This is going into the mainline manifest spec,
// remove the TODO once that PR goes in.
// The URLProtocolHandler explainer can be found here:
- // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/URLProtocolHandler/explainer.md
+ // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/URLProtocolHandler/explainer.md
array<ManifestProtocolHandler> protocol_handlers;
+ // TODO(crbug.com/1072058): This field is non-standard and part of an
+ // experiment. See:
+ // https://github.com/WICG/pwa-url-handler/blob/main/explainer.md
array<ManifestUrlHandler> url_handlers;
// TODO(crbug.com/1185678): This field is non-standard and part of a manifest
@@ -76,13 +84,25 @@ struct Manifest {
mojo_base.mojom.String16? gcm_sender_id;
+ // Defaults to the start URL (or document URL if start URL isn't present) with
+ // filename, query, and fragment removed if not present.
url.mojom.Url scope;
// TODO(crbug.com/1163398): This field is non-standard and part of a Chrome
// experiment. See:
- // https://github.com/WICG/sw-launch/blob/master/declarative_link_capturing.md#proposal
+ // https://github.com/WICG/sw-launch/blob/main/declarative_link_capturing.md#proposal
// As such, this field should not be exposed by default.
CaptureLinks capture_links;
+
+ // TODO(crbug.com/1212263): This field is non-standard and part of a Chrome
+ // experiment. See:
+ // https://github.com/robbiemc/pwa-isolated-storage/blob/main/explainer.md
+ bool isolated_storage;
+
+ // TODO(crbug.com/1231886): This field is non-standard and part of a Chrome
+ // experiment. See:
+ // https://github.com/WICG/sw-launch/blob/main/launch_handler.md
+ ManifestLaunchHandler? launch_handler;
};
// Structure representing a Shortcut Item per the Manifest specification, see:
@@ -220,11 +240,38 @@ struct ManifestShareTarget {
struct ManifestFileHandler {
// The URL that will be opened when the file handler is invoked.
url.mojom.Url action;
+ // Human-readable name for the file handler. May be displayed in file manager.
mojo_base.mojom.String16 name;
+ // Icon representing the file handler. May be displayed in file manager.
+ array<ManifestImageResource> icons;
// A mapping of a MIME types to a corresponding list of file extensions.
map<mojo_base.mojom.String16, array<mojo_base.mojom.String16>> accept;
};
+// Represents how web app launches should be handled with regard to opening
+// windows or recycling existing ones.
+// Spec: https://github.com/WICG/sw-launch/blob/main/launch_handler.md
+struct ManifestLaunchHandler {
+ // The client to use for app launches.
+ enum RouteTo {
+ // Use whatever the platform would do by default.
+ kAuto,
+ // Create a new client for each app launch.
+ kNewClient,
+ // Use an existing client if available, otherwise create a new one to use.
+ kExistingClient,
+ };
+ RouteTo route_to;
+
+ // When routing to an existing client this specifies whether to navigate it to
+ // the launch URL or just pass the URL in the enqueued LaunchParams.
+ enum NavigateExistingClient {
+ kAlways,
+ kNever,
+ };
+ NavigateExistingClient navigate_existing_client;
+};
+
// Debug information for a parsed manifest.
struct ManifestDebugInfo {
array<ManifestError> errors;
diff --git a/chromium/third_party/blink/public/mojom/manifest/manifest_observer.mojom b/chromium/third_party/blink/public/mojom/manifest/manifest_observer.mojom
index 1d2be9c8465..bf9b1d75b87 100644
--- a/chromium/third_party/blink/public/mojom/manifest/manifest_observer.mojom
+++ b/chromium/third_party/blink/public/mojom/manifest/manifest_observer.mojom
@@ -6,6 +6,9 @@ module blink.mojom;
import "url/mojom/url.mojom";
+// Implemented in the browser process. This interface defines observer methods
+// that are called upon a manifest URL change from the renderer process.
interface ManifestUrlChangeObserver {
- ManifestUrlChanged(url.mojom.Url? manifest_url);
+ // Notifies that a manifest URL is changed.
+ ManifestUrlChanged(url.mojom.Url manifest_url);
};
diff --git a/chromium/third_party/blink/public/mojom/mediastream/OWNERS b/chromium/third_party/blink/public/mojom/mediastream/OWNERS
index 96abc6a7ff0..2da2f53842b 100644
--- a/chromium/third_party/blink/public/mojom/mediastream/OWNERS
+++ b/chromium/third_party/blink/public/mojom/mediastream/OWNERS
@@ -1,5 +1,4 @@
guidou@chromium.org
-hbos@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/mediastream/media_stream.mojom b/chromium/third_party/blink/public/mojom/mediastream/media_stream.mojom
index 9d6092c94b4..4a972bbfa90 100644
--- a/chromium/third_party/blink/public/mojom/mediastream/media_stream.mojom
+++ b/chromium/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -66,6 +66,7 @@ enum MediaStreamRequestResult {
FAILED_DUE_TO_SHUTDOWN,
KILL_SWITCH_ON,
SYSTEM_PERMISSION_DENIED,
+ DEVICE_IN_USE,
NUM_MEDIA_REQUEST_RESULTS
};
diff --git a/chromium/third_party/blink/public/mojom/navigation/navigation_params.mojom b/chromium/third_party/blink/public/mojom/navigation/navigation_params.mojom
new file mode 100644
index 00000000000..090b94933ca
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -0,0 +1,483 @@
+// 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.
+
+module blink.mojom;
+
+import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/time.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
+import "mojo/public/mojom/base/values.mojom";
+import "services/network/public/mojom/content_security_policy.mojom";
+import "services/network/public/mojom/fetch_api.mojom";
+import "services/network/public/mojom/source_location.mojom";
+import "services/network/public/mojom/trust_tokens.mojom";
+import "services/network/public/mojom/url_loader.mojom";
+import "services/network/public/mojom/url_request.mojom";
+import "services/network/public/mojom/url_response_head.mojom";
+import "services/network/public/mojom/web_client_hints_types.mojom";
+import "services/network/public/mojom/web_sandbox_flags.mojom";
+import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
+import "third_party/blink/public/mojom/frame/frame_policy.mojom";
+import "third_party/blink/public/mojom/loader/mixed_content.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
+import "third_party/blink/public/mojom/navigation/navigation_policy.mojom";
+import "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom";
+import "third_party/blink/public/mojom/navigation/was_activated_option.mojom";
+import "third_party/blink/public/mojom/page/page.mojom";
+import "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom";
+import "third_party/blink/public/mojom/storage_key/storage_key.mojom";
+import "third_party/blink/public/mojom/tokens/tokens.mojom";
+import "url/mojom/origin.mojom";
+import "url/mojom/url.mojom";
+import "third_party/blink/public/mojom/conversions/conversions.mojom";
+
+enum NavigationType {
+ // Reload the page, validating only cache entry for the main resource.
+ RELOAD,
+
+ // Reload the page, bypassing any cache entries.
+ RELOAD_BYPASSING_CACHE,
+
+ // Reload the page using the original request URL.
+ RELOAD_ORIGINAL_REQUEST_URL,
+
+ // The navigation is the result of session restore and should honor the
+ // page's cache policy while restoring form state. This is set to true if
+ // restoring a tab/session from the previous session and the previous
+ // session did not crash. If this is not set and the page was restored then
+ // the page's cache policy is ignored and we load from the cache.
+ RESTORE,
+
+ // Like RESTORE, except that the navigation contains POST data.
+ RESTORE_WITH_POST,
+
+ // History navigation inside the same document.
+ HISTORY_SAME_DOCUMENT,
+
+ // History navigation to a different document.
+ HISTORY_DIFFERENT_DOCUMENT,
+
+ // Navigation inside the same document. It occurs when the part of the url
+ // that is modified is after the '#' part.
+ SAME_DOCUMENT,
+
+ // Navigation to another document.
+ DIFFERENT_DOCUMENT,
+};
+
+// Provided by the renderer ----------------------------------------------------
+//
+// This struct holds parameters sent by the renderer to the browser, that are
+// needed to start a navigation.
+struct BeginNavigationParams {
+ // The token of the RenderFrameHost that initiated the navigation. It might
+ // refer to a RenderFrameHost that doesn't exist anymore when the IPC reaches
+ // the browser process.
+ blink.mojom.LocalFrameToken? initiator_frame_token;
+
+ // Additional HTTP request headers.
+ string headers;
+
+ // net::URLRequest load flags (net::LOAD_NORMAL) by default).
+ int32 load_flags = 0; // 0 == net::LOAD_NORMAL
+
+ // True if the ServiceWorker should be skipped.
+ bool skip_service_worker = false;
+
+ // Indicates the request context type.
+ blink.mojom.RequestContextType request_context_type =
+ blink.mojom.RequestContextType.UNSPECIFIED;
+
+ // Indicates the request destination.
+ network.mojom.RequestDestination request_destination =
+ network.mojom.RequestDestination.kEmpty;
+
+ // The mixed content context type for potential mixed content checks.
+ blink.mojom.MixedContentContextType mixed_content_context_type =
+ blink.mojom.MixedContentContextType.kNotMixedContent;
+
+ // Whether or not the navigation has been initiated by a form submission.
+ bool is_form_submission = false;
+
+ // Whether or not the navigation has been initiated by a link click.
+ bool was_initiated_by_link_click = false;
+
+ // See WebSearchableFormData for a description of these.
+ url.mojom.Url searchable_form_url;
+ string searchable_form_encoding;
+
+ // If the transition type is a client side redirect, then this holds the URL
+ // of the page that had the client side redirect.
+ url.mojom.Url client_side_redirect_url;
+
+ // If the navigation is renderer-initiated and the renderer is being
+ // inspected by DevTools, this field is non-null and contains the
+ // initiator information in DevTools protocol format. See
+ // https://chromedevtools.github.io/devtools-protocol/tot/Network#type-Initiator
+ // for details.
+ mojo_base.mojom.DictionaryValue? devtools_initiator;
+
+ // Specifies whether, and how, the navigation should execute a Trust Tokens
+ // operation (https://github.com/wicg/trust-token-api) and attach headers
+ // conveying the result of the operation. Set on some child frame navigations.
+ network.mojom.TrustTokenParams? trust_token_params;
+
+ // Carries optional information associated with conversion measurement for
+ // this navigation. Only set on navigations originating from anchors with
+ // relevant impression attributes set.
+ Impression? impression;
+
+ // Timestamps of the renderer running beforeunload handlers on local frames
+ // in preparation for navigating. Used for metrics.
+ mojo_base.mojom.TimeTicks before_unload_start;
+ mojo_base.mojom.TimeTicks before_unload_end;
+
+ // Token to identify a WebBundle. Set on navigation to a resource in a
+ // WebBundle.
+ network.mojom.WebBundleTokenParams? web_bundle_token;
+};
+
+// Provided by the browser or the renderer -------------------------------------
+
+// Used by all navigation IPCs.
+struct CommonNavigationParams {
+ // The URL to navigate to.
+ // May be modified when the navigation is ready to commit.
+ url.mojom.Url url;
+
+ // When a frame navigates another frame, this is the origin of the document
+ // which initiated the navigation. This parameter can be null for
+ // browser-initiated navigations.
+ url.mojom.Origin? initiator_origin;
+
+ // The URL to send in the "Referer" header field. Can be empty if there is
+ // no referrer.
+ blink.mojom.Referrer referrer;
+
+ // The type of transition.
+ int32 transition;
+
+ // Type of navigation.
+ NavigationType navigation_type = DIFFERENT_DOCUMENT;
+
+ // Governs how downloads are handled by this navigation.
+ blink.mojom.NavigationDownloadPolicy download_policy;
+
+ // Informs the RenderView the pending navigation should replace the current
+ // history entry when it commits. This is used by client-side redirects to
+ // indicate that when the navigation commits, it should commit in the existing
+ // page.
+ bool should_replace_current_entry = false;
+
+ // Base URL for use in Blink's SubstituteData.
+ // Is only used with data: URLs.
+ url.mojom.Url base_url_for_data_url;
+
+ // History URL for use in Blink's SubstituteData.
+ // Is only used with data: URLs.
+ url.mojom.Url history_url_for_data_url;
+
+ // Bitmask that has whether or not to request a Preview version of the
+ // document for various preview types or let the browser decide.
+ // Defined in third_party/blink/public/common/loader/previews_state.h.
+ int32 previews_state = 0; // 0 == PREVIEWS_UNSPECIFIED
+
+ // The navigationStart time exposed through the Navigation Timing API to JS.
+ mojo_base.mojom.TimeTicks navigation_start;
+
+ // The request method: GET, POST, etc.
+ string method = "GET";
+
+ // Body of HTTP POST request.
+ network.mojom.URLRequestBody? post_data;
+
+ // Information about the Javascript source for this navigation. Used for
+ // providing information in console error messages triggered by the
+ // navigation. If the navigation is not caused by Javascript, the
+ // SourceLocation's URL is empty.
+ network.mojom.SourceLocation source_location;
+
+ // Whether or not this navigation was started from a context menu.
+ bool started_from_context_menu = false;
+
+ // True if the request was user initiated.
+ bool has_user_gesture = false;
+
+ // True if the navigation should allow the target document to invoke a text
+ // fragment (i.e. fragments with :~:text=). This is based on user gesture
+ // presence but separate from the bit above as the semantics for text
+ // fragments are different. Namely, this bit is always consumed on use and is
+ // propagated across client redirects.
+ bool text_fragment_token = false;
+
+ // Whether or not the CSP of the main world should apply. When the navigation
+ // is initiated from a content script in an isolated world, the CSP defined
+ // in the main world should not apply.
+ // TODO(arthursonzogni): Instead of this boolean, the origin of the isolated
+ // world which has initiated the navigation should be passed.
+ // See https://crbug.com/702540
+ network.mojom.CSPDisposition should_check_main_world_csp =
+ network.mojom.CSPDisposition.CHECK;
+
+ // The origin trial features activated in the initiator that should be applied
+ // in the document being navigated to. The int values are blink
+ // OriginTrialFeature enum values. OriginTrialFeature enum is not visible
+ // outside of blink (and doesn't need to be) so these values are casted to int
+ // as they are passed through content across navigations.
+ array<int32> initiator_origin_trial_features;
+
+ // The value of the hrefTranslate attribute if this navigation was initiated
+ // from a link that had that attribute set.
+ string href_translate;
+
+ // Whether this is a history navigation in a newly created child frame, in
+ // which case the browser process is instructing the renderer process to load
+ // a URL from a session history item. Defaults to false.
+ // TODO(ahemery): Move this to BeginNavigationParams.
+ bool is_history_navigation_in_new_child_frame = false;
+
+ // The time the input event leading to the navigation occurred. This will
+ // not always be set; it depends on the creator of the CommonNavigationParams
+ // setting it.
+ mojo_base.mojom.TimeTicks input_start;
+};
+
+// Provided by the browser -----------------------------------------------------
+
+// Timings collected in the browser during navigation for the
+// Navigation Timing API. Sent to Blink in CommitNavigationParams when
+// the navigation is ready to be committed.
+struct NavigationTiming {
+ mojo_base.mojom.TimeTicks redirect_start;
+ mojo_base.mojom.TimeTicks redirect_end;
+ mojo_base.mojom.TimeTicks fetch_start;
+};
+
+// Sent with CommitNavigationParams and should only be set for main-frame
+// same-site navigations where we did a proactive BrowsingInstance swap and
+// we're reusing the old page's process. Needed to ensure that the previous
+// page's pagehide and visibilitychange handlers are run before the new page
+// runs (which is what happens on other same-site main frame navigations).
+struct OldPageInfo {
+ // |routing_id_for_old_main_frame| contains the routing ID of the old page's
+ // main RenderFrameHost.
+ int32 routing_id_for_old_main_frame = -1;
+ // |new_lifecycle_state_for_old_page| contains the latest PageLifecycleState
+ // of the old page to ensure the PageVisibilityState gets properly updated,
+ // the "persisted" property of the pagehide event is set correctly, and
+ // pagehide and visibilitychange events won't get dispatched again when we
+ // unload/freeze the page later on.
+ blink.mojom.PageLifecycleState new_lifecycle_state_for_old_page;
+};
+
+// AppHistoryEntry contains a subset of a session history item that is used by
+// the appHistory API to represent a non-current history entry. The browser
+// ensures that an AppHistoryEntry is only sent to the renderer if its |url| is
+// same-origin to the navigation being committed.
+struct AppHistoryEntry {
+ mojo_base.mojom.String16 key;
+ mojo_base.mojom.String16 id;
+ mojo_base.mojom.String16 url;
+};
+
+// Used by commit IPC messages. Holds the parameters needed by the renderer to
+// commit a navigation besides those in CommonNavigationParams.
+struct CommitNavigationParams {
+ // The origin to be used for committing the navigation, if specified.
+ // This will be an origin that's compatible with the |url| in the
+ // CommonNavigationParams; if |url| is data: or about:blank, or the frame has
+ // sandbox attributes, this determines the origin of the resulting document.
+ // It is specified for session history navigations, for which the origin is
+ // known and saved in the FrameNavigationEntry.
+ url.mojom.Origin? origin_to_commit;
+
+ // The storage key of the document that will be created by the navigation.
+ // This is compatible with the `origin_to_commit`. Until the browser will be
+ // able to compute the `origin_to_commit` in all cases
+ // (https://crbug.com/888079), this is actually just a provisional
+ // `storage_key`. The final storage key is computed by the document loader
+ // taking into account the origin computed by the renderer.
+ blink.mojom.StorageKey storage_key;
+
+ // The sandbox flags to apply to the new document. This is the union of:
+ // - the frame's current sandbox, taken when the navigation started.
+ // - the navigation response's CSP sandbox flags.
+ // - the result of CSP embedded enforcement required CSP sandbox flags.
+ // - Various edge cases: MHTML document, error pages, ...
+ // See content/browser/renderer_host/sandbox_flags.md
+ network.mojom.WebSandboxFlags sandbox_flags =
+ network.mojom.WebSandboxFlags.kAll;
+
+ // Whether or not the user agent override string should be used.
+ bool is_overriding_user_agent = false;
+
+ // Any redirect URLs that occurred before |url|. Useful for cross-process
+ // navigations; defaults to empty.
+ array<url.mojom.Url> redirects;
+
+ // The ResourceResponseInfos received during redirects.
+ array<network.mojom.URLResponseHead> redirect_response;
+
+ // The RedirectInfos received during redirects.
+ array<network.mojom.URLRequestRedirectInfo> redirect_infos;
+
+ // The content type from the request headers for POST requests.
+ string post_content_type;
+
+ // The original URL & method for this navigation.
+ url.mojom.Url original_url;
+ string original_method;
+
+ // Whether or not this url should be allowed to access local file://
+ // resources.
+ bool can_load_local_resources = false;
+
+ // Encoded version of blink::PageState, opaque history state (received by
+ // UpdateState Mojo message).
+ string page_state;
+
+ // For browser-initiated navigations, this is the unique id of the
+ // NavigationEntry being navigated to. (For renderer-initiated navigations it
+ // is 0.) If the load succeeds, then this nav_entry_id will be reflected in
+ // the resulting DidCommitProvisionalLoadParams.
+ int32 nav_entry_id = 0;
+
+ // If this is a history navigation, this contains a map of frame unique names
+ // to |is_about_blank| for immediate children of the frame being navigated for
+ // which there are history items. The renderer process only needs to check
+ // with the browser process for newly created subframes that have these unique
+ // names (and only when not staying on about:blank).
+ // TODO(creis): Expand this to a data structure including corresponding
+ // same-process PageStates for the whole subtree in https://crbug.com/639842.
+ map<string, bool> subframe_unique_names;
+
+ // For browser-initiated navigations, this is true if this is a new entry
+ // being navigated to. This is false otherwise. TODO(avi): Remove this when
+ // the pending entry situation is made sane and the browser keeps them around
+ // long enough to match them via nav_entry_id, above.
+ bool intended_as_new_entry = false;
+
+ // For history navigations, this is the offset in the history list of the
+ // pending load. For non-history navigations, this will be ignored.
+ int32 pending_history_list_offset = -1;
+
+ // Where its current page contents reside in session history and the total
+ // size of the session history list.
+ int32 current_history_list_offset = -1;
+ int32 current_history_list_length = 0;
+
+ // Indicates that the tab was previously discarded.
+ // wasDiscarded is exposed on Document after discard, see:
+ // https://github.com/WICG/web-lifecycle
+ bool was_discarded = false;
+
+ // Indicates whether the navigation is to a view-source:// scheme or not.
+ // It is a separate boolean as the view-source scheme is stripped from the
+ // URL before it is sent to the renderer process and the RenderFrame needs
+ // to be put in special view source mode.
+ bool is_view_source = false;
+
+ // Whether session history should be cleared. In that case, the RenderView
+ // needs to notify the browser that the clearing was successful when the
+ // navigation commits.
+ bool should_clear_history_list = false;
+
+ // Timing of navigation events.
+ NavigationTiming navigation_timing;
+
+ // The AppCache host id to be used to identify this navigation.
+ mojo_base.mojom.UnguessableToken? appcache_host_id;
+
+ // Set to |kYes| if a navigation is following the rules of user activation
+ // propagation. This is different from |has_user_gesture|
+ // (in CommonNavigationParams) as the activation may have happened before
+ // the navigation was triggered, for example.
+ // In other words, the distinction isn't regarding user activation and user
+ // gesture but whether there was an activation prior to the navigation or to
+ // start it. `was_activated` will answer the former question while
+ // `user_gesture` will answer the latter.
+ blink.mojom.WasActivatedOption was_activated = kUnknown;
+
+ // A token that should be passed to the browser process in
+ // DidCommitProvisionalLoadParams.
+ // TODO(clamy): Remove this once NavigationClient has shipped and
+ // same-document browser-initiated navigations are properly handled as well.
+ mojo_base.mojom.UnguessableToken navigation_token;
+
+ // Prefetched signed exchanges. Used when SignedExchangeSubresourcePrefetch
+ // feature is enabled.
+ array<blink.mojom.PrefetchedSignedExchangeInfo> prefetched_signed_exchanges;
+
+ // The real content of the data: URL. Only used in Android WebView for
+ // implementing LoadDataWithBaseUrl API method to circumvent the restriction
+ // on the GURL max length in the IPC layer. Short data: URLs can still be
+ // passed in the |CommonNavigationParams::url| field.
+ [EnableIf=is_android]
+ string data_url_as_string;
+
+ // Whether this navigation was browser initiated.
+ bool is_browser_initiated = false;
+
+ // The physical URL of Web Bundle from which the document is loaded.
+ // Used as an additional identifier for MemoryCache.
+ url.mojom.Url web_bundle_physical_url;
+
+ // The claimed URL inside Web Bundle from which the document is loaded.
+ url.mojom.Url web_bundle_claimed_url;
+
+ // UKM source id to be associated with the Document that will be installed
+ // in the current frame. This could be an invalid id for empty Document. Only
+ // Documents that will emit UKM events need valid ids.
+ int64 document_ukm_source_id;
+
+ // A snapshot value of frame policy (both sandbox flags and container policy)
+ // of the frame that is being navigated. The snapshot value is captured at the
+ // start of navigation:
+ // - For local frame navigation, the value is set at NavigationRequest::
+ // CreateRendererInitiated.
+ // - For remote frame navigation, the value is set at
+ // NavigationControllerImpl::CreateNavigationRequestFromLoadParams.
+ // - For navigation created from
+ // NavigationControllerImpl::CreateNavigationRequestFromEntry which
+ // corresponds to history navigation, the value is set to current
+ // FrameTreeNode::pending_frame_policy in frame_tree_node. This behavior is
+ // currently undocumented and probably need further discussion. Another
+ // potential approach is to record frame policy value in NavigationEntry and
+ // reuse the historical value.
+ //
+ // The default FramePolicy is the laxest. It is used for:
+ // - Top-level browser-initiated navigations.
+ // - Ctrl+click navigation (opening a link in a new tab).
+ blink.mojom.FramePolicy frame_policy;
+
+ // The names of origin trials to be force enabled for this navigation.
+ array<string> force_enabled_origin_trials;
+
+ // Whether the page is in an origin-keyed agent cluster.
+ // https://html.spec.whatwg.org/C/#origin-keyed-agent-clusters
+ bool origin_agent_cluster = false;
+
+ // Client-hints enabled; this is based on the top-level frame and should be
+ // further narrowed down by permissions policy.
+ array<network.mojom.WebClientHintsType> enabled_client_hints;
+
+ // Whether this is a cross-site navigation that swaps BrowsingContextGroups.
+ bool is_cross_site_cross_browsing_context_group = false;
+
+ // Should only be set to a valid value for main-frame same-site navigations
+ // where we did a proactive BrowsingInstance swap and we're reusing the old
+ // page's process.
+ OldPageInfo? old_page_info;
+
+ // The HTTP response status code for the navigation. Set to -1 if we never
+ // received response headers.
+ int32 http_response_code = -1;
+
+ // A same-origin subset of the back/forward list exposed by the appHistory
+ // API.
+ array<AppHistoryEntry> app_history_back_entries;
+ array<AppHistoryEntry> app_history_forward_entries;
+
+ array<url.mojom.Url> early_hints_preloaded_resources;
+};
diff --git a/chromium/third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom b/chromium/third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom
new file mode 100644
index 00000000000..19dd4587c92
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "mojo/public/mojom/base/byte_string.mojom";
+import "services/network/public/mojom/url_loader_factory.mojom";
+import "services/network/public/mojom/url_loader.mojom";
+import "services/network/public/mojom/url_response_head.mojom";
+import "url/mojom/url.mojom";
+
+struct SHA256HashValue {
+ mojo_base.mojom.ByteString data;
+};
+
+// Used for SignedExchangeSubresourcePrefetch.
+// This struct keeps the information about a prefetched signed exchange. It is
+// used in CommitNavigationParams to be passed from the browser process to the
+// renderer process in CommitNavigation IPC.
+struct PrefetchedSignedExchangeInfo {
+ url.mojom.Url outer_url;
+ SHA256HashValue header_integrity;
+ url.mojom.Url inner_url;
+ network.mojom.URLResponseHead inner_response;
+ pending_remote<network.mojom.URLLoaderFactory> loader_factory_handle;
+};
diff --git a/chromium/third_party/blink/public/mojom/navigation/was_activated_option.mojom b/chromium/third_party/blink/public/mojom/navigation/was_activated_option.mojom
new file mode 100644
index 00000000000..f9a00640f3f
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/navigation/was_activated_option.mojom
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+// Whether the navigation should propagate user activation. This can be
+// specified by embedders in NavigationController::LoadURLParams.
+enum WasActivatedOption {
+ // The content layer should make a decision about whether to propagate user
+ // activation.
+ kUnknown,
+
+ // The navigation should propagate user activation.
+ kYes,
+
+ // The navigation should not propagate user activation.
+ kNo,
+};
diff --git a/chromium/third_party/blink/public/mojom/optimization_guide/DIR_METADATA b/chromium/third_party/blink/public/mojom/optimization_guide/DIR_METADATA
deleted file mode 100644
index f2192142409..00000000000
--- a/chromium/third_party/blink/public/mojom/optimization_guide/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>OptimizationGuide"
-}
diff --git a/chromium/third_party/blink/public/mojom/optimization_guide/OWNERS b/chromium/third_party/blink/public/mojom/optimization_guide/OWNERS
deleted file mode 100644
index 472244d4021..00000000000
--- a/chromium/third_party/blink/public/mojom/optimization_guide/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-dom@chromium.org
-falken@chromium.org
-kinuko@chromium.org
-nhiroki@chromium.org
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom b/chromium/third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom
deleted file mode 100644
index fa5a7d4bb69..00000000000
--- a/chromium/third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-// Enumerates the milestones at which execution of async scripts can be delayed
-// until.
-enum DelayAsyncScriptExecutionDelayType {
- // No delay (default behavior).
- kUnknown,
-
- // Delay until parse finish.
- kFinishedParsing,
-
- // Delay until first paint or parse finish (first win).
- kFirstPaintOrFinishedParsing,
-};
-
-// Hints for delay async script execution optimization.
-struct DelayAsyncScriptExecutionHints {
- DelayAsyncScriptExecutionDelayType delay_type;
-};
-
-// Enumerates the milestones at which competing low priority requests can be
-// delayed until.
-enum DelayCompetingLowPriorityRequestsDelayType {
- // No delay (default behavior).
- kUnknown,
-
- // Delay until first paint.
- kFirstPaint,
-
- // Delay until first contentful paint.
- kFirstContentfulPaint,
-};
-
-// Enumerates the different request priorities that the resource scheduler will
-// consider "important". For example, low priority requests will be queued
-// behind in-flight medium priority requests, when the threshold is kMedium,
-// etc.
-enum DelayCompetingLowPriorityRequestsPriorityThreshold {
- kUnknown,
- kMedium,
- kHigh,
-};
-
-// Hints for delay competing low priority requests optimization.
-struct DelayCompetingLowPriorityRequestsHints {
- DelayCompetingLowPriorityRequestsDelayType delay_type;
- DelayCompetingLowPriorityRequestsPriorityThreshold priority_threshold;
-};
-
-// The set of optimization hints for Blink provided by the optimization guide
-// service in the browser process.
-//
-// Each hint is optional as only a part of them might be populated.
-struct BlinkOptimizationGuideHints {
- DelayAsyncScriptExecutionHints? delay_async_script_execution_hints;
- DelayCompetingLowPriorityRequestsHints?
- delay_competing_low_priority_requests_hints;
-};
diff --git a/chromium/third_party/blink/public/mojom/page/page.mojom b/chromium/third_party/blink/public/mojom/page/page.mojom
index e122d4ffb85..df834821bd0 100644
--- a/chromium/third_party/blink/public/mojom/page/page.mojom
+++ b/chromium/third_party/blink/public/mojom/page/page.mojom
@@ -4,6 +4,7 @@
module blink.mojom;
import "mojo/public/mojom/base/time.mojom";
+import "skia/public/mojom/skcolor.mojom";
import "third_party/blink/public/mojom/page/page_visibility_state.mojom";
import "third_party/blink/public/mojom/webpreferences/web_preferences.mojom";
import "third_party/blink/public/mojom/renderer_preferences.mojom";
@@ -61,6 +62,20 @@ interface PageBroadcast {
// Notifies the renderer when audio is started or stopped.
AudioStateChanged(bool is_audio_playing);
+ // Notifies the renderer when a prerendered page is activated. The renderer
+ // is expected to update `document.prerendering` and dispatch the
+ // prerenderingchange event on relevant documents.
+ //
+ // `activation_start` is when the activation navigation started for use in
+ // PerformanceNavigationTiming. It is 0 if this blink::WebViewImpl does not
+ // host the main frame, to avoid sending the data cross-origin.
+ //
+ // The renderer calls the callback once all documents in the
+ // blink::WebViewImpl finished activating.
+ //
+ // TODO(falken): Move this to SetPageLifecycleState.
+ ActivatePrerenderedPage(mojo_base.mojom.TimeTicks activation_start) => ();
+
// Notifies renderers when a portal web contents is activated or if a
// web contents is adopted as a portal.
SetInsidePortal(bool is_inside_portal);
@@ -73,4 +88,7 @@ interface PageBroadcast {
// Set history offset and length.
SetHistoryOffsetAndLength(int32 offset, int32 length);
+
+ // Sent to whole page, but should only be used by the main frame.
+ SetPageBaseBackgroundColor(skia.mojom.SkColor? color);
};
diff --git a/chromium/third_party/blink/public/mojom/page/widget.mojom b/chromium/third_party/blink/public/mojom/page/widget.mojom
index a512423287d..a7cb9f64bbe 100644
--- a/chromium/third_party/blink/public/mojom/page/widget.mojom
+++ b/chromium/third_party/blink/public/mojom/page/widget.mojom
@@ -13,6 +13,7 @@ import "services/viz/public/mojom/compositing/compositor_frame_sink.mojom";
import "services/viz/public/mojom/compositing/local_surface_id.mojom";
import "services/viz/public/mojom/hit_test/input_target_client.mojom";
import "skia/public/mojom/bitmap.mojom";
+import "skia/public/mojom/skcolor.mojom";
import "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom";
import "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom";
import "third_party/blink/public/mojom/input/input_handler.mojom";
@@ -183,10 +184,6 @@ interface FrameWidgetHost {
// Sent by a widget to the browser to notify the end of the autoscroll.
AutoscrollEnd();
- // Sent once a paint happens after the first non empty layout. In other words,
- // after the frame widget has painted something.
- DidFirstVisuallyNonEmptyPaint();
-
// Used to tell the browser the user started dragging in the content area.
// |drag_data| contains contextual information about the pieces of the page
// the user dragged. The browser uses this notification to initiate a drag
@@ -245,6 +242,13 @@ interface WidgetHost {
UpdateTooltipUnderCursor(mojo_base.mojom.String16 tooltip_text,
mojo_base.mojom.TextDirection text_direction_hint);
+ // Sent by a widget to the browser to set the tooltip text and trigger a
+ // tooltip to show up, aligned with the bounds (in widget-relative DIPS)
+ // passed by parameter. An empty |tooltip_text| will hide the tooltip view.
+ UpdateTooltipFromKeyboard(mojo_base.mojom.String16 tooltip_text,
+ mojo_base.mojom.TextDirection text_direction_hint,
+ gfx.mojom.Rect bounds);
+
// Sent when the text input state is changed. This usually happens when
// a text input entry is focused.
TextInputStateChanged(ui.mojom.TextInputState state);
diff --git a/chromium/third_party/blink/public/mojom/payments/OWNERS b/chromium/third_party/blink/public/mojom/payments/OWNERS
index 65c11cbe213..cb9f41d5363 100644
--- a/chromium/third_party/blink/public/mojom/payments/OWNERS
+++ b/chromium/third_party/blink/public/mojom/payments/OWNERS
@@ -1,12 +1,8 @@
-
file://components/payments/OWNERS
jinho.bang@samsung.com
-mek@chromium.org
rouslan@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
-# Emeritus
-mathp@chromium.org
diff --git a/chromium/third_party/blink/public/mojom/payments/payment_credential.mojom b/chromium/third_party/blink/public/mojom/payments/payment_credential.mojom
index c33874ca19f..4acd42af616 100644
--- a/chromium/third_party/blink/public/mojom/payments/payment_credential.mojom
+++ b/chromium/third_party/blink/public/mojom/payments/payment_credential.mojom
@@ -21,13 +21,18 @@ struct PaymentCredentialInstrument {
// Friendly name for displaying this instrument to the user.
string display_name;
- // URL for an icon to display alongside the display_name.
+ // URL for an icon to display alongside the display_name. The URL is secure,
+ // not required to share the same origin with the current page.
url.mojom.Url icon;
};
-// An interface for storing PaymentCredentials in browser local storage. It is
-// implemented in the browser process and called by the renderer before and
-// after creation of a PaymentCredential through the Credential Management API.
+// A per-frame interface restricted to secure contexts for storing
+// PaymentCredentials in browser local storage. It is implemented in the
+// browser process and called by the renderer before and after creation of a
+// PaymentCredential through the Credential Management API. While a renderer
+// can request multiple instances of PaymentCredential for one frame, the
+// browser is responsible for choosing to show UI for one of these at any given
+// time per WebContents (on desktop) or window/app (on Android).
interface PaymentCredential {
// Download and save in-memory the instrument icon from |instrument.icon| URL
diff --git a/chromium/third_party/blink/public/mojom/payments/payment_request.mojom b/chromium/third_party/blink/public/mojom/payments/payment_request.mojom
index 0935f62ffba..06437dd52be 100644
--- a/chromium/third_party/blink/public/mojom/payments/payment_request.mojom
+++ b/chromium/third_party/blink/public/mojom/payments/payment_request.mojom
@@ -7,7 +7,9 @@ module payments.mojom;
import "components/payments/mojom/payment_request_data.mojom";
import "mojo/public/mojom/base/time.mojom";
+import "third_party/blink/public/mojom/payments/payment_credential.mojom";
import "url/mojom/url.mojom";
+import "third_party/blink/public/mojom/webauthn/authenticator.mojom";
struct PaymentResponse {
string method_name;
@@ -25,6 +27,16 @@ struct PaymentResponse {
PaymentAddress? shipping_address;
string? shipping_option;
PayerDetail payer;
+
+ SecurePaymentConfirmationResponse? secure_payment_confirmation;
+};
+
+// A response for the "secure-payment-confirmation" payment method. A subset of
+// blink.mojom.GetAssertionAuthenticatorResponse.
+struct SecurePaymentConfirmationResponse {
+ blink.mojom.CommonCredentialInfo credential_info;
+ array<uint8> signature;
+ array<uint8>? user_handle;
};
struct PayerDetail {
@@ -40,6 +52,7 @@ enum PaymentErrorReason {
NOT_SUPPORTED_FOR_INVALID_ORIGIN_OR_SSL,
ALREADY_SHOWING,
INVALID_DATA_FROM_RENDERER,
+ NOT_ALLOWED_ERROR,
};
enum CanMakePaymentQueryResult {
@@ -146,7 +159,11 @@ struct SecurePaymentConfirmationRequest {
// An indefinite-length blob passed from the relying party server, to be sent
// to an authenticator for signing together with the price and merchant
// origin.
- array<uint8> network_data;
+ array<uint8> challenge;
+
+ // The name and icon to display to the user and to be sent to the authenticator
+ // device for signing.
+ PaymentCredentialInstrument instrument;
// Time to wait for an authenticator to complete an operation provided by the
// relying party.
diff --git a/chromium/third_party/blink/public/mojom/performance_manager/v8_detailed_memory_reporter.mojom b/chromium/third_party/blink/public/mojom/performance_manager/v8_detailed_memory_reporter.mojom
index 6b4578f7235..c7e10cbe44b 100644
--- a/chromium/third_party/blink/public/mojom/performance_manager/v8_detailed_memory_reporter.mojom
+++ b/chromium/third_party/blink/public/mojom/performance_manager/v8_detailed_memory_reporter.mojom
@@ -19,6 +19,11 @@ struct PerContextV8MemoryUsage {
string? url;
};
+struct PerContextCanvasMemoryUsage {
+ ExecutionContextToken token;
+ uint64 bytes_used = 0;
+};
+
struct PerIsolateV8MemoryUsage {
// The number of V8 contexts not associated with an execution context,
// likely web application leaks, and their associated byte usage.
@@ -33,8 +38,11 @@ struct PerIsolateV8MemoryUsage {
// Bytes used on the Blink heap corresponding to this V8 isolate.
uint64 blink_bytes_used;
- // The V8 memory usage by individual V8 contexts in this process.
+ // The V8 memory usage by individual execution contexts in this process.
array<PerContextV8MemoryUsage> contexts;
+ // The memory used by canvas elements in individual execution contexts in
+ // this process.
+ array<PerContextCanvasMemoryUsage> canvas_contexts;
};
struct PerProcessV8MemoryUsage {
diff --git a/chromium/third_party/blink/public/mojom/permissions_policy/PRESUBMIT.py b/chromium/third_party/blink/public/mojom/permissions_policy/PRESUBMIT.py
index bb12c57d904..fcd468353ff 100644
--- a/chromium/third_party/blink/public/mojom/permissions_policy/PRESUBMIT.py
+++ b/chromium/third_party/blink/public/mojom/permissions_policy/PRESUBMIT.py
@@ -10,6 +10,9 @@ for more details about the presubmit API built into gcl.
import os
+USE_PYTHON3 = True
+
+
def _dynamic_import(module_dir, module_name):
import sys
diff --git a/chromium/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom b/chromium/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
index 41de86ef01e..78bf048623a 100644
--- a/chromium/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
+++ b/chromium/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
@@ -123,7 +123,7 @@ enum PermissionsPolicyFeature {
// Controls use of WebOTP API.
kOTPCredentials = 80,
- // Controls access to getDisplayMedia() and getCurrentBrowsingContextMedia().
+ // Controls access to screen capture via getDisplayMedia().
kDisplayCapture = 81,
// Controls the access to the interest cohort as well as the eligibility for
@@ -144,6 +144,23 @@ enum PermissionsPolicyFeature {
// Controls use of Multi-Screen Window Placement API.
kWindowPlacement = 86,
+ kClientHintUABitness = 87,
+
+ // Client hint for indicating that the User-Agent header contains the reduced
+ // user agent string.
+ //
+ // The `Sec-CH-UA-Reduced` header field is a temporary client hint, which
+ // will only be sent in the presence of a valid Origin Trial token. It was
+ // introduced to enable safely experimenting with sending a reduced user
+ // agent string in the `User-Agent` header.
+ //
+ // See https://www.chromestatus.com/feature/5704553745874944 for the
+ // User-Agent reduction Chrome feature and the design doc
+ // https://docs.google.com/document/d/1feIxK9S7oNgT2oGGebbxE9X0O-4wTKcsP_gRaY99tq4
+ // for details on the use of Client Hints guarded by an Origin Trial to
+ // enable experimenting with the reduced user agent string.
+ kClientHintUAReduced = 88,
+
// Don't change assigned numbers of any item, and don't reuse removed slots.
// Add new features at the end of the enum.
// Also, run update_permissions_policy_enum.py in
diff --git a/chromium/third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom b/chromium/third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom
index f4aae0178d5..b4f017d4829 100644
--- a/chromium/third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom
+++ b/chromium/third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom
@@ -28,7 +28,7 @@ interface PictureInPictureSession {
// This call cannot happen after `Stop()`.
Update(uint32 player_id,
pending_associated_remote<media.mojom.MediaPlayer> player_remote,
- viz.mojom.SurfaceId? surface_id,
+ viz.mojom.SurfaceId surface_id,
gfx.mojom.Size natural_size,
bool show_play_pause_button);
@@ -40,9 +40,14 @@ interface PictureInPictureSession {
// PictureInPictureService is a Document-associated interface that lives in
// the browser process. It is responsible for implementing the browser-side
// support for https://wicg.github.io/picture-in-picture and manages all
-// picture-in-picture interactions for Document. Picture-in-picture allows
+// picture-in-picture interactions for Document. Picture-in-Picture allows
// a Document to display a video in an always-on-top floating window with
// basic playback functionality (e.g. play and pause).
+// The window provides playback control by translating user actions into
+// media.mojom.MediaPlayer messages. The MediaPlayer remote can be reset by the
+// renderer even while the Picute-in-Picture session is active, indicating that
+// the media player is gone. A new MediaPlayer remote can be provided later by
+// an Update() message to the PictureInPictureSession object.
interface PictureInPictureService {
// Notify the service that it should start a Picture-in-Picture session. If a
// Picture-in-Picture session is already running, it will be closed.
@@ -61,7 +66,7 @@ interface PictureInPictureService {
StartSession(
uint32 player_id,
pending_associated_remote<media.mojom.MediaPlayer> player_remote,
- viz.mojom.SurfaceId? surface_id,
+ viz.mojom.SurfaceId surface_id,
gfx.mojom.Size natural_size,
bool show_play_pause_button,
pending_remote<PictureInPictureSessionObserver> observer)
diff --git a/chromium/third_party/blink/public/mojom/prerender/prerender.mojom b/chromium/third_party/blink/public/mojom/prerender/prerender.mojom
index d4a2268d8e2..3ad4ac257b5 100644
--- a/chromium/third_party/blink/public/mojom/prerender/prerender.mojom
+++ b/chromium/third_party/blink/public/mojom/prerender/prerender.mojom
@@ -14,6 +14,9 @@ enum PrerenderTriggerType {
// https://html.spec.whatwg.org/C/#link-type-next
kLinkRelNext,
+
+ // https://jeremyroman.github.io/alternate-loading-modes/#speculation-rules
+ kSpeculationRule,
};
struct PrerenderAttributes {
@@ -38,22 +41,3 @@ interface NoStatePrefetchProcessor {
// etc. This must be called after Start().
Cancel();
};
-
-// Prerender2 (https://crbug.com/1132746):
-// This interface is used only when blink::features::kPrerender2 is enabled.
-//
-// This interface is used to request prerendering from a renderer process to the
-// browser process. This is created per prerender request, for example, when a
-// new <link rel=prerender> element is added, when the element's href is
-// changed, etc.
-interface PrerenderProcessor {
- // Requests the browesr process to start prerendering with
- // |prerender_attribute|. This must be called only one time before any other
- // functions.
- Start(PrerenderAttributes prerender_attribute);
-
- // Cancels the ongoing prerendering. This is supposed to be called when the
- // <link rel=prerender> element is removed, the element's href is changed,
- // etc. This must be called after Start().
- Cancel();
-};
diff --git a/chromium/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom b/chromium/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom
deleted file mode 100644
index 92ba0dd017c..00000000000
--- a/chromium/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-import "ui/display/mojom/display.mojom";
-
-// A struct containing information about the set of connected displays.
-struct Displays {
- array<display.mojom.Display> displays; // The list of connected displays.
- int64 internal_id; // The internal display id or kInvalidDisplayId if none.
- int64 primary_id; // The primary display id or kInvalidDisplayId if none.
-};
-
-// An enum representing the presence of multiple displays, or an error state.
-enum MultipleDisplays {
- kFalse, // 0 or 1 displays are connected.
- kTrue, // 2 or more displays are connected.
- kError, // The display count is unavailable or access is denied.
-};
-
-// An interface enabling renderers to request information about screens
-// connected to the device from the browser process.
-interface ScreenEnumeration {
- // Returns information about the connected displays, or null if an error
- // occurred (e.g. display information is unavailable or access is denied).
- GetDisplays() => (Displays? result);
-
- // Returns information about the presence of multiple displays.
- HasMultipleDisplays() => (MultipleDisplays result);
-};
diff --git a/chromium/third_party/blink/public/mojom/insecure_input/OWNERS b/chromium/third_party/blink/public/mojom/shared_storage/OWNERS
index 08850f42120..08850f42120 100644
--- a/chromium/third_party/blink/public/mojom/insecure_input/OWNERS
+++ b/chromium/third_party/blink/public/mojom/shared_storage/OWNERS
diff --git a/chromium/third_party/blink/public/mojom/shared_storage/shared_storage.mojom b/chromium/third_party/blink/public/mojom/shared_storage/shared_storage.mojom
new file mode 100644
index 00000000000..4374d387b37
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/shared_storage/shared_storage.mojom
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "url/mojom/url.mojom";
+
+// SharedStorage is an origin-keyed storage mechanism where the output is
+// carefully guarded to mitigate the risk of cross-site correlation.
+// See https://github.com/pythagoraskitty/shared-storage/blob/main/README.md
+//
+// Implemented by the browser and exposed to the renderer process on a per-frame
+// basis, to allow accessing the shared storage and initiating worklet
+// operations, etc.
+interface SharedStorageDocumentService {};
diff --git a/chromium/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom b/chromium/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom
index 8def7887565..b719e575087 100644
--- a/chromium/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom
+++ b/chromium/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom
@@ -4,6 +4,7 @@
module blink.mojom;
+import "third_party/blink/public/mojom/loader/referrer.mojom";
import "url/mojom/url.mojom";
// See also third_party/blink/renderer/core/speculation_rules/README.md.
@@ -30,8 +31,8 @@ enum SpeculationAction {
kPrerender,
};
-// A single candidate: a URL, an action, and any associated metadata that
-// might be needed to make a decision.
+// A single candidate: a URL, an action, a referrer, and any associated
+// metadata that might be needed to make a decision.
struct SpeculationCandidate {
// The URL which is eligible for some action.
url.mojom.Url url;
@@ -39,6 +40,9 @@ struct SpeculationCandidate {
// The action which is proposed for that URL.
SpeculationAction action = kPrefetch;
+ // The referrer to be used when fetching this candidate.
+ Referrer referrer;
+
// If true, cross-origin requests associated with this speculation must be
// made in a manner which anonymizes the client IP. If this is not possible,
// this candidate must be discarded.
diff --git a/chromium/third_party/blink/public/mojom/storage_key/DIR_METADATA b/chromium/third_party/blink/public/mojom/storage_key/DIR_METADATA
new file mode 100644
index 00000000000..27f133595b6
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/storage_key/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "Blink>Storage"
+}
+
+team_email: "storage-dev@chromium.org" \ No newline at end of file
diff --git a/chromium/third_party/blink/public/mojom/storage_key/OWNERS b/chromium/third_party/blink/public/mojom/storage_key/OWNERS
new file mode 100644
index 00000000000..df3b83aead2
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/storage_key/OWNERS
@@ -0,0 +1,4 @@
+file://storage/OWNERS
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/third_party/blink/public/mojom/storage_key/storage_key.mojom b/chromium/third_party/blink/public/mojom/storage_key/storage_key.mojom
new file mode 100644
index 00000000000..6c597baf667
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/storage_key/storage_key.mojom
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "mojo/public/mojom/base/unguessable_token.mojom";
+import "url/mojom/origin.mojom";
+
+// Represents a blink::StorageKey (third_party/blink/common/storage_key).
+struct StorageKey {
+ // The origin of the context using this storage key.
+ url.mojom.Origin origin;
+
+ // An optional nonce, forcing a partitioned storage from anything else. Used
+ // by anonymous iframes:
+ // https://github.com/camillelamy/explainers/blob/master/anonymous_iframes.md
+ mojo_base.mojom.UnguessableToken? nonce;
+};
diff --git a/chromium/third_party/blink/public/mojom/subapps/DIR_METADATA b/chromium/third_party/blink/public/mojom/subapps/DIR_METADATA
new file mode 100644
index 00000000000..7f1ffb86b99
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/subapps/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "UI>Browser>WebAppInstalls>Desktop"
+}
diff --git a/chromium/third_party/blink/public/mojom/subapps/OWNERS b/chromium/third_party/blink/public/mojom/subapps/OWNERS
new file mode 100644
index 00000000000..fe15913e172
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/subapps/OWNERS
@@ -0,0 +1,4 @@
+file://third_party/blink/renderer/modules/subapps/OWNERS
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/subapps/sub_apps_provider.mojom b/chromium/third_party/blink/public/mojom/subapps/sub_apps_provider.mojom
new file mode 100644
index 00000000000..350a72a2b78
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/subapps/sub_apps_provider.mojom
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+enum SubAppsProviderResult {
+ kSuccess,
+ kFailure,
+};
+
+// The browser process implements this interface and receives requests from
+// renderers to resolve calls to navigator.subApps.*. NOTE: This Mojo interface
+// is per-frame, there is one logical instance per frame, and it's main-frame
+// only.
+// Sub Apps APIs allow installed PWAs to install shortcuts to their various
+// sub-parts by means of installing the sub-component. Example: main app hosted
+// at https://office.org/ which provides a full set of office productivity tools
+// creates a new shortcut to itself with https://office.org/spreadsheet as the
+// install_url effectively adding the Spreadsheet app to the launcher surface.
+interface SubAppsProvider {
+ // Installs a sub app of an already installed app (which has the same origin).
+ Add() => (SubAppsProviderResult result);
+};
diff --git a/chromium/third_party/blink/public/mojom/tokens/BUILD.gn b/chromium/third_party/blink/public/mojom/tokens/BUILD.gn
index 38d35a7a9e9..c7f9a0d0ef8 100644
--- a/chromium/third_party/blink/public/mojom/tokens/BUILD.gn
+++ b/chromium/third_party/blink/public/mojom/tokens/BUILD.gn
@@ -83,6 +83,10 @@ mojom_component("tokens") {
mojom = "blink.mojom.V8ContextToken"
cpp = "::blink::V8ContextToken"
},
+ {
+ mojom = "blink.mojom.ClipboardSequenceNumberToken"
+ cpp = "::blink::ClipboardSequenceNumberToken"
+ },
]
traits_headers = [
"//third_party/blink/public/common/tokens/token_mojom_traits_helper.h",
diff --git a/chromium/third_party/blink/public/mojom/tokens/tokens.mojom b/chromium/third_party/blink/public/mojom/tokens/tokens.mojom
index 6db6fbb35f9..9a0d9e9cc4b 100644
--- a/chromium/third_party/blink/public/mojom/tokens/tokens.mojom
+++ b/chromium/third_party/blink/public/mojom/tokens/tokens.mojom
@@ -106,3 +106,7 @@ struct PortalToken {
struct V8ContextToken {
mojo_base.mojom.UnguessableToken value;
};
+
+struct ClipboardSequenceNumberToken {
+ mojo_base.mojom.UnguessableToken value;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/public/mojom/use_counter/PRESUBMIT.py b/chromium/third_party/blink/public/mojom/use_counter/PRESUBMIT.py
index 4fbecf309c0..a662d3436ae 100644
--- a/chromium/third_party/blink/public/mojom/use_counter/PRESUBMIT.py
+++ b/chromium/third_party/blink/public/mojom/use_counter/PRESUBMIT.py
@@ -14,6 +14,9 @@ user.
import sys
+USE_PYTHON3 = True
+
+
def _RunUmaHistogramChecks(input_api, output_api):
original_sys_path = sys.path
try:
diff --git a/chromium/third_party/blink/public/mojom/use_counter/css_property_id.mojom b/chromium/third_party/blink/public/mojom/use_counter/css_property_id.mojom
index 4fd74c4ea4c..e265b63877c 100644
--- a/chromium/third_party/blink/public/mojom/use_counter/css_property_id.mojom
+++ b/chromium/third_party/blink/public/mojom/use_counter/css_property_id.mojom
@@ -747,6 +747,9 @@ enum CSSSampleId {
kBorderEndEndRadius = 694,
kAccentColor = 695,
kSizeAdjust = 696,
+ kContainerName = 697,
+ kContainerType = 698,
+ kContainer = 699,
// 1. Add new features above this line (don't change the assigned numbers of
// the existing items).
// 2. Run the src/tools/metrics/histograms/update_use_counter_css.py script
diff --git a/chromium/third_party/blink/public/mojom/use_counter/use_counter_feature.mojom b/chromium/third_party/blink/public/mojom/use_counter/use_counter_feature.mojom
index 2f5450326aa..e5378ae31b2 100644
--- a/chromium/third_party/blink/public/mojom/use_counter/use_counter_feature.mojom
+++ b/chromium/third_party/blink/public/mojom/use_counter/use_counter_feature.mojom
@@ -15,6 +15,10 @@ enum UseCounterFeatureType {
kAnimatedCssProperty,
// Blink.UseCounter.PermissionsPolicy.Violation.Enforce
kPermissionsPolicyViolationEnforce,
+ // Blink.UseCounter.PermissionsPolicy.Allow
+ kPermissionsPolicyIframeAttribute,
+ // Blink.UseCounter.PermissionsPolicy.Header
+ kPermissionsPolicyHeader,
};
// This struct corresponds to `blink::UseCounterFeature`.
diff --git a/chromium/third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom b/chromium/third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom
index 42f1af73842..d92f5c5d3ec 100644
--- a/chromium/third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom
+++ b/chromium/third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom
@@ -20,6 +20,7 @@ struct UserAgentMetadata {
string architecture;
string model;
bool mobile;
+ string bitness;
};
// See UserAgentOverride in
diff --git a/chromium/third_party/blink/public/mojom/web_feature/PRESUBMIT.py b/chromium/third_party/blink/public/mojom/web_feature/PRESUBMIT.py
index 05538def4d3..3e18b11a0b5 100644
--- a/chromium/third_party/blink/public/mojom/web_feature/PRESUBMIT.py
+++ b/chromium/third_party/blink/public/mojom/web_feature/PRESUBMIT.py
@@ -7,6 +7,8 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""
+USE_PYTHON3 = True
+
def _RunUmaHistogramChecks(input_api, output_api): # pylint: disable=C0103
import sys
diff --git a/chromium/third_party/blink/public/mojom/web_feature/web_feature.mojom b/chromium/third_party/blink/public/mojom/web_feature/web_feature.mojom
index fc37817eb0b..ca6fae9a49e 100644
--- a/chromium/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/chromium/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -259,7 +259,7 @@ enum WebFeature {
kFormsSubmitted = 442,
kOBSOLETE_HTMLImports = 455,
kOBSOLETE_ElementCreateShadowRoot = 456,
- kDocumentRegisterElement = 457,
+ kOBSOLETE_DocumentRegisterElement = 457,
kEditingAppleInterchangeNewline = 458,
kEditingAppleConvertedSpace = 459,
kEditingApplePasteAsQuotation = 460,
@@ -2498,10 +2498,10 @@ enum WebFeature {
kBreakIteratorTypeLine = 3177,
kV8FileSystemDirectoryHandle_Resolve_Method = 3178,
kV8FileSystemHandle_IsSameEntry_Method = 3179,
- kV8RTCRtpSender_CreateEncodedAudioStreams_Method = 3180,
- kV8RTCRtpSender_CreateEncodedVideoStreams_Method = 3181,
- kV8RTCRtpReceiver_CreateEncodedAudioStreams_Method = 3182,
- kV8RTCRtpReceiver_CreateEncodedVideoStreams_Method = 3183,
+ kOBSOLETEV8RTCRtpSender_CreateEncodedAudioStreams_Method = 3180,
+ kOBSOLETEV8RTCRtpSender_CreateEncodedVideoStreams_Method = 3181,
+ kOBSOLETEV8RTCRtpReceiver_CreateEncodedAudioStreams_Method = 3182,
+ kOBSOLETEV8RTCRtpReceiver_CreateEncodedVideoStreams_Method = 3183,
kQuicTransport = 3184,
kQuicTransportStreamApis = 3185,
kQuicTransportDatagramApis = 3186,
@@ -2604,8 +2604,8 @@ enum WebFeature {
kFlexRowGapPercentIndefinite = 3291,
kV8RTCRtpSender_CreateEncodedStreams_Method = 3292,
kV8RTCRtpReceiver_CreateEncodedStreams_Method = 3293,
- kForceEncodedAudioInsertableStreams = 3294,
- kForceEncodedVideoInsertableStreams = 3295,
+ kOBSOLETEForceEncodedAudioInsertableStreams = 3294,
+ kOBSOLETEForceEncodedVideoInsertableStreams = 3295,
kTransformStyleContainingBlockComputedUsedMismatch = 3296,
kOBSOLETE_AdditionalGroupingPropertiesForCompat = 3297,
kPopupDoesNotExceedOwnerWindowBounds = 3298,
@@ -2626,8 +2626,6 @@ enum WebFeature {
kRubyTextWithNonDefaultTextAlign = 3313,
kHTMLMetaElementReferrerPolicyOutsideHead = 3314,
kHTMLMetaElementReferrerPolicyMultipleTokens = 3315,
- kDynamicImportModuleScriptRelativeClassicSameOrigin = 3318,
- kDynamicImportModuleScriptRelativeClassicCrossOrigin = 3319,
kV8WasmBulkMemory = 3320,
kV8WasmRefTypes = 3321,
kV8WasmMultiValue = 3322,
@@ -2694,9 +2692,9 @@ enum WebFeature {
kV8FontManager_Query_Method = 3386,
kAudioContextBaseLatency = 3387,
kV8Window_GetScreens_Method = 3388,
- kV8Window_IsMultiScreen_Method = 3389,
- kV8Window_Onscreenschange_AttributeGetter = 3390,
- kV8Window_Onscreenschange_AttributeSetter = 3391,
+ kOBSOLETE_V8Window_IsMultiScreen_Method = 3389,
+ kOBSOLETE_V8Window_Onscreenschange_AttributeGetter = 3390,
+ kOBSOLETE_V8Window_Onscreenschange_AttributeSetter = 3391,
kDOMWindowOpenPositioningFeaturesCrossScreen = 3392,
kDOMWindowSetWindowRectCrossScreen = 3393,
kFullscreenCrossScreen = 3394,
@@ -2711,8 +2709,8 @@ enum WebFeature {
kOBSOLETE_BluetoothRemoteGATTDescriptor_Uuid = 3403,
kOBSOLETE_BluetoothRemoteGATTService_Uuid = 3404,
kGPUAdapter_Name = 3405,
- kWindowScreenInternal = 3406,
- kWindowScreenPrimary = 3407,
+ kOBSOLETE_WindowScreenInternal = 3406,
+ kOBSOLETE_WindowScreenPrimary = 3407,
kThirdPartyCookieRead = 3408,
kThirdPartyCookieWrite = 3409,
kRTCLegacyRtpDataChannelNegotiated = 3410,
@@ -2807,7 +2805,7 @@ enum WebFeature {
kV8Document_ElementsFromPoint_Method = 3501,
kV8ShadowRoot_ElementFromPoint_Method = 3502,
kV8ShadowRoot_ElementsFromPoint_Method = 3503,
- kWindowScreenTouchSupport = 3504,
+ kOBSOLETE_WindowScreenTouchSupport = 3504,
kIdentifiabilityStudyReserved3505 = 3505,
kIdentifiabilityStudyReserved3506 = 3506,
kV8PushManager_SupportedContentEncodings_AttributeGetter = 3507,
@@ -2870,7 +2868,7 @@ enum WebFeature {
kIdentifiabilityStudyReserved3564 = 3564,
kIdentifiabilityStudyReserved3565 = 3565,
kV8BaseAudioContext_SampleRate_AttributeGetter = 3566,
- kWindowScreenId = 3567,
+ kOBSOLETE_WindowScreenId = 3567,
kWebGLRenderingContextGetParameter = 3568,
kWebGLRenderingContextGetRenderbufferParameter = 3569,
kWebGLRenderingContextGetShaderPrecisionFormat = 3570,
@@ -3019,12 +3017,12 @@ enum WebFeature {
kBarcodeDetectorDetect = 3711,
kFaceDetectorDetect = 3712,
kTextDetectorDetect = 3713,
- kLocalStorageFirstUsedBeforeFcp = 3714,
- kLocalStorageFirstUsedAfterFcp = 3715,
+ kOBSOLETE_LocalStorageFirstUsedBeforeFcp = 3714,
+ kOBSOLETE_LocalStorageFirstUsedAfterFcp = 3715,
kOBSOLETE_CSSPseudoHostCompoundList = 3716,
kOBSOLETE_CSSPseudoHostContextCompoundList = 3717,
kOBSOLETE_CSSPseudoHostDynamicSpecificity = 3718,
- kGetCurrentBrowsingContextMedia = 3719,
+ kOBSOLETE_GetCurrentBrowsingContextMedia = 3719,
kMouseEventRelativePositionForInlineElement = 3720,
kV8SharedArrayBufferConstructedWithoutIsolation = 3721,
kV8HTMLVideoElement_GetVideoPlaybackQuality_Method = 3722,
@@ -3101,8 +3099,8 @@ enum WebFeature {
kWindowScreenChange = 3790,
kXRWebGLDepthInformationTextureAttribute = 3791,
kXRWebGLBindingGetDepthInformation = 3792,
- kSessionStorageFirstUsedBeforeFcp = 3793,
- kSessionStorageFirstUsedAfterFcp = 3794,
+ kOBSOLETE_SessionStorageFirstUsedBeforeFcp = 3793,
+ kOBSOLETE_SessionStorageFirstUsedAfterFcp = 3794,
kGravitySensorConstructor = 3795,
kElementInternalsStates = 3796,
kWebPImage = 3797,
@@ -3124,7 +3122,7 @@ enum WebFeature {
kWebAppManifestCaptureLinks = 3813,
kSanitizerAPICreated = 3814,
kSanitizerAPIDefaultConfiguration = 3815,
- kSanitizerAPIToString = 3816,
+ kOBSOLETE_SanitizerAPIToString = 3816,
kSanitizerAPIToFragment = 3817,
kSanitizerAPIActionTaken = 3818,
kSanitizerAPIFromString = 3819,
@@ -3199,7 +3197,7 @@ enum WebFeature {
kWebAppManifestProtocolHandlers = 3884,
kRTCPeerConnectionOfferAllowExtmapMixedFalse = 3885,
kNewCanvas2DAPI = 3886,
- kServiceWorkerSubresourceFilter = 3887,
+ kServiceWorkerSubresourceFilterBypassedRequest = 3887,
kWebGPU = 3888,
kCSSFilterColorMatrix = 3889,
kHTMLFencedFrameElement = 3890,
@@ -3239,6 +3237,9 @@ enum WebFeature {
kFontFaceDescentOverride = 3924,
kFontFaceLineGapOverride = 3925,
kFontFaceSizeAdjust = 3926,
+ kHiddenBackfaceWith3D = 3927,
+ kMainFrameNonSecurePrivateAddressSpace = 3928,
+ kHTMLMediaElementControlsListNoPlaybackRate = 3930,
kDocumentTransition = 3931,
kSpeculationRules = 3932,
kV8AbortSignal_Abort_Method = 3933,
@@ -3251,6 +3252,40 @@ enum WebFeature {
kXRFrameFillPoses = 3940,
kWindowOpenNewPopupBehaviorMismatch = 3941,
kExplicitPointerCaptureClickTargetDiff = 3942,
+ kControlledNonBlobURLWorkerWillBeUncontrolled = 3943,
+ kMediaMetaThemeColor = 3944,
+ kClientHintsUABitness = 3945,
+ kDifferentPerspectiveCBOrParent = 3946,
+ kWebkitImageSet = 3947,
+ kRTCPeerConnectionWithBlockingCsp = 3948,
+ kSanitizerAPISanitizeFor = 3949,
+ kSanitizerAPIElementSetSanitized = 3950,
+ kTextShadowInHighlightPseudo = 3951,
+ kTextShadowNotNoneInHighlightPseudo = 3952,
+ kSameSiteNoneRequired = 3953,
+ kSameSiteNoneIncludedBySamePartyTopResource = 3954,
+ kSameSiteNoneIncludedBySamePartyAncestors = 3955,
+ kSameSiteNoneIncludedBySameSiteLax = 3956,
+ kSameSiteNoneIncludedBySameSiteStrict = 3957,
+ kPrivateNetworkAccessNonSecureContextsAllowedDeprecationTrial = 3958,
+ kV8URLPattern_Constructor = 3959,
+ kV8URLPattern_Test_Method = 3960,
+ kV8URLPattern_Exec_Method = 3961,
+ kSameSiteCookieInclusionChangedByCrossSiteRedirect = 3962,
+ kBlobStoreAccessAcrossAgentClustersInResolveAsURLLoaderFactory = 3963,
+ kBlobStoreAccessAcrossAgentClustersInResolveForNavigation = 3964,
+ kTapDelayEnabled = 3965,
+ kV8URLPattern_CompareComponent_Method = 3966,
+ kEarlyHintsPreload = 3967,
+ kClientHintsUAReduced = 3968,
+ kSpeculationRulesPrerender = 3969,
+ kExecCommandWithTrustedTypes = 3970,
+ kCSSSelectorPseudoHasInSnapshotProfile = 3971,
+ kCSSSelectorPseudoHasInLiveProfile = 3972,
+ kNavigatorPdfViewerEnabled = 3973,
+ kCanvasRenderingContext2DContextLostEvent = 3974,
+ kCanvasRenderingContext2DContextRestoredEvent = 3975,
+ kReadOrWriteWebDatabaseThirdPartyContext = 3985,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
diff --git a/chromium/third_party/blink/public/mojom/webauthn/authenticator.mojom b/chromium/third_party/blink/public/mojom/webauthn/authenticator.mojom
index 4ac7f89fc1e..19d0d7619bc 100644
--- a/chromium/third_party/blink/public/mojom/webauthn/authenticator.mojom
+++ b/chromium/third_party/blink/public/mojom/webauthn/authenticator.mojom
@@ -4,7 +4,9 @@
module blink.mojom;
+import "components/payments/mojom/payment_request_data.mojom";
import "mojo/public/mojom/base/time.mojom";
+import "third_party/blink/public/mojom/payments/payment_credential.mojom";
import "url/mojom/url.mojom";
// This file describes the communication between the WebAuthentication renderer
@@ -38,6 +40,7 @@ enum AuthenticatorStatus {
BAD_RELYING_PARTY_ID,
CANNOT_READ_AND_WRITE_LARGE_BLOB,
INVALID_ALLOW_CREDENTIALS_FOR_LARGE_BLOB,
+ FAILED_TO_SAVE_CREDENTIAL_ID_FOR_PAYMENT_EXTENSION,
UNKNOWN_ERROR,
};
@@ -288,6 +291,15 @@ struct PRFValues {
array<uint8, 32>? second;
};
+// Payment parameters passed into calls to GetAssertion for Secure Payment
+// Confirmation.
+// TODO(https://crbug.com/1239249): Convert to a non-mojo struct, because this
+// is not used in any mojo interfaces.
+struct PaymentOptions {
+ payments.mojom.PaymentCurrencyAmount total;
+ payments.mojom.PaymentCredentialInstrument instrument;
+};
+
// Parameters passed into calls to GetAssertion.
struct PublicKeyCredentialRequestOptions {
// If true, indicates that this request should prioritize showing a UI only if
@@ -485,6 +497,11 @@ struct PublicKeyCredentialCreationOptions {
// If present, attempt the store the given value as a credblob.
// https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html#sctn-credBlob-extension
array<uint8>? cred_blob;
+
+ // Whether a U2F-API-compatible should be made to support a U2F API
+ // migration.
+ // https://groups.google.com/a/chromium.org/g/blink-dev/c/xHC3AtU_65A
+ bool google_legacy_app_id_support = false;
};
enum PublicKeyCredentialType {
diff --git a/chromium/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/chromium/third_party/blink/public/mojom/webid/federated_auth_request.mojom
index ffef84fd9e8..2753124fb07 100644
--- a/chromium/third_party/blink/public/mojom/webid/federated_auth_request.mojom
+++ b/chromium/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -40,10 +40,18 @@ enum RequestMode {
// This interface is called from a renderer process and implemented in the
// browser process.
interface FederatedAuthRequest {
- // Requests an IdToken to be generated, given an IDP URL and an OAuth request.
+ // Requests an IdToken to be generated, given an IDP URL, some request
+ // parameters, and a mode that specifies the UI flow.
+ // |client_id| and |nonce| can be empty strings to omit the fields in the
+ // request sent to the provider.
// Returns the raw content of the IdToken.
- RequestIdToken(url.mojom.Url provider, string id_request, RequestMode mode) => (RequestIdTokenStatus status, string? id_token);
-
- // Contact the list of Relying Party logout endpoints to attempt to initiate user logout.
+ RequestIdToken(url.mojom.Url provider,
+ string client_id,
+ string nonce,
+ RequestMode mode) =>
+ (RequestIdTokenStatus status, string? id_token);
+
+ // Contact the list of Relying Party logout endpoints to attempt to initiate
+ // user logout.
Logout(array<string> rp_logout_endpoints) => (LogoutStatus status);
};
diff --git a/chromium/third_party/blink/public/mojom/webpreferences/web_preferences.mojom b/chromium/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
index db9994ca72f..eaecb8c2b7d 100644
--- a/chromium/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
+++ b/chromium/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
@@ -8,6 +8,7 @@ import "third_party/blink/public/mojom/css/preferred_color_scheme.mojom";
import "third_party/blink/public/mojom/css/preferred_contrast.mojom";
import "third_party/blink/public/mojom/v8_cache_options.mojom";
import "url/mojom/url.mojom";
+import "url/mojom/origin.mojom";
import "mojo/public/mojom/base/string16.mojom";
enum PointerType {
@@ -153,6 +154,7 @@ struct WebPreferences {
bool hide_scrollbars;
bool accelerated_2d_canvas_enabled;
bool new_canvas_2d_api_enabled;
+ bool canvas_2d_layers_enabled;
bool antialiased_2d_canvas_disabled;
bool antialiased_clips_2d_canvas_enabled;
bool accelerated_filters_enabled;
@@ -435,4 +437,8 @@ struct WebPreferences {
// Controls whether WebXR's immersive-ar is allowed.
bool webxr_immersive_ar_allowed;
+
+ // Origin the subresources such as images should be redirected to when the
+ // kSubresourceRedirect feature is enabled.
+ url.mojom.Origin litepage_subresource_redirect_origin;
};
diff --git a/chromium/third_party/blink/public/mojom/webshare/OWNERS b/chromium/third_party/blink/public/mojom/webshare/OWNERS
index ad557205588..10c1a6f3087 100644
--- a/chromium/third_party/blink/public/mojom/webshare/OWNERS
+++ b/chromium/third_party/blink/public/mojom/webshare/OWNERS
@@ -1,6 +1,5 @@
ericwilligers@chromium.org
mgiuca@chromium.org
-sammc@chromium.org
# Changes to Mojo interfaces require a security review to avoid
# introducing new sandbox escapes.
diff --git a/chromium/third_party/blink/public/mojom/websockets/websocket_connector.mojom b/chromium/third_party/blink/public/mojom/websockets/websocket_connector.mojom
index d7cc2a09835..d1300c41145 100644
--- a/chromium/third_party/blink/public/mojom/websockets/websocket_connector.mojom
+++ b/chromium/third_party/blink/public/mojom/websockets/websocket_connector.mojom
@@ -4,6 +4,7 @@
module blink.mojom;
+import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/network/public/mojom/site_for_cookies.mojom";
import "services/network/public/mojom/websocket.mojom";
import "url/mojom/url.mojom";
@@ -20,5 +21,7 @@ interface WebSocketConnector {
array<string> requested_protocols,
network.mojom.SiteForCookies site_for_cookies,
string? user_agent,
- pending_remote<network.mojom.WebSocketHandshakeClient> handshake_client);
+ pending_remote<network.mojom.WebSocketHandshakeClient> handshake_client,
+ mojo_base.mojom.UnguessableToken? throttling_profile_id);
+
};
diff --git a/chromium/third_party/blink/public/mojom/widget/device_emulation_params.mojom b/chromium/third_party/blink/public/mojom/widget/device_emulation_params.mojom
index 8f21199e31e..00c2362ab44 100644
--- a/chromium/third_party/blink/public/mojom/widget/device_emulation_params.mojom
+++ b/chromium/third_party/blink/public/mojom/widget/device_emulation_params.mojom
@@ -5,7 +5,7 @@
module blink.mojom;
import "ui/gfx/geometry/mojom/geometry.mojom";
-import "third_party/blink/public/mojom/widget/screen_orientation.mojom";
+import "ui/display/mojom/screen_orientation.mojom";
enum EmulatedScreenType { kDesktop, kMobile };
@@ -42,7 +42,7 @@ struct DeviceEmulationParams {
// Optional screen orientation type, with ScreenOrientation::Undefined
// value meaning no emulation necessary.
- ScreenOrientation screen_orientation_type;
+ display.mojom.ScreenOrientation screen_orientation_type;
// Screen orientation angle, used together with screen_orientation_type.
uint32 screen_orientation_angle;
diff --git a/chromium/third_party/blink/public/mojom/widget/screen_info.mojom b/chromium/third_party/blink/public/mojom/widget/screen_info.mojom
deleted file mode 100644
index f4db7086206..00000000000
--- a/chromium/third_party/blink/public/mojom/widget/screen_info.mojom
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-import "third_party/blink/public/mojom/widget/screen_orientation.mojom";
-import "ui/gfx/geometry/mojom/geometry.mojom";
-import "ui/gfx/mojom/display_color_spaces.mojom";
-
-// Information about the screen on which a WidgetBase is being displayed. This
-// is the content counterpart to blink::ScreenInfo, and it roughly parallels
-// display.mojom.Display. It may be desirable to deprecate derived counterparts
-// of ui/display types, but doing so is complicated by widespread use and legacy
-// quirks around blink::ScreenInfo.
-struct ScreenInfo {
- // Device scale factor. Specifies the ratio between physical and logical
- // pixels.
- float device_scale_factor = 1;
-
- // The color spaces and buffer formats that this screen will use for various
- // content types.
- gfx.mojom.DisplayColorSpaces display_color_spaces;
-
- // The screen depth in bits per pixel.
- uint32 depth;
-
- // The bits per colour component. This assumes that the colours are balanced
- // equally.
- uint32 depth_per_component;
-
- // This can be true for black and white printers
- bool is_monochrome = false;
-
- // The display frequency in Hz of the monitor. Set to 0 if it fails in the
- // monitor frequency query.
- uint32 display_frequency;
-
- // The display monitor rectangle in virtual-screen coordinates. Note that
- // this may be negative.
- gfx.mojom.Rect rect;
-
- // The portion of the monitor's rectangle that can be used by applications.
- gfx.mojom.Rect available_rect;
-
- // The monitor's orientation.
- ScreenOrientation orientation_type = ScreenOrientation.kUndefined;
-
- // This is the orientation angle of the displayed content in degrees.
- // It is the opposite of the physical rotation.
- uint16 orientation_angle;
-
- // Proposed: https://github.com/webscreens/window-placement
- // Whether this Screen is part of a multi-screen extended visual workspace.
- bool is_extended;
-
- // Proposed: https://github.com/webscreens/window-placement
- // Whether this screen is designated as the 'primary' screen by the OS
- // (otherwise it is a 'secondary' screen).
- bool is_primary = false;
-
- // Proposed: https://github.com/webscreens/window-placement
- // Whether this screen is an 'internal' panel built into the device, like a
- // laptop display (otherwise it is 'external', like a wired monitor).
- bool is_internal = false;
-
- // Not web-exposed; the display::Display::id(), for internal tracking only.
- int64 display_id;
-};
diff --git a/chromium/third_party/blink/public/mojom/widget/screen_infos.mojom b/chromium/third_party/blink/public/mojom/widget/screen_infos.mojom
deleted file mode 100644
index 345ff0990e3..00000000000
--- a/chromium/third_party/blink/public/mojom/widget/screen_infos.mojom
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-import "third_party/blink/public/mojom/widget/screen_info.mojom";
-
-// Information about a set of screens that are relevant to a particular widget.
-// This includes an id for the screen currently showing the widget.
-// This structure roughly parallels display.mojom.DisplayList. It may be
-// desirable to deprecate derived counterparts of ui/display types, but doing so
-// is complicated by widespread use and legacy quirks around blink::ScreenInfo.
-struct ScreenInfos {
- // The array of ScreenInfo objects for the set of relevant screens.
- array<ScreenInfo> screen_infos;
-
- // The display_id of the current ScreenInfo in `screen_infos`.
- int64 current_display_id;
-};
diff --git a/chromium/third_party/blink/public/mojom/widget/screen_orientation.mojom b/chromium/third_party/blink/public/mojom/widget/screen_orientation.mojom
deleted file mode 100644
index afdb94e13b7..00000000000
--- a/chromium/third_party/blink/public/mojom/widget/screen_orientation.mojom
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-// The screen orientation. This is slightly different than the
-// device.mojom.ScreenOrientationLockType which is a request to lock to
-// a specific screen orientation.
-enum ScreenOrientation {
- kUndefined,
- kPortraitPrimary,
- kPortraitSecondary,
- kLandscapePrimary,
- kLandscapeSecondary,
-}; \ No newline at end of file
diff --git a/chromium/third_party/blink/public/mojom/widget/visual_properties.mojom b/chromium/third_party/blink/public/mojom/widget/visual_properties.mojom
index b2fe7bf659b..9ae972370cf 100644
--- a/chromium/third_party/blink/public/mojom/widget/visual_properties.mojom
+++ b/chromium/third_party/blink/public/mojom/widget/visual_properties.mojom
@@ -7,13 +7,13 @@ module blink.mojom;
import "cc/mojom/browser_controls_params.mojom";
import "services/viz/public/mojom/compositing/local_surface_id.mojom";
import "third_party/blink/public/mojom/manifest/display_mode.mojom";
-import "third_party/blink/public/mojom/widget/screen_infos.mojom";
+import "ui/display/mojom/screen_infos.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
// See public/common/widget/visual_properties.h
struct VisualProperties {
// Info about all screens, including the one currently showing the widget.
- ScreenInfos screen_infos;
+ display.mojom.ScreenInfos screen_infos;
// Whether or not blink should be in auto-resize mode.
bool auto_resize_enabled = false;
@@ -92,4 +92,12 @@ struct VisualProperties {
// Indicates whether a pinch gesture is currently active. Originates in the
// main frame's renderer, and needs to be shared with subframes.
bool is_pinch_gesture_active;
+
+ // The rect of the Windows Control Overlay, which contains system UX
+ // affordances (e.g. close), for installed desktop Progress Web Apps (PWAs),
+ // if the app specifies the 'window-controls-overlay' DisplayMode in its
+ // manifest. This is only valid and to be consumed by the outermost main
+ // frame.
+ gfx.mojom.Rect window_controls_overlay_rect;
+
};
diff --git a/chromium/third_party/blink/public/platform/DEPS b/chromium/third_party/blink/public/platform/DEPS
index cf38ed44531..9ce89bc764b 100644
--- a/chromium/third_party/blink/public/platform/DEPS
+++ b/chromium/third_party/blink/public/platform/DEPS
@@ -62,13 +62,13 @@ include_rules = [
"+services/network/public/mojom/ip_address_space.mojom-shared.h",
"+services/network/public/mojom/referrer_policy.mojom-shared.h",
"+services/network/public/mojom/trust_tokens.mojom-shared.h",
+ "+services/network/public/mojom/url_loader.mojom-forward.h",
"+services/network/public/mojom/url_loader_factory.mojom-forward.h",
"+services/network/public/mojom/url_loader_factory.mojom-shared.h",
"+services/network/public/mojom/url_response_head.mojom-forward.h",
"+services/network/public/mojom/web_client_hints_types.mojom-shared.h",
"+services/service_manager/public/mojom",
- "+third_party/abseil-cpp/absl/types/optional.h",
"+third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h",
"+third_party/blink/public/platform",
"+third_party/blink/public/mojom/tokens",
diff --git a/chromium/third_party/blink/public/platform/OWNERS b/chromium/third_party/blink/public/platform/OWNERS
index b566b5ee1b3..959f163c963 100644
--- a/chromium/third_party/blink/public/platform/OWNERS
+++ b/chromium/third_party/blink/public/platform/OWNERS
@@ -12,9 +12,7 @@ per-file web_rtc_*=hbos@chromium.org
# Video SurfaceLayer functionality.
per-file web_video_frame*=file://media/OWNERS
per-file webaudiosourceprovider_impl.h=file://media/OWNERS
-per-file web_video_frame*=lethalantidote@chromium.org
per-file web_surface_layer_bridge*=file://media/OWNERS
-per-file web_surface_layer_bridge*=lethalantidote@chromium.org
# Any core owner can also approve changes to runtime-enabled features.
# Please make sure to get a review from someone with expertise on the feature
diff --git a/chromium/third_party/blink/public/platform/TaskTypes.md b/chromium/third_party/blink/public/platform/TaskTypes.md
index b849f066a16..778e2ac7c7d 100644
--- a/chromium/third_party/blink/public/platform/TaskTypes.md
+++ b/chromium/third_party/blink/public/platform/TaskTypes.md
@@ -58,6 +58,7 @@ pausable. Some internal task queues are not.
| InternalNavigationAssociated | No | No | No | No | No | No |
| InternalFreezableIPC | No | No | No | Yes | No | No |
| InternalContinueScriptLoading | No | No | No | Yes | Yes | Yes |
+| InternalPostMessageForwarding | No | No | No | No | Yes | Yes |
Internal Translation queue supports concept of it running only in the foreground. It is disabled if the page that owns it goes in background.
diff --git a/chromium/third_party/blink/public/platform/child_url_loader_factory_bundle.h b/chromium/third_party/blink/public/platform/child_url_loader_factory_bundle.h
index cdd9ce54600..70656202bea 100644
--- a/chromium/third_party/blink/public/platform/child_url_loader_factory_bundle.h
+++ b/chromium/third_party/blink/public/platform/child_url_loader_factory_bundle.h
@@ -15,7 +15,6 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h"
#include "third_party/blink/public/platform/web_common.h"
@@ -46,6 +45,10 @@ class BLINK_PLATFORM_EXPORT ChildPendingURLLoaderFactoryBundle
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_prefetch_loader_factory,
bool bypass_redirect_checks);
+ ChildPendingURLLoaderFactoryBundle(
+ const ChildPendingURLLoaderFactoryBundle&) = delete;
+ ChildPendingURLLoaderFactoryBundle& operator=(
+ const ChildPendingURLLoaderFactoryBundle&) = delete;
~ChildPendingURLLoaderFactoryBundle() override;
static std::unique_ptr<ChildPendingURLLoaderFactoryBundle>
@@ -74,8 +77,6 @@ class BLINK_PLATFORM_EXPORT ChildPendingURLLoaderFactoryBundle
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_prefetch_loader_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ChildPendingURLLoaderFactoryBundle);
};
// This class extends URLLoaderFactoryBundle to support prefetch loader factory
diff --git a/chromium/third_party/blink/public/platform/input/input_handler_proxy.h b/chromium/third_party/blink/public/platform/input/input_handler_proxy.h
index 2d4e1d10ccf..ab527bb1ef5 100644
--- a/chromium/third_party/blink/public/platform/input/input_handler_proxy.h
+++ b/chromium/third_party/blink/public/platform/input/input_handler_proxy.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "cc/input/input_handler.h"
#include "cc/input/snap_fling_controller.h"
#include "cc/paint/element_id.h"
@@ -68,6 +67,8 @@ class BLINK_PLATFORM_EXPORT InputHandlerProxy
public:
InputHandlerProxy(cc::InputHandler& input_handler,
InputHandlerProxyClient* client);
+ InputHandlerProxy(const InputHandlerProxy&) = delete;
+ InputHandlerProxy& operator=(const InputHandlerProxy&) = delete;
~InputHandlerProxy() override;
ElasticOverscrollController* elastic_overscroll_controller() {
@@ -171,6 +172,7 @@ class BLINK_PLATFORM_EXPORT InputHandlerProxy
void WillShutdown() override;
void Animate(base::TimeTicks time) override;
void ReconcileElasticOverscrollAndRootScroll() override;
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override;
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -223,6 +225,7 @@ class BLINK_PLATFORM_EXPORT InputHandlerProxy
void DispatchSingleInputEvent(std::unique_ptr<EventWithCallback>,
const base::TimeTicks);
void DispatchQueuedInputEvents();
+ void UpdateElasticOverscroll();
// Helper functions for handling more complicated input events.
EventDisposition HandleMouseWheel(const blink::WebMouseWheelEvent& event);
@@ -242,7 +245,8 @@ class BLINK_PLATFORM_EXPORT InputHandlerProxy
const gfx::PointF& position);
const cc::InputHandlerPointerResult HandlePointerMove(
EventWithCallback* event_with_callback,
- const gfx::PointF& position);
+ const gfx::PointF& position,
+ bool should_cancel_scrollbar_drag);
const cc::InputHandlerPointerResult HandlePointerUp(
EventWithCallback* event_with_callback,
const gfx::PointF& position);
@@ -362,13 +366,14 @@ class BLINK_PLATFORM_EXPORT InputHandlerProxy
// hit test information is unnecessary (e.g. tests).
bool event_attribution_enabled_ = true;
+ // This tracks whether the user has set prefers reduced motion.
+ bool prefers_reduced_motion_ = false;
+
// Helpers for the momentum scroll jank UMAs.
std::unique_ptr<MomentumScrollJankTracker> momentum_scroll_jank_tracker_;
// Swipe to move cursor feature.
std::unique_ptr<CursorControlHandler> cursor_control_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/internet_disconnected_web_url_loader.h b/chromium/third_party/blink/public/platform/internet_disconnected_web_url_loader.h
index ddb435913a4..d4b4fe0f962 100644
--- a/chromium/third_party/blink/public/platform/internet_disconnected_web_url_loader.h
+++ b/chromium/third_party/blink/public/platform/internet_disconnected_web_url_loader.h
@@ -65,7 +65,7 @@ class InternetDisconnectedWebURLLoader final : public WebURLLoader {
std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
resource_load_info_notifier_wrapper,
WebURLLoaderClient* client) override;
- void SetDefersLoading(DeferType defers) override;
+ void Freeze(WebLoaderFreezeMode mode) override;
void DidChangePriority(WebURLRequest::Priority, int) override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
override;
diff --git a/chromium/third_party/blink/public/platform/media/BUILD.gn b/chromium/third_party/blink/public/platform/media/BUILD.gn
new file mode 100644
index 00000000000..1a4bc79ac2c
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/BUILD.gn
@@ -0,0 +1,57 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//media/media_options.gni")
+
+# TODO(https://crbug.com/1198341): once this code is ported to Blink code
+# conventions, this target should be merged into
+# //third_party/blink/public:blink_headers and
+# //third_party/blink/renderer/platform/media should be a dep of
+# //third_party/blink/renderer/platform.
+source_set("media") {
+ sources = [
+ "buffered_data_source_host_impl.h",
+ "interval_map.h",
+ "key_system_config_selector.h",
+ "lru.h",
+ "multi_buffer.h",
+ "power_status_helper.h",
+ "remote_playback_client_wrapper_impl.h",
+ "resource_fetch_context.h",
+ "url_index.h",
+ "video_frame_compositor.h",
+ "web_encrypted_media_client_impl.h",
+ "web_media_player_params.h",
+ ]
+ public_deps = [
+ "//base",
+ "//cc",
+ "//components/viz/common",
+ "//media",
+ "//media/mojo/mojom",
+ "//mojo/public/cpp/bindings",
+ "//services/device/public/mojom",
+ "//third_party/blink/public:blink",
+ "//third_party/blink/public:blink_headers",
+ "//ui/gfx/geometry",
+ "//url",
+ ]
+
+ allow_circular_includes_from =
+ [ "//third_party/blink/renderer/platform/media" ]
+ deps = [ "//third_party/blink/renderer/platform/media" ]
+
+ if (media_use_ffmpeg || !is_android) {
+ sources += [
+ "learning_experiment_helper.h",
+ "multi_buffer_data_source.h",
+ "smoothness_helper.h",
+ "web_media_player_impl.h",
+ ]
+ public_deps += [
+ "//media/learning/common",
+ "//services/media_session/public/cpp:base_cpp",
+ ]
+ }
+}
diff --git a/chromium/third_party/blink/public/platform/media/DEPS b/chromium/third_party/blink/public/platform/media/DEPS
new file mode 100644
index 00000000000..00636169fcf
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/DEPS
@@ -0,0 +1,20 @@
+include_rules = [
+ "+base/bind.h",
+ "+base/cancelable_callback.h",
+ "+base/compiler_specific.h",
+ "+base/containers/circular_deque.h",
+ "+base/feature_list.h",
+ "+base/gtest_prod_util.h",
+ "+base/hash/hash.h",
+ "+base/sequence_checker.h",
+ "+base/thread_annotations.h",
+ "+base/timer/elapsed_timer.h",
+ "+base/timer/timer.h",
+ "+media/base",
+ "+media/learning/common",
+ "+media/mojo/mojom",
+ "+media/renderers",
+ "+services/device/public/mojom",
+ "+services/media_session/public/cpp",
+ "+third_party/blink/public/web",
+]
diff --git a/chromium/third_party/blink/public/platform/media/buffered_data_source_host_impl.h b/chromium/third_party/blink/public/platform/media/buffered_data_source_host_impl.h
new file mode 100644
index 00000000000..6ba7be2e445
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/buffered_data_source_host_impl.h
@@ -0,0 +1,102 @@
+// 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_PUBLIC_PLATFORM_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
+
+#include <stdint.h>
+
+#include "base/callback.h"
+#include "base/containers/circular_deque.h"
+#include "base/gtest_prod_util.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "media/base/ranges.h"
+#include "third_party/blink/public/platform/media/interval_map.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace blink {
+
+// Interface for testing purposes.
+class BLINK_PLATFORM_EXPORT BufferedDataSourceHost {
+ public:
+ // Notify the host of the total size of the media file.
+ virtual void SetTotalBytes(int64_t total_bytes) = 0;
+
+ // Notify the host that byte range [start,end] has been buffered.
+ // TODO(fischman): remove this method when demuxing is push-based instead of
+ // pull-based. http://crbug.com/131444
+ virtual void AddBufferedByteRange(int64_t start, int64_t end) = 0;
+
+ protected:
+ virtual ~BufferedDataSourceHost() {}
+};
+
+// Provides an implementation of BufferedDataSourceHost that translates the
+// buffered byte ranges into estimated time ranges.
+class BLINK_PLATFORM_EXPORT BufferedDataSourceHostImpl
+ : public BufferedDataSourceHost {
+ public:
+ BufferedDataSourceHostImpl(base::RepeatingClosure progress_cb,
+ const base::TickClock* tick_clock);
+ BufferedDataSourceHostImpl(const BufferedDataSourceHostImpl&) = delete;
+ BufferedDataSourceHostImpl& operator=(const BufferedDataSourceHostImpl&) =
+ delete;
+ ~BufferedDataSourceHostImpl() override;
+
+ // BufferedDataSourceHost implementation.
+ void SetTotalBytes(int64_t total_bytes) override;
+ void AddBufferedByteRange(int64_t start, int64_t end) override;
+
+ // Translate the byte ranges to time ranges and append them to the list.
+ // TODO(sandersd): This is a confusing name, find something better.
+ void AddBufferedTimeRanges(
+ media::Ranges<base::TimeDelta>* buffered_time_ranges,
+ base::TimeDelta media_duration) const;
+
+ bool DidLoadingProgress();
+
+ // Returns true if we have enough buffered bytes to play from now
+ // until the end of media
+ bool CanPlayThrough(base::TimeDelta current_position,
+ base::TimeDelta media_duration,
+ double playback_rate) const;
+
+ // Caller must make sure |tick_clock| is valid for lifetime of this object.
+ void SetTickClockForTest(const base::TickClock* tick_clock);
+
+ private:
+ // Returns number of bytes not yet loaded in the given interval.
+ int64_t UnloadedBytesInInterval(const Interval<int64_t>& interval) const;
+
+ // Returns an estimate of the download rate.
+ // Returns 0.0 if an estimate cannot be made.
+ double DownloadRate() const;
+
+ // Total size of the data source.
+ int64_t total_bytes_;
+
+ // List of buffered byte ranges for estimating buffered time.
+ // The InterValMap value is 1 for bytes that are buffered, 0 otherwise.
+ IntervalMap<int64_t, int> buffered_byte_ranges_;
+
+ // True when AddBufferedByteRange() has been called more recently than
+ // DidLoadingProgress().
+ bool did_loading_progress_;
+
+ // Contains how much we had downloaded at a given time.
+ // Pruned to contain roughly the last 10 seconds of data.
+ base::circular_deque<std::pair<base::TimeTicks, uint64_t>> download_history_;
+ base::RepeatingClosure progress_cb_;
+
+ const base::TickClock* tick_clock_;
+
+ FRIEND_TEST_ALL_PREFIXES(BufferedDataSourceHostImplTest, CanPlayThrough);
+ FRIEND_TEST_ALL_PREFIXES(BufferedDataSourceHostImplTest,
+ CanPlayThroughSmallAdvances);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
diff --git a/chromium/third_party/blink/public/platform/media/interval_map.h b/chromium/third_party/blink/public/platform/media/interval_map.h
new file mode 100644
index 00000000000..d25edffb921
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/interval_map.h
@@ -0,0 +1,290 @@
+// 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_PUBLIC_PLATFORM_MEDIA_INTERVAL_MAP_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_INTERVAL_MAP_H_
+
+#include <algorithm>
+#include <limits>
+#include <map>
+
+#include "base/check.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace blink {
+
+// An IntervalMap<KeyType, ValueType> maps every value of KeyType to
+// a ValueType, and incrementing, decrementing and setting ranges of values
+// has been optimized. The default state is to map all values in
+// KeyType to ValueType(). (Which is usually zero.)
+//
+// Set/Increment operations should generally take
+// O(log(N)) + O(M) time where N is the number of intervals in the map and
+// M is the number of modified intervals.
+//
+// Internally, IntervalMap<> uses an std::map, where the beginning of each
+// interval is stored along with the value for that interval. Adjacent intervals
+// which have the same value are automatically merged. For instance, if you did:
+//
+// IntervalMap<int, int> tmp;
+// tmp.IncrementInterval(2, 5, 2);
+// tmp.IncrementInterval(4, 6, 1);
+//
+// Then:
+// tmp[0] = 0
+// tmp[1] = 0
+// tmp[2] = 2
+// tmp[3] = 2
+// tmp[4] = 3
+// tmp[5] = 1
+// tmp[6] = 0
+//
+// If you iterate over tmp, you get the following intervals:
+// -maxint .. 2 => 0
+// 2 .. 4 => 2
+// 4 .. 5 => 3
+// 5 .. 6 => 1
+// 6 .. maxint => 0
+//
+// Internally, this would be stored in a map as:
+// -maxint:0, 2:2, 4:3, 5:1, 6:0
+//
+// TODO(hubbe): Consider consolidating with media::Ranges.
+
+// Simple interval class.
+// Interval ends are always non-inclusive.
+// Please note that end <= begin is a valid (but empty) interval.
+template <typename T>
+struct BLINK_PLATFORM_EXPORT Interval {
+ public:
+ Interval(const T& begin, const T& end) : begin(begin), end(end) {}
+
+ // May return empty intervals (begin >= end).
+ Interval Intersect(const Interval& other) const {
+ return Interval(std::max(begin, other.begin), std::min(end, other.end));
+ }
+
+ bool Empty() const { return begin >= end; }
+
+ T begin;
+ T end;
+};
+
+// The IntervalMapConstIterator points to an interval in an
+// IntervalMap where all values are the same. Calling ++/--
+// goes to the next/previous interval, which is guaranteed to
+// have values different from the current interval.
+template <typename KeyType,
+ typename ValueType,
+ class Compare = std::less<KeyType>,
+ class NumericLimits = std::numeric_limits<KeyType>>
+class BLINK_PLATFORM_EXPORT IntervalMapConstIterator {
+ public:
+ typedef std::map<KeyType, ValueType, Compare> MapType;
+ IntervalMapConstIterator() {}
+ IntervalMapConstIterator(const MapType* map,
+ typename MapType::const_iterator iter)
+ : map_(map), iter_(iter) {}
+
+ bool operator==(const IntervalMapConstIterator& other) const {
+ return iter_ == other.iter_;
+ }
+
+ bool operator!=(const IntervalMapConstIterator& other) const {
+ return iter_ != other.iter_;
+ }
+
+ // Returns the beginning of the current interval.
+ KeyType interval_begin() const {
+ DCHECK(iter_ != map_->end());
+ return iter_->first;
+ }
+
+ // Returns the end of the current interval, non-inclusive.
+ KeyType interval_end() const {
+ DCHECK(iter_ != map_->end());
+ typename MapType::const_iterator next = iter_;
+ ++next;
+ if (next == map_->end()) {
+ return NumericLimits::max();
+ } else {
+ return next->first;
+ }
+ }
+
+ // Returns the current interval.
+ Interval<KeyType> interval() const {
+ return Interval<KeyType>(interval_begin(), interval_end());
+ }
+
+ // Returns the value associated with the current interval.
+ ValueType value() const {
+ DCHECK(iter_ != map_->end());
+ return iter_->second;
+ }
+
+ // Needed to make the following construct work:
+ // for (const auto& interval_value_pair : interval_map)
+ std::pair<Interval<KeyType>, ValueType> operator*() const {
+ return std::make_pair(interval(), value());
+ }
+
+ // Go to the next interval.
+ // The beginning of the next interval always matches the end of the current
+ // interval. (But should always have a different value.)
+ // Not allowed if we're already at map_->end().
+ void operator++() {
+ DCHECK(iter_ != map_->end());
+ ++iter_;
+ }
+
+ // Go to the previous interval.
+ // The end of the previous interval always matches the beginning of the
+ // current interval. (But should always have a different value.)
+ // Not allowed if we're already at map_->begin().
+ void operator--() {
+ DCHECK(iter_ != map_->begin());
+ --iter_;
+ }
+
+ private:
+ const MapType* map_;
+
+ // Pointer to the entry in the IntervalMap that specifies the
+ // beginning of the current interval.
+ typename MapType::const_iterator iter_;
+};
+
+template <typename KeyType,
+ typename ValueType,
+ class Compare = std::less<KeyType>,
+ class NumericLimits = std::numeric_limits<KeyType>>
+class BLINK_PLATFORM_EXPORT IntervalMap {
+ public:
+ typedef std::map<KeyType, ValueType, Compare> MapType;
+ typedef IntervalMapConstIterator<KeyType, ValueType, Compare, NumericLimits>
+ const_iterator;
+ IntervalMap() {
+ // Adding an explicit entry for the default interval is not strictly needed,
+ // but simplifies the code a lot.
+ map_[NumericLimits::min()] = ValueType();
+ }
+
+ // Returns the value at a particular point.
+ // Defaults to ValueType().
+ ValueType operator[](const KeyType& k) const {
+ typename MapType::const_iterator i = map_.upper_bound(k);
+ DCHECK(i != map_.begin());
+ --i;
+ return i->second;
+ }
+
+ // Increase [from..to) by |how_much|.
+ void IncrementInterval(KeyType from, KeyType to, ValueType how_much) {
+ if (to <= from || how_much == 0)
+ return;
+ typename MapType::iterator a = MakeEntry(from);
+ typename MapType::iterator b = MakeEntry(to);
+ for (typename MapType::iterator i = a; i != b; ++i) {
+ i->second += how_much;
+ }
+ RemoveDuplicates(a);
+ // b may be invalid
+ RemoveDuplicates(map_.lower_bound(to));
+ }
+
+ // Set [from..to) to |how_much|.
+ void SetInterval(KeyType from, KeyType to, ValueType how_much) {
+ if (to <= from)
+ return;
+ typename MapType::iterator a = MakeEntry(from);
+ typename MapType::iterator b = MakeEntry(to);
+ a->second = how_much;
+ while (true) {
+ typename MapType::iterator c = a;
+ ++c;
+ if (c == b) {
+ break;
+ } else {
+ map_.erase(c);
+ }
+ }
+ RemoveDuplicates(a);
+ // b may be invalid
+ RemoveDuplicates(map_.lower_bound(to));
+ }
+
+ // Returns an iterator to the first interval.
+ // Note, there is always at least one interval.
+ const_iterator begin() const { return const_iterator(&map(), map_.begin()); }
+
+ // Returns an end marker iterator.
+ const_iterator end() const { return const_iterator(&map(), map_.end()); }
+
+ // Returns an iterator to the interval containing |k|.
+ // Always returns a valid iterator.
+ const_iterator find(KeyType k) const {
+ typename MapType::const_iterator iter = map_.upper_bound(k);
+ DCHECK(iter != map_.begin());
+ --iter;
+ return const_iterator(&map(), iter);
+ }
+
+ bool empty() const { return map().size() == 1; }
+ void clear() {
+ map_.clear();
+ map_[NumericLimits::min()] = ValueType();
+ }
+
+ private:
+ const MapType& map() const { return map_; }
+
+ // Make an entry in map_ with the key |k| and return it's iterator.
+ // If such an entry already exists, just re-use it.
+ // If a new entry is created, it's value will be set to the same
+ // as the preceeding entry, or ValueType() if no preceeding entry exists.
+ // After calling this function, we'll need to call RemoveDuplicates()
+ // to clean up any duplicates that we made.
+ typename MapType::iterator MakeEntry(KeyType k) {
+ typename MapType::value_type tmp(k, 0);
+ std::pair<typename MapType::iterator, bool> insert_result;
+ insert_result = map_.insert(tmp);
+ if (insert_result.second) {
+ if (insert_result.first != map_.begin()) {
+ typename MapType::iterator i = insert_result.first;
+ --i;
+ insert_result.first->second = i->second;
+ }
+ }
+ return insert_result.first;
+ }
+
+ // Remove duplicates before and after |i|.
+ void RemoveDuplicates(typename MapType::iterator i) {
+ if (i == map_.end())
+ return;
+
+ typename MapType::iterator first = i;
+ typename MapType::iterator second = i;
+ if (i != map_.begin()) {
+ --first;
+ if (first->second == second->second) {
+ map_.erase(second);
+ second = first;
+ } else {
+ first = second;
+ }
+ }
+ ++second;
+ if (second != map_.end() && first->second == second->second) {
+ map_.erase(second);
+ }
+ }
+
+ MapType map_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_INTERVAL_MAP_H_
diff --git a/chromium/third_party/blink/public/platform/media/key_system_config_selector.h b/chromium/third_party/blink/public/platform/media/key_system_config_selector.h
new file mode 100644
index 00000000000..13121b8d05e
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/key_system_config_selector.h
@@ -0,0 +1,155 @@
+// 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_PUBLIC_PLATFORM_MEDIA_KEY_SYSTEM_CONFIG_SELECTOR_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_KEY_SYSTEM_CONFIG_SELECTOR_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "media/base/eme_constants.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/public/platform/web_media_key_system_media_capability.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+
+namespace media {
+class KeySystems;
+class MediaPermission;
+struct CdmConfig;
+} // namespace media
+
+namespace blink {
+class WebString;
+struct WebMediaKeySystemConfiguration;
+
+class BLINK_PLATFORM_EXPORT KeySystemConfigSelector {
+ public:
+ // This is to facilitate testing, it abstracts the calls we are making into
+ // WebLocalFrame so we can override them for testing without implementing the
+ // entire interface for WebLocalFrame.
+ class BLINK_PLATFORM_EXPORT WebLocalFrameDelegate {
+ public:
+ explicit WebLocalFrameDelegate(WebLocalFrame* web_frame)
+ : web_frame_(web_frame) {}
+
+ virtual ~WebLocalFrameDelegate() = default;
+
+ // Delegate to WebLocalFrame.
+ virtual bool IsCrossOriginToMainFrame();
+
+ // Delegate to WebContentSettingsClient within WebLocalFrame.
+ virtual bool AllowStorageAccessSync(
+ WebContentSettingsClient::StorageType storage_type);
+
+ private:
+ // The pointer below will always be valid for the lifetime of this object
+ // because it is held by KeySystemConfigSelector whose chain of ownership is
+ // the same as RenderFrameImpl.
+ WebLocalFrame* web_frame_;
+ };
+
+ KeySystemConfigSelector(
+ media::KeySystems* key_systems,
+ media::MediaPermission* media_permission,
+ std::unique_ptr<WebLocalFrameDelegate> web_frame_delegate);
+ KeySystemConfigSelector(const KeySystemConfigSelector&) = delete;
+ KeySystemConfigSelector& operator=(const KeySystemConfigSelector&) = delete;
+
+ ~KeySystemConfigSelector();
+
+ // The unsupported statuses will be mapped to different rejection messages.
+ // The statuses should not leak sensitive information, e.g. incognito mode or
+ // user settings. See https://crbug.com/760720
+ enum class Status {
+ kSupported,
+ kUnsupportedKeySystem,
+ kUnsupportedConfigs,
+ };
+
+ // Callback for the result of `SelectConfig()`. The returned configs must be
+ // non-null iff `status` is `kSupported`.
+ using SelectConfigCB = base::OnceCallback<
+ void(Status status, WebMediaKeySystemConfiguration*, media::CdmConfig*)>;
+
+ void SelectConfig(
+ const WebString& key_system,
+ const WebVector<WebMediaKeySystemConfiguration>& candidate_configurations,
+ SelectConfigCB cb);
+
+ using IsSupportedMediaTypeCB =
+ base::RepeatingCallback<bool(const std::string& container_mime_type,
+ const std::string& codecs,
+ bool use_aes_decryptor)>;
+
+ void SetIsSupportedMediaTypeCBForTesting(IsSupportedMediaTypeCB cb) {
+ is_supported_media_type_cb_ = std::move(cb);
+ }
+
+ private:
+ struct SelectionRequest;
+ class ConfigState;
+
+ enum ConfigurationSupport {
+ CONFIGURATION_NOT_SUPPORTED,
+ CONFIGURATION_REQUIRES_PERMISSION,
+ CONFIGURATION_SUPPORTED,
+ };
+
+ void SelectConfigInternal(std::unique_ptr<SelectionRequest> request);
+
+ void OnPermissionResult(std::unique_ptr<SelectionRequest> request,
+ bool is_permission_granted);
+
+ ConfigurationSupport GetSupportedConfiguration(
+ const std::string& key_system,
+ const WebMediaKeySystemConfiguration& candidate,
+ ConfigState* config_state,
+ WebMediaKeySystemConfiguration* accumulated_configuration);
+
+ bool GetSupportedCapabilities(
+ const std::string& key_system,
+ media::EmeMediaType media_type,
+ const WebVector<WebMediaKeySystemMediaCapability>&
+ requested_media_capabilities,
+ ConfigState* config_state,
+ std::vector<WebMediaKeySystemMediaCapability>*
+ supported_media_capabilities);
+
+ bool IsSupportedContentType(const std::string& key_system,
+ media::EmeMediaType media_type,
+ const std::string& container_mime_type,
+ const std::string& codecs,
+ ConfigState* config_state);
+
+ media::EmeConfigRule GetEncryptionSchemeConfigRule(
+ const std::string& key_system,
+ const WebMediaKeySystemMediaCapability::EncryptionScheme
+ encryption_scheme);
+
+ media::KeySystems* const key_systems_;
+
+ // This object is unowned but its pointer is always valid. It has the same
+ // lifetime as RenderFrameImpl, and |this| also has the same lifetime
+ // as RenderFrameImpl. RenderFrameImpl owns content::MediaFactory which owns
+ // WebEncryptedMediaClientImpl which owns |this|.
+ media::MediaPermission* media_permission_;
+
+ std::unique_ptr<WebLocalFrameDelegate> web_frame_delegate_;
+
+ // A callback used to check whether a media type is supported. Only set in
+ // tests. If null the implementation will check the support using MimeUtil.
+ IsSupportedMediaTypeCB is_supported_media_type_cb_;
+
+ base::WeakPtrFactory<KeySystemConfigSelector> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_KEY_SYSTEM_CONFIG_SELECTOR_H_
diff --git a/chromium/third_party/blink/public/platform/media/learning_experiment_helper.h b/chromium/third_party/blink/public/platform/media/learning_experiment_helper.h
new file mode 100644
index 00000000000..890380a831f
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/learning_experiment_helper.h
@@ -0,0 +1,52 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_LEARNING_EXPERIMENT_HELPER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_LEARNING_EXPERIMENT_HELPER_H_
+
+#include <memory>
+
+#include "media/learning/common/feature_dictionary.h"
+#include "media/learning/common/labelled_example.h"
+#include "media/learning/common/learning_task.h"
+#include "media/learning/common/learning_task_controller.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace blink {
+
+// Helper for adding a learning experiment to existing code.
+class BLINK_PLATFORM_EXPORT LearningExperimentHelper {
+ public:
+ // If |controller| is null, then everything else no-ops.
+ LearningExperimentHelper(
+ std::unique_ptr<media::learning::LearningTaskController> controller);
+
+ LearningExperimentHelper(const LearningExperimentHelper&) = delete;
+ LearningExperimentHelper& operator=(const LearningExperimentHelper&) = delete;
+
+ // Cancels any existing observation.
+ ~LearningExperimentHelper();
+
+ // Start a new observation. Any existing observation is cancelled. Does
+ // nothing if there's no controller.
+ void BeginObservation(const media::learning::FeatureDictionary& dictionary);
+
+ // Complete any pending observation. Does nothing if none is in progress.
+ void CompleteObservationIfNeeded(const media::learning::TargetValue& target);
+
+ // Cancel any pending observation.
+ void CancelObservationIfNeeded();
+
+ private:
+ // May be null.
+ std::unique_ptr<media::learning::LearningTaskController> controller_;
+
+ // May be null if no observation is in flight. Must be null if |controller_|
+ // is null.
+ base::UnguessableToken observation_id_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_LEARNING_EXPERIMENT_HELPER_H_
diff --git a/chromium/third_party/blink/public/platform/media/lru.h b/chromium/third_party/blink/public/platform/media/lru.h
new file mode 100644
index 00000000000..d68859383f8
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/lru.h
@@ -0,0 +1,96 @@
+// 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_PUBLIC_PLATFORM_MEDIA_LRU_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_LRU_H_
+
+#include <stddef.h>
+
+#include <list>
+#include <unordered_map>
+
+#include "base/check.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace blink {
+
+// Simple LRU (least recently used) class.
+// Keeps track of a set of data and lets you get the least recently used
+// (oldest) element at any time. All operations are O(1). Elements are expected
+// to be hashable and unique.
+// Example:
+// LRU<int> lru;
+// lru.Insert(1);
+// lru.Insert(2);
+// lru.Insert(3);
+// lru.Use(1);
+// cout << lru.Pop(); // this will print "2"
+template <typename T>
+class BLINK_PLATFORM_EXPORT LRU {
+ public:
+ LRU() = default;
+ LRU(const LRU&) = delete;
+ LRU& operator=(const LRU&) = delete;
+
+ // Adds |x| to LRU.
+ // |x| must not already be in the LRU.
+ // Faster than Use(), and will DCHECK that |x| is not in the LRU.
+ void Insert(const T& x) {
+ DCHECK(!Contains(x));
+ lru_.push_front(x);
+ pos_[x] = lru_.begin();
+ }
+
+ // Removes |x| from LRU.
+ // |x| must be in the LRU.
+ void Remove(const T& x) {
+ DCHECK(Contains(x));
+ lru_.erase(pos_[x]);
+ pos_.erase(x);
+ }
+
+ // Moves |x| to front of LRU. (most recently used)
+ // If |x| is not in LRU, it is added.
+ // Please call Insert() if you know that |x| is not in the LRU.
+ void Use(const T& x) {
+ if (Contains(x))
+ Remove(x);
+ Insert(x);
+ }
+
+ bool Empty() const { return lru_.empty(); }
+
+ // Returns the Least Recently Used T and removes it.
+ T Pop() {
+ DCHECK(!Empty());
+ T ret = lru_.back();
+ lru_.pop_back();
+ pos_.erase(ret);
+ return ret;
+ }
+
+ // Returns the Least Recently Used T _without_ removing it.
+ T Peek() const {
+ DCHECK(!Empty());
+ return lru_.back();
+ }
+
+ bool Contains(const T& x) const { return pos_.find(x) != pos_.end(); }
+
+ size_t Size() const { return pos_.size(); }
+
+ private:
+ friend class LRUTest;
+
+ // Linear list of elements, most recently used first.
+ std::list<T> lru_;
+
+ // Maps element values to positions in the list so that we
+ // can quickly remove elements.
+ std::unordered_map<T, typename std::list<T>::iterator> pos_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_LRU_H_
diff --git a/chromium/third_party/blink/public/platform/media/multi_buffer.h b/chromium/third_party/blink/public/platform/media/multi_buffer.h
new file mode 100644
index 00000000000..b6331d4b444
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/multi_buffer.h
@@ -0,0 +1,388 @@
+// 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_PUBLIC_PLATFORM_MEDIA_MULTI_BUFFER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_MULTI_BUFFER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <functional>
+#include <limits>
+#include <map>
+#include <memory>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/hash/hash.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+#include "media/base/data_buffer.h"
+#include "third_party/blink/public/platform/media/interval_map.h"
+#include "third_party/blink/public/platform/media/lru.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace blink {
+
+// Used to identify a block of data in the multibuffer.
+// Our blocks are 32kb (1 << 15), so our maximum cacheable file size
+// is 1 << (15 + 31) = 64Tb
+typedef int32_t MultiBufferBlockId;
+class MultiBuffer;
+
+// This type is used to identify a block in the LRU, which is shared between
+// multibuffers.
+typedef std::pair<MultiBuffer*, MultiBufferBlockId> MultiBufferGlobalBlockId;
+
+} // namespace blink
+
+namespace std {
+
+template <>
+struct hash<blink::MultiBufferGlobalBlockId> {
+ std::size_t operator()(const blink::MultiBufferGlobalBlockId& key) const {
+ return base::HashInts(reinterpret_cast<uintptr_t>(key.first), key.second);
+ }
+};
+
+} // namespace std
+
+namespace blink {
+
+// Freeing a lot of blocks can be expensive, to keep thing
+// flowing smoothly we only free a maximum of |kMaxFreesPerAdd|
+// blocks when a new block is added to the cache.
+const int kMaxFreesPerAdd = 10;
+
+// There is a simple logic for creating, destroying and deferring
+// data providers. Every data provider has a look-ahead region and
+// a look-behind region. If there are readers in the look-ahead
+// region, we keep reading. If not, but there are readers in the
+// look-behind region, we defer. If there are no readers in either
+// region, we destroy the data provider.
+
+// When new readers are added, new data providers are created if
+// the new reader doesn't fall into the look-ahead region of
+// an existing data provider.
+
+// This is the size of the look-ahead region.
+const int kMaxWaitForWriterOffset = 5;
+
+// This is the size of the look-behind region.
+const int kMaxWaitForReaderOffset = 50;
+
+// MultiBuffers are multi-reader multi-writer cache/buffers with
+// prefetching and pinning. Data is stored internally in ref-counted
+// blocks of identical size. |block_size_shift| is log2 of the block
+// size.
+//
+// Users should inherit this class and implement CreateWriter().
+// TODO(hubbe): Make the multibuffer respond to memory pressure.
+class BLINK_PLATFORM_EXPORT MultiBuffer {
+ public:
+ // Interface for clients wishing to read data out of this cache.
+ // Note: It might look tempting to replace this with a callback,
+ // but we keep and compare pointers to Readers internally.
+ class Reader {
+ public:
+ Reader() = default;
+ Reader(const Reader&) = delete;
+ Reader& operator=(const Reader&) = delete;
+ virtual ~Reader() = default;
+ // Notifies the reader that the range of available blocks has changed.
+ // The reader must call MultiBuffer::Observe() to activate this callback.
+ virtual void NotifyAvailableRange(
+ const Interval<MultiBufferBlockId>& range) = 0;
+ };
+
+ // DataProvider is the interface that MultiBuffer
+ // uses to get data into the cache.
+ class DataProvider {
+ public:
+ virtual ~DataProvider() {}
+
+ // Returns the block number that is to be returned
+ // by the next Read() call.
+ virtual MultiBufferBlockId Tell() const = 0;
+
+ // Returns true if one (or more) blocks are
+ // availble to read.
+ virtual bool Available() const = 0;
+
+ // Returns how many bytes are available, note that Available() may still
+ // return false even if AvailableBytes() returns a value greater than
+ // zero if less than a full block is available.
+ virtual int64_t AvailableBytes() const = 0;
+
+ // Returns the next block. Only valid if Available()
+ // returns true. Last block might be of a smaller size
+ // and after the last block we will get an end-of-stream
+ // DataBuffer.
+ virtual scoped_refptr<media::DataBuffer> Read() = 0;
+
+ // Ask the data provider to stop giving us data.
+ // It's ok if the effect is not immediate.
+ virtual void SetDeferred(bool deferred) = 0;
+ };
+
+ // MultiBuffers use a global shared LRU to free memory.
+ // This effectively means that recently used multibuffers can
+ // borrow memory from less recently used ones.
+ class BLINK_PLATFORM_EXPORT GlobalLRU : public base::RefCounted<GlobalLRU> {
+ public:
+ typedef MultiBufferGlobalBlockId GlobalBlockId;
+ explicit GlobalLRU(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ GlobalLRU(const GlobalLRU&) = delete;
+ GlobalLRU& operator=(const GlobalLRU&) = delete;
+
+ // Free elements from cache if possible.
+ // Don't free more than |max_to_free| blocks.
+ void TryFree(int64_t max_to_free);
+
+ // Free as much memory from the cache as possible.
+ // Only used during critical memory pressure.
+ void TryFreeAll();
+
+ // Like TryFree, but only frees blocks if the data
+ // number of the blocks in the cache is too large.
+ void Prune(int64_t max_to_free);
+
+ // Returns true if there are prunable blocks.
+ bool Pruneable() const;
+
+ // Incremnt the amount of data used by all multibuffers.
+ void IncrementDataSize(int64_t blocks);
+
+ // Each multibuffer is allowed a certain amount of memory,
+ // that memory is registered by calling this function.
+ // The memory is actually shared by all multibuffers.
+ // When the total amount of memory used by all multibuffers
+ // is greater than what has been registered here, we use the
+ // LRU to decide what blocks to free first.
+ void IncrementMaxSize(int64_t blocks);
+
+ // LRU operations.
+ void Use(MultiBuffer* multibuffer, MultiBufferBlockId id);
+ void Remove(MultiBuffer* multibuffer, MultiBufferBlockId id);
+ void Insert(MultiBuffer* multibuffer, MultiBufferBlockId id);
+ bool Contains(MultiBuffer* multibuffer, MultiBufferBlockId id);
+ int64_t Size() const;
+
+ private:
+ friend class base::RefCounted<GlobalLRU>;
+ ~GlobalLRU();
+
+ // Schedule background pruning, if needed.
+ void SchedulePrune();
+
+ // Perform background pruning.
+ void PruneTask();
+
+ // Max number of blocks.
+ int64_t max_size_;
+
+ // Sum of all multibuffer::data_.size().
+ int64_t data_size_;
+
+ // True if there is a call to the background pruning outstanding.
+ bool background_pruning_pending_;
+
+ // The LRU should contain all blocks which are not pinned from
+ // all multibuffers.
+ LRU<GlobalBlockId> lru_;
+
+ // Where we run our tasks.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ };
+
+ MultiBuffer(int32_t block_size_shift,
+ const scoped_refptr<GlobalLRU>& global_lru);
+ MultiBuffer(const MultiBuffer&) = delete;
+ MultiBuffer& operator=(const MultiBuffer&) = delete;
+ virtual ~MultiBuffer();
+
+ // Identifies a block in the cache.
+ // Block numbers can be calculated from byte positions as:
+ // block_num = byte_pos >> block_size_shift
+ typedef MultiBufferBlockId BlockId;
+ typedef std::unordered_map<BlockId, scoped_refptr<media::DataBuffer>> DataMap;
+
+ // Registers a reader at the given position.
+ // If the cache does not already contain |pos|, it will activate
+ // or create data providers to make sure that the block becomes
+ // available soon. If |pos| is already in the cache, no action is
+ // taken, it simply lets the cache know that this reader is likely
+ // to read pos+1, pos+2.. soon.
+ //
+ // Registered readers will be notified when the available range
+ // at their position changes. The available range at |pos| is a range
+ // from A to B where: A <= |pos|, B >= |pos| and all blocks in [A..B)
+ // are present in the cache. When this changes, we will call
+ // NotifyAvailableRange() on the reader.
+ void AddReader(const BlockId& pos, Reader* reader);
+
+ // Unregister a reader at block |pos|.
+ // Often followed by a call to AddReader(pos + 1, ...);
+ // Idempotent.
+ void RemoveReader(const BlockId& pos, Reader* reader);
+
+ // Immediately remove writers at or before |pos| if nobody needs them.
+ // Note that we can't really do this in StopWaitFor(), because it's very
+ // likely that StopWaitFor() is immediately followed by a call to WaitFor().
+ // It is also a bad idea to wait for the writers to clean themselves up when
+ // they try to provide unwanted data to the cache. Besides the obvoius
+ // inefficiency, it will also cause the http_cache to bypass the disk/memory
+ // cache if we have multiple simultaneous requests going against the same
+ // url.
+ void CleanupWriters(const BlockId& pos);
+
+ // Returns true if block |pos| is available in the cache.
+ bool Contains(const BlockId& pos) const;
+
+ // Returns the next unavailable block at or after |pos|.
+ BlockId FindNextUnavailable(const BlockId& pos) const;
+
+ // Change the pin count for a range of data blocks.
+ // Note that blocks do not have to be present in the
+ // cache to be pinned.
+ // Examples:
+ // Pin block 3, 4 & 5: PinRange(3, 6, 1);
+ // Unpin block 4 & 5: PinRange(4, 6, -1);
+ void PinRange(const BlockId& from, const BlockId& to, int32_t how_much);
+
+ // Calls PinRange for each range in |ranges|, convenience
+ // function for applying multiple changes to the pinned ranges.
+ void PinRanges(const IntervalMap<BlockId, int32_t>& ranges);
+
+ // Returns a continous (but possibly empty) list of blocks starting at
+ // |from| up to, but not including |to|. This function is thread safe.
+ void GetBlocksThreadsafe(
+ const BlockId& from,
+ const BlockId& to,
+ std::vector<scoped_refptr<media::DataBuffer>>* output);
+
+ // Increment max cache size by |size| (counted in blocks).
+ void IncrementMaxSize(int32_t size);
+
+ // Returns how many bytes have been received by the data providers at position
+ // |block|, which have not yet been submitted to the multibuffer cache.
+ // The returned number should be less than the size of one block.
+ int64_t UncommittedBytesAt(const BlockId& block);
+
+ // Caller takes ownership of 'provider', cache will
+ // not call it anymore.
+ std::unique_ptr<DataProvider> RemoveProvider(DataProvider* provider);
+
+ // Add a writer to this cache. Cache takes ownership, and may
+ // destroy |provider| later. (Not during this call.)
+ void AddProvider(std::unique_ptr<DataProvider> provider);
+
+ // Transfer all data from |other| to this.
+ void MergeFrom(MultiBuffer* other);
+
+ // Accessors.
+ const DataMap& map() const { return data_; }
+ int32_t block_size_shift() const { return block_size_shift_; }
+
+ // Setters.
+ void SetIsClientAudioElement(bool is_client_audio_element) {
+ is_client_audio_element_ = is_client_audio_element;
+ }
+
+ // Callback which notifies us that a data provider has
+ // some data for us. Also called when it might be appropriate
+ // for a provider in a deferred state to wake up.
+ void OnDataProviderEvent(DataProvider* provider);
+
+ protected:
+ // Create a new writer at |pos| and return it.
+ // Users needs to implemement this method.
+ virtual std::unique_ptr<DataProvider> CreateWriter(
+ const BlockId& pos,
+ bool is_client_audio_element) = 0;
+
+ virtual bool RangeSupported() const = 0;
+
+ // Called when the cache becomes empty. Implementations can use this
+ // as a signal for when we should free this object and any metadata
+ // that goes with it.
+ virtual void OnEmpty();
+
+ private:
+ // For testing.
+ friend class TestMultiBuffer;
+
+ enum ProviderState {
+ ProviderStateDead,
+ ProviderStateDefer,
+ ProviderStateLoad
+ };
+
+ // Can be overriden for testing.
+ virtual void Prune(size_t max_to_free);
+
+ // Remove the given blocks from the multibuffer, called from
+ // GlobalLRU::Prune().
+ void ReleaseBlocks(const std::vector<MultiBufferBlockId>& blocks);
+
+ // Figure out what state a writer at |pos| should be in.
+ ProviderState SuggestProviderState(const BlockId& pos) const;
+
+ // Returns true if a writer at |pos| is colliding with
+ // output of another writer.
+ bool ProviderCollision(const BlockId& pos) const;
+
+ // Call NotifyAvailableRange(new_range) on all readers waiting
+ // for a block in |observer_range|
+ void NotifyAvailableRange(const Interval<MultiBufferBlockId>& observer_range,
+ const Interval<MultiBufferBlockId>& new_range);
+
+ // Max number of blocks.
+ int64_t max_size_;
+
+ // log2 of block size.
+ int32_t block_size_shift_;
+
+ // Is the client an audio element?
+ bool is_client_audio_element_ = false;
+
+ // Stores the actual data.
+ DataMap data_;
+
+ // protects data_
+ // Note that because data_ is only modified on the a single thread,
+ // we don't need to lock this if we're reading data from the same thread.
+ // Instead, we only lock this when:
+ // * modifying data_
+ // * reading data_ from another thread
+ base::Lock data_lock_;
+
+ // Keeps track of readers waiting for data.
+ std::map<MultiBufferBlockId, std::set<Reader*>> readers_;
+
+ // Keeps track of writers by their position.
+ // The writers are owned by this class.
+ std::map<BlockId, std::unique_ptr<DataProvider>> writer_index_;
+
+ // Gloabally shared LRU, decides which block to free next.
+ scoped_refptr<GlobalLRU> lru_;
+
+ // Keeps track of what blocks are pinned. If block p is pinned,
+ // then pinned_[p] > 0. Pinned blocks cannot be freed and should not
+ // be present in |lru_|.
+ IntervalMap<BlockId, int32_t> pinned_;
+
+ // present_[block] should be 1 for all blocks that are present
+ // and 0 for all blocks that are not. Used to quickly figure out
+ // ranges of available/unavailable blocks without iterating.
+ IntervalMap<BlockId, int32_t> present_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_MULTI_BUFFER_H_
diff --git a/chromium/third_party/blink/public/platform/media/multi_buffer_data_source.h b/chromium/third_party/blink/public/platform/media/multi_buffer_data_source.h
new file mode 100644
index 00000000000..274308e54f2
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/multi_buffer_data_source.h
@@ -0,0 +1,300 @@
+// 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_PUBLIC_PLATFORM_MEDIA_MULTI_BUFFER_DATA_SOURCE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_MULTI_BUFFER_DATA_SOURCE_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "media/base/data_source.h"
+#include "media/base/ranges.h"
+#include "media/base/tuneable.h"
+#include "third_party/blink/public/platform/media/url_index.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+class GURL;
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace media {
+class MediaLog;
+}
+
+namespace blink {
+class BufferedDataSourceHost;
+class MultiBufferReader;
+
+// A data source capable of loading URLs and buffering the data using an
+// in-memory sliding window.
+//
+// MultiBufferDataSource must be created and destroyed on the thread associated
+// with the |task_runner| passed in the constructor.
+class BLINK_PLATFORM_EXPORT MultiBufferDataSource : public media::DataSource {
+ public:
+ using DownloadingCB = base::RepeatingCallback<void(bool)>;
+ using RedirectCB = base::RepeatingCallback<void()>;
+
+ // Used to specify video preload states. They are "hints" to the browser about
+ // how aggressively the browser should load and buffer data.
+ // Please see the HTML5 spec for the descriptions of these values:
+ // http://www.w3.org/TR/html5/video.html#attr-media-preload
+ //
+ // Enum values must match the values in WebMediaPlayer::Preload and
+ // there will be assertions at compile time if they do not match.
+ enum Preload {
+ NONE,
+ METADATA,
+ AUTO,
+ };
+
+ // |url| and |cors_mode| are passed to the object. Buffered byte range changes
+ // will be reported to |host|. |downloading_cb| will be called whenever the
+ // downloading/paused state of the source changes.
+ MultiBufferDataSource(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ scoped_refptr<UrlData> url_data,
+ media::MediaLog* media_log,
+ BufferedDataSourceHost* host,
+ DownloadingCB downloading_cb);
+ MultiBufferDataSource(const MultiBufferDataSource&) = delete;
+ MultiBufferDataSource& operator=(const MultiBufferDataSource&) = delete;
+ ~MultiBufferDataSource() override;
+
+ // Executes |init_cb| with the result of initialization when it has completed.
+ //
+ // Method called on the render thread.
+ using InitializeCB = base::OnceCallback<void(bool)>;
+ void Initialize(InitializeCB init_cb);
+
+ // Adjusts the buffering algorithm based on the given preload value.
+ void SetPreload(Preload preload);
+
+ // Returns true if the media resource has a single origin, false otherwise.
+ // Only valid to call after Initialize() has completed.
+ //
+ // Method called on the render thread.
+ bool HasSingleOrigin();
+
+ // https://html.spec.whatwg.org/#cors-cross-origin
+ // This must be called after the response arrives.
+ bool IsCorsCrossOrigin() const;
+
+ // Provides a callback to be run when the underlying url is redirected.
+ void OnRedirect(RedirectCB callback);
+
+ // Returns true if the response includes an Access-Control-Allow-Origin
+ // header (that is not "null").
+ bool HasAccessControl() const;
+
+ // Returns the CorsMode of the underlying UrlData.
+ UrlData::CorsMode cors_mode() const;
+
+ // Notifies changes in playback state for controlling media buffering
+ // behavior.
+ void MediaPlaybackRateChanged(double playback_rate);
+ void MediaIsPlaying();
+ bool media_has_played() const;
+
+ // Returns true if the resource is local.
+ bool AssumeFullyBuffered() const override;
+
+ // Cancels any open network connections once reaching the deferred state. If
+ // |always_cancel| is false this is done only for preload=metadata, non-
+ // streaming resources that have not started playback. If |always_cancel| is
+ // true, all resource types will have their connections canceled. If already
+ // deferred, connections will be immediately closed.
+ void OnBufferingHaveEnough(bool always_cancel);
+
+ int64_t GetMemoryUsage() override;
+
+ GURL GetUrlAfterRedirects() const;
+
+ // media::DataSource implementation.
+ // Called from demuxer thread.
+ void Stop() override;
+ void Abort() override;
+
+ void Read(int64_t position,
+ int size,
+ uint8_t* data,
+ media::DataSource::ReadCB read_cb) override;
+ bool GetSize(int64_t* size_out) override WARN_UNUSED_RESULT;
+ bool IsStreaming() override;
+ void SetBitrate(int bitrate) override;
+ void SetIsClientAudioElement(bool is_client_audio_element) {
+ is_client_audio_element_ = is_client_audio_element;
+ }
+
+ bool cancel_on_defer_for_testing() const { return cancel_on_defer_; }
+
+ protected:
+ void OnRedirected(const scoped_refptr<UrlData>& new_destination);
+
+ // A factory method to create a BufferedResourceLoader based on the read
+ // parameters.
+ void CreateResourceLoader(int64_t first_byte_position,
+ int64_t last_byte_position);
+
+ // Same as above, but called with |lock_| held.
+ void CreateResourceLoader_Locked(int64_t first_byte_position,
+ int64_t last_byte_position);
+
+ // Set reader_ while asserting proper locking.
+ void SetReader(MultiBufferReader* reader);
+
+ friend class MultiBufferDataSourceTest;
+
+ // Task posted to perform actual reading on the render thread.
+ void ReadTask();
+
+ // After a read, this function updates the read position.
+ // It's in a separate function because the read itself can either happen
+ // in ReadTask() or in Read(), both of which call this function afterwards.
+ void SeekTask_Locked();
+
+ // Lock |lock_| lock and call SeekTask_Locked().
+ // Called with PostTask when read() complets on the demuxer thread.
+ void SeekTask();
+
+ // Cancels oustanding callbacks and sets |stop_signal_received_|. Safe to call
+ // from any thread.
+ void StopInternal_Locked();
+
+ // Stops |reader_| if present. Used by Abort() and Stop().
+ void StopLoader();
+
+ // Tells |reader_| the bitrate of the media.
+ void SetBitrateTask(int bitrate);
+
+ // BufferedResourceLoader::Start() callback for initial load.
+ void StartCallback();
+
+ // Check if we've moved to a new url and update has_signgle_origin_.
+ void UpdateSingleOrigin();
+
+ // MultiBufferReader progress callback.
+ void ProgressCallback(int64_t begin, int64_t end);
+
+ // Update progress based on current reader state.
+ void UpdateProgress();
+
+ // call downloading_cb_ if needed.
+ // If |force_loading| is true, we call downloading_cb_ and tell it that
+ // we are currently loading, regardless of what reader_->IsLoading() says.
+ // Caller must hold |lock_|.
+ void UpdateLoadingState_Locked(bool force_loading);
+
+ // Update |reader_|'s preload and buffer settings.
+ void UpdateBufferSizes();
+
+ // The total size of the resource. Set during StartCallback() if the size is
+ // known, otherwise it will remain kPositionNotSpecified until the size is
+ // determined by reaching EOF.
+ int64_t total_bytes_;
+
+ // Bytes we've read but not reported to the url_data yet.
+ // SeekTask handles the reporting.
+ int64_t bytes_read_ = 0;
+
+ // Places we might want to seek to. After each read we add another
+ // location here, and when SeekTask() is called, it picks the best
+ // position and then clears it out.
+ std::vector<int64_t> seek_positions_;
+
+ // This value will be true if this data source can only support streaming.
+ // i.e. range request is not supported.
+ bool streaming_;
+
+ // This is the loading state that we last reported to our owner through
+ // |downloading_cb_|.
+ bool loading_;
+
+ // True if a failure has occured.
+ bool failed_;
+
+ // The task runner of the render thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_;
+
+ // URL of the resource requested.
+ scoped_refptr<UrlData> url_data_;
+
+ // A resource reader for the media resource.
+ std::unique_ptr<MultiBufferReader> reader_;
+
+ // Callback method from the pipeline for initialization.
+ InitializeCB init_cb_;
+
+ // Read parameters received from the Read() method call. Must be accessed
+ // under |lock_|.
+ class ReadOperation;
+ std::unique_ptr<ReadOperation> read_op_;
+
+ // Protects |stop_signal_received_|, |read_op_|, |reader_| and |total_bytes_|.
+ base::Lock lock_;
+
+ // Whether we've been told to stop via Abort() or Stop().
+ bool stop_signal_received_;
+
+ // This variable is true when the user has requested the video to play at
+ // least once.
+ bool media_has_played_;
+
+ // As we follow redirects, we set this variable to false if redirects
+ // go between different origins.
+ bool single_origin_;
+
+ // Callback used when a redirect occurs.
+ RedirectCB redirect_cb_;
+
+ // Close the connection when we have enough data.
+ bool cancel_on_defer_;
+
+ // This variable holds the value of the preload attribute for the video
+ // element.
+ Preload preload_;
+
+ // Bitrate of the content, 0 if unknown.
+ int bitrate_;
+
+ // Current playback rate.
+ double playback_rate_;
+
+ media::MediaLog* media_log_;
+
+ bool is_client_audio_element_ = false;
+
+ int buffer_size_update_counter_;
+
+ // Host object to report buffered byte range changes to.
+ BufferedDataSourceHost* host_;
+
+ DownloadingCB downloading_cb_;
+
+ // Preload this many seconds of data by default.
+ media::Tuneable<int> preload_seconds_ = {"SrcMediaMultiBufferPreloadSeconds",
+ 0, 10, 60};
+
+ // Keep this many seconds of data for going back by default.
+ media::Tuneable<int> keep_after_playback_seconds_ = {
+ "SrcMediaMultiBufferKeepAfterPlaybackSeconds", 0, 2, 60};
+
+ // Disallow rebinding WeakReference ownership to a different thread by keeping
+ // a persistent reference. This avoids problems with the thread-safety of
+ // reaching into this class from multiple threads to attain a WeakPtr.
+ base::WeakPtr<MultiBufferDataSource> weak_ptr_;
+ base::WeakPtrFactory<MultiBufferDataSource> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_MULTI_BUFFER_DATA_SOURCE_H_
diff --git a/chromium/third_party/blink/public/platform/media/power_status_helper.h b/chromium/third_party/blink/public/platform/media/power_status_helper.h
new file mode 100644
index 00000000000..6467d5af33b
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/power_status_helper.h
@@ -0,0 +1,151 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_POWER_STATUS_HELPER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_POWER_STATUS_HELPER_H_
+
+#include "base/callback.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+#include "media/base/video_codecs.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/device/public/mojom/battery_monitor.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+struct PipelineMetadata;
+}
+
+namespace blink {
+
+// Class to monitor for power events during playback and record them to UMA/UKM.
+class BLINK_PLATFORM_EXPORT PowerStatusHelper {
+ public:
+ using CreateBatteryMonitorCB = base::RepeatingCallback<
+ mojo::PendingRemote<device::mojom::BatteryMonitor>()>;
+
+ // Bits used to construct UMA buckets.
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum /* not class */ Bits {
+ // Bit layout is: [msb] xx f F RR CC [lsb]
+ // R == resolution
+ // C == codec
+ // F == frame rate
+ // f == full screen
+ // x == unused
+ // Remember that we can't use more than 6 bits, since we shouldn't go over
+ // 100 UMA buckets.
+
+ // Codec bits, values 0x00 to 0x03
+ // Named "CodecBits" to prevent a name collision with media::VideoCodec.
+ kCodecBitsH264 = (0x00) << 0,
+ kCodecBitsVP9Profile0 = (0x01) << 0,
+ // Ignore Profile1
+ kCodecBitsVP9Profile2 = (0x02) << 0,
+ // TODO(liberato): add AV1
+
+ // Resolution bits, values 0x00 to 0x03
+ kResolution360p = (0x00) << 2,
+ kResolution720p = (0x01) << 2,
+ kResolution1080p = (0x02) << 2,
+
+ // Frame rate bits, values 0x00 to 0x01
+ kFrameRate30 = (0x00) << 4,
+ kFrameRate60 = (0x01) << 4,
+
+ // Fullscreen bits, values 0x00 to 0x01
+ kFullScreenNo = (0x00) << 5,
+ kFullScreenYes = (0x01) << 5,
+
+ // This is not a valid bit for, you know, testing.
+ kNotAValidBitForTesting = (0x01) << 10,
+ };
+
+ // If |stats_cb| is not provided, then we'll record to UMA. It's just for
+ // the tests.
+ explicit PowerStatusHelper(CreateBatteryMonitorCB create_battery_monitor_cb);
+ PowerStatusHelper(const PowerStatusHelper&) = delete;
+ PowerStatusHelper& operator=(const PowerStatusHelper&) = delete;
+ ~PowerStatusHelper();
+
+ // Notify us about changes to the player.
+ void SetIsPlaying(bool is_playing);
+ void SetMetadata(const media::PipelineMetadata& metadata);
+ void SetIsFullscreen(bool is_fullscreen);
+ void SetAverageFrameRate(absl::optional<int> average_fps);
+
+ // Handle notifications about the experiment state from the power experiment.
+ // manager. |state| indicates whether our player is eligible to record power
+ // experiments readings.
+ void UpdatePowerExperimentState(bool state);
+
+ private:
+ friend class PowerStatusHelperTest;
+ friend class PowerStatusHelperBucketTest;
+
+ // Return the UMA bucket for the given video configuration, or nullopt if we
+ // don't want to record it.
+ static absl::optional<int> BucketFor(bool is_playing,
+ bool has_video,
+ media::VideoCodec codec,
+ media::VideoCodecProfile profile,
+ gfx::Size natural_size,
+ bool is_fullscreen,
+ absl::optional<int> average_fps);
+
+ // Return the histogram names. Here so that tests can find them too.
+ static const char* BatteryDeltaHistogram();
+ static const char* ElapsedTimeHistogram();
+
+ // Recompute everything when playback state or power experiment state changes.
+ void OnAnyStateChange();
+
+ // Handle updates about the current battery status.
+ void OnBatteryStatus(device::mojom::BatteryStatusPtr battery_status);
+
+ // Start monitoring if we haven't already. Any outstanding callbacks will be
+ // cancelled if monitoring was already in progress.
+ void StartMonitoring();
+ void StopMonitoring();
+
+ // Register to receive a power update the next time it changes.
+ void QueryNextStatus();
+
+ CreateBatteryMonitorCB create_battery_monitor_cb_;
+
+ // Most recent parameters we were given.
+ bool is_playing_ = false;
+ bool has_video_ = false;
+ media::VideoCodec codec_ = media::VideoCodec::kUnknownVideoCodec;
+ media::VideoCodecProfile profile_ =
+ media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
+ gfx::Size natural_size_;
+ bool is_fullscreen_ = false;
+ // For estimating fps. Can be unset if we don't know.
+ absl::optional<int> average_fps_;
+
+ // Current UMA bucket, if any.
+ absl::optional<int> current_bucket_;
+
+ // If set, our previous battery level, from 0-100.
+ absl::optional<float> battery_level_baseline_;
+ // The time at which we last got an update from |battery_monitor_|.
+ base::TimeTicks last_update_;
+
+ // Are we currently the player that should be recording power for the power
+ // experiment, according to the MediaPowerExperimentManager?
+ bool experiment_state_ = false;
+
+ mojo::Remote<device::mojom::BatteryMonitor> battery_monitor_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_POWER_STATUS_HELPER_H_
diff --git a/chromium/third_party/blink/public/platform/media/remote_playback_client_wrapper_impl.h b/chromium/third_party/blink/public/platform/media/remote_playback_client_wrapper_impl.h
new file mode 100644
index 00000000000..6151b9963ab
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/remote_playback_client_wrapper_impl.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_PUBLIC_PLATFORM_MEDIA_REMOTE_PLAYBACK_CLIENT_WRAPPER_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_REMOTE_PLAYBACK_CLIENT_WRAPPER_IMPL_H_
+
+#include <string>
+
+#include "media/renderers/remote_playback_client_wrapper.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace blink {
+class WebMediaPlayerClient;
+class WebRemotePlaybackClient;
+
+// Wraps a WebRemotePlaybackClient to expose only the methods used by the
+// FlingingRendererClientFactory. This avoids dependencies on the blink layer.
+class BLINK_PLATFORM_EXPORT RemotePlaybackClientWrapperImpl
+ : public media::RemotePlaybackClientWrapper {
+ public:
+ explicit RemotePlaybackClientWrapperImpl(WebMediaPlayerClient* client);
+ ~RemotePlaybackClientWrapperImpl() override;
+
+ std::string GetActivePresentationId() override;
+
+ private:
+ WebRemotePlaybackClient* remote_playback_client_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_REMOTE_PLAYBACK_CLIENT_WRAPPER_IMPL_H_
diff --git a/chromium/third_party/blink/public/platform/media/resource_fetch_context.h b/chromium/third_party/blink/public/platform/media/resource_fetch_context.h
new file mode 100644
index 00000000000..c065b3918a0
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/resource_fetch_context.h
@@ -0,0 +1,27 @@
+// 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_PUBLIC_PLATFORM_MEDIA_RESOURCE_FETCH_CONTEXT_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_RESOURCE_FETCH_CONTEXT_H_
+
+#include <memory>
+
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/web_associated_url_loader.h"
+#include "third_party/blink/public/web/web_associated_url_loader_options.h"
+
+namespace blink {
+
+class BLINK_PLATFORM_EXPORT ResourceFetchContext {
+ public:
+ virtual ~ResourceFetchContext() {}
+
+ virtual std::unique_ptr<WebAssociatedURLLoader> CreateUrlLoader(
+ const WebAssociatedURLLoaderOptions& options) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_RESOURCE_FETCH_CONTEXT_H_
diff --git a/chromium/third_party/blink/public/platform/media/smoothness_helper.h b/chromium/third_party/blink/public/platform/media/smoothness_helper.h
new file mode 100644
index 00000000000..caf2d3390f8
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/smoothness_helper.h
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_SMOOTHNESS_HELPER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_SMOOTHNESS_HELPER_H_
+
+#include <memory>
+
+#include "media/base/buffering_state.h"
+#include "media/base/pipeline_status.h"
+#include "media/learning/common/labelled_example.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace media {
+namespace learning {
+class LearningTaskController;
+}
+} // namespace media
+
+namespace blink {
+
+// Helper class to construct learning observations about the smoothness of a
+// video playback. Currently measures the worst-case frame drop ratio observed
+// among fixed-length segments.
+class BLINK_PLATFORM_EXPORT SmoothnessHelper {
+ public:
+ // Callback that provides the number of dropped / decoded frames since some
+ // point in the past. We assume that these values are comparable during
+ // playback, so that we can compute deltas.
+ class Client {
+ public:
+ virtual ~Client() {}
+
+ virtual unsigned DecodedFrameCount() const = 0;
+ virtual unsigned DroppedFrameCount() const = 0;
+ };
+
+ virtual ~SmoothnessHelper();
+
+ // Return the features that we were constructed with.
+ const media::learning::FeatureVector& features() const { return features_; }
+
+ // Notify us that an NNR has occurred.
+ virtual void NotifyNNR() = 0;
+
+ // |features| are the features that we'll use for any labelled examples that
+ // we create. They should be features that could be captured at the time a
+ // prediction would be needed.
+ static std::unique_ptr<SmoothnessHelper> Create(
+ std::unique_ptr<media::learning::LearningTaskController> bad_controller,
+ std::unique_ptr<media::learning::LearningTaskController> nnr_controller,
+ const media::learning::FeatureVector& features,
+ Client* player);
+
+ // We split playbacks up into |kSegmentSize| units, and record the worst
+ // dropped frame ratio over all segments of a playback. A playback is not
+ // recorded if it doesn't contain at least one full segment.
+ static base::TimeDelta SegmentSizeForTesting();
+
+ protected:
+ SmoothnessHelper(const media::learning::FeatureVector& features);
+
+ media::learning::FeatureVector features_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_SMOOTHNESS_HELPER_H_
diff --git a/chromium/third_party/blink/public/platform/media/url_index.h b/chromium/third_party/blink/public/platform/media/url_index.h
new file mode 100644
index 00000000000..e777caf4fdc
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/url_index.h
@@ -0,0 +1,313 @@
+// 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_PUBLIC_PLATFORM_MEDIA_URL_INDEX_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_URL_INDEX_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <deque>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/public/platform/media/multi_buffer.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "url/gurl.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+
+const int64_t kPositionNotSpecified = -1;
+
+class ResourceFetchContext;
+class UrlData;
+class UrlIndexTest;
+
+// A multibuffer for loading media resources which knows
+// how to create MultiBufferDataProviders to load data
+// into the cache.
+class BLINK_PLATFORM_EXPORT ResourceMultiBuffer : public MultiBuffer {
+ public:
+ ResourceMultiBuffer(UrlData* url_data_,
+ int block_shift,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~ResourceMultiBuffer() override;
+
+ // MultiBuffer implementation.
+ std::unique_ptr<MultiBuffer::DataProvider> CreateWriter(
+ const BlockId& pos,
+ bool is_client_audio_element) override;
+ bool RangeSupported() const override;
+ void OnEmpty() override;
+
+ protected:
+ // Do not access from destructor, it is a pointer to the
+ // object that contains us.
+ UrlData* url_data_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class UrlIndex;
+
+// All the data & metadata for a single resource.
+// Data is cached using a MultiBuffer instance.
+class BLINK_PLATFORM_EXPORT UrlData : public base::RefCounted<UrlData> {
+ public:
+ // Keep in sync with WebMediaPlayer::CorsMode.
+ enum CorsMode { CORS_UNSPECIFIED, CORS_ANONYMOUS, CORS_USE_CREDENTIALS };
+ using KeyType = std::pair<GURL, CorsMode>;
+
+ UrlData(const UrlData&) = delete;
+ UrlData& operator=(const UrlData&) = delete;
+
+ // Accessors
+ const GURL& url() const { return url_; }
+
+ // Cross-origin access mode
+ CorsMode cors_mode() const { return cors_mode_; }
+
+ bool has_access_control() const { return has_access_control_; }
+
+ // Are HTTP range requests supported?
+ bool range_supported() const { return range_supported_; }
+
+ // True if we found a reason why this URL won't be stored in the
+ // HTTP disk cache.
+ bool cacheable() const { return cacheable_; }
+
+ // Last used time.
+ base::Time last_used() const { return last_used_; }
+
+ // Last modified time.
+ base::Time last_modified() const { return last_modified_; }
+
+ const std::string& etag() const { return etag_; }
+
+ // Expiration time.
+ base::Time valid_until() const { return valid_until_; }
+
+ // The key used by UrlIndex to find this UrlData.
+ KeyType key() const;
+
+ // Length of data associated with url or |kPositionNotSpecified|
+ int64_t length() const { return length_; }
+
+ // Returns the number of blocks cached for this resource.
+ size_t CachedSize();
+
+ // Returns true if this resource is fully cached in memory.
+ bool FullyCached();
+
+ // Returns our url_index.
+ UrlIndex* url_index() const { return url_index_; }
+
+ // This must be called after the response arrives.
+ bool is_cors_cross_origin() const { return is_cors_cross_origin_; }
+
+ // Notifies the url index that this is currently used.
+ // The url <-> URLData mapping will be eventually be invalidated if
+ // this is not called regularly.
+ void Use();
+
+ // Call this before we add some data to the multibuffer().
+ // If the multibuffer is empty, the data origin is set from
+ // |origin| and returns true. If not, it compares |origin|
+ // to the previous origin and returns whether they match or not.
+ bool ValidateDataOrigin(const GURL& origin);
+
+ // Setters.
+ void set_length(int64_t length);
+ void set_cacheable(bool cacheable);
+ void set_valid_until(base::Time valid_until);
+ void set_range_supported();
+ void set_last_modified(base::Time last_modified);
+ void set_etag(const std::string& etag);
+ void set_is_cors_cross_origin(bool is_cors_cross_origin);
+ void set_has_access_control();
+
+ // A redirect has occurred (or we've found a better UrlData for the same
+ // resource).
+ void RedirectTo(const scoped_refptr<UrlData>& to);
+
+ // Fail, tell all clients that a failure has occurred.
+ void Fail();
+
+ // Callback for receiving notifications when a redirect occurs.
+ using RedirectCB = base::OnceCallback<void(const scoped_refptr<UrlData>&)>;
+
+ // Register a callback to be called when a redirect occurs.
+ // Callbacks are cleared when a redirect occurs, so clients must call
+ // OnRedirect again if they wish to continue receiving callbacks.
+ void OnRedirect(RedirectCB cb);
+
+ // Returns true it is valid to keep using this to access cached data.
+ // A single media player instance may choose to ignore this for resources
+ // that have already been opened.
+ bool Valid();
+
+ // Virtual so we can override it for testing.
+ virtual ResourceMultiBuffer* multibuffer();
+
+ void AddBytesRead(int64_t b) { bytes_read_from_cache_ += b; }
+ int64_t BytesReadFromCache() const { return bytes_read_from_cache_; }
+
+ protected:
+ UrlData(const GURL& url,
+ CorsMode cors_mode,
+ UrlIndex* url_index,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ virtual ~UrlData();
+
+ private:
+ friend class ResourceMultiBuffer;
+ friend class UrlIndex;
+ friend class UrlIndexTest;
+ friend class base::RefCounted<UrlData>;
+
+ void OnEmpty();
+ void MergeFrom(const scoped_refptr<UrlData>& other);
+
+ // Url we represent, note that there may be multiple UrlData for
+ // the same url.
+ const GURL url_;
+
+ // Origin of the data, should only be different from the url_.GetOrigin()
+ // when service workers are involved.
+ GURL data_origin_;
+ bool have_data_origin_;
+
+ // Cross-origin access mode.
+ const CorsMode cors_mode_;
+ bool has_access_control_;
+
+ UrlIndex* const url_index_;
+
+ // Length of resource this url points to. (in bytes)
+ int64_t length_;
+
+ // Number of bytes read from this resource.
+ int64_t bytes_read_from_cache_ = 0;
+
+ // Does the server support ranges?
+ bool range_supported_;
+
+ // Set to false if we have reason to believe the chrome disk cache
+ // will not cache this url.
+ bool cacheable_;
+
+ // https://html.spec.whatwg.org/#cors-cross-origin
+ bool is_cors_cross_origin_ = false;
+
+ // Last time some media time used this resource.
+ // Note that we use base::Time rather than base::TimeTicks because
+ // TimeTicks will stop advancing when a machine goes to sleep.
+ // base::Time can go backwards, jump hours at a time and be generally
+ // unpredictable, but it doesn't stop, which is preferable here.
+ // (False negatives are better than false positivies.)
+ base::Time last_used_;
+
+ // Expiration time according to http headers.
+ base::Time valid_until_;
+
+ // Last modification time according to http headers.
+ base::Time last_modified_;
+
+ // Etag from HTTP reply.
+ std::string etag_;
+
+ ResourceMultiBuffer multibuffer_;
+ std::vector<RedirectCB> redirect_callbacks_;
+
+ THREAD_CHECKER(thread_checker_);
+};
+
+// The UrlIndex lets you look up UrlData instances by url.
+class BLINK_PLATFORM_EXPORT UrlIndex {
+ public:
+ UrlIndex(ResourceFetchContext* fetch_context,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ UrlIndex(ResourceFetchContext* fetch_context,
+ int block_shift,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ virtual ~UrlIndex();
+
+ enum CacheMode { kNormal, kCacheDisabled };
+
+ // Look up an UrlData in the index and return it. If none is found,
+ // create a new one. Note that newly created UrlData entries are NOT
+ // added to the index, instead you must call TryInsert on them after
+ // initializing relevant parameters, like whether it support
+ // ranges and it's last modified time.
+ // Because the returned UrlData has a raw reference to |this|, it must be
+ // released before |this| is destroyed.
+ scoped_refptr<UrlData> GetByUrl(const GURL& gurl,
+ UrlData::CorsMode cors_mode,
+ CacheMode cache_mode);
+
+ // Add the given UrlData to the index if possible. If a better UrlData
+ // is already present in the index, return it instead. (If not, we just
+ // return the given UrlData.) Please make sure to initialize all the data
+ // that can be gathered from HTTP headers in |url_data| before calling this.
+ // In particular, the following fields are important:
+ // o range_supported: Entries which do not support ranges cannot be
+ // shared and are not added to the index.
+ // o valid_until, last_used: Entries have to be valid to be inserted
+ // into the index, this means that they have to have been recently
+ // used or have an Expires: header that says when they stop being valid.
+ // o last_modified: Expired cache entries can be re-used if last_modified
+ // matches.
+ // Because the returned UrlData has a raw reference to |this|, it must be
+ // released before |this| is destroyed.
+ // TODO(hubbe): Add etag support.
+ scoped_refptr<UrlData> TryInsert(const scoped_refptr<UrlData>& url_data);
+
+ ResourceFetchContext* fetch_context() const { return fetch_context_; }
+ int block_shift() const { return block_shift_; }
+
+ // Returns true kMaxParallelPreload or more urls are loading at the same time.
+ bool HasReachedMaxParallelPreload() const;
+
+ // Protected rather than private for testing.
+ protected:
+ friend class UrlData;
+ friend class ResourceMultiBuffer;
+ friend class UrlIndexTest;
+ void RemoveUrlData(const scoped_refptr<UrlData>& url_data);
+
+ // Virtual so we can override it in tests.
+ virtual scoped_refptr<UrlData> NewUrlData(const GURL& url,
+ UrlData::CorsMode cors_mode);
+
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+
+ ResourceFetchContext* fetch_context_;
+ using UrlDataMap = std::map<UrlData::KeyType, scoped_refptr<UrlData>>;
+ UrlDataMap indexed_data_;
+ scoped_refptr<MultiBuffer::GlobalLRU> lru_;
+
+ // log2 of block size in multibuffer cache. Defaults to kBlockSizeShift.
+ // Currently only changed for testing purposes.
+ const int block_shift_;
+
+ std::deque<scoped_refptr<UrlData>> loading_queue_;
+
+ base::MemoryPressureListener memory_pressure_listener_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_URL_INDEX_H_
diff --git a/chromium/third_party/blink/public/platform/media/video_frame_compositor.h b/chromium/third_party/blink/public/platform/media/video_frame_compositor.h
new file mode 100644
index 00000000000..538e987b3d8
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/video_frame_compositor.h
@@ -0,0 +1,296 @@
+// 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_PUBLIC_PLATFORM_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
+
+#include <utility>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "base/trace_event/auto_open_close_event.h"
+#include "cc/layers/surface_layer.h"
+#include "cc/layers/video_frame_provider.h"
+#include "media/base/video_renderer_sink.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_player.h"
+#include "third_party/blink/public/platform/web_video_frame_submitter.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace media {
+class VideoFrame;
+}
+
+namespace viz {
+class SurfaceId;
+}
+
+namespace blink {
+
+// VideoFrameCompositor acts as a bridge between the media and cc layers for
+// rendering video frames. I.e. a media::VideoRenderer will talk to this class
+// from the media side, while a cc::VideoFrameProvider::Client will talk to it
+// from the cc side.
+//
+// This class is responsible for requesting new frames from a video renderer in
+// response to requests from the VFP::Client. Since the VFP::Client may stop
+// issuing requests in response to visibility changes it is also responsible for
+// ensuring the "freshness" of the current frame for programmatic frame
+// requests; e.g., Canvas.drawImage() requests
+//
+// This class is also responsible for detecting frames dropped by the compositor
+// after rendering and signaling that information to a RenderCallback. It
+// detects frames not dropped by verifying each GetCurrentFrame() is followed
+// by a PutCurrentFrame() before the next UpdateCurrentFrame() call.
+//
+// VideoRenderSink::RenderCallback implementations must call Start() and Stop()
+// once new frames are expected or are no longer expected to be ready; this data
+// is relayed to the compositor to avoid extraneous callbacks.
+//
+// VideoFrameCompositor is also responsible for pumping UpdateCurrentFrame()
+// callbacks in the background when |client_| has decided to suspend them.
+//
+// VideoFrameCompositor must live on the same thread as the compositor, though
+// it may be constructed on any thread.
+class BLINK_PLATFORM_EXPORT VideoFrameCompositor
+ : public media::VideoRendererSink,
+ public cc::VideoFrameProvider {
+ public:
+ // Used to report back the time when the new frame has been processed.
+ using OnNewProcessedFrameCB = base::OnceCallback<void(base::TimeTicks)>;
+
+ using OnNewFramePresentedCB = base::OnceClosure;
+
+ enum UpdateType {
+ kNormal,
+ kBypassClient, // Disregards whether |client| is driving frame updates, and
+ // forces an attempt to update the frame.
+ };
+
+ // |task_runner| is the task runner on which this class will live,
+ // though it may be constructed on any thread.
+ VideoFrameCompositor(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ std::unique_ptr<WebVideoFrameSubmitter> submitter);
+
+ VideoFrameCompositor(const VideoFrameCompositor&) = delete;
+ VideoFrameCompositor& operator=(const VideoFrameCompositor&) = delete;
+
+ // Destruction must happen on the compositor thread; Stop() must have been
+ // called before destruction starts.
+ ~VideoFrameCompositor() override;
+
+ // Can be called from any thread.
+ cc::UpdateSubmissionStateCB GetUpdateSubmissionStateCallback();
+
+ // Signals the VideoFrameSubmitter to prepare to receive BeginFrames and
+ // submit video frames given by VideoFrameCompositor.
+ virtual void EnableSubmission(const viz::SurfaceId& id,
+ media::VideoTransformation rotation,
+ bool force_submit);
+
+ // cc::VideoFrameProvider implementation. These methods must be called on the
+ // |task_runner_|.
+ void SetVideoFrameProviderClient(
+ cc::VideoFrameProvider::Client* client) override;
+ bool UpdateCurrentFrame(base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max) override;
+ bool HasCurrentFrame() override;
+ scoped_refptr<media::VideoFrame> GetCurrentFrame() override;
+ void PutCurrentFrame() override;
+ base::TimeDelta GetPreferredRenderInterval() override;
+
+ // Returns |current_frame_|, without offering a guarantee as to how recently
+ // it was updated. In certain applications, one might need to periodically
+ // call UpdateCurrentFrameIfStale on |task_runner_| to drive the updates.
+ // Can be called from any thread.
+ virtual scoped_refptr<media::VideoFrame> GetCurrentFrameOnAnyThread();
+
+ // media::VideoRendererSink implementation. These methods must be called from
+ // the same thread (typically the media thread).
+ void Start(RenderCallback* callback) override;
+ void Stop() override;
+ void PaintSingleFrame(scoped_refptr<media::VideoFrame> frame,
+ bool repaint_duplicate_frame = false) override;
+
+ // If |client_| is not set, |callback_| is set, and |is_background_rendering_|
+ // is true, it requests a new frame from |callback_|. Uses the elapsed time
+ // between calls to this function as the render interval, defaulting to 16.6ms
+ // if no prior calls have been made. A cap of 250Hz (4ms) is in place to
+ // prevent clients from accidentally (or intentionally) spamming the rendering
+ // pipeline.
+ //
+ // This method is primarily to facilitate canvas and WebGL based applications
+ // where the <video> tag is invisible (possibly not even in the DOM) and thus
+ // does not receive a |client_|. In this case, frame acquisition is driven by
+ // the frequency of canvas or WebGL paints requested via JavaScript.
+ virtual void UpdateCurrentFrameIfStale(UpdateType type = UpdateType::kNormal);
+
+ // Sets the callback to be run when the new frame has been processed. The
+ // callback is only run once and then reset.
+ // Must be called on the compositor thread.
+ virtual void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb);
+
+ virtual void SetOnFramePresentedCallback(OnNewFramePresentedCB present_cb);
+
+ // Gets the metadata for the last frame that was presented to the compositor.
+ // Used to populate the VideoFrameMetadata of video.requestVideoFrameCallback
+ // callbacks. See https://wicg.github.io/video-rvfc/.
+ // Can be called on any thread.
+ virtual std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata>
+ GetLastPresentedFrameMetadata();
+
+ // Should be called when page visibility changes. Notifies |submitter_|.
+ virtual void SetIsPageVisible(bool is_visible);
+
+ // Notifies the |submitter_| that the frames must be submitted.
+ void SetForceSubmit(bool force_submit);
+
+ void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
+ }
+
+ // Enables or disables background rendering. If |enabled|, |timeout| is the
+ // amount of time to wait after the last Render() call before starting the
+ // background rendering mode. Note, this can not disable the background
+ // rendering call issues when a sink is started.
+ void set_background_rendering_for_testing(bool enabled) {
+ background_rendering_enabled_ = enabled;
+ }
+
+ void set_submitter_for_test(
+ std::unique_ptr<WebVideoFrameSubmitter> submitter) {
+ submitter_ = std::move(submitter);
+ }
+
+ private:
+ // TracingCategory name for |auto_open_close_|.
+ static constexpr const char kTracingCategory[] = "media,rail";
+
+ // Ran on the |task_runner_| to initialize |submitter_|;
+ void InitializeSubmitter();
+
+ // Signals the VideoFrameSubmitter to stop submitting frames. Sets whether the
+ // video surface is visible within the view port.
+ void SetIsSurfaceVisible(bool is_visible, base::WaitableEvent* done_event);
+
+ // Indicates whether the endpoint for the VideoFrame exists.
+ bool IsClientSinkAvailable();
+
+ // Called on the compositor thread in response to Start() or Stop() calls;
+ // must be used to change |rendering_| state.
+ void OnRendererStateUpdate(bool new_state);
+
+ // Handles setting of |current_frame_|.
+ bool ProcessNewFrame(scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks presentation_time,
+ bool repaint_duplicate_frame);
+
+ void SetCurrentFrame_Locked(scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks expected_display_time);
+
+ // Sets the ForceBeginFrames flag on |submitter_|, and resets
+ // |force_begin_frames_timer_|.
+ //
+ // The flag is used to keep receiving BeginFrame()/UpdateCurrentFrame() calls
+ // even if the video element is not visible, so websites can still use the
+ // requestVideoFrameCallback() API when the video is offscreen.
+ void StartForceBeginFrames();
+
+ // Called from |force_begin_frames_timer_| to unset the flag on |submitter_|.
+ void StopForceBeginFrames();
+
+ // Called by |background_rendering_timer_| when enough time elapses where we
+ // haven't seen a Render() call.
+ void BackgroundRender(
+ media::VideoRendererSink::RenderCallback::RenderingMode mode =
+ media::VideoRendererSink::RenderCallback::RenderingMode::kBackground);
+
+ // If |callback_| is available, calls Render() with the provided properties.
+ // Updates |is_background_rendering_|, |last_interval_|, and resets
+ // |background_rendering_timer_|. Returns true if there's a new frame
+ // available via GetCurrentFrame().
+ bool CallRender(base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max,
+ media::VideoRendererSink::RenderCallback::RenderingMode mode);
+
+ // Returns |last_interval_| without acquiring a lock.
+ // Can only be called from the compositor thread.
+ base::TimeDelta GetLastIntervalWithoutLock();
+
+ // This will run tasks on the compositor thread. If
+ // kEnableSurfaceLayerForVideo is enabled, it will instead run tasks on the
+ // media thread.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ const base::TickClock* tick_clock_;
+
+ // Allows tests to disable the background rendering task.
+ bool background_rendering_enabled_ = true;
+
+ // Manages UpdateCurrentFrame() callbacks if |client_| has stopped sending
+ // them for various reasons. Runs on |task_runner_| and is reset
+ // after each successful UpdateCurrentFrame() call.
+ base::RetainingOneShotTimer background_rendering_timer_;
+
+ // Calls StopForceBeginFrames() once we stop receiving calls to
+ // requestVideoFrameCallback() (or SetOnFramePresentedCallback() in our case).
+ base::RetainingOneShotTimer force_begin_frames_timer_;
+
+ // These values are only set and read on the compositor thread.
+ cc::VideoFrameProvider::Client* client_ = nullptr;
+ bool rendering_ = false;
+ bool rendered_last_frame_ = false;
+ bool is_background_rendering_ = false;
+ bool new_background_frame_ = false;
+
+ base::TimeTicks last_background_render_;
+ OnNewProcessedFrameCB new_processed_frame_cb_;
+ cc::UpdateSubmissionStateCB update_submission_state_callback_;
+
+ // Callback used to satisfy video.rVFC requests.
+ // Set on the main thread, fired on the compositor thread.
+ OnNewFramePresentedCB new_presented_frame_cb_ GUARDED_BY(current_frame_lock_);
+
+ // Set on the compositor thread, but also read on the media thread. Lock is
+ // not used when reading |current_frame_| on the compositor thread.
+ base::Lock current_frame_lock_;
+ scoped_refptr<media::VideoFrame> current_frame_;
+
+ // Used to fulfill video.requestVideoFrameCallback() calls.
+ // See https://wicg.github.io/video-rvfc/.
+ base::TimeTicks last_presentation_time_ GUARDED_BY(current_frame_lock_);
+ base::TimeTicks last_expected_display_time_ GUARDED_BY(current_frame_lock_);
+ uint32_t presentation_counter_ GUARDED_BY(current_frame_lock_) = 0u;
+
+ // These values are updated and read from the media and compositor threads.
+ base::Lock callback_lock_;
+ media::VideoRendererSink::RenderCallback* callback_
+ GUARDED_BY(callback_lock_) = nullptr;
+
+ // Assume 60Hz before the first UpdateCurrentFrame() call.
+ // Updated/read by the compositor thread, but also read on the media thread.
+ base::TimeDelta last_interval_ GUARDED_BY(callback_lock_) =
+ base::TimeDelta::FromSecondsD(1.0 / 60);
+
+ // AutoOpenCloseEvent for begin/end events.
+ std::unique_ptr<base::trace_event::AutoOpenCloseEvent<kTracingCategory>>
+ auto_open_close_;
+ std::unique_ptr<WebVideoFrameSubmitter> submitter_;
+
+ base::WeakPtrFactory<VideoFrameCompositor> weak_ptr_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
diff --git a/chromium/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h b/chromium/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h
new file mode 100644
index 00000000000..d005cc3dc7d
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h
@@ -0,0 +1,80 @@
+// 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_PUBLIC_PLATFORM_MEDIA_WEB_ENCRYPTED_MEDIA_CLIENT_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_WEB_ENCRYPTED_MEDIA_CLIENT_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/platform/media/key_system_config_selector.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_encrypted_media_client.h"
+
+namespace media {
+class CdmFactory;
+class MediaPermission;
+struct CdmConfig;
+} // namespace media
+
+namespace blink {
+class WebContentDecryptionModuleResult;
+class WebSecurityOrigin;
+struct WebMediaKeySystemConfiguration;
+
+class BLINK_PLATFORM_EXPORT WebEncryptedMediaClientImpl
+ : public WebEncryptedMediaClient {
+ public:
+ WebEncryptedMediaClientImpl(
+ media::CdmFactory* cdm_factory,
+ media::MediaPermission* media_permission,
+ std::unique_ptr<KeySystemConfigSelector::WebLocalFrameDelegate>
+ web_frame_delegate);
+ ~WebEncryptedMediaClientImpl() override;
+
+ // WebEncryptedMediaClient implementation.
+ void RequestMediaKeySystemAccess(WebEncryptedMediaRequest request) override;
+
+ // Create the CDM for |key_system| and |security_origin|. The caller owns
+ // the created cdm (passed back using |result|).
+ void CreateCdm(const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const media::CdmConfig& cdm_config,
+ std::unique_ptr<WebContentDecryptionModuleResult> result);
+
+ private:
+ // Report usage of key system to UMA. There are 2 different counts logged:
+ // 1. The key system is requested.
+ // 2. The requested key system and options are supported.
+ // Each stat is only reported once per renderer frame per key system.
+ class Reporter;
+
+ // Callback for `KeySystemConfigSelector::SelectConfig()`.
+ // `accumulated_configuration` and `cdm_config` are non-null iff `status` is
+ // `kSupported`.
+ void OnConfigSelected(
+ WebEncryptedMediaRequest request,
+ KeySystemConfigSelector::Status status,
+ WebMediaKeySystemConfiguration* accumulated_configuration,
+ media::CdmConfig* cdm_config);
+
+ // Gets the Reporter for |key_system|. If it doesn't already exist,
+ // create one.
+ Reporter* GetReporter(const WebString& key_system);
+
+ // Reporter singletons.
+ std::unordered_map<std::string, std::unique_ptr<Reporter>> reporters_;
+
+ media::CdmFactory* cdm_factory_;
+ KeySystemConfigSelector key_system_config_selector_;
+ base::WeakPtrFactory<WebEncryptedMediaClientImpl> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_WEB_ENCRYPTED_MEDIA_CLIENT_IMPL_H_
diff --git a/chromium/third_party/blink/public/platform/media/web_media_player_impl.h b/chromium/third_party/blink/public/platform/media/web_media_player_impl.h
new file mode 100644
index 00000000000..7d99b7f4aef
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/web_media_player_impl.h
@@ -0,0 +1,1047 @@
+// 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_PUBLIC_PLATFORM_MEDIA_WEB_MEDIA_PLAYER_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_WEB_MEDIA_PLAYER_IMPL_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/cancelable_callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "media/base/cdm_config.h"
+#include "media/base/encryption_scheme.h"
+#include "media/base/media_observer.h"
+#include "media/base/media_tracks.h"
+#include "media/base/overlay_info.h"
+#include "media/base/pipeline_impl.h"
+#include "media/base/renderer_factory_selector.h"
+#include "media/base/simple_watch_timer.h"
+#include "media/base/text_track.h"
+#include "media/mojo/mojom/playback_events_recorder.mojom.h"
+#include "media/renderers/paint_canvas_video_renderer.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/media_session/public/cpp/media_position.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/platform/media/buffered_data_source_host_impl.h"
+#include "third_party/blink/public/platform/media/learning_experiment_helper.h"
+#include "third_party/blink/public/platform/media/multi_buffer_data_source.h"
+#include "third_party/blink/public/platform/media/smoothness_helper.h"
+#include "third_party/blink/public/platform/media/video_frame_compositor.h"
+#include "third_party/blink/public/platform/media/web_media_player_params.h"
+#include "third_party/blink/public/platform/media/webmediaplayer_delegate.h"
+#include "third_party/blink/public/platform/web_audio_source_provider.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_result.h"
+#include "third_party/blink/public/platform/web_media_player.h"
+#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
+#include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
+#include "url/gurl.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+class TaskRunner;
+} // namespace base
+
+namespace cc {
+class VideoLayer;
+}
+
+namespace gfx {
+class Size;
+}
+
+namespace learning {
+class LearningTaskController;
+}
+
+namespace media {
+class CdmContextRef;
+class ChunkDemuxer;
+class MediaLog;
+class MemoryDumpProviderProxy;
+class PipelineController;
+} // namespace media
+
+namespace viz {
+class RasterContextProvider;
+}
+
+namespace blink {
+class PowerStatusHelper;
+class UrlIndex;
+class VideoDecodeStatsReporter;
+class VideoFrameCompositor;
+class WatchTimeReporter;
+class WebAudioSourceProviderImpl;
+class WebLocalFrame;
+class WebMediaPlayerClient;
+class WebMediaPlayerEncryptedMediaClient;
+
+// The canonical implementation of WebMediaPlayer that's backed by
+// Pipeline. Handles normal resource loading, Media Source, and
+// Encrypted Media.
+class BLINK_PLATFORM_EXPORT WebMediaPlayerImpl
+ : public WebMediaPlayer,
+ public WebMediaPlayerDelegate::Observer,
+ public media::Pipeline::Client,
+ public media::MediaObserverClient,
+ public WebSurfaceLayerBridgeObserver,
+ public SmoothnessHelper::Client {
+ public:
+ // Constructs a WebMediaPlayer implementation using Chromium's media stack.
+ // |delegate| and |renderer_factory_selector| must not be null.
+ WebMediaPlayerImpl(
+ WebLocalFrame* frame,
+ WebMediaPlayerClient* client,
+ WebMediaPlayerEncryptedMediaClient* encrypted_client,
+ WebMediaPlayerDelegate* delegate,
+ std::unique_ptr<media::RendererFactorySelector> renderer_factory_selector,
+ UrlIndex* url_index,
+ std::unique_ptr<VideoFrameCompositor> compositor,
+ std::unique_ptr<WebMediaPlayerParams> params);
+ WebMediaPlayerImpl(const WebMediaPlayerImpl&) = delete;
+ WebMediaPlayerImpl& operator=(const WebMediaPlayerImpl&) = delete;
+ ~WebMediaPlayerImpl() override;
+
+ // WebSurfaceLayerBridgeObserver implementation.
+ void OnWebLayerUpdated() override;
+ void RegisterContentsLayer(cc::Layer* layer) override;
+ void UnregisterContentsLayer(cc::Layer* layer) override;
+ void OnSurfaceIdUpdated(viz::SurfaceId surface_id) override;
+
+ WebMediaPlayer::LoadTiming Load(LoadType load_type,
+ const WebMediaPlayerSource& source,
+ CorsMode cors_mode,
+ bool is_cache_disabled) override;
+
+ // Playback controls.
+ void Play() override;
+ void Pause() override;
+ void Seek(double seconds) override;
+ void SetRate(double rate) override;
+ void SetVolume(double volume) override;
+ void SetLatencyHint(double seconds) override;
+ void SetPreservesPitch(bool preserves_pitch) override;
+ void SetAutoplayInitiated(bool autoplay_initiated) override;
+ void OnRequestPictureInPicture() override;
+ void OnTimeUpdate() override;
+ bool SetSinkId(const WebString& sink_id,
+ WebSetSinkIdCompleteCallback completion_callback) override;
+ void SetPoster(const WebURL& poster) override;
+ void SetPreload(WebMediaPlayer::Preload preload) override;
+ WebTimeRanges Buffered() const override;
+ WebTimeRanges Seekable() const override;
+
+ // paint() the current video frame into |canvas|. This is used to support
+ // various APIs and functionalities, including but not limited to: <canvas>,
+ // ImageBitmap, printing and capturing capabilities.
+ void Paint(cc::PaintCanvas* canvas,
+ const gfx::Rect& rect,
+ cc::PaintFlags& flags) override;
+ scoped_refptr<media::VideoFrame> GetCurrentFrame() override;
+ media::PaintCanvasVideoRenderer* GetPaintCanvasVideoRenderer() override;
+
+ // True if the loaded media has a playable video/audio track.
+ bool HasVideo() const override;
+ bool HasAudio() const override;
+
+ void EnabledAudioTracksChanged(
+ const WebVector<WebMediaPlayer::TrackId>& enabledTrackIds) override;
+ void SelectedVideoTrackChanged(
+ WebMediaPlayer::TrackId* selectedTrackId) override;
+
+ // Dimensions of the video.
+ gfx::Size NaturalSize() const override;
+
+ gfx::Size VisibleSize() const override;
+
+ // Getters of playback state.
+ bool Paused() const override;
+ bool Seeking() const override;
+ double Duration() const override;
+ virtual double timelineOffset() const;
+ double CurrentTime() const override;
+ bool IsEnded() const override;
+
+ bool PausedWhenHidden() const override;
+
+ // Internal states of loading and network.
+ // TODO(hclam): Ask the pipeline about the state rather than having reading
+ // them from members which would cause race conditions.
+ WebMediaPlayer::NetworkState GetNetworkState() const override;
+ WebMediaPlayer::ReadyState GetReadyState() const override;
+
+ WebMediaPlayer::SurfaceLayerMode GetVideoSurfaceLayerMode() const override;
+
+ WebString GetErrorMessage() const override;
+ bool DidLoadingProgress() override;
+ bool WouldTaintOrigin() const override;
+
+ double MediaTimeForTimeValue(double timeValue) const override;
+
+ unsigned DecodedFrameCount() const override;
+ unsigned DroppedFrameCount() const override;
+ uint64_t AudioDecodedByteCount() const override;
+ uint64_t VideoDecodedByteCount() const override;
+
+ void SetVolumeMultiplier(double multiplier) override;
+ void SetPersistentState(bool persistent) override;
+ void SetPowerExperimentState(bool state) override;
+ void SuspendForFrameClosed() override;
+
+ bool HasAvailableVideoFrame() const override;
+
+ scoped_refptr<WebAudioSourceProviderImpl> GetAudioSourceProvider() override;
+
+ void SetContentDecryptionModule(
+ WebContentDecryptionModule* cdm,
+ WebContentDecryptionModuleResult result) override;
+
+ void EnteredFullscreen() override;
+ void ExitedFullscreen() override;
+ void BecameDominantVisibleContent(bool is_dominant) override;
+ void SetIsEffectivelyFullscreen(
+ WebFullscreenVideoStatus fullscreen_video_status) override;
+ void OnHasNativeControlsChanged(bool) override;
+ void OnDisplayTypeChanged(DisplayType display_type) override;
+
+ // WebMediaPlayerDelegate::Observer implementation.
+ void OnFrameHidden() override;
+ void OnFrameShown() override;
+ void OnIdleTimeout() override;
+ void RequestRemotePlaybackDisabled(bool disabled) override;
+
+#if defined(OS_ANDROID)
+ // TODO(https://crbug.com/839651): Rename Flinging[Started/Stopped] to
+ // RemotePlayback[Started/Stopped] once the other RemotePlayback methods have
+ // been removed
+ void FlingingStarted() override;
+ void FlingingStopped() override;
+
+ // Called when the play/pause state of media playing on a remote cast device
+ // changes, and WMPI wasn't the originator of that change (e.g. a phone on the
+ // same network paused the cast device via the casting notification).
+ // This is only used by the FlingingRenderer/FlingingRendererClient, when we
+ // are flinging media (a.k.a. RemotePlayback).
+ // The consistency between the WMPI state and the cast device state is not
+ // guaranteed, and it a best effort, which can always be fixed by the user by
+ // tapping play/pause once. Attempts to enfore stronger consistency guarantees
+ // have lead to unstable states, and a worse user experience.
+ void OnRemotePlayStateChange(media::MediaStatus::State state);
+#endif
+
+ // media::MediaObserverClient implementation.
+ void SwitchToRemoteRenderer(
+ const std::string& remote_device_friendly_name) override;
+ void SwitchToLocalRenderer(
+ media::MediaObserverClient::ReasonToSwitchToLocal reason) override;
+ void UpdateRemotePlaybackCompatibility(bool is_compatible) override;
+
+ // Test helper methods for exercising media suspension. Once called, when
+ // |target_state| is reached or exceeded the stale flag will be set when
+ // computing the play state, which will trigger suspend if the player is
+ // paused; see UpdatePlayState_ComputePlayState() for the exact details.
+ void ForceStaleStateForTesting(ReadyState target_state) override;
+ bool IsSuspendedForTesting() override;
+ bool DidLazyLoad() const override;
+ void OnBecameVisible() override;
+ bool IsOpaque() const override;
+ int GetDelegateId() override;
+ absl::optional<viz::SurfaceId> GetSurfaceId() override;
+ GURL GetSrcAfterRedirects() override;
+ void RequestVideoFrameCallback() override;
+ std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata>
+ GetVideoFramePresentationMetadata() override;
+ void UpdateFrameIfStale() override;
+
+ base::WeakPtr<WebMediaPlayer> AsWeakPtr() override;
+
+ bool IsBackgroundMediaSuspendEnabled() const {
+ return is_background_suspend_enabled_;
+ }
+
+ // Distinct states that |delegate_| can be in. (Public for testing.)
+ enum class DelegateState {
+ GONE,
+ PLAYING,
+ PAUSED,
+ };
+
+ // Playback state variables computed together in UpdatePlayState().
+ // (Public for testing.)
+ struct PlayState {
+ DelegateState delegate_state;
+ bool is_idle;
+ bool is_memory_reporting_enabled;
+ bool is_suspended;
+ };
+
+ // Allow background video tracks with ~5 second keyframes (rounding down) to
+ // be disabled to save resources.
+ enum { kMaxKeyframeDistanceToDisableBackgroundVideoMs = 5500 };
+
+ private:
+ friend class WebMediaPlayerImplTest;
+ friend class WebMediaPlayerImplBackgroundBehaviorTest;
+
+ void EnableOverlay();
+ void DisableOverlay();
+
+ // Do we have overlay information? For CVV, this is a surface id. For
+ // AndroidOverlay, this is the routing token.
+ bool HaveOverlayInfo();
+
+ // Send OverlayInfo to the decoder.
+ //
+ // If we've requested but not yet received the surface id or routing token, or
+ // if there's no decoder-provided callback to send the overlay info, then this
+ // call will do nothing.
+ void MaybeSendOverlayInfoToDecoder();
+
+ void OnPipelineSuspended();
+ void OnBeforePipelineResume();
+ void OnPipelineResumed();
+ void OnPipelineSeeked(bool time_updated);
+ void OnDemuxerOpened();
+
+ // media::Pipeline::Client overrides.
+ void OnError(media::PipelineStatus status) override;
+ void OnEnded() override;
+ void OnMetadata(const media::PipelineMetadata& metadata) override;
+ void OnBufferingStateChange(
+ media::BufferingState state,
+ media::BufferingStateChangeReason reason) override;
+ void OnDurationChange() override;
+ void OnAddTextTrack(const media::TextTrackConfig& config,
+ media::AddTextTrackDoneCB done_cb) override;
+ void OnWaiting(media::WaitingReason reason) override;
+ void OnAudioConfigChange(const media::AudioDecoderConfig& config) override;
+ void OnVideoConfigChange(const media::VideoDecoderConfig& config) override;
+ void OnVideoNaturalSizeChange(const gfx::Size& size) override;
+ void OnVideoOpacityChange(bool opaque) override;
+ void OnVideoFrameRateChange(absl::optional<int> fps) override;
+ void OnVideoAverageKeyframeDistanceUpdate() override;
+ void OnAudioPipelineInfoChange(const media::AudioPipelineInfo& info) override;
+ void OnVideoPipelineInfoChange(const media::VideoPipelineInfo& info) override;
+
+ // Simplified watch time reporting.
+ void OnSimpleWatchTimerTick();
+
+ // Actually seek. Avoids causing |should_notify_time_changed_| to be set when
+ // |time_updated| is false.
+ void DoSeek(base::TimeDelta time, bool time_updated);
+
+ // Called after |defer_load_cb_| has decided to allow the load. If
+ // |defer_load_cb_| is null this is called immediately.
+ void DoLoad(LoadType load_type,
+ const WebURL& url,
+ CorsMode cors_mode,
+ bool is_cache_disabled);
+
+ // Called after asynchronous initialization of a data source completed.
+ void DataSourceInitialized(bool success);
+
+ // Called if the |MultiBufferDataSource| is redirected.
+ void OnDataSourceRedirected();
+
+ // Called when the data source is downloading or paused.
+ void NotifyDownloading(bool is_downloading);
+
+ // Called by RenderFrameImpl with the overlay routing token, if we request it.
+ void OnOverlayRoutingToken(const base::UnguessableToken& token);
+
+ // Called by GpuVideoDecoder on Android to request a surface to render to (if
+ // necessary).
+ void OnOverlayInfoRequested(
+ bool decoder_requires_restart_for_overlay,
+ media::ProvideOverlayInfoCB provide_overlay_info_cb);
+
+ // Creates a Renderer via the |renderer_factory_selector_|. If the
+ // |renderer_type| is absl::nullopt, create the base Renderer. Otherwise, set
+ // the base type to be |renderer_type| and create a Renderer of that type.
+ std::unique_ptr<media::Renderer> CreateRenderer(
+ absl::optional<media::RendererType> renderer_type);
+
+ // Finishes starting the pipeline due to a call to load().
+ void StartPipeline();
+
+ // Restart the player/pipeline as soon as possible. This will destroy the
+ // current renderer, if any, and create a new one via the RendererFactory; and
+ // then seek to resume playback at the current position.
+ void ScheduleRestart();
+
+ // Helpers that set the network/ready state and notifies the client if
+ // they've changed.
+ void SetNetworkState(WebMediaPlayer::NetworkState state);
+ void SetReadyState(WebMediaPlayer::ReadyState state);
+
+ // Returns the current video frame from |compositor_|, and asks the compositor
+ // to update its frame if it is stale.
+ // Can return a nullptr.
+ scoped_refptr<media::VideoFrame> GetCurrentFrameFromCompositor() const;
+
+ // Called when the demuxer encounters encrypted streams.
+ void OnEncryptedMediaInitData(media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data);
+
+ // Called when the FFmpegDemuxer encounters new media tracks. This is only
+ // invoked when using FFmpegDemuxer, since MSE/ChunkDemuxer handle media
+ // tracks separately in WebSourceBufferImpl.
+ void OnFFmpegMediaTracksUpdated(std::unique_ptr<media::MediaTracks> tracks);
+
+ // Sets CdmContext from |cdm| on the pipeline and calls OnCdmAttached()
+ // when done.
+ void SetCdmInternal(WebContentDecryptionModule* cdm);
+
+ // Called when a CDM has been attached to the |pipeline_|.
+ void OnCdmAttached(bool success);
+
+ // Inspects the current playback state and:
+ // - notifies |delegate_|,
+ // - toggles the memory usage reporting timer, and
+ // - toggles suspend/resume as necessary.
+ //
+ // This method should be called any time its dependent values change. These
+ // are:
+ // - is_flinging_,
+ // - hasVideo(),
+ // - delegate_->IsHidden(),
+ // - network_state_, ready_state_,
+ // - is_idle_, must_suspend_,
+ // - paused_, ended_,
+ // - pending_suspend_resume_cycle_,
+ // - enter_pip_callback_,
+ void UpdatePlayState();
+
+ // Methods internal to UpdatePlayState().
+ PlayState UpdatePlayState_ComputePlayState(bool is_flinging,
+ bool can_auto_suspend,
+ bool is_suspended,
+ bool is_backgrounded);
+ void SetDelegateState(DelegateState new_state, bool is_idle);
+ void SetMemoryReportingState(bool is_memory_reporting_enabled);
+ void SetSuspendState(bool is_suspended);
+
+ void SetDemuxer(std::unique_ptr<media::Demuxer> demuxer);
+
+ // Called at low frequency to tell external observers how much memory we're
+ // using for video playback. Called by |memory_usage_reporting_timer_|.
+ // Memory usage reporting is done in two steps, because |demuxer_| must be
+ // accessed on the media thread.
+ void ReportMemoryUsage();
+ void FinishMemoryUsageReport(int64_t demuxer_memory_usage);
+
+ void OnMainThreadMemoryDump(int32_t id,
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd);
+ static void OnMediaThreadMemoryDump(
+ int32_t id,
+ media::Demuxer* demuxer,
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd);
+
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+
+ // Called during OnHidden() when we want a suspended player to enter the
+ // paused state after some idle timeout.
+ void ScheduleIdlePauseTimer();
+
+ // Returns |true| before HaveFutureData whenever there has been loading
+ // progress and we have not been resumed for at least kLoadingToIdleTimeout
+ // since then.
+ //
+ // This is used to delay suspension long enough for preroll to complete, which
+ // is necessay because play() will not be called before HaveFutureData (and
+ // thus we think we are idle forever).
+ bool IsPrerollAttemptNeeded();
+
+ void CreateWatchTimeReporter();
+ void UpdateSecondaryProperties();
+
+ void CreateVideoDecodeStatsReporter();
+
+ // Returns true if the player is hidden.
+ bool IsHidden() const;
+
+ // Returns true if the player's source is streaming.
+ bool IsStreaming() const;
+
+ // Return whether |pipeline_metadata_| is compatible with an overlay. This
+ // is intended for android.
+ bool DoesOverlaySupportMetadata() const;
+
+ // Whether the playback should be paused when hidden. Uses metadata so has
+ // meaning only after the pipeline has started, otherwise returns false.
+ // Doesn't check if the playback can actually be paused depending on the
+ // pipeline's state.
+ bool ShouldPausePlaybackWhenHidden() const;
+
+ // Whether the video track should be disabled when hidden. Uses metadata so
+ // has meaning only after the pipeline has started, otherwise returns false.
+ // Doesn't check if the video track can actually be disabled depending on the
+ // pipeline's state.
+ bool ShouldDisableVideoWhenHidden() const;
+
+ // Whether the video is suitable for background playback optimizations (either
+ // pausing it or disabling the video track). Uses metadata so has meaning only
+ // after the pipeline has started, otherwise returns false.
+ // The logical OR between the two methods above that is also used as their
+ // common implementation.
+ bool IsBackgroundOptimizationCandidate() const;
+
+ // If enabling or disabling background video optimization has been delayed,
+ // because of the pipeline not running, seeking or resuming, this method
+ // needs to be called to update the optimization state.
+ void UpdateBackgroundVideoOptimizationState();
+
+ // Pauses a hidden video only player to save power if possible.
+ // Must be called when either of the following happens:
+ // - right after the video was hidden,
+ // - right ater the pipeline has resumed if the video is hidden.
+ void PauseVideoIfNeeded();
+
+ // Disables the video track to save power if possible.
+ // Must be called when either of the following happens:
+ // - right after the video was hidden,
+ // - right after the pipeline has started (|seeking_| is used to detect the
+ // when pipeline started) if the video is hidden,
+ // - right ater the pipeline has resumed if the video is hidden.
+ void DisableVideoTrackIfNeeded();
+
+ // Enables the video track if it was disabled before to save power.
+ // Must be called when either of the following happens:
+ // - right after the video was shown,
+ // - right before the pipeline is requested to resume
+ // (see https://crbug.com/678374),
+ // - right after the pipeline has resumed if the video is not hidden.
+ void EnableVideoTrackIfNeeded();
+
+ // Overrides the pipeline statistics returned by GetPiplineStatistics() for
+ // tests.
+ void SetPipelineStatisticsForTest(const media::PipelineStatistics& stats);
+
+ // Returns the pipeline statistics or the value overridden by tests.
+ media::PipelineStatistics GetPipelineStatistics() const;
+
+ // Overrides the pipeline media duration returned by
+ // GetPipelineMediaDuration() for tests.
+ void SetPipelineMediaDurationForTest(base::TimeDelta duration);
+
+ // Returns the pipeline media duration or the value overridden by tests.
+ base::TimeDelta GetPipelineMediaDuration() const;
+
+ media::MediaContentType GetMediaContentType() const;
+
+ // Records |duration| to the appropriate metric based on whether we're
+ // handling a src= or MSE based playback.
+ void RecordUnderflowDuration(base::TimeDelta duration);
+
+ // Called by the data source (for src=) or demuxer (for mse) when loading
+ // progresses.
+ // Can be called quite often.
+ void OnProgress();
+
+ // Returns true when we estimate that we can play the rest of the media
+ // without buffering.
+ bool CanPlayThrough();
+
+ // Internal implementation of Pipeline::Client::OnBufferingStateChange(). When
+ // |for_suspended_start| is true, the given state will be set even if the
+ // pipeline is not currently stable.
+ void OnBufferingStateChangeInternal(media::BufferingState state,
+ media::BufferingStateChangeReason reason,
+ bool for_suspended_start = false);
+
+ // Records |natural_size| to MediaLog and video height to UMA.
+ void RecordVideoNaturalSize(const gfx::Size& natural_size);
+
+ void SetTickClockForTest(const base::TickClock* tick_clock);
+
+ // Returns the current time without clamping to Duration() as required by
+ // HTMLMediaElement for handling ended. This method will never return a
+ // negative or kInfiniteDuration value. See http://crbug.com/409280,
+ // http://crbug.com/645998, and http://crbug.com/751823 for reasons why.
+ base::TimeDelta GetCurrentTimeInternal() const;
+
+ // Called by the compositor the very first time a frame is received.
+ void OnFirstFrame(base::TimeTicks frame_time);
+
+ // Records timing metrics for three UMA metrics: #key.SRC, #key.MSE, and
+ // #key.EME. The SRC and MSE ones are mutually exclusive based on the presence
+ // of |chunk_demuxer_|, while the EME one is only recorded if |is_encrypted_|.
+ void RecordTimingUMA(const std::string& key, base::TimeDelta elapsed);
+
+ // Records the encryption scheme used by the stream |stream_name|. This is
+ // only recorded when metadata is available.
+ void RecordEncryptionScheme(const std::string& stream_name,
+ media::EncryptionScheme encryption_scheme);
+
+ // Returns whether the player is currently displayed in Picture-in-Picture.
+ // It will return true even if the player is in AutoPIP mode.
+ // The player MUST have a `client_` when this call happen.
+ bool IsInPictureInPicture() const;
+
+ // Sets the UKM container name if needed.
+ void MaybeSetContainerNameForMetrics();
+
+ // Switch to SurfaceLayer, either initially or from VideoLayer.
+ void ActivateSurfaceLayerForVideo();
+
+ // Called by |compositor_| upon presenting a frame, after
+ // RequestAnimationFrame() is called.
+ void OnNewFramePresentedCallback();
+
+ // Notifies |mb_data_source_| of playback and rate changes which may increase
+ // the amount of data the DataSource buffers. Does nothing prior to reaching
+ // kReadyStateHaveEnoughData for the first time.
+ void MaybeUpdateBufferSizesForPlayback();
+
+ // Create / recreate |smoothness_helper_|, with current features. Will take
+ // no action if we already have a smoothness helper with the same features
+ // that we want now. Will destroy the helper if we shouldn't be measuring
+ // smoothness right now.
+ void UpdateSmoothnessHelper();
+
+ // Get the LearningTaskController for |task_name|.
+ std::unique_ptr<media::learning::LearningTaskController>
+ GetLearningTaskController(const char* task_name);
+
+ // Returns whether the player has an audio track and whether it should be
+ // allowed to play it.
+ bool HasUnmutedAudio() const;
+
+ // Returns true if the video frame from this player are being captured.
+ bool IsVideoBeingCaptured() const;
+
+ WebLocalFrame* const frame_;
+
+ WebMediaPlayer::NetworkState network_state_ =
+ WebMediaPlayer::kNetworkStateEmpty;
+ WebMediaPlayer::ReadyState ready_state_ =
+ WebMediaPlayer::kReadyStateHaveNothing;
+ WebMediaPlayer::ReadyState highest_ready_state_ =
+ WebMediaPlayer::kReadyStateHaveNothing;
+
+ // Preload state for when |data_source_| is created after setPreload().
+ MultiBufferDataSource::Preload preload_ = MultiBufferDataSource::METADATA;
+
+ // Poster state (for UMA reporting).
+ bool has_poster_ = false;
+
+ // Task runner for posting tasks on Chrome's main thread. Also used
+ // for DCHECKs so methods calls won't execute in the wrong thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+ const scoped_refptr<base::TaskRunner> worker_task_runner_;
+ std::unique_ptr<media::MediaLog> media_log_;
+
+ // |pipeline_controller_| owns an instance of Pipeline.
+ std::unique_ptr<media::PipelineController> pipeline_controller_;
+
+ // The LoadType passed in the |load_type| parameter of the load() call.
+ LoadType load_type_ = kLoadTypeURL;
+
+ // Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize().
+ media::PipelineMetadata pipeline_metadata_;
+
+ // Whether the video is known to be opaque or not.
+ bool opaque_ = false;
+
+ // Playback state.
+ //
+ // TODO(scherkus): we have these because Pipeline favours the simplicity of a
+ // single "playback rate" over worrying about paused/stopped etc... It forces
+ // all clients to manage the pause+playback rate externally, but is that
+ // really a bad thing?
+ //
+ // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want
+ // to hang the render thread during pause(), we record the time at the same
+ // time we pause and then return that value in currentTime(). Otherwise our
+ // clock can creep forward a little bit while the asynchronous
+ // SetPlaybackRate(0) is being executed.
+ double playback_rate_ = 0.0;
+
+ // Counter that limits spam to |media_log_| of |playback_rate_| changes.
+ int num_playback_rate_logs_ = 0;
+
+ // Set while paused. |paused_time_| is only valid when |paused_| is true.
+ bool paused_ = true;
+ base::TimeDelta paused_time_;
+
+ // Set if paused automatically when hidden and need to resume when visible.
+ // Reset if paused for any other reason.
+ bool paused_when_hidden_ = false;
+
+ // Set when starting, seeking, and resuming (all of which require a Pipeline
+ // seek). |seek_time_| is only valid when |seeking_| is true.
+ bool seeking_ = false;
+ base::TimeDelta seek_time_;
+
+ // Set when doing a restart (a suspend and resume in sequence) of the pipeline
+ // in order to destruct and reinitialize the decoders. This is separate from
+ // |pending_resume_| and |pending_suspend_| because they can be elided in
+ // certain cases, whereas for a restart they must happen.
+ // TODO(sandersd,watk): Create a simpler interface for a pipeline restart.
+ bool pending_suspend_resume_cycle_ = false;
+
+ // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
+ // see http://crbug.com/409280
+ bool ended_ = false;
+
+ // Tracks whether to issue time changed notifications during buffering state
+ // changes.
+ bool should_notify_time_changed_ = false;
+
+ bool overlay_enabled_ = false;
+
+ // Whether the current decoder requires a restart on overlay transitions.
+ bool decoder_requires_restart_for_overlay_ = false;
+
+ WebMediaPlayerClient* const client_;
+ WebMediaPlayerEncryptedMediaClient* const encrypted_client_;
+
+ // WebMediaPlayer notifies the |delegate_| of playback state changes using
+ // |delegate_id_|; an id provided after registering with the delegate. The
+ // WebMediaPlayer may also receive directives (play, pause) from the delegate
+ // via the WebMediaPlayerDelegate::Observer interface after registration.
+ //
+ // NOTE: HTMLMediaElement is a ExecutionContextLifecycleObserver, and
+ // will receive a call to contextDestroyed() when Document::shutdown()
+ // is called. Document::shutdown() is called before the frame detaches (and
+ // before the frame is destroyed). RenderFrameImpl owns |delegate_| and is
+ // guaranteed to outlive |this|; thus it is safe to store |delegate_| as a raw
+ // pointer.
+ WebMediaPlayerDelegate* delegate_;
+ int delegate_id_ = 0;
+
+ // The playback state last reported to |delegate_|, to avoid setting duplicate
+ // states.
+ // TODO(sandersd): The delegate should be implementing deduplication.
+ DelegateState delegate_state_ = DelegateState::GONE;
+ bool delegate_has_audio_ = false;
+
+ WebMediaPlayerParams::DeferLoadCB defer_load_cb_;
+
+ // Members for notifying upstream clients about internal memory usage. The
+ // |adjust_allocated_memory_cb_| must only be called on |main_task_runner_|.
+ base::RepeatingTimer memory_usage_reporting_timer_;
+ WebMediaPlayerParams::AdjustAllocatedMemoryCB adjust_allocated_memory_cb_;
+ int64_t last_reported_memory_usage_ = 0;
+ std::unique_ptr<media::MemoryDumpProviderProxy> main_thread_mem_dumper_;
+ std::unique_ptr<media::MemoryDumpProviderProxy> media_thread_mem_dumper_;
+
+ // Routes audio playback to either AudioRendererSink or WebAudio.
+ scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_;
+
+ // These two are mutually exclusive:
+ // |data_source_| is used for regular resource loads.
+ // |chunk_demuxer_| is used for Media Source resource loads.
+ //
+ // |demuxer_| will contain the appropriate demuxer based on which resource
+ // load strategy we're using.
+ MultiBufferDataSource* mb_data_source_ = nullptr;
+ std::unique_ptr<media::DataSource> data_source_;
+ std::unique_ptr<media::Demuxer> demuxer_;
+ media::ChunkDemuxer* chunk_demuxer_ = nullptr;
+
+ std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+
+ const base::TickClock* tick_clock_ = nullptr;
+
+ std::unique_ptr<BufferedDataSourceHostImpl> buffered_data_source_host_;
+ UrlIndex* const url_index_;
+ scoped_refptr<viz::RasterContextProvider> raster_context_provider_;
+
+ // Video rendering members.
+ // The |compositor_| runs on the compositor thread, or if
+ // kEnableSurfaceLayerForVideo is enabled, the media thread. This task runner
+ // posts tasks for the |compositor_| on the correct thread.
+ scoped_refptr<base::SingleThreadTaskRunner> vfc_task_runner_;
+ std::unique_ptr<VideoFrameCompositor>
+ compositor_; // Deleted on |vfc_task_runner_|.
+ media::PaintCanvasVideoRenderer video_renderer_;
+
+ // The compositor layer for displaying the video content when using composited
+ // playback.
+ scoped_refptr<cc::VideoLayer> video_layer_;
+
+ std::unique_ptr<WebContentDecryptionModuleResult> set_cdm_result_;
+
+ // If a CdmContext is attached keep a reference to the CdmContextRef, so that
+ // it is not destroyed until after the pipeline is done with it.
+ std::unique_ptr<media::CdmContextRef> cdm_context_ref_;
+
+ // Keep track of the CdmContextRef while it is in the process of attaching to
+ // the pipeline.
+ std::unique_ptr<media::CdmContextRef> pending_cdm_context_ref_;
+
+ // True when encryption is detected, either by demuxer or by presence of a
+ // ContentDecyprtionModule (CDM).
+ bool is_encrypted_ = false;
+
+ // Captured once the cdm is provided to SetCdmInternal(). Used in creation of
+ // |video_decode_stats_reporter_|.
+ absl::optional<media::CdmConfig> cdm_config_;
+
+ // String identifying the KeySystem described by |cdm_config_|. Empty until a
+ // CDM has been attached. Used in creation |video_decode_stats_reporter_|.
+ std::string key_system_;
+
+ // Tracks if we are currently flinging a video (e.g. in a RemotePlayback
+ // session). Used to prevent videos from being paused when hidden.
+ // TODO(https://crbug.com/839651): remove or rename this flag, when removing
+ // IsRemote().
+ bool is_flinging_ = false;
+
+ // Tracks if we are currently using a remote renderer. See
+ // SwitchToRemoteRenderer().
+ bool is_remote_rendering_ = false;
+
+ // The last volume received by setVolume() and the last volume multiplier from
+ // SetVolumeMultiplier(). The multiplier is typical 1.0, but may be less
+ // if the WebMediaPlayerDelegate has requested a volume reduction (ducking)
+ // for a transient sound. Playout volume is derived by volume * multiplier.
+ double volume_ = 1.0;
+ double volume_multiplier_ = 1.0;
+
+ std::unique_ptr<media::RendererFactorySelector> renderer_factory_selector_;
+
+ // For canceling AndroidOverlay routing token requests.
+ base::CancelableOnceCallback<void(const base::UnguessableToken&)>
+ token_available_cb_;
+
+ // If overlay info is requested before we have it, then the request is saved
+ // and satisfied once the overlay info is available. If the decoder does not
+ // require restart to change surfaces, this is callback is kept until cleared
+ // by the decoder.
+ media::ProvideOverlayInfoCB provide_overlay_info_cb_;
+
+ // On Android an overlay surface means using
+ // SurfaceView instead of SurfaceTexture.
+
+ // Allow overlays for all video on android.
+ bool always_enable_overlays_ = false;
+
+ // Suppresses calls to OnPipelineError() after destruction / shutdown has been
+ // started; prevents us from spuriously logging errors that are transient or
+ // unimportant.
+ bool suppress_destruction_errors_ = false;
+
+ // TODO(dalecurtis): The following comment is inaccurate as this value is also
+ // used for, for example, data URLs.
+ // Used for HLS playback and in certain fallback paths (e.g. on older devices
+ // that can't support the unified media pipeline).
+ GURL loaded_url_;
+
+ // NOTE: |using_media_player_renderer_| is set based on the usage of a
+ // MediaResource::Type::URL in StartPipeline(). This works because
+ // MediaPlayerRendererClientFactory is the only factory that uses
+ // MediaResource::Type::URL for now.
+ bool using_media_player_renderer_ = false;
+
+#if defined(OS_ANDROID)
+ // Set during the initial DoLoad() call. Used to determine whether to allow
+ // credentials or not for MediaPlayerRenderer.
+ bool allow_media_player_renderer_credentials_ = false;
+#endif
+
+ // Stores the current position state of the media.
+ media_session::MediaPosition media_position_state_;
+
+ // Set whenever the demuxer encounters an HLS file.
+ // This flag is distinct from |using_media_player_renderer_|, because on older
+ // devices we might use MediaPlayerRenderer for non HLS playback.
+ bool demuxer_found_hls_ = false;
+
+ // Called sometime after the media is suspended in a playing state in
+ // OnFrameHidden(), causing the state to change to paused.
+ base::OneShotTimer background_pause_timer_;
+
+ // Monitors the watch time of the played content.
+ std::unique_ptr<WatchTimeReporter> watch_time_reporter_;
+ media::AudioDecoderType audio_decoder_type_ =
+ media::AudioDecoderType::kUnknown;
+ media::VideoDecoderType video_decoder_type_ =
+ media::VideoDecoderType::kUnknown;
+
+ // The time at which DoLoad() is executed.
+ base::TimeTicks load_start_time_;
+
+ // Time elapsed time from |load_start_time_| to OnMetadata(). Used to later
+ // adjust |load_start_time_| if a suspended startup occurred.
+ base::TimeDelta time_to_metadata_;
+ bool skip_metrics_due_to_startup_suspend_ = false;
+
+ bool have_reported_time_to_play_ready_ = false;
+
+ // Records pipeline statistics for describing media capabilities.
+ std::unique_ptr<VideoDecodeStatsReporter> video_decode_stats_reporter_;
+
+ // Elapsed time since we've last reached BUFFERING_HAVE_NOTHING.
+ std::unique_ptr<base::ElapsedTimer> underflow_timer_;
+
+ // Used to track loading progress, used by IsPrerollAttemptNeeded().
+ // |preroll_attempt_pending_| indicates that the clock has been reset
+ // (awaiting a resume to start), while |preroll_attempt_start_time_| tracks
+ // when a preroll attempt began.
+ bool preroll_attempt_pending_ = false;
+ base::TimeTicks preroll_attempt_start_time_;
+
+ // Monitors the player events.
+ base::WeakPtr<media::MediaObserver> observer_;
+
+ // Owns the weblayer and obtains/maintains SurfaceIds.
+ std::unique_ptr<WebSurfaceLayerBridge> bridge_;
+
+ // The maximum video keyframe distance that allows triggering background
+ // playback optimizations (non-MSE).
+ base::TimeDelta max_keyframe_distance_to_disable_background_video_;
+
+ // The maximum video keyframe distance that allows triggering background
+ // playback optimizations (MSE).
+ base::TimeDelta max_keyframe_distance_to_disable_background_video_mse_;
+
+ // When MSE memory pressure based garbage collection is enabled, the
+ // |enable_instant_source_buffer_gc| controls whether the GC is done
+ // immediately on memory pressure notification or during the next SourceBuffer
+ // append (slower, but MSE spec compliant).
+ bool enable_instant_source_buffer_gc_ = false;
+
+ // Whether disabled the video track as an optimization.
+ bool video_track_disabled_ = false;
+
+ // Whether the pipeline is being resumed at the moment.
+ bool is_pipeline_resuming_ = false;
+
+ // When this is true, pipeline will not be auto suspended.
+ bool disable_pipeline_auto_suspend_ = false;
+
+ // Pipeline statistics overridden by tests.
+ absl::optional<media::PipelineStatistics> pipeline_statistics_for_test_;
+
+ // Pipeline media duration overridden by tests.
+ absl::optional<base::TimeDelta> pipeline_media_duration_for_test_;
+
+ // Whether the video requires a user gesture to resume after it was paused in
+ // the background. Affects the value of ShouldPausePlaybackWhenHidden().
+ bool video_locked_when_paused_when_hidden_ = false;
+
+ // Whether embedded media experience is currently enabled.
+ bool embedded_media_experience_enabled_ = false;
+
+ // When should we use SurfaceLayer for video?
+ WebMediaPlayer::SurfaceLayerMode surface_layer_mode_ =
+ WebMediaPlayer::SurfaceLayerMode::kNever;
+
+ // Whether surface layer is currently in use to display frames.
+ bool surface_layer_for_video_enabled_ = false;
+
+ CreateSurfaceLayerBridgeCB create_bridge_callback_;
+
+ bool initial_video_height_recorded_ = false;
+
+ enum class OverlayMode {
+ // All overlays are turned off.
+ kNoOverlays,
+
+ // Use AndroidOverlay for overlays.
+ kUseAndroidOverlay,
+ };
+
+ OverlayMode overlay_mode_ = OverlayMode::kNoOverlays;
+
+ // Optional callback to request the routing token for AndroidOverlay.
+ media::RequestRoutingTokenCallback request_routing_token_cb_;
+
+ // If |overlay_routing_token_is_pending_| is false, then
+ // |overlay_routing_token_| contains the routing token we should send, if any.
+ // Otherwise, |overlay_routing_token_| is undefined. We set the flag while
+ // we have a request for the token that hasn't been answered yet; i.e., it
+ // means that we don't know what, if any, token we should be using.
+ bool overlay_routing_token_is_pending_ = false;
+ media::OverlayInfo::RoutingToken overlay_routing_token_;
+
+ media::OverlayInfo overlay_info_;
+
+ base::CancelableOnceClosure update_background_status_cb_;
+
+ // We cannot use `update_background_status_cb_.IsCancelled()` as that changes
+ // when the callback is run, even if not explicitly cancelled. This is
+ // initialized to true to keep in line with the existing behavior of
+ // base::CancellableOnceClosure.
+ bool is_background_status_change_cancelled_ = true;
+
+ mojo::Remote<media::mojom::MediaMetricsProvider> media_metrics_provider_;
+ mojo::Remote<media::mojom::PlaybackEventsRecorder> playback_events_recorder_;
+
+ absl::optional<ReadyState> stale_state_override_for_testing_;
+
+ // True if we attempt to start the media pipeline in a suspended state for
+ // preload=metadata. Cleared upon pipeline startup.
+ bool attempting_suspended_start_ = false;
+
+ // True if a frame has ever been rendered.
+ bool has_first_frame_ = false;
+
+ // True if we have not yet rendered a first frame, but one is needed. Set back
+ // to false as soon as |has_first_frame_| is set to true.
+ bool needs_first_frame_ = false;
+
+ // True if StartPipeline() completed a lazy load startup.
+ bool did_lazy_load_ = false;
+
+ // Whether the renderer should automatically suspend media playback in
+ // background tabs.
+ bool is_background_suspend_enabled_ = false;
+
+ // If disabled, video will be auto paused when in background. Affects the
+ // value of ShouldPausePlaybackWhenHidden().
+ bool is_background_video_playback_enabled_ = true;
+
+ // Whether background video optimization is supported on current platform.
+ bool is_background_video_track_optimization_supported_ = true;
+
+ bool was_suspended_for_frame_closed_ = false;
+
+ base::CancelableOnceClosure have_enough_after_lazy_load_cb_;
+
+ media::RendererType renderer_type_ = media::RendererType::kDefault;
+ media::SimpleWatchTimer simple_watch_timer_;
+
+ LearningExperimentHelper will_play_helper_;
+
+ // Stores the optional override Demuxer until it is used in DoLoad().
+ std::unique_ptr<media::Demuxer> demuxer_override_;
+
+ std::unique_ptr<PowerStatusHelper> power_status_helper_;
+
+ // Created while playing, deleted otherwise.
+ std::unique_ptr<SmoothnessHelper> smoothness_helper_;
+ absl::optional<int> last_reported_fps_;
+
+ // Time of the last call to GetCurrentFrameFromCompositor(). Used to prevent
+ // background optimizations from being applied when capturing is active.
+ base::TimeTicks last_frame_request_time_;
+
+ base::WeakPtr<WebMediaPlayerImpl> weak_this_;
+ base::WeakPtrFactory<WebMediaPlayerImpl> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_WEB_MEDIA_PLAYER_IMPL_H_
diff --git a/chromium/third_party/blink/public/platform/media/web_media_player_params.h b/chromium/third_party/blink/public/platform/media/web_media_player_params.h
new file mode 100644
index 00000000000..9800411f230
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/media/web_media_player_params.h
@@ -0,0 +1,216 @@
+// 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_PUBLIC_PLATFORM_MEDIA_WEB_MEDIA_PLAYER_PARAMS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_WEB_MEDIA_PLAYER_PARAMS_H_
+
+#include <stdint.h>
+
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "cc/layers/surface_layer.h"
+#include "components/viz/common/gpu/raster_context_provider.h"
+#include "media/base/media_log.h"
+#include "media/base/media_observer.h"
+#include "media/base/media_switches.h"
+#include "media/base/routing_token_callback.h"
+#include "media/mojo/mojom/media_metrics_provider.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/platform/media/power_status_helper.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_player.h"
+#include "third_party/blink/public/platform/web_video_frame_submitter.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+class TaskRunner;
+}
+
+namespace media {
+class Demuxer;
+class SwitchableAudioRendererSink;
+} // namespace media
+
+namespace blink {
+class WebContentDecryptionModule;
+class WebSurfaceLayerBridge;
+class WebSurfaceLayerBridgeObserver;
+
+using CreateSurfaceLayerBridgeCB =
+ base::OnceCallback<std::unique_ptr<WebSurfaceLayerBridge>(
+ WebSurfaceLayerBridgeObserver*,
+ cc::UpdateSubmissionStateCB)>;
+
+// Holds parameters for constructing WebMediaPlayerImpl without having
+// to plumb arguments through various abstraction layers.
+class BLINK_PLATFORM_EXPORT WebMediaPlayerParams {
+ public:
+ // Returns true if load will deferred. False if it will run immediately.
+ using DeferLoadCB = base::RepeatingCallback<bool(base::OnceClosure)>;
+
+ // Callback to tell V8 about the amount of memory used by the WebMediaPlayer
+ // instance. The input parameter is the delta in bytes since the last call to
+ // AdjustAllocatedMemoryCB and the return value is the total number of bytes
+ // used by objects external to V8. Note: this value includes things that are
+ // not the WebMediaPlayer!
+ using AdjustAllocatedMemoryCB = base::RepeatingCallback<int64_t(int64_t)>;
+
+ // |defer_load_cb|, |audio_renderer_sink|, |compositor_task_runner|, and
+ // |context_3d_cb| may be null.
+ WebMediaPlayerParams(
+ std::unique_ptr<media::MediaLog> media_log,
+ const DeferLoadCB& defer_load_cb,
+ const scoped_refptr<media::SwitchableAudioRendererSink>&
+ audio_renderer_sink,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ const scoped_refptr<base::TaskRunner>& worker_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ video_frame_compositor_task_runner,
+ const AdjustAllocatedMemoryCB& adjust_allocated_memory_cb,
+ WebContentDecryptionModule* initial_cdm,
+ media::RequestRoutingTokenCallback request_routing_token_cb,
+ base::WeakPtr<media::MediaObserver> media_observer,
+ bool enable_instant_source_buffer_gc,
+ bool embedded_media_experience_enabled,
+ mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
+ CreateSurfaceLayerBridgeCB bridge_callback,
+ scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+ WebMediaPlayer::SurfaceLayerMode use_surface_layer_for_video,
+ bool is_background_suspend_enabled,
+ bool is_background_video_play_enabled,
+ bool is_background_video_track_optimization_supported,
+ std::unique_ptr<media::Demuxer> demuxer_override,
+ std::unique_ptr<PowerStatusHelper> power_status_helper);
+
+ WebMediaPlayerParams(const WebMediaPlayerParams&) = delete;
+ WebMediaPlayerParams& operator=(const WebMediaPlayerParams&) = delete;
+ ~WebMediaPlayerParams();
+
+ DeferLoadCB defer_load_cb() const { return defer_load_cb_; }
+
+ const scoped_refptr<media::SwitchableAudioRendererSink>& audio_renderer_sink()
+ const {
+ return audio_renderer_sink_;
+ }
+
+ std::unique_ptr<media::MediaLog> take_media_log() {
+ return std::move(media_log_);
+ }
+
+ mojo::PendingRemote<media::mojom::MediaMetricsProvider>
+ take_metrics_provider() {
+ return std::move(metrics_provider_);
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner() const {
+ return media_task_runner_;
+ }
+
+ const scoped_refptr<base::TaskRunner> worker_task_runner() const {
+ return worker_task_runner_;
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner()
+ const {
+ return compositor_task_runner_;
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ video_frame_compositor_task_runner() const {
+ return video_frame_compositor_task_runner_;
+ }
+
+ WebContentDecryptionModule* initial_cdm() const { return initial_cdm_; }
+
+ AdjustAllocatedMemoryCB adjust_allocated_memory_cb() const {
+ return adjust_allocated_memory_cb_;
+ }
+
+ base::WeakPtr<media::MediaObserver> media_observer() const {
+ return media_observer_;
+ }
+
+ bool enable_instant_source_buffer_gc() const {
+ return enable_instant_source_buffer_gc_;
+ }
+
+ bool embedded_media_experience_enabled() const {
+ return embedded_media_experience_enabled_;
+ }
+
+ media::RequestRoutingTokenCallback request_routing_token_cb() {
+ return request_routing_token_cb_;
+ }
+
+ CreateSurfaceLayerBridgeCB create_bridge_callback() {
+ return std::move(create_bridge_callback_);
+ }
+
+ scoped_refptr<viz::RasterContextProvider> raster_context_provider() {
+ return raster_context_provider_;
+ }
+
+ WebMediaPlayer::SurfaceLayerMode use_surface_layer_for_video() const {
+ return use_surface_layer_for_video_;
+ }
+
+ bool IsBackgroundSuspendEnabled() const {
+ return is_background_suspend_enabled_;
+ }
+
+ bool IsBackgroundVideoPlaybackEnabled() const {
+ return is_background_video_playback_enabled_;
+ }
+
+ bool IsBackgroundVideoTrackOptimizationSupported() const {
+ return is_background_video_track_optimization_supported_;
+ }
+
+ std::unique_ptr<media::Demuxer> TakeDemuxerOverride();
+
+ std::unique_ptr<PowerStatusHelper> TakePowerStatusHelper() {
+ return std::move(power_status_helper_);
+ }
+
+ private:
+ DeferLoadCB defer_load_cb_;
+ scoped_refptr<media::SwitchableAudioRendererSink> audio_renderer_sink_;
+ std::unique_ptr<media::MediaLog> media_log_;
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+ scoped_refptr<base::TaskRunner> worker_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ video_frame_compositor_task_runner_;
+ AdjustAllocatedMemoryCB adjust_allocated_memory_cb_;
+
+ WebContentDecryptionModule* initial_cdm_;
+ media::RequestRoutingTokenCallback request_routing_token_cb_;
+ base::WeakPtr<media::MediaObserver> media_observer_;
+ bool enable_instant_source_buffer_gc_;
+ const bool embedded_media_experience_enabled_;
+ mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider_;
+ CreateSurfaceLayerBridgeCB create_bridge_callback_;
+ scoped_refptr<viz::RasterContextProvider> raster_context_provider_;
+ WebMediaPlayer::SurfaceLayerMode use_surface_layer_for_video_;
+
+ // Whether the renderer should automatically suspend media playback in
+ // background tabs.
+ bool is_background_suspend_enabled_ = false;
+ // Whether the renderer is allowed to play video in background tabs.
+ bool is_background_video_playback_enabled_ = true;
+ // Whether background video optimization is supported on current platform.
+ bool is_background_video_track_optimization_supported_ = true;
+
+ // Optional custom demuxer to use instead of the standard demuxers.
+ std::unique_ptr<media::Demuxer> demuxer_override_;
+
+ std::unique_ptr<PowerStatusHelper> power_status_helper_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MEDIA_WEB_MEDIA_PLAYER_PARAMS_H_
diff --git a/chromium/third_party/blink/public/platform/modules/mediastream/OWNERS b/chromium/third_party/blink/public/platform/modules/mediastream/OWNERS
index b99ae052002..2ad93e6b341 100644
--- a/chromium/third_party/blink/public/platform/modules/mediastream/OWNERS
+++ b/chromium/third_party/blink/public/platform/modules/mediastream/OWNERS
@@ -1,3 +1 @@
file://third_party/blink/common/mediastream/OWNERS
-
-per-file media_stream_audio_processor*=aluebs@chromium.org
diff --git a/chromium/third_party/blink/public/platform/modules/mediastream/secure_display_link_tracker.h b/chromium/third_party/blink/public/platform/modules/mediastream/secure_display_link_tracker.h
index 2118977b005..bb2444229e7 100644
--- a/chromium/third_party/blink/public/platform/modules/mediastream/secure_display_link_tracker.h
+++ b/chromium/third_party/blink/public/platform/modules/mediastream/secure_display_link_tracker.h
@@ -14,8 +14,10 @@ namespace blink {
template <typename T>
class SecureDisplayLinkTracker {
public:
- SecureDisplayLinkTracker() {}
- ~SecureDisplayLinkTracker() {}
+ SecureDisplayLinkTracker() = default;
+ SecureDisplayLinkTracker(const SecureDisplayLinkTracker&) = delete;
+ SecureDisplayLinkTracker& operator=(const SecureDisplayLinkTracker&) = delete;
+ ~SecureDisplayLinkTracker() = default;
void Add(T* link, bool is_link_secure);
void Remove(T* link);
@@ -25,8 +27,6 @@ class SecureDisplayLinkTracker {
private:
// Record every insecure links.
Vector<T*> insecure_links_;
-
- DISALLOW_COPY_AND_ASSIGN(SecureDisplayLinkTracker);
};
template <typename T>
diff --git a/chromium/third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h b/chromium/third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h
index 18788fdc9b5..8ab1b54168c 100644
--- a/chromium/third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h
+++ b/chromium/third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h
@@ -26,7 +26,6 @@
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIASTREAM_WEB_MEDIA_STREAM_TRACK_H_
#include "media/mojo/mojom/display_media_information.mojom-shared.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_private_ptr.h"
diff --git a/chromium/third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h b/chromium/third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h
index a5b5cbf4da3..253c7846bf1 100644
--- a/chromium/third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h
+++ b/chromium/third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h
@@ -36,7 +36,11 @@ class BLINK_PLATFORM_EXPORT WebPlatformMediaStreamSource {
// https://dev.w3.org/2011/webrtc/editor/getusermedia.html.
static const char kSourceId[];
- WebPlatformMediaStreamSource();
+ explicit WebPlatformMediaStreamSource(
+ scoped_refptr<base::SingleThreadTaskRunner>);
+ WebPlatformMediaStreamSource(const WebPlatformMediaStreamSource&) = delete;
+ WebPlatformMediaStreamSource& operator=(const WebPlatformMediaStreamSource&) =
+ delete;
virtual ~WebPlatformMediaStreamSource();
// Returns device information about a source that has been created by a
@@ -86,6 +90,9 @@ class BLINK_PLATFORM_EXPORT WebPlatformMediaStreamSource {
// implementations to implement custom stop methods.
void FinalizeStopSource();
+ // Gets the TaskRunner for the main thread, for subclasses that need it.
+ base::SingleThreadTaskRunner* GetTaskRunner() const;
+
private:
MediaStreamDevice device_;
SourceStoppedCallback stop_callback_;
@@ -94,7 +101,10 @@ class BLINK_PLATFORM_EXPORT WebPlatformMediaStreamSource {
WebPrivatePtrStrength::kWeak>
owner_;
- DISALLOW_COPY_AND_ASSIGN(WebPlatformMediaStreamSource);
+ // Task runner for the main thread. Also used to check that all methods that
+ // could cause object graph or data flow changes are being called on the main
+ // thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_object_info.h b/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_object_info.h
index 4508cd8f67f..62d07019ca1 100644
--- a/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_object_info.h
+++ b/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_object_info.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_OBJECT_INFO_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_OBJECT_INFO_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-shared.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom-shared.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
@@ -34,6 +33,10 @@ struct WebServiceWorkerObjectInfo {
receiver(std::move(receiver)) {}
WebServiceWorkerObjectInfo(WebServiceWorkerObjectInfo&& other) = default;
+ WebServiceWorkerObjectInfo(const WebServiceWorkerObjectInfo&) = delete;
+ WebServiceWorkerObjectInfo& operator=(const WebServiceWorkerObjectInfo&) =
+ delete;
+
int64_t version_id;
mojom::ServiceWorkerState state;
WebURL url;
@@ -41,8 +44,6 @@ struct WebServiceWorkerObjectInfo {
host_remote;
CrossVariantMojoAssociatedReceiver<mojom::ServiceWorkerObjectInterfaceBase>
receiver;
-
- DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerObjectInfo);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h b/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h
index ff8a9f1c732..d92299cbc5d 100644
--- a/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h
+++ b/chromium/third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_REGISTRATION_OBJECT_INFO_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_REGISTRATION_OBJECT_INFO_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-shared.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration_options.mojom-shared.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
@@ -44,6 +43,11 @@ struct WebServiceWorkerRegistrationObjectInfo {
WebServiceWorkerRegistrationObjectInfo(
WebServiceWorkerRegistrationObjectInfo&& other) = default;
+ WebServiceWorkerRegistrationObjectInfo(
+ const WebServiceWorkerRegistrationObjectInfo&) = delete;
+ WebServiceWorkerRegistrationObjectInfo& operator=(
+ const WebServiceWorkerRegistrationObjectInfo&) = delete;
+
int64_t registration_id;
WebURL scope;
@@ -59,8 +63,6 @@ struct WebServiceWorkerRegistrationObjectInfo {
WebServiceWorkerObjectInfo installing;
WebServiceWorkerObjectInfo waiting;
WebServiceWorkerObjectInfo active;
-
- DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerRegistrationObjectInfo);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h b/chromium/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h
index a865239d172..19e305c71e7 100644
--- a/chromium/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h
+++ b/chromium/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
@@ -43,6 +42,9 @@ class WebString;
class BLINK_PLATFORM_EXPORT WebVideoCaptureImplManager {
public:
WebVideoCaptureImplManager();
+ WebVideoCaptureImplManager(const WebVideoCaptureImplManager&) = delete;
+ WebVideoCaptureImplManager& operator=(const WebVideoCaptureImplManager&) =
+ delete;
virtual ~WebVideoCaptureImplManager();
// Open a device associated with the session ID.
@@ -148,8 +150,6 @@ class BLINK_PLATFORM_EXPORT WebVideoCaptureImplManager {
// Bound to the render thread.
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<WebVideoCaptureImplManager> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WebVideoCaptureImplManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/modules/webrtc/DEPS b/chromium/third_party/blink/public/platform/modules/webrtc/DEPS
index 4ca2134e95d..69ac5a7b646 100644
--- a/chromium/third_party/blink/public/platform/modules/webrtc/DEPS
+++ b/chromium/third_party/blink/public/platform/modules/webrtc/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+base/compiler_specific.h",
"+media/base",
]
diff --git a/chromium/third_party/blink/public/platform/modules/webrtc/OWNERS b/chromium/third_party/blink/public/platform/modules/webrtc/OWNERS
index ec89f983fe2..29d9d1c7876 100644
--- a/chromium/third_party/blink/public/platform/modules/webrtc/OWNERS
+++ b/chromium/third_party/blink/public/platform/modules/webrtc/OWNERS
@@ -1,10 +1,8 @@
hbos@chromium.org
-perkj@chromium.org
tommi@chromium.org
guidou@chromium.org
olka@chromium.org
orphis@chromium.org
-sergeyu@chromium.org
ilnik@chromium.org
per-file rtc_video_*=file://media/gpu/OWNERS
diff --git a/chromium/third_party/blink/public/platform/modules/webrtc/webrtc_logging.h b/chromium/third_party/blink/public/platform/modules/webrtc/webrtc_logging.h
index 9f4c1626196..f57f11e5fa2 100644
--- a/chromium/third_party/blink/public/platform/modules/webrtc/webrtc_logging.h
+++ b/chromium/third_party/blink/public/platform/modules/webrtc/webrtc_logging.h
@@ -5,8 +5,11 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBRTC_WEBRTC_LOGGING_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBRTC_WEBRTC_LOGGING_H_
+#include <stdarg.h>
+
#include <string>
+#include "base/compiler_specific.h"
#include "third_party/blink/public/platform/web_common.h"
namespace blink {
@@ -35,10 +38,30 @@ BLINK_PLATFORM_EXPORT void InitWebRtcLogging();
// Otherwise it will be ignored. Note that this log may be uploaded to a
// server by the embedder - no sensitive information should be logged. May be
// called on any thread.
-// TODO(grunell): Create a macro for adding log messages. Messages should
-// probably also go to the ordinary logging stream.
void BLINK_PLATFORM_EXPORT WebRtcLogMessage(const std::string& message);
+// Helper methods which wraps calls to WebRtcLogMessage() using different
+// printf-like inputs allowing the user to create log messages with a similar
+// syntax as for printf format specifiers. These mathods use different versions
+// of base::StringPrintf() internally and can also prepend the logged string
+// with a |prefix| string and/or append a formated this pointer in |thiz|.
+
+// Example: WebRtcLog("%s({foo=%d})", "Foo", 10) <=>
+// WebRtcLogMessage("Foo({foo=10})")
+void BLINK_PLATFORM_EXPORT WebRtcLog(const char* format, ...)
+ PRINTF_FORMAT(1, 2);
+
+// Example: WebRtcLog(this, "%s({foo=%d})", "Foo", 10) <=>
+// WebRtcLogMessage("Foo({foo=10}) [this=0x24514CB47A0]")
+void BLINK_PLATFORM_EXPORT WebRtcLog(void* thiz, const char* format, ...)
+ PRINTF_FORMAT(2, 3);
+
+// Example: WebRtcLog("RTC::", this, "%s({foo=%d})", "Foo", 10) <=>
+// WebRtcLogMessage("RTC::Foo({foo=10}) [this=0x24514CB47A0]")
+void BLINK_PLATFORM_EXPORT WebRtcLog(const char* prefix,
+ void* thiz,
+ const char* format,
+ ...) PRINTF_FORMAT(3, 4);
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBRTC_WEBRTC_LOGGING_H_
diff --git a/chromium/third_party/blink/public/platform/platform.h b/chromium/third_party/blink/public/platform/platform.h
index d0df35ea0be..9d96af5c4c9 100644
--- a/chromium/third_party/blink/public/platform/platform.h
+++ b/chromium/third_party/blink/public/platform/platform.h
@@ -44,7 +44,6 @@
#include "media/base/audio_latency.h"
#include "media/base/audio_renderer_sink.h"
#include "media/base/media_log.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/security/protocol_handler_security_level.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
@@ -61,7 +60,6 @@
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_v8_value_converter.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle_provider.h"
#include "third_party/webrtc/api/video/video_codec_type.h"
@@ -102,8 +100,10 @@ class BigBuffer;
namespace network {
namespace mojom {
+class URLLoaderFactory;
class URLLoaderFactoryInterfaceBase;
}
+class PendingSharedURLLoaderFactory;
class SharedURLLoaderFactory;
}
@@ -142,7 +142,9 @@ class WebResourceRequestSenderDelegate;
class WebSandboxSupport;
class WebSecurityOrigin;
class WebThemeEngine;
+class WebURLLoaderFactory;
class WebVideoCaptureImplManager;
+struct WebContentSecurityPolicyHeader;
namespace scheduler {
class WebThreadScheduler;
@@ -287,20 +289,11 @@ class BLINK_PLATFORM_EXPORT Platform {
// Network -------------------------------------------------------------
- // Returns the WebCodeCacheLoader that is used to fetch data from code caches.
- // It is OK to return a nullptr. When a nullptr is returned, data would not
- // be fetched from code cache.
- virtual std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() {
- return nullptr;
- }
-
// Returns a new WebURLLoaderFactory that wraps the given
// network::mojom::URLLoaderFactory.
virtual std::unique_ptr<WebURLLoaderFactory> WrapURLLoaderFactory(
CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase>
- url_loader_factory) {
- return nullptr;
- }
+ url_loader_factory);
// Returns a new WebURLLoaderFactory that wraps the given
// network::SharedURLLoaderFactory.
@@ -328,6 +321,7 @@ class BLINK_PLATFORM_EXPORT Platform {
const uint8_t* data,
size_t data_size) {}
+ // A request to fetch contents associated with this URL from metadata cache.
using FetchCachedCodeCallback =
base::OnceCallback<void(base::Time, mojo_base::BigBuffer)>;
// A request to fetch previously cached code for the resource fetched from the
@@ -336,9 +330,6 @@ class BLINK_PLATFORM_EXPORT Platform {
virtual void FetchCachedCode(blink::mojom::CodeCacheType cache_type,
const WebURL&,
FetchCachedCodeCallback) {}
- // A request to clear cached code from storage. This can be called by the
- // Renderer after fetching cached code that has become stale due to changes
- // in the Renderer or runtime environment.
virtual void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type,
const GURL&) {}
@@ -449,7 +440,7 @@ class BLINK_PLATFORM_EXPORT Platform {
// used for resources which have compress="gzip" in *.grd.
virtual WebData GetDataResource(
int resource_id,
- ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_NONE) {
+ ui::ResourceScaleFactor scale_factor = ui::SCALE_FACTOR_NONE) {
return WebData();
}
@@ -609,7 +600,7 @@ class BLINK_PLATFORM_EXPORT Platform {
// Whether zoom for dsf is enabled. When true, inputs to blink would all be
// scaled by the device scale factor so that layout is done in device pixel
// space.
- virtual bool IsUseZoomForDSFEnabled() { return false; }
+ virtual bool IsUseZoomForDSFEnabled() { return true; }
// Whether LCD text is enabled.
virtual bool IsLcdTextEnabled() { return false; }
@@ -785,7 +776,7 @@ class BLINK_PLATFORM_EXPORT Platform {
worker_timing_callback_task_runner,
base::RepeatingCallback<
void(int, mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>)>
- worker_timing_callback) {}
+ worker_timing_callback);
// WebCrypto ----------------------------------------------------------
@@ -822,11 +813,14 @@ class BLINK_PLATFORM_EXPORT Platform {
// MediaLog from any thread, but it must be destroyed on |owner_task_runner|.
// MediaLog owners should destroy the MediaLog if the ExecutionContext is
// destroyed, since |inspector_context| may no longer be valid at that point.
+ // |is_on_worker| is used to avoid logging to the chrome://media-internal
+ // page, which can only be logged to from the window main thread.
// Note: |inspector_context| is only used on |owner_task_runner|, so
// destroying the MediaLog on |owner_task_runner| should avoid races.
virtual std::unique_ptr<media::MediaLog> GetMediaLog(
MediaInspectorContext* inspector_context,
- scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner,
+ bool is_on_worker) {
return nullptr;
}
@@ -873,6 +867,14 @@ class BLINK_PLATFORM_EXPORT Platform {
return nullptr;
}
+ // Content Security Policy --------------------------------------
+
+ // Appends to `csp`, the default CSP which should be applied to the given
+ // `url`. This allows the embedder to customize the applied CSP.
+ virtual void AppendContentSecurityPolicy(
+ const WebURL& url,
+ blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) {}
+
private:
static void InitializeMainThreadCommon(Platform* platform,
std::unique_ptr<Thread> main_thread);
diff --git a/chromium/third_party/blink/public/platform/scheduler/DEPS b/chromium/third_party/blink/public/platform/scheduler/DEPS
index ba3516c3c6e..3c616efdbe2 100644
--- a/chromium/third_party/blink/public/platform/scheduler/DEPS
+++ b/chromium/third_party/blink/public/platform/scheduler/DEPS
@@ -10,7 +10,6 @@ include_rules = [
"+base/threading/thread.h",
"+base/time/time.h",
"+build/build_config.h",
- "+third_party/abseil-cpp/absl/types/optional.h",
# Currently the only AgentSchedulingGroup-scoped object in Blink is the
# AgentGroupScheduler. As such, that is how we provide access to the
# ASG-bound BrowserInterfaceBroker, necessitating this dependency.
diff --git a/chromium/third_party/blink/public/platform/scheduler/web_thread_scheduler.h b/chromium/third_party/blink/public/platform/scheduler/web_thread_scheduler.h
index 4a30e525e27..edecd04c1ab 100644
--- a/chromium/third_party/blink/public/platform/scheduler/web_thread_scheduler.h
+++ b/chromium/third_party/blink/public/platform/scheduler/web_thread_scheduler.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/message_loop/message_pump.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
@@ -42,6 +41,8 @@ class WebWidgetScheduler;
class BLINK_PLATFORM_EXPORT WebThreadScheduler {
public:
+ WebThreadScheduler(const WebThreadScheduler&) = delete;
+ WebThreadScheduler& operator=(const WebThreadScheduler&) = delete;
virtual ~WebThreadScheduler();
// ==== Functions for any scheduler =========================================
@@ -74,6 +75,10 @@ class BLINK_PLATFORM_EXPORT WebThreadScheduler {
// Returns the default task runner.
virtual scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner();
+ // Returns a task runner for input-blocking tasks on the compositor thread.
+ // (For input tasks on the main thread, use WebWidgetScheduler instead.)
+ virtual scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner();
+
// Returns the compositor task runner.
virtual scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner();
@@ -216,10 +221,9 @@ class BLINK_PLATFORM_EXPORT WebThreadScheduler {
class BLINK_PLATFORM_EXPORT RendererPauseHandle {
public:
RendererPauseHandle() = default;
+ RendererPauseHandle(const RendererPauseHandle&) = delete;
+ RendererPauseHandle& operator=(const RendererPauseHandle&) = delete;
virtual ~RendererPauseHandle() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RendererPauseHandle);
};
// Tells the scheduler that the renderer process should be paused.
@@ -248,7 +252,6 @@ class BLINK_PLATFORM_EXPORT WebThreadScheduler {
protected:
WebThreadScheduler() = default;
- DISALLOW_COPY_AND_ASSIGN(WebThreadScheduler);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/public/platform/task_type.h b/chromium/third_party/blink/public/platform/task_type.h
index d2b2e22ea23..4f1bd8e66a4 100644
--- a/chromium/third_party/blink/public/platform/task_type.h
+++ b/chromium/third_party/blink/public/platform/task_type.h
@@ -13,7 +13,7 @@ namespace blink {
// For the task type usage guideline, see https://bit.ly/2vMAsQ4
//
// When a new task type is created:
-// * use kCount value as a new value,
+// * Update kMaxValue to point to a new value
// * in tools/metrics/histograms/enums.xml update the
// "RendererSchedulerTaskType" enum
// * update TaskTypes.md
@@ -261,6 +261,9 @@ enum class TaskType : unsigned char {
// Tasks related to the WebGPU API
kWebGPU = 78,
+ // Cross-process PostMessage IPCs that are deferred in the current task.
+ kInternalPostMessageForwarding = 79,
+
///////////////////////////////////////
// The following task types are only for thread-local queues.
///////////////////////////////////////
@@ -288,7 +291,7 @@ enum class TaskType : unsigned char {
kWorkerThreadTaskQueueV8 = 47,
kWorkerThreadTaskQueueCompositor = 48,
- kCount = 79,
+ kMaxValue = kInternalPostMessageForwarding,
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h b/chromium/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h
index adf5e3b76cb..4dd0e7c0c81 100644
--- a/chromium/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h
+++ b/chromium/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h
@@ -39,6 +39,10 @@ class BLINK_PLATFORM_EXPORT TrackedChildPendingURLLoaderFactoryBundle
pending_prefetch_loader_factory,
std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle,
bool bypass_redirect_checks);
+ TrackedChildPendingURLLoaderFactoryBundle(
+ const TrackedChildPendingURLLoaderFactoryBundle&) = delete;
+ TrackedChildPendingURLLoaderFactoryBundle& operator=(
+ const TrackedChildPendingURLLoaderFactoryBundle&) = delete;
~TrackedChildPendingURLLoaderFactoryBundle() override;
std::unique_ptr<HostPtrAndTaskRunner>& main_thread_host_bundle() {
@@ -52,8 +56,6 @@ class BLINK_PLATFORM_EXPORT TrackedChildPendingURLLoaderFactoryBundle
scoped_refptr<network::SharedURLLoaderFactory> CreateFactory() override;
std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedChildPendingURLLoaderFactoryBundle);
};
// This class extends |ChildURLLoaderFactoryBundle| to support a
@@ -77,6 +79,10 @@ class BLINK_PLATFORM_EXPORT TrackedChildURLLoaderFactoryBundle
explicit TrackedChildURLLoaderFactoryBundle(
std::unique_ptr<TrackedChildPendingURLLoaderFactoryBundle>
pending_factories);
+ TrackedChildURLLoaderFactoryBundle(
+ const TrackedChildURLLoaderFactoryBundle&) = delete;
+ TrackedChildURLLoaderFactoryBundle& operator=(
+ const TrackedChildURLLoaderFactoryBundle&) = delete;
// ChildURLLoaderFactoryBundle overrides.
// Returns |std::unique_ptr<TrackedChildPendingURLLoaderFactoryBundle>|.
@@ -102,8 +108,6 @@ class BLINK_PLATFORM_EXPORT TrackedChildURLLoaderFactoryBundle
// |WeakPtr| and |TaskRunner| of the host bundle. Can be copied and passed
// across sequences.
std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedChildURLLoaderFactoryBundle);
};
// |HostChildURLLoaderFactoryBundle| lives entirely on the main thread, and all
@@ -114,6 +118,10 @@ class BLINK_PLATFORM_EXPORT HostChildURLLoaderFactoryBundle
: public ChildURLLoaderFactoryBundle,
public base::SupportsWeakPtr<HostChildURLLoaderFactoryBundle> {
public:
+ HostChildURLLoaderFactoryBundle(const HostChildURLLoaderFactoryBundle&) =
+ delete;
+ HostChildURLLoaderFactoryBundle& operator=(
+ const HostChildURLLoaderFactoryBundle&) = delete;
using ObserverPtrAndTaskRunner =
std::pair<base::WeakPtr<TrackedChildURLLoaderFactoryBundle>,
scoped_refptr<base::SequencedTaskRunner>>;
@@ -162,8 +170,6 @@ class BLINK_PLATFORM_EXPORT HostChildURLLoaderFactoryBundle
std::unique_ptr<ObserverList> observer_list_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(HostChildURLLoaderFactoryBundle);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/web_audio_device.h b/chromium/third_party/blink/public/platform/web_audio_device.h
index 834f80978b3..571c66f2c25 100644
--- a/chromium/third_party/blink/public/platform/web_audio_device.h
+++ b/chromium/third_party/blink/public/platform/web_audio_device.h
@@ -44,7 +44,7 @@ class WebAudioDevice {
// |delay| does *not* represent the point-in-time at which the first
// rendered sample will be played out.
virtual void Render(const WebVector<float*>& destination_data,
- size_t number_of_frames,
+ uint32_t number_of_frames,
double delay, // Output delay in seconds.
double delay_timestamp, // System timestamp in seconds
// when |delay| was obtained.
diff --git a/chromium/third_party/blink/public/platform/web_audio_source_provider.h b/chromium/third_party/blink/public/platform/web_audio_source_provider.h
index 1ce318e991a..6391ade4178 100644
--- a/chromium/third_party/blink/public/platform/web_audio_source_provider.h
+++ b/chromium/third_party/blink/public/platform/web_audio_source_provider.h
@@ -39,7 +39,7 @@ class WebAudioSourceProvider {
// ProvideInput() gets called repeatedly to render time-slices of a continuous
// audio stream. May be called from any thread.
virtual void ProvideInput(const WebVector<float*>& audio_data,
- size_t number_of_frames) = 0;
+ int number_of_frames) = 0;
// If a client is set, we call it back when the audio format is available.
// Must always be called from the same thread. I.e., once called on a thread,
diff --git a/chromium/third_party/blink/public/platform/web_blob_info.h b/chromium/third_party/blink/public/platform/web_blob_info.h
index a2785c0e9b8..d15f3f3df9b 100644
--- a/chromium/third_party/blink/public/platform/web_blob_info.h
+++ b/chromium/third_party/blink/public/platform/web_blob_info.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_BLOB_INFO_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_BLOB_INFO_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-shared.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/web_common.h"
diff --git a/chromium/third_party/blink/public/platform/web_client_hints_type.h b/chromium/third_party/blink/public/platform/web_client_hints_type.h
deleted file mode 100644
index 2b166fcf309..00000000000
--- a/chromium/third_party/blink/public/platform/web_client_hints_type.h
+++ /dev/null
@@ -1,31 +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_PUBLIC_PLATFORM_WEB_CLIENT_HINTS_TYPE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CLIENT_HINTS_TYPE_H_
-
-#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
-
-namespace blink {
-
-// WebEnabledClientHints stores all the client hints along with whether the hint
-// is enabled or not.
-struct WebEnabledClientHints {
- WebEnabledClientHints() = default;
-
- bool IsEnabled(network::mojom::WebClientHintsType type) const {
- return enabled_types_[static_cast<int>(type)];
- }
- void SetIsEnabled(network::mojom::WebClientHintsType type, bool should_send) {
- enabled_types_[static_cast<int>(type)] = should_send;
- }
-
- bool enabled_types_[static_cast<int>(
- network::mojom::WebClientHintsType::kMaxValue) +
- 1] = {};
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CLIENT_HINTS_TYPE_H_
diff --git a/chromium/third_party/blink/public/platform/web_code_cache_loader.h b/chromium/third_party/blink/public/platform/web_code_cache_loader.h
index 3b924dc9896..daf84d36f3e 100644
--- a/chromium/third_party/blink/public/platform/web_code_cache_loader.h
+++ b/chromium/third_party/blink/public/platform/web_code_cache_loader.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "mojo/public/cpp/base/big_buffer.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-forward.h"
#include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -24,15 +25,7 @@ class BLINK_PLATFORM_EXPORT WebCodeCacheLoader {
virtual ~WebCodeCacheLoader() = default;
static std::unique_ptr<WebCodeCacheLoader> Create(
- base::WaitableEvent* terminate_sync_load_event = nullptr);
-
- // Fetched code cache corresponding to |url| synchronously and returns
- // response in |response_time_out| and |data_out|. |response_time_out| and
- // |data_out| cannot be nullptrs.
- virtual void FetchFromCodeCacheSynchronously(
- const WebURL& url,
- base::Time* response_time_out,
- mojo_base::BigBuffer* data_out) = 0;
+ blink::mojom::CodeCacheHost* code_cache_host);
virtual void FetchFromCodeCache(blink::mojom::CodeCacheType cache_type,
const WebURL& url,
FetchCodeCacheCallback) = 0;
diff --git a/chromium/third_party/blink/public/platform/web_content_decryption_module_session.h b/chromium/third_party/blink/public/platform/web_content_decryption_module_session.h
index cae958bd01b..9f47b3ce249 100644
--- a/chromium/third_party/blink/public/platform/web_content_decryption_module_session.h
+++ b/chromium/third_party/blink/public/platform/web_content_decryption_module_session.h
@@ -38,6 +38,8 @@
#include "third_party/blink/public/platform/web_vector.h"
namespace media {
+enum class CdmMessageType;
+enum class CdmSessionClosedReason;
enum class EmeInitDataType;
}
@@ -50,17 +52,10 @@ class BLINK_PLATFORM_EXPORT WebContentDecryptionModuleSession {
public:
class BLINK_PLATFORM_EXPORT Client {
public:
- enum class MessageType {
- kLicenseRequest,
- kLicenseRenewal,
- kLicenseRelease,
- kIndividualizationRequest
- };
-
- virtual void OnSessionMessage(MessageType,
+ virtual void OnSessionMessage(media::CdmMessageType,
const unsigned char* message,
size_t message_length) = 0;
- virtual void OnSessionClosed() = 0;
+ virtual void OnSessionClosed(media::CdmSessionClosedReason reason) = 0;
// Called when the expiration time for the session changes.
// |updated_expiry_time_in_ms| is specified as the number of milliseconds
diff --git a/chromium/third_party/blink/public/platform/web_content_security_policy_struct.h b/chromium/third_party/blink/public/platform/web_content_security_policy_struct.h
index d76135d5398..1e49abb26df 100644
--- a/chromium/third_party/blink/public/platform/web_content_security_policy_struct.h
+++ b/chromium/third_party/blink/public/platform/web_content_security_policy_struct.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CONTENT_SECURITY_POLICY_STRUCT_H_
#include "services/network/public/mojom/content_security_policy.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
@@ -61,6 +62,7 @@ struct WebCSPSourceList {
bool allow_inline;
bool allow_eval;
bool allow_wasm_eval;
+ bool allow_wasm_unsafe_eval;
bool allow_dynamic;
bool allow_unsafe_hashes;
bool report_sample;
diff --git a/chromium/third_party/blink/public/platform/web_content_settings_client.h b/chromium/third_party/blink/public/platform/web_content_settings_client.h
index 82770c85f06..49449b238fb 100644
--- a/chromium/third_party/blink/public/platform/web_content_settings_client.h
+++ b/chromium/third_party/blink/public/platform/web_content_settings_client.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/time/time.h"
-#include "third_party/blink/public/platform/web_client_hints_type.h"
+#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
namespace blink {
@@ -101,7 +101,7 @@ class WebContentSettingsClient {
// Called to persist the received client hint preferences when |url| was
// fetched. The preferences should be persisted for |duration|.
virtual void PersistClientHints(
- const WebEnabledClientHints& enabled_client_hints,
+ const EnabledClientHints& enabled_client_hints,
base::TimeDelta duration,
const blink::WebURL& url) {}
diff --git a/chromium/third_party/blink/public/platform/web_font.h b/chromium/third_party/blink/public/platform/web_font.h
index b2ad22d495f..97f0cffd8aa 100644
--- a/chromium/third_party/blink/public/platform/web_font.h
+++ b/chromium/third_party/blink/public/platform/web_font.h
@@ -10,7 +10,7 @@
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/skia/include/core/SkColor.h"
-// To avoid conflicts with the CreateWindow macro from the Windows SDK...
+// To avoid conflicts with the DrawText macro from the Windows SDK...
#undef DrawText
namespace cc {
diff --git a/chromium/third_party/blink/public/platform/web_http_load_info.h b/chromium/third_party/blink/public/platform/web_http_load_info.h
deleted file mode 100644
index ea1aef6054f..00000000000
--- a/chromium/third_party/blink/public/platform/web_http_load_info.h
+++ /dev/null
@@ -1,87 +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_PUBLIC_PLATFORM_WEB_HTTP_LOAD_INFO_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_HTTP_LOAD_INFO_H_
-
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_private_ptr.h"
-
-namespace blink {
-
-class WebString;
-struct ResourceLoadInfo;
-
-class WebHTTPLoadInfo {
- public:
- WebHTTPLoadInfo() { Initialize(); }
- ~WebHTTPLoadInfo() { Reset(); }
- WebHTTPLoadInfo(const WebHTTPLoadInfo& r) { Assign(r); }
- WebHTTPLoadInfo& operator=(const WebHTTPLoadInfo& r) {
- Assign(r);
- return *this;
- }
-
- BLINK_PLATFORM_EXPORT void Initialize();
- BLINK_PLATFORM_EXPORT void Reset();
- BLINK_PLATFORM_EXPORT void Assign(const WebHTTPLoadInfo& r);
-
- BLINK_PLATFORM_EXPORT int HttpStatusCode() const;
- BLINK_PLATFORM_EXPORT void SetHTTPStatusCode(int);
-
- BLINK_PLATFORM_EXPORT WebString HttpStatusText() const;
- BLINK_PLATFORM_EXPORT void SetHTTPStatusText(const WebString&);
-
- BLINK_PLATFORM_EXPORT void AddRequestHeader(const WebString& name,
- const WebString& value);
- BLINK_PLATFORM_EXPORT void AddResponseHeader(const WebString& name,
- const WebString& value);
-
- BLINK_PLATFORM_EXPORT WebString RequestHeadersText() const;
- BLINK_PLATFORM_EXPORT void SetRequestHeadersText(const WebString&);
-
- BLINK_PLATFORM_EXPORT WebString ResponseHeadersText() const;
- BLINK_PLATFORM_EXPORT void SetResponseHeadersText(const WebString&);
-
- BLINK_PLATFORM_EXPORT WebString NpnNegotiatedProtocol() const;
- BLINK_PLATFORM_EXPORT void SetNPNNegotiatedProtocol(const WebString&);
-
-#if INSIDE_BLINK
- BLINK_PLATFORM_EXPORT WebHTTPLoadInfo(scoped_refptr<ResourceLoadInfo>);
- BLINK_PLATFORM_EXPORT operator scoped_refptr<ResourceLoadInfo>() const;
-#endif
-
- private:
- WebPrivatePtr<ResourceLoadInfo> private_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_HTTP_LOAD_INFO_H_
diff --git a/chromium/third_party/blink/public/platform/web_impression.h b/chromium/third_party/blink/public/platform/web_impression.h
index d41effce77a..a5bbb4cdeda 100644
--- a/chromium/third_party/blink/public/platform/web_impression.h
+++ b/chromium/third_party/blink/public/platform/web_impression.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/public/platform/web_loader_freeze_mode.h b/chromium/third_party/blink/public/platform/web_loader_freeze_mode.h
new file mode 100644
index 00000000000..f80501a7e9b
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/web_loader_freeze_mode.h
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_LOADER_FREEZE_MODE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_LOADER_FREEZE_MODE_H_
+
+namespace blink {
+
+// An enum representing the mode of "freezing".
+// See also: third_party/blink/renderer/platform/loader/README.md
+enum class WebLoaderFreezeMode : uint8_t {
+ // Stop any incoming IPCs. Note that freezing loaders too long with this
+ // mode has negative performance impact globally, because the network
+ // service and the resource scheduler on it will be confused by this behavior.
+ kStrict,
+
+ // Do not stop incoming IPCs. Instead, read and buffer them. In some cases
+ // this is impossible (e.g., the response body is too large), and in such
+ // cases the loading would fail and the system will be notified.
+ kBufferIncoming,
+
+ // Stop freezing. This value will be moved out of this enum soon.
+ kNone,
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_LOADER_FREEZE_MODE_H_
diff --git a/chromium/third_party/blink/public/platform/web_media_player.h b/chromium/third_party/blink/public/platform/web_media_player.h
index 1da629188f4..306f13ae8af 100644
--- a/chromium/third_party/blink/public/platform/web_media_player.h
+++ b/chromium/third_party/blink/public/platform/web_media_player.h
@@ -36,6 +36,7 @@
#include "base/time/time.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "media/base/video_frame_metadata.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/media/display_type.h"
#include "third_party/blink/public/platform/web_content_decryption_module.h"
#include "third_party/blink/public/platform/web_media_source.h"
diff --git a/chromium/third_party/blink/public/platform/web_media_player_client.h b/chromium/third_party/blink/public/platform/web_media_player_client.h
index 6762c5f6c1c..55e80c1e542 100644
--- a/chromium/third_party/blink/public/platform/web_media_player_client.h
+++ b/chromium/third_party/blink/public/platform/web_media_player_client.h
@@ -185,11 +185,15 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
// Notify the client that the playback position has changed.
virtual void DidPlayerMediaPositionStateChange(double playback_rate,
base::TimeDelta duration,
- base::TimeDelta position) = 0;
+ base::TimeDelta position,
+ bool end_of_media) = 0;
// Notify the client that the audio sink cannot be changed.
virtual void DidDisableAudioOutputSinkChanges() = 0;
+ // Notify the client that the playback starts/stops to use AudioService.
+ virtual void DidUseAudioServiceChange(bool uses_audio_service) = 0;
+
// Notify the client that the size of the media player has changed.
// TODO(crbug.com/1039252): Remove by merging this method into SizeChanged().
virtual void DidPlayerSizeChange(const gfx::Size& size) = 0;
diff --git a/chromium/third_party/blink/public/platform/web_navigation_body_loader.h b/chromium/third_party/blink/public/platform/web_navigation_body_loader.h
index 384d8a16203..4ca39acb4ef 100644
--- a/chromium/third_party/blink/public/platform/web_navigation_body_loader.h
+++ b/chromium/third_party/blink/public/platform/web_navigation_body_loader.h
@@ -8,12 +8,19 @@
#include "base/containers/span.h"
#include "base/time/time.h"
#include "mojo/public/cpp/base/big_buffer.h"
+#include "services/network/public/mojom/url_loader.mojom-forward.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-forward.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
+#include "third_party/blink/public/platform/web_loader_freeze_mode.h"
#include "third_party/blink/public/platform/web_url_error.h"
-#include "third_party/blink/public/platform/web_url_loader.h"
namespace blink {
+class ResourceLoadInfoNotifierWrapper;
+struct WebNavigationParams;
+
// This class is used to load the body of main resource during navigation.
// It is provided by the client which commits a navigation.
// See WebNavigationParams for more details.
@@ -42,18 +49,34 @@ class BLINK_EXPORT WebNavigationBodyLoader {
const absl::optional<WebURLError>& error) = 0;
};
+ // This method fills navigation params related to the navigation request,
+ // redirects and response, and also creates a body loader if needed.
+ static void FillNavigationParamsResponseAndBodyLoader(
+ mojom::CommonNavigationParamsPtr common_params,
+ mojom::CommitNavigationParamsPtr commit_params,
+ int request_id,
+ network::mojom::URLResponseHeadPtr response_head,
+ mojo::ScopedDataPipeConsumerHandle response_body,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ bool is_main_frame,
+ WebNavigationParams* navigation_params);
+
// It should be safe to destroy WebNavigationBodyLoader at any moment,
// including from inside any client notification.
virtual ~WebNavigationBodyLoader() {}
- // While deferred, data will be read on the renderer side but will not invoke
+ // While frozen, data will be read on the renderer side but will not invoke
// any web-exposed behavior such as dispatching messages or handling
// redirects. This method can be called multiple times at any moment.
- virtual void SetDefersLoading(WebURLLoader::DeferType defers) = 0;
+ virtual void SetDefersLoading(WebLoaderFreezeMode mode) = 0;
// Starts loading the body. Client must be non-null, and will receive
// the body, code cache and final result.
- virtual void StartLoadingBody(Client*, bool use_isolated_code_cache) = 0;
+ virtual void StartLoadingBody(Client*,
+ mojom::CodeCacheHost* code_cache_host) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/web_resource_request_sender.h b/chromium/third_party/blink/public/platform/web_resource_request_sender.h
index 89ee407ff7d..c9084fa62b0 100644
--- a/chromium/third_party/blink/public/platform/web_resource_request_sender.h
+++ b/chromium/third_party/blink/public/platform/web_resource_request_sender.h
@@ -12,10 +12,10 @@
#include <string>
#include <vector>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
@@ -30,7 +30,7 @@
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/platform/web_loader_freeze_mode.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "url/gurl.h"
@@ -129,8 +129,10 @@ class BLINK_PLATFORM_EXPORT WebResourceRequestSender {
// Cancels the current request and `request_info_` will be released.
virtual void Cancel(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- // Toggles the is_deferred attribute for the specified request.
- virtual void SetDefersLoading(WebURLLoader::DeferType value);
+ // Freezes the loader. See blink/renderer/platform/loader/README.md for the
+ // general concept of "freezing" in the loading module. See
+ // blink/public/platform/web_loader_freezing_mode.h for `mode`.
+ virtual void Freeze(WebLoaderFreezeMode mode);
// Indicates the priority of the specified request changed.
void DidChangePriority(net::RequestPriority new_priority,
@@ -181,7 +183,7 @@ class BLINK_PLATFORM_EXPORT WebResourceRequestSender {
scoped_refptr<WebRequestPeer> peer;
network::mojom::RequestDestination request_destination;
- WebURLLoader::DeferType is_deferred = WebURLLoader::DeferType::kNotDeferred;
+ WebLoaderFreezeMode freeze_mode = WebLoaderFreezeMode::kNone;
// Original requested url.
GURL url;
// The url, method and referrer of the latest response even in case of
diff --git a/chromium/third_party/blink/public/platform/web_runtime_features.h b/chromium/third_party/blink/public/platform/web_runtime_features.h
index bf06f4719c8..b01e2b900ca 100644
--- a/chromium/third_party/blink/public/platform/web_runtime_features.h
+++ b/chromium/third_party/blink/public/platform/web_runtime_features.h
@@ -75,6 +75,7 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableAccessibilityExposeHTMLElement(bool);
BLINK_PLATFORM_EXPORT static void EnableAccessibilityExposeIgnoredNodes(bool);
BLINK_PLATFORM_EXPORT static void EnableAccessibilityObjectModel(bool);
+ BLINK_PLATFORM_EXPORT static void EnableAccessibilityPageZoom(bool);
BLINK_PLATFORM_EXPORT static void
EnableAccessibilityUseAXPositionForDocumentMarkers(bool);
BLINK_PLATFORM_EXPORT static void EnableAdTagging(bool);
@@ -94,21 +95,18 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableClickPointerEvent(bool enable);
BLINK_PLATFORM_EXPORT static void EnableCompositeBGColorAnimation(
bool enable);
- BLINK_PLATFORM_EXPORT static void EnableCookiesWithoutSameSiteMustBeSecure(
- bool);
BLINK_PLATFORM_EXPORT static void EnableCanvas2dImageChromium(bool);
BLINK_PLATFORM_EXPORT static void EnableCooperativeScheduling(bool);
BLINK_PLATFORM_EXPORT static void EnableCSSHexAlphaColor(bool);
- BLINK_PLATFORM_EXPORT static void EnableSameSiteByDefaultCookies(bool);
BLINK_PLATFORM_EXPORT static void EnableScrollTopLeftInterop(bool);
BLINK_PLATFORM_EXPORT static void EnableKeyboardAccessibleTooltip(bool);
BLINK_PLATFORM_EXPORT static void EnableKeyboardFocusableScrollers(bool);
BLINK_PLATFORM_EXPORT static void EnableDatabase(bool);
BLINK_PLATFORM_EXPORT static void EnableDecodeJpeg420ImagesToYUV(bool);
BLINK_PLATFORM_EXPORT static void EnableDecodeLossyWebPImagesToYUV(bool);
+ BLINK_PLATFORM_EXPORT static void EnableDevicePosture(bool enable);
BLINK_PLATFORM_EXPORT static void EnableRemoveMobileViewportDoubleTap(
bool enable);
- BLINK_PLATFORM_EXPORT static void EnableDisallowDocumentAccess(bool);
BLINK_PLATFORM_EXPORT static void EnableDisplayCutoutAPI(bool);
BLINK_PLATFORM_EXPORT static void EnableDocumentPolicy(bool);
BLINK_PLATFORM_EXPORT static void EnableDocumentPolicyNegotiation(bool);
@@ -143,6 +141,7 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static bool IsPortalsEnabled();
BLINK_PLATFORM_EXPORT static void EnablePreciseMemoryInfo(bool);
BLINK_PLATFORM_EXPORT static void EnablePrerender2(bool);
+ BLINK_PLATFORM_EXPORT static bool IsPrerender2Enabled();
BLINK_PLATFORM_EXPORT static void EnablePresentationAPI(bool);
BLINK_PLATFORM_EXPORT static void EnablePushMessaging(bool);
BLINK_PLATFORM_EXPORT static void EnablePushSubscriptionChangeEvent(bool);
@@ -152,12 +151,14 @@ class WebRuntimeFeatures {
EnableRestrictAutomaticLazyFrameLoadingToDataSaver(bool);
BLINK_PLATFORM_EXPORT static void
EnableRestrictAutomaticLazyImageLoadingToDataSaver(bool);
+ BLINK_PLATFORM_EXPORT static void EnableSecurePaymentConfirmationAPIV3(bool);
BLINK_PLATFORM_EXPORT static void EnableSecurePaymentConfirmationDebug(bool);
BLINK_PLATFORM_EXPORT static void EnableScriptedSpeechRecognition(bool);
BLINK_PLATFORM_EXPORT static void EnableScriptedSpeechSynthesis(bool);
BLINK_PLATFORM_EXPORT static void EnableAutoLazyLoadOnReloads(bool);
BLINK_PLATFORM_EXPORT static void EnableSharedArrayBuffer(bool);
BLINK_PLATFORM_EXPORT static void EnableSharedAutofill(bool);
+ BLINK_PLATFORM_EXPORT static void EnableSharedStorageAPI(bool);
BLINK_PLATFORM_EXPORT static void EnableSharedWorker(bool);
BLINK_PLATFORM_EXPORT static void EnableTextFragmentAnchor(bool);
BLINK_PLATFORM_EXPORT static void EnableTextFragmentColorChange(bool);
@@ -166,12 +167,14 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableUserActivationSameOriginVisibility(
bool);
BLINK_PLATFORM_EXPORT static void EnableV8IdleTasks(bool);
+ BLINK_PLATFORM_EXPORT static void EnableWebAppManifestId(bool);
BLINK_PLATFORM_EXPORT static void EnableWebAuth(bool);
BLINK_PLATFORM_EXPORT static void EnableWebBluetooth(bool);
BLINK_PLATFORM_EXPORT static void
EnableWebBluetoothRemoteCharacteristicNewWriteValue(bool);
BLINK_PLATFORM_EXPORT static void EnableWebBluetoothManufacturerDataFilter(
bool);
+ BLINK_PLATFORM_EXPORT static void EnableWebGLDeveloperExtensions(bool);
BLINK_PLATFORM_EXPORT static void EnableWebGLDraftExtensions(bool);
BLINK_PLATFORM_EXPORT static void EnableWebGLImageChromium(bool);
BLINK_PLATFORM_EXPORT static void EnableWebGPU(bool);
@@ -195,7 +198,6 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void ForceOverlayFullscreenVideo(bool);
BLINK_PLATFORM_EXPORT static void EnableTimerThrottlingForBackgroundTabs(
bool);
- BLINK_PLATFORM_EXPORT static void EnableTimerThrottlingForHiddenFrames(bool);
BLINK_PLATFORM_EXPORT static void EnableExpensiveBackgroundTimerThrottling(
bool);
BLINK_PLATFORM_EXPORT static void
@@ -203,6 +205,9 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableSharedArrayBufferOnDesktop(bool);
BLINK_PLATFORM_EXPORT static void
EnableSharedArrayBufferUnrestrictedAccessAllowed(bool);
+ BLINK_PLATFORM_EXPORT static void
+ EnableCrossOriginWebAssemblyModuleSharingAllowed(bool);
+ BLINK_PLATFORM_EXPORT static void EnableDisplayCapturePermissionsPolicy(bool);
BLINK_PLATFORM_EXPORT static void EnableVideoPlaybackQuality(bool);
BLINK_PLATFORM_EXPORT static void EnableMediaControlsOverlayPlayButton(bool);
BLINK_PLATFORM_EXPORT static void EnableMediaCastOverlayButton(bool);
@@ -213,7 +218,6 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableAutoplayIgnoresWebAudio(bool);
BLINK_PLATFORM_EXPORT static void EnableMediaControlsExpandGesture(bool);
BLINK_PLATFORM_EXPORT static void EnableGetDisplayMedia(bool);
- BLINK_PLATFORM_EXPORT static void EnableGetCurrentBrowsingContextMedia(bool);
BLINK_PLATFORM_EXPORT static void EnableAllowSyncXHRInPageDismissal(bool);
BLINK_PLATFORM_EXPORT static void
EnableSignedExchangePrefetchCacheForNavigations(bool);
@@ -232,19 +236,18 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableInstalledApp(bool);
BLINK_PLATFORM_EXPORT static void EnableTransformInterop(bool);
+ BLINK_PLATFORM_EXPORT static void EnableBackfaceVisibilityInterop(bool);
BLINK_PLATFORM_EXPORT static void EnableVideoWakeLockOptimisationHiddenMuted(
bool);
BLINK_PLATFORM_EXPORT static void EnableContentIndex(bool);
BLINK_PLATFORM_EXPORT static void EnableRestrictGamepadAccess(bool);
- BLINK_PLATFORM_EXPORT static void EnableConversionMeasurementInfraSupport(
- bool);
BLINK_PLATFORM_EXPORT static void EnableTargetBlankImpliesNoOpener(bool);
BLINK_PLATFORM_EXPORT static void EnableParseUrlProtocolHandler(bool);
- BLINK_PLATFORM_EXPORT static void EnableCSSColorSchemeUARendering(bool);
BLINK_PLATFORM_EXPORT static void EnableDocumentTransition(bool);
+ BLINK_PLATFORM_EXPORT static void EnableCLSScrollAnchoring(bool);
private:
WebRuntimeFeatures();
diff --git a/chromium/third_party/blink/public/platform/web_scoped_page_pauser.h b/chromium/third_party/blink/public/platform/web_scoped_page_pauser.h
index 7b77d18f5e1..5d3df6efbd7 100644
--- a/chromium/third_party/blink/public/platform/web_scoped_page_pauser.h
+++ b/chromium/third_party/blink/public/platform/web_scoped_page_pauser.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_common.h"
namespace blink {
@@ -20,12 +19,12 @@ class WebScopedPagePauser {
public:
BLINK_EXPORT static std::unique_ptr<WebScopedPagePauser> Create();
+ WebScopedPagePauser(const WebScopedPagePauser&) = delete;
+ WebScopedPagePauser& operator=(const WebScopedPagePauser&) = delete;
BLINK_EXPORT ~WebScopedPagePauser();
private:
WebScopedPagePauser();
-
- DISALLOW_COPY_AND_ASSIGN(WebScopedPagePauser);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/web_theme_engine.h b/chromium/third_party/blink/public/platform/web_theme_engine.h
index 928a94f37a8..cf28ea0476b 100644
--- a/chromium/third_party/blink/public/platform/web_theme_engine.h
+++ b/chromium/third_party/blink/public/platform/web_theme_engine.h
@@ -194,6 +194,7 @@ class WebThemeEngine {
bool is_overlay;
mojom::ColorScheme scrollbar_theme;
ScrollbarOrientation orientation;
+ float scale_from_dip;
};
#endif
diff --git a/chromium/third_party/blink/public/platform/web_url_loader.h b/chromium/third_party/blink/public/platform/web_url_loader.h
index 042a383fe17..38947759300 100644
--- a/chromium/third_party/blink/public/platform/web_url_loader.h
+++ b/chromium/third_party/blink/public/platform/web_url_loader.h
@@ -44,6 +44,7 @@
#include "third_party/blink/public/mojom/frame/frame.mojom-forward.h"
#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_loader_freeze_mode.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/platform/web_vector.h"
@@ -133,19 +134,10 @@ class BLINK_PLATFORM_EXPORT WebURLLoader {
resource_load_info_notifier_wrapper,
WebURLLoaderClient* client);
- // |kDeferred| is when an asynchronous load is suspended.
- // |kDeferredWithBackForwardCache| is when an asynchronous load is suspended
- // with BackForwardCache, and BackForwardCache entry can be evicted when
- // redirects etc. happen.
- // |kNotDeferred| is when an asynchronous load is resumed.
- // SetDefersLoading can be called with any value at any point.
- enum class DeferType {
- kDeferred,
- kDeferredWithBackForwardCache,
- kNotDeferred
- };
- // Suspends/resumes an asynchronous load.
- virtual void SetDefersLoading(DeferType value);
+ // Freezes the loader. See blink/renderer/platform/loader/README.md for the
+ // general concept of "freezing" in the loading module. See
+ // blink/public/platform/web_loader_freezing_mode.h for `mode`.
+ virtual void Freeze(WebLoaderFreezeMode mode);
// Notifies the loader that the priority of a WebURLRequest has changed from
// its previous value. For example, a preload request starts with low
diff --git a/chromium/third_party/blink/public/platform/web_url_request.h b/chromium/third_party/blink/public/platform/web_url_request.h
index 59ae894c628..bfba1a93a18 100644
--- a/chromium/third_party/blink/public/platform/web_url_request.h
+++ b/chromium/third_party/blink/public/platform/web_url_request.h
@@ -153,11 +153,6 @@ class WebURLRequest {
BLINK_PLATFORM_EXPORT bool ReportUploadProgress() const;
BLINK_PLATFORM_EXPORT void SetReportUploadProgress(bool);
- // Controls whether actual headers sent and received for request are
- // collected and reported.
- BLINK_PLATFORM_EXPORT bool ReportRawHeaders() const;
- BLINK_PLATFORM_EXPORT void SetReportRawHeaders(bool);
-
BLINK_PLATFORM_EXPORT mojom::RequestContextType GetRequestContext() const;
BLINK_PLATFORM_EXPORT void SetRequestContext(mojom::RequestContextType);
diff --git a/chromium/third_party/blink/public/platform/web_url_request_extra_data.h b/chromium/third_party/blink/public/platform/web_url_request_extra_data.h
index a99b7a81a0f..61eeb31dc41 100644
--- a/chromium/third_party/blink/public/platform/web_url_request_extra_data.h
+++ b/chromium/third_party/blink/public/platform/web_url_request_extra_data.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/memory/ref_counted.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_frame_request_blocker.h"
diff --git a/chromium/third_party/blink/public/platform/web_url_response.h b/chromium/third_party/blink/public/platform/web_url_response.h
index f650a0bfea2..70334f9b7ac 100644
--- a/chromium/third_party/blink/public/platform/web_url_response.h
+++ b/chromium/third_party/blink/public/platform/web_url_response.h
@@ -56,7 +56,6 @@ namespace blink {
class ResourceResponse;
class WebHTTPHeaderVisitor;
-class WebHTTPLoadInfo;
class WebURL;
class WebURLResponse {
@@ -179,8 +178,6 @@ class WebURLResponse {
BLINK_PLATFORM_EXPORT void SetLoadTiming(
const network::mojom::LoadTimingInfo&);
- BLINK_PLATFORM_EXPORT void SetHTTPLoadInfo(const WebHTTPLoadInfo&);
-
BLINK_PLATFORM_EXPORT base::Time ResponseTime() const;
BLINK_PLATFORM_EXPORT void SetResponseTime(base::Time);
@@ -351,6 +348,14 @@ class WebURLResponse {
BLINK_PLATFORM_EXPORT const absl::optional<net::AuthChallengeInfo>&
AuthChallengeInfo() const;
+ // The request's |includeCredentials| value from the "HTTP-network fetch"
+ // algorithm.
+ // See: https://fetch.spec.whatwg.org/#concept-http-network-fetch
+ BLINK_PLATFORM_EXPORT void SetRequestIncludeCredentials(bool);
+ BLINK_PLATFORM_EXPORT bool RequestIncludeCredentials() const;
+
+ BLINK_PLATFORM_EXPORT void SetWasFetchedViaCache(bool);
+
#if INSIDE_BLINK
protected:
// Permit subclasses to set arbitrary ResourceResponse pointer as
diff --git a/chromium/third_party/blink/public/platform/web_vector.h b/chromium/third_party/blink/public/platform/web_vector.h
index c7d72275c9c..b8df49228c8 100644
--- a/chromium/third_party/blink/public/platform/web_vector.h
+++ b/chromium/third_party/blink/public/platform/web_vector.h
@@ -171,6 +171,9 @@ class WebVector {
data_.emplace_back(std::forward<Args>(args)...);
}
+ void push_back(const T& value) { data_.push_back(value); }
+ void push_back(T&& value) { data_.push_back(std::move(value)); }
+
void Swap(WebVector<T>& other) { data_.swap(other.data_); }
void Clear() { data_.clear(); }
diff --git a/chromium/third_party/blink/public/platform/web_video_frame_submitter.h b/chromium/third_party/blink/public/platform/web_video_frame_submitter.h
index 955ade1b4ff..a6d12a54161 100644
--- a/chromium/third_party/blink/public/platform/web_video_frame_submitter.h
+++ b/chromium/third_party/blink/public/platform/web_video_frame_submitter.h
@@ -7,6 +7,7 @@
#include "cc/layers/video_frame_provider.h"
#include "cc/metrics/video_playback_roughness_reporter.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "third_party/blink/public/platform/web_common.h"
@@ -43,6 +44,7 @@ class BLINK_PLATFORM_EXPORT WebVideoFrameSubmitter
static std::unique_ptr<WebVideoFrameSubmitter> Create(
WebContextProviderCallback,
cc::VideoPlaybackRoughnessReporter::ReportingCallback,
+ const viz::FrameSinkId& parent_frame_sink_id,
const cc::LayerTreeSettings&,
bool use_sync_primitives);
~WebVideoFrameSubmitter() override = default;
@@ -55,7 +57,7 @@ class BLINK_PLATFORM_EXPORT WebVideoFrameSubmitter
//
// TODO(dalecurtis): This could be removed in favor of getting it from each
// VideoFrame, but today that information isn't set everywhere.
- virtual void SetRotation(media::VideoRotation) = 0;
+ virtual void SetTransform(media::VideoTransformation) = 0;
// Prepares the compositor frame sink to accept frames by providing
// a SurfaceId.
diff --git a/chromium/third_party/blink/public/platform/web_worker_fetch_context.h b/chromium/third_party/blink/public/platform/web_worker_fetch_context.h
index b43859735b3..af48f6908e5 100644
--- a/chromium/third_party/blink/public/platform/web_worker_fetch_context.h
+++ b/chromium/third_party/blink/public/platform/web_worker_fetch_context.h
@@ -10,6 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/mojom/url_loader_factory.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-shared.h"
#include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-shared.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
@@ -84,7 +85,12 @@ class WebWorkerFetchContext : public base::RefCounted<WebWorkerFetchContext> {
// Returns a WebCodeCacheLoader that fetches data from code caches. If
// a nullptr is returned then data would not be fetched from the code
// cache.
- virtual std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() {
+ // TODO(mythria): Currently, code_cache_host can be a nullptr when fetching
+ // cached code from worklets. For these cases we use a per-process mojo
+ // interface. Update worklets to use context specific interface and check that
+ // code_cache_host is not a nullptr.
+ virtual std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader(
+ blink::mojom::CodeCacheHost* code_cache_host) {
return nullptr;
}
diff --git a/chromium/third_party/blink/public/platform/webaudiosourceprovider_impl.h b/chromium/third_party/blink/public/platform/webaudiosourceprovider_impl.h
index 76911d62ce2..5e15d7aa91f 100644
--- a/chromium/third_party/blink/public/platform/webaudiosourceprovider_impl.h
+++ b/chromium/third_party/blink/public/platform/webaudiosourceprovider_impl.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "media/base/audio_renderer_sink.h"
@@ -60,10 +59,14 @@ class BLINK_PLATFORM_EXPORT WebAudioSourceProviderImpl
media::MediaLog* media_log,
base::OnceClosure on_set_client_callback = base::OnceClosure());
+ WebAudioSourceProviderImpl(const WebAudioSourceProviderImpl&) = delete;
+ WebAudioSourceProviderImpl& operator=(const WebAudioSourceProviderImpl&) =
+ delete;
+
// WebAudioSourceProvider implementation.
void SetClient(WebAudioSourceProviderClient* client) override;
void ProvideInput(const WebVector<float*>& audio_data,
- size_t number_of_frames) override;
+ int number_of_frames) override;
// RestartableAudioRendererSink implementation.
void Initialize(const media::AudioParameters& params,
@@ -126,8 +129,6 @@ class BLINK_PLATFORM_EXPORT WebAudioSourceProviderImpl
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<WebAudioSourceProviderImpl> weak_factory_{this};
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(WebAudioSourceProviderImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/public_features.gni b/chromium/third_party/blink/public/public_features.gni
index b6f5b998ece..b5cc81d0e05 100644
--- a/chromium/third_party/blink/public/public_features.gni
+++ b/chromium/third_party/blink/public/public_features.gni
@@ -12,7 +12,7 @@ declare_args() {
enable_blink_heap_young_generation = false
# Enables Blink's heap to use V8's version of Oilpan.
- enable_blink_heap_use_v8_oilpan = false
+ enable_blink_heap_use_v8_oilpan = true
}
declare_args() {
@@ -26,7 +26,7 @@ declare_args() {
declare_args() {
# If true, adds support for JPEG XL image decoding.
- enable_jxl_decoder = !is_android && !is_ios
+ enable_jxl_decoder = !is_ios
}
# Unhandled Tap enable means Contextual Search aka Touch to Search.
@@ -36,3 +36,8 @@ enable_unhandled_tap = is_android
# Use Minikin hyphenation engine.
use_minikin_hyphenation = !is_mac
+
+# Forward the request for naming to cppgc.
+if (enable_additional_blink_object_names) {
+ cppgc_enable_object_names = true
+}
diff --git a/chromium/third_party/blink/public/strings/blink_strings.grd b/chromium/third_party/blink/public/strings/blink_strings.grd
index 460fcf2476f..3c89d3d6035 100644
--- a/chromium/third_party/blink/public/strings/blink_strings.grd
+++ b/chromium/third_party/blink/public/strings/blink_strings.grd
@@ -853,6 +853,9 @@ below:
<message name="IDS_AX_COMBOBOX_EXPANDED" desc="Accessibility utterance for when a combobox element is expanded, but due to authoring errors we cannot say any more information than that.">
expanded.
</message>
+ <message name="IDS_AX_DIALOG_MODAL_OPENED" desc="Accessibility utterance for when a dialog / modal has been opened.">
+ dialog opened.
+ </message>
</if>
<!-- Automatic image annotations for accessibility -->
diff --git a/chromium/third_party/blink/public/strings/blink_strings_grd/IDS_AX_DIALOG_MODAL_OPENED.png.sha1 b/chromium/third_party/blink/public/strings/blink_strings_grd/IDS_AX_DIALOG_MODAL_OPENED.png.sha1
new file mode 100644
index 00000000000..59ea0654307
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/blink_strings_grd/IDS_AX_DIALOG_MODAL_OPENED.png.sha1
@@ -0,0 +1 @@
+cd7241ddb0de97bc50a6f26c311b4ffacda4fd56 \ No newline at end of file
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_af.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_af.xtb
index 578dfca70e4..2adce5e9379 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_af.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_af.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">bladsybreuk</translation>
<translation id="2335594187091864976">datum- en tydkieser</translation>
<translation id="2393030564806080191">Heksadesimale kleurwaarde</translation>
+<translation id="2398813069815436052">dialoog oopgemaak.</translation>
<translation id="245932805758469625">hoeveel sekondes van video oor is</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vul asseblief hierdie veld in.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb
index 4b4102e0597..2c53456ba19 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ገጽ ከፋይ</translation>
<translation id="2335594187091864976">የቀን እና የሰዓት መራጭ</translation>
<translation id="2393030564806080191">ባለአስራስድስትዮሽ የቀለም እሴት</translation>
+<translation id="2398813069815436052">መገናኛ ተከፍቷል።</translation>
<translation id="245932805758469625">የቪዲዮ ቀሪ ሰከንዶች ብዛት</translation>
<translation id="248395913932153421">ቀን</translation>
<translation id="2507943997699731163">እባክዎ ይህን መስክ ይሙሉት።</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb
index 80dae1989da..c67a6f3e6de 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">فاصل صفحة</translation>
<translation id="2335594187091864976">منتقي التاريخ والوقت</translation>
<translation id="2393030564806080191">قيمة اللون السداسية العشرية</translation>
+<translation id="2398813069815436052">تم فتح مربع الحوار.</translation>
<translation id="245932805758469625">عدد الثواني المتبقية من الفيديو</translation>
<translation id="248395913932153421">يوم</translation>
<translation id="2507943997699731163">يُرجى ملء هذا الحقل.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_as.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_as.xtb
index 7046b119f5f..7aea69a9229 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_as.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_as.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">পৃষ্ঠা বিচ্ছেদ</translation>
<translation id="2335594187091864976">তাৰিখ আৰু সময় নিৰ্বাচক</translation>
<translation id="2393030564806080191">হেক্সাডেচিমেল ৰঙৰ মান</translation>
+<translation id="2398813069815436052">ডায়লগ খোলা হৈছে।</translation>
<translation id="245932805758469625">ভিডিঅ'টো বাকী থকা ছেকেণ্ডৰ সংখ্যা</translation>
<translation id="248395913932153421">দিন</translation>
<translation id="2507943997699731163">অনুগ্ৰহ কৰি এই খালী ঠাই পূৰ কৰক।</translation>
@@ -202,6 +203,7 @@
<translation id="6443871981718447451">ছাবটাইটেলৰ মেনু দেখুৱাওক</translation>
<translation id="6453774872122745852">কৃতজ্ঞতা</translation>
<translation id="648732519525291180">সময় বাছনিকৰ্তা</translation>
+<translation id="6550675742724504774">বিকল্প</translation>
<translation id="6572309429103589720">অমান্য ব্যাকৰণ</translation>
<translation id="658823671542763450">স্ক্রীণখন সম্পূৰ্ণ ডাঙৰ কৰক</translation>
<translation id="663493177488814956">ফীড</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_az.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_az.xtb
index adc0b0c2c7a..7421acba542 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_az.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_az.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">səhifə sonu</translation>
<translation id="2335594187091864976">tarix və saat seçici</translation>
<translation id="2393030564806080191">Altırəqəmli rəng dəyəri</translation>
+<translation id="2398813069815436052">dialoq açılıb.</translation>
<translation id="245932805758469625">videonun göstərilməmiş saniyələrinin sayı</translation>
<translation id="248395913932153421">Gün</translation>
<translation id="2507943997699731163">Lütfən, bu sahəni doldurun.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_be.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_be.xtb
index 972630b05b7..69f9afd4669 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_be.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_be.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">разрыў старонкі</translation>
<translation id="2335594187091864976">выбар даты і часу</translation>
<translation id="2393030564806080191">Шаснаццатковае значэнне колеру</translation>
+<translation id="2398813069815436052">дыялогавае акно адкрыта.</translation>
<translation id="245932805758469625">колькі секунд відэа засталося</translation>
<translation id="248395913932153421">Дзень</translation>
<translation id="2507943997699731163">Запоўніце гэта поле.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb
index fbf50dc0b3c..e4e77ebfd07 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">разделител на страници</translation>
<translation id="2335594187091864976">инструмент за избор на дата и час</translation>
<translation id="2393030564806080191">Шестнадесетична стойност за цвета</translation>
+<translation id="2398813069815436052">диалоговият прозорец е отворен.</translation>
<translation id="245932805758469625">оставащи секунди до края на видеоклипа</translation>
<translation id="248395913932153421">Ден</translation>
<translation id="2507943997699731163">Моля, попълнете това поле.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb
index 3150a579dae..9a5b12996b4 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">পৃষ্ঠা বিরতি</translation>
<translation id="2335594187091864976">তারিখ এবং সময় চয়নকারি</translation>
<translation id="2393030564806080191">রঙের হেক্সাডেসিমেল মান</translation>
+<translation id="2398813069815436052">ডায়ালগ খোলা হয়েছে।</translation>
<translation id="245932805758469625">ভিডিও শেষ হতে এখনও যত সেকেন্ড বাকি আছে</translation>
<translation id="248395913932153421">দিন</translation>
<translation id="2507943997699731163">দয়া করে এই ক্ষেত্রটি পূরণ করুন৷</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_bs.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_bs.xtb
index aea5f47be03..18e18915ffe 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_bs.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_bs.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">prijelom stranice</translation>
<translation id="2335594187091864976">odabirač datuma i vremena</translation>
<translation id="2393030564806080191">Heksadecimalna vrijednost boje</translation>
+<translation id="2398813069815436052">dijaloški okvir je otvoren.</translation>
<translation id="245932805758469625">preostali broj sekundi videozapisa</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Ispunite ovo polje.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb
index 6abe938b466..1a47c674a11 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">salt de pàgina</translation>
<translation id="2335594187091864976">selector de data i hora</translation>
<translation id="2393030564806080191">Valor hexadecimal del color</translation>
+<translation id="2398813069815436052">s'ha obert el quadre de diàleg.</translation>
<translation id="245932805758469625">nombre de segons restants del vídeo</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Empleneu aquest camp.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb
index 9167a6bf3f9..1c3eff1d8a3 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">konec stránky</translation>
<translation id="2335594187091864976">výběr data a času</translation>
<translation id="2393030564806080191">Hexadecimální hodnota barvy</translation>
+<translation id="2398813069815436052">dialogové okno je otevřeno.</translation>
<translation id="245932805758469625">zbývající čas videa v sekundách</translation>
<translation id="248395913932153421">Den</translation>
<translation id="2507943997699731163">Vyplňte prosím toto pole.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb
index 306762329ef..999adb2b890 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sideskift</translation>
<translation id="2335594187091864976">dato- og tidsvælger</translation>
<translation id="2393030564806080191">Hexadecimal farveværdi</translation>
+<translation id="2398813069815436052">dialogboksen er åbnet.</translation>
<translation id="245932805758469625">antal sekunder tilbage af videoen</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Udfyld dette felt.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb
index ca0c7aa3322..b2228a814c4 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">Seitenumbruch</translation>
<translation id="2335594187091864976">Datums- und Uhrzeitauswahl</translation>
<translation id="2393030564806080191">Hexadezimal-Farbwert</translation>
+<translation id="2398813069815436052">Dialogfeld geöffnet.</translation>
<translation id="245932805758469625">verbleibende Videozeit in Sekunden</translation>
<translation id="248395913932153421">Tag</translation>
<translation id="2507943997699731163">Füllen Sie dieses Feld aus.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb
index 044a214a6dd..edafe996fa1 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">αλλαγή σελίδας</translation>
<translation id="2335594187091864976">εργαλείο επιλογής ημερομηνίας και ώρας</translation>
<translation id="2393030564806080191">Δεκαεξαδική τιμή χρώματος</translation>
+<translation id="2398813069815436052">το παράθυρο διαλόγου άνοιξε.</translation>
<translation id="245932805758469625">χρόνος που απομένει από το βίντεο σε δευτερόλεπτα</translation>
<translation id="248395913932153421">Ημέρα</translation>
<translation id="2507943997699731163">Συμπληρώστε αυτό το πεδίο.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb
index e9286c37467..39b5c325957 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">page break</translation>
<translation id="2335594187091864976">date and time picker</translation>
<translation id="2393030564806080191">Hexadecimal colour value</translation>
+<translation id="2398813069815436052">dialogue opened.</translation>
<translation id="245932805758469625">number of seconds of video remaining</translation>
<translation id="248395913932153421">Day</translation>
<translation id="2507943997699731163">Please fill in this field.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb
index f6cbc0f7f85..635f2e57d7b 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">salto de página</translation>
<translation id="2335594187091864976">selector de fecha y hora</translation>
<translation id="2393030564806080191">Valor hexadecimal de color</translation>
+<translation id="2398813069815436052">Se abrió el diálogo.</translation>
<translation id="245932805758469625">cantidad de segundos restantes del video</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb
index 0ad454a1c31..420298d3a86 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">salto de página</translation>
<translation id="2335594187091864976">selector de fecha y hora</translation>
<translation id="2393030564806080191">Valor hexadecimal del color</translation>
+<translation id="2398813069815436052">Cuadro de diálogo abierto.</translation>
<translation id="245932805758469625">segundos de vídeo restantes</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb
index fe8a3668c62..a2ec829c0b8 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">leheküljepiir</translation>
<translation id="2335594187091864976">kuupäeva ja kellaaja valija</translation>
<translation id="2393030564806080191">Värvi väärtus kuueteistkümnendsüsteemis</translation>
+<translation id="2398813069815436052">dialoog on avatud.</translation>
<translation id="245932805758469625">video allesjäänud sekundite arv</translation>
<translation id="248395913932153421">päev</translation>
<translation id="2507943997699731163">Täitke see väli.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_eu.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_eu.xtb
index fa34657d5fc..134b24bac85 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_eu.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_eu.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">orri-jauzia</translation>
<translation id="2335594187091864976">data- eta ordu-hautatzailea</translation>
<translation id="2393030564806080191">Kolore hamaseitarraren balioa</translation>
+<translation id="2398813069815436052">leiho bat ireki egin da.</translation>
<translation id="245932805758469625">bideoa amaitzeko geratzen den segundo kopurua</translation>
<translation id="248395913932153421">Eguna</translation>
<translation id="2507943997699731163">Bete eremu hau.</translation>
@@ -86,7 +87,7 @@
<translation id="3199563858620722075">koadro konbinatua</translation>
<translation id="3220661731597678625">une honetako urratsa</translation>
<translation id="3321030238473337787">Erreprodukzio-abiadura</translation>
-<translation id="3329013043687509092">Saturazioa</translation>
+<translation id="3329013043687509092">Asetasuna</translation>
<translation id="3450233048674729344">Balioak <ph name="MAXIMUM" /> edo gutxiago izan behar du.</translation>
<translation id="3486220673238053218">definizioa</translation>
<translation id="3557673793733683882"><ph name="HEADING_LEVEL" />. goiburua</translation>
@@ -217,7 +218,7 @@
<translation id="6790428901817661496">Erreproduzitu</translation>
<translation id="6820355525329141109">Ezin izan da kargatu plugina.</translation>
<translation id="6820615603175220800">bibliografia-erreferentzia</translation>
-<translation id="6831465880655513317">Bi dimentsioko graduatzailea duen zirkulu kromatikoa, saturazioa eta argitasuna hautatzeko</translation>
+<translation id="6831465880655513317">Bi dimentsioko graduatzailea duen zirkulu kromatikoa, asetasuna eta argitasuna hautatzeko</translation>
<translation id="6843725295806269523">desaktibatu audioa</translation>
<translation id="6885760532393684712">direktorioa</translation>
<translation id="689129560213475294">azken oharra</translation>
@@ -307,7 +308,7 @@
<translation id="8861621546968757188">leiho gainerakorraren botoia</translation>
<translation id="8875657656876809964">Bideoaren erreprodukzio-errorea</translation>
<translation id="8889402386540077796">Ñabardura</translation>
-<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="894736920926684893">Formatu-etengailua</translation>
<translation id="8987927404178983737">Hilabetea</translation>
<translation id="901493112792887934">oraingo denbora segundotan</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb
index 0a56bf81aa4..2f45c77692a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">جداساز صفحه</translation>
<translation id="2335594187091864976">انتخابگر تاریخ و زمان</translation>
<translation id="2393030564806080191">مقدار رنگ در مبنای شانزده</translation>
+<translation id="2398813069815436052">کادر گفتگو باز شد.</translation>
<translation id="245932805758469625">ثانیه‌های باقی‌مانده از ویدیو</translation>
<translation id="248395913932153421">روز</translation>
<translation id="2507943997699731163">لطفاً این قسمت را تکمیل کنید.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb
index bdb25d9399a..99f9fdb5c76 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sivunvaihto</translation>
<translation id="2335594187091864976">päivämäärän ja ajan valitsin</translation>
<translation id="2393030564806080191">Heksadesimaalinen väriarvo</translation>
+<translation id="2398813069815436052">ikkuna avattu</translation>
<translation id="245932805758469625">videon jäljellä oleva aika sekunteina</translation>
<translation id="248395913932153421">Päivä</translation>
<translation id="2507943997699731163">Täytä tämä kenttä.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb
index 126d4d8a2d3..28bd6b3fb3a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">page break</translation>
<translation id="2335594187091864976">picker ng petsa at oras</translation>
<translation id="2393030564806080191">Hexadecimal na value ng kulay</translation>
+<translation id="2398813069815436052">nabuksan ang dialog.</translation>
<translation id="245932805758469625">bilang ng mga segundong natitira sa video</translation>
<translation id="248395913932153421">Araw</translation>
<translation id="2507943997699731163">Pakipunan ang field na ito.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb
index 21b7043e98d..db8f12d55b9 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">saut de page</translation>
<translation id="2335594187091864976">sélecteur de date et d'heure</translation>
<translation id="2393030564806080191">Valeur hexadécimale de la couleur</translation>
+<translation id="2398813069815436052">boîte de dialogue ouverte</translation>
<translation id="245932805758469625">nombre de secondes de vidéo restantes</translation>
<translation id="248395913932153421">Jour</translation>
<translation id="2507943997699731163">Veuillez remplir ce champ.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb
index 1a0a73eaf2e..ddc3362f610 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">saut de page</translation>
<translation id="2335594187091864976">outil de sélection de la date et de l'heure</translation>
<translation id="2393030564806080191">Valeur de couleur hexadécimale</translation>
+<translation id="2398813069815436052">boîte de dialogue ouverte.</translation>
<translation id="245932805758469625">nombre de secondes de vidéo restantes</translation>
<translation id="248395913932153421">Jour</translation>
<translation id="2507943997699731163">Veuillez renseigner ce champ.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_gl.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_gl.xtb
index cb269a7cf94..d60bd9beca9 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_gl.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_gl.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">salto de páxina</translation>
<translation id="2335594187091864976">selector de data e hora</translation>
<translation id="2393030564806080191">Valor hexadecimal da cor</translation>
+<translation id="2398813069815436052">cadro de diálogo aberto.</translation>
<translation id="245932805758469625">número de segundos restantes do vídeo</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb
index 27f91c44328..4f366ad31e7 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">પેજ વિભાજન</translation>
<translation id="2335594187091864976">તારીખ અને સમય પીકર</translation>
<translation id="2393030564806080191">રંગનું હેક્ઝાડેસિમલ મૂલ્ય</translation>
+<translation id="2398813069815436052">સંવાદ ખોલવામાં આવ્યો.</translation>
<translation id="245932805758469625">વીડિયોની બાકી સેકન્ડ</translation>
<translation id="248395913932153421">દિવસ</translation>
<translation id="2507943997699731163">કૃપા કરીને આ ફીલ્ડ ભરો.</translation>
@@ -130,7 +131,7 @@
<translation id="4748357248530471599">ડિસ્પ્લેમાં જ સામેલ પૂર્ણસ્ક્રીન ટૉગલ કરો</translation>
<translation id="4757246831282535685">ટેબ પેનલ</translation>
<translation id="4763480195061959176">વીડિયો</translation>
-<translation id="479989351350248267">search</translation>
+<translation id="479989351350248267">શોધ</translation>
<translation id="4812940957355064477">કૃપા કરીને એક નંબર દાખલ કરો.</translation>
<translation id="4912200001568447310">વર્તમાન આઇટમ</translation>
<translation id="4912536737030637138">ગ્રંથસૂચિની એન્ટ્રી</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb
index 17d9374a9a6..cc41f321f36 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">नया पेज</translation>
<translation id="2335594187091864976">तारीख और समय पिकर</translation>
<translation id="2393030564806080191">रंग का हेक्साडेसिमल मान</translation>
+<translation id="2398813069815436052">डायलॉग खोला गया.</translation>
<translation id="245932805758469625">बचे हुए वीडियो का कुल समय सेकंड में</translation>
<translation id="248395913932153421">दिन</translation>
<translation id="2507943997699731163">कृपया इस फ़ील्ड को भरें.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb
index d5ac4f5548d..64d66952f28 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">prijelom stranice</translation>
<translation id="2335594187091864976">alat za odabir datuma i vremena</translation>
<translation id="2393030564806080191">Heksadecimalna vrijednost boje</translation>
+<translation id="2398813069815436052">dijalog je otvoren.</translation>
<translation id="245932805758469625">preostali broj sekundi videozapisa</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Ispunite ovo polje.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb
index 74bd85b67cf..2e32e3c7320 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">oldaltörés</translation>
<translation id="2335594187091864976">dátum- és időválasztó</translation>
<translation id="2393030564806080191">Szín hexadecimális értéke</translation>
+<translation id="2398813069815436052">párbeszédpanel megnyitva.</translation>
<translation id="245932805758469625">a videóból hátralévő másodpercek száma</translation>
<translation id="248395913932153421">nap</translation>
<translation id="2507943997699731163">Kérjük, töltse ki ezt a mezőt.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_hy.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_hy.xtb
index a7988b83783..e2766ab3e53 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_hy.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hy.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">էջի ընդհատում</translation>
<translation id="2335594187091864976">ամսաթվի և ժամի ընտրիչ</translation>
<translation id="2393030564806080191">Գույնի տասնվեցական կոդը</translation>
+<translation id="2398813069815436052">երկխոսության պատուհան է բացվել։</translation>
<translation id="245932805758469625">տեսանյութի ավարտին մնացած ժամանակը վայրկյաններով</translation>
<translation id="248395913932153421">Օր</translation>
<translation id="2507943997699731163">Խնդրում ենք լրացնել այս դաշտը:</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb
index e8d2e104e2c..b40b18ccb3e 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">batas halaman</translation>
<translation id="2335594187091864976">pemilih tanggal dan waktu</translation>
<translation id="2393030564806080191">Nilai warna heksadesimal</translation>
+<translation id="2398813069815436052">dialog dibuka.</translation>
<translation id="245932805758469625">sisa durasi video dalam detik</translation>
<translation id="248395913932153421">Hari</translation>
<translation id="2507943997699731163">Harap isi bidang ini.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_is.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_is.xtb
index 50254091fe0..2e70da23c67 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_is.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_is.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">síðuskil</translation>
<translation id="2335594187091864976">val á dagsetningu og tíma</translation>
<translation id="2393030564806080191">Sextándakerfisgildi litar</translation>
+<translation id="2398813069815436052">gluggi opnaðist.</translation>
<translation id="245932805758469625">fjöldi sekúndna sem eftir eru af myndskeiði</translation>
<translation id="248395913932153421">Dagur</translation>
<translation id="2507943997699731163">Fylltu þennan reit út.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb
index c45a83d70bd..636b488ac51 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">interruzione di pagina</translation>
<translation id="2335594187091864976">selettore di data e ora</translation>
<translation id="2393030564806080191">Valore del colore esadecimale</translation>
+<translation id="2398813069815436052">finestra di dialogo aperta.</translation>
<translation id="245932805758469625">numero di secondi di video rimanenti</translation>
<translation id="248395913932153421">Giorno</translation>
<translation id="2507943997699731163">Compila questo campo.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb
index 00b1df10323..0a3187c628f 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">מעבר דף</translation>
<translation id="2335594187091864976">בוחר תאריך ושעה</translation>
<translation id="2393030564806080191">הערך ההקסדצימלי של הצבע</translation>
+<translation id="2398813069815436052">תיבת הדו-שיח נפתחה.</translation>
<translation id="245932805758469625">מספר השניות שנותרו עד לסיום הסרטון</translation>
<translation id="248395913932153421">יום</translation>
<translation id="2507943997699731163">זהו שדה חובה.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb
index 28833517a26..2168f960984 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">改ページ</translation>
<translation id="2335594187091864976">日時選択ツール</translation>
<translation id="2393030564806080191">16 進数色コード</translation>
+<translation id="2398813069815436052">ダイアログが開いています。</translation>
<translation id="245932805758469625">残りの再生時間(秒)</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">このフィールドを入力してください。</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ka.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ka.xtb
index 7cca29c5094..6dc4adfbc35 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ka.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ka.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">გვერდის წყვეტა</translation>
<translation id="2335594187091864976">თარიღისა და დროის ამომრჩევი</translation>
<translation id="2393030564806080191">ფერის თექვსმეტობითი მნიშვნელობა</translation>
+<translation id="2398813069815436052">დიალოგი გახსნა.</translation>
<translation id="245932805758469625">ვიდეოს დარჩენილი წამების რაოდენობა</translation>
<translation id="248395913932153421">დღე</translation>
<translation id="2507943997699731163">შეავსეთ ეს ველი.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_kk.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_kk.xtb
index 174c3e96cf5..76aa722ee9a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_kk.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_kk.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">бетті үзу</translation>
<translation id="2335594187091864976">күн мен уақыт таңдағышы</translation>
<translation id="2393030564806080191">Оналтылық форматтағы түс</translation>
+<translation id="2398813069815436052">диалогтік терезе ашылды.</translation>
<translation id="245932805758469625">бейненің соңына дейін қалған секундтар саны</translation>
<translation id="248395913932153421">Күн</translation>
<translation id="2507943997699731163">Бұл өрісті толтырыңыз.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_km.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_km.xtb
index 582c2ccdffa..afa0e316649 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_km.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_km.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">បំបែក​ទំព័រ</translation>
<translation id="2335594187091864976">កម្មវិធីជ្រើសកាលបរិច្ឆេទ និងម៉ោង</translation>
<translation id="2393030564806080191">តម្លៃពណ៌​គោលដប់ប្រាំមួយ</translation>
+<translation id="2398813069815436052">បានបើក​ប្រអប់។</translation>
<translation id="245932805758469625">ចំនួន​វិនាទី​នៅ​សល់​សម្រាប់​ការចាក់​វីដេអូ</translation>
<translation id="248395913932153421">ថ្ងៃ</translation>
<translation id="2507943997699731163">សូមបំពេញប្រអប់នេះ។</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb
index 02a6042068a..42c5fb01e73 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ಪುಟ ವಿಭಜನೆ</translation>
<translation id="2335594187091864976">ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಪಿಕರ್</translation>
<translation id="2393030564806080191">ಹೆಕ್ಸಾಡೆಸಿಮಲ್‌‌ ಬಣ್ಣದ ಮೌಲ್ಯ</translation>
+<translation id="2398813069815436052">ಡೈಲಾಗ್ ತೆರೆಯಲಾಗಿದೆ.</translation>
<translation id="245932805758469625">ಇಷ್ಟು ಸೆಕೆಂಡಿನ ವೀಡಿಯೊ ಬಾಕಿ ಉಳಿದಿದೆ</translation>
<translation id="248395913932153421">ದಿನ</translation>
<translation id="2507943997699731163">ದಯವಿಟ್ಟು ಈ ಕ್ಷೇತ್ರವನ್ನು ಭರ್ತಿ ಮಾಡಿ.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb
index e5ae78e4560..2af785e14cd 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">페이지 나누기</translation>
<translation id="2335594187091864976">날짜 및 시간 선택기</translation>
<translation id="2393030564806080191">16진수 색상 값</translation>
+<translation id="2398813069815436052">대화상자가 열렸습니다.</translation>
<translation id="245932805758469625">동영상 남은 시간</translation>
<translation id="248395913932153421">일</translation>
<translation id="2507943997699731163">이 입력란을 작성하세요.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ky.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ky.xtb
index 2b0ccb0d187..ac5d9cb3c2b 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ky.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ky.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">барактардын үзүлгөн жери</translation>
<translation id="2335594187091864976">күн жана убакыт тандагыч</translation>
<translation id="2393030564806080191">Он алты түстүү код</translation>
+<translation id="2398813069815436052">диалог ачылды.</translation>
<translation id="245932805758469625">видеонун бүтөөрүнө канча секунд калды</translation>
<translation id="248395913932153421">Күн</translation>
<translation id="2507943997699731163">Бул талааны толтуруңуз.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_lo.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_lo.xtb
index d9a2c0cb54f..92c62f8f97e 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_lo.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_lo.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ແບ່ງໜ້າ</translation>
<translation id="2335594187091864976">ຕົວເລືອກວັນທີ ແລະ ເວລາ</translation>
<translation id="2393030564806080191">ຄ່າສີແບບຖານສິບຫົກ</translation>
+<translation id="2398813069815436052">ເປີດກ່ອງໂຕ້ຕອບແລ້ວ.</translation>
<translation id="245932805758469625">ຈໍານວນວິນາທີຂອງວິດີໂອທີ່ຍັງເຫຼືອ</translation>
<translation id="248395913932153421">ວັນ</translation>
<translation id="2507943997699731163">ກະລຸນາຕື່ມຂໍ້ມູນໃສ່ປ່ອງນີ້.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb
index 1b2805af5da..ff8ba37bf0d 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">puslapio lūžis</translation>
<translation id="2335594187091864976">datos ir laiko rinkiklis</translation>
<translation id="2393030564806080191">Šešioliktainė spalvos vertė</translation>
+<translation id="2398813069815436052">dialogo langas atidarytas.</translation>
<translation id="245932805758469625">likusių vaizdo įrašo sekundžių skaičius</translation>
<translation id="248395913932153421">Diena</translation>
<translation id="2507943997699731163">Užpildykite šį lauką.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb
index 0ab5ca1bfbe..93a572282a6 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">lappuses pārtraukums</translation>
<translation id="2335594187091864976">datuma un laika atlasītājs</translation>
<translation id="2393030564806080191">Heksadecimāla krāsas vērtība</translation>
+<translation id="2398813069815436052">tika atvērts dialoglodziņš.</translation>
<translation id="245932805758469625">atlikušais video laiks sekundēs</translation>
<translation id="248395913932153421">Diena</translation>
<translation id="2507943997699731163">Aizpildiet šo lauku.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_mk.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_mk.xtb
index 2a2fe97d7c0..de7992b50de 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_mk.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_mk.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">прелом на страница</translation>
<translation id="2335594187091864976">избирач на датум и време</translation>
<translation id="2393030564806080191">Хексадецимална вредност на бојата</translation>
+<translation id="2398813069815436052">дијалогот е отворен.</translation>
<translation id="245932805758469625">број на преостанати секунди од видеото</translation>
<translation id="248395913932153421">Ден</translation>
<translation id="2507943997699731163">Пополнете го ова поле.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb
index 10c1adcedfd..4bb4549c114 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">പേജ് ബ്രേക്ക്</translation>
<translation id="2335594187091864976">തീയതിയും സമയ പിക്കറും</translation>
<translation id="2393030564806080191">ഹെക്‌സാഡെസിമല്‍ വർണ മൂല്യം</translation>
+<translation id="2398813069815436052">ഡയലോഗ് തുറന്നു.</translation>
<translation id="245932805758469625">വീഡിയോയുടെ അവശേഷിക്കുന്ന സമയം സെക്കൻഡിൽ</translation>
<translation id="248395913932153421">ദിവസം</translation>
<translation id="2507943997699731163">ദയവായി ഈ ഫീല്‍ഡ് പൂരിപ്പിക്കുക.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_mn.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_mn.xtb
index 96a3ac0dab4..d60d712d592 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_mn.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_mn.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">хуудас тусгаарлагч</translation>
<translation id="2335594187091864976">огноо болон хугацаа сонгогч</translation>
<translation id="2393030564806080191">Арван зургаатын өнгөний утга</translation>
+<translation id="2398813069815436052">харилцах цонхыг нээсэн.</translation>
<translation id="245932805758469625">видео үргэлжлэх үлдсэн секундийн тоо</translation>
<translation id="248395913932153421">Өдөр</translation>
<translation id="2507943997699731163">Энэ талбарыг бөглөнө үү.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb
index 9a95d00c756..90dbdc64552 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">पेज ब्रेक</translation>
<translation id="2335594187091864976">तारीख आणि वेळ निवडक</translation>
<translation id="2393030564806080191">रंगाचे हेक्साडेसिमल मूल्य</translation>
+<translation id="2398813069815436052">डायलॉग उघडला.</translation>
<translation id="245932805758469625">व्हिडिओच्या शिल्लक सेकंदांची संख्या</translation>
<translation id="248395913932153421">दिवस</translation>
<translation id="2507943997699731163">कृपया हे फील्ड भरा.</translation>
@@ -130,7 +131,7 @@
<translation id="4748357248530471599">डिस्प्ले कटआउट फुलस्क्रीन टॉगल करा</translation>
<translation id="4757246831282535685">टॅब पॅनल</translation>
<translation id="4763480195061959176">व्हिडिओ</translation>
-<translation id="479989351350248267">search</translation>
+<translation id="479989351350248267">शोध</translation>
<translation id="4812940957355064477">कृपया एक नंबर एंटर करा.</translation>
<translation id="4912200001568447310">सध्याचा आयटम</translation>
<translation id="4912536737030637138">ग्रंथसूची नोंद</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb
index fe6b1771fb7..343d8525f1b 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">pemisah halaman</translation>
<translation id="2335594187091864976">pemilih tarikh dan masa</translation>
<translation id="2393030564806080191">Nilai warna perenambelasan</translation>
+<translation id="2398813069815436052">dialog dibuka.</translation>
<translation id="245932805758469625">bilangan saat baki video</translation>
<translation id="248395913932153421">Hari</translation>
<translation id="2507943997699731163">Sila isikan medan ini.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_my.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_my.xtb
index e31b172ea06..48f57bcf563 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_my.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_my.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">စာမျက်နှာခြားခြင်း</translation>
<translation id="2335594187091864976">ရက်စွဲနှင့် အချိန် ရွေးချယ်မှု</translation>
<translation id="2393030564806080191">ဟက်စ်အရောင် အညွှန်းကိန်း</translation>
+<translation id="2398813069815436052">ဒိုင်ယာလော့ ဖွင့်ထားသည်။</translation>
<translation id="245932805758469625">ဗီဒီယိုပြီးဆုံးရန် ကျန်ရှိ စက္ကန့်</translation>
<translation id="248395913932153421">ရက်</translation>
<translation id="2507943997699731163">ကျေးဇူးပြုပြီး ဒီအကွက်ကို ​ရေးဖြည့်ပါ။</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ne.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ne.xtb
index 38a287a72b4..ffdb9edd8ad 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ne.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ne.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">पृष्ठ विच्छेद</translation>
<translation id="2335594187091864976">मिति र समय टिप्ने</translation>
<translation id="2393030564806080191">रङको हेक्साडेसिमल मान</translation>
+<translation id="2398813069815436052">डायलग खोलिएको छ।</translation>
<translation id="245932805758469625">भिडियोको बाँकी सेकेन्डको अवधि</translation>
<translation id="248395913932153421">दिन</translation>
<translation id="2507943997699731163">कृपया यस क्षेत्रमा भर्नुहोस्।</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb
index 8444fae0e6d..6e8537715b7 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">pagina-einde</translation>
<translation id="2335594187091864976">datum- en tijdkiezer</translation>
<translation id="2393030564806080191">Hexadecimale kleurwaarde</translation>
+<translation id="2398813069815436052">dialoogvenster geopend.</translation>
<translation id="245932805758469625">aantal seconden van resterende video</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vul dit veld in.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb
index abacaa50081..60a6336f2a6 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sideskift</translation>
<translation id="2335594187091864976">dato- og klokkeslettvelger</translation>
<translation id="2393030564806080191">Heksadesimal fargeverdi</translation>
+<translation id="2398813069815436052">En dialogboks er åpnet.</translation>
<translation id="245932805758469625">antall sekunder med video som gjenstår</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vennligst fyll ut dette feltet.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_or.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_or.xtb
index 6d386b538c1..5c2a60dd775 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_or.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_or.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ପେଜ୍ ବ୍ରେକ୍</translation>
<translation id="2335594187091864976">ତାରିଖ ଓ ସମୟ ପିକର୍</translation>
<translation id="2393030564806080191">ହେକ୍ସାଡେସିମାଲ୍ ରଙ୍ଗର ମୂଲ୍ୟ</translation>
+<translation id="2398813069815436052">ଡାଏଲଗ୍ ଖୋଲା ଅଛି।</translation>
<translation id="245932805758469625">ସେକେଣ୍ଡର ଭିଡିଓ ବାକି ରହିଛି</translation>
<translation id="248395913932153421">ଦିନ</translation>
<translation id="2507943997699731163">ଦୟାକରି ଏହି କ୍ଷେତ୍ର ପୂରଣ କରନ୍ତୁ।</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_pa.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_pa.xtb
index 3f6ad9de535..adcca13c1a5 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_pa.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pa.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ਪੰਨਾ ਬ੍ਰੇਕ</translation>
<translation id="2335594187091864976">ਮਿਤੀ ਅਤੇ ਸਮਾਂ ਚੋਣਕਰਤਾ</translation>
<translation id="2393030564806080191">ਛੇ-ਦਸ਼ਮਲਵ ਪ੍ਰਨਾਲੀ ਰੰਗ ਮੁੱਲ</translation>
+<translation id="2398813069815436052">ਵਿੰਡੋ ਖੋਲ੍ਹੀ ਗਈ।</translation>
<translation id="245932805758469625">ਵੀਡੀਓ ਦੇ ਬਾਕੀ ਸਕਿੰਟ</translation>
<translation id="248395913932153421">ਦਿਨ</translation>
<translation id="2507943997699731163">ਕਿਰਪਾ ਕਰਕੇ ਇਹ ਖੇਤਰ ਭਰੋ।</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb
index ea71f0289a0..8977a08766b 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">podział strony</translation>
<translation id="2335594187091864976">selektor daty i godziny</translation>
<translation id="2393030564806080191">Wartość szesnastkowego kodu koloru</translation>
+<translation id="2398813069815436052">okno zostało otwarte.</translation>
<translation id="245932805758469625">pozostały czas filmu w sekundach</translation>
<translation id="248395913932153421">Dzień</translation>
<translation id="2507943997699731163">Wypełnij to pole.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb
index fc2e0468fdc..9128b269c6a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">quebra de página</translation>
<translation id="2335594187091864976">seletor de data e hora</translation>
<translation id="2393030564806080191">Valor hexadecimal da cor</translation>
+<translation id="2398813069815436052">caixa de diálogo aberta.</translation>
<translation id="245932805758469625">segundos restantes do vídeo</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Preencha este campo.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb
index a6ef3ef9adb..2fcf4576be2 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">quebra de página</translation>
<translation id="2335594187091864976">selecionador de data e hora</translation>
<translation id="2393030564806080191">Valor de cor hexadecimal</translation>
+<translation id="2398813069815436052">caixa de diálogo aberta.</translation>
<translation id="245932805758469625">segundos restantes do vídeo</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Preencha este campo.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb
index e32d91cb51c..b3c024d23c9 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sfârșit de pagină</translation>
<translation id="2335594187091864976">selector pentru dată și oră</translation>
<translation id="2393030564806080191">Valoarea hexazecimală a culorii</translation>
+<translation id="2398813069815436052">casetă de dialog deschisă.</translation>
<translation id="245932805758469625">numărul de secunde rămase din videoclip</translation>
<translation id="248395913932153421">Zi</translation>
<translation id="2507943997699731163">Completează acest câmp.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb
index a34f40b13aa..e8450a449b9 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">разрыв страницы</translation>
<translation id="2335594187091864976">окно выбора даты и времени</translation>
<translation id="2393030564806080191">Цвет в шестнадцатеричном формате</translation>
+<translation id="2398813069815436052">открыто диалоговое окно.</translation>
<translation id="245932805758469625">оставшееся время до конца видео в секундах</translation>
<translation id="248395913932153421">День</translation>
<translation id="2507943997699731163">Заполните это поле.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_si.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_si.xtb
index 700b7054201..3ce617d63b2 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_si.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_si.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">පිටු බිඳුම</translation>
<translation id="2335594187091864976">දිනය හා වේලාව තෝරකය</translation>
<translation id="2393030564806080191">ෂෂ්ඨ දශක වර්ණ අගය</translation>
+<translation id="2398813069815436052">සංවාදය විවෘත කරන ලදි.</translation>
<translation id="245932805758469625">වීඩියෝවේ ඉතිරි තත්පර ගණන</translation>
<translation id="248395913932153421">දිනය</translation>
<translation id="2507943997699731163">කරුණාකර මෙම ක්ෂේත්‍රය පුරවන්න.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb
index 1a09a12d1d9..054e8c4e631 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">zlom strany</translation>
<translation id="2335594187091864976">výber dátumu a času</translation>
<translation id="2393030564806080191">Hodnota farby v šestnástkovej sústave</translation>
+<translation id="2398813069815436052">dialógové okno je otvorené.</translation>
<translation id="245932805758469625">počet sekúnd do konca videa</translation>
<translation id="248395913932153421">Deň</translation>
<translation id="2507943997699731163">Vyplňte toto pole.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb
index a18667c56d7..c8a86dceca2 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">prelom strani</translation>
<translation id="2335594187091864976">izbirnik datuma in ure</translation>
<translation id="2393030564806080191">Šestnajstiška barvna vrednost</translation>
+<translation id="2398813069815436052">Pogovorno okno je bilo odprto.</translation>
<translation id="245932805758469625">preostale sekunde videoposnetka</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Izpolnite to polje</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sq.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sq.xtb
index d70824f243e..dd192f6afc3 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sq.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sq.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">thyerje faqeje</translation>
<translation id="2335594187091864976">zgjedhësi i datës dhe orës</translation>
<translation id="2393030564806080191">Vlera e ngjyrave heksadecimale</translation>
+<translation id="2398813069815436052">dialogu u hap.</translation>
<translation id="245932805758469625">numri i sekondave të mbetura të videos</translation>
<translation id="248395913932153421">Dita</translation>
<translation id="2507943997699731163">Plotësoje këtë fushë.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sr-Latn.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sr-Latn.xtb
index 62e255a9696..8e807b1d175 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sr-Latn.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sr-Latn.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">prelom stranice</translation>
<translation id="2335594187091864976">birač datuma i vremena</translation>
<translation id="2393030564806080191">Heksadecimalna vrednost boje</translation>
+<translation id="2398813069815436052">otvoren je dijalog.</translation>
<translation id="245932805758469625">broj preostalih sekundi video snimka</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Popunite ovo polje.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb
index 61061f9b292..5afa5ea6142 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">прелом странице</translation>
<translation id="2335594187091864976">бирач датума и времена</translation>
<translation id="2393030564806080191">Хексадецимална вредност боје</translation>
+<translation id="2398813069815436052">отворен је дијалог.</translation>
<translation id="245932805758469625">број преосталих секунди видео снимка</translation>
<translation id="248395913932153421">Дан</translation>
<translation id="2507943997699731163">Попуните ово поље.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb
index 0b38dc5fb27..d2ab97dc334 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sidbrytning</translation>
<translation id="2335594187091864976">datum- och tidsväljare</translation>
<translation id="2393030564806080191">Hexadecimalt färgvärde</translation>
+<translation id="2398813069815436052">en dialogruta har öppnats.</translation>
<translation id="245932805758469625">antal sekunder kvar av videon</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Fyll i det här fältet.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb
index fa316411d02..fa2a9496632 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">nafasi ya kugawa kurasa</translation>
<translation id="2335594187091864976">mchumaji tarehe na wakati</translation>
<translation id="2393030564806080191">Nambari ya rangi ya heksadesimali</translation>
+<translation id="2398813069815436052">kidirisha kimefunguliwa.</translation>
<translation id="245932805758469625">idadi ya sekunde za video zilizosalia</translation>
<translation id="248395913932153421">Siku</translation>
<translation id="2507943997699731163">Tafadhali jaza sehemu hii.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb
index 7c959fa6a5d..57887c5d49a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb
@@ -47,7 +47,7 @@
<translation id="2148716181193084225">இன்று</translation>
<translation id="2158401438286456825">பக்கப் பட்டியல்</translation>
<translation id="2226276347425096477">இந்த உரையை <ph name="MAX_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் குறைவாக சுருக்கிடுங்கள் (நீங்கள் தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்).</translation>
-<translation id="2246498165605549352">அகக் கோப்பு</translation>
+<translation id="2246498165605549352">அக ஃபைல்</translation>
<translation id="2247351761944213033">வாரம் <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">டிராக் <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">செக்பாக்ஸ்</translation>
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">பக்க முறிப்பு</translation>
<translation id="2335594187091864976">தேதி மற்றும் நேரம் தேர்வுக் கருவி</translation>
<translation id="2393030564806080191">ஹெக்சாடெசிமல் வண்ண மதிப்பு</translation>
+<translation id="2398813069815436052">உரையாடல் திறக்கப்பட்டது.</translation>
<translation id="245932805758469625">மீதமுள்ள வீடியோவின் வினாடிகள்</translation>
<translation id="248395913932153421">நாள்</translation>
<translation id="2507943997699731163">இந்தப் புலத்தை நிரப்புக.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb
index 45eabe19690..e7a4fe3055b 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb
@@ -5,7 +5,7 @@
<translation id="10623998915015855">టోగుల్ బటన్</translation>
<translation id="1088086359088493902">సెకన్లు</translation>
<translation id="1142001580032786438">వారం పికర్‌ను చూపుతుంది</translation>
-<translation id="1171774979989969504">దయచేసి ఇమెయిల్ చిరునామాను ఎంటర్ చేయండి.</translation>
+<translation id="1171774979989969504">దయచేసి ఈమెయిల్‌ అడ్రస్‌ను ఎంటర్ చేయండి.</translation>
<translation id="1178581264944972037">పాజ్ చేయి</translation>
<translation id="1188858454923323853">బహుమానపూర్వకం</translation>
<translation id="1206619573307042055">marquee</translation>
@@ -27,7 +27,7 @@
<translation id="1681022320378710418">ప్రస్తుత సమయం</translation>
<translation id="1727839386348365796">కలర్ పికర్</translation>
<translation id="1727886345390570319">ఉపశీర్షికల మెనూని దాచు</translation>
-<translation id="1729654308190250600">దయచేసి ఖాళీ-కాని ఇమెయిల్ చిరునామాను నమోదు చేయండి.</translation>
+<translation id="1729654308190250600">దయచేసి ఖాళీ-కాని ఈమెయిల్‌ అడ్రస్‌ను నమోదు చేయండి.</translation>
<translation id="1758486001363313524">ఇతర...</translation>
<translation id="1787192514241997742">మొత్తం సమయం: <ph name="REMAINING_TIME" /></translation>
<translation id="1806710327868736751">alert_dialog</translation>
@@ -45,7 +45,7 @@
<translation id="2031987842108996681">రెడ్ ఛానెల్</translation>
<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />'లో '<ph name="DOT" />' తప్పు స్థానంలో ఉపయోగించబడింది.</translation>
<translation id="2148716181193084225">ఈ రోజు</translation>
-<translation id="2158401438286456825">పేజీ జాబితా</translation>
+<translation id="2158401438286456825">పేజీ లిస్ట్‌</translation>
<translation id="2226276347425096477">దయచేసి ఈ వచనాన్ని <ph name="MAX_CHARACTERS" /> అక్షరాలకు లేదా అంతకంటే తక్కువకు తగ్గించండి (మీరు ప్రస్తుతం <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు).</translation>
<translation id="2246498165605549352">స్థానిక ఫైల్</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />వ వారం, <ph name="YEAR" /></translation>
@@ -55,10 +55,11 @@
<translation id="2311842470354187719">పేజీ విభజన</translation>
<translation id="2335594187091864976">తేదీ మరియు సమయం ఎంపిక</translation>
<translation id="2393030564806080191">హెక్సాడెసిమల్ రంగు విలువ</translation>
+<translation id="2398813069815436052">డైలాగ్ తెరవబడింది.</translation>
<translation id="245932805758469625">వీడియోలో మిగిలి ఉన్న సెకన్లు</translation>
<translation id="248395913932153421">రోజు</translation>
<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ను పూర్తి చేయండి.</translation>
-<translation id="2508569020611168319">ట్యాబ్ జాబితా</translation>
+<translation id="2508569020611168319">ట్యాబ్ లిస్ట్‌</translation>
<translation id="2530182415807757784">బహుళ వాటిని ఎంచుకోగలిగేది, ఏదీ ఎంచుకోలేదు.</translation>
<translation id="2561842179657104141">మరిన్ని మీడియా నియంత్రణలను చూపు</translation>
<translation id="2572483411312390101">ప్లే చేయి</translation>
@@ -74,7 +75,7 @@
<translation id="2761667185364618470">మీరు కొనసాగాలనుకుంటే దయచేసి ఈ బాక్స్‌కి టిక్కు పెట్టండి.</translation>
<translation id="2844350028562914727">వివరాలు</translation>
<translation id="2896972712917208084">రేడియో సమూహం</translation>
-<translation id="2908441821576996758">దయచేసి కామాతో వేరు చేసిన ఇమెయిల్ చిరునామాల జాబితాను నమోదు చేయండి.</translation>
+<translation id="2908441821576996758">దయచేసి కామాతో వేరు చేసిన ఈమెయిల్‌ అడ్రస్‌ల లిస్ట్‌ను నమోదు చేయండి.</translation>
<translation id="2940813599313844715">ఆబ్జెక్ట్</translation>
<translation id="3040011195152428237">లింక్</translation>
<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
@@ -186,7 +187,7 @@
<translation id="5987525920412732405">స్పిన్ బటన్</translation>
<translation id="6011459053400940133">వాల్యూమ్ స్లయిడర్</translation>
<translation id="6015796118275082299">సంవత్సరం</translation>
-<translation id="6023896073578205740">జాబితా పెట్టె</translation>
+<translation id="6023896073578205740">లిస్ట్‌ పెట్టె</translation>
<translation id="6150588977291308318">వివరణపట్టి</translation>
<translation id="6164829606128959761">మీటర్</translation>
<translation id="6165053282446038410">విస్తరించబడింది, <ph name="COUNT" /> ఆటోకంప్లీట్ ఆప్షన్‌లు అందుబాటులో ఉన్నాయి.</translation>
@@ -262,7 +263,7 @@
<translation id="7789962463072032349">నిలిపివేయి</translation>
<translation id="7802800022689234070">కంటెంట్‌ను విస్తరింపజేసే లేదా కుదించే త్రిభుజం</translation>
<translation id="7852167693871241274">రంగు స్లయిడర్</translation>
-<translation id="7888071071722539607">దయచేసి ఇమెయిల్ చిరునామాలో '<ph name="ATSIGN" />'ని చేర్చండి. '<ph name="INVALIDADDRESS" />'లో '<ph name="ATSIGN" />' లేదు.</translation>
+<translation id="7888071071722539607">దయచేసి ఈమెయిల్‌ అడ్రస్‌లో '<ph name="ATSIGN" />'ని చేర్చండి. '<ph name="INVALIDADDRESS" />'లో '<ph name="ATSIGN" />' లేదు.</translation>
<translation id="7891486169920085145">విభజన</translation>
<translation id="795667975304826397">ఫైల్ ఏదీ ఎంచుకోలేదు</translation>
<translation id="7962328325860248200"><ph name="ACCNAME" /> ఎంచుకోబడలేదు</translation>
@@ -291,7 +292,7 @@
<translation id="8534579021159131403">నిమిషాలు</translation>
<translation id="8541249477527128034">మీడియా నియంత్రణ</translation>
<translation id="8550857728288566671">గ్రాఫిక్స్ చిహ్నం</translation>
-<translation id="8583702881314752957">నిర్వచన జాబితా</translation>
+<translation id="8583702881314752957">నిర్వచన లిస్ట్‌</translation>
<translation id="8597182159515967513">శీర్షిక</translation>
<translation id="860475260694818407">కంటెంట్‌ల‌ పట్టిక</translation>
<translation id="8613126697340063924">రిమోట్ ప్లేబ్యాక్‌ను నియంత్రిస్తుంది</translation>
@@ -311,7 +312,7 @@
<translation id="894736920926684893">టోగుల్ బటన్‌ను ఫార్మాట్ చేయండి</translation>
<translation id="8987927404178983737">నెల</translation>
<translation id="901493112792887934">సెకన్లలో ప్రస్తుత సమయం</translation>
-<translation id="901834265349196618">ఇమెయిల్</translation>
+<translation id="901834265349196618">ఈమెయిల్‌</translation>
<translation id="9048119486235211610">నావిగేషన్</translation>
<translation id="9062295712474918030">పత్రం</translation>
<translation id="9093215626363556771">చిత్రంలో చిత్రం మోడ్ నుండి నిష్క్రమింపజేస్తుంది</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb
index 1a8cacc8f88..f5f9fe945ad 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ตัวแบ่งหน้า</translation>
<translation id="2335594187091864976">เครื่องมือเลือกวันที่และเวลา</translation>
<translation id="2393030564806080191">ค่าสีแบบฐานสิบหก</translation>
+<translation id="2398813069815436052">กล่องโต้ตอบเปิดอยู่</translation>
<translation id="245932805758469625">จำนวนวินาทีที่เหลือของวิดีโอ</translation>
<translation id="248395913932153421">วัน</translation>
<translation id="2507943997699731163">โปรดกรอกฟิลด์นี้</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb
index bae50b60cd8..d57052972ce 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sayfa sonu</translation>
<translation id="2335594187091864976">tarih ve saat seçici</translation>
<translation id="2393030564806080191">On altılı renk değeri</translation>
+<translation id="2398813069815436052">iletişim kutusu açıldı.</translation>
<translation id="245932805758469625">saniye olarak videonun kalan süresi</translation>
<translation id="248395913932153421">Gün</translation>
<translation id="2507943997699731163">Lütfen bu alanı doldurun.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb
index e9c2bc5a2a3..5b16ae9c42a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">розрив сторінки</translation>
<translation id="2335594187091864976">засіб вибору дати й часу</translation>
<translation id="2393030564806080191">Шістнадцяткове значення кольору</translation>
+<translation id="2398813069815436052">вікно відкрите.</translation>
<translation id="245932805758469625">кількість секунд до кінця відео</translation>
<translation id="248395913932153421">День</translation>
<translation id="2507943997699731163">Заповніть це поле.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_ur.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_ur.xtb
index fae56047141..813e3244bf3 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_ur.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ur.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">صفحہ کا انقطاع</translation>
<translation id="2335594187091864976">تاریخ اور وقت کا منتخب کنندہ</translation>
<translation id="2393030564806080191">رنگ کی ہیگسا ڈیسیمل قدر</translation>
+<translation id="2398813069815436052">ڈائیلاگ کھولا گیا۔</translation>
<translation id="245932805758469625">ویڈیو کے باقی بچے سیکنڈز کی تعداد</translation>
<translation id="248395913932153421">دن</translation>
<translation id="2507943997699731163">براہ کرم یہ فیلڈ پُر کریں۔</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_uz.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_uz.xtb
index 9927db2e1a6..5e59311feb1 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_uz.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_uz.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">sahifa oxiri</translation>
<translation id="2335594187091864976">sana va vaqt tanlash oynasi</translation>
<translation id="2393030564806080191">Rangning 16 raqamli qiymati</translation>
+<translation id="2398813069815436052">oyna ochildi.</translation>
<translation id="245932805758469625">qolgan video vaqti, soniyada</translation>
<translation id="248395913932153421">Kun</translation>
<translation id="2507943997699731163">Bu maydonni to‘ldiring.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb
index 811c1f016db..06c11b03b4a 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ngắt trang</translation>
<translation id="2335594187091864976">bộ chọn ngày và giờ</translation>
<translation id="2393030564806080191">Giá trị màu thập lục phân</translation>
+<translation id="2398813069815436052">đã mở hộp thoại.</translation>
<translation id="245932805758469625">số giây còn lại của video</translation>
<translation id="248395913932153421">Ngày</translation>
<translation id="2507943997699731163">Vui lòng điền vào trường này.</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
index f000ade084c..98971b65e54 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">分页符</translation>
<translation id="2335594187091864976">日期和时间选择器</translation>
<translation id="2393030564806080191">十六进制颜色值</translation>
+<translation id="2398813069815436052">对话框已打开。</translation>
<translation id="245932805758469625">视频剩余时间(以秒为单位)</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">请填写此字段。</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_zh-HK.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-HK.xtb
index d301ce30016..96fbaa2523d 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_zh-HK.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-HK.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">分頁</translation>
<translation id="2335594187091864976">日期和時間點選器</translation>
<translation id="2393030564806080191">十六進制顏色值</translation>
+<translation id="2398813069815436052">開咗對話框。</translation>
<translation id="245932805758469625">影片淨番嘅秒數</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">請填寫這個欄位。</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
index 0d810409988..7834d783947 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">分頁符號</translation>
<translation id="2335594187091864976">日期和時間選擇器</translation>
<translation id="2393030564806080191">十六進位顏色值</translation>
+<translation id="2398813069815436052">對話方塊已開啟。</translation>
<translation id="245932805758469625">影片剩餘秒數</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">請填寫這個欄位。</translation>
diff --git a/chromium/third_party/blink/public/strings/translations/blink_strings_zu.xtb b/chromium/third_party/blink/public/strings/translations/blink_strings_zu.xtb
index d32a510ed14..10864a32e31 100644
--- a/chromium/third_party/blink/public/strings/translations/blink_strings_zu.xtb
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_zu.xtb
@@ -55,6 +55,7 @@
<translation id="2311842470354187719">ukuhlukana kwekhasi</translation>
<translation id="2335594187091864976">isikhi sedethi nesesikhathi</translation>
<translation id="2393030564806080191">Inani lombala we-Hexadecimal</translation>
+<translation id="2398813069815436052">ibhokisi livuliwe.</translation>
<translation id="245932805758469625">inombolo yamasekhondi wevidiyo asele</translation>
<translation id="248395913932153421">Usuku</translation>
<translation id="2507943997699731163">Sicela ugcwalise le nkambu.</translation>
diff --git a/chromium/third_party/blink/public/web/DEPS b/chromium/third_party/blink/public/web/DEPS
index 5c4e4a116a4..317e571b16c 100644
--- a/chromium/third_party/blink/public/web/DEPS
+++ b/chromium/third_party/blink/public/web/DEPS
@@ -34,19 +34,22 @@ include_rules = [
"+services/metrics/public/cpp/ukm_source_id.h",
"+services/network/public/cpp/web_sandbox_flags.h",
"+services/network/public/mojom/web_client_hints_types.mojom-shared.h",
- "+services/network/public/mojom/web_sandbox_flags.mojom-shared.h",
- "+services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h",
"+services/network/public/mojom/content_security_policy.mojom-shared.h",
"+services/network/public/mojom/cors.mojom-shared.h",
"+services/network/public/mojom/cors_origin_pattern.mojom-shared.h",
"+services/network/public/mojom/fetch_api.mojom-shared.h",
+ "+services/network/public/mojom/restricted_cookie_manager.mojom-shared.h",
"+services/network/public/mojom/ip_address_space.mojom-shared.h",
+ "+services/network/public/mojom/link_header.mojom-shared.h",
"+services/network/public/mojom/referrer_policy.mojom-shared.h",
"+services/network/public/mojom/url_loader.mojom-shared.h",
"+services/network/public/mojom/url_loader_factory.mojom-shared.h",
+ "+services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h",
+ "+services/network/public/mojom/web_sandbox_flags.mojom-shared.h",
"+services/service_manager/public",
"+ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h",
"+ui/base/ime/ime_text_span.h",
+ "+ui/display/mojom",
"+ui/events/types",
"+ui/gfx/geometry",
"+ui/gfx/range/range.h",
@@ -62,7 +65,6 @@ include_rules = [
"+ui/base/ime/mojom/virtual_keyboard_types.mojom-shared.h",
# Allowed only inside INSIDE_BLINK
- "+third_party/abseil-cpp/absl/types/optional.h",
"+third_party/blink/renderer/core",
"+third_party/blink/renderer/platform",
]
diff --git a/chromium/third_party/blink/public/web/OWNERS b/chromium/third_party/blink/public/web/OWNERS
index 5dff49dda0c..e17c4e5dde3 100644
--- a/chromium/third_party/blink/public/web/OWNERS
+++ b/chromium/third_party/blink/public/web/OWNERS
@@ -1,10 +1,8 @@
# Accessibility
per-file web_ax_object.h=file://third_party/blink/renderer/modules/accessibility/OWNERS
per-file web_ax_enums.h=file://third_party/blink/renderer/modules/accessibility/OWNERS
-per-file web_ax_enums.h=dtseng@chromium.org
# Page load metrics
-per-file web_performance.h=bmcquade@chromium.org
per-file web_performance.h=csharrison@chromium.org
# Workers
diff --git a/chromium/third_party/blink/public/web/modules/autofill/OWNERS b/chromium/third_party/blink/public/web/modules/autofill/OWNERS
deleted file mode 100644
index d691287b2d5..00000000000
--- a/chromium/third_party/blink/public/web/modules/autofill/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-jochen@chromium.org
diff --git a/chromium/third_party/blink/public/web/modules/media/audio/fuchsia_audio_device_factory.h b/chromium/third_party/blink/public/web/modules/media/audio/fuchsia_audio_device_factory.h
index 3022c1004d1..50497c70e7d 100644
--- a/chromium/third_party/blink/public/web/modules/media/audio/fuchsia_audio_device_factory.h
+++ b/chromium/third_party/blink/public/web/modules/media/audio/fuchsia_audio_device_factory.h
@@ -12,32 +12,32 @@
namespace blink {
// TODO(https://crbug.com/787252): Move this class out of the Blink API layer.
-class BLINK_MODULES_EXPORT FuchsiaAudioDeviceFactory
+class BLINK_MODULES_EXPORT FuchsiaAudioDeviceFactory final
: public WebAudioDeviceFactory {
public:
FuchsiaAudioDeviceFactory();
- ~FuchsiaAudioDeviceFactory() final;
+ ~FuchsiaAudioDeviceFactory() override;
protected:
scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink(
const LocalFrameToken& frame_token,
const media::AudioSinkParameters& params,
- base::TimeDelta auth_timeout) final;
+ base::TimeDelta auth_timeout) override;
scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
WebAudioDeviceSourceType source_type,
const LocalFrameToken& frame_token,
- const media::AudioSinkParameters& params) final;
+ const media::AudioSinkParameters& params) override;
scoped_refptr<media::SwitchableAudioRendererSink>
CreateSwitchableAudioRendererSink(
WebAudioDeviceSourceType source_type,
const LocalFrameToken& frame_token,
- const media::AudioSinkParameters& params) final;
+ const media::AudioSinkParameters& params) override;
scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
const LocalFrameToken& frame_token,
- const media::AudioSourceParameters& params) final;
+ const media::AudioSourceParameters& params) override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/modules/media/audio/web_audio_device_factory.h b/chromium/third_party/blink/public/web/modules/media/audio/web_audio_device_factory.h
index 230b24261de..c7c26342456 100644
--- a/chromium/third_party/blink/public/web/modules/media/audio/web_audio_device_factory.h
+++ b/chromium/third_party/blink/public/web/modules/media/audio/web_audio_device_factory.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIA_AUDIO_WEB_AUDIO_DEVICE_FACTORY_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "media/audio/audio_sink_parameters.h"
#include "media/audio/audio_source_parameters.h"
@@ -31,6 +30,9 @@ namespace blink {
// AudioCapturerSourceFactory.
class BLINK_MODULES_EXPORT WebAudioDeviceFactory {
public:
+ WebAudioDeviceFactory(const WebAudioDeviceFactory&) = delete;
+ WebAudioDeviceFactory& operator=(const WebAudioDeviceFactory&) = delete;
+
// Maps the source type to the audio latency it requires.
static media::AudioLatency::LatencyType GetSourceLatencyType(
WebAudioDeviceSourceType source);
@@ -116,8 +118,6 @@ class BLINK_MODULES_EXPORT WebAudioDeviceFactory {
const LocalFrameToken& frame_token,
const media::AudioSinkParameters& params,
base::TimeDelta auth_timeout);
-
- DISALLOW_COPY_AND_ASSIGN(WebAudioDeviceFactory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/modules/media/audio/web_audio_input_ipc_factory.h b/chromium/third_party/blink/public/web/modules/media/audio/web_audio_input_ipc_factory.h
index 0d5d50dd946..c91f0f3deb9 100644
--- a/chromium/third_party/blink/public/web/modules/media/audio/web_audio_input_ipc_factory.h
+++ b/chromium/third_party/blink/public/web/modules/media/audio/web_audio_input_ipc_factory.h
@@ -29,6 +29,8 @@ class BLINK_MODULES_EXPORT WebAudioInputIPCFactory {
WebAudioInputIPCFactory(
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+ WebAudioInputIPCFactory(const WebAudioInputIPCFactory&) = delete;
+ WebAudioInputIPCFactory& operator=(const WebAudioInputIPCFactory&) = delete;
~WebAudioInputIPCFactory();
static WebAudioInputIPCFactory& GetInstance();
@@ -45,8 +47,6 @@ class BLINK_MODULES_EXPORT WebAudioInputIPCFactory {
private:
const scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(WebAudioInputIPCFactory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/modules/media/audio/web_audio_output_ipc_factory.h b/chromium/third_party/blink/public/web/modules/media/audio/web_audio_output_ipc_factory.h
index afa834b5d2c..5ae0c1f6527 100644
--- a/chromium/third_party/blink/public/web/modules/media/audio/web_audio_output_ipc_factory.h
+++ b/chromium/third_party/blink/public/web/modules/media/audio/web_audio_output_ipc_factory.h
@@ -36,6 +36,8 @@ class BLINK_MODULES_EXPORT WebAudioOutputIPCFactory {
public:
explicit WebAudioOutputIPCFactory(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+ WebAudioOutputIPCFactory(const WebAudioOutputIPCFactory&) = delete;
+ WebAudioOutputIPCFactory& operator=(const WebAudioOutputIPCFactory&) = delete;
~WebAudioOutputIPCFactory();
static WebAudioOutputIPCFactory& GetInstance();
@@ -61,8 +63,6 @@ class BLINK_MODULES_EXPORT WebAudioOutputIPCFactory {
// Blink public API layer, move this Pimpl class back to its outer class.
class Impl;
std::unique_ptr<Impl> impl_;
-
- DISALLOW_COPY_AND_ASSIGN(WebAudioOutputIPCFactory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h
index 28930c5f290..5b23e745312 100644
--- a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h
+++ b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h
@@ -36,8 +36,10 @@ class BLINK_MODULES_EXPORT MediaStreamVideoSink : public WebMediaStreamSink {
// UsesAlpha indicates if this MediaStreamVideoSink might use its source's
// alpha channel (if the source has one). This should be kDefault unless it is
- // guaranteed that the alpha channel of |track| will be ignored.
- enum class UsesAlpha { kDefault, kNo };
+ // guaranteed that the alpha channel of |track| will be ignored. If
+ // kDependsOnOtherSinks is used, the sink will not receive alpha if all other
+ // sinks do not use alpha.
+ enum class UsesAlpha { kDefault, kDependsOnOtherSinks, kNo };
protected:
MediaStreamVideoSink();
diff --git a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
index 1195a51f935..5662be529ee 100644
--- a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
+++ b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
@@ -10,9 +10,7 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
#include "media/base/video_frame.h"
#include "media/capture/video_capture_types.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -60,7 +58,10 @@ class BLINK_MODULES_EXPORT MediaStreamVideoSource
// RestartCallback is used for both the StopForRestart and Restart operations.
using RestartCallback = base::OnceCallback<void(RestartResult)>;
- MediaStreamVideoSource();
+ explicit MediaStreamVideoSource(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+ MediaStreamVideoSource(const MediaStreamVideoSource&) = delete;
+ MediaStreamVideoSource& operator=(const MediaStreamVideoSource&) = delete;
~MediaStreamVideoSource() override;
// Returns the MediaStreamVideoSource object owned by |source|.
@@ -181,7 +182,7 @@ class BLINK_MODULES_EXPORT MediaStreamVideoSource
virtual VideoCaptureFeedbackCB GetFeedbackCallback() const;
size_t NumTracks() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return tracks_.size();
}
@@ -365,8 +366,6 @@ class BLINK_MODULES_EXPORT MediaStreamVideoSource
// died before this callback is resolved, we still need to trigger the
// callback to notify the caller that the request is canceled.
base::OnceClosure remove_last_track_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h b/chromium/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
index 9ac5e9b6777..53782ddd9d7 100644
--- a/chromium/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
+++ b/chromium/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
@@ -90,6 +89,9 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
std::unique_ptr<WebVideoFrameSubmitter> submitter_,
WebMediaPlayer::SurfaceLayerMode surface_layer_mode);
+ WebMediaPlayerMS(const WebMediaPlayerMS&) = delete;
+ WebMediaPlayerMS& operator=(const WebMediaPlayerMS&) = delete;
+
~WebMediaPlayerMS() override;
WebMediaPlayer::LoadTiming Load(LoadType load_type,
@@ -174,10 +176,10 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
void OnFrameShown() override;
void OnIdleTimeout() override;
- void OnFirstFrameReceived(media::VideoRotation video_rotation,
+ void OnFirstFrameReceived(media::VideoTransformation video_transform,
bool is_opaque);
void OnOpacityChanged(bool is_opaque);
- void OnRotationChanged(media::VideoRotation video_rotation);
+ void OnTransformChanged(media::VideoTransformation video_transform);
// WebMediaStreamObserver implementation
void TrackAdded(const WebString& track_id) override;
@@ -355,8 +357,6 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
base::WeakPtr<WebMediaPlayerMS> weak_this_;
base::WeakPtrFactory<WebMediaPlayerMS> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerMS);
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_ax_context.h b/chromium/third_party/blink/public/web/web_ax_context.h
index c3e1728d463..cefdd30da9b 100644
--- a/chromium/third_party/blink/public/web/web_ax_context.h
+++ b/chromium/third_party/blink/public/web/web_ax_context.h
@@ -8,6 +8,10 @@
#include "third_party/blink/public/web/web_ax_object.h"
#include "third_party/blink/public/web/web_document.h"
+namespace ui {
+class AXMode;
+} // namespace ui
+
namespace blink {
class AXContext;
@@ -16,12 +20,15 @@ class AXContext;
// support for the given document.
class WebAXContext {
public:
- BLINK_EXPORT explicit WebAXContext(WebDocument document);
+ BLINK_EXPORT explicit WebAXContext(WebDocument document,
+ const ui::AXMode& mode);
BLINK_EXPORT ~WebAXContext();
// Returns the root element of the document's accessibility tree.
BLINK_EXPORT WebAXObject Root() const;
+ BLINK_EXPORT const ui::AXMode& GetAXMode() const;
+
private:
std::unique_ptr<AXContext> private_;
};
diff --git a/chromium/third_party/blink/public/web/web_ax_object.h b/chromium/third_party/blink/public/web/web_ax_object.h
index 1e5b15d3567..7342f45a663 100644
--- a/chromium/third_party/blink/public/web/web_ax_object.h
+++ b/chromium/third_party/blink/public/web/web_ax_object.h
@@ -38,7 +38,9 @@
#include "ui/accessibility/ax_enums.mojom-shared.h"
#include "ui/accessibility/ax_mode.h"
-class SkMatrix44;
+namespace skia {
+class Matrix44;
+}
namespace gfx {
class Point;
@@ -133,7 +135,6 @@ class WebAXObject {
BLINK_EXPORT void Serialize(ui::AXNodeData* node_data,
ui::AXMode accessibility_mode) const;
- BLINK_EXPORT bool IsAnchor() const;
BLINK_EXPORT ax::mojom::CheckedState CheckedState() const;
BLINK_EXPORT bool IsCheckable() const;
BLINK_EXPORT bool IsClickable() const;
@@ -346,7 +347,7 @@ class WebAXObject {
// or similar, set |clips_children| to true.
BLINK_EXPORT void GetRelativeBounds(WebAXObject& offset_container,
gfx::RectF& bounds_in_container,
- SkMatrix44& container_transform,
+ skia::Matrix44& container_transform,
bool* clips_children = nullptr) const;
// Retrieves a vector of all WebAXObjects in this document whose
diff --git a/chromium/third_party/blink/public/web/web_custom_element.h b/chromium/third_party/blink/public/web/web_custom_element.h
index fca6c280668..84305f05477 100644
--- a/chromium/third_party/blink/public/web/web_custom_element.h
+++ b/chromium/third_party/blink/public/web/web_custom_element.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_CUSTOM_ELEMENT_H_
#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_CUSTOM_ELEMENT_H_
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_common.h"
namespace blink {
@@ -52,12 +51,14 @@ class WebCustomElement {
class BLINK_EXPORT EmbedderNamesAllowedScope {
public:
EmbedderNamesAllowedScope();
+ EmbedderNamesAllowedScope(const EmbedderNamesAllowedScope&) = delete;
+ EmbedderNamesAllowedScope& operator=(const EmbedderNamesAllowedScope&) =
+ delete;
~EmbedderNamesAllowedScope();
static bool IsAllowed();
private:
- DISALLOW_COPY_AND_ASSIGN(EmbedderNamesAllowedScope);
void* operator new(size_t) = delete;
};
diff --git a/chromium/third_party/blink/public/web/web_document.h b/chromium/third_party/blink/public/web/web_document.h
index 4c9a6b2743c..9b465acce1c 100644
--- a/chromium/third_party/blink/public/web/web_document.h
+++ b/chromium/third_party/blink/public/web/web_document.h
@@ -34,6 +34,8 @@
#include "net/cookies/site_for_cookies.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-shared.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_draggable_region.h"
@@ -82,8 +84,8 @@ class WebDocument : public WebNode {
BLINK_EXPORT WebString Encoding() const;
BLINK_EXPORT WebString ContentLanguage() const;
BLINK_EXPORT WebString GetReferrer() const;
- BLINK_EXPORT absl::optional<SkColor> ThemeColor() const;
- // The url of the OpenSearch Desription Document (if any).
+ BLINK_EXPORT absl::optional<SkColor> ThemeColor();
+ // The url of the OpenSearch Description Document (if any).
BLINK_EXPORT WebURL OpenSearchDescriptionURL() const;
// Returns the frame the document belongs to or 0 if the document is
@@ -106,7 +108,7 @@ class WebDocument : public WebNode {
BLINK_EXPORT WebElement Head();
BLINK_EXPORT WebString Title() const;
BLINK_EXPORT WebString ContentAsTextForTesting() const;
- BLINK_EXPORT WebElementCollection All();
+ BLINK_EXPORT WebElementCollection All() const;
BLINK_EXPORT WebVector<WebFormElement> Forms() const;
BLINK_EXPORT WebURL CompleteURL(const WebString&) const;
BLINK_EXPORT WebElement GetElementById(const WebString&) const;
@@ -142,6 +144,22 @@ class WebDocument : public WebNode {
BLINK_EXPORT bool IsLoaded();
+ // Returns true if the document is in prerendering.
+ BLINK_EXPORT bool IsPrerendering();
+
+ // Return true if accessibility processing has been enabled.
+ BLINK_EXPORT bool IsAccessibilityEnabled();
+
+ // Adds `callback` to the post-prerendering activation steps.
+ // https://jeremyroman.github.io/alternate-loading-modes/#document-post-prerendering-activation-steps-list
+ BLINK_EXPORT void AddPostPrerenderingActivationStep(
+ base::OnceClosure callback);
+
+ // Sets a cookie manager which can be used for this document.
+ BLINK_EXPORT void SetCookieManager(
+ CrossVariantMojoRemote<
+ network::mojom::RestrictedCookieManagerInterfaceBase> cookie_manager);
+
#if INSIDE_BLINK
BLINK_EXPORT WebDocument(Document*);
BLINK_EXPORT WebDocument& operator=(Document*);
diff --git a/chromium/third_party/blink/public/web/web_document_loader.h b/chromium/third_party/blink/public/web/web_document_loader.h
index f897ebebab6..273fc965ba6 100644
--- a/chromium/third_party/blink/public/web/web_document_loader.h
+++ b/chromium/third_party/blink/public/web/web_document_loader.h
@@ -36,6 +36,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "third_party/blink/public/common/loader/previews_state.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
#include "third_party/blink/public/platform/web_archive_info.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_source_location.h"
@@ -47,8 +48,6 @@ class WebDocumentSubresourceFilter;
class WebServiceWorkerNetworkProvider;
class WebURL;
class WebURLResponse;
-template <typename T>
-class WebVector;
namespace mojom {
enum class FetchCacheMode : int32_t;
@@ -93,14 +92,6 @@ class BLINK_EXPORT WebDocumentLoader {
virtual bool HasUnreachableURL() const = 0;
virtual WebURL UnreachableURL() const = 0;
- // Returns all redirects that occurred (both client and server) before
- // at last committing the current page. This will contain one entry
- // for each intermediate URL, and one entry for the last URL (so if
- // there are no redirects, it will contain exactly the current URL, and
- // if there is one redirect, it will contain the source and destination
- // URL).
- virtual void RedirectChain(WebVector<WebURL>&) const = 0;
-
// Returns whether the navigation associated with this datasource is a
// client redirect.
virtual bool IsClientRedirect() const = 0;
@@ -156,6 +147,10 @@ class BLINK_EXPORT WebDocumentLoader {
// Returns true when the document is a FTP directory.
virtual bool IsListingFtpDirectory() const = 0;
+ // Sets the CodeCacheHost for this loader.
+ virtual void SetCodeCacheHost(
+ mojo::PendingRemote<mojom::CodeCacheHost> code_cache_host) = 0;
+
protected:
~WebDocumentLoader() = default;
};
diff --git a/chromium/third_party/blink/public/web/web_element.h b/chromium/third_party/blink/public/web/web_element.h
index 18351649707..940937d6e00 100644
--- a/chromium/third_party/blink/public/web/web_element.h
+++ b/chromium/third_party/blink/public/web/web_element.h
@@ -85,6 +85,9 @@ class BLINK_EXPORT WebElement : public WebNode {
// Returns true if this is an autonomous custom element.
bool IsAutonomousCustomElement() const;
+ // Returns the owning shadow host for this element, if there is one.
+ WebElement OwnerShadowHost() const;
+
// Returns an author ShadowRoot attached to this element, regardless
// of open or closed. This returns null WebNode if this
// element has no ShadowRoot or has a UA ShadowRoot.
diff --git a/chromium/third_party/blink/public/web/web_frame.h b/chromium/third_party/blink/public/web/web_frame.h
index a70289aff20..2eeeafe1c5c 100644
--- a/chromium/third_party/blink/public/web/web_frame.h
+++ b/chromium/third_party/blink/public/web/web_frame.h
@@ -162,6 +162,10 @@ class BLINK_EXPORT WebFrame {
// the given node is not a frame, iframe or if the frame is empty.
static WebFrame* FromFrameOwnerElement(const WebNode&);
+ // Whether the owner element of this frame is in the document tree or the
+ // shadow tree, per https://w3c.github.io/webcomponents/spec/shadow/.
+ mojom::TreeScopeType GetTreeScopeType() const { return scope_; }
+
// This identifier represents the stable identifier between a
// LocalFrame <--> RenderFrameHostImpl or a
// RemoteFrame <--> RenderFrameProxyHost in the browser process.
@@ -170,8 +174,6 @@ class BLINK_EXPORT WebFrame {
#if INSIDE_BLINK
static WebFrame* FromCoreFrame(Frame*);
static Frame* ToCoreFrame(const WebFrame&);
-
- bool InShadowTree() const { return scope_ == mojom::TreeScopeType::kShadow; }
#endif
protected:
diff --git a/chromium/third_party/blink/public/web/web_image.h b/chromium/third_party/blink/public/web/web_image.h
index 3a4cfc5329e..413b5ef4d6e 100644
--- a/chromium/third_party/blink/public/web/web_image.h
+++ b/chromium/third_party/blink/public/web/web_image.h
@@ -56,7 +56,9 @@ class WebImage {
// Decodes the given image data. If the image has multiple frames,
// then the frame whose size is desired_size is returned. Otherwise,
- // the first frame is returned.
+ // the first frame is returned. If the image contains EXIF data that changes
+ // the orientation, the returned image will be rotated such that the result is
+ // top-left oriented.
BLINK_EXPORT static SkBitmap FromData(const WebData&,
const gfx::Size& desired_size);
diff --git a/chromium/third_party/blink/public/web/web_local_frame.h b/chromium/third_party/blink/public/web/web_local_frame.h
index fd6ce9a3df3..7635bf51cb1 100644
--- a/chromium/third_party/blink/public/web/web_local_frame.h
+++ b/chromium/third_party/blink/public/web/web_local_frame.h
@@ -27,6 +27,7 @@
#include "third_party/blink/public/mojom/commit_result/commit_result.mojom-shared.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-shared.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-shared.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/media_player_action.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-shared.h"
@@ -45,7 +46,6 @@
#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/public/web/web_history_item.h"
#include "third_party/blink/public/web/web_navigation_params.h"
-#include "third_party/blink/public/web/web_optimization_guide_hints.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/base/ime/ime_text_span.h"
#include "ui/gfx/range/range.h"
@@ -369,6 +369,9 @@ class WebLocalFrame : public WebFrame {
// Returns the world ID associated with |script_context|.
virtual int32_t GetScriptContextWorldId(
v8::Local<v8::Context> script_context) const = 0;
+ virtual v8::Local<v8::Context> GetScriptContextFromWorldId(
+ v8::Isolate* isolate,
+ int world_id) const = 0;
// Executes script in the context of the current page and returns the value
// that the script evaluated to with callback. Script execution can be
@@ -794,12 +797,6 @@ class WebLocalFrame : public WebFrame {
UserActivationUpdateSource update_source =
UserActivationUpdateSource::kRenderer) = 0;
- // Optimization Guide --------------------------------------------------------
-
- // Sets the optimization hints provided by the optimization guide service. See
- // //components/optimization_guide/README.md.
- virtual void SetOptimizationGuideHints(const WebOptimizationGuideHints&) = 0;
-
// Testing ------------------------------------------------------------------
// Get the total spool size (the bounding box of all the pages placed after
@@ -842,6 +839,22 @@ class WebLocalFrame : public WebFrame {
// Reset TextFinder state for the web test runner in between two tests.
virtual void ClearActiveFindMatchForTesting() = 0;
+ virtual bool ServiceWorkerSubresourceFilterEnabled() = 0;
+
+ // Sets a local storage area which can be used for this frame. This storage
+ // area is ignored if a cached storage area already exists for the storage
+ // key.
+ virtual void SetLocalStorageArea(
+ CrossVariantMojoRemote<mojom::StorageAreaInterfaceBase>
+ local_storage_area) = 0;
+
+ // Sets a session storage area which can be used for this frame. This storage
+ // area is ignored if a cached storage area already exists for the storage
+ // key and namespace.
+ virtual void SetSessionStorageArea(
+ CrossVariantMojoRemote<mojom::StorageAreaInterfaceBase>
+ session_storage_area) = 0;
+
protected:
explicit WebLocalFrame(mojom::TreeScopeType scope,
const LocalFrameToken& frame_token)
diff --git a/chromium/third_party/blink/public/web/web_local_frame_client.h b/chromium/third_party/blink/public/web/web_local_frame_client.h
index c17f15d9cbf..99ddb8f4494 100644
--- a/chromium/third_party/blink/public/web/web_local_frame_client.h
+++ b/chromium/third_party/blink/public/web/web_local_frame_client.h
@@ -51,6 +51,7 @@
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/triggering_event_info.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-shared.h"
+#include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-shared.h"
#include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom-shared.h"
#include "third_party/blink/public/mojom/portal/portal.mojom-shared.h"
#include "third_party/blink/public/platform/blame_context.h"
@@ -262,6 +263,13 @@ class BLINK_EXPORT WebLocalFrameClient {
return nullptr;
}
+ // Request the creation of a new fenced frame, and return the WebRemoteFrame*
+ // associated with it.
+ virtual WebRemoteFrame* CreateFencedFrame(
+ const WebElement& fenced_frame_element) {
+ return nullptr;
+ }
+
// Called when Blink cannot find a frame with the given name in the frame's
// browsing instance. This gives the embedder a chance to return a frame
// from outside of the browsing instance.
@@ -419,12 +427,19 @@ class BLINK_EXPORT WebLocalFrameClient {
// |is_synchronously_committed| is true if the navigation is synchronously
// committed from within Blink, as opposed to being driven by the browser's
// navigation stack.
- virtual void DidFinishSameDocumentNavigation(WebHistoryCommitType,
- bool is_synchronously_committed,
- bool is_history_api_navigation,
- bool is_client_redirect) {}
+ virtual void DidFinishSameDocumentNavigation(
+ WebHistoryCommitType,
+ bool is_synchronously_committed,
+ mojom::SameDocumentNavigationType,
+ bool is_client_redirect) {}
+
+ // Called before a frame's page is frozen.
+ virtual void WillFreezePage() {}
- // Called when a RenderFrame's page lifecycle state gets updated.
+ // The frame's document changed its URL due to document.open().
+ virtual void DidOpenDocumentInputStream(const WebURL&) {}
+
+ // Called when a frame's page lifecycle state gets updated.
virtual void DidSetPageLifecycleState() {}
// Called upon update to scroll position, document state, and other
@@ -539,11 +554,6 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void DidObserveLayoutShift(double score, bool after_input_or_scroll) {
}
- // Reports input timestamps for segmenting layout shifts by users inputs to
- // create Session window.
- virtual void DidObserveInputForLayoutShiftTracking(
- base::TimeTicks timestamp) {}
-
// Reports the number of LayoutBlock creation, and LayoutObject::UpdateLayout
// calls. All values are deltas since the last calls of this function.
virtual void DidObserveLayoutNg(uint32_t all_block_count,
@@ -758,6 +768,10 @@ class BLINK_EXPORT WebLocalFrameClient {
// than the document's URL because it will contain a data URL if a base URL
// was used for its load or if an unreachable URL was used.
virtual WebURL LastCommittedUrlForUKM() { return WebURL(); }
+
+ // Called when script in the frame (and it subframes) wishes to be printed via
+ // a window.print() call.
+ virtual void ScriptedPrint() {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_manifest_manager.h b/chromium/third_party/blink/public/web/web_manifest_manager.h
index 503e2c676d9..d37c6a98f66 100644
--- a/chromium/third_party/blink/public/web/web_manifest_manager.h
+++ b/chromium/third_party/blink/public/web/web_manifest_manager.h
@@ -10,13 +10,12 @@
namespace blink {
-struct Manifest;
class WebLocalFrame;
class WebURL;
class WebManifestManager {
public:
- using Callback = base::OnceCallback<void(const WebURL&, const Manifest&)>;
+ using Callback = base::OnceCallback<void(const WebURL&)>;
BLINK_EXPORT static void RequestManifestForTesting(WebLocalFrame*,
Callback callback);
diff --git a/chromium/third_party/blink/public/web/web_navigation_params.h b/chromium/third_party/blink/public/web/web_navigation_params.h
index 8583eb494ab..e07991ccb63 100644
--- a/chromium/third_party/blink/public/web/web_navigation_params.h
+++ b/chromium/third_party/blink/public/web/web_navigation_params.h
@@ -11,11 +11,13 @@
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "services/network/public/mojom/link_header.mojom-shared.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "services/network/public/mojom/url_loader_factory.mojom-shared.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-shared.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
@@ -310,9 +312,18 @@ struct BLINK_EXPORT WebNavigationParams {
// The origin in which a navigation should commit. When provided, Blink
// should use this origin directly and not compute locally the new document
// origin.
- // TODO(arthursonzogni): Always provide origin_to_commit.
+ //
+ // TODO(https://crbug.com/888079): Always provide origin_to_commit.
WebSecurityOrigin origin_to_commit;
+ // The storage key of the document that will be created by the navigation.
+ // This is compatible with the `origin_to_commit`. Until the browser will be
+ // able to compute the `origin_to_commit` in all cases
+ // (https://crbug.com/888079), this is actually just a provisional
+ // `storage_key`. The final storage key is computed by the document loader
+ // taking into account the origin computed by the renderer.
+ StorageKey storage_key;
+
// The sandbox flags to apply to the new document. This is the union of:
// - the frame's current sandbox attribute, taken when the navigation started.
// - the navigation response's CSP sandbox flags.
@@ -343,8 +354,6 @@ struct BLINK_EXPORT WebNavigationParams {
bool has_text_fragment_token = false;
// Whether this navigation was browser initiated.
bool is_browser_initiated = false;
- // Whether this navigation was for prerendering.
- bool is_prerendering = false;
// Whether the document should be able to access local file:// resources.
bool grant_load_local_resources = false;
// The previews state which should be used for this navigation.
@@ -356,6 +365,10 @@ struct BLINK_EXPORT WebNavigationParams {
// The AppCache host id for this navigation.
base::UnguessableToken appcache_host_id;
+ // This is `true` only for commit requests coming from
+ // `RenderFrameImpl::SynchronouslyConmmitAboutBlankForBug778318`.
+ bool is_synchronous_commit_for_bug_778318 = false;
+
// Used for SignedExchangeSubresourcePrefetch.
// This struct keeps the information about a prefetched signed exchange.
struct BLINK_EXPORT PrefetchedSignedExchange {
@@ -428,6 +441,9 @@ struct BLINK_EXPORT WebNavigationParams {
// appHistory.
WebVector<WebHistoryItem> app_history_back_entries;
WebVector<WebHistoryItem> app_history_forward_entries;
+
+ // List of URLs which are preloaded by HTTP Early Hints.
+ WebVector<WebURL> early_hints_preloaded_resources;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_optimization_guide_hints.h b/chromium/third_party/blink/public/web/web_optimization_guide_hints.h
deleted file mode 100644
index 7d1c1c83cfd..00000000000
--- a/chromium/third_party/blink/public/web/web_optimization_guide_hints.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_OPTIMIZATION_GUIDE_HINTS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_OPTIMIZATION_GUIDE_HINTS_H_
-
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom-shared.h"
-
-namespace blink {
-
-struct WebOptimizationGuideHints {
- absl::optional<mojom::DelayAsyncScriptExecutionDelayType>
- delay_async_script_execution_delay_type;
-
- absl::optional<mojom::DelayCompetingLowPriorityRequestsDelayType>
- delay_competing_low_priority_requests_delay_type;
- absl::optional<mojom::DelayCompetingLowPriorityRequestsPriorityThreshold>
- delay_competing_low_priority_requests_priority_threshold;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_OPTIMIZATION_GUIDE_HINTS_H_
diff --git a/chromium/third_party/blink/public/web/web_performance.h b/chromium/third_party/blink/public/web/web_performance.h
index 1a0eb915bdd..fa2dfe0c836 100644
--- a/chromium/third_party/blink/public/web/web_performance.h
+++ b/chromium/third_party/blink/public/web/web_performance.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PERFORMANCE_H_
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_private_ptr.h"
#include "third_party/blink/public/platform/web_vector.h"
@@ -138,6 +139,7 @@ class WebPerformance {
BLINK_EXPORT double ParseBlockedOnScriptExecutionFromDocumentWriteDuration()
const;
BLINK_EXPORT absl::optional<base::TimeTicks> LastPortalActivatedPaint() const;
+ BLINK_EXPORT absl::optional<base::TimeDelta> PrerenderActivationStart() const;
BLINK_EXPORT absl::optional<base::TimeTicks> UnloadStart() const;
BLINK_EXPORT absl::optional<base::TimeTicks> UnloadEnd() const;
BLINK_EXPORT absl::optional<base::TimeTicks> CommitNavigationEnd() const;
diff --git a/chromium/third_party/blink/public/web/web_plugin.h b/chromium/third_party/blink/public/web/web_plugin.h
index c826ca02570..d055e7e4cce 100644
--- a/chromium/third_party/blink/public/web/web_plugin.h
+++ b/chromium/third_party/blink/public/web/web_plugin.h
@@ -147,8 +147,6 @@ class WebPlugin {
virtual bool GetPrintPresetOptionsFromDocument(WebPrintPresetOptions*) {
return false;
}
- // Returns true if the plugin is a PDF plugin.
- virtual bool IsPdfPlugin() { return false; }
// Sets up printing with the specified printParams. Returns the number of
// pages to be printed at these settings.
@@ -238,10 +236,7 @@ class WebPlugin {
virtual void StopFind() {}
// View rotation types.
- enum RotationType {
- kRotationType90Clockwise,
- kRotationType90Counterclockwise
- };
+ enum class RotationType { k90Clockwise, k90Counterclockwise };
// Whether the plugin can rotate the view of its content.
virtual bool CanRotateView() { return false; }
// Rotates the plugin's view of its content.
diff --git a/chromium/third_party/blink/public/web/web_print_preset_options.h b/chromium/third_party/blink/public/web/web_print_preset_options.h
index be28b55ec5c..c0c0cb834d4 100644
--- a/chromium/third_party/blink/public/web/web_print_preset_options.h
+++ b/chromium/third_party/blink/public/web/web_print_preset_options.h
@@ -5,44 +5,25 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRINT_PRESET_OPTIONS_H_
#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRINT_PRESET_OPTIONS_H_
-#include <vector>
-
#include "printing/mojom/print.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
namespace blink {
-struct WebPageRange;
-typedef std::vector<WebPageRange> WebPageRanges;
-
-struct WebPageRange {
- int from;
- int to;
-};
-
struct WebPrintPresetOptions {
- WebPrintPresetOptions()
- : is_scaling_disabled(false),
- copies(0),
- duplex_mode(printing::mojom::DuplexMode::kUnknownDuplexMode) {}
-
// Specifies whether scaling is disabled.
- bool is_scaling_disabled;
+ bool is_scaling_disabled = false;
// Specifies the number of copies to be printed.
- int copies;
+ int copies = 0;
// Specifies duplex mode to be used for printing.
- printing::mojom::DuplexMode duplex_mode;
-
- // Specifies page range to be used for printing.
- WebPageRanges page_ranges;
-
- // True if all the pages in the PDF are the same size.
- bool is_page_size_uniform;
+ printing::mojom::DuplexMode duplex_mode =
+ printing::mojom::DuplexMode::kUnknownDuplexMode;
// Only valid if the page sizes are uniform. The page size in points.
- gfx::Size uniform_page_size;
+ absl::optional<gfx::Size> uniform_page_size;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_remote_frame.h b/chromium/third_party/blink/public/web/web_remote_frame.h
index c05190b0ce4..112f3b0b1d8 100644
--- a/chromium/third_party/blink/public/web/web_remote_frame.h
+++ b/chromium/third_party/blink/public/web/web_remote_frame.h
@@ -7,7 +7,6 @@
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
#include "third_party/blink/public/common/tokens/tokens.h"
-#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-shared.h"
@@ -54,15 +53,15 @@ class WebRemoteFrame : public WebFrame {
WebFrame* opener);
// Also performs core initialization to associate the created remote frame
- // with the provided <portal> element.
- BLINK_EXPORT static WebRemoteFrame* CreateForPortal(
+ // with the provided <portal> or <fencedframe> element.
+ BLINK_EXPORT static WebRemoteFrame* CreateForPortalOrFencedFrame(
mojom::TreeScopeType,
WebRemoteFrameClient*,
InterfaceRegistry*,
AssociatedInterfaceProvider*,
const RemoteFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token,
- const WebElement& portal_element);
+ const WebElement& frame_owner);
// Specialized factory methods to allow the embedder to replicate the frame
// tree between processes.
@@ -117,14 +116,10 @@ class WebRemoteFrame : public WebFrame {
virtual void SetReplicatedInsecureNavigationsSet(
const WebVector<unsigned>&) = 0;
- virtual void SetReplicatedAdFrameType(
- blink::mojom::AdFrameType ad_frame_type) = 0;
+ virtual void SetReplicatedIsAdSubframe(bool is_ad_subframe) = 0;
virtual void DidStartLoading() = 0;
- // Returns true if this frame should be ignored during hittesting.
- virtual bool IsIgnoredForHitTest() const = 0;
-
// Update the user activation state in appropriate part of this frame's
// "local" frame tree (ancestors-only vs all-nodes).
//
@@ -136,13 +131,6 @@ class WebRemoteFrame : public WebFrame {
virtual void SetHadStickyUserActivationBeforeNavigation(bool value) = 0;
- virtual void SynchronizeVisualProperties() = 0;
- virtual void ResendVisualProperties() = 0;
-
- // Returns the ideal raster scale factor for the OOPIF's compositor so that it
- // doesn't raster at a higher scale than it needs to.
- virtual float GetCompositingScaleFactor() = 0;
-
// Unique name is an opaque identifier for maintaining association with
// session restore state for this frame.
virtual WebString UniqueName() const = 0;
diff --git a/chromium/third_party/blink/public/web/web_remote_frame_client.h b/chromium/third_party/blink/public/web/web_remote_frame_client.h
index 6184d3e4714..3f6402358d9 100644
--- a/chromium/third_party/blink/public/web/web_remote_frame_client.h
+++ b/chromium/third_party/blink/public/web/web_remote_frame_client.h
@@ -7,7 +7,6 @@
#include "cc/paint/paint_canvas.h"
#include "components/viz/common/surfaces/surface_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-shared.h"
diff --git a/chromium/third_party/blink/public/web/web_savable_resources_test_support.h b/chromium/third_party/blink/public/web/web_savable_resources_test_support.h
index 8281f5c4359..ec09a18964b 100644
--- a/chromium/third_party/blink/public/web/web_savable_resources_test_support.h
+++ b/chromium/third_party/blink/public/web/web_savable_resources_test_support.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SAVABLE_RESOURCES_TEST_SUPPORT_H_
#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SAVABLE_RESOURCES_TEST_SUPPORT_H_
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_common.h"
namespace blink {
diff --git a/chromium/third_party/blink/public/web/web_security_policy.h b/chromium/third_party/blink/public/web/web_security_policy.h
index 40e49d9306b..c6613ea15a2 100644
--- a/chromium/third_party/blink/public/web/web_security_policy.h
+++ b/chromium/third_party/blink/public/web/web_security_policy.h
@@ -130,6 +130,18 @@ class WebSecurityPolicy {
// Registers an URL scheme as an error page.
BLINK_EXPORT static void RegisterURLSchemeAsError(const WebString&);
+ // Registers an URL scheme as a browser extension.
+ BLINK_EXPORT static void RegisterURLSchemeAsExtension(const WebString&);
+
+ // Registers an URL scheme as trusted browser UI.
+ BLINK_EXPORT static void RegisterURLSchemeAsWebUI(const WebString&);
+
+ // Registers an URL scheme which can use code caching but must check in the
+ // renderer whether the script content has changed rather than relying on a
+ // response time match from the network cache.
+ BLINK_EXPORT static void RegisterURLSchemeAsCodeCacheWithHashing(
+ const WebString&);
+
private:
WebSecurityPolicy() = delete;
};
diff --git a/chromium/third_party/blink/public/web/web_settings.h b/chromium/third_party/blink/public/web/web_settings.h
index e555570ac36..73a644ee08a 100644
--- a/chromium/third_party/blink/public/web/web_settings.h
+++ b/chromium/third_party/blink/public/web/web_settings.h
@@ -172,7 +172,6 @@ class WebSettings {
virtual void SetMinimumLogicalFontSize(int) = 0;
virtual void SetHideScrollbars(bool) = 0;
virtual void SetOfflineWebApplicationCacheEnabled(bool) = 0;
- virtual void SetPassiveEventListenerDefault(PassiveEventListenerDefault) = 0;
virtual void SetPasswordEchoDurationInSeconds(double) = 0;
virtual void SetPasswordEchoEnabled(bool) = 0;
virtual void SetPictographFontFamily(const WebString&,
@@ -285,6 +284,7 @@ class WebSettings {
virtual void SetSelectionClipboardBufferAvailable(bool) = 0;
virtual void SetAccessibilityIncludeSvgGElement(bool) = 0;
virtual void SetWebXRImmersiveArAllowed(bool) = 0;
+ virtual void SetLitePageSubresourceRedirectOrigin(const WebString&) = 0;
protected:
~WebSettings() = default;
diff --git a/chromium/third_party/blink/public/web/web_view.h b/chromium/third_party/blink/public/web/web_view.h
index 7acd3f2bf49..f54b993e9fb 100644
--- a/chromium/third_party/blink/public/web/web_view.h
+++ b/chromium/third_party/blink/public/web/web_view.h
@@ -41,13 +41,13 @@
#include "third_party/blink/public/mojom/page/page.mojom-shared.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-shared.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom-shared.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-shared.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/display/mojom/screen_orientation.mojom-shared.h"
#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -98,6 +98,8 @@ class WebView {
//
// clients may be null, but should both be null or not together.
// |is_hidden| defines the initial visibility of the page.
+ // |is_prerendering| defines whether the page is being prerendered by the
+ // Prerender2 feature (see content/browser/prerender/README.md).
// [is_inside_portal] defines whether the page is inside_portal.
// |compositing_enabled| dictates whether accelerated compositing should be
// enabled for the page. It must be false if no clients are provided, or if a
@@ -114,10 +116,14 @@ class WebView {
// to inform blink it is in the foreground or background. Whereas this bit
// refers to user-visibility and whether the tab needs to produce pixels to
// put on the screen at some point or not.
+ // |page_base_background_color| initial base background color used by the main
+ // frame. Set on create to avoid races. Passing in nullopt indicates the
+ // default base background color should be used.
// TODO(yuzus): Remove |is_hidden| and start using |PageVisibilityState|.
BLINK_EXPORT static WebView* Create(
WebViewClient*,
bool is_hidden,
+ bool is_prerendering,
bool is_inside_portal,
bool compositing_enabled,
bool widgets_never_composited,
@@ -125,7 +131,8 @@ class WebView {
CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase>
page_handle,
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const SessionStorageNamespaceId& session_storage_namespace_id);
+ const SessionStorageNamespaceId& session_storage_namespace_id,
+ absl::optional<SkColor> page_base_background_color);
// Destroys the WebView.
virtual void Close() = 0;
@@ -283,7 +290,7 @@ class WebView {
// Override the screen orientation override.
virtual void SetScreenOrientationOverrideForTesting(
- absl::optional<blink::mojom::ScreenOrientation> orientation) = 0;
+ absl::optional<display::mojom::ScreenOrientation> orientation) = 0;
// Enable/Disable synchronous resize mode that is used for web tests.
virtual void UseSynchronousResizeModeForTesting(bool enable) = 0;
@@ -353,11 +360,6 @@ class WebView {
// Custom colors -------------------------------------------------------
- // Sets the default background color when the page has not loaded enough to
- // know a background colour. This can be overridden by the methods below as
- // well.
- virtual void SetBaseBackgroundColor(SkColor) {}
-
virtual void SetDeviceColorSpaceForTesting(
const gfx::ColorSpace& color_space) = 0;
@@ -462,7 +464,10 @@ class WebView {
virtual int32_t HistoryBackListCount() const = 0;
virtual int32_t HistoryForwardListCount() const = 0;
- // Portals --------------------------------------------------------------
+ // Misc -------------------------------------------------------------
+
+ // Returns the number of live WebView instances in this process.
+ BLINK_EXPORT static size_t GetWebViewCount();
protected:
~WebView() = default;
diff --git a/chromium/third_party/blink/public/web/web_view_client.h b/chromium/third_party/blink/public/web/web_view_client.h
index 75bdef8fa35..7b65e9d08cc 100644
--- a/chromium/third_party/blink/public/web/web_view_client.h
+++ b/chromium/third_party/blink/public/web/web_view_client.h
@@ -84,14 +84,6 @@ class WebViewClient {
// the layers.
virtual void InvalidateContainer() {}
- // Called when script in the page calls window.print(). If frame is
- // non-null, then it selects a particular frame, including its
- // children, to print. Otherwise, the main frame and its children
- // should be printed.
- virtual void PrintPage(WebLocalFrame*) {}
-
- virtual void OnPageFrozenChanged(bool frozen) {}
-
// UI ------------------------------------------------------------------
// Called when the View has changed size as a result of an auto-resize.
diff --git a/chromium/third_party/blink/public/web/web_widget.h b/chromium/third_party/blink/public/web/web_widget.h
index 190cc57ddbb..0eaa04ff2a2 100644
--- a/chromium/third_party/blink/public/web/web_widget.h
+++ b/chromium/third_party/blink/public/web/web_widget.h
@@ -60,14 +60,17 @@ class LayerTreeHost;
class LayerTreeSettings;
}
+namespace display {
+struct ScreenInfo;
+struct ScreenInfos;
+} // namespace display
+
namespace ui {
class Cursor;
class LatencyInfo;
}
namespace blink {
-struct ScreenInfo;
-struct ScreenInfos;
struct VisualProperties;
class WebCoalescedInputEvent;
@@ -84,7 +87,7 @@ class WebWidget {
// override the defaults.
virtual void InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const ScreenInfos& screen_info,
+ const display::ScreenInfos& screen_info,
const cc::LayerTreeSettings* settings) = 0;
// Set the compositor as visible. If |visible| is true, then the compositor
@@ -195,17 +198,17 @@ class WebWidget {
// Returns information about the screen where this view's widgets are being
// displayed.
- virtual const ScreenInfo& GetScreenInfo() = 0;
+ virtual const display::ScreenInfo& GetScreenInfo() = 0;
// Returns information about all available screens.
- virtual const ScreenInfos& GetScreenInfos() = 0;
+ virtual const display::ScreenInfos& GetScreenInfos() = 0;
// Returns original (non-emulated) information about the screen where this
// view's widgets are being displayed.
- virtual const ScreenInfo& GetOriginalScreenInfo() = 0;
+ virtual const display::ScreenInfo& GetOriginalScreenInfo() = 0;
// Returns original (non-emulated) information about all available screens.
- virtual const ScreenInfos& GetOriginalScreenInfos() = 0;
+ virtual const display::ScreenInfos& GetOriginalScreenInfos() = 0;
// Called to get the position of the widget's window in screen
// coordinates. Note, the window includes any decorations such as borders,
diff --git a/chromium/third_party/blink/renderer/DEPS b/chromium/third_party/blink/renderer/DEPS
index 697bddedd19..94659c10bbd 100644
--- a/chromium/third_party/blink/renderer/DEPS
+++ b/chromium/third_party/blink/renderer/DEPS
@@ -10,7 +10,9 @@ include_rules = [
"+base/compiler_specific.h",
"+base/containers/adapters.h",
"+base/containers/contains.h",
+ "+base/containers/cxx20_erase.h",
"+base/containers/span.h",
+ "+base/cxx17_backports.h",
"+base/dcheck_is_on.h",
"+base/debug",
"+base/feature_list.h",
@@ -21,7 +23,7 @@ include_rules = [
"+base/location.h",
"+base/logging.h",
"+base/macros.h",
- "+base/memory/checked_ptr.h",
+ "+base/memory/raw_ptr.h",
"+base/memory/ptr_util.h",
"+base/memory/weak_ptr.h",
"+base/metrics/field_trial_params.h",
@@ -63,14 +65,15 @@ include_rules = [
"+base/types/pass_key.h",
"+base/types/strong_alias.h",
"+build",
+ "+cc/paint",
"+components/crash/core/common/crash_key.h",
"+components/power_scheduler",
"+net/cookies",
"+net/http/structured_headers.h",
+ "+skia/ext",
"+services/network/public/mojom",
"+testing/gmock/include/gmock",
"+testing/gtest/include/gtest",
- "+third_party/abseil-cpp/absl/types/optional.h",
"+third_party/blink/public/platform",
"+third_party/blink/renderer/platform",
diff --git a/chromium/third_party/blink/renderer/README.md b/chromium/third_party/blink/renderer/README.md
index bf03536f813..97df608b766 100644
--- a/chromium/third_party/blink/renderer/README.md
+++ b/chromium/third_party/blink/renderer/README.md
@@ -84,6 +84,16 @@ just a part of a larger "core".
All of the above applies to `bindings/modules` and `modules/`.
+### `extensions/`
+
+The `extensions/` directory contains embedder-specific, not-web-exposed APIs (e.g., not-web-exposed APIs for Chromium OS etc).
+The directory is useful to implement embedder-specific, not-web-exposed APIs
+using Blink technologies for web-exposed APIs like WebIDL, V8 bindings and Oilpan.
+
+Remember that you should not implement web-exposed APIs in `extensions/`. Web-exposed APIs should go through the standardization process and be implemented in `core/` or `modules/`. Also, per [the Chromium contributor guideline](https://chromium.googlesource.com/chromium/src/+/main/docs/contributing.md#code-guidelines), code that is not used by Chromium should not be added to `extensions/`.
+
+In terms of dependencies, `extensions/` can depend on `modules/`, `core/` and `platform/`, but not vice versa.
+
### `controller/`
The `controller/` directory contains the system infrastructure
@@ -96,8 +106,7 @@ or to implement API for the embedder, it goes to `controller/`,
however most of the features should go to other directories.
Consult `controller/` OWNERS when in doubt.
-In terms of dependencies, `controller/` can depend on `core/`, `platform/` and `modules/`,
-but not vice versa.
+In terms of dependencies, `controller/` can depend on `extensions/`, `modules/`, `core/` and `platform/`, but not vice versa.
### `build/`
@@ -111,6 +120,7 @@ Dependencies only flow in the following order:
- `public/web`
- `controller/`
+- `extensions/`
- `modules/` and `bindings/modules`
- `core/` and `bindings/core`
- `platform/`
@@ -158,8 +168,7 @@ script](../tools/blinkpy/presubmit/audit_non_blink_usage.py).
### Mojo
-`core/`, `modules/`, `bindings/`, `platform/` and `controller/` can use Mojo and
-directly talk to the browser process. This allows removal of unnecessary
+Blink can use Mojo and directly talk to the browser process. This allows removal of unnecessary
public APIs and abstraction layers and it is highly recommended.
## Contact
diff --git a/chromium/third_party/blink/renderer/bindings/BUILD.gn b/chromium/third_party/blink/renderer/bindings/BUILD.gn
index 538cfc1eb26..30017570a13 100644
--- a/chromium/third_party/blink/renderer/bindings/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/BUILD.gn
@@ -4,70 +4,21 @@
import("//build/config/python.gni")
import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/core/v8/generated.gni")
import("//third_party/blink/renderer/bindings/generated_in_core.gni")
+import(
+ "//third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni")
import("//third_party/blink/renderer/bindings/generated_in_modules.gni")
import("//third_party/blink/renderer/bindings/idl_in_core.gni")
+import("//third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni")
import("//third_party/blink/renderer/bindings/idl_in_modules.gni")
-import("//third_party/blink/renderer/bindings/modules/v8/generated.gni")
import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
-import("//third_party/blink/renderer/build/scripts/scripts.gni")
-import("//third_party/blink/renderer/core/core_idl_files.gni")
-import("//third_party/blink/renderer/modules/modules_idl_files.gni")
visibility = [ "//third_party/blink/renderer/*" ]
-action("interfaces_info") {
- script = "$bindings_scripts_dir/compute_interfaces_info_overall.py"
-
- inputs = [
- "$bindings_core_output_dir/interfaces_info_core.pickle",
- "$bindings_modules_output_dir/interfaces_info_modules.pickle",
- ]
- outputs = [ "$bindings_output_dir/interfaces_info.pickle" ]
-
- args = [
- "--",
- rebase_path("$bindings_core_output_dir/interfaces_info_core.pickle",
- root_build_dir),
- rebase_path("$bindings_modules_output_dir/interfaces_info_modules.pickle",
- root_build_dir),
- rebase_path("$bindings_output_dir/interfaces_info.pickle", root_build_dir),
- ]
-
- public_deps = [
- "//third_party/blink/renderer/bindings/core:interfaces_info_core",
- "//third_party/blink/renderer/bindings/modules:interfaces_info_modules",
- ]
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("global_constructors_idls") {
- }
-} else {
- generate_global_constructors("global_constructors_idls") {
- sources =
- core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent +
- core_buffer_source_type_idl_files + core_callback_interface_idl_files
- global_objects_file =
- "$bindings_modules_output_dir/global_objects_modules.pickle"
- interfaces = modules_core_global_constructors_original_interfaces
- basenames = modules_core_global_constructors_original_interface_basenames
- component = "core"
- output_dir = blink_modules_output_dir
- deps = [
- "//third_party/blink/renderer/bindings/modules:modules_global_constructors_idls",
- "//third_party/blink/renderer/bindings/modules:modules_global_objects",
- ]
- }
-}
+bindings_gen_dir = get_path_info(".", "gen_dir")
template("collect_idl_files") {
action_with_pydeps(target_name) {
- # TODO(crbug.com/1194277): Investigate non-determinism in Py3 builds.
- run_under_python2 = true
-
script = "${bindings_scripts_dir}/collect_idl_files.py"
inputs = invoker.inputs
@@ -98,7 +49,7 @@ collect_idl_files("web_idl_in_core") {
inputs = static_idl_files_in_core
- output = "${bindings_output_dir}/web_idl_in_core.pickle"
+ output = "${bindings_gen_dir}/web_idl_in_core.pickle"
}
collect_idl_files("web_idl_in_core_for_testing") {
@@ -117,7 +68,15 @@ collect_idl_files("web_idl_in_core_for_testing") {
"//third_party/blink/renderer/core:generated_testing_idls_settings",
]
- output = "${bindings_output_dir}/web_idl_in_core_for_testing.pickle"
+ output = "${bindings_gen_dir}/web_idl_in_core_for_testing.pickle"
+}
+
+collect_idl_files("web_idl_in_extensions_chromeos") {
+ component = "extensions_chromeos"
+
+ inputs = static_idl_files_in_extensions_chromeos
+
+ output = "${bindings_gen_dir}/web_idl_in_extensions_chromeos.pickle"
}
collect_idl_files("web_idl_in_modules") {
@@ -125,7 +84,7 @@ collect_idl_files("web_idl_in_modules") {
inputs = static_idl_files_in_modules
- output = "${bindings_output_dir}/web_idl_in_modules.pickle"
+ output = "${bindings_gen_dir}/web_idl_in_modules.pickle"
}
collect_idl_files("web_idl_in_modules_for_testing") {
@@ -134,13 +93,10 @@ collect_idl_files("web_idl_in_modules_for_testing") {
inputs = static_idl_files_in_modules_for_testing
- output = "${bindings_output_dir}/web_idl_in_modules_for_testing.pickle"
+ output = "${bindings_gen_dir}/web_idl_in_modules_for_testing.pickle"
}
action_with_pydeps("web_idl_database") {
- # TODO(crbug.com/1194277): Investigate non-determinism in Py3 builds.
- run_under_python2 = true
-
visibility += [ "//tools/privacy_budget/blink_apis:*" ]
script = "${bindings_scripts_dir}/build_web_idl_database.py"
@@ -149,7 +105,18 @@ action_with_pydeps("web_idl_database") {
get_target_outputs(":web_idl_in_core_for_testing") +
get_target_outputs(":web_idl_in_modules") +
get_target_outputs(":web_idl_in_modules_for_testing")
+
runtime_enabled_features_file = "../platform/runtime_enabled_features.json5"
+ deps = [
+ ":web_idl_in_core",
+ ":web_idl_in_core_for_testing",
+ ":web_idl_in_modules",
+ ":web_idl_in_modules_for_testing",
+ ]
+ if (use_blink_extensions_chromeos) {
+ input_data_files += get_target_outputs(":web_idl_in_extensions_chromeos")
+ deps += [ ":web_idl_in_extensions_chromeos" ]
+ }
inputs = input_data_files + [ runtime_enabled_features_file ]
outputs = [ web_idl_database_filepath ]
@@ -160,20 +127,10 @@ action_with_pydeps("web_idl_database") {
rebase_path(runtime_enabled_features_file, root_build_dir),
"--",
] + rebase_path(input_data_files, root_build_dir)
-
- deps = [
- ":web_idl_in_core",
- ":web_idl_in_core_for_testing",
- ":web_idl_in_modules",
- ":web_idl_in_modules_for_testing",
- ]
}
template("generate_bindings") {
action_with_pydeps(target_name) {
- # TODO(crbug.com/1194277): Investigate non-determinism in Py3 builds.
- run_under_python2 = true
-
script = "${bindings_scripts_dir}/generate_bindings.py"
if (defined(invoker.visibility)) {
@@ -191,17 +148,29 @@ template("generate_bindings") {
outputs = invoker.outputs
args = [
- "--web_idl_database",
- rebase_path(web_idl_database, root_build_dir),
- "--root_src_dir",
- rebase_path("//", root_build_dir),
- "--root_gen_dir",
- rebase_path(root_gen_dir, root_build_dir),
- "--output_core_reldir",
- rebase_path("${bindings_output_dir}/core/v8/", root_gen_dir),
- "--output_modules_reldir",
- rebase_path("${bindings_output_dir}/modules/v8/", root_gen_dir),
- ] + invoker.targets
+ "--web_idl_database",
+ rebase_path(web_idl_database, root_build_dir),
+ "--root_src_dir",
+ rebase_path("//", root_build_dir),
+ "--root_gen_dir",
+ rebase_path(root_gen_dir, root_build_dir),
+ "--output_reldir",
+ "core=" + rebase_path("${bindings_gen_dir}/core/v8/", root_gen_dir),
+ "--output_reldir",
+ "modules=" + rebase_path("${bindings_gen_dir}/modules/v8/", root_gen_dir),
+ ]
+ if (use_blink_extensions_chromeos) {
+ args += [
+ "--output_reldir",
+ "extensions_chromeos=" +
+ rebase_path("${bindings_gen_dir}/extensions_chromeos/v8/",
+ root_gen_dir),
+ ]
+ }
+ if (blink_enable_generated_code_formatting) {
+ args += [ "--format_generated_files" ]
+ }
+ args += invoker.targets
deps = [ ":web_idl_database" ]
}
@@ -214,32 +183,27 @@ generate_bindings("generate_bindings_all") {
outputs = generated_enumeration_sources_in_core +
generated_enumeration_sources_in_modules +
generated_enumeration_sources_for_testing_in_core
- if (use_blink_v8_binding_new_idl_callback_function) {
- targets += [ "callback_function" ]
- outputs += generated_callback_function_sources_in_core +
- generated_callback_function_sources_in_modules +
- generated_callback_function_sources_for_testing_in_core
- }
- if (use_blink_v8_binding_new_idl_callback_interface) {
- targets += [ "callback_interface" ]
- outputs += generated_callback_interface_sources_in_core +
- generated_callback_interface_sources_in_modules
- }
- if (use_blink_v8_binding_new_idl_dictionary) {
- targets += [ "dictionary" ]
- outputs += generated_dictionary_sources_in_core +
- generated_dictionary_sources_in_modules +
- generated_dictionary_sources_for_testing_in_core
- }
- if (use_blink_v8_binding_new_idl_interface) {
- targets += [ "interface" ]
- outputs += generated_interface_sources_in_core +
- generated_interface_sources_in_modules +
- generated_interface_sources_for_testing_in_core +
- generated_interface_sources_for_testing_in_modules
- targets += [ "namespace" ]
- outputs += generated_namespace_sources_in_core +
- generated_namespace_sources_in_modules
+ targets += [ "callback_function" ]
+ outputs += generated_callback_function_sources_in_core +
+ generated_callback_function_sources_in_modules +
+ generated_callback_function_sources_for_testing_in_core
+ targets += [ "callback_interface" ]
+ outputs += generated_callback_interface_sources_in_core +
+ generated_callback_interface_sources_in_modules
+ targets += [ "dictionary" ]
+ outputs += generated_dictionary_sources_in_core +
+ generated_dictionary_sources_in_modules +
+ generated_dictionary_sources_for_testing_in_core
+ targets += [ "interface" ]
+ outputs += generated_interface_sources_in_core +
+ generated_interface_sources_in_modules +
+ generated_interface_sources_for_testing_in_core +
+ generated_interface_sources_for_testing_in_modules
+ targets += [ "namespace" ]
+ outputs += generated_namespace_sources_in_core +
+ generated_namespace_sources_in_modules
+ if (use_blink_extensions_chromeos) {
+ outputs += generated_namespace_sources_in_extensions_chromeos
}
targets += [ "typedef" ]
outputs +=
@@ -256,8 +220,7 @@ action_with_pydeps("validate_web_idl") {
web_idl_database_outputs = get_target_outputs(":web_idl_database")
web_idl_database = web_idl_database_outputs[0]
idl_syntax_known_issues = "idl_syntax_known_issues.txt"
- validate_web_idl_result =
- "${bindings_output_dir}/validate_web_idl_results.txt"
+ validate_web_idl_result = "${bindings_gen_dir}/validate_web_idl_results.txt"
inputs = [
web_idl_database,
diff --git a/chromium/third_party/blink/renderer/bindings/IDLCompiler.md b/chromium/third_party/blink/renderer/bindings/IDLCompiler.md
index 9e5c43b5fc2..7b31b8e00f0 100644
--- a/chromium/third_party/blink/renderer/bindings/IDLCompiler.md
+++ b/chromium/third_party/blink/renderer/bindings/IDLCompiler.md
@@ -9,7 +9,7 @@ Users of the IDL compiler consist of:
* Other bindings generators (who want to compile Blink IDL files), which use the front end and optionally parts of the top-level compiler and build scripts.
* Other IDL use: Web IDL is a convenient format for specifying JavaScript interfaces, and the front end can be used for reading these files, most simply using the IR object (`IdlDefinitions`).
-The compiler is in [Source/bindings/scripts](https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/bindings/scripts/), and bindings are generated as part of the build (see [IDL build](https://sites.google.com/a/chromium.org/dev/developers/design-documents/idl-build)). The top-level file [idl_compiler.py](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/idl_compiler.py), can be invoked directly (if you want to compile a single file), or via [tools/run_bindings_tests.py](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/tools/run_bindings_tests.py). The rest of this document describes design, implementation, and use.
+The compiler is in [Source/bindings/scripts](https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/bindings/scripts/), and bindings are generated as part of the build (see [IDL build](https://sites.google.com/a/chromium.org/dev/developers/design-documents/idl-build)). The top-level file [idl_compiler.py](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/idl_compiler.py), can be invoked directly (if you want to compile a single file), or via [tools/run_bindings_tests.py](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/tools/run_bindings_tests.py). The rest of this document describes design, implementation, and use.
## Overall structure
The compiler is factored into a pipeline, and the steps further divided into separate Python modules. While there are a number of components, each is simple and well-defined, and generally only one or two must be considered at a time.
@@ -59,11 +59,11 @@ However, the back end ([code generator](http://en.wikipedia.org/wiki/Code_genera
Further, the input language is declarative (the 'D' in IDL), so no optimizations of input code are necessary (there is no _middle end_): it's just filling in a template. The back end is itself divided into the templates themselves, and the Python code that fills in the templates (produces the _context_). There is also no separate [_semantic analysis_](http://en.wikipedia.org/wiki/Semantic_analysis_(compilers)) step, except for validation of extended attributes (see below): the code generator assumes types are valid, and errors show up when the resulting C++ code fails to compile. This avoids the complexity and time cost of either a separate validation step, or of type-checking in the code generator, at the cost of typos showing up in compile failures instead of at IDL compile time. Notably, there is no type checking or name binding, since identifiers are assumed to refer to Web IDL interfaces (C++ classes) and the Web IDL namespace is global, and there is no assignment, since Web IDL is declarative.
## Code
-Code-wise, the top-level file [`idl_compiler.py`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/idl_compiler.py) imports two modules: [`idl_reader`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/idl_reader.py) for the front end, [`code_generator_v8`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/code_generator_v8.py) for the back end. Each of these is used to create an object (`IdlReader` and `CodeGeneratorV8`), which handles the library initialization (PLY or Jinja, which are slow, and thus reused if running multiple times during one run) and global information. The objects are then called one time each, for the IDL --> IR and IR --> C++ steps, respectively. By contrast, `run_bindings_tests.py` creates these objects as well, then calls them multiple times, once for each test file. Note that in the actual build, compilation is parallelized, which is why only one file is compiled per process, and there is a pre-caching step which significantly speeds up library initialization.
+Code-wise, the top-level file [`idl_compiler.py`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/idl_compiler.py) imports two modules: [`idl_reader`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/idl_reader.py) for the front end, [`code_generator_v8`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/code_generator_v8.py) for the back end. Each of these is used to create an object (`IdlReader` and `CodeGeneratorV8`), which handles the library initialization (PLY or Jinja, which are slow, and thus reused if running multiple times during one run) and global information. The objects are then called one time each, for the IDL --> IR and IR --> C++ steps, respectively. By contrast, `run_bindings_tests.py` creates these objects as well, then calls them multiple times, once for each test file. Note that in the actual build, compilation is parallelized, which is why only one file is compiled per process, and there is a pre-caching step which significantly speeds up library initialization.
The code is mostly functional, except for a few module-level variables in the code generator (discussed below) for simplicity, and some objects used for initialization.
-The main classes are as follows, with the module in which they are defined. Note that the relations are primarily composition, with inheritance significantly used for the Blink-specific lexer and parser. `IdlCompiler, IdlReader,` and `CodeGeneratorV8` are expected to be used as singletons, and are just classes for initialization (avoids expensive re-initialization, and interface-wise separates initialization from execution). `IdlDefinitions` contains objects of a few other classes (for more minor data), and there is a bit of complex OO code in [`idl_definitions`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/idl_definitions.py) to simplify [typedef](http://heycam.github.io/webidl/#idl-typedefs) resolution.
+The main classes are as follows, with the module in which they are defined. Note that the relations are primarily composition, with inheritance significantly used for the Blink-specific lexer and parser. `IdlCompiler, IdlReader,` and `CodeGeneratorV8` are expected to be used as singletons, and are just classes for initialization (avoids expensive re-initialization, and interface-wise separates initialization from execution). `IdlDefinitions` contains objects of a few other classes (for more minor data), and there is a bit of complex OO code in [`idl_definitions`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/idl_definitions.py) to simplify [typedef](http://heycam.github.io/webidl/#idl-typedefs) resolution.
```
IdlCompiler :: idl_compiler
@@ -91,15 +91,15 @@ There are two other steps:
* extended attribute validation
* dependency resolution
-The top-level module for the front end is [`idl_reader`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/idl_reader.py). This implements a class, `IdlReader`, whose constructor also constructs a lexer, parser, validator, and resolver. `IdlReader` implements a method to construct an IR object (`IdlDefinitions`) from an IDL filename. Thus to convert IDL to IR one instantiates a reader, then call its method to read an IDL file.
+The top-level module for the front end is [`idl_reader`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/idl_reader.py). This implements a class, `IdlReader`, whose constructor also constructs a lexer, parser, validator, and resolver. `IdlReader` implements a method to construct an IR object (`IdlDefinitions`) from an IDL filename. Thus to convert IDL to IR one instantiates a reader, then call its method to read an IDL file.
-The lexer-parser uses [PLY (Python Lex-Yacc)](http://www.dabeaz.com/ply/). In fact, the lexer and parser for the Blink IDL dialect of Web IDL derive from a base lexer and base parser for standard Web IDL (in [tools/idl_parser](https://code.google.com/p/chromium/codesearch#chromium/src/tools/idl_parser)), and thus only need to include deviations from the standard. The lexical syntax of Blink IDL is standard (though the base lexer is slightly non-standard), so the Blink IDL lexer is very small and slated for removal (Bug [345137](https://code.google.com/p/chromium/issues/detail?id=345137)). The phrase syntax is slightly non-standard (primarily in extended attributes) and expected to stay this way, as extended attributes are implementation-dependent and the deviations are useful (see [Blink IDL: syntax](http://www.chromium.org/blink/webidl#TOC-Syntax)). We thus say that the base lexer/parser + Blink lexer/parser form 1 lexer and 1.1 parser (base + derived).
+The lexer-parser uses [PLY (Python Lex-Yacc)](http://www.dabeaz.com/ply/). In fact, the lexer and parser for the Blink IDL dialect of Web IDL derive from a base lexer and base parser for standard Web IDL (in [tools/idl_parser](https://source.chromium.org/chromium/chromium/src/+/main:tools/idl_parser)), and thus only need to include deviations from the standard. The lexical syntax of Blink IDL is standard (though the base lexer is slightly non-standard), so the Blink IDL lexer is very small and slated for removal (Bug [345137](https://code.google.com/p/chromium/issues/detail?id=345137)). The phrase syntax is slightly non-standard (primarily in extended attributes) and expected to stay this way, as extended attributes are implementation-dependent and the deviations are useful (see [Blink IDL: syntax](http://www.chromium.org/blink/webidl#TOC-Syntax)). We thus say that the base lexer/parser + Blink lexer/parser form 1 lexer and 1.1 parser (base + derived).
-The base lexer class, defined in [`idl_lexer`](https://code.google.com/p/chromium/codesearch#chromium/src/tools/idl_parser/idl_lexer.py), is straightforward and short: it is just a list of regular expressions and keywords, wrapped in a class, `IDLLexer`; a lexer (object) itself is an instance of this class. There is some minor complexity with error handling (correct line count) and methods to assist with derived classes, but it's quite simple. The derived lexer class is very simple: it's a class, `BlinkIDLLexer`, which derives from the base class. The only complexity is adding a method to remove a token class from the base class, and to remove comments (base lexer is non-standard here: standard lexer does not produce `COMMENT` tokens).
+The base lexer class, defined in [`idl_lexer`](https://source.chromium.org/chromium/chromium/src/+/main:tools/idl_parser/idl_lexer.py), is straightforward and short: it is just a list of regular expressions and keywords, wrapped in a class, `IDLLexer`; a lexer (object) itself is an instance of this class. There is some minor complexity with error handling (correct line count) and methods to assist with derived classes, but it's quite simple. The derived lexer class is very simple: it's a class, `BlinkIDLLexer`, which derives from the base class. The only complexity is adding a method to remove a token class from the base class, and to remove comments (base lexer is non-standard here: standard lexer does not produce `COMMENT` tokens).
-The base parser class, defined in [`idl_parser`](https://code.google.com/p/chromium/codesearch#chromium/src/tools/idl_parser/idl_parser.py), is considerably longer, but consists almost entirely of production rules in (a form of) [BNF](http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form), together with yacc _actions_ that build an [abstract syntax tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST, syntax tree). Recall that yacc _traverses_ the [concrete syntax tree](http://en.wikipedia.org/wiki/Concrete_syntax_tree) (CST, parse tree) and can take whatever actions it chooses; in this case it generates an AST, though it could also generate the IR directly. See [`blink_idl_parser`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py) for a detailed explanation of the PLY yacc syntax and `IDLParser` methods used to construct the AST. The grammar is directly from the [Web IDL grammar](http://heycam.github.io/webidl/#idl-grammar), which is an [LL(1) grammar](http://en.wikipedia.org/wiki/LL_grammar); the Blink IDL rules are exactly the deviations from the standard grammar, or overrides to irregularities in the base parser. A parser object is an instance of a class, `IDLParser`, from which `BlinkIDLParser` is derived. The parser constructor takes a lexer as an argument, and one passes the corresponding lexer.
+The base parser class, defined in [`idl_parser`](https://source.chromium.org/chromium/chromium/src/+/main:tools/idl_parser/idl_parser.py), is considerably longer, but consists almost entirely of production rules in (a form of) [BNF](http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form), together with yacc _actions_ that build an [abstract syntax tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST, syntax tree). Recall that yacc _traverses_ the [concrete syntax tree](http://en.wikipedia.org/wiki/Concrete_syntax_tree) (CST, parse tree) and can take whatever actions it chooses; in this case it generates an AST, though it could also generate the IR directly. See [`blink_idl_parser`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/blink_idl_parser.py) for a detailed explanation of the PLY yacc syntax and `IDLParser` methods used to construct the AST. The grammar is directly from the [Web IDL grammar](http://heycam.github.io/webidl/#idl-grammar), which is an [LL(1) grammar](http://en.wikipedia.org/wiki/LL_grammar); the Blink IDL rules are exactly the deviations from the standard grammar, or overrides to irregularities in the base parser. A parser object is an instance of a class, `IDLParser`, from which `BlinkIDLParser` is derived. The parser constructor takes a lexer as an argument, and one passes the corresponding lexer.
-The definitions classes, defined in [idl_definitions](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/idl_definitions.py), primarily consist of constructors, which take the AST and generate an intermediate representation (IR), in this case an object of type `IdlDefinitions` and contained objects for individual definitions and definition's members.
+The definitions classes, defined in [idl_definitions](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/idl_definitions.py), primarily consist of constructors, which take the AST and generate an intermediate representation (IR), in this case an object of type `IdlDefinitions` and contained objects for individual definitions and definition's members.
The classes are as follows (mostly composition, one case of inheritance); a few internal-use only classes are not shown:
@@ -120,7 +120,7 @@ After reading an IDL file (producing an IR), the reader has two optional additio
### Extended attribute validation
The front end largely does not do [semantic analysis](http://en.wikipedia.org/wiki/Semantic_analysis_%28compilers%29), as semantic errors (primarily name errors) are largely caught by the build visibly failing, either during the IDL compile or during the C++ compile (name lookup errors). Notably, there is no symbol table or name binding in the front end: each name is simply looked up on use (e.g., type names), or passed through to the output (e.g., attribute names), and catch errors by the lookup failing or the generated code failing to compile, respectively.
-However, extended attributes are validated, both the keys and values, based on the list in [`IDLExtendedAttributes.txt`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt). This is done because invalid extended attributes are _ignored_ by the compiler, specifically the code generator, and thus errors are easy to miss. The Python code checks for specific extended attributes, so errors just result in the attribute not being found; for example, writing `[EnforecRange]` for `[EnforceRange]` would otherwise silently result in the range not being enforced. This is not perfect: extended attributes may be valid but used incorrectly (e.g., specified on an attribute when they only apply to methods), which is not caught; this is however a minor problem.
+However, extended attributes are validated, both the keys and values, based on the list in [`IDLExtendedAttributes.txt`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/IDLExtendedAttributes.txt). This is done because invalid extended attributes are _ignored_ by the compiler, specifically the code generator, and thus errors are easy to miss. The Python code checks for specific extended attributes, so errors just result in the attribute not being found; for example, writing `[EnforecRange]` for `[EnforceRange]` would otherwise silently result in the range not being enforced. This is not perfect: extended attributes may be valid but used incorrectly (e.g., specified on an attribute when they only apply to methods), which is not caught; this is however a minor problem.
This is done in the front end since that is the proper place for semantic analysis, and simplifies the code generator.
@@ -141,7 +141,7 @@ The subtleties are:
Also, note that the compiler currently does not do significant type introspection of referenced interfaces: it mostly just uses certain global information about the interface (is it a callback interface?, `[ImplementedAs],` etc.). The only significant use of type introspection is in `[PutForwards],` where generating the code for an attribute with `[PutForwards]` requires looking up the referenced attribute in another interface. Type introspection may increase in future, to simplify complex cases and reduce hard-coding, but for now is in very limited use.</div>
## Back end (code generator)
-The back end (code generator, CG) is where the bulk of the complexity is. The structure is simple: the Python V8 CG modules (`v8_*`) generate a dictionary called the **context**, which is passed to Jinja, which uses this dict to fill in the appropriate templates ([bindings/templates](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/templates/)/*.{cpp,h}). The modules correspond to the class structure in IR, with the following exceptions:
+The back end (code generator, CG) is where the bulk of the complexity is. The structure is simple: the Python V8 CG modules (`v8_*`) generate a dictionary called the **context**, which is passed to Jinja, which uses this dict to fill in the appropriate templates ([bindings/templates](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/templates/)/*.{cpp,h}). The modules correspond to the class structure in IR, with the following exceptions:
* the CG uses “method” where the front end uses “operation” (the term in the spec), since “method” is a more standard term;
* constants are included in `v8_interface`, because very simple; and
* arguments are included in `v8_methods`, because they are closely related to methods.
@@ -162,15 +162,15 @@ IdlInterface :: v8_interface
```
The CG modules each have a top-level `*_context` function_,_ which takes an IR object (`Idl*`) as a parameter and returns a context (`dict`), looping through contained IR objects as necessary.
-Note that the context is nested – the context for an interfaces contains a list of contexts for the members: attributes, constants, and methods. The context for a given member is used throughout the corresponding template, generally to generate several methods; e.g., in `attributes.cpp` there are macros for getter, getter callback, setter, and setter callback, which are called from a loop in `interface_base.cpp`. The context for members is _also_ used at the overall interface level, notably for DOM configuration.
+Note that the context is nested – the context for an interfaces contains a list of contexts for the members: attributes, constants, and methods. The context for a given member is used throughout the corresponding template, generally to generate several methods; e.g., in `attributes.cc.tmpl` there are macros for getter, getter callback, setter, and setter callback, which are called from a loop in `interface_base.cpp`. The context for members is _also_ used at the overall interface level, notably for DOM configuration.
## Style
-[`v8_attributes.py`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/v8_attributes.py) (Python) and [`attributes.cpp`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/templates/attributes.cpp) (Jinja) are a good guide to style: the getter and setter methods themselves are quite complex, while the callbacks are simple.
+[`v8_attributes.py`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/v8_attributes.py) (Python) and [`attributes.cc.tmpl`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/templates/attributes.cc.tmpl) (Jinja) are a good guide to style: the getter and setter methods themselves are quite complex, while the callbacks are simple.
See [Jinja: Style](https://sites.google.com/a/chromium.org/dev/developers/jinja#TOC-Style) for general Jinja style tips; below is bindings generator specific guidance.
### Jinja
-If nesting macros (so macros that call macros), use top-down order: top-level macro, followed by macros it calls. This is most notable in [`methods.cpp`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/templates/methods.cpp), where generating a method also requires generating code for the arguments, which comes after.
+If nesting macros (so macros that call macros), use top-down order: top-level macro, followed by macros it calls. This is most notable in [`methods.cc.tmpl`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/templates/methods.cc.tmpl), where generating a method also requires generating code for the arguments, which comes after.
### Python
Assertions should _not_ be used for validating input, and this includes IDL files: if an IDL file is invalid (e.g., it uses an extended attribute improperly), raise an exception explicitly. Assertions can be used for validating internal logic, but in practice this is rare in the code generator; see [Using Assertions Effectively](https://wiki.python.org/moin/UsingAssertionsEffectively).
@@ -266,7 +266,7 @@ Potential future improvements (without substantial reengineering) would primaril
* [Jinja performance](http://www.chromium.org/developers/jinja#TOC-Performance)
## References
-* [Source/bindings/scripts](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/): the code
+* [Source/bindings/scripts](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/): the code
* [Issue <strike>239771</strike>: Rewrite the IDL compiler in Python](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/s1xTE428OAs): tracking bug for rewrite (2013/2014)
* [IDL compiler (V8 bindings generator) switched to Python](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/s1xTE428OAs): wrap-up email for rewrite (Feb 2014)
* [followup](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/5FSUhiugWsE) about front end
diff --git a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
index a2265deef88..b7766679f79 100644
--- a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
+++ b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -6,7 +6,7 @@
The main interest in extended attributes are their _semantics_: Blink implements many more extended attributes than the Web IDL standard, to specify various behavior.
-The authoritative list of allowed extended attributes and values is [bindings/IDLExtendedAttributes.txt](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt). This is complete but not necessarily precise (there may be unused extended attributes or values), since validation is run on build, but coverage isn't checked.
+The authoritative list of allowed extended attributes and values is [bindings/IDLExtendedAttributes.txt](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/IDLExtendedAttributes.txt). This is complete but not necessarily precise (there may be unused extended attributes or values), since validation is run on build, but coverage isn't checked.
Syntactically, Blink IDL extended attributes differ from standard Web IDL extended attributes in a few ways:
@@ -59,7 +59,7 @@ Extended attributes mostly work normally on overloaded methods, affecting only t
While `[DeprecateAs]`, `[MeasureAs]` only affect callback for non-overloaded methods, the logging code is instead put in the method itself for overloaded methods, so these can be placed on the method to log in question.
***
-Extended attributes that affect the callback must be on the _last_ overloaded method, though it is safest to put them on all the overloaded methods, for consistency (and in case they are rearranged or deleted). The source is [bindings/templates/methods.cpp](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/templates/methods.cpp), and currently there are no extended attribute that affect the callback (even for overloaded methods).
+Extended attributes that affect the callback must be on the _last_ overloaded method, though it is safest to put them on all the overloaded methods, for consistency (and in case they are rearranged or deleted). The source is [bindings/templates/methods.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/templates/methods.cpp), and currently there are no extended attribute that affect the callback (even for overloaded methods).
### Special operations (methods)
@@ -126,7 +126,7 @@ Extended attributes on members of an interface mixin work as normal. However, on
### Inheritance
-Extended attributes are generally not inherited: only extended attributes on the interface itself are consulted. However, there are a handful of extended attributes that are inherited (applying them to an ancestor interface applies them to the descendants). These are extended attributes that affect memory management, and currently consists of `[ActiveScriptWrappable]`; the up-to-date list is [compute_dependencies.INHERITED_EXTENDED_ATTRIBUTES](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/bindings/scripts/compute_dependencies.py&q=INHERITED_EXTENDED_ATTRIBUTES).
+Extended attributes are generally not inherited: only extended attributes on the interface itself are consulted. However, there are a handful of extended attributes that are inherited (applying them to an ancestor interface applies them to the descendants). These are extended attributes that affect memory management, and currently consists of `[ActiveScriptWrappable]`; the up-to-date list is [compute_dependencies.INHERITED_EXTENDED_ATTRIBUTES](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py?q=INHERITED_EXTENDED_ATTRIBUTES&ss=chromium).
## Standard Web IDL Extended Attributes
@@ -221,7 +221,7 @@ Currently `[Constructor(...)]` does not yet support optional arguments w/o defau
Standard: [CrossOriginIsolated](https://heycam.github.io/webidl/#CrossOriginIsolated)
-Summary: Interfaces and interface members with a `CrossOriginIsolated` attribute are exposed only inside contexts whose [cross-origin isolated capability](https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-cross-origin-isolated-capability) is enabled.
+Summary: Interfaces and interface members with a `CrossOriginIsolated` attribute are exposed only inside contexts whose [cross-origin isolated capability](https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-cross-origin-isolated-capability) is enabled.
Usage: The `[CrossOriginIsolated]` attribute may be specified on interfaces, attributes, and members:
@@ -977,7 +977,7 @@ v8::Local<v8::Value> V8XXX::CallAsFunctionCallback(const v8::Arguments& args) {
Summary: Denotes an API that exposes data that folks on the internet find useful for fingerprinting.
Attributes and methods marked as `[HighEntropy]` are known to be practically useful for [identifying particular clients](https://dev.chromium.org/Home/chromium-security/client-identification-mechanisms) on the web today.
-Both methods and attribute/constant getters annotated with this attribute are wired up to [`Dactyloscoper::Record`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/core/frame/dactyloscoper.cc&q=Dactyloscoper::Record) for additional processing.
+Both methods and attribute/constant getters annotated with this attribute are wired up to [`Dactyloscoper::Record`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/frame/dactyloscoper.cc&q=Dactyloscoper::Record) for additional processing.
This attribute must be accompanied by either `[Measure]` or `[MeasureAs]`.
@@ -1251,7 +1251,7 @@ Non-empty string values specified by `[ReflectOnly]` must be added to
Summary: `[RuntimeEnabled]` wraps the generated code with `if (RuntimeEnabledFeatures::FeatureNameEnabled) { ...code... }`.
-Usage: `[RuntimeEnabled=FeatureName]`. FeatureName must be included in [runtime\_enabled\_features.json5](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5).
+Usage: `[RuntimeEnabled=FeatureName]`. FeatureName must be included in [runtime\_enabled\_features.json5](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5).
```webidl
[
@@ -1267,7 +1267,7 @@ foo(long x);
[RuntimeEnabled=FeatureName] foo(long x, long y);
```
-For more information, see [RuntimeEnabledFeatures](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5).
+For more information, see [RuntimeEnabledFeatures](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5).
### [SaveSameObject] _(a)_
@@ -1585,24 +1585,24 @@ V8PrivateProperty::GetHTMLFooBarCachedAccessor().Set(context, object, new_value)
### [Affects] _(m, a)_
-Summary: `[Affects=Nothing]` indicates that a function must not produce JS-observable side effects. Functions without this attribute are never invoked by V8 with throwOnSideEffect.
+Summary: `[Affects=Nothing]` indicates that a function must not produce JS-observable side effects, while `[Affects=Everything]` indicates that a function may produce JS-observable side effects. Functions which are not considered free of JS-observable side effects will never be invoked by V8 with throwOnSideEffect.
-Marked functions are allowed to be nondeterministic, throw exceptions, force layout, and recalculate style, but must not set values, cache objects, or schedule execution that will be observable after the function completes. If a marked function calls into V8, it must properly handle cases when the V8 call returns an MaybeHandle.
-
-All DOM constructors are assumed to have side effects. However, an exception can be explicitly indicated when calling constructors using the V8 API method Function::NewInstanceWithSideEffectType().
-
-There is not yet support for marking SymbolKeyedMethodConfigurations as side-effect free. This requires additional support in V8 to allow Intrinsics.
-
-Usage for attributes and operations: `[Affects=Nothing]` can be specified on an operation, or on an attribute to indicate that its getter callback is side effect free:
+Usage for attributes and operations: `[Affects=Nothing]` and `[Affects=Everything]` can be specified on an operation, or on an attribute to indicate that its getter callback is side effect free or side effecting:
```webidl
interface HTMLFoo {
- [Affects=Nothing] attribute Bar bar;
+ [Affects=Everything] attribute Bar bar;
[Affects=Nothing] Bar baz();
void removeItems();
};
```
+When neither `[Affects=Nothing]` nor `[Affects=Everything]` is specified, the default for operations is `[Affects=Everything]`, while for attributes it's `[Affects=Nothing]`. Functions marked as side effect free are allowed to be nondeterministic, throw exceptions, force layout, and recalculate style, but must not set values, cache objects, or schedule execution that will be observable after the function completes. If a marked function calls into V8, it must properly handle cases when the V8 call returns an MaybeHandle.
+
+All DOM constructors are assumed to side effects. However, an exception can be explicitly indicated when calling constructors using the V8 API method Function::NewInstanceWithSideEffectType().
+
+There is not yet support for marking SymbolKeyedMethodConfigurations as side-effect free. This requires additional support in V8 to allow Intrinsics.
+
### [DefaultValue] _(p)_
diff --git a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
index ea35e717c76..77dda7d021e 100644
--- a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
+++ b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
@@ -32,7 +32,7 @@
#
ActiveScriptWrappable
-Affects=Nothing
+Affects=Everything|Nothing
AllowShared
CEReactions
CSSProperty
diff --git a/chromium/third_party/blink/renderer/bindings/OWNERS b/chromium/third_party/blink/renderer/bindings/OWNERS
index c86b5f21f29..5e4e3adc924 100644
--- a/chromium/third_party/blink/renderer/bindings/OWNERS
+++ b/chromium/third_party/blink/renderer/bindings/OWNERS
@@ -2,14 +2,10 @@ bashi@chromium.org
haraken@chromium.org
japhet@chromium.org
jbroman@chromium.org
-jl@opera.com
jochen@chromium.org
kouhei@chromium.org
-marja@chromium.org
mkwst@chromium.org
mlippautz@chromium.org
-peria@chromium.org
-pfeldman@chromium.org
vivekg@chromium.org
yhirano@chromium.org
yukishiino@chromium.org
diff --git a/chromium/third_party/blink/renderer/bindings/PRESUBMIT.py b/chromium/third_party/blink/renderer/bindings/PRESUBMIT.py
index 2d690d1e135..5e353465192 100644
--- a/chromium/third_party/blink/renderer/bindings/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/bindings/PRESUBMIT.py
@@ -31,6 +31,9 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""
+USE_PYTHON3 = True
+
+
def _RunBindingsTests(input_api, output_api):
# Make sure binding templates are considered as source files.
FILES_TO_CHECK = (r'.+\.tmpl$', )
@@ -60,8 +63,6 @@ def _RunBindingsTests(input_api, output_api):
cmd = [input_api.python_executable, run_bindings_tests_path]
else:
cmd = [run_bindings_tests_path]
- if not input_api.verbose:
- cmd.append('--suppress-diff')
test_cmd = input_api.Command(
name=cmd_name, cmd=cmd, kwargs={}, message=message_type)
if input_api.verbose:
diff --git a/chromium/third_party/blink/renderer/bindings/bindings.gni b/chromium/third_party/blink/renderer/bindings/bindings.gni
index e489311a2cf..0964a077da7 100644
--- a/chromium/third_party/blink/renderer/bindings/bindings.gni
+++ b/chromium/third_party/blink/renderer/bindings/bindings.gni
@@ -2,12 +2,14 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# All paths in this file should be absolute so it can be imported into
-# different contexts.
+# The database file produced by
+# "//third_party/blink/renderer/bindings:web_idl_database".
+web_idl_database_filepath =
+ get_path_info(".", "gen_dir") + "/web_idl_database.pickle"
-import("//third_party/blink/renderer/bindings/modules/v8/v8.gni")
-
-bindings_core_v8_files =
+# Source files to be part of
+# "//third_party/blink/renderer/core:core".
+blink_core_sources_bindings =
get_path_info([
"core/v8/active_script_wrappable.cc",
"core/v8/active_script_wrappable.h",
@@ -57,6 +59,7 @@ bindings_core_v8_files =
"core/v8/module_request.cc",
"core/v8/module_request.h",
"core/v8/native_value_traits.h",
+ "core/v8/native_value_traits_buffer_sources.cc",
"core/v8/native_value_traits_impl.cc",
"core/v8/native_value_traits_impl.h",
"core/v8/profiler_trace_builder.cc",
@@ -127,8 +130,6 @@ bindings_core_v8_files =
"core/v8/v8_code_cache.h",
"core/v8/v8_context_snapshot.cc",
"core/v8/v8_context_snapshot.h",
- "core/v8/v8_dom_configuration.cc",
- "core/v8/v8_dom_configuration.h",
"core/v8/v8_embedder_graph_builder.cc",
"core/v8/v8_embedder_graph_builder.h",
"core/v8/v8_event_listener_info.h",
@@ -172,14 +173,29 @@ bindings_core_v8_files =
],
"abspath")
-bindings_dir = get_path_info(".", "abspath")
-blink_output_dir = "$root_gen_dir/third_party/blink/renderer"
-bindings_output_dir = "$root_gen_dir/third_party/blink/renderer/bindings"
-bindings_core_v8_output_dir = "$bindings_output_dir/core/v8"
-web_idl_database_filepath = "${bindings_output_dir}/web_idl_database.pickle"
+# Source files to be part of
+# "//third_party/blink/renderer/modules:modules".
+blink_modules_sources_bindings = get_path_info(
+ [
+ "modules/v8/module_bindings_initializer.cc",
+ "modules/v8/module_bindings_initializer.h",
+ "modules/v8/serialization/serialized_script_value_for_modules_factory.cc",
+ "modules/v8/serialization/serialized_script_value_for_modules_factory.h",
+ "modules/v8/serialization/v8_script_value_deserializer_for_modules.cc",
+ "modules/v8/serialization/v8_script_value_deserializer_for_modules.h",
+ "modules/v8/serialization/v8_script_value_serializer_for_modules.cc",
+ "modules/v8/serialization/v8_script_value_serializer_for_modules.h",
+ "modules/v8/to_v8_for_modules.h",
+ "modules/v8/v8_binding_for_modules.cc",
+ "modules/v8/v8_binding_for_modules.h",
+ "modules/v8/v8_context_snapshot_impl.cc",
+ "modules/v8/v8_context_snapshot_impl.h",
+ "modules/v8/webgl_any.cc",
+ "modules/v8/webgl_any.h",
+ ],
+ "abspath")
-bindings_unittest_files =
- get_path_info(
+bindings_unittest_files = get_path_info(
[
"core/v8/activity_logger_test.cc",
"core/v8/binding_security_test.cc",
@@ -213,6 +229,7 @@ bindings_unittest_files =
"core/v8/v8_extras_test_utils.h",
"core/v8/script_promise_tester.cc",
"core/v8/script_promise_tester.h",
+ "modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc",
+ "modules/v8/v8_binding_for_modules_test.cc",
],
"abspath")
-bindings_unittest_files += bindings_modules_v8_unittest_files
diff --git a/chromium/third_party/blink/renderer/bindings/core/BUILD.gn b/chromium/third_party/blink/renderer/bindings/core/BUILD.gn
deleted file mode 100644
index 5d32b250560..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/BUILD.gn
+++ /dev/null
@@ -1,49 +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.
-
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
-import("//third_party/blink/renderer/core/core_idl_files.gni")
-
-visibility = [ "//third_party/blink/*" ]
-
-compute_interfaces_info("interfaces_info_core") {
- sources =
- core_static_interface_idl_files + core_static_dependency_idl_files +
- core_generated_interface_idl_files + core_generated_dependency_idl_files
- interfaces_info_file = "$bindings_core_output_dir/interfaces_info_core.pickle"
- component_info_file = "$bindings_core_output_dir/component_info_core.pickle"
- deps = [
- "//third_party/blink/renderer/bindings/core:core_global_constructors_idls",
- "//third_party/blink/renderer/core:generated_testing_idls_internal_runtime_flags",
- "//third_party/blink/renderer/core:generated_testing_idls_settings",
- ]
-}
-
-compute_global_objects("core_global_objects") {
- sources =
- core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent +
- core_buffer_source_type_idl_files + core_callback_interface_idl_files
- sources_generated = []
- output_file = "$bindings_core_output_dir/global_objects_core.pickle"
- deps = []
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("core_global_constructors_idls") {
- }
-} else {
- generate_global_constructors("core_global_constructors_idls") {
- sources =
- core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent +
- core_buffer_source_type_idl_files + core_callback_interface_idl_files
- global_objects_file = "$bindings_core_output_dir/global_objects_core.pickle"
- interfaces = core_global_constructors_original_interfaces
- basenames = core_global_constructors_original_interface_basenames
- component = "core"
- output_dir = blink_core_output_dir
- deps = [ ":core_global_objects" ]
- }
-}
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 2c1fd29632e..ae814bb8824 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -3,12 +3,8 @@
# found in the LICENSE file.
import("//testing/libfuzzer/fuzzer_test.gni")
-import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/core/v8/generated.gni")
import("//third_party/blink/renderer/bindings/generated_in_core.gni")
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
import("//third_party/blink/renderer/core/core.gni")
-import("//third_party/blink/renderer/core/core_idl_files.gni")
visibility = [ "//third_party/blink/renderer/*" ]
@@ -16,22 +12,13 @@ blink_core_sources("v8") {
visibility = []
visibility = [ "//third_party/blink/renderer/core" ]
- sources = generated_enumeration_sources_in_core
- if (use_blink_v8_binding_new_idl_callback_function) {
- sources += generated_callback_function_sources_in_core
- }
- if (use_blink_v8_binding_new_idl_callback_interface) {
- sources += generated_callback_interface_sources_in_core
- }
- if (use_blink_v8_binding_new_idl_dictionary) {
- sources += generated_dictionary_sources_in_core
- }
- if (use_blink_v8_binding_new_idl_interface) {
- sources += generated_interface_sources_in_core +
- generated_namespace_sources_in_core
- }
- sources += generated_typedef_sources_in_core
- sources += generated_union_sources_in_core
+ sources = generated_callback_function_sources_in_core +
+ generated_callback_interface_sources_in_core +
+ generated_dictionary_sources_in_core +
+ generated_enumeration_sources_in_core +
+ generated_interface_sources_in_core +
+ generated_namespace_sources_in_core +
+ generated_typedef_sources_in_core + generated_union_sources_in_core
deps = [
":generated",
@@ -51,21 +38,14 @@ source_set("testing") {
"//third_party/blink/renderer:inside_blink",
]
- sources = generated_enumeration_sources_for_testing_in_core
- if (use_blink_v8_binding_new_idl_callback_function) {
- sources += generated_callback_function_sources_for_testing_in_core
- }
- if (use_blink_v8_binding_new_idl_dictionary) {
- sources += generated_dictionary_sources_for_testing_in_core
- }
- if (use_blink_v8_binding_new_idl_interface) {
- sources += generated_interface_sources_for_testing_in_core
- }
- sources += generated_union_sources_for_testing_in_core
+ sources = generated_callback_function_sources_for_testing_in_core +
+ generated_dictionary_sources_for_testing_in_core +
+ generated_enumeration_sources_for_testing_in_core +
+ generated_interface_sources_for_testing_in_core +
+ generated_union_sources_for_testing_in_core
deps = [
":generated",
- ":testing_internal",
"//third_party/blink/renderer/core",
"//third_party/blink/renderer/platform",
"//v8",
@@ -79,160 +59,8 @@ group("generated") {
"//third_party/blink/renderer/core/*",
]
- public_deps = [
- ":bindings_core_v8_generated",
- "//third_party/blink/renderer/bindings:generate_bindings_all",
- ]
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("bindings_core_origin_trial_features") {
- }
-} else {
- generate_origin_trial_features("bindings_core_origin_trial_features") {
- sources = core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent +
- core_partial_definition_idl_files +
- core_global_constructors_generated_idl_files
- component = "core"
- output_dir = bindings_core_output_dir + "/v8"
- deps = [
- "//third_party/blink/renderer/bindings/core:core_global_constructors_idls",
- "//third_party/blink/renderer/bindings/core:interfaces_info_core",
- ]
- }
-}
-
-group("bindings_core_v8_generated") {
- public_deps = [ ":bindings_core_impl_generated" ]
- if (is_win && is_official_build) {
- public_deps += [ ":generate_bindings_core_v8_all_interfaces" ]
- } else {
- public_deps += [ ":generate_bindings_core_v8_interfaces" ]
- }
-}
-
-# IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces
-# Interface IDL files: generate individual bindings (includes testing)
-idl_compiler("generate_bindings_core_v8_interfaces") {
- sources = core_definition_idl_files + core_testing_definition_idl_files +
- generated_webcore_testing_idl_files
- if (use_blink_v8_binding_new_idl_callback_interface) {
- sources -= core_callback_interface_idl_files
- }
- if (use_blink_v8_binding_new_idl_dictionary) {
- sources -= core_dictionary_idl_files
- sources -= core_testing_dictionary_idl_files
- }
- if (use_blink_v8_binding_new_idl_interface) {
- sources -=
- core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent + webcore_testing_idl_files +
- webcore_testing_idl_with_modules_dependency_files +
- generated_webcore_testing_idl_files
- }
- output_dir = bindings_core_v8_output_dir
- output_name_suffix = ""
- target_component = "core"
-}
-
-aggregate_generated_bindings("generate_bindings_core_v8_all_interfaces") {
- sources =
- core_buffer_source_type_idl_files + core_callback_interface_idl_files
- if (!use_blink_v8_binding_new_idl_dictionary) {
- sources += core_dictionary_idl_files
- }
- if (!use_blink_v8_binding_new_idl_interface) {
- sources += core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent
- }
-
- outputs = [ "$bindings_core_v8_output_dir/v8_generated_core_bindings.cc" ]
- component = "core"
- public_deps = [ ":generate_bindings_core_v8_interfaces" ]
-}
-
-idl_impl("bindings_core_impl_generated") {
- if (use_blink_v8_binding_new_idl_dictionary) {
- dict_idls = []
- } else {
- dict_idls = core_dictionary_idl_files + core_testing_dictionary_idl_files
- }
- non_dict_outputs = bindings_core_generated_union_type_files
- if (!use_blink_v8_binding_new_idl_callback_function) {
- non_dict_outputs += generated_core_testing_callback_function_files +
- generated_core_callback_function_files
- }
- non_dict_output_dir = bindings_core_v8_output_dir
- target_component = "core"
-}
-
-# Compile the non-test sources generated above.
-blink_core_sources("bindings_core_impl") {
- sources = get_target_outputs(":bindings_core_impl_generated") +
- bindings_core_generated_interface_files
-
- if (!use_blink_v8_binding_new_idl_callback_function) {
- sources -= generated_core_testing_callback_function_files
- }
- if (!use_blink_v8_binding_new_idl_dictionary) {
- sources -= generated_core_testing_dictionary_files
- }
- if (!use_blink_v8_binding_new_idl_interface) {
- sources += get_target_outputs(":bindings_core_origin_trial_features")
- }
-
- deps = [
- ":bindings_core_impl_generated",
- ":bindings_core_origin_trial_features",
- ":bindings_core_v8_generated",
- ":generated",
- ]
-}
-
-# Compile the test sources generated above. This test target doesn't count
-# as part of the "core" component so shouldn't use the blink_core_sources for
-# linking on Windows.
-source_set("testing_internal") {
- testonly = true
-
- sources = []
- if (!use_blink_v8_binding_new_idl_callback_function) {
- sources += generated_core_testing_callback_function_files
- }
- if (!use_blink_v8_binding_new_idl_dictionary) {
- sources += generated_core_testing_dictionary_files
- }
-
- idl_files = []
- if (!use_blink_v8_binding_new_idl_dictionary) {
- idl_files += core_testing_dictionary_idl_files
- }
- if (!use_blink_v8_binding_new_idl_interface) {
- idl_files +=
- webcore_testing_idl_files + generated_webcore_testing_idl_files +
- webcore_testing_idl_with_modules_dependency_files
- }
- sources += process_file_template(
- idl_files,
- [
- "$bindings_core_v8_output_dir/v8_{{source_name_part}}.cc",
- "$bindings_core_v8_output_dir/v8_{{source_name_part}}.h",
- ])
-
- configs -= core_config_remove
- configs += core_config_add + [ "//third_party/blink/renderer:inside_blink" ] -
- [ "//third_party/blink/renderer/core:config" ]
-
- deps = [
- ":bindings_core_impl_generated",
- ":bindings_core_v8_generated",
- ":generated",
- "//skia",
- "//third_party/blink/renderer/core",
- "//third_party/blink/renderer/platform",
- "//v8",
- ]
+ public_deps =
+ [ "//third_party/blink/renderer/bindings:generate_bindings_all" ]
}
fuzzer_test("v8_serialized_script_value_fuzzer") {
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 c01fdeb4fa7..f1fc2afdfac 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
@@ -486,9 +486,7 @@ void BindingSecurity::FailedAccessCheckFor(v8::Isolate* isolate,
auto* local_dom_window = CurrentDOMWindow(isolate);
// Determine if the access check failure was because of cross-origin or if the
// WindowAgentFactory is different. If the WindowAgentFactories are different
- // it indicates that the "disallowdocumentaccess" attribute was used on an
- // iframe somewhere in the ancestor chain so report the error as "restricted"
- // instead of "cross-origin".
+ // so report the error as "restricted" instead of "cross-origin".
DOMWindow::CrossDocumentAccessPolicy cross_document_access =
(!target->ToLocalDOMWindow() ||
IsSameWindowAgentFactory(local_dom_window, target->ToLocalDOMWindow()))
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h b/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h
index 52e3d6d46a2..c071dcde406 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h
@@ -25,19 +25,13 @@ class CORE_EXPORT BoxedV8Module final : public GarbageCollected<BoxedV8Module> {
: record_(isolate, module),
identity_hash_(static_cast<unsigned>(module->GetIdentityHash())) {}
- void Trace(Visitor* visitor) const {
- // TODO(keishi): Remove UnsafeCast.
- visitor->Trace(record_.UnsafeCast<v8::Value>());
- }
+ void Trace(Visitor* visitor) const { visitor->Trace(record_); }
v8::Local<v8::Module> NewLocal(v8::Isolate* isolate) const {
return record_.NewLocal(isolate);
}
private:
- // TODO(keishi): Visitor only defines a trace method for v8::Value so this
- // needs to be cast.
- GC_PLUGIN_IGNORE("757708")
TraceWrapperV8Reference<v8::Module> record_;
const unsigned identity_hash_;
friend struct BoxedV8ModuleHash;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module_test.cc
index a08b2d354fe..5b4b91c29dc 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module_test.cc
@@ -27,11 +27,11 @@ TEST(BoxedV8ModuleTest, equalAndHash) {
Member<BoxedV8Module> module_deleted(kMemberDeletedValue);
v8::Local<v8::Module> local_module_a = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const a = 'a';", js_url_a);
+ scope.GetScriptState(), "export const a = 'a';", js_url_a);
Member<BoxedV8Module> module_a =
MakeGarbageCollected<BoxedV8Module>(scope.GetIsolate(), local_module_a);
v8::Local<v8::Module> local_module_b = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const b = 'b';", js_url_b);
+ scope.GetScriptState(), "export const b = 'b';", js_url_b);
Member<BoxedV8Module> module_b =
MakeGarbageCollected<BoxedV8Module>(scope.GetIsolate(), local_module_b);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc b/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
index 1cd701bcada..6f869fd1a38 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
@@ -37,17 +37,16 @@ inline bool IsCallbackObjectCallable(CallbackInterfaceBase* callback) {
template <class CallbackBase, CallbackInvokeHelperMode mode>
bool CallbackInvokeHelper<CallbackBase, mode>::PrepareForCall(
V8ValueOrScriptWrappableAdapter callback_this) {
+ v8::Isolate* isolate = callback_->GetIsolate();
if (UNLIKELY(ScriptForbiddenScope::IsScriptForbidden())) {
- ScriptForbiddenScope::ThrowScriptForbiddenException(
- callback_->GetIsolate());
+ ScriptForbiddenScope::ThrowScriptForbiddenException(isolate);
return Abort();
}
if (mode == CallbackInvokeHelperMode::kConstructorCall) {
// step 3. If ! IsConstructor(F) is false, throw a TypeError exception.
if (!IsCallbackConstructor(callback_)) {
- ExceptionState exception_state(callback_->GetIsolate(),
- ExceptionState::kExecutionContext,
+ ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
class_like_name_, property_name_);
exception_state.ThrowTypeError(
"The provided callback is not a constructor.");
@@ -61,7 +60,7 @@ bool CallbackInvokeHelper<CallbackBase, mode>::PrepareForCall(
if (!callback_->CallbackObject()->IsFunction()) {
// step 4.2. Return the result of converting undefined to the callback
// function's return type.
- result_ = v8::Undefined(callback_->GetIsolate());
+ result_ = v8::Undefined(isolate);
return false;
}
}
@@ -75,23 +74,21 @@ bool CallbackInvokeHelper<CallbackBase, mode>::PrepareForCall(
// step 10. If ! IsCallable(O) is false, then:
v8::MicrotaskQueue* microtask_queue =
ToMicrotaskQueue(callback_->CallbackRelevantScriptState());
- v8::MicrotasksScope microtasks_scope(callback_->GetIsolate(),
- microtask_queue,
+ v8::MicrotasksScope microtasks_scope(isolate, microtask_queue,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Value> value;
if (!callback_->CallbackObject()
->Get(callback_->CallbackRelevantScriptState()->GetContext(),
- V8String(callback_->GetIsolate(), property_name_))
+ V8String(isolate, property_name_))
.ToLocal(&value)) {
return Abort();
}
if (!value->IsFunction()) {
V8ThrowException::ThrowTypeError(
- callback_->GetIsolate(),
- ExceptionMessages::FailedToExecute(
- property_name_, class_like_name_,
- "The provided callback is not callable."));
+ isolate, ExceptionMessages::FailedToExecute(
+ property_name_, class_like_name_,
+ "The provided callback is not callable."));
return Abort();
}
function_ = value.As<v8::Function>();
@@ -106,7 +103,7 @@ bool CallbackInvokeHelper<CallbackBase, mode>::PrepareForCall(
callback_this_ = callback_->CallbackObject();
} else if (callback_this.IsEmpty()) {
// step 2. If thisArg was not given, let thisArg be undefined.
- callback_this_ = v8::Undefined(callback_->GetIsolate());
+ callback_this_ = v8::Undefined(isolate);
} else {
callback_this_ =
callback_this.V8Value(callback_->CallbackRelevantScriptState());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.h b/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.h
index c499eda79ee..2e580c46a5b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.h
@@ -68,11 +68,11 @@ class CallbackInvokeHelper final {
template <typename IDLReturnType, typename ReturnType>
v8::Maybe<ReturnType> Result() {
DCHECK(!aborted_);
- ExceptionState exception_state(callback_->GetIsolate(),
- ExceptionState::kExecutionContext,
+ v8::Isolate* isolate = callback_->GetIsolate();
+ ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
class_like_name_, property_name_);
auto&& result = NativeValueTraits<IDLReturnType>::NativeValue(
- callback_->GetIsolate(), result_, exception_state);
+ isolate, result_, exception_state);
if (exception_state.HadException())
return v8::Nothing<ReturnType>();
return v8::Just<ReturnType>(result);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_html_all_collection_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_html_all_collection_custom.cc
index 7b2cd59ce53..779af35166e 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_html_all_collection_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_html_all_collection_custom.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_html_all_collection.h"
-#include "third_party/blink/renderer/bindings/core/v8/html_collection_or_element.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_element_htmlcollection.h"
#include "third_party/blink/renderer/platform/bindings/v8_set_return_value.h"
@@ -63,7 +62,6 @@ void GetIndexedOrNamed(const v8::FunctionCallbackInfo<v8::Value>& info) {
}
TOSTRING_VOID(V8StringResource<>, name, info[0]);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state = ScriptState::From(info.This()->CreationContext());
v8::Local<v8::Value> v8_value;
if (!ToV8Traits<IDLNullable<V8UnionElementOrHTMLCollection>>::ToV8(
@@ -72,11 +70,6 @@ void GetIndexedOrNamed(const v8::FunctionCallbackInfo<v8::Value>& info) {
return;
}
bindings::V8SetReturnValue(info, v8_value);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HTMLCollectionOrElement result;
- impl->NamedGetter(name, result);
- V8SetReturnValue(info, result);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
void V8HTMLAllCollection::LegacyCallCustom(
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 1516c55c7c3..877af027942 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
@@ -58,6 +58,7 @@
#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_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/v8_set_return_value.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -101,12 +102,10 @@ static void LocationAttributeGet(const CallbackInfo& info) {
V8SetReturnValue(info, wrapper);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
void V8Window::LocationAttributeGetterCustom(
const v8::FunctionCallbackInfo<v8::Value>& info) {
LocationAttributeGet(info);
}
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
void V8Window::LocationAttributeGetterCustom(
const v8::PropertyCallbackInfo<v8::Value>& info) {
@@ -175,13 +174,11 @@ static void OpenerAttributeSet(v8::Local<v8::Value> value,
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
void V8Window::OpenerAttributeSetterCustom(
v8::Local<v8::Value> value,
const v8::FunctionCallbackInfo<v8::Value>& info) {
OpenerAttributeSet(value, info);
}
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
void V8Window::OpenerAttributeSetterCustom(
v8::Local<v8::Value> value,
@@ -230,18 +227,6 @@ void V8Window::NamedPropertyGetterCustom(
CurrentExecutionContext(info.GetIsolate()),
WebFeature::
kNamedAccessOnWindow_ChildBrowsingContext_CrossOriginNameMismatch);
- if (!RuntimeEnabledFeatures::
- IgnoreCrossOriginWindowWhenNamedAccessOnWindowEnabled()) {
- // In addition to the above spec'ed case, we return the child window
- // regardless of step 3 due to crbug.com/701489 for the time being.
- // TODO(yukishiino): Makes iframe.name update the browsing context name
- // appropriately and makes the new name available in the named access on
- // window. Then, removes the following two lines.
- bindings::V8SetReturnValue(
- info, child->DomWindow(), window,
- bindings::V8ReturnValue::kMaybeCrossOriginWindow);
- return;
- }
}
// This is a cross-origin interceptor. Check that the caller has access to the
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 4e8e60515a4..ae51fbaead7 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/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"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.cc
index 1ab638faf9c..58c917286f6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h"
+#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
@@ -15,7 +15,7 @@ namespace {
void InstallCustomWrappableTemplate(v8::Isolate* isolate,
const DOMWrapperWorld& world,
- v8::Local<v8::Template> v8_template);
+ v8::Local<v8::Template> interface_template);
const WrapperTypeInfo custom_wrappable_info = {
gin::kEmbedderBlink,
@@ -29,13 +29,21 @@ const WrapperTypeInfo custom_wrappable_info = {
WrapperTypeInfo::kCustomWrappableKind,
};
-void InstallCustomWrappableTemplate(v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Template> v8_template) {
- V8DOMConfiguration::InitializeDOMInterfaceTemplate(
- isolate, v8_template.As<v8::FunctionTemplate>(),
- custom_wrappable_info.interface_name, v8::Local<v8::FunctionTemplate>(),
- kV8DefaultWrapperInternalFieldCount);
+void InstallCustomWrappableTemplate(
+ v8::Isolate* isolate,
+ const DOMWrapperWorld& world,
+ v8::Local<v8::Template> interface_template) {
+ v8::Local<v8::FunctionTemplate> interface_function_template =
+ interface_template.As<v8::FunctionTemplate>();
+ v8::Local<v8::ObjectTemplate> instance_object_template =
+ interface_function_template->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype_object_template =
+ interface_function_template->PrototypeTemplate();
+ v8::Local<v8::FunctionTemplate> parent_interface_template;
+ bindings::SetupIDLInterfaceTemplate(
+ isolate, &custom_wrappable_info, instance_object_template,
+ prototype_object_template, interface_function_template,
+ parent_interface_template);
}
} // namespace
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 a40867aed6a..14d91535062 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h
@@ -26,6 +26,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_DICTIONARY_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_DICTIONARY_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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/core_export.h"
@@ -57,6 +59,7 @@ class CORE_EXPORT Dictionary final {
value_type_ = ValueType::kObject;
}
+ Dictionary(const Dictionary&) = default;
Dictionary& operator=(const Dictionary&) = default;
bool IsObject() const { return !dictionary_object_.IsEmpty(); }
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 f08a0549aec..b7c21f21f40 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
@@ -27,12 +27,10 @@
#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_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_message_port.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_text_track.h"
-#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"
@@ -257,7 +255,13 @@ CORE_EXPORT bool DictionaryHelper::Get(const Dictionary& dictionary,
if (!dictionary.Get(key, v8_value))
return false;
- value = V8Uint8Array::ToImplWithTypeCheck(dictionary.GetIsolate(), v8_value);
+ if (!v8_value->IsUint8Array())
+ return false;
+
+ NonThrowableExceptionState exception_state;
+ value = NativeValueTraits<MaybeShared<DOMUint8Array>>::NativeValue(
+ dictionary.GetIsolate(), v8_value, exception_state)
+ .Get();
return true;
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/generated.gni b/chromium/third_party/blink/renderer/bindings/core/v8/generated.gni
deleted file mode 100644
index a53634140ba..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/generated.gni
+++ /dev/null
@@ -1,231 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
-import("//third_party/blink/renderer/core/core.gni")
-import("//third_party/blink/renderer/core/core_idl_files.gni")
-
-bindings_core_generated_union_type_files = [
- "$bindings_core_v8_output_dir/add_event_listener_options_or_boolean.cc",
- "$bindings_core_v8_output_dir/add_event_listener_options_or_boolean.h",
- "$bindings_core_v8_output_dir/array_buffer_or_array_buffer_view.cc",
- "$bindings_core_v8_output_dir/array_buffer_or_array_buffer_view.h",
- "$bindings_core_v8_output_dir/array_buffer_or_array_buffer_view_or_blob_or_usv_string.cc",
- "$bindings_core_v8_output_dir/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h",
- "$bindings_core_v8_output_dir/blob_or_array_buffer_or_array_buffer_view_or_form_data_or_url_search_params_or_usv_string.cc",
- "$bindings_core_v8_output_dir/blob_or_array_buffer_or_array_buffer_view_or_form_data_or_url_search_params_or_usv_string.h",
- "$bindings_core_v8_output_dir/boolean_or_byte_string_byte_string_record.cc",
- "$bindings_core_v8_output_dir/boolean_or_byte_string_byte_string_record.h",
- "$bindings_core_v8_output_dir/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc",
- "$bindings_core_v8_output_dir/byte_string_sequence_sequence_or_byte_string_byte_string_record.h",
- "$bindings_core_v8_output_dir/composite_operation_or_auto_or_composite_operation_or_auto_sequence.cc",
- "$bindings_core_v8_output_dir/composite_operation_or_auto_or_composite_operation_or_auto_sequence.h",
- "$bindings_core_v8_output_dir/css_numeric_value_or_string_or_css_keyword_value_or_scroll_timeline_element_based_offset.cc",
- "$bindings_core_v8_output_dir/css_numeric_value_or_string_or_css_keyword_value_or_scroll_timeline_element_based_offset.h",
- "$bindings_core_v8_output_dir/css_numeric_value_or_string_or_css_keyword_value.h",
- "$bindings_core_v8_output_dir/css_numeric_value_or_string_or_css_keyword_value.cc",
- "$bindings_core_v8_output_dir/css_style_value_or_string.cc",
- "$bindings_core_v8_output_dir/css_style_value_or_string.h",
- "$bindings_core_v8_output_dir/document_or_xml_http_request_body_init.cc",
- "$bindings_core_v8_output_dir/document_or_xml_http_request_body_init.h",
- "$bindings_core_v8_output_dir/double_or_auto_keyword.cc",
- "$bindings_core_v8_output_dir/double_or_auto_keyword.h",
- "$bindings_core_v8_output_dir/double_or_css_numeric_value.cc",
- "$bindings_core_v8_output_dir/double_or_css_numeric_value.h",
- "$bindings_core_v8_output_dir/double_or_double_or_null_sequence.cc",
- "$bindings_core_v8_output_dir/double_or_double_or_null_sequence.h",
- "$bindings_core_v8_output_dir/double_or_double_sequence.cc",
- "$bindings_core_v8_output_dir/double_or_double_sequence.h",
- "$bindings_core_v8_output_dir/double_or_internal_enum.cc",
- "$bindings_core_v8_output_dir/double_or_internal_enum.h",
- "$bindings_core_v8_output_dir/double_or_scroll_timeline_auto_keyword.cc",
- "$bindings_core_v8_output_dir/double_or_scroll_timeline_auto_keyword.h",
- "$bindings_core_v8_output_dir/double_or_string.cc",
- "$bindings_core_v8_output_dir/double_or_string.h",
- "$bindings_core_v8_output_dir/double_or_string_or_string_sequence.cc",
- "$bindings_core_v8_output_dir/double_or_string_or_string_sequence.h",
- "$bindings_core_v8_output_dir/element_or_document.cc",
- "$bindings_core_v8_output_dir/element_or_document.h",
- "$bindings_core_v8_output_dir/event_listener_options_or_boolean.cc",
- "$bindings_core_v8_output_dir/event_listener_options_or_boolean.h",
- "$bindings_core_v8_output_dir/file_or_usv_string.cc",
- "$bindings_core_v8_output_dir/file_or_usv_string.h",
- "$bindings_core_v8_output_dir/file_or_usv_string_or_form_data.cc",
- "$bindings_core_v8_output_dir/file_or_usv_string_or_form_data.h",
- "$bindings_core_v8_output_dir/float_or_string_element_record.cc",
- "$bindings_core_v8_output_dir/float_or_string_element_record.h",
- "$bindings_core_v8_output_dir/html_collection_or_element.cc",
- "$bindings_core_v8_output_dir/html_collection_or_element.h",
- "$bindings_core_v8_output_dir/html_element_or_long.cc",
- "$bindings_core_v8_output_dir/html_element_or_long.h",
- "$bindings_core_v8_output_dir/html_option_element_or_html_opt_group_element.cc",
- "$bindings_core_v8_output_dir/html_option_element_or_html_opt_group_element.h",
- "$bindings_core_v8_output_dir/html_script_element_or_svg_script_element.cc",
- "$bindings_core_v8_output_dir/html_script_element_or_svg_script_element.h",
- "$bindings_core_v8_output_dir/internal_enum_or_internal_enum_sequence.cc",
- "$bindings_core_v8_output_dir/internal_enum_or_internal_enum_sequence.h",
- "$bindings_core_v8_output_dir/media_list_or_string.cc",
- "$bindings_core_v8_output_dir/media_list_or_string.h",
- "$bindings_core_v8_output_dir/node_list_or_element.cc",
- "$bindings_core_v8_output_dir/node_list_or_element.h",
- "$bindings_core_v8_output_dir/node_or_string_or_trusted_script.cc",
- "$bindings_core_v8_output_dir/node_or_string_or_trusted_script.h",
- "$bindings_core_v8_output_dir/radio_node_list_or_element.cc",
- "$bindings_core_v8_output_dir/radio_node_list_or_element.h",
- "$bindings_core_v8_output_dir/readable_stream_default_controller_or_readable_byte_stream_controller.cc",
- "$bindings_core_v8_output_dir/readable_stream_default_controller_or_readable_byte_stream_controller.h",
- "$bindings_core_v8_output_dir/readable_stream_default_reader_or_readable_stream_byob_reader.cc",
- "$bindings_core_v8_output_dir/readable_stream_default_reader_or_readable_stream_byob_reader.h",
- "$bindings_core_v8_output_dir/request_or_usv_string.cc",
- "$bindings_core_v8_output_dir/request_or_usv_string.h",
- "$bindings_core_v8_output_dir/scroll_into_view_options_or_boolean.cc",
- "$bindings_core_v8_output_dir/scroll_into_view_options_or_boolean.h",
- "$bindings_core_v8_output_dir/string_or_array_buffer.cc",
- "$bindings_core_v8_output_dir/string_or_array_buffer.h",
- "$bindings_core_v8_output_dir/string_or_array_buffer_or_array_buffer_view.cc",
- "$bindings_core_v8_output_dir/string_or_array_buffer_or_array_buffer_view.h",
- "$bindings_core_v8_output_dir/string_or_css_variable_reference_value.cc",
- "$bindings_core_v8_output_dir/string_or_css_variable_reference_value.h",
- "$bindings_core_v8_output_dir/string_or_css_keyword_value.cc",
- "$bindings_core_v8_output_dir/string_or_css_keyword_value.h",
- "$bindings_core_v8_output_dir/string_or_double.cc",
- "$bindings_core_v8_output_dir/string_or_double.h",
- "$bindings_core_v8_output_dir/string_or_element_creation_options.cc",
- "$bindings_core_v8_output_dir/string_or_element_creation_options.h",
- "$bindings_core_v8_output_dir/string_or_performance_measure_options.cc",
- "$bindings_core_v8_output_dir/string_or_performance_measure_options.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_or_trusted_script_or_trusted_script_url.cc",
- "$bindings_core_v8_output_dir/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h",
- "$bindings_core_v8_output_dir/string_or_trusted_script.cc",
- "$bindings_core_v8_output_dir/string_or_trusted_script.h",
- "$bindings_core_v8_output_dir/string_or_trusted_script_url.cc",
- "$bindings_core_v8_output_dir/string_or_trusted_script_url.h",
- "$bindings_core_v8_output_dir/string_or_unrestricted_double_sequence.cc",
- "$bindings_core_v8_output_dir/string_or_unrestricted_double_sequence.h",
- "$bindings_core_v8_output_dir/string_or_worker_options.cc",
- "$bindings_core_v8_output_dir/string_or_worker_options.h",
- "$bindings_core_v8_output_dir/string_treat_null_as_empty_string_or_trusted_script.cc",
- "$bindings_core_v8_output_dir/string_treat_null_as_empty_string_or_trusted_script.h",
- "$bindings_core_v8_output_dir/uint8_clamped_array_or_uint16_array_or_float32_array.cc",
- "$bindings_core_v8_output_dir/uint8_clamped_array_or_uint16_array_or_float32_array.h",
- "$bindings_core_v8_output_dir/unrestricted_double_or_keyframe_animation_options.cc",
- "$bindings_core_v8_output_dir/unrestricted_double_or_keyframe_animation_options.h",
- "$bindings_core_v8_output_dir/unrestricted_double_or_keyframe_effect_options.cc",
- "$bindings_core_v8_output_dir/unrestricted_double_or_keyframe_effect_options.h",
- "$bindings_core_v8_output_dir/unrestricted_double_or_string.cc",
- "$bindings_core_v8_output_dir/unrestricted_double_or_string.h",
- "$bindings_core_v8_output_dir/usv_string_sequence_sequence_or_usv_string_usv_string_record_or_usv_string.cc",
- "$bindings_core_v8_output_dir/usv_string_sequence_sequence_or_usv_string_usv_string_record_or_usv_string.h",
- "$bindings_core_v8_output_dir/video_track_or_audio_track_or_text_track.cc",
- "$bindings_core_v8_output_dir/video_track_or_audio_track_or_text_track.h",
-]
-
-generated_core_testing_callback_function_files = [
- "$bindings_core_v8_output_dir/v8_test_callback.cc",
- "$bindings_core_v8_output_dir/v8_test_callback.h",
- "$bindings_core_v8_output_dir/v8_test_enum_callback.cc",
- "$bindings_core_v8_output_dir/v8_test_enum_callback.h",
- "$bindings_core_v8_output_dir/v8_test_interface_callback.cc",
- "$bindings_core_v8_output_dir/v8_test_interface_callback.h",
- "$bindings_core_v8_output_dir/v8_test_receiver_object_callback.cc",
- "$bindings_core_v8_output_dir/v8_test_receiver_object_callback.h",
- "$bindings_core_v8_output_dir/v8_test_sequence_callback.cc",
- "$bindings_core_v8_output_dir/v8_test_sequence_callback.h",
-]
-
-generated_core_callback_function_files = [
- "$bindings_core_v8_output_dir/v8_blob_callback.cc",
- "$bindings_core_v8_output_dir/v8_blob_callback.h",
- "$bindings_core_v8_output_dir/v8_create_html_callback.cc",
- "$bindings_core_v8_output_dir/v8_create_html_callback.h",
- "$bindings_core_v8_output_dir/v8_create_script_callback.cc",
- "$bindings_core_v8_output_dir/v8_create_script_callback.h",
- "$bindings_core_v8_output_dir/v8_create_url_callback.cc",
- "$bindings_core_v8_output_dir/v8_create_url_callback.h",
- "$bindings_core_v8_output_dir/v8_custom_element_adopted_callback.cc",
- "$bindings_core_v8_output_dir/v8_custom_element_adopted_callback.h",
- "$bindings_core_v8_output_dir/v8_custom_element_attribute_changed_callback.cc",
- "$bindings_core_v8_output_dir/v8_custom_element_attribute_changed_callback.h",
- "$bindings_core_v8_output_dir/v8_custom_element_constructor.cc",
- "$bindings_core_v8_output_dir/v8_custom_element_constructor.h",
- "$bindings_core_v8_output_dir/v8_custom_element_form_associated_callback.cc",
- "$bindings_core_v8_output_dir/v8_custom_element_form_associated_callback.h",
- "$bindings_core_v8_output_dir/v8_custom_element_form_disabled_callback.cc",
- "$bindings_core_v8_output_dir/v8_custom_element_form_disabled_callback.h",
- "$bindings_core_v8_output_dir/v8_custom_element_form_state_restore_callback.cc",
- "$bindings_core_v8_output_dir/v8_custom_element_form_state_restore_callback.h",
- "$bindings_core_v8_output_dir/v8_event_handler_non_null.cc",
- "$bindings_core_v8_output_dir/v8_event_handler_non_null.h",
- "$bindings_core_v8_output_dir/v8_for_each_iterator_callback.cc",
- "$bindings_core_v8_output_dir/v8_for_each_iterator_callback.h",
- "$bindings_core_v8_output_dir/v8_frame_request_callback.cc",
- "$bindings_core_v8_output_dir/v8_frame_request_callback.h",
- "$bindings_core_v8_output_dir/v8_function.cc",
- "$bindings_core_v8_output_dir/v8_function.h",
- "$bindings_core_v8_output_dir/v8_function_string_callback.cc",
- "$bindings_core_v8_output_dir/v8_function_string_callback.h",
- "$bindings_core_v8_output_dir/v8_idle_request_callback.cc",
- "$bindings_core_v8_output_dir/v8_idle_request_callback.h",
- "$bindings_core_v8_output_dir/v8_intersection_observer_callback.cc",
- "$bindings_core_v8_output_dir/v8_intersection_observer_callback.h",
- "$bindings_core_v8_output_dir/v8_intrinsic_sizes_callback.cc",
- "$bindings_core_v8_output_dir/v8_intrinsic_sizes_callback.h",
- "$bindings_core_v8_output_dir/v8_layout_callback.cc",
- "$bindings_core_v8_output_dir/v8_layout_callback.h",
- "$bindings_core_v8_output_dir/v8_mojo_watch_callback.cc",
- "$bindings_core_v8_output_dir/v8_mojo_watch_callback.h",
- "$bindings_core_v8_output_dir/v8_mutation_callback.cc",
- "$bindings_core_v8_output_dir/v8_mutation_callback.h",
- "$bindings_core_v8_output_dir/v8_no_argument_constructor.cc",
- "$bindings_core_v8_output_dir/v8_no_argument_constructor.h",
- "$bindings_core_v8_output_dir/v8_performance_observer_callback.cc",
- "$bindings_core_v8_output_dir/v8_performance_observer_callback.h",
- "$bindings_core_v8_output_dir/v8_reporting_observer_callback.cc",
- "$bindings_core_v8_output_dir/v8_reporting_observer_callback.h",
- "$bindings_core_v8_output_dir/v8_resize_observer_callback.cc",
- "$bindings_core_v8_output_dir/v8_resize_observer_callback.h",
- "$bindings_core_v8_output_dir/v8_scroll_state_callback.cc",
- "$bindings_core_v8_output_dir/v8_scroll_state_callback.h",
- "$bindings_core_v8_output_dir/v8_void_function.cc",
- "$bindings_core_v8_output_dir/v8_void_function.h",
-]
-
-if (is_win && is_official_build) {
- # On Windows Official release builds, we try to preserve symbol space.
- # is_official_build adds /GL option and /LTCG automatically in link.exe.
- # But link.exe cannot make binary smaller than its size limit from
- # many obj files for bindings_core_impl.lib.
- bindings_core_generated_interface_files =
- [ "$bindings_core_v8_output_dir/v8_generated_core_bindings.cc" ]
-} else {
- _idl_files = core_buffer_source_type_idl_files
- if (!use_blink_v8_binding_new_idl_callback_interface) {
- _idl_files += core_callback_interface_idl_files
- }
- if (!use_blink_v8_binding_new_idl_dictionary) {
- _idl_files += core_dictionary_idl_files
- }
- if (!use_blink_v8_binding_new_idl_interface) {
- _idl_files += core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent
- }
- bindings_core_generated_interface_files =
- process_file_template(
- _idl_files,
- [
- "$bindings_core_v8_output_dir/v8_{{source_name_part}}.cc",
- "$bindings_core_v8_output_dir/v8_{{source_name_part}}.h",
- ])
-}
-
-generated_core_testing_dictionary_files =
- process_file_template(
- core_testing_dictionary_idl_files,
- [
- "$blink_core_output_dir/testing/{{source_name_part}}.cc",
- "$blink_core_output_dir/testing/{{source_name_part}}.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 df5c2987fbb..47616c47b1f 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
@@ -21,20 +21,6 @@
namespace blink {
-void V8ConstructorAttributeGetter(
- v8::Local<v8::Name> property_name,
- const v8::PropertyCallbackInfo<v8::Value>& info,
- const WrapperTypeInfo* wrapper_type_info) {
- RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(
- info.GetIsolate(), "Blink_V8ConstructorAttributeGetter");
- V8PerContextData* per_context_data =
- V8PerContextData::From(info.Holder()->CreationContext());
- if (!per_context_data)
- return;
- V8SetReturnValue(info,
- per_context_data->ConstructorForType(wrapper_type_info));
-}
-
namespace {
enum class IgnorePause { kDontIgnore, kIgnore };
@@ -103,57 +89,6 @@ bool IsCallbackFunctionRunnableIgnoringPause(
IgnorePause::kIgnore);
}
-void V8SetReflectedBooleanAttribute(
- const v8::FunctionCallbackInfo<v8::Value>& info,
- const char* interface_name,
- const char* idl_attribute_name,
- const QualifiedName& content_attr) {
- v8::Isolate* isolate = info.GetIsolate();
- Element* impl = V8Element::ToImpl(info.Holder());
-
- ExceptionState exception_state(isolate, ExceptionState::kSetterContext,
- interface_name, idl_attribute_name);
- CEReactionsScope ce_reactions_scope;
-
- // Prepare the value to be set.
- bool cpp_value = NativeValueTraits<IDLBoolean>::NativeValue(isolate, info[0],
- exception_state);
- if (exception_state.HadException())
- return;
-
- impl->SetBooleanAttribute(content_attr, cpp_value);
-}
-
-void V8SetReflectedDOMStringAttribute(
- const v8::FunctionCallbackInfo<v8::Value>& info,
- const QualifiedName& content_attr) {
- Element* impl = V8Element::ToImpl(info.Holder());
-
- CEReactionsScope ce_reactions_scope;
-
- // Prepare the value to be set.
- V8StringResource<> cpp_value{info[0]};
- if (!cpp_value.Prepare())
- return;
-
- impl->setAttribute(content_attr, cpp_value);
-}
-
-void V8SetReflectedNullableDOMStringAttribute(
- const v8::FunctionCallbackInfo<v8::Value>& info,
- const QualifiedName& content_attr) {
- Element* impl = V8Element::ToImpl(info.Holder());
-
- CEReactionsScope ce_reactions_scope;
-
- // Prepare the value to be set.
- V8StringResource<kTreatNullAndUndefinedAsNullString> cpp_value{info[0]};
- if (!cpp_value.Prepare())
- return;
-
- impl->setAttribute(content_attr, cpp_value);
-}
-
namespace bindings {
void SetupIDLInterfaceTemplate(
@@ -205,15 +140,15 @@ absl::optional<size_t> FindIndexInEnumStringTable(
base::span<const char* const> enum_value_table,
const char* enum_type_name,
ExceptionState& exception_state) {
- const String& str_value = NativeValueTraits<IDLStringV2>::NativeValue(
+ const String& str_value = NativeValueTraits<IDLString>::NativeValue(
isolate, value, exception_state);
- if (exception_state.HadException())
+ if (UNLIKELY(exception_state.HadException()))
return absl::nullopt;
absl::optional<size_t> index =
FindIndexInEnumStringTable(str_value, enum_value_table);
- if (!index.has_value()) {
+ if (UNLIKELY(!index.has_value())) {
exception_state.ThrowTypeError("The provided value '" + str_value +
"' is not a valid enum value of type " +
enum_type_name + ".");
@@ -387,8 +322,6 @@ v8::Local<v8::Array> EnumerateIndexedProperties(v8::Isolate* isolate,
return v8::Array::New(isolate, elements.data(), elements.size());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-
void InstallCSSPropertyAttributes(
v8::Isolate* isolate,
const DOMWrapperWorld& world,
@@ -448,9 +381,9 @@ void CSSPropertyAttributeSet(const v8::FunctionCallbackInfo<v8::Value>& info) {
V8CSSStyleDeclaration::ToWrappableUnsafe(v8_receiver);
v8::Local<v8::Value> v8_property_value = info[0];
auto&& arg1_value =
- NativeValueTraits<IDLStringTreatNullAsEmptyStringV2>::NativeValue(
+ NativeValueTraits<IDLStringTreatNullAsEmptyString>::NativeValue(
isolate, v8_property_value, exception_state);
- if (exception_state.HadException()) {
+ if (UNLIKELY(exception_state.HadException())) {
return;
}
v8::Local<v8::Context> receiver_context = v8_receiver->CreationContext();
@@ -484,7 +417,7 @@ void PerformAttributeSetCEReactionsReflect(
Element* blink_receiver = V8Element::ToWrappableUnsafe(info.This());
auto&& arg_value = NativeValueTraits<IDLType>::NativeValue(isolate, info[0],
exception_state);
- if (exception_state.HadException())
+ if (UNLIKELY(exception_state.HadException()))
return;
(blink_receiver->*MemFunc)(content_attribute, arg_value);
@@ -505,7 +438,7 @@ void PerformAttributeSetCEReactionsReflectTypeString(
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
- PerformAttributeSetCEReactionsReflect<IDLStringV2, const AtomicString&,
+ PerformAttributeSetCEReactionsReflect<IDLString, const AtomicString&,
&Element::setAttribute>(
info, content_attribute, interface_name, attribute_name);
}
@@ -515,7 +448,7 @@ void PerformAttributeSetCEReactionsReflectTypeStringLegacyNullToEmptyString(
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
- PerformAttributeSetCEReactionsReflect<IDLStringTreatNullAsEmptyStringV2,
+ PerformAttributeSetCEReactionsReflect<IDLStringTreatNullAsEmptyString,
const AtomicString&,
&Element::setAttribute>(
info, content_attribute, interface_name, attribute_name);
@@ -527,12 +460,10 @@ void PerformAttributeSetCEReactionsReflectTypeStringOrNull(
const char* interface_name,
const char* attribute_name) {
PerformAttributeSetCEReactionsReflect<
- IDLNullable<IDLStringV2>, const AtomicString&, &Element::setAttribute>(
+ IDLNullable<IDLString>, const AtomicString&, &Element::setAttribute>(
info, content_attribute, interface_name, attribute_name);
}
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
} // namespace bindings
} // 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 d88661cfc9f..b899507178f 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
@@ -9,6 +9,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -27,11 +28,6 @@ class QualifiedName;
class Range;
class ScriptState;
-CORE_EXPORT void V8ConstructorAttributeGetter(
- v8::Local<v8::Name> property_name,
- const v8::PropertyCallbackInfo<v8::Value>&,
- const WrapperTypeInfo*);
-
// ExceptionToRejectPromiseScope converts a possible exception to a reject
// promise and returns the promise instead of throwing the exception.
//
@@ -46,7 +42,7 @@ class CORE_EXPORT ExceptionToRejectPromiseScope final {
ExceptionState& exception_state)
: info_(info), exception_state_(exception_state) {}
~ExceptionToRejectPromiseScope() {
- if (!exception_state_.HadException())
+ if (LIKELY(!exception_state_.HadException()))
return;
// As exceptions must always be created in the current realm, reject
@@ -84,19 +80,6 @@ using InstallRuntimeEnabledFeaturesFunction =
using InstallRuntimeEnabledFeaturesOnTemplateFunction = InstallTemplateFunction;
-// Helpers for [CEReactions, Reflect] IDL attributes.
-void V8SetReflectedBooleanAttribute(
- const v8::FunctionCallbackInfo<v8::Value>& info,
- const char* interface_name,
- const char* idl_attribute_name,
- const QualifiedName& content_attr);
-void V8SetReflectedDOMStringAttribute(
- const v8::FunctionCallbackInfo<v8::Value>& info,
- const QualifiedName& content_attr);
-void V8SetReflectedNullableDOMStringAttribute(
- const v8::FunctionCallbackInfo<v8::Value>& info,
- const QualifiedName& content_attr);
-
namespace bindings {
CORE_EXPORT void SetupIDLInterfaceTemplate(
@@ -145,7 +128,7 @@ typename IDLSequence<T>::ImplType VariadicArgumentsToNativeValues(
for (int i = start_index; i < length; ++i) {
result.UncheckedAppend(NativeValueTraits<T>::ArgumentValue(
isolate, i, info[i], exception_state, extra_args...));
- if (exception_state.HadException())
+ if (UNLIKELY(exception_state.HadException()))
return VectorType();
}
return std::move(result);
@@ -209,37 +192,35 @@ CORE_EXPORT v8::Local<v8::Array> EnumerateIndexedProperties(
//
// |try_block| must be the innermost v8::TryCatch and it's used to internally
// capture an exception, which is rethrown in |exception_state|.
-template <typename NVTTag, bool is_required, typename T>
-bool ConvertDictionaryMember(v8::Isolate* isolate,
- v8::Local<v8::Context> current_context,
- v8::Local<v8::Object> v8_dictionary,
- v8::Local<v8::Name> v8_member_name,
- const char* dictionary_name,
- const char* member_name,
- T& value,
- bool& presence,
- v8::TryCatch& try_block,
- ExceptionState& exception_state) {
+template <typename IDLType, bool is_required, typename ValueType>
+bool GetDictionaryMemberFromV8Object(v8::Isolate* isolate,
+ v8::Local<v8::Context> current_context,
+ v8::Local<v8::Object> v8_dictionary,
+ v8::Local<v8::Name> v8_member_name,
+ bool& presence,
+ ValueType& value,
+ v8::TryCatch& try_block,
+ ExceptionState& exception_state) {
v8::Local<v8::Value> v8_value;
if (!v8_dictionary->Get(current_context, v8_member_name).ToLocal(&v8_value)) {
exception_state.RethrowV8Exception(try_block.Exception());
- try_block.Reset();
return false;
}
if (v8_value->IsUndefined()) {
if (is_required) {
exception_state.ThrowTypeError(ExceptionMessages::FailedToGet(
- member_name, dictionary_name, "Required member is undefined."));
+ exception_state.GetInnerMostContext().GetPropertyName(),
+ exception_state.GetInnerMostContext().GetClassName(),
+ "Required member is undefined."));
return false;
}
- presence = false;
return true;
}
- value = NativeValueTraits<NVTTag>::NativeValue(isolate, v8_value,
- exception_state);
- if (exception_state.HadException()) {
+ value = NativeValueTraits<IDLType>::NativeValue(isolate, v8_value,
+ exception_state);
+ if (UNLIKELY(exception_state.HadException())) {
return false;
}
presence = true;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/idl_types.h b/chromium/third_party/blink/renderer/bindings/core/v8/idl_types.h
index bf1d91e1122..000a29f02cc 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/idl_types.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/idl_types.h
@@ -12,9 +12,9 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types_base.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.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 "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -124,70 +124,6 @@ using IDLUnrestrictedDouble = IDLFloatingPointNumberTypeBase<
bindings::IDLFloatingPointNumberConvMode::kUnrestricted>;
// Strings
-// The "Base" classes are always templatized and require users to specify how JS
-// null and/or undefined are supposed to be handled.
-template <V8StringResourceMode Mode>
-struct IDLByteStringBase final : public IDLBaseHelper<String> {};
-template <V8StringResourceMode Mode>
-struct IDLStringBase final : public IDLBaseHelper<String> {};
-template <V8StringResourceMode Mode>
-struct IDLUSVStringBase final : public IDLBaseHelper<String> {};
-
-template <V8StringResourceMode Mode>
-struct IDLStringStringContextTrustedHTMLBase final
- : public IDLBaseHelper<String> {};
-template <V8StringResourceMode Mode>
-struct IDLStringStringContextTrustedScriptBase final
- : public IDLBaseHelper<String> {};
-template <V8StringResourceMode Mode>
-struct IDLUSVStringStringContextTrustedScriptURLBase final
- : public IDLBaseHelper<String> {};
-
-// Define non-template versions of the above for simplicity.
-using IDLByteString = IDLByteStringBase<V8StringResourceMode::kDefaultMode>;
-using IDLString = IDLStringBase<V8StringResourceMode::kDefaultMode>;
-using IDLUSVString = IDLUSVStringBase<V8StringResourceMode::kDefaultMode>;
-
-// Nullable strings
-using IDLByteStringOrNull =
- IDLByteStringBase<V8StringResourceMode::kTreatNullAndUndefinedAsNullString>;
-using IDLStringOrNull =
- IDLStringBase<V8StringResourceMode::kTreatNullAndUndefinedAsNullString>;
-using IDLUSVStringOrNull =
- IDLUSVStringBase<V8StringResourceMode::kTreatNullAndUndefinedAsNullString>;
-
-// [TreatNullAs] Strings
-using IDLStringTreatNullAsEmptyString =
- IDLStringBase<V8StringResourceMode::kTreatNullAsEmptyString>;
-
-// [StringContext] Strings
-using IDLStringStringContextTrustedHTML =
- IDLStringStringContextTrustedHTMLBase<V8StringResourceMode::kDefaultMode>;
-using IDLStringStringContextTrustedScript =
- IDLStringStringContextTrustedScriptBase<V8StringResourceMode::kDefaultMode>;
-using IDLUSVStringStringContextTrustedScriptURL =
- IDLUSVStringStringContextTrustedScriptURLBase<
- V8StringResourceMode::kDefaultMode>;
-using IDLStringStringContextTrustedHTMLOrNull =
- IDLStringStringContextTrustedHTMLBase<
- V8StringResourceMode::kTreatNullAndUndefinedAsNullString>;
-using IDLStringStringContextTrustedScriptOrNull =
- IDLStringStringContextTrustedScriptBase<
- V8StringResourceMode::kTreatNullAndUndefinedAsNullString>;
-using IDLUSVStringStringContextTrustedScriptURLOrNull =
- IDLUSVStringStringContextTrustedScriptURLBase<
- V8StringResourceMode::kTreatNullAndUndefinedAsNullString>;
-using IDLStringStringContextTrustedHTMLTreatNullAsEmptyString =
- IDLStringStringContextTrustedHTMLBase<
- V8StringResourceMode::kTreatNullAsEmptyString>;
-using IDLStringStringContextTrustedScriptTreatNullAsEmptyString =
- IDLStringStringContextTrustedScriptBase<
- V8StringResourceMode::kTreatNullAsEmptyString>;
-using IDLUSVStringStringContextTrustedScriptURLTreatNullAsEmptyString =
- IDLUSVStringStringContextTrustedScriptURLBase<
- V8StringResourceMode::kTreatNullAsEmptyString>;
-
-// Strings for the new bindings generator
namespace bindings {
@@ -204,51 +140,48 @@ struct IDLStringTypeBase : public IDLBaseHelper<String> {};
// ByteString
template <bindings::IDLStringConvMode mode>
-struct IDLByteStringBaseV2 final : public IDLStringTypeBase {};
-using IDLByteStringV2 =
- IDLByteStringBaseV2<bindings::IDLStringConvMode::kDefault>;
+struct IDLByteStringBase final : public IDLStringTypeBase {};
+using IDLByteString = IDLByteStringBase<bindings::IDLStringConvMode::kDefault>;
// DOMString
template <bindings::IDLStringConvMode mode>
-struct IDLStringBaseV2 final : public IDLStringTypeBase {};
-using IDLStringV2 = IDLStringBaseV2<bindings::IDLStringConvMode::kDefault>;
-using IDLStringTreatNullAsEmptyStringV2 =
- IDLStringBaseV2<bindings::IDLStringConvMode::kTreatNullAsEmptyString>;
+struct IDLStringBase final : public IDLStringTypeBase {};
+using IDLString = IDLStringBase<bindings::IDLStringConvMode::kDefault>;
+using IDLStringTreatNullAsEmptyString =
+ IDLStringBase<bindings::IDLStringConvMode::kTreatNullAsEmptyString>;
// USVString
template <bindings::IDLStringConvMode mode>
-struct IDLUSVStringBaseV2 final : public IDLStringTypeBase {};
-using IDLUSVStringV2 =
- IDLUSVStringBaseV2<bindings::IDLStringConvMode::kDefault>;
+struct IDLUSVStringBase final : public IDLStringTypeBase {};
+using IDLUSVString = IDLUSVStringBase<bindings::IDLStringConvMode::kDefault>;
// [StringContext=TrustedHTML] DOMString
template <bindings::IDLStringConvMode mode>
-struct IDLStringStringContextTrustedHTMLBaseV2 final
- : public IDLStringTypeBase {};
-using IDLStringStringContextTrustedHTMLV2 =
- IDLStringStringContextTrustedHTMLBaseV2<
- bindings::IDLStringConvMode::kDefault>;
-using IDLStringStringContextTrustedHTMLTreatNullAsEmptyStringV2 =
- IDLStringStringContextTrustedHTMLBaseV2<
+struct IDLStringStringContextTrustedHTMLBase final : public IDLStringTypeBase {
+};
+using IDLStringStringContextTrustedHTML = IDLStringStringContextTrustedHTMLBase<
+ bindings::IDLStringConvMode::kDefault>;
+using IDLStringStringContextTrustedHTMLTreatNullAsEmptyString =
+ IDLStringStringContextTrustedHTMLBase<
bindings::IDLStringConvMode::kTreatNullAsEmptyString>;
// [StringContext=TrustedScript] DOMString
template <bindings::IDLStringConvMode mode>
-struct IDLStringStringContextTrustedScriptBaseV2 final
+struct IDLStringStringContextTrustedScriptBase final
: public IDLStringTypeBase {};
-using IDLStringStringContextTrustedScriptV2 =
- IDLStringStringContextTrustedScriptBaseV2<
+using IDLStringStringContextTrustedScript =
+ IDLStringStringContextTrustedScriptBase<
bindings::IDLStringConvMode::kDefault>;
-using IDLStringStringContextTrustedScriptTreatNullAsEmptyStringV2 =
- IDLStringStringContextTrustedScriptBaseV2<
+using IDLStringStringContextTrustedScriptTreatNullAsEmptyString =
+ IDLStringStringContextTrustedScriptBase<
bindings::IDLStringConvMode::kTreatNullAsEmptyString>;
// [StringContext=TrustedScriptURL] USVString
template <bindings::IDLStringConvMode mode>
-struct IDLUSVStringStringContextTrustedScriptURLBaseV2 final
+struct IDLUSVStringStringContextTrustedScriptURLBase final
: public IDLStringTypeBase {};
-using IDLUSVStringStringContextTrustedScriptURLV2 =
- IDLUSVStringStringContextTrustedScriptURLBaseV2<
+using IDLUSVStringStringContextTrustedScriptURL =
+ IDLUSVStringStringContextTrustedScriptURLBase<
bindings::IDLStringConvMode::kDefault>;
// object
@@ -294,27 +227,6 @@ struct IDLNullable final : public IDLBase {
absl::optional<typename NativeValueTraits<T>::ImplType>>;
};
-// Union types
-//
-// IDL union class FooOrBar implements either of IDL types (Foo or Bar),
-// (Foo? or Bar), and (Foo or Bar?), given that neither of Foo nor Bar is a
-// nullable type.
-// IDLUnionNotINT<FooOrBar> represents (Foo or Bar) and IDLUnionINT represents
-// either of (Foo? or Bar) or (Foo or Bar?) where INT stands for
-// "includes a nullable type".
-// https://heycam.github.io/webidl/#dfn-includes-a-nullable-type
-//
-// Note that a conversion from ES null to (Foo or Bar) throws a TypeError while
-// a conversion from ES null to (Foo? or Bar) results in IDL null.
-template <typename T>
-struct IDLUnionNotINT final : public IDLBase {
- using ImplType = T;
-};
-template <typename T>
-struct IDLUnionINT final : public IDLBase {
- using ImplType = T;
-};
-
// Date
struct IDLDate final : public IDLBaseHelper<base::Time> {};
@@ -335,7 +247,7 @@ struct IDLOnErrorEventHandler final : public IDLBaseHelper<EventListener*> {};
// member.
template <typename T>
struct IDLOptional final : public IDLBase {
- using ImplType = void;
+ using ImplType = typename NativeValueTraits<T>::ImplType;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/idl_types_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/idl_types_test.cc
index 15f3ef7b481..ccc9194a1d3 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/idl_types_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/idl_types_test.cc
@@ -7,9 +7,9 @@
#include <type_traits>
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_string_sequence.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_internal_dictionary.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -115,9 +115,10 @@ static_assert(std::is_same<IDLSequence<Element>::ImplType,
static_assert(std::is_same<IDLSequence<InternalDictionary>::ImplType,
HeapVector<Member<InternalDictionary>>>::value,
"IDLSequence<dictionary type> produces a HeapVector<Member<>>");
-static_assert(std::is_same<IDLSequence<StringOrStringSequence>::ImplType,
- HeapVector<StringOrStringSequence>>::value,
- "IDLSequence<union type> produces a HeapVector");
+static_assert(
+ std::is_same<IDLSequence<V8UnionStringOrStringSequence>::ImplType,
+ HeapVector<Member<V8UnionStringOrStringSequence>>>::value,
+ "IDLSequence<union type> produces a HeapVector");
static_assert(std::is_base_of<IDLBase, IDLRecord<IDLString, IDLShort>>::value,
"IDLRecord inherits from IDLBase");
@@ -137,8 +138,10 @@ static_assert(
"IDLRecord<IDLUSVString, dictionary type> produces a HeapVector with "
"Member<>");
static_assert(
- std::is_same<IDLRecord<IDLString, StringOrStringSequence>::ImplType,
- HeapVector<std::pair<String, StringOrStringSequence>>>::value,
+ std::is_same<
+ IDLRecord<IDLString, V8UnionStringOrStringSequence>::ImplType,
+ HeapVector<std::pair<String, Member<V8UnionStringOrStringSequence>>>>::
+ value,
"IDLRecord<IDLString, union type> produces a HeapVector with no Member<>");
static_assert(std::is_base_of<IDLBase, IDLNullable<IDLDouble>>::value,
@@ -150,8 +153,8 @@ static_assert(std::is_same<IDLNullable<Element>::ImplType, Element*>::value,
"Element? doesn't require a absl::optional<> wrapper");
static_assert(std::is_same<IDLNullable<IDLString>::ImplType, String>::value,
"DOMString? doesn't require a absl::optional<> wrapper");
-static_assert(std::is_same<IDLNullable<StringOrStringSequence>::ImplType,
- StringOrStringSequence>::value,
+static_assert(std::is_same<IDLNullable<V8UnionStringOrStringSequence>::ImplType,
+ V8UnionStringOrStringSequence*>::value,
"(union type)? doesn't require a absl::optional<> wrapper");
} // namespace
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc b/chromium/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc
index 06b0c845a46..e424b2e145b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler.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/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/events/before_unload_event.h"
@@ -91,6 +91,7 @@ void JSEventHandler::InvokeInternal(EventTarget& event_target,
HeapVector<ScriptValue> arguments;
ScriptState* script_state_of_listener =
event_handler_->CallbackRelevantScriptState();
+ v8::Isolate* isolate = script_state_of_listener->GetIsolate();
if (special_error_event_handling) {
auto* error_event = To<ErrorEvent>(&event);
@@ -100,17 +101,27 @@ void JSEventHandler::InvokeInternal(EventTarget& event_target,
ScriptValue error_attribute = error_event->error(script_state_of_listener);
if (error_attribute.IsEmpty() ||
error_event->target()->InterfaceName() == event_target_names::kWorker) {
- error_attribute =
- ScriptValue::CreateNull(script_state_of_listener->GetIsolate());
+ error_attribute = ScriptValue::CreateNull(isolate);
}
arguments = {
- ScriptValue::From(script_state_of_listener, error_event->message()),
- ScriptValue::From(script_state_of_listener, error_event->filename()),
- ScriptValue::From(script_state_of_listener, error_event->lineno()),
- ScriptValue::From(script_state_of_listener, error_event->colno()),
+ ScriptValue(isolate,
+ ToV8Traits<IDLString>::ToV8(script_state_of_listener,
+ error_event->message())
+ .ToLocalChecked()),
+ ScriptValue(isolate,
+ ToV8Traits<IDLString>::ToV8(script_state_of_listener,
+ error_event->filename())
+ .ToLocalChecked()),
+ ScriptValue(isolate,
+ ToV8Traits<IDLUnsignedLong>::ToV8(script_state_of_listener,
+ error_event->lineno())
+ .ToLocalChecked()),
+ ScriptValue(isolate, ToV8Traits<IDLUnsignedLong>::ToV8(
+ script_state_of_listener, error_event->colno())
+ .ToLocalChecked()),
error_attribute};
} else {
- arguments = {ScriptValue::From(script_state_of_listener, js_event)};
+ arguments.push_back(ScriptValue(isolate, js_event));
}
if (!event_handler_->IsRunnableOrThrowException(
@@ -123,7 +134,7 @@ void JSEventHandler::InvokeInternal(EventTarget& event_target,
if (!event_handler_
->InvokeWithoutRunnabilityCheck(event.currentTarget(), arguments)
.To(&result) ||
- GetIsolate()->IsExecutionTerminating())
+ isolate->IsExecutionTerminating())
return;
v8::Local<v8::Value> v8_return_value = result.V8Value();
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 83b81f4c1fd..fbef5207c92 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
@@ -100,7 +100,20 @@ void LocalWindowProxy::DisposeContext(Lifecycle next_status,
// willReleaseScriptContext callback, so all disposing should happen after
// it returns.
GetFrame()->Client()->WillReleaseScriptContext(context, world_->GetWorldId());
- MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_);
+
+ // We don't notify context destruction during frame detachment that happens
+ // when we remove the frame from the DOM tree. This allows debug code evaled
+ // from those frames. However, we still want to notify that the context was
+ // destroyed when navigating between documents, because DevTools is designed
+ // to only show what's going on "currently".
+ // Also, delaying such message won't leak memory because
+ // `V8InspectorImpl::contextCollected` is also called when the context for
+ // detached iframe is collected by GC.
+ if (next_status != Lifecycle::kFrameIsDetached &&
+ next_status != Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged) {
+ MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_);
+ }
+
if (next_status == Lifecycle::kV8MemoryIsForciblyPurged ||
next_status == Lifecycle::kGlobalObjectIsDetached) {
// Clean up state on the global proxy, which will be reused.
@@ -249,7 +262,6 @@ void LocalWindowProxy::InstallConditionalFeatures() {
TRACE_EVENT1("v8", "InstallConditionalFeatures", "IsMainFrame",
GetFrame()->IsMainFrame());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
if (context_was_created_from_snapshot_) {
V8ContextSnapshot::InstallContextIndependentProps(script_state_);
}
@@ -261,38 +273,6 @@ void LocalWindowProxy::InstallConditionalFeatures() {
// and V8 can extend the context with origin trial features.
script_state_->GetIsolate()->InstallConditionalFeatures(
script_state_->GetContext());
-#else // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
- v8::Local<v8::Context> context = script_state_->GetContext();
-
- // If the context was created from snapshot, all conditionally
- // enabled features are installed in
- // V8ContextSnapshot::InstallConditionalFeatures().
- if (V8ContextSnapshot::InstallConditionalFeatures(
- context, GetFrame()->GetDocument())) {
- return;
- }
-
- v8::Local<v8::Object> global_proxy = context->Global();
- const WrapperTypeInfo* wrapper_type_info =
- GetFrame()->DomWindow()->GetWrapperTypeInfo();
-
- v8::Local<v8::Object> unused_prototype_object;
- v8::Local<v8::Function> unused_interface_object;
- wrapper_type_info->InstallConditionalFeatures(
- context, World(), global_proxy, unused_prototype_object,
- unused_interface_object,
- wrapper_type_info->DomTemplate(GetIsolate(), World()));
-
- if (World().IsMainWorld()) {
- // For the main world, install any remaining conditional bindings (i.e.
- // 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_,
- v8::Local<v8::Object>(),
- v8::Local<v8::Function>());
- }
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
}
void LocalWindowProxy::SetupWindowPrototypeChain() {
@@ -324,10 +304,6 @@ void LocalWindowProxy::SetupWindowPrototypeChain() {
v8::Local<v8::Object> window_prototype =
window_wrapper->GetPrototype().As<v8::Object>();
CHECK(!window_prototype.IsEmpty());
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
- V8DOMWrapper::SetNativeInfo(GetIsolate(), window_prototype, wrapper_type_info,
- window);
-#endif
// The named properties object of Window interface.
v8::Local<v8::Object> window_properties =
@@ -336,14 +312,12 @@ void LocalWindowProxy::SetupWindowPrototypeChain() {
V8DOMWrapper::SetNativeInfo(GetIsolate(), window_properties,
wrapper_type_info, window);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
// [CachedAccessor=kWindowProxy]
V8PrivateProperty::GetCachedAccessor(
GetIsolate(), V8PrivateProperty::CachedAccessor::kWindowProxy)
.Set(window_wrapper, global_proxy);
-#endif
- // TODO(keishi): Remove installPagePopupController and implement
+ // TODO(yukishiino): Remove installPagePopupController and implement
// PagePopupController in another way.
V8PagePopupControllerBinding::InstallPagePopupController(context,
window_wrapper);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/module_record.cc b/chromium/third_party/blink/renderer/bindings/core/v8/module_record.cc
index c3f7edf41a2..191b11682b5 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/module_record.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/module_record.cc
@@ -44,17 +44,18 @@ ModuleRecordProduceCacheData::ModuleRecordProduceCacheData(
void ModuleRecordProduceCacheData::Trace(Visitor* visitor) const {
visitor->Trace(cache_handler_);
- visitor->Trace(unbound_script_.UnsafeCast<v8::Value>());
+ visitor->Trace(unbound_script_);
}
v8::Local<v8::Module> ModuleRecord::Compile(
- v8::Isolate* isolate,
+ ScriptState* script_state,
const ModuleScriptCreationParams& params,
const ScriptFetchOptions& options,
const TextPosition& text_position,
ExceptionState& exception_state,
mojom::blink::V8CacheOptions v8_cache_options,
ModuleRecordProduceCacheData** out_produce_cache_data) {
+ v8::Isolate* isolate = script_state->GetIsolate();
v8::TryCatch try_catch(isolate);
v8::Local<v8::Module> module;
@@ -69,6 +70,12 @@ v8::Local<v8::Module> ModuleRecord::Compile(
v8::ScriptCompiler::CompileOptions compile_options;
V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ if (params.CacheHandler()) {
+ params.CacheHandler()->Check(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ params.GetSourceText());
+ }
std::tie(compile_options, produce_cache_options, no_cache_reason) =
V8CodeCache::GetCompileOptions(v8_cache_options, params.CacheHandler(),
params.GetSourceText().length(),
@@ -76,8 +83,7 @@ v8::Local<v8::Module> ModuleRecord::Compile(
if (!V8ScriptRunner::CompileModule(
isolate, params, text_position, compile_options, no_cache_reason,
- ReferrerScriptInfo(params.BaseURL(), options,
- ReferrerScriptInfo::BaseUrlSource::kOther))
+ ReferrerScriptInfo(params.BaseURL(), options))
.ToLocal(&module)) {
DCHECK(try_catch.HasCaught());
exception_state.RethrowV8Exception(try_catch.Exception());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/module_record.h b/chromium/third_party/blink/renderer/bindings/core/v8/module_record.h
index c4c02d9b10b..b14dfb0ff61 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/module_record.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/module_record.h
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -50,10 +50,6 @@ class CORE_EXPORT ModuleRecordProduceCacheData final
private:
Member<SingleCachedMetadataHandler> cache_handler_;
V8CodeCache::ProduceCacheOptions produce_cache_options_;
-
- // TODO(keishi): Visitor only defines a trace method for v8::Value so this
- // needs to be cast.
- GC_PLUGIN_IGNORE("757708")
TraceWrapperV8Reference<v8::UnboundModuleScript> unbound_script_;
};
@@ -63,7 +59,7 @@ class CORE_EXPORT ModuleRecord final {
public:
static v8::Local<v8::Module> Compile(
- v8::Isolate*,
+ ScriptState*,
const ModuleScriptCreationParams& params,
const ScriptFetchOptions&,
const TextPosition&,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/module_record_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/module_record_test.cc
index 39d0164390b..e4358dbdd23 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/module_record_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/module_record_test.cc
@@ -115,7 +115,7 @@ TEST_P(ModuleRecordTest, compileSuccess) {
V8TestingScope scope;
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const a = 42;", js_url);
+ scope.GetScriptState(), "export const a = 42;", js_url);
ASSERT_FALSE(module.IsEmpty());
}
@@ -123,7 +123,7 @@ TEST_P(ModuleRecordTest, compileFail) {
V8TestingScope scope;
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "123 = 456", js_url, scope.GetExceptionState());
+ scope.GetScriptState(), "123 = 456", js_url, scope.GetExceptionState());
ASSERT_TRUE(module.IsEmpty());
EXPECT_TRUE(scope.GetExceptionState().HadException());
}
@@ -132,7 +132,7 @@ TEST_P(ModuleRecordTest, moduleRequests) {
V8TestingScope scope;
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "import 'a'; import 'b'; export const c = 'c';",
+ scope.GetScriptState(), "import 'a'; import 'b'; export const c = 'c';",
js_url);
ASSERT_FALSE(module.IsEmpty());
@@ -149,7 +149,7 @@ TEST_P(ModuleRecordTest, moduleRequestsWithImportAssertions) {
v8::V8::SetFlagsFromString("--harmony-import-assertions");
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(),
+ scope.GetScriptState(),
"import 'a' assert { };"
"import 'b' assert { type: 'x'};"
"import 'c' assert { foo: 'y', type: 'z' };",
@@ -179,7 +179,7 @@ TEST_P(ModuleRecordTest, instantiateNoDeps) {
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const a = 42;", js_url);
+ scope.GetScriptState(), "export const a = 42;", js_url);
ASSERT_FALSE(module.IsEmpty());
ScriptValue exception =
ModuleRecord::Instantiate(scope.GetScriptState(), module, js_url);
@@ -197,19 +197,19 @@ TEST_P(ModuleRecordTest, instantiateWithDeps) {
const KURL js_url_a("https://example.com/a.js");
v8::Local<v8::Module> module_a = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const a = 'a';", js_url_a);
+ scope.GetScriptState(), "export const a = 'a';", js_url_a);
ASSERT_FALSE(module_a.IsEmpty());
resolver->PrepareMockResolveResult(module_a);
const KURL js_url_b("https://example.com/b.js");
v8::Local<v8::Module> module_b = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const b = 'b';", js_url_b);
+ scope.GetScriptState(), "export const b = 'b';", js_url_b);
ASSERT_FALSE(module_b.IsEmpty());
resolver->PrepareMockResolveResult(module_b);
const KURL js_url_c("https://example.com/c.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "import 'a'; import 'b'; export const c = 123;",
+ scope.GetScriptState(), "import 'a'; import 'b'; export const c = 123;",
js_url_c);
ASSERT_FALSE(module.IsEmpty());
ScriptValue exception =
@@ -230,7 +230,7 @@ TEST_P(ModuleRecordTest, EvaluationErrorIsRemembered) {
const KURL js_url_f("https://example.com/failure.js");
v8::Local<v8::Module> module_failure = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "nonexistent_function()", js_url_f);
+ scope.GetScriptState(), "nonexistent_function()", js_url_f);
ASSERT_FALSE(module_failure.IsEmpty());
ASSERT_TRUE(
ModuleRecord::Instantiate(state, module_failure, js_url_f).IsEmpty());
@@ -242,8 +242,8 @@ TEST_P(ModuleRecordTest, EvaluationErrorIsRemembered) {
const KURL js_url_c("https://example.com/c.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "import 'failure'; export const c = 123;", js_url_c,
- scope.GetExceptionState());
+ scope.GetScriptState(), "import 'failure'; export const c = 123;",
+ js_url_c, scope.GetExceptionState());
ASSERT_FALSE(module.IsEmpty());
ASSERT_TRUE(ModuleRecord::Instantiate(state, module, js_url_c).IsEmpty());
ScriptEvaluationResult evaluation_result2 =
@@ -268,7 +268,8 @@ TEST_P(ModuleRecordTest, Evaluate) {
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const a = 42; window.foo = 'bar';", js_url);
+ scope.GetScriptState(), "export const a = 42; window.foo = 'bar';",
+ js_url);
ASSERT_FALSE(module.IsEmpty());
ScriptValue exception =
ModuleRecord::Instantiate(scope.GetScriptState(), module, js_url);
@@ -301,8 +302,8 @@ TEST_P(ModuleRecordTest, EvaluateCaptureError) {
MakeGarbageCollected<ModuleRecordTestModulator>(scope.GetScriptState());
const KURL js_url("https://example.com/foo.js");
- v8::Local<v8::Module> module =
- ModuleTestBase::CompileModule(scope.GetIsolate(), "throw 'bar';", js_url);
+ v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
+ scope.GetScriptState(), "throw 'bar';", js_url);
ASSERT_FALSE(module.IsEmpty());
ScriptValue instantiation_exception =
ModuleRecord::Instantiate(scope.GetScriptState(), module, js_url);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
new file mode 100644
index 00000000000..71c068ddc30
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
@@ -0,0 +1,736 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
+
+#include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h"
+
+namespace blink {
+
+namespace {
+
+DOMArrayBuffer* ToDOMArrayBuffer(v8::Isolate* isolate,
+ v8::Local<v8::Value> value) {
+ if (UNLIKELY(!value->IsArrayBuffer()))
+ return nullptr;
+
+ v8::Local<v8::ArrayBuffer> v8_array_buffer = value.As<v8::ArrayBuffer>();
+ if (DOMArrayBuffer* array_buffer =
+ ToScriptWrappable(v8_array_buffer)->ToImpl<DOMArrayBuffer>()) {
+ return array_buffer;
+ }
+
+ // Transfer the ownership of the allocated memory to a DOMArrayBuffer without
+ // copying.
+ ArrayBufferContents contents(v8_array_buffer->GetBackingStore());
+ DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents);
+ v8::Local<v8::Object> wrapper = array_buffer->AssociateWithWrapper(
+ isolate, array_buffer->GetWrapperTypeInfo(), v8_array_buffer);
+ DCHECK(wrapper == v8_array_buffer);
+ return array_buffer;
+}
+
+DOMSharedArrayBuffer* ToDOMSharedArrayBuffer(v8::Isolate* isolate,
+ v8::Local<v8::Value> value) {
+ if (UNLIKELY(!value->IsSharedArrayBuffer()))
+ return nullptr;
+
+ v8::Local<v8::SharedArrayBuffer> v8_shared_array_buffer =
+ value.As<v8::SharedArrayBuffer>();
+ if (DOMSharedArrayBuffer* shared_array_buffer =
+ ToScriptWrappable(v8_shared_array_buffer)
+ ->ToImpl<DOMSharedArrayBuffer>()) {
+ return shared_array_buffer;
+ }
+
+ // Transfer the ownership of the allocated memory to a DOMArrayBuffer without
+ // copying.
+ ArrayBufferContents contents(v8_shared_array_buffer->GetBackingStore());
+ DOMSharedArrayBuffer* shared_array_buffer =
+ DOMSharedArrayBuffer::Create(contents);
+ v8::Local<v8::Object> wrapper = shared_array_buffer->AssociateWithWrapper(
+ isolate, shared_array_buffer->GetWrapperTypeInfo(),
+ v8_shared_array_buffer);
+ DCHECK(wrapper == v8_shared_array_buffer);
+ return shared_array_buffer;
+}
+
+template <typename T>
+struct ABVTrait; // ABV = ArrayBufferView
+
+template <typename DOMViewTypeArg,
+ typename V8ViewTypeArg,
+ bool (v8::Value::*IsV8ViewTypeMemFunc)() const>
+struct ABVTraitImpl {
+ using DOMViewType = DOMViewTypeArg;
+ using V8ViewType = V8ViewTypeArg;
+
+ static DOMViewType* CreateDOMViewType(DOMArrayBufferBase* blink_buffer,
+ v8::Local<V8ViewType> v8_view) {
+ return DOMViewType::Create(blink_buffer, v8_view->ByteOffset(),
+ v8_view->Length());
+ }
+ static bool IsV8ViewType(v8::Local<v8::Value> value) {
+ return ((*value)->*IsV8ViewTypeMemFunc)();
+ }
+ static bool IsShared(v8::Local<v8::Value> value) {
+ return IsV8ViewType(value) &&
+ value.As<V8ViewType>()->Buffer()->IsSharedArrayBuffer();
+ }
+};
+
+#define DEFINE_ABV_TRAIT(name) \
+ template <> \
+ struct ABVTrait<DOM##name> \
+ : ABVTraitImpl<DOM##name, v8::name, &v8::Value::Is##name> {}; \
+ template <> \
+ struct ABVTrait<Flexible##name> \
+ : ABVTraitImpl<DOM##name, v8::name, &v8::Value::Is##name> {};
+DEFINE_ABV_TRAIT(ArrayBufferView)
+DEFINE_ABV_TRAIT(Int8Array)
+DEFINE_ABV_TRAIT(Int16Array)
+DEFINE_ABV_TRAIT(Int32Array)
+DEFINE_ABV_TRAIT(Uint8Array)
+DEFINE_ABV_TRAIT(Uint8ClampedArray)
+DEFINE_ABV_TRAIT(Uint16Array)
+DEFINE_ABV_TRAIT(Uint32Array)
+DEFINE_ABV_TRAIT(BigInt64Array)
+DEFINE_ABV_TRAIT(BigUint64Array)
+DEFINE_ABV_TRAIT(Float32Array)
+DEFINE_ABV_TRAIT(Float64Array)
+#undef DEFINE_ABV_TRAIT
+
+template <>
+struct ABVTrait<DOMDataView>
+ : ABVTraitImpl<DOMDataView, v8::DataView, &v8::Value::IsDataView> {
+ static DOMViewType* CreateDOMViewType(DOMArrayBufferBase* blink_buffer,
+ v8::Local<V8ViewType> v8_view) {
+ return DOMViewType::Create(blink_buffer, v8_view->ByteOffset(),
+ v8_view->ByteLength());
+ }
+};
+
+constexpr bool kNotShared = false;
+constexpr bool kMaybeShared = true;
+
+template <typename DOMViewType, bool allow_shared>
+DOMViewType* ToDOMViewType(v8::Isolate* isolate, v8::Local<v8::Value> value) {
+ using Trait = ABVTrait<DOMViewType>;
+
+ if (UNLIKELY(!Trait::IsV8ViewType(value)))
+ return nullptr;
+
+ v8::Local<typename Trait::V8ViewType> v8_view =
+ value.As<typename Trait::V8ViewType>();
+ if (DOMViewType* blink_view =
+ ToScriptWrappable(v8_view)->template ToImpl<DOMViewType>()) {
+ return blink_view;
+ }
+
+ v8::Local<v8::Object> v8_buffer = v8_view->Buffer();
+ DOMArrayBufferBase* blink_buffer = nullptr;
+ if (allow_shared) {
+ if (v8_buffer->IsArrayBuffer())
+ blink_buffer = ToDOMArrayBuffer(isolate, v8_buffer);
+ else // must be IsSharedArrayBuffer()
+ blink_buffer = ToDOMSharedArrayBuffer(isolate, v8_buffer);
+ } else {
+ if (LIKELY(v8_buffer->IsArrayBuffer()))
+ blink_buffer = ToDOMArrayBuffer(isolate, v8_buffer);
+ else // must be IsSharedArrayBuffer()
+ return nullptr;
+ }
+
+ DOMViewType* blink_view = Trait::CreateDOMViewType(blink_buffer, v8_view);
+ v8::Local<v8::Object> wrapper = blink_view->AssociateWithWrapper(
+ isolate, blink_view->GetWrapperTypeInfo(), v8_view);
+ DCHECK(wrapper == v8_view);
+ return blink_view;
+}
+
+template <bool allow_shared>
+DOMArrayBufferView* ToDOMArrayBufferView(v8::Isolate* isolate,
+ v8::Local<v8::Value> value) {
+ if (UNLIKELY(!value->IsArrayBufferView()))
+ return nullptr;
+
+ v8::Local<v8::ArrayBufferView> v8_view = value.As<v8::ArrayBufferView>();
+ if (DOMArrayBufferView* blink_view =
+ ToScriptWrappable(v8_view)->template ToImpl<DOMArrayBufferView>()) {
+ return blink_view;
+ }
+
+ if (v8_view->IsInt8Array())
+ return ToDOMViewType<DOMInt8Array, allow_shared>(isolate, value);
+ if (v8_view->IsInt16Array())
+ return ToDOMViewType<DOMInt16Array, allow_shared>(isolate, value);
+ if (v8_view->IsInt32Array())
+ return ToDOMViewType<DOMInt32Array, allow_shared>(isolate, value);
+ if (v8_view->IsUint8Array())
+ return ToDOMViewType<DOMUint8Array, allow_shared>(isolate, value);
+ if (v8_view->IsUint8ClampedArray())
+ return ToDOMViewType<DOMUint8ClampedArray, allow_shared>(isolate, value);
+ if (v8_view->IsUint16Array())
+ return ToDOMViewType<DOMUint16Array, allow_shared>(isolate, value);
+ if (v8_view->IsUint32Array())
+ return ToDOMViewType<DOMUint32Array, allow_shared>(isolate, value);
+ if (v8_view->IsBigInt64Array())
+ return ToDOMViewType<DOMBigInt64Array, allow_shared>(isolate, value);
+ if (v8_view->IsBigUint64Array())
+ return ToDOMViewType<DOMBigUint64Array, allow_shared>(isolate, value);
+ if (v8_view->IsFloat32Array())
+ return ToDOMViewType<DOMFloat32Array, allow_shared>(isolate, value);
+ if (v8_view->IsFloat64Array())
+ return ToDOMViewType<DOMFloat64Array, allow_shared>(isolate, value);
+ if (v8_view->IsDataView())
+ return ToDOMViewType<DOMDataView, allow_shared>(isolate, value);
+
+ NOTREACHED();
+ return nullptr;
+}
+
+template <>
+DOMArrayBufferView* ToDOMViewType<DOMArrayBufferView, kNotShared>(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value) {
+ return ToDOMArrayBufferView<kNotShared>(isolate, value);
+}
+
+template <>
+DOMArrayBufferView* ToDOMViewType<DOMArrayBufferView, kMaybeShared>(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value) {
+ return ToDOMArrayBufferView<kMaybeShared>(isolate, value);
+}
+
+} // namespace
+
+// ArrayBuffer
+
+DOMArrayBuffer* NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::FailedToConvertJSValue("ArrayBuffer"));
+ return nullptr;
+}
+
+DOMArrayBuffer* NativeValueTraits<DOMArrayBuffer>::ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::ArgumentNotOfType(argument_index, "ArrayBuffer"));
+ return nullptr;
+}
+
+// Nullable ArrayBuffer
+
+DOMArrayBuffer* NativeValueTraits<IDLNullable<DOMArrayBuffer>>::NativeValue(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return nullptr;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::FailedToConvertJSValue("ArrayBuffer"));
+ return nullptr;
+}
+
+DOMArrayBuffer* NativeValueTraits<IDLNullable<DOMArrayBuffer>>::ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return nullptr;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::ArgumentNotOfType(argument_index, "ArrayBuffer"));
+ return nullptr;
+}
+
+// SharedArrayBuffer
+
+DOMSharedArrayBuffer* NativeValueTraits<DOMSharedArrayBuffer>::NativeValue(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::FailedToConvertJSValue("SharedArrayBuffer"));
+ return nullptr;
+}
+
+DOMSharedArrayBuffer* NativeValueTraits<DOMSharedArrayBuffer>::ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, "SharedArrayBuffer"));
+ return nullptr;
+}
+
+// Nullable SharedArrayBuffer
+
+DOMSharedArrayBuffer*
+NativeValueTraits<IDLNullable<DOMSharedArrayBuffer>>::NativeValue(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return nullptr;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::FailedToConvertJSValue("SharedArrayBuffer"));
+ return nullptr;
+}
+
+DOMSharedArrayBuffer*
+NativeValueTraits<IDLNullable<DOMSharedArrayBuffer>>::ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return nullptr;
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, "SharedArrayBuffer"));
+ return nullptr;
+}
+
+// [AllowShared] ArrayBuffer
+
+DOMArrayBufferBase* NativeValueTraits<DOMArrayBufferBase>::NativeValue(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::FailedToConvertJSValue("[AllowShared] ArrayBuffer"));
+ return nullptr;
+}
+
+DOMArrayBufferBase* NativeValueTraits<DOMArrayBufferBase>::ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, "[AllowShared] ArrayBuffer"));
+ return nullptr;
+}
+
+// Nullable [AllowShared] ArrayBuffer
+
+DOMArrayBufferBase*
+NativeValueTraits<IDLNullable<DOMArrayBufferBase>>::NativeValue(
+ v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return nullptr;
+
+ exception_state.ThrowTypeError(
+ ExceptionMessages::FailedToConvertJSValue("[AllowShared] ArrayBuffer"));
+ return nullptr;
+}
+
+DOMArrayBufferBase*
+NativeValueTraits<IDLNullable<DOMArrayBufferBase>>::ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
+ if (LIKELY(array_buffer))
+ return array_buffer;
+
+ DOMSharedArrayBuffer* shared_array_buffer =
+ ToDOMSharedArrayBuffer(isolate, value);
+ if (LIKELY(shared_array_buffer))
+ return shared_array_buffer;
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return nullptr;
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, "[AllowShared] ArrayBuffer"));
+ return nullptr;
+}
+
+// ArrayBufferView
+
+template <typename T>
+NotShared<T> NativeValueTraits<
+ NotShared<T>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return NotShared<T>(blink_view);
+
+ if (ABVTrait<T>::IsShared(value)) {
+ exception_state.ThrowTypeError(
+ ExceptionMessages::SharedArrayBufferNotAllowed(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+ }
+
+ exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+}
+
+template <typename T>
+NotShared<T> NativeValueTraits<
+ NotShared<T>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return NotShared<T>(blink_view);
+
+ if (ABVTrait<T>::IsShared(value)) {
+ exception_state.ThrowTypeError(
+ ExceptionMessages::SharedArrayBufferNotAllowed(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+ }
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+}
+
+// [AllowShared] ArrayBufferView
+
+template <typename T>
+MaybeShared<T> NativeValueTraits<
+ MaybeShared<T>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return MaybeShared<T>(blink_view);
+
+ exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return MaybeShared<T>();
+}
+
+template <typename T>
+MaybeShared<T> NativeValueTraits<
+ MaybeShared<T>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return MaybeShared<T>(blink_view);
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, T::GetStaticWrapperTypeInfo()->interface_name));
+ return MaybeShared<T>();
+}
+
+// Nullable ArrayBufferView
+
+template <typename T>
+NotShared<T> NativeValueTraits<
+ IDLNullable<NotShared<T>>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return NotShared<T>(blink_view);
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return NotShared<T>();
+
+ if (ABVTrait<T>::IsShared(value)) {
+ exception_state.ThrowTypeError(
+ ExceptionMessages::SharedArrayBufferNotAllowed(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+ }
+
+ exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+}
+
+template <typename T>
+NotShared<T> NativeValueTraits<
+ IDLNullable<NotShared<T>>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return NotShared<T>(blink_view);
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return NotShared<T>();
+
+ if (ABVTrait<T>::IsShared(value)) {
+ exception_state.ThrowTypeError(
+ ExceptionMessages::SharedArrayBufferNotAllowed(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+ }
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, T::GetStaticWrapperTypeInfo()->interface_name));
+ return NotShared<T>();
+}
+
+// Nullable [AllowShared] ArrayBufferView
+
+template <typename T>
+MaybeShared<T> NativeValueTraits<
+ IDLNullable<MaybeShared<T>>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return MaybeShared<T>(blink_view);
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return MaybeShared<T>();
+
+ exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
+ T::GetStaticWrapperTypeInfo()->interface_name));
+ return MaybeShared<T>();
+}
+
+template <typename T>
+MaybeShared<T> NativeValueTraits<
+ IDLNullable<MaybeShared<T>>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
+ ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
+ if (LIKELY(blink_view))
+ return MaybeShared<T>(blink_view);
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return MaybeShared<T>();
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index, T::GetStaticWrapperTypeInfo()->interface_name));
+ return MaybeShared<T>();
+}
+
+// [AllowShared, FlexibleArrayBufferView] ArrayBufferView
+
+template <typename T>
+T NativeValueTraits<T,
+ typename std::enable_if_t<
+ std::is_base_of<FlexibleArrayBufferView, T>::value>>::
+ ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ if (LIKELY(ABVTrait<T>::IsV8ViewType(value)))
+ return T(value.As<typename ABVTrait<T>::V8ViewType>());
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index,
+ ABVTrait<T>::DOMViewType::GetStaticWrapperTypeInfo()->interface_name));
+ return T();
+}
+
+// Nullable [AllowShared, FlexibleArrayBufferView] ArrayBufferView
+
+template <typename T>
+T NativeValueTraits<IDLNullable<T>,
+ typename std::enable_if_t<
+ std::is_base_of<FlexibleArrayBufferView, T>::value>>::
+ ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ if (LIKELY(ABVTrait<T>::IsV8ViewType(value)))
+ return T(value.As<typename ABVTrait<T>::V8ViewType>());
+
+ if (LIKELY(value->IsNullOrUndefined()))
+ return T();
+
+ exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
+ argument_index,
+ ABVTrait<T>::DOMViewType::GetStaticWrapperTypeInfo()->interface_name));
+ return T();
+}
+
+#define INSTANTIATE_NVT(type) \
+ template struct CORE_EXPORT NativeValueTraits<type>;
+// NotShared<T>
+INSTANTIATE_NVT(NotShared<DOMArrayBufferView>)
+INSTANTIATE_NVT(NotShared<DOMInt8Array>)
+INSTANTIATE_NVT(NotShared<DOMInt16Array>)
+INSTANTIATE_NVT(NotShared<DOMInt32Array>)
+INSTANTIATE_NVT(NotShared<DOMUint8Array>)
+INSTANTIATE_NVT(NotShared<DOMUint8ClampedArray>)
+INSTANTIATE_NVT(NotShared<DOMUint16Array>)
+INSTANTIATE_NVT(NotShared<DOMUint32Array>)
+INSTANTIATE_NVT(NotShared<DOMBigInt64Array>)
+INSTANTIATE_NVT(NotShared<DOMBigUint64Array>)
+INSTANTIATE_NVT(NotShared<DOMFloat32Array>)
+INSTANTIATE_NVT(NotShared<DOMFloat64Array>)
+INSTANTIATE_NVT(NotShared<DOMDataView>)
+// MaybeShared<T>
+INSTANTIATE_NVT(MaybeShared<DOMArrayBufferView>)
+INSTANTIATE_NVT(MaybeShared<DOMInt8Array>)
+INSTANTIATE_NVT(MaybeShared<DOMInt16Array>)
+INSTANTIATE_NVT(MaybeShared<DOMInt32Array>)
+INSTANTIATE_NVT(MaybeShared<DOMUint8Array>)
+INSTANTIATE_NVT(MaybeShared<DOMUint8ClampedArray>)
+INSTANTIATE_NVT(MaybeShared<DOMUint16Array>)
+INSTANTIATE_NVT(MaybeShared<DOMUint32Array>)
+INSTANTIATE_NVT(MaybeShared<DOMBigInt64Array>)
+INSTANTIATE_NVT(MaybeShared<DOMBigUint64Array>)
+INSTANTIATE_NVT(MaybeShared<DOMFloat32Array>)
+INSTANTIATE_NVT(MaybeShared<DOMFloat64Array>)
+INSTANTIATE_NVT(MaybeShared<DOMDataView>)
+// IDLNullable<NotShared<T>>
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMArrayBufferView>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMInt8Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMInt16Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMInt32Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMUint8Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMUint8ClampedArray>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMUint16Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMUint32Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMBigInt64Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMBigUint64Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMFloat32Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMFloat64Array>>)
+INSTANTIATE_NVT(IDLNullable<NotShared<DOMDataView>>)
+// IDLNullable<MaybeShared<T>>
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMArrayBufferView>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMInt8Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMInt16Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMInt32Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMUint8Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMUint8ClampedArray>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMUint16Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMUint32Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMBigInt64Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMBigUint64Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMFloat32Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMFloat64Array>>)
+INSTANTIATE_NVT(IDLNullable<MaybeShared<DOMDataView>>)
+// FlexibleArrayBufferView
+INSTANTIATE_NVT(FlexibleArrayBufferView)
+INSTANTIATE_NVT(FlexibleInt8Array)
+INSTANTIATE_NVT(FlexibleInt16Array)
+INSTANTIATE_NVT(FlexibleInt32Array)
+INSTANTIATE_NVT(FlexibleUint8Array)
+INSTANTIATE_NVT(FlexibleUint8ClampedArray)
+INSTANTIATE_NVT(FlexibleUint16Array)
+INSTANTIATE_NVT(FlexibleUint32Array)
+INSTANTIATE_NVT(FlexibleBigInt64Array)
+INSTANTIATE_NVT(FlexibleBigUint64Array)
+INSTANTIATE_NVT(FlexibleFloat32Array)
+INSTANTIATE_NVT(FlexibleFloat64Array)
+// IDLNullable<FlexibleArrayBufferView>
+INSTANTIATE_NVT(IDLNullable<FlexibleArrayBufferView>)
+INSTANTIATE_NVT(IDLNullable<FlexibleInt8Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleInt16Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleInt32Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleUint8Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleUint8ClampedArray>)
+INSTANTIATE_NVT(IDLNullable<FlexibleUint16Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleUint32Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleBigInt64Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleBigUint64Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleFloat32Array>)
+INSTANTIATE_NVT(IDLNullable<FlexibleFloat64Array>)
+#undef INSTANTIATE_NVT
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.cc b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.cc
index d4a62780e01..e09d565babd 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.cc
@@ -6,22 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler.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_big_int_64_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_big_uint_64_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_data_view.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_float32_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_float64_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_int16_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_int32_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_int8_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint16_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint32_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_clamped_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_xpath_ns_resolver.h"
-#include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
namespace blink {
@@ -55,299 +40,6 @@ void NativeValueTraitsInterfaceNotOfType(
} // namespace bindings
-// Buffer source types
-
-namespace {
-
-enum class IDLBufferSourceTypeConvMode {
- kDefault,
- kNullable,
-};
-
-template <
- typename T,
- typename V8T,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-T* NativeValueTraitsBufferSourcePtrNativeValue(
- v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- T* native_value = V8T::ToImplWithTypeCheck(isolate, value);
- if (native_value)
- return native_value;
-
- if (mode == IDLBufferSourceTypeConvMode::kNullable) {
- if (value->IsNullOrUndefined())
- return nullptr;
- }
-
- exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
- V8T::GetWrapperTypeInfo()->interface_name));
- return nullptr;
-}
-
-template <
- typename T,
- typename V8T,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-T* NativeValueTraitsBufferSourcePtrArgumentValue(
- v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- T* native_value = V8T::ToImplWithTypeCheck(isolate, value);
- if (native_value)
- return native_value;
-
- if (mode == IDLBufferSourceTypeConvMode::kNullable) {
- if (value->IsNullOrUndefined())
- return nullptr;
- }
-
- exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
- argument_index, V8T::GetWrapperTypeInfo()->interface_name));
- return nullptr;
-}
-
-template <
- typename T,
- typename V8T,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-NotShared<T> NativeValueTraitsBufferSourceNotSharedNativeValue(
- v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- T* native_value = NativeValueTraitsBufferSourcePtrNativeValue<T, V8T, mode>(
- isolate, value, exception_state);
- if (!native_value)
- return NotShared<T>();
- if (native_value->IsShared()) {
- exception_state.ThrowTypeError(
- "The provided ArrayBufferView value must not be shared.");
- return NotShared<T>();
- }
- return NotShared<T>(native_value);
-}
-
-template <
- typename T,
- typename V8T,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-NotShared<T> NativeValueTraitsBufferSourceNotSharedArgumentValue(
- v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- T* native_value = NativeValueTraitsBufferSourcePtrArgumentValue<T, V8T, mode>(
- isolate, argument_index, value, exception_state);
- if (!native_value)
- return NotShared<T>();
- if (native_value->IsShared()) {
- exception_state.ThrowTypeError(
- "The provided ArrayBufferView value must not be shared.");
- return NotShared<T>();
- }
- return NotShared<T>(native_value);
-}
-
-template <
- typename T,
- typename V8T,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-MaybeShared<T> NativeValueTraitsBufferSourceMaybeSharedNativeValue(
- v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return MaybeShared<T>(
- NativeValueTraitsBufferSourcePtrNativeValue<T, V8T, mode>(
- isolate, value, exception_state));
-}
-
-template <
- typename T,
- typename V8T,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-MaybeShared<T> NativeValueTraitsBufferSourceMaybeSharedArgumentValue(
- v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return MaybeShared<T>(
- NativeValueTraitsBufferSourcePtrArgumentValue<T, V8T, mode>(
- isolate, argument_index, value, exception_state));
-}
-
-template <
- typename T,
- typename V8T,
- typename FLEXIBLE,
- IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
-FLEXIBLE NativeValueTraitsBufferSourceFlexibleArgumentValue(
- v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- if (V8T::HasInstance(isolate, value))
- return FLEXIBLE(value.As<v8::ArrayBufferView>());
-
- if (mode == IDLBufferSourceTypeConvMode::kNullable) {
- if (value->IsNullOrUndefined())
- return FLEXIBLE();
- }
-
- exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
- argument_index, V8T::GetWrapperTypeInfo()->interface_name));
- return FLEXIBLE();
-}
-
-} // namespace
-
-DOMArrayBuffer* NativeValueTraits<DOMArrayBuffer>::NativeValue(
- v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValueTraitsBufferSourcePtrNativeValue<DOMArrayBuffer,
- V8ArrayBuffer>(
- isolate, value, exception_state);
-}
-
-DOMArrayBuffer* NativeValueTraits<DOMArrayBuffer>::ArgumentValue(
- v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValueTraitsBufferSourcePtrArgumentValue<DOMArrayBuffer,
- V8ArrayBuffer>(
- isolate, argument_index, value, exception_state);
-}
-
-DOMArrayBuffer* NativeValueTraits<IDLNullable<DOMArrayBuffer>>::NativeValue(
- v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValueTraitsBufferSourcePtrNativeValue<
- DOMArrayBuffer, V8ArrayBuffer, IDLBufferSourceTypeConvMode::kNullable>(
- isolate, value, exception_state);
-}
-
-DOMArrayBuffer* NativeValueTraits<IDLNullable<DOMArrayBuffer>>::ArgumentValue(
- v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValueTraitsBufferSourcePtrArgumentValue<
- DOMArrayBuffer, V8ArrayBuffer, IDLBufferSourceTypeConvMode::kNullable>(
- isolate, argument_index, value, exception_state);
-}
-
-#define DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_NOT_SHARED(T, V8T) \
- template <> \
- CORE_EXPORT NotShared<T> NativeValueTraits<NotShared<T>>::NativeValue( \
- v8::Isolate* isolate, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceNotSharedNativeValue<T, V8T>( \
- isolate, value, exception_state); \
- } \
- template <> \
- CORE_EXPORT NotShared<T> NativeValueTraits<NotShared<T>>::ArgumentValue( \
- v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceNotSharedArgumentValue<T, V8T>( \
- isolate, argument_index, value, exception_state); \
- } \
- template <> \
- CORE_EXPORT NotShared<T> \
- NativeValueTraits<IDLNullable<NotShared<T>>>::NativeValue( \
- v8::Isolate* isolate, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceNotSharedNativeValue< \
- T, V8T, IDLBufferSourceTypeConvMode::kNullable>(isolate, value, \
- exception_state); \
- } \
- template <> \
- CORE_EXPORT NotShared<T> \
- NativeValueTraits<IDLNullable<NotShared<T>>>::ArgumentValue( \
- v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceNotSharedArgumentValue< \
- T, V8T, IDLBufferSourceTypeConvMode::kNullable>( \
- isolate, argument_index, value, exception_state); \
- }
-#define DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_MAYBE_SHARED(T, V8T) \
- template <> \
- CORE_EXPORT MaybeShared<T> NativeValueTraits<MaybeShared<T>>::NativeValue( \
- v8::Isolate* isolate, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceMaybeSharedNativeValue<T, V8T>( \
- isolate, value, exception_state); \
- } \
- template <> \
- CORE_EXPORT MaybeShared<T> NativeValueTraits<MaybeShared<T>>::ArgumentValue( \
- v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceMaybeSharedArgumentValue<T, V8T>( \
- isolate, argument_index, value, exception_state); \
- } \
- template <> \
- CORE_EXPORT MaybeShared<T> \
- NativeValueTraits<IDLNullable<MaybeShared<T>>>::NativeValue( \
- v8::Isolate* isolate, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceMaybeSharedNativeValue< \
- T, V8T, IDLBufferSourceTypeConvMode::kNullable>(isolate, value, \
- exception_state); \
- } \
- template <> \
- CORE_EXPORT MaybeShared<T> \
- NativeValueTraits<IDLNullable<MaybeShared<T>>>::ArgumentValue( \
- v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceMaybeSharedArgumentValue< \
- T, V8T, IDLBufferSourceTypeConvMode::kNullable>( \
- isolate, argument_index, value, exception_state); \
- }
-#define DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_FLEXIBLE(T, V8T, \
- FLEXIBLE) \
- template <> \
- CORE_EXPORT FLEXIBLE NativeValueTraits<FLEXIBLE>::ArgumentValue( \
- v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceFlexibleArgumentValue<T, V8T, \
- FLEXIBLE>( \
- isolate, argument_index, value, exception_state); \
- } \
- template <> \
- CORE_EXPORT FLEXIBLE \
- NativeValueTraits<IDLNullable<FLEXIBLE>>::ArgumentValue( \
- v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
- ExceptionState& exception_state) { \
- return NativeValueTraitsBufferSourceFlexibleArgumentValue< \
- T, V8T, FLEXIBLE, IDLBufferSourceTypeConvMode::kNullable>( \
- isolate, argument_index, value, exception_state); \
- }
-#define DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(T) \
- DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_NOT_SHARED(DOM##T, V8##T) \
- DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_MAYBE_SHARED(DOM##T, V8##T) \
- DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_FLEXIBLE(DOM##T, V8##T, \
- Flexible##T)
-#define DEFINE_NATIVE_VALUE_TRAITS_DATA_VIEW(T) \
- DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_NOT_SHARED(DOM##T, V8##T) \
- DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_MAYBE_SHARED(DOM##T, V8##T)
-
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(ArrayBufferView)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Int8Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Int16Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Int32Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint8Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint8ClampedArray)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint16Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint32Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(BigInt64Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(BigUint64Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Float32Array)
-DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Float64Array)
-DEFINE_NATIVE_VALUE_TRAITS_DATA_VIEW(DataView)
-
// EventHandler
EventListener* NativeValueTraits<IDLEventHandler>::NativeValue(
v8::Isolate* isolate,
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 d55c9e20475..38b9b7cfec6 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_IMPL_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#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_iterator.h"
@@ -66,7 +67,7 @@ struct NativeValueTraits<IDLNullable<IDLAny>>;
template <>
struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLAny>>
- : public NativeValueTraitsBase<IDLAny> {
+ : public NativeValueTraitsBase<IDLOptional<IDLAny>> {
static ScriptValue NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
@@ -87,7 +88,7 @@ struct CORE_EXPORT NativeValueTraits<IDLBoolean>
template <>
struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLBoolean>>
- : public NativeValueTraitsBase<IDLBoolean> {
+ : public NativeValueTraitsBase<IDLOptional<IDLBoolean>> {
static bool NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
@@ -160,132 +161,6 @@ struct CORE_EXPORT NativeValueTraits<IDLUnrestrictedFloat>
};
// Strings
-template <V8StringResourceMode mode>
-struct NativeValueTraits<IDLByteStringBase<mode>>
- : public NativeValueTraitsBase<IDLByteStringBase<mode>> {
- // http://heycam.github.io/webidl/#es-ByteString
- static String NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- V8StringResource<mode> string_resource(value);
- // 1. Let x be ToString(v)
- if (!string_resource.Prepare(isolate, exception_state))
- return String();
- String x = string_resource;
- // 2. If the value of any element of x is greater than 255, then throw a
- // TypeError.
- if (!x.ContainsOnlyLatin1OrEmpty()) {
- exception_state.ThrowTypeError("Value is not a valid ByteString.");
- return String();
- }
-
- // 3. Return an IDL ByteString value whose length is the length of x, and
- // where the value of each element is the value of the corresponding
- // element of x.
- // Blink: A ByteString is simply a String with a range constrained per
- // the above, so this is the identity operation.
- return x;
- }
-};
-
-template <V8StringResourceMode mode>
-struct NativeValueTraits<IDLStringBase<mode>>
- : public NativeValueTraitsBase<IDLStringBase<mode>> {
- // https://heycam.github.io/webidl/#es-DOMString
- static String NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- V8StringResource<mode> string(value);
- if (!string.Prepare(isolate, exception_state))
- return String();
- return string;
- }
-};
-
-template <V8StringResourceMode mode>
-struct NativeValueTraits<IDLStringStringContextTrustedHTMLBase<mode>>
- : public NativeValueTraitsBase<
- IDLStringStringContextTrustedHTMLBase<mode>> {
- static String NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state,
- ExecutionContext* execution_context) {
- if (V8TrustedHTML::HasInstance(value, isolate)) {
- TrustedHTML* trusted_value =
- V8TrustedHTML::ToImpl(v8::Local<v8::Object>::Cast(value));
- return trusted_value->toString();
- } else {
- V8StringResource<mode> string(value);
- if (!string.Prepare(isolate, exception_state))
- return String();
- return TrustedTypesCheckForHTML(string, execution_context,
- exception_state);
- }
- }
-};
-
-template <V8StringResourceMode mode>
-struct NativeValueTraits<IDLStringStringContextTrustedScriptBase<mode>>
- : public NativeValueTraitsBase<
- IDLStringStringContextTrustedScriptBase<mode>> {
- static String NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state,
- ExecutionContext* execution_context) {
- if (V8TrustedScript::HasInstance(value, isolate)) {
- TrustedScript* trusted_value =
- V8TrustedScript::ToImpl(v8::Local<v8::Object>::Cast(value));
- return trusted_value->toString();
- } else {
- V8StringResource<mode> string(value);
- if (!string.Prepare(isolate, exception_state))
- return String();
- return TrustedTypesCheckForScript(string, execution_context,
- exception_state);
- }
- }
-};
-
-template <V8StringResourceMode mode>
-struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBase<mode>>
- : public NativeValueTraitsBase<
- IDLUSVStringStringContextTrustedScriptURLBase<mode>> {
- static String NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state,
- ExecutionContext* execution_context) {
- if (V8TrustedScriptURL::HasInstance(value, isolate)) {
- TrustedScriptURL* trusted_value =
- V8TrustedScriptURL::ToImpl(v8::Local<v8::Object>::Cast(value));
- return trusted_value->toString();
- } else {
- V8StringResource<mode> string(value);
- if (!string.Prepare(isolate, exception_state))
- return String();
- return TrustedTypesCheckForScriptURL(string, execution_context,
- exception_state);
- }
- }
-};
-
-template <V8StringResourceMode mode>
-struct NativeValueTraits<IDLUSVStringBase<mode>>
- : public NativeValueTraitsBase<IDLUSVStringBase<mode>> {
- // http://heycam.github.io/webidl/#es-USVString
- static String NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- // 1. Let string be the result of converting V to a DOMString.
- V8StringResource<mode> string(value);
- if (!string.Prepare(isolate, exception_state))
- return String();
- // 2. Return an IDL USVString value that is the result of converting string
- // to a sequence of Unicode scalar values.
- return ReplaceUnmatchedSurrogates(string);
- }
-};
-
-// Strings for the new bindings generator
namespace bindings {
@@ -363,8 +238,8 @@ class CORE_EXPORT NativeValueTraitsStringAdapter {
} // namespace bindings
template <bindings::IDLStringConvMode mode>
-struct NativeValueTraits<IDLByteStringBaseV2<mode>>
- : public NativeValueTraitsBase<IDLByteStringBaseV2<mode>> {
+struct NativeValueTraits<IDLByteStringBase<mode>>
+ : public NativeValueTraitsBase<IDLByteStringBase<mode>> {
// http://heycam.github.io/webidl/#es-ByteString
static bindings::NativeValueTraitsStringAdapter NativeValue(
v8::Isolate* isolate,
@@ -398,33 +273,33 @@ struct NativeValueTraits<IDLByteStringBaseV2<mode>>
};
template <>
-struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLByteStringV2>>
- : public NativeValueTraitsBase<IDLNullable<IDLByteStringV2>> {
+struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLByteString>>
+ : public NativeValueTraitsBase<IDLNullable<IDLByteString>> {
static decltype(auto) NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
- return NativeValueTraits<IDLByteStringBaseV2<
+ return NativeValueTraits<IDLByteStringBase<
bindings::IDLStringConvMode::kNullable>>::NativeValue(isolate, value,
exception_state);
}
};
template <>
-struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLByteStringV2>>
- : public NativeValueTraitsBase<IDLByteStringV2> {
+struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLByteString>>
+ : public NativeValueTraitsBase<IDLOptional<IDLByteString>> {
static decltype(auto) NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (value->IsUndefined())
return bindings::NativeValueTraitsStringAdapter();
- return NativeValueTraits<IDLByteStringV2>::NativeValue(isolate, value,
- exception_state);
+ return NativeValueTraits<IDLByteString>::NativeValue(isolate, value,
+ exception_state);
}
};
template <bindings::IDLStringConvMode mode>
-struct NativeValueTraits<IDLStringBaseV2<mode>>
- : public NativeValueTraitsBase<IDLStringBaseV2<mode>> {
+struct NativeValueTraits<IDLStringBase<mode>>
+ : public NativeValueTraitsBase<IDLStringBase<mode>> {
// https://heycam.github.io/webidl/#es-DOMString
static bindings::NativeValueTraitsStringAdapter NativeValue(
v8::Isolate* isolate,
@@ -457,39 +332,39 @@ struct NativeValueTraits<IDLStringBaseV2<mode>>
};
template <>
-struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLStringV2>>
- : public NativeValueTraitsBase<IDLNullable<IDLStringV2>> {
+struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLString>>
+ : public NativeValueTraitsBase<IDLNullable<IDLString>> {
static decltype(auto) NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
- return NativeValueTraits<IDLStringBaseV2<
+ return NativeValueTraits<IDLStringBase<
bindings::IDLStringConvMode::kNullable>>::NativeValue(isolate, value,
exception_state);
}
};
template <>
-struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLStringV2>>
- : public NativeValueTraitsBase<IDLStringV2> {
+struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLString>>
+ : public NativeValueTraitsBase<IDLOptional<IDLString>> {
static decltype(auto) NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (value->IsUndefined())
return bindings::NativeValueTraitsStringAdapter();
- return NativeValueTraits<IDLStringV2>::NativeValue(isolate, value,
- exception_state);
+ return NativeValueTraits<IDLString>::NativeValue(isolate, value,
+ exception_state);
}
};
template <bindings::IDLStringConvMode mode>
-struct NativeValueTraits<IDLUSVStringBaseV2<mode>>
- : public NativeValueTraitsBase<IDLUSVStringBaseV2<mode>> {
+struct NativeValueTraits<IDLUSVStringBase<mode>>
+ : public NativeValueTraitsBase<IDLUSVStringBase<mode>> {
// http://heycam.github.io/webidl/#es-USVString
static bindings::NativeValueTraitsStringAdapter NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
- String string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue(
+ String string = NativeValueTraits<IDLStringBase<mode>>::NativeValue(
isolate, value, exception_state);
if (exception_state.HadException())
return bindings::NativeValueTraitsStringAdapter();
@@ -500,34 +375,34 @@ struct NativeValueTraits<IDLUSVStringBaseV2<mode>>
};
template <>
-struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLUSVStringV2>>
- : public NativeValueTraitsBase<IDLNullable<IDLUSVStringV2>> {
+struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLUSVString>>
+ : public NativeValueTraitsBase<IDLNullable<IDLUSVString>> {
static decltype(auto) NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
- return NativeValueTraits<IDLUSVStringBaseV2<
+ return NativeValueTraits<IDLUSVStringBase<
bindings::IDLStringConvMode::kNullable>>::NativeValue(isolate, value,
exception_state);
}
};
template <>
-struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLUSVStringV2>>
- : public NativeValueTraitsBase<IDLUSVStringV2> {
+struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLUSVString>>
+ : public NativeValueTraitsBase<IDLOptional<IDLUSVString>> {
static decltype(auto) NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (value->IsUndefined())
return bindings::NativeValueTraitsStringAdapter();
- return NativeValueTraits<IDLUSVStringV2>::NativeValue(isolate, value,
- exception_state);
+ return NativeValueTraits<IDLUSVString>::NativeValue(isolate, value,
+ exception_state);
}
};
template <bindings::IDLStringConvMode mode>
-struct NativeValueTraits<IDLStringStringContextTrustedHTMLBaseV2<mode>>
+struct NativeValueTraits<IDLStringStringContextTrustedHTMLBase<mode>>
: public NativeValueTraitsBase<
- IDLStringStringContextTrustedHTMLBaseV2<mode>> {
+ IDLStringStringContextTrustedHTMLBase<mode>> {
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state,
@@ -537,7 +412,7 @@ struct NativeValueTraits<IDLStringStringContextTrustedHTMLBaseV2<mode>>
return trusted_html->toString();
}
- auto&& string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue(
+ auto&& string = NativeValueTraits<IDLStringBase<mode>>::NativeValue(
isolate, value, exception_state);
if (exception_state.HadException())
return String();
@@ -547,23 +422,23 @@ struct NativeValueTraits<IDLStringStringContextTrustedHTMLBaseV2<mode>>
template <>
struct CORE_EXPORT
- NativeValueTraits<IDLNullable<IDLStringStringContextTrustedHTMLV2>>
+ NativeValueTraits<IDLNullable<IDLStringStringContextTrustedHTML>>
: public NativeValueTraitsBase<
- IDLNullable<IDLStringStringContextTrustedHTMLV2>> {
+ IDLNullable<IDLStringStringContextTrustedHTML>> {
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state,
ExecutionContext* execution_context) {
- return NativeValueTraits<IDLStringStringContextTrustedHTMLBaseV2<
+ return NativeValueTraits<IDLStringStringContextTrustedHTMLBase<
bindings::IDLStringConvMode::kNullable>>::
NativeValue(isolate, value, exception_state, execution_context);
}
};
template <bindings::IDLStringConvMode mode>
-struct NativeValueTraits<IDLStringStringContextTrustedScriptBaseV2<mode>>
+struct NativeValueTraits<IDLStringStringContextTrustedScriptBase<mode>>
: public NativeValueTraitsBase<
- IDLStringStringContextTrustedScriptBaseV2<mode>> {
+ IDLStringStringContextTrustedScriptBase<mode>> {
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state,
@@ -573,7 +448,7 @@ struct NativeValueTraits<IDLStringStringContextTrustedScriptBaseV2<mode>>
return trusted_script->toString();
}
- auto&& string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue(
+ auto&& string = NativeValueTraits<IDLStringBase<mode>>::NativeValue(
isolate, value, exception_state);
if (exception_state.HadException())
return String();
@@ -584,23 +459,23 @@ struct NativeValueTraits<IDLStringStringContextTrustedScriptBaseV2<mode>>
template <>
struct CORE_EXPORT
- NativeValueTraits<IDLNullable<IDLStringStringContextTrustedScriptV2>>
+ NativeValueTraits<IDLNullable<IDLStringStringContextTrustedScript>>
: public NativeValueTraitsBase<
- IDLNullable<IDLStringStringContextTrustedScriptV2>> {
+ IDLNullable<IDLStringStringContextTrustedScript>> {
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state,
ExecutionContext* execution_context) {
- return NativeValueTraits<IDLStringStringContextTrustedScriptBaseV2<
+ return NativeValueTraits<IDLStringStringContextTrustedScriptBase<
bindings::IDLStringConvMode::kNullable>>::
NativeValue(isolate, value, exception_state, execution_context);
}
};
template <bindings::IDLStringConvMode mode>
-struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBaseV2<mode>>
+struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBase<mode>>
: public NativeValueTraitsBase<
- IDLUSVStringStringContextTrustedScriptURLBaseV2<mode>> {
+ IDLUSVStringStringContextTrustedScriptURLBase<mode>> {
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state,
@@ -610,7 +485,7 @@ struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBaseV2<mode>>
return trusted_script_url->toString();
}
- auto&& string = NativeValueTraits<IDLUSVStringBaseV2<mode>>::NativeValue(
+ auto&& string = NativeValueTraits<IDLUSVStringBase<mode>>::NativeValue(
isolate, value, exception_state);
if (exception_state.HadException())
return String();
@@ -621,14 +496,14 @@ struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBaseV2<mode>>
template <>
struct CORE_EXPORT
- NativeValueTraits<IDLNullable<IDLUSVStringStringContextTrustedScriptURLV2>>
+ NativeValueTraits<IDLNullable<IDLUSVStringStringContextTrustedScriptURL>>
: public NativeValueTraitsBase<
- IDLNullable<IDLUSVStringStringContextTrustedScriptURLV2>> {
+ IDLNullable<IDLUSVStringStringContextTrustedScriptURL>> {
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state,
ExecutionContext* execution_context) {
- return NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBaseV2<
+ return NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBase<
bindings::IDLStringConvMode::kNullable>>::
NativeValue(isolate, value, exception_state, execution_context);
}
@@ -661,6 +536,89 @@ struct CORE_EXPORT NativeValueTraits<IDLNullable<DOMArrayBuffer>>
ExceptionState& exception_state);
};
+template <>
+struct CORE_EXPORT NativeValueTraits<DOMSharedArrayBuffer>
+ : public NativeValueTraitsBase<DOMSharedArrayBuffer*> {
+ static DOMSharedArrayBuffer* NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+
+ static DOMSharedArrayBuffer* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+};
+
+template <>
+struct CORE_EXPORT NativeValueTraits<IDLNullable<DOMSharedArrayBuffer>>
+ : public NativeValueTraitsBase<DOMSharedArrayBuffer*> {
+ static DOMSharedArrayBuffer* NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+
+ static DOMSharedArrayBuffer* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+};
+
+// DOMArrayBufferBase is the common base class of DOMArrayBuffer and
+// DOMSharedArrayBuffer, so it behaves as "[AllowShared] ArrayBuffer" in
+// Web IDL.
+template <>
+struct CORE_EXPORT NativeValueTraits<DOMArrayBufferBase>
+ : public NativeValueTraitsBase<DOMArrayBufferBase*> {
+ static DOMArrayBufferBase* NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+
+ static DOMArrayBufferBase* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+};
+
+template <>
+struct CORE_EXPORT NativeValueTraits<IDLNullable<DOMArrayBufferBase>>
+ : public NativeValueTraitsBase<DOMArrayBufferBase*> {
+ static DOMArrayBufferBase* NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+
+ static DOMArrayBufferBase* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state);
+};
+
+template <typename T>
+struct NativeValueTraits<
+ T,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> {
+ // NotShared<T> or MaybeShared<T> should be used instead.
+ static T* NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) = delete;
+ static T* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) = delete;
+};
+
+template <typename T>
+struct NativeValueTraits<
+ IDLNullable<T>,
+ typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> {
+ // NotShared<T> or MaybeShared<T> should be used instead.
+ static T* NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) = delete;
+ static T* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) = delete;
+};
+
template <typename T>
struct NativeValueTraits<
NotShared<T>,
@@ -906,12 +864,37 @@ CreateIDLSequenceFromIterator(v8::Isolate* isolate,
} // namespace bindings
+// IDLSequence's implementation is a little tricky due to a historical reason.
+// The following type mapping is used for IDLSequence and its variants.
+//
+// tl;dr: Only IDLNullable<IDLSequence<traceable_type>> is a reference type.
+// The others are value types.
+//
+// - IDLSequence<T> where T is not traceable
+// => Vector<T> as a value type
+// - IDLSequence<T> where T is traceable
+// => HeapVector<T> as a value type despite that HeapVector is
+// GarbageCollected because HeapVector had been implemented as a non-GC
+// type (a value type) for years until 2021 January. This point is very
+// inconsistent but kept unchanged so far.
+// - IDLNullable<IDLSequence<T>> where T is not traceable
+// => absl::optional<Vector<T>> as a value type
+// - IDLNullable<IDLSequence<T>> where T is traceable
+// => HeapVector<T>* as a reference type. absl::optional<HeapVector<T>> is
+// not an option because it's not appropriately traceable despite that
+// the content HeapVector needs tracing. As same as other
+// GarbageCollected types, pointer type is used to represent IDL nullable
+// type.
template <typename T>
struct NativeValueTraits<IDLSequence<T>>
: public NativeValueTraitsBase<IDLSequence<T>> {
// Nondependent types need to be explicitly qualified to be accessible.
using typename NativeValueTraitsBase<IDLSequence<T>>::ImplType;
+ // HeapVector is GarbageCollected, so HeapVector<T>* is used for IDLNullable
+ // while absl::optional<Vector<T>> is used for IDLNullable<Vector<T>>.
+ static constexpr bool has_null_value = WTF::IsTraceable<T>::value;
+
// https://heycam.github.io/webidl/#es-sequence
static ImplType NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
@@ -963,8 +946,47 @@ struct NativeValueTraits<IDLSequence<T>>
};
template <typename T>
+struct NativeValueTraits<IDLNullable<IDLSequence<T>>,
+ typename std::enable_if_t<
+ NativeValueTraits<IDLSequence<T>>::has_null_value>>
+ : public NativeValueTraitsBase<HeapVector<AddMemberIfNeeded<T>>*> {
+ using ImplType = typename NativeValueTraits<IDLSequence<T>>::ImplType*;
+
+ static ImplType NativeValue(v8::Isolate* isolate,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ if (value->IsNullOrUndefined())
+ return nullptr;
+
+ auto on_stack = NativeValueTraits<IDLSequence<T>>::NativeValue(
+ isolate, value, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ auto* on_heap = MakeGarbageCollected<HeapVector<AddMemberIfNeeded<T>>>();
+ on_heap->swap(on_stack);
+ return on_heap;
+ }
+
+ static ImplType ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ if (value->IsNullOrUndefined())
+ return nullptr;
+
+ auto on_stack = NativeValueTraits<IDLSequence<T>>::ArgumentValue(
+ isolate, argument_index, value, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ auto* on_heap = MakeGarbageCollected<HeapVector<AddMemberIfNeeded<T>>>();
+ on_heap->swap(on_stack);
+ return on_heap;
+ }
+};
+
+template <typename T>
struct NativeValueTraits<IDLOptional<IDLSequence<T>>>
- : public NativeValueTraitsBase<IDLSequence<T>> {
+ : public NativeValueTraitsBase<IDLOptional<IDLSequence<T>>> {
static typename NativeValueTraits<IDLSequence<T>>::ImplType NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
@@ -974,6 +996,17 @@ struct NativeValueTraits<IDLOptional<IDLSequence<T>>>
return NativeValueTraits<IDLSequence<T>>::NativeValue(isolate, value,
exception_state);
}
+
+ static typename NativeValueTraits<IDLSequence<T>>::ImplType ArgumentValue(
+ v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ if (value->IsUndefined())
+ return {};
+ return NativeValueTraits<IDLSequence<T>>::ArgumentValue(
+ isolate, argument_index, value, exception_state);
+ }
};
// Frozen array types
@@ -981,6 +1014,12 @@ template <typename T>
struct NativeValueTraits<IDLArray<T>>
: public NativeValueTraits<IDLSequence<T>> {};
+template <typename T>
+struct NativeValueTraits<IDLNullable<IDLArray<T>>,
+ typename std::enable_if_t<
+ NativeValueTraits<IDLSequence<T>>::has_null_value>>
+ : public NativeValueTraits<IDLNullable<IDLSequence<T>>> {};
+
// Record types
template <typename K, typename V>
struct NativeValueTraits<IDLRecord<K, V>>
@@ -1341,6 +1380,13 @@ struct NativeValueTraits<
ExceptionState& exception_state) {
return T::Create(isolate, value, exception_state);
}
+
+ static T* ArgumentValue(v8::Isolate* isolate,
+ int argument_index,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ return T::Create(isolate, value, exception_state);
+ }
};
template <typename T>
@@ -1366,109 +1412,6 @@ struct NativeValueTraits<
}
};
-// Migration Adapters: union types generated by the old bindings generator.
-template <typename T>
-struct NativeValueTraits<IDLUnionNotINT<T>> : public NativeValueTraitsBase<T> {
- static T NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- T impl;
- V8TypeOf<T>::Type::ToImpl(isolate, value, impl,
- UnionTypeConversionMode::kNotNullable,
- exception_state);
- return impl;
- }
-
- static T ArgumentValue(v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValue(isolate, value, exception_state);
- }
-};
-
-template <typename T>
-struct NativeValueTraits<IDLUnionINT<T>> : public NativeValueTraitsBase<T> {
- static T NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- T impl;
- V8TypeOf<T>::Type::ToImpl(isolate, value, impl,
- UnionTypeConversionMode::kNullable,
- exception_state);
- return impl;
- }
-
- static T ArgumentValue(v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValue(isolate, value, exception_state);
- }
-};
-
-template <typename T>
-struct NativeValueTraits<IDLNullable<IDLUnionNotINT<T>>>
- : public NativeValueTraitsBase<T> {
- static T NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- if (value->IsNullOrUndefined())
- return T();
- return NativeValueTraits<IDLUnionNotINT<T>>::NativeValue(isolate, value,
- exception_state);
- }
-
- static T ArgumentValue(v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValue(isolate, value, exception_state);
- }
-};
-
-// IDLNullable<IDLUnionINT<T>> must not be used.
-template <typename T>
-struct NativeValueTraits<IDLNullable<IDLUnionINT<T>>>;
-
-template <typename T>
-struct NativeValueTraits<IDLOptional<IDLUnionNotINT<T>>>
- : public NativeValueTraitsBase<T> {
- static T NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- if (value->IsUndefined())
- return T();
- return NativeValueTraits<IDLUnionNotINT<T>>::NativeValue(isolate, value,
- exception_state);
- }
-
- static T ArgumentValue(v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValue(isolate, value, exception_state);
- }
-};
-
-template <typename T>
-struct NativeValueTraits<IDLOptional<IDLUnionINT<T>>>
- : public NativeValueTraitsBase<T> {
- static T NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValueTraits<IDLUnionINT<T>>::NativeValue(isolate, value,
- exception_state);
- }
-
- static T ArgumentValue(v8::Isolate* isolate,
- int argument_index,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- return NativeValue(isolate, value, exception_state);
- }
-};
-
// Nullable types
template <typename InnerType>
struct NativeValueTraits<
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.cc
index eebc10d9ef2..66f6ccaec68 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.cc
@@ -73,15 +73,8 @@ absl::optional<wtf_size_t> ProfilerTraceBuilder::GetOrInsertStackId(
if (!node)
return absl::optional<wtf_size_t>();
- // Omit frames that don't pass a cross-origin check.
- // Do this at the stack level (rather than the frame level) to avoid
- // including skeleton frames without data.
- KURL resource_url(node->GetScriptResourceNameStr());
- if (!ShouldIncludeStackFrame(resource_url, node->GetScriptId(),
- node->GetSourceType(),
- node->IsScriptSharedCrossOrigin())) {
+ if (!ShouldIncludeStackFrame(node))
return GetOrInsertStackId(node->GetParent());
- }
auto existing_stack_id = node_to_stack_map_.find(node);
if (existing_stack_id != node_to_stack_map_.end()) {
@@ -155,22 +148,31 @@ ProfilerTrace* ProfilerTraceBuilder::GetTrace() const {
}
bool ProfilerTraceBuilder::ShouldIncludeStackFrame(
- const KURL& script_url,
- int script_id,
- v8::CpuProfileNode::SourceType source_type,
- bool script_shared_cross_origin) {
+ const v8::CpuProfileNode* node) {
+ DCHECK(node);
+
// Omit V8 metadata frames.
+ const v8::CpuProfileNode::SourceType source_type = node->GetSourceType();
if (source_type != v8::CpuProfileNode::kScript &&
source_type != v8::CpuProfileNode::kBuiltin &&
source_type != v8::CpuProfileNode::kCallback) {
return false;
}
- // If we couldn't derive script data, only allow builtins and callbacks.
- if (script_id == v8::UnboundScript::kNoScriptId) {
- return source_type == v8::CpuProfileNode::kBuiltin ||
- source_type == v8::CpuProfileNode::kCallback;
+ // Attempt to attribute each stack frame to a script.
+ // - For JS functions, this is their own script.
+ // - For builtins, this is the first attributable caller script.
+ const v8::CpuProfileNode* resource_node = node;
+ if (source_type != v8::CpuProfileNode::kScript) {
+ while (resource_node &&
+ resource_node->GetScriptId() == v8::UnboundScript::kNoScriptId) {
+ resource_node = resource_node->GetParent();
+ }
}
+ if (!resource_node)
+ return false;
+
+ int script_id = resource_node->GetScriptId();
// If we already tested whether or not this script was cross-origin, return
// the cached results.
@@ -178,13 +180,16 @@ bool ProfilerTraceBuilder::ShouldIncludeStackFrame(
if (it != script_same_origin_cache_.end())
return it->value;
- if (!script_url.IsValid())
+ KURL resource_url(resource_node->GetScriptResourceNameStr());
+ if (!resource_url.IsValid())
return false;
- auto origin = SecurityOrigin::Create(script_url);
- // TODO(acomminos): Consider easing this check based on optional headers.
- bool allowed =
- script_shared_cross_origin || origin->IsSameOriginWith(allowed_origin_);
+ auto origin = SecurityOrigin::Create(resource_url);
+ // Omit frames that don't pass a cross-origin check.
+ // Do this at the stack level (rather than the frame level) to avoid
+ // including skeleton frames without data.
+ bool allowed = resource_node->IsScriptSharedCrossOrigin() ||
+ origin->IsSameOriginWith(allowed_origin_);
script_same_origin_cache_.Set(script_id, allowed);
return allowed;
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h b/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h
index 91ac86f0fb1..5bacc49243d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h
@@ -99,10 +99,7 @@ class ProfilerTraceBuilder final
// Discards metadata frames and performs an origin check on the given stack
// frame, returning true if it either has the same origin as the profiler, or
// if it should be shared cross origin.
- bool ShouldIncludeStackFrame(const KURL& script_url,
- int script_id,
- v8::CpuProfileNode::SourceType source_type,
- bool script_shared_cross_origin);
+ bool ShouldIncludeStackFrame(const v8::CpuProfileNode* node);
Member<ScriptState> script_state_;
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 4a3b3807462..53f444e271e 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
@@ -18,17 +18,50 @@ enum HostDefinedOptionsIndex : size_t {
kNonce,
kParserState,
kReferrerPolicy,
- kBaseUrlSource,
kLength
};
+// Omit storing base URL if it is same as ScriptOrigin::ResourceName().
+// Note: This improves chance of getting into a fast path in
+// ReferrerScriptInfo::ToV8HostDefinedOptions.
+KURL GetStoredBaseUrl(const ReferrerScriptInfo& referrer_info,
+ const KURL& script_origin_resource_name) {
+ if (referrer_info.BaseURL() == script_origin_resource_name)
+ return KURL();
+
+ // TODO(https://crbug.com/1235202): Currently when either `base_url_` is
+ // `script_origin_resource_name` or null URL, they both result in
+ // `script_origin_resource_name` in FromV8HostDefinedOptions(). Subsequent
+ // CLs will fix this issue.
+ if (referrer_info.BaseURL().IsNull())
+ return KURL();
+
+ return referrer_info.BaseURL();
+}
+
} // namespace
+bool ReferrerScriptInfo::IsDefaultValue(
+ const KURL& script_origin_resource_name) const {
+ // TODO(https://crbug.com/1235205): `referrer_policy_` should be checked.
+ return GetStoredBaseUrl(*this, script_origin_resource_name).IsNull() &&
+ credentials_mode_ == network::mojom::CredentialsMode::kSameOrigin &&
+ nonce_.IsEmpty() && parser_state_ == kNotParserInserted;
+}
+
ReferrerScriptInfo ReferrerScriptInfo::FromV8HostDefinedOptions(
v8::Local<v8::Context> context,
- v8::Local<v8::PrimitiveArray> host_defined_options) {
+ v8::Local<v8::PrimitiveArray> host_defined_options,
+ const KURL& script_origin_resource_name) {
if (host_defined_options.IsEmpty() || !host_defined_options->Length()) {
- return ReferrerScriptInfo();
+ // Default value. As base URL is null, defer to
+ // `script_origin_resource_name`.
+ ReferrerScriptInfo referrer_info(
+ script_origin_resource_name,
+ network::mojom::CredentialsMode::kSameOrigin, String(),
+ kNotParserInserted, network::mojom::ReferrerPolicy::kDefault);
+ DCHECK(referrer_info.IsDefaultValue(script_origin_resource_name));
+ return referrer_info;
}
v8::Isolate* isolate = context->GetIsolate();
@@ -39,6 +72,10 @@ ReferrerScriptInfo ReferrerScriptInfo::FromV8HostDefinedOptions(
ToCoreString(v8::Local<v8::String>::Cast(base_url_value));
KURL base_url = base_url_string.IsEmpty() ? KURL() : KURL(base_url_string);
DCHECK(base_url.IsNull() || base_url.IsValid());
+ if (base_url.IsNull()) {
+ // If base URL is null, defer to `script_origin_resource_name`.
+ base_url = script_origin_resource_name;
+ }
v8::Local<v8::Primitive> credentials_mode_value =
host_defined_options->Get(isolate, kCredentialsMode);
@@ -67,24 +104,22 @@ ReferrerScriptInfo ReferrerScriptInfo::FromV8HostDefinedOptions(
referrer_policy_int32)
.value_or(network::mojom::ReferrerPolicy::kDefault);
- v8::Local<v8::Primitive> base_url_source_value =
- host_defined_options->Get(isolate, kBaseUrlSource);
- SECURITY_CHECK(base_url_source_value->IsUint32());
- BaseUrlSource base_url_source = static_cast<BaseUrlSource>(
- base_url_source_value->IntegerValue(context).ToChecked());
-
return ReferrerScriptInfo(base_url, credentials_mode, nonce, parser_state,
- referrer_policy, base_url_source);
+ referrer_policy);
}
v8::Local<v8::PrimitiveArray> ReferrerScriptInfo::ToV8HostDefinedOptions(
- v8::Isolate* isolate) const {
- if (IsDefaultValue())
+ v8::Isolate* isolate,
+ const KURL& script_origin_resource_name) const {
+ if (IsDefaultValue(script_origin_resource_name))
return v8::Local<v8::PrimitiveArray>();
v8::Local<v8::PrimitiveArray> host_defined_options =
v8::PrimitiveArray::New(isolate, HostDefinedOptionsIndex::kLength);
+ const KURL stored_base_url =
+ GetStoredBaseUrl(*this, script_origin_resource_name);
+
v8::Local<v8::Primitive> base_url_value =
V8String(isolate, base_url_.GetString());
host_defined_options->Set(isolate, HostDefinedOptionsIndex::kBaseURL,
@@ -110,11 +145,6 @@ v8::Local<v8::PrimitiveArray> ReferrerScriptInfo::ToV8HostDefinedOptions(
host_defined_options->Set(isolate, HostDefinedOptionsIndex::kReferrerPolicy,
referrer_policy_value);
- v8::Local<v8::Primitive> base_url_source_value = v8::Integer::NewFromUnsigned(
- isolate, static_cast<uint32_t>(base_url_source_));
- host_defined_options->Set(isolate, HostDefinedOptionsIndex::kBaseUrlSource,
- base_url_source_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 279ac3ab4a0..b8635162b7a 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
@@ -23,38 +23,31 @@ class CORE_EXPORT ReferrerScriptInfo {
STACK_ALLOCATED();
public:
- enum class BaseUrlSource {
- kClassicScriptCORSSameOrigin,
- kClassicScriptCORSCrossOrigin,
- kOther
- };
ReferrerScriptInfo() {}
ReferrerScriptInfo(const KURL& base_url,
network::mojom::CredentialsMode credentials_mode,
const String& nonce,
ParserDisposition parser_state,
- network::mojom::ReferrerPolicy referrer_policy,
- BaseUrlSource base_url_source)
+ network::mojom::ReferrerPolicy referrer_policy)
: base_url_(base_url),
credentials_mode_(credentials_mode),
nonce_(nonce),
parser_state_(parser_state),
- referrer_policy_(referrer_policy),
- base_url_source_(base_url_source) {}
- ReferrerScriptInfo(const KURL& base_url,
- const ScriptFetchOptions& options,
- BaseUrlSource base_url_source)
+ referrer_policy_(referrer_policy) {}
+ ReferrerScriptInfo(const KURL& base_url, const ScriptFetchOptions& options)
: ReferrerScriptInfo(base_url,
options.CredentialsMode(),
options.Nonce(),
options.ParserState(),
- options.GetReferrerPolicy(),
- base_url_source) {}
+ options.GetReferrerPolicy()) {}
static ReferrerScriptInfo FromV8HostDefinedOptions(
v8::Local<v8::Context>,
- v8::Local<v8::PrimitiveArray>);
- v8::Local<v8::PrimitiveArray> ToV8HostDefinedOptions(v8::Isolate*) const;
+ v8::Local<v8::PrimitiveArray>,
+ const KURL& script_origin_resource_name);
+ v8::Local<v8::PrimitiveArray> ToV8HostDefinedOptions(
+ v8::Isolate*,
+ const KURL& script_origin_resource_name) const;
const KURL& BaseURL() const { return base_url_; }
network::mojom::CredentialsMode CredentialsMode() const {
@@ -65,22 +58,12 @@ class CORE_EXPORT ReferrerScriptInfo {
network::mojom::ReferrerPolicy GetReferrerPolicy() const {
return referrer_policy_;
}
- BaseUrlSource GetBaseUrlSource() const { return base_url_source_; }
- bool IsDefaultValue() const {
- return base_url_.IsNull() &&
- credentials_mode_ == network::mojom::CredentialsMode::kSameOrigin &&
- nonce_.IsEmpty() && parser_state_ == kNotParserInserted &&
- base_url_source_ == BaseUrlSource::kOther;
- }
+ bool IsDefaultValue(const KURL& script_origin_resource_name) const;
private:
// Spec: "referencing script's base URL"
// https://html.spec.whatwg.org/C/#concept-script-base-url
- //
- // If base_url_.IsNull(), refer to ScriptOrigin::ResourceName() instead.
- // Note: This improves the chance of getting into the fast path in
- // ToV8HostDefinedOptions().
const KURL base_url_;
// Spec: "referencing script's credentials mode"
@@ -102,9 +85,6 @@ class CORE_EXPORT ReferrerScriptInfo {
// https://html.spec.whatwg.org/C/#default-classic-script-fetch-options
const network::mojom::ReferrerPolicy referrer_policy_ =
network::mojom::ReferrerPolicy::kDefault;
-
- // Temporary flag to collect UMA for crbug.com/1082086.
- const BaseUrlSource base_url_source_ = BaseUrlSource::kOther;
};
} // 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 bf4c59b8bf9..fe4050b4f5b 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
@@ -11,32 +11,91 @@
namespace blink {
TEST(ReferrerScriptInfo, IsDefaultValue) {
- EXPECT_TRUE(ReferrerScriptInfo().IsDefaultValue());
+ const KURL script_origin_resource_name("http://example.org/script.js");
+
+ // TODO(https://crbug.com/1114993): There three cases should be distinguished.
+ EXPECT_TRUE(ReferrerScriptInfo().IsDefaultValue(script_origin_resource_name));
+ EXPECT_TRUE(
+ ReferrerScriptInfo(script_origin_resource_name, ScriptFetchOptions())
+ .IsDefaultValue(script_origin_resource_name));
+ EXPECT_TRUE(ReferrerScriptInfo(KURL(), ScriptFetchOptions())
+ .IsDefaultValue(script_origin_resource_name));
+
+ EXPECT_FALSE(
+ ReferrerScriptInfo(KURL("http://example.com"), ScriptFetchOptions())
+ .IsDefaultValue(script_origin_resource_name));
EXPECT_FALSE(ReferrerScriptInfo(KURL("http://example.com"),
network::mojom::CredentialsMode::kInclude, "",
kNotParserInserted,
- network::mojom::ReferrerPolicy::kDefault,
- ReferrerScriptInfo::BaseUrlSource::kOther)
- .IsDefaultValue());
+ network::mojom::ReferrerPolicy::kDefault)
+ .IsDefaultValue(script_origin_resource_name));
}
-TEST(ReferrerScriptInfo, ToFromV8) {
+TEST(ReferrerScriptInfo, ToFromV8NoReferencingScript) {
V8TestingScope scope;
- const KURL url("http://example.com");
+ const KURL script_origin_resource_name("http://example.org/script.js");
+
+ v8::Local<v8::PrimitiveArray> v8_info =
+ ReferrerScriptInfo().ToV8HostDefinedOptions(scope.GetIsolate(),
+ script_origin_resource_name);
+
+ EXPECT_TRUE(v8_info.IsEmpty());
+
+ ReferrerScriptInfo decoded = ReferrerScriptInfo::FromV8HostDefinedOptions(
+ scope.GetContext(), v8_info, script_origin_resource_name);
+
+ // TODO(https://crbug.com/1235202): This should be null URL.
+ EXPECT_EQ(script_origin_resource_name, decoded.BaseURL());
+}
+
+TEST(ReferrerScriptInfo, ToFromV8ScriptOriginBaseUrl) {
+ V8TestingScope scope;
+ const KURL script_origin_resource_name("http://example.org/script.js");
+
+ v8::Local<v8::PrimitiveArray> v8_info =
+ ReferrerScriptInfo(script_origin_resource_name, ScriptFetchOptions())
+ .ToV8HostDefinedOptions(scope.GetIsolate(),
+ script_origin_resource_name);
- EXPECT_TRUE(ReferrerScriptInfo()
- .ToV8HostDefinedOptions(scope.GetIsolate())
- .IsEmpty());
+ EXPECT_TRUE(v8_info.IsEmpty());
+
+ ReferrerScriptInfo decoded = ReferrerScriptInfo::FromV8HostDefinedOptions(
+ scope.GetContext(), v8_info, script_origin_resource_name);
+
+ EXPECT_EQ(script_origin_resource_name, decoded.BaseURL());
+}
+
+TEST(ReferrerScriptInfo, ToFromV8ScriptNullBaseUrl) {
+ V8TestingScope scope;
+ const KURL script_origin_resource_name("http://example.org/script.js");
- ReferrerScriptInfo info(
- url, network::mojom::CredentialsMode::kInclude, "foobar",
- kNotParserInserted, network::mojom::ReferrerPolicy::kOrigin,
- ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSCrossOrigin);
v8::Local<v8::PrimitiveArray> v8_info =
- info.ToV8HostDefinedOptions(scope.GetIsolate());
+ ReferrerScriptInfo(KURL(), ScriptFetchOptions())
+ .ToV8HostDefinedOptions(scope.GetIsolate(),
+ script_origin_resource_name);
+
+ EXPECT_TRUE(v8_info.IsEmpty());
+
+ ReferrerScriptInfo decoded = ReferrerScriptInfo::FromV8HostDefinedOptions(
+ scope.GetContext(), v8_info, script_origin_resource_name);
+
+ // TODO(https://crbug.com/1235202): This should be null URL.
+ EXPECT_EQ(script_origin_resource_name, decoded.BaseURL());
+}
+
+TEST(ReferrerScriptInfo, ToFromV8) {
+ V8TestingScope scope;
+ const KURL script_origin_resource_name("http://example.org/script.js");
+ const KURL url("http://example.com");
+
+ ReferrerScriptInfo info(url, network::mojom::CredentialsMode::kInclude,
+ "foobar", kNotParserInserted,
+ network::mojom::ReferrerPolicy::kOrigin);
+ v8::Local<v8::PrimitiveArray> v8_info = info.ToV8HostDefinedOptions(
+ scope.GetIsolate(), script_origin_resource_name);
- ReferrerScriptInfo decoded =
- ReferrerScriptInfo::FromV8HostDefinedOptions(scope.GetContext(), v8_info);
+ ReferrerScriptInfo decoded = ReferrerScriptInfo::FromV8HostDefinedOptions(
+ scope.GetContext(), v8_info, script_origin_resource_name);
EXPECT_EQ(url, decoded.BaseURL());
EXPECT_EQ(network::mojom::CredentialsMode::kInclude,
decoded.CredentialsMode());
@@ -44,8 +103,6 @@ TEST(ReferrerScriptInfo, ToFromV8) {
EXPECT_EQ(kNotParserInserted, decoded.ParserState());
EXPECT_EQ(network::mojom::ReferrerPolicy::kOrigin,
decoded.GetReferrerPolicy());
- EXPECT_EQ(ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSCrossOrigin,
- decoded.GetBaseUrlSource());
}
} // 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 7728ca77e8f..9d2aa7ace7b 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
@@ -48,10 +48,7 @@ class RejectedPromises::Message final {
bool IsCollected() { return collected_ || !script_state_->ContextIsValid(); }
- bool HasPromise(v8::Local<v8::Value> promise) {
- ScriptState::Scope scope(script_state_);
- return promise == promise_.NewLocal(script_state_->GetIsolate());
- }
+ bool HasPromise(v8::Local<v8::Value> promise) { return promise_ == promise; }
void Report() {
if (!script_state_->ContextIsValid())
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 871ec1da867..28aa8543b70 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
@@ -58,7 +58,7 @@ class ScheduledAction final : public GarbageCollected<ScheduledAction>,
ExecutionContext* target,
const String& handler);
- ~ScheduledAction();
+ ~ScheduledAction() override;
void Dispose();
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 85a9ce2f9d0..a89ef772898 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
@@ -241,8 +241,10 @@ void ScriptController::ExecuteJavaScriptURL(
auto params =
previous_document_loader->CreateWebNavigationParamsToCloneDocument();
String result = ToCoreString(v8::Local<v8::String>::Cast(v8_result));
- WebNavigationParams::FillStaticResponse(params.get(), "text/html", "UTF-8",
- StringUTF8Adaptor(result));
+ WebNavigationParams::FillStaticResponse(
+ params.get(), "text/html", "UTF-8",
+ StringUTF8Adaptor(
+ result, kStrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD));
params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
window_->GetFrame()->Loader().CommitNavigation(std::move(params), nullptr,
CommitReason::kJavascriptUrl);
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 947718c5501..63bd4485e87 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
@@ -327,7 +327,6 @@ void ScriptCustomElementDefinition::RunFormDisabledCallback(Element& element,
form_disabled_callback_->InvokeAndReportException(&element, is_disabled);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void ScriptCustomElementDefinition::RunFormStateRestoreCallback(
Element& element,
const V8ControlValue* value,
@@ -337,16 +336,5 @@ void ScriptCustomElementDefinition::RunFormStateRestoreCallback(
form_state_restore_callback_->InvokeAndReportException(
&element, value, V8FormStateRestoreMode::Create(mode).value());
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ScriptCustomElementDefinition::RunFormStateRestoreCallback(
- Element& element,
- const FileOrUSVStringOrFormData& value,
- const String& mode) {
- if (!form_state_restore_callback_)
- return;
- form_state_restore_callback_->InvokeAndReportException(
- &element, value, V8FormStateRestoreMode::Create(mode).value());
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // 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 ecdf8b7620f..9300b44bd07 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
@@ -67,15 +67,9 @@ class CORE_EXPORT ScriptCustomElementDefinition final
HTMLFormElement* nullable_form) override;
void RunFormResetCallback(Element& element) override;
void RunFormDisabledCallback(Element& element, bool is_disabled) override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void RunFormStateRestoreCallback(Element& element,
const V8ControlValue* value,
const String& mode) override;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void RunFormStateRestoreCallback(Element& element,
- const FileOrUSVStringOrFormData& value,
- const String& mode) override;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
// Implementations of |CustomElementDefinition|
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 23fe9bbb3f2..0e6f88d0687 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,7 +28,6 @@
#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"
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 ab15d685078..bb2e32f6a09 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
@@ -6,7 +6,7 @@
#include "base/feature_list.h"
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
namespace blink {
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 31a4c0d6719..3dd967b25b1 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
@@ -587,7 +587,15 @@ bool ScriptStreamer::TryStartStreamingTask() {
}
}
- if (V8CodeCache::HasCodeCache(script_resource_->CacheHandler())) {
+ // Here we can't call Check on the cache handler because it requires the
+ // script source, which would require having already loaded the script. It is
+ // OK at this point to disable streaming even though we might end up rejecting
+ // the cached data later, because we expect that the cached data is usually
+ // acceptable. If we detect a content mismatch once the content is loaded,
+ // then we reset the code cache entry to just a timestamp, so this condition
+ // will allow streaming the next time we load the resource.
+ if (V8CodeCache::HasCodeCache(script_resource_->CacheHandler(),
+ SingleCachedMetadataHandler::kAllowUnchecked)) {
// The resource has a code cache entry, so it's unnecessary to stream
// and parse the code.
// TODO(leszeks): Can we even reach this code path with data pipes?
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 1f9a6447158..ac74f1d0fbf 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
@@ -78,7 +78,7 @@ class NoopLoaderFactory final : public ResourceFetcher::LoaderFactory {
return std::make_unique<NoopWebURLLoader>();
}
std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
- return Platform::Current()->CreateCodeCacheLoader();
+ return std::make_unique<CodeCacheLoaderMock>();
}
class NoopWebURLLoader final : public WebURLLoader {
@@ -108,7 +108,7 @@ class NoopLoaderFactory final : public ResourceFetcher::LoaderFactory {
std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
resource_load_info_notifier_wrapper,
WebURLLoaderClient*) override {}
- void SetDefersLoading(WebURLLoader::DeferType) override {}
+ void Freeze(WebLoaderFreezeMode) override {}
void DidChangePriority(WebURLRequest::Priority, int) override {
NOTREACHED();
}
@@ -175,7 +175,7 @@ class ScriptStreamingTest : public testing::Test {
protected:
void AppendData(const char* data) {
- uint32_t data_len = strlen(data);
+ uint32_t data_len = base::checked_cast<uint32_t>(strlen(data));
MojoResult result = producer_handle_->WriteData(
data, &data_len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
EXPECT_EQ(result, MOJO_RESULT_OK);
@@ -359,7 +359,10 @@ TEST_F(ScriptStreamingTest, DISABLED_SuppressingStreaming) {
SingleCachedMetadataHandler* cache_handler = resource_->CacheHandler();
EXPECT_TRUE(cache_handler);
cache_handler->DisableSendToPlatformForTesting();
- cache_handler->SetCachedMetadata(V8CodeCache::TagForCodeCache(cache_handler),
+ // CodeCacheHost can be nullptr since we disabled sending data to
+ // GeneratedCodeCacheHost for testing.
+ cache_handler->SetCachedMetadata(/*code_cache_host*/ nullptr,
+ V8CodeCache::TagForCodeCache(cache_handler),
reinterpret_cast<const uint8_t*>("X"), 1);
AppendData("function foo() {");
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h
index 7285fc0074e..c165309a7c2 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h
@@ -104,8 +104,10 @@ enum SerializationTag {
kRTCEncodedAudioFrameTag = 'A', // uint32_t -> transferred audio frame ID
kRTCEncodedVideoFrameTag = 'V', // uint32_t -> transferred video frame ID
- kAudioDataTag = 'a', // uint32_t -> transferred audio data
- kVideoFrameTag = 'v', // uint32_t -> transferred video frame ID
+ kAudioDataTag = 'a', // uint32_t -> transferred audio data
+ kVideoFrameTag = 'v', // uint32_t -> transferred video frame ID
+ kEncodedAudioChunkTag = 'y', // uint32_t -> transferred chunk
+ kEncodedVideoChunkTag = 'z', // uint32_t -> transferred chunk
// The following tags were used by the Shape Detection API implementation
// between M71 and M81. During these milestones, the API was always behind
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
index 1732c2b027b..d2e93b16889 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
@@ -195,10 +195,6 @@ SkImageInfo SerializedImageBitmapSettings::GetSkImageInfo(
sk_alpha_type = kUnpremul_SkAlphaType;
}
- blink::OpacityMode opacity_mode = blink::kNonOpaque;
- if (opacity_mode_ == SerializedOpacityMode::kOpaque)
- opacity_mode = blink::kOpaque;
-
return SkImageInfo::Make(width, height, sk_color_type, sk_alpha_type,
std::move(sk_color_space));
}
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 2282416e0e9..680852b862e 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,7 +36,6 @@
#include "base/containers/span.h"
#include "base/dcheck_is_on.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink-forward.h"
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 4419baa6247..cb2c608f178 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
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
+#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/mojo/mojo_handle.h"
#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
@@ -41,7 +42,6 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
namespace blink {
@@ -551,9 +551,9 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
canvas->SetPlaceholderCanvasId(canvas_id);
canvas->SetFrameSinkId(client_id, sink_id);
if (filter_quality == 0)
- canvas->SetFilterQuality(kNone_SkFilterQuality);
+ canvas->SetFilterQuality(cc::PaintFlags::FilterQuality::kNone);
else
- canvas->SetFilterQuality(kLow_SkFilterQuality);
+ canvas->SetFilterQuality(cc::PaintFlags::FilterQuality::kLow);
return canvas;
}
case kReadableStreamTransferTag: {
@@ -755,13 +755,19 @@ V8ScriptValueDeserializer::GetWasmModuleFromId(v8::Isolate* isolate,
ExecutionContext* execution_context = ExecutionContext::From(script_state_);
DCHECK(serialized_script_value_->origin());
UseCounter::Count(execution_context, WebFeature::kWasmModuleSharing);
+ const v8::CompiledWasmModule& wasm_module =
+ serialized_script_value_->WasmModules()[id];
if (!serialized_script_value_->origin()->IsSameOriginWith(
execution_context->GetSecurityOrigin())) {
UseCounter::Count(execution_context,
WebFeature::kCrossOriginWasmModuleSharing);
+ AuditsIssue::ReportCrossOriginWasmModuleSharingIssue(
+ execution_context, wasm_module.source_url(),
+ serialized_script_value_->origin()->ToString(),
+ execution_context->GetSecurityOrigin()->ToString(),
+ true /* is_warning */);
}
- return v8::WasmModuleObject::FromCompiledModule(
- isolate, serialized_script_value_->WasmModules()[id]);
+ return v8::WasmModuleObject::FromCompiledModule(isolate, wasm_module);
}
CHECK(serialized_script_value_->WasmModules().IsEmpty());
return v8::MaybeLocal<v8::WasmModuleObject>();
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 42ebeeae305..9747961ff78 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
@@ -7,8 +7,8 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/public/platform/web_blob_info.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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_blob.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_matrix.h"
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_mojo_handle.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_offscreen_canvas.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_shared_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_transform_stream.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
@@ -44,6 +43,7 @@
#include "third_party/blink/renderer/core/streams/transform_stream.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h"
+#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -111,7 +111,10 @@ bool V8ScriptValueSerializer::ExtractTransferable(
}
if (object->IsArrayBuffer()) {
DOMArrayBuffer* array_buffer =
- V8ArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(object));
+ NativeValueTraits<DOMArrayBuffer>::NativeValue(isolate, object,
+ exception_state);
+ if (exception_state.HadException())
+ return false;
if (transferables.array_buffers.Contains(array_buffer)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
@@ -124,7 +127,10 @@ bool V8ScriptValueSerializer::ExtractTransferable(
}
if (object->IsSharedArrayBuffer()) {
DOMSharedArrayBuffer* shared_array_buffer =
- V8SharedArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(object));
+ NativeValueTraits<DOMSharedArrayBuffer>::NativeValue(isolate, object,
+ exception_state);
+ if (exception_state.HadException())
+ return false;
if (transferables.array_buffers.Contains(shared_array_buffer)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
@@ -678,7 +684,9 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
WriteUint64(canvas->PlaceholderCanvasId());
WriteUint32(canvas->ClientId());
WriteUint32(canvas->SinkId());
- WriteUint32(canvas->FilterQuality() == kNone_SkFilterQuality ? 0 : 1);
+ WriteUint32(canvas->FilterQuality() == cc::PaintFlags::FilterQuality::kNone
+ ? 0
+ : 1);
return true;
}
if (wrapper_type_info == V8ReadableStream::GetWrapperTypeInfo() &&
@@ -811,9 +819,8 @@ bool V8ScriptValueSerializer::WriteFile(File* file,
void V8ScriptValueSerializer::ThrowDataCloneError(
v8::Local<v8::String> v8_message) {
DCHECK(exception_state_);
- ExceptionState exception_state(
- script_state_->GetIsolate(), exception_state_->Context(),
- exception_state_->InterfaceName(), exception_state_->PropertyName());
+ ExceptionState exception_state(script_state_->GetIsolate(),
+ exception_state_->GetContext());
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
ToBlinkString<String>(v8_message, kDoNotExternalize));
@@ -824,9 +831,7 @@ v8::Maybe<bool> V8ScriptValueSerializer::WriteHostObject(
v8::Local<v8::Object> object) {
DCHECK(exception_state_);
DCHECK_EQ(isolate, script_state_->GetIsolate());
- ExceptionState exception_state(isolate, exception_state_->Context(),
- exception_state_->InterfaceName(),
- exception_state_->PropertyName());
+ ExceptionState exception_state(isolate, exception_state_->GetContext());
if (!V8DOMWrapper::IsWrapper(isolate, object)) {
exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
@@ -851,12 +856,12 @@ v8::Maybe<bool> V8ScriptValueSerializer::WriteHostObject(
v8::Maybe<uint32_t> V8ScriptValueSerializer::GetSharedArrayBufferId(
v8::Isolate* isolate,
v8::Local<v8::SharedArrayBuffer> v8_shared_array_buffer) {
+ DCHECK(exception_state_);
+ DCHECK_EQ(isolate, script_state_->GetIsolate());
+
+ ExceptionState exception_state(isolate, exception_state_->GetContext());
+
if (for_storage_) {
- DCHECK(exception_state_);
- DCHECK_EQ(isolate, script_state_->GetIsolate());
- ExceptionState exception_state(isolate, exception_state_->Context(),
- exception_state_->InterfaceName(),
- exception_state_->PropertyName());
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
"A SharedArrayBuffer can not be serialized for storage.");
@@ -864,7 +869,10 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetSharedArrayBufferId(
}
DOMSharedArrayBuffer* shared_array_buffer =
- V8SharedArrayBuffer::ToImpl(v8_shared_array_buffer);
+ NativeValueTraits<DOMSharedArrayBuffer>::NativeValue(
+ isolate, v8_shared_array_buffer, exception_state);
+ if (exception_state.HadException())
+ return v8::Nothing<uint32_t>();
// The index returned from this function will be serialized into the data
// stream. When deserializing, this will be used to index into the
@@ -883,9 +891,7 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetWasmModuleTransferId(
if (for_storage_) {
DCHECK(exception_state_);
DCHECK_EQ(isolate, script_state_->GetIsolate());
- ExceptionState exception_state(isolate, exception_state_->Context(),
- exception_state_->InterfaceName(),
- exception_state_->PropertyName());
+ ExceptionState exception_state(isolate, exception_state_->GetContext());
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
"A WebAssembly.Module can not be serialized for storage.");
@@ -899,9 +905,7 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetWasmModuleTransferId(
case Options::kBlockedInNonSecureContext: {
// This happens, currently, when we try to serialize to IndexedDB
// in an non-secure context.
- ExceptionState exception_state(isolate, exception_state_->Context(),
- exception_state_->InterfaceName(),
- exception_state_->PropertyName());
+ ExceptionState exception_state(isolate, exception_state_->GetContext());
exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
"Serializing WebAssembly modules in "
"non-secure contexts is not allowed.");
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 432ca8b1f2b..3e85f609dcc 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
@@ -787,11 +787,7 @@ TEST(V8ScriptValueSerializerTest, RoundTripDetachedImageData) {
ASSERT_NO_EXCEPTION);
SkPixmap pm = image_data->GetSkPixmap();
pm.writable_addr32(0, 0)[0] = 200u;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
image_data->data()->GetAsUint8ClampedArray()->BufferBase()->Detach();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- image_data->data().GetAsUint8ClampedArray()->BufferBase()->Detach();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
v8::Local<v8::Value> wrapper =
ToV8(image_data, scope.GetContext()->Global(), scope.GetIsolate());
@@ -1957,11 +1953,12 @@ TEST(V8ScriptValueSerializerTest, TransformStreamIntegerOverflow) {
// The final 5 bytes is the offset of the two message ports inside the
// transferred message port array. In order to trigger integer overflow this
// is set to 0xffffffff, encoded as a varint.
- char serialized_value[] = {0xff, 0x14, 0xff, 0x0d, 0x5c, 0x6d,
- 0xff, 0xff, 0xff, 0xff, 0x0f};
+ uint8_t serialized_value[] = {0xff, 0x14, 0xff, 0x0d, 0x5c, 0x6d,
+ 0xff, 0xff, 0xff, 0xff, 0x0f};
- auto corrupted_serialized_script_value =
- SerializedScriptValue::Create(serialized_value, sizeof(serialized_value));
+ auto corrupted_serialized_script_value = SerializedScriptValue::Create(
+ reinterpret_cast<const char*>(serialized_value),
+ sizeof(serialized_value));
corrupted_serialized_script_value->GetStreams() =
std::move(serialized_script_value->GetStreams());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/source_location.cc b/chromium/third_party/blink/renderer/bindings/core/v8/source_location.cc
index eeb1ad7155f..ab2665b82df 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/source_location.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/source_location.cc
@@ -121,7 +121,7 @@ std::unique_ptr<SourceLocation> SourceLocation::CreateFromNonEmptyV8StackTrace(
String url = ToCoreString(stack_trace->topSourceURL());
unsigned line_number = stack_trace->topLineNumber();
unsigned column_number = stack_trace->topColumnNumber();
- int script_id = stack_trace->topScriptIdAsInteger();
+ int script_id = stack_trace->topScriptId();
return base::WrapUnique(new SourceLocation(
url, line_number, column_number, std::move(stack_trace), script_id));
}
@@ -170,7 +170,7 @@ void SourceLocation::ToTracedValue(TracedValue* value, const char* name) const {
value->BeginDictionary();
value->SetString("functionName",
ToCoreString(stack_trace_->topFunctionName()));
- value->SetInteger("scriptId", stack_trace_->topScriptIdAsInteger());
+ value->SetInteger("scriptId", stack_trace_->topScriptId());
value->SetString("url", ToCoreString(stack_trace_->topSourceURL()));
value->SetInteger("lineNumber", stack_trace_->topLineNumber());
value->SetInteger("columnNumber", stack_trace_->topColumnNumber());
@@ -186,7 +186,7 @@ void SourceLocation::WriteIntoTrace(perfetto::TracedValue context) const {
// TODO(altimin): Add TracedValue support to v8::StringView and remove
// ToCoreString calls.
dict.Add("functionName", ToCoreString(stack_trace_->topFunctionName()));
- dict.Add("scriptId", stack_trace_->topScriptIdAsInteger());
+ dict.Add("scriptId", stack_trace_->topScriptId());
dict.Add("url", ToCoreString(stack_trace_->topSourceURL()));
dict.Add("lineNumber", stack_trace_->topLineNumber());
dict.Add("columnNumber", stack_trace_->topColumnNumber());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
index 7edaf26127c..4090c21362a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_TO_V8_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_TO_V8_TRAITS_H_
+#include "third_party/abseil-cpp/absl/types/optional.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/dom_data_store.h"
@@ -45,10 +46,9 @@ struct ToV8Traits<IDLAny> {
// It is not correct to take empty |script_value|.
// However, some call sites expect to get v8::Undefined
// when ToV8 takes empty |script_value|.
- // TODO(crbug.com/1183637): Remove this if-branch.
- if (script_value.IsEmpty())
- return v8::Undefined(script_state->GetIsolate());
- return script_value.V8Value();
+ // TODO(crbug.com/1183637): Enable the following DCHECK.
+ // DCHECK(!script_value.IsEmpty());
+ return script_value.V8ValueFor(script_state);
}
static v8::MaybeLocal<v8::Value> WARN_UNUSED_RESULT
@@ -179,7 +179,7 @@ struct ToV8Traits<IDLObject> {
static v8::MaybeLocal<v8::Value> WARN_UNUSED_RESULT
ToV8(ScriptState* script_state, const ScriptValue& script_value) {
DCHECK(!script_value.IsEmpty());
- v8::Local<v8::Value> v8_value = script_value.V8Value();
+ v8::Local<v8::Value> v8_value = script_value.V8ValueFor(script_state);
// TODO(crbug.com/1185033): Change this if-branch to DCHECK.
if (!v8_value->IsObject())
return v8::Undefined(script_state->GetIsolate());
@@ -266,10 +266,7 @@ struct ToV8Traits<
static v8::MaybeLocal<v8::Value> WARN_UNUSED_RESULT
ToV8(ScriptState* script_state, const T* dictionary) {
DCHECK(dictionary);
- v8::Local<v8::Value> v8_value = dictionary->CreateV8Object(
- script_state->GetIsolate(), script_state->GetContext()->Global());
- DCHECK(!v8_value.IsEmpty());
- return v8_value;
+ return dictionary->ToV8Value(script_state);
}
};
@@ -778,7 +775,7 @@ struct ToV8Traits<IDLNullable<IDLObject>> {
if (script_value.IsEmpty())
return v8::Null(script_state->GetIsolate());
- v8::Local<v8::Value> v8_value = script_value.V8Value();
+ v8::Local<v8::Value> v8_value = script_value.V8ValueFor(script_state);
DCHECK(v8_value->IsNull() || v8_value->IsObject());
return v8_value;
}
@@ -1022,39 +1019,6 @@ struct ToV8Traits<
}
};
-// IDLUnionINT
-template <typename T>
-struct ToV8Traits<IDLUnionINT<T>> {
- static v8::MaybeLocal<v8::Value> WARN_UNUSED_RESULT
- ToV8(ScriptState* script_state, const T& value) {
- return bindings::ToV8HelperUnion(script_state, value);
- }
-};
-
-// IDLUnionNotINT
-template <typename T>
-struct ToV8Traits<IDLUnionNotINT<T>> {
- static v8::MaybeLocal<v8::Value> WARN_UNUSED_RESULT
- ToV8(ScriptState* script_state, const T& value) {
- return bindings::ToV8HelperUnion(script_state, value);
- }
-};
-
-// Nullable IDLUnionINT must not be used.
-template <typename T>
-struct ToV8Traits<IDLNullable<IDLUnionINT<T>>>;
-
-// Nullable IDLUnionNotINT
-template <typename T>
-struct ToV8Traits<IDLNullable<IDLUnionNotINT<T>>> {
- static v8::MaybeLocal<v8::Value> WARN_UNUSED_RESULT
- ToV8(ScriptState* script_state, const T& value) {
- if (value.IsNull())
- return v8::Null(script_state->GetIsolate());
- return ToV8Traits<IDLUnionNotINT<T>>::ToV8(script_state, value);
- }
-};
-
// Optional
template <typename T>
struct ToV8Traits<IDLOptional<T>> {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc
index fe9cdf6bb5b..78033a0d104 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc
@@ -4,12 +4,12 @@
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
-#include "third_party/blink/renderer/bindings/core/v8/file_or_usv_string_or_form_data.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_address_space.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_create_html_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_point_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_event_listener.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_file_formdata_usvstring.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
#include "third_party/blink/renderer/core/testing/garbage_collected_script_wrappable.h"
@@ -144,52 +144,51 @@ TEST(ToV8TraitsTest, String) {
const String string("string");
const char* const charptr_string = "charptrString";
// ByteString
- TEST_TOV8_TRAITS(scope, IDLByteStringV2, "string", string);
- TEST_TOV8_TRAITS(scope, IDLByteStringV2, "charptrString", charptr_string);
+ TEST_TOV8_TRAITS(scope, IDLByteString, "string", string);
+ TEST_TOV8_TRAITS(scope, IDLByteString, "charptrString", charptr_string);
// DOMString
- TEST_TOV8_TRAITS(scope, IDLStringV2, "string", string);
- TEST_TOV8_TRAITS(scope, IDLStringV2, "charptrString", charptr_string);
- TEST_TOV8_TRAITS(scope, IDLStringTreatNullAsEmptyStringV2, "string", string);
- TEST_TOV8_TRAITS(scope, IDLStringTreatNullAsEmptyStringV2, "charptrString",
+ TEST_TOV8_TRAITS(scope, IDLString, "string", string);
+ TEST_TOV8_TRAITS(scope, IDLString, "charptrString", charptr_string);
+ TEST_TOV8_TRAITS(scope, IDLStringTreatNullAsEmptyString, "string", string);
+ TEST_TOV8_TRAITS(scope, IDLStringTreatNullAsEmptyString, "charptrString",
charptr_string);
// USVString
- TEST_TOV8_TRAITS(scope, IDLUSVStringV2, "string", string);
- TEST_TOV8_TRAITS(scope, IDLUSVStringV2, "charptrString", charptr_string);
+ TEST_TOV8_TRAITS(scope, IDLUSVString, "string", string);
+ TEST_TOV8_TRAITS(scope, IDLUSVString, "charptrString", charptr_string);
// [StringContext=TrustedHTML] DOMString
- TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedHTMLV2, "string",
- string);
- TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedHTMLV2, "charptrString",
+ TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedHTML, "string", string);
+ TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedHTML, "charptrString",
charptr_string);
TEST_TOV8_TRAITS(scope,
- IDLStringStringContextTrustedHTMLTreatNullAsEmptyStringV2,
+ IDLStringStringContextTrustedHTMLTreatNullAsEmptyString,
"string", string);
TEST_TOV8_TRAITS(scope,
- IDLStringStringContextTrustedHTMLTreatNullAsEmptyStringV2,
+ IDLStringStringContextTrustedHTMLTreatNullAsEmptyString,
"charptrString", charptr_string);
// [StringContext=TrustedScript] DOMString
- TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedScriptV2, "string",
+ TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedScript, "string",
string);
- TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedScriptV2,
- "charptrString", charptr_string);
+ TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedScript, "charptrString",
+ charptr_string);
TEST_TOV8_TRAITS(scope,
- IDLStringStringContextTrustedScriptTreatNullAsEmptyStringV2,
+ IDLStringStringContextTrustedScriptTreatNullAsEmptyString,
"string", string);
TEST_TOV8_TRAITS(scope,
- IDLStringStringContextTrustedScriptTreatNullAsEmptyStringV2,
+ IDLStringStringContextTrustedScriptTreatNullAsEmptyString,
"charptrString", charptr_string);
// [StringContext=TrustedScriptURL] USVString
- TEST_TOV8_TRAITS(scope, IDLUSVStringStringContextTrustedScriptURLV2, "string",
+ TEST_TOV8_TRAITS(scope, IDLUSVStringStringContextTrustedScriptURL, "string",
string);
- TEST_TOV8_TRAITS(scope, IDLUSVStringStringContextTrustedScriptURLV2,
+ TEST_TOV8_TRAITS(scope, IDLUSVStringStringContextTrustedScriptURL,
"charptrString", charptr_string);
}
TEST(ToV8TraitsTest, EmptyString) {
const V8TestingScope scope;
const String empty_string("");
- TEST_TOV8_TRAITS(scope, IDLStringV2, "", empty_string);
+ TEST_TOV8_TRAITS(scope, IDLString, "", empty_string);
const char* const empty = "";
- TEST_TOV8_TRAITS(scope, IDLStringV2, "", empty);
+ TEST_TOV8_TRAITS(scope, IDLString, "", empty);
}
TEST(ToV8TraitsTest, Object) {
@@ -198,7 +197,7 @@ TEST(ToV8TraitsTest, Object) {
string_vector.push_back("hello");
string_vector.push_back("world");
ScriptValue value(scope.GetIsolate(),
- ToV8Traits<IDLSequence<IDLStringV2>>::ToV8(
+ ToV8Traits<IDLSequence<IDLString>>::ToV8(
scope.GetScriptState(), string_vector));
TEST_TOV8_TRAITS(scope, IDLObject, "hello,world", value);
v8::Local<v8::Value> actual;
@@ -237,7 +236,7 @@ TEST(ToV8TraitsTest, Vector) {
Vector<String> string_vector;
string_vector.push_back("foo");
string_vector.push_back("bar");
- TEST_TOV8_TRAITS(scope, IDLSequence<IDLStringV2>, "foo,bar", string_vector);
+ TEST_TOV8_TRAITS(scope, IDLSequence<IDLString>, "foo,bar", string_vector);
}
TEST(ToV8TraitsTest, HeapVector) {
@@ -317,11 +316,11 @@ TEST(ToV8TraitsTest, StringVectorVector) {
compound_vector.push_back(string_vector2);
EXPECT_EQ(2U, compound_vector.size());
- TEST_TOV8_TRAITS(scope, IDLSequence<IDLSequence<IDLStringV2>>, "foo,bar,quux",
+ TEST_TOV8_TRAITS(scope, IDLSequence<IDLSequence<IDLString>>, "foo,bar,quux",
compound_vector);
v8::Local<v8::Value> actual;
- ASSERT_TRUE(ToV8Traits<IDLSequence<IDLSequence<IDLStringV2>>>::ToV8(
+ ASSERT_TRUE(ToV8Traits<IDLSequence<IDLSequence<IDLString>>>::ToV8(
scope.GetScriptState(), compound_vector)
.ToLocal(&actual))
<< "ToV8 throws an exception.";
@@ -394,7 +393,7 @@ TEST(ToV8TraitsTest, PairVector) {
Vector<std::pair<String, int8_t>> pair_vector;
pair_vector.push_back(std::make_pair("one", 1));
pair_vector.push_back(std::make_pair("two", 2));
- using ByteRecord = IDLRecord<IDLStringV2, IDLByte>;
+ using ByteRecord = IDLRecord<IDLString, IDLByte>;
TEST_TOV8_TRAITS(scope, ByteRecord, "[object Object]", pair_vector);
v8::Local<v8::Value> actual;
ASSERT_TRUE(ToV8Traits<ByteRecord>::ToV8(scope.GetScriptState(), pair_vector)
@@ -420,7 +419,7 @@ TEST(ToV8TraitsTest, PairHeapVector) {
"one", MakeGarbageCollected<GarbageCollectedScriptWrappable>("foo")));
pair_heap_vector.push_back(std::make_pair(
"two", MakeGarbageCollected<GarbageCollectedScriptWrappable>("bar")));
- using HeapRecord = IDLRecord<IDLStringV2, GarbageCollectedScriptWrappable>;
+ using HeapRecord = IDLRecord<IDLString, GarbageCollectedScriptWrappable>;
TEST_TOV8_TRAITS(scope, HeapRecord, "[object Object]", pair_heap_vector);
v8::Local<v8::Value> actual;
ASSERT_TRUE(
@@ -451,9 +450,9 @@ TEST(ToV8TraitsTest, PairHeapVector) {
TEST(ToV8TraitsTest, NullStringInputForNoneNullableType) {
const V8TestingScope scope;
const String null_string;
- TEST_TOV8_TRAITS(scope, IDLStringV2, "", null_string);
+ TEST_TOV8_TRAITS(scope, IDLString, "", null_string);
const char* const null = nullptr;
- TEST_TOV8_TRAITS(scope, IDLStringV2, "", null);
+ TEST_TOV8_TRAITS(scope, IDLString, "", null);
}
TEST(ToV8TraitsTest, Nullable) {
@@ -477,16 +476,16 @@ TEST(ToV8TraitsTest, Nullable) {
TEST(ToV8TraitsTest, NullableString) {
const V8TestingScope scope;
- TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "null", String());
- TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "string", String("string"));
- TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "", String(""));
+ TEST_TOV8_TRAITS(scope, IDLNullable<IDLString>, "null", String());
+ TEST_TOV8_TRAITS(scope, IDLNullable<IDLString>, "string", String("string"));
+ TEST_TOV8_TRAITS(scope, IDLNullable<IDLString>, "", String(""));
const char* const null = nullptr;
- TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "null", null);
+ TEST_TOV8_TRAITS(scope, IDLNullable<IDLString>, "null", null);
const char* const charptr_string = "charptrString";
- TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "charptrString",
+ TEST_TOV8_TRAITS(scope, IDLNullable<IDLString>, "charptrString",
charptr_string);
const char* const charptr_empty_string = "";
- TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "", charptr_empty_string);
+ TEST_TOV8_TRAITS(scope, IDLNullable<IDLString>, "", charptr_empty_string);
}
TEST(ToV8TraitsTest, NullableObject) {
@@ -592,21 +591,21 @@ TEST(ToV8TraitsTest, NullableDate) {
TEST(ToV8TraitsTest, Union) {
const V8TestingScope scope;
- const FileOrUSVStringOrFormData usv_string =
- FileOrUSVStringOrFormData::FromUSVString("https://example.com/");
- TEST_TOV8_TRAITS(scope, IDLUnionNotINT<FileOrUSVStringOrFormData>,
+ const auto* usv_string =
+ MakeGarbageCollected<V8UnionFileOrFormDataOrUSVString>(
+ "https://example.com/");
+ TEST_TOV8_TRAITS(scope, V8UnionFileOrFormDataOrUSVString,
"https://example.com/", usv_string);
}
TEST(ToV8TraitsTest, NullableUnion) {
const V8TestingScope scope;
- TEST_TOV8_TRAITS(scope,
- IDLNullable<IDLUnionNotINT<FileOrUSVStringOrFormData>>,
- "null", FileOrUSVStringOrFormData());
- const FileOrUSVStringOrFormData usv_string =
- FileOrUSVStringOrFormData::FromUSVString("http://example.com/");
- TEST_TOV8_TRAITS(scope,
- IDLNullable<IDLUnionNotINT<FileOrUSVStringOrFormData>>,
+ TEST_TOV8_TRAITS(scope, IDLNullable<V8UnionFileOrFormDataOrUSVString>, "null",
+ nullptr);
+ const auto* usv_string =
+ MakeGarbageCollected<V8UnionFileOrFormDataOrUSVString>(
+ "http://example.com/");
+ TEST_TOV8_TRAITS(scope, IDLNullable<V8UnionFileOrFormDataOrUSVString>,
"http://example.com/", usv_string);
}
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 8dd0021d59e..35e368178e6 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
@@ -35,7 +35,6 @@
#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_controller.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_event_target.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_html_link_element.h"
@@ -780,8 +779,7 @@ v8::Local<v8::Context> ToV8ContextEvenIfDetached(LocalFrame* frame,
ScriptState* ToScriptState(ExecutionContext* context, DOMWrapperWorld& world) {
DCHECK(context);
if (LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context)) {
- if (LocalFrame* frame = window->GetFrame())
- return ToScriptState(frame, world);
+ return ToScriptState(window->GetFrame(), world);
} else if (auto* scope = DynamicTo<WorkerOrWorkletGlobalScope>(context)) {
if (WorkerOrWorkletScriptController* script = scope->ScriptController())
return script->GetScriptState();
@@ -790,6 +788,8 @@ ScriptState* ToScriptState(ExecutionContext* context, DOMWrapperWorld& world) {
}
ScriptState* ToScriptState(LocalFrame* frame, DOMWrapperWorld& world) {
+ if (!frame)
+ return nullptr;
v8::HandleScope handle_scope(ToIsolate(frame));
return ToScriptStateImpl(frame, world);
}
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 9033403be41..9d260beeecb 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,6 +32,7 @@
#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/abseil-cpp/absl/types/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/to_v8_for_core.h"
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
index cf754fcc9b2..0b04fe6177f 100644
--- 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
@@ -64,12 +64,13 @@ bool IsResourceHotForCaching(const SingleCachedMetadataHandler* cache_handler) {
} // namespace
bool V8CodeCache::HasCodeCache(
- const SingleCachedMetadataHandler* cache_handler) {
+ const SingleCachedMetadataHandler* cache_handler,
+ SingleCachedMetadataHandler::GetCachedMetadataBehavior behavior) {
if (!cache_handler)
return false;
uint32_t code_cache_tag = V8CodeCache::TagForCodeCache(cache_handler);
- return cache_handler->GetCachedMetadata(code_cache_tag).get();
+ return cache_handler->GetCachedMetadata(code_cache_tag, behavior).get();
}
v8::ScriptCompiler::CachedData* V8CodeCache::CreateCachedData(
@@ -194,6 +195,7 @@ V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions cache_options,
template <typename UnboundScript>
static void ProduceCacheInternal(
v8::Isolate* isolate,
+ blink::mojom::CodeCacheHost* code_cache_host,
UnboundScript unbound_script,
SingleCachedMetadataHandler* cache_handler,
size_t source_text_length,
@@ -209,7 +211,7 @@ static void ProduceCacheInternal(
switch (produce_cache_options) {
case V8CodeCache::ProduceCacheOptions::kSetTimeStamp:
- V8CodeCache::SetCacheTimeStamp(cache_handler);
+ V8CodeCache::SetCacheTimeStamp(code_cache_host, cache_handler);
break;
case V8CodeCache::ProduceCacheOptions::kProduceCodeCache: {
// TODO(crbug.com/938269): Investigate why this can be empty here.
@@ -235,9 +237,10 @@ static void ProduceCacheInternal(
code_cache_size_histogram.Count(cache_size_ratio);
}
cache_handler->ClearCachedMetadata(
- CachedMetadataHandler::kClearLocally);
+ code_cache_host, CachedMetadataHandler::kClearLocally);
cache_handler->SetCachedMetadata(
- V8CodeCache::TagForCodeCache(cache_handler), data, length);
+ code_cache_host, V8CodeCache::TagForCodeCache(cache_handler), data,
+ length);
}
TRACE_EVENT_END1(
@@ -261,10 +264,11 @@ static void ProduceCacheInternal(
}
void V8CodeCache::ProduceCache(v8::Isolate* isolate,
+ blink::mojom::CodeCacheHost* code_cache_host,
v8::Local<v8::Script> script,
const ScriptSourceCode& source,
ProduceCacheOptions produce_cache_options) {
- ProduceCacheInternal(isolate, script->GetUnboundScript(),
+ ProduceCacheInternal(isolate, code_cache_host, script->GetUnboundScript(),
source.CacheHandler(), source.Source().length(),
source.Url(), source.StartPosition(), source.Streamer(),
"v8.compile", produce_cache_options,
@@ -272,16 +276,17 @@ void V8CodeCache::ProduceCache(v8::Isolate* isolate,
}
void V8CodeCache::ProduceCache(v8::Isolate* isolate,
+ blink::mojom::CodeCacheHost* code_cache_host,
ModuleRecordProduceCacheData* produce_cache_data,
size_t source_text_length,
const KURL& source_url,
const TextPosition& source_start_position) {
- ProduceCacheInternal(isolate, produce_cache_data->UnboundScript(isolate),
- produce_cache_data->CacheHandler(), source_text_length,
- source_url, source_start_position, false,
- "v8.compileModule",
- produce_cache_data->GetProduceCacheOptions(),
- ScriptStreamer::NotStreamingReason::kModuleScript);
+ ProduceCacheInternal(
+ isolate, code_cache_host, produce_cache_data->UnboundScript(isolate),
+ produce_cache_data->CacheHandler(), source_text_length, source_url,
+ source_start_position, false, "v8.compileModule",
+ produce_cache_data->GetProduceCacheOptions(),
+ ScriptStreamer::NotStreamingReason::kModuleScript);
}
uint32_t V8CodeCache::TagForCodeCache(
@@ -296,21 +301,25 @@ uint32_t V8CodeCache::TagForTimeStamp(
// Store a timestamp to the cache as hint.
void V8CodeCache::SetCacheTimeStamp(
+ blink::mojom::CodeCacheHost* code_cache_host,
SingleCachedMetadataHandler* cache_handler) {
uint64_t now_ms = base::TimeTicks::Now().since_origin().InMilliseconds();
- cache_handler->ClearCachedMetadata(CachedMetadataHandler::kClearLocally);
- cache_handler->SetCachedMetadata(TagForTimeStamp(cache_handler),
- reinterpret_cast<uint8_t*>(&now_ms),
- sizeof(now_ms));
+ cache_handler->ClearCachedMetadata(code_cache_host,
+ CachedMetadataHandler::kClearLocally);
+ cache_handler->SetCachedMetadata(
+ code_cache_host, TagForTimeStamp(cache_handler),
+ reinterpret_cast<uint8_t*>(&now_ms), sizeof(now_ms));
}
// static
scoped_refptr<CachedMetadata> V8CodeCache::GenerateFullCodeCache(
ScriptState* script_state,
const String& script_string,
- const String& file_name,
+ const KURL& source_url,
const WTF::TextEncoding& encoding,
OpaqueMode opaque_mode) {
+ const String file_name = source_url.GetString();
+
constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
file_name.Utf8());
@@ -331,7 +340,7 @@ scoped_refptr<CachedMetadata> V8CodeCache::GenerateFullCodeCache(
opaque_mode == OpaqueMode::kOpaque, // is_opaque
false, // is_wasm
false, // is_module
- referrer_info.ToV8HostDefinedOptions(isolate));
+ referrer_info.ToV8HostDefinedOptions(isolate, source_url));
v8::Local<v8::String> code(V8String(isolate, script_string));
v8::ScriptCompiler::Source source(code, origin);
scoped_refptr<CachedMetadata> cached_metadata;
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
index f7bb3dc47a7..c71df6c69e0 100644
--- 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
@@ -12,6 +12,7 @@
#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/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
@@ -25,10 +26,13 @@ namespace blink {
class CachedMetadata;
class KURL;
-class SingleCachedMetadataHandler;
class ScriptSourceCode;
class ModuleRecordProduceCacheData;
+namespace mojom {
+class CodeCacheHost;
+}
+
class CORE_EXPORT V8CodeCache final {
STATIC_ONLY(V8CodeCache);
@@ -46,11 +50,15 @@ class CORE_EXPORT V8CodeCache final {
static uint32_t TagForCodeCache(const SingleCachedMetadataHandler*);
static uint32_t TagForTimeStamp(const SingleCachedMetadataHandler*);
- static void SetCacheTimeStamp(SingleCachedMetadataHandler*);
+ static void SetCacheTimeStamp(blink::mojom::CodeCacheHost*,
+ SingleCachedMetadataHandler*);
// Returns true iff the SingleCachedMetadataHandler contains a code cache
// that can be consumed by V8.
- static bool HasCodeCache(const SingleCachedMetadataHandler*);
+ static bool HasCodeCache(
+ const SingleCachedMetadataHandler*,
+ SingleCachedMetadataHandler::GetCachedMetadataBehavior behavior =
+ SingleCachedMetadataHandler::kCrashIfUnchecked);
static std::tuple<v8::ScriptCompiler::CompileOptions,
ProduceCacheOptions,
@@ -68,10 +76,12 @@ class CORE_EXPORT V8CodeCache final {
const SingleCachedMetadataHandler*);
static void ProduceCache(v8::Isolate*,
+ blink::mojom::CodeCacheHost*,
v8::Local<v8::Script>,
const ScriptSourceCode&,
ProduceCacheOptions);
static void ProduceCache(v8::Isolate*,
+ blink::mojom::CodeCacheHost*,
ModuleRecordProduceCacheData*,
size_t source_text_length,
const KURL& source_url,
@@ -80,7 +90,7 @@ class CORE_EXPORT V8CodeCache final {
static scoped_refptr<CachedMetadata> GenerateFullCodeCache(
ScriptState*,
const String& script_string,
- const String& file_name,
+ const KURL& source_url,
const WTF::TextEncoding&,
OpaqueMode);
};
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 4cd260bec63..f8a6f848c6e 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
@@ -4,8 +4,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h"
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-
namespace blink {
namespace {
@@ -83,517 +81,3 @@ void V8ContextSnapshot::SetGetReferenceTableFunc(
}
} // namespace blink
-
-#else // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
-#include <cstring>
-
-#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_document.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_event_target.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_html_document.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_node.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_window.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/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"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-v8::Local<v8::Function> CreateInterfaceObject(const WrapperTypeInfo* type,
- v8::Local<v8::Context> context,
- const DOMWrapperWorld& world,
- v8::Isolate* isolate) {
- v8::Local<v8::Function> parent_interface_object;
- if (type->parent_class) {
- parent_interface_object =
- CreateInterfaceObject(type->parent_class, context, world, isolate);
- }
- return V8ObjectConstructor::CreateInterfaceObject(
- type, context, world, isolate, parent_interface_object,
- V8ObjectConstructor::CreationMode::kDoNotInstallConditionalFeatures);
-}
-
-// TODO(peria): This method is almost a copy of
-// V8PerContext::CreateWrapperFromCacheSlowCase(), so merge with it.
-v8::Local<v8::Object> CreatePlainWrapper(v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Context> context,
- const WrapperTypeInfo* type) {
- CHECK(V8HTMLDocument::GetWrapperTypeInfo()->Equals(type));
- v8::Context::Scope scope(context);
-
- v8::Local<v8::Function> interface_object =
- CreateInterfaceObject(type, context, world, isolate);
- CHECK(!interface_object.IsEmpty());
- v8::Local<v8::Object> instance_template =
- V8ObjectConstructor::NewInstance(isolate, interface_object)
- .ToLocalChecked();
- return instance_template->Clone();
-}
-
-int GetSnapshotIndexForWorld(const DOMWrapperWorld& world) {
- return world.IsMainWorld() ? 0 : 1;
-}
-
-// Interface templates of those classes are stored in a snapshot without any
-// runtime enabled features, so we have to install runtime enabled features on
-// them after instantiation.
-struct SnapshotInterface {
- const WrapperTypeInfo* wrapper_type_info;
- InstallRuntimeEnabledFeaturesOnTemplateFunction install_function;
-};
-SnapshotInterface g_snapshot_interfaces[] = {
- {V8Window::GetWrapperTypeInfo(),
- V8Window::InstallRuntimeEnabledFeaturesOnTemplate},
- {V8HTMLDocument::GetWrapperTypeInfo(),
- V8HTMLDocument::InstallRuntimeEnabledFeaturesOnTemplate},
- {V8EventTarget::GetWrapperTypeInfo(),
- V8EventTarget::InstallRuntimeEnabledFeaturesOnTemplate},
- {V8Node::GetWrapperTypeInfo(),
- V8Node::InstallRuntimeEnabledFeaturesOnTemplate},
- {V8Document::GetWrapperTypeInfo(),
- V8Document::InstallRuntimeEnabledFeaturesOnTemplate},
-};
-constexpr size_t kSnapshotInterfaceSize = base::size(g_snapshot_interfaces);
-
-enum class InternalFieldType : uint8_t {
- kNone,
- kNodeType,
- kDocumentType,
- kHTMLDocumentType,
- kHTMLDocumentObject,
-};
-
-const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(InternalFieldType type) {
- switch (type) {
- case InternalFieldType::kNone:
- NOTREACHED();
- break;
- case InternalFieldType::kNodeType:
- return V8Node::GetWrapperTypeInfo();
- case InternalFieldType::kDocumentType:
- return V8Document::GetWrapperTypeInfo();
- case InternalFieldType::kHTMLDocumentType:
- return V8HTMLDocument::GetWrapperTypeInfo();
- case InternalFieldType::kHTMLDocumentObject:
- return V8HTMLDocument::GetWrapperTypeInfo();
- }
- NOTREACHED();
- return nullptr;
-}
-
-struct DataForDeserializer {
- STACK_ALLOCATED();
- public:
- DataForDeserializer(Document* document) : document(document) {}
-
- Document* document;
- // Figures if we failed the deserialization.
- bool did_fail = false;
-};
-
-} // namespace
-
-v8::Local<v8::Context> V8ContextSnapshot::CreateContextFromSnapshot(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::ExtensionConfiguration* extension_configuration,
- v8::Local<v8::Object> global_proxy,
- Document* document) {
- if (!CanCreateContextFromSnapshot(isolate, world, document)) {
- return v8::Local<v8::Context>();
- }
-
- const int index = GetSnapshotIndexForWorld(world);
- DataForDeserializer data(document);
- v8::DeserializeInternalFieldsCallback callback =
- v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data);
-
- v8::Local<v8::Context> context =
- v8::Context::FromSnapshot(
- isolate, index, callback, extension_configuration, global_proxy,
- document->GetExecutionContext()->GetMicrotaskQueue())
- .ToLocalChecked();
-
- // In case we fail to deserialize v8::Context from snapshot,
- // disable the snapshot feature and returns an empty handle.
- // TODO(peria): Drop this fallback routine. crbug.com/881417
- if (data.did_fail) {
- V8PerIsolateData::From(isolate)->BailoutAndDisableV8ContextSnapshot();
- return v8::Local<v8::Context>();
- }
-
- VLOG(1) << "A context is created from snapshot for "
- << (world.IsMainWorld() ? "" : "non-") << "main world";
-
- return context;
-}
-
-bool V8ContextSnapshot::InstallConditionalFeatures(
- v8::Local<v8::Context> context,
- Document* document) {
- ScriptState* script_state = ScriptState::From(context);
- v8::Isolate* isolate = script_state->GetIsolate();
- const DOMWrapperWorld& world = script_state->World();
- if (!CanCreateContextFromSnapshot(isolate, world, document)) {
- return false;
- }
-
- TRACE_EVENT1("v8", "V8ContextSnapshot::InstallRuntimeEnabled", "IsMainFrame",
- world.IsMainWorld());
-
- v8::Local<v8::String> prototype_str = V8AtomicString(isolate, "prototype");
- V8PerContextData* data = script_state->PerContextData();
-
- v8::Local<v8::Object> global_proxy = context->Global();
- {
- v8::Local<v8::Object> window_wrapper =
- global_proxy->GetPrototype().As<v8::Object>();
- const WrapperTypeInfo* type = V8Window::GetWrapperTypeInfo();
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8Window::InstallRuntimeEnabledFeatures(isolate, world, window_wrapper,
- prototype, interface);
- type->InstallConditionalFeatures(context, world, window_wrapper, prototype,
- interface,
- type->DomTemplate(isolate, world));
- InstallOriginTrialFeatures(type, script_state, prototype, interface);
- }
- {
- const WrapperTypeInfo* type = V8EventTarget::GetWrapperTypeInfo();
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8EventTarget::InstallRuntimeEnabledFeatures(
- isolate, world, v8::Local<v8::Object>(), prototype, interface);
- type->InstallConditionalFeatures(context, world, v8::Local<v8::Object>(),
- prototype, interface,
- type->DomTemplate(isolate, world));
- InstallOriginTrialFeatures(type, script_state, prototype, interface);
- }
-
- if (!world.IsMainWorld()) {
- return true;
- }
-
- // The below code handles window.document on the main world.
- {
- CHECK(document);
- DCHECK(IsA<HTMLDocument>(document));
- CHECK(document->ContainsWrapper());
- v8::Local<v8::Object> document_wrapper =
- ToV8(document, global_proxy, isolate).As<v8::Object>();
- const WrapperTypeInfo* type = V8HTMLDocument::GetWrapperTypeInfo();
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8HTMLDocument::InstallRuntimeEnabledFeatures(
- isolate, world, document_wrapper, prototype, interface);
- type->InstallConditionalFeatures(context, world, document_wrapper,
- prototype, interface,
- type->DomTemplate(isolate, world));
- InstallOriginTrialFeatures(type, script_state, prototype, interface);
- }
- {
- const WrapperTypeInfo* type = V8Document::GetWrapperTypeInfo();
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8Document::InstallRuntimeEnabledFeatures(
- isolate, world, v8::Local<v8::Object>(), prototype, interface);
- type->InstallConditionalFeatures(context, world, v8::Local<v8::Object>(),
- prototype, interface,
- type->DomTemplate(isolate, world));
- InstallOriginTrialFeatures(type, script_state, prototype, interface);
- }
- {
- const WrapperTypeInfo* type = V8Node::GetWrapperTypeInfo();
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8Node::InstallRuntimeEnabledFeatures(
- isolate, world, v8::Local<v8::Object>(), prototype, interface);
- type->InstallConditionalFeatures(context, world, v8::Local<v8::Object>(),
- prototype, interface,
- type->DomTemplate(isolate, world));
- InstallOriginTrialFeatures(type, script_state, prototype, interface);
- }
-
- return true;
-}
-
-void V8ContextSnapshot::EnsureInterfaceTemplates(v8::Isolate* isolate) {
- if (V8PerIsolateData::From(isolate)->GetV8ContextSnapshotMode() !=
- V8PerIsolateData::V8ContextSnapshotMode::kUseSnapshot) {
- return;
- }
-
- v8::HandleScope handle_scope(isolate);
- // Update the install functions for V8Window and V8Document to work for their
- // partial interfaces.
- SnapshotInterface& snapshot_window = g_snapshot_interfaces[0];
- DCHECK(V8Window::GetWrapperTypeInfo()->Equals(
- snapshot_window.wrapper_type_info));
- snapshot_window.install_function =
- V8Window::install_runtime_enabled_features_on_template_function_;
-
- SnapshotInterface& snapshot_document = g_snapshot_interfaces[4];
- DCHECK(V8Document::GetWrapperTypeInfo()->Equals(
- snapshot_document.wrapper_type_info));
- snapshot_document.install_function =
- V8Document::install_runtime_enabled_features_on_template_function_;
-
- EnsureInterfaceTemplatesForWorld(isolate, DOMWrapperWorld::MainWorld());
- // Any world types other than |kMain| are acceptable for this.
- scoped_refptr<DOMWrapperWorld> isolated_world = DOMWrapperWorld::Create(
- isolate, DOMWrapperWorld::WorldType::kForV8ContextSnapshotNonMain);
- EnsureInterfaceTemplatesForWorld(isolate, *isolated_world);
-}
-
-v8::StartupData V8ContextSnapshot::TakeSnapshot() {
- DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate())
- ->GetV8ContextSnapshotMode(),
- V8PerIsolateData::V8ContextSnapshotMode::kTakeSnapshot);
-
- v8::SnapshotCreator* creator =
- V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate())
- ->GetSnapshotCreator();
- v8::Isolate* isolate = creator->GetIsolate();
- CHECK_EQ(isolate, v8::Isolate::GetCurrent());
-
- // Disable all runtime enabled features
- RuntimeEnabledFeatures::SetStableFeaturesEnabled(false);
- RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(false);
- RuntimeEnabledFeatures::SetTestFeaturesEnabled(false);
-
- {
- v8::HandleScope handleScope(isolate);
- creator->SetDefaultContext(v8::Context::New(isolate));
-
- TakeSnapshotForWorld(creator, DOMWrapperWorld::MainWorld());
- // For non main worlds, we can use any type to create a context.
- TakeSnapshotForWorld(
- creator,
- *DOMWrapperWorld::Create(
- isolate, DOMWrapperWorld::WorldType::kForV8ContextSnapshotNonMain));
- }
-
- isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread);
-
- v8::StartupData blob =
- creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
-
- return blob;
-}
-
-v8::StartupData V8ContextSnapshot::SerializeInternalField(
- v8::Local<v8::Object> object,
- int index,
- void*) {
- InternalFieldType field_type = InternalFieldType::kNone;
- const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(object);
- if (kV8DOMWrapperObjectIndex == index) {
- if (blink::V8HTMLDocument::GetWrapperTypeInfo()->Equals(wrapper_type)) {
- field_type = InternalFieldType::kHTMLDocumentObject;
- }
- DCHECK_LE(kV8DefaultWrapperInternalFieldCount,
- object->InternalFieldCount());
- } else if (kV8DOMWrapperTypeIndex == index) {
- if (blink::V8HTMLDocument::GetWrapperTypeInfo()->Equals(wrapper_type)) {
- field_type = InternalFieldType::kHTMLDocumentType;
- } else if (blink::V8Document::GetWrapperTypeInfo()->Equals(wrapper_type)) {
- field_type = InternalFieldType::kDocumentType;
- } else if (blink::V8Node::GetWrapperTypeInfo()->Equals(wrapper_type)) {
- field_type = InternalFieldType::kNodeType;
- }
- DCHECK_LE(kV8PrototypeInternalFieldcount, object->InternalFieldCount());
- }
- CHECK_NE(field_type, InternalFieldType::kNone);
-
- int size = sizeof(InternalFieldType);
- // Allocated memory on |data| will be released in
- // v8::i::PartialSerializer::SerializeEmbedderFields().
- char* data = new char[size];
- std::memcpy(data, &field_type, size);
-
- return {data, size};
-}
-
-void V8ContextSnapshot::DeserializeInternalField(v8::Local<v8::Object> object,
- int index,
- v8::StartupData payload,
- void* ptr) {
- // DeserializeInternalField() expects to be called in the main world
- // with |document| being HTMLDocument.
- CHECK_EQ(payload.raw_size, static_cast<int>(sizeof(InternalFieldType)));
- InternalFieldType type =
- *reinterpret_cast<const InternalFieldType*>(payload.data);
-
- const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type);
- DataForDeserializer* embed_data = static_cast<DataForDeserializer*>(ptr);
- switch (type) {
- case InternalFieldType::kNodeType:
- case InternalFieldType::kDocumentType:
- case InternalFieldType::kHTMLDocumentType: {
- // TODO(peria): Make this branch back to CHECK_EQ. crbug.com/881417
- if (index != kV8DOMWrapperTypeIndex) {
- LOG(ERROR) << "Invalid index for wrpper type info: " << index;
- embed_data->did_fail = true;
- return;
- }
- object->SetAlignedPointerInInternalField(
- index, const_cast<WrapperTypeInfo*>(wrapper_type_info));
- return;
- }
- case InternalFieldType::kHTMLDocumentObject: {
- // There seems to be few crash reports with invalid |index|.
- // In such cases, we fallback to create v8::Context without snapshots.
- // TODO(peria): Make this branch back to CHECK_EQ. crbug.com/881417
- if (index != kV8DOMWrapperObjectIndex) {
- LOG(ERROR) << "Invalid index for HTMLDocument object: " << index;
- embed_data->did_fail = true;
- return;
- }
-
- // The below code handles window.document on the main world.
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
- ScriptWrappable* document = embed_data->document;
- DCHECK(document);
-
- // Make reference from wrapper to document
- object->SetAlignedPointerInInternalField(index, document);
- // Make reference from document to wrapper
- // TODO(peria): Make this branch back to CHECK. crbug.com/881417
- if (!document->SetWrapper(isolate, wrapper_type_info, object)) {
- LOG(ERROR) << "Failed to set HTMLDocument wrapper on Blink object.";
- embed_data->did_fail = true;
- return;
- }
- return;
- }
- case InternalFieldType::kNone:
- NOTREACHED();
- return;
- }
-
- NOTREACHED();
-}
-
-bool V8ContextSnapshot::CanCreateContextFromSnapshot(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- Document* document) {
- DCHECK(document);
- if (V8PerIsolateData::From(isolate)->GetV8ContextSnapshotMode() !=
- V8PerIsolateData::V8ContextSnapshotMode::kUseSnapshot) {
- return false;
- }
-
- // When creating a context for the main world from snapshot, we also need a
- // HTMLDocument instance. If typeof window.document is not HTMLDocument, e.g.
- // SVGDocument or XMLDocument, we can't create contexts from the snapshot.
- return !world.IsMainWorld() || IsA<HTMLDocument>(document);
-}
-
-void V8ContextSnapshot::EnsureInterfaceTemplatesForWorld(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world) {
- V8PerIsolateData* data = V8PerIsolateData::From(isolate);
-
- // A snapshot has some interface templates in it. The first
- // |kSnapshotInterfaceSize| templates are for the main world, and the
- // remaining templates are for isolated worlds.
- const int index_offset = world.IsMainWorld() ? 0 : kSnapshotInterfaceSize;
-
- for (size_t i = 0; i < kSnapshotInterfaceSize; ++i) {
- auto& snapshot_interface = g_snapshot_interfaces[i];
- const WrapperTypeInfo* wrapper_type_info =
- snapshot_interface.wrapper_type_info;
- v8::Local<v8::FunctionTemplate> interface_template =
- isolate->GetDataFromSnapshotOnce<v8::FunctionTemplate>(index_offset + i)
- .ToLocalChecked();
- snapshot_interface.install_function(isolate, world, interface_template);
- CHECK(!interface_template.IsEmpty());
- data->SetInterfaceTemplate(world, wrapper_type_info, interface_template);
- }
-}
-
-void V8ContextSnapshot::TakeSnapshotForWorld(v8::SnapshotCreator* creator,
- const DOMWrapperWorld& world) {
- v8::Isolate* isolate = creator->GetIsolate();
- CHECK_EQ(isolate, v8::Isolate::GetCurrent());
-
- // Function templates
- v8::HandleScope handleScope(isolate);
- Vector<v8::Local<v8::FunctionTemplate>> interface_templates(
- kSnapshotInterfaceSize);
- v8::Local<v8::FunctionTemplate> window_template;
- for (size_t i = 0; i < kSnapshotInterfaceSize; ++i) {
- const WrapperTypeInfo* wrapper_type_info =
- g_snapshot_interfaces[i].wrapper_type_info;
- v8::Local<v8::FunctionTemplate> interface_template =
- wrapper_type_info->DomTemplate(isolate, world);
- CHECK(!interface_template.IsEmpty());
- interface_templates[i] = interface_template;
- if (V8Window::GetWrapperTypeInfo()->Equals(wrapper_type_info)) {
- window_template = interface_template;
- }
- }
- CHECK(!window_template.IsEmpty());
-
- v8::Local<v8::ObjectTemplate> window_instance_template =
- window_template->InstanceTemplate();
- CHECK(!window_instance_template.IsEmpty());
-
- v8::Local<v8::Context> context;
- {
- V8PerIsolateData::UseCounterDisabledScope use_counter_disabled(
- V8PerIsolateData::From(isolate));
- context = v8::Context::New(isolate, nullptr, window_instance_template);
- }
- CHECK(!context.IsEmpty());
-
- // For the main world context, we need to prepare a HTMLDocument wrapper and
- // set it to window.documnt.
- if (world.IsMainWorld()) {
- v8::Context::Scope scope(context);
- v8::Local<v8::Object> document_wrapper = CreatePlainWrapper(
- isolate, world, context, V8HTMLDocument::GetWrapperTypeInfo());
- int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
- void* values[] = {nullptr, const_cast<WrapperTypeInfo*>(
- V8HTMLDocument::GetWrapperTypeInfo())};
- document_wrapper->SetAlignedPointerInInternalFields(base::size(indices),
- indices, values);
-
- // Set the cached accessor for window.document.
- CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate).Set(
- context->Global(), document_wrapper));
- }
-
- for (auto& interface_template : interface_templates) {
- creator->AddData(interface_template);
- }
- creator->AddContext(context, SerializeInternalField);
-
- V8PerIsolateData::From(isolate)->ClearPersistentsForV8ContextSnapshot();
-}
-
-} // namespace blink
-
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h
index 40a899d1646..f2c4fe59e48 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h
@@ -15,8 +15,6 @@ class DOMWrapperWorld;
class Document;
class ScriptState;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-
// The V8 context snapshot is taken by //tools/v8_context_snapshot at build
// time, and it makes it faster to create a new v8::Context and global object.
//
@@ -60,69 +58,6 @@ class CORE_EXPORT V8ContextSnapshot {
static void SetGetReferenceTableFunc(GetReferenceTableFuncType func);
};
-#else // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
-// This class contains helper functions to take and use a V8 context snapshot.
-//
-// The V8 context snapshot is taken by tools/v8_context_snapshot/ when Chromium
-// is built, and is used when Blink creates a new V8 context. When to build or
-// to use the V8 context snapshot, you have a table of references of C++
-// callbacks exposed to V8.
-//
-// A V8 context snapshot contains:
-// - Interface templates of Window, EventTarget, Node, Document, and
-// HTMLDocument.
-// - Two types of V8 contexts; one is for the main world, and the other is for
-// other worlds.
-// - HTMLDocument's wrapper (window.document) in the context for the main
-// world.
-//
-// Currently, the V8 context snapshot supports only the main thread. If it is
-// the main world, we need a special logic to serialize / deserialize
-// window.document (so only HTMLDocument is supported on the main world).
-// Worker threads are not yet supported.
-class CORE_EXPORT V8ContextSnapshot {
- STATIC_ONLY(V8ContextSnapshot);
-
- public:
- static v8::Local<v8::Context> CreateContextFromSnapshot(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::ExtensionConfiguration*,
- v8::Local<v8::Object> global_proxy,
- Document*);
-
- // If the context was created from the snapshot, installs conditionally
- // enabled features on some v8::Object's in the context and returns true.
- // Otherwise, does nothing and returns false.
- static bool InstallConditionalFeatures(v8::Local<v8::Context>, Document*);
-
- static void EnsureInterfaceTemplates(v8::Isolate*);
-
- // Do not call this in production.
- static v8::StartupData TakeSnapshot();
-
- private:
- static v8::StartupData SerializeInternalField(v8::Local<v8::Object> holder,
- int index,
- void* data);
- static void DeserializeInternalField(v8::Local<v8::Object> holder,
- int index,
- v8::StartupData payload,
- void* data);
- static bool CanCreateContextFromSnapshot(v8::Isolate*,
- const DOMWrapperWorld&,
- Document*);
-
- static void EnsureInterfaceTemplatesForWorld(v8::Isolate*,
- const DOMWrapperWorld&);
-
- static void TakeSnapshotForWorld(v8::SnapshotCreator*,
- const DOMWrapperWorld&);
-};
-
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_CONTEXT_SNAPSHOT_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc
deleted file mode 100644
index 54ed4ad1b4a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc
+++ /dev/null
@@ -1,922 +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.
- * 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/bindings/core/v8/v8_dom_configuration.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/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-namespace {
-
-template <class Configuration>
-bool WorldConfigurationApplies(const Configuration& config,
- const DOMWrapperWorld& world) {
- const auto current_world_config = world.IsMainWorld()
- ? V8DOMConfiguration::kMainWorld
- : V8DOMConfiguration::kNonMainWorlds;
- return config.world_configuration & current_world_config;
-}
-
-template <>
-bool WorldConfigurationApplies(
- const V8DOMConfiguration::SymbolKeyedMethodConfiguration&,
- const DOMWrapperWorld&) {
- return true;
-}
-
-void DoInstallAttribute(
- v8::Local<v8::ObjectTemplate> object_template,
- v8::Local<v8::Name> name,
- const V8DOMConfiguration::AttributeConfiguration& attribute) {
- v8::SideEffectType getter_side_effect_type =
- attribute.getter_side_effect_type == V8DOMConfiguration::kHasNoSideEffect
- ? v8::SideEffectType::kHasNoSideEffect
- : v8::SideEffectType::kHasSideEffect;
- switch (static_cast<V8DOMConfiguration::AttributeGetterBehavior>(
- attribute.getter_behavior)) {
- case V8DOMConfiguration::kAlwaysCallGetter:
- object_template->SetNativeDataProperty(
- name, attribute.getter, attribute.setter, v8::Local<v8::Value>(),
- static_cast<v8::PropertyAttribute>(attribute.attribute),
- v8::Local<v8::AccessorSignature>(), v8::AccessControl::DEFAULT,
- getter_side_effect_type);
- break;
- case V8DOMConfiguration::kReplaceWithDataProperty:
- DCHECK(!attribute.setter);
- DCHECK_EQ(attribute.world_configuration, V8DOMConfiguration::kAllWorlds);
- object_template->SetLazyDataProperty(
- name, attribute.getter, v8::Local<v8::Value>(),
- static_cast<v8::PropertyAttribute>(attribute.attribute),
- getter_side_effect_type);
- break;
- }
-}
-
-void DoInstallAttribute(
- v8::Local<v8::Context> context,
- v8::Local<v8::Object> object,
- v8::Local<v8::Name> name,
- const V8DOMConfiguration::AttributeConfiguration& attribute) {
- v8::SideEffectType getter_side_effect_type =
- attribute.getter_side_effect_type == V8DOMConfiguration::kHasNoSideEffect
- ? v8::SideEffectType::kHasNoSideEffect
- : v8::SideEffectType::kHasSideEffect;
- switch (static_cast<V8DOMConfiguration::AttributeGetterBehavior>(
- attribute.getter_behavior)) {
- case V8DOMConfiguration::kAlwaysCallGetter:
- object
- ->SetNativeDataProperty(
- context, name, attribute.getter, attribute.setter,
- v8::Local<v8::Value>(),
- static_cast<v8::PropertyAttribute>(attribute.attribute),
- getter_side_effect_type)
- .ToChecked();
- break;
- case V8DOMConfiguration::kReplaceWithDataProperty:
- DCHECK(!attribute.setter);
- DCHECK_EQ(attribute.world_configuration, V8DOMConfiguration::kAllWorlds);
- object
- ->SetLazyDataProperty(
- context, name, attribute.getter, v8::Local<v8::Value>(),
- static_cast<v8::PropertyAttribute>(attribute.attribute),
- getter_side_effect_type)
- .ToChecked();
- break;
- }
-}
-
-void InstallAttributeInternal(
- v8::Isolate* isolate,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const V8DOMConfiguration::AttributeConfiguration& attribute,
- const DOMWrapperWorld& world) {
- if (!WorldConfigurationApplies(attribute, world))
- return;
-
- v8::Local<v8::Name> name = V8AtomicString(isolate, attribute.name);
- const unsigned location = attribute.property_location_configuration;
- DCHECK(location);
- if (location & V8DOMConfiguration::kOnInstance)
- DoInstallAttribute(instance_template, name, attribute);
- if (location & V8DOMConfiguration::kOnPrototype)
- DoInstallAttribute(prototype_template, name, attribute);
- if (location & V8DOMConfiguration::kOnInterface)
- NOTREACHED();
-}
-
-void InstallAttributeInternal(
- v8::Isolate* isolate,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- const V8DOMConfiguration::AttributeConfiguration& config,
- const DOMWrapperWorld& world) {
- DCHECK(!instance.IsEmpty() || !prototype.IsEmpty());
- if (!WorldConfigurationApplies(config, world))
- return;
-
- v8::Local<v8::Name> name = V8AtomicString(isolate, config.name);
- const unsigned location = config.property_location_configuration;
- DCHECK(location);
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- if (location & V8DOMConfiguration::kOnInstance && !instance.IsEmpty())
- DoInstallAttribute(context, instance, name, config);
- if (location & V8DOMConfiguration::kOnPrototype && !prototype.IsEmpty())
- DoInstallAttribute(context, prototype, name, config);
- if (location & V8DOMConfiguration::kOnInterface)
- NOTREACHED();
-}
-
-enum class AccessorType {
- Getter,
- Setter,
-};
-
-template <class FunctionOrTemplate>
-v8::Local<FunctionOrTemplate> CreateAccessorFunctionOrTemplate(
- v8::Isolate*,
- v8::FunctionCallback,
- V8PrivateProperty::CachedAccessor,
- v8::Local<v8::Value> data,
- v8::Local<v8::Signature>,
- const char* name,
- AccessorType,
- V8DOMConfiguration::AccessCheckConfiguration access_check_configuration,
- v8::SideEffectType side_effect_type = v8::SideEffectType::kHasSideEffect);
-
-template <>
-v8::Local<v8::FunctionTemplate>
-CreateAccessorFunctionOrTemplate<v8::FunctionTemplate>(
- v8::Isolate* isolate,
- v8::FunctionCallback callback,
- V8PrivateProperty::CachedAccessor cached_property_key,
- v8::Local<v8::Value> data,
- v8::Local<v8::Signature> signature,
- const char* name,
- AccessorType type,
- V8DOMConfiguration::AccessCheckConfiguration access_check_configuration,
- v8::SideEffectType side_effect_type) {
- v8::Local<v8::FunctionTemplate> function_template;
- if (callback) {
- // https://heycam.github.io/webidl/#dfn-attribute-getter has:
- //
- // 5. Perform ! SetFunctionLength(|F|, 0).
- //
- // https://heycam.github.io/webidl/#dfn-attribute-setter has:
- //
- // 7. Perform ! SetFunctionLength(|F|, 1).
- int length = type == AccessorType::Getter ? 0 : 1;
-
- if (cached_property_key != V8PrivateProperty::CachedAccessor::kNone) {
- function_template = v8::FunctionTemplate::NewWithCache(
- isolate, callback,
- V8PrivateProperty::GetCachedAccessor(isolate, cached_property_key)
- .GetPrivate(),
- data, signature, length, side_effect_type);
- } else {
- function_template = v8::FunctionTemplate::New(
- isolate, callback, data, signature, length,
- v8::ConstructorBehavior::kThrow, side_effect_type);
- }
-
- if (!function_template.IsEmpty()) {
- function_template->SetAcceptAnyReceiver(
- access_check_configuration == V8DOMConfiguration::kDoNotCheckAccess);
-
- // https://heycam.github.io/webidl/#dfn-attribute-getter has:
- //
- // 3. Let |name| be the string "get " prepended to |attribute|’s
- // identifier.
- //
- // 4. Perform ! SetFunctionName(|F|, |name|).
- //
- // https://heycam.github.io/webidl/#dfn-attribute-setter has:
- //
- // 5. Let |name| be the string "set " prepended to |id|.
- //
- // 6. Perform ! SetFunctionName(|F|, |name|).
- //
- // SetClassName on a FunctionTemplate that doesn't have a prototype just
- // sets the .name property of the generated function.
- WTF::StringBuilder full_name_builder;
- full_name_builder.Append(type == AccessorType::Getter ? "get " : "set ",
- 4);
- full_name_builder.Append(name);
- function_template->SetClassName(
- V8AtomicString(isolate, full_name_builder.ToString()));
- }
- }
- return function_template;
-}
-
-template <>
-v8::Local<v8::Function> CreateAccessorFunctionOrTemplate<v8::Function>(
- v8::Isolate* isolate,
- v8::FunctionCallback callback,
- V8PrivateProperty::CachedAccessor,
- v8::Local<v8::Value> data,
- v8::Local<v8::Signature> signature,
- const char* name,
- AccessorType type,
- V8DOMConfiguration::AccessCheckConfiguration access_check_configuration,
- v8::SideEffectType side_effect_type) {
- if (!callback)
- return v8::Local<v8::Function>();
-
- v8::Local<v8::FunctionTemplate> function_template =
- CreateAccessorFunctionOrTemplate<v8::FunctionTemplate>(
- isolate, callback, V8PrivateProperty::CachedAccessor::kNone, data,
- signature, name, type, access_check_configuration, side_effect_type);
- if (function_template.IsEmpty())
- return v8::Local<v8::Function>();
-
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Function> function;
- if (!function_template->GetFunction(context).ToLocal(&function))
- return v8::Local<v8::Function>();
- return function;
-}
-
-// Returns true iff |target| is the empty handle to v8::Object.
-// Returns false especially when |target| is a handle to v8::ObjectTemplate.
-bool IsObjectAndEmpty(v8::Local<v8::Object> target) {
- return target.IsEmpty();
-}
-
-bool IsObjectAndEmpty(v8::Local<v8::Function> target) {
- return target.IsEmpty();
-}
-
-bool IsObjectAndEmpty(v8::Local<v8::ObjectTemplate> target) {
- return false;
-}
-
-bool IsObjectAndEmpty(v8::Local<v8::FunctionTemplate> target) {
- return false;
-}
-
-template <class ObjectOrTemplate, class FunctionOrTemplate>
-void InstallAccessorInternal(
- v8::Isolate* isolate,
- v8::Local<ObjectOrTemplate> instance_or_template,
- v8::Local<ObjectOrTemplate> prototype_or_template,
- v8::Local<FunctionOrTemplate> interface_or_template,
- v8::Local<v8::Signature> signature,
- const V8DOMConfiguration::AccessorConfiguration& config,
- const DOMWrapperWorld& world) {
- DCHECK(!IsObjectAndEmpty(instance_or_template) ||
- !IsObjectAndEmpty(prototype_or_template) ||
- !IsObjectAndEmpty(interface_or_template));
- if (!WorldConfigurationApplies(config, world))
- return;
-
- v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
- v8::FunctionCallback getter_callback = config.getter;
- v8::FunctionCallback setter_callback = config.setter;
- auto cached_property_key = V8PrivateProperty::CachedAccessor::kNone;
- bool is_window_document = static_cast<V8PrivateProperty::CachedAccessor>(
- config.cached_property_key) ==
- V8PrivateProperty::CachedAccessor::kWindowDocument;
- if (!is_window_document || world.IsMainWorld()) {
- cached_property_key = static_cast<V8PrivateProperty::CachedAccessor>(
- config.cached_property_key);
- }
-
- // Support [LegacyLenientThis] and attributes with Promise types by not
- // specifying the signature. V8 does not do the type checking against holder
- // if no signature is specified. Note that info.Holder() passed to callbacks
- // will be *unsafe*.
- if (config.holder_check_configuration ==
- V8DOMConfiguration::kDoNotCheckHolder)
- signature = v8::Local<v8::Signature>();
-
- V8DOMConfiguration::AccessCheckConfiguration getter_access_check =
- static_cast<V8DOMConfiguration::AccessCheckConfiguration>(
- config.getter_access_check_configuration);
- V8DOMConfiguration::AccessCheckConfiguration setter_access_check =
- static_cast<V8DOMConfiguration::AccessCheckConfiguration>(
- config.setter_access_check_configuration);
-
- const unsigned location = config.property_location_configuration;
- v8::SideEffectType getter_side_effect_type =
- config.getter_side_effect_type == V8DOMConfiguration::kHasNoSideEffect
- ? v8::SideEffectType::kHasNoSideEffect
- : v8::SideEffectType::kHasSideEffect;
- DCHECK(location);
- if (location &
- (V8DOMConfiguration::kOnInstance | V8DOMConfiguration::kOnPrototype)) {
- v8::Local<FunctionOrTemplate> getter =
- CreateAccessorFunctionOrTemplate<FunctionOrTemplate>(
- isolate, getter_callback, cached_property_key,
- v8::Local<v8::Value>(), signature, config.name,
- AccessorType::Getter, getter_access_check, getter_side_effect_type);
- v8::Local<FunctionOrTemplate> setter =
- CreateAccessorFunctionOrTemplate<FunctionOrTemplate>(
- isolate, setter_callback, V8PrivateProperty::CachedAccessor::kNone,
- v8::Local<v8::Value>(), signature, config.name,
- AccessorType::Setter, setter_access_check);
- if (location & V8DOMConfiguration::kOnInstance &&
- !IsObjectAndEmpty(instance_or_template)) {
- instance_or_template->SetAccessorProperty(
- name, getter, setter,
- static_cast<v8::PropertyAttribute>(config.attribute));
- }
- if (location & V8DOMConfiguration::kOnPrototype &&
- !IsObjectAndEmpty(prototype_or_template)) {
- prototype_or_template->SetAccessorProperty(
- name, getter, setter,
- static_cast<v8::PropertyAttribute>(config.attribute));
- }
- }
- if (location & V8DOMConfiguration::kOnInterface &&
- !IsObjectAndEmpty(interface_or_template)) {
- // Attributes installed on the interface object must be static
- // attributes, so no need to specify a signature, i.e. no need to do
- // type check against a holder.
- v8::Local<FunctionOrTemplate> getter =
- CreateAccessorFunctionOrTemplate<FunctionOrTemplate>(
- isolate, getter_callback, V8PrivateProperty::CachedAccessor::kNone,
- v8::Local<v8::Value>(), v8::Local<v8::Signature>(), config.name,
- AccessorType::Getter, getter_access_check, getter_side_effect_type);
- v8::Local<FunctionOrTemplate> setter =
- CreateAccessorFunctionOrTemplate<FunctionOrTemplate>(
- isolate, setter_callback, V8PrivateProperty::CachedAccessor::kNone,
- v8::Local<v8::Value>(), v8::Local<v8::Signature>(), config.name,
- AccessorType::Setter, setter_access_check);
- interface_or_template->SetAccessorProperty(
- name, getter, setter,
- static_cast<v8::PropertyAttribute>(config.attribute));
- }
-}
-
-v8::Local<v8::Primitive> ValueForConstant(
- v8::Isolate* isolate,
- const V8DOMConfiguration::ConstantConfiguration& constant) {
- v8::Local<v8::Primitive> value;
- switch (constant.type) {
- case V8DOMConfiguration::kConstantTypeShort:
- case V8DOMConfiguration::kConstantTypeLong:
- case V8DOMConfiguration::kConstantTypeUnsignedShort:
- value = v8::Integer::New(isolate, constant.ivalue);
- break;
- case V8DOMConfiguration::kConstantTypeUnsignedLong:
- value = v8::Integer::NewFromUnsigned(isolate, constant.ivalue);
- break;
- case V8DOMConfiguration::kConstantTypeFloat:
- case V8DOMConfiguration::kConstantTypeDouble:
- value = v8::Number::New(isolate, constant.dvalue);
- break;
- default:
- NOTREACHED();
- }
- return value;
-}
-
-void InstallConstantInternal(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const V8DOMConfiguration::ConstantConfiguration& constant) {
- v8::Local<v8::String> constant_name = V8AtomicString(isolate, constant.name);
- v8::PropertyAttribute attributes =
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
- v8::Local<v8::Primitive> value = ValueForConstant(isolate, constant);
- interface_template->Set(constant_name, value, attributes);
- prototype_template->Set(constant_name, value, attributes);
-}
-
-void InstallConstantInternal(
- v8::Isolate* isolate,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Object> prototype,
- const V8DOMConfiguration::ConstantConfiguration& constant) {
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Name> name = V8AtomicString(isolate, constant.name);
- v8::PropertyAttribute attributes =
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
- v8::Local<v8::Primitive> value = ValueForConstant(isolate, constant);
- interface->DefineOwnProperty(context, name, value, attributes).ToChecked();
- prototype->DefineOwnProperty(context, name, value, attributes).ToChecked();
-}
-
-template <class Configuration>
-void AddMethodToTemplate(v8::Isolate* isolate,
- v8::Local<v8::Template> v8_template,
- v8::Local<v8::FunctionTemplate> function_template,
- const Configuration& method) {
- v8_template->Set(method.MethodName(isolate), function_template,
- static_cast<v8::PropertyAttribute>(method.attribute));
-}
-
-template <>
-void AddMethodToTemplate(
- v8::Isolate* isolate,
- v8::Local<v8::Template> v8_template,
- v8::Local<v8::FunctionTemplate> function_template,
- const V8DOMConfiguration::SymbolKeyedMethodConfiguration& method) {
- // The order matters here: if the Symbol is added first, the Function object
- // will have no associated name. For example, WebIDL states, among other
- // things, that a pair iterator's @@iterator Function object's name must be
- // set to "entries".
- if (method.symbol_alias) {
- v8_template->Set(V8AtomicString(isolate, method.symbol_alias),
- function_template);
- }
- v8_template->Set(method.MethodName(isolate), function_template,
- static_cast<v8::PropertyAttribute>(method.attribute));
-}
-
-template <class Configuration>
-void InstallMethodInternal(v8::Isolate* isolate,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature> signature,
- const Configuration& method,
- const DOMWrapperWorld& world,
- const v8::CFunction* v8_c_function = nullptr) {
- if (!WorldConfigurationApplies(method, world))
- return;
-
- v8::FunctionCallback callback = method.callback;
- // Promise-returning functions need to return a reject promise when
- // an exception occurs. This includes a case that the receiver object is not
- // of the type. So, we disable the type check of the receiver object on V8
- // side so that V8 won't throw. Instead, we do the check on Blink side and
- // convert an exception to a reject promise.
- if (method.holder_check_configuration ==
- V8DOMConfiguration::kDoNotCheckHolder)
- signature = v8::Local<v8::Signature>();
-
- DCHECK(method.property_location_configuration);
- v8::SideEffectType side_effect_type =
- method.side_effect_type == V8DOMConfiguration::kHasNoSideEffect
- ? v8::SideEffectType::kHasNoSideEffect
- : v8::SideEffectType::kHasSideEffect;
- if (method.property_location_configuration &
- (V8DOMConfiguration::kOnInstance | V8DOMConfiguration::kOnPrototype)) {
- v8::Local<v8::FunctionTemplate> function_template =
- v8::FunctionTemplate::New(
- isolate, callback, v8::Local<v8::Value>(), signature, method.length,
- v8::ConstructorBehavior::kThrow, side_effect_type, v8_c_function);
- function_template->SetAcceptAnyReceiver(
- method.access_check_configuration ==
- V8DOMConfiguration::kDoNotCheckAccess);
- if (method.property_location_configuration &
- V8DOMConfiguration::kOnInstance) {
- AddMethodToTemplate(isolate, instance_template, function_template,
- method);
- }
- if (method.property_location_configuration &
- V8DOMConfiguration::kOnPrototype) {
- AddMethodToTemplate(isolate, prototype_template, function_template,
- method);
- }
- }
- if (method.property_location_configuration &
- V8DOMConfiguration::kOnInterface) {
- // Operations installed on the interface object must be static methods, so
- // no need to specify a signature, i.e. no need to do type check against a
- // holder.
- v8::Local<v8::FunctionTemplate> function_template =
- v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(),
- v8::Local<v8::Signature>(), method.length,
- v8::ConstructorBehavior::kThrow,
- side_effect_type);
- // Similarly, there is no need to do an access check for static methods, as
- // there is no holder to check against.
- AddMethodToTemplate(isolate, interface_template, function_template, method);
- }
-}
-
-void InstallMethodInternal(
- v8::Isolate* isolate,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature> signature,
- const V8DOMConfiguration::MethodConfiguration& config,
- const DOMWrapperWorld& world) {
- DCHECK(!instance.IsEmpty() || !prototype.IsEmpty() || !interface.IsEmpty());
- if (!WorldConfigurationApplies(config, world))
- return;
-
- v8::Local<v8::String> name = config.MethodName(isolate);
- v8::FunctionCallback callback = config.callback;
- // Promise-returning functions need to return a reject promise when
- // an exception occurs. This includes a case that the receiver object is not
- // of the type. So, we disable the type check of the receiver object on V8
- // side so that V8 won't throw. Instead, we do the check on Blink side and
- // convert an exception to a reject promise.
- if (config.holder_check_configuration ==
- V8DOMConfiguration::kDoNotCheckHolder)
- signature = v8::Local<v8::Signature>();
-
- const unsigned location = config.property_location_configuration;
- v8::SideEffectType side_effect_type =
- config.side_effect_type == V8DOMConfiguration::kHasNoSideEffect
- ? v8::SideEffectType::kHasNoSideEffect
- : v8::SideEffectType::kHasSideEffect;
- DCHECK(location);
- if (location &
- (V8DOMConfiguration::kOnInstance | V8DOMConfiguration::kOnPrototype)) {
- v8::Local<v8::FunctionTemplate> function_template =
- v8::FunctionTemplate::New(
- isolate, callback, v8::Local<v8::Value>(), signature, config.length,
- v8::ConstructorBehavior::kThrow, side_effect_type);
- function_template->SetAcceptAnyReceiver(
- config.access_check_configuration ==
- V8DOMConfiguration::kDoNotCheckAccess);
- v8::Local<v8::Function> function =
- function_template->GetFunction(isolate->GetCurrentContext())
- .ToLocalChecked();
- function->SetName(name);
- if (location & V8DOMConfiguration::kOnInstance && !instance.IsEmpty()) {
- instance
- ->DefineOwnProperty(
- isolate->GetCurrentContext(), name, function,
- static_cast<v8::PropertyAttribute>(config.attribute))
- .ToChecked();
- }
- if (location & V8DOMConfiguration::kOnPrototype && !prototype.IsEmpty()) {
- prototype
- ->DefineOwnProperty(
- isolate->GetCurrentContext(), name, function,
- static_cast<v8::PropertyAttribute>(config.attribute))
- .ToChecked();
- }
- }
- if (location & V8DOMConfiguration::kOnInterface && !interface.IsEmpty()) {
- // Operations installed on the interface object must be static
- // operations, so no need to specify a signature, i.e. no need to do
- // type check against a holder.
- v8::Local<v8::FunctionTemplate> function_template =
- v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(),
- v8::Local<v8::Signature>(), config.length,
- v8::ConstructorBehavior::kThrow,
- side_effect_type);
- v8::Local<v8::Function> function =
- function_template->GetFunction(isolate->GetCurrentContext())
- .ToLocalChecked();
- function->SetName(name);
- interface->DefineOwnProperty(isolate->GetCurrentContext(), name, function, static_cast<v8::PropertyAttribute>(config.attribute)).ToChecked();
- }
-}
-
-} // namespace
-
-void V8DOMConfiguration::InstallAttributes(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const AttributeConfiguration* attributes,
- size_t attribute_count) {
- for (size_t i = 0; i < attribute_count; ++i)
- InstallAttributeInternal(isolate, instance_template, prototype_template,
- attributes[i], world);
-}
-
-void V8DOMConfiguration::InstallAttributes(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- const AttributeConfiguration* attributes,
- size_t attribute_count) {
- for (size_t i = 0; i < attribute_count; ++i) {
- InstallAttributeInternal(isolate, instance, prototype, attributes[i],
- world);
- }
-}
-
-void V8DOMConfiguration::InstallAttribute(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const AttributeConfiguration& attribute) {
- InstallAttributeInternal(isolate, instance_template, prototype_template,
- attribute, world);
-}
-
-void V8DOMConfiguration::InstallAttribute(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- const AttributeConfiguration& attribute) {
- InstallAttributeInternal(isolate, instance, prototype, attribute, world);
-}
-
-void V8DOMConfiguration::InstallAccessors(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature> signature,
- const AccessorConfiguration* accessors,
- size_t accessor_count) {
- for (size_t i = 0; i < accessor_count; ++i)
- InstallAccessorInternal(isolate, instance_template, prototype_template,
- interface_template, signature, accessors[i], world);
-}
-
-void V8DOMConfiguration::InstallAccessors(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature> signature,
- const AccessorConfiguration* accessors,
- size_t accessor_count) {
- for (size_t i = 0; i < accessor_count; ++i) {
- InstallAccessorInternal(isolate, instance, prototype, interface, signature,
- accessors[i], world);
- }
-}
-
-void V8DOMConfiguration::InstallAccessor(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature> signature,
- const AccessorConfiguration& accessor) {
- InstallAccessorInternal(isolate, instance_template, prototype_template,
- interface_template, signature, accessor, world);
-}
-
-void V8DOMConfiguration::InstallAccessor(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature> signature,
- const AccessorConfiguration& accessor) {
- InstallAccessorInternal(isolate, instance, prototype, interface, signature,
- accessor, world);
-}
-
-void V8DOMConfiguration::InstallConstants(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const ConstantConfiguration* constants,
- size_t constant_count) {
- for (size_t i = 0; i < constant_count; ++i) {
- InstallConstantInternal(isolate, interface_template, prototype_template,
- constants[i]);
- }
-}
-
-void V8DOMConfiguration::InstallConstant(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const ConstantConfiguration& constant) {
- InstallConstantInternal(isolate, interface_template, prototype_template,
- constant);
-}
-
-void V8DOMConfiguration::InstallConstant(
- v8::Isolate* isolate,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Object> prototype,
- const ConstantConfiguration& constant) {
- InstallConstantInternal(isolate, interface, prototype, constant);
-}
-
-void V8DOMConfiguration::InstallConstants(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const ConstantCallbackConfiguration* constants,
- size_t constant_count) {
- for (size_t i = 0; i < constant_count; ++i) {
- v8::Local<v8::String> name = V8AtomicString(isolate, constants[i].name);
- interface_template->SetNativeDataProperty(
- name, constants[i].getter, nullptr, v8::Local<v8::Value>(),
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete),
- v8::Local<v8::AccessorSignature>(), v8::DEFAULT,
- v8::SideEffectType::kHasNoSideEffect,
- v8::SideEffectType::kHasSideEffect);
- prototype_template->SetNativeDataProperty(
- name, constants[i].getter, nullptr, v8::Local<v8::Value>(),
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete),
- v8::Local<v8::AccessorSignature>(), v8::DEFAULT,
- v8::SideEffectType::kHasNoSideEffect,
- v8::SideEffectType::kHasSideEffect);
- }
-}
-
-void V8DOMConfiguration::InstallConstants(
- v8::Isolate* isolate,
- v8::Local<v8::Function> interface_object,
- v8::Local<v8::Object> prototype_object,
- const V8DOMConfiguration::ConstantConfiguration* constants,
- size_t constant_count) {
- for (size_t i = 0; i < constant_count; ++i) {
- InstallConstantInternal(isolate, interface_object, prototype_object,
- constants[i]);
- }
-}
-
-void V8DOMConfiguration::InstallConstantWithGetter(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const char* name,
- v8::AccessorNameGetterCallback getter) {
- v8::Local<v8::String> constant_name = V8AtomicString(isolate, name);
- v8::PropertyAttribute attributes =
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
- interface_template->SetNativeDataProperty(constant_name, getter, nullptr,
- v8::Local<v8::Value>(), attributes);
- prototype_template->SetNativeDataProperty(constant_name, getter, nullptr,
- v8::Local<v8::Value>(), attributes);
-}
-
-void V8DOMConfiguration::InstallMethods(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature> signature,
- const MethodConfiguration* methods,
- size_t method_count) {
- for (size_t i = 0; i < method_count; ++i)
- InstallMethodInternal(isolate, instance_template, prototype_template,
- interface_template, signature, methods[i], world);
-}
-
-void V8DOMConfiguration::InstallMethods(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature> signature,
- const NoAllocDirectCallMethodConfiguration* methods,
- size_t method_count) {
- for (size_t i = 0; i < method_count; ++i) {
- InstallMethodInternal(
- isolate, instance_template, prototype_template, interface_template,
- signature, methods[i].method_config, world, &methods[i].v8_c_function);
- }
-}
-
-void V8DOMConfiguration::InstallMethod(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature> signature,
- const MethodConfiguration& method) {
- InstallMethodInternal(isolate, instance_template, prototype_template,
- interface_template, signature, method, world);
-}
-
-void V8DOMConfiguration::InstallMethods(v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature> signature,
- const MethodConfiguration* methods,
- size_t method_count) {
- for (size_t i = 0; i < method_count; ++i) {
- InstallMethodInternal(isolate, instance, prototype, interface, signature,
- methods[i], world);
- }
-}
-
-void V8DOMConfiguration::InstallMethod(v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature> signature,
- const MethodConfiguration& method) {
- InstallMethodInternal(isolate, instance, prototype, interface, signature,
- method, world);
-}
-
-void V8DOMConfiguration::InstallMethod(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::Signature> signature,
- const SymbolKeyedMethodConfiguration& method) {
- InstallMethodInternal(isolate, v8::Local<v8::ObjectTemplate>(),
- prototype_template, v8::Local<v8::FunctionTemplate>(),
- signature, method, world);
-}
-
-void V8DOMConfiguration::InitializeDOMInterfaceTemplate(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- const char* interface_name,
- v8::Local<v8::FunctionTemplate> parent_interface_template,
- uint32_t v8_internal_field_count) {
- interface_template->SetClassName(V8AtomicString(isolate, interface_name));
- interface_template->ReadOnlyPrototype();
- v8::Local<v8::ObjectTemplate> instance_template =
- interface_template->InstanceTemplate();
- v8::Local<v8::ObjectTemplate> prototype_template =
- interface_template->PrototypeTemplate();
- instance_template->SetInternalFieldCount(v8_internal_field_count);
-
- // We intentionally don't set the class string to the platform object
- // (|instanceTemplate|), and set the class string "InterfaceName", without
- // "Prototype", to the prototype object (|prototypeTemplate|) despite a fact
- // that the current WebIDL spec (as of Feb 2017) requires to set the class
- // string "InterfaceName" for the platform objects and
- // "InterfaceNamePrototype" for the interface prototype object, because we
- // think it's more consistent with ECMAScript 2016.
- // See also https://crbug.com/643712
- // https://heycam.github.io/webidl/#es-platform-objects
- // https://heycam.github.io/webidl/#interface-prototype-object
- //
- // Note that V8 minor GC does not collect an object which has an own property.
- // So, if we set the class string to the platform object as an own property,
- // it prevents V8 minor GC to collect the object (V8 minor GC only collects
- // an empty object). If set, a web test fast/dom/minor-dom-gc.html fails.
- SetClassString(isolate, prototype_template, interface_name);
-
- if (!parent_interface_template.IsEmpty()) {
- interface_template->Inherit(parent_interface_template);
- // Marks the prototype object as one of native-backed objects.
- // This is needed since bug 110436 asks WebKit to tell native-initiated
- // prototypes from pure-JS ones. This doesn't mark kinds "root" classes
- // like Node, where setting this changes prototype chain structure.
- // The value of this field is not used, only the count.
- prototype_template->SetInternalFieldCount(kV8PrototypeInternalFieldcount);
- }
-}
-
-v8::Local<v8::FunctionTemplate> V8DOMConfiguration::DomClassTemplate(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- WrapperTypeInfo* wrapper_type_info,
- InstallTemplateFunction configure_dom_class_template) {
- V8PerIsolateData* data = V8PerIsolateData::From(isolate);
- v8::Local<v8::FunctionTemplate> interface_template =
- data->FindV8Template(world, wrapper_type_info).As<v8::FunctionTemplate>();
- if (!interface_template.IsEmpty())
- return interface_template;
-
- // We assume all constructors have no JS-observable side effect.
- interface_template = v8::FunctionTemplate::New(
- isolate, V8ObjectConstructor::IsValidConstructorMode);
- configure_dom_class_template(isolate, world, interface_template);
- data->AddV8Template(world, wrapper_type_info, interface_template);
- return interface_template;
-}
-
-void V8DOMConfiguration::SetClassString(
- v8::Isolate* isolate,
- v8::Local<v8::ObjectTemplate> object_template,
- const char* class_string) {
- object_template->Set(
- v8::Symbol::GetToStringTag(isolate),
- V8AtomicString(isolate, class_string),
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h
deleted file mode 100644
index a88efd6e334..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h
+++ /dev/null
@@ -1,444 +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.
- * 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_BINDINGS_CORE_V8_V8_DOM_CONFIGURATION_H_
-#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_DOM_CONFIGURATION_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.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/v8_dom_wrapper.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
-#include "v8/include/v8-fast-api-calls.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-class CORE_EXPORT V8DOMConfiguration final {
- STATIC_ONLY(V8DOMConfiguration);
-
- public:
- // The following Configuration structs and install methods are used for
- // setting multiple properties on ObjectTemplate / FunctionTemplate, used
- // from the generated bindings initialization (ConfigureXXXTemplate).
- // This greatly reduces the binary size by moving from code driven setup to
- // data table driven setup.
-
- // Bitflags to show where the member will be defined.
- enum PropertyLocationConfiguration : unsigned {
- kOnInstance = 1 << 0,
- kOnPrototype = 1 << 1,
- kOnInterface = 1 << 2,
- };
-
- // TODO(dcheng): Make these enum classes.
- enum HolderCheckConfiguration : unsigned {
- kCheckHolder,
- kDoNotCheckHolder,
- };
-
- enum AccessCheckConfiguration : unsigned {
- kCheckAccess,
- kDoNotCheckAccess,
- };
-
- enum SideEffectConfiguration : unsigned {
- kHasSideEffect,
- kHasNoSideEffect,
- };
-
- enum AttributeGetterBehavior : unsigned {
- // The getter will be called each time the property is gotten.
- kAlwaysCallGetter,
- // After the first access, the property will be turned into a plain data
- // property, taking the value returned by the getter.
- kReplaceWithDataProperty,
- };
-
- // Bit field to select which worlds the member will be defined in.
- enum WorldConfiguration : unsigned {
- kMainWorld = 1 << 0,
- kNonMainWorlds = 1 << 1,
- kAllWorlds = kMainWorld | kNonMainWorlds,
- };
-
- // AttributeConfiguration translates into calls to SetNativeDataProperty() on
- // either of instance or prototype object (or their object template).
- struct AttributeConfiguration {
- DISALLOW_NEW();
-
- public:
- AttributeConfiguration& operator=(const AttributeConfiguration&) = delete;
-
- const char* name;
- v8::AccessorNameGetterCallback getter;
- v8::AccessorNameSetterCallback setter;
-
- // v8::PropertyAttribute
- unsigned attribute : 8;
- // PropertyLocationConfiguration
- unsigned property_location_configuration : 3;
- // HolderCheckConfiguration
- unsigned holder_check_configuration : 1;
- // SideEffectConfiguration
- unsigned getter_side_effect_type : 1;
- // AttributeGetterBehavior
- unsigned getter_behavior : 1;
- // WorldConfiguration
- unsigned world_configuration : 2;
- };
-
- static void InstallAttributes(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const AttributeConfiguration*,
- size_t attribute_count);
- static void InstallAttribute(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const AttributeConfiguration&);
-
- // If an empty handle is passed as |instance| or |prototype|, that object is
- // ignored and no properties are installed on that object.
- static void InstallAttributes(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- const AttributeConfiguration*,
- size_t attribute_count);
- static void InstallAttribute(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- const AttributeConfiguration&);
-
- // AccessorConfiguration translates into calls to SetAccessorProperty() on
- // either of instance, prototype, or interface object (or their object
- // template).
- struct AccessorConfiguration {
- DISALLOW_NEW();
-
- public:
- AccessorConfiguration& operator=(const AccessorConfiguration&) = delete;
-
- const char* name;
- v8::FunctionCallback getter;
- v8::FunctionCallback setter;
- // V8PrivateProperty::CachedAccessor
- unsigned cached_property_key : 2;
- // v8::PropertyAttribute
- unsigned attribute : 8;
- // PropertyLocationConfiguration
- unsigned property_location_configuration : 3;
- // HolderCheckConfiguration
- unsigned holder_check_configuration : 1;
- // AccessCheckConfiguration
- unsigned getter_access_check_configuration : 1;
- unsigned setter_access_check_configuration : 1;
- // SideEffectConfiguration
- unsigned getter_side_effect_type : 1;
- // WorldConfiguration
- unsigned world_configuration : 2;
- };
-
- static void InstallAccessors(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature>,
- const AccessorConfiguration*,
- size_t accessor_count);
- static void InstallAccessor(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature>,
- const AccessorConfiguration&);
-
- // If an empty handle is passed as |instance|, |prototype|, or |interface|,
- // then that object is ignored and no properties are installed on that object.
- static void InstallAccessors(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature>,
- const AccessorConfiguration*,
- size_t accessor_count);
- static void InstallAccessor(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature>,
- const AccessorConfiguration&);
-
- enum ConstantType {
- kConstantTypeShort,
- kConstantTypeLong,
- kConstantTypeUnsignedShort,
- kConstantTypeUnsignedLong,
- kConstantTypeFloat,
- kConstantTypeDouble
- };
-
- // ConstantConfiguration translates into calls to Set() for setting up an
- // object's constants. It sets the constant on both the FunctionTemplate and
- // the ObjectTemplate. PropertyAttributes is always ReadOnly.
- struct ConstantConfiguration {
- DISALLOW_NEW();
-
- public:
- constexpr ConstantConfiguration(const char* name,
- ConstantType type,
- int value)
- : name(name), type(type), ivalue(value) {}
- constexpr ConstantConfiguration(const char* name,
- ConstantType type,
- double value)
- : name(name), type(type), dvalue(value) {}
- ConstantConfiguration& operator=(const ConstantConfiguration&) = delete;
-
- const char* name;
- ConstantType type;
- union {
- int ivalue;
- double dvalue;
- };
- };
-
- struct ConstantCallbackConfiguration {
- DISALLOW_NEW();
-
- public:
- constexpr ConstantCallbackConfiguration(
- const char* name,
- v8::AccessorNameGetterCallback getter)
- : name(name), getter(getter) {}
- ConstantCallbackConfiguration(const ConstantCallbackConfiguration&) =
- delete;
-
- ConstantCallbackConfiguration& operator=(
- const ConstantCallbackConfiguration&) = delete;
-
- const char* name;
- v8::AccessorNameGetterCallback getter;
- };
-
- // Constant installation
- //
- // installConstants and installConstant are used for simple constants. They
- // install constants using v8::Template::Set(), which results in a property
- // that is much faster to access from scripts.
- // installConstantWithGetter is used when some C++ code needs to be executed
- // when the constant is accessed, e.g. to handle deprecation or measuring
- // usage. The property appears the same to scripts, but is slower to access.
- static void InstallConstants(
- v8::Isolate*,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const ConstantConfiguration*,
- size_t constant_count);
- static void InstallConstant(
- v8::Isolate*,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const ConstantConfiguration&);
-
- static void InstallConstant(v8::Isolate*,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Object> prototype,
- const ConstantConfiguration&);
-
- static void InstallConstants(
- v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const ConstantCallbackConfiguration*,
- size_t constant_count);
-
- static void InstallConstants(v8::Isolate* isolate,
- v8::Local<v8::Function> interface_object,
- v8::Local<v8::Object> prototype_object,
- const ConstantConfiguration* constants,
- size_t constant_count);
-
- static void InstallConstantWithGetter(
- v8::Isolate*,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- const char* name,
- v8::AccessorNameGetterCallback);
-
- // MethodConfiguration translates into calls to Set() for setting up an
- // object's callbacks. It sets a method on instance, prototype or
- // interface object (or their object tepmplate).
- struct MethodConfiguration {
- DISALLOW_NEW();
-
- public:
- MethodConfiguration& operator=(const MethodConfiguration&) = delete;
-
- v8::Local<v8::String> MethodName(v8::Isolate* isolate) const {
- return V8AtomicString(isolate, name);
- }
-
- const char* name;
- v8::FunctionCallback callback;
- int length;
- // v8::PropertyAttribute
- unsigned attribute : 8;
- // PropertyLocationConfiguration
- unsigned property_location_configuration : 3;
- // HolderCheckConfiguration
- unsigned holder_check_configuration : 1;
- // AccessCheckConfiguration
- unsigned access_check_configuration : 1;
- // SideEffectConfiguration
- unsigned side_effect_type : 1;
- // WorldConfiguration
- unsigned world_configuration : 2;
- };
-
- struct SymbolKeyedMethodConfiguration {
- DISALLOW_NEW();
-
- public:
- SymbolKeyedMethodConfiguration& operator=(
- const SymbolKeyedMethodConfiguration&) = delete;
-
- v8::Local<v8::Name> MethodName(v8::Isolate* isolate) const {
- return get_symbol(isolate);
- }
-
- v8::Local<v8::Symbol> (*get_symbol)(v8::Isolate*);
- const char* symbol_alias;
- v8::FunctionCallback callback;
- // SymbolKeyedMethodConfiguration doesn't support per-world bindings.
- int length;
- // v8::PropertyAttribute
- unsigned attribute : 8;
- // PropertyLocationConfiguration
- unsigned property_location_configuration : 3;
- // HolderCheckConfiguration
- unsigned holder_check_configuration : 1;
- // AccessCheckConfiguration
- unsigned access_check_configuration : 1;
- // SideEffectConfiguration
- unsigned side_effect_type : 1;
- };
-
- struct NoAllocDirectCallMethodConfiguration {
- DISALLOW_NEW();
-
- public:
- NoAllocDirectCallMethodConfiguration& operator=(
- const NoAllocDirectCallMethodConfiguration&) = delete;
-
- MethodConfiguration method_config;
- v8::CFunction v8_c_function;
- };
-
- static void InstallMethods(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature>,
- const MethodConfiguration*,
- size_t method_count);
- static void InstallMethods(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature>,
- const NoAllocDirectCallMethodConfiguration*,
- size_t method_count);
-
- static void InstallMethod(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate> instance_template,
- v8::Local<v8::ObjectTemplate> prototype_template,
- v8::Local<v8::FunctionTemplate> interface_template,
- v8::Local<v8::Signature>,
- const MethodConfiguration&);
- static void InstallMethod(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::ObjectTemplate>,
- v8::Local<v8::Signature>,
- const SymbolKeyedMethodConfiguration&);
-
- // If an empty handle is passed as |instance|, |prototype|, or |interface|,
- // then that object is ignored and no properties are installed on that object.
- static void InstallMethods(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature>,
- const MethodConfiguration*,
- size_t method_count);
- static void InstallMethod(v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::Signature>,
- const MethodConfiguration&);
-
- static void InitializeDOMInterfaceTemplate(
- v8::Isolate*,
- v8::Local<v8::FunctionTemplate> interface_template,
- const char* interface_name,
- v8::Local<v8::FunctionTemplate> parent_interface_template,
- uint32_t v8_internal_field_count);
-
- static v8::Local<v8::FunctionTemplate> DomClassTemplate(
- v8::Isolate*,
- const DOMWrapperWorld&,
- WrapperTypeInfo*,
- InstallTemplateFunction);
-
- // Sets the class string of platform objects, interface prototype objects,
- // etc. See also http://heycam.github.io/webidl/#dfn-class-string
- static void SetClassString(v8::Isolate*,
- v8::Local<v8::ObjectTemplate>,
- const char* class_string);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_DOM_CONFIGURATION_H_
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 b91e5c1568c..2562829488b 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
@@ -36,33 +36,6 @@ using Traceable = const void*;
using Graph = v8::EmbedderGraph;
using Detachedness = v8::EmbedderGraph::Node::Detachedness;
-// Information about whether a node is attached to the main DOM tree
-// or not. It is computed as follows:
-// 1) A ExecutionContext with IsContextDestroyed() = true is detached.
-// 2) A ExecutionContext with IsContextDestroyed() = false is attached.
-// 3) A Node that is not connected to any ExecutionContext is detached.
-// 4) A Node that is connected to a detached ExecutionContext is detached.
-// 5) A Node that is connected to an attached ExecutionContext is attached.
-// 6) A ScriptWrappable that is reachable from an attached Node is
-// attached.
-// 7) A ScriptWrappable that is reachable from a detached Node is
-// detached.
-// 8) A ScriptWrappable that is not reachable from any Node is
-// considered (conservatively) as attached.
-// The unknown state applies to ScriptWrappables during graph
-// traversal when we don't have reachability information yet.
-Detachedness DetachednessFromWrapper(v8::Isolate* isolate,
- uint16_t class_id,
- v8::Local<v8::Object> v8_value) {
- if (class_id != WrapperTypeInfo::kNodeClassId)
- return Detachedness::kUnknown;
- Node* node = V8Node::ToImpl(v8_value);
- Node* root = V8GCController::OpaqueRootForGC(isolate, node);
- if (root->isConnected() && node->GetExecutionContext())
- return Detachedness::kAttached;
- return Detachedness::kDetached;
-}
-
class EmbedderNode : public Graph::Node {
public:
EmbedderNode(const char* name,
@@ -156,9 +129,7 @@ EmbedderNode* NodeBuilder::GraphNode(Traceable traceable,
// into its own subgraph to identify and filter subgraphs that only consist of
// internals. Roots, which are potentially Blink only, are transitively
// traversed after handling JavaScript related objects.
-class GC_PLUGIN_IGNORE(
- "This class is not managed by Oilpan but GC plugin recognizes it as such "
- "due to Trace methods.") V8EmbedderGraphBuilder
+class V8EmbedderGraphBuilder
: public Visitor,
public v8::PersistentHandleVisitor,
public v8::EmbedderHeapTracer::TracedGlobalHandleVisitor {
@@ -389,7 +360,6 @@ class GC_PLUGIN_IGNORE(
void AddEphemeronEdgeName(Traceable backing, State* parent, State* current);
void VisitPersistentHandleInternal(v8::Local<v8::Object>, uint16_t);
- void VisitPendingActivities();
void VisitBlinkRoots();
void VisitTransitiveClosure();
@@ -449,7 +419,6 @@ void V8EmbedderGraphBuilder::BuildEmbedderGraph() {
ThreadState::Current()->unified_heap_controller());
tracer->IterateTracedGlobalHandles(this);
VisitBlinkRoots();
- VisitPendingActivities();
VisitTransitiveClosure();
DCHECK(worklist_.empty());
// ephemeron_worklist_ might not be empty. We might have an ephemeron whose
@@ -467,7 +436,8 @@ void V8EmbedderGraphBuilder::VisitPersistentHandleInternal(
if (!traceable)
return;
Graph::Node* wrapper = node_builder_->GraphNode(v8_value);
- auto detachedness = DetachednessFromWrapper(isolate_, class_id, v8_value);
+ auto detachedness = V8GCController::DetachednessFromWrapper(
+ isolate_, v8_value.As<v8::Value>(), class_id, nullptr);
EmbedderNode* graph_node = node_builder_->GraphNode(
traceable, traceable->NameInHeapSnapshot(), wrapper, detachedness);
State* const to_process_state = EnsureState(traceable, graph_node);
@@ -650,20 +620,6 @@ void V8EmbedderGraphBuilder::VisitEphemeron(
value_trace_descriptor.callback));
}
-void V8EmbedderGraphBuilder::VisitPendingActivities() {
- // Ownership of the new node is transferred to the graph_.
- EmbedderNode* root =
- static_cast<EmbedderNode*>(graph_->AddNode(std::unique_ptr<Graph::Node>(
- new EmbedderRootNode("Pending activities"))));
- EnsureRootState(root);
- ParentScope parent(this, root);
- auto* asw_manager =
- V8PerIsolateData::From(isolate_)->GetActiveScriptWrappableManager();
- if (asw_manager) {
- asw_manager->IterateActiveScriptWrappables(this);
- }
-}
-
void V8EmbedderGraphBuilder::VisitBlinkRoots() {
{
EmbedderNode* root = static_cast<EmbedderNode*>(graph_->AddNode(
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 fb7bba9d23f..69256e73cb1 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
@@ -57,22 +57,41 @@
namespace blink {
-Node* V8GCController::OpaqueRootForGC(v8::Isolate*, Node* node) {
+namespace {
+
+const Node& OpaqueRootForGC(v8::Isolate*, const Node* node) {
DCHECK(node);
if (node->isConnected())
- return &node->GetDocument();
+ return node->GetDocument();
if (auto* attr = DynamicTo<Attr>(node)) {
Node* owner_element = attr->ownerElement();
if (!owner_element)
- return node;
+ return *node;
node = owner_element;
}
while (Node* parent = node->ParentOrShadowHostOrTemplateHostNode())
node = parent;
- return node;
+ return *node;
+}
+
+} // namespace
+
+// static
+v8::EmbedderGraph::Node::Detachedness V8GCController::DetachednessFromWrapper(
+ v8::Isolate* isolate,
+ const v8::Local<v8::Value>& v8_value,
+ uint16_t class_id,
+ void*) {
+ if (class_id != WrapperTypeInfo::kNodeClassId)
+ return v8::EmbedderGraph::Node::Detachedness::kUnknown;
+ const auto& root_node =
+ OpaqueRootForGC(isolate, V8Node::ToImpl(v8_value.As<v8::Object>()));
+ if (root_node.isConnected() && root_node.GetExecutionContext())
+ return v8::EmbedderGraph::Node::Detachedness::kAttached;
+ return v8::EmbedderGraph::Node::Detachedness::kDetached;
}
#if !BUILDFLAG(USE_V8_OILPAN)
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h
index 83f936e483e..e390435508f 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h
@@ -45,7 +45,18 @@ class CORE_EXPORT V8GCController {
STATIC_ONLY(V8GCController);
public:
- static Node* OpaqueRootForGC(v8::Isolate*, Node*);
+ // Information about whether a wrapper is attached to the main DOM tree
+ // or not. It is computed as follows:
+ // 1) A ExecutionContext with IsContextDestroyed() = true is detached.
+ // 2) A ExecutionContext with IsContextDestroyed() = false is attached.
+ // 3) A Node that is reachable from a detached ExecutionContext is detached.
+ // 4) A Node that is reachable from an attached ExecutionContext is attached.
+ // 5) Any non-Node wrappers return unknown.
+ static v8::EmbedderGraph::Node::Detachedness DetachednessFromWrapper(
+ v8::Isolate*,
+ const v8::Local<v8::Value>&,
+ uint16_t class_id,
+ void*);
// Prologue and epilogue callbacks for V8 garbage collections.
static void GcPrologue(v8::Isolate*, v8::GCType, v8::GCCallbackFlags);
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 72248101cda..c98a621a366 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
@@ -44,7 +44,6 @@
#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/source_location.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/use_counter_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h"
@@ -391,16 +390,9 @@ TrustedTypesCodeGenerationCheck(v8::Local<v8::Context> context,
return {true, v8::MaybeLocal<v8::String>()};
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionStringOrTrustedScript* string_or_trusted_script =
NativeValueTraits<V8UnionStringOrTrustedScript>::NativeValue(
context->GetIsolate(), source, exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrTrustedScript string_or_trusted_script;
- V8StringOrTrustedScript::ToImpl(
- context->GetIsolate(), source, string_or_trusted_script,
- UnionTypeConversionMode::kNotNullable, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException()) {
exception_state.ClearException();
// The input was a string or TrustedScript but the conversion failed.
@@ -408,18 +400,10 @@ TrustedTypesCodeGenerationCheck(v8::Local<v8::Context> context,
return {false, v8::MaybeLocal<v8::String>()};
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (is_code_like && string_or_trusted_script->IsString()) {
string_or_trusted_script->Set(MakeGarbageCollected<TrustedScript>(
string_or_trusted_script->GetAsString()));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (is_code_like && string_or_trusted_script.IsString()) {
- string_or_trusted_script = StringOrTrustedScript::FromTrustedScript(
- MakeGarbageCollected<TrustedScript>(
- string_or_trusted_script.GetAsString()));
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String stringified_source = TrustedTypesCheckForScript(
string_or_trusted_script, ToExecutionContext(context), exception_state);
@@ -501,14 +485,6 @@ static bool WasmExceptionsEnabledCallback(v8::Local<v8::Context> context) {
execution_context);
}
-static bool WasmSimdEnabledCallback(v8::Local<v8::Context> context) {
- ExecutionContext* execution_context = ToExecutionContext(context);
- if (!execution_context)
- return false;
-
- return RuntimeEnabledFeatures::WebAssemblySimdEnabled(execution_context);
-}
-
v8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
const char* message) {
return v8::Exception::RangeError(
@@ -624,12 +600,11 @@ static v8::MaybeLocal<v8::Promise> HostImportModuleDynamically(
ReferrerScriptInfo referrer_info =
ReferrerScriptInfo::FromV8HostDefinedOptions(
- context, v8_referrer->GetHostDefinedOptions());
+ context, v8_referrer->GetHostDefinedOptions(), referrer_resource_url);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- modulator->ResolveDynamically(module_request, referrer_resource_url,
- referrer_info, resolver);
+ modulator->ResolveDynamically(module_request, referrer_info, resolver);
return v8::Local<v8::Promise>::Cast(promise.V8Value());
}
@@ -670,7 +645,6 @@ static void InitializeV8Common(v8::Isolate* isolate) {
isolate->SetSharedArrayBufferConstructorEnabledCallback(
SharedArrayBufferConstructorEnabledCallback);
isolate->SetWasmExceptionsEnabledCallback(WasmExceptionsEnabledCallback);
- isolate->SetWasmSimdEnabledCallback(WasmSimdEnabledCallback);
isolate->SetHostImportModuleDynamicallyCallback(HostImportModuleDynamically);
isolate->SetHostInitializeImportMetaObjectCallback(
HostGetImportMetaProperties);
@@ -678,6 +652,11 @@ static void InitializeV8Common(v8::Isolate* isolate) {
V8ContextSnapshot::EnsureInterfaceTemplates(isolate);
WasmResponseExtensions::Initialize(isolate);
+
+ if (v8::HeapProfiler* profiler = isolate->GetHeapProfiler()) {
+ profiler->SetGetDetachednessCallback(
+ V8GCController::DetachednessFromWrapper, nullptr);
+ }
}
namespace {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc
index 185025ed059..69711164e4f 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc
@@ -4,6 +4,10 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_metrics.h"
+#include <cstdint>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -11,6 +15,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/page/page.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
@@ -77,6 +83,228 @@ void V8MetricsRecorder::AddMainThreadEvent(
.Record(ukm->recorder);
}
+namespace {
+
+#if BUILDFLAG(USE_V8_OILPAN)
+void ReportAtomicLatencyEvent(int64_t duration_us) {
+ UMA_HISTOGRAM_TIMES("V8.GC.Event.MainThread.Full.Atomic.Cpp",
+ base::TimeDelta::FromMicroseconds(duration_us));
+}
+
+// Helper function to convert a byte count to a KB count, capping at
+// INT_MAX if the number is larger than that.
+constexpr int32_t CappedSizeInKB(int64_t size_in_bytes) {
+ return base::saturated_cast<int32_t>(size_in_bytes / 1024);
+}
+
+// Helper function to convert a B/us count to a KB/ms count, capping at
+// INT_MAX if the number is larger than that.
+constexpr int32_t CappedEfficacyInKBPerMs(double efficacy_in_bytes_per_us) {
+ return base::saturated_cast<int32_t>(efficacy_in_bytes_per_us * 1000 / 1024);
+}
+
+void CheckCppEvents(const v8::metrics::GarbageCollectionFullCycle& event) {
+ // Check that all used values have been initialized.
+ DCHECK_NE(-1, event.total_cpp.mark_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.total_cpp.weak_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.total_cpp.compact_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.total_cpp.sweep_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_cpp.mark_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_cpp.weak_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_cpp.compact_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_cpp.sweep_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_atomic_cpp.mark_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_atomic_cpp.weak_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_atomic_cpp.compact_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.main_thread_atomic_cpp.sweep_wall_clock_duration_in_us);
+ DCHECK_NE(-1, event.objects_cpp.bytes_before);
+ DCHECK_NE(-1, event.objects_cpp.bytes_after);
+ DCHECK_NE(-1, event.objects_cpp.bytes_freed);
+ DCHECK_NE(-1, event.memory_cpp.bytes_freed);
+ DCHECK_NE(-1, event.efficiency_cpp_in_bytes_per_us);
+ DCHECK_NE(-1, event.main_thread_efficiency_cpp_in_bytes_per_us);
+ DCHECK_NE(-1, event.collection_rate_cpp_in_percent);
+}
+#endif // USE_V8_OILPAN
+
+} // namespace
+
+void V8MetricsRecorder::AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullCycle& event,
+ ContextId context_id) {
+#if BUILDFLAG(USE_V8_OILPAN)
+ // Cpp events should always be populated when building with USE_V8_OILPAN.
+ CheckCppEvents(event);
+ // Report throughput metrics:
+ UMA_HISTOGRAM_TIMES("V8.GC.Cycle.Full.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.total_cpp.mark_wall_clock_duration_in_us +
+ event.total_cpp.weak_wall_clock_duration_in_us +
+ event.total_cpp.compact_wall_clock_duration_in_us +
+ event.total_cpp.sweep_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES("V8.GC.Cycle.Full.Mark.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.total_cpp.mark_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES("V8.GC.Cycle.Full.Weak.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.total_cpp.weak_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES("V8.GC.Cycle.Full.Compact.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.total_cpp.compact_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES("V8.GC.Cycle.Full.Sweep.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.total_cpp.sweep_wall_clock_duration_in_us));
+
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Cycle.MainThread.Full.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_cpp.mark_wall_clock_duration_in_us +
+ event.main_thread_cpp.weak_wall_clock_duration_in_us +
+ event.main_thread_cpp.compact_wall_clock_duration_in_us +
+ event.main_thread_cpp.sweep_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Cycle.MainThread.Full.Mark.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_cpp.mark_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Cycle.MainThread.Full.Weak.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_cpp.weak_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Cycle.MainThread.Full.Compact.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_cpp.compact_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Cycle.MainThread.Full.Sweep.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_cpp.sweep_wall_clock_duration_in_us));
+
+ // Report latency metrics:
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Event.MainThread.Full.Atomic.Mark.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_atomic_cpp.mark_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Event.MainThread.Full.Atomic.Weak.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_atomic_cpp.weak_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Event.MainThread.Full.Atomic.Compact.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_atomic_cpp.compact_wall_clock_duration_in_us));
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Event.MainThread.Full.Atomic.Sweep.Cpp",
+ base::TimeDelta::FromMicroseconds(
+ event.main_thread_atomic_cpp.sweep_wall_clock_duration_in_us));
+ ReportAtomicLatencyEvent(
+ event.main_thread_atomic_cpp.mark_wall_clock_duration_in_us);
+ ReportAtomicLatencyEvent(
+ event.main_thread_atomic_cpp.weak_wall_clock_duration_in_us);
+ ReportAtomicLatencyEvent(
+ event.main_thread_atomic_cpp.compact_wall_clock_duration_in_us);
+ ReportAtomicLatencyEvent(
+ event.main_thread_atomic_cpp.sweep_wall_clock_duration_in_us);
+
+ // Report size metrics:
+ static constexpr size_t kMinSize = 1;
+ static constexpr size_t kMaxSize = 4 * 1024 * 1024;
+ static constexpr size_t kNumBuckets = 50;
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, object_size_before_histogram,
+ ("V8.GC.Cycle.Objects.Before.Full.Cpp", kMinSize, kMaxSize, kNumBuckets));
+ object_size_before_histogram.Count(
+ CappedSizeInKB(event.objects_cpp.bytes_before));
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, object_size_after_histogram,
+ ("V8.GC.Cycle.Objects.After.Full.Cpp", kMinSize, kMaxSize, kNumBuckets));
+ object_size_after_histogram.Count(
+ CappedSizeInKB(event.objects_cpp.bytes_after));
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, object_size_freed_histogram,
+ ("V8.GC.Cycle.Objects.Freed.Full.Cpp", kMinSize, kMaxSize, kNumBuckets));
+ object_size_freed_histogram.Count(
+ CappedSizeInKB(event.objects_cpp.bytes_freed));
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, memory_size_freed_histogram,
+ ("V8.GC.Cycle.Memory.Freed.Full.Cpp", kMinSize, kMaxSize, kNumBuckets));
+ memory_size_freed_histogram.Count(
+ CappedSizeInKB(event.memory_cpp.bytes_freed));
+
+ // Report efficacy metrics:
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, efficacy_histogram,
+ ("V8.GC.Cycle.Efficiency.Full.Cpp", kMinSize, kMaxSize, kNumBuckets));
+ efficacy_histogram.Count(
+ CappedEfficacyInKBPerMs(event.efficiency_cpp_in_bytes_per_us));
+
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, efficacy_main_thread_cpp_histogram,
+ ("V8.GC.Cycle.Efficiency.MainThread.Full.Cpp", kMinSize,
+ kMaxSize, kNumBuckets));
+ efficacy_main_thread_cpp_histogram.Count(CappedEfficacyInKBPerMs(
+ event.main_thread_efficiency_cpp_in_bytes_per_us));
+
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, collection_rate_histogram,
+ ("V8.GC.Cycle.CollectionRate.Full.Cpp", 0, 100, 20));
+ collection_rate_histogram.Count(base::saturated_cast<base::Histogram::Sample>(
+ 100 * event.collection_rate_cpp_in_percent));
+#endif // USE_V8_OILPAN
+}
+
+namespace {
+
+void ReportCppIncrementalLatencyEvent(int64_t duration_us) {
+ UMA_HISTOGRAM_TIMES("V8.GC.Event.MainThread.Full.Incremental.Cpp",
+ base::TimeDelta::FromMicroseconds(duration_us));
+}
+
+} // namespace
+
+void V8MetricsRecorder::AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadIncrementalMark& event,
+ ContextId context_id) {
+ if (event.cpp_wall_clock_duration_in_us != -1) {
+ // This is only a latency event.
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Event.MainThread.Full.Incremental.Mark.Cpp",
+ base::TimeDelta::FromMicroseconds(event.cpp_wall_clock_duration_in_us));
+ ReportCppIncrementalLatencyEvent(event.cpp_wall_clock_duration_in_us);
+ }
+}
+
+void V8MetricsRecorder::AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark&
+ batched_events,
+ ContextId context_id) {
+ for (auto event : batched_events.events) {
+ AddMainThreadEvent(event, context_id);
+ }
+}
+
+void V8MetricsRecorder::AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadIncrementalSweep& event,
+ ContextId context_id) {
+ if (event.cpp_wall_clock_duration_in_us != -1) {
+ // This is only a latency event.
+ UMA_HISTOGRAM_TIMES(
+ "V8.GC.Event.MainThread.Full.Incremental.Sweep.Cpp",
+ base::TimeDelta::FromMicroseconds(event.cpp_wall_clock_duration_in_us));
+ ReportCppIncrementalLatencyEvent(event.cpp_wall_clock_duration_in_us);
+ }
+}
+
+void V8MetricsRecorder::AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep&
+ batched_events,
+ ContextId context_id) {
+ for (auto event : batched_events.events) {
+ AddMainThreadEvent(event, context_id);
+ }
+}
+
void V8MetricsRecorder::NotifyIsolateDisposal() {
v8::metrics::Recorder::NotifyIsolateDisposal();
isolate_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.h
index 513796ccb1a..687b1c1ce5c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_metrics.h
@@ -33,6 +33,23 @@ class CORE_EXPORT V8MetricsRecorder : public v8::metrics::Recorder {
void AddMainThreadEvent(const v8::metrics::WasmModuleTieredUp& event,
ContextId context_id) override;
+ void AddMainThreadEvent(const v8::metrics::GarbageCollectionFullCycle& event,
+ ContextId context_id) override;
+ void AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadIncrementalMark& event,
+ ContextId context_id) override;
+ void AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark&
+ event,
+ ContextId context_id) override;
+ void AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadIncrementalSweep& event,
+ ContextId context_id) override;
+ void AddMainThreadEvent(
+ const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep&
+ event,
+ ContextId context_id) override;
+
void NotifyIsolateDisposal() override;
private:
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 43e2ca14dde..67f0f5d7a4b 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
@@ -56,7 +56,7 @@
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
@@ -114,7 +114,7 @@ v8::MaybeLocal<v8::Value> ThrowStackOverflowExceptionIfNeeded(
v8::MaybeLocal<v8::Script> CompileScriptInternal(
v8::Isolate* isolate,
- ExecutionContext* execution_context,
+ ScriptState* script_state,
const ScriptSourceCode& source_code,
v8::ScriptOrigin origin,
v8::ScriptCompiler::CompileOptions compile_options,
@@ -122,6 +122,8 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
inspector_compile_script_event::V8CacheResult* cache_result) {
v8::Local<v8::String> code = V8String(isolate, source_code.Source());
+ // TODO(kouhei): Plumb the ScriptState into this function and replace all
+ // Isolate->GetCurrentContext in this function with ScriptState->GetContext.
if (ScriptStreamer* streamer = source_code.Streamer()) {
// Final compile call for a streamed compilation.
// Streaming compilation may involve use of code cache.
@@ -129,8 +131,8 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
DCHECK(streamer->IsFinished());
DCHECK(!streamer->IsStreamingSuppressed());
return v8::ScriptCompiler::Compile(
- isolate->GetCurrentContext(),
- streamer->Source(v8::ScriptType::kClassic), code, origin);
+ script_state->GetContext(), streamer->Source(v8::ScriptType::kClassic),
+ code, origin);
}
// Allow inspector to use its own compilation cache store.
@@ -138,12 +140,13 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
// The probe below allows inspector to either inject the cached code
// or override compile_options to force eager compilation of code
// when producing the cache.
- probe::ApplyCompilationModeOverride(execution_context, source_code,
- &inspector_data, &compile_options);
+ probe::ApplyCompilationModeOverride(ExecutionContext::From(script_state),
+ source_code, &inspector_data,
+ &compile_options);
if (inspector_data) {
v8::ScriptCompiler::Source source(code, origin, inspector_data);
v8::MaybeLocal<v8::Script> script =
- v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
+ v8::ScriptCompiler::Compile(script_state->GetContext(), &source,
v8::ScriptCompiler::kConsumeCodeCache);
return script;
}
@@ -152,7 +155,7 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
case v8::ScriptCompiler::kNoCompileOptions:
case v8::ScriptCompiler::kEagerCompile: {
v8::ScriptCompiler::Source source(code, origin);
- return v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
+ return v8::ScriptCompiler::Compile(script_state->GetContext(), &source,
compile_options, no_cache_reason);
}
@@ -163,16 +166,27 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
V8CodeCache::CreateCachedData(cache_handler);
v8::ScriptCompiler::Source source(code, origin, cached_data);
v8::MaybeLocal<v8::Script> script =
- v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
+ v8::ScriptCompiler::Compile(script_state->GetContext(), &source,
v8::ScriptCompiler::kConsumeCodeCache);
+ // The ScriptState has an associated context. We expect the current
+ // context to match the context associated with Script context when
+ // compiling the script for main world. Hence it is safe to use the
+ // CodeCacheHost corresponding to the script execution context. For
+ // isolated world (for ex: extension scripts), the current context
+ // may not match the script context. Though currently code caching is
+ // disabled for extensions.
if (cached_data->rejected) {
cache_handler->ClearCachedMetadata(
+ ExecutionContext::GetCodeCacheHostFromContext(
+ ExecutionContext::From(script_state)),
CachedMetadataHandler::kClearPersistentStorage);
} else if (InDiscardExperiment()) {
// Experimentally free code cache from memory after first use. See
// http://crbug.com/1045052.
cache_handler->ClearCachedMetadata(
+ ExecutionContext::GetCodeCacheHostFromContext(
+ ExecutionContext::From(script_state)),
CachedMetadataHandler::kDiscardLocally);
}
if (cache_result) {
@@ -235,16 +249,16 @@ v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
sanitize_script_errors == SanitizeScriptErrors::kSanitize,
false, // is_wasm
false, // is_module
- referrer_info.ToV8HostDefinedOptions(isolate));
+ referrer_info.ToV8HostDefinedOptions(isolate, source.Url()));
if (!*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(kTraceEventCategoryGroup)) {
- return CompileScriptInternal(isolate, execution_context, source, origin,
+ return CompileScriptInternal(isolate, script_state, source, origin,
compile_options, no_cache_reason, nullptr);
}
inspector_compile_script_event::V8CacheResult cache_result;
v8::MaybeLocal<v8::Script> script =
- CompileScriptInternal(isolate, execution_context, source, origin,
+ CompileScriptInternal(isolate, script_state, source, origin,
compile_options, no_cache_reason, &cache_result);
TRACE_EVENT_END1(kTraceEventCategoryGroup, "v8.compile", "data",
[&](perfetto::TracedValue context) {
@@ -270,16 +284,17 @@ v8::MaybeLocal<v8::Module> V8ScriptRunner::CompileModule(
// |resource_is_shared_cross_origin| is always true and |resource_is_opaque|
// is always false because CORS is enforced to module scripts.
- v8::ScriptOrigin origin(isolate, V8String(isolate, file_name),
- start_position.line_.ZeroBasedInt(),
- start_position.column_.ZeroBasedInt(),
- true, // resource_is_shared_cross_origin
- -1, // script id
- v8::String::Empty(isolate), // source_map_url
- false, // resource_is_opaque
- false, // is_wasm
- true, // is_module
- referrer_info.ToV8HostDefinedOptions(isolate));
+ v8::ScriptOrigin origin(
+ isolate, V8String(isolate, file_name),
+ start_position.line_.ZeroBasedInt(),
+ start_position.column_.ZeroBasedInt(),
+ true, // resource_is_shared_cross_origin
+ -1, // script id
+ v8::String::Empty(isolate), // source_map_url
+ false, // resource_is_opaque
+ false, // is_wasm
+ true, // is_module
+ referrer_info.ToV8HostDefinedOptions(isolate, params.SourceURL()));
v8::Local<v8::String> code = V8String(isolate, params.GetSourceText());
inspector_compile_script_event::V8CacheResult cache_result;
@@ -314,13 +329,21 @@ v8::MaybeLocal<v8::Module> V8ScriptRunner::CompileModule(
v8::ScriptCompiler::Source source(code, origin, cached_data);
script = v8::ScriptCompiler::CompileModule(
isolate, &source, compile_options, no_cache_reason);
+ // The ScriptState also has an associated context. We expect the current
+ // context to match the context associated with Script context when
+ // compiling the module. Hence it is safe to use the CodeCacheHost
+ // corresponding to the current execution context.
+ ExecutionContext* execution_context =
+ ExecutionContext::From(isolate->GetCurrentContext());
if (cached_data->rejected) {
cache_handler->ClearCachedMetadata(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
CachedMetadataHandler::kClearPersistentStorage);
} else if (InDiscardExperiment()) {
// Experimentally free code cache from memory after first use. See
// http://crbug.com/1045052.
cache_handler->ClearCachedMetadata(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
CachedMetadataHandler::kDiscardLocally);
}
cache_result.consume_result = absl::make_optional(
@@ -449,35 +472,17 @@ ScriptEvaluationResult V8ScriptRunner::CompileAndRunScript(
try_catch.SetVerbose(true);
}
- // Omit storing base URL if it is same as source URL.
- // Note: This improves chance of getting into a fast path in
- // ReferrerScriptInfo::ToV8HostDefinedOptions.
- const KURL base_url = classic_script->BaseURL();
- KURL stored_base_url = (base_url == source.Url()) ? KURL() : base_url;
-
- // TODO(hiroshige): Remove this code and related use counters once the
- // measurement is done.
- ReferrerScriptInfo::BaseUrlSource base_url_source =
- ReferrerScriptInfo::BaseUrlSource::kOther;
- if (source.SourceLocationType() ==
- ScriptSourceLocationType::kExternalFile &&
- !base_url.IsNull()) {
- switch (sanitize_script_errors) {
- case SanitizeScriptErrors::kDoNotSanitize:
- base_url_source =
- ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSSameOrigin;
- break;
- case SanitizeScriptErrors::kSanitize:
- base_url_source =
- ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSCrossOrigin;
- break;
- }
- }
- const ReferrerScriptInfo referrer_info(
- stored_base_url, classic_script->FetchOptions(), base_url_source);
+ const ReferrerScriptInfo referrer_info(classic_script->BaseURL(),
+ classic_script->FetchOptions());
v8::Local<v8::Script> script;
+ if (source.CacheHandler()) {
+ source.CacheHandler()->Check(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ source.Source());
+ }
+
v8::ScriptCompiler::CompileOptions compile_options;
V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
@@ -494,7 +499,17 @@ ScriptEvaluationResult V8ScriptRunner::CompileAndRunScript(
V8ScriptRunner::RunCompiledScript(isolate, script, execution_context);
probe::DidProduceCompilationCache(
probe::ToCoreProbeSink(execution_context), source, script);
- V8CodeCache::ProduceCache(isolate, script, source, produce_cache_options);
+
+ // The ScriptState has an associated context. We expect the current
+ // context to match the context associated with Script context when
+ // compiling the script in the main world. Hence it is safe to use the
+ // CodeCacheHost corresponding to the script execution context. For
+ // isolated world the contexts may not match. Though code caching is
+ // disabled for extensions so it is OK to use execution_context here.
+ V8CodeCache::ProduceCache(
+ isolate,
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ script, source, produce_cache_options);
}
// TODO(crbug/1114601): Investigate whether to check CanContinue() in other
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 b09c9085530..55ed2665238 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,6 +26,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
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 53e97a49e2f..6c6b416de7a 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
@@ -13,12 +13,14 @@
#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/execution_context/execution_context.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"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "v8/include/v8.h"
@@ -45,8 +47,15 @@ class V8ScriptRunnerTest : public testing::Test {
return WTF::String::Format("a = function() { 1 + 1; } // %01000d\n",
counter_);
}
+ WTF::String DifferentCode() const {
+ return WTF::String::Format("a = function() { 1 + 2; } // %01000d\n",
+ counter_);
+ }
KURL Url() const {
- return KURL(WTF::String::Format("http://bla.com/bla%d", counter_));
+ return KURL(WTF::String::Format(code_cache_with_hashing_scheme_
+ ? "codecachewithhashing://bla.com/bla%d"
+ : "http://bla.com/bla%d",
+ counter_));
}
unsigned TagForCodeCache(SingleCachedMetadataHandler* cache_handler) const {
return V8CodeCache::TagForCodeCache(cache_handler);
@@ -54,14 +63,21 @@ class V8ScriptRunnerTest : public testing::Test {
unsigned TagForTimeStamp(SingleCachedMetadataHandler* cache_handler) const {
return V8CodeCache::TagForTimeStamp(cache_handler);
}
- void SetCacheTimeStamp(SingleCachedMetadataHandler* cache_handler) {
- V8CodeCache::SetCacheTimeStamp(cache_handler);
+ void SetCacheTimeStamp(mojom::CodeCacheHost* code_cache_host,
+ SingleCachedMetadataHandler* cache_handler) {
+ V8CodeCache::SetCacheTimeStamp(code_cache_host, cache_handler);
}
bool CompileScript(v8::Isolate* isolate,
ScriptState* script_state,
const ScriptSourceCode& source_code,
mojom::blink::V8CacheOptions cache_options) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ if (source_code.CacheHandler()) {
+ source_code.CacheHandler()->Check(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ source_code.Source());
+ }
v8::ScriptCompiler::CompileOptions compile_options;
V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
@@ -73,8 +89,10 @@ class V8ScriptRunnerTest : public testing::Test {
if (compiled_script.IsEmpty()) {
return false;
}
- V8CodeCache::ProduceCache(isolate, compiled_script.ToLocalChecked(),
- source_code, produce_cache_options);
+ V8CodeCache::ProduceCache(
+ isolate,
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ compiled_script.ToLocalChecked(), source_code, produce_cache_options);
return true;
}
@@ -84,14 +102,22 @@ class V8ScriptRunnerTest : public testing::Test {
v8::ScriptCompiler::CompileOptions compile_options,
v8::ScriptCompiler::NoCacheReason no_cache_reason,
V8CodeCache::ProduceCacheOptions produce_cache_options) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ if (source_code.CacheHandler()) {
+ source_code.CacheHandler()->Check(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ source_code.Source());
+ }
v8::MaybeLocal<v8::Script> compiled_script = V8ScriptRunner::CompileScript(
script_state, source_code, SanitizeScriptErrors::kSanitize,
compile_options, no_cache_reason, ReferrerScriptInfo());
if (compiled_script.IsEmpty()) {
return false;
}
- V8CodeCache::ProduceCache(isolate, compiled_script.ToLocalChecked(),
- source_code, produce_cache_options);
+ V8CodeCache::ProduceCache(
+ isolate,
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ compiled_script.ToLocalChecked(), source_code, produce_cache_options);
return true;
}
@@ -101,13 +127,21 @@ class V8ScriptRunnerTest : public testing::Test {
return resource;
}
- ScriptResource* CreateResource(const WTF::TextEncoding& encoding) {
+ ScriptResource* CreateResource(const WTF::TextEncoding& encoding,
+ Vector<uint8_t> serialized_metadata = {},
+ absl::optional<String> code = {}) {
ScriptResource* resource = ScriptResource::CreateForTest(Url(), encoding);
- String code = Code();
+ if (!code)
+ code = Code();
ResourceResponse response(Url());
response.SetHttpStatusCode(200);
resource->ResponseReceived(response);
- StringUTF8Adaptor code_utf8(code);
+ if (serialized_metadata.size() != 0) {
+ const uint8_t* begin = serialized_metadata.data();
+ resource->SetSerializedCachedMetadata(
+ base::make_span(begin, serialized_metadata.size()));
+ }
+ StringUTF8Adaptor code_utf8(code.value());
resource->AppendData(code_utf8.data(), code_utf8.size());
resource->FinishForTest();
return resource;
@@ -115,6 +149,7 @@ class V8ScriptRunnerTest : public testing::Test {
protected:
static int counter_;
+ bool code_cache_with_hashing_scheme_ = false;
base::test::ScopedFeatureList feature_list_;
};
@@ -174,7 +209,11 @@ TEST_F(V8ScriptRunnerTest, codeOption) {
nullptr, CreateResource(UTF8Encoding()),
ScriptStreamer::NotStreamingReason::kScriptTooSmall);
SingleCachedMetadataHandler* cache_handler = source_code.CacheHandler();
- SetCacheTimeStamp(cache_handler);
+ ExecutionContext* execution_context =
+ ExecutionContext::From(scope.GetScriptState());
+ SetCacheTimeStamp(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ cache_handler);
EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
source_code, mojom::blink::V8CacheOptions::kCode));
@@ -196,7 +235,11 @@ TEST_F(V8ScriptRunnerTest, consumeCodeOptionWithoutDiscarding) {
ScriptStreamer::NotStreamingReason::kScriptTooSmall);
// Set timestamp to simulate a warm run.
SingleCachedMetadataHandler* cache_handler = source_code.CacheHandler();
- SetCacheTimeStamp(cache_handler);
+ ExecutionContext* execution_context =
+ ExecutionContext::From(scope.GetScriptState());
+ SetCacheTimeStamp(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ cache_handler);
// Warm run - should produce code cache.
EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
@@ -231,7 +274,11 @@ TEST_F(V8ScriptRunnerTest, consumeCodeOptionWithDiscarding) {
ScriptStreamer::NotStreamingReason::kScriptTooSmall);
// Set timestamp to simulate a warm run.
SingleCachedMetadataHandler* cache_handler = source_code.CacheHandler();
- SetCacheTimeStamp(cache_handler);
+ ExecutionContext* execution_context =
+ ExecutionContext::From(scope.GetScriptState());
+ SetCacheTimeStamp(
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ cache_handler);
// Warm run - should produce code cache.
EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
@@ -385,6 +432,139 @@ TEST_F(V8ScriptRunnerTest, cacheDataTypeMismatch) {
EXPECT_EQ(1, counter.GetDataTypeMismatch());
}
+TEST_F(V8ScriptRunnerTest, successfulCodeCacheWithHashing) {
+ feature_list_.InitAndDisableFeature(
+ blink::features::kDiscardCodeCacheAfterFirstUse);
+ V8TestingScope scope;
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(
+ "codecachewithhashing");
+ code_cache_with_hashing_scheme_ = true;
+ ScriptSourceCode source_code(
+ nullptr, CreateResource(UTF8Encoding()),
+ ScriptStreamer::NotStreamingReason::kScriptTooSmall);
+ SingleCachedMetadataHandler* cache_handler = source_code.CacheHandler();
+ EXPECT_TRUE(cache_handler->HashRequired());
+
+ // Cold run - should set the timestamp.
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code,
+ mojom::blink::V8CacheOptions::kDefault));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(TagForTimeStamp(cache_handler)));
+ EXPECT_FALSE(
+ cache_handler->GetCachedMetadata(TagForCodeCache(cache_handler)));
+
+ // Warm run - should produce code cache.
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code,
+ mojom::blink::V8CacheOptions::kDefault));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(TagForCodeCache(cache_handler)));
+
+ // Hot run - should consume code cache.
+ v8::ScriptCompiler::CompileOptions compile_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
+ v8::ScriptCompiler::NoCacheReason no_cache_reason;
+ std::tie(compile_options, produce_cache_options, no_cache_reason) =
+ V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions::kDefault,
+ source_code);
+ EXPECT_EQ(produce_cache_options,
+ V8CodeCache::ProduceCacheOptions::kNoProduceCache);
+ EXPECT_EQ(compile_options,
+ v8::ScriptCompiler::CompileOptions::kConsumeCodeCache);
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code, compile_options, no_cache_reason,
+ produce_cache_options));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(TagForCodeCache(cache_handler)));
+}
+
+TEST_F(V8ScriptRunnerTest, codeCacheWithFailedHashCheck) {
+ V8TestingScope scope;
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(
+ "codecachewithhashing");
+ code_cache_with_hashing_scheme_ = true;
+
+ ScriptSourceCode source_code_1(
+ nullptr, CreateResource(UTF8Encoding()),
+ ScriptStreamer::NotStreamingReason::kScriptTooSmall);
+ ScriptCachedMetadataHandlerWithHashing* cache_handler_1 =
+ static_cast<ScriptCachedMetadataHandlerWithHashing*>(
+ source_code_1.CacheHandler());
+ EXPECT_TRUE(cache_handler_1->HashRequired());
+
+ // Cold run - should set the timestamp.
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code_1,
+ mojom::blink::V8CacheOptions::kDefault));
+ EXPECT_TRUE(
+ cache_handler_1->GetCachedMetadata(TagForTimeStamp(cache_handler_1)));
+ EXPECT_FALSE(
+ cache_handler_1->GetCachedMetadata(TagForCodeCache(cache_handler_1)));
+
+ // A second ScriptSourceCode with matching script text, using the state of
+ // the ScriptCachedMetadataHandler from the first ScriptSourceCode.
+ ScriptSourceCode source_code_2(
+ nullptr,
+ CreateResource(UTF8Encoding(),
+ cache_handler_1->GetSerializedCachedMetadata()),
+ ScriptStreamer::NotStreamingReason::kScriptTooSmall);
+ ScriptCachedMetadataHandlerWithHashing* cache_handler_2 =
+ static_cast<ScriptCachedMetadataHandlerWithHashing*>(
+ source_code_2.CacheHandler());
+ EXPECT_TRUE(cache_handler_2->HashRequired());
+
+ // Warm run - should produce code cache.
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code_2,
+ mojom::blink::V8CacheOptions::kDefault));
+ EXPECT_TRUE(
+ cache_handler_2->GetCachedMetadata(TagForCodeCache(cache_handler_2)));
+
+ // A third ScriptSourceCode with different script text, using the state of
+ // the ScriptCachedMetadataHandler from the second ScriptSourceCode.
+ ScriptSourceCode source_code_3(
+ nullptr,
+ CreateResource(UTF8Encoding(),
+ cache_handler_2->GetSerializedCachedMetadata(),
+ DifferentCode()),
+ ScriptStreamer::NotStreamingReason::kScriptTooSmall);
+ ScriptCachedMetadataHandlerWithHashing* cache_handler_3 =
+ static_cast<ScriptCachedMetadataHandlerWithHashing*>(
+ source_code_3.CacheHandler());
+ EXPECT_TRUE(cache_handler_3->HashRequired());
+
+ // Since the third script's text doesn't match the first two, the hash check
+ // should reject the existing code cache data and the cache entry should
+ // be updated back to a timestamp like it would during a cold run.
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code_3,
+ mojom::blink::V8CacheOptions::kDefault));
+ EXPECT_TRUE(
+ cache_handler_3->GetCachedMetadata(TagForTimeStamp(cache_handler_3)));
+ EXPECT_FALSE(
+ cache_handler_3->GetCachedMetadata(TagForCodeCache(cache_handler_3)));
+
+ // A fourth ScriptSourceCode with matching script text, using the state of
+ // the ScriptCachedMetadataHandler from the third ScriptSourceCode.
+ ScriptSourceCode source_code_4(
+ nullptr,
+ CreateResource(UTF8Encoding(),
+ cache_handler_3->GetSerializedCachedMetadata()),
+ ScriptStreamer::NotStreamingReason::kScriptTooSmall);
+ ScriptCachedMetadataHandlerWithHashing* cache_handler_4 =
+ static_cast<ScriptCachedMetadataHandlerWithHashing*>(
+ source_code_4.CacheHandler());
+ EXPECT_TRUE(cache_handler_4->HashRequired());
+
+ // Running the original script again once again sets the timestamp since the
+ // content has changed again.
+ EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
+ source_code_4,
+ mojom::blink::V8CacheOptions::kDefault));
+ EXPECT_TRUE(
+ cache_handler_4->GetCachedMetadata(TagForTimeStamp(cache_handler_4)));
+ EXPECT_FALSE(
+ cache_handler_4->GetCachedMetadata(TagForCodeCache(cache_handler_4)));
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h
index ea5139ba832..e099006e097 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h
@@ -14,51 +14,18 @@ namespace blink {
namespace bindings {
-class NativeValueTraitsStringAdapter;
-
// ScriptValue
template <typename CallbackInfo, typename... ExtraArgs>
void V8SetReturnValue(const CallbackInfo& info,
const ScriptValue& value,
ExtraArgs... extra_args) {
- // Ignore all |extra_args| given as inputs for optimization.
+ // APIs of iterable, maplike, setlike, etc. return their return value of type
+ // ScriptValue regardless of their Web IDL type since they perform `ToV8` on
+ // their side. The use of `V8Value` (instead of `V8ValueFor`) must be fine
+ // because the value must be created in the current world.
V8SetReturnValue(info, value.V8Value());
}
-// IDLObject type
-template <typename CallbackInfo>
-void V8SetReturnValue(const CallbackInfo& info,
- const ScriptValue& value,
- V8ReturnValue::IDLObject) {
- DCHECK(!value.IsEmpty());
- v8::Local<v8::Value> v8_value = value.V8Value();
- // TODO(crbug.com/1185033): Change this if-branch to DCHECK.
- if (!v8_value->IsObject()) {
- V8SetReturnValue(info, v8::Undefined(info.GetIsolate()));
- return;
- }
- V8SetReturnValue(info, v8_value);
-}
-
-// String types
-template <typename CallbackInfo>
-void V8SetReturnValue(const CallbackInfo& info,
- const NativeValueTraitsStringAdapter& value,
- v8::Isolate* isolate,
- V8ReturnValue::NonNullable) {
- V8SetReturnValue(info, static_cast<String>(value), isolate,
- V8ReturnValue::kNonNullable);
-}
-
-template <typename CallbackInfo>
-void V8SetReturnValue(const CallbackInfo& info,
- const NativeValueTraitsStringAdapter& value,
- v8::Isolate* isolate,
- V8ReturnValue::Nullable) {
- V8SetReturnValue(info, static_cast<String>(value), isolate,
- V8ReturnValue::kNullable);
-}
-
// EventListener
template <typename CallbackInfo>
void V8SetReturnValue(const CallbackInfo& info,
@@ -70,18 +37,6 @@ void V8SetReturnValue(const CallbackInfo& info,
JSEventHandler::AsV8Value(isolate, event_target, event_listener));
}
-// IDLDictionaryBase
-template <typename CallbackInfo>
-void V8SetReturnValue(const CallbackInfo& info,
- const IDLDictionaryBase* dictionary) {
- // TODO(crbug.com/1185018): Change this if-branch to DCHECK(dictionary).
- if (!dictionary)
- return V8SetReturnValue(info, v8::Null(info.GetIsolate()));
- V8SetReturnValue(info,
- dictionary->ToV8Impl(V8ReturnValue::CreationContext(info),
- info.GetIsolate()));
-}
-
} // namespace bindings
} // namespace blink
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 9cf1fc35664..984f82b6aa5 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
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -16,6 +17,9 @@
#include "third_party/blink/renderer/core/fetch/fetch_data_loader.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_backing_thread.h"
+#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -24,6 +28,8 @@
#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/loader/fetch/script_cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -204,18 +210,38 @@ class ExceptionToAbortStreamingScope {
DISALLOW_COPY_AND_ASSIGN(ExceptionToAbortStreamingScope);
};
+void SendCachedData(String response_url,
+ base::Time response_time,
+ ExecutionContext* execution_context,
+ Vector<uint8_t> serialized_module) {
+ if (!execution_context)
+ return;
+ scoped_refptr<CachedMetadata> cached_metadata =
+ CachedMetadata::CreateFromSerializedData(std::move(serialized_module));
+
+ blink::mojom::CodeCacheHost* code_cache_host =
+ ExecutionContext::GetCodeCacheHostFromContext(execution_context);
+ base::span<const uint8_t> serialized_data = cached_metadata->SerializedData();
+ CachedMetadataSender::SendToCodeCacheHost(
+ code_cache_host, mojom::blink::CodeCacheType::kWebAssembly, response_url,
+ response_time, serialized_data.data(), serialized_data.size());
+}
+
class WasmStreamingClient : public v8::WasmStreaming::Client {
public:
WasmStreamingClient(const String& response_url,
- const base::Time& response_time)
+ const base::Time& response_time,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ ExecutionContext* execution_context)
: response_url_(response_url.IsolatedCopy()),
- response_time_(response_time) {}
+ response_time_(response_time),
+ main_thread_task_runner_(std::move(task_runner)),
+ execution_context_(execution_context) {}
void OnModuleCompiled(v8::CompiledWasmModule compiled_module) override {
TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"v8.wasm.compiledModule", TRACE_EVENT_SCOPE_THREAD,
"url", response_url_.Utf8());
-
v8::MemorySpan<const uint8_t> wire_bytes =
compiled_module.GetWireBytesRef();
// Our heuristic for whether it's worthwhile to cache is that the module
@@ -239,20 +265,27 @@ class WasmStreamingClient : public v8::WasmStreaming::Client {
// The resources needed for caching may have been GC'ed, but we should still
// save the compiled module. Use the platform API directly.
- scoped_refptr<CachedMetadata> cached_metadata = CachedMetadata::Create(
+ Vector<uint8_t> serialized_data = CachedMetadata::GetSerializedData(
kWasmModuleTag,
reinterpret_cast<const uint8_t*>(serialized_module.buffer.get()),
serialized_module.size);
- base::span<const uint8_t> serialized_data =
- cached_metadata->SerializedData();
// Make sure the data could be copied.
if (serialized_data.size() < serialized_module.size)
return;
- Platform::Current()->CacheMetadata(
- mojom::CodeCacheType::kWebAssembly, KURL(response_url_), response_time_,
- serialized_data.data(), serialized_data.size());
+ // TODO(mythria): Add support for worklets and remove this code that uses
+ // per-process interface.
+ if (!main_thread_task_runner_.get()) {
+ SendCachedData(response_url_, response_time_, execution_context_.Lock(),
+ std::move(serialized_data));
+ return;
+ }
+
+ main_thread_task_runner_->PostTask(
+ FROM_HERE, ConvertToBaseOnceCallback(WTF::CrossThreadBindOnce(
+ &SendCachedData, response_url_, response_time_,
+ execution_context_, std::move(serialized_data))));
}
void SetBuffer(scoped_refptr<CachedMetadata> cached_module) {
@@ -263,10 +296,31 @@ class WasmStreamingClient : public v8::WasmStreaming::Client {
String response_url_;
base::Time response_time_;
scoped_refptr<CachedMetadata> cached_module_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+ CrossThreadWeakPersistent<ExecutionContext> execution_context_;
DISALLOW_COPY_AND_ASSIGN(WasmStreamingClient);
};
+scoped_refptr<base::SingleThreadTaskRunner> GetContextTaskRunner(
+ ExecutionContext& execution_context) {
+ if (execution_context.IsWorkerGlobalScope()) {
+ WorkerOrWorkletGlobalScope& global_scope =
+ To<WorkerOrWorkletGlobalScope>(execution_context);
+ return global_scope.GetThread()
+ ->GetWorkerBackingThread()
+ .BackingThread()
+ .GetTaskRunner();
+ }
+
+ if (execution_context.IsWindow()) {
+ return Thread::MainThread()->GetTaskRunner();
+ }
+
+ DCHECK(execution_context.IsWorkletGlobalScope());
+ return nullptr;
+}
+
void StreamFromResponseCallback(
const v8::FunctionCallbackInfo<v8::Value>& args) {
TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
@@ -328,8 +382,12 @@ void StreamFromResponseCallback(
streaming->SetUrl(url_utf8.c_str(), url_utf8.size());
if (auto* cache_handler =
response->BodyBuffer()->GetCachedMetadataHandler()) {
+ auto* execution_context = ExecutionContext::From(script_state);
+ DCHECK_NE(execution_context, nullptr);
+
auto client = std::make_shared<WasmStreamingClient>(
- url, response->GetResponse()->InternalResponse()->ResponseTime());
+ url, response->GetResponse()->InternalResponse()->ResponseTime(),
+ GetContextTaskRunner(*execution_context), execution_context);
streaming->SetClient(client);
scoped_refptr<CachedMetadata> cached_module =
cache_handler->GetCachedMetadata(kWasmModuleTag);
@@ -350,7 +408,15 @@ void StreamFromResponseCallback(
TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"v8.wasm.moduleCacheInvalid",
TRACE_EVENT_SCOPE_THREAD);
+ // TODO(mythria): Also support using context specific code cache host
+ // here. When we pass nullptr for CodeCacheHost we use per-process
+ // interface. Currently this code is run on a thread started via a
+ // Platform::PostJob. So it isn't safe to use CodeCacheHost interface
+ // that was bound on the frame / worker threads. We should instead post
+ // a task back to the frame / worker threads with the required data
+ // which can then write to generated code caches.
cache_handler->ClearCachedMetadata(
+ /*code_cache_host*/ nullptr,
CachedMetadataHandler::kClearPersistentStorage);
}
}
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 a52865104b5..8e576c2512f 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
@@ -253,39 +253,12 @@ void WorkerOrWorkletScriptController::PrepareForEvaluation() {
v8::HandleScope handle_scope(isolate_);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
V8PerContextData* per_context_data = script_state_->PerContextData();
ignore_result(per_context_data->ConstructorForType(
global_scope_->GetWrapperTypeInfo()));
// Inform V8 that origin trial information is now connected with the context,
// and V8 can extend the context with origin trial features.
isolate_->InstallConditionalFeatures(script_state_->GetContext());
-#else // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
- ScriptState::Scope scope(script_state_);
- v8::Local<v8::Context> context = script_state_->GetContext();
-
- auto* script_wrappable = static_cast<ScriptWrappable*>(global_scope_);
- const WrapperTypeInfo* wrapper_type_info =
- script_wrappable->GetWrapperTypeInfo();
-
- // All interfaces must be registered to V8PerContextData.
- // So we explicitly call constructorForType for the global object.
- // This should be called after OriginTrialContext::AddTokens() in
- // WorkerGlobalScope::Initialize() to install origin trial features.
- V8PerContextData::From(context)->ConstructorForType(wrapper_type_info);
-
- v8::Local<v8::Object> global_object =
- context->Global()->GetPrototype().As<v8::Object>();
- DCHECK(!global_object.IsEmpty());
-
- v8::Local<v8::FunctionTemplate> global_interface_template =
- wrapper_type_info->DomTemplate(isolate_, *world_);
- DCHECK(!global_interface_template.IsEmpty());
-
- wrapper_type_info->InstallConditionalFeatures(
- context, *world_, global_object, v8::Local<v8::Object>(),
- v8::Local<v8::Function>(), global_interface_template);
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
}
void WorkerOrWorkletScriptController::DisableEvalInternal(
diff --git a/chromium/third_party/blink/renderer/bindings/extensions/v8/BUILD.gn b/chromium/third_party/blink/renderer/bindings/extensions/v8/BUILD.gn
new file mode 100644
index 00000000000..9338a2c3ae4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/extensions/v8/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import(
+ "//third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni")
+import("//third_party/blink/renderer/extensions/extensions.gni")
+
+visibility = [ "//third_party/blink/renderer/*" ]
+
+blink_extensions_chromeos_sources("v8_chromeos") {
+ visibility = []
+ visibility = [ "//third_party/blink/renderer/extensions/chromeos" ]
+
+ sources = generated_namespace_sources_in_extensions_chromeos
+
+ deps = [
+ "//third_party/blink/renderer/bindings:generate_bindings_all",
+ "//third_party/blink/renderer/platform",
+ "//v8",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/bindings/generated_in_core.gni b/chromium/third_party/blink/renderer/bindings/generated_in_core.gni
index f9a253239e4..dbd963f7118 100644
--- a/chromium/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/chromium/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -85,10 +85,20 @@ generated_dictionary_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_animation_playback_event_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigation_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigation_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_reload_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_reload_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_update_current_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_update_current_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_application_cache_error_event_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_application_cache_error_event_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_assigned_nodes_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_assigned_nodes_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_attribution_source_params.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_attribution_source_params.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_base_keyframe.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_base_keyframe.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_base_property_indexed_keyframe.cc",
@@ -115,6 +125,10 @@ generated_dictionary_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_custom_layout_constraints_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_document_timeline_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_document_timeline_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_document_transition_prepare_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_document_transition_prepare_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_document_transition_start_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_document_transition_start_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_2d_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_2d_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_init.cc",
@@ -177,8 +191,6 @@ generated_dictionary_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_image_data_settings.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_image_encode_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_image_encode_options.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_impression_params.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_impression_params.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_device_capabilities_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_device_capabilities_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_event_init.cc",
@@ -486,6 +498,8 @@ generated_enumeration_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_text_track_kind.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_text_track_mode.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_text_track_mode.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_timeline_phase.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_timeline_phase.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visibility_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visibility_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_worker_type.cc",
@@ -517,16 +531,22 @@ generated_interface_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_animation_timeline.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_destination.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_destination.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_entry.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_entry.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigation_type.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigation_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_application_cache.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_application_cache.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_application_cache_error_event.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_application_cache_error_event.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_attr.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_attr.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_attribution_reporting.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_attribution_reporting.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_audio_track.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_audio_track.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_audio_track_list.cc",
@@ -1480,6 +1500,8 @@ generated_union_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_document_formdata_urlsearchparams_usvstring.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_document_formdata_urlsearchparams_usvstring.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_formdata_readablestream_urlsearchparams_usvstring.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_formdata_readablestream_urlsearchparams_usvstring.h",
@@ -1487,8 +1509,8 @@ generated_union_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_formdata_urlsearchparams_usvstring.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_usvstring.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_usvstring.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_readablestream.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_readablestream.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared_readablestream.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared_readablestream.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_usvstring.cc",
@@ -1521,18 +1543,16 @@ generated_union_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_cssstylevalue_string.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_cssvariablereferencevalue_string.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_cssvariablereferencevalue_string.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string_trustedhtml.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string_trustedhtml.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_element.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_document_element.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_documenttimeline_scrolltimeline.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_documenttimeline_scrolltimeline.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_dommatrix_float32array_float64array.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_dommatrix_float32array_float64array.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_dompoint_unrestricteddouble.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_dompoint_unrestricteddouble.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_dompointinit_unrestricteddouble.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_dompointinit_unrestricteddouble.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_double_doubleornullsequence_null.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_double_doubleornullsequence_null.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_double_doublesequence.cc",
@@ -1561,6 +1581,8 @@ generated_union_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_float32array_uint16array_uint8clampedarray.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_float_stringelementrecord.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_float_stringelementrecord.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_imagebitmap_offscreencanvas.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_imagebitmap_offscreencanvas.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlelement_long.cc",
@@ -1569,8 +1591,8 @@ generated_union_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmloptgroupelement_htmloptionelement.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlscriptelement_svgscriptelement.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlscriptelement_svgscriptelement.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_int32array_longsequence.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_int32array_longsequence.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_int32arrayallowshared_longsequence.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_int32arrayallowshared_longsequence.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_keyframeanimationoptions_unrestricteddouble.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_keyframeanimationoptions_unrestricteddouble.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.cc",
@@ -1609,8 +1631,8 @@ generated_union_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_string_workeroptions.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_stringtreatnullasemptystring_trustedscript.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_stringtreatnullasemptystring_trustedscript.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_uint32array_unsignedlongsequence.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_uint32array_unsignedlongsequence.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_uint32arrayallowshared_unsignedlongsequence.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_uint32arrayallowshared_unsignedlongsequence.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_unsignedlong_unsignedlongsequence.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_unsignedlong_unsignedlongsequence.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_usvstring_uint32array.cc",
diff --git a/chromium/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni b/chromium/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni
new file mode 100644
index 00000000000..dfb7b19d229
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni
@@ -0,0 +1,10 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generated sources for production
+
+generated_namespace_sources_in_extensions_chromeos = [
+ "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_chrome_os.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_chrome_os.cc",
+]
diff --git a/chromium/third_party/blink/renderer/bindings/generated_in_modules.gni b/chromium/third_party/blink/renderer/bindings/generated_in_modules.gni
index d4eb9fff293..f39c34eaaaf 100644
--- a/chromium/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/chromium/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -111,6 +111,12 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_android_pay_method_data.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_app_banner_prompt_result.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_app_banner_prompt_result.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_auction_ad.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_auction_ad.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_auction_ad_config.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_auction_ad_config.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_auction_ad_interest_group.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_auction_ad_interest_group.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_buffer_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_buffer_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_buffer_source_options.cc",
@@ -131,6 +137,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_config.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_support.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_support.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_node_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_node_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_param_descriptor.cc",
@@ -149,10 +157,10 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_inputs.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_outputs.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_outputs.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_payment_inputs.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_payment_inputs.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authenticator_selection_criteria.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authenticator_selection_criteria.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_bitstream_format.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_bitstream_format.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_encoder_config.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_encoder_config.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_background_fetch_event_init.cc",
@@ -201,6 +209,12 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_canvas_filter_dictionary.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_canvas_rendering_context_2d_settings.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_canvas_rendering_context_2d_settings.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_capture_handle.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_capture_handle.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_capture_handle_change_event_init.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_capture_handle_change_event_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_capture_handle_config.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_capture_handle_config.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_channel_merger_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_channel_merger_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_channel_splitter_options.cc",
@@ -215,8 +229,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_close_event_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_collected_client_data.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_collected_client_data.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_select_event_init.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_select_event_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_selection_result.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_selection_result.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_compute_pressure_observer_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_compute_pressure_observer_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_compute_pressure_observer_update.cc",
@@ -323,6 +337,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_file_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_handle_permission_descriptor.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_handle_permission_descriptor.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_read_write_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_read_write_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_remove_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_remove_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gain_options.cc",
@@ -355,6 +371,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_binding_layout.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_descriptor.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_descriptor.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_configuration.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_configuration.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_dict.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_dict.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_state_descriptor.cc",
@@ -377,18 +395,26 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_device_descriptor.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_extent_3d_dict.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_extent_3d_dict.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_binding_layout.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_binding_layout.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_descriptor.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_descriptor.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_fragment_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_fragment_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_buffer.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_buffer.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_external_image.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_external_image.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_image_bitmap.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_image_bitmap.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture_tagged.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture_tagged.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_data_layout.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_data_layout.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_limits.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_limits.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_multisample_state.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_multisample_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_object_descriptor_base.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_object_descriptor_base.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_origin_2d_dict.cc",
@@ -399,6 +425,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_pipeline_descriptor_base.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_pipeline_layout_descriptor.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_pipeline_layout_descriptor.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_predefined_color_space.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_predefined_color_space.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_primitive_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_primitive_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_programmable_stage.cc",
@@ -431,8 +459,6 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_stencil_face_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_storage_texture_binding_layout.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_storage_texture_binding_layout.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain_descriptor.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain_descriptor.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_binding_layout.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_binding_layout.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_descriptor.cc",
@@ -569,8 +595,6 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_generator_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_processor_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_processor_init.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_track_capabilities.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_track_capabilities.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraint_set.cc",
@@ -593,6 +617,10 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_midi_permission_descriptor.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_multi_cache_query_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_multi_cache_query_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_read_result.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_read_result.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_write_result.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_write_result.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ndef_message_init.cc",
@@ -681,8 +709,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_event_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_options.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_init.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_point_2d.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_point_2d.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_position_options.cc",
@@ -717,8 +745,6 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_push_subscription_options_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_query_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_query_options.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_quic_transport_options.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_quic_transport_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_registration_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_registration_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_related_application.cc",
@@ -815,6 +841,10 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sensor_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_share_data.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_share_data.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_run_operation_method_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_run_operation_method_options.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_set_method_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_set_method_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_config.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_config.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_spatial_sensor_options.cc",
@@ -841,12 +871,18 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_stream_abort_info.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sync_event_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sync_event_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_controller_init.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_controller_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_priority_change_event_init.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_priority_change_event_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_text_decode_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_text_decode_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_text_decoder_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_text_decoder_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_text_encoder_encode_into_result.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_text_encoder_encode_into_result.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_component.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_component.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_component_result.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_component_result.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_init.cc",
@@ -877,12 +913,16 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_encode_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_support.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_support.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_buffer_init.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_buffer_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_copy_to_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_copy_to_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_metadata.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_metadata.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_watch_advertisements_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_watch_advertisements_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_wave_shaper_options.cc",
@@ -891,6 +931,8 @@ generated_dictionary_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_id_request_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_transport_close_info.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_transport_close_info.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_transport_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_transport_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_webgl_context_attributes.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_webgl_context_attributes.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_webgl_context_event_init.cc",
@@ -938,6 +980,8 @@ generated_dictionary_sources_in_modules = [
]
generated_enumeration_sources_in_modules = [
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_alpha_option.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_alpha_option.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_app_banner_prompt_outcome.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_app_banner_prompt_outcome.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_append_mode.cc",
@@ -952,6 +996,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authenticator_attachment.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_automation_rate.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_automation_rate.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_bitstream_format.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_bitstream_format.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_background_fetch_failure_reason.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_background_fetch_failure_reason.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_background_fetch_result.cc",
@@ -984,14 +1030,6 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_codec_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_gamut.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_gamut.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_matrix_id.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_matrix_id.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_primary_id.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_primary_id.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_range_id.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_range_id.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_transfer_id.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_space_transfer_id.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_connection_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_connection_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_contact_property.cc",
@@ -1004,6 +1042,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_cookie_same_site.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_credential_mediation_requirement.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_credential_mediation_requirement.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_posture_type.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_posture_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_distance_model_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_distance_model_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_effective_connection_type.cc",
@@ -1014,6 +1054,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_end_of_stream_error.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_end_of_stream_error.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_handle_kind.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_handle_kind.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_permission_mode.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_permission_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_fill_light_mode.cc",
@@ -1038,6 +1080,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_binding_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_compare_function.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_compare_function.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_compilation_message_type.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_compilation_message_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_cull_mode.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_cull_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_error_filter.cc",
@@ -1050,8 +1094,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_front_face.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_index_format.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_index_format.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_input_step_mode.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_input_step_mode.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_vertex_step_mode.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_vertex_step_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_load_op.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_load_op.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_pipeline_statistic_name.cc",
@@ -1062,6 +1106,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_primitive_topology.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_query_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_query_type.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler_binding_type.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler_binding_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_stencil_operation.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_stencil_operation.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_storage_texture_access.cc",
@@ -1102,6 +1148,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_image_smoothing_quality.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_landmark_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_landmark_type.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_latency_mode.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_latency_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_local_coordinate_system.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_local_coordinate_system.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_lock_mode.cc",
@@ -1114,6 +1162,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_encoding_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_message_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_message_type.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_session_closed_reason.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_session_closed_reason.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_session_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_session_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_key_status.cc",
@@ -1124,8 +1174,6 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_session_action.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_session_playback_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_session_playback_state.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal_type.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_metering_mode.cc",
@@ -1136,6 +1184,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_midi_port_device_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_midi_port_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_midi_port_type.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mode.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_notification_action_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_notification_action_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_notification_direction.cc",
@@ -1170,8 +1220,6 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_presentation_connection_close_reason.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_presentation_connection_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_presentation_connection_state.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_presenter_type.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_presenter_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_purchase_state.cc",
@@ -1196,6 +1244,8 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_degradation_preference.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_dtls_transport_state.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_dtls_transport_state.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_video_frame_type.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_video_frame_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_error_detail_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_error_detail_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_candidate_type.cc",
@@ -1264,8 +1314,16 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_user_idle_state.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_user_verification_requirement.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_user_verification_requirement.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_color_primaries.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_color_primaries.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_matrix_coefficients.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_matrix_coefficients.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_transfer_characteristics.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_transfer_characteristics.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_webgl_power_preference.cc",
@@ -1290,6 +1348,12 @@ generated_enumeration_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_handedness.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_hit_test_trackable_type.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_hit_test_trackable_type.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_image_tracking_score.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_image_tracking_score.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_image_tracking_state.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_image_tracking_state.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_interaction_mode.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_interaction_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_plane_orientation.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_plane_orientation.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_reference_space_type.cc",
@@ -1327,6 +1391,8 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_context.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_data.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_data.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_data_copy_to_options.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_data_copy_to_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_destination_node.cc",
@@ -1343,6 +1409,8 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_param_map.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_processing_event.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_processing_event.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_sample_format.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_sample_format.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_scheduled_source_node.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_scheduled_source_node.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_track.cc",
@@ -1443,8 +1511,6 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_clipboard_item.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_close_event.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_close_event.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_select_event.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_select_event.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_compression_stream.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_compression_stream.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_compute_pressure_observer.cc",
@@ -1507,6 +1573,8 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_motion_event_rotation_rate.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_orientation_event.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_orientation_event.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_posture.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_posture.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_digital_goods_service.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_digital_goods_service.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_directory_entry.cc",
@@ -1527,6 +1595,8 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system_sync.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dynamics_compressor_node.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dynamics_compressor_node.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_element.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_element.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.cc",
@@ -1581,6 +1651,8 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_entry.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_entry_sync.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_entry_sync.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_sync_access_handle.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_sync_access_handle.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_iterator.cc",
@@ -1657,6 +1729,8 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_device.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_device_lost_info.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_device_lost_info.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_map_mode.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_map_mode.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_out_of_memory_error.cc",
@@ -1677,14 +1751,14 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_render_pipeline.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler_binding_type.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler_binding_type.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_shader_module.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_shader_module.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_shader_stage.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_shader_stage.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_supported_features.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_supported_features.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_supported_limits.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_supported_limits.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture.cc",
@@ -1765,12 +1839,16 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_image_track_list.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ink.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ink.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ink_presenter_param.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ink_presenter_param.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_input_device_info.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_input_device_info.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_install_event.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_install_event.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_keyboard.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_keyboard.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sub_apps.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sub_apps.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_keyboard_layout_map.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_keyboard_layout_map.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_khr_parallel_shader_compile.cc",
@@ -1967,8 +2045,6 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_event.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_window.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_window.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plugin.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plugin.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plugin_array.cc",
@@ -2087,8 +2163,12 @@ generated_interface_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_service_worker_registration.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shadow_root.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shadow_root.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_worker_global_scope.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_worker_global_scope.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_worklet.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_worklet.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_list.cc",
@@ -2456,8 +2536,8 @@ generated_union_sources_in_modules = [
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_filesystemhandle_wellknowndirectory.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_float_gpuloadop.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_float_gpuloadop.h",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpusampler_gputextureview.cc",
- "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpusampler_gputextureview.h",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.cc",
+ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h",
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpuextent3ddict_unsignedlongenforcerangesequence.cc",
diff --git a/chromium/third_party/blink/renderer/bindings/idl_in_core.gni b/chromium/third_party/blink/renderer/bindings/idl_in_core.gni
index bd98dc8f119..bccaa0392bd 100644
--- a/chromium/third_party/blink/renderer/bindings/idl_in_core.gni
+++ b/chromium/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -35,11 +35,14 @@ static_idl_files_in_core = get_path_info(
"//third_party/blink/renderer/core/aom/accessible_node_list.idl",
"//third_party/blink/renderer/core/aom/computed_accessible_node.idl",
"//third_party/blink/renderer/core/app_history/app_history.idl",
+ "//third_party/blink/renderer/core/app_history/app_history_destination.idl",
"//third_party/blink/renderer/core/app_history/app_history_entry.idl",
"//third_party/blink/renderer/core/app_history/app_history_navigate_event.idl",
"//third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl",
"//third_party/blink/renderer/core/app_history/app_history_navigate_options.idl",
"//third_party/blink/renderer/core/app_history/app_history_navigation_options.idl",
+ "//third_party/blink/renderer/core/app_history/app_history_reload_options.idl",
+ "//third_party/blink/renderer/core/app_history/app_history_update_current_options.idl",
"//third_party/blink/renderer/core/app_history/window_app_history.idl",
"//third_party/blink/renderer/core/clipboard/data_transfer.idl",
"//third_party/blink/renderer/core/clipboard/data_transfer_item.idl",
@@ -273,6 +276,7 @@ static_idl_files_in_core = get_path_info(
"//third_party/blink/renderer/core/frame/external.idl",
"//third_party/blink/renderer/core/frame/fragment_directive.idl",
"//third_party/blink/renderer/core/frame/history.idl",
+ "//third_party/blink/renderer/core/frame/attribution_reporting.idl",
"//third_party/blink/renderer/core/frame/attribution_source_params.idl",
"//third_party/blink/renderer/core/frame/intervention_report_body.idl",
"//third_party/blink/renderer/core/frame/is_input_pending_options.idl",
@@ -306,6 +310,7 @@ static_idl_files_in_core = get_path_info(
"//third_party/blink/renderer/core/frame/user_activation.idl",
"//third_party/blink/renderer/core/frame/visual_viewport.idl",
"//third_party/blink/renderer/core/frame/window.idl",
+ "//third_party/blink/renderer/core/frame/window_attribution_reporting.idl",
"//third_party/blink/renderer/core/frame/window_controls_overlay.idl",
"//third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.idl",
"//third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event_init.idl",
@@ -659,6 +664,7 @@ static_idl_files_in_core = get_path_info(
"//third_party/blink/renderer/core/timing/performance_measure_options.idl",
"//third_party/blink/renderer/core/timing/performance_navigation.idl",
"//third_party/blink/renderer/core/timing/performance_navigation_timing.idl",
+ "//third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl",
"//third_party/blink/renderer/core/timing/performance_observer.idl",
"//third_party/blink/renderer/core/timing/performance_observer_entry_list.idl",
"//third_party/blink/renderer/core/timing/performance_observer_init.idl",
@@ -730,9 +736,11 @@ static_idl_files_in_core_for_testing = get_path_info(
"//third_party/blink/renderer/core/testing/internal_dictionary_derived_derived.idl",
"//third_party/blink/renderer/core/testing/internal_settings.idl",
"//third_party/blink/renderer/core/testing/internals.idl",
+ "//third_party/blink/renderer/core/testing/internals_delete_all_cookies.idl",
"//third_party/blink/renderer/core/testing/origin_trials_test.idl",
"//third_party/blink/renderer/core/testing/origin_trials_test_dictionary.idl",
"//third_party/blink/renderer/core/testing/origin_trials_test_partial.idl",
+ "//third_party/blink/renderer/core/testing/origin_trials_test_window.idl",
"//third_party/blink/renderer/core/testing/record_test.idl",
"//third_party/blink/renderer/core/testing/sequence_test.idl",
"//third_party/blink/renderer/core/testing/static_selection.idl",
diff --git a/chromium/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni b/chromium/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni
new file mode 100644
index 00000000000..1c988d15cbb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni
@@ -0,0 +1,13 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Statically-defined (not runtime-generated) IDL files in 'extensions_*'
+# components for production.
+#
+# CAUTION: static_idl_files_in_extensions_* is used only by a new V8 bindings
+# generator, which is under development.
+static_idl_files_in_extensions_chromeos =
+ get_path_info(
+ [ "//third_party/blink/renderer/extensions/chromeos/chromeos.idl" ],
+ "abspath")
diff --git a/chromium/third_party/blink/renderer/bindings/idl_in_modules.gni b/chromium/third_party/blink/renderer/bindings/idl_in_modules.gni
index d5e757a7f2d..1b725be6817 100644
--- a/chromium/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/chromium/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -74,7 +74,6 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/breakout_box/media_stream_track_generator_init.idl",
"//third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.idl",
"//third_party/blink/renderer/modules/breakout_box/media_stream_track_processor_init.idl",
- "//third_party/blink/renderer/modules/breakout_box/media_stream_track_signal.idl",
"//third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.idl",
"//third_party/blink/renderer/modules/buckets/navigator_storage_buckets.idl",
"//third_party/blink/renderer/modules/buckets/storage_bucket.idl",
@@ -144,6 +143,7 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_outputs.idl",
"//third_party/blink/renderer/modules/credentialmanager/authentication_extensions_large_blob_inputs.idl",
"//third_party/blink/renderer/modules/credentialmanager/authentication_extensions_large_blob_outputs.idl",
+ "//third_party/blink/renderer/modules/credentialmanager/authentication_extensions_payment_inputs.idl",
"//third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.idl",
"//third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.idl",
"//third_party/blink/renderer/modules/credentialmanager/authenticator_response.idl",
@@ -191,6 +191,7 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl",
"//third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.idl",
"//third_party/blink/renderer/modules/delegated_ink/ink.idl",
+ "//third_party/blink/renderer/modules/delegated_ink/ink_presenter_param.idl",
"//third_party/blink/renderer/modules/delegated_ink/ink_trail_style.idl",
"//third_party/blink/renderer/modules/delegated_ink/navigator_ink.idl",
"//third_party/blink/renderer/modules/device_orientation/device_motion_event.idl",
@@ -203,6 +204,8 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/device_orientation/device_orientation_event_init.idl",
"//third_party/blink/renderer/modules/device_orientation/window_device_motion.idl",
"//third_party/blink/renderer/modules/device_orientation/window_device_orientation.idl",
+ "//third_party/blink/renderer/modules/device_posture/device_posture.idl",
+ "//third_party/blink/renderer/modules/device_posture/navigator_device_posture.idl",
"//third_party/blink/renderer/modules/donottrack/navigator_do_not_track.idl",
"//third_party/blink/renderer/modules/encoding/text_decode_options.idl",
"//third_party/blink/renderer/modules/encoding/text_decoder.idl",
@@ -227,13 +230,13 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.idl",
"//third_party/blink/renderer/modules/eventsource/event_source.idl",
"//third_party/blink/renderer/modules/eventsource/event_source_init.idl",
- "//third_party/blink/renderer/modules/eyedropper/color_select_event.idl",
- "//third_party/blink/renderer/modules/eyedropper/color_select_event_init.idl",
+ "//third_party/blink/renderer/modules/eyedropper/color_selection_result.idl",
"//third_party/blink/renderer/modules/eyedropper/eye_dropper.idl",
"//third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.idl",
"//third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl",
"//third_party/blink/renderer/modules/file_system_access/file_picker_accept_type.idl",
"//third_party/blink/renderer/modules/file_system_access/file_picker_options.idl",
+ "//third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_create_writable_options.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.idl",
@@ -242,6 +245,7 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/file_system_access/file_system_get_file_options.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_handle.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_handle_permission_descriptor.idl",
+ "//third_party/blink/renderer/modules/file_system_access/file_system_read_write_options.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_remove_options.idl",
"//third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.idl",
"//third_party/blink/renderer/modules/file_system_access/open_file_picker_options.idl",
@@ -626,18 +630,19 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/quota/worker_navigator_storage_quota.idl",
"//third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl",
"//third_party/blink/renderer/modules/remoteplayback/remote_playback.idl",
+ "//third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl",
"//third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl",
"//third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.idl",
"//third_party/blink/renderer/modules/scheduler/scheduler.idl",
"//third_party/blink/renderer/modules/scheduler/scheduler_post_task_callback.idl",
"//third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl",
"//third_party/blink/renderer/modules/scheduler/task_controller.idl",
+ "//third_party/blink/renderer/modules/scheduler/task_controller_init.idl",
"//third_party/blink/renderer/modules/scheduler/task_priority_change_event.idl",
"//third_party/blink/renderer/modules/scheduler/task_priority_change_event_init.idl",
"//third_party/blink/renderer/modules/scheduler/task_signal.idl",
- "//third_party/blink/renderer/modules/scheduler/window_scheduler.idl",
+ "//third_party/blink/renderer/modules/scheduler/window_or_worker_scheduler.idl",
"//third_party/blink/renderer/modules/screen_enumeration/screen_advanced.idl",
- "//third_party/blink/renderer/modules/screen_enumeration/screen_enumeration.idl",
"//third_party/blink/renderer/modules/screen_enumeration/screens.idl",
"//third_party/blink/renderer/modules/screen_enumeration/window_screens.idl",
"//third_party/blink/renderer/modules/screen_orientation/screen_orientation.idl",
@@ -683,6 +688,11 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/shapedetection/face_detector.idl",
"//third_party/blink/renderer/modules/shapedetection/face_detector_options.idl",
"//third_party/blink/renderer/modules/shapedetection/landmark.idl",
+ "//third_party/blink/renderer/modules/shared_storage/window_shared_storage.idl",
+ "//third_party/blink/renderer/modules/shared_storage/shared_storage.idl",
+ "//third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.idl",
+ "//third_party/blink/renderer/modules/shared_storage/shared_storage_set_method_options.idl",
+ "//third_party/blink/renderer/modules/shared_storage/shared_storage_run_operation_method_options.idl",
"//third_party/blink/renderer/modules/shapedetection/text_detector.idl",
"//third_party/blink/renderer/modules/speech/speech_grammar.idl",
"//third_party/blink/renderer/modules/speech/speech_grammar_list.idl",
@@ -707,6 +717,8 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/storage/storage_event.idl",
"//third_party/blink/renderer/modules/storage/storage_event_init.idl",
"//third_party/blink/renderer/modules/storage/window_storage.idl",
+ "//third_party/blink/renderer/modules/subapps/navigator_sub_apps.idl",
+ "//third_party/blink/renderer/modules/subapps/sub_apps.idl",
"//third_party/blink/renderer/modules/url_pattern/url_pattern.idl",
"//third_party/blink/renderer/modules/url_pattern/url_pattern_component_result.idl",
"//third_party/blink/renderer/modules/url_pattern/url_pattern_init.idl",
@@ -787,6 +799,7 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webaudio/wave_shaper_node.idl",
"//third_party/blink/renderer/modules/webaudio/wave_shaper_options.idl",
"//third_party/blink/renderer/modules/webcodecs/audio_data.idl",
+ "//third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_options.idl",
"//third_party/blink/renderer/modules/webcodecs/audio_data_init.idl",
"//third_party/blink/renderer/modules/webcodecs/audio_data_output_callback.idl",
"//third_party/blink/renderer/modules/webcodecs/audio_decoder.idl",
@@ -797,12 +810,9 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl",
"//third_party/blink/renderer/modules/webcodecs/audio_encoder_init.idl",
"//third_party/blink/renderer/modules/webcodecs/audio_encoder_support.idl",
+ "//third_party/blink/renderer/modules/webcodecs/audio_sample_format.idl",
"//third_party/blink/renderer/modules/webcodecs/avc_encoder_config.idl",
"//third_party/blink/renderer/modules/webcodecs/codec_state.idl",
- "//third_party/blink/renderer/modules/webcodecs/color_space_matrix_id.idl",
- "//third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl",
- "//third_party/blink/renderer/modules/webcodecs/color_space_range_id.idl",
- "//third_party/blink/renderer/modules/webcodecs/color_space_transfer_id.idl",
"//third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl",
"//third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_init.idl",
"//third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_metadata.idl",
@@ -818,10 +828,11 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl",
"//third_party/blink/renderer/modules/webcodecs/image_track.idl",
"//third_party/blink/renderer/modules/webcodecs/image_track_list.idl",
- "//third_party/blink/renderer/modules/webcodecs/plane.idl",
- "//third_party/blink/renderer/modules/webcodecs/plane_init.idl",
+ "//third_party/blink/renderer/modules/webcodecs/latency_mode.idl",
"//third_party/blink/renderer/modules/webcodecs/plane_layout.idl",
+ "//third_party/blink/renderer/modules/webcodecs/video_color_primaries.idl",
"//third_party/blink/renderer/modules/webcodecs/video_color_space.idl",
+ "//third_party/blink/renderer/modules/webcodecs/video_color_space_init.idl",
"//third_party/blink/renderer/modules/webcodecs/video_decoder.idl",
"//third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl",
"//third_party/blink/renderer/modules/webcodecs/video_decoder_init.idl",
@@ -832,12 +843,13 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webcodecs/video_encoder_init.idl",
"//third_party/blink/renderer/modules/webcodecs/video_encoder_support.idl",
"//third_party/blink/renderer/modules/webcodecs/video_frame.idl",
+ "//third_party/blink/renderer/modules/webcodecs/video_frame_buffer_init.idl",
+ "//third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_options.idl",
"//third_party/blink/renderer/modules/webcodecs/video_frame_init.idl",
"//third_party/blink/renderer/modules/webcodecs/video_frame_output_callback.idl",
- "//third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl",
- "//third_party/blink/renderer/modules/webcodecs/video_frame_read_into_options.idl",
- "//third_party/blink/renderer/modules/webcodecs/video_frame_region.idl",
+ "//third_party/blink/renderer/modules/webcodecs/video_matrix_coefficients.idl",
"//third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl",
+ "//third_party/blink/renderer/modules/webcodecs/video_transfer_characteristics.idl",
"//third_party/blink/renderer/modules/webcodecs/webcodecs_error_callback.idl",
"//third_party/blink/renderer/modules/webdatabase/database.idl",
"//third_party/blink/renderer/modules/webdatabase/sql_error.idl",
@@ -931,6 +943,7 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webgpu/gpu_buffer_binding_layout.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl",
@@ -952,12 +965,16 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_extent_3d_dict.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_external_texture.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_external_texture_binding_layout.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_external_texture_descriptor.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_fragment_state.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_image_copy_buffer.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_image_copy_image_bitmap.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_image_copy_texture.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_image_copy_texture_tagged.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_image_data_layout.idl",
- "//third_party/blink/renderer/modules/webgpu/gpu_limits.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_map_mode.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_multisample_state.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_object_base.idl",
@@ -997,8 +1014,8 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/webgpu/gpu_stencil_face_state.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_storage_texture_binding_layout.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl",
+ "//third_party/blink/renderer/modules/webgpu/gpu_supported_limits.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_swap_chain.idl",
- "//third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_texture.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_texture_binding_layout.idl",
"//third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl",
diff --git a/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn b/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
deleted file mode 100644
index aaf3e7e9c06..00000000000
--- a/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
+++ /dev/null
@@ -1,173 +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.
-
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
-import("//third_party/blink/renderer/build/scripts/scripts.gni")
-import("//third_party/blink/renderer/modules/modules.gni")
-
-group("bindings_modules_generated") {
- visibility = [ "//third_party/blink/*" ]
- public_deps = [
- ":event_modules",
- ":event_modules_names",
- ":event_target_modules_names",
- ":modules_bindings_generated_event_interfaces",
- ]
-}
-
-generate_event_interfaces("modules_bindings_generated_event_interfaces") {
- sources = [
- "//third_party/blink/renderer/modules/app_banner/before_install_prompt_event.idl",
- "//third_party/blink/renderer/modules/background_fetch/background_fetch_event.idl",
- "//third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.idl",
- "//third_party/blink/renderer/modules/background_sync/periodic_sync_event.idl",
- "//third_party/blink/renderer/modules/background_sync/sync_event.idl",
- "//third_party/blink/renderer/modules/content_index/content_index_event.idl",
- "//third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl",
- "//third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl",
- "//third_party/blink/renderer/modules/device_orientation/device_motion_event.idl",
- "//third_party/blink/renderer/modules/device_orientation/device_orientation_event.idl",
- "//third_party/blink/renderer/modules/encryptedmedia/media_encrypted_event.idl",
- "//third_party/blink/renderer/modules/encryptedmedia/media_key_message_event.idl",
- "//third_party/blink/renderer/modules/gamepad/gamepad_axis_event.idl",
- "//third_party/blink/renderer/modules/gamepad/gamepad_button_event.idl",
- "//third_party/blink/renderer/modules/gamepad/gamepad_event.idl",
- "//third_party/blink/renderer/modules/hid/hid_connection_event.idl",
- "//third_party/blink/renderer/modules/hid/hid_input_report_event.idl",
- "//third_party/blink/renderer/modules/indexeddb/idb_version_change_event.idl",
- "//third_party/blink/renderer/modules/mediarecorder/blob_event.idl",
- "//third_party/blink/renderer/modules/mediastream/capture_handle_change_event.idl",
- "//third_party/blink/renderer/modules/mediastream/capture_handle_change_event_init.idl",
- "//third_party/blink/renderer/modules/mediastream/media_stream_event.idl",
- "//third_party/blink/renderer/modules/mediastream/media_stream_track_event.idl",
- "//third_party/blink/renderer/modules/nfc/ndef_reading_event.idl",
- "//third_party/blink/renderer/modules/notifications/notification_event.idl",
- "//third_party/blink/renderer/modules/payments/abort_payment_event.idl",
- "//third_party/blink/renderer/modules/payments/can_make_payment_event.idl",
- "//third_party/blink/renderer/modules/payments/merchant_validation_event.idl",
- "//third_party/blink/renderer/modules/payments/payment_method_change_event.idl",
- "//third_party/blink/renderer/modules/payments/payment_request_details_update.idl",
- "//third_party/blink/renderer/modules/payments/payment_request_event.idl",
- "//third_party/blink/renderer/modules/payments/payment_request_update_event.idl",
- "//third_party/blink/renderer/modules/peerconnection/rtc_data_channel_event.idl",
- "//third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl",
- "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event.idl",
- "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.idl",
- "//third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_event.idl",
- "//third_party/blink/renderer/modules/presentation/presentation_connection_available_event.idl",
- "//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/scheduler/task_priority_change_event.idl",
- "//third_party/blink/renderer/modules/sensor/sensor_error_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_event.idl",
- "//third_party/blink/renderer/modules/speech/speech_recognition_event.idl",
- "//third_party/blink/renderer/modules/speech/speech_synthesis_error_event.idl",
- "//third_party/blink/renderer/modules/speech/speech_synthesis_event.idl",
- "//third_party/blink/renderer/modules/storage/storage_event.idl",
- "//third_party/blink/renderer/modules/webaudio/audio_processing_event.idl",
- "//third_party/blink/renderer/modules/webaudio/offline_audio_completion_event.idl",
- "//third_party/blink/renderer/modules/webgl/webgl_context_event.idl",
- "//third_party/blink/renderer/modules/webmidi/midi_connection_event.idl",
- "//third_party/blink/renderer/modules/webmidi/midi_message_event.idl",
- "//third_party/blink/renderer/modules/websockets/close_event.idl",
- "//third_party/blink/renderer/modules/xr/xr_input_source_event.idl",
- "//third_party/blink/renderer/modules/xr/xr_input_sources_change_event.idl",
- "//third_party/blink/renderer/modules/xr/xr_reference_space_event.idl",
- "//third_party/blink/renderer/modules/xr/xr_session_event.idl",
- ]
-
- output_file = "modules/event_interface_modules_names.json5"
- suffix = "Modules"
-}
-
-make_event_factory("event_modules") {
- visibility = [ ":*" ]
- in_files = [ "$blink_modules_output_dir/event_interface_modules_names.json5" ]
- outputs = [ "$blink_modules_output_dir/event_modules_factory.cc" ]
- deps = make_core_generated_deps + [ "//third_party/blink/renderer/bindings/modules:modules_bindings_generated_event_interfaces" ]
-}
-
-make_names("event_modules_names") {
- visibility = [ ":*" ]
- in_files = [ "$blink_modules_output_dir/event_interface_modules_names.json5" ]
- output_dir = blink_modules_output_dir
- deps = make_core_generated_deps + [ "//third_party/blink/renderer/bindings/modules:modules_bindings_generated_event_interfaces" ]
-}
-
-make_names("event_target_modules_names") {
- visibility = [ ":*" ]
- in_files = [ "../../modules/event_target_modules_names.json5" ]
- output_dir = blink_modules_output_dir
-}
-
-# ------------------------------------------------------------------------------
-
-compute_interfaces_info("interfaces_info_modules") {
- sources = modules_static_interface_idl_files + modules_definition_idl_files +
- modules_static_dependency_idl_files +
- modules_generated_dependency_idl_files
-
- interfaces_info_file =
- "$bindings_modules_output_dir/interfaces_info_modules.pickle"
- component_info_file =
- "$bindings_modules_output_dir/component_info_modules.pickle"
- deps = [
- ":modules_global_constructors_idls",
- "//third_party/blink/renderer/bindings:global_constructors_idls",
- ]
-}
-
-compute_global_objects("modules_global_objects") {
- sources = modules_idl_files
- sources_generated = [ "$bindings_core_output_dir/global_objects_core.pickle" ]
- output_file = "$bindings_modules_output_dir/global_objects_modules.pickle"
- deps = [ "//third_party/blink/renderer/bindings/core:core_global_objects" ]
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("modules_global_constructors_idls") {
- }
-} else {
- generate_global_constructors("modules_global_constructors_idls") {
- sources = modules_idl_files
- global_objects_file =
- "$bindings_modules_output_dir/global_objects_modules.pickle"
- interfaces = modules_global_constructors_original_interfaces
- basenames = modules_global_constructors_original_interface_basenames
- component = "modules"
- output_dir = blink_modules_output_dir
- deps = [ ":modules_global_objects" ]
- }
-}
-
-# Compile the sources produced above. This will get linked into "modules".
-source_set("generated") {
- visibility = [ "//third_party/blink/renderer/modules:*" ]
-
- sources = get_target_outputs(":event_modules") +
- get_target_outputs(":event_modules_names") +
- get_target_outputs(":event_target_modules_names")
-
- configs += [
- "//third_party/blink/renderer:config",
- "//third_party/blink/renderer/modules:modules_implementation",
- "//third_party/blink/renderer:non_test_config",
- "//third_party/blink/renderer:inside_blink",
- ]
-
- deps = [
- ":event_modules",
- ":event_modules_names",
- ":event_target_modules_names",
- "//media/midi:mojo_blink_headers",
- "//third_party/blink/public/mojom:mojom_modules_blink_headers",
- "//third_party/blink/renderer/core",
- "//third_party/blink/renderer/platform/wtf",
- "//v8",
- ]
-}
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn b/chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
index f52b72568d4..49ceb53b568 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
@@ -2,13 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/config/python.gni")
-import("//third_party/blink/renderer/bindings/bindings.gni")
import("//third_party/blink/renderer/bindings/generated_in_modules.gni")
-import("//third_party/blink/renderer/bindings/modules/v8/generated.gni")
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
import("//third_party/blink/renderer/modules/modules.gni")
-import("//third_party/blink/renderer/modules/modules_idl_files.gni")
visibility = [ "//third_party/blink/renderer/*" ]
@@ -16,25 +11,16 @@ blink_modules_sources("v8") {
visibility = []
visibility = [ "//third_party/blink/renderer/modules" ]
- sources = generated_enumeration_sources_in_modules
- if (use_blink_v8_binding_new_idl_callback_function) {
- sources += generated_callback_function_sources_in_modules
- }
- if (use_blink_v8_binding_new_idl_callback_interface) {
- sources += generated_callback_interface_sources_in_modules
- }
- if (use_blink_v8_binding_new_idl_dictionary) {
- sources += generated_dictionary_sources_in_modules
- }
- if (use_blink_v8_binding_new_idl_interface) {
- sources += generated_interface_sources_in_modules +
- generated_namespace_sources_in_modules
- }
- sources += generated_typedef_sources_in_modules
- sources += generated_union_sources_in_modules
+ sources =
+ generated_callback_function_sources_in_modules +
+ generated_callback_interface_sources_in_modules +
+ generated_dictionary_sources_in_modules +
+ generated_enumeration_sources_in_modules +
+ generated_interface_sources_in_modules +
+ generated_namespace_sources_in_modules +
+ generated_typedef_sources_in_modules + generated_union_sources_in_modules
deps = [
- ":generate_mojo_bindings",
":generated",
"//third_party/blink/renderer/platform",
"//v8",
@@ -52,15 +38,7 @@ source_set("testing") {
"//third_party/blink/renderer:inside_blink",
]
- sources = []
- if (use_blink_v8_binding_new_idl_interface) {
- sources += generated_interface_sources_for_testing_in_modules
- } else {
- sources += [
- "$bindings_modules_v8_output_dir/v8_internals_partial.cc",
- "$bindings_modules_v8_output_dir/v8_internals_partial.h",
- ]
- }
+ sources = generated_interface_sources_for_testing_in_modules
deps = [
":generated",
@@ -69,9 +47,6 @@ source_set("testing") {
"//third_party/blink/renderer/platform",
"//v8",
]
- if (!use_blink_v8_binding_new_idl_interface) {
- deps += [ ":generate_bindings_modules_v8_partial_interfaces_for_testing" ]
- }
}
group("generated") {
@@ -81,205 +56,6 @@ group("generated") {
"//third_party/blink/renderer/modules/*",
]
- public_deps = [
- ":bindings_modules_v8_generated",
- "//third_party/blink/renderer/bindings:generate_bindings_all",
- ]
-}
-
-group("bindings_modules_v8_generated") {
- public_deps = [
- ":bindings_modules_impl_generated",
- ":bindings_modules_v8_generated_init_partial",
- ":generate_bindings_modules_v8_interfaces",
- ":generate_bindings_modules_v8_partial_interfaces",
- ":generate_bindings_modules_v8_partial_interfaces_for_testing",
- ":generate_v8_context_snapshot_external_references",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
- ]
-}
-
-if (!use_blink_v8_binding_new_idl_callback_interface ||
- !use_blink_v8_binding_new_idl_dictionary ||
- !use_blink_v8_binding_new_idl_interface) {
- idl_compiler("generate_bindings_modules_v8_interfaces") {
- sources = []
- if (!use_blink_v8_binding_new_idl_callback_interface) {
- sources += filter_include(modules_idl_files, [ "*_callback.idl" ])
- }
- if (!use_blink_v8_binding_new_idl_dictionary) {
- sources += modules_dictionary_idl_files
- }
- if (!use_blink_v8_binding_new_idl_interface) {
- sources += filter_exclude(modules_idl_files, [ "*_callback.idl" ])
- }
- output_dir = bindings_modules_v8_output_dir
- output_name_suffix = ""
- target_component = "modules"
- }
-} else {
- group("generate_bindings_modules_v8_interfaces") {
- }
-}
-
-idl_impl("bindings_modules_impl_generated") {
- if (use_blink_v8_binding_new_idl_dictionary) {
- dict_idls = []
- } else {
- dict_idls = modules_dictionary_idl_files
- }
- non_dict_outputs = bindings_modules_generated_union_type_files
- if (!use_blink_v8_binding_new_idl_callback_function) {
- non_dict_outputs += generated_modules_callback_function_files
- }
- non_dict_output_dir = bindings_modules_v8_output_dir
- target_component = "modules"
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("generate_bindings_modules_v8_partial_interfaces") {
- }
-} else {
- idl_compiler("generate_bindings_modules_v8_partial_interfaces") {
- sources = core_interface_idl_files_modules_dependent
- output_dir = bindings_modules_v8_output_dir
- output_name_suffix = "_partial"
- target_component = "modules"
- }
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("generate_bindings_modules_v8_partial_interfaces_for_testing") {
- }
-} else {
- idl_compiler("generate_bindings_modules_v8_partial_interfaces_for_testing") {
- sources = webcore_testing_idl_with_modules_dependency_files
- output_dir = bindings_modules_v8_output_dir
- output_name_suffix = "_partial"
- target_component = "modules"
- }
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("bindings_modules_origin_trial_features") {
- }
-} else {
- generate_origin_trial_features("bindings_modules_origin_trial_features") {
- sources = modules_idl_files + modules_generated_dependency_idl_files +
- modules_dependency_idl_files
- component = "modules"
- output_dir = bindings_modules_output_dir + "/v8"
- deps = [
- "//third_party/blink/renderer/bindings:global_constructors_idls",
- "//third_party/blink/renderer/bindings/modules:interfaces_info_modules",
- "//third_party/blink/renderer/bindings/modules:modules_global_constructors_idls",
- ]
- }
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- group("bindings_modules_v8_generated_init_partial") {
- }
-} else {
- action("bindings_modules_v8_generated_init_partial") {
- script = "$bindings_scripts_dir/generate_init_partial_interfaces.py"
-
- inputs = [ "$bindings_output_dir/interfaces_info.pickle" ]
- outputs = [ bindings_modules_generated_init_partial_interfaces_file ]
-
- # Put the IDL file list in a response file to avoid command-line limits.
- response_file_contents =
- rebase_path(core_interface_idl_files_modules_dependent, root_build_dir)
-
- args = [
- "--idl-files-list",
- "{{response_file_name}}",
- "--output",
- rebase_path(bindings_modules_generated_init_partial_interfaces_file,
- root_build_dir),
- ]
-
- deps = [ "//third_party/blink/renderer/bindings:interfaces_info" ]
- }
-}
-
-# Note that this intentionally depends on the generator target of the mojom
-# target instead of the mojom target itself directly. This is to ensure that the
-# dependencies are header-only and don't link against any bindings code.
-group("generate_mojo_bindings") {
- visibility = [] # Allow re-assignment of list.
- visibility = [ ":*" ]
-
- deps = [
- "//device/gamepad/public/mojom:mojom_blink_headers",
- "//device/vr/public/mojom:vr_service_blink_headers",
- "//media/capture/mojom:image_capture_blink_headers",
- "//media/midi:mojo_blink_headers",
- "//services/device/public/mojom:generic_sensor_headers",
- "//services/device/public/mojom:mojom_blink_headers",
- "//services/device/public/mojom:usb_blink_headers",
- "//services/shape_detection/public/mojom:mojom_blink_headers",
-
- # IndexedDB Mojom Blink headers are provided by the mojom_modules
- # target.
- "//third_party/blink/public/mojom:mojom_modules_blink_headers",
- ]
-}
-
-blink_modules_sources("bindings_modules_impl") {
- # ":generate_bindings_modules_v8_partial_interfaces_for_testing" is not
- # included here.
- sources = get_target_outputs(":bindings_modules_impl_generated")
-
- if (!use_blink_v8_binding_new_idl_callback_interface ||
- !use_blink_v8_binding_new_idl_dictionary ||
- !use_blink_v8_binding_new_idl_interface) {
- sources += get_target_outputs(":generate_bindings_modules_v8_interfaces")
- }
- if (!use_blink_v8_binding_new_idl_interface) {
- sources +=
- get_target_outputs(":generate_bindings_modules_v8_partial_interfaces") +
- get_target_outputs(":bindings_modules_v8_generated_init_partial") +
- get_target_outputs(":bindings_modules_origin_trial_features")
- }
-
- deps = [
- ":bindings_modules_origin_trial_features",
- ":bindings_modules_v8_generated",
- ":generate_mojo_bindings",
- ":generated",
- "//third_party/blink/renderer/modules/mediarecorder:buildflags",
- "//third_party/dawn/src/dawn:dawn_headers",
- ]
-}
-
-action("generate_v8_context_snapshot_external_references") {
- script = "$bindings_scripts_dir/generate_v8_context_snapshot_external_references.py"
- idl_files =
- core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent + modules_definition_idl_files
- output = bindings_generated_v8_context_snapshot_external_references_file
-
- inputs = idl_files + [ script ]
- outputs = [ output ]
-
- response_file_contents = rebase_path(idl_files, root_build_dir)
- args = [
- "--cache-dir",
- rebase_path(bindings_scripts_output_dir, root_build_dir),
- "--output",
- rebase_path(output, root_build_dir),
- "--idl-files-list",
- "{{response_file_name}}",
- "--info-dir",
- rebase_path("$bindings_output_dir", root_build_dir),
- "--target-component",
- "modules",
- ]
-
- deps = [
- "//third_party/blink/renderer/bindings:interfaces_info",
- "//third_party/blink/renderer/bindings/scripts:cached_jinja_templates",
- "//third_party/blink/renderer/bindings/scripts:cached_lex_yacc_tables",
- ]
+ public_deps =
+ [ "//third_party/blink/renderer/bindings:generate_bindings_all" ]
}
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/custom/custom.gni b/chromium/third_party/blink/renderer/bindings/modules/v8/custom/custom.gni
deleted file mode 100644
index 2b8700cd118..00000000000
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/custom/custom.gni
+++ /dev/null
@@ -1,6 +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.
-
-# Make the files absolute so they can be imported to anywhere.
-bindings_modules_v8_custom_files = get_path_info([], "abspath")
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni b/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
deleted file mode 100644
index baf661b56dd..00000000000
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
+++ /dev/null
@@ -1,206 +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.
-
-import("//build/config/chrome_build.gni")
-import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
-import("//third_party/blink/renderer/core/core_idl_files.gni")
-import("//third_party/blink/renderer/modules/modules_idl_files.gni")
-
-bindings_modules_v8_output_dir = "$bindings_output_dir/modules/v8"
-
-bindings_modules_generated_init_partial_interfaces_file =
- "$bindings_modules_v8_output_dir/init_partial_interfaces_in_modules.cc"
-
-# TODO(bashi): It would be better to have a way to update this list automatically.
-bindings_modules_generated_union_type_files = [
- "$bindings_modules_v8_output_dir/animation_effect_or_animation_effect_sequence.cc",
- "$bindings_modules_v8_output_dir/animation_effect_or_animation_effect_sequence.h",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_blob_or_usv_string_or_write_params.cc",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_blob_or_usv_string_or_write_params.h",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_json_web_key.cc",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_json_web_key.h",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_readable_stream.cc",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_readable_stream.h",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_string.cc",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_string.h",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_usv_string.cc",
- "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_usv_string.h",
- "$bindings_modules_v8_output_dir/audio_context_latency_category_or_double.cc",
- "$bindings_modules_v8_output_dir/audio_context_latency_category_or_double.h",
- "$bindings_modules_v8_output_dir/boolean_or_constrain_boolean_parameters.cc",
- "$bindings_modules_v8_output_dir/boolean_or_constrain_boolean_parameters.h",
- "$bindings_modules_v8_output_dir/boolean_or_double_or_constrain_double_range.cc",
- "$bindings_modules_v8_output_dir/boolean_or_double_or_constrain_double_range.h",
- "$bindings_modules_v8_output_dir/boolean_or_media_track_constraints.cc",
- "$bindings_modules_v8_output_dir/boolean_or_media_track_constraints.h",
- "$bindings_modules_v8_output_dir/canvas_filter_dictionary_or_canvas_filter_dictionary_array.cc",
- "$bindings_modules_v8_output_dir/canvas_filter_dictionary_or_canvas_filter_dictionary_array.h",
- "$bindings_modules_v8_output_dir/canvas_image_source.cc",
- "$bindings_modules_v8_output_dir/canvas_image_source.h",
- "$bindings_modules_v8_output_dir/client_or_service_worker_or_message_port.cc",
- "$bindings_modules_v8_output_dir/client_or_service_worker_or_message_port.h",
- "$bindings_modules_v8_output_dir/document_timeline_or_scroll_timeline.cc",
- "$bindings_modules_v8_output_dir/document_timeline_or_scroll_timeline.h",
- "$bindings_modules_v8_output_dir/dom_exception_or_overconstrained_error.cc",
- "$bindings_modules_v8_output_dir/dom_exception_or_overconstrained_error.h",
- "$bindings_modules_v8_output_dir/double_or_constrain_double_range.cc",
- "$bindings_modules_v8_output_dir/double_or_constrain_double_range.h",
- "$bindings_modules_v8_output_dir/double_sequence_or_gpu_color_dict.cc",
- "$bindings_modules_v8_output_dir/double_sequence_or_gpu_color_dict.h",
- "$bindings_modules_v8_output_dir/encoded_audio_chunk_or_encoded_video_chunk.cc",
- "$bindings_modules_v8_output_dir/encoded_audio_chunk_or_encoded_video_chunk.h",
- "$bindings_modules_v8_output_dir/encoded_av_chunk_sequence_or_encoded_av_chunk.cc",
- "$bindings_modules_v8_output_dir/encoded_av_chunk_sequence_or_encoded_av_chunk.h",
- "$bindings_modules_v8_output_dir/float32_array_or_float64_array_or_dom_matrix.cc",
- "$bindings_modules_v8_output_dir/float32_array_or_float64_array_or_dom_matrix.h",
- "$bindings_modules_v8_output_dir/gpu_buffer_or_array_buffer.cc",
- "$bindings_modules_v8_output_dir/gpu_buffer_or_array_buffer.h",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_double_sequence_or_gpu_color_dict.cc",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_double_sequence_or_gpu_color_dict.h",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_float.cc",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_float.h",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_unsigned_long_enforce_range.cc",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_unsigned_long_enforce_range.h",
- "$bindings_modules_v8_output_dir/gpu_out_of_memory_error_or_gpu_validation_error.cc",
- "$bindings_modules_v8_output_dir/gpu_out_of_memory_error_or_gpu_validation_error.h",
- "$bindings_modules_v8_output_dir/gpu_sampler_or_gpu_texture_view_or_gpu_buffer_binding.cc",
- "$bindings_modules_v8_output_dir/gpu_sampler_or_gpu_texture_view_or_gpu_buffer_binding.h",
- "$bindings_modules_v8_output_dir/html_canvas_element_or_offscreen_canvas.cc",
- "$bindings_modules_v8_output_dir/html_canvas_element_or_offscreen_canvas.h",
- "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index.cc",
- "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index.h",
- "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index_or_idb_cursor.cc",
- "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index_or_idb_cursor.h",
- "$bindings_modules_v8_output_dir/image_bitmap_source.cc",
- "$bindings_modules_v8_output_dir/image_bitmap_source.h",
- "$bindings_modules_v8_output_dir/int32_array_or_long_sequence.cc",
- "$bindings_modules_v8_output_dir/int32_array_or_long_sequence.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/object_or_string.cc",
- "$bindings_modules_v8_output_dir/object_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",
- "$bindings_modules_v8_output_dir/password_credential_data_or_html_form_element.h",
- "$bindings_modules_v8_output_dir/path_2d_or_string.cc",
- "$bindings_modules_v8_output_dir/path_2d_or_string.h",
- "$bindings_modules_v8_output_dir/point_2d_sequence_or_constrain_point_2d_parameters.cc",
- "$bindings_modules_v8_output_dir/point_2d_sequence_or_constrain_point_2d_parameters.h",
- "$bindings_modules_v8_output_dir/readable_stream_or_xml_http_request_body_init.cc",
- "$bindings_modules_v8_output_dir/readable_stream_or_xml_http_request_body_init.h",
- "$bindings_modules_v8_output_dir/rendering_context.cc",
- "$bindings_modules_v8_output_dir/rendering_context.h",
- "$bindings_modules_v8_output_dir/request_or_usv_string_or_request_or_usv_string_sequence.cc",
- "$bindings_modules_v8_output_dir/request_or_usv_string_or_request_or_usv_string_sequence.h",
- "$bindings_modules_v8_output_dir/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.cc",
- "$bindings_modules_v8_output_dir/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.h",
- "$bindings_modules_v8_output_dir/string_or_canvas_filter.cc",
- "$bindings_modules_v8_output_dir/string_or_canvas_filter.h",
- "$bindings_modules_v8_output_dir/string_or_canvas_gradient_or_canvas_pattern_or_css_color_value.cc",
- "$bindings_modules_v8_output_dir/string_or_canvas_gradient_or_canvas_pattern_or_css_color_value.h",
- "$bindings_modules_v8_output_dir/string_or_document_fragment_or_document.cc",
- "$bindings_modules_v8_output_dir/string_or_document_fragment_or_document.h",
- "$bindings_modules_v8_output_dir/string_or_string_sequence_or_constrain_dom_string_parameters.cc",
- "$bindings_modules_v8_output_dir/string_or_string_sequence_or_constrain_dom_string_parameters.h",
- "$bindings_modules_v8_output_dir/string_or_trusted_html_or_document_fragment_or_document.cc",
- "$bindings_modules_v8_output_dir/string_or_trusted_html_or_document_fragment_or_document.h",
- "$bindings_modules_v8_output_dir/string_or_unsigned_long.cc",
- "$bindings_modules_v8_output_dir/string_or_unsigned_long.h",
- "$bindings_modules_v8_output_dir/uint32_array_or_unsigned_long_sequence.cc",
- "$bindings_modules_v8_output_dir/uint32_array_or_unsigned_long_sequence.h",
- "$bindings_modules_v8_output_dir/unrestricted_double_or_dom_point.h",
- "$bindings_modules_v8_output_dir/unrestricted_double_or_dom_point.cc",
- "$bindings_modules_v8_output_dir/unsigned_long_or_unsigned_long_sequence.cc",
- "$bindings_modules_v8_output_dir/unsigned_long_or_unsigned_long_sequence.h",
- "$bindings_modules_v8_output_dir/unsigned_long_enforce_range_sequence_or_gpu_extent_3d_dict.cc",
- "$bindings_modules_v8_output_dir/unsigned_long_enforce_range_sequence_or_gpu_extent_3d_dict.h",
- "$bindings_modules_v8_output_dir/unsigned_long_enforce_range_sequence_or_gpu_origin_2d_dict.cc",
- "$bindings_modules_v8_output_dir/unsigned_long_enforce_range_sequence_or_gpu_origin_2d_dict.h",
- "$bindings_modules_v8_output_dir/unsigned_long_enforce_range_sequence_or_gpu_origin_3d_dict.cc",
- "$bindings_modules_v8_output_dir/unsigned_long_enforce_range_sequence_or_gpu_origin_3d_dict.h",
- "$bindings_modules_v8_output_dir/usv_string_or_uint32_array.cc",
- "$bindings_modules_v8_output_dir/usv_string_or_uint32_array.h",
- "$bindings_modules_v8_output_dir/usv_string_or_url_pattern_init.cc",
- "$bindings_modules_v8_output_dir/usv_string_or_url_pattern_init.h",
- "$bindings_modules_v8_output_dir/usv_string_or_usv_string_sequence.cc",
- "$bindings_modules_v8_output_dir/usv_string_or_usv_string_sequence.h",
- "$bindings_modules_v8_output_dir/webgl_rendering_context_or_webgl2_rendering_context.cc",
- "$bindings_modules_v8_output_dir/webgl_rendering_context_or_webgl2_rendering_context.h",
- "$bindings_modules_v8_output_dir/well_known_directory_or_file_system_handle.cc",
- "$bindings_modules_v8_output_dir/well_known_directory_or_file_system_handle.h",
- "$bindings_modules_v8_output_dir/worklet_animation_effect_or_worklet_group_effect.cc",
- "$bindings_modules_v8_output_dir/worklet_animation_effect_or_worklet_group_effect.h",
-]
-
-generated_modules_callback_function_files = [
- "$bindings_modules_v8_output_dir/v8_animate_callback.cc",
- "$bindings_modules_v8_output_dir/v8_animate_callback.h",
- "$bindings_modules_v8_output_dir/v8_animator_constructor.cc",
- "$bindings_modules_v8_output_dir/v8_animator_constructor.h",
- "$bindings_modules_v8_output_dir/v8_audio_data_output_callback.cc",
- "$bindings_modules_v8_output_dir/v8_audio_data_output_callback.h",
- "$bindings_modules_v8_output_dir/v8_blink_audio_worklet_process_callback.cc",
- "$bindings_modules_v8_output_dir/v8_blink_audio_worklet_process_callback.h",
- "$bindings_modules_v8_output_dir/v8_blink_audio_worklet_processor_constructor.cc",
- "$bindings_modules_v8_output_dir/v8_blink_audio_worklet_processor_constructor.h",
- "$bindings_modules_v8_output_dir/v8_database_callback.cc",
- "$bindings_modules_v8_output_dir/v8_database_callback.h",
- "$bindings_modules_v8_output_dir/v8_decode_error_callback.cc",
- "$bindings_modules_v8_output_dir/v8_decode_error_callback.h",
- "$bindings_modules_v8_output_dir/v8_decode_success_callback.cc",
- "$bindings_modules_v8_output_dir/v8_decode_success_callback.h",
- "$bindings_modules_v8_output_dir/v8_encoded_audio_chunk_output_callback.cc",
- "$bindings_modules_v8_output_dir/v8_encoded_audio_chunk_output_callback.h",
- "$bindings_modules_v8_output_dir/v8_launch_consumer.cc",
- "$bindings_modules_v8_output_dir/v8_launch_consumer.h",
- "$bindings_modules_v8_output_dir/v8_lock_granted_callback.cc",
- "$bindings_modules_v8_output_dir/v8_lock_granted_callback.h",
- "$bindings_modules_v8_output_dir/v8_media_session_action_handler.cc",
- "$bindings_modules_v8_output_dir/v8_media_session_action_handler.h",
- "$bindings_modules_v8_output_dir/v8_navigator_user_media_error_callback.cc",
- "$bindings_modules_v8_output_dir/v8_navigator_user_media_error_callback.h",
- "$bindings_modules_v8_output_dir/v8_navigator_user_media_success_callback.cc",
- "$bindings_modules_v8_output_dir/v8_navigator_user_media_success_callback.h",
- "$bindings_modules_v8_output_dir/v8_notification_permission_callback.cc",
- "$bindings_modules_v8_output_dir/v8_notification_permission_callback.h",
- "$bindings_modules_v8_output_dir/v8_paint_callback.cc",
- "$bindings_modules_v8_output_dir/v8_paint_callback.h",
- "$bindings_modules_v8_output_dir/v8_position_callback.cc",
- "$bindings_modules_v8_output_dir/v8_position_callback.h",
- "$bindings_modules_v8_output_dir/v8_position_error_callback.cc",
- "$bindings_modules_v8_output_dir/v8_position_error_callback.h",
- "$bindings_modules_v8_output_dir/v8_remote_playback_availability_callback.cc",
- "$bindings_modules_v8_output_dir/v8_remote_playback_availability_callback.h",
- "$bindings_modules_v8_output_dir/v8_rtc_peer_connection_error_callback.cc",
- "$bindings_modules_v8_output_dir/v8_rtc_peer_connection_error_callback.h",
- "$bindings_modules_v8_output_dir/v8_rtc_session_description_callback.cc",
- "$bindings_modules_v8_output_dir/v8_rtc_session_description_callback.h",
- "$bindings_modules_v8_output_dir/v8_rtc_stats_callback.cc",
- "$bindings_modules_v8_output_dir/v8_rtc_stats_callback.h",
- "$bindings_modules_v8_output_dir/v8_state_callback.cc",
- "$bindings_modules_v8_output_dir/v8_state_callback.h",
- "$bindings_modules_v8_output_dir/v8_storage_error_callback.cc",
- "$bindings_modules_v8_output_dir/v8_storage_error_callback.h",
- "$bindings_modules_v8_output_dir/v8_storage_quota_callback.cc",
- "$bindings_modules_v8_output_dir/v8_storage_quota_callback.h",
- "$bindings_modules_v8_output_dir/v8_storage_usage_callback.cc",
- "$bindings_modules_v8_output_dir/v8_storage_usage_callback.h",
- "$bindings_modules_v8_output_dir/v8_video_encoder_output_callback.cc",
- "$bindings_modules_v8_output_dir/v8_video_encoder_output_callback.h",
- "$bindings_modules_v8_output_dir/v8_video_frame_output_callback.cc",
- "$bindings_modules_v8_output_dir/v8_video_frame_output_callback.h",
- "$bindings_modules_v8_output_dir/v8_video_frame_request_callback.cc",
- "$bindings_modules_v8_output_dir/v8_video_frame_request_callback.h",
- "$bindings_modules_v8_output_dir/v8_webcodecs_error_callback.cc",
- "$bindings_modules_v8_output_dir/v8_webcodecs_error_callback.h",
- "$bindings_modules_v8_output_dir/v8_xr_frame_request_callback.cc",
- "$bindings_modules_v8_output_dir/v8_xr_frame_request_callback.h",
-]
-
-bindings_generated_v8_context_snapshot_external_references_file =
- "$bindings_modules_v8_output_dir/v8_context_snapshot_external_references.cc"
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.cc
index 50af0c81717..c9e00f023d5 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.cc
@@ -4,34 +4,20 @@
#include "third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.h"
-#include "third_party/blink/renderer/bindings/modules/v8/serialization/serialized_script_value_for_modules_factory.h"
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
#include "third_party/blink/renderer/bindings/modules/v8/init_idl_interfaces.h"
#include "third_party/blink/renderer/bindings/modules/v8/properties_per_feature_installer.h"
+#include "third_party/blink/renderer/bindings/modules/v8/serialization/serialized_script_value_for_modules_factory.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_impl.h"
#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
-#else
-#include "third_party/blink/renderer/bindings/modules/v8/origin_trial_features_for_modules.h"
-#endif
namespace blink {
-// initPartialInterfacesInModules is generated by
-// generate_init_partial_interfaces.py.
-void InitPartialInterfacesInModules();
-
void ModuleBindingsInitializer::Init() {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
bindings::InitIDLInterfaces();
auto* old_installer =
SetInstallPropertiesPerFeatureFunc(bindings::InstallPropertiesPerFeature);
CHECK(!old_installer);
V8ContextSnapshotImpl::Init();
-#else
- RegisterInstallOriginTrialFeaturesForModules();
- InitPartialInterfacesInModules();
-#endif
SerializedScriptValueFactory::Initialize(
new SerializedScriptValueForModulesFactory);
}
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
index 91b621dd7be..05f72e22e5f 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -25,6 +25,9 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_delegate.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h"
+#include "third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h"
+#include "third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h"
+#include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h"
@@ -82,6 +85,10 @@ ScriptWrappable* V8ScriptValueDeserializerForModules::ReadDOMObject(
return ReadAudioData();
case kVideoFrameTag:
return ReadVideoFrame();
+ case kEncodedAudioChunkTag:
+ return ReadEncodedAudioChunk();
+ case kEncodedVideoChunkTag:
+ return ReadEncodedVideoChunk();
default:
break;
}
@@ -467,4 +474,52 @@ VideoFrame* V8ScriptValueDeserializerForModules::ReadVideoFrame() {
return MakeGarbageCollected<VideoFrame>(handles[index]);
}
+EncodedAudioChunk*
+V8ScriptValueDeserializerForModules::ReadEncodedAudioChunk() {
+ if (!RuntimeEnabledFeatures::WebCodecsEnabled(
+ ExecutionContext::From(GetScriptState()))) {
+ return nullptr;
+ }
+
+ uint32_t index;
+ if (!ReadUint32(&index))
+ return nullptr;
+
+ const auto* attachment =
+ GetSerializedScriptValue()
+ ->GetAttachmentIfExists<DecoderBufferAttachment>();
+ if (!attachment)
+ return nullptr;
+
+ const auto& buffers = attachment->Buffers();
+ if (index >= attachment->size())
+ return nullptr;
+
+ return MakeGarbageCollected<EncodedAudioChunk>(buffers[index]);
+}
+
+EncodedVideoChunk*
+V8ScriptValueDeserializerForModules::ReadEncodedVideoChunk() {
+ if (!RuntimeEnabledFeatures::WebCodecsEnabled(
+ ExecutionContext::From(GetScriptState()))) {
+ return nullptr;
+ }
+
+ uint32_t index;
+ if (!ReadUint32(&index))
+ return nullptr;
+
+ const auto* attachment =
+ GetSerializedScriptValue()
+ ->GetAttachmentIfExists<DecoderBufferAttachment>();
+ if (!attachment)
+ return nullptr;
+
+ const auto& buffers = attachment->Buffers();
+ if (index >= attachment->size())
+ return nullptr;
+
+ return MakeGarbageCollected<EncodedVideoChunk>(buffers[index]);
+}
+
} // namespace blink
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 bcab84578ea..2e2e0776e4a 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
@@ -12,6 +12,8 @@ namespace blink {
class AudioData;
class CryptoKey;
+class EncodedAudioChunk;
+class EncodedVideoChunk;
class FileSystemHandle;
class RTCEncodedAudioFrame;
class RTCEncodedVideoFrame;
@@ -52,6 +54,8 @@ class MODULES_EXPORT V8ScriptValueDeserializerForModules final
RTCEncodedVideoFrame* ReadRTCEncodedVideoFrame();
AudioData* ReadAudioData();
VideoFrame* ReadVideoFrame();
+ EncodedAudioChunk* ReadEncodedAudioChunk();
+ EncodedVideoChunk* ReadEncodedVideoChunk();
};
} // namespace blink
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 5eb90a3f9f9..fc61325d21d 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
@@ -14,6 +14,8 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_file_handle.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_landmark.h"
@@ -28,6 +30,9 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_delegate.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h"
+#include "third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h"
+#include "third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h"
+#include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_transfer_list.h"
@@ -175,6 +180,25 @@ bool V8ScriptValueSerializerForModules::WriteDOMObject(
}
return WriteMediaAudioBuffer(std::move(data));
}
+ if ((wrapper_type_info == V8EncodedAudioChunk::GetWrapperTypeInfo() ||
+ wrapper_type_info == V8EncodedVideoChunk::GetWrapperTypeInfo()) &&
+ RuntimeEnabledFeatures::WebCodecsEnabled(
+ ExecutionContext::From(GetScriptState()))) {
+ if (IsForStorage()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kDataCloneError,
+ "Encoded chunks cannot be serialized for storage.");
+ return false;
+ }
+
+ if (wrapper_type_info == V8EncodedAudioChunk::GetWrapperTypeInfo()) {
+ auto data = wrappable->ToImpl<EncodedAudioChunk>()->buffer();
+ return WriteDecoderBuffer(std::move(data), /*for_audio=*/true);
+ }
+
+ auto data = wrappable->ToImpl<EncodedVideoChunk>()->buffer();
+ return WriteDecoderBuffer(std::move(data), /*for_audio=*/false);
+ }
return false;
}
@@ -429,4 +453,19 @@ bool V8ScriptValueSerializerForModules::WriteMediaAudioBuffer(
return true;
}
+bool V8ScriptValueSerializerForModules::WriteDecoderBuffer(
+ scoped_refptr<media::DecoderBuffer> data,
+ bool for_audio) {
+ auto* attachment = GetSerializedScriptValue()
+ ->GetOrCreateAttachment<DecoderBufferAttachment>();
+ auto& buffers = attachment->Buffers();
+ buffers.push_back(std::move(data));
+ const uint32_t index = static_cast<uint32_t>(buffers.size() - 1);
+
+ WriteTag(for_audio ? kEncodedAudioChunkTag : kEncodedVideoChunkTag);
+ WriteUint32(index);
+
+ return true;
+}
+
} // namespace blink
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 a31e39f8972..b0566a33d6b 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
@@ -12,6 +12,7 @@
namespace media {
class AudioBuffer;
+class DecoderBuffer;
}
namespace blink {
@@ -50,6 +51,8 @@ class MODULES_EXPORT V8ScriptValueSerializerForModules final
bool WriteRTCEncodedVideoFrame(RTCEncodedVideoFrame*);
bool WriteVideoFrameHandle(scoped_refptr<VideoFrameHandle>);
bool WriteMediaAudioBuffer(scoped_refptr<media::AudioBuffer>);
+ bool WriteDecoderBuffer(scoped_refptr<media::DecoderBuffer> data,
+ bool for_audio);
};
} // namespace blink
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 d0692e169a5..f3b9ef4c042 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,15 +11,18 @@
#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_crypto_algorithm_params.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_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"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_copy_to_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h"
@@ -29,6 +32,7 @@
#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/modules/peerconnection/rtc_certificate_generator.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_transfer_list.h"
@@ -265,8 +269,9 @@ WebVector<unsigned char> ConvertCryptoResult<WebVector<unsigned char>>(
v8::Isolate* isolate,
const ScriptValue& value) {
WebVector<unsigned char> vector;
- if (DOMArrayBuffer* buffer =
- V8ArrayBuffer::ToImplWithTypeCheck(isolate, value.V8Value())) {
+ DummyExceptionStateForTesting exception_state;
+ if (DOMArrayBuffer* buffer = NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ isolate, value.V8Value(), exception_state)) {
vector.Assign(reinterpret_cast<const unsigned char*>(buffer->Data()),
buffer->ByteLength());
}
@@ -1086,13 +1091,13 @@ TEST(V8ScriptValueSerializerForModulesTest, RoundTripAudioData) {
auto audio_bus = media::AudioBus::Create(kChannels, kFrames);
- // Populate each frame with a unique value.
- const unsigned kTotalFrames = (kFrames * kChannels);
- const float kFramesMultiplier = 1.0 / kTotalFrames;
+ // Populate each sample with a unique value.
+ const unsigned kTotalSamples = (kFrames * kChannels);
+ const float kSampleMultiplier = 1.0 / kTotalSamples;
for (unsigned ch = 0; ch < kChannels; ++ch) {
float* data = audio_bus->channel(ch);
for (unsigned i = 0; i < kFrames; ++i)
- data[i] = (i + ch * kFrames) * kFramesMultiplier;
+ data[i] = (i + ch * kFrames) * kSampleMultiplier;
}
// Copying the data from an AudioBus instead of creating a media::AudioBuffer
@@ -1108,29 +1113,39 @@ TEST(V8ScriptValueSerializerForModulesTest, RoundTripAudioData) {
v8::Local<v8::Value> result = RoundTripForModules(wrapper, scope);
// The data should have been copied, not transferred.
- EXPECT_TRUE(audio_data->buffer());
+ EXPECT_TRUE(audio_data->data());
ASSERT_TRUE(V8AudioData::HasInstance(result, scope.GetIsolate()));
AudioData* new_data = V8AudioData::ToImpl(result.As<v8::Object>());
EXPECT_EQ(base::TimeDelta::FromMicroseconds(new_data->timestamp()),
kTimestamp);
- EXPECT_EQ(new_data->buffer()->numberOfChannels(), kChannels);
- EXPECT_EQ(new_data->buffer()->sampleRate(), kSampleRate);
- EXPECT_EQ(new_data->buffer()->length(), kFrames);
-
- // Make sure the data wasn't changed during the transfer.
- for (unsigned ch = 0; ch < kChannels; ++ch) {
- float* src_data = audio_data->buffer()->getChannelData(ch)->Data();
- float* dst_data = new_data->buffer()->getChannelData(ch)->Data();
- for (unsigned i = 0; i < kFrames; ++i) {
- EXPECT_EQ(src_data[i], dst_data[i]);
- }
+ EXPECT_EQ(new_data->numberOfChannels(), kChannels);
+ EXPECT_EQ(new_data->numberOfFrames(), kFrames);
+ EXPECT_EQ(new_data->sampleRate(), kSampleRate);
+
+ // Copy out the frames to make sure they haven't been changed during the
+ // transfer.
+ DOMArrayBuffer* copy_dest = DOMArrayBuffer::Create(kFrames, sizeof(float));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(copy_dest);
+ AudioDataCopyToOptions* options =
+ MakeGarbageCollected<AudioDataCopyToOptions>();
+
+ for (unsigned int ch = 0; ch < kChannels; ++ch) {
+ options->setPlaneIndex(ch);
+ new_data->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ float* new_samples = static_cast<float*>(copy_dest->Data());
+
+ for (unsigned int i = 0; i < kFrames; ++i)
+ ASSERT_EQ(new_samples[i], (i + ch * kFrames) * kSampleMultiplier);
}
// Closing the original |audio_data| should not affect |new_data|.
audio_data->close();
- EXPECT_TRUE(new_data->buffer());
+ EXPECT_TRUE(new_data->data());
}
TEST(V8ScriptValueSerializerForModulesTest, ClosedAudioDataThrows) {
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/v8.gni b/chromium/third_party/blink/renderer/bindings/modules/v8/v8.gni
deleted file mode 100644
index fc1351072c5..00000000000
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/v8.gni
+++ /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.
-
-import("//third_party/blink/renderer/config.gni")
-import("custom/custom.gni")
-
-# Make the files absolute so they can be imported to anywhere.
-bindings_modules_v8_files =
- get_path_info(
- [
- "module_bindings_initializer.cc",
- "module_bindings_initializer.h",
- "serialization/serialized_script_value_for_modules_factory.cc",
- "serialization/serialized_script_value_for_modules_factory.h",
- "serialization/v8_script_value_deserializer_for_modules.cc",
- "serialization/v8_script_value_deserializer_for_modules.h",
- "serialization/v8_script_value_serializer_for_modules.cc",
- "serialization/v8_script_value_serializer_for_modules.h",
- "to_v8_for_modules.h",
- "v8_binding_for_modules.cc",
- "v8_binding_for_modules.h",
- "v8_context_snapshot_external_references.h",
- "webgl_any.cc",
- "webgl_any.h",
- ],
- "abspath") + bindings_modules_v8_custom_files
-if (use_blink_v8_binding_new_idl_interface) {
- bindings_modules_v8_files += get_path_info([
- "v8_context_snapshot_impl.cc",
- "v8_context_snapshot_impl.h",
- ],
- "abspath")
-}
-
-bindings_modules_v8_unittest_files =
- get_path_info(
- [
- "serialization/v8_script_value_serializer_for_modules_test.cc",
- "v8_binding_for_modules_test.cc",
- ],
- "abspath")
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
index ab4e9b10afe..6ee74b880b2 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
@@ -27,15 +27,13 @@
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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/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"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_string_list.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_file.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_cursor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_cursor_with_value.h"
@@ -189,7 +187,10 @@ static std::unique_ptr<IDBKey> CreateIDBKeyFromSimpleValue(
return IDBKey::CreateDate(value.As<v8::Date>()->ValueOf());
if (value->IsArrayBuffer()) {
- DOMArrayBuffer* buffer = V8ArrayBuffer::ToImpl(value.As<v8::Object>());
+ DOMArrayBuffer* buffer = NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ isolate, value, exception_state);
+ if (exception_state.HadException())
+ return IDBKey::CreateInvalid();
if (buffer->IsDetached()) {
exception_state.ThrowTypeError("The ArrayBuffer is detached.");
return IDBKey::CreateInvalid();
@@ -201,7 +202,11 @@ static std::unique_ptr<IDBKey> CreateIDBKeyFromSimpleValue(
if (value->IsArrayBufferView()) {
DOMArrayBufferView* view =
- V8ArrayBufferView::ToImpl(value.As<v8::Object>());
+ NativeValueTraits<MaybeShared<DOMArrayBufferView>>::NativeValue(
+ isolate, value, exception_state)
+ .Get();
+ if (exception_state.HadException())
+ return IDBKey::CreateInvalid();
if (view->buffer()->IsDetached()) {
exception_state.ThrowTypeError("The viewed ArrayBuffer is detached.");
return IDBKey::CreateInvalid();
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.h b/chromium/third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.h
deleted file mode 100644
index ebdc5303673..00000000000
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.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_BINDINGS_MODULES_V8_V8_CONTEXT_SNAPSHOT_EXTERNAL_REFERENCES_H_
-#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_MODULES_V8_V8_CONTEXT_SNAPSHOT_EXTERNAL_REFERENCES_H_
-
-#include <cstdint>
-
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-// V8ContextSnapshotExternalReferences::GetTable() provides a table of pointers
-// of C++ callbacks exposed to V8. The table contains C++ callbacks for DOM
-// attribute getters, setters, DOM methods, wrapper type info etc.
-class MODULES_EXPORT V8ContextSnapshotExternalReferences {
- STATIC_ONLY(V8ContextSnapshotExternalReferences);
-
- public:
- // The definition of this method is auto-generated in
- // v8_context_snapshot_external_references.cc.
- static const intptr_t* GetTable();
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_MODULES_V8_V8_CONTEXT_SNAPSHOT_EXTERNAL_REFERENCES_H_
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn b/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn
deleted file mode 100644
index ced07798d66..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn
+++ /dev/null
@@ -1,43 +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.
-
-import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
-import("//third_party/blink/renderer/bindings/templates/templates.gni")
-
-visibility = [ "//third_party/blink/*" ]
-
-# This separate pre-caching step is required to use lex/parse table
-# caching in PLY, since PLY itself does not check if the cache is
-# valid, and thus may end up using a stale cache if this step hasn't
-# been run to update it.
-#
-# This action's dependencies *is* the cache validation.
-action("cached_lex_yacc_tables") {
- script = "blink_idl_parser.py"
-
- inputs = idl_lexer_parser_files
- outputs = [ "$bindings_scripts_output_dir/parsetab.pickle" ]
-
- args = [ rebase_path(bindings_scripts_output_dir, root_build_dir) ]
-}
-
-# A separate pre-caching step is *required* to use bytecode caching in
-# Jinja (which improves speed significantly), as the bytecode cache is
-# not concurrency-safe on write; details in code_generator_v8.py.
-action("cached_jinja_templates") {
- script = "code_generator.py"
-
- inputs = jinja_module_files + [ "code_generator.py" ] +
- code_generator_template_files
-
- # Dummy file to track dependency.
- stamp_file = "$bindings_scripts_output_dir/cached_jinja_templates.stamp"
- outputs = [ stamp_file ]
-
- args = [
- rebase_path(bindings_scripts_output_dir, root_build_dir),
- rebase_path(stamp_file, root_build_dir),
- ]
-}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py b/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
deleted file mode 100755
index c1d66c071f7..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Generates a .cpp file that includes all V8 binding .cpp files for interfaces.
-
-It is expected to preserve symbol space, and to be acceptable to make static
-build on Windows.
-
-Usage:
- $ aggregate_generated_bindings.py --component COMPONENT IDL_FILES_LIST OUTPUT_FILE
-
- COMPONENT is the relative directory of a component, e.g., 'core', 'modules'.
- IDL_FILES_LIST is a text file containing the IDL file paths
- OUTPUT_FILE is the filename of output file.
-
- Design doc: http://www.chromium.org/developers/design-documents/idl-build
-"""
-
-from __future__ import print_function
-
-import errno
-import optparse
-import os
-import re
-import sys
-from utilities import idl_filename_to_basename
-from utilities import read_idl_files_list_from_file
-from utilities import to_snake_case
-
-COPYRIGHT_TEMPLATE = """/*
- * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
- *
- * This file was generated by the aggregate_generated_bindings.py script.
- *
- * 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:
- * 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.
- */
-"""
-
-
-def parse_options():
- parser = optparse.OptionParser()
- parser.add_option('--component')
-
- options, args = parser.parse_args()
- if len(args) < 2:
- raise Exception(
- 'Expected 2 filenames; one is for input, and the other is for output.'
- )
-
- return options, args
-
-
-def generate_content(component, basenames):
- # Add fixed content.
- output = [COPYRIGHT_TEMPLATE, '#define NO_IMPLICIT_ATOMICSTRING\n\n']
-
- basenames.sort()
- output.extend(
- '#include "third_party/blink/renderer/bindings/%s/v8/v8_%s.cc"\n' %
- (component, to_snake_case(basename)) for basename in basenames)
- return ''.join(output)
-
-
-def write_content(content, output_file_name):
- parent_path, file_name = os.path.split(output_file_name)
- if not os.path.exists(parent_path):
- print('Creating directory: %s' % parent_path)
- os.makedirs(parent_path)
- with open(output_file_name, 'w') as f:
- f.write(content)
-
-
-def main():
- options, filenames = parse_options()
- component = options.component
- idl_filenames = read_idl_files_list_from_file(filenames[0])
- basenames = [
- idl_filename_to_basename(file_path) for file_path in idl_filenames
- ]
- file_contents = generate_content(component, basenames)
- write_content(file_contents, filenames[1])
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/README.md b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/README.md
new file mode 100644
index 00000000000..e6bd4db3624
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/README.md
@@ -0,0 +1,166 @@
+# Blink-V8 bindings generator (bind_gen package)
+
+[TOC]
+
+## What's bind_gen?
+
+Python package
+[`bind_gen`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/bind_gen/)
+is the core part of Blink-V8 bindings code generator.
+[`generate_bindings.py`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/generate_bindings.py)
+is the driver script, which takes a Web IDL database (`web_idl_database.pickle`
+generated by "web_idl_database" GN target) as an input and produces a set of
+C++ source files of Blink-V8 bindings (v8_\*.h, v8_\*.cc).
+
+## Design and code structure
+
+The bindings code generator is implemented as a tree builder of `CodeNode`
+which is a fundamental building block. The following sub sections describe
+what `CodeNode` is and how the code generator builds a tree of `CodeNode`.
+
+### CodeNode
+
+The code generator produces C++ source files (text files) but the content of
+each file is not represented as a single giant string nor a list of strings.
+The content of each file is represented as a CodeNode tree.
+
+`CodeNode` (defined in
+[code_node.py](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py))
+is a fundamental building block that represents a text fragment in the tree
+structure. A text file is represented as a tree of CodeNodes, each of which
+represents a corresponding text fragment. The code generator is the CodeNode
+tree builder.
+
+Here is a simple example to build a CodeNode tree.
+```python
+# SequenceNode and TextNode are subclasses of CodeNode.
+
+def prologue():
+ return SequenceNode([
+ TextNode("// Prologue"),
+ TextNode("SetUp();"),
+ ])
+
+def epilogue():
+ return SequenceNode([
+ TextNode("// Epilogue"),
+ TextNode("CleanUp();"),
+ ])
+
+def main():
+ root_node = SequenceNode([
+ prologue(),
+ TextNode("LOG(INFO) << \"hello, world\";"),
+ epilogue(),
+ ])
+```
+The `root_node` above represents the following text.
+
+```c++
+// Prologue
+SetUp();
+LOG(INFO) << "hello, world";
+// Epilogue
+CleanUp();
+```
+
+The basic features of CodeNode are implemented in
+[code_node.py](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py).
+Just for convenience, CodeNode subclasses corresponding to C++ constructs are
+provided in
+[code_node_cxx.py](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py).
+
+`CodeNode` has an object-oriented design and has internal states (not only the
+parent / child nodes but also more states to support advanced features).
+
+### CodeNode tree builders
+
+The bindings code generator consists of multiple sub code generators. For
+example, `interface.py` is a sub code generator of Web IDL interface and
+`enumeration.py` is a sub code generator of Web IDL enumeration. Each Web IDL
+definition has its own sub code generator.
+
+This sub section describes how a sub code generator builds a CodeNode tree and
+produces C++ source files by looking at
+[`enumeration.py`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py)
+as an example. The example code snippet below is simplified for explanation.
+
+```python
+def generate_enumerations(task_queue):
+ for enumeration in web_idl_database.enumerations:
+ task_queue.post_task(generate_enumeration, enumeration.identifier)
+```
+
+`generate_enumerations` is the entry point to this sub code generator. In
+favor of parallel processing, `task_queue` is used. `generate_enumeration`
+(singular form) actually produces a pair of C++ source files (\*.h and \*.cc).
+
+```python
+def generate_enumeration(enumeration_identifier):
+ # Filepaths
+ header_path = path_manager.api_path(ext="h")
+ source_path = path_manager.api_path(ext="cc")
+
+ # Root nodes
+ header_node = ListNode(tail="\n")
+ source_node = ListNode(tail="\n")
+
+ # ... fill the contents of `header_node` and `source_node` ...
+
+ # Write down to the files.
+ write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
+ write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))
+```
+
+The main task of `generate_enumeration` is to build the CodeNode trees and
+write them down to files. A key point here is to build two trees in parallel;
+one for \*.h and the other for \*.cc. We can add a function declaration to the
+header file while adding the corresponding function definition to the source
+file. The following code snippet is an example to add constructors into the
+header file and the source file.
+
+```python
+ # Namespaces
+ header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ # {header,source}_blink_ns are added to {header,source}_node (the root
+ # nodes) respectively.
+
+ # Class definition
+ class_def = CxxClassDefNode(cg_context.class_name,
+ base_class_names=["bindings::EnumerationBase"],
+ final=True,
+ export=component_export(
+ api_component, for_testing))
+
+ ctor_decls, ctor_defs = make_constructors(cg_context)
+
+ # Define the class in 'blink' namespace.
+ header_blink_ns.body.append(class_def)
+
+ # Add constructors to public: section of the class.
+ class_def.public_section.append(ctor_decls)
+ # Add constructors (function definitions) into 'blink' namespace in the
+ # source file.
+ source_blink_ns.body.append(ctor_defs)
+```
+
+In the above code snippet, `make_constructors` creates and returns a CodeNode
+tree for the header file and another CodeNode tree for the source file. For
+most cases, functions named `make_xxx` creates and returns a pair of the
+CodeNode trees. These functions are subtree builders of the CodeNode trees.
+They are implemented in a way of functional programming (unlike CodeNodes
+themselves are implemented in a way of object-oriented programming). These
+subtree builders create a pair of new CodeNode trees at every function call
+(returned code node instances are different per call, so their internal states
+are separate), but the contents are 100% determined by the input arguments.
+This property is very important when we use closures in advanced use cases.
+
+So far, the typical code structure of the sub code generators is covered.
+`enumeration.py` consists of several `make_xxx` functions (subtree builders) +
+`generate_enumeration` (the top-level tree builder + file writer).
+
+### Advanced: Auto-completion and declarative style
+
+TODO(yukishiino): Write about `SymbolNode`, `SymbolDefinitionNode`,
+`SequenceNode`, and `SymbolScopeNode`.
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
index c042a3e1c5d..9da2111cde0 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
@@ -44,7 +44,8 @@ from .typedef import generate_typedefs
from .union import generate_unions
-def init(web_idl_database_path, root_src_dir, root_gen_dir, component_reldirs):
+def init(web_idl_database_path, root_src_dir, root_gen_dir, component_reldirs,
+ enable_style_format):
"""
Args:
web_idl_database_path: File path to the web_idl.Database.
@@ -52,10 +53,12 @@ def init(web_idl_database_path, root_src_dir, root_gen_dir, component_reldirs):
root_gen_dir: Root directory of generated files, which corresponds to
"//out/Default/gen" in GN.
component_reldirs: Pairs of component and output directory.
+ enable_style_format: Enable style formatting of the generated files.
"""
from . import package_initializer
package_initializer.init(web_idl_database_path=web_idl_database_path,
root_src_dir=root_src_dir,
root_gen_dir=root_gen_dir,
- component_reldirs=component_reldirs)
+ component_reldirs=component_reldirs,
+ enable_style_format=enable_style_format)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
index 5856d41ab8e..68778e02248 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
@@ -5,6 +5,7 @@
import web_idl
from . import name_style
+from .code_node import FormatNode
from .code_node import Likeliness
from .code_node import SymbolDefinitionNode
from .code_node import SymbolNode
@@ -31,7 +32,7 @@ def blink_class_name(idl_definition):
(web_idl.CallbackFunction, web_idl.CallbackInterface,
web_idl.Enumeration, web_idl.Typedef)):
return "V8{}".format(idl_definition.identifier)
- elif isinstance(idl_definition, web_idl.NewUnion):
+ elif isinstance(idl_definition, web_idl.Union):
# Technically this name is not guaranteed to be unique because
# (X or sequence<Y or Z>) and (X or Y or sequence<Z>) have the same
# name, but it's highly unlikely to cause a conflict in the actual use
@@ -56,7 +57,7 @@ def v8_bridge_class_name(idl_definition):
return "V8{}".format(idl_definition.identifier)
-def blink_type_info(idl_type, use_new_union=True):
+def blink_type_info(idl_type):
"""
Returns an object that represents the types of Blink implementation
corresponding to the given IDL type, such as reference type, value type,
@@ -73,12 +74,17 @@ def blink_type_info(idl_type, use_new_union=True):
value_fmt="{}",
has_null_value=False,
is_gc_type=False,
+ is_heap_vector_type=False,
is_move_effective=False,
+ is_traceable=False,
clear_member_var_fmt="{}.Clear()"):
self._typename = typename
self._has_null_value = has_null_value
self._is_gc_type = is_gc_type
+ self._is_heap_vector_type = is_heap_vector_type
self._is_move_effective = is_move_effective
+ self._is_traceable = (is_gc_type or is_heap_vector_type
+ or is_traceable)
self._clear_member_var_fmt = clear_member_var_fmt
self._ref_t = ref_fmt.format(typename)
@@ -150,6 +156,18 @@ def blink_type_info(idl_type, use_new_union=True):
return self._is_gc_type
@property
+ def is_heap_vector_type(self):
+ """
+ Returns True if the Blink implementation type is HeapVector<T>.
+
+ HeapVector is very special because HeapVector is GarbageCollected
+ but it's used as a value type rather than a reference type for the
+ most cases because HeapVector had been implemented as a non-GC type
+ for a long time and it turned into a GC type in 2021 January.
+ """
+ return self._is_heap_vector_type
+
+ @property
def is_move_effective(self):
"""
Returns True if support of std::move is effective and desired.
@@ -157,6 +175,14 @@ def blink_type_info(idl_type, use_new_union=True):
"""
return self._is_move_effective
+ @property
+ def is_traceable(self):
+ """
+ Returns True if the Blink implementation type has Trace method.
+ E.g. ScriptValue => True and int32_t => False
+ """
+ return self._is_traceable
+
def clear_member_var_expr(self, var_name):
"""
Returns an expression to reset the given member variable. E.g.
@@ -164,15 +190,6 @@ def blink_type_info(idl_type, use_new_union=True):
"""
return self._clear_member_var_fmt.format(var_name)
- def vector_element_type(idl_type):
- # Use |Member<T>| explicitly so that the complete type definition of
- # |T| will not be required.
- type_info = blink_type_info(idl_type)
- if type_info.is_gc_type:
- return type_info.member_t
- else:
- return type_info.typename
-
real_type = idl_type.unwrap(typedef=True)
if real_type.is_boolean or real_type.is_numeric:
@@ -204,7 +221,9 @@ def blink_type_info(idl_type, use_new_union=True):
if real_type.is_array_buffer:
if "AllowShared" in idl_type.effective_annotations:
- typename = "DOMSharedArrayBuffer"
+ # DOMArrayBufferBase is the common base class of DOMArrayBuffer and
+ # DOMSharedArrayBuffer, so it works as [AllowShared] ArrayBuffer.
+ typename = "DOMArrayBufferBase"
else:
typename = "DOMArrayBuffer"
return TypeInfo(typename,
@@ -240,11 +259,11 @@ def blink_type_info(idl_type, use_new_union=True):
assert False, "Blink does not support/accept IDL symbol type."
if real_type.is_any or real_type.is_object:
- return TypeInfo(
- "ScriptValue",
- ref_fmt="{}&",
- const_ref_fmt="const {}&",
- has_null_value=True)
+ return TypeInfo("ScriptValue",
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ has_null_value=True,
+ is_traceable=True)
if real_type.is_void:
assert False, "Blink does not support/accept IDL void type."
@@ -252,7 +271,10 @@ def blink_type_info(idl_type, use_new_union=True):
if real_type.type_definition_object:
typename = blink_class_name(real_type.type_definition_object)
if real_type.is_enumeration:
- return TypeInfo(typename, clear_member_var_fmt="")
+ return TypeInfo(typename,
+ ref_fmt="{}",
+ const_ref_fmt="{}",
+ clear_member_var_fmt="")
return TypeInfo(typename,
member_fmt="Member<{}>",
ref_fmt="{}*",
@@ -263,30 +285,66 @@ def blink_type_info(idl_type, use_new_union=True):
if (real_type.is_sequence or real_type.is_frozen_array
or real_type.is_variadic):
- typename = "VectorOf<{}>".format(
- vector_element_type(real_type.element_type))
- return TypeInfo(typename,
- ref_fmt="{}&",
- const_ref_fmt="const {}&",
- is_move_effective=True,
- clear_member_var_fmt="{}.clear()")
+ element_type = blink_type_info(real_type.element_type)
+ if element_type.is_traceable:
+ # HeapVector is GarbageCollected but we'd like to treat it as
+ # a value type (is_gc_type=False, has_null_value=False) rather than
+ # a reference type (is_gc_type=True, has_null_value=True) by
+ # default.
+ typename = "HeapVector<AddMemberIfNeeded<{}>>".format(
+ element_type.member_t)
+ return TypeInfo(typename,
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ has_null_value=False,
+ is_gc_type=False,
+ is_move_effective=True,
+ is_heap_vector_type=True,
+ clear_member_var_fmt="{}.clear()")
+ else:
+ return TypeInfo("Vector<{}>".format(element_type.value_t),
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ is_move_effective=True,
+ clear_member_var_fmt="{}.clear()")
if real_type.is_record:
- typename = "VectorOfPairs<{}, {}>".format(
- vector_element_type(real_type.key_type),
- vector_element_type(real_type.value_type))
- return TypeInfo(typename,
- ref_fmt="{}&",
- const_ref_fmt="const {}&",
- is_move_effective=True,
- clear_member_var_fmt="{}.clear()")
+ assert real_type.key_type.is_string
+ key_type = blink_type_info(real_type.key_type)
+ value_type = blink_type_info(real_type.value_type)
+ if value_type.is_traceable:
+ # HeapVector is GarbageCollected but we'd like to treat it as
+ # a value type (is_gc_type=False, has_null_value=False) rather than
+ # a reference type (is_gc_type=True, has_null_value=True) by
+ # default.
+ typename = (
+ "HeapVector<std::pair<{}, AddMemberIfNeeded<{}>>>".format(
+ key_type.value_t, value_type.member_t))
+ return TypeInfo(typename,
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ has_null_value=False,
+ is_gc_type=False,
+ is_move_effective=True,
+ is_heap_vector_type=True,
+ clear_member_var_fmt="{}.clear()")
+ else:
+ typename = "Vector<std::pair<{}, {}>>".format(
+ key_type.value_t, value_type.value_t)
+ return TypeInfo(typename,
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ is_move_effective=True,
+ clear_member_var_fmt="{}.clear()")
if real_type.is_promise:
- return TypeInfo(
- "ScriptPromise", ref_fmt="{}&", const_ref_fmt="const {}&")
+ return TypeInfo("ScriptPromise",
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ is_traceable=True)
- if real_type.is_union and use_new_union:
- typename = blink_class_name(real_type.new_union_definition_object)
+ if real_type.is_union:
+ typename = blink_class_name(real_type.union_definition_object)
return TypeInfo(typename,
member_fmt="Member<{}>",
ref_fmt="{}*",
@@ -295,17 +353,21 @@ def blink_type_info(idl_type, use_new_union=True):
has_null_value=True,
is_gc_type=True)
- if real_type.is_union:
- typename = blink_class_name(real_type.union_definition_object)
- return TypeInfo(typename,
- ref_fmt="{}&",
- const_ref_fmt="const {}&",
- has_null_value=True)
-
if real_type.is_nullable:
inner_type = blink_type_info(real_type.inner_type)
if inner_type.has_null_value:
return inner_type
+ if inner_type.is_heap_vector_type:
+ return TypeInfo(inner_type.typename,
+ member_fmt="Member<{}>",
+ ref_fmt="{}*",
+ const_ref_fmt="const {}*",
+ value_fmt="{}*",
+ has_null_value=True,
+ is_gc_type=True,
+ is_move_effective=False,
+ is_heap_vector_type=False)
+ assert not inner_type.is_traceable
return TypeInfo("absl::optional<{}>".format(inner_type.value_t),
ref_fmt="{}&",
const_ref_fmt="const {}&",
@@ -341,15 +403,11 @@ def _native_value_tag_impl(idl_type):
real_type = idl_type.unwrap(typedef=True)
- if (real_type.is_boolean or real_type.is_numeric or real_type.is_any
- or real_type.is_object):
+ if (real_type.is_boolean or real_type.is_numeric or real_type.is_string
+ or real_type.is_any or real_type.is_object):
return "IDL{}".format(
idl_type.type_name_with_extended_attribute_key_values)
- if real_type.is_string:
- return "IDL{}V2".format(
- idl_type.type_name_with_extended_attribute_key_values)
-
if real_type.is_array_buffer:
return blink_type_info(real_type).typename
@@ -409,7 +467,7 @@ def make_blink_to_v8_value(
assert isinstance(creation_context_script_state, str)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
def create_definition(symbol_node):
binds = {
@@ -431,7 +489,7 @@ def make_blink_to_v8_value(
return SymbolNode(v8_var_name, definition_constructor=create_definition)
-def make_default_value_expr(idl_type, default_value, use_new_union=True):
+def make_default_value_expr(idl_type, default_value):
"""
Returns a set of C++ expressions to be used for initialization with default
values. The returned object has the following attributes.
@@ -490,7 +548,7 @@ def make_default_value_expr(idl_type, default_value, use_new_union=True):
self.assignment_value = assignment_value
self.assignment_deps = tuple(assignment_deps)
- if idl_type.unwrap(typedef=True).is_union and use_new_union:
+ if idl_type.unwrap(typedef=True).is_union:
union_type = idl_type.unwrap(typedef=True)
member_type = None
for member_type in union_type.flattened_member_types:
@@ -500,8 +558,7 @@ def make_default_value_expr(idl_type, default_value, use_new_union=True):
assert not (member_type is None) or default_value.idl_type.is_nullable
pattern = "MakeGarbageCollected<{}>({})"
- union_class_name = blink_class_name(
- union_type.new_union_definition_object)
+ union_class_name = blink_class_name(union_type.union_definition_object)
if default_value.idl_type.is_nullable:
value = pattern.format(union_class_name, "nullptr")
@@ -522,39 +579,6 @@ def make_default_value_expr(idl_type, default_value, use_new_union=True):
assignment_value=value,
assignment_deps=member_default_expr.assignment_deps)
- if idl_type.unwrap(typedef=True).is_union:
- union_type = idl_type.unwrap(typedef=True)
- member_type = None
- for member_type in union_type.flattened_member_types:
- if default_value.is_type_compatible_with(member_type):
- member_type = member_type
- break
- assert member_type is not None
-
- union_class_name = blink_class_name(union_type.union_definition_object)
- member_default_expr = make_default_value_expr(member_type,
- default_value)
- if default_value.idl_type.is_nullable:
- initializer_expr = None
- assignment_value = _format("{}()", union_class_name)
- else:
- func_name = name_style.func("From", member_type.type_name)
- argument = member_default_expr.assignment_value
- # TODO(peria): Remove this workaround when we support V8Enum types
- # in Union.
- if (member_type.is_sequence
- and member_type.element_type.unwrap().is_enumeration):
- argument = "{}"
- initializer_expr = _format("{}::{}({})", union_class_name,
- func_name, argument)
- assignment_value = initializer_expr
- return DefaultValueExpr(
- initializer_expr=initializer_expr,
- initializer_deps=member_default_expr.initializer_deps,
- is_initialization_lightweight=False,
- assignment_value=assignment_value,
- assignment_deps=member_default_expr.assignment_deps)
-
type_info = blink_type_info(idl_type)
is_initialization_lightweight = False
@@ -580,25 +604,32 @@ def make_default_value_expr(idl_type, default_value, use_new_union=True):
initializer_deps = ["isolate"]
assignment_value = "ScriptValue::CreateNull(${isolate})"
assignment_deps = ["isolate"]
- elif idl_type.unwrap().is_union and use_new_union:
+ elif idl_type.unwrap().is_union:
initializer_expr = "nullptr"
is_initialization_lightweight = True
assignment_value = "nullptr"
- elif idl_type.unwrap().is_union:
- initializer_expr = None # <union_type>::IsNull() by default
- assignment_value = "{}()".format(type_info.value_t)
else:
assert False
elif default_value.idl_type.is_sequence:
initializer_expr = None # VectorOf<T>::size() == 0 by default
assignment_value = "{}()".format(type_info.value_t)
elif default_value.idl_type.is_object:
- dict_name = blink_class_name(idl_type.unwrap().type_definition_object)
- value = _format("{}::Create(${isolate})", dict_name)
- initializer_expr = value
- initializer_deps = ["isolate"]
- assignment_value = value
- assignment_deps = ["isolate"]
+ dictionary = idl_type.unwrap().type_definition_object
+ # Currently "isolate" is the only possible dependency, so whenever
+ # .initializer_deps exists, it must be ["isolate"].
+ if any((make_default_value_expr(member.idl_type,
+ member.default_value).initializer_deps)
+ for member in dictionary.members if member.default_value):
+ value = _format("{}::Create(${isolate})",
+ blink_class_name(dictionary))
+ initializer_expr = value
+ initializer_deps = ["isolate"]
+ assignment_value = value
+ assignment_deps = ["isolate"]
+ else:
+ value = _format("{}::Create()", blink_class_name(dictionary))
+ initializer_expr = value
+ assignment_value = value
elif default_value.idl_type.is_boolean:
value = "true" if default_value.value else "false"
initializer_expr = value
@@ -665,7 +696,7 @@ def make_v8_to_blink_value(blink_var_name,
assert isinstance(error_exit_return_statement, str)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
# Use of fast path is a trade-off between speed and binary size, so apply
# it only when it's effective. This hack is most significant on Android.
@@ -722,7 +753,7 @@ def make_v8_to_blink_value(blink_var_name,
else:
default_expr = None
exception_exit_node = CxxUnlikelyIfNode(
- cond="${exception_state}.HadException()",
+ cond="UNLIKELY(${exception_state}.HadException())",
body=T(error_exit_return_statement))
if not (default_expr or fast_path_cond):
@@ -810,7 +841,7 @@ def make_v8_to_blink_value_variadic(blink_var_name, v8_array,
return SymbolDefinitionNode(symbol_node, [
TextNode(text),
CxxUnlikelyIfNode(
- cond="${exception_state}.HadException()",
+ cond="UNLIKELY(${exception_state}.HadException())",
body=TextNode("return;")),
])
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/callback_function.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/callback_function.py
index f15a7edcb49..f3c7b881099 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/callback_function.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/callback_function.py
@@ -10,6 +10,7 @@ from .blink_v8_bridge import blink_type_info
from .blink_v8_bridge import make_blink_to_v8_value
from .blink_v8_bridge import native_value_tag
from .code_node import EmptyNode
+from .code_node import FormatNode
from .code_node import ListNode
from .code_node import SequenceNode
from .code_node import SymbolNode
@@ -163,7 +164,7 @@ def make_callback_invocation_function(cg_context,
assert isinstance(is_construct_call, bool)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
func_like = cg_context.function_like
return_type = ("void" if func_like.return_type.unwrap().is_void else
@@ -360,7 +361,7 @@ def make_invoke_and_report_function(cg_context, function_name, api_func_name):
assert isinstance(api_func_name, str)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
func_like = cg_context.function_like
if not (func_like.return_type.unwrap().is_void
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
index 0f082f24543..de7850126e8 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
@@ -488,6 +488,14 @@ class _TextNode(CodeNode):
CodeNode.__init__(self, template_text=template_text)
+def FormatNode(format_string, *args, **argv):
+ """
+ Represents a template text node, which is produced by applying
+ codegen_format.format_template to the arguments.
+ """
+ return TextNode(format_template(format_string, *args, **argv))
+
+
class CompositeNode(CodeNode):
"""
Represents a composition of multiple code nodes. Composition will be done
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
index ba534077742..16626675e90 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
@@ -84,7 +84,14 @@ class CodeGenContext(object):
"named_property_deleter": None,
"stringifier": None,
- # Contents of union.
+ # Cache of a tuple of dictionary._DictionaryMember for the own
+ # members of the dictionary of which the Blink class is being
+ # generated. The cache is used in dictionary.py to save code
+ # generation time.
+ "dictionary_own_members": (),
+ # Cache of a tuple of union._UnionMember for the flattened member
+ # types of the union of which the Blink class is being generated.
+ # The cache is used in union.py to save code generation time.
"union_members": (),
# The names of the class being generated and its base class.
@@ -115,7 +122,6 @@ class CodeGenContext(object):
"idl_location",
"idl_location_and_name",
"idl_name",
- "is_return_by_argument",
"may_throw_exception",
"member_like",
"property_",
@@ -246,11 +252,6 @@ class CodeGenContext(object):
return "<<unknown name>>"
@property
- def is_return_by_argument(self):
- # TODO(yukishiino): Remove `is_return_by_argument`.
- return False
-
- @property
def is_return_type_promise_type(self):
if self.attribute:
return self.attribute.idl_type.unwrap().is_promise
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
index 7f16ff4dcc2..f7ef925f9c1 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
@@ -89,8 +89,8 @@ def collect_forward_decls_and_include_headers(idl_types):
elif idl_type.is_promise:
header_include_headers.add(
"third_party/blink/renderer/bindings/core/v8/script_promise.h")
- elif (idl_type.is_sequence or idl_type.is_record
- or idl_type.is_frozen_array or idl_type.is_variadic):
+ elif (idl_type.is_sequence or idl_type.is_frozen_array
+ or idl_type.is_record or idl_type.is_variadic):
header_include_headers.add(
"third_party/blink/renderer/platform/heap/heap_allocator.h")
elif idl_type.is_string:
@@ -114,13 +114,10 @@ def collect_forward_decls_and_include_headers(idl_types):
source_include_headers.add(
PathManager(type_def_obj).api_path(ext="h"))
elif idl_type.union_definition_object:
- union_def_obj = idl_type.new_union_definition_object
+ union_def_obj = idl_type.union_definition_object
header_forward_decls.add(blink_class_name(union_def_obj))
source_include_headers.add(
PathManager(union_def_obj).api_path(ext="h"))
- union_def_obj = idl_type.union_definition_object
- header_include_headers.add(
- PathManager(union_def_obj).api_path(ext="h"))
else:
assert False, "Unknown type: {}".format(idl_type.syntactic_form)
@@ -150,6 +147,8 @@ def component_export_header(component, for_testing):
return "third_party/blink/renderer/core/core_export.h"
elif component == "modules":
return "third_party/blink/renderer/modules/modules_export.h"
+ elif component == "extensions_chromeos":
+ return "third_party/blink/renderer/extensions/chromeos/extensions_chromeos_export.h"
else:
assert False
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
index f37ac4153bb..4f118b80cfb 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
@@ -11,7 +11,8 @@ from .blink_v8_bridge import make_blink_to_v8_value
from .blink_v8_bridge import make_default_value_expr
from .blink_v8_bridge import make_v8_to_blink_value
from .blink_v8_bridge import native_value_tag
-from .code_node import Likeliness
+from .code_node import EmptyNode
+from .code_node import FormatNode
from .code_node import ListNode
from .code_node import SequenceNode
from .code_node import SymbolNode
@@ -20,9 +21,9 @@ from .code_node import TextNode
from .code_node_cxx import CxxClassDefNode
from .code_node_cxx import CxxFuncDeclNode
from .code_node_cxx import CxxFuncDefNode
-from .code_node_cxx import CxxIfElseNode
from .code_node_cxx import CxxLikelyIfNode
from .code_node_cxx import CxxNamespaceNode
+from .code_node_cxx import CxxUnlikelyIfNode
from .codegen_accumulator import CodeGenAccumulator
from .codegen_context import CodeGenContext
from .codegen_expr import expr_from_exposure
@@ -41,83 +42,195 @@ from .path_manager import PathManager
from .task_queue import TaskQueue
-_DICT_MEMBER_PRESENCE_PREDICATES = {
- "ScriptValue": "!{}.IsEmpty()",
- "ScriptPromise": "!{}.IsEmpty()",
-}
-
-
-def _blink_member_name(member):
- assert isinstance(member, web_idl.DictionaryMember)
-
- class BlinkMemberName(object):
- def __init__(self, member):
- blink_name = (member.code_generator_info.property_implemented_as
- or member.identifier)
- self.get_api = name_style.api_func(blink_name)
- self.get_or_api = name_style.api_func(blink_name, "or")
- self.set_api = name_style.api_func("set", blink_name)
- self.has_api = name_style.api_func("has", blink_name)
- # C++ data member that shows the presence of the IDL member.
- self.presence_var = name_style.member_var("has", blink_name)
- # C++ data member that holds the value of the IDL member.
- self.value_var = name_style.member_var_f("member_{}", blink_name)
- # Migration Adapters
- self.get_non_null_api = name_style.api_func(blink_name, "non_null")
- self.has_non_null_api = name_style.api_func(
- "has", blink_name, "non_null")
-
- return BlinkMemberName(member)
-
-
-def _is_member_always_present(member):
- assert isinstance(member, web_idl.DictionaryMember)
- return member.is_required or member.default_value is not None
-
-
-def _does_use_presence_flag(member):
- assert isinstance(member, web_idl.DictionaryMember)
- return (not _is_member_always_present(member) and blink_type_info(
- member.idl_type).member_t not in _DICT_MEMBER_PRESENCE_PREDICATES)
-
-
-def _member_presence_expr(member):
- assert isinstance(member, web_idl.DictionaryMember)
- if _is_member_always_present(member):
- return "true"
- if _does_use_presence_flag(member):
- return _blink_member_name(member).presence_var
- blink_type = blink_type_info(member.idl_type).member_t
- assert blink_type in _DICT_MEMBER_PRESENCE_PREDICATES
- _1 = _blink_member_name(member).value_var
- return _format(_DICT_MEMBER_PRESENCE_PREDICATES[blink_type], _1)
-
-
-def bind_member_iteration_local_vars(code_node):
- local_vars = [
- SymbolNode(
- "current_context", "v8::Local<v8::Context> ${current_context} = "
- "${isolate}->GetCurrentContext();"),
- SymbolNode(
- "v8_member_names", "const auto* ${v8_member_names} = "
- "GetV8MemberNames(${isolate}).data();"),
- SymbolNode(
- "is_cross_origin_isolated",
- "const bool ${is_cross_origin_isolated} = "
- "${execution_context}->CrossOriginIsolatedCapability();"),
- SymbolNode(
- "is_direct_socket_enabled",
- "const bool ${is_direct_socket_enabled} = "
- "${execution_context}->DirectSocketCapability();"),
- SymbolNode(
- "is_in_secure_context", "const bool ${is_in_secure_context} = "
- "${execution_context}->IsSecureContext();"),
- ]
+class _DictionaryMember(object):
+ """
+ _DictionaryMember represents the properties that the code generator
+ directly needs while web_idl.DictionaryMember represents properties of IDL
+ dictionary member independent from ECMAScript binding. _DictionaryMember
+ is specific to not only ECMAScript binding but also Blink implementation
+ of IDL dictionary.
+ """
+
+ # Map from Blink member type to presence expression.
+ _MEMBER_TYPE_TO_PRESENCE_EXPR = {
+ "ScriptPromise": "!{}.IsEmpty()",
+ "ScriptValue": "!{}.IsEmpty()",
+ }
+
+ def __init__(self, dict_member):
+ assert isinstance(dict_member, web_idl.DictionaryMember)
+
+ self._identifier = dict_member.identifier
+ self._base_name = (
+ dict_member.code_generator_info.property_implemented_as
+ or dict_member.identifier)
+
+ self._api_has = name_style.api_func("has", self._base_name)
+ self._api_get = name_style.api_func(self._base_name)
+ self._api_get_or = name_style.api_func("get", self._base_name, "or")
+ self._api_set = name_style.api_func("set", self._base_name)
+ # C++ data member that shows the presence of the dictionary member.
+ self._presence_var = name_style.member_var("has", self._base_name)
+ # C++ data member that holds the value of the dictionary member.
+ self._value_var = name_style.member_var("member", self._base_name)
+
+ # Migration adapters
+ self._api_has_non_null = name_style.api_func("has", self._base_name,
+ "non_null")
+ self._api_get_non_null = name_style.api_func(self._base_name,
+ "non_null")
+
+ self._idl_type = dict_member.idl_type
+ self._type_info = blink_type_info(self._idl_type)
+ self._is_required = dict_member.is_required
+ if dict_member.default_value:
+ self._default_expr = make_default_value_expr(
+ self._idl_type, dict_member.default_value)
+ else:
+ self._default_expr = None
+
+ self._exposure = dict_member.exposure
+
+ @property
+ def identifier(self):
+ return self._identifier
+
+ @property
+ def api_has(self):
+ return self._api_has
+
+ @property
+ def api_get(self):
+ return self._api_get
+
+ @property
+ def api_get_or(self):
+ return self._api_get_or
+
+ @property
+ def api_set(self):
+ return self._api_set
+
+ @property
+ def api_has_non_null(self):
+ return self._api_has_non_null
+
+ @property
+ def api_get_non_null(self):
+ return self._api_get_non_null
+
+ @property
+ def presence_var(self):
+ return self._presence_var
+
+ @property
+ def value_var(self):
+ return self._value_var
+
+ @property
+ def idl_type(self):
+ return self._idl_type
+
+ @property
+ def type_info(self):
+ return self._type_info
+
+ @property
+ def is_required(self):
+ return self._is_required
+
+ @property
+ def presence_expr(self):
+ if self.is_always_present:
+ return "true"
+ expr = self._MEMBER_TYPE_TO_PRESENCE_EXPR.get(self.type_info.member_t)
+ if expr:
+ return expr.format(self.value_var)
+ return self.presence_var
+
+ @property
+ def does_use_presence_var(self):
+ return not (
+ self.is_always_present
+ or self.type_info.member_t in self._MEMBER_TYPE_TO_PRESENCE_EXPR)
+
+ @property
+ def is_always_present(self):
+ return bool(self.is_required or self._default_expr)
+
+ @property
+ def initializer_expr(self):
+ return (self._default_expr and self._default_expr.initializer_expr
+ or None)
+
+ @property
+ def initializer_deps(self):
+ return (self._default_expr and self._default_expr.initializer_deps
+ or None)
+
+ @property
+ def initializer_on_constructor(self):
+ # In order to avoid cyclic header inclusion of IDL dictionaries, put
+ # the initializer in *.cc if the type is a dictionary.
+ if (self.initializer_expr and (self.initializer_deps #
+ or self.idl_type.unwrap().is_dictionary
+ or self.idl_type.unwrap().is_union)):
+ return self.initializer_expr
+ return None
+
+ @property
+ def initializer_on_member_decl(self):
+ # In order to avoid cyclic header inclusion of IDL dictionaries, put
+ # the initializer in *.cc if the type is a dictionary.
+ if (self.initializer_expr
+ and not (self.initializer_deps
+ or self.idl_type.unwrap().is_dictionary
+ or self.idl_type.unwrap().is_union)):
+ return self.initializer_expr
+ idl_type = self.idl_type.unwrap(typedef=True)
+ if idl_type.is_enumeration:
+ # Since the IDL enumeration class is not default constructible,
+ # construct the IDL enumeration with 0th enum value. Note that
+ # this is necessary only for compilation, and the value must never
+ # be used due to the guard by `api_has` (`presence_expr`).
+ return "static_cast<{}::Enum>(0)".format(self.type_info.value_t)
+ return None
+
+ @property
+ def exposure(self):
+ return self._exposure
+
+
+def bind_local_vars(code_node, cg_context):
+ assert isinstance(code_node, SymbolScopeNode)
+ assert isinstance(cg_context, CodeGenContext)
- # Execution context
- node = SymbolNode(
- "execution_context", "ExecutionContext* ${execution_context} = "
- "ToExecutionContext(${current_context});")
+ S = SymbolNode
+
+ local_vars = []
+
+ local_vars.extend([
+ S("class_like_name", ("const char* const ${class_like_name} = "
+ "\"${class_like.identifier}\";")),
+ S("current_context", ("v8::Local<v8::Context> ${current_context} = "
+ "${isolate}->GetCurrentContext();")),
+ S("is_cross_origin_isolated",
+ ("const bool ${is_cross_origin_isolated} = "
+ "${execution_context}->CrossOriginIsolatedCapability();")),
+ S("is_direct_socket_enabled",
+ ("const bool ${is_direct_socket_enabled} = "
+ "${execution_context}->DirectSocketCapability();")),
+ S("is_in_secure_context",
+ ("const bool ${is_in_secure_context} = "
+ "${execution_context}->IsSecureContext();")),
+ S("v8_own_member_names", ("const auto& ${v8_own_member_names} = "
+ "GetV8OwnMemberNames(${isolate});")),
+ ])
+
+ # execution_context
+ node = S("execution_context",
+ ("ExecutionContext* ${execution_context} = "
+ "ExecutionContext::From(${current_context});"))
node.accumulate(
CodeGenAccumulator.require_include_headers([
"third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -127,583 +240,554 @@ def bind_member_iteration_local_vars(code_node):
code_node.register_code_symbols(local_vars)
-def _is_default_ctor_available(dictionary):
- for member in dictionary.members:
- if member.default_value is None:
- continue
- default_expr = make_default_value_expr(member.idl_type,
- member.default_value)
- if default_expr.initializer_deps:
- return False
- return True
+def _constructor_needs_v8_isolate(dictionary):
+ assert isinstance(dictionary, web_idl.Dictionary)
+
+ return any(
+ make_default_value_expr(member.idl_type,
+ member.default_value).initializer_deps
+ for member in dictionary.members if member.default_value)
-def make_create_dict_funcs(cg_context):
+def make_factory_methods(cg_context):
assert isinstance(cg_context, CodeGenContext)
- dictionary = cg_context.dictionary
- name = "Create"
- return_type = "${class_name}*"
+ T = TextNode
decls = ListNode()
defs = ListNode()
- if _is_default_ctor_available(dictionary):
- func_def = CxxFuncDefNode(name=name,
+ dictionary = cg_context.dictionary
+
+ if not _constructor_needs_v8_isolate(dictionary):
+ func_def = CxxFuncDefNode(name="Create",
arg_decls=[],
- return_type=return_type,
+ return_type="${class_name}*",
static=True)
decls.append(func_def)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.append(
TextNode("return MakeGarbageCollected<${class_name}>();"))
- func_def = CxxFuncDefNode(name=name,
+ func_def = CxxFuncDefNode(name="Create",
arg_decls=["v8::Isolate* isolate"],
- return_type=return_type,
+ return_type="${class_name}*",
static=True)
decls.append(func_def)
func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.add_template_vars({"isolate": "isolate"})
func_def.body.append(
- TextNode("return MakeGarbageCollected<${class_name}>(isolate);"))
-
- arg_decls = [
- "v8::Isolate* isolate",
- "v8::Local<v8::Value> v8_value",
- "ExceptionState& exception_state",
- ]
- func_decl = CxxFuncDeclNode(name=name,
- arg_decls=arg_decls,
- return_type=return_type,
+ TextNode("return MakeGarbageCollected<${class_name}>(${isolate});"))
+
+ func_decl = CxxFuncDeclNode(name="Create",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> v8_value",
+ "ExceptionState& exception_state",
+ ],
+ return_type="${class_name}*",
static=True)
decls.append(func_decl)
- func_def = CxxFuncDefNode(name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type)
+ func_def = CxxFuncDefNode(name="Create",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> v8_value",
+ "ExceptionState& exception_state",
+ ],
+ return_type="${class_name}*",
+ class_name=cg_context.class_name)
defs.append(func_def)
func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_vars({
+ "isolate": "isolate",
+ "v8_value": "v8_value",
+ "exception_state": "exception_state",
+ })
+ bind_local_vars(body, cg_context)
- func_def.body.append(
- TextNode("""\
-DCHECK(!v8_value.IsEmpty());
-
-${class_name}* dictionary = Create(isolate);
-dictionary->FillMembers(isolate, v8_value, exception_state);
-if (exception_state.HadException()) {
- return nullptr;
-}
-return dictionary;"""))
+ body.append(
+ T("${class_name}* dictionary = "
+ "MakeGarbageCollected<${class_name}>(${isolate});"))
+ if not dictionary.has_required_member:
+ body.append(
+ CxxLikelyIfNode(cond="${v8_value}->IsNullOrUndefined()",
+ body=T("return dictionary;")))
+ # [PermissiveDictionaryConversion]
+ if "PermissiveDictionaryConversion" in dictionary.extended_attributes:
+ body.append(
+ CxxUnlikelyIfNode(cond="!${v8_value}->IsObject()",
+ body=[
+ T("// [PermissiveDictionaryConversion]"),
+ T("return dictionary;"),
+ ]))
+ else:
+ body.append(
+ CxxUnlikelyIfNode(cond="!${v8_value}->IsObject()",
+ body=[
+ T("${exception_state}.ThrowTypeError("
+ "ExceptionMessages::ValueNotOfType("
+ "${class_like_name}));"),
+ T("return nullptr;"),
+ ]))
+ body.extend([
+ T("dictionary->FillMembersFromV8Object("
+ "${isolate}, ${v8_value}.As<v8::Object>(), ${exception_state});"),
+ CxxUnlikelyIfNode(cond="UNLIKELY(${exception_state}.HadException())",
+ body=T("return nullptr;")),
+ T("return dictionary;"),
+ ])
return decls, defs
-def make_dict_constructors(cg_context):
+def make_constructors(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
decls = ListNode()
defs = ListNode()
- dictionary = cg_context.dictionary
- class_name = blink_class_name(dictionary)
-
- member_initializer_list = []
- should_construct_in_source = False
- for member in dictionary.own_members:
- if member.default_value is None:
- continue
- # In order to avoid cyclic header inclusion of IDL dictionaries, do not
- # put dictionary member's initialization in the class definition.
- does_initialize_with_dict = member.default_value.idl_type.is_object
- if does_initialize_with_dict:
- should_construct_in_source = True
-
- default_expr = make_default_value_expr(member.idl_type,
- member.default_value)
- if (default_expr.initializer_deps == ["isolate"]
- or does_initialize_with_dict):
- _1 = _blink_member_name(member).value_var
- _2 = default_expr.initializer_expr
- member_initializer_list.append(_format("{_1}({_2})", _1=_1, _2=_2))
-
- if _is_default_ctor_available(dictionary):
- name = class_name
- arg_decls = []
- return_type = ""
- # In order to avoid cyclic header inclusion of IDL dictionaries, do not
- # put dictionary member's initialization in the class definition.
- if should_construct_in_source:
- ctor_decl = CxxFuncDeclNode(name=name,
- arg_decls=arg_decls,
- return_type=return_type)
- decls.append(ctor_decl)
- ctor_def = CxxFuncDefNode(
- name=name,
- class_name=class_name,
- arg_decls=arg_decls,
- return_type=return_type,
- member_initializer_list=member_initializer_list)
- defs.append(ctor_def)
- else:
- ctor_decl = CxxFuncDeclNode(name=name,
- arg_decls=arg_decls,
- return_type=return_type,
- default=True)
- decls.append(ctor_decl)
+ member_initializer_list = [
+ "{}({})".format(member.value_var, member.initializer_on_constructor)
+ for member in cg_context.dictionary_own_members
+ if member.initializer_on_constructor
+ ]
- ctor_decl = CxxFuncDeclNode(name=class_name,
+ if not _constructor_needs_v8_isolate(cg_context.dictionary):
+ func_decl = CxxFuncDeclNode(name=cg_context.class_name,
+ arg_decls=[],
+ return_type="",
+ explicit=True)
+ func_def = CxxFuncDefNode(
+ name=cg_context.class_name,
+ arg_decls=[],
+ return_type="",
+ class_name=cg_context.class_name,
+ member_initializer_list=member_initializer_list)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ decls.append(func_decl)
+ defs.append(func_def)
+ defs.append(EmptyNode())
+
+ if cg_context.dictionary.inherited:
+ member_initializer_list = ["${base_class_name}(isolate)"
+ ] + member_initializer_list
+ func_decl = CxxFuncDeclNode(name=cg_context.class_name,
arg_decls=["v8::Isolate* isolate"],
return_type="",
explicit=True)
- decls.append(ctor_decl)
- ctor_decl.set_base_template_vars(cg_context.template_bindings())
-
- member_initializer_list.insert(0, "BaseClass(${isolate})")
- ctor_def = CxxFuncDefNode(name=class_name,
- class_name=class_name,
+ func_def = CxxFuncDefNode(name=cg_context.class_name,
arg_decls=["v8::Isolate* isolate"],
return_type="",
+ class_name=cg_context.class_name,
member_initializer_list=member_initializer_list)
- defs.append(ctor_def)
- ctor_def.set_base_template_vars(cg_context.template_bindings())
- ctor_def.add_template_var("isolate", "isolate")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.add_template_vars({"isolate": "isolate"})
+ decls.append(func_decl)
+ defs.append(func_def)
return decls, defs
-def make_dict_member_get(cg_context):
+def make_accessor_functions(cg_context):
assert isinstance(cg_context, CodeGenContext)
- member = cg_context.dict_member
- blink_member_name = _blink_member_name(member)
- name = blink_member_name.get_api
- idl_type = member.idl_type.unwrap(typedef=True)
- blink_type = blink_type_info(idl_type)
- const_ref_t = blink_type.const_ref_t
- ref_t = blink_type.ref_t
-
- # Since Blink conventionally prefers non-const references to const
- # references for the certain types, makes const member's getters return a
- # non-const reference. For example, "Node* foo() const;" is preferable to
- # "const Node* foo() const;".
- if (idl_type.unwrap().is_interface
- or idl_type.unwrap().is_callback_interface
- or idl_type.unwrap().is_callback_function
- or idl_type.unwrap().is_buffer_source_type):
- const_ref_t = ref_t
-
- decls = ListNode()
- defs = ListNode()
-
- func_def = CxxFuncDefNode(name=name,
- arg_decls=[],
- return_type=const_ref_t,
- const=True)
- decls.append(func_def)
- func_def.set_base_template_vars(cg_context.template_bindings())
- func_def.body.extend([
- TextNode(_format("DCHECK({}());", blink_member_name.has_api)),
- TextNode(_format("return {};", blink_member_name.value_var)),
- ])
+ T = TextNode
+ F = FormatNode
+
+ def make_check_assigned_value(member):
+ idl_type = member.idl_type.unwrap(typedef=True)
+ if idl_type.is_object:
+ return F("DCHECK({}.IsObject());", member.value_var)
+ if (member.type_info.is_gc_type and not idl_type.is_nullable):
+ return F("DCHECK({});", member.value_var)
+ return None
+
+ def make_api_has(member):
+ func_def = CxxFuncDefNode(name=member.api_has,
+ arg_decls=[],
+ return_type="bool",
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(F("return {};", member.presence_expr))
+ return func_def, None
- if ref_t != const_ref_t:
- func_def = CxxFuncDefNode(name=name, arg_decls=[], return_type=ref_t)
- decls.append(func_def)
+ def make_api_get(member):
+ func_def = CxxFuncDefNode(name=member.api_get,
+ arg_decls=[],
+ return_type=member.type_info.member_ref_t,
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ if not member.is_always_present:
+ func_def.body.append(F("DCHECK({}());", member.api_has))
+ func_def.body.append(F("return {};", member.value_var))
+ return func_def, None
+
+ def make_api_get_or(member):
+ func_def = CxxFuncDefNode(name=member.api_get_or,
+ arg_decls=[
+ "{} fallback_value".format(
+ member.type_info.member_ref_t)
+ ],
+ return_type=member.type_info.value_t,
+ const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.extend([
- TextNode(_format("DCHECK({}());", blink_member_name.has_api)),
- TextNode(_format("return {};", blink_member_name.value_var)),
+ CxxUnlikelyIfNode(cond="!{}()".format(member.api_has),
+ body=T("return fallback_value;")),
+ F("return {};", member.value_var),
+ ])
+ return func_def, None
+
+ def make_api_get_or_copy_and_move(member):
+ copy_func_decl = CxxFuncDeclNode(name=member.api_get_or,
+ arg_decls=[
+ "{} fallback_value".format(
+ member.type_info.member_ref_t)
+ ],
+ return_type=member.type_info.value_t,
+ const=True)
+ copy_func_def = CxxFuncDefNode(name=member.api_get_or,
+ arg_decls=[
+ "{} fallback_value".format(
+ member.type_info.member_ref_t)
+ ],
+ return_type=member.type_info.value_t,
+ class_name=cg_context.class_name,
+ const=True)
+ copy_func_def.set_base_template_vars(cg_context.template_bindings())
+ copy_func_def.body.extend([
+ CxxUnlikelyIfNode(cond="!{}()".format(member.api_has),
+ body=T("return fallback_value;")),
+ F("return {};", member.value_var),
])
- if idl_type.is_numeric or idl_type.unwrap().is_string:
- arg_type = blink_type.const_ref_t
- return_type = blink_type.value_t
- elif idl_type.unwrap().is_enumeration:
- arg_type = ("absl::nullopt_t"
- if idl_type.is_nullable else blink_type.value_t)
- return_type = blink_type.value_t
- elif idl_type.unwrap().is_dictionary:
- arg_type = "nullptr_t"
- return_type = blink_type.const_ref_t
- elif idl_type.unwrap().type_definition_object:
- arg_type = "nullptr_t"
- return_type = blink_type.ref_t
- elif idl_type.is_nullable and (idl_type.unwrap().is_sequence
- or idl_type.unwrap().is_frozen_array
- or idl_type.unwrap().is_record):
- arg_type = "absl::nullopt_t"
- return_type = blink_type.value_t
- else:
- arg_type = None
- return_type = None
-
- if arg_type is not None or return_type is not None:
- assert arg_type is not None and return_type is not None
-
- name = blink_member_name.get_or_api
- arg_decls = [_format("{} fallback_value", arg_type)]
-
- def should_be_defined_in_source(member):
- # sequence<Dictionary> and record<String, Dictionary> are
- # implemented with HeapVector and Dictionary's definition is
- # required while promise<Dictionary> doesn't require it.
- def element_or_value_of(idl_type):
- return (idl_type.unwrap().element_type
- or idl_type.unwrap().value_type)
-
- idl_type = element_or_value_of(member.idl_type)
- while idl_type and element_or_value_of(idl_type):
- idl_type = element_or_value_of(idl_type)
- return idl_type and idl_type.unwrap().is_dictionary
-
- # In order to avoid cyclic header inclusion of IDL dictionaries,
- # whenever the function needs a dictionary's definition, do not put the
- # function definition in the header file.
- if should_be_defined_in_source(member):
- func_decl = CxxFuncDeclNode(name=name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True)
- decls.append(func_decl)
- func_def = CxxFuncDefNode(name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True)
- defs.append(func_def)
- func_def.set_base_template_vars(cg_context.template_bindings())
- else:
- func_def = CxxFuncDefNode(name=name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True)
- decls.append(func_def)
- func_def.set_base_template_vars(cg_context.template_bindings())
-
- body_node = TextNode(
- _format("""\
-if ({has}()) {{
- return {get}();
-}}
-return fallback_value;""",
- has=blink_member_name.has_api,
- get=blink_member_name.get_api))
- func_def.body.append(body_node)
-
- return decls, defs
-
-
-def make_dict_member_has(cg_context):
- assert isinstance(cg_context, CodeGenContext)
+ move_func_decl = CxxFuncDeclNode(
+ name=member.api_get_or,
+ arg_decls=["{}&& fallback_value".format(member.type_info.value_t)],
+ return_type=member.type_info.value_t,
+ const=True)
+ move_func_def = CxxFuncDefNode(
+ name=member.api_get_or,
+ arg_decls=["{}&& fallback_value".format(member.type_info.value_t)],
+ return_type=member.type_info.value_t,
+ class_name=cg_context.class_name,
+ const=True)
+ move_func_def.set_base_template_vars(cg_context.template_bindings())
+ move_func_def.body.extend([
+ CxxUnlikelyIfNode(cond="!{}()".format(member.api_has),
+ body=T("return std::move(fallback_value);")),
+ F("return {};", member.value_var),
+ ])
- member = cg_context.dict_member
+ decls = ListNode([copy_func_decl, move_func_decl])
+ defs = ListNode([copy_func_def, EmptyNode(), move_func_def])
+ return decls, defs
+
+ def make_api_get_or_string(member):
+ # getMemberOr(const char*) in addition to
+ # getMemberOr(const String&) to avoid creation of a temporary String
+ # object.
+ if not member.idl_type.unwrap(typedef=True).is_string:
+ return None, None
+ func_def = CxxFuncDefNode(name=member.api_get_or,
+ arg_decls=["const char* fallback_value"],
+ return_type=member.type_info.value_t,
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.extend([
+ CxxUnlikelyIfNode(cond="!{}()".format(member.api_has),
+ body=T("return fallback_value;")),
+ F("return {};", member.value_var),
+ ])
+ return func_def, None
+
+ def make_api_set(member, type_info=None):
+ if type_info is None:
+ type_info = member.type_info
+ func_def = CxxFuncDefNode(
+ name=member.api_set,
+ arg_decls=["{} value".format(type_info.member_ref_t)],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(F("{} = value;", member.value_var))
+ if member.does_use_presence_var:
+ func_def.body.append(F("{} = true;", member.presence_var))
+ func_def.body.append(make_check_assigned_value(member))
+ return func_def, None
+
+ def make_api_set_copy_and_move(member, type_info=None):
+ if type_info is None:
+ type_info = member.type_info
+ copy_func_decl = CxxFuncDeclNode(
+ name=member.api_set,
+ arg_decls=["{} value".format(type_info.member_ref_t)],
+ return_type="void")
+ copy_func_def = CxxFuncDefNode(
+ name=member.api_set,
+ arg_decls=["{} value".format(type_info.member_ref_t)],
+ return_type="void",
+ class_name=cg_context.class_name)
+ copy_func_def.set_base_template_vars(cg_context.template_bindings())
+ copy_func_def.body.append(F("{} = value;", member.value_var))
+ if member.does_use_presence_var:
+ copy_func_def.body.append(F("{} = true;", member.presence_var))
+ copy_func_def.body.append(make_check_assigned_value(member))
+
+ move_func_decl = CxxFuncDeclNode(
+ name=member.api_set,
+ arg_decls=["{}&& value".format(type_info.value_t)],
+ return_type="void")
+ move_func_def = CxxFuncDefNode(
+ name=member.api_set,
+ arg_decls=["{}&& value".format(type_info.value_t)],
+ return_type="void",
+ class_name=cg_context.class_name)
+ move_func_def.set_base_template_vars(cg_context.template_bindings())
+ move_func_def.body.append(F("{} = std::move(value);",
+ member.value_var))
+ if member.does_use_presence_var:
+ move_func_def.body.append(F("{} = true;", member.presence_var))
+ move_func_def.body.append(make_check_assigned_value(member))
+
+ decls = ListNode([copy_func_decl, move_func_decl])
+ defs = ListNode([copy_func_def, EmptyNode(), move_func_def])
+ return decls, defs
+
+ def make_api_set_non_nullable(member):
+ # setMember(InnerType) in addition to
+ # setMember(absl::optional<InnerType>) for convenience.
+ if not (member.idl_type.does_include_nullable_type
+ and not member.type_info.has_null_value):
+ return None, None
+ return make_api_set(member, blink_type_info(member.idl_type.unwrap()))
+
+ def make_api_set_copy_and_move_non_nullable(member):
+ # setMember(InnerType) in addition to
+ # setMember(absl::optional<InnerType>) for convenience.
+ if not (member.idl_type.does_include_nullable_type
+ and not member.type_info.has_null_value):
+ return None, None
+ return make_api_set_copy_and_move(
+ member, blink_type_info(member.idl_type.unwrap()))
+
+ def make_api_set_enum(member):
+ # setMember(V8Enum::Enum) in addition to
+ # setMember(V8Enum) for convenience.
+ if not member.idl_type.unwrap().is_enumeration:
+ return None, None
+ type_info = blink_type_info(member.idl_type.unwrap())
+ func_def = CxxFuncDefNode(
+ name=member.api_set,
+ arg_decls=["{}::Enum value".format(type_info.value_t)],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(
+ F("{} = {}(value);", member.value_var, type_info.value_t))
+ if member.does_use_presence_var:
+ func_def.body.append(F("{} = true;", member.presence_var))
+ func_def.body.append(make_check_assigned_value(member))
+ return func_def, None
decls = ListNode()
defs = ListNode()
- func_def = CxxFuncDefNode(
- name=_blink_member_name(member).has_api,
- arg_decls=[],
- return_type="bool",
- const=True)
- decls.append(func_def)
- func_def.set_base_template_vars(cg_context.template_bindings())
- body = func_def.body
-
- _1 = _member_presence_expr(member)
- body.append(TextNode(_format("return {_1};", _1=_1)))
-
- return decls, defs
-
-
-def make_dict_member_set(cg_context):
- assert isinstance(cg_context, CodeGenContext)
-
- T = TextNode
-
- member = cg_context.dict_member
- blink_member_name = _blink_member_name(member)
- real_type = member.idl_type.unwrap(typedef=True)
- type_info = blink_type_info(real_type)
+ def add(func_decl, func_def):
+ decls.append(func_decl)
+ defs.append(func_def)
+ defs.append(EmptyNode())
+
+ for member in cg_context.dictionary_own_members:
+ # Predicate
+ add(*make_api_has(member))
+
+ # Getter
+ add(*make_api_get(member))
+ if member.is_always_present:
+ pass
+ elif member.type_info.is_move_effective:
+ add(*make_api_get_or_copy_and_move(member))
+ else:
+ add(*make_api_get_or(member))
+ add(*make_api_get_or_string(member))
- decls = ListNode()
- defs = ListNode()
+ # Setter
+ if member.type_info.is_move_effective:
+ add(*make_api_set_copy_and_move(member))
+ add(*make_api_set_copy_and_move_non_nullable(member))
+ else:
+ add(*make_api_set(member))
+ add(*make_api_set_non_nullable(member))
+ add(*make_api_set_enum(member))
- template_func_def = CxxFuncDefNode(
- name=blink_member_name.set_api,
- arg_decls=["T&& value"],
- return_type="void",
- template_params=["typename T"])
- decls.append(template_func_def)
-
- # This setter with the explicit type declaration makes it possible to set
- # the dictionary member with uniform initialization (especially aggregate
- # initialization), e.g. setIntVector({3, 1, 4, 1, 5}).
- move_func_decl = CxxFuncDeclNode(
- name=blink_member_name.set_api,
- arg_decls=[_format("{}&&", type_info.member_t)],
- return_type="void")
- decls.append(move_func_decl)
-
- move_func_def = CxxFuncDefNode(
- name=blink_member_name.set_api,
- arg_decls=[_format("{}&& value", type_info.member_t)],
- return_type="void",
- class_name=cg_context.class_name)
- defs.append(move_func_def)
-
- _1 = blink_member_name.value_var
- template_func_def.body.append(
- T(_format("{_1} = std::forward<T>(value);", _1=_1)))
- move_func_def.body.append(T(_format("{_1} = value;", _1=_1)))
-
- if _does_use_presence_flag(member):
- set_presense_expr = _format("{} = true;",
- blink_member_name.presence_var)
- template_func_def.body.append(T(set_presense_expr))
- move_func_def.body.append(T(set_presense_expr))
-
- # Migration Adapter
- if (real_type.is_nullable and
- blink_type_info(real_type).typename.startswith("absl::optional")):
- to_null_func_def = CxxFuncDefNode(
- name=_format("{}ToNull", blink_member_name.set_api),
- arg_decls=[],
- return_type="void")
- decls.append(to_null_func_def)
- to_null_func_def.set_base_template_vars(cg_context.template_bindings())
- to_null_func_def.body.append(
- T(_format("{}(absl::nullopt);", blink_member_name.set_api)))
+ decls.append(EmptyNode())
return decls, defs
-def make_dict_member_vars(cg_context):
+def make_backward_compatible_accessors(cg_context):
assert isinstance(cg_context, CodeGenContext)
- member = cg_context.dict_member
-
- default_value_initializer = ""
- if member.default_value:
- default_expr = make_default_value_expr(member.idl_type,
- member.default_value)
- # In order to avoid cyclic header inclusion of IDL dictionaries, do not
- # put dictionary member's initialization in the class definition.
- if (default_expr.initializer_expr is not None
- and not default_expr.initializer_deps
- and not member.default_value.idl_type.is_object):
- default_value_initializer = _format("{{{}}}",
- default_expr.initializer_expr)
-
- _1 = blink_type_info(member.idl_type).member_t
- _2 = _blink_member_name(member).value_var
- _3 = default_value_initializer
- value_var_def = TextNode(_format("{_1} {_2}{_3};", _1=_1, _2=_2, _3=_3))
-
- if _does_use_presence_flag(member):
- _1 = _blink_member_name(member).presence_var
- presense_var_def = TextNode(_format("bool {_1} = false;", _1=_1))
- else:
- presense_var_def = None
-
- return value_var_def, presense_var_def
+ # TODO(crbug.com/1070871): Remove the accessors introduced just to be
+ # backward compatible.
+ F = FormatNode
-def make_dict_member_migration_adapters(cg_context):
- assert isinstance(cg_context, CodeGenContext)
-
- member = cg_context.dict_member
- blink_member_name = _blink_member_name(member)
- idl_type = member.idl_type
- blink_type = blink_type_info(idl_type)
- real_type = idl_type.unwrap(typedef=True)
-
- if (not real_type.is_nullable
- or blink_type_info(real_type.inner_type).has_null_value):
- return None, None
-
- decls = ListNode([TextNode("// Migration Adapters")])
- defs = ListNode()
+ decls = ListNode()
- # Accessors for non-null values, if the usual getter returns
- # absl::optional<T>.
- blink_inner_type = blink_type_info(real_type.inner_type)
- get_api = blink_member_name.get_api
- has_api = blink_member_name.has_api
- get_non_null_api = blink_member_name.get_non_null_api
- has_non_null_api = blink_member_name.has_non_null_api
-
- func_def = CxxFuncDefNode(name=get_non_null_api,
- arg_decls=[],
- return_type=blink_inner_type.const_ref_t,
- const=True)
- decls.extend([
- TextNode(
- _format(
- """\
-// Returns the value if this member has a non-null value. Call
-// |{}| in advance to check the condition.""", has_non_null_api)),
- func_def,
- ])
- func_def.set_base_template_vars(cg_context.template_bindings())
- func_def.body.extend([
- TextNode(_format("DCHECK({}());", has_non_null_api)),
- TextNode(_format("return {}().value();", get_api)),
- ])
+ def make_api_has_non_null(member):
+ func_def = CxxFuncDefNode(name=member.api_has_non_null,
+ arg_decls=[],
+ return_type="bool",
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(
+ F("return {}() && {}().has_value();", member.api_has,
+ member.api_get))
+ return func_def
- if blink_inner_type.ref_t != blink_inner_type.const_ref_t:
- func_def = CxxFuncDefNode(name=get_non_null_api,
+ def make_api_get_non_null(member):
+ func_def = CxxFuncDefNode(name=member.api_get_non_null,
arg_decls=[],
- return_type=blink_inner_type.ref_t)
- decls.append(func_def)
+ return_type=blink_type_info(
+ member.idl_type.unwrap()).member_ref_t,
+ const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.extend([
- TextNode(_format("DCHECK({}());", has_non_null_api)),
- TextNode(_format("return {}().value();", get_api)),
+ F("DCHECK({}());", member.api_has_non_null),
+ F("return {}().value();", member.api_get),
])
+ return func_def
- func_def = CxxFuncDefNode(name=has_non_null_api,
- arg_decls=[],
- return_type="bool",
- const=True)
- decls.extend([
- TextNode("""\
-// Returns true iff this member has a non-null value. Returns false if the
-// value is missing or the null value."""),
- func_def,
- ])
- func_def.set_base_template_vars(cg_context.template_bindings())
- func_def.body.append(
- TextNode(_format("return {}() && {}().has_value();", has_api,
- get_api)))
+ def make_api_set_enum_string(member):
+ type_info = blink_type_info(member.idl_type.unwrap())
+ func_def = CxxFuncDefNode(name=member.api_set,
+ arg_decls=["const String& value"],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(
+ F("{} = {}::Create(value).value();", member.value_var,
+ type_info.value_t))
+ if member.does_use_presence_var:
+ func_def.body.append(F("{} = true;", member.presence_var))
+ return func_def
+
+ for member in cg_context.dictionary_own_members:
+ if member.idl_type.unwrap().is_enumeration:
+ decls.append(make_api_set_enum_string(member))
+
+ if (not member.idl_type.unwrap(nullable=False).is_nullable
+ or member.type_info.has_null_value):
+ continue
+ # The Blink type is absl::optional<T>.
+ decls.append(make_api_has_non_null(member))
+ decls.append(make_api_get_non_null(member))
- return decls, defs
+ if decls:
+ decls.insert(0, TextNode("// Obsolete accessor functions"))
+
+ return decls, None
-def make_get_v8_dict_member_names_func(cg_context):
+def make_trace_function(cg_context):
assert isinstance(cg_context, CodeGenContext)
- dictionary = cg_context.dictionary
- name = "GetV8MemberNames"
- arg_decls = ["v8::Isolate* isolate"]
- return_type = "const base::span<const v8::Eternal<v8::Name>>"
+ func_decl = CxxFuncDeclNode(name="Trace",
+ arg_decls=["Visitor* visitor"],
+ return_type="void",
+ const=True,
+ override=True)
- func_decl = CxxFuncDeclNode(
- name=name, arg_decls=arg_decls, return_type=return_type, static=True)
- func_def = CxxFuncDefNode(
- name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type)
+ func_def = CxxFuncDefNode(name="Trace",
+ arg_decls=["Visitor* visitor"],
+ return_type="void",
+ class_name=cg_context.class_name,
+ const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- if dictionary.own_members:
- pattern = "static const char* const kKeyStrings[] = {{{_1}}};"
- _1 = ", ".join(
- _format("\"{}\"", member.identifier)
- for member in dictionary.own_members)
- body.extend([
- TextNode(_format(pattern, _1=_1)),
- TextNode("return V8PerIsolateData::From(isolate)"
- "->FindOrCreateEternalNameCache(kKeyStrings, "
- "kKeyStrings);"),
- ])
- else:
- body.append(TextNode("return {};"))
+ for member in cg_context.dictionary_own_members:
+ body.append(
+ TextNode("TraceIfNeeded<{}>::Trace(visitor, {});".format(
+ member.type_info.member_t, member.value_var)))
+ body.append(TextNode("${base_class_name}::Trace(visitor);"))
return func_decl, func_def
-def make_fill_with_dict_members_func(cg_context):
+def make_blink_to_v8_function(cg_context):
assert isinstance(cg_context, CodeGenContext)
- dictionary = cg_context.dictionary
- name = "FillWithMembers"
- arg_decls = [
- "v8::Isolate* isolate",
- "v8::Local<v8::Object> creation_context",
- "v8::Local<v8::Object> v8_dictionary",
- ]
- return_type = "bool"
+ S = SymbolNode
+ T = TextNode
+ F = FormatNode
+
+ func_decl = CxxFuncDeclNode(name="FillV8ObjectWithMembers",
+ arg_decls=[
+ "ScriptState* script_state",
+ "v8::Local<v8::Object> v8_dictionary",
+ ],
+ return_type="bool",
+ const=True,
+ override=True)
- func_decl = CxxFuncDeclNode(
- name=name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True,
- override=True)
- func_def = CxxFuncDefNode(
- name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True)
+ func_def = CxxFuncDefNode(name="FillV8ObjectWithMembers",
+ arg_decls=[
+ "ScriptState* script_state",
+ "v8::Local<v8::Object> v8_dictionary",
+ ],
+ return_type="bool",
+ class_name=cg_context.class_name,
+ const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
+ body.add_template_vars({
+ "script_state": "script_state",
+ "v8_dictionary": "v8_dictionary",
+ })
+ body.register_code_symbols([
+ S("isolate",
+ "v8::Isolate* ${isolate} = ${script_state}->GetIsolate();"),
+ S("v8_value", "v8::Local<v8::Value> ${v8_value};"),
+ S("was_property_created", "bool ${was_property_created};"),
+ ])
+ bind_local_vars(body, cg_context)
- if dictionary.inherited:
- text = """\
-if (!BaseClass::FillWithMembers(isolate, creation_context, v8_dictionary)) {
- return false;
-}"""
- body.append(TextNode(text))
-
- body.append(
- TextNode("return FillWithOwnMembers("
- "isolate, creation_context, v8_dictionary);"))
-
- return func_decl, func_def
-
-
-def make_fill_with_own_dict_members_func(cg_context):
- assert isinstance(cg_context, CodeGenContext)
-
- dictionary = cg_context.dictionary
- own_members = dictionary.own_members
- name = "FillWithOwnMembers"
- arg_decls = [
- "v8::Isolate* isolate",
- "v8::Local<v8::Object> creation_context",
- "v8::Local<v8::Object> v8_dictionary",
- ]
- return_type = "bool"
+ if cg_context.dictionary.inherited:
+ body.extend([
+ CxxUnlikelyIfNode( #
+ cond=T("!${base_class_name}::FillV8ObjectWithMembers"
+ "(${script_state}, ${v8_dictionary})"),
+ body=T("return false;")),
+ EmptyNode(),
+ ])
- func_decl = CxxFuncDeclNode(
- name=name, arg_decls=arg_decls, return_type=return_type, const=True)
- func_def = CxxFuncDefNode(
- name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True)
- func_def.set_base_template_vars(cg_context.template_bindings())
- body = func_def.body
- body.add_template_var("isolate", "isolate")
- body.add_template_var("creation_context", "creation_context")
- body.add_template_var("v8_dictionary", "v8_dictionary")
- bind_member_iteration_local_vars(body)
-
- for index, member in enumerate(own_members):
- member_name = _blink_member_name(member)
- v8_member_name = name_style.local_var_f("v8_member_{}",
- member.identifier)
- body.register_code_symbol(
- make_blink_to_v8_value(v8_member_name,
- "{}()".format(member_name.get_api),
- member.idl_type, "${creation_context}"))
+ for index, member in enumerate(cg_context.dictionary_own_members):
node = CxxLikelyIfNode(
- cond="{}()".format(member_name.has_api),
- body=TextNode(
- _format(
- "${v8_dictionary}->CreateDataProperty("
- "${current_context}, "
- "${v8_member_names}[{index}].Get(${isolate}), "
- "${{{v8_member_name}}}"
- ").ToChecked();",
- index=index,
- v8_member_name=v8_member_name)))
+ cond="{}()".format(member.api_has),
+ body=[
+ CxxUnlikelyIfNode( #
+ cond=_format(
+ "!ToV8Traits<{native_value_tag}>::"
+ "ToV8(${script_state}, {blink_value})"
+ ".ToLocal(&${v8_value})",
+ native_value_tag=native_value_tag(member.idl_type),
+ blink_value=member.value_var),
+ body=T("return false;")),
+ CxxUnlikelyIfNode( #
+ cond=_format(
+ "!${v8_dictionary}->CreateDataProperty("
+ "${current_context}, "
+ "${v8_own_member_names}[{index}].Get(${isolate}), "
+ "${v8_value}).To(&${was_property_created})",
+ index=index),
+ body=T("return false;")),
+ ])
+
conditional = expr_from_exposure(member.exposure)
if not conditional.is_always_true:
node = CxxLikelyIfNode(cond=conditional, body=node)
+
body.append(node)
body.append(TextNode("return true;"))
@@ -711,193 +795,154 @@ def make_fill_with_own_dict_members_func(cg_context):
return func_decl, func_def
-def make_fill_dict_members_func(cg_context):
+def make_v8_to_blink_function(cg_context):
assert isinstance(cg_context, CodeGenContext)
+ S = SymbolNode
T = TextNode
+ F = FormatNode
+
+ func_decl = CxxFuncDeclNode(name="FillMembersFromV8Object",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Object> v8_dictionary",
+ "ExceptionState& exception_state",
+ ],
+ return_type="void")
+
+ func_def = CxxFuncDefNode(name="FillMembersFromV8Object",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Object> v8_dictionary",
+ "ExceptionState& exception_state",
+ ],
+ return_type="void",
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_vars({
+ "isolate": "isolate",
+ "v8_dictionary": "v8_dictionary",
+ "exception_state": "exception_state",
+ })
+ body.register_code_symbols([
+ S("exception_context_scope",
+ ("ExceptionState::ContextScope ${exception_context_scope}("
+ "ExceptionContext("
+ "ExceptionContext::Context::kDictionaryMemberGet, "
+ "${class_like_name}, \"\"), "
+ "${exception_state});")),
+ S("fallback_presence_var", "bool ${fallback_presence_var};"),
+ S("is_optional", "constexpr bool ${is_optional} = false;"),
+ S("is_required", "constexpr bool ${is_required} = true;"),
+ S("try_block", "v8::TryCatch ${try_block}(${isolate});"),
+ ])
+ bind_local_vars(body, cg_context)
- dictionary = cg_context.dictionary
- own_members = dictionary.own_members
- required_own_members = list(
- member for member in own_members if member.is_required)
- name = "FillMembers"
- arg_decls = [
- "v8::Isolate* isolate",
- "v8::Local<v8::Value> v8_value",
- "ExceptionState& exception_state",
- ]
- return_type = "void"
+ if cg_context.dictionary.inherited:
+ body.extend([
+ T("${base_class_name}::FillMembersFromV8Object"
+ "(${isolate}, ${v8_dictionary}, ${exception_state});"),
+ CxxUnlikelyIfNode(
+ cond="UNLIKELY(${exception_state}.HadException())",
+ body=T("return;")),
+ EmptyNode(),
+ ])
- func_decl = CxxFuncDeclNode(
- name=name, arg_decls=arg_decls, return_type=return_type)
- func_def = CxxFuncDefNode(
- name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type)
- func_def.set_base_template_vars(cg_context.template_bindings())
+ for index, member in enumerate(cg_context.dictionary_own_members):
+ cond = _format(
+ "!bindings::GetDictionaryMemberFromV8Object"
+ "<{native_value_tag}, {is_required}>("
+ "${isolate}, ${current_context}, "
+ "${v8_dictionary}, "
+ "${v8_own_member_names}[{index}].Get(${isolate}), "
+ "{presence_var}, {value_var}, "
+ "${try_block}, ${exception_state})",
+ native_value_tag=native_value_tag(member.idl_type),
+ is_required=("${is_required}"
+ if member.is_required else "${is_optional}"),
+ index=index,
+ presence_var=(member.presence_var if member.does_use_presence_var
+ else "${fallback_presence_var}"),
+ value_var=member.value_var)
+ node = SequenceNode([
+ F(("${exception_context_scope}"
+ ".ChangePropertyNameAsOptimizationHack(\"{member_name}\");"),
+ member_name=member.identifier),
+ CxxUnlikelyIfNode(cond=cond, body=T("return;")),
+ ])
- if required_own_members:
- check_required_members_node = T("""\
-if (v8_value->IsNullOrUndefined()) {
- exception_state.ThrowTypeError(ExceptionMessages::FailedToConstruct(
- "${dictionary.identifier}",
- "has required members, but null/undefined was passed."));
- return;
-}""")
- else:
- check_required_members_node = T("""\
-if (v8_value->IsNullOrUndefined()) {
- return;
-}""")
+ conditional = expr_from_exposure(member.exposure)
+ if not conditional.is_always_true:
+ node = CxxLikelyIfNode(cond=conditional, body=node)
- # [PermissiveDictionaryConversion]
- if "PermissiveDictionaryConversion" in dictionary.extended_attributes:
- permissive_conversion_node = T("""\
-if (!v8_value->IsObject()) {
- // [PermissiveDictionaryConversion]
- return;
-}""")
- else:
- permissive_conversion_node = T("""\
-if (!v8_value->IsObject()) {
- exception_state.ThrowTypeError(
- ExceptionMessages::FailedToConstruct(
- "${dictionary.identifier}", "The value is not of type Object"));
- return;
-}""")
-
- call_internal_func_node = T("""\
-FillMembersInternal(isolate, v8_value.As<v8::Object>(), exception_state);""")
-
- func_def.body.extend([
- check_required_members_node,
- permissive_conversion_node,
- call_internal_func_node,
- ])
+ body.append(node)
return func_decl, func_def
-def make_fill_dict_members_internal_func(cg_context):
+def make_v8_own_member_names_function(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
-
- dictionary = cg_context.dictionary
- own_members = dictionary.own_members
- name = "FillMembersInternal"
- arg_decls = [
- "v8::Isolate* isolate",
- "v8::Local<v8::Object> v8_dictionary",
- "ExceptionState& exception_state",
- ]
- return_type = "void"
func_decl = CxxFuncDeclNode(
- name=name, arg_decls=arg_decls, return_type=return_type)
+ name="GetV8OwnMemberNames",
+ arg_decls=["v8::Isolate* isolate"],
+ return_type="const base::span<const v8::Eternal<v8::Name>>",
+ static=True)
+
func_def = CxxFuncDefNode(
- name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type)
+ name="GetV8OwnMemberNames",
+ arg_decls=["v8::Isolate* isolate"],
+ return_type="const base::span<const v8::Eternal<v8::Name>>",
+ class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- body.add_template_var("isolate", "isolate")
- body.add_template_var("exception_state", "exception_state")
- bind_member_iteration_local_vars(body)
- body.register_code_symbols([
- SymbolNode("try_block", "v8::TryCatch ${try_block}(${isolate});"),
- SymbolNode("v8_value", "v8::Local<v8::Value> ${v8_value};"),
- SymbolNode("unused_presence_var", "bool ${unused_presence_var};"),
- ])
+ func_def.body.add_template_vars({"isolate": "isolate"})
- if dictionary.inherited:
- text = """\
-BaseClass::FillMembersInternal(${isolate}, v8_dictionary, ${exception_state});
-if (${exception_state}.HadException()) {
- return;
-}
-"""
- body.append(T(text))
+ if not cg_context.dictionary.own_members:
+ body.append(TextNode("return {};"))
+ return func_decl, func_def
- for key_index, member in enumerate(own_members):
- body.append(make_fill_own_dict_member(key_index, member))
+ body.extend([
+ ListNode([
+ TextNode("static const char* const kOwnMemberNames[] = {"),
+ ListNode([
+ TextNode("\"{}\",".format(member.identifier))
+ for member in cg_context.dictionary.own_members
+ ]),
+ TextNode("};"),
+ ]),
+ TextNode("return V8PerIsolateData::From(${isolate})"
+ "->FindOrCreateEternalNameCache"
+ "(kOwnMemberNames, kOwnMemberNames);"),
+ ])
return func_decl, func_def
-def make_fill_own_dict_member(key_index, member):
- assert isinstance(key_index, int)
- assert isinstance(member, web_idl.DictionaryMember)
-
- pattern = """\
-if (!bindings::ConvertDictionaryMember<{nvt_tag}, {is_required}>(
- ${isolate},
- ${current_context},
- v8_dictionary,
- ${v8_member_names}[{key_index}].Get(${isolate}),
- "${{dictionary.identifier}}",
- "{member_name}",
- {value_var},
- {presence_var},
- ${try_block},
- ${exception_state})) {{
- return;
-}}"""
- if _does_use_presence_flag(member):
- presence_var = _blink_member_name(member).presence_var
- else:
- presence_var = "${unused_presence_var}"
- node = TextNode(
- _format(pattern,
- nvt_tag=native_value_tag(member.idl_type),
- is_required="true" if member.is_required else "false",
- key_index=key_index,
- member_name=member.identifier,
- value_var=_blink_member_name(member).value_var,
- presence_var=presence_var))
-
- conditional = expr_from_exposure(member.exposure)
- if not conditional.is_always_true:
- node = CxxLikelyIfNode(cond=conditional, body=node)
-
- return node
-
-
-def make_dict_trace_func(cg_context):
+def make_member_vars_def(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
-
- dictionary = cg_context.dictionary
- own_members = dictionary.own_members
- name = "Trace"
- arg_decls = ["Visitor* visitor"]
- return_type = "void"
-
- func_decl = CxxFuncDeclNode(name=name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True,
- override=True)
- func_def = CxxFuncDefNode(name=name,
- class_name=cg_context.class_name,
- arg_decls=arg_decls,
- return_type=return_type,
- const=True)
- func_def.set_base_template_vars(cg_context.template_bindings())
- body = func_def.body
+ F = FormatNode
- def make_trace_member_node(member):
- pattern = "TraceIfNeeded<{_1}>::Trace(visitor, {_2});"
- _1 = blink_type_info(member.idl_type).member_t
- _2 = _blink_member_name(member).value_var
- return TextNode(_format(pattern, _1=_1, _2=_2))
+ presence_vars = ListNode([
+ F("bool {} = false;", member.presence_var)
+ for member in cg_context.dictionary_own_members
+ if member.does_use_presence_var
+ ])
- body.extend(list(map(make_trace_member_node, own_members)))
- body.append(TextNode("BaseClass::Trace(visitor);"))
+ value_vars = ListNode([
+ F("{} {}{};", member.type_info.member_t, member.value_var,
+ ("{{{}}}".format(member.initializer_on_member_decl)
+ if member.initializer_on_member_decl else ""))
+ for member in cg_context.dictionary_own_members
+ ])
- return func_decl, func_def
+ return ListNode([
+ presence_vars,
+ EmptyNode(),
+ value_vars,
+ ])
def generate_dictionary(dictionary_identifier):
@@ -908,21 +953,23 @@ def generate_dictionary(dictionary_identifier):
path_manager = PathManager(dictionary)
assert path_manager.api_component == path_manager.impl_component, (
- "We don't support partial dictionaries across components yet.")
+ "Partial dictionaries across components are not supported.")
api_component = path_manager.api_component
for_testing = dictionary.code_generator_info.for_testing
- path_manager = PathManager(dictionary)
- class_name = name_style.class_(blink_class_name(dictionary))
+ # Class names
+ class_name = blink_class_name(dictionary)
if dictionary.inherited:
base_class_name = blink_class_name(dictionary.inherited)
else:
base_class_name = "bindings::DictionaryBase"
- cg_context = CodeGenContext(
- dictionary=dictionary,
- class_name=class_name,
- base_class_name=base_class_name)
+ cg_context = CodeGenContext(dictionary=dictionary,
+ dictionary_own_members=tuple(
+ map(_DictionaryMember,
+ dictionary.own_members)),
+ class_name=class_name,
+ base_class_name=base_class_name)
# Filepaths
header_path = path_manager.api_path(ext="h")
@@ -940,96 +987,53 @@ def generate_dictionary(dictionary_identifier):
header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
- # Class definitions
+ # Class definition
class_def = CxxClassDefNode(cg_context.class_name,
base_class_names=[cg_context.base_class_name],
export=component_export(
api_component, for_testing))
class_def.set_base_template_vars(cg_context.template_bindings())
- class_def.top_section.append(
- TextNode("using BaseClass = ${base_class_name};"))
-
- # Create functions
- create_decl, create_def = make_create_dict_funcs(cg_context)
-
- # Constructor and destructor
- constructor_decls, constructor_defs = make_dict_constructors(cg_context)
- destructor_decl = CxxFuncDeclNode(
- name="~${class_name}", arg_decls=[], return_type="", default=True)
-
- # Fill with members (Blink -> V8 conversion)
- (fill_with_members_decl,
- fill_with_members_def) = make_fill_with_dict_members_func(cg_context)
- (fill_with_own_members_decl, fill_with_own_members_def
- ) = make_fill_with_own_dict_members_func(cg_context)
-
- # Fill members (V8 -> Blink conversion)
- (fill_members_decl,
- fill_members_def) = make_fill_dict_members_func(cg_context)
- (fill_members_internal_decl, fill_members_internal_def
- ) = make_fill_dict_members_internal_func(cg_context)
-
- # Misc. functions
- (get_v8_member_names_decl,
- get_v8_member_names_def) = make_get_v8_dict_member_names_func(cg_context)
- trace_decl, trace_def = make_dict_trace_func(cg_context)
-
- member_accessor_decls = ListNode()
- member_accessor_defs = ListNode()
- member_value_var_defs = ListNode()
- member_presense_var_defs = ListNode()
- for member in cg_context.dictionary.own_members:
- member_context = cg_context.make_copy(dict_member=member)
- get_decls, get_defs = make_dict_member_get(member_context)
- has_decls, has_defs = make_dict_member_has(member_context)
- set_decls, set_defs = make_dict_member_set(member_context)
- value_var_def, presense_var_def = make_dict_member_vars(member_context)
- (migration_adapter_decls, migration_adapter_defs
- ) = make_dict_member_migration_adapters(member_context)
- member_accessor_decls.extend([
- TextNode(""),
- get_decls,
- has_decls,
- set_decls,
- migration_adapter_decls,
- ])
- member_accessor_defs.extend([
- TextNode(""),
- get_defs,
- has_defs,
- set_defs,
- migration_adapter_defs,
- ])
- member_value_var_defs.append(value_var_def)
- member_presense_var_defs.append(presense_var_def)
+
+ # Implementation parts
+ factory_decls, factory_defs = make_factory_methods(cg_context)
+ ctor_decls, ctor_defs = make_constructors(cg_context)
+ accessor_decls, accessor_defs = make_accessor_functions(cg_context)
+ backward_compatible_accessor_decls, backward_compatible_accessor_defs = (
+ make_backward_compatible_accessors(cg_context))
+ trace_func_decls, trace_func_defs = make_trace_function(cg_context)
+ blink_to_v8_decls, blink_to_v8_defs = make_blink_to_v8_function(cg_context)
+ v8_to_blink_decls, v8_to_blink_defs = make_v8_to_blink_function(cg_context)
+ v8_names_decls, v8_names_defs = make_v8_own_member_names_function(
+ cg_context)
+ member_vars_def = make_member_vars_def(cg_context)
# Header part (copyright, include directives, and forward declarations)
header_node.extend([
make_copyright_header(),
- TextNode(""),
+ EmptyNode(),
enclose_with_header_guard(
ListNode([
make_header_include_directives(header_node.accumulator),
- TextNode(""),
+ EmptyNode(),
header_blink_ns,
]), name_style.header_guard(header_path)),
])
header_blink_ns.body.extend([
make_forward_declarations(header_node.accumulator),
- TextNode(""),
+ EmptyNode(),
])
source_node.extend([
make_copyright_header(),
- TextNode(""),
+ EmptyNode(),
TextNode("#include \"{}\"".format(header_path)),
- TextNode(""),
+ EmptyNode(),
make_header_include_directives(source_node.accumulator),
- TextNode(""),
+ EmptyNode(),
source_blink_ns,
])
source_blink_ns.body.extend([
make_forward_declarations(source_node.accumulator),
- TextNode(""),
+ EmptyNode(),
])
# Assemble the parts.
@@ -1039,68 +1043,68 @@ def generate_dictionary(dictionary_identifier):
if dictionary.inherited else
"third_party/blink/renderer/platform/bindings/dictionary_base.h"),
component_export_header(api_component, for_testing),
- "v8/include/v8.h",
])
source_node.accumulator.add_include_headers([
"third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
"third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h",
+ "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h",
"third_party/blink/renderer/platform/bindings/exception_messages.h",
"third_party/blink/renderer/platform/bindings/exception_state.h",
"third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h",
])
(header_forward_decls, header_include_headers, source_forward_decls,
source_include_headers) = collect_forward_decls_and_include_headers(
- map(lambda member: member.idl_type, dictionary.own_members))
+ list(map(lambda member: member.idl_type, dictionary.own_members)))
header_node.accumulator.add_class_decls(header_forward_decls)
header_node.accumulator.add_include_headers(header_include_headers)
source_node.accumulator.add_class_decls(source_forward_decls)
source_node.accumulator.add_include_headers(source_include_headers)
header_blink_ns.body.append(class_def)
- class_def.public_section.extend([
- create_decl,
- constructor_decls,
- destructor_decl,
- TextNode(""),
- trace_decl,
- TextNode(""),
- member_accessor_decls,
- ])
- class_def.protected_section.extend([
- fill_with_members_decl,
- TextNode(""),
- fill_members_internal_decl,
- ])
- class_def.private_section.extend([
- get_v8_member_names_decl,
- TextNode(""),
- fill_with_own_members_decl,
- TextNode(""),
- fill_members_decl,
- TextNode(""),
- member_value_var_defs,
- TextNode(""),
- member_presense_var_defs,
- ])
- source_blink_ns.body.extend([
- constructor_defs,
- TextNode(""),
- get_v8_member_names_def,
- TextNode(""),
- create_def,
- TextNode(""),
- fill_with_members_def,
- TextNode(""),
- fill_with_own_members_def,
- TextNode(""),
- fill_members_def,
- TextNode(""),
- fill_members_internal_def,
- TextNode(""),
- member_accessor_defs,
- TextNode(""),
- trace_def,
- ])
+ header_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(factory_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(factory_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(ctor_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(ctor_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(accessor_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(accessor_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(backward_compatible_accessor_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(backward_compatible_accessor_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(trace_func_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(trace_func_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.protected_section.append(blink_to_v8_decls)
+ class_def.protected_section.append(EmptyNode())
+ source_blink_ns.body.append(blink_to_v8_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.protected_section.append(v8_to_blink_decls)
+ class_def.protected_section.append(EmptyNode())
+ source_blink_ns.body.append(v8_to_blink_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.private_section.append(v8_names_decls)
+ class_def.private_section.append(EmptyNode())
+ source_blink_ns.body.append(v8_names_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.private_section.append(member_vars_def)
+ class_def.private_section.append(EmptyNode())
# Write down to the files.
write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py
index d547b649b75..69f00def6c3 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py
@@ -35,18 +35,27 @@ def make_factory_methods(cg_context):
T = TextNode
decls = ListNode()
+ defs = ListNode()
- func_def = CxxFuncDefNode(
- name="Create",
- arg_decls=[
- "v8::Isolate* isolate",
- "v8::Local<v8::Value> value",
- "ExceptionState& exception_state",
- ],
- return_type="${class_name}",
- static=True)
+ func_decl = CxxFuncDeclNode(name="Create",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> value",
+ "ExceptionState& exception_state",
+ ],
+ return_type="${class_name}",
+ static=True)
+ func_def = CxxFuncDefNode(name="Create",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> value",
+ "ExceptionState& exception_state",
+ ],
+ return_type="${class_name}",
+ class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
- decls.append(func_def)
+ decls.append(func_decl)
+ defs.append(func_def)
func_def.body.extend([
T("const auto& result = bindings::FindIndexInEnumStringTable("
@@ -57,12 +66,18 @@ def make_factory_methods(cg_context):
"${class_name}();"),
])
+ func_decl = CxxFuncDeclNode(name="Create",
+ arg_decls=["const String& value"],
+ return_type="absl::optional<${class_name}>",
+ static=True)
func_def = CxxFuncDefNode(name="Create",
arg_decls=["const String& value"],
return_type="absl::optional<${class_name}>",
- static=True)
+ class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
- decls.append(func_def)
+ decls.append(func_decl)
+ defs.append(EmptyNode())
+ defs.append(func_def)
func_def.body.extend([
T("const auto& result = bindings::FindIndexInEnumStringTable"
@@ -72,7 +87,19 @@ def make_factory_methods(cg_context):
T("return ${class_name}(static_cast<Enum>(result.value()));"),
])
- return decls, None
+ return decls, defs
+
+
+def make_default_constructor(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ func_decl = CxxFuncDeclNode(name=cg_context.class_name,
+ arg_decls=[],
+ return_type="",
+ constexpr=True,
+ default=True)
+
+ return func_decl, None
def make_constructors(cg_context):
@@ -83,12 +110,6 @@ def make_constructors(cg_context):
class_name = cg_context.class_name
decls = ListNode([
- CxxFuncDeclNode(
- name=class_name,
- arg_decls=[],
- return_type="",
- constexpr=True,
- default=True),
CxxFuncDefNode(
name=class_name,
arg_decls=["Enum value"],
@@ -219,18 +240,23 @@ def make_nested_enum_class_def(cg_context):
def make_enum_string_table(cg_context):
assert isinstance(cg_context, CodeGenContext)
+ decls = TextNode("static const char* const string_table_[];")
+
str_values = [
TextNode("\"{}\"".format(value))
for value in cg_context.enumeration.values
]
- decls = ListNode([
- TextNode("static constexpr const char* const string_table_[] = {"),
+ # Define the string table in *.cc so that there never exists a copy of
+ # the table (i.e. the strings in the table are interned strings in the
+ # scope of this IDL enumeration). This trick makes it possible to compare
+ # the strings by their address.
+ defs = ListNode([
+ TextNode("constexpr const char* const "
+ "${class_name}::string_table_[] = {"),
ListNode(str_values, separator=", "),
TextNode("};"),
])
-
- defs = TextNode("const char* const ${class_name}::string_table_[];")
defs.set_base_template_vars(cg_context.template_bindings())
return decls, defs
@@ -281,6 +307,8 @@ def generate_enumeration(enumeration_identifier):
# Implementation parts
factory_decls, factory_defs = make_factory_methods(cg_context)
+ default_ctor_decls, default_ctor_defs = make_default_constructor(
+ cg_context)
ctor_decls, ctor_defs = make_constructors(cg_context)
assign_decls, assign_defs = make_assignment_operators(cg_context)
equal_decls, equal_defs = make_equality_operators(cg_context)
@@ -318,11 +346,17 @@ def generate_enumeration(enumeration_identifier):
])
# Assemble the parts.
+ header_node.accumulator.add_class_decls([
+ "ExceptionState",
+ ])
header_node.accumulator.add_include_headers([
component_export_header(api_component, for_testing),
- "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
+ "third_party/abseil-cpp/absl/types/optional.h",
"third_party/blink/renderer/platform/bindings/enumeration_base.h",
])
+ source_node.accumulator.add_include_headers([
+ "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
+ ])
header_blink_ns.body.append(class_def)
header_blink_ns.body.append(EmptyNode())
@@ -330,14 +364,19 @@ def generate_enumeration(enumeration_identifier):
class_def.public_section.append(nested_enum_class_def)
class_def.public_section.append(EmptyNode())
+ class_def.private_section.append(table_decls)
+ class_def.private_section.append(EmptyNode())
+ source_blink_ns.body.append(table_defs)
+ source_blink_ns.body.append(EmptyNode())
+
class_def.public_section.append(factory_decls)
class_def.public_section.append(EmptyNode())
source_blink_ns.body.append(factory_defs)
source_blink_ns.body.append(EmptyNode())
- class_def.private_section.append(table_decls)
+ class_def.private_section.append(default_ctor_decls)
class_def.private_section.append(EmptyNode())
- source_blink_ns.body.append(table_defs)
+ source_blink_ns.body.append(default_ctor_defs)
source_blink_ns.body.append(EmptyNode())
class_def.public_section.append(ctor_decls)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index ddf6e213ef5..2585390f470 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -9,11 +9,13 @@ import web_idl
from . import name_style
from .blink_v8_bridge import blink_class_name
from .blink_v8_bridge import blink_type_info
+from .blink_v8_bridge import make_default_value_expr
from .blink_v8_bridge import make_v8_to_blink_value
from .blink_v8_bridge import make_v8_to_blink_value_variadic
from .blink_v8_bridge import native_value_tag
from .blink_v8_bridge import v8_bridge_class_name
from .code_node import EmptyNode
+from .code_node import FormatNode
from .code_node import ListNode
from .code_node import SequenceNode
from .code_node import SymbolDefinitionNode
@@ -96,9 +98,25 @@ def backward_compatible_api_func(cg_context):
def callback_function_name(cg_context,
overload_index=None,
+ argument_count=None,
for_cross_origin=False):
+ """
+ Args:
+ cg_context: A CodeGenContext of the target IDL construct.
+ overload_index: An overload index if the target is an overloaded
+ IDL operation.
+ argument_count: When the target is an IDL operation that has optional
+ arguments and is annotated with [NoAllocDirectCall], the value is
+ the number of arguments that V8 passes in (excluding the fixed
+ arguments like the receiver object and the
+ v8::FastApiCallbackOptions.)
+ for_cross_origin: True if the target is the cross origin accessible
+ version.
+ """
+
assert isinstance(cg_context, CodeGenContext)
assert overload_index is None or isinstance(overload_index, int)
+ assert argument_count is None or isinstance(argument_count, int)
assert isinstance(for_cross_origin, bool)
def _cxx_name(name):
@@ -149,14 +167,24 @@ def callback_function_name(cg_context,
elif cg_context.stringifier:
kind = "Operation"
+ if cg_context.no_alloc_direct_call:
+ nadc = "NoAllocDirectCall"
+ elif cg_context.no_alloc_direct_call_for_testing:
+ nadc = "NoAllocDirectCallForTesting"
+ else:
+ nadc = ""
+
+ overload = ""
+ if overload_index is not None and (len(cg_context.constructor_group
+ or cg_context.operation_group) > 1):
+ overload += "Overload{}".format(overload_index + 1)
+ if argument_count is not None:
+ overload += "Arg{}".format(argument_count)
+
if for_cross_origin:
suffix = "CrossOrigin"
- elif overload_index is not None:
- suffix = "Overload{}".format(overload_index + 1)
- elif cg_context.no_alloc_direct_call:
- suffix = "NoAllocDirectCallCallback"
- elif cg_context.no_alloc_direct_call_for_testing:
- suffix = "NoAllocDirectCallForTestingCallback"
+ elif nadc or overload:
+ suffix = nadc + overload
else:
suffix = "Callback"
@@ -220,9 +248,9 @@ def bind_blink_api_arguments(code_node, cg_context):
// https://heycam.github.io/webidl/#dfn-attribute-setter
// step 4.6.1. Let S be ? ToString(V).
const auto&& arg1_value_string =
- NativeValueTraits<IDLStringV2>::NativeValue(
+ NativeValueTraits<IDLString>::NativeValue(
${isolate}, ${v8_property_value}, ${exception_state});
-if (${exception_state}.HadException())
+if (UNLIKELY(${exception_state}.HadException()))
return;
// step 4.6.2. If S is not one of the enumeration's values, then return
// undefined.
@@ -272,7 +300,7 @@ def bind_callback_local_vars(code_node, cg_context):
S = SymbolNode
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
local_vars = []
template_vars = {}
@@ -460,22 +488,23 @@ def bind_callback_local_vars(code_node, cg_context):
S("v8_receiver",
"v8::Local<v8::Object> ${v8_receiver} = ${info}.Holder();"))
- def create_definition_of_v8_return_value(symbol_node):
- # TODO(crbug.com/1186968): Write condition directly in cond=T()
- condition = _format(
- "!ToV8Traits<{}>::ToV8(${script_state}, ${return_value})"
- ".ToLocal(&${v8_return_value})",
- native_value_tag(cg_context.return_type))
- return SymbolDefinitionNode(symbol_node, [
- T("v8::Local<v8::Value> ${v8_return_value};"),
- CxxUnlikelyIfNode(cond=T(condition), body=T("return;"))
- ])
-
# v8_return_value
- if cg_context.return_type and not cg_context.return_type.unwrap().is_void:
- local_vars.append(
- S("v8_return_value",
- definition_constructor=create_definition_of_v8_return_value))
+ def create_v8_return_value(symbol_node):
+ return SymbolDefinitionNode(
+ symbol_node,
+ [
+ T("v8::Local<v8::Value> ${v8_return_value};"),
+ CxxUnlikelyIfNode( #
+ cond=F(
+ "!ToV8Traits<{}>::ToV8"
+ "(${script_state}, ${return_value})"
+ ".ToLocal(&${v8_return_value})",
+ native_value_tag(cg_context.return_type)),
+ body=T("return;")),
+ ])
+
+ local_vars.append(
+ S("v8_return_value", definition_constructor=create_v8_return_value))
# throw_security_error
template_vars["throw_security_error"] = T(
@@ -566,7 +595,7 @@ def _make_reflect_process_keyword_state(cg_context):
assert cg_context.attribute_get or cg_context.attribute_set
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
if not cg_context.attribute_get:
return None
@@ -676,9 +705,6 @@ def _make_blink_api_call(code_node,
name = name_style.arg_f("arg{}_{}", index + 1, argument.identifier)
arguments.append(_format("${{{}}}", name))
- if cg_context.is_return_by_argument:
- arguments.append("${return_value}")
-
if cg_context.may_throw_exception:
arguments.append("${exception_state}")
@@ -727,7 +753,7 @@ def bind_return_value(code_node, cg_context, overriding_args=None):
and all(isinstance(arg, str) for arg in overriding_args)))
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
def create_definition(symbol_node):
api_calls = [] # Pairs of (num_of_args, api_call_text)
@@ -759,9 +785,6 @@ def bind_return_value(code_node, cg_context, overriding_args=None):
_, api_call = api_calls[0]
if is_return_type_void:
nodes.append(F("{};", api_call))
- elif cg_context.is_return_by_argument:
- nodes.append(F("{} ${return_value};", return_type))
- nodes.append(F("{};", api_call))
elif "ReflectOnly" in cg_context.member_like.extended_attributes:
# [ReflectOnly]
nodes.append(F("auto ${return_value} = {};", api_call))
@@ -770,7 +793,7 @@ def bind_return_value(code_node, cg_context, overriding_args=None):
else:
branches = SequenceNode()
for index, api_call in api_calls:
- if is_return_type_void or cg_context.is_return_by_argument:
+ if is_return_type_void:
assignment = "{};".format(api_call)
else:
assignment = _format("${return_value} = {};", api_call)
@@ -794,7 +817,7 @@ def bind_return_value(code_node, cg_context, overriding_args=None):
if cg_context.may_throw_exception:
nodes.append(
CxxUnlikelyIfNode(
- cond="${exception_state}.HadException()",
+ cond="UNLIKELY(${exception_state}.HadException())",
body=T("return;")))
if "ReflectOnly" in cg_context.member_like.extended_attributes:
@@ -830,7 +853,7 @@ def make_check_argument_length(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
if cg_context.v8_callback_type != CodeGenContext.V8_FUNCTION_CALLBACK:
return None
@@ -1161,8 +1184,9 @@ def _make_overload_dispatcher_per_arg_size(cg_context, items):
dispatch_if("{value}->IsDataView()")
# 12.7. if Type(V) is Object, V has a [[TypedArrayName]] internal slot, ...
- typed_array_types = ("Int8Array", "Int16Array", "Int32Array", "Uint8Array",
- "Uint16Array", "Uint32Array", "Uint8ClampedArray",
+ typed_array_types = ("Int8Array", "Int16Array", "Int32Array",
+ "BigInt64Array", "Uint8Array", "Uint16Array",
+ "Uint32Array", "BigUint64Array", "Uint8ClampedArray",
"Float32Array", "Float64Array")
for typed_array_type in typed_array_types:
func_like = find(lambda t, u: u.keyword_typename == typed_array_type)
@@ -1181,8 +1205,9 @@ def _make_overload_dispatcher_per_arg_size(cg_context, items):
"bindings::IsEsIterableObject"
"(${isolate}, {value}, ${exception_state})")
dispatcher_nodes.append(
- CxxUnlikelyIfNode(cond="${exception_state}.HadException()",
- body=TextNode("return;")))
+ CxxUnlikelyIfNode(
+ cond="UNLIKELY(${exception_state}.HadException())",
+ body=TextNode("return;")))
# 12.10. if Type(V) is Object and ...
func_like = find(lambda t, u: u.is_callback_interface or u.is_dictionary or
@@ -1226,7 +1251,7 @@ def make_overload_dispatcher(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
overload_group = cg_context.property_
items = overload_group.effective_overload_set()
@@ -1574,7 +1599,7 @@ def make_v8_set_return_value(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
if cg_context.does_override_idl_return_type:
return T("bindings::V8SetReturnValue(${info}, ${return_value});")
@@ -1663,8 +1688,6 @@ def make_v8_set_return_value(cg_context):
"bindings::V8ReturnValue::PrimitiveType<{cxx_type}>());",
cxx_type=cxx_type)
- # TODO(yukishiino): Remove |return_type_body.is_enumeration| below once
- # the migration from String to V8Enum type is done.
if return_type_body.is_string or return_type_body.is_enumeration:
args = ["${info}", "${return_value}", "${isolate}"]
if return_type.is_nullable:
@@ -1686,18 +1709,6 @@ def make_v8_set_return_value(cg_context):
args.append("${blink_receiver}")
return T("bindings::V8SetReturnValue({});".format(", ".join(args)))
- if return_type.is_any:
- return T("bindings::V8SetReturnValue(${info}, ${return_value});")
-
- if return_type.is_object:
- return T("bindings::V8SetReturnValue("
- "${info}, "
- "${return_value}, "
- "bindings::V8ReturnValue::kIDLObject);")
-
- if return_type.is_dictionary:
- return T("bindings::V8SetReturnValue(${info}, ${return_value});")
-
if return_type.is_promise:
return T("bindings::V8SetReturnValue"
"(${info}, ${return_value}.V8Value());")
@@ -2193,13 +2204,73 @@ v8_private_named_constructor.Set(${v8_receiver}, v8_value);
return SequenceNode([named_ctor_def, EmptyNode(), func_def])
-def make_no_alloc_direct_call_callback_def(cg_context, function_name):
+def list_no_alloc_direct_call_callbacks(cg_context):
+ """
+ Returns a list of [NoAllocDirectCall] callback functions to be registered
+ at V8, including all overloaded operations annotated with
+ [NoAllocDirectCall] and their variants of optional arguments.
+
+ Example:
+ Given the following Web IDL fragments,
+ void f(DOMString); // (a)
+ [NoAllocDirectCall] void f(Node node); // (b)
+ [NoAllocDirectCall] void f(optional long a, optional long b); // (c)
+ the following callback functions should be generated,
+ void F(v8::Local<v8::Value> node); // (b)
+ void F(); // (c)
+ void F(int32_t a); // (c)
+ void F(int32_t a, int32_t b); // (c)
+ thus the following entries are returned.
+ [
+ Entry(operation=(b), argument_count=1), # overload_index=2
+ Entry(operation=(c), argument_count=2), # overload_index=3
+ Entry(operation=(c), argument_count=1), # overload_index=3
+ Entry(operation=(c), argument_count=0), # overload_index=3
+ ]
+ """
+ assert isinstance(cg_context, CodeGenContext)
+
+ class Entry(object):
+ def __init__(self, operation, argument_count):
+ self.operation = operation
+ self.argument_count = argument_count
+ self.callback_name = callback_function_name(
+ cg_context,
+ overload_index=self.operation.overload_index,
+ argument_count=self.argument_count)
+
+ entries = []
+ for operation in cg_context.operation_group:
+ if "NoAllocDirectCall" not in operation.extended_attributes:
+ continue
+ for argument in reversed(operation.arguments):
+ entries.append(Entry(operation, argument.index + 1))
+ if not argument.is_optional:
+ break
+ else:
+ entries.append(Entry(operation, 0))
+ return entries
+
+
+def make_no_alloc_direct_call_callback_def(cg_context, function_name,
+ argument_count):
+ """
+ Args:
+ cg_context: A CodeGenContext of the target IDL construct.
+ function_name: The function name to be produced.
+ argument_count: The number of arguments that the produced function
+ takes, which may be different from the number of arguments of
+ the target cg_context.function_like due to optional arguments.
+ """
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
+ assert isinstance(argument_count, int)
S = SymbolNode
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
+
+ function_like = cg_context.function_like
class ArgumentInfo(object):
def __init__(self, v8_type, v8_arg_name, blink_arg_name, symbol_node):
@@ -2222,7 +2293,9 @@ def make_no_alloc_direct_call_callback_def(cg_context, function_name):
"auto&& {} = {};".format(blink_arg_name, v8_arg_name)))
arg_list = []
- for argument in cg_context.operation.arguments:
+ for argument in function_like.arguments:
+ if not (argument.index < argument_count):
+ break
blink_arg_name = name_style.arg_f("arg{}_{}", argument.index + 1,
argument.identifier)
v8_arg_name = name_style.arg_f("v8_arg{}_{}", argument.index + 1,
@@ -2232,12 +2305,12 @@ def make_no_alloc_direct_call_callback_def(cg_context, function_name):
arg_list.append(
ArgumentInfo(v8_type, v8_arg_name, blink_arg_name, symbol_node))
- arg_decls = (["v8::Local<v8::Object> v8_arg0_receiver"] +
- map(lambda arg: "{} {}".format(arg.v8_type, arg.v8_arg_name),
- arg_list) +
+ arg_decls = (["v8::Local<v8::Object> v8_arg0_receiver"] + list(
+ map(lambda arg: "{} {}".format(arg.v8_type, arg.v8_arg_name),
+ arg_list)) +
["v8::FastApiCallbackOptions& v8_arg_callback_options"])
- return_type = ("void" if cg_context.operation.return_type.is_void else
- blink_type_info(cg_context.operation.return_type).value_t)
+ return_type = ("void" if function_like.return_type.is_void else
+ blink_type_info(function_like.return_type).value_t)
func_def = CxxFuncDefNode(name=function_name,
arg_decls=arg_decls,
@@ -2266,9 +2339,6 @@ def make_no_alloc_direct_call_callback_def(cg_context, function_name):
body.extend([
T("ThreadState::NoAllocationScope "
"thread_no_alloc_scope(ThreadState::Current());"),
- T("v8::Isolate::DisallowJavascriptExecutionScope no_js_exec_scope("
- "${isolate}, "
- "v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);"),
T("blink::NoAllocDirectCallScope no_alloc_direct_call_scope("
"${blink_receiver}, &${v8_arg_callback_options});"),
EmptyNode(),
@@ -2276,6 +2346,20 @@ def make_no_alloc_direct_call_callback_def(cg_context, function_name):
blink_arguments = list(
map(lambda arg: "${{{}}}".format(arg.blink_arg_name), arg_list))
+ # If there are following optional arguments with default values, append
+ # them filled with the default values.
+ for argument in function_like.arguments[argument_count:]:
+ if not argument.default_value:
+ break
+ blink_arg_name = name_style.arg_f("arg{}_{}", argument.index + 1,
+ argument.identifier)
+ default_expr = make_default_value_expr(argument.idl_type,
+ argument.default_value)
+ body.register_code_symbol(
+ S((blink_arg_name),
+ "auto&& {}{{{}}};".format(blink_arg_name,
+ default_expr.initializer_expr)))
+ blink_arguments.append("${{{}}}".format(blink_arg_name))
if cg_context.may_throw_exception:
blink_arguments.append("${exception_state}")
body.append(
@@ -2284,8 +2368,9 @@ def make_no_alloc_direct_call_callback_def(cg_context, function_name):
blink_arguments=", ".join(blink_arguments)))
if cg_context.may_throw_exception:
body.append(
- CxxUnlikelyIfNode(cond="${exception_state}.HadException()",
- body=T("return;")))
+ CxxUnlikelyIfNode(
+ cond="UNLIKELY(${exception_state}.HadException())",
+ body=T("return;")))
return func_def
@@ -2316,7 +2401,7 @@ def make_no_alloc_direct_call_for_testing_call(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
if "NoAllocDirectCall" not in cg_context.operation.extended_attributes:
return None
@@ -2328,10 +2413,10 @@ def make_no_alloc_direct_call_for_testing_call(cg_context):
"v8::FastApiCallbackOptions ${v8_fast_api_callback_options}"
" = v8::FastApiCallbackOptions::CreateForTesting(${isolate});"))
scope.extend([
- F(
- "{}(${info}, ${v8_fast_api_callback_options});",
- callback_function_name(
- cg_context.make_copy(no_alloc_direct_call_for_testing=True))),
+ F(("{}(${info}, ${v8_fast_api_callback_options});"),
+ callback_function_name(
+ cg_context.make_copy(no_alloc_direct_call_for_testing=True),
+ overload_index=cg_context.operation.overload_index)),
CxxUnlikelyIfNode(cond="${blink_receiver}->HasDeferredActions()",
body=[
T("${blink_receiver}->FlushDeferredActions();"),
@@ -2343,6 +2428,7 @@ def make_no_alloc_direct_call_for_testing_call(cg_context):
return ListNode([
T("#if DCHECK_IS_ON()"),
+ T("// [NoAllocDirectCall]"),
CxxUnlikelyIfNode(cond=("RuntimeEnabledFeatures::"
"FakeNoAllocDirectCallForTestingEnabled()"),
body=scope),
@@ -2356,12 +2442,15 @@ def make_no_alloc_direct_call_flush_deferred_actions(cg_context):
if "NoAllocDirectCall" not in cg_context.operation.extended_attributes:
return None
- return CxxUnlikelyIfNode(
- cond="UNLIKELY(${blink_receiver}->HasDeferredActions())",
- body=[
- TextNode("${blink_receiver}->FlushDeferredActions();"),
- TextNode("return;"),
- ])
+ return SequenceNode([
+ TextNode("// [NoAllocDirectCall]"),
+ CxxUnlikelyIfNode(
+ cond="UNLIKELY(${blink_receiver}->HasDeferredActions())",
+ body=[
+ TextNode("${blink_receiver}->FlushDeferredActions();"),
+ TextNode("return;"),
+ ]),
+ ])
def make_operation_entry(cg_context):
@@ -2392,8 +2481,6 @@ def make_operation_function_def(cg_context, function_name):
make_report_measure_as(cg_context),
make_log_activity(cg_context),
EmptyNode(),
- make_no_alloc_direct_call_flush_deferred_actions(cg_context),
- EmptyNode(),
])
if "Custom" in cg_context.property_.extended_attributes:
@@ -2403,6 +2490,8 @@ def make_operation_function_def(cg_context, function_name):
return func_def
body.extend([
+ make_no_alloc_direct_call_flush_deferred_actions(cg_context),
+ EmptyNode(),
make_check_argument_length(cg_context),
EmptyNode(),
make_steps_of_ce_reactions(cg_context),
@@ -2417,9 +2506,7 @@ def make_operation_function_def(cg_context, function_name):
return func_def
-def make_operation_callback_def(cg_context,
- function_name,
- no_alloc_direct_callback_name=None):
+def make_operation_callback_def(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
@@ -2427,48 +2514,54 @@ def make_operation_callback_def(cg_context,
assert (not ("Custom" in operation_group.extended_attributes)
or len(operation_group) == 1)
- assert (not ("NoAllocDirectCall" in operation_group.extended_attributes)
- or len(operation_group) == 1)
+ nodes = SequenceNode()
if "NoAllocDirectCall" in operation_group.extended_attributes:
- nodes = ListNode()
- cgc = cg_context.make_copy(operation=operation_group[0],
- no_alloc_direct_call=True)
- nodes.extend([
- make_no_alloc_direct_call_callback_def(
- cgc, no_alloc_direct_callback_name),
- EmptyNode(),
- ])
- cgc = cg_context.make_copy(operation=operation_group[0],
- no_alloc_direct_call_for_testing=True)
- nodes.extend([
- make_no_alloc_direct_call_for_testing_callback_def(
- cgc, callback_function_name(cgc)),
- EmptyNode(),
- ])
- cgc = cg_context.make_copy(operation=operation_group[0])
- nodes.extend([
- make_operation_function_def(cgc, function_name),
- ])
- return nodes
+ for entry in list_no_alloc_direct_call_callbacks(cg_context):
+ cgc = cg_context.make_copy(operation=entry.operation,
+ no_alloc_direct_call=True)
+ nodes.extend([
+ make_no_alloc_direct_call_callback_def(
+ cgc,
+ callback_function_name(
+ cgc,
+ overload_index=entry.operation.overload_index,
+ argument_count=entry.argument_count),
+ argument_count=entry.argument_count),
+ EmptyNode(),
+ ])
+ for operation in operation_group:
+ if "NoAllocDirectCall" not in operation.extended_attributes:
+ continue
+ cgc = cg_context.make_copy(operation=operation,
+ no_alloc_direct_call_for_testing=True)
+ nodes.extend([
+ make_no_alloc_direct_call_for_testing_callback_def(
+ cgc,
+ callback_function_name(
+ cgc, overload_index=operation.overload_index)),
+ EmptyNode(),
+ ])
if len(operation_group) == 1:
- return make_operation_function_def(
- cg_context.make_copy(operation=operation_group[0]), function_name)
+ nodes.append(
+ make_operation_function_def(
+ cg_context.make_copy(operation=operation_group[0]),
+ function_name))
+ return nodes
- node = SequenceNode()
for operation in operation_group:
cgc = cg_context.make_copy(operation=operation)
- node.extend([
+ nodes.extend([
make_operation_function_def(
cgc,
callback_function_name(
cgc, overload_index=operation.overload_index)),
EmptyNode(),
])
- node.append(
+ nodes.append(
make_overload_dispatcher_function_def(cg_context, function_name))
- return node
+ return nodes
def make_stringifier_callback_def(cg_context, function_name):
@@ -3094,7 +3187,7 @@ ExceptionState exception_state(${info}.GetIsolate(),
"${interface.identifier}");
bool does_exist = ${blink_receiver}->NamedPropertyQuery(
${blink_property_name}, exception_state);
-if (exception_state.HadException())
+if (UNLIKELY(exception_state.HadException()))
return;
if (does_exist) {
bindings::V8SetReturnValue(${info}, false);
@@ -3379,7 +3472,7 @@ ExceptionState exception_state(${info}.GetIsolate(),
"${interface.identifier}");
${blink_receiver}->NamedPropertyEnumerator(
blink_property_names, exception_state);
-if (exception_state.HadException())
+if (UNLIKELY(exception_state.HadException()))
return;
bindings::V8SetReturnValue(
${info},
@@ -4642,13 +4735,6 @@ def _make_property_entry_receiver_check(property_):
return "unsigned(IDLMemberInstaller::FlagReceiverCheck::kCheck)"
-def _make_property_entry_v8_c_function(entry):
- if entry.no_alloc_direct_callback_name is None:
- return None
- return "v8::CFunction::MakeWithFallbackSupport({})".format(
- entry.no_alloc_direct_callback_name)
-
-
def _make_property_entry_v8_cached_accessor(property_):
return "unsigned(V8PrivateProperty::CachedAccessor::{})".format(
property_.extended_attributes.value_of("CachedAccessor") or "kNone")
@@ -4671,10 +4757,23 @@ def _make_property_entry_v8_property_attribute(property_):
def _make_property_entry_v8_side_effect(property_):
- if property_.extended_attributes.value_of("Affects") == "Nothing":
+ value = property_.extended_attributes.value_of("Affects")
+ if value:
+ if value == "Everything":
+ return "unsigned(v8::SideEffectType::kHasSideEffect)"
+ elif value == "Nothing":
+ return "unsigned(v8::SideEffectType::kHasNoSideEffect)"
+ else:
+ assert False
+ elif isinstance(property_, web_idl.Attribute):
return "unsigned(v8::SideEffectType::kHasNoSideEffect)"
- else:
+ elif isinstance(property_, web_idl.Operation):
+ assert property_.identifier == "toString"
+ # The stringifier should have no side effect.
+ return "unsigned(v8::SideEffectType::kHasNoSideEffect)"
+ elif isinstance(property_, web_idl.OperationGroup):
return "unsigned(v8::SideEffectType::kHasSideEffect)"
+ assert False
def _make_property_entry_world(world):
@@ -4696,20 +4795,20 @@ def _make_attribute_registration_table(table_name, attribute_entries):
T = TextNode
entry_nodes = []
+ pattern = ("{{"
+ "\"{property_name}\", "
+ "{attribute_get_callback}, "
+ "{attribute_set_callback}, "
+ "{v8_property_attribute}, "
+ "{location}, "
+ "{world}, "
+ "{receiver_check}, "
+ "{cross_origin_check_for_get}, "
+ "{cross_origin_check_for_set}, "
+ "{v8_side_effect}, "
+ "{v8_cached_accessor}"
+ "}},")
for entry in attribute_entries:
- pattern = ("{{"
- "\"{property_name}\", "
- "{attribute_get_callback}, "
- "{attribute_set_callback}, "
- "{v8_property_attribute}, "
- "{location}, "
- "{world}, "
- "{receiver_check}, "
- "{cross_origin_check_for_get}, "
- "{cross_origin_check_for_set}, "
- "{v8_side_effect}, "
- "{v8_cached_accessor}"
- "}},")
text = _format(
pattern,
property_name=entry.property_.identifier,
@@ -4752,8 +4851,12 @@ def _make_constant_callback_registration_table(table_name, constant_entries):
T = TextNode
entry_nodes = []
+ pattern = (
+ "{{" #
+ "\"{property_name}\", "
+ "{constant_callback}"
+ "}},")
for entry in constant_entries:
- pattern = ("{{" "\"{property_name}\", " "{constant_callback}" "}},")
text = _format(
pattern,
property_name=entry.property_.identifier,
@@ -4778,11 +4881,12 @@ def _make_constant_value_registration_table(table_name, constant_entries):
T = TextNode
entry_nodes = []
+ pattern = (
+ "{{" #
+ "\"{property_name}\", "
+ "{constant_value}"
+ "}},")
for entry in constant_entries:
- pattern = ("{{"
- "\"{property_name}\", "
- "{constant_value}"
- "}},")
text = _format(pattern,
property_name=entry.property_.identifier,
constant_value=entry.const_constant_name)
@@ -4833,30 +4937,51 @@ def _make_operation_registration_table(table_name, operation_entries):
for entry in operation_entries)
T = TextNode
+ F = FormatNode
- no_alloc_direct_call_count = 0
- for entry in operation_entries:
- if entry.no_alloc_direct_callback_name:
- no_alloc_direct_call_count += 1
+ no_alloc_direct_call_count = len(
+ list(
+ filter(lambda entry: entry.no_alloc_direct_call_callbacks,
+ operation_entries)))
assert (no_alloc_direct_call_count == 0
or no_alloc_direct_call_count == len(operation_entries))
- no_alloc_direct_call_enabled = no_alloc_direct_call_count > 0
+ no_alloc_direct_call_enabled = bool(no_alloc_direct_call_count)
entry_nodes = []
+ nadc_overload_nodes = ListNode()
+ pattern = ("{{"
+ "\"{property_name}\", "
+ "{operation_callback}, "
+ "{function_length}, "
+ "{v8_property_attribute}, "
+ "{location}, "
+ "{world}, "
+ "{receiver_check}, "
+ "{cross_origin_check}, "
+ "{v8_side_effect}"
+ "}}, ")
+ if no_alloc_direct_call_enabled:
+ pattern = ("{{" + pattern + "{v8_cfunction_table}, "
+ "base::size({v8_cfunction_table})}}, ")
for entry in operation_entries:
- pattern = ("{{"
- "\"{property_name}\", "
- "{operation_callback}, "
- "{function_length}, "
- "{v8_property_attribute}, "
- "{location}, "
- "{world}, "
- "{receiver_check}, "
- "{cross_origin_check}, "
- "{v8_side_effect}"
- "}}, ")
if no_alloc_direct_call_enabled:
- pattern = "{{" + pattern + "{v8_c_function}}}, "
+ nadc_overload_table_name = name_style.constant(
+ "no_alloc_direct_call_overloads_of_",
+ entry.property_.identifier)
+ nadc_overload_nodes.append(
+ ListNode([
+ T("static const v8::CFunction " +
+ nadc_overload_table_name + "[] = {"),
+ ListNode([
+ F("v8::CFunctionBuilder().Fn({}).Build(),",
+ nadc_entry.callback_name)
+ for nadc_entry in entry.no_alloc_direct_call_callbacks
+ ]),
+ T("};"),
+ ]))
+ else:
+ nadc_overload_table_name = None
+
text = _format(
pattern,
property_name=entry.property_.identifier,
@@ -4872,7 +4997,7 @@ def _make_operation_registration_table(table_name, operation_entries):
entry.property_),
v8_side_effect=_make_property_entry_v8_side_effect(
entry.property_),
- v8_c_function=_make_property_entry_v8_c_function(entry))
+ v8_cfunction_table=nadc_overload_table_name)
entry_nodes.append(T(text))
table_decl_before_name = (
@@ -4881,11 +5006,18 @@ def _make_operation_registration_table(table_name, operation_entries):
table_decl_before_name = (
"static const "
"IDLMemberInstaller::NoAllocDirectCallOperationConfig")
- return ListNode([
+ node = ListNode()
+ if nadc_overload_nodes:
+ node.extend([
+ nadc_overload_nodes,
+ EmptyNode(),
+ ])
+ node.extend([
T(table_decl_before_name + " " + table_name + "[] = {"),
ListNode(entry_nodes),
T("};"),
])
+ return node
class _PropEntryBase(object):
@@ -4954,7 +5086,7 @@ class _PropEntryOperationGroup(_PropEntryBase):
operation_group,
op_callback_name,
op_func_length,
- no_alloc_direct_callback_name=None):
+ no_alloc_direct_call_callbacks=None):
assert isinstance(op_callback_name, str)
assert isinstance(op_func_length, int)
@@ -4962,7 +5094,7 @@ class _PropEntryOperationGroup(_PropEntryBase):
exposure_conditional, world, operation_group)
self.op_callback_name = op_callback_name
self.op_func_length = op_func_length
- self.no_alloc_direct_callback_name = no_alloc_direct_callback_name
+ self.no_alloc_direct_call_callbacks = no_alloc_direct_call_callbacks
def make_property_entries_and_callback_defs(cg_context, attribute_entries,
@@ -5163,14 +5295,12 @@ def make_property_entries_and_callback_defs(cg_context, attribute_entries,
cgc = cg_context.make_copy(
operation_group=operation_group, for_world=world)
op_callback_name = callback_function_name(cgc)
- no_alloc_direct_callback_name = (
- callback_function_name(cgc.make_copy(no_alloc_direct_call=True))
+ op_callback_node = make_operation_callback_def(cgc, op_callback_name)
+ no_alloc_direct_call_callbacks = (
+ list_no_alloc_direct_call_callbacks(
+ cgc.make_copy(no_alloc_direct_call=True))
if "NoAllocDirectCall" in operation_group.extended_attributes else
None)
- op_callback_node = make_operation_callback_def(
- cgc,
- op_callback_name,
- no_alloc_direct_callback_name=no_alloc_direct_callback_name)
callback_def_nodes.extend([
op_callback_node,
@@ -5185,7 +5315,7 @@ def make_property_entries_and_callback_defs(cg_context, attribute_entries,
operation_group=operation_group,
op_callback_name=op_callback_name,
op_func_length=operation_group.min_num_of_required_arguments,
- no_alloc_direct_callback_name=no_alloc_direct_callback_name))
+ no_alloc_direct_call_callbacks=no_alloc_direct_call_callbacks))
def process_stringifier(_, is_context_dependent, exposure_conditional,
world):
@@ -5917,12 +6047,12 @@ ${instance_object} = ${v8_context}->Global()->GetPrototype().As<v8::Object>();\
install_func="IDLMemberInstaller::InstallOperations",
table_name=table_name)
entries = list(
- filter(lambda entry: not entry.no_alloc_direct_callback_name,
+ filter(lambda entry: not entry.no_alloc_direct_call_callbacks,
operation_entries))
install_properties(table_name, entries, _make_operation_registration_table,
installer_call_text)
entries = list(
- filter(lambda entry: entry.no_alloc_direct_callback_name,
+ filter(lambda entry: entry.no_alloc_direct_call_callbacks,
operation_entries))
install_properties(table_name, entries, _make_operation_registration_table,
installer_call_text)
@@ -5942,7 +6072,7 @@ def make_indexed_and_named_property_callbacks_and_install_node(cg_context):
assert isinstance(cg_context, CodeGenContext)
- F = lambda *args, **kwargs: TextNode(_format(*args, **kwargs))
+ F = FormatNode
func_decls = ListNode()
func_defs = ListNode()
@@ -5995,8 +6125,8 @@ def make_indexed_and_named_property_callbacks_and_install_node(cg_context):
flags = ["v8::PropertyHandlerFlags::kOnlyInterceptStrings"]
if "LegacyOverrideBuiltIns" not in interface.extended_attributes:
flags.append("v8::PropertyHandlerFlags::kNonMasking")
- if (props.named_getter.extended_attributes.value_of("Affects") ==
- "Nothing"):
+ if (props.named_getter.extended_attributes.value_of("Affects") !=
+ "Everything"):
flags.append("v8::PropertyHandlerFlags::kHasNoSideEffect")
property_handler_flags = (
"static_cast<v8::PropertyHandlerFlags>({})".format(" | ".join(
@@ -6054,8 +6184,9 @@ interface.indexed_and_named_properties.named_getter.extended_attributes:
props.named_setter and props.named_setter.owner,
props.named_deleter and props.named_deleter.owner))
flags = []
- if (props.indexed_getter and props.indexed_getter.extended_attributes.
- value_of("Affects") == "Nothing"):
+ if (props.indexed_getter and
+ props.indexed_getter.extended_attributes.value_of("Affects") !=
+ "Everything"):
flags.append("v8::PropertyHandlerFlags::kHasNoSideEffect")
else:
flags.append("v8::PropertyHandlerFlags::kNone")
@@ -6393,8 +6524,7 @@ def make_cross_component_init(
assert isinstance(has_context_independent_props, bool)
assert isinstance(has_context_dependent_props, bool)
- T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
def filter_four_trampolines(nodes):
assert len(nodes) == 4
@@ -6467,7 +6597,7 @@ def make_wrapper_type_info(cg_context, function_name,
assert function_name == "GetWrapperTypeInfo"
assert isinstance(has_context_dependent_props, bool)
- F = lambda *args, **kwargs: TextNode(_format(*args, **kwargs))
+ F = FormatNode
func_def = CxxFuncDefNode(
name=function_name,
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/package_initializer.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/package_initializer.py
index 863da3d56b1..64c93bd49ab 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/package_initializer.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/package_initializer.py
@@ -58,7 +58,7 @@ class PackageInitializer(object):
return cls._the_instance
def __init__(self, web_idl_database_path, root_src_dir, root_gen_dir,
- component_reldirs):
+ component_reldirs, enable_style_format):
"""
Args:
web_idl_database_path: File path to the web_idl.Database.
@@ -67,12 +67,15 @@ class PackageInitializer(object):
root_gen_dir: Root directory of generated files, which corresponds
to "//out/Default/gen" in GN.
component_reldirs: Pairs of component and output directory.
+ enable_style_format: Enable style formatting of the generated
+ files.
"""
self._web_idl_database_path = web_idl_database_path
self._root_src_dir = root_src_dir
self._root_gen_dir = root_gen_dir
self._component_reldirs = component_reldirs
+ self._enable_style_format = enable_style_format
def init(self):
if PackageInitializer._the_instance:
@@ -88,7 +91,8 @@ class PackageInitializer(object):
PackageInitializer._the_web_idl_database = (
web_idl.Database.read_from_file(self._web_idl_database_path))
- style_format.init(self._root_src_dir)
+ style_format.init(root_src_dir=self._root_src_dir,
+ enable_style_format=self._enable_style_format)
PathManager.init(
root_src_dir=self._root_src_dir,
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
index 4554237dad8..eaabacce65b 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
@@ -94,8 +94,7 @@ class PathManager(object):
components = sorted(idl_definition.components) # "core" < "modules"
if len(components) == 0:
- assert isinstance(idl_definition,
- (web_idl.Union, web_idl.NewUnion))
+ assert isinstance(idl_definition, web_idl.Union)
# Unions of built-in types, e.g. (double or DOMString), do not have
# a component.
self._is_cross_components = False
@@ -114,7 +113,7 @@ class PathManager(object):
# Union does not support cross-component code generation because
# clients of IDL union must be on an upper or same layer to any of
# union members.
- if isinstance(idl_definition, (web_idl.Union, web_idl.NewUnion)):
+ if isinstance(idl_definition, web_idl.Union):
self._api_component = components[1]
else:
self._api_component = components[0]
@@ -124,9 +123,7 @@ class PathManager(object):
self._api_dir = self._component_reldirs[self._api_component]
self._impl_dir = self._component_reldirs[self._impl_component]
- self._api_basename = name_style.file("v8", idl_definition.identifier)
- self._impl_basename = name_style.file("v8", idl_definition.identifier)
- if isinstance(idl_definition, web_idl.NewUnion):
+ if isinstance(idl_definition, web_idl.Union):
# In case of IDL unions, underscore is used as a separator of union
# members, so we don't want any underscore inside a union member.
# For example, (Foo or Bar or Baz) and (FooBar or Baz) are defined
@@ -139,17 +136,13 @@ class PathManager(object):
idl_definition.member_tokens)).lower()
self._api_basename = filename
self._impl_basename = filename
- elif isinstance(idl_definition, web_idl.Union):
- union_class_name = idl_definition.identifier
- union_filepath = _BACKWARD_COMPATIBLE_UNION_FILEPATHS.get(
- union_class_name, union_class_name)
- self._api_basename = name_style.file(union_filepath)
- self._impl_basename = name_style.file(union_filepath)
-
- if isinstance(idl_definition, (web_idl.Union, web_idl.NewUnion)):
self._blink_dir = None
self._blink_basename = None
else:
+ self._api_basename = name_style.file("v8",
+ idl_definition.identifier)
+ self._impl_basename = name_style.file("v8",
+ idl_definition.identifier)
idl_path = idl_definition.debug_info.location.filepath
self._blink_dir = posixpath.dirname(idl_path)
self._blink_basename = name_style.file(
@@ -202,36 +195,3 @@ class PathManager(object):
if ext is not None:
filename = posixpath.extsep.join([filename, ext])
return posixpath.join(dirpath, filename)
-
-
-# A hack to make the filepaths to generated IDL unions compatible with the old
-# bindings generator.
-#
-# Copied from |shorten_union_name| defined in
-# //third_party/blink/renderer/bindings/scripts/utilities.py
-_BACKWARD_COMPATIBLE_UNION_FILEPATHS = {
- # modules/canvas2d/CanvasRenderingContext2D.idl
- "CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvasOrVideoFrame":
- "CanvasImageSource",
- # modules/canvas/htmlcanvas/html_canvas_element_module.idl
- "CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext":
- "RenderingContext",
- # core/frame/window_or_worker_global_scope.idl
- "HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvasOrVideoFrame":
- "ImageBitmapSource",
- # bindings/tests/idls/core/TestTypedefs.idl
- "NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord":
- "NestedUnionType",
- # modules/canvas/offscreencanvas/offscreen_canvas_module.idl
- "OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext":
- "OffscreenRenderingContext",
- # core/xmlhttprequest/xml_http_request.idl
- "DocumentOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString":
- "DocumentOrXMLHttpRequestBodyInit",
- # modules/beacon/navigator_beacon.idl
- 'ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString':
- 'ReadableStreamOrXMLHttpRequestBodyInit',
- # modules/mediasource/source_buffer.idl
- 'EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk':
- 'EncodedAVChunkSequenceOrEncodedAVChunk',
-}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py
index 017d3d47bb3..a623fe1bc96 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py
@@ -6,17 +6,25 @@ import os.path
import subprocess
import sys
+_enable_style_format = None
_clang_format_command_path = None
_gn_command_path = None
-def init(root_src_dir):
+def init(root_src_dir, enable_style_format=True):
+ assert isinstance(root_src_dir, str)
+ assert isinstance(enable_style_format, bool)
+
+ global _enable_style_format
global _clang_format_command_path
global _gn_command_path
+ assert _enable_style_format is None
assert _clang_format_command_path is None
assert _gn_command_path is None
+ _enable_style_format = enable_style_format
+
root_src_dir = os.path.abspath(root_src_dir)
# Determine //buildtools/<platform>/ directory
@@ -70,6 +78,12 @@ def gn_format(contents, filename=None):
def _invoke_format_command(command_line, filename, contents):
+ if not _enable_style_format:
+ return StyleFormatResult(stdout_output=contents,
+ stderr_output="",
+ exit_code=0,
+ filename=filename)
+
kwargs = {}
if sys.version_info.major != 2:
kwargs['encoding'] = 'utf-8'
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/task_queue.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/task_queue.py
index 7532e2ce160..e06b401b0a0 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/task_queue.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/task_queue.py
@@ -70,7 +70,7 @@ class TaskQueue(object):
for index, task in enumerate(self._requested_tasks):
func, args, kwargs = task
report_progress(len(self._requested_tasks), index)
- apply(func, args, kwargs)
+ func(*args, **kwargs)
report_progress(len(self._requested_tasks), len(self._requested_tasks))
def _run_in_parallel(self, report_progress):
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/typedef.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/typedef.py
index 73180ad84db..3d9c00b0c51 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/typedef.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/typedef.py
@@ -31,7 +31,7 @@ def _make_typedefs_to_unions(typedefs, component_selector):
map(
lambda typedef: (blink_class_name(typedef),
blink_class_name(typedef.idl_type.
- new_union_definition_object)),
+ union_definition_object)),
filter(
lambda typedef: component_selector(
[typedef, typedef.idl_type.union_definition_object]),
@@ -59,7 +59,7 @@ def make_typedefs(typedefs, component_selector):
def _make_unions_of_typedefed_member_types(unions, component_selector):
assert isinstance(unions, (list, tuple))
- assert all(isinstance(union, web_idl.NewUnion) for union in unions)
+ assert all(isinstance(union, web_idl.Union) for union in unions)
assert callable(component_selector)
def union_name_of_typedefed_members(idl_type, union):
@@ -111,7 +111,7 @@ def _make_unions_of_typedefed_member_types(unions, component_selector):
def make_unions(unions, component_selector):
assert isinstance(unions, (list, tuple))
- assert all(isinstance(union, web_idl.NewUnion) for union in unions)
+ assert all(isinstance(union, web_idl.Union) for union in unions)
assert callable(component_selector)
return ListNode([
@@ -182,7 +182,7 @@ def generate_typedefs_all(filepath_basename):
EmptyNode(),
])
- all_unions = sorted(web_idl_database.new_union_types,
+ all_unions = sorted(web_idl_database.union_types,
key=lambda x: x.identifier)
for component in components:
header_blink_ns[component].body.extend([
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
index 8b3e236c7c7..4973cc52f3e 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
@@ -11,6 +11,7 @@ from .blink_v8_bridge import make_v8_to_blink_value
from .blink_v8_bridge import native_value_tag
from .blink_v8_bridge import v8_bridge_class_name
from .code_node import EmptyNode
+from .code_node import FormatNode
from .code_node import ListNode
from .code_node import SequenceNode
from .code_node import SymbolDefinitionNode
@@ -42,6 +43,14 @@ from .task_queue import TaskQueue
class _UnionMember(object):
+ """
+ _UnionMember represents the properties that the code generator directly
+ needs while web_idl.Union represents properties of IDL union independent
+ from ECMAScript binding. _UnionMember is specific to not only ECMAScript
+ binding but also Blink implementation of IDL union and its flattened member
+ types.
+ """
+
def __init__(self, base_name):
assert isinstance(base_name, str)
@@ -98,8 +107,16 @@ class _UnionMember(object):
class _UnionMemberImpl(_UnionMember):
+ """
+ Represents a flattened member type of an union type or the special null
+ type, which represents that the union type includes a nullable type.
+
+ For example, either of (A? or B) or (A or B?) is represented as a list of
+ [_UnionMemberImpl(A), _UnionMemberImpl(B), _UnionMemberImpl(null)].
+ """
+
def __init__(self, union, idl_type):
- assert isinstance(union, web_idl.NewUnion)
+ assert isinstance(union, web_idl.Union)
assert idl_type is None or isinstance(idl_type, web_idl.IdlType)
if idl_type is None:
@@ -120,13 +137,24 @@ class _UnionMemberImpl(_UnionMember):
class _UnionMemberSubunion(_UnionMember):
+ """
+ Represents a subset of flattened member types in an union type as
+ 'subunion'.
+
+ For example, given an union type X = (A or B or C) with the following use
+ cases,
+ ((A or B) or C)
+ (A or (B or C))
+ subunions of the union type X are represented as
+ [_UnionMemberSubunion(A or B), _UnionMemberSubunion(B or C)].
+ """
+
def __init__(self, union, subunion):
- assert isinstance(union, web_idl.NewUnion)
- assert isinstance(subunion, web_idl.NewUnion)
+ assert isinstance(union, web_idl.Union)
+ assert isinstance(subunion, web_idl.Union)
_UnionMember.__init__(self, base_name=blink_class_name(subunion))
- self._type_info = blink_type_info(subunion.idl_types[0],
- use_new_union=True)
+ self._type_info = blink_type_info(subunion.idl_types[0])
self._typedef_aliases = tuple(
map(lambda typedef: _UnionMemberAlias(impl=self, typedef=typedef),
subunion.aliasing_typedefs))
@@ -138,17 +166,29 @@ class _UnionMemberSubunion(_UnionMember):
class _UnionMemberAlias(_UnionMember):
+ """
+ Represents a typedef'ed aliases to a flattened member type or subunion of
+ an union type.
+
+ For example, given the following Web IDL fragments,
+ typedef (A or B) T1;
+ typedef B T2;
+ (T1 or C)
+ _UnionMemberAlias(T1) represents an alias to _UnionMemberSubunion(A or B)
+ and _UnionMemberAlias(T2) represents an alias to _UnionMemberImpl(B).
+ """
+
def __init__(self, impl, typedef):
assert isinstance(impl, (_UnionMemberImpl, _UnionMemberSubunion))
assert isinstance(typedef, web_idl.Typedef)
- _UnionMember.__init__(self, base_name=typedef.identifier)
+ _UnionMember.__init__(self, base_name=blink_class_name(typedef))
self._var_name = impl.var_name
self._type_info = impl.type_info
def create_union_members(union):
- assert isinstance(union, web_idl.NewUnion)
+ assert isinstance(union, web_idl.Union)
union_members = list(map(
lambda member_type: _UnionMemberImpl(union, member_type),
@@ -195,7 +235,7 @@ def make_factory_methods(cg_context):
S = SymbolNode
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
func_decl = CxxFuncDeclNode(name="Create",
arg_decls=[
@@ -336,8 +376,9 @@ def make_factory_methods(cg_context):
# then:
# 8.1. If types includes a typed array type whose name is the value of V's
# [[TypedArrayName]] internal slot, ...
- typed_array_types = ("Int8Array", "Int16Array", "Int32Array", "Uint8Array",
- "Uint16Array", "Uint32Array", "Uint8ClampedArray",
+ typed_array_types = ("Int8Array", "Int16Array", "Int32Array",
+ "BigInt64Array", "Uint8Array", "Uint16Array",
+ "Uint32Array", "BigUint64Array", "Uint8ClampedArray",
"Float32Array", "Float64Array")
for typed_array_type in typed_array_types:
member = find_by_type(lambda t: t.keyword_typename == typed_array_type)
@@ -372,8 +413,9 @@ def make_factory_methods(cg_context):
T("ScriptIterator script_iterator = ScriptIterator::FromIterable("
"${isolate}, ${v8_value}.As<v8::Object>(), "
"${exception_state});"),
- CxxUnlikelyIfNode(cond="${exception_state}.HadException()",
- body=T("return nullptr;")),
+ CxxUnlikelyIfNode(
+ cond="UNLIKELY(${exception_state}.HadException())",
+ body=T("return nullptr;")),
])
def blink_value_from_iterator(union_member):
@@ -386,8 +428,9 @@ def make_factory_methods(cg_context):
"${exception_state});"),
native_value_tag(
union_member.idl_type.unwrap().element_type)),
- CxxUnlikelyIfNode(cond="${exception_state}.HadException()",
- body=T("return nullptr;")),
+ CxxUnlikelyIfNode(
+ cond="UNLIKELY(${exception_state}.HadException())",
+ body=T("return nullptr;")),
])
return node
@@ -543,16 +586,11 @@ def make_accessor_functions(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
- F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+ F = FormatNode
decls = ListNode()
defs = ListNode()
- def add(func_decl, func_def):
- decls.append(func_decl)
- defs.append(func_def)
- defs.append(EmptyNode())
-
func_def = CxxFuncDefNode(name="GetContentType",
arg_decls=[],
return_type="ContentType",
@@ -651,23 +689,6 @@ def make_accessor_functions(cg_context):
])
return func_def, None
- for member in cg_context.union_members:
- if member.is_null:
- add(*make_api_pred(member))
- add(*make_api_set_null(member))
- else:
- add(*make_api_pred(member))
- for alias in member.typedef_aliases:
- add(*make_api_pred(alias))
- add(*make_api_get(member))
- for alias in member.typedef_aliases:
- add(*make_api_get(alias))
- if member.type_info.is_move_effective:
- add(*make_api_set_copy_and_move(member))
- else:
- add(*make_api_set(member))
- decls.append(EmptyNode())
-
def make_api_subunion_pred(subunion, subunion_members):
func_def = CxxFuncDefNode(name=subunion.api_pred,
arg_decls=[],
@@ -724,12 +745,56 @@ def make_accessor_functions(cg_context):
func_def.body.append(node)
return func_decl, func_def
+ def make_api_subunion_alias_pred(subunion, alias):
+ func_def = CxxFuncDefNode(name=alias.api_pred,
+ arg_decls=[],
+ return_type="bool",
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(F("return {}();", subunion.api_pred))
+ return func_def, None
+
+ def make_api_subunion_alias_get(subunion, alias):
+ func_def = CxxFuncDefNode(name=alias.api_get,
+ arg_decls=[],
+ return_type=alias.type_info.value_t,
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(F("return {}();", subunion.api_get))
+ return func_def, None
+
+ def add(func_decl, func_def):
+ decls.append(func_decl)
+ defs.append(func_def)
+ defs.append(EmptyNode())
+
+ # Accessors to member types of the union type
+ for member in cg_context.union_members:
+ if member.is_null:
+ add(*make_api_pred(member))
+ add(*make_api_set_null(member))
+ else:
+ add(*make_api_pred(member))
+ add(*make_api_get(member))
+ if member.type_info.is_move_effective:
+ add(*make_api_set_copy_and_move(member))
+ else:
+ add(*make_api_set(member))
+ for alias in member.typedef_aliases:
+ add(*make_api_pred(alias))
+ add(*make_api_get(alias))
+ decls.append(EmptyNode())
+
+ # Accessors to subunions in the union type
for subunion in cg_context.union.union_members:
subunion_members = create_union_members(subunion)
subunion = _UnionMemberSubunion(cg_context.union, subunion)
add(*make_api_subunion_pred(subunion, subunion_members))
add(*make_api_subunion_get(subunion, subunion_members))
add(*make_api_subunion_set(subunion, subunion_members))
+ for alias in subunion.typedef_aliases:
+ add(*make_api_subunion_alias_pred(subunion, alias))
+ add(*make_api_subunion_alias_get(subunion, alias))
decls.append(EmptyNode())
return decls, defs
@@ -855,11 +920,20 @@ def make_member_vars_def(cg_context):
EmptyNode(),
])
- entries = [
- "{} {};".format(member.type_info.member_t, member.var_name)
- for member in cg_context.union_members if not member.is_null
- ]
- member_vars_def.extend(map(TextNode, entries))
+ for member in cg_context.union_members:
+ if member.is_null:
+ continue
+ if member.idl_type.is_enumeration:
+ # Since the IDL enumeration class is not default constructible,
+ # construct the IDL enumeration with 0th enum value. Note that
+ # this is necessary only for compilation, and the value must never
+ # be used due to the guard by `content_type_`.
+ pattern = "{} {}{{static_cast<{}::Enum>(0)}};"
+ else:
+ pattern = "{} {};"
+ node = FormatNode(pattern, member.type_info.member_t, member.var_name,
+ member.type_info.value_t)
+ member_vars_def.append(node)
return member_vars_def
@@ -1033,5 +1107,5 @@ def generate_unions(task_queue):
web_idl_database = package_initializer().web_idl_database()
- for union in web_idl_database.new_union_types:
+ for union in web_idl_database.union_types:
task_queue.post_task(generate_union, union.identifier)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py b/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py
deleted file mode 100644
index 86e651da75c..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py
+++ /dev/null
@@ -1,265 +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.
-
-# pylint: disable=import-error,print-statement,relative-import
-"""Plumbing for a Jinja-based code generator, including CodeGeneratorBase, a base class for all generators."""
-
-from __future__ import print_function
-
-import os
-import posixpath
-import re
-import sys
-
-from idl_types import set_ancestors, IdlType
-from itertools import groupby
-from v8_globals import includes
-from v8_interface import constant_filters
-from v8_types import set_component_dirs
-from v8_methods import method_filters
-from v8_utilities import capitalize
-from utilities import (idl_filename_to_component,
- is_valid_component_dependency, format_remove_duplicates,
- format_blink_cpp_source_code, to_snake_case,
- normalize_path)
-import v8_utilities
-
-# Path handling for libraries and templates
-# Paths have to be normalized because Jinja uses the exact template path to
-# determine the hash used in the cache filename, and we need a pre-caching step
-# to be concurrency-safe. Use absolute path because __file__ is absolute if
-# module is imported, and relative if executed directly.
-# If paths differ between pre-caching and individual file compilation, the cache
-# is regenerated, which causes a race condition and breaks concurrent build,
-# since some compile processes will try to read the partially written cache.
-MODULE_PATH, _ = os.path.split(os.path.realpath(__file__))
-THIRD_PARTY_DIR = os.path.normpath(
- os.path.join(MODULE_PATH, os.pardir, os.pardir, os.pardir, os.pardir))
-TEMPLATES_DIR = os.path.normpath(
- os.path.join(MODULE_PATH, os.pardir, 'templates'))
-
-# jinja2 is in chromium's third_party directory.
-# Insert at 1 so at front to override system libraries, and
-# after path[0] == invoking script dir
-sys.path.insert(1, THIRD_PARTY_DIR)
-import jinja2
-from jinja2.filters import make_attrgetter, environmentfilter
-
-
-def generate_indented_conditional(code, conditional):
- # Indent if statement to level of original code
- indent = re.match(' *', code).group(0)
- return ('%sif (%s) {\n' % (indent, conditional) +
- ' %s\n' % '\n '.join(code.splitlines()) + '%s}\n' % indent)
-
-
-# [Exposed]
-def exposed_if(code, exposed_test):
- if not exposed_test:
- return code
- return generate_indented_conditional(
- code, 'execution_context && (%s)' % exposed_test)
-
-
-# [CrossOriginIsolated]
-def cross_origin_isolated_if(code, cross_origin_isolated_test):
- if not cross_origin_isolated_test:
- return code
- return generate_indented_conditional(
- code, 'execution_context && (%s)' % cross_origin_isolated_test)
-
-
-# [DirectSocketEnabled]
-def direct_socket_enabled_if(code, direct_socket_enabled_test):
- if not direct_socket_enabled_test:
- return code
- return generate_indented_conditional(
- code, 'execution_context && (%s)' % direct_socket_enabled_test)
-
-
-# [SecureContext]
-def secure_context_if(code, secure_context_test):
- if secure_context_test is None:
- return code
- return generate_indented_conditional(code, secure_context_test)
-
-
-# [RuntimeEnabled]
-def origin_trial_enabled_if(code,
- origin_trial_feature_name,
- execution_context=None):
- if not origin_trial_feature_name:
- return code
-
- function = v8_utilities.origin_trial_function_call(
- origin_trial_feature_name, execution_context)
- return generate_indented_conditional(code, function)
-
-
-# [RuntimeEnabled]
-def runtime_enabled_if(code, name):
- if not name:
- return code
-
- function = v8_utilities.runtime_enabled_function(name)
- return generate_indented_conditional(code, function)
-
-
-@environmentfilter
-def do_stringify_key_group_by(environment, value, attribute):
- expr = make_attrgetter(environment, attribute)
- key = lambda item: '' if expr(item) is None else str(expr(item))
- return groupby(sorted(value, key=key), expr)
-
-
-def initialize_jinja_env(cache_dir):
- jinja_env = jinja2.Environment(
- loader=jinja2.FileSystemLoader(TEMPLATES_DIR),
- # Bytecode cache is not concurrency-safe unless pre-cached:
- # if pre-cached this is read-only, but writing creates a race condition.
- bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
- keep_trailing_newline=True, # newline-terminate generated files
- lstrip_blocks=True, # so can indent control flow tags
- trim_blocks=True)
- jinja_env.filters.update({
- 'blink_capitalize': capitalize,
- 'exposed': exposed_if,
- 'format_blink_cpp_source_code': format_blink_cpp_source_code,
- 'format_remove_duplicates': format_remove_duplicates,
- 'origin_trial_enabled': origin_trial_enabled_if,
- 'runtime_enabled': runtime_enabled_if,
- 'runtime_enabled_function': v8_utilities.runtime_enabled_function,
- 'cross_origin_isolated': cross_origin_isolated_if,
- 'direct_socket_enabled': direct_socket_enabled_if,
- 'secure_context': secure_context_if
- })
- jinja_env.filters.update(constant_filters())
- jinja_env.filters.update(method_filters())
- jinja_env.filters["stringifykeygroupby"] = do_stringify_key_group_by
- return jinja_env
-
-
-_BLINK_RELATIVE_PATH_PREFIXES = ('bindings/', 'core/', 'modules/', 'platform/')
-
-
-def normalize_and_sort_includes(include_paths):
- normalized_include_paths = set()
- for include_path in include_paths:
- match = re.search(r'/gen/(third_party/blink/.*)$',
- posixpath.abspath(include_path))
- if match:
- include_path = match.group(1)
- elif include_path.startswith(_BLINK_RELATIVE_PATH_PREFIXES):
- include_path = 'third_party/blink/renderer/' + include_path
- normalized_include_paths.add(include_path)
- return sorted(normalized_include_paths)
-
-
-def render_template(template, context):
- filename = str(template.filename)
- filename = filename[filename.rfind('third_party'):]
- filename = normalize_path(filename)
-
- context['jinja_template_filename'] = filename
- return template.render(context)
-
-
-class CodeGeneratorBase(object):
- """Base class for jinja-powered jinja template generation.
- """
-
- def __init__(self, generator_name, info_provider, cache_dir, output_dir):
- self.generator_name = generator_name
- self.info_provider = info_provider
- self.jinja_env = initialize_jinja_env(cache_dir)
- self.output_dir = output_dir
- self.set_global_type_info()
-
- def should_generate_code(self, definitions):
- return definitions.interfaces or definitions.dictionaries
-
- def set_global_type_info(self):
- interfaces_info = self.info_provider.interfaces_info
- set_ancestors(interfaces_info['ancestors'])
- IdlType.set_callback_interfaces(interfaces_info['callback_interfaces'])
- IdlType.set_dictionaries(interfaces_info['dictionaries'])
- IdlType.set_enums(self.info_provider.enumerations)
- IdlType.set_callback_functions(self.info_provider.callback_functions)
- IdlType.set_implemented_as_interfaces(
- interfaces_info['implemented_as_interfaces'])
- IdlType.set_garbage_collected_types(
- interfaces_info['garbage_collected_interfaces'])
- IdlType.set_garbage_collected_types(interfaces_info['dictionaries'])
- set_component_dirs(interfaces_info['component_dirs'])
-
- def render_templates(self,
- include_paths,
- header_template,
- cpp_template,
- context,
- component=None):
- context['code_generator'] = self.generator_name
-
- # Add includes for any dependencies
- for include_path in include_paths:
- if component:
- dependency = idl_filename_to_component(include_path)
- assert is_valid_component_dependency(component, dependency)
- includes.add(include_path)
-
- context['header_forward_decls'] = sorted(
- context.get('header_forward_decls', set()))
-
- cpp_includes = set(context.get('cpp_includes', []))
- context['cpp_includes'] = normalize_and_sort_includes(cpp_includes
- | includes)
- context['header_includes'] = normalize_and_sort_includes(
- context['header_includes'])
-
- header_text = render_template(header_template, context)
- cpp_text = render_template(cpp_template, context)
- return header_text, cpp_text
-
- def generate_code(self, definitions, definition_name):
- """Invokes code generation. The [definitions] argument is a list of definitions,
- and the [definition_name] is the name of the definition
- """
- # This should be implemented in subclasses.
- raise NotImplementedError()
-
- def normalize_this_header_path(self, header_path):
- header_path = normalize_path(header_path)
- match = re.search('(third_party/blink/.*)$', header_path)
- assert match, 'Unkown style of path to output: ' + header_path
- return match.group(1)
-
-
-def main(argv):
- # If file itself executed, cache templates
- try:
- cache_dir = argv[1]
- dummy_filename = argv[2]
- except IndexError:
- print('Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0])
- return 1
-
- # Cache templates
- jinja_env = initialize_jinja_env(cache_dir)
- template_filenames = [
- filename for filename in os.listdir(TEMPLATES_DIR)
- # Skip .svn, directories, etc.
- if filename.endswith(('.tmpl', '.txt'))
- ]
- for template_filename in template_filenames:
- jinja_env.get_template(template_filename)
-
- # Create a dummy file as output for the build system,
- # since filenames of individual cache files are unpredictable and opaque
- # (they are hashes of the template path, which varies based on environment)
- with open(dummy_filename, 'w') as dummy_file:
- pass # |open| creates or touches the file
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py b/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
deleted file mode 100644
index f296d486a3c..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
+++ /dev/null
@@ -1,453 +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.
-
-# pylint: disable=import-error,print-statement,relative-import
-"""Generate Blink V8 bindings (.h and .cpp files).
-
-If run itself, caches Jinja templates (and creates dummy file for build,
-since cache filenames are unpredictable and opaque).
-
-This module is *not* concurrency-safe without care: bytecode caching creates
-a race condition on cache *write* (crashes if one process tries to read a
-partially-written cache). However, if you pre-cache the templates (by running
-the module itself), then you can parallelize compiling individual files, since
-cache *reading* is safe.
-
-Input: An object of class IdlDefinitions, containing an IDL interface X
-Output: V8X.h and V8X.cpp
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-import os
-import posixpath
-
-from code_generator import CodeGeneratorBase
-from idl_definitions import Visitor
-from idl_types import IdlType
-import v8_callback_function
-import v8_callback_interface
-import v8_dictionary
-from v8_globals import includes
-import v8_interface
-import v8_types
-import v8_union
-from v8_utilities import build_basename, cpp_name
-from utilities import idl_filename_to_component, is_testing_target, shorten_union_name, to_header_guard, to_snake_case
-
-# 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'
-
-
-def depending_union_type(idl_type):
- """Returns the union type name if the given idl_type depends on a
- union type.
- """
-
- def find_base_type(current_type):
- if current_type.is_array_or_sequence_type:
- return find_base_type(current_type.element_type)
- if current_type.is_record_type:
- # IdlRecordType.key_type is always a string type, so we only need
- # to looking into value_type.
- return find_base_type(current_type.value_type)
- if current_type.is_nullable:
- return find_base_type(current_type.inner_type)
- return current_type
-
- base_type = find_base_type(idl_type)
- if base_type.is_union_type:
- return base_type
- return None
-
-
-class TypedefResolver(Visitor):
- def __init__(self, info_provider):
- self.info_provider = info_provider
- self.additional_header_includes = set()
- self.typedefs = {}
-
- def resolve(self, definitions, definition_name):
- """Traverse definitions and resolves typedefs with the actual types."""
- self.typedefs = {}
- for name, typedef in self.info_provider.typedefs.items():
- self.typedefs[name] = typedef.idl_type
- self.additional_header_includes = set()
- definitions.accept(self)
- self._update_dependencies_include_paths(definition_name)
-
- def _update_dependencies_include_paths(self, definition_name):
- if definition_name not in self.info_provider.interfaces_info:
- return
- interface_info = self.info_provider.interfaces_info[definition_name]
- interface_info['additional_header_includes'] = set(
- self.additional_header_includes)
-
- def _resolve_typedefs(self, typed_object):
- """Resolve typedefs to actual types in the object."""
- for attribute_name in typed_object.idl_type_attributes:
- try:
- idl_type = getattr(typed_object, attribute_name)
- except AttributeError:
- continue
- if not idl_type:
- continue
- resolved_idl_type = idl_type.resolve_typedefs(self.typedefs)
- # TODO(bashi): Dependency resolution shouldn't happen here.
- # Move this into includes_for_type() families.
- union_type = depending_union_type(resolved_idl_type)
- if union_type:
- self.additional_header_includes.add(
- self.info_provider.include_path_for_union_types(
- union_type))
- # Need to re-assign the attribute, not just mutate idl_type, since
- # type(idl_type) may change.
- setattr(typed_object, attribute_name, resolved_idl_type)
-
- def visit_typed_object(self, typed_object):
- self._resolve_typedefs(typed_object)
-
-
-class CodeGeneratorV8Base(CodeGeneratorBase):
- """Base class for v8 bindings generator and IDL dictionary impl generator"""
-
- def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
- cache_dir, output_dir)
- self.typedef_resolver = TypedefResolver(info_provider)
-
- def generate_code(self, definitions, definition_name):
- """Returns .h/.cpp code as ((path, content)...)."""
- # Set local type info
- if not self.should_generate_code(definitions):
- return set()
-
- # Resolve typedefs
- self.typedef_resolver.resolve(definitions, definition_name)
- return self.generate_code_internal(definitions, definition_name)
-
- def generate_code_internal(self, definitions, definition_name):
- # This should be implemented in subclasses.
- raise NotImplementedError()
-
- def get_output_filename(self, definition_name, ext, prefix=None):
- return build_basename(definition_name, prefix=prefix) + ext
-
-
-class CodeGeneratorV8(CodeGeneratorV8Base):
- def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorV8Base.__init__(self, info_provider, cache_dir,
- output_dir)
-
- def output_paths(self, definition_name):
- header_path = posixpath.join(
- self.output_dir,
- self.get_output_filename(definition_name, '.h', prefix='v8_'))
- cpp_path = posixpath.join(
- self.output_dir,
- self.get_output_filename(definition_name, '.cc', prefix='v8_'))
- return header_path, cpp_path
-
- def generate_code_internal(self, definitions, definition_name):
- if definition_name in definitions.interfaces:
- return self.generate_interface_code(
- definitions, definition_name,
- definitions.interfaces[definition_name])
- if definition_name in definitions.dictionaries:
- return self.generate_dictionary_code(
- definitions, definition_name,
- definitions.dictionaries[definition_name])
- raise ValueError('%s is not in IDL definitions' % definition_name)
-
- def generate_interface_code(self, definitions, interface_name, interface):
- interface_info = self.info_provider.interfaces_info[interface_name]
- full_path = interface_info.get('full_path')
- component = idl_filename_to_component(full_path)
- include_paths = interface_info.get('dependencies_include_paths')
-
- # Select appropriate Jinja template and contents function
- if interface.is_callback:
- header_template_filename = 'callback_interface.h.tmpl'
- cpp_template_filename = 'callback_interface.cc.tmpl'
- interface_context = v8_callback_interface.callback_interface_context
- elif interface.is_partial:
- interface_context = v8_interface.interface_context
- header_template_filename = 'partial_interface.h.tmpl'
- cpp_template_filename = 'partial_interface.cc.tmpl'
- interface_name += 'Partial'
- assert component == 'core'
- component = 'modules'
- include_paths = interface_info.get(
- 'dependencies_other_component_include_paths')
- else:
- header_template_filename = 'interface.h.tmpl'
- cpp_template_filename = 'interface.cc.tmpl'
- interface_context = v8_interface.interface_context
-
- component_info = self.info_provider.component_info
- template_context = interface_context(interface, definitions.interfaces,
- component_info)
- includes.update(
- interface_info.get('cpp_includes', {}).get(component, set()))
- if not interface.is_partial and not is_testing_target(full_path):
- template_context['header_includes'].add(
- self.info_provider.include_path_for_export)
- template_context['exported'] = \
- self.info_provider.specifier_for_export
- # Add the include for interface itself
- if IdlType(interface_name).is_typed_array:
- template_context['header_includes'].add(
- 'core/typed_arrays/dom_typed_array.h')
- elif interface.is_callback:
- pass
- else:
- template_context['header_includes'].add(
- interface_info['include_path'])
- template_context['header_includes'].update(
- interface_info.get('additional_header_includes', []))
- header_path, cpp_path = self.output_paths(interface_name)
- this_include_header_path = self.normalize_this_header_path(header_path)
- template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(
- this_include_header_path)
- header_template = self.jinja_env.get_template(header_template_filename)
- cpp_template = self.jinja_env.get_template(cpp_template_filename)
- header_text, cpp_text = self.render_templates(
- include_paths, header_template, cpp_template, template_context,
- component)
- return (
- (header_path, header_text),
- (cpp_path, cpp_text),
- )
-
- def generate_dictionary_code(self, definitions, dictionary_name,
- dictionary):
- # pylint: disable=unused-argument
- interfaces_info = self.info_provider.interfaces_info
- header_template = self.jinja_env.get_template('dictionary_v8.h.tmpl')
- cpp_template = self.jinja_env.get_template('dictionary_v8.cc.tmpl')
- interface_info = interfaces_info[dictionary_name]
- component_info = self.info_provider.component_info
- template_context = v8_dictionary.dictionary_context(
- dictionary, interfaces_info, component_info)
- include_paths = interface_info.get('dependencies_include_paths')
- # Add the include for interface itself
- template_context['header_includes'].add(interface_info['include_path'])
- if not is_testing_target(interface_info.get('full_path')):
- template_context['header_includes'].add(
- self.info_provider.include_path_for_export)
- template_context['exported'] = \
- self.info_provider.specifier_for_export
- header_path, cpp_path = self.output_paths(dictionary_name)
- this_include_header_path = self.normalize_this_header_path(header_path)
- template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(
- this_include_header_path)
- header_text, cpp_text = self.render_templates(
- include_paths, header_template, cpp_template, template_context)
- return (
- (header_path, header_text),
- (cpp_path, cpp_text),
- )
-
-
-class CodeGeneratorDictionaryImpl(CodeGeneratorV8Base):
- def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorV8Base.__init__(self, info_provider, cache_dir,
- output_dir)
-
- def output_paths(self, definition_name, interface_info):
- output_dir = posixpath.join(self.output_dir,
- interface_info['relative_dir'])
- header_path = posixpath.join(
- output_dir, self.get_output_filename(definition_name, '.h'))
- cpp_path = posixpath.join(
- output_dir, self.get_output_filename(definition_name, '.cc'))
- return header_path, cpp_path
-
- def generate_code_internal(self, definitions, definition_name):
- if not definition_name in definitions.dictionaries:
- raise ValueError('%s is not an IDL dictionary' % definition_name)
- interfaces_info = self.info_provider.interfaces_info
- dictionary = definitions.dictionaries[definition_name]
- interface_info = interfaces_info[definition_name]
- header_template = self.jinja_env.get_template('dictionary_impl.h.tmpl')
- cpp_template = self.jinja_env.get_template('dictionary_impl.cc.tmpl')
- template_context = v8_dictionary.dictionary_impl_context(
- dictionary, interfaces_info)
- include_paths = interface_info.get('dependencies_include_paths')
- if not is_testing_target(interface_info.get('full_path')):
- template_context['exported'] = \
- self.info_provider.specifier_for_export
- template_context['header_includes'].add(
- self.info_provider.include_path_for_export)
- template_context['header_includes'].update(
- interface_info.get('additional_header_includes', []))
- header_path, cpp_path = self.output_paths(definition_name,
- interface_info)
- this_include_header_path = self.normalize_this_header_path(header_path)
- template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(
- this_include_header_path)
- header_text, cpp_text = self.render_templates(
- include_paths, header_template, cpp_template, template_context)
- return (
- (header_path, header_text),
- (cpp_path, cpp_text),
- )
-
-
-class CodeGeneratorUnionType(CodeGeneratorBase):
- """Generates union type container classes.
- This generator is different from CodeGeneratorV8 and
- CodeGeneratorDictionaryImpl. It assumes that all union types are already
- collected. It doesn't process idl files directly.
- """
-
- def __init__(self, info_provider, cache_dir, output_dir, target_component):
- CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
- cache_dir, output_dir)
- self.target_component = target_component
- # The code below duplicates parts of TypedefResolver. We do not use it
- # directly because IdlUnionType is not a type defined in
- # idl_definitions.py. What we do instead is to resolve typedefs in
- # _generate_container_code() whenever a new union file is generated.
- self.typedefs = {}
- for name, typedef in self.info_provider.typedefs.items():
- self.typedefs[name] = typedef.idl_type
-
- def _generate_container_code(self, union_type):
- includes.clear()
- union_type = union_type.resolve_typedefs(self.typedefs)
- header_template = self.jinja_env.get_template('union_container.h.tmpl')
- cpp_template = self.jinja_env.get_template('union_container.cc.tmpl')
- template_context = v8_union.container_context(union_type,
- self.info_provider)
- template_context['header_includes'].append(
- self.info_provider.include_path_for_export)
- template_context['exported'] = self.info_provider.specifier_for_export
- snake_base_name = to_snake_case(shorten_union_name(union_type))
- header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
- cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
- this_include_header_path = self.normalize_this_header_path(header_path)
- template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(
- this_include_header_path)
- header_text, cpp_text = self.render_templates(
- [], header_template, cpp_template, template_context)
- return (
- (header_path, header_text),
- (cpp_path, cpp_text),
- )
-
- def _get_union_types_for_containers(self):
- union_types = self.info_provider.union_types
- if not union_types:
- return None
- # For container classes we strip nullable wrappers. For example,
- # both (A or B)? and (A? or B) will become AOrB. This should be OK
- # because container classes can handle null and it seems that
- # distinguishing (A or B)? and (A? or B) doesn't make sense.
- container_cpp_types = set()
- union_types_for_containers = set()
- for union_type in union_types:
- cpp_type = union_type.cpp_type
- if cpp_type not in container_cpp_types:
- union_types_for_containers.add(union_type)
- container_cpp_types.add(cpp_type)
- return union_types_for_containers
-
- def generate_code(self):
- union_types = self._get_union_types_for_containers()
- if not union_types:
- return ()
- outputs = set()
- for union_type in union_types:
- outputs.update(self._generate_container_code(union_type))
- return outputs
-
-
-class CodeGeneratorCallbackFunction(CodeGeneratorBase):
- def __init__(self, info_provider, cache_dir, output_dir, target_component):
- CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
- cache_dir, output_dir)
- self.target_component = target_component
- self.typedef_resolver = TypedefResolver(info_provider)
-
- def generate_code_internal(self, callback_function, path):
- self.typedef_resolver.resolve(callback_function,
- callback_function.name)
- header_template = self.jinja_env.get_template(
- 'callback_function.h.tmpl')
- cpp_template = self.jinja_env.get_template('callback_function.cc.tmpl')
- template_context = v8_callback_function.callback_function_context(
- callback_function)
- if not is_testing_target(path):
- template_context['exported'] = \
- self.info_provider.specifier_for_export
- template_context['header_includes'].append(
- self.info_provider.include_path_for_export)
-
- # TODO(bashi): Dependency resolution shouldn't happen here.
- # Move this into includes_for_type() families.
- for argument in callback_function.arguments:
- if argument.idl_type.is_union_type:
- template_context['header_includes'].append(
- self.info_provider.include_path_for_union_types(
- argument.idl_type))
-
- snake_base_name = to_snake_case('V8%s' % callback_function.name)
- header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
- cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
- this_include_header_path = self.normalize_this_header_path(header_path)
- template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(
- this_include_header_path)
- header_text, cpp_text = self.render_templates(
- [], header_template, cpp_template, template_context)
- return (
- (header_path, header_text),
- (cpp_path, cpp_text),
- )
-
- # pylint: disable=W0221
- def generate_code(self):
- callback_functions = self.info_provider.callback_functions
- if not callback_functions:
- return ()
- outputs = set()
- for callback_function_dict in callback_functions.values():
- if callback_function_dict['component_dir'] != self.target_component:
- continue
- callback_function = callback_function_dict['callback_function']
- if 'Custom' in callback_function.extended_attributes:
- continue
- path = callback_function_dict['full_path']
- outputs.update(
- self.generate_code_internal(callback_function, path))
- return outputs
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py b/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
index bfe9bb1d0c0..cfc0d742f89 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
@@ -15,7 +15,7 @@ import blink_idl_parser
import utilities
import web_idl
-_VALID_COMPONENTS = ('core', 'modules')
+_VALID_COMPONENTS = ('core', 'modules', 'extensions_chromeos')
def parse_options():
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py b/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
deleted file mode 100755
index fb889cdbfd2..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-"""Compute global objects.
-
-Global objects are defined by interfaces with [Global] on
-their definition: http://heycam.github.io/webidl/#Global
-
-Design document: http://www.chromium.org/developers/design-documents/idl-build
-"""
-
-# pylint: disable=relative-import
-
-import optparse
-import os
-import sys
-
-from utilities import get_file_contents
-from utilities import get_interface_extended_attributes_from_idl
-from utilities import get_first_interface_name_from_idl
-from utilities import read_file_to_list
-from utilities import read_pickle_files
-from utilities import write_pickle_file
-
-
-def parse_options():
- usage = 'Usage: %prog [options] [GlobalObjects.pickle]'
- parser = optparse.OptionParser(usage=usage)
- parser.add_option('--idl-files-list', help='file listing IDL files')
- parser.add_option(
- '--global-objects-component-files',
- action='append',
- help='optionally preceeded input pickle filename.')
-
- options, args = parser.parse_args()
-
- if options.idl_files_list is None:
- parser.error(
- 'Must specify a file listing IDL files using --idl-files-list.')
- if options.global_objects_component_files is None:
- options.global_objects_component_files = []
- if len(args) != 1:
- parser.error('Must specify an output pickle filename as an argument')
-
- return options, args
-
-
-def dict_union(dicts):
- return dict((k, v) for d in dicts for k, v in d.items())
-
-
-def idl_file_to_global_names(idl_filename):
- """Returns global names, if any, for an IDL file.
-
- The identifier argument or identifier list argument the [Global] extended
- attribute is declared with define the interface's global names
- (http://heycam.github.io/webidl/#Global).
- """
- full_path = os.path.realpath(idl_filename)
- idl_file_contents = get_file_contents(full_path)
- extended_attributes = get_interface_extended_attributes_from_idl(
- idl_file_contents)
- interface_name = get_first_interface_name_from_idl(idl_file_contents)
-
- if 'Global' not in extended_attributes:
- return
- global_value = extended_attributes['Global']
- if not global_value:
- raise ValueError(
- '[Global] must take an indentifier or an identifier list.\n' +
- full_path)
- return map(str.strip, global_value.strip('()').split(','))
-
-
-def idl_files_to_interface_name_global_names(idl_files):
- """Yields pairs (interface_name, global_names) found in IDL files."""
- for idl_filename in idl_files:
- interface_name = get_first_interface_name_from_idl(
- get_file_contents(idl_filename))
- global_names = idl_file_to_global_names(idl_filename)
- if global_names:
- yield interface_name, global_names
-
-
-################################################################################
-
-
-def main():
- options, args = parse_options()
- output_global_objects_filename = args.pop()
- interface_name_global_names = dict_union(
- existing_interface_name_global_names
- for existing_interface_name_global_names in read_pickle_files(
- options.global_objects_component_files))
-
- # File paths of input IDL files are passed in a file, which is generated at
- # GN time. It is OK because the target IDL files themselves are static.
- idl_files = read_file_to_list(options.idl_files_list)
- interface_name_global_names.update(
- idl_files_to_interface_name_global_names(idl_files))
-
- write_pickle_file(output_global_objects_filename,
- interface_name_global_names)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py b/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
deleted file mode 100755
index 9561fdc664a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
+++ /dev/null
@@ -1,410 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-"""Compute global interface information for individual IDL files.
-
-Auxiliary module for compute_interfaces_info_overall, which consolidates
-this individual information, computing info that spans multiple files
-(dependencies and ancestry).
-
-This distinction is so that individual interface info can be computed
-separately for each component (avoiding duplicated reading of individual
-files), then consolidated using *only* the info visible to a given component.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-build
-"""
-
-from collections import defaultdict
-import optparse
-import os
-import posixpath
-import sys
-
-from idl_definitions import Visitor
-from idl_reader import IdlReader
-from utilities import idl_filename_to_component
-from utilities import idl_filename_to_basename
-from utilities import merge_dict_recursively
-from utilities import read_idl_files_list_from_file
-from utilities import shorten_union_name
-from utilities import to_snake_case
-from utilities import read_pickle_file
-from utilities import write_pickle_file
-
-module_path = os.path.dirname(__file__)
-source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
-gen_path = os.path.join('gen', 'blink')
-
-
-class IdlBadFilenameError(Exception):
- """Raised if an IDL filename disagrees with the interface name in the file."""
- pass
-
-
-def parse_options():
- usage = 'Usage: %prog [options]'
- parser = optparse.OptionParser(usage=usage)
- parser.add_option('--cache-directory', help='cache directory')
- parser.add_option('--idl-files-list', help='file listing IDL files')
- parser.add_option(
- '--interfaces-info-file', help='interface info pickle file')
- parser.add_option(
- '--component-info-file', help='component wide info pickle file')
- parser.add_option(
- '--runtime-enabled-features-file',
- help='runtime-enabled features pickle file')
-
- options, args = parser.parse_args()
- if options.interfaces_info_file is None:
- parser.error(
- 'Must specify an output file using --interfaces-info-file.')
- if options.idl_files_list is None:
- parser.error(
- 'Must specify a file listing IDL files using --idl-files-list.')
- return options, args
-
-
-################################################################################
-# Computations
-################################################################################
-
-
-def relative_dir_posix(idl_filename, base_path):
- """Returns relative path to the directory of idl_file in POSIX format."""
- relative_path_local = os.path.relpath(idl_filename, base_path)
- relative_dir_local = os.path.dirname(relative_path_local)
- return relative_dir_local.replace(os.path.sep, posixpath.sep)
-
-
-def include_path(idl_filename, implemented_as=None):
- """Returns relative path to header file in POSIX format; used in includes.
-
- POSIX format is used for consistency of output, so reference tests are
- platform-independent.
- """
- if idl_filename.startswith(gen_path):
- relative_dir = relative_dir_posix(idl_filename, gen_path)
- else:
- relative_dir = relative_dir_posix(idl_filename, source_path)
-
- # IDL file basename is used even if only a partial interface file
- output_file_basename = implemented_as or idl_filename_to_basename(
- idl_filename)
- output_file_basename = to_snake_case(output_file_basename)
- return posixpath.join(relative_dir, output_file_basename + '.h')
-
-
-def get_includes_from_definitions(definitions, definition_name):
- interfaces = []
- mixins = []
- for include in definitions.includes:
- if definition_name == include.interface:
- mixins.append(include.mixin)
- elif definition_name == include.mixin:
- interfaces.append(include.interface)
- else:
- raise IdlBadFilenameError(
- 'includes statement found in unrelated IDL file.\n'
- 'Statement is:\n'
- ' %s includes %s;\n'
- 'but filename is unrelated "%s.idl"' %
- (include.interface, include.mixin, definition_name))
- return interfaces, mixins
-
-
-def get_put_forward_interfaces_from_definition(definition):
- return sorted(
- set(attribute.idl_type.base_type for attribute in definition.attributes
- if 'PutForwards' in attribute.extended_attributes))
-
-
-def get_unforgeable_attributes_from_definition(definition):
- return sorted(attribute for attribute in definition.attributes
- if 'LegacyUnforgeable' in attribute.extended_attributes)
-
-
-def collect_union_types_from_definitions(definitions):
- """Traverse definitions and collect all union types."""
-
- class UnionTypeCollector(Visitor):
- def collect(self, definitions):
- self._union_types = set()
- definitions.accept(self)
- return self._union_types
-
- def visit_typed_object(self, typed_object):
- for attribute_name in typed_object.idl_type_attributes:
- attribute = getattr(typed_object, attribute_name, None)
- if not attribute:
- continue
- for idl_type in attribute.idl_types():
- if idl_type.is_union_type:
- self._union_types.add(idl_type)
-
- return UnionTypeCollector().collect(definitions)
-
-
-class InterfaceInfoCollector(object):
- """A class that collects interface information from idl files."""
-
- def __init__(self, cache_directory=None):
- self.reader = IdlReader(
- interfaces_info=None, outputdir=cache_directory)
- self.interfaces_info = {}
- self.partial_interface_files = defaultdict(lambda: {
- 'full_paths': [],
- 'include_paths': [], })
- self.enumerations = {}
- self.union_types = set()
- self.typedefs = {}
- self.callback_functions = {}
-
- def add_paths_to_partials_dict(self, partial_interface_name, full_path,
- include_paths):
- paths_dict = self.partial_interface_files[partial_interface_name]
- paths_dict['full_paths'].append(full_path)
- paths_dict['include_paths'].extend(include_paths)
-
- def check_enum_consistency(self, enum):
- existing_enum = self.enumerations.get(enum.name)
- if not existing_enum:
- return True
- # TODO(bashi): Ideally we should not allow multiple enum declarations
- # but we allow them to work around core/module separation.
- if len(existing_enum.values) != len(enum.values):
- return False
- return all(value in existing_enum.values for value in enum.values)
-
- def collect_info(self, idl_filename):
- """Reads an idl file and collects information which is required by the
- binding code generation."""
-
- def collect_unforgeable_attributes(definition, idl_filename):
- """Collects [LegacyUnforgeable] attributes so that we can define
- them on sub-interfaces later. The resulting structure is as
- follows.
- interfaces_info[interface_name] = {
- 'unforgeable_attributes': [IdlAttribute, ...],
- ...
- }
- """
- interface_info = {}
- unforgeable_attributes = get_unforgeable_attributes_from_definition(
- definition)
- if not unforgeable_attributes:
- return interface_info
-
- if definition.is_partial:
- interface_basename = idl_filename_to_interface_name(
- idl_filename)
- # TODO(yukishiino): [PartialInterfaceImplementedAs] is treated
- # in interface_dependency_resolver.transfer_extended_attributes.
- # Come up with a better way to keep them consistent.
- for attr in unforgeable_attributes:
- attr.extended_attributes[
- 'PartialInterfaceImplementedAs'] = definition.extended_attributes.get(
- 'ImplementedAs', interface_basename)
- interface_info['unforgeable_attributes'] = unforgeable_attributes
- return interface_info
-
- definitions = self.reader.read_idl_file(idl_filename)
-
- this_union_types = collect_union_types_from_definitions(definitions)
- self.union_types.update(this_union_types)
- self.typedefs.update(definitions.typedefs)
- for callback_function_name, callback_function in \
- definitions.callback_functions.items():
- # Set 'component_dir' to specify a directory that callback function files belong to
- self.callback_functions[callback_function_name] = {
- 'callback_function': callback_function,
- 'component_dir': idl_filename_to_component(idl_filename),
- 'full_path': os.path.realpath(idl_filename),
- }
- # Check enum duplication.
- for enum in definitions.enumerations.values():
- if not self.check_enum_consistency(enum):
- raise Exception('Enumeration "%s" is defined more than once '
- 'with different valid values' % enum.name)
- self.enumerations.update(definitions.enumerations)
-
- if definitions.interfaces:
- definition = next(iter(definitions.interfaces.values()))
- interface_info = {
- 'is_callback_interface':
- definition.is_callback,
- 'is_dictionary':
- False,
- # Interfaces that are referenced (used as types) and that we
- # introspect during code generation (beyond interface-level
- # data ([ImplementedAs], is_callback_interface, ancestors, and
- # inherited extended attributes): deep dependencies.
- # These cause rebuilds of referrers, due to the dependency,
- # so these should be minimized; currently only targets of
- # [PutForwards].
- 'referenced_interfaces':
- get_put_forward_interfaces_from_definition(definition),
- }
- elif definitions.dictionaries:
- definition = next(iter(definitions.dictionaries.values()))
- interface_info = {
- 'is_callback_interface': False,
- 'is_dictionary': True,
- 'referenced_interfaces': None,
- }
- else:
- return
-
- if definition.name not in self.interfaces_info:
- self.interfaces_info[definition.name] = {}
-
- # Remember [LegacyUnforgeable] attributes.
- if definitions.interfaces:
- merge_dict_recursively(
- self.interfaces_info[definition.name],
- collect_unforgeable_attributes(definition, idl_filename))
-
- component = idl_filename_to_component(idl_filename)
- extended_attributes = definition.extended_attributes
- implemented_as = extended_attributes.get('ImplementedAs')
- full_path = os.path.realpath(idl_filename)
- if interface_info['is_dictionary']:
- this_include_path = include_path(idl_filename)
- else:
- this_include_path = include_path(idl_filename, implemented_as)
- if definition.is_partial:
- # We don't create interface_info for partial interfaces, but
- # adds paths to another dict.
- partial_include_paths = []
- if this_include_path:
- partial_include_paths.append(this_include_path)
- self.add_paths_to_partials_dict(definition.name, full_path,
- partial_include_paths)
- # Collects C++ header paths which should be included from generated
- # .cpp files. The resulting structure is as follows.
- # interfaces_info[interface_name] = {
- # 'cpp_includes': {
- # 'core': set(['core/foo/Foo.h', ...]),
- # 'modules': set(['modules/bar/Bar.h', ...]),
- # },
- # ...
- # }
- if this_include_path:
- merge_dict_recursively(
- self.interfaces_info[definition.name],
- {'cpp_includes': {
- component: set([this_include_path])
- }})
- return
-
- # 'includes' statements can be included in either the file for the
- # interface (lhs of 'includes') or mixin (rhs of 'includes'). Store both
- # for now, then merge to the interface later.
- includes_interfaces, includes_mixins = get_includes_from_definitions(
- definitions, definition.name)
-
- interface_info.update({
- 'extended_attributes':
- extended_attributes,
- 'full_path':
- full_path,
- 'union_types':
- this_union_types,
- 'implemented_as':
- implemented_as,
- 'included_by_interfaces':
- includes_interfaces,
- 'including_mixins':
- includes_mixins,
- 'include_path':
- this_include_path,
- # FIXME: temporary private field, while removing old
- # treatement of 'implements': http://crbug.com/360435
- 'is_legacy_treat_as_partial_interface':
- 'LegacyTreatAsPartialInterface' in extended_attributes,
- 'parent':
- definition.parent,
- 'relative_dir':
- relative_dir_posix(idl_filename, source_path),
- })
- merge_dict_recursively(self.interfaces_info[definition.name],
- interface_info)
-
- def get_info_as_dict(self):
- """Returns info packaged as a dict."""
- return {
- 'interfaces_info': self.interfaces_info,
- # Can't pickle defaultdict, convert to dict
- # FIXME: this should be included in get_component_info.
- 'partial_interface_files': dict(self.partial_interface_files),
- }
-
- def get_component_info_as_dict(self, runtime_enabled_features):
- """Returns component wide information as a dict."""
- return {
- 'callback_functions':
- self.callback_functions,
- 'enumerations':
- dict((enum.name, enum.values)
- for enum in self.enumerations.values()),
- 'runtime_enabled_features':
- runtime_enabled_features,
- 'typedefs':
- self.typedefs,
- 'union_types':
- self.union_types,
- }
-
-
-################################################################################
-
-
-def main():
- options, _ = parse_options()
-
- # IDL files are passed in a file, due to OS command line length limits
- idl_files = read_idl_files_list_from_file(options.idl_files_list)
-
- # Compute information for individual files
- # Information is stored in global variables interfaces_info and
- # partial_interface_files.
- info_collector = InterfaceInfoCollector(options.cache_directory)
- for idl_filename in idl_files:
- info_collector.collect_info(idl_filename)
-
- write_pickle_file(options.interfaces_info_file,
- info_collector.get_info_as_dict())
- runtime_enabled_features = read_pickle_file(
- options.runtime_enabled_features_file)
- write_pickle_file(
- options.component_info_file,
- info_collector.get_component_info_as_dict(runtime_enabled_features))
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py b/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py
deleted file mode 100755
index 474ee75b57d..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-"""Compute global interface information, including public information, dependencies, and inheritance.
-
-Computed data is stored in a global variable, |interfaces_info|, and written as
-output (concretely, exported as a pickle). This is then used by the IDL compiler
-itself, so it does not need to compute global information itself, and so that
-inter-IDL dependencies are clear, since they are all computed here.
-
-The |interfaces_info| pickle is a *global* dependency: any changes cause a full
-rebuild. This is to avoid having to compute which public data is visible by
-which IDL files on a file-by-file basis, which is very complex for little
-benefit.
-|interfaces_info| should thus only contain data about an interface that
-contains paths or is needed by *other* interfaces, e.g., path data (to abstract
-the compiler from OS-specific file paths) or public data (to avoid having to
-read other interfaces unnecessarily).
-It should *not* contain full information about an interface (e.g., all
-extended attributes), as this would cause unnecessary rebuilds.
-
-|interfaces_info| is a dict, keyed by |interface_name|.
-
-Current keys are:
-* dependencies:
- 'including_mixins': targets of 'includes' statements
- 'referenced_interfaces': reference interfaces that are introspected
- (currently just targets of [PutForwards])
-
-* inheritance:
- 'ancestors': all ancestor interfaces
- 'inherited_extended_attributes': inherited extended attributes
- (all controlling memory management)
-
-* public:
- 'is_callback_interface': bool, callback interface or not
- 'implemented_as': value of [ImplementedAs=...] on interface (C++ class name)
-
-* paths:
- 'full_path': path to the IDL file, so can lookup an IDL by interface name
- 'include_path': path for use in C++ #include directives
- 'dependencies_full_paths': paths to dependencies (for merging into main)
- 'dependencies_include_paths': paths for use in C++ #include directives
- 'dependencies_other_component_full_paths':
- paths to dependencies (cannot merge because of other component)
- 'dependencies_other_component_include_paths':
- paths for use in C++ #include directives because of dependencies in
- other component
-
-Note that all of these are stable information, unlikely to change without
-moving or deleting files (hence requiring a full rebuild anyway) or significant
-code changes (for inherited extended attributes).
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-build
-"""
-
-# pylint: disable=relative-import
-
-import optparse
-import sys
-
-from collections import defaultdict
-from utilities import idl_filename_to_component
-from utilities import merge_dict_recursively
-from utilities import read_pickle_files
-from utilities import shorten_union_name
-from utilities import write_pickle_file
-
-INHERITED_EXTENDED_ATTRIBUTES = set([
- 'ActiveScriptWrappable',
- 'LegacyUnenumerableNamedProperties',
-])
-
-# Main variable (filled in and exported)
-interfaces_info = {}
-
-# Auxiliary variables (not visible to future build steps)
-partial_interface_files = defaultdict(lambda: {
- 'full_paths': [],
- 'include_paths': [], })
-parent_interfaces = {}
-
-# interface name -> extended attributes
-inherited_extended_attributes_by_interface = {}
-
-
-class IdlInterfaceFileNotFoundError(Exception):
- """Raised if an IDL file that contains the mixin cannot be found."""
- pass
-
-
-def parse_options():
- usage = 'Usage: %prog [input_info.pickle]... [output_info.pickle]'
- parser = optparse.OptionParser(usage=usage)
-
- return parser.parse_args()
-
-
-def dict_of_dicts_of_lists_update_or_append(existing, other):
- """Updates an existing dict of dicts of lists, or appends to lists if key already present.
-
- Needed for merging partial_interface_files across components.
- """
- for key, value in other.items():
- if key not in existing:
- existing[key] = value
- continue
- existing_value = existing[key]
- for inner_key, inner_value in value.items():
- existing_value[inner_key].extend(inner_value)
-
-
-################################################################################
-# Computations
-################################################################################
-
-
-def compute_inheritance_info(interface_name):
- """Compute inheritance information, namely ancestors and inherited
- extended attributes.
- """
-
- def generate_ancestors(interface_name):
- while interface_name in parent_interfaces:
- interface_name = parent_interfaces[interface_name]
- yield interface_name
-
- ancestors = list(generate_ancestors(interface_name))
- inherited_extended_attributes = \
- inherited_extended_attributes_by_interface[interface_name]
- for ancestor in ancestors:
- # Ancestors may not be present, notably if an ancestor is a generated
- # IDL file and we are running this script from run_bindings_tests.py,
- # where we don't generate these files.
- ancestor_extended_attributes = \
- inherited_extended_attributes_by_interface.get(ancestor, {})
- inherited_extended_attributes.update(ancestor_extended_attributes)
-
- interfaces_info[interface_name].update({
- 'ancestors':
- ancestors,
- 'inherited_extended_attributes':
- inherited_extended_attributes,
- })
-
-
-def compute_global_type_info():
- ancestors = {}
- dictionaries = {}
- component_dirs = {}
- implemented_as_interfaces = {}
- garbage_collected_interfaces = set()
- callback_interfaces = set()
-
- for interface_name, interface_info in interfaces_info.items():
- component_dirs[interface_name] = idl_filename_to_component(
- interface_info['full_path'])
-
- if interface_info['ancestors']:
- ancestors[interface_name] = interface_info['ancestors']
- if interface_info['is_callback_interface']:
- callback_interfaces.add(interface_name)
- if interface_info['is_dictionary']:
- dictionaries[interface_name] = interface_info['is_dictionary']
- if interface_info['implemented_as']:
- implemented_as_interfaces[interface_name] = \
- interface_info['implemented_as']
-
- inherited_extended_attributes = \
- interface_info['inherited_extended_attributes']
- garbage_collected_interfaces.add(interface_name)
-
- interfaces_info['ancestors'] = ancestors
- interfaces_info['callback_interfaces'] = callback_interfaces
- interfaces_info['dictionaries'] = dictionaries
- interfaces_info['implemented_as_interfaces'] = implemented_as_interfaces
- interfaces_info['garbage_collected_interfaces'] = \
- garbage_collected_interfaces
- interfaces_info['component_dirs'] = component_dirs
-
-
-def compute_interfaces_info_overall(info_individuals):
- """Compute information about IDL files.
-
- Information is stored in global interfaces_info.
- """
- for info in info_individuals:
- merge_dict_recursively(interfaces_info, info['interfaces_info'])
- # Interfaces in one component may have partial interfaces in
- # another component. This is ok (not a layering violation), since
- # partial interfaces are used to *extend* interfaces.
- # We thus need to update or append if already present
- dict_of_dicts_of_lists_update_or_append(
- partial_interface_files, info['partial_interface_files'])
-
- # Record inheritance information individually
- for interface_name, interface_info in interfaces_info.items():
- extended_attributes = interface_info['extended_attributes']
- inherited_extended_attributes_by_interface[interface_name] = dict(
- (key, value) for key, value in extended_attributes.items()
- if key in INHERITED_EXTENDED_ATTRIBUTES)
- parent = interface_info['parent']
- if parent:
- parent_interfaces[interface_name] = parent
-
- # Once all individual files handled, can compute inheritance information
- # and dependencies
-
- # Compute inheritance info
- for interface_name in interfaces_info:
- compute_inheritance_info(interface_name)
-
- # Compute dependencies
- # Move includes info from mixin (rhs of 'includes') to interface (lhs of
- # 'includes').
- # Note that moving an 'includes' statement between files does not change the
- # info itself (or hence cause a rebuild)!
- for mixin_name, interface_info in interfaces_info.items():
- for interface_name in interface_info['included_by_interfaces']:
- interfaces_info[interface_name]['including_mixins'].append(
- mixin_name)
- del interface_info['included_by_interfaces']
-
- # An IDL file's dependencies are partial interface files that extend it,
- # and files for other interfaces that this interfaces include.
- for interface_name, interface_info in interfaces_info.items():
- partial_interface_paths = partial_interface_files[interface_name]
- partial_interfaces_full_paths = partial_interface_paths['full_paths']
- # Partial interface definitions each need an include, as they are
- # implemented in separate classes from the main interface.
- partial_interfaces_include_paths = \
- partial_interface_paths['include_paths']
-
- mixins = interface_info['including_mixins']
- try:
- mixins_info = [interfaces_info[mixin] for mixin in mixins]
- except KeyError as key_name:
- raise IdlInterfaceFileNotFoundError(
- 'Could not find the IDL file where the following mixin is defined: %s'
- % key_name)
- mixins_full_paths = [
- mixin_info['full_path'] for mixin_info in mixins_info
- ]
- # Mixins don't need include files, as this is handled in the Blink
- # implementation (they are implemented on |impl| itself, hence header
- # declaration is included in the interface class).
- # However, they are needed for legacy mixins that are being treated as
- # partial interfaces, until we remove these.
- # https://crbug.com/360435
- mixins_include_paths = [
- mixin_info['include_path'] for mixin_info in mixins_info
- if mixin_info['is_legacy_treat_as_partial_interface']
- ]
-
- dependencies_full_paths = mixins_full_paths
- dependencies_include_paths = mixins_include_paths
- dependencies_other_component_full_paths = []
- dependencies_other_component_include_paths = []
-
- component = idl_filename_to_component(interface_info['full_path'])
- for full_path in partial_interfaces_full_paths:
- partial_interface_component = idl_filename_to_component(full_path)
- if component == partial_interface_component:
- dependencies_full_paths.append(full_path)
- else:
- dependencies_other_component_full_paths.append(full_path)
-
- for include_path in partial_interfaces_include_paths:
- partial_interface_component = idl_filename_to_component(
- include_path)
- if component == partial_interface_component:
- dependencies_include_paths.append(include_path)
- else:
- dependencies_other_component_include_paths.append(include_path)
-
- interface_info.update({
- 'dependencies_full_paths':
- dependencies_full_paths,
- 'dependencies_include_paths':
- dependencies_include_paths,
- 'dependencies_other_component_full_paths':
- dependencies_other_component_full_paths,
- 'dependencies_other_component_include_paths':
- dependencies_other_component_include_paths,
- })
-
- # Clean up temporary private information
- for interface_info in interfaces_info.values():
- del interface_info['extended_attributes']
- del interface_info['union_types']
- del interface_info['is_legacy_treat_as_partial_interface']
-
- # Compute global_type_info to interfaces_info so that idl_compiler does
- # not need to always calculate the info in __init__.
- compute_global_type_info()
-
-
-################################################################################
-
-
-def main():
- _, args = parse_options()
- # args = Input1, Input2, ..., Output
- interfaces_info_filename = args.pop()
- info_individuals = read_pickle_files(args)
-
- compute_interfaces_info_overall(info_individuals)
- write_pickle_file(interfaces_info_filename, interfaces_info)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
index 0d5eeabb6c3..47769c30f4a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
@@ -5,62 +5,75 @@
Runs the bindings code generator for the given tasks.
"""
-import optparse
+import argparse
import sys
import web_idl
import bind_gen
-def parse_options():
- parser = optparse.OptionParser(usage="%prog [options] TASK...")
- parser.add_option(
- "--web_idl_database",
- type="string",
- help="filepath of the input database")
- parser.add_option(
- "--root_src_dir",
- type="string",
- help='root directory of chromium project, i.e. "//"')
- parser.add_option(
- "--root_gen_dir",
- type="string",
- help='root directory of generated code files, i.e. '
- '"//out/Default/gen"')
- parser.add_option(
- "--output_core_reldir",
- type="string",
- help='output directory for "core" component relative to '
- 'root_gen_dir')
- parser.add_option(
- "--output_modules_reldir",
- type="string",
- help='output directory for "modules" component relative '
- 'to root_gen_dir')
- parser.add_option(
+def parse_output_reldirs(reldirs):
+ required = ['core', 'modules']
+ valid = required + ['extensions_chromeos']
+ result = {}
+ for key_value_pair in reldirs:
+ key, value = key_value_pair.split("=", 1)
+ key = key.strip()
+ result[key] = value
+
+ for c in required:
+ assert c in result, 'missing required --output_reldir "{0}"'.format(c)
+
+ for c in result.keys():
+ assert c in valid, 'invalid --output_reldir "{0}"'.format(c)
+
+ return result
+
+
+def parse_options(valid_tasks):
+ parser = argparse.ArgumentParser(
+ description='Generator for blink bindings.')
+ parser.add_argument("--web_idl_database",
+ required=True,
+ type=str,
+ help="filepath of the input database")
+ parser.add_argument("--root_src_dir",
+ required=True,
+ type=str,
+ help='root directory of chromium project, i.e. "//"')
+ parser.add_argument("--root_gen_dir",
+ required=True,
+ type=str,
+ help='root directory of generated code files, i.e. '
+ '"//out/Default/gen"')
+ parser.add_argument(
+ "--output_reldir",
+ metavar="KEY=VALUE",
+ action="append",
+ help="output directory of KEY component relative to root_gen_dir.")
+ parser.add_argument(
+ '--format_generated_files',
+ action="store_true",
+ default=False,
+ help=("format the resulting generated files by applying clang-format, "
+ "etc."))
+ parser.add_argument(
'--single_process',
action="store_true",
default=False,
help=('run everything in a single process, which makes debugging '
'easier'))
- options, args = parser.parse_args()
+ parser.add_argument('tasks',
+ nargs='+',
+ choices=valid_tasks,
+ help='types to generate')
- required_option_names = ("web_idl_database", "root_src_dir",
- "root_gen_dir", "output_core_reldir",
- "output_modules_reldir")
- for opt_name in required_option_names:
- if getattr(options, opt_name) is None:
- parser.error("--{} is a required option.".format(opt_name))
+ options = parser.parse_args()
- if not args:
- parser.error("No argument specified.")
-
- return options, args
+ return options
def main():
- options, tasks = parse_options()
-
dispatch_table = {
'callback_function': bind_gen.generate_callback_functions,
'callback_interface': bind_gen.generate_callback_interfaces,
@@ -72,22 +85,23 @@ def main():
'union': bind_gen.generate_unions,
}
- for task in tasks:
- if task not in dispatch_table:
- sys.exit("Unknown task: {}".format(task))
+ options = parse_options(dispatch_table.keys())
+
+ output_reldirs = parse_output_reldirs(options.output_reldir)
+
+ component_reldirs = {}
+ for component, reldir in output_reldirs.items():
+ component_reldirs[web_idl.Component(component)] = reldir
- component_reldirs = {
- web_idl.Component('core'): options.output_core_reldir,
- web_idl.Component('modules'): options.output_modules_reldir,
- }
bind_gen.init(web_idl_database_path=options.web_idl_database,
root_src_dir=options.root_src_dir,
root_gen_dir=options.root_gen_dir,
- component_reldirs=component_reldirs)
+ component_reldirs=component_reldirs,
+ enable_style_format=options.format_generated_files)
task_queue = bind_gen.TaskQueue(single_process=options.single_process)
- for task in tasks:
+ for task in options.tasks:
dispatch_table[task](task_queue)
def print_to_console(message):
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
deleted file mode 100755
index 8a571d5a68a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
+++ /dev/null
@@ -1,220 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-"""Generates interface properties on global objects.
-
-Concretely these are implemented as "constructor attributes", meaning
-"attributes whose name ends with Constructor" (special-cased by code generator),
-hence "global constructors" for short.
-
-For reference on global objects, see:
-http://heycam.github.io/webidl/#Global
-http://heycam.github.io/webidl/#Exposed
-
-Design document: http://www.chromium.org/developers/design-documents/idl-build
-"""
-
-# pylint: disable=relative-import
-
-import itertools
-import optparse
-import os
-import re
-import sys
-
-from collections import defaultdict
-from utilities import get_file_contents
-from utilities import get_first_interface_name_from_idl
-from utilities import get_interface_exposed_arguments
-from utilities import get_interface_extended_attributes_from_idl
-from utilities import is_non_legacy_callback_interface_from_idl
-from utilities import is_interface_mixin_from_idl
-from utilities import read_file_to_list
-from utilities import read_pickle_file
-from utilities import should_generate_impl_file_from_idl
-from utilities import write_file
-from v8_utilities import EXPOSED_EXECUTION_CONTEXT_METHOD
-
-interface_name_to_global_names = {}
-global_name_to_constructors = defaultdict(list)
-
-HEADER_FORMAT = """// Stub header file for {{idl_basename}}
-// Required because the IDL compiler assumes that a corresponding header
-// file exists for each IDL file.
-"""
-
-
-def parse_options():
- parser = optparse.OptionParser()
- parser.add_option('--idl-files-list', help='file listing IDL files')
- parser.add_option(
- '--global-objects-file', help='pickle file of global objects')
- options, args = parser.parse_args()
-
- if options.idl_files_list is None:
- parser.error(
- 'Must specify a file listing IDL files using --idl-files-list.')
- if options.global_objects_file is None:
- parser.error(
- 'Must specify a pickle file of global objects using --global-objects-file.'
- )
-
- return options, args
-
-
-def flatten_list(iterable):
- return list(itertools.chain.from_iterable(iterable))
-
-
-def interface_name_to_constructors(interface_name):
- """Returns constructors for an interface."""
- global_names = interface_name_to_global_names[interface_name]
- return flatten_list(global_name_to_constructors[global_name]
- for global_name in global_names)
-
-
-def record_global_constructors(idl_filename):
- full_path = os.path.realpath(idl_filename)
- idl_file_contents = get_file_contents(full_path)
- extended_attributes = get_interface_extended_attributes_from_idl(
- idl_file_contents)
- interface_name = get_first_interface_name_from_idl(idl_file_contents)
-
- # An interface property is produced for every non-callback interface
- # that does not have [LegacyNoInterfaceObject].
- # http://heycam.github.io/webidl/#es-interfaces
- if (not should_generate_impl_file_from_idl(idl_file_contents)
- or is_non_legacy_callback_interface_from_idl(idl_file_contents)
- or is_interface_mixin_from_idl(idl_file_contents)
- or 'LegacyNoInterfaceObject' in extended_attributes):
- return
-
- exposed_arguments = get_interface_exposed_arguments(idl_file_contents)
- if exposed_arguments:
- # Exposed(Arguments) case
- for argument in exposed_arguments:
- if 'RuntimeEnabled' in extended_attributes:
- raise ValueError(
- 'RuntimeEnabled should not be used with Exposed(Arguments)'
- )
- attributes = extended_attributes.copy()
- attributes['RuntimeEnabled'] = argument['runtime_enabled']
- new_constructors_list = generate_global_constructors_list(
- interface_name, attributes)
- global_name_to_constructors[argument['exposed']].extend(
- new_constructors_list)
- elif 'Exposed' in extended_attributes:
- # Exposed=env or Exposed=(env1,...) case
- exposed_value = extended_attributes.get('Exposed')
- exposed_global_names = map(str.strip,
- exposed_value.strip('()').split(','))
- new_constructors_list = generate_global_constructors_list(
- interface_name, extended_attributes)
- for name in exposed_global_names:
- global_name_to_constructors[name].extend(new_constructors_list)
-
-
-def generate_global_constructors_list(interface_name, extended_attributes):
- extended_attributes_list = [
- name +
- (('=' +
- extended_attributes[name]) if extended_attributes[name] else '')
- for name in [
- 'RuntimeEnabled', 'ContextEnabled', 'CrossOriginIsolated',
- 'DirectSocketEnabled', 'SecureContext'
- ] if name in extended_attributes
- ]
-
- # Getters for these Constructors are auto-generated and considered
- # side-effect free w.r.t to V8. That is, executing the getter has no
- # JavaScript observable effect.
- extended_attributes_list.append('Affects=Nothing')
-
- extended_string = '[%s] ' % ', '.join(extended_attributes_list)
-
- attribute_string = 'attribute {interface_name}Constructor {interface_name}'.format(
- interface_name=interface_name)
- attributes_list = [extended_string + attribute_string]
-
- # In addition to the usual interface property, for every [NamedConstructor]
- # extended attribute on an interface, a corresponding property MUST exist
- # on the ECMAScript global object.
- # http://heycam.github.io/webidl/#NamedConstructor
- if 'NamedConstructor' in extended_attributes:
- named_constructor = extended_attributes['NamedConstructor']
- # Extract function name, namely everything before opening '('
- constructor_name = re.sub(r'\(.*', '', named_constructor)
- # Note the reduplicated 'ConstructorConstructor'
- # FIXME: rename to NamedConstructor
- attribute_string = 'attribute %sConstructorConstructor %s' % (
- interface_name, constructor_name)
- attributes_list.append(extended_string + attribute_string)
-
- return attributes_list
-
-
-def write_global_constructors_partial_interface(interface_name, idl_filename,
- constructor_attributes_list):
- idl_basename = os.path.basename(idl_filename)
- basename = os.path.splitext(idl_basename)[0]
- # FIXME: replace this with a simple Jinja template
- lines = ([
- '[\n',
- ' ImplementedAs=%s\n' % basename,
- '] partial interface %s {\n' % interface_name
- ] + [
- ' %s;\n' % constructor_attribute
- # FIXME: sort by interface name (not first by extended attributes)
- for constructor_attribute in sorted(constructor_attributes_list)
- ] + ['};\n'])
- write_file(''.join(lines), idl_filename)
- header_filename = os.path.splitext(idl_filename)[0] + '.h'
- write_file(
- HEADER_FORMAT.format(idl_basename=idl_basename), header_filename)
-
-
-################################################################################
-
-
-def main():
- options, args = parse_options()
-
- # File paths of input IDL files are passed in a file, which is generated at
- # GN time. It is OK because the target IDL files are static.
- idl_files = read_file_to_list(options.idl_files_list)
-
- # Output IDL files (to generate) are passed at the command line, since
- # these are in the build directory, which is determined at build time, not
- # GN time.
- # These are passed as pairs of GlobalObjectName, global_object.idl
- interface_name_idl_filename = [(args[i], args[i + 1])
- for i in range(0, len(args), 2)]
-
- interface_name_to_global_names.update(
- read_pickle_file(options.global_objects_file))
-
- for idl_filename in idl_files:
- record_global_constructors(idl_filename)
-
- # Check for [Exposed] / [Global] mismatch.
- known_global_names = EXPOSED_EXECUTION_CONTEXT_METHOD.keys()
- exposed_global_names = frozenset(global_name_to_constructors)
- if not exposed_global_names.issubset(known_global_names):
- unknown_global_names = exposed_global_names.difference(
- known_global_names)
- raise ValueError('The following global names were used in '
- '[Exposed=xxx] but do not match any global names: %s'
- % list(unknown_global_names))
-
- # Write partial interfaces containing constructor attributes for each
- # global interface.
- for interface_name, idl_filename in interface_name_idl_filename:
- constructors = interface_name_to_constructors(interface_name)
- write_global_constructors_partial_interface(interface_name,
- idl_filename, constructors)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
deleted file mode 100755
index 91aa20bc7d0..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python
-# 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.
-"""Generate initPartialInterfacesInModules(), which registers partial
-interfaces in modules to core interfaces.
-"""
-
-# pylint: disable=relative-import
-
-from __future__ import print_function
-
-from optparse import OptionParser
-import os
-import posixpath
-import sys
-
-from utilities import get_file_contents
-from utilities import get_first_interface_name_from_idl
-from utilities import read_idl_files_list_from_file
-from utilities import should_generate_impl_file_from_idl
-from utilities import write_file
-from v8_utilities import build_basename
-
-_COPYRIGHT = """// 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.
-"""
-
-_INIT_PARTIAL_INTERFACE = """%s
-%s
-
-namespace blink {
-
-void InitPartialInterfacesInModules() {
-%s
-}
-
-} // namespace blink
-"""
-
-
-def parse_options():
- usage = 'Usage: %prog [options]'
- parser = OptionParser(usage=usage)
- parser.add_option(
- '--idl-files-list',
- help='a text file containing the IDL file paths, so the command '
- 'line doesn\'t exceed OS length limits.')
- parser.add_option('--output')
-
- options, args = parser.parse_args()
- if options.output is None:
- parser.error('Must specify output file using --output.')
- if options.idl_files_list is None:
- parser.error(
- 'Must specify a list of IDL files using --idl-files-list.')
- return options
-
-
-def extract_meta_data(file_paths):
- """Extracts interface name from each IDL file."""
- meta_data_list = []
-
- for file_path in file_paths:
- if not file_path.endswith('.idl'):
- print('WARNING: non-IDL file passed: "%s"' % file_path)
- continue
- if not os.path.exists(file_path):
- print('WARNING: file not found: "%s"' % file_path)
- continue
-
- idl_file_contents = get_file_contents(file_path)
- if not should_generate_impl_file_from_idl(idl_file_contents):
- continue
-
- # Extract interface name from file content
- basename = get_first_interface_name_from_idl(idl_file_contents)
-
- meta_data = {
- 'basename': basename,
- }
- meta_data_list.append(meta_data)
-
- return meta_data_list
-
-
-def main():
- options = parse_options()
-
- idl_file_names = read_idl_files_list_from_file(options.idl_files_list)
-
- meta_data_list = extract_meta_data(idl_file_names)
- interface_names = [
- 'V8%sPartial' % meta_data['basename'] for meta_data in meta_data_list
- ]
- interface_names.sort()
-
- includes = [
- '#include "third_party/blink/renderer/bindings/modules/v8/%s.h"' %
- build_basename(interface_name) for interface_name in interface_names
- ]
- initialize_calls = [
- ' %s::Initialize();' % interface_name
- for interface_name in interface_names
- ]
-
- content = _INIT_PARTIAL_INTERFACE % (_COPYRIGHT, '\n'.join(includes),
- '\n'.join(initialize_calls))
-
- write_file(content, options.output)
-
-
-if __name__ == '__main__':
- sys.exit(main())
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
deleted file mode 100755
index 3ab08200e05..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
+++ /dev/null
@@ -1,291 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script reads the global interface data collected by
-# compute_interfaces_info_overall.py, and writes out the code which adds
-# bindings for origin-trial-enabled features at runtime.
-
-import optparse
-import os
-import posixpath
-import sys
-from collections import defaultdict, namedtuple
-
-from code_generator import (initialize_jinja_env, normalize_and_sort_includes,
- render_template)
-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, origin_trial_feature_name)
-
-# 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'
-
-OriginTrialInterfaceInfo = namedtuple(
- 'OriginTrialInterfaceInfo',
- ['name', 'v8_class', 'v8_class_or_partial', 'is_global'])
-
-
-def get_install_functions(interfaces, feature_names):
- """Construct a list of V8 bindings installation functions for each feature
- on each interface.
-
- interfaces is a list of OriginTrialInterfaceInfo tuples
- feature_names is a list of strings, containing names of features which can
- be installed on those interfaces.
- """
- return [{
- 'condition':
- 'RuntimeEnabledFeatures::%sEnabled' % feature_name,
- 'name':
- feature_name,
- 'install_method':
- 'Install%s' % feature_name,
- 'interface_is_global':
- interface_info.is_global,
- 'global_type_check_method':
- interface_global_type_check_method(interface_info),
- 'v8_class':
- interface_info.v8_class,
- 'v8_class_or_partial':
- interface_info.v8_class_or_partial,
- } for feature_name in feature_names for interface_info in interfaces]
-
-
-def get_origin_trial_feature_names_from_interface(interface, runtime_features):
- feature_names = set()
-
- def add_if_not_none(value):
- if value:
- feature_names.add(value)
-
- if interface.is_partial:
- add_if_not_none(origin_trial_feature_name(interface, runtime_features))
- for operation in interface.operations:
- add_if_not_none(origin_trial_feature_name(operation, runtime_features))
- for attribute in interface.attributes:
- add_if_not_none(origin_trial_feature_name(attribute, runtime_features))
- return feature_names
-
-
-def read_idl_file(reader, idl_filename):
- definitions = reader.read_idl_file(idl_filename)
- interfaces = definitions.interfaces
- includes = definitions.includes
- # There should only be a single interface defined in an IDL file. Return it.
- assert len(interfaces) == 1, (
- "Expected one interface in file %r, found %d" %
- (idl_filename, len(interfaces)))
- return (list(interfaces.values())[0], includes)
-
-
-def interface_is_global(interface):
- return 'Global' in interface.extended_attributes
-
-
-def interface_global_type_check_method(interface_info):
- """Generate the name of the method on ExecutionContext used to check if the
- context matches the type of the interface, which is a global.
-
- Returns None for non-global interfaces.
- """
- if not interface_info.is_global:
- return None
-
- return 'Is%s' % interface_info.name
-
-
-def origin_trial_features_info(info_provider, reader, idl_filenames,
- target_component):
- """Read a set of IDL files and compile the mapping between interfaces and
- the conditional features defined on them.
-
- Returns a tuple (features_for_type, types_for_feature, includes):
- - features_for_type is a mapping of interface->feature
- - types_for_feature is the reverse mapping: feature->interface
- - includes is a set of header files which need to be included in the
- generated implementation code.
- """
- features_for_type = defaultdict(set)
- types_for_feature = defaultdict(set)
- include_files = set()
- runtime_features = info_provider.component_info['runtime_enabled_features']
-
- for idl_filename in idl_filenames:
- interface, includes = read_idl_file(reader, idl_filename)
- feature_names = get_origin_trial_feature_names_from_interface(
- interface, runtime_features)
-
- # If this interface is a mixin, we don't generate V8 bindings code for
- # it.
- # TODO(crbug.com/1061995): This incorrectly ignores includes in the
- # mixin idl like "SomeInterface includes MixinInterface".
- if interface.is_mixin:
- continue
-
- # If this interface include another one,
- # it inherits any conditional features from it.
- for include in includes:
- assert include.interface == interface.name, (
- "'includes' interface identifier %r in file %r should be %r" %
- (include.interface, idl_filename, interface.name))
- mixin, _ = read_idl_file(
- reader,
- info_provider.interfaces_info[include.mixin].get('full_path'))
- feature_names |= get_origin_trial_feature_names_from_interface(
- mixin, runtime_features)
-
- feature_names = list(feature_names)
- if feature_names:
- is_global = interface_is_global(interface)
- if interface.is_partial:
- # For partial interfaces, we need to generate different
- # |include_files| if the parent interface is in a different
- # component.
- parent_interface_info = \
- info_provider.interfaces_info[interface.name]
- parent_interface, _ = read_idl_file(
- reader, parent_interface_info.get('full_path'))
- is_global = is_global or interface_is_global(parent_interface)
- parent_component = idl_filename_to_component(
- parent_interface_info.get('full_path'))
- if interface.is_partial and target_component != parent_component:
- include_files.add('bindings/%s/v8/%s' % (
- parent_component, binding_header_filename(interface.name)))
- include_files.add(
- 'bindings/%s/v8/%s' %
- (target_component,
- binding_header_filename(interface.name + 'Partial')))
- else:
- include_files.add('bindings/%s/v8/%s' % (
- target_component, binding_header_filename(interface.name)))
- # If this is a partial interface in the same component as
- # its parent, then treat it as a non-partial interface.
- interface.is_partial = False
- interface_info = OriginTrialInterfaceInfo(
- interface.name, v8_class_name(interface),
- v8_class_name_or_partial(interface), is_global)
- for feature_name in feature_names:
- features_for_type[interface_info].add(feature_name)
- types_for_feature[feature_name].add(interface_info)
-
- return features_for_type, types_for_feature, include_files
-
-
-def origin_trial_features_context(generator_name, feature_info):
- context = {'code_generator': generator_name}
-
- # Unpack the feature info tuple.
- features_for_type, types_for_feature, include_files = feature_info
-
- # Add includes needed for cpp code and normalize.
- include_files.update([
- 'core/context_features/context_feature_settings.h',
- 'core/execution_context/execution_context.h',
- 'core/frame/frame.h',
- 'core/origin_trials/origin_trials.h',
- 'platform/bindings/origin_trial_features.h',
- 'platform/bindings/script_state.h',
- 'platform/bindings/v8_per_context_data.h',
- 'platform/runtime_enabled_features.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',
- ])
- context['includes'] = normalize_and_sort_includes(include_files)
-
- # For each interface, collect a list of bindings installation functions to
- # call, organized by conditional feature.
- context['installers_by_interface'] = [{
- 'name':
- interface_info.name,
- 'is_global':
- interface_info.is_global,
- 'v8_class':
- interface_info.v8_class,
- 'installers':
- get_install_functions([interface_info], feature_names)
- } for interface_info, feature_names in features_for_type.items()]
- context['installers_by_interface'].sort(key=lambda x: x['name'])
-
- # For each conditional feature, collect a list of bindings installation
- # functions to call, organized by interface.
- context['installers_by_feature'] = [{
- 'name':
- feature_name,
- 'name_constant':
- 'OriginTrialFeature::k%s' % feature_name,
- 'installers':
- get_install_functions(interfaces, [feature_name])
- } for feature_name, interfaces in types_for_feature.items()]
- context['installers_by_feature'].sort(key=lambda x: x['name'])
-
- return context
-
-
-def parse_options():
- parser = optparse.OptionParser()
- parser.add_option(
- '--cache-directory',
- help='cache directory, defaults to output directory')
- parser.add_option('--output-directory')
- parser.add_option('--info-dir')
- parser.add_option(
- '--target-component',
- type='choice',
- choices=['core', 'modules'],
- help='target component to generate code')
- parser.add_option('--idl-files-list')
-
- options, _ = parser.parse_args()
- if options.output_directory is None:
- parser.error('Must specify output directory using --output-directory.')
- return options
-
-
-def generate_origin_trial_features(info_provider, options, idl_filenames):
- reader = IdlReader(info_provider.interfaces_info, options.cache_directory)
- jinja_env = initialize_jinja_env(options.cache_directory)
-
- # Extract the bidirectional mapping of conditional features <-> interfaces
- # from the global info provider and the supplied list of IDL files.
- feature_info = origin_trial_features_info(
- info_provider, reader, idl_filenames, options.target_component)
-
- # Convert that mapping into the context required for the Jinja2 templates.
- template_context = origin_trial_features_context(MODULE_PYNAME,
- feature_info)
-
- file_basename = 'origin_trial_features_for_%s' % options.target_component
-
- # Generate and write out the header file
- header_text = render_template(
- jinja_env.get_template(file_basename + '.h.tmpl'), template_context)
- header_path = posixpath.join(options.output_directory,
- file_basename + '.h')
- write_file(header_text, header_path)
-
- # Generate and write out the implementation file
- cpp_text = render_template(
- jinja_env.get_template(file_basename + '.cc.tmpl'), template_context)
- cpp_path = posixpath.join(options.output_directory, file_basename + '.cc')
- write_file(cpp_text, cpp_path)
-
-
-def main():
- options = parse_options()
-
- info_provider = create_component_info_provider(
- os.path.normpath(options.info_dir), options.target_component)
- idl_filenames = list(map(str.strip, open(options.idl_files_list)))
-
- generate_origin_trial_features(info_provider, options, idl_filenames)
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
deleted file mode 100644
index 4f23b299d0d..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
+++ /dev/null
@@ -1,277 +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.
-
-# pylint: disable=relative-import
-
-import argparse
-import os
-import posixpath
-
-from code_generator import initialize_jinja_env
-from idl_reader import IdlReader
-from utilities import create_component_info_provider, write_file
-import utilities
-import v8_attributes
-import v8_interface
-import v8_types
-import v8_utilities
-
-INCLUDES = frozenset([
- 'third_party/blink/renderer/bindings/core/v8/generated_code_helper.h',
- 'third_party/blink/renderer/bindings/core/v8/v8_html_document.h',
- 'third_party/blink/renderer/bindings/core/v8/v8_initializer.h',
- 'third_party/blink/renderer/bindings/core/v8/v8_window.h',
- 'third_party/blink/renderer/platform/bindings/v8_object_constructor.h',
- 'v8/include/v8.h'
-])
-
-TEMPLATE_FILE = 'external_reference_table.cc.tmpl'
-
-SNAPSHOTTED_INTERFACES = frozenset([
- 'Window',
- 'EventTarget',
- 'HTMLDocument',
- 'Document',
- 'Node',
-])
-
-
-def parse_args():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- '--idl-files-list',
- type=str,
- required=True,
- help='file listing IDL files')
- parser.add_argument(
- '--output', type=str, required=True, help='output file path')
- parser.add_argument(
- '--info-dir',
- type=str,
- required=True,
- help='directory contains component info')
- parser.add_argument(
- '--cache-dir', type=str, required=True, help='cache directory')
- parser.add_argument(
- '--target-component', type=str, required=True, help='target component')
- return parser.parse_known_args()
-
-
-# This class creates a Jinja template context about an interface.
-class InterfaceTemplateContextBuilder(object):
- def __init__(self, opts, info_provider):
- self._opts = opts
- self._info_provider = info_provider
-
- def create_interface_context(self, interface, component, interfaces):
- '''Creates a Jinja context which is based on an interface.'''
-
- assert component in ['core', 'modules']
-
- name = '%s%s' % (v8_utilities.cpp_name(interface),
- 'Partial' if interface.is_partial else '')
-
- # Constructors
- has_constructor_callback = False
- if not interface.is_partial:
- constructors = any(constructor.name == 'Constructor'
- for constructor in interface.constructors)
- custom_constructors = interface.custom_constructors
- html_constructor = 'HTMLConstructor' in interface.extended_attributes
- has_constructor_callback = constructors or custom_constructors or html_constructor
-
- attributes = []
- methods = []
- has_cross_origin_indexed_getter = False
- has_cross_origin_named_enum = False
- has_cross_origin_named_getter = False
- has_cross_origin_named_setter = False
- has_security_check = False
- indexed_property_getter = None
- is_global = False
- named_property_getter = None
- component_info = self._info_provider.component_info
- if interface.name in SNAPSHOTTED_INTERFACES:
- attributes = [
- v8_attributes.attribute_context(interface, attribute,
- interfaces, component_info)
- for attribute in interface.attributes
- ]
- methods = v8_interface.methods_context(interface,
- component_info)['methods']
- is_global = 'Global' in interface.extended_attributes
-
- named_property_getter = v8_interface.property_getter(
- interface.named_property_getter, ['name'])
- indexed_property_getter = v8_interface.property_getter(
- interface.indexed_property_getter, ['index'])
-
- if not interface.is_partial:
- has_security_check = (
- 'CheckSecurity' in interface.extended_attributes
- and interface.name != 'EventTarget')
- has_cross_origin_named_getter = (
- any(method['is_cross_origin'] for method in methods)
- or any(attribute['has_cross_origin_getter']
- for attribute in attributes))
- has_cross_origin_named_setter = any(
- attribute['has_cross_origin_setter']
- for attribute in attributes)
- has_cross_origin_indexed_getter = (
- indexed_property_getter
- and indexed_property_getter['is_cross_origin'])
- has_cross_origin_named_enum = has_cross_origin_named_getter \
- or has_cross_origin_named_setter
- if (named_property_getter
- and named_property_getter['is_cross_origin']):
- has_cross_origin_named_getter = True
-
- return {
- 'attributes':
- attributes,
- 'component':
- component,
- 'has_constructor_callback':
- has_constructor_callback,
- 'has_cross_origin_named_getter':
- has_cross_origin_named_getter,
- 'has_cross_origin_named_setter':
- has_cross_origin_named_setter,
- 'has_cross_origin_named_enumerator':
- has_cross_origin_named_enum,
- 'has_cross_origin_indexed_getter':
- has_cross_origin_indexed_getter,
- 'has_security_check':
- has_security_check,
- 'indexed_property_getter':
- indexed_property_getter,
- 'indexed_property_setter':
- v8_interface.property_setter(interface.indexed_property_setter,
- interface),
- 'indexed_property_deleter':
- v8_interface.property_deleter(interface.indexed_property_deleter),
- 'internal_namespace':
- v8_interface.internal_namespace(interface),
- 'is_partial':
- interface.is_partial,
- 'methods':
- methods,
- 'name':
- name,
- 'named_constructor':
- v8_interface.named_constructor_context(interface),
- 'named_property_getter':
- named_property_getter,
- 'named_property_setter':
- v8_interface.property_setter(interface.named_property_setter,
- interface),
- 'named_property_deleter':
- v8_interface.property_deleter(interface.named_property_deleter),
- 'v8_class':
- v8_utilities.v8_class_name_or_partial(interface),
- }
-
-
-# This class applies a Jinja template and creates a .cpp file for the external reference table.
-class ExternalReferenceTableGenerator(object):
- def __init__(self, opts, info_provider):
- self._opts = opts
- self._info_provider = info_provider
- self._reader = IdlReader(info_provider.interfaces_info, opts.cache_dir)
- self._interface_contexts = {}
- self._include_files = set(INCLUDES)
- v8_types.set_component_dirs(
- info_provider.interfaces_info['component_dirs'])
-
- # Creates a Jinja context from an IDL file.
- def process_idl_file(self, idl_filename):
- definitions = self._reader.read_idl_definitions(idl_filename)
- for component in definitions:
- target_definitions = definitions[component]
- interfaces = target_definitions.interfaces
- first_name = target_definitions.first_name
- if first_name in interfaces.keys():
- interface = interfaces[first_name]
- self._process_interface(interface, component, interfaces)
-
- # Creates a Jinja context from an interface. Some interfaces are not used
- # in V8 context snapshot, so we can skip them.
- def _process_interface(self, interface, component, interfaces):
- def has_impl(interface):
- component_info = self._info_provider.component_info
- runtime_features = component_info['runtime_enabled_features']
- # Non legacy callback interface does not provide V8 callbacks.
- if interface.is_callback:
- return len(interface.constants) > 0
- if v8_utilities.runtime_enabled_feature_name(
- interface, runtime_features):
- return False
- if 'Exposed' not in interface.extended_attributes:
- return True
- return any(
- exposure.exposed == 'Window'
- and exposure.runtime_enabled is None
- for exposure in interface.extended_attributes['Exposed'])
-
- if not has_impl(interface):
- return
-
- context_builder = InterfaceTemplateContextBuilder(
- self._opts, self._info_provider)
- context = context_builder.create_interface_context(
- interface, component, interfaces)
- name = '%s%s' % (interface.name,
- 'Partial' if interface.is_partial else '')
- self._interface_contexts[name] = context
-
- # Do not include unnecessary header files.
- if not context['attributes'] and not context['named_property_setter']:
- return
-
- include_file = 'third_party/blink/renderer/bindings/%s/v8/%s.h' % (
- component, utilities.to_snake_case(context['v8_class']))
- self._include_files.add(include_file)
-
- # Gathers all interface-dependent information and returns as a Jinja template context.
- def _create_template_context(self):
- interfaces = []
- for name in sorted(self._interface_contexts):
- interfaces.append(self._interface_contexts[name])
- header_path = 'third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.h'
- include_files = list(self._include_files)
- return {
- 'class': 'V8ContextSnapshotExternalReferences',
- 'interfaces': interfaces,
- 'include_files': sorted(include_files),
- 'this_include_header_path': header_path,
- 'code_generator': os.path.basename(__file__),
- 'jinja_template_filename': TEMPLATE_FILE
- }
-
- # Applies a Jinja template on a context and generates a C++ code.
- def generate(self):
- jinja_env = initialize_jinja_env(self._opts.cache_dir)
- context = self._create_template_context()
- cpp_template = jinja_env.get_template(TEMPLATE_FILE)
- cpp_text = cpp_template.render(context)
- return cpp_text
-
-
-def main():
- opts, _ = parse_args()
- # TODO(peria): get rid of |info_provider|
- info_provider = create_component_info_provider(opts.info_dir,
- opts.target_component)
- generator = ExternalReferenceTableGenerator(opts, info_provider)
-
- idl_files = utilities.read_idl_files_list_from_file(opts.idl_files_list)
- for idl_file in idl_files:
- generator.process_idl_file(idl_file)
- output_code = generator.generate()
- output_path = opts.output
- write_file(output_code, output_path)
-
-
-if __name__ == '__main__':
- main()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py
deleted file mode 100755
index 22ac9c29024..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env python
-# 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.
-"""Compile an .idl file to Blink V8 bindings (.h and .cpp files).
-
-Design doc: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/IDLCompiler.md
-"""
-
-import abc
-from optparse import OptionParser
-import os
-import sys
-
-from code_generator_v8 import CodeGeneratorDictionaryImpl
-from code_generator_v8 import CodeGeneratorV8
-from code_generator_v8 import CodeGeneratorUnionType
-from code_generator_v8 import CodeGeneratorCallbackFunction
-from idl_reader import IdlReader
-from utilities import create_component_info_provider
-from utilities import read_idl_files_list_from_file
-from utilities import write_file
-
-
-def parse_options():
- parser = OptionParser()
- parser.add_option(
- '--cache-directory',
- help='cache directory, defaults to output directory')
- parser.add_option('--generate-impl', action='store_true', default=False)
- parser.add_option('--generate-impl-skip-callback-function',
- action='store_true',
- default=False)
- parser.add_option(
- '--read-idl-list-from-file', action='store_true', default=False)
- parser.add_option('--output-directory')
- parser.add_option('--impl-output-directory')
- parser.add_option('--info-dir')
- # FIXME: We should always explicitly specify --target-component and
- # remove the default behavior.
- parser.add_option(
- '--target-component',
- type='choice',
- choices=['core', 'modules'],
- help='target component to generate code, defaults to '
- 'component of input idl file')
- # ensure output comes last, so command line easy to parse via regexes
- parser.disable_interspersed_args()
-
- options, args = parser.parse_args()
- if options.output_directory is None:
- parser.error('Must specify output directory using --output-directory.')
- if len(args) != 1:
- parser.error(
- 'Must specify exactly 1 input file as argument, but %d given.' %
- len(args))
- idl_filename = os.path.realpath(args[0])
- return options, idl_filename
-
-
-class IdlCompiler(object):
- """The IDL Compiler.
-
- """
- __metaclass__ = abc.ABCMeta
-
- def __init__(self,
- output_directory,
- cache_directory=None,
- code_generator_class=None,
- info_provider=None,
- target_component=None):
- """
- Args:
- output_directory: directory to put output files.
- cache_directory: directory which contains PLY caches.
- code_generator_class: code generator class to be used.
- info_provider: component-specific information provider.
- target_component: component to be processed.
- """
- self.cache_directory = cache_directory
- self.info_provider = info_provider
- self.output_directory = output_directory
- self.target_component = target_component
- self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
- self.code_generator = code_generator_class(
- self.info_provider, self.cache_directory, self.output_directory)
-
- def compile_and_write(self, idl_filename):
- definitions = self.reader.read_idl_definitions(idl_filename)
- target_definitions = definitions[self.target_component]
- interface_name = target_definitions.first_name
- output_code_list = self.code_generator.generate_code(
- target_definitions, interface_name)
-
- # Generator may choose to omit the file.
- if output_code_list is None:
- return
-
- for output_path, output_code in output_code_list:
- write_file(output_code, output_path)
-
- def compile_file(self, idl_filename):
- self.compile_and_write(idl_filename)
-
-
-def generate_bindings(code_generator_class, info_provider, options,
- input_filenames):
- idl_compiler = IdlCompiler(
- output_directory=options.output_directory,
- cache_directory=options.cache_directory,
- code_generator_class=code_generator_class,
- info_provider=info_provider,
- target_component=options.target_component)
-
- for idl_filename in input_filenames:
- idl_compiler.compile_file(idl_filename)
-
-
-def generate_dictionary_impl(code_generator_class, info_provider, options,
- input_filenames):
- idl_compiler = IdlCompiler(
- output_directory=options.impl_output_directory,
- cache_directory=options.cache_directory,
- code_generator_class=code_generator_class,
- info_provider=info_provider,
- target_component=options.target_component)
-
- for idl_filename in input_filenames:
- idl_compiler.compile_file(idl_filename)
-
-
-def generate_union_type_containers(code_generator_class, info_provider,
- options):
- generator = code_generator_class(info_provider, options.cache_directory,
- options.output_directory,
- options.target_component)
- output_code_list = generator.generate_code()
- for output_path, output_code in output_code_list:
- write_file(output_code, output_path)
-
-
-def generate_callback_function_impl(code_generator_class, info_provider,
- options):
- generator = code_generator_class(info_provider, options.cache_directory,
- options.output_directory,
- options.target_component)
- output_code_list = generator.generate_code()
- for output_path, output_code in output_code_list:
- write_file(output_code, output_path)
-
-
-def main():
- options, input_filename = parse_options()
- info_provider = create_component_info_provider(options.info_dir,
- options.target_component)
- if options.generate_impl or options.read_idl_list_from_file:
- # |input_filename| should be a file which contains a list of IDL
- # dictionary paths.
- input_filenames = read_idl_files_list_from_file(input_filename)
- else:
- input_filenames = [input_filename]
-
- if options.generate_impl:
- if not info_provider.interfaces_info:
- raise Exception('Interfaces info is required to generate '
- 'impl classes')
- generate_dictionary_impl(CodeGeneratorDictionaryImpl, info_provider,
- options, input_filenames)
- generate_union_type_containers(CodeGeneratorUnionType, info_provider,
- options)
- if not options.generate_impl_skip_callback_function:
- generate_callback_function_impl(CodeGeneratorCallbackFunction,
- info_provider, options)
- else:
- generate_bindings(CodeGeneratorV8, info_provider, options,
- input_filenames)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
deleted file mode 100644
index 4ebf537abdd..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
+++ /dev/null
@@ -1,1251 +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.
-
-# pylint: disable=relative-import
-"""Blink IDL Intermediate Representation (IR) classes.
-
-Classes are primarily constructors, which build an IdlDefinitions object
-(and various contained objects) from an AST (produced by blink_idl_parser).
-
-IR stores typedefs and they are resolved by the code generator.
-
-Typedef resolution uses some auxiliary classes and OOP techniques to make this
-a generic call. See TypedefResolver class in code_generator_v8.py.
-
-Class hierarchy (mostly containment, '<' for inheritance):
-
-IdlDefinitions
- IdlCallbackFunction < TypedObject
- IdlEnum :: FIXME: remove, just use a dict for enums
- IdlInterface
- IdlAttribute < TypedObject
- IdlConstant < TypedObject
- IdlLiteral
- IdlOperation < TypedObject
- IdlArgument < TypedObject
- IdlStringifier
- IdlIterable < IdlIterableOrMaplikeOrSetlike
- IdlMaplike < IdlIterableOrMaplikeOrSetlike
- IdlSetlike < IdlIterableOrMaplikeOrSetlike
-
-TypedObject :: Object with one or more attributes that is a type.
-
-IdlArgument is 'picklable', as it is stored in interfaces_info.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-import abc
-
-from idl_types import IdlAnnotatedType
-from idl_types import IdlFrozenArrayType
-from idl_types import IdlNullableType
-from idl_types import IdlRecordType
-from idl_types import IdlSequenceType
-from idl_types import IdlType
-from idl_types import IdlUnionType
-
-SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
-
-################################################################################
-# TypedObject
-################################################################################
-
-
-class TypedObject(object):
- """Object with a type, such as an Attribute or Operation (return value).
-
- The type can be an actual type, or can be a typedef, which must be resolved
- by the TypedefResolver before passing data to the code generator.
- """
- __metaclass__ = abc.ABCMeta
- idl_type_attributes = ('idl_type', )
-
-
-################################################################################
-# Definitions (main container class)
-################################################################################
-
-
-class IdlDefinitions(object):
- def __init__(self, node):
- """Args: node: AST root node, class == 'File'"""
- self.callback_functions = {}
- self.dictionaries = {}
- self.enumerations = {}
- self.includes = []
- self.interfaces = {}
- self.first_name = None
- self.typedefs = {}
-
- node_class = node.GetClass()
- if node_class != 'File':
- raise ValueError('Unrecognized node class: %s' % node_class)
-
- children = node.GetChildren()
- for child in children:
- child_class = child.GetClass()
- if child_class == 'Interface' or child_class == 'Namespace':
- interface = IdlInterface(child)
- self.interfaces[interface.name] = interface
- if not self.first_name:
- self.first_name = interface.name
- elif child_class == 'Typedef':
- typedef = IdlTypedef(child)
- self.typedefs[typedef.name] = typedef
- elif child_class == 'Enum':
- enumeration = IdlEnum(child)
- self.enumerations[enumeration.name] = enumeration
- elif child_class == 'Callback':
- callback_function = IdlCallbackFunction(child)
- self.callback_functions[callback_function.
- name] = callback_function
- elif child_class == 'Includes':
- self.includes.append(IdlIncludes(child))
- elif child_class == 'Dictionary':
- dictionary = IdlDictionary(child)
- self.dictionaries[dictionary.name] = dictionary
- if not self.first_name:
- self.first_name = dictionary.name
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- def accept(self, visitor):
- visitor.visit_definitions(self)
- for interface in self.interfaces.values():
- interface.accept(visitor)
- for callback_function in self.callback_functions.values():
- callback_function.accept(visitor)
- for dictionary in self.dictionaries.values():
- dictionary.accept(visitor)
- for enumeration in self.enumerations.values():
- enumeration.accept(visitor)
- for include in self.includes:
- include.accept(visitor)
- for typedef in self.typedefs.values():
- typedef.accept(visitor)
-
- def update(self, other):
- """Update with additional IdlDefinitions."""
- for interface_name, new_interface in other.interfaces.items():
- if not new_interface.is_partial:
- # Add as new interface
- self.interfaces[interface_name] = new_interface
- continue
-
- # Merge partial to existing interface
- try:
- self.interfaces[interface_name].merge(new_interface)
- except KeyError:
- raise Exception('Tried to merge partial interface for {0}, '
- 'but no existing interface by that name'.
- format(interface_name))
-
- # Merge callbacks and enumerations
- self.enumerations.update(other.enumerations)
- self.callback_functions.update(other.callback_functions)
-
-
-################################################################################
-# Callback Functions
-################################################################################
-
-
-class IdlCallbackFunction(TypedObject):
- def __init__(self, node):
- children = node.GetChildren()
- num_children = len(children)
- if num_children < 2 or num_children > 3:
- raise ValueError('Expected 2 or 3 children, got %s' % num_children)
- type_node = children[0]
- arguments_node = children[1]
- if num_children == 3:
- ext_attributes_node = children[2]
- self.extended_attributes = (
- ext_attributes_node_to_extended_attributes(ext_attributes_node)
- )
- else:
- self.extended_attributes = {}
- arguments_node_class = arguments_node.GetClass()
- if arguments_node_class != 'Arguments':
- raise ValueError(
- 'Expected Arguments node, got %s' % arguments_node_class)
-
- self.name = node.GetName()
- self.idl_type = type_node_to_type(type_node)
- self.arguments = arguments_node_to_arguments(arguments_node)
-
- def accept(self, visitor):
- visitor.visit_callback_function(self)
- for argument in self.arguments:
- argument.accept(visitor)
-
-
-################################################################################
-# Dictionary
-################################################################################
-
-
-class IdlDictionary(object):
- def __init__(self, node):
- self.extended_attributes = {}
- self.is_partial = bool(node.GetProperty('PARTIAL'))
- self.name = node.GetName()
- self.members = []
- self.parent = None
- for child in node.GetChildren():
- child_class = child.GetClass()
- if child_class == 'Inherit':
- self.parent = child.GetName()
- elif child_class == 'Key':
- self.members.append(IdlDictionaryMember(child))
- elif child_class == 'ExtAttributes':
- self.extended_attributes = (
- ext_attributes_node_to_extended_attributes(child))
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- def accept(self, visitor):
- visitor.visit_dictionary(self)
- for member in self.members:
- member.accept(visitor)
-
-
-class IdlDictionaryMember(TypedObject):
- def __init__(self, node):
- self.default_value = None
- self.extended_attributes = {}
- self.idl_type = None
- self.is_required = bool(node.GetProperty('REQUIRED'))
- self.name = node.GetName()
- for child in node.GetChildren():
- child_class = child.GetClass()
- if child_class == 'Type':
- self.idl_type = type_node_to_type(child)
- elif child_class == 'Default':
- self.default_value = default_node_to_idl_literal(child)
- elif child_class == 'ExtAttributes':
- self.extended_attributes = (
- ext_attributes_node_to_extended_attributes(child))
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- def accept(self, visitor):
- visitor.visit_dictionary_member(self)
-
-
-################################################################################
-# Enumerations
-################################################################################
-
-
-class IdlEnum(object):
- def __init__(self, node):
- self.name = node.GetName()
- self.values = []
- for child in node.GetChildren():
- self.values.append(child.GetName())
-
- def accept(self, visitor):
- visitor.visit_enumeration(self)
-
-
-################################################################################
-# Typedefs
-################################################################################
-
-
-class IdlTypedef(object):
- idl_type_attributes = ('idl_type', )
-
- def __init__(self, node):
- self.name = node.GetName()
- self.idl_type = typedef_node_to_type(node)
-
- def accept(self, visitor):
- visitor.visit_typedef(self)
-
-
-################################################################################
-# Interfaces
-################################################################################
-
-
-class IdlInterface(object):
- def __init__(self, node):
- self.attributes = []
- self.constants = []
- self.constructors = []
- self.custom_constructors = []
- self.extended_attributes = {}
- self.operations = []
- self.parent = None
- self.stringifier = None
- self.iterable = None
- self.has_indexed_elements = False
- self.has_named_property_getter = False
- self.maplike = None
- self.setlike = None
- self.original_interface = None
- self.partial_interfaces = []
-
- self.is_callback = bool(node.GetProperty('CALLBACK'))
- self.is_partial = bool(node.GetProperty('PARTIAL'))
- self.is_mixin = bool(node.GetProperty('MIXIN'))
- self.name = node.GetName()
- self.idl_type = IdlType(self.name)
-
- has_indexed_property_getter = False
- has_integer_typed_length = False
-
- # These are used to support both constructor operations and old style
- # [Constructor] extended attributes. Ideally we should do refactoring
- # for constructor code generation but we will use a new code generator
- # soon so this kind of workaround should be fine.
- constructor_operations = []
- custom_constructor_operations = []
- constructor_operations_extended_attributes = {}
-
- def is_invalid_attribute_type(idl_type):
- return idl_type.is_callback_function or \
- idl_type.is_dictionary or \
- idl_type.is_record_type or \
- idl_type.is_sequence_type
-
- children = node.GetChildren()
- for child in children:
- child_class = child.GetClass()
- if child_class == 'Attribute':
- attr = IdlAttribute(child)
- if is_invalid_attribute_type(attr.idl_type):
- raise ValueError(
- 'Type "%s" cannot be used as an attribute.' %
- attr.idl_type)
- if attr.idl_type.is_integer_type and attr.name == 'length':
- has_integer_typed_length = True
- self.attributes.append(attr)
- elif child_class == 'Const':
- self.constants.append(IdlConstant(child))
- elif child_class == 'ExtAttributes':
- extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- self.constructors, self.custom_constructors = (
- extended_attributes_to_constructors(extended_attributes))
- clear_constructor_attributes(extended_attributes)
- self.extended_attributes = extended_attributes
- elif child_class == 'Operation':
- op = IdlOperation(child)
- if 'getter' in op.specials:
- if str(op.arguments[0].idl_type) == 'unsigned long':
- has_indexed_property_getter = True
- elif str(op.arguments[0].idl_type) == 'DOMString':
- self.has_named_property_getter = True
- self.operations.append(op)
- elif child_class == 'Constructor':
- operation = constructor_operation_from_node(child)
- if operation.is_custom:
- custom_constructor_operations.append(operation.constructor)
- else:
- # Check extended attributes consistency when we previously
- # handle constructor operations.
- if constructor_operations:
- check_constructor_operations_extended_attributes(
- constructor_operations_extended_attributes,
- operation.extended_attributes)
- constructor_operations.append(operation.constructor)
- constructor_operations_extended_attributes.update(
- operation.extended_attributes)
- elif child_class == 'Inherit':
- self.parent = child.GetName()
- elif child_class == 'Stringifier':
- self.stringifier = IdlStringifier(child)
- self.process_stringifier()
- elif child_class == 'Iterable':
- self.iterable = IdlIterable(child)
- elif child_class == 'AsyncIterable':
- pass # 'async iterable' is not implemented.
- elif child_class == 'Maplike':
- self.maplike = IdlMaplike(child)
- elif child_class == 'Setlike':
- self.setlike = IdlSetlike(child)
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- if len(list(filter(None,
- [self.iterable, self.maplike, self.setlike]))) > 1:
- raise ValueError(
- 'Interface can only have one of iterable<>, maplike<> and setlike<>.'
- )
-
- # TODO(rakuco): This validation logic should be in v8_interface according to bashi@.
- # At the moment, doing so does not work because several IDL files are partial Window
- # interface definitions, and interface_dependency_resolver.py doesn't seem to have any logic
- # to prevent these partial interfaces from resetting has_named_property to False.
- if 'LegacyUnenumerableNamedProperties' in self.extended_attributes and \
- not self.has_named_property_getter:
- raise ValueError(
- '[LegacyUnenumerableNamedProperties] can be used only in interfaces '
- 'that support named properties.')
-
- if has_integer_typed_length and has_indexed_property_getter:
- self.has_indexed_elements = True
- else:
- if self.iterable is not None and self.iterable.key_type is None:
- raise ValueError(
- 'Value iterators (iterable<V>) must be accompanied by an indexed '
- 'property getter and an integer-typed length attribute.')
-
- if 'LegacyUnforgeable' in self.extended_attributes:
- raise ValueError(
- '[LegacyUnforgeable] cannot appear on interfaces.')
-
- if constructor_operations or custom_constructor_operations:
- if self.constructors or self.custom_constructors:
- raise ValueError('Detected mixed [Constructor] and consructor '
- 'operations. Do not use both in a single '
- 'interface.')
- extended_attributes = (
- convert_constructor_operations_extended_attributes(
- constructor_operations_extended_attributes))
- if any(name in extended_attributes.keys()
- for name in self.extended_attributes.keys()):
- raise ValueError('Detected mixed extended attributes for '
- 'both [Constructor] and constructor '
- 'operations. Do not use both in a single '
- 'interface')
- self.constructors = constructor_operations
- self.custom_constructors = custom_constructor_operations
- self.extended_attributes.update(extended_attributes)
-
- def accept(self, visitor):
- visitor.visit_interface(self)
- for attribute in self.attributes:
- attribute.accept(visitor)
- for constant in self.constants:
- constant.accept(visitor)
- for constructor in self.constructors:
- constructor.accept(visitor)
- for custom_constructor in self.custom_constructors:
- custom_constructor.accept(visitor)
- for operation in self.operations:
- operation.accept(visitor)
- if self.iterable:
- self.iterable.accept(visitor)
- elif self.maplike:
- self.maplike.accept(visitor)
- elif self.setlike:
- self.setlike.accept(visitor)
-
- def process_stringifier(self):
- """Add the stringifier's attribute or named operation child, if it has
- one, as a regular attribute/operation of this interface."""
- if self.stringifier.attribute:
- self.attributes.append(self.stringifier.attribute)
- elif self.stringifier.operation:
- self.operations.append(self.stringifier.operation)
-
- def merge(self, other):
- """Merge in another interface's members (e.g., partial interface)"""
- self.attributes.extend(other.attributes)
- self.constants.extend(other.constants)
- self.operations.extend(other.operations)
- if self.stringifier is None:
- self.stringifier = other.stringifier
-
-
-################################################################################
-# Attributes
-################################################################################
-
-
-class IdlAttribute(TypedObject):
- def __init__(self, node=None):
- self.is_read_only = bool(
- node.GetProperty('READONLY')) if node else False
- self.is_static = bool(node.GetProperty('STATIC')) if node else False
- self.name = node.GetName() if node else None
- self.idl_type = None
- self.extended_attributes = {}
- # In what interface the attribute is (originally) defined when the
- # attribute is inherited from an ancestor interface.
- self.defined_in = None
-
- if node:
- children = node.GetChildren()
- for child in children:
- child_class = child.GetClass()
- if child_class == 'Type':
- self.idl_type = type_node_to_type(child)
- elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- else:
- raise ValueError(
- 'Unrecognized node class: %s' % child_class)
-
- if 'LegacyUnforgeable' in self.extended_attributes and self.is_static:
- raise ValueError(
- '[LegacyUnforgeable] cannot appear on static attributes.')
-
- def accept(self, visitor):
- visitor.visit_attribute(self)
-
- def __lt__(self, other):
- return self.name < other.name
-
-
-################################################################################
-# Constants
-################################################################################
-
-
-class IdlConstant(TypedObject):
- def __init__(self, node):
- children = node.GetChildren()
- num_children = len(children)
- if num_children < 2 or num_children > 3:
- raise ValueError('Expected 2 or 3 children, got %s' % num_children)
- type_node = children[0]
- value_node = children[1]
- value_node_class = value_node.GetClass()
- if value_node_class != 'Value':
- raise ValueError('Expected Value node, got %s' % value_node_class)
-
- self.name = node.GetName()
- # ConstType is more limited than Type, so subtree is smaller and
- # we don't use the full type_node_to_type function.
- self.idl_type = type_node_inner_to_type(type_node)
- self.value = value_node.GetProperty('VALUE')
- # In what interface the attribute is (originally) defined when the
- # attribute is inherited from an ancestor interface.
- self.defined_in = None
-
- if num_children == 3:
- ext_attributes_node = children[2]
- self.extended_attributes = ext_attributes_node_to_extended_attributes(
- ext_attributes_node)
- else:
- self.extended_attributes = {}
-
- def accept(self, visitor):
- visitor.visit_constant(self)
-
-
-################################################################################
-# Literals
-################################################################################
-
-
-class IdlLiteral(object):
- def __init__(self, idl_type, value):
- self.idl_type = idl_type
- self.value = value
- self.is_null = False
-
- def __str__(self):
- if self.idl_type == 'DOMString':
- if self.value:
- return '"%s"' % self.value
- else:
- return 'WTF::g_empty_string'
- if self.idl_type == 'integer':
- return '%d' % self.value
- if self.idl_type == 'float':
- return '%g' % self.value
- if self.idl_type == 'boolean':
- return 'true' if self.value else 'false'
- if self.idl_type == 'dictionary':
- return self.value
- raise ValueError('Unsupported literal type: %s' % self.idl_type)
-
-
-class IdlLiteralNull(IdlLiteral):
- def __init__(self):
- self.idl_type = 'NULL'
- self.value = None
- self.is_null = True
-
- def __str__(self):
- return 'nullptr'
-
-
-def default_node_to_idl_literal(node):
- idl_type = node.GetProperty('TYPE')
- value = node.GetProperty('VALUE')
- if idl_type == 'DOMString':
- if '"' in value or '\\' in value:
- raise ValueError('Unsupported string value: %r' % value)
- return IdlLiteral(idl_type, value)
- if idl_type == 'integer':
- return IdlLiteral(idl_type, int(value, base=0))
- if idl_type == 'float':
- return IdlLiteral(idl_type, float(value))
- if idl_type in ['boolean', 'sequence']:
- return IdlLiteral(idl_type, value)
- if idl_type == 'NULL':
- return IdlLiteralNull()
- if idl_type == 'dictionary':
- return IdlLiteral(idl_type, value)
- raise ValueError('Unrecognized default value type: %s' % idl_type)
-
-
-################################################################################
-# Operations
-################################################################################
-
-
-class IdlOperation(TypedObject):
- def __init__(self, node=None):
- self.arguments = []
- self.extended_attributes = {}
- self.specials = []
- self.is_constructor = False
- self.idl_type = None
- self.is_static = False
- # In what interface the attribute is (originally) defined when the
- # attribute is inherited from an ancestor interface.
- self.defined_in = None
-
- if not node:
- return
-
- self.name = node.GetName()
-
- self.is_static = bool(node.GetProperty('STATIC'))
- property_dictionary = node.GetProperties()
- for special_keyword in SPECIAL_KEYWORD_LIST:
- if special_keyword in property_dictionary:
- self.specials.append(special_keyword.lower())
-
- children = node.GetChildren()
- for child in children:
- child_class = child.GetClass()
- if child_class == 'Arguments':
- self.arguments = arguments_node_to_arguments(child)
- elif child_class == 'Type':
- self.idl_type = type_node_to_type(child)
- elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- if 'LegacyUnforgeable' in self.extended_attributes and self.is_static:
- raise ValueError(
- '[LegacyUnforgeable] cannot appear on static operations.')
-
- @classmethod
- def constructor_from_arguments_node(cls, name, arguments_node):
- constructor = cls()
- constructor.name = name
- constructor.arguments = arguments_node_to_arguments(arguments_node)
- constructor.is_constructor = True
- return constructor
-
- def accept(self, visitor):
- visitor.visit_operation(self)
- for argument in self.arguments:
- argument.accept(visitor)
-
-
-################################################################################
-# Arguments
-################################################################################
-
-
-class IdlArgument(TypedObject):
- def __init__(self, node=None):
- self.extended_attributes = {}
- self.idl_type = None
- self.is_optional = False # syntax: (optional T)
- self.is_variadic = False # syntax: (T...)
- self.default_value = None
-
- if not node:
- return
-
- self.is_optional = node.GetProperty('OPTIONAL')
- self.name = node.GetName()
-
- children = node.GetChildren()
- for child in children:
- child_class = child.GetClass()
- if child_class == 'Type':
- self.idl_type = type_node_to_type(child)
- elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- elif child_class == 'Argument':
- child_name = child.GetName()
- if child_name != '...':
- raise ValueError(
- 'Unrecognized Argument node; expected "...", got "%s"'
- % child_name)
- self.is_variadic = bool(child.GetProperty('ELLIPSIS'))
- elif child_class == 'Default':
- self.default_value = default_node_to_idl_literal(child)
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- def accept(self, visitor):
- visitor.visit_argument(self)
-
-
-def arguments_node_to_arguments(node):
- # [Constructor] and [CustomConstructor] without arguments (the bare form)
- # have None instead of an arguments node, but have the same meaning as using
- # an empty argument list, [Constructor()], so special-case this.
- # http://www.w3.org/TR/WebIDL/#Constructor
- if node is None:
- return []
- return [IdlArgument(argument_node) for argument_node in node.GetChildren()]
-
-
-################################################################################
-# Stringifiers
-################################################################################
-
-
-class IdlStringifier(object):
- def __init__(self, node):
- self.attribute = None
- self.operation = None
- self.extended_attributes = {}
-
- for child in node.GetChildren():
- child_class = child.GetClass()
- if child_class == 'Attribute':
- self.attribute = IdlAttribute(child)
- elif child_class == 'Operation':
- operation = IdlOperation(child)
- if operation.name:
- self.operation = operation
- elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- # Copy the stringifier's extended attributes (such as [Unforgable]) onto
- # the underlying attribute or operation, if there is one.
- if self.attribute or self.operation:
- (self.attribute or self.operation).extended_attributes.update(
- self.extended_attributes)
-
-
-################################################################################
-# Iterable, Maplike, Setlike
-################################################################################
-
-
-class IdlIterableOrMaplikeOrSetlike(TypedObject):
- def __init__(self, node):
- self.extended_attributes = {}
- self.type_children = []
-
- for child in node.GetChildren():
- child_class = child.GetClass()
- if child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- elif child_class == 'Type':
- self.type_children.append(child)
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
-
-class IdlIterable(IdlIterableOrMaplikeOrSetlike):
- idl_type_attributes = ('key_type', 'value_type')
-
- def __init__(self, node):
- super(IdlIterable, self).__init__(node)
-
- if len(self.type_children) == 1:
- self.key_type = None
- self.value_type = type_node_to_type(self.type_children[0])
- elif len(self.type_children) == 2:
- self.key_type = type_node_to_type(self.type_children[0])
- self.value_type = type_node_to_type(self.type_children[1])
- else:
- raise ValueError('Unexpected number of type children: %d' % len(
- self.type_children))
- del self.type_children
-
- def accept(self, visitor):
- visitor.visit_iterable(self)
-
-
-class IdlMaplike(IdlIterableOrMaplikeOrSetlike):
- idl_type_attributes = ('key_type', 'value_type')
-
- def __init__(self, node):
- super(IdlMaplike, self).__init__(node)
-
- self.is_read_only = bool(node.GetProperty('READONLY'))
-
- if len(self.type_children) == 2:
- self.key_type = type_node_to_type(self.type_children[0])
- self.value_type = type_node_to_type(self.type_children[1])
- else:
- raise ValueError(
- 'Unexpected number of children: %d' % len(self.type_children))
- del self.type_children
-
- def accept(self, visitor):
- visitor.visit_maplike(self)
-
-
-class IdlSetlike(IdlIterableOrMaplikeOrSetlike):
- idl_type_attributes = ('value_type', )
-
- def __init__(self, node):
- super(IdlSetlike, self).__init__(node)
-
- self.is_read_only = bool(node.GetProperty('READONLY'))
-
- if len(self.type_children) == 1:
- self.value_type = type_node_to_type(self.type_children[0])
- else:
- raise ValueError(
- 'Unexpected number of children: %d' % len(self.type_children))
- del self.type_children
-
- def accept(self, visitor):
- visitor.visit_setlike(self)
-
-
-################################################################################
-# Includes statements
-################################################################################
-
-
-class IdlIncludes(object):
- def __init__(self, node):
- self.interface = node.GetName()
- self.mixin = node.GetProperty('REFERENCE')
-
- def accept(self, visitor):
- visitor.visit_include(self)
-
-
-################################################################################
-# Extended attributes
-################################################################################
-
-
-class Exposure(object):
- """An Exposure holds one Exposed or RuntimeEnabled condition.
- Each exposure has two properties: exposed and runtime_enabled.
- Exposure(e, r) corresponds to [Exposed(e r)]. Exposure(e) corresponds to
- [Exposed=e].
- """
-
- def __init__(self, exposed, runtime_enabled=None):
- self.exposed = exposed
- self.runtime_enabled = runtime_enabled
-
-
-def ext_attributes_node_to_extended_attributes(node):
- """
- Returns:
- Dictionary of {ExtAttributeName: ExtAttributeValue}.
- Value is usually a string, with these exceptions:
- Constructors: value is a list of Arguments nodes, corresponding to
- possible signatures of the constructor.
- CustomConstructors: value is a list of Arguments nodes, corresponding to
- possible signatures of the custom constructor.
- NamedConstructor: value is a Call node, corresponding to the single
- signature of the named constructor.
- """
- # Primarily just make a dictionary from the children.
- # The only complexity is handling various types of constructors:
- # Constructors and Custom Constructors can have duplicate entries due to
- # overloading, and thus are stored in temporary lists.
- # However, Named Constructors cannot be overloaded, and thus do not have
- # a list.
- # TODO(bashi): Remove |constructors| and |custom_constructors|.
- constructors = []
- custom_constructors = []
- extended_attributes = {}
-
- def child_node(extended_attribute_node):
- children = extended_attribute_node.GetChildren()
- if not children:
- return None
- if len(children) > 1:
- raise ValueError(
- 'ExtAttributes node with %s children, expected at most 1' %
- len(children))
- return children[0]
-
- extended_attribute_node_list = node.GetChildren()
- for extended_attribute_node in extended_attribute_node_list:
- name = extended_attribute_node.GetName()
- child = child_node(extended_attribute_node)
- child_class = child and child.GetClass()
- if name == 'Constructor':
- raise ValueError('[Constructor] is deprecated. Use constructor '
- 'operations')
- elif name == 'CustomConstructor':
- raise ValueError('[CustomConstructor] is deprecated. Use '
- 'constructor operations with [Custom]')
- elif name == 'NamedConstructor':
- if child_class and child_class != 'Call':
- raise ValueError(
- '[NamedConstructor] only supports Call as child, but has child of class: %s'
- % child_class)
- extended_attributes[name] = child
- elif name == 'Exposed':
- if child_class and child_class != 'Arguments':
- raise ValueError(
- '[Exposed] only supports Arguments as child, but has child of class: %s'
- % child_class)
- exposures = []
- if child_class == 'Arguments':
- exposures = [
- Exposure(
- exposed=str(arg.idl_type), runtime_enabled=arg.name)
- for arg in arguments_node_to_arguments(child)
- ]
- else:
- value = extended_attribute_node.GetProperty('VALUE')
- if type(value) is str:
- exposures = [Exposure(exposed=value)]
- else:
- exposures = [Exposure(exposed=v) for v in value]
- extended_attributes[name] = exposures
- elif child:
- raise ValueError(
- 'ExtAttributes node with unexpected children: %s' % name)
- else:
- value = extended_attribute_node.GetProperty('VALUE')
- extended_attributes[name] = value
-
- # Store constructors and custom constructors in special list attributes,
- # which are deleted later. Note plural in key.
- if constructors:
- extended_attributes['Constructors'] = constructors
- if custom_constructors:
- extended_attributes['CustomConstructors'] = custom_constructors
-
- return extended_attributes
-
-
-def extended_attributes_to_constructors(extended_attributes):
- """Returns constructors and custom_constructors (lists of IdlOperations).
-
- Auxiliary function for IdlInterface.__init__.
- """
-
- # TODO(bashi): Remove 'Constructors' and 'CustomConstructors'.
-
- constructor_list = extended_attributes.get('Constructors', [])
- constructors = [
- IdlOperation.constructor_from_arguments_node('Constructor',
- arguments_node)
- for arguments_node in constructor_list
- ]
-
- custom_constructor_list = extended_attributes.get('CustomConstructors', [])
- custom_constructors = [
- IdlOperation.constructor_from_arguments_node('CustomConstructor',
- arguments_node)
- for arguments_node in custom_constructor_list
- ]
-
- if 'NamedConstructor' in extended_attributes:
- # FIXME: support overloaded named constructors, and make homogeneous
- name = 'NamedConstructor'
- call_node = extended_attributes['NamedConstructor']
- extended_attributes['NamedConstructor'] = call_node.GetName()
- children = call_node.GetChildren()
- if len(children) != 1:
- raise ValueError('NamedConstructor node expects 1 child, got %s.' %
- len(children))
- arguments_node = children[0]
- named_constructor = IdlOperation.constructor_from_arguments_node(
- 'NamedConstructor', arguments_node)
- # FIXME: should return named_constructor separately; appended for Perl
- constructors.append(named_constructor)
-
- return constructors, custom_constructors
-
-
-class ConstructorOperation(object):
- """Represents a constructor operation. This is a tentative object used to
- create constructors in IdlInterface.
- """
-
- def __init__(self, constructor, extended_attributes, is_custom):
- self.constructor = constructor
- self.extended_attributes = extended_attributes
- self.is_custom = is_custom
-
-
-def constructor_operation_from_node(node):
- """Creates a ConstructorOperation from the given |node|.
- """
-
- arguments_node = None
- extended_attributes = {}
-
- for child in node.GetChildren():
- child_class = child.GetClass()
- if child_class == 'Arguments':
- arguments_node = child
- elif child_class == 'ExtAttributes':
- extended_attributes = ext_attributes_node_to_extended_attributes(
- child)
- else:
- raise ValueError('Unrecognized node class: %s' % child_class)
-
- if not arguments_node:
- raise ValueError('Expected Arguments node for constructor operation')
-
- if 'Custom' in extended_attributes:
- if extended_attributes['Custom']:
- raise ValueError('[Custom] should not have a value on constructor '
- 'operations')
- del extended_attributes['Custom']
- constructor = IdlOperation.constructor_from_arguments_node(
- 'CustomConstructor', arguments_node)
- return ConstructorOperation(
- constructor, extended_attributes, is_custom=True)
- else:
- constructor = IdlOperation.constructor_from_arguments_node(
- 'Constructor', arguments_node)
- return ConstructorOperation(
- constructor, extended_attributes, is_custom=False)
-
-
-def check_constructor_operations_extended_attributes(current_attrs, new_attrs):
- """Raises a ValueError if two extended attribute lists have different values
- of constructor related attributes.
- """
-
- attrs_to_check = ['CallWith', 'RaisesException']
- for attr in attrs_to_check:
- if current_attrs.get(attr) != new_attrs.get(attr):
- raise ValueError('[{}] should have the same value on all '
- 'constructor operations'.format(attr))
-
-
-def convert_constructor_operations_extended_attributes(extended_attributes):
- """Converts extended attributes specified on constructor operations to
- extended attributes for an interface definition (e.g. [ConstructorCallWith])
- """
-
- converted = {}
- for name, value in extended_attributes.items():
- if name == "CallWith":
- converted["ConstructorCallWith"] = value
- elif name == "RaisesException":
- if value:
- raise ValueError(
- '[RaisesException] should not have a value on '
- 'constructor operations')
- converted["RaisesException"] = 'Constructor'
- elif name == "MeasureAs":
- converted["MeasureAs"] = value
- elif name == "Measure":
- converted["Measure"] = None
- else:
- raise ValueError(
- '[{}] is not supported on constructor operations'.format(name))
-
- return converted
-
-
-def clear_constructor_attributes(extended_attributes):
- # Deletes Constructor*s* (plural), sets Constructor (singular)
- if 'Constructors' in extended_attributes:
- del extended_attributes['Constructors']
- extended_attributes['Constructor'] = None
- if 'CustomConstructors' in extended_attributes:
- del extended_attributes['CustomConstructors']
- extended_attributes['CustomConstructor'] = None
-
-
-################################################################################
-# Types
-################################################################################
-
-
-def type_node_to_type(node):
- children = node.GetChildren()
- if len(children) != 1 and len(children) != 2:
- raise ValueError(
- 'Type node expects 1 or 2 child(ren), got %d.' % len(children))
-
- base_type = type_node_inner_to_type(children[0])
- if len(children) == 2:
- extended_attributes = ext_attributes_node_to_extended_attributes(
- children[1])
- base_type = IdlAnnotatedType(base_type, extended_attributes)
-
- if node.GetProperty('NULLABLE'):
- base_type = IdlNullableType(base_type)
-
- return base_type
-
-
-def type_node_inner_to_type(node):
- node_class = node.GetClass()
- # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
- # either a typedef shorthand (but not a Typedef declaration itself) or an
- # interface type. We do not distinguish these, and just use the type name.
- if node_class in ['PrimitiveType', 'StringType', 'Typeref']:
- # unrestricted syntax: unrestricted double | unrestricted float
- is_unrestricted = bool(node.GetProperty('UNRESTRICTED'))
- return IdlType(node.GetName(), is_unrestricted=is_unrestricted)
- elif node_class == 'Any':
- return IdlType('any')
- elif node_class in ['Sequence', 'FrozenArray']:
- return sequence_node_to_type(node)
- elif node_class == 'UnionType':
- return union_type_node_to_idl_union_type(node)
- elif node_class == 'Promise':
- return IdlType('Promise')
- elif node_class == 'Record':
- return record_node_to_type(node)
- raise ValueError('Unrecognized node class: %s' % node_class)
-
-
-def record_node_to_type(node):
- children = node.GetChildren()
- if len(children) != 2:
- raise ValueError('record<K,V> node expects exactly 2 children, got %d'
- % (len(children)))
- key_child = children[0]
- value_child = children[1]
- if key_child.GetClass() != 'StringType':
- raise ValueError('Keys in record<K,V> nodes must be string types.')
- if value_child.GetClass() != 'Type':
- raise ValueError('Unrecognized node class for record<K,V> value: %s' %
- value_child.GetClass())
- return IdlRecordType(
- IdlType(key_child.GetName()), type_node_to_type(value_child))
-
-
-def sequence_node_to_type(node):
- children = node.GetChildren()
- class_name = node.GetClass()
- if len(children) != 1:
- raise ValueError('%s node expects exactly 1 child, got %s' %
- (class_name, len(children)))
- sequence_child = children[0]
- sequence_child_class = sequence_child.GetClass()
- if sequence_child_class != 'Type':
- raise ValueError('Unrecognized node class: %s' % sequence_child_class)
- element_type = type_node_to_type(sequence_child)
- if class_name == 'Sequence':
- sequence_type = IdlSequenceType(element_type)
- elif class_name == 'FrozenArray':
- sequence_type = IdlFrozenArrayType(element_type)
- else:
- raise ValueError('Unexpected node: %s' % class_name)
- if node.GetProperty('NULLABLE'):
- return IdlNullableType(sequence_type)
- return sequence_type
-
-
-def typedef_node_to_type(node):
- children = node.GetChildren()
- if len(children) != 1:
- raise ValueError(
- 'Typedef node with %s children, expected 1' % len(children))
- child = children[0]
- child_class = child.GetClass()
- if child_class != 'Type':
- raise ValueError('Unrecognized node class: %s' % child_class)
- return type_node_to_type(child)
-
-
-def union_type_node_to_idl_union_type(node):
- member_types = [
- type_node_to_type(member_type_node)
- for member_type_node in node.GetChildren()
- ]
- return IdlUnionType(member_types)
-
-
-################################################################################
-# Visitor
-################################################################################
-
-
-class Visitor(object):
- """Abstract visitor class for IDL definitions traverse."""
-
- def visit_definitions(self, definitions):
- pass
-
- def visit_typed_object(self, typed_object):
- pass
-
- def visit_callback_function(self, callback_function):
- self.visit_typed_object(callback_function)
-
- def visit_dictionary(self, dictionary):
- pass
-
- def visit_dictionary_member(self, member):
- self.visit_typed_object(member)
-
- def visit_enumeration(self, enumeration):
- pass
-
- def visit_include(self, include):
- pass
-
- def visit_interface(self, interface):
- pass
-
- def visit_typedef(self, typedef):
- self.visit_typed_object(typedef)
-
- def visit_attribute(self, attribute):
- self.visit_typed_object(attribute)
-
- def visit_constant(self, constant):
- self.visit_typed_object(constant)
-
- def visit_operation(self, operation):
- self.visit_typed_object(operation)
-
- def visit_argument(self, argument):
- self.visit_typed_object(argument)
-
- def visit_iterable(self, iterable):
- self.visit_typed_object(iterable)
-
- def visit_maplike(self, maplike):
- self.visit_typed_object(maplike)
-
- def visit_setlike(self, setlike):
- self.visit_typed_object(setlike)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py
deleted file mode 100644
index e2a91843a9a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py
+++ /dev/null
@@ -1,19 +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.
-
-# pylint: disable=import-error,print-statement,relative-import
-"""Unit tests for idl_definitions.py."""
-
-import unittest
-
-from idl_definitions import IdlAttribute
-
-
-class IdlAttributeTest(unittest.TestCase):
- def test_no_params(self):
- try:
- IdlAttribute()
- except Exception as exception: # pylint: disable=broad-except
- self.fail('Creating an IdlAttribute with no parameters raised'
- 'an exception: {}.'.format(exception))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py
deleted file mode 100644
index b80eebdcd61..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py
+++ /dev/null
@@ -1,144 +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.
-"""Read an IDL file or complete IDL interface, producing an IdlDefinitions object.
-
-Design doc:
-http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end
-"""
-
-import os
-
-import blink_idl_parser
-from blink_idl_parser import BlinkIDLParser
-from idl_definitions import IdlDefinitions
-from idl_validator import EXTENDED_ATTRIBUTES_RELATIVE_PATH, IDLInvalidExtendedAttributeError, IDLExtendedAttributeValidator
-from interface_dependency_resolver import InterfaceDependencyResolver
-from utilities import idl_filename_to_component
-from utilities import to_snake_case
-
-
-def validate_blink_idl_definitions(idl_filename, idl_file_basename,
- definitions):
- """Validate file contents with filename convention.
-
- The Blink IDL conventions are:
- - If an IDL file defines an interface or a dictionary,
- the IDL file must contain exactly one definition. The definition
- name must agree with the file's basename, unless it is a partial
- definition. (e.g., 'partial interface Foo' can be in FooBar.idl).
- - An IDL file can contain typedefs and enums without having other
- definitions. There is no filename convention in this case.
- - Otherwise, an IDL file is invalid.
- """
- targets = (list(definitions.interfaces.values()) +
- list(definitions.dictionaries.values()))
- number_of_targets = len(targets)
- if number_of_targets > 1:
- raise Exception(
- 'Expected exactly 1 definition in file {0}, but found {1}'.format(
- idl_filename, number_of_targets))
- if number_of_targets == 0:
- number_of_definitions = (len(definitions.enumerations) + len(
- definitions.typedefs) + len(definitions.callback_functions))
- if number_of_definitions == 0:
- raise Exception('No definition found in %s. (Missing semicolon?)' %
- idl_filename)
- return
- target = targets[0]
- if target.is_partial:
- return
- if (target.name != idl_file_basename
- and to_snake_case(target.name) != idl_file_basename):
- raise Exception(
- 'Definition name "{0}" disagrees with IDL file basename "{1}".'.
- format(target.name, idl_file_basename))
-
-
-class IdlReader(object):
- def __init__(self, interfaces_info=None, outputdir=''):
- self.extended_attribute_validator = IDLExtendedAttributeValidator()
- self.interfaces_info = interfaces_info
-
- if interfaces_info:
- self.interface_dependency_resolver = InterfaceDependencyResolver(
- interfaces_info, self)
- else:
- self.interface_dependency_resolver = None
-
- self.parser = BlinkIDLParser(outputdir=outputdir)
-
- def read_idl_definitions(self, idl_filename):
- """Returns a dictionary whose key is component and value is an IdlDefinitions object for an IDL file, including all dependencies."""
- definitions = self.read_idl_file(idl_filename)
- component = idl_filename_to_component(idl_filename)
-
- if not self.interface_dependency_resolver:
- return {component: definitions}
-
- # This definitions should have a dictionary. No need to resolve any
- # dependencies.
- if not definitions.interfaces:
- return {component: definitions}
-
- return self.interface_dependency_resolver.resolve_dependencies(
- definitions, component)
-
- def read_idl_file(self, idl_filename):
- """Returns an IdlDefinitions object for an IDL file, without any dependencies.
-
- The IdlDefinitions object is guaranteed to contain a single
- IdlInterface; it may also contain other definitions, such as
- callback functions and enumerations."""
- ast = blink_idl_parser.parse_file(self.parser, idl_filename)
- if not ast:
- raise Exception('Failed to parse %s' % idl_filename)
- idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
- definitions = IdlDefinitions(ast)
-
- validate_blink_idl_definitions(idl_filename, idl_file_basename,
- definitions)
-
- # Validate extended attributes
- if not self.extended_attribute_validator:
- return definitions
-
- try:
- self.extended_attribute_validator.validate_extended_attributes(
- definitions)
- except IDLInvalidExtendedAttributeError as error:
- raise IDLInvalidExtendedAttributeError("""
-IDL ATTRIBUTE ERROR in file:
-%s:
- %s
-If you want to add a new IDL extended attribute, please add it to:
- %s
-and add an explanation to the Blink IDL documentation at:
- http://www.chromium.org/blink/webidl/blink-idl-extended-attributes
- """ % (idl_filename, str(error), EXTENDED_ATTRIBUTES_RELATIVE_PATH))
-
- return definitions
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
deleted file mode 100644
index ab95e9c0b08..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
+++ /dev/null
@@ -1,682 +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.
-"""IDL type handling.
-
-Classes:
-IdlTypeBase
- IdlType
- IdlUnionType
- IdlArrayOrSequenceType
- IdlSequenceType
- IdlFrozenArrayType
- IdlNullableType
- IdlAnnotatedType
-
-IdlTypes are picklable because we store them in interfaces_info.
-"""
-
-from collections import defaultdict
-
-################################################################################
-# IDL types
-################################################################################
-
-INTEGER_TYPES = frozenset([
- # http://www.w3.org/TR/WebIDL/#dfn-integer-type
- 'byte',
- 'octet',
- 'short',
- 'unsigned short',
- # int and unsigned are not IDL types
- 'long',
- 'unsigned long',
- 'long long',
- 'unsigned long long',
-])
-NUMERIC_TYPES = (
- INTEGER_TYPES | frozenset([
- # http://www.w3.org/TR/WebIDL/#dfn-numeric-type
- 'float',
- 'unrestricted float',
- 'double',
- 'unrestricted double',
- ]))
-# http://www.w3.org/TR/WebIDL/#dfn-primitive-type
-PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES)
-BASIC_TYPES = (
- PRIMITIVE_TYPES | frozenset([
- # Built-in, non-composite, non-object data types
- # http://heycam.github.io/webidl/#idl-types
- 'DOMString',
- 'ByteString',
- 'USVString',
- # http://heycam.github.io/webidl/#idl-types
- 'void',
- ]))
-TYPE_NAMES = {
- # http://heycam.github.io/webidl/#dfn-type-name
- 'any': 'Any',
- 'boolean': 'Boolean',
- 'byte': 'Byte',
- 'octet': 'Octet',
- 'short': 'Short',
- 'unsigned short': 'UnsignedShort',
- 'long': 'Long',
- 'unsigned long': 'UnsignedLong',
- 'long long': 'LongLong',
- 'unsigned long long': 'UnsignedLongLong',
- 'float': 'Float',
- 'unrestricted float': 'UnrestrictedFloat',
- 'double': 'Double',
- 'unrestricted double': 'UnrestrictedDouble',
- 'DOMString': 'String',
- 'ByteString': 'ByteString',
- 'USVString': 'USVString',
- 'object': 'Object',
-}
-
-STRING_TYPES = frozenset([
- # http://heycam.github.io/webidl/#es-interface-call (step 10.11)
- # (Interface object [[Call]] method's string types.)
- 'String',
- 'ByteString',
- 'USVString',
-])
-
-EXTENDED_ATTRIBUTES_APPLICABLE_TO_TYPES = frozenset([
- 'AllowShared',
- 'Clamp',
- 'EnforceRange',
- 'StringContext',
- 'TreatNullAs',
-])
-
-################################################################################
-# Inheritance
-################################################################################
-
-ancestors = defaultdict(list) # interface_name -> ancestors
-
-
-def inherits_interface(interface_name, ancestor_name):
- return (interface_name == ancestor_name
- or ancestor_name in ancestors[interface_name])
-
-
-def set_ancestors(new_ancestors):
- ancestors.update(new_ancestors)
-
-
-class IdlTypeBase(object):
- """Base class for IdlType, IdlUnionType, IdlArrayOrSequenceType
- and IdlNullableType.
- """
-
- def __str__(self):
- raise NotImplementedError('__str__() should be defined in subclasses')
-
- def __getattr__(self, name):
- # Default undefined attributes to None (analogous to Jinja variables).
- # This allows us to not define default properties in the base class, and
- # allows us to relay __getattr__ in IdlNullableType to the inner type.
- return None
-
- def resolve_typedefs(self, typedefs):
- raise NotImplementedError(
- 'resolve_typedefs should be defined in subclasses')
-
- def idl_types(self):
- """A generator which yields IdlTypes which are referenced from |self|,
- including itself."""
- yield self
-
-
-################################################################################
-# IdlType
-################################################################################
-
-
-class IdlType(IdlTypeBase):
- # FIXME: incorporate Nullable, etc.
- # to support types like short?[] vs. short[]?, instead of treating these
- # as orthogonal properties (via flags).
- callback_functions = {}
- callback_interfaces = set()
- dictionaries = set()
- enums = {} # name -> values
-
- def __init__(self, base_type, is_unrestricted=False):
- super(IdlType, self).__init__()
- if is_unrestricted:
- self.base_type = 'unrestricted %s' % base_type
- else:
- self.base_type = base_type
-
- def __str__(self):
- return self.base_type
-
- def __getstate__(self):
- return {
- 'base_type': self.base_type,
- }
-
- def __setstate__(self, state):
- self.base_type = state['base_type']
-
- @property
- def is_basic_type(self):
- return self.base_type in BASIC_TYPES
-
- @property
- def is_callback_function(self): # pylint: disable=C0103
- return self.base_type in IdlType.callback_functions
-
- @property
- def is_custom_callback_function(self):
- entry = IdlType.callback_functions.get(self.base_type)
- callback_function = entry.get('callback_function')
- if not callback_function:
- return False
- return 'Custom' in callback_function.extended_attributes
-
- @property
- def is_callback_interface(self):
- return self.base_type in IdlType.callback_interfaces
-
- @property
- def is_dictionary(self):
- return self.base_type in IdlType.dictionaries
-
- @property
- def is_enum(self):
- # FIXME: add an IdlEnumType class and a resolve_enums step
- # at end of IdlDefinitions constructor
- return self.name in IdlType.enums
-
- @property
- def enum_values(self):
- return IdlType.enums.get(self.name)
-
- @property
- def enum_type(self):
- return self.name if self.is_enum else None
-
- @property
- def is_integer_type(self):
- return self.base_type in INTEGER_TYPES
-
- @property
- def is_void(self):
- return self.base_type == 'void'
-
- @property
- def is_numeric_type(self):
- return self.base_type in NUMERIC_TYPES
-
- @property
- def is_primitive_type(self):
- return self.base_type in PRIMITIVE_TYPES
-
- @property
- def is_interface_type(self):
- # Anything that is not another type is an interface type.
- # http://www.w3.org/TR/WebIDL/#idl-types
- # http://www.w3.org/TR/WebIDL/#idl-interface
- # In C++ these are RefPtr types.
- return not (self.is_basic_type or self.is_callback_function
- or self.is_dictionary or self.is_enum or self.name == 'Any'
- or self.name == 'Object' or self.name == 'Promise'
- ) # Promise will be basic in future
-
- @property
- def is_string_type(self):
- return self.name in STRING_TYPES
-
- @property
- def name(self):
- """Return type name
-
- http://heycam.github.io/webidl/#dfn-type-name
- """
- base_type = self.base_type
- return TYPE_NAMES.get(base_type, base_type)
-
- @classmethod
- def set_callback_functions(cls, new_callback_functions):
- cls.callback_functions.update(new_callback_functions)
-
- @classmethod
- def set_callback_interfaces(cls, new_callback_interfaces):
- cls.callback_interfaces.update(new_callback_interfaces)
-
- @classmethod
- def set_dictionaries(cls, new_dictionaries):
- cls.dictionaries.update(new_dictionaries)
-
- @classmethod
- def set_enums(cls, new_enums):
- cls.enums.update(new_enums)
-
- def resolve_typedefs(self, typedefs):
- base_type = self.base_type
- if base_type in typedefs:
- resolved_type = typedefs[base_type]
- if resolved_type.base_type in typedefs:
- raise ValueError("We can't typedef a typedef'ed type.")
- # For the case that the resolved type contains other typedef'ed
- # type(s).
- return resolved_type.resolve_typedefs(typedefs)
- return self
-
-
-################################################################################
-# IdlUnionType
-################################################################################
-
-
-class IdlUnionType(IdlTypeBase):
- # http://heycam.github.io/webidl/#idl-union
- # IdlUnionType has __hash__() and __eq__() methods because they are stored
- # in sets.
- def __init__(self, member_types):
- super(IdlUnionType, self).__init__()
- self.member_types = member_types
-
- def __str__(self):
- return '(' + ' or '.join(
- str(member_type) for member_type in self.member_types) + ')'
-
- def __hash__(self):
- return hash(self.name)
-
- def __eq__(self, rhs):
- return self.name == rhs.name
-
- def __getstate__(self):
- return {
- 'member_types': self.member_types,
- }
-
- def __setstate__(self, state):
- self.member_types = state['member_types']
-
- @property
- def flattened_member_types(self):
- """Returns the set of the union's flattened member types.
-
- https://heycam.github.io/webidl/#dfn-flattened-union-member-types
- """
- # We cannot use a set directly because each member is an
- # IdlTypeBase-derived class, and comparing two objects of the
- # same type is not the same as comparing their names.
- # In other words:
- # x = IdlType('ByteString')
- # y = IdlType('ByteString')
- # x == y # False
- # x.name == y.name # True
- # |flattened_members|'s keys are type names, the values are type
- # |objects|.
- # We assume we can use two IDL objects of the same type interchangeably.
- flattened_members = {}
- for member in self.member_types:
- if member.is_nullable:
- member = member.inner_type
- if member.is_union_type:
- for inner_member in member.flattened_member_types:
- flattened_members[inner_member.name] = inner_member
- else:
- flattened_members[member.name] = member
- return set(flattened_members.values())
-
- @property
- def number_of_nullable_member_types(self):
- """Returns the union's number of nullable types.
-
- http://heycam.github.io/webidl/#dfn-number-of-nullable-member-types
- """
- count = 0
- for member in self.member_types:
- if member.is_nullable:
- count += 1
- member = member.inner_type
- if member.is_union_type:
- count += member.number_of_nullable_member_types
- return count
-
- @property
- def is_union_type(self):
- return True
-
- def single_matching_member_type(self, predicate):
- matching_types = list(filter(predicate, self.flattened_member_types))
- if len(matching_types) > 1:
- raise ValueError('%s is ambiguous.' % self.name)
- return matching_types[0] if matching_types else None
-
- @property
- def string_member_type(self):
- return self.single_matching_member_type(
- lambda member_type: (member_type.is_string_type or member_type.is_enum)
- )
-
- @property
- def numeric_member_type(self):
- return self.single_matching_member_type(
- lambda member_type: member_type.is_numeric_type)
-
- @property
- def boolean_member_type(self):
- return self.single_matching_member_type(
- lambda member_type: member_type.base_type == 'boolean')
-
- @property
- def sequence_member_type(self):
- return self.single_matching_member_type(
- lambda member_type: member_type.is_sequence_type)
-
- @property
- def dictionary_member_type(self):
- return self.single_matching_member_type(
- lambda member_type: member_type.is_dictionary)
-
- @property
- def as_union_type(self):
- # Note: Use this to "look through" a possible IdlNullableType wrapper.
- return self
-
- @property
- def name(self):
- """Return type name (or inner type name if nullable)
-
- http://heycam.github.io/webidl/#dfn-type-name
- """
- return 'Or'.join(member_type.name for member_type in self.member_types)
-
- def resolve_typedefs(self, typedefs):
- self.member_types = [
- member_type.resolve_typedefs(typedefs)
- for member_type in self.member_types
- ]
- return self
-
- def idl_types(self):
- yield self
- for member_type in self.member_types:
- for idl_type in member_type.idl_types():
- yield idl_type
-
-
-################################################################################
-# IdlArrayOrSequenceType, IdlSequenceType, IdlFrozenArrayType
-################################################################################
-
-
-# TODO(bashi): Rename this like "IdlArrayTypeBase" or something.
-class IdlArrayOrSequenceType(IdlTypeBase):
- """Base class for array-like types."""
-
- def __init__(self, element_type):
- super(IdlArrayOrSequenceType, self).__init__()
- self.element_type = element_type
-
- def __getstate__(self):
- return {
- 'element_type': self.element_type,
- }
-
- def __setstate__(self, state):
- self.element_type = state['element_type']
-
- def resolve_typedefs(self, typedefs):
- self.element_type = self.element_type.resolve_typedefs(typedefs)
- return self
-
- @property
- def is_array_or_sequence_type(self):
- return True
-
- @property
- def is_sequence_type(self):
- return False
-
- @property
- def is_frozen_array(self):
- return False
-
- @property
- def enum_values(self):
- return self.element_type.enum_values
-
- @property
- def enum_type(self):
- return self.element_type.enum_type
-
- def idl_types(self):
- yield self
- for idl_type in self.element_type.idl_types():
- yield idl_type
-
-
-class IdlSequenceType(IdlArrayOrSequenceType):
- def __init__(self, element_type):
- super(IdlSequenceType, self).__init__(element_type)
-
- def __str__(self):
- return 'sequence<%s>' % self.element_type
-
- @property
- def name(self):
- return self.element_type.name + 'Sequence'
-
- @property
- def is_sequence_type(self):
- return True
-
-
-class IdlFrozenArrayType(IdlArrayOrSequenceType):
- def __init__(self, element_type):
- super(IdlFrozenArrayType, self).__init__(element_type)
-
- def __str__(self):
- return 'FrozenArray<%s>' % self.element_type
-
- @property
- def name(self):
- return self.element_type.name + 'Array'
-
- @property
- def is_frozen_array(self):
- return True
-
-
-################################################################################
-# IdlRecordType
-################################################################################
-
-
-class IdlRecordType(IdlTypeBase):
- def __init__(self, key_type, value_type):
- super(IdlRecordType, self).__init__()
- self.key_type = key_type
- self.value_type = value_type
-
- def __str__(self):
- return 'record<%s, %s>' % (self.key_type, self.value_type)
-
- def __getstate__(self):
- return {
- 'key_type': self.key_type,
- 'value_type': self.value_type,
- }
-
- def __setstate__(self, state):
- self.key_type = state['key_type']
- self.value_type = state['value_type']
-
- def idl_types(self):
- yield self
- for idl_type in self.key_type.idl_types():
- yield idl_type
- for idl_type in self.value_type.idl_types():
- yield idl_type
-
- def resolve_typedefs(self, typedefs):
- self.key_type = self.key_type.resolve_typedefs(typedefs)
- self.value_type = self.value_type.resolve_typedefs(typedefs)
- return self
-
- @property
- def is_record_type(self):
- return True
-
- @property
- def name(self):
- return self.key_type.name + self.value_type.name + 'Record'
-
-
-################################################################################
-# IdlNullableType
-################################################################################
-
-
-# https://heycam.github.io/webidl/#idl-nullable-type
-class IdlNullableType(IdlTypeBase):
- def __init__(self, inner_type):
- super(IdlNullableType, self).__init__()
- if inner_type.name == 'Any':
- raise ValueError('Inner type of nullable type must not be any.')
- if inner_type.name == 'Promise':
- raise ValueError(
- 'Inner type of nullable type must not be a promise.')
- if inner_type.is_nullable:
- raise ValueError(
- 'Inner type of nullable type must not be a nullable type.')
- if inner_type.is_union_type:
- if inner_type.number_of_nullable_member_types > 0:
- raise ValueError(
- 'Inner type of nullable type must not be a union type that '
- 'itself includes a nullable type.')
- if any(member.is_dictionary
- for member in inner_type.flattened_member_types):
- raise ValueError(
- 'Inner type of nullable type must not be a union type that '
- 'has a dictionary type as its members.')
-
- self.inner_type = inner_type
-
- def __str__(self):
- # FIXME: Dictionary::ConversionContext::setConversionType can't
- # handle the '?' in nullable types (passes nullability separately).
- # Update that function to handle nullability from the type name,
- # simplifying its signature.
- # return str(self.inner_type) + '?'
- return str(self.inner_type)
-
- def __getattr__(self, name):
- return getattr(self.inner_type, name)
-
- def __getstate__(self):
- return {
- 'inner_type': self.inner_type,
- }
-
- def __setstate__(self, state):
- self.inner_type = state['inner_type']
-
- @property
- def is_nullable(self):
- return True
-
- @property
- def name(self):
- return self.inner_type.name + 'OrNull'
-
- @property
- def enum_values(self):
- # Nullable enums are handled by preprending a None value to the list of
- # enum values. This None value is converted to nullptr on the C++ side,
- # which matches the JavaScript 'null' in the enum parsing code.
- inner_values = self.inner_type.enum_values
- if inner_values:
- return [None] + inner_values
- return None
-
- def resolve_typedefs(self, typedefs):
- self.inner_type = self.inner_type.resolve_typedefs(typedefs)
- return self
-
- def idl_types(self):
- yield self
- for idl_type in self.inner_type.idl_types():
- yield idl_type
-
-
-################################################################################
-# IdlAnnotatedType
-################################################################################
-
-
-class IdlAnnotatedType(IdlTypeBase):
- """IdlAnnoatedType represents an IDL type with extended attributes.
- [Clamp], [EnforceRange], [StringContext], and [TreatNullAs] are applicable
- to types.
- https://heycam.github.io/webidl/#idl-annotated-types
- """
-
- def __init__(self, inner_type, extended_attributes):
- super(IdlAnnotatedType, self).__init__()
- self.inner_type = inner_type
- self.extended_attributes = extended_attributes
-
- if any(key not in EXTENDED_ATTRIBUTES_APPLICABLE_TO_TYPES
- for key in extended_attributes):
- raise ValueError(
- 'Extended attributes not applicable to types: %s' % self)
-
- if ('StringContext' in extended_attributes
- and inner_type.base_type not in ['DOMString', 'USVString']):
- raise ValueError(
- 'StringContext is only applicable to string types.')
-
- def __str__(self):
- annotation = ', '.join(
- (key + ('' if val is None else '=' + val))
- for key, val in self.extended_attributes.items())
- return '[%s] %s' % (annotation, str(self.inner_type))
-
- def __getattr__(self, name):
- return getattr(self.inner_type, name)
-
- def __getstate__(self):
- return {
- 'inner_type': self.inner_type,
- 'extended_attributes': self.extended_attributes,
- }
-
- def __setstate__(self, state):
- self.inner_type = state['inner_type']
- self.extended_attributes = state['extended_attributes']
-
- @property
- def is_annotated_type(self):
- return True
-
- @property
- def has_string_context(self):
- return 'StringContext' in self.extended_attributes
-
- @property
- def name(self):
- annotation = ''.join(
- (key + ('' if val is None else val))
- for key, val in sorted(self.extended_attributes.items()))
- return self.inner_type.name + annotation
-
- def resolve_typedefs(self, typedefs):
- self.inner_type = self.inner_type.resolve_typedefs(typedefs)
- return self
-
- def idl_types(self):
- yield self
- yield self.inner_type
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py
deleted file mode 100644
index 519fbcf84e8..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py
+++ /dev/null
@@ -1,276 +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.
-
-# pylint: disable=import-error,print-statement,relative-import
-"""Unit tests for idl_types.py."""
-
-import unittest
-
-from idl_types import IdlNullableType
-from idl_types import IdlRecordType
-from idl_types import IdlSequenceType
-from idl_types import IdlType
-from idl_types import IdlUnionType
-
-
-class IdlTypeTest(unittest.TestCase):
- def test_is_void(self):
- idl_type = IdlType('void')
- self.assertTrue(idl_type.is_void)
- idl_type = IdlType('somethingElse')
- self.assertFalse(idl_type.is_void)
-
-
-class IdlRecordTypeTest(unittest.TestCase):
- def test_idl_types(self):
- idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
- idl_types = list(idl_type.idl_types())
- self.assertEqual(len(idl_types), 3)
- self.assertIs(idl_types[0], idl_type)
- self.assertEqual(idl_types[1].name, 'USVString')
- self.assertEqual(idl_types[2].name, 'Long')
- self.assertListEqual(
- list(idl_type.idl_types()),
- [idl_type, idl_type.key_type, idl_type.value_type])
-
- idl_type = IdlRecordType(
- IdlType('DOMString'), IdlSequenceType(
- IdlType('unrestricted float')))
- idl_types = list(idl_type.idl_types())
- self.assertEqual(len(idl_types), 4)
- self.assertIs(idl_types[0], idl_type)
- self.assertEqual(idl_types[1].name, 'String')
- self.assertEqual(idl_types[2].name, 'UnrestrictedFloatSequence')
- self.assertEqual(idl_types[3].name, 'UnrestrictedFloat')
- self.assertListEqual(
- list(idl_type.idl_types()), [
- idl_type, idl_type.key_type, idl_type.value_type,
- idl_type.value_type.element_type
- ])
-
- idl_type = IdlRecordType(
- IdlType('ByteString'),
- IdlRecordType(IdlType('DOMString'), IdlType('octet')))
- idl_types = list(idl_type.idl_types())
- self.assertEqual(len(idl_types), 5)
- self.assertIs(idl_types[0], idl_type)
- self.assertEqual(idl_types[1].name, 'ByteString')
- self.assertEqual(idl_types[2].name, 'StringOctetRecord')
- self.assertEqual(idl_types[3].name, 'String')
- self.assertEqual(idl_types[4].name, 'Octet')
- self.assertListEqual(
- list(idl_type.idl_types()), [
- idl_type, idl_type.key_type, idl_type.value_type,
- idl_type.value_type.key_type, idl_type.value_type.value_type
- ])
-
- def test_is_record(self):
- idl_type = IdlType('USVString')
- self.assertFalse(idl_type.is_record_type)
- idl_type = IdlSequenceType(
- IdlRecordType(IdlType('DOMString'), IdlType('byte')))
- self.assertFalse(idl_type.is_record_type)
- idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
- self.assertTrue(idl_type.is_record_type)
- idl_type = IdlRecordType(
- IdlType('USVString'), IdlSequenceType(IdlType('boolean')))
- self.assertTrue(idl_type.is_record_type)
-
- def test_name(self):
- idl_type = IdlRecordType(IdlType('ByteString'), IdlType('octet'))
- self.assertEqual(idl_type.name, 'ByteStringOctetRecord')
- idl_type = IdlRecordType(
- IdlType('USVString'), IdlSequenceType(IdlType('double')))
- self.assertEqual(idl_type.name, 'USVStringDoubleSequenceRecord')
- idl_type = IdlRecordType(
- IdlType('DOMString'),
- IdlRecordType(
- IdlType('ByteString'),
- IdlSequenceType(IdlType('unsigned short'))))
- self.assertEqual(idl_type.name,
- 'StringByteStringUnsignedShortSequenceRecordRecord')
-
-
-class IdlUnionTypeTest(unittest.TestCase):
- def test_flattened_member_types(self):
- # We are only testing the algorithm here, so we do create some
- # ambiguous union types.
-
- def compare_flattened_members(actual, expected):
- """Compare a set of IDL types by name, as the objects
- are different
- """
- actual_names = set([member.name for member in actual])
- expected_names = set([member.name for member in expected])
- self.assertEqual(actual_names, expected_names)
-
- idl_type = IdlUnionType([IdlType('long'), IdlType('SomeInterface')])
- compare_flattened_members(
- idl_type.flattened_member_types,
- set([IdlType('long'), IdlType('SomeInterface')]))
-
- idl_type = IdlUnionType([
- IdlUnionType([IdlType('ByteString'),
- IdlType('float')]),
- IdlType('boolean')
- ])
- compare_flattened_members(
- idl_type.flattened_member_types,
- set([IdlType('float'),
- IdlType('boolean'),
- IdlType('ByteString')]))
-
- idl_type = IdlUnionType([
- IdlUnionType([IdlType('ByteString'),
- IdlType('DOMString')]),
- IdlType('DOMString')
- ])
- compare_flattened_members(
- idl_type.flattened_member_types,
- set([IdlType('DOMString'),
- IdlType('ByteString')]))
-
- idl_type = IdlUnionType(
- [IdlNullableType(IdlType('ByteString')),
- IdlType('byte')])
- compare_flattened_members(
- idl_type.flattened_member_types,
- set([IdlType('ByteString'), IdlType('byte')]))
-
- idl_type = IdlUnionType([
- IdlNullableType(IdlType('ByteString')),
- IdlType('byte'),
- IdlUnionType([IdlType('ByteString'),
- IdlType('float')])
- ])
- self.assertEqual(len(idl_type.flattened_member_types), 3)
- compare_flattened_members(
- idl_type.flattened_member_types,
- set([IdlType('ByteString'),
- IdlType('byte'),
- IdlType('float')]))
-
- # From the example in the spec: "the flattened member types of the
- # union type (Node or (sequence<long> or Event) or
- # (XMLHttpRequest or DOMString)? or
- # sequence<(sequence<double> or NodeList)>) are the six types Node,
- # sequence<long>, Event, XMLHttpRequest, DOMString and
- # sequence<(sequence<double> or NodeList)>"
- idl_type = IdlUnionType([
- IdlType('Node'),
- IdlUnionType([IdlSequenceType(IdlType('long')),
- IdlType('Event')]),
- IdlNullableType(
- IdlUnionType([IdlType('XMLHttpRequest'),
- IdlType('DOMString')])),
- IdlSequenceType(
- IdlUnionType(
- [IdlSequenceType(IdlType('double')),
- IdlType('NodeList')]))
- ])
- self.assertEqual(len(idl_type.flattened_member_types), 6)
- compare_flattened_members(
- idl_type.flattened_member_types,
- set([
- IdlType('Node'),
- IdlSequenceType(IdlType('long')),
- IdlType('Event'),
- IdlType('XMLHttpRequest'),
- IdlType('DOMString'),
- IdlSequenceType(
- IdlUnionType([
- IdlSequenceType(IdlType('double')),
- IdlType('NodeList')
- ]))
- ]))
-
- def test_resolve_typedefs(self):
- # This is a simplification of the typedef mechanism to avoid having to
- # use idl_definitions and use actual nodes from //tools/idl_parser.
- typedefs = {
- 'Foo': IdlType('unsigned short'),
- 'MyBooleanType': IdlType('boolean'),
- 'SomeInterfaceT': IdlType('MyInterface'),
- }
-
- # (long long or MyBooleanType)
- union = IdlUnionType(
- [IdlType('long long'),
- IdlType('MyBooleanType')]).resolve_typedefs(typedefs)
- self.assertEqual(union.name, 'LongLongOrBoolean')
- self.assertEqual(union.member_types[0].name, 'LongLong')
- self.assertEqual(union.member_types[1].name, 'Boolean')
-
- # (Foo or SomeInterfaceT)
- union = IdlUnionType(
- [IdlType('Foo'),
- IdlType('SomeInterfaceT')]).resolve_typedefs(typedefs)
- self.assertEqual(union.name, 'UnsignedShortOrMyInterface')
- self.assertEqual(union.member_types[0].name, 'UnsignedShort')
- self.assertEqual(union.member_types[1].name, 'MyInterface')
-
- # (Foo or sequence<(MyBooleanType or double)>)
- union = IdlUnionType([
- IdlType('Foo'),
- IdlSequenceType(
- IdlUnionType([IdlType('MyBooleanType'),
- IdlType('double')]))
- ]).resolve_typedefs(typedefs)
- self.assertEqual(union.name, 'UnsignedShortOrBooleanOrDoubleSequence')
- self.assertEqual(union.member_types[0].name, 'UnsignedShort')
- self.assertEqual(union.member_types[1].name, 'BooleanOrDoubleSequence')
- self.assertEqual(union.member_types[1].element_type.name,
- 'BooleanOrDouble')
- self.assertEqual(
- union.member_types[1].element_type.member_types[0].name, 'Boolean')
- self.assertEqual(
- union.member_types[1].element_type.member_types[1].name, 'Double')
- self.assertEqual(2, len(union.flattened_member_types))
-
-
-class IdlNullableTypeTest(unittest.TestCase):
- _TEST_DICTIONARY = 'TestDictionary'
-
- def setUp(self):
- IdlType.dictionaries.add(self._TEST_DICTIONARY)
-
- def tearDown(self):
- IdlType.dictionaries.remove(self._TEST_DICTIONARY)
-
- def test_valid_inner_type_basic(self):
- inner_type = IdlType('long')
- self.assertTrue(IdlNullableType(inner_type).is_nullable)
-
- def test_valid_inner_type_dictionary(self):
- inner_type = IdlType(self._TEST_DICTIONARY)
- self.assertTrue(IdlNullableType(inner_type).is_nullable)
-
- def test_valid_inner_type_union(self):
- inner_type = IdlUnionType([IdlType('long')])
- self.assertTrue(IdlNullableType(inner_type).is_nullable)
-
- def test_invalid_inner_type_any(self):
- inner_type = IdlType('any')
- with self.assertRaises(ValueError):
- IdlNullableType(inner_type)
-
- def test_invalid_inner_type_promise(self):
- inner_type = IdlType('Promise')
- with self.assertRaises(ValueError):
- IdlNullableType(inner_type)
-
- def test_invalid_inner_type_nullable(self):
- inner_type = IdlNullableType(IdlType('long'))
- with self.assertRaises(ValueError):
- IdlNullableType(inner_type)
-
- def test_invalid_inner_type_union_nullable_member(self):
- inner_type = IdlUnionType([IdlNullableType(IdlType('long'))])
- with self.assertRaises(ValueError):
- IdlNullableType(inner_type)
-
- def test_invalid_inner_type_union_dictionary_member(self):
- inner_type = IdlUnionType([IdlType(self._TEST_DICTIONARY)])
- with self.assertRaises(ValueError):
- IdlNullableType(inner_type)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
deleted file mode 100644
index 64e84ef7da1..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
+++ /dev/null
@@ -1,119 +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.
-"""Validate extended attributes.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Extended-attribute-validation
-"""
-
-import os.path
-import re
-
-module_path = os.path.dirname(__file__)
-source_path = os.path.join(module_path, os.pardir, os.pardir)
-EXTENDED_ATTRIBUTES_RELATIVE_PATH = os.path.join('bindings',
- 'IDLExtendedAttributes.txt')
-EXTENDED_ATTRIBUTES_FILENAME = os.path.join(source_path,
- EXTENDED_ATTRIBUTES_RELATIVE_PATH)
-
-
-class IDLInvalidExtendedAttributeError(Exception):
- pass
-
-
-class IDLExtendedAttributeValidator(object):
- def __init__(self):
- self.valid_extended_attributes = read_extended_attributes_file()
-
- def validate_extended_attributes(self, definitions):
- # FIXME: this should be done when parsing the file, rather than after.
- for interface in definitions.interfaces.values():
- self.validate_extended_attributes_node(interface)
- for attribute in interface.attributes:
- self.validate_extended_attributes_node(attribute)
- for operation in interface.operations:
- self.validate_extended_attributes_node(operation)
- for argument in operation.arguments:
- self.validate_extended_attributes_node(argument)
- for dictionary in definitions.dictionaries.values():
- self.validate_extended_attributes_node(dictionary)
- for member in dictionary.members:
- self.validate_extended_attributes_node(member)
- for callback_function in definitions.callback_functions.values():
- self.validate_extended_attributes_node(callback_function)
- for argument in callback_function.arguments:
- self.validate_extended_attributes_node(argument)
-
- def validate_extended_attributes_node(self, node):
- for name, values_string in node.extended_attributes.items():
- self.validate_name_values_string(name, values_string)
-
- def validate_name_values_string(self, name, values_string):
- if name not in self.valid_extended_attributes:
- raise IDLInvalidExtendedAttributeError(
- 'Unknown extended attribute [%s]' % name)
- valid_values = self.valid_extended_attributes[name]
- if values_string is None and None not in valid_values:
- raise IDLInvalidExtendedAttributeError(
- 'Missing required argument for extended attribute [%s]' % name)
- if '*' in valid_values: # wildcard, any (non-empty) value ok
- return
- if values_string is None:
- values = set([None])
- elif isinstance(values_string, list):
- values = set(values_string)
- else:
- values = set([values_string])
- invalid_values = values - valid_values
- if invalid_values:
- invalid_value = invalid_values.pop()
- raise IDLInvalidExtendedAttributeError(
- 'Invalid value "%s" found in extended attribute [%s=%s]' %
- (invalid_value, name, values_string))
-
-
-def read_extended_attributes_file():
- def extended_attribute_name_values():
- with open(EXTENDED_ATTRIBUTES_FILENAME) as extended_attributes_file:
- for line in extended_attributes_file:
- line = line.strip()
- if not line or line.startswith('#'):
- continue
- name, _, values_string = map(str.strip, line.partition('='))
- value_list = [
- value.strip() for value in values_string.split('|')
- ]
- yield name, value_list
-
- valid_extended_attributes = {}
- for name, value_list in extended_attribute_name_values():
- if not value_list:
- valid_extended_attributes[name] = set([None])
- continue
- valid_extended_attributes[name] = set(
- [value if value else None for value in value_list])
- return valid_extended_attributes
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py b/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
deleted file mode 100644
index 8845480e660..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
+++ /dev/null
@@ -1,386 +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.
-"""Resolve interface dependencies, producing a merged IdlDefinitions object.
-
-This library computes interface dependencies (partial interfaces and
-includes), reads the dependency files, and merges them to the IdlDefinitions
-for the main IDL file, producing an IdlDefinitions object representing the
-entire interface.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Dependency-resolution
-"""
-
-import os.path
-from utilities import idl_filename_to_component, is_valid_component_dependency, merge_dict_recursively
-
-# The following extended attributes can be applied to a dependency interface,
-# and are then applied to the individual members when merging.
-# Note that this moves the extended attribute from the interface to the member,
-# which changes the semantics and yields different code than the same extended
-# attribute on the main interface.
-DEPENDENCY_EXTENDED_ATTRIBUTES = frozenset([
- 'CrossOriginIsolated',
- 'DirectSocketEnabled',
- 'RuntimeEnabled',
- 'SecureContext',
-])
-
-
-class InterfaceDependencyResolver(object):
- def __init__(self, interfaces_info, reader):
- """Initialize dependency resolver.
-
- Args:
- interfaces_info:
- dict of interfaces information, from compute_dependencies.py
- reader:
- IdlReader, used for reading dependency files
- """
- self.interfaces_info = interfaces_info
- self.reader = reader
-
- def resolve_dependencies(self, definitions, component):
- """Resolve dependencies, merging them into IDL definitions of main file.
-
- Dependencies consist of 'partial interface' for the same interface as
- in the main file, and mixins that this interface 'includes'.
- These are merged into the main IdlInterface, as the main IdlInterface
- implements all these members.
-
- Partial interfaces and mixins are added to IdlDefinitions, but not
- merged into the main IdlInterface, as these are only referenced (their
- members are introspected, but not implemented in this interface).
-
- Inherited extended attributes are also added to the main IdlInterface.
-
- Modifies definitions in place by adding parsed dependencies.
-
- Args:
- definitions: IdlDefinitions object, modified in place
- component:
- string, describing where the above definitions are defined,
- 'core' or 'modules'. See KNOWN_COMPONENTS in utilities.py
-
- Returns:
- A dictionary whose key is component and value is IdlDefinitions
- object whose dependency is resolved.
-
- Raises:
- Exception:
- A given IdlDefinitions object doesn't have any interfaces,
- or a given IdlDefinitions object has incorrect referenced
- interfaces.
- """
- # TODO(crbug.com/579896): we need to resolve dependency when we
- # support partial dictionary.
- if not definitions.interfaces:
- raise Exception('No need to resolve any dependencies of '
- 'this definition: %s, because this should '
- 'have a dictionary.' % definitions.idl_name)
-
- target_interface = next(iter(definitions.interfaces.values()))
- interface_name = target_interface.name
- interface_info = self.interfaces_info[interface_name]
-
- if 'inherited_extended_attributes' in interface_info:
- target_interface.extended_attributes.update(
- interface_info['inherited_extended_attributes'])
-
- resolved_definitions = merge_interface_dependencies(
- definitions, component, target_interface,
- interface_info['dependencies_full_paths'] +
- interface_info['dependencies_other_component_full_paths'],
- self.reader)
-
- inherit_unforgeable_attributes(resolved_definitions,
- self.interfaces_info)
-
- for referenced_interface_name in \
- interface_info['referenced_interfaces']:
- referenced_definitions = self.reader.read_idl_definitions(
- self.interfaces_info[referenced_interface_name]['full_path'])
-
- for referenced_component in referenced_definitions:
- if not is_valid_component_dependency(component,
- referenced_component):
- raise Exception('This definitions: %s is defined in %s '
- 'but reference interface:%s is defined '
- 'in %s' % (definitions.idl_name, component,
- referenced_interface_name,
- referenced_component))
-
- resolved_definitions[component].update(
- referenced_definitions[component])
-
- return resolved_definitions
-
-
-def merge_interface_dependencies(definitions, component, target_interface,
- dependency_idl_filenames, reader):
- """Merge dependencies ('partial interface' and 'implements') in dependency_idl_filenames into target_interface.
-
- Args:
- definitions: IdlDefinitions object, modified in place
- component:
- string, describing where the above definitions are defined,
- 'core' or 'modules'. See KNOWN_COMPONENTS in utilities.py
- target_interface: IdlInterface object, modified in place
- dependency_idl_filenames:
- Idl filenames which depend on the above definitions.
- reader: IdlReader object.
- Returns:
- A dictionary whose key is component and value is IdlDefinitions
- object whose dependency is resolved.
- """
- resolved_definitions = {component: definitions}
- # Sort so order consistent, so can compare output from run to run.
- for dependency_idl_filename in sorted(dependency_idl_filenames):
- dependency_definitions = reader.read_idl_file(dependency_idl_filename)
- dependency_component = idl_filename_to_component(
- dependency_idl_filename)
-
- dependency_interface = next(
- iter(dependency_definitions.interfaces.values()))
-
- transfer_extended_attributes(dependency_interface,
- dependency_idl_filename)
-
- # We need to use different checkdeps here for partial interface and
- # inheritance.
- if dependency_interface.is_partial:
- # Case: dependency_interface is a partial interface of
- # target_interface.
- # So,
- # - A partial interface defined in modules can update
- # the original interface defined in core.
- # However,
- # - A partial interface defined in core cannot update
- # the original interface defined in modules.
- if not is_valid_component_dependency(dependency_component,
- component):
- raise Exception(
- 'The partial interface:%s in %s cannot update '
- 'the original interface:%s in %s' %
- (dependency_interface.name, dependency_component,
- target_interface.name, component))
-
- if dependency_component in resolved_definitions:
- # When merging a new partial interfaces, should not overwrite
- # ImpelemntedAs extended attributes in merged partial
- # interface.
- # See also the below "if 'ImplementedAs' not in ... " line's
- # comment.
- dependency_interface.extended_attributes.pop(
- 'ImplementedAs', None)
- resolved_definitions[dependency_component].update(
- dependency_definitions)
- continue
-
- dependency_interface.extended_attributes.update(
- target_interface.extended_attributes)
- assert target_interface == \
- definitions.interfaces[dependency_interface.name]
- # A partial interface should use its original interface's
- # ImplementedAs. If the original interface doesn't have,
- # remove ImplementedAs defined in the partial interface.
- # Because partial interface needs the original interface's
- # cpp class to obtain partial interface's cpp class.
- # e.g.. V8WindowPartial.cpp:
- # DOMWindow* impl = V8Window::ToImpl(holder);
- # DOMWindowQuota* cpp_value(DOMWindowQuota::webkitStorageInfo(impl));
- # TODO(tasak): remove ImplementedAs extended attributes
- # from all partial interfaces. Instead, rename all cpp/header
- # files correctly. ImplementedAs should not be allowed in
- # partial interfaces.
- if 'ImplementedAs' not in target_interface.extended_attributes:
- dependency_interface.extended_attributes.pop(
- 'ImplementedAs', None)
- dependency_interface.original_interface = target_interface
- target_interface.partial_interfaces.append(dependency_interface)
- resolved_definitions[dependency_component] = dependency_definitions
- else:
- # Case: |target_interface| includes |dependency_interface| mixin.
- # So,
- # - An interface defined in modules can include any interface mixin
- # defined in core.
- # However,
- # - An interface defined in core cannot include an interface mixin
- # defined in modules.
- if not dependency_interface.is_mixin:
- raise Exception(
- 'The interface:%s cannot include '
- 'the non-mixin interface: %s.' %
- (target_interface.name, dependency_interface.name))
-
- if not is_valid_component_dependency(component,
- dependency_component):
- raise Exception(
- 'The interface:%s in %s cannot include '
- 'the interface mixin:%s in %s.' %
- (target_interface.name, component,
- dependency_interface.name, dependency_component))
-
- # merges partial interfaces
- resolved_definitions[component].update(dependency_definitions)
- # Mixins are also merged into the target interface, so Code
- # Generator can just iterate over one list (and not need to handle
- # 'includes' itself).
- target_interface.merge(dependency_interface)
-
- return resolved_definitions
-
-
-def transfer_extended_attributes(dependency_interface,
- dependency_idl_filename):
- """Transfer extended attributes from dependency interface onto members.
-
- Merging consists of storing certain interface-level data in extended
- attributes of the *members* (because there is no separate dependency
- interface post-merging).
-
- The data storing consists of:
- * moving certain extended attributes from the dependency interface
- to its members (deleting the extended attribute from the interface)
- * storing the C++ class of the implementation in an internal
- extended attribute of each member, [PartialInterfaceImplementedAs]
-
- No return: modifies dependency_interface in place.
- """
- merged_extended_attributes = {}
- for key in DEPENDENCY_EXTENDED_ATTRIBUTES:
- if key not in dependency_interface.extended_attributes:
- continue
-
- merged_extended_attributes[key] = \
- dependency_interface.extended_attributes[key]
- # Remove the merged attributes from the original dependency interface.
- # This ensures that if other dependency interfaces are merged onto this
- # one, its extended_attributes do not leak through
- # (https://crbug.com/603782).
- del dependency_interface.extended_attributes[key]
-
- # A partial interface's members are implemented as static member functions
- # in a separate C++ class. This class name is stored in
- # [PartialInterfaceImplementedAs] which is copied from [ImplementedAs] on
- # the partial interface definition.
- #
- # Note that implemented interfaces do *not* need [ImplementedAs], since
- # they are implemented on the C++ object |impl| itself, just like members of
- # the main interface definition, so the bindings do not need to know in
- # which class implemented interfaces are implemented.
- #
- # Currently [LegacyTreatAsPartialInterface] can be used to have partial
- # interface behavior on mixins, but this is being removed as legacy cruft:
- # http://crbug.com/360435
- #
- # Note that [ImplementedAs] is used with different meanings on interfaces
- # and members:
- # for Blink class name and function name (or constant name), respectively.
- # Thus we do not want to copy this from the interface to the member, but
- # instead extract it and handle it separately.
- if dependency_interface.is_partial:
- if 'ImplementedAs' not in dependency_interface.extended_attributes:
- raise ValueError('Partial interface in %s must have ImplementedAs.'
- % dependency_idl_filename)
- merged_extended_attributes['PartialInterfaceImplementedAs'] = \
- dependency_interface.extended_attributes.pop('ImplementedAs')
- elif 'LegacyTreatAsPartialInterface' in \
- dependency_interface.extended_attributes:
- merged_extended_attributes['PartialInterfaceImplementedAs'] = (
- dependency_interface.extended_attributes.pop(
- 'ImplementedAs', dependency_interface.name))
-
- def update_attributes(attributes, extras):
- for key, value in extras.items():
- if key not in attributes:
- attributes[key] = value
-
- for attribute in dependency_interface.attributes:
- update_attributes(attribute.extended_attributes,
- merged_extended_attributes)
- for constant in dependency_interface.constants:
- update_attributes(constant.extended_attributes,
- merged_extended_attributes)
- for operation in dependency_interface.operations:
- update_attributes(operation.extended_attributes,
- merged_extended_attributes)
-
-
-def inherit_unforgeable_attributes(resolved_definitions, interfaces_info):
- """Inherits [LegacyUnforgeable] attributes and updates the arguments
- accordingly.
-
- For each interface in |resolved_definitions|, collects all
- [LegacyUnforgeable] attributes in ancestor interfaces and adds them to the
- interface. 'referenced_interfaces' and 'cpp_includes' in |interfaces_info|
- are updated accordingly.
- """
-
- def collect_unforgeable_attributes_in_ancestors(interface_name, component):
- if not interface_name:
- # unforgeable_attributes, referenced_interfaces, cpp_includes
- return [], [], set()
- interface = interfaces_info[interface_name]
- unforgeable_attributes, referenced_interfaces, cpp_includes = \
- collect_unforgeable_attributes_in_ancestors(
- interface.get('parent'), component)
- this_unforgeable = interface.get('unforgeable_attributes', [])
- for attr in this_unforgeable:
- if attr.defined_in is None:
- attr.defined_in = interface_name
- unforgeable_attributes.extend(this_unforgeable)
- this_referenced = [
- attr.idl_type.base_type for attr in this_unforgeable
- if attr.idl_type.base_type in interface.get(
- 'referenced_interfaces', [])
- ]
- referenced_interfaces.extend(this_referenced)
- cpp_includes.update(
- interface.get('cpp_includes', {}).get(component, {}))
- return unforgeable_attributes, referenced_interfaces, cpp_includes
-
- for component, definitions in resolved_definitions.items():
- for interface_name, interface in definitions.interfaces.items():
- interface_info = interfaces_info[interface_name]
- inherited_unforgeable_attributes, referenced_interfaces, cpp_includes = \
- collect_unforgeable_attributes_in_ancestors(
- interface_info.get('parent'), component)
- # This loop may process the same interface many times, so it's
- # possible that we're adding the same attributes twice or more.
- # So check if there is a duplicate.
- for attr in inherited_unforgeable_attributes:
- if attr not in interface.attributes:
- interface.attributes.append(attr)
- referenced_interfaces.extend(
- interface_info.get('referenced_interfaces', []))
- interface_info['referenced_interfaces'] = sorted(
- set(referenced_interfaces))
- merge_dict_recursively(interface_info,
- {'cpp_includes': {
- component: cpp_includes
- }})
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py b/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py
deleted file mode 100644
index 309de695493..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py
+++ /dev/null
@@ -1,193 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# coding=utf-8
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from collections import Counter
-import itertools
-from operator import itemgetter
-
-
-def sort_and_groupby(list_to_sort, key=None):
- """Returns a generator of (key, list), sorting and grouping list by key."""
- list_to_sort.sort(key=key)
- return ((k, list(g)) for k, g in itertools.groupby(list_to_sort, key))
-
-
-def effective_overload_set(F): # pylint: disable=invalid-name
- """Returns the effective overload set of an overloaded function.
-
- An effective overload set is the set of overloaded functions + signatures
- derived from the set F by transforming it into the distinct permutations of
- function invocations possible given the argument types. It is used by the
- overload resolution algorithm.
-
- For example, given input:
- [
- f1(DOMString a),
- f2(Node a, DOMString b, double... c),
- f3(),
- f4(Event a, DOMString b, optional DOMString c, double... d)
- ]
-
- The output is:
- [
- (f1, [DOMString], [required]),
- (f2, [Node, DOMString], [required, required]),
- (f2, [Node, DOMString, double], [required, required, variadic]),
- (f2, [Node, DOMString, double, double], [required, required, variadic, variadic]),
- (f3, [], []),
- (f4, [Event, DOMString], [required, required],
- (f4, [Event, DOMString, DOMString], [required, required, optional]),
- (f4, [Event, DOMString, DOMString, double], [required, required, optional, variadic])
- ]
-
- Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set.
-
- Formally the input and output lists are sets, but methods are stored
- internally as dicts, which can't be stored in a set because they are not
- hashable, so we use lists instead.
-
- Arguments:
- F: list of overloads for a given callable name.
-
- Returns:
- S: list of tuples of the form:
- (callable, tuple(type list), tuple(optionality list)).
- """
- # Code closely follows the algorithm in the spec, for clarity and
- # correctness, and hence is not very Pythonic.
-
- # 1. Let S be an ordered set.
- # (We use a list because we can't use a set, as noted above.)
- S = [] # pylint: disable=invalid-name
-
- # 2. Let F be an ordered set with items as follows, according to the kind of
- # effective overload set:
- # (Passed as argument, nothing to do.)
-
- # 3. Let maxarg be the maximum number of arguments the operations,
- # constructor extended attributes or callback functions in F are declared
- # to take. For variadic operations and constructor extended attributes,
- # the argument on which the ellipsis appears counts as a single argument.
- # Note: So void f(long x, long... y); is considered to be declared to take
- # two arguments.
- # X is the "callable".
- maxarg = max([len(X['arguments']) for X in F])
-
- # 4. Let max be max(maxarg, N).
- # Per: https://github.com/heycam/webidl/issues/600.
-
- # The effective overload set as defined in the Web IDL spec is used at
- # runtime as an input to the overload resolution algorithm. The runtime
- # portion of the overload resolution algorithm includes coercing arguments
- # into the proper type. To perform that coercion, the effective overload set
- # must produce variadic entries in the type list to match the number of
- # arguments supplied for the invocation (N) of the function.
-
- # Our use of the effective overload set, however, is limited to determining
- # which function overload should handle the invocation. Coercion of
- # arguments is a separate problem making N irrelevant and max always equal
- # to maxarg.
-
- # 5. For each operation, extended attribute or callback function X in F:
- for X in F: # pylint: disable=invalid-name
- # 5.1. Let arguments be the list of arguments X is declared to take.
- arguments = X['arguments'] # pylint: disable=invalid-name
- # 5.2. Let n be the size of arguments.
- n = len(arguments) # pylint: disable=invalid-name
- # 5.3. Let types be a type list.
- # 5.4. Let optionalityValues be an optionality list.
- types, optionality_values = [], []
-
- # 5.5. For each argument in arguments:
- for argument in arguments:
- # 5.5.1. Append the type of argument to types.
- types.append(argument['idl_type_object'])
- # 5.5.2. Append "variadic" to optionalityValues if argument is a
- # final, variadic argument, "optional" if argument is optional,
- # and "required" otherwise.
- if argument['is_variadic']:
- optionality_values.append('variadic')
- elif argument['is_optional']:
- optionality_values.append('optional')
- else:
- optionality_values.append('required')
-
- # 5.6. Append the tuple (X, types, optionalityValues) to S.
- S.append((X, tuple(types), tuple(optionality_values)))
-
- # 5.7. If X is declared to be variadic, then:
- if optionality_values and optionality_values[-1] == 'variadic':
- # 5.7.1. For each i in the range n to max - 1, inclusive:
- for i in range(n, maxarg):
- # 5.7.1.1. Let t be a type list.
- # 5.7.1.2. Let o be an optionality list.
- type_list, optionality_list = [], []
- # 5.7.1.3. For each j in the range 0 to n-1, inclusive:
- for j in range(0, n):
- # 5.7.1.3.1. Append types[j] to t.
- type_list.append(types[j])
- # 5.7.1.3.2. Append optionalityValues[j] to o.
- optionality_list.append(optionality_values[j])
- # 5.7.1.4. For each j in the range n to i, inclusive:
- for j in range(n, i + 1):
- # 5.7.1.4.1. Append types[n - 1] to t.
- type_list.append(types[n - 1])
- # 5.7.1.4.2. Append "variadic" to o.
- optionality_list.append('variadic')
- # 5.7.1.5. Append the tuple (X, t, o) to S.
- S.append((X, tuple(type_list), tuple(optionality_list)))
- # 5.8. Let i be n - 1.
- i = n - 1
-
- # 5.9. While i ≥ 0:
- while i >= 0:
- # 5.9.1. If arguments[i] is not optional (i.e., it is not marked as
- # "optional" and is not a final, variadic argument), then break.
- if optionality_values[i] == 'required':
- break
-
- # 5.9.2. Let t be a type list.
- # 5.9.3. Let o be an optionality list.
- type_list, optionality_list = [], []
- # 5.9.4. For each j in the range 0 to i-1, inclusive:
- for j in range(0, i):
- # 5.9.4.1. Append types[j] to t.
- type_list.append(types[j])
- # 5.9.4.2. Append optionalityValues[j] to o.
- optionality_list.append(optionality_values[j])
- # 5.9.5. Append the tuple (X, t, o) to S.
- # Note: if i is 0, this means to add to S the tuple (X, « », « »);
- # (where "« »" represents an empty list).
- S.append((X, tuple(type_list), tuple(optionality_list)))
- # 5.9.6. Set i to i−1.
- i = i - 1
-
- # 6. Return S.
- return S
-
-
-def effective_overload_set_by_length(overloads):
- def type_list_length(entry):
- # Entries in the effective overload set are 3-tuples:
- # (callable, type list, optionality list)
- return len(entry[1])
-
- effective_overloads = effective_overload_set(overloads)
- return list(sort_and_groupby(effective_overloads, type_list_length))
-
-
-def method_overloads_by_name(methods):
- """Returns generator of overloaded methods by name: [name, [method]]"""
- # Filter to only methods that are actually overloaded
- method_counts = Counter(method['name'] for method in methods)
- overloaded_method_names = set(
- name for name, count in method_counts.items() if count > 1)
- overloaded_methods = [
- method for method in methods
- if method['name'] in overloaded_method_names
- ]
-
- # Group by name (generally will be defined together, but not necessarily)
- return sort_and_groupby(overloaded_methods, itemgetter('name'))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py b/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py
deleted file mode 100644
index 3a94c06e615..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py
+++ /dev/null
@@ -1,339 +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.
-
-# pylint: disable=import-error,print-statement,relative-import,protected-access
-"""Unit tests for overload_set_algorithm.py."""
-
-import unittest
-from overload_set_algorithm import effective_overload_set
-
-# disabling yapf formating for complex data, see
-# https://github.com/google/yapf#why-does-yapf-destroy-my-awesome-formatting
-# yapf: disable
-
-class EffectiveOverloadSetTest(unittest.TestCase):
- def test_example_in_comments(self):
- operation_list = [
- # f1: f(optional long x)
- {'arguments': [{'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False}]},
- # f2: f(DOMString s)
- {'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False}]}]
-
- overload_set = [
- # <f1, (long), (optional)>
- ({'arguments': [{'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False}]},
- ('long',),
- ('optional',)),
- # <f1, (), ()>
- ({'arguments': [{'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False}]},
- (),
- ()),
- # <f2, (DOMString), (required)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False}]},
- ('DOMString',),
- ('required',))]
-
- self.assertEqual(effective_overload_set(operation_list), overload_set)
-
- def test_example_in_spec(self):
- """Tests the example provided in Web IDL spec:
- https://heycam.github.io/webidl/#dfn-effective-overload-set,
- look for example right after the algorithm."""
- operation_list = [
- # f1: f(DOMString a)
- {'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False}]},
- # f2: f(Node a, DOMString b, double... c)
- {'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- # f3: f()
- {'arguments': []},
- # f4: f(Event a, DOMString b, optional DOMString c, double... d)
- {'arguments': [{'idl_type_object': 'Event',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]}]
-
- overload_set = [
- # <f1, (DOMString), (required)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False}]},
- ('DOMString',),
- ('required',)),
- # <f2, (Node, DOMString, double), (required, required, variadic)>
- ({'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Node', 'DOMString', 'double'),
- ('required', 'required', 'variadic')),
- # <f2, (Node, DOMString, double, double),
- # (required, required, variadic, variadic)>
- ({'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Node', 'DOMString', 'double', 'double'),
- ('required', 'required', 'variadic', 'variadic')),
- # <f2, (Node, DOMString), (required, required)>
- ({'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Node', 'DOMString'),
- ('required', 'required')),
- # <f3, (), ()>
- ({'arguments': []},
- (),
- ()),
- # <f4, (Event, DOMString, DOMString, double),
- # (required, required, optional, variadic)>
- ({'arguments': [{'idl_type_object': 'Event',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Event', 'DOMString', 'DOMString', 'double'),
- ('required', 'required', 'optional', 'variadic')),
- # <f4, (Event, DOMString, DOMString),
- # (required, required, optional)>
- ({'arguments': [{'idl_type_object': 'Event',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Event', 'DOMString', 'DOMString'),
- ('required', 'required', 'optional')),
- # <f4, (Event, DOMString), (required, required)>
- ({'arguments': [{'idl_type_object': 'Event',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'double',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Event', 'DOMString'),
- ('required', 'required'))]
-
- self.assertEqual(effective_overload_set(operation_list), overload_set)
-
- def test_element_create_proposed_syntax(self):
- """Tests the proposed syntax for the convenience method Element.create.
- Github issue: https://github.com/whatwg/dom/issues/477"""
- operation_list = [
- # f1: f(DOMString tag, Record<DOMString, DOMString> attrs, (Node or DOMString)... children)
- {'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'record<DOMString, DOMString>',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- # f2: f(DOMString tag, (Node or DOMString)... children)
- {'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]}]
-
- overload_set = [
- # <f1, (DOMString, Record, NodeOrDOMString), (required, required, variadic)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'record<DOMString, DOMString>',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString', 'record<DOMString, DOMString>', 'NodeOrDOMString'),
- ('required', 'required', 'variadic')),
- # <f1, (DOMString, Record), (required, required)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'record<DOMString, DOMString>',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString', 'record<DOMString, DOMString>'),
- ('required', 'required')),
- # <f2, (DOMString, NodeOrDOMString), (required, variadic)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString', 'NodeOrDOMString'),
- ('required', 'variadic')),
- # <f2, (DOMString, NodeOrDOMString, NodeOrDOMString), (required, variadic, variadic)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString', 'NodeOrDOMString', 'NodeOrDOMString'),
- ('required', 'variadic', 'variadic')),
- # <f2, (DOMString), (required)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'NodeOrDOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString',),
- ('required',))]
-
- self.assertEqual(effective_overload_set(operation_list), overload_set)
-
- def test_optional_preceding_variadic(self):
- operation_list = [
- # f1: f(Node a, optional long b, DOMString... c)
- {'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- # f2: f(DOMString... a)
- {'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]}]
-
- overload_set = [
- # <f1, (Node, long, DOMString), (required, optional, variadic)>
- ({'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Node', 'long', 'DOMString'),
- ('required', 'optional', 'variadic')),
- # <f1, (Node, long), (required, optional)>
- ({'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Node', 'long'),
- ('required', 'optional')),
- # <f1, (Node), (required)>
- ({'arguments': [{'idl_type_object': 'Node',
- 'is_optional': False,
- 'is_variadic': False},
- {'idl_type_object': 'long',
- 'is_optional': True,
- 'is_variadic': False},
- {'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('Node',),
- ('required',)),
- # <f2, (DOMString), (variadic)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString',),
- ('variadic',)),
- # <f2, (DOMString, DOMString), (variadic, variadic)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString', 'DOMString'),
- ('variadic', 'variadic')),
- # <f2, (DOMString, DOMString, DOMString), (variadic, variadic, variadic)>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- ('DOMString', 'DOMString', 'DOMString'),
- ('variadic', 'variadic', 'variadic')),
- # <f2, (), ()>
- ({'arguments': [{'idl_type_object': 'DOMString',
- 'is_optional': False,
- 'is_variadic': True}]},
- (),
- ())]
-
- self.assertEqual(effective_overload_set(operation_list), overload_set)
-# yapf: enable
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni b/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni
index eb796d6ba09..e6367394035 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni
+++ b/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni
@@ -4,108 +4,10 @@
import("//build/config/python.gni")
import("//third_party/blink/renderer/build/scripts/scripts.gni")
-import("//third_party/blink/renderer/core/core_idl_files.gni")
-import("//third_party/blink/renderer/modules/modules_idl_files.gni")
bindings_scripts_dir = get_path_info(".", "abspath")
bindings_scripts_output_dir = get_path_info(".", "gen_dir")
-jinja_module_files = [
- "//third_party/jinja2/__init__.py",
- "//third_party/markupsafe/__init__.py", # jinja2 dep
-]
-
-idl_lexer_parser_files = get_path_info([
- # PLY (Python Lex-Yacc)
- "//third_party/ply/lex.py",
- "//third_party/ply/yacc.py",
-
- # Web IDL lexer/parser (base parser)
- "//tools/idl_parser/idl_lexer.py",
- "//tools/idl_parser/idl_node.py",
- "//tools/idl_parser/idl_parser.py",
-
- # Blink IDL lexer/parser/constructor
- "blink_idl_lexer.py",
- "blink_idl_parser.py",
- ],
- "abspath")
-idl_compiler_files = get_path_info(
- [
- "idl_compiler.py",
-
- # Blink IDL front end (ex-lexer/parser)
- "idl_definitions.py",
- "idl_reader.py",
- "idl_types.py",
- "idl_validator.py",
- "interface_dependency_resolver.py",
-
- # V8 code generator
- "code_generator.py",
- "code_generator_v8.py",
- "v8_attributes.py",
- "v8_callback_function.py",
- "v8_callback_interface.py",
- "v8_dictionary.py",
- "v8_globals.py",
- "v8_interface.py",
- "v8_methods.py",
- "v8_types.py",
- "v8_union.py",
- "v8_utilities.py",
- "//third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py",
- ],
- "abspath")
-
-# Calls the compute_interfaces_info_individual script.
-#
-# Parameters:
-# sources = list of IDL files to pass as inputs
-# interfaces_info_file = output pickle file for interfaces info.
-# component_info_file = output pickle file for component wide info.
-# deps = dependencies
-template("compute_interfaces_info") {
- action(target_name) {
- script = "$bindings_scripts_dir/compute_interfaces_info_individual.py"
- if (defined(invoker.visibility)) {
- visibility = invoker.visibility
- }
-
- build_scripts_output_dir =
- "$root_gen_dir/third_party/blink/renderer/build/scripts"
- runtime_enabled_features_file =
- "$build_scripts_output_dir/runtime_enabled_features.pickle"
- inputs = [
- "$bindings_scripts_dir/utilities.py",
- runtime_enabled_features_file,
- ] + idl_compiler_files + invoker.sources
- outputs = [
- invoker.interfaces_info_file,
- invoker.component_info_file,
- ]
-
- response_file_contents = rebase_path(invoker.sources, root_build_dir)
- args = [
- "--cache-directory",
- rebase_path(bindings_scripts_output_dir, root_build_dir),
- "--idl-files-list",
- "{{response_file_name}}",
- "--interfaces-info-file",
- rebase_path(invoker.interfaces_info_file, root_build_dir),
- "--component-info-file",
- rebase_path(invoker.component_info_file, root_build_dir),
- "--runtime-enabled-features-file",
- rebase_path(runtime_enabled_features_file, root_build_dir),
- ]
-
- deps = [
- "//third_party/blink/renderer/bindings/scripts:cached_lex_yacc_tables",
- "//third_party/blink/renderer/platform:runtime_enabled_features",
- ] + invoker.deps
- }
-}
-
# Calls generate_event_interfaces
#
# Parameters:
@@ -144,335 +46,3 @@ template("generate_event_interfaces") {
}
}
}
-
-# Runs the idl_compiler script over a list of sources.
-#
-# Parameters:
-# sources = list of IDL files to compile
-# output_dir = string containing the directory to put the output files.
-# output_name_suffix = a suffix after the basename of the output file names.
-# target_component = component to generate code for.
-template("idl_compiler") {
- output_dir = invoker.output_dir
- output_name_suffix = invoker.output_name_suffix
-
- # TODO(brettw): we used to add a "-S" before the script name to skip
- # "import site" to speed up startup. Figure out if we need this and do
- # something similar (not really expressible in GN now).
- _script = "//third_party/blink/renderer/bindings/scripts/idl_compiler.py"
- _inputs =
- idl_lexer_parser_files + idl_compiler_files # to be explicit (covered by
- # parsetab)
- _inputs += [
- "$bindings_scripts_output_dir/parsetab.pickle",
- "$bindings_scripts_output_dir/cached_jinja_templates.stamp",
- "$bindings_dir/IDLExtendedAttributes.txt",
-
- # If the dependency structure or public interface info (e.g.,
- # [ImplementedAs]) changes, we rebuild all files, since we're not
- # computing dependencies file-by-file in the build.
- # This data is generally stable.
- "$bindings_output_dir/interfaces_info.pickle",
- ]
-
- # Further, if any dependency (partial interface or implemented
- # interface) changes, rebuild everything, since every IDL potentially
- # depends on them, because we're not computing dependencies
- # file-by-file.
- # FIXME: This is too conservative, and causes excess rebuilds:
- # compute this file-by-file. http://crbug.com/341748
- # This should theoretically just be the IDL files passed in.
- _inputs += core_all_dependency_idl_files + modules_all_dependency_idl_files
-
- _public_deps = [
- "//third_party/blink/renderer/bindings:global_constructors_idls",
- "//third_party/blink/renderer/bindings:interfaces_info",
- "//third_party/blink/renderer/bindings/core:core_global_constructors_idls",
- "//third_party/blink/renderer/bindings/modules:modules_global_constructors_idls",
- "//third_party/blink/renderer/bindings/scripts:cached_jinja_templates",
- "//third_party/blink/renderer/bindings/scripts:cached_lex_yacc_tables",
- "//third_party/blink/renderer/core:generated_testing_idls",
- ]
-
- # Spawning a python process per IDL file is slow. Use a single action
- # instead (crbug.com/821256).
- action(target_name) {
- script = _script
- inputs = _inputs
- public_deps = _public_deps
-
- sources = invoker.sources
- outputs = []
- foreach(_source, sources) {
- _name_part = get_path_info(_source, "name")
- outputs += [
- "$output_dir/v8_${_name_part}${output_name_suffix}.cc",
- "$output_dir/v8_${_name_part}${output_name_suffix}.h",
- ]
- }
-
- idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
- write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir))
- inputs += [ idl_files_list ]
-
- args = [
- "--cache-dir",
- rebase_path(bindings_scripts_output_dir, root_build_dir),
- "--output-dir",
- rebase_path(output_dir, root_build_dir),
- "--info-dir",
- rebase_path("$bindings_output_dir", root_build_dir),
- "--target-component",
- invoker.target_component,
- "--read-idl-list-from-file",
- rebase_path(idl_files_list, root_build_dir),
- ]
- }
-}
-
-# Runs idl_compiler.py to generate IDL dictionary impl files, unions and
-# callback functions.
-#
-# Parameters:
-# dict_idls = a list of dictionary IDL files to process. the callback and
-# union IDL file names are already known and do not need to be
-# specified.
-# non_dict_outputs = a list of files generated from callback functions and
-# unions. the list of files generated from |dict_idls| is
-# added automatically and does not need to be specified.
-# non_dict_output_dir = the directory to put the non-dict output files.
-# target_component = component to generate code for
-template("idl_impl") {
- dictionary_impl_output_dir = "$root_gen_dir/third_party/blink/renderer/"
-
- action(target_name) {
- script = "//third_party/blink/renderer/bindings/scripts/idl_compiler.py"
- idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
- write_file(idl_files_list, rebase_path(invoker.dict_idls, root_build_dir))
-
- inputs =
- idl_lexer_parser_files + idl_compiler_files # to be explicit (covered
- # by parsetab)
- inputs += [
- "$bindings_scripts_output_dir/parsetab.pickle",
- "$bindings_scripts_output_dir/cached_jinja_templates.stamp",
- "$bindings_dir/IDLExtendedAttributes.txt",
- ]
- inputs += [ idl_files_list ] + invoker.dict_idls
- outputs = invoker.non_dict_outputs
-
- # Derive the names of the generated dictionary impl files. Contrary to
- # generated interfaces, callbacks and unions, these files go to
- # $root_gen_dir/third_party/blink/renderer/{core,modules}/<module name>/<IDLName>.{cpp,h}.
- foreach(dict_idl, invoker.dict_idls) {
- rel_path = rebase_path(dict_idl, "//third_party/blink/renderer")
- impl_dir = get_path_info(rel_path, "dir")
- idl_name = get_path_info(rel_path, "name")
- outputs += [
- "${dictionary_impl_output_dir}$impl_dir/$idl_name.cc",
- "${dictionary_impl_output_dir}$impl_dir/$idl_name.h",
- ]
- }
-
- args = [
- "--cache-dir",
- rebase_path(bindings_scripts_output_dir, root_build_dir),
- "--output-dir",
- rebase_path(invoker.non_dict_output_dir, root_build_dir),
- "--impl-output-dir",
- rebase_path(dictionary_impl_output_dir, root_build_dir),
- "--info-dir",
- rebase_path("$bindings_output_dir", root_build_dir),
- "--target-component",
- invoker.target_component,
- "--generate-impl",
- ]
- if (use_blink_v8_binding_new_idl_callback_function) {
- args += [ "--generate-impl-skip-callback-function" ]
- }
- args += [ rebase_path(idl_files_list, root_build_dir) ]
-
- deps = [
- "//third_party/blink/renderer/bindings:interfaces_info",
- "//third_party/blink/renderer/bindings/scripts:cached_jinja_templates",
- "//third_party/blink/renderer/bindings/scripts:cached_lex_yacc_tables",
- ]
- }
-}
-
-# Calls the aggregate_generated_bindings script.
-#
-# Parameters:
-# sources = a list of source IDL files.
-# component = a name of directory for these files (one word, no slashes).
-# outputs = a name of file to write to.
-template("aggregate_generated_bindings") {
- action(target_name) {
- script = "//third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py"
-
- inputs = invoker.sources
- outputs = invoker.outputs
-
- response_file_contents = rebase_path(inputs, root_build_dir)
- args = [
- "--component",
- invoker.component,
- "{{response_file_name}}",
- ]
- args += rebase_path(outputs, root_build_dir)
-
- public_deps = invoker.public_deps
- }
-}
-
-# Calls the compute_global_objects script.
-#
-# Parameters:
-# sources = a list of source IDL files.
-# sources_generated = a list of generated pickle sources.
-# output_file = a pickle file to write to (need to specify directory)
-#
-template("compute_global_objects") {
- action(target_name) {
- script = "//third_party/blink/renderer/bindings/scripts/compute_global_objects.py"
-
- # Write the file list to a unique temp file to avoid blowing out the
- # command line length limit.
- idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
- write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir))
-
- inputs = [
- "//third_party/blink/renderer/bindings/scripts/utilities.py",
- idl_files_list,
- ] + invoker.sources_generated + invoker.sources
-
- outputs = [ invoker.output_file ]
-
- args = [
- "--idl-files-list",
- rebase_path(idl_files_list, root_build_dir),
- ]
- foreach(component, invoker.sources_generated) {
- args += [
- "--global-objects-component-files",
- rebase_path(component, root_build_dir),
- ]
- }
- args += [ rebase_path(invoker.output_file, root_build_dir) ]
-
- deps = invoker.deps
- }
-}
-
-# Calls the generate_global_constructors script.
-#
-# Parameters:
-# sources = a list of source IDL files.
-# global_objects_file = a global objects file generated by compute_global_objects
-# interfaces = interfaces to generate global constructors for.
-# component = component to generate global constructors for.
-# output_dir = output directory to generate idl files and header files.
-# deps = dependencies
-#
-template("generate_global_constructors") {
- action(target_name) {
- script = "//third_party/blink/renderer/bindings/scripts/generate_global_constructors.py"
-
- # Write the file list to a unique temp file to avoid blowing out the
- # command line length limit.
- idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
- write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir))
-
- inputs = [
- "//third_party/blink/renderer/bindings/scripts/utilities.py",
- idl_files_list,
- invoker.global_objects_file,
- ] + invoker.sources
-
- args = [
- "--idl-files-list",
- rebase_path(idl_files_list, root_build_dir),
- "--global-objects-file",
- rebase_path(invoker.global_objects_file, root_build_dir),
- "--",
- ]
-
- output_dir = invoker.output_dir
- component = invoker.component
-
- # generate outputs from invoker.interfaces and invoker.basenames.
- output_idl_files = []
- output_header_files = []
-
- # Need a variable due to a GN sytax restriction. We can't do "invoker.basenames[i]".
- basename_list = invoker.basenames
- i = 0
- foreach(interface, invoker.interfaces) {
- basename = basename_list[i]
- args += [ interface ]
- output_idl_file = "$output_dir/${basename}_${component}_constructors.idl"
- args += [ rebase_path(output_idl_file, root_build_dir) ]
- output_idl_files += [ output_idl_file ]
- output_header_files +=
- [ "$output_dir/${basename}_${component}_constructors.h" ]
- i += 1
- }
-
- outputs = output_idl_files + output_header_files
- if (defined(invoker.deps)) {
- deps = invoker.deps
- }
- if (defined(invoker.public_deps)) {
- public_deps = invoker.public_deps
- }
- }
-}
-
-# Calls the generate_origin_trial_features script.
-#
-# Parameters:
-# sources = a list of source IDL files.
-# component = component for which to generate origin trial feature bindings
-# ("core" or "modules")
-# output_dir = output directory to generate cpp file and header file.
-# deps = dependencies
-#
-template("generate_origin_trial_features") {
- action(target_name) {
- script = "//third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py"
-
- # Write the file list to a unique temp file to avoid blowing out the
- # command line length limit.
- idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
- write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir))
-
- inputs = [
- "//third_party/blink/renderer/bindings/scripts/utilities.py",
- "//third_party/blink/renderer/bindings/templates/origin_trial_features_for_${invoker.component}.cc.tmpl",
- "//third_party/blink/renderer/bindings/templates/origin_trial_features_for_${invoker.component}.h.tmpl",
- "$bindings_output_dir/interfaces_info.pickle",
- idl_files_list,
- ] + invoker.sources
-
- args = [
- "--output-directory",
- rebase_path(invoker.output_dir, root_build_dir),
- "--info-dir",
- rebase_path("$bindings_output_dir", root_build_dir),
- "--cache-dir",
- rebase_path(bindings_scripts_output_dir, root_build_dir),
- "--target-component",
- invoker.component,
- "--idl-files-list",
- rebase_path(idl_files_list, root_build_dir),
- ]
-
- outputs = [
- "${invoker.output_dir}/origin_trial_features_for_${invoker.component}.cc",
- "${invoker.output_dir}/origin_trial_features_for_${invoker.component}.h",
- ]
-
- deps = [ "//third_party/blink/renderer/bindings:interfaces_info" ] +
- invoker.deps
- }
-}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
deleted file mode 100644
index 3adf4eaf841..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
+++ /dev/null
@@ -1,812 +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.
-
-# pylint: disable=relative-import
-"""Generate template values for attributes.
-
-Extends IdlType with property |constructor_type_name|.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-import os
-import sys
-
-sys.path.append(
- os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
-from blinkbuild.name_style_converter import NameStyleConverter
-import idl_types
-from idl_types import inherits_interface
-from v8_globals import includes
-import v8_types
-import v8_utilities
-from v8_utilities import capitalize
-from v8_utilities import cpp_encoded_property_name
-from v8_utilities import cpp_name
-from v8_utilities import extended_attribute_value_as_list
-from v8_utilities import has_extended_attribute_value
-from v8_utilities import is_unforgeable
-from v8_utilities import scoped_name
-from v8_utilities import strip_suffix
-from v8_utilities import uncapitalize
-from blinkbuild.name_style_converter import NameStyleConverter
-
-
-def attribute_context(interface, attribute, interfaces, component_info):
- """Creates a Jinja template context for an attribute of an interface.
-
- Args:
- interface: An interface which |attribute| belongs to
- attribute: An attribute to create the context for
- interfaces: A dict which maps an interface name to the definition
- which can be referred if needed
- component_info: A dict containing component wide information
-
- Returns:
- A Jinja template context for |attribute|
- """
-
- idl_type = attribute.idl_type
- base_idl_type = idl_type.base_type
- extended_attributes = attribute.extended_attributes
-
- idl_type.add_includes_for_type(extended_attributes)
- if idl_type.enum_values:
- includes.add('core/inspector/console_message.h')
- includes.add('platform/heap/heap.h')
-
- # [CheckSecurity]
- is_cross_origin = 'CrossOrigin' in extended_attributes
- is_check_security_for_receiver = (has_extended_attribute_value(
- interface, 'CheckSecurity', 'Receiver') and is_cross_origin)
- is_check_security_for_return_value = (has_extended_attribute_value(
- attribute, 'CheckSecurity', 'ReturnValue'))
- if is_check_security_for_receiver or is_check_security_for_return_value:
- includes.add('bindings/core/v8/binding_security.h')
- if is_check_security_for_return_value:
- includes.add('core/frame/web_feature.h')
- includes.add('platform/instrumentation/use_counter.h')
- # [CrossOrigin]
- if has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'):
- includes.add('platform/bindings/v8_cross_origin_callback_info.h')
- # [Constructor]
- # TODO(yukishiino): Constructors are much like methods although constructors
- # are not methods. Constructors must be data-type properties, and we can
- # support them as a kind of methods.
- constructor_type = idl_type.constructor_type_name if is_constructor_attribute(
- attribute) else None
- # [CEReactions]
- is_ce_reactions = 'CEReactions' in extended_attributes
- if is_ce_reactions:
- includes.add('core/html/custom/ce_reactions_scope.h')
- # [Reflect]
- is_reflect = 'Reflect' in extended_attributes
- # [ReflectOnly]
- reflect_only = extended_attribute_value_as_list(attribute, 'ReflectOnly')
- if reflect_only:
- reflect_only = map(
- lambda v: cpp_content_attribute_value_name(interface, v),
- reflect_only)
- # [PerWorldBindings]
- if 'PerWorldBindings' in extended_attributes:
- assert idl_type.is_wrapper_type or 'LogActivity' in \
- extended_attributes, \
- '[PerWorldBindings] should only be used with wrapper types: %s.%s' % \
- (interface.name, attribute.name)
- # [SaveSameObject]
- is_save_same_object = ('SameObject' in attribute.extended_attributes and
- 'SaveSameObject' in attribute.extended_attributes)
-
- # [StringContext]
- if idl_type.has_string_context:
- includes.add('bindings/core/v8/generated_code_helper.h')
-
- # [CachedAccessor]
- is_cached_accessor = 'CachedAccessor' in extended_attributes
-
- # [LegacyLenientSetter]
- is_lenient_setter = 'LegacyLenientSetter' in extended_attributes
-
- # [CachedAttribute]
- cached_attribute_validation_method = extended_attributes.get(
- 'CachedAttribute')
-
- keep_alive_for_gc = is_keep_alive_for_gc(interface, attribute)
-
- does_generate_getter = (not has_custom_getter(attribute)
- and not constructor_type)
- does_generate_setter = (
- has_setter(interface, attribute)
- and not (has_custom_setter(attribute) or is_lenient_setter))
-
- use_private_property_in_getter = (does_generate_getter
- and (cached_attribute_validation_method
- or is_save_same_object
- or keep_alive_for_gc))
- use_private_property_in_setter = (does_generate_setter
- and cached_attribute_validation_method)
- private_property_is_shared_between_getter_and_setter = (
- use_private_property_in_getter and use_private_property_in_setter)
-
- does_use_private_property = (use_private_property_in_getter
- or use_private_property_in_setter
- or is_cached_accessor)
- if does_use_private_property:
- includes.add('platform/bindings/v8_private_property.h')
-
- # [LogActivity]
- if 'LogActivity' in extended_attributes:
- includes.add('platform/bindings/v8_per_context_data.h')
-
- # [DeprecateAs], [MeasureAs]
- deprecate_as = v8_utilities.deprecate_as(attribute)
- measure_as = v8_utilities.measure_as(attribute, interface)
-
- # [HighEntropy]
- high_entropy = v8_utilities.high_entropy(attribute)
-
- is_lazy_data_attribute = \
- (constructor_type and not (measure_as or deprecate_as)) or \
- (str(idl_type) == 'Window' and attribute.name in ('frames', 'self', 'window'))
-
- runtime_features = component_info['runtime_enabled_features']
-
- internal_name = cpp_encoded_property_name(attribute)
-
- cpp_type = idl_type.cpp_type
- if idl_type.is_explicit_nullable:
- cpp_type = v8_types.cpp_template_type('absl::optional', cpp_type)
-
- context = {
- # [ActivityLogging]
- '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]
- 'activity_logging_world_check':
- v8_utilities.activity_logging_world_check(attribute),
- 'cached_accessor_name':
- 'k%s%s' % (interface.name, attribute.name.capitalize()),
- 'cached_attribute_validation_method':
- cached_attribute_validation_method,
- 'camel_case_name':
- NameStyleConverter(internal_name).to_upper_camel_case(),
- 'constructor_type':
- constructor_type,
- 'context_enabled_feature_name':
- v8_utilities.context_enabled_feature_name(attribute),
- 'cpp_name': cpp_name(attribute),
- 'cpp_type': cpp_type,
- 'cpp_type_initializer': idl_type.cpp_type_initializer,
- 'deprecate_as': deprecate_as,
- 'does_generate_getter': does_generate_getter,
- 'does_generate_setter': does_generate_setter,
- 'enum_type': idl_type.enum_type,
- 'enum_values': idl_type.enum_values,
- # [Exposed]
- 'exposed_test':
- v8_utilities.exposed(attribute, interface),
- 'getter_has_no_side_effect':
- has_extended_attribute_value(attribute, 'Affects', 'Nothing'),
- 'has_cross_origin_getter':
- has_extended_attribute_value(attribute, 'CrossOrigin', None) or
- has_extended_attribute_value(attribute, 'CrossOrigin', 'Getter'),
- 'has_cross_origin_setter':
- has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'),
- 'has_custom_getter': has_custom_getter(attribute),
- 'has_custom_setter': has_custom_setter(attribute),
- 'has_promise_type': idl_type.name == 'Promise',
- 'has_setter': has_setter(interface, attribute),
- 'high_entropy': high_entropy,
- 'idl_type': str(idl_type),
- 'is_cached_accessor': is_cached_accessor,
- 'is_call_with_execution_context':
- has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'),
- 'is_call_with_script_state':
- has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'),
- 'is_ce_reactions': is_ce_reactions,
- 'is_check_security_for_receiver': is_check_security_for_receiver,
- 'is_check_security_for_return_value':
- is_check_security_for_return_value,
- # TODO(yukishiino): Make all DOM attributes accessor-type properties.
- 'is_data_type_property': is_data_type_property(interface, attribute),
- 'is_getter_raises_exception': # [RaisesException]
- 'RaisesException' in extended_attributes and
- extended_attributes['RaisesException'] in (None, 'Getter'),
- 'is_keep_alive_for_gc': keep_alive_for_gc,
- 'is_lazy_data_attribute': is_lazy_data_attribute,
- 'is_lenient_setter': is_lenient_setter,
- 'is_lenient_this': 'LegacyLenientThis' in extended_attributes,
- 'is_nullable': idl_type.is_nullable,
- 'is_explicit_nullable': idl_type.is_explicit_nullable,
- 'is_named_constructor': is_named_constructor_attribute(attribute),
- 'is_partial_interface_member':
- 'PartialInterfaceImplementedAs' in extended_attributes,
- 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
- 'is_put_forwards': 'PutForwards' in extended_attributes,
- 'is_read_only': attribute.is_read_only,
- 'is_reflect': is_reflect,
- 'is_replaceable': 'Replaceable' in attribute.extended_attributes,
- 'is_save_same_object': is_save_same_object,
- 'is_static': attribute.is_static,
- 'is_url': 'URL' in extended_attributes,
- 'is_unforgeable': is_unforgeable(attribute),
- 'measure_as': measure_as,
- 'name': attribute.name,
- 'on_instance': v8_utilities.on_instance(interface, attribute),
- 'on_interface': v8_utilities.on_interface(interface, attribute),
- 'on_prototype': v8_utilities.on_prototype(interface, attribute),
- # [RuntimeEnabled] for origin trial
- 'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(attribute, runtime_features),
- 'private_property_is_shared_between_getter_and_setter':
- private_property_is_shared_between_getter_and_setter,
- 'property_attributes': property_attributes(interface, attribute),
- 'reflect_empty': cpp_content_attribute_value_name(
- interface, extended_attributes.get('ReflectEmpty')),
- 'reflect_invalid': cpp_content_attribute_value_name(
- interface, extended_attributes.get('ReflectInvalid', '')),
- 'reflect_missing': cpp_content_attribute_value_name(
- interface, extended_attributes.get('ReflectMissing')),
- 'reflect_only': reflect_only,
- # [RuntimeEnabled] if not in origin trial
- 'runtime_enabled_feature_name':
- v8_utilities.runtime_enabled_feature_name(attribute, runtime_features),
- # [CrossOriginIsolated]
- 'cross_origin_isolated_test':
- v8_utilities.cross_origin_isolated(attribute, interface),
- # [DirectSocketEnabled]
- 'direct_socket_enabled_test':
- v8_utilities.direct_socket_enabled(attribute, interface),
- # [SecureContext]
- 'secure_context_test': v8_utilities.secure_context(attribute, interface),
- 'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
- 'world_suffixes': (
- ['', 'ForMainWorld']
- if 'PerWorldBindings' in extended_attributes
- else ['']), # [PerWorldBindings]
- }
-
- if not has_custom_getter(attribute):
- getter_context(interface, attribute, context)
- if not has_custom_setter(attribute) and has_setter(interface, attribute):
- setter_context(interface, attribute, interfaces, context)
-
- # [RuntimeCallStatsCounter]
- runtime_call_stats_context(interface, attribute, context)
-
- # [CrossOrigin] is incompatible with a number of other attributes, so check
- # for them here.
- if is_cross_origin:
- if context['has_cross_origin_setter'] and context['has_custom_setter']:
- raise Exception(
- '[CrossOrigin] and [Custom] are incompatible on the same setter: %s.%s',
- interface.name, attribute.name)
- if context['is_per_world_bindings']:
- raise Exception(
- '[CrossOrigin] and [PerWorldBindings] are incompatible: %s.%s',
- interface.name, attribute.name)
- if context['constructor_type']:
- raise Exception(
- '[CrossOrigin] cannot be used for constructors: %s.%s',
- interface.name, attribute.name)
-
- return context
-
-
-def runtime_call_stats_context(interface, attribute, context):
- includes.add('platform/bindings/runtime_call_stats.h')
- generic_counter_name = (
- 'Blink_' + v8_utilities.cpp_name(interface) + '_' + attribute.name)
- (counter, extended_attribute_defined) = v8_utilities.rcs_counter_name(
- attribute, generic_counter_name)
- runtime_call_stats = {
- 'extended_attribute_defined':
- extended_attribute_defined,
- 'getter_counter':
- '%s_Getter' % counter,
- 'setter_counter':
- '%s_Setter' % counter,
- 'constructor_getter_callback_counter':
- '%s_ConstructorGetterCallback' % generic_counter_name,
- }
- context.update({'runtime_call_stats': runtime_call_stats})
-
-
-def is_origin_trial_enabled(attribute):
- return bool(attribute['origin_trial_feature_name'])
-
-
-def is_cross_origin_isolated(attribute):
- return bool(attribute['cross_origin_isolated_test'])
-
-
-def is_direct_socket_enabled(attribute):
- return bool(attribute['direct_socket_enabled_test'])
-
-
-def is_secure_context(attribute):
- return bool(attribute['secure_context_test'])
-
-
-def filter_accessors(attributes):
- return [
- attribute for attribute in attributes if not (
- attribute['exposed_test'] or is_secure_context(attribute)
- or is_cross_origin_isolated(attribute) or is_direct_socket_enabled(
- attribute) or attribute['context_enabled_feature_name']
- or is_origin_trial_enabled(attribute)
- or attribute['runtime_enabled_feature_name'])
- and not attribute['is_data_type_property']
- ]
-
-
-def is_data_attribute(attribute):
- return (not (attribute['exposed_test'] or is_secure_context(attribute)
- or is_cross_origin_isolated(attribute)
- or is_direct_socket_enabled(attribute)
- or attribute['context_enabled_feature_name']
- or is_origin_trial_enabled(attribute)
- or attribute['runtime_enabled_feature_name'])
- and attribute['is_data_type_property'])
-
-
-def filter_data_attributes(attributes):
- return [
- attribute for attribute in attributes if is_data_attribute(attribute)
- ]
-
-
-def filter_runtime_enabled(attributes):
- return [
- attribute for attribute in attributes
- if not (attribute['exposed_test'] or is_secure_context(attribute)
- or is_cross_origin_isolated(attribute)
- or is_direct_socket_enabled(attribute))
- and attribute['runtime_enabled_feature_name']
- ]
-
-
-def filter_conditionally_enabled(attributes):
- return [
- attribute for attribute in attributes if attribute['exposed_test'] or (
- (is_secure_context(attribute) or is_cross_origin_isolated(
- attribute) or is_direct_socket_enabled(attribute))
- and not is_origin_trial_enabled(attribute))
- ]
-
-
-################################################################################
-# Getter
-################################################################################
-
-
-def getter_context(interface, attribute, context):
- idl_type = attribute.idl_type
- base_idl_type = idl_type.base_type
- extended_attributes = attribute.extended_attributes
-
- cpp_value = getter_expression(interface, attribute, context)
- # Normally we can inline the function call into the return statement to
- # avoid the overhead of using a Ref<> temporary, but for some cases
- # (nullable types, EventHandler, [CachedAttribute], or if there are
- # exceptions), we need to use a local variable.
- # FIXME: check if compilers are smart enough to inline this, and if so,
- # always use a local variable (for readability and CG simplicity).
- if (idl_type.is_explicit_nullable or base_idl_type == 'EventHandler'
- or 'CachedAttribute' in extended_attributes
- or 'ReflectOnly' in extended_attributes
- or context['is_keep_alive_for_gc']
- or context['is_getter_raises_exception']
- or context['high_entropy'] == 'Direct'):
- context['cpp_value_original'] = cpp_value
- cpp_value = 'cpp_value'
-
- def v8_set_return_value_statement(for_main_world=False):
- if (context['is_keep_alive_for_gc']
- or 'CachedAttribute' in extended_attributes):
- return 'V8SetReturnValue(info, v8_value)'
- if idl_type.is_explicit_nullable:
- cpp_return_value = 'cpp_value.value()'
- if idl_type.is_frozen_array:
- cpp_return_value = 'FreezeV8Object(ToV8(cpp_value.value(), info.Holder(), info.GetIsolate()), info.GetIsolate())'
- return 'V8SetReturnValue(info, {})'.format(cpp_return_value)
- return idl_type.v8_set_return_value(
- cpp_value,
- extended_attributes=extended_attributes,
- script_wrappable='impl',
- for_main_world=for_main_world,
- is_static=attribute.is_static)
-
- cpp_value_to_script_wrappable = cpp_value
- if idl_type.is_array_buffer_view_or_typed_array:
- cpp_value_to_script_wrappable += '.View()'
-
- context.update({
- 'cpp_value':
- cpp_value,
- 'cpp_value_to_script_wrappable':
- cpp_value_to_script_wrappable,
- 'cpp_value_to_v8_value':
- idl_type.cpp_value_to_v8_value(
- cpp_value=cpp_value,
- creation_context='holder',
- extended_attributes=extended_attributes),
- 'is_getter_call_with_script_state':
- has_extended_attribute_value(attribute, 'GetterCallWith',
- 'ScriptState'),
- 'v8_set_return_value_for_main_world':
- v8_set_return_value_statement(for_main_world=True),
- 'v8_set_return_value':
- v8_set_return_value_statement(),
- })
-
-
-def getter_expression(interface, attribute, context):
- extra_arguments = []
- this_getter_base_name = getter_base_name(interface, attribute,
- extra_arguments)
- getter_name = scoped_name(interface, attribute, this_getter_base_name)
-
- arguments = v8_utilities.call_with_arguments(
- attribute.extended_attributes.get('GetterCallWith')
- or attribute.extended_attributes.get('CallWith'))
- # Members of IDL partial interface definitions are implemented in C++ as
- # static member functions, which for instance members (non-static members)
- # take *impl as their first argument
- if ('PartialInterfaceImplementedAs' in attribute.extended_attributes
- and not attribute.is_static):
- arguments.append('*impl')
- arguments.extend(extra_arguments)
- if context['is_getter_raises_exception']:
- arguments.append('exception_state')
- if attribute.idl_type.use_output_parameter_for_result:
- arguments.append('result')
-
- expression = '%s(%s)' % (getter_name, ', '.join(arguments))
- # Needed to handle getter expressions returning Type& as the
- # use site for |expression| expects Type*.
- if (attribute.idl_type.is_interface_type and len(arguments) == 0
- and not attribute.idl_type.is_array_buffer_view_or_typed_array):
- return 'WTF::GetPtr(%s)' % expression
- return expression
-
-
-CONTENT_ATTRIBUTE_GETTER_NAMES = {
- 'boolean': 'FastHasAttribute',
- 'long': 'GetIntegralAttribute',
- 'unsigned long': 'GetUnsignedIntegralAttribute',
- 'Element': 'GetElementAttribute',
-}
-
-
-def getter_base_name(interface, attribute, arguments):
- extended_attributes = attribute.extended_attributes
-
- if 'Reflect' not in extended_attributes:
- name = cpp_name(attribute)
- return name if 'ImplementedAs' in extended_attributes \
- else uncapitalize(name)
-
- content_attribute_name = (extended_attributes['Reflect']
- or attribute.name.lower())
- if content_attribute_name in ['class', 'id', 'name']:
- # Special-case for performance optimization.
- return 'Get%sAttribute' % content_attribute_name.capitalize()
-
- arguments.append(scoped_content_attribute_name(interface, attribute))
-
- base_idl_type = attribute.idl_type.base_type
- if base_idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES:
- return CONTENT_ATTRIBUTE_GETTER_NAMES[base_idl_type]
- if 'URL' in attribute.extended_attributes:
- return 'GetURLAttribute'
- idl_type = attribute.idl_type
- if idl_type.is_frozen_array:
- return 'Get%sArrayAttribute' % idl_type.element_type
- return 'FastGetAttribute'
-
-
-def is_keep_alive_for_gc(interface, attribute):
- idl_type = attribute.idl_type
- base_idl_type = idl_type.base_type
- extended_attributes = attribute.extended_attributes
- if attribute.is_static:
- return False
- if idl_type.is_array_buffer_or_view:
- return False
- return (
- # For readonly attributes, for performance reasons we keep the attribute
- # wrapper alive while the owner wrapper is alive, because the attribute
- # never changes.
- (
- attribute.is_read_only and idl_type.is_wrapper_type and
- # There are some exceptions, however:
- not (
- # Node lifetime is managed by object grouping.
- inherits_interface(interface.name, 'Node')
- or inherits_interface(base_idl_type, 'Node') or
- # A self-reference is unnecessary.
- attribute.name == 'self' or
- # FIXME: Remove these hard-coded hacks.
- base_idl_type in ['EventTarget', 'Window']
- or base_idl_type.startswith(('HTML', 'SVG')))))
-
-
-################################################################################
-# Setter
-################################################################################
-
-
-def setter_context(interface, attribute, interfaces, context):
- if 'PutForwards' in attribute.extended_attributes:
- # Make sure the target interface and attribute exist.
- target_interface_name = attribute.idl_type.base_type
- target_attribute_name = attribute.extended_attributes['PutForwards']
- interface = interfaces[target_interface_name]
- try:
- next(candidate for candidate in interface.attributes
- if candidate.name == target_attribute_name)
- except StopIteration:
- raise Exception('[PutForward] target not found:\n'
- 'Attribute "%s" is not present in interface "%s"' %
- (target_attribute_name, target_interface_name))
- context['target_attribute_name'] = target_attribute_name
- return
-
- if ('Replaceable' in attribute.extended_attributes):
- # Create the property, and early-return if an exception is thrown.
- # Subsequent cleanup code may not be prepared to handle a pending
- # exception.
- context['cpp_setter'] = (
- 'if (info.Holder()->CreateDataProperty(' +
- 'info.GetIsolate()->GetCurrentContext(), ' +
- 'property_name, v8_value).IsNothing())' + '\n return')
- return
-
- extended_attributes = attribute.extended_attributes
- idl_type = attribute.idl_type
-
- # [RaisesException], [RaisesException=Setter]
- is_setter_raises_exception = (
- 'RaisesException' in extended_attributes
- and extended_attributes['RaisesException'] in [None, 'Setter'])
-
- has_type_checking_interface = idl_type.is_wrapper_type
-
- use_common_reflection_setter = False
- # Enable use_common_reflection_setter if
- # * extended_attributes is [CEReactions, Reflect] or
- # [CEReactions, Reflect, RuntimeEnabled],
- # * the type is boolean, DOMString, or DOMString?, and
- # * the interface inherits from 'Element'.
- if ('Reflect' in extended_attributes
- and 'CEReactions' in extended_attributes
- and str(idl_type) in ('boolean', 'DOMString', 'DOMString?')
- and inherits_interface(interface.name, 'Element')):
- if (len(extended_attributes) == 2
- or (len(extended_attributes) == 3
- and 'RuntimeEnabled' in extended_attributes)):
- use_common_reflection_setter = True
-
- context.update({
- 'has_setter_exception_state':
- is_setter_raises_exception or has_type_checking_interface
- or idl_type.v8_conversion_needs_exception_state,
- 'has_type_checking_interface':
- has_type_checking_interface,
- 'is_setter_call_with_execution_context':
- has_extended_attribute_value(attribute, 'SetterCallWith',
- 'ExecutionContext'),
- 'is_setter_call_with_script_state':
- has_extended_attribute_value(attribute, 'SetterCallWith',
- 'ScriptState'),
- 'is_setter_raises_exception':
- is_setter_raises_exception,
- 'use_common_reflection_setter':
- use_common_reflection_setter,
- 'v8_value_to_local_cpp_value':
- idl_type.v8_value_to_local_cpp_value(
- extended_attributes,
- 'v8_value',
- 'cpp_value',
- code_generation_target='attribute_set'),
- })
-
- # setter_expression() depends on context values we set above.
- context['cpp_setter'] = setter_expression(interface, attribute, context)
-
-
-def setter_expression(interface, attribute, context):
- extended_attributes = attribute.extended_attributes
- arguments = v8_utilities.call_with_arguments(
- extended_attributes.get('SetterCallWith')
- or extended_attributes.get('CallWith'))
-
- extra_arguments = []
- this_setter_base_name = setter_base_name(interface, attribute,
- extra_arguments)
- setter_name = scoped_name(interface, attribute, this_setter_base_name)
-
- # Members of IDL partial interface definitions are implemented in C++ as
- # static member functions, which for instance members (non-static members)
- # take *impl as their first argument
- if ('PartialInterfaceImplementedAs' in extended_attributes
- and not attribute.is_static):
- arguments.append('*impl')
- arguments.extend(extra_arguments)
- idl_type = attribute.idl_type
- if idl_type.base_type in ('EventHandler', 'OnBeforeUnloadEventHandler',
- 'OnErrorEventHandler'):
- if idl_type.base_type == 'EventHandler':
- handler_type = 'kEventHandler'
- elif idl_type.base_type == 'OnBeforeUnloadEventHandler':
- handler_type = 'kOnBeforeUnloadEventHandler'
- elif idl_type.base_type == 'OnErrorEventHandler':
- handler_type = 'kOnErrorEventHandler'
- arguments.append('JSEventHandler::CreateOrNull(' + 'v8_value, ' +
- 'JSEventHandler::HandlerType::' + handler_type + ')')
- else:
- arguments.append('cpp_value')
- if context['is_setter_raises_exception']:
- arguments.append('exception_state')
- if context['use_common_reflection_setter']:
- attr_name = scoped_content_attribute_name(interface, attribute)
- if idl_type.base_type == 'boolean':
- setter_name = 'V8SetReflectedBooleanAttribute'
- arguments = [
- 'info',
- '"%s"' % interface.name,
- '"%s"' % attribute.name, attr_name
- ]
- elif idl_type.base_type == 'DOMString':
- if idl_type.is_nullable:
- setter_name = 'V8SetReflectedNullableDOMStringAttribute'
- else:
- setter_name = 'V8SetReflectedDOMStringAttribute'
- arguments = ['info', attr_name]
-
- return '%s(%s)' % (setter_name, ', '.join(arguments))
-
-
-CONTENT_ATTRIBUTE_SETTER_NAMES = {
- 'boolean': 'SetBooleanAttribute',
- 'long': 'SetIntegralAttribute',
- 'unsigned long': 'SetUnsignedIntegralAttribute',
- 'Element': 'SetElementAttribute',
-}
-
-
-def setter_base_name(interface, attribute, arguments):
- if 'Reflect' not in attribute.extended_attributes:
- return 'set%s' % capitalize(cpp_name(attribute))
- arguments.append(scoped_content_attribute_name(interface, attribute))
-
- base_idl_type = attribute.idl_type.base_type
- if base_idl_type in CONTENT_ATTRIBUTE_SETTER_NAMES:
- return CONTENT_ATTRIBUTE_SETTER_NAMES[base_idl_type]
- idl_type = attribute.idl_type
- if idl_type.is_frozen_array:
- return 'Set%sArrayAttribute' % idl_type.element_type
- return 'setAttribute'
-
-
-def scoped_content_attribute_name(interface, attribute):
- content_attribute_name = (attribute.extended_attributes['Reflect']
- or attribute.name.lower())
- symbol_name = 'k' + NameStyleConverter(
- content_attribute_name).to_upper_camel_case()
- if interface.name.startswith('SVG'):
- namespace = 'svg_names'
- includes.add('core/svg_names.h')
- else:
- namespace = 'html_names'
- includes.add('core/html_names.h')
- return '%s::%sAttr' % (namespace, symbol_name)
-
-
-def cpp_content_attribute_value_name(interface, value):
- if value == '':
- return 'g_empty_atom'
- if not value:
- return value
- includes.add('core/keywords.h')
- return 'keywords::' + NameStyleConverter(value).to_enum_value()
-
-
-################################################################################
-# Attribute configuration
-################################################################################
-
-
-# Property descriptor's {writable: boolean}
-def is_writable(attribute):
- return (not attribute.is_read_only or any(
- keyword in attribute.extended_attributes
- for keyword in ['PutForwards', 'Replaceable', 'LegacyLenientSetter']))
-
-
-def is_data_type_property(interface, attribute):
- return (is_constructor_attribute(attribute)
- or 'CrossOrigin' in attribute.extended_attributes)
-
-
-# [PutForwards], [Replaceable], [LegacyLenientSetter]
-def has_setter(interface, attribute):
- if (is_data_type_property(interface, attribute)
- and (is_constructor_attribute(attribute)
- or 'Replaceable' in attribute.extended_attributes)):
- return False
-
- return is_writable(attribute)
-
-
-# [NotEnumerable], [LegacyUnforgeable]
-def property_attributes(interface, attribute):
- extended_attributes = attribute.extended_attributes
- property_attributes_list = []
- if ('NotEnumerable' in extended_attributes
- or is_constructor_attribute(attribute)):
- property_attributes_list.append('v8::DontEnum')
- if is_unforgeable(attribute):
- property_attributes_list.append('v8::DontDelete')
- if not is_writable(attribute):
- property_attributes_list.append('v8::ReadOnly')
- return property_attributes_list or ['v8::None']
-
-
-# [Custom], [Custom=Getter]
-def has_custom_getter(attribute):
- extended_attributes = attribute.extended_attributes
- return ('Custom' in extended_attributes
- and extended_attributes['Custom'] in [None, 'Getter'])
-
-
-# [Custom], [Custom=Setter]
-def has_custom_setter(attribute):
- extended_attributes = attribute.extended_attributes
- return (not attribute.is_read_only and 'Custom' in extended_attributes
- and extended_attributes['Custom'] in [None, 'Setter'])
-
-
-################################################################################
-# Constructors
-################################################################################
-
-idl_types.IdlType.constructor_type_name = property(
- lambda self: strip_suffix(self.base_type, 'Constructor'))
-
-
-def is_constructor_attribute(attribute):
- return attribute.idl_type.name.endswith('Constructor')
-
-
-def is_named_constructor_attribute(attribute):
- return attribute.idl_type.name.endswith('ConstructorConstructor')
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
deleted file mode 100644
index 65679db65d1..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
+++ /dev/null
@@ -1,125 +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.
-"""Generate template values for a callback function.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-from v8_globals import includes
-import v8_types
-
-CALLBACK_FUNCTION_H_INCLUDES = frozenset([
- 'platform/bindings/callback_function_base.h',
- 'platform/bindings/v8_value_or_script_wrappable_adapter.h',
- 'platform/wtf/forward.h',
-])
-CALLBACK_FUNCTION_CPP_INCLUDES = frozenset([
- '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',
- 'platform/bindings/script_forbidden_scope.h',
-])
-
-
-def callback_function_context(callback_function):
- includes.clear()
- includes.update(CALLBACK_FUNCTION_CPP_INCLUDES)
- idl_type = callback_function.idl_type
- idl_type_str = str(idl_type)
-
- for argument in callback_function.arguments:
- argument.idl_type.add_includes_for_type(
- callback_function.extended_attributes)
-
- context = {
- # While both |callback_function_name| and |cpp_class| are identical at
- # the moment, the two are being defined because their values may change
- # in the future (e.g. if we support [ImplementedAs=] in callback
- # functions).
- 'callback_function_name':
- callback_function.name,
- 'cpp_class':
- 'V8%s' % callback_function.name,
- 'cpp_includes':
- sorted(includes),
- 'forward_declarations':
- sorted(forward_declarations(callback_function)),
- 'header_includes':
- sorted(CALLBACK_FUNCTION_H_INCLUDES),
- 'idl_type':
- idl_type_str,
- 'is_treat_non_object_as_null':
- 'LegacyTreatNonObjectAsNull' in callback_function.extended_attributes,
- 'native_value_traits_tag':
- v8_types.idl_type_to_native_value_traits_tag(idl_type),
- 'return_cpp_type':
- idl_type.cpp_type,
- }
-
- context.update(arguments_context(callback_function.arguments))
- return context
-
-
-def forward_declarations(callback_function):
- def find_forward_declaration(idl_type):
- if idl_type.is_interface_type or idl_type.is_dictionary:
- return idl_type.implemented_as
- elif idl_type.is_array_or_sequence_type:
- return find_forward_declaration(idl_type.element_type)
- return None
-
- declarations = set()
- for argument in callback_function.arguments:
- name = find_forward_declaration(argument.idl_type)
- if name:
- declarations.add(name)
- return declarations
-
-
-def arguments_context(arguments):
- def argument_context(argument):
- idl_type = argument.idl_type
- return {
- 'cpp_value_to_v8_value':
- idl_type.cpp_value_to_v8_value(
- argument.name,
- isolate='GetIsolate()',
- creation_context='argument_creation_context'),
- 'enum_type':
- idl_type.enum_type,
- 'enum_values':
- idl_type.enum_values,
- 'is_variadic':
- argument.is_variadic,
- 'name':
- argument.name,
- 'v8_name':
- 'v8_%s' % argument.name,
- }
-
- def argument_cpp_type(argument):
- if argument.idl_type.is_dictionary:
- return 'const %s*' % argument.idl_type.implemented_as
-
- return argument.idl_type.cpp_type_args(
- extended_attributes=argument.extended_attributes,
- raw_type=False,
- used_as_rvalue_type=True,
- used_as_variadic_argument=argument.is_variadic)
-
- argument_declarations = [
- 'bindings::V8ValueOrScriptWrappableAdapter callback_this_value'
- ]
- argument_declarations.extend(
- '%s %s' % (argument_cpp_type(argument), argument.name)
- for argument in arguments)
- return {
- 'argument_declarations': argument_declarations,
- 'arguments': [argument_context(argument) for argument in arguments],
- }
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
deleted file mode 100644
index 33232bdbbb4..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
+++ /dev/null
@@ -1,190 +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.
-"""Generate template values for a callback interface.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-from idl_types import IdlTypeBase
-from v8_globals import includes
-from v8_interface import constant_context
-import v8_types
-import v8_utilities
-
-CALLBACK_INTERFACE_H_INCLUDES = frozenset([
- 'platform/bindings/callback_interface_base.h',
- 'platform/bindings/v8_value_or_script_wrappable_adapter.h',
-])
-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',
- 'platform/bindings/script_forbidden_scope.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',
-])
-
-
-def callback_interface_context(callback_interface, _, component_info):
- is_legacy_callback_interface = len(callback_interface.constants) > 0
-
- includes.clear()
- includes.update(CALLBACK_INTERFACE_CPP_INCLUDES)
- if is_legacy_callback_interface:
- includes.update(LEGACY_CALLBACK_INTERFACE_CPP_INCLUDES)
-
- header_includes = set(CALLBACK_INTERFACE_H_INCLUDES)
- if is_legacy_callback_interface:
- header_includes.update(LEGACY_CALLBACK_INTERFACE_H_INCLUDES)
-
- # https://heycam.github.io/webidl/#dfn-single-operation-callback-interface
- is_single_operation = True
- if (callback_interface.parent or len(callback_interface.attributes) > 0
- or len(callback_interface.operations) == 0):
- is_single_operation = False
- else:
- operations = callback_interface.operations
- basis = operations[0]
- for op in operations[1:]:
- if op.name != basis.name:
- is_single_operation = False
- break
-
- return {
- 'constants': [
- constant_context(constant, callback_interface, component_info)
- for constant in callback_interface.constants
- ],
- 'cpp_class':
- callback_interface.name,
- 'do_not_check_constants':
- 'DoNotCheckConstants' in callback_interface.extended_attributes,
- 'forward_declarations':
- sorted(forward_declarations(callback_interface)),
- 'header_includes':
- header_includes,
- 'interface_name':
- callback_interface.name,
- 'is_legacy_callback_interface':
- is_legacy_callback_interface,
- 'is_single_operation_callback_interface':
- is_single_operation,
- 'methods': [
- method_context(operation)
- for operation in callback_interface.operations
- ],
- 'v8_class':
- v8_utilities.v8_class_name(callback_interface),
- }
-
-
-def forward_declarations(callback_interface):
- def find_forward_declaration(idl_type):
- if idl_type.is_interface_type or idl_type.is_dictionary:
- return idl_type.implemented_as
- elif idl_type.is_array_or_sequence_type:
- return find_forward_declaration(idl_type.element_type)
- elif idl_type.is_nullable:
- return find_forward_declaration(idl_type.inner_type)
- return None
-
- declarations = set()
- for operation in callback_interface.operations:
- for argument in operation.arguments:
- name = find_forward_declaration(argument.idl_type)
- if name:
- declarations.add(name)
- return declarations
-
-
-def add_includes_for_operation(operation):
- operation.idl_type.add_includes_for_type()
- for argument in operation.arguments:
- argument.idl_type.add_includes_for_type()
-
-
-def method_context(operation):
- extended_attributes = operation.extended_attributes
- idl_type = operation.idl_type
- idl_type_str = str(idl_type)
-
- add_includes_for_operation(operation)
- context = {
- 'cpp_type':
- idl_type.cpp_type,
- 'idl_type':
- idl_type_str,
- 'name':
- operation.name,
- 'native_value_traits_tag':
- v8_types.idl_type_to_native_value_traits_tag(idl_type),
- }
- context.update(arguments_context(operation.arguments))
- return context
-
-
-def arguments_context(arguments):
- def argument_context(argument):
- return {
- 'cpp_value_to_v8_value':
- argument.idl_type.cpp_value_to_v8_value(
- argument.name,
- isolate='GetIsolate()',
- creation_context='argument_creation_context'),
- 'name':
- argument.name,
- 'v8_name':
- 'v8_' + argument.name,
- }
-
- def argument_cpp_type(argument):
- if argument.idl_type.is_dictionary:
- return 'const %s*' % argument.idl_type.implemented_as
-
- return argument.idl_type.cpp_type_args(
- extended_attributes=argument.extended_attributes,
- raw_type=False,
- used_as_rvalue_type=True,
- used_as_variadic_argument=argument.is_variadic)
-
- argument_declarations = [
- 'bindings::V8ValueOrScriptWrappableAdapter callback_this_value'
- ]
- argument_declarations.extend(
- '%s %s' % (argument_cpp_type(argument), argument.name)
- for argument in arguments)
- return {
- 'argument_declarations': argument_declarations,
- 'arguments': [argument_context(argument) for argument in arguments],
- }
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
deleted file mode 100644
index 81b0e6b99d8..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
+++ /dev/null
@@ -1,379 +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.
-"""Generate template contexts of dictionaries for both v8 bindings and
-implementation classes that are used by blink's core/modules.
-"""
-
-from blinkbuild.name_style_converter import NameStyleConverter
-from idl_types import IdlType
-from utilities import to_snake_case
-from v8_globals import includes
-from v8_utilities import has_extended_attribute_value
-import operator
-import v8_types
-import v8_utilities
-
-DICTIONARY_H_INCLUDES = frozenset([
- 'base/containers/span.h',
- 'bindings/core/v8/native_value_traits.h',
- 'bindings/core/v8/to_v8_for_core.h',
- 'bindings/core/v8/v8_binding_for_core.h',
- 'platform/heap/handle.h',
-])
-
-DICTIONARY_CPP_INCLUDES = frozenset([
- 'base/stl_util.h',
- 'platform/bindings/exception_state.h',
-])
-
-
-def getter_name_for_dictionary_member(member):
- name = v8_utilities.cpp_name(member)
- return NameStyleConverter(name).to_lower_camel_case()
-
-
-def non_null_getter_name_for_dictionary_member(member):
- name = v8_utilities.cpp_name(member)
- return NameStyleConverter('{}_non_null'.format(name)).to_lower_camel_case()
-
-
-def setter_name_for_dictionary_member(member):
- name = 'set_{}'.format(v8_utilities.cpp_name(member))
- return NameStyleConverter(name).to_lower_camel_case()
-
-
-def null_setter_name_for_dictionary_member(member):
- if member.idl_type.is_nullable:
- name = 'set_{}_to_null'.format(v8_utilities.cpp_name(member))
- return NameStyleConverter(name).to_lower_camel_case()
- return None
-
-
-def has_method_name_for_dictionary_member(member):
- name = NameStyleConverter('has_' + v8_utilities.cpp_name(member))
- return name.to_lower_camel_case()
-
-
-def non_null_has_method_name_for_dictionary_member(member, for_non_null=False):
- name = 'has_{}_non_null'.format(v8_utilities.cpp_name(member))
- return NameStyleConverter(name).to_lower_camel_case()
-
-
-def unwrap_nullable_if_needed(idl_type):
- if idl_type.is_nullable:
- return idl_type.inner_type
- return idl_type
-
-
-# Context for V8 bindings
-
-
-def dictionary_context(dictionary, interfaces_info, component_info):
- includes.clear()
- includes.update(DICTIONARY_CPP_INCLUDES)
-
- if 'RuntimeEnabled' in dictionary.extended_attributes:
- raise Exception(
- 'Dictionary cannot be RuntimeEnabled: %s' % dictionary.name)
-
- members = [
- member_context(dictionary, member, component_info)
- for member in sorted(
- dictionary.members, key=operator.attrgetter('name'))
- ]
-
- for member in members:
- if member['runtime_enabled_feature_name']:
- includes.add('platform/runtime_enabled_features.h')
- break
-
- has_origin_trial_members = False
- for member in members:
- if member['origin_trial_feature_name']:
- has_origin_trial_members = True
- includes.add('core/origin_trials/origin_trials.h')
- includes.add('core/execution_context/execution_context.h')
- break
-
- cpp_class = v8_utilities.cpp_name(dictionary)
- context = {
- 'cpp_class':
- cpp_class,
- 'has_origin_trial_members':
- has_origin_trial_members,
- 'header_includes':
- set(DICTIONARY_H_INCLUDES),
- 'members':
- members,
- 'required_member_names':
- sorted([
- member.name for member in dictionary.members if member.is_required
- ]),
- 'use_permissive_dictionary_conversion':
- 'PermissiveDictionaryConversion' in dictionary.extended_attributes,
- 'v8_class':
- v8_types.v8_type(cpp_class),
- }
- if dictionary.parent:
- IdlType(dictionary.parent).add_includes_for_type()
- parent_cpp_class = v8_utilities.cpp_name_from_interfaces_info(
- dictionary.parent, interfaces_info)
- context.update({
- 'parent_cpp_class': parent_cpp_class,
- 'parent_v8_class': v8_types.v8_type(parent_cpp_class),
- })
- return context
-
-
-def member_context(_, member, component_info):
- extended_attributes = member.extended_attributes
- idl_type = member.idl_type
- idl_type.add_includes_for_type(extended_attributes)
- unwrapped_idl_type = unwrap_nullable_if_needed(idl_type)
-
- if member.is_required and member.default_value:
- raise Exception(
- 'Required member %s must not have a default value.' % member.name)
-
- if idl_type.is_nullable and idl_type.inner_type.is_dictionary:
- raise Exception(
- 'The inner type of nullable member %s must not be a dictionary.' %
- 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
- if member.default_value.is_null:
- return None, 'v8::Null(isolate)'
-
- cpp_default_value = unwrapped_idl_type.literal_cpp_value(
- member.default_value)
- v8_default_value = unwrapped_idl_type.cpp_value_to_v8_value(
- cpp_value=cpp_default_value,
- isolate='isolate',
- creation_context='creationContext')
- return cpp_default_value, v8_default_value
-
- cpp_default_value, v8_default_value = default_values()
- snake_case_name = to_snake_case(member.name)
- cpp_value = snake_case_name + "_cpp_value"
- v8_value = snake_case_name + "_value"
- has_value_or_default = snake_case_name + "_has_value_or_default"
- getter_name = getter_name_for_dictionary_member(member)
- runtime_features = component_info['runtime_enabled_features']
-
- return {
- 'cpp_default_value':
- cpp_default_value,
- 'cpp_type':
- unwrapped_idl_type.cpp_type,
- 'cpp_value':
- cpp_value,
- 'cpp_value_to_v8_value':
- unwrapped_idl_type.cpp_value_to_v8_value(
- cpp_value='impl->%s()' % getter_name,
- isolate='isolate',
- creation_context='creationContext',
- extended_attributes=extended_attributes),
- 'deprecate_as':
- v8_utilities.deprecate_as(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_callback_function_type':
- idl_type.is_callback_function,
- 'is_interface_type':
- idl_type.is_interface_type,
- 'is_nullable':
- idl_type.is_nullable,
- 'is_object':
- unwrapped_idl_type.name == 'Object',
- 'is_string_type':
- idl_type.preprocessed_type.is_string_type,
- 'is_required':
- member.is_required,
- 'name':
- member.name,
- # [RuntimeEnabled] for origin trial
- 'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(member, runtime_features),
- # [RuntimeEnabled] if not in origin trial
- 'runtime_enabled_feature_name':
- v8_utilities.runtime_enabled_feature_name(member, runtime_features),
- 'setter_name':
- setter_name_for_dictionary_member(member),
- 'has_value_or_default':
- has_value_or_default,
- 'null_setter_name':
- null_setter_name_for_dictionary_member(member),
- 'v8_default_value':
- v8_default_value,
- 'v8_value':
- v8_value,
- 'v8_value_to_local_cpp_value':
- idl_type.v8_value_to_local_cpp_value(
- extended_attributes,
- v8_value,
- cpp_value,
- isolate='isolate',
- use_exception_state=True),
- }
-
-
-# Context for implementation classes
-
-
-def dictionary_impl_context(dictionary, interfaces_info):
- def remove_duplicate_members(members):
- # When [ImplementedAs] is used, cpp_name can conflict. For example,
- # dictionary D { long foo; [ImplementedAs=foo, DeprecateAs=Foo] long oldFoo; };
- # This function removes such duplications, checking they have the same type.
- members_dict = {}
- for member in members:
- cpp_name = member['cpp_name']
- duplicated_member = members_dict.get(cpp_name)
- if duplicated_member and duplicated_member != member:
- raise Exception('Member name conflict: %s' % cpp_name)
- members_dict[cpp_name] = member
- return sorted(
- members_dict.values(), key=lambda member: member['cpp_name'])
-
- includes.clear()
- header_forward_decls = set()
- header_includes = set(['platform/heap/handle.h'])
- members = [
- member_impl_context(member, interfaces_info, header_includes,
- header_forward_decls)
- for member in dictionary.members
- ]
- members = remove_duplicate_members(members)
- context = {
- 'header_forward_decls': header_forward_decls,
- 'header_includes': header_includes,
- 'cpp_class': v8_utilities.cpp_name(dictionary),
- 'members': members,
- }
- if dictionary.parent:
- context['parent_cpp_class'] = \
- v8_utilities.cpp_name_from_interfaces_info(dictionary.parent,
- interfaces_info)
- parent_interface_info = interfaces_info.get(dictionary.parent)
- if parent_interface_info:
- context['header_includes'].add(
- parent_interface_info['include_path'])
- else:
- context['parent_cpp_class'] = 'IDLDictionaryBase'
- context['header_includes'].add(
- 'bindings/core/v8/idl_dictionary_base.h')
- return context
-
-
-def member_impl_context(member, interfaces_info, header_includes,
- header_forward_decls):
- 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 or has_explicit_presence:
- nullable_indicator_name = 'has_' + cpp_name + '_'
-
- def has_method_expression():
- if nullable_indicator_name:
- return nullable_indicator_name
- if idl_type.is_union_type or idl_type.is_enum or idl_type.is_string_type:
- return '!%s_.IsNull()' % cpp_name
- if idl_type.name == 'Any':
- return '!({0}_.IsEmpty() || {0}_.IsUndefined())'.format(cpp_name)
- if idl_type.name == 'Object':
- return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(
- cpp_name)
- return '!!%s_' % cpp_name
-
- cpp_default_value = None
- 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:
- includes.update(idl_type.impl_includes_for_type(interfaces_info))
- header_forward_decls.add(forward_decl_name)
- else:
- header_includes.update(
- idl_type.impl_includes_for_type(interfaces_info))
-
- setter_value = 'value'
- non_null_type = idl_type.inner_type if idl_type.is_nullable else idl_type
- setter_inline = 'inline ' if (non_null_type.is_basic_type
- or non_null_type.is_enum
- or non_null_type.is_wrapper_type) else ''
-
- extended_attributes = member.extended_attributes
-
- 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(),
- 'has_method_name':
- has_method_name_for_dictionary_member(member),
- 'is_nullable':
- member.idl_type.is_nullable,
- 'is_traceable':
- idl_type.is_traceable,
- 'member_cpp_type':
- idl_type.cpp_type_args(used_in_cpp_sequence=True,
- extended_attributes=extended_attributes),
- 'non_null_getter_name':
- non_null_getter_name_for_dictionary_member(member),
- 'non_null_has_method_name':
- non_null_has_method_name_for_dictionary_member(member),
- 'null_setter_name':
- null_setter_name_for_dictionary_member(member),
- 'nullable_indicator_name':
- nullable_indicator_name,
- 'rvalue_cpp_type':
- idl_type.cpp_type_args(used_as_rvalue_type=True,
- extended_attributes=extended_attributes),
- 'setter_inline':
- setter_inline,
- 'setter_name':
- setter_name_for_dictionary_member(member),
- 'setter_value':
- setter_value,
- }
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py
deleted file mode 100644
index 49fb86151e3..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py
+++ /dev/null
@@ -1,30 +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.
-"""Module to share global variables (includes and interfaces) across modules."""
-
-includes = set()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
deleted file mode 100644
index 60a1adb309d..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
+++ /dev/null
@@ -1,1850 +0,0 @@
-# Copyright (C) 2013 Google Inc. All rights reserved.
-# coding=utf-8
-#
-# 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.
-
-# pylint: disable=relative-import
-"""Generate template values for an interface.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-import os
-import sys
-from operator import or_
-
-sys.path.append(
- os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
-from blinkbuild.name_style_converter import NameStyleConverter
-from idl_definitions import IdlAttribute, IdlOperation, IdlArgument
-from idl_types import IdlType, inherits_interface
-from overload_set_algorithm import effective_overload_set_by_length
-from overload_set_algorithm import method_overloads_by_name
-
-import v8_attributes
-from v8_globals import includes
-import v8_methods
-import v8_types
-import v8_utilities
-from v8_utilities import (
- binding_header_filename, context_enabled_feature_name, cpp_name_or_partial,
- cpp_name, has_extended_attribute_value, runtime_enabled_feature_name)
-
-INTERFACE_H_INCLUDES = frozenset([
- 'bindings/core/v8/generated_code_helper.h',
- 'bindings/core/v8/native_value_traits.h',
- 'platform/bindings/script_wrappable.h',
- 'bindings/core/v8/to_v8_for_core.h',
- 'bindings/core/v8/v8_binding_for_core.h',
- 'platform/bindings/v8_dom_wrapper.h',
- 'platform/bindings/wrapper_type_info.h',
- 'platform/heap/handle.h',
-])
-INTERFACE_CPP_INCLUDES = frozenset([
- 'base/memory/scoped_refptr.h',
- 'bindings/core/v8/native_value_traits_impl.h',
- 'bindings/core/v8/v8_dom_configuration.h',
- 'core/execution_context/execution_context.h',
- 'platform/scheduler/public/cooperative_scheduling_manager.h',
- 'platform/bindings/exception_messages.h',
- 'platform/bindings/exception_state.h',
- 'platform/bindings/v8_object_constructor.h',
- 'platform/wtf/get_ptr.h',
-])
-
-
-def filter_has_constant_configuration(constants):
- return [
- constant for constant in constants
- if not constant['measure_as'] and not constant['deprecate_as']
- and not constant['runtime_enabled_feature_name']
- and not constant['origin_trial_feature_name']
- ]
-
-
-def filter_has_special_getter(constants):
- return [
- constant for constant in constants
- if constant['measure_as'] or constant['deprecate_as']
- ]
-
-
-def filter_runtime_enabled(constants):
- return [
- constant for constant in constants
- if constant['runtime_enabled_feature_name']
- ]
-
-
-def filter_origin_trial_enabled(constants):
- return [
- constant for constant in constants
- if constant['origin_trial_feature_name']
- ]
-
-
-def constant_filters():
- return {
- 'has_constant_configuration': filter_has_constant_configuration,
- 'has_special_getter': filter_has_special_getter,
- 'runtime_enabled_constants': filter_runtime_enabled,
- 'origin_trial_enabled_constants': filter_origin_trial_enabled
- }
-
-
-def origin_trial_features(interface, constants, attributes, methods):
- """ Returns a list of the origin trial features used in this interface.
-
- Each element is a dictionary with keys 'name' and 'needs_instance'.
- 'needs_instance' is true if any member associated with the interface needs
- to be installed on every instance of the interface. This list is the union
- of the sets of features used for constants, attributes and methods.
- """
- KEY = 'origin_trial_feature_name' # pylint: disable=invalid-name
-
- def member_filter(members):
- return sorted([member for member in members if member.get(KEY)])
-
- def member_filter_by_name(members, name):
- return [member for member in members if member[KEY] == name]
-
- # Collect all members visible on this interface with a defined origin trial
- origin_trial_constants = member_filter(constants)
- origin_trial_attributes = member_filter(attributes)
- origin_trial_methods = member_filter([
- method for method in methods
- if v8_methods.method_is_visible(method, interface.is_partial)
- and not v8_methods.custom_registration(method)
- ])
-
- feature_names = set([
- member[KEY] for member in origin_trial_constants +
- origin_trial_attributes + origin_trial_methods
- ])
-
- # Construct the list of dictionaries. 'needs_instance' will be true if any
- # member for the feature has 'on_instance' defined as true.
- features = [{
- 'name':
- name,
- 'constants':
- member_filter_by_name(origin_trial_constants, name),
- 'attributes':
- member_filter_by_name(origin_trial_attributes, name),
- 'methods':
- member_filter_by_name(origin_trial_methods, name)
- } for name in feature_names]
- for feature in features:
- members = feature['constants'] + feature['attributes'] + feature[
- 'methods']
- feature['needs_instance'] = any(
- member.get('on_instance', False) for member in members)
- # TODO(chasej): Need to handle method overloads? e.g.
- # (method['overloads']['secure_context_test_all'] if 'overloads' in method else method['secure_context_test'])
- feature['needs_secure_context'] = any(
- member.get('secure_context_test', False) for member in members)
- feature['needs_cross_origin_isolated'] = any(
- member.get('cross_origin_isolated_test', False)
- for member in members)
- feature['needs_direct_socket_enabled'] = any(
- member.get('direct_socket_enabled_test', False)
- for member in members)
- feature['needs_context'] = feature['needs_secure_context'] or feature[
- 'needs_cross_origin_isolated'] or feature[
- 'needs_direct_socket_enabled'] or any(
- member.get('exposed_test', False) for member in members)
-
- if features:
- includes.add('platform/bindings/script_state.h')
- includes.add('platform/runtime_enabled_features.h')
- includes.add('core/execution_context/execution_context.h')
-
- return features
-
-
-def context_enabled_features(attributes):
- """ Returns a list of context-enabled features from a set of attributes.
-
- Each element is a dictionary with the feature's |name| and lists of
- |attributes| associated with the feature.
- """
- KEY = 'context_enabled_feature_name' # pylint: disable=invalid-name
-
- def member_filter(members):
- return sorted([
- member for member in members
- if member.get(KEY) and not member.get('exposed_test')
- ], key=lambda item: item['name'])
-
- def member_filter_by_name(members, name):
- return [member for member in members if member[KEY] == name]
-
- # Collect all members visible on this interface with a defined origin trial
- context_enabled_attributes = member_filter(attributes)
- feature_names = set([member[KEY] for member in context_enabled_attributes])
- features = [{
- 'name':
- name,
- 'attributes':
- member_filter_by_name(context_enabled_attributes, name),
- 'needs_instance':
- False
- } for name in feature_names]
- if features:
- includes.add('platform/bindings/script_state.h')
- return features
-
-
-def runtime_call_stats_context(interface):
- counter_prefix = 'Blink_' + v8_utilities.cpp_name(interface) + '_'
- return {
- 'constructor_counter':
- counter_prefix + 'Constructor',
- 'cross_origin_named_getter_counter':
- counter_prefix + 'CrossOriginNamedGetter',
- 'cross_origin_named_setter_counter':
- counter_prefix + 'CrossOriginNamedSetter',
- 'indexed_property_getter_counter':
- counter_prefix + 'IndexedPropertyGetter',
- 'named_property_getter_counter':
- counter_prefix + 'NamedPropertyGetter',
- 'named_property_query_counter':
- counter_prefix + 'NamedPropertyQuery',
- 'named_property_setter_counter':
- counter_prefix + 'NamedPropertySetter',
- }
-
-
-def interface_context(interface, interfaces, component_info):
- """Creates a Jinja template context for an interface.
-
- Args:
- interface: An interface to create the context for
- interfaces: A dict which maps an interface name to the definition
- which can be referred if needed
- component_info: A dict containing component wide information
-
- Returns:
- A Jinja template context for |interface|
- """
-
- includes.clear()
- includes.update(INTERFACE_CPP_INCLUDES)
- header_includes = set(INTERFACE_H_INCLUDES)
-
- if interface.is_partial:
- # A partial interface definition cannot specify that the interface
- # inherits from another interface. Inheritance must be specified on
- # the original interface definition.
- parent_interface = None
- is_event_target = False
- # partial interface needs the definition of its original interface.
- includes.add(
- 'bindings/core/v8/%s' % binding_header_filename(interface.name))
- else:
- parent_interface = interface.parent
- if parent_interface:
- header_includes.update(
- v8_types.includes_for_interface(parent_interface))
- is_event_target = inherits_interface(interface.name, 'EventTarget')
-
- extended_attributes = interface.extended_attributes
-
- is_array_buffer_or_view = interface.idl_type.is_array_buffer_or_view
- is_typed_array_type = interface.idl_type.is_typed_array
- if is_array_buffer_or_view:
- includes.update(('bindings/core/v8/v8_array_buffer.h',
- 'bindings/core/v8/v8_shared_array_buffer.h'))
- if interface.name == 'ArrayBufferView':
- includes.update(('bindings/core/v8/v8_int8_array.h',
- 'bindings/core/v8/v8_int16_array.h',
- 'bindings/core/v8/v8_int32_array.h',
- 'bindings/core/v8/v8_uint8_array.h',
- 'bindings/core/v8/v8_uint8_clamped_array.h',
- 'bindings/core/v8/v8_uint16_array.h',
- 'bindings/core/v8/v8_uint32_array.h',
- 'bindings/core/v8/v8_big_int_64_array.h',
- 'bindings/core/v8/v8_big_uint_64_array.h',
- 'bindings/core/v8/v8_float32_array.h',
- 'bindings/core/v8/v8_float64_array.h',
- 'bindings/core/v8/v8_data_view.h'))
-
- # [ActiveScriptWrappable]
- active_scriptwrappable = 'ActiveScriptWrappable' in extended_attributes
-
- # [CheckSecurity]
- is_check_security = 'CheckSecurity' in extended_attributes
- if is_check_security:
- includes.add('bindings/core/v8/binding_security.h')
- includes.add('core/frame/local_dom_window.h')
-
- # [Global]
- is_global = 'Global' in extended_attributes
-
- # [ImmutablePrototype]
- # TODO(littledan): Is it possible to deduce this based on inheritance,
- # as in the WebIDL spec?
- is_immutable_prototype = is_global or 'ImmutablePrototype' in extended_attributes
-
- # interface mixin
- assert not interface.is_mixin, (
- "Interface mixin {} must not be a direct target of bindings code generation."
- .format(interface.name))
-
- wrapper_class_id = ('kNodeClassId' if inherits_interface(
- interface.name, 'Node') else 'kObjectClassId')
-
- # [LegacyUnenumerableNamedProperties]
- # pylint: disable=C0103
- has_legacy_unenumerable_named_properties = (
- interface.has_named_property_getter
- and 'LegacyUnenumerableNamedProperties' in extended_attributes)
-
- v8_class_name = v8_utilities.v8_class_name(interface)
- cpp_class_name = cpp_name(interface)
- cpp_class_name_or_partial = cpp_name_or_partial(interface)
- v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface)
-
- # TODO(peria): Generate the target list from 'Window' and 'HTMLDocument'.
- needs_runtime_enabled_installer = v8_class_name in [
- 'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget'
- ]
-
- runtime_features = component_info['runtime_enabled_features']
-
- context = {
- 'active_scriptwrappable':
- active_scriptwrappable,
- 'context_enabled_feature_name':
- context_enabled_feature_name(interface), # [ContextEnabled]
- 'cpp_class':
- cpp_class_name,
- 'cpp_class_or_partial':
- cpp_class_name_or_partial,
- 'is_gc_type':
- True,
- # FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699
- 'has_access_check_callbacks': (is_check_security
- and interface.name != 'EventTarget'),
- # [Custom=LegacyCallAsFunction]
- 'has_custom_legacy_call_as_function':
- has_extended_attribute_value(interface, 'Custom',
- 'LegacyCallAsFunction'),
- 'has_legacy_unenumerable_named_properties':
- has_legacy_unenumerable_named_properties,
- 'has_partial_interface':
- len(interface.partial_interfaces) > 0,
- 'header_includes':
- header_includes,
- 'interface_name':
- interface.name,
- 'internal_namespace':
- internal_namespace(interface),
- 'is_array_buffer_or_view':
- is_array_buffer_or_view,
- 'is_check_security':
- is_check_security,
- 'is_event_target':
- is_event_target,
- 'is_global':
- is_global,
- 'is_immutable_prototype':
- is_immutable_prototype,
- 'is_node':
- inherits_interface(interface.name, 'Node'),
- 'is_partial':
- interface.is_partial,
- 'is_typed_array_type':
- is_typed_array_type,
- # [MeasureAs]
- 'measure_as':
- v8_utilities.measure_as(interface, None),
- 'needs_runtime_enabled_installer':
- needs_runtime_enabled_installer,
- 'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(interface, runtime_features),
- 'parent_interface':
- parent_interface,
- 'pass_cpp_type':
- cpp_name(interface) + '*',
- 'runtime_call_stats':
- runtime_call_stats_context(interface),
- # [RuntimeEnabled]
- 'runtime_enabled_feature_name':
- runtime_enabled_feature_name(interface, runtime_features),
- 'snake_case_v8_class':
- NameStyleConverter(v8_class_name).to_snake_case(),
- 'v8_class':
- v8_class_name,
- 'v8_class_or_partial':
- v8_class_name_or_partial,
- 'wrapper_class_id':
- wrapper_class_id,
- }
-
- # Constructors
- constructors = [
- constructor_context(interface, constructor)
- for constructor in interface.constructors
- # FIXME: shouldn't put named constructors with constructors
- # (currently needed for Perl compatibility)
- # Handle named constructors separately
- if constructor.name == 'Constructor'
- ]
- if len(constructors) > 1:
- context['constructor_overloads'] = overloads_context(
- interface, constructors)
-
- # [CustomConstructor]
- custom_constructors = [{ # Only needed for computing interface length
- 'number_of_required_arguments':
- number_of_required_arguments(constructor),
- } for constructor in interface.custom_constructors]
-
- # [HTMLConstructor]
- has_html_constructor = 'HTMLConstructor' in extended_attributes
- # https://html.spec.whatwg.org/C/#html-element-constructors
- if has_html_constructor:
- if ('Constructor' in extended_attributes
- or 'LegacyNoInterfaceObject' in extended_attributes):
- raise Exception(
- '[HTMLConstructor] cannot be specified with '
- '[Constructor] or [LegacyNoInterfaceObject], or on '
- 'a mixin : %s' % interface.name)
- includes.add('bindings/core/v8/v8_html_constructor.h')
-
- # [NamedConstructor]
- named_constructor = named_constructor_context(interface)
-
- if constructors or custom_constructors or named_constructor:
- if interface.is_partial:
- raise Exception('[Constructor] and [NamedConstructor] MUST NOT be'
- ' 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')
- includes.add('core/frame/local_dom_window.h')
- elif 'Measure' in extended_attributes or 'MeasureAs' in extended_attributes:
- if not interface.is_partial:
- raise Exception(
- '[Measure] or [MeasureAs] specified for interface without a constructor: '
- '%s' % interface.name)
-
- # [ConstructorCallWith=Document]
- if has_extended_attribute_value(interface, 'ConstructorCallWith',
- 'Document'):
- includes.add('core/dom/document.h')
-
- # [Unscopable] attributes and methods
- unscopables = []
- for attribute in interface.attributes:
- if 'Unscopable' in attribute.extended_attributes:
- unscopables.append((attribute.name,
- runtime_enabled_feature_name(
- attribute, runtime_features)))
- for method in interface.operations:
- if 'Unscopable' in method.extended_attributes:
- unscopables.append((method.name,
- runtime_enabled_feature_name(
- method, runtime_features)))
-
- # [CEReactions]
- setter_or_deleters = (
- interface.indexed_property_setter,
- interface.indexed_property_deleter,
- interface.named_property_setter,
- interface.named_property_deleter,
- )
- has_ce_reactions = any(
- setter_or_deleter
- and 'CEReactions' in setter_or_deleter.extended_attributes
- for setter_or_deleter in setter_or_deleters)
- if has_ce_reactions:
- includes.add('core/html/custom/ce_reactions_scope.h')
-
- context.update({
- 'constructors':
- constructors,
- 'has_custom_constructor':
- bool(custom_constructors),
- 'has_html_constructor':
- has_html_constructor,
- 'interface_length':
- interface_length(constructors + custom_constructors),
- # [RaisesException=Constructor]
- 'is_constructor_raises_exception':
- extended_attributes.get('RaisesException') == 'Constructor',
- 'named_constructor':
- named_constructor,
- 'unscopables':
- sorted(unscopables),
- })
-
- # Constants
- context.update({
- 'constants': [
- constant_context(constant, interface, component_info)
- for constant in interface.constants
- ],
- 'do_not_check_constants':
- 'DoNotCheckConstants' in extended_attributes,
- })
-
- # Attributes
- attributes = attributes_context(interface, interfaces, component_info)
-
- context.update({
- 'attributes':
- attributes,
- # Elements in attributes are broken in following members.
- 'accessors':
- v8_attributes.filter_accessors(attributes),
- 'data_attributes':
- v8_attributes.filter_data_attributes(attributes),
- 'runtime_enabled_attributes':
- v8_attributes.filter_runtime_enabled(attributes),
- })
-
- # Conditionally enabled attributes
- conditionally_enabled_attributes = v8_attributes.filter_conditionally_enabled(
- attributes)
- conditional_attributes = [
- attr for attr in conditionally_enabled_attributes
- if not attr['constructor_type']
- ]
- conditional_interface_objects = [
- attr for attr in conditionally_enabled_attributes
- if attr['constructor_type']
- ]
- has_conditional_coi_attributes = any( # pylint: disable=invalid-name
- v8_attributes.is_cross_origin_isolated(attr)
- for attr in conditionally_enabled_attributes)
- has_conditional_direct_socket_attributes = any( # pylint: disable=invalid-name
- v8_attributes.is_direct_socket_enabled(attr)
- for attr in conditionally_enabled_attributes)
- has_conditional_secure_attributes = any( # pylint: disable=invalid-name
- v8_attributes.is_secure_context(attr)
- for attr in conditionally_enabled_attributes)
- context.update({
- 'conditional_attributes':
- conditional_attributes,
- 'conditional_interface_objects':
- conditional_interface_objects,
- 'has_conditional_coi_attributes':
- has_conditional_coi_attributes,
- 'has_conditional_direct_socket_attributes':
- has_conditional_direct_socket_attributes,
- 'has_conditional_secure_attributes':
- has_conditional_secure_attributes,
- })
-
- # Methods
- context.update(methods_context(interface, component_info))
- methods = context['methods']
-
- # Conditionally enabled methods
- conditional_methods = v8_methods.filter_conditionally_enabled(
- methods, interface.is_partial)
- has_conditional_coi_methods = any( # pylint: disable=invalid-name
- v8_methods.is_cross_origin_isolated(method)
- for method in conditional_methods)
- has_conditional_direct_socket_methods = any( # pylint: disable=invalid-name
- v8_methods.is_direct_socket_enabled(method)
- for method in conditional_methods)
- has_conditional_secure_methods = any( # pylint: disable=invalid-name
- v8_methods.is_secure_context(method) for method in conditional_methods)
- context.update({
- 'has_conditional_coi_methods': has_conditional_coi_methods,
- 'has_conditional_direct_socket_methods':
- has_conditional_direct_socket_methods,
- 'has_conditional_secure_methods': has_conditional_secure_methods,
- 'conditional_methods': conditional_methods,
- })
-
- # Window.idl in Blink has indexed properties, but the spec says Window
- # interface doesn't have indexed properties, instead the WindowProxy exotic
- # object has indexed properties. Thus, Window interface must not support
- # iterators.
- has_array_iterator = (not interface.is_partial
- and interface.has_indexed_elements
- and interface.name != 'Window')
- context.update({
- 'has_array_iterator': has_array_iterator,
- 'iterable': interface.iterable,
- })
-
- # Conditionally enabled members
- install_conditional_features_func = None # pylint: disable=invalid-name
- if unscopables or conditional_interface_objects or conditional_attributes or conditional_methods:
- install_conditional_features_func = ( # pylint: disable=invalid-name
- v8_class_name_or_partial + '::InstallConditionalFeatures')
-
- context.update({
- 'install_conditional_features_func':
- install_conditional_features_func,
- })
-
- context.update({
- 'indexed_property_getter':
- property_getter(interface.indexed_property_getter, ['index']),
- 'indexed_property_setter':
- property_setter(interface.indexed_property_setter, interface),
- 'indexed_property_deleter':
- property_deleter(interface.indexed_property_deleter),
- 'is_override_builtins':
- 'LegacyOverrideBuiltIns' in extended_attributes,
- 'named_property_getter':
- property_getter(interface.named_property_getter, ['name']),
- 'named_property_setter':
- property_setter(interface.named_property_setter, interface),
- 'named_property_deleter':
- property_deleter(interface.named_property_deleter),
- })
- context.update({
- 'has_named_properties_object':
- is_global and context['named_property_getter'],
- })
-
- # Origin Trials and ContextEnabled features
- context.update({
- 'optional_features':
- sorted(
- origin_trial_features(interface, context['constants'],
- context['attributes'], context['methods']) +
- context_enabled_features(context['attributes']),
- key=lambda item: item['name']),
- })
- if context['optional_features']:
- includes.add('platform/bindings/v8_per_context_data.h')
-
- # Cross-origin interceptors
- has_cross_origin_named_getter = False
- has_cross_origin_named_setter = False
- has_cross_origin_indexed_getter = False
-
- for attribute in attributes:
- if attribute['has_cross_origin_getter']:
- has_cross_origin_named_getter = True
- if attribute['has_cross_origin_setter']:
- has_cross_origin_named_setter = True
-
- # Methods are exposed as getter attributes on the interface: e.g.
- # window.location gets the location attribute on the Window interface. For
- # the cross-origin case, this attribute getter is guaranteed to only return
- # a Function object, which the actual call is dispatched against.
- for method in methods:
- if method['is_cross_origin']:
- has_cross_origin_named_getter = True
-
- has_cross_origin_named_enumerator = has_cross_origin_named_getter or has_cross_origin_named_setter # pylint: disable=invalid-name
-
- if (context['named_property_getter']
- and context['named_property_getter']['is_cross_origin']):
- has_cross_origin_named_getter = True
-
- if context['indexed_property_getter'] and context[
- 'indexed_property_getter']['is_cross_origin']:
- has_cross_origin_indexed_getter = True
-
- context.update({
- 'has_cross_origin_named_getter':
- has_cross_origin_named_getter,
- 'has_cross_origin_named_setter':
- has_cross_origin_named_setter,
- 'has_cross_origin_named_enumerator':
- has_cross_origin_named_enumerator,
- 'has_cross_origin_indexed_getter':
- has_cross_origin_indexed_getter,
- })
-
- return context
-
-
-def attributes_context(interface, interfaces, component_info):
- """Creates a list of Jinja template contexts for attributes of an interface.
-
- Args:
- interface: An interface to create contexts for
- interfaces: A dict which maps an interface name to the definition
- which can be referred if needed
-
- Returns:
- A list of attribute contexts
- """
-
- attributes = [
- v8_attributes.attribute_context(interface, attribute, interfaces,
- component_info)
- for attribute in interface.attributes
- ]
-
- has_conditional_attributes = any(
- attribute['exposed_test'] for attribute in attributes)
- if has_conditional_attributes and interface.is_partial:
- raise Exception(
- 'Conditional attributes between partial interfaces in modules '
- 'and the original interfaces(%s) in core are not allowed.' %
- interface.name)
-
- # See also comment in methods_context.
- if not interface.is_partial and (interface.maplike or interface.setlike):
- if any(attribute['name'] == 'size' for attribute in attributes):
- raise ValueError(
- 'An interface cannot define an attribute called "size"; it is '
- 'implied by maplike/setlike in the IDL.')
- size_attribute = IdlAttribute()
- size_attribute.name = 'size'
- size_attribute.idl_type = IdlType('unsigned long')
- size_attribute.is_read_only = True
- size_attribute.extended_attributes['NotEnumerable'] = None
- attributes.append(
- v8_attributes.attribute_context(interface, size_attribute,
- interfaces, component_info))
-
- return attributes
-
-
-def methods_context(interface, component_info):
- """Creates a list of Jinja template contexts for methods of an interface.
-
- Args:
- interface: An interface to create contexts for
- component_info: A dict containing component wide information
-
- Returns:
- A dictionary with 3 keys:
- 'iterator_method': An iterator context if available or None.
- 'iterator_method_alias': A string that can also be used to refer to the
- @@iterator symbol or None.
- 'methods': A list of method contexts.
- """
-
- methods = []
-
- if interface.original_interface:
- methods.extend([
- v8_methods.method_context(
- interface, operation, component_info, is_visible=False)
- for operation in interface.original_interface.operations
- if operation.name
- ])
- methods.extend([
- v8_methods.method_context(interface, method, component_info)
- for method in interface.operations if method.name
- ]) # Skip anonymous special operations (methods)
- if interface.partial_interfaces:
- assert len(interface.partial_interfaces) == len(
- set(interface.partial_interfaces))
- for partial_interface in interface.partial_interfaces:
- methods.extend([
- v8_methods.method_context(
- interface, operation, component_info, is_visible=False)
- for operation in partial_interface.operations if operation.name
- ])
- compute_method_overloads_context(interface, methods)
-
- def generated_method(return_type,
- name,
- arguments=None,
- extended_attributes=None,
- implemented_as=None):
- operation = IdlOperation()
- operation.idl_type = return_type
- operation.name = name
- if arguments:
- operation.arguments = arguments
- if extended_attributes:
- operation.extended_attributes.update(extended_attributes)
- if implemented_as is None:
- implemented_as = name + 'ForBinding'
- operation.extended_attributes['ImplementedAs'] = implemented_as
- return v8_methods.method_context(interface, operation, component_info)
-
- def generated_argument(idl_type,
- name,
- is_optional=False,
- extended_attributes=None):
- argument = IdlArgument()
- argument.idl_type = idl_type
- argument.name = name
- argument.is_optional = is_optional
- if extended_attributes:
- argument.extended_attributes.update(extended_attributes)
- return argument
-
- # iterable<>, maplike<> and setlike<>
- iterator_method = None
-
- # Depending on the declaration, @@iterator may be a synonym for e.g.
- # 'entries' or 'values'.
- iterator_method_alias = None
-
- # FIXME: support Iterable in partial interfaces. However, we don't
- # need to support iterator overloads between interface and
- # partial interface definitions.
- # http://heycam.github.io/webidl/#idl-overloading
- if (not interface.is_partial
- and (interface.iterable or interface.maplike or interface.setlike
- or interface.has_indexed_elements)):
-
- used_extended_attributes = {}
-
- if interface.iterable:
- used_extended_attributes.update(
- interface.iterable.extended_attributes)
- elif interface.maplike:
- used_extended_attributes.update(
- interface.maplike.extended_attributes)
- elif interface.setlike:
- used_extended_attributes.update(
- interface.setlike.extended_attributes)
-
- if 'RaisesException' in used_extended_attributes:
- raise ValueError(
- '[RaisesException] is implied for iterable<>/maplike<>/setlike<>'
- )
- if 'CallWith' in used_extended_attributes:
- raise ValueError(
- '[CallWith=ScriptState] is implied for iterable<>/maplike<>/setlike<>'
- )
-
- used_extended_attributes.update({
- 'RaisesException': None,
- 'CallWith': 'ScriptState',
- })
-
- forEach_extended_attributes = used_extended_attributes.copy()
- forEach_extended_attributes.update({
- 'CallWith': ['ScriptState', 'ThisValue'],
- })
-
- def generated_iterator_method(name, implemented_as=None):
- return generated_method(
- return_type=IdlType('Iterator'),
- name=name,
- extended_attributes=used_extended_attributes,
- implemented_as=implemented_as)
-
- if not interface.has_indexed_elements:
- iterator_method = generated_iterator_method(
- 'iterator', implemented_as='GetIterator')
-
- if interface.iterable or interface.maplike or interface.setlike:
- non_overridable_methods = []
- overridable_methods = []
-
- is_value_iterator = interface.iterable and interface.iterable.key_type is None
-
- # For value iterators, the |entries|, |forEach|, |keys| and |values| are originally set
- # to corresponding properties in %ArrayPrototype%.
- # For pair iterators and maplike declarations, |entries| is an alias for @@iterator
- # itself. For setlike declarations, |values| is an alias for @@iterator.
- if not is_value_iterator:
- if not interface.setlike:
- iterator_method_alias = 'entries'
- entries_or_values_method = generated_iterator_method(
- 'values')
- else:
- iterator_method_alias = 'values'
- entries_or_values_method = generated_iterator_method(
- 'entries')
-
- non_overridable_methods.extend([
- generated_iterator_method('keys'),
- entries_or_values_method,
-
- # void forEach(ForEachIteratorCallback callback, [DefaultValue=Undefined] optional any thisArg)
- generated_method(
- IdlType('void'),
- 'forEach',
- arguments=[
- generated_argument(
- IdlType('ForEachIteratorCallback'),
- 'callback'),
- generated_argument(
- IdlType('any'),
- 'thisArg',
- is_optional=True,
- extended_attributes={
- 'DefaultValue': 'Undefined'
- })
- ],
- extended_attributes=forEach_extended_attributes),
- ])
-
- if interface.maplike:
- key_argument = generated_argument(interface.maplike.key_type,
- 'key')
- value_argument = generated_argument(
- interface.maplike.value_type, 'value')
-
- non_overridable_methods.extend([
- generated_method(
- IdlType('boolean'),
- 'has',
- arguments=[key_argument],
- extended_attributes=used_extended_attributes),
- generated_method(
- IdlType('any'),
- 'get',
- arguments=[key_argument],
- extended_attributes=used_extended_attributes),
- ])
-
- if not interface.maplike.is_read_only:
- overridable_methods.extend([
- generated_method(
- IdlType('void'),
- 'clear',
- extended_attributes=used_extended_attributes),
- generated_method(
- IdlType('boolean'),
- 'delete',
- arguments=[key_argument],
- extended_attributes=used_extended_attributes),
- generated_method(
- IdlType(interface.name),
- 'set',
- arguments=[key_argument, value_argument],
- extended_attributes=used_extended_attributes),
- ])
-
- if interface.setlike:
- value_argument = generated_argument(
- interface.setlike.value_type, 'value')
-
- non_overridable_methods.extend([
- generated_method(
- IdlType('boolean'),
- 'has',
- arguments=[value_argument],
- extended_attributes=used_extended_attributes),
- ])
-
- if not interface.setlike.is_read_only:
- overridable_methods.extend([
- generated_method(
- IdlType(interface.name),
- 'add',
- arguments=[value_argument],
- extended_attributes=used_extended_attributes),
- generated_method(
- IdlType('void'),
- 'clear',
- extended_attributes=used_extended_attributes),
- generated_method(
- IdlType('boolean'),
- 'delete',
- arguments=[value_argument],
- extended_attributes=used_extended_attributes),
- ])
-
- methods_by_name = {}
- for method in methods:
- methods_by_name.setdefault(method['name'], []).append(method)
-
- for non_overridable_method in non_overridable_methods:
- if non_overridable_method['name'] in methods_by_name:
- raise ValueError(
- 'An interface cannot define an operation called "%s()", it '
- 'comes from the iterable, maplike or setlike declaration '
- 'in the IDL.' % non_overridable_method['name'])
- methods.append(non_overridable_method)
-
- for overridable_method in overridable_methods:
- if overridable_method['name'] in methods_by_name:
- # FIXME: Check that the existing method is compatible.
- continue
- methods.append(overridable_method)
-
- # FIXME: maplike<> and setlike<> should also imply the presence of a
- # 'size' attribute.
-
- # Stringifier
- if interface.stringifier:
- stringifier = interface.stringifier
- stringifier_ext_attrs = stringifier.extended_attributes.copy()
- if stringifier.attribute:
- implemented_as = stringifier.attribute.name
- elif stringifier.operation:
- implemented_as = stringifier.operation.name
- else:
- implemented_as = 'toString'
- methods.append(
- generated_method(
- return_type=IdlType('DOMString'),
- name='toString',
- extended_attributes=stringifier_ext_attrs,
- implemented_as=implemented_as))
-
- for method in methods:
- # The value of the Function object’s “length” property is a Number
- # determined as follows:
- # 1. Let S be the effective overload set for regular operations (if the
- # operation is a regular operation) or for static operations (if the
- # operation is a static operation) with identifier id on interface I and
- # with argument count 0.
- # 2. Return the length of the shortest argument list of the entries in S.
- # FIXME: This calculation doesn't take into account whether runtime
- # enabled overloads are actually enabled, so length may be incorrect.
- # E.g., [RuntimeEnabled=Foo] void f(); void f(long x);
- # should have length 1 if Foo is not enabled, but length 0 if it is.
- method['length'] = (method['overloads']['length']
- if 'overloads' in method else
- method['number_of_required_arguments'])
-
- return {
- 'iterator_method': iterator_method,
- 'iterator_method_alias': iterator_method_alias,
- 'methods': methods,
- }
-
-
-def reflected_name(constant_name):
- """Returns the name to use for the matching constant name in blink code.
-
- Given an all-uppercase 'CONSTANT_NAME', returns a camel-case
- 'kConstantName'.
- """
- # Check for SHOUTY_CASE constants
- if constant_name.upper() != constant_name:
- return constant_name
- return 'k' + ''.join(part.title() for part in constant_name.split('_'))
-
-
-# [DeprecateAs], [Reflect], [RuntimeEnabled]
-def constant_context(constant, interface, component_info):
- extended_attributes = constant.extended_attributes
- runtime_features = component_info['runtime_enabled_features']
-
- return {
- 'camel_case_name':
- NameStyleConverter(constant.name).to_upper_camel_case(),
- 'cpp_class':
- extended_attributes.get('PartialInterfaceImplementedAs'),
- 'cpp_type':
- constant.idl_type.cpp_type,
- 'deprecate_as':
- v8_utilities.deprecate_as(constant), # [DeprecateAs]
- 'idl_type':
- constant.idl_type.name,
- 'measure_as':
- v8_utilities.measure_as(constant, interface), # [MeasureAs]
- 'high_entropy':
- v8_utilities.high_entropy(constant), # [HighEntropy]
- 'name':
- constant.name,
- # [RuntimeEnabled] for origin trial
- 'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(constant, runtime_features),
- # FIXME: use 'reflected_name' as correct 'name'
- 'rcs_counter':
- 'Blink_' + v8_utilities.cpp_name(interface) + '_' + constant.name +
- '_ConstantGetter',
- 'reflected_name':
- extended_attributes.get('Reflect', reflected_name(constant.name)),
- # [RuntimeEnabled] if not in origin trial
- 'runtime_enabled_feature_name':
- runtime_enabled_feature_name(constant, runtime_features),
- 'value':
- constant.value,
- }
-
-
-################################################################################
-# Overloads
-################################################################################
-
-
-def compute_method_overloads_context(interface, methods):
- # Regular methods
- compute_method_overloads_context_by_type(
- interface, [method for method in methods if not method['is_static']])
- # Static methods
- compute_method_overloads_context_by_type(
- interface, [method for method in methods if method['is_static']])
-
-
-def compute_method_overloads_context_by_type(interface, methods):
- """Computes |method.overload*| template values.
-
- Called separately for static and non-static (regular) methods,
- as these are overloaded separately.
- Modifies |method| in place for |method| in |methods|.
- Doesn't change the |methods| list itself (only the values, i.e. individual
- methods), so ok to treat these separately.
- """
- # Add overload information only to overloaded methods, so template code can
- # easily verify if a function is overloaded
- for name, overloads in method_overloads_by_name(methods):
- # Resolution function is generated after last overloaded function;
- # package necessary information into |method.overloads| for that method.
- overloads[-1]['overloads'] = overloads_context(interface, overloads)
- overloads[-1]['overloads']['name'] = name
- overloads[-1]['overloads']['camel_case_name'] = NameStyleConverter(
- name).to_upper_camel_case()
-
-
-def overloads_context(interface, overloads):
- """Returns |overloads| template values for a single name.
-
- Sets |method.overload_index| in place for |method| in |overloads|
- and returns dict of overall overload template values.
- """
- assert len(overloads) > 1 # only apply to overloaded names
- for index, method in enumerate(overloads, 1):
- method['overload_index'] = index
-
- # [RuntimeEnabled]
- if any(method.get('origin_trial_feature_name') for method in overloads):
- raise Exception(
- '[RuntimeEnabled] for origin trial cannot be specified on '
- 'overloaded methods: %s.%s' % (interface.name,
- overloads[0]['name']))
-
- effective_overloads_by_length = effective_overload_set_by_length(overloads)
- lengths = [length for length, _ in effective_overloads_by_length]
- name = overloads[0].get('name', '<constructor>')
- camel_case_name = NameStyleConverter(name).to_upper_camel_case()
-
- runtime_determined_lengths = None
- function_length = lengths[0]
- runtime_determined_maxargs = None
- maxarg = lengths[-1]
-
- # The special case handling below is not needed if all overloads are
- # runtime enabled by the same feature.
- if not common_value(overloads, 'runtime_enabled_feature_name'):
- # Check if all overloads with the shortest acceptable arguments list are
- # runtime enabled, in which case we need to have a runtime determined
- # Function.length.
- shortest_overloads = effective_overloads_by_length[0][1]
- if (all(
- method.get('runtime_enabled_feature_name')
- for method, _, _ in shortest_overloads)):
- # Generate a list of (length, runtime_enabled_feature_names) tuples.
- runtime_determined_lengths = []
- 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 None in runtime_enabled_feature_names:
- # This "length" is unconditionally enabled, so stop here.
- runtime_determined_lengths.append((length, [None]))
- break
- runtime_determined_lengths.append(
- (length, sorted(runtime_enabled_feature_names)))
- function_length = ('%s::%sMethodLength()' % (
- internal_namespace(interface), camel_case_name))
-
- # Check if all overloads with the longest required arguments list are
- # runtime enabled, in which case we need to have a runtime determined
- # maximum distinguishing argument index.
- longest_overloads = effective_overloads_by_length[-1][1]
- if (not common_value(overloads, 'runtime_enabled_feature_name')
- and all(
- method.get('runtime_enabled_feature_name')
- for method, _, _ in longest_overloads)):
- # Generate a list of (length, runtime_enabled_feature_name) tuples.
- runtime_determined_maxargs = []
- for length, effective_overloads in reversed(
- 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:
- # This "length" is unconditionally enabled, so stop here.
- runtime_determined_maxargs.append((length, [None]))
- break
- runtime_determined_maxargs.append(
- (length, sorted(runtime_enabled_feature_names)))
- maxarg = ('%s::%sMethodMaxArg()' % (internal_namespace(interface),
- camel_case_name))
-
- # Check and fail if overloads disagree about whether the return type
- # is a Promise or not.
- promise_overload_count = sum(
- 1 for method in overloads if method.get('returns_promise'))
- if promise_overload_count not in (0, len(overloads)):
- raise ValueError(
- 'Overloads of %s have conflicting Promise/non-Promise types' %
- (name))
-
- has_overload_visible = False
- has_overload_not_visible = False
- for overload in overloads:
- if overload.get('visible', True):
- # If there exists an overload which is visible, need to generate
- # overload_resolution, i.e. overlods_visible should be True.
- has_overload_visible = True
- else:
- has_overload_not_visible = True
-
- # If some overloads are not visible and others are visible,
- # the method is overloaded between core and modules.
- has_partial_overloads = has_overload_visible and has_overload_not_visible
-
- return {
- 'deprecate_all_as':
- common_value(overloads, 'deprecate_as'), # [DeprecateAs]
- 'exposed_test_all':
- common_value(overloads, 'exposed_test'), # [Exposed]
- 'length':
- function_length,
- 'length_tests_methods':
- length_tests_methods(effective_overloads_by_length),
- # 1. Let maxarg be the length of the longest type list of the
- # entries in S.
- 'maxarg':
- maxarg,
- 'measure_all_as':
- common_value(overloads, 'measure_as'), # [MeasureAs]
- 'returns_promise_all':
- promise_overload_count > 0,
- 'runtime_determined_lengths':
- runtime_determined_lengths,
- 'runtime_determined_maxargs':
- runtime_determined_maxargs,
- # [RuntimeEnabled]
- 'runtime_enabled_all':
- common_value(overloads, 'runtime_enabled_feature_name'),
- # [CrossOriginIsolated]
- 'cross_origin_isolated_test_all':
- common_value(overloads, 'cross_origin_isolated_test'),
- # [DirectSocketEnabled]
- 'direct_socket_enabled_test_all':
- common_value(overloads, 'direct_socket_enabled_test'),
- # [SecureContext]
- 'secure_context_test_all':
- common_value(overloads, 'secure_context_test'),
- 'valid_arities': (
- lengths
- # Only need to report valid arities if there is a gap in the
- # sequence of possible lengths, otherwise invalid length means
- # "not enough arguments".
- if lengths[-1] - lengths[0] != len(lengths) - 1 else None),
- 'visible':
- has_overload_visible,
- 'has_partial_overloads':
- has_partial_overloads,
- }
-
-
-def distinguishing_argument_index(entries):
- """Returns the distinguishing argument index for a sequence of entries.
-
- Entries are elements of the effective overload set with the same number
- of arguments (formally, same type list length), each a 3-tuple of the form
- (callable, type list, optionality list).
-
- Spec: http://heycam.github.io/webidl/#dfn-distinguishing-argument-index
-
- If there is more than one entry in an effective overload set that has a
- given type list length, then for those entries there must be an index i
- such that for each pair of entries the types at index i are
- distinguishable.
- The lowest such index is termed the distinguishing argument index for the
- entries of the effective overload set with the given type list length.
- """
- # Only applicable “If there is more than one entry”
- assert len(entries) > 1
-
- def typename_without_nullable(idl_type):
- if idl_type.is_nullable:
- return idl_type.inner_type.name
- return idl_type.name
-
- type_lists = [
- tuple(typename_without_nullable(idl_type) for idl_type in entry[1])
- for entry in entries
- ]
- type_list_length = len(type_lists[0])
- # Only applicable for entries that “[have] a given type list length”
- assert all(len(type_list) == type_list_length for type_list in type_lists)
- name = entries[0][0].get('name', 'Constructor') # for error reporting
-
- # The spec defines the distinguishing argument index by conditions it must
- # satisfy, but does not give an algorithm.
- #
- # We compute the distinguishing argument index by first computing the
- # minimum index where not all types are the same, and then checking that
- # all types in this position are distinguishable (and the optionality lists
- # up to this point are identical), since "minimum index where not all types
- # are the same" is a *necessary* condition, and more direct to check than
- # distinguishability.
- types_by_index = (set(types) for types in zip(*type_lists))
- try:
- # “In addition, for each index j, where j is less than the
- # distinguishing argument index for a given type list length, the types
- # at index j in all of the entries’ type lists must be the same”
- index = next(
- i for i, types in enumerate(types_by_index) if len(types) > 1)
- except StopIteration:
- raise ValueError('No distinguishing index found for %s, length %s:\n'
- 'All entries have the same type list:\n'
- '%s' % (name, type_list_length, type_lists[0]))
- # Check optionality
- # “and the booleans in the corresponding list indicating argument
- # optionality must be the same.”
- # FIXME: spec typo: optionality value is no longer a boolean
- # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25628
- initial_optionality_lists = set(entry[2][:index] for entry in entries)
- if len(initial_optionality_lists) > 1:
- raise ValueError(
- 'Invalid optionality lists for %s, length %s:\n'
- 'Optionality lists differ below distinguishing argument index %s:\n'
- '%s' % (name, type_list_length, index,
- set(initial_optionality_lists)))
-
- # Check distinguishability
- # http://heycam.github.io/webidl/#dfn-distinguishable
- # Use names to check for distinct types, since objects are distinct
- # FIXME: check distinguishability more precisely, for validation
- distinguishing_argument_type_names = [
- type_list[index] for type_list in type_lists
- ]
- if (len(set(distinguishing_argument_type_names)) !=
- len(distinguishing_argument_type_names)):
- raise ValueError('Types in distinguishing argument are not distinct:\n'
- '%s' % distinguishing_argument_type_names)
-
- return index
-
-
-def length_tests_methods(effective_overloads_by_length):
- """Returns sorted list of resolution tests and associated methods, by length.
-
- This builds the main data structure for the overload resolution loop.
- For a given argument length, bindings test argument at distinguishing
- argument index, in order given by spec: if it is compatible with
- (optionality or) type required by an overloaded method, resolve to that
- method.
-
- Returns:
- [(length, [(test, method)])]
- """
- return [(length, list(resolution_tests_methods(effective_overloads)))
- for length, effective_overloads in effective_overloads_by_length]
-
-
-def resolution_tests_methods(effective_overloads):
- """Yields resolution test and associated method, in resolution order, for effective overloads of a given length.
-
- This is the heart of the resolution algorithm.
- https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-
- Note that a given method can be listed multiple times, with different tests!
- This is to handle implicit type conversion.
-
- Returns:
- [(test, method)]
- """
- methods = [
- effective_overload[0] for effective_overload in effective_overloads
- ]
- if len(methods) == 1:
- # If only one method with a given length, no test needed
- yield 'true', methods[0]
- return
-
- # 8. If there is more than one entry in S, then set d to be the
- # distinguishing argument index for the entries of S.
- index = distinguishing_argument_index(effective_overloads)
-
- # (11. is for handling |undefined| values for optional arguments
- # before the distinguishing argument (as “missing”).)
- # TODO(peria): We have to handle this step. Also in 15.4.2.
-
- # 12. If i = d, then:
- # 12.1. Let V be args[i].
- cpp_value = 'info[%s]' % index
-
- # Extract argument and IDL type to simplify accessing these in each loop.
- arguments = [method['arguments'][index] for method in methods]
- arguments_methods = list(zip(arguments, methods))
- idl_types = [argument['idl_type_object'] for argument in arguments]
- idl_types_methods = list(zip(idl_types, methods))
-
- # We can’t do a single loop through all methods or simply sort them, because
- # a method may be listed in multiple steps of the resolution algorithm, and
- # which test to apply differs depending on the step.
- #
- # Instead, we need to go through all methods at each step, either finding
- # first match (if only one test is allowed) or filtering to matches (if
- # multiple tests are allowed), and generating an appropriate tests.
- #
- # In listing types, we put ellipsis (...) for shorthand nullable type(s),
- # annotated type(s), and a (nullable/annotated) union type, which extend
- # listed types.
- # TODO(peria): Support handling general union types. https://crbug.com/838787
-
- # 12.2. If V is undefined, and there is an entry in S whose list of
- # optionality values has “optional” at index i, then remove from S all
- # other entries.
- try:
- method = next(method for argument, method in arguments_methods
- if argument['is_optional'])
- test = '%s->IsUndefined()' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.3. Otherwise: if V is null or undefined, and there is an entry in S that
- # has one of the following types at position i of its type list,
- # • a nullable type
- # • a dictionary type
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_nullable or idl_type.is_dictionary)
- test = 'IsUndefinedOrNull(%s)' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.4. Otherwise: if V is a platform object, and there is an entry in S that
- # has one of the following types at position i of its type list,
- # • an interface type that V implements
- # ...
- for idl_type, method in idl_types_methods:
- if idl_type.is_wrapper_type and not idl_type.is_array_buffer_or_view:
- test = 'V8{idl_type}::HasInstance({cpp_value}, info.GetIsolate())'.format(
- idl_type=idl_type.base_type, cpp_value=cpp_value)
- yield test, method
-
- # 12.5. Otherwise: if V is a DOMException platform object and there is an entry
- # in S that has one of the following types at position i of its type list,
- # • DOMException
- # • Error
- # ...
- # (DOMException is handled in 12.4, and we don't support Error type.)
-
- # 12.6. Otherwise: if Type(V) is Object, V has an [[ErrorData]] internal slot,
- # and there is an entry in S that has one of the following types at position
- # i of its type list,
- # • Error
- # ...
- # (We don't support Error type.)
-
- # 12.7. Otherwise: if Type(V) is Object, V has an [[ArrayBufferData]] internal
- # slot, and there is an entry in S that has one of the following types at
- # position i of its type list,
- # • ArrayBuffer
- # ...
- for idl_type, method in idl_types_methods:
- if idl_type.is_array_buffer_or_view or idl_type.is_typed_array:
- test = '{cpp_value}->Is{idl_type}()'.format(
- idl_type=idl_type.base_type, cpp_value=cpp_value)
- yield test, method
-
- # 12.8. Otherwise: if Type(V) is Object, V has a [[DataView]] internal slot,
- # and there is an entry in S that has one of the following types at position
- # i of its type list,
- # • DataView
- # ...
- # (DataView is included in 12.7.)
-
- # 12.9. Otherwise: if Type(V) is Object, V has a [[TypedArrayName]] internal
- # slot, and there is an entry in S that has one of the following types at
- # position i of its type list,
- # • a typed array type whose name is equal to the value of V’s
- # [[TypedArrayName]] internal slot
- # ...
- # (TypedArrays are included in 12.7.)
-
- # 12.10. Otherwise: if IsCallable(V) is true, and there is an entry in S that
- # has one of the following types at position i of its type list,
- # • a callback function type
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_callback_function)
- test = '%s->IsFunction()' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.11. Otherwise: if Type(V) is Object and there is an entry in S that has
- # one of the following types at position i of its type list,
- # • a sequence type
- # • a frozen array type
- # ...
- # and after performing the following steps,
- # 12.11.1. Let method be ? GetMethod(V, @@iterator).
- # method is not undefined, then remove from S all other entries.
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.native_array_element_type)
- # Either condition should be fulfilled to call this |method|.
- test = '%s->IsArray()' % cpp_value
- yield test, method
- test = 'HasCallableIteratorSymbol(info.GetIsolate(), %s, exception_state)' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.12. Otherwise: if Type(V) is Object and there is an entry in S that has
- # one of the following types at position i of its type list,
- # • a callback interface type
- # • a dictionary type
- # • a record type
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_callback_interface
- or idl_type.is_dictionary or idl_type.is_record_type)
- test = '%s->IsObject()' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.13. Otherwise: if Type(V) is Boolean and there is an entry in S that has
- # one of the following types at position i of its type list,
- # • boolean
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.name == 'Boolean')
- test = '%s->IsBoolean()' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.14. Otherwise: if Type(V) is Number and there is an entry in S that has
- # one of the following types at position i of its type list,
- # • a numeric type
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_numeric_type)
- test = '%s->IsNumber()' % cpp_value
- yield test, method
- except StopIteration:
- pass
-
- # 12.15. Otherwise: if there is an entry in S that has one of the following
- # types at position i of its type list,
- # • a string type
- # ...
- try:
- method = next(
- method for idl_type, method in idl_types_methods
- if idl_type.is_string_type or idl_type.is_enum or (
- idl_type.is_union_type and idl_type.string_member_type))
- yield 'true', method
- except StopIteration:
- pass
-
- # 12.16. Otherwise: if there is an entry in S that has one of the following
- # types at position i of its type list,
- # • a numeric type
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_numeric_type)
- yield 'true', method
- except StopIteration:
- pass
-
- # 12.17. Otherwise: if there is an entry in S that has one of the following
- # types at position i of its type list,
- # • boolean
- # ...
- try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.name == 'Boolean')
- yield 'true', method
- except StopIteration:
- pass
-
-
-################################################################################
-# Utility functions
-################################################################################
-
-
-def common(dicts, f):
- """Returns common result of f across an iterable of dicts, or None.
-
- Call f for each dict and return its result if the same across all dicts.
- """
- values = (f(d) for d in dicts)
- first_value = next(values)
- if all(value == first_value for value in values):
- return first_value
- return None
-
-
-def common_key(dicts, key):
- """Returns common presence of a key across an iterable of dicts, or None.
-
- True if all dicts have the key, False if none of the dicts have the key,
- and None if some but not all dicts have the key.
- """
- return common(dicts, lambda d: key in d)
-
-
-def common_value(dicts, key):
- """Returns common value of a key across an iterable of dicts, or None.
-
- Auxiliary function for overloads, so can consolidate an extended attribute
- that appears with the same value on all items in an overload set.
- """
- return common(dicts, lambda d: d.get(key))
-
-
-def internal_namespace(interface):
- return (v8_utilities.to_snake_case(cpp_name_or_partial(interface)) +
- '_v8_internal')
-
-
-################################################################################
-# Constructors
-################################################################################
-
-
-# [Constructor]
-def constructor_context(interface, constructor):
- # [RaisesException=Constructor]
- is_constructor_raises_exception = \
- interface.extended_attributes.get('RaisesException') == 'Constructor'
-
- argument_contexts = [
- v8_methods.argument_context(interface, constructor, argument, index)
- for index, argument in enumerate(constructor.arguments)
- ]
-
- return {
- 'arguments':
- argument_contexts,
- 'cpp_type':
- cpp_name(interface) + '*',
- 'cpp_value':
- v8_methods.cpp_value(interface, constructor,
- len(constructor.arguments)),
- 'has_exception_state':
- is_constructor_raises_exception
- or any(argument for argument in constructor.arguments
- if argument.idl_type.v8_conversion_needs_exception_state),
- 'has_optional_argument_without_default_value':
- any(True for argument_context in argument_contexts
- if argument_context['is_optional_without_default_value']),
- 'is_call_with_document':
- # [ConstructorCallWith=Document]
- has_extended_attribute_value(interface, 'ConstructorCallWith',
- 'Document'),
- 'is_call_with_execution_context':
- # [ConstructorCallWith=ExecutionContext]
- has_extended_attribute_value(interface, 'ConstructorCallWith',
- 'ExecutionContext'),
- 'is_call_with_script_state':
- # [ConstructorCallWith=ScriptState]
- has_extended_attribute_value(interface, 'ConstructorCallWith',
- 'ScriptState'),
- 'is_constructor':
- True,
- 'is_named_constructor':
- False,
- 'is_raises_exception':
- is_constructor_raises_exception,
- 'number_of_required_arguments':
- number_of_required_arguments(constructor),
- 'rcs_counter':
- 'Blink_' + v8_utilities.cpp_name(interface) + '_ConstructorCallback'
- }
-
-
-# [NamedConstructor]
-def named_constructor_context(interface):
- extended_attributes = interface.extended_attributes
- if 'NamedConstructor' not in extended_attributes:
- return None
- # FIXME: parser should return named constructor separately;
- # included in constructors (and only name stored in extended attribute)
- # for Perl compatibility
- idl_constructor = interface.constructors[-1]
- assert idl_constructor.name == 'NamedConstructor'
- context = constructor_context(interface, idl_constructor)
- context.update({
- 'name': extended_attributes['NamedConstructor'],
- 'is_named_constructor': True,
- })
- return context
-
-
-def number_of_required_arguments(constructor):
- return len([
- argument for argument in constructor.arguments
- if not (argument.is_optional or argument.is_variadic)
- ])
-
-
-def interface_length(constructors):
- # Docs: http://heycam.github.io/webidl/#es-interface-call
- if not constructors:
- return 0
- return min(constructor['number_of_required_arguments']
- for constructor in constructors)
-
-
-################################################################################
-# Special operations (methods)
-# http://heycam.github.io/webidl/#idl-special-operations
-################################################################################
-
-
-def property_getter(getter, cpp_arguments):
- if not getter:
- return None
-
- def is_null_expression(idl_type):
- if idl_type.use_output_parameter_for_result or idl_type.is_string_type:
- return 'result.IsNull()'
- if idl_type.is_interface_type:
- return '!result'
- if idl_type.base_type in ('any', 'object'):
- return 'result.IsEmpty()'
- return ''
-
- extended_attributes = getter.extended_attributes
- has_no_side_effect = v8_utilities.has_extended_attribute_value(
- getter, 'Affects', 'Nothing')
- idl_type = getter.idl_type
- idl_type.add_includes_for_type(extended_attributes)
- is_call_with_script_state = v8_utilities.has_extended_attribute_value(
- getter, 'CallWith', 'ScriptState')
- is_raises_exception = 'RaisesException' in extended_attributes
- use_output_parameter_for_result = idl_type.use_output_parameter_for_result
-
- # FIXME: make more generic, so can use v8_methods.cpp_value
- cpp_method_name = 'impl->%s' % cpp_name(getter)
-
- if is_call_with_script_state:
- cpp_arguments.insert(0, 'script_state')
- if is_raises_exception:
- cpp_arguments.append('exception_state')
- if use_output_parameter_for_result:
- cpp_arguments.append('result')
-
- cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
-
- return {
- 'cpp_type':
- idl_type.cpp_type,
- 'cpp_value':
- cpp_value,
- 'has_no_side_effect':
- has_no_side_effect,
- 'is_call_with_script_state':
- is_call_with_script_state,
- 'is_cross_origin':
- 'CrossOrigin' in extended_attributes,
- 'is_custom':
- 'Custom' in extended_attributes and
- (not extended_attributes['Custom']
- or has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')),
- 'is_custom_property_enumerator':
- has_extended_attribute_value(getter, 'Custom', 'PropertyEnumerator'),
- 'is_custom_property_query':
- has_extended_attribute_value(getter, 'Custom', 'PropertyQuery'),
- # TODO(rakuco): [NotEnumerable] does not make sense here and is only
- # used in non-standard IDL operations. We need to get rid of them.
- 'is_enumerable':
- 'NotEnumerable' not in extended_attributes,
- 'is_null_expression':
- is_null_expression(idl_type),
- 'is_raises_exception':
- is_raises_exception,
- 'name':
- cpp_name(getter),
- 'use_output_parameter_for_result':
- use_output_parameter_for_result,
- 'v8_set_return_value':
- idl_type.v8_set_return_value(
- 'result',
- extended_attributes=extended_attributes,
- script_wrappable='impl'),
- }
-
-
-def property_setter(setter, interface):
- if not setter:
- return None
-
- extended_attributes = setter.extended_attributes
- idl_type = setter.arguments[1].idl_type
- idl_type.add_includes_for_type(extended_attributes)
- is_call_with_script_state = v8_utilities.has_extended_attribute_value(
- setter, 'CallWith', 'ScriptState')
- is_raises_exception = 'RaisesException' in extended_attributes
- is_ce_reactions = 'CEReactions' in extended_attributes
-
- has_type_checking_interface = idl_type.is_wrapper_type
-
- return {
- 'has_exception_state':
- (is_raises_exception or idl_type.v8_conversion_needs_exception_state),
- 'has_type_checking_interface':
- has_type_checking_interface,
- 'idl_type':
- idl_type.base_type,
- 'is_call_with_script_state':
- is_call_with_script_state,
- 'is_ce_reactions':
- is_ce_reactions,
- 'is_custom':
- 'Custom' in extended_attributes,
- 'is_nullable':
- idl_type.is_nullable,
- 'is_raises_exception':
- is_raises_exception,
- 'name':
- cpp_name(setter),
- 'v8_value_to_local_cpp_value':
- idl_type.v8_value_to_local_cpp_value(extended_attributes, 'v8_value',
- 'property_value'),
- }
-
-
-def property_deleter(deleter):
- if not deleter:
- return None
-
- extended_attributes = deleter.extended_attributes
- is_call_with_script_state = v8_utilities.has_extended_attribute_value(
- deleter, 'CallWith', 'ScriptState')
- is_ce_reactions = 'CEReactions' in extended_attributes
- return {
- 'is_call_with_script_state': is_call_with_script_state,
- 'is_ce_reactions': is_ce_reactions,
- 'is_custom': 'Custom' in extended_attributes,
- 'is_raises_exception': 'RaisesException' in extended_attributes,
- 'name': cpp_name(deleter),
- }
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
deleted file mode 100644
index 7f5bf2c1d1f..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
+++ /dev/null
@@ -1,641 +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.
-"""Generate template values for methods.
-
-Extends IdlArgument with property |default_cpp_value|.
-Extends IdlTypeBase and IdlUnionType with property |union_arguments|.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-import os
-import sys
-
-sys.path.append(
- os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
-from blinkbuild.name_style_converter import NameStyleConverter
-from idl_definitions import IdlArgument, IdlOperation
-from idl_types import IdlTypeBase, IdlUnionType, inherits_interface
-from v8_globals import includes
-import v8_types
-import v8_utilities
-from v8_utilities import (has_extended_attribute_value, is_unforgeable)
-
-# TODO(crbug.com/1174969): Remove this once Python2 is obsoleted.
-if sys.version_info.major != 2:
- basestring = str
-
-
-def method_is_visible(method, interface_is_partial):
- if 'overloads' in method:
- return method['overloads']['visible'] and not (
- method['overloads']['has_partial_overloads']
- and interface_is_partial)
- return method['visible'] and 'overload_index' not in method
-
-
-def is_origin_trial_enabled(method):
- return bool(method['origin_trial_feature_name'])
-
-
-def is_cross_origin_isolated(method):
- return bool(
- method['overloads']['cross_origin_isolated_test_all'] if 'overloads' in
- method else method['cross_origin_isolated_test'])
-
-
-def is_direct_socket_enabled(method):
- return bool(
- method['overloads']['direct_socket_enabled_test_all'] if 'overloads' in
- method else method['direct_socket_enabled_test'])
-
-
-def is_secure_context(method):
- return bool(method['overloads']['secure_context_test_all'] if 'overloads'
- in method else method['secure_context_test'])
-
-
-def is_conditionally_enabled(method):
- exposed = method['overloads']['exposed_test_all'] \
- if 'overloads' in method else method['exposed_test']
- return exposed or is_secure_context(method) or is_cross_origin_isolated(
- method) or is_direct_socket_enabled(method)
-
-
-def filter_conditionally_enabled(methods, interface_is_partial):
- return [
- method for method in methods
- if (method_is_visible(method, interface_is_partial)
- and is_conditionally_enabled(method)
- and not is_origin_trial_enabled(method))
- ]
-
-
-def custom_registration(method):
- # TODO(dcheng): Currently, bindings must create a function object for each
- # realm as a hack to support the incumbent realm. Remove the need for custom
- # registration when Blink properly supports the incumbent realm.
- if method['is_cross_origin']:
- return True
- if 'overloads' in method:
- return (method['overloads']['runtime_determined_lengths']
- or (method['overloads']['runtime_enabled_all']
- and not is_conditionally_enabled(method)))
- return method[
- 'runtime_enabled_feature_name'] and not is_conditionally_enabled(
- method)
-
-
-def filter_custom_registration(methods, interface_is_partial):
- return [
- method for method in methods
- if (method_is_visible(method, interface_is_partial)
- and custom_registration(method))
- ]
-
-
-def filter_method_configuration(methods, interface_is_partial):
- return [
- method for method in methods
- if method_is_visible(method, interface_is_partial)
- and not is_origin_trial_enabled(method)
- and not is_conditionally_enabled(method)
- and not custom_registration(method)
- ]
-
-
-def method_filters():
- return {
- 'custom_registration': filter_custom_registration,
- 'has_method_configuration': filter_method_configuration
- }
-
-
-def use_local_result(method):
- extended_attributes = method.extended_attributes
- idl_type = method.idl_type
- return (has_extended_attribute_value(method, 'CallWith', 'ScriptState')
- or 'NewObject' in extended_attributes
- or 'RaisesException' in extended_attributes
- or idl_type.is_union_type or idl_type.is_dictionary
- or idl_type.is_explicit_nullable
- or v8_utilities.high_entropy(method) == 'Direct')
-
-
-def runtime_call_stats_context(interface, method):
- includes.add('platform/bindings/runtime_call_stats.h')
- generic_counter_name = (
- 'Blink_' + v8_utilities.cpp_name(interface) + '_' + method.name)
- (method_counter, extended_attribute_defined) = \
- v8_utilities.rcs_counter_name(method, generic_counter_name)
- trace_event_name = interface.name + '.' + method.name
- return {
- 'extended_attribute_defined':
- extended_attribute_defined,
- 'method_counter':
- method_counter,
- 'origin_safe_method_getter_counter':
- generic_counter_name + '_OriginSafeMethodGetter',
- 'trace_event_name':
- trace_event_name,
- }
-
-
-def method_context(interface, method, component_info, is_visible=True):
- arguments = method.arguments
- extended_attributes = method.extended_attributes
- idl_type = method.idl_type
- is_static = method.is_static
- name = method.name
-
- if is_visible:
- idl_type.add_includes_for_type(extended_attributes)
-
- this_cpp_value = cpp_value(interface, method, len(arguments))
-
- is_call_with_script_state = has_extended_attribute_value(
- method, 'CallWith', 'ScriptState')
- is_call_with_this_value = has_extended_attribute_value(
- method, 'CallWith', 'ThisValue')
- if is_call_with_script_state or is_call_with_this_value:
- includes.add('platform/bindings/script_state.h')
-
- # [CheckSecurity]
- is_cross_origin = 'CrossOrigin' in extended_attributes
- is_check_security_for_receiver = (has_extended_attribute_value(
- interface, 'CheckSecurity', 'Receiver') and not is_cross_origin)
- is_check_security_for_return_value = (has_extended_attribute_value(
- method, 'CheckSecurity', 'ReturnValue'))
- if is_check_security_for_receiver or is_check_security_for_return_value:
- includes.add('bindings/core/v8/binding_security.h')
- if is_check_security_for_return_value:
- includes.add('core/frame/web_feature.h')
- includes.add('platform/instrumentation/use_counter.h')
-
- is_ce_reactions = 'CEReactions' in extended_attributes
- if is_ce_reactions:
- includes.add('core/html/custom/ce_reactions_scope.h')
-
- is_raises_exception = 'RaisesException' in extended_attributes
-
- if 'LegacyLenientThis' in extended_attributes:
- raise Exception('[LegacyLenientThis] is not supported for operations.')
-
- if has_extended_attribute_value(method, 'Affects', 'Nothing'):
- side_effect_type = 'V8DOMConfiguration::kHasNoSideEffect'
- 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)
- ]
-
- runtime_features = component_info['runtime_enabled_features']
-
- return {
- 'activity_logging_world_list':
- v8_utilities.activity_logging_world_list(method), # [ActivityLogging]
- 'arguments':
- argument_contexts,
- 'camel_case_name':
- NameStyleConverter(name).to_upper_camel_case(),
- 'cpp_type':
- (v8_types.cpp_template_type('absl::optional', idl_type.cpp_type)
- if idl_type.is_explicit_nullable else v8_types.cpp_type(
- idl_type, extended_attributes=extended_attributes)),
- 'cpp_value':
- this_cpp_value,
- 'cpp_type_initializer':
- idl_type.cpp_type_initializer,
- 'high_entropy':
- v8_utilities.high_entropy(method), # [HighEntropy]
- 'deprecate_as':
- v8_utilities.deprecate_as(method), # [DeprecateAs]
- 'do_not_test_new_object':
- 'DoNotTestNewObject' in extended_attributes,
- 'exposed_test':
- v8_utilities.exposed(method, interface), # [Exposed]
- 'has_exception_state':
- is_raises_exception or is_check_security_for_receiver
- or any(argument for argument in arguments
- if argument_conversion_needs_exception_state(method, argument)),
- 'has_optional_argument_without_default_value':
- any(True for argument_context in argument_contexts
- if argument_context['is_optional_without_default_value']),
- 'idl_type':
- idl_type.base_type,
- 'is_call_with_execution_context':
- has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'),
- 'is_call_with_script_state':
- is_call_with_script_state,
- 'is_call_with_this_value':
- is_call_with_this_value,
- 'is_ce_reactions':
- is_ce_reactions,
- 'is_check_security_for_receiver':
- is_check_security_for_receiver,
- 'is_check_security_for_return_value':
- is_check_security_for_return_value,
- 'is_cross_origin':
- 'CrossOrigin' in extended_attributes,
- 'is_custom':
- 'Custom' in extended_attributes,
- 'is_explicit_nullable':
- idl_type.is_explicit_nullable,
- 'is_new_object':
- 'NewObject' in extended_attributes,
- 'is_partial_interface_member':
- 'PartialInterfaceImplementedAs' in extended_attributes,
- 'is_per_world_bindings':
- 'PerWorldBindings' in extended_attributes,
- 'is_raises_exception':
- is_raises_exception,
- 'is_static':
- is_static,
- 'is_unforgeable':
- is_unforgeable(method),
- 'is_variadic':
- arguments and arguments[-1].is_variadic,
- 'measure_as':
- v8_utilities.measure_as(method, interface), # [MeasureAs]
- 'name':
- name,
- 'number_of_arguments':
- len(arguments),
- 'number_of_required_arguments':
- len([
- argument for argument in arguments
- if not (argument.is_optional or argument.is_variadic)
- ]),
- 'number_of_required_or_variadic_arguments':
- len([argument for argument in arguments if not argument.is_optional]),
- 'on_instance':
- v8_utilities.on_instance(interface, method),
- 'on_interface':
- v8_utilities.on_interface(interface, method),
- 'on_prototype':
- v8_utilities.on_prototype(interface, method),
- # [RuntimeEnabled] for origin trial
- 'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(method, runtime_features),
- 'property_attributes':
- property_attributes(interface, method),
- 'returns_promise':
- method.returns_promise,
- 'runtime_call_stats':
- runtime_call_stats_context(interface, method),
- # [RuntimeEnabled] if not in origin trial
- 'runtime_enabled_feature_name':
- v8_utilities.runtime_enabled_feature_name(method, runtime_features),
- # [CrossOriginIsolated]
- 'cross_origin_isolated_test':
- v8_utilities.cross_origin_isolated(method, interface),
- # [DirectSocketEnabled]
- 'direct_socket_enabled_test':
- v8_utilities.direct_socket_enabled(method, interface),
- # [SecureContext]
- 'secure_context_test':
- v8_utilities.secure_context(method, interface),
- # [Affects]
- 'side_effect_type':
- side_effect_type,
- 'snake_case_name':
- NameStyleConverter(name).to_snake_case(),
- 'use_output_parameter_for_result':
- idl_type.use_output_parameter_for_result,
- 'use_local_result':
- use_local_result(method),
- 'v8_set_return_value':
- v8_set_return_value(interface.name, method, this_cpp_value),
- 'v8_set_return_value_for_main_world':
- v8_set_return_value(interface.name,
- method,
- this_cpp_value,
- for_main_world=True),
- 'visible':
- is_visible,
- 'world_suffixes':
- ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else
- [''], # [PerWorldBindings],
- }
-
-
-def argument_context(interface, method, argument, index, is_visible=True):
- extended_attributes = argument.extended_attributes
- idl_type = argument.idl_type
- if idl_type.has_string_context:
- includes.add(
- 'third_party/blink/renderer/bindings/core/v8/generated_code_helper.h'
- )
- if is_visible:
- idl_type.add_includes_for_type(extended_attributes)
- this_cpp_value = cpp_value(interface, method, index)
- is_variadic_wrapper_type = argument.is_variadic and idl_type.is_wrapper_type
-
- has_type_checking_interface = idl_type.is_wrapper_type
-
- set_default_value = argument.set_default_value
- this_cpp_type = idl_type.cpp_type_args(
- extended_attributes=extended_attributes,
- raw_type=True,
- used_as_variadic_argument=argument.is_variadic)
- snake_case_name = NameStyleConverter(argument.name).to_snake_case()
- context = {
- 'cpp_type': (v8_types.cpp_template_type(
- 'absl::optional', this_cpp_type) if idl_type.is_explicit_nullable
- and not argument.is_variadic else this_cpp_type),
- 'cpp_value':
- this_cpp_value,
- # FIXME: check that the default value's type is compatible with the argument's
- 'enum_type':
- idl_type.enum_type,
- 'enum_values':
- idl_type.enum_values,
- 'handle':
- '%s_handle' % snake_case_name,
- # TODO(peria): remove once [DefaultValue] removed and just use
- # argument.default_value. https://crbug.com/924419
- 'has_default':
- 'DefaultValue' in extended_attributes or set_default_value,
- 'has_type_checking_interface':
- has_type_checking_interface,
- # Dictionary is special-cased, but arrays and sequences shouldn't be
- 'idl_type':
- idl_type.base_type,
- 'idl_type_object':
- idl_type,
- 'index':
- index,
- 'is_callback_function':
- idl_type.is_callback_function,
- 'is_callback_interface':
- idl_type.is_callback_interface,
- # FIXME: Remove generic 'Dictionary' special-casing
- 'is_dictionary':
- idl_type.is_dictionary,
- 'is_explicit_nullable':
- idl_type.is_explicit_nullable,
- 'is_nullable':
- idl_type.is_nullable,
- 'is_optional':
- argument.is_optional,
- 'is_variadic':
- argument.is_variadic,
- 'is_variadic_wrapper_type':
- is_variadic_wrapper_type,
- 'is_wrapper_type':
- idl_type.is_wrapper_type,
- 'local_cpp_variable':
- snake_case_name,
- 'name':
- argument.name,
- 'set_default_value':
- set_default_value,
- 'use_permissive_dictionary_conversion':
- 'PermissiveDictionaryConversion' in extended_attributes,
- 'v8_set_return_value':
- v8_set_return_value(interface.name, method, this_cpp_value),
- 'v8_set_return_value_for_main_world':
- v8_set_return_value(
- interface.name, method, this_cpp_value, for_main_world=True),
- 'v8_value_to_local_cpp_value':
- v8_value_to_local_cpp_value(interface.name, method, argument, index),
- }
- context.update({
- 'is_optional_without_default_value':
- context['is_optional'] and not context['has_default']
- and not context['is_dictionary']
- and not context['is_callback_interface'],
- })
- return context
-
-
-################################################################################
-# Value handling
-################################################################################
-
-
-def cpp_value(interface, method, number_of_arguments):
- # Truncate omitted optional arguments
- arguments = method.arguments[:number_of_arguments]
- cpp_arguments = []
-
- if method.is_constructor:
- call_with_values = interface.extended_attributes.get(
- 'ConstructorCallWith')
- else:
- call_with_values = method.extended_attributes.get('CallWith')
- cpp_arguments.extend(v8_utilities.call_with_arguments(call_with_values))
-
- # Members of IDL partial interface definitions are implemented in C++ as
- # static member functions, which for instance members (non-static members)
- # take *impl as their first argument
- if ('PartialInterfaceImplementedAs' in method.extended_attributes
- and not method.is_static):
- cpp_arguments.append('*impl')
- for argument in arguments:
- variable_name = NameStyleConverter(argument.name).to_snake_case()
- cpp_arguments.append(variable_name)
-
- # If a method returns an IDL dictionary or union type, the return value is
- # passed as an argument to impl classes.
- idl_type = method.idl_type
- if idl_type and idl_type.use_output_parameter_for_result:
- cpp_arguments.append('result')
-
- if ('RaisesException' in method.extended_attributes
- or (method.is_constructor and has_extended_attribute_value(
- interface, 'RaisesException', 'Constructor'))):
- cpp_arguments.append('exception_state')
-
- if method.name == 'Constructor':
- base_name = 'Create'
- elif method.name == 'NamedConstructor':
- base_name = 'CreateForJSConstructor'
- else:
- base_name = v8_utilities.cpp_name(method)
-
- cpp_method_name = v8_utilities.scoped_name(interface, method, base_name)
- return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
-
-
-def v8_set_return_value(interface_name,
- method,
- cpp_value,
- for_main_world=False):
- idl_type = method.idl_type
- extended_attributes = method.extended_attributes
- if not idl_type or idl_type.name == 'void':
- # Constructors and void methods don't have a return type
- return None
-
- # [CallWith=ScriptState], [RaisesException]
- if use_local_result(method):
- if idl_type.is_explicit_nullable:
- # result is of type absl::optional<T>
- cpp_value = 'result.value()'
- else:
- cpp_value = 'result'
-
- script_wrappable = 'impl' if inherits_interface(interface_name,
- 'Node') else ''
- return idl_type.v8_set_return_value(
- cpp_value,
- extended_attributes,
- script_wrappable=script_wrappable,
- for_main_world=for_main_world,
- is_static=method.is_static)
-
-
-def v8_value_to_local_cpp_variadic_value(argument,
- index,
- for_constructor_callback=False):
- assert argument.is_variadic
- idl_type = v8_types.native_value_traits_type_name(
- argument.idl_type, argument.extended_attributes, True)
- execution_context_if_needed = ''
- if argument.idl_type.has_string_context:
- execution_context_if_needed = ', bindings::ExecutionContextFromV8Wrappable(impl)'
- if for_constructor_callback:
- execution_context_if_needed = ', CurrentExecutionContext(info.GetIsolate())'
- assign_expression = 'ToImplArguments<%s>(info, %s, exception_state%s)' % (
- idl_type, index, execution_context_if_needed)
- return {
- 'assign_expression': assign_expression,
- 'check_expression': 'exception_state.HadException()',
- 'cpp_name': NameStyleConverter(argument.name).to_snake_case(),
- 'declare_variable': False,
- }
-
-
-def v8_value_to_local_cpp_value(interface_name, method, argument, index):
- extended_attributes = argument.extended_attributes
- idl_type = argument.idl_type
- name = NameStyleConverter(argument.name).to_snake_case()
- v8_value = 'info[{index}]'.format(index=index)
- for_constructor_callback = method.name == 'Constructor'
-
- if argument.is_variadic:
- return v8_value_to_local_cpp_variadic_value(
- argument, index, for_constructor_callback=for_constructor_callback)
- return idl_type.v8_value_to_local_cpp_value(
- extended_attributes,
- v8_value,
- name,
- declare_variable=False,
- use_exception_state=method.returns_promise,
- for_constructor_callback=for_constructor_callback)
-
-
-################################################################################
-# Auxiliary functions
-################################################################################
-
-
-# [NotEnumerable], [LegacyUnforgeable]
-def property_attributes(interface, method):
- extended_attributes = method.extended_attributes
- property_attributes_list = []
- if 'NotEnumerable' in extended_attributes:
- property_attributes_list.append('v8::DontEnum')
- if is_unforgeable(method):
- property_attributes_list.append('v8::ReadOnly')
- property_attributes_list.append('v8::DontDelete')
- return property_attributes_list
-
-
-def argument_set_default_value(argument):
- idl_type = argument.idl_type
- default_value = argument.default_value
- variable_name = NameStyleConverter(argument.name).to_snake_case()
- if not default_value:
- return None
- if idl_type.is_dictionary:
- if argument.default_value.is_null:
- return None
- if argument.default_value.value == '{}':
- return None
- raise Exception('invalid default value for dictionary type')
- if idl_type.is_array_or_sequence_type:
- if default_value.value != '[]':
- raise Exception('invalid default value for sequence type: %s' %
- default_value.value)
- # Nothing to do when we set an empty sequence as default value, but we
- # need to return non-empty value so that we don't generate method calls
- # without this argument.
- return '/* Nothing to do */'
- if idl_type.is_union_type:
- if argument.default_value.is_null:
- if not idl_type.includes_nullable_type:
- raise Exception(
- 'invalid default value for union type: null for %s' %
- idl_type.name)
- # Union container objects are "null" initially.
- return '/* null default value */'
- if default_value.value == "{}":
- member_type = idl_type.dictionary_member_type
- elif isinstance(default_value.value, basestring):
- member_type = idl_type.string_member_type
- elif isinstance(default_value.value, (int, float)):
- member_type = idl_type.numeric_member_type
- elif isinstance(default_value.value, bool):
- member_type = idl_type.boolean_member_type
- else:
- member_type = None
- if member_type is None:
- raise Exception('invalid default value for union type: %r for %s' %
- (default_value.value, idl_type.name))
- member_type_name = (member_type.inner_type.name
- if member_type.is_nullable else member_type.name)
- return '%s.Set%s(%s)' % (variable_name, member_type_name,
- member_type.literal_cpp_value(default_value))
- return '%s = %s' % (variable_name,
- idl_type.literal_cpp_value(default_value))
-
-
-IdlArgument.set_default_value = property(argument_set_default_value)
-
-
-def method_returns_promise(method):
- return method.idl_type and method.idl_type.name == 'Promise'
-
-
-IdlOperation.returns_promise = property(method_returns_promise)
-
-
-def argument_conversion_needs_exception_state(method, argument):
- idl_type = argument.idl_type
- return (idl_type.v8_conversion_needs_exception_state
- or argument.is_variadic
- or (method.returns_promise and idl_type.is_string_type))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
deleted file mode 100644
index 9a14758395a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
+++ /dev/null
@@ -1,1348 +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.
-
-# pylint: disable=relative-import
-"""Functions for type handling and type conversion (Blink/C++ <-> V8/JS).
-
-Extends IdlType and IdlUnionType with V8-specific properties, methods, and
-class methods.
-
-Spec:
-http://www.w3.org/TR/WebIDL/#es-type-mapping
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-import posixpath
-
-from idl_types import IdlAnnotatedType
-from idl_types import IdlArrayOrSequenceType
-from idl_types import IdlNullableType
-from idl_types import IdlRecordType
-from idl_types import IdlType
-from idl_types import IdlTypeBase
-from idl_types import IdlUnionType
-from utilities import to_snake_case
-import v8_attributes # for IdlType.constructor_type_name
-from v8_globals import includes
-from v8_utilities import binding_header_filename, extended_attribute_value_contains
-
-################################################################################
-# V8-specific handling of IDL types
-################################################################################
-
-NON_WRAPPER_TYPES = frozenset([
- 'EventHandler',
- 'NodeFilter',
- 'OnBeforeUnloadEventHandler',
- 'OnErrorEventHandler',
-])
-TYPED_ARRAY_TYPES = frozenset([
- 'Float32Array',
- 'Float64Array',
- 'Int8Array',
- 'Int16Array',
- 'Int32Array',
- 'Uint8Array',
- 'Uint8ClampedArray',
- 'Uint16Array',
- 'Uint32Array',
- 'BigInt64Array',
- 'BigUint64Array',
-])
-ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES = TYPED_ARRAY_TYPES.union(
- frozenset(['ArrayBufferView']))
-ARRAY_BUFFER_AND_VIEW_TYPES = TYPED_ARRAY_TYPES.union(
- frozenset([
- 'ArrayBuffer',
- 'ArrayBufferView',
- 'DataView',
- 'SharedArrayBuffer',
- ]))
-# We have an unfortunate hack that treats types whose name ends with
-# 'Constructor' as aliases to IDL interface object. This list is used to disable
-# the hack.
-_CALLBACK_CONSTRUCTORS = frozenset((
- 'AnimatorConstructor',
- 'BlinkAudioWorkletProcessorConstructor',
- 'CustomElementConstructor',
- 'NoArgumentConstructor',
-))
-
-IdlType.is_array_buffer_or_view = property(
- lambda self: self.base_type in ARRAY_BUFFER_AND_VIEW_TYPES)
-
-IdlType.is_array_buffer_view_or_typed_array = property(
- lambda self: self.base_type in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES)
-
-IdlType.is_typed_array = property(
- lambda self: self.base_type in TYPED_ARRAY_TYPES)
-
-IdlType.is_wrapper_type = property(
- lambda self: (self.is_interface_type and not self.is_callback_interface and self.base_type not in NON_WRAPPER_TYPES)
-)
-
-################################################################################
-# C++ types
-################################################################################
-
-CPP_TYPE_SAME_AS_IDL_TYPE = set([
- 'double',
- 'float',
-])
-CPP_INTEGER_CONVERSION_RULES = {
- 'byte': 'int8_t',
- 'octet': 'uint8_t',
- 'short': 'int16_t',
- 'unsigned short': 'uint16_t',
- 'long': 'int32_t',
- 'unsigned long': 'uint32_t',
- 'long long': 'int64_t',
- 'unsigned long long': 'uint64_t',
-}
-CPP_SPECIAL_CONVERSION_RULES = {
- 'EventHandler': 'EventListener*',
- 'OnBeforeUnloadEventHandler': 'EventListener*',
- 'OnErrorEventHandler': 'EventListener*',
- 'Promise': 'ScriptPromise',
- 'ScriptValue': 'ScriptValue',
- # FIXME: Eliminate custom bindings for XPathNSResolver http://crbug.com/345529
- 'XPathNSResolver': 'XPathNSResolver*',
- 'boolean': 'bool',
- 'object': 'ScriptValue',
- 'unrestricted double': 'double',
- 'unrestricted float': 'float',
-}
-
-
-def string_resource_mode(idl_type):
- """Returns a V8StringResourceMode value corresponding to the IDL type.
-
- Args:
- idl_type:
- A string IdlType.
- """
- if idl_type.is_nullable:
- return 'kTreatNullAndUndefinedAsNullString'
- if idl_type.is_annotated_type:
- treat_null_as = idl_type.extended_attributes.get('TreatNullAs')
- if treat_null_as == 'EmptyString':
- return 'kTreatNullAsEmptyString'
- elif treat_null_as:
- raise ValueError(
- 'Unknown value for [TreatNullAs]: %s' % treat_null_as)
- return ''
-
-
-def cpp_type(idl_type,
- extended_attributes=None,
- raw_type=False,
- used_as_rvalue_type=False,
- used_as_variadic_argument=False,
- used_in_cpp_sequence=False):
- """Returns C++ type corresponding to IDL type.
-
- |idl_type| argument is of type IdlType, while return value is a string
-
- Args:
- idl_type:
- IdlType
- raw_type:
- bool, True if idl_type's raw/primitive C++ type should be returned.
- used_as_rvalue_type:
- bool, True if the C++ type is used as an argument or the return
- type of a method.
- used_as_variadic_argument:
- bool, True if the C++ type is used as a variadic argument of a method.
- used_in_cpp_sequence:
- bool, True if the C++ type is used as an element of a container.
- Containers can be an array, a sequence, a dictionary or a record.
- """
-
- extended_attributes = extended_attributes or {}
- idl_type = idl_type.preprocessed_type
-
- # Nullable types
- def needs_optional_wrapper():
- if not idl_type.is_nullable or not used_in_cpp_sequence:
- return False
- # NativeValueTraits<T>::NullValue should exist in order to provide the
- # implicit null value, if needed.
- return not idl_type.inner_type.cpp_type_has_null_value
-
- if needs_optional_wrapper():
- inner_type = idl_type.inner_type
- if inner_type.is_dictionary or inner_type.is_sequence or inner_type.is_record_type:
- # TODO(jbroman, bashi): Implement this if needed.
- # This is non-trivial to support because HeapVector refuses to hold
- # absl::optional<>, and IDLDictionaryBase (and subclasses) have no
- # integrated null state that can be distinguished from a present but
- # empty dictionary. It's unclear whether this will ever come up in
- # real spec WebIDL.
- raise NotImplementedError(
- 'Sequences of nullable dictionary, sequence or record types are not yet supported.'
- )
- return 'absl::optional<%s>' % inner_type.cpp_type_args(
- extended_attributes, raw_type, used_as_rvalue_type,
- used_as_variadic_argument, used_in_cpp_sequence)
-
- # Array or sequence types
- if used_as_variadic_argument:
- native_array_element_type = idl_type
- else:
- native_array_element_type = idl_type.native_array_element_type
- if native_array_element_type:
- vector_type = cpp_ptr_type('Vector', 'HeapVector',
- native_array_element_type.is_traceable)
- vector_template_type = cpp_template_type(
- vector_type,
- native_array_element_type.cpp_type_args(used_in_cpp_sequence=True))
- if used_as_rvalue_type:
- return 'const %s&' % vector_template_type
- return vector_template_type
-
- # Record types.
- if idl_type.is_record_type:
- vector_type = cpp_ptr_type('Vector', 'HeapVector',
- idl_type.value_type.is_traceable)
- value_type = idl_type.value_type.cpp_type_args(
- used_in_cpp_sequence=True)
- vector_template_type = cpp_template_type(
- vector_type, 'std::pair<String, %s>' % value_type)
- if used_as_rvalue_type:
- return 'const %s&' % vector_template_type
- return vector_template_type
-
- # Simple types
- base_idl_type = idl_type.base_type
-
- if base_idl_type in CPP_TYPE_SAME_AS_IDL_TYPE:
- return base_idl_type
- if base_idl_type in CPP_INTEGER_CONVERSION_RULES:
- return CPP_INTEGER_CONVERSION_RULES[base_idl_type]
- if base_idl_type in CPP_SPECIAL_CONVERSION_RULES:
- return CPP_SPECIAL_CONVERSION_RULES[base_idl_type]
-
- if idl_type.is_string_type:
- if idl_type.has_string_context:
- return 'String'
- if not raw_type:
- return 'const String&' if used_as_rvalue_type else 'String'
- return 'V8StringResource<%s>' % string_resource_mode(idl_type)
-
- if base_idl_type == 'ArrayBufferView' and 'FlexibleArrayBufferView' in extended_attributes:
- return 'FlexibleArrayBufferView'
- if base_idl_type in TYPED_ARRAY_TYPES and 'FlexibleArrayBufferView' in extended_attributes:
- return 'Flexible' + base_idl_type
- if base_idl_type in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES or base_idl_type == 'DataView':
- if 'AllowShared' in extended_attributes:
- return cpp_template_type('MaybeShared', idl_type.implemented_as)
- else:
- return cpp_template_type('NotShared', idl_type.implemented_as)
- if idl_type.is_interface_type or idl_type.is_dictionary:
- implemented_as_class = idl_type.implemented_as
- if raw_type or not used_in_cpp_sequence:
- return implemented_as_class + '*'
- if not used_in_cpp_sequence:
- return implemented_as_class + '*'
- if used_as_rvalue_type and idl_type.is_garbage_collected:
- return 'const %s*' % implemented_as_class
- return cpp_template_type('Member', implemented_as_class)
- if idl_type.is_union_type:
- # Avoid "AOrNullOrB" for cpp type of (A? or B) because we generate
- # V8AOrBOrNull to handle nulle for (A? or B), (A or B?) and (A or B)?
- def member_cpp_name(idl_type):
- if idl_type.is_nullable:
- return idl_type.inner_type.name
- return idl_type.name
-
- idl_type_name = 'Or'.join(
- member_cpp_name(member) for member in idl_type.member_types)
- return 'const %s&' % idl_type_name if used_as_rvalue_type else idl_type_name
- if idl_type.is_callback_function:
- v8_type_name = 'V8' + base_idl_type
- if idl_type.is_custom_callback_function:
- return v8_type_name
- if not used_in_cpp_sequence:
- return v8_type_name + '*'
- return cpp_template_type('Member', v8_type_name)
-
- if base_idl_type == 'void':
- return base_idl_type
- # Default, assume native type is a pointer with same type name as idl type
- return base_idl_type + '*'
-
-
-def cpp_type_initializer(idl_type):
- """Returns a string containing a C++ initialization statement for the
- corresponding type.
-
- |idl_type| argument is of type IdlType.
- """
-
- base_idl_type = idl_type.base_type
-
- if idl_type.native_array_element_type:
- return ''
- if idl_type.is_explicit_nullable:
- return ''
- if idl_type.is_numeric_type:
- return ' = 0'
- if base_idl_type == 'boolean':
- return ' = false'
- if (base_idl_type in NON_WRAPPER_TYPES
- or base_idl_type in CPP_SPECIAL_CONVERSION_RULES
- or base_idl_type == 'any' or idl_type.is_string_type
- or idl_type.is_enum):
- return ''
- return ' = nullptr'
-
-
-# Allow access as idl_type.cpp_type if no arguments
-IdlTypeBase.cpp_type = property(cpp_type)
-IdlTypeBase.cpp_type_initializer = property(cpp_type_initializer)
-IdlTypeBase.cpp_type_args = cpp_type
-IdlUnionType.cpp_type_initializer = ''
-
-IdlArrayOrSequenceType.native_array_element_type = property(
- lambda self: self.element_type)
-
-
-def cpp_template_type(template, inner_type):
- """Returns C++ template specialized to type."""
- format_string = '{template}<{inner_type}>'
- return format_string.format(template=template, inner_type=inner_type)
-
-
-def cpp_ptr_type(old_type, new_type, is_gc_type):
- if is_gc_type:
- return new_type
- return old_type
-
-
-def v8_type(interface_name):
- return 'V8' + interface_name
-
-
-# [ImplementedAs]
-# This handles [ImplementedAs] on interface types, not [ImplementedAs] in the
-# interface being generated. e.g., given:
-# Foo.idl: interface Foo {attribute Bar bar};
-# Bar.idl: [ImplementedAs=Zork] interface Bar {};
-# when generating bindings for Foo, the [ImplementedAs] on Bar is needed.
-# This data is external to Foo.idl, and hence computed as global information in
-# compute_interfaces_info.py to avoid having to parse IDLs of all used interfaces.
-IdlType.implemented_as_interfaces = {}
-
-
-def implemented_as(idl_type):
- base_idl_type = idl_type.base_type
- if base_idl_type in IdlType.implemented_as_interfaces:
- return IdlType.implemented_as_interfaces[base_idl_type]
- elif idl_type.is_callback_function or idl_type.is_callback_interface:
- return 'V8%s' % base_idl_type
- return base_idl_type
-
-
-IdlType.implemented_as = property(implemented_as)
-
-IdlType.set_implemented_as_interfaces = classmethod(
- lambda cls, new_implemented_as_interfaces: \
- cls.implemented_as_interfaces.update(new_implemented_as_interfaces)
-)
-
-# [GarbageCollected]
-IdlType.garbage_collected_types = set()
-
-IdlType.is_garbage_collected = property(
- lambda self: self.base_type in IdlType.garbage_collected_types)
-
-IdlType.set_garbage_collected_types = classmethod(
- lambda cls, new_garbage_collected_types: \
- cls.garbage_collected_types.update(new_garbage_collected_types)
-)
-
-
-def is_gc_type(idl_type):
- return idl_type.is_garbage_collected or idl_type.is_union_type
-
-
-IdlTypeBase.is_gc_type = property(is_gc_type)
-
-
-def is_traceable(idl_type):
- return (idl_type.is_garbage_collected or idl_type.is_callback_function
- or idl_type.cpp_type in ('ScriptValue', 'ScriptPromise'))
-
-
-IdlTypeBase.is_traceable = property(is_traceable)
-IdlUnionType.is_traceable = property(lambda self: True)
-IdlArrayOrSequenceType.is_traceable = property(
- lambda self: self.element_type.is_traceable)
-IdlRecordType.is_traceable = property(
- lambda self: self.value_type.is_traceable)
-IdlNullableType.is_traceable = property(
- lambda self: self.inner_type.is_traceable)
-
-################################################################################
-# Includes
-################################################################################
-
-INCLUDES_FOR_TYPE = {
- 'object':
- set([
- 'bindings/core/v8/script_value.h', 'bindings/core/v8/idl_types.h',
- 'bindings/core/v8/native_value_traits_impl.h'
- ]),
- 'ArrayBufferView':
- set([
- 'bindings/core/v8/v8_array_buffer_view.h',
- 'core/typed_arrays/array_buffer_view_helpers.h',
- 'core/typed_arrays/flexible_array_buffer_view.h'
- ]),
- 'EventHandler':
- set(['bindings/core/v8/js_event_handler.h']),
- 'HTMLCollection':
- set([
- 'bindings/core/v8/v8_html_collection.h', 'core/dom/class_collection.h',
- 'core/dom/tag_collection.h', 'core/html/html_collection.h',
- 'core/html/html_table_rows_collection.h',
- 'core/html/forms/html_data_list_options_collection.h',
- 'core/html/forms/html_form_controls_collection.h'
- ]),
- 'NodeList':
- set([
- 'bindings/core/v8/v8_node_list.h', 'core/dom/name_node_list.h',
- 'core/dom/node_list.h', 'core/dom/static_node_list.h',
- 'core/html/forms/labels_node_list.h'
- ]),
- 'Promise':
- set(['bindings/core/v8/script_promise.h']),
- 'ScriptValue':
- set(['bindings/core/v8/script_value.h']),
-}
-
-
-def includes_for_type(idl_type, extended_attributes=None):
- idl_type = idl_type.preprocessed_type
- extended_attributes = extended_attributes or {}
-
- # Simple types
- base_idl_type = idl_type.base_type
- if base_idl_type in INCLUDES_FOR_TYPE:
- return INCLUDES_FOR_TYPE[base_idl_type]
- if base_idl_type in TYPED_ARRAY_TYPES:
- return INCLUDES_FOR_TYPE['ArrayBufferView'].union(
- set([
- 'bindings/%s/v8/%s' % (component_dir[base_idl_type],
- binding_header_filename(base_idl_type))
- ]))
- if idl_type.is_basic_type:
- return set([
- 'bindings/core/v8/idl_types.h',
- 'bindings/core/v8/native_value_traits_impl.h'
- ])
- if base_idl_type.endswith('ConstructorConstructor'):
- # FIXME: rename to NamedConstructor
- # FIXME: replace with a [NamedConstructorAttribute] extended attribute
- # Ending with 'ConstructorConstructor' indicates a named constructor,
- # and these do not have header files, as they are part of the generated
- # bindings for the interface
- return set()
- if (base_idl_type.endswith('Constructor')
- and base_idl_type not in _CALLBACK_CONSTRUCTORS):
- # FIXME: replace with a [ConstructorAttribute] extended attribute
- base_idl_type = idl_type.constructor_type_name
- if idl_type.is_custom_callback_function:
- return set()
- if idl_type.is_callback_function:
- component = IdlType.callback_functions[base_idl_type]['component_dir']
- return set([
- 'bindings/%s/v8/%s' % (component,
- binding_header_filename(base_idl_type))
- ])
- if base_idl_type not in component_dir:
- return set()
- return set([
- 'bindings/%s/v8/%s' % (component_dir[base_idl_type],
- binding_header_filename(base_idl_type))
- ])
-
-
-IdlType.includes_for_type = includes_for_type
-
-
-def includes_for_union_type(idl_type, extended_attributes=None):
- return set.union(*[
- member_type.includes_for_type(extended_attributes)
- for member_type in idl_type.member_types
- ])
-
-
-IdlUnionType.includes_for_type = includes_for_union_type
-
-
-def includes_for_array_or_sequence_type(idl_type, extended_attributes=None):
- return set.union(
- set([
- 'bindings/core/v8/idl_types.h',
- 'bindings/core/v8/native_value_traits_impl.h'
- ]), idl_type.element_type.includes_for_type(extended_attributes))
-
-
-IdlArrayOrSequenceType.includes_for_type = includes_for_array_or_sequence_type
-
-
-def includes_for_record_type(idl_type, extended_attributes=None):
- return set.union(
- idl_type.key_type.includes_for_type(extended_attributes),
- idl_type.value_type.includes_for_type(extended_attributes))
-
-
-IdlRecordType.includes_for_type = includes_for_record_type
-
-
-def add_includes_for_type(idl_type, extended_attributes=None):
- includes.update(idl_type.includes_for_type(extended_attributes))
-
-
-IdlTypeBase.add_includes_for_type = add_includes_for_type
-
-
-def includes_for_interface(interface_name):
- return IdlType(interface_name).includes_for_type()
-
-
-def add_includes_for_interface(interface_name):
- includes.update(includes_for_interface(interface_name))
-
-
-def impl_includes_for_type(idl_type, interfaces_info):
- includes_for_type = set()
-
- idl_type = idl_type.preprocessed_type
- native_array_element_type = idl_type.native_array_element_type
- if native_array_element_type:
- includes_for_type.update(
- impl_includes_for_type(native_array_element_type, interfaces_info))
- includes_for_type.add('platform/wtf/vector.h')
-
- base_idl_type = idl_type.base_type
- if idl_type.is_string_type:
- includes_for_type.add('platform/wtf/text/wtf_string.h')
- if idl_type.is_record_type:
- includes_for_type.update(impl_includes_for_type(idl_type.key_type,
- interfaces_info))
- includes_for_type.update(impl_includes_for_type(idl_type.value_type,
- interfaces_info))
- if idl_type.is_callback_function:
- component = IdlType.callback_functions[base_idl_type]['component_dir']
- return set([
- 'bindings/%s/v8/%s' % (component,
- binding_header_filename(base_idl_type))
- ])
- if base_idl_type in interfaces_info:
- interface_info = interfaces_info[base_idl_type]
- includes_for_type.add(interface_info['include_path'])
- if base_idl_type in INCLUDES_FOR_TYPE:
- includes_for_type.update(INCLUDES_FOR_TYPE[base_idl_type])
- if idl_type.is_array_buffer_view_or_typed_array:
- return set([
- 'core/typed_arrays/dom_typed_array.h',
- 'core/typed_arrays/array_buffer_view_helpers.h'
- ])
- return includes_for_type
-
-
-def impl_includes_for_type_union(idl_type, interfaces_info):
- includes_for_type = set()
- for member_type in idl_type.member_types:
- includes_for_type.update(
- member_type.impl_includes_for_type(interfaces_info))
- return includes_for_type
-
-
-IdlTypeBase.impl_includes_for_type = impl_includes_for_type
-IdlUnionType.impl_includes_for_type = impl_includes_for_type_union
-
-
-def impl_forward_declaration_name(idl_type):
- element_type = idl_type.native_array_element_type
- if element_type:
- return element_type.impl_forward_declaration_name
-
- if ((idl_type.is_wrapper_type
- and not idl_type.is_array_buffer_view_or_typed_array)
- or idl_type.is_dictionary):
- return idl_type.implemented_as
- return None
-
-
-IdlTypeBase.impl_forward_declaration_name = property(
- impl_forward_declaration_name)
-
-component_dir = {}
-
-
-def set_component_dirs(new_component_dirs):
- component_dir.update(new_component_dirs)
-
-
-################################################################################
-# V8 -> C++
-################################################################################
-
-# TODO(rakuco): Get rid of this definition altogether and move to NativeValueTraits<T>::nativeValue().
-# That requires not requiring ExceptionState where it is not used, and we must be careful not
-# to introduce any performance regressions.
-V8_VALUE_TO_CPP_VALUE = {
- # Basic
- 'DOMString':
- '{v8_value}',
- # Interface types
- 'FlexibleArrayBufferView':
- 'ToFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name})',
- 'Promise':
- 'ScriptPromise::Cast(ScriptState::Current({isolate}), {v8_value})',
- 'ScriptValue':
- 'ScriptValue({isolate}, {v8_value})',
- 'Window':
- 'ToDOMWindow({isolate}, {v8_value})',
- 'XPathNSResolver':
- 'ToXPathNSResolver(ScriptState::Current({isolate}), {v8_value})',
-}
-
-
-def v8_conversion_needs_exception_state(idl_type):
- return (idl_type.is_numeric_type or idl_type.is_enum
- or idl_type.is_dictionary
- or idl_type.is_array_buffer_view_or_typed_array
- or idl_type.has_string_context or
- idl_type.name in ('Boolean', 'ByteString', 'Object', 'USVString'))
-
-
-IdlType.v8_conversion_needs_exception_state = property(
- v8_conversion_needs_exception_state)
-IdlAnnotatedType.v8_conversion_needs_exception_state = property(
- v8_conversion_needs_exception_state)
-IdlArrayOrSequenceType.v8_conversion_needs_exception_state = True
-IdlRecordType.v8_conversion_needs_exception_state = True
-IdlUnionType.v8_conversion_needs_exception_state = True
-
-TRIVIAL_CONVERSIONS = frozenset(
- ['any', 'boolean', 'NodeFilter', 'XPathNSResolver', 'Promise'])
-
-
-def v8_conversion_is_trivial(idl_type):
- # The conversion is a simple expression that returns the converted value and
- # cannot raise an exception.
- return (idl_type.base_type in TRIVIAL_CONVERSIONS
- or idl_type.is_wrapper_type)
-
-
-IdlType.v8_conversion_is_trivial = property(v8_conversion_is_trivial)
-
-
-def native_value_traits_type_name(idl_type,
- extended_attributes,
- in_sequence_or_record=False):
- idl_type = idl_type.preprocessed_type
-
- if idl_type.is_string_type:
- # Strings are handled separately because null and/or undefined are
- # processed by V8StringResource due to the [TreatNullAs] extended
- # attribute and nullable string types.
- name = 'IDL%s' % idl_type.name
- elif idl_type.is_nullable:
- inner_type = idl_type.inner_type
- inner_type_nvt_type = native_value_traits_type_name(
- inner_type, extended_attributes)
- # The IDL compiler has special cases to handle some nullable types in operation
- # parameters, dictionary fields, etc.
- if in_sequence_or_record or inner_type.name == 'Object':
- name = 'IDLNullable<%s>' % inner_type_nvt_type
- else:
- name = inner_type_nvt_type
- elif idl_type.native_array_element_type:
- name = 'IDLSequence<%s>' % native_value_traits_type_name(
- idl_type.native_array_element_type, extended_attributes, True)
- elif idl_type.is_record_type:
- name = 'IDLRecord<%s, %s>' % (native_value_traits_type_name(
- idl_type.key_type, extended_attributes),
- native_value_traits_type_name(
- idl_type.value_type,
- extended_attributes, True))
- elif idl_type.is_basic_type or idl_type.name in ['Object', 'Promise']:
- name = 'IDL%s' % idl_type.name
- elif idl_type.implemented_as is not None:
- name = idl_type.implemented_as
- else:
- name = idl_type.name
- return name
-
-
-def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value,
- variable_name, isolate, for_constructor_callback):
- if idl_type.name == 'void':
- return ''
-
- # Simple types
- idl_type = idl_type.preprocessed_type
- base_idl_type = idl_type.as_union_type.name if idl_type.is_union_type else idl_type.base_type
-
- if 'FlexibleArrayBufferView' in extended_attributes:
- if base_idl_type not in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
- raise ValueError(
- 'Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s'
- % (idl_type.base_type))
- if 'AllowShared' not in extended_attributes:
- raise ValueError(
- '"FlexibleArrayBufferView" extended attribute requires "AllowShared" on %s'
- % (idl_type.base_type))
- base_idl_type = 'FlexibleArrayBufferView'
-
- if 'AllowShared' in extended_attributes and not idl_type.is_array_buffer_view_or_typed_array:
- raise ValueError(
- 'Unrecognized base type for extended attribute "AllowShared": %s' %
- (idl_type.base_type))
-
- if idl_type.is_integer_type:
- arguments = ', '.join([v8_value, 'exception_state'])
- elif idl_type.v8_conversion_needs_exception_state:
- arguments = ', '.join([v8_value, 'exception_state'])
- else:
- arguments = v8_value
-
- if idl_type.has_string_context:
- execution_context = 'bindings::ExecutionContextFromV8Wrappable(impl)'
- if for_constructor_callback:
- execution_context = 'CurrentExecutionContext(info.GetIsolate())'
- cpp_expression_format = 'NativeValueTraits<IDL%s>::NativeValue(%s, %s, exception_state, %s)' % (
- idl_type.name, isolate, v8_value, execution_context)
- elif base_idl_type in V8_VALUE_TO_CPP_VALUE:
- cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type]
- elif idl_type.name == 'ArrayBuffer':
- cpp_expression_format = (
- '{v8_value}->Is{idl_type}() ? '
- 'V8{idl_type}::ToImpl(v8::Local<v8::{idl_type}>::Cast({v8_value})) : 0'
- )
- elif idl_type.is_array_buffer_view_or_typed_array or base_idl_type == 'DataView':
- this_cpp_type = idl_type.cpp_type_args(
- extended_attributes=extended_attributes)
- if 'AllowShared' in extended_attributes:
- cpp_expression_format = (
- 'ToMaybeShared<%s>({isolate}, {v8_value}, exception_state)' %
- this_cpp_type)
- else:
- cpp_expression_format = (
- 'ToNotShared<%s>({isolate}, {v8_value}, exception_state)' %
- this_cpp_type)
- elif idl_type.is_union_type:
- nullable = 'UnionTypeConversionMode::kNullable' if idl_type.includes_nullable_type \
- else 'UnionTypeConversionMode::kNotNullable'
- # We need to consider the moving of the null through the union in order
- # to generate the correct V8* class name.
- this_cpp_type = idl_type.cpp_type_args(
- extended_attributes=extended_attributes)
- cpp_expression_format = '%s::ToImpl({isolate}, {v8_value}, {variable_name}, %s, exception_state)' % \
- (v8_type(this_cpp_type), nullable)
- elif idl_type.use_output_parameter_for_result:
- cpp_expression_format = 'V8{idl_type}::ToImpl({isolate}, {v8_value}, {variable_name}, exception_state)'
- elif idl_type.is_callback_function:
- cpp_expression_format = 'V8{idl_type}::Create({v8_value}.As<v8::Function>())'
- elif idl_type.v8_conversion_needs_exception_state:
- # Effectively, this if branch means everything with v8_conversion_needs_exception_state == True
- # except for unions and dictionary interfaces.
- base_idl_type = native_value_traits_type_name(idl_type,
- extended_attributes)
- cpp_expression_format = (
- 'NativeValueTraits<{idl_type}>::NativeValue({isolate}, {arguments})'
- )
- else:
- cpp_expression_format = (
- 'V8{idl_type}::ToImplWithTypeCheck({isolate}, {v8_value})')
-
- return cpp_expression_format.format(
- arguments=arguments,
- idl_type=base_idl_type,
- v8_value=v8_value,
- variable_name=variable_name,
- isolate=isolate)
-
-
-# FIXME: this function should be refactored, as this takes too many flags.
-def v8_value_to_local_cpp_value(idl_type,
- extended_attributes,
- v8_value,
- variable_name,
- declare_variable=True,
- isolate='info.GetIsolate()',
- bailout_return_value=None,
- use_exception_state=False,
- code_generation_target=None,
- for_constructor_callback=False):
- """Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
-
- this_cpp_type = idl_type.cpp_type_args(
- extended_attributes=extended_attributes, raw_type=True)
- idl_type = idl_type.preprocessed_type
-
- cpp_value = v8_value_to_cpp_value(
- idl_type,
- extended_attributes,
- v8_value,
- variable_name,
- isolate,
- for_constructor_callback=for_constructor_callback)
-
- # Optional expression that returns a value to be assigned to the local variable.
- assign_expression = None
- # Optional void expression executed unconditionally.
- set_expression = None
- # Optional expression that returns true if the conversion fails.
- check_expression = None
- # Optional expression used as the return value when returning. Only
- # meaningful if 'check_expression' is not None.
- return_expression = bailout_return_value
-
- if 'FlexibleArrayBufferView' in extended_attributes:
- if idl_type.base_type not in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
- raise ValueError(
- 'Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s'
- % (idl_type.base_type))
- set_expression = cpp_value
- elif idl_type.is_string_type or idl_type.v8_conversion_needs_exception_state:
- # Types for which conversion can fail and that need error handling.
-
- check_expression = 'exception_state.HadException()'
-
- if idl_type.is_union_type:
- set_expression = cpp_value
- else:
- assign_expression = cpp_value
- # Note: 'not idl_type.v8_conversion_needs_exception_state' implies
- # 'idl_type.is_string_type', but there are types for which both are
- # true (ByteString and USVString), so using idl_type.is_string_type
- # as the condition here would be wrong.
- if not idl_type.v8_conversion_needs_exception_state:
- if use_exception_state:
- check_expression = '!%s.Prepare(exception_state)' % variable_name
- else:
- check_expression = '!%s.Prepare()' % variable_name
- elif not idl_type.v8_conversion_is_trivial and not idl_type.is_callback_function:
- return {
- 'error_message':
- 'no V8 -> C++ conversion for IDL type: %s' % idl_type.name
- }
- else:
- assign_expression = cpp_value
-
- # Types that don't need error handling, and simply assign a value to the
- # local variable.
-
- if (idl_type.is_explicit_nullable
- and code_generation_target == 'attribute_set'):
- this_cpp_type = cpp_template_type('absl::optional', this_cpp_type)
- expr = '{cpp_type}({expr})'.format(
- cpp_type=this_cpp_type, expr=assign_expression)
- assign_expression = ("is_null "
- "? absl::nullopt "
- ": {expr}".format(expr=expr))
-
- return {
- 'assign_expression': assign_expression,
- 'check_expression': check_expression,
- 'cpp_type': this_cpp_type,
- 'cpp_name': variable_name,
- 'declare_variable': declare_variable,
- 'return_expression': return_expression,
- 'set_expression': set_expression,
- }
-
-
-IdlTypeBase.v8_value_to_local_cpp_value = v8_value_to_local_cpp_value
-
-
-def use_output_parameter_for_result(idl_type):
- """True when methods/getters which return the given idl_type should
- take the output argument.
- """
- return idl_type.is_union_type
-
-
-IdlTypeBase.use_output_parameter_for_result = property(
- use_output_parameter_for_result)
-
-################################################################################
-# C++ -> V8
-################################################################################
-
-
-def preprocess_idl_type(idl_type):
- if idl_type.is_nullable:
- return IdlNullableType(idl_type.inner_type.preprocessed_type)
- if idl_type.is_enum:
- # Enumerations are internally DOMStrings
- return IdlType('DOMString')
- if idl_type.base_type == 'any' or idl_type.is_custom_callback_function:
- return IdlType('ScriptValue')
- if idl_type.is_callback_function:
- return idl_type
- return idl_type
-
-
-IdlTypeBase.preprocessed_type = property(preprocess_idl_type)
-
-
-def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes):
- """Returns IDL type and value, with preliminary type conversions applied."""
- idl_type = idl_type.preprocessed_type
- if idl_type.name == 'Promise':
- idl_type = IdlType('ScriptValue')
- if idl_type.base_type in ['long long', 'unsigned long long']:
- # long long and unsigned long long are not representable in ECMAScript;
- # we represent them as doubles.
- is_nullable = idl_type.is_nullable
- idl_type = IdlType('double')
- if is_nullable:
- idl_type = IdlNullableType(idl_type)
- cpp_value = 'static_cast<double>(%s)' % cpp_value
- # HTML5 says that unsigned reflected attributes should be in the range
- # [0, 2^31). When a value isn't in this range, a default value (or 0)
- # should be returned instead.
- extended_attributes = extended_attributes or {}
- if ('Reflect' in extended_attributes
- and idl_type.base_type in ['unsigned long', 'unsigned short']):
- cpp_value = cpp_value.replace('GetUnsignedIntegralAttribute',
- 'GetIntegralAttribute')
- cpp_value = 'std::max(0, static_cast<int>(%s))' % cpp_value
- return idl_type, cpp_value
-
-
-def v8_conversion_type(idl_type, extended_attributes):
- """Returns V8 conversion type, adding any additional includes.
-
- The V8 conversion type is used to select the C++ -> V8 conversion function
- or V8SetReturnValue* function; it can be an idl_type, a cpp_type, or a
- separate name for the type of conversion (e.g., 'DOMWrapper').
- """
- extended_attributes = extended_attributes or {}
-
- # Nullable dictionaries need to be handled differently than either
- # non-nullable dictionaries or unions.
- if idl_type.is_dictionary and idl_type.is_nullable:
- return 'NullableDictionary'
-
- if idl_type.is_dictionary or idl_type.is_union_type:
- return 'DictionaryOrUnion'
-
- # Array or sequence types
- native_array_element_type = idl_type.native_array_element_type
- if native_array_element_type:
- return 'FrozenArray' if idl_type.is_frozen_array else 'sequence'
-
- # Record types.
- if idl_type.is_record_type:
- return 'Record'
-
- # Simple types
- base_idl_type = idl_type.base_type
- # Basic types, without additional includes
- if base_idl_type in CPP_INTEGER_CONVERSION_RULES:
- return CPP_INTEGER_CONVERSION_RULES[base_idl_type]
- if idl_type.is_string_type:
- if idl_type.is_nullable:
- return 'StringOrNull'
- return base_idl_type
- if idl_type.is_basic_type:
- return base_idl_type
- if base_idl_type in ['object', 'ScriptValue']:
- return 'ScriptValue'
-
- # Data type with potential additional includes
- if base_idl_type in V8_SET_RETURN_VALUE: # Special V8SetReturnValue treatment
- return base_idl_type
-
- # Pointer type
- return 'DOMWrapper'
-
-
-IdlTypeBase.v8_conversion_type = v8_conversion_type
-
-V8_SET_RETURN_VALUE = {
- 'boolean':
- 'V8SetReturnValueBool(info, {cpp_value})',
- 'DOMString':
- 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
- 'ByteString':
- 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
- 'USVString':
- 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
- 'StringOrNull':
- 'V8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
- 'void':
- '',
- # All the int types below are converted to (u)int32_t in the V8SetReturnValue{Int,Unsigned}() calls.
- # The 64-bit int types have already been converted to double when V8_SET_RETURN_VALUE is used, so they are not
- # listed here.
- 'int8_t':
- 'V8SetReturnValueInt(info, {cpp_value})',
- 'int16_t':
- 'V8SetReturnValueInt(info, {cpp_value})',
- 'int32_t':
- 'V8SetReturnValueInt(info, {cpp_value})',
- 'uint8_t':
- 'V8SetReturnValueUnsigned(info, {cpp_value})',
- 'uint16_t':
- 'V8SetReturnValueUnsigned(info, {cpp_value})',
- 'uint32_t':
- 'V8SetReturnValueUnsigned(info, {cpp_value})',
- # No special V8SetReturnValue* function (set value directly)
- 'float':
- 'V8SetReturnValue(info, {cpp_value})',
- 'unrestricted float':
- 'V8SetReturnValue(info, {cpp_value})',
- 'double':
- 'V8SetReturnValue(info, {cpp_value})',
- 'unrestricted double':
- 'V8SetReturnValue(info, {cpp_value})',
- # No special V8SetReturnValue* function, but instead convert value to V8
- # and then use general V8SetReturnValue.
- 'sequence':
- 'V8SetReturnValue(info, {cpp_value})',
- 'FrozenArray':
- 'V8SetReturnValue(info, {cpp_value})',
- 'EventHandler':
- 'V8SetReturnValue(info, {cpp_value})',
- 'NodeFilter':
- 'V8SetReturnValue(info, {cpp_value})',
- 'OnBeforeUnloadEventHandler':
- 'V8SetReturnValue(info, {cpp_value})',
- 'OnErrorEventHandler':
- 'V8SetReturnValue(info, {cpp_value})',
- 'ScriptValue':
- 'V8SetReturnValue(info, {cpp_value})',
- # Records.
- 'Record':
- 'V8SetReturnValue(info, ToV8({cpp_value}, info.Holder(), info.GetIsolate()))',
- # DOMWrapper
- 'DOMWrapperForMainWorld':
- 'V8SetReturnValueForMainWorld(info, {cpp_value})',
- 'DOMWrapperFast':
- 'V8SetReturnValueFast(info, {cpp_value}, {script_wrappable})',
- 'DOMWrapperDefault':
- 'V8SetReturnValue(info, {cpp_value})',
- # If [CheckSecurity=ReturnValue] is specified, the returned object must be
- # wrapped in its own realm, which can be different from the realm of the
- # receiver object.
- #
- # [CheckSecurity=ReturnValue] is used only for contentDocument and
- # getSVGDocument attributes of HTML{IFrame,Frame,Object,Embed}Element,
- # and Window.frameElement. Except for Window.frameElement, all interfaces
- # support contentWindow(), so we create a new wrapper in the realm of
- # contentWindow(). Note that DOMWindow* has its own realm and there is no
- # need to pass |creationContext| in for ToV8(DOMWindow*).
- # Window.frameElement is implemented with [Custom].
- 'DOMWrapperAcrossContext':
- ('V8SetReturnValue(info, ToV8({cpp_value}, ' +
- 'ToV8(impl->contentWindow(), v8::Local<v8::Object>(), ' +
- 'info.GetIsolate()).As<v8::Object>(), info.GetIsolate()))'),
- # Note that static attributes and operations do not check whether |this| is
- # an instance of the interface nor |this|'s creation context is the same as
- # the current context. So we must always use the current context as the
- # creation context of the DOM wrapper for the return value.
- 'DOMWrapperStatic':
- 'V8SetReturnValue(info, {cpp_value}, info.GetIsolate()->GetCurrentContext()->Global())',
- # Nullable dictionaries
- 'NullableDictionary':
- 'V8SetReturnValue(info, result)',
- 'NullableDictionaryStatic':
- 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
- # Union types or dictionaries
- 'DictionaryOrUnion':
- 'V8SetReturnValue(info, result)',
- 'DictionaryOrUnionStatic':
- 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
-}
-
-
-def v8_set_return_value(idl_type,
- cpp_value,
- extended_attributes=None,
- script_wrappable='',
- for_main_world=False,
- is_static=False):
- """Returns a statement that converts a C++ value to a V8 value and sets it as a return value.
-
- """
-
- def dom_wrapper_conversion_type():
- if ('CheckSecurity' in extended_attributes
- and extended_attribute_value_contains(
- extended_attributes['CheckSecurity'], 'ReturnValue')):
- return 'DOMWrapperAcrossContext'
- if is_static:
- return 'DOMWrapperStatic'
- if not script_wrappable:
- return 'DOMWrapperDefault'
- if for_main_world:
- return 'DOMWrapperForMainWorld'
- return 'DOMWrapperFast'
-
- idl_type, cpp_value = preprocess_idl_type_and_value(
- idl_type, cpp_value, extended_attributes)
- this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
- # SetReturn-specific overrides
- if this_v8_conversion_type in ('EventHandler', 'NodeFilter',
- 'OnBeforeUnloadEventHandler',
- 'OnErrorEventHandler', 'ScriptValue',
- 'sequence', 'FrozenArray'):
- # Convert value to V8 and then use general V8SetReturnValue
- cpp_value = idl_type.cpp_value_to_v8_value(
- cpp_value, extended_attributes=extended_attributes)
- if this_v8_conversion_type == 'DOMWrapper':
- this_v8_conversion_type = dom_wrapper_conversion_type()
- if is_static and this_v8_conversion_type in ('NullableDictionary',
- 'DictionaryOrUnion'):
- this_v8_conversion_type += 'Static'
-
- format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type]
- statement = format_string.format(
- cpp_value=cpp_value, script_wrappable=script_wrappable)
- return statement
-
-
-IdlTypeBase.v8_set_return_value = v8_set_return_value
-
-CPP_VALUE_TO_V8_VALUE = {
- # Built-in types
- 'DOMString':
- 'V8String({isolate}, {cpp_value})',
- 'ByteString':
- 'V8String({isolate}, {cpp_value})',
- 'USVString':
- 'V8String({isolate}, {cpp_value})',
- 'boolean':
- 'v8::Boolean::New({isolate}, {cpp_value})',
- # All the int types below are converted to (u)int32_t in the v8::Integer::New*() calls.
- # The 64-bit int types have already been converted to double when CPP_VALUE_TO_V8_VALUE is used, so they are not
- # listed here.
- 'int8_t':
- 'v8::Integer::New({isolate}, {cpp_value})',
- 'int16_t':
- 'v8::Integer::New({isolate}, {cpp_value})',
- 'int32_t':
- 'v8::Integer::New({isolate}, {cpp_value})',
- 'uint8_t':
- 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
- 'uint16_t':
- 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
- 'uint32_t':
- 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
- 'float':
- 'v8::Number::New({isolate}, {cpp_value})',
- 'unrestricted float':
- 'v8::Number::New({isolate}, {cpp_value})',
- 'double':
- 'v8::Number::New({isolate}, {cpp_value})',
- 'unrestricted double':
- 'v8::Number::New({isolate}, {cpp_value})',
- 'StringOrNull':
- ('({cpp_value}.IsNull() ? ' + 'v8::Null({isolate}).As<v8::Value>() : ' +
- 'V8String({isolate}, {cpp_value}).As<v8::Value>())'),
- # Special cases
- 'EventHandler':
- 'JSEventHandler::AsV8Value({isolate}, impl, {cpp_value})',
- 'NodeFilter':
- 'ToV8({cpp_value}, {creation_context}, {isolate})',
- 'OnBeforeUnloadEventHandler':
- 'JSEventHandler::AsV8Value({isolate}, impl, {cpp_value})',
- 'OnErrorEventHandler':
- 'JSEventHandler::AsV8Value({isolate}, impl, {cpp_value})',
- 'Record':
- 'ToV8({cpp_value}, {creation_context}, {isolate})',
- 'ScriptValue':
- '{cpp_value}.V8Value()',
- # General
- 'sequence':
- 'ToV8({cpp_value}, {creation_context}, {isolate})',
- 'FrozenArray':
- 'FreezeV8Object(ToV8({cpp_value}, {creation_context}, {isolate}), {isolate})',
- 'DOMWrapper':
- 'ToV8({cpp_value}, {creation_context}, {isolate})',
- # Passing nullable dictionaries isn't a pattern currently used
- # anywhere in the web platform, and more work would be needed in
- # the code generator to distinguish between passing null, and
- # passing an object which happened to not contain any of the
- # dictionary's defined attributes. For now, don't define
- # NullableDictionary here, which will cause an exception to be
- # thrown during code generation if an argument to a method is a
- # nullable dictionary type.
- #
- # Union types or dictionaries
- 'DictionaryOrUnion':
- 'ToV8({cpp_value}, {creation_context}, {isolate})',
-}
-
-
-def cpp_value_to_v8_value(idl_type,
- cpp_value,
- isolate='info.GetIsolate()',
- creation_context='info.Holder()',
- extended_attributes=None):
- """Returns an expression that converts a C++ value to a V8 value."""
- # the isolate parameter is needed for callback interfaces
- idl_type, cpp_value = preprocess_idl_type_and_value(
- idl_type, cpp_value, extended_attributes)
- this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
- format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type]
- statement = format_string.format(
- cpp_value=cpp_value,
- isolate=isolate,
- creation_context=creation_context)
- return statement
-
-
-IdlTypeBase.cpp_value_to_v8_value = cpp_value_to_v8_value
-
-
-def literal_cpp_value(idl_type, idl_literal):
- """Converts an expression that is a valid C++ literal for this type."""
- # FIXME: add validation that idl_type and idl_literal are compatible
- if idl_type.base_type in ('any', 'object') and idl_literal.is_null:
- return 'ScriptValue::CreateNull(script_state->GetIsolate())'
- literal_value = str(idl_literal)
- if idl_type.base_type in ('octet', 'unsigned short', 'unsigned long'):
- return literal_value + 'u'
- if idl_type.is_dictionary and literal_value == '{}':
- return 'MakeGarbageCollected<{}>()'.format(idl_type.base_type)
- return literal_value
-
-
-def union_literal_cpp_value(idl_type, idl_literal):
- if idl_literal.is_null:
- return idl_type.name + '()'
- elif idl_literal.idl_type == 'DOMString':
- member_type = idl_type.string_member_type
- elif idl_literal.idl_type in ('integer', 'float'):
- member_type = idl_type.numeric_member_type
- elif idl_literal.idl_type == 'boolean':
- member_type = idl_type.boolean_member_type
- elif idl_literal.idl_type == 'sequence':
- member_type = idl_type.sequence_member_type
- elif idl_literal.idl_type == 'dictionary':
- member_type = idl_type.dictionary_member_type
- else:
- raise ValueError('Unsupported literal type: ' + idl_literal.idl_type)
-
- return '%s::From%s(%s)' % (idl_type.cpp_type_args(), member_type.name,
- member_type.literal_cpp_value(idl_literal))
-
-
-def array_or_sequence_literal_cpp_value(idl_type, idl_literal):
- # Only support empty sequences.
- if idl_literal.value == '[]':
- return cpp_type(idl_type) + '()'
- raise ValueError('Unsupported literal type: ' + idl_literal.idl_type)
-
-
-IdlType.literal_cpp_value = literal_cpp_value
-IdlUnionType.literal_cpp_value = union_literal_cpp_value
-IdlArrayOrSequenceType.literal_cpp_value = array_or_sequence_literal_cpp_value
-
-_IDL_TYPE_TO_NATIVE_VALUE_TRAITS_TAG_MAP = {
- 'DOMString': 'IDLString',
- 'USVString': 'IDLUSVString',
- 'DOMStringOrNull': 'IDLStringOrNull',
- 'USVStringOrNull': 'IDLUSVStringOrNull',
- 'any': 'ScriptValue',
- 'boolean': 'IDLBoolean',
- 'long': 'IDLLong',
- 'sequence<DOMString>': 'IDLSequence<IDLString>',
- 'unsigned short': 'IDLUnsignedShort',
- 'void': None,
-}
-
-
-def idl_type_to_native_value_traits_tag(idl_type):
- idl_type_str = str(idl_type)
- if idl_type.is_nullable:
- idl_type_str += "OrNull"
- if idl_type_str in _IDL_TYPE_TO_NATIVE_VALUE_TRAITS_TAG_MAP:
- return _IDL_TYPE_TO_NATIVE_VALUE_TRAITS_TAG_MAP[idl_type_str]
- else:
- raise Exception("Type `%s' is not supported." % idl_type_str)
-
-
-################################################################################
-# Utility properties for nullable types
-################################################################################
-
-
-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 and Dictionary types 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 or idl_type.is_enum
- or idl_type.is_interface_type or idl_type.is_callback_interface
- or idl_type.is_callback_function
- or idl_type.is_custom_callback_function or idl_type.is_dictionary
- or idl_type.is_union_type or idl_type.base_type == 'object'
- or idl_type.base_type == 'any')
-
-
-IdlTypeBase.cpp_type_has_null_value = property(cpp_type_has_null_value)
-
-
-def is_implicit_nullable(idl_type):
- # Nullable type where the corresponding C++ type supports a null value.
- return idl_type.is_nullable and idl_type.cpp_type_has_null_value
-
-
-def is_explicit_nullable(idl_type):
- # Nullable type that isn't implicit nullable (see above.) For such types,
- # we use absl::optional<T> or similar explicit ways to represent a null value.
- return idl_type.is_nullable and not idl_type.is_implicit_nullable
-
-
-IdlTypeBase.is_implicit_nullable = property(is_implicit_nullable)
-IdlUnionType.is_implicit_nullable = False
-IdlTypeBase.is_explicit_nullable = property(is_explicit_nullable)
-
-
-def includes_nullable_type_union(idl_type):
- # http://heycam.github.io/webidl/#dfn-includes-a-nullable-type
- return idl_type.number_of_nullable_member_types == 1
-
-
-IdlTypeBase.includes_nullable_type = False
-IdlNullableType.includes_nullable_type = True
-IdlUnionType.includes_nullable_type = property(includes_nullable_type_union)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
deleted file mode 100644
index 95f5bb790e1..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
+++ /dev/null
@@ -1,198 +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.
-
-from utilities import to_snake_case
-import v8_types
-import v8_utilities
-
-UNION_CPP_INCLUDES = frozenset([
- 'base/stl_util.h',
- 'bindings/core/v8/native_value_traits_impl.h',
- 'bindings/core/v8/to_v8_for_core.h',
-])
-
-UNION_H_INCLUDES = frozenset([
- 'bindings/core/v8/dictionary.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',
- 'third_party/abseil-cpp/absl/types/optional.h',
-])
-
-cpp_includes = set()
-header_forward_decls = set()
-header_includes = set()
-
-
-def container_context(union_type, info_provider):
- cpp_includes.clear()
- header_forward_decls.clear()
- header_includes.clear()
- cpp_includes.update(UNION_CPP_INCLUDES)
- header_includes.update(UNION_H_INCLUDES)
- members = []
-
- # These variables refer to member contexts if the given union type has
- # corresponding types. They are used for V8 -> impl conversion.
- array_buffer_type = None
- array_buffer_view_type = None
- array_or_sequence_type = None
- boolean_type = None
- dictionary_type = None
- interface_types = []
- numeric_type = None
- object_type = None
- record_type = None
- string_type = None
- for member in sorted(
- union_type.flattened_member_types, key=lambda m: m.name):
- context = member_context(member, info_provider)
- members.append(context)
- if member.base_type == 'ArrayBuffer':
- if array_buffer_type:
- raise Exception('%s is ambiguous.' % union_type.name)
- array_buffer_type = context
- elif member.base_type == 'ArrayBufferView':
- if array_buffer_view_type:
- raise Exception('%s is ambiguous.' % union_type.name)
- array_buffer_view_type = context
- elif member.is_dictionary:
- if dictionary_type:
- raise Exception('%s is ambiguous.' % union_type.name)
- dictionary_type = context
- elif member.is_array_or_sequence_type:
- if array_or_sequence_type:
- raise Exception('%s is ambiguous.' % union_type.name)
- array_or_sequence_type = context
- elif member.base_type == 'object':
- if object_type or record_type:
- raise Exception('%s is ambiguous.' % union_type.name)
- object_type = context
- elif member.is_record_type:
- if object_type or record_type:
- raise Exception('%s is ambiguous.' % union_type.name)
- record_type = context
- elif member.is_interface_type:
- interface_types.append(context)
- elif member is union_type.boolean_member_type:
- boolean_type = context
- elif member is union_type.numeric_member_type:
- numeric_type = context
- elif member is union_type.string_member_type:
- string_type = context
- else:
- raise Exception(
- '%s is not supported as an union member.' % member.name)
-
- # Nullable restriction checks
- nullable_members = union_type.number_of_nullable_member_types
- if nullable_members > 1:
- raise Exception(
- '%s contains more than one nullable members' % union_type.name)
- if dictionary_type and nullable_members == 1:
- raise Exception(
- '%s has a dictionary and a nullable member' % union_type.name)
-
- cpp_class = union_type.cpp_type
- return {
- 'array_buffer_type': array_buffer_type,
- 'array_buffer_view_type': array_buffer_view_type,
- 'array_or_sequence_type': array_or_sequence_type,
- 'boolean_type': boolean_type,
- 'cpp_class': cpp_class,
- 'cpp_includes': sorted(cpp_includes),
- 'dictionary_type': dictionary_type,
- 'header_includes': sorted(header_includes),
- 'header_forward_decls': sorted(header_forward_decls),
- 'includes_nullable_type': union_type.includes_nullable_type,
- 'interface_types': interface_types,
- 'members': members,
- 'numeric_type': numeric_type,
- 'object_type': object_type,
- 'record_type': record_type,
- 'string_type': string_type,
- 'type_string': str(union_type),
- 'v8_class': v8_types.v8_type(cpp_class),
- }
-
-
-def _update_includes_and_forward_decls(member, info_provider):
- interface_info = info_provider.interfaces_info.get(member.name, None)
- if interface_info:
- cpp_includes.update(
- interface_info.get('dependencies_include_paths', []))
- # We need complete types for IDL dictionaries in union containers.
- if member.is_dictionary or member.is_array_buffer_view_or_typed_array:
- header_includes.update(member.includes_for_type())
- else:
- cpp_includes.update(member.includes_for_type())
- header_forward_decls.add(member.implemented_as)
- else:
- if member.is_record_type:
- _update_includes_and_forward_decls(member.key_type, info_provider)
- _update_includes_and_forward_decls(member.value_type,
- info_provider)
- elif member.is_array_or_sequence_type:
- _update_includes_and_forward_decls(member.element_type,
- info_provider)
- cpp_includes.add('bindings/core/v8/script_iterator.h')
- elif member.is_union_type:
- # Reaching this block means we have a union that is inside a
- # record or sequence.
- header_forward_decls.add(member.name)
- cpp_includes.update(
- [info_provider.include_path_for_union_types(member)])
- cpp_includes.update(member.includes_for_type())
-
-
-def member_context(member, info_provider):
- _update_includes_and_forward_decls(member, info_provider)
- if member.is_nullable:
- member = member.inner_type
- type_name = (member.inner_type
- if member.is_annotated_type else member).name
- # When converting a sequence or frozen array, we need to call the GetMethod(V, @@iterator)
- # ES abstract operation and then use the result of that call to create a sequence from an
- # iterable. For the purposes of this method, it means we need to pass |script_iterator|
- # rather than |v8_value| in v8_value_to_local_cpp_value().
- if member.is_array_or_sequence_type:
- v8_value_name = 'std::move(script_iterator)'
- else:
- v8_value_name = 'v8_value'
- return {
- 'cpp_name':
- to_snake_case(v8_utilities.cpp_name(member)),
- 'cpp_type':
- member.cpp_type_args(used_in_cpp_sequence=True),
- 'cpp_local_type':
- member.cpp_type,
- 'cpp_value_to_v8_value':
- member.cpp_value_to_v8_value(
- cpp_value='impl.GetAs%s()' % type_name,
- isolate='isolate',
- creation_context='creationContext'),
- 'enum_type':
- member.enum_type,
- 'enum_values':
- member.enum_values,
- 'is_array_buffer_or_view_type':
- member.is_array_buffer_or_view,
- 'is_array_buffer_view_or_typed_array':
- member.is_array_buffer_view_or_typed_array,
- 'is_traceable':
- member.is_traceable,
- 'rvalue_cpp_type':
- member.cpp_type_args(used_as_rvalue_type=True),
- 'specific_type_enum':
- 'k' + member.name,
- 'type_name':
- type_name,
- 'v8_value_to_local_cpp_value':
- member.v8_value_to_local_cpp_value({},
- v8_value_name,
- 'cpp_value',
- isolate='isolate',
- use_exception_state=True)
- }
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
deleted file mode 100644
index 7432ab4e17f..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
+++ /dev/null
@@ -1,716 +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.
-"""Functions shared by various parts of the code generator.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
-"""
-
-import os
-import re
-import sys
-
-from blinkbuild.name_style_converter import NameStyleConverter
-from idl_types import IdlTypeBase
-import idl_types
-from idl_definitions import Exposure, IdlInterface, IdlAttribute
-from utilities import to_snake_case
-from v8_globals import includes
-
-ACRONYMS = [
- 'CSSOM', # must come *before* CSS to match full acronym
- 'CSS',
- 'HTML',
- 'IME',
- 'JS',
- 'SMIL',
- 'SVG',
- 'URL',
- 'WOFF',
- 'XML',
- 'XSLT',
-]
-
-################################################################################
-# Extended attribute parsing
-################################################################################
-
-
-def extended_attribute_value_contains(extended_attribute_value, key):
- return (extended_attribute_value == key
- or (isinstance(extended_attribute_value, list)
- and key in extended_attribute_value))
-
-
-def has_extended_attribute(definition_or_member, extended_attribute_list):
- return any(extended_attribute in definition_or_member.extended_attributes
- for extended_attribute in extended_attribute_list)
-
-
-def has_extended_attribute_value(definition_or_member, name, value):
- extended_attributes = definition_or_member.extended_attributes
- return (name in extended_attributes and extended_attribute_value_contains(
- extended_attributes[name], value))
-
-
-def extended_attribute_value_as_list(definition_or_member, name):
- extended_attributes = definition_or_member.extended_attributes
- if name not in extended_attributes:
- return None
- value = extended_attributes[name]
- if isinstance(value, list):
- return value
- return [value]
-
-
-################################################################################
-# String handling
-################################################################################
-
-
-def capitalize(name):
- """Capitalize first letter or initial acronym (used in setter names)."""
- for acronym in ACRONYMS:
- if name.startswith(acronym.lower()):
- return name.replace(acronym.lower(), acronym)
- return name[0].upper() + name[1:]
-
-
-def strip_suffix(string, suffix):
- if not suffix or not string.endswith(suffix):
- return string
- return string[:-len(suffix)]
-
-
-def uncapitalize(name):
- """Uncapitalizes first letter or initial acronym (used in method names).
-
- E.g., 'SetURL' becomes 'setURL', but 'URLFoo' becomes 'urlFoo'.
- """
- for acronym in ACRONYMS:
- if name.startswith(acronym):
- return name.replace(acronym, acronym.lower())
- return name[0].lower() + name[1:]
-
-
-def runtime_enabled_function(name):
- """Returns a function call of a runtime enabled feature."""
- return 'RuntimeEnabledFeatures::%sEnabled()' % name
-
-
-################################################################################
-# C++
-################################################################################
-
-
-def scoped_name(interface, definition, base_name):
- # partial interfaces are implemented as separate classes, with their members
- # implemented as static member functions
- partial_interface_implemented_as = definition.extended_attributes.get(
- 'PartialInterfaceImplementedAs')
- if partial_interface_implemented_as:
- return '%s::%s' % (partial_interface_implemented_as, base_name)
- if (definition.is_static
- or definition.name in ('Constructor', 'NamedConstructor')):
- return '%s::%s' % (cpp_name(interface), base_name)
- return 'impl->%s' % base_name
-
-
-def v8_class_name(interface):
- return 'V8' + interface.name
-
-
-def v8_class_name_or_partial(interface):
- class_name = v8_class_name(interface)
- if interface.is_partial:
- return ''.join([class_name, 'Partial'])
- return class_name
-
-
-def build_basename(name, prefix=None):
- basename = to_snake_case(name)
- if prefix:
- basename = prefix + basename
- return basename
-
-
-def binding_header_filename(name):
- """Returns a binding header filename for the specified interface name.
-
- E.g. 'NodeList' -> 'v8_node_list.h'
- """
- return build_basename(name, prefix='v8_') + '.h'
-
-
-################################################################################
-# Specific extended attributes
-################################################################################
-
-
-# [ActivityLogging]
-def activity_logging_world_list(member, access_type=''):
- """Returns a set of world suffixes for which a definition member has activity logging, for specified access type.
-
- access_type can be 'Getter' or 'Setter' if only checking getting or setting.
- """
- extended_attributes = member.extended_attributes
- if 'LogActivity' not in extended_attributes:
- return set()
- log_activity = extended_attributes['LogActivity']
- if log_activity and not log_activity.startswith(access_type):
- return set()
-
- includes.add('platform/bindings/v8_dom_activity_logger.h')
- if 'LogAllWorlds' in extended_attributes:
- return set(['', 'ForMainWorld'])
- return set(['']) # At minimum, include isolated worlds.
-
-
-# [ActivityLogging]
-def activity_logging_world_check(member):
- """Returns if an isolated world check is required when generating activity
- logging code.
-
- The check is required when there is no per-world binding code and logging is
- required only for isolated world.
- """
- extended_attributes = member.extended_attributes
- if 'LogActivity' not in extended_attributes:
- return False
- if ('PerWorldBindings' not in extended_attributes
- and 'LogAllWorlds' not in extended_attributes):
- return True
- return False
-
-
-# [CallWith]
-CALL_WITH_ARGUMENTS = {
- 'Isolate': 'info.GetIsolate()',
- 'ScriptState': 'script_state',
- 'ExecutionContext': 'execution_context',
- 'Document': 'document',
- 'ThisValue': 'ScriptValue(info.GetIsolate(), info.Holder())',
-}
-# List because key order matters, as we want arguments in deterministic order
-CALL_WITH_VALUES = [
- 'Isolate',
- 'ScriptState',
- 'ExecutionContext',
- 'Document',
- 'ThisValue',
-]
-
-
-def call_with_arguments(call_with_values):
- if not call_with_values:
- return []
- return [
- CALL_WITH_ARGUMENTS[value] for value in CALL_WITH_VALUES
- if extended_attribute_value_contains(call_with_values, value)
- ]
-
-
-# [Constructor], [NamedConstructor]
-def is_constructor_attribute(member):
- # TODO(yukishiino): replace this with [Constructor] and [NamedConstructor] extended attribute
- return (type(member) == IdlAttribute
- and member.idl_type.name.endswith('Constructor'))
-
-
-# [DeprecateAs]
-def deprecate_as(member):
- extended_attributes = member.extended_attributes
- if 'DeprecateAs' not in extended_attributes:
- return None
- includes.add('core/frame/deprecation.h')
- return extended_attributes['DeprecateAs']
-
-
-# [Exposed]
-EXPOSED_EXECUTION_CONTEXT_METHOD = {
- 'AnimationWorklet': 'IsAnimationWorkletGlobalScope',
- 'AudioWorklet': 'IsAudioWorkletGlobalScope',
- 'DedicatedWorker': 'IsDedicatedWorkerGlobalScope',
- 'LayoutWorklet': 'IsLayoutWorkletGlobalScope',
- 'PaintWorklet': 'IsPaintWorkletGlobalScope',
- 'ServiceWorker': 'IsServiceWorkerGlobalScope',
- 'SharedWorker': 'IsSharedWorkerGlobalScope',
- 'Window': 'IsWindow',
- 'Worker': 'IsWorkerGlobalScope',
- 'Worklet': 'IsWorkletGlobalScope',
-}
-
-EXPOSED_WORKERS = set([
- 'DedicatedWorker',
- 'SharedWorker',
- 'ServiceWorker',
-])
-
-
-class ExposureSet(object):
- """An ExposureSet is a collection of Exposure instructions."""
-
- def __init__(self, exposures=None):
- self.exposures = set(exposures) if exposures else set()
-
- def issubset(self, other):
- """Returns true if |self|'s exposure set is a subset of
- |other|'s exposure set. This function doesn't care about
- RuntimeEnabled."""
- self_set = self._extended(set(e.exposed for e in self.exposures))
- other_set = self._extended(set(e.exposed for e in other.exposures))
- return self_set.issubset(other_set)
-
- @staticmethod
- def _extended(target):
- if EXPOSED_WORKERS.issubset(target):
- return target | set(['Worker'])
- elif 'Worker' in target:
- return target | EXPOSED_WORKERS
- return target
-
- def add(self, exposure):
- self.exposures.add(exposure)
-
- def __len__(self):
- return len(self.exposures)
-
- def __iter__(self):
- return self.exposures.__iter__()
-
- @staticmethod
- def _code(exposure):
- condition = ('execution_context->%s()' %
- EXPOSED_EXECUTION_CONTEXT_METHOD[exposure.exposed])
- if exposure.runtime_enabled is not None:
- runtime_enabled = (runtime_enabled_function(
- exposure.runtime_enabled))
- return '({0} && {1})'.format(condition, runtime_enabled)
- return condition
-
- def code(self):
- if len(self.exposures) == 0:
- return None
- # We use sorted here to deflake output.
- return ' || '.join(sorted(self._code(e) for e in self.exposures))
-
-
-def exposed(member, interface):
- """Returns a C++ code that checks if a method/attribute/etc is exposed.
-
- When the Exposed attribute contains RuntimeEnabledFeatures (i.e.
- Exposed(Arguments) form is given), the code contains check for them as
- well.
-
- EXAMPLE: [Exposed=Window, RuntimeEnabledFeature=Feature1]
- => context->IsWindow()
-
- EXAMPLE: [Exposed(Window Feature1, Window Feature2)]
- => context->IsWindow() && RuntimeEnabledFeatures::Feature1Enabled() ||
- context->IsWindow() && RuntimeEnabledFeatures::Feature2Enabled()
- """
- exposure_set = ExposureSet(
- extended_attribute_value_as_list(member, 'Exposed'))
- interface_exposure_set = ExposureSet(
- extended_attribute_value_as_list(interface, 'Exposed'))
- for e in exposure_set:
- if e.exposed not in EXPOSED_EXECUTION_CONTEXT_METHOD:
- raise ValueError('Invalid execution context: %s' % e.exposed)
-
- # Methods must not be exposed to a broader scope than their interface.
- if not exposure_set.issubset(interface_exposure_set):
- raise ValueError(
- 'Interface members\' exposure sets must be a subset of the interface\'s.'
- )
-
- return exposure_set.code()
-
-
-# [CrossOriginIsolated]
-def cross_origin_isolated(member, interface):
- """Returns C++ code that checks whether an interface/method/attribute/etc. is exposed
- to the current context. Requires that the surrounding code defines an |is_cross_origin_isolated|
- variable prior to this check."""
- member_is_cross_origin_isolated = 'CrossOriginIsolated' in member.extended_attributes
- interface_is_cross_origin_isolated = (
- (member.defined_in is None or member.defined_in == interface.name)
- and 'CrossOriginIsolated' in interface.extended_attributes)
-
- if not (member_is_cross_origin_isolated
- or interface_is_cross_origin_isolated):
- return None
-
- return 'is_cross_origin_isolated'
-
-
-# [DirectSocketEnabled]
-def direct_socket_enabled(member, interface):
- """Returns C++ code that checks whether an interface/method/attribute/etc.
- is exposed to the current context. Requires that the surrounding code
- defines an |is_direct_socket_enabled| variable prior to this check."""
- member_is_direct_socket_enabled = (
- 'DirectSocketEnabled' in member.extended_attributes)
- interface_is_direct_socket_enabled = (
- (member.defined_in is None or member.defined_in == interface.name)
- and 'DirectSocketEnabled' in interface.extended_attributes)
-
- if not (member_is_direct_socket_enabled
- or interface_is_direct_socket_enabled):
- return None
-
- return 'is_direct_socket_enabled'
-
-
-# [SecureContext]
-def secure_context(member, interface):
- """Returns C++ code that checks whether an interface/method/attribute/etc. is exposed
- to the current context. Requires that the surrounding code defines an |is_secure_context|
- variable prior to this check."""
- member_is_secure_context = 'SecureContext' in member.extended_attributes
- interface_is_secure_context = (
- (member.defined_in is None or member.defined_in == interface.name)
- and 'SecureContext' in interface.extended_attributes)
-
- if not (member_is_secure_context or interface_is_secure_context):
- return None
-
- conditions = ['is_secure_context']
-
- if member_is_secure_context:
- conditional = member.extended_attributes['SecureContext']
- if conditional:
- conditions.append('!{}'.format(
- runtime_enabled_function(conditional)))
-
- if interface_is_secure_context:
- conditional = interface.extended_attributes['SecureContext']
- if conditional:
- conditions.append('!{}'.format(
- runtime_enabled_function(conditional)))
-
- return ' || '.join(conditions)
-
-
-# [ImplementedAs]
-def cpp_name(definition_or_member):
- extended_attributes = definition_or_member.extended_attributes
- if extended_attributes and 'ImplementedAs' in extended_attributes:
- return extended_attributes['ImplementedAs']
- # WebIDL identifiers can contain hyphens[1], but C++ identifiers cannot.
- # Therefore camelCase hyphen-containing identifiers.
- #
- # [1] https://heycam.github.io/webidl/#prod-identifier
- if '-' in definition_or_member.name:
- return NameStyleConverter(
- definition_or_member.name).to_lower_camel_case()
- return definition_or_member.name
-
-
-def cpp_name_from_interfaces_info(name, interfaces_info):
- return interfaces_info.get(name, {}).get('implemented_as') or name
-
-
-def cpp_name_or_partial(interface):
- cpp_class_name = cpp_name(interface)
- if interface.is_partial:
- return ''.join([cpp_class_name, 'Partial'])
- return cpp_class_name
-
-
-def cpp_encoded_property_name(member):
- """
- Returns a property name that the bindings generator can use in generated
- code internally.
-
- Note that Web IDL allows '-' (hyphen-minus) and '_' (low line) in
- identifiers but C++ does not allow or recommend them. This function
- encodes these characters.
- """
- property_name = member.name
- # We're optimistic about name conflict. It's highly unlikely that these
- # replacements will cause a conflict.
- assert "Dec45" not in property_name
- assert "Dec95" not in property_name
- property_name = property_name.replace("-", "Dec45")
- property_name = property_name.replace("_", "Dec95")
- return property_name
-
-
-# [MeasureAs]
-def measure_as(definition_or_member, interface):
- extended_attributes = definition_or_member.extended_attributes
- if 'MeasureAs' in extended_attributes:
- includes.add('core/frame/web_feature.h')
- includes.add('platform/instrumentation/use_counter.h')
- return lambda suffix: extended_attributes['MeasureAs']
- if 'Measure' in extended_attributes:
- includes.add('core/frame/web_feature.h')
- includes.add('platform/instrumentation/use_counter.h')
- measure_as_name = capitalize(definition_or_member.name)
- if interface is not None:
- measure_as_name = '%s_%s' % (capitalize(interface.name),
- measure_as_name)
- return lambda suffix: 'V8%s_%s' % (measure_as_name, suffix)
- return None
-
-
-# [HighEntropy]
-def high_entropy(definition_or_member):
- extended_attributes = definition_or_member.extended_attributes
- if 'HighEntropy' in extended_attributes:
- includes.add('core/frame/dactyloscoper.h')
- if not ('Measure' in extended_attributes
- or 'MeasureAs' in extended_attributes):
- raise Exception(
- '%s specified [HighEntropy], but does not include '
- 'either [Measure] or [MeasureAs]' % definition_or_member.name)
- if extended_attributes['HighEntropy'] == 'Direct':
- return 'Direct'
- return True
- return False
-
-
-# [RuntimeEnabled]
-def _is_origin_trial_feature(feature_name, runtime_features):
- assert feature_name in runtime_features, feature_name + ' is not a runtime feature.'
- feature = runtime_features[feature_name]
- return feature['in_origin_trial']
-
-
-def origin_trial_feature_name(definition_or_member, runtime_features):
- """
- Returns the name of the origin trial feature if found, None otherwise.
- Looks for origin trial feature specified by the RuntimeEnabled attribute.
- """
- extended_attributes = definition_or_member.extended_attributes
- feature_name = extended_attributes.get('RuntimeEnabled')
- if feature_name and _is_origin_trial_feature(feature_name,
- runtime_features):
- return feature_name
-
-
-def origin_trial_function_call(feature_name, execution_context=None):
- """Returns a function call to determine if an origin trial is enabled."""
- return 'RuntimeEnabledFeatures::{feature_name}Enabled({context})'.format(
- feature_name=feature_name,
- context=execution_context
- if execution_context else "execution_context")
-
-
-# [ContextEnabled]
-def context_enabled_feature_name(definition_or_member):
- return definition_or_member.extended_attributes.get('ContextEnabled')
-
-
-# [RuntimeCallStatsCounter]
-def rcs_counter_name(member, generic_counter_name):
- extended_attribute_defined = 'RuntimeCallStatsCounter' in member.extended_attributes
- if extended_attribute_defined:
- counter = 'k' + member.extended_attributes['RuntimeCallStatsCounter']
- else:
- counter = generic_counter_name
- return (counter, extended_attribute_defined)
-
-
-# [RuntimeEnabled]
-def runtime_enabled_feature_name(definition_or_member, runtime_features):
- extended_attributes = definition_or_member.extended_attributes
- feature_name = extended_attributes.get('RuntimeEnabled')
- if feature_name and not _is_origin_trial_feature(feature_name,
- runtime_features):
- includes.add('platform/runtime_enabled_features.h')
- return feature_name
-
-
-# [LegacyUnforgeable]
-def is_unforgeable(member):
- return 'LegacyUnforgeable' in member.extended_attributes
-
-
-# [LegacyUnforgeable], [Global]
-def on_instance(interface, member):
- """Returns True if the interface's member needs to be defined on every
- instance object.
-
- The following members must be defined on an instance object.
- - [LegacyUnforgeable] members
- - regular members of [Global] interfaces
- """
- if member.is_static:
- return False
-
- # TODO(yukishiino): Remove a hack for ToString once we support
- # Symbol.ToStringTag.
- if interface.name == 'Window' and member.name == 'ToString':
- return False
-
- # TODO(yukishiino): Implement "interface object" and its [[Call]] method
- # in a better way. Then we can get rid of this hack.
- if is_constructor_attribute(member):
- return True
-
- if ('Global' in interface.extended_attributes
- or 'LegacyUnforgeable' in member.extended_attributes):
- return True
- return False
-
-
-def on_prototype(interface, member):
- """Returns True if the interface's member needs to be defined on the
- prototype object.
-
- Most members are defined on the prototype object. Exceptions are as
- follows.
- - static members (optional)
- - [LegacyUnforgeable] members
- - members of [Global] interfaces
- - named properties of [Global] interfaces
- """
- if member.is_static:
- return False
-
- # TODO(yukishiino): Remove a hack for toString once we support
- # Symbol.toStringTag.
- if (interface.name == 'Window' and member.name == 'toString'):
- return True
-
- # TODO(yukishiino): Implement "interface object" and its [[Call]] method
- # in a better way. Then we can get rid of this hack.
- if is_constructor_attribute(member):
- return False
-
- if ('Global' in interface.extended_attributes
- or 'LegacyUnforgeable' in member.extended_attributes):
- return False
- return True
-
-
-# static, const
-def on_interface(interface, member):
- """Returns True if the interface's member needs to be defined on the
- interface object.
-
- The following members must be defiend on an interface object.
- - static members
- """
- if member.is_static:
- return True
- return False
-
-
-################################################################################
-# Indexed properties
-# http://heycam.github.io/webidl/#idl-indexed-properties
-################################################################################
-
-
-def indexed_property_getter(interface):
- try:
- # Find indexed property getter, if present; has form:
- # getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1)
- return next(
- method for method in interface.operations
- if ('getter' in method.specials and len(method.arguments) == 1
- and str(method.arguments[0].idl_type) == 'unsigned long'))
- except StopIteration:
- return None
-
-
-def indexed_property_setter(interface):
- try:
- # Find indexed property setter, if present; has form:
- # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE ARG2)
- return next(
- method for method in interface.operations
- if ('setter' in method.specials and len(method.arguments) == 2
- and str(method.arguments[0].idl_type) == 'unsigned long'))
- except StopIteration:
- return None
-
-
-def indexed_property_deleter(interface):
- try:
- # Find indexed property deleter, if present; has form:
- # deleter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG)
- return next(
- method for method in interface.operations
- if ('deleter' in method.specials and len(method.arguments) == 1
- and str(method.arguments[0].idl_type) == 'unsigned long'))
- except StopIteration:
- return None
-
-
-################################################################################
-# Named properties
-# http://heycam.github.io/webidl/#idl-named-properties
-################################################################################
-
-
-def named_property_getter(interface):
- try:
- # Find named property getter, if present; has form:
- # getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1)
- getter = next(
- method for method in interface.operations
- if ('getter' in method.specials and len(method.arguments) == 1
- and str(method.arguments[0].idl_type) == 'DOMString'))
- getter.name = getter.name or 'AnonymousNamedGetter'
- return getter
- except StopIteration:
- return None
-
-
-def named_property_setter(interface):
- try:
- # Find named property setter, if present; has form:
- # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2)
- return next(
- method for method in interface.operations
- if ('setter' in method.specials and len(method.arguments) == 2
- and str(method.arguments[0].idl_type) == 'DOMString'))
- except StopIteration:
- return None
-
-
-def named_property_deleter(interface):
- try:
- # Find named property deleter, if present; has form:
- # deleter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG)
- return next(
- method for method in interface.operations
- if ('deleter' in method.specials and len(method.arguments) == 1
- and str(method.arguments[0].idl_type) == 'DOMString'))
- except StopIteration:
- return None
-
-
-IdlInterface.indexed_property_getter = property(indexed_property_getter)
-IdlInterface.indexed_property_setter = property(indexed_property_setter)
-IdlInterface.indexed_property_deleter = property(indexed_property_deleter)
-IdlInterface.named_property_getter = property(named_property_getter)
-IdlInterface.named_property_setter = property(named_property_setter)
-IdlInterface.named_property_deleter = property(named_property_deleter)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/validate_web_idl.py b/chromium/third_party/blink/renderer/bindings/scripts/validate_web_idl.py
index f3b980744ee..671e23875ce 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/validate_web_idl.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/validate_web_idl.py
@@ -32,7 +32,8 @@ def parse_options():
]
for required_option_name in required_option_names:
if getattr(options, required_option_name) is None:
- parser.error("--{} is a required option.".format(opt_name))
+ parser.error(
+ "--{} is a required option.".format(required_option_name))
return options, args
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
index a2d17cc577d..0b77592e80b 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
@@ -70,7 +70,6 @@ from .operation import Operation
from .operation import OperationGroup
from .runtime_enabled_features import RuntimeEnabledFeatures
from .typedef import Typedef
-from .union import NewUnion
from .union import Union
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py
index 7c5e759f5b3..f5d59129449 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py
@@ -4,8 +4,6 @@
from . import file_io
from .typedef import Typedef
-from .union import BackwardCompatibleUnion
-from .union import NewUnion
from .union import Union
from .user_defined_type import UserDefinedType
@@ -36,7 +34,6 @@ class DatabaseBody(object):
NAMESPACE = 'namespace'
TYPEDEF = 'typedef'
UNION = 'union'
- NEW_UNION = 'new union' # Will replace UNION.
_ALL_ENTRIES = (
CALLBACK_FUNCTION,
@@ -48,7 +45,6 @@ class DatabaseBody(object):
NAMESPACE,
TYPEDEF,
UNION,
- NEW_UNION, # Will replace UNION.
)
@classmethod
@@ -61,9 +57,7 @@ class DatabaseBody(object):
self._defs[kind] = {}
def register(self, kind, user_defined_type):
- assert isinstance(
- user_defined_type,
- (Typedef, BackwardCompatibleUnion, NewUnion, UserDefinedType))
+ assert isinstance(user_defined_type, (Typedef, Union, UserDefinedType))
assert kind in DatabaseBody.Kind.values()
try:
self.find_by_identifier(user_defined_type.identifier)
@@ -161,9 +155,5 @@ class Database(object):
"""Returns all union type definitions."""
return self._view_by_kind(Database._Kind.UNION)
- @property
- def new_union_types(self):
- return self.union_types
-
def _view_by_kind(self, kind):
return list(self._impl.find_by_kind(kind).values())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
index 0d5b5792f69..a480c3fbc31 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
@@ -3,12 +3,7 @@
# found in the LICENSE file.
import os
-import sys
-
-if sys.version_info.major == 2:
- import cPickle as pickle # 'cPickle' is faster than 'pickle' on Py2
-else:
- import pickle
+import pickle
def read_pickle_file(filepath):
@@ -25,9 +20,7 @@ def write_pickle_file_if_changed(filepath, obj):
Returns True if the object is written to the file, and False if skipped.
"""
- # TODO(crbug.com/1112471): Drop protocol=2 when we're no longer
- # compiling anything using Python2.
- return write_to_file_if_changed(filepath, pickle.dumps(obj, protocol=2))
+ return write_to_file_if_changed(filepath, pickle.dumps(obj))
def write_to_file_if_changed(filepath, contents):
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
index 5047d4af13a..e73136e859d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
@@ -29,8 +29,7 @@ from .namespace import Namespace
from .operation import OperationGroup
from .reference import RefByIdFactory
from .typedef import Typedef
-from .union import BackwardCompatibleUnion
-from .union import NewUnion
+from .union import Union
from .user_defined_type import StubUserDefinedType
from .user_defined_type import UserDefinedType
@@ -542,10 +541,18 @@ class IdlCompiler(object):
for overload in group):
group.extended_attributes.append(
ExtendedAttribute(key=key))
- if all((overload.extended_attributes.value_of('Affects') ==
- 'Nothing') for overload in group):
+
+ affects_values = set()
+ for overload in group:
+ affects_values.add(
+ overload.extended_attributes.value_of('Affects'))
+ assert len(affects_values) == 1, (
+ "Overloaded operations have inconsistent extended "
+ "attributes of [Affects].")
+ affects_value = affects_values.pop()
+ if affects_value:
group.extended_attributes.append(
- ExtendedAttribute(key='Affects', values='Nothing'))
+ ExtendedAttribute(key='Affects', values=affects_value))
def _calculate_group_exposure(self):
old_irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.CALLBACK_INTERFACE,
@@ -767,18 +774,18 @@ class IdlCompiler(object):
grouped_unions = {} # {unique token: list of union types}
for union_type in all_union_types:
- token = NewUnion.unique_token(union_type)
+ token = Union.unique_token(union_type)
grouped_unions.setdefault(token, []).append(union_type)
irs = {} # {token: Union.IR}
for token, union_types in grouped_unions.items():
- irs[token] = NewUnion.IR(token, union_types)
+ irs[token] = Union.IR(token, union_types)
all_typedefs = self._db.find_by_kind(DatabaseBody.Kind.TYPEDEF)
for typedef in all_typedefs.values():
if not typedef.idl_type.is_union:
continue
- token = NewUnion.unique_token(typedef.idl_type)
+ token = Union.unique_token(typedef.idl_type)
irs[token].typedefs.append(typedef)
for ir_i in irs.values():
@@ -787,54 +794,4 @@ class IdlCompiler(object):
ir_i.sub_union_irs.append(ir_j)
for ir in sorted(irs.values()):
- self._db.register(DatabaseBody.Kind.UNION, NewUnion(ir))
-
- def _create_backward_compatible_public_unions(self):
- all_union_types = [] # all instances of UnionType
-
- def collect_unions(idl_type):
- if idl_type.is_union:
- all_union_types.append(idl_type)
-
- self._idl_type_factory.for_each(collect_unions)
-
- def unique_key(union_type):
- """
- Returns an unique (but meaningless) key. Returns the same key for
- the identical union types.
- """
- # TODO(peria, yukishiino): Produce unique union names. Trying to
- # produce the names compatible to the old bindings generator for
- # the time being.
- key_pieces = []
-
- def flatten_member_types(idl_type):
- idl_type = idl_type.unwrap()
- if idl_type.is_union:
- for member_type in idl_type.member_types:
- flatten_member_types(member_type)
- else:
- key_pieces.append(idl_type.syntactic_form)
-
- flatten_member_types(union_type)
- return '|'.join(key_pieces)
-
- grouped_unions = {} # {unique key: list of union types}
- for union_type in all_union_types:
- key = unique_key(union_type)
- grouped_unions.setdefault(key, []).append(union_type)
-
- grouped_typedefs = {} # {unique key: list of typedefs to the union}
- all_typedefs = self._db.find_by_kind(DatabaseBody.Kind.TYPEDEF)
- for typedef in all_typedefs.values():
- if not typedef.idl_type.is_union:
- continue
- key = unique_key(typedef.idl_type)
- grouped_typedefs.setdefault(key, []).append(typedef)
-
- for key, union_types in grouped_unions.items():
- self._db.register(
- DatabaseBody.Kind.UNION,
- BackwardCompatibleUnion(union_types=union_types,
- typedef_backrefs=grouped_typedefs.get(
- key, [])))
+ self._db.register(DatabaseBody.Kind.UNION, Union(ir))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
index f01c2220da7..e1b469d349d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -570,10 +570,6 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
return None
@property
- def new_union_definition_object(self):
- return None
-
- @property
def union_definition_object(self):
"""
Returns an object that represents an union or None.
@@ -608,8 +604,9 @@ class SimpleType(IdlType):
_NUMERIC_TYPES = _FLOATING_POINT_NUMERIC_TYPES + _INTEGER_TYPES
_STRING_TYPES = ('DOMString', 'ByteString', 'USVString')
_TYPED_ARRAY_TYPES = ('Int8Array', 'Int16Array', 'Int32Array',
- 'Uint8Array', 'Uint16Array', 'Uint32Array',
- 'Uint8ClampedArray', 'Float32Array', 'Float64Array')
+ 'BigInt64Array', 'Uint8Array', 'Uint16Array',
+ 'Uint32Array', 'BigUint64Array', 'Uint8ClampedArray',
+ 'Float32Array', 'Float64Array')
# ArrayBufferView is not defined as a buffer source type in Web IDL, it's
# defined as an union type of all typed array types. However, practically
# it's much more convenient and reasonable for most of (if not all) use
@@ -1191,7 +1188,6 @@ class UnionType(IdlType):
debug_info=debug_info,
pass_key=pass_key)
self._member_types = tuple(member_types)
- self._new_union_definition_object = None
self._union_definition_object = None
def __eq__(self, other):
@@ -1266,17 +1262,6 @@ class UnionType(IdlType):
return set(flatten(self))
@property
- def new_union_definition_object(self):
- return self._new_union_definition_object
-
- def set_new_union_definition_object(self, union_definition_object):
- # In Python2, we need to avoid circular imports.
- from .union import NewUnion
- assert isinstance(union_definition_object, NewUnion)
- assert self._new_union_definition_object is None
- self._new_union_definition_object = union_definition_object
-
- @property
def union_definition_object(self):
return self._union_definition_object
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
index 936588a75c5..8c7f1542eb9 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
@@ -916,9 +916,11 @@ class _IRBuilder(object):
'Int8Array',
'Int16Array',
'Int32Array',
+ 'BigInt64Array',
'Uint8Array',
'Uint16Array',
'Uint32Array',
+ 'BigUint64Array',
'Uint8ClampedArray',
'Float32Array',
'Float64Array',
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py
index 49baae0d8df..526d6c08220 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py
@@ -12,9 +12,8 @@ from .idl_type import IdlType
from .typedef import Typedef
-# NewUnion is a tentative name and will be renamed to Union.
-class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
- WithDebugInfo):
+class Union(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
+ WithDebugInfo):
"""
Union class makes a group of union types with the same flattened member
types and the same result whether it includes a nullable type or not.
@@ -84,12 +83,12 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
return len(self.token) < len(other.token)
def contains(self, other):
- assert isinstance(other, NewUnion.IR)
+ assert isinstance(other, Union.IR)
return (self.token != other.token
and self._member_set.issuperset(other._member_set))
def __init__(self, ir):
- assert isinstance(ir, NewUnion.IR)
+ assert isinstance(ir, Union.IR)
assert ir.public_object is None
identifier = Identifier('Union_{}'.format('_'.join(ir.token)))
@@ -109,7 +108,7 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
if member_type.is_typedef:
typedef_members.add(member_type.typedef_object)
for sub_union_ir in ir.sub_union_irs:
- assert isinstance(sub_union_ir.public_object, NewUnion)
+ assert isinstance(sub_union_ir.public_object, Union)
typedef_members.update(sub_union_ir.typedefs)
union_members.add(sub_union_ir.public_object)
@@ -156,7 +155,6 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
ir.public_object = self
for idl_type in self._idl_types:
- idl_type.set_new_union_definition_object(self)
idl_type.set_union_definition_object(self)
@property
@@ -229,182 +227,3 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
aliasing_typedefs returns a list of IdlType(T1) and IdlType(T2).
"""
return self._aliasing_typedefs
-
-
-class BackwardCompatibleUnion(WithIdentifier, WithCodeGeneratorInfo,
- WithComponent, WithDebugInfo):
- """
- Union class makes a group of union types with the same flattened member
- types and the same result whether it includes a nullable type or not.
-
- For example, the following union types will be grouped into one Union
- instance.
- (A? or B or C), (A or B? or C), ((A or B) or C?), (A or (B or C?)), ...
- All these unions have the same set of flattened member types (A, B, C) and
- include a nullable type.
-
- However, all following union types will be grouped into separate Union
- instances.
- (A or B), ([X] A or B), ([Y] A or B)
- IdlType(A), IdlType([X] A), and IdlType([Y] A) are all distinguished from
- each other as they behave differently. Bindings code generators are
- expected to define an implementation class for each Union instance.
- """
-
- def __init__(self, union_types, typedef_backrefs):
- """
- Args:
- union_types: Union types of which this object consists. All types
- in |union_types| must have the same flattened_member_types and
- the same value of does_include_nullable_type.
- typedef_backrefs: Typedef instances whose typedef'ed type is this
- union.
- """
- assert isinstance(union_types, (list, tuple))
- assert len(union_types) > 0
- assert all(
- isinstance(union_type, IdlType) and union_type.is_union
- for union_type in union_types)
- assert isinstance(typedef_backrefs, (list, tuple))
- assert all(
- isinstance(typedef, Typedef) for typedef in typedef_backrefs)
-
- flattened_members = union_types[0].flattened_member_types
- does_include_nullable_type = union_types[0].does_include_nullable_type
-
- nullable_members = set()
- typedef_members = set()
- union_members = set()
- for union_type in union_types:
- assert union_type.flattened_member_types == flattened_members
- assert (union_type.does_include_nullable_type ==
- does_include_nullable_type)
- union_type.set_union_definition_object(self)
- for direct_member in union_type.member_types:
- if direct_member.is_nullable:
- nullable_members.add(direct_member)
- if direct_member.is_typedef:
- typedef_members.add(direct_member)
- if direct_member.is_union:
- union_members.add(direct_member)
-
- sort_key = lambda x: x.syntactic_form
-
- components = set()
-
- def collect_primary_component(idl_type):
- type_definition_object = idl_type.type_definition_object
- if type_definition_object and type_definition_object.components:
- components.add(type_definition_object.components[0])
-
- for idl_type in flattened_members:
- idl_type.apply_to_all_composing_elements(collect_primary_component)
- # Make this union type look defined in 'modules' if the union type is
- # used in 'modules' in order to keep the backward compatibility with
- # the old bindings generator.
- is_defined_in_core = False
- is_defined_in_modules = False
- for idl_type in union_types:
- filepath = idl_type.debug_info.location.filepath
- if filepath.startswith('third_party/blink/renderer/core/'):
- is_defined_in_core = True
- if filepath.startswith('third_party/blink/renderer/modules/'):
- is_defined_in_modules = True
- if not is_defined_in_core and is_defined_in_modules:
- from .composition_parts import Component
- components.add(Component('modules'))
-
- # TODO(peria, yukishiino): Produce unique union names. Trying to
- # produce the names compatible to the old bindings generator for the
- # time being.
- #
- # type_names = sorted(
- # [idl_type.type_name for idl_type in flattened_members])
- def backward_compatible_member_name(idl_type):
- name = idl_type.unwrap().type_name
- if name == 'StringTreatNullAs':
- return 'StringTreatNullAsEmptyString'
- else:
- return name
-
- identifier = Identifier('Or'.join([
- backward_compatible_member_name(idl_type)
- for idl_type in union_types[0].member_types
- ]))
-
- WithIdentifier.__init__(self, identifier)
- WithCodeGeneratorInfo.__init__(self, readonly=True)
- WithComponent.__init__(self, sorted(components), readonly=True)
- WithDebugInfo.__init__(self)
-
- # Sort improves reproducibility.
- self._flattened_members = tuple(
- sorted(flattened_members, key=sort_key))
- self._does_include_nullable_type = does_include_nullable_type
- self._nullable_members = tuple(sorted(nullable_members, key=sort_key))
- self._typedef_members = tuple(sorted(typedef_members, key=sort_key))
- self._union_members = tuple(sorted(union_members, key=sort_key))
- self._typedef_backrefs = tuple(typedef_backrefs)
-
- @property
- def flattened_member_types(self):
- """
- Returns the same list of flattened member types as
- IdlType.flattened_member_types.
- """
- return self._flattened_members
-
- @property
- def does_include_nullable_type(self):
- """
- Returns True if any of member type is nullable or a member union
- includes a nullable type.
- """
- return self._does_include_nullable_type
-
- @property
- def nullable_member_types(self):
- """
- Returns a list of nullable types which are direct members of union types
- of which this object consists.
-
- Given the following unions,
- (A? or B or C), (A or B? or C), (A or B or CN) where typedef C? CN;
- nullable_member_types returns a list of IdlType(A?) and IdlType(B?).
- """
- return self._nullable_members
-
- @property
- def typedef_member_types(self):
- """
- Returns a list of typedef types which are direct members of union types
- of which this object consists.
-
- Given the following unions,
- (AT or B), (A or BT) where typedef A AT, and typedef B BT;
- typedef_member_types returns a list of IdlType(AT) and IdlType(BT).
- """
- return self._typedef_members
-
- @property
- def union_member_types(self):
- """
- Returns a list of union types which are direct members of union types of
- which this object consists.
-
- Given the following unions,
- ((A or B) or C), (A or (B or C))
- union_member_types returns a list of IdlType(A or B) and
- IdlType(B or C).
- """
- return self._union_members
-
- @property
- def aliasing_typedefs(self):
- """
- Returns a list of typedefs which are aliases to this union type.
- """
- return self._typedef_backrefs
-
-
-Union = NewUnion
diff --git a/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
deleted file mode 100644
index 52865862c0f..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
+++ /dev/null
@@ -1,725 +0,0 @@
-{% from 'utilities.cc.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %}
-{% from 'methods.cc.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %}
-
-{##############################################################################}
-{% macro attribute_getter(attribute, world_suffix) %}
-static void {{attribute.camel_case_name}}AttributeGetter{{world_suffix}}(
-{%- if attribute.is_data_type_property %}
-const v8::PropertyCallbackInfo<v8::Value>& info
-{%- else %}
-const v8::FunctionCallbackInfo<v8::Value>& info
-{%- endif %}) {
- {% filter format_remove_duplicates(['ExceptionState exception_state']) %}
- {% set define_exception_state -%}
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "{{interface_name}}", "{{attribute.name}}");
- {%- endset %}
-
- {% if attribute.is_lenient_this %}
- // [LegacyLenientThis]
- // Make sure that info.Holder() really points to an instance if [LegacyLenientThis].
- if (!{{v8_class}}::HasInstance(info.Holder(), info.GetIsolate()))
- return; // Return silently because of [LegacyLenientThis].
- {% elif attribute.has_promise_type %}
- // This attribute returns a Promise.
- // Per https://heycam.github.io/webidl/#dfn-attribute-getter, all exceptions
- // must be turned into a Promise rejection.
- {{define_exception_state}}
- ExceptionToRejectPromiseScope reject_promise_scope(info, exception_state);
-
- // Returning a Promise type requires us to disable some of V8's type checks,
- // so we have to manually check that info.Holder() really points to an
- // instance of the type.
- if (!{{v8_class}}::HasInstance(info.Holder(), info.GetIsolate())) {
- exception_state.ThrowTypeError("Illegal invocation");
- return;
- }
- {% endif %}
-
- {% if not attribute.is_static or attribute.is_save_same_object %}
- v8::Local<v8::Object> holder = info.Holder();
- {% endif %}
-
- {% if attribute.is_save_same_object %}
- // [SaveSameObject]
- static const V8PrivateProperty::SymbolKey kSaveSameObjectKey;
- auto private_same_object =
- V8PrivateProperty::GetSymbol(info.GetIsolate(), kSaveSameObjectKey);
- {
- v8::Local<v8::Value> v8_value;
- if (private_same_object.GetOrUndefined(holder).ToLocal(&v8_value) && !v8_value->IsUndefined()) {
- V8SetReturnValue(info, v8_value);
- return;
- }
- }
- {% endif %}
-
- {% if not attribute.is_static %}
- {% set local_dom_window_only = interface_name == 'Window' and not attribute.has_cross_origin_getter %}
- {% if local_dom_window_only %}
- {% if attribute.is_check_security_for_receiver %}
- {{cpp_class}}* unchecked_impl = {{v8_class}}::ToImpl(holder);
- {% else %}
- // Same-origin attribute getters are never exposed via the cross-origin
- // interceptors. Since same-origin access requires a LocalDOMWindow, it is
- // safe to downcast here.
- LocalDOMWindow* impl = To<LocalDOMWindow>({{v8_class}}::ToImpl(holder));
- {% endif %}{# attribute.is_check_security_for_receiver #}
- {% else %}
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(holder);
- {% endif %}{# local_dom_window_only #}
- {% endif %}{# not attribute.is_static #}
-
- {% if interface_name == "Window" and attribute.has_cross_origin_getter %}
- impl->ReportCoopAccess("{{attribute.name}}");
- {% endif %}
-
- {% if attribute.cached_attribute_validation_method %}
- // [CachedAttribute]
- {% if not attribute.private_property_is_shared_between_getter_and_setter %}
- static const V8PrivateProperty::SymbolKey kPrivateProperty{{attribute.camel_case_name}};
-
- {% endif %}
- V8PrivateProperty::Symbol property_symbol =
- V8PrivateProperty::GetSymbol(info.GetIsolate(),
- kPrivateProperty{{attribute.camel_case_name}});
- if (!static_cast<const {{cpp_class}}*>(impl)->{{attribute.cached_attribute_validation_method}}()) {
- v8::Local<v8::Value> v8_value;
- if (property_symbol.GetOrUndefined(holder).ToLocal(&v8_value) && !v8_value->IsUndefined()) {
- V8SetReturnValue(info, v8_value);
- return;
- }
- }
- {% endif %}
-
- {% if attribute.is_check_security_for_receiver and not attribute.is_data_type_property %}
- // Perform a security check for the receiver object.
- {{define_exception_state}}
- {% if local_dom_window_only %}
- if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), unchecked_impl, exception_state)) {
- {% else %}
- if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), impl, exception_state)) {
- {% endif %}{# local_dom_window_only #}
- V8SetReturnValueNull(info);
- return;
- }
- {% if local_dom_window_only %}
- LocalDOMWindow* impl = To<LocalDOMWindow>(unchecked_impl);
- {% endif %}{# local_dom_window_only #}
- {% endif %}
-
- {% if attribute.is_check_security_for_return_value %}
- // Perform a security check for the returned object.
- {{define_exception_state}}
- if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), {{attribute.cpp_value}}, BindingSecurity::ErrorReportOption::kDoNotReport)) {
- UseCounter::Count(CurrentExecutionContext(info.GetIsolate()),
- WebFeature::kCrossOrigin{{interface_name}}{{attribute.camel_case_name}});
- V8SetReturnValueNull(info);
- return;
- }
- {% endif %}
-
- {% if attribute.is_call_with_execution_context or
- attribute.high_entropy == 'Direct' %}
- {% if attribute.is_static %}
- ExecutionContext* execution_context = ExecutionContext::ForCurrentRealm(info);
- {% else %}
- ExecutionContext* execution_context = ExecutionContext::ForRelevantRealm(info);
- {% endif %}
- {% endif %}
-
- {% if attribute.is_call_with_script_state or
- attribute.is_getter_call_with_script_state %}
- {% if attribute.is_static %}
- ScriptState* script_state = ScriptState::ForCurrentRealm(info);
- {% else %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
- {% endif %}
-
- {% if attribute.is_getter_raises_exception %}
- {{define_exception_state}}
- {% endif %}
-
- {% if attribute.cpp_value_original %}
- {{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_original}});
- {% endif %}
-
- {% if attribute.high_entropy == 'Direct' %}
- Dactyloscoper::RecordDirectSurface(execution_context, WebFeature::k{{attribute.measure_as('AttributeGetter')}}, {{attribute.cpp_value}});
- {% endif %}
-
- {% if attribute.use_output_parameter_for_result %}
- {{attribute.cpp_type}} result;
- {{attribute.cpp_value}};
- {% endif %}
-
- {% if attribute.is_getter_raises_exception %}
- if (UNLIKELY(exception_state.HadException()))
- return;
- {% endif %}
-
- {% if attribute.reflect_only %}
- {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
- attribute.reflect_invalid, attribute.reflect_empty,
- attribute.cpp_value)
- | trim | indent(2)}}
- {% endif %}
-
- {% if attribute.is_explicit_nullable %}
- if (!{{attribute.cpp_value}}.has_value()) {
- {% if attribute.cached_attribute_validation_method %}
- // [CachedAttribute]
- property_symbol.Set(holder, v8::Null(info.GetIsolate()));
- {% endif %}
- V8SetReturnValueNull(info);
- return;
- }
- {% endif %}
-
- {% if attribute.cached_attribute_validation_method %}
- // [CachedAttribute]
- v8::Local<v8::Value> v8_value({{attribute.cpp_value_to_v8_value}});
- property_symbol.Set(holder, v8_value);
- {% endif %}
-
- {% if attribute.is_keep_alive_for_gc %}
- // Keep the wrapper object for the return value alive as long as |this|
- // object is alive in order to save creation time of the wrapper object.
- if ({{attribute.cpp_value}} && DOMDataStore::SetReturnValue{{world_suffix}}(info.GetReturnValue(), {{attribute.cpp_value_to_script_wrappable}}))
- return;
- v8::Local<v8::Value> v8_value(ToV8({{attribute.cpp_value_to_script_wrappable}}, holder, info.GetIsolate()));
- static const V8PrivateProperty::SymbolKey kKeepAliveKey;
- V8PrivateProperty::GetSymbol(info.GetIsolate(), kKeepAliveKey)
- .Set(holder, v8_value);
- {% endif %}
-
- {% if world_suffix %}
- {{attribute.v8_set_return_value_for_main_world}};
- {% else %}
- {{attribute.v8_set_return_value}};
- {% endif %}
-
- {% if attribute.is_save_same_object %}
- // [SaveSameObject]
- private_same_object.Set(holder, info.GetReturnValue().Get());
- {% endif %}
- {% endfilter %}{# format_remove_duplicates #}
-}
-{% endmacro %}
-
-
-{######################################}
-{% macro release_only_check(reflect_only_values, reflect_missing,
- reflect_invalid, reflect_empty, cpp_value) %}
-{# Attribute is limited to only known values: check that the attribute value is
- one of those. If not, set it to the empty string.
- http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
-{% if reflect_only_values %}
-AtomicString atomic_{{cpp_value}}({{cpp_value}}.LowerASCII());
-{% endif %}
-{% if reflect_empty %}
-if ({{cpp_value}}.IsNull()) {
-{% if reflect_missing %}
- {{cpp_value}} = {{reflect_missing}};
-{% else %}
- ;
-{% endif %}
-} else if ({{cpp_value}}.IsEmpty()) {
- {{cpp_value}} = {{reflect_empty}};
-{% else %}
-if ({{cpp_value}}.IsEmpty()) {
-{# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
-{% if reflect_missing %}
- {{cpp_value}} = {{reflect_missing}};
-{% else %}
- ;
-{% endif %}
-{% endif %}
-{% for value in reflect_only_values %}
-} else if (atomic_{{cpp_value}} == {{value}}) {
- {{cpp_value}} = {{value}};
-{% endfor %}
-} else {
- {{cpp_value}} = {{reflect_invalid}};
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro attribute_getter_callback(attribute, world_suffix) %}
-void {{v8_class_or_partial}}::{{attribute.camel_case_name}}AttributeGetterCallback{{world_suffix}}(
-{%- if attribute.is_data_type_property %}
-v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info
-{%- else %}
-const v8::FunctionCallbackInfo<v8::Value>& info
-{%- endif %}) {
- {% if attribute.runtime_call_stats.extended_attribute_defined %}
- {{ runtime_timer_scope(attribute.runtime_call_stats.getter_counter) | trim | indent(2) }}
- {% else %}
- {{ runtime_timer_scope_disabled_by_default(attribute.runtime_call_stats.getter_counter) }}
- {% endif %}
-
- {% if attribute.deprecate_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
- {% endif %}
-
- {% if attribute.measure_as %}
- ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
- UseCounter::Count(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('AttributeGetter')}});
- {% if attribute.high_entropy %}
- Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('AttributeGetter')}});
- {% endif %}
- {% endif %}
-
- {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
- {% if attribute.is_static %}
- ScriptState* script_state = ScriptState::ForCurrentRealm(info);
- {% else %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
- V8PerContextData* context_data = script_state->PerContextData();
- if (
- {%- if attribute.activity_logging_world_check -%}
- script_state->World().IsIsolatedWorld() && {# one space at the end #}
- {%- endif -%}
- context_data && context_data->ActivityLogger()) {
- context_data->ActivityLogger()->LogGetter("{{interface_name}}.{{attribute.name}}");
- }
- {% endif %}
-
- {% if attribute.has_custom_getter %}
- {{v8_class}}::{{attribute.camel_case_name}}AttributeGetterCustom(info);
- {% else %}
- {{internal_namespace}}::{{attribute.camel_case_name}}AttributeGetter{{world_suffix}}(info);
- {% endif %}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro constructor_getter_callback(attribute, world_suffix) %}
-void {{v8_class_or_partial}}::{{attribute.camel_case_name}}ConstructorGetterCallback{{world_suffix}}(
- v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(attribute.runtime_call_stats.constructor_getter_callback_counter) }}
- {% if attribute.deprecate_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
- {% endif %}
-
- {% if attribute.measure_as %}
- ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
- UseCounter::Count(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('ConstructorGetter')}});
- {% if attribute.high_entropy %}
- Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('ConstructorGetter')}});
- {% endif %}
- {% endif %}
-
- {% if attribute.is_named_constructor %}
- V8{{attribute.constructor_type}}::NamedConstructorAttributeGetter(property, info);
- {% else %}
- V8ConstructorAttributeGetter(property, info, V8{{attribute.constructor_type}}::GetWrapperTypeInfo());
- {% endif %}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro attribute_setter(attribute, world_suffix) %}
-{% if not attribute.use_common_reflection_setter %}
-static void {{attribute.camel_case_name}}AttributeSetter{{world_suffix}}(
- {% if attribute.has_cross_origin_setter %}
- v8::Local<v8::Value> v8_value, const V8CrossOriginCallbackInfo& info
- {% elif attribute.is_data_type_property %}
- v8::Local<v8::Value> v8_value, const v8::PropertyCallbackInfo<void>& info
- {% else %}
- v8::Local<v8::Value> v8_value, const v8::FunctionCallbackInfo<v8::Value>& info
- {%- endif %}) {
- {% filter format_remove_duplicates(['ExceptionState exception_state']) %}
- v8::Isolate* isolate = info.GetIsolate();
- ALLOW_UNUSED_LOCAL(isolate);
-
- v8::Local<v8::Object> holder = info.Holder();
- ALLOW_UNUSED_LOCAL(holder);
-
- {% set define_exception_state -%}
- ExceptionState exception_state(isolate, ExceptionState::kSetterContext, "{{interface_name}}", "{{attribute.name}}");
- {%- endset %}
-
- {% if attribute.is_lenient_this %}
- // [LegacyLenientThis]
- // Make sure that info.Holder() really points to an instance if [LegacyLenientThis].
- if (!{{v8_class}}::HasInstance(holder, isolate))
- return; // Return silently because of [LegacyLenientThis].
- {% endif %}
-
- {% if not attribute.is_static and not attribute.is_replaceable and not attribute.is_put_forwards %}
- {% set local_dom_window_only = interface_name == 'Window' and not attribute.has_cross_origin_setter %}
- {% if local_dom_window_only %}
- {% if attribute.is_check_security_for_receiver %}
- {{cpp_class}}* unchecked_impl = {{v8_class}}::ToImpl(holder);
- {% else %}
- // Same-origin attributes setters are never exposed via the cross-origin
- // interceptors. Since same-origin access requires a LocalDOMWindow, it is
- // safe to downcast here.
- LocalDOMWindow* impl = To<LocalDOMWindow>({{v8_class}}::ToImpl(holder));
- {% endif %}{# attribute.is_check_security_for_receiver #}
- {% else %}
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(holder);
- {% endif %}{# local_dom_window_only #}
- {% endif %}
-
- {% if attribute.is_check_security_for_receiver and not attribute.is_data_type_property %}
- // Perform a security check for the receiver object.
- {{define_exception_state}}
- {% if local_dom_window_only %}
- if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(isolate), unchecked_impl, exception_state)) {
- {% else %}
- if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(isolate), impl, exception_state)) {
- {% endif %}{# local_dom_window_only #}
- V8SetReturnValue(info, v8_value);
- return;
- }
- {% if local_dom_window_only %}
- LocalDOMWindow* impl = To<LocalDOMWindow>(unchecked_impl);
- {% endif %}{# local_dom_window_only #}
- {% endif %}
-
- {% if attribute.is_check_security_for_return_value %}
-#error Attribute setter with the security check for the return value is not supported. Since the return value is the given value to be set, it\'s meaningless to perform the security check for the return value.
- {% endif %}
-
- {% if attribute.is_put_forwards %}
- // [PutForwards] => {{attribute.name}}.{{attribute.target_attribute_name}}
- {{define_exception_state}}
- v8::Local<v8::Value> target;
- if (!holder->Get(isolate->GetCurrentContext(), V8AtomicString(isolate, "{{attribute.name}}"))
- .ToLocal(&target)) {
- return;
- }
- if (!target->IsObject()) {
- exception_state.ThrowTypeError("The attribute value is not an object");
- return;
- }
- bool result;
- if (!target.As<v8::Object>()->Set(
- isolate->GetCurrentContext(),
- V8AtomicString(isolate, "{{attribute.target_attribute_name}}"),
- v8_value).To(&result)) {
- return;
- }
- if (!result)
- return;
- {% else %}{# attribute.is_put_forwards #}
- {% if attribute.has_setter_exception_state %}
- {{define_exception_state}}
- {% endif %}
- {% if attribute.is_ce_reactions %}
- CEReactionsScope ce_reactions_scope;
- {% endif %}
-
- {% if attribute.is_explicit_nullable %}
- bool is_null = IsUndefinedOrNull(v8_value);
- {% endif %}
-
- // Prepare the value to be set.
- {% if attribute.idl_type != 'EventHandler' %}
- {{v8_value_to_local_cpp_value(attribute) | trim | indent(2)}}
- {% endif %}
-
- {% if attribute.has_type_checking_interface %}
- // Type check per: http://heycam.github.io/webidl/#es-interface
- if (!cpp_value{% if attribute.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) {
- exception_state.ThrowTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
- return;
- }
- {% endif %}
-
- {% if attribute.enum_values %}
- // Type check per: http://heycam.github.io/webidl/#dfn-attribute-setter
- // Returns undefined without setting the value if the value is invalid.
- DummyExceptionStateForTesting dummy_exception_state;
- {
- {{declare_enum_validation_variable(attribute.enum_values) | trim | indent(2)}}
- if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues),
- "{{attribute.enum_type}}", dummy_exception_state)) {
- ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage(
- MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kWarning,
- dummy_exception_state.Message()));
- return;
- }
- }
- {% endif %}
-
- {% if attribute.is_call_with_execution_context or
- attribute.is_setter_call_with_execution_context %}
- {% if attribute.is_static %}
- ExecutionContext* execution_context = ExecutionContext::ForCurrentRealm(info);
- {% else %}
- ExecutionContext* execution_context = ExecutionContext::ForRelevantRealm(info);
- {% endif %}
- {% endif %}
-
- {% if attribute.is_call_with_script_state or
- attribute.is_setter_call_with_script_state %}
- {% if attribute.is_static %}
- ScriptState* script_state = ScriptState::ForCurrentRealm(info);
- {% else %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
- {% endif %}
-
- {% if attribute.is_replaceable %}
- v8::Local<v8::String> property_name = V8AtomicString(isolate, "{{attribute.name}}");
- {% endif %}
- {{attribute.cpp_setter | indent(2)}};
-
- {% if attribute.cached_attribute_validation_method %}
- // [CachedAttribute]
- // Invalidate the cached value.
- V8PrivateProperty::GetSymbol(
- isolate,
- kPrivateProperty{{attribute.camel_case_name}})
- .DeleteProperty(holder);
- {% endif %}
- {% endif %}{# attribute.is_put_forwards #}
- {% endfilter %}{# format_remove_duplicates #}
-}
-{% endif %}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro attribute_setter_callback(attribute, world_suffix) %}
-void {{v8_class_or_partial}}::{{attribute.camel_case_name}}AttributeSetterCallback{{world_suffix}}(
- {% if attribute.is_data_type_property %}
- v8::Local<v8::Name>, v8::Local<v8::Value> v8_value, const v8::PropertyCallbackInfo<void>& info
- {% else %}
- const v8::FunctionCallbackInfo<v8::Value>& info
- {%- endif %}) {
- {% if attribute.is_lenient_setter %}
- // Setter for {{attribute.name}} is no-op because [LegacyLenientSetter] is specified.
- {% else %}
- {% if attribute.runtime_call_stats.extended_attribute_defined %}
- {{ runtime_timer_scope(attribute.runtime_call_stats.setter_counter) | trim | indent(2) }}
- {% else %}
- {{ runtime_timer_scope_disabled_by_default(attribute.runtime_call_stats.setter_counter) }}
- {% endif %}
-
- {% if not attribute.is_data_type_property and not attribute.use_common_reflection_setter %}
- v8::Local<v8::Value> v8_value = info[0];
- {% endif %}
-
- {% if attribute.deprecate_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
- {% endif %}
-
- {% if attribute.measure_as %}
- UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('AttributeSetter')}});
- {% endif %}
-
- {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
- {% if attribute.is_static %}
- ScriptState* script_state = ScriptState::ForCurrentRealm(info);
- {% else %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
- V8PerContextData* context_data = script_state->PerContextData();
- if (
- {%- if attribute.activity_logging_world_check -%}
- script_state->World().IsIsolatedWorld() && {# one space at the end #}
- {%- endif -%}
- context_data && context_data->ActivityLogger()) {
- context_data->ActivityLogger()->LogSetter("{{interface_name}}.{{attribute.name}}", v8_value);
- }
- {% endif %}
-
- {% if attribute.has_custom_setter %}
- {{v8_class}}::{{attribute.camel_case_name}}AttributeSetterCustom(v8_value, info);
- {% elif attribute.has_cross_origin_setter %}
- {{internal_namespace}}::{{attribute.camel_case_name}}AttributeSetter(
- v8_value, V8CrossOriginCallbackInfo(info));
- {% elif attribute.use_common_reflection_setter %}
- {{attribute.cpp_setter}};
- {% else %}
- {{internal_namespace}}::{{attribute.camel_case_name}}AttributeSetter{{world_suffix}}(v8_value, info);
- {% endif %}
- {% endif %}{# attribute.is_lenient_setter #}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro build_attribute_or_accessor_configuration(attribute, config_type) %}
-{% from 'utilities.cc.tmpl' import property_location %}
-{% if attribute.constructor_type %}
- {% set getter_callback = '%s::%sConstructorGetterCallback' % (v8_class_or_partial, attribute.camel_case_name) %}
- {% set setter_callback = 'nullptr' %}
-{% else %}{# regular attributes #}
- {% set getter_callback = '%s::%sAttributeGetterCallback' % (v8_class_or_partial, attribute.camel_case_name) %}
- {% set setter_callback = '%s::%sAttributeSetterCallback' % (v8_class_or_partial, attribute.camel_case_name)
- if attribute.has_setter else 'nullptr' %}
-{% endif %}
-
-{% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' %
- ' | '.join(attribute.property_attributes) %}
-{% set cached_property_key = 'V8PrivateProperty::CachedAccessor::' +
- (attribute.cached_accessor_name if attribute.is_cached_accessor
- else 'kNone') %}
-{% set cached_property_key = 'static_cast<unsigned>(%s)' % cached_property_key %}
-{% set holder_check = 'V8DOMConfiguration::kDoNotCheckHolder'
- if attribute.is_lenient_this or attribute.has_promise_type
- else 'V8DOMConfiguration::kCheckHolder' %}
-{% set getter_side_effect_type = 'V8DOMConfiguration::kHasNoSideEffect'
- if attribute.getter_has_no_side_effect else 'V8DOMConfiguration::kHasSideEffect' %}
-{% set getter_behavior = 'V8DOMConfiguration::kAlwaysCallGetter'
- if not attribute.is_lazy_data_attribute else 'V8DOMConfiguration::kReplaceWithDataProperty' %}
-{% if attribute.is_per_world_bindings %}
- {% set getter_callback_for_main_world = '%sForMainWorld' % getter_callback %}
- {% set setter_callback_for_main_world =
- '%sForMainWorld' % setter_callback if attribute.has_setter else 'nullptr' %}
-{% endif %}
-{% set world_dependent_config = {
- 'main' : [
- '"%s"' % attribute.name,
- getter_callback_for_main_world,
- setter_callback_for_main_world,
- ],
- 'non_main' : [
- '"%s"' % attribute.name,
- getter_callback,
- setter_callback,
- ],
-} %}
-{% if config_type == 'attribute' %}
-{% set world_common_config = [
- property_attribute,
- property_location(attribute),
- holder_check,
- getter_side_effect_type,
- getter_behavior,
-] %}
-{% else %}{# config_type == 'accessor' #}
-{% set world_common_config = [
- cached_property_key,
- property_attribute,
- property_location(attribute),
- holder_check,
- 'V8DOMConfiguration::kCheckAccess',
- 'V8DOMConfiguration::kCheckAccess',
- getter_side_effect_type,
-] %}
-{% endif %}
-
-{% if attribute.is_per_world_bindings %}
- {% set main_config_list = world_dependent_config["main"] +
- world_common_config + ['V8DOMConfiguration::kMainWorld'] %}
- {% set non_main_config_list = world_dependent_config["non_main"] +
- world_common_config + ['V8DOMConfiguration::kNonMainWorlds'] %}
- {# Emit for main world then non-main.#}
-{ {{main_config_list | join(', ')}} },
-{ {{non_main_config_list | join(', ')}} }
-{%- else -%}
- {% set all_worlds_config_list = world_dependent_config["non_main"] +
- world_common_config + ['V8DOMConfiguration::kAllWorlds'] %}
- {# Emit only for all worlds #}
-{ {{all_worlds_config_list | join(', ')}} }
-{%- endif -%}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro attribute_configuration(attribute) %}
-{{build_attribute_or_accessor_configuration(attribute, 'attribute')}}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro accessor_configuration(attribute) %}
-{{build_attribute_or_accessor_configuration(attribute, 'accessor')}}
-{% endmacro %}
-
-
-{##############################################################################}
-{# This macro installs |attributes_to_install| conditionally based on Exposed, CrossOriginIsolated, DirectSocketEnabled, SecureContext, and RuntimeEnabled checks. #}
-{% macro install_conditional_attributes(attributes_to_install) %}
-{% for exposed_test, exposed_attribute_list in attributes_to_install | groupby('exposed_test') %}
-{% filter exposed(exposed_test) %}
-{% for cross_origin_isolated_test, cross_origin_isolated_attribute_list in exposed_attribute_list | groupby('cross_origin_isolated_test') %}
-{% filter cross_origin_isolated(cross_origin_isolated_test) %}
-{% for direct_socket_enabled_test, direct_socket_enabled_attribute_list in cross_origin_isolated_attribute_list | groupby('direct_socket_enabled_test') %}
-{% filter direct_socket_enabled(direct_socket_enabled_test) %}
-{% for secure_context_test, secure_context_attribute_list in direct_socket_enabled_isolated_attribute_list | groupby('secure_context_test') %}
-{% filter secure_context(secure_context_test) %}
-{% for feature_name, attribute_list in secure_context_attribute_list | groupby('runtime_enabled_feature_name') %}
-{% filter runtime_enabled(feature_name) %}
-{{install_attributes(attribute_list | sort, 'instance_object', 'prototype_object', 'interface_object')}}
-{% endfilter %}{# runtime_enabled #}
-{% endfor %}{# secure_context_attribute_list grouped by runtime_enabled #}
-{% endfilter %}{# secure_context #}
-{% endfor %}{# direct_socket_isolated_attribute_list grouped by secure_context_text #}
-{% endfilter %}{# direct_socket_enabled #}
-{% endfor %}{# cross_origin_isolated_attribute_list grouped by direct_socket_enabled_test #}
-{% endfilter %}{# cross_origin_isolated #}
-{% endfor %}{# exposed_attribute_list grouped by cross_origin_isolation_test #}
-{% endfilter %}{# exposed #}
-{% endfor %}{# attributes grouped by exposed_test #}
-{% endmacro %}
-
-
-{##############################################################################}
-{# This macro installs |attributes_to_install| unconditionally. #}
-{% macro install_attributes(attributes_to_install, instance_variable, prototype_variable, interface_variable) %}
-static constexpr V8DOMConfiguration::AccessorConfiguration
-kAccessorConfigurations[] = {
- {% for attribute in attributes_to_install %}
- {{accessor_configuration(attribute) | trim | indent(4)}},
- {% endfor %}
-};
-V8DOMConfiguration::InstallAccessors(
- isolate, world, {{instance_variable}}, {{prototype_variable}}, {{interface_variable}},
- signature, kAccessorConfigurations,
- base::size(kAccessorConfigurations));
-{% endmacro %}
-
-
-{##############################################################################}
-{# This macro installs |attributes_to_install| conditionally based on Exposed, CrossOriginIsolated, DirectSocketEnabled, SecureContext, and RuntimeEnabled checks. #}
-{% macro install_conditional_interface_objects(attributes_to_install) %}
-{% for exposed_test, exposed_attribute_list in attributes_to_install | groupby('exposed_test') %}
-{% filter exposed(exposed_test) %}
-{% for cross_origin_isolated_test, cross_origin_isolated_attribute_list in exposed_attribute_list | groupby('cross_origin_isolated_test') %}
-{% filter cross_origin_isolated(cross_origin_isolated_test) %}
-{% for direct_socket_enabled_test, direct_socket_enabled_attribute_list in cross_origin_isolated_attribute_list | groupby('direct_socket_enabled_test') %}
-{% filter direct_socket_enabled(direct_socket_enabled_test) %}
-{% for secure_context_test, secure_context_attribute_list in direct_socket_enabled_attribute_list | groupby('secure_context_test') %}
-{% filter secure_context(secure_context_test) %}
-{% for feature_name, attribute_list in secure_context_attribute_list | groupby('runtime_enabled_feature_name') %}
-{% filter runtime_enabled(feature_name) %}
-{{install_interface_objects(attribute_list | sort, 'instance_object', 'prototype_object')}}
-{% endfilter %}{# runtime_enabled #}
-{% endfor %}{# secure_context_attribute_list grouped by runtime_enabled #}
-{% endfilter %}{# secure_context #}
-{% endfor %}{# direct_socket_isolated_attribute_list grouped by secure_context_text #}
-{% endfilter %}{# direct_socket_enabled #}
-{% endfor %}{# cross_origin_isolated_attribute_list grouped by direct_socket_enabled_test #}
-{% endfilter %}{# cross_origin_isolated #}
-{% endfor %}{# exposed_attribute_list grouped by cross_origin_isolation_test #}
-{% endfilter %}{# exposed #}
-{% endfor %}{# attributes grouped by exposed_test #}
-{% endmacro %}
-
-
-{##############################################################################}
-{# This macro installs |attributes_to_install| unconditionally. #}
-{% macro install_interface_objects(attributes_to_install, instance_variable, prototype_variable) %}
-static constexpr V8DOMConfiguration::AttributeConfiguration
-kAttributeConfigurations[] = {
- {% for attribute in attributes_to_install %}
- {{attribute_configuration(attribute) | trim | indent(4)}},
- {% endfor %}
-};
-V8DOMConfiguration::InstallAttributes(
- isolate, world, {{instance_variable}}, {{prototype_variable}},
- kAttributeConfigurations, base::size(kAttributeConfigurations));
-{% endmacro %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl
deleted file mode 100644
index 42fa4af20db..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl
+++ /dev/null
@@ -1,90 +0,0 @@
-{% from 'callback_invoke.cc.tmpl' import callback_invoke %}
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-
-#include "{{this_include_header_path}}"
-
-{% for filename in cpp_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-const char* {{cpp_class}}::NameInHeapSnapshot() const {
- return "{{cpp_class}}";
-}
-
-v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::Invoke({{argument_declarations | join(', ')}}) {
-{{callback_invoke(
- 'callback function', 'invoke',
- return_cpp_type, native_value_traits_tag, arguments,
- is_treat_non_object_as_null, False,
- callback_function_name, 'invoke')}}
-}
-
-{% if idl_type == 'any' %}
-v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::Construct({{argument_declarations[1:] | join(', ')}}) {
-{{callback_invoke(
- 'callback function', 'construct',
- return_cpp_type, native_value_traits_tag, arguments,
- is_treat_non_object_as_null, False,
- callback_function_name, 'construct')}}
-}
-{% endif %}
-
-{% if idl_type == 'void' or callback_function_name == 'Function' %}
-void {{cpp_class}}::InvokeAndReportException({{argument_declarations | join(', ')}}) {
- v8::TryCatch try_catch(GetIsolate());
- try_catch.SetVerbose(true);
-
- v8::Maybe<{{return_cpp_type}}> maybe_result =
- Invoke({{
- (['callback_this_value'] +
- (arguments|map(attribute='name')|list)
- )|join(', ')
- }});
- // An exception if any is killed with the v8::TryCatch above.
- ALLOW_UNUSED_LOCAL(maybe_result);
-}
-{% endif %}
-
-{% if callback_function_name == 'EventHandlerNonNull' %}
-bool {{cpp_class}}::IsRunnableOrThrowException(IgnorePause ignore_pause) {
- ScriptState* callback_relevant_script_state =
- CallbackRelevantScriptState();
-
- bool is_runnable =
- ignore_pause == IgnorePause::kIgnore ?
- IsCallbackFunctionRunnableIgnoringPause(
- callback_relevant_script_state, IncumbentScriptState()) :
- IsCallbackFunctionRunnable(
- callback_relevant_script_state, IncumbentScriptState());
- if (is_runnable)
- return true;
-
- // 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.
- ScriptState::Scope scope(callback_relevant_script_state);
- V8ThrowException::ThrowError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "invoke",
- "{{callback_function_name}}",
- "The provided callback is no longer runnable."));
- return false;
-}
-
-v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::InvokeWithoutRunnabilityCheck({{argument_declarations | join(', ')}}) {
-{{callback_invoke(
- 'callback function', 'invoke',
- return_cpp_type, native_value_traits_tag, arguments,
- is_treat_non_object_as_null, True,
- callback_function_name, 'invoke')}}
-}
-{% endif %}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
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
deleted file mode 100644
index d32ed1b454d..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl
+++ /dev/null
@@ -1,74 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% for forward_declaration in forward_declarations %}
-class {{forward_declaration}};
-{% endfor %}
-
-class {{exported}}{{cpp_class}} final : public CallbackFunctionBase {
- public:
- static {{cpp_class}}* Create(
- {%- if is_treat_non_object_as_null %}v8::Local<v8::Object>
- {%- else %}v8::Local<v8::Function>{% endif %} callback_function) {
- return MakeGarbageCollected<{{cpp_class}}>(callback_function);
- }
-
- explicit {{cpp_class}}(
- {%- if is_treat_non_object_as_null %}v8::Local<v8::Object>
- {%- else %}v8::Local<v8::Function>{% endif %} callback_function)
- : CallbackFunctionBase(callback_function) {}
- ~{{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;
-
-{# Web IDL does not distinguish callback constructors from callback functions.
- If the return type is 'any', then it\'s likely to be used as a callback
- constructor. #}
-{% if idl_type == 'any' %}
- // Performs "construct".
- // https://heycam.github.io/webidl/#construct-a-callback-function
- v8::Maybe<{{return_cpp_type}}> Construct({{argument_declarations[1:] | join(', ')}}) WARN_UNUSED_RESULT;
-{% endif %}
-
-{# Type Function is often used as a sort of wild cards, and its return value is
- often discarded. So, this provides some convenience. #}
-{% if idl_type == 'void' or callback_function_name == 'Function' %}
- // Performs "invoke", and then reports an exception, if any, to the global
- // error handler such as DevTools' console.
- void InvokeAndReportException({{argument_declarations | join(', ')}});
-{% endif %}
-
-{% if callback_function_name == 'EventHandlerNonNull' %}
- // Returns true if the callback is runnable, otherwise returns false and
- // throws an exception. 'beforeunload' event need to have priority over pause
- // of execution contexts.
- enum class IgnorePause { kDontIgnore, kIgnore };
- bool IsRunnableOrThrowException(IgnorePause);
-
- // Performs "invoke" without checking the runnability check, which must be
- // done prior to this call by |IsRunnableOrThrowException|.
- // https://heycam.github.io/webidl/#es-invoking-callback-functions
- // This function may throw unlike InvokeAndReportException.
- v8::Maybe<{{return_cpp_type}}> InvokeWithoutRunnabilityCheck({{argument_declarations | join(', ')}}) WARN_UNUSED_RESULT;
-{% endif %}
-};
-
-} // namespace blink
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl
deleted file mode 100644
index 180c7eef641..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl
+++ /dev/null
@@ -1,137 +0,0 @@
-{% from 'callback_invoke.cc.tmpl' import callback_invoke %}
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-
-#include "{{this_include_header_path}}"
-
-{% for filename in cpp_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% if is_legacy_callback_interface %}
-// Support of "legacy callback interface"
-
-// Suppress warning: global constructors, because struct WrapperTypeInfo is
-// trivial and does not depend on another global objects.
-#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wglobal-constructors"
-#endif
-const WrapperTypeInfo {{snake_case_v8_class}}_wrapper_type_info = {
- gin::kEmbedderBlink,
- {{v8_class}}::DomTemplate,
- nullptr,
- "{{interface_name}}",
- nullptr,
- WrapperTypeInfo::kWrapperTypeNoPrototype,
- WrapperTypeInfo::kObjectClassId,
- WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
-};
-#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-{% from 'constants.cc.tmpl' import install_constants with context %}
-static void Install{{v8_class}}Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interface_template) {
- // Legacy callback interface must not have a prototype object.
- interface_template->RemovePrototype();
-
- // Initialize the interface object's template.
- V8DOMConfiguration::InitializeDOMInterfaceTemplate(
- isolate, interface_template,
- {{v8_class}}::GetWrapperTypeInfo()->interface_name,
- v8::Local<v8::FunctionTemplate>(),
- kV8DefaultWrapperInternalFieldCount);
- interface_template->SetLength(0);
-
- // Register IDL constants.
- {# |install_constants| requires |interface_template| and |prototype_template|. #}
- v8::Local<v8::ObjectTemplate> prototype_template =
- interface_template->PrototypeTemplate();
- {{install_constants() | trim | indent(2)}}
-}
-
-// static
-v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world) {
- return V8DOMConfiguration::DomClassTemplate(
- isolate,
- world,
- const_cast<WrapperTypeInfo*>(GetWrapperTypeInfo()),
- Install{{v8_class}}Template);
-}
-{% 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(', ')}}) {
-{{callback_invoke(
- 'callback interface', None,
- method.cpp_type, method.native_value_traits_tag, method.arguments,
- False, False,
- interface_name, method.name)}}
-}
-
-{% endfor %}
-
-{% if methods|length == 1 and methods[0].idl_type == 'void' %}
-void {{v8_class}}::InvokeAndReportException({{methods[0].argument_declarations | join(', ')}}) {
- v8::TryCatch try_catch(GetIsolate());
- try_catch.SetVerbose(true);
-
- v8::Maybe<void> maybe_result =
- {{methods[0].name}}({{
- (['callback_this_value'] +
- (methods[0].arguments|map(attribute='name')|list)
- )|join(', ')
- }});
- // An exception if any is killed with the v8::TryCatch above.
- ALLOW_UNUSED_LOCAL(maybe_result);
-}
-{% endif %}
-
-{% if interface_name == 'EventListener' %}
-bool {{v8_class}}::IsRunnableOrThrowException(IgnorePause ignore_pause) {
- ScriptState* callback_relevant_script_state =
- CallbackRelevantScriptState();
-
- bool is_runnable =
- ignore_pause == IgnorePause::kIgnore ?
- IsCallbackFunctionRunnableIgnoringPause(
- callback_relevant_script_state, IncumbentScriptState()) :
- IsCallbackFunctionRunnable(
- callback_relevant_script_state, IncumbentScriptState());
- if (is_runnable)
- return true;
-
- // 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.
- ScriptState::Scope scope(callback_relevant_script_state);
- V8ThrowException::ThrowError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "{{methods[0].name}}",
- "{{interface_name}}",
- "The provided callback is no longer runnable."));
- return false;
-}
-
-v8::Maybe<{{methods[0].cpp_type}}> {{v8_class}}::InvokeWithoutRunnabilityCheck({{methods[0].argument_declarations | join(', ')}}) {
-{{callback_invoke(
- 'callback interface', None,
- methods[0].cpp_type, methods[0].native_value_traits_tag, methods[0].arguments,
- False, True,
- interface_name, methods[0].name)}}
-}
-{% endif %}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
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
deleted file mode 100644
index dd35f492206..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl
+++ /dev/null
@@ -1,84 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% for forward_declaration in forward_declarations %}
-class {{forward_declaration}};
-{% endfor %}
-
-{% if is_legacy_callback_interface %}
-{{exported}}extern const WrapperTypeInfo {{snake_case_v8_class}}_wrapper_type_info;
-{% endif %}
-
-class {{exported}}{{v8_class}} final : public CallbackInterfaceBase {
- public:
-{% if is_legacy_callback_interface %}
- // Support of "legacy callback interface"
- static v8::Local<v8::FunctionTemplate> DomTemplate(v8::Isolate*, const DOMWrapperWorld&);
- static constexpr const WrapperTypeInfo* GetWrapperTypeInfo() {
- return &{{snake_case_v8_class}}_wrapper_type_info;
- }
-
- // Constants
-{% for constant in constants %}
- static constexpr {{constant.cpp_type}} {{constant.name}} = {{constant.value}};
-{% endfor %}
-
-{% endif %}
- static {{v8_class}}* Create(v8::Local<v8::Object> callback_object) {
- return MakeGarbageCollected<{{v8_class}}>(callback_object);
- }
-
-{% set single_operation_enum_value =
- 'kSingleOperation' if is_single_operation_callback_interface else
- 'kNotSingleOperation' %}
- explicit {{v8_class}}(v8::Local<v8::Object> callback_object)
- : CallbackInterfaceBase(callback_object,
- {{single_operation_enum_value}}) {}
- ~{{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
- 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' %}
- // Performs "call a user object's operation", and then reports an exception,
- // if any, to the global error handler such as DevTools' console.
- void InvokeAndReportException({{methods[0].argument_declarations | join(', ')}});
-{% endif %}
-
-{% if interface_name == 'EventListener' %}
- // Returns true if the callback is runnable, otherwise returns false and
- // throws an exception. 'beforeunload' event need to have priority over pause
- // of execution contexts.
- enum class IgnorePause { kDontIgnore, kIgnore };
- bool IsRunnableOrThrowException(IgnorePause);
-
- // Performs "call a user object's operation" for '{{methods[0].name}}' without
- // checking the runnability check, which must be done prior to this call by
- // |IsRunnableOrThrowException|.
- // https://heycam.github.io/webidl/#call-a-user-objects-operation
- // This function may throw unlike InvokeAndReportException.
- v8::Maybe<{{methods[0].cpp_type}}> InvokeWithoutRunnabilityCheck({{methods[0].argument_declarations | join(', ')}}) WARN_UNUSED_RESULT;
-{% endif %}
-};
-
-} // namespace blink
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl
deleted file mode 100644
index bfe419f4eea..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl
+++ /dev/null
@@ -1,277 +0,0 @@
-{% from 'utilities.cc.tmpl' import declare_enum_validation_variable %}
-
-{# Implements callback interface\'s "call a user object's operation", or
- callback function\'s "invoke" and/or "construct".
- https://heycam.github.io/webidl/#call-a-user-objects-operation
- https://heycam.github.io/webidl/#es-invoking-callback-functions
-
- Args:
- interface_or_function = 'callback interface' or 'callback function'
- invoke_or_construct = 'invoke', 'construct', or None
- return_cpp_type = Blink (C++) return type
- return_native_value_traits_tag = tag of NativeValueTraits for return type
- arguments = dict of arguments\' info
- is_treat_non_object_as_null = True if [LegacyTreatNonObjectAsNull]
- bypass_runnability_check = Skip IsCallbackFunctionRunnable check if True
- interface_name = interface name used for exception
- operation_name = interface name used for exception and property lookup
-#}
-{% macro callback_invoke(
- interface_or_function, invoke_or_construct,
- return_cpp_type, return_native_value_traits_tag, arguments,
- is_treat_non_object_as_null, bypass_runnability_check,
- interface_name, operation_name) %}
- ScriptState* callback_relevant_script_state =
- CallbackRelevantScriptStateOrThrowException(
- "{{interface_name}}",
- "{{operation_name}}");
- if (!callback_relevant_script_state) {
- return v8::Nothing<{{return_cpp_type}}>();
- }
-
- {% if not bypass_runnability_check %}
- if (!IsCallbackFunctionRunnable(callback_relevant_script_state,
- 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.
- v8::HandleScope handle_scope(GetIsolate());
- v8::Local<v8::Object> callback_object = CallbackObject();
- CHECK(!callback_object.IsEmpty());
- v8::Context::Scope context_scope(callback_object->CreationContext());
- V8ThrowException::ThrowError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "{{operation_name}}",
- "{{interface_name}}",
- "The provided callback is no longer runnable."));
- return v8::Nothing<{{return_cpp_type}}>();
- }
- {% endif %}
-
- // step: Prepare to run script with relevant settings.
- ScriptState::Scope callback_relevant_context_scope(
- callback_relevant_script_state);
- // step: Prepare to run a callback with stored settings.
- v8::Context::BackupIncumbentScope backup_incumbent_scope(
- IncumbentScriptState()->GetContext());
-
- if (UNLIKELY(ScriptForbiddenScope::IsScriptForbidden())) {
- ScriptForbiddenScope::ThrowScriptForbiddenException(GetIsolate());
- return v8::Nothing<{{return_cpp_type}}>();
- }
-
- {% if invoke_or_construct == 'construct' %}
- // step 3. If ! IsConstructor(F) is false, throw a TypeError exception.
- //
- // Note that step 7. and 8. are side effect free (except for a very rare
- // exception due to no incumbent realm), so it's okay to put step 3. after
- // step 7. and 8.
- if (!IsConstructor()) {
- V8ThrowException::ThrowTypeError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "{{operation_name}}",
- "{{interface_name}}",
- "The provided callback is not a constructor."));
- return v8::Nothing<{{return_cpp_type}}>();
- }
- {% endif %}
-
- v8::Local<v8::Function> function;
- {# Fill |function|. #}
- {% if interface_or_function == 'callback function' %}
- // callback function's invoke:
- // step 4. If ! IsCallable(F) is false:
- {% if is_treat_non_object_as_null %}
- if (!CallbackObject()->IsFunction()) {
- // Handle the special case of [LegacyTreatNonObjectAsNull].
- //
- {% if return_cpp_type == 'void' %}
- // step 4.1. If the callback function's return type is void, return.
- return v8::JustVoid();
- {% else %}
- // step 4.2. Return the result of converting undefined to the callback
- // function's return type.
- ExceptionState exception_state(GetIsolate(),
- ExceptionState::kExecutionContext,
- "{{interface_name}}",
- "{{operation_name}}");
- auto native_result =
- NativeValueTraits<{{return_native_value_traits_tag}}>::NativeValue(
- GetIsolate(), v8::Undefined(GetIsolate()), exception_state);
- if (exception_state.HadException())
- return v8::Nothing<{{return_cpp_type}}>();
- else
- return v8::Just<{{return_cpp_type}}>(native_result);
- {% endif %}{# if return_cpp_type == 'void' #}
- }
- {% else %}
- //
- // No [LegacyTreatNonObjectAsNull] presents. Must be always callable.
- DCHECK(CallbackObject()->IsFunction());
- {% endif %}
- function = CallbackFunction();
- {% else %}
- if (IsCallbackObjectCallable()) {
- // step 9.1. If value's interface is a single operation callback interface
- // and !IsCallable(O) is true, then set X to O.
- function = CallbackObject().As<v8::Function>();
- } else {
- // step 9.2.1. Let getResult be Get(O, opName).
- // step 9.2.2. If getResult is an abrupt completion, set completion to
- // getResult and jump to the step labeled return.
- v8::Local<v8::Value> value;
- if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(),
- V8String(GetIsolate(), "{{operation_name}}"))
- .ToLocal(&value)) {
- return v8::Nothing<{{return_cpp_type}}>();
- }
- // step 10. If !IsCallable(X) is false, then set completion to a new
- // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError
- // object, [[Target]]: empty}, and jump to the step labeled return.
- if (!value->IsFunction()) {
- V8ThrowException::ThrowTypeError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "{{operation_name}}",
- "{{interface_name}}",
- "The provided callback is not callable."));
- return v8::Nothing<{{return_cpp_type}}>();
- }
- function = value.As<v8::Function>();
- }
- {% endif %}
-
- {% if invoke_or_construct != 'construct' %}
- v8::Local<v8::Value> this_arg;
- {% endif %}
- {# Fill |this_arg|. #}
- {% if invoke_or_construct == 'invoke' %}
- if (callback_this_value.IsEmpty()) {
- // step 2. If thisArg was not given, let thisArg be undefined.
- this_arg = v8::Undefined(GetIsolate());
- } else {
- this_arg = callback_this_value.V8Value(callback_relevant_script_state);
- }
- {% elif interface_or_function == 'callback interface' %}
- if (!IsCallbackObjectCallable()) {
- // step 11. If value's interface is not a single operation callback
- // interface, or if !IsCallable(O) is false, set thisArg to O (overriding
- // the provided value).
- this_arg = CallbackObject();
- } else if (callback_this_value.IsEmpty()) {
- // step 2. If thisArg was not given, let thisArg be undefined.
- this_arg = v8::Undefined(GetIsolate());
- } else {
- this_arg = callback_this_value.V8Value(callback_relevant_script_state);
- }
- {% endif %}
-
- {% for argument in arguments if argument.enum_values %}
- // Enum values provided by Blink must be valid, otherwise typo.
-#if DCHECK_IS_ON()
- {
- {% set valid_enum_variables = 'kValid' + argument.name[0].upper() + argument.name[1:] + 'Values' %}
- {{declare_enum_validation_variable(argument.enum_values, valid_enum_variables) | trim | indent(4)}}
- ExceptionState exception_state(GetIsolate(),
- ExceptionState::kExecutionContext,
- "{{interface_name}}",
- "{{operation_name}}");
- if (!IsValidEnum({{argument.name}}, {{valid_enum_variables}}, base::size({{valid_enum_variables}}), "{{argument.enum_type}}", exception_state)) { //
- NOTREACHED();
- return v8::Nothing<{{return_cpp_type}}>();
- }
- }
-#endif
- {% endfor %}
-
- // step: Let esArgs be the result of converting args to an ECMAScript
- // arguments list. If this throws an exception, set completion to the
- // completion value representing the thrown exception and jump to the step
- // labeled return.
- {% if arguments %}
- v8::Local<v8::Object> argument_creation_context =
- callback_relevant_script_state->GetContext()->Global();
- ALLOW_UNUSED_LOCAL(argument_creation_context);
- {% set has_variadic_argument = arguments[-1].is_variadic %}
- {% set non_variadic_arguments = arguments | rejectattr('is_variadic') | list %}
- {% set variadic_argument = arguments[-1] if has_variadic_argument else None %}
- {% for argument in non_variadic_arguments %}
- v8::Local<v8::Value> {{argument.v8_name}} = {{argument.cpp_value_to_v8_value}};
- {% endfor %}
- {% if has_variadic_argument %}
- // Secure one element at least in |argv| to avoid the following restriction.
- //
- // C++14 8.3.4 Arrays
- // If the constant-expression (5.19) is present, it shall be a converted
- // constant expression of type std::size_t and its value shall be greater than
- // zero.
- const int argc = {{non_variadic_arguments|length}} + {{variadic_argument.name}}.size();
- v8::Local<v8::Value> argv[std::max(1, argc)];
- {% for argument in non_variadic_arguments %}
- argv[{{loop.index0}}] = {{argument.v8_name}};
- {% endfor %}
- for (wtf_size_t i = 0; i < {{variadic_argument.name}}.size(); ++i) {
- argv[{{non_variadic_arguments|length}} + i] = ToV8({{variadic_argument.name}}[i], argument_creation_context, GetIsolate());
- }
- {% else %}{# if has_variadic_argument #}
- constexpr int argc = {{non_variadic_arguments|length}};
- v8::Local<v8::Value> argv[] = { {{non_variadic_arguments | join(', ', 'v8_name')}} };
- static_assert(static_cast<size_t>(argc) == base::size(argv), "size mismatch");
- {% endif %}
- {% else %}{# if arguments #}
- const int argc = 0;
- {# Zero-length arrays are ill-formed in C++. #}
- v8::Local<v8::Value> *argv = nullptr;
- {% endif %}
-
- v8::Local<v8::Value> call_result;
- {# Fill |call_result|. #}
- {% if invoke_or_construct == 'construct' %}
- if (!V8ScriptRunner::CallAsConstructor(
- GetIsolate(),
- function,
- ExecutionContext::From(callback_relevant_script_state),
- argc,
- argv).ToLocal(&call_result)) {
- // step 11. If callResult is an abrupt completion, set completion to
- // callResult and jump to the step labeled return.
- return v8::Nothing<{{return_cpp_type}}>();
- }
- {% else %}
- // step: Let callResult be Call(X, thisArg, esArgs).
- if (!V8ScriptRunner::CallFunction(
- function,
- ExecutionContext::From(callback_relevant_script_state),
- this_arg,
- argc,
- argv,
- GetIsolate()).ToLocal(&call_result)) {
- // step: If callResult is an abrupt completion, set completion to callResult
- // and jump to the step labeled return.
- return v8::Nothing<{{return_cpp_type}}>();
- }
- {% endif %}
-
-
- // step: Set completion to the result of converting callResult.[[Value]] to
- // an IDL value of the same type as the operation's return type.
- {% if return_cpp_type == 'void' %}
- return v8::JustVoid();
- {% else %}
- {
- ExceptionState exception_state(GetIsolate(),
- ExceptionState::kExecutionContext,
- "{{interface_name}}",
- "{{operation_name}}");
- auto native_result =
- NativeValueTraits<{{return_native_value_traits_tag}}>::NativeValue(
- GetIsolate(), call_result, exception_state);
- if (exception_state.HadException())
- return v8::Nothing<{{return_cpp_type}}>();
- else
- return v8::Just<{{return_cpp_type}}>(native_result);
- }
- {% endif %}
-{% endmacro %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/constants.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/constants.cc.tmpl
deleted file mode 100644
index 2ba625e541f..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/constants.cc.tmpl
+++ /dev/null
@@ -1,71 +0,0 @@
-{% from 'methods.cc.tmpl' import runtime_timer_scope_disabled_by_default %}
-
-{##############################################################################}
-{% macro constant_getter_callback(constant) %}
-void {{v8_class_or_partial}}::{{constant.camel_case_name}}ConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(constant.rcs_counter) }}
- {% if constant.deprecate_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{constant.deprecate_as}});
- {% endif %}
- {% if constant.measure_as %}
- ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
- UseCounter::Count(execution_context_for_measurement, WebFeature::k{{constant.measure_as('ConstantGetter')}});
- {% if constant.high_entropy %}
- Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{constant.measure_as('ConstantGetter')}});
- {% endif %}
- {% endif %}
- {% if constant.idl_type in ('Double', 'Float') %}
- V8SetReturnValue(info, {{constant.value}});
- {% elif constant.idl_type == 'String' %}
- V8SetReturnValueString(info, "{{constant.value}}");
- {% else %}
- V8SetReturnValueInt(info, {{constant.value}});
- {% endif %}
-}
-{% endmacro %}
-
-
-{######################################}
-{% macro install_constants() %}
-{% if constants | has_constant_configuration %}
-{# Normal constants #}
-{
- static constexpr V8DOMConfiguration::ConstantConfiguration kConstants[] = {
- {% for constant in constants | has_constant_configuration %}
- {{constant_configuration(constant)}},
- {% endfor %}
- };
- V8DOMConfiguration::InstallConstants(
- isolate, interface_template, prototype_template,
- kConstants, base::size(kConstants));
-}
-{% endif %}
-{# Constants with [DeprecateAs] or [MeasureAs] #}
-{% for constant in constants | has_special_getter %}
-V8DOMConfiguration::InstallConstantWithGetter(
- isolate, interface_template, prototype_template,
- "{{constant.name}}", {{v8_class_or_partial}}::{{constant.camel_case_name}}ConstantGetterCallback);
-{% endfor %}
-{# Check constants #}
-{% if not do_not_check_constants %}
-{% for constant in constants %}
-{% if constant.idl_type not in ('Double', 'Float', 'String') %}
-{% set constant_cpp_class = constant.cpp_class or cpp_class %}
-static_assert({{constant.value}} == {{constant_cpp_class}}::{{constant.reflected_name}}, "the value of {{cpp_class}}_{{constant.reflected_name}} does not match with implementation");
-{% endif %}
-{% endfor %}
-{% endif %}
-{% endmacro %}
-
-
-{######################################}
-{%- macro constant_configuration(constant) %}
-{# Explicitly select the correct overload to populate the union. #}
-{% if constant.idl_type in ('Double', 'Float') %}
- {% set value = 'static_cast<double>(%s)' % constant.value %}
-{% else %}
- {# 'Short', 'Long' etc. #}
- {% set value = 'static_cast<int>(%s)' % constant.value %}
-{% endif %}
-{"{{constant.name}}", V8DOMConfiguration::kConstantType{{constant.idl_type}}, {{value}}}
-{%- endmacro %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/copyright_block.txt b/chromium/third_party/blink/renderer/bindings/templates/copyright_block.txt
deleted file mode 100644
index 22710834de0..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/copyright_block.txt
+++ /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.
-
-// This file has been auto-generated from the Jinja2 template
-// {{jinja_template_filename}}
-// by the script {{code_generator}}.
-// DO NOT MODIFY!
-
-// clang-format off
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl
deleted file mode 100644
index 14c6a2c66a5..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl
+++ /dev/null
@@ -1,41 +0,0 @@
-{% from 'dictionary_impl_common.cc.tmpl' import dictionary_setter_impl with context %}
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#include "{{this_include_header_path}}"
-
-{% for filename in cpp_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-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 %}
-}
-
-{{cpp_class}}::~{{cpp_class}}() = default;
-
-{% for member in members if not member.setter_inline %}
-{{dictionary_setter_impl(member)}}
-{% endfor %}
-
-void {{cpp_class}}::Trace(Visitor* visitor) const {
- {% for member in members if member.is_traceable %}
- visitor->Trace({{member.cpp_name}}_);
- {% endfor %}
- {% if parent_cpp_class %}
- {{parent_cpp_class}}::Trace(visitor);
- {% endif %}
-}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
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
deleted file mode 100644
index b5e295a269a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
+++ /dev/null
@@ -1,78 +0,0 @@
-{% from 'dictionary_impl_common.cc.tmpl' import dictionary_setter_impl with context %}
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% for decl in header_forward_decls %}
-class {{decl}};
-{% endfor %}
-
-{# FIXME: Add "final" if this class doesn\'t have subclasses #}
-class {{exported}}{{cpp_class}} : public {{parent_cpp_class}} {
- public:
- static {{cpp_class}}* Create() { return MakeGarbageCollected<{{cpp_class}}>(); }
- static {{cpp_class}}* Create(v8::Isolate* isolate) {
- return MakeGarbageCollected<{{cpp_class}}>();
- }
-
- {{cpp_class}}();
- ~{{cpp_class}}() override;
-
- {% 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 and not member.has_explicit_presence %}
- DCHECK({{member.nullable_indicator_name}});
- {% endif %}
- return {{member.getter_expression}};
- }
- {{member.setter_inline}}void {{member.setter_name}}({{member.rvalue_cpp_type}});
- {% if member.null_setter_name %}
- {{member.setter_inline}}void {{member.null_setter_name}}();
- {% endif %}
- {% if member.is_nullable %}
- // Migration adapters
- // Returns true iff this member has a non-null value. Returns false if the
- // value is missing or a null value.
- bool {{member.non_null_has_method_name}}() const { return {{member.has_method_expression}}; }
- // Returns the value if this member has a non-null value. Call
- // |{{member.non_null_has_method_name}}| in advance to check the condition.
- {{member.rvalue_cpp_type}} {{member.non_null_getter_name}}() const {
- DCHECK({{member.non_null_has_method_name}}());
- return {{member.getter_expression}};
- }
- {% endif %}
-
- {% endfor %}
- v8::Local<v8::Value> ToV8Impl(v8::Local<v8::Object>, v8::Isolate*) const override;
- void Trace(Visitor*) const override;
-
- private:
- {% for member in members if member.nullable_indicator_name %}
- bool {{member.nullable_indicator_name}} = false;
- {% endfor %}
-
- {% for member in members %}
- {{member.member_cpp_type}} {{member.cpp_name}}_;
- {% endfor %}
-
- friend class V8{{cpp_class}};
-};
-
-{% for member in members if member.setter_inline %}
-{{dictionary_setter_impl(member)}}
-{% endfor %}
-
-} // namespace blink
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cc.tmpl
deleted file mode 100644
index d4cf49b6baf..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cc.tmpl
+++ /dev/null
@@ -1,21 +0,0 @@
-{% macro dictionary_setter_impl(member) %}
-void {{cpp_class}}::{{member.setter_name}}({{member.rvalue_cpp_type}} value) {
- {{member.cpp_name}}_ = {{member.setter_value}};
- {% if member.nullable_indicator_name %}
- {{member.nullable_indicator_name}} = true;
- {% endif %}
-}
-
-{% if member.null_setter_name %}
-void {{cpp_class}}::{{member.null_setter_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}}();
- {% endif %}
-}
-{% endif %}
-{%- endmacro %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
deleted file mode 100644
index dc910f6d227..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
+++ /dev/null
@@ -1,203 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% from 'utilities.cc.tmpl' import declare_enum_validation_variable %}
-{% include 'copyright_block.txt' %}
-#include "{{this_include_header_path}}"
-
-{% for filename in cpp_includes if filename != '%s.h' % v8_class %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% if members %}
-static const base::span<const v8::Eternal<v8::Name>>
-eternal{{v8_class}}Keys(v8::Isolate* isolate) {
- static const char* const kKeys[] = {
- {% for member in members %}
- "{{member.name}}",
- {% endfor %}
- };
- return V8PerIsolateData::From(isolate)->FindOrCreateEternalNameCache(kKeys, kKeys);
-}
-{% endif %}
-
-{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %}
-void {{v8_class}}::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8_value, {{cpp_class}}* impl, ExceptionState& exception_state) {
- if (IsUndefinedOrNull(v8_value)) {
- {% if required_member_names %}
- exception_state.ThrowTypeError("Missing required member(s): {{required_member_names|join(', ')}}.");
- {% endif %}
- return;
- }
- if (!v8_value->IsObject()) {
- {% if use_permissive_dictionary_conversion %}
- // Do nothing.
- return;
- {% else %}
- exception_state.ThrowTypeError("cannot convert to dictionary.");
- return;
- {% endif %}
- }
- v8::Local<v8::Object> v8Object = v8_value.As<v8::Object>();
- ALLOW_UNUSED_LOCAL(v8Object);
-
- {% if parent_v8_class %}
- {{parent_v8_class}}::ToImpl(isolate, v8_value, impl, exception_state);
- if (exception_state.HadException())
- return;
-
- {% endif %}
-
- {# Declare local variables only when the dictionary has members to avoid unused variable warnings. #}
- {% if members %}
- const auto* keys = eternal{{v8_class}}Keys(isolate).data();
- v8::TryCatch block(isolate);
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- {% if has_origin_trial_members %}
- ExecutionContext* executionContext = ToExecutionContext(context);
- DCHECK(executionContext);
- {% endif %}{# has_origin_trial_members #}
- {% endif %}{# members #}
- {% for origin_trial_test, origin_trial_member_list in members | stringifykeygroupby('origin_trial_feature_name') %}
- {% filter origin_trial_enabled(origin_trial_test, "executionContext") %}
- {% for feature_name, member_list in origin_trial_member_list | stringifykeygroupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- {% for member in member_list %}
- v8::Local<v8::Value> {{member.v8_value}};
- if (!v8Object->Get(context, keys[{{members.index(member)}}].Get(isolate)).ToLocal(&{{member.v8_value}})) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
- if ({{member.v8_value}}.IsEmpty() || {{member.v8_value}}->IsUndefined()) {
- {% if member.is_required %}
- exception_state.ThrowTypeError("required member {{member.name}} is undefined.");
- return;
- {% else %}
- // Do nothing.
- {% endif %}
- {% if member.is_nullable and not member.is_string_type %}{# String types handle null via V8StringResource #}
- } else if ({{member.v8_value}}->IsNull()) {
- impl->{{member.null_setter_name}}();
- {% endif %}
- } else {
- {% if member.deprecate_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(isolate), WebFeature::k{{member.deprecate_as}});
- {% endif %}
- {% if member.is_callback_function_type %}
- if (!{{member.v8_value}}->IsFunction()) {
- exception_state.ThrowTypeError("member {{member.name}} is not a function.");
- return;
- }
- {% endif %}
- {{v8_value_to_local_cpp_value(member) | trim | indent}}
- {% if member.is_interface_type %}
- if (!{{member.cpp_value}}) {
- exception_state.ThrowTypeError("member {{member.name}} is not of type {{member.idl_type}}.");
- return;
- }
- {% endif %}
- {% if member.enum_values %}
- {{declare_enum_validation_variable(member.enum_values) | trim | indent}}
- if (!IsValidEnum({{member.cpp_value}}, kValidValues, base::size(kValidValues), "{{member.enum_type}}", exception_state))
- return;
- {% endif %}
- impl->{{member.setter_name}}({{member.cpp_value}});
- }
-
- {% endfor %}
- {% endfilter %}{# runtime_enabled #}
-
- {% endfor %}{# origin_trial_member_list grouped by runtime_enabled #}
- {% endfilter %}{# origin_trial_enabled #}
-
- {% endfor %}{# members grouped by origin_trial_enabled #}
-}
-
-v8::Local<v8::Value> {{cpp_class}}::ToV8Impl(v8::Local<v8::Object> creationContext, v8::Isolate* isolate) const {
- v8::Local<v8::Object> v8Object = v8::Object::New(isolate);
- if (!toV8{{cpp_class}}(this, v8Object, creationContext, isolate))
- return v8::Undefined(isolate);
- return v8Object;
-}
-
-bool toV8{{cpp_class}}(const {{cpp_class}}* impl, v8::Local<v8::Object> dictionary, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
- {% if parent_v8_class %}
- if (!toV8{{parent_cpp_class}}(impl, dictionary, creationContext, isolate))
- return false;
-
- {% endif %}
- {% if members %}
- const auto* keys = eternal{{v8_class}}Keys(isolate).data();
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
-
- auto create_property = [dictionary, context, keys, isolate](
- size_t key_index, v8::Local<v8::Value> value) {
- bool added_property;
- v8::Local<v8::Name> key = keys[key_index].Get(isolate);
- if (!dictionary->CreateDataProperty(context, key, value)
- .To(&added_property)) {
- return false;
- }
- return added_property;
- };
-
- {% if has_origin_trial_members %}
- ExecutionContext* executionContext = ToExecutionContext(context);
- DCHECK(executionContext);
- {% endif %}{# has_origin_trial_members #}
- {% endif %}{# members #}
- {% for origin_trial_test, origin_trial_member_list in members | stringifykeygroupby('origin_trial_feature_name') %}
- {% filter origin_trial_enabled(origin_trial_test, "executionContext") %}
- {% for feature_name, member_list in origin_trial_member_list | stringifykeygroupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- {% for member in member_list %}
- v8::Local<v8::Value> {{member.v8_value}};
- bool {{member.has_value_or_default}} = false;
- if (impl->{{member.has_method_name}}()) {
- {% if member.is_object %}
- DCHECK(impl->{{member.getter_name}}().IsObject());
- {% endif %}
- {{member.v8_value}} = {{member.cpp_value_to_v8_value}};
- {{member.has_value_or_default}} = true;
- {% if member.v8_default_value %}
- } else {
- {{member.v8_value}} = {{member.v8_default_value}};
- {{member.has_value_or_default}} = true;
- {% elif member.is_nullable and not member.has_explicit_presence %}
- } else {
- {{member.v8_value}} = v8::Null(isolate);
- {{member.has_value_or_default}} = true;
- {% elif member.is_required %}
- } else {
- NOTREACHED();
- {% endif %}
- }
- {# The _has_value_or_default variable will be optimized out.
- If there is a default value, the compiler will notice that all branches set it to true.
- If there is not, then the compiler will inline this call into the only branch that sets it to true.
- Either way, the code is efficient and the variable is completely elided. #}
- if ({{member.has_value_or_default}} &&
- !create_property({{members.index(member)}}, {{member.v8_value}})) {
- return false;
- }
-
- {% endfor %}
- {% endfilter %}{# runtime_enabled #}
-
- {% endfor %}{# origin_trial_member_list grouped by runtime_enabled #}
- {% endfilter %}{# origin_trial_enabled #}
-
- {% endfor %}{# members grouped by origin_trial_enabled #}
- return true;
-}
-
-{{cpp_class}}* NativeValueTraits<{{cpp_class}}>::NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) {
- {{cpp_class}}* impl = MakeGarbageCollected<{{cpp_class}}>();
- {{v8_class}}::ToImpl(isolate, value, impl, exception_state);
- return impl;
-}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.h.tmpl
deleted file mode 100644
index 6b0b2a7c761..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.h.tmpl
+++ /dev/null
@@ -1,46 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-class ExceptionState;
-
-class {{v8_class}} {
- public:
- {{exported}}static void ToImpl(v8::Isolate*, v8::Local<v8::Value>, {{cpp_class}}* impl, ExceptionState&);
-};
-
-{{exported}}bool toV8{{cpp_class}}(const {{cpp_class}}*, v8::Local<v8::Object> dictionary, v8::Local<v8::Object> creationContext, v8::Isolate*);
-
-template <class CallbackInfo>
-inline void V8SetReturnValue(const CallbackInfo& callbackInfo, {{cpp_class}}* impl) {
- V8SetReturnValue(callbackInfo, ToV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
-}
-
-template <class CallbackInfo>
-inline void V8SetReturnValue(const CallbackInfo& callbackInfo, {{cpp_class}}* impl, v8::Local<v8::Object> creationContext) {
- V8SetReturnValue(callbackInfo, ToV8(impl, creationContext, callbackInfo.GetIsolate()));
-}
-
-template <>
-struct NativeValueTraits<{{cpp_class}}> : public NativeValueTraitsBase<{{cpp_class}}*> {
- {{exported}}static {{cpp_class}}* NativeValue(v8::Isolate*, v8::Local<v8::Value>, ExceptionState&);
-};
-
-template <>
-struct V8TypeOf<{{cpp_class}}> {
- typedef {{v8_class}} Type;
-};
-
-} // namespace blink
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl
deleted file mode 100644
index 3097b0d3cbc..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl
+++ /dev/null
@@ -1,119 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-
-#include "{{this_include_header_path}}"
-
-#include <cstdint>
-
-{% for include_file in include_files %}
-#include "{{include_file}}"
-{% endfor %}
-
-namespace blink {
-
-// We use forward declaration instead of include for faster compile time here.
-{% for interface in interfaces %}
-{% if interface.has_constructor_callback %}
-namespace {{interface.internal_namespace}} {
-{{interface.component|upper}}_EXPORT void ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);
-} // namespace {{interface.internal_namespace}}
-
-{% endif %}
-{% endfor %}
-
-const intptr_t* {{class}}::GetTable() {
- static const intptr_t kReferenceTable[] = {
-#if defined(USE_V8_CONTEXT_SNAPSHOT)
- // Android is sensitive on its APK size, and this table improves it.
- // So we drop the table entries until the V8 context snapshot feature
- // is released on Android.
- {% for interface in interfaces %}
- {% set v8_class = interface.v8_class %}
- {# Attributes #}
- {%- for attribute in interface.attributes %}
- {%- for world_suffix in attribute.world_suffixes %}
- {% if not attribute.constructor_type %}
- reinterpret_cast<intptr_t>({{v8_class}}::{{attribute.camel_case_name}}AttributeGetterCallback{{world_suffix}}),
- {% else %}
- reinterpret_cast<intptr_t>({{v8_class}}::{{attribute.camel_case_name}}ConstructorGetterCallback{{world_suffix}}),
- {% endif %}
- {% if attribute.has_setter %}
- reinterpret_cast<intptr_t>({{v8_class}}::{{attribute.camel_case_name}}AttributeSetterCallback{{world_suffix}}),
- {% endif %}
- {%- endfor %}{# world_suffix #}
- {%- endfor %}{# attributes #}
- {# Methods / Operations #}
- {% for method in interface.methods %}
- {%- for world_suffix in method.world_suffixes %}
- {% if not method.overload_index or method.overloads %}
- {% if (method.overloads and method.overloads.visible and
- (not method.overloads.has_partial_overloads or not interface.is_partial)) or
- (not method.overloads and method.visible) %}
- reinterpret_cast<intptr_t>({{v8_class}}::{{method.camel_case_name}}MethodCallback{{world_suffix}}),
- {% endif %}
- {% endif %}
- {% if method.is_cross_origin and method.visible and not method.overloads %}
- reinterpret_cast<intptr_t>({{v8_class}}::{{method.camel_case_name}}OriginSafeMethodGetterCallback{{world_suffix}}),
- {% endif%}
- {% endfor %}
- {% endfor %}{# method #}
- {% if interface.has_cross_origin_named_getter %}
- reinterpret_cast<intptr_t>({{v8_class}}::CrossOriginNamedGetter),
- {% endif %}
- {% if interface.has_cross_origin_named_setter %}
- reinterpret_cast<intptr_t>({{v8_class}}::CrossOriginNamedSetter),
- {% endif %}
- {% if interface.has_cross_origin_named_enumerator %}
- reinterpret_cast<intptr_t>({{v8_class}}::CrossOriginNamedEnumerator),
- {% endif %}
- {% if interface.has_cross_origin_indexed_getter %}
- reinterpret_cast<intptr_t>({{v8_class}}::CrossOriginIndexedGetter),
- {% endif %}
- {% if interface.has_security_check %}
- reinterpret_cast<intptr_t>({{v8_class}}::SecurityCheck),
- reinterpret_cast<intptr_t>({{v8_class}}::GetWrapperTypeInfo()),
- {% endif %}
- {# Other properties #}
- {% if interface.has_constructor_callback %}
- reinterpret_cast<intptr_t>({{interface.internal_namespace}}::ConstructorCallback),
- {% endif %}
- {% if interface.named_property_getter %}
- reinterpret_cast<intptr_t>({{v8_class}}::NamedPropertyGetterCallback),
- {% endif %}
- {% if interface.named_property_setter %}
- reinterpret_cast<intptr_t>({{v8_class}}::NamedPropertySetterCallback),
- {% endif %}
- {% if interface.named_property_deleter %}
- reinterpret_cast<intptr_t>({{v8_class}}::NamedPropertyDeleterCallback),
- {% endif %}
- {% if interface.named_property_getter and interface.named_property_getter.is_enumerable %}
- reinterpret_cast<intptr_t>({{v8_class}}::NamedPropertyQueryCallback),
- reinterpret_cast<intptr_t>({{v8_class}}::NamedPropertyEnumeratorCallback),
- {% endif %}
- {% if interface.indexed_property_getter %}
- reinterpret_cast<intptr_t>({{v8_class}}::IndexedPropertyGetterCallback),
- reinterpret_cast<intptr_t>({{v8_class}}::IndexedPropertyDefinerCallback),
- reinterpret_cast<intptr_t>({{v8_class}}::IndexedPropertyDescriptorCallback),
- {% endif %}
- {% if interface.indexed_property_getter or interface.named_property_setter %}
- reinterpret_cast<intptr_t>({{v8_class}}::IndexedPropertySetterCallback),
- {% endif %}
- {% if interface.indexed_property_deleter %}
- reinterpret_cast<intptr_t>({{v8_class}}::IndexedPropertyDeleterCallback),
- {% endif %}
- {% if interface.has_security_check_function %}
- reinterpret_cast<intptr_t>({{v8_class}}::SecurityCheck),
- {% endif %}
- {% endfor %}{# interfaces #}
- reinterpret_cast<intptr_t>(V8ObjectConstructor::IsValidConstructorMode),
-#endif // USE_V8_CONTEXT_SNAPSHOT
- 0 // terminate with a null
- };
-
- return kReferenceTable;
-}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
deleted file mode 100644
index 36cb832ba9f..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
+++ /dev/null
@@ -1,1256 +0,0 @@
-{% extends 'interface_base.cc.tmpl' %}
-
-{% from 'methods.cc.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %}
-
-{##############################################################################}
-{% block indexed_property_getter %}
-{% if indexed_property_getter and not indexed_property_getter.is_custom %}
-{% set getter = indexed_property_getter %}
-static void IndexedPropertyGetter(
- uint32_t index,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if getter.is_raises_exception %}
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kIndexedGetterContext, "{{interface_name}}");
- {% endif %}
-
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
-
- // We assume that all the implementations support length() method, although
- // the spec doesn't require that length() must exist. It's okay that
- // the interface does not have length attribute as long as the
- // implementation supports length() member function.
- if (index >= impl->length())
- return; // Returns undefined due to out-of-range.
-
- {% set getter_name = getter.name or 'AnonymousIndexedGetter' %}
- {% set getter_arguments = ['index'] %}
- {% if getter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% set getter_arguments = ['script_state'] + getter_arguments %}
- {% endif %}
- {% if getter.is_raises_exception %}
- {% set getter_arguments = getter_arguments + ['exception_state'] %}
- {% endif %}
- {{getter.cpp_type}} result = impl->{{getter_name}}({{getter_arguments | join(', ')}});
- {{getter.v8_set_return_value}};
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_getter_callback %}
-{% if indexed_property_getter or named_property_getter %}
-{% set getter = indexed_property_getter or named_property_getter %}
-void {{v8_class_or_partial}}::IndexedPropertyGetterCallback(
- uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.indexed_property_getter_counter) }}
- {% if indexed_property_getter %}
-
- {% if getter.is_custom %}
- {{v8_class}}::IndexedPropertyGetterCustom(index, info);
- {% else %}
- {{internal_namespace}}::IndexedPropertyGetter(index, info);
- {% endif %}
-
- {% else %}{# otherwise, named property #}
-
- const AtomicString& property_name = AtomicString::Number(index);
-
- {% if getter.is_custom %}
- {{v8_class}}::NamedPropertyGetterCustom(property_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyGetter(property_name, info);
- {% endif %}
-
- {% endif %}{# indexed_property_getter #}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_setter %}
-{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %}
-{% if indexed_property_setter and not indexed_property_setter.is_custom %}
-{% set setter = indexed_property_setter %}
-static void IndexedPropertySetter(
- uint32_t index,
- v8::Local<v8::Value> v8_value,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if setter.has_exception_state %}
- ExceptionState exception_state(
- 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)}}
- {% if setter.has_type_checking_interface %}
- {# Type checking for interface types (if interface not implemented, throw
- TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
- if (!property_value{% if setter.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) {
- exception_state.ThrowTypeError("The provided value is not of type '{{setter.idl_type}}'.");
- return;
- }
- {% endif %}
-
- {% set setter_name = setter.name or 'AnonymousIndexedSetter' %}
- {% set setter_arguments = ['index', 'property_value'] %}
- {% if setter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% set setter_arguments = ['script_state'] + setter_arguments %}
- {% endif %}
- {% if setter.is_raises_exception %}
- {% set setter_arguments = setter_arguments + ['exception_state'] %}
- {% endif %}
- IndexedPropertySetterResult result = impl->{{setter_name}}({{setter_arguments | join(', ')}});
- {% if setter.is_raises_exception %}
- if (exception_state.HadException())
- return;
- {% endif %}
- if (result == IndexedPropertySetterResult::kDidNotIntercept)
- return;
- V8SetReturnValue(info, v8_value);
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_setter_callback %}
-{% 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> v8_value,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if indexed_property_setter %}
-
- {% if setter.is_custom %}
- {{v8_class}}::IndexedPropertySetterCustom(index, v8_value, info);
- {% else %}
- {{internal_namespace}}::IndexedPropertySetter(index, v8_value, info);
- {% endif %}
-
- {% elif not indexed_property_getter and named_property_setter %}
-
- const AtomicString& property_name = AtomicString::Number(index);
-
- {% if setter.is_custom %}
- {{v8_class}}::NamedPropertySetterCustom(property_name, v8_value, info);
- {% else %}
- {{internal_namespace}}::NamedPropertySetter(property_name, v8_value, info);
- {% endif %}
-
- {% else %}{# neither of indexed_property_setter nor named_property_setter #}
-
- // No indexed property setter defined. Do not fall back to the default
- // setter.
- V8SetReturnValue(info, v8::Null(info.GetIsolate()));
- if (info.ShouldThrowOnError()) {
- ExceptionState exception_state(info.GetIsolate(),
- ExceptionState::kIndexedSetterContext,
- "{{interface_name}}");
- {% if setter.is_ce_reactions %}
- CEReactionsScope ce_reactions_scope;
- {% endif %}
- exception_state.ThrowTypeError("Index property setter is not supported.");
- }
-
- {% endif %}{# indexed/named_property_setter #}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_descriptor %}
-{% if indexed_property_getter %}
-static void IndexedPropertyDescriptor(
- uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
- // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
- // Steps 1.1 to 1.2.4 are covered here: we rely on indexedPropertyGetter() to
- // call the getter function and check that |index| is a valid property index,
- // in which case it will have set info.GetReturnValue() to something other
- // than undefined.
- {{v8_class_or_partial}}::IndexedPropertyGetterCallback(index, info);
- v8::Local<v8::Value> getter_value = info.GetReturnValue().Get();
- if (!getter_value->IsUndefined()) {
- // 1.2.5. Let |desc| be a newly created Property Descriptor with no fields.
- // 1.2.6. Set desc.[[Value]] to the result of converting value to an
- // ECMAScript value.
- // 1.2.7. If O implements an interface with an indexed property setter,
- // then set desc.[[Writable]] to true, otherwise set it to false.
- v8::PropertyDescriptor desc(getter_value, {% if indexed_property_setter %}true{% else %}false{% endif %});
- // 1.2.8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
- desc.set_enumerable(true);
- desc.set_configurable(true);
- // 1.2.9. Return |desc|.
- V8SetReturnValue(info, desc);
- }
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_descriptor %}
-{% if not indexed_property_getter and named_property_getter %}
-static void NamedPropertyDescriptor(
- uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
- // This function is called when an IDL interface supports named properties
- // but not indexed properties. When a numeric property is queried, V8 calls
- // indexedPropertyDescriptorCallback(), which calls this function.
-
- {% if named_property_getter.is_enumerable %}
- // Since we initialize our indexed and named property handlers differently
- // (the former use descriptors and definers, the latter uses a query
- // callback), we need to inefficiently call the query callback and convert
- // the v8::PropertyAttribute integer it returns into a v8::PropertyDescriptor
- // expected by a descriptor callback.
- // TODO(rakuco): remove this hack once we switch named property handlers to
- // using descriptor and definer callbacks (bug 764633).
- const AtomicString& index_as_name = AtomicString::Number(index);
- {% if named_property_getter.is_custom_property_query %}
- {{v8_class}}::NamedPropertyQueryCustom(index_as_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyQuery(index_as_name, info);
- {% endif %}
- v8::Local<v8::Value> getter_value = info.GetReturnValue().Get();
- if (!getter_value->IsUndefined()) {
- DCHECK(getter_value->IsInt32());
- const int32_t props =
- getter_value->ToInt32(info.GetIsolate()->GetCurrentContext())
- .ToLocalChecked()
- ->Value();
- v8::PropertyDescriptor desc(V8String(info.GetIsolate(), index_as_name),
- !(props & v8::ReadOnly));
- desc.set_enumerable(!(props & v8::DontEnum));
- desc.set_configurable(!(props & v8::DontDelete));
- V8SetReturnValue(info, desc);
- }
- {% else %}{# TODO(rakuco): drop this once we remove [NotEnumerable] getters #}
- // This IDL interface defines a [NotEnumerable] getter. We need to do
- // something similar to indexedPropertyDescriptor(): call
- // indexedPropertyGetterCallback, let it end up calling the named property
- // getter and, if all goes well, we create a v8::PropertyDescriptor with the
- // right values.
- {{v8_class_or_partial}}::IndexedPropertyGetterCallback(index, info);
- v8::Local<v8::Value> getter_value = info.GetReturnValue().Get();
- if (!getter_value->IsUndefined()) {
- v8::PropertyDescriptor desc(getter_value, {% if named_property_setter %}true{% else %}false{% endif %});
- desc.set_enumerable(false);
- desc.set_configurable(true);
- V8SetReturnValue(info, desc);
- }
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_descriptor_callback %}
-{% if indexed_property_getter or named_property_getter %}
-void {{v8_class_or_partial}}::IndexedPropertyDescriptorCallback(
- uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if indexed_property_getter %}
- {{internal_namespace}}::IndexedPropertyDescriptor(index, info);
- {% else %}{# The interface only supports named properties. #}
- {{internal_namespace}}::NamedPropertyDescriptor(index, info);
- {% endif %}{# indexed_property_getter #}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_deleter %}
-{% if indexed_property_deleter and not indexed_property_deleter.is_custom %}
-{% set deleter = indexed_property_deleter %}
-static void IndexedPropertyDeleter(
- uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
- {% if deleter.is_raises_exception %}
- ExceptionState exception_state(
- 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());
-
- {% set deleter_name = deleter.name or 'AnonymousIndexedDeleter' %}
- {% set deleter_arguments = ['index'] %}
- {% if deleter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% set deleter_arguments = ['script_state'] + deleter_arguments %}
- {% endif %}
- {% if deleter.is_raises_exception %}
- {% set deleter_arguments = deleter_arguments + ['exception_state'] %}
- {% endif %}
- NamedPropertyDeleterResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}});
- {% if deleter.is_raises_exception %}
- if (exception_state.HadException())
- return;
- {% endif %}
- if (result == NamedPropertyDeleterResult::kDidNotIntercept)
- return;
- V8SetReturnValue(info, result == NamedPropertyDeleterResult::kDeleted);
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_deleter_callback %}
-{% 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 indexed_property_deleter %}
-
- {% if deleter.is_custom %}
- {{v8_class}}::IndexedPropertyDeleterCustom(index, info);
- {% else %}
- {{internal_namespace}}::IndexedPropertyDeleter(index, info);
- {% endif %}
-
- {% else %}{# otherwise, named property #}
-
- const AtomicString& property_name = AtomicString::Number(index);
-
- {% if deleter.is_custom %}
- {{v8_class}}::NamedPropertyDeleterCustom(property_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyDeleter(property_name, info);
- {% endif %}
-
- {% endif %}{# indexed_property_deleter #}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block indexed_property_definer_callback %}
-{% if indexed_property_getter %}
-void {{v8_class_or_partial}}::IndexedPropertyDefinerCallback(
- uint32_t index,
- const v8::PropertyDescriptor& desc,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
-{% if indexed_property_setter %}
- // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
- // 3.9.3. [[DefineOwnProperty]]
- // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then
- // return false.
- if (desc.has_get() || desc.has_set()) {
- V8SetReturnValue(info, v8::Null(info.GetIsolate()));
- if (info.ShouldThrowOnError()) {
- ExceptionState exception_state(info.GetIsolate(),
- ExceptionState::kIndexedSetterContext,
- "{{interface_name}}");
- exception_state.ThrowTypeError("Accessor properties are not allowed.");
- }
- return;
- }
-
- // Return nothing and fall back to indexedPropertySetterCallback.
-{% else %}{# indexed_property_setter #}
- // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
- // 3.9.3. [[DefineOwnProperty]]
- // step 1.2. If O does not implement an interface with an indexed property
- // setter, then return false.
- //
- // https://html.spec.whatwg.org/C/window-object.html#windowproxy-defineownproperty
- // 7.4.6 [[DefineOwnProperty]] (P, Desc)
- // step 2.1. If P is an array index property name, return false.
- V8SetReturnValue(info, v8::Null(info.GetIsolate()));
- if (info.ShouldThrowOnError()) {
- ExceptionState exception_state(info.GetIsolate(),
- ExceptionState::kIndexedSetterContext,
- "{{interface_name}}");
- exception_state.ThrowTypeError("Index property setter is not supported.");
- }
-{% endif %}{# indexed_property_setter #}
-}
-
-{% endif %}{# indexed_property_getter #}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_getter %}
-{% if named_property_getter and not named_property_getter.is_custom %}
-{% set getter = named_property_getter %}
-static void NamedPropertyGetter(const AtomicString& name,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if getter.is_raises_exception %}
- const std::string& name_in_utf8 = name.Utf8();
- ExceptionState exception_state(
- info.GetIsolate(),
- ExceptionState::kGetterContext,
- "{{interface_name}}",
- name_in_utf8.c_str());
- {% endif %}
- {% if getter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
-
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
- {% if getter.use_output_parameter_for_result %}
- {{getter.cpp_type}} result;
- {{getter.cpp_value}};
- {% else %}
- {{getter.cpp_type}} result = {{getter.cpp_value}};
- {% endif %}
- if ({{getter.is_null_expression}})
- return;
- {{getter.v8_set_return_value}};
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_getter_callback %}
-{% if named_property_getter %}
-{% set getter = named_property_getter %}
-void {{v8_class_or_partial}}::NamedPropertyGetterCallback(
- v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_getter_counter) }}
- if (!name->IsString())
- return;
- const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
-
- {% if getter.is_custom %}
- {{v8_class}}::NamedPropertyGetterCustom(property_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyGetter(property_name, info);
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_setter %}
-{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %}
-{% if named_property_setter and not named_property_setter.is_custom %}
-{% set setter = named_property_setter %}
-static void NamedPropertySetter(
- const AtomicString& name,
- v8::Local<v8::Value> v8_value,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if setter.has_exception_state %}
- const std::string& name_in_utf8 = name.Utf8();
- ExceptionState exception_state(
- info.GetIsolate(),
- ExceptionState::kSetterContext,
- "{{interface_name}}",
- name_in_utf8.c_str());
- {% endif %}
- {% if setter.is_ce_reactions %}
- CEReactionsScope ce_reactions_scope;
- {% endif %}
- {% if setter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
-
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
- {{v8_value_to_local_cpp_value(setter) | trim | indent(2)}}
- {% if setter.has_type_checking_interface %}
- {# Type checking for interface types (if interface not implemented, throw
- TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
- if (!property_value{% if setter.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) {
- exception_state.ThrowTypeError("The provided value is not of type '{{setter.idl_type}}'.");
- return;
- }
- {% endif %}
-
- {% set setter_name = setter.name or 'AnonymousNamedSetter' %}
- {% set setter_arguments = ['name', 'property_value'] %}
- {% if setter.is_call_with_script_state %}
- {% set setter_arguments = ['script_state'] + setter_arguments %}
- {% endif %}
- {% if setter.is_raises_exception %}
- {% set setter_arguments = setter_arguments + ['exception_state'] %}
- {% endif %}
- NamedPropertySetterResult result = impl->{{setter_name}}({{setter_arguments | join(', ')}});
- {% if setter.is_raises_exception %}
- if (exception_state.HadException())
- return;
- {% endif %}
- if (result == NamedPropertySetterResult::kDidNotIntercept)
- return;
- V8SetReturnValue(info, v8_value);
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_setter_callback %}
-{% if named_property_setter %}
-{% set setter = named_property_setter %}
-void {{v8_class_or_partial}}::NamedPropertySetterCallback(
- v8::Local<v8::Name> name,
- v8::Local<v8::Value> v8_value,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_setter_counter) }}
- if (!name->IsString())
- return;
- const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
-
- {% if setter.is_custom %}
- {{v8_class}}::NamedPropertySetterCustom(property_name, v8_value, info);
- {% else %}
- {{internal_namespace}}::NamedPropertySetter(property_name, v8_value, info);
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_deleter %}
-{% if named_property_deleter and not named_property_deleter.is_custom %}
-{% set deleter = named_property_deleter %}
-static void NamedPropertyDeleter(
- const AtomicString& name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
- {% if deleter.is_raises_exception %}
- const std::string& name_in_utf8 = name.Utf8();
- ExceptionState exception_state(
- info.GetIsolate(),
- ExceptionState::kDeletionContext,
- "{{interface_name}}",
- name_in_utf8.c_str());
- {% endif %}
- {% if deleter.is_ce_reactions %}
- CEReactionsScope ce_reactions_scope;
- {% endif %}
- {% if deleter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
-
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
-
- {% set deleter_name = deleter.name or 'AnonymousNamedDeleter' %}
- {% set deleter_arguments = ['name'] %}
- {% if deleter.is_call_with_script_state %}
- {% set deleter_arguments = ['script_state'] + deleter_arguments %}
- {% endif %}
- {% if deleter.is_raises_exception %}
- {% set deleter_arguments = deleter_arguments + ['exception_state'] %}
- {% endif %}
- NamedPropertyDeleterResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}});
- {% if deleter.is_raises_exception %}
- if (exception_state.HadException())
- return;
- {% endif %}
- if (result == NamedPropertyDeleterResult::kDidNotIntercept)
- return;
- V8SetReturnValue(info, result == NamedPropertyDeleterResult::kDeleted);
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_deleter_callback %}
-{% if named_property_deleter %}
-{% set deleter = named_property_deleter %}
-void {{v8_class_or_partial}}::NamedPropertyDeleterCallback(
- v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
- if (!name->IsString())
- return;
- const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
-
- {% if deleter.is_custom %}
- {{v8_class}}::NamedPropertyDeleterCustom(property_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyDeleter(property_name, info);
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_query %}
-{% if named_property_getter and named_property_getter.is_enumerable and
- not named_property_getter.is_custom_property_query %}
-{% set getter = named_property_getter %}
-{# If there is an enumerator, there MUST be a query method to properly
- communicate property attributes. #}
-{% if indexed_property_getter %}
-static void NamedPropertyQuery(
- const AtomicString& name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
-{% else %}
-{# If we do not have an indexed property getter, this function is called #}
-{# from namedPropertyDescriptor(), whose v8::PropertyCallbackInfo has a #}
-{# v8::Value instead of a v8::Integer. We use this template trick to make #}
-{# the compiler accept the call. #}
-{# TODO(rakuco): remove this hack once we switch named property handlers to #}
-{# using descriptor and definer callbacks (bug 764633). #}
-template <typename T>
-static void NamedPropertyQuery(
- const AtomicString& name, const v8::PropertyCallbackInfo<T>& info) {
-{% endif %}
- const std::string& name_in_utf8 = name.Utf8();
- ExceptionState exception_state(
- info.GetIsolate(),
- ExceptionState::kGetterContext,
- "{{interface_name}}",
- name_in_utf8.c_str());
- {% if getter.is_call_with_script_state %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
-
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
-
- {% set getter_arguments = ['name', 'exception_state'] %}
- {% if getter.is_call_with_script_state %}
- {% set getter_arguments = ['script_state'] + getter_arguments %}
- {% endif %}
- bool result = impl->NamedPropertyQuery({{getter_arguments | join(', ')}});
- if (!result)
- return;
- // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
- // 2.7. If |O| implements an interface with a named property setter, then set
- // desc.[[Writable]] to true, otherwise set it to false.
- // 2.8. If |O| implements an interface with the
- // [LegacyUnenumerableNamedProperties] extended attribute, then set
- // desc.[[Enumerable]] to false, otherwise set it to true.
- {% if named_property_setter %}
- {% set desc_properties = ['v8::None'] %}
- {% else %}
- {% set desc_properties = ['v8::ReadOnly'] %}
- {% endif %}
- {% if has_legacy_unenumerable_named_properties %}
- {% set desc_properties = ['v8::DontEnum'] + desc_properties %}
- {% endif %}
- V8SetReturnValueInt(info, {{desc_properties | join(' | ')}});
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_query_callback %}
-{% if named_property_getter and named_property_getter.is_enumerable %}
-{% set getter = named_property_getter %}
-void {{v8_class_or_partial}}::NamedPropertyQueryCallback(
- v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_query_counter) }}
- if (!name->IsString())
- return;
- const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
-
- {% if getter.is_custom_property_query %}
- {{v8_class}}::NamedPropertyQueryCustom(property_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyQuery(property_name, info);
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_enumerator %}
-{% if named_property_getter and named_property_getter.is_enumerable and
- not named_property_getter.is_custom_property_enumerator %}
-static void NamedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
- ExceptionState exception_state(
- info.GetIsolate(),
- ExceptionState::kEnumerationContext,
- "{{interface_name}}");
-
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
-
- Vector<String> names;
- impl->NamedPropertyEnumerator(names, exception_state);
- if (exception_state.HadException())
- return;
- V8SetReturnValue(info, ToV8(names, info.Holder(), info.GetIsolate()).As<v8::Array>());
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_property_enumerator_callback %}
-{% if named_property_getter and named_property_getter.is_enumerable %}
-{% set getter = named_property_getter %}
-void {{v8_class_or_partial}}::NamedPropertyEnumeratorCallback(
- const v8::PropertyCallbackInfo<v8::Array>& info) {
- {% if getter.is_custom_property_enumerator %}
- {{v8_class}}::NamedPropertyEnumeratorCustom(info);
- {% else %}
- {{internal_namespace}}::NamedPropertyEnumerator(info);
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block named_constructor %}
-{% from 'methods.cc.tmpl' import generate_constructor with context %}
-{% if named_constructor %}
-{% set active_scriptwrappable_inheritance =
- 'kInheritFromActiveScriptWrappable'
- if active_scriptwrappable else
- 'kNotInheritFromActiveScriptWrappable' %}
-// Suppress warning: global constructors, because struct WrapperTypeInfo is trivial
-// and does not depend on another global objects.
-#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wglobal-constructors"
-#endif
-const WrapperTypeInfo {{snake_case_v8_class}}_constructor_wrapper_type_info = {
- gin::kEmbedderBlink,
- {{v8_class}}Constructor::DomTemplate,
- {{install_conditional_features_func or 'nullptr'}},
- "{{interface_name}}",
- nullptr,
- WrapperTypeInfo::kWrapperTypeObjectPrototype,
- WrapperTypeInfo::{{wrapper_class_id}},
- WrapperTypeInfo::{{active_scriptwrappable_inheritance}},
-};
-#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-{{generate_constructor(named_constructor)}}
-v8::Local<v8::FunctionTemplate> {{v8_class}}Constructor::DomTemplate(
- v8::Isolate* isolate, const DOMWrapperWorld& world) {
- static int dom_template_key; // This address is used for a key to look up the dom template.
- V8PerIsolateData* data = V8PerIsolateData::From(isolate);
- v8::Local<v8::FunctionTemplate> result =
- data->FindInterfaceTemplate(world, &dom_template_key);
- if (!result.IsEmpty())
- return result;
-
- result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback);
- v8::Local<v8::ObjectTemplate> instance_template = result->InstanceTemplate();
- instance_template->SetInternalFieldCount({{v8_class}}::kInternalFieldCount);
- result->SetClassName(V8AtomicString(isolate, "{{named_constructor.name}}"));
- result->Inherit({{v8_class}}::DomTemplate(isolate, world));
- data->SetInterfaceTemplate(world, &dom_template_key, result);
- return result;
-}
-
-void {{v8_class}}Constructor::NamedConstructorAttributeGetter(
- v8::Local<v8::Name> property_name,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- v8::Local<v8::Context> creationContext = info.Holder()->CreationContext();
- V8PerContextData* per_context_data = V8PerContextData::From(creationContext);
- if (!per_context_data) {
- // TODO(yukishiino): Return a valid named constructor even after the context is detached
- return;
- }
-
- v8::Local<v8::Function> named_constructor =
- per_context_data->ConstructorForType({{v8_class}}Constructor::GetWrapperTypeInfo());
-
- // Set the prototype of named constructors to the regular constructor.
- static const V8PrivateProperty::SymbolKey kPrivatePropertyInitialized;
- auto private_property =
- V8PrivateProperty::GetSymbol(
- info.GetIsolate(), kPrivatePropertyInitialized);
- v8::Local<v8::Context> current_context = info.GetIsolate()->GetCurrentContext();
- v8::Local<v8::Value> private_value;
-
- if (!private_property.GetOrUndefined(named_constructor).ToLocal(&private_value) ||
- private_value->IsUndefined()) {
- v8::Local<v8::Function> interface =
- per_context_data->ConstructorForType({{v8_class}}::GetWrapperTypeInfo());
- v8::Local<v8::Value> interface_prototype =
- interface->Get(current_context, V8AtomicString(info.GetIsolate(), "prototype"))
- .ToLocalChecked();
- // https://heycam.github.io/webidl/#named-constructors
- // 8. Perform ! DefinePropertyOrThrow(F, "prototype",
- // PropertyDescriptor{[[Value]]: proto, [[Writable]]: false,
- // [[Enumerable]]: false,
- // [Configurable]]: false}).
- const v8::PropertyAttribute prototype_attributes =
- static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
- bool result = named_constructor->DefineOwnProperty(
- current_context, V8AtomicString(info.GetIsolate(), "prototype"),
- interface_prototype, prototype_attributes).ToChecked();
- CHECK(result);
- private_property.Set(named_constructor, v8::True(info.GetIsolate()));
- }
-
- V8SetReturnValue(info, named_constructor);
-}
-
-{% endif %}
-{% endblock %}
-
-{##############################################################################}
-{% block overloaded_constructor %}
-{% if constructor_overloads %}
-static void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kConstructionContext, "{{interface_name}}");
- {# This follows the overload resolution algorithm. #}
- {# https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm #}
- {# 3. Initialize argcount to be min(maxarg, n). #}
- switch (std::min({{constructor_overloads.maxarg}}, info.Length())) {
- {# 4. Remove from S all entries whose type list is not of length argcount. #}
- {% for length, tests_constructors in constructor_overloads.length_tests_methods %}
- {# 12. If i = d, then: #}
- case {{length}}:
- {# Then resolve by testing argument #}
- {% for test, constructor in tests_constructors %}
- if ({{test}}) {
- {{internal_namespace}}::Constructor{{constructor.overload_index}}(info);
- return;
- }
- {% if "exception_state" in test %}
- if (exception_state.HadException()) {
- exception_state.RethrowV8Exception(exception_state.GetException());
- return;
- }
- {% endif %}
- {% endfor %}
- break;
- {% endfor %}
- default:
- {# Invalid arity, throw error #}
- {# Report full list of valid arities if gaps and above minimum #}
- {% if constructor_overloads.valid_arities %}
- if (info.Length() >= {{constructor_overloads.length}}) {
- exception_state.ThrowTypeError(ExceptionMessages::InvalidArity("{{constructor_overloads.valid_arities}}", info.Length()));
- return;
- }
- {% endif %}
- {# Otherwise just report "not enough arguments" #}
- exception_state.ThrowTypeError(ExceptionMessages::NotEnoughArguments({{constructor_overloads.length}}, info.Length()));
- return;
- }
- {# No match, throw error #}
- exception_state.ThrowTypeError("No matching constructor signature.");
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block constructor_callback %}
-{% if constructors or has_custom_constructor or has_html_constructor %}
-{{exported}}void ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.constructor_counter) }}
- {% if measure_as %}
- ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
- UseCounter::Count(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}});
- {% if high_entropy %}
- Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}});
- {% endif %}
- {% endif %}
- if (!info.IsConstructCall()) {
- V8ThrowException::ThrowTypeError(
- info.GetIsolate(),
- ExceptionMessages::ConstructorNotCallableAsFunction("{{interface_name}}"));
- return;
- }
-
- if (ConstructorMode::Current(info.GetIsolate()) == ConstructorMode::kWrapExistingObject) {
- V8SetReturnValue(info, info.Holder());
- return;
- }
-
- {% if has_custom_constructor %}
- {{v8_class}}::ConstructorCustom(info);
- {% elif has_html_constructor %}
- V8HTMLConstructor::HtmlConstructor(
- info, *{{v8_class}}::GetWrapperTypeInfo(), HTMLElementType::k{{interface_name}});
- {% else %}
- {{internal_namespace}}::Constructor(info);
- {% endif %}
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% macro install_origin_safe_method(method, instance_template, prototype_template, interface_template, signature) %}
-{% from 'utilities.cc.tmpl' import property_location %}
-{# TODO(dcheng): Currently, bindings must create a function object for each
- realm as a hack to support the incumbent realm. Clean this up when Blink
- properly supports the incumbent realm. #}
-{% set function_callback =
- '%s::%sMethodCallback' % (v8_class_or_partial, method.camel_case_name) %}
-{% set property_attribute =
- 'static_cast<v8::PropertyAttribute>(%s)' %
- ' | '.join(method.property_attributes or ['v8::None']) %}
-{% set holder_check = 'V8DOMConfiguration::kCheckHolder' %}
-static const V8DOMConfiguration::MethodConfiguration k{{method.camel_case_name}}OriginSafeMethodConfiguration[] = {
-{% if method.is_per_world_bindings %}
-{% set function_callback_for_main_world = '%sForMainWorld' % function_callback %}
- {
- "{{method.name}}",
- {{function_callback_for_main_world}},
- {{method.length}},
- {{property_attribute}},
- {{property_location(method)}},
- {{holder_check}},
- V8DOMConfiguration::kCheckAccess,
- V8DOMConfiguration::kHasSideEffect,
- V8DOMConfiguration::MainWorld,
- },
- {
- "{{method.name}}",
- {{function_callback}},
- {{method.length}},
- {{property_attribute}},
- {{property_location(method)}},
- {{holder_check}},
- V8DOMConfiguration::kCheckAccess,
- V8DOMConfiguration::kHasSideEffect,
- V8DOMConfiguration::NonMainWorlds,
- }
-{% else %}
- {
- "{{method.name}}",
- {{function_callback}},
- {{method.length}},
- {{property_attribute}},
- {{property_location(method)}},
- {{holder_check}},
- V8DOMConfiguration::kCheckAccess,
- V8DOMConfiguration::kHasSideEffect,
- V8DOMConfiguration::kAllWorlds,
- }
-{% endif %}
-};
-for (const auto& method_config : k{{method.camel_case_name}}OriginSafeMethodConfiguration)
- V8DOMConfiguration::InstallMethod(isolate, world, {{instance_template}}, {{prototype_template}}, {{interface_template}}, {{signature}}, method_config);
-{%- endmacro %}
-
-
-{##############################################################################}
-{% macro install_indexed_property_handler(target) %}
-{% set indexed_property_getter_callback =
- '%s::IndexedPropertyGetterCallback' % v8_class_or_partial %}
-{% set indexed_property_setter_callback =
- '%s::IndexedPropertySetterCallback' % v8_class_or_partial
- if indexed_property_getter or named_property_setter else 'nullptr' %}
-{% set indexed_property_descriptor_callback =
- '%s::IndexedPropertyDescriptorCallback' % v8_class_or_partial
- if indexed_property_getter or named_property_getter else 'nullptr' %}
-{% set indexed_property_deleter_callback =
- '%s::IndexedPropertyDeleterCallback' % v8_class_or_partial
- if indexed_property_deleter or named_property_deleter else 'nullptr' %}
-{% set indexed_property_enumerator_callback =
- 'IndexedPropertyEnumerator<%s>' % cpp_class
- if indexed_property_getter.is_enumerable else 'nullptr' %}
-{% set indexed_property_definer_callback =
- '%s::IndexedPropertyDefinerCallback' % v8_class_or_partial
- if indexed_property_getter else 'nullptr' %}
-{% set property_handler_flags =
- 'v8::PropertyHandlerFlags::kHasNoSideEffect'
- if indexed_property_getter.has_no_side_effect else 'v8::PropertyHandlerFlags::kNone' %}
-v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(
- {{indexed_property_getter_callback}},
- {{indexed_property_setter_callback}},
- {{indexed_property_descriptor_callback}},
- {{indexed_property_deleter_callback}},
- {{indexed_property_enumerator_callback}},
- {{indexed_property_definer_callback}},
- v8::Local<v8::Value>(),
- {{property_handler_flags}});
-{{target}}->SetHandler(indexedPropertyHandlerConfig);
-{%- endmacro %}
-
-
-{##############################################################################}
-{% macro install_named_property_handler(target) %}
-{% set named_property_getter_callback =
- '%s::NamedPropertyGetterCallback' % v8_class_or_partial %}
-{% set named_property_setter_callback =
- '%s::NamedPropertySetterCallback' % v8_class_or_partial
- if named_property_setter else 'nullptr' %}
-{% set named_property_query_callback =
- '%s::NamedPropertyQueryCallback' % v8_class_or_partial
- if named_property_getter.is_enumerable else 'nullptr' %}
-{% set named_property_deleter_callback =
- '%s::NamedPropertyDeleterCallback' % v8_class_or_partial
- if named_property_deleter else 'nullptr' %}
-{% set named_property_enumerator_callback =
- '%s::NamedPropertyEnumeratorCallback' % v8_class_or_partial
- if named_property_getter.is_enumerable else 'nullptr' %}
-{% set property_handler_flags_list =
- ['int(v8::PropertyHandlerFlags::kOnlyInterceptStrings)'] %}
-{% if not is_override_builtins %}
-{% set property_handler_flags_list =
- property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kNonMasking)'] %}
-{% endif %}
-{% if named_property_getter.has_no_side_effect %}
-{% set property_handler_flags_list =
- property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kHasNoSideEffect)'] %}
-{% endif %}
-{% set property_handler_flags =
- 'static_cast<v8::PropertyHandlerFlags>(%s)' %
- ' | '.join(property_handler_flags_list) %}
-v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}, v8::Local<v8::Value>(), {{property_handler_flags}});
-{{target}}->SetHandler(namedPropertyHandlerConfig);
-{%- endmacro %}
-
-
-{##############################################################################}
-{% block get_dom_template %}
-{% if not is_array_buffer_or_view %}
-v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate(
- v8::Isolate* isolate, const DOMWrapperWorld& world) {
- {% set install_template_function = '%s::install_%s_template_function_' % (v8_class, snake_case_v8_class) if has_partial_interface else 'Install%sTemplate' % v8_class %}
- return V8DOMConfiguration::DomClassTemplate(
- isolate, world, const_cast<WrapperTypeInfo*>({{v8_class}}::GetWrapperTypeInfo()),
- {{install_template_function}});
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block get_dom_template_for_named_properties_object %}
-{% if has_named_properties_object %}
-v8::Local<v8::FunctionTemplate>
-{{v8_class}}::DomTemplateForNamedPropertiesObject(
- v8::Isolate* isolate, const DOMWrapperWorld& world) {
- v8::Local<v8::FunctionTemplate> parentTemplate =
- V8{{parent_interface}}::DomTemplate(isolate, world);
-
- v8::Local<v8::FunctionTemplate> named_properties_function_template =
- v8::FunctionTemplate::New(isolate,
- V8ObjectConstructor::IsValidConstructorMode);
- named_properties_function_template->SetClassName(
- V8AtomicString(isolate, "{{interface_name}}Properties"));
- named_properties_function_template->Inherit(parentTemplate);
-
- v8::Local<v8::ObjectTemplate> named_properties_object_template =
- named_properties_function_template->PrototypeTemplate();
- named_properties_object_template->SetInternalFieldCount(
- {{v8_class}}::kInternalFieldCount);
- // Named Properties object has SetPrototype method of Immutable Prototype Exotic Objects
- named_properties_object_template->SetImmutableProto();
- V8DOMConfiguration::SetClassString(
- isolate, named_properties_object_template, "{{interface_name}}Properties");
- {{install_named_property_handler('named_properties_object_template') | trim | indent(2)}}
-
- return named_properties_function_template;
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block has_instance %}
-{% if not is_array_buffer_or_view %}
-
-bool {{v8_class}}::HasInstance(v8::Local<v8::Value> v8_value, v8::Isolate* isolate) {
- return V8PerIsolateData::From(isolate)->HasInstance({{v8_class}}::GetWrapperTypeInfo(), v8_value);
-}
-
-v8::Local<v8::Object> {{v8_class}}::FindInstanceInPrototypeChain(
- v8::Local<v8::Value> v8_value, v8::Isolate* isolate) {
- return V8PerIsolateData::From(isolate)->FindInstanceInPrototypeChain(
- {{v8_class}}::GetWrapperTypeInfo(), v8_value);
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block to_impl %}
-{% if interface_name == 'ArrayBuffer' or interface_name == 'SharedArrayBuffer' %}
-{{cpp_class}}* V8{{interface_name}}::ToImpl(v8::Local<v8::Object> object) {
- DCHECK(object->Is{{interface_name}}());
- v8::Local<v8::{{interface_name}}> v8buffer = object.As<v8::{{interface_name}}>();
- if (auto script_wrappable = ToScriptWrappable(object)) {
- const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(object);
- CHECK(wrapper_type);
- CHECK_EQ(wrapper_type->gin_embedder, gin::kEmbedderBlink);
- return script_wrappable->ToImpl<{{cpp_class}}>();
- }
-
- // Transfer the ownership of the allocated memory to an {{interface_name}} without
- // copying.
- ArrayBufferContents contents(v8buffer->GetBackingStore());
- {{cpp_class}}* buffer = {{cpp_class}}::Create(contents);
- v8::Local<v8::Object> associatedWrapper = buffer->AssociateWithWrapper(v8::Isolate::GetCurrent(), buffer->GetWrapperTypeInfo(), object);
- DCHECK(associatedWrapper == object);
-
- return buffer;
-}
-
-{% elif interface_name == 'ArrayBufferView' %}
-{{cpp_class}}* V8ArrayBufferView::ToImpl(v8::Local<v8::Object> object) {
- DCHECK(object->IsArrayBufferView());
- ScriptWrappable* script_wrappable = ToScriptWrappable(object);
- if (script_wrappable)
- return script_wrappable->ToImpl<{{cpp_class}}>();
-
- if (object->IsInt8Array())
- return V8Int8Array::ToImpl(object);
- if (object->IsInt16Array())
- return V8Int16Array::ToImpl(object);
- if (object->IsInt32Array())
- return V8Int32Array::ToImpl(object);
- if (object->IsUint8Array())
- return V8Uint8Array::ToImpl(object);
- if (object->IsUint8ClampedArray())
- return V8Uint8ClampedArray::ToImpl(object);
- if (object->IsUint16Array())
- return V8Uint16Array::ToImpl(object);
- if (object->IsUint32Array())
- return V8Uint32Array::ToImpl(object);
- if (object->IsBigInt64Array())
- return V8BigInt64Array::ToImpl(object);
- if (object->IsBigUint64Array())
- return V8BigUint64Array::ToImpl(object);
- if (object->IsFloat32Array())
- return V8Float32Array::ToImpl(object);
- if (object->IsFloat64Array())
- return V8Float64Array::ToImpl(object);
- if (object->IsDataView())
- return V8DataView::ToImpl(object);
-
- NOTREACHED();
- return nullptr;
-}
-
-{% elif is_array_buffer_or_view %}
-{{cpp_class}}* {{v8_class}}::ToImpl(v8::Local<v8::Object> object) {
- DCHECK(object->Is{{interface_name}}());
- ScriptWrappable* script_wrappable = ToScriptWrappable(object);
- if (script_wrappable)
- return script_wrappable->ToImpl<{{cpp_class}}>();
-
- v8::Local<v8::{{interface_name}}> v8_view = object.As<v8::{{interface_name}}>();
- v8::Local<v8::Object> array_buffer = v8_view->Buffer();
- {{cpp_class}}* typed_array = nullptr;
- if (array_buffer->IsArrayBuffer()) {
- typed_array = {{cpp_class}}::Create(
- V8ArrayBuffer::ToImpl(array_buffer),
- v8_view->ByteOffset(),
- v8_view->{% if interface_name == 'DataView' %}Byte{% endif %}Length());
- } else if (array_buffer->IsSharedArrayBuffer()) {
- typed_array = {{cpp_class}}::Create(
- V8SharedArrayBuffer::ToImpl(array_buffer),
- v8_view->ByteOffset(),
- v8_view->{% if interface_name == 'DataView' %}Byte{% endif %}Length());
- } else {
- NOTREACHED();
- }
- v8::Local<v8::Object> associated_wrapper =
- typed_array->AssociateWithWrapper(
- v8::Isolate::GetCurrent(), typed_array->GetWrapperTypeInfo(), object);
- DCHECK(associated_wrapper == object);
-
- return typed_array->ToImpl<{{cpp_class}}>();
-}
-
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
-{% block to_impl_with_type_check %}
-{{cpp_class}}* {{v8_class}}::ToImplWithTypeCheck(
- v8::Isolate* isolate, v8::Local<v8::Value> value) {
-{% if is_array_buffer_or_view %}
- return value->Is{{interface_name}}() ? ToImpl(v8::Local<v8::Object>::Cast(value)) : nullptr;
-{% else %}
- return HasInstance(value, isolate) ? ToImpl(v8::Local<v8::Object>::Cast(value)) : nullptr;
-{% endif %}
-}
-
-{% endblock %}
-
-
-{##############################################################################}
-{% block partial_interface %}
-{% if has_partial_interface %}
-{% if needs_runtime_enabled_installer %}
-InstallRuntimeEnabledFeaturesFunction
-{{v8_class}}::install_runtime_enabled_features_function_ =
- &{{v8_class}}::InstallRuntimeEnabledFeaturesImpl;
-{% endif %}
-{% if not is_array_buffer_or_view %}
-InstallRuntimeEnabledFeaturesOnTemplateFunction
-{{v8_class}}::install_runtime_enabled_features_on_template_function_ =
- &{{v8_class}}::InstallRuntimeEnabledFeaturesOnTemplate;
-{% endif %}
-
-InstallTemplateFunction
-{{v8_class}}::install_{{snake_case_v8_class}}_template_function_ =
- &{{v8_class}}::Install{{v8_class}}Template;
-
-void {{v8_class}}::UpdateWrapperTypeInfo(
- InstallTemplateFunction install_template_function,
- InstallRuntimeEnabledFeaturesFunction install_runtime_enabled_features_function,
- InstallRuntimeEnabledFeaturesOnTemplateFunction install_runtime_enabled_features_on_template_function,
- InstallConditionalFeaturesFunction install_conditional_features_function) {
- {{v8_class}}::install_{{snake_case_v8_class}}_template_function_ =
- install_template_function;
-
- {% if needs_runtime_enabled_installer %}
- CHECK(install_runtime_enabled_features_function);
- {{v8_class}}::install_runtime_enabled_features_function_ =
- install_runtime_enabled_features_function;
-
- {% endif %}
- {% if not is_array_buffer_or_view %}
- CHECK(install_runtime_enabled_features_on_template_function);
- {{v8_class}}::install_runtime_enabled_features_on_template_function_ =
- install_runtime_enabled_features_on_template_function;
- {% endif %}
-
- if (install_conditional_features_function) {
- {{v8_class}}::GetWrapperTypeInfo()->install_conditional_features_function =
- install_conditional_features_function;
- }
-}
-
-{% for method in methods if method.overloads and method.overloads.has_partial_overloads %}
-void {{v8_class}}::Register{{method.camel_case_name}}MethodForPartialInterface(void (*method)(const v8::FunctionCallbackInfo<v8::Value>&)) {
- {{internal_namespace}}::{{method.name}}MethodForPartialInterface = method;
-}
-
-{% endfor %}
-{% endif %}{# has_partial_interface #}
-{% endblock %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
deleted file mode 100644
index cd96099294e..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
+++ /dev/null
@@ -1,319 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% if optional_features %}
-class ScriptState;
-{% endif %}
-{% if named_constructor %}
-
-extern const WrapperTypeInfo {{snake_case_v8_class}}_constructor_wrapper_type_info;
-
-class {{v8_class}}Constructor {
- STATIC_ONLY({{v8_class}}Constructor);
- public:
- static v8::Local<v8::FunctionTemplate> DomTemplate(v8::Isolate*, const DOMWrapperWorld&);
- static void NamedConstructorAttributeGetter(v8::Local<v8::Name> property_name, const v8::PropertyCallbackInfo<v8::Value>& info);
- static constexpr const WrapperTypeInfo* GetWrapperTypeInfo() {
- return &{{snake_case_v8_class}}_constructor_wrapper_type_info;
- }
-};
-
-{% endif %}
-
-{% if has_partial_interface %}
-{{exported}}extern WrapperTypeInfo {{snake_case_v8_class}}_wrapper_type_info;
-{% else %}
-{{exported}}extern const WrapperTypeInfo {{snake_case_v8_class}}_wrapper_type_info;
-{% endif %}
-
-class {{v8_class}} {
- STATIC_ONLY({{v8_class}});
- public:
- {% if is_array_buffer_or_view %}
- // Migration adapter
- {{exported}}static bool HasInstance(v8::Isolate*, v8::Local<v8::Value> value) {
- return value->Is{{interface_name}}();
- }
-
- {{exported}}static {{cpp_class}}* ToImpl(v8::Local<v8::Object> object);
- {% else %}
- {{exported}}static bool HasInstance(v8::Local<v8::Value>, v8::Isolate*);
- static v8::Local<v8::Object> FindInstanceInPrototypeChain(v8::Local<v8::Value>, v8::Isolate*);
- {{exported}}static v8::Local<v8::FunctionTemplate> DomTemplate(v8::Isolate*, const DOMWrapperWorld&);
- {% if has_named_properties_object %}
- {{exported}}static v8::Local<v8::FunctionTemplate> DomTemplateForNamedPropertiesObject(v8::Isolate*, const DOMWrapperWorld&);
- {% endif %}
- static {{cpp_class}}* ToImpl(v8::Local<v8::Object> object) {
- return ToScriptWrappable(object)->ToImpl<{{cpp_class}}>();
- }
- {% endif %}
- {{exported}}static {{cpp_class}}* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
-
- {% if has_partial_interface %}
- {{exported}}static constexpr WrapperTypeInfo* GetWrapperTypeInfo() {
- {% else %}
- {{exported}}static constexpr const WrapperTypeInfo* GetWrapperTypeInfo() {
- {% endif %}
- return &{{snake_case_v8_class}}_wrapper_type_info;
- }
-
- {% for method in methods %}
- {% if method.is_custom %}
- static void {{method.camel_case_name}}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
- {% endfor %}
- {% if has_custom_constructor %}
- static void ConstructorCustom(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
- {% for attribute in attributes %}
- {% if attribute.has_custom_getter %}{# FIXME: and not attribute.implemented_by #}
- {% if attribute.is_data_type_property %}
- static void {{attribute.camel_case_name}}AttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>&);
- {% else %}
- static void {{attribute.camel_case_name}}AttributeGetterCustom(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
- {% endif %}
- {% if attribute.has_custom_setter %}{# FIXME: and not attribute.implemented_by #}
- {% if attribute.is_data_type_property %}
- static void {{attribute.camel_case_name}}AttributeSetterCustom(v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&);
- {% else %}
- static void {{attribute.camel_case_name}}AttributeSetterCustom(v8::Local<v8::Value>, const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
- {% endif %}
- {% endfor %}
- {# Custom special operations #}
- {% if indexed_property_getter and indexed_property_getter.is_custom %}
- static void IndexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if indexed_property_setter and indexed_property_setter.is_custom %}
- static void IndexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if indexed_property_deleter and indexed_property_deleter.is_custom %}
- static void IndexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);
- {% endif %}
- {% if named_property_getter and named_property_getter.is_custom %}
- static void NamedPropertyGetterCustom(const AtomicString&, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if named_property_setter and named_property_setter.is_custom %}
- static void NamedPropertySetterCustom(const AtomicString&, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if named_property_getter and named_property_getter.is_custom_property_query %}
- static void NamedPropertyQueryCustom(const AtomicString&, const v8::PropertyCallbackInfo<v8::Integer>&);
- {% endif %}
- {% if named_property_deleter and named_property_deleter.is_custom %}
- static void NamedPropertyDeleterCustom(const AtomicString&, const v8::PropertyCallbackInfo<v8::Boolean>&);
- {% endif %}
- {% if named_property_getter and named_property_getter.is_custom_property_enumerator %}
- static void NamedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>&);
- {% endif %}
- {# END custom special operations #}
- {% if has_custom_legacy_call_as_function %}
- static void LegacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
- {# Custom internal fields #}
- {# persistentHandleIndex must be the last field, if it is present.
- Detailed explanation: https://codereview.chromium.org/139173012
- FIXME: Remove this internal field, and share one field for either:
- * a persistent handle (if the object is in oilpan) or
- * a C++ pointer to the DOM object (if the object is not in oilpan) #}
- static constexpr int kInternalFieldCount = kV8DefaultWrapperInternalFieldCount;
- {# End custom internal fields #}
-
- {% if install_conditional_features_func %}
- {{exported}}static void InstallConditionalFeatures(
- v8::Local<v8::Context>,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance_object,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object,
- v8::Local<v8::FunctionTemplate> interface_template);
- {% elif has_partial_interface %}
- {{exported}}static void InstallConditionalFeatures(
- v8::Local<v8::Context>,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance_object,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object,
- v8::Local<v8::FunctionTemplate> interface_template) {}
- {% endif %}
-
- {% if has_partial_interface %}
- {{exported}}static void UpdateWrapperTypeInfo(
- InstallTemplateFunction,
- InstallRuntimeEnabledFeaturesFunction,
- InstallRuntimeEnabledFeaturesOnTemplateFunction,
- InstallConditionalFeaturesFunction);
- {{exported}}static void Install{{v8_class}}Template(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interface_template);
- {% for method in methods if method.overloads and method.overloads.has_partial_overloads %}
- {{exported}}static void Register{{method.camel_case_name}}MethodForPartialInterface(void (*)(const v8::FunctionCallbackInfo<v8::Value>&));
- {% endfor %}
- {% endif %}
-
- {% for feature in optional_features %}
-
- static void Install{{feature.name}}(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface);
- static void Install{{feature.name}}(ScriptState*, v8::Local<v8::Object> instance);
- {% if not feature.needs_instance %}
- static void Install{{feature.name}}(ScriptState*);
- {% endif %}
- {% endfor %}
-
- // Callback functions
- {% for constant in constants | has_special_getter %}
- {{exported}}static void {{constant.camel_case_name}}ConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endfor %}
-
- {% for attribute in attributes %}
- {% if attribute.is_cached_accessor %}
- {{exported}}static v8::Local<v8::Private> {{attribute.camel_case_name}}CachedPropertyKey(v8::Isolate*);
- {% endif %}
- {% for world_suffix in attribute.world_suffixes %}
- {% if not attribute.constructor_type %}
- {{exported}}static void {{attribute.camel_case_name}}AttributeGetterCallback{{world_suffix}}(
- {%- if attribute.is_data_type_property -%}
- v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&
- {%- else -%}
- const v8::FunctionCallbackInfo<v8::Value>&
- {%- endif -%});
- {% else %}
- {{exported}}static void {{attribute.camel_case_name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if attribute.has_setter %}
- {{exported}}static void {{attribute.camel_case_name}}AttributeSetterCallback{{world_suffix}}(
- {%- if attribute.is_data_type_property -%}
- v8::Local<v8::Name>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&
- {%- else -%}
- const v8::FunctionCallbackInfo<v8::Value>&
- {%- endif -%});
- {% endif %}
- {% endfor %}
- {% endfor %}
-
- {% for method in methods %}
- {% for world_suffix in method.world_suffixes %}
- {% if not method.overload_index or method.overloads %}
- {# Document about the following condition: #}
- {# https://docs.google.com/document/d/1qBC7Therp437Jbt_QYAtNYMZs6zQ_7_tnMkNUG_ACqs/edit?usp=sharing #}
- {% if (method.overloads and method.overloads.visible and
- (not method.overloads.has_partial_overloads or not is_partial)) or
- (not method.overloads and method.visible) %}
- {# A single callback is generated for overloaded methods #}
- {# with considering partial overloads #}
- {{exported}}static void {{method.camel_case_name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
- {% if method.is_cross_origin and method.visible %}
- {{exported}}static void {{method.camel_case_name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% endif %}
- {% endfor %}
- {% endfor %}
- {% if iterator_method %}
- {{exported}}static void {{iterator_method.camel_case_name}}MethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endif %}
-
- {% if has_access_check_callbacks and not is_partial %}
- {{exported}}static bool SecurityCheck(v8::Local<v8::Context>, v8::Local<v8::Object>, v8::Local<v8::Value>);
- {% if has_cross_origin_named_getter %}
- {{exported}}static void CrossOriginNamedGetter(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if has_cross_origin_named_setter %}
- {{exported}}static void CrossOriginNamedSetter(v8::Local<v8::Name>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if has_cross_origin_named_enumerator %}
- {{exported}}static void CrossOriginNamedEnumerator(const v8::PropertyCallbackInfo<v8::Array>&);
- {% endif %}
- {% if has_cross_origin_indexed_getter %}
- {{exported}}static void CrossOriginIndexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% endif %}
-
- {% if named_property_getter %}
- {{exported}}static void NamedPropertyGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if named_property_setter %}
- {{exported}}static void NamedPropertySetterCallback(v8::Local<v8::Name>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if named_property_deleter %}
- {{exported}}static void NamedPropertyDeleterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Boolean>&);
- {% endif %}
- {% if named_property_getter and named_property_getter.is_enumerable %}
- {{exported}}static void NamedPropertyQueryCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Integer>&);
- {% endif %}
- {% if named_property_getter and named_property_getter.is_enumerable %}
- {{exported}}static void NamedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>&);
- {% endif %}
- {% if indexed_property_getter or named_property_getter %}
- {{exported}}static void IndexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if indexed_property_getter or named_property_setter %}
- {{exported}}static void IndexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if indexed_property_getter or named_property_getter %}
- {{exported}}static void IndexedPropertyDescriptorCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if indexed_property_deleter or named_property_deleter %}
- {{exported}}static void IndexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&);
- {% endif %}
- {% if indexed_property_getter %}
- {{exported}}static void IndexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
-
- {% if needs_runtime_enabled_installer %}
- {{exported if has_partial_interface else ''}}static void InstallRuntimeEnabledFeatures(
- v8::Isolate*,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface);
- {% endif %}{# needs_runtime_enabled_installer #}
-
- {% if not is_array_buffer_or_view %}
- {{exported if has_partial_interface else ''}}static void InstallRuntimeEnabledFeaturesOnTemplate(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::FunctionTemplate> interface_template);
- {% if has_partial_interface %}
- static InstallRuntimeEnabledFeaturesOnTemplateFunction
- install_runtime_enabled_features_on_template_function_;
- {% endif %}
- {% endif %}{# not is_array_buffer_or_view #}
-
- {% if needs_runtime_enabled_installer or has_partial_interface %}
- private:
- {% if needs_runtime_enabled_installer %}
- static void InstallRuntimeEnabledFeaturesImpl(
- v8::Isolate*,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface);
- {% endif %}{# needs_runtime_enabled_installer #}
- {% if has_partial_interface %}
- static InstallTemplateFunction install_{{snake_case_v8_class}}_template_function_;
- {% if needs_runtime_enabled_installer %}
- static InstallRuntimeEnabledFeaturesFunction
- install_runtime_enabled_features_function_;
- {% endif %}
- {% endif %}{# has_partial_interface #}
- {% endif %}
-};
-
-template <>
-struct V8TypeOf<{{cpp_class}}> {
- typedef {{v8_class}} Type;
-};
-
-} // namespace blink
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl
deleted file mode 100644
index 8d502128095..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl
+++ /dev/null
@@ -1,1058 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#include "{{this_include_header_path}}"
-
-#include <algorithm>
-
-{% for filename in cpp_includes if filename != '%s.h' % cpp_class_or_partial %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-{% set dom_template = '%s::DomTemplate' % v8_class if not is_array_buffer_or_view else 'nullptr' %}
-{% set parent_wrapper_type_info = 'V8%s::GetWrapperTypeInfo()' % parent_interface
- if parent_interface else 'nullptr' %}
-{% set active_scriptwrappable_inheritance =
- 'kInheritFromActiveScriptWrappable'
- if active_scriptwrappable else
- 'kNotInheritFromActiveScriptWrappable' %}
-
-{% set wrapper_type_info_const = '' if has_partial_interface else 'const ' %}
-{% if not is_partial %}
-// Suppress warning: global constructors, because struct WrapperTypeInfo is trivial
-// and does not depend on another global objects.
-#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wglobal-constructors"
-#endif
-{{wrapper_type_info_const}}WrapperTypeInfo {{snake_case_v8_class}}_wrapper_type_info = {
- gin::kEmbedderBlink,
- {{dom_template}},
- {{install_conditional_features_func or 'nullptr'}},
- "{{interface_name}}",
- {{parent_wrapper_type_info}},
- WrapperTypeInfo::kWrapperTypeObjectPrototype,
- WrapperTypeInfo::{{wrapper_class_id}},
- WrapperTypeInfo::{{active_scriptwrappable_inheritance}},
-};
-#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-{% if not is_typed_array_type %}
-// This static member must be declared by DEFINE_WRAPPERTYPEINFO in {{cpp_class}}.h.
-// For details, see the comment of DEFINE_WRAPPERTYPEINFO in
-// platform/bindings/ScriptWrappable.h.
-const WrapperTypeInfo& {{cpp_class}}::wrapper_type_info_ = {{snake_case_v8_class}}_wrapper_type_info;
-{% endif %}
-
-{% if active_scriptwrappable %}
-// [ActiveScriptWrappable]
-static_assert(
- std::is_base_of<ActiveScriptWrappableBase, {{cpp_class}}>::value,
- "{{cpp_class}} does not inherit from ActiveScriptWrappable<>, but specifying "
- "[ActiveScriptWrappable] extended attribute in the IDL file. "
- "Be consistent.");
-static_assert(
- !std::is_same<decltype(&{{cpp_class}}::HasPendingActivity),
- decltype(&ScriptWrappable::HasPendingActivity)>::value,
- "{{cpp_class}} is not overriding hasPendingActivity(), but is specifying "
- "[ActiveScriptWrappable] extended attribute in the IDL file. "
- "Be consistent.");
-{% else %}
-// not [ActiveScriptWrappable]
-static_assert(
- !std::is_base_of<ActiveScriptWrappableBase, {{cpp_class}}>::value,
- "{{cpp_class}} inherits from ActiveScriptWrappable<>, but is not specifying "
- "[ActiveScriptWrappable] extended attribute in the IDL file. "
- "Be consistent.");
-static_assert(
- std::is_same<decltype(&{{cpp_class}}::HasPendingActivity),
- decltype(&ScriptWrappable::HasPendingActivity)>::value,
- "{{cpp_class}} is overriding hasPendingActivity(), but is not specifying "
- "[ActiveScriptWrappable] extended attribute in the IDL file. "
- "Be consistent.");
-{% endif %}
-
-{% endif %}{# not is_partial #}
-{% if not is_array_buffer_or_view %}
-namespace {{internal_namespace}} {
-{% if has_partial_interface %}
-{% for method in methods if method.overloads and method.overloads.has_partial_overloads %}
-static void (*{{method.name}}MethodForPartialInterface)(const v8::FunctionCallbackInfo<v8::Value>&) = 0;
-{% endfor %}
-{% endif %}
-
-{##############################################################################}
-{# Attributes #}
-{% from 'attributes.cc.tmpl' import attribute_getter, attribute_setter,
- with context %}
-{% for attribute in attributes %}
-{% for world_suffix in attribute.world_suffixes %}
-{% if attribute.private_property_is_shared_between_getter_and_setter %}
-// Define a private property key shared between getter and setter.
-static const V8PrivateProperty::SymbolKey kPrivateProperty{{attribute.camel_case_name}};
-{% endif %}
-
-{% if attribute.does_generate_getter %}
-{{attribute_getter(attribute, world_suffix)}}
-{% endif %}
-{% if attribute.does_generate_setter %}
-{{attribute_setter(attribute, world_suffix)}}
-{% endif %}
-{% endfor %}
-{% endfor %}
-{##############################################################################}
-{# Methods #}
-{% from 'methods.cc.tmpl' import generate_method, overload_resolution_method,
- origin_safe_method_getter, generate_constructor,
- runtime_determined_length_method, runtime_determined_maxarg_method
- with context %}
-{% for method in methods %}
-{% for world_suffix in method.world_suffixes %}
-{% if not method.is_custom and method.visible %}
-{{generate_method(method, world_suffix)}}
-{% endif %}
-{% if method.overloads and method.overloads.visible %}
-{% if method.overloads.runtime_determined_lengths %}
-{{runtime_determined_length_method(method.overloads)}}
-{% endif %}
-{% if method.overloads.runtime_determined_maxargs %}
-{{runtime_determined_maxarg_method(method.overloads)}}
-{% endif %}
-{{overload_resolution_method(method.overloads, world_suffix)}}
-{% endif %}
-{% 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 %}
-{% endfor %}
-{% if iterator_method %}
-{{generate_method(iterator_method)}}
-{% endif %}
-{# Constructors #}
-{% for constructor in constructors %}
-{{generate_constructor(constructor)}}
-{% endfor %}
-{% block overloaded_constructor %}{% endblock %}
-{% block constructor_callback %}{% endblock %}
-{# Special operations (methods) #}
-{% block named_property_getter %}{% endblock %}
-{% block named_property_setter %}{% endblock %}
-{% block named_property_deleter %}{% endblock %}
-{% block named_property_query %}{% endblock %}
-{% block named_property_descriptor %}{% endblock %}
-{% block named_property_enumerator %}{% endblock %}
-{% block indexed_property_getter %}{% endblock %}
-{% block indexed_property_descriptor %}{% endblock %}
-{% block indexed_property_setter %}{% endblock %}
-{% block indexed_property_deleter %}{% endblock %}
-{##############################################################################}
-{% if has_access_check_callbacks and not is_partial and has_cross_origin_named_enumerator %}
-static const struct {
- using GetterCallback = void(*)(const v8::PropertyCallbackInfo<v8::Value>&);
- using SetterCallback = void(*)(v8::Local<v8::Value>, const V8CrossOriginCallbackInfo&);
-
- const char* const name;
- const GetterCallback getter;
- const SetterCallback setter;
-} kCrossOriginAttributeTable[] = {
- {% for attribute in attributes if attribute.has_cross_origin_getter or attribute.has_cross_origin_setter %}
- {
- "{{attribute.name}}",
- {% if attribute.has_cross_origin_getter %}
- {% if attribute.has_custom_getter %}
- {{v8_class}}::{{attribute.camel_case_name}}AttributeGetterCustom,
- {% else %}
- {{internal_namespace}}::{{attribute.camel_case_name}}AttributeGetter,
- {% endif %}
- {% else %}
- nullptr,
- {% endif %}
- {%+ if attribute.has_cross_origin_setter %}&{{internal_namespace}}::{{attribute.camel_case_name}}AttributeSetter{% else %}nullptr{% endif %},
- },
- {% endfor %}
-};
-
-static const struct {
- using ValueCallback = void(*)(const v8::PropertyCallbackInfo<v8::Value>&);
-
- const char* const name;
- const ValueCallback value;
-} kCrossOriginOperationTable[] = {
- {% for method in methods if method.is_cross_origin and
- (not method.overload_index or method.overloads) %}
- {"{{method.name}}", &{{internal_namespace}}::{{method.camel_case_name}}OriginSafeMethodGetter},
- {% endfor %}
-};
-{% endif %}
-{##############################################################################}
-} // namespace {{internal_namespace}}
-
-{# Constants #}
-{% from 'constants.cc.tmpl' import constant_getter_callback with context %}
-{% for constant in constants | has_special_getter %}
-{{constant_getter_callback(constant)}}
-{% endfor %}
-
-{# Attributes #}
-{% from 'attributes.cc.tmpl' import constructor_getter_callback,
- attribute_getter_callback, attribute_setter_callback with context %}
-{% for attribute in attributes %}
-{% for world_suffix in attribute.world_suffixes %}
-{% if not attribute.constructor_type %}
-{{attribute_getter_callback(attribute, world_suffix)}}
-{% else %}
-{{constructor_getter_callback(attribute, world_suffix)}}
-{% endif %}
-{% if attribute.has_setter %}
-{{attribute_setter_callback(attribute, world_suffix)}}
-{% endif %}
-{% endfor %}
-{% endfor %}
-
-{# Methods #}
-{% from 'methods.cc.tmpl' import origin_safe_method_getter_callback,
- method_callback with context %}
-{% for method in methods %}
-{% for world_suffix in method.world_suffixes %}
-{% if not method.overload_index or method.overloads %}
-{# Document about the following condition: #}
-{# https://docs.google.com/document/d/1qBC7Therp437Jbt_QYAtNYMZs6zQ_7_tnMkNUG_ACqs/edit?usp=sharing #}
-{% if (method.overloads and method.overloads.visible and
- (not method.overloads.has_partial_overloads or not is_partial)) or
- (not method.overloads and method.visible) %}
-{# A single callback is generated for overloaded methods #}
-{# with considering partial overloads #}
-{{method_callback(method, world_suffix)}}
-{% endif %}
-{% endif %}
-{% 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 %}
-{% endfor %}
-{% if iterator_method %}
-{{method_callback(iterator_method)}}
-{% endif %}
-{# Special operations (methods) #}
-{% block named_property_getter_callback %}{% endblock %}
-{% block named_property_setter_callback %}{% endblock %}
-{% block named_property_deleter_callback %}{% endblock %}
-{% block named_property_query_callback %}{% endblock %}
-{% block named_property_enumerator_callback %}{% endblock %}
-{% block indexed_property_getter_callback %}{% endblock %}
-{% block indexed_property_descriptor_callback %}{% endblock %}
-{% block indexed_property_setter_callback %}{% endblock %}
-{% block indexed_property_deleter_callback %}{% endblock %}
-{% block indexed_property_definer_callback %}{% endblock %}
-
-{% if has_access_check_callbacks and not is_partial %}
-bool {{v8_class_or_partial}}::SecurityCheck(v8::Local<v8::Context> accessing_context, v8::Local<v8::Object> accessed_object, v8::Local<v8::Value> data) {
- {% if interface_name == 'Window' %}
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
- v8::Local<v8::Object> window = V8Window::FindInstanceInPrototypeChain(accessed_object, isolate);
- if (window.IsEmpty())
- return false; // the frame is gone.
-
- const DOMWindow* target_window = V8Window::ToImpl(window);
- return BindingSecurity::ShouldAllowAccessTo(ToLocalDOMWindow(accessing_context), target_window, BindingSecurity::ErrorReportOption::kDoNotReport);
- {% elif interface_name == 'Location' %}
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(accessed_object);
- return BindingSecurity::ShouldAllowAccessTo(ToLocalDOMWindow(accessing_context), impl, BindingSecurity::ErrorReportOption::kDoNotReport);
- {% else %}
- #error "Unexpected security check for interface {{interface_name}}"
- {% endif %}
-}
-
-{% if has_cross_origin_named_getter %}
-void {{v8_class_or_partial}}::CrossOriginNamedGetter(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.cross_origin_named_getter_counter) }}
- if (!name->IsString())
- return;
- const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
-
- for (const auto& attribute : {{internal_namespace}}::kCrossOriginAttributeTable) {
- if (property_name == attribute.name && attribute.getter) {
- attribute.getter(info);
- return;
- }
- }
- for (const auto& operation : {{internal_namespace}}::kCrossOriginOperationTable) {
- if (property_name == operation.name) {
- operation.value(info);
- return;
- }
- }
-
- {% if named_property_getter and named_property_getter.is_cross_origin %}
- {% if named_property_getter.is_custom %}
- {{v8_class}}::NamedPropertyGetterCustom(property_name, info);
- {% else %}
- {{internal_namespace}}::NamedPropertyGetter(property_name, info);
- {% endif %}
- {% else %}
- // HTML 7.2.3.3 CrossOriginGetOwnPropertyHelper ( O, P )
- // https://html.spec.whatwg.org/C/#crossorigingetownpropertyhelper-(-o,-p-)
- // step 3. If P is "then", @@toStringTag, @@hasInstance, or
- // @@isConcatSpreadable, then return PropertyDescriptor{ [[Value]]:
- // undefined, [[Writable]]: false, [[Enumerable]]: false,
- // [[Configurable]]: true }.
- if (property_name == "then") {
- V8SetReturnValue(info, v8::Undefined(info.GetIsolate()));
- return;
- }
-
- BindingSecurity::FailedAccessCheckFor(
- info.GetIsolate(),
- {{v8_class}}::GetWrapperTypeInfo(),
- info.Holder());
- {% endif %}
-}
-{% endif %}
-
-{% if has_cross_origin_named_setter %}
-void {{v8_class_or_partial}}::CrossOriginNamedSetter(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.cross_origin_named_setter_counter) }}
- if (!name->IsString())
- return;
- const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
-
- for (const auto& attribute : {{internal_namespace}}::kCrossOriginAttributeTable) {
- if (property_name == attribute.name && attribute.setter) {
- attribute.setter(value, V8CrossOriginCallbackInfo(info));
- return;
- }
- }
-
- {# If there were no matches in the cross-origin attribute table, consider it
- an access check failure: there are no custom named setters that are
- accessible from a cross-origin context. #}
-
- BindingSecurity::FailedAccessCheckFor(
- info.GetIsolate(),
- {{v8_class}}::GetWrapperTypeInfo(),
- info.Holder());
-}
-{% endif %}
-
-{% if has_cross_origin_named_enumerator %}
-void {{v8_class_or_partial}}::CrossOriginNamedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
- Vector<String> names;
- for (const auto& attribute : {{internal_namespace}}::kCrossOriginAttributeTable)
- names.push_back(attribute.name);
- for (const auto& operation : {{internal_namespace}}::kCrossOriginOperationTable)
- names.push_back(operation.name);
-
- // Use the current context as the creation context, as a cross-origin access
- // may involve an object that does not have a creation context.
- V8SetReturnValue(info,
- ToV8(names, info.GetIsolate()->GetCurrentContext()->Global(),
- info.GetIsolate()).As<v8::Array>());
-}
-{% endif %}
-
-{% if has_cross_origin_indexed_getter %}
-void {{v8_class_or_partial}}::CrossOriginIndexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if indexed_property_getter.is_custom %}
- {{v8_class}}::IndexedPropertyGetterCustom(index, info);
- {% else %}
- {{internal_namespace}}::IndexedPropertyGetter(index, info);
- {% endif %}
-}
-{% endif %}
-{% endif %}{# has_access_check_callbacks #}
-
-{% block visit_dom_wrapper %}{% endblock %}
-{##############################################################################}
-{% block install_methods %}
-{% from 'methods.cc.tmpl' import method_configuration with context %}
-{% if methods | has_method_configuration(is_partial) %}
-static constexpr V8DOMConfiguration::MethodConfiguration k{{v8_class}}Methods[] = {
- {% for method in methods | has_method_configuration(is_partial) %}
- {{method_configuration(method) | trim | indent(4)}},
- {% endfor %}
-};
-
-{% endif %}
-{% endblock %}
-{% endif %}{# not is_array_buffer_or_view #}
-{##############################################################################}
-{% block named_constructor %}{% endblock %}
-{##############################################################################}
-{% block install_dom_template %}
-{% if not is_array_buffer_or_view %}
-{% from 'methods.cc.tmpl' import install_custom_signature,
- method_configuration with context %}
-{% from 'attributes.cc.tmpl' import accessor_configuration,
- attribute_configuration, install_attributes, install_interface_objects,
- with context %}
-{% from 'constants.cc.tmpl' import install_constants,
- constant_configuration with context %}
-{% if has_partial_interface or is_partial %}
-void {{v8_class_or_partial}}::Install{{v8_class}}Template(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::FunctionTemplate> interface_template) {
-{% else %}
-static void Install{{v8_class}}Template(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::FunctionTemplate> interface_template) {
-{% endif %}
- // Initialize the interface object's template.
- {% if is_partial %}
- {{v8_class}}::Install{{v8_class}}Template(isolate, world, interface_template);
- {% else %}
- {% set parent_interface_template =
- '%s::DomTemplateForNamedPropertiesObject(isolate, world)' % v8_class
- if has_named_properties_object else
- 'V8%s::DomTemplate(isolate, world)' % parent_interface
- if parent_interface else
- 'v8::Local<v8::FunctionTemplate>()' %}
- V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interface_template, {{v8_class}}::GetWrapperTypeInfo()->interface_name, {{parent_interface_template}}, {{v8_class}}::kInternalFieldCount);
- {% if constructors or has_custom_constructor or has_html_constructor %}
- interface_template->SetCallHandler({{internal_namespace}}::ConstructorCallback);
- interface_template->SetLength({{interface_length}});
- {% endif %}
- {% endif %}{# is_partial #}
-
- {% if runtime_enabled_feature_name and not context_enabled_feature_name %}
- if (!{{runtime_enabled_feature_name | runtime_enabled_function}}) {
- return;
- }
- {% endif %}
-
- v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interface_template);
- ALLOW_UNUSED_LOCAL(signature);
- v8::Local<v8::ObjectTemplate> instance_template = interface_template->InstanceTemplate();
- ALLOW_UNUSED_LOCAL(instance_template);
- v8::Local<v8::ObjectTemplate> prototype_template = interface_template->PrototypeTemplate();
- ALLOW_UNUSED_LOCAL(prototype_template);
-
- {% if interface_name == 'Window' and not is_partial %}
- prototype_template->SetInternalFieldCount(V8Window::kInternalFieldCount);
- {% endif %}
-
- {% if is_immutable_prototype %}
- // Global object prototype chain consists of Immutable Prototype Exotic Objects
- prototype_template->SetImmutableProto();
- {% endif %}
-
- {% if is_global %}
- // Global objects are Immutable Prototype Exotic Objects
- instance_template->SetImmutableProto();
- {% endif %}
-
- // Register IDL constants, attributes and operations.
- {% if constants %}
- {{install_constants() | trim | indent(2)}}
- {% endif %}
- {% if data_attributes %}
- {{install_interface_objects(data_attributes, 'instance_template', 'prototype_template') | trim | indent(2)}}
- {% endif %}
- {% if accessors %}
- {{install_attributes(accessors, 'instance_template', 'prototype_template', 'interface_template') | trim | indent(2)}}
- {% endif %}
- {% if methods | has_method_configuration(is_partial) %}
- V8DOMConfiguration::InstallMethods(
- isolate, world, instance_template, prototype_template, interface_template,
- signature, k{{v8_class}}Methods, base::size(k{{v8_class}}Methods));
- {% endif %}
-
- {% if has_access_check_callbacks and not is_partial %}
- // Cross-origin access check
- {% set cross_origin_named_getter = '%s::CrossOriginNamedGetter' % v8_class_or_partial if has_cross_origin_named_getter else 'nullptr' %}
- {% set cross_origin_named_setter = '%s::CrossOriginNamedSetter' % v8_class_or_partial if has_cross_origin_named_setter else 'nullptr' %}
- {% set cross_origin_named_enumerator = '%s::CrossOriginNamedEnumerator' % v8_class_or_partial if has_cross_origin_named_enumerator else 'nullptr' %}
- {% set cross_origin_indexed_getter = '%s::CrossOriginIndexedGetter' % v8_class_or_partial if has_cross_origin_indexed_getter else 'nullptr' %}
- instance_template->SetAccessCheckCallbackAndHandler(
- {{v8_class_or_partial}}::SecurityCheck,
- v8::NamedPropertyHandlerConfiguration(
- {{cross_origin_named_getter}},
- {{cross_origin_named_setter}},
- nullptr,
- nullptr,
- {{cross_origin_named_enumerator}}),
- v8::IndexedPropertyHandlerConfiguration({{cross_origin_indexed_getter}}),
- v8::External::New(isolate, const_cast<WrapperTypeInfo*>({{v8_class}}::GetWrapperTypeInfo())));
- {% endif %}
-
- {% if (indexed_property_getter or named_property_getter) and not is_partial %}
- // Indexed properties
- {{install_indexed_property_handler('instance_template') | trim | indent(2)}}
- {% endif %}
- {% if named_property_getter and not is_partial and not has_named_properties_object %}
- // Named properties
- {{install_named_property_handler('instance_template') | trim | indent(2)}}
- {% endif %}
-
- {% if has_array_iterator and not is_partial %}
- // Array iterator (@@iterator)
- {%+ if is_global %}instance_template{% else %}prototype_template{% endif %}->SetIntrinsicDataProperty(v8::Symbol::GetIterator(isolate), v8::kArrayProto_values, v8::DontEnum);
- {% if iterable %}
- {% if is_global %}
-#error "iterable<V> on [Global] is currently unsupported."
- {% endif %}
- // For value iterators, the properties below must originally be set to the corresponding ones in %ArrayPrototype%.
- // See https://heycam.github.io/webidl/#es-iterators.
- prototype_template->SetIntrinsicDataProperty(V8AtomicString(isolate, "entries"), v8::kArrayProto_entries);
- prototype_template->SetIntrinsicDataProperty(V8AtomicString(isolate, "forEach"), v8::kArrayProto_forEach);
- prototype_template->SetIntrinsicDataProperty(V8AtomicString(isolate, "keys"), v8::kArrayProto_keys);
- prototype_template->SetIntrinsicDataProperty(V8AtomicString(isolate, "values"), v8::kArrayProto_values);
- {% endif %}
- {% endif %}
-
- {% if iterator_method and not iterator_method.runtime_enabled_feature_name %}
- {% filter exposed(iterator_method.exposed_test) %}
- {% set symbol_alias = '"%s"' % iterator_method_alias
- if iterator_method_alias else 'nullptr' %}
- // Iterator (@@iterator)
- static const V8DOMConfiguration::SymbolKeyedMethodConfiguration
- kSymbolKeyedIteratorConfiguration = {
- v8::Symbol::GetIterator,
- {{symbol_alias}},
- {{v8_class_or_partial}}::IteratorMethodCallback,
- 0,
- v8::DontEnum,
- V8DOMConfiguration::kOnPrototype,
- V8DOMConfiguration::kCheckHolder,
- V8DOMConfiguration::kDoNotCheckAccess,
- V8DOMConfiguration::kHasSideEffect
- };
- V8DOMConfiguration::InstallMethod(
- isolate, world, prototype_template, signature,
- kSymbolKeyedIteratorConfiguration);
- {% endfilter %}
- {% endif %}
-
- {% if interface_name == 'FileSystemDirectoryHandle' %}
- // Temporary @@asyncIterator support for FileSystemDirectoryHandle
- // TODO(https://crbug.com/1087157): Replace with proper bindings support.
- static const V8DOMConfiguration::SymbolKeyedMethodConfiguration
- kSymbolKeyedIteratorConfiguration = {
- v8::Symbol::GetAsyncIterator,
- "entries",
- V8FileSystemDirectoryHandle::EntriesMethodCallback,
- 0,
- v8::DontEnum,
- V8DOMConfiguration::kOnPrototype,
- V8DOMConfiguration::kCheckHolder,
- V8DOMConfiguration::kDoNotCheckAccess,
- V8DOMConfiguration::kHasSideEffect
- };
- V8DOMConfiguration::InstallMethod(
- isolate, world, prototype_template, signature,
- kSymbolKeyedIteratorConfiguration);
- {% endif %}
-
- {% if interface_name == 'Iterator' %}
- // The WebIDL spec says when an interface has pair iterators the iterators it
- // returns must be instances of the "default iterator object" whose
- // [[Prototype]] points to an "iterator prototype object" whose
- // [[Prototype]], on its turn, points to %IteratorPrototype%. next() must be
- // implemented in the "iterator prototype object", while %IteratorPrototype%
- // provides @@iterator.
- // References:
- // https://heycam.github.io/webidl/#es-default-iterator-object
- // https://heycam.github.io/webidl/#es-iterator-prototype-object
- //
- // The iterators we return from interfaces that have pair interators adhere
- // to the above by:
- // - Adding the "next()" property to its prototype object.
- // - Making the prototype object inherit from %IteratorPrototype% with the
- // hack below, which creates another function template with no prototype
- // and sets the "prototype" property of its function object.
- // When |interface_template|'s function object is created, its
- // prototype.__proto__ will point to the value of the "prototype" property
- // of |intrinsic_iterator_prototype_interface_template|, which is exactly
- // what we want.
- //
- // Finally, creating a FunctionTemplate here might look expensive since they
- // have the same lifetime as their context, but:
- // - |interface_template| is cached in V8PerIsolateData, so we create only one
- // FunctionTemplate per interface.
- // - There is only one Iterator interface that creates this FunctionTemplate,
- // so there is no need to reuse this FunctionTemplate and register it in
- // V8PerIsolateData.
- v8::Local<v8::FunctionTemplate> intrinsic_iterator_prototype_interface_template =
- v8::FunctionTemplate::New(isolate, nullptr, v8::Local<v8::Value>(),
- v8::Local<v8::Signature>(), 0,
- v8::ConstructorBehavior::kThrow);
- intrinsic_iterator_prototype_interface_template->SetIntrinsicDataProperty(
- V8AtomicString(isolate, "prototype"), v8::kIteratorPrototype);
- interface_template->Inherit(intrinsic_iterator_prototype_interface_template);
- {% endif %}
-
- {% if interface_name == 'FileSystemDirectoryIterator' %}
- // Temporary @@asyncIterator support for FileSystemDirectoryHandle
- // TODO(https://crbug.com/1087157): Replace with proper bindings support.
- v8::Local<v8::FunctionTemplate> intrinsic_iterator_prototype_interface_template =
- v8::FunctionTemplate::New(isolate, nullptr, v8::Local<v8::Value>(),
- v8::Local<v8::Signature>(), 0,
- v8::ConstructorBehavior::kThrow);
- intrinsic_iterator_prototype_interface_template->SetIntrinsicDataProperty(
- V8AtomicString(isolate, "prototype"), v8::kAsyncIteratorPrototype);
- interface_template->Inherit(intrinsic_iterator_prototype_interface_template);
- {% endif %}
-
- {% if interface_name == 'DOMException' %}
- // The WebIDL spec states that DOMException objects have a few peculiarities.
- // One of them is similar to what it mandates for Iterator objects when it
- // comes to the inheritance chain. Instead of
- // DOMException -> prototype -> %ObjectPrototype%
- // we have
- // DOMException -> prototype -> %ErrorPrototype% -> %ObjectPrototype%
- // so that DOMException objects "inherit" toString() and a few properties
- // from %ErrorPrototype%.
- // See https://heycam.github.io/webidl/#es-DOMException-specialness.
- //
- // We achieve this with the same hack we use for Iterators: create a new
- // function template with no prototype, set its "prototype" property to
- // %ErrorPrototype% and make |interface_template| inherit from it. When
- // |interface_template| is instantiated, its prototype.__proto__ will point to
- // |intrinsic_error_prototype_interface_template|'s "prototype" property.
- v8::Local<v8::FunctionTemplate> intrinsic_error_prototype_interface_template =
- v8::FunctionTemplate::New(isolate, nullptr, v8::Local<v8::Value>(),
- v8::Local<v8::Signature>(), 0,
- v8::ConstructorBehavior::kThrow);
- intrinsic_error_prototype_interface_template->SetIntrinsicDataProperty(
- V8AtomicString(isolate, "prototype"), v8::kErrorPrototype);
- interface_template->Inherit(intrinsic_error_prototype_interface_template);
- {% endif %}
-
- {% if interface_name == 'Location' %}
- // Symbol.toPrimitive
- // Prevent author scripts to inject Symbol.toPrimitive property into location
- // objects, also prevent the look-up of Symbol.toPrimitive through the
- // prototype chain.
- instance_template->Set(v8::Symbol::GetToPrimitive(isolate),
- v8::Undefined(isolate),
- static_cast<v8::PropertyAttribute>(
- v8::ReadOnly | v8::DontEnum | v8::DontDelete));
- {% endif %}
-
- {% if has_custom_legacy_call_as_function and not is_partial %}
- instance_template->SetCallAsFunctionHandler({{v8_class}}::LegacyCallCustom);
- {% endif %}
-
- {% if interface_name == 'HTMLAllCollection' and not is_partial %}
- // Needed for legacy support of document.all
- instance_template->MarkAsUndetectable();
- {% endif %}
-
- // Custom signature
- {% for method in methods | custom_registration(is_partial) %}
- {% filter exposed(method.overloads.exposed_test_all
- if method.overloads else method.exposed_test) %}
- {% set feature_name = method.overloads.runtime_enabled_all
- if method.overloads else method.runtime_enabled_feature_name %}
- {% if not feature_name %}
- {% if method.is_cross_origin %}
- {{install_origin_safe_method(method, 'instance_template', 'prototype_template', 'interface_template', 'signature') | trim | indent(2)}}
- {% else %}
- {{install_custom_signature(method, 'instance_template', 'prototype_template', 'interface_template', 'signature') | trim | indent(2)}}
- {% endif %}
- {% endif %}
- {% endfilter %}
- {% endfor %}
- {% if not has_partial_interface %}
-
- {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesOnTemplate(
- isolate, world, interface_template);
- {% endif %}
-}
-
-void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesOnTemplate(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::FunctionTemplate> interface_template) {
- {% if runtime_enabled_feature_name and not context_enabled_feature_name %}
- if (!{{runtime_enabled_feature_name | runtime_enabled_function}}) {
- return;
- }
- {% endif %}
-
- {% if is_partial %}
- {{v8_class}}::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world, interface_template);
- {% endif %}
-
- v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interface_template);
- ALLOW_UNUSED_LOCAL(signature);
- v8::Local<v8::ObjectTemplate> instance_template = interface_template->InstanceTemplate();
- ALLOW_UNUSED_LOCAL(instance_template);
- v8::Local<v8::ObjectTemplate> prototype_template = interface_template->PrototypeTemplate();
- ALLOW_UNUSED_LOCAL(prototype_template);
-
- // Register IDL constants, attributes and operations.
- {% for feature_name, constants_list in constants | selectattr('runtime_enabled_feature_name') | groupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- static constexpr V8DOMConfiguration::ConstantConfiguration kConfigurations[] = {
- {% for constant in constants_list %}
- {{constant_configuration(constant) | trim | indent(6)}},
- {% endfor %}
- };
- V8DOMConfiguration::InstallConstants(
- isolate, interface_template, prototype_template,
- kConfigurations, base::size(kConfigurations));
- {% endfilter %}
- {% endfor %}
-
- {% for feature_name, attribute_list in runtime_enabled_attributes | selectattr('is_data_type_property') | groupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- {{install_interface_objects(attribute_list | sort, 'instance_template', 'prototype_template') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
-
- {% for feature_name, attribute_list in runtime_enabled_attributes | selectattr('is_data_type_property', 'equalto', False) | groupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- {{install_attributes(attribute_list | sort, 'instance_template', 'prototype_template', 'interface_template') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
-
- {% if iterator_method and iterator_method.runtime_enabled_feature_name %}
- {% filter exposed(iterator_method.exposed_test) %}
- {% filter runtime_enabled(iterator_method.runtime_enabled_feature_name) %}
- {% set symbol_alias = '"%s"' % iterator_method_alias
- if iterator_method_alias else 'nullptr' %}
- // Iterator (@@iterator)
- static constexpr V8DOMConfiguration::SymbolKeyedMethodConfiguration
- kSymbolKeyedIteratorConfiguration = {
- v8::Symbol::GetIterator,
- {{symbol_alias}},
- {{v8_class_or_partial}}::IteratorMethodCallback,
- 0,
- v8::DontEnum,
- V8DOMConfiguration::kOnPrototype,
- V8DOMConfiguration::kCheckHolder,
- V8DOMConfiguration::kDoNotCheckAccess,
- V8DOMConfiguration::kHasSideEffect
- };
- V8DOMConfiguration::InstallMethod(
- isolate, world, prototype_template, signature,
- kSymbolKeyedIteratorConfiguration);
- {% endfilter %}
- {% endfilter %}
- {% endif %}
-
- // Custom signature
- {% for method in methods | custom_registration(is_partial) %}
- {% filter exposed(method.overloads.exposed_test_all
- if method.overloads else method.exposed_test) %}
- {% set feature_name = method.overloads.runtime_enabled_all
- if method.overloads else method.runtime_enabled_feature_name %}
- {% if feature_name %}
- {% filter runtime_enabled(feature_name) %}
- {% if method.is_cross_origin %}
- {{install_origin_safe_method(method, 'instance_template', 'prototype_template') | trim | indent(2)}}
- {% else %}
- {{install_custom_signature(method, 'instance_template', 'prototype_template', 'interface_template', 'signature') | trim | indent(2)}}
- {% endif %}
- {% endfilter %}
- {% endif %}
- {% endfilter %}
- {% endfor %}
-}
-
-{% endif %}{# not is_array_buffer_or_view #}
-{% endblock %}
-{##############################################################################}
-{% block install_runtime_enabled %}
-{% if needs_runtime_enabled_installer %}
-{% from 'attributes.cc.tmpl' import accessor_configuration,
- attribute_configuration, install_attributes, install_interface_objects,
- with context %}
-{% from 'methods.cc.tmpl' import install_custom_signature with context %}
-{% if not is_partial %}
-void {{v8_class}}::InstallRuntimeEnabledFeatures(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface) {
- {% if runtime_enabled_feature_name %}
-#error "We don't expect a runtime enabled interface {{v8_class_or_partial}} to have InstallRuntimeEnabledFeatures()."
- {% endif %}
-
- InstallRuntimeEnabledFeaturesImpl(isolate, world, instance, prototype, interface);
- {% if has_partial_interface %}
-
- // Call partial interface's installer.
- install_runtime_enabled_features_function_(isolate, world, instance, prototype, interface);
- {% endif %}
-}
-{% endif %}{# not is_partial #}
-
-void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesImpl(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface) {
- {% if runtime_enabled_feature_name %}
-#error "We don't expect a runtime enabled interface {{v8_class_or_partial}} to have InstallRuntimeEnabledFeatures()."
- {% endif %}
-
- v8::Local<v8::FunctionTemplate> interface_template = {{v8_class}}::GetWrapperTypeInfo()->DomTemplate(isolate, world);
- v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interface_template);
- ALLOW_UNUSED_LOCAL(signature);
-
- {# TODO(peria): Generate code to install constants. It depends on runtime_enabled_feaure of this interface. #}
-
- {% for feature_name, attrs in runtime_enabled_attributes | selectattr('is_data_type_property') | groupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- {{install_interface_objects(attrs | sort, 'instance', 'prototype')}}
- {% endfilter %}
- {% endfor %}
-
- {% for feature_name, attrs in runtime_enabled_attributes | selectattr('is_data_type_property', 'equalto', False) | groupby('runtime_enabled_feature_name') %}
- {% filter runtime_enabled(feature_name) %}
- {{install_attributes(attrs | sort, 'instance', 'prototype', 'interface') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
-
- {% if iterator_method and iterator_method.runtime_enabled_feature_name %}
-#error "{{v8_class_or_partial}} should not have runtime enabled iterator (@@iterator)."
- {% endif %}
-
- {% if methods | custom_registration(is_partial) %}
- {% for method in methods | custom_registration(is_partial) %}
- {% filter exposed(method.overloads.exposed_test_all
- if method.overloads else method.exposed_test) %}
- {% set feature_name = (method.overloads.runtime_enabled_all
- if method.overloads else method.runtime_enabled_feature_name) %}
- {% if feature_name %}
- {% filter runtime_enabled(feature_name) %}
- {% if method.is_cross_origin %}
-#error "{{v8_class_or_partial}} should not have runtime enabled and cross origin methods."
- {% else %}
- {{install_custom_signature(method, 'instance', 'prototype', 'interface', 'signature') | trim | indent(2)}}
- {% endif %}
- {% endfilter %}
- {% endif %}
- {% endfilter %}
- {% endfor %}
- {% endif %}
-}
-
-{% endif %}{# needs_runtime_enabled_installer #}
-{% endblock %}
-{##############################################################################}
-{% block origin_trials %}
-{% from 'attributes.cc.tmpl' import accessor_configuration,
- attribute_configuration, install_attributes, install_interface_objects,
- with context %}
-{% from 'constants.cc.tmpl' import constant_configuration with context %}
-{% from 'methods.cc.tmpl' import method_configuration with context %}
-{% for feature in optional_features %}
-void {{v8_class_or_partial}}::Install{{feature.name}}(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface) {
- {% if feature.attributes or feature.methods %}
- v8::Local<v8::FunctionTemplate> interface_template =
- {{v8_class}}::GetWrapperTypeInfo()->DomTemplate(isolate, world);
- v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interface_template);
- ALLOW_UNUSED_LOCAL(signature);
- {% endif %}
- {% if feature.needs_context %}
- ExecutionContext* execution_context = ToExecutionContext(isolate->GetCurrentContext());
- {% endif %}{# needs context #}
- {% if feature.needs_cross_origin_isolated %}
- bool is_cross_origin_isolated = (execution_context && execution_context->CrossOriginIsolatedCapability());
- {% endif %}{# needs cross-origin isolated #}
- {% if feature.needs_direct_socket_enabled %}
- bool is_direct_socket_enabled = (execution_context && execution_context->DirectSocketCapability());
- {% endif %}{# needs direct socket enabled #}
- {% if feature.needs_secure_context %}
- bool is_secure_context = (execution_context && execution_context->IsSecureContext());
- {% endif %}{# needs secure context #}
- {# Origin-Trial-enabled attributes #}
- {% for cross_origin_isolated_test, attribute_list in feature.attributes | selectattr('is_data_type_property') | groupby('cross_origin_isolated_test') %}
- {% filter cross_origin_isolated(cross_origin_isolated_test) %}
- {{install_interface_objects(attribute_list, 'instance', 'prototype') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
- {% for cross_origin_isolated_test, attribute_list in feature.attributes | rejectattr('is_data_type_property') | groupby('cross_origin_isolated_test') %}
- {% filter cross_origin_isolated(cross_origin_isolated_test) %}
- {{install_interface_objects(attribute_list, 'instance', 'prototype') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
- {% for direct_socket_enabled_test, attribute_list in feature.attributes | selectattr('is_data_type_property') | groupby('direct_socket_enabled_test') %}
- {% filter direct_socket_enabled(direct_socket_enabled_test) %}
- {{install_interface_objects(attribute_list, 'instance', 'prototype') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
- {% for direct_socket_enabled_test, attribute_list in feature.attributes | rejectattr('is_data_type_property') | groupby('direct_socket_enabled_test') %}
- {% filter direct_socket_enabled(direct_socket_enabled_test) %}
- {{install_interface_objects(attribute_list, 'instance', 'prototype') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
- {% for secure_context_test, attribute_list in feature.attributes | selectattr('is_data_type_property') | groupby('secure_context_test') %}
- {% filter secure_context(secure_context_test) %}
- {{install_interface_objects(attribute_list, 'instance', 'prototype') | trim | indent(2)}}
- {% endfilter %}
- {% endfor %}
- {% for secure_context_test, attribute_list in feature.attributes | rejectattr('is_data_type_property') | groupby('secure_context_test') %}
- {% filter secure_context(secure_context_test) %}
- {{install_attributes(attribute_list, 'instance', 'prototype', 'interface') | trim | indent(2)}}
- {% endfilter %}{# secure_context #}
- {% endfor %}
- {# Origin-Trial-enabled constants #}
- {% for constant in feature.constants %}
- {% set constant_name = constant.camel_case_name %}
- static constexpr V8DOMConfiguration::ConstantConfiguration
- k{{constant_name}}Configuration = {{constant_configuration(constant)}};
- V8DOMConfiguration::InstallConstant(
- isolate, interface, prototype, k{{constant_name}}Configuration);
- {% endfor %}
- {# Origin-Trial-enabled methods (no overloads) #}
- {% for method in feature.methods %}
- {% filter exposed(method.exposed_test) %}
- {% filter secure_context(method.secure_context_test) %}
- {% filter cross_origin_isolated(method.cross_origin_isolated_test) %}
- {% filter direct_socket_enabled(method.direct_socket_enabled_test) %}
- static constexpr V8DOMConfiguration::MethodConfiguration
- k{{method.camel_case_name}}Configurations[] = {
- {{method_configuration(method) | trim | indent(6)}}
- };
- for (const auto& config : k{{method.camel_case_name}}Configurations) {
- V8DOMConfiguration::InstallMethod(
- isolate, world, instance, prototype,
- interface, signature, config);
- }
- {% endfilter %}{# direct_socket_enabled #}
- {% endfilter %}{# cross_origin_isolated #}
- {% endfilter %}{# secure_context #}
- {% endfilter %}{# exposed_test #}
- {% endfor %}
-}
-
-void {{v8_class_or_partial}}::Install{{feature.name}}(
- ScriptState* script_state, v8::Local<v8::Object> instance) {
- V8PerContextData* per_context_data = script_state->PerContextData();
- v8::Local<v8::Object> prototype = per_context_data->PrototypeForType(
- {{v8_class}}::GetWrapperTypeInfo());
- v8::Local<v8::Function> interface = per_context_data->ConstructorForType(
- {{v8_class}}::GetWrapperTypeInfo());
- ALLOW_UNUSED_LOCAL(interface);
- Install{{feature.name}}(script_state->GetIsolate(), script_state->World(), instance, prototype, interface);
-}
-{% if not feature.needs_instance %}
-
-void {{v8_class_or_partial}}::Install{{feature.name}}(ScriptState* script_state) {
- Install{{feature.name}}(script_state, v8::Local<v8::Object>());
-}
-{% endif %}
-
-{% endfor %}{# feature #}
-{% endblock %}
-{##############################################################################}
-{% block get_dom_template %}{% endblock %}
-{% block get_dom_template_for_named_properties_object %}{% endblock %}
-{% block has_instance %}{% endblock %}
-{% block to_impl %}{% endblock %}
-{% block to_impl_with_type_check %}{% endblock %}
-{##############################################################################}
-{% block install_conditional_features %}
-{% from 'attributes.cc.tmpl' import install_conditional_attributes,
- install_conditional_interface_objects with context %}
-{% from 'methods.cc.tmpl' import install_conditional_methods with context %}
-{% if install_conditional_features_func %}
-void {{v8_class_or_partial}}::InstallConditionalFeatures(
- v8::Local<v8::Context> context,
- const DOMWrapperWorld& world,
- v8::Local<v8::Object> instance_object,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object,
- v8::Local<v8::FunctionTemplate> interface_template) {
- CHECK(!interface_template.IsEmpty());
- DCHECK((!prototype_object.IsEmpty() && !interface_object.IsEmpty()) ||
- !instance_object.IsEmpty());
- {% if is_partial %}
- {{v8_class}}::InstallConditionalFeatures(
- context, world, instance_object, prototype_object, interface_object, interface_template);
- {% endif %}
-
- v8::Isolate* isolate = context->GetIsolate();
-
- {% if unscopables %}
- if (!prototype_object.IsEmpty()) {
- v8::Local<v8::Name> unscopables_symbol(v8::Symbol::GetUnscopables(isolate));
- v8::Local<v8::Object> unscopables;
- bool has_unscopables;
- if (prototype_object->HasOwnProperty(context, unscopables_symbol)
- .To(&has_unscopables) && has_unscopables) {
- unscopables = prototype_object->Get(context, unscopables_symbol)
- .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) %}
- unscopables->CreateDataProperty(
- context, V8AtomicString(isolate, "{{name}}"), v8::True(isolate))
- .FromJust();
- {% endfilter %}
- {% endfor %}
- prototype_object->CreateDataProperty(
- context, unscopables_symbol, unscopables).FromJust();
- }
- {% endif %}{# unscopables #}
-
- {% if conditional_attributes or conditional_methods %}
- v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interface_template);
- {% endif %}
- {% if conditional_attributes or conditional_methods or conditional_interface_objects %}
- ExecutionContext* execution_context = ToExecutionContext(context);
- DCHECK(execution_context);
- {% if has_conditional_secure_attributes or has_conditional_secure_methods %}
- bool is_secure_context = (execution_context && execution_context->IsSecureContext());
- {% endif %}
- {% if has_conditional_coi_attributes or has_conditional_coi_methods %}
- bool is_cross_origin_isolated = (execution_context && execution_context->CrossOriginIsolatedCapability());
- {% endif %}
- {% if has_conditional_direct_socket_attributes or has_conditional_direct_socket_methods %}
- bool is_direct_socket_enabled = (execution_context && execution_context->DirectSocketCapability());
- {% endif %}
-
- {% set attributes_on_instance = conditional_attributes | selectattr('on_instance') | list %}
- {% set methods_on_instance = conditional_methods | selectattr('on_instance') | list %}
- {% if attributes_on_instance or conditional_interface_objects or methods_on_instance %}
- if (!instance_object.IsEmpty()) {
- {{install_conditional_attributes(attributes_on_instance) | trim | indent(4)}}
- {{install_conditional_interface_objects(conditional_interface_objects) | trim | indent(4)}}
- {{install_conditional_methods(methods_on_instance) | trim | indent(4)}}
- }
- {% endif %}
-
- {% set attributes_on_prototype = conditional_attributes | selectattr('on_prototype') | list %}
- {% set attributes_on_interface = conditional_attributes | selectattr('on_interface') | list %}
- {% set methods_on_prototype = conditional_methods | selectattr('on_prototype') | list %}
- {% set methods_on_interface = conditional_methods | selectattr('on_interface') | list %}
- {% if attributes_on_prototype or attributes_on_interface or methods_on_prototype or methods_on_interface %}
- if (!prototype_object.IsEmpty() || !interface_object.IsEmpty()) {
- {{install_conditional_attributes(attributes_on_prototype + attributes_on_interface) | trim | indent(4)}}
- {{install_conditional_methods(methods_on_prototype + methods_on_interface) | trim | indent(4)}}
- }
- {% endif %}
- {% endif %}{# conditional_attributes or conditional_methods #}
-}
-{% endif %}
-
-{% endblock %}{# install_conditional_features #}
-{##############################################################################}
-{% block partial_interface %}{% endblock %}
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
deleted file mode 100644
index 02c4fd66c27..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
+++ /dev/null
@@ -1,654 +0,0 @@
-{% from 'utilities.cc.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %}
-
-{##############################################################################}
-{% macro runtime_timer_scope(counter) %}
-RUNTIME_CALL_TIMER_SCOPE(info.GetIsolate(), RuntimeCallStats::CounterId::{{counter}});
-{% endmacro %}
-
-{% macro runtime_timer_scope_disabled_by_default(counter) %}
-RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "{{counter}}");
-{% endmacro %}
-
-{% macro trace_event(name) %}
-BLINK_BINDINGS_TRACE_EVENT("{{name}}");
-{% endmacro %}
-
-{% macro generate_method(method, world_suffix) %}
-static void {{method.camel_case_name}}{{method.overload_index}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
- {% filter format_remove_duplicates([
- 'ExceptionState exception_state',
- 'ScriptState* script_state = ']) %}
- {% set define_exception_state -%}
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kExecutionContext, "{{interface_name}}", "{{method.name}}");
- {%- endset %}
-
- {% set function_call = func_call_with_prep_of_args(method, world_suffix) %}
-
- {% if 'exception_state' in function_call or
- (method.returns_promise and not method.is_static) %}
- {{define_exception_state}}
- {% if method.returns_promise %}
- ExceptionToRejectPromiseScope reject_promise_scope(info, exception_state);
- {% endif %}
- {% endif %}
- {% if method.is_ce_reactions %}
- CEReactionsScope ce_reactions_scope;
- {% endif %}
-
- {% if not method.is_static %}
- {% if method.returns_promise %}
- // V8DOMConfiguration::kDoNotCheckHolder
- // Make sure that info.Holder() really points to an instance of the type.
- if (!{{v8_class}}::HasInstance(info.Holder(), info.GetIsolate())) {
- {{throw_type_error(method, '"Illegal invocation"')}}
- return;
- }
- {% endif %}
- {% if interface_name == 'Window' and not method.is_cross_origin %}
- // Same-origin methods are never exposed via the cross-origin interceptors.
- // Since same-origin access requires a LocalDOMWindow, it is safe to downcast
- // here.
- LocalDOMWindow* impl = To<LocalDOMWindow>({{v8_class}}::ToImpl(info.Holder()));
- {% else %}
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
- {% endif %}{# interface_name == 'Window' and not method.is_cross_origin #}
- {% endif %}{# not method.is_static #}
-
- {% if interface_name == "Window" and method.is_cross_origin %}
- impl->ReportCoopAccess("{{method.name}}");
- {% endif %}
-
- {# Security checks #}
- {% if method.is_check_security_for_return_value %}
- {{define_exception_state}}
- if (!BindingSecurity::ShouldAllowAccessTo(
- CurrentDOMWindow(info.GetIsolate()), {{method.cpp_value}},
- BindingSecurity::ErrorReportOption::kDoNotReport)) {
- UseCounter::Count(CurrentExecutionContext(info.GetIsolate()),
- WebFeature::kCrossOrigin{{interface_name}}{{method.camel_case_name}});
- V8SetReturnValueNull(info);
- return;
- }
- {% endif %}
-
- {% if 'script_state' in function_call %}
- {% if method.is_static %}
- ScriptState* script_state = ScriptState::ForCurrentRealm(info);
- {% else %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
- {% endif %}
-
- {{function_call | trim | indent(2)}}
-}
-{% endfilter %}
-{% endmacro %}
-
-
-{######################################}
-{% macro func_call_with_prep_of_args(method, world_suffix) %}
-{{generate_arguments(method, world_suffix)}}
-{% if world_suffix %}
-{{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.cpp_value)}}
-{% else %}
-{{cpp_method_call(method, method.v8_set_return_value, method.cpp_value)}}
-{% endif %}
-{% endmacro %}
-
-
-{######################################}
-{% macro generate_arguments(method, world_suffix) %}
-{% if method.arguments %}
-
-{# Overloaded methods/constructors have length checked during overload resolution #}
-{% if method.number_of_required_arguments and not method.overload_index %}
-if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) {
- {{throw_type_error(method,
- 'ExceptionMessages::NotEnoughArguments(%(expected)d, info.Length())'
- | format(expected=method.number_of_required_arguments))}}
- return;
-}
-{% endif %}
-
-{% for argument in method.arguments %}
-{{argument.cpp_type}} {{argument.local_cpp_variable}};
-{% endfor %}
-{% if method.has_optional_argument_without_default_value %}
-{# Count the effective number of arguments. (arg1, arg2, undefined) is
- interpreted as two arguments are passed and (arg1, undefined, arg3) is
- interpreted as three arguments are passed. #}
-int num_args_passed = info.Length();
-while (num_args_passed > 0) {
- if (!info[num_args_passed - 1]->IsUndefined())
- break;
- --num_args_passed;
-}
-{% endif %}
-{% for argument in method.arguments %}
-{% if argument.set_default_value %}
-if (!info[{{argument.index}}]->IsUndefined()) {
- {{generate_argument(method, argument, world_suffix) | trim | indent(2)}}
-} else {
- {{argument.set_default_value | trim | indent(2)}};
-}
-{% else %}
-{{generate_argument(method, argument, world_suffix)}}
-{% endif %}
-{% endfor %}
-
-{% endif %}{# method.arguments #}
-{% endmacro %}
-
-
-{######################################}
-{% macro generate_argument(method, argument, world_suffix) %}
-{% if argument.is_optional_without_default_value %}
-{# Optional arguments without a default value generate an early call with
- fewer arguments if they are omitted.
- Optional Dictionary arguments default to empty dictionary. #}
-if (UNLIKELY(num_args_passed <= {{argument.index}})) {
- {% if world_suffix %}
- {{cpp_method_call(method, argument.v8_set_return_value_for_main_world, argument.cpp_value) | trim | indent(2)}}
- {% else %}
- {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value) | trim | indent(2)}}
- {% endif %}
- return;
-}
-{% endif %}
-{% if argument.is_callback_interface %}
-if (info[{{argument.index}}]->IsObject()) {
- {{argument.local_cpp_variable}} = V8{{argument.idl_type}}::Create(info[{{argument.index}}].As<v8::Object>());
-{% if argument.is_nullable %}
-} else if (info[{{argument.index}}]->IsNullOrUndefined()) {
- {{argument.local_cpp_variable}} = nullptr;
-{% elif argument.is_optional %}
-} else if (info[{{argument.index}}]->IsUndefined()) {
- {{argument.local_cpp_variable}} = nullptr;
-{% endif %}
-} else {
- {{throw_argument_error(method, argument, "The callback provided as parameter %(index)d is not an object.")}}
- return;
-}
-{% elif argument.is_callback_function %}
-if (info[{{argument.index}}]->IsFunction()) {
- {{v8_value_to_local_cpp_value(argument)}}
-{% if argument.is_nullable %}
-} else if (info[{{argument.index}}]->IsNullOrUndefined()) {
- {{argument.local_cpp_variable}} = nullptr;
-{% elif argument.is_optional %}
-} else if (info[{{argument.index}}]->IsUndefined()) {
- {{argument.local_cpp_variable}} = nullptr;
-{% endif %}
-} else {
- {{throw_argument_error(method, argument, "The callback provided as parameter %(index)d is not a function.")}}
- return;
-}
-{% elif argument.is_variadic_wrapper_type %}
-for (int i = {{argument.index}}; i < info.Length(); ++i) {
- if (!V8{{argument.idl_type}}::HasInstance(info[i], info.GetIsolate())) {
- {{throw_type_error(method, "ExceptionMessages::ArgumentNotOfType(%(index)d, \"%(type)s\")" | format(index=argument.index, type=argument.idl_type))}}
- return;
- }
- {{argument.local_cpp_variable}}.push_back(V8{{argument.idl_type}}::ToImpl(v8::Local<v8::Object>::Cast(info[i])));
-}
-{% elif argument.is_dictionary %}
-{% if not argument.use_permissive_dictionary_conversion %}
-{# Dictionaries must have type Undefined, Null or Object:
- http://heycam.github.io/webidl/#es-dictionary #}
-if (!info[{{argument.index}}]->IsNullOrUndefined() && !info[{{argument.index}}]->IsObject()) {
- {{throw_argument_error(method, argument, "parameter %(index)d ('%(name)s') is not an object.")}}
- return;
-}
-{% endif %}{# not argument.use_permissive_dictionary_conversion #}
-{{v8_value_to_local_cpp_value(argument)}}
-{% elif argument.is_explicit_nullable %}
-if (!info[{{argument.index}}]->IsNullOrUndefined()) {
- {{v8_value_to_local_cpp_value(argument) | trim | indent(2)}}
-}
-{% else %}{# argument is something else #}
-{{v8_value_to_local_cpp_value(argument)}}
-{% endif %}{# end of the dispatch by the argument type #}
-{# Type checking, possibly throw a TypeError, per:
- http://www.w3.org/TR/WebIDL/#es-type-mapping #}
-{% if argument.has_type_checking_interface and not argument.is_variadic_wrapper_type %}
-{# Type checking for wrapper interface types (if interface not implemented,
- throw a TypeError), per http://www.w3.org/TR/WebIDL/#es-interface
- Note: for variadic arguments, the type checking is done for each matched
- argument instead; see argument.is_variadic_wrapper_type code-path above. #}
-if (!{{argument.local_cpp_variable}}{% if argument.is_nullable %} && !IsUndefinedOrNull(info[{{argument.index}}]){% endif %}) {
- {{throw_type_error(method, "ExceptionMessages::ArgumentNotOfType(%(index)d, \"%(type)s\")" | format(index=argument.index, type=argument.idl_type))}}
- return;
-}
-{% elif argument.enum_values %}
-{# Invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
-{% set enum_variable = 'kValid' + argument.name[0].upper() + argument.name[1:] + 'Values' %}
-{{declare_enum_validation_variable(argument.enum_values, enum_variable)}}
-if (!IsValidEnum({{argument.local_cpp_variable}}, {{enum_variable}}, base::size({{enum_variable}}), "{{argument.enum_type}}", exception_state)) {
- return;
-}
-{% elif argument.idl_type == 'Promise' %}
-{# We require this for our implementation of promises, though not in spec:
-http://heycam.github.io/webidl/#es-promise #}
-if (!{{argument.local_cpp_variable}}.IsUndefinedOrNull() && !{{argument.local_cpp_variable}}.IsObject()) {
- {{throw_argument_error(method, argument, "parameter %(index)d ('%(name)s') is not an object.")}}
- return;
-}
-{% endif %}
-{% endmacro %}
-
-
-{######################################}
-{% macro cpp_method_call(method, v8_set_return_value, cpp_value) %}
-{# Local variables #}
-{% if method.is_call_with_execution_context or method.high_entropy == 'Direct' %}
-{# [ConstructorCallWith=ExecutionContext] or [CallWith=ExecutionContext] #}
-{% if method.is_constructor %}
-ExecutionContext* execution_context = ToExecutionContext(
- info.NewTarget().As<v8::Object>()->CreationContext());
-{% elif method.is_static %}
-ExecutionContext* execution_context = ExecutionContext::ForCurrentRealm(info);
-{% else %}
-ExecutionContext* execution_context = ExecutionContext::ForRelevantRealm(info);
-{% endif %}
-{% endif %}
-{% if method.is_call_with_document %}
-{# [ConstructorCallWith=Document] #}
-Document& document = *ToLocalDOMWindow(
- info.NewTarget().As<v8::Object>()->CreationContext())->document();
-{% endif %}
-{# Call #}
-{% if method.idl_type == 'void' %}
-{{cpp_value}};
-{% elif method.use_output_parameter_for_result %}
-{{method.cpp_type}} result;
-{{cpp_value}};
-{% elif method.is_constructor %}
-{{method.cpp_type}} impl = {{cpp_value}};
-{% elif method.use_local_result %}
-{{method.cpp_type}} result = {{cpp_value}};
-{% if method.high_entropy == 'Direct' %}
-Dactyloscoper::RecordDirectSurface(execution_context, WebFeature::k{{method.measure_as('Method')}}, result);
-{% endif %}
-{% endif %}
-{# Post-call #}
-{% if method.is_raises_exception %}
-if (exception_state.HadException()) {
- return;
-}
-{% endif %}
-{# Set return value #}
-{% if method.is_new_object and not method.do_not_test_new_object %}
-{% if not method.returns_promise %}
-{# We currently only add the DCHECK for IDL interfaces. Even though #}
-{# [NewObject] also applies to promises, there is nothing for us to check at #}
-{# the moment. #}
-// [NewObject] must always create a new wrapper. Check that a wrapper
-// does not exist yet.
-DCHECK(!result || DOMDataStore::GetWrapper(result, info.GetIsolate()).IsEmpty());
-{% endif %}{# not method.returns_promise #}
-{% endif %}
-{% if method.is_constructor %}
-{{generate_constructor_wrapper(method)}}
-{%- elif v8_set_return_value %}
-{% if method.is_explicit_nullable %}
-if (!result)
- V8SetReturnValueNull(info);
-else
- {{v8_set_return_value}};
-{% else %}
-{{v8_set_return_value}};
-{% endif %}
-{%- endif %}{# None for void #}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro throw_type_error(method, error_message) %}
-{% if method.has_exception_state or method.returns_promise %}
-exception_state.ThrowTypeError({{error_message}});
-{%- elif method.is_constructor %}
-V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToConstruct("{{interface_name}}", {{error_message}}));
-{%- else %}
-V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}}));
-{%- endif %}
-{%- endmacro %}
-
-
-{##############################################################################}
-{% macro throw_argument_error(method, argument, error_message) %}
-{% set quoted_message = '"%s"' % (error_message | replace('\"', '\\\"')) %}
-{{throw_type_error(method, quoted_message | format(index=(argument.index + 1), name=argument.name, type=argument.idl_type))}}
-{%- endmacro %}
-
-
-{##############################################################################}
-{% macro runtime_determined_length_method(overloads) %}
-static int {{overloads.camel_case_name}}MethodLength() {
- {% for length, runtime_enabled_features in overloads.runtime_determined_lengths %}
- {% for runtime_enabled_feature in runtime_enabled_features %}
- {% filter runtime_enabled(runtime_enabled_feature) %}
- return {{length}};
- {% endfilter %}
- {% endfor %}
- {% endfor %}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro runtime_determined_maxarg_method(overloads) %}
-static int {{overloads.camel_case_name}}MethodMaxArg() {
- {% for length, runtime_enabled_features in overloads.runtime_determined_maxargs %}
- {% for name in runtime_enabled_features %}
- {% filter runtime_enabled(name) %}
- return {{length}};
- {% endfilter %}
- {% endfor %}
- {% endfor %}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro overload_resolution_method(overloads, world_suffix) %}
-static void {{overloads.camel_case_name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
- scheduler::CooperativeSchedulingManager::Instance()->Safepoint();
-
- {% set fall_through_to_partial_overloads = not is_partial and overloads.has_partial_overloads %}
-
- {% if overloads.measure_all_as %}
- UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{overloads.measure_all_as}});
- {% endif %}
- {% if overloads.deprecate_all_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{overloads.deprecate_all_as}});
- {% endif %}
-
- {# First resolve by length #}
- {% if not fall_through_to_partial_overloads %}
- bool is_arity_error = false;
- {% endif %}
-
- {# This follows the overload resolution algorithm. #}
- {# https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm #}
- {# 3. Initialize argcount to be min(maxarg, n). #}
- switch (std::min({{overloads.maxarg}}, info.Length())) {
- {# 4. Remove from S all entries whose type list is not of length argcount. #}
- {% for length, tests_methods in overloads.length_tests_methods %}
- {# 12. If i = d, then: #}
- case {{length}}:
- {# Then resolve by testing argument #}
- {% for test, method in tests_methods %}
- {% if method.visible %}
- {% filter runtime_enabled(not overloads.runtime_enabled_all and method.runtime_enabled_feature_name) %}
- {% if "exception_state" in test %}
- {
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kExecutionContext,
- "{{interface_name}}", "{{overloads.name}}");
- {{ test_and_call_overloaded_method(test, method, overloads, world_suffix) | trim | indent(8) }}
- if (exception_state.HadException()) {
- exception_state.RethrowV8Exception(exception_state.GetException());
- return;
- }
- }
- {% else %}{# exception_state #}
- {{ test_and_call_overloaded_method(test, method, overloads, world_suffix) | trim | indent(6) }}
- {% endif %}{# exception_state #}
- {% endfilter %}
- {% endif %}
- {% endfor %}
- break;
- {% endfor %}{# length, tests_methods #}
- {% if not fall_through_to_partial_overloads %}
- default:
- {# 12.19. Otherwise: throw a TypeError. #}
- is_arity_error = true;
- {% endif %}
- }
-
- {% if fall_through_to_partial_overloads %}
- DCHECK({{overloads.name}}MethodForPartialInterface);
- ({{overloads.name}}MethodForPartialInterface)(info);
- {% else %}{# fall_through_to_partial_overloads #}
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kExecutionContext, "{{interface_name}}", "{{overloads.name}}");
- {% if overloads.returns_promise_all %}
- ExceptionToRejectPromiseScope reject_promise_scope(info, exception_state);
- {% endif %}
- if (is_arity_error) {
- {% if overloads.length != 0 %}
- if (info.Length() < {{overloads.length}}) {
- exception_state.ThrowTypeError(ExceptionMessages::NotEnoughArguments({{overloads.length}}, info.Length()));
- return;
- }
- {% endif %}
- {% if overloads.valid_arities %}
- if (info.Length() >= {{overloads.length}}) {
- exception_state.ThrowTypeError(ExceptionMessages::InvalidArity("{{overloads.valid_arities}}", info.Length()));
- return;
- }
- {% endif %}
- }
- exception_state.ThrowTypeError("No function was found that matched the signature provided.");
- {% endif %}{# fall_through_to_partial_overloads #}
-}
-{% endmacro %}
-
-{% macro test_and_call_overloaded_method(test, method, overloads, world_suffix) %}
-if ({{test}}) {
- {% if method.measure_as and not overloads.measure_all_as %}
- ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
- UseCounter::Count(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}});
- {% if method.high_entropy %}
- Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}});
- {% endif %}
- {% endif %}
- {% if method.deprecate_as and not overloads.deprecate_all_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
- {% endif %}
- {{method.camel_case_name}}{{method.overload_index}}Method{{world_suffix}}(info);
- return;
-}
-{% endmacro %}
-
-
-
-{##############################################################################}
-{% macro method_callback(method, world_suffix) %}
-void {{v8_class_or_partial}}::{{method.camel_case_name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
- {{ trace_event(method.runtime_call_stats.trace_event_name) | trim | indent(2) }}
- {% if method.runtime_call_stats.extended_attribute_defined %}
- {{ runtime_timer_scope(method.runtime_call_stats.method_counter) | trim | indent(2) }}
- {% else %}
- {{ runtime_timer_scope_disabled_by_default(method.runtime_call_stats.method_counter) }}
- {% endif %}
- {% if not method.overloads %}{# Overloaded methods are measured in overload_resolution_method() #}
- {% if method.measure_as %}
- ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
- UseCounter::Count(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}});
- {% if method.high_entropy %}
- Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}});
- {% endif %}
- {% endif %}
- {% if method.deprecate_as %}
- Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
- {% endif %}
- {% endif %}{# not method.overloads #}
- {% if world_suffix in method.activity_logging_world_list %}
- {% if method.is_static %}
- ScriptState* script_state = ScriptState::ForCurrentRealm(info);
- {% else %}
- ScriptState* script_state = ScriptState::ForRelevantRealm(info);
- {% endif %}
- V8PerContextData* context_data = script_state->PerContextData();
- if (context_data && context_data->ActivityLogger()) {
- context_data->ActivityLogger()->LogMethod("{{interface_name}}.{{method.name}}", info);
- }
- {% endif %}
- {% if method.is_custom %}
- {{v8_class}}::{{method.camel_case_name}}MethodCustom(info);
- {% else %}
- {{internal_namespace}}::{{method.camel_case_name}}Method{{world_suffix}}(info);
- {% endif %}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro origin_safe_method_getter(method, world_suffix) %}
-static void {{method.camel_case_name}}OriginSafeMethodGetter{{world_suffix}}(const v8::PropertyCallbackInfo<v8::Value>& info) {
- v8::Isolate* isolate = info.GetIsolate();
- V8PerIsolateData* data = V8PerIsolateData::From(isolate);
- const DOMWrapperWorld& world =
- DOMWrapperWorld::World(isolate->GetCurrentContext());
- v8::Local<v8::FunctionTemplate> interface_template =
- data->FindInterfaceTemplate(world, {{v8_class}}::GetWrapperTypeInfo());
- v8::Local<v8::Signature> signature =
- v8::Signature::New(isolate, interface_template);
-
- static int dom_template_key; // This address is used for a key to look up the dom template.
- v8::Local<v8::FunctionTemplate> method_template =
- data->FindOrCreateOperationTemplate(
- world,
- &dom_template_key,
- {{v8_class_or_partial}}::{{method.camel_case_name}}MethodCallback{{world_suffix}},
- v8::Local<v8::Value>(),
- signature,
- {{method.length}});
-
- V8SetReturnValue(
- info,
- method_template->GetFunction(
- isolate->GetCurrentContext()).ToLocalChecked());
-}
-{% endmacro %}
-
-{% macro origin_safe_method_getter_callback(method, world_suffix) %}
-void {{v8_class_or_partial}}::{{method.camel_case_name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(method.runtime_call_stats.origin_safe_method_getter_counter) }}
- {{internal_namespace}}::{{method.camel_case_name}}OriginSafeMethodGetter{{world_suffix}}(info);
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro generate_constructor(constructor) %}
-{% set name = '%sConstructorCallback' % v8_class
- if constructor.is_named_constructor else
- 'Constructor%s' % (constructor.overload_index or '') %}
-static void {{name}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
- {{ runtime_timer_scope_disabled_by_default(constructor.rcs_counter) }}
- {% set function_call = func_call_with_prep_of_args(constructor) %}
-
- {% if constructor.is_named_constructor %}
- if (!info.IsConstructCall()) {
- V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::ConstructorNotCallableAsFunction("{{constructor.name}}"));
- return;
- }
-
- if (ConstructorMode::Current(info.GetIsolate()) == ConstructorMode::kWrapExistingObject) {
- V8SetReturnValue(info, info.Holder());
- return;
- }
- {% endif %}
-
- {% if 'exception_state' in function_call %}
- ExceptionState exception_state(info.GetIsolate(), ExceptionState::kConstructionContext, "{{interface_name}}");
- {% endif %}
- {% if 'script_state' in function_call %}
- ScriptState* script_state = ScriptState::From(
- info.NewTarget().As<v8::Object>()->CreationContext());
- {% endif %}
-
- {{function_call | trim | indent(2)}}
-}
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro generate_constructor_wrapper(constructor) %}
-{% set constructor_class = v8_class + ('Constructor'
- if constructor.is_named_constructor else
- '') %}
-v8::Local<v8::Object> wrapper = info.Holder();
-wrapper = impl->AssociateWithWrapper(info.GetIsolate(), {{constructor_class}}::GetWrapperTypeInfo(), wrapper);
-V8SetReturnValue(info, wrapper);
-{% endmacro %}
-
-
-{##############################################################################}
-{% macro method_configuration(method) %}
-{% from 'utilities.cc.tmpl' import property_location %}
-{% set method_callback =
- '%s::%sMethodCallback' % (v8_class_or_partial, method.camel_case_name) %}
-{% set method_callback_for_main_world =
- '%s::%sMethodCallbackForMainWorld' % (v8_class_or_partial, method.camel_case_name)
- if method.is_per_world_bindings else 'nullptr' %}
-{% set property_attribute =
- 'static_cast<v8::PropertyAttribute>(%s)' % ' | '.join(method.property_attributes)
- if method.property_attributes else 'v8::None' %}
-{% set holder_check = 'V8DOMConfiguration::kDoNotCheckHolder'
- if method.returns_promise else 'V8DOMConfiguration::kCheckHolder' %}
-{% set access_check = 'V8DOMConfiguration::kCheckAccess'
- if method.is_check_security_for_receiver else 'V8DOMConfiguration::kDoNotCheckAccess' %}
-{% if method.is_per_world_bindings %}
-{% set method_callback_for_main_world =
- '%s::%sMethodCallbackForMainWorld' % (v8_class_or_partial, method.camel_case_name) %}
-{"{{method.name}}", {{method_callback_for_main_world}}, {{method.length}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, {{access_check}}, {{method.side_effect_type}}, V8DOMConfiguration::kMainWorld},
-{"{{method.name}}", {{method_callback}}, {{method.length}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, {{access_check}}, {{method.side_effect_type}}, V8DOMConfiguration::kNonMainWorlds}
-{%- else %}
-{"{{method.name}}", {{method_callback}}, {{method.length}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, {{access_check}}, {{method.side_effect_type}}, V8DOMConfiguration::kAllWorlds}
-{%- endif %}
-{%- endmacro %}
-
-
-{######################################}
-{% macro install_custom_signature(method, instance_template, prototype_template, interface_template, signature) %}
-{
- // Install {{method.name}} configuration
- constexpr V8DOMConfiguration::MethodConfiguration kConfigurations[] = {
- {{method_configuration(method) | trim | indent(4)}}
- };
- for (const auto& config : kConfigurations) {
- V8DOMConfiguration::InstallMethod(
- isolate, world, {{instance_template}}, {{prototype_template}},
- {{interface_template}}, {{signature}}, config);
- }
-}
-{%- endmacro %}
-
-
-{######################################}
-{% macro install_conditional_methods(methods_to_install) %}
-{% for method in methods_to_install %}
-{% filter cross_origin_isolated(method.overloads.cross_origin_isolated_test_all
- if method.overloads else
- method.cross_origin_isolated_test) %}
-{% filter direct_socket_enabled(method.overloads.direct_socket_enabled_test_all
- if method.overloads else
- method.direct_socket_enabled_test) %}
-{% filter secure_context(method.overloads.secure_context_test_all
- if method.overloads else
- method.secure_context_test) %}
-{% filter exposed(method.overloads.exposed_test_all
- if method.overloads else
- method.exposed_test) %}
-{% filter runtime_enabled(method.overloads.runtime_enabled_all
- if method.overloads else
- method.runtime_enabled_feature_name) %}
-{
- // Install {{method.name}} configuration
- const V8DOMConfiguration::MethodConfiguration kConfigurations[] = {
- {{method_configuration(method) | trim | indent(4)}}
- };
- for (const auto& config : kConfigurations) {
- V8DOMConfiguration::InstallMethod(
- isolate, world, instance_object, prototype_object,
- interface_object, signature, config);
- }
-}
-{% endfilter %}{# runtime_enabled() #}
-{% endfilter %}{# exposed() #}
-{% endfilter %}{# secure_context() #}
-{% endfilter %}{# direct_socket_enabled() #}
-{% endfilter %}{# cross_origin_isolated() #}
-{% endfor %}
-{%- endmacro %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.cc.tmpl
deleted file mode 100644
index 57f28d7ffb7..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.cc.tmpl
+++ /dev/null
@@ -1,118 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-
-#include "third_party/blink/renderer/bindings/core/v8/origin_trial_features_for_core.h"
-
-{% for include in includes %}
-#include "{{include}}"
-{% endfor %}
-
-namespace blink {
-
-namespace {
-InstallOriginTrialFeaturesFunction g_old_install_origin_trial_features_function =
- nullptr;
-InstallPendingOriginTrialFeatureFunction
- g_old_install_pending_origin_trial_feature_function = nullptr;
-
-void InstallOriginTrialFeaturesForCore(
- const WrapperTypeInfo* wrapper_type_info,
- const ScriptState* script_state,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object) {
- (*g_old_install_origin_trial_features_function)(
- wrapper_type_info, script_state, prototype_object, interface_object);
-
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- if (!execution_context)
- return;
- v8::Isolate* isolate = script_state->GetIsolate();
- const DOMWrapperWorld& world = script_state->World();
- // TODO(iclelland): Unify ContextFeatureSettings with the rest of the
- // conditional features.
- if (wrapper_type_info == V8Window::GetWrapperTypeInfo()) {
- auto* settings = ContextFeatureSettings::From(
- execution_context,
- ContextFeatureSettings::CreationMode::kDontCreateIfNotExists);
- if (settings && settings->isMojoJSEnabled()) {
- v8::Local<v8::Object> instance_object =
- script_state->GetContext()->Global();
- V8Window::InstallMojoJS(isolate, world, instance_object, prototype_object,
- interface_object);
- }
- }
- // TODO(iclelland): Extract this common code out of OriginTrialFeaturesForCore
- // and OriginTrialFeaturesForModules into a block.
- {% for interface in installers_by_interface %}
- if (wrapper_type_info == {{interface.v8_class}}::GetWrapperTypeInfo()) {
- {% if interface.is_global %}
- v8::Local<v8::Object> instance_object =
- script_state->GetContext()->Global();
- {% endif %}
- {% for installer in interface.installers %}
- if ({{installer.condition}}(execution_context)) {
- {{installer.v8_class_or_partial}}::{{installer.install_method}}(
- isolate, world, {% if interface.is_global %}instance_object{% else %}v8::Local<v8::Object>(){% endif %}, prototype_object, interface_object);
- }
- {% endfor %}
- }
- {% endfor %}
-}
-
-void InstallPendingOriginTrialFeatureForCore(OriginTrialFeature feature,
- const ScriptState* script_state) {
- (*g_old_install_pending_origin_trial_feature_function)(feature, script_state);
-
- // TODO(iclelland): Extract this common code out of OriginTrialFeaturesForCore
- // and OriginTrialFeaturesForModules into a block.
- {% if installers_by_feature %}
- v8::Local<v8::Object> prototype_object;
- v8::Local<v8::Function> interface_object;
- v8::Isolate* isolate = script_state->GetIsolate();
- const DOMWrapperWorld& world = script_state->World();
- V8PerContextData* context_data = script_state->PerContextData();
- v8::Local<v8::Context> current_context = script_state->GetContext();
- v8::Local<v8::Object> global_object = current_context->Global();
- ALLOW_UNUSED_LOCAL(global_object);
- ExecutionContext* execution_context = ToExecutionContext(current_context);
- ALLOW_UNUSED_LOCAL(execution_context);
- switch (feature) {
- {% for feature in installers_by_feature %}
- case {{feature.name_constant}}: {
- {% for installer in feature.installers %}
- {% if installer.interface_is_global %}
- if (execution_context && execution_context->{{installer.global_type_check_method}}()) {
- {{installer.v8_class_or_partial}}::{{installer.install_method}}(
- isolate, world, global_object, v8::Local<v8::Object>(), v8::Local<v8::Function>());
- }
- {% else %}
- if (context_data->GetExistingConstructorAndPrototypeForType(
- {{installer.v8_class}}::GetWrapperTypeInfo(), &prototype_object, &interface_object)) {
- {{installer.v8_class_or_partial}}::{{installer.install_method}}(
- isolate, world, v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- {% endif %}
- {% endfor %}
- break;
- }
- {% endfor %}
- default:
- break;
- }
- {% endif %}
-}
-
-} // namespace
-
-void RegisterInstallOriginTrialFeaturesForCore() {
- g_old_install_origin_trial_features_function =
- SetInstallOriginTrialFeaturesFunction(&InstallOriginTrialFeaturesForCore);
- g_old_install_pending_origin_trial_feature_function =
- SetInstallPendingOriginTrialFeatureFunction(
- &InstallPendingOriginTrialFeatureForCore);
-}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.h.tmpl
deleted file mode 100644
index a4963503470..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_core.h.tmpl
+++ /dev/null
@@ -1,17 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef THIRD_PARTY_BLINK_BINDINGS_CORE_V8_ORIGIN_TRIAL_FEATURES_FOR_CORE_H_
-#define THIRD_PARTY_BLINK_BINDINGS_CORE_V8_ORIGIN_TRIAL_FEATURES_FOR_CORE_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-
-namespace blink {
-
-CORE_EXPORT void RegisterInstallOriginTrialFeaturesForCore();
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_BINDINGS_CORE_V8_ORIGIN_TRIAL_FEATURES_FOR_CORE_H_
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.cc.tmpl
deleted file mode 100644
index e61bd0617eb..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.cc.tmpl
+++ /dev/null
@@ -1,112 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-
-#include "third_party/blink/renderer/bindings/modules/v8/origin_trial_features_for_modules.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/origin_trial_features_for_core.h"
-{% for include in includes %}
-#include "{{include}}"
-{% endfor %}
-
-namespace blink {
-
-namespace {
-InstallOriginTrialFeaturesFunction
- g_original_install_origin_trial_features_function = nullptr;
-InstallPendingOriginTrialFeatureFunction
- g_original_install_pending_origin_trial_feature_function = nullptr;
-
-void InstallOriginTrialFeaturesForModules(
- const WrapperTypeInfo* wrapper_type_info,
- const ScriptState* script_state,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object) {
- (*g_original_install_origin_trial_features_function)(
- wrapper_type_info, script_state, prototype_object, interface_object);
-
- {% if installers_by_interface %}
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- if (!execution_context)
- return;
- v8::Isolate* isolate = script_state->GetIsolate();
- const DOMWrapperWorld& world = script_state->World();
- // TODO(iclelland): Extract this common code out of OriginTrialFeaturesForCore
- // and OriginTrialFeaturesForModules into a block.
- {% for interface in installers_by_interface %}
- if (wrapper_type_info == {{interface.v8_class}}::GetWrapperTypeInfo()) {
- {% if interface.is_global %}
- v8::Local<v8::Object> instance_object =
- script_state->GetContext()->Global();
- {% endif %}
- {% for installer in interface.installers %}
- if ({{installer.condition}}(execution_context)) {
- {{installer.v8_class_or_partial}}::{{installer.install_method}}(
- isolate, world, {% if interface.is_global %}instance_object{% else %}v8::Local<v8::Object>(){% endif %}, prototype_object, interface_object);
- }
- {% endfor %}
- }
- {% endfor %}
- {% endif %}
-}
-
-void InstallPendingOriginTrialFeatureForModules(
- OriginTrialFeature feature,
- const ScriptState* script_state) {
- (*g_original_install_pending_origin_trial_feature_function)(feature,
- script_state);
-
- // TODO(iclelland): Extract this common code out of OriginTrialFeaturesForCore
- // and OriginTrialFeaturesForModules into a block.
- {% if installers_by_feature %}
- v8::Local<v8::Object> prototype_object;
- v8::Local<v8::Function> interface_object;
- v8::Isolate* isolate = script_state->GetIsolate();
- const DOMWrapperWorld& world = script_state->World();
- V8PerContextData* context_data = script_state->PerContextData();
- v8::Local<v8::Context> current_context = script_state->GetContext();
- v8::Local<v8::Object> global_object = current_context->Global();
- ALLOW_UNUSED_LOCAL(global_object);
- ExecutionContext* execution_context = ToExecutionContext(current_context);
- ALLOW_UNUSED_LOCAL(execution_context);
- switch (feature) {
- {% for feature in installers_by_feature %}
- case {{feature.name_constant}}: {
- {% for installer in feature.installers %}
- {% if installer.interface_is_global %}
- if (execution_context && execution_context->{{installer.global_type_check_method}}()) {
- {{installer.v8_class_or_partial}}::{{installer.install_method}}(
- isolate, world, global_object, v8::Local<v8::Object>(), v8::Local<v8::Function>());
- }
- {% else %}
- if (context_data->GetExistingConstructorAndPrototypeForType(
- {{installer.v8_class}}::GetWrapperTypeInfo(), &prototype_object, &interface_object)) {
- {{installer.v8_class_or_partial}}::{{installer.install_method}}(
- isolate, world, v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- {% endif %}
- {% endfor %}
- break;
- }
- {% endfor %}
- default:
- break;
- }
- {% endif %}
-}
-
-} // namespace
-
-void RegisterInstallOriginTrialFeaturesForModules() {
- RegisterInstallOriginTrialFeaturesForCore();
- g_original_install_origin_trial_features_function =
- SetInstallOriginTrialFeaturesFunction(
- &InstallOriginTrialFeaturesForModules);
- g_original_install_pending_origin_trial_feature_function =
- SetInstallPendingOriginTrialFeatureFunction(
- &InstallPendingOriginTrialFeatureForModules);
-}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.h.tmpl
deleted file mode 100644
index bac0cf176ed..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/origin_trial_features_for_modules.h.tmpl
+++ /dev/null
@@ -1,15 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef THIRD_PARTY_BLINK_BINDINGS_MODULES_V8_ORIGIN_TRIAL_FEATURES_FOR_MODULES_H_
-#define THIRD_PARTY_BLINK_BINDINGS_MODULES_V8_ORIGIN_TRIAL_FEATURES_FOR_MODULES_H_
-
-namespace blink {
-
-void RegisterInstallOriginTrialFeaturesForModules();
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_BINDINGS_MODULES_V8_ORIGIN_TRIAL_FEATURES_FOR_MODULES_H_
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl
deleted file mode 100644
index 3ca4e951b75..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends 'interface_base.cc.tmpl' %}
-
-{##############################################################################}
-{% block partial_interface %}
-void {{v8_class_or_partial}}::Initialize() {
- // Should be invoked from ModulesInitializer.
- {{v8_class}}::UpdateWrapperTypeInfo(
- &{{v8_class_or_partial}}::Install{{v8_class}}Template,
- {% if needs_runtime_enabled_installer %}
- &{{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesImpl,
- {% else %}
- nullptr,
- {% endif %}
- &{{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesOnTemplate,
- {{install_conditional_features_func or 'nullptr'}});
- {% for method in methods %}
- {% if method.overloads and method.overloads.has_partial_overloads %}
- {{v8_class}}::Register{{method.camel_case_name}}MethodForPartialInterface(&{{internal_namespace}}::{{method.camel_case_name}}Method);
- {% endif %}
- {% endfor %}
-}
-
-{% endblock %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl
deleted file mode 100644
index 41b235f6dc3..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl
+++ /dev/null
@@ -1,121 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% if optional_features %}
-class ScriptState;
-{% endif %}
-
-class {{v8_class_or_partial}} {
- STATIC_ONLY({{v8_class_or_partial}});
- public:
- static void Initialize();
- {% for method in methods if method.is_custom %}
- static void {{method.camel_case_name}}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
- {% endfor %}
- {% for attribute in attributes %}
- {% if attribute.has_custom_getter %}{# FIXME: and not attribute.implemented_by #}
- static void {{attribute.camel_case_name}}AttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>&);
- {% endif %}
- {% if attribute.has_custom_setter %}{# FIXME: and not attribute.implemented_by #}
- static void {{attribute.camel_case_name}}AttributeSetterCustom(v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&);
- {% endif %}
- {% endfor %}
- {% if install_conditional_features_func %}
- static void InstallConditionalFeatures(
- v8::Local<v8::Context>,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface,
- v8::Local<v8::FunctionTemplate> interface_template);
- {% endif %}
-
- {% for feature in optional_features %}
- static void Install{{feature.name}}(ScriptState*, v8::Local<v8::Object> instance);
- static void Install{{feature.name}}(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface);
- {% if not feature.needs_instance %}
- static void Install{{feature.name}}(ScriptState*);
- {% endif %}
- {% endfor %}
-
- static void InstallRuntimeEnabledFeaturesOnTemplate(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::FunctionTemplate> interface_template);
-
- // Callback functions
- {% for attribute in attributes %}
- {% if attribute.is_cached_accessor %}
- {{exported}}static v8::Local<v8::Private> {{attribute.camel_case_name}}CachedPropertyKey(v8::Isolate* isolate);
- {% endif %}
- {% for world_suffix in attribute.world_suffixes %}
- {% if not attribute.constructor_type %}
- {{exported}}static void {{attribute.camel_case_name}}AttributeGetterCallback{{world_suffix}}(
- {%- if attribute.is_data_type_property %}
- v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info
- {%- else %}
- const v8::FunctionCallbackInfo<v8::Value>& info
- {%- endif %});
- {% else %}
- {{exported}}static void {{attribute.camel_case_name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info);
- {% endif %}
- {% if attribute.has_setter %}
- {{exported}}static void {{attribute.camel_case_name}}AttributeSetterCallback{{world_suffix}}(
- {%- if attribute.is_data_type_property %}
- v8::Local<v8::Name>, v8::Local<v8::Value> v8_value, const v8::PropertyCallbackInfo<void>& info
- {%- else %}
- const v8::FunctionCallbackInfo<v8::Value>& info
- {%- endif %});
- {% endif %}
- {% endfor %}
- {% endfor %}
-
- {% for method in methods %}
- {% for world_suffix in method.world_suffixes %}
- {% if not method.overload_index or method.overloads %}
- {# Document about the following condition: #}
- {# https://docs.google.com/document/d/1qBC7Therp437Jbt_QYAtNYMZs6zQ_7_tnMkNUG_ACqs/edit?usp=sharing #}
- {% if (method.overloads and method.overloads.visible and
- (not method.overloads.has_partial_overloads or not is_partial)) or
- (not method.overloads and method.visible) %}
- {# A single callback is generated for overloaded methods #}
- {# with considering partial overloads #}
- {{exported}}static void {{method.camel_case_name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info);
- {% endif %}
- {% endif %}
- {% if method.is_cross_origin and method.visible %}
- {{exported}}static void {{method.camel_case_name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info);
- {% endif %}
- {% endfor %}
- {% endfor %}
- {% if iterator_method %}
- {{exported}}static void {{iterator_method.camel_case_name}}MethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
- {% endif %}
-
- private:
- {% if needs_runtime_enabled_installer %}
- static void InstallRuntimeEnabledFeaturesImpl(
- v8::Isolate*,
- const DOMWrapperWorld&,
- v8::Local<v8::Object> instance,
- v8::Local<v8::Object> prototype,
- v8::Local<v8::Function> interface);
-
- {% endif %}
- static void Install{{v8_class}}Template(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interface_template);
-};
-
-} // namespace blink
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/templates.gni b/chromium/third_party/blink/renderer/bindings/templates/templates.gni
deleted file mode 100644
index b30d21128ab..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/templates.gni
+++ /dev/null
@@ -1,32 +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.
-
-# Paths should be absolute so this file can be imported from anywhere.
-code_generator_template_files =
- get_path_info([
- "attributes.cc.tmpl",
- "callback_function.cc.tmpl",
- "callback_function.h.tmpl",
- "callback_interface.cc.tmpl",
- "callback_interface.h.tmpl",
- "callback_invoke.cc.tmpl",
- "constants.cc.tmpl",
- "copyright_block.txt",
- "dictionary_impl.cc.tmpl",
- "dictionary_impl.h.tmpl",
- "dictionary_impl_common.cc.tmpl",
- "dictionary_v8.cc.tmpl",
- "dictionary_v8.h.tmpl",
- "external_reference_table.cc.tmpl",
- "interface.cc.tmpl",
- "interface.h.tmpl",
- "interface_base.cc.tmpl",
- "methods.cc.tmpl",
- "partial_interface.cc.tmpl",
- "partial_interface.h.tmpl",
- "union_container.cc.tmpl",
- "union_container.h.tmpl",
- "utilities.cc.tmpl",
- ],
- "abspath")
diff --git a/chromium/third_party/blink/renderer/bindings/templates/union_container.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/union_container.cc.tmpl
deleted file mode 100644
index 90e1e25f3f7..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/union_container.cc.tmpl
+++ /dev/null
@@ -1,238 +0,0 @@
-{% from 'utilities.cc.tmpl' import declare_enum_validation_variable %}
-{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %}
-{#############################################################################}
-{% macro assign_and_return_if_hasinstance(member) %}
-{% if member.is_array_buffer_or_view_type %}
-if (v8_value->Is{{member.type_name}}()) {
-{% else %}
-if (V8{{member.type_name}}::HasInstance(v8_value, isolate)) {
-{% endif %}
-{% if member.is_array_buffer_view_or_typed_array %}
- {{member.cpp_local_type}} cpp_value = ToNotShared<{{member.cpp_local_type}}>(isolate, v8_value, exception_state);
- if (exception_state.HadException())
- return;
-{% else %}
- {{member.cpp_local_type}} cpp_value = V8{{member.type_name}}::ToImpl(v8::Local<v8::Object>::Cast(v8_value));
-{% endif %}
- impl.Set{{member.type_name}}(cpp_value);
- return;
-}
-{% endmacro %}
-{#############################################################################}
-{% filter format_blink_cpp_source_code %}
-{% include 'copyright_block.txt' %}
-#include "{{this_include_header_path}}"
-
-{% for filename in cpp_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{{cpp_class}}::{{cpp_class}}() : type_(SpecificType::kNone) {}
-
-{% for member in members %}
-{{member.rvalue_cpp_type}} {{cpp_class}}::GetAs{{member.type_name}}() const {
- DCHECK(Is{{member.type_name}}());
- return {{member.cpp_name}}_;
-}
-
-void {{cpp_class}}::Set{{member.type_name}}({{member.rvalue_cpp_type}} value) {
- DCHECK(IsNull());
- {% if member.enum_values %}
- NonThrowableExceptionState exception_state;
- {{declare_enum_validation_variable(member.enum_values) | trim | indent(2)}}
- if (!IsValidEnum(value, kValidValues, base::size(kValidValues), "{{member.enum_type}}", exception_state)) {
- NOTREACHED();
- return;
- }
- {% endif %}
- {{member.cpp_name}}_ = value;
- type_ = SpecificType::{{member.specific_type_enum}};
-}
-
-{{cpp_class}} {{cpp_class}}::From{{member.type_name}}({{member.rvalue_cpp_type}} value) {
- {{cpp_class}} container;
- container.Set{{member.type_name}}(value);
- return container;
-}
-
-{% endfor %}
-{{cpp_class}}::{{cpp_class}}(const {{cpp_class}}&) = default;
-{{cpp_class}}::~{{cpp_class}}() = default;
-{{cpp_class}}& {{cpp_class}}::operator=(const {{cpp_class}}&) = default;
-
-void {{cpp_class}}::Trace(Visitor* visitor) const {
- {% for member in members if member.is_traceable %}
- visitor->Trace({{member.cpp_name}}_);
- {% endfor %}
-}
-
-void {{v8_class}}::ToImpl(
- v8::Isolate* isolate,
- v8::Local<v8::Value> v8_value,
- {{cpp_class}}& impl,
- UnionTypeConversionMode conversion_mode,
- ExceptionState& exception_state) {
- if (v8_value.IsEmpty())
- return;
-
- {# The numbers in the following comments refer to the steps described in
- http://heycam.github.io/webidl/#es-union #}
- {# 1. null or undefined #}
- if (conversion_mode == UnionTypeConversionMode::kNullable && IsUndefinedOrNull(v8_value))
- return;
-
- {% if dictionary_type %}
- {# 3. Dictionaries for null or undefined #}
- if (IsUndefinedOrNull(v8_value)) {
- {{v8_value_to_local_cpp_value(dictionary_type) | trim | indent}}
- impl.Set{{dictionary_type.type_name}}(cpp_value);
- return;
- }
-
- {% endif %}
- {# 4. Platform objects (interfaces) #}
- {% for interface in interface_types %}
- {{assign_and_return_if_hasinstance(interface) | trim | indent(2)}}
-
- {% endfor %}
- {# 8. ArrayBuffer #}
- {% if array_buffer_type %}
- {{assign_and_return_if_hasinstance(array_buffer_type) | trim | indent(2)}}
-
- {% endif %}
- {# 9., 10. ArrayBufferView #}
- {# FIXME: Individual typed arrays (e.g. Uint8Array) aren\'t supported yet. #}
- {% if array_buffer_view_type %}
- {{assign_and_return_if_hasinstance(array_buffer_view_type) | trim | indent(2)}}
-
- {% endif %}
- {% if array_or_sequence_type %}
- {# 11.1, 11.2. Sequences and frozen arrays #}
- if (v8_value->IsObject()) {
- ScriptIterator script_iterator = ScriptIterator::FromIterable(
- isolate, v8_value.As<v8::Object>(), exception_state);
- if (exception_state.HadException())
- return;
- if (!script_iterator.IsNull()) {
- {{v8_value_to_local_cpp_value(array_or_sequence_type) | trim | indent(6)}}
- {% if array_or_sequence_type.enum_values %}
- {{declare_enum_validation_variable(array_or_sequence_type.enum_values) | trim | indent(6)}}
- if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues),
- "{{array_or_sequence_type.enum_type}}", exception_state))
- return;
- {% endif %}
- impl.Set{{array_or_sequence_type.type_name}}(cpp_value);
- return;
- }
- }
-
- {% endif %}
- {% if dictionary_type %}
- {# 11.3. Dictionaries #}
- if (v8_value->IsObject()) {
- {{v8_value_to_local_cpp_value(dictionary_type) | trim | indent}}
- impl.Set{{dictionary_type.type_name}}(cpp_value);
- return;
- }
-
- {% endif %}
- {# 11.4. Records #}
- {% if record_type %}
- if (v8_value->IsObject()) {
- {{v8_value_to_local_cpp_value(record_type) | trim | indent}}
- impl.Set{{record_type.type_name}}(cpp_value);
- return;
- }
-
- {% endif %}
- {# TODO(bashi): Support 11.5 Callback interface when we need it #}
- {# 11.6. Objects #}
- {% if object_type %}
- if (IsUndefinedOrNull(v8_value) || v8_value->IsObject()) {
- {{v8_value_to_local_cpp_value(object_type) | trim | indent}}
- impl.Set{{object_type.type_name}}(cpp_value);
- return;
- }
-
- {% endif %}
- {# FIXME: In some cases, we can omit boolean and numeric type checks because
- we have fallback conversions. (step 16 and 17) #}
- {% if boolean_type %}
- {# 12. Boolean #}
- if (v8_value->IsBoolean()) {
- impl.SetBoolean(v8_value.As<v8::Boolean>()->Value());
- return;
- }
-
- {% endif %}
- {% if numeric_type %}
- {# 13. Number #}
- if (v8_value->IsNumber()) {
- {{v8_value_to_local_cpp_value(numeric_type) | trim | indent}}
- impl.Set{{numeric_type.type_name}}(cpp_value);
- return;
- }
-
- {% endif %}
- {% if string_type %}
- {# 14. String #}
- {
- {{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(cpp_value, kValidValues, base::size(kValidValues), "{{string_type.enum_type}}", exception_state))
- return;
- {% endif %}
- impl.Set{{string_type.type_name}}(cpp_value);
- return;
- }
-
- {# 15. Number (fallback) #}
- {% elif numeric_type %}
- {
- {{v8_value_to_local_cpp_value(numeric_type) | trim | indent}}
- impl.Set{{numeric_type.type_name}}(cpp_value);
- return;
- }
-
- {# 16. Boolean (fallback) #}
- {% elif boolean_type %}
- {
- impl.SetBoolean(v8_value->BooleanValue(isolate));
- return;
- }
-
- {% else %}
- {# 17. TypeError #}
- exception_state.ThrowTypeError("The provided value is not of type '{{type_string}}'");
- {% endif %}
-}
-
-v8::Local<v8::Value> ToV8(const {{cpp_class}}& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
- switch (impl.type_) {
- case {{cpp_class}}::SpecificType::kNone:
- {# FIXME: We might want to return undefined in some cases #}
- return v8::Null(isolate);
- {% for member in members %}
- case {{cpp_class}}::SpecificType::{{member.specific_type_enum}}:
- return {{member.cpp_value_to_v8_value}};
- {% endfor %}
- default:
- NOTREACHED();
- }
- return v8::Local<v8::Value>();
-}
-
-{{cpp_class}} NativeValueTraits<{{cpp_class}}>::NativeValue(
- v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) {
- {{cpp_class}} impl;
- {{v8_class}}::ToImpl(isolate, value, impl, UnionTypeConversionMode::kNotNullable, exception_state);
- return impl;
-}
-
-} // namespace blink
-
-{% endfilter %}{# format_blink_cpp_source_code #}
-
diff --git a/chromium/third_party/blink/renderer/bindings/templates/union_container.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/union_container.h.tmpl
deleted file mode 100644
index 374868f4419..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/union_container.h.tmpl
+++ /dev/null
@@ -1,89 +0,0 @@
-{% filter format_blink_cpp_source_code %}
-
-{% include 'copyright_block.txt' %}
-#ifndef {{header_guard}}
-#define {{header_guard}}
-
-{% for filename in header_includes %}
-#include "{{filename}}"
-{% endfor %}
-
-namespace blink {
-
-{% for decl in header_forward_decls %}
-class {{decl}};
-{% endfor %}
-
-class {{exported}}{{cpp_class}} final {
- DISALLOW_NEW();
- public:
- {{cpp_class}}();
- bool IsNull() const { return type_ == SpecificType::kNone; }
-
- {% for member in members %}
- bool Is{{member.type_name}}() const { return type_ == SpecificType::{{member.specific_type_enum}}; }
- {{member.rvalue_cpp_type}} GetAs{{member.type_name}}() const;
- void Set{{member.type_name}}({{member.rvalue_cpp_type}});
- static {{cpp_class}} From{{member.type_name}}({{member.rvalue_cpp_type}});
-
- {% endfor %}
- {{cpp_class}}(const {{cpp_class}}&);
- ~{{cpp_class}}();
- {{cpp_class}}& operator=(const {{cpp_class}}&);
- void Trace(Visitor*) const;
-
- private:
- enum class SpecificType {
- kNone,
- {% for member in members %}
- {{member.specific_type_enum}},
- {% endfor %}
- };
- SpecificType type_;
-
- {% for member in members %}
- {{member.cpp_type}} {{member.cpp_name}}_;
- {% endfor %}
-
- friend {{exported}}v8::Local<v8::Value> ToV8(const {{cpp_class}}&, v8::Local<v8::Object>, v8::Isolate*);
-};
-
-class {{v8_class}} final {
- public:
- {{exported}}static void ToImpl(v8::Isolate*, v8::Local<v8::Value>, {{cpp_class}}&, UnionTypeConversionMode, ExceptionState&);
-};
-
-{{exported}}v8::Local<v8::Value> ToV8(const {{cpp_class}}&, v8::Local<v8::Object>, v8::Isolate*);
-
-template <class CallbackInfo>
-inline void V8SetReturnValue(const CallbackInfo& callbackInfo, {{cpp_class}}& impl) {
- V8SetReturnValue(callbackInfo, ToV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
-}
-
-template <class CallbackInfo>
-inline void V8SetReturnValue(const CallbackInfo& callbackInfo, {{cpp_class}}& impl, v8::Local<v8::Object> creationContext) {
- V8SetReturnValue(callbackInfo, ToV8(impl, creationContext, callbackInfo.GetIsolate()));
-}
-
-template <>
-struct NativeValueTraits<{{cpp_class}}> : public NativeValueTraitsBase<{{cpp_class}}> {
- {{exported}}static {{cpp_class}} NativeValue(v8::Isolate*, v8::Local<v8::Value>, ExceptionState&);
- {{exported}}static {{cpp_class}} NullValue() { return {{cpp_class}}(); }
-};
-
-template <>
-struct V8TypeOf<{{cpp_class}}> {
- typedef {{v8_class}} Type;
-};
-
-} // namespace blink
-
-// We need to set canInitializeWithMemset=true because HeapVector supports
-// items that can initialize with memset or have a vtable. It is safe to
-// set canInitializeWithMemset=true for a union type object in practice.
-// See https://codereview.chromium.org/1118993002/#msg5 for more details.
-WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::{{cpp_class}})
-
-#endif // {{header_guard}}
-
-{% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl
deleted file mode 100644
index 1a81c99dd0f..00000000000
--- a/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl
+++ /dev/null
@@ -1,59 +0,0 @@
-{% macro v8_value_to_local_cpp_value(thing) %}
-{# This indirection is just to avoid spurious white-space lines. #}
-{{generate_v8_value_to_local_cpp_value(thing) | trim}}
-{%- endmacro %}
-
-
-{% macro generate_v8_value_to_local_cpp_value(thing) %}
-{% set item = thing.v8_value_to_local_cpp_value or thing %}
-{% if item.error_message %}
-/* {{item.error_message}} */
-{% else %}
-{% if item.declare_variable %}
-{% if item.assign_expression %}
-{{item.cpp_type}} {{item.cpp_name}}{ {{item.assign_expression}} };
-{% else %}
-{{item.cpp_type}} {{item.cpp_name}};
-{% endif %}
-{% else %}{# item.declare_variable #}
-{% if item.assign_expression %}
-{{item.cpp_name}} = {{item.assign_expression}};
-{% endif %}
-{% endif %}{# item.declare_variable #}
-{% if item.set_expression %}
-{{item.set_expression}};
-{% endif %}
-{% if item.check_expression %}
-if ({{item.check_expression}})
- return{% if item.return_expression %} {{item.return_expression}}{% endif %};
-{% endif %}{# item.check_expression #}
-{% endif %}{# item.error_message #}
-{% endmacro %}
-
-
-{% macro declare_enum_validation_variable(enum_values, enum_variable='kValidValues') %}
-const char* const {{enum_variable}}[] = {
-{% for enum_value in enum_values %}
-{% if enum_value is none %}
- nullptr,
-{% else %}
- "{{enum_value}}",
-{% endif %}
-{% endfor %}
-};
-{%-endmacro %}
-
-
-{% macro property_location(member) %}
-{% set property_location_list = [] %}
-{% if member.on_instance %}
-{% set property_location_list = property_location_list + ['V8DOMConfiguration::kOnInstance'] %}
-{% endif %}
-{% if member.on_prototype %}
-{% set property_location_list = property_location_list + ['V8DOMConfiguration::kOnPrototype'] %}
-{% endif %}
-{% if member.on_interface %}
-{% set property_location_list = property_location_list + ['V8DOMConfiguration::kOnInterface'] %}
-{% endif %}
-{{property_location_list | join(' | ')}}
-{%- endmacro %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/PRESUBMIT.py b/chromium/third_party/blink/renderer/build/scripts/PRESUBMIT.py
index 4cc2799ee46..347a3c6efa3 100644
--- a/chromium/third_party/blink/renderer/build/scripts/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/build/scripts/PRESUBMIT.py
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+USE_PYTHON3 = True
+
def _GenerateTestCommand(input_api, output_api, file_name, affected_list):
if not input_api.AffectedFiles(
@@ -50,6 +52,9 @@ def _RunTests(input_api, output_api):
}, {
'file_name': 'make_document_policy_features_tests.py',
'affected_list': [r'.*make_document_policy_features.*']
+ }, {
+ 'file_name': 'make_permissions_policy_features_tests.py',
+ 'affected_list': [r'.*make_permissions_policy_features.*']
}]
test_commands = []
for test in tests:
diff --git a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py
index 75dda00cbfc..e30b9382faa 100644
--- a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py
@@ -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 __future__ import print_function
+USE_PYTHON3 = True
def _RunBindingsTests(input_api, output_api):
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py b/chromium/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py
index ef5c5f57bca..5d7c6bf0f3a 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py
@@ -31,8 +31,8 @@ class CSSOMTypesWriter(json5_generator.Writer):
property_['typedom_types'] = types
# Generate CSSValueID values from keywords.
- property_['keywordIDs'] = map(enum_key_for_css_keyword,
- property_['keywords'])
+ property_['keywordIDs'] = list(
+ map(enum_key_for_css_keyword, property_['keywords']))
self._outputs = {
'cssom_types.cc': self.generate_types,
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 900fa592198..99cdf8a5725 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_AT_RULE_DESCRIPTORS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_AT_RULE_DESCRIPTORS_H_
+#include "base/notreached.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include <string.h>
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
index 39d359d8e5a..67030438d29 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
@@ -49,6 +49,7 @@ namespace {{namespace}} {
(property.font and 'kAffectsFont' or ''),
(property.is_background and 'kBackground' or ''),
(property.is_border and 'kBorder' or ''),
+ (property.is_border_radius and 'kBorderRadius' or ''),
(property.tree_scoped_value and 'kTreeScopedValue' or ''),
(property.valid_for_highlight and 'kValidForHighlight' or ''),
(property.logical_property_group and 'kInLogicalPropertyGroup' or ''),
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 6e885ec4682..20c8df084d8 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
@@ -387,13 +387,13 @@ To<Longhand>(resolved_property).{{apply_call}};
{% call(property) apply_value(property) %}
GridTrackList track_sizes;
- Vector<GridTrackSize> auto_repeat_track_sizes;
+ Vector<GridTrackSize, 1> 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 =
+ wtf_size_t auto_repeat_insertion_point =
ComputedStyleInitialValues::InitialGridAutoRepeatInsertionPoint();
StyleBuilderConverter::ConvertGridTrackList(
value, track_sizes, named_grid_lines, ordered_named_grid_lines,
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/css_value_keywords.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/css_value_keywords.h.tmpl
index 4cada5c0906..b254d4b3b67 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/css_value_keywords.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/css_value_keywords.h.tmpl
@@ -8,6 +8,7 @@
#include <string.h>
#include <stdint.h>
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
namespace blink {
@@ -27,7 +28,7 @@ inline bool IsValidCSSValueID(CSSValueID id)
return id != CSSValueID::kInvalid;
}
-const char* getValueName(CSSValueID);
+CORE_EXPORT const char* getValueName(CSSValueID);
bool isValueAllowedInMode(CSSValueID id, CSSParserMode mode);
} // namespace blink
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 9d5c8a9d298..89283606be3 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
@@ -24,7 +24,7 @@
#include "third_party/blink/renderer/core/style_property_shorthand.h"
-#include "base/stl_util.h" // for base::size()
+#include "base/cxx17_backports.h" // for base::size()
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
{% macro define_shorthand(property, expansion) -%}
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py b/chromium/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py
index 36d24dc48c1..130386e0983 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py
@@ -30,6 +30,7 @@ ALIGNMENT_ORDER = [
'RotateTransformOperation',
'TranslateTransformOperation',
'GridTrackList',
+ 'Vector<GridTrackSize, 1>',
'absl::optional<IntSize>',
'double',
# Aligns like a pointer (can be 32 or 64 bits)
@@ -38,7 +39,6 @@ ALIGNMENT_ORDER = [
'NamedGridAreaMap',
'TransformOperations',
'Vector<CSSPropertyID>',
- 'Vector<GridTrackSize>',
'Vector<AtomicString>',
'GridPosition',
'AtomicString',
@@ -80,6 +80,7 @@ ALIGNMENT_ORDER = [
'OutlineValue',
'unsigned',
'size_t',
+ 'wtf_size_t',
'int',
# Aligns like short
'unsigned short',
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_base.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_base.h.tmpl
index ff4532cee95..0089249e1c1 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_base.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_base.h.tmpl
@@ -143,10 +143,6 @@ class ComputedStyleBase {
void InheritFrom(const ComputedStyleBase& other,
IsAtShadowBoundary isAtShadowBoundary);
- void InheritCustomPropertiesFrom(const ComputedStyleBase& other) {
- inherited_variables_data_ = other.inherited_variables_data_;
- }
-
void CopyNonInheritedFromCached(
const ComputedStyleBase& other);
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl
index 734cc51b066..2d232180cfa 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl
@@ -50,7 +50,7 @@ class ComputedStyleInitialValues{
}
// Grid properties.
- static size_t InitialGridAutoRepeatInsertionPoint() { return 0; }
+ static wtf_size_t InitialGridAutoRepeatInsertionPoint() { return 0; }
static AutoRepeatType InitialGridAutoRepeatType() {
return AutoRepeatType::kNoAutoRepeat;
}
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_permissions_policy_features_tests.py b/chromium/third_party/blink/renderer/build/scripts/make_permissions_policy_features_tests.py
new file mode 100644
index 00000000000..1211aab5919
--- /dev/null
+++ b/chromium/third_party/blink/renderer/build/scripts/make_permissions_policy_features_tests.py
@@ -0,0 +1,27 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Note(crbug.com/1167597): Do NOT change the file name to end with
+# '_test.py' or '_unittest.py' as these files will be recognized by
+# 'run_blinkpy_tests.py' task, where jinja2 module is not available.
+
+import unittest
+import os
+from make_permissions_policy_features import PermissionsPolicyFeatureWriter
+from writer_test_util import path_to_test_file, WriterTest
+
+
+class MakeDocumentPolicyFeaturesTest(WriterTest):
+ def test_default_value_control(self):
+ self._test_writer(
+ PermissionsPolicyFeatureWriter, [
+ path_to_test_file('permissions_policy_default_value_control',
+ 'input', 'permissions_policy_features.json5')
+ ],
+ path_to_test_file('permissions_policy_default_value_control',
+ 'output'))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/element_factory.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/element_factory.cc.tmpl
index 3eefcf9f0ee..22e8c1b0aff 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/element_factory.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/element_factory.cc.tmpl
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/{{namespace|lower}}_element_factory.h"
-#include "base/stl_util.h" // for base::size()
+#include "base/cxx17_backports.h" // for base::size()
#include "third_party/blink/renderer/core/{{namespace|lower}}_names.h"
{% for header in tags|groupby('interface_header') %}
#include "{{header[0]}}"
@@ -66,9 +66,11 @@ static void Create{{namespace}}FunctionMap() {
const CreateElementFlags flags) {
if (!g_{{namespace|lower}}_constructors)
Create{{namespace}}FunctionMap();
- if ({{namespace}}ConstructorFunction function = g_{{namespace|lower}}_constructors->at(local_name))
- return function(document, flags);
- return nullptr;
+ auto it = g_{{namespace|lower}}_constructors->find(local_name);
+ if (it == g_{{namespace|lower}}_constructors->end())
+ return nullptr;
+ {{namespace}}ConstructorFunction function = it->value;
+ return function(document, flags);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl
index acd9e0f500f..7add4147a0d 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl
@@ -5,7 +5,7 @@
#include "{{this_include_path}}"
-#include "base/stl_util.h" // for base::size()
+#include "base/cxx17_backports.h" // for base::size()
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
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 6fbf1ae5d5a..65930e2f44d 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
@@ -7,7 +7,7 @@
#include <memory>
-#include "base/stl_util.h" // for base::size()
+#include "base/cxx17_backports.h" // for base::size()
#include "third_party/blink/renderer/platform/wtf/static_constructors.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/permissions_policy_features.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/permissions_policy_features.cc.tmpl
index 08376fc7ce4..c6dfeee43fd 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/permissions_policy_features.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/permissions_policy_features.cc.tmpl
@@ -1,24 +1,41 @@
{% 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/common/permissions_policy/permissions_policy_features.h"
#include "base/no_destructor.h"
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
namespace blink {
const PermissionsPolicyFeatureList& GetPermissionsPolicyFeatureList() {
- static const base::NoDestructor<PermissionsPolicyFeatureList> feature_list({
+ static const base::NoDestructor<PermissionsPolicyFeatureList> feature_list([] {
+ PermissionsPolicyFeatureList map({
+ {%- for feature in features %}
+ {
+ mojom::PermissionsPolicyFeature::k{{feature.name}},
+ PermissionsPolicyFeatureDefault::{{feature.feature_default}}
+ },
+ {%- endfor %}
+ });
+
{%- for feature in features %}
- {
- mojom::PermissionsPolicyFeature::k{{feature.name}},
- PermissionsPolicyFeatureDefault::{{feature.feature_default}}
- },
+ {%- if feature.default_value_behind_flag %}
+ {%- for flag, default_value in feature.default_value_behind_flag %}
+ {%- if not loop.first %} else {% endif %}
+ if (base::FeatureList::IsEnabled(features::k{{flag}})) {
+ map.find(mojom::PermissionsPolicyFeature::k{{feature.name}})->second =
+ PermissionsPolicyFeatureDefault::{{default_value}};
+ }
+ {%- endfor %}
+ {%- endif %}
{%- endfor %}
- });
+
+ return map;
+ }());
return *feature_list;
}
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 602131e3d64..0325bd26a50 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
@@ -8,6 +8,7 @@
#include <string>
+#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/build/win/precompile.h b/chromium/third_party/blink/renderer/build/win/precompile.h
index fde39b807c4..519fdffea71 100644
--- a/chromium/third_party/blink/renderer/build/win/precompile.h
+++ b/chromium/third_party/blink/renderer/build/win/precompile.h
@@ -18,8 +18,6 @@
#define _USE_MATH_DEFINES // Make math.h behave like other platforms.
-#include <Windows.h>
-
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
diff --git a/chromium/third_party/blink/renderer/config.gni b/chromium/third_party/blink/renderer/config.gni
index a073a3f1948..b9b441177b0 100644
--- a/chromium/third_party/blink/renderer/config.gni
+++ b/chromium/third_party/blink/renderer/config.gni
@@ -21,6 +21,10 @@ declare_args() {
}
declare_args() {
+ # Format the generated files to improve the code readability. Apply clang-
+ # format, gn format, etc. to the generated files if possible.
+ blink_enable_generated_code_formatting = true
+
# How many symbols to include in the build of blink. This affects
# the performance of the build since the symbols are large and dealing with
# them is slow.
@@ -38,25 +42,8 @@ declare_args() {
# If true, ffmpeg will be used for computing FFTs for WebAudio
use_webaudio_ffmpeg = !is_mac && !is_android && !use_webaudio_pffft
- # If true, the new implementation (experimental) of Blink-V8 bindings
- # (of IDL callback function) is used.
- use_blink_v8_binding_new_idl_callback_function = true
-
- # If true, the new implementation (experimental) of Blink-V8 bindings
- # (of IDL callback interface) is used.
- use_blink_v8_binding_new_idl_callback_interface = true
-
- # If true, the new implementation (experimental) of Blink-V8 bindings
- # (of IDL dictionary) is used.
- use_blink_v8_binding_new_idl_dictionary = false
-
- # If true, the new implementation (experimental) of Blink-V8 bindings
- # (of IDL interface) is used.
- use_blink_v8_binding_new_idl_interface = true
-
- # If true, the new implementation (experimental) of Blink-V8 bindings
- # (of IDL union) is used.
- use_blink_v8_binding_new_idl_union = true
+ # If true, the experimental renderer extensions library will be used.
+ use_blink_extensions_chromeos = false
}
# feature_defines_list ---------------------------------------------------------
@@ -75,18 +62,6 @@ if (use_webaudio_pffft) {
feature_defines_list += [ "WTF_USE_WEBAUDIO_PFFFT=1" ]
}
-if (use_blink_v8_binding_new_idl_dictionary) {
- feature_defines_list += [ "USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY" ]
-}
-
-if (use_blink_v8_binding_new_idl_interface) {
- feature_defines_list += [ "USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE" ]
-}
-
-if (use_blink_v8_binding_new_idl_union) {
- feature_defines_list += [ "USE_BLINK_V8_BINDING_NEW_IDL_UNION" ]
-}
-
if (blink_symbol_level == 2) {
blink_symbols_config = [ "//build/config/compiler:symbols" ]
} else if (blink_symbol_level == 1) {
diff --git a/chromium/third_party/blink/renderer/controller/OWNERS b/chromium/third_party/blink/renderer/controller/OWNERS
index 00ade91cf4e..a2c8317ef81 100644
--- a/chromium/third_party/blink/renderer/controller/OWNERS
+++ b/chromium/third_party/blink/renderer/controller/OWNERS
@@ -1,6 +1,4 @@
dcheng@chromium.org
haraken@chromium.org
-nverne@chromium.org
-slangley@chromium.org
tkent@chromium.org
diff --git a/chromium/third_party/blink/renderer/controller/blink_initializer.cc b/chromium/third_party/blink/renderer/controller/blink_initializer.cc
index 0489b8e5cd9..0b0bd41f8ed 100644
--- a/chromium/third_party/blink/renderer/controller/blink_initializer.cc
+++ b/chromium/third_party/blink/renderer/controller/blink_initializer.cc
@@ -37,10 +37,10 @@
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/binder_map.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"
#include "third_party/blink/renderer/controller/blink_leak_detector.h"
#include "third_party/blink/renderer/controller/dev_tools_frontend_impl.h"
@@ -75,10 +75,9 @@
#include "third_party/blink/renderer/controller/user_level_memory_pressure_signal_generator.h"
#endif
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-#include "third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.h"
-#else
-#include "third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.h"
+// #if expression should match the one in InitializeCommon
+#if !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_ARM64) && defined(OS_WIN)
+#include <windows.h>
#endif
namespace blink {
@@ -106,6 +105,7 @@ BlinkInitializer& GetBlinkInitializer() {
}
void InitializeCommon(Platform* platform, mojo::BinderMap* binders) {
+// #if expression should match the one around #include <windows.h>
#if !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_ARM64) && defined(OS_WIN)
// Reserve address space on 32 bit Windows, to make it likelier that large
// array buffer allocations succeed.
@@ -127,12 +127,7 @@ void InitializeCommon(Platform* platform, mojo::BinderMap* binders) {
// BlinkInitializer::Initialize() must be called before InitializeMainThread
GetBlinkInitializer().Initialize();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
V8Initializer::InitializeMainThread(V8ContextSnapshot::GetReferenceTable());
-#else
- V8Initializer::InitializeMainThread(
- V8ContextSnapshotExternalReferences::GetTable());
-#endif
GetBlinkInitializer().RegisterInterfaces(*binders);
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 9974b0ba46b..48847669959 100644
--- a/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
+++ b/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
@@ -50,6 +50,10 @@ void BlinkLeakDetector::PerformLeakDetection(
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
+ // Instruct V8 to drop its non-essential internal caches. In contrast to
+ // a memory pressure notification, this method does its work synchronously.
+ isolate->ClearCachesForTesting();
+
// For example, calling isValidEmailAddress in EmailInputType.cpp with a
// non-empty string creates a static ScriptRegexp value which holds a
// V8PerContextData indirectly. This affects the number of V8PerContextData.
@@ -57,7 +61,6 @@ void BlinkLeakDetector::PerformLeakDetection(
// here.
V8PerIsolateData::From(isolate)->EnsureScriptRegexpContext();
- WorkerThread::TerminateAllWorkersForTesting();
GetMemoryCache()->EvictResources();
// FIXME: HTML5 Notification should be closed because notification affects
@@ -73,6 +76,13 @@ void BlinkLeakDetector::PerformLeakDetection(
Page::PrepareForLeakDetection();
+ // Bail out if any worker threads are still running at this point as
+ // synchronous destruction is not supported. See https://crbug.com/1221158.
+ if (WorkerThread::WorkerThreadCount() > 0) {
+ ReportInvalidResult();
+ return;
+ }
+
// Task queue may contain delayed object destruction tasks.
// This method is called from navigation hook inside FrameLoader,
// so previous document is still held by the loader until the next event loop.
@@ -110,6 +120,10 @@ void BlinkLeakDetector::TimerFiredGC(TimerBase*) {
}
}
+void BlinkLeakDetector::ReportInvalidResult() {
+ std::move(callback_).Run(nullptr);
+}
+
void BlinkLeakDetector::ReportResult() {
mojom::blink::LeakDetectionResultPtr result =
mojom::blink::LeakDetectionResult::New();
diff --git a/chromium/third_party/blink/renderer/controller/blink_leak_detector.h b/chromium/third_party/blink/renderer/controller/blink_leak_detector.h
index d4852907272..d13685bccd5 100644
--- a/chromium/third_party/blink/renderer/controller/blink_leak_detector.h
+++ b/chromium/third_party/blink/renderer/controller/blink_leak_detector.h
@@ -28,6 +28,7 @@ class CONTROLLER_EXPORT BlinkLeakDetector : public mojom::blink::LeakDetector {
void TimerFiredGC(TimerBase*);
void ReportResult();
+ void ReportInvalidResult();
TaskRunnerTimer<BlinkLeakDetector> delayed_gc_timer_;
int number_of_gc_needed_ = 0;
diff --git a/chromium/third_party/blink/renderer/controller/memory_usage_monitor_posix.cc b/chromium/third_party/blink/renderer/controller/memory_usage_monitor_posix.cc
index 27b6056e291..ac78ff737ec 100644
--- a/chromium/third_party/blink/renderer/controller/memory_usage_monitor_posix.cc
+++ b/chromium/third_party/blink/renderer/controller/memory_usage_monitor_posix.cc
@@ -17,7 +17,7 @@ namespace {
bool ReadFileContents(int fd, base::span<char> contents) {
lseek(fd, 0, SEEK_SET);
- int res = read(fd, contents.data(), contents.size() - 1);
+ ssize_t res = read(fd, contents.data(), contents.size() - 1);
if (res <= 0)
return false;
contents.data()[res] = '\0';
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 88fd3fb0c0e..4753070d6bd 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
@@ -278,8 +278,13 @@ TEST_F(OomInterventionImplTest, V1DetectionAdsNavigation) {
frame_test_helpers::PumpPendingRequestsForFrameToLoad(
non_ad_iframe->ToWebLocalFrame());
+ blink::FrameAdEvidence ad_evidence(/*parent_is_ad=*/false);
+ ad_evidence.set_created_by_ad_script(
+ mojom::FrameCreationStackEvidence::kCreatedByAdScript);
+ ad_evidence.set_is_complete();
+
auto* local_adframe = To<LocalFrame>(WebFrame::ToCoreFrame(*ad_iframe));
- local_adframe->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ local_adframe->SetAdEvidence(ad_evidence);
auto* local_non_adframe =
To<LocalFrame>(WebFrame::ToCoreFrame(*non_ad_iframe));
diff --git a/chromium/third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.cc b/chromium/third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.cc
index d917e5bbaac..eef45fbba63 100644
--- a/chromium/third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.cc
+++ b/chromium/third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.cc
@@ -74,7 +74,7 @@ bool IsExtensionStableWorldId(const String& stable_world_id) {
return false;
if (stable_world_id.length() != 32)
return false;
- for (size_t i = 0; i < stable_world_id.length(); ++i) {
+ for (unsigned i = 0; i < stable_world_id.length(); ++i) {
if (stable_world_id[i] < 'a' || stable_world_id[i] > 'p')
return false;
}
diff --git a/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.cc b/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.cc
index ee59deac750..7aca71fa01b 100644
--- a/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.cc
+++ b/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.h"
#include <memory>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -17,6 +18,8 @@
#include "third_party/blink/renderer/controller/performance_manager/v8_worker_memory_reporter.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -130,9 +133,10 @@ class V8ProcessMemoryReporter : public RefCounted<V8ProcessMemoryReporter> {
void StartMeasurements(V8DetailedMemoryReporterImpl::Mode mode) {
DCHECK(IsMainThread());
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ DCHECK(!isolate_);
+ isolate_ = v8::Isolate::GetCurrent();
// 1. Start measurement of the main V8 isolate.
- if (!isolate) {
+ if (!isolate_) {
// This can happen in tests that do not set up the main V8 isolate
// or during setup/teardown of the process.
MainMeasurementComplete(mojom::blink::PerIsolateV8MemoryUsage::New());
@@ -141,8 +145,8 @@ class V8ProcessMemoryReporter : public RefCounted<V8ProcessMemoryReporter> {
WTF::Bind(&V8ProcessMemoryReporter::MainV8MeasurementComplete,
scoped_refptr<V8ProcessMemoryReporter>(this)));
- isolate->MeasureMemory(std::move(delegate),
- ToV8MeasureMemoryExecution(mode));
+ isolate_->MeasureMemory(std::move(delegate),
+ ToV8MeasureMemoryExecution(mode));
}
// 2. Start measurement of all worker isolates.
V8WorkerMemoryReporter::GetMemoryUsage(
@@ -173,6 +177,38 @@ class V8ProcessMemoryReporter : public RefCounted<V8ProcessMemoryReporter> {
size_t node_bytes,
size_t css_bytes) {
isolate_memory_usage->blink_bytes_used = node_bytes + css_bytes;
+ MeasureCanvasMemory(std::move(isolate_memory_usage));
+ }
+
+ void MeasureCanvasMemory(
+ mojom::blink::PerIsolateV8MemoryUsagePtr isolate_memory_usage) {
+ // We do not use HashMap here because there is no designated deleted value
+ // of ExecutionContextToken.
+ std::unordered_map<ExecutionContextToken, uint64_t,
+ ExecutionContextToken::Hasher>
+ per_context_bytes;
+ // Group and accumulate canvas bytes by execution context token.
+ for (auto entry : CanvasResourceTracker::For(isolate_)->GetResourceMap()) {
+ ExecutionContextToken token = entry.value->GetExecutionContextToken();
+ uint64_t bytes_used = entry.key->GetMemoryUsage();
+ if (!bytes_used) {
+ // Ignore canvas elements that do not have buffers.
+ continue;
+ }
+ auto it = per_context_bytes.find(token);
+ if (it == per_context_bytes.end()) {
+ per_context_bytes[token] = bytes_used;
+ } else {
+ it->second += bytes_used;
+ }
+ }
+ for (auto entry : per_context_bytes) {
+ auto memory_usage = mojom::blink::PerContextCanvasMemoryUsage::New();
+ memory_usage->token = entry.first;
+ memory_usage->bytes_used = entry.second;
+ isolate_memory_usage->canvas_contexts.push_back(std::move(memory_usage));
+ }
+
MainMeasurementComplete(std::move(isolate_memory_usage));
}
@@ -205,6 +241,7 @@ class V8ProcessMemoryReporter : public RefCounted<V8ProcessMemoryReporter> {
std::move(callback_).Run(std::move(result_));
}
+ v8::Isolate* isolate_ = nullptr;
GetV8MemoryUsageCallback callback_;
mojom::blink::PerProcessV8MemoryUsagePtr result_;
bool main_measurement_done_ = false;
diff --git a/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl_test.cc b/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl_test.cc
index 712de8d330a..984ceeee28e 100644
--- a/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl_test.cc
+++ b/chromium/third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/controller/performance_manager/v8_detailed_memory_reporter_impl.h"
+#include "base/test/bind.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
@@ -58,6 +59,33 @@ class MemoryUsageChecker {
bool called_ = false;
};
+class CanvasMemoryUsageChecker {
+ public:
+ CanvasMemoryUsageChecker(size_t canvas_width, size_t canvas_height)
+ : canvas_width_(canvas_width), canvas_height_(canvas_height) {}
+
+ void Callback(mojom::blink::PerProcessV8MemoryUsagePtr result) {
+ const size_t kMinBytesPerPixel = 1;
+ size_t actual_context_count = 0;
+ for (const auto& isolate : result->isolates) {
+ for (const auto& entry : isolate->contexts) {
+ EXPECT_LE(canvas_width_ * canvas_height_ * kMinBytesPerPixel,
+ entry->bytes_used);
+ ++actual_context_count;
+ }
+ }
+ EXPECT_EQ(1u, actual_context_count);
+ called_ = true;
+ test::ExitRunLoop();
+ }
+ bool IsCalled() { return called_; }
+
+ private:
+ size_t canvas_width_ = 0;
+ size_t canvas_height_ = 0;
+ bool called_ = false;
+};
+
} // anonymous namespace
TEST_F(V8DetailedMemoryReporterImplTest, GetV8MemoryUsage) {
@@ -138,4 +166,48 @@ TEST_F(V8DetailedMemoryReporterImplWorkerTest, GetV8MemoryUsage) {
EXPECT_TRUE(checker.IsCalled());
}
+TEST_F(V8DetailedMemoryReporterImplTest, CanvasMemoryUsage) {
+ SimRequest main_resource("https://example.com/", "text/html");
+
+ LoadURL("https://example.com/");
+
+ // CanvasPerformanceMonitor::CurrentTaskDrawsToContext() which is invoked from
+ // JS below expects to be run from a task as it adds itself to as a
+ // TaskTimeObserver that is cleared when the task is finished. Not doing so
+ // violates CanvasPerformanceMonitor consistency.
+ Thread::Current()->GetTaskRunner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&main_resource] {
+ main_resource.Complete(R"HTML(
+ <script>
+ window.onload = function () {
+ let canvas = document.getElementById('test');
+ let ctx = canvas.getContext("2d");
+ ctx.moveTo(0, 0);
+ ctx.lineTo(200, 100);
+ ctx.stroke();
+ console.log("main loaded");
+ }
+ </script>
+ <body>
+ <canvas id="test" width="10" height="10"></canvas>
+ </body>)HTML");
+ }));
+
+ test::RunPendingTasks();
+
+ // Ensure that main frame and subframe are loaded before measuring memory
+ // usage.
+ ASSERT_TRUE(ConsoleMessages().Contains("main loaded"));
+
+ V8DetailedMemoryReporterImpl reporter;
+ CanvasMemoryUsageChecker checker(10, 10);
+ reporter.GetV8MemoryUsage(V8DetailedMemoryReporterImpl::Mode::EAGER,
+ WTF::Bind(&CanvasMemoryUsageChecker::Callback,
+ WTF::Unretained(&checker)));
+
+ test::EnterRunLoop();
+
+ EXPECT_TRUE(checker.IsCalled());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/BUILD.gn b/chromium/third_party/blink/renderer/core/BUILD.gn
index dccd9d974b9..6ddecad8b81 100644
--- a/chromium/third_party/blink/renderer/core/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/BUILD.gn
@@ -7,10 +7,10 @@ import("//build/config/compiler/compiler.gni")
import("//build/config/dcheck_always_on.gni")
import("//build/config/ui.gni")
import("//build/toolchain/toolchain.gni")
+import("//media/media_options.gni")
import("//printing/buildflags/buildflags.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/modules/v8/generated.gni")
import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
import("//third_party/blink/renderer/build/scripts/scripts.gni")
import("//third_party/blink/renderer/config.gni")
@@ -62,11 +62,11 @@ import("//third_party/blink/renderer/core/svg/build.gni")
import("//third_party/blink/renderer/core/timezone/build.gni")
import("//third_party/blink/renderer/core/timing/build.gni")
import("//third_party/blink/renderer/core/trustedtypes/build.gni")
+import("//third_party/blink/renderer/core/typed_arrays/build.gni")
import("//third_party/blink/renderer/core/url/build.gni")
import("//third_party/blink/renderer/core/workers/build.gni")
import("//third_party/blink/renderer/core/xml/build.gni")
import("//third_party/blink/renderer/core/xmlhttprequest/build.gni")
-import("//third_party/blink/renderer/modules/modules_idl_files.gni")
import("//third_party/blink/renderer/platform/platform_generated.gni")
import("//third_party/protobuf/proto_library.gni")
@@ -129,7 +129,6 @@ source_set("prerequisites") {
"//skia",
"//third_party/blink/public/mojom:color_scheme_mojo_bindings",
"//third_party/blink/public/mojom:mojom_broadcastchannel_bindings_blink",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
"//third_party/blink/renderer/bindings/core/v8:generated",
"//third_party/blink/renderer/core/animation:buildflags",
"//third_party/blink/renderer/core/inspector:generated",
@@ -155,12 +154,7 @@ source_set("prerequisites") {
"//url",
"//v8",
]
- deps = [
- "//third_party/blink/public:scaled_resources",
-
- # FIXME: don't depend on bindings_modules http://crbug.com/358074
- "//third_party/blink/renderer/bindings/modules/v8:bindings_modules_v8_generated",
- ]
+ deps = [ "//third_party/blink/public:scaled_resources" ]
public_configs = [
":core_include_dirs",
@@ -180,6 +174,8 @@ component("core") {
"core_initializer.h",
]
+ sources += blink_core_sources_bindings
+
# If you create a new subdirectory 'foo', make 'foo/build.gni' to define
# blink_core_sources_foo, and include it here. Add any dependencies in the
# deps section below. For unit tests, do the same thing in the "unit_tests"
@@ -245,6 +241,7 @@ component("core") {
sources += rebase_path(blink_core_sources_timezone, "", "timezone")
sources += rebase_path(blink_core_sources_timing, "", "timing")
sources += rebase_path(blink_core_sources_trustedtypes, "", "trustedtypes")
+ sources += rebase_path(blink_core_sources_typed_arrays, "", "typed_arrays")
sources += rebase_path(blink_core_sources_url, "", "url")
sources += rebase_path(blink_core_sources_workers, "", "workers")
sources += rebase_path(blink_core_sources_xml, "", "xml")
@@ -253,6 +250,7 @@ component("core") {
configs -= core_config_remove
configs += core_config_add
+ configs += [ "//tools/v8_context_snapshot:use_v8_context_snapshot" ]
public_deps = [
":core_generated",
@@ -263,11 +261,9 @@ component("core") {
"//third_party/blink/public/mojom:mojom_broadcastchannel_bindings_blink",
"//third_party/blink/public/mojom:mojom_core_blink",
"//third_party/blink/renderer/bindings/core/v8",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
"//third_party/blink/renderer/core/animation",
"//third_party/blink/renderer/core/exported",
"//third_party/blink/renderer/core/probe",
- "//third_party/blink/renderer/core/typed_arrays",
"//third_party/blink/renderer/core/xml:xpath_generated",
"//third_party/blink/renderer/platform",
"//third_party/blink/renderer/platform/wtf",
@@ -280,6 +276,7 @@ component("core") {
]
deps = [
+ ":generated_settings_macros",
"//build:chromeos_buildflags",
"//components/paint_preview/common",
"//components/performance_manager/public/mojom:mojom_blink",
@@ -300,8 +297,8 @@ component("core") {
"//third_party/blink/public:image_resources_grit",
"//third_party/blink/public:resources",
"//third_party/blink/public/common",
+ "//third_party/blink/public/mojom:web_feature_mojo_bindings",
"//third_party/blink/public/strings",
- "//third_party/blink/renderer/core/typed_arrays:typed_arrays",
"//ui/base/cursor:cursor_base",
"//ui/base/cursor/mojom:cursor_type_blink",
"//ui/base/dragdrop/mojom:mojom_blink",
@@ -419,6 +416,8 @@ source_set("testing") {
"testing/internal_settings.h",
"testing/internals.cc",
"testing/internals.h",
+ "testing/internals_delete_all_cookies.cc",
+ "testing/internals_delete_all_cookies.h",
"testing/intersection_observer_test_helper.h",
"testing/mock_clipboard_host.cc",
"testing/mock_clipboard_host.h",
@@ -432,6 +431,7 @@ source_set("testing") {
"testing/null_execution_context.h",
"testing/origin_trials_test.cc",
"testing/origin_trials_test.h",
+ "testing/origin_trials_test_global.h",
"testing/origin_trials_test_partial.h",
"testing/record_test.cc",
"testing/record_test.h",
@@ -458,7 +458,7 @@ source_set("testing") {
public_deps = [ "//testing/gmock:gmock" ]
}
-# core_bindings_generated ------------------------------------------------------
+# generate_event_interfaces ----------------------------------------------------
generate_event_interfaces("core_event_interfaces") {
sources = [
@@ -883,6 +883,11 @@ make_names("make_core_generated_performance_entry_names") {
output_dir = blink_core_output_dir
}
+make_names("make_core_generated_pointer_type_names") {
+ in_files = [ "events/pointer_type_names.json5" ]
+ output_dir = blink_core_output_dir
+}
+
make_names("make_core_generated_securitypolicyviolation_disposition_names") {
in_files = [ "events/securitypolicyviolation_disposition_names.json5" ]
output_dir = blink_core_output_dir
@@ -1086,6 +1091,7 @@ targets_generating_sources = [
":make_core_generated_origin_trials",
":make_core_generated_performance_entry_names",
":make_core_generated_permissions_policy_helper",
+ ":make_core_generated_pointer_type_names",
":make_core_generated_securitypolicyviolation_disposition_names",
":make_core_generated_shadow_element_names",
":make_core_generated_style_property_shorthand",
@@ -1117,9 +1123,8 @@ if (is_component_build) {
}
target(core_generated_target_type, "core_generated") {
- sources = bindings_core_v8_files
-
# Add all sources generated by the targets above.
+ sources = []
foreach(current, targets_generating_sources) {
sources += get_target_outputs(current)
}
@@ -1137,19 +1142,13 @@ target(core_generated_target_type, "core_generated") {
":prerequisites",
"//gin",
"//skia",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_impl",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
+ "//third_party/blink/renderer/platform:make_platform_generated",
+ "//third_party/blink/renderer/platform/wtf",
"//third_party/iccjpeg",
"//third_party/libpng",
"//third_party/libwebp",
"//third_party/libxml",
"//third_party/libxslt",
-
- # FIXME: don't depend on bindings/modules http://crbug.com/358074
- "//third_party/blink/renderer/bindings/modules:bindings_modules_generated",
- "//third_party/blink/renderer/bindings/modules/v8:bindings_modules_v8_generated",
- "//third_party/blink/renderer/platform:make_platform_generated",
- "//third_party/blink/renderer/platform/wtf",
"//url",
"//v8",
]
@@ -1157,10 +1156,7 @@ target(core_generated_target_type, "core_generated") {
allow_circular_includes_from =
[ "//third_party/blink/renderer/core/probe:probe" ]
- configs += [
- ":core_include_dirs",
- "//tools/v8_context_snapshot:use_v8_context_snapshot",
- ]
+ configs += [ ":core_include_dirs" ]
cflags = []
defines = []
@@ -1335,7 +1331,6 @@ source_set("unit_tests") {
"layout/layout_box_test.cc",
"layout/layout_embedded_content_test.cc",
"layout/layout_flexible_box_test.cc",
- "layout/layout_grid_test.cc",
"layout/layout_image_test.cc",
"layout/layout_inline_test.cc",
"layout/layout_list_marker_test.cc",
@@ -1371,9 +1366,9 @@ source_set("unit_tests") {
"layout/ng/flex/ng_flex_layout_algorithm_test.cc",
"layout/ng/geometry/ng_box_strut_test.cc",
"layout/ng/geometry/ng_static_position_test.cc",
- "layout/ng/grid/ng_grid_child_iterator_test.cc",
"layout/ng/grid/ng_grid_layout_algorithm_test.cc",
"layout/ng/grid/ng_grid_track_collection_test.cc",
+ "layout/ng/inline/layout_ng_text_combine_test.cc",
"layout/ng/inline/layout_ng_text_test.cc",
"layout/ng/inline/ng_bidi_paragraph_test.cc",
"layout/ng/inline/ng_caret_position_test.cc",
@@ -1387,6 +1382,7 @@ source_set("unit_tests") {
"layout/ng/inline/ng_line_breaker_test.cc",
"layout/ng/inline/ng_offset_mapping_test.cc",
"layout/ng/inline/ng_physical_line_box_fragment_test.cc",
+ "layout/ng/layout_ng_fieldset_test.cc",
"layout/ng/list/layout_ng_list_item_test.cc",
"layout/ng/ng_absolute_utils_test.cc",
"layout/ng/ng_base_layout_algorithm_test.cc",
@@ -1397,7 +1393,6 @@ source_set("unit_tests") {
"layout/ng/ng_column_layout_algorithm_test.cc",
"layout/ng/ng_constraint_space_builder_test.cc",
"layout/ng/ng_fieldset_layout_algorithm_test.cc",
- "layout/ng/ng_fragment_child_iterator_test.cc",
"layout/ng/ng_fragmentation_test.cc",
"layout/ng/ng_ink_overflow_test.cc",
"layout/ng/ng_inline_layout_test.cc",
@@ -1423,9 +1418,9 @@ source_set("unit_tests") {
"layout/svg/layout_svg_text_test.cc",
"layout/text_autosizer_test.cc",
"layout/visual_rect_mapping_test.cc",
- "loader/address_space_feature_test.cc",
"loader/alternate_signed_exchange_resource_info_test.cc",
"loader/base_fetch_context_test.cc",
+ "loader/cookie_jar_unittest.cc",
"loader/document_load_timing_test.cc",
"loader/document_loader_test.cc",
"loader/font_preload_manager_test.cc",
@@ -1454,6 +1449,7 @@ source_set("unit_tests") {
"loader/resource/mock_image_resource_observer.cc",
"loader/resource/mock_image_resource_observer.h",
"loader/resource/multipart_image_resource_parser_test.cc",
+ "loader/resource/resource_loader_code_cache_test.cc",
"loader/resource/script_resource_test.cc",
"loader/resource_load_observer_for_frame_test.cc",
"loader/threadable_loader_test.cc",
@@ -1536,6 +1532,8 @@ source_set("unit_tests") {
"paint/paint_property_tree_update_tests.cc",
"paint/paint_timing_test_helper.h",
"paint/pre_paint_tree_walk_test.cc",
+ "paint/scrollable_area_painter_test.cc",
+ "paint/selection_bounds_recorder_test.cc",
"paint/svg_container_painter_test.cc",
"paint/table_painter_test.cc",
"paint/text_paint_timing_detector_test.cc",
@@ -1641,6 +1639,7 @@ source_set("unit_tests") {
"//components/paint_preview/common:common",
"//components/shared_highlighting/core/common",
"//components/ukm:test_support",
+ "//content/test:test_support",
"//mojo/public/cpp/system",
"//mojo/public/cpp/test_support:test_utils",
"//services/metrics/public/cpp:ukm_builders",
@@ -1669,6 +1668,22 @@ source_set("unit_tests") {
if (use_aura) {
sources += [ "scroll/scrollbar_theme_aura_test.cc" ]
}
+
+ if (media_use_ffmpeg || !is_android) {
+ sources += [ "exported/web_media_player_impl_unittest.cc" ]
+ data = [ "//media/test/data/" ]
+ deps += [
+ "//media",
+ "//media:test_support",
+ "//media/mojo/services",
+ "//third_party/blink/public:blink",
+ "//third_party/blink/public:test_support",
+ "//third_party/blink/public/common/tokens:tokens_headers",
+ "//third_party/blink/public/platform/media",
+ "//third_party/blink/renderer/platform/media",
+ "//ui/gfx/geometry",
+ ]
+ }
}
group("unit_tests_data") {
diff --git a/chromium/third_party/blink/renderer/core/DEPS b/chromium/third_party/blink/renderer/core/DEPS
index b51c546961c..823fcc84fa4 100644
--- a/chromium/third_party/blink/renderer/core/DEPS
+++ b/chromium/third_party/blink/renderer/core/DEPS
@@ -62,6 +62,7 @@ include_rules = [
"+cc/trees/browser_controls_params.h",
"+cc/trees/layer_tree_host.h",
"+cc/trees/paint_holding_commit_trigger.h",
+ "+cc/trees/paint_holding_reason.h",
"+cc/trees/ukm_manager.h",
"+components/performance_manager/public/mojom/coordination_unit.mojom-blink.h",
"+components/performance_manager/public/mojom/web_memory.mojom-blink.h",
@@ -73,6 +74,8 @@ include_rules = [
"+mojo/public/cpp/system",
"+mojo/public/mojom/base",
"+services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom-blink.h",
+ "+services/device/public/mojom/device_posture_provider.mojom-blink.h",
+ "+services/device/public/mojom/device_posture_provider.mojom-blink-forward.h",
"+services/device/public/mojom/wake_lock.mojom-blink.h",
"+services/metrics/public",
"+services/network/public/cpp/cors/cors_error_status.h",
@@ -113,9 +116,12 @@ include_rules = [
"+ui/base/ime/mojom/virtual_keyboard_types.mojom-blink.h",
"+ui/base/ime/mojom/virtual_keyboard_types.mojom-blink-forward.h",
"+ui/base/mojom/attributed_string.mojom-blink.h",
+ "+ui/base/pointer/pointer_device.h",
"+ui/base/resource/scale_factor.h",
"+ui/base/ui_base_features.h",
"+ui/display/mojom/display.mojom-blink.h",
+ "+ui/display/screen_info.h",
+ "+ui/display/screen_infos.h",
"+ui/gfx/geometry",
"+ui/gfx/range/range.h",
"+ui/gfx/skia_util.h",
diff --git a/chromium/third_party/blink/renderer/core/OWNERS b/chromium/third_party/blink/renderer/core/OWNERS
index 5436e37c11d..ede99cd4452 100644
--- a/chromium/third_party/blink/renderer/core/OWNERS
+++ b/chromium/third_party/blink/renderer/core/OWNERS
@@ -9,6 +9,7 @@
# Reviewers (comments indicate areas of expertise):
alexis.menard@intel.com
almaher@microsoft.com
+andruud@chromium.org
# bokan reviews changes around viewport behavior, scrolling, cc/blink interaction, co-ordinate spaces and input events
bokan@chromium.org
cbiesinger@chromium.org
@@ -19,8 +20,6 @@ dgozman@chromium.org
dlibby@microsoft.com
# drott reviews font specific changes.
drott@chromium.org
-dsinclair@chromium.org
-dstockwell@chromium.org
# dtapuska reviews input-related changes
dtapuska@chromium.org
enne@chromium.org
@@ -37,17 +36,14 @@ haraken@chromium.org
hayato@chromium.org
hiroshige@chromium.org
ikilpatrick@chromium.org
-inferno@chromium.org
japhet@chromium.org
jarhar@chromium.org
jbroman@chromium.org
jfernandez@igalia.com
-jianli@chromium.org
jochen@chromium.org
junov@chromium.org
kbr@chromium.org
keishi@chromium.org
-kenneth.r.christiansen@intel.com
kinuko@chromium.org
kojii@chromium.org
kouhei@chromium.org
@@ -61,16 +57,13 @@ pdr@chromium.org
pfeldman@chromium.org
pkasting@chromium.org
rego@igalia.com
-rbyers@chromium.org
rbuis@igalia.com
-robhogan@gmail.com
schenney@chromium.org
senorblanco@chromium.org
skobes@chromium.org
svillar@igalia.com
szager@chromium.org
thakis@chromium.org
-timloh@chromium.org
tkent@chromium.org
vmpstr@chromium.org
vollick@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/accessibility/ax_context.h b/chromium/third_party/blink/renderer/core/accessibility/ax_context.h
index 8302aebac05..16bfe8ce2aa 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/ax_context.h
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_context.h
@@ -22,8 +22,7 @@ class CORE_EXPORT AXContext {
USING_FAST_MALLOC(AXContext);
public:
- explicit AXContext(Document& document,
- const ui::AXMode& mode = ui::kAXModeComplete);
+ AXContext(Document& document, const ui::AXMode& mode);
AXContext(const AXContext&) = delete;
AXContext& operator=(const AXContext&) = delete;
virtual ~AXContext();
@@ -38,7 +37,7 @@ class CORE_EXPORT AXContext {
Document* GetDocument();
- ui::AXMode GetAXMode() { return ax_mode_; }
+ const ui::AXMode& GetAXMode() { return ax_mode_; }
protected:
WeakPersistent<Document> document_;
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
index a5e96bf7f4e..31f808cdc7e 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc
@@ -30,14 +30,14 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_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/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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
index 39309496930..beeda720b84 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -73,14 +73,11 @@ class CORE_EXPORT AXObjectCache : public GarbageCollected<AXObjectCache> {
virtual void Freeze() = 0;
virtual void Thaw() = 0;
- // Register/remove popups
- virtual void InitializePopup(Document* document) = 0;
- virtual void DisposePopup(Document* document) = 0;
-
virtual void SelectionChanged(Node*) = 0;
virtual void ChildrenChanged(Node*) = 0;
virtual void ChildrenChanged(const LayoutObject*) = 0;
virtual void ChildrenChanged(AccessibleNode*) = 0;
+ virtual void SlotAssignmentWillChange(Node*) = 0;
virtual void CheckedStateChanged(Node*) = 0;
virtual void ListboxOptionStateChanged(HTMLOptionElement*) = 0;
virtual void ListboxSelectedChildrenChanged(HTMLSelectElement*) = 0;
diff --git a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc
index 11f599ff8b1..09a63f771a1 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc
+++ b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc
index 77f2ab94b24..da4993f34a0 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc
+++ b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc
@@ -12,13 +12,14 @@
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "ui/accessibility/ax_enums.mojom-blink.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
using ScopedBlinkAXEventIntentTest = RenderingTest;
TEST_F(ScopedBlinkAXEventIntentTest, SingleIntent) {
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
ASSERT_NE(nullptr, cache);
@@ -38,7 +39,7 @@ TEST_F(ScopedBlinkAXEventIntentTest, SingleIntent) {
}
TEST_F(ScopedBlinkAXEventIntentTest, MultipleIdenticalIntents) {
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
ASSERT_NE(nullptr, cache);
@@ -63,7 +64,7 @@ TEST_F(ScopedBlinkAXEventIntentTest, MultipleIdenticalIntents) {
}
TEST_F(ScopedBlinkAXEventIntentTest, NestedIndividualIntents) {
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
ASSERT_NE(nullptr, cache);
@@ -101,7 +102,7 @@ TEST_F(ScopedBlinkAXEventIntentTest, NestedIndividualIntents) {
}
TEST_F(ScopedBlinkAXEventIntentTest, NestedMultipleIntents) {
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
ASSERT_NE(nullptr, cache);
@@ -155,7 +156,7 @@ TEST_F(ScopedBlinkAXEventIntentTest, NestedMultipleIntents) {
}
TEST_F(ScopedBlinkAXEventIntentTest, NestedIdenticalIntents) {
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
ASSERT_NE(nullptr, cache);
diff --git a/chromium/third_party/blink/renderer/core/animation/OWNERS b/chromium/third_party/blink/renderer/core/animation/OWNERS
index e7571208635..0e56346f40d 100644
--- a/chromium/third_party/blink/renderer/core/animation/OWNERS
+++ b/chromium/third_party/blink/renderer/core/animation/OWNERS
@@ -1,10 +1,6 @@
flackr@chromium.org
kevers@chromium.org
-majidvp@chromium.org
smcgruer@chromium.org
# Legacy owners:
alancutter@chromium.org
-ericwilligers@chromium.org
-
-per-file compositor_*=loyso@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/animation/animatable.cc b/chromium/third_party/blink/renderer/core/animation/animatable.cc
index 3cea3241785..1a4aed042c1 100644
--- a/chromium/third_party/blink/renderer/core/animation/animatable.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animatable.cc
@@ -4,9 +4,8 @@
#include "third_party/blink/renderer/core/animation/animatable.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/bindings/core/v8/v8_get_animations_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_animation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeanimationoptions_unrestricteddouble.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation.h"
@@ -45,7 +44,6 @@ void ReportPermissionsPolicyViolationsIfNecessary(
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionKeyframeEffectOptionsOrUnrestrictedDouble* CoerceEffectOptions(
const V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble* options) {
switch (options->GetContentType()) {
@@ -63,18 +61,6 @@ V8UnionKeyframeEffectOptionsOrUnrestrictedDouble* CoerceEffectOptions(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-UnrestrictedDoubleOrKeyframeEffectOptions CoerceEffectOptions(
- UnrestrictedDoubleOrKeyframeAnimationOptions options) {
- if (options.IsKeyframeAnimationOptions()) {
- return UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
- options.GetAsKeyframeAnimationOptions());
- } else {
- return UnrestrictedDoubleOrKeyframeEffectOptions::FromUnrestrictedDouble(
- options.GetAsUnrestrictedDouble());
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace
@@ -82,11 +68,7 @@ UnrestrictedDoubleOrKeyframeEffectOptions CoerceEffectOptions(
Animation* Animatable::animate(
ScriptState* script_state,
const ScriptValue& keyframes,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble* options,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const UnrestrictedDoubleOrKeyframeAnimationOptions& options,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (!script_state->ContextIsValid())
return nullptr;
@@ -106,22 +88,12 @@ Animation* Animatable::animate(
ReportPermissionsPolicyViolationsIfNecessary(*element->GetExecutionContext(),
*effect->Model());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!options->IsKeyframeAnimationOptions())
return element->GetDocument().Timeline().Play(effect);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (!options.IsKeyframeAnimationOptions())
- return element->GetDocument().Timeline().Play(effect);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Animation* animation;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const KeyframeAnimationOptions* options_dict =
options->GetAsKeyframeAnimationOptions();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const KeyframeAnimationOptions* options_dict =
- options.GetAsKeyframeAnimationOptions();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!options_dict->hasTimeline()) {
animation = element->GetDocument().Timeline().Play(effect);
} else if (AnimationTimeline* timeline = options_dict->timeline()) {
diff --git a/chromium/third_party/blink/renderer/core/animation/animatable.h b/chromium/third_party/blink/renderer/core/animation/animatable.h
index 5ed319271f4..03d9603b65f 100644
--- a/chromium/third_party/blink/renderer/core/animation/animatable.h
+++ b/chromium/third_party/blink/renderer/core/animation/animatable.h
@@ -43,7 +43,6 @@ class ExceptionState;
class GetAnimationsOptions;
class ScriptState;
class ScriptValue;
-class UnrestrictedDoubleOrKeyframeAnimationOptions;
class V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble;
// https://drafts.csswg.org/web-animations-1/#the-animatable-interface-mixin
@@ -53,18 +52,11 @@ class CORE_EXPORT Animatable {
// called on.
virtual Element* GetAnimationTarget() = 0;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Animation* animate(
ScriptState* script_state,
const ScriptValue& keyframes,
const V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Animation* animate(ScriptState*,
- const ScriptValue&,
- const UnrestrictedDoubleOrKeyframeAnimationOptions&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Animation* animate(ScriptState*, const ScriptValue&, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.cc b/chromium/third_party/blink/renderer/core/animation/animation.cc
index 4efce95eeaa..f11b55b34cd 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation.cc
@@ -36,7 +36,6 @@
#include "base/metrics/histogram_macros.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/double_or_scroll_timeline_auto_keyword.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
@@ -52,6 +51,7 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline_util.h"
#include "third_party/blink/renderer/core/animation/timing_calculations.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unit_values.h"
#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
@@ -186,18 +186,6 @@ bool GreaterThanOrEqualWithinTimeTolerance(const AnimationTimeDelta& a,
return a_ms > b_ms;
}
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-V8CSSNumberish* CSSNumberishToV8CSSNumberish(const CSSNumberish& value) {
- if (value.IsDouble()) {
- return MakeGarbageCollected<V8CSSNumberish>(value.GetAsDouble());
- } else if (value.IsCSSNumericValue()) {
- return MakeGarbageCollected<V8CSSNumberish>(value.GetAsCSSNumericValue());
- }
- DCHECK(value.IsNull());
- return nullptr;
-}
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
} // namespace
Animation* Animation::Create(AnimationEffect* effect,
@@ -212,29 +200,40 @@ Animation* Animation::Create(AnimationEffect* effect,
}
DCHECK(IsA<DocumentTimeline>(timeline) || timeline->IsScrollTimeline());
- // TODO(crbug.com/1097041): Support 'auto' value.
- if (timeline->IsScrollTimeline()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- auto* time_range = To<ScrollTimeline>(timeline)->timeRange();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DoubleOrScrollTimelineAutoKeyword time_range;
- To<ScrollTimeline>(timeline)->timeRange(time_range);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- // TODO(crbug.com/1140602): Support progress based animations
- // We are currently abusing the intended use of the "auto" keyword. We are
- // using it here as a signal to use progress based timeline instead of
- // having a range based current time. We are doing this maintain backwards
- // compatibility with existing tests.
- if (
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- time_range->IsScrollTimelineAutoKeyword()
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- time_range.IsScrollTimelineAutoKeyword()
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "progress based animations are not supported");
+ if (effect && timeline->IsProgressBasedTimeline()) {
+ if (effect->timing_.iteration_duration) {
+ if (effect->timing_.iteration_duration->is_inf()) {
+ exception_state.ThrowTypeError(
+ "Effect duration cannot be Infinity when used with Scroll "
+ "Timelines");
+ return nullptr;
+ }
+ } else {
+ // TODO(crbug.com/1216527)
+ // Eventually we hope to be able to be more flexible with
+ // iteration_duration "auto" and its interaction with start_delay and
+ // end_delay. For now we will throw an exception if either delay is set.
+ // Once the spec (https://github.com/w3c/csswg-drafts/pull/6337) has been
+ // ratified, we will be able to better handle mixed scenarios like "auto"
+ // and time based delays.
+
+ // If either delay or end_delay are non-zero, we can't yet handle "auto"
+ if (!effect->timing_.start_delay.is_zero() ||
+ !effect->timing_.end_delay.is_zero()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Effect duration \"auto\" with delays is not yet implemented when "
+ "used with Scroll Timelines");
+ return nullptr;
+ }
+ }
+
+ if (effect->timing_.iteration_count ==
+ std::numeric_limits<double>::infinity()) {
+ // iteration count of infinity makes no sense for scroll timelines
+ exception_state.ThrowTypeError(
+ "Effect iterations cannot be Infinity when used with Scroll "
+ "Timelines");
return nullptr;
}
}
@@ -287,7 +286,9 @@ Animation::Animation(ExecutionContext* execution_context,
compositor_state_(nullptr),
compositor_pending_(false),
compositor_group_(0),
- effect_suppressed_(false) {
+ effect_suppressed_(false),
+ compositor_property_animations_have_no_effect_(false),
+ animation_has_no_effect_(false) {
if (content_) {
if (content_->GetAnimation()) {
content_->GetAnimation()->cancel();
@@ -295,14 +296,16 @@ Animation::Animation(ExecutionContext* execution_context,
}
content_->Attach(this);
}
- document_ = timeline_ ? timeline_->GetDocument()
- : To<LocalDOMWindow>(execution_context)->document();
- DCHECK(document_);
- if (timeline_)
+ if (timeline_) {
+ document_ = timeline_->GetDocument();
+ DCHECK(document_);
timeline_->AnimationAttached(this);
- else
+ } else {
+ document_ = To<LocalDOMWindow>(execution_context)->document();
+ DCHECK(document_);
document_->Timeline().AnimationAttached(this);
+ }
probe::DidCreateAnimation(document_, sequence_number_);
}
@@ -323,7 +326,7 @@ void Animation::Dispose() {
}
AnimationTimeDelta Animation::EffectEnd() const {
- return content_ ? content_->SpecifiedTiming().EndTimeInternal()
+ return content_ ? content_->NormalizedTiming().end_time
: AnimationTimeDelta();
}
@@ -346,6 +349,88 @@ absl::optional<double> Animation::TimelineTime() const {
return timeline_ ? timeline_->CurrentTimeMilliseconds() : absl::nullopt;
}
+bool Animation::ConvertCSSNumberishToTime(
+ const V8CSSNumberish* numberish,
+ absl::optional<AnimationTimeDelta>& time,
+ String variable_name,
+ ExceptionState& exception_state) {
+ // This function is used to handle the CSSNumberish input for setting
+ // currentTime and startTime. Spec issue can be found here for this process:
+ // https://github.com/w3c/csswg-drafts/issues/6458
+
+ // Handle converting null
+ if (!numberish) {
+ time = absl::nullopt;
+ return true;
+ }
+
+ if (timeline_ && timeline_->IsProgressBasedTimeline()) {
+ // Progress based timeline
+ if (numberish->IsCSSNumericValue()) {
+ CSSUnitValue* numberish_as_percentage =
+ numberish->GetAsCSSNumericValue()->to(
+ CSSPrimitiveValue::UnitType::kPercentage);
+ if (!numberish_as_percentage) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Invalid " + variable_name +
+ ". CSSNumericValue must be a percentage for "
+ "progress based animations.");
+ return false;
+ }
+ time = (numberish_as_percentage->value() / 100) *
+ timeline_->GetDuration().value();
+ return true;
+ } else {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Invalid " + variable_name + ". Setting " + variable_name +
+ " using absolute time "
+ "values is not supported for progress based animations.");
+ return false;
+ }
+ }
+
+ // Document timeline
+ if (numberish->IsCSSNumericValue()) {
+ CSSUnitValue* numberish_as_number = numberish->GetAsCSSNumericValue()->to(
+ CSSPrimitiveValue::UnitType::kNumber);
+ if (numberish_as_number) {
+ time =
+ AnimationTimeDelta::FromMillisecondsD(numberish_as_number->value());
+ return true;
+ }
+
+ CSSUnitValue* numberish_as_milliseconds =
+ numberish->GetAsCSSNumericValue()->to(
+ CSSPrimitiveValue::UnitType::kMilliseconds);
+ if (numberish_as_milliseconds) {
+ time = AnimationTimeDelta::FromMillisecondsD(
+ numberish_as_milliseconds->value());
+ return true;
+ }
+
+ CSSUnitValue* numberish_as_seconds = numberish->GetAsCSSNumericValue()->to(
+ CSSPrimitiveValue::UnitType::kSeconds);
+ if (numberish_as_seconds) {
+ time = AnimationTimeDelta::FromSecondsD(numberish_as_seconds->value());
+ return true;
+ }
+
+ // TODO (crbug.com/1232181): Look into allowing document timelines to set
+ // currentTime and startTime using CSSNumericValues that are percentages.
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Invalid " + variable_name +
+ ". CSSNumericValue must be either a number or a time value for "
+ "time based animations.");
+ return false;
+ }
+
+ time = AnimationTimeDelta::FromMillisecondsD(numberish->GetAsDouble());
+ return true;
+}
+
// https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation.
void Animation::setCurrentTime(const V8CSSNumberish* current_time,
ExceptionState& exception_state) {
@@ -358,18 +443,11 @@ void Animation::setCurrentTime(const V8CSSNumberish* current_time,
return;
}
- if (current_time->IsCSSNumericValue()) {
- // Throw exception for CSSNumberish that is a CSSNumericValue
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "Invalid startTime. CSSNumericValue not yet supported.");
+ absl::optional<AnimationTimeDelta> new_current_time;
+ // Failure to convert results in a thrown exception and returning false.
+ if (!ConvertCSSNumberishToTime(current_time, new_current_time, "currentTime",
+ exception_state))
return;
- }
-
- DCHECK(current_time->IsDouble());
- // Convert from double to AnimationTimeDelta for internal use.
- absl::optional<AnimationTimeDelta> new_current_time =
- AnimationTimeDelta::FromMillisecondsD(current_time->GetAsDouble());
DCHECK(new_current_time);
SetCurrentTimeInternal(new_current_time.value());
@@ -393,22 +471,6 @@ void Animation::setCurrentTime(const V8CSSNumberish* current_time,
NotifyProbe();
}
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-// https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation.
-void Animation::setCurrentTime(CSSNumberish current_time,
- ExceptionState& exception_state) {
- // Forward to the new implementation.
- setCurrentTime(CSSNumberishToV8CSSNumberish(current_time), exception_state);
-}
-
-void Animation::setCurrentTime(CSSNumberish current_time) {
- NonThrowableExceptionState exception_state;
- setCurrentTime(current_time, exception_state);
-}
-
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
// https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation
// See steps for silently setting the current time. The preliminary step of
// handling an unresolved time are to be handled by the caller.
@@ -451,31 +513,27 @@ void Animation::ResetHoldTimeAndPhase() {
hold_phase_ = absl::nullopt;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* Animation::startTime() const {
if (start_time_) {
- return MakeGarbageCollected<V8CSSNumberish>(
- start_time_.value().InMillisecondsF());
+ return ConvertTimeToCSSNumberish(start_time_.value());
}
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void Animation::startTime(CSSNumberish& startTime) const {
- startTime =
- start_time_
- ? CSSNumberish::FromDouble(start_time_.value().InMillisecondsF())
- : CSSNumberish();
+
+V8CSSNumberish* Animation::ConvertTimeToCSSNumberish(
+ AnimationTimeDelta time) const {
+ if (timeline_ && timeline_->IsProgressBasedTimeline()) {
+ return To<ScrollTimeline>(*timeline_).ConvertTimeToProgress(time);
+ }
+ return MakeGarbageCollected<V8CSSNumberish>(time.InMillisecondsF());
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// https://drafts.csswg.org/web-animations/#the-current-time-of-an-animation
V8CSSNumberish* Animation::currentTime() const {
// 1. If the animation’s hold time is resolved,
// The current time is the animation’s hold time.
if (hold_time_.has_value()) {
- return MakeGarbageCollected<V8CSSNumberish>(
- hold_time_.value().InMillisecondsF());
+ return ConvertTimeToCSSNumberish(hold_time_.value());
}
// 2. If any of the following are true:
@@ -497,43 +555,8 @@ V8CSSNumberish* Animation::currentTime() const {
AnimationTimeDelta calculated_current_time =
(timeline_time.value() - start_time_.value()) * playback_rate_;
- return MakeGarbageCollected<V8CSSNumberish>(
- calculated_current_time.InMillisecondsF());
-}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// https://drafts.csswg.org/web-animations/#the-current-time-of-an-animation
-void Animation::currentTime(CSSNumberish& currentTime) const {
- // 1. If the animation’s hold time is resolved,
- // The current time is the animation’s hold time.
- if (hold_time_.has_value()) {
- currentTime =
- CSSNumberish::FromDouble(hold_time_.value().InMillisecondsF());
- return;
- }
-
- // 2. If any of the following are true:
- // * the animation has no associated timeline, or
- // * the associated timeline is inactive, or
- // * the animation’s start time is unresolved.
- // The current time is an unresolved time value.
- if (!timeline_ || !timeline_->IsActive() || !start_time_)
- return;
-
- // 3. Otherwise,
- // current time = (timeline time - start time) × playback rate
- absl::optional<AnimationTimeDelta> timeline_time = timeline_->CurrentTime();
-
- // An active timeline should always have a value, and since inactive timeline
- // is handled in step 2 above, make sure that timeline_time has a value.
- DCHECK(timeline_time.has_value());
-
- AnimationTimeDelta calculated_current_time =
- (timeline_time.value() - start_time_.value()) * playback_rate_;
-
- currentTime =
- CSSNumberish::FromDouble(calculated_current_time.InMillisecondsF());
+ return ConvertTimeToCSSNumberish(calculated_current_time);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool Animation::ValidateHoldTimeAndPhase() const {
return hold_phase_ ||
@@ -576,6 +599,9 @@ bool Animation::PreCommit(
!IsWithinAnimationTimeEpsilon(compositor_state_->start_time.value(),
start_time_.value().InSecondsF()));
+ compositor_property_animations_have_no_effect_ = false;
+ animation_has_no_effect_ = false;
+
// FIXME: softChange && !hardChange should generate a Pause/ThenStart,
// not a Cancel, but we can't communicate these to the compositor yet.
@@ -612,6 +638,14 @@ bool Animation::PreCommit(
} else {
CancelIncompatibleAnimationsOnCompositor();
}
+
+ compositor_property_animations_have_no_effect_ =
+ failure_reasons &
+ CompositorAnimations::kCompositorPropertyAnimationsHaveNoEffect;
+ animation_has_no_effect_ =
+ failure_reasons ==
+ CompositorAnimations::kCompositorPropertyAnimationsHaveNoEffect;
+
DCHECK_EQ(kRunning, CalculateAnimationPlayState());
TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
"blink.animations,devtools.timeline,benchmark,rail", "Animation",
@@ -880,6 +914,15 @@ void Animation::setTimeline(AnimationTimeline* timeline) {
AnimationPlayState old_play_state = CalculateAnimationPlayState();
absl::optional<AnimationTimeDelta> old_current_time = CurrentTimeInternal();
+ // In some cases, we need to preserve the progress of the animation between
+ // the old timeline and the new one. We do this by storing the progress using
+ // the old current time and the effect end based on the old timeline. Pending
+ // spec issue: https://github.com/w3c/csswg-drafts/issues/6452
+ double progress = 0;
+ if (old_current_time && !EffectEnd().is_zero()) {
+ progress = old_current_time.value() / EffectEnd();
+ }
+
CancelAnimationOnCompositor();
// 3. Let the timeline of the animation be the new timeline.
@@ -899,6 +942,11 @@ void Animation::setTimeline(AnimationTimeline* timeline) {
document_->Timeline().AnimationAttached(this);
SetOutdated();
+ // Update content timing to be based on new timeline type. This ensures that
+ // EffectEnd() is returning a value appropriate to the new timeline.
+ if (content_ && timeline_)
+ content_->InvalidateNormalizedTiming();
+
reset_current_time_on_resume_ = false;
if (timeline) {
@@ -921,7 +969,8 @@ void Animation::setTimeline(AnimationTimeline* timeline) {
if (old_current_time) {
reset_current_time_on_resume_ = true;
start_time_ = absl::nullopt;
- SetHoldTimeAndPhase(old_current_time, TimelinePhase::kInactive);
+ SetHoldTimeAndPhase(progress * EffectEnd(),
+ TimelinePhase::kInactive);
} else if (PendingInternal()) {
start_time_ = boundary_time;
}
@@ -932,7 +981,7 @@ void Animation::setTimeline(AnimationTimeline* timeline) {
}
} else if (old_current_time && old_timeline &&
!old_timeline->IsMonotonicallyIncreasing()) {
- SetCurrentTimeInternal(old_current_time.value());
+ SetCurrentTimeInternal(progress * EffectEnd());
}
}
@@ -994,19 +1043,12 @@ TimelinePhase Animation::CalculateCurrentPhase() const {
// https://drafts.csswg.org/web-animations/#setting-the-start-time-of-an-animation
void Animation::setStartTime(const V8CSSNumberish* start_time,
ExceptionState& exception_state) {
- if (start_time && start_time->IsCSSNumericValue()) {
- // Throw exception for CSSNumberish that is a CSSNumericValue
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "Invalid startTime. CSSNumericValue not yet supported.");
- return;
- }
absl::optional<AnimationTimeDelta> new_start_time;
- if (start_time) {
- new_start_time =
- AnimationTimeDelta::FromMillisecondsD(start_time->GetAsDouble());
- }
+ // Failure to convert results in a thrown exception and returning false.
+ if (!ConvertCSSNumberishToTime(start_time, new_start_time, "startTime",
+ exception_state))
+ return;
const bool had_start_time = start_time_.has_value();
@@ -1093,22 +1135,6 @@ void Animation::setStartTime(const V8CSSNumberish* start_time,
NotifyProbe();
}
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-// https://drafts.csswg.org/web-animations/#setting-the-start-time-of-an-animation
-void Animation::setStartTime(CSSNumberish start_time,
- ExceptionState& exception_state) {
- // Forward to the new implementation.
- setStartTime(CSSNumberishToV8CSSNumberish(start_time), exception_state);
-}
-
-void Animation::setStartTime(CSSNumberish start_time) {
- NonThrowableExceptionState exception_state;
- setStartTime(start_time, exception_state);
-}
-
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
// https://drafts.csswg.org/web-animations-1/#setting-the-associated-effect
void Animation::setEffect(AnimationEffect* new_effect) {
// 1. Let old effect be the current associated effect of animation, if any.
@@ -1930,24 +1956,19 @@ void Animation::setPlaybackRate(double playback_rate,
// 4. If previous time is resolved, set the current time of animation to
// previous time
pending_playback_rate_ = absl::nullopt;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* previous_current_time = currentTime();
playback_rate_ = playback_rate;
if (previous_current_time) {
setCurrentTime(previous_current_time, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish previous_current_time;
- currentTime(previous_current_time);
- playback_rate_ = playback_rate;
- if (!previous_current_time.IsNull()) {
- setCurrentTime(previous_current_time, exception_state);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Adds a UseCounter to check if setting playbackRate causes a compensatory
// seek forcing a change in start_time_
- if (start_time_before && start_time_ != start_time_before &&
+ // We use an epsilon (1 microsecond) to handle precision issue.
+ double epsilon = 1e-6;
+ if (start_time_before && start_time_ &&
+ fabs(start_time_.value().InMillisecondsF() -
+ start_time_before.value().InMillisecondsF()) > epsilon &&
CalculateAnimationPlayState() != kFinished) {
UseCounter::Count(GetExecutionContext(),
WebFeature::kAnimationSetPlaybackRateCompensatorySeek);
@@ -2078,6 +2099,34 @@ base::TimeDelta Animation::ComputeCompositorTimeOffset() const {
return base::TimeDelta::FromSecondsD(time_offset_s / fabs(playback_rate));
}
+void Animation::MarkPendingIfCompositorPropertyAnimationChanges(
+ const PaintArtifactCompositor* paint_artifact_compositor) {
+ // |compositor_property_animations_have_no_effect_| will already be calculated
+ // in |Animation::PreCommit| if the animation is pending.
+ if (compositor_pending_)
+ return;
+
+ bool had_no_effect = compositor_property_animations_have_no_effect_;
+ compositor_property_animations_have_no_effect_ = false;
+
+ auto* keyframe_effect = DynamicTo<KeyframeEffect>(content_.Get());
+ if (!keyframe_effect || !keyframe_effect->IsCurrent()) {
+ // If the animation is not running, we can skip checking for having no
+ // effect. We can also skip the call to |SetCompositorPending| to avoid
+ // marking finished animations as pending.
+ return;
+ }
+
+ Element* target = keyframe_effect->EffectTarget();
+ if (target && keyframe_effect->Model()) {
+ compositor_property_animations_have_no_effect_ =
+ CompositorAnimations::CompositorPropertyAnimationsHaveNoEffect(
+ *target, *keyframe_effect->Model(), paint_artifact_compositor);
+ }
+ if (compositor_property_animations_have_no_effect_ != had_no_effect)
+ SetCompositorPending();
+}
+
void Animation::StartAnimationOnCompositor(
const PaintArtifactCompositor* paint_artifact_compositor) {
DCHECK_EQ(
@@ -2290,9 +2339,11 @@ absl::optional<AnimationTimeDelta> Animation::TimeToEffectChange() {
return -current_time.value() / playback_rate_;
}
- if (!HasActiveAnimationsOnCompositor() &&
- (content_->GetPhase() == Timing::kPhaseActive))
+ // If this animation has no effect, we can skip ticking it on main.
+ if (!HasActiveAnimationsOnCompositor() && !animation_has_no_effect_ &&
+ (content_->GetPhase() == Timing::kPhaseActive)) {
return AnimationTimeDelta();
+ }
return (playback_rate_ > 0)
? (content_->TimeToForwardsEffectChange() / playback_rate_)
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.h b/chromium/third_party/blink/renderer/core/animation/animation.h
index cb2fa53733b..b344716fb32 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation.h
@@ -33,7 +33,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -147,18 +146,10 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
void cancel();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* currentTime() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void currentTime(CSSNumberish&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<AnimationTimeDelta> CurrentTimeInternal() const;
void setCurrentTime(const V8CSSNumberish* current_time,
ExceptionState& exception_state);
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setCurrentTime(CSSNumberish, ExceptionState& exception_state);
- void setCurrentTime(CSSNumberish);
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void SetCurrentTimeInternal(AnimationTimeDelta);
absl::optional<AnimationTimeDelta> UnlimitedCurrentTime() const;
@@ -214,23 +205,16 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
double playbackRate() const;
void setPlaybackRate(double, ExceptionState& = ASSERT_NO_EXCEPTION);
AnimationTimeline* timeline() { return timeline_; }
+ AnimationTimeline* timeline() const { return timeline_; }
virtual void setTimeline(AnimationTimeline* timeline);
Document* GetDocument() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* startTime() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void startTime(CSSNumberish&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<AnimationTimeDelta> StartTimeInternal() const {
return start_time_;
}
virtual void setStartTime(const V8CSSNumberish* start_time,
ExceptionState& exception_state);
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void setStartTime(CSSNumberish, ExceptionState&);
- void setStartTime(CSSNumberish);
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const AnimationEffect* effect() const { return content_.Get(); }
AnimationEffect* effect() { return content_.Get(); }
@@ -320,6 +304,15 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
base::TimeDelta ComputeCompositorTimeOffset() const;
+ // Updates |compositor_property_animations_have_no_effect_| and marks the
+ // animation as pending if it changes.
+ void MarkPendingIfCompositorPropertyAnimationChanges(
+ const PaintArtifactCompositor*);
+ bool CompositorPropertyAnimationsHaveNoEffectForTesting() const {
+ return compositor_property_animations_have_no_effect_;
+ }
+ bool AnimationHasNoEffect() const { return animation_has_no_effect_; }
+
protected:
DispatchEventResult DispatchEventInternal(Event&) override;
void AddedEventListener(const AtomicString& event_type,
@@ -354,6 +347,13 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
absl::optional<AnimationTimeDelta> CalculateCurrentTime() const;
TimelinePhase CalculateCurrentPhase() const;
+ V8CSSNumberish* ConvertTimeToCSSNumberish(AnimationTimeDelta) const;
+ // Failure to convert results in a thrown exception and returning false.
+ bool ConvertCSSNumberishToTime(const V8CSSNumberish* numberish,
+ absl::optional<AnimationTimeDelta>& time,
+ String variable_name,
+ ExceptionState& exception_state);
+
void BeginUpdatingState();
void EndUpdatingState();
@@ -486,12 +486,14 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
playback_rate(animation.EffectivePlaybackRate()),
effect_changed(false),
pending_action(animation.start_time_ ? kNone : kStart) {}
+ CompositorState(const CompositorState&) = delete;
+ CompositorState& operator=(const CompositorState&) = delete;
+
absl::optional<double> start_time;
absl::optional<double> hold_time;
double playback_rate;
bool effect_changed;
CompositorAction pending_action;
- DISALLOW_COPY_AND_ASSIGN(CompositorState);
};
enum CompositorPendingChange {
@@ -544,7 +546,15 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
base::TimeTicks last_display_lock_update_time_ = base::TimeTicks();
bool is_in_display_locked_subtree_ = false;
- FRIEND_TEST_ALL_PREFIXES(AnimationAnimationTestCompositeAfterPaint,
+ // True if we animate compositor properties but they would have no effect due
+ // to being optimized out on the compositor. Updated in |Animation::PreCommit|
+ // and |MarkPendingIfCompositorPropertyAnimationChanges|.
+ bool compositor_property_animations_have_no_effect_;
+ // True if the only reason for not running the animation on the compositor is
+ // that the animation would have no effect. Updated in |Animation::PreCommit|.
+ bool animation_has_no_effect_;
+
+ FRIEND_TEST_ALL_PREFIXES(AnimationAnimationTestCompositing,
NoCompositeWithoutCompositedElementId);
FRIEND_TEST_ALL_PREFIXES(AnimationAnimationTestNoCompositing,
PendingActivityWithFinishedEventListener);
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_clock.h b/chromium/third_party/blink/renderer/core/animation/animation_clock.h
index 8f10d8b6852..abf6727bcb9 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_clock.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_clock.h
@@ -33,7 +33,6 @@
#include <limits>
-#include "base/macros.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -53,6 +52,8 @@ class CORE_EXPORT AnimationClock {
clock_(base::DefaultTickClock::GetInstance()),
task_for_which_time_was_calculated_(
std::numeric_limits<unsigned>::max()) {}
+ AnimationClock(const AnimationClock&) = delete;
+ AnimationClock& operator=(const AnimationClock&) = delete;
void UpdateTime(base::TimeTicks time);
base::TimeTicks CurrentTime();
@@ -97,8 +98,6 @@ class CORE_EXPORT AnimationClock {
// See |NotifyTaskStart| documentation for these members.
unsigned task_for_which_time_was_calculated_;
static unsigned currently_running_task_;
-
- DISALLOW_COPY_AND_ASSIGN(AnimationClock);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_effect.cc b/chromium/third_party/blink/renderer/core/animation/animation_effect.cc
index 47ad163d059..7d0acea85ec 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_computed_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
@@ -49,6 +50,92 @@ AnimationEffect::AnimationEffect(const Timing& timing,
needs_update_(true),
cancel_time_(AnimationTimeDelta()) {
timing_.AssertValid();
+ InvalidateNormalizedTiming();
+}
+
+// Scales all timing values so that end_time == timeline_duration
+void AnimationEffect::EnsureNormalizedTiming() const {
+ // Only run the normalization process if needed
+ if (normalized_)
+ return;
+
+ normalized_ = Timing::NormalizedTiming();
+ if (GetAnimation() && GetAnimation()->timeline() &&
+ GetAnimation()->timeline()->IsProgressBasedTimeline()) {
+ // Normalize timings for progress based timelines
+ normalized_->timeline_duration = GetAnimation()->timeline()->GetDuration();
+ DCHECK(normalized_->timeline_duration);
+
+ if (timing_.iteration_duration) {
+ // Scaling up iteration_duration allows animation effect to be able to
+ // handle values produced by progress based timelines. At this point it
+ // can be assumed that EndTimeInternal() will give us a good value.
+
+ const AnimationTimeDelta active_duration = MultiplyZeroAlwaysGivesZero(
+ timing_.iteration_duration.value(), timing_.iteration_count);
+ DCHECK_GE(active_duration, AnimationTimeDelta());
+
+ // Per the spec, the end time has a lower bound of 0.0:
+ // https://drafts.csswg.org/web-animations-1/#end-time
+ const AnimationTimeDelta end_time =
+ std::max(timing_.start_delay + active_duration + timing_.end_delay,
+ AnimationTimeDelta());
+
+ // Exceptions should have already been thrown when trying to input values
+ // that would result in an infinite end_time for progress based timelines.
+ DCHECK(!end_time.is_inf());
+
+ // Negative start_delay that is >= iteration_duration or iteration_count
+ // of 0 will cause end_time to be 0 or negative.
+ if (end_time.is_zero()) {
+ // end_time of zero causes division by zero so we handle it here
+ normalized_->start_delay = AnimationTimeDelta();
+ normalized_->end_delay = AnimationTimeDelta();
+ normalized_->iteration_duration = AnimationTimeDelta();
+ } else {
+ // convert to percentages then multiply by the timeline_duration
+ normalized_->start_delay = (timing_.start_delay / end_time) *
+ normalized_->timeline_duration.value();
+
+ normalized_->end_delay = (timing_.end_delay / end_time) *
+ normalized_->timeline_duration.value();
+
+ normalized_->iteration_duration =
+ (timing_.iteration_duration.value() / end_time) *
+ normalized_->timeline_duration.value();
+ }
+ } else {
+ // Handle iteration_duration value of "auto"
+
+ // TODO(crbug.com/1216527)
+ // this will change to support percentage delays and possibly mixed
+ // delays.
+ DCHECK(normalized_->start_delay.is_zero() &&
+ normalized_->end_delay.is_zero());
+
+ normalized_->iteration_duration =
+ GetAnimation()->timeline()->CalculateIntrinsicIterationDuration(
+ timing_);
+ // TODO: add support for progress based timelines and "auto" duration
+ // effects
+ }
+ } else {
+ // Populates normalized values for use with time based timelines.
+ normalized_->start_delay = timing_.start_delay;
+ normalized_->end_delay = timing_.end_delay;
+ normalized_->iteration_duration =
+ timing_.iteration_duration.value_or(AnimationTimeDelta());
+ }
+
+ normalized_->active_duration = MultiplyZeroAlwaysGivesZero(
+ normalized_->iteration_duration, timing_.iteration_count);
+
+ // Per the spec, the end time has a lower bound of 0.0:
+ // https://drafts.csswg.org/web-animations-1/#end-time
+ normalized_->end_time =
+ std::max(normalized_->start_delay + normalized_->active_duration +
+ normalized_->end_delay,
+ AnimationTimeDelta());
}
void AnimationEffect::UpdateSpecifiedTiming(const Timing& timing) {
@@ -81,6 +168,8 @@ void AnimationEffect::UpdateSpecifiedTiming(const Timing& timing) {
if (!timing_.HasTimingOverride(Timing::kOverrideTimingFunction))
timing_.timing_function = timing.timing_function;
}
+
+ InvalidateNormalizedTiming();
InvalidateAndNotifyOwner();
}
@@ -95,16 +184,61 @@ EffectTiming* AnimationEffect::getTiming() const {
}
ComputedEffectTiming* AnimationEffect::getComputedTiming() const {
- return SpecifiedTiming().getComputedTiming(EnsureCalculated(),
- IsA<KeyframeEffect>(this));
+ return SpecifiedTiming().getComputedTiming(
+ EnsureCalculated(), NormalizedTiming(), IsA<KeyframeEffect>(this));
}
void AnimationEffect::updateTiming(OptionalEffectTiming* optional_timing,
ExceptionState& exception_state) {
+ if (GetAnimation() && GetAnimation()->timeline() &&
+ GetAnimation()->timeline()->IsProgressBasedTimeline()) {
+ if (optional_timing->hasDuration()) {
+ if (optional_timing->duration()->IsUnrestrictedDouble()) {
+ double duration =
+ optional_timing->duration()->GetAsUnrestrictedDouble();
+ if (duration == std::numeric_limits<double>::infinity()) {
+ exception_state.ThrowTypeError(
+ "Effect duration cannot be Infinity when used with Scroll "
+ "Timelines");
+ return;
+ }
+ } else if (optional_timing->duration()->GetAsString() == "auto") {
+ // TODO(crbug.com/1216527)
+ // Eventually we hope to be able to be more flexible with
+ // iteration_duration "auto" and its interaction with start_delay and
+ // end_delay. For now we will throw an exception if either delay is set.
+ // Once delays are changed to CSSNumberish, we will need to adjust logic
+ // here to allow for percentage values but not time values.
+
+ // If either delay or end_delay are non-zero, we can't handle "auto"
+ if (!SpecifiedTiming().start_delay.is_zero() ||
+ !SpecifiedTiming().end_delay.is_zero()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Effect duration \"auto\" with delays is not yet implemented "
+ "when used with Scroll Timelines");
+ return;
+ }
+ }
+ }
+
+ if (optional_timing->hasIterations() &&
+ optional_timing->iterations() ==
+ std::numeric_limits<double>::infinity()) {
+ // iteration count of infinity makes no sense for scroll timelines
+ exception_state.ThrowTypeError(
+ "Effect iterations cannot be Infinity when used with Scroll "
+ "Timelines");
+ return;
+ }
+ }
+
// TODO(crbug.com/827178): Determine whether we should pass a Document in here
// (and which) to resolve the CSS secure/insecure context against.
if (!TimingInput::Update(timing_, optional_timing, nullptr, exception_state))
return;
+
+ InvalidateNormalizedTiming();
InvalidateAndNotifyOwner();
}
@@ -154,8 +288,8 @@ void AnimationEffect::UpdateInheritedTime(
if (needs_update) {
Timing::CalculatedTiming calculated = SpecifiedTiming().CalculateTimings(
- inherited_time, timeline_phase, direction, IsA<KeyframeEffect>(this),
- playback_rate);
+ inherited_time, timeline_phase, NormalizedTiming(), direction,
+ IsA<KeyframeEffect>(this), playback_rate);
const bool was_canceled = calculated.phase != calculated_.phase &&
calculated.phase == Timing::kPhaseNone;
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 5763f0cdab8..b04f02e3c98 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.h
@@ -104,6 +104,13 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable {
}
const Timing& SpecifiedTiming() const { return timing_; }
+
+ const Timing::NormalizedTiming& NormalizedTiming() const {
+ EnsureNormalizedTiming();
+ return normalized_.value();
+ }
+ void InvalidateNormalizedTiming() { normalized_.reset(); }
+
void UpdateSpecifiedTiming(const Timing&);
void SetIgnoreCssTimingProperties();
@@ -120,7 +127,10 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable {
}
// Attach/Detach the AnimationEffect from its owning animation.
- virtual void Attach(AnimationEffectOwner* owner) { owner_ = owner; }
+ virtual void Attach(AnimationEffectOwner* owner) {
+ owner_ = owner;
+ InvalidateNormalizedTiming();
+ }
virtual void Detach() {
DCHECK(owner_);
owner_ = nullptr;
@@ -169,11 +179,13 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable {
Member<EventDelegate> event_delegate_;
mutable Timing::CalculatedTiming calculated_;
+ mutable absl::optional<Timing::NormalizedTiming> normalized_;
mutable bool needs_update_;
mutable absl::optional<AnimationTimeDelta> last_update_time_;
mutable absl::optional<Timing::Phase> last_update_phase_;
AnimationTimeDelta cancel_time_;
const Timing::CalculatedTiming& EnsureCalculated() const;
+ void EnsureNormalizedTiming() const;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_effect_test.cc b/chromium/third_party/blink/renderer/core/animation/animation_effect_test.cc
index 7628a5a1315..dd84e04a4e0 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_effect_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_effect_test.cc
@@ -34,6 +34,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_computed_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation_effect_owner.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -139,7 +140,7 @@ TEST(AnimationAnimationEffectTest, Sanity) {
EXPECT_TRUE(animation_node->IsInEffect());
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(2),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(0, animation_node->Progress());
animation_node->UpdateInheritedTime(1);
@@ -150,7 +151,7 @@ TEST(AnimationAnimationEffectTest, Sanity) {
EXPECT_TRUE(animation_node->IsInEffect());
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(2),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(0.5, animation_node->Progress());
animation_node->UpdateInheritedTime(2);
@@ -161,7 +162,7 @@ TEST(AnimationAnimationEffectTest, Sanity) {
EXPECT_TRUE(animation_node->IsInEffect());
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(2),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(1, animation_node->Progress());
animation_node->UpdateInheritedTime(3);
@@ -172,7 +173,7 @@ TEST(AnimationAnimationEffectTest, Sanity) {
EXPECT_TRUE(animation_node->IsInEffect());
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(2),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(1, animation_node->Progress());
}
@@ -253,13 +254,13 @@ TEST(AnimationAnimationEffectTest, ZeroIteration) {
animation_node->UpdateInheritedTime(-1);
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(0, animation_node->Progress());
}
@@ -276,7 +277,7 @@ TEST(AnimationAnimationEffectTest, InfiniteIteration) {
EXPECT_FALSE(animation_node->Progress());
EXPECT_EQ(AnimationTimeDelta::Max(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
animation_node->UpdateInheritedTime(0);
EXPECT_EQ(0, animation_node->CurrentIteration());
@@ -383,7 +384,7 @@ TEST(AnimationAnimationEffectTest, ZeroDurationSanity) {
EXPECT_TRUE(animation_node->IsInEffect());
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(1, animation_node->Progress());
animation_node->UpdateInheritedTime(1);
@@ -394,7 +395,7 @@ TEST(AnimationAnimationEffectTest, ZeroDurationSanity) {
EXPECT_TRUE(animation_node->IsInEffect());
EXPECT_EQ(0, animation_node->CurrentIteration());
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(1, animation_node->Progress());
}
@@ -486,13 +487,13 @@ TEST(AnimationAnimationEffectTest, ZeroDurationInfiniteIteration) {
animation_node->UpdateInheritedTime(-1);
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(std::numeric_limits<double>::infinity(),
animation_node->CurrentIteration());
EXPECT_EQ(1, animation_node->Progress());
@@ -586,7 +587,7 @@ TEST(AnimationAnimationEffectTest, InfiniteDurationSanity) {
animation_node->UpdateInheritedTime(0);
EXPECT_EQ(AnimationTimeDelta::Max(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(Timing::kPhaseActive, animation_node->GetPhase());
EXPECT_TRUE(animation_node->IsInPlay());
EXPECT_TRUE(animation_node->IsCurrent());
@@ -597,7 +598,7 @@ TEST(AnimationAnimationEffectTest, InfiniteDurationSanity) {
animation_node->UpdateInheritedTime(1);
EXPECT_EQ(AnimationTimeDelta::Max(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(Timing::kPhaseActive, animation_node->GetPhase());
EXPECT_TRUE(animation_node->IsInPlay());
EXPECT_TRUE(animation_node->IsCurrent());
@@ -616,7 +617,7 @@ TEST(AnimationAnimationEffectTest, InfiniteDurationZeroIterations) {
animation_node->UpdateInheritedTime(0);
EXPECT_EQ(AnimationTimeDelta(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(Timing::kPhaseAfter, animation_node->GetPhase());
EXPECT_FALSE(animation_node->IsInPlay());
EXPECT_FALSE(animation_node->IsCurrent());
@@ -644,7 +645,7 @@ TEST(AnimationAnimationEffectTest, InfiniteDurationInfiniteIterations) {
animation_node->UpdateInheritedTime(0);
EXPECT_EQ(AnimationTimeDelta::Max(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(Timing::kPhaseActive, animation_node->GetPhase());
EXPECT_TRUE(animation_node->IsInPlay());
EXPECT_TRUE(animation_node->IsCurrent());
@@ -655,7 +656,7 @@ TEST(AnimationAnimationEffectTest, InfiniteDurationInfiniteIterations) {
animation_node->UpdateInheritedTime(1);
EXPECT_EQ(AnimationTimeDelta::Max(),
- animation_node->SpecifiedTiming().ActiveDuration());
+ animation_node->NormalizedTiming().active_duration);
EXPECT_EQ(Timing::kPhaseActive, animation_node->GetPhase());
EXPECT_TRUE(animation_node->IsInPlay());
EXPECT_TRUE(animation_node->IsCurrent());
@@ -672,7 +673,7 @@ TEST(AnimationAnimationEffectTest, EndTime) {
timing.iteration_count = 2;
auto* animation_node = MakeGarbageCollected<TestAnimationEffect>(timing);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(11),
- animation_node->SpecifiedTiming().EndTimeInternal());
+ animation_node->NormalizedTiming().end_time);
}
TEST(AnimationAnimationEffectTest, Events) {
@@ -790,12 +791,12 @@ TEST(AnimationAnimationEffectTest, UpdateTiming) {
effect->updateTiming(effect_timing);
EXPECT_EQ("ease-in-out", effect->getTiming()->easing());
- EXPECT_EQ("auto", effect->getTiming()->duration().GetAsString());
+ EXPECT_EQ("auto", effect->getTiming()->duration()->GetAsString());
effect_timing = OptionalEffectTiming::Create();
effect_timing->setDuration(
- UnrestrictedDoubleOrString::FromUnrestrictedDouble(2.5));
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(2.5));
effect->updateTiming(effect_timing);
- EXPECT_EQ(2.5, effect->getTiming()->duration().GetAsUnrestrictedDouble());
+ EXPECT_EQ(2.5, effect->getTiming()->duration()->GetAsUnrestrictedDouble());
}
TEST(AnimationAnimationEffectTest, UpdateTimingThrowsWhenExpected) {
@@ -827,14 +828,15 @@ TEST(AnimationAnimationEffectTest, UpdateTimingThrowsWhenExpected) {
exception_state.ClearException();
effect_timing = OptionalEffectTiming::Create();
effect_timing->setDuration(
- UnrestrictedDoubleOrString::FromUnrestrictedDouble(-100));
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(-100));
effect->updateTiming(effect_timing, exception_state);
EXPECT_TRUE(exception_state.HadException());
exception_state.ClearException();
effect_timing = OptionalEffectTiming::Create();
- effect_timing->setDuration(UnrestrictedDoubleOrString::FromUnrestrictedDouble(
- std::numeric_limits<double>::quiet_NaN()));
+ effect_timing->setDuration(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
+ std::numeric_limits<double>::quiet_NaN()));
effect->updateTiming(effect_timing, exception_state);
EXPECT_TRUE(exception_state.HadException());
@@ -897,7 +899,7 @@ TEST(AnimationAnimationEffectTest, UpdateTimingNoChange) {
effect_timing = OptionalEffectTiming::Create();
effect_timing->setIterations(3);
effect_timing->setDuration(
- UnrestrictedDoubleOrString::FromUnrestrictedDouble(2000));
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(2000));
effect_timing->setDirection("alternate-reverse");
effect->updateTiming(effect_timing);
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 86a7a8b13d0..8d713ffc8d9 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,7 @@
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
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 900360888d6..8acba7e3622 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test.cc
@@ -33,12 +33,15 @@
#include <memory>
#include "base/bits.h"
+#include "base/macros.h"
+#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_double.h"
#include "third_party/blink/renderer/core/animation/css_number_interpolation_type.h"
@@ -49,6 +52,7 @@
#include "third_party/blink/renderer/core/animation/pending_animations.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/timing.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -64,6 +68,7 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/heap.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/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -73,7 +78,8 @@ void ExpectRelativeErrorWithinEpsilon(double expected, double observed) {
EXPECT_NEAR(1.0, observed / expected, std::numeric_limits<double>::epsilon());
}
-class AnimationAnimationTestNoCompositing : public RenderingTest {
+class AnimationAnimationTestNoCompositing : public PaintTestConfigurations,
+ public RenderingTest {
public:
AnimationAnimationTestNoCompositing()
: RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
@@ -90,12 +96,8 @@ class AnimationAnimationTestNoCompositing : public RenderingTest {
timeline = GetDocument().Timeline();
timeline->ResetForTesting();
animation = timeline->Play(nullptr);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setEffect(MakeAnimation());
}
@@ -137,7 +139,9 @@ class AnimationAnimationTestNoCompositing : public RenderingTest {
RunDocumentLifecycle();
- SetBodyInnerHTML("<div id='target'></div>");
+ SetBodyInnerHTML(R"HTML(
+ <div id='target' style='width: 1px; height: 1px; background: green'></div>
+ )HTML");
MakeCompositedAnimation();
}
@@ -221,43 +225,19 @@ class AnimationAnimationTestNoCompositing : public RenderingTest {
}
bool StartTimeIsSet(Animation* animation) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return animation->startTime();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish start_time;
- animation->startTime(start_time);
- return !start_time.IsNull();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
bool CurrentTimeIsSet(Animation* animation) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return animation->currentTime();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish current_time;
- animation->currentTime(current_time);
- return !current_time.IsNull();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
double GetStartTimeMs(Animation* animation) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return animation->startTime()->GetAsDouble();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish start_time;
- animation->startTime(start_time);
- return start_time.GetAsDouble();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
double GetCurrentTimeMs(Animation* animation) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return animation->currentTime()->GetAsDouble();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish current_time;
- animation->currentTime(current_time);
- return current_time.GetAsDouble();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
#define EXPECT_TIME(expected, observed) \
@@ -308,17 +288,10 @@ class AnimationAnimationTestCompositing
}
};
-class AnimationAnimationTestCompositeAfterPaint
- : public AnimationAnimationTestNoCompositing {
- void SetUp() override {
- EnableCompositing();
- AnimationAnimationTestNoCompositing::SetUp();
- }
-
- ScopedCompositeAfterPaintForTest enable_cap{true};
-};
+INSTANTIATE_PAINT_TEST_SUITE_P(AnimationAnimationTestNoCompositing);
+INSTANTIATE_PAINT_TEST_SUITE_P(AnimationAnimationTestCompositing);
-TEST_F(AnimationAnimationTestNoCompositing, InitialState) {
+TEST_P(AnimationAnimationTestNoCompositing, InitialState) {
SetUpWithoutStartingTimeline();
animation = timeline->Play(nullptr);
EXPECT_TIME(0, GetCurrentTimeMs(animation));
@@ -337,7 +310,7 @@ TEST_F(AnimationAnimationTestNoCompositing, InitialState) {
EXPECT_TIME(0, GetStartTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, CurrentTimeDoesNotSetOutdated) {
+TEST_P(AnimationAnimationTestNoCompositing, CurrentTimeDoesNotSetOutdated) {
EXPECT_FALSE(animation->Outdated());
EXPECT_TIME(0, GetCurrentTimeMs(animation));
EXPECT_FALSE(animation->Outdated());
@@ -350,14 +323,10 @@ TEST_F(AnimationAnimationTestNoCompositing, CurrentTimeDoesNotSetOutdated) {
EXPECT_FALSE(animation->Outdated());
}
-TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTime) {
+TEST_P(AnimationAnimationTestNoCompositing, SetCurrentTime) {
EXPECT_EQ("running", animation->playState());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("running", animation->playState());
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
@@ -366,25 +335,17 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTime) {
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeNegative) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, SetCurrentTimeNegative) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("running", animation->playState());
EXPECT_TIME(-10000, GetCurrentTimeMs(animation));
SimulateFrame(20000);
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
animation->setPlaybackRate(-2);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
// A seek can set current time outside the range [0, EffectEnd()].
EXPECT_TIME(-10000, GetCurrentTimeMs(animation));
@@ -396,7 +357,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeNegative) {
EXPECT_TIME(-10000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
SetCurrentTimeNegativeWithoutSimultaneousPlaybackRateChange) {
SimulateFrame(20000);
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
@@ -412,22 +373,14 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
EXPECT_EQ("running", animation->playState());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
}
-TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
EXPECT_TIME(50000, GetCurrentTimeMs(animation));
@@ -437,12 +390,8 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
// Reversing the play direction changes the play state from finished to
// running.
animation->setPlaybackRate(-2);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("running", animation->playState());
EXPECT_TIME(50000, GetCurrentTimeMs(animation));
SimulateAwaitReady();
@@ -452,35 +401,23 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestCompositing, SetCurrentTimeMax) {
+TEST_P(AnimationAnimationTestCompositing, SetCurrentTimeMax) {
ResetWithCompositedAnimation();
EXPECT_EQ(CompositorAnimations::kNoFailure,
animation->CheckCanStartAnimationOnCompositor(nullptr));
double limit = std::numeric_limits<double>::max();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(limit),
ASSERT_NO_EXCEPTION);
V8CSSNumberish* current_time = animation->currentTime();
ExpectRelativeErrorWithinEpsilon(limit, current_time->GetAsDouble());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(limit));
- CSSNumberish current_time;
- animation->currentTime(current_time);
- ExpectRelativeErrorWithinEpsilon(limit, current_time.GetAsDouble());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TRUE(animation->CheckCanStartAnimationOnCompositor(nullptr) &
CompositorAnimations::kEffectHasUnsupportedTimingParameters);
SimulateFrame(100000);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
current_time = animation->currentTime();
ExpectRelativeErrorWithinEpsilon(limit, current_time->GetAsDouble());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->currentTime(current_time);
- ExpectRelativeErrorWithinEpsilon(limit, current_time.GetAsDouble());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
-TEST_F(AnimationAnimationTestCompositing, SetCurrentTimeAboveMaxTimeDelta) {
+TEST_P(AnimationAnimationTestCompositing, SetCurrentTimeAboveMaxTimeDelta) {
// Similar to the SetCurrentTimeMax test. The limit is much less, but still
// too large to be expressed as a 64-bit int and thus not able to run on the
// compositor.
@@ -488,27 +425,17 @@ TEST_F(AnimationAnimationTestCompositing, SetCurrentTimeAboveMaxTimeDelta) {
EXPECT_EQ(CompositorAnimations::kNoFailure,
animation->CheckCanStartAnimationOnCompositor(nullptr));
double limit = 1e30;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(limit),
ASSERT_NO_EXCEPTION);
ignore_result(animation->currentTime());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(limit));
- CSSNumberish current_time;
- animation->currentTime(current_time);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TRUE(animation->CheckCanStartAnimationOnCompositor(nullptr) &
CompositorAnimations::kEffectHasUnsupportedTimingParameters);
}
-TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeSetsStartTime) {
+TEST_P(AnimationAnimationTestNoCompositing, SetCurrentTimeSetsStartTime) {
EXPECT_TIME(0, GetStartTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(1000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(1000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIME(-1000, GetStartTimeMs(animation));
SimulateFrame(1000);
@@ -516,17 +443,13 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeSetsStartTime) {
EXPECT_TIME(2000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetStartTime) {
+TEST_P(AnimationAnimationTestNoCompositing, SetStartTime) {
SimulateFrame(20000);
EXPECT_EQ("running", animation->playState());
EXPECT_TIME(0, GetStartTimeMs(animation));
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("running", animation->playState());
EXPECT_TIME(10000, GetStartTimeMs(animation));
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
@@ -534,73 +457,49 @@ TEST_F(AnimationAnimationTestNoCompositing, SetStartTime) {
SimulateFrame(30000);
EXPECT_TIME(10000, GetStartTimeMs(animation));
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(-20000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(-20000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
}
-TEST_F(AnimationAnimationTestNoCompositing, SetStartTimeLimitsAnimation) {
+TEST_P(AnimationAnimationTestNoCompositing, SetStartTimeLimitsAnimation) {
// Setting the start time is a seek operation, which is not constrained by the
// normal limits on the animation.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(-50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(-50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
EXPECT_TRUE(animation->Limited());
EXPECT_TIME(50000, GetCurrentTimeMs(animation));
animation->setPlaybackRate(-1);
EXPECT_EQ("running", animation->playState());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(-100000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(-100000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
EXPECT_TIME(-100000, GetCurrentTimeMs(animation));
EXPECT_TRUE(animation->Limited());
}
-TEST_F(AnimationAnimationTestNoCompositing, SetStartTimeOnLimitedAnimation) {
+TEST_P(AnimationAnimationTestNoCompositing, SetStartTimeOnLimitedAnimation) {
// The setStartTime method is a seek and thus not constrained by the normal
// limits on the animation.
SimulateFrame(30000);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
EXPECT_TIME(40000, GetCurrentTimeMs(animation));
EXPECT_TRUE(animation->Limited());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIME(50000, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(-40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(-40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIME(70000, GetCurrentTimeMs(animation));
EXPECT_EQ("finished", animation->playState());
EXPECT_TRUE(animation->Limited());
}
-TEST_F(AnimationAnimationTestNoCompositing, StartTimePauseFinish) {
+TEST_P(AnimationAnimationTestNoCompositing, StartTimePauseFinish) {
NonThrowableExceptionState exception_state;
animation->pause();
EXPECT_EQ("paused", animation->playState());
@@ -614,7 +513,7 @@ TEST_F(AnimationAnimationTestNoCompositing, StartTimePauseFinish) {
EXPECT_TIME(-30000, GetStartTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, FinishWhenPaused) {
+TEST_P(AnimationAnimationTestNoCompositing, FinishWhenPaused) {
NonThrowableExceptionState exception_state;
animation->pause();
EXPECT_EQ("paused", animation->playState());
@@ -627,7 +526,7 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishWhenPaused) {
EXPECT_EQ("finished", animation->playState());
}
-TEST_F(AnimationAnimationTestNoCompositing, StartTimeFinishPause) {
+TEST_P(AnimationAnimationTestNoCompositing, StartTimeFinishPause) {
NonThrowableExceptionState exception_state;
animation->finish(exception_state);
EXPECT_TIME(-30000, GetStartTimeMs(animation));
@@ -639,7 +538,7 @@ TEST_F(AnimationAnimationTestNoCompositing, StartTimeFinishPause) {
EXPECT_FALSE(StartTimeIsSet(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, StartTimeWithZeroPlaybackRate) {
+TEST_P(AnimationAnimationTestNoCompositing, StartTimeWithZeroPlaybackRate) {
animation->setPlaybackRate(0);
EXPECT_EQ("running", animation->playState());
SimulateAwaitReady();
@@ -650,7 +549,7 @@ TEST_F(AnimationAnimationTestNoCompositing, StartTimeWithZeroPlaybackRate) {
EXPECT_TIME(0, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, PausePlay) {
+TEST_P(AnimationAnimationTestNoCompositing, PausePlay) {
// Pause the animation at the 10s mark.
SimulateFrame(10000);
animation->pause();
@@ -674,24 +573,16 @@ TEST_F(AnimationAnimationTestNoCompositing, PausePlay) {
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
+TEST_P(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
// Auto-replay when starting from limit.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(30000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(30000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->play();
EXPECT_TIME(0, GetCurrentTimeMs(animation));
// Auto-replay when starting past the upper bound.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->play();
EXPECT_TIME(0, GetCurrentTimeMs(animation));
EXPECT_EQ("running", animation->playState());
@@ -701,12 +592,8 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
// from a negative value of current time.
SimulateFrame(10000);
EXPECT_FALSE(animation->pending());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("running", animation->playState());
EXPECT_FALSE(animation->pending());
animation->play();
@@ -718,19 +605,15 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
EXPECT_FALSE(animation->pending());
}
-TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
+TEST_P(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
// Snap to end when playing a reversed animation from the start.
animation->setPlaybackRate(-1);
animation->play();
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
// Snap to end if playing a reversed animation starting past the upper limit.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
animation->play();
@@ -743,12 +626,8 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
// Snap to the end if playing a reversed animation starting with a negative
// value for current time.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->play();
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
EXPECT_EQ("running", animation->playState());
@@ -759,7 +638,7 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
EXPECT_FALSE(animation->pending());
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
PlayWithPlaybackRateZeroDoesNotSeek) {
// When playback rate is zero, any value set for the current time effectively
// becomes the hold time.
@@ -767,26 +646,18 @@ TEST_F(AnimationAnimationTestNoCompositing,
animation->play();
EXPECT_TIME(0, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->play();
EXPECT_TIME(40000, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->play();
EXPECT_TIME(-10000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
PlayAfterPauseWithPlaybackRateZeroUpdatesPlayState) {
animation->pause();
animation->setPlaybackRate(0);
@@ -798,13 +669,9 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->pending());
}
-TEST_F(AnimationAnimationTestNoCompositing, Reverse) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, Reverse) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->pause();
animation->reverse();
EXPECT_EQ("running", animation->playState());
@@ -819,14 +686,10 @@ TEST_F(AnimationAnimationTestNoCompositing, Reverse) {
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
ReverseHoldsCurrentTimeWithPlaybackRateZero) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(0);
animation->pause();
animation->reverse();
@@ -839,55 +702,39 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, ReverseSeeksToStart) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, ReverseSeeksToStart) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(-1);
animation->reverse();
EXPECT_TIME(0, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, ReverseSeeksToEnd) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, ReverseSeeksToEnd) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->reverse();
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, ReverseBeyondLimit) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, ReverseBeyondLimit) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(-1);
animation->reverse();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_TIME(0, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->reverse();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, Finish) {
+TEST_P(AnimationAnimationTestNoCompositing, Finish) {
NonThrowableExceptionState exception_state;
animation->finish(exception_state);
// Finished snaps to the end of the animation.
@@ -903,50 +750,38 @@ TEST_F(AnimationAnimationTestNoCompositing, Finish) {
EXPECT_FALSE(animation->pending());
}
-TEST_F(AnimationAnimationTestNoCompositing, FinishAfterEffectEnd) {
+TEST_P(AnimationAnimationTestNoCompositing, FinishAfterEffectEnd) {
NonThrowableExceptionState exception_state;
// OK to set current time out of bounds.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->finish(exception_state);
// The finish method triggers a snap to the upper boundary.
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, FinishBeforeStart) {
+TEST_P(AnimationAnimationTestNoCompositing, FinishBeforeStart) {
NonThrowableExceptionState exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(-1);
animation->finish(exception_state);
EXPECT_TIME(0, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
FinishDoesNothingWithPlaybackRateZero) {
// Cannot finish an animation that has a playback rate of zero.
DummyExceptionStateForTesting exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(0);
animation->finish(exception_state);
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
EXPECT_TRUE(exception_state.HadException());
}
-TEST_F(AnimationAnimationTestNoCompositing, FinishRaisesException) {
+TEST_P(AnimationAnimationTestNoCompositing, FinishRaisesException) {
// Cannot finish an animation that has an infinite iteration-count and a
// non-zero iteration-duration.
Timing timing;
@@ -954,12 +789,8 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishRaisesException) {
timing.iteration_count = std::numeric_limits<double>::infinity();
animation->setEffect(MakeGarbageCollected<KeyframeEffect>(
nullptr, MakeEmptyEffectModel(), timing));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(10000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(10000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DummyExceptionStateForTesting exception_state;
animation->finish(exception_state);
@@ -969,7 +800,7 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishRaisesException) {
exception_state.CodeAs<DOMExceptionCode>());
}
-TEST_F(AnimationAnimationTestNoCompositing, LimitingAtEffectEnd) {
+TEST_P(AnimationAnimationTestNoCompositing, LimitingAtEffectEnd) {
SimulateFrame(30000);
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
EXPECT_TRUE(animation->Limited());
@@ -980,7 +811,7 @@ TEST_F(AnimationAnimationTestNoCompositing, LimitingAtEffectEnd) {
EXPECT_FALSE(animation->Paused());
}
-TEST_F(AnimationAnimationTestNoCompositing, LimitingAtStart) {
+TEST_P(AnimationAnimationTestNoCompositing, LimitingAtStart) {
SimulateFrame(30000);
animation->setPlaybackRate(-2);
SimulateAwaitReady();
@@ -994,14 +825,14 @@ TEST_F(AnimationAnimationTestNoCompositing, LimitingAtStart) {
EXPECT_FALSE(animation->Paused());
}
-TEST_F(AnimationAnimationTestNoCompositing, LimitingWithNoEffect) {
+TEST_P(AnimationAnimationTestNoCompositing, LimitingWithNoEffect) {
animation->setEffect(nullptr);
EXPECT_TRUE(animation->Limited());
SimulateFrame(30000);
EXPECT_TIME(0, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRate) {
+TEST_P(AnimationAnimationTestNoCompositing, SetPlaybackRate) {
animation->setPlaybackRate(2);
SimulateAwaitReady();
EXPECT_EQ(2, animation->playbackRate());
@@ -1011,7 +842,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRate) {
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateWhilePaused) {
+TEST_P(AnimationAnimationTestNoCompositing, SetPlaybackRateWhilePaused) {
SimulateFrame(10000);
animation->pause();
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
@@ -1029,7 +860,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateWhilePaused) {
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateWhileLimited) {
+TEST_P(AnimationAnimationTestNoCompositing, SetPlaybackRateWhileLimited) {
// Animation plays until it hits the upper bound.
SimulateFrame(40000);
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
@@ -1048,23 +879,19 @@ TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateWhileLimited) {
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateZero) {
+TEST_P(AnimationAnimationTestNoCompositing, SetPlaybackRateZero) {
SimulateFrame(10000);
animation->setPlaybackRate(0);
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
SimulateFrame(20000);
EXPECT_TIME(10000, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(20000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(20000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateMax) {
+TEST_P(AnimationAnimationTestNoCompositing, SetPlaybackRateMax) {
animation->setPlaybackRate(std::numeric_limits<double>::max());
EXPECT_EQ(std::numeric_limits<double>::max(), animation->playbackRate());
EXPECT_TIME(0, GetCurrentTimeMs(animation));
@@ -1074,7 +901,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateMax) {
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRate) {
+TEST_P(AnimationAnimationTestNoCompositing, UpdatePlaybackRate) {
animation->updatePlaybackRate(2);
EXPECT_EQ(1, animation->playbackRate());
SimulateAwaitReady();
@@ -1085,7 +912,7 @@ TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRate) {
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhilePaused) {
+TEST_P(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhilePaused) {
animation->pause();
// Pending playback rate on pending-paused animation is picked up after async
@@ -1104,7 +931,7 @@ TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhilePaused) {
EXPECT_EQ(3, animation->playbackRate());
}
-TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileLimited) {
+TEST_P(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileLimited) {
NonThrowableExceptionState exception_state;
animation->finish(exception_state);
EXPECT_TIME(30000, GetCurrentTimeMs(animation));
@@ -1118,7 +945,7 @@ TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileLimited) {
EXPECT_EQ(2, animation->playbackRate());
}
-TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileRunning) {
+TEST_P(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileRunning) {
animation->play();
SimulateFrame(1000);
animation->updatePlaybackRate(2);
@@ -1132,25 +959,17 @@ TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileRunning) {
EXPECT_EQ(2, animation->playbackRate());
}
-TEST_F(AnimationAnimationTestNoCompositing, SetEffect) {
+TEST_P(AnimationAnimationTestNoCompositing, SetEffect) {
animation = timeline->Play(nullptr);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AnimationEffect* effect1 = MakeAnimation();
AnimationEffect* effect2 = MakeAnimation();
animation->setEffect(effect1);
EXPECT_EQ(effect1, animation->effect());
EXPECT_TIME(0, GetCurrentTimeMs(animation));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(15000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(15000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setEffect(effect2);
EXPECT_TIME(15000, GetCurrentTimeMs(animation));
EXPECT_EQ(nullptr, effect1->GetAnimationForTesting());
@@ -1158,13 +977,9 @@ TEST_F(AnimationAnimationTestNoCompositing, SetEffect) {
EXPECT_EQ(effect2, animation->effect());
}
-TEST_F(AnimationAnimationTestNoCompositing, SetEffectLimitsAnimation) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, SetEffectLimitsAnimation) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(20000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(20000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setEffect(MakeAnimation(10));
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
EXPECT_TRUE(animation->Limited());
@@ -1172,13 +987,9 @@ TEST_F(AnimationAnimationTestNoCompositing, SetEffectLimitsAnimation) {
EXPECT_TIME(20000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, SetEffectUnlimitsAnimation) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+TEST_P(AnimationAnimationTestNoCompositing, SetEffectUnlimitsAnimation) {
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(40000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(40000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setEffect(MakeAnimation(60));
EXPECT_FALSE(animation->Limited());
EXPECT_TIME(40000, GetCurrentTimeMs(animation));
@@ -1186,7 +997,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetEffectUnlimitsAnimation) {
EXPECT_TIME(50000, GetCurrentTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, EmptyAnimationsDontUpdateEffects) {
+TEST_P(AnimationAnimationTestNoCompositing, EmptyAnimationsDontUpdateEffects) {
animation = timeline->Play(nullptr);
animation->Update(kTimingUpdateOnDemand);
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
@@ -1195,7 +1006,7 @@ TEST_F(AnimationAnimationTestNoCompositing, EmptyAnimationsDontUpdateEffects) {
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
}
-TEST_F(AnimationAnimationTestNoCompositing, AnimationsDisassociateFromEffect) {
+TEST_P(AnimationAnimationTestNoCompositing, AnimationsDisassociateFromEffect) {
AnimationEffect* animation_node = animation->effect();
Animation* animation2 = timeline->Play(animation_node);
EXPECT_EQ(nullptr, animation->effect());
@@ -1207,7 +1018,7 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsDisassociateFromEffect) {
EXPECT_NEAR(expected.InMillisecondsF(), observed.InMillisecondsF(), \
Animation::kTimeToleranceMs)
-TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
+TEST_P(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
Timing timing;
timing.start_delay = AnimationTimeDelta::FromSecondsD(1);
timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
@@ -1215,12 +1026,8 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
nullptr, MakeEmptyEffectModel(), timing);
animation = timeline->Play(keyframe_effect);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Next effect change at end of start delay.
SimulateFrame(0);
@@ -1252,12 +1059,8 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
// Reset to start of animation. Next effect at the end of the start delay.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
SimulateFrame(3000);
EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(1),
animation->TimeToEffectChange().value());
@@ -1274,12 +1077,8 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
// Reversed animation from end time. Next effect after end delay.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(3000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(3000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(-1);
animation->Update(kTimingUpdateOnDemand);
SimulateFrame(3000);
@@ -1294,7 +1093,7 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
animation->TimeToEffectChange().value());
}
-TEST_F(AnimationAnimationTestNoCompositing, TimeToNextEffectWhenPaused) {
+TEST_P(AnimationAnimationTestNoCompositing, TimeToNextEffectWhenPaused) {
EXPECT_TIMEDELTA(AnimationTimeDelta(),
animation->TimeToEffectChange().value());
animation->pause();
@@ -1306,16 +1105,12 @@ TEST_F(AnimationAnimationTestNoCompositing, TimeToNextEffectWhenPaused) {
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
TimeToNextEffectWhenCancelledBeforeStart) {
EXPECT_TIMEDELTA(AnimationTimeDelta(),
animation->TimeToEffectChange().value());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(-8000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(-8000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(2);
EXPECT_EQ("running", animation->playState());
animation->cancel();
@@ -1327,16 +1122,12 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
TimeToNextEffectWhenCancelledBeforeStartReverse) {
EXPECT_TIMEDELTA(AnimationTimeDelta(),
animation->TimeToEffectChange().value());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(9000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(9000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setPlaybackRate(-3);
EXPECT_EQ("running", animation->playState());
animation->cancel();
@@ -1346,7 +1137,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
TimeToNextEffectSimpleCancelledBeforeStart) {
EXPECT_TIMEDELTA(AnimationTimeDelta(),
animation->TimeToEffectChange().value());
@@ -1358,7 +1149,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_EQ(absl::nullopt, animation->TimeToEffectChange());
}
-TEST_F(AnimationAnimationTestNoCompositing, AttachedAnimations) {
+TEST_P(AnimationAnimationTestNoCompositing, AttachedAnimations) {
// Prevent |element| from being collected by |CollectAllGarbageForTesting|.
Persistent<Element> element = GetDocument().CreateElementForBinding("foo");
@@ -1375,7 +1166,7 @@ TEST_F(AnimationAnimationTestNoCompositing, AttachedAnimations) {
EXPECT_TRUE(element->GetElementAnimations()->Animations().IsEmpty());
}
-TEST_F(AnimationAnimationTestNoCompositing, HasLowerCompositeOrdering) {
+TEST_P(AnimationAnimationTestNoCompositing, HasLowerCompositeOrdering) {
Animation* animation1 = timeline->Play(nullptr);
Animation* animation2 = timeline->Play(nullptr);
EXPECT_TRUE(Animation::HasLowerCompositeOrdering(
@@ -1383,7 +1174,7 @@ TEST_F(AnimationAnimationTestNoCompositing, HasLowerCompositeOrdering) {
Animation::CompareAnimationsOrdering::kPointerOrder));
}
-TEST_F(AnimationAnimationTestNoCompositing, PlayAfterCancel) {
+TEST_P(AnimationAnimationTestNoCompositing, PlayAfterCancel) {
animation->cancel();
EXPECT_EQ("idle", animation->playState());
EXPECT_FALSE(CurrentTimeIsSet(animation));
@@ -1404,14 +1195,10 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayAfterCancel) {
EXPECT_TIME(0, GetStartTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, PlayBackwardsAfterCancel) {
+TEST_P(AnimationAnimationTestNoCompositing, PlayBackwardsAfterCancel) {
animation->setPlaybackRate(-1);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(15000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(15000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->cancel();
EXPECT_EQ("idle", animation->playState());
EXPECT_FALSE(animation->pending());
@@ -1434,7 +1221,7 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayBackwardsAfterCancel) {
EXPECT_TIME(30000, GetStartTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, ReverseAfterCancel) {
+TEST_P(AnimationAnimationTestNoCompositing, ReverseAfterCancel) {
animation->cancel();
EXPECT_EQ("idle", animation->playState());
EXPECT_FALSE(animation->pending());
@@ -1457,7 +1244,7 @@ TEST_F(AnimationAnimationTestNoCompositing, ReverseAfterCancel) {
EXPECT_TIME(30000, GetStartTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, FinishAfterCancel) {
+TEST_P(AnimationAnimationTestNoCompositing, FinishAfterCancel) {
NonThrowableExceptionState exception_state;
animation->cancel();
EXPECT_EQ("idle", animation->playState());
@@ -1470,7 +1257,7 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishAfterCancel) {
EXPECT_TIME(-30000, GetStartTimeMs(animation));
}
-TEST_F(AnimationAnimationTestNoCompositing, PauseAfterCancel) {
+TEST_P(AnimationAnimationTestNoCompositing, PauseAfterCancel) {
animation->cancel();
EXPECT_EQ("idle", animation->playState());
EXPECT_FALSE(CurrentTimeIsSet(animation));
@@ -1487,7 +1274,7 @@ TEST_F(AnimationAnimationTestNoCompositing, PauseAfterCancel) {
}
// crbug.com/1052217
-TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateAfterFinish) {
+TEST_P(AnimationAnimationTestNoCompositing, SetPlaybackRateAfterFinish) {
animation->setEffect(MakeAnimation(30, Timing::FillMode::FORWARDS));
animation->finish();
animation->Update(kTimingUpdateOnDemand);
@@ -1506,7 +1293,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateAfterFinish) {
EXPECT_FALSE(animation->Outdated());
}
-TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateAfterFinish) {
+TEST_P(AnimationAnimationTestNoCompositing, UpdatePlaybackRateAfterFinish) {
animation->setEffect(MakeAnimation(30, Timing::FillMode::FORWARDS));
animation->finish();
animation->Update(kTimingUpdateOnDemand);
@@ -1527,7 +1314,7 @@ TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateAfterFinish) {
EXPECT_FALSE(animation->Outdated());
}
-TEST_F(AnimationAnimationTestCompositeAfterPaint,
+TEST_P(AnimationAnimationTestCompositing,
NoCompositeWithoutCompositedElementId) {
SetBodyInnerHTML(
"<div id='foo' style='position: relative; will-change: "
@@ -1567,7 +1354,7 @@ TEST_F(AnimationAnimationTestCompositeAfterPaint,
// played and then paused before any start time is set (either blink or
// compositor side), the pausing must still set compositor pending or the pause
// won't be synced.
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
SetCompositorPendingWithUnresolvedStartTimes) {
ResetWithCompositedAnimation();
@@ -1585,7 +1372,7 @@ TEST_F(AnimationAnimationTestCompositing,
EXPECT_TRUE(animation->CompositorPending());
}
-TEST_F(AnimationAnimationTestCompositing, PreCommitWithUnresolvedStartTimes) {
+TEST_P(AnimationAnimationTestCompositing, PreCommitWithUnresolvedStartTimes) {
ResetWithCompositedAnimation();
// At this point, the animation exists on both the compositor and blink side,
@@ -1610,7 +1397,7 @@ int GenerateHistogramValue(CompositorAnimations::FailureReason reason) {
}
} // namespace
-TEST_F(AnimationAnimationTestCompositing, PreCommitRecordsHistograms) {
+TEST_P(AnimationAnimationTestCompositing, PreCommitRecordsHistograms) {
const std::string histogram_name =
"Blink.Animation.CompositedAnimationFailureReason";
@@ -1675,7 +1462,7 @@ TEST_F(AnimationAnimationTestCompositing, PreCommitRecordsHistograms) {
}
// crbug.com/990000.
-TEST_F(AnimationAnimationTestCompositing, ReplaceCompositedAnimation) {
+TEST_P(AnimationAnimationTestCompositing, ReplaceCompositedAnimation) {
const std::string histogram_name =
"Blink.Animation.CompositedAnimationFailureReason";
@@ -1690,7 +1477,7 @@ TEST_F(AnimationAnimationTestCompositing, ReplaceCompositedAnimation) {
ASSERT_TRUE(animation->HasActiveAnimationsOnCompositor());
}
-TEST_F(AnimationAnimationTestCompositing, SetKeyframesCausesCompositorPending) {
+TEST_P(AnimationAnimationTestCompositing, SetKeyframesCausesCompositorPending) {
ResetWithCompositedAnimation();
// At this point, the animation exists on both the compositor and blink side,
@@ -1720,14 +1507,15 @@ TEST_F(AnimationAnimationTestCompositing, SetKeyframesCausesCompositorPending) {
// crbug.com/1057076
// Infinite duration animations should not run on the compositor.
-TEST_F(AnimationAnimationTestCompositing, InfiniteDurationAnimation) {
+TEST_P(AnimationAnimationTestCompositing, InfiniteDurationAnimation) {
ResetWithCompositedAnimation();
EXPECT_EQ(CompositorAnimations::kNoFailure,
animation->CheckCanStartAnimationOnCompositor(nullptr));
OptionalEffectTiming* effect_timing = OptionalEffectTiming::Create();
- effect_timing->setDuration(UnrestrictedDoubleOrString::FromUnrestrictedDouble(
- std::numeric_limits<double>::infinity()));
+ effect_timing->setDuration(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
+ std::numeric_limits<double>::infinity()));
animation->effect()->updateTiming(effect_timing);
EXPECT_EQ(CompositorAnimations::kEffectHasUnsupportedTimingParameters,
animation->CheckCanStartAnimationOnCompositor(nullptr));
@@ -1738,14 +1526,14 @@ TEST_F(AnimationAnimationTestCompositing, InfiniteDurationAnimation) {
// relative transforms after a size change. In this test, the transform depends
// on the width and height of the box and a change to either triggers a restart
// of the animation if running.
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
RestartCompositedAnimationOnSizeChange) {
// TODO(crbug.com/389359): Remove forced feature enabling once on by
// default.
ScopedCompositeRelativeKeyframesForTest composite_relative_keyframes(true);
SetBodyInnerHTML(R"HTML(
- <div id ="target"
- style="width: 100px; height: 200px; will-change: transform">
+ <div id="target" style="width: 100px; height: 200px; background: blue;
+ will-change: transform">
</div>
)HTML");
@@ -1765,12 +1553,8 @@ TEST_F(AnimationAnimationTestCompositing,
EXPECT_TRUE(animation->HasActiveAnimationsOnCompositor());
// Kick the animation out of the play-pending state.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// No size change and animation does not require a restart.
keyframe_effect->UpdateBoxSizeAndCheckTransformAxisAlignment(
@@ -1795,14 +1579,14 @@ TEST_F(AnimationAnimationTestCompositing,
// Regression test to ensure proper restart logic for composited animations on
// relative transforms after a size change. In this test, the transform only
// depends on width and a change to the height does not trigger a restart.
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
RestartCompositedAnimationOnWidthChange) {
// TODO(crbug.com/389359): Remove forced feature enabling once on by
// default.
ScopedCompositeRelativeKeyframesForTest composite_relative_keyframes(true);
SetBodyInnerHTML(R"HTML(
- <div id ="target"
- style="width: 100px; height: 200px; will-change: transform">
+ <div id="target" style="width: 100px; height: 200px; background: blue;
+ will-change: transform">
</div>
)HTML");
@@ -1819,12 +1603,8 @@ TEST_F(AnimationAnimationTestCompositing,
EXPECT_TRUE(animation->HasActiveAnimationsOnCompositor());
keyframe_effect->UpdateBoxSizeAndCheckTransformAxisAlignment(
FloatSize(100, 200));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Transform is not height dependent and a change to the height does not force
// an animation restart.
@@ -1842,14 +1622,14 @@ TEST_F(AnimationAnimationTestCompositing,
// Regression test to ensure proper restart logic for composited animations on
// relative transforms after a size change. In this test, the transition only
// affects height and a change to the width does not trigger a restart.
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
RestartCompositedAnimationOnHeightChange) {
// TODO(crbug.com/389359): Remove forced feature enabling once on by
// default.
ScopedCompositeRelativeKeyframesForTest composite_relative_keyframes(true);
SetBodyInnerHTML(R"HTML(
- <div id ="target"
- style="width: 100px; height: 200px; will-change: transform">
+ <div id="target" style="width: 100px; height: 200px; background: blue;
+ will-change: transform">
</div>
)HTML");
@@ -1866,12 +1646,8 @@ TEST_F(AnimationAnimationTestCompositing,
EXPECT_TRUE(animation->HasActiveAnimationsOnCompositor());
keyframe_effect->UpdateBoxSizeAndCheckTransformAxisAlignment(
FloatSize(100, 200));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Transform is not width dependent and a change to the width does not force
// an animation restart.
@@ -1885,13 +1661,60 @@ TEST_F(AnimationAnimationTestCompositing,
EXPECT_FALSE(animation->HasActiveAnimationsOnCompositor());
}
-TEST_F(AnimationAnimationTestCompositing,
+// This test ensures that a clip-path animation can start on compositor.
+TEST_P(AnimationAnimationTestCompositing, ClipPathComposited) {
+ ScopedCompositeClipPathAnimationForTest composite_clip_path_animation(true);
+ SetBodyInnerHTML(R"HTML(
+ <div id ="target" style="width: 100px; height: 100px; clip-path: circle(50% at 50% 50%)">
+ </div>
+ )HTML");
+
+ // Create KeyframeEffect
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
+
+ Persistent<StringKeyframe> start_keyframe =
+ MakeGarbageCollected<StringKeyframe>();
+ start_keyframe->SetCSSPropertyValue(
+ CSSPropertyID::kClipPath, "circle(50% at 50% 50%)",
+ SecureContextMode::kInsecureContext, nullptr);
+ Persistent<StringKeyframe> end_keyframe =
+ MakeGarbageCollected<StringKeyframe>();
+ end_keyframe->SetCSSPropertyValue(
+ CSSPropertyID::kClipPath, "(20% at 20% 20%)",
+ SecureContextMode::kInsecureContext, nullptr);
+
+ StringKeyframeVector keyframes;
+ keyframes.push_back(start_keyframe);
+ keyframes.push_back(end_keyframe);
+
+ Element* element = GetElementById("target");
+ auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
+
+ NonThrowableExceptionState exception_state;
+ DocumentTimeline* timeline =
+ MakeGarbageCollected<DocumentTimeline>(&GetDocument());
+ Animation* animation = Animation::Create(
+ MakeGarbageCollected<KeyframeEffect>(element, model, timing), timeline,
+ exception_state);
+
+ UpdateAllLifecyclePhasesForTest();
+ animation->play();
+ EXPECT_EQ(animation->CheckCanStartAnimationOnCompositor(nullptr),
+ CompositorAnimations::kNoFailure);
+}
+
+TEST_P(AnimationAnimationTestCompositing,
ScrollLinkedAnimationCanBeComposited) {
ResetWithCompositedAnimation();
SetBodyInnerHTML(R"HTML(
<style>
- #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
- #target { width: 100px; height: 200px; will-change: opacity;}
+ #scroller {
+ will-change: transform; overflow: scroll; width: 100px; height: 100px;
+ }
+ #target {
+ width: 100px; height: 200px; background: blue; will-change: opacity;
+ }
#spacer { width: 200px; height: 2000px; }
</style>
<div id ='scroller'>
@@ -1907,8 +1730,8 @@ TEST_F(AnimationAnimationTestCompositing,
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -1950,13 +1773,17 @@ TEST_F(AnimationAnimationTestCompositing,
CompositorAnimations::kNoFailure);
}
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
StartScrollLinkedAnimationWithStartTimeIfApplicable) {
ResetWithCompositedAnimation();
SetBodyInnerHTML(R"HTML(
<style>
- #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
- #target { width: 100px; height: 200px; will-change: opacity;}
+ #scroller {
+ will-change: transform; overflow: scroll; width: 100px; height: 100px; background: blue;
+ }
+ #target {
+ width: 100px; height: 200px; background: blue; will-change: opacity;
+ }
#spacer { width: 200px; height: 700px; }
</style>
<div id ='scroller'>
@@ -1972,8 +1799,8 @@ TEST_F(AnimationAnimationTestCompositing,
scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
mojom::blink::ScrollType::kProgrammatic);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -2013,13 +1840,9 @@ TEST_F(AnimationAnimationTestCompositing,
UpdateAllLifecyclePhasesForTest();
const double TEST_START_TIME = 10;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
scroll_animation->setStartTime(
MakeGarbageCollected<V8CSSNumberish>(TEST_START_TIME),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- scroll_animation->setStartTime(CSSNumberish::FromDouble(TEST_START_TIME));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
scroll_animation->play();
EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr),
CompositorAnimations::kNoFailure);
@@ -2038,7 +1861,7 @@ TEST_F(AnimationAnimationTestCompositing,
// Verifies correctness of scroll linked animation current and start times in
// various animation states.
-TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
+TEST_P(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; width: 100px; height: 100px; }
@@ -2055,8 +1878,8 @@ TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -2090,13 +1913,13 @@ TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
// Verifies that finished composited scroll-linked animations restart on
// compositor upon reverse scrolling.
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
FinishedScrollLinkedAnimationRestartsOnReverseScrolling) {
ResetWithCompositedAnimation();
SetBodyInnerHTML(R"HTML(
<style>
#scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
- #target { width: 100px; height: 200px; will-change: opacity;}
+ #target { width: 100px; height: 200px; will-change: opacity; background: green;}
#spacer { width: 200px; height: 700px; }
</style>
<div id ='scroller'>
@@ -2111,8 +1934,8 @@ TEST_F(AnimationAnimationTestCompositing,
// Create ScrollTimeline
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -2156,24 +1979,16 @@ TEST_F(AnimationAnimationTestCompositing,
// Advances the animation to "finished" state. The composited animation will
// be destroyed accordingly.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
scroll_animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- scroll_animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ(scroll_animation->playState(), "finished");
scroll_animation->Update(kTimingUpdateForAnimationFrame);
GetDocument().GetPendingAnimations().Update(nullptr, true);
EXPECT_FALSE(scroll_animation->HasActiveAnimationsOnCompositor());
// Restarting the animation should create a new compositor animation.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
scroll_animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(100),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- scroll_animation->setCurrentTime(CSSNumberish::FromDouble(100));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(scroll_animation->playState(), "running");
scroll_animation->Update(kTimingUpdateForAnimationFrame);
@@ -2181,7 +1996,7 @@ TEST_F(AnimationAnimationTestCompositing,
EXPECT_TRUE(scroll_animation->HasActiveAnimationsOnCompositor());
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
RemoveCanceledAnimationFromActiveSet) {
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
@@ -2192,7 +2007,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
RemoveFinishedAnimationFromActiveSet) {
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
@@ -2210,17 +2025,13 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
// Asynchronous completion.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
}
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
PendingActivityWithFinishedPromise) {
// No pending activity even when running if there is no finished promise
// or event listener.
@@ -2235,12 +2046,8 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->HasPendingActivity());
// Resolving the finished promise clears the pending activity.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
SimulateMicrotask();
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
@@ -2265,7 +2072,7 @@ class MockEventListener final : public NativeEventListener {
MOCK_METHOD2(Invoke, void(ExecutionContext*, Event*));
};
-TEST_F(AnimationAnimationTestNoCompositing,
+TEST_P(AnimationAnimationTestNoCompositing,
PendingActivityWithFinishedEventListener) {
EXPECT_EQ("running", animation->playState());
EXPECT_FALSE(animation->HasPendingActivity());
@@ -2290,12 +2097,8 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->HasPendingActivity());
// Finishing the animation asynchronously clears the pending activity.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(50000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ("finished", animation->playState());
SimulateMicrotask();
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
@@ -2313,7 +2116,8 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_FALSE(animation->HasPendingActivity());
}
-class AnimationPendingAnimationsTest : public RenderingTest {
+class AnimationPendingAnimationsTest : public PaintTestConfigurations,
+ public RenderingTest {
public:
AnimationPendingAnimationsTest()
: RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
@@ -2379,9 +2183,11 @@ class AnimationPendingAnimationsTest : public RenderingTest {
Persistent<DocumentTimeline> timeline;
};
-TEST_F(AnimationPendingAnimationsTest, PendingAnimationStartSynchronization) {
+INSTANTIATE_PAINT_TEST_SUITE_P(AnimationPendingAnimationsTest);
+
+TEST_P(AnimationPendingAnimationsTest, PendingAnimationStartSynchronization) {
RunDocumentLifecycle();
- SetBodyInnerHTML("<div id='foo'></div><div id='bar'></div>");
+ SetBodyInnerHTML("<div id='foo'>f</div><div id='bar'>b</div>");
Animation* animA = MakeAnimation("foo", kComposited);
Animation* animB = MakeAnimation("bar", kNonComposited);
@@ -2397,10 +2203,10 @@ TEST_F(AnimationPendingAnimationsTest, PendingAnimationStartSynchronization) {
EXPECT_FALSE(animB->pending());
}
-TEST_F(AnimationPendingAnimationsTest,
+TEST_P(AnimationPendingAnimationsTest,
PendingAnimationCancelUnblocksSynchronizedStart) {
RunDocumentLifecycle();
- SetBodyInnerHTML("<div id='foo'></div><div id='bar'></div>");
+ SetBodyInnerHTML("<div id='foo'>f</div><div id='bar'>b</div>");
Animation* animA = MakeAnimation("foo", kComposited);
Animation* animB = MakeAnimation("bar", kNonComposited);
@@ -2415,11 +2221,11 @@ TEST_F(AnimationPendingAnimationsTest,
EXPECT_FALSE(animB->pending());
}
-TEST_F(AnimationPendingAnimationsTest,
+TEST_P(AnimationPendingAnimationsTest,
PendingAnimationOnlySynchronizeStartsOfNewlyPendingAnimations) {
RunDocumentLifecycle();
SetBodyInnerHTML(
- "<div id='foo'></div><div id='bar'></div><div id='baz'></div>");
+ "<div id='foo'>f</div><div id='bar'>b</div><div id='baz'>z</div>");
Animation* animA = MakeAnimation("foo", kComposited);
Animation* animB = MakeAnimation("bar", kNonComposited);
@@ -2450,7 +2256,7 @@ TEST_F(AnimationPendingAnimationsTest,
EXPECT_FALSE(animD->pending());
}
-TEST_F(AnimationAnimationTestCompositing,
+TEST_P(AnimationAnimationTestCompositing,
ScrollLinkedAnimationNotCompositedIfScrollSourceIsNotComposited) {
GetDocument().GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
SetBodyInnerHTML(R"HTML(
@@ -2475,8 +2281,8 @@ TEST_F(AnimationAnimationTestCompositing,
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -2518,7 +2324,14 @@ TEST_F(AnimationAnimationTestCompositing,
CompositorAnimations::kTimelineSourceHasInvalidCompositingState);
}
-TEST_F(AnimationAnimationTestCompositing, ContentVisibleDisplayLockTest) {
+#if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
+// https://crbug.com/1222646
+#define MAYBE_ContentVisibleDisplayLockTest \
+ DISABLED_ContentVisibleDisplayLockTest
+#else
+#define MAYBE_ContentVisibleDisplayLockTest ContentVisibleDisplayLockTest
+#endif
+TEST_P(AnimationAnimationTestCompositing, MAYBE_ContentVisibleDisplayLockTest) {
animation->cancel();
RunDocumentLifecycle();
@@ -2576,4 +2389,120 @@ TEST_F(AnimationAnimationTestCompositing, ContentVisibleDisplayLockTest) {
EXPECT_EQ(animation->playState(), "running");
}
+TEST_P(AnimationAnimationTestCompositing, HiddenAnimationsDoNotTick) {
+ // This test applies to CompositeAfterPaint only.
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ @keyframes anim {
+ from { opacity: 0; }
+ to { opacity: 1; }
+ }
+ #target {
+ width: 10px;
+ height: 10px;
+ background: rebeccapurple;
+ animation: anim 30s;
+ }
+ </style>
+ <div id="visibility" style="visibility: hidden;">
+ <div id="target"></div>
+ </div>
+ )HTML");
+
+ Element* target = GetElementById("target");
+ ElementAnimations* element_animations = target->GetElementAnimations();
+ ASSERT_EQ(1u, element_animations->Animations().size());
+ Animation* animation = element_animations->Animations().begin()->key;
+
+ RunDocumentLifecycle();
+
+ const PaintArtifactCompositor* paint_artifact_compositor =
+ GetDocument().View()->GetPaintArtifactCompositor();
+ ASSERT_TRUE(paint_artifact_compositor);
+
+ // The animation should run on main because compositor properties are missing.
+ EXPECT_EQ(
+ animation->CheckCanStartAnimationOnCompositor(paint_artifact_compositor),
+ CompositorAnimations::kCompositorPropertyAnimationsHaveNoEffect);
+ EXPECT_TRUE(animation->CompositorPropertyAnimationsHaveNoEffectForTesting());
+ EXPECT_TRUE(animation->AnimationHasNoEffect());
+
+ // The next effect change should be at the end because the animation does not
+ // tick while hidden.
+ EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(30),
+ animation->TimeToEffectChange().value());
+}
+
+TEST_P(AnimationAnimationTestCompositing, HiddenAnimationsTickWhenVisible) {
+ // This test applies to CompositeAfterPaint only.
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ @keyframes anim {
+ from { opacity: 0; }
+ to { opacity: 1; }
+ }
+ #target {
+ width: 10px;
+ height: 10px;
+ background: rebeccapurple;
+ animation: anim 30s;
+ }
+ </style>
+ <div id="visibility" style="visibility: hidden;">
+ <div id="target"></div>
+ </div>
+ )HTML");
+
+ Element* target = GetElementById("target");
+ ElementAnimations* element_animations = target->GetElementAnimations();
+ ASSERT_EQ(1u, element_animations->Animations().size());
+ Animation* animation = element_animations->Animations().begin()->key;
+
+ RunDocumentLifecycle();
+
+ const PaintArtifactCompositor* paint_artifact_compositor =
+ GetDocument().View()->GetPaintArtifactCompositor();
+ ASSERT_TRUE(paint_artifact_compositor);
+
+ // The animation should run on main because compositor properties are missing.
+ EXPECT_EQ(
+ animation->CheckCanStartAnimationOnCompositor(paint_artifact_compositor),
+ CompositorAnimations::kCompositorPropertyAnimationsHaveNoEffect);
+ EXPECT_TRUE(animation->CompositorPropertyAnimationsHaveNoEffectForTesting());
+ EXPECT_TRUE(animation->AnimationHasNoEffect());
+
+ // The no-effect animation doesn't count. The one animation is
+ // AnimationAnimationTestCompositing::animation_.
+ EXPECT_EQ(1u, animation->timeline()->AnimationsNeedingUpdateCount());
+
+ // The next effect change should be at the end because the animation does not
+ // tick while hidden.
+ EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(30),
+ animation->TimeToEffectChange().value());
+
+ Element* visibility = GetElementById("visibility");
+ visibility->setAttribute(html_names::kStyleAttr, "visibility: visible;");
+ RunDocumentLifecycle();
+
+ // The animation should run on the compositor after the properties are
+ // created.
+ EXPECT_EQ(
+ animation->CheckCanStartAnimationOnCompositor(paint_artifact_compositor),
+ CompositorAnimations::kNoFailure);
+ EXPECT_FALSE(animation->CompositorPropertyAnimationsHaveNoEffectForTesting());
+ EXPECT_FALSE(animation->AnimationHasNoEffect());
+ EXPECT_EQ(2u, animation->timeline()->AnimationsNeedingUpdateCount());
+
+ // The next effect change should be at the end because the animation is
+ // running on the compositor.
+ EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(30),
+ animation->TimeToEffectChange().value());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.cc b/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.cc
index 081611af432..3d1e0176b89 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_csskeywordvalue_cssnumericvalue_scrolltimelineelementbasedoffset_string.h"
#include "third_party/blink/renderer/core/animation/css_interpolation_environment.h"
#include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h"
#include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
@@ -78,7 +79,8 @@ void EnsureInterpolatedValueCached(ActiveInterpolations* interpolations,
// require our callers to properly register every animation they pass in
// here, which the current tests do not do.
auto style = document.GetStyleResolver().CreateComputedStyle();
- StyleResolverState state(document, *element, StyleRequest(style.get()));
+ StyleResolverState state(document, *element, StyleRecalcContext(),
+ StyleRequest(style.get()));
state.SetStyle(style);
ActiveInterpolationsMap map;
@@ -89,21 +91,19 @@ void EnsureInterpolatedValueCached(ActiveInterpolations* interpolations,
cascade.Apply();
}
-ScrollTimelineOffsetValue OffsetFromString(Document& document,
- const String& string) {
- ScrollTimelineOffsetValue result;
-
+V8ScrollTimelineOffset* OffsetFromString(Document& document,
+ const String& string) {
const CSSValue* value = css_test_helpers::ParseValue(
document, "<length-percentage> | auto", string);
- if (const auto* primitive = DynamicTo<CSSPrimitiveValue>(value))
- result.SetCSSNumericValue(CSSNumericValue::FromCSSValue(*primitive));
- else if (DynamicTo<CSSIdentifierValue>(value))
- result.SetCSSKeywordValue(CSSKeywordValue::Create("auto"));
- else
- result.SetString(string);
-
- return result;
+ if (const auto* primitive = DynamicTo<CSSPrimitiveValue>(value)) {
+ return MakeGarbageCollected<V8ScrollTimelineOffset>(
+ CSSNumericValue::FromCSSValue(*primitive));
+ } else if (DynamicTo<CSSIdentifierValue>(value)) {
+ return MakeGarbageCollected<V8ScrollTimelineOffset>(
+ CSSKeywordValue::Create("auto"));
+ }
+ return MakeGarbageCollected<V8ScrollTimelineOffset>(string);
}
} // namespace animation_test_helpers
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.h b/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.h
index dd7018198df..6841d213fc8 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test_helpers.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_TEST_HELPERS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_TEST_HELPERS_H_
-#include "third_party/blink/renderer/bindings/core/v8/css_numeric_value_or_string_or_css_keyword_value_or_scroll_timeline_element_based_offset.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/animation/interpolation.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
@@ -50,7 +50,7 @@ void EnsureInterpolatedValueCached(ActiveInterpolations*, Document&, Element*);
// <length-percentage>.
// - A CSSKeywordValue. if the incoming string can be parsed as 'auto'.
// - Otherwise, the incoming string.
-ScrollTimelineOffsetValue OffsetFromString(Document&, const String&);
+V8ScrollTimelineOffset* OffsetFromString(Document&, const String&);
} // namespace animation_test_helpers
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_time_delta.h b/chromium/third_party/blink/renderer/core/animation/animation_time_delta.h
index 83d0364413e..cb47f72f02a 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_time_delta.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_time_delta.h
@@ -7,10 +7,7 @@
#include "third_party/blink/renderer/core/animation/buildflags.h"
-#if BUILDFLAG(BLINK_ANIMATION_USE_TIME_DELTA)
#include "base/time/time.h"
-#endif
-
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc b/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc
index 26237576c55..de96ec3f84a 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc
@@ -41,20 +41,12 @@ bool CompareAnimations(const Member<Animation>& left,
Animation::CompareAnimationsOrdering::kPointerOrder);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* AnimationTimeline::currentTime() {
const absl::optional<base::TimeDelta>& result = CurrentPhaseAndTime().time;
if (result)
return MakeGarbageCollected<V8CSSNumberish>(result->InMillisecondsF());
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void AnimationTimeline::currentTime(CSSNumberish& currentTime) {
- absl::optional<base::TimeDelta> result = CurrentPhaseAndTime().time;
- currentTime = result ? CSSNumberish::FromDouble(result->InMillisecondsF())
- : CSSNumberish();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<AnimationTimeDelta> AnimationTimeline::CurrentTime() {
absl::optional<base::TimeDelta> result = CurrentPhaseAndTime().time;
@@ -73,15 +65,9 @@ absl::optional<double> AnimationTimeline::CurrentTimeSeconds() {
return result ? absl::make_optional(result->InSecondsF()) : absl::nullopt;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* AnimationTimeline::duration() {
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void AnimationTimeline::duration(CSSNumberish& duration) {
- duration = CSSNumberish();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String AnimationTimeline::phase() {
switch (CurrentPhaseAndTime().phase) {
@@ -101,6 +87,17 @@ void AnimationTimeline::ClearOutdatedAnimation(Animation* animation) {
outdated_animation_count_--;
}
+wtf_size_t AnimationTimeline::AnimationsNeedingUpdateCount() const {
+ wtf_size_t count = 0;
+ for (const auto& animation : animations_needing_update_) {
+ // This function is for frame sequence tracking for animations. Exclude
+ // no-effect animations which don't generate frames.
+ if (!animation->AnimationHasNoEffect())
+ count++;
+ }
+ return count;
+}
+
bool AnimationTimeline::NeedsAnimationTimingUpdate() {
PhaseAndTime current_phase_and_time = CurrentPhaseAndTime();
if (current_phase_and_time == last_current_phase_and_time_)
@@ -205,6 +202,14 @@ void AnimationTimeline::MarkAnimationsCompositorPending(bool source_changed) {
}
}
+void AnimationTimeline::MarkPendingIfCompositorPropertyAnimationChanges(
+ const PaintArtifactCompositor* paint_artifact_compositor) {
+ for (const auto& animation : animations_) {
+ animation->MarkPendingIfCompositorPropertyAnimationChanges(
+ paint_artifact_compositor);
+ }
+}
+
void AnimationTimeline::Trace(Visitor* visitor) const {
visitor->Trace(document_);
visitor->Trace(animations_needing_update_);
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_timeline.h b/chromium/third_party/blink/renderer/core/animation/animation_timeline.h
index 0ab43c1998f..082f0547a1c 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_timeline.h
@@ -35,20 +35,12 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
AnimationTimeline(Document*);
~AnimationTimeline() override = default;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual V8CSSNumberish* currentTime();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void currentTime(CSSNumberish&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<AnimationTimeDelta> CurrentTime();
absl::optional<double> CurrentTimeMilliseconds();
absl::optional<double> CurrentTimeSeconds();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual V8CSSNumberish* duration();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void duration(CSSNumberish&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String phase();
TimelinePhase Phase() { return CurrentPhaseAndTime().phase; }
@@ -56,6 +48,7 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
virtual bool IsDocumentTimeline() const { return false; }
virtual bool IsScrollTimeline() const { return false; }
virtual bool IsCSSScrollTimeline() const { return false; }
+ virtual bool IsProgressBasedTimeline() const { return false; }
virtual bool IsActive() const = 0;
virtual AnimationTimeDelta ZeroTime() = 0;
// https://drafts.csswg.org/web-animations/#monotonically-increasing-timeline
@@ -71,6 +64,10 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
// Changing scroll-linked animation start_time initialization is under
// consideration here: https://github.com/w3c/csswg-drafts/issues/2075.
virtual absl::optional<base::TimeDelta> InitialStartTimeForAnimations() = 0;
+ virtual AnimationTimeDelta CalculateIntrinsicIterationDuration(
+ const Timing&) {
+ return AnimationTimeDelta();
+ }
Document* GetDocument() { return document_; }
virtual void AnimationAttached(Animation*);
virtual void AnimationDetached(Animation*);
@@ -92,9 +89,7 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
void SetOutdatedAnimation(Animation*);
void ClearOutdatedAnimation(Animation*);
- virtual wtf_size_t AnimationsNeedingUpdateCount() const {
- return animations_needing_update_.size();
- }
+ virtual wtf_size_t AnimationsNeedingUpdateCount() const;
const HeapHashSet<WeakMember<Animation>>& GetAnimations() const {
return animations_;
}
@@ -107,6 +102,11 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
void MarkAnimationsCompositorPending(bool source_changed = false);
+ // Checks for animations of composited properties that would have no effect
+ // and marks them as pending if this changes.
+ void MarkPendingIfCompositorPropertyAnimationChanges(
+ const PaintArtifactCompositor*);
+
using ReplaceableAnimationsMap =
HeapHashMap<Member<Element>, Member<HeapVector<Member<Animation>>>>;
void getReplaceableAnimations(
@@ -114,6 +114,10 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
void Trace(Visitor*) const override;
+ virtual absl::optional<AnimationTimeDelta> GetDuration() const {
+ return absl::nullopt;
+ }
+
protected:
virtual PhaseAndTime CurrentPhaseAndTime() = 0;
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 4da41e05724..2e1e6decce4 100644
--- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -187,8 +187,10 @@ bool IsNoOpBGColorOrVariableAnimation(const PropertyHandle& property,
return is_no_op_variable_anim || is_no_op_bgcolor_anim;
}
-bool CompositedAnimationRequiresProperties(CSSPropertyID property) {
- switch (property) {
+bool CompositedAnimationRequiresProperties(const PropertyHandle& property) {
+ if (!property.IsCSSProperty())
+ return false;
+ switch (property.GetCSSProperty().PropertyID()) {
case CSSPropertyID::kOpacity:
case CSSPropertyID::kBackdropFilter:
case CSSPropertyID::kRotate:
@@ -200,7 +202,6 @@ bool CompositedAnimationRequiresProperties(CSSPropertyID property) {
default:
return false;
}
- return false;
}
} // namespace
@@ -220,6 +221,7 @@ CompositorAnimations::CompositorElementNamespaceForProperty(
case CSSPropertyID::kFilter:
return CompositorElementIdNamespace::kEffectFilter;
case CSSPropertyID::kBackgroundColor:
+ case CSSPropertyID::kClipPath:
case CSSPropertyID::kVariable:
// TODO(crbug.com/883721): Variables and background color should not
// require the target element to have any composited property tree nodes -
@@ -327,12 +329,19 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
bool background_transfers_to_view = false;
Animation* compositable_animation = nullptr;
if (RuntimeEnabledFeatures::CompositeBGColorAnimationEnabled()) {
+ // Not having a layout object is a reason for not compositing marked
+ // in CompositorAnimations::CheckCanStartElementOnCompositor.
+ if (!layout_object)
+ continue;
BackgroundColorPaintImageGenerator* generator =
target_element.GetDocument()
.GetFrame()
->GetBackgroundColorPaintImageGenerator();
- compositable_animation =
- generator->GetAnimationIfCompositable(&target_element);
+ // The generator may be null in tests.
+ if (generator) {
+ compositable_animation =
+ generator->GetAnimationIfCompositable(&target_element);
+ }
// When this is true, we have a background-color animation in the
// body element, while the view is responsible for painting the
// body's background. In this case, we need to let the
@@ -348,7 +357,7 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
// BackgroundColorPaintWorklet, as a result, we should not composite
// the background color animation on the table rows or cols.
if (!RuntimeEnabledFeatures::CompositeBGColorAnimationEnabled() ||
- !layout_object || layout_object->IsLayoutTableCol() ||
+ layout_object->IsLayoutTableCol() ||
layout_object->IsTableRow() || background_transfers_to_view ||
!compositable_animation) {
DefaultToUnsupportedProperty(unsupported_properties, property,
@@ -356,6 +365,13 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
}
break;
}
+ case CSSPropertyID::kClipPath: {
+ if (!RuntimeEnabledFeatures::CompositeClipPathAnimationEnabled()) {
+ DefaultToUnsupportedProperty(unsupported_properties, property,
+ &reasons);
+ }
+ break;
+ }
case CSSPropertyID::kVariable: {
// Custom properties are supported only in the case of
// OffMainThreadCSSPaintEnabled, and even then only for some specific
@@ -391,11 +407,9 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
break;
}
default:
- // We skip the rest of the loop in this case for two reasons:
- // i. Getting a CompositorElementId below will DCHECK if we pass it
- // an unsupported property.
- // ii. GetCompositorKeyframeValue() will be false so we will
- // accidentally count this as kInvalidAnimationOrEffect as well.
+ // We skip the rest of the loop in this case because
+ // |GetCompositorKeyframeValue()| will be false so we will
+ // accidentally count this as kInvalidAnimationOrEffect as well.
DefaultToUnsupportedProperty(unsupported_properties, property,
&reasons);
continue;
@@ -406,31 +420,14 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
if (!keyframe->GetCompositorKeyframeValue()) {
reasons |= kInvalidAnimationOrEffect;
}
-
- if (CompositedAnimationRequiresProperties(
- property.GetCSSProperty().PropertyID())) {
- if (!paint_artifact_compositor) {
- // TODO(pdr): We should return |kTargetHasInvalidCompositingState|.
- continue;
- } else if (!target_element.GetLayoutObject() ||
- !target_element.GetLayoutObject()
- ->FirstFragment()
- .PaintProperties()) {
- reasons |= kTargetHasInvalidCompositingState;
- } else {
- CompositorElementId target_element_id =
- CompositorElementIdFromUniqueObjectId(
- layout_object->UniqueId(),
- CompositorElementNamespaceForProperty(
- property.GetCSSProperty().PropertyID()));
- DCHECK(target_element_id);
- if (!paint_artifact_compositor->HasComposited(target_element_id))
- reasons |= kTargetHasInvalidCompositingState;
- }
- }
}
}
+ if (CompositorPropertyAnimationsHaveNoEffect(target_element, effect,
+ paint_artifact_compositor)) {
+ reasons |= kCompositorPropertyAnimationsHaveNoEffect;
+ }
+
// TODO: Support multiple transform property animations on the compositor
if (transform_property_count > 1)
reasons |= kMultipleTransformAnimationsOnSameTarget;
@@ -452,6 +449,54 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
return reasons;
}
+bool CompositorAnimations::CompositorPropertyAnimationsHaveNoEffect(
+ const Element& target_element,
+ const EffectModel& effect,
+ const PaintArtifactCompositor* paint_artifact_compositor) {
+ LayoutObject* layout_object = target_element.GetLayoutObject();
+ if (!layout_object || !layout_object->FirstFragment().PaintProperties())
+ return false;
+
+ if (!paint_artifact_compositor) {
+ // TODO(pdr): This should return true. This likely only affects tests.
+ return false;
+ }
+
+ bool any_compositor_properties_missing = false;
+ bool any_compositor_properties_present = false;
+
+ const auto& keyframe_effect = To<KeyframeEffectModelBase>(effect);
+ const auto& groups = keyframe_effect.GetPropertySpecificKeyframeGroups();
+ for (const PropertyHandle& property : groups.Keys()) {
+ if (!CompositedAnimationRequiresProperties(property))
+ continue;
+
+ CompositorElementId target_element_id =
+ CompositorElementIdFromUniqueObjectId(
+ layout_object->UniqueId(),
+ CompositorAnimations::CompositorElementNamespaceForProperty(
+ property.GetCSSProperty().PropertyID()));
+ DCHECK(target_element_id);
+ if (paint_artifact_compositor->HasComposited(target_element_id))
+ any_compositor_properties_present = true;
+ else
+ any_compositor_properties_missing = true;
+ }
+
+ // Because animations are a direct compositing reason for paint properties,
+ // the only case when we wouldn't have compositor paint properties if when
+ // they were optimized out due to not having an effect. An example of this is
+ // hidden animations that do not paint.
+ if (any_compositor_properties_missing) {
+ // Because animations create all properties (crbug.com/900241), we should
+ // either have all properties or be missing all properties.
+ DCHECK(!any_compositor_properties_present);
+ return true;
+ }
+
+ return false;
+}
+
CompositorAnimations::FailureReasons
CompositorAnimations::CheckCanStartElementOnCompositor(
const Element& target_element,
@@ -663,9 +708,20 @@ bool CompositorAnimations::ConvertTimingForCompositor(
DCHECK(animation_playback_rate);
double delay =
animation_playback_rate > 0 ? timing.start_delay.InSecondsF() : 0;
- out.scaled_time_offset =
- -base::TimeDelta::FromSecondsD(delay / animation_playback_rate) +
- time_offset;
+
+ base::TimeDelta scaled_delay =
+ base::TimeDelta::FromSecondsD(delay / animation_playback_rate);
+
+ // Arithmetic operations involving a value that is effectively +/-infinity
+ // result in a value that is +/-infinity or undefined. Check before computing
+ // the scaled time offset to guard against the following:
+ // infinity - infinity or
+ // -infinity + infinity
+ // The result of either of these edge cases is undefined.
+ if (scaled_delay.is_max() || scaled_delay.is_min())
+ return false;
+
+ out.scaled_time_offset = -scaled_delay + time_offset;
// Delay is effectively +/- infinity.
if (out.scaled_time_offset.is_max() || out.scaled_time_offset.is_min())
return false;
@@ -782,9 +838,6 @@ void CompositorAnimations::GetAnimationOnCompositor(
PropertyHandleSet properties = effect.Properties();
DCHECK(!properties.IsEmpty());
for (const auto& property : properties) {
- AtomicString custom_property_name = "";
- CompositorPaintWorkletInput::NativePropertyType native_property_type =
- CompositorPaintWorkletInput::NativePropertyType::kInvalid;
// If the animation duration is infinite, it doesn't make sense to scale
// the keyframe offset, so use a scale of 1.0. This is connected to
// the known issue of how the Web Animations spec handles infinite
@@ -795,31 +848,32 @@ void CompositorAnimations::GetAnimationOnCompositor(
const PropertySpecificKeyframeVector& values =
*effect.GetPropertySpecificKeyframes(property);
- compositor_target_property::Type target_property;
std::unique_ptr<CompositorAnimationCurve> curve;
DCHECK(timing.timing_function);
+ absl::optional<CompositorKeyframeModel::TargetPropertyId>
+ target_property_id = absl::nullopt;
switch (property.GetCSSProperty().PropertyID()) {
case CSSPropertyID::kOpacity: {
- target_property = compositor_target_property::OPACITY;
auto float_curve = std::make_unique<CompositorFloatAnimationCurve>();
AddKeyframesToCurve(*float_curve, values);
float_curve->SetTimingFunction(*timing.timing_function);
float_curve->SetScaledDuration(scale);
curve = std::move(float_curve);
+ target_property_id = CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::OPACITY);
break;
}
case CSSPropertyID::kFilter:
case CSSPropertyID::kBackdropFilter: {
- target_property = compositor_target_property::FILTER;
- if (property.GetCSSProperty().PropertyID() ==
- CSSPropertyID::kBackdropFilter) {
- target_property = compositor_target_property::BACKDROP_FILTER;
- }
auto filter_curve = std::make_unique<CompositorFilterAnimationCurve>();
AddKeyframesToCurve(*filter_curve, values);
filter_curve->SetTimingFunction(*timing.timing_function);
filter_curve->SetScaledDuration(scale);
curve = std::move(filter_curve);
+ target_property_id = CompositorKeyframeModel::TargetPropertyId(
+ property.GetCSSProperty().PropertyID() == CSSPropertyID::kFilter
+ ? compositor_target_property::FILTER
+ : compositor_target_property::BACKDROP_FILTER);
break;
}
case CSSPropertyID::kRotate:
@@ -829,31 +883,35 @@ void CompositorAnimations::GetAnimationOnCompositor(
FloatSize box_size = ComputedStyleUtils::ReferenceBoxForTransform(
*target_element.GetLayoutObject())
.Size();
- target_property = compositor_target_property::TRANSFORM;
auto transform_curve =
std::make_unique<CompositorTransformAnimationCurve>();
AddKeyframesToCurve(*transform_curve, values, box_size);
transform_curve->SetTimingFunction(*timing.timing_function);
transform_curve->SetScaledDuration(scale);
curve = std::move(transform_curve);
+ target_property_id = CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::TRANSFORM);
break;
}
- case CSSPropertyID::kBackgroundColor: {
- native_property_type =
- CompositorPaintWorkletInput::NativePropertyType::kBackgroundColor;
+ case CSSPropertyID::kBackgroundColor:
+ case CSSPropertyID::kClipPath: {
+ CompositorPaintWorkletInput::NativePropertyType native_property_type =
+ property.GetCSSProperty().PropertyID() ==
+ CSSPropertyID::kBackgroundColor
+ ? CompositorPaintWorkletInput::NativePropertyType::
+ kBackgroundColor
+ : CompositorPaintWorkletInput::NativePropertyType::kClipPath;
auto float_curve = std::make_unique<CompositorFloatAnimationCurve>();
- target_property = compositor_target_property::NATIVE_PROPERTY;
AddKeyframesToCurve(*float_curve, values);
float_curve->SetTimingFunction(*timing.timing_function);
float_curve->SetScaledDuration(scale);
curve = std::move(float_curve);
+ target_property_id = CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::NATIVE_PROPERTY, native_property_type);
break;
}
case CSSPropertyID::kVariable: {
DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled());
- custom_property_name = property.CustomPropertyName();
- target_property = compositor_target_property::CSS_CUSTOM_PROPERTY;
-
// Create curve based on the keyframe value type
if (values.front()->GetCompositorKeyframeValue()->IsColor()) {
auto color_curve = std::make_unique<CompositorColorAnimationCurve>();
@@ -868,6 +926,9 @@ void CompositorAnimations::GetAnimationOnCompositor(
float_curve->SetScaledDuration(scale);
curve = std::move(float_curve);
}
+ target_property_id = CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::CSS_CUSTOM_PROPERTY,
+ property.CustomPropertyName().Utf8().data());
break;
}
default:
@@ -875,19 +936,10 @@ void CompositorAnimations::GetAnimationOnCompositor(
continue;
}
DCHECK(curve.get());
-
- std::unique_ptr<CompositorKeyframeModel> keyframe_model;
- if (!custom_property_name.IsEmpty()) {
- keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, target_property, 0, group, std::move(custom_property_name));
- } else if (native_property_type !=
- CompositorPaintWorkletInput::NativePropertyType::kInvalid) {
- keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, target_property, 0, group, native_property_type);
- } else {
- keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, target_property, 0, group);
- }
+ DCHECK(target_property_id.has_value());
+ std::unique_ptr<CompositorKeyframeModel> keyframe_model =
+ std::make_unique<CompositorKeyframeModel>(
+ *curve, 0, group, std::move(target_property_id.value()));
if (start_time)
keyframe_model->SetStartTime(start_time.value());
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 678215237a4..82743a275db 100644
--- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_COMPOSITOR_ANIMATIONS_H_
#include <memory>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/animation/keyframe.h"
#include "third_party/blink/renderer/core/animation/timing.h"
@@ -98,11 +99,15 @@ class CORE_EXPORT CompositorAnimations {
// Cases where the scroll timeline source is not composited.
kTimelineSourceHasInvalidCompositingState = 1 << 16,
+ // Cases where there is an animation of compositor properties but they have
+ // been optimized out so the animation of those properties has no effect.
+ kCompositorPropertyAnimationsHaveNoEffect = 1 << 17,
+
// The maximum number of flags in this enum (excluding itself). New flags
// should increment this number but it should never be decremented because
// the values are used in UMA histograms. It should also be noted that it
// excludes the kNoFailure value.
- kFailureReasonCount = 17,
+ kFailureReasonCount = 18,
};
static FailureReasons CheckCanStartAnimationOnCompositor(
@@ -113,6 +118,10 @@ class CORE_EXPORT CompositorAnimations {
const PaintArtifactCompositor*,
double animation_playback_rate,
PropertyHandleSet* unsupported_properties = nullptr);
+ static bool CompositorPropertyAnimationsHaveNoEffect(
+ const Element& target_element,
+ const EffectModel& effect,
+ const PaintArtifactCompositor*);
static void CancelIncompatibleAnimationsOnCompositor(const Element&,
const Animation&,
const EffectModel&);
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 45174540cfe..353a6c76e7e 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
@@ -52,6 +52,7 @@
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "third_party/blink/renderer/core/css/mock_css_paint_image_generator.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -754,6 +755,11 @@ TEST_P(AnimationCompositorAnimationsTest,
EXPECT_TRUE(
ConvertTimingForCompositor(timing_, compositor_timing_, play_reverse));
EXPECT_DOUBLE_EQ(0.0, compositor_timing_.scaled_time_offset.InSecondsF());
+
+ // Stress test with an effectively infinite start delay.
+ timing_.start_delay = AnimationTimeDelta::FromSecondsD(1e19);
+ EXPECT_FALSE(
+ ConvertTimingForCompositor(timing_, compositor_timing_, play_forward));
}
TEST_P(AnimationCompositorAnimationsTest,
@@ -2339,9 +2345,14 @@ TEST_P(AnimationCompositorAnimationsTest, Fragmented) {
0% { transform: translateX(10px); }
100% { transform: translateX(20px); }
}
+ #target {
+ width: 10px;
+ height: 150px;
+ background: green;
+ }
</style>
<div style="columns: 2; height: 100px">
- <div id="target" style="height: 150px; animation: move 1s infinite">
+ <div id="target" style="animation: move 1s infinite">
</div>
</div>
)HTML");
diff --git a/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc b/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
index fc5d1f41582..8e69843d00c 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
@@ -68,7 +68,8 @@ CompositorKeyframeValue* CompositorKeyframeValueFactory::Create(
return CreateFromTransformProperties(style.Scale(), style.EffectiveZoom(),
nullptr);
}
- case CSSPropertyID::kBackgroundColor: {
+ case CSSPropertyID::kBackgroundColor:
+ case CSSPropertyID::kClipPath: {
return MakeGarbageCollected<CompositorKeyframeDouble>(offset);
}
case CSSPropertyID::kVariable: {
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc b/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc
index 34f54d30029..22dc98e467d 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc
@@ -13,7 +13,7 @@ namespace blink {
CSSAnimation::CSSAnimation(ExecutionContext* execution_context,
AnimationTimeline* timeline,
AnimationEffect* content,
- int animation_index,
+ wtf_size_t animation_index,
const String& animation_name)
: Animation(execution_context, timeline, content),
animation_index_(animation_index),
@@ -60,19 +60,11 @@ void CSSAnimation::setTimeline(AnimationTimeline* timeline) {
ignore_css_timeline_ = true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void CSSAnimation::setStartTime(const V8CSSNumberish* start_time,
ExceptionState& exception_state) {
PlayStateTransitionScope scope(*this);
Animation::setStartTime(start_time, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void CSSAnimation::setStartTime(CSSNumberish start_time_ms,
- ExceptionState& exception_state) {
- PlayStateTransitionScope scope(*this);
- Animation::setStartTime(start_time_ms, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AnimationEffect::EventDelegate* CSSAnimation::CreateEventDelegate(
Element* target,
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation.h b/chromium/third_party/blink/renderer/core/animation/css/css_animation.h
index ad68b5b8c37..a531dac2167 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation.h
@@ -19,7 +19,7 @@ class CORE_EXPORT CSSAnimation : public Animation {
CSSAnimation(ExecutionContext*,
AnimationTimeline*,
AnimationEffect*,
- int animation_index,
+ wtf_size_t animation_index,
const String& animation_name);
bool IsCSSAnimation() const final { return true; }
@@ -28,7 +28,7 @@ class CORE_EXPORT CSSAnimation : public Animation {
Element* OwningElement() const override { return owning_element_; }
const String& animationName() const { return animation_name_; }
- int AnimationIndex() const { return animation_index_; }
+ wtf_size_t AnimationIndex() const { return animation_index_; }
void SetAnimationIndex(wtf_size_t absolute_position) {
animation_index_ = absolute_position;
}
@@ -51,12 +51,8 @@ class CORE_EXPORT CSSAnimation : public Animation {
void play(ExceptionState& = ASSERT_NO_EXCEPTION) override;
void reverse(ExceptionState& = ASSERT_NO_EXCEPTION) override;
void setTimeline(AnimationTimeline*) override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setStartTime(const V8CSSNumberish* start_time,
ExceptionState& exception_state) override;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setStartTime(CSSNumberish, ExceptionState&) override;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// When set, subsequent changes to animation-play-state no longer affect the
// play state.
@@ -98,7 +94,7 @@ class CORE_EXPORT CSSAnimation : public Animation {
// animation_index_ represents the absolute position of an animation within
// the same owning element. This index helps resolve the animation ordering
// when comparing two animations with the same owning element.
- int animation_index_;
+ wtf_size_t animation_index_;
AtomicString animation_name_;
// When set, the web-animation API is overruling the animation-play-state
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.cc b/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.cc
index 8fd81d08efe..fcbaa038ca2 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.cc
@@ -17,14 +17,10 @@ void CSSAnimationUpdate::Copy(const CSSAnimationUpdate& update) {
new_animations_ = update.NewAnimations();
animations_with_updates_ = update.AnimationsWithUpdates();
new_transitions_ = update.NewTransitions();
- active_interpolations_for_custom_animations_ =
- update.ActiveInterpolationsForCustomAnimations();
- active_interpolations_for_standard_animations_ =
- update.ActiveInterpolationsForStandardAnimations();
- active_interpolations_for_custom_transitions_ =
- update.ActiveInterpolationsForCustomTransitions();
- active_interpolations_for_standard_transitions_ =
- update.ActiveInterpolationsForStandardTransitions();
+ active_interpolations_for_animations_ =
+ update.ActiveInterpolationsForAnimations();
+ active_interpolations_for_transitions_ =
+ update.ActiveInterpolationsForTransitions();
cancelled_animation_indices_ = update.CancelledAnimationIndices();
animation_indices_with_pause_toggled_ =
update.AnimationIndicesWithPauseToggled();
@@ -37,10 +33,8 @@ void CSSAnimationUpdate::Clear() {
new_animations_.clear();
animations_with_updates_.clear();
new_transitions_.clear();
- active_interpolations_for_custom_animations_.clear();
- active_interpolations_for_standard_animations_.clear();
- active_interpolations_for_custom_transitions_.clear();
- active_interpolations_for_standard_transitions_.clear();
+ active_interpolations_for_animations_.clear();
+ active_interpolations_for_transitions_.clear();
cancelled_animation_indices_.clear();
animation_indices_with_pause_toggled_.clear();
cancelled_transitions_.clear();
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h b/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h
index d2143017e86..024f65b5583 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_UPDATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_UPDATE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
#include "third_party/blink/renderer/core/animation/effect_stack.h"
#include "third_party/blink/renderer/core/animation/inert_effect.h"
@@ -29,7 +28,7 @@ class NewCSSAnimation {
public:
NewCSSAnimation(AtomicString name,
size_t name_index,
- size_t position_index,
+ wtf_size_t position_index,
const InertEffect& effect,
Timing timing,
StyleRuleKeyframes* style_rule,
@@ -53,7 +52,7 @@ class NewCSSAnimation {
AtomicString name;
size_t name_index;
- size_t position_index;
+ wtf_size_t position_index;
Member<const InertEffect> effect;
Timing timing;
Member<StyleRuleKeyframes> style_rule;
@@ -114,6 +113,8 @@ class CORE_EXPORT CSSAnimationUpdate final {
public:
CSSAnimationUpdate();
+ CSSAnimationUpdate(const CSSAnimationUpdate&) = delete;
+ CSSAnimationUpdate& operator=(const CSSAnimationUpdate&) = delete;
~CSSAnimationUpdate();
void Copy(const CSSAnimationUpdate&);
@@ -210,58 +211,35 @@ class CORE_EXPORT CSSAnimationUpdate final {
return finished_transitions_;
}
- void AdoptActiveInterpolationsForCustomAnimations(
+ void AdoptActiveInterpolationsForAnimations(
ActiveInterpolationsMap& new_map) {
- new_map.swap(active_interpolations_for_custom_animations_);
+ new_map.swap(active_interpolations_for_animations_);
}
- void AdoptActiveInterpolationsForStandardAnimations(
+ void AdoptActiveInterpolationsForTransitions(
ActiveInterpolationsMap& new_map) {
- new_map.swap(active_interpolations_for_standard_animations_);
+ new_map.swap(active_interpolations_for_transitions_);
}
- void AdoptActiveInterpolationsForCustomTransitions(
- ActiveInterpolationsMap& new_map) {
- new_map.swap(active_interpolations_for_custom_transitions_);
- }
- void AdoptActiveInterpolationsForStandardTransitions(
- ActiveInterpolationsMap& new_map) {
- new_map.swap(active_interpolations_for_standard_transitions_);
- }
- const ActiveInterpolationsMap& ActiveInterpolationsForCustomAnimations()
- const {
- return active_interpolations_for_custom_animations_;
- }
- ActiveInterpolationsMap& ActiveInterpolationsForCustomAnimations() {
- return active_interpolations_for_custom_animations_;
+ const ActiveInterpolationsMap& ActiveInterpolationsForAnimations() const {
+ return active_interpolations_for_animations_;
}
- const ActiveInterpolationsMap& ActiveInterpolationsForStandardAnimations()
- const {
- return active_interpolations_for_standard_animations_;
+ ActiveInterpolationsMap& ActiveInterpolationsForAnimations() {
+ return active_interpolations_for_animations_;
}
- ActiveInterpolationsMap& ActiveInterpolationsForStandardAnimations() {
- return active_interpolations_for_standard_animations_;
- }
- const ActiveInterpolationsMap& ActiveInterpolationsForCustomTransitions()
- const {
- return active_interpolations_for_custom_transitions_;
- }
- const ActiveInterpolationsMap& ActiveInterpolationsForStandardTransitions()
- const {
- return active_interpolations_for_standard_transitions_;
+ const ActiveInterpolationsMap& ActiveInterpolationsForTransitions() const {
+ return active_interpolations_for_transitions_;
}
- bool IsEmpty() const {
- return new_animations_.IsEmpty() &&
- cancelled_animation_indices_.IsEmpty() &&
- suppressed_animations_.IsEmpty() &&
- animation_indices_with_pause_toggled_.IsEmpty() &&
- animations_with_updates_.IsEmpty() && new_transitions_.IsEmpty() &&
- cancelled_transitions_.IsEmpty() &&
- finished_transitions_.IsEmpty() &&
- active_interpolations_for_custom_animations_.IsEmpty() &&
- active_interpolations_for_standard_animations_.IsEmpty() &&
- active_interpolations_for_custom_transitions_.IsEmpty() &&
- active_interpolations_for_standard_transitions_.IsEmpty() &&
- updated_compositor_keyframes_.IsEmpty();
+ bool IsEmpty() const { return !HasUpdates() && !HasActiveInterpolations(); }
+
+ bool HasUpdates() const {
+ return !new_animations_.IsEmpty() ||
+ !cancelled_animation_indices_.IsEmpty() ||
+ !suppressed_animations_.IsEmpty() ||
+ !animation_indices_with_pause_toggled_.IsEmpty() ||
+ !animations_with_updates_.IsEmpty() || !new_transitions_.IsEmpty() ||
+ !cancelled_transitions_.IsEmpty() ||
+ !finished_transitions_.IsEmpty() ||
+ !updated_compositor_keyframes_.IsEmpty();
}
void Trace(Visitor* visitor) const {
@@ -270,13 +248,16 @@ class CORE_EXPORT CSSAnimationUpdate final {
visitor->Trace(suppressed_animations_);
visitor->Trace(animations_with_updates_);
visitor->Trace(updated_compositor_keyframes_);
- visitor->Trace(active_interpolations_for_custom_animations_);
- visitor->Trace(active_interpolations_for_standard_animations_);
- visitor->Trace(active_interpolations_for_custom_transitions_);
- visitor->Trace(active_interpolations_for_standard_transitions_);
+ visitor->Trace(active_interpolations_for_animations_);
+ visitor->Trace(active_interpolations_for_transitions_);
}
private:
+ bool HasActiveInterpolations() const {
+ return !active_interpolations_for_animations_.IsEmpty() ||
+ !active_interpolations_for_transitions_.IsEmpty();
+ }
+
// Order is significant since it defines the order in which new animations
// will be started. Note that there may be multiple animations present
// with the same name, due to the way in which we split up animations with
@@ -292,13 +273,10 @@ class CORE_EXPORT CSSAnimationUpdate final {
HashSet<PropertyHandle> cancelled_transitions_;
HashSet<PropertyHandle> finished_transitions_;
- ActiveInterpolationsMap active_interpolations_for_custom_animations_;
- ActiveInterpolationsMap active_interpolations_for_standard_animations_;
- ActiveInterpolationsMap active_interpolations_for_custom_transitions_;
- ActiveInterpolationsMap active_interpolations_for_standard_transitions_;
+ ActiveInterpolationsMap active_interpolations_for_animations_;
+ ActiveInterpolationsMap active_interpolations_for_transitions_;
friend class PendingAnimationUpdate;
- DISALLOW_COPY_AND_ASSIGN(CSSAnimationUpdate);
};
} // namespace blink
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 37c670acca9..0bc89d41ee9 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
@@ -63,6 +63,7 @@
#include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/css/resolver/css_to_style_map.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
@@ -86,7 +87,7 @@
namespace blink {
-using PropertySet = HashSet<const CSSProperty*>;
+using PropertySet = HashSet<CSSPropertyName>;
namespace {
@@ -116,11 +117,12 @@ StringKeyframeVector ProcessKeyframesRule(
keyframe->SetEasing(default_timing_function);
const CSSPropertyValueSet& properties = style_keyframe->Properties();
for (unsigned j = 0; j < properties.PropertyCount(); j++) {
- // TODO(crbug.com/980160): Remove access to static Variable instance.
- const CSSProperty& property =
- CSSProperty::Get(properties.PropertyAt(j).Id());
+ CSSPropertyValueSet::PropertyReference property_reference =
+ properties.PropertyAt(j);
+ CSSPropertyRef ref(property_reference.Name(), document);
+ const CSSProperty& property = ref.GetProperty();
if (property.PropertyID() == CSSPropertyID::kAnimationTimingFunction) {
- const CSSValue& value = properties.PropertyAt(j).Value();
+ const CSSValue& value = property_reference.Value();
scoped_refptr<TimingFunction> timing_function;
if (value.IsInheritedValue() && parent_style->Animations()) {
timing_function = parent_style->Animations()->TimingFunctionList()[0];
@@ -137,8 +139,8 @@ StringKeyframeVector ProcessKeyframesRule(
const CSSProperty& physical_property =
property.ResolveDirectionAwareProperty(text_direction,
writing_mode);
- keyframe->SetCSSPropertyValue(physical_property,
- properties.PropertyAt(j).Value());
+ const CSSPropertyName& name = physical_property.GetCSSPropertyName();
+ keyframe->SetCSSPropertyValue(name, property_reference.Value());
}
}
keyframes.push_back(keyframe);
@@ -315,25 +317,26 @@ StringKeyframeEffectModel* CreateKeyframeEffectModel(
// to animated properties.
StringKeyframe* keyframe = keyframes[target_index];
for (const auto& property : rule_keyframe->Properties()) {
- const CSSProperty& css_property = property.GetCSSProperty();
+ CSSPropertyName property_name = property.GetCSSPropertyName();
// Since processing keyframes in reverse order, skipping properties that
// have already been inserted prevents overwriting a later merged
// keyframe.
- if (current_offset_properties.Contains(&css_property))
+ if (current_offset_properties.Contains(property_name))
continue;
if (source_index != target_index) {
keyframe->SetCSSPropertyValue(
- css_property, rule_keyframe->CssPropertyValue(property));
+ property.GetCSSPropertyName(),
+ rule_keyframe->CssPropertyValue(property));
}
- current_offset_properties.insert(&css_property);
- animated_properties.insert(&css_property);
+ current_offset_properties.insert(property_name);
+ animated_properties.insert(property_name);
if (keyframe_offset == 0)
- start_properties.insert(&css_property);
+ start_properties.insert(property_name);
else if (keyframe_offset == 1)
- end_properties.insert(&css_property);
+ end_properties.insert(property_name);
}
}
@@ -405,9 +408,9 @@ AnimationTimeDelta StartTimeFromDelay(AnimationTimeDelta start_delay) {
// Timing functions for computing elapsed time of an event.
AnimationTimeDelta IntervalStart(const AnimationEffect& effect) {
- AnimationTimeDelta start_delay = effect.SpecifiedTiming().start_delay;
+ AnimationTimeDelta start_delay = effect.NormalizedTiming().start_delay;
const AnimationTimeDelta active_duration =
- effect.SpecifiedTiming().ActiveDuration();
+ effect.NormalizedTiming().active_duration;
// This fixes a problem where start_delay could be -0
if (!start_delay.is_zero()) {
start_delay = -start_delay;
@@ -416,10 +419,10 @@ AnimationTimeDelta IntervalStart(const AnimationEffect& effect) {
}
AnimationTimeDelta IntervalEnd(const AnimationEffect& effect) {
- const AnimationTimeDelta start_delay = effect.SpecifiedTiming().start_delay;
- const AnimationTimeDelta end_delay = effect.SpecifiedTiming().end_delay;
+ const AnimationTimeDelta start_delay = effect.NormalizedTiming().start_delay;
+ const AnimationTimeDelta end_delay = effect.NormalizedTiming().end_delay;
const AnimationTimeDelta active_duration =
- effect.SpecifiedTiming().ActiveDuration();
+ effect.NormalizedTiming().active_duration;
const AnimationTimeDelta target_effect_end =
std::max(start_delay + active_duration + end_delay, AnimationTimeDelta());
return std::max(std::min(target_effect_end - start_delay, active_duration),
@@ -434,41 +437,12 @@ AnimationTimeDelta IterationElapsedTime(const AnimationEffect& effect,
: current_iteration;
const double iteration_start = effect.SpecifiedTiming().iteration_start;
const AnimationTimeDelta iteration_duration =
- effect.SpecifiedTiming().IterationDuration();
+ effect.NormalizedTiming().iteration_duration;
return iteration_duration * (iteration_boundary - iteration_start);
}
-CSSScrollTimeline* CreateCSSScrollTimeline(
- Document& document,
- CSSScrollTimeline::Options&& options) {
- if (!options.IsValid())
- return nullptr;
- auto* scroll_timeline =
- MakeGarbageCollected<CSSScrollTimeline>(&document, std::move(options));
- // It's is not allowed for a style resolve to create timelines that
- // needs timing updates (i.e. AnimationTimeline::NeedsAnimationTimingUpdate()
- // must return false). Servicing animations after creation preserves this
- // invariant by ensuring the last-update time of the timeline is equal to
- // the current time.
- scroll_timeline->ServiceAnimations(kTimingUpdateOnDemand);
- return scroll_timeline;
-}
-
-CSSScrollTimeline* FindMatchingCachedTimeline(
- Document& document,
- const AtomicString& name,
- const CSSScrollTimeline::Options& options) {
- auto* cached_timeline = DynamicTo<CSSScrollTimeline>(
- document.GetDocumentAnimations().FindCachedCSSScrollTimeline(name));
- if (cached_timeline && cached_timeline->Matches(options))
- return cached_timeline;
- return nullptr;
-}
-
AnimationTimeline* ComputeTimeline(Element* element,
- const StyleNameOrKeyword& timeline_name,
- StyleRuleScrollTimeline* rule,
- AnimationTimeline* existing_timeline) {
+ const StyleNameOrKeyword& timeline_name) {
Document& document = element->GetDocument();
if (timeline_name.IsKeyword()) {
if (timeline_name.GetKeyword() == CSSValueID::kAuto)
@@ -476,37 +450,7 @@ AnimationTimeline* ComputeTimeline(Element* element,
DCHECK_EQ(timeline_name.GetKeyword(), CSSValueID::kNone);
return nullptr;
}
- if (rule) {
- CSSScrollTimeline::Options options(document, *rule);
-
- const AtomicString& name = timeline_name.GetName().GetValue();
- // When multiple animations refer to the same @scroll-timeline, the same
- // CSSScrollTimeline instance should be shared.
- if (auto* timeline = FindMatchingCachedTimeline(document, name, options))
- return timeline;
- // When the incoming options match the existing timeline (associated with
- // an existing animation), we can continue to use the existing timeline,
- // since creating a new timeline from the options would just yield an
- // identical timeline.
- if (auto* timeline = DynamicTo<CSSScrollTimeline>(existing_timeline)) {
- if (timeline->Matches(options))
- return existing_timeline;
- }
- if (auto* timeline =
- CreateCSSScrollTimeline(document, std::move(options))) {
- document.GetDocumentAnimations().CacheCSSScrollTimeline(*timeline);
- return timeline;
- }
- }
- return nullptr;
-}
-
-StyleRuleScrollTimeline* FindScrollTimelineRule(
- Document& document,
- const StyleNameOrKeyword& timeline_name) {
- if (timeline_name.IsKeyword())
- return nullptr;
- return document.GetStyleEngine().FindScrollTimelineRule(
+ return document.GetStyleEngine().FindScrollTimeline(
timeline_name.GetName().GetValue());
}
@@ -708,9 +652,6 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
const StyleNameOrKeyword& timeline_name = animation_data->GetTimeline(i);
- StyleRuleScrollTimeline* scroll_timeline_rule =
- FindScrollTimelineRule(element.GetDocument(), timeline_name);
-
const RunningAnimation* existing_animation = nullptr;
wtf_size_t existing_animation_index = 0;
@@ -753,10 +694,8 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
toggle_pause_state ? animation->Paused() : animation->Playing();
AnimationTimeline* timeline = existing_animation->Timeline();
- if (!is_animation_style_change && !animation->GetIgnoreCSSTimeline()) {
- timeline = ComputeTimeline(&element, timeline_name,
- scroll_timeline_rule, timeline);
- }
+ if (!is_animation_style_change && !animation->GetIgnoreCSSTimeline())
+ timeline = ComputeTimeline(&element, timeline_name);
if (keyframes_rule != existing_animation->style_rule ||
keyframes_rule->Version() !=
@@ -795,9 +734,7 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
}
} else {
DCHECK(!is_animation_style_change);
- AnimationTimeline* timeline =
- ComputeTimeline(&element, timeline_name, scroll_timeline_rule,
- nullptr /* existing_timeline */);
+ AnimationTimeline* timeline = ComputeTimeline(&element, timeline_name);
absl::optional<TimelinePhase> inherited_phase;
absl::optional<AnimationTimeDelta> inherited_time =
AnimationTimeDelta();
@@ -891,15 +828,20 @@ void CSSAnimations::SnapshotCompositorKeyframes(
}
void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
- previous_active_interpolations_for_custom_animations_.clear();
- previous_active_interpolations_for_standard_animations_.clear();
+ previous_active_interpolations_for_animations_.clear();
if (pending_update_.IsEmpty())
return;
- previous_active_interpolations_for_custom_animations_.swap(
- pending_update_.ActiveInterpolationsForCustomAnimations());
- previous_active_interpolations_for_standard_animations_.swap(
- pending_update_.ActiveInterpolationsForStandardAnimations());
+ previous_active_interpolations_for_animations_.swap(
+ pending_update_.ActiveInterpolationsForAnimations());
+
+ if (!pending_update_.HasUpdates()) {
+ ClearPendingUpdate();
+ return;
+ }
+
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled())
+ element->SetNeedsAnimationStyleRecalc();
for (wtf_size_t paused_index :
pending_update_.AnimationIndicesWithPauseToggled()) {
@@ -933,6 +875,14 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
}
running_animations_[entry.index]->Update(entry);
+
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) {
+ // If the timing was updated, we need to update the animation to get the
+ // correct result the next time we resolve style. This is not needed
+ // if CSSIsolatedAnimationUpdates is disabled, since we're "faking" an
+ // updated animation with InertEffect.
+ entry.animation->Update(kTimingUpdateOnDemand);
+ }
}
const Vector<wtf_size_t>& cancelled_indices =
@@ -1006,14 +956,37 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
}
}
+ HashSet<PropertyHandle> suppressed_transitions;
+
if (!pending_update_.NewTransitions().IsEmpty()) {
element->GetDocument()
.GetDocumentAnimations()
.IncrementTrasitionGeneration();
+
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) {
+ // We generally do not start transitions if there's an animation
+ // running for the same property. This is mainly handled by
+ // CanCalculateTransitionUpdateForProperty. However, that function
+ // will not take into account newly started or newly updated animations,
+ // hence we need to check against an updated set of affected properties
+ // from the EffectStack whenever an animation is created/updated.
+ if (auto* element_animations = element->GetElementAnimations()) {
+ if (!pending_update_.NewAnimations().IsEmpty() ||
+ !pending_update_.AnimationsWithUpdates().IsEmpty()) {
+ suppressed_transitions =
+ element_animations->GetEffectStack().AffectedProperties(
+ KeyframeEffect::kDefaultPriority);
+ }
+ }
+ }
}
for (const auto& entry : pending_update_.NewTransitions()) {
const CSSAnimationUpdate::NewTransition* new_transition = entry.value;
+ const PropertyHandle& property = new_transition->property;
+
+ if (suppressed_transitions.Contains(property))
+ continue;
RunningTransition* running_transition =
MakeGarbageCollected<RunningTransition>();
@@ -1024,7 +997,6 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
running_transition->reversing_shortening_factor =
new_transition->reversing_shortening_factor;
- const PropertyHandle& property = new_transition->property;
const InertEffect* inert_animation = new_transition->effect.Get();
TransitionEventDelegate* event_delegate =
MakeGarbageCollected<TransitionEventDelegate>(element, property);
@@ -1044,14 +1016,8 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
// Set the current time as the start time for retargeted transitions
if (retargeted_compositor_transitions.Contains(property)) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(element->GetDocument().Timeline().currentTime(),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish current_time;
- element->GetDocument().Timeline().currentTime(current_time);
- animation->setStartTime(current_time);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
animation->Update(kTimingUpdateOnDemand);
running_transition->animation = animation;
@@ -1060,34 +1026,30 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
ClearPendingUpdate();
}
-void CSSAnimations::CalculateTransitionUpdateForProperty(
+bool CSSAnimations::CanCalculateTransitionUpdateForProperty(
+ TransitionUpdateState& state,
+ const PropertyHandle& property) {
+ // TODO(crbug.com/1226772): We should transition if an !important property
+ // changes even when an animation is running.
+ if (state.update.ActiveInterpolationsForAnimations().Contains(property) ||
+ (state.animating_element.GetElementAnimations() &&
+ state.animating_element.GetElementAnimations()
+ ->CssAnimations()
+ .previous_active_interpolations_for_animations_.Contains(
+ property))) {
+ return false;
+ }
+ return true;
+}
+
+void CSSAnimations::CalculateTransitionUpdateForPropertyHandle(
TransitionUpdateState& state,
const PropertyHandle& property,
size_t transition_index) {
state.listed_properties.insert(property);
- // FIXME: We should transition if an !important property changes even when an
- // animation is running, but this is a bit hard to do with the current
- // applyMatchedProperties system.
- if (property.IsCSSCustomProperty()) {
- if (state.update.ActiveInterpolationsForCustomAnimations().Contains(
- property) ||
- (state.animating_element.GetElementAnimations() &&
- state.animating_element.GetElementAnimations()
- ->CssAnimations()
- .previous_active_interpolations_for_custom_animations_.Contains(
- property))) {
- return;
- }
- } else if (state.update.ActiveInterpolationsForStandardAnimations().Contains(
- property) ||
- (state.animating_element.GetElementAnimations() &&
- state.animating_element.GetElementAnimations()
- ->CssAnimations()
- .previous_active_interpolations_for_standard_animations_
- .Contains(property))) {
+ if (!CanCalculateTransitionUpdateForProperty(state, property))
return;
- }
const RunningTransition* interrupted_transition = nullptr;
if (state.active_transitions) {
@@ -1139,24 +1101,14 @@ void CSSAnimations::CalculateTransitionUpdateForProperty(
// Lazy evaluation of the before change style. We only need to update where
// we are transitioning from if the final destination is changing.
if (!state.before_change_style) {
- ElementAnimations* element_animations =
- state.animating_element.GetElementAnimations();
- if (element_animations) {
- const ComputedStyle* base_style = element_animations->BaseComputedStyle();
- if (base_style) {
- state.before_change_style =
- CalculateBeforeChangeStyle(state.animating_element, *base_style);
- }
- }
- // Use the style from the previous frame if no base style is found.
- // Elements that have not been animated will not have a base style.
- // Elements that were previously animated, but where all previously running
- // animations have stopped may also be missing a base style. In both cases,
- // the old style is equivalent to the base computed style.
- if (!state.before_change_style) {
- state.before_change_style =
- CalculateBeforeChangeStyle(state.animating_element, state.old_style);
- }
+ // By calling GetBaseComputedStyleOrThis, we're using the style from the
+ // previous frame if no base style is found. Elements that have not been
+ // animated will not have a base style. Elements that were previously
+ // animated, but where all previously running animations have stopped may
+ // also be missing a base style. In both cases, the old style is equivalent
+ // to the base computed style.
+ state.before_change_style = CalculateBeforeChangeStyle(
+ state.animating_element, *state.old_style.GetBaseComputedStyleOrThis());
}
if (ComputedValuesEqual(property, *state.before_change_style, state.style)) {
@@ -1271,19 +1223,37 @@ void CSSAnimations::CalculateTransitionUpdateForProperty(
->IsAnimationStyleChange());
}
+void CSSAnimations::CalculateTransitionUpdateForProperty(
+ TransitionUpdateState& state,
+ const CSSTransitionData::TransitionProperty& transition_property,
+ size_t transition_index,
+ const ComputedStyle& style) {
+ switch (transition_property.property_type) {
+ case CSSTransitionData::kTransitionUnknownProperty:
+ CalculateTransitionUpdateForCustomProperty(state, transition_property,
+ transition_index);
+ break;
+ case CSSTransitionData::kTransitionKnownProperty:
+ CalculateTransitionUpdateForStandardProperty(state, transition_property,
+ transition_index, style);
+ break;
+ default:
+ break;
+ }
+}
+
void CSSAnimations::CalculateTransitionUpdateForCustomProperty(
TransitionUpdateState& state,
const CSSTransitionData::TransitionProperty& transition_property,
size_t transition_index) {
- if (transition_property.property_type !=
- CSSTransitionData::kTransitionUnknownProperty) {
- return;
- }
+ DCHECK_EQ(transition_property.property_type,
+ CSSTransitionData::kTransitionUnknownProperty);
+
if (!CSSVariableParser::IsValidVariableName(
transition_property.property_string)) {
return;
}
- CalculateTransitionUpdateForProperty(
+ CalculateTransitionUpdateForPropertyHandle(
state, PropertyHandle(transition_property.property_string),
transition_index);
}
@@ -1293,10 +1263,8 @@ void CSSAnimations::CalculateTransitionUpdateForStandardProperty(
const CSSTransitionData::TransitionProperty& transition_property,
size_t transition_index,
const ComputedStyle& style) {
- if (transition_property.property_type !=
- CSSTransitionData::kTransitionKnownProperty) {
- return;
- }
+ DCHECK_EQ(transition_property.property_type,
+ CSSTransitionData::kTransitionKnownProperty);
CSSPropertyID resolved_id =
ResolveCSSPropertyID(transition_property.unresolved_property);
@@ -1321,13 +1289,12 @@ void CSSAnimations::CalculateTransitionUpdateForStandardProperty(
continue;
}
- CalculateTransitionUpdateForProperty(state, property_handle,
- transition_index);
+ CalculateTransitionUpdateForPropertyHandle(state, property_handle,
+ transition_index);
}
}
void CSSAnimations::CalculateTransitionUpdate(CSSAnimationUpdate& update,
- PropertyPass property_pass,
Element& animating_element,
const ComputedStyle& style) {
if (animating_element.GetDocument().FinishingOrIsPrinting())
@@ -1367,34 +1334,21 @@ void CSSAnimations::CalculateTransitionUpdate(CSSAnimationUpdate& update,
if (transition_property.unresolved_property == CSSPropertyID::kAll) {
any_transition_had_transition_all = true;
}
- if (property_pass == PropertyPass::kCustom) {
- CalculateTransitionUpdateForCustomProperty(state, transition_property,
- transition_index);
- } else {
- DCHECK_EQ(property_pass, PropertyPass::kStandard);
- CalculateTransitionUpdateForStandardProperty(
- state, transition_property, transition_index, style);
- }
+ CalculateTransitionUpdateForProperty(state, transition_property,
+ transition_index, style);
}
} else if (active_transitions && active_transitions->size()) {
// !transition_data implies transition: all 0s
any_transition_had_transition_all = true;
- if (property_pass == PropertyPass::kStandard) {
CSSTransitionData::TransitionProperty default_property(
CSSPropertyID::kAll);
- CalculateTransitionUpdateForStandardProperty(state, default_property, 0,
- style);
- }
+ CalculateTransitionUpdateForProperty(state, default_property, 0, style);
}
}
if (active_transitions) {
for (const auto& entry : *active_transitions) {
const PropertyHandle& property = entry.key;
- if (property.IsCSSCustomProperty() !=
- (property_pass == PropertyPass::kCustom)) {
- continue;
- }
if (!any_transition_had_transition_all && !animation_style_recalc &&
!listed_properties.Contains(property)) {
update.CancelTransition(property);
@@ -1404,8 +1358,7 @@ void CSSAnimations::CalculateTransitionUpdate(CSSAnimationUpdate& update,
}
}
- CalculateTransitionActiveInterpolations(update, property_pass,
- animating_element);
+ CalculateTransitionActiveInterpolations(update, animating_element);
}
scoped_refptr<const ComputedStyle> CSSAnimations::CalculateBeforeChangeStyle(
@@ -1435,32 +1388,16 @@ scoped_refptr<const ComputedStyle> CSSAnimations::CalculateBeforeChangeStyle(
// Sample animations and add to the interpolatzions map.
for (Animation* animation : animations) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* current_time_numberish = animation->currentTime();
if (!current_time_numberish)
continue;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish current_time_numberish;
- animation->currentTime(current_time_numberish);
- if (current_time_numberish.IsNull())
- continue;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// CSSNumericValue is not yet supported, verify that it is not used
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(!current_time_numberish->IsCSSNumericValue());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DCHECK(!current_time_numberish.IsCSSNumericValue());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<AnimationTimeDelta> current_time =
AnimationTimeDelta::FromMillisecondsD(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- current_time_numberish->GetAsDouble()
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- current_time_numberish.GetAsDouble()
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- );
+ current_time_numberish->GetAsDouble());
auto* effect = DynamicTo<KeyframeEffect>(animation->effect());
if (!effect)
@@ -1526,9 +1463,8 @@ bool IsFontAffectingPropertyHandle(const PropertyHandle& property) {
// the case of effect collisions.
// Example: Both 'color' and 'svg-color' set the color on ComputedStyle but are
// considered distinct properties in the ActiveInterpolationsMap.
-bool IsStandardPropertyHandle(const PropertyHandle& property) {
- return (property.IsCSSProperty() && !property.IsCSSCustomProperty()) ||
- property.IsPresentationAttribute();
+bool IsCSSPropertyHandle(const PropertyHandle& property) {
+ return property.IsCSSProperty() || property.IsPresentationAttribute();
}
void AdoptActiveAnimationInterpolations(
@@ -1536,18 +1472,19 @@ void AdoptActiveAnimationInterpolations(
CSSAnimationUpdate& update,
const HeapVector<Member<const InertEffect>>* new_animations,
const HeapHashSet<Member<const Animation>>* suppressed_animations) {
- ActiveInterpolationsMap custom_interpolations(
- EffectStack::ActiveInterpolations(
- effect_stack, new_animations, suppressed_animations,
- KeyframeEffect::kDefaultPriority, IsCustomPropertyHandle));
- update.AdoptActiveInterpolationsForCustomAnimations(custom_interpolations);
-
- ActiveInterpolationsMap standard_interpolations(
- EffectStack::ActiveInterpolations(
- effect_stack, new_animations, suppressed_animations,
- KeyframeEffect::kDefaultPriority, IsStandardPropertyHandle));
- update.AdoptActiveInterpolationsForStandardAnimations(
- standard_interpolations);
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) {
+ // The new/suppressed animations options are not used by
+ // CSSIsolatedAnimationUpdates. Eventually we want to avoid setting
+ // that up in the first place, but while this is behind a flag, the least
+ // intrusive approach is to just nullify here.
+ new_animations = nullptr;
+ suppressed_animations = nullptr;
+ }
+
+ ActiveInterpolationsMap interpolations(EffectStack::ActiveInterpolations(
+ effect_stack, new_animations, suppressed_animations,
+ KeyframeEffect::kDefaultPriority, IsCSSPropertyHandle));
+ update.AdoptActiveInterpolationsForAnimations(interpolations);
}
} // namespace
@@ -1578,22 +1515,8 @@ void CSSAnimations::CalculateAnimationActiveInterpolations(
&update.SuppressedAnimations());
}
-namespace {
-
-EffectStack::PropertyHandleFilter PropertyFilter(
- CSSAnimations::PropertyPass property_pass) {
- if (property_pass == CSSAnimations::PropertyPass::kCustom) {
- return IsCustomPropertyHandle;
- }
- DCHECK_EQ(property_pass, CSSAnimations::PropertyPass::kStandard);
- return IsStandardPropertyHandle;
-}
-
-} // namespace
-
void CSSAnimations::CalculateTransitionActiveInterpolations(
CSSAnimationUpdate& update,
- PropertyPass property_pass,
const Element& animating_element) {
ElementAnimations* element_animations =
animating_element.GetElementAnimations();
@@ -1605,7 +1528,7 @@ void CSSAnimations::CalculateTransitionActiveInterpolations(
update.CancelledTransitions().IsEmpty()) {
active_interpolations_for_transitions = EffectStack::ActiveInterpolations(
effect_stack, nullptr, nullptr, KeyframeEffect::kTransitionPriority,
- PropertyFilter(property_pass));
+ IsCSSPropertyHandle);
} else {
HeapVector<Member<const InertEffect>> new_transitions;
for (const auto& entry : update.NewTransitions())
@@ -1623,15 +1546,20 @@ void CSSAnimations::CalculateTransitionActiveInterpolations(
}
}
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) {
+ // Eventually we should avoid building these in the first place,
+ // but for now it's less intrusive to clear them after-the-fact.
+ new_transitions.clear();
+ cancelled_animations.clear();
+ }
+
active_interpolations_for_transitions = EffectStack::ActiveInterpolations(
effect_stack, &new_transitions, &cancelled_animations,
- KeyframeEffect::kTransitionPriority, PropertyFilter(property_pass));
+ KeyframeEffect::kTransitionPriority, IsCSSPropertyHandle);
}
const ActiveInterpolationsMap& animations =
- property_pass == PropertyPass::kCustom
- ? update.ActiveInterpolationsForCustomAnimations()
- : update.ActiveInterpolationsForStandardAnimations();
+ update.ActiveInterpolationsForAnimations();
// Properties being animated by animations don't get values from transitions
// applied.
if (!animations.IsEmpty() &&
@@ -1640,14 +1568,8 @@ void CSSAnimations::CalculateTransitionActiveInterpolations(
active_interpolations_for_transitions.erase(entry.key);
}
- if (property_pass == PropertyPass::kCustom) {
- update.AdoptActiveInterpolationsForCustomTransitions(
- active_interpolations_for_transitions);
- } else {
- DCHECK_EQ(property_pass, PropertyPass::kStandard);
- update.AdoptActiveInterpolationsForStandardTransitions(
- active_interpolations_for_transitions);
- }
+ update.AdoptActiveInterpolationsForTransitions(
+ active_interpolations_for_transitions);
}
EventTarget* CSSAnimations::AnimationEventDelegate::GetEventTarget() const {
@@ -1764,7 +1686,7 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
if (previous_phase_ == Timing::kPhaseNone) {
EnqueueEvent(
event_type_names::kTransitionrun,
- StartTimeFromDelay(animation_node.SpecifiedTiming().start_delay));
+ StartTimeFromDelay(animation_node.NormalizedTiming().start_delay));
}
}
@@ -1775,14 +1697,14 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
previous_phase_ == Timing::kPhaseBefore)) {
EnqueueEvent(
event_type_names::kTransitionstart,
- StartTimeFromDelay(animation_node.SpecifiedTiming().start_delay));
+ StartTimeFromDelay(animation_node.NormalizedTiming().start_delay));
} else if ((current_phase == Timing::kPhaseActive ||
current_phase == Timing::kPhaseBefore) &&
previous_phase_ == Timing::kPhaseAfter) {
// If the transition is progressing backwards it is considered to have
// started at the end position.
EnqueueEvent(event_type_names::kTransitionstart,
- animation_node.SpecifiedTiming().IterationDuration());
+ animation_node.NormalizedTiming().iteration_duration);
}
}
@@ -1792,7 +1714,7 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
previous_phase_ == Timing::kPhaseBefore ||
previous_phase_ == Timing::kPhaseNone)) {
EnqueueEvent(event_type_names::kTransitionend,
- animation_node.SpecifiedTiming().IterationDuration());
+ animation_node.NormalizedTiming().iteration_duration);
} else if (current_phase == Timing::kPhaseBefore &&
(previous_phase_ == Timing::kPhaseActive ||
previous_phase_ == Timing::kPhaseAfter)) {
@@ -1800,7 +1722,7 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
// ended at the start position.
EnqueueEvent(
event_type_names::kTransitionend,
- StartTimeFromDelay(animation_node.SpecifiedTiming().start_delay));
+ StartTimeFromDelay(animation_node.NormalizedTiming().start_delay));
}
}
@@ -1811,10 +1733,9 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
// "active time of the animation at the moment it was cancelled,
// calculated using a fill mode of both".
absl::optional<AnimationTimeDelta> cancel_active_time =
- CalculateActiveTime(animation_node.SpecifiedTiming().ActiveDuration(),
+ CalculateActiveTime(animation_node.NormalizedTiming(),
Timing::FillMode::BOTH,
- animation_node.LocalTime(), previous_phase_,
- animation_node.SpecifiedTiming());
+ animation_node.LocalTime(), previous_phase_);
// Being the FillMode::BOTH the only possibility to get a null
// cancel_active_time is that previous_phase_ is kPhaseNone. This cannot
// happen because we know that current_phase == kPhaseNone and
@@ -1953,8 +1874,7 @@ void CSSAnimations::Trace(Visitor* visitor) const {
visitor->Trace(transitions_);
visitor->Trace(pending_update_);
visitor->Trace(running_animations_);
- visitor->Trace(previous_active_interpolations_for_standard_animations_);
- visitor->Trace(previous_active_interpolations_for_custom_animations_);
+ visitor->Trace(previous_active_interpolations_for_animations_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animations.h b/chromium/third_party/blink/renderer/core/animation/css/css_animations.h
index cf367221edc..ccc8b993dde 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animations.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATIONS_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_update.h"
#include "third_party/blink/renderer/core/animation/css/css_transition_data.h"
@@ -57,6 +56,8 @@ class CORE_EXPORT CSSAnimations final {
public:
CSSAnimations();
+ CSSAnimations(const CSSAnimations&) = delete;
+ CSSAnimations& operator=(const CSSAnimations&) = delete;
static const StylePropertyShorthand& PropertiesForTransitionAll();
static bool IsAnimationAffectingProperty(const CSSProperty&);
@@ -91,10 +92,7 @@ class CORE_EXPORT CSSAnimations final {
const AtomicString& animation_name,
const AnimationEffect::EventDelegate* old_event_delegate);
- // Specifies whether to process custom or standard CSS properties.
- enum class PropertyPass { kCustom, kStandard };
static void CalculateTransitionUpdate(CSSAnimationUpdate&,
- PropertyPass,
Element& animating_element,
const ComputedStyle&);
@@ -173,9 +171,7 @@ class CORE_EXPORT CSSAnimations final {
CSSAnimationUpdate pending_update_;
- ActiveInterpolationsMap previous_active_interpolations_for_custom_animations_;
- ActiveInterpolationsMap
- previous_active_interpolations_for_standard_animations_;
+ ActiveInterpolationsMap previous_active_interpolations_for_animations_;
struct TransitionUpdateState {
STACK_ALLOCATED();
@@ -192,6 +188,12 @@ class CORE_EXPORT CSSAnimations final {
const CSSTransitionData* transition_data;
};
+ static void CalculateTransitionUpdateForProperty(
+ TransitionUpdateState&,
+ const CSSTransitionData::TransitionProperty&,
+ size_t transition_index,
+ const ComputedStyle&);
+
static void CalculateTransitionUpdateForCustomProperty(
TransitionUpdateState&,
const CSSTransitionData::TransitionProperty&,
@@ -203,16 +205,20 @@ class CORE_EXPORT CSSAnimations final {
size_t transition_index,
const ComputedStyle&);
- static void CalculateTransitionUpdateForProperty(TransitionUpdateState&,
- const PropertyHandle&,
- size_t transition_index);
+ static bool CanCalculateTransitionUpdateForProperty(
+ TransitionUpdateState& state,
+ const PropertyHandle& property);
+
+ static void CalculateTransitionUpdateForPropertyHandle(
+ TransitionUpdateState&,
+ const PropertyHandle&,
+ size_t transition_index);
static void CalculateAnimationActiveInterpolations(
CSSAnimationUpdate&,
const Element& animating_element);
static void CalculateTransitionActiveInterpolations(
CSSAnimationUpdate&,
- PropertyPass,
const Element& animating_element);
// The before-change style is defined as the computed values of all properties
@@ -289,8 +295,6 @@ class CORE_EXPORT CSSAnimations final {
PropertyHandle property_;
Timing::Phase previous_phase_;
};
-
- DISALLOW_COPY_AND_ASSIGN(CSSAnimations);
};
template <>
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
index 1e2f5ab8eb8..cd3c10158db 100644
--- 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
@@ -350,37 +350,20 @@ TEST_F(CSSAnimationsCompositorSyncTest, SetStartTime) {
Animation* animation = GetAnimation();
int compositor_group = animation->CompositorGroup();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* start_time = animation->startTime();
V8CSSNumberish* current_time = animation->currentTime();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish start_time, current_time;
- animation->startTime(start_time);
- animation->currentTime(current_time);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Partially rewind the animation via setStartTime.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* new_start_time = MakeGarbageCollected<V8CSSNumberish>(
start_time->GetAsDouble() + (current_time->GetAsDouble() / 2));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish new_start_time = CSSNumberish::FromDouble(
- start_time.GetAsDouble() + (current_time.GetAsDouble() / 2));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(new_start_time, ASSERT_NO_EXCEPTION);
UpdateAllLifecyclePhasesForTest();
// Verify blink updates.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
current_time = animation->currentTime();
EXPECT_TRUE(current_time->IsDouble());
EXPECT_NEAR(250, current_time->GetAsDouble(), kTimeToleranceMilliseconds);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->currentTime(current_time);
- EXPECT_TRUE(current_time.IsDouble());
- EXPECT_NEAR(250, current_time.GetAsDouble(), kTimeToleranceMilliseconds);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_NEAR(0.75, element_->GetComputedStyle()->Opacity(), kTolerance);
// Compositor animation needs to restart and will have a new compositor group.
@@ -411,25 +394,14 @@ TEST_F(CSSAnimationsCompositorSyncTest, SetCurrentTime) {
int compositor_group = animation->CompositorGroup();
// Advance current time.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(750),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(750), ASSERT_NO_EXCEPTION);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
UpdateAllLifecyclePhasesForTest();
// Verify blink updates.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* current_time = animation->currentTime();
EXPECT_TRUE(current_time->IsDouble());
EXPECT_NEAR(750, current_time->GetAsDouble(), kTimeToleranceMilliseconds);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish current_time;
- animation->currentTime(current_time);
- EXPECT_TRUE(current_time.IsDouble());
- EXPECT_NEAR(750, current_time.GetAsDouble(), kTimeToleranceMilliseconds);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_NEAR(0.25, element_->GetComputedStyle()->Opacity(), kTolerance);
// Compositor animation needs to restart and will have a new compositor group.
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc b/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc
index 5729b43432a..8bc0e717866 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc
@@ -78,16 +78,11 @@ void ResolveComputedValues(Element* element, StringKeyframe* keyframe) {
keyframe->RemoveCustomCSSProperty(property);
} else if (property.IsCSSProperty()) {
const CSSValue& value = keyframe->CssPropertyValue(property);
- const CSSPropertyName property_name =
- property.IsCSSCustomProperty()
- ? CSSPropertyName(property.CustomPropertyName())
- : CSSPropertyName(property.GetCSSProperty().PropertyID());
+ const CSSPropertyName property_name = property.GetCSSPropertyName();
const CSSValue* computed_value =
StyleResolver::ComputeValue(element, property_name, value);
- if (computed_value) {
- keyframe->SetCSSPropertyValue(property.GetCSSProperty(),
- *computed_value);
- }
+ if (computed_value)
+ keyframe->SetCSSPropertyValue(property_name, *computed_value);
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.cc b/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.cc
index 854e05f9707..6f0d6cc1ce1 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/css/css_id_selector_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -49,14 +50,15 @@ const cssvalue::CSSIdSelectorValue* GetIdSelectorValue(const CSSValue* value) {
return nullptr;
}
-Element* ComputeScrollSource(Document& document, const CSSValue* value) {
+absl::optional<Element*> ComputeScrollSource(Document& document,
+ const CSSValue* value) {
if (const auto* id = GetIdSelectorValue(value))
return document.getElementById(id->Id());
if (IsNone(value))
return nullptr;
DCHECK(!value || IsAuto(value));
// TODO(crbug.com/1189101): Respond when the scrolling element changes.
- return document.ScrollingElementNoLayout();
+ return absl::nullopt;
}
Element* ComputeElementOffsetTarget(Document& document, const CSSValue* value) {
@@ -157,18 +159,21 @@ class ElementReferenceObserver : public IdTargetObserver {
const AtomicString& id,
CSSScrollTimeline* timeline)
: IdTargetObserver(document->GetIdTargetObserverRegistry(), id),
+ document_(document),
timeline_(timeline) {}
void Trace(Visitor* visitor) const override {
visitor->Trace(timeline_);
+ visitor->Trace(document_);
IdTargetObserver::Trace(visitor);
}
private:
void IdTargetChanged() override {
if (timeline_)
- timeline_->InvalidateEffectTargetStyle();
+ document_->GetStyleEngine().ScrollTimelineInvalidated(*timeline_);
}
+ Member<Document> document_;
WeakMember<CSSScrollTimeline> timeline_;
};
@@ -217,9 +222,8 @@ CSSScrollTimeline::CSSScrollTimeline(Document* document, Options&& options)
options.source_,
options.direction_,
std::move(options.offsets_),
- *options.time_range_),
+ options.time_range_),
rule_(options.rule_) {
- DCHECK(options.IsValid());
DCHECK(rule_);
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.h b/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.h
index 013b7f5cc43..b946ac3b870 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline.h
@@ -25,13 +25,10 @@ class CORE_EXPORT CSSScrollTimeline : public ScrollTimeline {
public:
Options(Document&, StyleRuleScrollTimeline&);
- // TODO(crbug.com/1097041): Support 'auto' value.
- bool IsValid() const { return time_range_.has_value(); }
-
private:
friend class CSSScrollTimeline;
- Element* source_;
+ absl::optional<Element*> source_;
ScrollTimeline::ScrollDirection direction_;
HeapVector<Member<ScrollTimelineOffset>> offsets_;
absl::optional<double> time_range_;
@@ -42,6 +39,8 @@ class CORE_EXPORT CSSScrollTimeline : public ScrollTimeline {
const AtomicString& Name() const;
+ StyleRuleScrollTimeline* GetRule() const { return rule_; }
+
bool Matches(const Options&) const;
// AnimationTimeline implementation.
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc b/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
index 8de8d872b2c..3b3c46ed417 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
@@ -32,6 +32,12 @@ class CSSScrollTimelineTest : public PageTestBase,
DocumentAnimations& GetDocumentAnimations() const {
return GetDocument().GetDocumentAnimations();
}
+
+ void SimulateFrame() {
+ auto new_time = GetAnimationClock().CurrentTime() +
+ base::TimeDelta::FromMilliseconds(100);
+ GetPage().Animator().ServiceScriptedAnimations(new_time);
+ }
};
TEST_F(CSSScrollTimelineTest, IdObserverElementRemoval) {
@@ -64,11 +70,13 @@ TEST_F(CSSScrollTimelineTest, IdObserverElementRemoval) {
ASSERT_TRUE(element2);
element1->remove();
+ SimulateFrame();
UpdateAllLifecyclePhasesForTest();
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_TRUE(HasObservers("scroller"));
element2->remove();
+ SimulateFrame();
UpdateAllLifecyclePhasesForTest();
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_FALSE(HasObservers("scroller"));
@@ -282,20 +290,26 @@ namespace {
class AnimationTriggeringDelegate : public ResizeObserver::Delegate {
public:
- explicit AnimationTriggeringDelegate(Element* element) : element_(element) {}
+ explicit AnimationTriggeringDelegate(Element* style_element)
+ : style_element_(style_element) {}
void OnResize(
const HeapVector<Member<ResizeObserverEntry>>& entries) override {
- element_->setAttribute(blink::html_names::kClassAttr, "animate");
+ style_element_->setTextContent(R"CSS(
+ @scroll-timeline timeline {
+ source: selector(#scroller);
+ time-range: 10s;
+ }
+ )CSS");
}
void Trace(Visitor* visitor) const override {
ResizeObserver::Delegate::Trace(visitor);
- visitor->Trace(element_);
+ visitor->Trace(style_element_);
}
private:
- Member<Element> element_;
+ Member<Element> style_element_;
};
} // namespace
@@ -307,10 +321,6 @@ TEST_F(CSSScrollTimelineTest, ResizeObserverTriggeredTimelines) {
from { width: 100px; }
to { width: 100px; }
}
- @scroll-timeline timeline {
- source: selector(#scroller);
- time-range: 10s;
- }
#scroller {
height: 100px;
overflow: scroll;
@@ -320,8 +330,6 @@ TEST_F(CSSScrollTimelineTest, ResizeObserverTriggeredTimelines) {
}
#element {
width: 1px;
- }
- #element.animate {
animation: anim 10s timeline;
}
</style>
@@ -338,12 +346,16 @@ TEST_F(CSSScrollTimelineTest, ResizeObserverTriggeredTimelines) {
scroller->setAttribute(blink::html_names::kIdAttr, "scroller");
scroller->AppendChild(MakeGarbageCollected<HTMLDivElement>(GetDocument()));
+ Element* style = MakeGarbageCollected<HTMLStyleElement>(GetDocument(),
+ CreateElementFlags());
+
Element* main = GetDocument().getElementById("main");
ASSERT_TRUE(main);
+ main->AppendChild(style);
main->AppendChild(element);
main->AppendChild(scroller);
- auto* delegate = MakeGarbageCollected<AnimationTriggeringDelegate>(element);
+ auto* delegate = MakeGarbageCollected<AnimationTriggeringDelegate>(style);
ResizeObserver* observer =
ResizeObserver::Create(GetDocument().domWindow(), delegate);
observer->observe(element);
diff --git a/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
index ff399b71577..5112f4fdd2c 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
@@ -99,6 +99,7 @@ CSSColorInterpolationType::MaybeCreateInterpolableColor(const CSSValue& value) {
return CreateInterpolableColor(identifier_value->GetValueID());
}
+// Spec link: https://www.w3.org/TR/css-color-4/#interpolation-alpha
Color CSSColorInterpolationType::GetRGBA(const InterpolableValue& value) {
const InterpolableList& list = To<InterpolableList>(value);
DCHECK_GE(list.length(), kAlpha);
@@ -107,6 +108,9 @@ Color CSSColorInterpolationType::GetRGBA(const InterpolableValue& value) {
const InterpolableValue& current_value = *(list.Get(i));
color[i] = To<InterpolableNumber>(current_value).Value();
}
+ // Prevent dividing 0
+ if (color[kAlpha] == 0)
+ return Color::kTransparent;
return Color(MakeRGBA(std::round(color[kRed] / color[kAlpha]),
std::round(color[kGreen] / color[kAlpha]),
std::round(color[kBlue] / color[kAlpha]),
diff --git a/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc b/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc
index 3cc0c4ee5f2..03540ef2d51 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc
@@ -29,4 +29,10 @@ TEST(CSSColorInterpolationTypeTest, GetRGBA3) {
*CSSColorInterpolationType::CreateInterpolableColor(color)));
}
+TEST(CSSColorInterpolationTypeTest, GetRGBA4) {
+ Color color(35, 140, 10, 0);
+ EXPECT_EQ(Color(MakeRGBA(0, 0, 0, 0)),
+ CSSColorInterpolationType::GetRGBA(
+ *CSSColorInterpolationType::CreateInterpolableColor(color)));
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
index bfe74bd5d21..aa886124e9b 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
@@ -15,7 +15,7 @@ namespace blink {
InterpolationValue CSSCustomListInterpolationType::MaybeConvertNeutral(
const InterpolationValue& underlying,
ConversionCheckers& conversion_checkers) const {
- size_t underlying_length =
+ wtf_size_t underlying_length =
UnderlyingLengthChecker::GetUnderlyingLength(underlying);
conversion_checkers.push_back(
std::make_unique<UnderlyingLengthChecker>(underlying_length));
@@ -46,7 +46,7 @@ InterpolationValue CSSCustomListInterpolationType::MaybeConvertValue(
ConversionCheckers null_checkers;
return ListInterpolationFunctions::CreateList(
- list->length(), [this, list, state, &null_checkers](size_t index) {
+ list->length(), [this, list, state, &null_checkers](wtf_size_t index) {
return inner_interpolation_type_->MaybeConvertValue(
list->Item(index), state, null_checkers);
});
@@ -77,7 +77,7 @@ const CSSValue* CSSCustomListInterpolationType::CreateCSSValue(
DCHECK(!non_interpolable_list ||
interpolable_list.length() == non_interpolable_list->length());
- for (size_t i = 0; i < interpolable_list.length(); ++i) {
+ for (wtf_size_t i = 0; i < interpolable_list.length(); ++i) {
const NonInterpolableValue* non_interpolable_single_value =
non_interpolable_list ? non_interpolable_list->Get(i) : nullptr;
list->Append(*inner_interpolation_type_->CreateCSSValue(
diff --git a/chromium/third_party/blink/renderer/core/animation/css_font_size_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_font_size_interpolation_type.cc
index 1d47beba58d..805d46ffbe6 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_font_size_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_font_size_interpolation_type.cc
@@ -10,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/animation/interpolable_length.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
@@ -108,18 +109,22 @@ InterpolationValue CSSFontSizeInterpolationType::MaybeConvertValue(
const CSSValue& value,
const StyleResolverState* state,
ConversionCheckers& conversion_checkers) const {
+ DCHECK(state);
+
std::unique_ptr<InterpolableValue> result =
InterpolableLength::MaybeConvertCSSValue(value);
if (result)
return InterpolationValue(std::move(result));
- auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
- if (!identifier_value)
- return nullptr;
+ if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ return MaybeConvertKeyword(identifier_value->GetValueID(), *state,
+ conversion_checkers);
+ }
- DCHECK(state);
- return MaybeConvertKeyword(identifier_value->GetValueID(), *state,
- conversion_checkers);
+ if (auto* system_font = DynamicTo<cssvalue::CSSPendingSystemFontValue>(value))
+ return ConvertFontSize(system_font->ResolveFontSize(&state->GetDocument()));
+
+ return nullptr;
}
InterpolationValue
diff --git a/chromium/third_party/blink/renderer/core/animation/css_font_stretch_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_font_stretch_interpolation_type.cc
index 3dc54b266e6..a9c686f621f 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_font_stretch_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_font_stretch_interpolation_type.cc
@@ -8,7 +8,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
-#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -62,39 +62,8 @@ InterpolationValue CSSFontStretchInterpolationType::MaybeConvertValue(
const CSSValue& value,
const StyleResolverState* state,
ConversionCheckers& conversion_checkers) const {
- if (auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value)) {
- return CreateFontStretchValue(
- FontSelectionValue(primitive_value->GetFloatValue()));
- }
-
- const auto& identifier_value = To<CSSIdentifierValue>(value);
- CSSValueID keyword = identifier_value.GetValueID();
-
- switch (keyword) {
- case CSSValueID::kInvalid:
- return nullptr;
- case CSSValueID::kUltraCondensed:
- return CreateFontStretchValue(UltraCondensedWidthValue());
- case CSSValueID::kExtraCondensed:
- return CreateFontStretchValue(ExtraCondensedWidthValue());
- case CSSValueID::kCondensed:
- return CreateFontStretchValue(CondensedWidthValue());
- case CSSValueID::kSemiCondensed:
- return CreateFontStretchValue(SemiCondensedWidthValue());
- case CSSValueID::kNormal:
- return CreateFontStretchValue(NormalWidthValue());
- case CSSValueID::kSemiExpanded:
- return CreateFontStretchValue(SemiExpandedWidthValue());
- case CSSValueID::kExpanded:
- return CreateFontStretchValue(ExpandedWidthValue());
- case CSSValueID::kExtraExpanded:
- return CreateFontStretchValue(ExtraExpandedWidthValue());
- case CSSValueID::kUltraExpanded:
- return CreateFontStretchValue(UltraExpandedWidthValue());
- default:
- NOTREACHED();
- return nullptr;
- }
+ return CreateFontStretchValue(
+ StyleBuilderConverterBase::ConvertFontStretch(value));
}
InterpolationValue
diff --git a/chromium/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc
index 9870c5ec5db..0fd1672cb72 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc
@@ -8,7 +8,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
-#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -62,40 +62,18 @@ InterpolationValue CSSFontWeightInterpolationType::MaybeConvertValue(
const CSSValue& value,
const StyleResolverState* state,
ConversionCheckers& conversion_checkers) const {
- if (auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value)) {
- return CreateFontWeightValue(
- FontSelectionValue(primitive_value->GetFloatValue()));
- }
-
- const auto& identifier_value = To<CSSIdentifierValue>(value);
- CSSValueID keyword = identifier_value.GetValueID();
-
- switch (keyword) {
- case CSSValueID::kInvalid:
- return nullptr;
- case CSSValueID::kNormal:
- return CreateFontWeightValue(NormalWeightValue());
- case CSSValueID::kBold:
- return CreateFontWeightValue(BoldWeightValue());
-
- case CSSValueID::kBolder:
- case CSSValueID::kLighter: {
- DCHECK(state);
- FontSelectionValue inherited_font_weight =
- state->ParentStyle()->GetFontWeight();
+ DCHECK(state);
+ FontSelectionValue inherited_font_weight =
+ state->ParentStyle()->GetFontWeight();
+ if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ CSSValueID keyword = identifier_value->GetValueID();
+ if (keyword == CSSValueID::kBolder || keyword == CSSValueID::kLighter) {
conversion_checkers.push_back(
std::make_unique<InheritedFontWeightChecker>(inherited_font_weight));
- if (keyword == CSSValueID::kBolder) {
- return CreateFontWeightValue(
- FontDescription::BolderWeight(inherited_font_weight));
- }
- return CreateFontWeightValue(
- FontDescription::LighterWeight(inherited_font_weight));
}
- default:
- NOTREACHED();
- return nullptr;
}
+ return CreateFontWeightValue(StyleBuilderConverterBase::ConvertFontWeight(
+ value, inherited_font_weight));
}
InterpolationValue
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 9281ca47be8..5af9aada6ec 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
@@ -79,7 +79,7 @@ class InheritedCustomPropertyChecker
return DataEquivalent(inherited_value_.Get(), inherited_value);
}
- const AtomicString& name_;
+ AtomicString name_;
const bool is_inherited_property_;
Persistent<const CSSValue> inherited_value_;
Persistent<const CSSValue> initial_value_;
@@ -89,17 +89,18 @@ class ResolvedRegisteredCustomPropertyChecker
: public InterpolationType::ConversionChecker {
public:
ResolvedRegisteredCustomPropertyChecker(
- const CSSCustomPropertyDeclaration& declaration,
+ const PropertyHandle& property,
+ const CSSValue& value,
scoped_refptr<CSSVariableData> resolved_tokens)
- : declaration_(declaration),
+ : property_(property),
+ value_(value),
resolved_tokens_(std::move(resolved_tokens)) {}
private:
bool IsValid(const InterpolationEnvironment& environment,
const InterpolationValue&) const final {
const auto& css_environment = To<CSSInterpolationEnvironment>(environment);
- const CSSValue* resolved = css_environment.Resolve(
- PropertyHandle(declaration_->GetName()), declaration_);
+ const CSSValue* resolved = css_environment.Resolve(property_, value_);
scoped_refptr<CSSVariableData> resolved_tokens;
if (const auto* decl = DynamicTo<CSSCustomPropertyDeclaration>(resolved))
resolved_tokens = decl->Value();
@@ -107,7 +108,8 @@ class ResolvedRegisteredCustomPropertyChecker
return DataEquivalent(resolved_tokens, resolved_tokens_);
}
- Persistent<const CSSCustomPropertyDeclaration> declaration_;
+ PropertyHandle property_;
+ Persistent<const CSSValue> value_;
scoped_refptr<CSSVariableData> resolved_tokens_;
};
@@ -210,8 +212,7 @@ InterpolationValue CSSInterpolationType::MaybeConvertCustomPropertyDeclaration(
const auto& css_environment = To<CSSInterpolationEnvironment>(environment);
const StyleResolverState& state = css_environment.GetState();
- const AtomicString& name = declaration.GetName();
- DCHECK_EQ(GetProperty().CustomPropertyName(), name);
+ AtomicString name = GetProperty().CustomPropertyName();
const CSSValue* value = &declaration;
value = css_environment.Resolve(GetProperty(), value);
@@ -228,7 +229,7 @@ InterpolationValue CSSInterpolationType::MaybeConvertCustomPropertyDeclaration(
if (resolved_declaration != &declaration) {
conversion_checkers.push_back(
std::make_unique<ResolvedRegisteredCustomPropertyChecker>(
- declaration, resolved_declaration->Value()));
+ GetProperty(), declaration, resolved_declaration->Value()));
}
}
@@ -333,7 +334,7 @@ void CSSInterpolationType::ApplyCustomPropertyValue(
// TODO(andruud): Avoid making the CSSCustomPropertyDeclaration by allowing
// any CSSValue in CustomProperty::ApplyValue.
const CSSValue* value = MakeGarbageCollected<CSSCustomPropertyDeclaration>(
- property.CustomPropertyName(), std::move(variable_data));
+ std::move(variable_data));
StyleBuilder::ApplyProperty(GetProperty().GetCSSPropertyName(), state,
ScopedCSSValue(*value, nullptr));
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc
index d38c2150c27..8e9a29f6bc5 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc
@@ -42,8 +42,7 @@ const CSSValue* CSSNumberInterpolationType::CreateCSSValue(
const StyleResolverState&) const {
double number = To<InterpolableNumber>(value).Value();
return CSSNumericLiteralValue::Create(
- round_to_integer_ ? round(number) : number,
- CSSPrimitiveValue::UnitType::kNumber);
+ round_to_integer_ ? round(number) : number, UnitType());
}
InterpolationValue CSSNumberInterpolationType::CreateNumberValue(
@@ -111,12 +110,10 @@ void CSSNumberInterpolationType::ApplyStandardPropertyValue(
CssProperty(), To<InterpolableNumber>(interpolable_value).Value());
if (!NumberPropertyFunctions::SetNumber(CssProperty(), *state.Style(),
clamped_number)) {
- StyleBuilder::ApplyProperty(
- GetProperty().GetCSSProperty(), state,
- ScopedCSSValue(
- *CSSNumericLiteralValue::Create(
- clamped_number, CSSPrimitiveValue::UnitType::kNumber),
- nullptr));
+ StyleBuilder::ApplyProperty(GetProperty().GetCSSProperty(), state,
+ ScopedCSSValue(*CSSNumericLiteralValue::Create(
+ clamped_number, UnitType()),
+ nullptr));
}
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.h
index fbdd09a8c4b..128637e9b5e 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/css_number_interpolation_type.h
@@ -43,6 +43,11 @@ class CORE_EXPORT CSSNumberInterpolationType : public CSSInterpolationType {
const StyleResolverState*,
ConversionCheckers&) const final;
+ CSSPrimitiveValue::UnitType UnitType() const {
+ return round_to_integer_ ? CSSPrimitiveValue::UnitType::kInteger
+ : CSSPrimitiveValue::UnitType::kNumber;
+ }
+
const bool round_to_integer_;
};
diff --git a/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
index 6dc26c3fa20..9c763e03db6 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/animation/interpolable_transform_list.h"
#include "third_party/blink/renderer/core/animation/length_units_checker.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
@@ -24,7 +23,7 @@ namespace blink {
namespace {
InterpolationValue ConvertTransform(TransformOperations&& transform) {
return InterpolationValue(
- InterpolableTransformList::Create(std::move(transform)));
+ std::make_unique<InterpolableTransformList>(std::move(transform)));
}
InterpolationValue ConvertTransform(const TransformOperations& transform) {
diff --git a/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc
index 226e20ff0e8..90b0708a8b0 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc
@@ -21,20 +21,21 @@ namespace blink {
class CycleChecker : public InterpolationType::ConversionChecker {
public:
- CycleChecker(const CSSCustomPropertyDeclaration& declaration,
+ CycleChecker(const PropertyHandle& property,
+ const CSSValue& value,
bool cycle_detected)
- : declaration_(declaration), cycle_detected_(cycle_detected) {}
+ : property_(property), value_(value), cycle_detected_(cycle_detected) {}
private:
bool IsValid(const InterpolationEnvironment& environment,
const InterpolationValue&) const final {
const auto& css_environment = To<CSSInterpolationEnvironment>(environment);
- bool cycle_detected = !css_environment.Resolve(
- PropertyHandle(declaration_->GetName()), declaration_);
+ bool cycle_detected = !css_environment.Resolve(property_, value_);
return cycle_detected == cycle_detected_;
}
- Persistent<const CSSCustomPropertyDeclaration> declaration_;
+ PropertyHandle property_;
+ Persistent<const CSSValue> value_;
const bool cycle_detected_;
};
@@ -56,7 +57,6 @@ InterpolationValue CSSVarCycleInterpolationType::MaybeConvertSingle(
ConversionCheckers& conversion_checkers) const {
const auto& declaration = *To<CSSCustomPropertyDeclaration>(
To<CSSPropertySpecificKeyframe>(keyframe).Value());
- DCHECK_EQ(GetProperty().CustomPropertyName(), declaration.GetName());
if ((!declaration.Value() ||
!declaration.Value()->NeedsVariableResolution()) &&
!declaration.IsRevert()) {
@@ -65,9 +65,10 @@ InterpolationValue CSSVarCycleInterpolationType::MaybeConvertSingle(
const auto& css_environment = To<CSSInterpolationEnvironment>(environment);
- bool cycle_detected = !css_environment.Resolve(GetProperty(), &declaration);
+ PropertyHandle property = GetProperty();
+ bool cycle_detected = !css_environment.Resolve(property, &declaration);
conversion_checkers.push_back(
- std::make_unique<CycleChecker>(declaration, cycle_detected));
+ std::make_unique<CycleChecker>(property, declaration, cycle_detected));
return cycle_detected ? CreateCycleDetectedValue() : nullptr;
}
@@ -117,10 +118,9 @@ void CSSVarCycleInterpolationType::Apply(
StyleBuilder::ApplyProperty(
GetProperty().GetCSSPropertyName(),
To<CSSInterpolationEnvironment>(environment).GetState(),
- ScopedCSSValue(
- *MakeGarbageCollected<CSSCustomPropertyDeclaration>(
- GetProperty().CustomPropertyName(), CSSValueID::kUnset),
- nullptr));
+ ScopedCSSValue(*MakeGarbageCollected<CSSCustomPropertyDeclaration>(
+ CSSValueID::kUnset),
+ nullptr));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/document_animations.cc b/chromium/third_party/blink/renderer/core/animation/document_animations.cc
index c7ed01c694e..6e5b4f97038 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_animations.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
#include "third_party/blink/renderer/core/animation/css/css_scroll_timeline.h"
+#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/pending_animations.h"
#include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
@@ -110,9 +111,13 @@ void DocumentAnimations::UpdateAnimationTimingIfNeeded() {
void DocumentAnimations::UpdateAnimations(
DocumentLifecycle::LifecycleState required_lifecycle_state,
- const PaintArtifactCompositor* paint_artifact_compositor) {
+ const PaintArtifactCompositor* paint_artifact_compositor,
+ bool compositor_properties_updated) {
DCHECK(document_->Lifecycle().GetState() >= required_lifecycle_state);
+ if (compositor_properties_updated)
+ MarkPendingIfCompositorPropertyAnimationChanges(paint_artifact_compositor);
+
if (document_->GetPendingAnimations().Update(paint_artifact_compositor)) {
DCHECK(document_->View());
document_->View()->ScheduleAnimation();
@@ -123,6 +128,14 @@ void DocumentAnimations::UpdateAnimations(
timeline->ScheduleNextService();
}
+void DocumentAnimations::MarkPendingIfCompositorPropertyAnimationChanges(
+ const PaintArtifactCompositor* paint_artifact_compositor) {
+ for (auto& timeline : timelines_) {
+ timeline->MarkPendingIfCompositorPropertyAnimationChanges(
+ paint_artifact_compositor);
+ }
+}
+
size_t DocumentAnimations::GetAnimationsCount() {
wtf_size_t total_animations_count = 0;
if (document_->View()) {
@@ -169,21 +182,40 @@ void DocumentAnimations::ValidateTimelines() {
unvalidated_timelines_.clear();
}
-void DocumentAnimations::CacheCSSScrollTimeline(CSSScrollTimeline& timeline) {
- // We cache the least seen CSSScrollTimeline for a given name.
- cached_css_timelines_.Set(timeline.Name(), &timeline);
+DocumentAnimations::AllowAnimationUpdatesScope::AllowAnimationUpdatesScope(
+ DocumentAnimations& document_animations,
+ bool value)
+ : allow_(&document_animations.allow_animation_updates_,
+ document_animations.allow_animation_updates_.value_or(true) &&
+ value) {}
+
+void DocumentAnimations::AddElementWithPendingAnimationUpdate(
+ Element& element) {
+ DCHECK(AnimationUpdatesAllowed());
+ elements_with_pending_updates_.insert(&element);
}
-CSSScrollTimeline* DocumentAnimations::FindCachedCSSScrollTimeline(
- const AtomicString& name) {
- return To<CSSScrollTimeline>(cached_css_timelines_.at(name));
+void DocumentAnimations::ApplyPendingElementUpdates() {
+ HeapHashSet<WeakMember<Element>> pending;
+ std::swap(pending, elements_with_pending_updates_);
+
+ for (auto& element : pending) {
+ ElementAnimations* element_animations = element->GetElementAnimations();
+ if (!element_animations)
+ continue;
+ element_animations->CssAnimations().MaybeApplyPendingUpdate(element.Get());
+ }
+
+ DCHECK(elements_with_pending_updates_.IsEmpty())
+ << "MaybeApplyPendingUpdate must not mark any elements as having a "
+ "pending update";
}
void DocumentAnimations::Trace(Visitor* visitor) const {
visitor->Trace(document_);
visitor->Trace(timelines_);
visitor->Trace(unvalidated_timelines_);
- visitor->Trace(cached_css_timelines_);
+ visitor->Trace(elements_with_pending_updates_);
}
void DocumentAnimations::GetAnimationsTargetingTreeScope(
diff --git a/chromium/third_party/blink/renderer/core/animation/document_animations.h b/chromium/third_party/blink/renderer/core/animation/document_animations.h
index 5c74f71615f..b57c9b62760 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/document_animations.h
@@ -31,6 +31,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_DOCUMENT_ANIMATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_DOCUMENT_ANIMATIONS_H_
+#include "base/auto_reset.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/platform/heap/member.h"
@@ -38,7 +40,6 @@
namespace blink {
class AnimationTimeline;
-class CSSScrollTimeline;
class Document;
class PaintArtifactCompositor;
@@ -64,7 +65,8 @@ class CORE_EXPORT DocumentAnimations final
// both composited and non-composited animations.
void UpdateAnimations(
DocumentLifecycle::LifecycleState required_lifecycle_state,
- const PaintArtifactCompositor* paint_artifact_compositor);
+ const PaintArtifactCompositor*,
+ bool compositor_properties_updated);
size_t GetAnimationsCount();
@@ -88,8 +90,39 @@ class CORE_EXPORT DocumentAnimations final
// https://github.com/w3c/csswg-drafts/issues/5261
void ValidateTimelines();
- void CacheCSSScrollTimeline(CSSScrollTimeline&);
- CSSScrollTimeline* FindCachedCSSScrollTimeline(const AtomicString&);
+ // By default, animation updates are *implicitly* disallowed. This object
+ // can be used to allow or disallow animation updates as follows:
+ //
+ // AllowAnimationUpdatesScope(..., true): Allow animation updates, unless
+ // updates are currently *explicitly* disallowed.
+ //
+ // AllowAnimationUpdatesScope(..., false): Explicitly disallow animation
+ // updates.
+ class CORE_EXPORT AllowAnimationUpdatesScope {
+ STACK_ALLOCATED();
+
+ public:
+ AllowAnimationUpdatesScope(DocumentAnimations&, bool);
+
+ private:
+ base::AutoReset<absl::optional<bool>> allow_;
+ };
+
+ // Add an element to the set of elements with a pending animation update.
+ // The elements in the set can be applied later using,
+ // ApplyPendingElementUpdates.
+ //
+ // It's invalid to call this function during if animation updates are not
+ // allowed (see AnimationUpdatesAllowed).
+ void AddElementWithPendingAnimationUpdate(Element&);
+
+ // Apply pending updates for any elements previously added during AddElement-
+ // WithPendingAnimationUpdate
+ void ApplyPendingElementUpdates();
+
+ bool AnimationUpdatesAllowed() const {
+ return allow_animation_updates_.value_or(false);
+ }
const HeapHashSet<WeakMember<AnimationTimeline>>& GetTimelinesForTesting()
const {
@@ -102,23 +135,29 @@ class CORE_EXPORT DocumentAnimations final
uint64_t current_transition_generation_;
void Trace(Visitor*) const;
+#if DCHECK_IS_ON()
+ void AssertNoPendingUpdates() {
+ DCHECK(elements_with_pending_updates_.IsEmpty());
+ }
+#endif
+
protected:
using ReplaceableAnimationsMap =
HeapHashMap<Member<Element>, Member<HeapVector<Member<Animation>>>>;
void RemoveReplacedAnimations(ReplaceableAnimationsMap*);
private:
+ friend class AllowAnimationUpdatesScope;
+ friend class AnimationUpdateScope;
+
+ void MarkPendingIfCompositorPropertyAnimationChanges(
+ const PaintArtifactCompositor*);
+
Member<Document> document_;
HeapHashSet<WeakMember<AnimationTimeline>> timelines_;
HeapHashSet<WeakMember<AnimationTimeline>> unvalidated_timelines_;
-
- // We cache CSSScrollTimelines by name, such that multiple animations using
- // the same timeline can use the same CSSScrollTimeline instance.
- //
- // Note that timelines present in |cached_css_timelines_| are also present
- // in |timelines_|.
- HeapHashMap<AtomicString, WeakMember<AnimationTimeline>>
- cached_css_timelines_;
+ HeapHashSet<WeakMember<Element>> elements_with_pending_updates_;
+ absl::optional<bool> allow_animation_updates_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc b/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc
index 7dabd7cb713..16e40802b59 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc
@@ -142,4 +142,50 @@ TEST_F(DocumentAnimationsTest, UpdateAnimationsUpdatesAllTimelines) {
EXPECT_EQ(5u, host->MainThreadAnimationsCount());
}
+TEST_F(DocumentAnimationsTest, AllowAnimationUpdatesScope) {
+ DocumentAnimations& document_animations = document->GetDocumentAnimations();
+ auto allowed = [&document_animations]() -> bool {
+ return document_animations.AnimationUpdatesAllowed();
+ };
+
+ using AllowAnimationUpdatesScope =
+ DocumentAnimations::AllowAnimationUpdatesScope;
+
+ // Implicitly disallowed by default:
+ EXPECT_FALSE(allowed());
+
+ {
+ AllowAnimationUpdatesScope scope(document_animations, true);
+ EXPECT_TRUE(allowed());
+
+ {
+ AllowAnimationUpdatesScope scope(document_animations, true);
+ EXPECT_TRUE(allowed());
+ }
+
+ {
+ // Disallow explicitly:
+ AllowAnimationUpdatesScope scope(document_animations, false);
+ EXPECT_FALSE(allowed());
+
+ {
+ // Allowing while explicitly disallowed has no effect:
+ AllowAnimationUpdatesScope scope(document_animations, true);
+ EXPECT_FALSE(allowed());
+ }
+
+ EXPECT_FALSE(allowed());
+ }
+
+ EXPECT_TRUE(allowed());
+ }
+
+ {
+ AllowAnimationUpdatesScope scope(document_animations, false);
+ EXPECT_FALSE(allowed());
+ }
+
+ EXPECT_FALSE(allowed());
+}
+
} // namespace blink
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 d42c89dbb3d..490925a7008 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
@@ -371,22 +371,12 @@ TEST_F(AnimationDocumentTimelineTest, PauseForTesting) {
Animation* animation2 = timeline->Play(anim2);
timeline->PauseAnimationsForTesting(seek_time);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* current_time = animation1->currentTime();
EXPECT_NEAR(seek_time.InMillisecondsF(), current_time->GetAsDouble(),
Animation::kTimeToleranceMs);
current_time = animation2->currentTime();
EXPECT_NEAR(seek_time.InMillisecondsF(), current_time->GetAsDouble(),
Animation::kTimeToleranceMs);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish current_time;
- animation1->currentTime(current_time);
- EXPECT_NEAR(seek_time.InMillisecondsF(), current_time.GetAsDouble(),
- Animation::kTimeToleranceMs);
- animation2->currentTime(current_time);
- EXPECT_NEAR(seek_time.InMillisecondsF(), current_time.GetAsDouble(),
- Animation::kTimeToleranceMs);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
TEST_F(AnimationDocumentTimelineTest, DelayBeforeAnimationStart) {
@@ -421,12 +411,8 @@ TEST_F(AnimationDocumentTimelineTest, UseAnimationAfterTimelineDeref) {
Animation* animation = timeline->Play(nullptr);
timeline.Clear();
// Test passes if this does not crash.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(MakeGarbageCollected<V8CSSNumberish>(0),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(0));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
TEST_F(AnimationDocumentTimelineTest, PlayAfterDocumentDeref) {
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 be3c8bca7d5..ee8b9f5f7b8 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_input.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_input.cc
@@ -35,9 +35,11 @@
#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/string_or_string_sequence.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_base_keyframe.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_base_property_indexed_keyframe.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_compositeoperationorauto_compositeoperationorautosequence.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_doubleornullsequence_null.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.h"
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
#include "third_party/blink/renderer/core/animation/compositor_animations.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
@@ -65,21 +67,25 @@ namespace {
// vector of absl::optional<EffectModel::CompositeOperation> enums.
Vector<absl::optional<EffectModel::CompositeOperation>> ParseCompositeProperty(
const BasePropertyIndexedKeyframe* keyframe) {
- const CompositeOperationOrAutoOrCompositeOperationOrAutoSequence& composite =
- keyframe->composite();
-
- if (composite.IsCompositeOperationOrAuto()) {
- return {EffectModel::StringToCompositeOperation(
- composite.GetAsCompositeOperationOrAuto())};
- }
-
- Vector<absl::optional<EffectModel::CompositeOperation>> result;
- for (const String& composite_operation_string :
- composite.GetAsCompositeOperationOrAutoSequence()) {
- result.push_back(
- EffectModel::StringToCompositeOperation(composite_operation_string));
+ const auto* composite = keyframe->composite();
+ switch (composite->GetContentType()) {
+ case V8UnionCompositeOperationOrAutoOrCompositeOperationOrAutoSequence::
+ ContentType::kCompositeOperationOrAuto:
+ return {EffectModel::StringToCompositeOperation(
+ composite->GetAsCompositeOperationOrAuto().AsString())};
+ case V8UnionCompositeOperationOrAutoOrCompositeOperationOrAutoSequence::
+ ContentType::kCompositeOperationOrAutoSequence: {
+ Vector<absl::optional<EffectModel::CompositeOperation>> result;
+ for (const auto& composite_operation :
+ composite->GetAsCompositeOperationOrAutoSequence()) {
+ result.push_back(EffectModel::StringToCompositeOperation(
+ composite_operation.AsString()));
+ }
+ return result;
+ }
}
- return result;
+ NOTREACHED();
+ return {};
}
void SetKeyframeValue(Element* element,
@@ -414,17 +420,19 @@ bool GetPropertyIndexedKeyframeValues(const v8::Local<v8::Object>& keyframe,
return {};
}
- StringOrStringSequence string_or_string_sequence;
- V8StringOrStringSequence::ToImpl(
- script_state->GetIsolate(), v8_value, string_or_string_sequence,
- UnionTypeConversionMode::kNotNullable, exception_state);
+ auto* string_or_string_sequence =
+ V8UnionStringOrStringSequence::Create(isolate, v8_value, exception_state);
if (exception_state.HadException())
return false;
- if (string_or_string_sequence.IsString())
- result.push_back(string_or_string_sequence.GetAsString());
- else
- result = string_or_string_sequence.GetAsStringSequence();
+ switch (string_or_string_sequence->GetContentType()) {
+ case V8UnionStringOrStringSequence::ContentType::kString:
+ result.push_back(string_or_string_sequence->GetAsString());
+ break;
+ case V8UnionStringOrStringSequence::ContentType::kStringSequence:
+ result = string_or_string_sequence->GetAsStringSequence();
+ break;
+ }
return true;
}
@@ -451,20 +459,20 @@ StringKeyframeVector ConvertObjectForm(Element* element,
return {};
Vector<absl::optional<double>> offsets;
- if (property_indexed_keyframe->offset().IsNull())
+ if (property_indexed_keyframe->offset()->IsNull())
offsets.push_back(absl::nullopt);
- else if (property_indexed_keyframe->offset().IsDouble())
- offsets.push_back(property_indexed_keyframe->offset().GetAsDouble());
+ else if (property_indexed_keyframe->offset()->IsDouble())
+ offsets.push_back(property_indexed_keyframe->offset()->GetAsDouble());
else
- offsets = property_indexed_keyframe->offset().GetAsDoubleOrNullSequence();
+ offsets = property_indexed_keyframe->offset()->GetAsDoubleOrNullSequence();
// The web-animations spec explicitly states that easings should be kept as
// DOMStrings here and not parsed into timing functions until later.
Vector<String> easings;
- if (property_indexed_keyframe->easing().IsString())
- easings.push_back(property_indexed_keyframe->easing().GetAsString());
+ if (property_indexed_keyframe->easing()->IsString())
+ easings.push_back(property_indexed_keyframe->easing()->GetAsString());
else
- easings = property_indexed_keyframe->easing().GetAsStringSequence();
+ easings = property_indexed_keyframe->easing()->GetAsStringSequence();
Vector<absl::optional<EffectModel::CompositeOperation>> composite_operations =
ParseCompositeProperty(property_indexed_keyframe);
@@ -657,6 +665,7 @@ bool HasAdditiveCompositeCSSKeyframe(
}
return false;
}
+
} // namespace
KeyframeEffectModelBase* EffectInput::Convert(
@@ -751,4 +760,5 @@ EffectModel::CompositeOperation EffectInput::ResolveCompositeOperation(
}
return result;
}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_model.h b/chromium/third_party/blink/renderer/core/animation/effect_model.h
index 30ca0846f47..3cff2b57fbc 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_model.h
+++ b/chromium/third_party/blink/renderer/core/animation/effect_model.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_EFFECT_MODEL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_EFFECT_MODEL_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/animation_time_delta.h"
#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_stack.cc b/chromium/third_party/blink/renderer/core/animation/effect_stack.cc
index 0b5911bc87d..cee21c61ad7 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_stack.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_stack.cc
@@ -140,6 +140,20 @@ bool EffectStack::AffectsProperties(const CSSBitset& bitset,
return false;
}
+HashSet<PropertyHandle> EffectStack::AffectedProperties(
+ KeyframeEffect::Priority priority) const {
+ HashSet<PropertyHandle> affected;
+
+ for (const auto& sampled_effect : sampled_effects_) {
+ if (sampled_effect->GetPriority() != priority)
+ continue;
+ for (const auto& interpolation : sampled_effect->Interpolations())
+ affected.insert(interpolation->GetProperty());
+ }
+
+ return affected;
+}
+
bool EffectStack::HasRevert() const {
for (const auto& sampled_effect : sampled_effects_) {
if (sampled_effect->Effect() && sampled_effect->Effect()->HasRevert())
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_stack.h b/chromium/third_party/blink/renderer/core/animation/effect_stack.h
index f97e0619a74..7a18409ff1c 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_stack.h
+++ b/chromium/third_party/blink/renderer/core/animation/effect_stack.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_EFFECT_STACK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_EFFECT_STACK_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
@@ -54,6 +53,8 @@ class CORE_EXPORT EffectStack {
public:
EffectStack();
+ EffectStack(const EffectStack&) = delete;
+ EffectStack& operator=(const EffectStack&) = delete;
void Add(SampledEffect* sampled_effect) {
sampled_effects_.push_back(sampled_effect);
@@ -67,6 +68,8 @@ class CORE_EXPORT EffectStack {
bool AffectsProperties(PropertyHandleFilter) const;
bool AffectsProperties(const CSSBitset&,
KeyframeEffect::Priority priority) const;
+ HashSet<PropertyHandle> AffectedProperties(
+ KeyframeEffect::Priority priority) const;
bool HasRevert() const;
// Produces a map of properties to active effects.
@@ -97,7 +100,6 @@ class CORE_EXPORT EffectStack {
HeapVector<Member<SampledEffect>> sampled_effects_;
friend class AnimationEffectStackTest;
- DISALLOW_COPY_AND_ASSIGN(EffectStack);
};
} // 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 13a728cafc9..ce47be151d2 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
@@ -36,13 +36,9 @@ class AnimationEffectStackTest : public PageTestBase {
Animation* Play(KeyframeEffect* effect, double start_time) {
Animation* animation = timeline->Play(effect);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setStartTime(
MakeGarbageCollected<V8CSSNumberish>(start_time * 1000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setStartTime(CSSNumberish::FromDouble(start_time * 1000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->Update(kTimingUpdateOnDemand);
return animation;
}
@@ -291,4 +287,46 @@ TEST_F(AnimationEffectStackTest, AffectsPropertiesCSSBitsetTransitionPriority) {
KeyframeEffect::kTransitionPriority));
}
+TEST_F(AnimationEffectStackTest, AffectedPropertiesDefaultPriority) {
+ Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kColor, "red")), 10);
+ Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kTop, "1px")), 10);
+ Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kLeft, "1px")), 10);
+
+ ASSERT_TRUE(element->GetElementAnimations());
+ const EffectStack& effect_stack =
+ element->GetElementAnimations()->GetEffectStack();
+
+ EXPECT_TRUE(
+ effect_stack.AffectedProperties(KeyframeEffect::kTransitionPriority)
+ .IsEmpty());
+
+ auto set = effect_stack.AffectedProperties(KeyframeEffect::kDefaultPriority);
+ ASSERT_EQ(3u, set.size());
+ EXPECT_TRUE(set.Contains(PropertyHandle(GetCSSPropertyColor())));
+ EXPECT_TRUE(set.Contains(PropertyHandle(GetCSSPropertyTop())));
+ EXPECT_TRUE(set.Contains(PropertyHandle(GetCSSPropertyLeft())));
+}
+
+TEST_F(AnimationEffectStackTest, AffectedPropertiesTransitionPriority) {
+ Element* body = GetDocument().body();
+ body->SetInlineStyleProperty(CSSPropertyID::kTransition, "color 10s");
+ body->SetInlineStyleProperty(CSSPropertyID::kColor, "red");
+ UpdateAllLifecyclePhasesForTest();
+
+ body->SetInlineStyleProperty(CSSPropertyID::kColor, "blue");
+ UpdateAllLifecyclePhasesForTest();
+
+ ASSERT_TRUE(body->GetElementAnimations());
+ const EffectStack& effect_stack =
+ body->GetElementAnimations()->GetEffectStack();
+
+ EXPECT_TRUE(effect_stack.AffectedProperties(KeyframeEffect::kDefaultPriority)
+ .IsEmpty());
+
+ auto set =
+ effect_stack.AffectedProperties(KeyframeEffect::kTransitionPriority);
+ ASSERT_EQ(1u, set.size());
+ EXPECT_TRUE(set.Contains(PropertyHandle(GetCSSPropertyColor())));
+}
+
} // 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 fa1b98062d0..9ca568de879 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.cc
@@ -53,6 +53,8 @@ void UpdateAnimationFlagsForEffect(const KeyframeEffect& effect,
style.SetHasCurrentBackdropFilterAnimation(true);
if (effect.Affects(PropertyHandle(GetCSSPropertyBackgroundColor())))
style.SetHasCurrentBackgroundColorAnimation(true);
+ if (effect.Affects(PropertyHandle(GetCSSPropertyClipPath())))
+ style.SetHasCurrentClipPathAnimation(true);
}
} // namespace
@@ -124,29 +126,6 @@ void ElementAnimations::Trace(Visitor* visitor) const {
visitor->Trace(worklet_animations_);
}
-const ComputedStyle* ElementAnimations::BaseComputedStyle() const {
- return base_computed_style_.get();
-}
-
-const CSSBitset* ElementAnimations::BaseImportantSet() const {
- if (IsAnimationStyleChange())
- return base_important_set_.get();
- return nullptr;
-}
-
-void ElementAnimations::UpdateBaseComputedStyle(
- const ComputedStyle* computed_style,
- std::unique_ptr<CSSBitset> base_important_set) {
- DCHECK(computed_style);
- base_computed_style_ = ComputedStyle::Clone(*computed_style);
- base_important_set_ = std::move(base_important_set);
-}
-
-void ElementAnimations::ClearBaseComputedStyle() {
- base_computed_style_ = nullptr;
- base_important_set_ = nullptr;
-}
-
bool ElementAnimations::UpdateBoxSizeAndCheckTransformAxisAlignment(
const FloatSize& box_size) {
bool preserves_axis_alignment = true;
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 babb8cbff4c..e6e2cf4c8fb 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ELEMENT_ANIMATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ELEMENT_ANIMATIONS_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
#include "third_party/blink/renderer/core/animation/effect_stack.h"
@@ -51,6 +50,8 @@ class CORE_EXPORT ElementAnimations final
: public GarbageCollected<ElementAnimations> {
public:
ElementAnimations();
+ ElementAnimations(const ElementAnimations&) = delete;
+ ElementAnimations& operator=(const ElementAnimations&) = delete;
~ElementAnimations();
// Animations that are currently active for this element, their effects will
@@ -82,12 +83,6 @@ class CORE_EXPORT ElementAnimations final
}
bool IsAnimationStyleChange() const { return animation_style_change_; }
- const ComputedStyle* BaseComputedStyle() const;
- const CSSBitset* BaseImportantSet() const;
- void UpdateBaseComputedStyle(const ComputedStyle*,
- std::unique_ptr<CSSBitset> base_important_set);
- void ClearBaseComputedStyle();
-
bool UpdateBoxSizeAndCheckTransformAxisAlignment(const FloatSize& box_size);
bool IsIdentityOrTranslation() const;
@@ -105,24 +100,9 @@ class CORE_EXPORT ElementAnimations final
// style, we store a cached value of the 'base' computed style (e.g. with no
// change from the running animations) and use that during style recalc,
// applying only the animation changes on top of it.
- bool animation_style_change_;
- scoped_refptr<ComputedStyle> base_computed_style_;
- // Keeps track of the !important declarations used to build the base
- // computed style. These declarations must not be overwritten by animation
- // effects, hence we have to disable the base computed style optimization when
- // !important declarations conflict with active animations.
//
- // If there were no !important declarations in the base style, this field
- // will be nullptr.
- //
- // TODO(andruud): We should be able to simply skip applying the animation
- // for properties in this set instead of disabling the optimization.
- // However, we currently need the cascade to handle the case where
- // an !important declaration appears in a :visited selector.
- // See https://crbug.com/1062217.
- std::unique_ptr<CSSBitset> base_important_set_;
-
- DISALLOW_COPY_AND_ASSIGN(ElementAnimations);
+ // See also StyleBaseData.
+ bool animation_style_change_;
FRIEND_TEST_ALL_PREFIXES(StyleEngineTest, PseudoElementBaseComputedStyle);
};
diff --git a/chromium/third_party/blink/renderer/core/animation/inert_effect.cc b/chromium/third_party/blink/renderer/core/animation/inert_effect.cc
index 94a09d84855..8a3e492bfca 100644
--- a/chromium/third_party/blink/renderer/core/animation/inert_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/inert_effect.cc
@@ -56,7 +56,7 @@ void InertEffect::Sample(HeapVector<Member<Interpolation>>& result) const {
DCHECK(iteration);
DCHECK_GE(iteration.value(), 0);
model_->Sample(clampTo<int>(iteration.value(), 0), Progress().value(),
- SpecifiedTiming().IterationDuration(), result);
+ NormalizedTiming().iteration_duration, result);
}
AnimationTimeDelta InertEffect::CalculateTimeToEffectChange(
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_aspect_ratio.cc b/chromium/third_party/blink/renderer/core/animation/interpolable_aspect_ratio.cc
index cfcbc5408f0..7754db3b091 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_aspect_ratio.cc
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_aspect_ratio.cc
@@ -13,9 +13,6 @@ namespace blink {
// static
std::unique_ptr<InterpolableAspectRatio> InterpolableAspectRatio::MaybeCreate(
const StyleAspectRatio& aspect_ratio) {
- if (!RuntimeEnabledFeatures::CSSAspectRatioInterpolationEnabled())
- return nullptr;
-
// Auto aspect ratio cannot be interpolated to / from.
if (aspect_ratio.IsAuto())
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc b/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc
index 92c9fbab3bb..92a6b85d05b 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc
@@ -10,12 +10,6 @@
namespace blink {
// static
-std::unique_ptr<InterpolableTransformList> InterpolableTransformList::Create(
- TransformOperations&& operations) {
- return std::make_unique<InterpolableTransformList>(std::move(operations));
-}
-
-// static
std::unique_ptr<InterpolableTransformList>
InterpolableTransformList::ConvertCSSValue(const CSSValue& css_value,
const StyleResolverState* state) {
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h b/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h
index 9275a2e0fc9..65f9ca508f4 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_TRANSFORM_LIST_H_
#include <memory>
+
#include "third_party/blink/renderer/core/animation/interpolable_value.h"
#include "third_party/blink/renderer/platform/transforms/transform_operations.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -22,8 +23,6 @@ class CORE_EXPORT InterpolableTransformList final : public InterpolableValue {
InterpolableTransformList(TransformOperations&& operations)
: operations_(std::move(operations)) {}
- static std::unique_ptr<InterpolableTransformList> Create(
- TransformOperations&&);
static std::unique_ptr<InterpolableTransformList> ConvertCSSValue(
const CSSValue&,
const StyleResolverState*);
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_value.h b/chromium/third_party/blink/renderer/core/animation/interpolable_value.h
index 0fe3e2eb890..54cb5f25e93 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_value.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_value.h
@@ -8,11 +8,10 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.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/casting.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
namespace blink {
@@ -104,22 +103,15 @@ class CORE_EXPORT InterpolableNumber final : public InterpolableValue {
double value_;
};
-class CORE_EXPORT InterpolableList : public InterpolableValue {
+class CORE_EXPORT InterpolableList final : public InterpolableValue {
public:
- // Explicitly delete operator= because MSVC automatically generate
- // copy constructors and operator= for dll-exported classes.
- // Since InterpolableList is not copyable, automatically generated
- // operator= causes MSVC compiler error.
- // However, we cannot use DISALLOW_COPY_AND_ASSIGN because InterpolableList
- // has its own copy constructor. So just delete operator= here.
- InterpolableList& operator=(const InterpolableList&) = delete;
-
explicit InterpolableList(wtf_size_t size) : values_(size) {}
- InterpolableList(const InterpolableList& other) : values_(other.length()) {
- for (wtf_size_t i = 0; i < length(); i++)
- Set(i, other.values_[i]->Clone());
- }
+ // Move-only; use Clone() to make a copy.
+ InterpolableList(const InterpolableList&) = delete;
+ InterpolableList& operator=(const InterpolableList&) = delete;
+ InterpolableList(InterpolableList&&) = default;
+ InterpolableList& operator=(InterpolableList&&) = default;
const InterpolableValue* Get(wtf_size_t position) const {
return values_[position].get();
@@ -146,7 +138,10 @@ class CORE_EXPORT InterpolableList : public InterpolableValue {
private:
InterpolableList* RawClone() const final {
- return new InterpolableList(*this);
+ auto* result = new InterpolableList(length());
+ for (wtf_size_t i = 0; i < length(); i++)
+ result->Set(i, values_[i]->Clone());
+ return result;
}
InterpolableList* RawCloneAndZero() const final;
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolated_svg_path_source.h b/chromium/third_party/blink/renderer/core/animation/interpolated_svg_path_source.h
index e7cdaf7159c..0eb69b39f3b 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolated_svg_path_source.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolated_svg_path_source.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLATED_SVG_PATH_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLATED_SVG_PATH_SOURCE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/svg_path_seg_interpolation_functions.h"
#include "third_party/blink/renderer/core/svg/svg_path_data.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -24,6 +23,10 @@ class InterpolatedSVGPathSource {
DCHECK_EQ(interpolable_path_segs_.length(), path_seg_types_.size());
}
+ InterpolatedSVGPathSource(const InterpolatedSVGPathSource&) = delete;
+ InterpolatedSVGPathSource& operator=(const InterpolatedSVGPathSource&) =
+ delete;
+
bool HasMoreData() const;
PathSegmentData ParseSegment();
@@ -32,7 +35,6 @@ class InterpolatedSVGPathSource {
wtf_size_t current_index_;
const InterpolableList& interpolable_path_segs_;
const Vector<SVGPathSegType>& path_seg_types_;
- DISALLOW_COPY_AND_ASSIGN(InterpolatedSVGPathSource);
};
bool InterpolatedSVGPathSource::HasMoreData() const {
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation.h b/chromium/third_party/blink/renderer/core/animation/interpolation.h
index 228bab31669..d57ab9d2bd9 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolation.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolation.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLATION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLATION_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/interpolable_value.h"
#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -57,6 +56,8 @@ namespace blink {
// the subclass documentation for more.
class CORE_EXPORT Interpolation : public GarbageCollected<Interpolation> {
public:
+ Interpolation(const Interpolation&) = delete;
+ Interpolation& operator=(const Interpolation&) = delete;
virtual ~Interpolation() {}
virtual void Interpolate(int iteration, double fraction) = 0;
@@ -76,7 +77,6 @@ class CORE_EXPORT Interpolation : public GarbageCollected<Interpolation> {
protected:
Interpolation() = default;
- DISALLOW_COPY_AND_ASSIGN(Interpolation);
};
using ActiveInterpolations = HeapVector<Member<Interpolation>, 1>;
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/interpolation_type.h
index 431d50dd590..b2567c485df 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolation_type.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/interpolation_value.h"
#include "third_party/blink/renderer/core/animation/keyframe.h"
#include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h"
@@ -33,6 +32,8 @@ class CORE_EXPORT InterpolationType {
USING_FAST_MALLOC(InterpolationType);
public:
+ InterpolationType(const InterpolationType&) = delete;
+ InterpolationType& operator=(const InterpolationType&) = delete;
virtual ~InterpolationType() = default;
PropertyHandle GetProperty() const { return property_; }
@@ -45,6 +46,8 @@ class CORE_EXPORT InterpolationType {
USING_FAST_MALLOC(ConversionChecker);
public:
+ ConversionChecker(const ConversionChecker&) = delete;
+ ConversionChecker& operator=(const ConversionChecker&) = delete;
virtual ~ConversionChecker() = default;
void SetType(const InterpolationType& type) { type_ = &type; }
const InterpolationType& GetType() const { return *type_; }
@@ -54,7 +57,6 @@ class CORE_EXPORT InterpolationType {
protected:
ConversionChecker() : type_(nullptr) {}
const InterpolationType* type_;
- DISALLOW_COPY_AND_ASSIGN(ConversionChecker);
};
using ConversionCheckers = Vector<std::unique_ptr<ConversionChecker>>;
@@ -121,7 +123,6 @@ class CORE_EXPORT InterpolationType {
explicit InterpolationType(PropertyHandle property) : property_(property) {}
const PropertyHandle property_;
- DISALLOW_COPY_AND_ASSIGN(InterpolationType);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe.h b/chromium/third_party/blink/renderer/core/animation/keyframe.h
index a70ac6cd969..b4064141803 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_KEYFRAME_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_KEYFRAME_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
@@ -62,6 +61,8 @@ class V8ObjectBuilder;
// FIXME: Make Keyframe immutable
class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
public:
+ Keyframe(const Keyframe&) = delete;
+ Keyframe& operator=(const Keyframe&) = delete;
virtual ~Keyframe() = default;
// TODO(smcgruer): The keyframe offset should be immutable.
@@ -124,6 +125,9 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
PropertySpecificKeyframe(double offset,
scoped_refptr<TimingFunction> easing,
EffectModel::CompositeOperation);
+ PropertySpecificKeyframe(const PropertySpecificKeyframe&) = delete;
+ PropertySpecificKeyframe& operator=(const PropertySpecificKeyframe&) =
+ delete;
virtual ~PropertySpecificKeyframe() = default;
double Offset() const { return offset_; }
TimingFunction& Easing() const { return *easing_; }
@@ -165,8 +169,6 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
double offset_;
scoped_refptr<TimingFunction> easing_;
EffectModel::CompositeOperation composite_;
-
- DISALLOW_COPY_AND_ASSIGN(PropertySpecificKeyframe);
};
// Construct and return a property-specific keyframe for this keyframe.
@@ -202,7 +204,6 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
// absl::nullopt value represents 'auto'.
absl::optional<EffectModel::CompositeOperation> composite_;
scoped_refptr<TimingFunction> easing_;
- DISALLOW_COPY_AND_ASSIGN(Keyframe);
};
using PropertySpecificKeyframe = Keyframe::PropertySpecificKeyframe;
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 68f1663432f..3b1953b375b 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,7 @@
#include "third_party/blink/renderer/core/animation/keyframe_effect.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_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
@@ -88,11 +88,7 @@ KeyframeEffect* KeyframeEffect::Create(
ScriptState* script_state,
Element* element,
const ScriptValue& keyframes,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionKeyframeEffectOptionsOrUnrestrictedDouble* options,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const UnrestrictedDoubleOrKeyframeEffectOptions& options,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
Document* document = element ? &element->GetDocument() : nullptr;
Timing timing = TimingInput::Convert(options, document, exception_state);
@@ -101,18 +97,8 @@ KeyframeEffect* KeyframeEffect::Create(
EffectModel::CompositeOperation composite = EffectModel::kCompositeReplace;
String pseudo = String();
- if (
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- options->IsKeyframeEffectOptions()
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- options.IsKeyframeEffectOptions()
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ if (options->IsKeyframeEffectOptions()) {
auto* effect_options = options->GetAsKeyframeEffectOptions();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- auto* effect_options = options.GetAsKeyframeEffectOptions();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
composite =
EffectModel::StringToCompositeOperation(effect_options->composite())
.value();
@@ -585,12 +571,12 @@ void KeyframeEffect::ApplyEffects() {
if (sampled_effect_) {
changed =
model_->Sample(clampTo<int>(iteration.value(), 0), Progress().value(),
- SpecifiedTiming().IterationDuration(),
+ NormalizedTiming().iteration_duration,
sampled_effect_->MutableInterpolations());
} else {
HeapVector<Member<Interpolation>> interpolations;
model_->Sample(clampTo<int>(iteration.value(), 0), Progress().value(),
- SpecifiedTiming().IterationDuration(), interpolations);
+ NormalizedTiming().iteration_duration, interpolations);
if (!interpolations.IsEmpty()) {
auto* sampled_effect =
MakeGarbageCollected<SampledEffect>(this, owner_->SequenceNumber());
@@ -672,11 +658,14 @@ AnimationTimeDelta KeyframeEffect::CalculateTimeToEffectChange(
bool forwards,
absl::optional<AnimationTimeDelta> local_time,
AnimationTimeDelta time_to_next_iteration) const {
- const AnimationTimeDelta start_time = SpecifiedTiming().start_delay;
+ const AnimationTimeDelta start_time = NormalizedTiming().start_delay;
+
const AnimationTimeDelta end_time_minus_end_delay =
- start_time + SpecifiedTiming().ActiveDuration();
+ start_time + NormalizedTiming().active_duration;
+
const AnimationTimeDelta end_time =
- end_time_minus_end_delay + SpecifiedTiming().end_delay;
+ end_time_minus_end_delay + NormalizedTiming().end_delay;
+
const AnimationTimeDelta after_time =
std::min(end_time_minus_end_delay, end_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 ea23ee7f945..702db6ae8d5 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
@@ -46,7 +46,6 @@ class ExceptionState;
class KeyframeEffectModelBase;
class PaintArtifactCompositor;
class SampledEffect;
-class UnrestrictedDoubleOrKeyframeEffectOptions;
class V8UnionKeyframeEffectOptionsOrUnrestrictedDouble;
// Represents the effect of an Animation on an Element's properties.
@@ -58,21 +57,12 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
enum Priority { kDefaultPriority, kTransitionPriority };
// Web Animations API Bindings constructors.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static KeyframeEffect* Create(
ScriptState* script_state,
Element* element,
const ScriptValue& keyframes,
const V8UnionKeyframeEffectOptionsOrUnrestrictedDouble* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static KeyframeEffect* Create(
- ScriptState*,
- Element*,
- const ScriptValue&,
- const UnrestrictedDoubleOrKeyframeEffectOptions&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static KeyframeEffect* Create(ScriptState*,
Element*,
const ScriptValue&,
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 88ec4bdb326..bbc8e7c2746 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
@@ -41,7 +41,6 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
-#include "third_party/blink/renderer/platform/animation/animation_utilities.h"
#include "third_party/blink/renderer/platform/geometry/float_box.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -96,7 +95,7 @@ bool KeyframeEffectModelBase::Sample(
namespace {
-static const size_t num_compositable_properties = 8;
+static const size_t num_compositable_properties = 9;
const CSSProperty** CompositableProperties() {
static const CSSProperty*
@@ -104,7 +103,8 @@ const CSSProperty** CompositableProperties() {
&GetCSSPropertyOpacity(), &GetCSSPropertyRotate(),
&GetCSSPropertyScale(), &GetCSSPropertyTransform(),
&GetCSSPropertyTranslate(), &GetCSSPropertyFilter(),
- &GetCSSPropertyBackdropFilter(), &GetCSSPropertyBackgroundColor()};
+ &GetCSSPropertyBackdropFilter(), &GetCSSPropertyBackgroundColor(),
+ &GetCSSPropertyClipPath()};
return kCompositableProperties;
}
@@ -211,11 +211,12 @@ bool KeyframeEffectModelBase::SnapshotCompositorKeyFrames(
if (!should_snapshot_property_callback(property))
return false;
- PropertySpecificKeyframeGroup* keyframe_group =
- keyframe_groups_->at(property);
- if (!keyframe_group)
+ auto it = keyframe_groups_->find(property);
+ if (it == keyframe_groups_->end())
return false;
+ PropertySpecificKeyframeGroup* keyframe_group = it->value;
+
bool updated = false;
for (auto& keyframe : keyframe_group->keyframes_) {
if (!should_snapshot_keyframe_callback(*keyframe))
@@ -357,7 +358,8 @@ bool KeyframeEffectModelBase::RequiresPropertyNode() const {
if (!property.IsCSSProperty() ||
(property.GetCSSProperty().PropertyID() != CSSPropertyID::kVariable &&
property.GetCSSProperty().PropertyID() !=
- CSSPropertyID::kBackgroundColor))
+ CSSPropertyID::kBackgroundColor &&
+ property.GetCSSProperty().PropertyID() != CSSPropertyID::kClipPath))
return true;
}
}
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
index 990602e28c8..1c229edbcb5 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
@@ -8,7 +8,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.h"
@@ -16,6 +15,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
@@ -90,13 +90,8 @@ class AnimationKeyframeEffectV8Test : public KeyframeEffectTest {
NonThrowableExceptionState exception_state;
return KeyframeEffect::Create(
script_state, element, keyframe_object,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MakeGarbageCollected<V8UnionKeyframeEffectOptionsOrUnrestrictedDouble>(
timing_input),
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeEffectOptions::FromUnrestrictedDouble(
- timing_input),
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
exception_state);
}
static KeyframeEffect* CreateAnimationFromOption(
@@ -107,13 +102,8 @@ class AnimationKeyframeEffectV8Test : public KeyframeEffectTest {
NonThrowableExceptionState exception_state;
return KeyframeEffect::Create(
script_state, element, keyframe_object,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MakeGarbageCollected<V8UnionKeyframeEffectOptionsOrUnrestrictedDouble>(
const_cast<KeyframeEffectOptions*>(timing_input)),
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
- const_cast<KeyframeEffectOptions*>(timing_input)),
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
exception_state);
}
static KeyframeEffect* CreateAnimation(ScriptState* script_state,
@@ -315,10 +305,10 @@ TEST_F(AnimationKeyframeEffectV8Test, SpecifiedDurationGetter) {
timing_input_dictionary_with_duration);
EffectTiming* specified_with_duration = animation_with_duration->getTiming();
- UnrestrictedDoubleOrString duration = specified_with_duration->duration();
- EXPECT_TRUE(duration.IsUnrestrictedDouble());
- EXPECT_EQ(2.5, duration.GetAsUnrestrictedDouble());
- EXPECT_FALSE(duration.IsString());
+ auto* duration = specified_with_duration->duration();
+ EXPECT_TRUE(duration->IsUnrestrictedDouble());
+ EXPECT_EQ(2.5, duration->GetAsUnrestrictedDouble());
+ EXPECT_FALSE(duration->IsString());
v8::Local<v8::Object> timing_input_no_duration =
v8::Object::New(scope.GetIsolate());
@@ -332,10 +322,10 @@ TEST_F(AnimationKeyframeEffectV8Test, SpecifiedDurationGetter) {
timing_input_dictionary_no_duration);
EffectTiming* specified_no_duration = animation_no_duration->getTiming();
- UnrestrictedDoubleOrString duration2 = specified_no_duration->duration();
- EXPECT_FALSE(duration2.IsUnrestrictedDouble());
- EXPECT_TRUE(duration2.IsString());
- EXPECT_EQ("auto", duration2.GetAsString());
+ auto* duration2 = specified_no_duration->duration();
+ EXPECT_FALSE(duration2->IsUnrestrictedDouble());
+ EXPECT_TRUE(duration2->IsString());
+ EXPECT_EQ("auto", duration2->GetAsString());
}
TEST_F(AnimationKeyframeEffectV8Test, SetKeyframesAdditiveCompositeOperation) {
@@ -390,48 +380,32 @@ TEST_F(KeyframeEffectTest, TimeToEffectChange) {
keyframe_effect->TimeToReverseEffectChange());
// End of the before phase.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(100000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(100000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_TIMEDELTA(AnimationTimeDelta(),
keyframe_effect->TimeToReverseEffectChange());
// Nearing the end of the active phase.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(199000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(199000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(1),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_TIMEDELTA(AnimationTimeDelta(),
keyframe_effect->TimeToReverseEffectChange());
// End of the active phase.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(200000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(200000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_TIMEDELTA(AnimationTimeDelta(),
keyframe_effect->TimeToReverseEffectChange());
// End of the animation.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(300000),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- animation->setCurrentTime(CSSNumberish::FromDouble(300000));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ(AnimationTimeDelta::Max(),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
diff --git a/chromium/third_party/blink/renderer/core/animation/length_property_functions.cc b/chromium/third_party/blink/renderer/core/animation/length_property_functions.cc
index 498f66ba252..3cd0a544662 100644
--- a/chromium/third_party/blink/renderer/core/animation/length_property_functions.cc
+++ b/chromium/third_party/blink/renderer/core/animation/length_property_functions.cc
@@ -457,8 +457,6 @@ bool LengthPropertyFunctions::SetLength(const CSSProperty& property,
case CSSPropertyID::kTabSize:
return false;
- return false;
-
default:
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc
index 09218341b00..ff54bfdfccf 100644
--- a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc
@@ -16,9 +16,9 @@ namespace blink {
namespace {
-class TestNonInterpolableValue : public NonInterpolableValue {
+class TestNonInterpolableValue final : public NonInterpolableValue {
public:
- ~TestNonInterpolableValue() final = default;
+ ~TestNonInterpolableValue() override = default;
static scoped_refptr<TestNonInterpolableValue> Create(int value) {
DCHECK_GE(value, 1);
@@ -78,7 +78,7 @@ class TestUnderlyingValue : public UnderlyingValue {
InterpolationValue CreateInterpolableList(
const Vector<std::pair<double, int>>& values) {
return ListInterpolationFunctions::CreateList(
- values.size(), [&values](size_t i) {
+ values.size(), [&values](wtf_size_t i) {
return InterpolationValue(
std::make_unique<InterpolableNumber>(values[i].first),
TestNonInterpolableValue::Create(values[i].second));
@@ -89,7 +89,7 @@ InterpolationValue CreateInterpolableList(
// but a non-interpolable list of nullptrs.
InterpolationValue CreateInterpolableList(const Vector<double>& values) {
return ListInterpolationFunctions::CreateList(
- values.size(), [&values](size_t i) {
+ values.size(), [&values](wtf_size_t i) {
return InterpolationValue(
std::make_unique<InterpolableNumber>(values[i]), nullptr);
});
@@ -99,7 +99,7 @@ InterpolationValue CreateInterpolableList(const Vector<double>& values) {
// values, but an interpolable list of zeroes.
InterpolationValue CreateNonInterpolableList(const Vector<int>& values) {
return ListInterpolationFunctions::CreateList(
- values.size(), [&values](size_t i) {
+ values.size(), [&values](wtf_size_t i) {
return InterpolationValue(std::make_unique<InterpolableNumber>(0),
TestNonInterpolableValue::Create(values[i]));
});
diff --git a/chromium/third_party/blink/renderer/core/animation/pending_animations.h b/chromium/third_party/blink/renderer/core/animation/pending_animations.h
index ff8a6fe2f0d..e4b794621fd 100644
--- a/chromium/third_party/blink/renderer/core/animation/pending_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/pending_animations.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_PENDING_ANIMATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_PENDING_ANIMATIONS_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/animation/primitive_interpolation.h b/chromium/third_party/blink/renderer/core/animation/primitive_interpolation.h
index e50e7cd7c01..e2627eac4a4 100644
--- a/chromium/third_party/blink/renderer/core/animation/primitive_interpolation.h
+++ b/chromium/third_party/blink/renderer/core/animation/primitive_interpolation.h
@@ -10,10 +10,9 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/animation/typed_interpolation_value.h"
-#include "third_party/blink/renderer/platform/animation/animation_utilities.h"
+#include "third_party/blink/renderer/platform/geometry/blend.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -25,6 +24,8 @@ class PrimitiveInterpolation {
USING_FAST_MALLOC(PrimitiveInterpolation);
public:
+ PrimitiveInterpolation(const PrimitiveInterpolation&) = delete;
+ PrimitiveInterpolation& operator=(const PrimitiveInterpolation&) = delete;
virtual ~PrimitiveInterpolation() = default;
virtual void InterpolateValue(
@@ -37,7 +38,6 @@ class PrimitiveInterpolation {
protected:
PrimitiveInterpolation() = default;
- DISALLOW_COPY_AND_ASSIGN(PrimitiveInterpolation);
};
// Represents a pair of keyframes that are compatible for "smooth" interpolation
diff --git a/chromium/third_party/blink/renderer/core/animation/property_handle.h b/chromium/third_party/blink/renderer/core/animation/property_handle.h
index d540ad6e044..8597f4b2ffc 100644
--- a/chromium/third_party/blink/renderer/core/animation/property_handle.h
+++ b/chromium/third_party/blink/renderer/core/animation/property_handle.h
@@ -27,11 +27,23 @@ class CORE_EXPORT PropertyHandle {
DCHECK_NE(CSSPropertyID::kVariable, property.PropertyID());
}
+ // TODO(crbug.com/980160): Eliminate call to GetCSSPropertyVariable().
explicit PropertyHandle(const AtomicString& property_name)
: handle_type_(kHandleCSSCustomProperty),
css_property_(&GetCSSPropertyVariable()),
property_name_(property_name) {}
+ // TODO(crbug.com/980160): Eliminate call to GetCSSPropertyVariable().
+ explicit PropertyHandle(const CSSPropertyName& property_name)
+ : handle_type_(property_name.IsCustomProperty() ? kHandleCSSCustomProperty
+ : kHandleCSSProperty),
+ css_property_(property_name.IsCustomProperty()
+ ? &GetCSSPropertyVariable()
+ : &CSSProperty::Get(property_name.Id())),
+ property_name_(property_name.IsCustomProperty()
+ ? property_name.ToAtomicString()
+ : g_null_atom) {}
+
explicit PropertyHandle(const QualifiedName& attribute_name)
: handle_type_(kHandleSVGAttribute), svg_attribute_(&attribute_name) {}
diff --git a/chromium/third_party/blink/renderer/core/animation/sampled_effect.cc b/chromium/third_party/blink/renderer/core/animation/sampled_effect.cc
index f4bf0734b7c..e0202437f53 100644
--- a/chromium/third_party/blink/renderer/core/animation/sampled_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/sampled_effect.cc
@@ -29,7 +29,8 @@ void SampledEffect::RemoveReplacedInterpolations(
[&](const auto& interpolation) {
return replaced_properties.Contains(interpolation->GetProperty());
});
- interpolations_.Shrink(new_end - interpolations_.begin());
+ interpolations_.Shrink(
+ static_cast<wtf_size_t>(new_end - interpolations_.begin()));
}
void SampledEffect::UpdateReplacedProperties(
diff --git a/chromium/third_party/blink/renderer/core/animation/sampled_effect.h b/chromium/third_party/blink/renderer/core/animation/sampled_effect.h
index 5f9a5dff41d..ed21e02330d 100644
--- a/chromium/third_party/blink/renderer/core/animation/sampled_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/sampled_effect.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SAMPLED_EFFECT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SAMPLED_EFFECT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/interpolation.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
@@ -19,6 +18,8 @@ namespace blink {
class SampledEffect final : public GarbageCollected<SampledEffect> {
public:
SampledEffect(KeyframeEffect*, unsigned sequence_number);
+ SampledEffect(const SampledEffect&) = delete;
+ SampledEffect& operator=(const SampledEffect&) = delete;
void Clear();
@@ -43,7 +44,6 @@ class SampledEffect final : public GarbageCollected<SampledEffect> {
HeapVector<Member<Interpolation>> interpolations_;
const unsigned sequence_number_;
KeyframeEffect::Priority priority_;
- DISALLOW_COPY_AND_ASSIGN(SampledEffect);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
index f5b2ce5a0e0..769e1accad3 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
@@ -31,12 +31,6 @@ namespace blink {
namespace {
-constexpr double kScrollTimelineDuration = 100.0;
-// Animation times are tracked as TimeDeltas which are stored internally as an
-// integer number of microseconds. Multiplying by 1000 converts this into a
-// value equivalent to Milliseconds.
-constexpr double kScrollTimelineDurationMs = kScrollTimelineDuration * 1000.0;
-
using ScrollTimelineSet =
HeapHashMap<WeakMember<Node>,
Member<HeapHashSet<WeakMember<ScrollTimeline>>>>;
@@ -90,25 +84,23 @@ ScrollOrientation ToPhysicalScrollOrientation(
}
}
-// Note that the resolution process may trigger document lifecycle to clean
-// style and layout.
Node* ResolveScrollSource(Element* scroll_source) {
- // When in quirks mode we need the style to be clean, so we don't use
- // |ScrollingElementNoLayout|.
if (scroll_source &&
- scroll_source == scroll_source->GetDocument().scrollingElement()) {
+ scroll_source ==
+ scroll_source->GetDocument().ScrollingElementNoLayout()) {
return &scroll_source->GetDocument();
}
return scroll_source;
}
+
} // namespace
ScrollTimeline* ScrollTimeline::Create(Document& document,
ScrollTimelineOptions* options,
ExceptionState& exception_state) {
- Element* scroll_source = options->hasScrollSource()
- ? options->scrollSource()
- : document.scrollingElement();
+ absl::optional<Element*> scroll_source =
+ options->hasScrollSource() ? absl::make_optional(options->scrollSource())
+ : absl::nullopt;
ScrollDirection orientation;
if (!StringToScrollDirection(options->orientation(), orientation)) {
@@ -139,22 +131,29 @@ ScrollTimeline* ScrollTimeline::Create(Document& document,
}
absl::optional<double> time_range;
- if (options->timeRange().IsDouble()) {
- time_range = absl::make_optional(options->timeRange().GetAsDouble());
+ if (options->timeRange()->IsDouble()) {
+ time_range = absl::make_optional(options->timeRange()->GetAsDouble());
}
+ // The scrollingElement depends on style/layout-tree in quirks mode. Update
+ // such that subsequent calls to ScrollingElementNoLayout returns up-to-date
+ // information.
+ if (document.InQuirksMode())
+ document.UpdateStyleAndLayoutTree();
+
return MakeGarbageCollected<ScrollTimeline>(
&document, scroll_source, orientation, scroll_offsets, time_range);
}
ScrollTimeline::ScrollTimeline(
Document* document,
- Element* scroll_source,
+ absl::optional<Element*> scroll_source,
ScrollDirection orientation,
HeapVector<Member<ScrollTimelineOffset>> scroll_offsets,
absl::optional<double> time_range)
: AnimationTimeline(document),
- scroll_source_(scroll_source),
+ scroll_source_(
+ scroll_source.value_or(document->ScrollingElementNoLayout())),
resolved_scroll_source_(ResolveScrollSource(scroll_source_)),
orientation_(orientation),
scroll_offsets_(std::move(scroll_offsets)),
@@ -289,15 +288,20 @@ bool ScrollTimeline::ScrollOffsetsEqual(
const HeapVector<Member<ScrollTimelineOffset>>& other) const {
if (scroll_offsets_.size() != other.size())
return false;
- size_t size = scroll_offsets_.size();
- for (size_t i = 0; i < size; ++i) {
+ wtf_size_t size = scroll_offsets_.size();
+ for (wtf_size_t i = 0; i < size; ++i) {
if (!DataEquivalent(scroll_offsets_.at(i), other.at(i)))
return false;
}
return true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+V8CSSNumberish* ScrollTimeline::ConvertTimeToProgress(
+ AnimationTimeDelta time) const {
+ return MakeGarbageCollected<V8CSSNumberish>(
+ CSSUnitValues::percent((time / GetDuration().value()) * 100));
+}
+
V8CSSNumberish* ScrollTimeline::currentTime() {
// time returns either in milliseconds or a 0 to 100 value representing the
// progress of the timeline
@@ -307,7 +311,7 @@ V8CSSNumberish* ScrollTimeline::currentTime() {
// We are currently abusing the intended use of the "auto" keyword. We are
// using it here as a signal to use progress based timeline instead of having
// a range based current time.
- // We are doing this maintain backwards compatibility with existing tests.
+ // We are doing this to maintain backwards compatibility with existing tests.
if (time_range_) {
// not using progress based, return time as double
if (current_time) {
@@ -317,55 +321,21 @@ V8CSSNumberish* ScrollTimeline::currentTime() {
return nullptr;
} else {
if (current_time) {
- return MakeGarbageCollected<V8CSSNumberish>(
- CSSUnitValues::percent(current_time->InSecondsF()));
+ return ConvertTimeToProgress(AnimationTimeDelta(current_time.value()));
}
return nullptr;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ScrollTimeline::currentTime(CSSNumberish& currentTime) {
- // time returns either in milliseconds or a 0 to 100 value representing the
- // progress of the timeline
- auto current_time = timeline_state_snapshotted_.current_time;
- // TODO(crbug.com/1140602): Support progress based animations
- // We are currently abusing the intended use of the "auto" keyword. We are
- // using it here as a signal to use progress based timeline instead of having
- // a range based current time.
- // We are doing this maintain backwards compatibility with existing tests.
- if (time_range_) {
- // not using progress based, return time as double
- currentTime =
- current_time ? CSSNumberish::FromDouble(current_time->InMillisecondsF())
- : CSSNumberish();
- } else {
- currentTime = current_time
- ? CSSNumberish::FromCSSNumericValue(
- CSSUnitValues::percent(current_time->InSecondsF()))
- : CSSNumberish();
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* ScrollTimeline::duration() {
+ // TODO (crbug.com/1216655): Time range should be removed from ScrollTimeline.
+ // Currently still left in for the sake of backwards compatibility with
+ // existing tests.
if (time_range_) {
return MakeGarbageCollected<V8CSSNumberish>(time_range_.value());
}
- return MakeGarbageCollected<V8CSSNumberish>(
- CSSUnitValues::percent(kScrollTimelineDuration));
+ return MakeGarbageCollected<V8CSSNumberish>(CSSUnitValues::percent(100));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ScrollTimeline::duration(CSSNumberish& duration) {
- if (time_range_) {
- duration = CSSNumberish::FromDouble(time_range_.value());
- } else {
- duration = CSSNumberish::FromCSSNumericValue(
- CSSUnitValues::percent(kScrollTimelineDuration));
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// https://drafts.csswg.org/scroll-animations-1/#current-time-algorithm
ScrollTimeline::TimelineState ScrollTimeline::ComputeTimelineState() const {
@@ -409,8 +379,12 @@ ScrollTimeline::TimelineState ScrollTimeline::ComputeTimelineState() const {
return {TimelinePhase::kBefore, base::TimeDelta(), resolved_offsets};
}
- double duration =
- time_range_ ? time_range_.value() : kScrollTimelineDurationMs;
+ // TODO (crbug.com/1216655): Time range should be removed from ScrollTimeline.
+ // Currently still left in for the sake of backwards compatibility with
+ // existing tests.
+ base::TimeDelta duration =
+ time_range_ ? base::TimeDelta::FromMillisecondsD(time_range_.value())
+ : base::TimeDelta::FromSecondsD(GetDuration()->InSecondsF());
// 3.2 If current scroll offset is greater than or equal to effective end
// offset:
@@ -421,8 +395,7 @@ ScrollTimeline::TimelineState ScrollTimeline::ComputeTimelineState() const {
// after phase.
TimelinePhase phase = end_offset >= max_offset ? TimelinePhase::kActive
: TimelinePhase::kAfter;
- return {phase, base::TimeDelta::FromMillisecondsD(duration),
- resolved_offsets};
+ return {phase, duration, resolved_offsets};
}
// 3.3 Otherwise,
@@ -434,7 +407,7 @@ ScrollTimeline::TimelineState ScrollTimeline::ComputeTimelineState() const {
absl::optional<base::TimeDelta> calculated_current_time =
base::TimeDelta::FromMillisecondsD(scroll_timeline_util::ComputeProgress(
current_offset, resolved_offsets) *
- duration);
+ duration.InMillisecondsF());
return {TimelinePhase::kActive, calculated_current_time, resolved_offsets};
}
@@ -444,6 +417,24 @@ ScrollTimeline::InitialStartTimeForAnimations() {
return base::TimeDelta();
}
+AnimationTimeDelta ScrollTimeline::CalculateIntrinsicIterationDuration(
+ const Timing& timing) {
+ absl::optional<AnimationTimeDelta> duration = GetDuration();
+
+ // Only run calculation for progress based scroll timelines
+ if (duration) {
+ // if iteration_duration == "auto" and iterations > 0
+ if (!timing.iteration_duration && timing.iteration_count > 0) {
+ // duration represents 100% so we divide it by iteration count to
+ // calculate the iteration duration. TODO: (crbug.com/1216527) Once
+ // delays can be percentages we will include them in the calculation:
+ // ((100% - start_delay% - end_delay%) / iterations) * duration
+ return duration.value() / timing.iteration_count;
+ }
+ }
+ return AnimationTimeDelta();
+}
+
void ScrollTimeline::ServiceAnimations(TimingUpdateReason reason) {
// Snapshot timeline state once at top of animation frame.
if (reason == kTimingUpdateForAnimationFrame)
@@ -500,7 +491,6 @@ String ScrollTimeline::orientation() {
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8ScrollTimelineOffset>> ScrollTimeline::scrollOffsets()
const {
HeapVector<Member<V8ScrollTimelineOffset>> scroll_offsets;
@@ -511,20 +501,7 @@ const HeapVector<Member<V8ScrollTimelineOffset>> ScrollTimeline::scrollOffsets()
}
return scroll_offsets;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-const HeapVector<ScrollTimelineOffsetValue> ScrollTimeline::scrollOffsets()
- const {
- HeapVector<ScrollTimelineOffsetValue> scroll_offsets;
- for (auto& offset : scroll_offsets_) {
- scroll_offsets.push_back(offset->ToScrollTimelineOffsetValue());
- // 'auto' can only be the end offset.
- DCHECK(!offset->IsDefaultValue() || scroll_offsets.size() == 2);
- }
- return scroll_offsets;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionDoubleOrScrollTimelineAutoKeyword* ScrollTimeline::timeRange() const {
// TODO(crbug.com/1140602): Support progress based animations
// We are currently abusing the intended use of the "auto" keyword. We are
@@ -538,20 +515,6 @@ V8UnionDoubleOrScrollTimelineAutoKeyword* ScrollTimeline::timeRange() const {
return MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(
V8ScrollTimelineAutoKeyword(V8ScrollTimelineAutoKeyword::Enum::kAuto));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) {
- // TODO(crbug.com/1140602): Support progress based animations
- // We are currently abusing the intended use of the "auto" keyword. We are
- // using it here as a signal to use progress based timeline instead of having
- // a range based current time.
- // We are doing this maintain backwards compatibility with existing tests.
- if (time_range_) {
- result.SetDouble(time_range_.value());
- } else {
- result.SetScrollTimelineAutoKeyword("auto");
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void ScrollTimeline::GetCurrentAndMaxOffset(const LayoutBox* layout_box,
double& current_offset,
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 7c5a2fc7c72..0fb0db92843 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
@@ -15,7 +15,6 @@
namespace blink {
-class DoubleOrScrollTimelineAutoKeyword;
class ScrollTimelineOptions;
class V8UnionDoubleOrScrollTimelineAutoKeyword;
@@ -44,17 +43,23 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
ExceptionState&);
ScrollTimeline(Document*,
- Element*,
+ absl::optional<Element*> scroll_source,
ScrollDirection,
HeapVector<Member<ScrollTimelineOffset>>,
absl::optional<double>);
bool IsScrollTimeline() const override { return true; }
+ // TODO (crbug.com/1216655): Time range should be removed from ScrollTimeline
+ // at which point this function becomes redundant as all scroll timelines will
+ // then be progress based timelines.
+ bool IsProgressBasedTimeline() const override { return !time_range_; }
// ScrollTimeline is not active if scrollSource is null, does not currently
// have a CSS layout box, or if its layout box is not a scroll container.
// https://github.com/WICG/scroll-animations/issues/31
bool IsActive() const override;
absl::optional<base::TimeDelta> InitialStartTimeForAnimations() override;
+ AnimationTimeDelta CalculateIntrinsicIterationDuration(
+ const Timing&) override;
AnimationTimeDelta ZeroTime() override { return AnimationTimeDelta(); }
void ServiceAnimations(TimingUpdateReason) override;
@@ -63,21 +68,12 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
// IDL API implementation.
Element* scrollSource() const;
String orientation();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8ScrollTimelineOffset>> scrollOffsets() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<ScrollTimelineOffsetValue> scrollOffsets() const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* currentTime() override;
V8CSSNumberish* duration() override;
V8UnionDoubleOrScrollTimelineAutoKeyword* timeRange() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void currentTime(CSSNumberish&) override;
- void duration(CSSNumberish&) override;
- void timeRange(DoubleOrScrollTimelineAutoKeyword&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ V8CSSNumberish* ConvertTimeToProgress(AnimationTimeDelta time) const;
// Returns the Node that should actually have the ScrollableArea (if one
// exists). This can differ from |scrollSource| when |scroll_source_| is the
@@ -128,9 +124,22 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
// overflow, adding and removal of scrollable area.
static void Invalidate(Node* node);
+ // TODO (crbug.com/1216655): Time range should be removed from ScrollTimeline.
+ // Currently still left in for the sake of backwards compatibility with
+ // existing tests.
+ double GetTimeRange() const { return time_range_ ? time_range_.value() : 0; }
+
+ // Duration is the maximum value a timeline may generate for current time.
+ // Used to convert time values to proportional values.
+ absl::optional<AnimationTimeDelta> GetDuration() const override {
+ return time_range_
+ ? absl::nullopt
+ // Any arbitrary value should be able to be used here.
+ : absl::make_optional(AnimationTimeDelta::FromSecondsD(100));
+ }
+
protected:
PhaseAndTime CurrentPhaseAndTime() override;
- double GetTimeRange() const { return time_range_ ? time_range_.value() : 0; }
bool ScrollOffsetsEqual(
const HeapVector<Member<ScrollTimelineOffset>>& other) const;
@@ -179,6 +188,9 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
ScrollDirection orientation_;
HeapVector<Member<ScrollTimelineOffset>> scroll_offsets_;
+ // TODO (crbug.com/1216655): Time range should be removed from ScrollTimeline.
+ // Currently still left in for the sake of backwards compatibility with
+ // existing tests.
absl::optional<double> time_range_;
// Snapshotted value produced by the last SnapshotState call.
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc
index 4e4d8405464..dc38a92cd3d 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/css_numeric_value_or_string_or_css_keyword_value_or_scroll_timeline_element_based_offset.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_element_based_offset.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_csskeywordvalue_cssnumericvalue_scrolltimelineelementbasedoffset_string.h"
#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
@@ -22,7 +21,8 @@ namespace blink {
namespace {
-bool ValidateElementBasedOffset(ScrollTimelineElementBasedOffset* offset) {
+bool ValidateElementBasedOffset(
+ const ScrollTimelineElementBasedOffset* offset) {
if (!offset->hasTarget())
return false;
@@ -66,45 +66,45 @@ bool ElementBasedOffsetsEqual(ScrollTimelineElementBasedOffset* o1,
o1->threshold() == o2->threshold();
}
-CSSKeywordValue* GetCSSKeywordValue(const ScrollTimelineOffsetValue& offset) {
- if (offset.IsCSSKeywordValue())
- return offset.GetAsCSSKeywordValue();
- // CSSKeywordish:
- if (offset.IsString() && !offset.GetAsString().IsEmpty())
- return CSSKeywordValue::Create(offset.GetAsString());
- return nullptr;
-}
-
} // namespace
// static
ScrollTimelineOffset* ScrollTimelineOffset::Create(
- const ScrollTimelineOffsetValue& input_offset) {
- if (input_offset.IsCSSNumericValue()) {
- auto* numeric = input_offset.GetAsCSSNumericValue();
- const auto& offset = To<CSSPrimitiveValue>(*numeric->ToCSSValue());
- bool matches_length_percentage = offset.IsLength() ||
- offset.IsPercentage() ||
- offset.IsCalculatedPercentageWithLength();
- if (!matches_length_percentage)
- return nullptr;
- return MakeGarbageCollected<ScrollTimelineOffset>(&offset);
- }
-
- if (input_offset.IsScrollTimelineElementBasedOffset()) {
- auto* offset = input_offset.GetAsScrollTimelineElementBasedOffset();
- if (!ValidateElementBasedOffset(offset))
- return nullptr;
-
- return MakeGarbageCollected<ScrollTimelineOffset>(offset);
- }
-
- if (auto* keyword = GetCSSKeywordValue(input_offset)) {
- if (keyword->KeywordValueID() != CSSValueID::kAuto)
- return nullptr;
- return MakeGarbageCollected<ScrollTimelineOffset>();
+ const V8ScrollTimelineOffset* offset) {
+ switch (offset->GetContentType()) {
+ case V8ScrollTimelineOffset::ContentType::kCSSKeywordValue: {
+ const auto* keyword = offset->GetAsCSSKeywordValue();
+ if (keyword->KeywordValueID() != CSSValueID::kAuto)
+ return nullptr;
+ return MakeGarbageCollected<ScrollTimelineOffset>();
+ }
+ case V8ScrollTimelineOffset::ContentType::kCSSNumericValue: {
+ const auto* value =
+ To<CSSPrimitiveValue>(offset->GetAsCSSNumericValue()->ToCSSValue());
+ bool matches_length_percentage =
+ value->IsLength() || value->IsPercentage() ||
+ value->IsCalculatedPercentageWithLength();
+ if (!matches_length_percentage)
+ return nullptr;
+ return MakeGarbageCollected<ScrollTimelineOffset>(value);
+ }
+ case V8ScrollTimelineOffset::ContentType::
+ kScrollTimelineElementBasedOffset: {
+ auto* value = offset->GetAsScrollTimelineElementBasedOffset();
+ if (!ValidateElementBasedOffset(value))
+ return nullptr;
+ return MakeGarbageCollected<ScrollTimelineOffset>(value);
+ }
+ case V8ScrollTimelineOffset::ContentType::kString: {
+ if (offset->GetAsString().IsEmpty())
+ return nullptr;
+ const auto* keyword = CSSKeywordValue::Create(offset->GetAsString());
+ if (keyword->KeywordValueID() != CSSValueID::kAuto)
+ return nullptr;
+ return MakeGarbageCollected<ScrollTimelineOffset>();
+ }
}
-
+ NOTREACHED();
return nullptr;
}
@@ -125,9 +125,10 @@ absl::optional<double> ScrollTimelineOffset::ResolveOffset(
? document.documentElement()->GetComputedStyle()
: document.GetComputedStyle();
+ // TOOD(crbug.com/1223030): Handle container relative units.
CSSToLengthConversionData conversion_data = CSSToLengthConversionData(
&computed_style, root_style, document.GetLayoutView(),
- computed_style.EffectiveZoom());
+ /* nearest_container */ nullptr, computed_style.EffectiveZoom());
double resolved = FloatValueForLength(
length_based_offset_->ConvertToLength(conversion_data), max_offset);
@@ -210,7 +211,6 @@ absl::optional<double> ScrollTimelineOffset::ResolveOffset(
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8ScrollTimelineOffset* ScrollTimelineOffset::ToV8ScrollTimelineOffset() const {
if (length_based_offset_) {
return MakeGarbageCollected<V8ScrollTimelineOffset>(
@@ -222,23 +222,6 @@ V8ScrollTimelineOffset* ScrollTimelineOffset::ToV8ScrollTimelineOffset() const {
return MakeGarbageCollected<V8ScrollTimelineOffset>(
CSSKeywordValue::Create("auto"));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScrollTimelineOffsetValue ScrollTimelineOffset::ToScrollTimelineOffsetValue()
- const {
- ScrollTimelineOffsetValue result;
- if (length_based_offset_) {
- result.SetCSSNumericValue(
- CSSNumericValue::FromCSSValue(*length_based_offset_.Get()));
- } else if (element_based_offset_) {
- result.SetScrollTimelineElementBasedOffset(element_based_offset_);
- } else {
- // This is the default value (i.e., 'auto' value)
- result.SetCSSKeywordValue(CSSKeywordValue::Create("auto"));
- }
-
- return result;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool ScrollTimelineOffset::operator==(const ScrollTimelineOffset& o) const {
return DataEquivalent(length_based_offset_, o.length_based_offset_) &&
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h
index 5cf0c9e4611..55ba05de76d 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_OFFSET_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_OFFSET_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_element_based_offset.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
@@ -13,18 +14,12 @@
namespace blink {
-class
- CSSNumericValueOrStringOrCSSKeywordValueOrScrollTimelineElementBasedOffset;
-
-using ScrollTimelineOffsetValue =
- CSSNumericValueOrStringOrCSSKeywordValueOrScrollTimelineElementBasedOffset;
-
// Represent a scroll timeline start/end offset which can be an
// scroll offset or an element based offset
class CORE_EXPORT ScrollTimelineOffset final
: public GarbageCollected<ScrollTimelineOffset> {
public:
- static ScrollTimelineOffset* Create(const ScrollTimelineOffsetValue& offset);
+ static ScrollTimelineOffset* Create(const V8ScrollTimelineOffset* offset);
// Create a default offset representing 'auto'.
ScrollTimelineOffset() = default;
@@ -53,11 +48,7 @@ class CORE_EXPORT ScrollTimelineOffset final
double max_offset,
double default_offset);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8ScrollTimelineOffset* ToV8ScrollTimelineOffset() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollTimelineOffsetValue ToScrollTimelineOffsetValue() const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool IsDefaultValue() const {
return !length_based_offset_ && !element_based_offset_;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset_test.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset_test.cc
index fb883616c30..41b620e3bb5 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_csskeywordvalue_cssnumericvalue_scrolltimelineelementbasedoffset_string.h"
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
@@ -27,8 +28,7 @@ class ScrollTimelineOffsetTest : public PageTestBase {
auto* inner = CreateElementBasedOffset(target, edge, threshold);
if (!inner)
return nullptr;
- ScrollTimelineOffsetValue param;
- param.SetScrollTimelineElementBasedOffset(inner);
+ auto* param = MakeGarbageCollected<V8ScrollTimelineOffset>(inner);
return ScrollTimelineOffset::Create(param);
}
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 bdc9d1c9dd8..a126710d7d0 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
@@ -6,6 +6,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_csskeywordvalue_cssnumericvalue_scrolltimelineelementbasedoffset_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
@@ -91,7 +93,7 @@ class ScrollTimelineTest : public RenderingTest {
return count;
}
- ScrollTimelineOffsetValue OffsetFromString(const String& value) {
+ V8ScrollTimelineOffset* OffsetFromString(const String& value) {
return animation_test_helpers::OffsetFromString(GetDocument(), value);
}
};
@@ -134,8 +136,8 @@ TEST_F(ScrollTimelineTest, CurrentTimeIsNullIfScrollSourceIsNotScrollable) {
ASSERT_TRUE(scroller);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -164,8 +166,8 @@ TEST_F(ScrollTimelineTest,
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
options->setScrollOffsets(
@@ -173,7 +175,6 @@ TEST_F(ScrollTimelineTest,
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
- bool current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 5),
mojom::blink::ScrollType::kProgrammatic);
// Simulate a new animation frame which allows the timeline to compute new
@@ -182,34 +183,30 @@ TEST_F(ScrollTimelineTest,
EXPECT_EQ(scroll_timeline->CurrentTimeMilliseconds(), 0);
EXPECT_EQ("before", scroll_timeline->phase());
- current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 10),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
EXPECT_EQ(scroll_timeline->CurrentTimeMilliseconds(), 0);
EXPECT_EQ("active", scroll_timeline->phase());
- current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 50),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
EXPECT_EQ(scroll_timeline->CurrentTimeMilliseconds(), 50);
EXPECT_EQ("active", scroll_timeline->phase());
- current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 90),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
EXPECT_EQ(scroll_timeline->CurrentTimeMilliseconds(),
- time_range.GetAsDouble());
+ time_range->GetAsDouble());
EXPECT_EQ("after", scroll_timeline->phase());
- current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
EXPECT_EQ(scroll_timeline->CurrentTimeMilliseconds(),
- time_range.GetAsDouble());
+ time_range->GetAsDouble());
EXPECT_EQ("after", scroll_timeline->phase());
EXPECT_TRUE(scroll_timeline->IsActive());
}
@@ -233,8 +230,8 @@ TEST_F(ScrollTimelineTest,
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
options->setScrollOffsets(
@@ -242,7 +239,6 @@ TEST_F(ScrollTimelineTest,
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
- bool current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
// Simulate a new animation frame which allows the timeline to compute new
@@ -251,18 +247,16 @@ TEST_F(ScrollTimelineTest,
EXPECT_EQ(0, scroll_timeline->CurrentTimeMilliseconds());
EXPECT_EQ("before", scroll_timeline->phase());
- current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 60),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
EXPECT_EQ(0, scroll_timeline->CurrentTimeMilliseconds());
EXPECT_EQ("before", scroll_timeline->phase());
- current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- EXPECT_EQ(time_range.GetAsDouble(),
+ EXPECT_EQ(time_range->GetAsDouble(),
scroll_timeline->CurrentTimeMilliseconds());
EXPECT_EQ("after", scroll_timeline->phase());
EXPECT_TRUE(scroll_timeline->IsActive());
@@ -286,8 +280,8 @@ TEST_F(ScrollTimelineTest, PhasesAreCorrectWhenUsingOffsets) {
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
options->setScrollOffsets(
@@ -333,8 +327,8 @@ TEST_F(ScrollTimelineTest,
// Create the ScrollTimeline with Document.scrollingElement() as source. The
// resolved scroll source should be the Document.
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetDocument().scrollingElement());
ScrollTimeline* scroll_timeline =
@@ -359,8 +353,8 @@ TEST_F(ScrollTimelineTest,
// Create the ScrollTimeline with Document.scrollingElement() as source. The
// resolved scroll source should be the Document.
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetDocument().scrollingElement());
ScrollTimeline* scroll_timeline =
@@ -724,8 +718,8 @@ TEST_F(ScrollTimelineTest, CurrentTimeUpdateAfterNewAnimationFrame) {
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
@@ -934,10 +928,11 @@ TEST_F(ScrollTimelineTest, ResolveScrollOffsets) {
double time_range = 100.0;
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
options->setTimeRange(
- DoubleOrScrollTimelineAutoKeyword::FromDouble(time_range));
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(
+ time_range));
options->setScrollSource(GetElementById("scroller"));
// Empty scroll offsets resolve into [0, 100%].
- HeapVector<ScrollTimelineOffsetValue> scroll_offsets = {};
+ HeapVector<Member<V8ScrollTimelineOffset>> scroll_offsets = {};
options->setScrollOffsets(scroll_offsets);
ScrollTimeline* scroll_timeline =
@@ -1001,9 +996,10 @@ TEST_F(ScrollTimelineTest, MultipleScrollOffsetsCurrentTimeCalculations) {
double time_range = 100.0;
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
options->setTimeRange(
- DoubleOrScrollTimelineAutoKeyword::FromDouble(time_range));
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(
+ time_range));
options->setScrollSource(GetElementById("scroller"));
- HeapVector<ScrollTimelineOffsetValue> scroll_offsets;
+ HeapVector<Member<V8ScrollTimelineOffset>> scroll_offsets;
scroll_offsets.push_back(OffsetFromString("10px"));
scroll_offsets.push_back(OffsetFromString("20px"));
scroll_offsets.push_back(OffsetFromString("40px"));
@@ -1092,9 +1088,10 @@ TEST_F(ScrollTimelineTest, OverlappingScrollOffsets) {
double time_range = 100.0;
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
options->setTimeRange(
- DoubleOrScrollTimelineAutoKeyword::FromDouble(time_range));
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(
+ time_range));
options->setScrollSource(GetElementById("scroller"));
- HeapVector<ScrollTimelineOffsetValue> scroll_offsets = {
+ HeapVector<Member<V8ScrollTimelineOffset>> scroll_offsets = {
OffsetFromString("90px"), OffsetFromString("40px"),
OffsetFromString("10px")};
options->setScrollOffsets(scroll_offsets);
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc
index 714034716e1..a33ffa18b67 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline_util.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
@@ -26,16 +25,6 @@ scoped_refptr<CompositorScrollTimeline> ToCompositorScrollTimeline(
absl::optional<CompositorElementId> element_id =
GetCompositorScrollElementId(scroll_source);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- auto* time_range = scroll_timeline->timeRange();
- DCHECK(time_range);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DoubleOrScrollTimelineAutoKeyword time_range;
- scroll_timeline->timeRange(time_range);
- // TODO(smcgruer): Handle 'auto' time range value.
- DCHECK(time_range.IsDouble());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
LayoutBox* box =
scroll_timeline->IsActive() ? scroll_source->GetLayoutBox() : nullptr;
@@ -44,12 +33,7 @@ scoped_refptr<CompositorScrollTimeline> ToCompositorScrollTimeline(
return CompositorScrollTimeline::Create(
element_id, orientation, scroll_timeline->GetResolvedScrollOffsets(),
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- time_range->GetAsDouble()
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- time_range.GetAsDouble()
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- );
+ scroll_timeline->GetTimeRange());
}
absl::optional<CompositorElementId> GetCompositorScrollElementId(
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc
index 223443d5116..8f111114fde 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc
@@ -6,8 +6,11 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_csskeywordvalue_cssnumericvalue_scrolltimelineelementbasedoffset_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -61,7 +64,8 @@ TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimeline) {
options->setScrollSource(scroller);
const double time_range = 100;
options->setTimeRange(
- DoubleOrScrollTimelineAutoKeyword::FromDouble(time_range));
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(
+ time_range));
options->setOrientation("block");
options->setScrollOffsets({OffsetFromString(GetDocument(), "50px"),
OffsetFromString(GetDocument(), "auto")});
@@ -115,8 +119,8 @@ TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimelineNullLayoutBox) {
ASSERT_FALSE(div->GetLayoutBox());
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(div);
ScrollTimeline* timeline =
diff --git a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
index 4503d3bb652..f0db35c5666 100644
--- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
+++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
@@ -19,17 +19,6 @@ namespace blink {
namespace {
-// Returns handle for the given CSSProperty.
-// |value| is required only for custom properties.
-PropertyHandle ToPropertyHandle(const CSSProperty& property,
- const CSSValue* value) {
- if (property.IDEquals(CSSPropertyID::kVariable)) {
- return PropertyHandle(To<CSSCustomPropertyDeclaration>(*value).GetName());
- } else {
- return PropertyHandle(property, false);
- }
-}
-
bool IsLogicalProperty(CSSPropertyID property_id) {
const CSSProperty& property = CSSProperty::Get(property_id);
const CSSProperty& resolved_property = property.ResolveDirectionAwareProperty(
@@ -135,15 +124,20 @@ MutableCSSPropertyValueSet::SetResult StringKeyframe::SetCSSPropertyValue(
return result;
}
-void StringKeyframe::SetCSSPropertyValue(const CSSProperty& property,
+void StringKeyframe::SetCSSPropertyValue(const CSSPropertyName& name,
const CSSValue& value) {
- CSSPropertyID property_id = property.PropertyID();
+ CSSPropertyID property_id = name.Id();
DCHECK_NE(property_id, CSSPropertyID::kInvalid);
- DCHECK(!CSSAnimations::IsAnimationAffectingProperty(property));
- DCHECK(!property.IsShorthand());
+#if DCHECK_IS_ON()
+ if (property_id != CSSPropertyID::kVariable) {
+ const CSSProperty& property = CSSProperty::Get(property_id);
+ DCHECK(!CSSAnimations::IsAnimationAffectingProperty(property));
+ DCHECK(!property.IsShorthand());
+ }
+#endif // DCHECK_IS_ON()
DCHECK(!IsLogicalProperty(property_id));
input_properties_.Set(
- ToPropertyHandle(property, &value),
+ PropertyHandle(name),
MakeGarbageCollected<PropertyResolver>(property_id, value));
InvalidateCssPropertyMap();
}
@@ -181,12 +175,12 @@ PropertyHandleSet StringKeyframe::Properties() const {
for (unsigned i = 0; i < css_property_map_->PropertyCount(); ++i) {
CSSPropertyValueSet::PropertyReference property_reference =
css_property_map_->PropertyAt(i);
- // TODO(crbug.com/980160): Remove access to static Variable instance.
- const CSSProperty& property = CSSProperty::Get(property_reference.Id());
- DCHECK(!property.IsShorthand())
+ const CSSPropertyName& name = property_reference.Name();
+ DCHECK(!name.IsCustomProperty() ||
+ !CSSProperty::Get(name.Id()).IsShorthand())
<< "Web Animations: Encountered unexpanded shorthand CSS property ("
- << static_cast<int>(property.PropertyID()) << ").";
- properties.insert(ToPropertyHandle(property, &property_reference.Value()));
+ << static_cast<int>(name.Id()) << ").";
+ properties.insert(PropertyHandle(name));
}
for (unsigned i = 0; i < presentation_attribute_map_->PropertyCount(); ++i) {
diff --git a/chromium/third_party/blink/renderer/core/animation/string_keyframe.h b/chromium/third_party/blink/renderer/core/animation/string_keyframe.h
index a46dbc5e87a..7928e8cbe41 100644
--- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.h
+++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.h
@@ -12,6 +12,7 @@
namespace blink {
+class CSSPropertyName;
class StyleSheetContents;
// An implementation of Keyframe used for CSS Animations, web-animations, and
@@ -41,7 +42,7 @@ class CORE_EXPORT StringKeyframe : public Keyframe {
const String& value,
SecureContextMode,
StyleSheetContents*);
- void SetCSSPropertyValue(const CSSProperty&, const CSSValue&);
+ void SetCSSPropertyValue(const CSSPropertyName&, const CSSValue&);
void RemoveCustomCSSProperty(const PropertyHandle& property);
void SetPresentationAttributeValue(const CSSProperty&,
diff --git a/chromium/third_party/blink/renderer/core/animation/test_data/scale-animation.html b/chromium/third_party/blink/renderer/core/animation/test_data/scale-animation.html
index 22e197dc79d..4e4fec2df0e 100644
--- a/chromium/third_party/blink/renderer/core/animation/test_data/scale-animation.html
+++ b/chromium/third_party/blink/renderer/core/animation/test_data/scale-animation.html
@@ -8,6 +8,9 @@
.animate {
animation-name: test;
animation-duration: 1s;
+ width: 10px;
+ height: 10px;
+ background: green;
}
</style>
<div id="target" class="animate">TARGET</div>
diff --git a/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation-update.html b/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation-update.html
index 4f011a80917..399e3bf576d 100644
--- a/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation-update.html
+++ b/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation-update.html
@@ -7,6 +7,7 @@
#target {
width: 100px;
height: 100px;
+ background: green;
animation: rotate 9999s linear 0s infinite;
}
.backface-visible {
diff --git a/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation.html b/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation.html
index 9bfccc43f9a..33d682b33b4 100644
--- a/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation.html
+++ b/chromium/third_party/blink/renderer/core/animation/test_data/transform-animation.html
@@ -8,6 +8,9 @@
.animate {
animation-name: test;
animation-duration: 1s;
+ width: 10px;
+ height: 10px;
+ background: green;
}
</style>
<div id="target" class="animate">TARGET</div>
diff --git a/chromium/third_party/blink/renderer/core/animation/timing.cc b/chromium/third_party/blink/renderer/core/animation/timing.cc
index c1cec54438f..5138547f32e 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing.cc
@@ -6,8 +6,10 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_computed_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_effect_timing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/timing_calculations.h"
-#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unit_values.h"
namespace blink {
@@ -66,39 +68,21 @@ Timing::FillMode Timing::ResolvedFillMode(bool is_keyframe_effect) const {
return Timing::FillMode::BOTH;
}
-AnimationTimeDelta Timing::IterationDuration() const {
- AnimationTimeDelta result = iteration_duration.value_or(AnimationTimeDelta());
- DCHECK_GE(result, AnimationTimeDelta());
- return result;
-}
-
-AnimationTimeDelta Timing::ActiveDuration() const {
- const AnimationTimeDelta result =
- MultiplyZeroAlwaysGivesZero(IterationDuration(), iteration_count);
- DCHECK_GE(result, AnimationTimeDelta());
- return result;
-}
-
-AnimationTimeDelta Timing::EndTimeInternal() const {
- // Per the spec, the end time has a lower bound of 0.0:
- // https://drafts.csswg.org/web-animations-1/#end-time
- return std::max(start_delay + ActiveDuration() + end_delay,
- AnimationTimeDelta());
-}
-
EffectTiming* Timing::ConvertToEffectTiming() const {
EffectTiming* effect_timing = EffectTiming::Create();
+ // Specified values used here so that inputs match outputs for JS API calls
effect_timing->setDelay(start_delay.InMillisecondsF());
effect_timing->setEndDelay(end_delay.InMillisecondsF());
effect_timing->setFill(FillModeString(fill_mode));
effect_timing->setIterationStart(iteration_start);
effect_timing->setIterations(iteration_count);
- UnrestrictedDoubleOrString duration;
+ V8UnionStringOrUnrestrictedDouble* duration;
if (iteration_duration) {
- duration.SetUnrestrictedDouble(iteration_duration->InMillisecondsF());
+ duration = MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
+ iteration_duration->InMillisecondsF());
} else {
- duration.SetString("auto");
+ duration = MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>("auto");
}
effect_timing->setDuration(duration);
effect_timing->setDirection(PlaybackDirectionString(direction));
@@ -107,23 +91,38 @@ EffectTiming* Timing::ConvertToEffectTiming() const {
return effect_timing;
}
+// Converts values to CSSNumberish based on corresponding timeline type
+V8CSSNumberish* Timing::ToComputedValue(
+ absl::optional<AnimationTimeDelta> time,
+ absl::optional<AnimationTimeDelta> max_time) const {
+ if (time) {
+ // A valid timeline_duration indicates use of progress based timeline. We
+ // need to convert values to percentages using timeline_duration as 100%
+ if (max_time) {
+ return MakeGarbageCollected<V8CSSNumberish>(
+ CSSUnitValues::percent((time.value() / max_time.value()) * 100));
+ } else {
+ // For time based timeline, simply return the value in milliseconds.
+ return MakeGarbageCollected<V8CSSNumberish>(
+ time.value().InMillisecondsF());
+ }
+ }
+ return nullptr;
+}
+
ComputedEffectTiming* Timing::getComputedTiming(
const CalculatedTiming& calculated_timing,
+ const NormalizedTiming& normalized_timing,
bool is_keyframe_effect) const {
ComputedEffectTiming* computed_timing = ComputedEffectTiming::Create();
// ComputedEffectTiming members.
- computed_timing->setEndTime(
- CSSNumberish::FromDouble(EndTimeInternal().InMillisecondsF()));
- computed_timing->setActiveDuration(
- CSSNumberish::FromDouble(ActiveDuration().InMillisecondsF()));
-
- if (calculated_timing.local_time) {
- computed_timing->setLocalTime(CSSNumberish::FromDouble(
- calculated_timing.local_time->InMillisecondsF()));
- } else {
- computed_timing->setLocalTime(CSSNumberish());
- }
+ computed_timing->setEndTime(ToComputedValue(
+ normalized_timing.end_time, normalized_timing.timeline_duration));
+ computed_timing->setActiveDuration(ToComputedValue(
+ normalized_timing.active_duration, normalized_timing.timeline_duration));
+ computed_timing->setLocalTime(ToComputedValue(
+ calculated_timing.local_time, normalized_timing.timeline_duration));
if (calculated_timing.is_in_effect) {
DCHECK(calculated_timing.current_iteration);
@@ -132,14 +131,17 @@ ComputedEffectTiming* Timing::getComputedTiming(
computed_timing->setCurrentIteration(
calculated_timing.current_iteration.value());
} else {
- computed_timing->setProgressToNull();
- computed_timing->setCurrentIterationToNull();
+ computed_timing->setProgress(absl::nullopt);
+ computed_timing->setCurrentIteration(absl::nullopt);
}
// For the EffectTiming members, getComputedTiming is equivalent to getTiming
// except that the fill and duration must be resolved.
//
// https://drafts.csswg.org/web-animations-1/#dom-animationeffect-getcomputedtiming
+
+ // TODO(crbug.com/1216527): Animation effect timing members start_delay and
+ // end_delay should be CSSNumberish
computed_timing->setDelay(start_delay.InMillisecondsF());
computed_timing->setEndDelay(end_delay.InMillisecondsF());
computed_timing->setFill(
@@ -147,9 +149,22 @@ ComputedEffectTiming* Timing::getComputedTiming(
computed_timing->setIterationStart(iteration_start);
computed_timing->setIterations(iteration_count);
- UnrestrictedDoubleOrString duration;
- duration.SetUnrestrictedDouble(IterationDuration().InMillisecondsF());
- computed_timing->setDuration(duration);
+ // TODO(crbug.com/1219008): Animation effect computed iteration_duration
+ // should return CSSNumberish, which will simplify this logic.
+ V8CSSNumberish* computed_duration =
+ ToComputedValue(normalized_timing.iteration_duration,
+ normalized_timing.timeline_duration);
+ if (computed_duration->IsCSSNumericValue()) {
+ computed_timing->setDuration(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
+ computed_duration->GetAsCSSNumericValue()
+ ->to(CSSPrimitiveValue::UnitType::kPercentage)
+ ->value()));
+ } else {
+ computed_timing->setDuration(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
+ computed_duration->GetAsDouble()));
+ }
computed_timing->setDirection(Timing::PlaybackDirectionString(direction));
computed_timing->setEasing(timing_function->ToString());
@@ -160,23 +175,24 @@ ComputedEffectTiming* Timing::getComputedTiming(
Timing::CalculatedTiming Timing::CalculateTimings(
absl::optional<AnimationTimeDelta> local_time,
absl::optional<Phase> timeline_phase,
+ const NormalizedTiming& normalized_timing,
AnimationDirection animation_direction,
bool is_keyframe_effect,
absl::optional<double> playback_rate) const {
- const AnimationTimeDelta active_duration = ActiveDuration();
+ const AnimationTimeDelta active_duration = normalized_timing.active_duration;
+ const AnimationTimeDelta duration = normalized_timing.iteration_duration;
Timing::Phase current_phase = CalculatePhase(
- active_duration, local_time, timeline_phase, animation_direction, *this);
+ normalized_timing, local_time, timeline_phase, animation_direction);
- const absl::optional<AnimationTimeDelta> active_time =
- CalculateActiveTime(active_duration, ResolvedFillMode(is_keyframe_effect),
- local_time, current_phase, *this);
+ const absl::optional<AnimationTimeDelta> active_time = CalculateActiveTime(
+ normalized_timing, ResolvedFillMode(is_keyframe_effect), local_time,
+ current_phase);
absl::optional<double> progress;
- const absl::optional<double> overall_progress =
- CalculateOverallProgress(current_phase, active_time, IterationDuration(),
- iteration_count, iteration_start);
+ const absl::optional<double> overall_progress = CalculateOverallProgress(
+ current_phase, active_time, duration, iteration_count, iteration_start);
const absl::optional<double> simple_iteration_progress =
CalculateSimpleIterationProgress(current_phase, overall_progress,
iteration_start, active_time,
@@ -196,20 +212,19 @@ Timing::CalculatedTiming Timing::CalculateTimings(
AnimationTimeDelta time_to_next_iteration = AnimationTimeDelta::Max();
// Conditionally compute the time to next iteration, which is only
// applicable if the iteration duration is non-zero.
- if (!IterationDuration().is_zero()) {
+ if (!duration.is_zero()) {
const AnimationTimeDelta start_offset =
- MultiplyZeroAlwaysGivesZero(IterationDuration(), iteration_start);
+ MultiplyZeroAlwaysGivesZero(duration, iteration_start);
DCHECK_GE(start_offset, AnimationTimeDelta());
const absl::optional<AnimationTimeDelta> offset_active_time =
CalculateOffsetActiveTime(active_duration, active_time, start_offset);
const absl::optional<AnimationTimeDelta> iteration_time =
- CalculateIterationTime(IterationDuration(), active_duration,
- offset_active_time, start_offset, current_phase,
- *this);
+ CalculateIterationTime(duration, active_duration, offset_active_time,
+ start_offset, current_phase, *this);
if (iteration_time) {
// active_time cannot be null if iteration_time is not null.
DCHECK(active_time);
- time_to_next_iteration = IterationDuration() - iteration_time.value();
+ time_to_next_iteration = duration - iteration_time.value();
if (active_duration - active_time.value() < time_to_next_iteration)
time_to_next_iteration = AnimationTimeDelta::Max();
}
diff --git a/chromium/third_party/blink/renderer/core/animation/timing.h b/chromium/third_party/blink/renderer/core/animation/timing.h
index cb00ec731ed..4ef4abf7811 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing.h
+++ b/chromium/third_party/blink/renderer/core/animation/timing.h
@@ -34,6 +34,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/animation_time_delta.h"
+#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/style/data_equivalency.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h"
#include "third_party/blink/renderer/platform/animation/timing_function.h"
@@ -101,13 +102,6 @@ struct CORE_EXPORT Timing {
DCHECK(timing_function);
}
- // https://drafts.csswg.org/web-animations-1/#iteration-duration
- AnimationTimeDelta IterationDuration() const;
-
- // https://drafts.csswg.org/web-animations-1/#active-duration
- AnimationTimeDelta ActiveDuration() const;
- AnimationTimeDelta EndTimeInternal() const;
-
Timing::FillMode ResolvedFillMode(bool is_animation) const;
EffectTiming* ConvertToEffectTiming() const;
@@ -133,6 +127,10 @@ struct CORE_EXPORT Timing {
}
bool HasTimingOverrides() { return timing_overrides != kOverrideNode; }
+ V8CSSNumberish* ToComputedValue(absl::optional<AnimationTimeDelta>,
+ absl::optional<AnimationTimeDelta>) const;
+
+ // TODO(crbug.com/1216527): Support CSSNumberish delays
AnimationTimeDelta start_delay;
AnimationTimeDelta end_delay;
FillMode fill_mode = FillMode::AUTO;
@@ -165,13 +163,31 @@ struct CORE_EXPORT Timing {
AnimationTimeDelta time_to_next_iteration = AnimationTimeDelta::Max();
};
+ // Normalized values contain specified timing values after normalizing to
+ // timeline.
+ struct NormalizedTiming {
+ DISALLOW_NEW();
+ // Value used in normalization math. Stored so that we can convert back if
+ // needed.
+ absl::optional<AnimationTimeDelta> timeline_duration;
+ AnimationTimeDelta start_delay;
+ AnimationTimeDelta end_delay;
+ AnimationTimeDelta iteration_duration;
+ // Calculated as (iteration_duration * iteration_count)
+ AnimationTimeDelta active_duration;
+ // Calculated as (start_delay + active_duration + end_delay)
+ AnimationTimeDelta end_time;
+ };
+
CalculatedTiming CalculateTimings(
absl::optional<AnimationTimeDelta> local_time,
absl::optional<Phase> timeline_phase,
+ const NormalizedTiming& normalized_timing,
AnimationDirection animation_direction,
bool is_keyframe_effect,
absl::optional<double> playback_rate) const;
ComputedEffectTiming* getComputedTiming(const CalculatedTiming& calculated,
+ const NormalizedTiming& normalized,
bool is_keyframe_effect) const;
};
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
index 56966564ed1..de1059ba672 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
+++ b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMING_CALCULATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMING_CALCULATIONS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -108,20 +109,18 @@ static inline AnimationTimeDelta MultiplyZeroAlwaysGivesZero(
// https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states
static inline Timing::Phase CalculatePhase(
- AnimationTimeDelta active_duration,
+ const Timing::NormalizedTiming& normalized,
absl::optional<AnimationTimeDelta> local_time,
absl::optional<Timing::Phase> timeline_phase,
- Timing::AnimationDirection direction,
- const Timing& specified) {
- DCHECK(GreaterThanOrEqualToWithinTimeTolerance(active_duration,
+ Timing::AnimationDirection direction) {
+ DCHECK(GreaterThanOrEqualToWithinTimeTolerance(normalized.active_duration,
AnimationTimeDelta()));
if (!local_time)
return Timing::kPhaseNone;
- AnimationTimeDelta end_time =
- std::max(specified.start_delay + active_duration + specified.end_delay,
- AnimationTimeDelta());
+
AnimationTimeDelta before_active_boundary_time =
- std::max(std::min(specified.start_delay, end_time), AnimationTimeDelta());
+ std::max(std::min(normalized.start_delay, normalized.end_time),
+ AnimationTimeDelta());
if (local_time.value() < before_active_boundary_time ||
(local_time.value() == before_active_boundary_time && timeline_phase &&
timeline_phase.value() == Timing::kPhaseBefore) ||
@@ -130,7 +129,8 @@ static inline Timing::Phase CalculatePhase(
return Timing::kPhaseBefore;
}
AnimationTimeDelta active_after_boundary_time =
- std::max(std::min(specified.start_delay + active_duration, end_time),
+ std::max(std::min(normalized.start_delay + normalized.active_duration,
+ normalized.end_time),
AnimationTimeDelta());
if (local_time > active_after_boundary_time ||
(local_time.value() == active_after_boundary_time && timeline_phase &&
@@ -144,33 +144,31 @@ static inline Timing::Phase CalculatePhase(
// https://drafts.csswg.org/web-animations/#calculating-the-active-time
static inline absl::optional<AnimationTimeDelta> CalculateActiveTime(
- AnimationTimeDelta active_duration,
+ const Timing::NormalizedTiming& normalized,
Timing::FillMode fill_mode,
absl::optional<AnimationTimeDelta> local_time,
- Timing::Phase phase,
- const Timing& specified) {
- DCHECK(GreaterThanOrEqualToWithinTimeTolerance(active_duration,
+ Timing::Phase phase) {
+ DCHECK(GreaterThanOrEqualToWithinTimeTolerance(normalized.active_duration,
AnimationTimeDelta()));
-
switch (phase) {
case Timing::kPhaseBefore:
if (fill_mode == Timing::FillMode::BACKWARDS ||
fill_mode == Timing::FillMode::BOTH) {
DCHECK(local_time.has_value());
- return std::max(local_time.value() - specified.start_delay,
+ return std::max(local_time.value() - normalized.start_delay,
AnimationTimeDelta());
}
return absl::nullopt;
case Timing::kPhaseActive:
DCHECK(local_time.has_value());
- return local_time.value() - specified.start_delay;
+ return local_time.value() - normalized.start_delay;
case Timing::kPhaseAfter:
if (fill_mode == Timing::FillMode::FORWARDS ||
fill_mode == Timing::FillMode::BOTH) {
DCHECK(local_time.has_value());
return std::max(AnimationTimeDelta(),
- std::min(active_duration,
- local_time.value() - specified.start_delay));
+ std::min(normalized.active_duration,
+ local_time.value() - normalized.start_delay));
}
return absl::nullopt;
case Timing::kPhaseNone:
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc b/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc
index f07595c0f1f..4888dabd89f 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc
@@ -36,66 +36,60 @@
namespace blink {
TEST(AnimationTimingCalculationsTest, ActiveTime) {
- Timing timing;
+ Timing::NormalizedTiming normalized_timing;
// calculateActiveTime(
// activeDuration, fillMode, localTime, parentPhase, phase, timing)
// Before Phase
- timing.start_delay = AnimationTimeDelta::FromSecondsD(10);
- EXPECT_FALSE(CalculateActiveTime(
- AnimationTimeDelta::FromSecondsD(20), Timing::FillMode::FORWARDS,
- AnimationTimeDelta(), Timing::kPhaseBefore, timing));
- EXPECT_FALSE(CalculateActiveTime(AnimationTimeDelta::FromSecondsD(20),
- Timing::FillMode::NONE, AnimationTimeDelta(),
- Timing::kPhaseBefore, timing));
- EXPECT_EQ(
- AnimationTimeDelta(),
- CalculateActiveTime(AnimationTimeDelta::FromSecondsD(20),
- Timing::FillMode::BACKWARDS, AnimationTimeDelta(),
- Timing::kPhaseBefore, timing));
+ normalized_timing.start_delay = AnimationTimeDelta::FromSecondsD(10);
+ normalized_timing.active_duration = AnimationTimeDelta::FromSecondsD(20);
+ EXPECT_FALSE(CalculateActiveTime(normalized_timing,
+ Timing::FillMode::FORWARDS,
+ AnimationTimeDelta(), Timing::kPhaseBefore));
+ EXPECT_FALSE(CalculateActiveTime(normalized_timing, Timing::FillMode::NONE,
+ AnimationTimeDelta(), Timing::kPhaseBefore));
EXPECT_EQ(AnimationTimeDelta(),
- CalculateActiveTime(AnimationTimeDelta::FromSecondsD(20),
- Timing::FillMode::BOTH, AnimationTimeDelta(),
- Timing::kPhaseBefore, timing));
- timing.start_delay = AnimationTimeDelta::FromSecondsD(-10);
+ CalculateActiveTime(normalized_timing, Timing::FillMode::BACKWARDS,
+ AnimationTimeDelta(), Timing::kPhaseBefore));
+ EXPECT_EQ(AnimationTimeDelta(),
+ CalculateActiveTime(normalized_timing, Timing::FillMode::BOTH,
+ AnimationTimeDelta(), Timing::kPhaseBefore));
+ normalized_timing.start_delay = AnimationTimeDelta::FromSecondsD(-10);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5),
- CalculateActiveTime(AnimationTimeDelta::FromSecondsD(20),
- Timing::FillMode::BACKWARDS,
+ CalculateActiveTime(normalized_timing, Timing::FillMode::BACKWARDS,
AnimationTimeDelta::FromSecondsD(-5),
- Timing::kPhaseBefore, timing));
+ Timing::kPhaseBefore));
// Active Phase
- timing.start_delay = AnimationTimeDelta::FromSecondsD(10);
+ normalized_timing.start_delay = AnimationTimeDelta::FromSecondsD(10);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5),
- CalculateActiveTime(AnimationTimeDelta::FromSecondsD(20),
- Timing::FillMode::FORWARDS,
+ CalculateActiveTime(normalized_timing, Timing::FillMode::FORWARDS,
AnimationTimeDelta::FromSecondsD(15),
- Timing::kPhaseActive, timing));
+ Timing::kPhaseActive));
// After Phase
- timing.start_delay = AnimationTimeDelta::FromSecondsD(10);
+ normalized_timing.start_delay = AnimationTimeDelta::FromSecondsD(10);
+ normalized_timing.active_duration = AnimationTimeDelta::FromSecondsD(21);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21),
- CalculateActiveTime(AnimationTimeDelta::FromSecondsD(21),
- Timing::FillMode::FORWARDS,
+ CalculateActiveTime(normalized_timing, Timing::FillMode::FORWARDS,
AnimationTimeDelta::FromSecondsD(45),
- Timing::kPhaseAfter, timing));
+ Timing::kPhaseAfter));
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21),
- CalculateActiveTime(AnimationTimeDelta::FromSecondsD(21),
- Timing::FillMode::BOTH,
+ CalculateActiveTime(normalized_timing, Timing::FillMode::BOTH,
AnimationTimeDelta::FromSecondsD(45),
- Timing::kPhaseAfter, timing));
- EXPECT_FALSE(CalculateActiveTime(
- AnimationTimeDelta::FromSecondsD(21), Timing::FillMode::BACKWARDS,
- AnimationTimeDelta::FromSecondsD(45), Timing::kPhaseAfter, timing));
+ Timing::kPhaseAfter));
EXPECT_FALSE(CalculateActiveTime(
- AnimationTimeDelta::FromSecondsD(21), Timing::FillMode::NONE,
- AnimationTimeDelta::FromSecondsD(45), Timing::kPhaseAfter, timing));
+ normalized_timing, Timing::FillMode::BACKWARDS,
+ AnimationTimeDelta::FromSecondsD(45), Timing::kPhaseAfter));
+ EXPECT_FALSE(CalculateActiveTime(normalized_timing, Timing::FillMode::NONE,
+ AnimationTimeDelta::FromSecondsD(45),
+ Timing::kPhaseAfter));
// None
- EXPECT_FALSE(CalculateActiveTime(AnimationTimeDelta::FromSecondsD(32),
- Timing::FillMode::NONE, absl::nullopt,
- Timing::kPhaseNone, timing));
+ normalized_timing.active_duration = AnimationTimeDelta::FromSecondsD(32);
+ EXPECT_FALSE(CalculateActiveTime(normalized_timing, Timing::FillMode::NONE,
+ absl::nullopt, Timing::kPhaseNone));
}
TEST(AnimationTimingCalculationsTest, OffsetActiveTime) {
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 90ed70bd569..03009262e42 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_input.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing_input.cc
@@ -4,19 +4,20 @@
#include "third_party/blink/renderer/core/animation/timing_input.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/bindings/core/v8/v8_effect_timing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_animation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeanimationoptions_unrestricteddouble.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
namespace {
+
Timing::PlaybackDirection ConvertPlaybackDirection(const String& direction) {
if (direction == "reverse")
return Timing::PlaybackDirection::REVERSE;
@@ -29,10 +30,10 @@ Timing::PlaybackDirection ConvertPlaybackDirection(const String& direction) {
}
absl::optional<AnimationTimeDelta> ConvertIterationDuration(
- const UnrestrictedDoubleOrString& duration) {
- if (duration.IsUnrestrictedDouble()) {
+ const V8UnionStringOrUnrestrictedDouble* duration) {
+ if (duration->IsUnrestrictedDouble()) {
return AnimationTimeDelta::FromMillisecondsD(
- duration.GetAsUnrestrictedDouble());
+ duration->GetAsUnrestrictedDouble());
}
return absl::nullopt;
}
@@ -59,7 +60,6 @@ bool UpdateValueIfChanged(V& lhs, const V& rhs) {
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Timing TimingInput::Convert(
const V8UnionKeyframeEffectOptionsOrUnrestrictedDouble* options,
Document* document,
@@ -81,7 +81,7 @@ Timing TimingInput::Convert(
// their default values and duration set to options.
EffectTiming* timing_input = EffectTiming::Create();
timing_input->setDuration(
- UnrestrictedDoubleOrString::FromUnrestrictedDouble(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
options->GetAsUnrestrictedDouble()));
return ConvertEffectTiming(timing_input, document, exception_state);
}
@@ -89,34 +89,7 @@ Timing TimingInput::Convert(
NOTREACHED();
return Timing();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-Timing TimingInput::Convert(
- const UnrestrictedDoubleOrKeyframeEffectOptions& options,
- Document* document,
- ExceptionState& exception_state) {
- if (options.IsNull()) {
- return Timing();
- }
-
- if (options.IsKeyframeEffectOptions()) {
- return ConvertEffectTiming(options.GetAsKeyframeEffectOptions(), document,
- exception_state);
- }
-
- DCHECK(options.IsUnrestrictedDouble());
-
- // https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect
- // If options is a double,
- // Let timing input be a new EffectTiming object with all members set to
- // their default values and duration set to options.
- EffectTiming* timing_input = EffectTiming::Create();
- timing_input->setDuration(UnrestrictedDoubleOrString::FromUnrestrictedDouble(
- options.GetAsUnrestrictedDouble()));
- return ConvertEffectTiming(timing_input, document, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Timing TimingInput::Convert(
const V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble* options,
Document* document,
@@ -138,7 +111,7 @@ Timing TimingInput::Convert(
// their default values and duration set to options.
EffectTiming* timing_input = EffectTiming::Create();
timing_input->setDuration(
- UnrestrictedDoubleOrString::FromUnrestrictedDouble(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(
options->GetAsUnrestrictedDouble()));
return ConvertEffectTiming(timing_input, document, exception_state);
}
@@ -146,31 +119,6 @@ Timing TimingInput::Convert(
NOTREACHED();
return Timing();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-Timing TimingInput::Convert(
- const UnrestrictedDoubleOrKeyframeAnimationOptions& options,
- Document* document,
- ExceptionState& exception_state) {
- if (options.IsNull())
- return Timing();
-
- if (options.IsKeyframeAnimationOptions()) {
- return ConvertEffectTiming(options.GetAsKeyframeAnimationOptions(),
- document, exception_state);
- }
-
- DCHECK(options.IsUnrestrictedDouble());
-
- // https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect
- // If options is a double,
- // Let timing input be a new EffectTiming object with all members set to
- // their default values and duration set to options.
- EffectTiming* timing_input = EffectTiming::Create();
- timing_input->setDuration(UnrestrictedDoubleOrString::FromUnrestrictedDouble(
- options.GetAsUnrestrictedDouble()));
- return ConvertEffectTiming(timing_input, document, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
template <class InputTiming>
bool TimingInput::Update(Timing& timing,
@@ -199,15 +147,22 @@ bool TimingInput::Update(Timing& timing,
// https://github.com/w3c/csswg-drafts/issues/247 .
if (input->hasDuration()) {
const char* error_message = "duration must be non-negative or auto";
- if (input->duration().IsUnrestrictedDouble()) {
- double duration = input->duration().GetAsUnrestrictedDouble();
- if (std::isnan(duration) || duration < 0) {
- exception_state.ThrowTypeError(error_message);
- return false;
+ switch (input->duration()->GetContentType()) {
+ case V8UnionStringOrUnrestrictedDouble::ContentType::kString:
+ if (input->duration()->GetAsString() != "auto") {
+ exception_state.ThrowTypeError(error_message);
+ return false;
+ }
+ break;
+ case V8UnionStringOrUnrestrictedDouble::ContentType::
+ kUnrestrictedDouble: {
+ double duration = input->duration()->GetAsUnrestrictedDouble();
+ if (std::isnan(duration) || duration < 0) {
+ exception_state.ThrowTypeError(error_message);
+ return false;
+ }
+ break;
}
- } else if (input->duration().GetAsString() != "auto") {
- exception_state.ThrowTypeError(error_message);
- return false;
}
}
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_input.h b/chromium/third_party/blink/renderer/core/animation/timing_input.h
index 6a30531d57f..7ab8be1dd66 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_input.h
+++ b/chromium/third_party/blink/renderer/core/animation/timing_input.h
@@ -13,8 +13,6 @@ namespace blink {
class Document;
class ExceptionState;
-class UnrestrictedDoubleOrKeyframeAnimationOptions;
-class UnrestrictedDoubleOrKeyframeEffectOptions;
class V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble;
class V8UnionKeyframeEffectOptionsOrUnrestrictedDouble;
@@ -26,31 +24,19 @@ class CORE_EXPORT TimingInput {
// the 'options' parameter into timing information.
//
// https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Timing Convert(
const V8UnionKeyframeEffectOptionsOrUnrestrictedDouble* options,
Document* document,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Timing Convert(const UnrestrictedDoubleOrKeyframeEffectOptions&,
- Document*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Implements step 2 of the Animatable::animate() method, converting the
// 'options' parameter into timing information.
//
// https://drafts.csswg.org/web-animations-1/#dom-animatable-animate
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Timing Convert(
const V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble* options,
Document* document,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Timing Convert(const UnrestrictedDoubleOrKeyframeAnimationOptions&,
- Document*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Implements the procedure to 'update the timing properties of an animation
// effect'.
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc b/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc
index 4a7b2bbacc1..267e9c26ce5 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc
@@ -6,8 +6,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_animation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.h"
@@ -64,15 +62,9 @@ Timing AnimationTimingInputTest::ApplyTimingInputNumber(
return Timing();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* timing_input =
MakeGarbageCollected<V8UnionKeyframeEffectOptionsOrUnrestrictedDouble>(
timing_input_dictionary);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeEffectOptions timing_input =
- UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
- timing_input_dictionary);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
if (exception_state.HadException())
return Timing();
@@ -83,15 +75,9 @@ Timing AnimationTimingInputTest::ApplyTimingInputNumber(
if (exception_state.HadException())
return Timing();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* timing_input = MakeGarbageCollected<
V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble>(
timing_input_dictionary);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeAnimationOptions timing_input =
- UnrestrictedDoubleOrKeyframeAnimationOptions::
- FromKeyframeAnimationOptions(timing_input_dictionary);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
if (exception_state.HadException())
return Timing();
@@ -120,15 +106,9 @@ Timing AnimationTimingInputTest::ApplyTimingInputString(
if (exception_state.HadException())
return Timing();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* timing_input =
MakeGarbageCollected<V8UnionKeyframeEffectOptionsOrUnrestrictedDouble>(
timing_input_dictionary);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeEffectOptions timing_input =
- UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
- timing_input_dictionary);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
if (exception_state.HadException())
return Timing();
@@ -139,15 +119,9 @@ Timing AnimationTimingInputTest::ApplyTimingInputString(
if (exception_state.HadException())
return Timing();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* timing_input = MakeGarbageCollected<
V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble>(
timing_input_dictionary);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeAnimationOptions timing_input =
- UnrestrictedDoubleOrKeyframeAnimationOptions::
- FromKeyframeAnimationOptions(timing_input_dictionary);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
if (exception_state.HadException())
return Timing();
@@ -479,15 +453,9 @@ TEST_F(AnimationTimingInputTest, TimingInputTimingFunction) {
TEST_F(AnimationTimingInputTest, TimingInputEmpty) {
DummyExceptionStateForTesting exception_state;
Timing control_timing;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* timing_input =
MakeGarbageCollected<V8UnionKeyframeEffectOptionsOrUnrestrictedDouble>(
KeyframeEffectOptions::Create());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeEffectOptions timing_input =
- UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
- KeyframeEffectOptions::Create());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Timing updated_timing =
TimingInput::Convert(timing_input, nullptr, exception_state);
EXPECT_FALSE(exception_state.HadException());
@@ -504,15 +472,9 @@ TEST_F(AnimationTimingInputTest, TimingInputEmpty) {
TEST_F(AnimationTimingInputTest, TimingInputEmptyKeyframeAnimationOptions) {
DummyExceptionStateForTesting exception_state;
Timing control_timing;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* input_timing =
MakeGarbageCollected<V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble>(
KeyframeAnimationOptions::Create());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnrestrictedDoubleOrKeyframeAnimationOptions input_timing =
- UnrestrictedDoubleOrKeyframeAnimationOptions::
- FromKeyframeAnimationOptions(KeyframeAnimationOptions::Create());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Timing updated_timing =
TimingInput::Convert(input_timing, nullptr, exception_state);
EXPECT_FALSE(exception_state.HadException());
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_test.cc b/chromium/third_party/blink/renderer/core/animation/timing_test.cc
index 9ce6f35240d..fed9dfee939 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing_test.cc
@@ -18,8 +18,8 @@ class AnimationTimingTest : public testing::Test {
playback_rate < 0 ? Timing::AnimationDirection::kBackwards
: Timing::AnimationDirection::kForwards;
return timing_.CalculateTimings(
- local_time, /*timeline_phase*/ absl::nullopt, animation_direction,
- is_keyframe_effect, playback_rate);
+ local_time, /*timeline_phase*/ absl::nullopt, normalized_timing_,
+ animation_direction, is_keyframe_effect, playback_rate);
}
bool IsCurrent(absl::optional<double> local_time, double playback_rate) {
absl::optional<AnimationTimeDelta> local_time_delta;
@@ -32,9 +32,14 @@ class AnimationTimingTest : public testing::Test {
private:
void SetUp() override {
- timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
+ normalized_timing_.start_delay = AnimationTimeDelta();
+ normalized_timing_.end_delay = AnimationTimeDelta();
+ normalized_timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
+ normalized_timing_.active_duration = AnimationTimeDelta::FromSecondsD(1);
+ normalized_timing_.end_time = AnimationTimeDelta::FromSecondsD(1);
}
Timing timing_;
+ Timing::NormalizedTiming normalized_timing_;
};
TEST_F(AnimationTimingTest, IsCurrent) {
diff --git a/chromium/third_party/blink/renderer/core/animation/underlying_value_owner.h b/chromium/third_party/blink/renderer/core/animation/underlying_value_owner.h
index 95efc5d1992..1f6d277e017 100644
--- a/chromium/third_party/blink/renderer/core/animation/underlying_value_owner.h
+++ b/chromium/third_party/blink/renderer/core/animation/underlying_value_owner.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/typed_interpolation_value.h"
#include "third_party/blink/renderer/core/animation/underlying_value.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -25,6 +24,8 @@ class CORE_EXPORT UnderlyingValueOwner : public UnderlyingValue {
public:
UnderlyingValueOwner()
: type_(nullptr), value_owner_(nullptr), value_(nullptr) {}
+ UnderlyingValueOwner(const UnderlyingValueOwner&) = delete;
+ UnderlyingValueOwner& operator=(const UnderlyingValueOwner&) = delete;
operator bool() const {
DCHECK_EQ(static_cast<bool>(type_), static_cast<bool>(value_));
@@ -56,7 +57,6 @@ class CORE_EXPORT UnderlyingValueOwner : public UnderlyingValue {
const InterpolationType* type_;
InterpolationValue value_owner_;
const InterpolationValue* value_;
- DISALLOW_COPY_AND_ASSIGN(UnderlyingValueOwner);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
index bffb2db57b0..99c5df0d8ed 100644
--- a/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
+++ b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FRAME_WORKER_ANIMATION_FRAME_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FRAME_WORKER_ANIMATION_FRAME_PROVIDER_H_
-#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/platform/graphics/begin_frame_provider.h"
@@ -33,6 +32,9 @@ class CORE_EXPORT WorkerAnimationFrameProvider
WorkerAnimationFrameProvider(
ExecutionContext* context,
const BeginFrameProviderParams& begin_frame_provider_params);
+ WorkerAnimationFrameProvider(const WorkerAnimationFrameProvider&) = delete;
+ WorkerAnimationFrameProvider& operator=(const WorkerAnimationFrameProvider&) =
+ delete;
int RegisterCallback(FrameCallback* callback);
void CancelCallback(int id);
@@ -49,7 +51,6 @@ class CORE_EXPORT WorkerAnimationFrameProvider
private:
const Member<BeginFrameProvider> begin_frame_provider_;
- DISALLOW_COPY_AND_ASSIGN(WorkerAnimationFrameProvider);
FrameRequestCallbackCollection callback_collection_;
HeapLinkedHashSet<WeakMember<OffscreenCanvas>> offscreen_canvases_;
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.cc b/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
index 295f82bbd5a..3fc7a1696d3 100644
--- a/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
@@ -201,7 +201,6 @@ Document* AccessibleNode::GetDocument() const {
if (element_)
return &element_->GetDocument();
- NOTREACHED();
return nullptr;
}
@@ -939,6 +938,7 @@ void AccessibleNode::appendChild(AccessibleNode* child,
"Reparenting is not supported yet.");
return;
}
+ child->document_ = GetAncestorDocument();
child->parent_ = this;
if (!GetExecutionContext()->GetSecurityOrigin()->CanAccess(
@@ -954,6 +954,22 @@ void AccessibleNode::appendChild(AccessibleNode* child,
cache->ChildrenChanged(this);
}
+void AccessibleNode::DetachedFromDocument() {
+ // Clear associated AXObject from AXObjectCache since its accessible node is
+ // removed from document.
+ if (AXObjectCache* cache = GetAXObjectCache())
+ cache->Remove(this);
+
+ // Clear reference to its document, since this accessible node is removed from
+ // document.
+ document_ = nullptr;
+
+ // Remove references for subtree.
+ for (auto child : GetChildren()) {
+ child->DetachedFromDocument();
+ }
+}
+
void AccessibleNode::removeChild(AccessibleNode* old_child,
ExceptionState& exception_state) {
if (old_child->parent_ != this) {
@@ -973,6 +989,7 @@ void AccessibleNode::removeChild(AccessibleNode* old_child,
return;
}
old_child->parent_ = nullptr;
+ old_child->DetachedFromDocument();
children_.erase(ix);
if (AXObjectCache* cache = GetAXObjectCache())
@@ -1022,6 +1039,16 @@ ExecutionContext* AccessibleNode::GetExecutionContext() const {
return nullptr;
}
+Document* AccessibleNode::GetAncestorDocument() {
+ if (element_)
+ return &(element_->GetDocument());
+
+ if (parent_)
+ return parent_->GetAncestorDocument();
+
+ return nullptr;
+}
+
void AccessibleNode::SetStringProperty(AOMStringProperty property,
const AtomicString& value) {
for (auto& item : string_properties_) {
@@ -1124,7 +1151,10 @@ void AccessibleNode::NotifyAttributeChanged(
}
AXObjectCache* AccessibleNode::GetAXObjectCache() {
- return GetDocument()->ExistingAXObjectCache();
+ if (Document* document = GetDocument())
+ return document->ExistingAXObjectCache();
+
+ return nullptr;
}
void AccessibleNode::Trace(Visitor* visitor) const {
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.h b/chromium/third_party/blink/renderer/core/aom/accessible_node.h
index 46165b7416b..232bd7f4e83 100644
--- a/chromium/third_party/blink/renderer/core/aom/accessible_node.h
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_H_
+#include "third_party/abseil-cpp/absl/types/optional.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"
@@ -122,6 +123,9 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
// Gets the associated document.
Document* GetDocument() const;
+ // Returns the parent of this node.
+ AccessibleNode* GetParent() { return parent_; }
+
// Children. These are only virtual AccessibleNodes that were added
// explicitly, never AccessibleNodes from DOM Elements.
HeapVector<Member<AccessibleNode>> GetChildren() { return children_; }
@@ -346,6 +350,10 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
void appendChild(AccessibleNode*, ExceptionState&);
void removeChild(AccessibleNode*, ExceptionState&);
+ // Called when an accessible node is removed from document.
+ void DetachedFromDocument();
+ Document* GetAncestorDocument();
+
// EventTarget
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
diff --git a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
index dd746a6b14a..5f0e230fc02 100644
--- a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
@@ -18,6 +18,7 @@
#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"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
@@ -28,6 +29,10 @@ class ComputedAccessibleNodePromiseResolver::RequestAnimationFrameCallback final
ComputedAccessibleNodePromiseResolver* resolver)
: resolver_(resolver) {}
+ RequestAnimationFrameCallback(const RequestAnimationFrameCallback&) = delete;
+ RequestAnimationFrameCallback& operator=(
+ const RequestAnimationFrameCallback&) = delete;
+
void Invoke(double) override {
resolver_->continue_callback_request_id_ = 0;
resolver_->UpdateTreeAndResolve();
@@ -40,8 +45,6 @@ class ComputedAccessibleNodePromiseResolver::RequestAnimationFrameCallback final
private:
Member<ComputedAccessibleNodePromiseResolver> resolver_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestAnimationFrameCallback);
};
ComputedAccessibleNodePromiseResolver::ComputedAccessibleNodePromiseResolver(
@@ -50,7 +53,8 @@ ComputedAccessibleNodePromiseResolver::ComputedAccessibleNodePromiseResolver(
: element_(element),
resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)),
resolve_with_node_(false),
- ax_context_(std::make_unique<AXContext>(element_->GetDocument())) {}
+ ax_context_(std::make_unique<AXContext>(element_->GetDocument(),
+ ui::kAXModeComplete)) {}
ScriptPromise ComputedAccessibleNodePromiseResolver::Promise() {
return resolver_->Promise();
@@ -106,11 +110,11 @@ void ComputedAccessibleNodePromiseResolver::UpdateTreeAndResolve() {
// ComputedAccessibleNode ------------------------------------------------------
-ComputedAccessibleNode::ComputedAccessibleNode(AXID ax_id,
- Document* document)
+ComputedAccessibleNode::ComputedAccessibleNode(AXID ax_id, Document* document)
: ax_id_(ax_id),
document_(document),
- ax_context_(std::make_unique<AXContext>(*document)) {}
+ ax_context_(std::make_unique<AXContext>(*document, ui::kAXModeComplete)) {
+}
absl::optional<bool> ComputedAccessibleNode::atomic() const {
return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_ATOMIC);
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history.cc b/chromium/third_party/blink/renderer/core/app_history/app_history.cc
index 8d3aa88992c..f50aaab401c 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history.cc
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history.cc
@@ -4,55 +4,104 @@
#include "third_party/blink/renderer/core/app_history/app_history.h"
+#include <memory>
+
+#include "third_party/blink/public/web/web_frame_load_type.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/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_reload_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_update_current_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/app_history/app_history_destination.h"
#include "third_party/blink/renderer/core/app_history/app_history_entry.h"
#include "third_party/blink/renderer/core/app_history/app_history_navigate_event.h"
-#include "third_party/blink/renderer/core/app_history/app_history_navigate_options.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/events/error_event.h"
#include "third_party/blink/renderer/core/frame/history_util.h"
#include "third_party/blink/renderer/core/frame/local_frame.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/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
namespace blink {
-namespace {
+class AppHistoryApiNavigation final
+ : public GarbageCollected<AppHistoryApiNavigation> {
+ public:
+ AppHistoryApiNavigation(ScriptState* script_state,
+ AppHistoryNavigationOptions* options,
+ const String& key = String())
+ : info(options->getInfoOr(
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())))),
+ returned_promise(
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state)),
+ key(key) {}
+
+ ScriptValue info;
+ Member<ScriptPromiseResolver> returned_promise;
+ String key;
+ bool did_react_to_promise = false;
+
+ void Trace(Visitor* visitor) const {
+ visitor->Trace(info);
+ visitor->Trace(returned_promise);
+ }
+};
class NavigateReaction final : public ScriptFunction {
public:
- enum class ResolveType {
- kFulfill,
- kReject,
- };
+ enum class ResolveType { kFulfill, kReject, kDetach };
static void React(ScriptState* script_state,
ScriptPromise promise,
- ScriptPromiseResolver* resolver) {
- promise.Then(CreateFunction(script_state, resolver, ResolveType::kFulfill),
- CreateFunction(script_state, resolver, ResolveType::kReject));
+ AppHistoryApiNavigation* navigation,
+ AbortSignal* signal) {
+ if (navigation)
+ navigation->did_react_to_promise = true;
+ promise.Then(
+ CreateFunction(script_state, navigation, signal, ResolveType::kFulfill),
+ CreateFunction(script_state, navigation, signal, ResolveType::kReject));
+ }
+
+ static void CleanupWithoutResolving(ScriptState* script_state,
+ AppHistoryApiNavigation* navigation) {
+ ScriptPromise::CastUndefined(script_state)
+ .Then(CreateFunction(script_state, navigation, nullptr,
+ ResolveType::kDetach));
}
NavigateReaction(ScriptState* script_state,
- ScriptPromiseResolver* resolver,
+ AppHistoryApiNavigation* navigation,
+ AbortSignal* signal,
ResolveType type)
: ScriptFunction(script_state),
window_(LocalDOMWindow::From(script_state)),
- resolver_(resolver),
+ navigation_(navigation),
+ signal_(signal),
type_(type) {}
void Trace(Visitor* visitor) const final {
ScriptFunction::Trace(visitor);
visitor->Trace(window_);
- visitor->Trace(resolver_);
+ visitor->Trace(navigation_);
+ visitor->Trace(signal_);
}
private:
- static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
- ScriptPromiseResolver* resolver,
- ResolveType type) {
- return MakeGarbageCollected<NavigateReaction>(script_state, resolver, type)
+ static v8::Local<v8::Function> CreateFunction(
+ ScriptState* script_state,
+ AppHistoryApiNavigation* navigation,
+ AbortSignal* signal,
+ ResolveType type) {
+ return MakeGarbageCollected<NavigateReaction>(script_state, navigation,
+ signal, type)
->BindToV8Function();
}
@@ -74,24 +123,44 @@ class NavigateReaction final : public ScriptFunction {
ScriptValue Call(ScriptValue value) final {
DCHECK(window_);
- AppHistory::appHistory(*window_)->DispatchEvent(*InitEvent(value));
- if (resolver_) {
+ if (signal_ && signal_->aborted()) {
+ window_ = nullptr;
+ return ScriptValue();
+ }
+
+ AppHistory* app_history = AppHistory::appHistory(*window_);
+ if (navigation_) {
+ if (navigation_->key.IsNull()) {
+ if (navigation_ == app_history->ongoing_non_traversal_navigation_)
+ app_history->ongoing_non_traversal_navigation_ = nullptr;
+ } else {
+ DCHECK(app_history->ongoing_traversals_.Contains(navigation_->key));
+ app_history->ongoing_traversals_.erase(navigation_->key);
+ }
+ }
+
+ if (type_ == ResolveType::kDetach) {
+ navigation_->returned_promise->Detach();
+ window_ = nullptr;
+ return ScriptValue();
+ }
+ app_history->DispatchEvent(*InitEvent(value));
+ if (navigation_) {
if (type_ == ResolveType::kFulfill)
- resolver_->Resolve(value);
+ navigation_->returned_promise->Resolve();
else
- resolver_->Reject(value);
+ navigation_->returned_promise->Reject(value);
}
window_ = nullptr;
return ScriptValue();
}
Member<LocalDOMWindow> window_;
- Member<ScriptPromiseResolver> resolver_;
+ Member<AppHistoryApiNavigation> navigation_;
+ Member<AbortSignal> signal_;
ResolveType type_;
};
-} // namespace
-
const char AppHistory::kSupplementName[] = "AppHistory";
AppHistory* AppHistory::appHistory(LocalDOMWindow& window) {
@@ -110,7 +179,7 @@ AppHistory::AppHistory(LocalDOMWindow& window)
void AppHistory::PopulateKeySet() {
DCHECK(keys_to_indices_.IsEmpty());
- for (size_t i = 0; i < entries_.size(); i++)
+ for (wtf_size_t i = 0; i < entries_.size(); i++)
keys_to_indices_.insert(entries_[i]->key(), i);
}
@@ -122,13 +191,14 @@ void AppHistory::InitializeForNavigation(
// Construct |entries_|. Any back entries are inserted, then the current
// entry, then any forward entries.
- entries_.ReserveCapacity(back_entries.size() + forward_entries.size() + 1);
+ entries_.ReserveCapacity(base::checked_cast<wtf_size_t>(
+ back_entries.size() + forward_entries.size() + 1));
for (const auto& entry : back_entries) {
entries_.emplace_back(
MakeGarbageCollected<AppHistoryEntry>(GetSupplementable(), entry));
}
- current_index_ = back_entries.size();
+ current_index_ = base::checked_cast<wtf_size_t>(back_entries.size());
entries_.emplace_back(
MakeGarbageCollected<AppHistoryEntry>(GetSupplementable(), &current));
@@ -142,7 +212,7 @@ void AppHistory::InitializeForNavigation(
void AppHistory::CloneFromPrevious(AppHistory& previous) {
DCHECK(entries_.IsEmpty());
entries_.ReserveCapacity(previous.entries_.size());
- for (size_t i = 0; i < previous.entries_.size(); i++) {
+ for (wtf_size_t i = 0; i < previous.entries_.size(); i++) {
// It's possible that |old_item| is indirectly holding a reference to
// the old Document. Also, it has a bunch of state we don't need for a
// non-current entry. Clone a subset of its state to a |new_item|.
@@ -165,6 +235,7 @@ void AppHistory::UpdateForNavigation(HistoryItem& item, WebFrameLoadType type) {
// A same-document navigation (e.g., a document.open()) in a newly created
// iframe will try to operate on an empty |entries_|. appHistory considers
// this a no-op.
+ post_navigate_event_ongoing_navigation_signal_ = nullptr;
if (entries_.IsEmpty())
return;
@@ -181,7 +252,7 @@ void AppHistory::UpdateForNavigation(HistoryItem& item, WebFrameLoadType type) {
// For a new back/forward entry, truncate any forward entries and prepare to
// append.
current_index_++;
- for (size_t i = current_index_; i < entries_.size(); i++)
+ for (wtf_size_t i = current_index_; i < entries_.size(); i++)
keys_to_indices_.erase(entries_[i]->key());
entries_.resize(current_index_ + 1);
}
@@ -209,53 +280,106 @@ HeapVector<Member<AppHistoryEntry>> AppHistory::entries() {
: HeapVector<Member<AppHistoryEntry>>();
}
+void AppHistory::updateCurrent(AppHistoryUpdateCurrentOptions* options,
+ ExceptionState& exception_state) {
+ AppHistoryEntry* current_entry = current();
+
+ if (!current_entry) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "updateCurrent() cannot be called when on the initial about:blank "
+ "Document, or when the Window is detached.");
+ return;
+ }
+
+ scoped_refptr<SerializedScriptValue> serialized_state =
+ SerializeState(options->state(), exception_state);
+ if (exception_state.HadException())
+ return;
+
+ current_entry->GetItem()->SetAppHistoryState(std::move(serialized_state));
+}
+
ScriptPromise AppHistory::navigate(ScriptState* script_state,
const String& url,
AppHistoryNavigateOptions* options,
ExceptionState& exception_state) {
- if (!GetSupplementable()->GetFrame()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "navigate() may not be called in a "
- "detached window");
- return ScriptPromise();
- }
-
KURL completed_url(GetSupplementable()->Url(), url);
if (!completed_url.IsValid()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "Invalid url");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kSyntaxError,
+ "Invalid URL '" + completed_url.GetString() + "'.");
return ScriptPromise();
}
- navigate_serialized_state_ = nullptr;
+ PerformSharedNavigationChecks(exception_state, "navigate()");
+ if (exception_state.HadException())
+ return ScriptPromise();
+
+ scoped_refptr<SerializedScriptValue> serialized_state = nullptr;
if (options->hasState()) {
- navigate_serialized_state_ = SerializedScriptValue::Serialize(
- script_state->GetIsolate(), options->state().V8Value(),
- SerializedScriptValue::SerializeOptions(
- SerializedScriptValue::kForStorage),
- exception_state);
+ serialized_state = SerializeState(options->state(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
}
- base::AutoReset<Member<ScriptPromiseResolver>> promise(
- &navigate_method_call_promise_resolver_,
- MakeGarbageCollected<ScriptPromiseResolver>(script_state));
- base::AutoReset<ScriptValue> event_info(&navigate_event_info_,
- options->navigateInfo());
WebFrameLoadType frame_load_type = options->replace()
? WebFrameLoadType::kReplaceCurrentItem
: WebFrameLoadType::kStandard;
+
+ return PerformNonTraverseNavigation(script_state, completed_url,
+ std::move(serialized_state), options,
+ frame_load_type, exception_state);
+}
+
+ScriptPromise AppHistory::reload(ScriptState* script_state,
+ AppHistoryReloadOptions* options,
+ ExceptionState& exception_state) {
+ PerformSharedNavigationChecks(exception_state, "reload()");
+ if (exception_state.HadException())
+ return ScriptPromise();
+
+ scoped_refptr<SerializedScriptValue> serialized_state = nullptr;
+ if (options->hasState()) {
+ serialized_state = SerializeState(options->state(), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
+ } else if (AppHistoryEntry* current_entry = current()) {
+ serialized_state = current_entry->GetItem()->GetAppHistoryState();
+ }
+
+ return PerformNonTraverseNavigation(
+ script_state, GetSupplementable()->Url(), std::move(serialized_state),
+ options, WebFrameLoadType::kReload, exception_state);
+}
+
+ScriptPromise AppHistory::PerformNonTraverseNavigation(
+ ScriptState* script_state,
+ const KURL& url,
+ scoped_refptr<SerializedScriptValue> serialized_state,
+ AppHistoryNavigationOptions* options,
+ WebFrameLoadType frame_load_type,
+ ExceptionState& exception_state) {
+ DCHECK(frame_load_type == WebFrameLoadType::kReplaceCurrentItem ||
+ frame_load_type == WebFrameLoadType::kReload ||
+ frame_load_type == WebFrameLoadType::kStandard);
+
+ AppHistoryApiNavigation* navigation =
+ MakeGarbageCollected<AppHistoryApiNavigation>(script_state, options);
+ upcoming_non_traversal_navigation_ = navigation;
+
+ to_be_set_serialized_state_ = serialized_state;
+
GetSupplementable()->GetFrame()->MaybeLogAdClickNavigation();
- FrameLoadRequest request(GetSupplementable(), ResourceRequest(completed_url));
+ FrameLoadRequest request(GetSupplementable(), ResourceRequest(url));
request.SetClientRedirectReason(ClientNavigationReason::kFrameNavigation);
GetSupplementable()->GetFrame()->Navigate(request, frame_load_type);
// The spec says to handle the window-detach case in DispatchNavigateEvent()
- // using navigate_method_call_promise_resolver_, but ScriptPromiseResolver
- // clears its state on window detach, so we can't use it to return a rejected
- // promise in the detach case (it returns undefined instead). Rather than
+ // using navigation->returned_promise, but ScriptPromiseResolver
+ // clears its state on window detach, so we can't use it to return a rejected
+ // promise in the detach case (it returns undefined instead). Rather than
// bypassing ScriptPromiseResolver and managing our own v8::Promise::Resolver,
// special case detach here.
if (!GetSupplementable()->GetFrame()) {
@@ -263,56 +387,237 @@ ScriptPromise AppHistory::navigate(ScriptState* script_state,
"Navigation was aborted");
return ScriptPromise();
}
- if (navigate_serialized_state_)
- current()->GetItem()->SetAppHistoryState(navigate_serialized_state_);
- return navigate_method_call_promise_resolver_->Promise();
+
+ // DispatchNavigateEvent() will clear upcoming_non_traversal_navigation_ if we
+ // get that far. If the navigation is blocked before DispatchNavigateEvent()
+ // is called, reject the promise and cleanup here.
+ if (upcoming_non_traversal_navigation_ == navigation) {
+ upcoming_non_traversal_navigation_ = nullptr;
+ exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
+ "Navigation was aborted");
+ return ScriptPromise();
+ }
+
+ // The spec assumes it's ok to leave a promise permanently unresolved, but
+ // ScriptPromiseResolver requires either resolution or explicit detach.
+ // Do the detach on a microtask so that we can still return the promise.
+ if (!navigation->did_react_to_promise)
+ NavigateReaction::CleanupWithoutResolving(script_state, navigation);
+ if (to_be_set_serialized_state_) {
+ current()->GetItem()->SetAppHistoryState(
+ std::move(to_be_set_serialized_state_));
+ }
+ return navigation->returned_promise->Promise();
}
-ScriptPromise AppHistory::navigate(ScriptState* script_state,
- AppHistoryNavigateOptions* options,
- ExceptionState& exception_state) {
- if (!options->hasState() && !options->hasNavigateInfo()) {
- exception_state.ThrowTypeError(
- "Must pass at least one of url, state, or navigateInfo to navigate()");
+ScriptPromise AppHistory::goTo(ScriptState* script_state,
+ const String& key,
+ AppHistoryNavigationOptions* options,
+ ExceptionState& exception_state) {
+ PerformSharedNavigationChecks(exception_state, "goTo()/back()/forward()");
+ if (exception_state.HadException())
return ScriptPromise();
+
+ if (!keys_to_indices_.Contains(key)) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Invalid key");
+ return ScriptPromise();
+ }
+ if (key == current()->key())
+ return ScriptPromise::CastUndefined(script_state);
+
+ auto previous_navigation = ongoing_traversals_.find(key);
+ if (previous_navigation != ongoing_traversals_.end()) {
+ return previous_navigation->value->returned_promise->Promise();
+ }
+
+ AppHistoryApiNavigation* ongoing_navigation =
+ MakeGarbageCollected<AppHistoryApiNavigation>(script_state, options, key);
+ ongoing_traversals_.insert(key, ongoing_navigation);
+
+ AppHistoryEntry* destination = entries_[keys_to_indices_.at(key)];
+
+ // TODO(japhet): We will fire the navigate event for same-document navigations
+ // at commit time, but not cross-document. This should probably move to a more
+ // central location if we want to fire the navigate event for cross-document
+ // back-forward navigations in general.
+ if (!destination->sameDocument()) {
+ if (DispatchNavigateEvent(
+ destination->url(), nullptr, NavigateEventType::kCrossDocument,
+ WebFrameLoadType::kBackForward, UserNavigationInvolvement::kNone,
+ nullptr,
+ destination->GetItem()) != AppHistory::DispatchResult::kContinue) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
+ "Navigation was aborted");
+ return ScriptPromise();
+ }
}
- return navigate(script_state, GetSupplementable()->Url(), options,
- exception_state);
+
+ GetSupplementable()
+ ->GetFrame()
+ ->GetLocalFrameHostRemote()
+ .NavigateToAppHistoryKey(key, LocalFrame::HasTransientUserActivation(
+ GetSupplementable()->GetFrame()));
+ return ongoing_navigation->returned_promise->Promise();
+}
+
+bool AppHistory::canGoBack() const {
+ return GetSupplementable()->GetFrame() && current_index_ > 0;
+}
+
+bool AppHistory::canGoForward() const {
+ return GetSupplementable()->GetFrame() && current_index_ != -1 &&
+ static_cast<size_t>(current_index_) < entries_.size() - 1;
+}
+
+ScriptPromise AppHistory::back(ScriptState* script_state,
+ AppHistoryNavigationOptions* options,
+ ExceptionState& exception_state) {
+ if (!canGoBack()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Cannot go back");
+ return ScriptPromise();
+ }
+ return goTo(script_state, entries_[current_index_ - 1]->key(), options,
+ exception_state);
+}
+
+ScriptPromise AppHistory::forward(ScriptState* script_state,
+ AppHistoryNavigationOptions* options,
+ ExceptionState& exception_state) {
+ if (!canGoForward()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Cannot go forward");
+ return ScriptPromise();
+ }
+ return goTo(script_state, entries_[current_index_ + 1]->key(), options,
+ exception_state);
}
-bool AppHistory::DispatchNavigateEvent(const KURL& url,
- HTMLFormElement* form,
- NavigateEventType event_type,
- WebFrameLoadType type,
- UserNavigationInvolvement involvement,
- SerializedScriptValue* state_object) {
- if (GetSupplementable()->document()->IsInitialEmptyDocument())
- return true;
+void AppHistory::PerformSharedNavigationChecks(
+ ExceptionState& exception_state,
+ const String& method_name_for_error_message) {
+ if (!GetSupplementable()->GetFrame()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ method_name_for_error_message +
+ " cannot be called when the Window is detached.");
+ }
+ if (GetSupplementable()->document()->PageDismissalEventBeingDispatched()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ method_name_for_error_message +
+ " cannot be called during unload or beforeunload.");
+ }
+}
+scoped_refptr<SerializedScriptValue> AppHistory::SerializeState(
+ const ScriptValue& value,
+ ExceptionState& exception_state) {
+ return SerializedScriptValue::Serialize(
+ GetSupplementable()->GetIsolate(), value.V8Value(),
+ SerializedScriptValue::SerializeOptions(
+ SerializedScriptValue::kForStorage),
+ exception_state);
+}
+
+String DetermineNavigationType(WebFrameLoadType type) {
+ switch (type) {
+ case WebFrameLoadType::kStandard:
+ return "push";
+ case WebFrameLoadType::kBackForward:
+ return "traverse";
+ case WebFrameLoadType::kReload:
+ case WebFrameLoadType::kReloadBypassingCache:
+ return "reload";
+ case WebFrameLoadType::kReplaceCurrentItem:
+ return "replace";
+ }
+ NOTREACHED();
+ return String();
+}
+
+AppHistory::DispatchResult AppHistory::DispatchNavigateEvent(
+ const KURL& url,
+ HTMLFormElement* form,
+ NavigateEventType event_type,
+ WebFrameLoadType type,
+ UserNavigationInvolvement involvement,
+ SerializedScriptValue* state_object,
+ HistoryItem* destination_item) {
// TODO(japhet): The draft spec says to cancel any ongoing navigate event
- // before invoked DispatchNavigateEvent(), because not all navigations will
+ // before invoking DispatchNavigateEvent(), because not all navigations will
// fire a navigate event, but all should abort an ongoing navigate event.
// The main case were that would be a problem (browser-initiated back/forward)
// is not implemented yet. Move this once it is implemented.
- CancelOngoingNavigateEvent();
+ InformAboutCanceledNavigation();
+ if (upcoming_non_traversal_navigation_) {
+ ongoing_non_traversal_navigation_ =
+ upcoming_non_traversal_navigation_.Release();
+ }
+
+ if (!GetSupplementable()->GetFrame()->Loader().HasLoadedNonEmptyDocument()) {
+ if (ongoing_non_traversal_navigation_ &&
+ event_type != NavigateEventType::kCrossDocument) {
+ ongoing_non_traversal_navigation_->returned_promise->Resolve();
+ }
+ ongoing_non_traversal_navigation_ = nullptr;
+ return DispatchResult::kContinue;
+ }
+
+ auto* script_state =
+ ToScriptStateForMainWorld(GetSupplementable()->GetFrame());
+ ScriptState::Scope scope(script_state);
const KURL& current_url = GetSupplementable()->Url();
+ AppHistoryApiNavigation* navigation = nullptr;
+ if (destination_item && !destination_item->GetAppHistoryKey().IsNull()) {
+ auto iter = ongoing_traversals_.find(destination_item->GetAppHistoryKey());
+ navigation = iter == ongoing_traversals_.end() ? nullptr : iter->value;
+ } else {
+ navigation = ongoing_non_traversal_navigation_;
+ }
+
auto* init = AppHistoryNavigateEventInit::Create();
+ init->setNavigationType(DetermineNavigationType(type));
+
+ SerializedScriptValue* destination_state = nullptr;
+ if (destination_item)
+ destination_state = destination_item->GetAppHistoryState();
+ else if (to_be_set_serialized_state_)
+ destination_state = to_be_set_serialized_state_.get();
+ AppHistoryDestination* destination =
+ MakeGarbageCollected<AppHistoryDestination>(
+ url, event_type != NavigateEventType::kCrossDocument,
+ destination_state);
+ if (type == WebFrameLoadType::kBackForward) {
+ const String& key = destination_item->GetAppHistoryKey();
+ auto iter = keys_to_indices_.find(key);
+ int index = iter == keys_to_indices_.end() ? 0 : iter->value;
+ destination->SetTraverseProperties(key, destination_item->GetAppHistoryId(),
+ index);
+ }
+ init->setDestination(destination);
+
init->setCancelable(involvement != UserNavigationInvolvement::kBrowserUI ||
type != WebFrameLoadType::kBackForward);
init->setCanRespond(
CanChangeToUrlForHistoryApi(url, GetSupplementable()->GetSecurityOrigin(),
current_url) &&
- (event_type == NavigateEventType::kFragment ||
+ (event_type != NavigateEventType::kCrossDocument ||
type != WebFrameLoadType::kBackForward));
init->setHashChange(event_type == NavigateEventType::kFragment &&
url != current_url &&
EqualIgnoringFragmentIdentifier(url, current_url));
+
init->setUserInitiated(involvement != UserNavigationInvolvement::kNone);
- init->setFormData(form ? FormData::Create(form, ASSERT_NO_EXCEPTION)
- : nullptr);
- init->setInfo(navigate_event_info_);
+ if (form && form->Method() == FormSubmission::kPostMethod) {
+ init->setFormData(FormData::Create(form, ASSERT_NO_EXCEPTION));
+ }
+ if (navigation)
+ init->setInfo(navigation->info);
+ init->setSignal(MakeGarbageCollected<AbortSignal>(GetSupplementable()));
auto* navigate_event = AppHistoryNavigateEvent::Create(
GetSupplementable(), event_type_names::kNavigate, init);
navigate_event->SetUrl(url);
@@ -322,46 +627,83 @@ bool AppHistory::DispatchNavigateEvent(const KURL& url,
DispatchEvent(*navigate_event);
ongoing_navigate_event_ = nullptr;
- if (!GetSupplementable()->GetFrame())
- return false;
+ if (!GetSupplementable()->GetFrame()) {
+ FinalizeWithAbortedNavigationError(script_state, navigation);
+ return DispatchResult::kAbort;
+ }
- ScriptPromise promise = navigate_event->GetNavigationActionPromise();
- if (!promise.IsEmpty()) {
- DocumentLoader* loader = GetSupplementable()->document()->Loader();
- loader->RunURLAndHistoryUpdateSteps(url, state_object, type);
+ auto promise_list = navigate_event->GetNavigationActionPromisesList();
+ if (!promise_list.IsEmpty()) {
+ // The spec says that at this point we should either run the URL and history
+ // update steps (for non-traverse cases) or we should do a same-document
+ // history traversal. In our implementation it's easier for the caller to do
+ // a history traversal since it has access to all the info it needs.
+ // TODO(japhet): Figure out how cross-document back-forward should work.
+ if (type != WebFrameLoadType::kBackForward) {
+ GetSupplementable()->document()->Loader()->RunURLAndHistoryUpdateSteps(
+ url, mojom::blink::SameDocumentNavigationType::kAppHistoryRespondWith,
+ state_object, type);
+ }
}
+ post_navigate_event_ongoing_navigation_signal_ = navigate_event->signal();
- auto* script_state =
- ToScriptStateForMainWorld(GetSupplementable()->GetFrame());
- ScriptState::Scope scope(script_state);
- if (!promise.IsEmpty() || (!navigate_event->defaultPrevented() &&
- event_type != NavigateEventType::kCrossDocument)) {
- if (promise.IsEmpty())
+ if (!promise_list.IsEmpty() ||
+ (!navigate_event->defaultPrevented() &&
+ event_type != NavigateEventType::kCrossDocument)) {
+ ScriptPromise promise;
+ if (promise_list.IsEmpty())
promise = ScriptPromise::CastUndefined(script_state);
- NavigateReaction::React(script_state, promise,
- navigate_method_call_promise_resolver_);
+ else
+ promise = ScriptPromise::All(script_state, promise_list);
+ NavigateReaction::React(
+ script_state, promise, navigation,
+ promise_list.IsEmpty() ? nullptr : navigate_event->signal());
} else {
- navigate_serialized_state_.reset();
+ to_be_set_serialized_state_.reset();
}
- if (navigate_event->defaultPrevented() && promise.IsEmpty()) {
- promise = ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
- "Navigation was aborted"));
- NavigateReaction::React(script_state, promise,
- navigate_method_call_promise_resolver_);
+ if (navigate_event->defaultPrevented()) {
+ FinalizeWithAbortedNavigationError(script_state, navigation);
+ return DispatchResult::kAbort;
}
- return !navigate_event->defaultPrevented();
+ return promise_list.IsEmpty() ? DispatchResult::kContinue
+ : DispatchResult::kRespondWith;
}
-void AppHistory::CancelOngoingNavigateEvent() {
- if (!ongoing_navigate_event_)
- return;
- ongoing_navigate_event_->preventDefault();
- ongoing_navigate_event_->ClearNavigationActionPromise();
- ongoing_navigate_event_ = nullptr;
+void AppHistory::InformAboutCanceledNavigation() {
+ if (ongoing_non_traversal_navigation_ || ongoing_navigate_event_ ||
+ post_navigate_event_ongoing_navigation_signal_) {
+ auto* script_state =
+ ToScriptStateForMainWorld(GetSupplementable()->GetFrame());
+ ScriptState::Scope scope(script_state);
+ FinalizeWithAbortedNavigationError(script_state,
+ ongoing_non_traversal_navigation_);
+ }
+}
+
+void AppHistory::FinalizeWithAbortedNavigationError(
+ ScriptState* script_state,
+ AppHistoryApiNavigation* navigation) {
+ DCHECK(!ongoing_navigate_event_ ||
+ !post_navigate_event_ongoing_navigation_signal_);
+ if (ongoing_navigate_event_) {
+ ongoing_navigate_event_->preventDefault();
+ ongoing_navigate_event_->signal()->SignalAbort();
+ ongoing_navigate_event_ = nullptr;
+ } else if (post_navigate_event_ongoing_navigation_signal_) {
+ post_navigate_event_ongoing_navigation_signal_->SignalAbort();
+ post_navigate_event_ongoing_navigation_signal_ = nullptr;
+ }
+
+ to_be_set_serialized_state_ = nullptr;
+ if (navigation) {
+ ScriptPromise promise = ScriptPromise::RejectWithDOMException(
+ script_state,
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
+ "Navigation was aborted"));
+ NavigateReaction::React(script_state, promise, navigation, nullptr);
+ }
}
int AppHistory::GetIndexFor(AppHistoryEntry* entry) {
@@ -379,9 +721,11 @@ void AppHistory::Trace(Visitor* visitor) const {
EventTargetWithInlineData::Trace(visitor);
Supplement<LocalDOMWindow>::Trace(visitor);
visitor->Trace(entries_);
+ visitor->Trace(ongoing_non_traversal_navigation_);
+ visitor->Trace(ongoing_traversals_);
+ visitor->Trace(upcoming_non_traversal_navigation_);
visitor->Trace(ongoing_navigate_event_);
- visitor->Trace(navigate_method_call_promise_resolver_);
- visitor->Trace(navigate_event_info_);
+ visitor->Trace(post_navigate_event_ongoing_navigation_signal_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history.h b/chromium/third_party/blink/renderer/core/app_history/app_history.h
index 0114a43c25f..ad465969ec5 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history.h
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history.h
@@ -5,25 +5,31 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_H_
+#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/public/web/web_history_item.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/frame/local_dom_window.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/heap/member.h"
#include "third_party/blink/renderer/platform/supplementable.h"
namespace blink {
+class AbortSignal;
+class AppHistoryApiNavigation;
+class AppHistoryUpdateCurrentOptions;
class AppHistoryEntry;
class AppHistoryNavigateEvent;
class AppHistoryNavigateOptions;
+class AppHistoryReloadOptions;
+class AppHistoryNavigationOptions;
class HTMLFormElement;
class HistoryItem;
class KURL;
class ScriptPromise;
-class ScriptPromiseResolver;
class SerializedScriptValue;
// TODO(japhet): This should probably move to frame_loader_types.h and possibly
@@ -51,27 +57,41 @@ class CORE_EXPORT AppHistory final : public EventTargetWithInlineData,
// Web-exposed:
AppHistoryEntry* current() const;
HeapVector<Member<AppHistoryEntry>> entries();
+ void updateCurrent(AppHistoryUpdateCurrentOptions*, ExceptionState&);
+
+ bool canGoBack() const;
+ bool canGoForward() const;
ScriptPromise navigate(ScriptState*,
const String& url,
AppHistoryNavigateOptions*,
ExceptionState&);
- ScriptPromise navigate(ScriptState*,
- AppHistoryNavigateOptions*,
- ExceptionState&);
+ ScriptPromise reload(ScriptState*, AppHistoryReloadOptions*, ExceptionState&);
+
+ ScriptPromise goTo(ScriptState*,
+ const String& key,
+ AppHistoryNavigationOptions*,
+ ExceptionState&);
+ ScriptPromise back(ScriptState*,
+ AppHistoryNavigationOptions*,
+ ExceptionState&);
+ ScriptPromise forward(ScriptState*,
+ AppHistoryNavigationOptions*,
+ ExceptionState&);
DEFINE_ATTRIBUTE_EVENT_LISTENER(navigate, kNavigate)
DEFINE_ATTRIBUTE_EVENT_LISTENER(navigatesuccess, kNavigatesuccess)
DEFINE_ATTRIBUTE_EVENT_LISTENER(navigateerror, kNavigateerror)
- // Returns true if the navigation should continue.
- bool DispatchNavigateEvent(const KURL& url,
- HTMLFormElement* form,
- NavigateEventType,
- WebFrameLoadType,
- UserNavigationInvolvement,
- SerializedScriptValue* = nullptr);
- void CancelOngoingNavigateEvent();
+ enum class DispatchResult { kContinue, kAbort, kRespondWith };
+ DispatchResult DispatchNavigateEvent(const KURL& url,
+ HTMLFormElement* form,
+ NavigateEventType,
+ WebFrameLoadType,
+ UserNavigationInvolvement,
+ SerializedScriptValue* = nullptr,
+ HistoryItem* destination_item = nullptr);
+ void InformAboutCanceledNavigation();
int GetIndexFor(AppHistoryEntry*);
@@ -84,17 +104,38 @@ class CORE_EXPORT AppHistory final : public EventTargetWithInlineData,
void Trace(Visitor*) const final;
private:
+ friend class NavigateReaction;
void PopulateKeySet();
+ void FinalizeWithAbortedNavigationError(ScriptState*,
+ AppHistoryApiNavigation*);
+
+ ScriptPromise PerformNonTraverseNavigation(
+ ScriptState*,
+ const KURL&,
+ scoped_refptr<SerializedScriptValue>,
+ AppHistoryNavigationOptions*,
+ WebFrameLoadType,
+ ExceptionState&);
+
+ void PerformSharedNavigationChecks(
+ ExceptionState&,
+ const String& method_name_for_error_message);
+
+ scoped_refptr<SerializedScriptValue> SerializeState(const ScriptValue&,
+ ExceptionState&);
HeapVector<Member<AppHistoryEntry>> entries_;
HashMap<String, int> keys_to_indices_;
int current_index_ = -1;
+ Member<AppHistoryApiNavigation> ongoing_non_traversal_navigation_;
+ HeapHashMap<String, Member<AppHistoryApiNavigation>> ongoing_traversals_;
+ Member<AppHistoryApiNavigation> upcoming_non_traversal_navigation_;
+
Member<AppHistoryNavigateEvent> ongoing_navigate_event_;
- Member<ScriptPromiseResolver> navigate_method_call_promise_resolver_;
- scoped_refptr<SerializedScriptValue> navigate_serialized_state_;
+ Member<AbortSignal> post_navigate_event_ongoing_navigation_signal_;
- ScriptValue navigate_event_info_;
+ scoped_refptr<SerializedScriptValue> to_be_set_serialized_state_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history.idl b/chromium/third_party/blink/renderer/core/app_history/app_history.idl
index 5a2581084a3..1de99c5db29 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history.idl
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history.idl
@@ -9,9 +9,17 @@
] interface AppHistory : EventTarget {
readonly attribute AppHistoryEntry current;
sequence<AppHistoryEntry> entries();
+ [RaisesException] void updateCurrent(AppHistoryUpdateCurrentOptions options);
+
+ readonly attribute boolean canGoBack;
+ readonly attribute boolean canGoForward;
[CallWith=ScriptState, RaisesException] Promise<void> navigate(USVString url, optional AppHistoryNavigateOptions options = {});
- [CallWith=ScriptState, RaisesException] Promise<void> navigate(AppHistoryNavigateOptions options);
+ [CallWith=ScriptState, RaisesException] Promise<void> reload(optional AppHistoryReloadOptions options = {});
+
+ [CallWith=ScriptState, RaisesException] Promise<void> goTo(DOMString key, optional AppHistoryNavigationOptions options = {});
+ [CallWith=ScriptState, RaisesException] Promise<void> back(optional AppHistoryNavigationOptions options = {});
+ [CallWith=ScriptState, RaisesException] Promise<void> forward(optional AppHistoryNavigationOptions options = {});
attribute EventHandler onnavigate;
attribute EventHandler onnavigatesuccess;
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_destination.h b/chromium/third_party/blink/renderer/core/app_history/app_history_destination.h
new file mode 100644
index 00000000000..ff6010da82d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_destination.h
@@ -0,0 +1,59 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_DESTINATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_DESTINATION_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/core_export.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/heap_allocator.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+class CORE_EXPORT AppHistoryDestination final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ AppHistoryDestination(const KURL& url,
+ bool same_document,
+ SerializedScriptValue* state)
+ : url_(url), same_document_(same_document), state_(state) {}
+ ~AppHistoryDestination() final = default;
+
+ void SetTraverseProperties(const String& key,
+ const String& id,
+ int64_t index) {
+ key_ = key;
+ id_ = id;
+ index_ = index;
+ }
+
+ const String& key() const { return key_; }
+ const String& id() const { return id_; }
+ const KURL& url() const { return url_; }
+ int64_t index() const { return index_; }
+ bool sameDocument() const { return same_document_; }
+ ScriptValue getState(ScriptState* script_state) {
+ v8::Isolate* isolate = script_state->GetIsolate();
+ return state_ ? ScriptValue(isolate, state_->Deserialize(isolate))
+ : ScriptValue();
+ }
+
+ private:
+ String key_;
+ String id_;
+ KURL url_;
+ int64_t index_ = -1;
+ bool same_document_;
+ scoped_refptr<SerializedScriptValue> state_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_DESTINATION_H_
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_destination.idl b/chromium/third_party/blink/renderer/core/app_history/app_history_destination.idl
new file mode 100644
index 00000000000..79cf81a5f8d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_destination.idl
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/app-history/
+[
+ Exposed=Window,
+ RuntimeEnabled=AppHistory
+] interface AppHistoryDestination {
+ readonly attribute DOMString? key;
+ readonly attribute DOMString? id;
+ readonly attribute USVString url;
+ readonly attribute long long index;
+ readonly attribute boolean sameDocument;
+ [CallWith=ScriptState] any getState();
+};
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.cc b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.cc
index aca594ec30a..e0fa6219c32 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.cc
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/core/app_history/app_history_navigate_event.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.h"
+#include "third_party/blink/renderer/core/app_history/app_history_destination.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/event_interface_names.h"
#include "third_party/blink/renderer/core/event_type_names.h"
@@ -19,11 +21,17 @@ AppHistoryNavigateEvent::AppHistoryNavigateEvent(
AppHistoryNavigateEventInit* init)
: Event(type, init),
ExecutionContextClient(context),
+ navigation_type_(init->navigationType()),
+ destination_(init->destination()),
can_respond_(init->canRespond()),
user_initiated_(init->userInitiated()),
hash_change_(init->hashChange()),
+ signal_(init->signal()),
form_data_(init->formData()),
- info_(init->info()) {
+ info_(init->hasInfo()
+ ? init->info()
+ : ScriptValue(context->GetIsolate(),
+ v8::Undefined(context->GetIsolate()))) {
DCHECK(IsA<LocalDOMWindow>(context));
}
@@ -60,12 +68,7 @@ void AppHistoryNavigateEvent::respondWith(ScriptState* script_state,
return;
}
- preventDefault();
- navigation_action_promise_ = newNavigationAction;
-}
-
-void AppHistoryNavigateEvent::ClearNavigationActionPromise() {
- navigation_action_promise_ = ScriptPromise();
+ navigation_action_promises_list_.push_back(newNavigationAction);
}
const AtomicString& AppHistoryNavigateEvent::InterfaceName() const {
@@ -75,9 +78,11 @@ const AtomicString& AppHistoryNavigateEvent::InterfaceName() const {
void AppHistoryNavigateEvent::Trace(Visitor* visitor) const {
Event::Trace(visitor);
ExecutionContextClient::Trace(visitor);
+ visitor->Trace(destination_);
+ visitor->Trace(signal_);
visitor->Trace(form_data_);
visitor->Trace(info_);
- visitor->Trace(navigation_action_promise_);
+ visitor->Trace(navigation_action_promises_list_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.h b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.h
index 558c60d1178..cd2cdad42c7 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.h
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.h
@@ -18,6 +18,8 @@
namespace blink {
+class AbortSignal;
+class AppHistoryDestination;
class AppHistoryNavigateEventInit;
class ExceptionState;
class FormData;
@@ -40,9 +42,12 @@ class AppHistoryNavigateEvent final : public Event,
void SetUrl(const KURL& url) { url_ = url; }
+ String navigationType() { return navigation_type_; }
+ AppHistoryDestination* destination() { return destination_; }
bool canRespond() const { return can_respond_; }
bool userInitiated() const { return user_initiated_; }
bool hashChange() const { return hash_change_; }
+ AbortSignal* signal() { return signal_; }
FormData* formData() const { return form_data_; }
ScriptValue info() const { return info_; }
@@ -50,23 +55,25 @@ class AppHistoryNavigateEvent final : public Event,
ScriptPromise newNavigationAction,
ExceptionState&);
- ScriptPromise GetNavigationActionPromise() {
- return navigation_action_promise_;
+ const HeapVector<ScriptPromise>& GetNavigationActionPromisesList() {
+ return navigation_action_promises_list_;
}
- void ClearNavigationActionPromise();
const AtomicString& InterfaceName() const final;
void Trace(Visitor*) const final;
private:
+ String navigation_type_;
+ Member<AppHistoryDestination> destination_;
bool can_respond_;
bool user_initiated_;
bool hash_change_;
+ Member<AbortSignal> signal_;
Member<FormData> form_data_;
ScriptValue info_;
KURL url_;
- ScriptPromise navigation_action_promise_;
+ HeapVector<ScriptPromise> navigation_action_promises_list_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl
index d2536a89b4a..b699da7d448 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl
@@ -9,11 +9,12 @@
] interface AppHistoryNavigateEvent : Event {
[CallWith=ExecutionContext] constructor(DOMString type, optional AppHistoryNavigateEventInit eventInit = {});
+ readonly attribute AppHistoryNavigationType navigationType;
+ readonly attribute AppHistoryDestination destination;
readonly attribute boolean canRespond;
readonly attribute boolean userInitiated;
readonly attribute boolean hashChange;
- // readonly attribute AppHistoryEntry destination;
- // readonly attribute AbortSignal signal;
+ readonly attribute AbortSignal signal;
readonly attribute FormData? formData;
readonly attribute any info;
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl
index 1c32429d193..1c0b744bd4d 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl
@@ -3,12 +3,20 @@
// found in the LICENSE file.
// https://github.com/WICG/app-history/
+enum AppHistoryNavigationType {
+ "reload",
+ "push",
+ "replace",
+ "traverse"
+};
+
dictionary AppHistoryNavigateEventInit : EventInit {
+ AppHistoryNavigationType navigationType = "push";
+ required AppHistoryDestination destination;
boolean canRespond = false;
boolean userInitiated = false;
boolean hashChange = false;
- // AppHistoryEntry destination;
- // AbortSignal signal;
+ required AbortSignal signal;
FormData? formData = null;
any info;
};
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_navigation_options.idl b/chromium/third_party/blink/renderer/core/app_history/app_history_navigation_options.idl
index 81888fd43e8..c698c4362e4 100644
--- a/chromium/third_party/blink/renderer/core/app_history/app_history_navigation_options.idl
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_navigation_options.idl
@@ -4,5 +4,5 @@
// https://github.com/WICG/app-history/
dictionary AppHistoryNavigationOptions {
- any navigateInfo;
+ any info;
};
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_reload_options.idl b/chromium/third_party/blink/renderer/core/app_history/app_history_reload_options.idl
new file mode 100644
index 00000000000..e1103e3e7e2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_reload_options.idl
@@ -0,0 +1,8 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/app-history/
+dictionary AppHistoryReloadOptions : AppHistoryNavigationOptions {
+ any state;
+};
diff --git a/chromium/third_party/blink/renderer/core/app_history/app_history_update_current_options.idl b/chromium/third_party/blink/renderer/core/app_history/app_history_update_current_options.idl
new file mode 100644
index 00000000000..e8a8005af61
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/app_history/app_history_update_current_options.idl
@@ -0,0 +1,8 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/app-history/
+dictionary AppHistoryUpdateCurrentOptions {
+ required any state;
+};
diff --git a/chromium/third_party/blink/renderer/core/app_history/build.gni b/chromium/third_party/blink/renderer/core/app_history/build.gni
index 12271643734..8861e3942e0 100644
--- a/chromium/third_party/blink/renderer/core/app_history/build.gni
+++ b/chromium/third_party/blink/renderer/core/app_history/build.gni
@@ -5,6 +5,7 @@
blink_core_sources_app_history = [
"app_history.cc",
"app_history.h",
+ "app_history_destination.h",
"app_history_entry.cc",
"app_history_entry.h",
"app_history_navigate_event.cc",
diff --git a/chromium/third_party/blink/renderer/core/app_history/window_app_history.idl b/chromium/third_party/blink/renderer/core/app_history/window_app_history.idl
index 954daa2c633..ac6516cd8a9 100644
--- a/chromium/third_party/blink/renderer/core/app_history/window_app_history.idl
+++ b/chromium/third_party/blink/renderer/core/app_history/window_app_history.idl
@@ -6,5 +6,5 @@
[
ImplementedAs=AppHistory
] partial interface Window {
- [RuntimeEnabled=AppHistory, Affects=Nothing] readonly attribute AppHistory appHistory;
+ [RuntimeEnabled=AppHistory] readonly attribute AppHistory appHistory;
};
diff --git a/chromium/third_party/blink/renderer/core/clipboard/OWNERS b/chromium/third_party/blink/renderer/core/clipboard/OWNERS
index 7e397eb0d9c..e0898d310a2 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/OWNERS
+++ b/chromium/third_party/blink/renderer/core/clipboard/OWNERS
@@ -1,7 +1,6 @@
# Primary:
-huangdarwin@chromium.org
+mek@chromium.org
# Secondary:
dcheng@chromium.org
-mek@chromium.org
pwnall@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/clipboard/README.md b/chromium/third_party/blink/renderer/core/clipboard/README.md
new file mode 100644
index 00000000000..aee45fd33f5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/clipboard/README.md
@@ -0,0 +1,126 @@
+# Blink Clipboard Overview
+
+Blink exposes the clipboard to users, to allow them to share content between
+a web application and a native or web application. Users most commonly interact
+with this via "ctl+c" / "ctl+v" or the context menu's "copy", "cut", and "paste"
+buttons. That said, Blink does also expose some APIs for use by sites.
+
+## APIs
+
+A few different clipboard APIs are exposed:
+* `document.execCommand('copy')`
+* `DataTransfer`
+* Async Clipboard API
+
+### Overviews
+
+#### `document.execCommand('copy')`
+
+`document.execCommand('copy')` can be used to copy content from HTML documents,
+like text, HTML, and images. This API is deprecated and has inconsistent support
+between browsers, and is mostly only supported for legacy reasons. It is also
+synchronous, which means large copies or pastes will cause jank and freeze the
+browser. Therefore, while we continue to maintain this API for legacy reasons,
+we recommend sites against using this API.
+
+`document.execCommand('copy')` is:
+* specified in the
+ [execCommand](https://w3c.github.io/editing/docs/execCommand/#the-copy-command)
+ specification.
+* documented for web developers in
+ [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand).
+
+#### `DataTransfer`
+
+`DataTransfer` is a mature, flexible API with strong user gesture guarantees,
+that Chrome inherited when it forked from WebKit, and was likely based on IE's
+implementation at the time. It supports both clipboard and drag-and-drop.
+
+`DataTransfer` is:
+* specified in the
+ [HTML](https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface).
+ specification.
+* documented for web developers in the
+ [MDN](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer).
+
+#### Async Clipboard API
+
+The Async Clipboard API is a relatively new, programmatic API that aims to be
+the primary API for new clipboard functionality. It allows for much larger
+clipboard payloads due to its asynchronous behavior, and includes some newer
+protections like permissions policy.
+
+The Async Clipboard API is:
+* specified in the
+ [Clipboard API and events](https://w3c.github.io/clipboard-apis/)
+ specification.
+* documented for web developers in
+ [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API).
+
+### Common topics
+
+#### Sanitization
+
+As documented in the
+[mojo barrier's](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/clipboard/clipboard.mojom)
+"security note" and "privacy note", sanitization is an important part of
+safeguarding the user's:
+* security and system integrity on write
+* privacy and personally identifiable information (PII) on read
+
+Unfortunately, sanitization often reduces fidelity by stripping away important
+metadata or other information, like CSS `<style>` tags and `<script>` tags in
+HTML. While this is done to protect the integrity of the underlying operating
+system, the reduced fidelity can harm the productivity of web applications by
+reducing the set of features they can adopt.
+
+Sanitization is commonly accomplished by sending untrusted web-originated
+payloads through encoders and decoders trusted to safely remove malicious
+content, as seen in the Async Clipboard API's
+[`ClipboardWriter`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/clipboard/clipboard_writer.h).
+
+Currently:
+* `document.execCommand('copy')` aggressively sanitizes clipboard content,
+ including HTML, where `<style>`, `<meta>`, `<script>`, etc are all sanitized.
+ This is especially important for this API because it handles content actively
+ on the HTML document.
+* The Async Clipboard API sanitizes relatively aggressively, like
+ `document.execCommand('copy')`, for safety.
+* `DataTransfer` does *not* sanitize most clipboard content, including HTML.
+ This was likely done in the past for parity with Internet Explorer, and
+ sanitization cannot be added now without breaking compatibility with sites.
+
+#### Asynchronous Behavior
+
+The Async Clipboard API is the only asynchronous clipboard API currently
+available to websites. It's recommended for all new use cases, because the API
+surface allows sites, especially those copying or pasting large payloads
+(ex. image editing applications) to copy or paste without blocking the
+browser process and freezing users screens until the operation is complete.
+Currently, much of the clipboard infrastructure is synchronous, so this benefit
+is mostly only realized during sanitization, which is done in a background
+thread in the renderer. This asynchronous behavior can be improved by improving
+[promise support](https://crbug.com/1014310) or
+[improvements in asynchronicity](https://crbug.com/443355) of the browser
+process clipboard implementation.
+
+In contrast, all other clipboard APIs are completely synchronous, and a very
+large clipboard payload will freeze the renderer both during sanitization,
+and while passing information around, until the operation is complete. As their
+API surfaces are synchronous, improvements in asynchronicity of clipboard
+infrastructure will be unlikely to improve these other APIs' freezing of the
+renderer on large reads/writes.
+
+#### User Gesture
+
+`document.execCommand('copy')` and the Async Clipboard API do not require user
+gesture, whereas DataTransfer requires a strict user gesture in the form of a
+`copy` or `paste` event. It would be web-incompatible to require user gesture,
+but requiring it could greatly secure the clipboard and improve specification
+compliance. This is tracked and discussed in greater detail in
+[this bug](https://crbug.com/1230211).
+
+#### API Recommendations
+
+Generally, the Async Clipboard API is recommended for new use-cases, as it's
+the most modern, asynchronous, and a generally new API.
diff --git a/chromium/third_party/blink/renderer/core/clipboard/build.gni b/chromium/third_party/blink/renderer/core/clipboard/build.gni
index 65a04dc540d..fe60db8ad3d 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/build.gni
+++ b/chromium/third_party/blink/renderer/core/clipboard/build.gni
@@ -21,8 +21,6 @@ blink_core_sources_clipboard = [
"dragged_isolated_file_system.cc",
"dragged_isolated_file_system.h",
"paste_mode.h",
- "raw_system_clipboard.cc",
- "raw_system_clipboard.h",
"system_clipboard.cc",
"system_clipboard.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
index 45e0b1b4327..7b05201f802 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "net/base/escape.h"
#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -93,6 +94,18 @@ String URLToImageMarkup(const KURL& url, const String& title) {
return builder.ToString();
}
+String PNGToImageMarkup(const mojo_base::BigBuffer& png_data) {
+ if (!png_data.size())
+ return String();
+
+ StringBuilder markup;
+ markup.Append("<img src=\"data:image/png;base64,");
+ markup.Append(Base64Encode(png_data));
+ markup.Append("\" alt=\"\"/>");
+ return markup.ToString();
+}
+
+// TODO(crbug.com/1223849): Remove this method once `ReadImage()` is removed.
String BitmapToImageMarkup(const SkBitmap& bitmap) {
if (bitmap.isNull())
return String();
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h
index 25709b7664c..a4dd3e2dfc8 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_UTILITIES_H_
#include "build/build_config.h"
+#include "mojo/public/cpp/base/big_buffer.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"
@@ -45,6 +46,8 @@ CORE_EXPORT void ReplaceNewlinesWithWindowsStyleNewlines(String&);
CORE_EXPORT void ReplaceNBSPWithSpace(String&);
CORE_EXPORT String ConvertURIListToURL(const String& uri_list);
CORE_EXPORT String URLToImageMarkup(const KURL&, const String& title);
+CORE_EXPORT String PNGToImageMarkup(const mojo_base::BigBuffer& png_data);
+// TODO(crbug.com/1223849): Remove this method once `ReadImage()` is removed.
CORE_EXPORT String BitmapToImageMarkup(const SkBitmap& bitmap);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_test.cc b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_test.cc
index 4aabc435c74..a8b4387e493 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_test.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_test.cc
@@ -4,9 +4,14 @@
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
+#include "base/containers/span.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/encode/SkPngEncoder.h"
namespace blink {
@@ -43,6 +48,30 @@ TEST(ClipboardUtilitiesTest, URLToImageMarkupEmbeddedNull) {
String(kTitleWithNull, sizeof(kTitleWithNull) - 1)));
}
+TEST(ClipboardUtilitiesTest, PNGToImageMarkupEmpty) {
+ EXPECT_TRUE(PNGToImageMarkup(mojo_base::BigBuffer()).IsNull());
+}
+
+TEST(ClipboardUtilitiesTest, PNGToImageMarkup) {
+ SkBitmap bitmap;
+ bitmap.allocPixels(SkImageInfo::MakeN32Premul(10, 5));
+ SkPixmap pixmap;
+ bitmap.peekPixels(&pixmap);
+
+ // Set encoding options to favor speed over size.
+ SkPngEncoder::Options options;
+ options.fZLibLevel = 1;
+ options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
+
+ Vector<uint8_t> png_data;
+ EXPECT_TRUE(ImageEncoder::Encode(&png_data, pixmap, options));
+
+ mojo_base::BigBuffer png = base::as_bytes(base::make_span(png_data));
+ EXPECT_EQ(
+ R"HTML(<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAFCAYAAAB8ZH1oAAAADElEQVQYGWNgGEYAAADNAAGVVebMAAAAAElFTkSuQmCC" alt=""/>)HTML",
+ PNGToImageMarkup(png));
+}
+
TEST(ClipboardUtilitiesTest, BitmapToImageMarkupEmpty) {
SkBitmap bitmap;
EXPECT_TRUE(BitmapToImageMarkup(bitmap).IsNull());
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 58d1c47df2c..a328b62c4ac 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_object.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_object.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/core/clipboard/data_object.h"
-#include "base/feature_list.h"
#include "base/notreached.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/platform.h"
@@ -42,7 +41,6 @@
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "ui/base/ui_base_features.h"
namespace blink {
@@ -53,13 +51,13 @@ DataObject* DataObject::CreateFromClipboard(SystemClipboard* system_clipboard,
#if DCHECK_IS_ON()
HashSet<String> types_seen;
#endif
- uint64_t sequence_number = system_clipboard->SequenceNumber();
+ ClipboardSequenceNumberToken sequence_number =
+ system_clipboard->SequenceNumber();
for (const String& type : system_clipboard->ReadAvailableTypes()) {
if (paste_mode == PasteMode::kPlainTextOnly && type != kMimeTypeTextPlain)
continue;
mojom::blink::ClipboardFilesPtr files;
- if (type == kMimeTypeTextURIList &&
- base::FeatureList::IsEnabled(features::kClipboardFilenames)) {
+ if (type == kMimeTypeTextURIList) {
files = system_clipboard->ReadFiles();
// Ignore ReadFiles() result if clipboard sequence number has changed.
if (system_clipboard->SequenceNumber() != sequence_number) {
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 c0546a3cbba..e4ddd63538a 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,6 +31,8 @@
#include "third_party/blink/renderer/core/clipboard/data_object_item.h"
#include "base/time/time.h"
+#include "base/unguessable_token.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_data_transfer_token.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
@@ -39,6 +41,7 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -113,7 +116,7 @@ DataObjectItem* DataObjectItem::CreateFromSharedBuffer(
DataObjectItem* DataObjectItem::CreateFromClipboard(
SystemClipboard* system_clipboard,
const String& type,
- uint64_t sequence_number) {
+ const ClipboardSequenceNumberToken& sequence_number) {
if (type == kMimeTypeImagePng) {
return MakeGarbageCollected<DataObjectItem>(
kFileKind, type, sequence_number, system_clipboard);
@@ -126,13 +129,14 @@ DataObjectItem::DataObjectItem(ItemKind kind, const String& type)
: source_(DataSource::kInternalSource),
kind_(kind),
type_(type),
- sequence_number_(0),
+ sequence_number_(base::UnguessableToken::Create()),
system_clipboard_(nullptr) {}
-DataObjectItem::DataObjectItem(ItemKind kind,
- const String& type,
- uint64_t sequence_number,
- SystemClipboard* system_clipboard)
+DataObjectItem::DataObjectItem(
+ ItemKind kind,
+ const String& type,
+ const ClipboardSequenceNumberToken& sequence_number,
+ SystemClipboard* system_clipboard)
: source_(DataSource::kClipboardSource),
kind_(kind),
type_(type),
@@ -157,24 +161,36 @@ File* DataObjectItem::GetAsFile() const {
DCHECK_EQ(source_, DataSource::kClipboardSource);
if (GetType() == kMimeTypeImagePng) {
- SkBitmap bitmap =
- system_clipboard_->ReadImage(mojom::ClipboardBuffer::kStandard);
+ // TODO(crbug.com/1223849): Reorder to initialize `data` after the system
+ // clipboard call once `ReadImage()` is removed entirely. This was moved up
+ // to allow `AppendBytes()` to read either vector or buffer data.
+ auto data = std::make_unique<BlobData>();
+ data->SetContentType(kMimeTypeImagePng);
- SkPixmap pixmap;
- bitmap.peekPixels(&pixmap);
+ if (RuntimeEnabledFeatures::ClipboardReadPngEnabled()) {
+ mojo_base::BigBuffer png_data =
+ system_clipboard_->ReadPng(mojom::blink::ClipboardBuffer::kStandard);
- // Set encoding options to favor speed over size.
- SkPngEncoder::Options options;
- options.fZLibLevel = 1;
- options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
+ data->AppendBytes(png_data.data(), png_data.size());
+ } else {
+ SkBitmap bitmap = system_clipboard_->ReadImage(
+ mojom::blink::ClipboardBuffer::kStandard);
- Vector<uint8_t> png_data;
- if (!ImageEncoder::Encode(&png_data, pixmap, options))
- return nullptr;
+ SkPixmap pixmap;
+ bitmap.peekPixels(&pixmap);
+
+ // Set encoding options to favor speed over size.
+ SkPngEncoder::Options options;
+ options.fZLibLevel = 1;
+ options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
+
+ Vector<uint8_t> png_data;
+ if (!ImageEncoder::Encode(&png_data, pixmap, options))
+ return nullptr;
+
+ data->AppendBytes(png_data.data(), png_data.size());
+ }
- auto data = std::make_unique<BlobData>();
- 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 MakeGarbageCollected<File>("image.png", base::Time::Now(),
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_object_item.h b/chromium/third_party/blink/renderer/core/clipboard/data_object_item.h
index 7bd24dab60b..08aa539f02c 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_object_item.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_object_item.h
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_DATA_OBJECT_ITEM_H_
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_data_transfer_token.mojom-blink.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -69,14 +68,15 @@ class CORE_EXPORT DataObjectItem final
const KURL&,
const String& file_extension,
const AtomicString& content_disposition);
- static DataObjectItem* CreateFromClipboard(SystemClipboard* system_clipboard,
- const String& type,
- uint64_t sequence_number);
+ static DataObjectItem* CreateFromClipboard(
+ SystemClipboard* system_clipboard,
+ const String& type,
+ const ClipboardSequenceNumberToken& sequence_number);
DataObjectItem(ItemKind kind, const String& type);
DataObjectItem(ItemKind,
const String& type,
- uint64_t sequence_number,
+ const ClipboardSequenceNumberToken& sequence_number,
SystemClipboard* system_clipboard);
ItemKind Kind() const { return kind_; }
@@ -120,9 +120,9 @@ class CORE_EXPORT DataObjectItem final
String title_;
KURL base_url_;
- uint64_t sequence_number_; // Only valid when |source_| ==
- // DataSource::kClipboardSource.
- String file_system_id_; // Only valid when |file_| is backed by FileEntry.
+ ClipboardSequenceNumberToken // Only valid when |source_| ==
+ sequence_number_; // DataSource::kClipboardSource.
+ String file_system_id_; // Only valid when |file_| is backed by FileEntry.
// Access to the global system clipboard.
Member<SystemClipboard> system_clipboard_;
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 5f9a4f1dcb1..dfecbbd65a1 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -29,7 +29,6 @@
#include "build/build_config.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/widget/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"
@@ -51,6 +50,7 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_image.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/cull_rect_updater.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"
@@ -61,6 +61,7 @@
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -124,15 +125,22 @@ class DraggedNodeImageBuilder {
layer->GetLayoutObject()
.AbsoluteToLocalQuad(FloatQuad(absolute_bounding_box))
.BoundingBox();
+ absl::optional<OverriddenCullRectScope> cull_rect_scope;
+ if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
+ FloatRect cull_rect = bounding_box;
+ cull_rect.Move(
+ FloatSize(layer->GetLayoutObject().FirstFragment().PaintOffset()));
+ cull_rect_scope.emplace(*layer, CullRect(EnclosingIntRect(cull_rect)));
+ }
PaintLayerPaintingInfo painting_info(
layer, CullRect(EnclosingIntRect(bounding_box)),
kGlobalPaintFlattenCompositingLayers, PhysicalOffset());
- PaintLayerFlags flags = kPaintLayerHaveTransparency;
PaintRecordBuilder builder;
dragged_layout_object->GetDocument().Lifecycle().AdvanceTo(
DocumentLifecycle::kInPaint);
- PaintLayerPainter(*layer).Paint(builder.Context(), painting_info, flags);
+ PaintLayerPainter(*layer).Paint(builder.Context(), painting_info,
+ kPaintLayerNoFlag);
dragged_layout_object->GetDocument().Lifecycle().AdvanceTo(
DocumentLifecycle::kPaintClean);
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item.h b/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item.h
index 5b8eb4a3fd6..e51f88d2fee 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_DATA_TRANSFER_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_DATA_TRANSFER_ITEM_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_function_string_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
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 57627202f37..59750877450 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
@@ -13,16 +13,19 @@
#include "third_party/blink/renderer/core/page/drag_image.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"
namespace blink {
-class DataTransferTest : public RenderingTest {
+class DataTransferTest : public PaintTestConfigurations, public RenderingTest {
protected:
Page& GetPage() const { return *GetDocument().GetPage(); }
LocalFrame& GetFrame() const { return *GetDocument().GetFrame(); }
};
-TEST_F(DataTransferTest, NodeImage) {
+INSTANTIATE_PAINT_TEST_SUITE_P(DataTransferTest);
+
+TEST_P(DataTransferTest, NodeImage) {
SetBodyInnerHTML(R"HTML(
<style>
#sample { width: 100px; height: 100px; }
@@ -35,7 +38,7 @@ TEST_F(DataTransferTest, NodeImage) {
EXPECT_EQ(IntSize(100, 100), image->Size());
}
-TEST_F(DataTransferTest, NodeImageWithNestedElement) {
+TEST_P(DataTransferTest, NodeImageWithNestedElement) {
SetBodyInnerHTML(R"HTML(
<style>
div { -webkit-user-drag: element }
@@ -52,7 +55,7 @@ TEST_F(DataTransferTest, NodeImageWithNestedElement) {
<< "Descendants node should have :-webkit-drag.";
}
-TEST_F(DataTransferTest, NodeImageWithPsuedoClassWebKitDrag) {
+TEST_P(DataTransferTest, NodeImageWithPsuedoClassWebKitDrag) {
SetBodyInnerHTML(R"HTML(
<style>
#sample { width: 100px; height: 100px; }
@@ -67,7 +70,7 @@ TEST_F(DataTransferTest, NodeImageWithPsuedoClassWebKitDrag) {
<< ":-webkit-drag should affect dragged image.";
}
-TEST_F(DataTransferTest, NodeImageWithoutDraggedLayoutObject) {
+TEST_P(DataTransferTest, NodeImageWithoutDraggedLayoutObject) {
SetBodyInnerHTML(R"HTML(
<style>
#sample { width: 100px; height: 100px; }
@@ -81,7 +84,7 @@ TEST_F(DataTransferTest, NodeImageWithoutDraggedLayoutObject) {
EXPECT_EQ(nullptr, image.get()) << ":-webkit-drag blows away layout object";
}
-TEST_F(DataTransferTest, NodeImageWithChangingLayoutObject) {
+TEST_P(DataTransferTest, NodeImageWithChangingLayoutObject) {
SetBodyInnerHTML(R"HTML(
<style>
#sample { color: blue; }
@@ -109,7 +112,7 @@ TEST_F(DataTransferTest, NodeImageWithChangingLayoutObject) {
<< "#sample doesn't have :-webkit-drag.";
}
-TEST_F(DataTransferTest, NodeImageExceedsViewportBounds) {
+TEST_P(DataTransferTest, NodeImageExceedsViewportBounds) {
SetBodyInnerHTML(R"HTML(
<style>
* { margin: 0; }
@@ -122,7 +125,7 @@ TEST_F(DataTransferTest, NodeImageExceedsViewportBounds) {
EXPECT_EQ(IntSize(800, 600), image->Size());
}
-TEST_F(DataTransferTest, NodeImageUnderScrollOffset) {
+TEST_P(DataTransferTest, NodeImageUnderScrollOffset) {
SetBodyInnerHTML(R"HTML(
<style>
* { margin: 0; }
@@ -153,7 +156,7 @@ TEST_F(DataTransferTest, NodeImageUnderScrollOffset) {
second_image->Size());
}
-TEST_F(DataTransferTest, NodeImageSizeWithPageScaleFactor) {
+TEST_P(DataTransferTest, NodeImageSizeWithPageScaleFactor) {
SetBodyInnerHTML(R"HTML(
<style>
* { margin: 0; }
@@ -184,7 +187,7 @@ TEST_F(DataTransferTest, NodeImageSizeWithPageScaleFactor) {
image_with_offset->Size());
}
-TEST_F(DataTransferTest, NodeImageSizeWithPageScaleFactorTooLarge) {
+TEST_P(DataTransferTest, NodeImageSizeWithPageScaleFactorTooLarge) {
SetBodyInnerHTML(R"HTML(
<style>
* { margin: 0; }
@@ -215,7 +218,7 @@ TEST_F(DataTransferTest, NodeImageSizeWithPageScaleFactorTooLarge) {
image_with_offset->Size());
}
-TEST_F(DataTransferTest, NodeImageWithPageScaleFactor) {
+TEST_P(DataTransferTest, NodeImageWithPageScaleFactor) {
// #bluegreen is a 2x1 rectangle where the left pixel is blue and the right
// pixel is green. The element is offset by a margin of 1px.
SetBodyInnerHTML(R"HTML(
@@ -254,7 +257,7 @@ TEST_F(DataTransferTest, NodeImageWithPageScaleFactor) {
EXPECT_EQ(expected_bitmap.getColor(x, y), bitmap.getColor(x, y));
}
-TEST_F(DataTransferTest, NodeImageFullyOffscreen) {
+TEST_P(DataTransferTest, NodeImageFullyOffscreen) {
SetBodyInnerHTML(R"HTML(
<style>
#target {
@@ -281,7 +284,7 @@ TEST_F(DataTransferTest, NodeImageFullyOffscreen) {
EXPECT_EQ(IntSize(200, 100), image->Size());
}
-TEST_F(DataTransferTest, NodeImageWithScrolling) {
+TEST_P(DataTransferTest, NodeImageWithScrolling) {
SetBodyInnerHTML(R"HTML(
<style>
#target {
@@ -303,7 +306,7 @@ TEST_F(DataTransferTest, NodeImageWithScrolling) {
EXPECT_EQ(IntSize(200, 100), image->Size());
}
-TEST_F(DataTransferTest, NodeImageInOffsetStackingContext) {
+TEST_P(DataTransferTest, NodeImageInOffsetStackingContext) {
SetBodyInnerHTML(R"HTML(
<style>
* { margin: 0; }
@@ -337,7 +340,7 @@ TEST_F(DataTransferTest, NodeImageInOffsetStackingContext) {
}
}
-TEST_F(DataTransferTest, NodeImageWithLargerPositionedDescendant) {
+TEST_P(DataTransferTest, NodeImageWithLargerPositionedDescendant) {
SetBodyInnerHTML(R"HTML(
<style>
* { margin: 0; }
@@ -380,4 +383,50 @@ TEST_F(DataTransferTest, NodeImageWithLargerPositionedDescendant) {
}
}
+TEST_P(DataTransferTest, NodeImageOutOfView) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="drag" style="position: absolute; z-index: 1; top: -200px; left: 0;
+ width: 100px; height: 100px; background: green">
+ </div>
+ )HTML");
+
+ auto image = DataTransfer::NodeImage(GetFrame(),
+ *GetDocument().getElementById("drag"));
+ EXPECT_EQ(IntSize(100, 100), image->Size());
+ Color green(0, 0x80, 0);
+ const SkBitmap& bitmap = image->Bitmap();
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 100; ++y)
+ ASSERT_EQ(green, bitmap.getColor(x, y));
+ }
+}
+
+TEST_P(DataTransferTest, NodeImageFixedChild) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="drag" style="position: absolute; z-index: 1; top: 100px; left: 0;
+ width: 50px; height: 100px; background: green">
+ <div style="position: fixed; top: 50px; width: 100px; height: 50px;
+ background: blue">
+ </div>
+ </div>
+ <div style="height: 2000px"></div>
+ )HTML");
+
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 100), mojom::blink::ScrollType::kProgrammatic);
+
+ auto image = DataTransfer::NodeImage(GetFrame(),
+ *GetDocument().getElementById("drag"));
+ EXPECT_EQ(IntSize(100, 100), image->Size());
+ Color green(0, 0x80, 0);
+ Color blue(0, 0, 0xFF);
+ const SkBitmap& bitmap = image->Bitmap();
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 50; ++y)
+ ASSERT_EQ(x < 50 ? green : Color::kTransparent, bitmap.getColor(x, y));
+ for (int y = 50; y < 100; ++y)
+ ASSERT_EQ(blue, bitmap.getColor(x, y));
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h b/chromium/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h
index 15fbc949d33..75092ce1151 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_DRAGGED_ISOLATED_FILE_SYSTEM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_DRAGGED_ISOLATED_FILE_SYSTEM_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc b/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc
deleted file mode 100644
index 73e8a755ede..00000000000
--- a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/clipboard/raw_system_clipboard.h"
-
-#include "mojo/public/cpp/base/big_buffer.h"
-#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-
-#include "third_party/blink/public/mojom/clipboard/raw_clipboard.mojom-blink.h"
-namespace blink {
-
-RawSystemClipboard::RawSystemClipboard(LocalFrame* frame)
- : clipboard_(frame->DomWindow()) {
- frame->GetBrowserInterfaceBroker().GetInterface(
- clipboard_.BindNewPipeAndPassReceiver(
- frame->GetTaskRunner(TaskType::kUserInteraction)));
-}
-
-void RawSystemClipboard::ReadAvailableFormatNames(
- mojom::blink::RawClipboardHost::ReadAvailableFormatNamesCallback callback) {
- clipboard_->ReadAvailableFormatNames(std::move(callback));
-}
-
-void RawSystemClipboard::Read(
- const String& type,
- mojom::blink::RawClipboardHost::ReadCallback callback) {
- clipboard_->Read(type, std::move(callback));
-}
-
-void RawSystemClipboard::Write(const String& type, mojo_base::BigBuffer data) {
- clipboard_->Write(type, std::move(data));
-}
-
-void RawSystemClipboard::CommitWrite() {
- clipboard_->CommitWrite();
-}
-
-void RawSystemClipboard::Trace(Visitor* visitor) const {
- visitor->Trace(clipboard_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h b/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h
deleted file mode 100644
index e78f93e19b7..00000000000
--- a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_RAW_SYSTEM_CLIPBOARD_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_RAW_SYSTEM_CLIPBOARD_H_
-
-#include "third_party/blink/public/mojom/clipboard/raw_clipboard.mojom-blink.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
-
-// RawSystemClipboard:
-// - is a singleton.
-// - provides read/write access of unsanitized, platform-specific data.
-// - mediates between async clipboard and mojom::RawClipboardHost.
-//
-// All calls to Write() must be followed by a call to CommitWrite().
-namespace blink {
-
-class LocalFrame;
-
-class CORE_EXPORT RawSystemClipboard final
- : public GarbageCollected<RawSystemClipboard> {
- public:
- explicit RawSystemClipboard(LocalFrame* frame);
-
- RawSystemClipboard(const RawSystemClipboard&) = delete;
- RawSystemClipboard& operator=(const RawSystemClipboard&) = delete;
-
- void ReadAvailableFormatNames(
- mojom::blink::RawClipboardHost::ReadAvailableFormatNamesCallback
- callback);
-
- void Read(const String& type,
- mojom::blink::RawClipboardHost::ReadCallback callback);
-
- void Write(const String& type, mojo_base::BigBuffer data);
-
- void CommitWrite();
- void Trace(Visitor*) const;
-
- private:
- HeapMojoRemote<mojom::blink::RawClipboardHost> clipboard_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_RAW_SYSTEM_CLIPBOARD_H_
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 8383fe3d8e2..dfe5ebe3035 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -5,8 +5,10 @@
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "base/memory/scoped_refptr.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
@@ -50,7 +52,8 @@ enum class ClipboardPastedImageUrls {
kOtherUrls = 4,
kBase64EncodedImage = 5,
kLocalFileUrlWithRtf = 6,
- kMaxValue = kLocalFileUrlWithRtf,
+ kImageLoadError = 7,
+ kMaxValue = kImageLoadError,
};
} // namespace
@@ -83,10 +86,10 @@ bool SystemClipboard::IsFormatAvailable(blink::mojom::ClipboardFormat format) {
return result;
}
-uint64_t SystemClipboard::SequenceNumber() {
+ClipboardSequenceNumberToken SystemClipboard::SequenceNumber() {
if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
- return 0;
- uint64_t result = 0;
+ return ClipboardSequenceNumberToken();
+ ClipboardSequenceNumberToken result;
clipboard_->GetSequenceNumber(buffer_, &result);
return result;
}
@@ -119,14 +122,15 @@ void SystemClipboard::WritePlainText(const String& plain_text,
#if defined(OS_WIN)
ReplaceNewlinesWithWindowsStyleNewlines(text);
#endif
- clipboard_->WriteText(NonNullString(text));
+ if (clipboard_.is_bound())
+ clipboard_->WriteText(NonNullString(text));
}
String SystemClipboard::ReadHTML(KURL& url,
unsigned& fragment_start,
unsigned& fragment_end) {
String html;
- if (IsValidBufferType(buffer_)) {
+ if (IsValidBufferType(buffer_) && clipboard_.is_bound()) {
clipboard_->ReadHtml(buffer_, &html, &url,
static_cast<uint32_t*>(&fragment_start),
static_cast<uint32_t*>(&fragment_end));
@@ -142,6 +146,8 @@ String SystemClipboard::ReadHTML(KURL& url,
void SystemClipboard::WriteHTML(const String& markup,
const KURL& document_url,
SmartReplaceOption smart_replace_option) {
+ if (!clipboard_.is_bound())
+ return;
clipboard_->WriteHtml(NonNullString(markup), document_url);
if (smart_replace_option == kCanSmartReplace)
clipboard_->WriteSmartPasteMarker();
@@ -157,7 +163,8 @@ void SystemClipboard::ReadSvg(
}
void SystemClipboard::WriteSvg(const String& markup) {
- clipboard_->WriteSvg(NonNullString(markup));
+ if (clipboard_.is_bound())
+ clipboard_->WriteSvg(NonNullString(markup));
}
String SystemClipboard::ReadRTF() {
@@ -168,6 +175,15 @@ String SystemClipboard::ReadRTF() {
return rtf;
}
+mojo_base::BigBuffer SystemClipboard::ReadPng(
+ mojom::blink::ClipboardBuffer buffer) {
+ if (!IsValidBufferType(buffer) || !clipboard_.is_bound())
+ return mojo_base::BigBuffer();
+ mojo_base::BigBuffer png;
+ clipboard_->ReadPng(buffer, &png);
+ return png;
+}
+
SkBitmap SystemClipboard::ReadImage(mojom::ClipboardBuffer buffer) {
if (!IsValidBufferType(buffer) || !clipboard_.is_bound())
return SkBitmap();
@@ -178,8 +194,14 @@ SkBitmap SystemClipboard::ReadImage(mojom::ClipboardBuffer buffer) {
String SystemClipboard::ReadImageAsImageMarkup(
mojom::blink::ClipboardBuffer buffer) {
- SkBitmap bitmap = ReadImage(buffer);
- return BitmapToImageMarkup(bitmap);
+ // TODO(crbug.com/1223849): Remove check once `ReadImage()` is removed.
+ if (RuntimeEnabledFeatures::ClipboardReadPngEnabled()) {
+ mojo_base::BigBuffer png_data = ReadPng(buffer);
+ return PNGToImageMarkup(png_data);
+ } else {
+ SkBitmap bitmap = ReadImage(buffer);
+ return BitmapToImageMarkup(bitmap);
+ }
}
void SystemClipboard::WriteImageWithTag(Image* image,
@@ -191,6 +213,8 @@ void SystemClipboard::WriteImageWithTag(Image* image,
SkBitmap bitmap;
if (sk_sp<SkImage> sk_image = paint_image.GetSwSkImage())
sk_image->asLegacyBitmap(&bitmap);
+ if (!clipboard_.is_bound())
+ return;
// The bitmap backing a canvas can be in non-native skia pixel order (aka
// RGBA when kN32_SkColorType is BGRA-ordered, or higher bit-depth color-types
// like F16. The IPC to the browser requires the bitmap to be in N32 format
@@ -219,7 +243,8 @@ void SystemClipboard::WriteImageWithTag(Image* image,
}
void SystemClipboard::WriteImage(const SkBitmap& bitmap) {
- clipboard_->WriteImage(bitmap);
+ if (clipboard_.is_bound())
+ clipboard_->WriteImage(bitmap);
}
mojom::blink::ClipboardFilesPtr SystemClipboard::ReadFiles() {
@@ -240,6 +265,8 @@ String SystemClipboard::ReadCustomData(const String& type) {
void SystemClipboard::WriteDataObject(DataObject* data_object) {
DCHECK(data_object);
+ if (!clipboard_.is_bound())
+ return;
// This plagiarizes the logic in DropDataBuilder::Build, but only extracts the
// data needed for the implementation of WriteDataObject.
//
@@ -250,7 +277,6 @@ void SystemClipboard::WriteDataObject(DataObject* data_object) {
// TODO(slangley): Use a mojo struct to send web_drag_data and allow receiving
// side to extract the data required.
// TODO(dcheng): Properly support text/uri-list here.
-
HashMap<String, String> custom_data;
WebDragData data = data_object->ToWebDragData();
for (const WebDragData::Item& item : data.Items()) {
@@ -270,12 +296,14 @@ void SystemClipboard::WriteDataObject(DataObject* data_object) {
}
void SystemClipboard::CommitWrite() {
- clipboard_->CommitWrite();
+ if (clipboard_.is_bound())
+ clipboard_->CommitWrite();
}
void SystemClipboard::CopyToFindPboard(const String& text) {
#if defined(OS_MAC)
- clipboard_->WriteStringToFindPboard(text);
+ if (clipboard_.is_bound())
+ clipboard_->WriteStringToFindPboard(text);
#endif
}
@@ -283,55 +311,88 @@ void SystemClipboard::RecordClipboardImageUrls(
DocumentFragment* pasting_fragment) {
if (!pasting_fragment)
return;
+ image_urls_in_paste_.clear();
bool rtf_format_available =
IsFormatAvailable(blink::mojom::ClipboardFormat::kRtf);
for (Element& element : ElementTraversal::DescendantsOf(*pasting_fragment)) {
if (!IsA<HTMLImageElement>(&element))
continue;
- AttributeCollection attributes = element.Attributes();
- for (const auto& attribute : attributes) {
- if (element.IsURLAttribute(attribute) && !attribute.Value().IsEmpty()) {
- static constexpr char kFilePrefix[] = "file:";
- static constexpr char kCidPrefix[] = "cid:";
- static constexpr char kHttpPrefix[] = "http:";
- static constexpr char kHttpsPrefix[] = "https:";
- static constexpr char kDataPrefix[] = "data:";
- static constexpr char kBase64[] = "base64,";
- const AtomicString& filename = attribute.Value();
- ClipboardPastedImageUrls image_src_url_prefix =
- ClipboardPastedImageUrls::kUnknown;
- if (filename.StartsWithIgnoringCase(kFilePrefix)) {
- // Record local file urls.
- image_src_url_prefix = ClipboardPastedImageUrls::kLocalFileUrls;
- } else if (filename.StartsWithIgnoringCase(kCidPrefix)) {
- // Record cid prefix.
- image_src_url_prefix = ClipboardPastedImageUrls::kCidUrls;
- } else if (filename.StartsWithIgnoringCase(kHttpPrefix) ||
- filename.StartsWithIgnoringCase(kHttpsPrefix)) {
- // Record http prefix.
- image_src_url_prefix = ClipboardPastedImageUrls::kHttpUrls;
- } else if (filename.StartsWithIgnoringCase(kDataPrefix) &&
- filename.Contains(kBase64)) {
- // Record base64 encoded image.
- image_src_url_prefix = ClipboardPastedImageUrls::kBase64EncodedImage;
- } else {
- image_src_url_prefix = ClipboardPastedImageUrls::kOtherUrls;
- }
- base::UmaHistogramEnumeration("Blink.Clipboard.Paste.Image",
- image_src_url_prefix);
- // Check if RTF is present in the clipboard.
- if (image_src_url_prefix == ClipboardPastedImageUrls::kLocalFileUrls &&
- rtf_format_available) {
- image_src_url_prefix = ClipboardPastedImageUrls::kLocalFileUrlWithRtf;
- base::UmaHistogramEnumeration("Blink.Clipboard.Paste.Image",
- image_src_url_prefix);
- }
- }
+ auto* html_image_element = DynamicTo<HTMLImageElement>(&element);
+ const AtomicString& image_src_url = html_image_element->ImageSourceURL();
+ if (image_src_url.IsEmpty())
+ continue;
+ // Save the image url so we can record it when the image loading fails.
+ image_urls_in_paste_.insert(image_src_url.GetString());
+ static constexpr char kFilePrefix[] = "file:";
+ static constexpr char kCidPrefix[] = "cid:";
+ static constexpr char kHttpPrefix[] = "http:";
+ static constexpr char kHttpsPrefix[] = "https:";
+ static constexpr char kDataPrefix[] = "data:";
+ static constexpr char kBase64[] = "base64,";
+ ClipboardPastedImageUrls image_src_url_prefix =
+ ClipboardPastedImageUrls::kUnknown;
+ if (image_src_url.StartsWithIgnoringCase(kFilePrefix)) {
+ // Record local file urls.
+ image_src_url_prefix = ClipboardPastedImageUrls::kLocalFileUrls;
+ } else if (image_src_url.StartsWithIgnoringCase(kCidPrefix)) {
+ // Record cid prefix.
+ image_src_url_prefix = ClipboardPastedImageUrls::kCidUrls;
+ } else if (image_src_url.StartsWithIgnoringCase(kHttpPrefix) ||
+ image_src_url.StartsWithIgnoringCase(kHttpsPrefix)) {
+ // Record http prefix.
+ image_src_url_prefix = ClipboardPastedImageUrls::kHttpUrls;
+ } else if (image_src_url.StartsWithIgnoringCase(kDataPrefix) &&
+ image_src_url.Contains(kBase64)) {
+ // Record base64 encoded image.
+ image_src_url_prefix = ClipboardPastedImageUrls::kBase64EncodedImage;
+ } else {
+ image_src_url_prefix = ClipboardPastedImageUrls::kOtherUrls;
+ }
+ base::UmaHistogramEnumeration("Blink.Clipboard.Paste.Image",
+ image_src_url_prefix);
+ // Check if RTF is present in the clipboard.
+ if (image_src_url_prefix == ClipboardPastedImageUrls::kLocalFileUrls &&
+ rtf_format_available) {
+ image_src_url_prefix = ClipboardPastedImageUrls::kLocalFileUrlWithRtf;
+ base::UmaHistogramEnumeration("Blink.Clipboard.Paste.Image",
+ image_src_url_prefix);
}
}
}
+void SystemClipboard::RecordImageLoadError(const String& image_url) {
+ if (image_urls_in_paste_.IsEmpty())
+ return;
+ if (base::Contains(image_urls_in_paste_, image_url)) {
+ base::UmaHistogramEnumeration("Blink.Clipboard.Paste.Image",
+ ClipboardPastedImageUrls::kImageLoadError);
+ }
+}
+
+void SystemClipboard::ReadAvailableCustomAndStandardFormats(
+ mojom::blink::ClipboardHost::ReadAvailableCustomAndStandardFormatsCallback
+ callback) {
+ clipboard_->ReadAvailableCustomAndStandardFormats(std::move(callback));
+}
+
+void SystemClipboard::ReadUnsanitizedCustomFormat(
+ const String& type,
+ mojom::blink::ClipboardHost::ReadUnsanitizedCustomFormatCallback callback) {
+ // The format size restriction is added in `ClipboardWriter::IsValidType`.
+ DCHECK_LT(type.length(), mojom::blink::ClipboardHost::kMaxFormatSize);
+ clipboard_->ReadUnsanitizedCustomFormat(type, std::move(callback));
+}
+
+void SystemClipboard::WriteUnsanitizedCustomFormat(const String& type,
+ mojo_base::BigBuffer data) {
+ if (data.size() >= mojom::blink::ClipboardHost::kMaxDataSize)
+ return;
+ // The format size restriction is added in `ClipboardWriter::IsValidType`.
+ DCHECK_LT(type.length(), mojom::blink::ClipboardHost::kMaxFormatSize);
+ clipboard_->WriteUnsanitizedCustomFormat(type, std::move(data));
+}
+
void SystemClipboard::Trace(Visitor* visitor) const {
visitor->Trace(clipboard_);
}
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 54d6d533666..b381f12a10f 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -36,7 +36,7 @@ class CORE_EXPORT SystemClipboard final
SystemClipboard(const SystemClipboard&) = delete;
SystemClipboard& operator=(const SystemClipboard&) = delete;
- uint64_t SequenceNumber();
+ ClipboardSequenceNumberToken SequenceNumber();
bool IsSelectionMode() const;
void SetSelectionMode(bool);
Vector<String> ReadAvailableTypes();
@@ -62,6 +62,7 @@ class CORE_EXPORT SystemClipboard final
String ReadRTF();
+ mojo_base::BigBuffer ReadPng(mojom::blink::ClipboardBuffer);
SkBitmap ReadImage(mojom::ClipboardBuffer);
String ReadImageAsImageMarkup(mojom::blink::ClipboardBuffer);
@@ -83,6 +84,18 @@ class CORE_EXPORT SystemClipboard final
void CopyToFindPboard(const String& text);
void RecordClipboardImageUrls(DocumentFragment* pasting_fragment);
+ void RecordImageLoadError(const String& image_url);
+
+ void ReadAvailableCustomAndStandardFormats(
+ mojom::blink::ClipboardHost::ReadAvailableCustomAndStandardFormatsCallback
+ callback);
+ void ReadUnsanitizedCustomFormat(
+ const String& type,
+ mojom::blink::ClipboardHost::ReadUnsanitizedCustomFormatCallback
+ callback);
+
+ void WriteUnsanitizedCustomFormat(const String& type,
+ mojo_base::BigBuffer data);
void Trace(Visitor*) const;
@@ -97,7 +110,8 @@ class CORE_EXPORT SystemClipboard final
// Whether the selection buffer is available on the underlying platform.
bool is_selection_buffer_available_ = false;
-
+ // Cache of image elements inserted by paste.
+ WTF::HashSet<String> image_urls_in_paste_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/content_capture/OWNERS b/chromium/third_party/blink/renderer/core/content_capture/OWNERS
index bc2e55fe2bc..ef41f5bb0c5 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/OWNERS
+++ b/chromium/third_party/blink/renderer/core/content_capture/OWNERS
@@ -1,4 +1,3 @@
pdr@chromium.org
michaelbai@chromium.org
-skyostil@chromium.org
wangxianzhu@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.h b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.h
index 161e434e202..2a9101b78da 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.h
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.h
@@ -9,6 +9,7 @@
#include "base/time/time.h"
#include "cc/paint/node_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h"
#include "third_party/blink/renderer/core/content_capture/task_session.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
index b533148b1df..7d2d23166c7 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
@@ -94,7 +94,7 @@ void ContentCaptureTaskHistogramReporter::OnAllCapturedContentSent() {
}
void ContentCaptureTaskHistogramReporter::RecordsSentContentCountPerDocument(
- size_t sent_content_count) {
+ int sent_content_count) {
base::UmaHistogramCounts10000(kSentContentCount, sent_content_count);
}
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h
index 3372116c6fc..d8c74da536a 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h
@@ -45,7 +45,7 @@ class CORE_EXPORT ContentCaptureTaskHistogramReporter
// Invoked on a capturing session ends, at that time, all captured changes
// which include the new, changed and removed content has been sent.
void OnAllCapturedContentSent();
- void RecordsSentContentCountPerDocument(size_t sent_content_count);
+ void RecordsSentContentCountPerDocument(int sent_content_count);
private:
void MayRecordTaskRunsPerCapture();
@@ -65,7 +65,7 @@ class CORE_EXPORT ContentCaptureTaskHistogramReporter
base::TimeTicks task_scheduled_time_;
// Counts the task run times to complete a capture which includes capturing
// and sending the content.
- size_t task_runs_per_capture_ = 0;
+ int task_runs_per_capture_ = 0;
// Records time to capture the content, its range is from 0 to 50,000
// microseconds.
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc b/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc
index 980debec4b5..518284b069c 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc
@@ -68,10 +68,9 @@ void ToNodeIds(const Vector<Persistent<Node>>& nodes,
}
}
-void ToNodeTexts(const Vector<Persistent<Node>>& nodes,
- Vector<std::string>& texts) {
+void ToNodeTexts(const Vector<Persistent<Node>>& nodes, Vector<String>& texts) {
for (auto& n : nodes)
- texts.push_back(n->nodeValue().Utf8());
+ texts.push_back(n->nodeValue());
}
} // namespace
@@ -89,7 +88,7 @@ class WebContentCaptureClientTestHelper : public WebContentCaptureClient {
data_ = data;
first_data_ = first_data;
for (auto& d : data) {
- auto text = d.GetValue().Utf8();
+ auto text = d.GetValue();
all_text_.push_back(text);
captured_text_.push_back(text);
}
@@ -98,7 +97,7 @@ class WebContentCaptureClientTestHelper : public WebContentCaptureClient {
void DidUpdateContent(const WebVector<WebContentHolder>& data) override {
updated_data_ = data;
for (auto& d : data)
- updated_text_.push_back(d.GetValue().Utf8());
+ updated_text_.push_back(d.GetValue());
}
void DidRemoveContent(WebVector<int64_t> data) override {
@@ -113,11 +112,11 @@ class WebContentCaptureClientTestHelper : public WebContentCaptureClient {
return updated_data_;
}
- const Vector<std::string>& AllText() const { return all_text_; }
+ const Vector<String>& AllText() const { return all_text_; }
- const Vector<std::string>& CapturedText() const { return captured_text_; }
+ const Vector<String>& CapturedText() const { return captured_text_; }
- const Vector<std::string>& UpdatedText() const { return updated_text_; }
+ const Vector<String>& UpdatedText() const { return updated_text_; }
const WebVector<int64_t>& RemovedData() const { return removed_data_; }
@@ -134,9 +133,9 @@ class WebContentCaptureClientTestHelper : public WebContentCaptureClient {
WebVector<WebContentHolder> data_;
WebVector<WebContentHolder> updated_data_;
WebVector<int64_t> removed_data_;
- Vector<std::string> all_text_;
- Vector<std::string> updated_text_;
- Vector<std::string> captured_text_;
+ Vector<String> all_text_;
+ Vector<String> updated_text_;
+ Vector<String> captured_text_;
};
class ContentCaptureTaskTestHelper : public ContentCaptureTask {
@@ -247,7 +246,7 @@ class ContentCaptureTest
InitScrollingTestData();
}
- void SimulateScrolling(size_t step) {
+ void SimulateScrolling(wtf_size_t step) {
CHECK_LT(step, 4u);
content_capture_manager_->GetContentCaptureTask()
->SetCapturedContentForTesting(scrolling_node_ids_[step]);
@@ -329,7 +328,7 @@ class ContentCaptureTest
Node& invisible_node() const { return *invisible_node_; }
- const Vector<Vector<std::string>>& scrolling_expected_captured_nodes() {
+ const Vector<Vector<String>>& scrolling_expected_captured_nodes() {
return scrolling_expected_captured_nodes_;
}
@@ -342,11 +341,11 @@ class ContentCaptureTest
GetWebContentCaptureClient()->ResetResults();
}
- void BuildNodesInfo(const Vector<std::string>& ids,
+ void BuildNodesInfo(const Vector<String>& ids,
Vector<Persistent<Node>>& nodes,
Vector<cc::NodeInfo>& node_ids) {
for (auto id : ids) {
- Node* node = GetElementById(id.c_str())->firstChild();
+ Node* node = GetDocument().getElementById(AtomicString(id))->firstChild();
CHECK(node);
LayoutObject* layout_object = node->GetLayoutObject();
CHECK(layout_object);
@@ -361,21 +360,21 @@ class ContentCaptureTest
// TODO(michaelbai): Remove this once integrate with LayoutText.
void InitNodeHolders() {
BuildNodesInfo(
- Vector<std::string>{"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"},
- nodes_, node_ids_);
+ Vector<String>{"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"}, nodes_,
+ node_ids_);
invisible_node_ = GetElementById("invisible")->firstChild();
DCHECK(invisible_node_.Get());
}
void InitScrollingTestData() {
Vector<Vector<Persistent<Node>>> nodes{4};
- BuildNodesInfo(Vector<std::string>{"p1", "p2", "p3"}, nodes[0],
+ BuildNodesInfo(Vector<String>{"p1", "p2", "p3"}, nodes[0],
scrolling_node_ids_[0]);
- BuildNodesInfo(Vector<std::string>{"p3", "p4", "p5"}, nodes[1],
+ BuildNodesInfo(Vector<String>{"p3", "p4", "p5"}, nodes[1],
scrolling_node_ids_[1]);
- BuildNodesInfo(Vector<std::string>{"p6", "p7", "p8"}, nodes[2],
+ BuildNodesInfo(Vector<String>{"p6", "p7", "p8"}, nodes[2],
scrolling_node_ids_[2]);
- BuildNodesInfo(Vector<std::string>{"p2", "p3"}, nodes[3],
+ BuildNodesInfo(Vector<String>{"p2", "p3"}, nodes[3],
scrolling_node_ids_[3]);
// Build expected result.
if (base::FeatureList::IsEnabled(
@@ -406,7 +405,7 @@ class ContentCaptureTest
Vector<Persistent<Node>> nodes_;
Vector<cc::NodeInfo> node_ids_;
Persistent<Node> invisible_node_;
- Vector<Vector<std::string>> scrolling_expected_captured_nodes_{4};
+ Vector<Vector<String>> scrolling_expected_captured_nodes_{4};
Vector<Vector<int64_t>> scrolling_expected_removed_nodes_{4};
Vector<Vector<cc::NodeInfo>> scrolling_node_ids_{4};
std::unique_ptr<WebContentCaptureClientTestHelper> content_capture_client_;
@@ -433,7 +432,7 @@ TEST_P(ContentCaptureTest, Basic) {
}
TEST_P(ContentCaptureTest, Scrolling) {
- for (size_t step = 0; step < 4; ++step) {
+ for (wtf_size_t step = 0; step < 4; ++step) {
SimulateScrolling(step);
RunContentCaptureTask();
EXPECT_EQ(ContentCaptureTask::TaskState::kStop,
@@ -818,8 +817,7 @@ class ContentCaptureSimTest : public SimTest {
child_frame_expected_text_.push_back("New Text");
}
- void InsertMainFrameEditableContent(const std::string& content,
- unsigned offset) {
+ void InsertMainFrameEditableContent(const String& content, unsigned offset) {
InsertNodeContent(GetDocument(), "editable_id", content, offset);
}
@@ -827,16 +825,16 @@ class ContentCaptureSimTest : public SimTest {
DeleteNodeContent(GetDocument(), "editable_id", offset, length);
}
- const Vector<std::string>& MainFrameExpectedText() const {
+ const Vector<String>& MainFrameExpectedText() const {
return main_frame_expected_text_;
}
- const Vector<std::string>& ChildFrameExpectedText() const {
+ const Vector<String>& ChildFrameExpectedText() const {
return child_frame_expected_text_;
}
- void ReplaceMainFrameExpectedText(const std::string& old_text,
- const std::string& new_text) {
+ void ReplaceMainFrameExpectedText(const String& old_text,
+ const String& new_text) {
std::replace(main_frame_expected_text_.begin(),
main_frame_expected_text_.end(), old_text, new_text);
}
@@ -913,8 +911,8 @@ class ContentCaptureSimTest : public SimTest {
}
void InitMainFrameNodeHolders() {
- Vector<std::string> ids = {"p1", "p2", "p3", "p4", "p5",
- "p6", "p7", "s8", "editable_id"};
+ Vector<String> ids = {"p1", "p2", "p3", "p4", "p5",
+ "p6", "p7", "s8", "editable_id"};
main_frame_expected_text_ = {
"Hello World1", "Hello World2", "Hello World3",
"Hello World4", "Hello World5", "Hello World6",
@@ -924,18 +922,19 @@ class ContentCaptureSimTest : public SimTest {
}
void InitChildFrameNodeHolders(const Document& doc) {
- Vector<std::string> ids = {"c1", "c2"};
+ Vector<String> ids = {"c1", "c2"};
child_frame_expected_text_ = {"Hello World11", "Hello World12"};
InitNodeHolders(child_frame_content_, ids, doc);
EXPECT_EQ(2u, child_frame_content_.size());
}
void InitNodeHolders(Vector<cc::NodeInfo>& buffer,
- const Vector<std::string>& ids,
+ const Vector<String>& ids,
const Document& document) {
for (auto id : ids) {
- auto* layout_object =
- document.getElementById(id.c_str())->firstChild()->GetLayoutObject();
+ auto* layout_object = document.getElementById(AtomicString(id))
+ ->firstChild()
+ ->GetLayoutObject();
auto* layout_text = To<LayoutText>(layout_object);
EXPECT_TRUE(layout_text->HasNodeId());
buffer.push_back(
@@ -957,20 +956,19 @@ class ContentCaptureSimTest : public SimTest {
}
void InsertNodeContent(Document& doc,
- const std::string& id,
- const std::string& content,
+ const String& id,
+ const String& content,
unsigned offset) {
- To<Text>(doc.getElementById(id.c_str())->firstChild())
- ->insertData(offset, String(content.c_str()),
- IGNORE_EXCEPTION_FOR_TESTING);
+ To<Text>(doc.getElementById(AtomicString(id))->firstChild())
+ ->insertData(offset, content, IGNORE_EXCEPTION_FOR_TESTING);
Compositor().BeginFrame();
}
void DeleteNodeContent(Document& doc,
- const std::string& id,
+ const String& id,
unsigned offset,
unsigned length) {
- To<Text>(doc.getElementById(id.c_str())->firstChild())
+ To<Text>(doc.getElementById(AtomicString(id))->firstChild())
->deleteData(offset, length, IGNORE_EXCEPTION_FOR_TESTING);
Compositor().BeginFrame();
}
@@ -984,8 +982,8 @@ class ContentCaptureSimTest : public SimTest {
->SetCapturedContentForTesting(captured_content);
}
- Vector<std::string> main_frame_expected_text_;
- Vector<std::string> child_frame_expected_text_;
+ Vector<String> main_frame_expected_text_;
+ Vector<String> child_frame_expected_text_;
Vector<cc::NodeInfo> main_frame_content_;
Vector<cc::NodeInfo> child_frame_content_;
WebContentCaptureClientTestHelper client_;
@@ -1056,8 +1054,8 @@ TEST_F(ContentCaptureSimTest, ChangeNode) {
EXPECT_TRUE(ChildClient().Data().empty());
EXPECT_THAT(Client().AllText(),
testing::UnorderedElementsAreArray(MainFrameExpectedText()));
- Vector<std::string> expected_text_update;
- std::string insert_text = "content ";
+ Vector<String> expected_text_update;
+ String insert_text = "content ";
// Changed content to 'content editable'.
InsertMainFrameEditableContent(insert_text, 0);
@@ -1071,13 +1069,13 @@ TEST_F(ContentCaptureSimTest, ChangeNode) {
testing::UnorderedElementsAreArray(expected_text_update));
// Changing content multiple times before capturing.
- std::string insert_text1 = "i";
+ String insert_text1 = "i";
// Changed content to 'content ieditable'.
- InsertMainFrameEditableContent(insert_text1, insert_text.size());
- std::string insert_text2 = "s ";
+ InsertMainFrameEditableContent(insert_text1, insert_text.length());
+ String insert_text2 = "s ";
// Changed content to 'content is editable'.
InsertMainFrameEditableContent(insert_text2,
- insert_text.size() + insert_text1.size());
+ insert_text.length() + insert_text1.length());
SetCapturedContent(ContentType::kMainFrame);
RunContentCaptureTaskUntil(ContentCaptureTask::TaskState::kStop);
@@ -1092,16 +1090,16 @@ TEST_F(ContentCaptureSimTest, ChangeNode) {
TEST_F(ContentCaptureSimTest, ChangeNodeBeforeCapture) {
// Changed content to 'content editable' before capture.
- std::string insert_text = "content ";
+ String insert_text = "content ";
InsertMainFrameEditableContent(insert_text, 0);
// Changing content multiple times before capturing.
- std::string insert_text1 = "i";
+ String insert_text1 = "i";
// Changed content to 'content ieditable'.
- InsertMainFrameEditableContent(insert_text1, insert_text.size());
- std::string insert_text2 = "s ";
+ InsertMainFrameEditableContent(insert_text1, insert_text.length());
+ String insert_text2 = "s ";
// Changed content to 'content is editable'.
InsertMainFrameEditableContent(insert_text2,
- insert_text.size() + insert_text1.size());
+ insert_text.length() + insert_text1.length());
// The changed content shall be captured as new content.
ReplaceMainFrameExpectedText(
@@ -1133,7 +1131,7 @@ TEST_F(ContentCaptureSimTest, DeleteNodeContent) {
EXPECT_EQ(1u, Client().UpdatedData().size());
EXPECT_FALSE(Client().FirstData());
EXPECT_TRUE(ChildClient().Data().empty());
- Vector<std::string> expected_text_update;
+ Vector<String> expected_text_update;
expected_text_update.push_back("edit");
EXPECT_THAT(Client().UpdatedText(),
testing::UnorderedElementsAreArray(expected_text_update));
diff --git a/chromium/third_party/blink/renderer/core/content_capture/task_session.h b/chromium/third_party/blink/renderer/core/content_capture/task_session.h
index 6a8cab012eb..1d610a148c9 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/task_session.h
+++ b/chromium/third_party/blink/renderer/core/content_capture/task_session.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "cc/paint/node_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/core/content_capture/content_holder.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -47,7 +48,7 @@ class TaskSession final : public GarbageCollected<TaskSession> {
class DocumentSession final : public GarbageCollected<DocumentSession> {
public:
// The callback for total_sent_nodes_ metrics.
- using SentNodeCountCallback = base::RepeatingCallback<void(size_t)>;
+ using SentNodeCountCallback = base::RepeatingCallback<void(int)>;
DocumentSession(const Document& document,
SentNodeCountCallback& call_back);
@@ -110,7 +111,7 @@ class TaskSession final : public GarbageCollected<TaskSession> {
bool first_data_has_sent_ = false;
// This is for the metrics to record the total node that has been sent.
- size_t total_sent_nodes_ = 0;
+ int total_sent_nodes_ = 0;
// Histogram could be disabed in low time resolution OS, see
// base::TimeTicks::IsHighResolution and ContentCaptureTask.
absl::optional<SentNodeCountCallback> callback_;
diff --git a/chromium/third_party/blink/renderer/core/core_idl_files.gni b/chromium/third_party/blink/renderer/core/core_idl_files.gni
deleted file mode 100644
index de8e63bc7e6..00000000000
--- a/chromium/third_party/blink/renderer/core/core_idl_files.gni
+++ /dev/null
@@ -1,880 +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/bindings/bindings.gni")
-import("//third_party/blink/renderer/core/core.gni")
-
-# The paths in this file are absolute since this file is imported and the
-# file lists must be valid from multple "current directories".
-
-bindings_core_output_dir = "$bindings_output_dir/core"
-
-# Global constructors
-core_global_constructors_original_interfaces = [
- "DedicatedWorkerGlobalScope",
- "LayoutWorkletGlobalScope",
- "SharedWorkerGlobalScope",
- "Window",
-]
-
-# The size and the order in the following list must match to the previous one.
-if (use_blink_v8_binding_new_idl_interface) {
- core_global_constructors_original_interface_basenames = []
-} else {
- core_global_constructors_original_interface_basenames = [
- "dedicated_worker_global_scope",
- "layout_worklet_global_scope",
- "shared_worker_global_scope",
- "window",
- ]
-}
-
-# The interfaces aren't technically files, but we can treat them as file names
-# to get process_file_template to generate lists of IDL files corresponding
-# to each interface.
-core_global_constructors_generated_idl_files =
- process_file_template(
- core_global_constructors_original_interface_basenames,
- [ "$blink_core_output_dir/{{source_name_part}}_core_constructors.idl" ])
-
-# IDL interfaces that do not have any dependency to modules/ (partial
-# interfaces, mixins, partial mixins).
-core_interface_idl_files_core_only =
- get_path_info([
- "animation/animation.idl",
- "animation/animation_effect.idl",
- "animation/animation_timeline.idl",
- "animation/css/css_animation.idl",
- "animation/css/css_transition.idl",
- "animation/document_timeline.idl",
- "animation/keyframe_effect.idl",
- "animation/scroll_timeline.idl",
- "aom/accessible_node.idl",
- "aom/accessible_node_list.idl",
- "aom/computed_accessible_node.idl",
- "app_history/app_history.idl",
- "app_history/app_history_entry.idl",
- "app_history/app_history_navigate_event.idl",
- "clipboard/data_transfer.idl",
- "clipboard/data_transfer_item_list.idl",
- "css/css_condition_rule.idl",
- "css/css_container_rule.idl",
- "css/css_counter_style_rule.idl",
- "css/css_font_face_rule.idl",
- "css/css_grouping_rule.idl",
- "css/css_import_rule.idl",
- "css/css_keyframe_rule.idl",
- "css/css_keyframes_rule.idl",
- "css/css_media_rule.idl",
- "css/css_namespace_rule.idl",
- "css/css_page_rule.idl",
- "css/css_property_rule.idl",
- "css/css_rule.idl",
- "css/css_rule_list.idl",
- "css/css_scroll_timeline_rule.idl",
- "css/css_style_declaration.idl",
- "css/css_style_rule.idl",
- "css/css_style_sheet.idl",
- "css/css_supports_rule.idl",
- "css/cssom/css_color_value.idl",
- "css/cssom/css_hsl.idl",
- "css/cssom/css_image_value.idl",
- "css/cssom/css_keyword_value.idl",
- "css/cssom/css_math_invert.idl",
- "css/cssom/css_math_max.idl",
- "css/cssom/css_math_min.idl",
- "css/cssom/css_math_negate.idl",
- "css/cssom/css_math_product.idl",
- "css/cssom/css_math_sum.idl",
- "css/cssom/css_math_value.idl",
- "css/cssom/css_matrix_component.idl",
- "css/cssom/css_numeric_array.idl",
- "css/cssom/css_numeric_value.idl",
- "css/cssom/css_perspective.idl",
- "css/cssom/css_position_value.idl",
- "css/cssom/css_rgb.idl",
- "css/cssom/css_rotate.idl",
- "css/cssom/css_scale.idl",
- "css/cssom/css_skew.idl",
- "css/cssom/css_skew_x.idl",
- "css/cssom/css_skew_y.idl",
- "css/cssom/css_style_value.idl",
- "css/cssom/css_transform_component.idl",
- "css/cssom/css_transform_value.idl",
- "css/cssom/css_translate.idl",
- "css/cssom/css_unit_value.idl",
- "css/cssom/css_unparsed_value.idl",
- "css/cssom/css_variable_reference_value.idl",
- "css/cssom/style_property_map.idl",
- "css/cssom/style_property_map_read_only.idl",
- "css/font_face.idl",
- "css/font_face_set.idl",
- "css/font_face_set_load_event.idl",
- "css/media_list.idl",
- "css/media_query_list.idl",
- "css/media_query_list_event.idl",
- "css/style_media.idl",
- "css/style_sheet.idl",
- "css/style_sheet_list.idl",
- "document_transition/document_transition.idl",
- "dom/abort_controller.idl",
- "dom/abort_signal.idl",
- "dom/abstract_range.idl",
- "dom/attr.idl",
- "dom/cdata_section.idl",
- "dom/character_data.idl",
- "dom/comment.idl",
- "dom/document_fragment.idl",
- "dom/document_type.idl",
- "dom/dom_exception.idl",
- "dom/dom_implementation.idl",
- "dom/dom_string_list.idl",
- "dom/dom_string_map.idl",
- "dom/dom_token_list.idl",
- "dom/element.idl",
- "dom/events/custom_event.idl",
- "dom/events/event.idl",
- "dom/events/event_target.idl",
- "dom/idle_deadline.idl",
- "dom/iterator.idl",
- "dom/mutation_observer.idl",
- "dom/mutation_record.idl",
- "dom/named_node_map.idl",
- "dom/node.idl",
- "dom/node_iterator.idl",
- "dom/node_list.idl",
- "dom/processing_instruction.idl",
- "dom/range.idl",
- "dom/static_range.idl",
- "dom/text.idl",
- "dom/tree_walker.idl",
- "dom/xml_document.idl",
- "editing/ime/edit_context.idl",
- "editing/ime/text_format_update_event.idl",
- "editing/ime/text_update_event.idl",
- "editing/selection.idl",
- "events/animation_event.idl",
- "events/animation_playback_event.idl",
- "events/application_cache_error_event.idl",
- "events/before_create_policy_event.idl",
- "events/before_unload_event.idl",
- "events/clipboard_event.idl",
- "events/composition_event.idl",
- "events/drag_event.idl",
- "events/error_event.idl",
- "events/focus_event.idl",
- "events/hash_change_event.idl",
- "events/input_event.idl",
- "events/keyboard_event.idl",
- "events/message_event.idl",
- "events/mouse_event.idl",
- "events/mutation_event.idl",
- "events/overscroll_event.idl",
- "events/page_transition_event.idl",
- "events/pointer_event.idl",
- "events/pop_state_event.idl",
- "events/progress_event.idl",
- "events/promise_rejection_event.idl",
- "events/resource_progress_event.idl",
- "events/security_policy_violation_event.idl",
- "events/text_event.idl",
- "events/touch_event.idl",
- "events/transition_event.idl",
- "events/ui_event.idl",
- "events/wheel_event.idl",
- "permissions_policy/feature_policy.idl",
- "fetch/headers.idl",
- "fetch/request.idl",
- "fetch/response.idl",
- "fileapi/blob.idl",
- "fileapi/file.idl",
- "fileapi/file_list.idl",
- "fileapi/file_reader.idl",
- "fileapi/file_reader_sync.idl",
- "frame/bar_prop.idl",
- "frame/coop_access_violation_report_body.idl",
- "frame/csp/csp_violation_report_body.idl",
- "frame/deprecation_report_body.idl",
- "frame/document_policy_violation_report_body.idl",
- "frame/external.idl",
- "frame/fragment_directive.idl",
- "frame/history.idl",
- "frame/intervention_report_body.idl",
- "frame/location.idl",
- "frame/navigator_ua_data.idl",
- "frame/permissions_policy_violation_report_body.idl",
- "frame/report.idl",
- "frame/report_body.idl",
- "frame/reporting_observer.idl",
- "frame/scheduling.idl",
- "frame/test_report_body.idl",
- "frame/user_activation.idl",
- "frame/visual_viewport.idl",
- "frame/window_controls_overlay.idl",
- "frame/window_controls_overlay_geometry_change_event.idl",
- "geometry/dom_matrix.idl",
- "geometry/dom_matrix_read_only.idl",
- "geometry/dom_point.idl",
- "geometry/dom_point_read_only.idl",
- "geometry/dom_quad.idl",
- "geometry/dom_rect.idl",
- "geometry/dom_rect_list.idl",
- "geometry/dom_rect_read_only.idl",
- "highlight/highlight.idl",
- "highlight/highlight_registry.idl",
- "html/canvas/image_data.idl",
- "html/canvas/text_metrics.idl",
- "html/custom/custom_element_registry.idl",
- "html/custom/custom_state_set.idl",
- "html/custom/element_internals.idl",
- "html/fenced_frame/html_fenced_frame_element.idl",
- "html/forms/form_data.idl",
- "html/forms/form_data_event.idl",
- "html/forms/html_button_element.idl",
- "html/forms/html_data_list_element.idl",
- "html/forms/html_field_set_element.idl",
- "html/forms/html_form_controls_collection.idl",
- "html/forms/html_form_element.idl",
- "html/forms/html_label_element.idl",
- "html/forms/html_legend_element.idl",
- "html/forms/html_opt_group_element.idl",
- "html/forms/html_option_element.idl",
- "html/forms/html_options_collection.idl",
- "html/forms/html_output_element.idl",
- "html/forms/html_select_element.idl",
- "html/forms/html_select_menu_element.idl",
- "html/forms/html_text_area_element.idl",
- "html/forms/radio_node_list.idl",
- "html/forms/submit_event.idl",
- "html/forms/validity_state.idl",
- "html/html_all_collection.idl",
- "html/html_anchor_element.idl",
- "html/html_area_element.idl",
- "html/html_base_element.idl",
- "html/html_body_element.idl",
- "html/html_br_element.idl",
- "html/html_collection.idl",
- "html/html_data_element.idl",
- "html/html_details_element.idl",
- "html/html_dialog_element.idl",
- "html/html_directory_element.idl",
- "html/html_div_element.idl",
- "html/html_dlist_element.idl",
- "html/html_document.idl",
- "html/html_embed_element.idl",
- "html/html_font_element.idl",
- "html/html_frame_element.idl",
- "html/html_frame_set_element.idl",
- "html/html_head_element.idl",
- "html/html_heading_element.idl",
- "html/html_hr_element.idl",
- "html/html_html_element.idl",
- "html/html_image_element.idl",
- "html/html_li_element.idl",
- "html/html_link_element.idl",
- "html/html_map_element.idl",
- "html/html_marquee_element.idl",
- "html/html_menu_element.idl",
- "html/html_meta_element.idl",
- "html/html_meter_element.idl",
- "html/html_mod_element.idl",
- "html/html_object_element.idl",
- "html/html_olist_element.idl",
- "html/html_paragraph_element.idl",
- "html/html_param_element.idl",
- "html/html_picture_element.idl",
- "html/html_popup_element.idl",
- "html/html_pre_element.idl",
- "html/html_progress_element.idl",
- "html/html_quote_element.idl",
- "html/html_script_element.idl",
- "html/html_slot_element.idl",
- "html/html_source_element.idl",
- "html/html_span_element.idl",
- "html/html_style_element.idl",
- "html/html_table_caption_element.idl",
- "html/html_table_cell_element.idl",
- "html/html_table_col_element.idl",
- "html/html_table_element.idl",
- "html/html_table_row_element.idl",
- "html/html_table_section_element.idl",
- "html/html_template_element.idl",
- "html/html_time_element.idl",
- "html/html_title_element.idl",
- "html/html_ulist_element.idl",
- "html/html_unknown_element.idl",
- "html/media/html_audio_element.idl",
- "html/media/media_error.idl",
- "html/portal/html_portal_element.idl",
- "html/portal/portal_activate_event.idl",
- "html/portal/portal_host.idl",
- "html/time_ranges.idl",
- "html/track/audio_track_list.idl",
- "html/track/html_track_element.idl",
- "html/track/text_track.idl",
- "html/track/text_track_cue.idl",
- "html/track/text_track_cue_list.idl",
- "html/track/text_track_list.idl",
- "html/track/track_event.idl",
- "html/track/video_track_list.idl",
- "html/track/vtt/vtt_cue.idl",
- "html/track/vtt/vtt_region.idl",
- "imagebitmap/image_bitmap.idl",
- "input/input_device_capabilities.idl",
- "input/touch.idl",
- "input/touch_list.idl",
- "inspector/inspector_overlay_host.idl",
- "intersection_observer/intersection_observer.idl",
- "intersection_observer/intersection_observer_entry.idl",
- "layout/ng/custom/intrinsic_sizes.idl",
- "layout/ng/custom/layout_child.idl",
- "layout/ng/custom/layout_constraints.idl",
- "layout/ng/custom/layout_edges.idl",
- "layout/ng/custom/layout_fragment.idl",
- "layout/ng/custom/layout_worklet_global_scope.idl",
- "loader/appcache/application_cache.idl",
- "messaging/message_channel.idl",
- "messaging/message_port.idl",
- "mojo/mojo.idl",
- "mojo/mojo_handle.idl",
- "mojo/mojo_watcher.idl",
- "mojo/test/mojo_interface_interceptor.idl",
- "mojo/test/mojo_interface_request_event.idl",
- "page/color_page_popup_controller.idl",
- "page/page_popup_controller.idl",
- "page/scrolling/scroll_state.idl",
- "resize_observer/resize_observer.idl",
- "resize_observer/resize_observer_entry.idl",
- "resize_observer/resize_observer_size.idl",
- "streams/byte_length_queuing_strategy.idl",
- "streams/count_queuing_strategy.idl",
- "streams/readable_byte_stream_controller.idl",
- "streams/readable_stream.idl",
- "streams/readable_stream_byob_reader.idl",
- "streams/readable_stream_byob_request.idl",
- "streams/readable_stream_default_controller.idl",
- "streams/readable_stream_default_reader.idl",
- "streams/transform_stream.idl",
- "streams/transform_stream_default_controller.idl",
- "streams/underlying_sink_base.idl",
- "streams/underlying_source_base.idl",
- "streams/writable_stream.idl",
- "streams/writable_stream_default_controller.idl",
- "streams/writable_stream_default_writer.idl",
- "svg/svg_a_element.idl",
- "svg/svg_angle.idl",
- "svg/svg_animate_element.idl",
- "svg/svg_animate_motion_element.idl",
- "svg/svg_animate_transform_element.idl",
- "svg/svg_animated_angle.idl",
- "svg/svg_animated_boolean.idl",
- "svg/svg_animated_enumeration.idl",
- "svg/svg_animated_integer.idl",
- "svg/svg_animated_length.idl",
- "svg/svg_animated_length_list.idl",
- "svg/svg_animated_number.idl",
- "svg/svg_animated_number_list.idl",
- "svg/svg_animated_preserve_aspect_ratio.idl",
- "svg/svg_animated_rect.idl",
- "svg/svg_animated_string.idl",
- "svg/svg_animated_transform_list.idl",
- "svg/svg_animation_element.idl",
- "svg/svg_circle_element.idl",
- "svg/svg_clip_path_element.idl",
- "svg/svg_component_transfer_function_element.idl",
- "svg/svg_defs_element.idl",
- "svg/svg_desc_element.idl",
- "svg/svg_ellipse_element.idl",
- "svg/svg_fe_blend_element.idl",
- "svg/svg_fe_color_matrix_element.idl",
- "svg/svg_fe_component_transfer_element.idl",
- "svg/svg_fe_composite_element.idl",
- "svg/svg_fe_convolve_matrix_element.idl",
- "svg/svg_fe_diffuse_lighting_element.idl",
- "svg/svg_fe_displacement_map_element.idl",
- "svg/svg_fe_distant_light_element.idl",
- "svg/svg_fe_drop_shadow_element.idl",
- "svg/svg_fe_flood_element.idl",
- "svg/svg_fe_func_a_element.idl",
- "svg/svg_fe_func_b_element.idl",
- "svg/svg_fe_func_g_element.idl",
- "svg/svg_fe_func_r_element.idl",
- "svg/svg_fe_gaussian_blur_element.idl",
- "svg/svg_fe_image_element.idl",
- "svg/svg_fe_merge_element.idl",
- "svg/svg_fe_merge_node_element.idl",
- "svg/svg_fe_morphology_element.idl",
- "svg/svg_fe_offset_element.idl",
- "svg/svg_fe_point_light_element.idl",
- "svg/svg_fe_specular_lighting_element.idl",
- "svg/svg_fe_spot_light_element.idl",
- "svg/svg_fe_tile_element.idl",
- "svg/svg_fe_turbulence_element.idl",
- "svg/svg_filter_element.idl",
- "svg/svg_foreign_object_element.idl",
- "svg/svg_g_element.idl",
- "svg/svg_geometry_element.idl",
- "svg/svg_gradient_element.idl",
- "svg/svg_graphics_element.idl",
- "svg/svg_image_element.idl",
- "svg/svg_length.idl",
- "svg/svg_length_list.idl",
- "svg/svg_line_element.idl",
- "svg/svg_linear_gradient_element.idl",
- "svg/svg_marker_element.idl",
- "svg/svg_mask_element.idl",
- "svg/svg_matrix.idl",
- "svg/svg_metadata_element.idl",
- "svg/svg_mpath_element.idl",
- "svg/svg_number.idl",
- "svg/svg_number_list.idl",
- "svg/svg_path_element.idl",
- "svg/svg_pattern_element.idl",
- "svg/svg_point.idl",
- "svg/svg_point_list.idl",
- "svg/svg_polygon_element.idl",
- "svg/svg_polyline_element.idl",
- "svg/svg_preserve_aspect_ratio.idl",
- "svg/svg_radial_gradient_element.idl",
- "svg/svg_rect.idl",
- "svg/svg_rect_element.idl",
- "svg/svg_script_element.idl",
- "svg/svg_set_element.idl",
- "svg/svg_stop_element.idl",
- "svg/svg_string_list.idl",
- "svg/svg_style_element.idl",
- "svg/svg_svg_element.idl",
- "svg/svg_switch_element.idl",
- "svg/svg_symbol_element.idl",
- "svg/svg_text_content_element.idl",
- "svg/svg_text_element.idl",
- "svg/svg_text_path_element.idl",
- "svg/svg_text_positioning_element.idl",
- "svg/svg_title_element.idl",
- "svg/svg_transform.idl",
- "svg/svg_transform_list.idl",
- "svg/svg_tspan_element.idl",
- "svg/svg_unit_types.idl",
- "svg/svg_use_element.idl",
- "svg/svg_view_element.idl",
- "timing/event_counts.idl",
- "timing/largest_contentful_paint.idl",
- "timing/layout_shift.idl",
- "timing/layout_shift_attribution.idl",
- "timing/memory_info.idl",
- "timing/performance.idl",
- "timing/performance_element_timing.idl",
- "timing/performance_entry.idl",
- "timing/performance_event_timing.idl",
- "timing/performance_long_task_timing.idl",
- "timing/performance_mark.idl",
- "timing/performance_measure.idl",
- "timing/performance_navigation.idl",
- "timing/performance_navigation_timing.idl",
- "timing/performance_observer.idl",
- "timing/performance_observer_entry_list.idl",
- "timing/performance_paint_timing.idl",
- "timing/performance_resource_timing.idl",
- "timing/performance_server_timing.idl",
- "timing/performance_timing.idl",
- "timing/profiler.idl",
- "timing/task_attribution_timing.idl",
- "timing/visibility_state_entry.idl",
- "trustedtypes/trusted_html.idl",
- "trustedtypes/trusted_script.idl",
- "trustedtypes/trusted_script_url.idl",
- "trustedtypes/trusted_type_policy.idl",
- "trustedtypes/trusted_type_policy_factory.idl",
- "url/url_search_params.idl",
- "workers/shared_worker.idl",
- "workers/worker.idl",
- "workers/worker_location.idl",
- "workers/worklet.idl",
- "workers/worklet_global_scope.idl",
- "xml/dom_parser.idl",
- "xml/xml_serializer.idl",
- "xml/xpath_evaluator.idl",
- "xml/xpath_expression.idl",
- "xml/xpath_ns_resolver.idl",
- "xml/xpath_result.idl",
- "xml/xslt_processor.idl",
- "xmlhttprequest/xml_http_request.idl",
- "xmlhttprequest/xml_http_request_event_target.idl",
- "xmlhttprequest/xml_http_request_upload.idl",
- ],
- "abspath")
-
-# IDL interfaces that depend on partial definitions in modules/ (partial
-# interfaces, mixins, partial mixins).
-core_interface_idl_files_modules_dependent =
- get_path_info([
- "clipboard/data_transfer_item.idl",
- "css/css.idl",
- "dom/document.idl",
- "dom/shadow_root.idl",
- "frame/navigator.idl",
- "frame/screen.idl",
- "frame/window.idl",
- "html/canvas/html_canvas_element.idl",
- "html/forms/html_input_element.idl",
- "html/html_element.idl",
- "html/html_iframe_element.idl",
- "html/media/html_media_element.idl",
- "html/media/html_video_element.idl",
- "html/track/audio_track.idl",
- "html/track/video_track.idl",
- "inspector/dev_tools_host.idl",
- "mathml/mathml_element.idl",
- "offscreencanvas/offscreen_canvas.idl",
- "svg/svg_element.idl",
- "url/url.idl",
- "workers/dedicated_worker_global_scope.idl",
- "workers/shared_worker_global_scope.idl",
- "workers/worker_global_scope.idl",
- "workers/worker_navigator.idl",
- ],
- "abspath")
-
-# IDL partial definitions (partial interfaces, mixins, partial mixins).
-core_partial_definition_idl_files =
- get_path_info([
- "animation/animatable.idl",
- "animation/document_animation.idl",
- "app_history/window_app_history.idl",
- "css/cssom/css_unit_values.idl",
- "css/cssom/element_computed_style_map.idl",
- "css/font_face_source.idl",
- "css/property_registration.idl",
- "document_transition/document_transition_supplement.idl",
- "dom/accessibility_role.idl",
- "dom/aria_attributes.idl",
- "dom/aria_relationship_attributes.idl",
- "dom/child_node.idl",
- "dom/document_and_element_event_handlers.idl",
- "dom/document_or_shadow_root.idl",
- "dom/global_event_handlers.idl",
- "dom/non_document_type_child_node.idl",
- "dom/non_element_parent_node.idl",
- "dom/parent_node.idl",
- "events/navigator_events.idl",
- "fetch/body.idl",
- "fetch/window_fetch.idl",
- "fetch/worker_fetch.idl",
- "fileapi/url_file_api.idl",
- "frame/navigator_automation_information.idl",
- "frame/navigator_concurrent_hardware.idl",
- "frame/navigator_cookies.idl",
- "frame/navigator_device_memory.idl",
- "frame/navigator_id.idl",
- "frame/navigator_language.idl",
- "frame/navigator_on_line.idl",
- "frame/navigator_scheduling.idl",
- "frame/navigator_ua.idl",
- "frame/navigator_user_activation.idl",
- "frame/navigator_window_controls_overlay.idl",
- "frame/window_event_handlers.idl",
- "frame/window_or_worker_global_scope.idl",
- "fullscreen/document_fullscreen.idl",
- "fullscreen/element_fullscreen.idl",
- "highlight/css_highlight_registry.idl",
- "html/html_hyperlink_element_utils.idl",
- "html/html_or_foreign_element.idl",
- "html/portal/window_portal_host.idl",
- "layout/ng/custom/css_layout_worklet.idl",
- "svg/svg_document.idl",
- "svg/svg_filter_primitive_standard_attributes.idl",
- "svg/svg_fit_to_view_box.idl",
- "svg/svg_tests.idl",
- "svg/svg_uri_reference.idl",
- "svg/svg_zoom_and_pan.idl",
- "timing/window_performance.idl",
- "timing/worker_global_scope_performance.idl",
- "workers/abstract_worker.idl",
- "xml/document_xpath_evaluator.idl",
- ],
- "abspath")
-
-core_buffer_source_type_idl_files =
- get_path_info([
- "typed_arrays/array_buffer.idl",
- "typed_arrays/array_buffer_view.idl",
- "typed_arrays/big_int_64_array.idl",
- "typed_arrays/big_uint_64_array.idl",
- "typed_arrays/data_view.idl",
- "typed_arrays/float32_array.idl",
- "typed_arrays/float64_array.idl",
- "typed_arrays/int16_array.idl",
- "typed_arrays/int32_array.idl",
- "typed_arrays/int8_array.idl",
- "typed_arrays/shared_array_buffer.idl",
- "typed_arrays/uint16_array.idl",
- "typed_arrays/uint32_array.idl",
- "typed_arrays/uint8_array.idl",
- "typed_arrays/uint8_clamped_array.idl",
- ],
- "abspath")
-
-# IDL files that only have typedefs/enums.
-core_typedefs_enums_only_idl_files =
- get_path_info([
- "css/cssom_string.idl",
- "dom/common_definitions.idl",
- "timing/dom_high_res_time_stamp.idl",
- "timing/performance_entry_list.idl",
- ],
- "abspath")
-
-core_callback_function_idl_files =
- get_path_info([
- "html/event_handler.idl",
- "dom/frame_request_callback.idl",
- "dom/function_string_callback.idl",
- "dom/idle_request_callback.idl",
- "dom/void_function.idl",
- "streams/underlying_source_cancel_callback.idl",
- "streams/underlying_source_pull_callback.idl",
- "streams/underlying_source_start_callback.idl",
- ],
- "abspath")
-
-core_callback_interface_idl_files =
- get_path_info([
- "dom/events/event_listener.idl",
- "dom/node_filter.idl",
- "html/void_callback.idl",
- ],
- "abspath")
-
-core_dictionary_idl_files =
- get_path_info(
- [
- "animation/base_keyframe.idl",
- "animation/base_property_indexed_keyframe.idl",
- "animation/computed_effect_timing.idl",
- "animation/document_timeline_options.idl",
- "animation/effect_timing.idl",
- "animation/get_animations_options.idl",
- "animation/keyframe_animation_options.idl",
- "animation/keyframe_effect_options.idl",
- "animation/optional_effect_timing.idl",
- "animation/scroll_timeline_element_based_offset.idl",
- "animation/scroll_timeline_options.idl",
- "app_history/app_history_navigate_event_init.idl",
- "app_history/app_history_navigate_options.idl",
- "app_history/app_history_navigation_options.idl",
- "css/css_style_sheet_init.idl",
- "css/font_face_descriptors.idl",
- "css/font_face_set_load_event_init.idl",
- "css/media_query_list_event_init.idl",
- "css/property_definition.idl",
- "css/cssom/css_matrix_component_options.idl",
- "css/cssom/css_numeric_type.idl",
- "document_transition/document_transition_prepare_options.idl",
- "document_transition/document_transition_start_options.idl",
- "dom/element_creation_options.idl",
- "dom/element_definition_options.idl",
- "dom/element_registration_options.idl",
- "dom/get_inner_html_options.idl",
- "dom/get_root_node_options.idl",
- "dom/idle_request_options.idl",
- "dom/interest_cohort.idl",
- "dom/mutation_observer_init.idl",
- "dom/pointer_lock_options.idl",
- "dom/shadow_root_init.idl",
- "dom/static_range_init.idl",
- "dom/events/add_event_listener_options.idl",
- "dom/events/custom_event_init.idl",
- "dom/events/event_init.idl",
- "dom/events/event_listener_options.idl",
- "dom/events/event_modifier_init.idl",
- "editing/ime/edit_context_init.idl",
- "editing/ime/text_update_event_init.idl",
- "editing/ime/text_format_update_event_init.idl",
- "events/animation_event_init.idl",
- "events/animation_playback_event_init.idl",
- "events/application_cache_error_event_init.idl",
- "events/clipboard_event_init.idl",
- "events/composition_event_init.idl",
- "events/drag_event_init.idl",
- "events/error_event_init.idl",
- "events/focus_event_init.idl",
- "events/hash_change_event_init.idl",
- "events/input_event_init.idl",
- "events/keyboard_event_init.idl",
- "events/message_event_init.idl",
- "events/mouse_event_init.idl",
- "events/overscroll_event_init.idl",
- "events/page_transition_event_init.idl",
- "events/pointer_event_init.idl",
- "events/pop_state_event_init.idl",
- "events/progress_event_init.idl",
- "events/promise_rejection_event_init.idl",
- "events/security_policy_violation_event_init.idl",
- "events/touch_event_init.idl",
- "events/transition_event_init.idl",
- "events/ui_event_init.idl",
- "events/wheel_event_init.idl",
- "fetch/request_init.idl",
- "fetch/response_init.idl",
- "fetch/trust_token.idl",
- "fileapi/blob_property_bag.idl",
- "fileapi/file_property_bag.idl",
- "frame/attribution_source_params.idl",
- "frame/is_input_pending_options.idl",
- "frame/navigator_ua_brand_version.idl",
- "frame/reporting_observer_options.idl",
- "frame/scroll_into_view_options.idl",
- "frame/scroll_options.idl",
- "frame/scroll_to_options.idl",
- "frame/window_controls_overlay_geometry_change_event_init.idl",
- "frame/window_post_message_options.idl",
- "fullscreen/fullscreen_options.idl",
- "geometry/dom_matrix_2d_init.idl",
- "geometry/dom_matrix_init.idl",
- "geometry/dom_point_init.idl",
- "geometry/dom_quad_init.idl",
- "geometry/dom_rect_init.idl",
- "html/focus_options.idl",
- "html/assigned_nodes_options.idl",
- "html/canvas/baselines.idl",
- "html/canvas/image_data_settings.idl",
- "html/canvas/image_encode_options.idl",
- "html/custom/validity_state_flags.idl",
- "html/forms/form_data_event_init.idl",
- "html/forms/submit_event_init.idl",
- "html/portal/portal_activate_event_init.idl",
- "html/portal/portal_activate_options.idl",
- "html/track/track_event_init.idl",
- "imagebitmap/image_bitmap_options.idl",
- "input/input_device_capabilities_init.idl",
- "input/touch_init.idl",
- "intersection_observer/intersection_observer_init.idl",
- "frame/ua_data_values.idl",
- "layout/ng/custom/custom_layout_constraints_options.idl",
- "layout/ng/custom/fragment_result_options.idl",
- "layout/ng/custom/intrinsic_sizes_result_options.idl",
- "messaging/post_message_options.idl",
- "mojo/mojo_create_data_pipe_options.idl",
- "mojo/mojo_create_data_pipe_result.idl",
- "mojo/mojo_create_message_pipe_result.idl",
- "mojo/mojo_create_shared_buffer_result.idl",
- "mojo/mojo_discard_data_options.idl",
- "mojo/mojo_duplicate_buffer_handle_options.idl",
- "mojo/mojo_handle_signals.idl",
- "mojo/mojo_map_buffer_result.idl",
- "mojo/mojo_read_data_options.idl",
- "mojo/mojo_read_data_result.idl",
- "mojo/mojo_read_message_flags.idl",
- "mojo/mojo_read_message_result.idl",
- "mojo/mojo_write_data_options.idl",
- "mojo/mojo_write_data_result.idl",
- "mojo/test/mojo_interface_request_event_init.idl",
- "page/scrolling/scroll_state_init.idl",
- "resize_observer/resize_observer_options.idl",
- "streams/readable_stream_byob_read_result.idl",
- "streams/readable_stream_get_reader_options.idl",
- "streams/readable_writable_pair.idl",
- "streams/stream_pipe_options.idl",
- "streams/underlying_source.idl",
- "streams/queuing_strategy_init.idl",
- "timing/measure_memory/memory_measurement.idl",
- "timing/measure_memory/memory_breakdown_entry.idl",
- "timing/measure_memory/memory_attribution.idl",
- "timing/measure_memory/memory_attribution_container.idl",
- "timing/performance_mark_options.idl",
- "timing/performance_measure_options.idl",
- "timing/performance_observer_init.idl",
- "timing/profiler_frame.idl",
- "timing/profiler_init_options.idl",
- "timing/profiler_sample.idl",
- "timing/profiler_stack.idl",
- "timing/profiler_trace.idl",
- "trustedtypes/trusted_type_policy_options.idl",
- "workers/worker_options.idl",
- "workers/worklet_options.idl",
- "xml/parse_from_string_options.idl",
- ],
- "abspath")
-
-core_testing_dictionary_idl_files =
- get_path_info([
- "testing/internal_dictionary.idl",
- "testing/internal_dictionary_derived.idl",
- "testing/internal_dictionary_derived_derived.idl",
- "testing/origin_trials_test_dictionary.idl",
- ],
- "abspath")
-
-webcore_testing_idl_files =
- get_path_info([
- "testing/callback_function_test.idl",
- "testing/death_aware_script_wrappable.idl",
- "testing/dictionary_test.idl",
- "testing/garbage_collected_script_wrappable.idl",
- "testing/gc_observation.idl",
- "testing/hit_test_layer_rect.idl",
- "testing/hit_test_layer_rect_list.idl",
- "testing/internal_settings.idl",
- "testing/origin_trials_test.idl",
- "testing/record_test.idl",
- "testing/sequence_test.idl",
- "testing/static_selection.idl",
- "testing/type_conversions.idl",
- "testing/union_types_test.idl",
- "testing/worker_internals.idl",
- ],
- "abspath")
-
-# Testing IDL files that have partial interfaces in modules.
-webcore_testing_idl_with_modules_dependency_files =
- get_path_info([ "testing/internals.idl" ], "abspath")
-
-webcore_testing_dependency_idl_files =
- get_path_info([
- "dom/testing/internals_storage_access.idl",
- "fetch/testing/internals_fetch.idl",
- "fetch/testing/worker_internals_fetch.idl",
- "testing/origin_trials_test_partial.idl",
- "timing/internals_profiler.idl",
- ],
- "abspath")
-
-generated_webcore_testing_idl_files =
- get_path_info(
- [
- "$blink_core_output_dir/testing/internal_runtime_flags.idl",
- "$blink_core_output_dir/testing/internal_settings_generated.idl",
- ],
- "abspath")
-
-core_definition_idl_files =
- core_interface_idl_files_core_only +
- core_interface_idl_files_modules_dependent +
- core_buffer_source_type_idl_files + core_callback_interface_idl_files +
- core_dictionary_idl_files
-
-core_testing_definition_idl_files =
- core_testing_dictionary_idl_files + webcore_testing_idl_files +
- webcore_testing_idl_with_modules_dependency_files
-
-# Static IDL files
-core_static_interface_idl_files =
- core_definition_idl_files + core_testing_definition_idl_files +
- core_callback_function_idl_files + core_typedefs_enums_only_idl_files
-
-core_static_dependency_idl_files =
- core_partial_definition_idl_files + webcore_testing_dependency_idl_files
-
-# Generated IDL files
-core_generated_interface_idl_files =
- generated_webcore_testing_idl_files # interfaces
-core_generated_dependency_idl_files =
- core_global_constructors_generated_idl_files # partial interfaces
-
-# Dependency IDL files: don't generate individual bindings, but do process
-# in IDL dependency computation, and count as build dependencies
-# 'core_dependency_idl_files' is already used in Source/core, so avoid
-# collision
-core_all_dependency_idl_files =
- core_static_dependency_idl_files + core_generated_dependency_idl_files
diff --git a/chromium/third_party/blink/renderer/core/core_initializer.cc b/chromium/third_party/blink/renderer/core/core_initializer.cc
index 19cd2edc94f..c04151d0156 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.cc
+++ b/chromium/third_party/blink/renderer/core/core_initializer.cc
@@ -52,6 +52,7 @@
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/media_type_names.h"
#include "third_party/blink/renderer/core/performance_entry_names.h"
+#include "third_party/blink/renderer/core/pointer_type_names.h"
#include "third_party/blink/renderer/core/securitypolicyviolation_disposition_names.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/core/timezone/timezone_controller.h"
@@ -109,7 +110,8 @@ void CoreInitializer::Initialize() {
html_tokenizer_names::kNamesCount + http_names::kNamesCount +
input_type_names::kNamesCount + keywords::kNamesCount +
media_feature_names::kNamesCount + media_type_names::kNamesCount +
- performance_entry_names::kNamesCount + shadow_element_names::kNamesCount;
+ performance_entry_names::kNamesCount + pointer_type_names::kNamesCount +
+ shadow_element_names::kNamesCount;
StringImpl::ReserveStaticStringsCapacityForSize(
kCoreStaticStringsCount + StringImpl::AllStaticStrings().size());
@@ -136,6 +138,7 @@ void CoreInitializer::Initialize() {
media_feature_names::Init();
media_type_names::Init();
performance_entry_names::Init();
+ pointer_type_names::Init();
shadow_element_names::Init();
securitypolicyviolation_disposition_names::Init();
diff --git a/chromium/third_party/blink/renderer/core/core_initializer.h b/chromium/third_party/blink/renderer/core/core_initializer.h
index 39ea294ce3b..6f211906952 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.h
+++ b/chromium/third_party/blink/renderer/core/core_initializer.h
@@ -33,11 +33,16 @@
#include <memory>
-#include "base/macros.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+namespace display {
+struct ScreenInfos;
+}
+
namespace mojo {
class BinderMap;
}
@@ -53,7 +58,6 @@ class LocalFrame;
class MediaControls;
class Page;
class PictureInPictureController;
-struct ScreenInfos;
class Settings;
class ShadowRoot;
class WebLocalFrameClient;
@@ -64,7 +68,6 @@ class WebRemotePlaybackClient;
class CORE_EXPORT CoreInitializer {
USING_FAST_MALLOC(CoreInitializer);
- DISALLOW_COPY_AND_ASSIGN(CoreInitializer);
public:
// Initialize must be called before GetInstance.
@@ -73,6 +76,8 @@ class CORE_EXPORT CoreInitializer {
return *instance_;
}
+ CoreInitializer(const CoreInitializer&) = delete;
+ CoreInitializer& operator=(const CoreInitializer&) = delete;
virtual ~CoreInitializer() = default;
// Should be called by clients before trying to create Frames.
@@ -124,11 +129,26 @@ class CORE_EXPORT CoreInitializer {
Page* clone_from_page,
const SessionStorageNamespaceId& clone_to_namespace) = 0;
+ // Evicts the cached data of Session Storage. Called after dispatching a
+ // document unload or freeze event to avoid reusing old data in the cache in
+ // case the same renderer process is reused after the session storage has been
+ // modified by another renderer process. (Eg: Back navigation from a
+ // prerendered page.)
+ virtual void EvictSessionStorageCachedData(Page*) = 0;
+
virtual void DidChangeManifest(LocalFrame&) = 0;
virtual void NotifyOrientationChanged(LocalFrame&) = 0;
// Called with an updated set of ScreenInfos for a local root frame
// during a visual property update.
- virtual void DidUpdateScreens(LocalFrame& frame, const ScreenInfos&) = 0;
+ virtual void DidUpdateScreens(LocalFrame& frame,
+ const display::ScreenInfos&) = 0;
+
+ virtual void SetLocalStorageArea(
+ LocalFrame& frame,
+ mojo::PendingRemote<mojom::blink::StorageArea> local_storage_area) = 0;
+ virtual void SetSessionStorageArea(
+ LocalFrame& frame,
+ mojo::PendingRemote<mojom::blink::StorageArea> session_storage_area) = 0;
protected:
// CoreInitializer is only instantiated by subclass ModulesInitializer.
diff --git a/chromium/third_party/blink/renderer/core/css/OWNERS b/chromium/third_party/blink/renderer/core/css/OWNERS
index 7c1cab453b7..ec2b6419752 100644
--- a/chromium/third_party/blink/renderer/core/css/OWNERS
+++ b/chromium/third_party/blink/renderer/core/css/OWNERS
@@ -1,4 +1,3 @@
-alancutter@chromium.org
andruud@chromium.org
ericwilligers@chromium.org
futhark@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc b/chromium/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
index 060346478e7..5b78aba94f4 100644
--- a/chromium/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
+++ b/chromium/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.h"
-#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/style_attribute_mutation_scope.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
@@ -38,10 +37,7 @@ unsigned AbstractPropertySetCSSStyleDeclaration::length() const {
String AbstractPropertySetCSSStyleDeclaration::item(unsigned i) const {
if (i >= PropertySet().PropertyCount())
return "";
- CSSPropertyValueSet::PropertyReference property = PropertySet().PropertyAt(i);
- if (property.Id() == CSSPropertyID::kVariable)
- return To<CSSCustomPropertyDeclaration>(property.Value()).GetName();
- return property.Name().ToAtomicString();
+ return PropertySet().PropertyAt(i).Name().ToAtomicString();
}
String AbstractPropertySetCSSStyleDeclaration::cssText() const {
diff --git a/chromium/third_party/blink/renderer/core/css/background_color_paint_image_generator.h b/chromium/third_party/blink/renderer/core/css/background_color_paint_image_generator.h
index 4816b875227..0147d7ef1f5 100644
--- a/chromium/third_party/blink/renderer/core/css/background_color_paint_image_generator.h
+++ b/chromium/third_party/blink/renderer/core/css/background_color_paint_image_generator.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/native_paint_image_generator.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
diff --git a/chromium/third_party/blink/renderer/core/css/basic_shape_functions.h b/chromium/third_party/blink/renderer/core/css/basic_shape_functions.h
index bc4c5ef456b..cbf1981254a 100644
--- a/chromium/third_party/blink/renderer/core/css/basic_shape_functions.h
+++ b/chromium/third_party/blink/renderer/core/css/basic_shape_functions.h
@@ -42,8 +42,9 @@ class StyleResolverState;
class ComputedStyle;
CSSValue* ValueForBasicShape(const ComputedStyle&, const BasicShape*);
-scoped_refptr<BasicShape> BasicShapeForValue(const StyleResolverState&,
- const CSSValue&);
+CORE_EXPORT scoped_refptr<BasicShape> BasicShapeForValue(
+ const StyleResolverState&,
+ const CSSValue&);
FloatPoint FloatPointForCenterCoordinate(const BasicShapeCenterCoordinate&,
const BasicShapeCenterCoordinate&,
FloatSize);
diff --git a/chromium/third_party/blink/renderer/core/css/build.gni b/chromium/third_party/blink/renderer/core/css/build.gni
index 08706778e35..d170dc0a9cd 100644
--- a/chromium/third_party/blink/renderer/core/css/build.gni
+++ b/chromium/third_party/blink/renderer/core/css/build.gni
@@ -13,6 +13,8 @@ blink_core_sources_css = [
"basic_shape_functions.h",
"binary_data_font_face_source.cc",
"binary_data_font_face_source.h",
+ "clip_path_paint_image_generator.cc",
+ "clip_path_paint_image_generator.h",
"computed_style_css_value_mapping.cc",
"computed_style_css_value_mapping.h",
"counter_style.cc",
@@ -149,6 +151,8 @@ blink_core_sources_css = [
"css_path_value.h",
"css_pending_substitution_value.cc",
"css_pending_substitution_value.h",
+ "css_pending_system_font_value.cc",
+ "css_pending_system_font_value.h",
"css_primitive_value.cc",
"css_primitive_value.h",
"css_primitive_value_mappings.h",
@@ -362,6 +366,10 @@ blink_core_sources_css = [
"font_size_functions.cc",
"font_size_functions.h",
"hash_tools.h",
+ "has_argument_match_context.cc",
+ "has_argument_match_context.h",
+ "has_matched_cache_scope.cc",
+ "has_matched_cache_scope.h",
"inline_css_style_declaration.cc",
"inline_css_style_declaration.h",
"invalidation/invalidation_flags.cc",
@@ -673,6 +681,7 @@ blink_core_tests_css = [
"media_query_matcher_test.cc",
"media_query_set_test.cc",
"media_values_test.cc",
+ "parser/at_rule_descriptor_parser_test.cc",
"parser/css_lazy_parsing_test.cc",
"parser/css_parser_fast_paths_test.cc",
"parser/css_parser_impl_test.cc",
@@ -714,6 +723,7 @@ blink_core_tests_css = [
"selector_query_test.cc",
"style_element_test.cc",
"style_engine_test.cc",
+ "style_recalc_test.cc",
"style_environment_variables_test.cc",
"style_rule_test.cc",
"style_sheet_contents_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.cc b/chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.cc
new file mode 100644
index 00000000000..7bd33abcdfb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.cc
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/clip_path_paint_image_generator.h"
+
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+
+namespace blink {
+
+namespace {
+
+ClipPathPaintImageGenerator::ClipPathPaintImageGeneratorCreateFunction*
+ g_create_function = nullptr;
+
+} // namespace
+
+// static
+void ClipPathPaintImageGenerator::Init(
+ ClipPathPaintImageGeneratorCreateFunction* create_function) {
+ DCHECK(!g_create_function);
+ g_create_function = create_function;
+}
+
+ClipPathPaintImageGenerator* ClipPathPaintImageGenerator::Create(
+ LocalFrame& local_root) {
+ DCHECK(g_create_function);
+ DCHECK(local_root.IsLocalRoot());
+ return g_create_function(local_root);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.h b/chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.h
new file mode 100644
index 00000000000..a2ed92ab69a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/clip_path_paint_image_generator.h
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CLIP_PATH_PAINT_IMAGE_GENERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CLIP_PATH_PAINT_IMAGE_GENERATOR_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/native_paint_image_generator.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+
+namespace blink {
+
+class Image;
+class LocalFrame;
+class Node;
+class FloatRect;
+
+class CORE_EXPORT ClipPathPaintImageGenerator
+ : public NativePaintImageGenerator {
+ public:
+ static ClipPathPaintImageGenerator* Create(LocalFrame& local_root);
+
+ ~ClipPathPaintImageGenerator() override = default;
+
+ using ClipPathPaintImageGeneratorCreateFunction =
+ ClipPathPaintImageGenerator*(LocalFrame&);
+ static void Init(ClipPathPaintImageGeneratorCreateFunction* create_function);
+
+ virtual scoped_refptr<Image> Paint(float zoom,
+ const FloatRect& reference_box,
+ const Node&) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CLIP_PATH_PAINT_IMAGE_GENERATOR_H_
diff --git a/chromium/third_party/blink/renderer/core/css/container_query.cc b/chromium/third_party/blink/renderer/core/css/container_query.cc
index 6b75aa2459c..a39850fb4a7 100644
--- a/chromium/third_party/blink/renderer/core/css/container_query.cc
+++ b/chromium/third_party/blink/renderer/core/css/container_query.cc
@@ -26,8 +26,10 @@ PhysicalAxes ComputeQueriedAxes(const MediaQuerySet& media_queries) {
} // namespace
-ContainerQuery::ContainerQuery(scoped_refptr<MediaQuerySet> media_queries)
- : media_queries_(media_queries),
+ContainerQuery::ContainerQuery(const AtomicString& name,
+ scoped_refptr<MediaQuerySet> media_queries)
+ : name_(name),
+ media_queries_(media_queries),
queried_axes_(ComputeQueriedAxes(*media_queries)) {}
ContainerQuery::ContainerQuery(const ContainerQuery& other)
diff --git a/chromium/third_party/blink/renderer/core/css/container_query.h b/chromium/third_party/blink/renderer/core/css/container_query.h
index 1257645c088..3acdcbba0a0 100644
--- a/chromium/third_party/blink/renderer/core/css/container_query.h
+++ b/chromium/third_party/blink/renderer/core/css/container_query.h
@@ -14,9 +14,10 @@ namespace blink {
class CORE_EXPORT ContainerQuery final
: public GarbageCollected<ContainerQuery> {
public:
- explicit ContainerQuery(scoped_refptr<MediaQuerySet>);
+ ContainerQuery(const AtomicString& name, scoped_refptr<MediaQuerySet>);
ContainerQuery(const ContainerQuery&);
+ const AtomicString& Name() const { return name_; }
PhysicalAxes QueriedAxes() const { return queried_axes_; }
String ToString() const;
@@ -26,8 +27,12 @@ class CORE_EXPORT ContainerQuery final
private:
friend class ContainerQueryTest;
friend class ContainerQueryEvaluator;
+ friend class CSSContainerRule;
- // TODO(crbug.com/1145970): Refactor to avoid internal MediaQuerySet.
+ scoped_refptr<MediaQuerySet> MediaQueries() const { return media_queries_; }
+
+ AtomicString name_;
+ // TODO(crbug.com/1214810): Refactor to avoid internal MediaQuerySet.
scoped_refptr<MediaQuerySet> media_queries_;
PhysicalAxes queried_axes_{kPhysicalAxisNone};
};
diff --git a/chromium/third_party/blink/renderer/core/css/container_query_evaluator.cc b/chromium/third_party/blink/renderer/core/css/container_query_evaluator.cc
index aee25f87272..1d301c61e60 100644
--- a/chromium/third_party/blink/renderer/core/css/container_query_evaluator.cc
+++ b/chromium/third_party/blink/renderer/core/css/container_query_evaluator.cc
@@ -4,11 +4,38 @@
#include "third_party/blink/renderer/core/css/container_query_evaluator.h"
#include "third_party/blink/renderer/core/css/container_query.h"
+#include "third_party/blink/renderer/core/css/style_recalc.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
namespace blink {
+// static
+Element* ContainerQueryEvaluator::FindContainer(
+ const StyleRecalcContext& context,
+ const AtomicString& container_name) {
+ Element* container = context.container;
+ if (!container)
+ return nullptr;
+
+ if (container_name == g_null_atom)
+ return container;
+
+ // TODO(crbug.com/1213888): Cache results.
+ for (Element* element = container; element;
+ element = LayoutTreeBuilderTraversal::ParentElement(*element)) {
+ if (const ComputedStyle* style = element->GetComputedStyle()) {
+ if (style->IsContainerForContainerQueries() &&
+ style->ContainerName() == container_name)
+ return element;
+ }
+ }
+
+ return nullptr;
+}
+
namespace {
bool IsSufficientlyContained(PhysicalAxes contained_axes,
@@ -18,15 +45,21 @@ bool IsSufficientlyContained(PhysicalAxes contained_axes,
} // namespace
-ContainerQueryEvaluator::ContainerQueryEvaluator(PhysicalSize size,
- PhysicalAxes contained_axes) {
- SetData(size, contained_axes);
+double ContainerQueryEvaluator::Width() const {
+ return size_.width.ToDouble();
+}
+
+double ContainerQueryEvaluator::Height() const {
+ return size_.height.ToDouble();
}
bool ContainerQueryEvaluator::Eval(
const ContainerQuery& container_query) const {
+ if (container_query.QueriedAxes() == PhysicalAxes(kPhysicalAxisNone))
+ return false;
if (!IsSufficientlyContained(contained_axes_, container_query.QueriedAxes()))
return false;
+ DCHECK(media_query_evaluator_);
return media_query_evaluator_->Eval(*container_query.media_queries_);
}
@@ -34,22 +67,24 @@ void ContainerQueryEvaluator::Add(const ContainerQuery& query, bool result) {
results_.Set(&query, result);
}
-bool ContainerQueryEvaluator::ContainerChanged(PhysicalSize size,
- PhysicalAxes contained_axes) {
+ContainerQueryEvaluator::Change ContainerQueryEvaluator::ContainerChanged(
+ PhysicalSize size,
+ PhysicalAxes contained_axes) {
if (size_ == size && contained_axes_ == contained_axes)
- return false;
+ return Change::kNone;
SetData(size, contained_axes);
- if (!ResultsChanged())
- return false;
+ Change change = ComputeChange();
// We can clear the results here because we will always recaculate the style
// of all descendants which depend on this evaluator whenever we return
- // 'true' from this function, so the results will always be repopulated.
- results_.clear();
+ // something other than kNone from this function, so the results will always
+ // be repopulated.
+ if (change != Change::kNone)
+ ClearResults();
- return true;
+ return change;
}
void ContainerQueryEvaluator::Trace(Visitor* visitor) const {
@@ -68,12 +103,26 @@ void ContainerQueryEvaluator::SetData(PhysicalSize size,
MakeGarbageCollected<MediaQueryEvaluator>(*cached_values);
}
-bool ContainerQueryEvaluator::ResultsChanged() const {
+void ContainerQueryEvaluator::ClearResults() {
+ results_.clear();
+ referenced_by_unit_ = false;
+}
+
+ContainerQueryEvaluator::Change ContainerQueryEvaluator::ComputeChange() const {
+ Change change = Change::kNone;
+
+ if (referenced_by_unit_)
+ return Change::kDescendantContainers;
+
for (const auto& result : results_) {
- if (Eval(*result.key) != result.value)
- return true;
+ if (Eval(*result.key) != result.value) {
+ change = std::max(change, result.key->Name() == g_null_atom
+ ? Change::kNearestContainer
+ : Change::kDescendantContainers);
+ }
}
- return false;
+
+ return change;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/container_query_evaluator.h b/chromium/third_party/blink/renderer/core/css/container_query_evaluator.h
index 939d0488b3a..a4ced75a181 100644
--- a/chromium/third_party/blink/renderer/core/css/container_query_evaluator.h
+++ b/chromium/third_party/blink/renderer/core/css/container_query_evaluator.h
@@ -14,11 +14,23 @@
namespace blink {
class ContainerQuery;
+class Element;
+class StyleRecalcContext;
class CORE_EXPORT ContainerQueryEvaluator final
: public GarbageCollected<ContainerQueryEvaluator> {
public:
- ContainerQueryEvaluator(PhysicalSize, PhysicalAxes contained_axes);
+ static Element* FindContainer(const StyleRecalcContext& context,
+ const AtomicString& container_name);
+
+ // Creates an evaluator with no containment, hence all queries evaluated
+ // against it will fail.
+ ContainerQueryEvaluator() = default;
+
+ // Used by container relative units (qi, qb, etc).
+ double Width() const;
+ double Height() const;
+ void SetReferencedByUnit() { referenced_by_unit_ = true; }
bool Eval(const ContainerQuery&) const;
@@ -33,31 +45,39 @@ class CORE_EXPORT ContainerQueryEvaluator final
return result;
}
+ enum class Change {
+ // The update has no effect on the evaluation of queries associated with
+ // this evaluator, and therefore we do not need to perform style recalc of
+ // any elements which depend on this evaluator.
+ kNone,
+ // The update can only affect elements for which this container is the
+ // nearest container. In other words, we do not need to recalculate style
+ // for elements in nested containers.
+ kNearestContainer,
+ // The update can affect elements within this container, and also in
+ // descendant containers.
+ kDescendantContainers,
+ };
+
// Update the size/axis information of the evaluator.
//
- // A return value of 'false' means that the update has no effect on the
- // evaluation of queries associated with this evaluator, and therefore we do
- // not need to perform style recalc of any elements which depend on this
- // evaluator.
- //
- // A return value of 'true' means that the update *may* have an effect, and
- // therefore elements that depends on this evaluator need style recalc.
- //
- // Dependent queries are cleared when 'true' is returned (and left unchanged
- // otherwise).
- bool ContainerChanged(PhysicalSize, PhysicalAxes contained_axes);
+ // Dependent queries are cleared when kUnnamed/kNamed is returned (and left
+ // unchanged otherwise).
+ Change ContainerChanged(PhysicalSize, PhysicalAxes contained_axes);
void Trace(Visitor*) const;
private:
void SetData(PhysicalSize, PhysicalAxes contained_axes);
- bool ResultsChanged() const;
+ void ClearResults();
+ Change ComputeChange() const;
// TODO(crbug.com/1145970): Don't lean on MediaQueryEvaluator.
Member<MediaQueryEvaluator> media_query_evaluator_;
PhysicalSize size_;
PhysicalAxes contained_axes_;
HeapHashMap<Member<const ContainerQuery>, bool> results_;
+ bool referenced_by_unit_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/container_query_evaluator_test.cc b/chromium/third_party/blink/renderer/core/css/container_query_evaluator_test.cc
index 8c79745a321..4507a8250bc 100644
--- a/chromium/third_party/blink/renderer/core/css/container_query_evaluator_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/container_query_evaluator_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/css/css_test_helpers.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/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -35,11 +36,19 @@ class ContainerQueryEvaluatorTest : public PageTestBase,
PhysicalAxes contained_axes) {
ContainerQuery* container_query = ParseContainer(query);
DCHECK(container_query);
- auto* evaluator = MakeGarbageCollected<ContainerQueryEvaluator>(
+ auto* evaluator = MakeGarbageCollected<ContainerQueryEvaluator>();
+ evaluator->ContainerChanged(
PhysicalSize(LayoutUnit(width), LayoutUnit(height)), contained_axes);
return evaluator->Eval(*container_query);
}
+ bool ContainerChanged(ContainerQueryEvaluator* evaluator,
+ PhysicalSize size,
+ PhysicalAxes axes) {
+ return evaluator->ContainerChanged(size, axes) !=
+ ContainerQueryEvaluator::Change::kNone;
+ }
+
const PhysicalAxes none{kPhysicalAxisNone};
const PhysicalAxes both{kPhysicalAxisBoth};
const PhysicalAxes horizontal{kPhysicalAxisHorizontal};
@@ -85,26 +94,26 @@ TEST_F(ContainerQueryEvaluatorTest, ContainerChanged) {
ASSERT_TRUE(container_query_100);
ASSERT_TRUE(container_query_200);
- auto* evaluator =
- MakeGarbageCollected<ContainerQueryEvaluator>(size_100, horizontal);
+ auto* evaluator = MakeGarbageCollected<ContainerQueryEvaluator>();
+ evaluator->ContainerChanged(size_100, horizontal);
ASSERT_TRUE(evaluator);
EXPECT_TRUE(evaluator->EvalAndAdd(*container_query_100));
EXPECT_FALSE(evaluator->EvalAndAdd(*container_query_200));
- EXPECT_FALSE(evaluator->ContainerChanged(size_100, horizontal));
+ EXPECT_FALSE(ContainerChanged(evaluator, size_100, horizontal));
EXPECT_TRUE(evaluator->EvalAndAdd(*container_query_100));
EXPECT_FALSE(evaluator->EvalAndAdd(*container_query_200));
- EXPECT_TRUE(evaluator->ContainerChanged(size_200, horizontal));
+ EXPECT_TRUE(ContainerChanged(evaluator, size_200, horizontal));
EXPECT_TRUE(evaluator->EvalAndAdd(*container_query_100));
EXPECT_TRUE(evaluator->EvalAndAdd(*container_query_200));
- EXPECT_FALSE(evaluator->ContainerChanged(size_200, horizontal));
+ EXPECT_FALSE(ContainerChanged(evaluator, size_200, horizontal));
EXPECT_TRUE(evaluator->EvalAndAdd(*container_query_100));
EXPECT_TRUE(evaluator->EvalAndAdd(*container_query_200));
- EXPECT_TRUE(evaluator->ContainerChanged(size_200, vertical));
+ EXPECT_TRUE(ContainerChanged(evaluator, size_200, vertical));
EXPECT_FALSE(evaluator->EvalAndAdd(*container_query_100));
EXPECT_FALSE(evaluator->EvalAndAdd(*container_query_200));
}
@@ -178,33 +187,33 @@ TEST_F(ContainerQueryEvaluatorTest, DependentQueries) {
ContainerQuery* query_max_300px = ParseContainer("(max-width: 300px)");
ASSERT_TRUE(query_min_200px);
- auto* evaluator =
- MakeGarbageCollected<ContainerQueryEvaluator>(size_100, horizontal);
+ auto* evaluator = MakeGarbageCollected<ContainerQueryEvaluator>();
+ evaluator->ContainerChanged(size_100, horizontal);
evaluator->EvalAndAdd(*query_min_200px);
evaluator->EvalAndAdd(*query_max_300px);
// Updating with the same size as we initially had should not invalidate
// any query results.
- EXPECT_FALSE(evaluator->ContainerChanged(size_100, horizontal));
+ EXPECT_FALSE(ContainerChanged(evaluator, size_100, horizontal));
// Makes no difference for either of (min-width: 200px), (max-width: 300px):
- EXPECT_FALSE(evaluator->ContainerChanged(size_150, horizontal));
+ EXPECT_FALSE(ContainerChanged(evaluator, size_150, horizontal));
// (min-width: 200px) becomes true:
- EXPECT_TRUE(evaluator->ContainerChanged(size_200, horizontal));
+ EXPECT_TRUE(ContainerChanged(evaluator, size_200, horizontal));
evaluator->EvalAndAdd(*query_min_200px);
evaluator->EvalAndAdd(*query_max_300px);
- EXPECT_FALSE(evaluator->ContainerChanged(size_200, horizontal));
+ EXPECT_FALSE(ContainerChanged(evaluator, size_200, horizontal));
// Makes no difference for either of (min-width: 200px), (max-width: 300px):
- EXPECT_FALSE(evaluator->ContainerChanged(size_300, horizontal));
+ EXPECT_FALSE(ContainerChanged(evaluator, size_300, horizontal));
// (max-width: 300px) becomes false:
- EXPECT_TRUE(evaluator->ContainerChanged(size_400, horizontal));
+ EXPECT_TRUE(ContainerChanged(evaluator, size_400, horizontal));
}
-TEST_F(ContainerQueryEvaluatorTest, EvaluatorOnDetachLayoutTree) {
+TEST_F(ContainerQueryEvaluatorTest, EvaluatorDisplayNone) {
SetBodyInnerHTML(R"HTML(
<style>
main {
@@ -213,36 +222,50 @@ TEST_F(ContainerQueryEvaluatorTest, EvaluatorOnDetachLayoutTree) {
width: 500px;
height: 500px;
}
+ main.none {
+ display: none;
+ }
@container (min-width: 500px) {
div { --x:test; }
}
</style>
- <main id=container1>
- <div></div>
- </main>
- <main id=container2>
- <div></div>
+ <main id=outer>
+ <div>
+ <main id=inner>
+ <div></div>
+ </main>
+ </div>
</main>
)HTML");
- Element* container1 = GetDocument().getElementById("container1");
- ASSERT_TRUE(container1);
- ASSERT_TRUE(container1->GetContainerQueryEvaluator());
+ // Inner container
+ Element* inner = GetDocument().getElementById("inner");
+ ASSERT_TRUE(inner);
+ EXPECT_TRUE(inner->GetContainerQueryEvaluator());
+
+ inner->classList().Add("none");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(inner->GetContainerQueryEvaluator());
- // DetachLayoutTree with performing_reattach=false:
- container1->remove();
+ inner->classList().Remove("none");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(container1->GetContainerQueryEvaluator())
- << "ContainerQueryEvaluator should be removed";
-
- // DetachLayoutTree with performing_reattach=true:
- Element* container2 = GetDocument().getElementById("container2");
- ASSERT_TRUE(container2);
- ASSERT_TRUE(container2->GetContainerQueryEvaluator());
- container2->SetInlineStyleProperty(CSSPropertyID::kDisplay, "none");
+ ASSERT_TRUE(inner->GetContainerQueryEvaluator());
+
+ // Outer container
+ Element* outer = GetDocument().getElementById("outer");
+ ASSERT_TRUE(outer);
+ EXPECT_TRUE(outer->GetContainerQueryEvaluator());
+ EXPECT_TRUE(inner->GetContainerQueryEvaluator());
+
+ outer->classList().Add("none");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(outer->GetContainerQueryEvaluator());
+ EXPECT_FALSE(inner->GetContainerQueryEvaluator());
+
+ outer->classList().Remove("none");
UpdateAllLifecyclePhasesForTest();
- EXPECT_TRUE(container2->GetContainerQueryEvaluator())
- << "ContainerQueryEvaluator should persist";
+ EXPECT_TRUE(outer->GetContainerQueryEvaluator());
+ EXPECT_TRUE(inner->GetContainerQueryEvaluator());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/container_query_test.cc b/chromium/third_party/blink/renderer/core/css/container_query_test.cc
index 3e6b0e994c3..2bdeb065f3c 100644
--- a/chromium/third_party/blink/renderer/core/css/container_query_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/container_query_test.cc
@@ -6,9 +6,11 @@
#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -50,6 +52,21 @@ class ContainerQueryTest : public PageTestBase,
MediaQuerySet& GetMediaQuerySet(ContainerQuery& container_query) {
return *container_query.media_queries_;
}
+
+ const CSSValue* ComputedValue(Element* element, String property_name) {
+ CSSPropertyRef ref(property_name, GetDocument());
+ DCHECK(ref.IsValid());
+ return ref.GetProperty().CSSValueFromComputedStyle(
+ element->ComputedStyleRef(),
+ /* layout_object */ nullptr,
+ /* allow_visited_style */ false);
+ }
+
+ String ComputedValueString(Element* element, String property_name) {
+ if (const CSSValue* value = ComputedValue(element, property_name))
+ return value->CssText();
+ return g_null_atom;
+ }
};
TEST_F(ContainerQueryTest, PreludeParsing) {
@@ -195,4 +212,140 @@ TEST_F(ContainerQueryTest, QueriedAxes) {
EXPECT_EQ(none, QueriedAxes("(resolution: 150dpi)"));
}
+TEST_F(ContainerQueryTest, QueryZoom) {
+ GetFrame().SetPageZoomFactor(2.0f);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #container1 {
+ width: 100px;
+ height: 200px;
+ container-type: inline-size block-size;
+ }
+ #container2 {
+ width: 200px;
+ height: 400px;
+ container-type: inline-size block-size;
+ }
+ @container (width: 100px) {
+ div { --w100:1; }
+ }
+ @container (width: 200px) {
+ div { --w200:1; }
+ }
+ @container (height: 200px) {
+ div { --h200:1; }
+ }
+ @container (height: 400px) {
+ div { --h400:1; }
+ }
+ </style>
+ <div id=container1>
+ <div id=target1></div>
+ </div>
+ <div id=container2>
+ <div id=target2></div>
+ </div>
+ )HTML");
+
+ Element* target1 = GetDocument().getElementById("target1");
+ Element* target2 = GetDocument().getElementById("target2");
+ ASSERT_TRUE(target1);
+ ASSERT_TRUE(target2);
+
+ EXPECT_TRUE(target1->ComputedStyleRef().GetVariableData("--w100"));
+ EXPECT_TRUE(target1->ComputedStyleRef().GetVariableData("--h200"));
+ EXPECT_FALSE(target1->ComputedStyleRef().GetVariableData("--w200"));
+ EXPECT_FALSE(target1->ComputedStyleRef().GetVariableData("--h400"));
+
+ EXPECT_FALSE(target2->ComputedStyleRef().GetVariableData("--w100"));
+ EXPECT_FALSE(target2->ComputedStyleRef().GetVariableData("--h200"));
+ EXPECT_TRUE(target2->ComputedStyleRef().GetVariableData("--w200"));
+ EXPECT_TRUE(target2->ComputedStyleRef().GetVariableData("--h400"));
+}
+
+TEST_F(ContainerQueryTest, ContainerUnitsViewportFallback) {
+ using css_test_helpers::RegisterProperty;
+
+ ScopedCSSContainerRelativeUnitsForTest feature(true);
+
+ RegisterProperty(GetDocument(), "--qw", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--qi", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--qh", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--qb", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--qmin", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--qmax", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--fallback-w", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--fallback-h", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--fallback-min-qi-vh", "<length>", "0px",
+ false);
+ RegisterProperty(GetDocument(), "--fallback-min-qb-vw", "<length>", "0px",
+ false);
+ RegisterProperty(GetDocument(), "--fallback-max-qi-vh", "<length>", "0px",
+ false);
+ RegisterProperty(GetDocument(), "--fallback-max-qb-vw", "<length>", "0px",
+ false);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #inline, #block {
+ width: 100px;
+ height: 100px;
+ }
+ #inline {
+ container-type: inline-size;
+ }
+ #block {
+ container-type: block-size;
+ }
+ #inline_target, #block_target {
+ --qw: 10qw;
+ --qi: 10qi;
+ --qh: 10qh;
+ --qb: 10qb;
+ --qmin: 10qmin;
+ --qmax: 10qmax;
+ --fallback-w: 10vw;
+ --fallback-h: 10vh;
+ --fallback-min-qi-vh: min(10qi, 10vh);
+ --fallback-min-qb-vw: min(10qb, 10vw);
+ --fallback-max-qi-vh: max(10qi, 10vh);
+ --fallback-max-qb-vw: max(10qb, 10vw);
+ }
+ </style>
+ <div id=inline>
+ <div id="inline_target"></div>
+ </div>
+ <div id=block>
+ <div id="block_target"></div>
+ </div>
+ )HTML");
+
+ Element* inline_target = GetDocument().getElementById("inline_target");
+ ASSERT_TRUE(inline_target);
+ EXPECT_EQ(ComputedValueString(inline_target, "--qw"), "10px");
+ EXPECT_EQ(ComputedValueString(inline_target, "--qi"), "10px");
+ EXPECT_EQ(ComputedValueString(inline_target, "--qh"),
+ ComputedValueString(inline_target, "--fallback-h"));
+ EXPECT_EQ(ComputedValueString(inline_target, "--qb"),
+ ComputedValueString(inline_target, "--fallback-h"));
+ EXPECT_EQ(ComputedValueString(inline_target, "--qmin"),
+ ComputedValueString(inline_target, "--fallback-min-qi-vh"));
+ EXPECT_EQ(ComputedValueString(inline_target, "--qmax"),
+ ComputedValueString(inline_target, "--fallback-max-qi-vh"));
+
+ Element* block_target = GetDocument().getElementById("block_target");
+ ASSERT_TRUE(block_target);
+ EXPECT_EQ(ComputedValueString(block_target, "--qw"),
+ ComputedValueString(block_target, "--fallback-w"));
+ EXPECT_EQ(ComputedValueString(block_target, "--qi"),
+ ComputedValueString(block_target, "--fallback-w"));
+ EXPECT_EQ(ComputedValueString(block_target, "--qh"), "10px");
+ EXPECT_EQ(ComputedValueString(block_target, "--qb"), "10px");
+ EXPECT_EQ(ComputedValueString(block_target, "--qmin"),
+ ComputedValueString(block_target, "--fallback-min-qb-vw"));
+ EXPECT_EQ(ComputedValueString(block_target, "--qmax"),
+ ComputedValueString(block_target, "--fallback-max-qb-vw"));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/counter_style.cc b/chromium/third_party/blink/renderer/core/css/counter_style.cc
index b49e0fc43eb..15140d619b9 100644
--- a/chromium/third_party/blink/renderer/core/css/counter_style.cc
+++ b/chromium/third_party/blink/renderer/core/css/counter_style.cc
@@ -2,6 +2,31 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights
+ * reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ * Copyright (C) 2010 Daniel Bates (dbates@intudata.com)
+ *
+ * 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/css/counter_style.h"
#include "third_party/blink/renderer/core/css/counter_style_map.h"
@@ -12,7 +37,6 @@
#include "third_party/blink/renderer/core/css/css_value_pair.h"
#include "third_party/blink/renderer/core/css/style_rule_counter_style.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -85,7 +109,7 @@ Vector<wtf_size_t> CyclicAlgorithm(int value, wtf_size_t num_symbols) {
value -= 1;
if (value < 0)
value += num_symbols;
- return {value};
+ return {static_cast<wtf_size_t>(value)};
}
// https://drafts.csswg.org/css-counter-styles/#fixed-system
@@ -95,7 +119,7 @@ Vector<wtf_size_t> FixedAlgorithm(int value,
if (value < first_symbol_value ||
static_cast<unsigned>(value - first_symbol_value) >= num_symbols)
return Vector<wtf_size_t>();
- return {value - first_symbol_value};
+ return {static_cast<wtf_size_t>(value - first_symbol_value)};
}
// https://drafts.csswg.org/css-counter-styles/#symbolic-system
@@ -172,71 +196,295 @@ Vector<wtf_size_t> AdditiveAlgorithm(unsigned value,
return result;
}
-// TODO(crbug.com/687225): After @counter-style is shipped and the legacy
-// code paths are removed, remove everything else of list_marker_text and move
-// the implementation of the special algorithms here.
+enum CJKLang { kChinese = 1, kKorean, kJapanese };
+
+enum CJKStyle { kFormal, kInformal };
+
+// The table uses the order from the CSS3 specification:
+// first 3 group markers, then 3 digit markers, then ten digits.
+String CJKIdeoGraphicAlgorithm(unsigned number,
+ const UChar table[21],
+ CJKStyle cjk_style) {
+ enum AbstractCJKChar {
+ kNoChar = 0,
+ kLang = 0,
+ // FourthGroupMarker for simplified chinese has two codepoints, to simplify
+ // the main algorithm below use two codepoints for all group markers.
+ kSecondGroupMarker = 1,
+ kThirdGroupMarker = 3,
+ kFourthGroupMarker = 5,
+ kSecondDigitMarker = 7,
+ kThirdDigitMarker,
+ kFourthDigitMarker,
+ kDigit0,
+ kDigit1,
+ kDigit2,
+ kDigit3,
+ kDigit4,
+ kDigit5,
+ kDigit6,
+ kDigit7,
+ kDigit8,
+ kDigit9
+ };
+
+ if (number == 0)
+ return String(&table[kDigit0], 1u);
+
+ const unsigned kGroupLength =
+ 9; // 4 digits, 3 digit markers, group marker of size 2.
+ const unsigned kBufferLength = 4 * kGroupLength;
+ AbstractCJKChar buffer[kBufferLength] = {kNoChar};
+
+ for (unsigned i = 0; i < 4; ++i) {
+ unsigned group_value = number % 10000;
+ number /= 10000;
+
+ // Process least-significant group first, but put it in the buffer last.
+ AbstractCJKChar* group = &buffer[(3 - i) * kGroupLength];
+
+ if (group_value && i) {
+ group[8] = static_cast<AbstractCJKChar>(kSecondGroupMarker + i);
+ group[7] = static_cast<AbstractCJKChar>(kSecondGroupMarker - 1 + i);
+ }
-String HebrewAlgorithm(unsigned value) {
- if (value > 999999)
- return String();
- return list_marker_text::GetText(EListStyleType::kHebrew, value);
-}
+ // Put in the four digits and digit markers for any non-zero digits.
+ unsigned digit_value = (group_value % 10);
+ bool trailing_zero = table[kLang] == kChinese && !digit_value;
+ if (digit_value) {
+ bool drop_one = table[kLang] == kKorean && cjk_style == kInformal &&
+ digit_value == 1 && i > 0;
+ if (!drop_one)
+ group[6] = static_cast<AbstractCJKChar>(kDigit0 + (group_value % 10));
+ }
+ if (number != 0 || group_value > 9) {
+ digit_value = ((group_value / 10) % 10);
+ bool drop_one =
+ table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
+ if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
+ group[4] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
+ trailing_zero &= !digit_value;
+ if (digit_value)
+ group[5] = kSecondDigitMarker;
+ }
+ if (number != 0 || group_value > 99) {
+ digit_value = ((group_value / 100) % 10);
+ bool drop_one =
+ table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
+ if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
+ group[2] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
+ trailing_zero &= !digit_value;
+ if (digit_value)
+ group[3] = kThirdDigitMarker;
+ }
+ if (number != 0 || group_value > 999) {
+ digit_value = group_value / 1000;
+ bool drop_one =
+ table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
+ if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
+ group[0] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
+ if (digit_value)
+ group[1] = kFourthDigitMarker;
+ }
-int AbsoluteValueForLegacyCJKAlgorithms(int value) {
- // @counter-style algorithm works on absolute value, but the legacy
- // implementation works on the original value (and handles negative sign on
- // its own). Clamp to the signed int range before proceeding.
- if (UNLIKELY(value == std::numeric_limits<int>::min()))
- return std::numeric_limits<int>::max();
- else
- return std::abs(value);
-}
+ if (trailing_zero && i > 0) {
+ group[6] = group[7];
+ group[7] = group[8];
+ group[8] = kDigit0;
+ }
-String SimpChineseInformalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kSimpChineseInformal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
-}
+ // Remove the tens digit, but leave the marker, for any group that has
+ // a value of less than 20.
+ if (table[kLang] == kChinese && cjk_style == kInformal &&
+ group_value < 20) {
+ DCHECK(group[4] == kNoChar || group[4] == kDigit0 || group[4] == kDigit1);
+ group[4] = kNoChar;
+ }
-String SimpChineseFormalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kSimpChineseFormal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
-}
+ if (number == 0)
+ break;
+ }
-String TradChineseInformalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kTradChineseInformal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
+ // Convert into characters, omitting consecutive runs of Digit0 and
+ // any trailing Digit0.
+ unsigned length = 0;
+ UChar characters[kBufferLength];
+ AbstractCJKChar last = kNoChar;
+ for (unsigned i = 0; i < kBufferLength; ++i) {
+ AbstractCJKChar a = buffer[i];
+ if (a != kNoChar) {
+ if (a != kDigit0 || (table[kLang] == kChinese && last != kDigit0)) {
+ UChar new_char = table[a];
+ if (new_char != kNoChar) {
+ characters[length++] = table[a];
+ if (table[kLang] == kKorean &&
+ (a == kSecondGroupMarker || a == kThirdGroupMarker ||
+ a == kFourthGroupMarker))
+ characters[length++] = ' ';
+ }
+ }
+ last = a;
+ }
+ }
+ if ((table[kLang] == kChinese && last == kDigit0) ||
+ characters[length - 1] == ' ')
+ --length;
+
+ return String(characters, length);
+}
+
+String SimpChineseInformalAlgorithm(unsigned value) {
+ static const UChar kSimpleChineseInformalTable[21] = {
+ kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF,
+ 0x5341, 0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09,
+ 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kSimpleChineseInformalTable, kInformal);
+}
+
+String SimpChineseFormalAlgorithm(unsigned value) {
+ static const UChar kSimpleChineseFormalTable[21] = {
+ kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF,
+ 0x62FE, 0x4F70, 0x4EDF, 0x96F6, 0x58F9, 0x8D30, 0x53C1,
+ 0x8086, 0x4F0D, 0x9646, 0x67D2, 0x634C, 0x7396, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kSimpleChineseFormalTable, kFormal);
+}
+
+String TradChineseInformalAlgorithm(unsigned value) {
+ static const UChar kTraditionalChineseInformalTable[21] = {
+ kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
+ 0x5341, 0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09,
+ 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kTraditionalChineseInformalTable,
+ kInformal);
+}
+
+String TradChineseFormalAlgorithm(unsigned value) {
+ static const UChar kTraditionalChineseFormalTable[21] = {
+ kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
+ 0x62FE, 0x4F70, 0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3,
+ 0x8086, 0x4F0D, 0x9678, 0x67D2, 0x634C, 0x7396, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kTraditionalChineseFormalTable,
+ kFormal);
+}
+
+String KoreanHangulFormalAlgorithm(unsigned value) {
+ static const UChar kKoreanHangulFormalTable[21] = {
+ kKorean, 0xB9CC, 0x0000, 0xC5B5, 0x0000, 0xC870, 0x0000,
+ 0xC2ED, 0xBC31, 0xCC9C, 0xC601, 0xC77C, 0xC774, 0xC0BC,
+ 0xC0AC, 0xC624, 0xC721, 0xCE60, 0xD314, 0xAD6C, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kKoreanHangulFormalTable, kFormal);
+}
+
+String KoreanHanjaInformalAlgorithm(unsigned value) {
+ static const UChar kKoreanHanjaInformalTable[21] = {
+ kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
+ 0x5341, 0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09,
+ 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kKoreanHanjaInformalTable, kInformal);
+}
+
+String KoreanHanjaFormalAlgorithm(unsigned value) {
+ static const UChar kKoreanHanjaFormalTable[21] = {
+ kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
+ 0x62FE, 0x767E, 0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3,
+ 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x0000};
+ return CJKIdeoGraphicAlgorithm(value, kKoreanHanjaFormalTable, kFormal);
+}
+
+String HebrewAlgorithmUnder1000(unsigned number) {
+ // FIXME: CSS3 mentions various refinements not implemented here.
+ // FIXME: Should take a look at Mozilla's HebrewToText function (in
+ // CounterStyleManager.cpp).
+ DCHECK_LT(number, 1000u);
+ StringBuilder letters;
+ unsigned four_hundreds = number / 400;
+ for (unsigned i = 0; i < four_hundreds; i++) {
+ letters.Append(static_cast<UChar>(1511 + 3));
+ }
+ number %= 400;
+ if (number / 100)
+ letters.Append(static_cast<UChar>(1511 + (number / 100) - 1));
+ number %= 100;
+ if (number == 15 || number == 16) {
+ letters.Append(static_cast<UChar>(1487 + 9));
+ letters.Append(static_cast<UChar>(1487 + number - 9));
+ } else {
+ if (unsigned tens = number / 10) {
+ static const UChar kHebrewTens[9] = {1497, 1499, 1500, 1502, 1504,
+ 1505, 1506, 1508, 1510};
+ letters.Append(kHebrewTens[tens - 1]);
+ }
+ if (unsigned ones = number % 10)
+ letters.Append(static_cast<UChar>(1487 + ones));
+ }
+ return letters.ToString();
}
-String TradChineseFormalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kTradChineseFormal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
-}
+String HebrewAlgorithm(unsigned number) {
+ // FIXME: CSS3 mentions ways to make this work for much larger numbers.
+ if (number > 999999)
+ return String();
-String KoreanHangulFormalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kKoreanHangulFormal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
-}
+ if (number == 0) {
+ static const UChar kHebrewZero[3] = {0x05D0, 0x05E4, 0x05E1};
+ return String(kHebrewZero, 3u);
+ }
-String KoreanHanjaInformalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kKoreanHanjaInformal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
-}
+ if (number <= 999)
+ return HebrewAlgorithmUnder1000(number);
-String KoreanHanjaFormalAlgorithm(int value) {
- return list_marker_text::GetText(EListStyleType::kKoreanHanjaFormal,
- AbsoluteValueForLegacyCJKAlgorithms(value));
+ return HebrewAlgorithmUnder1000(number / 1000) +
+ kHebrewPunctuationGereshCharacter +
+ HebrewAlgorithmUnder1000(number % 1000);
}
-String LowerArmenianAlgorithm(unsigned value) {
- if (value > 99999999)
- return String();
- return list_marker_text::GetText(EListStyleType::kLowerArmenian, value);
+String ArmenianAlgorithmUnder10000(unsigned number,
+ bool upper,
+ bool add_circumflex) {
+ DCHECK_LT(number, 10000u);
+ StringBuilder letters;
+
+ unsigned lower_offset = upper ? 0 : 0x0030;
+
+ if (unsigned thousands = number / 1000) {
+ if (thousands == 7) {
+ letters.Append(static_cast<UChar>(0x0552 + lower_offset));
+ if (add_circumflex)
+ letters.Append(static_cast<UChar>(0x0302));
+ } else {
+ letters.Append(
+ static_cast<UChar>((0x054C - 1 + lower_offset) + thousands));
+ if (add_circumflex)
+ letters.Append(static_cast<UChar>(0x0302));
+ }
+ }
+
+ if (unsigned hundreds = (number / 100) % 10) {
+ letters.Append(static_cast<UChar>((0x0543 - 1 + lower_offset) + hundreds));
+ if (add_circumflex)
+ letters.Append(static_cast<UChar>(0x0302));
+ }
+
+ if (unsigned tens = (number / 10) % 10) {
+ letters.Append(static_cast<UChar>((0x053A - 1 + lower_offset) + tens));
+ if (add_circumflex)
+ letters.Append(static_cast<UChar>(0x0302));
+ }
+
+ if (unsigned ones = number % 10) {
+ letters.Append(static_cast<UChar>((0x531 - 1 + lower_offset) + ones));
+ if (add_circumflex)
+ letters.Append(static_cast<UChar>(0x0302));
+ }
+
+ return letters.ToString();
}
-String UpperArmenianAlgorithm(unsigned value) {
- if (value > 99999999)
+String ArmenianAlgorithm(unsigned number, bool upper) {
+ if (!number || number > 99999999)
return String();
- return list_marker_text::GetText(EListStyleType::kUpperArmenian, value);
+ return ArmenianAlgorithmUnder10000(number / 10000, upper, true) +
+ ArmenianAlgorithmUnder10000(number % 10000, upper, false);
}
// https://drafts.csswg.org/css-counter-styles-3/#ethiopic-numeric-counter-style
@@ -250,7 +498,7 @@ String EthiopicNumericAlgorithm(unsigned value) {
if (!value)
return String();
if (value < 10u)
- return String(&units[value - 1], 1);
+ return String(&units[value - 1], 1u);
// Generate characters in the reversed ordering
Vector<UChar> result;
@@ -354,6 +602,24 @@ CounterStyleSystem CounterStyle::ToCounterStyleSystemEnum(
}
}
+// static
+CounterStyleSpeakAs ToCounterStyleSpeakAsEnum(
+ const CSSIdentifierValue& keyword) {
+ switch (keyword.GetValueID()) {
+ case CSSValueID::kAuto:
+ return CounterStyleSpeakAs::kAuto;
+ case CSSValueID::kBullets:
+ return CounterStyleSpeakAs::kBullets;
+ case CSSValueID::kNumbers:
+ return CounterStyleSpeakAs::kNumbers;
+ case CSSValueID::kWords:
+ return CounterStyleSpeakAs::kWords;
+ default:
+ NOTREACHED();
+ return CounterStyleSpeakAs::kAuto;
+ }
+}
+
CounterStyle::~CounterStyle() = default;
AtomicString CounterStyle::GetName() const {
@@ -430,7 +696,17 @@ CounterStyle::CounterStyle(const StyleRuleCounterStyle& rule)
if (const CSSValue* suffix = rule.GetSuffix())
suffix_ = SymbolToString(*suffix);
- // TODO(crbug.com/1166766): Implement 'speak-as'.
+ if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleSpeakAsDescriptorEnabled()) {
+ if (const CSSValue* speak_as = rule.GetSpeakAs()) {
+ if (const auto* keyword = DynamicTo<CSSIdentifierValue>(speak_as)) {
+ speak_as_ = ToCounterStyleSpeakAsEnum(*keyword);
+ } else {
+ DCHECK(speak_as->IsCustomIdentValue());
+ speak_as_ = CounterStyleSpeakAs::kReference;
+ speak_as_name_ = To<CSSCustomIdentValue>(speak_as)->Value();
+ }
+ }
+ }
}
void CounterStyle::ResolveExtends(CounterStyle& extended) {
@@ -469,7 +745,13 @@ void CounterStyle::ResolveExtends(CounterStyle& extended) {
if (!style_rule_->GetSuffix())
suffix_ = extended.suffix_;
- // TODO(crbug.com/1166766): Implement 'speak-as'.
+ if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleSpeakAsDescriptorEnabled()) {
+ if (!style_rule_->GetSpeakAs()) {
+ speak_as_ = extended.speak_as_;
+ speak_as_name_ = extended.speak_as_name_;
+ speak_as_style_ = nullptr;
+ }
+ }
}
bool CounterStyle::RangeContains(int value) const {
@@ -504,7 +786,7 @@ bool CounterStyle::RangeContains(int value) const {
return value >= 0 && value <= 999999;
case CounterStyleSystem::kLowerArmenian:
case CounterStyleSystem::kUpperArmenian:
- return value >= 0 && value <= 99999999;
+ return value >= 1 && value <= 99999999;
case CounterStyleSystem::kUnresolvedExtends:
NOTREACHED();
return false;
@@ -612,23 +894,27 @@ String CounterStyle::GenerateInitialRepresentation(int value) const {
case CounterStyleSystem::kHebrew:
return HebrewAlgorithm(abs_value);
case CounterStyleSystem::kSimpChineseInformal:
- return SimpChineseInformalAlgorithm(value);
+ return SimpChineseInformalAlgorithm(abs_value);
case CounterStyleSystem::kSimpChineseFormal:
- return SimpChineseFormalAlgorithm(value);
+ return SimpChineseFormalAlgorithm(abs_value);
case CounterStyleSystem::kTradChineseInformal:
- return TradChineseInformalAlgorithm(value);
+ return TradChineseInformalAlgorithm(abs_value);
case CounterStyleSystem::kTradChineseFormal:
- return TradChineseFormalAlgorithm(value);
+ return TradChineseFormalAlgorithm(abs_value);
case CounterStyleSystem::kKoreanHangulFormal:
- return KoreanHangulFormalAlgorithm(value);
+ return KoreanHangulFormalAlgorithm(abs_value);
case CounterStyleSystem::kKoreanHanjaInformal:
- return KoreanHanjaInformalAlgorithm(value);
+ return KoreanHanjaInformalAlgorithm(abs_value);
case CounterStyleSystem::kKoreanHanjaFormal:
- return KoreanHanjaFormalAlgorithm(value);
- case CounterStyleSystem::kLowerArmenian:
- return LowerArmenianAlgorithm(abs_value);
- case CounterStyleSystem::kUpperArmenian:
- return UpperArmenianAlgorithm(abs_value);
+ return KoreanHanjaFormalAlgorithm(abs_value);
+ case CounterStyleSystem::kLowerArmenian: {
+ const bool lower_case = false;
+ return ArmenianAlgorithm(abs_value, lower_case);
+ }
+ case CounterStyleSystem::kUpperArmenian: {
+ const bool upper_case = true;
+ return ArmenianAlgorithm(abs_value, upper_case);
+ }
case CounterStyleSystem::kEthiopicNumeric:
return EthiopicNumericAlgorithm(abs_value);
case CounterStyleSystem::kUnresolvedExtends:
@@ -681,6 +967,7 @@ void CounterStyle::Trace(Visitor* visitor) const {
visitor->Trace(style_rule_);
visitor->Trace(extended_style_);
visitor->Trace(fallback_style_);
+ visitor->Trace(speak_as_style_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/counter_style.h b/chromium/third_party/blink/renderer/core/css/counter_style.h
index 7dc26c957f8..1b82026fb3d 100644
--- a/chromium/third_party/blink/renderer/core/css/counter_style.h
+++ b/chromium/third_party/blink/renderer/core/css/counter_style.h
@@ -35,6 +35,14 @@ enum class CounterStyleSystem {
kUnresolvedExtends,
};
+enum class CounterStyleSpeakAs {
+ kAuto,
+ kBullets,
+ kNumbers,
+ kWords,
+ kReference,
+};
+
// Represents a valid counter style defined in a tree scope.
class CORE_EXPORT CounterStyle final : public GarbageCollected<CounterStyle> {
public:
@@ -68,8 +76,8 @@ class CORE_EXPORT CounterStyle final : public GarbageCollected<CounterStyle> {
void TraverseAndMarkDirtyIfNeeded(HeapHashSet<Member<CounterStyle>>& visited);
- // Set to true when there's no counter style matching 'extends' or 'fallback',
- // and therefore we are resorting to 'decimal'.
+ // Set to true when there's no counter style matching 'extends', 'fallback' or
+ // 'speak-as', so this style must be dirtied when new styles are added.
void SetHasInexistentReferences() { has_inexistent_references_ = true; }
// https://drafts.csswg.org/css-counter-styles/#generate-a-counter
@@ -90,6 +98,24 @@ class CORE_EXPORT CounterStyle final : public GarbageCollected<CounterStyle> {
bool HasUnresolvedFallback() const { return !fallback_style_; }
void ResolveFallback(CounterStyle& fallback) { fallback_style_ = &fallback; }
+ CounterStyleSpeakAs GetSpeakAs() const { return speak_as_; }
+ AtomicString GetSpeakAsName() const { return speak_as_name_; }
+ bool HasUnresolvedSpeakAsReference() const {
+ return speak_as_ == CounterStyleSpeakAs::kReference && !speak_as_style_;
+ }
+ void ResolveInvalidSpeakAsReference() {
+ speak_as_ = CounterStyleSpeakAs::kAuto;
+ speak_as_style_ = nullptr;
+ }
+ void ResolveSpeakAsReference(CounterStyle& speak_as) {
+ DCHECK_NE(CounterStyleSpeakAs::kReference, speak_as.speak_as_);
+ speak_as_style_ = speak_as;
+ }
+ const CounterStyle& GetSpeakAsStyle() const {
+ DCHECK_EQ(CounterStyleSpeakAs::kReference, speak_as_);
+ return *speak_as_style_;
+ }
+
void Trace(Visitor*) const;
explicit CounterStyle(const StyleRuleCounterStyle& rule);
@@ -130,6 +156,12 @@ class CORE_EXPORT CounterStyle final : public GarbageCollected<CounterStyle> {
AtomicString fallback_name_ = "decimal";
Member<CounterStyle> fallback_style_;
+ CounterStyleSpeakAs speak_as_ = CounterStyleSpeakAs::kAuto;
+
+ // These two members are set if 'speak-as' references another counter style.
+ AtomicString speak_as_name_;
+ Member<CounterStyle> speak_as_style_;
+
// True if we are looking for a fallback counter style to generate a counter
// value. Supports cycle detection in fallback.
mutable bool is_in_fallback_ = false;
diff --git a/chromium/third_party/blink/renderer/core/css/counter_style_map.cc b/chromium/third_party/blink/renderer/core/css/counter_style_map.cc
index c9c826f97ba..31d7c9f9844 100644
--- a/chromium/third_party/blink/renderer/core/css/counter_style_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/counter_style_map.cc
@@ -59,7 +59,7 @@ void CounterStyleMap::AddCounterStyles(const RuleSet& rule_set) {
if (!counter_style)
continue;
AtomicString name = rule->GetName();
- if (CounterStyle* replaced = counter_styles_.at(name))
+ if (CounterStyle* replaced = counter_styles_.DeprecatedAtOrEmptyValue(name))
replaced->SetIsDirty();
counter_styles_.Set(rule->GetName(), counter_style);
}
@@ -100,7 +100,7 @@ CounterStyle* CounterStyleMap::FindCounterStyleAcrossScopes(
return &const_cast<CounterStyleMap*>(this)->CreateUACounterStyle(name);
}
- if (CounterStyle* style = counter_styles_.at(name))
+ if (CounterStyle* style = counter_styles_.DeprecatedAtOrEmptyValue(name))
return style;
return GetAncestorMap()->FindCounterStyleAcrossScopes(name);
}
@@ -172,6 +172,43 @@ void CounterStyleMap::ResolveFallbackFor(CounterStyle& counter_style) {
}
}
+void CounterStyleMap::ResolveSpeakAsReferenceFor(CounterStyle& counter_style) {
+ DCHECK(counter_style.HasUnresolvedSpeakAsReference());
+
+ HeapVector<Member<CounterStyle>, 2> speak_as_chain;
+ HeapHashSet<Member<CounterStyle>> unresolved_styles;
+ speak_as_chain.push_back(&counter_style);
+ do {
+ unresolved_styles.insert(speak_as_chain.back());
+ AtomicString speak_as_name = speak_as_chain.back()->GetSpeakAsName();
+ speak_as_chain.push_back(FindCounterStyleAcrossScopes(speak_as_name));
+ } while (speak_as_chain.back() &&
+ speak_as_chain.back()->HasUnresolvedSpeakAsReference() &&
+ !unresolved_styles.Contains(speak_as_chain.back()));
+
+ if (!speak_as_chain.back()) {
+ // If the specified style does not exist, this value is treated as 'auto'.
+ DCHECK_GE(speak_as_chain.size(), 2u);
+ speak_as_chain.pop_back();
+ speak_as_chain.back()->ResolveInvalidSpeakAsReference();
+ speak_as_chain.back()->SetHasInexistentReferences();
+ } else if (speak_as_chain.back()->HasUnresolvedSpeakAsReference()) {
+ // If a loop is detected when following 'speak-as' references, this value is
+ // treated as 'auto' for the counter styles participating in the loop.
+ CounterStyle* cycle_start = speak_as_chain.back();
+ do {
+ speak_as_chain.back()->ResolveInvalidSpeakAsReference();
+ speak_as_chain.pop_back();
+ } while (speak_as_chain.back() != cycle_start);
+ }
+
+ CounterStyle* back = speak_as_chain.back();
+ while (speak_as_chain.size() > 1u) {
+ speak_as_chain.pop_back();
+ speak_as_chain.back()->ResolveSpeakAsReference(*back);
+ }
+}
+
void CounterStyleMap::ResolveReferences(
HeapHashSet<Member<CounterStyleMap>>& visited_maps) {
if (visited_maps.Contains(this))
@@ -187,6 +224,11 @@ void CounterStyleMap::ResolveReferences(
ResolveExtendsFor(*counter_style);
if (counter_style->HasUnresolvedFallback())
ResolveFallbackFor(*counter_style);
+ if (RuntimeEnabledFeatures::
+ CSSAtRuleCounterStyleSpeakAsDescriptorEnabled()) {
+ if (counter_style->HasUnresolvedSpeakAsReference())
+ ResolveSpeakAsReferenceFor(*counter_style);
+ }
}
}
@@ -255,6 +297,7 @@ void CounterStyleMap::ResolveAllReferences(
DCHECK(!counter_style->IsDirty());
DCHECK(!counter_style->HasUnresolvedExtends());
DCHECK(!counter_style->HasUnresolvedFallback());
+ DCHECK(!counter_style->HasUnresolvedSpeakAsReference());
}
#endif
}
diff --git a/chromium/third_party/blink/renderer/core/css/counter_style_map.h b/chromium/third_party/blink/renderer/core/css/counter_style_map.h
index 276f3e9a94b..226a851ff03 100644
--- a/chromium/third_party/blink/renderer/core/css/counter_style_map.h
+++ b/chromium/third_party/blink/renderer/core/css/counter_style_map.h
@@ -48,6 +48,7 @@ class CORE_EXPORT CounterStyleMap : public GarbageCollected<CounterStyleMap> {
void ResolveExtendsFor(CounterStyle&);
void ResolveFallbackFor(CounterStyle&);
+ void ResolveSpeakAsReferenceFor(CounterStyle&);
static CounterStyleMap* CreateUACounterStyleMap();
CounterStyle& CreateUACounterStyle(const AtomicString& name);
diff --git a/chromium/third_party/blink/renderer/core/css/counter_style_map_test.cc b/chromium/third_party/blink/renderer/core/css/counter_style_map_test.cc
index 99dbdff24e8..1bc40f12b94 100644
--- a/chromium/third_party/blink/renderer/core/css/counter_style_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/counter_style_map_test.cc
@@ -13,12 +13,9 @@ namespace blink {
class CounterStyleMapTest
: public PageTestBase,
- private ScopedCSSAtRuleCounterStyleForTest,
private ScopedCSSAtRuleCounterStyleInShadowDOMForTest {
public:
- CounterStyleMapTest()
- : ScopedCSSAtRuleCounterStyleForTest(true),
- ScopedCSSAtRuleCounterStyleInShadowDOMForTest(true) {}
+ CounterStyleMapTest() : ScopedCSSAtRuleCounterStyleInShadowDOMForTest(true) {}
ShadowRoot& AttachShadowTo(const char* host_id) {
Element* host = GetElementById(host_id);
@@ -205,4 +202,86 @@ TEST_F(CounterStyleMapTest, UpdateReferencesInChildScope) {
EXPECT_EQ("decimal", new_bar.GetExtendedStyle().GetName());
}
+TEST_F(CounterStyleMapTest, SpeakAsKeywords) {
+ ScopedCSSAtRuleCounterStyleSpeakAsDescriptorForTest enabled(true);
+
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ @counter-style implicit-auto { symbols: 'X'; }
+ @counter-style explicit-auto { speak-as: auto; symbols: 'X'; }
+ @counter-style bullets { speak-as: bullets; symbols: 'X'; }
+ @counter-style numbers { speak-as: numbers; symbols: 'X'; }
+ @counter-style words { speak-as: words; symbols: 'X'; }
+ </style>
+ )HTML");
+
+ const CounterStyle& implicit_auto =
+ GetCounterStyle(GetDocument(), "implicit-auto");
+ EXPECT_EQ(CounterStyleSpeakAs::kAuto, implicit_auto.GetSpeakAs());
+
+ const CounterStyle& explicit_auto =
+ GetCounterStyle(GetDocument(), "explicit-auto");
+ EXPECT_EQ(CounterStyleSpeakAs::kAuto, explicit_auto.GetSpeakAs());
+
+ const CounterStyle& bullets = GetCounterStyle(GetDocument(), "bullets");
+ EXPECT_EQ(CounterStyleSpeakAs::kBullets, bullets.GetSpeakAs());
+
+ const CounterStyle& numbers = GetCounterStyle(GetDocument(), "numbers");
+ EXPECT_EQ(CounterStyleSpeakAs::kNumbers, numbers.GetSpeakAs());
+
+ const CounterStyle& words = GetCounterStyle(GetDocument(), "words");
+ EXPECT_EQ(CounterStyleSpeakAs::kWords, words.GetSpeakAs());
+}
+
+TEST_F(CounterStyleMapTest, SpeakAsReference) {
+ ScopedCSSAtRuleCounterStyleSpeakAsDescriptorForTest enabled(true);
+
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ @counter-style base { symbols: 'X'; }
+ @counter-style valid-author-ref { speak-as: base; symbols: 'X'; }
+ @counter-style valid-ua-ref { speak-as: disc; symbols: 'X'; }
+ @counter-style invalid { speak-as: unknown; symbols: 'X'; }
+ </style>
+ )HTML");
+
+ const CounterStyle& valid_author_ref =
+ GetCounterStyle(GetDocument(), "valid-author-ref");
+ EXPECT_EQ(CounterStyleSpeakAs::kReference, valid_author_ref.GetSpeakAs());
+ EXPECT_EQ("base", valid_author_ref.GetSpeakAsStyle().GetName());
+
+ const CounterStyle& valid_ua_ref =
+ GetCounterStyle(GetDocument(), "valid-ua-ref");
+ EXPECT_EQ(CounterStyleSpeakAs::kReference, valid_ua_ref.GetSpeakAs());
+ EXPECT_EQ("disc", valid_ua_ref.GetSpeakAsStyle().GetName());
+
+ // Invalid 'speak-as' reference will be treated as 'speak-as: auto'.
+ const CounterStyle& invalid = GetCounterStyle(GetDocument(), "invalid");
+ EXPECT_EQ(CounterStyleSpeakAs::kAuto, invalid.GetSpeakAs());
+}
+
+TEST_F(CounterStyleMapTest, SpeakAsReferenceLoop) {
+ ScopedCSSAtRuleCounterStyleSpeakAsDescriptorForTest enabled(true);
+
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ @counter-style a { speak-as: b; symbols: 'X'; }
+ @counter-style b { speak-as: a; symbols: 'X'; }
+ @counter-style c { speak-as: b; symbols: 'X'; }
+ </style>
+ )HTML");
+
+ const CounterStyle& a = GetCounterStyle(GetDocument(), "a");
+ const CounterStyle& b = GetCounterStyle(GetDocument(), "b");
+ const CounterStyle& c = GetCounterStyle(GetDocument(), "c");
+
+ // Counter styles on a 'speak-as' loop will be treated as 'speak-as: auto'.
+ EXPECT_EQ(CounterStyleSpeakAs::kAuto, a.GetSpeakAs());
+ EXPECT_EQ(CounterStyleSpeakAs::kAuto, b.GetSpeakAs());
+
+ // c is not on the loop, so its reference remains valid.
+ EXPECT_EQ(CounterStyleSpeakAs::kReference, c.GetSpeakAs());
+ EXPECT_EQ(&b, &c.GetSpeakAsStyle());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/counter_style_test.cc b/chromium/third_party/blink/renderer/core/css/counter_style_test.cc
index a7606551b2a..8cbcbcd6567 100644
--- a/chromium/third_party/blink/renderer/core/css/counter_style_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/counter_style_test.cc
@@ -8,14 +8,11 @@
#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/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
-class CounterStyleTest : public PageTestBase,
- private ScopedCSSAtRuleCounterStyleForTest {
- public:
- CounterStyleTest() : ScopedCSSAtRuleCounterStyleForTest(true) {}
-
+class CounterStyleTest : public PageTestBase {
protected:
const CounterStyle& GetCounterStyle(const AtomicString& name) {
if (const CounterStyleMap* document_map =
@@ -508,6 +505,42 @@ TEST_F(CounterStyleTest, UpperArmenian) {
}
}
+TEST_F(CounterStyleTest, ExtendArmenianRangeToIncludeZero) {
+ // 'lower-armenian' and 'upper-armenian' counter styles cannot represent 0.
+ // Even if we extend them to include 0 into the range, we still fall back.
+ const CounterStyle& extends_lower_armenian =
+ AddCounterStyle("extends-lower-armenian", R"CSS(
+ system: extends lower-armenian;
+ range: 0 infinity;
+ )CSS");
+ EXPECT_EQ("0", extends_lower_armenian.GenerateRepresentation(0));
+
+ const CounterStyle& extends_upper_armenian =
+ AddCounterStyle("extends-upper-armenian", R"CSS(
+ system: extends upper-armenian;
+ range: 0 infinity;
+ )CSS");
+ EXPECT_EQ("0", extends_upper_armenian.GenerateRepresentation(0));
+}
+
+TEST_F(CounterStyleTest, ExtendArmenianRangeToAuto) {
+ // 'lower-armenian' and 'upper-armenian' counter styles cannot represent 0,
+ // even if we extend their range to 'auto'.
+ const CounterStyle& extends_lower_armenian =
+ AddCounterStyle("extends-lower-armenian", R"CSS(
+ system: extends lower-armenian;
+ range: auto;
+ )CSS");
+ EXPECT_EQ("0", extends_lower_armenian.GenerateRepresentation(0));
+
+ const CounterStyle& extends_upper_armenian =
+ AddCounterStyle("extends-upper-armenian", R"CSS(
+ system: extends upper-armenian;
+ range: 0 auto;
+ )CSS");
+ EXPECT_EQ("0", extends_upper_armenian.GenerateRepresentation(0));
+}
+
TEST_F(CounterStyleTest, KoreanHangulFormal) {
// Verifies that our 'korean-hangul-formal' implementation matches the spec in
// the officially specified range 1-9999.
diff --git a/chromium/third_party/blink/renderer/core/css/css.dict b/chromium/third_party/blink/renderer/core/css/css.dict
index bc5274c9e7c..3cd35b83ea0 100644
--- a/chromium/third_party/blink/renderer/core/css/css.dict
+++ b/chromium/third_party/blink/renderer/core/css/css.dict
@@ -927,7 +927,7 @@
"hidden-matchable"
"more"
"less"
-"forced"
+"custom"
# at-rules
"@charset"
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 366573c5f26..f6d57c7b01c 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,7 @@
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
@@ -74,21 +74,6 @@ void LogUnimplementedPropertyID(const CSSProperty& property) {
<< property.GetPropertyName() << "'.";
}
-// TODO(crbug.com/1167696): We probably want to avoid doing this for
-// performance reasons.
-bool InclusiveAncestorMayDependOnContainerQueries(Node* node) {
- if (!RuntimeEnabledFeatures::CSSContainerQueriesEnabled())
- return false;
- for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*node)) {
- const ComputedStyle* style = ancestor.GetComputedStyle();
- // Since DependsOnContainerQueries is stored on ComputedStyle, we have to
- // behave as if the flag is set for nullptr-styles (display:none).
- if (!style || style->DependsOnContainerQueries())
- return true;
- }
- return false;
-}
-
} // namespace
const Vector<const CSSProperty*>&
@@ -179,6 +164,19 @@ const ComputedStyle* CSSComputedStyleDeclaration::ComputeComputedStyle() const {
return style;
}
+const Vector<AtomicString>* CSSComputedStyleDeclaration::GetVariableNames()
+ const {
+ if (auto* style = ComputeComputedStyle())
+ return &style->GetVariableNames();
+ return nullptr;
+}
+
+wtf_size_t CSSComputedStyleDeclaration::GetVariableNamesCount() const {
+ if (auto* style = ComputeComputedStyle())
+ return style->GetVariableNamesCount();
+ return 0;
+}
+
Node* CSSComputedStyleDeclaration::StyledNode() const {
if (!node_)
return nullptr;
@@ -247,8 +245,7 @@ void CSSComputedStyleDeclaration::UpdateStyleAndLayoutTreeIfNeeded(
bool is_for_layout_dependent_property =
property_name && !property_name->IsCustomProperty() &&
CSSProperty::Get(property_name->Id()).IsLayoutDependentProperty();
- if (is_for_layout_dependent_property ||
- document.GetStyleEngine().HasViewportDependentMediaQueries()) {
+ if (is_for_layout_dependent_property) {
owner->GetDocument().UpdateStyleAndLayout(
DocumentUpdateReason::kJavaScript);
// The style recalc could have caused the styled node to be discarded or
@@ -270,8 +267,7 @@ void CSSComputedStyleDeclaration::UpdateStyleAndLayoutIfNeeded(
property &&
property->IsLayoutDependent(ComputeComputedStyle(), StyledLayoutObject());
- if (is_for_layout_dependent_property ||
- InclusiveAncestorMayDependOnContainerQueries(styled_node)) {
+ if (is_for_layout_dependent_property) {
styled_node->GetDocument().UpdateStyleAndLayoutForNode(
styled_node, DocumentUpdateReason::kJavaScript);
}
@@ -317,15 +313,33 @@ String CSSComputedStyleDeclaration::GetPropertyValue(
unsigned CSSComputedStyleDeclaration::length() const {
if (!node_ || !node_->InActiveDocument())
return 0;
- return ComputableProperties(GetExecutionContext()).size();
+
+ wtf_size_t variable_count = 0;
+
+ if (RuntimeEnabledFeatures::CSSEnumeratedCustomPropertiesEnabled()) {
+ UpdateStyleAndLayoutTreeIfNeeded(nullptr /* property_name */);
+ UpdateStyleAndLayoutIfNeeded(nullptr /* property */);
+ variable_count = GetVariableNamesCount();
+ }
+
+ return ComputableProperties(GetExecutionContext()).size() + variable_count;
}
String CSSComputedStyleDeclaration::item(unsigned i) const {
if (i >= length())
return "";
- return ComputableProperties(GetExecutionContext())[i]
- ->GetPropertyNameString();
+ const auto& standard_names = ComputableProperties(GetExecutionContext());
+
+ if (i < standard_names.size())
+ return standard_names[i]->GetPropertyNameString();
+
+ DCHECK(RuntimeEnabledFeatures::CSSEnumeratedCustomPropertiesEnabled());
+ DCHECK(GetVariableNames());
+ const auto& variable_names = *GetVariableNames();
+ CHECK_LT(i - standard_names.size(), variable_names.size());
+
+ return variable_names[i - standard_names.size()];
}
bool CSSComputedStyleDeclaration::CssPropertyMatches(
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 fc65ad0b355..635b5027c2e 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
@@ -94,6 +94,8 @@ class CORE_EXPORT CSSComputedStyleDeclaration final
// CSSOM functions.
CSSRule* parentRule() const override;
const ComputedStyle* ComputeComputedStyle() const;
+ const Vector<AtomicString>* GetVariableNames() const;
+ wtf_size_t GetVariableNamesCount() const;
String getPropertyValue(const String& property_name) override;
String getPropertyPriority(const String& property_name) override;
String GetPropertyShorthand(const String& property_name) override;
diff --git a/chromium/third_party/blink/renderer/core/css/css_container_rule.cc b/chromium/third_party/blink/renderer/core/css/css_container_rule.cc
index 1dd370f41dc..38d3108a75f 100644
--- a/chromium/third_party/blink/renderer/core/css/css_container_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_container_rule.cc
@@ -16,9 +16,50 @@ CSSContainerRule::CSSContainerRule(StyleRuleContainer* container_rule,
CSSContainerRule::~CSSContainerRule() = default;
String CSSContainerRule::cssText() const {
- // TODO(crbug.com/1145970): Spec and implement serialization.
- NOTIMPLEMENTED();
- return "";
+ StringBuilder result;
+ result.Append("@container ");
+ if (!Name().IsNull()) {
+ result.Append(Name());
+ result.Append(' ');
+ }
+ if (ContainerQueries()) {
+ result.Append(ContainerQueries()->MediaText());
+ result.Append(' ');
+ }
+ result.Append("{\n");
+ AppendCSSTextForItems(result);
+ result.Append('}');
+ return result.ToString();
}
+scoped_refptr<MediaQuerySet> CSSContainerRule::ContainerQueries() const {
+ return To<StyleRuleContainer>(group_rule_.Get())
+ ->GetContainerQuery()
+ .MediaQueries();
+}
+
+MediaList* CSSContainerRule::container() const {
+ if (!ContainerQueries())
+ return nullptr;
+ if (!media_cssom_wrapper_) {
+ media_cssom_wrapper_ = MakeGarbageCollected<MediaList>(
+ ContainerQueries(), const_cast<CSSContainerRule*>(this));
+ }
+ return media_cssom_wrapper_.Get();
+}
+
+const AtomicString& CSSContainerRule::Name() const {
+ return To<StyleRuleContainer>(group_rule_.Get())->GetContainerQuery().Name();
+}
+
+void CSSContainerRule::Reattach(StyleRuleBase* rule) {
+ CSSConditionRule::Reattach(rule);
+ if (media_cssom_wrapper_ && ContainerQueries())
+ media_cssom_wrapper_->Reattach(ContainerQueries());
+}
+
+void CSSContainerRule::Trace(Visitor* visitor) const {
+ visitor->Trace(media_cssom_wrapper_);
+ CSSConditionRule::Trace(visitor);
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_container_rule.h b/chromium/third_party/blink/renderer/core/css/css_container_rule.h
index dba352576e7..0215b531b19 100644
--- a/chromium/third_party/blink/renderer/core/css/css_container_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/css_container_rule.h
@@ -19,10 +19,26 @@ class CSSContainerRule final : public CSSConditionRule {
CSSContainerRule(StyleRuleContainer*, CSSStyleSheet*);
~CSSContainerRule() override;
+ void Reattach(StyleRuleBase*) override;
String cssText() const override;
+ void Trace(Visitor*) const override;
+
private:
+ // TODO(crbug.com/1214810): Don't lean on MediaList.
+ friend class InspectorCSSAgent;
+ friend class InspectorDOMAgent;
+ friend class InspectorStyleSheet;
+
CSSRule::Type GetType() const override { return kContainerRule; }
+
+ scoped_refptr<MediaQuerySet> ContainerQueries() const;
+
+ MediaList* container() const;
+
+ const AtomicString& Name() const;
+
+ mutable Member<MediaList> media_cssom_wrapper_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/css/css_counter_style_rule.idl b/chromium/third_party/blink/renderer/core/css/css_counter_style_rule.idl
index 88fcfc1fcbe..7aa08870bdc 100644
--- a/chromium/third_party/blink/renderer/core/css/css_counter_style_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_counter_style_rule.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// https://drafts.csswg.org/css-counter-styles-3/#the-csscounterstylerule-interface
-[Exposed=Window, RuntimeEnabled=CSSAtRuleCounterStyle]
+[Exposed=Window]
interface CSSCounterStyleRule : CSSRule {
[SetterCallWith=ExecutionContext] attribute CSSOMString name;
[SetterCallWith=ExecutionContext] attribute CSSOMString system;
diff --git a/chromium/third_party/blink/renderer/core/css/css_counter_value.h b/chromium/third_party/blink/renderer/core/css/css_counter_value.h
index 36458e232e6..ffd2314a7eb 100644
--- a/chromium/third_party/blink/renderer/core/css/css_counter_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_counter_value.h
@@ -41,9 +41,9 @@ class CSSCounterValue : public CSSValue {
list_style_(list_style),
separator_(separator) {}
- String Identifier() const { return identifier_->Value(); }
- AtomicString ListStyle() const { return list_style_->Value(); }
- String Separator() const { return separator_->Value(); }
+ const String& Identifier() const { return identifier_->Value(); }
+ const AtomicString& ListStyle() const { return list_style_->Value(); }
+ const String& Separator() const { return separator_->Value(); }
bool Equals(const CSSCounterValue& other) const {
return Identifier() == other.Identifier() &&
diff --git a/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc b/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc
index 3e1ce9c3dbc..2b6ca621277 100644
--- a/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc
@@ -25,111 +25,22 @@
#include "third_party/blink/renderer/core/css/css_crossfade_value.h"
-#include "third_party/blink/renderer/core/css/css_image_value.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/style/style_fetched_image.h"
-#include "third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h"
-#include "third_party/blink/renderer/platform/graphics/crossfade_generated_image.h"
+#include "third_party/blink/renderer/core/loader/resource/image_resource_observer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
namespace cssvalue {
-static bool SubimageIsPending(const CSSValue& value) {
- if (auto* image_value = DynamicTo<CSSImageValue>(value))
- return image_value->IsCachePending();
-
- if (auto* image_generator_value = DynamicTo<CSSImageGeneratorValue>(value))
- return image_generator_value->IsPending();
-
- NOTREACHED();
-
- return false;
-}
-
-static bool SubimageKnownToBeOpaque(const CSSValue& value,
- const Document& document,
- const ComputedStyle& style) {
- if (auto* image_value = DynamicTo<CSSImageValue>(value))
- return image_value->KnownToBeOpaque(document, style);
-
- if (auto* img_generator_value = DynamicTo<CSSImageGeneratorValue>(value))
- return img_generator_value->KnownToBeOpaque(document, style);
-
- NOTREACHED();
-
- return false;
-}
-
-static ImageResourceContent* CachedImageForCSSValue(CSSValue* value,
- const Document& document) {
- if (!value)
- return nullptr;
-
- if (auto* image_value = DynamicTo<CSSImageValue>(value)) {
- StyleImage* style_image_resource =
- image_value->CacheImage(document, FetchParameters::kNone);
- if (!style_image_resource)
- return nullptr;
-
- return style_image_resource->CachedImage();
- }
-
- if (auto* img_generator_value = DynamicTo<CSSImageGeneratorValue>(value)) {
- img_generator_value->LoadSubimages(document);
- // FIXME: Handle CSSImageGeneratorValue (and thus cross-fades with gradients
- // and canvas).
- return nullptr;
- }
-
- NOTREACHED();
-
- return nullptr;
-}
-
-static Image* RenderableImageForCSSValue(CSSValue* value,
- const Document& document) {
- ImageResourceContent* cached_image = CachedImageForCSSValue(value, document);
-
- if (!cached_image || cached_image->ErrorOccurred() ||
- cached_image->GetImage()->IsNull())
- return nullptr;
-
- return cached_image->GetImage();
-}
-
-static KURL UrlForCSSValue(const CSSValue& value) {
- auto* image_value = DynamicTo<CSSImageValue>(value);
- if (!image_value)
- return KURL();
-
- return KURL(image_value->Url());
-}
-
CSSCrossfadeValue::CSSCrossfadeValue(CSSValue* from_value,
CSSValue* to_value,
CSSPrimitiveValue* percentage_value)
: CSSImageGeneratorValue(kCrossfadeClass),
from_value_(from_value),
to_value_(to_value),
- percentage_value_(percentage_value),
- cached_from_image_(nullptr),
- cached_to_image_(nullptr),
- crossfade_subimage_observer_(this) {}
+ percentage_value_(percentage_value) {}
CSSCrossfadeValue::~CSSCrossfadeValue() = default;
-void CSSCrossfadeValue::Dispose() {
- if (cached_from_image_) {
- cached_from_image_->RemoveObserver(&crossfade_subimage_observer_);
- cached_from_image_ = nullptr;
- }
- if (cached_to_image_) {
- cached_to_image_->RemoveObserver(&crossfade_subimage_observer_);
- cached_to_image_ = nullptr;
- }
-}
-
String CSSCrossfadeValue::CustomCSSText() const {
StringBuilder result;
result.Append("-webkit-cross-fade(");
@@ -142,180 +53,71 @@ String CSSCrossfadeValue::CustomCSSText() const {
return result.ToString();
}
-CSSCrossfadeValue* CSSCrossfadeValue::ComputedCSSValue(
- const ComputedStyle& style,
- bool allow_visited_style) {
- CSSValue* from_value = from_value_;
- if (auto* from_image_value = DynamicTo<CSSImageValue>(from_value_.Get())) {
- from_value = from_image_value->ValueWithURLMadeAbsolute();
- } else if (auto* from_generator_value =
- DynamicTo<CSSImageGeneratorValue>(from_value_.Get())) {
- from_value =
- from_generator_value->ComputedCSSValue(style, allow_visited_style);
- }
- CSSValue* to_value = to_value_;
- if (auto* to_image_value = DynamicTo<CSSImageValue>(to_value_.Get())) {
- to_value = to_image_value->ValueWithURLMadeAbsolute();
- } else if (auto* to_generator_value =
- DynamicTo<CSSImageGeneratorValue>(to_value_.Get())) {
- to_value = to_generator_value->ComputedCSSValue(style, allow_visited_style);
- }
- return MakeGarbageCollected<CSSCrossfadeValue>(from_value, to_value,
- percentage_value_);
-}
-
-FloatSize CSSCrossfadeValue::FixedSize(
- const Document& document,
- const FloatSize& default_object_size) const {
- Image* from_image = RenderableImageForCSSValue(from_value_.Get(), document);
- Image* to_image = RenderableImageForCSSValue(to_value_.Get(), document);
-
- if (!from_image || !to_image)
- return FloatSize();
-
- FloatSize from_image_size(from_image->Size());
- FloatSize to_image_size(to_image->Size());
-
- if (auto* from_svg_image = DynamicTo<SVGImage>(from_image)) {
- from_image_size = from_svg_image->ConcreteObjectSize(default_object_size);
- }
-
- if (auto* to_svg_image = DynamicTo<SVGImage>(to_image)) {
- to_image_size = to_svg_image->ConcreteObjectSize(default_object_size);
- }
-
- // Rounding issues can cause transitions between images of equal size to
- // return a different fixed size; avoid performing the interpolation if the
- // images are the same size.
- if (from_image_size == to_image_size)
- return from_image_size;
-
- float percentage = percentage_value_->GetFloatValue();
- float inverse_percentage = 1 - percentage;
-
- return FloatSize(from_image_size.Width() * inverse_percentage +
- to_image_size.Width() * percentage,
- from_image_size.Height() * inverse_percentage +
- to_image_size.Height() * percentage);
-}
-
-bool CSSCrossfadeValue::IsPending() const {
- return SubimageIsPending(*from_value_) || SubimageIsPending(*to_value_);
-}
-
-bool CSSCrossfadeValue::KnownToBeOpaque(const Document& document,
- const ComputedStyle& style) const {
- return SubimageKnownToBeOpaque(*from_value_, document, style) &&
- SubimageKnownToBeOpaque(*to_value_, document, style);
+bool CSSCrossfadeValue::HasFailedOrCanceledSubresources() const {
+ return from_value_->HasFailedOrCanceledSubresources() ||
+ to_value_->HasFailedOrCanceledSubresources();
}
-void CSSCrossfadeValue::LoadSubimages(const Document& document) {
- ImageResourceContent* old_cached_from_image = cached_from_image_;
- ImageResourceContent* old_cached_to_image = cached_to_image_;
-
- cached_from_image_ = CachedImageForCSSValue(from_value_.Get(), document);
- cached_to_image_ = CachedImageForCSSValue(to_value_.Get(), document);
-
- if (cached_from_image_ != old_cached_from_image) {
- if (old_cached_from_image)
- old_cached_from_image->RemoveObserver(&crossfade_subimage_observer_);
- if (cached_from_image_)
- cached_from_image_->AddObserver(&crossfade_subimage_observer_);
- }
-
- if (cached_to_image_ != old_cached_to_image) {
- if (old_cached_to_image)
- old_cached_to_image->RemoveObserver(&crossfade_subimage_observer_);
- if (cached_to_image_)
- cached_to_image_->AddObserver(&crossfade_subimage_observer_);
- }
-
- crossfade_subimage_observer_.SetReady(true);
+bool CSSCrossfadeValue::Equals(const CSSCrossfadeValue& other) const {
+ return DataEquivalent(from_value_, other.from_value_) &&
+ DataEquivalent(to_value_, other.to_value_) &&
+ DataEquivalent(percentage_value_, other.percentage_value_);
}
-scoped_refptr<Image> CSSCrossfadeValue::GetImage(
- const ImageResourceObserver& client,
- const Document& document,
- const ComputedStyle&,
- const FloatSize& size) const {
- if (size.IsEmpty())
- return nullptr;
-
- Image* from_image = RenderableImageForCSSValue(from_value_.Get(), document);
- Image* to_image = RenderableImageForCSSValue(to_value_.Get(), document);
-
- if (!from_image || !to_image)
- return Image::NullImage();
-
- scoped_refptr<Image> from_image_ref(from_image);
- scoped_refptr<Image> to_image_ref(to_image);
+class CSSCrossfadeValue::ObserverProxy final
+ : public GarbageCollected<CSSCrossfadeValue::ObserverProxy>,
+ public ImageResourceObserver {
+ public:
+ explicit ObserverProxy(CSSCrossfadeValue* owner) : owner_(owner) {}
- if (auto* from_svg_image = DynamicTo<SVGImage>(from_image)) {
- from_image_ref = SVGImageForContainer::Create(from_svg_image, size, 1,
- UrlForCSSValue(*from_value_));
+ void ImageChanged(ImageResourceContent*,
+ CanDeferInvalidation defer) override {
+ for (const ImageResourceObserver* const_observer : Clients().Keys()) {
+ auto* observer = const_cast<ImageResourceObserver*>(const_observer);
+ observer->ImageChanged(static_cast<WrappedImagePtr>(owner_), defer);
+ }
}
- if (auto* to_svg_image = DynamicTo<SVGImage>(to_image)) {
- to_image_ref = SVGImageForContainer::Create(to_svg_image, size, 1,
- UrlForCSSValue(*to_value_));
+ bool WillRenderImage() override {
+ for (const ImageResourceObserver* const_observer : Clients().Keys()) {
+ auto* observer = const_cast<ImageResourceObserver*>(const_observer);
+ if (observer->WillRenderImage())
+ return true;
+ }
+ return false;
}
- return CrossfadeGeneratedImage::Create(from_image_ref, to_image_ref,
- percentage_value_->GetFloatValue(),
- FixedSize(document, size), size);
-}
-
-void CSSCrossfadeValue::CrossfadeChanged(
- ImageResourceObserver::CanDeferInvalidation defer) {
- for (const auto& curr : Clients()) {
- ImageResourceObserver* client =
- const_cast<ImageResourceObserver*>(curr.key);
- client->ImageChanged(static_cast<WrappedImagePtr>(this), defer);
+ bool GetImageAnimationPolicy(
+ mojom::blink::ImageAnimationPolicy& animation_policy) override {
+ for (const ImageResourceObserver* const_observer : Clients().Keys()) {
+ auto* observer = const_cast<ImageResourceObserver*>(const_observer);
+ if (observer->GetImageAnimationPolicy(animation_policy))
+ return true;
+ }
+ return false;
}
-}
-bool CSSCrossfadeValue::WillRenderImage() const {
- for (const auto& curr : Clients()) {
- if (const_cast<ImageResourceObserver*>(curr.key)->WillRenderImage())
- return true;
- }
- return false;
-}
+ String DebugName() const override { return "CrossfadeObserverProxy"; }
-void CSSCrossfadeValue::CrossfadeSubimageObserverProxy::ImageChanged(
- ImageResourceContent*,
- CanDeferInvalidation defer) {
- if (ready_)
- owner_value_->CrossfadeChanged(defer);
-}
+ void Trace(Visitor* visitor) const { visitor->Trace(owner_); }
-bool CSSCrossfadeValue::CrossfadeSubimageObserverProxy::WillRenderImage() {
- // If the images are not ready/loaded we won't paint them. If the images
- // are ready then ask the clients.
- return ready_ && owner_value_->WillRenderImage();
-}
+ private:
+ const ClientSizeCountMap& Clients() const { return owner_->Clients(); }
-bool CSSCrossfadeValue::HasFailedOrCanceledSubresources() const {
- if (cached_from_image_ && cached_from_image_->LoadFailedOrCanceled())
- return true;
- if (cached_to_image_ && cached_to_image_->LoadFailedOrCanceled())
- return true;
- return false;
-}
+ Member<CSSCrossfadeValue> owner_;
+};
-bool CSSCrossfadeValue::Equals(const CSSCrossfadeValue& other) const {
- return DataEquivalent(from_value_, other.from_value_) &&
- DataEquivalent(to_value_, other.to_value_) &&
- DataEquivalent(percentage_value_, other.percentage_value_);
+ImageResourceObserver* CSSCrossfadeValue::GetObserverProxy() {
+ if (!observer_proxy_)
+ observer_proxy_ = MakeGarbageCollected<ObserverProxy>(this);
+ return observer_proxy_;
}
-void CSSCrossfadeValue::TraceAfterDispatch(blink::Visitor* visitor) const {
+void CSSCrossfadeValue::TraceAfterDispatch(Visitor* visitor) const {
visitor->Trace(from_value_);
visitor->Trace(to_value_);
visitor->Trace(percentage_value_);
- visitor->Trace(cached_from_image_);
- visitor->Trace(cached_to_image_);
- visitor->Trace(crossfade_subimage_observer_);
+ visitor->Trace(observer_proxy_);
CSSImageGeneratorValue::TraceAfterDispatch(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_crossfade_value.h b/chromium/third_party/blink/renderer/core/css/css_crossfade_value.h
index 1d100f5d3af..afccbc7d83b 100644
--- a/chromium/third_party/blink/renderer/core/css/css_crossfade_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_crossfade_value.h
@@ -29,86 +29,41 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_image_generator_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
-#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
-#include "third_party/blink/renderer/core/loader/resource/image_resource_observer.h"
-#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
-class CrossfadeSubimageObserverProxy;
+class ImageResourceObserver;
namespace cssvalue {
class CORE_EXPORT CSSCrossfadeValue final : public CSSImageGeneratorValue {
- friend class blink::CrossfadeSubimageObserverProxy;
- USING_PRE_FINALIZER(CSSCrossfadeValue, Dispose);
-
public:
CSSCrossfadeValue(CSSValue* from_value,
CSSValue* to_value,
CSSPrimitiveValue* percentage_value);
~CSSCrossfadeValue();
- String CustomCSSText() const;
-
- scoped_refptr<Image> GetImage(const ImageResourceObserver&,
- const Document&,
- const ComputedStyle&,
- const FloatSize& target_size) const;
- bool IsFixedSize() const { return true; }
- FloatSize FixedSize(const Document&, const FloatSize&) const;
-
- bool IsPending() const;
- bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
+ CSSValue& From() const { return *from_value_; }
+ CSSValue& To() const { return *to_value_; }
+ CSSPrimitiveValue& Percentage() const { return *percentage_value_; }
- void LoadSubimages(const Document&);
+ bool HasClients() const { return !Clients().IsEmpty(); }
+ ImageResourceObserver* GetObserverProxy();
+ String CustomCSSText() const;
bool HasFailedOrCanceledSubresources() const;
-
bool Equals(const CSSCrossfadeValue&) const;
- CSSCrossfadeValue* ComputedCSSValue(const ComputedStyle&,
- bool allow_visited_style);
-
- void TraceAfterDispatch(blink::Visitor*) const;
+ void TraceAfterDispatch(Visitor*) const;
private:
- void Dispose();
-
- class CrossfadeSubimageObserverProxy final : public ImageResourceObserver {
- DISALLOW_NEW();
-
- public:
- explicit CrossfadeSubimageObserverProxy(CSSCrossfadeValue* owner_value)
- : owner_value_(owner_value), ready_(false) {}
-
- ~CrossfadeSubimageObserverProxy() override = default;
- void Trace(Visitor* visitor) const { visitor->Trace(owner_value_); }
-
- void ImageChanged(ImageResourceContent*, CanDeferInvalidation) override;
- bool WillRenderImage() override;
- String DebugName() const override {
- return "CrossfadeSubimageObserverProxy";
- }
- void SetReady(bool ready) { ready_ = ready; }
-
- private:
- Member<CSSCrossfadeValue> owner_value_;
- bool ready_;
- };
-
- bool WillRenderImage() const;
- void CrossfadeChanged(ImageResourceObserver::CanDeferInvalidation);
+ class ObserverProxy;
Member<CSSValue> from_value_;
Member<CSSValue> to_value_;
Member<CSSPrimitiveValue> percentage_value_;
-
- Member<ImageResourceContent> cached_from_image_;
- Member<ImageResourceContent> cached_to_image_;
-
- CrossfadeSubimageObserverProxy crossfade_subimage_observer_;
+ Member<ObserverProxy> observer_proxy_;
};
} // namespace cssvalue
diff --git a/chromium/third_party/blink/renderer/core/css/css_custom_font_data.h b/chromium/third_party/blink/renderer/core/css/css_custom_font_data.h
index 697046ef0b9..37d259accd9 100644
--- a/chromium/third_party/blink/renderer/core/css/css_custom_font_data.h
+++ b/chromium/third_party/blink/renderer/core/css/css_custom_font_data.h
@@ -56,6 +56,10 @@ class CSSCustomFontData final : public CustomFontData {
bool IsLoadingFallback() const override { return true; }
void ClearFontFaceSource() override { font_face_source_ = nullptr; }
+ bool IsPendingDataUrl() const override {
+ return font_face_source_ && font_face_source_->IsPendingDataUrl();
+ }
+
private:
CSSCustomFontData(CSSFontFaceSource* source, FallbackVisibility visibility)
: font_face_source_(source),
diff --git a/chromium/third_party/blink/renderer/core/css/css_custom_ident_value.h b/chromium/third_party/blink/renderer/core/css/css_custom_ident_value.h
index 0179c94cdc2..51c0cebbac3 100644
--- a/chromium/third_party/blink/renderer/core/css/css_custom_ident_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_custom_ident_value.h
@@ -17,7 +17,7 @@ class CORE_EXPORT CSSCustomIdentValue : public CSSValue {
explicit CSSCustomIdentValue(const AtomicString&);
explicit CSSCustomIdentValue(CSSPropertyID);
- AtomicString Value() const {
+ const AtomicString& Value() const {
DCHECK(!IsKnownPropertyID());
return string_;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h b/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h
index 6a92125c29c..a7570c03550 100644
--- a/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h
+++ b/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h
@@ -17,22 +17,18 @@ namespace blink {
class CORE_EXPORT CSSCustomPropertyDeclaration : public CSSValue {
public:
- CSSCustomPropertyDeclaration(const AtomicString& name, CSSValueID id)
+ explicit CSSCustomPropertyDeclaration(CSSValueID id)
: CSSValue(kCustomPropertyDeclarationClass),
- name_(name),
value_(nullptr),
value_id_(id) {
DCHECK(css_parsing_utils::IsCSSWideKeyword(id));
}
- CSSCustomPropertyDeclaration(const AtomicString& name,
- scoped_refptr<CSSVariableData> value)
+ explicit CSSCustomPropertyDeclaration(scoped_refptr<CSSVariableData> value)
: CSSValue(kCustomPropertyDeclarationClass),
- name_(name),
value_(std::move(value)),
value_id_(CSSValueID::kInvalid) {}
- const AtomicString& GetName() const { return name_; }
CSSVariableData* Value() const { return value_.get(); }
bool IsInherit(bool is_inherited_property) const {
@@ -54,7 +50,6 @@ class CORE_EXPORT CSSCustomPropertyDeclaration : public CSSValue {
void TraceAfterDispatch(blink::Visitor*) const;
private:
- const AtomicString name_;
scoped_refptr<CSSVariableData> value_;
CSSValueID value_id_;
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc
index 8b62da40ca3..1954fed4826 100644
--- a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc
@@ -104,16 +104,16 @@ CSSDefaultStyleSheets::CSSDefaultStyleSheets()
InitializeDefaultStyles();
-#if DCHECK_IS_ON()
- default_style_->CompactRulesIfNeeded();
+#if EXPENSIVE_DCHECKS_ARE_ON()
+ default_html_style_->CompactRulesIfNeeded();
default_mathml_style_->CompactRulesIfNeeded();
default_svg_style_->CompactRulesIfNeeded();
- default_quirks_style_->CompactRulesIfNeeded();
+ default_html_quirks_style_->CompactRulesIfNeeded();
default_print_style_->CompactRulesIfNeeded();
- DCHECK(default_style_->UniversalRules()->IsEmpty());
+ DCHECK(default_html_style_->UniversalRules()->IsEmpty());
DCHECK(default_mathml_style_->UniversalRules()->IsEmpty());
DCHECK(default_svg_style_->UniversalRules()->IsEmpty());
- DCHECK(default_quirks_style_->UniversalRules()->IsEmpty());
+ DCHECK(default_html_quirks_style_->UniversalRules()->IsEmpty());
DCHECK(default_print_style_->UniversalRules()->IsEmpty());
#endif
}
@@ -144,17 +144,18 @@ void CSSDefaultStyleSheets::PrepareForLeakDetection() {
void CSSDefaultStyleSheets::InitializeDefaultStyles() {
// This must be called only from constructor / PrepareForLeakDetection.
- default_style_ = MakeGarbageCollected<RuleSet>();
+ default_html_style_ = MakeGarbageCollected<RuleSet>();
default_mathml_style_ = MakeGarbageCollected<RuleSet>();
default_svg_style_ = MakeGarbageCollected<RuleSet>();
- default_quirks_style_ = MakeGarbageCollected<RuleSet>();
+ default_html_quirks_style_ = MakeGarbageCollected<RuleSet>();
default_print_style_ = MakeGarbageCollected<RuleSet>();
default_media_controls_style_ = MakeGarbageCollected<RuleSet>();
default_forced_color_style_.Clear();
default_pseudo_element_style_.Clear();
- default_style_->AddRulesFromSheet(DefaultStyleSheet(), ScreenEval());
- default_quirks_style_->AddRulesFromSheet(QuirksStyleSheet(), ScreenEval());
+ default_html_style_->AddRulesFromSheet(DefaultStyleSheet(), ScreenEval());
+ default_html_quirks_style_->AddRulesFromSheet(QuirksStyleSheet(),
+ ScreenEval());
default_print_style_->AddRulesFromSheet(DefaultStyleSheet(), PrintEval());
}
@@ -204,6 +205,30 @@ static void AddTextTrackCSSProperties(StringBuilder* builder,
builder->Append("; ");
}
+void CSSDefaultStyleSheets::AddRulesToDefaultStyleSheets(
+ StyleSheetContents* rules,
+ NamespaceType type) {
+ switch (type) {
+ case NamespaceType::kHTML:
+ default_html_style_->AddRulesFromSheet(rules, ScreenEval());
+ default_html_quirks_style_->AddRulesFromSheet(rules, ScreenEval());
+ break;
+ case NamespaceType::kSVG:
+ default_svg_style_->AddRulesFromSheet(rules, ScreenEval());
+ break;
+ case NamespaceType::kMathML:
+ default_mathml_style_->AddRulesFromSheet(rules, ScreenEval());
+ break;
+ case NamespaceType::kMediaControls:
+ default_media_controls_style_->AddRulesFromSheet(rules, ScreenEval());
+ break;
+ }
+ // Add to print and forced color for all namespaces.
+ default_print_style_->AddRulesFromSheet(rules, PrintEval());
+ if (default_forced_color_style_)
+ default_forced_color_style_->AddRulesFromSheet(rules, ForcedColorsEval());
+}
+
bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
const Element& element) {
bool changed_default_style = false;
@@ -211,12 +236,7 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
if (element.IsSVGElement() && !svg_style_sheet_) {
svg_style_sheet_ =
ParseUASheet(UncompressResourceAsASCIIString(IDR_UASTYLE_SVG_CSS));
- default_svg_style_->AddRulesFromSheet(SvgStyleSheet(), ScreenEval());
- default_print_style_->AddRulesFromSheet(SvgStyleSheet(), PrintEval());
- if (default_forced_color_style_) {
- default_forced_color_style_->AddRulesFromSheet(SvgStyleSheet(),
- ForcedColorsEval());
- }
+ AddRulesToDefaultStyleSheets(svg_style_sheet_, NamespaceType::kSVG);
changed_default_style = true;
}
@@ -227,8 +247,7 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
RuntimeEnabledFeatures::MathMLCoreEnabled()
? UncompressResourceAsASCIIString(IDR_UASTYLE_MATHML_CSS)
: UncompressResourceAsASCIIString(IDR_UASTYLE_MATHML_FALLBACK_CSS));
- default_mathml_style_->AddRulesFromSheet(MathmlStyleSheet(), ScreenEval());
- default_print_style_->AddRulesFromSheet(MathmlStyleSheet(), PrintEval());
+ AddRulesToDefaultStyleSheets(mathml_style_sheet_, NamespaceType::kMathML);
changed_default_style = true;
}
@@ -238,14 +257,8 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
// and <audio>.
media_controls_style_sheet_ =
ParseUASheet(media_controls_style_sheet_loader_->GetUAStyleSheet());
- default_media_controls_style_->AddRulesFromSheet(MediaControlsStyleSheet(),
- ScreenEval());
- default_print_style_->AddRulesFromSheet(MediaControlsStyleSheet(),
- PrintEval());
- if (default_forced_color_style_) {
- default_forced_color_style_->AddRulesFromSheet(MediaControlsStyleSheet(),
- ForcedColorsEval());
- }
+ AddRulesToDefaultStyleSheets(media_controls_style_sheet_,
+ NamespaceType::kMediaControls);
changed_default_style = true;
}
@@ -277,10 +290,8 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
settings->GetTextTrackTextSize());
builder.Append(" } ");
text_track_style_sheet_ = ParseUASheet(builder.ToString());
- default_media_controls_style_->AddRulesFromSheet(text_track_style_sheet_,
- ScreenEval());
- default_print_style_->AddRulesFromSheet(text_track_style_sheet_,
- PrintEval());
+ AddRulesToDefaultStyleSheets(text_track_style_sheet_,
+ NamespaceType::kMediaControls);
changed_default_style = true;
}
}
@@ -292,18 +303,11 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
? UncompressResourceAsASCIIString(IDR_UASTYLE_POPUP_CSS)
: String();
popup_style_sheet_ = ParseUASheet(popup_rules);
- // TODO(crbug.com/1201360): refactor this into a separate function.
- default_style_->AddRulesFromSheet(PopupStyleSheet(), ScreenEval());
- default_print_style_->AddRulesFromSheet(PopupStyleSheet(), PrintEval());
- default_quirks_style_->AddRulesFromSheet(PopupStyleSheet(), ScreenEval());
- if (default_forced_color_style_) {
- default_forced_color_style_->AddRulesFromSheet(PopupStyleSheet(),
- ForcedColorsEval());
- }
+ AddRulesToDefaultStyleSheets(popup_style_sheet_, NamespaceType::kHTML);
changed_default_style = true;
}
- DCHECK(!default_style_->Features().HasIdsInSelectors());
+ DCHECK(!default_html_style_->Features().HasIdsInSelectors());
return changed_default_style;
}
@@ -337,13 +341,8 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetForXrOverlay() {
webxr_overlay_style_sheet_ = ParseUASheet(
UncompressResourceAsASCIIString(IDR_UASTYLE_WEBXR_OVERLAY_CSS));
- default_style_->AddRulesFromSheet(webxr_overlay_style_sheet_, ScreenEval());
- default_print_style_->AddRulesFromSheet(webxr_overlay_style_sheet_,
- PrintEval());
- if (default_forced_color_style_) {
- default_forced_color_style_->AddRulesFromSheet(webxr_overlay_style_sheet_,
- ForcedColorsEval());
- }
+ AddRulesToDefaultStyleSheets(webxr_overlay_style_sheet_,
+ NamespaceType::kHTML);
return true;
}
@@ -355,9 +354,7 @@ void CSSDefaultStyleSheets::EnsureDefaultStyleSheetForFullscreen() {
UncompressResourceAsASCIIString(IDR_UASTYLE_FULLSCREEN_CSS) +
LayoutTheme::GetTheme().ExtraFullscreenStyleSheet();
fullscreen_style_sheet_ = ParseUASheet(fullscreen_rules);
- default_style_->AddRulesFromSheet(FullscreenStyleSheet(), ScreenEval());
- default_quirks_style_->AddRulesFromSheet(FullscreenStyleSheet(),
- ScreenEval());
+ AddRulesToDefaultStyleSheets(fullscreen_style_sheet_, NamespaceType::kHTML);
}
bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetForForcedColors() {
@@ -394,8 +391,8 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetForForcedColors() {
void CSSDefaultStyleSheets::CollectFeaturesTo(const Document& document,
RuleFeatureSet& features) {
- if (DefaultStyle())
- features.Add(DefaultStyle()->Features());
+ if (DefaultHtmlStyle())
+ features.Add(DefaultHtmlStyle()->Features());
if (DefaultMediaControlsStyle())
features.Add(DefaultMediaControlsStyle()->Features());
if (DefaultMathMLStyle())
@@ -405,10 +402,10 @@ void CSSDefaultStyleSheets::CollectFeaturesTo(const Document& document,
}
void CSSDefaultStyleSheets::Trace(Visitor* visitor) const {
- visitor->Trace(default_style_);
+ visitor->Trace(default_html_style_);
visitor->Trace(default_mathml_style_);
visitor->Trace(default_svg_style_);
- visitor->Trace(default_quirks_style_);
+ visitor->Trace(default_html_quirks_style_);
visitor->Trace(default_print_style_);
visitor->Trace(default_view_source_style_);
visitor->Trace(default_forced_color_style_);
diff --git a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h
index bab7c6b24e7..44fed53e051 100644
--- a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h
+++ b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h
@@ -55,10 +55,10 @@ class CSSDefaultStyleSheets final
void EnsureDefaultStyleSheetForFullscreen();
bool EnsureDefaultStyleSheetForForcedColors();
- RuleSet* DefaultStyle() { return default_style_.Get(); }
+ RuleSet* DefaultHtmlStyle() { return default_html_style_.Get(); }
RuleSet* DefaultMathMLStyle() { return default_mathml_style_.Get(); }
RuleSet* DefaultSVGStyle() { return default_svg_style_.Get(); }
- RuleSet* DefaultQuirksStyle() { return default_quirks_style_.Get(); }
+ RuleSet* DefaultHtmlQuirksStyle() { return default_html_quirks_style_.Get(); }
RuleSet* DefaultPrintStyle() { return default_print_style_.Get(); }
RuleSet* DefaultViewSourceStyle();
RuleSet* DefaultForcedColorStyle() {
@@ -116,10 +116,19 @@ class CSSDefaultStyleSheets final
private:
void InitializeDefaultStyles();
- Member<RuleSet> default_style_;
+ enum class NamespaceType {
+ kHTML,
+ kMathML,
+ kSVG,
+ kMediaControls, // Not exactly a namespace
+ };
+ void AddRulesToDefaultStyleSheets(StyleSheetContents* rules,
+ NamespaceType type);
+
+ Member<RuleSet> default_html_style_;
Member<RuleSet> default_mathml_style_;
Member<RuleSet> default_svg_style_;
- Member<RuleSet> default_quirks_style_;
+ Member<RuleSet> default_html_quirks_style_;
Member<RuleSet> default_print_style_;
Member<RuleSet> default_view_source_style_;
Member<RuleSet> default_forced_color_style_;
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_source.h b/chromium/third_party/blink/renderer/core/css/css_font_face_source.h
index 5a0b18b9067..083cc28ef5c 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_source.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_source.h
@@ -62,6 +62,8 @@ class CORE_EXPORT CSSFontFaceSource
// Returns nullptr unless the source is a loaded RemoteFontFaceSource.
virtual String GetURL() const { return g_null_atom; }
+ virtual bool IsPendingDataUrl() const { return false; }
+
// Returns nullptr unless the source is a loaded RemoteFontFaceSource.
virtual const FontCustomPlatformData* GetCustomPlaftormData() const {
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc
index df689dac59a..eea2b835661 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc
@@ -35,7 +35,6 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/loader/resource/font_resource.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_custom_platform_data.h"
#include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
@@ -93,7 +92,8 @@ FontResource& CSSFontFaceSrcValue::Fetch(ExecutionContext* context,
resource_request.SetIsAdResource();
ResourceLoaderOptions options(world_);
options.initiator_info.name = fetch_initiator_type_names::kCSS;
- options.initiator_info.referrer = referrer_.referrer;
+ if (referrer_.referrer != Referrer::ClientReferrerString())
+ options.initiator_info.referrer = referrer_.referrer;
FetchParameters params(std::move(resource_request), options);
if (base::FeatureList::IsEnabled(
features::kWebFontsCacheAwareTimeoutAdaption)) {
@@ -108,11 +108,6 @@ FontResource& CSSFontFaceSrcValue::Fetch(ExecutionContext* context,
params.SetCrossOriginAccessControl(security_origin,
kCrossOriginAttributeAnonymous);
}
- // For Workers, Fetcher is lazily loaded, so we must ensure it's available
- // here.
- if (auto* scope = DynamicTo<WorkerGlobalScope>(context)) {
- scope->EnsureFetcher();
- }
fetched_ = MakeGarbageCollected<FontResourceHelper>(
FontResource::Fetch(params, context->Fetcher(), client),
context->GetTaskRunner(TaskType::kInternalLoading).get());
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 42df3dc690f..5aa86b0bd91 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
@@ -30,7 +30,7 @@
#include <tuple>
#include <utility>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_math_expression_node.h"
@@ -132,8 +132,10 @@ scoped_refptr<Image> CSSGradientValue::GetImage(
// We need to create an image.
const ComputedStyle* root_style =
document.documentElement()->GetComputedStyle();
+ // TOOD(crbug.com/1223030): Handle container relative units.
CSSToLengthConversionData conversion_data(
- &style, root_style, document.GetLayoutView(), style.EffectiveZoom());
+ &style, root_style, document.GetLayoutView(),
+ /* nearest_container */ nullptr, style.EffectiveZoom());
scoped_refptr<Gradient> gradient;
switch (GetClassType()) {
@@ -764,6 +766,25 @@ bool CSSGradientValue::KnownToBeOpaque(const Document& document,
return true;
}
+CSSGradientValue* CSSGradientValue::ComputedCSSValue(
+ const ComputedStyle& style,
+ bool allow_visited_style) const {
+ switch (GetClassType()) {
+ case kLinearGradientClass:
+ return To<CSSLinearGradientValue>(this)->ComputedCSSValue(
+ style, allow_visited_style);
+ case kRadialGradientClass:
+ return To<CSSRadialGradientValue>(this)->ComputedCSSValue(
+ style, allow_visited_style);
+ case kConicGradientClass:
+ return To<CSSConicGradientValue>(this)->ComputedCSSValue(
+ style, allow_visited_style);
+ default:
+ NOTREACHED();
+ }
+ return nullptr;
+}
+
Vector<Color> CSSGradientValue::GetStopColors(
const Document& document,
const ComputedStyle& style) const {
@@ -1043,7 +1064,7 @@ bool CSSLinearGradientValue::Equals(const CSSLinearGradientValue& other) const {
CSSLinearGradientValue* CSSLinearGradientValue::ComputedCSSValue(
const ComputedStyle& style,
- bool allow_visited_style) {
+ bool allow_visited_style) const {
CSSLinearGradientValue* result = MakeGarbageCollected<CSSLinearGradientValue>(
first_x_, first_y_, second_x_, second_y_, angle_,
repeating_ ? kRepeating : kNonRepeating, GradientType());
@@ -1439,7 +1460,7 @@ bool CSSRadialGradientValue::Equals(const CSSRadialGradientValue& other) const {
CSSRadialGradientValue* CSSRadialGradientValue::ComputedCSSValue(
const ComputedStyle& style,
- bool allow_visited_style) {
+ bool allow_visited_style) const {
CSSRadialGradientValue* result = MakeGarbageCollected<CSSRadialGradientValue>(
first_x_, first_y_, first_radius_, second_x_, second_y_, second_radius_,
shape_, sizing_behavior_, end_horizontal_size_, end_vertical_size_,
@@ -1521,7 +1542,7 @@ bool CSSConicGradientValue::Equals(const CSSConicGradientValue& other) const {
CSSConicGradientValue* CSSConicGradientValue::ComputedCSSValue(
const ComputedStyle& style,
- bool allow_visited_style) {
+ bool allow_visited_style) const {
auto* result = MakeGarbageCollected<CSSConicGradientValue>(
x_, y_, from_angle_, repeating_ ? kRepeating : kNonRepeating);
result->AddComputedStops(style, allow_visited_style, stops_);
diff --git a/chromium/third_party/blink/renderer/core/css/css_gradient_value.h b/chromium/third_party/blink/renderer/core/css/css_gradient_value.h
index eaae4a673f8..20ced691a66 100644
--- a/chromium/third_party/blink/renderer/core/css/css_gradient_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_gradient_value.h
@@ -109,13 +109,9 @@ class CSSGradientValue : public CSSImageGeneratorValue {
CSSGradientType GradientType() const { return gradient_type_; }
- bool IsFixedSize() const { return false; }
- FloatSize FixedSize(const Document&) const { return FloatSize(); }
-
- bool IsPending() const { return false; }
bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
-
- void LoadSubimages(const Document&) {}
+ CSSGradientValue* ComputedCSSValue(const ComputedStyle&,
+ bool allow_visited_style) const;
Vector<Color> GetStopColors(const Document&, const ComputedStyle&) const;
@@ -181,7 +177,7 @@ class CSSLinearGradientValue final : public CSSGradientValue {
bool Equals(const CSSLinearGradientValue&) const;
CSSLinearGradientValue* ComputedCSSValue(const ComputedStyle&,
- bool allow_visited_style);
+ bool allow_visited_style) const;
void TraceAfterDispatch(blink::Visitor*) const;
@@ -279,7 +275,7 @@ class CSSRadialGradientValue final : public CSSGradientValue {
bool Equals(const CSSRadialGradientValue&) const;
CSSRadialGradientValue* ComputedCSSValue(const ComputedStyle&,
- bool allow_visited_style);
+ bool allow_visited_style) const;
void TraceAfterDispatch(blink::Visitor*) const;
@@ -325,7 +321,7 @@ class CSSConicGradientValue final : public CSSGradientValue {
bool Equals(const CSSConicGradientValue&) const;
CSSConicGradientValue* ComputedCSSValue(const ComputedStyle&,
- bool allow_visited_style);
+ bool allow_visited_style) const;
void TraceAfterDispatch(blink::Visitor*) const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h b/chromium/third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h
index e7b5c8b5627..9861bccb8d7 100644
--- a/chromium/third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h
@@ -22,7 +22,7 @@ namespace cssvalue {
// [ <line-names>? <fixed-size> ]+ <line-names>? )
class CSSGridIntegerRepeatValue : public CSSValueList {
public:
- CSSGridIntegerRepeatValue(size_t repetitions)
+ CSSGridIntegerRepeatValue(wtf_size_t repetitions)
: CSSValueList(kGridIntegerRepeatClass, kSpaceSeparator),
repetitions_(repetitions) {
DCHECK_GT(repetitions, 0UL);
@@ -31,14 +31,14 @@ class CSSGridIntegerRepeatValue : public CSSValueList {
String CustomCSSText() const;
bool Equals(const CSSGridIntegerRepeatValue&) const;
- size_t Repetitions() const { return repetitions_; }
+ wtf_size_t Repetitions() const { return repetitions_; }
void TraceAfterDispatch(blink::Visitor* visitor) const {
CSSValueList::TraceAfterDispatch(visitor);
}
private:
- const size_t repetitions_;
+ const wtf_size_t repetitions_;
};
} // namespace cssvalue
diff --git a/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.cc b/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.cc
index 57a7d1e672d..4c3ffc6becf 100644
--- a/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.cc
@@ -37,8 +37,8 @@ namespace cssvalue {
CSSGridTemplateAreasValue::CSSGridTemplateAreasValue(
const NamedGridAreaMap& grid_area_map,
- size_t row_count,
- size_t column_count)
+ wtf_size_t row_count,
+ wtf_size_t column_count)
: CSSValue(kGridTemplateAreasClass),
grid_area_map_(grid_area_map),
row_count_(row_count),
@@ -48,8 +48,8 @@ CSSGridTemplateAreasValue::CSSGridTemplateAreasValue(
}
static String StringForPosition(const NamedGridAreaMap& grid_area_map,
- size_t row,
- size_t column) {
+ wtf_size_t row,
+ wtf_size_t column) {
for (const auto& item : grid_area_map) {
const GridArea& area = item.value;
if (row >= area.rows.StartLine() && row < area.rows.EndLine() &&
@@ -62,9 +62,9 @@ static String StringForPosition(const NamedGridAreaMap& grid_area_map,
String CSSGridTemplateAreasValue::CustomCSSText() const {
StringBuilder builder;
- for (size_t row = 0; row < row_count_; ++row) {
+ for (wtf_size_t row = 0; row < row_count_; ++row) {
builder.Append('"');
- for (size_t column = 0; column < column_count_; ++column) {
+ for (wtf_size_t column = 0; column < column_count_; ++column) {
builder.Append(StringForPosition(grid_area_map_, row, column));
if (column != column_count_ - 1)
builder.Append(' ');
diff --git a/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.h b/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.h
index 69e7b35f552..10779e6bbbb 100644
--- a/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_grid_template_areas_value.h
@@ -42,15 +42,15 @@ namespace cssvalue {
class CSSGridTemplateAreasValue : public CSSValue {
public:
CSSGridTemplateAreasValue(const NamedGridAreaMap&,
- size_t row_count,
- size_t column_count);
+ wtf_size_t row_count,
+ wtf_size_t column_count);
~CSSGridTemplateAreasValue() = default;
String CustomCSSText() const;
const NamedGridAreaMap& GridAreaMap() const { return grid_area_map_; }
- size_t RowCount() const { return row_count_; }
- size_t ColumnCount() const { return column_count_; }
+ wtf_size_t RowCount() const { return row_count_; }
+ wtf_size_t ColumnCount() const { return column_count_; }
bool Equals(const CSSGridTemplateAreasValue&) const;
@@ -60,8 +60,8 @@ class CSSGridTemplateAreasValue : public CSSValue {
private:
NamedGridAreaMap grid_area_map_;
- size_t row_count_;
- size_t column_count_;
+ wtf_size_t row_count_;
+ wtf_size_t column_count_;
};
} // namespace cssvalue
diff --git a/chromium/third_party/blink/renderer/core/css/css_identifier_value.cc b/chromium/third_party/blink/renderer/core/css/css_identifier_value.cc
index b1a26003f2d..9c6dc062038 100644
--- a/chromium/third_party/blink/renderer/core/css/css_identifier_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_identifier_value.cc
@@ -49,6 +49,9 @@ CSSIdentifierValue::CSSIdentifierValue(const Length& length)
case Length::kFitContent:
value_id_ = CSSValueID::kFitContent;
break;
+ case Length::kContent:
+ value_id_ = CSSValueID::kContent;
+ break;
case Length::kExtendToZoom:
value_id_ = CSSValueID::kInternalExtendToZoom;
break;
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_generator_value.cc b/chromium/third_party/blink/renderer/core/css/css_image_generator_value.cc
index db328c5a651..7c00de57a0f 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_generator_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_image_generator_value.cc
@@ -25,15 +25,14 @@
#include "third_party/blink/renderer/core/css/css_image_generator_value.h"
-#include "third_party/blink/renderer/core/css/css_crossfade_value.h"
#include "third_party/blink/renderer/core/css/css_gradient_value.h"
#include "third_party/blink/renderer/core/css/css_paint_value.h"
+#include "third_party/blink/renderer/core/loader/resource/image_resource_observer.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
namespace blink {
using cssvalue::CSSConicGradientValue;
-using cssvalue::CSSCrossfadeValue;
using cssvalue::CSSLinearGradientValue;
using cssvalue::CSSRadialGradientValue;
@@ -138,9 +137,6 @@ scoped_refptr<Image> CSSImageGeneratorValue::GetImage(
const ComputedStyle& style,
const FloatSize& target_size) {
switch (GetClassType()) {
- case kCrossfadeClass:
- return To<CSSCrossfadeValue>(this)->GetImage(client, document, style,
- target_size);
case kLinearGradientClass:
return To<CSSLinearGradientValue>(this)->GetImage(client, document, style,
target_size);
@@ -169,68 +165,9 @@ bool CSSImageGeneratorValue::IsUsingCustomProperty(
return false;
}
-bool CSSImageGeneratorValue::IsFixedSize() const {
- switch (GetClassType()) {
- case kCrossfadeClass:
- return To<CSSCrossfadeValue>(this)->IsFixedSize();
- case kLinearGradientClass:
- return To<CSSLinearGradientValue>(this)->IsFixedSize();
- case kPaintClass:
- return To<CSSPaintValue>(this)->IsFixedSize();
- case kRadialGradientClass:
- return To<CSSRadialGradientValue>(this)->IsFixedSize();
- case kConicGradientClass:
- return To<CSSConicGradientValue>(this)->IsFixedSize();
- default:
- NOTREACHED();
- }
- return false;
-}
-
-FloatSize CSSImageGeneratorValue::FixedSize(
- const Document& document,
- const FloatSize& default_object_size) {
- switch (GetClassType()) {
- case kCrossfadeClass:
- return To<CSSCrossfadeValue>(this)->FixedSize(document,
- default_object_size);
- case kLinearGradientClass:
- return To<CSSLinearGradientValue>(this)->FixedSize(document);
- case kPaintClass:
- return To<CSSPaintValue>(this)->FixedSize(document);
- case kRadialGradientClass:
- return To<CSSRadialGradientValue>(this)->FixedSize(document);
- case kConicGradientClass:
- return To<CSSConicGradientValue>(this)->FixedSize(document);
- default:
- NOTREACHED();
- }
- return FloatSize();
-}
-
-bool CSSImageGeneratorValue::IsPending() const {
- switch (GetClassType()) {
- case kCrossfadeClass:
- return To<CSSCrossfadeValue>(this)->IsPending();
- case kLinearGradientClass:
- return To<CSSLinearGradientValue>(this)->IsPending();
- case kPaintClass:
- return To<CSSPaintValue>(this)->IsPending();
- case kRadialGradientClass:
- return To<CSSRadialGradientValue>(this)->IsPending();
- case kConicGradientClass:
- return To<CSSConicGradientValue>(this)->IsPending();
- default:
- NOTREACHED();
- }
- return false;
-}
-
bool CSSImageGeneratorValue::KnownToBeOpaque(const Document& document,
const ComputedStyle& style) const {
switch (GetClassType()) {
- case kCrossfadeClass:
- return To<CSSCrossfadeValue>(this)->KnownToBeOpaque(document, style);
case kLinearGradientClass:
return To<CSSLinearGradientValue>(this)->KnownToBeOpaque(document, style);
case kPaintClass:
@@ -245,51 +182,4 @@ bool CSSImageGeneratorValue::KnownToBeOpaque(const Document& document,
return false;
}
-void CSSImageGeneratorValue::LoadSubimages(const Document& document) {
- switch (GetClassType()) {
- case kCrossfadeClass:
- To<CSSCrossfadeValue>(this)->LoadSubimages(document);
- break;
- case kLinearGradientClass:
- To<CSSLinearGradientValue>(this)->LoadSubimages(document);
- break;
- case kPaintClass:
- To<CSSPaintValue>(this)->LoadSubimages(document);
- break;
- case kRadialGradientClass:
- To<CSSRadialGradientValue>(this)->LoadSubimages(document);
- break;
- case kConicGradientClass:
- To<CSSConicGradientValue>(this)->LoadSubimages(document);
- break;
- default:
- NOTREACHED();
- }
-}
-
-CSSImageGeneratorValue* CSSImageGeneratorValue::ComputedCSSValue(
- const ComputedStyle& style,
- bool allow_visited_style) {
- switch (GetClassType()) {
- case kCrossfadeClass:
- return To<CSSCrossfadeValue>(this)->ComputedCSSValue(style,
- allow_visited_style);
- case kLinearGradientClass:
- return To<CSSLinearGradientValue>(this)->ComputedCSSValue(
- style, allow_visited_style);
- case kPaintClass:
- return To<CSSPaintValue>(this)->ComputedCSSValue(style,
- allow_visited_style);
- case kRadialGradientClass:
- return To<CSSRadialGradientValue>(this)->ComputedCSSValue(
- style, allow_visited_style);
- case kConicGradientClass:
- return To<CSSConicGradientValue>(this)->ComputedCSSValue(
- style, allow_visited_style);
- default:
- NOTREACHED();
- }
- return nullptr;
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_generator_value.h b/chromium/third_party/blink/renderer/core/css/css_image_generator_value.h
index 2d6f9b3fa22..43af6fca32a 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_generator_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_image_generator_value.h
@@ -94,17 +94,8 @@ class CORE_EXPORT CSSImageGeneratorValue : public CSSValue {
const ComputedStyle&,
const FloatSize& target_size);
- bool IsFixedSize() const;
- FloatSize FixedSize(const Document&, const FloatSize& default_object_size);
-
- bool IsPending() const;
bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
- void LoadSubimages(const Document&);
-
- CSSImageGeneratorValue* ComputedCSSValue(const ComputedStyle&,
- bool allow_visited_style);
-
bool IsUsingCustomProperty(const AtomicString& custom_property_name,
const Document&) const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_value.cc b/chromium/third_party/blink/renderer/core/css/css_image_value.cc
index a54fb823421..81fe3aa1175 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_image_value.cc
@@ -71,7 +71,8 @@ FetchParameters CSSImageValue::PrepareFetch(
options.initiator_info.name = initiator_name_.IsEmpty()
? fetch_initiator_type_names::kCSS
: initiator_name_;
- options.initiator_info.referrer = referrer_.referrer;
+ if (referrer_.referrer != Referrer::ClientReferrerString())
+ options.initiator_info.referrer = referrer_.referrer;
FetchParameters params(std::move(resource_request), options);
if (cross_origin != kCrossOriginAttributeNotSet) {
@@ -157,12 +158,6 @@ String CSSImageValue::CustomCSSText() const {
return SerializeURI(relative_url_);
}
-bool CSSImageValue::KnownToBeOpaque(const Document& document,
- const ComputedStyle& style) const {
- return cached_image_ ? cached_image_->KnownToBeOpaque(document, style)
- : false;
-}
-
void CSSImageValue::TraceAfterDispatch(blink::Visitor* visitor) const {
visitor->Trace(cached_image_);
CSSValue::TraceAfterDispatch(visitor);
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_value.h b/chromium/third_party/blink/renderer/core/css/css_image_value.h
index 4839b0204e9..fca1d73c764 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_image_value.h
@@ -35,7 +35,6 @@ namespace blink {
class Document;
class KURL;
class StyleImage;
-class ComputedStyle;
class CORE_EXPORT CSSImageValue : public CSSValue {
public:
@@ -71,8 +70,6 @@ class CORE_EXPORT CSSImageValue : public CSSValue {
bool Equals(const CSSImageValue&) const;
- bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
-
CSSImageValue* ValueWithURLMadeAbsolute() const {
return MakeGarbageCollected<CSSImageValue>(
absolute_url_, KURL(absolute_url_), Referrer(), origin_clean_,
diff --git a/chromium/third_party/blink/renderer/core/css/css_layout_function_value.h b/chromium/third_party/blink/renderer/core/css/css_layout_function_value.h
index 853110df141..ea14616fb16 100644
--- a/chromium/third_party/blink/renderer/core/css/css_layout_function_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_layout_function_value.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LAYOUT_FUNCTION_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LAYOUT_FUNCTION_VALUE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
index 3f5ed024a0c..82f0a055f5d 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -39,8 +39,6 @@
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-static const int maxExpressionDepth = 100;
-
enum ParseState { OK, TooDeep, NoMoreTokens };
namespace blink {
@@ -69,6 +67,15 @@ static CalculationCategory UnitCategory(CSSPrimitiveValue::UnitType type) {
case CSSPrimitiveValue::UnitType::kViewportMin:
case CSSPrimitiveValue::UnitType::kViewportMax:
return kCalcLength;
+ case CSSPrimitiveValue::UnitType::kContainerWidth:
+ case CSSPrimitiveValue::UnitType::kContainerHeight:
+ case CSSPrimitiveValue::UnitType::kContainerInlineSize:
+ case CSSPrimitiveValue::UnitType::kContainerBlockSize:
+ case CSSPrimitiveValue::UnitType::kContainerMin:
+ case CSSPrimitiveValue::UnitType::kContainerMax:
+ return RuntimeEnabledFeatures::CSSContainerRelativeUnitsEnabled()
+ ? kCalcLength
+ : kCalcOther;
case CSSPrimitiveValue::UnitType::kDegrees:
case CSSPrimitiveValue::UnitType::kGradians:
case CSSPrimitiveValue::UnitType::kRadians:
@@ -113,6 +120,12 @@ static bool HasDoubleValue(CSSPrimitiveValue::UnitType type) {
case CSSPrimitiveValue::UnitType::kViewportHeight:
case CSSPrimitiveValue::UnitType::kViewportMin:
case CSSPrimitiveValue::UnitType::kViewportMax:
+ case CSSPrimitiveValue::UnitType::kContainerWidth:
+ case CSSPrimitiveValue::UnitType::kContainerHeight:
+ case CSSPrimitiveValue::UnitType::kContainerInlineSize:
+ case CSSPrimitiveValue::UnitType::kContainerBlockSize:
+ case CSSPrimitiveValue::UnitType::kContainerMin:
+ case CSSPrimitiveValue::UnitType::kContainerMax:
case CSSPrimitiveValue::UnitType::kDotsPerPixel:
case CSSPrimitiveValue::UnitType::kDotsPerInch:
case CSSPrimitiveValue::UnitType::kDotsPerCentimeter:
@@ -1055,15 +1068,6 @@ bool CSSMathExpressionVariadicOperation::InvolvesPercentageComparisons() const {
// ------ End of CSSMathExpressionVariadicOperation member functions
-static ParseState CheckDepthAndIndex(int* depth, CSSParserTokenRange tokens) {
- (*depth)++;
- if (tokens.AtEnd())
- return NoMoreTokens;
- if (*depth > maxExpressionDepth)
- return TooDeep;
- return OK;
-}
-
class CSSMathExpressionNodeParser {
STACK_ALLOCATED();
@@ -1082,7 +1086,7 @@ class CSSMathExpressionNodeParser {
CSSMathOperator op,
int depth) {
DCHECK(op == CSSMathOperator::kMin || op == CSSMathOperator::kMax);
- if (CheckDepthAndIndex(&depth, tokens) != OK)
+ if (tokens.AtEnd())
return nullptr;
CSSMathExpressionVariadicOperation::Operands operands;
@@ -1108,7 +1112,7 @@ class CSSMathExpressionNodeParser {
}
CSSMathExpressionNode* ParseClamp(CSSParserTokenRange tokens, int depth) {
- if (CheckDepthAndIndex(&depth, tokens) != OK)
+ if (tokens.AtEnd())
return nullptr;
CSSMathExpressionNode* min_operand = ParseValueExpression(tokens, depth);
@@ -1184,7 +1188,7 @@ class CSSMathExpressionNodeParser {
CSSMathExpressionNode* ParseValueTerm(CSSParserTokenRange& tokens,
int depth) {
- if (CheckDepthAndIndex(&depth, tokens) != OK)
+ if (tokens.AtEnd())
return nullptr;
if (tokens.Peek().GetType() == kLeftParenthesisToken ||
@@ -1222,7 +1226,7 @@ class CSSMathExpressionNodeParser {
CSSMathExpressionNode* ParseValueMultiplicativeExpression(
CSSParserTokenRange& tokens,
int depth) {
- if (CheckDepthAndIndex(&depth, tokens) != OK)
+ if (tokens.AtEnd())
return nullptr;
CSSMathExpressionNode* result = ParseValueTerm(tokens, depth);
@@ -1253,7 +1257,7 @@ class CSSMathExpressionNodeParser {
CSSMathExpressionNode* ParseAdditiveValueExpression(
CSSParserTokenRange& tokens,
int depth) {
- if (CheckDepthAndIndex(&depth, tokens) != OK)
+ if (tokens.AtEnd())
return nullptr;
CSSMathExpressionNode* result =
@@ -1290,6 +1294,8 @@ class CSSMathExpressionNodeParser {
CSSMathExpressionNode* ParseValueExpression(CSSParserTokenRange& tokens,
int depth) {
+ if (++depth > kMaxExpressionDepth)
+ return nullptr;
return ParseAdditiveValueExpression(tokens, depth);
}
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h
index ddb239ef8a3..624e5d70ac5 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h
+++ b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_MATH_EXPRESSION_NODE_H_
#include "base/dcheck_is_on.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_math_operator.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -42,6 +43,8 @@
namespace blink {
+static const int kMaxExpressionDepth = 100;
+
class CalculationExpressionNode;
class CSSNumericLiteralValue;
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_expression_node_test.cc b/chromium/third_party/blink/renderer/core/css/css_math_expression_node_test.cc
index 9d31c408459..4bf0957e083 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_expression_node_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_math_expression_node_test.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
+#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/calculation_expression_node.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -93,6 +94,7 @@ TEST(CSSCalculationValue, AccumulatePixelsAndPercent) {
ComputedStyle::CreateInitialStyleSingleton();
style->SetEffectiveZoom(5);
CSSToLengthConversionData conversion_data(style.get(), style.get(), nullptr,
+ /* nearest_container */ nullptr,
style->EffectiveZoom());
TestAccumulatePixelsAndPercent(
@@ -212,6 +214,85 @@ TEST(CSSCalculationValue, AddToLengthUnitValues) {
actual, "calc((1 * 2) * (5px + 20em / 2) - 80% / (3 - 1) + 5px)")));
}
+TEST(CSSMathExpressionNode, TestParseDeeplyNestedExpression) {
+ enum Kind {
+ calc,
+ min,
+ max,
+ clamp,
+ };
+
+ // Ref: https://bugs.chromium.org/p/chromium/issues/detail?id=1211283
+ const struct TestCase {
+ const Kind kind;
+ const int nest_num;
+ const bool expected;
+ } test_cases[] = {
+ {calc, 1, true},
+ {calc, 10, true},
+ {calc, kMaxExpressionDepth - 1, true},
+ {calc, kMaxExpressionDepth, false},
+ {calc, kMaxExpressionDepth + 1, false},
+ {min, 1, true},
+ {min, 10, true},
+ {min, kMaxExpressionDepth - 1, true},
+ {min, kMaxExpressionDepth, false},
+ {min, kMaxExpressionDepth + 1, false},
+ {max, 1, true},
+ {max, 10, true},
+ {max, kMaxExpressionDepth - 1, true},
+ {max, kMaxExpressionDepth, false},
+ {max, kMaxExpressionDepth + 1, false},
+ {clamp, 1, true},
+ {clamp, 10, true},
+ {clamp, kMaxExpressionDepth - 1, true},
+ {clamp, kMaxExpressionDepth, false},
+ {clamp, kMaxExpressionDepth + 1, false},
+ };
+
+ for (const auto& test_case : test_cases) {
+ std::stringstream ss;
+
+ // Make nested expression as follows:
+ // calc(1px + calc(1px + calc(1px)))
+ // min(1px, 1px + min(1px, 1px + min(1px, 1px)))
+ // max(1px, 1px + max(1px, 1px + max(1px, 1px)))
+ // clamp(1px, 1px, 1px + clamp(1px, 1px, 1px + clamp(1px, 1px, 1px)))
+ for (int i = 0; i < test_case.nest_num; i++) {
+ if (i)
+ ss << " + ";
+ switch (test_case.kind) {
+ case calc:
+ ss << "calc(1px";
+ break;
+ case min:
+ ss << "min(1px, 1px";
+ break;
+ case max:
+ ss << "max(1px, 1px";
+ break;
+ case clamp:
+ ss << "clamp(1px, 1px, 1px";
+ break;
+ }
+ }
+ for (int i = 0; i < test_case.nest_num; i++) {
+ ss << ")";
+ }
+
+ CSSTokenizer tokenizer(String(ss.str().c_str()));
+ const auto tokens = tokenizer.TokenizeToEOF();
+ const CSSParserTokenRange range(tokens);
+ const CSSMathExpressionNode* res = CSSMathExpressionNode::ParseCalc(range);
+
+ if (test_case.expected) {
+ EXPECT_TRUE(res);
+ } else {
+ EXPECT_FALSE(res);
+ }
+ }
+}
+
} // anonymous namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_numeric_literal_value.cc b/chromium/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
index 27e722894df..eb3bffe794c 100644
--- a/chromium/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
@@ -220,7 +220,13 @@ String CSSNumericLiteralValue::CustomCSSText() const {
case UnitType::kViewportWidth:
case UnitType::kViewportHeight:
case UnitType::kViewportMin:
- case UnitType::kViewportMax: {
+ case UnitType::kViewportMax:
+ case UnitType::kContainerWidth:
+ case UnitType::kContainerHeight:
+ case UnitType::kContainerInlineSize:
+ case UnitType::kContainerBlockSize:
+ case UnitType::kContainerMin:
+ case UnitType::kContainerMax: {
// The following integers are minimal and maximum integers which can
// be represented in non-exponential format with 6 digit precision.
constexpr int kMinInteger = -999999;
@@ -241,7 +247,7 @@ String CSSNumericLiteralValue::CustomCSSText() const {
int int_value = value;
const char* unit_type = UnitTypeToString(GetType());
builder.AppendNumber(int_value);
- builder.Append(unit_type, strlen(unit_type));
+ builder.Append(unit_type, static_cast<unsigned>(strlen(unit_type)));
text = builder.ToString();
}
} break;
diff --git a/chromium/third_party/blink/renderer/core/css/css_paint_value.cc b/chromium/third_party/blink/renderer/core/css/css_paint_value.cc
index bac65b23a27..42d810d7948 100644
--- a/chromium/third_party/blink/renderer/core/css/css_paint_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_paint_value.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -62,7 +63,8 @@ String CSSPaintValue::GetName() const {
const Vector<CSSPropertyID>* CSSPaintValue::NativeInvalidationProperties(
const Document& document) const {
- const CSSPaintImageGenerator* generator = generators_.at(&document);
+ const CSSPaintImageGenerator* generator =
+ generators_.DeprecatedAtOrEmptyValue(&document);
if (!generator)
return nullptr;
return &generator->NativeInvalidationProperties();
@@ -70,7 +72,8 @@ const Vector<CSSPropertyID>* CSSPaintValue::NativeInvalidationProperties(
const Vector<AtomicString>* CSSPaintValue::CustomInvalidationProperties(
const Document& document) const {
- const CSSPaintImageGenerator* generator = generators_.at(&document);
+ const CSSPaintImageGenerator* generator =
+ generators_.DeprecatedAtOrEmptyValue(&document);
if (!generator)
return nullptr;
return &generator->CustomInvalidationProperties();
@@ -79,7 +82,8 @@ const Vector<AtomicString>* CSSPaintValue::CustomInvalidationProperties(
bool CSSPaintValue::IsUsingCustomProperty(
const AtomicString& custom_property_name,
const Document& document) const {
- const CSSPaintImageGenerator* generator = generators_.at(&document);
+ const CSSPaintImageGenerator* generator =
+ generators_.DeprecatedAtOrEmptyValue(&document);
if (!generator || !generator->IsImageGeneratorReady())
return false;
return generator->CustomInvalidationProperties().Contains(
@@ -197,9 +201,10 @@ bool CSSPaintValue::ParseInputArguments(const Document& document) {
!RuntimeEnabledFeatures::CSSPaintAPIArgumentsEnabled())
return true;
- DCHECK(generators_.at(&document)->IsImageGeneratorReady());
+ DCHECK(
+ generators_.DeprecatedAtOrEmptyValue(&document)->IsImageGeneratorReady());
const Vector<CSSSyntaxDefinition>& input_argument_types =
- generators_.at(&document)->InputArgumentTypes();
+ generators_.DeprecatedAtOrEmptyValue(&document)->InputArgumentTypes();
if (argument_variable_data_.size() != input_argument_types.size()) {
input_arguments_invalid_ = true;
return false;
@@ -240,7 +245,8 @@ void CSSPaintValue::PaintImageGeneratorReady() {
bool CSSPaintValue::KnownToBeOpaque(const Document& document,
const ComputedStyle&) const {
- const CSSPaintImageGenerator* generator = generators_.at(&document);
+ const CSSPaintImageGenerator* generator =
+ generators_.DeprecatedAtOrEmptyValue(&document);
return generator && !generator->HasAlpha();
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_paint_value.h b/chromium/third_party/blink/renderer/core/css/css_paint_value.h
index c835d56be00..bf0145f3e90 100644
--- a/chromium/third_party/blink/renderer/core/css/css_paint_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_paint_value.h
@@ -34,14 +34,9 @@ class CORE_EXPORT CSSPaintValue : public CSSImageGeneratorValue {
const Document&,
const ComputedStyle&,
const FloatSize& target_size);
- bool IsFixedSize() const { return false; }
- FloatSize FixedSize(const Document&) { return FloatSize(); }
- bool IsPending() const { return true; }
bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
- void LoadSubimages(const Document&) {}
-
bool Equals(const CSSPaintValue&) const;
const Vector<CSSPropertyID>* NativeInvalidationProperties(
@@ -57,11 +52,6 @@ class CORE_EXPORT CSSPaintValue : public CSSImageGeneratorValue {
BuildInputArgumentValues(style_value);
}
- CSSPaintValue* ComputedCSSValue(const ComputedStyle&,
- bool allow_visited_style) {
- return this;
- }
-
bool IsUsingCustomProperty(const AtomicString& custom_property_name,
const Document&) const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_paint_value_test.cc b/chromium/third_party/blink/renderer/core/css/css_paint_value_test.cc
index 1de40b33900..97bd24aaa2c 100644
--- a/chromium/third_party/blink/renderer/core/css/css_paint_value_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_paint_value_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
#include "third_party/blink/renderer/core/css/mock_css_paint_image_generator.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
diff --git a/chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.cc b/chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.cc
new file mode 100644
index 00000000000..05547f1bee6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.cc
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h"
+#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+namespace cssvalue {
+
+CSSPendingSystemFontValue::CSSPendingSystemFontValue(CSSValueID system_font_id)
+ : CSSValue(kPendingSystemFontValueClass), system_font_id_(system_font_id) {
+ DCHECK(CSSParserFastPaths::IsValidSystemFont(system_font_id));
+}
+
+// static
+CSSPendingSystemFontValue* CSSPendingSystemFontValue::Create(
+ CSSValueID system_font_id) {
+ return MakeGarbageCollected<CSSPendingSystemFontValue>(system_font_id);
+}
+
+const FontSelectionValue& CSSPendingSystemFontValue::ResolveFontStyle() const {
+ return LayoutThemeFontProvider::SystemFontStyle(system_font_id_);
+}
+
+const FontSelectionValue& CSSPendingSystemFontValue::ResolveFontWeight() const {
+ return LayoutThemeFontProvider::SystemFontWeight(system_font_id_);
+}
+
+const AtomicString& CSSPendingSystemFontValue::ResolveFontFamily() const {
+ return LayoutThemeFontProvider::SystemFontFamily(system_font_id_);
+}
+
+float CSSPendingSystemFontValue::ResolveFontSize(
+ const Document* document) const {
+ return LayoutThemeFontProvider::SystemFontSize(system_font_id_, document);
+}
+
+String CSSPendingSystemFontValue::CustomCSSText() const {
+ return "";
+}
+
+void CSSPendingSystemFontValue::TraceAfterDispatch(
+ blink::Visitor* visitor) const {
+ CSSValue::TraceAfterDispatch(visitor);
+}
+
+} // namespace cssvalue
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.h b/chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.h
new file mode 100644
index 00000000000..d1687283166
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_pending_system_font_value.h
@@ -0,0 +1,67 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SYSTEM_FONT_VALUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SYSTEM_FONT_VALUE_H_
+
+#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class FontSelectionValue;
+
+namespace cssvalue {
+
+// The 'font' shorthand accepts some special system font values, like 'caption'
+// (https://drafts.csswg.org/css-fonts/#valdef-font-caption).
+//
+// The resolution of these values into longhands is platform-dependent, and can
+// also depend on user's settings, like the default font size.
+//
+// The CSS parser wouldn't be able to resolve these, since we need a |Document|
+// in order to retrieve the settings, and |CSSParserContext::GetDocument()|
+// would be null when system fonts are set in UA styles.
+//
+// So the parser sets all the font longhands to a |CSSPendingSystemFontValue|,
+// and the resolution is deferred until computed-value time, when we can use
+// |StyleResolverState::GetDocument()|.
+class CSSPendingSystemFontValue : public CSSValue {
+ public:
+ static CSSPendingSystemFontValue* Create(CSSValueID);
+
+ explicit CSSPendingSystemFontValue(CSSValueID);
+
+ CSSValueID SystemFontId() const { return system_font_id_; }
+
+ const FontSelectionValue& ResolveFontStyle() const;
+ const FontSelectionValue& ResolveFontWeight() const;
+ const AtomicString& ResolveFontFamily() const;
+ float ResolveFontSize(const Document*) const;
+
+ bool Equals(const CSSPendingSystemFontValue& other) const {
+ return system_font_id_ == other.system_font_id_;
+ }
+
+ String CustomCSSText() const;
+
+ void TraceAfterDispatch(blink::Visitor*) const;
+
+ private:
+ const CSSValueID system_font_id_;
+};
+
+} // namespace cssvalue
+
+template <>
+struct DowncastTraits<cssvalue::CSSPendingSystemFontValue> {
+ static bool AllowFrom(const CSSValue& value) {
+ return value.IsPendingSystemFontValue();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SYSTEM_FONT_VALUE_H_
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 63445819c1a..d088a96a7e8 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
@@ -477,6 +477,24 @@ bool CSSPrimitiveValue::UnitTypeToLengthUnitType(UnitType unit_type,
case CSSPrimitiveValue::UnitType::kViewportMax:
length_type = kUnitTypeViewportMax;
return true;
+ case CSSPrimitiveValue::UnitType::kContainerWidth:
+ length_type = kUnitTypeContainerWidth;
+ return true;
+ case CSSPrimitiveValue::UnitType::kContainerHeight:
+ length_type = kUnitTypeContainerHeight;
+ return true;
+ case CSSPrimitiveValue::UnitType::kContainerInlineSize:
+ length_type = kUnitTypeContainerInlineSize;
+ return true;
+ case CSSPrimitiveValue::UnitType::kContainerBlockSize:
+ length_type = kUnitTypeContainerBlockSize;
+ return true;
+ case CSSPrimitiveValue::UnitType::kContainerMin:
+ length_type = kUnitTypeContainerMin;
+ return true;
+ case CSSPrimitiveValue::UnitType::kContainerMax:
+ length_type = kUnitTypeContainerMax;
+ return true;
default:
return false;
}
@@ -505,6 +523,18 @@ CSSPrimitiveValue::UnitType CSSPrimitiveValue::LengthUnitTypeToUnitType(
return CSSPrimitiveValue::UnitType::kViewportMin;
case kUnitTypeViewportMax:
return CSSPrimitiveValue::UnitType::kViewportMax;
+ case kUnitTypeContainerWidth:
+ return CSSPrimitiveValue::UnitType::kContainerWidth;
+ case kUnitTypeContainerHeight:
+ return CSSPrimitiveValue::UnitType::kContainerHeight;
+ case kUnitTypeContainerInlineSize:
+ return CSSPrimitiveValue::UnitType::kContainerInlineSize;
+ case kUnitTypeContainerBlockSize:
+ return CSSPrimitiveValue::UnitType::kContainerBlockSize;
+ case kUnitTypeContainerMin:
+ return CSSPrimitiveValue::UnitType::kContainerMin;
+ case kUnitTypeContainerMax:
+ return CSSPrimitiveValue::UnitType::kContainerMax;
case kLengthUnitTypeCount:
break;
}
@@ -575,6 +605,18 @@ const char* CSSPrimitiveValue::UnitTypeToString(UnitType type) {
return "vmin";
case UnitType::kViewportMax:
return "vmax";
+ case UnitType::kContainerWidth:
+ return "qw";
+ case UnitType::kContainerHeight:
+ return "qh";
+ case UnitType::kContainerInlineSize:
+ return "qi";
+ case UnitType::kContainerBlockSize:
+ return "qb";
+ case UnitType::kContainerMin:
+ return "qmin";
+ case UnitType::kContainerMax:
+ return "qmax";
default:
break;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_primitive_value.h b/chromium/third_party/blink/renderer/core/css/css_primitive_value.h
index abdcc486b3b..f7757ab85a1 100644
--- a/chromium/third_party/blink/renderer/core/css/css_primitive_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -83,6 +83,12 @@ class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
kViewportHeight,
kViewportMin,
kViewportMax,
+ kContainerWidth,
+ kContainerHeight,
+ kContainerInlineSize,
+ kContainerBlockSize,
+ kContainerMin,
+ kContainerMax,
kRems,
kChs,
kUserUnits, // The SVG term for unitless lengths
@@ -124,6 +130,12 @@ class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
kUnitTypeViewportHeight,
kUnitTypeViewportMin,
kUnitTypeViewportMax,
+ kUnitTypeContainerWidth,
+ kUnitTypeContainerHeight,
+ kUnitTypeContainerInlineSize,
+ kUnitTypeContainerBlockSize,
+ kUnitTypeContainerMin,
+ kUnitTypeContainerMax,
// This value must come after the last length unit type to enable iteration
// over the length unit types.
@@ -167,6 +179,9 @@ class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
static bool IsViewportPercentageLength(UnitType type) {
return type >= UnitType::kViewportWidth && type <= UnitType::kViewportMax;
}
+ static bool IsContainerPercentageLength(UnitType type) {
+ return type >= UnitType::kContainerWidth && type <= UnitType::kContainerMax;
+ }
static bool IsLength(UnitType type) {
return (type >= UnitType::kEms && type <= UnitType::kUserUnits) ||
type == UnitType::kQuirkyEms;
@@ -174,7 +189,8 @@ class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
static inline bool IsRelativeUnit(UnitType type) {
return type == UnitType::kPercentage || type == UnitType::kEms ||
type == UnitType::kExs || type == UnitType::kRems ||
- type == UnitType::kChs || IsViewportPercentageLength(type);
+ type == UnitType::kChs || IsViewportPercentageLength(type) ||
+ IsContainerPercentageLength(type);
}
bool IsLength() const;
bool IsNumber() const;
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 c3168197c26..1737b4d593b 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
@@ -1544,6 +1544,22 @@ inline Containment CSSIdentifierValue::ConvertTo() const {
}
template <>
+inline EContainerType CSSIdentifierValue::ConvertTo() const {
+ switch (GetValueID()) {
+ case CSSValueID::kNone:
+ return kContainerTypeNone;
+ case CSSValueID::kInlineSize:
+ return kContainerTypeInlineSize;
+ case CSSValueID::kBlockSize:
+ return kContainerTypeBlockSize;
+ default:
+ break;
+ }
+ NOTREACHED();
+ return kContainerTypeNone;
+}
+
+template <>
inline CSSIdentifierValue::CSSIdentifierValue(TextUnderlinePosition position)
: CSSValue(kIdentifierClass) {
switch (position) {
@@ -1595,14 +1611,8 @@ inline CSSIdentifierValue::CSSIdentifierValue(ScrollbarGutter scrollbar_gutter)
case kScrollbarGutterStable:
value_id_ = CSSValueID::kStable;
break;
- case kScrollbarGutterAlways:
- value_id_ = CSSValueID::kAlways;
- break;
- case kScrollbarGutterBoth:
- value_id_ = CSSValueID::kBoth;
- break;
- case kScrollbarGutterForce:
- value_id_ = CSSValueID::kForce;
+ case kScrollbarGutterBothEdges:
+ value_id_ = CSSValueID::kBothEdges;
break;
}
}
@@ -1614,12 +1624,8 @@ inline ScrollbarGutter CSSIdentifierValue::ConvertTo() const {
return kScrollbarGutterAuto;
case CSSValueID::kStable:
return kScrollbarGutterStable;
- case CSSValueID::kAlways:
- return kScrollbarGutterAlways;
- case CSSValueID::kBoth:
- return kScrollbarGutterBoth;
- case CSSValueID::kForce:
- return kScrollbarGutterForce;
+ case CSSValueID::kBothEdges:
+ return kScrollbarGutterBothEdges;
default:
break;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_primitive_value_units.json5 b/chromium/third_party/blink/renderer/core/css/css_primitive_value_units.json5
index 582963e3ebe..8b9f1c3874a 100644
--- a/chromium/third_party/blink/renderer/core/css/css_primitive_value_units.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_primitive_value_units.json5
@@ -103,6 +103,30 @@
unit_type: "kViewportMax",
},
{
+ name: "qw",
+ unit_type: "kContainerWidth",
+ },
+ {
+ name: "qh",
+ unit_type: "kContainerHeight",
+ },
+ {
+ name: "qi",
+ unit_type: "kContainerInlineSize",
+ },
+ {
+ name: "qb",
+ unit_type: "kContainerBlockSize",
+ },
+ {
+ name: "qmin",
+ unit_type: "kContainerMin",
+ },
+ {
+ name: "qmax",
+ unit_type: "kContainerMax",
+ },
+ {
name: "rem",
unit_type: "kRems",
},
diff --git a/chromium/third_party/blink/renderer/core/css/css_properties.json5 b/chromium/third_party/blink/renderer/core/css/css_properties.json5
index 44cdfea4be4..67af261ce5b 100644
--- a/chromium/third_party/blink/renderer/core/css/css_properties.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_properties.json5
@@ -510,6 +510,14 @@
valid_type: "bool",
},
+ // - is_border_radius
+ // The property, when used by the author, will disable any native
+ // appearance on UI elements.
+ is_border_radius: {
+ default: false,
+ valid_type: "bool",
+ },
+
// - tree_scoped_value: true
// Whether the property takes a tree-scoped reference as its value.
// https://drafts.csswg.org/css-scoping/#css-tree-scoped-reference
@@ -994,6 +1002,7 @@
},
{
name: "forced-color-adjust",
+ field_group: "*",
property_methods: ["CSSValueFromComputedStyleInternal"],
inherited: true,
runtime_flag: "ForcedColors",
@@ -1162,7 +1171,6 @@
type_name: "StyleAspectRatio",
converter: "ConvertAspectRatio",
include_paths: ["third_party/blink/renderer/core/style/style_aspect_ratio.h"],
- runtime_flag: "CSSAspectRatioProperty",
computable: false,
},
{
@@ -1371,7 +1379,7 @@
default_value: "Length::Fixed()",
style_builder_custom_functions: ["inherit", "value"],
keywords: ["baseline", "sub", "super"],
- typedom_types: ["Keyword", "Percentage", "Length"]
+ typedom_types: ["Keyword", "Percentage", "Length"],
},
{
name: "border-bottom-color",
@@ -1407,6 +1415,7 @@
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
is_border: true,
+ is_border_radius: true,
logical_property_group: {
name: "border-radius",
resolver: "bottom-left",
@@ -1425,6 +1434,7 @@
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
is_border: true,
+ is_border_radius: true,
logical_property_group: {
name: "border-radius",
resolver: "bottom-right",
@@ -1692,6 +1702,7 @@
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
is_border: true,
+ is_border_radius: true,
logical_property_group: {
name: "border-radius",
resolver: "top-left",
@@ -1710,6 +1721,7 @@
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
is_border: true,
+ is_border_radius: true,
logical_property_group: {
name: "border-radius",
resolver: "top-right",
@@ -1895,6 +1907,7 @@
name: "clip-path",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
+ compositable: true,
field_group: "*",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/style/clip_path_operation.h"],
@@ -1904,7 +1917,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertClipPath",
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "clip-rule",
@@ -1918,7 +1931,7 @@
type_name: "WindRule",
keywords: ["nonzero", "evenodd"],
default_value: "RULE_NONZERO",
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "color-interpolation",
@@ -2004,6 +2017,31 @@
computable: false,
},
{
+ name: "container-name",
+ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
+ type_name: "AtomicString",
+ default_value: "AtomicString()",
+ field_group: "*",
+ field_template: "external",
+ converter: "ConvertContainerName",
+ keywords: ["none"],
+ typedom_types: ["Keyword"],
+ runtime_flag: "CSSContainerQueries",
+ },
+ {
+ name: "container-type",
+ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
+ keywords: ["none", "block-size", "inline-size"],
+ field_group: "*",
+ field_size: 2,
+ field_template: "primitive",
+ default_value: "kContainerTypeNone",
+ type_name: "unsigned",
+ converter: "ConvertFlags<EContainerType>",
+ typedom_types: ["Keyword"],
+ runtime_flag: "CSSContainerQueries",
+ },
+ {
name: "content",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
field_group: "*",
@@ -2126,7 +2164,7 @@
keywords: ["auto", "alphabetic", "ideographic", "middle", "central", "mathematical", "hanging",
"use-script", "no-change", "reset-size", "text-after-edge", "text-before-edge"],
default_value: "auto",
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "empty-cells",
@@ -2180,7 +2218,7 @@
type_name: "WindRule",
keywords: ["nonzero", "evenodd"],
default_value: "RULE_NONZERO",
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "filter",
@@ -2205,9 +2243,9 @@
field_group: "*",
field_template: "<length>",
default_value: "Length::Auto()",
- converter: "ConvertLengthOrAuto",
+ converter: "ConvertLengthSizing",
typedom_types: ["Keyword", "Length", "Percentage"],
- keywords: ["auto"],
+ keywords: ["auto", "fit-content", "min-content", "max-content", "content"],
},
{
name: "flex-direction",
@@ -2285,7 +2323,7 @@
type_name: "float",
default_value: "1",
converter: "ConvertAlpha",
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "grid-auto-columns",
@@ -2311,7 +2349,7 @@
computed_style_custom_functions: ["getter"],
converter: "ConvertGridAutoFlow",
keywords: ["row", "column"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "grid-auto-rows",
@@ -2379,7 +2417,7 @@
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
style_builder_custom_functions: ["initial", "inherit", "value"],
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "grid-template-columns",
@@ -2395,7 +2433,7 @@
type: "Column",
},
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "grid-template-rows",
@@ -2411,7 +2449,7 @@
type: "Row",
},
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "height",
@@ -2618,21 +2656,8 @@
type_name: "ListStyleTypeData",
keywords: [
"disc", "circle", "square", "disclosure-open", "disclosure-closed",
- "decimal", "decimal-leading-zero",
- "arabic-indic", "bengali", "cambodian", "khmer", "devanagari",
- "gujarati", "gurmukhi", "kannada", "lao", "malayalam", "mongolian",
- "myanmar", "oriya", "persian", "urdu", "telugu", "tibetan", "thai",
- "lower-roman", "upper-roman", "lower-greek", "lower-alpha",
- "lower-latin", "upper-alpha", "upper-latin", "cjk-earthly-branch",
- "cjk-heavenly-stem", "ethiopic-halehame", "ethiopic-halehame-am",
- "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "hangul",
- "hangul-consonant", "korean-hangul-formal", "korean-hanja-formal",
- "korean-hanja-informal", "hebrew", "armenian", "lower-armenian",
- "upper-armenian", "georgian", "cjk-ideographic", "simp-chinese-formal",
- "simp-chinese-informal", "trad-chinese-formal", "trad-chinese-informal",
- "hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "none"
+ "decimal", "none"
],
- computed_style_custom_functions: ["getter"],
style_builder_custom_functions: ["initial", "inherit", "value"],
tree_scoped_value: true,
},
@@ -2720,7 +2745,7 @@
name_for_methods: "MarkerEndResource",
converter: "ConvertElementReference",
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "marker-mid",
@@ -2734,7 +2759,7 @@
name_for_methods: "MarkerMidResource",
converter: "ConvertElementReference",
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "marker-start",
@@ -2748,7 +2773,7 @@
name_for_methods: "MarkerStartResource",
converter: "ConvertElementReference",
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "mask",
@@ -2775,6 +2800,7 @@
{
name: "math-shift",
property_methods: ["CSSValueFromComputedStyleInternal"],
+ field_group: "*",
field_template: "keyword",
inherited: true,
keywords: ["normal", "compact"],
@@ -2785,6 +2811,7 @@
{
name: "math-style",
property_methods: ["CSSValueFromComputedStyleInternal"],
+ field_group: "*",
field_template: "keyword",
inherited: true,
keywords: ["normal", "compact"],
@@ -2904,7 +2931,7 @@
type_name: "LengthPoint",
converter: "ConvertPositionOrAuto",
keywords: ["auto"],
- typedom_types: ["Keyword", "Position"]
+ typedom_types: ["Keyword", "Position"],
},
{
name: "offset-distance",
@@ -2914,7 +2941,7 @@
field_template: "<length>",
default_value: "Length::Fixed(0)",
converter: "ConvertLength",
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "offset-path",
@@ -2928,7 +2955,7 @@
type_name: "BasicShape",
converter: "ConvertOffsetPath",
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "offset-position",
@@ -2942,7 +2969,7 @@
type_name: "LengthPoint",
converter: "ConvertPositionOrAuto",
keywords: ["auto"],
- typedom_types: ["Keyword", "Position"]
+ typedom_types: ["Keyword", "Position"],
},
{
name: "offset-rotate",
@@ -2955,7 +2982,7 @@
type_name: "StyleOffsetRotation",
converter: "ConvertOffsetRotate",
keywords: ["auto", "reverse"],
- typedom_types: ["Keyword", "Angle"]
+ typedom_types: ["Keyword", "Angle"],
},
{
name: "opacity",
@@ -2981,7 +3008,7 @@
default_value: "0",
type_name: "int",
computed_style_custom_functions: ["setter"],
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
// This property is used for testing with origin trial intergration only.
@@ -3005,7 +3032,7 @@
computed_style_custom_functions: ["setter"],
default_value: "2",
type_name: "short",
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "outline-color",
@@ -3291,7 +3318,7 @@
default_value: "kPaintOrderNormal",
converter: "ConvertPaintOrder",
keywords: ["normal", "fill", "stroke", "markers"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "perspective",
@@ -3299,11 +3326,11 @@
interpolable: true,
field_group: "*",
field_template: "primitive",
- default_value: "0.0",
+ default_value: "-1.0",
type_name: "float",
converter: "ConvertPerspective",
keywords: ["none"],
- typedom_types: ["Keyword", "Length"]
+ typedom_types: ["Keyword", "Length"],
},
{
name: "perspective-origin",
@@ -3316,7 +3343,7 @@
default_value: "LengthPoint(Length::Percent(50.0), Length::Percent(50.0))",
type_name: "LengthPoint",
converter: "ConvertPosition",
- typedom_types: ["Position"]
+ typedom_types: ["Position"],
},
{
name: "pointer-events",
@@ -3439,7 +3466,7 @@
type_name: "unsigned",
converter: "ConvertScrollbarGutter",
keywords: [
- "auto", "stable", "always"
+ "auto", "stable", "both-edges"
],
typedom_types: ["Keyword"],
runtime_flag: "ScrollbarGutter",
@@ -3473,7 +3500,7 @@
name: "scroll-margin",
resolver: "block-end",
},
- typedom_types: ["Keyword", "Length"]
+ typedom_types: ["Keyword", "Length"],
},
{
name: "scroll-customization",
@@ -3494,7 +3521,7 @@
name: "scroll-margin",
resolver: "block-start",
},
- typedom_types: ["Keyword", "Length"]
+ typedom_types: ["Keyword", "Length"],
},
{
name: "scroll-margin-bottom",
@@ -3518,7 +3545,7 @@
name: "scroll-margin",
resolver: "inline-end",
},
- typedom_types: ["Keyword", "Length"]
+ typedom_types: ["Keyword", "Length"],
},
{
name: "scroll-margin-inline-start",
@@ -3527,7 +3554,7 @@
name: "scroll-margin",
resolver: "inline-start",
},
- typedom_types: ["Keyword", "Length"]
+ typedom_types: ["Keyword", "Length"],
},
{
name: "scroll-margin-left",
@@ -3732,7 +3759,7 @@
default_value: "0.0",
type_name: "float",
computed_style_custom_functions: ["setter"],
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "shape-margin",
@@ -3743,7 +3770,7 @@
default_value: "Length::Fixed(0)",
converter: "ConvertLength",
keywords: ["none"],
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "shape-outside",
@@ -3815,7 +3842,7 @@
type_name: "float",
default_value: "1",
converter: "ConvertAlpha",
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "stroke",
@@ -3849,7 +3876,7 @@
name_for_methods: "StrokeDashArray",
converter: "ConvertStrokeDasharray",
keywords: ["none"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "stroke-dashoffset",
@@ -3862,7 +3889,7 @@
default_value: "Length::Fixed()",
name_for_methods: "StrokeDashOffset",
converter: "ConvertLength",
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "stroke-linecap",
@@ -3875,7 +3902,7 @@
default_value: "kButtCap",
name_for_methods: "CapStyle",
keywords: ["butt", "round", "square"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "stroke-linejoin",
@@ -3888,7 +3915,7 @@
default_value: "kMiterJoin",
name_for_methods: "JoinStyle",
keywords: ["miter", "bevel", "round"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "stroke-miterlimit",
@@ -3900,7 +3927,7 @@
type_name: "float",
default_value: "4",
name_for_methods: "StrokeMiterLimit",
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "stroke-opacity",
@@ -3912,7 +3939,7 @@
type_name: "float",
default_value: "1",
converter: "ConvertAlpha",
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "stroke-width",
@@ -3977,7 +4004,7 @@
field_template: "keyword",
keywords: ["auto", "start", "end", "left", "right", "center", "justify"],
default_value: "auto",
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "text-anchor",
@@ -4092,7 +4119,7 @@
field_template: "<length>",
default_value: "Length::Fixed()",
style_builder_custom_functions: ["initial", "inherit", "value"],
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "text-justify",
@@ -4152,7 +4179,7 @@
type_name: "TextSizeAdjust",
converter: "ConvertTextSizeAdjust",
keywords: ["none", "auto"],
- typedom_types: ["Keyword", "Percentage"]
+ typedom_types: ["Keyword", "Percentage"],
},
{
name: "text-transform",
@@ -4226,7 +4253,7 @@
type_name: "TouchAction",
converter: "ConvertFlags<blink::TouchAction>",
keywords: ["auto", "none", "pan-x", "pan-left", "pan-right", "pan-y", "pan-up", "pan-down", "pinch-zoom", "manipulation"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "transform",
@@ -4525,7 +4552,7 @@
computed_style_custom_functions: ["setter"],
style_builder_template: "auto",
keywords: ["auto"],
- typedom_types: ["Keyword", "Number"]
+ typedom_types: ["Keyword", "Number"],
},
{
name: "column-gap",
@@ -4579,7 +4606,7 @@
],
default_value: "none",
type_name: "EBorderStyle",
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "column-rule-width",
@@ -5015,7 +5042,7 @@
computed_style_custom_functions: ["setter"],
default_value: "2",
type_name: "short",
- typedom_types: ["Number"]
+ typedom_types: ["Number"],
},
{
name: "width",
@@ -5039,7 +5066,7 @@
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
style_builder_custom_functions: ["initial", "inherit", "value"],
keywords: ["auto"],
- typedom_types: ["Keyword"]
+ typedom_types: ["Keyword"],
},
{
name: "word-break",
@@ -5077,7 +5104,7 @@
computed_style_custom_functions: ["setter"],
style_builder_template: "auto",
keywords: ["auto"],
- typedom_types: ["Keyword", "Number"]
+ typedom_types: ["Keyword", "Number"],
},
// CSS logical props
@@ -5197,7 +5224,7 @@
name: "padding",
resolver: "inline-start",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "padding-inline-end",
@@ -5207,7 +5234,7 @@
name: "padding",
resolver: "inline-end",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "padding-block-start",
@@ -5217,7 +5244,7 @@
name: "padding",
resolver: "block-start",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "padding-block-end",
@@ -5227,7 +5254,7 @@
name: "padding",
resolver: "block-end",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "border-inline-start-width",
@@ -5340,7 +5367,7 @@
name: "inset",
resolver: "inline-start",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "inset-inline-end",
@@ -5349,7 +5376,7 @@
name: "inset",
resolver: "inline-end",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "inset-block-start",
@@ -5358,7 +5385,7 @@
name: "inset",
resolver: "block-start",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "inset-block-end",
@@ -5367,7 +5394,7 @@
name: "inset",
resolver: "block-end",
},
- typedom_types: ["Length", "Percentage"]
+ typedom_types: ["Length", "Percentage"],
},
{
name: "border-start-start-radius",
@@ -5625,85 +5652,66 @@
name: "ascent-override",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSFontMetricsOverride",
},
{
name: "descent-override",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSFontMetricsOverride",
- },
- {
- name: "advance-override",
- is_descriptor: true,
- is_property: false,
- runtime_flag: "CSSFontFaceAdvanceOverride",
},
{
name: "line-gap-override",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSFontMetricsOverride",
},
{
name: "system",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "negative",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "prefix",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "suffix",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "range",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "pad",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "fallback",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "symbols",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "additive-symbols",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "speak-as",
is_descriptor: true,
is_property: false,
- runtime_flag: "CSSAtRuleCounterStyle",
},
{
name: "size-adjust",
@@ -5942,6 +5950,14 @@
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
},
{
+ name: "container",
+ longhands: [
+ "container-type", "container-name"
+ ],
+ property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
+ runtime_flag: "CSSContainerQueries",
+ },
+ {
name: "flex",
longhands: ["flex-grow", "flex-shrink", "flex-basis"],
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
@@ -6294,7 +6310,7 @@
visited_property_for: "caret-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
inherited: true,
- field_group: "*",
+ field_group: "*->inherited_visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_auto_color.h"],
default_value: "StyleAutoColor::AutoColor()",
@@ -6311,7 +6327,7 @@
name: "-internal-visited-column-rule-color",
visited_property_for: "column-rule-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*->multi-col",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6324,7 +6340,7 @@
name: "-internal-visited-background-color",
visited_property_for: "background-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor(Color::kTransparent)",
@@ -6344,7 +6360,7 @@
name: "-internal-visited-border-left-color",
visited_property_for: "border-left-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6362,7 +6378,7 @@
name: "-internal-visited-border-right-color",
visited_property_for: "border-right-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6380,7 +6396,7 @@
name: "-internal-visited-border-top-color",
visited_property_for: "border-top-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6398,7 +6414,7 @@
name: "-internal-visited-border-bottom-color",
visited_property_for: "border-bottom-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6474,7 +6490,7 @@
name: "-internal-visited-outline-color",
visited_property_for: "outline-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6506,7 +6522,7 @@
name: "-internal-visited-text-decoration-color",
visited_property_for: "text-decoration-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6524,7 +6540,7 @@
visited_property_for: "-webkit-text-emphasis-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
inherited: true,
- field_group: "*",
+ field_group: "*->inherited_visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6539,7 +6555,7 @@
visited_property_for: "-webkit-text-fill-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
inherited: true,
- field_group: "*",
+ field_group: "*->inherited_visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6554,7 +6570,7 @@
visited_property_for: "-webkit-text-stroke-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
inherited: true,
- field_group: "*",
+ field_group: "*->inherited_visited",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6569,7 +6585,7 @@
{
name: "-internal-forced-background-color",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->forced_colors",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/layout/layout_theme.h"],
default_value: "StyleColor(CSSValueID::kCanvas)",
@@ -6587,7 +6603,7 @@
{
name: "-internal-forced-border-color",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->forced_colors",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6601,7 +6617,7 @@
name: "-internal-forced-color",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"],
inherited: true,
- field_group: "*",
+ field_group: "*->inherited_forced_colors",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/layout/layout_theme.h"],
default_value: "StyleColor(CSSValueID::kCanvastext)",
@@ -6616,7 +6632,7 @@
{
name: "-internal-forced-outline-color",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"],
- field_group: "*",
+ field_group: "*->forced_colors",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
default_value: "StyleColor::CurrentColor()",
@@ -6631,7 +6647,7 @@
visited_property_for: "-internal-forced-color",
property_methods: ["ParseSingleValue", "ColorIncludingFallback"],
inherited: true,
- field_group: "*",
+ field_group: "*->inherited_forced_colors",
field_template: "external",
include_paths: ["third_party/blink/renderer/core/layout/layout_theme.h"],
default_value: "StyleColor(CSSValueID::kCanvastext)",
diff --git a/chromium/third_party/blink/renderer/core/css/css_property_source_data.h b/chromium/third_party/blink/renderer/core/css/css_property_source_data.h
index 0ba300fdbd8..acea6b36e04 100644
--- a/chromium/third_party/blink/renderer/core/css/css_property_source_data.h
+++ b/chromium/third_party/blink/renderer/core/css/css_property_source_data.h
@@ -97,6 +97,8 @@ class CSSRuleSourceData final : public GarbageCollected<CSSRuleSourceData> {
return type == StyleRule::kMedia || type == StyleRule::kImport;
}
+ bool HasContainer() const { return type == StyleRule::kContainer; }
+
StyleRule::RuleType type;
// Range of the selector list in the enclosing source.
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 9aba0de4a26..757b8a920e2 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
@@ -122,7 +122,6 @@ static uint16_t GetConvertedCSSPropertyID(AtRuleDescriptorID descriptor_id) {
}
static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
- const CSSValue&,
uint16_t id,
CSSPropertyID property_id) {
DCHECK_EQ(id, static_cast<uint16_t>(property_id));
@@ -138,20 +137,16 @@ static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
}
static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
- const CSSValue& value,
uint16_t id,
const AtomicString& custom_property_name) {
DCHECK_EQ(id, static_cast<uint16_t>(CSSPropertyID::kVariable));
- return static_cast<uint16_t>(metadata.PropertyID()) == id &&
- To<CSSCustomPropertyDeclaration>(value).GetName() ==
- custom_property_name;
+ return metadata.Name() == CSSPropertyName(custom_property_name);
}
static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
- const CSSValue& css_value,
uint16_t id,
AtRuleDescriptorID descriptor_id) {
- return IsPropertyMatch(metadata, css_value, id,
+ return IsPropertyMatch(metadata, id,
AtRuleDescriptorIDAsCSSPropertyID(descriptor_id));
}
@@ -159,7 +154,7 @@ template <typename T>
int ImmutableCSSPropertyValueSet::FindPropertyIndex(T property) const {
uint16_t id = GetConvertedCSSPropertyID(property);
for (int n = array_size_ - 1; n >= 0; --n) {
- if (IsPropertyMatch(MetadataArray()[n], *ValueArray()[n], id, property))
+ if (IsPropertyMatch(MetadataArray()[n], id, property))
return n;
}
@@ -404,16 +399,11 @@ MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty(
context_style_sheet, is_animation_tainted);
}
-void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id,
+void MutableCSSPropertyValueSet::SetProperty(const CSSPropertyName& name,
const CSSValue& value,
bool important) {
- StylePropertyShorthand shorthand = shorthandForProperty(property_id);
+ StylePropertyShorthand shorthand = shorthandForProperty(name.Id());
if (!shorthand.length()) {
- // TODO(crbug.com/1112291): Don't use this function for custom properties.
- CSSPropertyName name =
- (property_id == CSSPropertyID::kVariable)
- ? CSSPropertyName(To<CSSCustomPropertyDeclaration>(value).GetName())
- : CSSPropertyName(property_id);
SetProperty(CSSPropertyValue(name, value, important));
return;
}
@@ -421,11 +411,19 @@ void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id,
RemovePropertiesInSet(shorthand.properties(), shorthand.length());
for (unsigned i = 0; i < shorthand.length(); ++i) {
- CSSPropertyName name(shorthand.properties()[i]->PropertyID());
- property_vector_.push_back(CSSPropertyValue(name, value, important));
+ CSSPropertyName longhand_name(shorthand.properties()[i]->PropertyID());
+ property_vector_.push_back(
+ CSSPropertyValue(longhand_name, value, important));
}
}
+void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id,
+ const CSSValue& value,
+ bool important) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
+ SetProperty(CSSPropertyName(property_id), value, important);
+}
+
bool MutableCSSPropertyValueSet::SetProperty(const CSSPropertyValue& property,
CSSPropertyValue* slot) {
CSSPropertyValue* to_replace =
@@ -435,7 +433,8 @@ bool MutableCSSPropertyValueSet::SetProperty(const CSSPropertyValue& property,
const CSSProperty& prop = CSSProperty::Get(property.Id());
if (prop.IsInLogicalPropertyGroup()) {
DCHECK(property_vector_.Contains(*to_replace));
- int to_replace_index = to_replace - property_vector_.begin();
+ int to_replace_index =
+ static_cast<int>(to_replace - property_vector_.begin());
for (int n = property_vector_.size() - 1; n > to_replace_index; --n) {
if (prop.IsInSameLogicalPropertyGroupWithDifferentMappingLogic(
PropertyAt(n).Id())) {
@@ -663,8 +662,7 @@ int MutableCSSPropertyValueSet::FindPropertyIndex(T property) const {
const CSSPropertyValue* it = std::find_if(
begin, end, [property, id](const CSSPropertyValue& css_property) -> bool {
- return IsPropertyMatch(css_property.Metadata(), *css_property.Value(),
- id, property);
+ return IsPropertyMatch(css_property.Metadata(), id, property);
});
return (it == end) ? -1 : static_cast<int>(it - begin);
@@ -685,8 +683,9 @@ unsigned CSSPropertyValueSet::AverageSizeInBytes() {
// Please update this if the storage scheme changes so that this longer
// reflects the actual size.
return sizeof(ImmutableCSSPropertyValueSet) +
- AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(4)
- .value;
+ static_cast<wtf_size_t>(
+ AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(4)
+ .value);
}
// See the function above if you need to update this.
diff --git a/chromium/third_party/blink/renderer/core/css/css_property_value_set.h b/chromium/third_party/blink/renderer/core/css/css_property_value_set.h
index 701682d8db5..179a1bd2d0c 100644
--- a/chromium/third_party/blink/renderer/core/css/css_property_value_set.h
+++ b/chromium/third_party/blink/renderer/core/css/css_property_value_set.h
@@ -256,6 +256,9 @@ class CORE_EXPORT MutableCSSPropertyValueSet : public CSSPropertyValueSet {
SecureContextMode,
StyleSheetContents* context_style_sheet,
bool is_animation_tainted);
+ void SetProperty(const CSSPropertyName&,
+ const CSSValue&,
+ bool important = false);
void SetProperty(CSSPropertyID, const CSSValue&, bool important = false);
// These do not. FIXME: This is too messy, we can do better.
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 899ccc80900..75d97712dd6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.cc
@@ -33,10 +33,10 @@ struct SameSizeAsCSSRule : public GarbageCollected<SameSizeAsCSSRule>,
~SameSizeAsCSSRule() override;
unsigned char bitfields;
Member<ScriptWrappable> member;
-#if !DCHECK_IS_ON()
- // Increasing size of Member increases size of CSSRule.
- ASSERT_SIZE(Member<ScriptWrappable>, void*);
-#endif // DCHECK_IS_ON()
+ static_assert(kBlinkGCHasDebugChecks ||
+ ::WTF::internal::SizesEqual<sizeof(Member<ScriptWrappable>),
+ sizeof(void*)>::value,
+ "Member<ScriptWrappable> should stay small");
};
ASSERT_SIZE(CSSRule, SameSizeAsCSSRule);
diff --git a/chromium/third_party/blink/renderer/core/css/css_rule.idl b/chromium/third_party/blink/renderer/core/css/css_rule.idl
index 51d0c6aec33..972a4f1ba00 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.idl
@@ -44,7 +44,6 @@
// CSS Counter Styles
// https://drafts.csswg.org/css-counter-styles-3/#extentions-to-cssrule-interface
- [RuntimeEnabled=CSSAtRuleCounterStyle]
const unsigned short COUNTER_STYLE_RULE = 11;
// CSS Conditional Rules
diff --git a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc
index 19119d7dcc9..8c5d0daada5 100644
--- a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc
@@ -98,11 +98,9 @@ scoped_refptr<FontData> CSSSegmentedFontFace::GetFontData(
if (!IsValid())
return nullptr;
- const FontSelectionRequest& font_selection_request =
- font_description.GetFontSelectionRequest();
bool is_unique_match = false;
- FontCacheKey key = font_description.CacheKey(
- FontFaceCreationParams(), is_unique_match, font_selection_request);
+ FontCacheKey key =
+ font_description.CacheKey(FontFaceCreationParams(), is_unique_match);
// font_data_table_ caches FontData and SegmentedFontData instances, which
// provide SimpleFontData objects containing FontPlatformData objects. In the
@@ -127,6 +125,8 @@ scoped_refptr<FontData> CSSSegmentedFontFace::GetFontData(
FontDescription requested_font_description(font_description);
if (!font_selection_capabilities_.HasRange()) {
+ const FontSelectionRequest& font_selection_request =
+ font_description.GetFontSelectionRequest();
requested_font_description.SetSyntheticBold(
font_selection_capabilities_.weight.maximum < BoldThreshold() &&
font_selection_request.weight >= BoldThreshold());
diff --git a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h
index 3e4b7356b92..f343ceb3ef6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h
+++ b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h
@@ -50,7 +50,7 @@ class SegmentedFontData;
// Iterating over the combined set, behaves as if all non-CSS-connected
// FontFaces were stored after the CSS-connected ones.
class FontFaceList : public GarbageCollected<FontFaceList> {
- using FontFaceListPart = HeapListHashSet<Member<FontFace>>;
+ using FontFaceListPart = HeapLinkedHashSet<Member<FontFace>>;
public:
bool IsEmpty() const;
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 b49259d641e..d19412d4667 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_selector.cc
@@ -29,7 +29,7 @@
#include <algorithm>
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/css/css_markup.h"
#include "third_party/blink/renderer/core/css/css_selector_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
@@ -143,6 +143,10 @@ inline unsigned CSSSelector::SpecificityForOneSelector() const {
FALLTHROUGH;
case kPseudoIs:
return MaximumSpecificity(SelectorList());
+ case kPseudoHas:
+ return MaximumSpecificity(SelectorList());
+ case kPseudoRelativeLeftmost:
+ return 0;
// FIXME: PseudoAny should base the specificity on the sub-selectors.
// See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html
case kPseudoAny:
@@ -341,6 +345,8 @@ PseudoId CSSSelector::GetPseudoId(PseudoType type) {
case kPseudoVideoPersistentAncestor:
case kPseudoXrOverlay:
case kPseudoModal:
+ case kPseudoHas:
+ case kPseudoRelativeLeftmost:
return kPseudoIdNone;
}
@@ -368,6 +374,7 @@ const static NameToPseudoStruct kPseudoTypeWithoutArgumentsMap[] = {
{"-internal-modal", CSSSelector::kPseudoModal},
{"-internal-multi-select-focus", CSSSelector::kPseudoMultiSelectFocus},
{"-internal-popup-open", CSSSelector::kPseudoPopupOpen},
+ {"-internal-relative-leftmost", CSSSelector::kPseudoRelativeLeftmost},
{"-internal-shadow-host-has-appearance",
CSSSelector::kPseudoHostHasAppearance},
{"-internal-spatial-navigation-focus",
@@ -464,6 +471,7 @@ const static NameToPseudoStruct kPseudoTypeWithArgumentsMap[] = {
{"-webkit-any", CSSSelector::kPseudoAny},
{"cue", CSSSelector::kPseudoCue},
{"dir", CSSSelector::kPseudoDir},
+ {"has", CSSSelector::kPseudoHas},
{"highlight", CSSSelector::kPseudoHighlight},
{"host", CSSSelector::kPseudoHost},
{"host-context", CSSSelector::kPseudoHostContext},
@@ -545,6 +553,11 @@ CSSSelector::PseudoType CSSSelector::NameToPseudoType(const AtomicString& name,
return CSSSelector::kPseudoUnknown;
}
+ if (match->type == CSSSelector::kPseudoHas &&
+ !RuntimeEnabledFeatures::CSSPseudoHasInSnapshotProfileEnabled()) {
+ return CSSSelector::kPseudoUnknown;
+ }
+
return static_cast<CSSSelector::PseudoType>(match->type);
}
@@ -688,6 +701,7 @@ void CSSSelector::UpdatePseudoType(const AtomicString& value,
case kPseudoFullScreenAncestor:
case kPseudoFullscreen:
case kPseudoFutureCue:
+ case kPseudoHas:
case kPseudoHorizontal:
case kPseudoHost:
case kPseudoHostContext:
@@ -719,6 +733,7 @@ void CSSSelector::UpdatePseudoType(const AtomicString& value,
case kPseudoPastCue:
case kPseudoReadOnly:
case kPseudoReadWrite:
+ case kPseudoRelativeLeftmost:
case kPseudoRequired:
case kPseudoRoot:
case kPseudoScope:
@@ -848,6 +863,7 @@ const CSSSelector* CSSSelector::SerializeCompound(
SerializeIdentifier(simple_selector->Argument(), builder);
builder.Append(')');
break;
+ case kPseudoHas:
case kPseudoNot:
DCHECK(simple_selector->SelectorList());
break;
@@ -861,6 +877,9 @@ const CSSSelector* CSSSelector::SerializeCompound(
case kPseudoIs:
case kPseudoWhere:
break;
+ case kPseudoRelativeLeftmost:
+ NOTREACHED();
+ return nullptr;
default:
break;
}
@@ -984,6 +1003,14 @@ String CSSSelector::SelectorText() const {
case kShadowSlot:
result = builder.ToString() + result;
break;
+ case kRelativeDescendant:
+ return builder.ToString() + result;
+ case kRelativeChild:
+ return "> " + builder.ToString() + result;
+ case kRelativeDirectAdjacent:
+ return "+ " + builder.ToString() + result;
+ case kRelativeIndirectAdjacent:
+ return "~ " + builder.ToString() + result;
}
}
NOTREACHED();
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 540f8a693fd..e850dc4e11f 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector.h
+++ b/chromium/third_party/blink/renderer/core/css/css_selector.h
@@ -156,6 +156,15 @@ class CORE_EXPORT CSSSelector {
// matching a ::part in shadow-including descendant tree for #host in
// "#host::part(button)".
kShadowPart,
+
+ // leftmost "Space" combinator of relative selector
+ kRelativeDescendant,
+ // leftmost > combinator of relative selector
+ kRelativeChild,
+ // leftmost + combinator of relative selector
+ kRelativeDirectAdjacent,
+ // leftmost ~ combinator of relative selector
+ kRelativeIndirectAdjacent
};
enum PseudoType {
@@ -276,6 +285,12 @@ class CORE_EXPORT CSSSelector {
kPseudoHighlight,
kPseudoSpellingError,
kPseudoGrammarError,
+ kPseudoHas,
+ // TODO(blee@igalia.com) Need to clarify the :scope dependency in relative
+ // selector definition.
+ // - spec : https://www.w3.org/TR/selectors-4/#relative
+ // - csswg issue : https://github.com/w3c/csswg-drafts/issues/6399
+ kPseudoRelativeLeftmost,
};
enum class AttributeMatchType {
diff --git a/chromium/third_party/blink/renderer/core/css/css_selector_test.cc b/chromium/third_party/blink/renderer/core/css/css_selector_test.cc
index a376702b8e8..fa4bbff759b 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_selector_test.cc
@@ -152,6 +152,24 @@ TEST(CSSSelector, Specificity_Not) {
Specificity(":is(.c + .c + .c, .b + .c:not(span), .b + .c + .e)"));
}
+TEST(CSSSelector, Specificity_Has) {
+ EXPECT_EQ(Specificity(":has(div)"), Specificity("div"));
+ EXPECT_EQ(Specificity(":has(div)"), Specificity("* div"));
+ EXPECT_EQ(Specificity(":has(~ div)"), Specificity("* ~ div"));
+ EXPECT_EQ(Specificity(":has(> .a)"), Specificity("* > .a"));
+ EXPECT_EQ(Specificity(":has(+ div.a)"), Specificity("* + div.a"));
+ EXPECT_EQ(Specificity(".a :has(.b, div.c)"), Specificity(".a div.c"));
+ EXPECT_EQ(Specificity(".a :has(.c#d, .e)"), Specificity(".a .c#d"));
+ EXPECT_EQ(Specificity(":has(.e+.f, .g>.b, .h)"), Specificity(".e+.f"));
+ EXPECT_EQ(Specificity(".a :has(.e+.f, .g>.b, .h#i)"), Specificity(".a .h#i"));
+ EXPECT_EQ(Specificity(".a+:has(.b+span.f, :has(.c>.e, .g))"),
+ Specificity(".a+.b+span.f"));
+ EXPECT_EQ(Specificity("div > :has(div:where(span:where(.b ~ .c)))"),
+ Specificity("div > div"));
+ EXPECT_EQ(Specificity(":has(.c + .c + .c, .b + .c:not(span), .b + .c + .e)"),
+ Specificity(".c + .c + .c"));
+}
+
TEST(CSSSelector, HasLinkOrVisited) {
EXPECT_FALSE(HasLinkOrVisited("tag"));
EXPECT_FALSE(HasLinkOrVisited("visited"));
diff --git a/chromium/third_party/blink/renderer/core/css/css_selector_watch_test.cc b/chromium/third_party/blink/renderer/core/css/css_selector_watch_test.cc
index 46e58f5f810..fdeba848587 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector_watch_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_selector_watch_test.cc
@@ -83,4 +83,53 @@ TEST_F(CSSSelectorWatchTest, RecalcOnDocumentChange) {
EXPECT_TRUE(RemovedSelectors(watch).Contains(".b"));
}
+class CSSSelectorWatchCQTest : public CSSSelectorWatchTest,
+ private ScopedCSSContainerQueriesForTest {
+ protected:
+ CSSSelectorWatchCQTest() : ScopedCSSContainerQueriesForTest(true) {}
+};
+
+TEST_F(CSSSelectorWatchCQTest, ContainerQueryDisplayNone) {
+ CSSSelectorWatch& watch = CSSSelectorWatch::From(GetDocument());
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ .c #container {
+ container-name: c1;
+ container-type: inline-size;
+ }
+ .c #inner { display: none; }
+ @container c1 (min-width: 200px) {
+ .c #inner { display: inline }
+ }
+ </style>
+ <div id="container">
+ <span id="inner"></span>
+ </div>
+ )HTML");
+
+ Vector<String> selectors;
+ selectors.push_back("#inner");
+ watch.WatchCSSSelectors(selectors);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(1u, AddedSelectors(watch).size());
+ EXPECT_TRUE(AddedSelectors(watch).Contains("#inner"));
+ EXPECT_EQ(0u, RemovedSelectors(watch).size());
+
+ // Setting the class 'c' on body will make #inner display:none, but also make
+ // #container a container 'c1' which is flipping the span back to
+ // display:inline.
+ ClearAddedRemoved(watch);
+ GetDocument().body()->setAttribute(html_names::kClassAttr, "c");
+ UpdateAllLifecyclePhasesForTest();
+
+ // Element::UpdateCallbackSelectors() will both remove and add #inner in the
+ // two passes. First without the CQ matching, and then in an interleaved style
+ // and layout pass. The accounting in CSSSelectorWatch::UpdateSelectorMatches
+ // will make sure we up with a zero balance.
+ EXPECT_EQ(0u, AddedSelectors(watch).size());
+ EXPECT_EQ(0u, RemovedSelectors(watch).size());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_string_value.h b/chromium/third_party/blink/renderer/core/css/css_string_value.h
index 7c9d034c9d8..bdf43558936 100644
--- a/chromium/third_party/blink/renderer/core/css/css_string_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_string_value.h
@@ -15,7 +15,7 @@ class CORE_EXPORT CSSStringValue : public CSSValue {
public:
CSSStringValue(const String&);
- String Value() const { return string_; }
+ const String& Value() const { return string_; }
String CustomCSSText() const;
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 ae168e9ad64..7542d526a79 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
@@ -24,7 +24,7 @@
Exposed=Window
] interface CSSStyleDeclaration {
[CEReactions, RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString cssText;
- [Affects=Nothing] readonly attribute unsigned long length;
+ readonly attribute unsigned long length;
[Affects=Nothing] getter DOMString item(unsigned long index);
DOMString getPropertyValue(DOMString property);
DOMString getPropertyPriority(DOMString property);
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 ed2308f3949..ae1a1272629 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,11 +20,11 @@
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
-#include "third_party/blink/renderer/bindings/core/v8/media_list_or_string.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"
#include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_medialist_string.h"
#include "third_party/blink/renderer/core/css/css_import_rule.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/media_list.h"
@@ -96,34 +96,21 @@ const Document* CSSStyleSheet::SingleOwnerDocument(
CSSStyleSheet* CSSStyleSheet::Create(Document& document,
const CSSStyleSheetInit* options,
ExceptionState& exception_state) {
- auto* parser_context = MakeGarbageCollected<CSSParserContext>(document);
+ return CSSStyleSheet::Create(document, document.BaseURL(), options,
+ exception_state);
+}
+
+CSSStyleSheet* CSSStyleSheet::Create(Document& document,
+ const KURL& base_url,
+ const CSSStyleSheetInit* options,
+ ExceptionState& exception_state) {
+ auto* parser_context =
+ MakeGarbageCollected<CSSParserContext>(document, base_url);
if (AdTracker::IsAdScriptExecutingInDocument(&document))
parser_context->SetIsAdRelated();
- // Following steps at spec draft
- // https://wicg.github.io/construct-stylesheets/#dom-cssstylesheet-cssstylesheet
auto* contents = MakeGarbageCollected<StyleSheetContents>(parser_context);
- CSSStyleSheet* sheet = MakeGarbageCollected<CSSStyleSheet>(contents, nullptr);
- sheet->SetConstructorDocument(document);
- sheet->SetTitle(options->title());
- sheet->ClearOwnerNode();
- sheet->ClearOwnerRule();
- contents->RegisterClient(sheet);
- scoped_refptr<MediaQuerySet> media_query_set;
- if (options->media().IsString()) {
- media_query_set = MediaQuerySet::Create(options->media().GetAsString(),
- document.GetExecutionContext());
- } else {
- media_query_set = options->media().GetAsMediaList()->Queries()->Copy();
- }
- auto* media_list = MakeGarbageCollected<MediaList>(
- media_query_set, const_cast<CSSStyleSheet*>(sheet));
- sheet->SetMedia(media_list);
- if (options->alternate())
- sheet->SetAlternateFromConstructor(true);
- if (options->disabled())
- sheet->setDisabled(true);
- return sheet;
+ return MakeGarbageCollected<CSSStyleSheet>(contents, document, options);
}
CSSStyleSheet* CSSStyleSheet::CreateInline(StyleSheetContents* sheet,
@@ -143,10 +130,13 @@ CSSStyleSheet* CSSStyleSheet::CreateInline(Node& owner_node,
owner_node_document, owner_node_document.BaseURL(),
true /* origin_clean */,
Referrer(
- owner_node_document.GetExecutionContext()
- ? owner_node_document.GetExecutionContext()->OutgoingReferrer()
- : String(), // GetExecutionContext() only returns null in tests.
- owner_node.GetDocument().GetReferrerPolicy()),
+ // Fetch requests from an inline CSS use the referrer of the owner
+ // document. `Referrer::ClientReferrerString()` for a fetch request
+ // just means "use the default referrer", which will be computed from
+ // the client (in this case, the owner document's ExecutionContext)
+ // when fetching.
+ Referrer::ClientReferrerString(),
+ network::mojom::ReferrerPolicy::kDefault),
encoding);
if (AdTracker::IsAdScriptExecutingInDocument(&owner_node.GetDocument()))
parser_context->SetIsAdRelated();
@@ -165,6 +155,36 @@ CSSStyleSheet::CSSStyleSheet(StyleSheetContents* contents,
}
CSSStyleSheet::CSSStyleSheet(StyleSheetContents* contents,
+ Document& document,
+ const CSSStyleSheetInit* options)
+ : CSSStyleSheet(contents, nullptr) {
+ // Following steps at spec draft
+ // https://wicg.github.io/construct-stylesheets/#dom-cssstylesheet-cssstylesheet
+ SetConstructorDocument(document);
+ SetTitle(options->title());
+ ClearOwnerNode();
+ ClearOwnerRule();
+ Contents()->RegisterClient(this);
+ scoped_refptr<MediaQuerySet> media_query_set;
+ switch (options->media()->GetContentType()) {
+ case V8UnionMediaListOrString::ContentType::kMediaList:
+ media_query_set = options->media()->GetAsMediaList()->Queries()->Copy();
+ break;
+ case V8UnionMediaListOrString::ContentType::kString:
+ media_query_set = MediaQuerySet::Create(options->media()->GetAsString(),
+ document.GetExecutionContext());
+ break;
+ }
+ auto* media_list = MakeGarbageCollected<MediaList>(
+ media_query_set, const_cast<CSSStyleSheet*>(this));
+ SetMedia(media_list);
+ if (options->alternate())
+ SetAlternateFromConstructor(true);
+ if (options->disabled())
+ setDisabled(true);
+}
+
+CSSStyleSheet::CSSStyleSheet(StyleSheetContents* contents,
Node& owner_node,
bool is_inline_stylesheet,
const TextPosition& start_position)
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 7445ecc6a67..76d4d3247b9 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
@@ -60,7 +60,10 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
static CSSStyleSheet* Create(Document&,
const CSSStyleSheetInit*,
ExceptionState&);
-
+ static CSSStyleSheet* Create(Document&,
+ const KURL& base_url,
+ const CSSStyleSheetInit*,
+ ExceptionState&);
static CSSStyleSheet* CreateInline(
Node&,
const KURL&,
@@ -73,6 +76,7 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
explicit CSSStyleSheet(StyleSheetContents*,
CSSImportRule* owner_rule = nullptr);
+ CSSStyleSheet(StyleSheetContents*, Document&, const CSSStyleSheetInit*);
CSSStyleSheet(
StyleSheetContents*,
Node& owner_node,
@@ -209,6 +213,8 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
void SetAlternateFromConstructor(bool);
bool CanBeActivated(const String& current_preferrable_name) const;
bool IsConstructed() const { return ConstructorDocument(); }
+ void SetIsForCSSModuleScript() { is_for_css_module_script_ = true; }
+ bool IsForCSSModuleScript() const { return is_for_css_module_script_; }
void Trace(Visitor*) const override;
@@ -247,6 +253,7 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
Member<StyleSheetContents> contents_;
bool is_inline_stylesheet_ = false;
+ bool is_for_css_module_script_ = false;
bool is_disabled_ = false;
bool load_completed_ = false;
// This alternate variable is only used for constructed CSSStyleSheet.
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 2ecb48e21a4..6fc7921930b 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
@@ -3,15 +3,16 @@
// 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/public/web/web_heap.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/bindings/core/v8/v8_css_style_sheet_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_medialist_string.h"
#include "third_party/blink/renderer/core/css/css_rule.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/media_list.h"
@@ -56,7 +57,8 @@ TEST_F(CSSStyleSheetTest,
CSSStyleSheetConstructionWithNonEmptyCSSStyleSheetInit) {
DummyExceptionStateForTesting exception_state;
CSSStyleSheetInit* init = CSSStyleSheetInit::Create();
- init->setMedia(MediaListOrString::FromString("screen, print"));
+ init->setMedia(
+ MakeGarbageCollected<V8UnionMediaListOrString>("screen, print"));
init->setTitle("test");
init->setAlternate(true);
init->setDisabled(true);
@@ -68,7 +70,7 @@ TEST_F(CSSStyleSheetTest,
EXPECT_EQ(sheet->ownerNode(), nullptr);
EXPECT_EQ(sheet->ownerRule(), nullptr);
EXPECT_EQ(sheet->media()->length(), 2U);
- EXPECT_EQ(sheet->media()->mediaText(nullptr), init->media().GetAsString());
+ EXPECT_EQ(sheet->media()->mediaText(nullptr), init->media()->GetAsString());
EXPECT_EQ(sheet->title(), init->title());
EXPECT_TRUE(sheet->AlternateFromConstructor());
EXPECT_TRUE(sheet->disabled());
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_component.h b/chromium/third_party/blink/renderer/core/css/css_syntax_component.h
index a4e11012a48..3dbd4b4433f 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_component.h
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_component.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_SYNTAX_COMPONENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_SYNTAX_COMPONENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/css/css_test_helpers.h b/chromium/third_party/blink/renderer/core/css/css_test_helpers.h
index 4d33d3c13c3..90f05d47813 100644
--- a/chromium/third_party/blink/renderer/core/css/css_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/css/css_test_helpers.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TEST_HELPERS_H_
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/css_selector_list.h"
#include "third_party/blink/renderer/core/css/rule_set.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc b/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc
index f7c4f68e909..1061859eeb6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc
@@ -30,12 +30,72 @@
#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
+#include "third_party/blink/renderer/core/css/container_query_evaluator.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
+namespace {
+
+PhysicalAxes SupportedAxes(const ComputedStyle& style) {
+ LogicalAxes supported(kLogicalAxisNone);
+ if (style.ContainerType() & kContainerTypeInlineSize)
+ supported |= LogicalAxes(kLogicalAxisInline);
+ if (style.ContainerType() & kContainerTypeBlockSize)
+ supported |= LogicalAxes(kLogicalAxisBlock);
+ return ToPhysicalAxes(supported, style.GetWritingMode());
+}
+
+absl::optional<double> FindSizeForContainerAxis(PhysicalAxes physical_axes,
+ LogicalAxes logical_axes,
+ Element* nearest_container) {
+ // Exactly one physical *or* logical axis must be provided.
+ DCHECK(physical_axes == PhysicalAxes(kPhysicalAxisNone) ||
+ logical_axes == LogicalAxes(kLogicalAxisNone));
+ DCHECK(physical_axes == PhysicalAxes(kPhysicalAxisHorizontal) ||
+ physical_axes == PhysicalAxes(kPhysicalAxisVertical) ||
+ logical_axes == LogicalAxes(kLogicalAxisInline) ||
+ logical_axes == LogicalAxes(kLogicalAxisBlock));
+
+ for (Element* element = nearest_container; element;
+ element = LayoutTreeBuilderTraversal::ParentElement(*element)) {
+ auto* evaluator = element->GetContainerQueryEvaluator();
+ if (!evaluator)
+ continue;
+ const ComputedStyle* style = element->GetComputedStyle();
+ if (!style)
+ continue;
+ PhysicalAxes requested_axes =
+ physical_axes | ToPhysicalAxes(logical_axes, style->GetWritingMode());
+ if ((requested_axes & SupportedAxes(*style)) != requested_axes)
+ continue;
+ evaluator->SetReferencedByUnit();
+ if (requested_axes == PhysicalAxes(kPhysicalAxisHorizontal))
+ return evaluator->Width();
+ DCHECK_EQ(requested_axes, PhysicalAxes(kPhysicalAxisVertical));
+ return evaluator->Height();
+ }
+ return absl::nullopt;
+}
+
+absl::optional<double> FindSizeForContainerAxis(PhysicalAxes physical_axes,
+ Element* nearest_container) {
+ return FindSizeForContainerAxis(physical_axes, LogicalAxes(kLogicalAxisNone),
+ nearest_container);
+}
+
+absl::optional<double> FindSizeForContainerAxis(LogicalAxes logical_axes,
+ Element* nearest_container) {
+ return FindSizeForContainerAxis(PhysicalAxes(kLogicalAxisNone), logical_axes,
+ nearest_container);
+}
+
+} // namespace
+
CSSToLengthConversionData::FontSizes::FontSizes(float em,
float rem,
const Font* font,
@@ -77,24 +137,70 @@ CSSToLengthConversionData::ViewportSize::ViewportSize(
: size_(layout_view ? layout_view->ViewportSizeForViewportUnits()
: DoubleSize()) {}
+absl::optional<double> CSSToLengthConversionData::ContainerSizes::Width()
+ const {
+ CacheSizeIfNeeded(PhysicalAxes(kPhysicalAxisHorizontal), cached_width_);
+ return cached_width_;
+}
+
+absl::optional<double> CSSToLengthConversionData::ContainerSizes::Height()
+ const {
+ CacheSizeIfNeeded(PhysicalAxes(kPhysicalAxisVertical), cached_height_);
+ return cached_height_;
+}
+
+absl::optional<double> CSSToLengthConversionData::ContainerSizes::InlineSize()
+ const {
+ CacheSizeIfNeeded(LogicalAxes(kLogicalAxisInline), cached_inline_size_);
+ return cached_inline_size_;
+}
+
+absl::optional<double> CSSToLengthConversionData::ContainerSizes::BlockSize()
+ const {
+ CacheSizeIfNeeded(LogicalAxes(kLogicalAxisBlock), cached_block_size_);
+ return cached_block_size_;
+}
+
+void CSSToLengthConversionData::ContainerSizes::CacheSizeIfNeeded(
+ PhysicalAxes requested_axis,
+ absl::optional<double>& cache) const {
+ if ((cached_physical_axes_ & requested_axis) == requested_axis)
+ return;
+ cached_physical_axes_ |= requested_axis;
+ cache = FindSizeForContainerAxis(requested_axis, nearest_container_);
+}
+
+void CSSToLengthConversionData::ContainerSizes::CacheSizeIfNeeded(
+ LogicalAxes requested_axis,
+ absl::optional<double>& cache) const {
+ if ((cached_logical_axes_ & requested_axis) == requested_axis)
+ return;
+ cached_logical_axes_ |= requested_axis;
+ cache = FindSizeForContainerAxis(requested_axis, nearest_container_);
+}
+
CSSToLengthConversionData::CSSToLengthConversionData(
const ComputedStyle* style,
const FontSizes& font_sizes,
const ViewportSize& viewport_size,
+ const ContainerSizes& container_sizes,
float zoom)
: style_(style),
font_sizes_(font_sizes),
viewport_size_(viewport_size),
+ container_sizes_(container_sizes),
zoom_(clampTo<float>(zoom, std::numeric_limits<float>::denorm_min())) {}
CSSToLengthConversionData::CSSToLengthConversionData(
const ComputedStyle* style,
const ComputedStyle* root_style,
const LayoutView* layout_view,
+ Element* nearest_container,
float zoom)
: CSSToLengthConversionData(style,
FontSizes(style, root_style),
ViewportSize(layout_view),
+ ContainerSizes(nearest_container),
zoom) {}
double CSSToLengthConversionData::ViewportWidthPercent() const {
@@ -121,6 +227,50 @@ double CSSToLengthConversionData::ViewportMaxPercent() const {
return std::max(viewport_size_.Width(), viewport_size_.Height()) / 100;
}
+double CSSToLengthConversionData::ContainerWidthPercent() const {
+ if (style_)
+ const_cast<ComputedStyle*>(style_)->SetHasContainerRelativeUnits();
+ if (absl::optional<double> size = container_sizes_.Width())
+ return *size / 100;
+ // TODO(crbug.com/1223030): Support "small viewport size".
+ return ViewportWidthPercent();
+}
+
+double CSSToLengthConversionData::ContainerHeightPercent() const {
+ if (style_)
+ const_cast<ComputedStyle*>(style_)->SetHasContainerRelativeUnits();
+ if (absl::optional<double> size = container_sizes_.Height())
+ return *size / 100;
+ // // TODO(crbug.com/1223030): Support "small viewport size".
+ return ViewportHeightPercent();
+}
+
+double CSSToLengthConversionData::ContainerInlineSizePercent() const {
+ if (style_)
+ const_cast<ComputedStyle*>(style_)->SetHasContainerRelativeUnits();
+ if (absl::optional<double> size = container_sizes_.InlineSize())
+ return *size / 100;
+ // TODO(crbug.com/1223030): Support "small viewport size".
+ return ViewportWidthPercent();
+}
+
+double CSSToLengthConversionData::ContainerBlockSizePercent() const {
+ if (style_)
+ const_cast<ComputedStyle*>(style_)->SetHasContainerRelativeUnits();
+ if (absl::optional<double> size = container_sizes_.BlockSize())
+ return *size / 100;
+ // TODO(crbug.com/1223030): Support "small viewport size".
+ return ViewportHeightPercent();
+}
+
+double CSSToLengthConversionData::ContainerMinPercent() const {
+ return std::min(ContainerWidthPercent(), ContainerHeightPercent());
+}
+
+double CSSToLengthConversionData::ContainerMaxPercent() const {
+ return std::max(ContainerWidthPercent(), ContainerHeightPercent());
+}
+
float CSSToLengthConversionData::EmFontSize() const {
if (style_)
const_cast<ComputedStyle*>(style_)->SetHasEmUnits();
@@ -187,6 +337,24 @@ double CSSToLengthConversionData::ZoomedComputedPixels(
case CSSPrimitiveValue::UnitType::kViewportMax:
return value * ViewportMaxPercent() * Zoom();
+ case CSSPrimitiveValue::UnitType::kContainerWidth:
+ return value * ContainerWidthPercent() * Zoom();
+
+ case CSSPrimitiveValue::UnitType::kContainerHeight:
+ return value * ContainerHeightPercent() * Zoom();
+
+ case CSSPrimitiveValue::UnitType::kContainerInlineSize:
+ return value * ContainerInlineSizePercent() * Zoom();
+
+ case CSSPrimitiveValue::UnitType::kContainerBlockSize:
+ return value * ContainerBlockSizePercent() * Zoom();
+
+ case CSSPrimitiveValue::UnitType::kContainerMin:
+ return value * ContainerMinPercent() * Zoom();
+
+ case CSSPrimitiveValue::UnitType::kContainerMax:
+ return value * ContainerMaxPercent() * Zoom();
+
// We do not apply the zoom factor when we are computing the value of the
// font-size property. The zooming for font sizes is much more complicated,
// since we have to worry about enforcing the minimum font size preference
diff --git a/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.h b/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.h
index 654862aa8ed..9438a944d29 100644
--- a/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.h
+++ b/chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.h
@@ -32,9 +32,12 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TO_LENGTH_CONVERSION_DATA_H_
#include <limits>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
+#include "third_party/blink/renderer/core/layout/geometry/axis.h"
#include "third_party/blink/renderer/platform/geometry/double_size.h"
+#include "third_party/blink/renderer/platform/text/writing_mode.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -43,6 +46,7 @@ namespace blink {
class ComputedStyle;
class LayoutView;
class Font;
+class Element;
class CORE_EXPORT CSSToLengthConversionData {
STACK_ALLOCATED();
@@ -84,14 +88,42 @@ class CORE_EXPORT CSSToLengthConversionData {
DoubleSize size_;
};
+ class CORE_EXPORT ContainerSizes {
+ STACK_ALLOCATED();
+
+ public:
+ ContainerSizes() = default;
+ explicit ContainerSizes(Element* nearest_container)
+ : nearest_container_(nearest_container) {}
+
+ absl::optional<double> Width() const;
+ absl::optional<double> Height() const;
+ absl::optional<double> InlineSize() const;
+ absl::optional<double> BlockSize() const;
+
+ private:
+ void CacheSizeIfNeeded(LogicalAxes, absl::optional<double>& cache) const;
+ void CacheSizeIfNeeded(PhysicalAxes, absl::optional<double>& cache) const;
+
+ Element* nearest_container_{nullptr};
+ mutable PhysicalAxes cached_physical_axes_{kPhysicalAxisNone};
+ mutable LogicalAxes cached_logical_axes_{kLogicalAxisNone};
+ mutable absl::optional<double> cached_width_;
+ mutable absl::optional<double> cached_height_;
+ mutable absl::optional<double> cached_inline_size_;
+ mutable absl::optional<double> cached_block_size_;
+ };
+
CSSToLengthConversionData() : style_(nullptr), zoom_(1) {}
CSSToLengthConversionData(const ComputedStyle*,
const FontSizes&,
const ViewportSize&,
+ const ContainerSizes&,
float zoom);
CSSToLengthConversionData(const ComputedStyle* curr_style,
const ComputedStyle* root_style,
const LayoutView*,
+ Element* nearest_container,
float zoom);
float Zoom() const { return zoom_; }
@@ -108,16 +140,27 @@ class CORE_EXPORT CSSToLengthConversionData {
double ViewportMinPercent() const;
double ViewportMaxPercent() const;
+ // Accessing these marks the style as having container relative units.
+ double ContainerWidthPercent() const;
+ double ContainerHeightPercent() const;
+ double ContainerInlineSizePercent() const;
+ double ContainerBlockSizePercent() const;
+ double ContainerMinPercent() const;
+ double ContainerMaxPercent() const;
+
void SetFontSizes(const FontSizes& font_sizes) { font_sizes_ = font_sizes; }
void SetZoom(float zoom) {
DCHECK(std::isfinite(zoom));
DCHECK_GT(zoom, 0);
zoom_ = zoom;
}
+ void SetContainerSizes(const ContainerSizes& container_sizes) {
+ container_sizes_ = container_sizes;
+ }
CSSToLengthConversionData CopyWithAdjustedZoom(float new_zoom) const {
return CSSToLengthConversionData(style_, font_sizes_, viewport_size_,
- new_zoom);
+ container_sizes_, new_zoom);
}
double ZoomedComputedPixels(double value, CSSPrimitiveValue::UnitType) const;
@@ -126,6 +169,7 @@ class CORE_EXPORT CSSToLengthConversionData {
const ComputedStyle* style_;
FontSizes font_sizes_;
ViewportSize viewport_size_;
+ ContainerSizes container_sizes_;
float zoom_;
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_unicode_range_value.h b/chromium/third_party/blink/renderer/core/css/css_unicode_range_value.h
index 4db1508cd36..f49be2e3204 100644
--- a/chromium/third_party/blink/renderer/core/css/css_unicode_range_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_unicode_range_value.h
@@ -28,7 +28,7 @@
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
namespace cssvalue {
diff --git a/chromium/third_party/blink/renderer/core/css/css_value.cc b/chromium/third_party/blink/renderer/core/css/css_value.cc
index bb2cb20d33c..102f6d6d5d4 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_value.cc
@@ -65,6 +65,7 @@
#include "third_party/blink/renderer/core/css/css_paint_value.h"
#include "third_party/blink/renderer/core/css/css_path_value.h"
#include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_quad_value.h"
#include "third_party/blink/renderer/core/css/css_ray_value.h"
@@ -96,6 +97,7 @@ CSSValue* CSSValue::Create(const Length& value, float zoom) {
case Length::kMaxContent:
case Length::kFillAvailable:
case Length::kFitContent:
+ case Length::kContent:
case Length::kExtendToZoom:
return CSSIdentifierValue::Create(value);
case Length::kPercent:
@@ -278,6 +280,9 @@ bool CSSValue::operator==(const CSSValue& other) const {
case kPendingSubstitutionValueClass:
return CompareCSSValues<cssvalue::CSSPendingSubstitutionValue>(*this,
other);
+ case kPendingSystemFontValueClass:
+ return CompareCSSValues<cssvalue::CSSPendingSystemFontValue>(*this,
+ other);
case kInvalidVariableValueClass:
return CompareCSSValues<CSSInvalidVariableValue>(*this, other);
case kCyclicVariableValueClass:
@@ -404,6 +409,8 @@ String CSSValue::CssText() const {
return To<CSSCustomPropertyDeclaration>(this)->CustomCSSText();
case kPendingSubstitutionValueClass:
return To<cssvalue::CSSPendingSubstitutionValue>(this)->CustomCSSText();
+ case kPendingSystemFontValueClass:
+ return To<cssvalue::CSSPendingSystemFontValue>(this)->CustomCSSText();
case kInvalidVariableValueClass:
return To<CSSInvalidVariableValue>(this)->CustomCSSText();
case kCyclicVariableValueClass:
@@ -588,6 +595,10 @@ void CSSValue::FinalizeGarbageCollectedObject() {
To<cssvalue::CSSPendingSubstitutionValue>(this)
->~CSSPendingSubstitutionValue();
return;
+ case kPendingSystemFontValueClass:
+ To<cssvalue::CSSPendingSystemFontValue>(this)
+ ->~CSSPendingSystemFontValue();
+ return;
case kInvalidVariableValueClass:
To<CSSInvalidVariableValue>(this)->~CSSInvalidVariableValue();
return;
@@ -776,6 +787,10 @@ void CSSValue::Trace(Visitor* visitor) const {
To<cssvalue::CSSPendingSubstitutionValue>(this)->TraceAfterDispatch(
visitor);
return;
+ case kPendingSystemFontValueClass:
+ To<cssvalue::CSSPendingSystemFontValue>(this)->TraceAfterDispatch(
+ visitor);
+ return;
case kInvalidVariableValueClass:
To<CSSInvalidVariableValue>(this)->TraceAfterDispatch(visitor);
return;
diff --git a/chromium/third_party/blink/renderer/core/css/css_value.h b/chromium/third_party/blink/renderer/core/css/css_value.h
index a26ea3330e4..abcd472d36c 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value.h
@@ -166,6 +166,9 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
bool IsPendingSubstitutionValue() const {
return class_type_ == kPendingSubstitutionValueClass;
}
+ bool IsPendingSystemFontValue() const {
+ return class_type_ == kPendingSystemFontValueClass;
+ }
bool IsInvalidVariableValue() const {
return class_type_ == kInvalidVariableValueClass ||
class_type_ == kCyclicVariableValueClass;
@@ -265,6 +268,7 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
kVariableReferenceClass,
kCustomPropertyDeclarationClass,
kPendingSubstitutionValueClass,
+ kPendingSystemFontValueClass,
kInvalidVariableValueClass,
kCyclicVariableValueClass,
kLayoutFunctionClass,
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h b/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h
index 72c589539c5..793d5738a38 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h
@@ -177,132 +177,6 @@ inline EDisplay CssValueIDToPlatformEnum(CSSValueID v) {
}
template <>
-inline EListStyleType CssValueIDToPlatformEnum(CSSValueID v) {
- switch (v) {
- case CSSValueID::kDisc:
- return EListStyleType::kDisc;
- case CSSValueID::kCircle:
- return EListStyleType::kCircle;
- case CSSValueID::kSquare:
- return EListStyleType::kSquare;
- case CSSValueID::kDisclosureOpen:
- return EListStyleType::kDisclosureOpen;
- case CSSValueID::kDisclosureClosed:
- return EListStyleType::kDisclosureClosed;
- case CSSValueID::kDecimal:
- return EListStyleType::kDecimal;
- case CSSValueID::kDecimalLeadingZero:
- return EListStyleType::kDecimalLeadingZero;
- case CSSValueID::kArabicIndic:
- return EListStyleType::kArabicIndic;
- case CSSValueID::kBengali:
- return EListStyleType::kBengali;
- case CSSValueID::kCambodian:
- return EListStyleType::kCambodian;
- case CSSValueID::kKhmer:
- return EListStyleType::kKhmer;
- case CSSValueID::kDevanagari:
- return EListStyleType::kDevanagari;
- case CSSValueID::kGujarati:
- return EListStyleType::kGujarati;
- case CSSValueID::kGurmukhi:
- return EListStyleType::kGurmukhi;
- case CSSValueID::kKannada:
- return EListStyleType::kKannada;
- case CSSValueID::kLao:
- return EListStyleType::kLao;
- case CSSValueID::kMalayalam:
- return EListStyleType::kMalayalam;
- case CSSValueID::kMongolian:
- return EListStyleType::kMongolian;
- case CSSValueID::kMyanmar:
- return EListStyleType::kMyanmar;
- case CSSValueID::kOriya:
- return EListStyleType::kOriya;
- case CSSValueID::kPersian:
- return EListStyleType::kPersian;
- case CSSValueID::kUrdu:
- return EListStyleType::kUrdu;
- case CSSValueID::kTelugu:
- return EListStyleType::kTelugu;
- case CSSValueID::kTibetan:
- return EListStyleType::kTibetan;
- case CSSValueID::kThai:
- return EListStyleType::kThai;
- case CSSValueID::kLowerRoman:
- return EListStyleType::kLowerRoman;
- case CSSValueID::kUpperRoman:
- return EListStyleType::kUpperRoman;
- case CSSValueID::kLowerGreek:
- return EListStyleType::kLowerGreek;
- case CSSValueID::kLowerAlpha:
- return EListStyleType::kLowerAlpha;
- case CSSValueID::kLowerLatin:
- return EListStyleType::kLowerLatin;
- case CSSValueID::kUpperAlpha:
- return EListStyleType::kUpperAlpha;
- case CSSValueID::kUpperLatin:
- return EListStyleType::kUpperLatin;
- case CSSValueID::kCjkEarthlyBranch:
- return EListStyleType::kCjkEarthlyBranch;
- case CSSValueID::kCjkHeavenlyStem:
- return EListStyleType::kCjkHeavenlyStem;
- case CSSValueID::kEthiopicHalehame:
- return EListStyleType::kEthiopicHalehame;
- case CSSValueID::kEthiopicHalehameAm:
- return EListStyleType::kEthiopicHalehameAm;
- case CSSValueID::kEthiopicHalehameTiEr:
- return EListStyleType::kEthiopicHalehameTiEr;
- case CSSValueID::kEthiopicHalehameTiEt:
- return EListStyleType::kEthiopicHalehameTiEt;
- case CSSValueID::kHangul:
- return EListStyleType::kHangul;
- case CSSValueID::kHangulConsonant:
- return EListStyleType::kHangulConsonant;
- case CSSValueID::kKoreanHangulFormal:
- return EListStyleType::kKoreanHangulFormal;
- case CSSValueID::kKoreanHanjaFormal:
- return EListStyleType::kKoreanHanjaFormal;
- case CSSValueID::kKoreanHanjaInformal:
- return EListStyleType::kKoreanHanjaInformal;
- case CSSValueID::kHebrew:
- return EListStyleType::kHebrew;
- case CSSValueID::kArmenian:
- return EListStyleType::kArmenian;
- case CSSValueID::kLowerArmenian:
- return EListStyleType::kLowerArmenian;
- case CSSValueID::kUpperArmenian:
- return EListStyleType::kUpperArmenian;
- case CSSValueID::kGeorgian:
- return EListStyleType::kGeorgian;
- case CSSValueID::kCjkIdeographic:
- return EListStyleType::kCjkIdeographic;
- case CSSValueID::kSimpChineseFormal:
- return EListStyleType::kSimpChineseFormal;
- case CSSValueID::kSimpChineseInformal:
- return EListStyleType::kSimpChineseInformal;
- case CSSValueID::kTradChineseFormal:
- return EListStyleType::kTradChineseFormal;
- case CSSValueID::kTradChineseInformal:
- return EListStyleType::kTradChineseInformal;
- case CSSValueID::kHiragana:
- return EListStyleType::kHiragana;
- case CSSValueID::kKatakana:
- return EListStyleType::kKatakana;
- case CSSValueID::kHiraganaIroha:
- return EListStyleType::kHiraganaIroha;
- case CSSValueID::kKatakanaIroha:
- return EListStyleType::kKatakanaIroha;
- case CSSValueID::kNone:
- return EListStyleType::kNone;
- default:
- break;
- }
-
- return EListStyleType::kNone;
-}
-
-template <>
inline EUserSelect CssValueIDToPlatformEnum(CSSValueID v) {
if (v == CSSValueID::kAuto)
return EUserSelect::kAuto;
@@ -365,134 +239,6 @@ inline CSSValueID PlatformEnumToCSSValueID(EDisplay v) {
}
template <>
-inline CSSValueID PlatformEnumToCSSValueID(EListStyleType v) {
- switch (v) {
- case EListStyleType::kDisc:
- return CSSValueID::kDisc;
- case EListStyleType::kCircle:
- return CSSValueID::kCircle;
- case EListStyleType::kSquare:
- return CSSValueID::kSquare;
- case EListStyleType::kDisclosureOpen:
- return CSSValueID::kDisclosureOpen;
- case EListStyleType::kDisclosureClosed:
- return CSSValueID::kDisclosureClosed;
- case EListStyleType::kDecimal:
- return CSSValueID::kDecimal;
- case EListStyleType::kDecimalLeadingZero:
- return CSSValueID::kDecimalLeadingZero;
- case EListStyleType::kArabicIndic:
- return CSSValueID::kArabicIndic;
- case EListStyleType::kBengali:
- return CSSValueID::kBengali;
- case EListStyleType::kCambodian:
- return CSSValueID::kCambodian;
- case EListStyleType::kKhmer:
- return CSSValueID::kKhmer;
- case EListStyleType::kDevanagari:
- return CSSValueID::kDevanagari;
- case EListStyleType::kGujarati:
- return CSSValueID::kGujarati;
- case EListStyleType::kGurmukhi:
- return CSSValueID::kGurmukhi;
- case EListStyleType::kKannada:
- return CSSValueID::kKannada;
- case EListStyleType::kLao:
- return CSSValueID::kLao;
- case EListStyleType::kMalayalam:
- return CSSValueID::kMalayalam;
- case EListStyleType::kMongolian:
- return CSSValueID::kMongolian;
- case EListStyleType::kMyanmar:
- return CSSValueID::kMyanmar;
- case EListStyleType::kOriya:
- return CSSValueID::kOriya;
- case EListStyleType::kPersian:
- return CSSValueID::kPersian;
- case EListStyleType::kUrdu:
- return CSSValueID::kUrdu;
- case EListStyleType::kTelugu:
- return CSSValueID::kTelugu;
- case EListStyleType::kTibetan:
- return CSSValueID::kTibetan;
- case EListStyleType::kThai:
- return CSSValueID::kThai;
- case EListStyleType::kLowerRoman:
- return CSSValueID::kLowerRoman;
- case EListStyleType::kUpperRoman:
- return CSSValueID::kUpperRoman;
- case EListStyleType::kLowerGreek:
- return CSSValueID::kLowerGreek;
- case EListStyleType::kLowerAlpha:
- return CSSValueID::kLowerAlpha;
- case EListStyleType::kLowerLatin:
- return CSSValueID::kLowerLatin;
- case EListStyleType::kUpperAlpha:
- return CSSValueID::kUpperAlpha;
- case EListStyleType::kUpperLatin:
- return CSSValueID::kUpperLatin;
- case EListStyleType::kCjkEarthlyBranch:
- return CSSValueID::kCjkEarthlyBranch;
- case EListStyleType::kCjkHeavenlyStem:
- return CSSValueID::kCjkHeavenlyStem;
- case EListStyleType::kEthiopicHalehame:
- return CSSValueID::kEthiopicHalehame;
- case EListStyleType::kEthiopicHalehameAm:
- return CSSValueID::kEthiopicHalehameAm;
- case EListStyleType::kEthiopicHalehameTiEr:
- return CSSValueID::kEthiopicHalehameTiEr;
- case EListStyleType::kEthiopicHalehameTiEt:
- return CSSValueID::kEthiopicHalehameTiEt;
- case EListStyleType::kHangul:
- return CSSValueID::kHangul;
- case EListStyleType::kHangulConsonant:
- return CSSValueID::kHangulConsonant;
- case EListStyleType::kKoreanHangulFormal:
- return CSSValueID::kKoreanHangulFormal;
- case EListStyleType::kKoreanHanjaFormal:
- return CSSValueID::kKoreanHanjaFormal;
- case EListStyleType::kKoreanHanjaInformal:
- return CSSValueID::kKoreanHanjaInformal;
- case EListStyleType::kHebrew:
- return CSSValueID::kHebrew;
- case EListStyleType::kArmenian:
- return CSSValueID::kArmenian;
- case EListStyleType::kLowerArmenian:
- return CSSValueID::kLowerArmenian;
- case EListStyleType::kUpperArmenian:
- return CSSValueID::kUpperArmenian;
- case EListStyleType::kGeorgian:
- return CSSValueID::kGeorgian;
- case EListStyleType::kCjkIdeographic:
- return CSSValueID::kCjkIdeographic;
- case EListStyleType::kSimpChineseFormal:
- return CSSValueID::kSimpChineseFormal;
- case EListStyleType::kSimpChineseInformal:
- return CSSValueID::kSimpChineseInformal;
- case EListStyleType::kTradChineseFormal:
- return CSSValueID::kTradChineseFormal;
- case EListStyleType::kTradChineseInformal:
- return CSSValueID::kTradChineseInformal;
- case EListStyleType::kHiragana:
- return CSSValueID::kHiragana;
- case EListStyleType::kKatakana:
- return CSSValueID::kKatakana;
- case EListStyleType::kHiraganaIroha:
- return CSSValueID::kHiraganaIroha;
- case EListStyleType::kKatakanaIroha:
- return CSSValueID::kKatakanaIroha;
- case EListStyleType::kNone:
- return CSSValueID::kNone;
- case EListStyleType::kString:
- NOTREACHED();
- break;
- }
-
- NOTREACHED();
- return CSSValueID::kDisc;
-}
-
-template <>
inline PageOrientation CssValueIDToPlatformEnum(CSSValueID v) {
if (v == CSSValueID::kUpright)
return PageOrientation::kUpright;
@@ -511,12 +257,8 @@ inline ScrollbarGutter CssValueIDToPlatformEnum(CSSValueID v) {
return kScrollbarGutterAuto;
if (v == CSSValueID::kStable)
return kScrollbarGutterStable;
- if (v == CSSValueID::kAlways)
- return kScrollbarGutterAlways;
- if (v == CSSValueID::kBoth)
- return kScrollbarGutterBoth;
- if (v == CSSValueID::kForce)
- return kScrollbarGutterForce;
+ if (v == CSSValueID::kBothEdges)
+ return kScrollbarGutterBothEdges;
NOTREACHED();
return kScrollbarGutterAuto;
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5 b/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
index dc2c319f7cb..efd4db0cab9 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -430,7 +430,6 @@
"inside",
//
// list-style-type
- // The order of this enum must match the order found in CSSParserFastPaths::IsValidKeywordPropertyAndValue().
//
"disc",
"circle",
@@ -438,57 +437,6 @@
"disclosure-open",
"disclosure-closed",
"decimal",
- "decimal-leading-zero",
- "arabic-indic",
- "bengali",
- "cambodian",
- "khmer",
- "devanagari",
- "gujarati",
- "gurmukhi",
- "kannada",
- "lao",
- "malayalam",
- "mongolian",
- "myanmar",
- "oriya",
- "persian",
- "urdu",
- "telugu",
- "tibetan",
- "thai",
- "lower-roman",
- "upper-roman",
- "lower-greek",
- "lower-alpha",
- "lower-latin",
- "upper-alpha",
- "upper-latin",
- "cjk-earthly-branch",
- "cjk-heavenly-stem",
- "ethiopic-halehame",
- "ethiopic-halehame-am",
- "ethiopic-halehame-ti-er",
- "ethiopic-halehame-ti-et",
- "hangul",
- "hangul-consonant",
- "korean-hangul-formal",
- "korean-hanja-formal",
- "korean-hanja-informal",
- "hebrew",
- "armenian",
- "lower-armenian",
- "upper-armenian",
- "georgian",
- "cjk-ideographic",
- "simp-chinese-formal",
- "simp-chinese-informal",
- "trad-chinese-formal",
- "trad-chinese-informal",
- "hiragana",
- "katakana",
- "hiragana-iroha",
- "katakana-iroha",
//none
//
// The order must match the order found in IsDisplayOutside().
@@ -1446,25 +1394,20 @@
"single-fold-horizontal",
// (device-posture) media feature
- "no-fold",
- "laptop",
- // flat,
- "tent",
- "tablet",
- "book",
+ "continuous",
+ "folded",
+ "folded-over",
// scrollbar-gutter
// auto
"stable",
- // always
- // both
- "force",
+ "both-edges",
// (prefers-contrast:) media feature
// no-preference
"more",
"less",
- "forced",
+ "custom",
// @counter-style system
"cyclic",
@@ -1495,6 +1438,12 @@
"bullets",
"numbers",
"words",
- // spell-out,
+
+ // ([video]-dynamic-range) media feature
+ "standard",
+ "high",
+
+ // Layered @import rule
+ "layer",
],
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_list.cc b/chromium/third_party/blink/renderer/core/css/css_value_list.cc
index fb8bf14737f..a3d78539db9 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_list.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_value_list.cc
@@ -20,8 +20,6 @@
#include "third_party/blink/renderer/core/css/css_value_list.h"
-#include "third_party/blink/renderer/core/css/css_primitive_value.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -52,16 +50,13 @@ bool CSSValueList::RemoveAll(const CSSValue& val) {
found = true;
}
}
-
return found;
}
bool CSSValueList::HasValue(const CSSValue& val) const {
- for (wtf_size_t index = 0; index < values_.size(); index++) {
- const Member<const CSSValue>& value = values_.at(index);
- if (value && *value == val) {
+ for (const auto& value : values_) {
+ if (value && *value == val)
return true;
- }
}
return false;
}
@@ -86,8 +81,7 @@ CSSValueList* CSSValueList::Copy() const {
}
String CSSValueList::CustomCSSText() const {
- StringBuilder result;
- String separator;
+ StringView separator;
switch (value_list_separator_) {
case kSpaceSeparator:
separator = " ";
@@ -102,13 +96,16 @@ String CSSValueList::CustomCSSText() const {
NOTREACHED();
}
- unsigned size = values_.size();
- for (unsigned i = 0; i < size; i++) {
+ StringBuilder result;
+ for (const auto& value : values_) {
if (!result.IsEmpty())
result.Append(separator);
- result.Append(values_[i]->CssText());
+ // TODO(crbug.com/1213338): value_[i] can be null by CSSMathExpressionNode
+ // which is implemented by css-values-3. Until fully implement the
+ // css-values-4 features, we should append empty string to remove
+ // null-pointer exception.
+ result.Append(value ? value->CssText() : " ");
}
-
return result.ToString();
}
@@ -118,8 +115,8 @@ bool CSSValueList::Equals(const CSSValueList& other) const {
}
bool CSSValueList::HasFailedOrCanceledSubresources() const {
- for (unsigned i = 0; i < values_.size(); ++i) {
- if (values_[i]->HasFailedOrCanceledSubresources())
+ for (const auto& value : values_) {
+ if (value->HasFailedOrCanceledSubresources())
return true;
}
return false;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.cc
index 5152b2db7cd..eea5a7fb329 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.cc
@@ -23,7 +23,6 @@ const CSSValue* CSSColorValue::ToCSSValue() const {
return cssvalue::CSSColor::Create(ToColor().Rgb());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSNumericValue* CSSColorValue::ToNumberOrPercentage(
const V8CSSNumberish* input) {
CSSNumericValue* value = CSSNumericValue::FromPercentish(input);
@@ -35,21 +34,7 @@ CSSNumericValue* CSSColorValue::ToNumberOrPercentage(
return value;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSNumericValue* CSSColorValue::ToNumberOrPercentage(
- const CSSNumberish& input) {
- CSSNumericValue* value = CSSNumericValue::FromPercentish(input);
- DCHECK(value);
- if (!CSSOMTypes::IsCSSStyleValueNumber(*value) &&
- !CSSOMTypes::IsCSSStyleValuePercentage(*value)) {
- return nullptr;
- }
- return value;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSNumericValue* CSSColorValue::ToPercentage(const V8CSSNumberish* input) {
CSSNumericValue* value = CSSNumericValue::FromPercentish(input);
DCHECK(value);
@@ -58,16 +43,6 @@ CSSNumericValue* CSSColorValue::ToPercentage(const V8CSSNumberish* input) {
return value;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSNumericValue* CSSColorValue::ToPercentage(const CSSNumberish& input) {
- CSSNumericValue* value = CSSNumericValue::FromPercentish(input);
- DCHECK(value);
- if (!CSSOMTypes::IsCSSStyleValuePercentage(*value))
- return nullptr;
-
- return value;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
float CSSColorValue::ComponentToColorInput(CSSNumericValue* input) {
if (CSSOMTypes::IsCSSStyleValuePercentage(*input))
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.h b/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.h
index 9256a094025..eb5c4db438d 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_color_value.h
@@ -32,13 +32,8 @@ class CORE_EXPORT CSSColorValue : public CSSStyleValue {
virtual Color ToColor() const = 0;
protected:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSNumericValue* ToNumberOrPercentage(const V8CSSNumberish*);
static CSSNumericValue* ToPercentage(const V8CSSNumberish*);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSNumericValue* ToNumberOrPercentage(const CSSNumberish&);
- static CSSNumericValue* ToPercentage(const CSSNumberish&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static float ComponentToColorInput(CSSNumericValue*);
};
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.cc
index 759e4c3de29..4fd102fb93f 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/css/cssom/cssom_types.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
namespace blink {
@@ -30,15 +31,9 @@ CSSHSL::CSSHSL(CSSNumericValue* h,
: h_(h), s_(s), l_(l), alpha_(alpha) {}
CSSHSL* CSSHSL::Create(CSSNumericValue* hue,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* saturation,
const V8CSSNumberish* lightness,
const V8CSSNumberish* alpha,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& saturation,
- const CSSNumberish& lightness,
- const CSSNumberish& alpha,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (!CSSOMTypes::IsCSSStyleValueAngle(*hue)) {
exception_state.ThrowTypeError("Hue must be a CSS angle type.");
@@ -59,8 +54,6 @@ CSSHSL* CSSHSL::Create(CSSNumericValue* hue,
return MakeGarbageCollected<CSSHSL>(hue, s, l, a);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8CSSNumberish* CSSHSL::s() const {
return MakeGarbageCollected<V8CSSNumberish>(s_);
}
@@ -73,8 +66,6 @@ V8CSSNumberish* CSSHSL::alpha() const {
return MakeGarbageCollected<V8CSSNumberish>(alpha_);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void CSSHSL::setH(CSSNumericValue* hue, ExceptionState& exception_state) {
if (CSSOMTypes::IsCSSStyleValueAngle(*hue))
h_ = hue;
@@ -83,11 +74,7 @@ void CSSHSL::setH(CSSNumericValue* hue, ExceptionState& exception_state) {
}
void CSSHSL::setS(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* saturation,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& saturation,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToPercentage(saturation))
s_ = value;
@@ -96,11 +83,7 @@ void CSSHSL::setS(
}
void CSSHSL::setL(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* lightness,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& lightness,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToPercentage(lightness))
l_ = value;
@@ -109,11 +92,7 @@ void CSSHSL::setL(
}
void CSSHSL::setAlpha(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* alpha,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& alpha,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToPercentage(alpha))
alpha_ = value;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.h b/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.h
index 22f9fd48004..0a3bbc71f50 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_hsl.h
@@ -19,19 +19,11 @@ class CORE_EXPORT CSSHSL final : public CSSColorValue {
public:
// Constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSHSL* Create(CSSNumericValue* hue,
const V8CSSNumberish* saturation,
const V8CSSNumberish* lightness,
const V8CSSNumberish* alpha,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSHSL* Create(CSSNumericValue* hue,
- const CSSNumberish& saturation,
- const CSSNumberish& lightness,
- const CSSNumberish& alpha,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Internal constructor used by blink.
explicit CSSHSL(const Color&);
@@ -41,7 +33,6 @@ class CORE_EXPORT CSSHSL final : public CSSColorValue {
CSSNumericValue*);
// Getters and setters from the IDL
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<CSSNumericValue> h() const { return h_; }
V8CSSNumberish* s() const;
V8CSSNumberish* l() const;
@@ -50,16 +41,6 @@ class CORE_EXPORT CSSHSL final : public CSSColorValue {
void setS(const V8CSSNumberish* s, ExceptionState& exception_state);
void setL(const V8CSSNumberish* l, ExceptionState& exception_state);
void setAlpha(const V8CSSNumberish* alpha, ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Member<CSSNumericValue> h() { return h_; }
- void s(CSSNumberish& g) { g.SetCSSNumericValue(s_); }
- void l(CSSNumberish& b) { b.SetCSSNumericValue(l_); }
- void alpha(CSSNumberish& alpha) { alpha.SetCSSNumericValue(alpha_); }
- void setH(CSSNumericValue*, ExceptionState&);
- void setS(const CSSNumberish&, ExceptionState&);
- void setL(const CSSNumberish&, ExceptionState&);
- void setAlpha(const CSSNumberish&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor* visitor) const override {
visitor->Trace(h_);
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 5e1d2e091e3..4c041c63722 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
@@ -11,11 +11,9 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* CSSMathInvert::value() {
return MakeGarbageCollected<V8CSSNumberish>(value_);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<CSSNumericSumValue> CSSMathInvert::SumValue() const {
auto sum = value_->SumValue();
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.h b/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.h
index 67af5fb6cdd..5344a2b191e 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.h
@@ -17,15 +17,9 @@ class CORE_EXPORT CSSMathInvert : public CSSMathValue {
public:
// The constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSMathInvert* Create(V8CSSNumberish* arg) {
return Create(CSSNumericValue::FromNumberish(arg));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSMathInvert* Create(const CSSNumberish& arg) {
- return Create(CSSNumericValue::FromNumberish(arg));
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal constructor
static CSSMathInvert* Create(CSSNumericValue* value) {
return MakeGarbageCollected<CSSMathInvert>(
@@ -39,11 +33,7 @@ class CORE_EXPORT CSSMathInvert : public CSSMathValue {
String getOperator() const final { return "invert"; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* value();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void value(CSSNumberish& value) { value.SetCSSNumericValue(value_); }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal methods
const CSSNumericValue& Value() const { return *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 c901aa7b0e3..8a742f26c14 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
@@ -6,11 +6,11 @@
#include "third_party/blink/renderer/core/css/css_math_expression_node.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathMax* CSSMathMax::Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
@@ -27,24 +27,6 @@ CSSMathMax* CSSMathMax::Create(const HeapVector<Member<V8CSSNumberish>>& args,
return result;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSMathMax* CSSMathMax::Create(const HeapVector<CSSNumberish>& args,
- ExceptionState& exception_state) {
- if (args.IsEmpty()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "Arguments can't be empty");
- return nullptr;
- }
-
- CSSMathMax* result = Create(CSSNumberishesToNumericValues(args));
- if (!result) {
- exception_state.ThrowTypeError("Incompatible types");
- return nullptr;
- }
-
- return result;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathMax* CSSMathMax::Create(CSSNumericValueVector values) {
bool error = false;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.h b/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.h
index 64ec59967ff..aab7bc56511 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_MAX_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_MAX_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_variadic.h"
namespace blink {
@@ -16,13 +17,8 @@ class CORE_EXPORT CSSMathMax final : public CSSMathVariadic {
public:
// The constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSMathMax* Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSMathMax* Create(const HeapVector<CSSNumberish>& args,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal constructor.
static CSSMathMax* Create(CSSNumericValueVector);
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 eae1635b74a..bea82a81ea0 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
@@ -6,11 +6,11 @@
#include "third_party/blink/renderer/core/css/css_math_expression_node.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathMin* CSSMathMin::Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
@@ -27,24 +27,6 @@ CSSMathMin* CSSMathMin::Create(const HeapVector<Member<V8CSSNumberish>>& args,
return result;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSMathMin* CSSMathMin::Create(const HeapVector<CSSNumberish>& args,
- ExceptionState& exception_state) {
- if (args.IsEmpty()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "Arguments can't be empty");
- return nullptr;
- }
-
- CSSMathMin* result = Create(CSSNumberishesToNumericValues(args));
- if (!result) {
- exception_state.ThrowTypeError("Incompatible types");
- return nullptr;
- }
-
- return result;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathMin* CSSMathMin::Create(CSSNumericValueVector values) {
bool error = false;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.h b/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.h
index 719376941d0..fcf0ad8498f 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_MIN_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_MIN_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_variadic.h"
namespace blink {
@@ -18,13 +19,8 @@ class CORE_EXPORT CSSMathMin final : public CSSMathVariadic {
public:
// The constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSMathMin* Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSMathMin* Create(const HeapVector<CSSNumberish>& args,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal constructor.
static CSSMathMin* Create(CSSNumericValueVector);
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 045af43c41e..e3a4971a24e 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
@@ -11,11 +11,9 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* CSSMathNegate::value() {
return MakeGarbageCollected<V8CSSNumberish>(value_);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<CSSNumericSumValue> CSSMathNegate::SumValue() const {
auto maybe_sum = value_->SumValue();
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.h b/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.h
index 15ecaa72961..39049b74583 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.h
@@ -16,15 +16,9 @@ class CORE_EXPORT CSSMathNegate : public CSSMathValue {
public:
// The constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSMathNegate* Create(V8CSSNumberish* arg) {
return Create(CSSNumericValue::FromNumberish(arg));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSMathNegate* Create(const CSSNumberish& arg) {
- return Create(CSSNumericValue::FromNumberish(arg));
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal constructor
static CSSMathNegate* Create(CSSNumericValue* value) {
return MakeGarbageCollected<CSSMathNegate>(value, value->Type());
@@ -37,11 +31,7 @@ class CORE_EXPORT CSSMathNegate : public CSSMathValue {
String getOperator() const final { return "negate"; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* value();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void value(CSSNumberish& value) { value.SetCSSNumericValue(value_); }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal methods
const CSSNumericValue& Value() const { return *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 a629a17f2f7..8206c64b88d 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_math_expression_node.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_invert.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -31,7 +32,6 @@ CSSNumericSumValue::UnitMap MultiplyUnitMaps(
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathProduct* CSSMathProduct::Create(
const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state) {
@@ -49,24 +49,6 @@ CSSMathProduct* CSSMathProduct::Create(
return result;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSMathProduct* CSSMathProduct::Create(const HeapVector<CSSNumberish>& args,
- ExceptionState& exception_state) {
- if (args.IsEmpty()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "Arguments can't be empty");
- return nullptr;
- }
-
- CSSMathProduct* result = Create(CSSNumberishesToNumericValues(args));
- if (!result) {
- exception_state.ThrowTypeError("Incompatible types");
- return nullptr;
- }
-
- return result;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathProduct* CSSMathProduct::Create(CSSNumericValueVector values) {
bool error = false;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.h b/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.h
index d709ed83810..94ff7d086c1 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_PRODUCT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_PRODUCT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_variadic.h"
namespace blink {
@@ -16,13 +17,8 @@ class CORE_EXPORT CSSMathProduct final : public CSSMathVariadic {
public:
// The constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSMathProduct* Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSMathProduct* Create(const HeapVector<CSSNumberish>& args,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink internal-constructor.
static CSSMathProduct* Create(CSSNumericValueVector);
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 d2bdb7a7c9c..826c651cca8 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
@@ -49,7 +49,6 @@ bool operator==(const CSSNumericSumValue::Term& a, const UnitMapComparator& b) {
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathSum* CSSMathSum::Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
@@ -67,18 +66,6 @@ CSSMathSum* CSSMathSum::Create(const HeapVector<Member<V8CSSNumberish>>& args,
return result;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSMathSum* CSSMathSum::Create(const HeapVector<CSSNumberish>& args,
- ExceptionState& exception_state) {
- if (args.IsEmpty()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "Arguments can't be empty");
- return nullptr;
- }
-
- return Create(CSSNumberishesToNumericValues(args), exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSMathSum* CSSMathSum::Create(CSSNumericValueVector values,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.h b/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.h
index 84a1231d96d..701d37b963c 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.h
@@ -5,7 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_SUM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_MATH_SUM_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_variadic.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -16,13 +18,8 @@ class CORE_EXPORT CSSMathSum final : public CSSMathVariadic {
public:
// The constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSMathSum* Create(const HeapVector<Member<V8CSSNumberish>>& args,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSMathSum* Create(const HeapVector<CSSNumberish>& args,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal constructor.
static CSSMathSum* Create(CSSNumericValueVector,
ExceptionState& = ASSERT_NO_EXCEPTION);
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 97a61c4ae67..27d91996d4a 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
@@ -281,7 +281,6 @@ CSSNumericValue* CSSNumericValue::FromCSSValue(const CSSPrimitiveValue& value) {
return CSSUnitValue::FromCSSValue(To<CSSNumericLiteralValue>(value));
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
CSSNumericValue* CSSNumericValue::FromNumberish(const V8CSSNumberish* value) {
if (value->IsDouble()) {
@@ -290,18 +289,7 @@ CSSNumericValue* CSSNumericValue::FromNumberish(const V8CSSNumberish* value) {
}
return value->GetAsCSSNumericValue();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-CSSNumericValue* CSSNumericValue::FromNumberish(const CSSNumberish& value) {
- if (value.IsDouble()) {
- return CSSUnitValue::Create(value.GetAsDouble(),
- CSSPrimitiveValue::UnitType::kNumber);
- }
- return value.GetAsCSSNumericValue();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
CSSNumericValue* CSSNumericValue::FromPercentish(const V8CSSNumberish* value) {
if (value->IsDouble()) {
@@ -310,16 +298,6 @@ CSSNumericValue* CSSNumericValue::FromPercentish(const V8CSSNumberish* value) {
}
return value->GetAsCSSNumericValue();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-CSSNumericValue* CSSNumericValue::FromPercentish(const CSSNumberish& value) {
- if (value.IsDouble()) {
- return CSSUnitValue::Create(value.GetAsDouble() * 100,
- CSSPrimitiveValue::UnitType::kPercentage);
- }
- return value.GetAsCSSNumericValue();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSUnitValue* CSSNumericValue::to(const String& unit_string,
ExceptionState& exception_state) {
@@ -448,11 +426,7 @@ CSSNumericType* CSSNumericValue::type() const {
}
CSSNumericValue* CSSNumericValue::add(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto values = CSSNumberishesToNumericValues(numberishes);
PrependValueForArithmetic<kSumType>(values, this);
@@ -465,11 +439,7 @@ CSSNumericValue* CSSNumericValue::add(
}
CSSNumericValue* CSSNumericValue::sub(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto values = CSSNumberishesToNumericValues(numberishes);
std::transform(values.begin(), values.end(), values.begin(),
@@ -484,11 +454,7 @@ CSSNumericValue* CSSNumericValue::sub(
}
CSSNumericValue* CSSNumericValue::mul(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto values = CSSNumberishesToNumericValues(numberishes);
PrependValueForArithmetic<kProductType>(values, this);
@@ -499,11 +465,7 @@ CSSNumericValue* CSSNumericValue::mul(
}
CSSNumericValue* CSSNumericValue::div(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto values = CSSNumberishesToNumericValues(numberishes);
for (auto& v : values) {
@@ -523,11 +485,7 @@ CSSNumericValue* CSSNumericValue::div(
}
CSSNumericValue* CSSNumericValue::min(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto values = CSSNumberishesToNumericValues(numberishes);
PrependValueForArithmetic<kMinType>(values, this);
@@ -540,11 +498,7 @@ CSSNumericValue* CSSNumericValue::min(
}
CSSNumericValue* CSSNumericValue::max(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto values = CSSNumberishesToNumericValues(numberishes);
PrependValueForArithmetic<kMaxType>(values, this);
@@ -557,11 +511,7 @@ CSSNumericValue* CSSNumericValue::max(
}
bool CSSNumericValue::equals(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSNumberish>>& numberishes
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSNumberish>& numberishes
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
CSSNumericValueVector values = CSSNumberishesToNumericValues(numberishes);
return std::all_of(values.begin(), values.end(),
@@ -582,7 +532,6 @@ CSSNumericValue* CSSNumericValue::Invert() {
return CSSMathInvert::Create(this);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSNumericValueVector CSSNumberishesToNumericValues(
const HeapVector<Member<V8CSSNumberish>>& values) {
CSSNumericValueVector result;
@@ -591,15 +540,5 @@ CSSNumericValueVector CSSNumberishesToNumericValues(
}
return result;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSNumericValueVector CSSNumberishesToNumericValues(
- const HeapVector<CSSNumberish>& values) {
- CSSNumericValueVector result;
- for (const CSSNumberish& value : values) {
- result.push_back(CSSNumericValue::FromNumberish(value));
- }
- return result;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.h b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.h
index e0358955c8d..66584a786c9 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_NUMERIC_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_NUMERIC_VALUE_H_
-#include "third_party/blink/renderer/bindings/core/v8/double_or_css_numeric_value.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -24,7 +24,6 @@ class CSSNumericValue;
class CSSUnitValue;
class ExceptionState;
-using CSSNumberish = DoubleOrCSSNumericValue;
using CSSNumericValueVector = HeapVector<Member<CSSNumericValue>>;
class CORE_EXPORT CSSNumericValue : public CSSStyleValue {
@@ -37,18 +36,12 @@ class CORE_EXPORT CSSNumericValue : public CSSStyleValue {
static CSSNumericValue* parse(const String& css_text, ExceptionState&);
// Blink-internal ways of creating CSSNumericValues.
static CSSNumericValue* FromCSSValue(const CSSPrimitiveValue&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// https://drafts.css-houdini.org/css-typed-om/#rectify-a-numberish-value
static CSSNumericValue* FromNumberish(const V8CSSNumberish* value);
// https://drafts.css-houdini.org/css-typed-om/#rectify-a-percentish-value
static CSSNumericValue* FromPercentish(const V8CSSNumberish* value);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSNumericValue* FromNumberish(const CSSNumberish& value);
- static CSSNumericValue* FromPercentish(const CSSNumberish& value);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Methods defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSNumericValue* add(const HeapVector<Member<V8CSSNumberish>>& numberishes,
ExceptionState& exception_state);
CSSNumericValue* sub(const HeapVector<Member<V8CSSNumberish>>& numberishes,
@@ -62,15 +55,6 @@ class CORE_EXPORT CSSNumericValue : public CSSStyleValue {
CSSNumericValue* max(const HeapVector<Member<V8CSSNumberish>>& numberishes,
ExceptionState& exception_state);
bool equals(const HeapVector<Member<V8CSSNumberish>>& numberishes);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumericValue* add(const HeapVector<CSSNumberish>&, ExceptionState&);
- CSSNumericValue* sub(const HeapVector<CSSNumberish>&, ExceptionState&);
- CSSNumericValue* mul(const HeapVector<CSSNumberish>&, ExceptionState&);
- CSSNumericValue* div(const HeapVector<CSSNumberish>&, ExceptionState&);
- CSSNumericValue* min(const HeapVector<CSSNumberish>&, ExceptionState&);
- CSSNumericValue* max(const HeapVector<CSSNumberish>&, ExceptionState&);
- bool equals(const HeapVector<CSSNumberish>&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Converts between compatible types, as defined in the IDL.
CSSUnitValue* to(const String&, ExceptionState&);
@@ -109,13 +93,8 @@ class CORE_EXPORT CSSNumericValue : public CSSStyleValue {
CSSNumericValueType type_;
};
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSNumericValueVector CSSNumberishesToNumericValues(
const HeapVector<Member<V8CSSNumberish>>& values);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSNumericValueVector CSSNumberishesToNumericValues(
- const HeapVector<CSSNumberish>&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value_type.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value_type.cc
index 288714653e4..f053f728b1a 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value_type.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value_type.cc
@@ -31,6 +31,12 @@ CSSNumericValueType::BaseType UnitTypeToBaseType(
case UnitType::kViewportHeight:
case UnitType::kViewportMin:
case UnitType::kViewportMax:
+ case UnitType::kContainerWidth:
+ case UnitType::kContainerHeight:
+ case UnitType::kContainerInlineSize:
+ case UnitType::kContainerBlockSize:
+ case UnitType::kContainerMin:
+ case UnitType::kContainerMax:
case UnitType::kRems:
case UnitType::kChs:
return BaseType::kLength;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h b/chromium/third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h
index d6c7c8a9cc5..f77d9745082 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h
@@ -63,6 +63,10 @@ class CORE_EXPORT CSSPaintWorkletInput : public PaintWorkletInput {
return PaintWorkletStylePropertyMap::CopyCrossThreadData(style_map_data_);
}
+ PaintWorkletInputType GetType() const override {
+ return PaintWorkletInputType::kCSS;
+ }
+
private:
const String name_;
const float effective_zoom_;
@@ -71,6 +75,19 @@ class CORE_EXPORT CSSPaintWorkletInput : public PaintWorkletInput {
Vector<std::unique_ptr<CrossThreadStyleValue>> parsed_input_arguments_;
};
+template <>
+struct DowncastTraits<CSSPaintWorkletInput> {
+ static bool AllowFrom(const cc::PaintWorkletInput& worklet_input) {
+ auto* input = DynamicTo<PaintWorkletInput>(worklet_input);
+ return input && AllowFrom(*input);
+ }
+
+ static bool AllowFrom(const PaintWorkletInput& worklet_input) {
+ return worklet_input.GetType() ==
+ PaintWorkletInput::PaintWorkletInputType::kCSS;
+ }
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_PAINT_WORKLET_INPUT_H_
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.cc
index 8056dd552c2..64b51270d7d 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
namespace blink {
@@ -27,17 +28,10 @@ CSSRGB::CSSRGB(CSSNumericValue* r,
: r_(r), g_(g), b_(b), alpha_(alpha) {}
CSSRGB* CSSRGB::Create(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* red,
const V8CSSNumberish* green,
const V8CSSNumberish* blue,
const V8CSSNumberish* alpha,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& red,
- const CSSNumberish& green,
- const CSSNumberish& blue,
- const CSSNumberish& alpha,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
CSSNumericValue* r;
CSSNumericValue* g;
@@ -57,8 +51,6 @@ CSSRGB* CSSRGB::Create(
return MakeGarbageCollected<CSSRGB>(r, g, b, a);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8CSSNumberish* CSSRGB::r() const {
return MakeGarbageCollected<V8CSSNumberish>(r_);
}
@@ -75,14 +67,8 @@ V8CSSNumberish* CSSRGB::alpha() const {
return MakeGarbageCollected<V8CSSNumberish>(alpha_);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void CSSRGB::setR(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* red,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& red,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToNumberOrPercentage(red)) {
r_ = value;
@@ -93,11 +79,7 @@ void CSSRGB::setR(
}
void CSSRGB::setG(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* green,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& green,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToNumberOrPercentage(green)) {
g_ = value;
@@ -108,11 +90,7 @@ void CSSRGB::setG(
}
void CSSRGB::setB(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* blue,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& blue,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToNumberOrPercentage(blue)) {
b_ = value;
@@ -123,11 +101,7 @@ void CSSRGB::setB(
}
void CSSRGB::setAlpha(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CSSNumberish* alpha,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CSSNumberish& alpha,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (auto* value = ToPercentage(alpha))
alpha_ = value;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.h b/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.h
index 39bd3226ffa..7e8d53ca152 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_rgb.h
@@ -20,19 +20,11 @@ class CORE_EXPORT CSSRGB final : public CSSColorValue {
public:
// Constructor defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSRGB* Create(const V8CSSNumberish* r,
const V8CSSNumberish* g,
const V8CSSNumberish* b,
const V8CSSNumberish* alpha,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSRGB* Create(const CSSNumberish&,
- const CSSNumberish&,
- const CSSNumberish&,
- const CSSNumberish&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Internal constructor used by blink.
explicit CSSRGB(const Color&);
@@ -42,7 +34,6 @@ class CORE_EXPORT CSSRGB final : public CSSColorValue {
CSSNumericValue*);
// Getters and setters from the IDL
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* r() const;
V8CSSNumberish* g() const;
V8CSSNumberish* b() const;
@@ -51,16 +42,6 @@ class CORE_EXPORT CSSRGB final : public CSSColorValue {
void setG(const V8CSSNumberish* g, ExceptionState& exception_state);
void setB(const V8CSSNumberish* b, ExceptionState& exception_state);
void setAlpha(const V8CSSNumberish* alpha, ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void r(CSSNumberish& r) { r.SetCSSNumericValue(r_); }
- void g(CSSNumberish& g) { g.SetCSSNumericValue(g_); }
- void b(CSSNumberish& b) { b.SetCSSNumericValue(b_); }
- void alpha(CSSNumberish& alpha) { alpha.SetCSSNumericValue(alpha_); }
- void setR(const CSSNumberish&, ExceptionState&);
- void setG(const CSSNumberish&, ExceptionState&);
- void setB(const CSSNumberish&, ExceptionState&);
- void setAlpha(const CSSNumberish&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor* visitor) const override {
visitor->Trace(r_);
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 4007a058322..afb154af268 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
@@ -81,7 +81,6 @@ CSSRotate* CSSRotate::Create(CSSNumericValue* angle,
angle, true /* is2D */);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSRotate* CSSRotate::Create(const V8CSSNumberish* x,
const V8CSSNumberish* y,
const V8CSSNumberish* z,
@@ -103,29 +102,6 @@ CSSRotate* CSSRotate::Create(const V8CSSNumberish* x,
return MakeGarbageCollected<CSSRotate>(x_value, y_value, z_value, angle,
false /* is2D */);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSRotate* CSSRotate::Create(const CSSNumberish& x,
- const CSSNumberish& y,
- const CSSNumberish& z,
- CSSNumericValue* angle,
- ExceptionState& exception_state) {
- CSSNumericValue* x_value = CSSNumericValue::FromNumberish(x);
- CSSNumericValue* y_value = CSSNumericValue::FromNumberish(y);
- CSSNumericValue* z_value = CSSNumericValue::FromNumberish(z);
-
- if (!IsValidRotateCoord(x_value) || !IsValidRotateCoord(y_value) ||
- !IsValidRotateCoord(z_value)) {
- exception_state.ThrowTypeError("Must specify an number unit");
- return nullptr;
- }
- if (!IsValidRotateAngle(angle)) {
- exception_state.ThrowTypeError("Must pass an angle to CSSRotate");
- return nullptr;
- }
- return MakeGarbageCollected<CSSRotate>(x_value, y_value, z_value, angle,
- false /* is2D */);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSRotate* CSSRotate::Create(CSSNumericValue* angle) {
return MakeGarbageCollected<CSSRotate>(
@@ -214,8 +190,6 @@ const CSSFunctionValue* CSSRotate::ToCSSValue() const {
return result;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8CSSNumberish* CSSRotate::x() {
return MakeGarbageCollected<V8CSSNumberish>(x_);
}
@@ -255,37 +229,6 @@ void CSSRotate::setZ(const V8CSSNumberish* z, ExceptionState& exception_state) {
z_ = value;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void CSSRotate::setX(const CSSNumberish& x, ExceptionState& exception_state) {
- CSSNumericValue* value = CSSNumericValue::FromNumberish(x);
- if (!IsValidRotateCoord(value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return;
- }
- x_ = value;
-}
-
-void CSSRotate::setY(const CSSNumberish& y, ExceptionState& exception_state) {
- CSSNumericValue* value = CSSNumericValue::FromNumberish(y);
- if (!IsValidRotateCoord(value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return;
- }
- y_ = value;
-}
-
-void CSSRotate::setZ(const CSSNumberish& z, ExceptionState& exception_state) {
- CSSNumericValue* value = CSSNumericValue::FromNumberish(z);
- if (!IsValidRotateCoord(value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return;
- }
- z_ = value;
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
CSSRotate::CSSRotate(CSSNumericValue* x,
CSSNumericValue* y,
CSSNumericValue* z,
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.h b/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.h
index 75d67e0757c..e958eea8073 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.h
@@ -23,19 +23,11 @@ class CORE_EXPORT CSSRotate final : public CSSTransformComponent {
public:
// Constructors defined in the IDL.
static CSSRotate* Create(CSSNumericValue* angle, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSRotate* Create(const V8CSSNumberish* x,
const V8CSSNumberish* y,
const V8CSSNumberish* z,
CSSNumericValue* angle,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSRotate* Create(const CSSNumberish& x,
- const CSSNumberish& y,
- const CSSNumberish& z,
- CSSNumericValue* angle,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal ways of creating CSSRotates.
static CSSRotate* Create(CSSNumericValue* angle);
@@ -56,21 +48,12 @@ class CORE_EXPORT CSSRotate final : public CSSTransformComponent {
// Getters and setters for attributes defined in the IDL.
CSSNumericValue* angle() { return angle_.Get(); }
void setAngle(CSSNumericValue* angle, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* x();
V8CSSNumberish* y();
V8CSSNumberish* z();
void setX(const V8CSSNumberish* x, ExceptionState& exception_state);
void setY(const V8CSSNumberish* y, ExceptionState& exception_state);
void setZ(const V8CSSNumberish* z, ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void x(CSSNumberish& x) { x.SetCSSNumericValue(x_); }
- void y(CSSNumberish& y) { y.SetCSSNumericValue(y_); }
- void z(CSSNumberish& z) { z.SetCSSNumericValue(z_); }
- void setX(const CSSNumberish&, ExceptionState&);
- void setY(const CSSNumberish&, ExceptionState&);
- void setZ(const CSSNumberish&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMMatrix* toMatrix(ExceptionState&) const final;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_scale.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_scale.cc
index 079301d9f58..1cfa353c081 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_scale.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_scale.cc
@@ -75,8 +75,6 @@ CSSScale* FromScale3d(const CSSFunctionValue& value) {
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
CSSScale* CSSScale::Create(const V8CSSNumberish* x,
const V8CSSNumberish* y,
ExceptionState& exception_state) {
@@ -108,41 +106,6 @@ CSSScale* CSSScale::Create(const V8CSSNumberish* x,
return CSSScale::Create(x_value, y_value, z_value);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-CSSScale* CSSScale::Create(const CSSNumberish& x,
- const CSSNumberish& y,
- ExceptionState& exception_state) {
- CSSNumericValue* x_value = CSSNumericValue::FromNumberish(x);
- CSSNumericValue* y_value = CSSNumericValue::FromNumberish(y);
-
- if (!IsValidScaleCoord(x_value) || !IsValidScaleCoord(y_value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return nullptr;
- }
-
- return CSSScale::Create(x_value, y_value);
-}
-
-CSSScale* CSSScale::Create(const CSSNumberish& x,
- const CSSNumberish& y,
- const CSSNumberish& z,
- ExceptionState& exception_state) {
- CSSNumericValue* x_value = CSSNumericValue::FromNumberish(x);
- CSSNumericValue* y_value = CSSNumericValue::FromNumberish(y);
- CSSNumericValue* z_value = CSSNumericValue::FromNumberish(z);
-
- if (!IsValidScaleCoord(x_value) || !IsValidScaleCoord(y_value) ||
- !IsValidScaleCoord(z_value)) {
- exception_state.ThrowTypeError("Must specify a number for X, Y and Z");
- return nullptr;
- }
-
- return CSSScale::Create(x_value, y_value, z_value);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
CSSScale* CSSScale::FromCSSValue(const CSSFunctionValue& value) {
switch (value.FunctionType()) {
case CSSValueID::kScale:
@@ -159,8 +122,6 @@ CSSScale* CSSScale::FromCSSValue(const CSSFunctionValue& value) {
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8CSSNumberish* CSSScale::x() {
return MakeGarbageCollected<V8CSSNumberish>(x_);
}
@@ -206,43 +167,6 @@ void CSSScale::setZ(const V8CSSNumberish* z, ExceptionState& exception_state) {
z_ = value;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void CSSScale::setX(const CSSNumberish& x, ExceptionState& exception_state) {
- CSSNumericValue* value = CSSNumericValue::FromNumberish(x);
-
- if (!IsValidScaleCoord(value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return;
- }
-
- x_ = value;
-}
-
-void CSSScale::setY(const CSSNumberish& y, ExceptionState& exception_state) {
- CSSNumericValue* value = CSSNumericValue::FromNumberish(y);
-
- if (!IsValidScaleCoord(value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return;
- }
-
- y_ = value;
-}
-
-void CSSScale::setZ(const CSSNumberish& z, ExceptionState& exception_state) {
- CSSNumericValue* value = CSSNumericValue::FromNumberish(z);
-
- if (!IsValidScaleCoord(value)) {
- exception_state.ThrowTypeError("Must specify a number unit");
- return;
- }
-
- z_ = value;
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
DOMMatrix* CSSScale::toMatrix(ExceptionState& exception_state) const {
CSSUnitValue* x = x_->to(CSSPrimitiveValue::UnitType::kNumber);
CSSUnitValue* y = y_->to(CSSPrimitiveValue::UnitType::kNumber);
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_scale.h b/chromium/third_party/blink/renderer/core/css/cssom/css_scale.h
index 19bbe9777e7..5b92eea83e1 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_scale.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_scale.h
@@ -22,7 +22,6 @@ class CORE_EXPORT CSSScale final : public CSSTransformComponent {
public:
// Constructors defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSScale* Create(const V8CSSNumberish* x,
const V8CSSNumberish* y,
ExceptionState& exception_state);
@@ -30,15 +29,6 @@ class CORE_EXPORT CSSScale final : public CSSTransformComponent {
const V8CSSNumberish* y,
const V8CSSNumberish* z,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSScale* Create(const CSSNumberish&,
- const CSSNumberish&,
- ExceptionState&);
- static CSSScale* Create(const CSSNumberish&,
- const CSSNumberish&,
- const CSSNumberish&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal ways of creating CSSScales.
static CSSScale* Create(CSSNumericValue* x, CSSNumericValue* y) {
@@ -60,21 +50,12 @@ class CORE_EXPORT CSSScale final : public CSSTransformComponent {
CSSScale& operator=(const CSSScale&) = delete;
// Getters and setters for attributes defined in the IDL.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSNumberish* x();
V8CSSNumberish* y();
V8CSSNumberish* z();
void setX(const V8CSSNumberish* x, ExceptionState& exception_state);
void setY(const V8CSSNumberish* y, ExceptionState& exception_state);
void setZ(const V8CSSNumberish* z, ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void x(CSSNumberish& x) { x.SetCSSNumericValue(x_); }
- void y(CSSNumberish& y) { y.SetCSSNumericValue(y_); }
- void z(CSSNumberish& z) { z.SetCSSNumericValue(z_); }
- void setX(const CSSNumberish&, ExceptionState&);
- void setY(const CSSNumberish&, ExceptionState&);
- void setZ(const CSSNumberish&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMMatrix* toMatrix(ExceptionState&) const final;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_style_image_value_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_style_image_value_test.cc
index 277268c2fb4..8c47ed3f78f 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_style_image_value_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_style_image_value_test.cc
@@ -24,8 +24,12 @@ class FakeCSSStyleImageValue : public CSSStyleImageValue {
}
// CanvasImageSource
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) final {
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) final {
+ // Only cover premultiply alpha cases.
+ DCHECK_EQ(alpha_disposition, kPremultiplyAlpha);
return nullptr;
}
ResourceStatus Status() const final {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.h b/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.h
index 6921830e56a..c10c284e616 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_STYLE_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_STYLE_VALUE_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_value.h"
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.cc
index 9a5859364d4..636ae0021bd 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
namespace blink {
CSSStyleVariableReferenceValue* CSSStyleVariableReferenceValue::Create(
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.h b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.h
index 1f972dbfd9d..7460be3b435 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_UNIT_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_UNIT_VALUE_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.h b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.h
index 0411b2656ad..4ca380bc8ba 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.h
@@ -49,6 +49,36 @@ class CSSUnitValues {
CSSPrimitiveValue::UnitType::kViewportHeight);
}
+ static CSSUnitValue* qw(double value) {
+ return CSSUnitValue::Create(value,
+ CSSPrimitiveValue::UnitType::kContainerWidth);
+ }
+
+ static CSSUnitValue* qh(double value) {
+ return CSSUnitValue::Create(value,
+ CSSPrimitiveValue::UnitType::kContainerHeight);
+ }
+
+ static CSSUnitValue* qi(double value) {
+ return CSSUnitValue::Create(
+ value, CSSPrimitiveValue::UnitType::kContainerInlineSize);
+ }
+
+ static CSSUnitValue* qb(double value) {
+ return CSSUnitValue::Create(
+ value, CSSPrimitiveValue::UnitType::kContainerBlockSize);
+ }
+
+ static CSSUnitValue* qmin(double value) {
+ return CSSUnitValue::Create(value,
+ CSSPrimitiveValue::UnitType::kContainerMin);
+ }
+
+ static CSSUnitValue* qmax(double value) {
+ return CSSUnitValue::Create(value,
+ CSSPrimitiveValue::UnitType::kContainerMax);
+ }
+
static CSSUnitValue* vmin(double value) {
return CSSUnitValue::Create(value,
CSSPrimitiveValue::UnitType::kViewportMin);
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 b83741545fc..4e51cde7d6d 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
@@ -19,6 +19,14 @@
[NewObject] CSSUnitValue vh(double value);
[NewObject] CSSUnitValue vmin(double value);
[NewObject] CSSUnitValue vmax(double value);
+
+ [NewObject, RuntimeEnabled=CSSContainerRelativeUnits] CSSUnitValue qw(double value);
+ [NewObject, RuntimeEnabled=CSSContainerRelativeUnits] CSSUnitValue qh(double value);
+ [NewObject, RuntimeEnabled=CSSContainerRelativeUnits] CSSUnitValue qi(double value);
+ [NewObject, RuntimeEnabled=CSSContainerRelativeUnits] CSSUnitValue qb(double value);
+ [NewObject, RuntimeEnabled=CSSContainerRelativeUnits] CSSUnitValue qmin(double value);
+ [NewObject, RuntimeEnabled=CSSContainerRelativeUnits] CSSUnitValue qmax(double value);
+
[NewObject] CSSUnitValue cm(double value);
[NewObject] CSSUnitValue mm(double value);
[NewObject] CSSUnitValue in(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 813f96ac848..5d45172df67 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
@@ -10,6 +10,7 @@
#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/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -21,17 +22,9 @@ StringView FindVariableName(CSSParserTokenRange& range) {
return range.Consume().Value();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSUnparsedSegment*
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSUnparsedSegment
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
VariableReferenceValue(const StringView& variable_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8CSSUnparsedSegment>>& tokens
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSUnparsedSegment>& tokens
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
CSSUnparsedValue* unparsed_value;
if (tokens.size() == 0)
@@ -42,35 +35,19 @@ VariableReferenceValue(const StringView& variable_name,
CSSStyleVariableReferenceValue* variable_reference =
CSSStyleVariableReferenceValue::Create(variable_name.ToString(),
unparsed_value);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return MakeGarbageCollected<V8CSSUnparsedSegment>(variable_reference);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return CSSUnparsedSegment::FromCSSVariableReferenceValue(variable_reference);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8CSSUnparsedSegment>>
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-HeapVector<CSSUnparsedSegment>
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ParserTokenRangeToTokens(CSSParserTokenRange range) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8CSSUnparsedSegment>> tokens;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<CSSUnparsedSegment> tokens;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
StringBuilder builder;
while (!range.AtEnd()) {
if (range.Peek().FunctionId() == CSSValueID::kVar ||
range.Peek().FunctionId() == CSSValueID::kEnv) {
if (!builder.IsEmpty()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
tokens.push_back(
MakeGarbageCollected<V8CSSUnparsedSegment>(builder.ToString()));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- tokens.push_back(CSSUnparsedSegment::FromString(builder.ToString()));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
builder.Clear();
}
CSSParserTokenRange block = range.ConsumeBlock();
@@ -85,12 +62,8 @@ ParserTokenRangeToTokens(CSSParserTokenRange range) {
}
}
if (!builder.IsEmpty()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
tokens.push_back(
MakeGarbageCollected<V8CSSUnparsedSegment>(builder.ToString()));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- tokens.push_back(CSSUnparsedSegment::FromString(builder.ToString()));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
return tokens;
}
@@ -117,8 +90,6 @@ CSSUnparsedValue* CSSUnparsedValue::FromCSSVariableData(
return CSSUnparsedValue::Create(ParserTokenRangeToTokens(value.TokenRange()));
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8CSSUnparsedSegment* CSSUnparsedValue::AnonymousIndexedGetter(
uint32_t index,
ExceptionState& exception_state) const {
@@ -149,42 +120,6 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
return IndexedPropertySetterResult::kIntercepted;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void CSSUnparsedValue::AnonymousIndexedGetter(
- unsigned index,
- CSSUnparsedSegment& return_value,
- ExceptionState& exception_state) const {
- if (index < tokens_.size()) {
- return_value = tokens_[index];
- } else {
- return_value = CSSUnparsedSegment();
- }
-}
-
-IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
- unsigned index,
- const CSSUnparsedSegment& segment,
- ExceptionState& exception_state) {
- if (index < tokens_.size()) {
- tokens_[index] = segment;
- return IndexedPropertySetterResult::kIntercepted;
- }
-
- if (index == tokens_.size()) {
- tokens_.push_back(segment);
- return IndexedPropertySetterResult::kIntercepted;
- }
-
- exception_state.ThrowRangeError(
- ExceptionMessages::IndexOutsideRange<unsigned>(
- "index", index, 0, ExceptionMessages::kInclusiveBound, tokens_.size(),
- ExceptionMessages::kInclusiveBound));
- return IndexedPropertySetterResult::kIntercepted;
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
const CSSValue* CSSUnparsedValue::ToCSSValue() const {
CSSTokenizer tokenizer(ToString());
const auto tokens = tokenizer.TokenizeToEOF();
@@ -201,7 +136,6 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
false /* needs_variable_resolution */, KURL(), WTF::TextEncoding()));
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String CSSUnparsedValue::ToString() const {
StringBuilder input;
@@ -230,32 +164,5 @@ String CSSUnparsedValue::ToString() const {
return input.ToString();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-String CSSUnparsedValue::ToString() const {
- StringBuilder input;
-
- for (unsigned i = 0; i < tokens_.size(); i++) {
- if (i) {
- input.Append("/**/");
- }
- if (tokens_[i].IsString()) {
- input.Append(tokens_[i].GetAsString());
- } else if (tokens_[i].IsCSSVariableReferenceValue()) {
- const auto* reference_value = tokens_[i].GetAsCSSVariableReferenceValue();
- input.Append("var(");
- input.Append(reference_value->variable());
- if (reference_value->fallback()) {
- input.Append(",");
- input.Append(reference_value->fallback()->ToString());
- }
- input.Append(")");
- } else {
- NOTREACHED();
- }
- }
-
- return input.ToString();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
index fa533cc88df..b3cf87ad0c9 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
@@ -5,66 +5,44 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_UNPARSED_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_UNPARSED_VALUE_H_
-#include "third_party/blink/renderer/bindings/core/v8/string_or_css_variable_reference_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_cssvariablereferencevalue_string.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-class CSSVariableReferenceValue;
class CSSCustomPropertyDeclaration;
class CSSVariableData;
-using CSSUnparsedSegment = StringOrCSSVariableReferenceValue;
+class CSSVariableReferenceValue;
class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSUnparsedValue* Create(
const HeapVector<Member<V8CSSUnparsedSegment>>& tokens) {
return MakeGarbageCollected<CSSUnparsedValue>(tokens);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSUnparsedValue* Create(
- const HeapVector<CSSUnparsedSegment>& tokens) {
- return MakeGarbageCollected<CSSUnparsedValue>(tokens);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Blink-internal constructor
static CSSUnparsedValue* Create() {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return Create(HeapVector<Member<V8CSSUnparsedSegment>>());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return Create(HeapVector<CSSUnparsedSegment>());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&);
static CSSUnparsedValue* FromCSSValue(const CSSCustomPropertyDeclaration&);
static CSSUnparsedValue* FromCSSVariableData(const CSSVariableData&);
static CSSUnparsedValue* FromString(const String& string) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8CSSUnparsedSegment>> tokens;
tokens.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(string));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<CSSUnparsedSegment> tokens;
- tokens.push_back(CSSUnparsedSegment::FromString(string));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return Create(tokens);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
explicit CSSUnparsedValue(
const HeapVector<Member<V8CSSUnparsedSegment>>& tokens)
: tokens_(tokens) {}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- explicit CSSUnparsedValue(const HeapVector<CSSUnparsedSegment>& tokens)
- : tokens_(tokens) {}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSUnparsedValue(const CSSUnparsedValue&) = delete;
CSSUnparsedValue& operator=(const CSSUnparsedValue&) = delete;
@@ -72,7 +50,6 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
StyleValueType GetType() const override { return kUnparsedType; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8CSSUnparsedSegment* AnonymousIndexedGetter(
uint32_t index,
ExceptionState& exception_state) const;
@@ -80,14 +57,6 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
uint32_t index,
V8CSSUnparsedSegment* segment,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void AnonymousIndexedGetter(uint32_t index,
- CSSUnparsedSegment& return_value,
- ExceptionState& exception_state) const;
- IndexedPropertySetterResult AnonymousIndexedSetter(unsigned,
- const CSSUnparsedSegment&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
wtf_size_t length() const { return tokens_.size(); }
@@ -99,11 +68,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
String ToString() const;
private:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8CSSUnparsedSegment>> tokens_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<CSSUnparsedSegment> tokens_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FRIEND_TEST_ALL_PREFIXES(CSSVariableReferenceValueTest, MixedList);
};
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 dff69eda26b..261d71594cd 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
@@ -34,7 +34,10 @@ ResourceStatus CSSURLImageValue::Status() const {
scoped_refptr<Image> CSSURLImageValue::GetSourceImageForCanvas(
SourceImageStatus*,
- const FloatSize&) {
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition) {
+ // UnpremultiplyAlpha is not implemented yet.
+ DCHECK_EQ(alpha_disposition, kPremultiplyAlpha);
return GetImage();
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.h b/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.h
index 7e6f53e8358..97bed821793 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.h
@@ -24,8 +24,10 @@ class CORE_EXPORT CSSURLImageValue final : public CSSStyleImageValue {
// CanvasImageSource
ResourceStatus Status() const final;
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) final;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) final;
bool IsAccelerated() const final;
// CSSStyleValue
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 acc8ce68951..5a3574b6c13 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
@@ -39,6 +39,7 @@ const CSSValue* DeclaredStylePropertyMap::GetCustomProperty(
void DeclaredStylePropertyMap::SetProperty(CSSPropertyID property_id,
const CSSValue& value) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
if (!GetStyleRule())
return;
CSSStyleSheet::RuleMutationScope mutation_scope(owner_rule_);
@@ -66,9 +67,8 @@ void DeclaredStylePropertyMap::SetCustomProperty(
auto* variable_data =
To<CSSVariableReferenceValue>(value).VariableDataValue();
GetStyleRule()->MutableProperties().SetProperty(
- CSSPropertyID::kVariable,
- *MakeGarbageCollected<CSSCustomPropertyDeclaration>(property_name,
- variable_data));
+ CSSPropertyName(property_name),
+ *MakeGarbageCollected<CSSCustomPropertyDeclaration>(variable_data));
}
void DeclaredStylePropertyMap::RemoveProperty(CSSPropertyID property_id) {
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 854c00e197a..33b063f2d55 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
@@ -32,6 +32,7 @@ const CSSValue* InlineStylePropertyMap::GetCustomProperty(
void InlineStylePropertyMap::SetProperty(CSSPropertyID property_id,
const CSSValue& value) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
owner_element_->SetInlineStyleProperty(property_id, value);
owner_element_->NotifyInlineStyleMutation();
}
@@ -53,9 +54,8 @@ void InlineStylePropertyMap::SetCustomProperty(
auto* variable_data =
To<CSSVariableReferenceValue>(value).VariableDataValue();
owner_element_->SetInlineStyleProperty(
- CSSPropertyID::kVariable,
- *MakeGarbageCollected<CSSCustomPropertyDeclaration>(property_name,
- variable_data));
+ CSSPropertyName(property_name),
+ *MakeGarbageCollected<CSSCustomPropertyDeclaration>(variable_data));
owner_element_->NotifyInlineStyleMutation();
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc
index dabf73f7084..937861989f3 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc
@@ -26,6 +26,8 @@ TEST(InlineStylePropertyMapTest, PendingSubstitutionValueCrash) {
const CSSProperty& shorthand = CSSProperty::Get(property_id);
if (!shorthand.IsShorthand())
continue;
+ if (shorthand.Exposure() == CSSExposure::kNone)
+ continue;
div->SetInlineStyleProperty(property_id, "var(--dummy)");
const StylePropertyShorthand& longhands = shorthandForProperty(property_id);
for (unsigned i = 0; i < longhands.length(); i++) {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.cc b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.cc
index 62b78885b2a..50cd68f8978 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.cc
@@ -31,12 +31,11 @@ void PaintWorkletDeferredImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
- const SkSamplingOptions& sampling,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode clamping_mode,
ImageDecodingMode) {
- DrawInternal(canvas, dest_rect, src_rect, sampling, flags, clamping_mode,
- image_);
+ DrawInternal(canvas, dest_rect, src_rect, draw_options.sampling_options,
+ flags, clamping_mode, image_);
}
void PaintWorkletDeferredImage::DrawTile(GraphicsContext& context,
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h
index ecccd20e76c..47584824a0a 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h
@@ -35,8 +35,7 @@ class CORE_EXPORT PaintWorkletDeferredImage : public GeneratedImage {
const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
void DrawTile(GraphicsContext&,
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h
index 32a1c56bc07..a433597d897 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h
@@ -11,6 +11,7 @@
#include "cc/paint/paint_worklet_input.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -18,6 +19,12 @@ namespace blink {
// CSS paint worklet.
class CORE_EXPORT PaintWorkletInput : public cc::PaintWorkletInput {
public:
+ enum class PaintWorkletInputType {
+ kCSS,
+ kBackgroundColor,
+ kClipPath,
+ };
+
// PaintWorkletInput implementation
gfx::SizeF GetSize() const override {
return gfx::SizeF(container_size_.Width(), container_size_.Height());
@@ -30,6 +37,8 @@ class CORE_EXPORT PaintWorkletInput : public cc::PaintWorkletInput {
// These accessors are safe on any thread.
const FloatSize& ContainerSize() const { return container_size_; }
+ virtual PaintWorkletInputType GetType() const = 0;
+
protected:
PaintWorkletInput(const FloatSize& container_size, int worklet_id)
: container_size_(container_size), worklet_id_(worklet_id) {}
@@ -43,6 +52,8 @@ class CORE_EXPORT PaintWorkletInput : public cc::PaintWorkletInput {
~PaintWorkletInput() override = default;
private:
+ bool IsCSSPaintWorkletInput() const override { return true; }
+
const FloatSize container_size_;
const int worklet_id_;
@@ -54,6 +65,13 @@ class CORE_EXPORT PaintWorkletInput : public cc::PaintWorkletInput {
cc::PaintWorkletInput::PropertyKeys property_keys_;
};
+template <>
+struct DowncastTraits<PaintWorkletInput> {
+ static bool AllowFrom(const cc::PaintWorkletInput& worklet_input) {
+ return worklet_input.IsCSSPaintWorkletInput();
+ }
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_PAINT_WORKLET_INPUT_H_
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
index 6b4d258b69b..5207e72488c 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
@@ -18,7 +18,6 @@
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h"
#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
index 4be98c2a783..6dff022d647 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
@@ -87,7 +87,7 @@ const CSSValue* PrepopulatedComputedStylePropertyMap::GetProperty(
const CSSValue* PrepopulatedComputedStylePropertyMap::GetCustomProperty(
AtomicString property_name) const {
- return custom_values_.at(property_name);
+ return custom_values_.DeprecatedAtOrEmptyValue(property_name);
}
void PrepopulatedComputedStylePropertyMap::ForEachProperty(
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 54471296e62..d76aa4b6eb7 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
@@ -205,7 +205,6 @@ const CSSValue* StyleValueToCSSValue(
return style_value.ToCSSValueWithProperty(property_id);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const CSSValue* CoerceStyleValueOrString(
const CSSProperty& property,
const AtomicString& custom_property_name,
@@ -235,44 +234,11 @@ const CSSValue* CoerceStyleValueOrString(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-const CSSValue* CoerceStyleValueOrString(
- const CSSProperty& property,
- const AtomicString& custom_property_name,
- const CSSStyleValueOrString& value,
- const ExecutionContext& execution_context) {
- DCHECK(!property.IsRepeated());
- DCHECK_EQ(property.IDEquals(CSSPropertyID::kVariable),
- !custom_property_name.IsNull());
-
- if (value.IsCSSStyleValue()) {
- if (!value.GetAsCSSStyleValue())
- return nullptr;
-
- return StyleValueToCSSValue(property, custom_property_name,
- *value.GetAsCSSStyleValue(), execution_context);
- } else {
- DCHECK(value.IsString());
- const auto values = StyleValueFactory::FromString(
- property.PropertyID(), custom_property_name, value.GetAsString(),
- MakeGarbageCollected<CSSParserContext>(execution_context));
- if (values.size() != 1U)
- return nullptr;
-
- return StyleValueToCSSValue(property, custom_property_name, *values[0],
- execution_context);
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const CSSValue* CoerceStyleValuesOrStrings(
const CSSProperty& property,
const AtomicString& custom_property_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionCSSStyleValueOrString>>& values,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSStyleValueOrString>& values,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ExecutionContext& execution_context) {
DCHECK(property.IsRepeated());
DCHECK_EQ(property.IDEquals(CSSPropertyID::kVariable),
@@ -306,11 +272,7 @@ const CSSValue* CoerceStyleValuesOrStrings(
void StylePropertyMap::set(
const ExecutionContext* execution_context,
const String& property_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionCSSStyleValueOrString>>& values,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSStyleValueOrString>& values,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
const CSSPropertyID property_id =
CssPropertyID(execution_context, property_name);
@@ -328,7 +290,6 @@ void StylePropertyMap::set(
}
String css_text;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (values[0]->GetContentType()) {
case V8UnionCSSStyleValueOrString::ContentType::kCSSStyleValue: {
CSSStyleValue* style_value = values[0]->GetAsCSSStyleValue();
@@ -342,17 +303,6 @@ void StylePropertyMap::set(
css_text = values[0]->GetAsString();
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (values[0].IsCSSStyleValue()) {
- CSSStyleValue* style_value = values[0].GetAsCSSStyleValue();
- if (style_value &&
- CSSOMTypes::PropertyCanTake(property_id, g_null_atom, *style_value)) {
- css_text = style_value->toString();
- }
- } else {
- css_text = values[0].GetAsString();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (css_text.IsEmpty() ||
!SetShorthandProperty(property.PropertyID(), css_text,
@@ -390,11 +340,7 @@ void StylePropertyMap::set(
void StylePropertyMap::append(
const ExecutionContext* execution_context,
const String& property_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionCSSStyleValueOrString>>& values,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<CSSStyleValueOrString>& values,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (values.IsEmpty())
return;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.h b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.h
index bc01b784c24..6f6d6ee3e2d 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_PROPERTY_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_PROPERTY_MAP_H_
-#include "third_party/blink/renderer/bindings/core/v8/css_style_value_or_string.h"
#include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -22,7 +21,6 @@ class CORE_EXPORT StylePropertyMap : public StylePropertyMapReadOnlyMainThread {
StylePropertyMap(const StylePropertyMap&) = delete;
StylePropertyMap& operator=(const StylePropertyMap&) = delete;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void set(const ExecutionContext* execution_context,
const String& property_name,
const HeapVector<Member<V8UnionCSSStyleValueOrString>>& values,
@@ -31,16 +29,6 @@ class CORE_EXPORT StylePropertyMap : public StylePropertyMapReadOnlyMainThread {
const String& property_name,
const HeapVector<Member<V8UnionCSSStyleValueOrString>>& values,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void set(const ExecutionContext*,
- const String& property_name,
- const HeapVector<CSSStyleValueOrString>& values,
- ExceptionState&);
- void append(const ExecutionContext*,
- const String& property_name,
- const HeapVector<CSSStyleValueOrString>& values,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void remove(const ExecutionContext*,
const String& property_name,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h
index 284dd4105c7..63b7aac4434 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_PROPERTY_MAP_READ_ONLY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_PROPERTY_MAP_READ_ONLY_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/iterable.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
index b40d228663a..d79059f740b 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
@@ -70,9 +70,8 @@ CSSStyleValue* StylePropertyMapReadOnlyMainThread::get(
return nullptr;
}
- const CSSProperty& property = CSSProperty::Get(name->Id());
- if (property.IsShorthand())
- return GetShorthandProperty(property);
+ if (CSSProperty::IsShorthand(*name))
+ return GetShorthandProperty(*name);
const CSSValue* value = (name->IsCustomProperty())
? GetCustomProperty(name->ToAtomicString())
@@ -81,7 +80,7 @@ CSSStyleValue* StylePropertyMapReadOnlyMainThread::get(
return nullptr;
// Custom properties count as repeated whenever we have a CSSValueList.
- if (property.IsRepeated() ||
+ if (CSSProperty::IsRepeated(*name) ||
(name->IsCustomProperty() && value->IsValueList())) {
CSSStyleValueVector values =
StyleValueFactory::CssValueToStyleValueVector(*name, *value);
@@ -103,10 +102,9 @@ CSSStyleValueVector StylePropertyMapReadOnlyMainThread::getAll(
return CSSStyleValueVector();
}
- const CSSProperty& property = CSSProperty::Get(name->Id());
- if (property.IsShorthand()) {
+ if (CSSProperty::IsShorthand(*name)) {
CSSStyleValueVector values;
- if (CSSStyleValue* value = GetShorthandProperty(property))
+ if (CSSStyleValue* value = GetShorthandProperty(*name))
values.push_back(value);
return values;
}
@@ -142,8 +140,9 @@ StylePropertyMapReadOnlyMainThread::StartIteration(ScriptState* script_state,
}
CSSStyleValue* StylePropertyMapReadOnlyMainThread::GetShorthandProperty(
- const CSSProperty& property) const {
- DCHECK(property.IsShorthand());
+ const CSSPropertyName& name) const {
+ DCHECK(CSSProperty::IsShorthand(name));
+ const CSSProperty& property = CSSProperty::Get(name.Id());
const auto serialization = SerializationForShorthand(property);
if (serialization.IsEmpty())
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h
index ca85956e3da..76ee9c3703b 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h
@@ -50,7 +50,7 @@ class CORE_EXPORT StylePropertyMapReadOnlyMainThread
private:
IterationSource* StartIteration(ScriptState*, ExceptionState&) override;
- CSSStyleValue* GetShorthandProperty(const CSSProperty&) const;
+ CSSStyleValue* GetShorthandProperty(const CSSPropertyName&) const;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc
index 136a47fb6c1..60f79df0d4a 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc
@@ -19,7 +19,6 @@ class StylePropertyMapTest : public PageTestBase {};
TEST_F(StylePropertyMapTest, SetRevertWithFeatureEnabled) {
DummyExceptionStateForTesting exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionCSSStyleValueOrString>> revert_string;
revert_string.push_back(
MakeGarbageCollected<V8UnionCSSStyleValueOrString>(" revert"));
@@ -28,14 +27,6 @@ TEST_F(StylePropertyMapTest, SetRevertWithFeatureEnabled) {
revert_style_value.push_back(
MakeGarbageCollected<V8UnionCSSStyleValueOrString>(
CSSKeywordValue::Create("revert", exception_state)));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<CSSStyleValueOrString> revert_string;
- revert_string.push_back(CSSStyleValueOrString::FromString(" revert"));
-
- HeapVector<CSSStyleValueOrString> revert_style_value;
- revert_style_value.push_back(CSSStyleValueOrString::FromCSSStyleValue(
- CSSKeywordValue::Create("revert", exception_state)));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* map =
MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body());
@@ -66,14 +57,9 @@ TEST_F(StylePropertyMapTest, SetOverflowClipString) {
DummyExceptionStateForTesting exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionCSSStyleValueOrString>> clip_string;
clip_string.push_back(
MakeGarbageCollected<V8UnionCSSStyleValueOrString>(" clip"));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<CSSStyleValueOrString> clip_string;
- clip_string.push_back(CSSStyleValueOrString::FromString(" clip"));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* map =
MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body());
@@ -95,15 +81,9 @@ TEST_F(StylePropertyMapTest, SetOverflowClipStyleValue) {
DummyExceptionStateForTesting exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionCSSStyleValueOrString>> clip_style_value;
clip_style_value.push_back(MakeGarbageCollected<V8UnionCSSStyleValueOrString>(
CSSKeywordValue::Create("clip", exception_state)));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<CSSStyleValueOrString> clip_style_value;
- clip_style_value.push_back(CSSStyleValueOrString::FromCSSStyleValue(
- CSSKeywordValue::Create("clip", exception_state)));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* map =
MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body());
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 db3ae431d71..50e79e32814 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
@@ -307,7 +307,7 @@ CSSStyleValueVector StyleValueFactory::FromString(
CSSStyleValue* StyleValueFactory::CssValueToStyleValue(
const CSSPropertyName& name,
const CSSValue& css_value) {
- DCHECK(!CSSProperty::Get(name.Id()).IsRepeated());
+ DCHECK(!CSSProperty::IsRepeated(name));
CSSStyleValue* style_value =
CreateStyleValueWithProperty(name.Id(), css_value);
if (!style_value)
@@ -315,7 +315,6 @@ CSSStyleValue* StyleValueFactory::CssValueToStyleValue(
return style_value;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSStyleValueVector StyleValueFactory::CoerceStyleValuesOrStrings(
const CSSProperty& property,
const AtomicString& custom_property_name,
@@ -350,40 +349,6 @@ CSSStyleValueVector StyleValueFactory::CoerceStyleValuesOrStrings(
}
return style_values;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CSSStyleValueVector StyleValueFactory::CoerceStyleValuesOrStrings(
- const CSSProperty& property,
- const AtomicString& custom_property_name,
- const HeapVector<CSSStyleValueOrString>& values,
- const ExecutionContext& execution_context) {
- const CSSParserContext* parser_context = nullptr;
-
- CSSStyleValueVector style_values;
- for (const auto& value : values) {
- if (value.IsCSSStyleValue()) {
- if (!value.GetAsCSSStyleValue())
- return CSSStyleValueVector();
- style_values.push_back(*value.GetAsCSSStyleValue());
- } else {
- DCHECK(value.IsString());
- if (!parser_context) {
- parser_context =
- MakeGarbageCollected<CSSParserContext>(execution_context);
- }
-
- const auto subvalues = StyleValueFactory::FromString(
- property.PropertyID(), custom_property_name, value.GetAsString(),
- parser_context);
- if (subvalues.IsEmpty())
- return CSSStyleValueVector();
-
- DCHECK(!subvalues.Contains(nullptr));
- style_values.AppendVector(subvalues);
- }
- }
- return style_values;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CSSStyleValueVector StyleValueFactory::CssValueToStyleValueVector(
const CSSPropertyName& name,
@@ -404,8 +369,8 @@ CSSStyleValueVector StyleValueFactory::CssValueToStyleValueVector(
// TODO(andruud): Custom properties claim to not be repeated, even though
// they may be. Therefore we must ignore "IsRepeated" for custom
// properties.
- (!CSSProperty::Get(property_id).IsRepeated() &&
- property_id != CSSPropertyID::kVariable) ||
+ (property_id != CSSPropertyID::kVariable &&
+ !CSSProperty::Get(property_id).IsRepeated()) ||
// Note: CSSTransformComponent is parsed as CSSFunctionValue, which is a
// CSSValueList. We do not yet support such CSSFunctionValues, however.
// TODO(andruud): Make CSSTransformComponent a subclass of CSSStyleValue,
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.h b/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.h
index 5741ba23235..c8b38fbeced 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_VALUE_FACTORY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_VALUE_FACTORY_H_
-#include "third_party/blink/renderer/bindings/core/v8/css_style_value_or_string.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -33,19 +32,11 @@ class CORE_EXPORT StyleValueFactory {
static CSSStyleValueVector CssValueToStyleValueVector(const CSSPropertyName&,
const CSSValue&);
// Returns an empty vector on error conditions.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CSSStyleValueVector CoerceStyleValuesOrStrings(
const CSSProperty& property,
const AtomicString& custom_property_name,
const HeapVector<Member<V8UnionCSSStyleValueOrString>>& values,
const ExecutionContext& execution_context);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CSSStyleValueVector CoerceStyleValuesOrStrings(
- const CSSProperty& property,
- const AtomicString& custom_property_name,
- const HeapVector<CSSStyleValueOrString>& values,
- const ExecutionContext&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Reify a CSSStyleValue without the context of a CSS property. For most
// CSSValues, this will result in a CSSUnsupportedStyleValue. Note that the
// CSSUnsupportedStyleValue returned from this function (unlike regular
diff --git a/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc b/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc
index ae08bd591e9..007039f2b82 100644
--- a/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc
+++ b/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -44,6 +44,8 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver_stats.h"
#include "third_party/blink/renderer/core/css/resolver/style_rule_usage_tracker.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.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/style/computed_style.h"
@@ -58,6 +60,17 @@ unsigned AdjustLinkMatchType(EInsideLink inside_link,
return link_match_type;
}
+ContainerQueryEvaluator* FindContainerQueryEvaluator(
+ const AtomicString& name,
+ const StyleRecalcContext& style_recalc_context) {
+ if (auto* element =
+ ContainerQueryEvaluator::FindContainer(style_recalc_context, name)) {
+ return element->GetContainerQueryEvaluator();
+ }
+
+ return nullptr;
+}
+
} // namespace
ElementRuleCollector::ElementRuleCollector(
@@ -198,7 +211,8 @@ void ElementRuleCollector::CollectMatchingRulesForList(
if (auto* container_query = rule_data->GetContainerQuery()) {
result_.SetDependsOnContainerQueries();
- auto* evaluator = style_recalc_context_.cq_evaluator;
+ auto* evaluator = FindContainerQueryEvaluator(container_query->Name(),
+ style_recalc_context_);
if (!evaluator || !evaluator->EvalAndAdd(*container_query)) {
rejected++;
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 5b6a853ac01..1f06ab34122 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face.cc
@@ -32,7 +32,6 @@
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/public/platform/task_type.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_font_face_descriptors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
#include "third_party/blink/renderer/core/css/binary_data_font_face_source.h"
@@ -60,6 +59,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.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"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
@@ -123,7 +123,6 @@ const CSSValue* ConvertSizeAdjustValue(const CSSValue* parsed_value) {
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FontFace* FontFace::Create(
ExecutionContext* execution_context,
const AtomicString& family,
@@ -147,23 +146,6 @@ FontFace* FontFace::Create(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-FontFace* FontFace::Create(ExecutionContext* context,
- const AtomicString& family,
- StringOrArrayBufferOrArrayBufferView& source,
- const FontFaceDescriptors* descriptors) {
- if (source.IsString())
- return Create(context, family, source.GetAsString(), descriptors);
- if (source.IsArrayBuffer())
- return Create(context, family, source.GetAsArrayBuffer(), descriptors);
- if (source.IsArrayBufferView()) {
- return Create(context, family, source.GetAsArrayBufferView().Get(),
- descriptors);
- }
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FontFace* FontFace::Create(ExecutionContext* context,
const AtomicString& family,
@@ -190,7 +172,8 @@ FontFace* FontFace::Create(ExecutionContext* context,
const FontFaceDescriptors* descriptors) {
FontFace* font_face =
MakeGarbageCollected<FontFace>(context, family, descriptors);
- font_face->InitCSSFontFace(static_cast<const unsigned char*>(source->Data()),
+ font_face->InitCSSFontFace(context,
+ static_cast<const unsigned char*>(source->Data()),
source->ByteLength());
return font_face;
}
@@ -202,7 +185,7 @@ FontFace* FontFace::Create(ExecutionContext* context,
FontFace* font_face =
MakeGarbageCollected<FontFace>(context, family, descriptors);
font_face->InitCSSFontFace(
- static_cast<const unsigned char*>(source->BaseAddress()),
+ context, static_cast<const unsigned char*>(source->BaseAddress()),
source->byteLength());
return font_face;
}
@@ -245,8 +228,6 @@ FontFace* FontFace::Create(Document* document,
font_face->SetPropertyFromStyle(properties,
AtRuleDescriptorID::LineGapOverride) &&
font_face->SetPropertyFromStyle(properties,
- AtRuleDescriptorID::AdvanceOverride) &&
- font_face->SetPropertyFromStyle(properties,
AtRuleDescriptorID::SizeAdjust) &&
font_face->GetFontSelectionCapabilities().IsValid() &&
!font_face->family().IsEmpty()) {
@@ -277,14 +258,12 @@ FontFace::FontFace(ExecutionContext* context,
AtRuleDescriptorID::FontFeatureSettings);
SetPropertyFromString(context, descriptors->display(),
AtRuleDescriptorID::FontDisplay);
- if (RuntimeEnabledFeatures::CSSFontMetricsOverrideEnabled()) {
- SetPropertyFromString(context, descriptors->ascentOverride(),
- AtRuleDescriptorID::AscentOverride);
- SetPropertyFromString(context, descriptors->descentOverride(),
- AtRuleDescriptorID::DescentOverride);
- SetPropertyFromString(context, descriptors->lineGapOverride(),
- AtRuleDescriptorID::LineGapOverride);
- }
+ SetPropertyFromString(context, descriptors->ascentOverride(),
+ AtRuleDescriptorID::AscentOverride);
+ SetPropertyFromString(context, descriptors->descentOverride(),
+ AtRuleDescriptorID::DescentOverride);
+ SetPropertyFromString(context, descriptors->lineGapOverride(),
+ AtRuleDescriptorID::LineGapOverride);
if (RuntimeEnabledFeatures::CSSFontFaceSizeAdjustEnabled()) {
SetPropertyFromString(context, descriptors->sizeAdjust(),
AtRuleDescriptorID::SizeAdjust);
@@ -474,9 +453,6 @@ bool FontFace::SetPropertyValue(const CSSValue* value,
case AtRuleDescriptorID::LineGapOverride:
line_gap_override_ = ConvertFontMetricOverrideValue(value);
break;
- case AtRuleDescriptorID::AdvanceOverride:
- advance_override_ = ConvertFontMetricOverrideValue(value);
- break;
case AtRuleDescriptorID::SizeAdjust:
size_adjust_ = ConvertSizeAdjustValue(value);
break;
@@ -888,7 +864,9 @@ void FontFace::InitCSSFontFace(ExecutionContext* context, const CSSValue& src) {
}
}
-void FontFace::InitCSSFontFace(const unsigned char* data, size_t size) {
+void FontFace::InitCSSFontFace(ExecutionContext* context,
+ const unsigned char* data,
+ size_t size) {
css_font_face_ = CreateCSSFontFace(this, unicode_range_.Get());
if (error_)
return;
@@ -900,6 +878,12 @@ void FontFace::InitCSSFontFace(const unsigned char* data, size_t size) {
if (source->IsValid()) {
SetLoadStatus(kLoaded);
} else {
+ if (!ots_parse_message_.IsEmpty()) {
+ context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "OTS parsing error: " + ots_parse_message_));
+ }
SetError(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSyntaxError, "Invalid font data in ArrayBuffer."));
}
@@ -960,13 +944,6 @@ FontMetricsOverride FontFace::GetFontMetricsOverride() const {
result.line_gap_override =
To<CSSPrimitiveValue>(*line_gap_override_).GetFloatValue() / 100;
}
- if (advance_override_) {
- const CSSValuePair& pair = To<CSSValuePair>(*advance_override_);
- result.advance_override =
- To<CSSPrimitiveValue>(pair.First()).GetFloatValue() / 100;
- result.advance_override_vertical_upright =
- To<CSSPrimitiveValue>(pair.Second()).GetFloatValue() / 100;
- }
return result;
}
diff --git a/chromium/third_party/blink/renderer/core/css/font_face.h b/chromium/third_party/blink/renderer/core/css/font_face.h
index a307e7b2330..2cfde0003fb 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.h
+++ b/chromium/third_party/blink/renderer/core/css/font_face.h
@@ -53,7 +53,6 @@ class DOMArrayBufferView;
class Document;
class ExceptionState;
class FontFaceDescriptors;
-class StringOrArrayBufferOrArrayBufferView;
class StyleRuleFontFace;
class V8UnionArrayBufferOrArrayBufferViewOrString;
struct FontMetricsOverride;
@@ -66,18 +65,11 @@ class CORE_EXPORT FontFace : public ScriptWrappable,
public:
enum LoadStatusType { kUnloaded, kLoading, kLoaded, kError };
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static FontFace* Create(
ExecutionContext* execution_context,
const AtomicString& family,
const V8UnionArrayBufferOrArrayBufferViewOrString* source,
const FontFaceDescriptors* descriptors);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static FontFace* Create(ExecutionContext*,
- const AtomicString& family,
- StringOrArrayBufferOrArrayBufferView&,
- const FontFaceDescriptors*);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static FontFace* Create(Document*, const StyleRuleFontFace*);
explicit FontFace(ExecutionContext*);
@@ -176,7 +168,7 @@ class CORE_EXPORT FontFace : public ScriptWrappable,
const FontFaceDescriptors*);
void InitCSSFontFace(ExecutionContext*, const CSSValue& src);
- void InitCSSFontFace(const unsigned char* data, size_t);
+ void InitCSSFontFace(ExecutionContext*, const unsigned char* data, size_t);
void SetPropertyFromString(const ExecutionContext*,
const String&,
AtRuleDescriptorID,
@@ -187,8 +179,8 @@ class CORE_EXPORT FontFace : public ScriptWrappable,
ScriptPromise FontStatusPromise(ScriptState*);
void RunCallbacks();
- using LoadedProperty = ScriptPromiseProperty<Member<FontFace>,
- Member<DOMException>>;
+ using LoadedProperty =
+ ScriptPromiseProperty<Member<FontFace>, Member<DOMException>>;
AtomicString family_;
String ots_parse_message_;
diff --git a/chromium/third_party/blink/renderer/core/css/font_face.idl b/chromium/third_party/blink/renderer/core/css/font_face.idl
index 5b287336927..f0a14b383bb 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.idl
+++ b/chromium/third_party/blink/renderer/core/css/font_face.idl
@@ -51,9 +51,9 @@ enum FontFaceLoadStatus {
[RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString variant;
[RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString featureSettings;
[RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString display;
- [RaisesException=Setter, SetterCallWith=ExecutionContext, RuntimeEnabled=CSSFontMetricsOverride] attribute DOMString ascentOverride;
- [RaisesException=Setter, SetterCallWith=ExecutionContext, RuntimeEnabled=CSSFontMetricsOverride] attribute DOMString descentOverride;
- [RaisesException=Setter, SetterCallWith=ExecutionContext, RuntimeEnabled=CSSFontMetricsOverride] attribute DOMString lineGapOverride;
+ [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString ascentOverride;
+ [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString descentOverride;
+ [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString lineGapOverride;
[RaisesException=Setter, SetterCallWith=ExecutionContext, RuntimeEnabled=CSSFontFaceSizeAdjust] attribute DOMString sizeAdjust;
readonly attribute FontFaceLoadStatus status;
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc b/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc
index 26ca0030ab5..91fe60a993d 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/font_face_cache.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_font_face_src_value.h"
#include "third_party/blink/renderer/core/css/css_font_family_value.h"
@@ -72,7 +72,7 @@ void FontFaceCacheTest::AppendTestFaceForCapabilities(const CSSValue& stretch,
*family_name),
CSSPropertyValue(CSSPropertyName(CSSPropertyID::kSrc), *src_value_list)};
auto* font_face_descriptor = MakeGarbageCollected<MutableCSSPropertyValueSet>(
- properties, base::size(properties));
+ properties, static_cast<wtf_size_t>(base::size(properties)));
font_face_descriptor->SetProperty(CSSPropertyID::kFontStretch, stretch);
font_face_descriptor->SetProperty(CSSPropertyID::kFontStyle, style);
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_descriptors.idl b/chromium/third_party/blink/renderer/core/css/font_face_descriptors.idl
index 49daa2f3d11..829b74844a5 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_descriptors.idl
+++ b/chromium/third_party/blink/renderer/core/css/font_face_descriptors.idl
@@ -12,8 +12,8 @@ dictionary FontFaceDescriptors {
DOMString variant = "normal";
DOMString featureSettings = "normal";
DOMString display = "auto";
- [RuntimeEnabled=CSSFontMetricsOverride, MeasureAs=FontFaceAscentOverride] DOMString ascentOverride = "normal";
- [RuntimeEnabled=CSSFontMetricsOverride, MeasureAs=FontFaceDescentOverride] DOMString descentOverride = "normal";
- [RuntimeEnabled=CSSFontMetricsOverride, MeasureAs=FontFaceLineGapOverride] DOMString lineGapOverride = "normal";
+ [MeasureAs=FontFaceAscentOverride] DOMString ascentOverride = "normal";
+ [MeasureAs=FontFaceDescentOverride] DOMString descentOverride = "normal";
+ [MeasureAs=FontFaceLineGapOverride] DOMString lineGapOverride = "normal";
[RuntimeEnabled=CSSFontFaceSizeAdjust, MeasureAs=FontFaceSizeAdjust] DOMString sizeAdjust = "100%";
};
diff --git a/chromium/third_party/blink/renderer/core/css/has_argument_match_context.cc b/chromium/third_party/blink/renderer/core/css/has_argument_match_context.cc
new file mode 100644
index 00000000000..07c14bd2094
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/has_argument_match_context.cc
@@ -0,0 +1,205 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/has_argument_match_context.h"
+
+#include "third_party/blink/renderer/core/dom/element_traversal.h"
+
+namespace { // anonymous namespace for file-local method and constant
+
+using blink::CSSSelector;
+using blink::Element;
+using blink::To;
+using blink::Traversal;
+
+const int kInfiniteDepth = -1;
+const int kInfiniteAdjacentDistance = -1;
+
+inline Element* LastDescendantOf(const Element& element,
+ int& depth,
+ const int& depth_limit) {
+ // If the current depth is at the depth limit, return null.
+ if (depth == depth_limit)
+ return nullptr;
+
+ // Return the rightmost bottom element of the element without exceeding the
+ // depth limit.
+ Element* last_descendant = nullptr;
+ for (Element* descendant = Traversal<Element>::LastChild(element); descendant;
+ descendant = Traversal<Element>::LastChild(*descendant)) {
+ last_descendant = descendant;
+ if (++depth == depth_limit)
+ break;
+ }
+ return last_descendant;
+}
+
+inline const CSSSelector* GetCurrentRelationAndNextCompound(
+ const CSSSelector* compound_selector,
+ CSSSelector::RelationType& relation) {
+ DCHECK(compound_selector);
+ for (; compound_selector;
+ compound_selector = compound_selector->TagHistory()) {
+ relation = compound_selector->Relation();
+ if (relation != CSSSelector::kSubSelector)
+ return compound_selector->TagHistory();
+ }
+ return nullptr;
+}
+
+} // namespace
+
+namespace blink {
+
+HasArgumentMatchContext::HasArgumentMatchContext(const CSSSelector* selector)
+ : leftmost_relation_(CSSSelector::kSubSelector),
+ adjacent_traversal_distance_(0),
+ descendant_traversal_depth_(0) {
+ CSSSelector::RelationType relation = CSSSelector::kSubSelector;
+ // The explicit ':scope' in ':has' argument selector is not considered
+ // for getting the depth and adjacent distance.
+ // TODO(blee@igalia.com) Need to clarify the :scope dependency in relative
+ // selector definition.
+ // - spec : https://www.w3.org/TR/selectors-4/#relative
+ // - csswg issue : https://github.com/w3c/csswg-drafts/issues/6399
+ for (selector = GetCurrentRelationAndNextCompound(selector, relation);
+ selector;
+ selector = GetCurrentRelationAndNextCompound(selector, relation)) {
+ switch (relation) {
+ case CSSSelector::kRelativeDescendant:
+ leftmost_relation_ = relation;
+ FALLTHROUGH;
+ case CSSSelector::kDescendant:
+ descendant_traversal_depth_ = kInfiniteDepth;
+ adjacent_traversal_distance_ = 0;
+ break;
+
+ case CSSSelector::kRelativeChild:
+ leftmost_relation_ = relation;
+ FALLTHROUGH;
+ case CSSSelector::kChild:
+ if (descendant_traversal_depth_ != kInfiniteDepth) {
+ descendant_traversal_depth_++;
+ adjacent_traversal_distance_ = 0;
+ }
+ break;
+
+ case CSSSelector::kRelativeDirectAdjacent:
+ leftmost_relation_ = relation;
+ FALLTHROUGH;
+ case CSSSelector::kDirectAdjacent:
+ if (adjacent_traversal_distance_ != kInfiniteAdjacentDistance)
+ adjacent_traversal_distance_++;
+ break;
+
+ case CSSSelector::kRelativeIndirectAdjacent:
+ leftmost_relation_ = relation;
+ FALLTHROUGH;
+ case CSSSelector::kIndirectAdjacent:
+ adjacent_traversal_distance_ = kInfiniteAdjacentDistance;
+ break;
+
+ case CSSSelector::kUAShadow:
+ case CSSSelector::kShadowSlot:
+ case CSSSelector::kShadowPart:
+ // TODO(blee@igalia.com) Need to check how to handle the shadow tree
+ // (e.g. ':has(::slotted(img))', ':has(component::part(my-part))')
+ return;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+CSSSelector::RelationType HasArgumentMatchContext::GetLeftMostRelation() const {
+ return leftmost_relation_;
+}
+
+bool HasArgumentMatchContext::GetDepthFixed() const {
+ return descendant_traversal_depth_ != kInfiniteDepth;
+}
+
+bool HasArgumentMatchContext::GetAdjacentDistanceFixed() const {
+ return adjacent_traversal_distance_ != kInfiniteAdjacentDistance;
+}
+
+HasArgumentSubtreeIterator::HasArgumentSubtreeIterator(
+ Element& scope_element,
+ HasArgumentMatchContext& context)
+ : scope_element_(&scope_element),
+ adjacent_distance_fixed_(context.GetAdjacentDistanceFixed()),
+ adjacent_distance_limit_(adjacent_distance_fixed_
+ ? context.adjacent_traversal_distance_
+ : std::numeric_limits<int>::max()),
+ depth_limit_(context.GetDepthFixed() ? context.descendant_traversal_depth_
+ : std::numeric_limits<int>::max()),
+ depth_(0) {
+ if (!adjacent_distance_fixed_) {
+ // Set the traversal_end_ as the next sibling of the :has scope element,
+ // and move to the last sibling of the :has scope element, and move again
+ // to the last descendant of the last sibling.
+ traversal_end_ = Traversal<Element>::NextSibling(*scope_element_);
+ if (!traversal_end_) {
+ current_ = nullptr;
+ return;
+ }
+ Element* last_sibling =
+ Traversal<Element>::LastChild(*scope_element_->parentNode());
+ current_ = LastDescendantOf(*last_sibling, depth_, depth_limit_);
+ if (!current_)
+ current_ = last_sibling;
+ } else if (adjacent_distance_limit_ == 0) {
+ DCHECK_GT(depth_limit_, 0);
+ // Set the traversal_end_ as the first child of the :has scope element,
+ // and move to the last descendant of the :has scope element without
+ // exceeding the depth limit.
+ traversal_end_ = Traversal<Element>::FirstChild(*scope_element_);
+ if (!traversal_end_) {
+ current_ = nullptr;
+ return;
+ }
+ current_ = LastDescendantOf(*scope_element_, depth_, depth_limit_);
+ DCHECK(current_);
+ } else {
+ // Set the traversal_end_ as the element at the adjacent distance of the
+ // :has scope element, and move to the last descendant of the element
+ // without exceeding the depth limit.
+ int distance;
+ for (distance = 1,
+ traversal_end_ = Traversal<Element>::NextSibling(*scope_element_);
+ distance < adjacent_distance_limit_ && traversal_end_; distance++,
+ traversal_end_ = Traversal<Element>::NextSibling(*traversal_end_)) {
+ }
+ if (!traversal_end_) {
+ current_ = nullptr;
+ return;
+ }
+ if ((current_ = LastDescendantOf(*traversal_end_, depth_, depth_limit_)))
+ return;
+ current_ = traversal_end_;
+ }
+}
+
+void HasArgumentSubtreeIterator::operator++() {
+ DCHECK(current_);
+ DCHECK_NE(current_, scope_element_);
+ if (current_ == traversal_end_) {
+ current_ = nullptr;
+ return;
+ }
+
+ // Move to the previous element in DOM tree order within the depth limit.
+ if (Element* next = Traversal<Element>::PreviousSibling(*current_)) {
+ Element* last_descendant = LastDescendantOf(*next, depth_, depth_limit_);
+ current_ = last_descendant ? last_descendant : next;
+ } else {
+ DCHECK_GT(depth_, 0);
+ depth_--;
+ current_ = current_->parentElement();
+ }
+ DCHECK(current_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/has_argument_match_context.h b/chromium/third_party/blink/renderer/core/css/has_argument_match_context.h
new file mode 100644
index 00000000000..1d84cdc18ac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/has_argument_match_context.h
@@ -0,0 +1,215 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_ARGUMENT_MATCH_CONTEXT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_ARGUMENT_MATCH_CONTEXT_H_
+
+#include "third_party/blink/renderer/core/css/css_selector.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+
+namespace blink {
+
+class HasArgumentSubtreeIterator;
+
+class HasArgumentMatchContext {
+ STACK_ALLOCATED();
+
+ public:
+ explicit HasArgumentMatchContext(const CSSSelector* selector);
+ CSSSelector::RelationType GetLeftMostRelation() const;
+ bool GetDepthFixed() const;
+ bool GetAdjacentDistanceFixed() const;
+
+ private:
+ // Indicate the :has argument relative type and subtree traversal scope.
+ // If 'adjacent_traversal_distance_' is greater than 0, then it means that
+ // it is enough to traverse the adjacent subtree at that distance.
+ // If it is -1, it means that all the adjacent subtree need to be traversed.
+ // If 'descendant_traversal_depth_' is greater than 0, then it means that
+ // it is enough to traverse elements at the certain depth. If it is -1,
+ // it means that all of the descendant subtree need to be traversed.
+ //
+ // Case 1: (kDescendant, 0, -1)
+ // - Argument selector conditions
+ // - Starts with descendant combinator.
+ // - E.g. ':has(.a)', ':has(:scope .a)', ':has(.a ~ .b > .c)'
+ // - Traverse all descendants of the :has scope element.
+ // Case 2: (kChild, 0, -1)
+ // - Argument selector conditions
+ // - Starts with child combinator.
+ // - At least one descendant combinator.
+ // - E.g. ':has(:scope > .a .b)', ':has(:scope > .a ~ .b .c)'
+ // - Traverse all descendants of the :has scope element.
+ // Case 3: (kChild, 0, n)
+ // - Argument selector conditions
+ // - Starts with child combinator.
+ // - n number of child combinator. (n > 0)
+ // - No descendant combinator.
+ // - E.g.
+ // - ':has(:scope > .a)' : (kChild, 0, 1)
+ // - ':has(:scope > .a ~ .b > .c)' : (kChild, 0, 2)
+ // - Traverse the depth n descendants of the :has scope element.
+ // Case 4: (kIndirectAdjacent, -1, -1)
+ // - Argument selector conditions
+ // - Starts with subsequent-sibling combinator.
+ // - At least one descendant combinator.
+ // - E.g. ':has(:scope ~ .a .b)', ':has(:scope ~ .a + .b > .c ~ .d .e)'
+ // - Traverse all the subsequent sibling subtrees of the :has scope element.
+ // (all subsequent siblings and it's descendants)
+ // Case 5: (kIndirectAdjacent, -1, 0)
+ // - Argument selector conditions
+ // - Starts with subsequent-sibling combinator.
+ // - No descendant/child combinator.
+ // - E.g. ':has(:scope ~ .a)', ':has(:scope ~ .a + .b ~ .c)'
+ // - Traverse all subsequent siblings of the :has scope element.
+ // Case 6: (kIndirectAdjacent, -1, n)
+ // - Argument selector conditions
+ // - Starts with subsequent-sibling combinator.
+ // - n number of child combinator. (n > 0)
+ // - No descendant combinator.
+ // - E.g.
+ // - ':has(:scope ~ .a > .b)' : (kIndirectAdjacent, -1, 1)
+ // - ':has(:scope ~ .a + .b > .c ~ .d > .e)' : (kIndirectAdjacent, -1, 2)
+ // - Traverse depth n elements of all subsequent sibling subtree of the
+ // :has scope element.
+ // Case 7: (kDirectAdjacent, -1, -1)
+ // - Argument selector conditions
+ // - Starts with next-sibling combinator.
+ // - At least one subsequent-sibling combinator to the left of every
+ // descendant or child combinator.
+ // - At least 1 descendant combinator.
+ // - E.g. ':has(:scope + .a ~ .b .c)', ':has(:scope + .a ~ .b > .c + .e .f)'
+ // - Traverse all the subsequent sibling subtrees of the :has scope element.
+ // (all subsequent siblings and it's descendants)
+ // Case 8: (kDirectAdjacent, -1, 0)
+ // - Argument selector conditions
+ // - Starts with next-sibling combinator.
+ // - At least one subsequent-sibling combinator.
+ // - No descendant/child combinator.
+ // - E.g. ':has(:scope + .a ~ .b)', ':has(:scope + .a + .b ~ .c)'
+ // - Traverse all subsequent siblings of the :has scope element.
+ // Case 9: (kDirectAdjacent, -1, n)
+ // - Argument selector conditions
+ // - Starts with next-sibling combinator.
+ // - At least one subsequent-sibling combinator to the left of every
+ // descendant or child combinator.
+ // - n number of child combinator. (n > 0)
+ // - No descendant combinator.
+ // - E.g.
+ // - ':has(:scope + .a ~ .b > .c)' : (kDirectAdjacent, -1, 1)
+ // - ':has(:scope + .a ~ .b > .c + .e >.f)' : (kDirectAdjacent, -1, 2)
+ // - Traverse depth n elements of all subsequent sibling subtree of the
+ // :has scope element.
+ // Case 10: (kDirectAdjacent, n, -1)
+ // - Argument selector conditions
+ // - Starts with next-sibling combinator.
+ // - n number of next-sibling combinator to the left of the leftmost
+ // child(or descendant) combinator. (n > 0)
+ // - No subsequent-sibling combinator to the left of the leftmost child
+ // (or descendant) combinator.
+ // - At least 1 descendant combinator.
+ // - E.g.
+ // - ':has(:scope + .a .b)' : (kDirectAdjacent, 1, -1)
+ // - ':has(:scope + .a > .b + .c .d)' : (kDirectAdjacent, 1, -1)
+ // - ':has(:scope + .a + .b > .c .d)' : (kDirectAdjacent, 2, -1)
+ // - Traverse the distance n sibling subtree of the :has scope element.
+ // (sibling element at distance n, and it's descendants).
+ // Case 11: (kDirectAdjacent, n, 0)
+ // - Argument selector conditions
+ // - Starts with next-sibling combinator.
+ // - n number of next-sibling combinator. (n > 0)
+ // - No child/descendant/subsequent-sibling combinator.
+ // - E.g.
+ // - ':has(:scope + .a)' : (kDirectAdjacent, 1, 0)
+ // - ':has(:scope + .a + .b + .c)' : (kDirectAdjacent, 3, 0)
+ // - Traverse the distance n sibling element of the :has scope element.
+ // Case 12: (kDirectAdjacent, n, m)
+ // - Argument selector conditions
+ // - Starts with next-sibling combinator.
+ // - n number of next-sibling combinator to the left of the leftmost
+ // child combinator. (n > 0)
+ // - No subsequent-sibling combinator to the left of the leftmost child
+ // combinator.
+ // - n number of child combinator. (n > 0)
+ // - No descendant combinator.
+ // - E.g.
+ // - ':has(:scope + .a > .b)' : (kDirectAdjacent, 1, 1)
+ // - ':has(:scope + .a + .b > .c ~ .d > .e)' : (kDirectAdjacent, 2, 2)
+ // - Traverse the depth m elements of the distance n sibling subtree of
+ // the :has scope element. (elements at depth m of the descendant subtree
+ // of the sibling element at distance n)
+ CSSSelector::RelationType leftmost_relation_;
+ int adjacent_traversal_distance_;
+ int descendant_traversal_depth_;
+
+ friend class HasArgumentSubtreeIterator;
+};
+
+// Subtree traversal iterator class for ':has' argument matching. To
+// solve the following problems, this traversal uses the right-to-left
+// postorder tree traversal, and provides a functionality to limit the
+// traversal depth.
+//
+// 1. Prevent incorrect 'NotMatched' cache status marked in the ':has'
+// argument selector matching iteration.
+//
+// With the pre-order tree traversal, the previous ':has' matching logic
+// cannot guarantee that an element with 'NotMatched' status is actually
+// 'checked the :has selector on the element but not matched'.
+// To skip the duplicated argument selector matching on the descendant
+// subtree of an element, in the :has argument matching iteration,
+// SelectorChecker marks every descendant elements as 'NotMatched' if
+// the element status is not 'Matched'. This logic works when the subtree
+// doesn't have any argument matched element, or only 1 element. But
+// if the subtree has more than 2 argument matching elements and one of
+// them is an ancestor of the other, the pre-order tree traversal cannot
+// guarantee the 'NotMatched' status of the ancestor element because it
+// traverse root first before traversing it's descendants.
+// The right-to-left post-order traversal can guarantee the logic of
+// marking 'NotMatched' in the ':has' argument matching iteration
+// because it guarantee that the descendant subtree of the element and
+// the downward subtree(succeeding siblings and it's descendants) of the
+// element was already checked. (If any of the previous traversals have
+// matched the argument selector, the element marked as 'Matched' when
+// it was the :has scope element of the match)
+//
+// 2. Prevent unnecessary subtree traversal when it can be limited with
+// child combinator or direct sibling combinator.
+//
+// We can limit the tree traversal range when we count the leftmost
+// combinators of a ':has' argument selector. For example, when we have
+// 'div:has(:scope > .a > .b)', instead of traversing all the descendants
+// of div element, we can limit the traversal only for the elements at
+// depth 2 of the div element. When we have 'div:has(:scope + .a > .b)',
+// we can limit the traversal only for the child elements of the direct
+// adjacent sibling of the div element. To implement this, we need a
+// way to limit the traversal depth and a way to check whether the
+// iterator is currently at the fixed depth or not.
+//
+// TODO(blee@igalia.com) Need to check how to handle the shadow tree
+// cases (e.g. ':has(::slotted(img))', ':has(component::part(my-part))')
+class HasArgumentSubtreeIterator {
+ STACK_ALLOCATED();
+
+ public:
+ HasArgumentSubtreeIterator(Element&, HasArgumentMatchContext&);
+ void operator++();
+ Element* Get() const { return current_; }
+ bool IsEnd() const { return !current_; }
+ bool IsAtFixedDepth() const { return depth_ == depth_limit_; }
+ int IsAtSiblingOfHasScope() const { return depth_ == 0; }
+
+ private:
+ Element* const scope_element_;
+ const bool adjacent_distance_fixed_;
+ const int adjacent_distance_limit_;
+ const int depth_limit_;
+ int depth_;
+ Element* current_;
+ Element* traversal_end_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_ARGUMENT_MATCH_CONTEXT_H_
diff --git a/chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.cc b/chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.cc
new file mode 100644
index 00000000000..c6b2709e9d9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.cc
@@ -0,0 +1,56 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
+
+#include "third_party/blink/renderer/core/css/css_selector.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+
+namespace blink {
+
+HasMatchedCacheScope::HasMatchedCacheScope(Document* document)
+ : document_(document) {
+ DCHECK(document_);
+
+ if (document_->GetHasMatchedCacheScope())
+ return;
+
+ document_->SetHasMatchedCacheScope(this);
+}
+
+HasMatchedCacheScope::~HasMatchedCacheScope() {
+ if (document_->GetHasMatchedCacheScope() != this)
+ return;
+
+ document_->SetHasMatchedCacheScope(nullptr);
+}
+
+// static
+ElementHasMatchedMap& HasMatchedCacheScope::GetCacheForSelector(
+ const Document* document,
+ const CSSSelector* selector) {
+ // To increase the cache hit ratio, we need to have a same cache key
+ // for multiple selector instances those are actually has a same selector.
+ // TODO(blee@igalia.com) Find a way to get hash key without serialization.
+ String selector_text = selector->SelectorText();
+
+ DCHECK(document);
+ DCHECK(document->GetHasMatchedCacheScope());
+
+ HasMatchedCache& cache =
+ document->GetHasMatchedCacheScope()->has_matched_cache_;
+
+ auto element_has_matched_map = cache.find(selector_text);
+
+ if (element_has_matched_map == cache.end()) {
+ return *cache
+ .Set(selector_text,
+ MakeGarbageCollected<ElementHasMatchedMap>())
+ .stored_value->value;
+ }
+
+ return *element_has_matched_map->value;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.h b/chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.h
new file mode 100644
index 00000000000..b5cbdef4276
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/has_matched_cache_scope.h
@@ -0,0 +1,119 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_MATCHED_CACHE_SCOPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_MATCHED_CACHE_SCOPE_H_
+
+#include "third_party/blink/renderer/core/dom/element.h"
+
+namespace blink {
+
+class Document;
+
+using ElementHasMatchedMap = HeapHashMap<Member<const Element>, bool>;
+using HasMatchedCache = HeapHashMap<String, Member<ElementHasMatchedMap>>;
+
+// HasMatchedCacheScope is the stack-allocated scoping class for :has
+// matching cache.
+//
+// This class has a hashmap to hold the matching status, so the cache
+// lifecycle follows the lifecycle of the HasMatchedCacheScope instance.
+// (The hashmap for caching will be created at the construction of a
+// HasMatchedCacheScope instance, and removed at the destruction of the
+// instance)
+//
+// void SomeFunction() {
+// HasMatchedCacheScope cache_scope; // A cache will be created here.
+// // Can use the created cache here.
+// } // The cache will be deleted here.
+//
+// The scope instance is allocated in the function-call stack, so the
+// allocation can be nested. In this case, nested cache scope should not
+// override the previous cache scope for a better cache hit ratio.
+//
+// void SomeFunction2() {
+// HasMatchedCacheScope cache_scope2;
+// // Use the cache in the cache_scope1.
+// // The cache in the cache_scope2 will not be used.
+// }
+//
+// void SomeFunction1() {
+// HasMatchedCacheScope cache_scope1;
+// // Use the cache in the cache_scope1
+// SomeFunction2();
+// }
+//
+// To make this simple, the first allocated instance on the call stack will
+// be held in the Document instance. (The instance registers itself in the
+// contructor and deregisters itself in the destructor) This is based on
+// the restriction : The HasMatchedCacheScope is allowed to use only in the
+// sequences on the blink main thread.
+//
+// The cache is valid until the DOM doesn't mutate, so any DOM mutations
+// inside the cache scope is not allowed because it will make incorrect
+// matching behavior.
+//
+// The cache keeps all the :has() matching status regardless of location.
+// (e.g. '.a:has(.b) .c', '.a .b:has(.c)', ':is(.a:has(.b) .c) .d', ...)
+//
+// It stores the matching status of a :has simple selector. For example,
+// when we have the selector '.a:has(.b) .c', during the selector matching
+// sequence, matching result for ':has(.b)' will be inserted into the cache.
+//
+// To differentiate multiple :has() simple selectors, the argument selector
+// text is selected as a cache key. For example, if we already have the result
+// of ':has(.a)' in the cache with cache key '.a', and we have the selectors
+// '.b:has(.a) .c' and '.b .c:has(a)' to be matched, then the matching
+// overhead of those 2 selectors will be similar with the overhead of '.a .c'
+// because we can get the result of ':has(.a)' from the cache with the cache
+// key '.a'.
+//
+// The cache uses 2 dimensional hash map to store the matching status.
+// - hashmap[<argument-selector>][<element>] = <boolean>
+//
+// A cache item has 3 status as below.
+// - Matched:
+// - Checked :has(<argument-selector>) on <element> and matched
+// - Cache item with 'true' value
+// - Checked:
+// - Checked :has(<argument-selector>) on <element> but not matched
+// - Cache item with 'false' value
+// - NotChecked:
+// - Not checked :has(<argument-selector>) on <element> (default)
+// - Cache item doesn't exist
+//
+// During the selector matching operation on an element, the cache items
+// will be inserted for every :has argument selector matching operations
+// on the subtree elements of the element.
+//
+// When we have a style rule 'div.b:has(.a1,.a2,.a3,...,.an) {...}', and
+// m number of elements in the descendant subtree of div.b elements, and
+// o number of ancestors of div.b elements, the maximum number of
+// inserted cache items will be n*(m+o)
+//
+// TODO(blee@igalia.com) Need to think about some restrictions that can
+// help to limit the cache size. For example, compounding with universal.
+// When the ':has' is compounded with universal selector(e.g. ':has(...)'
+// or '*:has(...)'), cache size can be large (m will be the number of
+// elements in the document, and o will be zero). Need to restrict the
+// case of compounding ':has' with universal selector?
+class HasMatchedCacheScope {
+ STACK_ALLOCATED();
+
+ public:
+ explicit HasMatchedCacheScope(Document*);
+ ~HasMatchedCacheScope();
+
+ static ElementHasMatchedMap& GetCacheForSelector(const Document*,
+ const CSSSelector*);
+
+ private:
+ HasMatchedCache has_matched_cache_;
+
+ Document* document_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_MATCHED_CACHE_SCOPE_H_
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
index b8d4534fe88..e2fb46f0eb5 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
@@ -14,7 +14,6 @@
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
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 483e3d2c52b..0463c266a2a 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
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/mathml.css b/chromium/third_party/blink/renderer/core/css/mathml.css
index 7a26d2937e8..fb143737bfc 100644
--- a/chromium/third_party/blink/renderer/core/css/mathml.css
+++ b/chromium/third_party/blink/renderer/core/css/mathml.css
@@ -35,6 +35,16 @@
/* By default, we only display the MathML formulas without any formatting other than the one specified by the display attribute. */
math {
+ direction: ltr;
+ writing-mode: horizontal-tb;
+ text-indent: 0;
+ letter-spacing: normal;
+ line-height: normal;
+ word-spacing: normal;
+ /* TODO(1228189): Implement font-family: math */
+ font-size: inherited;
+ font-style: normal;
+ font-weight: normal;
display: inline math;
math-shift: normal;
math-style: compact;
@@ -66,7 +76,7 @@ semantics > :not(:first-child) {
}
merror {
- color: red;
+ border: 1px solid red;
background-color: lightYellow;
}
@@ -82,6 +92,18 @@ mi {
/* Tables */
mtable {
math-style: compact;
+ display: inline-table;
+}
+
+mtr {
+ display: table-row;
+}
+
+mtd {
+ display: table-cell;
+ padding: 0.5ex 0.4em;
+ /* TODO(crbug.com/1125111): Properly center complex <mtd> children like mrow. */
+ text-align: -webkit-center;
}
/* Fractions */
@@ -124,10 +146,14 @@ munderover[accentunder="true" i] > :nth-child(2),
munderover[accent="true" i] > :nth-child(3) {
font-size: inherit;
}
-
-munder > :nth-child(2),
-munderover > :nth-child(2),
+msub > :nth-child(2),
+msubsup > :nth-child(2),
+mmultiscripts > :nth-child(even),
+mmultiscripts > mprescripts ~ :nth-child(odd),
mover[accent="true" i] > :first-child,
munderover[accent="true" i] > :first-child {
math-shift: compact;
}
+mmultiscripts > mprescripts ~ :nth-child(even) {
+ math-shift: inherit;
+}
diff --git a/chromium/third_party/blink/renderer/core/css/media_feature_names.json5 b/chromium/third_party/blink/renderer/core/css/media_feature_names.json5
index 002c071d317..4c70cb97df2 100644
--- a/chromium/third_party/blink/renderer/core/css/media_feature_names.json5
+++ b/chromium/third_party/blink/renderer/core/css/media_feature_names.json5
@@ -19,6 +19,8 @@
"orientation",
"aspect-ratio",
"device-aspect-ratio",
+ "dynamic-range",
+ "video-dynamic-range",
"-webkit-device-pixel-ratio",
"device-height",
"device-width",
diff --git a/chromium/third_party/blink/renderer/core/css/media_feature_overrides.h b/chromium/third_party/blink/renderer/core/css/media_feature_overrides.h
index 96e2e1da8ed..5ad58a17fa0 100644
--- a/chromium/third_party/blink/renderer/core/css/media_feature_overrides.h
+++ b/chromium/third_party/blink/renderer/core/css/media_feature_overrides.h
@@ -15,7 +15,7 @@ class CORE_EXPORT MediaFeatureOverrides {
public:
void SetOverride(const AtomicString& feature, const String& value_string);
MediaQueryExpValue GetOverride(const AtomicString& feature) const {
- return overrides_.at(feature);
+ return overrides_.DeprecatedAtOrEmptyValue(feature);
}
private:
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc b/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc
index e8eabbb24d4..d1f712f90a8 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -29,14 +29,9 @@
#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
+#include "services/device/public/mojom/device_posture_provider.mojom-blink.h"
#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/public/common/css/navigation_controls.h"
-#include "third_party/blink/renderer/core/css/media_values.h"
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -46,6 +41,7 @@
#include "third_party/blink/renderer/core/css/media_features.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/media_query.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/media_values_dynamic.h"
#include "third_party/blink/renderer/core/css/resolver/media_query_result.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
@@ -58,33 +54,14 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
+using device::mojom::blink::DevicePostureType;
using mojom::blink::HoverType;
using mojom::blink::PointerType;
-namespace {
-
-void RecordMediaQueryResult(Document* doc,
- const MediaQueryExp& expr,
- bool result) {
- IdentifiableTokenBuilder input_builder;
- input_builder.AddToken(IdentifiabilityBenignStringToken(expr.MediaFeature()));
- input_builder.AddToken(
- IdentifiabilityBenignStringToken(expr.ExpValue().CssText()));
- IdentifiableSurface surface = IdentifiableSurface::FromTypeAndToken(
- IdentifiableSurface::Type::kMediaQuery, input_builder.GetToken());
-
- IdentifiabilityMetricBuilder(doc->UkmSourceID())
- .Set(surface, result)
- .Record(doc->UkmRecorder());
-}
-
-} // namespace
-
enum MediaFeaturePrefix { kMinPrefix, kMaxPrefix, kNoPrefix };
using EvalFunc = bool (*)(const MediaQueryExpValue&,
@@ -350,6 +327,35 @@ static bool DeviceAspectRatioMediaFeatureEval(const MediaQueryExpValue& value,
return true;
}
+static bool DynamicRangeMediaFeatureEval(const MediaQueryExpValue& value,
+ MediaFeaturePrefix op,
+ const MediaValues& media_values) {
+ if (!value.is_id)
+ return false;
+
+ bool const supports_hdr = media_values.DeviceSupportsHDR();
+
+ switch (value.id) {
+ case CSSValueID::kStandard:
+ return !supports_hdr;
+
+ case CSSValueID::kHigh:
+ return supports_hdr;
+
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+static bool VideoDynamicRangeMediaFeatureEval(const MediaQueryExpValue& value,
+ MediaFeaturePrefix op,
+ const MediaValues& media_values) {
+ // For now, Chrome makes no distinction between video-dynamic-range and
+ // dynamic-range
+ return DynamicRangeMediaFeatureEval(value, op, media_values);
+}
+
static bool EvalResolution(const MediaQueryExpValue& value,
MediaFeaturePrefix op,
const MediaValues& media_values) {
@@ -902,27 +908,24 @@ static bool PrefersContrastMediaFeatureEval(const MediaQueryExpValue& value,
WebFeature::kPrefersContrastMediaFeature);
auto preferred_contrast = media_values.GetPreferredContrast();
- ForcedColors forced_colors = media_values.GetForcedColors();
if (!value.IsValid()) {
- return forced_colors != ForcedColors::kNone ||
- preferred_contrast != mojom::blink::PreferredContrast::kNoPreference;
+ return preferred_contrast != mojom::blink::PreferredContrast::kNoPreference;
}
if (!value.is_id)
return false;
switch (value.id) {
- case CSSValueID::kForced:
- return forced_colors == ForcedColors::kActive;
case CSSValueID::kMore:
return preferred_contrast == mojom::blink::PreferredContrast::kMore;
case CSSValueID::kLess:
return preferred_contrast == mojom::blink::PreferredContrast::kLess;
case CSSValueID::kNoPreference:
- return forced_colors != ForcedColors::kActive &&
- preferred_contrast ==
- mojom::blink::PreferredContrast::kNoPreference;
+ return preferred_contrast ==
+ mojom::blink::PreferredContrast::kNoPreference;
+ case CSSValueID::kCustom:
+ return preferred_contrast == mojom::blink::PreferredContrast::kCustom;
default:
NOTREACHED();
return false;
@@ -1000,20 +1003,14 @@ static bool DevicePostureMediaFeatureEval(const MediaQueryExpValue& value,
DCHECK(value.is_id);
- DevicePosture device_posture = media_values.GetDevicePosture();
+ DevicePostureType device_posture = media_values.GetDevicePosture();
switch (value.id) {
- case CSSValueID::kNoFold:
- return device_posture == DevicePosture::kNoFold;
- case CSSValueID::kLaptop:
- return device_posture == DevicePosture::kLaptop;
- case CSSValueID::kFlat:
- return device_posture == DevicePosture::kFlat;
- case CSSValueID::kTent:
- return device_posture == DevicePosture::kTent;
- case CSSValueID::kTablet:
- return device_posture == DevicePosture::kTablet;
- case CSSValueID::kBook:
- return device_posture == DevicePosture::kBook;
+ case CSSValueID::kContinuous:
+ return device_posture == DevicePostureType::kContinuous;
+ case CSSValueID::kFolded:
+ return device_posture == DevicePostureType::kFolded;
+ case CSSValueID::kFoldedOver:
+ return device_posture == DevicePostureType::kFoldedOver;
default:
NOTREACHED();
return false;
@@ -1044,17 +1041,8 @@ bool MediaQueryEvaluator::Eval(const MediaQueryExp& expr) const {
// Call the media feature evaluation function. Assume no prefix and let
// trampoline functions override the prefix if prefix is used.
EvalFunc func = g_function_map->at(expr.MediaFeature().Impl());
- if (func) {
- bool result = func(expr.ExpValue(), kNoPrefix, *media_values_);
- Document* doc = nullptr;
- if (!skip_ukm_reporting_ && (doc = media_values_->GetDocument()) &&
- (IdentifiabilityStudySettings::Get()->ShouldSample(
- IdentifiableSurface::Type::kMediaQuery))) {
- RecordMediaQueryResult(doc, expr, result);
- }
-
- return result;
- }
+ if (func)
+ return func(expr.ExpValue(), kNoPrefix, *media_values_);
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc b/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
index f18549a37fb..9f3dec4a68b 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
@@ -22,329 +22,311 @@
namespace blink {
-typedef struct {
+struct MediaQueryEvaluatorTestCase {
const char* input;
const bool output;
-} MediaQueryEvaluatorTestCase;
+};
MediaQueryEvaluatorTestCase g_screen_test_cases[] = {
- {"", 1},
- {" ", 1},
- {"screen", 1},
- {"screen and (color)", 1},
- {"not screen and (color)", 0},
- {"screen and (device-aspect-ratio: 16/9)", 0},
- {"screen and (device-aspect-ratio: 1/1)", 1},
- {"all and (min-color: 2)", 1},
- {"all and (min-color: 32)", 0},
- {"all and (min-color-index: 0)", 1},
- {"all and (min-color-index: 1)", 0},
- {"all and (monochrome)", 0},
- {"all and (min-monochrome: 0)", 1},
- {"all and (grid: 0)", 1},
- {"(resolution: 2dppx)", 1},
- {"(resolution: 1dppx)", 0},
- {"(orientation: portrait)", 1},
- {"(orientation: landscape)", 0},
- {"(orientation: url(portrait))", 0},
- {"(orientation: #portrait)", 0},
- {"(orientation: @portrait)", 0},
- {"(orientation: 'portrait')", 0},
- {"(orientation: @junk portrait)", 0},
- {"screen and (orientation: @portrait) and (max-width: 1000px)", 0},
- {"screen and (orientation: @portrait), (max-width: 1000px)", 1},
- {"tv and (scan: progressive)", 0},
- {"(pointer: coarse)", 0},
- {"(pointer: fine)", 1},
- {"(hover: hover)", 1},
- {"(hover: on-demand)", 0},
- {"(hover: none)", 0},
- {"(display-mode)", 1},
- {"(display-mode: fullscreen)", 0},
- {"(display-mode: standalone)", 0},
- {"(display-mode: minimal-ui)", 0},
- {"(display-mode: browser)", 1},
- {"(display-mode: min-browser)", 0},
- {"(display-mode: url(browser))", 0},
- {"(display-mode: #browser)", 0},
- {"(display-mode: @browser)", 0},
- {"(display-mode: 'browser')", 0},
- {"(display-mode: @junk browser)", 0},
- {"(max-device-aspect-ratio: 4294967295/1)", 1},
- {"(min-device-aspect-ratio: 1/4294967296)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"", true},
+ {" ", true},
+ {"screen", true},
+ {"screen and (color)", true},
+ {"not screen and (color)", false},
+ {"screen and (device-aspect-ratio: 16/9)", false},
+ {"screen and (device-aspect-ratio: 1/1)", true},
+ {"all and (min-color: 2)", true},
+ {"all and (min-color: 32)", false},
+ {"all and (min-color-index: 0)", true},
+ {"all and (min-color-index: 1)", false},
+ {"all and (monochrome)", false},
+ {"all and (min-monochrome: 0)", true},
+ {"all and (grid: 0)", true},
+ {"(resolution: 2dppx)", true},
+ {"(resolution: 1dppx)", false},
+ {"(orientation: portrait)", true},
+ {"(orientation: landscape)", false},
+ {"(orientation: url(portrait))", false},
+ {"(orientation: #portrait)", false},
+ {"(orientation: @portrait)", false},
+ {"(orientation: 'portrait')", false},
+ {"(orientation: @junk portrait)", false},
+ {"screen and (orientation: @portrait) and (max-width: 1000px)", false},
+ {"screen and (orientation: @portrait), (max-width: 1000px)", true},
+ {"tv and (scan: progressive)", false},
+ {"(pointer: coarse)", false},
+ {"(pointer: fine)", true},
+ {"(hover: hover)", true},
+ {"(hover: on-demand)", false},
+ {"(hover: none)", false},
+ {"(display-mode)", true},
+ {"(display-mode: fullscreen)", false},
+ {"(display-mode: standalone)", false},
+ {"(display-mode: minimal-ui)", false},
+ {"(display-mode: browser)", true},
+ {"(display-mode: min-browser)", false},
+ {"(display-mode: url(browser))", false},
+ {"(display-mode: #browser)", false},
+ {"(display-mode: @browser)", false},
+ {"(display-mode: 'browser')", false},
+ {"(display-mode: @junk browser)", false},
+ {"(max-device-aspect-ratio: 4294967295/1)", true},
+ {"(min-device-aspect-ratio: 1/4294967296)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_monochrome_test_cases[] = {
- {"(color)", 0},
- {"(monochrome)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(color)", false},
+ {"(monochrome)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_viewport_test_cases[] = {
- {"all and (min-width: 500px)", 1},
- {"(min-width: 500px)", 1},
- {"(min-width: 501px)", 0},
- {"(max-width: 500px)", 1},
- {"(max-width: 499px)", 0},
- {"(width: 500px)", 1},
- {"(width: 501px)", 0},
- {"(min-height: 500px)", 1},
- {"(min-height: 501px)", 0},
- {"(min-height: 500.02px)", 0},
- {"(max-height: 500px)", 1},
- {"(max-height: calc(500px))", 1},
- {"(max-height: 499.98px)", 0},
- {"(max-height: 499px)", 0},
- {"(height: 500px)", 1},
- {"(height: calc(500px))", 1},
- {"(height: 500.001px)", 1},
- {"(height: 499.999px)", 1},
- {"(height: 500.02px)", 0},
- {"(height: 499.98px)", 0},
- {"(height: 501px)", 0},
- {"(height)", 1},
- {"(width)", 1},
- {"(width: whatisthis)", 0},
- {"screen and (min-width: 400px) and (max-width: 700px)", 1},
- {"(max-aspect-ratio: 4294967296/1)", 1},
- {"(max-aspect-ratio: calc(4294967296) / calc(1)", 1},
- {"(min-aspect-ratio: 1/4294967295)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"all and (min-width: 500px)", true},
+ {"(min-width: 500px)", true},
+ {"(min-width: 501px)", false},
+ {"(max-width: 500px)", true},
+ {"(max-width: 499px)", false},
+ {"(width: 500px)", true},
+ {"(width: 501px)", false},
+ {"(min-height: 500px)", true},
+ {"(min-height: 501px)", false},
+ {"(min-height: 500.02px)", false},
+ {"(max-height: 500px)", true},
+ {"(max-height: calc(500px))", true},
+ {"(max-height: 499.98px)", false},
+ {"(max-height: 499px)", false},
+ {"(height: 500px)", true},
+ {"(height: calc(500px))", true},
+ {"(height: 500.001px)", true},
+ {"(height: 499.999px)", true},
+ {"(height: 500.02px)", false},
+ {"(height: 499.98px)", false},
+ {"(height: 501px)", false},
+ {"(height)", true},
+ {"(width)", true},
+ {"(width: whatisthis)", false},
+ {"screen and (min-width: 400px) and (max-width: 700px)", true},
+ {"(max-aspect-ratio: 4294967296/1)", true},
+ {"(max-aspect-ratio: calc(4294967296) / calc(1)", true},
+ {"(min-aspect-ratio: 1/4294967295)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_float_viewport_test_cases[] = {
- {"all and (min-width: 600.5px)", 1},
- {"(min-width: 600px)", 1},
- {"(min-width: 600.5px)", 1},
- {"(min-width: 601px)", 0},
- {"(max-width: 600px)", 0},
- {"(max-width: 600.5px)", 1},
- {"(max-width: 601px)", 1},
- {"(width: 600.5px)", 1},
- {"(width: 601px)", 0},
- {"(min-height: 700px)", 1},
- {"(min-height: 700.125px)", 1},
- {"(min-height: 701px)", 0},
- {"(min-height: 700.141px)", 0},
- {"(max-height: 701px)", 1},
- {"(max-height: 700.125px)", 1},
- {"(max-height: 700px)", 0},
- {"(height: 700.125px)", 1},
- {"(height: 700.141px)", 0},
- {"(height: 700.109px)", 0},
- {"(height: 701px)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"all and (min-width: 600.5px)", true},
+ {"(min-width: 600px)", true},
+ {"(min-width: 600.5px)", true},
+ {"(min-width: 601px)", false},
+ {"(max-width: 600px)", false},
+ {"(max-width: 600.5px)", true},
+ {"(max-width: 601px)", true},
+ {"(width: 600.5px)", true},
+ {"(width: 601px)", false},
+ {"(min-height: 700px)", true},
+ {"(min-height: 700.125px)", true},
+ {"(min-height: 701px)", false},
+ {"(min-height: 700.141px)", false},
+ {"(max-height: 701px)", true},
+ {"(max-height: 700.125px)", true},
+ {"(max-height: 700px)", false},
+ {"(height: 700.125px)", true},
+ {"(height: 700.141px)", false},
+ {"(height: 700.109px)", false},
+ {"(height: 701px)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_float_non_friendly_viewport_test_cases[] = {
- {"(min-width: 821px)", 1},
- {"(max-width: 821px)", 1},
- {"(width: 821px)", 1},
- {"(min-height: 821px)", 1},
- {"(max-height: 821px)", 1},
- {"(height: 821px)", 1},
- {"(width: 100vw)", 1},
- {"(height: 100vh)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(min-width: 821px)", true},
+ {"(max-width: 821px)", true},
+ {"(width: 821px)", true},
+ {"(min-height: 821px)", true},
+ {"(max-height: 821px)", true},
+ {"(height: 821px)", true},
+ {"(width: 100vw)", true},
+ {"(height: 100vh)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_print_test_cases[] = {
- {"print and (min-resolution: 1dppx)", 1},
- {"print and (min-resolution: 118dpcm)", 1},
- {"print and (min-resolution: 119dpcm)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"print and (min-resolution: 1dppx)", true},
+ {"print and (min-resolution: 118dpcm)", true},
+ {"print and (min-resolution: 119dpcm)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_non_immersive_test_cases[] = {
- {"(immersive: 1)", 0},
- {"(immersive: 0)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(immersive: 1)", false},
+ {"(immersive: 0)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_immersive_test_cases[] = {
- {"(immersive: 1)", 1},
- {"(immersive: 0)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(immersive: 1)", true},
+ {"(immersive: 0)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_non_ua_sheet_immersive_test_cases[] = {
- {"(immersive: 1)", 0},
- {"(immersive: 0)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(immersive: 1)", false},
+ {"(immersive: 0)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_forcedcolors_active_cases[] = {
- {"(forced-colors: active)", 1},
- {"(forced-colors: none)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(forced-colors: active)", true},
+ {"(forced-colors: none)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_forcedcolors_none_cases[] = {
- {"(forced-colors: active)", 0},
- {"(forced-colors: none)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(forced-colors: active)", false},
+ {"(forced-colors: none)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_preferscontrast_nopreference_cases[] = {
- {"(prefers-contrast)", 0},
- {"(prefers-contrast: more)", 0},
- {"(prefers-contrast: less)", 0},
- {"(prefers-contrast: forced)", 0},
- {"(prefers-contrast: no-preference)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(prefers-contrast)", false},
+ {"(prefers-contrast: more)", false},
+ {"(prefers-contrast: less)", false},
+ {"(prefers-contrast: no-preference)", true},
+ {"(prefers-contrast: custom)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_preferscontrast_more_cases[] = {
- {"(prefers-contrast)", 1},
- {"(prefers-contrast: more)", 1},
- {"(prefers-contrast: less)", 0},
- {"(prefers-contrast: forced)", 0},
- {"(prefers-contrast: no-preference)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(prefers-contrast)", true},
+ {"(prefers-contrast: more)", true},
+ {"(prefers-contrast: less)", false},
+ {"(prefers-contrast: no-preference)", false},
+ {"(prefers-contrast: custom)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_preferscontrast_less_cases[] = {
- {"(prefers-contrast)", 1},
- {"(prefers-contrast: more)", 0},
- {"(prefers-contrast: less)", 1},
- {"(prefers-contrast: forced)", 0},
- {"(prefers-contrast: no-preference)", 0},
- {nullptr, 0} // Do not remove the terminator line.
-};
-
-MediaQueryEvaluatorTestCase g_preferscontrast_forced_cases[] = {
- {"(prefers-contrast)", 1},
- {"(prefers-contrast: more)", 0},
- {"(prefers-contrast: less)", 0},
- {"(prefers-contrast: forced)", 1},
- {"(prefers-contrast: no-preference)", 0},
- {nullptr, 0} // Do not remove the terminator line.
-};
-
-MediaQueryEvaluatorTestCase g_preferscontrast_forced_more_cases[] = {
- {"(prefers-contrast)", 1},
- {"(prefers-contrast: more)", 1},
- {"(prefers-contrast: less)", 0},
- {"(prefers-contrast: forced)", 1},
- {"(prefers-contrast: no-preference)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(prefers-contrast)", true},
+ {"(prefers-contrast: more)", false},
+ {"(prefers-contrast: less)", true},
+ {"(prefers-contrast: no-preference)", false},
+ {"(prefers-contrast: custom)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
-MediaQueryEvaluatorTestCase g_preferscontrast_forced_less_cases[] = {
- {"(prefers-contrast)", 1},
- {"(prefers-contrast: more)", 0},
- {"(prefers-contrast: less)", 1},
- {"(prefers-contrast: forced)", 1},
- {"(prefers-contrast: no-preference)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+MediaQueryEvaluatorTestCase g_preferscontrast_custom_cases[] = {
+ {"(prefers-contrast)", true},
+ {"(prefers-contrast: more)", false},
+ {"(prefers-contrast: less)", false},
+ {"(prefers-contrast: no-preference)", false},
+ {"(prefers-contrast: custom)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_navigationcontrols_back_button_cases[] = {
- {"(navigation-controls: back-button)", 1},
- {"(navigation-controls: none)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(navigation-controls: back-button)", true},
+ {"(navigation-controls: none)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_navigationcontrols_none_cases[] = {
- {"(navigation-controls: back-button)", 0},
- {"(navigation-controls: none)", 1},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(navigation-controls: back-button)", false},
+ {"(navigation-controls: none)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_screen_spanning_none_cases[] = {
- {"(screen-spanning)", 0},
- {"(screen-spanning: single-fold-vertical)", 0},
- {"(screen-spanning: single-fold-horizontal)", 0},
- {"(screen-spanning: none)", 1},
- {"(screen-spanning: 1px)", 0},
- {"(screen-spanning: 16/9)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(screen-spanning)", false},
+ {"(screen-spanning: single-fold-vertical)", false},
+ {"(screen-spanning: single-fold-horizontal)", false},
+ {"(screen-spanning: none)", true},
+ {"(screen-spanning: 1px)", false},
+ {"(screen-spanning: 16/9)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_vertical_cases[] = {
- {"(screen-spanning)", 1},
- {"(screen-spanning: single-fold-vertical)", 1},
- {"(screen-spanning: single-fold-horizontal)", 0},
- {"(screen-spanning: none)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(screen-spanning)", true},
+ {"(screen-spanning: single-fold-vertical)", true},
+ {"(screen-spanning: single-fold-horizontal)", false},
+ {"(screen-spanning: none)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_horizontal_cases[] = {
- {"(screen-spanning)", 1},
- {"(screen-spanning: single-fold-vertical)", 0},
- {"(screen-spanning: single-fold-horizontal)", 1},
- {"(screen-spanning: none)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(screen-spanning)", true},
+ {"(screen-spanning: single-fold-vertical)", false},
+ {"(screen-spanning: single-fold-horizontal)", true},
+ {"(screen-spanning: none)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
MediaQueryEvaluatorTestCase g_device_posture_none_cases[] = {
- {"(device-posture)", 1},
- {"(device-posture: laptop)", 0},
- {"(device-posture: flat)", 0},
- {"(device-posture: tent)", 0},
- {"(device-posture: tablet)", 0},
- {"(device-posture: book)", 0},
- {"(device-posture: no-fold)", 1},
- {"(device-posture: 15)", 0},
- {"(device-posture: 2px)", 0},
- {"(device-posture: 16/9)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+ {"(device-posture)", true},
+ {"(device-posture: continuous)", true},
+ {"(device-posture: folded)", false},
+ {"(device-posture: folded-over)", false},
+ {"(device-posture: 15)", false},
+ {"(device-posture: 2px)", false},
+ {"(device-posture: 16/9)", false},
+ {nullptr, false} // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_device_posture_folded_cases[] = {
+ {"(device-posture)", true},
+ {"(device-posture: continuous)", false},
+ {"(device-posture: folded)", true},
+ {"(device-posture: folded-over)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
-MediaQueryEvaluatorTestCase g_device_posture_laptop_cases[] = {
- {"(device-posture)", 1},
- {"(device-posture: laptop)", 1},
- {"(device-posture: flat)", 0},
- {"(device-posture: tent)", 0},
- {"(device-posture: tablet)", 0},
- {"(device-posture: book)", 0},
- {"(device-posture: no-fold)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+MediaQueryEvaluatorTestCase g_device_posture_folded_over_cases[] = {
+ {"(device-posture)", true},
+ {"(device-posture: continuous)", false},
+ {"(device-posture: folded)", false},
+ {"(device-posture: folded-over)", true},
+ {nullptr, false} // Do not remove the terminator line.
};
-MediaQueryEvaluatorTestCase g_device_posture_flat_cases[] = {
- {"(device-posture)", 1},
- {"(device-posture: laptop)", 0},
- {"(device-posture: flat)", 1},
- {"(device-posture: tent)", 0},
- {"(device-posture: tablet)", 0},
- {"(device-posture: book)", 0},
- {"(device-posture: no-fold)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+MediaQueryEvaluatorTestCase g_dynamic_range_standard_cases[] = {
+ {"(dynamic-range: standard)", true},
+ {"(dynamic-range: high)", false},
+ {"(dynamic-range: invalid)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
-MediaQueryEvaluatorTestCase g_device_posture_tent_cases[] = {
- {"(device-posture)", 1},
- {"(device-posture: laptop)", 0},
- {"(device-posture: flat)", 0},
- {"(device-posture: tent)", 1},
- {"(device-posture: tablet)", 0},
- {"(device-posture: book)", 0},
- {"(device-posture: no-fold)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+MediaQueryEvaluatorTestCase g_dynamic_range_high_cases[] = {
+ {"(dynamic-range: standard)", false},
+ {"(dynamic-range: high)", true},
+ {"(dynamic-range: invalid)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
-MediaQueryEvaluatorTestCase g_device_posture_tablet_cases[] = {
- {"(device-posture)", 1},
- {"(device-posture: laptop)", 0},
- {"(device-posture: flat)", 0},
- {"(device-posture: tent)", 0},
- {"(device-posture: tablet)", 1},
- {"(device-posture: book)", 0},
- {"(device-posture: no-fold)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+MediaQueryEvaluatorTestCase g_dynamic_range_feature_disabled_cases[] = {
+ {"(dynamic-range: standard)", false},
+ {"(dynamic-range: high)", false},
+ {"(dynamic-range: invalid)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
-MediaQueryEvaluatorTestCase g_device_posture_book_cases[] = {
- {"(device-posture)", 1},
- {"(device-posture: laptop)", 0},
- {"(device-posture: flat)", 0},
- {"(device-posture: tent)", 0},
- {"(device-posture: tablet)", 0},
- {"(device-posture: book)", 1},
- {"(device-posture: no-fold)", 0},
- {nullptr, 0} // Do not remove the terminator line.
+MediaQueryEvaluatorTestCase g_video_dynamic_range_standard_cases[] = {
+ {"(video-dynamic-range: standard)", true},
+ {"(video-dynamic-range: high)", false},
+ {"(video-dynamic-range: invalid)", false},
+ {nullptr, false} // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_video_dynamic_range_high_cases[] = {
+ {"(video-dynamic-range: standard)", false},
+ {"(video-dynamic-range: high)", true},
+ {"(video-dynamic-range: invalid)", false},
+ {nullptr, false} // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_video_dynamic_range_feature_disabled_cases[] = {
+ {"(video-dynamic-range: standard)", false},
+ {"(video-dynamic-range: high)", false},
+ {"(video-dynamic-range: invalid)", false},
+ {nullptr, false} // Do not remove the terminator line.
};
void TestMQEvaluator(MediaQueryEvaluatorTestCase* test_cases,
@@ -535,29 +517,12 @@ TEST(MediaQueryEvaluatorTest, CachedPrefersContrast) {
TestMQEvaluator(g_preferscontrast_less_cases, media_query_evaluator);
}
- // Prefers-contrast - forced.
- {
- data.preferred_contrast = mojom::blink::PreferredContrast::kNoPreference;
- data.forced_colors = ForcedColors::kActive;
- MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
- MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_preferscontrast_forced_cases, media_query_evaluator);
- }
-
- // Prefers-contrast - forced and more.
+ // Prefers-contrast - custom.
{
- data.preferred_contrast = mojom::blink::PreferredContrast::kMore;
+ data.preferred_contrast = mojom::blink::PreferredContrast::kCustom;
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_preferscontrast_forced_more_cases, media_query_evaluator);
- }
-
- // Prefers-contrast - forced and less.
- {
- data.preferred_contrast = mojom::blink::PreferredContrast::kLess;
- MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
- MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_preferscontrast_forced_less_cases, media_query_evaluator);
+ TestMQEvaluator(g_preferscontrast_custom_cases, media_query_evaluator);
}
}
@@ -595,46 +560,126 @@ TEST(MediaQueryEvaluatorTest, CachedDevicePosture) {
MediaValuesCached::MediaValuesCachedData data;
{
- data.device_posture = DevicePosture::kNoFold;
+ data.device_posture = device::mojom::blink::DevicePostureType::kContinuous;
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
-
MediaQueryEvaluator media_query_evaluator(*media_values);
TestMQEvaluator(g_device_posture_none_cases, media_query_evaluator);
}
{
- data.device_posture = DevicePosture::kLaptop;
+ data.device_posture = device::mojom::blink::DevicePostureType::kFolded;
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_device_posture_laptop_cases, media_query_evaluator);
+ TestMQEvaluator(g_device_posture_folded_cases, media_query_evaluator);
}
{
- data.device_posture = DevicePosture::kFlat;
+ data.device_posture = device::mojom::blink::DevicePostureType::kFoldedOver;
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_device_posture_flat_cases, media_query_evaluator);
+ TestMQEvaluator(g_device_posture_folded_over_cases, media_query_evaluator);
}
+}
+TEST(MediaQueryEvaluatorTest, CachedDynamicRange) {
+ MediaValuesCached::MediaValuesCachedData data;
+
+ // Test with color spaces supporting standard dynamic range
{
- data.device_posture = DevicePosture::kTent;
+ data.device_supports_hdr = gfx::DisplayColorSpaces().SupportsHDR();
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_device_posture_tent_cases, media_query_evaluator);
+ TestMQEvaluator(g_dynamic_range_standard_cases, media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_standard_cases,
+ media_query_evaluator);
+
+ // Test again with the feature disabled
+ ScopedCSSDynamicRangeMediaQueriesForTest const disable_feature{false};
+ TestMQEvaluator(g_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
}
+ {
+ data.device_supports_hdr =
+ gfx::DisplayColorSpaces(gfx::ColorSpace::CreateDisplayP3D65())
+ .SupportsHDR();
+ MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+ MediaQueryEvaluator media_query_evaluator(*media_values);
+ TestMQEvaluator(g_dynamic_range_standard_cases, media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_standard_cases,
+ media_query_evaluator);
+ // Test again with the feature disabled
+ ScopedCSSDynamicRangeMediaQueriesForTest const disable_feature{false};
+ TestMQEvaluator(g_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ }
+
+ // Test with color spaces supporting high dynamic range
{
- data.device_posture = DevicePosture::kTablet;
+ data.device_supports_hdr =
+ gfx::DisplayColorSpaces(gfx::ColorSpace::CreateExtendedSRGB())
+ .SupportsHDR();
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_device_posture_tablet_cases, media_query_evaluator);
+ TestMQEvaluator(g_dynamic_range_high_cases, media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_high_cases, media_query_evaluator);
+
+ // Test again with the feature disabled
+ ScopedCSSDynamicRangeMediaQueriesForTest const disable_feature{false};
+ TestMQEvaluator(g_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
}
+ {
+ data.device_supports_hdr =
+ gfx::DisplayColorSpaces(gfx::ColorSpace::CreateSCRGBLinear())
+ .SupportsHDR();
+ MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+ MediaQueryEvaluator media_query_evaluator(*media_values);
+ TestMQEvaluator(g_dynamic_range_high_cases, media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_high_cases, media_query_evaluator);
+
+ // Test again with the feature disabled
+ ScopedCSSDynamicRangeMediaQueriesForTest const disable_feature{false};
+ TestMQEvaluator(g_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ }
+ {
+ data.device_supports_hdr =
+ gfx::DisplayColorSpaces(gfx::ColorSpace::CreateHDR10()).SupportsHDR();
+ MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+ MediaQueryEvaluator media_query_evaluator(*media_values);
+ TestMQEvaluator(g_dynamic_range_high_cases, media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_high_cases, media_query_evaluator);
+ // Test again with the feature disabled
+ ScopedCSSDynamicRangeMediaQueriesForTest const disable_feature{false};
+ TestMQEvaluator(g_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ }
{
- data.device_posture = DevicePosture::kBook;
+ data.device_supports_hdr =
+ gfx::DisplayColorSpaces(gfx::ColorSpace::CreateHLG()).SupportsHDR();
MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
MediaQueryEvaluator media_query_evaluator(*media_values);
- TestMQEvaluator(g_device_posture_book_cases, media_query_evaluator);
+ TestMQEvaluator(g_dynamic_range_high_cases, media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_high_cases, media_query_evaluator);
+
+ // Test again with the feature disabled
+ ScopedCSSDynamicRangeMediaQueriesForTest const disable_feature{false};
+ TestMQEvaluator(g_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
+ TestMQEvaluator(g_video_dynamic_range_feature_disabled_cases,
+ media_query_evaluator);
}
}
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 39e4f220d83..0f47524eac9 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
@@ -82,13 +82,19 @@ static inline bool FeatureWithValidIdent(const String& media_feature,
if (RuntimeEnabledFeatures::PrefersContrastEnabled()) {
if (media_feature == media_feature_names::kPrefersContrastMediaFeature) {
return ident == CSSValueID::kNoPreference || ident == CSSValueID::kMore ||
- ident == CSSValueID::kLess || ident == CSSValueID::kForced;
+ ident == CSSValueID::kLess || ident == CSSValueID::kCustom;
}
}
if (media_feature == media_feature_names::kPrefersReducedMotionMediaFeature)
return ident == CSSValueID::kNoPreference || ident == CSSValueID::kReduce;
+ if (RuntimeEnabledFeatures::CSSDynamicRangeMediaQueriesEnabled()) {
+ if (media_feature == media_feature_names::kDynamicRangeMediaFeature ||
+ media_feature == media_feature_names::kVideoDynamicRangeMediaFeature)
+ return ident == CSSValueID::kStandard || ident == CSSValueID::kHigh;
+ }
+
if (RuntimeEnabledFeatures::PrefersReducedDataEnabled() &&
media_feature == media_feature_names::kPrefersReducedDataMediaFeature) {
return ident == CSSValueID::kNoPreference || ident == CSSValueID::kReduce;
@@ -116,9 +122,8 @@ static inline bool FeatureWithValidIdent(const String& media_feature,
if (RuntimeEnabledFeatures::DevicePostureEnabled()) {
if (media_feature == media_feature_names::kDevicePostureMediaFeature) {
- return ident == CSSValueID::kNoFold || ident == CSSValueID::kLaptop ||
- ident == CSSValueID::kFlat || ident == CSSValueID::kTent ||
- ident == CSSValueID::kTablet || ident == CSSValueID::kBook;
+ return ident == CSSValueID::kContinuous || ident == CSSValueID::kFolded ||
+ ident == CSSValueID::kFoldedOver;
}
}
@@ -283,7 +288,9 @@ bool MediaQueryExp::IsDeviceDependent() const {
media_feature_ == media_feature_names::kMinDeviceHeightMediaFeature ||
media_feature_ == kMaxDeviceAspectRatioMediaFeature ||
media_feature_ == media_feature_names::kMaxDeviceWidthMediaFeature ||
- media_feature_ == media_feature_names::kMaxDeviceHeightMediaFeature;
+ media_feature_ == media_feature_names::kMaxDeviceHeightMediaFeature ||
+ media_feature_ == media_feature_names::kDynamicRangeMediaFeature ||
+ media_feature_ == media_feature_names::kVideoDynamicRangeMediaFeature;
}
bool MediaQueryExp::IsWidthDependent() const {
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_matcher.cc b/chromium/third_party/blink/renderer/core/css/media_query_matcher.cc
index fc2965fa987..7379575fdef 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_matcher.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_matcher.cc
@@ -106,9 +106,12 @@ void MediaQueryMatcher::MediaFeaturesChanged() {
if (!document_)
return;
- // Make sure the favicon is updated when media features have changed.
- if (document_->GetFrame())
+ // Update favicon and theme color when a media query value has changed.
+ if (document_->GetFrame()) {
document_->GetFrame()->UpdateFaviconURL();
+ document_->GetFrame()->DidChangeThemeColor(
+ /*update_theme_color_cache=*/false);
+ }
HeapVector<Member<MediaQueryListListener>> listeners_to_notify;
for (const auto& list : media_lists_) {
diff --git a/chromium/third_party/blink/renderer/core/css/media_values.cc b/chromium/third_party/blink/renderer/core/css/media_values.cc
index 2ef2ed42f7f..4117ba30c38 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/css/media_values.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
@@ -12,22 +11,36 @@
#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
#include "third_party/blink/renderer/core/css/media_values_dynamic.h"
+#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/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/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/layout/layout_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/platform/graphics/color_space_gamut.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/widget/frame_widget.h"
+#include "ui/display/screen_info.h"
namespace blink {
+namespace {
+static ForcedColors CSSValueIDToForcedColors(CSSValueID id) {
+ switch (id) {
+ case CSSValueID::kActive:
+ return ForcedColors::kActive;
+ case CSSValueID::kNone:
+ return ForcedColors::kNone;
+ default:
+ NOTREACHED();
+ return ForcedColors::kNone;
+ }
+}
+} // namespace
+
mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme(
CSSValueID id) {
switch (id) {
@@ -41,6 +54,22 @@ mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme(
}
}
+mojom::blink::PreferredContrast CSSValueIDToPreferredContrast(CSSValueID id) {
+ switch (id) {
+ case CSSValueID::kMore:
+ return mojom::blink::PreferredContrast::kMore;
+ case CSSValueID::kLess:
+ return mojom::blink::PreferredContrast::kLess;
+ case CSSValueID::kNoPreference:
+ return mojom::blink::PreferredContrast::kNoPreference;
+ case CSSValueID::kCustom:
+ return mojom::blink::PreferredContrast::kCustom;
+ default:
+ NOTREACHED();
+ return mojom::blink::PreferredContrast::kNoPreference;
+ }
+}
+
MediaValues* MediaValues::CreateDynamicIfFrameExists(LocalFrame* frame) {
if (frame)
return MediaValuesDynamic::Create(frame);
@@ -63,7 +92,7 @@ double MediaValues::CalculateViewportHeight(LocalFrame* frame) {
int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
- const ScreenInfo& screen_info =
+ const display::ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
int device_width = screen_info.rect.width();
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
@@ -75,7 +104,7 @@ int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
int MediaValues::CalculateDeviceHeight(LocalFrame* frame) {
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
- const ScreenInfo& screen_info =
+ const display::ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
int device_height = screen_info.rect.height();
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
@@ -95,10 +124,19 @@ float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) {
return frame->DevicePixelRatio();
}
+bool MediaValues::CalculateDeviceSupportsHDR(LocalFrame* frame) {
+ DCHECK(frame);
+ DCHECK(frame->GetPage());
+ return frame->GetPage()
+ ->GetChromeClient()
+ .GetScreenInfo(*frame)
+ .display_color_spaces.SupportsHDR();
+}
+
int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
- const ScreenInfo& screen_info =
+ const display::ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
if (screen_info.is_monochrome)
return 0;
@@ -108,7 +146,7 @@ int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) {
int MediaValues::CalculateMonochromeBitsPerComponent(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
- const ScreenInfo& screen_info =
+ const display::ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
if (!screen_info.is_monochrome)
return 0;
@@ -215,6 +253,12 @@ mojom::blink::PreferredContrast MediaValues::CalculatePreferredContrast(
LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
+ DCHECK(frame->GetPage());
+ if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
+ MediaQueryExpValue value = overrides->GetOverride("prefers-contrast");
+ if (value.IsValid())
+ return CSSValueIDToPreferredContrast(value.id);
+ }
return frame->GetSettings()->GetPreferredContrast();
}
@@ -241,7 +285,14 @@ bool MediaValues::CalculatePrefersReducedData(LocalFrame* frame) {
!frame->GetSettings()->GetDataSaverHoldbackWebApi());
}
-ForcedColors MediaValues::CalculateForcedColors() {
+ForcedColors MediaValues::CalculateForcedColors(LocalFrame* frame) {
+ DCHECK(frame);
+ DCHECK(frame->GetSettings());
+ if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
+ MediaQueryExpValue value = overrides->GetOverride("forced-colors");
+ if (value.IsValid())
+ return CSSValueIDToForcedColors(value.id);
+ }
if (Platform::Current() && Platform::Current()->ThemeEngine())
return Platform::Current()->ThemeEngine()->GetForcedColors();
else
@@ -277,9 +328,9 @@ ScreenSpanning MediaValues::CalculateScreenSpanning(LocalFrame* frame) {
return ScreenSpanning::kNone;
}
-DevicePosture MediaValues::CalculateDevicePosture(LocalFrame* frame) {
- // TODO(darktears): Retrieve information from the host.
- return DevicePosture::kNoFold;
+device::mojom::blink::DevicePostureType MediaValues::CalculateDevicePosture(
+ LocalFrame* frame) {
+ return frame->GetDevicePosture();
}
bool MediaValues::ComputeLengthImpl(double value,
diff --git a/chromium/third_party/blink/renderer/core/css/media_values.h b/chromium/third_party/blink/renderer/core/css/media_values.h
index 604147c6fed..95b2484e4a8 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_VALUES_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_VALUES_H_
+#include "services/device/public/mojom/device_posture_provider.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/css/preferred_contrast.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
@@ -24,7 +25,6 @@ enum class ColorSpaceGamut;
enum class ForcedColors;
enum class NavigationControls;
enum class ScreenSpanning { kNone, kSingleFoldHorizontal, kSingleFoldVertical };
-enum class DevicePosture { kNoFold, kLaptop, kFlat, kTent, kTablet, kBook };
mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme(
CSSValueID id);
@@ -69,6 +69,7 @@ class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
virtual int DeviceWidth() const = 0;
virtual int DeviceHeight() const = 0;
virtual float DevicePixelRatio() const = 0;
+ virtual bool DeviceSupportsHDR() const = 0;
virtual int ColorBitsPerComponent() const = 0;
virtual int MonochromeBitsPerComponent() const = 0;
virtual mojom::blink::PointerType PrimaryPointerType() const = 0;
@@ -93,7 +94,7 @@ class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
virtual ForcedColors GetForcedColors() const = 0;
virtual NavigationControls GetNavigationControls() const = 0;
virtual ScreenSpanning GetScreenSpanning() const = 0;
- virtual DevicePosture GetDevicePosture() const = 0;
+ virtual device::mojom::blink::DevicePostureType GetDevicePosture() const = 0;
protected:
static double CalculateViewportWidth(LocalFrame*);
@@ -102,6 +103,7 @@ class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
static int CalculateDeviceHeight(LocalFrame*);
static bool CalculateStrictMode(LocalFrame*);
static float CalculateDevicePixelRatio(LocalFrame*);
+ static bool CalculateDeviceSupportsHDR(LocalFrame*);
static int CalculateColorBitsPerComponent(LocalFrame*);
static int CalculateMonochromeBitsPerComponent(LocalFrame*);
static int CalculateDefaultFontSize(LocalFrame*);
@@ -120,10 +122,11 @@ class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
LocalFrame*);
static bool CalculatePrefersReducedMotion(LocalFrame*);
static bool CalculatePrefersReducedData(LocalFrame*);
- static ForcedColors CalculateForcedColors();
+ static ForcedColors CalculateForcedColors(LocalFrame*);
static NavigationControls CalculateNavigationControls(LocalFrame*);
static ScreenSpanning CalculateScreenSpanning(LocalFrame*);
- static DevicePosture CalculateDevicePosture(LocalFrame*);
+ static device::mojom::blink::DevicePostureType CalculateDevicePosture(
+ LocalFrame*);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_cached.cc b/chromium/third_party/blink/renderer/core/css/media_values_cached.cc
index f95a9887d45..935072d1d79 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_cached.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values_cached.cc
@@ -4,44 +4,12 @@
#include "third_party/blink/renderer/core/css/media_values_cached.h"
-#include "third_party/blink/public/common/css/forced_colors.h"
-#include "third_party/blink/public/common/css/navigation_controls.h"
-#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-blink.h"
-#include "third_party/blink/public/mojom/css/preferred_contrast.mojom-blink.h"
-#include "third_party/blink/renderer/core/css/css_primitive_value.h"
-#include "third_party/blink/renderer/core/css/media_values.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/layout/layout_object.h"
-#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
namespace blink {
-MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData()
- : viewport_width(0),
- viewport_height(0),
- device_width(0),
- device_height(0),
- device_pixel_ratio(1.0),
- color_bits_per_component(24),
- monochrome_bits_per_component(0),
- primary_pointer_type(mojom::blink::PointerType::kPointerNone),
- available_pointer_types(ui::POINTER_TYPE_NONE),
- primary_hover_type(mojom::blink::HoverType::kHoverNone),
- available_hover_types(ui::HOVER_TYPE_NONE),
- default_font_size(16),
- three_d_enabled(false),
- immersive_mode(false),
- strict_mode(true),
- display_mode(blink::mojom::DisplayMode::kBrowser),
- color_gamut(ColorSpaceGamut::kUnknown),
- preferred_color_scheme(mojom::blink::PreferredColorScheme::kLight),
- preferred_contrast(mojom::blink::PreferredContrast::kNoPreference),
- prefers_reduced_motion(false),
- forced_colors(ForcedColors::kNone),
- navigation_controls(NavigationControls::kNone),
- screen_spanning(ScreenSpanning::kNone),
- device_posture(DevicePosture::kNoFold) {}
+MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData() = default;
MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
Document& document)
@@ -63,6 +31,7 @@ MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
device_width = MediaValues::CalculateDeviceWidth(frame);
device_height = MediaValues::CalculateDeviceHeight(frame);
device_pixel_ratio = MediaValues::CalculateDevicePixelRatio(frame);
+ device_supports_hdr = MediaValues::CalculateDeviceSupportsHDR(frame);
color_bits_per_component =
MediaValues::CalculateColorBitsPerComponent(frame);
monochrome_bits_per_component =
@@ -83,7 +52,7 @@ MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
preferred_contrast = MediaValues::CalculatePreferredContrast(frame);
prefers_reduced_motion = MediaValues::CalculatePrefersReducedMotion(frame);
prefers_reduced_data = MediaValues::CalculatePrefersReducedData(frame);
- forced_colors = MediaValues::CalculateForcedColors();
+ forced_colors = MediaValues::CalculateForcedColors(frame);
navigation_controls = MediaValues::CalculateNavigationControls(frame);
screen_spanning = MediaValues::CalculateScreenSpanning(frame);
device_posture = MediaValues::CalculateDevicePosture(frame);
@@ -135,6 +104,10 @@ float MediaValuesCached::DevicePixelRatio() const {
return data_.device_pixel_ratio;
}
+bool MediaValuesCached::DeviceSupportsHDR() const {
+ return data_.device_supports_hdr;
+}
+
int MediaValuesCached::ColorBitsPerComponent() const {
return data_.color_bits_per_component;
}
@@ -227,7 +200,8 @@ ScreenSpanning MediaValuesCached::GetScreenSpanning() const {
return data_.screen_spanning;
}
-DevicePosture MediaValuesCached::GetDevicePosture() const {
+device::mojom::blink::DevicePostureType MediaValuesCached::GetDevicePosture()
+ const {
return data_.device_posture;
}
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_cached.h b/chromium/third_party/blink/renderer/core/css/media_values_cached.h
index c38b20d4343..d9ec747c877 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_cached.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values_cached.h
@@ -5,9 +5,19 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_VALUES_CACHED_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_VALUES_CACHED_H_
+#include "services/device/public/mojom/device_posture_provider.mojom-blink.h"
+#include "third_party/blink/public/common/css/forced_colors.h"
+#include "third_party/blink/public/common/css/navigation_controls.h"
+#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-blink.h"
+#include "third_party/blink/public/mojom/css/preferred_contrast.mojom-blink.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/media_values.h"
+#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
+#include "ui/base/pointer/pointer_device.h"
namespace blink {
@@ -17,32 +27,41 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
DISALLOW_NEW();
// Members variables must be thread safe, since they're copied to the parser
// thread
- double viewport_width;
- double viewport_height;
- int device_width;
- int device_height;
- float device_pixel_ratio;
- int color_bits_per_component;
- int monochrome_bits_per_component;
- mojom::blink::PointerType primary_pointer_type;
- int available_pointer_types;
- mojom::blink::HoverType primary_hover_type;
- int available_hover_types;
- int default_font_size;
- bool three_d_enabled;
- bool immersive_mode;
- bool strict_mode;
+ double viewport_width = 0;
+ double viewport_height = 0;
+ int device_width = 0;
+ int device_height = 0;
+ float device_pixel_ratio = 1.0;
+ bool device_supports_hdr = false;
+ int color_bits_per_component = 24;
+ int monochrome_bits_per_component = 0;
+ mojom::blink::PointerType primary_pointer_type =
+ mojom::blink::PointerType::kPointerNone;
+ // Bitmask of |ui::PointerType|
+ int available_pointer_types = ui::POINTER_TYPE_NONE;
+ mojom::blink::HoverType primary_hover_type =
+ mojom::blink::HoverType::kHoverNone;
+ // Bitmask of |ui::HoverType|
+ int available_hover_types = ui::HOVER_TYPE_NONE;
+ int default_font_size = 16;
+ bool three_d_enabled = false;
+ bool immersive_mode = false;
+ bool strict_mode = true;
String media_type;
- blink::mojom::DisplayMode display_mode;
- ColorSpaceGamut color_gamut;
- mojom::blink::PreferredColorScheme preferred_color_scheme;
- mojom::blink::PreferredContrast preferred_contrast;
- bool prefers_reduced_motion;
+ mojom::blink::DisplayMode display_mode =
+ mojom::blink::DisplayMode::kBrowser;
+ ColorSpaceGamut color_gamut = ColorSpaceGamut::kUnknown;
+ mojom::blink::PreferredColorScheme preferred_color_scheme =
+ mojom::blink::PreferredColorScheme::kLight;
+ mojom::blink::PreferredContrast preferred_contrast =
+ mojom::blink::PreferredContrast::kNoPreference;
+ bool prefers_reduced_motion = false;
bool prefers_reduced_data = false;
- ForcedColors forced_colors;
- NavigationControls navigation_controls;
- ScreenSpanning screen_spanning;
- DevicePosture device_posture;
+ ForcedColors forced_colors = ForcedColors::kNone;
+ NavigationControls navigation_controls = NavigationControls::kNone;
+ ScreenSpanning screen_spanning = ScreenSpanning::kNone;
+ device::mojom::blink::DevicePostureType device_posture =
+ device::mojom::blink::DevicePostureType::kContinuous;
MediaValuesCachedData();
explicit MediaValuesCachedData(Document&);
@@ -54,6 +73,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
data.device_width = device_width;
data.device_height = device_height;
data.device_pixel_ratio = device_pixel_ratio;
+ data.device_supports_hdr = device_supports_hdr;
data.color_bits_per_component = color_bits_per_component;
data.monochrome_bits_per_component = monochrome_bits_per_component;
data.primary_pointer_type = primary_pointer_type;
@@ -80,8 +100,8 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
};
MediaValuesCached();
- MediaValuesCached(LocalFrame*);
- MediaValuesCached(const MediaValuesCachedData&);
+ explicit MediaValuesCached(LocalFrame*);
+ explicit MediaValuesCached(const MediaValuesCachedData&);
MediaValues* Copy() const override;
bool ComputeLength(double value,
@@ -96,6 +116,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
int DeviceWidth() const override;
int DeviceHeight() const override;
float DevicePixelRatio() const override;
+ bool DeviceSupportsHDR() const override;
int ColorBitsPerComponent() const override;
int MonochromeBitsPerComponent() const override;
mojom::blink::PointerType PrimaryPointerType() const override;
@@ -117,7 +138,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
ForcedColors GetForcedColors() const override;
NavigationControls GetNavigationControls() const override;
ScreenSpanning GetScreenSpanning() const override;
- DevicePosture GetDevicePosture() const override;
+ device::mojom::blink::DevicePostureType GetDevicePosture() const override;
void OverrideViewportDimensions(double width, double height) override;
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc
index 312bf87c06e..99b20c73df8 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc
@@ -91,6 +91,10 @@ float MediaValuesDynamic::DevicePixelRatio() const {
return CalculateDevicePixelRatio(frame_);
}
+bool MediaValuesDynamic::DeviceSupportsHDR() const {
+ return CalculateDeviceSupportsHDR(frame_);
+}
+
int MediaValuesDynamic::ColorBitsPerComponent() const {
return CalculateColorBitsPerComponent(frame_);
}
@@ -158,7 +162,7 @@ bool MediaValuesDynamic::PrefersReducedData() const {
}
ForcedColors MediaValuesDynamic::GetForcedColors() const {
- return CalculateForcedColors();
+ return CalculateForcedColors(frame_);
}
NavigationControls MediaValuesDynamic::GetNavigationControls() const {
@@ -169,7 +173,8 @@ ScreenSpanning MediaValuesDynamic::GetScreenSpanning() const {
return CalculateScreenSpanning(frame_);
}
-DevicePosture MediaValuesDynamic::GetDevicePosture() const {
+device::mojom::blink::DevicePostureType MediaValuesDynamic::GetDevicePosture()
+ const {
return CalculateDevicePosture(frame_);
}
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h
index 07ea92e1e00..3f6a4da6197 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h
@@ -16,7 +16,7 @@ class CORE_EXPORT MediaValuesDynamic : public MediaValues {
static MediaValues* Create(Document&);
static MediaValues* Create(LocalFrame*);
- MediaValuesDynamic(LocalFrame*);
+ explicit MediaValuesDynamic(LocalFrame*);
MediaValuesDynamic(LocalFrame*,
bool overridden_viewport_dimensions,
double viewport_width,
@@ -35,6 +35,7 @@ class CORE_EXPORT MediaValuesDynamic : public MediaValues {
int DeviceWidth() const override;
int DeviceHeight() const override;
float DevicePixelRatio() const override;
+ bool DeviceSupportsHDR() const override;
int ColorBitsPerComponent() const override;
int MonochromeBitsPerComponent() const override;
mojom::blink::PointerType PrimaryPointerType() const override;
@@ -54,7 +55,7 @@ class CORE_EXPORT MediaValuesDynamic : public MediaValues {
ForcedColors GetForcedColors() const override;
NavigationControls GetNavigationControls() const override;
ScreenSpanning GetScreenSpanning() const override;
- DevicePosture GetDevicePosture() const override;
+ device::mojom::blink::DevicePostureType GetDevicePosture() const override;
Document* GetDocument() const override;
bool HasValues() const override;
void OverrideViewportDimensions(double width, double height) override;
diff --git a/chromium/third_party/blink/renderer/core/css/parser/at_rule_counter_style_descriptor_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/at_rule_counter_style_descriptor_parser.cc
index 00028f6e730..f0fc37c995b 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/at_rule_counter_style_descriptor_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/at_rule_counter_style_descriptor_parser.cc
@@ -221,10 +221,11 @@ CSSValue* ConsumeCounterStyleAdditiveSymbols(CSSParserTokenRange& range,
CSSValue* ConsumeCounterStyleSpeakAs(CSSParserTokenRange& range,
const CSSParserContext& context) {
- // Syntax: auto | bullets | numbers | words | spell-out | <counter-style-name>
+ // Syntax: auto | bullets | numbers | words | <counter-style-name>
+ // We don't support spell-out now.
if (CSSValue* ident = css_parsing_utils::ConsumeIdent<
CSSValueID::kAuto, CSSValueID::kBullets, CSSValueID::kNumbers,
- CSSValueID::kWords, CSSValueID::kSpellOut>(range))
+ CSSValueID::kWords>(range))
return ident;
if (CSSValue* name =
css_parsing_utils::ConsumeCounterStyleName(range, context))
@@ -238,8 +239,6 @@ CSSValue* AtRuleDescriptorParser::ParseAtCounterStyleDescriptor(
AtRuleDescriptorID id,
CSSParserTokenRange& range,
const CSSParserContext& context) {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
-
CSSValue* parsed_value = nullptr;
switch (id) {
case AtRuleDescriptorID::System:
diff --git a/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
index 132e56983b0..2ea3ace21a2 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
@@ -187,6 +187,8 @@ CSSValue* ConsumeDescriptor(StyleRule::RuleType rule_type,
case StyleRule::kPage:
case StyleRule::kKeyframes:
case StyleRule::kKeyframe:
+ case StyleRule::kLayerBlock:
+ case StyleRule::kLayerStatement:
case StyleRule::kNamespace:
case StyleRule::kSupports:
case StyleRule::kViewport:
@@ -198,8 +200,6 @@ CSSValue* ConsumeDescriptor(StyleRule::RuleType rule_type,
CSSValue* ConsumeFontMetricOverride(CSSParserTokenRange& range,
const CSSParserContext& context) {
- if (!RuntimeEnabledFeatures::CSSFontMetricsOverrideEnabled())
- return nullptr;
if (CSSIdentifierValue* normal =
css_parsing_utils::ConsumeIdent<CSSValueID::kNormal>(range)) {
return normal;
@@ -208,27 +208,6 @@ CSSValue* ConsumeFontMetricOverride(CSSParserTokenRange& range,
kValueRangeNonNegative);
}
-CSSValue* ConsumeAdvanceOverride(CSSParserTokenRange& range,
- const CSSParserContext& context) {
- if (!RuntimeEnabledFeatures::CSSFontFaceAdvanceOverrideEnabled())
- return nullptr;
- if (CSSIdentifierValue* normal =
- css_parsing_utils::ConsumeIdent<CSSValueID::kNormal>(range)) {
- return normal;
- }
- CSSValue* override_horizontal =
- css_parsing_utils::ConsumePercent(range, context, kValueRangeNonNegative);
- if (!override_horizontal)
- return nullptr;
- CSSValue* override_vertical_upright =
- css_parsing_utils::ConsumePercent(range, context, kValueRangeNonNegative);
- if (!override_vertical_upright)
- override_vertical_upright = override_horizontal;
- return MakeGarbageCollected<CSSValuePair>(override_horizontal,
- override_vertical_upright,
- CSSValuePair::kDropIdenticalValues);
-}
-
} // namespace
CSSValue* AtRuleDescriptorParser::ParseFontFaceDescriptor(
@@ -283,9 +262,6 @@ CSSValue* AtRuleDescriptorParser::ParseFontFaceDescriptor(
case AtRuleDescriptorID::LineGapOverride:
parsed_value = ConsumeFontMetricOverride(range, context);
break;
- case AtRuleDescriptorID::AdvanceOverride:
- parsed_value = ConsumeAdvanceOverride(range, context);
- break;
case AtRuleDescriptorID::SizeAdjust:
if (RuntimeEnabledFeatures::CSSFontFaceSizeAdjustEnabled()) {
parsed_value = css_parsing_utils::ConsumePercent(
@@ -339,8 +315,7 @@ CSSValue* AtRuleDescriptorParser::ParseAtPropertyDescriptor(
case AtRuleDescriptorID::InitialValue: {
// Note that we must retain leading whitespace here.
return CSSVariableParser::ParseDeclarationValue(
- g_null_atom, tokenized_value, false /* is_animation_tainted */,
- context);
+ tokenized_value, false /* is_animation_tainted */, context);
}
case AtRuleDescriptorID::Inherits:
range.ConsumeWhitespace();
@@ -405,6 +380,7 @@ bool AtRuleDescriptorParser::ParseAtRule(
CSSPropertyID equivalent_property_id = AtRuleDescriptorIDAsCSSPropertyID(id);
parsed_descriptors.push_back(
CSSPropertyValue(CSSPropertyName(equivalent_property_id), *result));
+ context.Count(context.Mode(), equivalent_property_id);
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser_test.cc
new file mode 100644
index 00000000000..fa096c862f0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser_test.cc
@@ -0,0 +1,96 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+class AtRuleDescriptorParserTest : public PageTestBase {};
+
+TEST_F(AtRuleDescriptorParserTest, NoUseCountUACounterStyle) {
+ SetBodyInnerHTML(R"HTML(
+ <ol>
+ <!-- Basic counter styles -->
+ <li style="list-style-type: decimal">decimal</li>
+ <li style="list-style-type: disc">disc</li>
+ <!-- Counter style with additive-symbols -->
+ <li style="list-style-type: upper-roman">upper-roman</li>
+ <!-- Counter style with fallback ->
+ <li style="list-style-type: simp-chinese-informal">chinese</li>
+ </ol>
+ )HTML");
+
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(mojom::WebFeature::kCSSAtRuleCounterStyle));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kSystem));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kSymbols));
+ EXPECT_FALSE(
+ GetDocument().IsPropertyCounted(CSSPropertyID::kAdditiveSymbols));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kPrefix));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kSuffix));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kNegative));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kRange));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kPad));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kFallback));
+ EXPECT_FALSE(GetDocument().IsPropertyCounted(CSSPropertyID::kSpeakAs));
+}
+
+TEST_F(AtRuleDescriptorParserTest, UseCountCounterStyleDescriptors) {
+ InsertStyleElement(R"CSS(
+ @counter-style foo {
+ system: symbolic;
+ symbols: 'X' 'Y' 'Z';
+ prefix: '<';
+ suffix: '>';
+ negative: '~';
+ range: 0 infinite;
+ pad: 3 'O';
+ fallback: upper-alpha;
+ speak-as: numbers;
+ }
+ )CSS");
+
+ InsertStyleElement(R"CSS(
+ @counter-style bar {
+ system: additive;
+ additive-symbols: 1 'I', 0 'O';
+ }
+ )CSS");
+
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(mojom::WebFeature::kCSSAtRuleCounterStyle));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kSystem));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kSymbols));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kAdditiveSymbols));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kPrefix));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kSuffix));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kNegative));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kRange));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kPad));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kFallback));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kSpeakAs));
+}
+
+TEST_F(AtRuleDescriptorParserTest, UseCountFontMetricOverrideDescriptors) {
+ InsertStyleElement(R"CSS(
+ @font-face {
+ font-family: foo;
+ src: url(foo.woff);
+ ascent-override: 80%;
+ descent-override: 20%;
+ line-gap-override: 0%;
+ size-adjust: 110%;
+ }
+ )CSS");
+
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kAscentOverride));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kDescentOverride));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kLineGapOverride));
+ EXPECT_TRUE(GetDocument().IsPropertyCounted(CSSPropertyID::kSizeAdjust));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/parser/at_rule_names.json5 b/chromium/third_party/blink/renderer/core/css/parser/at_rule_names.json5
index 531f6d10c03..0dca5e4c7fc 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/at_rule_names.json5
+++ b/chromium/third_party/blink/renderer/core/css/parser/at_rule_names.json5
@@ -58,9 +58,6 @@
name: "initial-value"
},
{
- name: "advance-override"
- },
- {
name: "fallback",
},
{
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css.proto b/chromium/third_party/blink/renderer/core/css/parser/css.proto
index aaf078faa44..3f86011ac37 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css.proto
+++ b/chromium/third_party/blink/renderer/core/css/parser/css.proto
@@ -811,7 +811,9 @@ message MfName {
SCAN = 43;
SHAPE = 44;
IMMERSIVE = 45;
- INVALID_NAME = 46;
+ DYNAMIC_RANGE = 46;
+ VIDEO_DYNAMIC_RANGE = 47;
+ INVALID_NAME = 48;
}
required ValueId id = 1;
}
@@ -2385,7 +2387,9 @@ message PropertyAndValue {
NO_DRAG = 759;
JIS_B5 = 760;
JIS_B4 = 761;
- INVALID_VALUE = 762;
+ STANDARD = 762;
+ HIGH = 763;
+ INVALID_VALUE = 764;
};
optional ValueId value_id = 4;
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc b/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc
index 050c681591d..3af857ed071 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc
@@ -19,6 +19,11 @@ CSSAtRuleID CssAtRuleID(StringView name) {
return kCSSAtRuleImport;
if (EqualIgnoringASCIICase(name, "keyframes"))
return kCSSAtRuleKeyframes;
+ if (EqualIgnoringASCIICase(name, "layer")) {
+ if (RuntimeEnabledFeatures::CSSCascadeLayersEnabled())
+ return kCSSAtRuleLayer;
+ return kCSSAtRuleInvalid;
+ }
if (EqualIgnoringASCIICase(name, "media"))
return kCSSAtRuleMedia;
if (EqualIgnoringASCIICase(name, "namespace"))
@@ -32,11 +37,8 @@ CSSAtRuleID CssAtRuleID(StringView name) {
return kCSSAtRuleContainer;
return kCSSAtRuleInvalid;
}
- if (EqualIgnoringASCIICase(name, "counter-style")) {
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled())
- return kCSSAtRuleCounterStyle;
- return kCSSAtRuleInvalid;
- }
+ if (EqualIgnoringASCIICase(name, "counter-style"))
+ return kCSSAtRuleCounterStyle;
if (EqualIgnoringASCIICase(name, "scroll-timeline")) {
if (RuntimeEnabledFeatures::CSSScrollTimelineEnabled())
return kCSSAtRuleScrollTimeline;
@@ -67,6 +69,9 @@ void CountAtRule(const CSSParserContext* context, CSSAtRuleID rule_id) {
case kCSSAtRuleKeyframes:
feature = WebFeature::kCSSAtRuleKeyframes;
break;
+ case kCSSAtRuleLayer:
+ // TODO(crbug.com/1095765): Add use-counter.
+ return;
case kCSSAtRuleMedia:
feature = WebFeature::kCSSAtRuleMedia;
break;
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.h b/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.h
index 9ec2aa3ec04..2aa93ffff2a 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.h
@@ -17,6 +17,7 @@ enum CSSAtRuleID {
kCSSAtRuleFontFace,
kCSSAtRuleImport,
kCSSAtRuleKeyframes,
+ kCSSAtRuleLayer,
kCSSAtRuleMedia,
kCSSAtRuleNamespace,
kCSSAtRulePage,
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 ad3afab165a..16de152cc3a 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
@@ -89,9 +89,13 @@ CSSParserContext::CSSParserContext(CSSParserMode mode,
ResourceFetchRestriction::kNone) {}
CSSParserContext::CSSParserContext(const Document& document)
+ : CSSParserContext(document, document.BaseURL()) {}
+
+CSSParserContext::CSSParserContext(const Document& document,
+ const KURL& base_url_override)
: CSSParserContext(
document,
- document.BaseURL(),
+ base_url_override,
true /* origin_clean */,
Referrer(document.GetExecutionContext()
? document.GetExecutionContext()->OutgoingReferrer()
@@ -257,7 +261,7 @@ void CSSParserContext::ReportLayoutAnimationsViolationIfNeeded(
const StyleRuleKeyframe& rule) const {
if (!document_ || !document_->GetExecutionContext())
return;
- for (size_t i = 0; i < rule.Properties().PropertyCount(); ++i) {
+ for (unsigned i = 0; i < rule.Properties().PropertyCount(); ++i) {
CSSPropertyID id = rule.Properties().PropertyAt(i).Id();
if (id == CSSPropertyID::kVariable)
continue;
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h b/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h
index ed1263bb359..f93fbdaef21 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h
@@ -58,6 +58,7 @@ class CORE_EXPORT CSSParserContext final
SelectorProfile = kLiveProfile,
const Document* use_counter_document = nullptr);
explicit CSSParserContext(const Document&);
+ CSSParserContext(const Document&, const KURL& base_url_override);
CSSParserContext(const Document&,
const KURL& base_url_override,
bool origin_clean,
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 e2718da1361..da3d47c865f 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
@@ -366,7 +366,8 @@ static bool ParseColorNumberOrPercentage(const CharacterType*& string,
}
template <typename CharacterType>
-static inline bool IsTenthAlpha(const CharacterType* string, const int length) {
+static inline bool IsTenthAlpha(const CharacterType* string,
+ const wtf_size_t length) {
// "0.X"
if (length == 3 && string[0] == '0' && string[1] == '.' &&
IsASCIIDigit(string[2]))
@@ -396,7 +397,7 @@ static inline bool ParseAlphaValue(const CharacterType*& string,
value = 0;
- size_t length = end - string;
+ wtf_size_t length = static_cast<wtf_size_t>(end - string);
if (length < 2)
return false;
@@ -1118,6 +1119,10 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
}
}
+bool CSSParserFastPaths::IsValidSystemFont(CSSValueID value_id) {
+ return value_id >= CSSValueID::kCaption && value_id <= CSSValueID::kStatusBar;
+}
+
static CSSValue* ParseKeywordValue(CSSPropertyID property_id,
const String& string,
CSSParserMode parser_mode) {
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h b/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
index 85a29d953ae..faf577c8535 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
@@ -32,6 +32,8 @@ class CORE_EXPORT CSSParserFastPaths {
CSSValueID,
CSSParserMode);
+ static bool IsValidSystemFont(CSSValueID);
+
static CSSValue* ParseColor(const String&, CSSParserMode);
};
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_idioms.h b/chromium/third_party/blink/renderer/core/css/parser/css_parser_idioms.h
index 1eebf8db92b..01c5141fdb6 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_idioms.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_idioms.h
@@ -31,8 +31,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_IDIOMS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_IDIOMS_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/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
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 0e9f36457af..d1436178960 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
@@ -62,6 +62,39 @@ AtomicString ConsumeStringOrURI(CSSParserTokenStream& stream) {
return uri.Value().ToAtomicString();
}
+AtomicString ConsumeContainerName(CSSParserTokenRange& range,
+ const CSSParserContext& context) {
+ CSSValue* name = css_parsing_utils::ConsumeContainerName(range, context);
+ if (auto* custom_ident = DynamicTo<CSSCustomIdentValue>(name))
+ return custom_ident->Value();
+ return g_null_atom;
+}
+
+// Finds the longest prefix of |range| that matches a <layer-name> and parses
+// it. Returns an empty result with |range| unmodified if parsing fails.
+StyleRuleBase::LayerName ConsumeCascadeLayerName(CSSParserTokenRange& range) {
+ CSSParserTokenRange original_range = range;
+ StyleRuleBase::LayerName name;
+ while (!range.AtEnd() && range.Peek().GetType() == kIdentToken) {
+ const CSSParserToken& name_part = range.Consume();
+ name.emplace_back(name_part.Value().ToString());
+
+ const bool has_next_part = range.Peek().GetType() == kDelimiterToken &&
+ range.Peek().Delimiter() == '.' &&
+ range.Peek(1).GetType() == kIdentToken;
+ if (!has_next_part)
+ break;
+ range.Consume();
+ }
+
+ if (!name.size())
+ original_range = range;
+ else
+ range.ConsumeWhitespace();
+
+ return name;
+}
+
} // namespace
CSSParserImpl::CSSParserImpl(const CSSParserContext* context,
@@ -133,8 +166,7 @@ static inline void FilterProperties(
if (property.IsImportant() != important)
continue;
if (property.Id() == CSSPropertyID::kVariable) {
- const AtomicString& name =
- To<CSSCustomPropertyDeclaration>(property.Value())->GetName();
+ AtomicString name = property.Name().ToAtomicString();
if (seen_custom_properties.Contains(name))
continue;
seen_custom_properties.insert(name);
@@ -560,6 +592,8 @@ StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenStream& stream,
return ConsumeKeyframesRule(true, stream);
case kCSSAtRuleKeyframes:
return ConsumeKeyframesRule(false, stream);
+ case kCSSAtRuleLayer:
+ return ConsumeLayerRule(stream);
case kCSSAtRulePage:
return ConsumePageRule(stream);
case kCSSAtRuleProperty:
@@ -670,6 +704,27 @@ StyleRuleImport* CSSParserImpl::ConsumeImportRule(
if (uri.IsNull())
return nullptr; // Parse error, expected string or URI
+ absl::optional<StyleRuleBase::LayerName> layer;
+ if (RuntimeEnabledFeatures::CSSCascadeLayersEnabled()) {
+ if (prelude.Peek().GetType() == kIdentToken &&
+ prelude.Peek().Id() == CSSValueID::kLayer) {
+ prelude.ConsumeIncludingWhitespace();
+ layer = StyleRuleBase::LayerName();
+ } else if (prelude.Peek().GetType() == kFunctionToken &&
+ prelude.Peek().FunctionId() == CSSValueID::kLayer) {
+ CSSParserTokenRange original_prelude = prelude;
+ CSSParserTokenRange name_range =
+ css_parsing_utils::ConsumeFunction(prelude);
+ StyleRuleBase::LayerName name = ConsumeCascadeLayerName(name_range);
+ if (!name.size() || !name_range.AtEnd()) {
+ // Invalid layer() function can still be parsed as <general-enclosed>
+ prelude = original_prelude;
+ } else {
+ layer = std::move(name);
+ }
+ }
+ }
+
if (observer_) {
observer_->StartRuleHeader(StyleRule::kImport, prelude_offset_start);
observer_->EndRuleHeader(prelude_offset_end);
@@ -678,7 +733,7 @@ StyleRuleImport* CSSParserImpl::ConsumeImportRule(
}
return MakeGarbageCollected<StyleRuleImport>(
- uri,
+ uri, std::move(layer),
MediaQueryParser::ParseMediaQuerySet(prelude,
context_->GetExecutionContext()),
context_->IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse);
@@ -999,6 +1054,8 @@ StyleRuleContainer* CSSParserImpl::ConsumeContainerRule(
observer_->StartRuleBody(stream.Offset());
}
+ AtomicString name = ConsumeContainerName(prelude, *context_);
+
// TODO(crbug.com/1145970): Restrict what is allowed by @container.
scoped_refptr<MediaQuerySet> media_queries =
MediaQueryParser::ParseMediaQuerySet(prelude,
@@ -1006,7 +1063,7 @@ StyleRuleContainer* CSSParserImpl::ConsumeContainerRule(
if (!media_queries)
return nullptr;
ContainerQuery* container_query =
- MakeGarbageCollected<ContainerQuery>(media_queries);
+ MakeGarbageCollected<ContainerQuery>(name, media_queries);
HeapVector<Member<StyleRuleBase>> rules;
ConsumeRuleList(stream, kRegularRuleList,
@@ -1018,6 +1075,72 @@ StyleRuleContainer* CSSParserImpl::ConsumeContainerRule(
return MakeGarbageCollected<StyleRuleContainer>(*container_query, rules);
}
+StyleRuleBase* CSSParserImpl::ConsumeLayerRule(CSSParserTokenStream& stream) {
+ DCHECK(RuntimeEnabledFeatures::CSSCascadeLayersEnabled());
+
+ wtf_size_t prelude_offset_start = stream.LookAheadOffset();
+ CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
+ wtf_size_t prelude_offset_end = stream.LookAheadOffset();
+
+ // @layer statement rule without style declarations.
+ if (stream.AtEnd() || stream.UncheckedPeek().GetType() == kSemicolonToken) {
+ if (!ConsumeEndOfPreludeForAtRuleWithoutBlock(stream))
+ return nullptr;
+
+ Vector<StyleRuleBase::LayerName> names;
+ while (!prelude.AtEnd()) {
+ if (names.size()) {
+ if (!css_parsing_utils::ConsumeCommaIncludingWhitespace(prelude))
+ return nullptr;
+ }
+ StyleRuleBase::LayerName name = ConsumeCascadeLayerName(prelude);
+ if (!name.size())
+ return nullptr;
+ names.push_back(std::move(name));
+ }
+ if (!names.size())
+ return nullptr;
+
+ if (observer_) {
+ observer_->StartRuleHeader(StyleRule::kLayerStatement,
+ prelude_offset_start);
+ observer_->EndRuleHeader(prelude_offset_end);
+ observer_->StartRuleBody(prelude_offset_end);
+ observer_->EndRuleBody(prelude_offset_end);
+ }
+
+ return MakeGarbageCollected<StyleRuleLayerStatement>(std::move(names));
+ }
+
+ // @layer block rule with style declarations.
+ if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
+ return nullptr;
+ CSSParserTokenStream::BlockGuard guard(stream);
+
+ StyleRuleBase::LayerName name;
+ prelude.ConsumeWhitespace();
+ if (!prelude.AtEnd()) {
+ name = ConsumeCascadeLayerName(prelude);
+ if (!name.size() || !prelude.AtEnd())
+ return nullptr;
+ }
+
+ if (observer_) {
+ observer_->StartRuleHeader(StyleRule::kLayerBlock, prelude_offset_start);
+ observer_->EndRuleHeader(prelude_offset_end);
+ observer_->StartRuleBody(stream.Offset());
+ }
+
+ HeapVector<Member<StyleRuleBase>> rules;
+ ConsumeRuleList(stream, kRegularRuleList,
+ [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
+
+ if (observer_)
+ observer_->EndRuleBody(stream.Offset());
+
+ return MakeGarbageCollected<StyleRuleLayerBlock>(std::move(name), rules);
+}
+
StyleRuleKeyframe* CSSParserImpl::ConsumeKeyframeStyleRule(
const CSSParserTokenRange prelude,
const RangeOffset& prelude_offset,
@@ -1214,8 +1337,7 @@ void CSSParserImpl::ConsumeVariableValue(
bool is_animation_tainted) {
if (CSSCustomPropertyDeclaration* value =
CSSVariableParser::ParseDeclarationValue(
- variable_name, tokenized_value, is_animation_tainted,
- *context_)) {
+ tokenized_value, is_animation_tainted, *context_)) {
parsed_properties_.push_back(
CSSPropertyValue(CSSPropertyName(variable_name), *value, important));
context_->Count(context_->Mode(), CSSPropertyID::kVariable);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.h b/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.h
index 34c728d8000..c3b3fa00285 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.h
@@ -169,6 +169,7 @@ class CORE_EXPORT CSSParserImpl {
StyleRuleCounterStyle* ConsumeCounterStyleRule(CSSParserTokenStream&);
StyleRuleScrollTimeline* ConsumeScrollTimelineRule(CSSParserTokenStream&);
StyleRuleContainer* ConsumeContainerRule(CSSParserTokenStream&);
+ StyleRuleBase* ConsumeLayerRule(CSSParserTokenStream&);
StyleRuleKeyframe* ConsumeKeyframeStyleRule(CSSParserTokenRange prelude,
const RangeOffset& prelude_offset,
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
index 73529674561..fca18b667cd 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/css/parser/css_parser_observer.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 "third_party/blink/renderer/core/css/style_rule_import.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/testing/runtime_enabled_features_test_helpers.h"
@@ -194,8 +195,6 @@ TEST(CSSParserImplTest, AtScrollTimelineOffsets) {
}
TEST(CSSParserImplTest, AtCounterStyleOffsets) {
- ScopedCSSAtRuleCounterStyleForTest scoped_feature(true);
-
String sheet_text = "@counter-style test { }";
auto* context = MakeGarbageCollected<CSSParserContext>(
kHTMLStandardMode, SecureContextMode::kInsecureContext);
@@ -212,19 +211,6 @@ TEST(CSSParserImplTest, AtCounterStyleOffsets) {
EXPECT_EQ(test_css_parser_observer.rule_body_end_, 22u);
}
-TEST(CSSParserImplTest, AtCounterStyleDisabled) {
- ScopedCSSAtRuleCounterStyleForTest scoped_feature(false);
-
- String sheet_text = "@counter-style test { }";
- auto* context = MakeGarbageCollected<CSSParserContext>(
- kHTMLStandardMode, SecureContextMode::kInsecureContext);
- auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(context);
- TestCSSParserObserver test_css_parser_observer;
- CSSParserImpl::ParseStyleSheetForInspector(sheet_text, context, style_sheet,
- test_css_parser_observer);
- EXPECT_EQ(style_sheet->ChildRules().size(), 0u);
-}
-
TEST(CSSParserImplTest, AtContainerOffsets) {
ScopedCSSContainerQueriesForTest scoped_feature(true);
@@ -291,4 +277,324 @@ TEST(CSSParserImplTest, RemoveImportantAnnotationIfPresent) {
}
}
+TEST(CSSParserImplTest, LayerRuleDisabled) {
+ ScopedCSSCascadeLayersForTest disabled_scope(false);
+
+ // @layer rules should be ignored when the feature is disabled.
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+ EXPECT_FALSE(ParseRule(*document, "@layer foo;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo, bar;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo.bar { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer { }"));
+}
+
+TEST(CSSParserImplTest, InvalidLayerRules) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ // At most one layer name in an @layer block rule
+ EXPECT_FALSE(ParseRule(*document, "@layer foo, bar { }"));
+
+ // Layers must be named in an @layer statement rule
+ EXPECT_FALSE(ParseRule(*document, "@layer ;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo, , bar;"));
+
+ // Invalid layer names
+ EXPECT_FALSE(ParseRule(*document, "@layer foo.bar. { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo.bar.;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer .foo.bar { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer .foo.bar;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo. bar { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo. bar;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo bar { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo bar;"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo/bar { }"));
+ EXPECT_FALSE(ParseRule(*document, "@layer foo/bar;"));
+}
+
+TEST(CSSParserImplTest, ValidLayerBlockRule) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ // Basic named layer
+ {
+ String rule = "@layer foo { }";
+ auto* parsed = DynamicTo<StyleRuleLayerBlock>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_EQ(1u, parsed->GetName().size());
+ EXPECT_EQ("foo", parsed->GetName()[0]);
+ }
+
+ // Unnamed layer
+ {
+ String rule = "@layer { }";
+ auto* parsed = DynamicTo<StyleRuleLayerBlock>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_EQ(0u, parsed->GetName().size());
+ }
+
+ // Sub-layer declared directly
+ {
+ String rule = "@layer foo.bar { }";
+ auto* parsed = DynamicTo<StyleRuleLayerBlock>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_EQ(2u, parsed->GetName().size());
+ EXPECT_EQ("foo", parsed->GetName()[0]);
+ EXPECT_EQ("bar", parsed->GetName()[1]);
+ }
+}
+
+TEST(CSSParserImplTest, ValidLayerStatementRule) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ {
+ String rule = "@layer foo;";
+ auto* parsed =
+ DynamicTo<StyleRuleLayerStatement>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_EQ(1u, parsed->GetNames().size());
+ ASSERT_EQ(1u, parsed->GetNames()[0].size());
+ EXPECT_EQ("foo", parsed->GetNames()[0][0]);
+ }
+
+ {
+ String rule = "@layer foo, bar;";
+ auto* parsed =
+ DynamicTo<StyleRuleLayerStatement>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_EQ(2u, parsed->GetNames().size());
+ ASSERT_EQ(1u, parsed->GetNames()[0].size());
+ EXPECT_EQ("foo", parsed->GetNames()[0][0]);
+ ASSERT_EQ(1u, parsed->GetNames()[1].size());
+ EXPECT_EQ("bar", parsed->GetNames()[1][0]);
+ }
+
+ {
+ String rule = "@layer foo, bar.baz;";
+ auto* parsed =
+ DynamicTo<StyleRuleLayerStatement>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_EQ(2u, parsed->GetNames().size());
+ ASSERT_EQ(1u, parsed->GetNames()[0].size());
+ EXPECT_EQ("foo", parsed->GetNames()[0][0]);
+ ASSERT_EQ(2u, parsed->GetNames()[1].size());
+ EXPECT_EQ("bar", parsed->GetNames()[1][0]);
+ EXPECT_EQ("baz", parsed->GetNames()[1][1]);
+ }
+}
+
+TEST(CSSParserImplTest, NestedLayerRules) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ // Block rule as a child rule.
+ {
+ String rule = "@layer foo { @layer bar { } }";
+ auto* foo = DynamicTo<StyleRuleLayerBlock>(ParseRule(*document, rule));
+ ASSERT_TRUE(foo);
+ ASSERT_EQ(1u, foo->GetName().size());
+ EXPECT_EQ("foo", foo->GetName()[0]);
+ ASSERT_EQ(1u, foo->ChildRules().size());
+
+ auto* bar = DynamicTo<StyleRuleLayerBlock>(foo->ChildRules()[0].Get());
+ ASSERT_TRUE(bar);
+ ASSERT_EQ(1u, bar->GetName().size());
+ EXPECT_EQ("bar", bar->GetName()[0]);
+ }
+
+ // Statement rule as a child rule.
+ {
+ String rule = "@layer foo { @layer bar, baz; }";
+ auto* foo = DynamicTo<StyleRuleLayerBlock>(ParseRule(*document, rule));
+ ASSERT_TRUE(foo);
+ ASSERT_EQ(1u, foo->GetName().size());
+ EXPECT_EQ("foo", foo->GetName()[0]);
+ ASSERT_EQ(1u, foo->ChildRules().size());
+
+ auto* barbaz =
+ DynamicTo<StyleRuleLayerStatement>(foo->ChildRules()[0].Get());
+ ASSERT_TRUE(barbaz);
+ ASSERT_EQ(2u, barbaz->GetNames().size());
+ ASSERT_EQ(1u, barbaz->GetNames()[0].size());
+ EXPECT_EQ("bar", barbaz->GetNames()[0][0]);
+ ASSERT_EQ(1u, barbaz->GetNames()[1].size());
+ EXPECT_EQ("baz", barbaz->GetNames()[1][0]);
+ }
+
+ // Nested in an unnamed layer.
+ {
+ String rule = "@layer { @layer foo; @layer bar { } }";
+ auto* parent = DynamicTo<StyleRuleLayerBlock>(ParseRule(*document, rule));
+ ASSERT_TRUE(parent);
+ ASSERT_EQ(0u, parent->GetName().size());
+ ASSERT_EQ(2u, parent->ChildRules().size());
+
+ auto* foo =
+ DynamicTo<StyleRuleLayerStatement>(parent->ChildRules()[0].Get());
+ ASSERT_TRUE(foo);
+ ASSERT_EQ(1u, foo->GetNames().size());
+ ASSERT_EQ(1u, foo->GetNames()[0].size());
+ EXPECT_EQ("foo", foo->GetNames()[0][0]);
+
+ auto* bar = DynamicTo<StyleRuleLayerBlock>(parent->ChildRules()[1].Get());
+ ASSERT_TRUE(bar);
+ ASSERT_EQ(1u, bar->GetName().size());
+ EXPECT_EQ("bar", bar->GetName()[0]);
+ }
+}
+
+TEST(CSSParserImplTest, LayeredImportDisabled) {
+ ScopedCSSCascadeLayersForTest disabled_scope(false);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ // When the feature is disabled, layered @import rules should still parse and
+ // the layer keyword/function should be parsed as a <general-enclosed>, and
+ // hence has no effect.
+
+ {
+ String rule = "@import url(foo.css) layer;";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->IsLayered());
+ EXPECT_EQ("layer", parsed->MediaQueries()->MediaText());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->IsLayered());
+ EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar.baz);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->IsLayered());
+ EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
+ }
+}
+
+TEST(CSSParserImplTest, LayeredImportRules) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ {
+ String rule = "@import url(foo.css) layer;";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_TRUE(parsed->IsLayered());
+ EXPECT_EQ(0u, parsed->GetLayerName().size());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_TRUE(parsed->IsLayered());
+ ASSERT_EQ(1u, parsed->GetLayerName().size());
+ EXPECT_EQ("bar", parsed->GetLayerName()[0]);
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar.baz);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_TRUE(parsed->IsLayered());
+ ASSERT_EQ(2u, parsed->GetLayerName().size());
+ EXPECT_EQ("bar", parsed->GetLayerName()[0]);
+ EXPECT_EQ("baz", parsed->GetLayerName()[1]);
+ }
+}
+
+TEST(CSSParserImplTest, LayeredImportRulesInvalid) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ // Invalid layer declarations in @import rules should not make the entire rule
+ // invalid. They should be parsed as <general-enclosed> and have no effect.
+
+ {
+ String rule = "@import url(foo.css) layer();";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->IsLayered());
+ EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar, baz);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->IsLayered());
+ EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar.baz.);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->IsLayered());
+ EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
+ }
+}
+
+TEST(CSSParserImplTest, LayeredImportRulesMultipleLayers) {
+ ScopedCSSCascadeLayersForTest enabled_scope(true);
+
+ using css_test_helpers::ParseRule;
+ Document* document = Document::CreateForTest();
+
+ // If an @import rule has more than one layer keyword/function, only the first
+ // one is parsed as layer, and the remaining ones are parsed as
+ // <general-enclosed> and hence have no effect.
+
+ {
+ String rule = "@import url(foo.css) layer layer;";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_TRUE(parsed->IsLayered());
+ EXPECT_EQ(0u, parsed->GetLayerName().size());
+ EXPECT_EQ("layer", parsed->MediaQueries()->MediaText());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer layer(bar);";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_TRUE(parsed->IsLayered());
+ EXPECT_EQ(0u, parsed->GetLayerName().size());
+ EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
+ }
+
+ {
+ String rule = "@import url(foo.css) layer(bar) layer;";
+ auto* parsed = DynamicTo<StyleRuleImport>(ParseRule(*document, rule));
+ ASSERT_TRUE(parsed);
+ ASSERT_TRUE(parsed->IsLayered());
+ ASSERT_EQ(1u, parsed->GetLayerName().size());
+ EXPECT_EQ("bar", parsed->GetLayerName()[0]);
+ EXPECT_EQ("layer", parsed->MediaQueries()->MediaText());
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
index 20c28bee82b..6940df639d8 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
@@ -666,6 +666,15 @@ TEST_F(CSSPropertyUseCounterTest, CSSPropertyFontSizeWebkitXxxLargeUseCount) {
EXPECT_TRUE(IsCounted(feature));
}
+TEST_F(CSSPropertyUseCounterTest, CSSPropertyBackgroundImageWebkitImageSet) {
+ WebFeature feature = WebFeature::kWebkitImageSet;
+ ParseProperty(CSSPropertyID::kBackgroundImage, "none");
+ EXPECT_FALSE(IsCounted(feature));
+ ParseProperty(CSSPropertyID::kBackgroundImage,
+ "-webkit-image-set(url(foo) 2x)");
+ EXPECT_TRUE(IsCounted(feature));
+}
+
TEST(CSSPropertyParserTest, InternalLightDarkAuthor) {
auto* context = MakeGarbageCollected<CSSParserContext>(
kHTMLStandardMode, SecureContextMode::kInsecureContext);
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 10f9bce4051..15fd88658b6 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
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/css/parser/css_proto_converter.h"
// TODO(metzman): Figure out how to remove this include and use DCHECK.
+#include "base/notreached.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/core/css/parser/css.pb.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -190,6 +191,8 @@ const std::string Converter::kMfNameLookupTable[] = {
"scan",
"shape",
"immersive",
+ "dynamic-range",
+ "video-dynamic-range",
"INVALID_NAME"};
const std::string Converter::kImportLookupTable[] = {
@@ -964,6 +967,8 @@ const std::string Converter::kValueLookupTable[] = {
"no-drag",
"jis-b5",
"jis-b4",
+ "standard",
+ "high",
"INVALID_VALUE",
};
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 75209858ee3..68bbeb89158 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
@@ -226,6 +226,27 @@ CSSSelectorList CSSSelectorParser::ConsumeForgivingCompoundSelectorList(
return CSSSelectorList::AdoptSelectorVector(selector_list);
}
+CSSSelectorList CSSSelectorParser::ConsumeRelativeSelectorList(
+ CSSParserTokenRange& range) {
+ Vector<std::unique_ptr<CSSParserSelector>> selector_list;
+ std::unique_ptr<CSSParserSelector> selector = ConsumeRelativeSelector(range);
+ if (!selector)
+ return CSSSelectorList();
+ selector_list.push_back(std::move(selector));
+ while (!range.AtEnd() && range.Peek().GetType() == kCommaToken) {
+ range.ConsumeIncludingWhitespace();
+ selector = ConsumeRelativeSelector(range);
+ if (!selector)
+ return CSSSelectorList();
+ selector_list.push_back(std::move(selector));
+ }
+
+ if (failed_parsing_)
+ return CSSSelectorList();
+
+ return CSSSelectorList::AdoptSelectorVector(selector_list);
+}
+
namespace {
enum CompoundSelectorFlags {
@@ -249,6 +270,41 @@ unsigned ExtractCompoundFlags(const CSSParserSelector& simple_selector,
} // namespace
+std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumeRelativeSelector(
+ CSSParserTokenRange& range) {
+ std::unique_ptr<CSSParserSelector> selector =
+ std::make_unique<CSSParserSelector>();
+ selector->SetMatch(CSSSelector::kPseudoClass);
+ selector->UpdatePseudoType("-internal-relative-leftmost", *context_,
+ false /*has_arguments*/, context_->Mode());
+ DCHECK_EQ(selector->GetPseudoType(), CSSSelector::kPseudoRelativeLeftmost);
+
+ CSSSelector::RelationType combinator = ConsumeCombinator(range);
+ switch (combinator) {
+ case CSSSelector::kSubSelector:
+ case CSSSelector::kDescendant:
+ combinator = CSSSelector::kRelativeDescendant;
+ break;
+ case CSSSelector::kChild:
+ combinator = CSSSelector::kRelativeChild;
+ break;
+ case CSSSelector::kDirectAdjacent:
+ combinator = CSSSelector::kRelativeDirectAdjacent;
+ break;
+ case CSSSelector::kIndirectAdjacent:
+ combinator = CSSSelector::kRelativeIndirectAdjacent;
+ break;
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+
+ unsigned previous_compound_flags = 0;
+
+ return ConsumePartialComplexSelector(range, combinator, std::move(selector),
+ previous_compound_flags);
+}
+
std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumeComplexSelector(
CSSParserTokenRange& range) {
std::unique_ptr<CSSParserSelector> selector = ConsumeCompoundSelector(range);
@@ -261,7 +317,21 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumeComplexSelector(
simple && !previous_compound_flags; simple = simple->TagHistory())
previous_compound_flags |= ExtractCompoundFlags(*simple, context_->Mode());
- while (CSSSelector::RelationType combinator = ConsumeCombinator(range)) {
+ if (CSSSelector::RelationType combinator = ConsumeCombinator(range)) {
+ return ConsumePartialComplexSelector(range, combinator, std::move(selector),
+ previous_compound_flags);
+ }
+
+ return selector;
+}
+
+std::unique_ptr<CSSParserSelector>
+CSSSelectorParser::ConsumePartialComplexSelector(
+ CSSParserTokenRange& range,
+ CSSSelector::RelationType& combinator,
+ std::unique_ptr<CSSParserSelector> selector,
+ unsigned& previous_compound_flags) {
+ do {
std::unique_ptr<CSSParserSelector> next_selector =
ConsumeCompoundSelector(range);
if (!next_selector)
@@ -280,7 +350,7 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumeComplexSelector(
end->SetTagHistory(std::move(selector));
selector = std::move(next_selector);
- }
+ } while ((combinator = ConsumeCombinator(range)));
return selector;
}
@@ -455,6 +525,7 @@ bool IsSimpleSelectorValidAfterPseudoElement(
case CSSSelector::kPseudoIs:
case CSSSelector::kPseudoWhere:
case CSSSelector::kPseudoNot:
+ case CSSSelector::kPseudoHas:
// These pseudo-classes are themselves always valid.
// CSSSelectorParser::restricting_pseudo_element_ ensures that invalid
// nested selectors will be dropped if they are invalid according to
@@ -796,6 +867,25 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumePseudo(
selector->SetSelectorList(std::move(selector_list));
return selector;
}
+ case CSSSelector::kPseudoHas: {
+ if (!RuntimeEnabledFeatures::CSSPseudoHasInSnapshotProfileEnabled() ||
+ (context_->IsLiveProfile() &&
+ !RuntimeEnabledFeatures::CSSPseudoHasEnabled())) {
+ return nullptr;
+ }
+
+ DisallowPseudoElementsScope scope(this);
+ base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
+
+ std::unique_ptr<CSSSelectorList> selector_list =
+ std::make_unique<CSSSelectorList>();
+ *selector_list = ConsumeRelativeSelectorList(block);
+ if (!selector_list->IsValid() || !block.AtEnd())
+ return nullptr;
+
+ selector->SetSelectorList(std::move(selector_list));
+ return selector;
+ }
case CSSSelector::kPseudoNot: {
DisallowPseudoElementsScope scope(this);
base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
@@ -1356,6 +1446,16 @@ void CSSSelectorParser::RecordUsageAndDeprecations(
DCHECK(RuntimeEnabledFeatures::CSSPseudoDirEnabled());
feature = WebFeature::kCSSSelectorPseudoDir;
break;
+ case CSSSelector::kPseudoHas:
+ if (context_->IsLiveProfile()) {
+ DCHECK(RuntimeEnabledFeatures::CSSPseudoHasEnabled());
+ feature = WebFeature::kCSSSelectorPseudoHasInLiveProfile;
+ } else {
+ DCHECK(
+ RuntimeEnabledFeatures::CSSPseudoHasInSnapshotProfileEnabled());
+ feature = WebFeature::kCSSSelectorPseudoHasInSnapshotProfile;
+ }
+ break;
default:
break;
}
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.h b/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.h
index 589f8ef2c66..b2047bd21f8 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.h
@@ -61,9 +61,32 @@ class CORE_EXPORT CSSSelectorParser {
// https://drafts.csswg.org/selectors/#typedef-forgiving-selector-list
CSSSelectorList ConsumeForgivingComplexSelectorList(CSSParserTokenRange&);
CSSSelectorList ConsumeForgivingCompoundSelectorList(CSSParserTokenRange&);
+ // https://drafts.csswg.org/selectors/#typedef-relative-selector-list
+ CSSSelectorList ConsumeRelativeSelectorList(CSSParserTokenRange&);
+ std::unique_ptr<CSSParserSelector> ConsumeRelativeSelector(
+ CSSParserTokenRange&);
std::unique_ptr<CSSParserSelector> ConsumeComplexSelector(
CSSParserTokenRange&);
+
+ // ConsumePartialComplexSelector() method provides the common logic of
+ // consuming a complex selector and consuming a relative selector.
+ //
+ // After consuming the left-most combinator of a relative selector, we can
+ // consume the remaining selectors with the common logic.
+ // For example, after consuming the left-most combinator '~' of the relative
+ // selector '~ .a ~ .b', we can consume remaining selectors '.a ~ .b'
+ // with this method.
+ //
+ // After consuming the left-most compound selector and a combinator of a
+ // complex selector, we can also use this method to consume the remaining
+ // selectors of the complex selector.
+ std::unique_ptr<CSSParserSelector> ConsumePartialComplexSelector(
+ CSSParserTokenRange&,
+ CSSSelector::RelationType& /* current combinator */,
+ std::unique_ptr<CSSParserSelector> /* previous compound selector */,
+ unsigned& /* previous compound flags */);
+
std::unique_ptr<CSSParserSelector> ConsumeCompoundSelector(
CSSParserTokenRange&);
// This doesn't include element names, since they're handled specially
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
index 10f1c17fc70..1b669f37223 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
@@ -13,16 +13,6 @@ namespace blink {
namespace {
-// The result kUnknown must be converted to 'false' if passed to a context
-// which requires a boolean value.
-// TODO(crbug.com/1052274): This is supposed to happen at the top-level,
-// but currently happens on ConsumeGeneralEnclosed's result.
-CSSSupportsParser::Result EvalUnknown(CSSSupportsParser::Result result) {
- return result == CSSSupportsParser::Result::kUnknown
- ? CSSSupportsParser::Result::kUnsupported
- : result;
-}
-
// https://drafts.csswg.org/css-syntax/#typedef-any-value
bool IsNextTokenAllowedForAnyValue(CSSParserTokenRange& range) {
switch (range.Peek().GetType()) {
@@ -168,13 +158,7 @@ CSSSupportsParser::Result CSSSupportsParser::ConsumeSupportsInParens(
}
// <general-enclosed>
- //
- // TODO(crbug.com/1052274): Support kUnknown beyond this point.
- //
- // The result kUnknown is supposed to be evaluated at the top level, but
- // we have already shipped the behavior of evaluating it here, and Firefox
- // does the same thing.
- return EvalUnknown(ConsumeGeneralEnclosed(first_token, stream));
+ return ConsumeGeneralEnclosed(first_token, stream);
}
// <supports-feature> = <supports-selector-fn> | <supports-decl>
@@ -225,7 +209,7 @@ CSSSupportsParser::Result CSSSupportsParser::ConsumeGeneralEnclosed(
return Result::kParseFailure;
stream.ConsumeWhitespace();
- return Result::kUnknown;
+ return Result::kUnsupported;
}
return Result::kParseFailure;
}
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.h b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.h
index 478cacb2728..a9f324d0ebd 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser.h
@@ -24,13 +24,6 @@ class CORE_EXPORT CSSSupportsParser {
// don't support the feature.
kUnsupported,
kSupported,
- // kUnknown is a special value used for productions that only match
- // <general-enclosed> [1]. See note regarding Kleene 3-valued logic [2]
- // for explanation of how this is different from kUnsupported.
- //
- // [1] https://drafts.csswg.org/css-conditional-3/#at-supports
- // [2] https://drafts.csswg.org/mediaqueries-4/#evaluating
- kUnknown,
// This is used to signal parse failure in the @supports syntax itself.
// This means that for a production like:
//
@@ -114,8 +107,6 @@ inline CSSSupportsParser::Result operator&(CSSSupportsParser::Result a,
using Result = CSSSupportsParser::Result;
if (a == Result::kParseFailure || b == Result::kParseFailure)
return Result::kParseFailure;
- if (a == Result::kUnknown && b == Result::kUnknown)
- return Result::kUnknown;
if (a != Result::kSupported || b != Result::kSupported)
return Result::kUnsupported;
return Result::kSupported;
@@ -128,8 +119,6 @@ inline CSSSupportsParser::Result operator|(CSSSupportsParser::Result a,
return Result::kParseFailure;
if (a == Result::kSupported || b == Result::kSupported)
return Result::kSupported;
- if (a == Result::kUnknown || b == Result::kUnknown)
- return Result::kUnknown;
return Result::kUnsupported;
}
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc
index 438a118aabf..ec9025d16fc 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc
@@ -106,7 +106,6 @@ TEST_F(CSSSupportsParserTest, ResultNot) {
EXPECT_EQ(Result::kSupported, !Result::kUnsupported);
EXPECT_EQ(Result::kUnsupported, !Result::kSupported);
EXPECT_EQ(Result::kParseFailure, !Result::kParseFailure);
- EXPECT_EQ(Result::kUnknown, !Result::kUnknown);
}
TEST_F(CSSSupportsParserTest, ResultAnd) {
@@ -117,10 +116,6 @@ TEST_F(CSSSupportsParserTest, ResultAnd) {
EXPECT_EQ(Result::kParseFailure, Result::kSupported & Result::kParseFailure);
EXPECT_EQ(Result::kParseFailure, Result::kParseFailure & Result::kSupported);
-
- EXPECT_EQ(Result::kUnknown, Result::kUnknown & Result::kUnknown);
- EXPECT_EQ(Result::kUnsupported, Result::kSupported & Result::kUnknown);
- EXPECT_EQ(Result::kUnsupported, Result::kUnknown & Result::kSupported);
}
TEST_F(CSSSupportsParserTest, ResultOr) {
@@ -131,10 +126,6 @@ TEST_F(CSSSupportsParserTest, ResultOr) {
EXPECT_EQ(Result::kParseFailure, Result::kSupported | Result::kParseFailure);
EXPECT_EQ(Result::kParseFailure, Result::kParseFailure | Result::kSupported);
-
- EXPECT_EQ(Result::kUnknown, Result::kUnknown | Result::kUnknown);
- EXPECT_EQ(Result::kSupported, Result::kSupported | Result::kUnknown);
- EXPECT_EQ(Result::kSupported, Result::kUnknown | Result::kSupported);
}
TEST_F(CSSSupportsParserTest, ConsumeSupportsCondition) {
@@ -318,12 +309,12 @@ TEST_F(CSSSupportsParserTest, ConsumeSupportsFeature) {
}
TEST_F(CSSSupportsParserTest, ConsumeGeneralEnclosed) {
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(asdf)"));
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("( asdf )"));
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(3)"));
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("max(1, 2)"));
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("asdf(1, 2)"));
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("asdf(1, 2)\t"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("(asdf)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("( asdf )"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("(3)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("max(1, 2)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("asdf(1, 2)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("asdf(1, 2)\t"));
EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("("));
EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("()"));
@@ -335,8 +326,8 @@ TEST_F(CSSSupportsParserTest, ConsumeGeneralEnclosed) {
EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("(url(as'df))"));
// Valid <any-value>
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(as;df)"));
- EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(as ! df)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("(as;df)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeGeneralEnclosed("(as ! df)"));
}
TEST_F(CSSSupportsParserTest, AtSupportsCondition) {
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 9b998e87f21..53cb2b8db55 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
@@ -145,7 +145,6 @@ bool CSSVariableParser::ContainsValidVariableReferences(
}
CSSCustomPropertyDeclaration* CSSVariableParser::ParseDeclarationValue(
- const AtomicString& variable_name,
const CSSTokenizedValue& tokenized_value,
bool is_animation_tainted,
const CSSParserContext& context) {
@@ -160,13 +159,12 @@ CSSCustomPropertyDeclaration* CSSVariableParser::ParseDeclarationValue(
return nullptr;
if (type == CSSValueID::kInternalVariableValue) {
return MakeGarbageCollected<CSSCustomPropertyDeclaration>(
- variable_name,
+
CSSVariableData::Create(tokenized_value, is_animation_tainted,
has_references, context.BaseURL(),
context.Charset()));
}
- return MakeGarbageCollected<CSSCustomPropertyDeclaration>(variable_name,
- type);
+ return MakeGarbageCollected<CSSCustomPropertyDeclaration>(type);
}
CSSVariableReferenceValue* CSSVariableParser::ParseRegisteredPropertyValue(
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 c70944564ec..58ad55fc02a 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
@@ -23,7 +23,6 @@ class CORE_EXPORT CSSVariableParser {
static bool ContainsValidVariableReferences(CSSParserTokenRange);
static CSSCustomPropertyDeclaration* ParseDeclarationValue(
- const AtomicString&,
const CSSTokenizedValue&,
bool is_animation_tainted,
const CSSParserContext&);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc
index e47d8070b79..fc0d2d757bc 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc
@@ -57,8 +57,9 @@ static void VerifyCSSCalc(String text,
1);
CSSToLengthConversionData::ViewportSize viewport_size(viewport_width,
viewport_height);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversion_data(nullptr, font_sizes, viewport_size,
- 1.0);
+ container_sizes, 1.0);
EXPECT_APPROX_EQ(value, math_value->ComputeLength<float>(conversion_data));
}
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 3e411a6e4ba..789e7d51b33 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
@@ -1290,7 +1290,7 @@ void AddValuesForNamedGridLinesAtIndex(OrderedNamedLinesCollector& collector,
CSSValue* ComputedStyleUtils::ValueForGridTrackSizeList(
GridTrackSizingDirection direction,
const ComputedStyle& style) {
- const Vector<GridTrackSize>& auto_track_sizes =
+ const Vector<GridTrackSize, 1>& auto_track_sizes =
direction == kForColumns ? style.GridAutoColumns().LegacyTrackList()
: style.GridAutoRows().LegacyTrackList();
@@ -1304,27 +1304,26 @@ CSSValue* ComputedStyleUtils::ValueForGridTrackSizeList(
template <typename T, typename F>
void PopulateGridTrackList(CSSValueList* list,
OrderedNamedLinesCollector& collector,
- const Vector<T>& tracks,
+ const Vector<T, 1>& tracks,
F getTrackSize,
- int start,
- int end,
+ wtf_size_t start,
+ wtf_size_t end,
int offset = 0) {
- DCHECK_LE(0, start);
DCHECK_LE(start, end);
- DCHECK_LE((unsigned)end, tracks.size());
- for (int i = start; i < end; ++i) {
- if (i + offset >= 0)
+ DCHECK_LE(end, tracks.size());
+ for (wtf_size_t i = start; i < end; ++i) {
+ if (offset >= 0 || i >= static_cast<wtf_size_t>(-offset))
AddValuesForNamedGridLinesAtIndex(collector, i + offset, *list);
list->Append(*getTrackSize(tracks[i]));
}
- if (end + offset >= 0)
+ if (offset >= 0 || end >= static_cast<wtf_size_t>(-offset))
AddValuesForNamedGridLinesAtIndex(collector, end + offset, *list);
}
template <typename T, typename F>
void PopulateGridTrackList(CSSValueList* list,
OrderedNamedLinesCollector& collector,
- const Vector<T>& tracks,
+ const Vector<T, 1>& tracks,
F getTrackSize,
int offset = 0) {
PopulateGridTrackList<T>(list, collector, tracks, getTrackSize, 0,
@@ -1336,10 +1335,10 @@ CSSValue* ComputedStyleUtils::ValueForGridTrackList(
const LayoutObject* layout_object,
const ComputedStyle& style) {
bool is_row_axis = direction == kForColumns;
- const Vector<GridTrackSize>& track_sizes =
+ const Vector<GridTrackSize, 1>& track_sizes =
is_row_axis ? style.GridTemplateColumns().LegacyTrackList()
: style.GridTemplateRows().LegacyTrackList();
- const Vector<GridTrackSize>& auto_repeat_track_sizes =
+ const Vector<GridTrackSize, 1>& auto_repeat_track_sizes =
is_row_axis ? style.GridAutoRepeatColumns() : style.GridAutoRepeatRows();
bool is_layout_grid =
@@ -1374,7 +1373,8 @@ CSSValue* ComputedStyleUtils::ValueForGridTrackList(
// Named grid line indices are relative to the explicit grid, but we are
// including all tracks. So we need to subtract the number of leading
// implicit tracks in order to get the proper line index.
- int offset = -grid->ExplicitGridStartForDirection(direction);
+ int offset = -base::checked_cast<int>(
+ grid->ExplicitGridStartForDirection(direction));
PopulateGridTrackList(
list, collector, grid->TrackSizesForComputedStyle(direction),
[&](const LayoutUnit& v) { return ZoomAdjustedPixelValue(v, style); },
@@ -1395,7 +1395,7 @@ CSSValue* ComputedStyleUtils::ValueForGridTrackList(
}
// Add the line names and track sizes that precede the auto repeat().
- size_t auto_repeat_insertion_point =
+ wtf_size_t auto_repeat_insertion_point =
is_row_axis ? style.GridAutoRepeatColumnsInsertionPoint()
: style.GridAutoRepeatRowsInsertionPoint();
PopulateGridTrackList(list, collector, track_sizes, getTrackSize, 0,
@@ -2683,6 +2683,38 @@ CSSValue* ComputedStyleUtils::ValuesForFontVariantProperty(
}
}
+CSSValueList* ComputedStyleUtils::ValuesForContainerShorthand(
+ const ComputedStyle& style,
+ const LayoutObject* layout_object,
+ bool allow_visited_style) {
+ CHECK_EQ(containerShorthand().length(), 2u);
+ CHECK_EQ(containerShorthand().properties()[0],
+ &GetCSSPropertyContainerType());
+ CHECK_EQ(containerShorthand().properties()[1],
+ &GetCSSPropertyContainerName());
+
+ CSSValueList* list = CSSValueList::CreateSlashSeparated();
+
+ const CSSValue* type =
+ GetCSSPropertyContainerType().CSSValueFromComputedStyle(
+ style, layout_object, allow_visited_style);
+ const CSSValue* name =
+ GetCSSPropertyContainerName().CSSValueFromComputedStyle(
+ style, layout_object, allow_visited_style);
+
+ DCHECK(type);
+ DCHECK(name);
+
+ list->Append(*type);
+
+ if (!(IsA<CSSIdentifierValue>(name) &&
+ To<CSSIdentifierValue>(*name).GetValueID() == CSSValueID::kNone)) {
+ list->Append(*name);
+ }
+
+ return list;
+}
+
// Returns up to two values for 'scroll-customization' property. The values
// correspond to the customization values for 'x' and 'y' axes.
CSSValue* ComputedStyleUtils::ScrollCustomizationFlagsToCSSValue(
diff --git a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h
index 34c84b3699c..ff391ca8188 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_COMPUTED_STYLE_UTILS_H_
#include "cc/input/scroll_snap_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/css_border_image_slice_value.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
@@ -243,6 +244,9 @@ class CORE_EXPORT ComputedStyleUtils {
static CSSValue* ValuesForFontVariantProperty(const ComputedStyle&,
const LayoutObject*,
bool allow_visited_style);
+ static CSSValueList* ValuesForContainerShorthand(const ComputedStyle&,
+ const LayoutObject*,
+ bool allow_visited_style);
static CSSValue* ScrollCustomizationFlagsToCSSValue(
scroll_customization::ScrollDirection);
static CSSValue* ValueForGapLength(const absl::optional<Length>&,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.cc b/chromium/third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.cc
index 3b1b6963106..84c1df92ca7 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.h"
-#include "base/stl_util.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 9fbc109a3f9..08029c8f77f 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
@@ -810,6 +810,15 @@ CSSPrimitiveValue* ConsumeLength(CSSParserTokenRange& range,
case CSSPrimitiveValue::UnitType::kViewportMin:
case CSSPrimitiveValue::UnitType::kViewportMax:
break;
+ case CSSPrimitiveValue::UnitType::kContainerWidth:
+ case CSSPrimitiveValue::UnitType::kContainerHeight:
+ case CSSPrimitiveValue::UnitType::kContainerInlineSize:
+ case CSSPrimitiveValue::UnitType::kContainerBlockSize:
+ case CSSPrimitiveValue::UnitType::kContainerMin:
+ case CSSPrimitiveValue::UnitType::kContainerMax:
+ if (!RuntimeEnabledFeatures::CSSContainerRelativeUnitsEnabled())
+ return nullptr;
+ break;
default:
return nullptr;
}
@@ -2226,6 +2235,7 @@ static CSSValue* ConsumeImageSet(CSSParserTokenRange& range,
} while (ConsumeCommaIncludingWhitespace(args));
if (!args.AtEnd())
return nullptr;
+ context.Count(WebFeature::kWebkitImageSet);
range = range_copy;
return image_set;
}
@@ -3975,7 +3985,7 @@ bool ConsumeGridTrackRepeatFunction(CSSParserTokenRange& range,
CSSParserTokenRange args = ConsumeFunction(range);
// The number of repetitions for <auto-repeat> is not important at parsing
// level because it will be computed later, let's set it to 1.
- size_t repetitions = 1;
+ wtf_size_t repetitions = 1;
is_auto_repeat = IdentMatches<CSSValueID::kAutoFill, CSSValueID::kAutoFit>(
args.Peek().Id());
CSSValueList* repeated_values;
@@ -3988,7 +3998,7 @@ bool ConsumeGridTrackRepeatFunction(CSSParserTokenRange& range,
if (!repetition)
return false;
repetitions =
- clampTo<size_t>(repetition->GetDoubleValue(), 0, kGridMaxTracks);
+ clampTo<wtf_size_t>(repetition->GetDoubleValue(), 0, kGridMaxTracks);
repeated_values = CSSValueList::CreateSpaceSeparated();
}
if (!ConsumeCommaIncludingWhitespace(args))
@@ -3997,7 +4007,7 @@ bool ConsumeGridTrackRepeatFunction(CSSParserTokenRange& range,
if (line_names)
repeated_values->Append(*line_names);
- size_t number_of_tracks = 0;
+ wtf_size_t number_of_tracks = 0;
while (!args.AtEnd()) {
CSSValue* track_size = ConsumeGridTrackSize(args, context);
if (!track_size)
@@ -4023,7 +4033,7 @@ bool ConsumeGridTrackRepeatFunction(CSSParserTokenRange& range,
repetitions = std::min(repetitions, kGridMaxTracks / number_of_tracks);
auto* integer_repeated_values =
MakeGarbageCollected<cssvalue::CSSGridIntegerRepeatValue>(repetitions);
- for (size_t i = 0; i < repeated_values->length(); ++i)
+ for (wtf_size_t i = 0; i < repeated_values->length(); ++i)
integer_repeated_values->Append(repeated_values->Item(i));
list.Append(*integer_repeated_values);
}
@@ -4042,8 +4052,8 @@ bool ConsumeGridTemplateRowsAndAreasAndColumns(bool important,
DCHECK(!template_areas);
NamedGridAreaMap grid_area_map;
- size_t row_count = 0;
- size_t column_count = 0;
+ wtf_size_t row_count = 0;
+ wtf_size_t column_count = 0;
CSSValueList* template_rows_value_list = CSSValueList::CreateSpaceSeparated();
// Persists between loop iterations so we can use the same value for
@@ -4198,8 +4208,8 @@ CSSValue* ConsumeGridTrackList(CSSParserTokenRange& range,
bool ParseGridTemplateAreasRow(const String& grid_row_names,
NamedGridAreaMap& grid_area_map,
- const size_t row_count,
- size_t& column_count) {
+ const wtf_size_t row_count,
+ wtf_size_t& column_count) {
if (grid_row_names.ContainsOnlyWhitespaceOrEmpty())
return false;
@@ -4215,7 +4225,7 @@ bool ParseGridTemplateAreasRow(const String& grid_row_names,
return false;
}
- for (size_t current_column = 0; current_column < column_count;
+ for (wtf_size_t current_column = 0; current_column < column_count;
++current_column) {
const String& grid_area_name = column_names[current_column];
@@ -4223,7 +4233,7 @@ bool ParseGridTemplateAreasRow(const String& grid_row_names,
if (grid_area_name == ".")
continue;
- size_t look_ahead_column = current_column + 1;
+ wtf_size_t look_ahead_column = current_column + 1;
while (look_ahead_column < column_count &&
column_names[look_ahead_column] == grid_area_name)
look_ahead_column++;
@@ -4870,6 +4880,43 @@ CSSValue* ParseSpacing(CSSParserTokenRange& range,
return ConsumeLength(range, context, kValueRangeAll, UnitlessQuirk::kAllow);
}
+CSSValue* ConsumeContainerName(CSSParserTokenRange& range,
+ const CSSParserContext& context) {
+ if (CSSValue* value = ConsumeIdent<CSSValueID::kNone>(range))
+ return value;
+ // TODO(crbug.com/1066390): ConsumeCustomIdent should not allow "default".
+ if (range.Peek().Id() == CSSValueID::kDefault)
+ return nullptr;
+ return ConsumeCustomIdent(range, context);
+}
+
+CSSValue* ConsumeContainerType(CSSParserTokenRange& range) {
+ if (CSSValue* value = ConsumeIdent<CSSValueID::kNone>(range))
+ return value;
+
+ CSSIdentifierValue* inline_size = nullptr;
+ CSSIdentifierValue* block_size = nullptr;
+
+ while (range.Peek().GetType() == kIdentToken) {
+ CSSValueID id = range.Peek().Id();
+ if (id == CSSValueID::kInlineSize && !inline_size) {
+ inline_size = ConsumeIdent(range);
+ } else if (id == CSSValueID::kBlockSize && !block_size) {
+ block_size = ConsumeIdent(range);
+ } else {
+ return nullptr;
+ }
+ }
+
+ CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+
+ if (inline_size)
+ list->Append(*inline_size);
+ if (block_size)
+ list->Append(*block_size);
+
+ return list;
+}
CSSValue* ConsumeSVGPaint(CSSParserTokenRange& range,
const CSSParserContext& context) {
if (range.Peek().Id() == CSSValueID::kNone)
@@ -4902,8 +4949,6 @@ UnitlessQuirk UnitlessUnlessShorthand(
bool ShouldLowerCaseCounterStyleNameOnParse(const AtomicString& name,
const CSSParserContext& context) {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
-
if (context.Mode() == kUASheetMode) {
// Names in UA sheet should be already in lower case.
DCHECK_EQ(name, name.LowerASCII());
@@ -4915,8 +4960,6 @@ bool ShouldLowerCaseCounterStyleNameOnParse(const AtomicString& name,
CSSCustomIdentValue* ConsumeCounterStyleName(CSSParserTokenRange& range,
const CSSParserContext& context) {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
-
CSSParserTokenRange original_range = range;
// <counter-style-name> is a <custom-ident> that is not an ASCII
@@ -4946,7 +4989,11 @@ AtomicString ConsumeCounterStyleNameInPrelude(CSSParserTokenRange& prelude,
if (context.Mode() != kUASheetMode) {
if (name_token.Id() == CSSValueID::kDecimal ||
- name_token.Id() == CSSValueID::kDisc)
+ name_token.Id() == CSSValueID::kDisc ||
+ name_token.Id() == CSSValueID::kCircle ||
+ name_token.Id() == CSSValueID::kSquare ||
+ name_token.Id() == CSSValueID::kDisclosureOpen ||
+ name_token.Id() == CSSValueID::kDisclosureClosed)
return g_null_atom;
}
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 2991b6b2aaf..4e704134764 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
@@ -384,8 +384,8 @@ CSSValue* ConsumeGridTrackList(CSSParserTokenRange&,
TrackListType);
bool ParseGridTemplateAreasRow(const WTF::String& grid_row_names,
NamedGridAreaMap&,
- const size_t row_count,
- size_t& column_count);
+ const wtf_size_t row_count,
+ wtf_size_t& column_count);
CSSValue* ConsumeGridTemplatesRowsOrColumns(CSSParserTokenRange&,
const CSSParserContext&);
bool ConsumeGridItemPositionShorthand(bool important,
@@ -453,6 +453,9 @@ CSSValue* ConsumeBorderWidth(CSSParserTokenRange&,
CSSValue* ConsumeSVGPaint(CSSParserTokenRange&, const CSSParserContext&);
CSSValue* ParseSpacing(CSSParserTokenRange&, const CSSParserContext&);
+CSSValue* ConsumeContainerName(CSSParserTokenRange&, const CSSParserContext&);
+CSSValue* ConsumeContainerType(CSSParserTokenRange&);
+
UnitlessQuirk UnitlessUnlessShorthand(const CSSParserLocalContext&);
// https://drafts.csswg.org/css-counter-styles-3/#typedef-counter-style-name
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_property.cc b/chromium/third_party/blink/renderer/core/css/properties/css_property.cc
index ac97989bd73..f331ba3210d 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_property.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_property.cc
@@ -4,10 +4,10 @@
#include "third_party/blink/renderer/core/css/properties/css_property.h"
-#include "base/stl_util.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h"
#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
+#include "third_party/blink/renderer/core/css/properties/longhands/variable.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
@@ -23,6 +23,20 @@ const CSSProperty& CSSProperty::Get(CSSPropertyID id) {
return To<CSSProperty>(CSSUnresolvedProperty::GetNonAliasProperty(id));
}
+// The correctness of static functions that operate on CSSPropertyName is
+// ensured by:
+//
+// - DCHECKs in the CustomProperty constructor.
+// - CSSPropertyTest.StaticVariableInstanceFlags
+
+bool CSSProperty::IsShorthand(const CSSPropertyName& name) {
+ return !name.IsCustomProperty() && Get(name.Id()).IsShorthand();
+}
+
+bool CSSProperty::IsRepeated(const CSSPropertyName& name) {
+ return !name.IsCustomProperty() && Get(name.Id()).IsRepeated();
+}
+
std::unique_ptr<CrossThreadStyleValue>
CSSProperty::CrossThreadStyleValueFromComputedStyle(
const ComputedStyle& computed_style,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_property.h b/chromium/third_party/blink/renderer/core/css/properties/css_property.h
index 8021a803bb4..b46b95cb1df 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_property.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_property.h
@@ -29,6 +29,9 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
static const CSSProperty& Get(CSSPropertyID);
+ static bool IsShorthand(const CSSPropertyName&);
+ static bool IsRepeated(const CSSPropertyName&);
+
// For backwards compatibility when passing around CSSUnresolvedProperty
// references. In case we need to call a function that hasn't been converted
// to using property classes yet.
@@ -59,6 +62,7 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
bool AffectsFont() const { return flags_ & kAffectsFont; }
bool IsBackground() const { return flags_ & kBackground; }
bool IsBorder() const { return flags_ & kBorder; }
+ bool IsBorderRadius() const { return flags_ & kBorderRadius; }
bool TakesTreeScopedValue() const { return flags_ & kTreeScopedValue; }
bool IsInLogicalPropertyGroup() const {
return flags_ & kInLogicalPropertyGroup;
@@ -138,18 +142,19 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
// inline-size is a surrogate for either width or height.
kSurrogate = 1 << 13,
kAffectsFont = 1 << 14,
- // If the author specifies any background or border property on an UI
- // element, the native appearance must be disabled.
+ // If the author specifies any background, border or border-radius property
+ // on an UI element, the native appearance must be disabled.
kBackground = 1 << 15,
kBorder = 1 << 16,
+ kBorderRadius = 1 << 17,
// Set if the property values are tree-scoped references.
- kTreeScopedValue = 1 << 17,
+ kTreeScopedValue = 1 << 18,
// https://drafts.csswg.org/css-pseudo-4/#highlight-styling
- kValidForHighlight = 1 << 18,
+ kValidForHighlight = 1 << 19,
// https://drafts.csswg.org/css-logical/#logical-property-group
- kInLogicalPropertyGroup = 1 << 19,
+ kInLogicalPropertyGroup = 1 << 20,
// https://drafts.csswg.org/css-pseudo-4/#first-line-styling
- kValidForFirstLine = 1 << 20,
+ kValidForFirstLine = 1 << 21,
};
constexpr CSSProperty(CSSPropertyID property_id,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc b/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc
index 196be04f955..66d7dd0426f 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc
@@ -145,4 +145,9 @@ TEST_F(CSSPropertyTest, PairsWithIdenticalValues) {
EXPECT_NE(*border_radius, *perspective_origin);
}
+TEST_F(CSSPropertyTest, StaticVariableInstanceFlags) {
+ EXPECT_FALSE(GetCSSPropertyVariable().IsShorthand());
+ EXPECT_FALSE(GetCSSPropertyVariable().IsRepeated());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
index af51b0aeb7d..d70280e4326 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
@@ -39,7 +39,10 @@ CustomProperty::CustomProperty(const AtomicString& name,
const PropertyRegistration* registration)
: Variable(InheritedFlag(registration)),
name_(name),
- registration_(registration) {}
+ registration_(registration) {
+ DCHECK_EQ(IsShorthand(), CSSProperty::IsShorthand(GetCSSPropertyName()));
+ DCHECK_EQ(IsRepeated(), CSSProperty::IsRepeated(GetCSSPropertyName()));
+}
const AtomicString& CustomProperty::GetPropertyNameAtomicString() const {
return name_;
@@ -176,7 +179,7 @@ const CSSValue* CustomProperty::CSSValueFromComputedStyleInternal(
if (!data)
return nullptr;
- return MakeGarbageCollected<CSSCustomPropertyDeclaration>(name_, data);
+ return MakeGarbageCollected<CSSCustomPropertyDeclaration>(data);
}
const CSSValue* CustomProperty::ParseUntyped(
@@ -185,8 +188,7 @@ const CSSValue* CustomProperty::ParseUntyped(
const CSSParserLocalContext& local_context) const {
// TODO(crbug.com/661854): Pass through the original string when we have it.
return CSSVariableParser::ParseDeclarationValue(
- name_, {range, StringView()}, local_context.IsAnimationTainted(),
- context);
+ {range, StringView()}, local_context.IsAnimationTainted(), context);
}
const CSSValue* CustomProperty::ParseTyped(
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
index 2666dc84bd5..df1e6cbdf39 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
@@ -24,9 +24,7 @@ class CORE_EXPORT CustomProperty : public Variable {
DISALLOW_NEW();
public:
- CustomProperty()
- : CustomProperty(AtomicString(),
- static_cast<const PropertyRegistration*>(nullptr)) {}
+ CustomProperty() = default;
CustomProperty(const AtomicString& name, const Document&);
CustomProperty(const AtomicString& name, const PropertyRegistry*);
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 99473f58186..65d6ca3f9d9 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -1610,6 +1610,7 @@ const CSSValue* ColorScheme::ParseSingleValue(
if (range.Peek().Id() == CSSValueID::kNormal)
return css_parsing_utils::ConsumeIdent(range);
+ CSSValue* only = nullptr;
CSSValueList* values = CSSValueList::CreateSpaceSeparated();
do {
CSSValueID id = range.Peek().Id();
@@ -1621,14 +1622,29 @@ const CSSValue* ColorScheme::ParseSingleValue(
return nullptr;
}
CSSValue* value =
- css_parsing_utils::ConsumeIdent<CSSValueID::kDark, CSSValueID::kLight>(
- range);
+ css_parsing_utils::ConsumeIdent<CSSValueID::kDark, CSSValueID::kLight,
+ CSSValueID::kOnly>(range);
+ if (id == CSSValueID::kOnly &&
+ RuntimeEnabledFeatures::CSSColorSchemeOnlyEnabled()) {
+ if (only)
+ return nullptr;
+ if (values->length()) {
+ values->Append(*value);
+ return values;
+ }
+ only = value;
+ continue;
+ }
if (!value)
value = css_parsing_utils::ConsumeCustomIdent(range, context);
if (!value)
return nullptr;
values->Append(*value);
} while (!range.AtEnd());
+ if (!values->length())
+ return nullptr;
+ if (only)
+ values->Append(*only);
return values;
}
@@ -1652,11 +1668,13 @@ const CSSValue* ColorScheme::InitialValue() const {
void ColorScheme::ApplyInitial(StyleResolverState& state) const {
state.Style()->SetColorScheme(Vector<AtomicString>());
state.Style()->SetDarkColorScheme(false);
+ state.Style()->SetColorSchemeOnly(false);
}
void ColorScheme::ApplyInherit(StyleResolverState& state) const {
state.Style()->SetColorScheme(state.ParentStyle()->ColorScheme());
state.Style()->SetDarkColorScheme(state.ParentStyle()->DarkColorScheme());
+ state.Style()->SetColorSchemeOnly(state.ParentStyle()->ColorSchemeOnly());
}
void ColorScheme::ApplyValue(StyleResolverState& state,
@@ -1665,28 +1683,41 @@ void ColorScheme::ApplyValue(StyleResolverState& state,
DCHECK(identifier_value->GetValueID() == CSSValueID::kNormal);
state.Style()->SetColorScheme(Vector<AtomicString>());
state.Style()->SetDarkColorScheme(false);
+ state.Style()->SetColorSchemeOnly(false);
} else if (const auto* scheme_list = DynamicTo<CSSValueList>(value)) {
bool prefers_dark =
state.GetDocument().GetStyleEngine().GetPreferredColorScheme() ==
mojom::blink::PreferredColorScheme::kDark;
bool has_dark = false;
bool has_light = false;
+ bool has_only = false;
Vector<AtomicString> color_schemes;
for (auto& item : *scheme_list) {
if (const auto* custom_ident = DynamicTo<CSSCustomIdentValue>(*item)) {
color_schemes.push_back(custom_ident->Value());
} else if (const auto* ident = DynamicTo<CSSIdentifierValue>(*item)) {
color_schemes.push_back(ident->CssText());
- if (ident->GetValueID() == CSSValueID::kDark)
- has_dark = true;
- else if (ident->GetValueID() == CSSValueID::kLight)
- has_light = true;
+ switch (ident->GetValueID()) {
+ case CSSValueID::kDark:
+ has_dark = true;
+ break;
+ case CSSValueID::kLight:
+ has_light = true;
+ break;
+ case CSSValueID::kOnly:
+ has_only = true;
+ break;
+ default:
+ break;
+ }
} else {
NOTREACHED();
}
}
state.Style()->SetColorScheme(color_schemes);
state.Style()->SetDarkColorScheme(has_dark && (!has_light || prefers_dark));
+ if (RuntimeEnabledFeatures::CSSColorSchemeOnlyEnabled())
+ state.Style()->SetColorSchemeOnly(has_only);
if (has_dark) {
// Record kColorSchemeDarkSupportedOnRoot if dark is present (though dark
@@ -1885,19 +1916,19 @@ const CSSValue* Contain::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(CSSValueID::kContent);
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
- if (style.ContainsSize()) {
+ if ((style.Contain() & kContainsSize) == kContainsSize) {
list->Append(*CSSIdentifierValue::Create(CSSValueID::kSize));
} else {
- if (style.ContainsInlineSize())
+ if (style.Contain() & kContainsInlineSize)
list->Append(*CSSIdentifierValue::Create(CSSValueID::kInlineSize));
- else if (style.ContainsBlockSize())
+ else if (style.Contain() & kContainsBlockSize)
list->Append(*CSSIdentifierValue::Create(CSSValueID::kBlockSize));
}
- if (style.ContainsLayout())
+ if (style.Contain() & kContainsLayout)
list->Append(*CSSIdentifierValue::Create(CSSValueID::kLayout));
- if (style.ContainsStyle())
+ if (style.Contain() & kContainsStyle)
list->Append(*CSSIdentifierValue::Create(CSSValueID::kStyle));
- if (style.ContainsPaint())
+ if (style.Contain() & kContainsPaint)
list->Append(*CSSIdentifierValue::Create(CSSValueID::kPaint));
DCHECK(list->length());
return list;
@@ -1938,6 +1969,43 @@ const CSSValue* ContainIntrinsicSize::CSSValueFromComputedStyleInternal(
CSSValuePair::kDropIdenticalValues);
}
+const CSSValue* ContainerName::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return css_parsing_utils::ConsumeContainerName(range, context);
+}
+
+const CSSValue* ContainerName::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const LayoutObject* layout_object,
+ bool allow_visited_style) const {
+ if (style.ContainerName().IsNull())
+ return CSSIdentifierValue::Create(CSSValueID::kNone);
+ return MakeGarbageCollected<CSSCustomIdentValue>(style.ContainerName());
+}
+
+const CSSValue* ContainerType::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return css_parsing_utils::ConsumeContainerType(range);
+}
+
+const CSSValue* ContainerType::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const LayoutObject* layout_object,
+ bool allow_visited_style) const {
+ if (style.ContainerType() == kContainerTypeNone)
+ return CSSIdentifierValue::Create(CSSValueID::kNone);
+ CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+ if (style.ContainerType() & kContainerTypeInlineSize)
+ list->Append(*CSSIdentifierValue::Create(CSSValueID::kInlineSize));
+ if (style.ContainerType() & kContainerTypeBlockSize)
+ list->Append(*CSSIdentifierValue::Create(CSSValueID::kBlockSize));
+ return list;
+}
+
namespace {
CSSValue* ConsumeAttr(CSSParserTokenRange args,
@@ -1980,24 +2048,14 @@ CSSValue* ConsumeCounterContent(CSSParserTokenRange args,
CSSCustomIdentValue* list_style = nullptr;
if (css_parsing_utils::ConsumeCommaIncludingWhitespace(args)) {
- if (!RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- CSSValueID id = args.Peek().Id();
- if ((id != CSSValueID::kNone &&
- (id < CSSValueID::kDisc || id > CSSValueID::kKatakanaIroha)))
- return nullptr;
- list_style = MakeGarbageCollected<CSSCustomIdentValue>(
- AtomicString(getValueName(id)));
+ // Note: CSS3 spec doesn't allow 'none' but CSS2.1 allows it. We currently
+ // allow it for backward compatibility.
+ // See https://github.com/w3c/csswg-drafts/issues/5795 for details.
+ if (args.Peek().Id() == CSSValueID::kNone) {
+ list_style = MakeGarbageCollected<CSSCustomIdentValue>("none");
args.ConsumeIncludingWhitespace();
} else {
- // Note: CSS3 spec doesn't allow 'none' but CSS2.1 allows it. We currently
- // allow it for backward compatibility.
- // See https://github.com/w3c/csswg-drafts/issues/5795 for details.
- if (args.Peek().Id() == CSSValueID::kNone) {
- list_style = MakeGarbageCollected<CSSCustomIdentValue>("none");
- args.ConsumeIncludingWhitespace();
- } else {
- list_style = css_parsing_utils::ConsumeCounterStyleName(args, context);
- }
+ list_style = css_parsing_utils::ConsumeCounterStyleName(args, context);
}
} else {
list_style = MakeGarbageCollected<CSSCustomIdentValue>("decimal");
@@ -2646,8 +2704,9 @@ const CSSValue* FlexBasis::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext&) const {
- // FIXME: Support intrinsic dimensions too.
- if (range.Peek().Id() == CSSValueID::kAuto)
+ if (css_parsing_utils::IdentMatches<
+ CSSValueID::kAuto, CSSValueID::kContent, CSSValueID::kMinContent,
+ CSSValueID::kMaxContent, CSSValueID::kFitContent>(range.Peek().Id()))
return css_parsing_utils::ConsumeIdent(range);
return css_parsing_utils::ConsumeLengthOrPercent(range, context,
kValueRangeNonNegative);
@@ -3275,8 +3334,8 @@ const CSSValue* GridTemplateAreas::ParseSingleValue(
return css_parsing_utils::ConsumeIdent(range);
NamedGridAreaMap grid_area_map;
- size_t row_count = 0;
- size_t column_count = 0;
+ wtf_size_t row_count = 0;
+ wtf_size_t column_count = 0;
while (range.Peek().GetType() == kStringToken) {
if (!css_parsing_utils::ParseGridTemplateAreasRow(
@@ -4259,19 +4318,9 @@ const CSSValue* ListStyleType::ParseSingleValue(
if (auto* none = css_parsing_utils::ConsumeIdent<CSSValueID::kNone>(range))
return none;
- if (!RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- if (auto* ident = css_parsing_utils::ConsumeIdent(range)) {
- CSSValueID value_id = ident->GetValueID();
- if (value_id < CSSValueID::kDisc || value_id > CSSValueID::kKatakanaIroha)
- return nullptr;
- return MakeGarbageCollected<CSSCustomIdentValue>(
- AtomicString(getValueName(value_id)));
- }
- } else {
- if (auto* counter_style_name =
- css_parsing_utils::ConsumeCounterStyleName(range, context))
- return counter_style_name;
- }
+ if (auto* counter_style_name =
+ css_parsing_utils::ConsumeCounterStyleName(range, context))
+ return counter_style_name;
return css_parsing_utils::ConsumeString(range);
}
@@ -4280,15 +4329,15 @@ const CSSValue* ListStyleType::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const LayoutObject*,
bool allow_visited_style) const {
- if (!style.GetListStyleType())
+ if (!style.ListStyleType())
return CSSIdentifierValue::Create(CSSValueID::kNone);
- if (style.GetListStyleType()->IsString()) {
+ if (style.ListStyleType()->IsString()) {
return MakeGarbageCollected<CSSStringValue>(
- style.GetListStyleType()->GetStringValue());
+ style.ListStyleType()->GetStringValue());
}
// TODO(crbug.com/687225): Return a scoped CSSValue?
return MakeGarbageCollected<CSSCustomIdentValue>(
- style.GetListStyleType()->GetCounterStyleName());
+ style.ListStyleType()->GetCounterStyleName());
}
void ListStyleType::ApplyInitial(StyleResolverState& state) const {
@@ -4297,7 +4346,7 @@ void ListStyleType::ApplyInitial(StyleResolverState& state) const {
}
void ListStyleType::ApplyInherit(StyleResolverState& state) const {
- state.Style()->SetListStyleType(state.ParentStyle()->GetListStyleType());
+ state.Style()->SetListStyleType(state.ParentStyle()->ListStyleType());
}
void ListStyleType::ApplyValue(StyleResolverState& state,
@@ -5357,20 +5406,18 @@ const CSSValue* Perspective::ParseSingleValue(
if (range.Peek().Id() == CSSValueID::kNone)
return css_parsing_utils::ConsumeIdent(range);
CSSPrimitiveValue* parsed_value =
- css_parsing_utils::ConsumeLength(range, context, kValueRangeAll);
+ css_parsing_utils::ConsumeLength(range, context, kValueRangeNonNegative);
bool use_legacy_parsing = localContext.UseAliasParsing();
if (!parsed_value && use_legacy_parsing) {
double perspective;
- if (!css_parsing_utils::ConsumeNumberRaw(range, context, perspective))
+ if (!css_parsing_utils::ConsumeNumberRaw(range, context, perspective) ||
+ perspective < 0.0)
return nullptr;
context.Count(WebFeature::kUnitlessPerspectiveInPerspectiveProperty);
parsed_value = CSSNumericLiteralValue::Create(
perspective, CSSPrimitiveValue::UnitType::kPixels);
}
- if (parsed_value &&
- (parsed_value->IsCalculated() || parsed_value->GetDoubleValue() > 0))
- return parsed_value;
- return nullptr;
+ return parsed_value;
}
const CSSValue* Perspective::CSSValueFromComputedStyleInternal(
@@ -5697,7 +5744,7 @@ const CSSValue* Scale::CSSValueFromComputedStyleInternal(
}
// https://www.w3.org/TR/css-overflow-4
-// auto | [ stable | always ] && both? && force?
+// auto | stable && both-edges?
const CSSValue* ScrollbarGutter::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -5708,37 +5755,30 @@ const CSSValue* ScrollbarGutter::ParseSingleValue(
if (auto* value = css_parsing_utils::ConsumeIdent<CSSValueID::kAuto>(range))
return value;
- CSSIdentifierValue* stable_or_always = nullptr;
- CSSIdentifierValue* both = nullptr;
- CSSIdentifierValue* force = nullptr;
+ CSSIdentifierValue* stable = nullptr;
+ CSSIdentifierValue* both_edges = nullptr;
while (!range.AtEnd()) {
- if (!stable_or_always) {
- if ((stable_or_always =
- css_parsing_utils::ConsumeIdent<CSSValueID::kStable,
- CSSValueID::kAlways>(range)))
+ if (!stable) {
+ if ((stable =
+ css_parsing_utils::ConsumeIdent<CSSValueID::kStable>(range)))
continue;
}
CSSValueID id = range.Peek().Id();
- if (id == CSSValueID::kBoth && !both)
- both = css_parsing_utils::ConsumeIdent(range);
- else if (id == CSSValueID::kForce && !force)
- force = css_parsing_utils::ConsumeIdent(range);
+ if (id == CSSValueID::kBothEdges && !both_edges)
+ both_edges = css_parsing_utils::ConsumeIdent(range);
else
return nullptr;
}
- if (!stable_or_always)
+ if (!stable)
return nullptr;
- if (both || force) {
+ if (both_edges) {
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
- list->Append(*stable_or_always);
- if (both)
- list->Append(*both);
- if (force)
- list->Append(*force);
+ list->Append(*stable);
+ list->Append(*both_edges);
return list;
}
- return stable_or_always;
+ return stable;
}
const CSSValue* ScrollbarGutter::CSSValueFromComputedStyleInternal(
@@ -5749,23 +5789,19 @@ const CSSValue* ScrollbarGutter::CSSValueFromComputedStyleInternal(
if (scrollbar_gutter == kScrollbarGutterAuto)
return CSSIdentifierValue::Create(CSSValueID::kAuto);
- DCHECK(scrollbar_gutter & (kScrollbarGutterStable | kScrollbarGutterAlways));
+ DCHECK(scrollbar_gutter & kScrollbarGutterStable);
- CSSValue* main_value = nullptr;
+ CSSValue* stable = nullptr;
if (scrollbar_gutter & kScrollbarGutterStable)
- main_value = CSSIdentifierValue::Create(CSSValueID::kStable);
- else
- main_value = CSSIdentifierValue::Create(CSSValueID::kAlways);
+ stable = CSSIdentifierValue::Create(CSSValueID::kStable);
- if (!(scrollbar_gutter & (kScrollbarGutterBoth | kScrollbarGutterForce)))
- return main_value;
+ if (!(scrollbar_gutter & kScrollbarGutterBothEdges))
+ return stable;
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
- list->Append(*main_value);
- if (scrollbar_gutter & kScrollbarGutterBoth)
- list->Append(*CSSIdentifierValue::Create(kScrollbarGutterBoth));
- if (scrollbar_gutter & kScrollbarGutterForce)
- list->Append(*CSSIdentifierValue::Create(kScrollbarGutterForce));
+ list->Append(*stable);
+ if (scrollbar_gutter & kScrollbarGutterBothEdges)
+ list->Append(*CSSIdentifierValue::Create(kScrollbarGutterBothEdges));
return list;
}
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
index 485b157c49a..0d4f9a2da7d 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/css/css_content_distribution_value.h"
-#include "third_party/blink/renderer/core/css/css_font_family_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_initial_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
#include "third_party/blink/renderer/core/css/css_property_value.h"
#include "third_party/blink/renderer/core/css/css_value_pair.h"
@@ -23,7 +23,6 @@
#include "third_party/blink/renderer/core/css/properties/shorthands.h"
#include "third_party/blink/renderer/core/css/zoom_adjusted_pixel_value.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -868,6 +867,46 @@ const CSSValue* Columns::CSSValueFromComputedStyleInternal(
columnsShorthand(), style, layout_object, allow_visited_style);
}
+bool Container::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ const CSSValue* type = css_parsing_utils::ConsumeContainerType(range);
+ if (!type)
+ return false;
+
+ const CSSValue* name = CSSIdentifierValue::Create(CSSValueID::kNone);
+ if (css_parsing_utils::ConsumeSlashIncludingWhitespace(range)) {
+ if (!(name = css_parsing_utils::ConsumeContainerName(range, context)))
+ return false;
+ }
+
+ if (!range.AtEnd())
+ return false;
+
+ css_parsing_utils::AddProperty(
+ CSSPropertyID::kContainerType, CSSPropertyID::kContainer, *type,
+ important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
+ properties);
+
+ css_parsing_utils::AddProperty(
+ CSSPropertyID::kContainerName, CSSPropertyID::kContainer, *name,
+ important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
+ properties);
+
+ return true;
+}
+
+const CSSValue* Container::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const LayoutObject* layout_object,
+ bool allow_visited_style) const {
+ return ComputedStyleUtils::ValuesForContainerShorthand(style, layout_object,
+ allow_visited_style);
+}
+
bool Flex::ParseShorthand(bool important,
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -904,8 +943,12 @@ bool Flex::ParseShorthand(bool important,
return false;
}
} else if (!flex_basis) {
- if (range.Peek().Id() == CSSValueID::kAuto)
+ if (css_parsing_utils::IdentMatches<
+ CSSValueID::kAuto, CSSValueID::kContent,
+ CSSValueID::kMinContent, CSSValueID::kMaxContent,
+ CSSValueID::kFitContent>(range.Peek().Id())) {
flex_basis = css_parsing_utils::ConsumeIdent(range);
+ }
if (!flex_basis) {
flex_basis = css_parsing_utils::ConsumeLengthOrPercent(
range, context, kValueRangeNonNegative);
@@ -979,69 +1022,14 @@ bool ConsumeSystemFont(bool important,
CSSParserTokenRange& range,
HeapVector<CSSPropertyValue, 256>& properties) {
CSSValueID system_font_id = range.ConsumeIncludingWhitespace().Id();
- DCHECK_GE(system_font_id, CSSValueID::kCaption);
- DCHECK_LE(system_font_id, CSSValueID::kStatusBar);
+ DCHECK(CSSParserFastPaths::IsValidSystemFont(system_font_id));
if (!range.AtEnd())
return false;
- FontSelectionValue font_slope = NormalSlopeValue();
- FontSelectionValue font_weight = NormalWeightValue();
- float font_size = 0;
- AtomicString font_family;
- LayoutThemeFontProvider::SystemFont(system_font_id, font_slope, font_weight,
- font_size, font_family);
-
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontStyle, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(font_slope == ItalicSlopeValue()
- ? CSSValueID::kItalic
- : CSSValueID::kNormal),
- important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
- properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontWeight, CSSPropertyID::kFont,
- *CSSNumericLiteralValue::Create(font_weight,
- CSSPrimitiveValue::UnitType::kNumber),
- important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
- properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontSize, CSSPropertyID::kFont,
- *CSSNumericLiteralValue::Create(font_size,
- CSSPrimitiveValue::UnitType::kPixels),
- important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
- properties);
-
- CSSValueList* font_family_list = CSSValueList::CreateCommaSeparated();
- font_family_list->Append(*CSSFontFamilyValue::Create(font_family));
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontFamily, CSSPropertyID::kFont, *font_family_list,
- important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
+ css_parsing_utils::AddExpandedPropertyForValue(
+ CSSPropertyID::kFont,
+ *cssvalue::CSSPendingSystemFontValue::Create(system_font_id), important,
properties);
-
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontStretch, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
- css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontVariantCaps, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
- css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontVariantLigatures, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
- css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontVariantNumeric, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
- css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kFontVariantEastAsian, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
- css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
- css_parsing_utils::AddProperty(
- CSSPropertyID::kLineHeight, CSSPropertyID::kFont,
- *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
- css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
return true;
}
@@ -1186,8 +1174,7 @@ bool Font::ParseShorthand(bool important,
const CSSParserLocalContext&,
HeapVector<CSSPropertyValue, 256>& properties) const {
const CSSParserToken& token = range.Peek();
- if (token.Id() >= CSSValueID::kCaption &&
- token.Id() <= CSSValueID::kStatusBar)
+ if (CSSParserFastPaths::IsValidSystemFont(token.Id()))
return ConsumeSystemFont(important, range, properties);
return ConsumeFont(important, range, context, properties);
}
diff --git a/chromium/third_party/blink/renderer/core/css/property_registry.cc b/chromium/third_party/blink/renderer/core/css/property_registry.cc
index 226faaf9dfd..6150a8336f1 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registry.cc
+++ b/chromium/third_party/blink/renderer/core/css/property_registry.cc
@@ -32,9 +32,10 @@ const PropertyRegistration* PropertyRegistry::Registration(
// the registration from CSS.registerProperty must win.
//
// https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
- if (const auto* registration = registered_properties_.at(name))
+ if (const auto* registration =
+ registered_properties_.DeprecatedAtOrEmptyValue(name))
return registration;
- return declared_properties_.at(name);
+ return declared_properties_.DeprecatedAtOrEmptyValue(name);
}
bool PropertyRegistry::IsEmpty() const {
diff --git a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
index 5ec29a3695b..4fa775454ad 100644
--- a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
+++ b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -204,7 +204,7 @@ void RemoteFontFaceSource::NotifyFinished(Resource* resource) {
mojom::ConsoleMessageSource::kOther,
mojom::ConsoleMessageLevel::kWarning,
"Failed to decode downloaded font: " + font->Url().ElidedString()));
- if (font->OtsParsingMessage().length() > 1) {
+ if (!font->OtsParsingMessage().IsEmpty()) {
execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kOther,
mojom::ConsoleMessageLevel::kWarning,
@@ -423,6 +423,10 @@ void RemoteFontFaceSource::FontLoadHistograms::LongLimitExceeded() {
MaySetDataSource(kFromNetwork);
}
+bool RemoteFontFaceSource::IsPendingDataUrl() const {
+ return GetResource() && GetResource()->Url().ProtocolIsData();
+}
+
void RemoteFontFaceSource::FontLoadHistograms::RecordFallbackTime() {
if (blank_paint_time_.is_null() || blank_paint_time_recorded_)
return;
diff --git a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
index c6720151699..64ac297d499 100644
--- a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
+++ b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
@@ -34,6 +34,8 @@ class RemoteFontFaceSource final : public CSSFontFaceSource,
String GetURL() const override { return url_; }
+ bool IsPendingDataUrl() const override;
+
const FontCustomPlatformData* GetCustomPlaftormData() const override {
return custom_font_data_.get();
}
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.cc
index d801816989d..1c7e39d5036 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.cc
@@ -56,7 +56,7 @@ CascadeFilter AmendFilter(CascadeFilter filter,
CascadeExpansion::CascadeExpansion(const MatchedProperties& matched_properties,
const Document& document,
CascadeFilter filter,
- size_t matched_properties_index)
+ wtf_size_t matched_properties_index)
: document_(document),
matched_properties_(matched_properties),
size_(matched_properties.properties->PropertyCount()),
@@ -192,7 +192,7 @@ void CascadeExpansion::AdvanceAll() {
}
CSSPropertyValueSet::PropertyReference CascadeExpansion::PropertyAt(
- size_t index) const {
+ wtf_size_t index) const {
DCHECK(!AtEnd());
return matched_properties_.properties->PropertyAt(index_);
}
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.h b/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.h
index 34c6145e135..9f1f908eebd 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.h
@@ -21,11 +21,11 @@ inline uint32_t EncodeMatchResultPosition(uint16_t block,
return (static_cast<uint32_t>(block) << 16) | declaration;
}
-inline size_t DecodeMatchedPropertiesIndex(uint32_t position) {
+inline wtf_size_t DecodeMatchedPropertiesIndex(uint32_t position) {
return (position >> 16) & 0xFFFF;
}
-inline size_t DecodeDeclarationIndex(uint32_t position) {
+inline wtf_size_t DecodeDeclarationIndex(uint32_t position) {
return position & 0xFFFF;
}
@@ -69,15 +69,15 @@ class CORE_EXPORT CascadeExpansion {
public:
// CascadeExpansion objects which exceed these limits will emit nothing.
- static constexpr size_t kMaxDeclarationIndex =
+ static constexpr wtf_size_t kMaxDeclarationIndex =
std::numeric_limits<uint16_t>::max();
- static constexpr size_t kMaxMatchedPropertiesIndex =
+ static constexpr wtf_size_t kMaxMatchedPropertiesIndex =
std::numeric_limits<uint16_t>::max();
CascadeExpansion(const MatchedProperties&,
const Document&,
CascadeFilter,
- size_t matched_properties_index);
+ wtf_size_t matched_properties_index);
// We need an explicit copy constructor, since CascadeExpansion has self-
// pointers.
CascadeExpansion(const CascadeExpansion& o);
@@ -111,7 +111,7 @@ class CORE_EXPORT CascadeExpansion {
bool AdvanceVisited();
void AdvanceAll();
- CSSPropertyValueSet::PropertyReference PropertyAt(size_t) const;
+ CSSPropertyValueSet::PropertyReference PropertyAt(wtf_size_t) const;
const Document& document_;
State state_ = State::kInit;
@@ -128,11 +128,11 @@ class CORE_EXPORT CascadeExpansion {
//
// Note that this is initialized to ~0 such that the first call to Next()
// (done by the constructor) will produce ~0+1 = 0.
- size_t index_ = std::numeric_limits<size_t>::max();
- size_t size_;
+ wtf_size_t index_ = std::numeric_limits<wtf_size_t>::max();
+ wtf_size_t size_;
CascadeFilter filter_;
- const size_t matched_properties_index_;
+ const wtf_size_t matched_properties_index_;
// The id/property of the current "virtual" declaration. In other words,
// the id/property will be updated when expanding 'all', etc.
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc
index a45487282f4..42c0229ae36 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc
@@ -47,7 +47,7 @@ const CSSPropertyID kVisitedPropertySamples[] = {
class CascadeExpansionTest : public PageTestBase {
public:
CascadeExpansion ExpansionAt(const MatchResult& result,
- size_t i,
+ wtf_size_t i,
CascadeFilter filter = CascadeFilter()) {
return CascadeExpansion(result.GetMatchedProperties()[i], GetDocument(),
filter, i);
@@ -717,7 +717,7 @@ TEST_F(CascadeExpansionTest, Position) {
}
TEST_F(CascadeExpansionTest, MatchedPropertiesLimit) {
- constexpr size_t max = std::numeric_limits<uint16_t>::max();
+ constexpr wtf_size_t max = std::numeric_limits<uint16_t>::max();
static_assert(CascadeExpansion::kMaxMatchedPropertiesIndex == max,
"Unexpected max. If the limit increased, evaluate whether it "
@@ -726,12 +726,12 @@ TEST_F(CascadeExpansionTest, MatchedPropertiesLimit) {
auto* set = ParseDeclarationBlock("left:1px");
MatchResult result;
- for (size_t i = 0; i < max + 3; ++i)
+ for (wtf_size_t i = 0; i < max + 3; ++i)
result.AddMatchedProperties(set);
ASSERT_EQ(max + 3u, result.GetMatchedProperties().size());
- for (size_t i = 0; i < max + 1; ++i)
+ for (wtf_size_t i = 0; i < max + 1; ++i)
EXPECT_FALSE(ExpansionAt(result, i).AtEnd());
// The indices beyond the max should not yield anything.
@@ -740,7 +740,7 @@ TEST_F(CascadeExpansionTest, MatchedPropertiesLimit) {
}
TEST_F(CascadeExpansionTest, MatchedDeclarationsLimit) {
- constexpr size_t max = std::numeric_limits<uint16_t>::max();
+ constexpr wtf_size_t max = std::numeric_limits<uint16_t>::max();
static_assert(CascadeExpansion::kMaxDeclarationIndex == max,
"Unexpected max. If the limit increased, evaluate whether it "
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc
index 10c56197870..91ac52301b7 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc
@@ -48,7 +48,7 @@ inline CascadePriority* FindNative(const CSSPropertyName& name,
inline CascadePriority AtCustom(const CSSPropertyName& name,
const CascadeMap::CustomMap& map) {
- return map.at(name);
+ return map.DeprecatedAtOrEmptyValue(name);
}
inline CascadePriority AtNative(const CSSPropertyName& name,
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc
index c2d0af1e462..386ddb38865 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc
@@ -12,13 +12,13 @@
namespace blink {
namespace {
-CascadePriority UaPriority(size_t position) {
+CascadePriority UaPriority(wtf_size_t position) {
return CascadePriority(CascadeOrigin::kUserAgent, false, 0, position);
}
-CascadePriority UserPriority(size_t position) {
+CascadePriority UserPriority(wtf_size_t position) {
return CascadePriority(CascadeOrigin::kUser, false, 0, position);
}
-CascadePriority AuthorPriority(size_t position) {
+CascadePriority AuthorPriority(wtf_size_t position) {
return CascadePriority(CascadeOrigin::kAuthor, false, 0, position);
}
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
index d56194ea412..79559b71f2b 100644
--- 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
@@ -50,7 +50,7 @@ TEST(CSSVariableDataTest, Serialize) {
}
TEST(CSSVariableDataTest, SerializeSpecialCases) {
- const String replacement_character_string = String(&kReplacementCharacter, 1);
+ const String replacement_character_string(&kReplacementCharacter, 1u);
const std::pair<String, String> test_cases[] = {
{"value\\", "value" + replacement_character_string},
{"\"value\\", "\"value\""},
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/element_resolve_context.h b/chromium/third_party/blink/renderer/core/css/resolver/element_resolve_context.h
index 43503c963a6..c65c69fc54f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/element_resolve_context.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/element_resolve_context.h
@@ -24,6 +24,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_ELEMENT_RESOLVE_CONTEXT_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/style/computed_style_constants.h"
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 0d3f61763e0..46bd4fb6200 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
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/css/resolver/element_style_resources.h"
+#include "third_party/blink/renderer/core/css/css_crossfade_value.h"
#include "third_party/blink/renderer/core/css/css_gradient_value.h"
#include "third_party/blink/renderer/core/css/css_image_set_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
@@ -41,6 +42,7 @@
#include "third_party/blink/renderer/core/style/cursor_data.h"
#include "third_party/blink/renderer/core/style/fill_layer.h"
#include "third_party/blink/renderer/core/style/filter_operation.h"
+#include "third_party/blink/renderer/core/style/style_crossfade_image.h"
#include "third_party/blink/renderer/core/style/style_fetched_image.h"
#include "third_party/blink/renderer/core/style/style_fetched_image_set.h"
#include "third_party/blink/renderer/core/style/style_generated_image.h"
@@ -49,11 +51,93 @@
#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/geometry/length.h"
+#include "third_party/blink/renderer/platform/loader/fetch/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_fetcher.h"
namespace blink {
+namespace {
+
+class StyleImageLoader {
+ STACK_ALLOCATED();
+
+ public:
+ StyleImageLoader(Document& document,
+ ComputedStyle& style,
+ float device_scale_factor)
+ : document_(document),
+ style_(style),
+ device_scale_factor_(device_scale_factor) {}
+
+ StyleImage* Load(
+ CSSValue&,
+ FetchParameters::ImageRequestBehavior = FetchParameters::kNone,
+ CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
+
+ private:
+ StyleImage* CrossfadeArgument(CSSValue&, CrossOriginAttributeValue);
+
+ Document& document_;
+ ComputedStyle& style_;
+ const float device_scale_factor_;
+};
+
+StyleImage* StyleImageLoader::Load(
+ CSSValue& value,
+ FetchParameters::ImageRequestBehavior image_request_behavior,
+ CrossOriginAttributeValue cross_origin) {
+ if (auto* image_value = DynamicTo<CSSImageValue>(value)) {
+ return image_value->CacheImage(document_, image_request_behavior,
+ cross_origin);
+ }
+
+ if (auto* paint_value = DynamicTo<CSSPaintValue>(value)) {
+ auto* image = MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
+ style_.AddPaintImage(image);
+ return image;
+ }
+
+ if (auto* crossfade_value = DynamicTo<cssvalue::CSSCrossfadeValue>(value)) {
+ return MakeGarbageCollected<StyleCrossfadeImage>(
+ *crossfade_value,
+ CrossfadeArgument(crossfade_value->From(), cross_origin),
+ CrossfadeArgument(crossfade_value->To(), cross_origin));
+ }
+
+ if (auto* image_gradient_value =
+ DynamicTo<cssvalue::CSSGradientValue>(value)) {
+ return MakeGarbageCollected<StyleGeneratedImage>(*image_gradient_value);
+ }
+
+ if (auto* image_set_value = DynamicTo<CSSImageSetValue>(value)) {
+ return image_set_value->CacheImage(document_, device_scale_factor_,
+ image_request_behavior, cross_origin);
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
+StyleImage* StyleImageLoader::CrossfadeArgument(
+ CSSValue& value,
+ CrossOriginAttributeValue cross_origin) {
+ // TODO(crbug.com/614906): For some reason we allow 'none' as an argument to
+ // -webkit-cross-fade() - the unprefixed cross-fade() function does however
+ // not accept 'none'. Map 'none' to a null StyleImage.
+ if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ DCHECK_EQ(identifier_value->GetValueID(), CSSValueID::kNone);
+ return nullptr;
+ }
+ // Reject paint() functions. They make assumptions about the client (being
+ // a LayoutObject) that we can't meet with the current implementation.
+ if (IsA<CSSPaintValue>(value))
+ return nullptr;
+ return Load(value, FetchParameters::kNone, cross_origin);
+}
+
+} // namespace
+
ElementStyleResources::ElementStyleResources(Element& element,
float device_scale_factor,
PseudoElement* pseudo_element)
@@ -61,49 +145,61 @@ ElementStyleResources::ElementStyleResources(Element& element,
device_scale_factor_(device_scale_factor),
pseudo_element_(pseudo_element) {}
-StyleImage* ElementStyleResources::GetStyleImage(CSSPropertyID property,
- const CSSValue& value) {
+bool ElementStyleResources::IsPending(const CSSValue& value) const {
if (auto* img_value = DynamicTo<CSSImageValue>(value))
- return CachedOrPendingFromValue(property, *img_value);
+ return img_value->IsCachePending();
+
+ // paint(...) is always treated as pending because it needs to call
+ // AddPaintImage() on the ComputedStyle.
+ if (IsA<CSSPaintValue>(value))
+ return true;
- if (auto* img_generator_value = DynamicTo<CSSImageGeneratorValue>(value))
- return GeneratedOrPendingFromValue(property, *img_generator_value);
+ // cross-fade(...) is always treated as pending (to avoid adding more complex
+ // recursion).
+ if (IsA<cssvalue::CSSCrossfadeValue>(value))
+ return true;
+
+ // Gradient functions are never pending.
+ if (IsA<cssvalue::CSSGradientValue>(value))
+ return false;
if (auto* img_set_value = DynamicTo<CSSImageSetValue>(value))
- return SetOrPendingFromValue(property, *img_set_value);
+ return img_set_value->IsCachePending(device_scale_factor_);
- return nullptr;
+ NOTREACHED();
+ return false;
}
-StyleImage* ElementStyleResources::GeneratedOrPendingFromValue(
- CSSPropertyID property,
- const CSSImageGeneratorValue& value) {
- if (value.IsPending()) {
- pending_image_properties_.insert(property);
- return MakeGarbageCollected<StylePendingImage>(value);
+StyleImage* ElementStyleResources::CachedStyleImage(
+ const CSSValue& value) const {
+ DCHECK(!IsPending(value));
+ if (auto* img_value = DynamicTo<CSSImageValue>(value)) {
+ img_value->RestoreCachedResourceIfNeeded(element_.GetDocument());
+ return img_value->CachedImage();
}
- return MakeGarbageCollected<StyleGeneratedImage>(value);
-}
-StyleImage* ElementStyleResources::SetOrPendingFromValue(
- CSSPropertyID property,
- const CSSImageSetValue& value) {
- if (value.IsCachePending(device_scale_factor_)) {
- pending_image_properties_.insert(property);
- return MakeGarbageCollected<StylePendingImage>(value);
- }
- return value.CachedImage(device_scale_factor_);
+ // Gradient functions are never pending (but don't cache StyleImages).
+ if (auto* gradient_value = DynamicTo<cssvalue::CSSGradientValue>(value))
+ return MakeGarbageCollected<StyleGeneratedImage>(*gradient_value);
+
+ if (auto* img_set_value = DynamicTo<CSSImageSetValue>(value))
+ return img_set_value->CachedImage(device_scale_factor_);
+
+ NOTREACHED();
+ return nullptr;
}
-StyleImage* ElementStyleResources::CachedOrPendingFromValue(
- CSSPropertyID property,
- const CSSImageValue& value) {
- if (value.IsCachePending()) {
+StyleImage* ElementStyleResources::GetStyleImage(CSSPropertyID property,
+ const CSSValue& value) {
+ if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ DCHECK_EQ(identifier_value->GetValueID(), CSSValueID::kNone);
+ return nullptr;
+ }
+ if (IsPending(value)) {
pending_image_properties_.insert(property);
return MakeGarbageCollected<StylePendingImage>(value);
}
- value.RestoreCachedResourceIfNeeded(element_.GetDocument());
- return value.CachedImage();
+ return CachedStyleImage(value);
}
static bool AllowExternalResources(CSSPropertyID property) {
@@ -168,37 +264,6 @@ static bool BackgroundLayerMayBeSprite(const FillLayer& background_layer) {
background_layer.PositionY().IsFixed();
}
-StyleImage* ElementStyleResources::LoadPendingImage(
- ComputedStyle& style,
- CSSValue& value,
- FetchParameters::ImageRequestBehavior image_request_behavior,
- CrossOriginAttributeValue cross_origin) {
- if (auto* image_value = DynamicTo<CSSImageValue>(value)) {
- return image_value->CacheImage(element_.GetDocument(),
- image_request_behavior, cross_origin);
- }
-
- if (auto* paint_value = DynamicTo<CSSPaintValue>(value)) {
- auto* image = MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
- style.AddPaintImage(image);
- return image;
- }
-
- if (auto* image_generator_value = DynamicTo<CSSImageGeneratorValue>(value)) {
- image_generator_value->LoadSubimages(element_.GetDocument());
- return MakeGarbageCollected<StyleGeneratedImage>(*image_generator_value);
- }
-
- if (auto* image_set_value = DynamicTo<CSSImageSetValue>(value)) {
- return image_set_value->CacheImage(element_.GetDocument(),
- device_scale_factor_,
- image_request_behavior, cross_origin);
- }
-
- NOTREACHED();
- return nullptr;
-}
-
static CSSValue* PendingCssValue(StyleImage* style_image) {
if (auto* pending_image = DynamicTo<StylePendingImage>(style_image))
return pending_image->CssValue();
@@ -223,7 +288,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
// If we eagerly loaded the images we'd fetch a.png, even though it's not
// used. If we didn't null check below we'd crash since the none actually
// removed all background images.
-
+ StyleImageLoader loader(element_.GetDocument(), style, device_scale_factor_);
for (CSSPropertyID property : pending_image_properties_) {
switch (property) {
case CSSPropertyID::kBackgroundImage: {
@@ -242,7 +307,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
}
}
StyleImage* new_image =
- LoadPendingImage(style, *pending_value, image_request_behavior);
+ loader.Load(*pending_value, image_request_behavior);
if (new_image && new_image->IsLazyloadPossiblyDeferred()) {
LazyImageHelper::StartMonitoring(pseudo_element_ ? pseudo_element_
: &element_);
@@ -260,7 +325,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
DynamicTo<ImageContentData>(*content_data)) {
if (auto* pending_value =
PendingCssValue(image_content->GetImage())) {
- image_content->SetImage(LoadPendingImage(style, *pending_value));
+ image_content->SetImage(loader.Load(*pending_value));
}
}
}
@@ -270,26 +335,26 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
if (CursorList* cursor_list = style.Cursors()) {
for (CursorData& cursor : *cursor_list) {
if (auto* pending_value = PendingCssValue(cursor.GetImage()))
- cursor.SetImage(LoadPendingImage(style, *pending_value));
+ cursor.SetImage(loader.Load(*pending_value));
}
}
break;
}
case CSSPropertyID::kListStyleImage: {
if (auto* pending_value = PendingCssValue(style.ListStyleImage()))
- style.SetListStyleImage(LoadPendingImage(style, *pending_value));
+ style.SetListStyleImage(loader.Load(*pending_value));
break;
}
case CSSPropertyID::kBorderImageSource: {
if (auto* pending_value = PendingCssValue(style.BorderImageSource()))
- style.SetBorderImageSource(LoadPendingImage(style, *pending_value));
+ style.SetBorderImageSource(loader.Load(*pending_value));
break;
}
case CSSPropertyID::kWebkitBoxReflect: {
if (StyleReflection* reflection = style.BoxReflect()) {
const NinePieceImage& mask_image = reflection->Mask();
if (auto* pending_value = PendingCssValue(mask_image.GetImage())) {
- StyleImage* loaded_image = LoadPendingImage(style, *pending_value);
+ StyleImage* loaded_image = loader.Load(*pending_value);
reflection->SetMask(NinePieceImage(
loaded_image, mask_image.ImageSlices(), mask_image.Fill(),
mask_image.BorderSlices(), mask_image.Outset(),
@@ -300,16 +365,16 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
}
case CSSPropertyID::kWebkitMaskBoxImageSource: {
if (auto* pending_value = PendingCssValue(style.MaskBoxImageSource()))
- style.SetMaskBoxImageSource(LoadPendingImage(style, *pending_value));
+ style.SetMaskBoxImageSource(loader.Load(*pending_value));
break;
}
case CSSPropertyID::kWebkitMaskImage: {
for (FillLayer* mask_layer = &style.AccessMaskLayers(); mask_layer;
mask_layer = mask_layer->Next()) {
if (auto* pending_value = PendingCssValue(mask_layer->GetImage())) {
- mask_layer->SetImage(
- LoadPendingImage(style, *pending_value, FetchParameters::kNone,
- kCrossOriginAttributeAnonymous));
+ mask_layer->SetImage(loader.Load(*pending_value,
+ FetchParameters::kNone,
+ kCrossOriginAttributeAnonymous));
}
}
break;
@@ -317,9 +382,9 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
case CSSPropertyID::kShapeOutside:
if (ShapeValue* shape_value = style.ShapeOutside()) {
if (auto* pending_value = PendingCssValue(shape_value->GetImage())) {
- shape_value->SetImage(
- LoadPendingImage(style, *pending_value, FetchParameters::kNone,
- kCrossOriginAttributeAnonymous));
+ shape_value->SetImage(loader.Load(*pending_value,
+ FetchParameters::kNone,
+ kCrossOriginAttributeAnonymous));
}
}
break;
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h
index b76a99f915c..c13c95063e1 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h
@@ -26,17 +26,11 @@
#include "third_party/blink/renderer/core/css/css_property_id_templates.h"
#include "third_party/blink/renderer/core/css/css_property_names.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/loader/fetch/cross_origin_attribute_value.h"
-#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
-class CSSImageGeneratorValue;
-class CSSImageSetValue;
-class CSSImageValue;
class CSSValue;
class ComputedStyle;
class Element;
@@ -45,9 +39,7 @@ class SVGResource;
class StyleImage;
namespace cssvalue {
-
class CSSURIValue;
-
}
// Holds information about resources, requested by stylesheets.
@@ -63,8 +55,6 @@ class ElementStyleResources {
ElementStyleResources& operator=(const ElementStyleResources&) = delete;
StyleImage* GetStyleImage(CSSPropertyID, const CSSValue&);
- StyleImage* CachedOrPendingFromValue(CSSPropertyID, const CSSImageValue&);
- StyleImage* SetOrPendingFromValue(CSSPropertyID, const CSSImageSetValue&);
SVGResource* GetSVGResourceFromValue(CSSPropertyID,
const cssvalue::CSSURIValue&);
@@ -72,18 +62,12 @@ class ElementStyleResources {
void LoadPendingResources(ComputedStyle&);
private:
- StyleImage* GeneratedOrPendingFromValue(CSSPropertyID,
- const CSSImageGeneratorValue&);
+ bool IsPending(const CSSValue&) const;
+ StyleImage* CachedStyleImage(const CSSValue&) const;
void LoadPendingSVGResources(ComputedStyle&);
void LoadPendingImages(ComputedStyle&);
- StyleImage* LoadPendingImage(
- ComputedStyle&,
- CSSValue&,
- FetchParameters::ImageRequestBehavior = FetchParameters::kNone,
- CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
-
Element& element_;
HashSet<CSSPropertyID> pending_image_properties_;
HashSet<CSSPropertyID> pending_svg_resource_properties_;
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 086cd3ddb3a..a3bb205e0db 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
@@ -84,6 +84,7 @@ static void CountFilterUse(FilterOperation::OperationType operation_type,
case FilterOperation::NONE:
case FilterOperation::BOX_REFLECT:
case FilterOperation::CONVOLVE_MATRIX:
+ case FilterOperation::COMPONENT_TRANSFER:
NOTREACHED();
return;
case FilterOperation::REFERENCE:
@@ -261,8 +262,10 @@ FilterOperations FilterOperationResolver::CreateOffscreenFilterOperations(
CSSToLengthConversionData::FontSizes font_sizes(
kOffScreenCanvasEmFontSize, kOffScreenCanvasRemFontSize, &font, zoom);
CSSToLengthConversionData::ViewportSize viewport_size(0, 0);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversion_data(nullptr, // ComputedStyle
font_sizes, viewport_size,
+ container_sizes,
1); // zoom
for (auto& curr_value : To<CSSValueList>(in_value)) {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/font_builder.cc b/chromium/third_party/blink/renderer/core/css/resolver/font_builder.cc
index d427f22f2f1..2fa0a3e4bed 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/font_builder.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/font_builder.cc
@@ -217,7 +217,7 @@ void FontBuilder::SetFamilyDescription(
bool is_initial =
family_description.generic_family == FontDescription::kStandardFamily &&
- family_description.family.FamilyIsEmpty();
+ family_description.family.Family().IsEmpty();
font_description.SetGenericFamily(family_description.generic_family);
font_description.SetFamily(is_initial ? StandardFontFamily()
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc
index cbac112bb23..5721167f03f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc
@@ -21,13 +21,15 @@ FontDescription FontStyleResolver::ComputeFont(
Font font(fontDescription, font_selector);
CSSToLengthConversionData::FontSizes fontSizes(10, 10, &font, 1);
CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
- CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize, 1);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
+ CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize,
+ container_sizes, 1);
// CSSPropertyID::kFontSize
if (property_set.HasProperty(CSSPropertyID::kFontSize)) {
builder.SetSize(StyleBuilderConverterBase::ConvertFontSize(
*property_set.GetPropertyCSSValue(CSSPropertyID::kFontSize),
- conversionData, FontDescription::Size(0, 0.0f, false)));
+ conversionData, FontDescription::Size(0, 0.0f, false), nullptr));
}
// CSSPropertyID::kFontFamily
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/match_result.h b/chromium/third_party/blink/renderer/core/css/resolver/match_result.h
index b8ab8595873..23b27861269 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/match_result.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/match_result.h
@@ -80,7 +80,7 @@ class MatchedExpansionsIterator {
MatchedExpansionsIterator(Iterator iterator,
const Document& document,
CascadeFilter filter,
- size_t index)
+ wtf_size_t index)
: iterator_(iterator),
document_(document),
filter_(filter),
@@ -105,7 +105,7 @@ class MatchedExpansionsIterator {
Iterator iterator_;
const Document& document_;
CascadeFilter filter_;
- size_t index_;
+ wtf_size_t index_;
};
class MatchedExpansionsRange {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/match_result_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/match_result_test.cc
index af8f3d618a4..3164f5fbf0e 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/match_result_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/match_result_test.cc
@@ -26,12 +26,12 @@ class MatchResultTest : public PageTestBase {
return result.GetMatchedProperties().size();
}
- CascadeOrigin OriginAt(const MatchResult& result, size_t index) const {
+ CascadeOrigin OriginAt(const MatchResult& result, wtf_size_t index) const {
DCHECK_LT(index, LengthOf(result));
return result.GetMatchedProperties()[index].types_.origin;
}
- const TreeScope& TreeScopeAt(const MatchResult& result, size_t index) {
+ const TreeScope& TreeScopeAt(const MatchResult& result, wtf_size_t index) {
DCHECK_EQ(CascadeOrigin::kAuthor, OriginAt(result, index));
return result.ScopeFromTreeOrder(
result.GetMatchedProperties()[index].types_.tree_order);
@@ -204,8 +204,8 @@ TEST_F(MatchResultTest, ExpansionsRange) {
CascadeFilter filter;
- size_t i = 0;
- size_t size = result.GetMatchedProperties().size();
+ wtf_size_t i = 0;
+ wtf_size_t size = result.GetMatchedProperties().size();
for (auto actual : result.Expansions(GetDocument(), filter)) {
ASSERT_LT(i, size);
CascadeExpansion expected(result.GetMatchedProperties()[i], GetDocument(),
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
index bd9bdfaf27a..f53fddd0f02 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
@@ -157,14 +157,13 @@ void MatchedPropertiesCache::Add(const Key& key,
const ComputedStyle& style,
const ComputedStyle& parent_style) {
DCHECK(key.IsValid());
- Cache::AddResult add_result = cache_.insert(key.hash_, nullptr);
- if (add_result.is_new_entry || !add_result.stored_value->value) {
- add_result.stored_value->value =
- MakeGarbageCollected<CachedMatchedProperties>();
- }
- CachedMatchedProperties* cache_item = add_result.stored_value->value.Get();
- if (!add_result.is_new_entry)
+ Member<CachedMatchedProperties>& cache_item =
+ cache_.insert(key.hash_, nullptr).stored_value->value;
+
+ if (!cache_item)
+ cache_item = MakeGarbageCollected<CachedMatchedProperties>();
+ else
cache_item->Clear();
cache_item->Set(style, parent_style, key.result_.GetMatchedProperties());
@@ -205,6 +204,8 @@ bool MatchedPropertiesCache::IsStyleCacheable(const ComputedStyle& style) {
// based on the used value of color-scheme.
if (style.HasNonInheritedLightDarkValue())
return false;
+ if (style.HasContainerRelativeUnits())
+ return false;
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
index 4c1f4dc3e81..017815daac7 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
@@ -64,7 +64,7 @@ class MatchedPropertiesCacheTestCache {
const CachedMatchedProperties* Find(const TestKey& key,
const ComputedStyle& style,
const ComputedStyle& parent_style) {
- StyleResolverState state(document_, *document_.body(),
+ StyleResolverState state(document_, *document_.body(), StyleRecalcContext(),
StyleRequest(&parent_style));
state.SetStyle(ComputedStyle::Clone(style));
return cache_.Find(key.InnerKey(), state);
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 83c646d9722..05d1b98ca3f 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
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
+#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
@@ -54,10 +55,9 @@
#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/input_type_names.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/list_marker.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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/svg/svg_svg_element.h"
@@ -94,17 +94,24 @@ bool IsEditableElement(Element* element, const ComputedStyle& style) {
TouchAction AdjustTouchActionForElement(TouchAction touch_action,
const ComputedStyle& style,
+ const ComputedStyle& parent_style,
Element* element) {
- // if body is the viewport defining element then ScrollsOverflow should
- // return false as body should have overflow-x/overflow-y set to visible
- Element* body = element ? element->GetDocument().body() : nullptr;
- bool is_body_and_viewport =
- element && element == body &&
- body == element->GetDocument().ViewportDefiningElement();
- bool is_child_document =
- element && element == element->GetDocument().documentElement() &&
- element->GetDocument().LocalOwner();
- if ((!is_body_and_viewport && style.ScrollsOverflow()) || is_child_document)
+ Element* document_element = element->GetDocument().documentElement();
+ bool scrolls_overflow = style.ScrollsOverflow();
+ if (element && element == element->GetDocument().FirstBodyElement()) {
+ // Body scrolls overflow if html root overflow is not visible or the
+ // propagation of overflow is stopped by containment.
+ if (parent_style.IsOverflowVisibleAlongBothAxes()) {
+ if (!RuntimeEnabledFeatures::CSSContainedBodyPropagationEnabled() ||
+ (!parent_style.ShouldApplyAnyContainment(*document_element) &&
+ !style.ShouldApplyAnyContainment(*element))) {
+ scrolls_overflow = false;
+ }
+ }
+ }
+ bool is_child_document = element && element == document_element &&
+ element->GetDocument().LocalOwner();
+ if (scrolls_overflow || is_child_document)
return touch_action | TouchAction::kPan | TouchAction::kInternalPanXScrolls;
return touch_action;
}
@@ -232,6 +239,46 @@ void StyleAdjuster::AdjustStyleForEditing(ComputedStyle& style) {
style.SetWhiteSpace(EWhiteSpace::kPreWrap);
}
+void StyleAdjuster::AdjustStyleForTextCombine(ComputedStyle& style) {
+ DCHECK_EQ(style.Display(), EDisplay::kInlineBlock);
+ // Set box sizes
+ const Font& font = style.GetFont();
+ DCHECK(font.GetFontDescription().IsVerticalBaseline());
+ const auto one_em = style.ComputedFontSizeAsFixed();
+ const auto line_height = style.GetFontHeight().LineHeight();
+ const auto size =
+ LengthSize(Length::Fixed(line_height), Length::Fixed(one_em));
+ style.SetContainIntrinsicSize(size);
+ style.SetHeight(size.Height());
+ style.SetLineHeight(size.Height());
+ style.SetMaxHeight(size.Height());
+ style.SetMaxWidth(size.Width());
+ style.SetMinHeight(size.Height());
+ style.SetMinWidth(size.Width());
+ style.SetWidth(size.Width());
+ AdjustStyleForCombinedText(style);
+}
+
+void StyleAdjuster::AdjustStyleForCombinedText(ComputedStyle& style) {
+ style.ResetTextCombine();
+ style.SetLetterSpacing(0.0f);
+ style.SetTextAlign(ETextAlign::kCenter);
+ style.SetTextDecoration(TextDecoration::kNone);
+ style.SetTextEmphasisMark(TextEmphasisMark::kNone);
+ style.SetVerticalAlign(EVerticalAlign ::kMiddle);
+ style.SetWordBreak(EWordBreak::kKeepAll);
+ style.SetWordSpacing(0.0f);
+ style.SetWritingMode(WritingMode::kHorizontalTb);
+
+ style.ClearAppliedTextDecorations();
+ style.UpdateFontOrientation();
+
+ DCHECK_EQ(style.GetFont().GetFontDescription().Orientation(),
+ FontOrientation::kHorizontal);
+
+ LayoutNGTextCombine::AssertStyleIsValid(style);
+}
+
static void AdjustStyleForFirstLetter(ComputedStyle& style) {
if (style.StyleType() != kPseudoIdFirstLetter)
return;
@@ -569,8 +616,8 @@ static void AdjustEffectiveTouchAction(ComputedStyle& style,
// The panning-restricted cancellation should also apply to iframes, so we
// allow (panning & local touch action) on the first descendant element of a
// iframe element.
- inherited_action =
- AdjustTouchActionForElement(inherited_action, style, element);
+ inherited_action = AdjustTouchActionForElement(inherited_action, style,
+ parent_style, element);
TouchAction enforced_by_policy = TouchAction::kNone;
if (element->GetDocument().IsVerticalScrollEnforced())
@@ -619,6 +666,9 @@ void StyleAdjuster::AdjustForForcedColorsMode(ComputedStyle& style) {
style.SetTextShadow(ComputedStyleInitialValues::InitialTextShadow());
style.SetBoxShadow(ComputedStyleInitialValues::InitialBoxShadow());
+ style.SetColorScheme({"light", "dark"});
+ if (style.ShouldForceColor(style.AccentColor()))
+ style.SetAccentColor(ComputedStyleInitialValues::InitialAccentColor());
if (!style.HasUrlBackgroundImage())
style.ClearBackgroundImage();
}
@@ -770,6 +820,20 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
// Columns don't apply to svg text elements.
if (IsA<SVGTextElement>(*element))
style.ClearMultiCol();
+
+ // Copy DominantBaseline to CssDominantBaseline without 'no-change',
+ // 'reset-size', and 'use-script'.
+ auto baseline = style.DominantBaseline();
+ if (baseline == EDominantBaseline::kUseScript) {
+ // TODO(fs): The dominant-baseline and the baseline-table components
+ // are set by determining the predominant script of the character data
+ // content.
+ baseline = EDominantBaseline::kAlphabetic;
+ } else if (baseline == EDominantBaseline::kNoChange ||
+ baseline == EDominantBaseline::kResetSize) {
+ baseline = layout_parent_style.CssDominantBaseline();
+ }
+ style.SetCssDominantBaseline(baseline);
} else if (element && element->IsMathMLElement()) {
if (style.Display() == EDisplay::kContents) {
// https://drafts.csswg.org/css-display/#unbox-mathml
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.h b/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.h
index e32fe3682ed..b668fff514a 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.h
@@ -40,7 +40,9 @@ class StyleAdjuster {
public:
CORE_EXPORT static void AdjustComputedStyle(StyleResolverState&, Element*);
+ static void AdjustStyleForCombinedText(ComputedStyle&);
static void AdjustStyleForEditing(ComputedStyle&);
+ static void AdjustStyleForTextCombine(ComputedStyle&);
private:
static void AdjustOverflow(ComputedStyle& style, Element* element);
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
index b83eb724373..10bb5dd920f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
@@ -275,4 +275,25 @@ TEST_F(StyleAdjusterTest, OverflowClipUseCount) {
GetDocument().IsUseCounted(WebFeature::kOverflowClipAlongEitherAxis));
}
+// crbug.com/1216721
+TEST_F(StyleAdjusterTest, AdjustForSVGCrash) {
+ SetBodyInnerHTML(R"HTML(
+<style>
+.class1 { dominant-baseline: hanging; }
+</style>
+<svg>
+<tref>
+<text id="text5" style="dominant-baseline: no-change;"/>
+</svg>
+<svg>
+<use id="use1" xlink:href="#text5" class="class1" />
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ Element* text =
+ GetDocument().getElementById("use1")->GetShadowRoot()->getElementById(
+ "text5");
+ EXPECT_EQ(EDominantBaseline::kHanging,
+ text->GetComputedStyle()->CssDominantBaseline());
+}
+
} // 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 985326a9861..fba4e4eaf07 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
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_path_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
#include "third_party/blink/renderer/core/css/css_quad_value.h"
#include "third_party/blink/renderer/core/css/css_reflect_value.h"
@@ -222,6 +223,13 @@ FontDescription::FamilyDescription StyleBuilderConverterBase::ConvertFontFamily(
FontBuilder* font_builder,
const Document* document_for_count) {
FontDescription::FamilyDescription desc(FontDescription::kNoFamily);
+
+ if (const auto* system_font =
+ DynamicTo<cssvalue::CSSPendingSystemFontValue>(value)) {
+ desc.family.SetFamily(system_font->ResolveFontFamily());
+ return desc;
+ }
+
FontFamily* curr_family = nullptr;
for (auto& family : To<CSSValueList>(value)) {
@@ -388,7 +396,8 @@ static float ComputeFontSize(const CSSToLengthConversionData& conversion_data,
FontDescription::Size StyleBuilderConverterBase::ConvertFontSize(
const CSSValue& value,
const CSSToLengthConversionData& conversion_data,
- FontDescription::Size parent_size) {
+ FontDescription::Size parent_size,
+ const Document* document) {
if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
CSSValueID value_id = identifier_value->GetValueID();
if (FontSizeFunctions::IsValidValueID(value_id)) {
@@ -403,6 +412,12 @@ FontDescription::Size StyleBuilderConverterBase::ConvertFontSize(
return FontBuilder::InitialSize();
}
+ if (const auto* system_font =
+ DynamicTo<cssvalue::CSSPendingSystemFontValue>(value)) {
+ return FontDescription::Size(0, system_font->ResolveFontSize(document),
+ true);
+ }
+
const auto& primitive_value = To<CSSPrimitiveValue>(value);
if (primitive_value.IsPercentage()) {
return FontDescription::Size(
@@ -439,7 +454,7 @@ FontDescription::Size StyleBuilderConverter::ConvertFontSize(
}
return StyleBuilderConverterBase::ConvertFontSize(
- value, state.FontSizeConversionData(), parent_size);
+ value, state.FontSizeConversionData(), parent_size, &state.GetDocument());
}
float StyleBuilderConverter::ConvertFontSizeAdjust(StyleResolverState& state,
@@ -486,6 +501,10 @@ FontSelectionValue StyleBuilderConverterBase::ConvertFontStretch(
break;
}
}
+
+ if (value.IsPendingSystemFontValue())
+ return NormalWidthValue();
+
NOTREACHED();
return NormalWidthValue();
}
@@ -511,6 +530,11 @@ FontSelectionValue StyleBuilderConverterBase::ConvertFontStyle(
NOTREACHED();
return NormalSlopeValue();
}
+ } else if (const auto* system_font =
+ DynamicTo<cssvalue::CSSPendingSystemFontValue>(value)) {
+ if (system_font->ResolveFontStyle() == ItalicSlopeValue())
+ return ItalicSlopeValue();
+ return NormalSlopeValue();
} else if (const auto* style_range_value =
DynamicTo<cssvalue::CSSFontStyleRangeValue>(value)) {
const CSSValueList* values = style_range_value->GetObliqueValues();
@@ -546,6 +570,10 @@ FontSelectionValue StyleBuilderConverterBase::ConvertFontWeight(
return clampTo<FontSelectionValue>(primitive_value->GetFloatValue());
}
+ if (const auto* system_font =
+ DynamicTo<cssvalue::CSSPendingSystemFontValue>(value))
+ return system_font->ResolveFontWeight();
+
if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
switch (identifier_value->GetValueID()) {
case CSSValueID::kNormal:
@@ -574,6 +602,9 @@ FontSelectionValue StyleBuilderConverter::ConvertFontWeight(
FontDescription::FontVariantCaps
StyleBuilderConverterBase::ConvertFontVariantCaps(const CSSValue& value) {
+ if (value.IsPendingSystemFontValue())
+ return FontDescription::kCapsNormal;
+
CSSValueID value_id = To<CSSIdentifierValue>(value).GetValueID();
switch (value_id) {
case CSSValueID::kNormal:
@@ -641,6 +672,9 @@ StyleBuilderConverter::ConvertFontVariantLigatures(StyleResolverState&,
return ligatures;
}
+ if (value.IsPendingSystemFontValue())
+ return FontDescription::VariantLigatures();
+
if (To<CSSIdentifierValue>(value).GetValueID() == CSSValueID::kNone) {
return FontDescription::VariantLigatures(
FontDescription::kDisabledLigaturesState);
@@ -658,6 +692,9 @@ FontVariantNumeric StyleBuilderConverter::ConvertFontVariantNumeric(
return FontVariantNumeric();
}
+ if (value.IsPendingSystemFontValue())
+ return FontVariantNumeric();
+
FontVariantNumeric variant_numeric;
for (const CSSValue* feature : To<CSSValueList>(value)) {
switch (To<CSSIdentifierValue>(feature)->GetValueID()) {
@@ -704,6 +741,9 @@ FontVariantEastAsian StyleBuilderConverter::ConvertFontVariantEastAsian(
return FontVariantEastAsian();
}
+ if (value.IsPendingSystemFontValue())
+ return FontVariantEastAsian();
+
FontVariantEastAsian variant_east_asian;
for (const CSSValue* feature : To<CSSValueList>(value)) {
switch (To<CSSIdentifierValue>(feature)->GetValueID()) {
@@ -908,7 +948,7 @@ GridTrackSize StyleBuilderConverter::ConvertGridTrackSize(
static void ConvertGridLineNamesList(
const CSSValue& value,
- size_t current_named_grid_line,
+ wtf_size_t current_named_grid_line,
NamedGridLinesMap& named_grid_lines,
OrderedNamedGridLines& ordered_named_grid_lines) {
DCHECK(value.IsGridLineNamesValue());
@@ -917,7 +957,7 @@ static void ConvertGridLineNamesList(
String named_grid_line =
To<CSSCustomIdentValue>(*named_grid_line_value).Value();
NamedGridLinesMap::AddResult result =
- named_grid_lines.insert(named_grid_line, Vector<size_t>());
+ named_grid_lines.insert(named_grid_line, Vector<wtf_size_t>());
result.stored_value->value.push_back(current_named_grid_line);
OrderedNamedGridLines::AddResult ordered_insertion_result =
ordered_named_grid_lines.insert(current_named_grid_line,
@@ -929,7 +969,7 @@ static void ConvertGridLineNamesList(
GridTrackList StyleBuilderConverter::ConvertGridTrackSizeList(
StyleResolverState& state,
const CSSValue& value) {
- Vector<GridTrackSize> track_sizes;
+ Vector<GridTrackSize, 1> track_sizes;
for (auto& curr_value : To<CSSValueList>(value)) {
DCHECK(!curr_value->IsGridLineNamesValue());
DCHECK(!curr_value->IsGridAutoRepeatValue());
@@ -945,10 +985,10 @@ void StyleBuilderConverter::ConvertGridTrackList(
GridTrackList& track_sizes,
NamedGridLinesMap& named_grid_lines,
OrderedNamedGridLines& ordered_named_grid_lines,
- Vector<GridTrackSize>& auto_repeat_track_sizes,
+ Vector<GridTrackSize, 1>& auto_repeat_track_sizes,
NamedGridLinesMap& auto_repeat_named_grid_lines,
OrderedNamedGridLines& auto_repeat_ordered_named_grid_lines,
- size_t& auto_repeat_insertion_point,
+ wtf_size_t& auto_repeat_insertion_point,
AutoRepeatType& auto_repeat_type,
StyleResolverState& state) {
if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
@@ -956,7 +996,7 @@ void StyleBuilderConverter::ConvertGridTrackList(
return;
}
- size_t current_named_grid_line = 0;
+ wtf_size_t current_named_grid_line = 0;
auto convert_line_name_or_track_size = [&](const CSSValue& curr_value) {
if (curr_value.IsGridLineNamesValue()) {
ConvertGridLineNamesList(curr_value, current_named_grid_line,
@@ -971,8 +1011,8 @@ void StyleBuilderConverter::ConvertGridTrackList(
for (auto curr_value : To<CSSValueList>(value)) {
if (auto* grid_auto_repeat_value =
DynamicTo<cssvalue::CSSGridAutoRepeatValue>(curr_value.Get())) {
- Vector<GridTrackSize> repeated_track_sizes;
- size_t auto_repeat_index = 0;
+ Vector<GridTrackSize, 1> repeated_track_sizes;
+ wtf_size_t auto_repeat_index = 0;
CSSValueID auto_repeat_id = grid_auto_repeat_value->AutoRepeatID();
DCHECK(auto_repeat_id == CSSValueID::kAutoFill ||
auto_repeat_id == CSSValueID::kAutoFit);
@@ -1003,13 +1043,13 @@ void StyleBuilderConverter::ConvertGridTrackList(
if (auto* repeated_values =
DynamicTo<cssvalue::CSSGridIntegerRepeatValue>(curr_value.Get())) {
- size_t repetitions = repeated_values->Repetitions();
- for (size_t i = 0; i < repetitions; ++i) {
+ wtf_size_t repetitions = repeated_values->Repetitions();
+ for (wtf_size_t i = 0; i < repetitions; ++i) {
for (auto curr_repeat_value : *repeated_values)
convert_line_name_or_track_size(*curr_repeat_value);
}
if (RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
- Vector<GridTrackSize> repeater_sizes;
+ Vector<GridTrackSize, 1> repeater_sizes;
for (auto curr_repeat_value : *repeated_values) {
if (!curr_repeat_value->IsGridLineNamesValue()) {
repeater_sizes.push_back(
@@ -1045,14 +1085,14 @@ void StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
: named_grid_area_entry.value.columns;
{
NamedGridLinesMap::AddResult start_result = named_grid_lines.insert(
- named_grid_area_entry.key + "-start", Vector<size_t>());
+ named_grid_area_entry.key + "-start", Vector<wtf_size_t>());
start_result.stored_value->value.push_back(area_span.StartLine());
std::sort(start_result.stored_value->value.begin(),
start_result.stored_value->value.end());
}
{
NamedGridLinesMap::AddResult end_result = named_grid_lines.insert(
- named_grid_area_entry.key + "-end", Vector<size_t>());
+ named_grid_area_entry.key + "-end", Vector<wtf_size_t>());
end_result.stored_value->value.push_back(area_span.EndLine());
std::sort(end_result.stored_value->value.begin(),
end_result.stored_value->value.end());
@@ -1168,6 +1208,8 @@ Length StyleBuilderConverter::ConvertLengthSizing(StyleResolverState& state,
case CSSValueID::kWebkitFitContent:
case CSSValueID::kFitContent:
return Length::FitContent();
+ case CSSValueID::kContent:
+ return Length::Content();
case CSSValueID::kAuto:
return Length::Auto();
default:
@@ -1228,6 +1270,9 @@ Length StyleBuilderConverter::ConvertLineHeight(StyleResolverState& state,
}
}
+ if (value.IsPendingSystemFontValue())
+ return ComputedStyleInitialValues::InitialLineHeight();
+
DCHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueID::kNormal);
return ComputedStyleInitialValues::InitialLineHeight();
}
@@ -1547,8 +1592,11 @@ StyleAutoColor StyleBuilderConverter::ConvertStyleAutoColor(
return StyleAutoColor::AutoColor();
if (StyleColor::IsSystemColor(value_id)) {
CountSystemColorComputeToSelfUsage(state);
- if (RuntimeEnabledFeatures::CSSSystemColorComputeToSelfEnabled())
- return StyleAutoColor(value_id);
+ return StyleAutoColor(
+ state.GetDocument().GetTextLinkColors().ColorFromCSSValue(
+ value, Color(), state.Style()->UsedColorScheme(),
+ for_visited_link),
+ value_id);
}
}
return StyleAutoColor(
@@ -2115,4 +2163,13 @@ ScrollbarGutter StyleBuilderConverter::ConvertScrollbarGutter(
return flags;
}
+AtomicString StyleBuilderConverter::ConvertContainerName(
+ StyleResolverState& state,
+ const CSSValue& value) {
+ if (auto* custom_ident_value = DynamicTo<CSSCustomIdentValue>(value))
+ return AtomicString(custom_ident_value->Value());
+ DCHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueID::kNone);
+ return AtomicString();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
index 092ae44ecb8..7e0d2c25aae 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
@@ -28,6 +28,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_STYLE_BUILDER_CONVERTER_H_
#include "cc/input/scroll_snap_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -88,7 +89,8 @@ class StyleBuilderConverterBase {
static FontDescription::Size ConvertFontSize(
const CSSValue&,
const CSSToLengthConversionData&,
- FontDescription::Size parent_size);
+ FontDescription::Size parent_size,
+ const Document*);
};
// Note that we assume the parser only allows valid CSSValue types.
@@ -228,10 +230,10 @@ class StyleBuilderConverter {
GridTrackList&,
NamedGridLinesMap&,
OrderedNamedGridLines&,
- Vector<GridTrackSize>& auto_repeat_track_sizes,
+ Vector<GridTrackSize, 1>& auto_repeat_track_sizes,
NamedGridLinesMap&,
OrderedNamedGridLines&,
- size_t& auto_repeat_insertion_point,
+ wtf_size_t& auto_repeat_insertion_point,
AutoRepeatType&,
StyleResolverState&);
static void CreateImplicitNamedGridLinesFromGridArea(
@@ -294,6 +296,9 @@ class StyleBuilderConverter {
static ScrollbarGutter ConvertScrollbarGutter(StyleResolverState& state,
const CSSValue& value);
+ static AtomicString ConvertContainerName(StyleResolverState&,
+ const CSSValue&);
+
static void CountSystemColorComputeToSelfUsage(
const StyleResolverState& state);
};
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc
index 5983d831eb4..e71c66f4b53 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc
@@ -40,6 +40,7 @@ TEST_F(StyleBuilderTest, WritingModeChangeDirtiesFont) {
style->SetWritingMode(WritingMode::kVerticalLr);
StyleResolverState state(GetDocument(), *GetDocument().body(),
+ StyleRecalcContext(),
StyleRequest(parent_style.get()));
state.SetStyle(style);
@@ -73,6 +74,7 @@ TEST_F(StyleBuilderTest, TextOrientationChangeDirtiesFont) {
style->SetTextOrientation(ETextOrientation::kUpright);
StyleResolverState state(GetDocument(), *GetDocument().body(),
+ StyleRecalcContext(),
StyleRequest(parent_style.get()));
state.SetStyle(style);
@@ -88,6 +90,7 @@ TEST_F(StyleBuilderTest, HasExplicitInheritance) {
auto parent_style = GetDocument().GetStyleResolver().CreateComputedStyle();
auto style = GetDocument().GetStyleResolver().CreateComputedStyle();
StyleResolverState state(GetDocument(), *GetDocument().body(),
+ StyleRecalcContext(),
StyleRequest(parent_style.get()));
state.SetStyle(style);
EXPECT_FALSE(style->HasExplicitInheritance());
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index 84a46679c48..90d1d3f993e 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -75,15 +75,15 @@ const CSSValue* Parse(const CSSProperty& property,
}
const CSSValue* ValueAt(const MatchResult& result, uint32_t position) {
- size_t matched_properties_index = DecodeMatchedPropertiesIndex(position);
- size_t declaration_index = DecodeDeclarationIndex(position);
+ wtf_size_t matched_properties_index = DecodeMatchedPropertiesIndex(position);
+ wtf_size_t declaration_index = DecodeDeclarationIndex(position);
const MatchedPropertiesVector& vector = result.GetMatchedProperties();
const CSSPropertyValueSet* set = vector[matched_properties_index].properties;
return &set->PropertyAt(declaration_index).Value();
}
const TreeScope& TreeScopeAt(const MatchResult& result, uint32_t position) {
- size_t matched_properties_index = DecodeMatchedPropertiesIndex(position);
+ wtf_size_t matched_properties_index = DecodeMatchedPropertiesIndex(position);
const MatchedProperties& properties =
result.GetMatchedProperties()[matched_properties_index];
DCHECK_EQ(properties.types_.origin, CascadeOrigin::kAuthor);
@@ -195,6 +195,8 @@ void StyleCascade::Apply(CascadeFilter filter) {
state_.Style()->SetHasAuthorBackground();
if (resolver.AuthorFlags() & CSSProperty::kBorder)
state_.Style()->SetHasAuthorBorder();
+ if (resolver.AuthorFlags() & CSSProperty::kBorderRadius)
+ state_.Style()->SetHasAuthorBorderRadius();
}
}
@@ -299,7 +301,7 @@ void StyleCascade::AnalyzeMatchResult() {
void StyleCascade::AnalyzeInterpolations() {
const auto& entries = interpolations_.GetEntries();
- for (size_t i = 0; i < entries.size(); ++i) {
+ for (wtf_size_t i = 0; i < entries.size(); ++i) {
for (const auto& active_interpolation : *entries[i].map) {
auto name = active_interpolation.key.GetCSSPropertyName();
uint32_t position = EncodeInterpolationPosition(
@@ -421,7 +423,7 @@ void StyleCascade::ApplyMatchResult(CascadeResolver& resolver) {
void StyleCascade::ApplyInterpolations(CascadeResolver& resolver) {
const auto& entries = interpolations_.GetEntries();
- for (size_t i = 0; i < entries.size(); ++i) {
+ for (wtf_size_t i = 0; i < entries.size(); ++i) {
const auto& entry = entries[i];
ApplyInterpolationMap(*entry.map, entry.origin, i, resolver);
}
@@ -560,7 +562,7 @@ void StyleCascade::LookupAndApplyInterpolation(const CSSProperty& property,
if (property.IsVisited())
return;
DCHECK(priority.GetOrigin() >= CascadeOrigin::kAnimation);
- size_t index = DecodeInterpolationIndex(priority.GetPosition());
+ wtf_size_t index = DecodeInterpolationIndex(priority.GetPosition());
DCHECK_LE(index, interpolations_.GetEntries().size());
const ActiveInterpolationsMap& map = *interpolations_.GetEntries()[index].map;
PropertyHandle handle = ToPropertyHandle(property, priority);
@@ -657,8 +659,7 @@ const CSSValue* StyleCascade::ResolveCustomProperty(
if (data == decl.Value())
return &decl;
- return MakeGarbageCollected<CSSCustomPropertyDeclaration>(decl.GetName(),
- data);
+ return MakeGarbageCollected<CSSCustomPropertyDeclaration>(data);
}
const CSSValue* StyleCascade::ResolveVariableReference(
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
index cd6a0d63b26..8c5bad2e11f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet_init.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/css/active_style_sheets.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_initial_color_value.h"
@@ -166,22 +167,18 @@ class TestCascade {
CascadeOrigin GetOrigin(String name) { return GetPriority(name).GetOrigin(); }
- void CalculateTransitionUpdate() {
- CSSAnimations::CalculateTransitionUpdate(
- state_.AnimationUpdate(), CSSAnimations::PropertyPass::kCustom,
- state_.GetElement(), *state_.Style());
- CSSAnimations::CalculateTransitionUpdate(
- state_.AnimationUpdate(), CSSAnimations::PropertyPass::kStandard,
- state_.GetElement(), *state_.Style());
- AddTransitions();
- }
+ void AddInterpolations() {
+ CalculateInterpolationUpdate();
- void CalculateAnimationUpdate() {
- CSSAnimations::CalculateAnimationUpdate(
- state_.AnimationUpdate(), state_.GetElement(), state_.GetElement(),
- *state_.Style(), state_.ParentStyle(),
- &GetDocument().GetStyleResolver());
- AddAnimations();
+ // Add to cascade:
+ const auto& update = state_.AnimationUpdate();
+ if (update.IsEmpty())
+ return;
+
+ cascade_.AddInterpolations(&update.ActiveInterpolationsForAnimations(),
+ CascadeOrigin::kAnimation);
+ cascade_.AddInterpolations(&update.ActiveInterpolationsForTransitions(),
+ CascadeOrigin::kTransition);
}
void Reset() {
@@ -246,28 +243,13 @@ class TestCascade {
FinishOrigin();
}
- void AddAnimations() {
- const auto& update = state_.AnimationUpdate();
- if (update.IsEmpty())
- return;
- cascade_.AddInterpolations(
- &update.ActiveInterpolationsForCustomAnimations(),
- CascadeOrigin::kAnimation);
- cascade_.AddInterpolations(
- &update.ActiveInterpolationsForStandardAnimations(),
- CascadeOrigin::kAnimation);
- }
-
- void AddTransitions() {
- const auto& update = state_.AnimationUpdate();
- if (update.IsEmpty())
- return;
- cascade_.AddInterpolations(
- &update.ActiveInterpolationsForCustomTransitions(),
- CascadeOrigin::kTransition);
- cascade_.AddInterpolations(
- &update.ActiveInterpolationsForStandardTransitions(),
- CascadeOrigin::kTransition);
+ void CalculateInterpolationUpdate() {
+ CSSAnimations::CalculateTransitionUpdate(
+ state_.AnimationUpdate(), state_.GetElement(), *state_.Style());
+ CSSAnimations::CalculateAnimationUpdate(
+ state_.AnimationUpdate(), state_.GetElement(), state_.GetElement(),
+ *state_.Style(), state_.ParentStyle(),
+ &GetDocument().GetStyleResolver());
}
CascadeOrigin current_origin_ = CascadeOrigin::kUserAgent;
@@ -1690,7 +1672,7 @@ TEST_F(StyleCascadeTest, RevertInKeyframe) {
cascade.Add("animation:test linear 1000s -500s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("50px", cascade.ComputedValue("margin-left"));
@@ -1713,7 +1695,7 @@ TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframe) {
cascade.Add("animation:test linear 1000s -500s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("50px", cascade.ComputedValue("--x"));
@@ -1742,7 +1724,7 @@ TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframeUnset) {
cascade.Add("animation:test linear 1000s -500s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("50px", cascade.ComputedValue("--x"));
@@ -1764,7 +1746,7 @@ TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframeEmptyInherit) {
cascade.Add("animation:test linear 1000s -500s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("50px", cascade.ComputedValue("--x"));
@@ -1784,7 +1766,7 @@ TEST_F(StyleCascadeTest, RevertInKeyframeResponsive) {
cascade.Add("margin-left:var(--x)", CascadeOrigin::kUser);
cascade.Add("animation:test linear 1000s -500s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("50px", cascade.ComputedValue("margin-left"));
@@ -1795,7 +1777,7 @@ TEST_F(StyleCascadeTest, RevertInKeyframeResponsive) {
cascade.Add("animation:test linear 1000s -500s");
cascade.Add("--x:80px", CascadeOrigin::kAuthor);
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("40px", cascade.ComputedValue("margin-left"));
@@ -1819,7 +1801,7 @@ TEST_F(StyleCascadeTest, RevertToCycleInKeyframe) {
cascade.Add("animation:test linear 1000s -500s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("0px", cascade.ComputedValue("--x"));
@@ -1843,7 +1825,7 @@ TEST_F(StyleCascadeTest, RevertCausesTransition) {
CascadeOrigin::kAuthor);
cascade2.Apply();
- cascade2.CalculateTransitionUpdate();
+ cascade2.AddInterpolations();
cascade2.Apply();
EXPECT_EQ("150px", cascade2.ComputedValue("width"));
@@ -2135,7 +2117,7 @@ TEST_F(StyleCascadeTest, AnimationApplyFilter) {
cascade.Add("color:green");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
@@ -2160,7 +2142,7 @@ TEST_F(StyleCascadeTest, TransitionApplyFilter) {
cascade2.Add("transition: all steps(2, start) 100s");
cascade2.Apply();
- cascade2.CalculateTransitionUpdate();
+ cascade2.AddInterpolations();
cascade2.Apply(CascadeFilter(CSSProperty::kInherited, true));
EXPECT_EQ("rgb(128, 128, 128)", cascade2.ComputedValue("color"));
@@ -2183,7 +2165,7 @@ TEST_F(StyleCascadeTest, PendingKeyframeAnimation) {
cascade.Add("animation-duration", "1s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin());
@@ -2207,7 +2189,7 @@ TEST_F(StyleCascadeTest, PendingKeyframeAnimationApply) {
cascade.Add("animation-delay", "-5s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin());
@@ -2233,7 +2215,7 @@ TEST_F(StyleCascadeTest, TransitionCausesInterpolationValue) {
cascade2.Add("transition", "--x 1s");
cascade2.Apply();
- cascade2.CalculateTransitionUpdate();
+ cascade2.AddInterpolations();
cascade2.Apply();
EXPECT_EQ(CascadeOrigin::kTransition,
@@ -2261,7 +2243,7 @@ TEST_F(StyleCascadeTest, TransitionDetectedForChangedFontSize) {
cascade2.Add("transition", "--x 1s, width 1s");
cascade2.Apply();
- cascade2.CalculateTransitionUpdate();
+ cascade2.AddInterpolations();
cascade2.Apply();
EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("--x"));
@@ -2290,7 +2272,7 @@ TEST_F(StyleCascadeTest, AnimatingVarReferences) {
cascade.Add("--y", "var(--x)");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("15px", cascade.ComputedValue("--x"));
@@ -2313,7 +2295,7 @@ TEST_F(StyleCascadeTest, AnimateStandardProperty) {
cascade.Add("animation-delay", "-5s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width"));
@@ -2338,7 +2320,7 @@ TEST_F(StyleCascadeTest, AnimateLogicalProperty) {
cascade.Add("animation:test 1s linear paused");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
@@ -2363,7 +2345,7 @@ TEST_F(StyleCascadeTest, AnimateLogicalPropertyWithLookup) {
cascade.Add("animation:test 1s linear paused");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.ApplySingle(GetCSSPropertyMarginLeft());
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
@@ -2388,7 +2370,7 @@ TEST_F(StyleCascadeTest, AuthorImportantWinOverAnimations) {
cascade.Add("height:40px !important");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width"));
@@ -2417,7 +2399,7 @@ TEST_F(StyleCascadeTest, TransitionsWinOverAuthorImportant) {
cascade2.Add("transition:all 1s");
cascade2.Apply();
- cascade2.CalculateTransitionUpdate();
+ cascade2.AddInterpolations();
cascade2.Apply();
EXPECT_EQ(CascadeOrigin::kTransition,
@@ -2446,7 +2428,7 @@ TEST_F(StyleCascadeTest, EmRespondsToAnimatedFontSize) {
cascade.Add("width", "10em");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("30px", cascade.ComputedValue("--x"));
@@ -2473,7 +2455,7 @@ TEST_F(StyleCascadeTest, AnimateStandardPropertyWithVar) {
cascade.Add("--to", "20px");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("15px", cascade.ComputedValue("width"));
@@ -2497,7 +2479,7 @@ TEST_F(StyleCascadeTest, AnimateStandardShorthand) {
cascade.Add("animation-delay", "-5s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top"));
@@ -2530,7 +2512,7 @@ TEST_F(StyleCascadeTest, AnimatedVisitedImportantOverride) {
cascade.Add("animation-delay:-5s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("background-color"));
@@ -2558,7 +2540,7 @@ TEST_F(StyleCascadeTest, AnimatedVisitedHighPrio) {
cascade.Add("animation:test 10s -5s linear");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("color"));
@@ -2593,7 +2575,7 @@ TEST_F(StyleCascadeTest, AnimatePendingSubstitutionValue) {
cascade.Add("--to", "20px");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top"));
@@ -3149,7 +3131,7 @@ TEST_F(StyleCascadeTest, AnalyzeFlagsClean) {
EXPECT_FALSE(cascade.NeedsMatchResultAnalyze());
EXPECT_FALSE(cascade.NeedsInterpolationsAnalyze());
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
EXPECT_FALSE(cascade.NeedsMatchResultAnalyze());
EXPECT_FALSE(cascade.NeedsInterpolationsAnalyze());
@@ -3430,7 +3412,7 @@ TEST_F(StyleCascadeTest, GetCascadedValuesInterpolated) {
cascade.Add("animation-delay: -5s");
cascade.Apply();
- cascade.CalculateAnimationUpdate();
+ cascade.AddInterpolations();
cascade.Apply();
// Verify that effect values from the animation did apply:
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 7f3d5192c27..cb4b09e0e2e 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
@@ -30,10 +30,13 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
+#include "third_party/blink/renderer/core/css/container_query_evaluator.h"
#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_identifier_value.h"
@@ -114,10 +117,20 @@ void SetAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) {
// If any changes to CSS Animations were detected, stash the update away for
// application after the layout object is updated if we're in the appropriate
// scope.
- if (!state.AnimationUpdate().IsEmpty()) {
- auto& element_animations = element.EnsureElementAnimations();
- element_animations.CssAnimations().SetPendingUpdate(
- state.AnimationUpdate());
+ if (state.AnimationUpdate().IsEmpty())
+ return;
+
+ auto& element_animations = element.EnsureElementAnimations();
+ auto& document_animations = state.GetDocument().GetDocumentAnimations();
+
+ element_animations.CssAnimations().SetPendingUpdate(state.AnimationUpdate());
+
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) {
+ if (document_animations.AnimationUpdatesAllowed()) {
+ state.GetDocument()
+ .GetDocumentAnimations()
+ .AddElementWithPendingAnimationUpdate(element);
+ }
}
}
@@ -127,6 +140,12 @@ bool HasAnimationsOrTransitions(const StyleResolverState& state) {
state.GetAnimatingElement()->HasAnimations());
}
+bool IsAnimationStyleChange(Element& element) {
+ if (auto* element_animations = element.GetElementAnimations())
+ return element_animations->IsAnimationStyleChange();
+ return false;
+}
+
bool ShouldComputeBaseComputedStyle(const ComputedStyle* base_computed_style) {
#if DCHECK_IS_ON()
// The invariant in the base computed style optimization is that as long as
@@ -197,6 +216,25 @@ void MaybeResetCascade(StyleCascade& cascade) {
#endif // DCHECK_IS_ON()
}
+void PreserveTextAutosizingMultiplierIfNeeded(
+ StyleResolverState& state,
+ const StyleRequest& style_request) {
+ const ComputedStyle* old_style = state.GetElement().GetComputedStyle();
+ if (!style_request.IsPseudoStyleRequest() && old_style) {
+ state.Style()->SetTextAutosizingMultiplier(
+ old_style->TextAutosizingMultiplier());
+ }
+}
+
+bool TextAutosizingMultiplierChanged(const StyleResolverState& state,
+ const ComputedStyle& base_computed_style) {
+ // Note that |old_style| can be a style replaced by
+ // TextAutosizer::ApplyMultiplier.
+ const ComputedStyle* old_style = state.GetElement().GetComputedStyle();
+ return old_style && (old_style->TextAutosizingMultiplier() !=
+ base_computed_style.TextAutosizingMultiplier());
+}
+
} // namespace
static CSSPropertyValueSet* LeftToRightDeclaration() {
@@ -570,7 +608,7 @@ void StyleResolver::MatchUARules(const Element& element,
CSSDefaultStyleSheets::Instance();
if (!print_media_type_) {
if (LIKELY(element.IsHTMLElement() || element.IsVTTElement())) {
- MatchRuleSet(collector, default_style_sheets.DefaultStyle());
+ MatchRuleSet(collector, default_style_sheets.DefaultHtmlStyle());
if (UNLIKELY(IsInMediaUAShadow(element))) {
MatchRuleSet(collector,
default_style_sheets.DefaultMediaControlsStyle());
@@ -586,7 +624,7 @@ void StyleResolver::MatchUARules(const Element& element,
// In quirks mode, we match rules from the quirks user agent sheet.
if (GetDocument().InQuirksMode())
- MatchRuleSet(collector, default_style_sheets.DefaultQuirksStyle());
+ MatchRuleSet(collector, default_style_sheets.DefaultHtmlQuirksStyle());
// If document uses view source styles (in view source mode or in xml viewer
// mode), then we match rules from the view source style sheet.
@@ -688,40 +726,19 @@ static ElementAnimations* GetElementAnimations(
return state.GetAnimatingElement()->GetElementAnimations();
}
-static const ComputedStyle* CachedAnimationBaseComputedStyle(
- StyleResolverState& state) {
- ElementAnimations* element_animations = GetElementAnimations(state);
- if (!element_animations)
+static StyleBaseData* GetBaseData(const StyleResolverState& state) {
+ Element* animating_element = state.GetAnimatingElement();
+ if (!animating_element)
return nullptr;
-
- return element_animations->BaseComputedStyle();
+ auto* old_style = animating_element->GetComputedStyle();
+ return old_style ? old_style->BaseData().get() : nullptr;
}
-static void UpdateAnimationBaseComputedStyle(StyleResolverState& state,
- StyleCascade& cascade,
- bool forced_update) {
- if (!state.GetAnimatingElement())
- return;
-
- if (!state.CanCacheBaseStyle())
- return;
-
- if (forced_update)
- state.GetAnimatingElement()->EnsureElementAnimations();
-
- ElementAnimations* element_animations =
- state.GetAnimatingElement()->GetElementAnimations();
- if (!element_animations)
- return;
-
- if (element_animations->IsAnimationStyleChange() &&
- element_animations->BaseComputedStyle()) {
- return;
- }
-
- std::unique_ptr<CSSBitset> important_set = cascade.GetImportantSet();
- element_animations->UpdateBaseComputedStyle(state.Style(),
- std::move(important_set));
+static const ComputedStyle* CachedAnimationBaseComputedStyle(
+ StyleResolverState& state) {
+ if (auto* base_data = GetBaseData(state))
+ return base_data->GetBaseComputedStyle();
+ return nullptr;
}
static void IncrementResolvedStyleCounters(const StyleRequest& style_request,
@@ -753,7 +770,8 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
SelectorFilterParentScope::EnsureParentStackIsPushed();
- StyleResolverState state(GetDocument(), *element, style_request);
+ StyleResolverState state(GetDocument(), *element, style_recalc_context,
+ style_request);
STACK_UNINITIALIZED StyleCascade cascade(state);
@@ -779,6 +797,22 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
if (element->IsMathMLElement())
ApplyMathMLCustomStyleProperties(element, state);
+ } else if (IsHighlightPseudoElement(style_request.pseudo_id)) {
+ if (element->GetComputedStyle() &&
+ element->GetComputedStyle()->TextShadow() !=
+ state.Style()->TextShadow()) {
+ // This counts the usage of text-shadow in CSS highlight pseudos.
+ UseCounter::Count(GetDocument(),
+ WebFeature::kTextShadowInHighlightPseudo);
+ if (state.Style()->TextShadow()) {
+ // This counts the cases in which text-shadow is not "none" in CSS
+ // highlight pseudos, as the most common use case is using it to disable
+ // text-shadow, and that won't be need once some painting issues related
+ // to highlight pseudos are fixed.
+ UseCounter::Count(GetDocument(),
+ WebFeature::kTextShadowNotNoneInHighlightPseudo);
+ }
+ }
}
if (Element* animating_element = state.GetAnimatingElement())
@@ -787,6 +821,11 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
if (state.Style()->HasViewportUnits())
GetDocument().SetHasViewportUnits();
+ if (state.Style()->HasContainerRelativeUnits()) {
+ state.Style()->SetDependsOnContainerQueries(true);
+ GetDocument().GetStyleEngine().SetUsesContainerRelativeUnits();
+ }
+
if (state.Style()->HasRemUnits())
GetDocument().GetStyleEngine().SetUsesRemUnit(true);
@@ -950,16 +989,11 @@ void StyleResolver::ApplyBaseStyle(
return;
}
- if (!style_request.IsPseudoStyleRequest() && element->GetComputedStyle() &&
- element->GetComputedStyle()->TextAutosizingMultiplier() !=
- state.Style()->TextAutosizingMultiplier()) {
- // Preserve the text autosizing multiplier on style recalc. Autosizer will
- // update it during layout if needed.
- // NOTE: this must occur before ApplyMatchedProperties for correct
- // computation of font-relative lengths.
- state.Style()->SetTextAutosizingMultiplier(
- element->GetComputedStyle()->TextAutosizingMultiplier());
- }
+ // Preserve the text autosizing multiplier on style recalc. Autosizer will
+ // update it during layout if needed.
+ // NOTE: This must occur before CascadeAndApplyMatchedProperties for correct
+ // computation of font-relative lengths.
+ PreserveTextAutosizingMultiplierIfNeeded(state, style_request);
CascadeAndApplyMatchedProperties(state, cascade);
@@ -981,6 +1015,8 @@ void StyleResolver::ApplyBaseStyle(
if (base_is_usable) {
DCHECK(animation_base_computed_style);
state.SetStyle(ComputedStyle::Clone(*animation_base_computed_style));
+ state.StyleRef().SetBaseData(
+ scoped_refptr<StyleBaseData>(GetBaseData(state)));
state.Style()->SetStyleType(style_request.pseudo_id);
if (!state.ParentStyle()) {
state.SetParentStyle(InitialStyleForElement());
@@ -1001,14 +1037,16 @@ CompositorKeyframeValue* StyleResolver::CreateCompositorKeyframeValueSnapshot(
double offset) {
// TODO(alancutter): Avoid creating a StyleResolverState just to apply a
// single value on a ComputedStyle.
- StyleResolverState state(element.GetDocument(), element,
+ // TOOD(crbug.com/1223030): Propagate a real StyleRecalcContext to handle
+ // container relative units.
+ StyleResolverState state(element.GetDocument(), element, StyleRecalcContext(),
StyleRequest(parent_style));
state.SetStyle(ComputedStyle::Clone(base_style));
if (value) {
STACK_UNINITIALIZED StyleCascade cascade(state);
auto* set =
MakeGarbageCollected<MutableCSSPropertyValueSet>(state.GetParserMode());
- set->SetProperty(property.GetCSSProperty().PropertyID(), *value);
+ set->SetProperty(property.GetCSSPropertyName(), *value);
cascade.MutableMatchResult().FinishAddingUARules();
cascade.MutableMatchResult().FinishAddingUserRules();
cascade.MutableMatchResult().AddMatchedProperties(set);
@@ -1028,6 +1066,7 @@ scoped_refptr<const ComputedStyle> StyleResolver::StyleForPage(
return initial_style;
StyleResolverState state(GetDocument(), *GetDocument().documentElement(),
+ StyleRecalcContext(),
StyleRequest(initial_style.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
@@ -1154,6 +1193,13 @@ StyleResolver::CascadedValuesForElement(Element* element, PseudoId pseudo_id) {
return cascade.GetCascadedValues();
}
+Element* StyleResolver::FindContainerForElement(
+ Element* element,
+ const AtomicString& container_name) {
+ auto context = StyleRecalcContext::FromAncestors(*element);
+ return ContainerQueryEvaluator::FindContainer(context, container_name);
+}
+
RuleIndexList* StyleResolver::PseudoCSSRulesForElement(
Element* element,
PseudoId pseudo_id,
@@ -1161,8 +1207,8 @@ RuleIndexList* StyleResolver::PseudoCSSRulesForElement(
DCHECK(element);
StyleResolverState state(GetDocument(), *element);
MatchResult match_result;
- // TODO(crbug.com/1145970): Use actual StyleRecalcContext.
- StyleRecalcContext style_recalc_context;
+ StyleRecalcContext style_recalc_context =
+ StyleRecalcContext::FromAncestors(*element);
ElementRuleCollector collector(state.ElementContext(), style_recalc_context,
selector_filter_, match_result, state.Style(),
EInsideLink::kNotInsideLink);
@@ -1223,12 +1269,13 @@ bool StyleResolver::ApplyAnimatedStyle(StyleResolverState& state,
DCHECK(animating_element == &element ||
animating_element->ParentOrShadowHostElement() == element);
- if (!HasAnimationsOrTransitions(state)) {
- // Ensure that the base computed style is not stale even if not currently
- // running an animation or transition. This ensures that any new transitions
- // use the correct starting point based on the "before change" style.
- UpdateAnimationBaseComputedStyle(state, cascade, false);
+ if (!HasAnimationsOrTransitions(state))
return false;
+
+ if (!IsAnimationStyleChange(*animating_element) ||
+ !state.StyleRef().BaseData()) {
+ state.StyleRef().SetBaseData(StyleBaseData::Create(
+ ComputedStyle::Clone(state.StyleRef()), cascade.GetImportantSet()));
}
CSSAnimations::CalculateAnimationUpdate(
@@ -1237,35 +1284,22 @@ bool StyleResolver::ApplyAnimatedStyle(StyleResolverState& state,
CSSAnimations::CalculateCompositorAnimationUpdate(
state.AnimationUpdate(), *animating_element, element, *state.Style(),
state.ParentStyle(), WasViewportResized());
- CSSAnimations::CalculateTransitionUpdate(
- state.AnimationUpdate(), CSSAnimations::PropertyPass::kStandard,
- *animating_element, *state.Style());
CSSAnimations::CalculateTransitionUpdate(state.AnimationUpdate(),
- CSSAnimations::PropertyPass::kCustom,
*animating_element, *state.Style());
CSSAnimations::SnapshotCompositorKeyframes(
element, state.AnimationUpdate(), *state.Style(), state.ParentStyle());
- bool has_update = !state.AnimationUpdate().IsEmpty();
- UpdateAnimationBaseComputedStyle(state, cascade, has_update);
-
- if (!has_update)
+ if (state.AnimationUpdate().IsEmpty())
return false;
- const ActiveInterpolationsMap& standard_animations =
- state.AnimationUpdate().ActiveInterpolationsForStandardAnimations();
- const ActiveInterpolationsMap& standard_transitions =
- state.AnimationUpdate().ActiveInterpolationsForStandardTransitions();
- const ActiveInterpolationsMap& custom_animations =
- state.AnimationUpdate().ActiveInterpolationsForCustomAnimations();
- const ActiveInterpolationsMap& custom_transitions =
- state.AnimationUpdate().ActiveInterpolationsForCustomTransitions();
+ const ActiveInterpolationsMap& animations =
+ state.AnimationUpdate().ActiveInterpolationsForAnimations();
+ const ActiveInterpolationsMap& transitions =
+ state.AnimationUpdate().ActiveInterpolationsForTransitions();
- cascade.AddInterpolations(&standard_animations, CascadeOrigin::kAnimation);
- cascade.AddInterpolations(&standard_transitions, CascadeOrigin::kTransition);
- cascade.AddInterpolations(&custom_animations, CascadeOrigin::kAnimation);
- cascade.AddInterpolations(&custom_transitions, CascadeOrigin::kTransition);
+ cascade.AddInterpolations(&animations, CascadeOrigin::kAnimation);
+ cascade.AddInterpolations(&transitions, CascadeOrigin::kTransition);
CascadeFilter filter;
if (state.Style()->StyleType() == kPseudoIdMarker)
@@ -1428,10 +1462,11 @@ bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) {
return false;
ElementAnimations* element_animations = GetElementAnimations(state);
- if (!element_animations || !element_animations->BaseComputedStyle())
+ if (!element_animations || !element_animations->IsAnimationStyleChange())
return false;
- if (!element_animations->IsAnimationStyleChange())
+ StyleBaseData* base_data = GetBaseData(state);
+ if (!base_data || !base_data->GetBaseComputedStyle())
return false;
// Animating a custom property can have side effects on other properties
@@ -1449,10 +1484,8 @@ bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) {
// animation. We cannot use the base computed style optimization in such
// cases.
if (CSSAnimations::IsAnimatingFontAffectingProperties(element_animations)) {
- if (element_animations->BaseComputedStyle() &&
- element_animations->BaseComputedStyle()->HasFontRelativeUnits()) {
+ if (base_data->GetBaseComputedStyle()->HasFontRelativeUnits())
return false;
- }
}
// Normally, we apply all active animation effects on top of the style created
@@ -1462,11 +1495,16 @@ bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) {
// style, we disable the base computed style optimization.
// [1] https://drafts.csswg.org/css-cascade-4/#cascade-origin
if (CSSAnimations::IsAnimatingStandardProperties(
- element_animations, element_animations->BaseImportantSet(),
+ element_animations, base_data->GetBaseImportantSet(),
KeyframeEffect::kDefaultPriority)) {
return false;
}
+ if (TextAutosizingMultiplierChanged(state,
+ *base_data->GetBaseComputedStyle())) {
+ return false;
+ }
+
return true;
}
@@ -1480,11 +1518,7 @@ const CSSValue* StyleResolver::ComputeValue(
state.SetStyle(ComputedStyle::Clone(*base_style));
auto* set =
MakeGarbageCollected<MutableCSSPropertyValueSet>(state.GetParserMode());
- if (property_name.IsCustomProperty()) {
- set->SetProperty(CSSPropertyValue(property_name, value));
- } else {
- set->SetProperty(property_name.Id(), value);
- }
+ set->SetProperty(property_name, value);
cascade.MutableMatchResult().FinishAddingUARules();
cascade.MutableMatchResult().FinishAddingUserRules();
cascade.MutableMatchResult().AddMatchedProperties(set);
@@ -1497,15 +1531,37 @@ const CSSValue* StyleResolver::ComputeValue(
*state.Style());
}
+FilterOperations StyleResolver::ComputeFilterOperations(
+ Element* element,
+ const Font& font,
+ const CSSValue& filter_value) {
+ scoped_refptr<ComputedStyle> parent = CreateComputedStyle();
+ parent->SetFont(font);
+
+ // TODO(crbug.com/1145970): Use actual StyleRecalcContext.
+ StyleResolverState state(GetDocument(), *element, StyleRecalcContext(),
+ StyleRequest(parent.get()));
+
+ state.SetStyle(ComputedStyle::Clone(*parent));
+
+ StyleBuilder::ApplyProperty(GetCSSPropertyFilter(), state,
+ ScopedCSSValue(filter_value, &GetDocument()));
+
+ state.LoadPendingResources();
+
+ return state.Style()->Filter();
+}
+
scoped_refptr<ComputedStyle> StyleResolver::StyleForInterpolations(
Element& element,
ActiveInterpolationsMap& interpolations) {
+ // TODO(crbug.com/1145970): Use actual StyleRecalcContext.
+ StyleRecalcContext style_recalc_context;
StyleRequest style_request;
- StyleResolverState state(GetDocument(), element, style_request);
+ StyleResolverState state(GetDocument(), element, style_recalc_context,
+ style_request);
STACK_UNINITIALIZED StyleCascade cascade(state);
- // TODO(crbug.com/1145970): Use actual StyleRecalcContext.
- StyleRecalcContext style_recalc_context;
ApplyBaseStyle(&element, style_recalc_context, style_request, state, cascade);
ApplyInterpolations(state, cascade, interpolations);
@@ -1613,7 +1669,8 @@ void StyleResolver::ComputeFont(Element& element,
};
// TODO(timloh): This is weird, the style is being used as its own parent
- StyleResolverState state(GetDocument(), element, StyleRequest(style));
+ StyleResolverState state(GetDocument(), element, StyleRecalcContext(),
+ StyleRequest(style));
state.SetStyle(style);
for (const CSSProperty* property : properties) {
@@ -1715,17 +1772,43 @@ bool PropagateScrollSnapStyleToViewport(
} // namespace
+bool StyleResolver::ShouldStopBodyPropagation(const Element& body_or_html) {
+ DCHECK(!body_or_html.NeedsReattachLayoutTree())
+ << "This method relies on LayoutObject to be attached and up-to-date";
+ DCHECK(IsA<HTMLBodyElement>(body_or_html) ||
+ IsA<HTMLHtmlElement>(body_or_html));
+ LayoutObject* layout_object = body_or_html.GetLayoutObject();
+ if (!layout_object)
+ return true;
+ bool contained = layout_object->ShouldApplyAnyContainment();
+ if (contained) {
+ UseCounter::Count(GetDocument(), IsA<HTMLHtmlElement>(body_or_html)
+ ? WebFeature::kHTMLRootContained
+ : WebFeature::kHTMLBodyContained);
+ }
+ if (!RuntimeEnabledFeatures::CSSContainedBodyPropagationEnabled())
+ return false;
+ DCHECK_EQ(contained,
+ layout_object->StyleRef().ShouldApplyAnyContainment(body_or_html))
+ << "Applied containment must give the same result from LayoutObject and "
+ "ComputedStyle";
+ return contained;
+}
+
void StyleResolver::PropagateStyleToViewport() {
DCHECK(GetDocument().InStyleRecalc());
- HTMLBodyElement* body = GetDocument().FirstBodyElement();
Element* document_element = GetDocument().documentElement();
-
const ComputedStyle* document_element_style =
document_element && document_element->GetLayoutObject()
? document_element->GetComputedStyle()
: nullptr;
- const ComputedStyle* body_style =
- body && body->GetLayoutObject() ? body->GetComputedStyle() : nullptr;
+ const ComputedStyle* body_style = nullptr;
+ if (HTMLBodyElement* body = GetDocument().FirstBodyElement()) {
+ if (!ShouldStopBodyPropagation(*document_element) &&
+ !ShouldStopBodyPropagation(*body)) {
+ body_style = body->GetComputedStyle();
+ }
+ }
const ComputedStyle& viewport_style =
GetDocument().GetLayoutView()->StyleRef();
@@ -1751,10 +1834,8 @@ void StyleResolver::PropagateStyleToViewport() {
// <html> root element with no background steals background from its first
// <body> child.
// Also see LayoutBoxModelObject::BackgroundTransfersToView()
- if (body_style && IsA<HTMLHtmlElement>(document_element) &&
- !background_style->HasBackground()) {
+ if (body_style && !background_style->HasBackground())
background_style = body_style;
- }
Color background_color = Color::kTransparent;
FillLayer background_layers(EFillLayerType::kBackground, true);
@@ -1794,22 +1875,17 @@ void StyleResolver::PropagateStyleToViewport() {
// Overflow
{
- const ComputedStyle* overflow_style = nullptr;
- if (Element* viewport_element = GetDocument().ViewportDefiningElement()) {
- if (viewport_element == body) {
+ const ComputedStyle* overflow_style = document_element_style;
+ if (body_style) {
+ if (document_element_style->IsOverflowVisibleAlongBothAxes()) {
overflow_style = body_style;
- } else {
- DCHECK_EQ(viewport_element, document_element);
- overflow_style = document_element_style;
-
+ } else if (body_style->IsScrollContainer()) {
// The body element has its own scrolling box, independent from the
- // viewport. This is a bit of a weird edge case in the CSS spec that we
- // might want to try to eliminate some day (eg. for ScrollTopLeftInterop
- // - see http://crbug.com/157855).
- if (body_style && body_style->IsScrollContainer()) {
- UseCounter::Count(GetDocument(),
- WebFeature::kBodyScrollsInAdditionToViewport);
- }
+ // viewport. This is a bit of a weird edge case in the CSS spec that
+ // we might want to try to eliminate some day (e.g. for
+ // ScrollTopLeftInterop - see http://crbug.com/157855).
+ UseCounter::Count(GetDocument(),
+ WebFeature::kBodyScrollsInAdditionToViewport);
}
}
@@ -1900,6 +1976,8 @@ void StyleResolver::PropagateStyleToViewport() {
false);
PROPAGATE_FROM(document_element_style, ScrollbarGutter, SetScrollbarGutter,
kScrollbarGutterAuto);
+ PROPAGATE_FROM(document_element_style, ForcedColorAdjust,
+ SetForcedColorAdjust, EForcedColorAdjust::kAuto);
}
changed |= PropagateScrollSnapStyleToViewport(
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 7eadad1e068..4e72fa1db26 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
@@ -143,6 +143,8 @@ class CORE_EXPORT StyleResolver final : public GarbageCollected<StyleResolver> {
Element*,
PseudoId);
+ Element* FindContainerForElement(Element*, const AtomicString&);
+
void ComputeFont(Element&, ComputedStyle*, const CSSPropertyValueSet&);
// FIXME: Rename to reflect the purpose, like didChangeFontSize or something.
@@ -161,6 +163,14 @@ class CORE_EXPORT StyleResolver final : public GarbageCollected<StyleResolver> {
const CSSPropertyName&,
const CSSValue&);
+ // Compute FilterOperations from the specified CSSValue, using the provided
+ // Font to resolve any font-relative units.
+ //
+ // Triggers loading of any external references held by |CSSValue|.
+ FilterOperations ComputeFilterOperations(Element*,
+ const Font&,
+ const CSSValue&);
+
scoped_refptr<ComputedStyle> StyleForInterpolations(
Element& element,
ActiveInterpolationsMap& animations);
@@ -175,6 +185,10 @@ class CORE_EXPORT StyleResolver final : public GarbageCollected<StyleResolver> {
const ComputedStyle& base_style,
ActiveInterpolationsMap& transition_interpolations);
+ // Check if the BODY or HTML element's display or containment stops
+ // propagation of BODY style to HTML and viewport.
+ bool ShouldStopBodyPropagation(const Element& body_or_html);
+
void Trace(Visitor*) const;
private:
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
index 04d8b7965a3..09e0e1229b4 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -44,9 +44,11 @@ bool CanCacheBaseStyle(const StyleRequest& style_request) {
} // namespace
-StyleResolverState::StyleResolverState(Document& document,
- Element& element,
- const StyleRequest& style_request)
+StyleResolverState::StyleResolverState(
+ Document& document,
+ Element& element,
+ const StyleRecalcContext& style_recalc_context,
+ const StyleRequest& style_request)
: element_context_(element),
document_(&document),
parent_style_(style_request.parent_override),
@@ -60,6 +62,7 @@ StyleResolverState::StyleResolverState(Document& document,
element_type_(style_request.IsPseudoStyleRequest()
? ElementType::kPseudoElement
: ElementType::kElement),
+ nearest_container_(style_recalc_context.container),
can_cache_base_style_(blink::CanCacheBaseStyle(style_request)) {
DCHECK(!!parent_style_ == !!layout_parent_style_);
@@ -87,7 +90,7 @@ void StyleResolverState::SetStyle(scoped_refptr<ComputedStyle> style) {
style_ = std::move(style);
css_to_length_conversion_data_ = CSSToLengthConversionData(
style_.get(), RootElementStyle(), GetDocument().GetLayoutView(),
- style_->EffectiveZoom());
+ nearest_container_, style_->EffectiveZoom());
}
scoped_refptr<ComputedStyle> StyleResolverState::TakeStyle() {
@@ -106,8 +109,10 @@ CSSToLengthConversionData StyleResolverState::UnzoomedLengthConversionData(
em, rem, &font_style->GetFont(), font_style->EffectiveZoom());
CSSToLengthConversionData::ViewportSize viewport_size(
GetDocument().GetLayoutView());
+ CSSToLengthConversionData::ContainerSizes container_sizes(nearest_container_);
- return CSSToLengthConversionData(Style(), font_sizes, viewport_size, 1);
+ return CSSToLengthConversionData(Style(), font_sizes, viewport_size,
+ container_sizes, 1);
}
CSSToLengthConversionData StyleResolverState::FontSizeConversionData() const {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
index b0379a70dc9..a1ebb5023fb 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -42,6 +42,7 @@ namespace blink {
class ComputedStyle;
class FontDescription;
class PseudoElement;
+class StyleRecalcContext;
// A per-element object which wraps an ElementResolveContext. It collects state
// throughout the process of computing the style. It also gives convenient
@@ -52,7 +53,10 @@ class CORE_EXPORT StyleResolverState {
enum class ElementType { kElement, kPseudoElement };
public:
- StyleResolverState(Document&, Element&, const StyleRequest& = StyleRequest());
+ StyleResolverState(Document&,
+ Element&,
+ const StyleRecalcContext& = StyleRecalcContext(),
+ const StyleRequest& = StyleRequest());
StyleResolverState(const StyleResolverState&) = delete;
StyleResolverState& operator=(const StyleResolverState&) = delete;
~StyleResolverState();
@@ -190,6 +194,7 @@ class CORE_EXPORT StyleResolverState {
PseudoElement* pseudo_element_;
ElementStyleResources element_style_resources_;
ElementType element_type_;
+ Element* nearest_container_;
// True if the base style can be cached to optimize style recalculations for
// animation updates or transition retargeting.
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
index c225ee52e32..7e35c1f5631 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -88,13 +88,14 @@ TEST_F(StyleResolverTest, AnimationBaseComputedStyle) {
animations.SetAnimationStyleChange(true);
StyleResolver& resolver = GetStyleEngine().GetStyleResolver();
- ASSERT_TRUE(resolver.ResolveStyle(div, StyleRecalcContext()));
- EXPECT_EQ(20, resolver.ResolveStyle(div, StyleRecalcContext())->FontSize());
- ASSERT_TRUE(animations.BaseComputedStyle());
- EXPECT_EQ(20, animations.BaseComputedStyle()->FontSize());
-
- // Getting style with customized parent style should not affect cached
- // animation base computed style.
+ auto style1 = resolver.ResolveStyle(div, StyleRecalcContext());
+ ASSERT_TRUE(style1);
+ EXPECT_EQ(20, style1->FontSize());
+ ASSERT_TRUE(style1->GetBaseComputedStyle());
+ EXPECT_EQ(20, style1->GetBaseComputedStyle()->FontSize());
+
+ // Getting style with customized parent style should not affect previously
+ // produced animation base computed style.
const ComputedStyle* parent_style =
GetDocument().documentElement()->GetComputedStyle();
StyleRequest style_request;
@@ -102,8 +103,8 @@ TEST_F(StyleResolverTest, AnimationBaseComputedStyle) {
style_request.layout_parent_override = parent_style;
EXPECT_EQ(10, resolver.ResolveStyle(div, StyleRecalcContext(), style_request)
->FontSize());
- ASSERT_TRUE(animations.BaseComputedStyle());
- EXPECT_EQ(20, animations.BaseComputedStyle()->FontSize());
+ ASSERT_TRUE(style1->GetBaseComputedStyle());
+ EXPECT_EQ(20, style1->GetBaseComputedStyle()->FontSize());
EXPECT_EQ(20, resolver.ResolveStyle(div, StyleRecalcContext())->FontSize());
}
@@ -134,9 +135,6 @@ TEST_F(StyleResolverTest, BaseReusableIfFontRelativeUnitsAbsent) {
GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
StyleForId("div");
- ASSERT_TRUE(div->GetElementAnimations());
- EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
-
StyleResolverState state(GetDocument(), *div);
EXPECT_TRUE(StyleResolver::CanReuseBaseComputedStyle(state));
}
@@ -164,13 +162,12 @@ TEST_F(StyleResolverTest, AnimationNotMaskedByImportant) {
div->SetNeedsAnimationStyleRecalc();
GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
- StyleForId("div");
+ auto style = StyleForId("div");
- ASSERT_TRUE(div->GetElementAnimations());
- const CSSBitset* bitset = div->GetElementAnimations()->BaseImportantSet();
+ const CSSBitset* bitset = style->GetBaseImportantSet();
EXPECT_FALSE(CSSAnimations::IsAnimatingStandardProperties(
div->GetElementAnimations(), bitset, KeyframeEffect::kDefaultPriority));
- EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
+ EXPECT_TRUE(style->GetBaseComputedStyle());
EXPECT_FALSE(bitset && bitset->Has(CSSPropertyID::kWidth));
EXPECT_TRUE(bitset && bitset->Has(CSSPropertyID::kHeight));
}
@@ -235,11 +232,10 @@ TEST_F(StyleResolverTest, AnimationMaskedByImportant) {
div->SetNeedsAnimationStyleRecalc();
GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
- StyleForId("div");
+ auto style = StyleForId("div");
- ASSERT_TRUE(div->GetElementAnimations());
- EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
- EXPECT_TRUE(div->GetElementAnimations()->BaseImportantSet());
+ EXPECT_TRUE(style->GetBaseComputedStyle());
+ EXPECT_TRUE(style->GetBaseImportantSet());
StyleResolverState state(GetDocument(), *div);
EXPECT_FALSE(StyleResolver::CanReuseBaseComputedStyle(state));
@@ -275,12 +271,8 @@ TEST_F(StyleResolverTest,
EXPECT_EQ("20px", ComputedValue("font-size", *StyleForId("target")));
// Bump the animation time to ensure a transition reversal.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
transition->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(50),
ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- transition->setCurrentTime(CSSNumberish::FromDouble(50));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
transition->pause();
UpdateAllLifecyclePhasesForTest();
const String before_reversal_font_size =
@@ -298,57 +290,6 @@ TEST_F(StyleResolverTest,
ComputedValue("font-size", *StyleForId("target")));
}
-TEST_F(StyleResolverTest, NonCachableStyleCheckDoesNotAffectBaseComputedStyle) {
- GetDocument().documentElement()->setInnerHTML(R"HTML(
- <style>
- .adjust { color: rgb(0, 0, 0); }
- </style>
- <div>
- <div style="color: rgb(0, 128, 0)">
- <div id="target" style="transition: color 1s linear"></div>
- </div>
- </div>
- )HTML");
- UpdateAllLifecyclePhasesForTest();
-
- Element* target = GetDocument().getElementById("target");
-
- EXPECT_EQ("rgb(0, 128, 0)", ComputedValue("color", *StyleForId("target")));
-
- // Trigger a transition on an inherited property.
- target->setAttribute(html_names::kClassAttr, "adjust");
- UpdateAllLifecyclePhasesForTest();
- ElementAnimations* element_animations = target->GetElementAnimations();
- EXPECT_TRUE(element_animations);
- Animation* transition = (*element_animations->Animations().begin()).key;
- EXPECT_TRUE(transition);
-
- // Advance to the midpoint of the transition.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- transition->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(500),
- ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- transition->setCurrentTime(CSSNumberish::FromDouble(500));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ("rgb(0, 64, 0)", ComputedValue("color", *StyleForId("target")));
- EXPECT_TRUE(element_animations->BaseComputedStyle());
-
- element_animations->ClearBaseComputedStyle();
-
- // Perform a non-cacheable style resolution, and ensure that the base computed
- // style is not updated.
- StyleRequest style_request;
- style_request.matching_behavior = kMatchAllRulesExcludingSMIL;
- GetStyleEngine().GetStyleResolver().ResolveStyle(target, StyleRecalcContext(),
- style_request);
- EXPECT_FALSE(element_animations->BaseComputedStyle());
-
- // Computing the style with default args updates the base computed style.
- EXPECT_EQ("rgb(0, 64, 0)", ComputedValue("color", *StyleForId("target")));
- EXPECT_TRUE(element_animations->BaseComputedStyle());
-}
-
class StyleResolverFontRelativeUnitTest
: public testing::WithParamInterface<const char*>,
public StyleResolverTest {};
@@ -371,8 +312,7 @@ TEST_P(StyleResolverFontRelativeUnitTest,
auto computed_style = StyleForId("div");
EXPECT_TRUE(computed_style->HasFontRelativeUnits());
- ASSERT_TRUE(div->GetElementAnimations());
- EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
+ EXPECT_TRUE(computed_style->GetBaseComputedStyle());
StyleResolverState state(GetDocument(), *div);
EXPECT_FALSE(StyleResolver::CanReuseBaseComputedStyle(state));
@@ -396,8 +336,7 @@ TEST_P(StyleResolverFontRelativeUnitTest,
auto computed_style = StyleForId("div");
EXPECT_TRUE(computed_style->HasFontRelativeUnits());
- ASSERT_TRUE(div->GetElementAnimations());
- EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
+ EXPECT_TRUE(computed_style->GetBaseComputedStyle());
StyleResolverState state(GetDocument(), *div);
EXPECT_TRUE(StyleResolver::CanReuseBaseComputedStyle(state));
@@ -1120,6 +1059,196 @@ TEST_F(StyleResolverTest, InheritStyleImagesFromDisplayContents) {
<< "-webkit-mask-image is fetched";
}
+TEST_F(StyleResolverTest, TextShadowInHighlightPseudoNotCounted1) {
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ * {
+ text-shadow: 5px 5px green;
+ }
+ </style>
+ <div id="target">target</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+ const auto* element_style = target->GetComputedStyle();
+ ASSERT_TRUE(element_style);
+
+ StyleRequest pseudo_style_request;
+ pseudo_style_request.parent_override = element_style;
+ pseudo_style_request.layout_parent_override = element_style;
+ pseudo_style_request.pseudo_id = kPseudoIdSelection;
+ scoped_refptr<ComputedStyle> selection_style =
+ GetDocument().GetStyleResolver().ResolveStyle(
+ target, StyleRecalcContext(), pseudo_style_request);
+ ASSERT_FALSE(selection_style);
+
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+}
+
+TEST_F(StyleResolverTest, TextShadowInHighlightPseudoNotCounted2) {
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ * {
+ text-shadow: 5px 5px green;
+ }
+ ::selection {
+ color: white;
+ background: blue;
+ }
+ </style>
+ <div id="target">target</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+ const auto* element_style = target->GetComputedStyle();
+ ASSERT_TRUE(element_style);
+
+ StyleRequest pseudo_style_request;
+ pseudo_style_request.parent_override = element_style;
+ pseudo_style_request.layout_parent_override = element_style;
+ pseudo_style_request.pseudo_id = kPseudoIdSelection;
+ scoped_refptr<ComputedStyle> selection_style =
+ GetDocument().GetStyleResolver().ResolveStyle(
+ target, StyleRecalcContext(), pseudo_style_request);
+ ASSERT_TRUE(selection_style);
+
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+}
+
+TEST_F(StyleResolverTest, TextShadowInHighlightPseudotNone) {
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ * {
+ text-shadow: 5px 5px green;
+ }
+ ::selection {
+ text-shadow: none;
+ }
+ </style>
+ <div id="target">target</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+ const auto* element_style = target->GetComputedStyle();
+ ASSERT_TRUE(element_style);
+
+ StyleRequest pseudo_style_request;
+ pseudo_style_request.parent_override = element_style;
+ pseudo_style_request.layout_parent_override = element_style;
+ pseudo_style_request.pseudo_id = kPseudoIdSelection;
+ scoped_refptr<ComputedStyle> selection_style =
+ GetDocument().GetStyleResolver().ResolveStyle(
+ target, StyleRecalcContext(), pseudo_style_request);
+ ASSERT_TRUE(selection_style);
+
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+}
+
+TEST_F(StyleResolverTest, TextShadowInHighlightPseudoNotNone1) {
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ ::selection {
+ text-shadow: 5px 5px green;
+ }
+ </style>
+ <div id="target">target</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+ const auto* element_style = target->GetComputedStyle();
+ ASSERT_TRUE(element_style);
+
+ StyleRequest pseudo_style_request;
+ pseudo_style_request.parent_override = element_style;
+ pseudo_style_request.layout_parent_override = element_style;
+ pseudo_style_request.pseudo_id = kPseudoIdSelection;
+ scoped_refptr<ComputedStyle> selection_style =
+ GetDocument().GetStyleResolver().ResolveStyle(
+ target, StyleRecalcContext(), pseudo_style_request);
+ ASSERT_TRUE(selection_style);
+
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+}
+
+TEST_F(StyleResolverTest, TextShadowInHighlightPseudoNotNone2) {
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ * {
+ text-shadow: 5px 5px green;
+ }
+ ::selection {
+ text-shadow: 5px 5px green;
+ }
+ </style>
+ <div id="target">target</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+ const auto* element_style = target->GetComputedStyle();
+ ASSERT_TRUE(element_style);
+
+ StyleRequest pseudo_style_request;
+ pseudo_style_request.parent_override = element_style;
+ pseudo_style_request.layout_parent_override = element_style;
+ pseudo_style_request.pseudo_id = kPseudoIdSelection;
+ scoped_refptr<ComputedStyle> selection_style =
+ GetDocument().GetStyleResolver().ResolveStyle(
+ target, StyleRecalcContext(), pseudo_style_request);
+ ASSERT_TRUE(selection_style);
+
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kTextShadowInHighlightPseudo));
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kTextShadowNotNoneInHighlightPseudo));
+}
+
TEST_F(StyleResolverTestCQ, DependsOnContainerQueries) {
GetDocument().documentElement()->setInnerHTML(R"HTML(
<style>
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 59e969843b1..ae56fefad5a 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
@@ -250,9 +250,10 @@ Length ViewportStyleResolver::ViewportLengthValue(CSSPropertyID id) {
initial_style_.get());
CSSToLengthConversionData::ViewportSize viewport_size(
view->InitialViewportWidth(), view->InitialViewportHeight());
+ CSSToLengthConversionData::ContainerSizes container_sizes;
Length result = primitive_value->ConvertToLength(CSSToLengthConversionData(
- initial_style_.get(), font_sizes, viewport_size, 1.0f));
+ initial_style_.get(), font_sizes, viewport_size, container_sizes, 1.0f));
if (result.IsFixed() && document_->GetPage()) {
float scaled_value =
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 3f3a42381d9..c3f6e5cf284 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
@@ -185,6 +185,7 @@ bool SupportsInvalidation(CSSSelector::PseudoType type) {
case CSSSelector::kPseudoHighlight:
case CSSSelector::kPseudoSpellingError:
case CSSSelector::kPseudoGrammarError:
+ case CSSSelector::kPseudoHas:
return true;
case CSSSelector::kPseudoUnknown:
case CSSSelector::kPseudoLeftPage:
@@ -733,6 +734,13 @@ void RuleFeatureSet::ExtractInvalidationSetFeaturesFromSelectorList(
return;
CSSSelector::PseudoType pseudo_type = simple_selector.GetPseudoType();
+ // For the :has pseudo class, we should not extract invalidation set features
+ // here because the :has invalidation direction is different with others.
+ // (preceding-sibling/ancestors/preceding-sibling-of-ancestors)
+ // TODO(blee@igalia.com) Need to add :has invalidation
+ if (UNLIKELY(pseudo_type == CSSSelector::kPseudoHas))
+ return;
+
DCHECK(SupportsInvalidationWithSelectorList(pseudo_type));
const CSSSelector* sub_selector = selector_list->First();
@@ -950,7 +958,16 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForSimpleSelector(
return;
}
- if (simple_selector.GetPseudoType() == CSSSelector::kPseudoPart)
+ CSSSelector::PseudoType pseudo_type = simple_selector.GetPseudoType();
+
+ // For the :has pseudo class, we should not extract invalidation set features
+ // here because the :has invalidation direction is different with others.
+ // (preceding-sibling/ancestors/preceding-sibling-of-ancestors)
+ // TODO(blee@igalia.com) Need to add :has invalidation
+ if (UNLIKELY(pseudo_type == CSSSelector::kPseudoHas))
+ return;
+
+ if (pseudo_type == CSSSelector::kPseudoPart)
descendant_features.invalidation_flags.SetInvalidatesParts(true);
AddFeaturesToInvalidationSetsForSelectorList(
@@ -1019,6 +1036,8 @@ RuleFeatureSet::SelectorPreMatch RuleFeatureSet::CollectFeaturesFromRuleData(
kSelectorNeverMatches) {
return kSelectorNeverMatches;
}
+ metadata.uses_container_queries |=
+ static_cast<bool>(rule_data->GetContainerQuery());
metadata_.Add(metadata);
@@ -1036,6 +1055,8 @@ RuleFeatureSet::SelectorPreMatch RuleFeatureSet::CollectFeaturesFromSelector(
for (const CSSSelector* current = &selector; current;
current = current->TagHistory()) {
switch (current->GetPseudoType()) {
+ case CSSSelector::kPseudoHas:
+ break;
case CSSSelector::kPseudoFirstLine:
metadata.uses_first_line_rules = true;
break;
@@ -1089,6 +1110,7 @@ RuleFeatureSet::SelectorPreMatch RuleFeatureSet::CollectFeaturesFromSelector(
void RuleFeatureSet::FeatureMetadata::Add(const FeatureMetadata& other) {
uses_first_line_rules |= other.uses_first_line_rules;
uses_window_inactive_selector |= other.uses_window_inactive_selector;
+ uses_container_queries |= other.uses_container_queries;
max_direct_adjacent_selectors = std::max(max_direct_adjacent_selectors,
other.max_direct_adjacent_selectors);
}
@@ -1096,6 +1118,7 @@ void RuleFeatureSet::FeatureMetadata::Add(const FeatureMetadata& other) {
void RuleFeatureSet::FeatureMetadata::Clear() {
uses_first_line_rules = false;
uses_window_inactive_selector = false;
+ uses_container_queries = false;
needs_full_recalc_for_rule_set_invalidation = false;
max_direct_adjacent_selectors = 0;
invalidates_parts = false;
@@ -1105,6 +1128,7 @@ bool RuleFeatureSet::FeatureMetadata::operator==(
const FeatureMetadata& other) const {
return uses_first_line_rules == other.uses_first_line_rules &&
uses_window_inactive_selector == other.uses_window_inactive_selector &&
+ uses_container_queries == other.uses_container_queries &&
needs_full_recalc_for_rule_set_invalidation ==
other.needs_full_recalc_for_rule_set_invalidation &&
max_direct_adjacent_selectors == other.max_direct_adjacent_selectors &&
@@ -1545,6 +1569,7 @@ String RuleFeatureSet::ToString() const {
StringBuilder metadata;
metadata.Append(metadata_.uses_first_line_rules ? "F" : "");
metadata.Append(metadata_.uses_window_inactive_selector ? "W" : "");
+ metadata.Append(metadata_.uses_container_queries ? "C" : "");
metadata.Append(metadata_.needs_full_recalc_for_rule_set_invalidation ? "R"
: "");
metadata.Append(metadata_.invalidates_parts ? "P" : "");
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 d794a4661f8..5c3bf76d234 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
@@ -69,6 +69,7 @@ class CORE_EXPORT RuleFeatureSet {
bool UsesWindowInactiveSelector() const {
return metadata_.uses_window_inactive_selector;
}
+ bool UsesContainerQueries() const { return metadata_.uses_container_queries; }
bool NeedsFullRecalcForRuleSetInvalidation() const {
return metadata_.needs_full_recalc_for_rule_set_invalidation;
}
@@ -205,6 +206,7 @@ class CORE_EXPORT RuleFeatureSet {
bool uses_first_line_rules = false;
bool uses_window_inactive_selector = false;
+ bool uses_container_queries = false;
bool needs_full_recalc_for_rule_set_invalidation = false;
unsigned max_direct_adjacent_selectors = 0;
bool invalidates_parts = false;
diff --git a/chromium/third_party/blink/renderer/core/css/rule_set.h b/chromium/third_party/blink/renderer/core/css/rule_set.h
index 09afd61d4ff..9ee704a291f 100644
--- a/chromium/third_party/blink/renderer/core/css/rule_set.h
+++ b/chromium/third_party/blink/renderer/core/css/rule_set.h
@@ -256,22 +256,22 @@ class CORE_EXPORT RuleSet final : public GarbageCollected<RuleSet> {
const HeapVector<Member<const RuleData>>* IdRules(
const AtomicString& key) const {
DCHECK(!pending_rules_);
- return id_rules_.at(key);
+ return id_rules_.DeprecatedAtOrEmptyValue(key);
}
const HeapVector<Member<const RuleData>>* ClassRules(
const AtomicString& key) const {
DCHECK(!pending_rules_);
- return class_rules_.at(key);
+ return class_rules_.DeprecatedAtOrEmptyValue(key);
}
const HeapVector<Member<const RuleData>>* TagRules(
const AtomicString& key) const {
DCHECK(!pending_rules_);
- return tag_rules_.at(key);
+ return tag_rules_.DeprecatedAtOrEmptyValue(key);
}
const HeapVector<Member<const RuleData>>* UAShadowPseudoElementRules(
const AtomicString& key) const {
DCHECK(!pending_rules_);
- return ua_shadow_pseudo_element_rules_.at(key);
+ return ua_shadow_pseudo_element_rules_.DeprecatedAtOrEmptyValue(key);
}
const HeapVector<Member<const RuleData>>* LinkPseudoClassRules() const {
DCHECK(!pending_rules_);
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 ce49058a766..de183780345 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_checker.cc
@@ -32,6 +32,8 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/renderer/core/css/css_selector_list.h"
+#include "third_party/blink/renderer/core/css/has_argument_match_context.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
#include "third_party/blink/renderer/core/css/part_names.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -215,6 +217,7 @@ bool SelectorChecker::Match(const SelectorCheckingContext& context,
if (context.selector->IsLastInTagHistory())
return false;
}
+ HasMatchedCacheScope has_matched_cache_scope(&context.element->GetDocument());
return MatchSelector(context, result) == kSelectorMatches;
}
@@ -311,6 +314,10 @@ SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
next_context.pseudo_id = kPseudoIdNone;
switch (relation) {
+ case CSSSelector::kRelativeDescendant:
+ DCHECK(result.has_argument_leftmost_compound_matches);
+ result.has_argument_leftmost_compound_matches->push_back(context.element);
+ FALLTHROUGH;
case CSSSelector::kDescendant:
if (next_context.selector->GetPseudoType() == CSSSelector::kPseudoScope) {
if (next_context.selector->IsLastInTagHistory()) {
@@ -330,6 +337,10 @@ SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
next_context.is_inside_visited_link = false;
}
return kSelectorFailsCompletely;
+ case CSSSelector::kRelativeChild:
+ DCHECK(result.has_argument_leftmost_compound_matches);
+ result.has_argument_leftmost_compound_matches->push_back(context.element);
+ FALLTHROUGH;
case CSSSelector::kChild: {
if (next_context.selector->GetPseudoType() == CSSSelector::kPseudoScope) {
if (next_context.selector->IsLastInTagHistory()) {
@@ -344,6 +355,10 @@ SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
return kSelectorFailsCompletely;
return MatchSelector(next_context, result);
}
+ case CSSSelector::kRelativeDirectAdjacent:
+ DCHECK(result.has_argument_leftmost_compound_matches);
+ result.has_argument_leftmost_compound_matches->push_back(context.element);
+ FALLTHROUGH;
case CSSSelector::kDirectAdjacent:
if (mode_ == kResolvingStyle) {
if (ContainerNode* parent =
@@ -355,7 +370,10 @@ SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
if (!next_context.element)
return kSelectorFailsAllSiblings;
return MatchSelector(next_context, result);
-
+ case CSSSelector::kRelativeIndirectAdjacent:
+ DCHECK(result.has_argument_leftmost_compound_matches);
+ result.has_argument_leftmost_compound_matches->push_back(context.element);
+ FALLTHROUGH;
case CSSSelector::kIndirectAdjacent:
if (mode_ == kResolvingStyle) {
if (ContainerNode* parent =
@@ -631,6 +649,170 @@ bool SelectorChecker::CheckPseudoNot(const SelectorCheckingContext& context,
return true;
}
+bool SelectorChecker::CheckPseudoHas(const SelectorCheckingContext& context,
+ MatchResult& result) const {
+ Document& document = context.element->GetDocument();
+ DCHECK(document.GetHasMatchedCacheScope());
+ Element* element = context.element;
+ SelectorCheckingContext sub_context(element);
+ // TODO(blee@igalia.com) Need to clarify the :scope dependency in relative
+ // selector definition.
+ // - spec : https://www.w3.org/TR/selectors-4/#relative
+ // - csswg issue : https://github.com/w3c/csswg-drafts/issues/6399
+ sub_context.scope = context.scope;
+ // sub_context.is_inside_visited_link is false (by default) to disable
+ // :visited matching when it is in the :has argument
+
+ DCHECK(context.selector->SelectorList());
+ for (const CSSSelector* selector = context.selector->SelectorList()->First();
+ selector; selector = CSSSelectorList::Next(*selector)) {
+ ElementHasMatchedMap& map =
+ HasMatchedCacheScope::GetCacheForSelector(&document, selector);
+
+ // Get the cache item of matching ':has(<selector>)' on the element
+ // to skip argument matching on the subtree elements
+ // - If the element was already marked as matched, return true.
+ // - If the element was already checked but not matched,
+ // move to the next argument selector.
+ // - Otherwise, mark the element as checked but not matched.
+ { // Limit the the AddResult scope to prevent SECURITY_DCHECK
+ auto cache_result = map.insert(element, false); // Mark as checked
+ if (!cache_result.is_new_entry) { // Was already marked as checked
+ if (cache_result.stored_value->value) // Was already marked as matched
+ return true;
+ continue;
+ }
+ }
+
+ sub_context.selector = selector;
+ HasArgumentMatchContext has_argument_match_context(selector);
+
+ bool depth_fixed = has_argument_match_context.GetDepthFixed();
+
+ // To prevent incorrect 'NotChecked' status while matching ':has' pseudo
+ // class, change the argument matching context scope when the ':has'
+ // argument matching traversal cannot be fixed with a certain depth and
+ // adjacent distance.
+ //
+ // For example, When we tries to match '.a:has(.b .c) .d' on below DOM,
+ // <div id=d1 class="a">
+ // <div id=d2 class="b">
+ // <div id=d3 class="a">
+ // <div id=d4 class="c">
+ // <div id=d5 class="d"></div>
+ // </div>
+ // </div>
+ // </div>
+ // </div>
+ // the ':has(.b .c)' selector will be checked on the #d3 element first
+ // because the selector '.a:has(.b .c) .d' will be matched upward from
+ // the #d5 element.
+ // 1) '.d' will be matched first on #d5
+ // 2) move to the #d3 until the '.a' matched
+ // 3) match the ':has(.b .c)' on the #d3
+ // 3.1) match the argument selector '.b .c' on the descendants of #d3
+ // 4) move to the #d1 until the '.a' matched
+ // 5) match the ':has(.b .c)' on the #d1
+ // 5.1) match the argument selector '.b .c' on the descendants of #d1
+ //
+ // The argument selector '.b .c' will not be matched on the #d4 at this
+ // step if the argument matching scope is limited to #d3. But the '.b .c'
+ // can be matched on the #d4 if the argument matching scope is #d1.
+ // To prevent duplicated argument matching operation, the #d1 should be
+ // marked as 'Matched' at the step 3.
+ //
+ // TODO(blee@igalia.com) Need to clarify the :scope dependency in relative
+ // selector definition.
+ // - spec : https://www.w3.org/TR/selectors-4/#relative
+ // - csswg issue : https://github.com/w3c/csswg-drafts/issues/6399
+ if (!depth_fixed) {
+ sub_context.relative_leftmost_element =
+ &element->GetTreeScope().RootNode();
+ } else if (has_argument_match_context.GetAdjacentDistanceFixed()) {
+ if (ContainerNode* parent_node = element->parentNode()) {
+ sub_context.relative_leftmost_element =
+ Traversal<Element>::FirstChild(*parent_node);
+ } else {
+ sub_context.relative_leftmost_element = element;
+ }
+ } else {
+ sub_context.relative_leftmost_element = element;
+ }
+
+ bool selector_matched = false;
+ for (HasArgumentSubtreeIterator iterator(*element,
+ has_argument_match_context);
+ !iterator.IsEnd(); ++iterator) {
+ if (depth_fixed && !iterator.IsAtFixedDepth())
+ continue;
+ sub_context.element = iterator.Get();
+ HeapVector<Member<Element>> has_argument_leftmost_compound_matches;
+ MatchResult sub_result;
+ sub_result.has_argument_leftmost_compound_matches =
+ &has_argument_leftmost_compound_matches;
+
+ MatchSelector(sub_context, sub_result);
+
+ switch (has_argument_match_context.GetLeftMostRelation()) {
+ case CSSSelector::kRelativeDescendant:
+ map.insert(iterator.Get(), false); // Mark as checked
+ if (!has_argument_leftmost_compound_matches.IsEmpty()) {
+ sub_context.element =
+ has_argument_leftmost_compound_matches.front();
+ for (sub_context.element = ParentElement(sub_context);
+ sub_context.element;
+ sub_context.element = ParentElement(sub_context)) {
+ map.Set(sub_context.element, true); // Mark as matched
+ if (sub_context.element == element)
+ selector_matched = true;
+ }
+ }
+ break;
+ case CSSSelector::kRelativeChild:
+ for (auto leftmost : has_argument_leftmost_compound_matches) {
+ Element* parent = leftmost->parentElement();
+ map.Set(parent, true); // Mark as matched
+ if (parent == element)
+ selector_matched = true;
+ }
+ break;
+ case CSSSelector::kRelativeDirectAdjacent:
+ if (!depth_fixed && !iterator.IsAtSiblingOfHasScope())
+ map.insert(iterator.Get(), false); // Mark as checked
+ for (auto leftmost : has_argument_leftmost_compound_matches) {
+ if (Element* sibling =
+ Traversal<Element>::PreviousSibling(*leftmost)) {
+ map.Set(sibling, true); // Mark as matched
+ if (sibling == element)
+ selector_matched = true;
+ }
+ }
+ break;
+ case CSSSelector::kRelativeIndirectAdjacent:
+ if (!depth_fixed)
+ map.insert(iterator.Get(), false); // Mark as checked
+ for (auto leftmost : has_argument_leftmost_compound_matches) {
+ for (Element* sibling =
+ Traversal<Element>::PreviousSibling(*leftmost);
+ sibling;
+ sibling = Traversal<Element>::PreviousSibling(*sibling)) {
+ map.Set(sibling, true); // Mark as matched
+ if (sibling == element)
+ selector_matched = true;
+ }
+ }
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ if (selector_matched)
+ return true;
+ }
+ }
+ return false;
+}
+
bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
MatchResult& result) const {
Element& element = *context.element;
@@ -1064,6 +1246,11 @@ bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
if (const auto* dialog_element = DynamicTo<HTMLDialogElement>(element))
return dialog_element->IsModal();
return false;
+ case CSSSelector::kPseudoHas:
+ return CheckPseudoHas(context, result);
+ case CSSSelector::kPseudoRelativeLeftmost:
+ DCHECK(context.relative_leftmost_element);
+ return context.relative_leftmost_element == &element;
case CSSSelector::kPseudoUnknown:
default:
NOTREACHED();
@@ -1132,9 +1319,13 @@ bool SelectorChecker::CheckPseudoElement(const SelectorCheckingContext& context,
return true;
}
case CSSSelector::kPseudoHighlight: {
- const AtomicString& highlight_name = selector.Argument();
result.dynamic_pseudo = PseudoId::kPseudoIdHighlight;
- return highlight_name == pseudo_argument_;
+ // A null pseudo_argument_ means we are matching rules on the originating
+ // element. We keep track of which pseudo elements may match for the
+ // element through result.dynamic_pseudo. For ::highlight() pseudo
+ // elements we have a single flag for tracking whether an element may
+ // match _any_ ::highlight() element (kPseudoIdHighlight).
+ return !pseudo_argument_ || pseudo_argument_ == selector.Argument();
}
case CSSSelector::kPseudoTargetText:
if (!is_ua_rule_) {
diff --git a/chromium/third_party/blink/renderer/core/css/selector_checker.h b/chromium/third_party/blink/renderer/core/css/selector_checker.h
index b0400065caa..5c8504034f5 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_checker.h
+++ b/chromium/third_party/blink/renderer/core/css/selector_checker.h
@@ -121,6 +121,7 @@ class CORE_EXPORT SelectorChecker {
Element* vtt_originating_element = nullptr;
bool in_nested_complex_selector = false;
bool is_inside_visited_link = false;
+ const ContainerNode* relative_leftmost_element = nullptr;
};
struct MatchResult {
@@ -128,6 +129,60 @@ class CORE_EXPORT SelectorChecker {
public:
PseudoId dynamic_pseudo{kPseudoIdNone};
+
+ // From the shortest argument selector match, we need to get the element
+ // that matches the leftmost compound selector to mark the correct scope
+ // elements of :has() pseudo class having the argument selectors starts
+ // with descendant combinator.
+ //
+ // <main id=main>
+ // <div id=d1>
+ // <div id=d2 class="a">
+ // <div id=d3 class="a">
+ // <div id=d4>
+ // <div id=d5 class="b">
+ // </div>
+ // </div>
+ // </div>
+ // </div>
+ // </div>
+ // </div>
+ // <script>
+ // main.querySelectorAll('div:has(.a .b)'); // Should return #d1, #d2
+ // </script>
+ //
+ // In case of the above example, div#d5 element matches the argument
+ // selector '.a .b'. Among the ancestors of the div#d5, the div#d3 and
+ // div#d4 is not the correct candidate scope element of ':has(.a .b)'
+ // because those elements don't have .a element as it's descendant.
+ // So instead of marking ancestors of div#d5, we should mark ancestors
+ // of div#d3 to prevent incorrect marking.
+ // In case of the shortest match for the argument selector '.a .b' on
+ // div#d5 element, the div#d3 is the element that matches the leftmost
+ // compound selector '.a'. So the MatchResult will return the div#d3
+ // element for the matching operation.
+ //
+ // In case of matching none desendant relative argument selectors, we
+ // can get the candidate leftmost compound matches while matching the
+ // argument selector.
+ // To process the 'main.querySelectorAll("div:has(:scope > .a .b)")'
+ // on the above DOM tree, selector checker will try to match the
+ // argument selector ':scope > .a .b' on the descendants of #d1 div
+ // element with the :scope element as #d1. When it matches the argument
+ // selector on #d5 element, the matching result is true and it can get
+ // the element that matches the leftmost(except :scope) compound '.a'
+ // as #d2 element. But while matching the argument selector on the #d5
+ // element, selector checker can also aware that the #d3 element can
+ // be a leftmost compound matching element when the scope element is
+ // #d2 element. So the selector checker will return the #d2 and #d3
+ // element so that the #d1 and #d2 can be marked as matched with the
+ // ':has(:scope > .a .b)'
+ //
+ // Instead of having vector for the :has argument matching, MatchResult
+ // has a pointer field to hold a element vector instance to minimize the
+ // MatchResult instance allocation overhead for none-has matching operations
+ HeapVector<Member<Element>>* has_argument_leftmost_compound_matches{
+ nullptr};
};
bool Match(const SelectorCheckingContext& context, MatchResult& result) const;
@@ -188,6 +243,7 @@ class CORE_EXPORT SelectorChecker {
MatchResult&) const;
bool CheckPseudoHost(const SelectorCheckingContext&, MatchResult&) const;
bool CheckPseudoNot(const SelectorCheckingContext&, MatchResult&) const;
+ bool CheckPseudoHas(const SelectorCheckingContext&, MatchResult&) const;
ComputedStyle* element_style_;
CustomScrollbar* scrollbar_;
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 0c67f267db3..67eb6277d18 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_filter.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_filter.cc
@@ -208,6 +208,12 @@ void SelectorFilter::CollectIdentifierHashes(
skip_over_subselectors = false;
CollectDescendantSelectorIdentifierHashes(*current, hash);
break;
+ case CSSSelector::kRelativeDescendant:
+ case CSSSelector::kRelativeChild:
+ case CSSSelector::kRelativeDirectAdjacent:
+ case CSSSelector::kRelativeIndirectAdjacent:
+ NOTREACHED();
+ break;
}
if (hash == end)
return;
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 52d3dd9cfed..eb86a2be8dc 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_query.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_query.cc
@@ -30,6 +30,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.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"
@@ -106,11 +107,13 @@ inline bool SelectorMatches(const CSSSelector& selector,
bool SelectorQuery::Matches(Element& target_element) const {
QUERY_STATS_RESET();
+ HasMatchedCacheScope has_matched_cache_scope(&target_element.GetDocument());
return SelectorListMatches(target_element, target_element);
}
Element* SelectorQuery::Closest(Element& target_element) const {
QUERY_STATS_RESET();
+ HasMatchedCacheScope has_matched_cache_scope(&target_element.GetDocument());
if (selectors_.IsEmpty())
return nullptr;
@@ -124,6 +127,7 @@ Element* SelectorQuery::Closest(Element& target_element) const {
StaticElementList* SelectorQuery::QueryAll(ContainerNode& root_node) const {
QUERY_STATS_RESET();
+ HasMatchedCacheScope has_matched_cache_scope(&root_node.GetDocument());
NthIndexCache nth_index_cache(root_node.GetDocument());
HeapVector<Member<Element>> result;
Execute<AllElementsSelectorQueryTrait>(root_node, result);
@@ -132,6 +136,7 @@ StaticElementList* SelectorQuery::QueryAll(ContainerNode& root_node) const {
Element* SelectorQuery::QueryFirst(ContainerNode& root_node) const {
QUERY_STATS_RESET();
+ HasMatchedCacheScope has_matched_cache_scope(&root_node.GetDocument());
NthIndexCache nth_index_cache(root_node.GetDocument());
Element* matched_element = nullptr;
Execute<SingleElementSelectorQueryTrait>(root_node, matched_element);
diff --git a/chromium/third_party/blink/renderer/core/css/selector_query_test.cc b/chromium/third_party/blink/renderer/core/css/selector_query_test.cc
index 54234b94200..5fd9c986aaf 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_query_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_query_test.cc
@@ -240,7 +240,8 @@ TEST(SelectorQueryTest, FastPathScoped) {
ShadowRoot& shadowRoot =
scope->AttachShadowRootInternal(ShadowRootType::kOpen);
// Make the inside the shadow root be identical to that of the outer document.
- shadowRoot.appendChild(&document->documentElement()->CloneWithChildren());
+ shadowRoot.appendChild(&document->documentElement()->CloneWithChildren(
+ CloneChildrenFlag::kClone));
static const struct QueryTest kTestCases[] = {
// Id in the right most selector.
{"#first", false, 0, {0, 0, 0, 0, 0, 0, 0}},
diff --git a/chromium/third_party/blink/renderer/core/css/style_auto_color.h b/chromium/third_party/blink/renderer/core/css/style_auto_color.h
index ff143c21adf..0435f516abd 100644
--- a/chromium/third_party/blink/renderer/core/css/style_auto_color.h
+++ b/chromium/third_party/blink/renderer/core/css/style_auto_color.h
@@ -16,6 +16,8 @@ class StyleAutoColor : public StyleColor {
public:
explicit StyleAutoColor(Color color) : StyleColor(color) {}
explicit StyleAutoColor(CSSValueID keyword) : StyleColor(keyword) {}
+ StyleAutoColor(Color color, CSSValueID keyword)
+ : StyleColor(color, keyword) {}
static StyleAutoColor AutoColor() {
return StyleAutoColor(CSSValueID::kAuto);
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_color.h b/chromium/third_party/blink/renderer/core/css/style_color.h
index 4cab8f2cade..aca9de13346 100644
--- a/chromium/third_party/blink/renderer/core/css/style_color.h
+++ b/chromium/third_party/blink/renderer/core/css/style_color.h
@@ -63,7 +63,11 @@ class CORE_EXPORT StyleColor {
}
bool IsSystemColor() const { return IsSystemColor(color_keyword_); }
Color GetColor() const {
- DCHECK(IsNumeric());
+ // TODO(1081945): System colors will fail the IsNumeric check, as they store
+ // a keyword, but they also have a stored color that may need to be accessed
+ // directly. For example in FilterEffectBuilder::BuildFilterEffect for
+ // shadow colors.
+ DCHECK(IsNumeric() || IsSystemColor());
return color_;
}
CSSValueID GetColorKeyword() const {
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 7c62ba0df9a..a04f5aa789b 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.cc
@@ -44,6 +44,7 @@
#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/has_matched_cache_scope.h"
#include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h"
#include "third_party/blink/renderer/core/css/media_feature_overrides.h"
#include "third_party/blink/renderer/core/css/media_values.h"
@@ -77,6 +78,7 @@
#include "third_party/blink/renderer/core/html/html_link_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/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -516,7 +518,6 @@ void StyleEngine::UpdateActiveStyleSheets() {
void StyleEngine::UpdateCounterStyles() {
if (!counter_styles_need_update_)
return;
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
CounterStyleMap::MarkAllDirtyCounterStyles(GetDocument(),
active_tree_scopes_);
CounterStyleMap::ResolveAllReferences(GetDocument(), active_tree_scopes_);
@@ -541,6 +542,7 @@ void StyleEngine::UpdateActiveStyle() {
UpdateViewport();
UpdateActiveStyleSheets();
UpdateGlobalRuleSet();
+ UpdateTimelines();
}
const ActiveStyleSheetVector StyleEngine::ActiveStyleSheetsForInspector() {
@@ -1752,6 +1754,17 @@ void StyleEngine::EnvironmentVariableChanged() {
resolver_->InvalidateMatchedPropertiesCache();
}
+void StyleEngine::ScrollTimelinesChanged() {
+ MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
+ style_change_reason::kScrollTimeline));
+ // We currently rely on marking at least one element for recalc in order
+ // to clean the timelines_need_update_ flag. (Otherwise the timelines
+ // will just remain dirty). Hence, if we in the future remove the call
+ // to mark elements for recalc, we would need to call
+ // ScheduleLayoutTreeUpdateIfNeeded to ensure that we reach UpdateTimelines.
+ timelines_need_update_ = true;
+}
+
void StyleEngine::MarkForWhitespaceReattachment() {
DCHECK(GetDocument().InStyleRecalc());
for (auto element : whitespace_reattach_set_) {
@@ -1843,7 +1856,8 @@ void StyleEngine::ClearPropertyRules() {
}
void StyleEngine::ClearScrollTimelineRules() {
- scroll_timeline_map_.clear();
+ scroll_timeline_rule_map_.clear();
+ ScrollTimelinesChanged();
}
void StyleEngine::AddPropertyRulesFromSheets(
@@ -1914,9 +1928,8 @@ void StyleEngine::AddScrollTimelineRules(const RuleSet& rule_set) {
if (scroll_timeline_rules.IsEmpty())
return;
for (const auto& rule : scroll_timeline_rules)
- scroll_timeline_map_.Set(AtomicString(rule->GetName()), rule);
- MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
- style_change_reason::kScrollTimeline));
+ scroll_timeline_rule_map_.Set(rule->GetName(), rule);
+ ScrollTimelinesChanged();
}
StyleRuleKeyframes* StyleEngine::KeyframeStylesForAnimation(
@@ -1931,9 +1944,48 @@ StyleRuleKeyframes* StyleEngine::KeyframeStylesForAnimation(
return it->value.Get();
}
-StyleRuleScrollTimeline* StyleEngine::FindScrollTimelineRule(
- const AtomicString& name) {
- return scroll_timeline_map_.at(name);
+void StyleEngine::UpdateTimelines() {
+ if (!timelines_need_update_)
+ return;
+ timelines_need_update_ = false;
+
+ HeapHashMap<AtomicString, Member<CSSScrollTimeline>> timelines;
+
+ for (const auto& it : scroll_timeline_rule_map_) {
+ const AtomicString& name = it.key;
+
+ CSSScrollTimeline::Options options(GetDocument(), *it.value);
+
+ // Check if we can re-use existing timeline.
+ CSSScrollTimeline* existing_timeline = FindScrollTimeline(name);
+ if (existing_timeline && existing_timeline->Matches(options)) {
+ timelines.Set(name, existing_timeline);
+ continue;
+ }
+
+ // Create a new timeline.
+ auto* timeline = MakeGarbageCollected<CSSScrollTimeline>(
+ &GetDocument(), std::move(options));
+ // It is not allowed for a style update to create timelines that
+ // needs timing updates (i.e.
+ // AnimationTimeline::NeedsAnimationTimingUpdate() must return false).
+ // Servicing animations after creation preserves this invariant by ensuring
+ // the last-update time of the timeline is equal to the current time.
+ timeline->ServiceAnimations(kTimingUpdateOnDemand);
+ timelines.Set(name, timeline);
+ }
+
+ std::swap(scroll_timeline_map_, timelines);
+}
+
+CSSScrollTimeline* StyleEngine::FindScrollTimeline(const AtomicString& name) {
+ DCHECK(!timelines_need_update_);
+ return scroll_timeline_map_.DeprecatedAtOrEmptyValue(name);
+}
+
+void StyleEngine::ScrollTimelineInvalidated(CSSScrollTimeline& timeline) {
+ timelines_need_update_ = true;
+ timeline.InvalidateEffectTargetStyle();
}
DocumentStyleEnvironmentVariables& StyleEngine::EnsureEnvironmentVariables() {
@@ -1965,23 +2017,46 @@ void StyleEngine::UpdateStyleAndLayoutTreeForContainer(
base::AutoReset<bool> cq_recalc(&in_container_query_style_recalc_, true);
DCHECK(container.GetLayoutObject()) << "Containers must have a LayoutObject";
- WritingMode writing_mode =
- container.GetLayoutObject()->StyleRef().GetWritingMode();
- PhysicalSize physical_size = ToPhysicalSize(logical_size, writing_mode);
+ const ComputedStyle& style = container.GetLayoutObject()->StyleRef();
+ DCHECK(style.IsContainerForContainerQueries());
+ WritingMode writing_mode = style.GetWritingMode();
+ PhysicalSize physical_size = AdjustForAbsoluteZoom::AdjustPhysicalSize(
+ ToPhysicalSize(logical_size, writing_mode), style);
PhysicalAxes physical_axes = ToPhysicalAxes(contained_axes, writing_mode);
- if (auto* evaluator = container.GetContainerQueryEvaluator()) {
- if (!evaluator->ContainerChanged(physical_size, physical_axes))
+ StyleRecalcChange change;
+
+ auto* evaluator = container.GetContainerQueryEvaluator();
+ DCHECK(evaluator);
+
+ switch (evaluator->ContainerChanged(physical_size, physical_axes)) {
+ case ContainerQueryEvaluator::Change::kNone:
return;
- } else {
- container.SetContainerQueryEvaluator(
- MakeGarbageCollected<ContainerQueryEvaluator>(physical_size,
- physical_axes));
+ case ContainerQueryEvaluator::Change::kNearestContainer:
+ change = change.ForceRecalcContainer();
+ break;
+ case ContainerQueryEvaluator::Change::kDescendantContainers:
+ change = change.ForceRecalcDescendantContainers();
+ break;
}
+ // The container node must not need recalc at this point.
+ DCHECK(!StyleRecalcChange().ShouldRecalcStyleFor(container));
+
+ // If the container itself depends on an outer container, then its
+ // DependsOnContainerQueries flag will be set, and we would recalc its
+ // style (due to ForceRecalcContainer/ForceRecalcDescendantContainers).
+ // This is not necessary, hence we suppress recalc for this element.
+ change = change.SuppressRecalc();
+
+ NthIndexCache nth_index_cache(GetDocument());
style_recalc_root_.Update(nullptr, &container);
- RecalcStyle({StyleRecalcChange::kRecalcContainerQueryDependent},
- StyleRecalcContext());
+
+ // No need to initialize container for the StyleRecalcContext with
+ // FromAncestors because style will not be recalculated for "container, and
+ // Element::RecalcStyle for the "container" will initialize StyleRecalcContext
+ // with itself for its children.
+ RecalcStyle(change, StyleRecalcContext());
// Nodes are marked for whitespace reattachment for DOM removal only. This set
// should have been cleared before layout.
@@ -2016,6 +2091,7 @@ void StyleEngine::UpdateStyleAndLayoutTreeForContainer(
void StyleEngine::RecalcStyle(StyleRecalcChange change,
const StyleRecalcContext& style_recalc_context) {
DCHECK(GetDocument().documentElement());
+ HasMatchedCacheScope has_matched_cache_scope(&GetDocument());
Element& root_element = style_recalc_root_.RootElement();
Element* parent = FlatTreeTraversal::ParentElement(root_element);
@@ -2084,6 +2160,9 @@ void StyleEngine::RebuildLayoutTree() {
ancestor->ClearChildNeedsReattachLayoutTree();
}
layout_tree_rebuild_root_.Clear();
+
+ if (IsA<HTMLHtmlElement>(root_element) || IsA<HTMLBodyElement>(root_element))
+ PropagateWritingModeAndDirectionToHTMLRoot();
}
void StyleEngine::UpdateStyleAndLayoutTree() {
@@ -2329,12 +2408,17 @@ void StyleEngine::UpdateColorSchemeBackground(bool color_scheme_changed) {
else if (SupportsDarkColorScheme())
root_color_scheme = mojom::blink::ColorScheme::kDark;
}
+ auto* settings = GetDocument().GetSettings();
+ bool force_dark_enabled = settings && settings->GetForceDarkModeEnabled();
color_scheme_background_ =
- root_color_scheme == mojom::blink::ColorScheme::kLight
+ root_color_scheme == mojom::blink::ColorScheme::kLight &&
+ !force_dark_enabled
? Color::kWhite
: Color(0x12, 0x12, 0x12);
if (GetDocument().IsInMainFrame()) {
- if (root_color_scheme == mojom::blink::ColorScheme::kDark) {
+ if (root_color_scheme == mojom::blink::ColorScheme::kDark ||
+ (root_color_scheme == mojom::blink::ColorScheme::kLight &&
+ force_dark_enabled)) {
use_color_adjust_background =
LocalFrameView::UseColorAdjustBackground::kIfBaseNotTransparent;
}
@@ -2466,6 +2550,7 @@ void StyleEngine::Trace(Visitor* visitor) const {
visitor->Trace(custom_element_default_style_sheets_);
visitor->Trace(keyframes_rule_map_);
visitor->Trace(user_counter_style_map_);
+ visitor->Trace(scroll_timeline_rule_map_);
visitor->Trace(scroll_timeline_map_);
visitor->Trace(inspector_style_sheet_);
visitor->Trace(document_style_sheet_collection_);
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 9935144d33a..3799f40d477 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.h
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.h
@@ -36,6 +36,7 @@
#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-shared.h"
#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/renderer/core/animation/css/css_scroll_timeline.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/core/css/css_global_rule_set.h"
@@ -235,6 +236,14 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
bool UsesWindowInactiveSelector() const {
return GetRuleFeatureSet().UsesWindowInactiveSelector();
}
+ bool UsesContainerQueries() const {
+ return GetRuleFeatureSet().UsesContainerQueries() ||
+ uses_container_relative_units_;
+ }
+
+ void SetUsesContainerRelativeUnits() {
+ uses_container_relative_units_ = true;
+ }
bool UsesRemUnits() const { return uses_rem_units_; }
void SetUsesRemUnit(bool uses_rem_units) { uses_rem_units_ = uses_rem_units; }
@@ -373,6 +382,13 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
void EnvironmentVariableChanged();
+ // Called when the set of @scroll-timeline rules changes. E.g. if a new
+ // @scroll-timeline rule was inserted.
+ //
+ // Not to be confused with ScrollTimelineInvalidated, which is called when
+ // elements *referenced* by @scroll-timeline rules change.
+ void ScrollTimelinesChanged();
+
bool NeedsWhitespaceReattachment() const {
return !whitespace_reattach_set_.IsEmpty();
}
@@ -396,7 +412,18 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
StyleRuleKeyframes* KeyframeStylesForAnimation(
const AtomicString& animation_name);
- StyleRuleScrollTimeline* FindScrollTimelineRule(const AtomicString& name);
+
+ void UpdateTimelines();
+
+ CSSScrollTimeline* FindScrollTimeline(const AtomicString& name);
+
+ // Called when information a @scroll-timeline depends on changes, e.g.
+ // when we have source:selector(#foo), and the element referenced by
+ // #foo changes.
+ //
+ // Not to be confused with ScrollTimelinesChanged, which is called when
+ // @scroll-timeline rules themselves change.
+ void ScrollTimelineInvalidated(CSSScrollTimeline&);
CounterStyleMap* GetUserCounterStyleMap() { return user_counter_style_map_; }
const CounterStyle& FindCounterStyleAcrossScopes(const AtomicString&,
@@ -606,12 +633,14 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
String preferred_stylesheet_set_name_;
bool uses_rem_units_{false};
+ bool uses_container_relative_units_{false};
bool in_layout_tree_rebuild_{false};
bool in_container_query_style_recalc_{false};
bool in_dom_removal_{false};
bool viewport_style_dirty_{false};
bool fonts_need_update_{false};
bool counter_styles_need_update_{false};
+ bool timelines_need_update_{false};
// Set to true if we allow marking style dirty from style recalc. Ideally, we
// should get rid of this, but we keep track of where we allow it with
@@ -667,7 +696,8 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
Member<CounterStyleMap> user_counter_style_map_;
HeapHashMap<AtomicString, Member<StyleRuleScrollTimeline>>
- scroll_timeline_map_;
+ scroll_timeline_rule_map_;
+ HeapHashMap<AtomicString, Member<CSSScrollTimeline>> scroll_timeline_map_;
scoped_refptr<DocumentStyleEnvironmentVariables> environment_variables_;
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 016afeb5a7d..cc73e3f9188 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
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/layout/list_marker.h"
#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/core/testing/color_scheme_helper.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/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -116,10 +117,28 @@ class StyleEngineTest : public testing::Test {
return ListMarker::Get(marker)->TextAlternative(*marker);
}
+ StyleRuleScrollTimeline* FindScrollTimelineRule(AtomicString name) {
+ CSSScrollTimeline* timeline = GetStyleEngine().FindScrollTimeline(name);
+ if (!timeline)
+ return nullptr;
+ return timeline->GetRule();
+ }
+
private:
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
};
+// It's currently not possible to use ScopedCSSContainerQueriesForTest in
+// individual tests. CSSContainerQueries implies LayoutNGGrid, and
+// LayoutNGGrid needs to be enabled early (before StyleResolver::InitialStyle
+// is created, probably). Otherwise assumptions made by e.g.
+// GridTrackList::AssignFrom do not hold.
+class StyleEngineContainerQueryTest : public StyleEngineTest,
+ private ScopedCSSContainerQueriesForTest {
+ public:
+ StyleEngineContainerQueryTest() : ScopedCSSContainerQueriesForTest(true) {}
+};
+
void StyleEngineTest::SetUp() {
dummy_page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600));
}
@@ -1569,7 +1588,6 @@ TEST_F(StyleEngineTest, MediaQueriesChangePrefersContrast) {
ColorSchemeHelper color_scheme_helper(GetDocument());
color_scheme_helper.SetPreferredContrast(
mojom::blink::PreferredContrast::kNoPreference);
- color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kNone);
GetDocument().body()->setInnerHTML(R"HTML(
<style>
@@ -1603,7 +1621,8 @@ TEST_F(StyleEngineTest, MediaQueriesChangePrefersContrast) {
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
- color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive);
+ color_scheme_helper.SetPreferredContrast(
+ mojom::blink::PreferredContrast::kCustom);
UpdateAllLifecyclePhases();
EXPECT_EQ(MakeRGB(0, 0, 255),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
@@ -1617,7 +1636,6 @@ TEST_F(StyleEngineTest, MediaQueriesChangeSpecificPrefersContrast) {
ColorSchemeHelper color_scheme_helper(GetDocument());
color_scheme_helper.SetPreferredContrast(
mojom::blink::PreferredContrast::kNoPreference);
- color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kNone);
GetDocument().body()->setInnerHTML(R"HTML(
<style>
@@ -1628,15 +1646,9 @@ TEST_F(StyleEngineTest, MediaQueriesChangeSpecificPrefersContrast) {
@media (prefers-contrast: less) {
body { color: orange }
}
- @media (prefers-contrast: forced) {
+ @media (prefers-contrast: custom) {
body { color: yellow }
}
- @media (prefers-contrast: forced) and (prefers-contrast: more) {
- body { color: green }
- }
- @media (prefers-contrast: forced) and (prefers-contrast: less) {
- body { color: purple }
- }
</style>
<body></body>
)HTML");
@@ -1660,25 +1672,79 @@ TEST_F(StyleEngineTest, MediaQueriesChangeSpecificPrefersContrast) {
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
- color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive);
+ color_scheme_helper.SetPreferredContrast(
+ mojom::blink::PreferredContrast::kCustom);
UpdateAllLifecyclePhases();
- EXPECT_EQ(MakeRGB(128, 0, 128),
+ EXPECT_EQ(MakeRGB(255, 255, 0),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
+}
+TEST_F(StyleEngineTest, MediaQueriesChangePrefersContrastOverride) {
+ ScopedForcedColorsForTest forced_scoped_feature(true);
+ ScopedPrefersContrastForTest contrast_scoped_feature(true);
+
+ ColorSchemeHelper color_scheme_helper(GetDocument());
color_scheme_helper.SetPreferredContrast(
- mojom::blink::PreferredContrast::kMore);
+ mojom::blink::PreferredContrast::kNoPreference);
+
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ body { color: red; forced-color-adjust: none; }
+ @media (prefers-contrast: more) {
+ body { color: blue }
+ }
+ @media (prefers-contrast: less) {
+ body { color: orange }
+ }
+ @media (prefers-contrast: custom) {
+ body { color: yellow }
+ }
+ </style>
+ <body></body>
+ )HTML");
+
UpdateAllLifecyclePhases();
- EXPECT_EQ(MakeRGB(0, 128, 0),
+ EXPECT_EQ(MakeRGB(255, 0, 0),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
- color_scheme_helper.SetPreferredContrast(
- mojom::blink::PreferredContrast::kNoPreference);
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-contrast", "more");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(0, 0, 255),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-contrast",
+ "no-preference");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-contrast", "less");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 165, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-contrast",
+ "custom");
+
UpdateAllLifecyclePhases();
EXPECT_EQ(MakeRGB(255, 255, 0),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->ClearMediaFeatureOverrides();
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
}
TEST_F(StyleEngineTest, MediaQueriesChangePrefersReducedMotion) {
@@ -1833,6 +1899,48 @@ TEST_F(StyleEngineTest, MediaQueriesChangeForcedColorsAndPreferredColorScheme) {
GetCSSPropertyColor()));
}
+TEST_F(StyleEngineTest, MediaQueriesForcedColorsOverride) {
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ body {
+ forced-color-adjust: none;
+ }
+ @media (forced-colors: none) {
+ body { color: red }
+ }
+ @media (forced-colors: active) {
+ body { color: green }
+ }
+ </style>
+ <body></body>
+ )HTML");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ ColorSchemeHelper color_scheme_helper(GetDocument());
+ GetDocument().GetPage()->SetMediaFeatureOverride("forced-colors", "active");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(0, 128, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("forced-colors", "none");
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->ClearMediaFeatureOverrides();
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+}
+
TEST_F(StyleEngineTest, MediaQueriesColorSchemeOverride) {
ColorSchemeHelper color_scheme_helper(GetDocument());
color_scheme_helper.SetPreferredColorScheme(
@@ -2079,8 +2187,7 @@ TEST_F(StyleEngineTest, RejectSelectorForPseudoElement) {
UpdateAllLifecyclePhases();
StyleEngine& engine = GetStyleEngine();
- // If the Stats() were already enabled, we would not start with 0 counts.
- EXPECT_FALSE(engine.Stats());
+ // Even if the Stats() were already enabled, the following resets it to 0.
engine.SetStatsEnabled(true);
StyleResolverStats* stats = engine.Stats();
@@ -2426,8 +2533,6 @@ TEST_F(StyleEngineTest, ColorSchemeBaseBackgroundChange) {
}
TEST_F(StyleEngineTest, ColorSchemeOverride) {
- ScopedCSSColorSchemeUARenderingForTest enable_color_scheme_ua(true);
-
ColorSchemeHelper color_scheme_helper(GetDocument());
color_scheme_helper.SetPreferredColorScheme(
mojom::blink::PreferredColorScheme::kLight);
@@ -2475,18 +2580,21 @@ TEST_F(StyleEngineTest, PseudoElementBaseComputedStyle) {
before->SetNeedsAnimationStyleRecalc();
UpdateAllLifecyclePhases();
- scoped_refptr<ComputedStyle> base_computed_style =
- animations->base_computed_style_;
+ ASSERT_TRUE(before->GetComputedStyle());
+ const ComputedStyle* base_computed_style =
+ before->GetComputedStyle()->GetBaseComputedStyle();
EXPECT_TRUE(base_computed_style);
before->SetNeedsAnimationStyleRecalc();
UpdateAllLifecyclePhases();
- EXPECT_TRUE(animations->base_computed_style_);
+ ASSERT_TRUE(before->GetComputedStyle());
+ EXPECT_TRUE(before->GetComputedStyle()->GetBaseComputedStyle());
#if !DCHECK_IS_ON()
// When DCHECK is enabled, BaseComputedStyle() returns null and we repeatedly
// create new instances which means the pointers will be different here.
- EXPECT_EQ(base_computed_style, animations->base_computed_style_);
+ EXPECT_EQ(base_computed_style,
+ before->GetComputedStyle()->GetBaseComputedStyle());
#endif
}
@@ -2524,6 +2632,22 @@ TEST_F(StyleEngineTest, ForceReattachLayoutTreeStyleRecalcRoot) {
EXPECT_EQ(outer, GetStyleRecalcRoot());
}
+TEST_F(StyleEngineTest, ForceReattachNoStyleForElement) {
+ GetDocument().body()->setInnerHTML(R"HTML(<div id="reattach"></div>)HTML");
+
+ auto* reattach = GetDocument().getElementById("reattach");
+
+ UpdateAllLifecyclePhases();
+
+ unsigned initial_count = GetStyleEngine().StyleForElementCount();
+
+ reattach->SetForceReattachLayoutTree();
+ EXPECT_EQ(reattach, GetStyleRecalcRoot());
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(GetStyleEngine().StyleForElementCount(), initial_count);
+}
+
TEST_F(StyleEngineTest, RecalcPropagatedWritingMode) {
GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kWritingMode,
"vertical-lr");
@@ -3121,12 +3245,12 @@ TEST_F(StyleEngineTest, AtScrollTimelineInUserOrigin) {
// @scroll-timeline in the user origin:
InjectSheet("user1", WebDocument::kUserOrigin, R"CSS(
@scroll-timeline timeline1 {
+ time-range: 10s;
source: selector(#scroller1);
}
)CSS");
UpdateAllLifecyclePhases();
- StyleRuleScrollTimeline* rule1 =
- GetStyleEngine().FindScrollTimelineRule("timeline1");
+ StyleRuleScrollTimeline* rule1 = FindScrollTimelineRule("timeline1");
ASSERT_TRUE(rule1);
ASSERT_TRUE(rule1->GetSource());
EXPECT_EQ("selector(#scroller1)", rule1->GetSource()->CssText());
@@ -3134,12 +3258,12 @@ TEST_F(StyleEngineTest, AtScrollTimelineInUserOrigin) {
// @scroll-timeline in the author origin (should win over user origin)
InjectSheet("author", WebDocument::kAuthorOrigin, R"CSS(
@scroll-timeline timeline1 {
+ time-range: 10s;
source: selector(#scroller2);
}
)CSS");
UpdateAllLifecyclePhases();
- StyleRuleScrollTimeline* rule2 =
- GetStyleEngine().FindScrollTimelineRule("timeline1");
+ StyleRuleScrollTimeline* rule2 = FindScrollTimelineRule("timeline1");
ASSERT_TRUE(rule2);
ASSERT_TRUE(rule2->GetSource());
EXPECT_EQ("selector(#scroller2)", rule2->GetSource()->CssText());
@@ -3147,12 +3271,12 @@ TEST_F(StyleEngineTest, AtScrollTimelineInUserOrigin) {
// An additional @scroll-timeline in the user origin:
InjectSheet("user2", WebDocument::kUserOrigin, R"CSS(
@scroll-timeline timeline2 {
+ time-range: 10s;
source: selector(#scroller3);
}
)CSS");
UpdateAllLifecyclePhases();
- StyleRuleScrollTimeline* rule3 =
- GetStyleEngine().FindScrollTimelineRule("timeline2");
+ StyleRuleScrollTimeline* rule3 = FindScrollTimelineRule("timeline2");
ASSERT_TRUE(rule3);
ASSERT_TRUE(rule3->GetSource());
EXPECT_EQ("selector(#scroller3)", rule3->GetSource()->CssText());
@@ -3340,28 +3464,16 @@ TEST_F(StyleEngineSimTest, ColorSchemeBaseBackgroundWhileRenderBlocking) {
css_resource.Finish();
}
-namespace {
-
-void SetDependsOnContainerQueries(Element& element) {
- if (const ComputedStyle* style = element.GetComputedStyle()) {
- scoped_refptr<ComputedStyle> cloned_style = ComputedStyle::Clone(*style);
- cloned_style->SetDependsOnContainerQueries(true);
- element.SetComputedStyle(cloned_style);
- }
-}
-
-void SetDependsOnContainerQueries(HTMLCollection& affected) {
- for (Element* element : affected)
- SetDependsOnContainerQueries(*element);
-}
-
-} // namespace
-
-TEST_F(StyleEngineTest, UpdateStyleAndLayoutTreeForContainer) {
+TEST_F(StyleEngineContainerQueryTest, UpdateStyleAndLayoutTreeForContainer) {
GetDocument().body()->setInnerHTML(R"HTML(
<style>
.container {
contain: layout size style;
+ width: 100px;
+ height: 100px;
+ }
+ @container (min-width: 200px) {
+ .affected { background-color: green; }
}
</style>
<div id="container1" class="container">
@@ -3395,83 +3507,99 @@ TEST_F(StyleEngineTest, UpdateStyleAndLayoutTreeForContainer) {
auto* container1 = GetDocument().getElementById("container1");
auto* container2 = GetDocument().getElementById("container2");
- auto* affected = GetDocument().getElementsByClassName("affected");
ASSERT_TRUE(container1);
ASSERT_TRUE(container2);
- ASSERT_TRUE(affected);
- SetDependsOnContainerQueries(*affected);
unsigned start_count = GetStyleEngine().StyleForElementCount();
GetStyleEngine().UpdateStyleAndLayoutTreeForContainer(
- *container1, LogicalSize(), LogicalAxes(kLogicalAxisBoth));
+ *container1, LogicalSize(200, 100), LogicalAxes(kLogicalAxisBoth));
// The first span.affected child and #container2
EXPECT_EQ(2u, GetStyleEngine().StyleForElementCount() - start_count);
start_count = GetStyleEngine().StyleForElementCount();
GetStyleEngine().UpdateStyleAndLayoutTreeForContainer(
- *container2, LogicalSize(), LogicalAxes(kLogicalAxisBoth));
+ *container2, LogicalSize(200, 100), LogicalAxes(kLogicalAxisBoth));
// Three direct span.affected children, and the two display:none elements.
EXPECT_EQ(6u, GetStyleEngine().StyleForElementCount() - start_count);
}
-TEST_F(StyleEngineTest, ContainerQueriesContainmentNotApplying) {
+TEST_F(StyleEngineContainerQueryTest, ContainerQueriesContainmentNotApplying) {
GetDocument().body()->setInnerHTML(R"HTML(
<style>
.container {
contain: layout size style;
+ width: 100px;
+ height: 100px;
+ }
+ @container (min-width: 200px) {
+ .toggle { background-color: green; }
}
</style>
<div id="container" class="container">
+
+ <!-- None of the following should be affected by a change in the
+ size of #container. -->
<div class="container" style="display:contents">
- <span class="affected"></span>
+ <span class="toggle"></span>
</div>
<span class="container">
- <span class="affected"></span>
+ <span class="toggle"></span>
</span>
<rt class="container">
- <span class="affected"></span>
+ <span class="toggle"></span>
</rt>
<div class="container" style="display:table">
- <span class="affected"></span>
+ <span class="toggle"></span>
</div>
<div class="container" style="display:table-cell">
- <span class="affected"></span>
+ <span class="toggle"></span>
</div>
<div class="container" style="display:table-row">
- <span class="affected"></span>
+ <span class="toggle"></span>
</div>
<div class="container" style="display:table-row-group">
- <span class="affected"></span>
+ <span class="toggle"></span>
</div>
+
+ <!-- This should be affected, however. -->
+ <div class="toggle">Affected</div>
</div>
)HTML");
UpdateAllLifecyclePhases();
auto* container = GetDocument().getElementById("container");
- auto* affected = GetDocument().getElementsByClassName("affected");
ASSERT_TRUE(container);
- ASSERT_TRUE(affected);
- SetDependsOnContainerQueries(*affected);
unsigned start_count = GetStyleEngine().StyleForElementCount();
+
GetStyleEngine().UpdateStyleAndLayoutTreeForContainer(
- *container, LogicalSize(), LogicalAxes(kLogicalAxisBoth));
+ *container, LogicalSize(200, 100), LogicalAxes(kLogicalAxisBoth));
- // span.affected is updated because containment does not apply to the display
- // types on the element styled with containment. All marked as affected are
- // recalculated.
- EXPECT_EQ(7u, GetStyleEngine().StyleForElementCount() - start_count);
+ // Even though none of the inner containers are eligible for containment,
+ // they are still containers for the purposes of evaluating container
+ // queries. Hence, they should not be affected when the outer container
+ // changes its size.
+ EXPECT_EQ(1u, GetStyleEngine().StyleForElementCount() - start_count);
}
-TEST_F(StyleEngineTest, PseudoElementContainerQueryRecalc) {
+TEST_F(StyleEngineContainerQueryTest, PseudoElementContainerQueryRecalc) {
GetDocument().body()->setInnerHTML(R"HTML(
<style>
- #container { contain: layout size style }
+ #container {
+ contain: layout size style;
+ width: 100px;
+ height: 100px;
+ }
+ /* TODO(crbug.com/1217976): For now we need to create the pseudo-
+ element #container outside of the container query. */
#container::before { content: " " }
- span::before { content: " " }
+ @container (min-width: 200px) {
+ #container::before { content: " " }
+ span::before { content: " " }
+ }
</style>
<div id="container">
<span id="span"></span>
@@ -3485,25 +3613,29 @@ TEST_F(StyleEngineTest, PseudoElementContainerQueryRecalc) {
ASSERT_TRUE(container);
ASSERT_TRUE(span);
- auto* before = span->GetPseudoElement(kPseudoIdBefore);
- ASSERT_TRUE(before);
- SetDependsOnContainerQueries(*before);
-
- before = container->GetPseudoElement(kPseudoIdBefore);
- ASSERT_TRUE(before);
- SetDependsOnContainerQueries(*before);
-
unsigned start_count = GetStyleEngine().StyleForElementCount();
GetStyleEngine().UpdateStyleAndLayoutTreeForContainer(
- *container, LogicalSize(), LogicalAxes(kLogicalAxisBoth));
+ *container, LogicalSize(200, 100), LogicalAxes(kLogicalAxisBoth));
- EXPECT_EQ(2u, GetStyleEngine().StyleForElementCount() - start_count);
+ // Two ::before elements, plus #span. (Originating elements are also
+ // marked as SetDependsOnContainerQueries).
+ EXPECT_EQ(3u, GetStyleEngine().StyleForElementCount() - start_count);
}
-TEST_F(StyleEngineTest, MarkStyleDirtyFromContainerRecalc) {
+TEST_F(StyleEngineContainerQueryTest, MarkStyleDirtyFromContainerRecalc) {
GetDocument().body()->setInnerHTML(R"HTML(
- <div id="container" style="contain: layout size style">
- <input id="input" type="text" class="affected">
+ <style>
+ #container {
+ contain: layout size style;
+ width: 100px;
+ height: 100px;
+ }
+ @container (min-width: 200px) {
+ #input { background-color: green; }
+ }
+ </style>
+ <div id="container">
+ <input id="input" type="text">
</div>
)HTML");
@@ -3511,13 +3643,10 @@ TEST_F(StyleEngineTest, MarkStyleDirtyFromContainerRecalc) {
auto* container = GetDocument().getElementById("container");
auto* input = GetDocument().getElementById("input");
- auto* affected = GetDocument().getElementsByClassName("affected");
ASSERT_TRUE(container);
ASSERT_TRUE(input);
auto* inner_editor = DynamicTo<HTMLInputElement>(input)->InnerEditorElement();
ASSERT_TRUE(inner_editor);
- ASSERT_TRUE(affected);
- SetDependsOnContainerQueries(*affected);
scoped_refptr<const ComputedStyle> old_inner_style =
inner_editor->GetComputedStyle();
@@ -3525,7 +3654,7 @@ TEST_F(StyleEngineTest, MarkStyleDirtyFromContainerRecalc) {
unsigned start_count = GetStyleEngine().StyleForElementCount();
GetStyleEngine().UpdateStyleAndLayoutTreeForContainer(
- *container, LogicalSize(), LogicalAxes(kLogicalAxisBoth));
+ *container, LogicalSize(200, 100), LogicalAxes(kLogicalAxisBoth));
// Input elements mark their InnerEditorElement() style-dirty when they are
// recalculated. That means the UpdateStyleAndLayoutTreeForContainer() call
@@ -3544,6 +3673,149 @@ TEST_F(StyleEngineTest, MarkStyleDirtyFromContainerRecalc) {
EXPECT_NE(old_inner_style, new_inner_style);
}
+TEST_F(StyleEngineContainerQueryTest, UsesContainerQueries) {
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ #a { z-index:2; }
+ </style>
+ <style id=late>
+ </style>
+ <div id=a></div>
+ )HTML");
+ UpdateAllLifecyclePhases();
+ auto* a = GetDocument().getElementById("a");
+ ASSERT_TRUE(a);
+ EXPECT_EQ(2, a->ComputedStyleRef().ZIndex());
+ EXPECT_FALSE(GetStyleEngine().UsesContainerQueries());
+
+ auto* late_style = GetDocument().getElementById("late");
+ ASSERT_TRUE(late_style);
+
+ late_style->setTextContent(R"CSS(
+ @container (min-width: 1px) {
+ #a { color: green; }
+ }
+ )CSS");
+ GetStyleEngine().UpdateActiveStyle();
+ // Note the @container query does not match anything (it's not inside a
+ // container), but UsesContainerQueries should still be true.
+ EXPECT_TRUE(GetStyleEngine().UsesContainerQueries());
+
+ late_style->setTextContent("");
+ GetStyleEngine().UpdateActiveStyle();
+ EXPECT_FALSE(GetStyleEngine().UsesContainerQueries());
+}
+
+TEST_F(StyleEngineContainerQueryTest,
+ UpdateStyleAndLayoutTreeWithoutLayoutDependency) {
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ .toggle { width: 200px; }
+ </style>
+ <div id=a></div>
+ )HTML");
+ UpdateAllLifecyclePhases();
+ EXPECT_FALSE(GetDocument().View()->NeedsLayout());
+
+ Element* a = GetDocument().getElementById("a");
+ ASSERT_TRUE(a);
+ a->classList().Add("toggle");
+
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_TRUE(GetDocument().View()->NeedsLayout())
+ << "No layout if style does not depend on layout";
+}
+
+TEST_F(StyleEngineContainerQueryTest,
+ UpdateStyleAndLayoutTreeWithLayoutDependency) {
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ #container {
+ container-type: inline-size;
+ }
+ #container.toggle {
+ width: 200px;
+ }
+
+ @container (min-width: 200px) {
+ #a { z-index: 2; }
+ }
+ </style>
+ <main id=container>
+ <div id=a></div>
+ </main>
+ )HTML");
+ UpdateAllLifecyclePhases();
+ EXPECT_FALSE(GetDocument().View()->NeedsLayout());
+
+ Element* container = GetDocument().getElementById("container");
+ ASSERT_TRUE(container);
+ container->classList().Add("toggle");
+
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_FALSE(GetDocument().View()->NeedsLayout())
+ << "Layout should happen as part of UpdateStyleAndLayoutTree";
+
+ Element* a = GetDocument().getElementById("a");
+ ASSERT_TRUE(a);
+ EXPECT_EQ(2, a->ComputedStyleRef().ZIndex());
+}
+
+TEST_F(StyleEngineTest, ContainerRelativeUnitsRuntimeFlag) {
+ String css = R"CSS(
+ top: 1qw;
+ left: 1qh;
+ bottom: 1qi;
+ right: 1qb;
+ padding-top: 1qmin;
+ padding-right: 1qmax;
+ padding-bottom: calc(1qw);
+ margin-left: 1px;
+ )CSS";
+
+ {
+ ScopedCSSContainerRelativeUnitsForTest feature(false);
+ const CSSPropertyValueSet* set =
+ css_test_helpers::ParseDeclarationBlock(css);
+ ASSERT_TRUE(set);
+ EXPECT_EQ(1u, set->PropertyCount());
+ EXPECT_TRUE(set->HasProperty(CSSPropertyID::kMarginLeft));
+ }
+
+ {
+ ScopedCSSContainerRelativeUnitsForTest feature(true);
+ const CSSPropertyValueSet* set =
+ css_test_helpers::ParseDeclarationBlock(css);
+ ASSERT_TRUE(set);
+ EXPECT_EQ(8u, set->PropertyCount());
+ }
+}
+
+TEST_F(StyleEngineTest, ContainerPropertiesRuntimeFlag) {
+ Vector<String> declarations = {"container-type:inline-size",
+ "container-name:foo", "container:inline-size"};
+
+ {
+ ScopedCSSContainerQueriesForTest feature(false);
+
+ for (const String& decl : declarations) {
+ const auto* set = css_test_helpers::ParseDeclarationBlock(decl);
+ ASSERT_TRUE(set);
+ EXPECT_EQ(0u, set->PropertyCount());
+ }
+ }
+
+ {
+ ScopedCSSContainerQueriesForTest feature(true);
+
+ for (const String& decl : declarations) {
+ const auto* set = css_test_helpers::ParseDeclarationBlock(decl);
+ ASSERT_TRUE(set);
+ EXPECT_GT(set->PropertyCount(), 0u);
+ }
+ }
+}
+
TEST_F(StyleEngineTest, VideoControlsReject) {
GetDocument().body()->setInnerHTML(R"HTML(
<video controls></video>
@@ -3552,8 +3824,7 @@ TEST_F(StyleEngineTest, VideoControlsReject) {
UpdateAllLifecyclePhases();
StyleEngine& engine = GetStyleEngine();
- // If the Stats() were already enabled, we would not start with 0 counts.
- EXPECT_FALSE(engine.Stats());
+ // Even if the Stats() were already enabled, the following resets it to 0.
engine.SetStatsEnabled(true);
StyleResolverStats* stats = engine.Stats();
@@ -3595,8 +3866,7 @@ TEST_F(StyleEngineTest, FastRejectForHostChild) {
UpdateAllLifecyclePhases();
StyleEngine& engine = GetStyleEngine();
- // If the Stats() were already enabled, we would not start with 0 counts.
- EXPECT_FALSE(engine.Stats());
+ // Even if the Stats() were already enabled, the following resets it to 0.
engine.SetStatsEnabled(true);
StyleResolverStats* stats = engine.Stats();
@@ -3636,8 +3906,7 @@ TEST_F(StyleEngineTest, RejectSlottedSelector) {
UpdateAllLifecyclePhases();
StyleEngine& engine = GetStyleEngine();
- // If the Stats() were already enabled, we would not start with 0 counts.
- EXPECT_FALSE(engine.Stats());
+ // Even if the Stats() were already enabled, the following resets it to 0.
engine.SetStatsEnabled(true);
StyleResolverStats* stats = engine.Stats();
@@ -3701,63 +3970,6 @@ TEST_F(StyleEngineTest, TargetTextUseCount) {
ClearUseCounter(WebFeature::kCSSSelectorTargetText);
}
-// https://crbug.com/1172679
-TEST_F(StyleEngineTest, CounterContentNameCase) {
- // Reproducible only with legacy counter styles
- ScopedCSSAtRuleCounterStyleForTest disabled_scope(false);
-
- GetDocument().body()->setInnerHTML(R"HTML(
- <style>
- body { counter-reset: a; }
- #target::before {
- counter-increment: a;
- content: counter(a, Hiragana);
- }
- </style>
- <p id="target"></p>
- )HTML");
-
- // Shouldn't crash
- UpdateAllLifecyclePhases();
-
- PseudoElement* before =
- GetDocument().getElementById("target")->GetPseudoElement(kPseudoIdBefore);
- LayoutCounter* counter =
- To<LayoutCounter>(before->GetLayoutObject()->SlowFirstChild());
-
- // Hiragana "A"
- EXPECT_EQ(String(u"\u3042"), counter->GetText());
-}
-
-// https://crbug.com/1182969
-TEST_F(StyleEngineTest, CountersShouldNotCauseListMarkerUpdates) {
- // Reproducible only when @counter-style rules are disabled
- ScopedCSSAtRuleCounterStyleForTest disabled_scope(false);
-
- GetDocument().body()->setInnerHTML(R"HTML(
- <style>
- body { counter-reset: a; }
- p::before {
- counter-increment: a;
- content: counter(a);
- }
- </style>
- <ol><li id="target"></li></ol>
- )HTML");
-
- // Shouldn't crash
- UpdateAllLifecyclePhases();
-
- LayoutObject* list_item =
- GetDocument().getElementById("target")->GetLayoutObject();
- LayoutObject* marker = ListMarker::MarkerFromListItem(list_item);
-
- GetDocument().body()->appendChild(GetDocument().CreateElementForBinding("p"));
- GetDocument().UpdateStyleAndLayoutTree();
-
- EXPECT_FALSE(marker->NeedsLayout());
-}
-
TEST_F(StyleEngineTest, NonDirtyStyleRecalcRoot) {
GetDocument().body()->setInnerHTML(R"HTML(
<div id="host">
@@ -3782,8 +3994,6 @@ TEST_F(StyleEngineTest, NonDirtyStyleRecalcRoot) {
}
TEST_F(StyleEngineTest, AtCounterStyleUseCounter) {
- ScopedCSSAtRuleCounterStyleForTest scope(true);
-
GetDocument().View()->UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(IsUseCounted(WebFeature::kCSSAtRuleCounterStyle));
@@ -3793,7 +4003,6 @@ TEST_F(StyleEngineTest, AtCounterStyleUseCounter) {
}
TEST_F(StyleEngineTest, CounterStyleDisabledInShadowDOM) {
- ScopedCSSAtRuleCounterStyleForTest counter_style_enabled(true);
ScopedCSSAtRuleCounterStyleInShadowDOMForTest
counter_style_in_shadow_dom_disabled(false);
@@ -3834,4 +4043,50 @@ TEST_F(StyleEngineTest, CounterStyleDisabledInShadowDOM) {
EXPECT_EQ("1. ", GetListMarkerText(shadow_bar));
}
+TEST_F(StyleEngineTest, SystemFontsObeyDefaultFontSize) {
+ // <input> get assigned "font: -webkit-small-control" in the UA sheet.
+ Element* body = GetDocument().body();
+ body->setInnerHTML("<input>");
+ Element* input = GetDocument().QuerySelector("input");
+
+ // Test the standard font sizes that can be chosen in chrome://settings/
+ for (int fontSize : {9, 12, 16, 20, 24}) {
+ GetDocument().GetSettings()->SetDefaultFontSize(fontSize);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(fontSize, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(fontSize - 3, input->GetComputedStyle()->FontSize());
+ }
+
+ // Now test degenerate cases
+ GetDocument().GetSettings()->SetDefaultFontSize(-1);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(1, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(1, input->GetComputedStyle()->FontSize());
+
+ GetDocument().GetSettings()->SetDefaultFontSize(0);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(1, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(13, input->GetComputedStyle()->FontSize());
+
+ GetDocument().GetSettings()->SetDefaultFontSize(1);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(1, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(1, input->GetComputedStyle()->FontSize());
+
+ GetDocument().GetSettings()->SetDefaultFontSize(2);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(2, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(2, input->GetComputedStyle()->FontSize());
+
+ GetDocument().GetSettings()->SetDefaultFontSize(3);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(3, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(0, input->GetComputedStyle()->FontSize());
+
+ GetDocument().GetSettings()->SetDefaultFontSize(12345);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(10000, body->GetComputedStyle()->FontSize());
+ EXPECT_EQ(10000, input->GetComputedStyle()->FontSize());
+}
+
} // 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 d536af0a403..500d3ad20a0 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
@@ -25,12 +25,13 @@
#include <bitset>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_markup.h"
#include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
#include "third_party/blink/renderer/core/css/css_value_pair.h"
#include "third_party/blink/renderer/core/css/css_value_pool.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
@@ -105,7 +106,8 @@ StylePropertySerializer::CSSPropertyValueSetForSerializer::PropertyAt(
CSSPropertyValueSet::PropertyReference property =
property_set_->PropertyAt(all_index_);
return StylePropertySerializer::PropertyValueForSerializer(
- CSSProperty::Get(property_id), &property.Value(), property.IsImportant());
+ CSSProperty::Get(property_id).GetCSSPropertyName(), &property.Value(),
+ property.IsImportant());
}
bool StylePropertySerializer::CSSPropertyValueSetForSerializer::
@@ -179,12 +181,13 @@ StylePropertySerializer::StylePropertySerializer(
String StylePropertySerializer::GetCustomPropertyText(
const PropertyValueForSerializer& property,
bool is_not_first_decl) const {
- DCHECK_EQ(property.Property().PropertyID(), CSSPropertyID::kVariable);
+ DCHECK_EQ(property.Name().Id(), CSSPropertyID::kVariable);
StringBuilder result;
if (is_not_first_decl)
result.Append(' ');
const auto* value = To<CSSCustomPropertyDeclaration>(property.Value());
- SerializeIdentifier(value->GetName(), result, is_not_first_decl);
+ SerializeIdentifier(property.Name().ToAtomicString(), result,
+ is_not_first_decl);
result.Append(':');
if (!value->Value())
result.Append(' ');
@@ -195,14 +198,14 @@ String StylePropertySerializer::GetCustomPropertyText(
return result.ToString();
}
-String StylePropertySerializer::GetPropertyText(const CSSProperty& property,
+String StylePropertySerializer::GetPropertyText(const CSSPropertyName& name,
const String& value,
bool is_important,
bool is_not_first_decl) const {
StringBuilder result;
if (is_not_first_decl)
result.Append(' ');
- result.Append(property.GetPropertyName());
+ result.Append(name.ToAtomicString());
result.Append(": ");
result.Append(value);
if (is_important)
@@ -225,24 +228,29 @@ String StylePropertySerializer::AsText() const {
StylePropertySerializer::PropertyValueForSerializer property =
property_set_.PropertyAt(n);
- const CSSProperty& property_class = property.Property();
- CSSPropertyID property_id = property_class.PropertyID();
- // Only web exposed properties should be part of the style.
- DCHECK(property_class.IsWebExposed());
- // All shorthand properties should have been expanded at parse time.
- DCHECK(property_set_.IsDescriptorContext() ||
- (property_class.IsProperty() && !property_class.IsShorthand()));
- DCHECK(!property_set_.IsDescriptorContext() ||
- property_class.IsDescriptor());
+ const CSSPropertyName& name = property.Name();
+ CSSPropertyID property_id = name.Id();
+
+#if DCHECK_IS_ON()
+ if (property_id != CSSPropertyID::kVariable) {
+ const CSSProperty& property_class = CSSProperty::Get(property_id);
+ // Only web exposed properties should be part of the style.
+ DCHECK(property_class.IsWebExposed());
+ // All shorthand properties should have been expanded at parse time.
+ DCHECK(property_set_.IsDescriptorContext() ||
+ (property_class.IsProperty() && !property_class.IsShorthand()));
+ DCHECK(!property_set_.IsDescriptorContext() ||
+ property_class.IsDescriptor());
+ }
+#endif // DCHECK_IS_ON()
switch (property_id) {
case CSSPropertyID::kVariable:
result.Append(GetCustomPropertyText(property, num_decls++));
continue;
case CSSPropertyID::kAll:
- result.Append(GetPropertyText(property_class,
- property.Value()->CssText(),
+ result.Append(GetPropertyText(name, property.Value()->CssText(),
property.IsImportant(), num_decls++));
continue;
default:
@@ -282,9 +290,9 @@ String StylePropertySerializer::AsText() const {
if (shorthand_result.IsEmpty())
continue;
- result.Append(GetPropertyText(CSSProperty::Get(shorthand_property),
- shorthand_result, property.IsImportant(),
- num_decls++));
+ result.Append(GetPropertyText(
+ CSSProperty::Get(shorthand_property).GetCSSPropertyName(),
+ shorthand_result, property.IsImportant(), num_decls++));
serialized_as_shorthand = true;
for (unsigned i = 0; i < shorthand.length(); i++) {
longhand_serialized.set(
@@ -296,7 +304,7 @@ String StylePropertySerializer::AsText() const {
if (serialized_as_shorthand)
continue;
- result.Append(GetPropertyText(property_class, property.Value()->CssText(),
+ result.Append(GetPropertyText(name, property.Value()->CssText(),
property.IsImportant(), num_decls++));
}
@@ -474,6 +482,8 @@ String StylePropertySerializer::SerializeShorthand(
return GetShorthandValue(borderInlineStartShorthand());
case CSSPropertyID::kBorderInlineEnd:
return GetShorthandValue(borderInlineEndShorthand());
+ case CSSPropertyID::kContainer:
+ return ContainerValue();
case CSSPropertyID::kOutline:
return GetShorthandValue(outlineShorthand());
case CSSPropertyID::kBorderColor:
@@ -671,6 +681,33 @@ bool StylePropertySerializer::AppendFontLonghandValueIfNotNormal(
return true;
}
+String StylePropertySerializer::ContainerValue() const {
+ CHECK_EQ(containerShorthand().length(), 2u);
+ CHECK_EQ(containerShorthand().properties()[0],
+ &GetCSSPropertyContainerType());
+ CHECK_EQ(containerShorthand().properties()[1],
+ &GetCSSPropertyContainerName());
+
+ CSSValueList* list = CSSValueList::CreateSlashSeparated();
+
+ const CSSValue* type =
+ property_set_.GetPropertyCSSValue(GetCSSPropertyContainerType());
+ const CSSValue* name =
+ property_set_.GetPropertyCSSValue(GetCSSPropertyContainerName());
+
+ DCHECK(type);
+ DCHECK(name);
+
+ list->Append(*type);
+
+ if (!(IsA<CSSIdentifierValue>(name) &&
+ To<CSSIdentifierValue>(*name).GetValueID() == CSSValueID::kNone)) {
+ list->Append(*name);
+ }
+
+ return list->CssText();
+}
+
String StylePropertySerializer::FontValue() const {
int font_size_property_index =
property_set_.FindPropertyIndex(GetCSSPropertyFontSize());
@@ -730,6 +767,26 @@ String StylePropertySerializer::FontValue() const {
east_asian_value->IsValueList())
return g_empty_string;
+ const StylePropertyShorthand& shorthand = fontShorthand();
+ const CSSProperty** longhands = shorthand.properties();
+ unsigned length = shorthand.length();
+ const CSSValue* first = property_set_.GetPropertyCSSValue(*longhands[0]);
+ if (const auto* system_font =
+ DynamicTo<cssvalue::CSSPendingSystemFontValue>(first)) {
+ for (unsigned i = 1; i < length; i++) {
+ const CSSValue* value = property_set_.GetPropertyCSSValue(*longhands[i]);
+ if (!DataEquivalent(first, value))
+ return g_empty_string;
+ }
+ return getValueName(system_font->SystemFontId());
+ } else {
+ for (unsigned i = 1; i < length; i++) {
+ const CSSValue* value = property_set_.GetPropertyCSSValue(*longhands[i]);
+ if (value->IsPendingSystemFontValue())
+ return g_empty_string;
+ }
+ }
+
StringBuilder result;
AppendFontLonghandValueIfNotNormal(GetCSSPropertyFontStyle(), result);
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 00edf39e27f..f6407d459f7 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
@@ -30,6 +30,7 @@
namespace blink {
+class CSSPropertyName;
class CSSPropertyValueSet;
class StylePropertyShorthand;
@@ -55,6 +56,7 @@ class StylePropertySerializer {
String PageBreakPropertyValue(const StylePropertyShorthand&) const;
String GetShorthandValue(const StylePropertyShorthand&,
String separator = " ") const;
+ String ContainerValue() const;
String FontValue() const;
String FontVariantValue() const;
bool AppendFontLonghandValueIfNotNormal(const CSSProperty&,
@@ -62,7 +64,7 @@ class StylePropertySerializer {
String OffsetValue() const;
String TextDecorationValue() const;
String BackgroundRepeatPropertyValue() const;
- String GetPropertyText(const CSSProperty&,
+ String GetPropertyText(const CSSPropertyName&,
const String& value,
bool is_important,
bool is_not_first_decl) const;
@@ -88,24 +90,23 @@ class StylePropertySerializer {
explicit PropertyValueForSerializer(
CSSPropertyValueSet::PropertyReference property)
: value_(&property.Value()),
- property_(CSSProperty::Get(property.Id())),
+ name_(property.Name()),
is_important_(property.IsImportant()) {}
// TODO(sashab): Make this take a const CSSValue&.
- PropertyValueForSerializer(const CSSProperty& property,
+ PropertyValueForSerializer(const CSSPropertyName& name,
const CSSValue* value,
bool is_important)
- : value_(value), property_(property), is_important_(is_important) {}
+ : value_(value), name_(name), is_important_(is_important) {}
- // TODO(crbug.com/980160): Remove this function.
- const CSSProperty& Property() const { return property_; }
+ const CSSPropertyName& Name() const { return name_; }
const CSSValue* Value() const { return value_; }
bool IsImportant() const { return is_important_; }
bool IsValid() const { return value_; }
private:
const CSSValue* value_;
- const CSSProperty& property_;
+ CSSPropertyName name_;
bool is_important_;
};
diff --git a/chromium/third_party/blink/renderer/core/css/style_property_shorthand_custom.cc b/chromium/third_party/blink/renderer/core/css/style_property_shorthand_custom.cc
index 8fb1a5d927f..076849b6dac 100644
--- a/chromium/third_party/blink/renderer/core/css/style_property_shorthand_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_property_shorthand_custom.cc
@@ -21,7 +21,7 @@
#include "third_party/blink/renderer/core/style_property_shorthand.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/style_recalc.cc b/chromium/third_party/blink/renderer/core/css/style_recalc.cc
index c92bb6f2d5d..d5ebf9cb82a 100644
--- a/chromium/third_party/blink/renderer/core/css/style_recalc.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_recalc.cc
@@ -21,16 +21,16 @@ bool StyleRecalcChange::TraversePseudoElements(const Element& element) const {
bool StyleRecalcChange::TraverseChild(const Node& node) const {
return ShouldRecalcStyleFor(node) || node.ChildNeedsStyleRecalc() ||
- RecalcContainerQueryDependent();
+ node.GetForceReattachLayoutTree() || RecalcContainerQueryDependent();
}
bool StyleRecalcChange::ShouldRecalcStyleFor(const Node& node) const {
+ if (flags_ & kSuppressRecalc)
+ return false;
if (RecalcChildren())
return true;
if (node.NeedsStyleRecalc())
return true;
- if (node.GetForceReattachLayoutTree())
- return true;
// Early exit before getting the computed style.
if (propagate_ != kClearEnsured && !RecalcContainerQueryDependent())
return false;
@@ -56,20 +56,26 @@ bool StyleRecalcChange::ShouldUpdatePseudoElement(
pseudo_element.ComputedStyleRef().DependsOnContainerQueries();
}
-bool StyleRecalcChange::RecalcContainerQueryDependentChildren(
+StyleRecalcChange::Flags StyleRecalcChange::FlagsForChildren(
const Element& element) const {
- // We are at the container root for a container query recalc.
- if (propagate_ == kRecalcContainerQueryDependent)
- return true;
- if (!RecalcContainerQueryDependent())
- return false;
- // Don't traverse into children if we hit a descendant container while
- // recalculating container queries. If the queries for this container also
- // changes, we will enter another container query recalc for this subtree from
- // layout.
- if (LayoutObject* layout_object = element.GetLayoutObject())
- return !layout_object->IsContainerForContainerQueries();
- return true;
+ Flags result = flags_;
+
+ // Note that kSuppressRecalc is used on the root container for the
+ // interleaved style recalc.
+ if ((result & (kRecalcContainerFlags | kSuppressRecalc)) ==
+ kRecalcContainer) {
+ // Don't traverse into children if we hit a descendant container while
+ // recalculating container queries. If the queries for this container also
+ // changes, we will enter another container query recalc for this subtree
+ // from layout.
+ const ComputedStyle* old_style = element.GetComputedStyle();
+ if (old_style && old_style->IsContainerForContainerQueries())
+ result &= ~kRecalcContainer;
+ }
+
+ result &= ~kSuppressRecalc;
+
+ return result;
}
StyleRecalcContext StyleRecalcContext::FromAncestors(Element& element) {
@@ -77,10 +83,10 @@ StyleRecalcContext StyleRecalcContext::FromAncestors(Element& element) {
// TODO(crbug.com/1145970): Avoid this work if we're not inside a container.
while ((ancestor = DynamicTo<Element>(
LayoutTreeBuilderTraversal::Parent(*ancestor)))) {
- ContainerQueryEvaluator* evaluator = ancestor->GetContainerQueryEvaluator();
- if (evaluator)
- return StyleRecalcContext{evaluator};
+ if (ancestor->GetContainerQueryEvaluator())
+ return StyleRecalcContext{ancestor};
}
+
return StyleRecalcContext();
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_recalc.h b/chromium/third_party/blink/renderer/core/css/style_recalc.h
index 6c958c9c829..9e080e2ed72 100644
--- a/chromium/third_party/blink/renderer/core/css/style_recalc.h
+++ b/chromium/third_party/blink/renderer/core/css/style_recalc.h
@@ -5,11 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_RECALC_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_RECALC_H_
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
-class ContainerQueryEvaluator;
class Element;
class Node;
class PseudoElement;
@@ -17,7 +17,27 @@ class PseudoElement;
// Class for keeping track of the need for traversing down flat tree children,
// recompute their computed styles, and marking nodes for layout tree re-
// attachment during the style recalc phase.
-class StyleRecalcChange {
+class CORE_EXPORT StyleRecalcChange {
+ private:
+ enum Flag {
+ kNoFlags = 0,
+ // Recalc container query dependent elements within this container,
+ // but not in nested containers.
+ kRecalcContainer = 1 << 0,
+ // Recalc container query dependent elements within this container,
+ // and also in nested containers.
+ kRecalcDescendantContainers = 1 << 1,
+ // If set, need to reattach layout tree.
+ kReattach = 1 << 2,
+ // If set, will prevent style recalc for the node passed to
+ // ShouldRecalcStyleFor. This flag is lost when ForChildren is called.
+ kSuppressRecalc = 1 << 3,
+ };
+ using Flags = uint8_t;
+
+ static const Flags kRecalcContainerFlags =
+ kRecalcContainer | kRecalcDescendantContainers;
+
public:
enum Propagate {
// No need to update style of any children.
@@ -25,11 +45,6 @@ class StyleRecalcChange {
// Need to traverse children in display:none or non-slotted/distributed
// children of shadow hosts to clear ensured computed styles.
kClearEnsured,
- // Need to traverse descendants to invalidate style for container queries.
- // This value is passed in for the container itself, it will translate into
- // recalc_container_query_dependent_=true for descendants. We should not
- // recalc style for the container itself.
- kRecalcContainerQueryDependent,
// Need to update existence and style for pseudo elements.
kUpdatePseudoElements,
// Need to recalculate style for children for inheritance. All changed
@@ -44,30 +59,41 @@ class StyleRecalcChange {
StyleRecalcChange() = default;
StyleRecalcChange(const StyleRecalcChange&) = default;
- StyleRecalcChange(Propagate propagate) : propagate_(propagate) {}
+ StyleRecalcChange& operator=(const StyleRecalcChange&) = default;
+ explicit StyleRecalcChange(Propagate propagate) : propagate_(propagate) {}
StyleRecalcChange ForChildren(const Element& element) const {
- return {RecalcDescendants() ? kRecalcDescendants : kNo, reattach_,
- RecalcContainerQueryDependentChildren(element)};
+ return {RecalcDescendants() ? kRecalcDescendants : kNo,
+ FlagsForChildren(element)};
}
StyleRecalcChange ForPseudoElement() const {
if (propagate_ == kUpdatePseudoElements)
- return {kRecalcChildren, reattach_, recalc_container_query_dependent_};
+ return {kRecalcChildren, flags_};
return *this;
}
StyleRecalcChange EnsureAtLeast(Propagate propagate) const {
if (propagate > propagate_)
- return {propagate, reattach_, recalc_container_query_dependent_};
- return {propagate_, reattach_, recalc_container_query_dependent_};
+ return {propagate, flags_};
+ return {propagate_, flags_};
}
StyleRecalcChange ForceRecalcDescendants() const {
- return {kRecalcDescendants, reattach_, recalc_container_query_dependent_};
+ return {kRecalcDescendants, flags_};
}
StyleRecalcChange ForceReattachLayoutTree() const {
- return {propagate_, true, recalc_container_query_dependent_};
+ return {propagate_, static_cast<Flags>(flags_ | kReattach)};
+ }
+ StyleRecalcChange ForceRecalcContainer() const {
+ return {propagate_, static_cast<Flags>(flags_ | kRecalcContainer)};
+ }
+ StyleRecalcChange ForceRecalcDescendantContainers() const {
+ return {propagate_,
+ static_cast<Flags>(flags_ | kRecalcDescendantContainers)};
+ }
+ StyleRecalcChange SuppressRecalc() const {
+ return {propagate_, static_cast<Flags>(flags_ | kSuppressRecalc)};
}
- bool ReattachLayoutTree() const { return reattach_; }
+ bool ReattachLayoutTree() const { return flags_ & kReattach; }
bool RecalcChildren() const { return propagate_ > kUpdatePseudoElements; }
bool RecalcDescendants() const { return propagate_ == kRecalcDescendants; }
bool UpdatePseudoElements() const { return propagate_ != kNo; }
@@ -79,24 +105,18 @@ class StyleRecalcChange {
bool ShouldUpdatePseudoElement(const PseudoElement&) const;
private:
- StyleRecalcChange(Propagate propagate,
- bool reattach,
- bool recalc_container_query_dependent)
- : propagate_(propagate),
- reattach_(reattach),
- recalc_container_query_dependent_(recalc_container_query_dependent) {}
+ StyleRecalcChange(Propagate propagate, Flags flags)
+ : propagate_(propagate), flags_(flags) {}
bool RecalcContainerQueryDependent() const {
- return recalc_container_query_dependent_;
+ return flags_ & kRecalcContainerFlags;
}
- bool RecalcContainerQueryDependentChildren(const Element&) const;
+ Flags FlagsForChildren(const Element&) const;
// To what extent do we need to update style for children.
Propagate propagate_ = kNo;
- // Need to reattach layout tree if true.
- bool reattach_ = false;
- // Force recalc of elements depending on container queries.
- bool recalc_container_query_dependent_ = false;
+ // See StyleRecalc::Flag.
+ Flags flags_ = kNoFlags;
};
// StyleRecalcContext is an object that is passed on the stack during
@@ -113,10 +133,9 @@ class StyleRecalcContext {
// resolving the style of the given Element.
static StyleRecalcContext FromAncestors(Element&);
- // If style is being calculated for an element inside a container,
- // this ContainerQueryEvaluator may be used to evaluate @container
- // rules against that container.
- ContainerQueryEvaluator* cq_evaluator = nullptr;
+ // Set to the nearest container (for container queries), if any.
+ // This is used to evaluate container queries in ElementRuleCollector.
+ Element* container = nullptr;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_recalc_test.cc b/chromium/third_party/blink/renderer/core/css/style_recalc_test.cc
new file mode 100644
index 00000000000..8c388943548
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/style_recalc_test.cc
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/style_recalc.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.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+class StyleRecalcTest : public PageTestBase {};
+
+TEST_F(StyleRecalcTest, SuppressRecalc) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .foo { color: green; }
+ </style>
+ <div id=element></div>
+ )HTML");
+
+ Element* element = GetDocument().getElementById("element");
+ ASSERT_TRUE(element);
+ element->classList().Add("foo");
+
+ EXPECT_TRUE(StyleRecalcChange().ShouldRecalcStyleFor(*element));
+ EXPECT_FALSE(
+ StyleRecalcChange().SuppressRecalc().ShouldRecalcStyleFor(*element));
+ // The flag should be lost when ForChildren is called.
+ EXPECT_TRUE(StyleRecalcChange()
+ .SuppressRecalc()
+ .ForChildren(*element)
+ .ShouldRecalcStyleFor(*element));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_request.h b/chromium/third_party/blink/renderer/core/css/style_request.h
index 169aa936ed6..62f9f0de88c 100644
--- a/chromium/third_party/blink/renderer/core/css/style_request.h
+++ b/chromium/third_party/blink/renderer/core/css/style_request.h
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/layout/custom_scrollbar.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -57,10 +58,13 @@ class StyleRequest {
: parent_override(parent_override),
layout_parent_override(parent_override) {}
- StyleRequest(PseudoId pseudo_id, const ComputedStyle* parent_override)
+ StyleRequest(PseudoId pseudo_id,
+ const ComputedStyle* parent_override,
+ const AtomicString& pseudo_argument = g_null_atom)
: parent_override(parent_override),
layout_parent_override(parent_override),
- pseudo_id(pseudo_id) {}
+ pseudo_id(pseudo_id),
+ pseudo_argument(pseudo_argument) {}
StyleRequest(PseudoId pseudo_id,
CustomScrollbar* scrollbar,
@@ -76,8 +80,7 @@ class StyleRequest {
: pseudo_id(pseudo_id),
type(request_type),
scrollbar_part(kNoPart),
- scrollbar(nullptr),
- pseudo_argument(g_null_atom) {}
+ scrollbar(nullptr) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule.cc b/chromium/third_party/blink/renderer/core/css/style_rule.cc
index 536701a8bf1..ae97eb2e572 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_rule.cc
@@ -92,6 +92,12 @@ void StyleRuleBase::Trace(Visitor* visitor) const {
case kKeyframe:
To<StyleRuleKeyframe>(this)->TraceAfterDispatch(visitor);
return;
+ case kLayerBlock:
+ To<StyleRuleLayerBlock>(this)->TraceAfterDispatch(visitor);
+ return;
+ case kLayerStatement:
+ To<StyleRuleLayerStatement>(this)->TraceAfterDispatch(visitor);
+ return;
case kNamespace:
To<StyleRuleNamespace>(this)->TraceAfterDispatch(visitor);
return;
@@ -143,6 +149,12 @@ void StyleRuleBase::FinalizeGarbageCollectedObject() {
case kKeyframe:
To<StyleRuleKeyframe>(this)->~StyleRuleKeyframe();
return;
+ case kLayerBlock:
+ To<StyleRuleLayerBlock>(this)->~StyleRuleLayerBlock();
+ return;
+ case kLayerStatement:
+ To<StyleRuleLayerStatement>(this)->~StyleRuleLayerStatement();
+ return;
case kNamespace:
To<StyleRuleNamespace>(this)->~StyleRuleNamespace();
return;
@@ -183,6 +195,10 @@ StyleRuleBase* StyleRuleBase::Copy() const {
return To<StyleRuleKeyframes>(this)->Copy();
case kViewport:
return To<StyleRuleViewport>(this)->Copy();
+ case kLayerBlock:
+ return To<StyleRuleLayerBlock>(this)->Copy();
+ case kLayerStatement:
+ return To<StyleRuleLayerStatement>(this)->Copy();
case kNamespace:
return To<StyleRuleNamespace>(this)->Copy();
case kCharset:
@@ -239,6 +255,10 @@ CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet,
rule = MakeGarbageCollected<CSSKeyframesRule>(
To<StyleRuleKeyframes>(self), parent_sheet);
break;
+ case kLayerBlock:
+ case kLayerStatement:
+ // TODO(crbug.com/1095765): Implement.
+ return nullptr;
case kNamespace:
rule = MakeGarbageCollected<CSSNamespaceRule>(
To<StyleRuleNamespace>(self), parent_sheet);
@@ -454,6 +474,33 @@ void StyleRuleGroup::TraceAfterDispatch(blink::Visitor* visitor) const {
StyleRuleBase::TraceAfterDispatch(visitor);
}
+StyleRuleLayerBlock::StyleRuleLayerBlock(
+ LayerName&& name,
+ HeapVector<Member<StyleRuleBase>>& adopt_rules)
+ : StyleRuleGroup(kLayerBlock, adopt_rules), name_(std::move(name)) {}
+
+StyleRuleLayerBlock::StyleRuleLayerBlock(const StyleRuleLayerBlock& other) =
+ default;
+
+StyleRuleLayerBlock::~StyleRuleLayerBlock() = default;
+
+void StyleRuleLayerBlock::TraceAfterDispatch(blink::Visitor* visitor) const {
+ StyleRuleGroup::TraceAfterDispatch(visitor);
+}
+
+StyleRuleLayerStatement::StyleRuleLayerStatement(Vector<LayerName>&& names)
+ : StyleRuleBase(kLayerStatement), names_(std::move(names)) {}
+
+StyleRuleLayerStatement::StyleRuleLayerStatement(
+ const StyleRuleLayerStatement& other) = default;
+
+StyleRuleLayerStatement::~StyleRuleLayerStatement() = default;
+
+void StyleRuleLayerStatement::TraceAfterDispatch(
+ blink::Visitor* visitor) const {
+ StyleRuleBase::TraceAfterDispatch(visitor);
+}
+
StyleRuleCondition::StyleRuleCondition(
RuleType type,
HeapVector<Member<StyleRuleBase>>& adopt_rules)
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule.h b/chromium/third_party/blink/renderer/core/css/style_rule.h
index a3ba768834f..19e3b4088ac 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/style_rule.h
@@ -48,6 +48,8 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
kProperty,
kKeyframes,
kKeyframe,
+ kLayerBlock,
+ kLayerStatement,
kNamespace,
kContainer,
kCounterStyle,
@@ -56,6 +58,11 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
kViewport,
};
+ // Name of a cascade layer as given by an @layer rule, split at '.' into a
+ // vector. Note that this may not be the full layer name if the rule is nested
+ // in another @layer rule or in a layered @import.
+ using LayerName = Vector<AtomicString, 1>;
+
RuleType GetType() const { return static_cast<RuleType>(type_); }
bool IsCharsetRule() const { return GetType() == kCharset; }
@@ -64,6 +71,8 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
bool IsFontFaceRule() const { return GetType() == kFontFace; }
bool IsKeyframesRule() const { return GetType() == kKeyframes; }
bool IsKeyframeRule() const { return GetType() == kKeyframe; }
+ bool IsLayerBlockRule() const { return GetType() == kLayerBlock; }
+ bool IsLayerStatementRule() const { return GetType() == kLayerStatement; }
bool IsNamespaceRule() const { return GetType() == kNamespace; }
bool IsMediaRule() const { return GetType() == kMedia; }
bool IsPageRule() const { return GetType() == kPage; }
@@ -264,6 +273,45 @@ class CORE_EXPORT StyleRuleGroup : public StyleRuleBase {
HeapVector<Member<StyleRuleBase>> child_rules_;
};
+// https://www.w3.org/TR/css-cascade-5/#layer-block
+class CORE_EXPORT StyleRuleLayerBlock : public StyleRuleGroup {
+ public:
+ StyleRuleLayerBlock(LayerName&& name,
+ HeapVector<Member<StyleRuleBase>>& adopt_rule);
+ StyleRuleLayerBlock(const StyleRuleLayerBlock&);
+ ~StyleRuleLayerBlock();
+
+ const LayerName& GetName() const { return name_; }
+
+ StyleRuleLayerBlock* Copy() const {
+ return MakeGarbageCollected<StyleRuleLayerBlock>(*this);
+ }
+
+ void TraceAfterDispatch(blink::Visitor*) const;
+
+ private:
+ LayerName name_;
+};
+
+// https://www.w3.org/TR/css-cascade-5/#layer-empty
+class CORE_EXPORT StyleRuleLayerStatement : public StyleRuleBase {
+ public:
+ explicit StyleRuleLayerStatement(Vector<LayerName>&& names);
+ StyleRuleLayerStatement(const StyleRuleLayerStatement& other);
+ ~StyleRuleLayerStatement();
+
+ const Vector<LayerName>& GetNames() const { return names_; }
+
+ StyleRuleLayerStatement* copy() const {
+ return MakeGarbageCollected<StyleRuleLayerStatement>(*this);
+ }
+
+ void TraceAfterDispatch(blink::Visitor*) const;
+
+ private:
+ Vector<LayerName> names_;
+};
+
class CORE_EXPORT StyleRuleCondition : public StyleRuleGroup {
public:
String ConditionText() const { return condition_text_; }
@@ -409,6 +457,20 @@ struct DowncastTraits<StyleRuleGroup> {
};
template <>
+struct DowncastTraits<StyleRuleLayerBlock> {
+ static bool AllowFrom(const StyleRuleBase& rule) {
+ return rule.IsLayerBlockRule();
+ }
+};
+
+template <>
+struct DowncastTraits<StyleRuleLayerStatement> {
+ static bool AllowFrom(const StyleRuleBase& rule) {
+ return rule.IsLayerStatementRule();
+ }
+};
+
+template <>
struct DowncastTraits<StyleRuleMedia> {
static bool AllowFrom(const StyleRuleBase& rule) {
return rule.IsMediaRule();
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule_import.cc b/chromium/third_party/blink/renderer/core/css/style_rule_import.cc
index ed9abb6bd0d..f7d67765249 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule_import.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_rule_import.cc
@@ -35,12 +35,14 @@
namespace blink {
StyleRuleImport::StyleRuleImport(const String& href,
+ absl::optional<LayerName>&& layer,
scoped_refptr<MediaQuerySet> media,
OriginClean origin_clean)
: StyleRuleBase(kImport),
parent_style_sheet_(nullptr),
style_sheet_client_(MakeGarbageCollected<ImportedStyleSheetClient>(this)),
str_href_(href),
+ layer_(std::move(layer)),
media_queries_(media),
loading_(false),
origin_clean_(origin_clean) {
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule_import.h b/chromium/third_party/blink/renderer/core/css/style_rule_import.h
index 30f02f3e00e..94a07cf0117 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule_import.h
+++ b/chromium/third_party/blink/renderer/core/css/style_rule_import.h
@@ -38,6 +38,7 @@ class StyleRuleImport : public StyleRuleBase {
public:
StyleRuleImport(const String& href,
+ absl::optional<LayerName>&& layer,
scoped_refptr<MediaQuerySet>,
OriginClean origin_clean);
~StyleRuleImport();
@@ -57,6 +58,9 @@ class StyleRuleImport : public StyleRuleBase {
void RequestStyleSheet();
+ bool IsLayered() const { return layer_.has_value(); }
+ const LayerName& GetLayerName() const { return layer_.value(); }
+
void TraceAfterDispatch(blink::Visitor*) const;
private:
@@ -95,6 +99,7 @@ class StyleRuleImport : public StyleRuleBase {
Member<ImportedStyleSheetClient> style_sheet_client_;
String str_href_;
+ absl::optional<LayerName> layer_;
scoped_refptr<MediaQuerySet> media_queries_;
Member<StyleSheetContents> style_sheet_;
bool loading_;
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 c2f9311a3a8..142e6bf9be8 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
@@ -51,7 +51,7 @@ class CORE_EXPORT StyleSheetCollection
StyleSheetCollection();
StyleSheetCollection(const StyleSheetCollection&) = delete;
StyleSheetCollection& operator=(const StyleSheetCollection&) = delete;
- virtual ~StyleSheetCollection() = default;
+ ~StyleSheetCollection() override = default;
const ActiveStyleSheetVector& ActiveStyleSheets() const {
return active_style_sheets_;
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 120dd10ceb0..ef3cb134840 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
@@ -316,7 +316,7 @@ void StyleSheetContents::ParserAddNamespace(const AtomicString& prefix,
const AtomicString& StyleSheetContents::NamespaceURIFromPrefix(
const AtomicString& prefix) const {
- return namespaces_.at(prefix);
+ return namespaces_.DeprecatedAtOrEmptyValue(prefix);
}
void StyleSheetContents::ParseAuthorStyleSheet(
@@ -487,6 +487,7 @@ static bool ChildRulesHaveFailedOrCanceledSubresources(
break;
case StyleRuleBase::kContainer:
case StyleRuleBase::kMedia:
+ case StyleRuleBase::kLayerBlock:
if (ChildRulesHaveFailedOrCanceledSubresources(
To<StyleRuleGroup>(rule)->ChildRules()))
return true;
@@ -500,6 +501,7 @@ static bool ChildRulesHaveFailedOrCanceledSubresources(
case StyleRuleBase::kProperty:
case StyleRuleBase::kKeyframes:
case StyleRuleBase::kKeyframe:
+ case StyleRuleBase::kLayerStatement:
case StyleRuleBase::kScrollTimeline:
case StyleRuleBase::kSupports:
case StyleRuleBase::kViewport:
diff --git a/chromium/third_party/blink/renderer/core/css/style_traversal_root.cc b/chromium/third_party/blink/renderer/core/css/style_traversal_root.cc
index a0bb3942ded..eb7a5d80853 100644
--- a/chromium/third_party/blink/renderer/core/css/style_traversal_root.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_traversal_root.cc
@@ -57,9 +57,10 @@ void StyleTraversalRoot::Update(ContainerNode* common_ancestor,
}
#if DCHECK_IS_ON()
-bool StyleTraversalRoot::InDOMRemoval() const {
+bool StyleTraversalRoot::IsModifyingFlatTree() const {
DCHECK(root_node_);
- return root_node_->GetDocument().GetStyleEngine().InDOMRemoval();
+ return root_node_->GetDocument().GetStyleEngine().InDOMRemoval() ||
+ root_node_->GetDocument().IsInSlotAssignmentRecalc();
}
#endif
diff --git a/chromium/third_party/blink/renderer/core/css/style_traversal_root.h b/chromium/third_party/blink/renderer/core/css/style_traversal_root.h
index b45acd79609..04c3f821890 100644
--- a/chromium/third_party/blink/renderer/core/css/style_traversal_root.h
+++ b/chromium/third_party/blink/renderer/core/css/style_traversal_root.h
@@ -71,13 +71,14 @@ class CORE_EXPORT StyleTraversalRoot {
friend class StyleTraversalRootTestImpl;
#if DCHECK_IS_ON()
- bool InDOMRemoval() const;
+ bool IsModifyingFlatTree() const;
#endif
void AssertRootNodeInvariants() {
#if DCHECK_IS_ON()
DCHECK(!root_node_ || root_node_->IsDocumentNode() ||
- IsDirty(*root_node_) || IsChildDirty(*root_node_) || InDOMRemoval());
+ IsDirty(*root_node_) || IsChildDirty(*root_node_) ||
+ IsModifyingFlatTree());
#endif
}
diff --git a/chromium/third_party/blink/renderer/core/css/threaded/css_to_length_conversion_data_threaded_test.cc b/chromium/third_party/blink/renderer/core/css/threaded/css_to_length_conversion_data_threaded_test.cc
index f5e79068125..4dc91bb18f5 100644
--- a/chromium/third_party/blink/renderer/core/css/threaded/css_to_length_conversion_data_threaded_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/threaded/css_to_length_conversion_data_threaded_test.cc
@@ -19,8 +19,9 @@ TSAN_TEST(CSSToLengthConversionDataThreadedTest, Construction) {
Font font(fontDescription);
CSSToLengthConversionData::FontSizes fontSizes(16, 16, &font, 1);
CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize,
- 1);
+ container_sizes, 1);
});
}
@@ -30,8 +31,9 @@ TSAN_TEST(CSSToLengthConversionDataThreadedTest, ConversionEm) {
Font font(fontDescription);
CSSToLengthConversionData::FontSizes fontSizes(16, 16, &font, 1);
CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize,
- 1);
+ container_sizes, 1);
CSSPrimitiveValue& value = *CSSNumericLiteralValue::Create(
3.14, CSSPrimitiveValue::UnitType::kEms);
@@ -47,8 +49,9 @@ TSAN_TEST(CSSToLengthConversionDataThreadedTest, ConversionPixel) {
Font font(fontDescription);
CSSToLengthConversionData::FontSizes fontSizes(16, 16, &font, 1);
CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize,
- 1);
+ container_sizes, 1);
CSSPrimitiveValue& value = *CSSNumericLiteralValue::Create(
44, CSSPrimitiveValue::UnitType::kPixels);
@@ -64,8 +67,9 @@ TSAN_TEST(CSSToLengthConversionDataThreadedTest, ConversionViewport) {
Font font(fontDescription);
CSSToLengthConversionData::FontSizes fontSizes(16, 16, &font, 1);
CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize,
- 1);
+ container_sizes, 1);
CSSPrimitiveValue& value = *CSSNumericLiteralValue::Create(
1, CSSPrimitiveValue::UnitType::kViewportWidth);
@@ -81,8 +85,9 @@ TSAN_TEST(CSSToLengthConversionDataThreadedTest, ConversionRem) {
Font font(fontDescription);
CSSToLengthConversionData::FontSizes fontSizes(16, 16, &font, 1);
CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
+ CSSToLengthConversionData::ContainerSizes container_sizes;
CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize,
- 1);
+ container_sizes, 1);
CSSPrimitiveValue& value =
*CSSNumericLiteralValue::Create(1, CSSPrimitiveValue::UnitType::kRems);
diff --git a/chromium/third_party/blink/renderer/core/display_lock/OWNERS b/chromium/third_party/blink/renderer/core/display_lock/OWNERS
index 3c848756f5d..9ec5de05bb2 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/OWNERS
+++ b/chromium/third_party/blink/renderer/core/display_lock/OWNERS
@@ -1,3 +1,2 @@
chrishtr@chromium.org
-rakina@chromium.org
vmpstr@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 4e49698dff4..a6207c2a5b3 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html_element_type_helpers.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.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/page/page.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
@@ -131,7 +130,10 @@ void DisplayLockContext::SetRequestedState(EContentVisibility state) {
break;
case EContentVisibility::kHidden:
UseCounter::Count(document_, WebFeature::kContentVisibilityHidden);
- RequestLock(0u);
+ RequestLock(
+ for_details_element_
+ ? static_cast<uint16_t>(DisplayLockActivationReason::kFindInPage)
+ : 0u);
break;
case EContentVisibility::kHiddenMatchable:
UseCounter::Count(document_,
@@ -167,14 +169,8 @@ void DisplayLockContext::SetRequestedState(EContentVisibility state) {
void DisplayLockContext::AdjustElementStyle(ComputedStyle* style) const {
if (state_ == EContentVisibility::kVisible)
return;
- // If not visible, element gains style, layout, and paint containment. If
- // skipped, it also gains size containment.
- // https://wicg.github.io/display-locking/#content-visibility
- auto contain =
- style->Contain() | kContainsStyle | kContainsLayout | kContainsPaint;
if (IsLocked())
- contain |= kContainsSize;
- style->SetContain(contain);
+ style->SetSkipsContents();
}
void DisplayLockContext::RequestLock(uint16_t activation_mask) {
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
index f665a7a475a..85cda9550bd 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/core/style/computed_style_base_constants.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -219,6 +220,12 @@ class CORE_EXPORT DisplayLockContext final
// We unlock auto locks for printing, which is set here.
void SetShouldUnlockAutoForPrint(bool);
+ void SetForDetailsElement(bool for_details_element) {
+ for_details_element_ = for_details_element;
+ }
+
+ bool HasElement() const { return element_; }
+
private:
// Give access to |NotifyForcedUpdateScopeStarted()| and
// |NotifyForcedUpdateScopeEnded()|.
@@ -430,6 +437,10 @@ class CORE_EXPORT DisplayLockContext final
bool set_requested_state_scope_ = false;
absl::optional<ScrollOffset> stashed_scroll_offset_;
+
+ // When we use content-visibility:hidden for a <details> element, it should be
+ // activatable by find-in-page, element fragments, and text fragments.
+ bool for_details_element_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index b85e1d236d8..093845b458f 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -899,10 +899,10 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
auto* host = GetDocument().getElementById("shadowHost");
auto* slotted = GetDocument().getElementById("slotted");
- ASSERT_FALSE(
- host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
- ASSERT_FALSE(slotted->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *host, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *slotted, DisplayLockActivationReason::kAny));
ShadowRoot& shadow_root =
host->AttachShadowRootInternal(ShadowRootType::kOpen);
@@ -912,12 +912,12 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
UpdateAllLifecyclePhasesForTest();
auto* container = shadow_root.getElementById("container");
- EXPECT_FALSE(
- host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
- EXPECT_FALSE(container->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
- EXPECT_FALSE(slotted->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *host, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *container, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *slotted, DisplayLockActivationReason::kAny));
LockElement(*container, false);
@@ -927,12 +927,13 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
.GetDisplayLockDocumentState()
.DisplayLockBlockingAllActivationCount(),
1);
- EXPECT_FALSE(
- host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
- EXPECT_TRUE(container->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
- EXPECT_TRUE(slotted->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *host, DisplayLockActivationReason::kAny));
+ // The container itself is locked but that doesn't mean it should be ignored.
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *container, DisplayLockActivationReason::kAny));
+ ASSERT_TRUE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *slotted, DisplayLockActivationReason::kAny));
// Ensure that we resolve the acquire callback, thus finishing the acquire
// step.
@@ -946,12 +947,12 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
.GetDisplayLockDocumentState()
.DisplayLockBlockingAllActivationCount(),
0);
- EXPECT_FALSE(
- host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
- EXPECT_FALSE(container->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
- EXPECT_FALSE(slotted->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *host, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *container, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *slotted, DisplayLockActivationReason::kAny));
UpdateAllLifecyclePhasesForTest();
@@ -961,20 +962,21 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
.GetDisplayLockDocumentState()
.DisplayLockBlockingAllActivationCount(),
0);
- EXPECT_FALSE(
- host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
- EXPECT_FALSE(container->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
- EXPECT_FALSE(slotted->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *host, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *container, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *slotted, DisplayLockActivationReason::kAny));
SetHtmlInnerHTML(R"HTML(
<body>
<div id="nonviewport" style="content-visibility: hidden-matchable">
+ <div id="nonviewport-child"></div>
</div>
</body>
)HTML");
- auto* non_viewport = GetDocument().getElementById("nonviewport");
+ auto* non_viewport = GetDocument().getElementById("nonviewport-child");
EXPECT_EQ(
GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
@@ -983,12 +985,12 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
.DisplayLockBlockingAllActivationCount(),
0);
- EXPECT_FALSE(non_viewport->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kAny));
- EXPECT_FALSE(non_viewport->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kFindInPage));
- EXPECT_TRUE(non_viewport->DisplayLockPreventsActivation(
- DisplayLockActivationReason::kUserFocus));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *non_viewport, DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *non_viewport, DisplayLockActivationReason::kFindInPage));
+ ASSERT_TRUE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *non_viewport, DisplayLockActivationReason::kUserFocus));
}
TEST_F(DisplayLockContextTest,
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc
index 9aa3952d054..54eb5ac5601 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc
@@ -222,8 +222,17 @@ DisplayLockDocumentState::ScopedForceActivatableDisplayLocks::
ScopedForceActivatableDisplayLocks(DisplayLockDocumentState* state)
: state_(state) {
if (++state_->activatable_display_locks_forced_ == 1) {
- for (auto context : state_->display_lock_contexts_)
- context->DidForceActivatableDisplayLocks();
+ for (auto context : state_->display_lock_contexts_) {
+ if (context->HasElement()) {
+ context->DidForceActivatableDisplayLocks();
+ } else {
+ NOTREACHED()
+ << "The DisplayLockContext's element has been garbage collected or"
+ << " otherwise deleted, but the DisplayLockContext is still alive!"
+ << " This shouldn't happen and could cause a crash. See"
+ << " crbug.com/1230206";
+ }
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index e23ce229976..47bacf0393e 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -174,6 +174,9 @@ DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return;
+ if (!node_)
+ return;
+
auto* owner_node = GetFrameOwnerNode(node);
if (owner_node)
parent_frame_impl_ = MakeGarbageCollected<Impl>(owner_node, true);
@@ -216,6 +219,8 @@ DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
}
void DisplayLockUtilities::ScopedForcedUpdate::Impl::Destroy() {
+ if (!node_)
+ return;
if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
node_->GetDocument().GetDisplayLockDocumentState().EndNodeForcedScope(this);
if (parent_frame_impl_)
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
index 45aeb57b9d2..31cafc43f3f 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
#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/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -21,23 +22,21 @@ class CORE_EXPORT DisplayLockUtilities {
// This class forces updates on display locks from the given node up the
// ancestor chain until the local frame root.
class CORE_EXPORT ScopedForcedUpdate {
- DISALLOW_COPY_AND_ASSIGN(ScopedForcedUpdate);
STACK_ALLOCATED();
public:
ScopedForcedUpdate(ScopedForcedUpdate&& other) : impl_(other.impl_) {
other.impl_ = nullptr;
}
- ~ScopedForcedUpdate() {
- if (impl_)
- impl_->Destroy();
- }
-
ScopedForcedUpdate& operator=(ScopedForcedUpdate&& other) {
impl_ = other.impl_;
other.impl_ = nullptr;
return *this;
}
+ ~ScopedForcedUpdate() {
+ if (impl_)
+ impl_->Destroy();
+ }
private:
// It is important not to create multiple ScopedChainForcedUpdate scopes.
@@ -52,6 +51,8 @@ class CORE_EXPORT DisplayLockUtilities {
friend void Document::EnsurePaintLocationDataValidForNode(
const Node* node,
DocumentUpdateReason reason);
+ friend VisibleSelection
+ FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated() const;
friend class DisplayLockContext;
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition.cc b/chromium/third_party/blink/renderer/core/document_transition/document_transition.cc
index 7ea173680cb..55ab927a951 100644
--- a/chromium/third_party/blink/renderer/core/document_transition/document_transition.cc
+++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition.cc
@@ -4,21 +4,33 @@
#include "third_party/blink/renderer/core/document_transition/document_transition.h"
+#include "base/trace_event/trace_event.h"
+#include "cc/document_transition/document_transition_request.h"
+#include "cc/trees/paint_holding_reason.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document_transition_prepare_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document_transition_start_options.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.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/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_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/paint_layer.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.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/wtf_string.h"
namespace blink {
namespace {
+const char kAbortedFromPrepare[] = "Aborted due to prepare() call";
+const char kAbortedFromSignal[] = "Aborted due to abortSignal";
+
DocumentTransition::Request::Effect ParseEffect(const String& input) {
using MapType = HashMap<String, DocumentTransition::Request::Effect>;
DEFINE_STATIC_LOCAL(
@@ -65,6 +77,7 @@ void DocumentTransition::Trace(Visitor* visitor) const {
visitor->Trace(prepare_promise_resolver_);
visitor->Trace(start_promise_resolver_);
visitor->Trace(active_shared_elements_);
+ visitor->Trace(signal_);
ScriptWrappable::Trace(visitor);
ActiveScriptWrappable::Trace(visitor);
@@ -81,6 +94,8 @@ void DocumentTransition::ContextDestroyed() {
start_promise_resolver_ = nullptr;
}
active_shared_elements_.clear();
+ signal_ = nullptr;
+ StopDeferringCommits();
}
bool DocumentTransition::HasPendingActivity() const {
@@ -95,12 +110,7 @@ ScriptPromise DocumentTransition::prepare(
ExceptionState& exception_state) {
// Reject any previous prepare promises.
if (state_ == State::kPreparing || state_ == State::kPrepared) {
- if (prepare_promise_resolver_) {
- prepare_promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kAbortError, "Aborted due to prepare() call"));
- prepare_promise_resolver_ = nullptr;
- }
- state_ = State::kIdle;
+ CancelPendingTransition(kAbortedFromPrepare);
}
// Get the sequence id before any early outs so we will correctly process
@@ -123,6 +133,19 @@ ScriptPromise DocumentTransition::prepare(
return ScriptPromise();
}
+ if (options->hasAbortSignal()) {
+ if (options->abortSignal()->aborted()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
+ kAbortedFromSignal);
+ return ScriptPromise();
+ }
+
+ signal_ = options->abortSignal();
+ signal_->AddAlgorithm(WTF::Bind(&DocumentTransition::Abort,
+ WrapWeakPersistent(this),
+ WrapWeakPersistent(signal_.Get())));
+ }
+
// We're going to be creating a new transition, parse the options.
auto effect = ParseRootTransition(options);
if (options->hasSharedElements())
@@ -143,6 +166,15 @@ ScriptPromise DocumentTransition::prepare(
return prepare_promise_resolver_->Promise();
}
+void DocumentTransition::Abort(AbortSignal* signal) {
+ // There is no RemoveAlgorithm() method on AbortSignal so compare the signal
+ // bound to this callback to the one last passed to start().
+ if (signal_ != signal)
+ return;
+
+ CancelPendingTransition(kAbortedFromSignal);
+}
+
ScriptPromise DocumentTransition::start(
ScriptState* script_state,
const DocumentTransitionStartOptions* options,
@@ -154,6 +186,8 @@ ScriptPromise DocumentTransition::start(
return ScriptPromise();
}
+ signal_ = nullptr;
+ StopDeferringCommits();
if (options->hasSharedElements())
SetActiveSharedElements(options->sharedElements());
@@ -207,6 +241,9 @@ void DocumentTransition::NotifyPrepareFinished(uint32_t sequence_id) {
DCHECK(state_ == State::kPreparing);
DCHECK(prepare_promise_resolver_);
+ // Defer commits before resolving the promise to ensure any updates made in
+ // the callback are deferred.
+ StartDeferringCommits();
prepare_promise_resolver_->Resolve();
prepare_promise_resolver_ = nullptr;
state_ = State::kPrepared;
@@ -260,13 +297,23 @@ void DocumentTransition::VerifySharedElements() {
auto* object = active_element->GetLayoutObject();
// TODO(vmpstr): Should this work for replaced elements as well?
- if (object && object->ShouldApplyPaintContainment())
- continue;
+ if (object) {
+ if (object->ShouldApplyPaintContainment())
+ continue;
+
+ auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+ mojom::ConsoleMessageSource::kRendering,
+ mojom::ConsoleMessageLevel::kError,
+ "Dropping element from transition. Shared element must have "
+ "containt:paint");
+ console_message->SetNodes(document_->GetFrame(),
+ {DOMNodeIds::IdForNode(active_element)});
+ document_->AddConsoleMessage(console_message);
+ }
// Clear the shared element. Note that we don't remove the element from the
// vector, since we need to preserve the order of the elements and we
// support nulls as a valid active element.
- // TODO(vmpstr): We should issue a console warning here.
// Invalidate the element since we should no longer be compositing it.
auto* box = active_element->GetLayoutBox();
@@ -309,4 +356,54 @@ void DocumentTransition::InvalidateActiveElements() {
}
}
+void DocumentTransition::StartDeferringCommits() {
+ DCHECK(!deferring_commits_);
+
+ if (!document_->GetPage() || !document_->View())
+ return;
+
+ // Don't do paint holding if it could already be in progress for first
+ // contentful paint.
+ if (document_->View()->WillDoPaintHoldingForFCP())
+ return;
+
+ // Based on the viz side timeout to hold snapshots for 5 seconds.
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+ "blink", "DocumentTransition::DeferringCommits", this);
+ constexpr base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(4);
+ deferring_commits_ =
+ document_->GetPage()->GetChromeClient().StartDeferringCommits(
+ *document_->GetFrame(), kTimeout,
+ cc::PaintHoldingReason::kDocumentTransition);
+}
+
+void DocumentTransition::StopDeferringCommits() {
+ if (!deferring_commits_)
+ return;
+
+ TRACE_EVENT_NESTABLE_ASYNC_END0("blink",
+ "DocumentTransition::DeferringCommits", this);
+ deferring_commits_ = false;
+ if (!document_->GetPage())
+ return;
+
+ document_->GetPage()->GetChromeClient().StopDeferringCommits(
+ *document_->GetFrame(),
+ cc::PaintHoldingCommitTrigger::kDocumentTransition);
+}
+
+void DocumentTransition::CancelPendingTransition(const char* abort_message) {
+ DCHECK(state_ == State::kPreparing || state_ == State::kPrepared)
+ << "Can not cancel transition at state : " << static_cast<int>(state_);
+
+ if (prepare_promise_resolver_) {
+ prepare_promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kAbortError, abort_message));
+ prepare_promise_resolver_ = nullptr;
+ }
+ StopDeferringCommits();
+ state_ = State::kIdle;
+ signal_ = nullptr;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition.h b/chromium/third_party/blink/renderer/core/document_transition/document_transition.h
index e40ee37b354..0f1a7e6d91a 100644
--- a/chromium/third_party/blink/renderer/core/document_transition/document_transition.h
+++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition.h
@@ -5,21 +5,29 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOCUMENT_TRANSITION_DOCUMENT_TRANSITION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOCUMENT_TRANSITION_DOCUMENT_TRANSITION_H_
-#include "cc/document_transition/document_transition_request.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_resolver.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/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/graphics/document_transition_shared_element_id.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace cc {
+class DocumentTransitionRequest;
+}
namespace blink {
+class AbortSignal;
class Document;
class DocumentTransitionPrepareOptions;
class DocumentTransitionStartOptions;
+class Element;
+class ExceptionState;
+class ScriptPromise;
+class ScriptPromiseResolver;
class ScriptState;
class CORE_EXPORT DocumentTransition
@@ -80,12 +88,24 @@ class CORE_EXPORT DocumentTransition
void SetActiveSharedElements(HeapVector<Member<Element>> elements);
void InvalidateActiveElements();
+ // Used to defer visual updates between transition prepare finishing and
+ // transition start to allow the page to set up the final scene
+ // asynchronously.
+ void StartDeferringCommits();
+ void StopDeferringCommits();
+
+ // Allow canceling a transition until it reaches start().
+ void CancelPendingTransition(const char* abort_message);
+
+ void Abort(AbortSignal* signal);
+
Member<Document> document_;
State state_ = State::kIdle;
Member<ScriptPromiseResolver> prepare_promise_resolver_;
Member<ScriptPromiseResolver> start_promise_resolver_;
+ Member<AbortSignal> signal_;
// `active_shared_elements_` represents elements that are identified as shared
// during the current step of the transition. Specifically, it represents
@@ -111,6 +131,8 @@ class CORE_EXPORT DocumentTransition
// The document tag identifies the document to which this transition belongs.
// It's unique among other local documents.
uint32_t document_tag_ = 0u;
+
+ bool deferring_commits_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition_origin_trial_test.cc b/chromium/third_party/blink/renderer/core/document_transition/document_transition_origin_trial_test.cc
index d3bded033f2..77e5c1b2d15 100644
--- a/chromium/third_party/blink/renderer/core/document_transition/document_transition_origin_trial_test.cc
+++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition_origin_trial_test.cc
@@ -4,12 +4,11 @@
#include <vector>
#include "base/bind.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
-#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -26,12 +25,6 @@
namespace blink {
namespace {
-constexpr char 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,
-};
-
// Generated by:
// tools/origin_trials/generate_token.py --version 3 --expire-days 3650 \
// https://documenttransition.test DocumentTransition
@@ -52,24 +45,8 @@ constexpr char kDocumentTransitionToken[] =
"YW5zaXRpb24udGVzdDo0NDMiLCAiZmVhdHVyZSI6ICJEb2N1bWVudFRyYW5zaXRpb2"
"4iLCAiZXhwaXJ5IjogMTkzNTc2OTMzMX0=";
-class ScopedOriginTrialPolicy : public OriginTrialPolicy {
- public:
- ScopedOriginTrialPolicy() {
- TrialTokenValidator::SetOriginTrialPolicyGetter(WTF::BindRepeating(
- [](OriginTrialPolicy* self) { return self; }, base::Unretained(this)));
- }
- ~ScopedOriginTrialPolicy() override {
- TrialTokenValidator::ResetOriginTrialPolicyGetter();
- }
- bool IsOriginTrialsSupported() const override { return true; }
- std::vector<base::StringPiece> GetPublicKeys() const override {
- return {{kOriginTrialPublicKey, base::size(kOriginTrialPublicKey)}};
- }
- bool IsOriginSecure(const GURL& url) const override { return true; }
-};
-
::testing::AssertionResult CheckTokenControlsFeature(const char* trial_token) {
- ScopedOriginTrialPolicy using_test_keys;
+ blink::ScopedTestOriginTrialPolicy using_test_keys;
DummyPageHolder page_holder;
Document& document = page_holder.GetDocument();
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition_prepare_options.idl b/chromium/third_party/blink/renderer/core/document_transition/document_transition_prepare_options.idl
index cb52fd68c66..71cba286b29 100644
--- a/chromium/third_party/blink/renderer/core/document_transition/document_transition_prepare_options.idl
+++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition_prepare_options.idl
@@ -20,4 +20,5 @@ enum RootTransitionType {
dictionary DocumentTransitionPrepareOptions {
RootTransitionType rootTransition;
sequence<Element?> sharedElements;
+ AbortSignal abortSignal;
};
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition_supplement.cc b/chromium/third_party/blink/renderer/core/document_transition/document_transition_supplement.cc
index 7e964eea8c8..d7349c6b06e 100644
--- a/chromium/third_party/blink/renderer/core/document_transition/document_transition_supplement.cc
+++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition_supplement.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h"
+#include "cc/document_transition/document_transition_request.h"
#include "third_party/blink/renderer/core/document_transition/document_transition.h"
#include "third_party/blink/renderer/core/dom/document.h"
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc b/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc
index 661d03845f0..541ccb7b77f 100644
--- a/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc
+++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/document_transition/document_transition.h"
#include "base/test/scoped_feature_list.h"
+#include "cc/document_transition/document_transition_request.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -12,10 +13,12 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_document_transition_start_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_root_transition_type.h"
#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_state.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
#include "third_party/blink/renderer/platform/testing/find_cc_layer.h"
#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
@@ -508,11 +511,17 @@ TEST_P(DocumentTransitionTest, StartPromiseIsResolved) {
transition->prepare(script_state, &prepare_options, exception_state));
EXPECT_EQ(GetState(transition), State::kPreparing);
+ // Visual updates are allows during prepare phase.
+ EXPECT_FALSE(LayerTreeHost()->IsDeferringCommits());
+
UpdateAllLifecyclePhasesAndFinishDirectives();
prepare_tester.WaitUntilSettled();
EXPECT_TRUE(prepare_tester.IsFulfilled());
EXPECT_EQ(GetState(transition), State::kPrepared);
+ // Visual updates are stalled between prepared and start.
+ EXPECT_TRUE(LayerTreeHost()->IsDeferringCommits());
+
DocumentTransitionStartOptions start_options;
ScriptPromiseTester start_tester(
script_state,
@@ -521,9 +530,35 @@ TEST_P(DocumentTransitionTest, StartPromiseIsResolved) {
EXPECT_EQ(GetState(transition), State::kStarted);
UpdateAllLifecyclePhasesAndFinishDirectives();
+ // Visual updates are restored on start.
+ EXPECT_FALSE(LayerTreeHost()->IsDeferringCommits());
+
start_tester.WaitUntilSettled();
EXPECT_TRUE(start_tester.IsFulfilled());
EXPECT_EQ(GetState(transition), State::kIdle);
}
+TEST_P(DocumentTransitionTest, AbortSignal) {
+ auto* transition =
+ DocumentTransitionSupplement::documentTransition(GetDocument());
+
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ ExceptionState& exception_state = v8_scope.GetExceptionState();
+
+ auto* abort_signal =
+ MakeGarbageCollected<AbortSignal>(v8_scope.GetExecutionContext());
+ DocumentTransitionPrepareOptions prepare_options;
+ prepare_options.setAbortSignal(abort_signal);
+ ScriptPromiseTester prepare_tester(
+ script_state,
+ transition->prepare(script_state, &prepare_options, exception_state));
+ EXPECT_EQ(GetState(transition), State::kPreparing);
+
+ abort_signal->SignalAbort();
+ prepare_tester.WaitUntilSettled();
+ EXPECT_TRUE(prepare_tester.IsRejected());
+ EXPECT_EQ(GetState(transition), State::kIdle);
+}
+
} // namespace blink
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 97968689a8b..1cb50c28080 100644
--- a/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
@@ -11,6 +11,7 @@
#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/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -22,6 +23,14 @@ AbortSignal::AbortSignal(ExecutionContext* execution_context)
: execution_context_(execution_context) {}
AbortSignal::~AbortSignal() = default;
+// static
+AbortSignal* AbortSignal::abort(ScriptState* script_state) {
+ AbortSignal* signal =
+ MakeGarbageCollected<AbortSignal>(ExecutionContext::From(script_state));
+ signal->aborted_flag_ = true;
+ return signal;
+}
+
const AtomicString& AbortSignal::InterfaceName() const {
return event_target_names::kAbortSignal;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/abort_signal.h b/chromium/third_party/blink/renderer/core/dom/abort_signal.h
index 22efc1ede00..a9c77a34685 100644
--- a/chromium/third_party/blink/renderer/core/dom/abort_signal.h
+++ b/chromium/third_party/blink/renderer/core/dom/abort_signal.h
@@ -15,6 +15,7 @@
namespace blink {
class ExecutionContext;
+class ScriptState;
// Implementation of https://dom.spec.whatwg.org/#interface-AbortSignal
class CORE_EXPORT AbortSignal : public EventTargetWithInlineData {
@@ -25,6 +26,7 @@ class CORE_EXPORT AbortSignal : public EventTargetWithInlineData {
~AbortSignal() override;
// abort_signal.idl
+ static AbortSignal* abort(ScriptState*);
bool aborted() const { return aborted_flag_; }
DEFINE_ATTRIBUTE_EVENT_LISTENER(abort, kAbort)
diff --git a/chromium/third_party/blink/renderer/core/dom/abort_signal.idl b/chromium/third_party/blink/renderer/core/dom/abort_signal.idl
index 41836a8ade8..d2675b6d1d4 100644
--- a/chromium/third_party/blink/renderer/core/dom/abort_signal.idl
+++ b/chromium/third_party/blink/renderer/core/dom/abort_signal.idl
@@ -7,6 +7,12 @@
[
Exposed=(Window,Worker)
] interface AbortSignal : EventTarget {
+ [
+ CallWith=ScriptState,
+ Measure,
+ NewObject
+ ] static AbortSignal abort();
+
readonly attribute boolean aborted;
attribute EventHandler onabort;
diff --git a/chromium/third_party/blink/renderer/core/dom/abstract_range.cc b/chromium/third_party/blink/renderer/core/dom/abstract_range.cc
index e7111b875b6..3cda6b111e0 100644
--- a/chromium/third_party/blink/renderer/core/dom/abstract_range.cc
+++ b/chromium/third_party/blink/renderer/core/dom/abstract_range.cc
@@ -4,9 +4,39 @@
#include "third_party/blink/renderer/core/dom/abstract_range.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/node.h"
+
namespace blink {
AbstractRange::AbstractRange() = default;
AbstractRange::~AbstractRange() = default;
+bool AbstractRange::HasDifferentRootContainer(Node* start_root_container,
+ Node* end_root_container) {
+ return start_root_container->TreeRoot() != end_root_container->TreeRoot();
+}
+
+unsigned AbstractRange::LengthOfContents(const Node* node) {
+ // This switch statement must be consistent with that of
+ // Range::processContentsBetweenOffsets.
+ switch (node->getNodeType()) {
+ case Node::kTextNode:
+ case Node::kCdataSectionNode:
+ case Node::kCommentNode:
+ case Node::kProcessingInstructionNode:
+ return To<CharacterData>(node)->length();
+ case Node::kElementNode:
+ case Node::kDocumentNode:
+ case Node::kDocumentFragmentNode:
+ return To<ContainerNode>(node)->CountChildren();
+ case Node::kAttributeNode:
+ case Node::kDocumentTypeNode:
+ return 0;
+ }
+ NOTREACHED();
+ return 0;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/abstract_range.h b/chromium/third_party/blink/renderer/core/dom/abstract_range.h
index bac6bb9efef..2d731296e51 100644
--- a/chromium/third_party/blink/renderer/core/dom/abstract_range.h
+++ b/chromium/third_party/blink/renderer/core/dom/abstract_range.h
@@ -10,6 +10,7 @@
namespace blink {
+class Document;
class Node;
class CORE_EXPORT AbstractRange : public ScriptWrappable {
@@ -22,6 +23,12 @@ class CORE_EXPORT AbstractRange : public ScriptWrappable {
virtual unsigned endOffset() const = 0;
virtual bool collapsed() const = 0;
+ static bool HasDifferentRootContainer(Node* start_root_container,
+ Node* end_root_container);
+ static unsigned LengthOfContents(const Node*);
+ virtual bool IsStaticRange() const = 0;
+ virtual Document& OwnerDocument() const = 0;
+
protected:
AbstractRange();
~AbstractRange() override;
diff --git a/chromium/third_party/blink/renderer/core/dom/build.gni b/chromium/third_party/blink/renderer/core/dom/build.gni
index eaa501d85e5..4cb1e0ca4e4 100644
--- a/chromium/third_party/blink/renderer/core/dom/build.gni
+++ b/chromium/third_party/blink/renderer/core/dom/build.gni
@@ -311,6 +311,7 @@ blink_core_tests_dom = [
"mutation_observer_test.cc",
"names_map_test.cc",
"node_test.cc",
+ "node_traversal_test.cc",
"nth_index_cache_test.cc",
"range_test.cc",
"scripted_animation_controller_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/dom/child_node.h b/chromium/third_party/blink/renderer/core/dom/child_node.h
index 0d6f8385495..b8460e1e4ee 100644
--- a/chromium/third_party/blink/renderer/core/dom/child_node.h
+++ b/chromium/third_party/blink/renderer/core/dom/child_node.h
@@ -16,33 +16,21 @@ class ChildNode {
public:
static void before(
Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return node.Before(nodes, exception_state);
}
static void after(
Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return node.After(nodes, exception_state);
}
static void replaceWith(
Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return node.ReplaceWith(nodes, exception_state);
}
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 ba6cc662704..fc93700ec64 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc
@@ -55,6 +55,7 @@
#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/core/layout/line/root_inline_box.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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"
@@ -485,7 +486,9 @@ bool ContainerNode::CheckParserAcceptChild(const Node& new_child) const {
void ContainerNode::ParserInsertBefore(Node* new_child, Node& next_child) {
DCHECK(new_child);
- DCHECK_EQ(next_child.parentNode(), this);
+ DCHECK(next_child.parentNode() == this ||
+ (DynamicTo<DocumentFragment>(this) &&
+ DynamicTo<DocumentFragment>(this)->IsTemplateContent()));
DCHECK(!new_child->IsDocumentFragment());
DCHECK(!IsA<HTMLTemplateElement>(this));
@@ -502,6 +505,9 @@ void ContainerNode::ParserInsertBefore(Node* new_child, Node& next_child) {
while (ContainerNode* parent = new_child->parentNode())
parent->ParserRemoveChild(*new_child);
+ // This can happen if foster parenting moves nodes into a template
+ // content document, but next_child is still a "direct" child of the
+ // template.
if (next_child.parentNode() != this)
return;
@@ -668,6 +674,36 @@ void ContainerNode::Trace(Visitor* visitor) const {
Node::Trace(visitor);
}
+static bool ShouldMergeCombinedTextAfterRemoval(const Node& old_child) {
+ DCHECK(!old_child.parentNode()->GetForceReattachLayoutTree());
+
+ auto* const layout_object = old_child.GetLayoutObject();
+ if (!layout_object)
+ return false;
+
+ // Request to merge previous and next |LayoutNGTextCombine| of |child|.
+ // See http:://crbug.com/1227066
+ auto* const previous_sibling = layout_object->PreviousSibling();
+ if (!previous_sibling)
+ return false;
+ auto* const next_sibling = layout_object->NextSibling();
+ if (!next_sibling)
+ return false;
+ if (UNLIKELY(IsA<LayoutNGTextCombine>(previous_sibling)) &&
+ UNLIKELY(IsA<LayoutNGTextCombine>(next_sibling)))
+ return true;
+
+ // Request to merge combined texts in anonymous block.
+ // See http://crbug.com/1233432
+ if (!previous_sibling->IsAnonymousBlock() ||
+ !next_sibling->IsAnonymousBlock())
+ return false;
+
+ return UNLIKELY(
+ IsA<LayoutNGTextCombine>(previous_sibling->SlowLastChild())) &&
+ UNLIKELY(IsA<LayoutNGTextCombine>(next_sibling->SlowFirstChild()));
+}
+
Node* ContainerNode::RemoveChild(Node* old_child,
ExceptionState& exception_state) {
// NotFoundError: Raised if oldChild is not a child of this node.
@@ -713,6 +749,10 @@ Node* ContainerNode::RemoveChild(Node* old_child,
return nullptr;
}
+ if (!GetForceReattachLayoutTree() &&
+ UNLIKELY(ShouldMergeCombinedTextAfterRemoval(*child)))
+ SetForceReattachLayoutTree();
+
{
HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
TreeOrderedMap::RemoveScope tree_remove_scope;
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index 4eebb1d70ca..985683e9928 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -41,7 +41,6 @@
#include "base/auto_reset.h"
#include "base/containers/contains.h"
#include "base/debug/dump_without_crashing.h"
-#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/time/time.h"
#include "cc/input/overscroll_behavior.h"
@@ -66,20 +65,17 @@
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
-#include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h"
#include "third_party/blink/public/mojom/page_state/page_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/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/public/web/web_print_page_description.h"
-#include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#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/source_location.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_element_creation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_interest_cohort.h"
@@ -103,6 +99,7 @@
#include "third_party/blink/renderer/core/css/invalidation/style_invalidator.h"
#include "third_party/blink/renderer/core/css/media_query_list.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
#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_registry.h"
@@ -164,6 +161,7 @@
#include "third_party/blink/renderer/core/editing/editing_utilities.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/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/events/before_unload_event.h"
#include "third_party/blink/renderer/core/events/event_factory.h"
@@ -183,6 +181,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/page_dismissal_scope.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
@@ -312,6 +311,7 @@
#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/fonts/font_matching_metrics.h"
+#include "third_party/blink/renderer/platform/fonts/font_performance.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -743,7 +743,6 @@ Document::Document(const DocumentInit& initializer,
? kAllowDeferredParsing
: kAllowAsynchronousParsing),
node_count_(0),
- logged_field_edit_(false),
// Use the source id from the document initializer if it is available.
// Otherwise, generate a new source id to cover any cases that don't
// receive a valid source id, this for example includes but is not limited
@@ -819,7 +818,7 @@ Document::Document(const DocumentInit& initializer,
// |fetcher_|.
style_engine_ = MakeGarbageCollected<StyleEngine>(*this);
- UpdateForcedColors();
+ UpdateThemeColorCache();
// The parent's parser should be suspended together with all the other
// objects, else this new Document would have a new ExecutionContext which
@@ -1045,7 +1044,6 @@ Element* Document::CreateElementForBinding(const AtomicString& name,
QualifiedName(g_null_atom, name, g_null_atom), this);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AtomicString GetTypeExtension(
Document* document,
const V8UnionElementCreationOptionsOrString* string_or_options) {
@@ -1068,48 +1066,15 @@ AtomicString GetTypeExtension(
NOTREACHED();
return AtomicString();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-AtomicString GetTypeExtension(
- Document* document,
- const StringOrElementCreationOptions& string_or_options) {
- if (string_or_options.IsNull())
- return AtomicString();
-
- if (string_or_options.IsString()) {
- UseCounter::Count(document,
- WebFeature::kDocumentCreateElement2ndArgStringHandling);
- return AtomicString(string_or_options.GetAsString());
- }
-
- if (string_or_options.IsElementCreationOptions()) {
- const ElementCreationOptions& options =
- *string_or_options.GetAsElementCreationOptions();
- if (options.hasIs())
- return AtomicString(options.is());
- }
-
- return AtomicString();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// https://dom.spec.whatwg.org/#dom-document-createelement
Element* Document::CreateElementForBinding(
const AtomicString& local_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionElementCreationOptionsOrString* string_or_options,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrElementCreationOptions& string_or_options,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!string_or_options) {
return CreateElementForBinding(local_name, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (string_or_options.IsNull()) {
- return CreateElementForBinding(local_name, exception_state);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// 1. If localName does not match Name production, throw InvalidCharacterError
if (!IsValidElementName(this, local_name)) {
@@ -1126,22 +1091,13 @@ Element* Document::CreateElementForBinding(
? html_names::xhtmlNamespaceURI
: g_null_atom);
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool create_builtin = string_or_options.IsElementCreationOptions() ||
- string_or_options.IsString();
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
// 3.
const AtomicString& is = GetTypeExtension(this, string_or_options);
// 5. Let element be the result of creating an element given ...
Element* element =
CreateElement(q_name, CreateElementFlags::ByCreateElement(),
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
is
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- create_builtin ? is : g_null_atom
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
);
return element;
@@ -1187,18 +1143,9 @@ Element* Document::createElementNS(const AtomicString& namespace_uri,
Element* Document::createElementNS(
const AtomicString& namespace_uri,
const AtomicString& qualified_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionElementCreationOptionsOrString* string_or_options,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrElementCreationOptions& string_or_options,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(string_or_options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (string_or_options.IsNull())
- return createElementNS(namespace_uri, qualified_name, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// 1. Validate and extract
QualifiedName q_name(
@@ -1206,11 +1153,6 @@ Element* Document::createElementNS(
if (q_name == QualifiedName::Null())
return nullptr;
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool create_builtin = string_or_options.IsElementCreationOptions() ||
- string_or_options.IsString();
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
// 2.
const AtomicString& is = GetTypeExtension(this, string_or_options);
@@ -1225,11 +1167,7 @@ Element* Document::createElementNS(
// 3. Let element be the result of creating an element
Element* element =
CreateElement(q_name, CreateElementFlags::ByCreateElement(),
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
is
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- create_builtin ? is : g_null_atom
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
);
return element;
@@ -1593,8 +1531,6 @@ Element* Document::scrollingElement() {
Element* Document::ScrollingElementNoLayout() {
if (RuntimeEnabledFeatures::ScrollTopLeftInteropEnabled()) {
if (InQuirksMode()) {
- DCHECK(!IsActive() || InStyleRecalc() ||
- lifecycle_.GetState() >= DocumentLifecycle::kStyleClean);
HTMLBodyElement* body = FirstBodyElement();
if (body && body->GetLayoutObject() &&
body->GetLayoutObject()->IsScrollContainer())
@@ -1894,9 +1830,24 @@ TreeWalker* Document::createTreeWalker(Node* root,
}
bool Document::NeedsLayoutTreeUpdate() const {
+ return NeedsLayoutTreeUpdateForThisDocument() ||
+ ParentFrameNeedsLayoutTreeUpdate();
+}
+
+bool Document::NeedsFullLayoutTreeUpdate() const {
+ return NeedsFullLayoutTreeUpdateForThisDocument() ||
+ ParentFrameNeedsLayoutTreeUpdate();
+}
+
+bool Document::ParentFrameNeedsLayoutTreeUpdate() const {
+ HTMLFrameOwnerElement* owner = LocalOwner();
+ return owner && owner->GetDocument().NeedsLayoutTreeUpdate();
+}
+
+bool Document::NeedsLayoutTreeUpdateForThisDocument() const {
if (!IsActive() || !View())
return false;
- if (NeedsFullLayoutTreeUpdate())
+ if (NeedsFullLayoutTreeUpdateForThisDocument())
return true;
if (style_engine_->NeedsStyleRecalc())
return true;
@@ -1916,7 +1867,7 @@ bool Document::NeedsLayoutTreeUpdate() const {
return false;
}
-bool Document::NeedsFullLayoutTreeUpdate() const {
+bool Document::NeedsFullLayoutTreeUpdateForThisDocument() const {
// This method returns true if we cannot decide which specific elements need
// to have its style or layout tree updated on the next lifecycle update. If
// this method returns false, we typically use that to walk up the ancestor
@@ -2048,10 +1999,21 @@ void Document::UpdateStyleAndLayoutTree() {
HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
ScriptForbiddenScope forbid_script;
- if (HTMLFrameOwnerElement* owner = LocalOwner())
- owner->GetDocument().UpdateStyleAndLayoutTree();
+ if (HTMLFrameOwnerElement* owner = LocalOwner()) {
+ if (GetStyleEngine().HasViewportDependentMediaQueries()) {
+ // TODO(andruud): Provide a better reason.
+ owner->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kUnknown);
+ } else {
+ owner->GetDocument().UpdateStyleAndLayoutTree();
+ }
+ }
UpdateStyleAndLayoutTreeForThisDocument();
+
+ if (GetStyleEngine().UsesContainerQueries()) {
+ // TODO(crbug.com/1145970): Provide a better reason.
+ UpdateStyleAndLayout(DocumentUpdateReason::kUnknown);
+ }
}
void Document::UpdateStyleAndLayoutTreeForThisDocument() {
@@ -2062,7 +2024,7 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() {
return;
}
-#if DCHECK_IS_ON()
+#if EXPENSIVE_DCHECKS_ARE_ON()
if (HTMLFrameOwnerElement* owner = LocalOwner()) {
DCHECK(!owner->GetDocument()
.GetSlotAssignmentEngine()
@@ -2070,10 +2032,14 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() {
DCHECK(!owner->GetDocument().NeedsLayoutTreeUpdate());
AssertLayoutTreeUpdated(owner->GetDocument());
}
-#endif
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
+
+ SCOPED_UMA_AND_UKM_TIMER(View()->EnsureUkmAggregator(),
+ LocalFrameUkmAggregator::kStyle);
+ FontPerformance::StyleScope font_performance_scope;
// RecalcSlotAssignments should be done before checking
- // NeedsLayoutTreeUpdate().
+ // NeedsLayoutTreeUpdateForThisDocument().
GetSlotAssignmentEngine().RecalcSlotAssignments();
// We can call FlatTreeTraversal::AssertFlatTreeNodeDataUpdated just after
@@ -2083,20 +2049,26 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() {
SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(*this);
- if (!NeedsLayoutTreeUpdate()) {
+ if (!NeedsLayoutTreeUpdateForThisDocument()) {
if (Lifecycle().GetState() < DocumentLifecycle::kStyleClean) {
- // needsLayoutTreeUpdate may change to false without any actual layout
- // tree update. For example, needsAnimationTimingUpdate may change to
- // false when time elapses. Advance lifecycle to StyleClean because style
- // is actually clean now.
+ // NeedsLayoutTreeUpdateForThisDocument may change to false without any
+ // actual layout tree update. For example, NeedsAnimationTimingUpdate
+ // may change to false when time elapses. Advance lifecycle to
+ // StyleClean because style is actually clean now.
Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean);
}
+ // If we insert <object> elements into display:none subtrees, we might not
+ // need a layout tree update, but need to make sure they are not blocking
+ // the load event.
+ UnblockLoadEventAfterLayoutTreeUpdate();
return;
}
- if (InStyleRecalc())
+ if (InStyleRecalc()) {
+ NOTREACHED() << "We should not re-enter style recalc for the same document";
return;
+ }
#if DCHECK_IS_ON()
int assigned_nodes_in_slot_count = 0;
@@ -2151,6 +2123,8 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() {
// Make sure that document.fonts.ready fires, if appropriate.
FontFaceSetDocument::DidLayout(*this);
+ UnblockLoadEventAfterLayoutTreeUpdate();
+
TRACE_EVENT_END1("blink,devtools.timeline", "UpdateLayoutTree",
"elementCount", element_count);
@@ -2166,10 +2140,26 @@ void Document::InvalidateStyleAndLayoutForFontUpdates() {
}
void Document::UpdateStyle() {
+ UpdateStyleInternal();
+ DCHECK_EQ(lifecycle_.GetState(), DocumentLifecycle::kStyleClean);
+
+ if (RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled()) {
+ GetDocumentAnimations().ApplyPendingElementUpdates();
+ if (lifecycle_.GetState() < DocumentLifecycle::kStyleClean) {
+ DocumentAnimations::AllowAnimationUpdatesScope allow_updates(
+ GetDocumentAnimations(), false);
+ UpdateStyleInternal();
+ }
+ }
+}
+
+void Document::UpdateStyleInternal() {
DCHECK(!View()->ShouldThrottleRendering());
TRACE_EVENT_BEGIN0("blink,blink_style", "Document::updateStyle");
RUNTIME_CALL_TIMER_SCOPE(V8PerIsolateData::MainThreadIsolate(),
RuntimeCallStats::CounterId::kUpdateStyle);
+ DocumentAnimations::AllowAnimationUpdatesScope allow_updates(
+ GetDocumentAnimations(), true);
unsigned initial_element_count = GetStyleEngine().StyleForElementCount();
@@ -2685,6 +2675,7 @@ void Document::Initialize() {
DCHECK_EQ(lifecycle_.GetState(), DocumentLifecycle::kInactive);
DCHECK(!ax_object_cache_ || this != &AXObjectCacheOwner());
+ UpdateForcedColors();
layout_view_ = new LayoutView(this);
SetLayoutObject(layout_view_);
@@ -2770,8 +2761,8 @@ void Document::Shutdown() {
markers_->PrepareForDestruction();
- if (GetFrame()->GetTextFragmentSelectorGenerator())
- GetFrame()->GetTextFragmentSelectorGenerator()->ClearSelection();
+ if (TextFragmentHandler* handler = GetFrame()->GetTextFragmentHandler())
+ handler->DidDetachDocumentOrFrame();
GetPage()->DocumentDetached(this);
@@ -3096,7 +3087,7 @@ void Document::open(LocalDOMWindow* entered_window,
new_url.SetFragmentIdentifier(String());
SetURL(new_url);
if (Loader())
- Loader()->UpdateUrlForDocumentOpen(new_url);
+ Loader()->DidOpenDocumentInputStream(new_url);
if (dom_window_ != entered_window) {
// We inherit the sandbox flags of the entered document, so mask on
@@ -3345,21 +3336,37 @@ Element* Document::ViewportDefiningElement() const {
// If a BODY element sets non-visible overflow, it is to be propagated to the
// viewport, as long as the following conditions are all met:
// (1) The root element is HTML.
- // (2) It is the primary BODY element (we only assert for this, expecting
- // callers to behave).
+ // (2) It is the primary BODY element.
// (3) The root element has visible overflow.
+ // (4) The root or BODY elements do not apply any containment.
// Otherwise it's the root element's properties that are to be propagated.
+
+ // This method is called in the middle of a lifecycle update, for instance
+ // from a LayoutObject which is created but not yet inserted into the box
+ // tree, which is why we have to do the decision based on the ComputedStyle
+ // and not the LayoutObject style and the containment checks below also.
+
Element* root_element = documentElement();
- HTMLBodyElement* body_element = FirstBodyElement();
if (!root_element)
return nullptr;
const ComputedStyle* root_style = root_element->GetComputedStyle();
if (!root_style || root_style->IsEnsuredInDisplayNone())
return nullptr;
- if (body_element && root_style->IsOverflowVisibleAlongBothAxes() &&
- IsA<HTMLHtmlElement>(root_element))
- return body_element;
- return root_element;
+ if (!root_style->IsOverflowVisibleAlongBothAxes())
+ return root_element;
+ HTMLBodyElement* body_element = FirstBodyElement();
+ if (!body_element)
+ return root_element;
+ const ComputedStyle* body_style = body_element->GetComputedStyle();
+ if (!body_style || body_style->IsEnsuredInDisplayNone())
+ return root_element;
+ if (RuntimeEnabledFeatures::CSSContainedBodyPropagationEnabled()) {
+ if (root_style->ShouldApplyAnyContainment(*root_element) ||
+ body_style->ShouldApplyAnyContainment(*body_element)) {
+ return root_element;
+ }
+ }
+ return body_element;
}
Document* Document::open(v8::Isolate* isolate,
@@ -3477,7 +3484,8 @@ void Document::ImplicitClose() {
fetcher_->ScheduleWarnUnusedPreloads();
- UpdateStyleAndLayout(DocumentUpdateReason::kUnknown);
+ if (GetStyleEngine().HaveRenderBlockingStylesheetsLoaded())
+ UpdateStyleAndLayout(DocumentUpdateReason::kUnknown);
load_event_progress_ = kLoadEventCompleted;
@@ -3626,6 +3634,9 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient* chrome_client,
if (ProcessingBeforeUnload())
return false;
+ if (auto* mf_checker = View()->GetMobileFriendlinessChecker())
+ mf_checker->EvaluateNow();
+
PageDismissalScope in_page_dismissal;
auto& before_unload_event = *MakeGarbageCollected<BeforeUnloadEvent>();
before_unload_event.initEvent(event_type_names::kBeforeunload, false, true);
@@ -3785,8 +3796,6 @@ void Document::DispatchUnloadEvents(
return;
GetFrame()->Loader().SaveScrollAnchor();
- if (auto* mf_checker = View()->GetMobileFriendlinessChecker())
- mf_checker->NotifyDocumentUnload();
// TODO(crbug.com/1161996): Remove this VLOG once the investigation is done.
VLOG(1) << "Actually dispatching an UnloadEvent: URL = " << Url();
@@ -4582,6 +4591,8 @@ void Document::LayoutViewportWasResized() {
load_event_progress_ == kLoadEventInProgress) {
EnqueueResizeEvent();
EnqueueVisualViewportResizeEvent();
+ if (GetFrame()->IsMainFrame() && !Printing())
+ probe::DidResizeMainFrame(GetFrame());
}
if (!HasViewportUnits())
return;
@@ -5277,17 +5288,6 @@ const OriginAccessEntry& Document::AccessEntryFromURL() {
return *access_entry_from_url_;
}
-void Document::SendDidEditFieldInInsecureContext() {
- if (!GetFrame())
- return;
-
- mojo::Remote<mojom::blink::InsecureInputService> insecure_input_service;
- GetFrame()->GetBrowserInterfaceBroker().GetInterface(
- insecure_input_service.BindNewPipeAndPassReceiver());
-
- insecure_input_service->DidEditFieldInInsecureContext();
-}
-
void Document::RegisterEventFactory(
std::unique_ptr<EventFactoryBase> event_factory) {
DCHECK(!EventFactories().Contains(event_factory.get()));
@@ -5487,6 +5487,12 @@ bool Document::CookiesEnabled() const {
return cookie_jar_->CookiesEnabled();
}
+void Document::SetCookieManager(
+ mojo::PendingRemote<network::mojom::blink::RestrictedCookieManager>
+ cookie_manager) {
+ cookie_jar_->SetCookieManager(std::move(cookie_manager));
+}
+
const AtomicString& Document::referrer() const {
if (Loader())
return Loader()->GetReferrer().referrer;
@@ -6337,7 +6343,6 @@ KURL Document::OpenSearchDescriptionURL() {
return KURL();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8HTMLOrSVGScriptElement* Document::currentScriptForBinding() const {
if (current_script_stack_.IsEmpty())
return nullptr;
@@ -6346,15 +6351,6 @@ V8HTMLOrSVGScriptElement* Document::currentScriptForBinding() const {
return nullptr;
return script_element_base->AsV8HTMLOrSVGScriptElement();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void Document::currentScriptForBinding(
- HTMLScriptElementOrSVGScriptElement& script_element) const {
- if (!current_script_stack_.IsEmpty()) {
- if (ScriptElementBase* script_element_base = current_script_stack_.back())
- script_element_base->SetScriptElementForBinding(script_element);
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Document::PushCurrentScript(ScriptElementBase* new_current_script) {
current_script_stack_.push_back(new_current_script);
@@ -6530,75 +6526,6 @@ void Document::RecordAsyncScriptCount() {
.Record(recorder);
}
-void Document::MaybeExecuteDelayedAsyncScripts() {
- if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) &&
- features::kDelayAsyncScriptExecutionDelayParam.Get() ==
- features::DelayAsyncScriptDelayType::kUseOptimizationGuide) {
- // If the optimization hints aren't available in the first place, then
- // ScriptRunner won't delay async scripts at all, so we don't need to worry
- // about notifying it.
- if (!GetFrame() || !GetFrame()->GetOptimizationGuideHints())
- return;
-
- mojom::blink::DelayAsyncScriptExecutionHintsPtr delay_hint =
- std::move(GetFrame()
- ->GetOptimizationGuideHints()
- ->delay_async_script_execution_hints);
-
- if (!delay_hint)
- return;
-
- mojom::blink::DelayAsyncScriptExecutionDelayType delay_type =
- delay_hint->delay_type;
- switch (delay_type) {
- case mojom::blink::DelayAsyncScriptExecutionDelayType::kFinishedParsing:
- if (!Parsing())
- script_runner_->NotifyDelayedAsyncScriptsMilestoneReached();
- return;
- case mojom::blink::DelayAsyncScriptExecutionDelayType::
- kFirstPaintOrFinishedParsing:
- if (first_paint_recorded_ || !Parsing())
- script_runner_->NotifyDelayedAsyncScriptsMilestoneReached();
- return;
- case mojom::blink::DelayAsyncScriptExecutionDelayType::kUnknown:
- // If the delay type is kUnknown, or the optimization guide hints are
- // unavailable, then ScriptRunner::CanDelayAsyncScripts will always
- // return false, causing no delay. Therefore in this case, we don't
- // need to anything here.
- return;
- }
- }
-
- // Notify the ScriptRunner if the first paint has been recorded and
- // we're delaying async scripts until first paint or finished parsing
- // (whichever comes first).
- if ((first_paint_recorded_ || !Parsing()) &&
- ((base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) &&
- features::kDelayAsyncScriptExecutionDelayParam.Get() ==
- features::DelayAsyncScriptDelayType::
- kFirstPaintOrFinishedParsing) ||
- RuntimeEnabledFeatures::
- DelayAsyncScriptExecutionUntilFirstPaintOrFinishedParsingEnabled())) {
- script_runner_->NotifyDelayedAsyncScriptsMilestoneReached();
- }
-
- // Notify the ScriptRunner if we're finished parsing and we're delaying async
- // scripts until finished parsing occurs.
- if (!Parsing() &&
- (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) ||
- RuntimeEnabledFeatures::
- DelayAsyncScriptExecutionUntilFinishedParsingEnabled() ||
- RuntimeEnabledFeatures::
- DelayAsyncScriptExecutionUntilFirstPaintOrFinishedParsingEnabled())) {
- script_runner_->NotifyDelayedAsyncScriptsMilestoneReached();
- }
-}
-
-void Document::MarkFirstPaint() {
- first_paint_recorded_ = true;
- MaybeExecuteDelayedAsyncScripts();
-}
-
using AllowState = blink::Document::DeclarativeShadowRootAllowState;
AllowState Document::GetDeclarativeShadowRootAllowState() const {
return declarative_shadow_root_allow_state_;
@@ -6616,8 +6543,6 @@ void Document::FinishedParsing() {
SetParsingState(kInDOMContentLoaded);
DocumentParserTiming::From(*this).MarkParserStop();
- MaybeExecuteDelayedAsyncScripts();
-
// FIXME: DOMContentLoaded is dispatched synchronously, but this should be
// dispatched in a queued task, see https://crbug.com/425790
if (document_timing_.DomContentLoadedEventStart().is_null())
@@ -6654,13 +6579,18 @@ void Document::FinishedParsing() {
// the window load event too early. To avoid this we force the styles to be
// up to date before calling FrameLoader::finishedParsing(). See
// https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
- if (!is_initial_empty_document_)
+ if (!is_initial_empty_document_ &&
+ GetStyleEngine().HaveRenderBlockingStylesheetsLoaded()) {
UpdateStyleAndLayoutTree();
+ }
BeginLifecycleUpdatesIfRenderingReady();
frame->Loader().FinishedParsing();
+ if (frame->GetFrameScheduler())
+ frame->GetFrameScheduler()->OnDomContentLoaded();
+
DEVTOOLS_TIMELINE_TRACE_EVENT_INSTANT(
"MarkDOMContent", inspector_mark_load_event::Data, frame);
probe::DomContentLoadedEventFired(frame);
@@ -6781,17 +6711,35 @@ Vector<IconURL> Document::IconURLs(int icon_types_mask) {
return icon_urls;
}
-absl::optional<Color> Document::ThemeColor() const {
+void Document::UpdateThemeColorCache() {
+ meta_theme_color_elements_.clear();
auto* root_element = documentElement();
if (!root_element)
- return absl::nullopt;
+ return;
+
for (HTMLMetaElement& meta_element :
Traversal<HTMLMetaElement>::DescendantsOf(*root_element)) {
+ if (EqualIgnoringASCIICase(meta_element.GetName(), "theme-color"))
+ meta_theme_color_elements_.push_back(meta_element);
+ }
+}
+
+absl::optional<Color> Document::ThemeColor() {
+ // Returns the color of the first meta[name=theme-color] element in
+ // tree order that matches and is valid.
+ // https://html.spec.whatwg.org/multipage/semantics.html#meta-theme-color
+ for (auto& element : meta_theme_color_elements_) {
+ if (!element->Media().IsEmpty()) {
+ auto* media_query = GetMediaQueryMatcher().MatchMedia(
+ element->Media().GetString().StripWhiteSpace());
+ if (!media_query->matches())
+ continue;
+ }
Color color;
- if (EqualIgnoringASCIICase(meta_element.GetName(), "theme-color") &&
- CSSParser::ParseColor(
- color, meta_element.Content().GetString().StripWhiteSpace(), true))
+ if (CSSParser::ParseColor(
+ color, element->Content().GetString().StripWhiteSpace(), true)) {
return color;
+ }
}
return absl::nullopt;
}
@@ -7180,11 +7128,13 @@ void Document::CancelAnimationFrame(int id) {
}
void Document::ServiceScriptedAnimations(
- base::TimeTicks monotonic_animation_start_time) {
- auto start_time = base::TimeTicks::Now();
+ base::TimeTicks monotonic_animation_start_time,
+ bool can_throttle) {
+ base::TimeTicks start_time =
+ can_throttle ? base::TimeTicks() : base::TimeTicks::Now();
scripted_animation_controller_->ServiceScriptedAnimations(
- monotonic_animation_start_time);
- if (GetFrame()) {
+ monotonic_animation_start_time, can_throttle);
+ if (!can_throttle && GetFrame()) {
GetFrame()->GetFrameScheduler()->AddTaskTime(base::TimeTicks::Now() -
start_time);
}
@@ -7791,25 +7741,6 @@ PropertyRegistry& Document::EnsurePropertyRegistry() {
return *property_registry_;
}
-void Document::MaybeQueueSendDidEditFieldInInsecureContext() {
- if (logged_field_edit_ || sensitive_input_edited_task_.IsActive() ||
- execution_context_->IsSecureContext()) {
- // Send a message on the first edit; the browser process doesn't care
- // about the presence of additional edits.
- //
- // The browser process only cares about editing fields on pages where the
- // top-level URL is not secure. Secure contexts must have a top-level URL
- // that is secure, so there is no need to send notifications for editing
- // in secure contexts.
- return;
- }
- logged_field_edit_ = true;
- sensitive_input_edited_task_ = PostCancellableTask(
- *GetTaskRunner(TaskType::kUserInteraction), FROM_HERE,
- WTF::Bind(&Document::SendDidEditFieldInInsecureContext,
- WrapWeakPersistent(this)));
-}
-
DocumentResourceCoordinator* Document::GetResourceCoordinator() {
if (!resource_coordinator_ && GetFrame()) {
resource_coordinator_ = DocumentResourceCoordinator::MaybeCreate(
@@ -7929,6 +7860,7 @@ void Document::Trace(Visitor* visitor) const {
visitor->Trace(font_preload_manager_);
visitor->Trace(find_in_page_active_match_node_);
visitor->Trace(data_);
+ visitor->Trace(meta_theme_color_elements_);
Supplementable<Document>::Trace(visitor);
TreeScope::Trace(visitor);
ContainerNode::Trace(visitor);
@@ -8073,6 +8005,12 @@ void Document::ColorSchemeChanged() {
UpdateForcedColors();
GetStyleEngine().ColorSchemeChanged();
MediaQueryAffectingValueChanged(MediaValueChange::kOther);
+ MediaValues* media_values =
+ MediaValues::CreateDynamicIfFrameExists(GetFrame());
+ if (GetFrame()) {
+ GetFrame()->GetLocalFrameHostRemote().DidUpdatePreferredColorScheme(
+ media_values->GetPreferredColorScheme());
+ }
}
void Document::VisionDeficiencyChanged() {
@@ -8112,6 +8050,11 @@ void Document::CountUse(mojom::WebFeature feature) {
execution_context_->CountUse(feature);
}
+void Document::CountDeprecation(mojom::WebFeature feature) {
+ if (execution_context_)
+ execution_context_->CountDeprecation(feature);
+}
+
void Document::CountProperty(CSSPropertyID property) const {
if (DocumentLoader* loader = Loader()) {
loader->GetUseCounter().Count(
@@ -8177,15 +8120,8 @@ const Node* Document::GetFindInPageActiveMatchNode() const {
return find_in_page_active_match_node_;
}
-void Document::ActivateForPrerendering() {
- DCHECK(RuntimeEnabledFeatures::Prerender2Enabled());
-
- // For subframes, this can be called before the navigation commit, and this
- // document may be the initial empty one with `is_prerendering_` being false.
- if (is_initial_empty_document_) {
- DCHECK(!is_prerendering_);
- return;
- }
+void Document::ActivateForPrerendering(base::TimeTicks activation_start) {
+ DCHECK(features::IsPrerender2Enabled());
// TODO(bokan): Portals will change this assumption since they mean an active
// document can be "adopted" into a portal.
@@ -8193,7 +8129,7 @@ void Document::ActivateForPrerendering() {
is_prerendering_ = false;
if (DocumentLoader* loader = Loader())
- loader->NotifyPrerenderingDocumentActivated();
+ loader->NotifyPrerenderingDocumentActivated(activation_start);
Vector<base::OnceClosure> callbacks;
callbacks.swap(will_dispatch_prerenderingchange_callbacks_);
@@ -8203,14 +8139,19 @@ void Document::ActivateForPrerendering() {
// https://jeremyroman.github.io/alternate-loading-modes/#prerendering-browsing-context-activate
// Step 8.3.4 "Fire an event named prerenderingchange at doc."
- DispatchEvent(*Event::Create(event_type_names::kPrerenderingchange));
+ if (RuntimeEnabledFeatures::Prerender2Enabled(GetExecutionContext())) {
+ DispatchEvent(*Event::Create(event_type_names::kPrerenderingchange));
+ } else {
+ AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "Failed to dispatch 'prerenderingchange' event: Prerender2 feature is "
+ "not enabled on the document."));
+ }
// Step 8.3.5 "For each steps in doc’s post-prerendering activation steps
// list:"
RunPostPrerenderingActivationSteps();
-
- if (LocalFrame* frame = GetFrame())
- frame->DidActivateForPrerendering();
}
void Document::AddWillDispatchPrerenderingchangeCallback(
@@ -8236,6 +8177,20 @@ bool Document::InStyleRecalc() const {
style_engine_->InContainerQueryStyleRecalc();
}
+void Document::DelayLoadEventUntilLayoutTreeUpdate() {
+ if (delay_load_event_until_layout_tree_update_)
+ return;
+ delay_load_event_until_layout_tree_update_ = true;
+ IncrementLoadEventDelayCount();
+}
+
+void Document::UnblockLoadEventAfterLayoutTreeUpdate() {
+ if (delay_load_event_until_layout_tree_update_) {
+ delay_load_event_until_layout_tree_update_ = false;
+ DecrementLoadEventDelayCount();
+ }
+}
+
Document::PaintPreviewScope::PaintPreviewScope(Document& document,
PaintPreviewState state)
: document_(document) {
diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h
index 6355a6e9174..300598a21d2 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.h
+++ b/chromium/third_party/blink/renderer/core/dom/document.h
@@ -39,7 +39,9 @@
#include "base/timer/elapsed_timer.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink-forward.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/public/mojom/federated_learning/floc.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/color_scheme.mojom-blink-forward.h"
@@ -152,8 +154,9 @@ class HTMLElement;
class HTMLFrameOwnerElement;
class HTMLHeadElement;
class HTMLLinkElement;
+class HTMLMetaElement;
class HTMLPopupElement;
-class HTMLScriptElementOrSVGScriptElement;
+class HasMatchedCacheScope;
class HitTestRequest;
class HttpRefreshScheduler;
class IdleRequestOptions;
@@ -196,7 +199,6 @@ class SerializedScriptValue;
class Settings;
class SlotAssignmentEngine;
class SnapCoordinator;
-class StringOrElementCreationOptions;
class StyleEngine;
class StylePropertyMapReadOnly;
class StyleResolver;
@@ -368,31 +370,18 @@ class CORE_EXPORT Document : public ContainerNode,
Element* CreateElementForBinding(const AtomicString& local_name,
ExceptionState& = ASSERT_NO_EXCEPTION);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Element* CreateElementForBinding(
const AtomicString& local_name,
const V8UnionElementCreationOptionsOrString* string_or_options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Element* CreateElementForBinding(const AtomicString& local_name,
- const StringOrElementCreationOptions&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Element* createElementNS(const AtomicString& namespace_uri,
const AtomicString& qualified_name,
ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Element* createElementNS(
const AtomicString& namespace_uri,
const AtomicString& qualified_name,
const V8UnionElementCreationOptionsOrString* string_or_options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Element* createElementNS(const AtomicString& namespace_uri,
- const AtomicString& qualified_name,
- const StringOrElementCreationOptions&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DocumentFragment* createDocumentFragment();
Text* createTextNode(const String& data);
Comment* createComment(const String& data);
@@ -421,6 +410,14 @@ class CORE_EXPORT Document : public ContainerNode,
Element* scrollingElement();
// When calling from C++ code, use this method. scrollingElement() is
// just for the web IDL implementation.
+ //
+ // Style/layout-tree needs to be updated before calling this function,
+ // otherwise the returned element might be outdated. However, accessing
+ // information based on the layout of the previous frame is occasionally
+ // the correct behavior [1], hence it's not invalid to call this function
+ // while style/layout dirty.
+ //
+ // [1] https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles
Element* ScrollingElementNoLayout();
String readyState() const;
@@ -1047,6 +1044,10 @@ class CORE_EXPORT Document : public ContainerNode,
void setCookie(const String&, ExceptionState&);
bool CookiesEnabled() const;
+ void SetCookieManager(
+ mojo::PendingRemote<network::mojom::blink::RestrictedCookieManager>
+ cookie_manager);
+
const AtomicString& referrer() const;
String domain() const;
@@ -1175,11 +1176,7 @@ class CORE_EXPORT Document : public ContainerNode,
ScriptRunner* GetScriptRunner() { return script_runner_.Get(); }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8HTMLOrSVGScriptElement* currentScriptForBinding() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void currentScriptForBinding(HTMLScriptElementOrSVGScriptElement&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void PushCurrentScript(ScriptElementBase*);
void PopCurrentScript(ScriptElementBase*);
@@ -1204,7 +1201,8 @@ class CORE_EXPORT Document : public ContainerNode,
Vector<IconURL> IconURLs(int icon_types_mask);
- absl::optional<Color> ThemeColor() const;
+ void UpdateThemeColorCache();
+ absl::optional<Color> ThemeColor();
// Returns the HTMLLinkElement currently in use for the Web Manifest.
// Returns null if there is no such element.
@@ -1329,15 +1327,24 @@ class CORE_EXPORT Document : public ContainerNode,
void CheckLoadEventSoon();
bool IsDelayingLoadEvent();
void LoadPluginsSoon();
- // This calls checkCompleted() sync and thus can cause JavaScript execution.
+ // This calls CheckCompleted() sync and thus can cause JavaScript execution.
void DecrementLoadEventDelayCountAndCheckLoadEvent();
+ // Objects and embeds depend on "being rendered" for delaying the load event.
+ // This method makes sure we run a layout tree update before unblocking the
+ // load event after such elements have been inserted.
+ //
+ // Spec:
+ //
+ // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element
+ // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-embed-element
+ void DelayLoadEventUntilLayoutTreeUpdate();
const DocumentTiming& GetTiming() const { return document_timing_; }
int RequestAnimationFrame(FrameCallback*);
void CancelAnimationFrame(int id);
- void ServiceScriptedAnimations(
- base::TimeTicks monotonic_animation_start_time);
+ void ServiceScriptedAnimations(base::TimeTicks monotonic_animation_start_time,
+ bool can_throttle = false);
int RequestIdleCallback(IdleTask*, const IdleRequestOptions*);
void CancelIdleCallback(int id);
@@ -1447,6 +1454,10 @@ class CORE_EXPORT Document : public ContainerNode,
NthIndexCache* GetNthIndexCache() const { return nth_index_cache_; }
+ HasMatchedCacheScope* GetHasMatchedCacheScope() const {
+ return has_matched_cache_scope_;
+ }
+
CanvasFontCache* GetCanvasFontCache();
// Used by unit tests so that all parsing will be main thread for
@@ -1485,10 +1496,6 @@ class CORE_EXPORT Document : public ContainerNode,
}
PropertyRegistry& EnsurePropertyRegistry();
- // Used to notify the embedder when the user edits the value of a
- // text field in a non-secure context.
- void MaybeQueueSendDidEditFieldInInsecureContext();
-
// May return nullptr when PerformanceManager instrumentation is disabled.
DocumentResourceCoordinator* GetResourceCoordinator();
@@ -1565,7 +1572,7 @@ class CORE_EXPORT Document : public ContainerNode,
// Deferred compositor commits are disallowed by default, and are only allowed
// for same-origin navigations to an html document fetched with http.
- bool DeferredCompositorCommitIsAllowed() {
+ bool DeferredCompositorCommitIsAllowed() const {
return deferred_compositor_commit_is_allowed_;
}
void SetDeferredCompositorCommitIsAllowed(bool new_value) {
@@ -1579,6 +1586,9 @@ class CORE_EXPORT Document : public ContainerNode,
ComputedAccessibleNode* GetOrCreateComputedAccessibleNode(AXID ax_id);
+ // Return true if any accessibility contexts have been enabled.
+ bool IsAccessibilityEnabled() const { return !ax_contexts_.IsEmpty(); }
+
bool HaveRenderBlockingResourcesLoaded() const;
// Sets a beforeunload handler for documents which are embedding plugins. This
@@ -1601,6 +1611,7 @@ class CORE_EXPORT Document : public ContainerNode,
// Use counter related functions.
void CountUse(mojom::WebFeature feature) final;
+ void CountDeprecation(mojom::WebFeature feature) final;
void CountUse(mojom::WebFeature feature) const;
void CountProperty(CSSPropertyID property_id) const;
void CountAnimatedProperty(CSSPropertyID property_id) const;
@@ -1668,9 +1679,6 @@ class CORE_EXPORT Document : public ContainerNode,
void IncrementAsyncScriptCount() { async_script_count_++; }
void RecordAsyncScriptCount();
- void MarkFirstPaint();
- void MaybeExecuteDelayedAsyncScripts();
-
enum class DeclarativeShadowRootAllowState : uint8_t {
kNotSet,
kAllow,
@@ -1682,7 +1690,7 @@ class CORE_EXPORT Document : public ContainerNode,
void SetFindInPageActiveMatchNode(Node*);
const Node* GetFindInPageActiveMatchNode() const;
- void ActivateForPrerendering();
+ void ActivateForPrerendering(base::TimeTicks activation_start);
void AddWillDispatchPrerenderingchangeCallback(base::OnceClosure);
@@ -1721,6 +1729,7 @@ class CORE_EXPORT Document : public ContainerNode,
friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
friend class IgnoreOpensDuringUnloadCountIncrementer;
friend class NthIndexCache;
+ friend class HasMatchedCacheScope;
friend class CanvasRenderingAPIUkmMetricsTest;
friend class OffscreenCanvasRenderingAPIUkmMetricsTest;
FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest,
@@ -1754,15 +1763,31 @@ class CORE_EXPORT Document : public ContainerNode,
void ScheduleLayoutTreeUpdate();
bool NeedsFullLayoutTreeUpdate() const;
+ bool ParentFrameNeedsLayoutTreeUpdate() const;
+
+ // See UpdateStyleAndLayoutTreeForThisDocument for an explanation of
+ // the "ForThisDocument" suffix.
+ //
+ // These functions do not take into account dirtiness of parent frames:
+ // they are assumed to be clean. If it isn't possible to guarantee
+ // clean parent frames, use Needs[Full]LayoutTreeUpdate() instead.
+ bool NeedsLayoutTreeUpdateForThisDocument() const;
+ bool NeedsFullLayoutTreeUpdateForThisDocument() const;
void UpdateUseShadowTreesIfNeeded();
void EvaluateMediaQueryListIfNeeded();
void UpdateStyleInvalidationIfNeeded();
void UpdateStyle();
+ void UpdateStyleInternal();
void NotifyLayoutTreeOfSubtreeChanges();
bool ChildrenCanHaveStyle() const final;
+ // Objects and embeds depend on "being rendered" for delaying the load event.
+ // This method unblocks the load event after the first layout tree update
+ // after parsing finished.
+ void UnblockLoadEventAfterLayoutTreeUpdate();
+
// ImplicitClose() actually does the work of closing the input stream.
void ImplicitClose();
bool ShouldComplete();
@@ -1819,9 +1844,12 @@ class CORE_EXPORT Document : public ContainerNode,
nth_index_cache_ = nth_index_cache;
}
- const OriginAccessEntry& AccessEntryFromURL();
+ void SetHasMatchedCacheScope(HasMatchedCacheScope* has_matched_cache_scope) {
+ DCHECK(!has_matched_cache_scope_ || !has_matched_cache_scope);
+ has_matched_cache_scope_ = has_matched_cache_scope;
+ }
- void SendDidEditFieldInInsecureContext();
+ const OriginAccessEntry& AccessEntryFromURL();
void UpdateActiveState(bool is_active, bool update_active_chain, Element*);
void UpdateHoverState(Element*);
@@ -2059,6 +2087,13 @@ class CORE_EXPORT Document : public ContainerNode,
GC_PLUGIN_IGNORE("461878")
NthIndexCache* nth_index_cache_ = nullptr;
+ // This is an untraced pointer to the cache-scoped object that is first
+ // allocated on the stack. It is set upon the first object being allocated
+ // on the stack, and cleared upon leaving its allocated scope. The object's
+ // references will be traced by a stack walk.
+ GC_PLUGIN_IGNORE("669058")
+ HasMatchedCacheScope* has_matched_cache_scope_ = nullptr;
+
DocumentClassFlags document_classes_;
bool is_view_source_;
@@ -2078,6 +2113,16 @@ class CORE_EXPORT Document : public ContainerNode,
HeapVector<Member<HTMLPopupElement>> popup_element_stack_;
int load_event_delay_count_;
+
+ // Objects and embeds depend on "being rendered" for delaying the load event.
+ // This is a document-wide flag saying that we have incremented the
+ // load_event_delay_count_ to wait for the next layout tree update. On the
+ // next layout tree update, the counter will be decremented and this flag will
+ // be set to false. If any of the objects/embeds started to fetch a blocking
+ // resource, they would have incremented the delay count during the layout
+ // tree update and further blocked the load event.
+ bool delay_load_event_until_layout_tree_update_ = false;
+
HeapTaskRunnerTimer<Document> load_event_delay_timer_;
HeapTaskRunnerTimer<Document> plugin_loading_timer_;
@@ -2125,10 +2170,6 @@ class CORE_EXPORT Document : public ContainerNode,
Member<PropertyRegistry> property_registry_;
- bool logged_field_edit_;
-
- TaskHandle sensitive_input_edited_task_;
-
Member<NetworkStateObserver> network_state_observer_;
// |ukm_recorder_| and |source_id_| will allow objects that are part of
@@ -2249,7 +2290,6 @@ class CORE_EXPORT Document : public ContainerNode,
Member<FontPreloadManager> font_preload_manager_;
int async_script_count_ = 0;
- bool first_paint_recorded_ = false;
DeclarativeShadowRootAllowState declarative_shadow_root_allow_state_ =
DeclarativeShadowRootAllowState::kNotSet;
@@ -2258,6 +2298,10 @@ class CORE_EXPORT Document : public ContainerNode,
Member<DocumentData> data_;
+ // List of meta[name=theme-color] elements cached used when getting theme
+ // color.
+ HeapVector<Member<HTMLMetaElement>> meta_theme_color_elements_;
+
// If you want to add new data members to blink::Document, please reconsider
// if the members really should be in blink::Document. document.h is a very
// popular header, and the size of document.h affects build time
diff --git a/chromium/third_party/blink/renderer/core/dom/document.idl b/chromium/third_party/blink/renderer/core/dom/document.idl
index a831dba1303..818bf05428a 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.idl
+++ b/chromium/third_party/blink/renderer/core/dom/document.idl
@@ -48,7 +48,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
readonly attribute DOMString contentType;
readonly attribute DocumentType? doctype;
- [Affects=Nothing] readonly attribute Element? documentElement;
+ readonly attribute Element? documentElement;
[Affects=Nothing] HTMLCollection getElementsByTagName(DOMString localName);
[Affects=Nothing] HTMLCollection getElementsByTagNameNS(DOMString? namespaceURI, DOMString localName);
[Affects=Nothing] HTMLCollection getElementsByClassName(DOMString classNames);
@@ -85,10 +85,10 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
// resource metadata management
- [Affects=Nothing, PutForwards=href, LegacyUnforgeable] readonly attribute Location? location;
- [Affects=Nothing, RaisesException=Setter] attribute USVString domain;
- [Affects=Nothing] readonly attribute USVString referrer;
- [Affects=Nothing, RaisesException, RuntimeCallStatsCounter=DocumentCookie] attribute DOMString cookie;
+ [PutForwards=href, LegacyUnforgeable] readonly attribute Location? location;
+ [RaisesException=Setter] attribute USVString domain;
+ readonly attribute USVString referrer;
+ [RaisesException, RuntimeCallStatsCounter=DocumentCookie] attribute DOMString cookie;
readonly attribute DOMString lastModified;
readonly attribute DocumentReadyState readyState;
@@ -96,10 +96,10 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
// Named getter is implemented without IDL code generation for better
// performance. See local_window_proxy.cc.
// getter object (DOMString name);
- [Affects=Nothing, CEReactions] attribute DOMString title;
+ [CEReactions] attribute DOMString title;
[CEReactions] attribute DOMString dir;
- [Affects=Nothing, CEReactions, RaisesException=Setter, PerWorldBindings] attribute HTMLElement? body;
- [Affects=Nothing] readonly attribute HTMLHeadElement? head;
+ [CEReactions, RaisesException=Setter, PerWorldBindings] attribute HTMLElement? body;
+ readonly attribute HTMLHeadElement? head;
[SameObject, Measure] readonly attribute HTMLCollection images;
[SameObject, Measure] readonly attribute HTMLCollection embeds;
[SameObject, ImplementedAs=embeds, Measure] readonly attribute HTMLCollection plugins;
@@ -124,7 +124,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
[CallWith=Isolate, CEReactions, RaisesException] void writeln(TrustedHTML text);
// user interaction
- [Affects=Nothing] readonly attribute Window? defaultView;
+ readonly attribute Window? defaultView;
[Affects=Nothing] boolean hasFocus();
[CEReactions, MeasureAs=DocumentDesignMode] attribute DOMString designMode;
[CEReactions, RaisesException] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
@@ -154,7 +154,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
[SameObject, MeasureAs=DocumentAll] readonly attribute HTMLAllCollection all;
- [Affects=Nothing] readonly attribute Element? scrollingElement;
+ readonly attribute Element? scrollingElement;
// Pointer Lock
// https://w3c.github.io/pointerlock/#extensions-to-the-document-interface
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 a642d35f492..18fdd6be2b7 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
@@ -17,7 +17,7 @@
// https://drafts.csswg.org/cssom-view/#extensions-to-the-document-interface
[Measure] Element? elementFromPoint(double x, double y);
[Measure] sequence<Element> elementsFromPoint(double x, double y);
- [Affects=Nothing] readonly attribute Element? activeElement;
+ readonly attribute Element? activeElement;
[SameObject] readonly attribute StyleSheetList styleSheets;
// PointerLock API
// https://w3c.github.io/pointerlock/
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 3a61a1b374f..67998621e57 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_parser.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_parser.h
@@ -40,7 +40,7 @@ class TextResourceDecoder;
class CORE_EXPORT DocumentParser : public GarbageCollected<DocumentParser>,
public NameClient {
public:
- virtual ~DocumentParser();
+ ~DocumentParser() override;
virtual void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override { return "DocumentParser"; }
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 b575ca1e27f..0c15543566f 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/dom/document_statistics_collector.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_distillability.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_token_list.idl b/chromium/third_party/blink/renderer/core/dom/dom_token_list.idl
index 2d40af5d732..bb030421e75 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_token_list.idl
+++ b/chromium/third_party/blink/renderer/core/dom/dom_token_list.idl
@@ -28,7 +28,7 @@
[
Exposed=Window
] interface DOMTokenList {
- [Affects=Nothing] readonly attribute unsigned long length;
+ readonly attribute unsigned long length;
[Affects=Nothing] getter DOMString? item(unsigned long index);
[Affects=Nothing] boolean contains(DOMString token);
[RaisesException, CEReactions] void add(DOMString... tokens);
diff --git a/chromium/third_party/blink/renderer/core/dom/element-hot.cc b/chromium/third_party/blink/renderer/core/dom/element-hot.cc
index aca8d116555..1ea15e254fa 100644
--- a/chromium/third_party/blink/renderer/core/dom/element-hot.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element-hot.cc
@@ -165,12 +165,7 @@ void Element::SetAttributeHinted(const AtomicString& local_name,
void Element::SetAttributeHinted(const AtomicString& local_name,
WTF::AtomicStringTable::WeakResult hint,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8TrustedString* trusted_string,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&
- string_or_trusted,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (!Document::IsValidName(local_name)) {
exception_state.ThrowDOMException(
@@ -183,15 +178,9 @@ void Element::SetAttributeHinted(const AtomicString& local_name,
wtf_size_t index;
QualifiedName q_name = QualifiedName::Null();
std::tie(index, q_name) = LookupAttributeQNameHinted(local_name, hint);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AtomicString value(TrustedTypesCheckFor(
ExpectedTrustedTypeForAttribute(q_name), trusted_string,
GetExecutionContext(), exception_state));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- AtomicString value(TrustedTypesCheckFor(
- ExpectedTrustedTypeForAttribute(q_name), string_or_trusted,
- GetExecutionContext(), exception_state));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException())
return;
SetAttributeInternal(index, q_name, value,
diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc
index 68e84e3c759..fb24f5710d3 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element.cc
@@ -38,8 +38,6 @@
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/scroll_into_view_options_or_boolean.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_get_inner_html_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_pointer_lock_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
@@ -50,6 +48,7 @@
#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/container_query_evaluator.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -61,6 +60,7 @@
#include "third_party/blink/renderer/core/css/parser/css_selector_parser.h"
#include "third_party/blink/renderer/core/css/property_set_css_style_declaration.h"
#include "third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.h"
+#include "third_party/blink/renderer/core/css/resolver/style_adjuster.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_stats.h"
#include "third_party/blink/renderer/core/css/selector_query.h"
@@ -96,7 +96,9 @@
#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/whitespace_attacher.h"
+#include "third_party/blink/renderer/core/editing/commands/undo_stack.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/ime/edit_context.h"
@@ -140,6 +142,7 @@
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -171,6 +174,7 @@
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
@@ -399,8 +403,8 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element,
return true;
}
- // 'text-combine-upright' property is not supported yet.
- if (style.HasTextCombine() && !style.IsHorizontalWritingMode()) {
+ if (!RuntimeEnabledFeatures::LayoutNGTextCombineEnabled() &&
+ style.HasTextCombine() && !style.IsHorizontalWritingMode()) {
UseCounter::Count(document, WebFeature::kLegacyLayoutByTextCombine);
return true;
}
@@ -480,7 +484,8 @@ HeapLinkedHashSet<WeakMember<Element>>* GetExplicitlySetElementsForAttr(
const QualifiedName& name) {
ExplicitlySetAttrElementsMap* element_attribute_map =
element->GetDocument().GetExplicitlySetAttrElementsMap(element);
- return element_attribute_map->at(name);
+ return element_attribute_map->Contains(name) ? element_attribute_map->at(name)
+ : nullptr;
}
// Checks that the given element |candidate| is a descendant of
@@ -651,7 +656,7 @@ bool Element::IsFocusableStyle() const {
Node* Element::Clone(Document& factory, CloneChildrenFlag flag) const {
if (flag == CloneChildrenFlag::kSkip)
return &CloneWithoutChildren(&factory);
- Element* copy = &CloneWithChildren(&factory);
+ Element* copy = &CloneWithChildren(flag, &factory);
// 7. If node is a shadow host and the clone shadows flag is set, run these
// steps:
if (flag == CloneChildrenFlag::kCloneWithShadows) {
@@ -689,7 +694,8 @@ Node* Element::Clone(Document& factory, CloneChildrenFlag flag) const {
return copy;
}
-Element& Element::CloneWithChildren(Document* nullable_factory) const {
+Element& Element::CloneWithChildren(CloneChildrenFlag flag,
+ Document* nullable_factory) const {
Element& clone = CloneWithoutAttributesAndChildren(
nullable_factory ? *nullable_factory : GetDocument());
// This will catch HTML elements in the wrong namespace that are not correctly
@@ -697,8 +703,8 @@ Element& Element::CloneWithChildren(Document* nullable_factory) const {
DCHECK_EQ(IsHTMLElement(), clone.IsHTMLElement());
clone.CloneAttributesFrom(*this);
- clone.CloneNonAttributePropertiesFrom(*this, CloneChildrenFlag::kClone);
- clone.CloneChildNodesFrom(*this, CloneChildrenFlag::kClone);
+ clone.CloneNonAttributePropertiesFrom(*this, flag);
+ clone.CloneChildNodesFrom(*this, flag);
return clone;
}
@@ -845,7 +851,7 @@ Element* Element::GetElementAttribute(const QualifiedName& name) {
void Element::SetElementArrayAttribute(
const QualifiedName& name,
- const absl::optional<HeapVector<Member<Element>>>& given_elements) {
+ const HeapVector<Member<Element>>* given_elements) {
ExplicitlySetAttrElementsMap* element_attribute_map =
GetDocument().GetExplicitlySetAttrElementsMap(this);
@@ -863,7 +869,8 @@ void Element::SetElementArrayAttribute(
// run the synchronization steps which modify the map invalidating any
// outstanding iterators.
HeapLinkedHashSet<WeakMember<Element>>* stored_elements =
- element_attribute_map->at(name);
+ element_attribute_map->Contains(name) ? element_attribute_map->at(name)
+ : nullptr;
if (!stored_elements) {
stored_elements =
MakeGarbageCollected<HeapLinkedHashSet<WeakMember<Element>>>();
@@ -872,7 +879,7 @@ void Element::SetElementArrayAttribute(
}
SpaceSplitString value;
- for (auto element : given_elements.value()) {
+ for (auto element : *given_elements) {
// If |value| is null and |stored_elements| is non-empty, then a previous
// element must have been invalid wrt. the content attribute string rules,
// and therefore the content attribute string should reflect the empty
@@ -916,9 +923,10 @@ void Element::SetElementArrayAttribute(
element_attribute_map->Set(name, stored_elements);
}
-absl::optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute(
+HeapVector<Member<Element>>* Element::GetElementArrayAttribute(
const QualifiedName& name) {
- HeapVector<Member<Element>> result_elements;
+ HeapVector<Member<Element>>* result_elements =
+ MakeGarbageCollected<HeapVector<Member<Element>>>();
// TODO(chrishall): this will fail to preserve `e1.ariaFoo === e1.ariaFoo`,
// need additional cache to preserve this invariant, add tests covering this
// case.
@@ -928,7 +936,7 @@ absl::optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute(
if (explicitly_set_elements) {
for (auto attrElement : *explicitly_set_elements) {
if (ElementIsDescendantOfShadowIncludingAncestor(*this, *attrElement))
- result_elements.push_back(attrElement);
+ result_elements->push_back(attrElement);
}
return result_elements;
}
@@ -944,7 +952,7 @@ absl::optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute(
}
if (!hasAttribute(attr))
- return absl::nullopt;
+ return nullptr;
String attribute_value = getAttribute(attr).GetString();
Vector<String> tokens;
@@ -957,7 +965,7 @@ absl::optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute(
for (auto id : tokens) {
Element* candidate = GetTreeScope().getElementById(AtomicString(id));
if (candidate)
- result_elements.push_back(candidate);
+ result_elements->push_back(candidate);
}
return result_elements;
@@ -1069,7 +1077,6 @@ void Element::setNonce(const AtomicString& nonce) {
EnsureElementRareData().SetNonce(nonce);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Element::scrollIntoView(const V8UnionBooleanOrScrollIntoViewOptions* arg) {
ScrollIntoViewOptions* options = nullptr;
switch (arg->GetContentType()) {
@@ -1086,30 +1093,10 @@ void Element::scrollIntoView(const V8UnionBooleanOrScrollIntoViewOptions* arg) {
DCHECK(options);
scrollIntoViewWithOptions(options);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void Element::scrollIntoView(ScrollIntoViewOptionsOrBoolean arg) {
- ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
- if (arg.IsBoolean()) {
- if (arg.GetAsBoolean())
- options->setBlock("start");
- else
- options->setBlock("end");
- options->setInlinePosition("nearest");
- } else if (arg.IsScrollIntoViewOptions()) {
- options = arg.GetAsScrollIntoViewOptions();
- }
- scrollIntoViewWithOptions(options);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Element::scrollIntoView(bool align_to_top) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(align_to_top);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetBoolean(align_to_top);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
scrollIntoView(arg);
}
@@ -2156,7 +2143,7 @@ const AtomicString& Element::computedRole() {
document.View()->UpdateAllLifecyclePhasesExceptPaint(
DocumentUpdateReason::kJavaScript);
}
- AXContext ax_context(document);
+ AXContext ax_context(document, ui::kAXModeBasic);
return ax_context.GetAXObjectCache().ComputedRoleForNode(this);
}
@@ -2170,7 +2157,7 @@ String Element::computedName() {
document.View()->UpdateAllLifecyclePhasesExceptPaint(
DocumentUpdateReason::kJavaScript);
}
- AXContext ax_context(document);
+ AXContext ax_context(document, ui::kAXModeBasic);
return ax_context.GetAXObjectCache().ComputedNameForNode(this);
}
@@ -2662,7 +2649,11 @@ void Element::RemovedFrom(ContainerNode& insertion_point) {
UpdateName(name_value, g_null_atom);
}
+ if (AccessibleNode* accessible_node = ExistingAccessibleNode())
+ accessible_node->DetachedFromDocument();
+
ContainerNode::RemovedFrom(insertion_point);
+
if (was_in_document) {
if (this == GetDocument().CssTarget())
GetDocument().SetCSSTarget(nullptr);
@@ -2703,8 +2694,11 @@ void Element::RemovedFrom(ContainerNode& insertion_point) {
DCHECK(!data->HasPseudoElements());
}
- if (GetDocument().GetFrame())
- GetDocument().GetFrame()->GetEventHandler().ElementRemoved(this);
+ if (auto* const frame = GetDocument().GetFrame()) {
+ if (UNLIKELY(HasUndoStack()))
+ frame->GetEditor().GetUndoStack().ElementRemoved(this);
+ frame->GetEventHandler().ElementRemoved(this);
+ }
}
void Element::AttachLayoutTree(AttachContext& context) {
@@ -2780,10 +2774,8 @@ void Element::DetachLayoutTree(bool performing_reattach) {
HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
if (HasRareData()) {
ElementRareData* data = GetElementRareData();
- if (!performing_reattach) {
+ if (!performing_reattach)
data->ClearPseudoElements();
- data->SetContainerQueryEvaluator(nullptr);
- }
if (ElementAnimations* element_animations = data->GetElementAnimations()) {
if (performing_reattach) {
@@ -2795,7 +2787,6 @@ void Element::DetachLayoutTree(bool performing_reattach) {
element_animations->CssAnimations().Cancel();
element_animations->SetAnimationStyleChange(false);
}
- element_animations->ClearBaseComputedStyle();
}
}
@@ -2861,9 +2852,12 @@ scoped_refptr<ComputedStyle> Element::StyleForLayoutObject(
return nullptr;
}
- // ResolveStyle() might add active animations so we need to get it again.
if (ElementAnimations* element_animations = GetElementAnimations()) {
- element_animations->CssAnimations().MaybeApplyPendingUpdate(this);
+ // With CSSIsolatedAnimationUpdates enabled, animation updates are not
+ // applied during an Element's style recalc, but during
+ // Document::UpdateStyle.
+ if (!RuntimeEnabledFeatures::CSSIsolatedAnimationUpdatesEnabled())
+ element_animations->CssAnimations().MaybeApplyPendingUpdate(this);
element_animations->UpdateAnimationFlags(*style);
}
@@ -2903,6 +2897,12 @@ void Element::RecalcStyle(const StyleRecalcChange change,
if (GetStyleChangeType() == kSubtreeStyleChange)
child_change = child_change.ForceRecalcDescendants();
ClearNeedsStyleRecalc();
+ } else if (GetForceReattachLayoutTree()) {
+ DCHECK(GetComputedStyle()) << "No need to force a layout tree reattach if "
+ "we had no computed style";
+ SetNeedsReattachLayoutTree();
+ child_change = child_change.ForceReattachLayoutTree();
+ ClearNeedsStyleRecalc();
}
// We're done with self style, notify the display lock.
@@ -2939,9 +2939,9 @@ void Element::RecalcStyle(const StyleRecalcChange change,
StyleRecalcContext child_recalc_context = style_recalc_context;
- if (LayoutObject* layout_object = GetLayoutObject()) {
- if (layout_object->IsContainerForContainerQueries())
- child_recalc_context.cq_evaluator = GetContainerQueryEvaluator();
+ if (const ComputedStyle* style = GetComputedStyle()) {
+ if (style->IsContainerForContainerQueries())
+ child_recalc_context.container = this;
}
if (child_change.TraversePseudoElements(*this)) {
@@ -2960,8 +2960,9 @@ void Element::RecalcStyle(const StyleRecalcChange change,
// make sure we clear out-of-date ComputedStyles outside the flat tree
// in Element::EnsureComputedStyle().
if (child_change.RecalcDescendants()) {
- RecalcDescendantStyles(StyleRecalcChange::kClearEnsured,
- child_recalc_context);
+ RecalcDescendantStyles(
+ StyleRecalcChange(StyleRecalcChange::kClearEnsured),
+ child_recalc_context);
}
} else if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(this)) {
slot->RecalcStyleForSlotChildren(child_change, child_recalc_context);
@@ -3008,13 +3009,33 @@ scoped_refptr<ComputedStyle> Element::PropagateInheritedProperties() {
return new_style;
}
+static ContainerQueryEvaluator* ComputeContainerQueryEvaluator(
+ Element& element,
+ const ComputedStyle* old_style,
+ const ComputedStyle& new_style) {
+ if (!new_style.IsContainerForContainerQueries())
+ return nullptr;
+ // If we're switching to display:contents, any existing results cached on
+ // ContainerQueryEvaluator are no longer valid, since any style recalc
+ // based on that information would *not* be corrected by a subsequent
+ // interleaved style recalc, since the element has no layout object.
+ if (old_style && !element.LayoutObjectIsNeeded(new_style) &&
+ element.LayoutObjectIsNeeded(*old_style)) {
+ return MakeGarbageCollected<ContainerQueryEvaluator>();
+ }
+ // Othewise, the existing ContainerQueryEvaluator can be used, if any.
+ if (auto* evaluator = element.GetContainerQueryEvaluator())
+ return evaluator;
+ return MakeGarbageCollected<ContainerQueryEvaluator>();
+}
+
static const StyleRecalcChange ApplyComputedStyleDiff(
const StyleRecalcChange change,
ComputedStyle::Difference diff) {
if (change.RecalcDescendants() ||
diff < ComputedStyle::Difference::kPseudoElementStyle)
return change;
- if (diff == ComputedStyle::Difference::kDisplayAffectingDescendantStyles)
+ if (diff == ComputedStyle::Difference::kDescendantAffecting)
return change.ForceRecalcDescendants();
if (diff == ComputedStyle::Difference::kInherited)
return change.EnsureAtLeast(StyleRecalcChange::kRecalcChildren);
@@ -3076,13 +3097,14 @@ StyleRecalcChange Element::RecalcOwnStyle(
rare_data->GetElementAnimations()) {
element_animations->CssAnimations().Cancel();
}
+ rare_data->SetContainerQueryEvaluator(nullptr);
rare_data->ClearPseudoElements();
}
SetComputedStyle(new_style);
if (!child_change.ReattachLayoutTree() &&
- (GetForceReattachLayoutTree() ||
+ (GetForceReattachLayoutTree() || NeedsReattachLayoutTree() ||
ComputedStyle::NeedsReattachLayoutTree(*this, old_style.get(),
new_style.get()))) {
child_change = child_change.ForceReattachLayoutTree();
@@ -3127,8 +3149,14 @@ StyleRecalcChange Element::RecalcOwnStyle(
if (old_style && !child_change.RecalcChildren() &&
old_style->HasChildDependentFlags())
new_style->CopyChildDependentFlagsFrom(*old_style);
- if (RuntimeEnabledFeatures::LayoutNGEnabled())
- UpdateForceLegacyLayout(*new_style, old_style.get());
+ if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+ if (UpdateForceLegacyLayout(*new_style, old_style.get()))
+ child_change = child_change.ForceReattachLayoutTree();
+ }
+ auto* evaluator =
+ ComputeContainerQueryEvaluator(*this, old_style.get(), *new_style);
+ if (evaluator != GetContainerQueryEvaluator())
+ SetContainerQueryEvaluator(evaluator);
}
if (child_change.ReattachLayoutTree()) {
@@ -3137,8 +3165,19 @@ StyleRecalcChange Element::RecalcOwnStyle(
return child_change;
}
+ DCHECK(!NeedsReattachLayoutTree())
+ << "If we need to reattach the layout tree we should have returned "
+ "above. Updating and diffing the style of a LayoutObject which is "
+ "about to be deleted is a waste.";
+
if (LayoutObject* layout_object = GetLayoutObject()) {
DCHECK(new_style);
+ if (UNLIKELY(layout_object->IsText()) &&
+ UNLIKELY(IsA<LayoutNGTextCombine>(layout_object->Parent()))) {
+ // Adjust style for <br> and <wbr> in combined text.
+ // See http://crbug.com/1228058
+ StyleAdjuster::AdjustStyleForCombinedText(*new_style);
+ }
scoped_refptr<const ComputedStyle> layout_style(std::move(new_style));
if (auto* pseudo_element = DynamicTo<PseudoElement>(this)) {
if (layout_style->Display() == EDisplay::kContents) {
@@ -3146,7 +3185,8 @@ StyleRecalcChange Element::RecalcOwnStyle(
pseudo_element->LayoutStyleForDisplayContents(*layout_style);
}
} else if (auto* html_element = DynamicTo<HTMLHtmlElement>(this)) {
- layout_style = html_element->LayoutStyleForElement(layout_style);
+ if (this == GetDocument().documentElement())
+ layout_style = html_element->LayoutStyleForElement(layout_style);
}
// kEqual means that the computed style didn't change, but there are
// additional flags in ComputedStyle which may have changed. For instance,
@@ -3402,6 +3442,7 @@ void Element::SetNeedsCompositingUpdate() {
// TODO(pdr): Do not depend on PaintLayer for compositing decisions.
if (!layout_object->HasLayer())
return;
+
layout_object->Layer()->SetNeedsCompositingInputsUpdate();
// Changes to RequiresAcceleratedCompositing change if the PaintLayer is
@@ -3413,6 +3454,11 @@ void Element::SetNeedsCompositingUpdate() {
// reasons which affect paint properties.
if (layout_object->CanHaveAdditionalCompositingReasons())
layout_object->SetNeedsPaintPropertyUpdate();
+
+ // With CompositeAfterPaint, we need to repaint the layer because the foreign
+ // layer may have changed.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ layout_object->Layer()->SetNeedsRepaint();
}
void Element::SetCustomElementDefinition(CustomElementDefinition* definition) {
@@ -3812,27 +3858,16 @@ bool Element::ParseAttributeName(QualifiedName& out,
void Element::setAttributeNS(const AtomicString& namespace_uri,
const AtomicString& qualified_name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8TrustedString* trusted_string,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&
- string_or_trusted,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
QualifiedName parsed_name = g_any_name;
if (!ParseAttributeName(parsed_name, namespace_uri, qualified_name,
exception_state))
return;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AtomicString value(TrustedTypesCheckFor(
ExpectedTrustedTypeForAttribute(parsed_name), trusted_string,
GetExecutionContext(), exception_state));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- AtomicString value(TrustedTypesCheckFor(
- ExpectedTrustedTypeForAttribute(parsed_name), string_or_trusted,
- GetExecutionContext(), exception_state));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException())
return;
@@ -4007,15 +4042,21 @@ void Element::focus(const FocusParams& params) {
this, GetDocument().GetFrame(), params))
return;
- if (GetDocument().FocusedElement() == this &&
- GetDocument().GetFrame()->HasStickyUserActivation()) {
+ if (GetDocument().FocusedElement() == this) {
ChromeClient& chrome_client = GetDocument().GetPage()->GetChromeClient();
- // Bring up the keyboard in the context of anything triggered by a user
- // gesture. Since tracking that across arbitrary boundaries (eg.
- // animations) is difficult, for now we match IE's heuristic and bring
- // up the keyboard if there's been any gesture since load.
- chrome_client.ShowVirtualKeyboardOnElementFocus(*GetDocument().GetFrame());
+ if (GetDocument().GetFrame()->HasStickyUserActivation()) {
+ // Bring up the keyboard in the context of anything triggered by a user
+ // gesture. Since tracking that across arbitrary boundaries (eg.
+ // animations) is difficult, for now we match IE's heuristic and bring
+ // up the keyboard if there's been any gesture since load.
+ chrome_client.ShowVirtualKeyboardOnElementFocus(
+ *GetDocument().GetFrame());
+ }
+ // TODO(bebeaudr): We might want to move the following code into the
+ // HasStickyUserActivation condition above once https://crbug.com/1208874 is
+ // fixed.
+ //
// Trigger a tooltip to show for the newly focused element only when the
// focus was set resulting from a keyboard action.
//
@@ -4187,6 +4228,14 @@ bool Element::IsFocusableStyleAfterUpdate() const {
// Note that this isn't a part of `IsFocusableStyle()` because there are
// callers of that function which cannot do a layout tree update (e.g.
// accessibility).
+ //
+ // Also note that if this node is ignored due to a display lock for focus
+ // activation reason, we simply return false to avoid updating style & layout
+ // tree for this node.
+ if (DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ *this, DisplayLockActivationReason::kUserFocus)) {
+ return false;
+ }
GetDocument().UpdateStyleAndLayoutTreeForNode(this);
return IsFocusableStyle();
}
@@ -4196,16 +4245,12 @@ bool Element::IsKeyboardFocusable() const {
((SupportsFocus() &&
GetIntegralAttribute(html_names::kTabindexAttr, 0) >= 0) ||
(RuntimeEnabledFeatures::KeyboardFocusableScrollersEnabled() &&
- IsScrollableNode(this))) &&
- !DisplayLockPreventsActivation(
- DisplayLockActivationReason::kUserFocus);
+ IsScrollableNode(this)));
}
bool Element::IsMouseFocusable() const {
return isConnected() && !IsInert() && IsFocusableStyleAfterUpdate() &&
- SupportsFocus() &&
- !DisplayLockPreventsActivation(
- DisplayLockActivationReason::kUserFocus);
+ SupportsFocus();
}
bool Element::IsAutofocusable() const {
@@ -4252,32 +4297,6 @@ bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) {
return activated;
}
-bool Element::DisplayLockPreventsActivation(
- DisplayLockActivationReason reason) const {
- if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
- return false;
-
- if (GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount() == 0)
- return false;
-
- // TODO(vmpstr): Similar to Document::EnsurePaintLocationDataValidForNode(),
- // this iterates up to the ancestor hierarchy looking for locked display
- // locks. This is inefficient, particularly since it's unlikely that this will
- // yield any "true" results in practice. We need to come up with a way to
- // check whether a node is in a locked subtree quickly.
- // See crbug.com/924550 for more details.
- for (const Node& current : FlatTreeTraversal::InclusiveAncestorsOf(*this)) {
- auto* current_element = DynamicTo<Element>(current);
- if (!current_element)
- continue;
- if (auto* context = current_element->GetDisplayLockContext()) {
- if (context->IsLocked() && !context->IsActivatable(reason))
- return true;
- }
- }
- return false;
-}
-
bool Element::StyleShouldForceLegacyLayoutInternal() const {
return GetElementRareData()->StyleShouldForceLegacyLayout();
}
@@ -4294,7 +4313,15 @@ void Element::SetShouldForceLegacyLayoutForChildInternal(bool force) {
EnsureElementRareData().SetShouldForceLegacyLayoutForChild(force);
}
-void Element::UpdateForceLegacyLayout(const ComputedStyle& new_style,
+bool Element::HasUndoStack() const {
+ return HasRareData() && GetElementRareData()->HasUndoStack();
+}
+
+void Element::SetHasUndoStack(bool value) {
+ EnsureElementRareData().SetHasUndoStack(value);
+}
+
+bool Element::UpdateForceLegacyLayout(const ComputedStyle& new_style,
const ComputedStyle* old_style) {
// ::first-letter may cause structure discrepancies between DOM and layout
// tree (in layout the layout object will be wrapped around the actual text
@@ -4305,7 +4332,8 @@ void Element::UpdateForceLegacyLayout(const ComputedStyle& new_style,
// ::first-letter pseudo element cannot introduce the need for legacy layout
// on its own, so just bail. We'll do whatever the parent layout object does.
if (IsFirstLetterPseudoElement())
- return;
+ return false;
+ bool needs_reattach = false;
bool old_force = old_style && ShouldForceLegacyLayout();
SetStyleShouldForceLegacyLayout(
CalculateStyleShouldForceLegacyLayout(*this, new_style));
@@ -4317,13 +4345,14 @@ void Element::UpdateForceLegacyLayout(const ComputedStyle& new_style,
// check with the LayoutObject whether this is news and that it really
// needs to be reattached.
if (!layout_object->ForceLegacyLayout())
- SetNeedsReattachLayoutTree();
+ needs_reattach = true;
}
}
// Even if we also previously forced legacy layout, we may need to introduce
// forced legacy layout in the ancestry, e.g. if this element no longer
// establishes a new formatting context.
- ForceLegacyLayoutInFormattingContext(new_style);
+ if (ForceLegacyLayoutInFormattingContext(new_style))
+ needs_reattach = true;
// If we're inside an NG fragmentation context, we also need the entire
// fragmentation context to fall back to legacy layout. Note that once this
@@ -4331,19 +4360,23 @@ void Element::UpdateForceLegacyLayout(const ComputedStyle& new_style,
// even if all the reasons for requiring it in the first place disappear
// (e.g. if the only reason was a table, and that table is removed, we'll
// still be using legacy layout).
- if (new_style.InsideNGFragmentationContext())
+ if (new_style.InsideNGFragmentationContext()) {
ForceLegacyLayoutInFragmentationContext(new_style);
+ needs_reattach = true;
+ }
} else if (old_force) {
// TODO(mstensho): If we have ancestors that got legacy layout just because
// of this child, we should clean it up, and switch the subtree back to NG,
// rather than being stuck with legacy forever.
- SetNeedsReattachLayoutTree();
+ needs_reattach = true;
}
+ return needs_reattach;
}
-void Element::ForceLegacyLayoutInFormattingContext(
+bool Element::ForceLegacyLayoutInFormattingContext(
const ComputedStyle& new_style) {
bool found_fc = DefinitelyNewFormattingContext(*this, new_style);
+ bool needs_reattach = false;
for (Element* ancestor = this; !found_fc;) {
ancestor =
@@ -4365,7 +4398,9 @@ void Element::ForceLegacyLayoutInFormattingContext(
found_fc = DefinitelyNewFormattingContext(*ancestor, *style);
ancestor->SetShouldForceLegacyLayoutForChild(true);
ancestor->SetNeedsReattachLayoutTree();
+ needs_reattach = true;
}
+ return needs_reattach;
}
void Element::ForceLegacyLayoutInFragmentationContext(
@@ -4378,6 +4413,16 @@ void Element::ForceLegacyLayoutInFragmentationContext(
// positives; e.g. if there's an absolutely positioned table, whose containing
// block of the table is on the outside of the fragmentation context, we're
// still going to fall back to legacy.
+
+ if (GetDocument().Printing()) {
+ // Force legacy layout on the entire document, since we're printing, and
+ // there's some fragmentable box that needs legacy layout inside somewhere.
+ Element* root = GetDocument().documentElement();
+ root->SetShouldForceLegacyLayoutForChild(true);
+ root->SetNeedsReattachLayoutTree();
+ return;
+ }
+
Element* parent;
for (Element* walker = this; walker; walker = parent) {
parent = DynamicTo<Element>(LayoutTreeBuilderTraversal::Parent(*walker));
@@ -4392,12 +4437,6 @@ void Element::ForceLegacyLayoutInFragmentationContext(
if (parent && !parent->GetComputedStyle()->InsideNGFragmentationContext())
return;
}
- DCHECK(GetDocument().Printing());
- // Force legacy layout on the entire document, since we're printing, and
- // there's some fragmentable box that needs legacy layout inside somewhere.
- Element* root = GetDocument().documentElement();
- root->SetShouldForceLegacyLayoutForChild(true);
- root->SetNeedsReattachLayoutTree();
}
bool Element::IsFocusedElementInDocument() const {
@@ -4928,7 +4967,10 @@ const ComputedStyle* Element::EnsureComputedStyle(
while (!ancestors.IsEmpty()) {
Element* ancestor = ancestors.back();
ancestors.pop_back();
- ancestor->EnsureOwnComputedStyle(style_recalc_context, kPseudoIdNone);
+ const ComputedStyle* style =
+ ancestor->EnsureOwnComputedStyle(style_recalc_context, kPseudoIdNone);
+ if (style->IsContainerForContainerQueries())
+ style_recalc_context.container = ancestor;
}
return EnsureOwnComputedStyle(style_recalc_context, pseudo_element_specifier,
@@ -5272,7 +5314,9 @@ bool Element::PseudoElementStylesDependOnFontMetrics() const {
return false;
}
-const ComputedStyle* Element::CachedStyleForPseudoElement(PseudoId pseudo_id) {
+const ComputedStyle* Element::CachedStyleForPseudoElement(
+ PseudoId pseudo_id,
+ const AtomicString& pseudo_argument) {
const ComputedStyle* style = GetComputedStyle();
if (!style || (pseudo_id < kFirstInternalPseudoId &&
@@ -5281,11 +5325,11 @@ const ComputedStyle* Element::CachedStyleForPseudoElement(PseudoId pseudo_id) {
}
if (const ComputedStyle* cached =
- style->GetCachedPseudoElementStyle(pseudo_id))
+ style->GetCachedPseudoElementStyle(pseudo_id, pseudo_argument))
return cached;
- scoped_refptr<ComputedStyle> result =
- UncachedStyleForPseudoElement(StyleRequest(pseudo_id, style));
+ scoped_refptr<ComputedStyle> result = UncachedStyleForPseudoElement(
+ StyleRequest(pseudo_id, style, pseudo_argument));
if (result)
return style->AddCachedPseudoElementStyle(std::move(result));
return nullptr;
@@ -6121,6 +6165,7 @@ void Element::InlineStyleChanged() {
void Element::SetInlineStyleProperty(CSSPropertyID property_id,
CSSValueID identifier,
bool important) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
SetInlineStyleProperty(property_id, *CSSIdentifierValue::Create(identifier),
important);
}
@@ -6129,6 +6174,7 @@ void Element::SetInlineStyleProperty(CSSPropertyID property_id,
double value,
CSSPrimitiveValue::UnitType unit,
bool important) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
SetInlineStyleProperty(
property_id, *CSSNumericLiteralValue::Create(value, unit), important);
}
@@ -6136,6 +6182,7 @@ void Element::SetInlineStyleProperty(CSSPropertyID property_id,
void Element::SetInlineStyleProperty(CSSPropertyID property_id,
const CSSValue& value,
bool important) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
DCHECK(IsStyledElement());
EnsureMutableInlineStyle().SetProperty(property_id, value, important);
InlineStyleChanged();
@@ -6144,6 +6191,7 @@ void Element::SetInlineStyleProperty(CSSPropertyID property_id,
bool Element::SetInlineStyleProperty(CSSPropertyID property_id,
const String& value,
bool important) {
+ DCHECK_NE(property_id, CSSPropertyID::kVariable);
DCHECK(IsStyledElement());
bool did_change =
EnsureMutableInlineStyle()
@@ -6158,6 +6206,14 @@ bool Element::SetInlineStyleProperty(CSSPropertyID property_id,
return did_change;
}
+void Element::SetInlineStyleProperty(const CSSPropertyName& name,
+ const CSSValue& value,
+ bool important) {
+ DCHECK(IsStyledElement());
+ EnsureMutableInlineStyle().SetProperty(name, value, important);
+ InlineStyleChanged();
+}
+
bool Element::RemoveInlineStyleProperty(CSSPropertyID property_id) {
DCHECK(IsStyledElement());
if (!InlineStyle())
diff --git a/chromium/third_party/blink/renderer/core/dom/element.h b/chromium/third_party/blink/renderer/core/dom/element.h
index 30d5071cbdb..0e21ca7ac74 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.h
+++ b/chromium/third_party/blink/renderer/core/dom/element.h
@@ -54,6 +54,8 @@ namespace blink {
class AccessibleNode;
class Attr;
class Attribute;
+class ContainerQueryEvaluator;
+class CSSPropertyName;
class CSSPropertyValueSet;
class CSSStyleDeclaration;
class CustomElementDefinition;
@@ -84,12 +86,10 @@ class PseudoElement;
class ResizeObservation;
class ResizeObserver;
class ScrollIntoViewOptions;
-class ScrollIntoViewOptionsOrBoolean;
class ScrollToOptions;
class ShadowRoot;
class ShadowRootInit;
class SpaceSplitString;
-class StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL;
class StylePropertyMap;
class StylePropertyMapReadOnly;
class StyleRecalcContext;
@@ -202,11 +202,11 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
bool HasExplicitlySetAttrAssociatedElements(const QualifiedName& name);
Element* GetElementAttribute(const QualifiedName& name);
void SetElementAttribute(const QualifiedName&, Element*);
- absl::optional<HeapVector<Member<Element>>> GetElementArrayAttribute(
+ HeapVector<Member<Element>>* GetElementArrayAttribute(
const QualifiedName& name);
void SetElementArrayAttribute(
- const QualifiedName&,
- const absl::optional<HeapVector<Member<Element>>>&);
+ const QualifiedName& name,
+ const HeapVector<Member<Element>>* given_elements);
// Call this to get the value of an attribute that is known not to be the
// style attribute or one of the SVG animatable attributes.
@@ -243,22 +243,12 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
}
// Trusted Types variant for explicit setAttribute() use.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setAttribute(const AtomicString& name,
const V8TrustedString* trusted_string,
ExceptionState& exception_state) {
SetAttributeHinted(name, WeakLowercaseIfNecessary(name), trusted_string,
exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setAttribute(const AtomicString& name,
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&
- string_or_trusted,
- ExceptionState& exception_state) {
- SetAttributeHinted(name, WeakLowercaseIfNecessary(name), string_or_trusted,
- exception_state);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Returns attributes that should be checked against Trusted Types
virtual const AttrNameToTrustedType& GetCheckedAttributeTypes() const;
@@ -269,18 +259,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
const AtomicString& namespace_uri,
const AtomicString& qualified_name,
ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setAttributeNS(const AtomicString& namespace_uri,
const AtomicString& qualified_name,
const V8TrustedString* trusted_string,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setAttributeNS(
- const AtomicString& namespace_uri,
- const AtomicString& qualified_name,
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool toggleAttribute(const AtomicString&, ExceptionState&);
bool toggleAttribute(const AtomicString&, bool force, ExceptionState&);
@@ -319,11 +301,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// when not interested in style attribute or one of the SVG attributes.
AttributeCollection AttributesWithoutUpdate() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void scrollIntoView(const V8UnionBooleanOrScrollIntoViewOptions* arg);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void scrollIntoView(ScrollIntoViewOptionsOrBoolean);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void scrollIntoView(bool align_to_top = true);
void scrollIntoViewWithOptions(const ScrollIntoViewOptions*);
void ScrollIntoViewNoVisualUpdate(const ScrollIntoViewOptions*);
@@ -406,6 +384,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
bool HasTagName(const HTMLQualifiedName& tag_name) const {
return ContainerNode::HasTagName(tag_name);
}
+ bool HasTagName(const MathMLQualifiedName& tag_name) const {
+ return ContainerNode::HasTagName(tag_name);
+ }
bool HasTagName(const SVGQualifiedName& tag_name) const {
return ContainerNode::HasTagName(tag_name);
}
@@ -429,7 +410,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
String nodeName() const override;
- Element& CloneWithChildren(Document* = nullptr) const;
+ Element& CloneWithChildren(CloneChildrenFlag flag, Document* = nullptr) const;
Element& CloneWithoutChildren(Document* = nullptr) const;
void SetBooleanAttribute(const QualifiedName&, bool);
@@ -456,6 +437,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
bool SetInlineStyleProperty(CSSPropertyID,
const String& value,
bool important = false);
+ void SetInlineStyleProperty(const CSSPropertyName&,
+ const CSSValue&,
+ bool important = false);
bool RemoveInlineStyleProperty(CSSPropertyID);
bool RemoveInlineStyleProperty(const AtomicString&);
@@ -758,8 +742,12 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// Retrieve the ComputedStyle (if any) corresponding to the provided
// PseudoId from cache, calculating the ComputedStyle on-demand if it's
- // missing from the cache.
- const ComputedStyle* CachedStyleForPseudoElement(PseudoId);
+ // missing from the cache. The |pseudo_argument| is also used to match the
+ // ComputedStyle in cases where the PseudoId corresponds to a pseudo element
+ // that takes arguments (e.g. ::highlight()).
+ const ComputedStyle* CachedStyleForPseudoElement(
+ PseudoId,
+ const AtomicString& pseudo_argument = g_null_atom);
// Calculate the ComputedStyle corresponding to the provided StyleRequest,
// bypassing the pseudo style cache.
@@ -980,6 +968,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// information.
bool ShouldCompositeForDocumentTransition() const;
+ // For undo stack cleanup
+ bool HasUndoStack() const;
+ void SetHasUndoStack(bool);
+
protected:
const ElementData* GetElementData() const { return element_data_.Get(); }
UniqueElementData& EnsureUniqueElementData();
@@ -1205,18 +1197,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
WTF::AtomicStringTable::WeakResult hint,
const AtomicString& value,
ExceptionState& = ASSERT_NO_EXCEPTION);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void SetAttributeHinted(const AtomicString& name,
WTF::AtomicStringTable::WeakResult hint,
const V8TrustedString* trusted_string,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetAttributeHinted(
- const AtomicString& name,
- WTF::AtomicStringTable::WeakResult hint,
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
std::pair<wtf_size_t, const QualifiedName> LookupAttributeQNameHinted(
const AtomicString& name,
WTF::AtomicStringTable::WeakResult hint) const;
@@ -1265,10 +1249,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
void DetachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
void DetachAttrNodeAtIndex(Attr*, wtf_size_t index);
- bool DisplayLockPreventsActivation(DisplayLockActivationReason reason) const;
- FRIEND_TEST_ALL_PREFIXES(DisplayLockContextTest,
- DisplayLockPreventsActivation);
-
// Return whether this element type requires legacy layout.
virtual bool TypeShouldForceLegacyLayout() const { return false; }
@@ -1285,6 +1265,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
return;
SetStyleShouldForceLegacyLayoutInternal(force);
}
+ FRIEND_TEST_ALL_PREFIXES(LayoutNGTextCombineTest, LegacyQuote);
void SetStyleShouldForceLegacyLayoutInternal(bool);
// Return whether this element needs legacy layout because of a child.
@@ -1304,7 +1285,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// Update ForceLegacyLayout flags for this element, and for ancestors, if
// necessary. We cannot establish a ForceLegacyLayout subtree at an arbitrary
// element; it needs to be a block formatting context root.
- void UpdateForceLegacyLayout(const ComputedStyle& new_style,
+ // Returns true if we need to reattach this element or any ancestor element.
+ bool UpdateForceLegacyLayout(const ComputedStyle& new_style,
const ComputedStyle* old_style);
// If this element requires legacy layout, and we can't tell for sure that it
@@ -1312,7 +1294,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// layout on ancestors until we reach one that we're sure that will establish
// a new formatting context. LayoutNG and legacy layout cannot cooperate
// within a formatting context.
- void ForceLegacyLayoutInFormattingContext(const ComputedStyle& new_style);
+ // Returns true if we need to reattach this element or any ancestor element.
+ bool ForceLegacyLayoutInFormattingContext(const ComputedStyle& new_style);
// If this element requires legacy layout, and we're inside a fragmentation
// context, we need to force legacy layout for the entire fragmentation
diff --git a/chromium/third_party/blink/renderer/core/dom/element.idl b/chromium/third_party/blink/renderer/core/dom/element.idl
index 4f7cbbec559..a0bd2711f68 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.idl
+++ b/chromium/third_party/blink/renderer/core/dom/element.idl
@@ -32,15 +32,15 @@ callback ScrollStateCallback = void (ScrollState scrollState);
readonly attribute DOMString? namespaceURI;
readonly attribute DOMString? prefix;
readonly attribute DOMString localName;
- [Affects=Nothing] readonly attribute DOMString tagName;
+ readonly attribute DOMString tagName;
- [Affects=Nothing, CEReactions, Reflect] attribute DOMString id;
- [Affects=Nothing, CEReactions, Reflect=class] attribute DOMString className;
- [Affects=Nothing, SameObject, PerWorldBindings, PutForwards=value] readonly attribute DOMTokenList classList;
+ [CEReactions, Reflect] attribute DOMString id;
+ [CEReactions, Reflect=class] attribute DOMString className;
+ [SameObject, PerWorldBindings, PutForwards=value] readonly attribute DOMTokenList classList;
[Unscopable, CEReactions, Reflect] attribute DOMString slot;
[Affects=Nothing] boolean hasAttributes();
- [Affects=Nothing, SameObject, PerWorldBindings, ImplementedAs=attributesForBindings] readonly attribute NamedNodeMap attributes;
+ [SameObject, PerWorldBindings, ImplementedAs=attributesForBindings] readonly attribute NamedNodeMap attributes;
[Affects=Nothing] sequence<DOMString> getAttributeNames();
[Affects=Nothing] DOMString? getAttribute(DOMString name);
[Affects=Nothing] DOMString? getAttributeNS(DOMString? namespaceURI, DOMString localName);
@@ -61,7 +61,7 @@ callback ScrollStateCallback = void (ScrollState scrollState);
[RuntimeEnabled=EditContext] attribute EditContext? editContext;
[RaisesException, MeasureAs=ElementAttachShadow] ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
- [Affects=Nothing, PerWorldBindings, ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
+ [PerWorldBindings, ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
[RaisesException] Element? closest(DOMString selectors);
[RaisesException] boolean matches(DOMString selectors);
@@ -76,7 +76,7 @@ callback ScrollStateCallback = void (ScrollState scrollState);
// CSS Shadow Parts
// https://drafts.csswg.org/css-shadow-parts/#idl
- [Affects=Nothing, SameObject, PerWorldBindings, PutForwards=value] readonly attribute DOMTokenList part;
+ [SameObject, PerWorldBindings, PutForwards=value] readonly attribute DOMTokenList part;
// Pointer Events
// https://w3c.github.io/pointerevents/#extensions-to-the-element-interface
@@ -94,8 +94,8 @@ callback ScrollStateCallback = void (ScrollState scrollState);
// TODO(mkwst): Write a spec for the `TrustedHTML` variants.
// TODO(lyf): Change the type to `[TreatNullAs=xxx] HTMLString` after
// https://crbug.com/1058762 has been fixed.
- [Affects=Nothing, CEReactions, RuntimeCallStatsCounter=ElementInnerHTML, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML;
- [Affects=Nothing, CEReactions, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString outerHTML;
+ [CEReactions, RuntimeCallStatsCounter=ElementInnerHTML, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML;
+ [CEReactions, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString outerHTML;
[CEReactions, RaisesException] void insertAdjacentHTML(DOMString position, HTMLString text);
// Declarative Shadow DOM getInnerHTML() function.
@@ -120,14 +120,14 @@ callback ScrollStateCallback = void (ScrollState scrollState);
void scrollTo(unrestricted double x, unrestricted double y);
void scrollBy(optional ScrollToOptions options = {});
void scrollBy(unrestricted double x, unrestricted double y);
- [Affects=Nothing] attribute unrestricted double scrollTop;
- [Affects=Nothing] attribute unrestricted double scrollLeft;
- [Affects=Nothing] readonly attribute long scrollWidth;
- [Affects=Nothing] readonly attribute long scrollHeight;
- [Affects=Nothing] readonly attribute long clientTop;
- [Affects=Nothing] readonly attribute long clientLeft;
- [Affects=Nothing] readonly attribute long clientWidth;
- [Affects=Nothing] readonly attribute long clientHeight;
+ attribute unrestricted double scrollTop;
+ attribute unrestricted double scrollLeft;
+ readonly attribute long scrollWidth;
+ readonly attribute long scrollHeight;
+ readonly attribute long clientTop;
+ readonly attribute long clientLeft;
+ readonly attribute long clientWidth;
+ readonly attribute long clientHeight;
// Typed OM
// https://drafts.css-houdini.org/css-typed-om/#inline-stylepropertymap-objects
@@ -151,7 +151,7 @@ callback ScrollStateCallback = void (ScrollState scrollState);
[RuntimeEnabled=BeforeMatchEvent] attribute EventHandler onbeforematch;
// Element Timing
- [Affects=Nothing, CEReactions, Reflect=elementtiming] attribute DOMString elementTiming;
+ [CEReactions, Reflect=elementtiming] attribute DOMString elementTiming;
};
Element includes ParentNode;
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 2cc01ae9478..dfb67536536 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
@@ -50,7 +50,8 @@ struct SameSizeAsElementRareData : NodeRareData {
};
ElementRareData::ElementRareData(NodeRenderingData* node_layout_data)
- : NodeRareData(node_layout_data, true), class_list_(nullptr) {}
+ : NodeRareData(ClassType::kElementRareData, node_layout_data),
+ class_list_(nullptr) {}
ElementRareData::~ElementRareData() {
DCHECK(!pseudo_element_data_);
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 f82d6732f28..9480f0c221f 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
@@ -51,7 +51,7 @@ class HTMLElement;
class ResizeObservation;
class ResizeObserver;
-class ElementRareData : public NodeRareData {
+class ElementRareData final : public NodeRareData {
public:
explicit ElementRareData(NodeRenderingData*);
~ElementRareData();
@@ -158,6 +158,8 @@ class ElementRareData : public NodeRareData {
bool ShouldForceLegacyLayoutForChild() const {
return should_force_legacy_layout_for_child_;
}
+ bool HasUndoStack() const { return has_undo_stack_; }
+ void SetHasUndoStack(bool value) { has_undo_stack_ = value; }
AccessibleNode* GetAccessibleNode() const { return accessible_node_.Get(); }
AccessibleNode* EnsureAccessibleNode(Element* owner_element) {
@@ -246,6 +248,7 @@ class ElementRareData : public NodeRareData {
bool did_attach_internals_ = false;
bool should_force_legacy_layout_for_child_ = false;
bool style_should_force_legacy_layout_ = false;
+ bool has_undo_stack_ = false;
};
inline LayoutSize DefaultMinimumSizeForResizing() {
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 37c1b9a1c66..3cfc91628a5 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
@@ -161,8 +161,12 @@ DispatchEventResult EventDispatcher::Dispatch() {
}
std::unique_ptr<EventTiming> eventTiming;
LocalFrame* frame = node_->GetDocument().GetFrame();
- if (frame && frame->DomWindow())
+ if (frame && frame->DomWindow()) {
eventTiming = EventTiming::Create(frame->DomWindow(), *event_);
+ // TODO(hbsong): Calculate First Input Delay for filtered events.
+ EventTiming::HandleInputDelay(frame->DomWindow(), *event_);
+ }
+
if (event_->type() == event_type_names::kChange && event_->isTrusted() &&
view_) {
view_->GetLayoutShiftTracker().NotifyChangeEvent();
@@ -226,8 +230,6 @@ DispatchEventResult EventDispatcher::Dispatch() {
}
DispatchEventPostProcess(activation_target,
pre_dispatch_event_handler_result);
- if (eventTiming)
- eventTiming->DidDispatchEvent(*event_, node_->GetDocument());
return EventTarget::GetDispatchEventResult(*event_);
}
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 40da26ff83c..b2dfc21f517 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
@@ -48,7 +48,7 @@ class CORE_EXPORT EventListener : public GarbageCollected<EventListener>,
public:
EventListener(const EventListener&) = delete;
EventListener& operator=(const EventListener&) = delete;
- virtual ~EventListener() = default;
+ ~EventListener() override = default;
// Invokes this event listener.
virtual void Invoke(ExecutionContext*, Event*) = 0;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_path.cc b/chromium/third_party/blink/renderer/core/dom/events/event_path.cc
index 7222d2944ea..8c3456289ce 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_path.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_path.cc
@@ -68,7 +68,11 @@ void EventPath::InitializeWith(Node& node, Event* event) {
}
static inline bool EventPathShouldBeEmptyFor(Node& node) {
- return node.IsPseudoElement() && !node.parentElement();
+ // Event path should be empty for orphaned pseudo elements, and nodes
+ // whose document is stopped. In corner cases (crbug.com/1210480), the node
+ // document can get detached before we can remove event listeners.
+ return (node.IsPseudoElement() && !node.parentElement()) ||
+ node.GetDocument().IsStopped();
}
void EventPath::Initialize() {
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
index 7fa5be79d87..75e38e3cd53 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
@@ -26,7 +26,6 @@
#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"
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 120ac0fcd3e..56f427f8900 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,6 +27,7 @@
#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/public/platform/task_type.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
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 9a6f75cf5ef..dce24eb1d76 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
@@ -35,8 +35,6 @@
#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/js_based_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
@@ -56,6 +54,7 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/pointer_type_names.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"
@@ -90,15 +89,6 @@ Event::PassiveMode EventPassiveMode(
return Event::PassiveMode::kPassiveDefault;
}
-Settings* WindowSettings(LocalDOMWindow* executing_window) {
- if (executing_window) {
- if (LocalFrame* frame = executing_window->GetFrame()) {
- return frame->GetSettings();
- }
- }
- return nullptr;
-}
-
bool IsTouchScrollBlockingEvent(const AtomicString& event_type) {
return event_type == event_type_names::kTouchstart ||
event_type == event_type_names::kTouchmove;
@@ -184,7 +174,8 @@ void CountFiringEventListeners(const Event& event,
if (CheckTypeThenUseCount(event, event_type_names::kPointerdown,
WebFeature::kPointerDownFired, document)) {
if (IsA<PointerEvent>(event) &&
- static_cast<const PointerEvent&>(event).pointerType() == "touch") {
+ static_cast<const PointerEvent&>(event).pointerType() ==
+ pointer_type_names::kTouch) {
UseCounter::Count(document, WebFeature::kPointerDownFiredForTouch);
}
return;
@@ -218,34 +209,6 @@ void CountFiringEventListeners(const Event& event,
}
}
-void RegisterWithScheduler(ExecutionContext* execution_context,
- const AtomicString& event_type) {
- if (!execution_context || !execution_context->GetScheduler())
- return;
- // TODO(altimin): Ideally we would also support tracking unregistration of
- // event listeners, but we don't do this for performance reasons.
- absl::optional<SchedulingPolicy::Feature> feature_for_scheduler;
- if (event_type == event_type_names::kPageshow) {
- feature_for_scheduler = SchedulingPolicy::Feature::kPageShowEventListener;
- } else if (event_type == event_type_names::kPagehide) {
- feature_for_scheduler = SchedulingPolicy::Feature::kPageHideEventListener;
- } else if (event_type == event_type_names::kBeforeunload) {
- feature_for_scheduler =
- SchedulingPolicy::Feature::kBeforeUnloadEventListener;
- } else if (event_type == event_type_names::kUnload) {
- feature_for_scheduler = SchedulingPolicy::Feature::kUnloadEventListener;
- } else if (event_type == event_type_names::kFreeze) {
- feature_for_scheduler = SchedulingPolicy::Feature::kFreezeEventListener;
- } else if (event_type == event_type_names::kResume) {
- feature_for_scheduler = SchedulingPolicy::Feature::kResumeEventListener;
- }
- if (feature_for_scheduler) {
- execution_context->GetScheduler()->RegisterStickyFeature(
- feature_for_scheduler.value(),
- {SchedulingPolicy::DisableBackForwardCache()});
- }
-}
-
} // namespace
EventTargetData::EventTargetData() = default;
@@ -408,24 +371,8 @@ void EventTarget::SetDefaultAddEventListenerOptions(
}
}
- if (Settings* settings = WindowSettings(ExecutingWindow())) {
- switch (settings->GetPassiveListenerDefault()) {
- case PassiveListenerDefault::kFalse:
- if (!options->hasPassive())
- options->setPassive(false);
- break;
- case PassiveListenerDefault::kTrue:
- if (!options->hasPassive())
- options->setPassive(true);
- break;
- case PassiveListenerDefault::kForceAllTrue:
- options->setPassive(true);
- break;
- }
- } else {
- if (!options->hasPassive())
- options->setPassive(false);
- }
+ if (!options->hasPassive())
+ options->setPassive(false);
if (!options->passive() && !options->PassiveSpecified()) {
String message_text = String::Format(
@@ -447,7 +394,6 @@ bool EventTarget::addEventListener(const AtomicString& event_type,
return addEventListener(event_type, event_listener);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool EventTarget::addEventListener(
const AtomicString& event_type,
V8EventListener* listener,
@@ -481,37 +427,6 @@ bool EventTarget::addEventListener(
NOTREACHED();
return false;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool EventTarget::addEventListener(
- const AtomicString& event_type,
- V8EventListener* listener,
- const AddEventListenerOptionsOrBoolean& options_union) {
- EventListener* event_listener = JSEventListener::CreateOrNull(listener);
-
- if (options_union.IsBoolean()) {
- return addEventListener(event_type, event_listener,
- options_union.GetAsBoolean());
- }
-
- if (options_union.IsAddEventListenerOptions()) {
- auto* resolved_options =
- MakeGarbageCollected<AddEventListenerOptionsResolved>();
- AddEventListenerOptions* options =
- options_union.GetAsAddEventListenerOptions();
- if (options->hasPassive())
- resolved_options->setPassive(options->passive());
- if (options->hasOnce())
- resolved_options->setOnce(options->once());
- if (options->hasCapture())
- resolved_options->setCapture(options->capture());
- if (options->hasSignal())
- resolved_options->setSignal(options->signal());
- return addEventListener(event_type, event_listener, resolved_options);
- }
-
- return addEventListener(event_type, event_listener);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool EventTarget::addEventListener(const AtomicString& event_type,
EventListener* listener,
@@ -615,8 +530,6 @@ void EventTarget::AddedEventListener(
}
}
- RegisterWithScheduler(GetExecutionContext(), event_type);
-
if (event_util::IsDOMMutationEventType(event_type)) {
if (ExecutionContext* context = GetExecutionContext()) {
String message_text = String::Format(
@@ -636,7 +549,6 @@ bool EventTarget::removeEventListener(const AtomicString& event_type,
return removeEventListener(event_type, event_listener);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool EventTarget::removeEventListener(
const AtomicString& event_type,
V8EventListener* listener,
@@ -660,26 +572,6 @@ bool EventTarget::removeEventListener(
NOTREACHED();
return false;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool EventTarget::removeEventListener(
- const AtomicString& event_type,
- V8EventListener* listener,
- const EventListenerOptionsOrBoolean& options_union) {
- EventListener* event_listener = JSEventListener::CreateOrNull(listener);
-
- if (options_union.IsBoolean()) {
- return removeEventListener(event_type, event_listener,
- options_union.GetAsBoolean());
- }
-
- if (options_union.IsEventListenerOptions()) {
- EventListenerOptions* options = options_union.GetAsEventListenerOptions();
- return removeEventListener(event_type, event_listener, options);
- }
-
- return removeEventListener(event_type, event_listener);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool EventTarget::removeEventListener(const AtomicString& event_type,
const EventListener* listener,
@@ -1086,6 +978,11 @@ void EventTarget::DispatchEnqueuedEvent(Event* event,
DispatchEvent(*event);
}
+void EventTargetWithInlineData::Trace(Visitor* visitor) const {
+ EventTargetData::Trace(visitor);
+ EventTarget::Trace(visitor);
+}
+
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 08d1ebbd0c6..8f633fc3b55 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
@@ -47,11 +47,9 @@
namespace blink {
-class AddEventListenerOptionsOrBoolean;
class AddEventListenerOptionsResolved;
class DOMWindow;
class Event;
-class EventListenerOptionsOrBoolean;
class ExceptionState;
class ExecutionContext;
class LocalDOMWindow;
@@ -77,15 +75,14 @@ struct FiringEventIterator {
};
using FiringEventIteratorVector = Vector<FiringEventIterator, 1>;
-class CORE_EXPORT EventTargetData final
- : public GarbageCollected<EventTargetData> {
+class CORE_EXPORT EventTargetData : public GarbageCollectedMixin {
public:
EventTargetData();
EventTargetData(const EventTargetData&) = delete;
EventTargetData& operator=(const EventTargetData&) = delete;
~EventTargetData();
- void Trace(Visitor*) const;
+ void Trace(Visitor*) const override;
EventListenerMap event_listener_map;
std::unique_ptr<FiringEventIteratorVector> firing_event_iterators;
@@ -136,16 +133,10 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
static EventTarget* Create(ScriptState*);
bool addEventListener(const AtomicString& event_type, V8EventListener*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool addEventListener(
const AtomicString& event_type,
V8EventListener* listener,
const V8UnionAddEventListenerOptionsOrBoolean* bool_or_options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool addEventListener(const AtomicString& event_type,
- V8EventListener*,
- const AddEventListenerOptionsOrBoolean&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool addEventListener(const AtomicString& event_type,
EventListener*,
bool use_capture = false);
@@ -154,16 +145,10 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
AddEventListenerOptionsResolved*);
bool removeEventListener(const AtomicString& event_type, V8EventListener*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool removeEventListener(
const AtomicString& event_type,
V8EventListener* listener,
const V8UnionBooleanOrEventListenerOptions* bool_or_options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool removeEventListener(const AtomicString& event_type,
- V8EventListener*,
- const EventListenerOptionsOrBoolean&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool removeEventListener(const AtomicString& event_type,
const EventListener*,
bool use_capture = false);
@@ -254,25 +239,21 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
friend class EventListenerIterator;
};
-class CORE_EXPORT EventTargetWithInlineData : public EventTarget {
+// Provide EventTarget with inlined EventTargetData for improved performance.
+class CORE_EXPORT EventTargetWithInlineData : public EventTarget,
+ private EventTargetData {
public:
~EventTargetWithInlineData() override = default;
- void Trace(Visitor* visitor) const override {
- visitor->Trace(event_target_data_);
- EventTarget::Trace(visitor);
- }
+ void Trace(Visitor* visitor) const override;
protected:
- EventTargetData* GetEventTargetData() final { return &event_target_data_; }
- EventTargetData& EnsureEventTargetData() final { return event_target_data_; }
-
- private:
- // 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::event_target_data_ and store it to a Member etc.
- GC_PLUGIN_IGNORE("513199") EventTargetData event_target_data_;
+ EventTargetData* GetEventTargetData() final {
+ return static_cast<EventTargetData*>(this);
+ }
+ EventTargetData& EnsureEventTargetData() final {
+ return *static_cast<EventTargetData*>(this);
+ }
};
// Macros to define an attribute event listener.
diff --git a/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.cc b/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.cc
index 9f5ab9b93aa..baab2521395 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.cc
@@ -50,6 +50,9 @@ RegisteredEventListener::RegisteredEventListener(
options->PassiveForcedForDocumentTarget()),
passive_specified_(options->PassiveSpecified()) {}
+RegisteredEventListener::RegisteredEventListener(
+ const RegisteredEventListener& that) = default;
+
RegisteredEventListener& RegisteredEventListener::operator=(
const RegisteredEventListener& that) = default;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.h b/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.h
index 2098939a962..9654dc5918d 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/registered_event_listener.h
@@ -44,6 +44,7 @@ class RegisteredEventListener final {
RegisteredEventListener();
RegisteredEventListener(EventListener* listener,
const AddEventListenerOptionsResolved* options);
+ RegisteredEventListener(const RegisteredEventListener& that);
RegisteredEventListener& operator=(const RegisteredEventListener& that);
void Trace(Visitor* visitor) const;
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 1a429bf8930..f3b5d6626f5 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
@@ -96,6 +96,10 @@ static bool IsInvalidFirstLetterLayoutObject(const LayoutObject* obj) {
return (obj->IsBR() || (obj->IsText() && To<LayoutText>(obj)->IsWordBreak()));
}
+static bool IsParentInlineLayoutObject(const LayoutObject* obj) {
+ return (obj && obj->Parent() && obj->Parent()->IsLayoutInline());
+}
+
LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
const Element& element) {
LayoutObject* parent_layout_object = nullptr;
@@ -129,17 +133,30 @@ LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
kPseudoIdFirstLetter) {
first_letter_text_layout_object =
first_letter_text_layout_object->NextSibling();
- } else if (first_letter_text_layout_object->IsText()) {
+ } else if (auto* layout_text =
+ DynamicTo<LayoutText>(first_letter_text_layout_object)) {
+ // Don't apply first letter styling to passwords and other elements
+ // obfuscated by -webkit-text-security. Also, see
+ // ShouldUpdateLayoutByReattaching() in text.cc.
+ if (layout_text->IsSecure())
+ return nullptr;
// FIXME: If there is leading punctuation in a different LayoutText than
// the first letter, we'll not apply the correct style to it.
scoped_refptr<StringImpl> str =
- To<LayoutText>(first_letter_text_layout_object)->IsTextFragment()
+ layout_text->IsTextFragment()
? To<LayoutTextFragment>(first_letter_text_layout_object)
->CompleteText()
- : To<LayoutText>(first_letter_text_layout_object)->OriginalText();
+ : layout_text->OriginalText();
if (FirstLetterLength(str.get()) ||
IsInvalidFirstLetterLayoutObject(first_letter_text_layout_object))
break;
+
+ // In case of inline level content made of punctuation and there is no
+ // sibling, we'll apply style to it.
+ if (IsParentInlineLayoutObject(first_letter_text_layout_object) &&
+ str->length() && !first_letter_text_layout_object->NextSibling())
+ break;
+
first_letter_text_layout_object =
first_letter_text_layout_object->NextSibling();
} else if (first_letter_text_layout_object->IsListMarkerIncludingAll()) {
@@ -341,6 +358,13 @@ void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects(LayoutText* fi
// FIXME: This would already have been calculated in firstLetterLayoutObject.
// Can we pass the length through?
unsigned length = FirstLetterPseudoElement::FirstLetterLength(old_text);
+
+ // In case of inline level content made of punctuation, we use
+ // first_letter_text length instead of FirstLetterLength.
+ if (IsParentInlineLayoutObject(first_letter_text) && length == 0 &&
+ first_letter_text->TextLength())
+ length = first_letter_text->TextLength();
+
unsigned remaining_length = old_text.length() - length;
// Construct a text fragment for the text after the first letter.
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 1123eec64de..8577e449e42 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
@@ -23,7 +23,7 @@ class CORE_EXPORT FrameCallback : public GarbageCollected<FrameCallback>,
public:
virtual void Trace(Visitor* visitor) const {}
const char* NameInHeapSnapshot() const override { return "FrameCallback"; }
- virtual ~FrameCallback() = default;
+ ~FrameCallback() override = default;
virtual void Invoke(double) = 0;
int Id() const { return id_; }
@@ -63,8 +63,7 @@ class CORE_EXPORT V8FrameCallback : public FrameCallback {
Member<V8FrameRequestCallback> callback_;
};
-class GC_PLUGIN_IGNORE("crbug.com/841830")
- CORE_EXPORT FrameRequestCallbackCollection final : public NameClient {
+class CORE_EXPORT FrameRequestCallbackCollection final : public NameClient {
DISALLOW_NEW();
public:
diff --git a/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.cc b/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.cc
index c5d8545fc73..7517b761a7c 100644
--- a/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.cc
+++ b/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.cc
@@ -63,7 +63,8 @@ void IdTargetObserverRegistry::NotifyObserversInternal(const AtomicString& id) {
DCHECK(!id.IsEmpty());
DCHECK(!registry_.IsEmpty());
- notifying_observers_in_set_ = registry_.at(id.Impl());
+ if (registry_.Contains(id.Impl()))
+ notifying_observers_in_set_ = registry_.at(id.Impl());
if (!notifying_observers_in_set_)
return;
@@ -81,10 +82,9 @@ void IdTargetObserverRegistry::NotifyObserversInternal(const AtomicString& id) {
}
bool IdTargetObserverRegistry::HasObservers(const AtomicString& id) const {
- if (id.IsEmpty() || registry_.IsEmpty())
+ if (id.IsEmpty() || registry_.IsEmpty() || !registry_.Contains(id.Impl()))
return false;
- ObserverSet* set = registry_.at(id.Impl());
- return set && !set->IsEmpty();
+ return !registry_.at(id.Impl())->IsEmpty();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.h b/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.h
index 997eb12d21d..4d8b18edac3 100644
--- a/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.h
+++ b/chromium/third_party/blink/renderer/core/dom/id_target_observer_registry.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ID_TARGET_OBSERVER_REGISTRY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ID_TARGET_OBSERVER_REGISTRY_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
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 f434b5cb0bc..1b34883f0ad 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
@@ -30,6 +30,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
@@ -80,11 +81,22 @@ class LayoutTreeBuilder {
// next layout object. Otherwise we would need to add code to various
// AddChild() implementations to walk up the tree to find the correct
// layout tree parent/siblings.
- if (next && next->IsText() && next->Parent()->IsAnonymous() &&
- next->Parent()->IsInline()) {
- return next->Parent();
- }
- return next;
+ if (!next || !next->IsText())
+ return next;
+ auto* const parent = next->Parent();
+ if (!IsAnonymousInline(parent))
+ return next;
+ if (!LIKELY(parent->IsLayoutNGTextCombine()))
+ return parent;
+ auto* const text_combine_parent = parent->Parent();
+ if (IsAnonymousInline(text_combine_parent))
+ return text_combine_parent;
+ return parent;
+ }
+
+ static bool IsAnonymousInline(const LayoutObject* layout_object) {
+ return layout_object && layout_object->IsAnonymous() &&
+ layout_object->IsInline();
}
NodeType* node_;
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 bfafac41691..fbbbfd529d5 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc
@@ -32,6 +32,7 @@
#include <algorithm>
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h"
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 5c177040c0d..c1ec547e1dd 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
@@ -81,7 +81,7 @@ class CORE_EXPORT MutationObserver final
class CORE_EXPORT Delegate : public GarbageCollected<Delegate>,
public NameClient {
public:
- virtual ~Delegate() = default;
+ ~Delegate() override = default;
virtual ExecutionContext* GetExecutionContext() const = 0;
virtual void Deliver(const MutationRecordVector& records,
MutationObserver&) = 0;
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 28a7ead5bc9..1e8934ef1c2 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
@@ -51,7 +51,7 @@ class CORE_EXPORT MutationObserverRegistration final
Node*,
MutationObserverOptions,
const HashSet<AtomicString>& attribute_filter);
- ~MutationObserverRegistration();
+ ~MutationObserverRegistration() override;
void ResetObservation(MutationObserverOptions,
const HashSet<AtomicString>& attribute_filter);
diff --git a/chromium/third_party/blink/renderer/core/dom/named_node_map.idl b/chromium/third_party/blink/renderer/core/dom/named_node_map.idl
index 63bb2867eca..08a87490684 100644
--- a/chromium/third_party/blink/renderer/core/dom/named_node_map.idl
+++ b/chromium/third_party/blink/renderer/core/dom/named_node_map.idl
@@ -24,7 +24,7 @@
LegacyUnenumerableNamedProperties,
Exposed=Window
] interface NamedNodeMap {
- [Affects=Nothing] readonly attribute unsigned long length;
+ readonly attribute unsigned long length;
[Affects=Nothing, MeasureAs=NamedNodeMapItem] getter Attr? item(unsigned long index);
[Affects=Nothing, MeasureAs=NamedNodeMapGetNamedItem] getter Attr? getNamedItem(DOMString name);
[MeasureAs=NamedNodeMapGetNamedItemNS] Attr? getNamedItemNS(DOMString? namespaceURI, DOMString localName);
diff --git a/chromium/third_party/blink/renderer/core/dom/node.cc b/chromium/third_party/blink/renderer/core/dom/node.cc
index b5f6dda08ac..d2681307938 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node.cc
@@ -29,8 +29,6 @@
#include <algorithm>
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/node_or_string_or_trusted_script.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_get_root_node_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_node_string_trustedscript.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedscript.h"
@@ -108,6 +106,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
@@ -182,10 +181,11 @@ struct SameSizeAsNode : EventTarget {
uint32_t node_flags_;
Member<void*> willbe_member_[4];
Member<NodeData> member_;
-#if !DCHECK_IS_ON()
// Increasing size of Member increases size of Node.
- ASSERT_SIZE(Member<NodeData>, void*);
-#endif // !DCHECK_IS_ON()
+ static_assert(kBlinkGCHasDebugChecks ||
+ ::WTF::internal::SizesEqual<sizeof(Member<NodeData>),
+ sizeof(void*)>::value,
+ "Member<NodeData> should stay small");
};
ASSERT_SIZE(Node, SameSizeAsNode);
@@ -766,7 +766,6 @@ Node* Node::appendChild(Node* new_child) {
return appendChild(new_child, ASSERT_NO_EXCEPTION);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static bool IsNodeInNodes(
const Node* const node,
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes) {
@@ -776,25 +775,10 @@ static bool IsNodeInNodes(
}
return false;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-static bool IsNodeInNodes(
- const Node* const node,
- const HeapVector<NodeOrStringOrTrustedScript>& nodes) {
- for (const NodeOrStringOrTrustedScript& node_or_string : nodes) {
- if (node_or_string.IsNode() && node_or_string.GetAsNode() == node)
- return true;
- }
- return false;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Node* FindViablePreviousSibling(
const Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
for (Node* sibling = node.previousSibling(); sibling;
sibling = sibling->previousSibling()) {
@@ -806,11 +790,7 @@ static Node* FindViablePreviousSibling(
static Node* FindViableNextSibling(
const Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
for (Node* sibling = node.nextSibling(); sibling;
sibling = sibling->nextSibling()) {
@@ -820,7 +800,6 @@ static Node* FindViableNextSibling(
return nullptr;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Node* NodeOrStringToNode(
const V8UnionNodeOrStringOrTrustedScript* node_or_string,
Document& document,
@@ -862,54 +841,11 @@ static Node* NodeOrStringToNode(
return nullptr;
return Text::Create(document, string_value);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-static Node* NodeOrStringToNode(
- const NodeOrStringOrTrustedScript& node_or_string,
- Document& document,
- bool needs_trusted_types_check,
- ExceptionState& exception_state) {
- if (!needs_trusted_types_check) {
- // Without trusted type checks, we simply extract the string from whatever
- // constituent type we find.
- if (node_or_string.IsNode())
- return node_or_string.GetAsNode();
- if (node_or_string.IsTrustedScript()) {
- return Text::Create(document,
- node_or_string.GetAsTrustedScript()->toString());
- }
- return Text::Create(document, node_or_string.GetAsString());
- }
-
- // With trusted type checks, we can process trusted script or non-text nodes
- // directly. Strings or text nodes need to be checked.
- if (node_or_string.IsNode() && !node_or_string.GetAsNode()->IsTextNode())
- return node_or_string.GetAsNode();
-
- if (node_or_string.IsTrustedScript()) {
- return Text::Create(document,
- node_or_string.GetAsTrustedScript()->toString());
- }
-
- String string_value = node_or_string.IsString()
- ? node_or_string.GetAsString()
- : node_or_string.GetAsNode()->textContent();
-
- string_value = TrustedTypesCheckForScript(
- string_value, document.GetExecutionContext(), exception_state);
- if (exception_state.HadException())
- return nullptr;
- return Text::Create(document, string_value);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Returns nullptr if an exception was thrown.
static Node* ConvertNodesIntoNode(
const Node* parent,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Document& document,
ExceptionState& exception_state) {
bool needs_check = IsA<HTMLScriptElement>(parent) &&
@@ -932,11 +868,7 @@ static Node* ConvertNodesIntoNode(
}
void Node::Prepend(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto* this_node = DynamicTo<ContainerNode>(this);
if (!this_node) {
@@ -948,15 +880,11 @@ void Node::Prepend(
if (Node* node =
ConvertNodesIntoNode(this, nodes, GetDocument(), exception_state))
- this_node->InsertBefore(node, firstChild(), exception_state);
+ this_node->InsertBefore(node, this_node->firstChild(), exception_state);
}
void Node::Append(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto* this_node = DynamicTo<ContainerNode>(this);
if (!this_node) {
@@ -972,92 +900,54 @@ void Node::Append(
}
void Node::Before(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
- Node* parent = parentNode();
+ ContainerNode* parent = parentNode();
if (!parent)
return;
- auto* parent_node = DynamicTo<ContainerNode>(parent);
- if (!parent_node) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kHierarchyRequestError,
- "This node type does not support this method.");
- return;
- }
Node* viable_previous_sibling = FindViablePreviousSibling(*this, nodes);
if (Node* node =
ConvertNodesIntoNode(parent, nodes, GetDocument(), exception_state)) {
- parent_node->InsertBefore(node,
- viable_previous_sibling
- ? viable_previous_sibling->nextSibling()
- : parent->firstChild(),
- exception_state);
+ parent->InsertBefore(node,
+ viable_previous_sibling
+ ? viable_previous_sibling->nextSibling()
+ : parent->firstChild(),
+ exception_state);
}
}
void Node::After(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
- Node* parent = parentNode();
+ ContainerNode* parent = parentNode();
if (!parent)
return;
- auto* parent_node = DynamicTo<ContainerNode>(parent);
- if (!parent_node) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kHierarchyRequestError,
- "This node type does not support this method.");
- return;
- }
Node* viable_next_sibling = FindViableNextSibling(*this, nodes);
if (Node* node =
ConvertNodesIntoNode(parent, nodes, GetDocument(), exception_state))
- parent_node->InsertBefore(node, viable_next_sibling, exception_state);
+ parent->InsertBefore(node, viable_next_sibling, exception_state);
}
void Node::ReplaceWith(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
- Node* parent = parentNode();
+ ContainerNode* parent = parentNode();
if (!parent)
return;
- auto* parent_node = DynamicTo<ContainerNode>(parent);
- if (!parent_node) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kHierarchyRequestError,
- "This node type does not support this method.");
- return;
- }
-
Node* viable_next_sibling = FindViableNextSibling(*this, nodes);
Node* node =
ConvertNodesIntoNode(parent, nodes, GetDocument(), exception_state);
if (exception_state.HadException())
return;
- if (parent_node == parentNode())
- parent_node->ReplaceChild(node, this, exception_state);
+ if (parent == parentNode())
+ parent->ReplaceChild(node, this, exception_state);
else
- parent_node->InsertBefore(node, viable_next_sibling, exception_state);
+ parent->InsertBefore(node, viable_next_sibling, exception_state);
}
// https://dom.spec.whatwg.org/#dom-parentnode-replacechildren
void Node::ReplaceChildren(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
auto* this_node = DynamicTo<ContainerNode>(this);
if (!this_node) {
@@ -1081,13 +971,13 @@ void Node::ReplaceChildren(
// 3. Replace all with node within this.
ChildListMutationScope mutation(*this);
- while (Node* first_child = firstChild()) {
- removeChild(first_child, exception_state);
+ while (Node* first_child = this_node->firstChild()) {
+ this_node->RemoveChild(first_child, exception_state);
if (exception_state.HadException())
return;
}
- appendChild(node, exception_state);
+ this_node->AppendChild(node, exception_state);
}
void Node::remove(ExceptionState& exception_state) {
@@ -2120,8 +2010,6 @@ String Node::textContent(bool convert_brs_to_newlines) const {
return content.ToString();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionStringOrTrustedScript* Node::textContentForBinding() const {
const String& value = textContent();
if (value.IsNull())
@@ -2144,28 +2032,6 @@ void Node::setTextContentForBinding(const V8UnionStringOrTrustedScript* value,
NOTREACHED();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void Node::textContentForBinding(StringOrTrustedScript& result) {
- String value = textContent();
- if (!value.IsNull())
- result.SetString(value);
-}
-
-void Node::setTextContentForBinding(
- const StringOrTrustedScript& string_or_trusted_script,
- ExceptionState& exception_state) {
- String value =
- string_or_trusted_script.IsString()
- ? string_or_trusted_script.GetAsString()
- : string_or_trusted_script.IsTrustedScript()
- ? string_or_trusted_script.GetAsTrustedScript()->toString()
- : g_empty_string;
- setTextContent(value);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void Node::setTextContent(const String& text) {
switch (getNodeType()) {
case kAttributeNode:
@@ -2836,11 +2702,24 @@ EventTargetData* Node::GetEventTargetData() {
return HasEventTargetData() ? GetEventTargetDataMap().at(this) : nullptr;
}
+namespace {
+
+// Helper object to allocate EventTargetData which is otherwise only used
+// through EventTargetWithInlineData.
+class EventTargetDataObject final
+ : public GarbageCollected<EventTargetDataObject>,
+ public EventTargetData {
+ public:
+ void Trace(Visitor* visitor) const final { EventTargetData::Trace(visitor); }
+};
+
+} // namespace
+
EventTargetData& Node::EnsureEventTargetData() {
if (HasEventTargetData())
return *GetEventTargetDataMap().at(this);
DCHECK(!GetEventTargetDataMap().Contains(this));
- EventTargetData* data = MakeGarbageCollected<EventTargetData>();
+ auto* data = MakeGarbageCollected<EventTargetDataObject>();
GetEventTargetDataMap().Set(this, data);
SetHasEventTargetData(true);
return *data;
@@ -3160,7 +3039,7 @@ bool Node::HasActivationBehavior() const {
return false;
}
-bool Node::WillRespondToMouseMoveEvents() {
+bool Node::WillRespondToMouseMoveEvents() const {
if (IsDisabledFormControl(this))
return false;
return HasEventListeners(event_type_names::kMousemove) ||
@@ -3222,8 +3101,15 @@ HTMLSlotElement* Node::AssignedSlot() const {
// dirty. RecalcAssignment() is almost no-op if we don't need to recalc.
root->GetSlotAssignment().RecalcAssignment();
if (FlatTreeNodeData* data = GetFlatTreeNodeData()) {
- DCHECK_EQ(root->AssignedSlotFor(*this), data->AssignedSlot())
- << "Assigned slot mismatch for node " << this;
+#if DCHECK_IS_ON()
+ // User agent shadow slot assignment (FindSlotInUserAgentShadow()) will
+ // re-check the DOM tree, and if we're in the process of removing nodes
+ // from the tree, there could be a mismatch here.
+ if (root->SupportsNameBasedSlotAssignment()) {
+ DCHECK_EQ(root->AssignedSlotFor(*this), data->AssignedSlot())
+ << "Assigned slot mismatch for node " << this;
+ }
+#endif
return data->AssignedSlot();
}
return nullptr;
@@ -3449,8 +3335,17 @@ void Node::FlatTreeParentChanged() {
void Node::AddCandidateDirectionalityForSlot() {
ShadowRoot* root = ShadowRootOfParent();
- if (!root || !root->HasSlotAssignment())
- return;
+ if (!root || !root->HasSlotAssignment()) {
+ // We should add this node as a candidate that needs to recalculate its
+ // direcationality if the parent slot has the dir auto flag.
+ if (auto* parent_slot = DynamicTo<HTMLSlotElement>(parentElement())) {
+ if (parent_slot->SelfOrAncestorHasDirAutoAttribute())
+ root = ContainingShadowRoot();
+ }
+
+ if (!root)
+ return;
+ }
root->GetSlotAssignment().GetCandidateDirectionality().insert(this);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/node.h b/chromium/third_party/blink/renderer/core/dom/node.h
index 8fa516f2591..ab0a31b041d 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.h
+++ b/chromium/third_party/blink/renderer/core/dom/node.h
@@ -27,7 +27,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
@@ -67,7 +66,6 @@ class MutationObserver;
class MutationObserverRegistration;
class NodeList;
class NodeListsNodeData;
-class NodeOrStringOrTrustedScript;
class NodeRareData;
class QualifiedName;
class RegisteredEventListener;
@@ -79,7 +77,6 @@ class ShadowRoot;
template <typename NodeType>
class StaticNodeTypeList;
using StaticNodeList = StaticNodeTypeList<Node>;
-class StringOrTrustedScript;
class StyleChangeReasonForTracing;
class V8ScrollStateCallback;
class V8UnionNodeOrStringOrTrustedScript;
@@ -240,7 +237,6 @@ class CORE_EXPORT Node : public EventTarget {
// https://dom.spec.whatwg.org/#concept-closed-shadow-hidden
bool IsClosedShadowHiddenFrom(const Node&) const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Prepend(
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
ExceptionState& exception_state);
@@ -259,16 +255,6 @@ class CORE_EXPORT Node : public EventTarget {
void ReplaceChildren(
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void Prepend(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
- void Append(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
- void Before(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
- void After(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
- void ReplaceWith(const HeapVector<NodeOrStringOrTrustedScript>&,
- ExceptionState&);
- void ReplaceChildren(const HeapVector<NodeOrStringOrTrustedScript>&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void remove(ExceptionState&);
void remove();
@@ -304,16 +290,10 @@ class CORE_EXPORT Node : public EventTarget {
String textContent(bool convert_brs_to_newlines = false) const;
virtual void setTextContent(const String&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionStringOrTrustedScript* textContentForBinding() const;
virtual void setTextContentForBinding(
const V8UnionStringOrTrustedScript* value,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void textContentForBinding(StringOrTrustedScript& result);
- virtual void setTextContentForBinding(const StringOrTrustedScript&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool SupportsAltText();
@@ -751,10 +731,10 @@ class CORE_EXPORT Node : public EventTarget {
// Note that the following 'inline' functions are not defined in this header,
// but in node_computed_style.h. Please include that file if you want to use
// these functions.
- ComputedStyle* MutableComputedStyleForEditingDeprecated() const;
- const ComputedStyle* GetComputedStyle() const;
- const ComputedStyle* ParentComputedStyle() const;
- const ComputedStyle& ComputedStyleRef() const;
+ inline ComputedStyle* MutableComputedStyleForEditingDeprecated() const;
+ inline const ComputedStyle* GetComputedStyle() const;
+ inline const ComputedStyle* ParentComputedStyle() const;
+ inline const ComputedStyle& ComputedStyleRef() const;
bool ShouldSkipMarkingStyleDirty() const;
const ComputedStyle* EnsureComputedStyle(
@@ -839,7 +819,7 @@ class CORE_EXPORT Node : public EventTarget {
void ClearFlatTreeNodeData();
void ClearFlatTreeNodeDataIfHostChanged(const ContainerNode& parent);
- virtual bool WillRespondToMouseMoveEvents();
+ virtual bool WillRespondToMouseMoveEvents() const;
virtual bool WillRespondToMouseClickEvents();
enum ShadowTreesTreatment {
diff --git a/chromium/third_party/blink/renderer/core/dom/node.idl b/chromium/third_party/blink/renderer/core/dom/node.idl
index 5609ad34dce..f3db8424f6d 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.idl
+++ b/chromium/third_party/blink/renderer/core/dom/node.idl
@@ -35,8 +35,8 @@
const unsigned short DOCUMENT_TYPE_NODE = 10;
const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
const unsigned short NOTATION_NODE = 12; // historical
- [Affects=Nothing, ImplementedAs=getNodeType] readonly attribute unsigned short nodeType;
- [Affects=Nothing, RuntimeCallStatsCounter=NodeName] readonly attribute DOMString nodeName;
+ [ImplementedAs=getNodeType] readonly attribute unsigned short nodeType;
+ [RuntimeCallStatsCounter=NodeName] readonly attribute DOMString nodeName;
readonly attribute USVString baseURI;
@@ -44,21 +44,21 @@
[RuntimeEnabled=ScrollCustomization] void setApplyScroll(ScrollStateCallback scrollStateCallback, NativeScrollBehavior nativeScrollBehavior);
[RuntimeEnabled=ScrollCustomization] void setDistributeScroll(ScrollStateCallback scrollStateCallback, NativeScrollBehavior nativeScrollBehavior);
- [Affects=Nothing, Measure] readonly attribute boolean isConnected;
- [Affects=Nothing, PerWorldBindings] readonly attribute Document? ownerDocument;
- [Affects=Nothing, PerWorldBindings] readonly attribute Node? parentNode;
- [Affects=Nothing, PerWorldBindings] readonly attribute Element? parentElement;
+ [Measure] readonly attribute boolean isConnected;
+ [PerWorldBindings] readonly attribute Document? ownerDocument;
+ [PerWorldBindings] readonly attribute Node? parentNode;
+ [PerWorldBindings] readonly attribute Element? parentElement;
[Affects=Nothing, ImplementedAs=hasChildren] boolean hasChildNodes();
- [Affects=Nothing, SameObject, PerWorldBindings] readonly attribute NodeList childNodes;
- [Affects=Nothing, PerWorldBindings] readonly attribute Node? firstChild;
- [Affects=Nothing, PerWorldBindings] readonly attribute Node? lastChild;
- [Affects=Nothing, PerWorldBindings] readonly attribute Node? previousSibling;
- [Affects=Nothing, PerWorldBindings] readonly attribute Node? nextSibling;
+ [SameObject, PerWorldBindings] readonly attribute NodeList childNodes;
+ [PerWorldBindings] readonly attribute Node? firstChild;
+ [PerWorldBindings] readonly attribute Node? lastChild;
+ [PerWorldBindings] readonly attribute Node? previousSibling;
+ [PerWorldBindings] readonly attribute Node? nextSibling;
[MeasureAs=NodeGetRootNode] Node getRootNode(optional GetRootNodeOptions options = {});
- [Affects=Nothing, CEReactions] attribute DOMString? nodeValue;
+ [CEReactions] attribute DOMString? nodeValue;
- [Affects=Nothing, CEReactions, ImplementedAs=textContentForBinding, RaisesException=Setter] attribute (DOMString or TrustedScript)? textContent;
+ [CEReactions, ImplementedAs=textContentForBinding, RaisesException=Setter] attribute (DOMString or TrustedScript)? textContent;
[CEReactions] void normalize();
[NewObject, DoNotTestNewObject, CEReactions, RaisesException] Node cloneNode(optional boolean deep = false);
diff --git a/chromium/third_party/blink/renderer/core/dom/node_list.idl b/chromium/third_party/blink/renderer/core/dom/node_list.idl
index 2c3f716f590..59780eef5f5 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_list.idl
+++ b/chromium/third_party/blink/renderer/core/dom/node_list.idl
@@ -24,6 +24,6 @@
Exposed=Window
] interface NodeList {
[Affects=Nothing] getter Node? item(unsigned long index);
- [Affects=Nothing] readonly attribute unsigned long length;
+ readonly attribute unsigned long length;
iterable<Node>;
};
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 f2457b59bc8..52ba9da0bf2 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
@@ -112,8 +112,11 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> {
template <typename T>
T* Cached(CollectionType collection_type) {
- return static_cast<T*>(atomic_name_caches_.at(NamedNodeListKey(
- collection_type, CSSSelector::UniversalSelectorAtom())));
+ auto key =
+ NamedNodeListKey(collection_type, CSSSelector::UniversalSelectorAtom());
+ return static_cast<T*>(atomic_name_caches_.Contains(key)
+ ? atomic_name_caches_.at(key)
+ : nullptr);
}
TagCollectionNS* AddCache(ContainerNode& node,
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 fed737f8efb..f110a3f6296 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
@@ -79,20 +79,23 @@ void NodeMutationObserverData::RemoveRegistration(
}
void NodeData::Trace(Visitor* visitor) const {
- if (bit_field_.get_concurrently<IsRareData>()) {
- if (bit_field_.get_concurrently<IsElementRareData>())
- static_cast<const ElementRareData*>(this)->TraceAfterDispatch(visitor);
- else
- static_cast<const NodeRareData*>(this)->TraceAfterDispatch(visitor);
- } else {
- static_cast<const NodeRenderingData*>(this)->TraceAfterDispatch(visitor);
+ switch (GetClassType()) {
+ case ClassType::kNodeRareData:
+ To<NodeRareData>(this)->TraceAfterDispatch(visitor);
+ break;
+ case ClassType::kElementRareData:
+ To<ElementRareData>(this)->TraceAfterDispatch(visitor);
+ break;
+ case ClassType::kNodeRenderingData:
+ To<NodeRenderingData>(this)->TraceAfterDispatch(visitor);
+ break;
}
}
NodeRenderingData::NodeRenderingData(
LayoutObject* layout_object,
scoped_refptr<const ComputedStyle> computed_style)
- : NodeData(false, false),
+ : NodeData(ClassType::kNodeRenderingData),
layout_object_(layout_object),
computed_style_(computed_style) {}
@@ -109,6 +112,10 @@ NodeRenderingData& NodeRenderingData::SharedEmptyData() {
return *shared_empty_data;
}
+void NodeRenderingData::TraceAfterDispatch(Visitor* visitor) const {
+ NodeData::TraceAfterDispatch(visitor);
+}
+
void NodeRareData::RegisterScrollTimeline(ScrollTimeline* timeline) {
if (!scroll_timelines_) {
scroll_timelines_ =
@@ -129,13 +136,6 @@ void NodeRareData::TraceAfterDispatch(blink::Visitor* visitor) const {
NodeData::TraceAfterDispatch(visitor);
}
-void NodeRareData::FinalizeGarbageCollectedObject() {
- if (bit_field_.get<IsElementRareData>())
- static_cast<ElementRareData*>(this)->~ElementRareData();
- else
- this->~NodeRareData();
-}
-
void NodeRareData::IncrementConnectedSubframeCount() {
SECURITY_CHECK((connected_frame_count_ + 1) <= Page::MaxNumberOfFrames());
++connected_frame_count_;
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 3ea8cc3a9e9..d9e0238cee2 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
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/wtf/bit_field.h"
#include "third_party/blink/renderer/platform/wtf/buildflags.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
@@ -34,10 +35,13 @@ namespace blink {
class ComputedStyle;
enum class DynamicRestyleFlags;
enum class ElementFlags;
+class ElementRareData;
class FlatTreeNodeData;
class LayoutObject;
class MutationObserverRegistration;
class NodeListsNodeData;
+class NodeRenderingData;
+class NodeRareData;
class ScrollTimeline;
class NodeMutationObserverData final
@@ -67,45 +71,78 @@ class NodeMutationObserverData final
HeapHashSet<Member<MutationObserverRegistration>> transient_registry_;
};
-class GC_PLUGIN_IGNORE(
- "GC plugin reports that TraceAfterDispatch is not called but it is called "
- "by both NodeRareDate::TraceAfterDispatch and "
- "NodeRenderingData::TraceAfterDispatch.") NodeData
- : public GarbageCollected<NodeData> {
+class NodeData : public GarbageCollected<NodeData> {
public:
- NodeData(bool is_rare_data, bool is_element_rare_data)
- : connected_frame_count_(0),
- element_flags_(0),
- bit_field_(RestyleFlags::encode(0) |
- IsElementRareData::encode(is_element_rare_data) |
- IsRareData::encode(is_rare_data)) {
- DCHECK(!is_element_rare_data || is_rare_data);
- }
- void Trace(Visitor*) const;
- void TraceAfterDispatch(blink::Visitor*) const {}
-
enum {
kConnectedFrameCountBits = 10, // Must fit Page::maxNumberOfFrames.
kNumberOfElementFlags = 6,
kNumberOfDynamicRestyleFlags = 14
};
+ enum class ClassType : uint8_t {
+ kNodeRareData,
+ kElementRareData,
+ kNodeRenderingData,
+ kLastType = kNodeRenderingData
+ };
+
+ void Trace(Visitor*) const;
+ void TraceAfterDispatch(blink::Visitor*) const {}
+
protected:
using BitField = WTF::ConcurrentlyReadBitField<uint16_t>;
using RestyleFlags =
BitField::DefineFirstValue<uint16_t, kNumberOfDynamicRestyleFlags>;
- using IsElementRareData = RestyleFlags::
- DefineNextValue<bool, 1, WTF::BitFieldValueConstness::kConst>;
- using IsRareData = IsElementRareData::
- DefineNextValue<bool, 1, WTF::BitFieldValueConstness::kConst>;
+ static constexpr size_t kClassTypeBits = 2;
+ static_assert(static_cast<size_t>(ClassType::kLastType) <
+ ((size_t{1} << kClassTypeBits)),
+ "Too many subtypes to fit into bitfield.");
+ using ClassTypeData =
+ RestyleFlags::DefineNextValue<uint8_t,
+ kClassTypeBits,
+ WTF::BitFieldValueConstness::kConst>;
+
+ explicit NodeData(ClassType sub_type)
+ : connected_frame_count_(0),
+ element_flags_(0),
+ bit_field_(RestyleFlags::encode(0) |
+ ClassTypeData::encode(static_cast<uint8_t>(sub_type))) {}
+
+ ClassType GetClassType() const {
+ return static_cast<ClassType>(bit_field_.get_concurrently<ClassTypeData>());
+ }
uint16_t connected_frame_count_ : kConnectedFrameCountBits;
uint16_t element_flags_ : kNumberOfElementFlags;
BitField bit_field_;
+
+ friend struct DowncastTraits<NodeRareData>;
+ friend struct DowncastTraits<NodeRenderingData>;
+ friend struct DowncastTraits<ElementRareData>;
+};
+
+template <>
+struct DowncastTraits<NodeRenderingData> {
+ static bool AllowFrom(const NodeData& node_data) {
+ return node_data.GetClassType() == NodeData::ClassType::kNodeRenderingData;
+ }
+};
+
+template <>
+struct DowncastTraits<NodeRareData> {
+ static bool AllowFrom(const NodeData& node_data) {
+ return node_data.GetClassType() == NodeData::ClassType::kNodeRareData;
+ }
};
-class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.")
- NodeRenderingData final : public NodeData {
+template <>
+struct DowncastTraits<ElementRareData> {
+ static bool AllowFrom(const NodeData& node_data) {
+ return node_data.GetClassType() == NodeData::ClassType::kElementRareData;
+ }
+};
+
+class NodeRenderingData final : public NodeData {
public:
NodeRenderingData(LayoutObject*,
scoped_refptr<const ComputedStyle> computed_style);
@@ -126,20 +163,17 @@ class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.")
static NodeRenderingData& SharedEmptyData();
bool IsSharedEmptyData() { return this == &SharedEmptyData(); }
- void TraceAfterDispatch(Visitor* visitor) const {
- NodeData::TraceAfterDispatch(visitor);
- }
+ void TraceAfterDispatch(Visitor* visitor) const;
private:
LayoutObject* layout_object_;
scoped_refptr<const ComputedStyle> computed_style_;
};
-class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.") NodeRareData
- : public NodeData {
+class NodeRareData : public NodeData {
public:
explicit NodeRareData(NodeRenderingData* node_layout_data)
- : NodeRareData(node_layout_data, false) {}
+ : NodeRareData(ClassType::kNodeRareData, node_layout_data) {}
NodeRareData(const NodeRareData&) = delete;
NodeRareData& operator=(const NodeRareData&) = delete;
@@ -204,16 +238,14 @@ class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.") NodeRareData
bool HasRestyleFlags() const { return bit_field_.get<RestyleFlags>(); }
void ClearRestyleFlags() { bit_field_.set<RestyleFlags>(0); }
- void TraceAfterDispatch(blink::Visitor*) const;
- void FinalizeGarbageCollectedObject();
void RegisterScrollTimeline(ScrollTimeline*);
void UnregisterScrollTimeline(ScrollTimeline*);
+ void TraceAfterDispatch(blink::Visitor*) const;
+
protected:
- explicit NodeRareData(NodeRenderingData* node_layout_data,
- bool is_element_rare_data)
- : NodeData(true, is_element_rare_data),
- node_layout_data_(node_layout_data) {
+ NodeRareData(ClassType class_type, NodeRenderingData* node_layout_data)
+ : NodeData(class_type), node_layout_data_(node_layout_data) {
CHECK_NE(node_layout_data, nullptr);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/node_traversal.cc b/chromium/third_party/blink/renderer/core/dom/node_traversal.cc
index d45ad20f352..90ca86e0607 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_traversal.cc
@@ -47,14 +47,10 @@ Node* NodeTraversal::NextIncludingPseudo(const Node& current,
const Node* stay_within) {
if (Node* next = current.PseudoAwareFirstChild())
return next;
- if (current == stay_within)
- return nullptr;
- if (Node* next = current.PseudoAwareNextSibling())
- return next;
- for (Node& parent : AncestorsOf(current)) {
- if (parent == stay_within)
+ for (Node& node : InclusiveAncestorsOf(current)) {
+ if (node == stay_within)
return nullptr;
- if (Node* next = parent.PseudoAwareNextSibling())
+ if (Node* next = node.PseudoAwareNextSibling())
return next;
}
return nullptr;
@@ -63,14 +59,10 @@ Node* NodeTraversal::NextIncludingPseudo(const Node& current,
Node* NodeTraversal::NextIncludingPseudoSkippingChildren(
const Node& current,
const Node* stay_within) {
- if (current == stay_within)
- return nullptr;
- if (Node* next = current.PseudoAwareNextSibling())
- return next;
- for (Node& parent : AncestorsOf(current)) {
- if (parent == stay_within)
+ for (Node& node : InclusiveAncestorsOf(current)) {
+ if (node == stay_within)
return nullptr;
- if (Node* next = parent.PseudoAwareNextSibling())
+ if (Node* next = node.PseudoAwareNextSibling())
return next;
}
return nullptr;
@@ -138,15 +130,11 @@ Node* NodeTraversal::PreviousAbsoluteSiblingIncludingPseudo(
Node* NodeTraversal::PreviousAbsoluteSibling(const Node& current,
const Node* stay_within) {
- if (current == stay_within)
- return nullptr;
- if (current.previousSibling())
- return current.previousSibling();
- for (Node& parent : AncestorsOf(current)) {
- if (parent == stay_within)
+ for (Node& node : InclusiveAncestorsOf(current)) {
+ if (node == stay_within)
return nullptr;
- if (parent.previousSibling())
- return parent.previousSibling();
+ if (Node* prev = node.previousSibling())
+ return prev;
}
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/node_traversal.h b/chromium/third_party/blink/renderer/core/dom/node_traversal.h
index 862f37c2718..94a9b44ad15 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_traversal.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_traversal.h
@@ -36,7 +36,7 @@
namespace blink {
-class NodeTraversal {
+class CORE_EXPORT NodeTraversal {
STATIC_ONLY(NodeTraversal);
public:
@@ -61,9 +61,8 @@ class NodeTraversal {
}
// Like next, but skips children and starts with the next sibling.
- CORE_EXPORT static Node* NextSkippingChildren(const Node&);
- CORE_EXPORT static Node* NextSkippingChildren(const Node&,
- const Node* stay_within);
+ static Node* NextSkippingChildren(const Node&);
+ static Node* NextSkippingChildren(const Node&, const Node* stay_within);
static Node* FirstWithin(const Node& current) { return current.firstChild(); }
@@ -89,23 +88,20 @@ class NodeTraversal {
const Node* stay_within = nullptr);
// Pre-order traversal including the pseudo-elements.
- CORE_EXPORT static Node* PreviousIncludingPseudo(
- const Node&,
- const Node* stay_within = nullptr);
- CORE_EXPORT static Node* NextIncludingPseudo(
- const Node&,
- const Node* stay_within = nullptr);
+ static Node* PreviousIncludingPseudo(const Node&,
+ const Node* stay_within = nullptr);
+ static Node* NextIncludingPseudo(const Node&,
+ const Node* stay_within = nullptr);
// See comment for |FlatTreeTraversal::PreviousAbsoluteSibling| for details.
- CORE_EXPORT static Node* PreviousAbsoluteSiblingIncludingPseudo(
+ static Node* PreviousAbsoluteSiblingIncludingPseudo(
const Node&,
const Node* stay_within = nullptr);
- CORE_EXPORT static Node* NextIncludingPseudoSkippingChildren(
+ static Node* NextIncludingPseudoSkippingChildren(
const Node&,
const Node* stay_within = nullptr);
- CORE_EXPORT static Node* NextAncestorSibling(const Node&);
- CORE_EXPORT static Node* NextAncestorSibling(const Node&,
- const Node* stay_within);
+ static Node* NextAncestorSibling(const Node&);
+ static Node* NextAncestorSibling(const Node&, const Node* stay_within);
static Node& HighestAncestorOrSelf(const Node&);
// Children traversal.
diff --git a/chromium/third_party/blink/renderer/core/dom/node_traversal_test.cc b/chromium/third_party/blink/renderer/core/dom/node_traversal_test.cc
new file mode 100644
index 00000000000..e14b7bab903
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/node_traversal_test.cc
@@ -0,0 +1,412 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/dom/node_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/text.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/html/html_head_element.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+namespace node_traversal_test {
+
+namespace {
+
+template <class T>
+HeapVector<Member<Node>> CollectFromIterable(T iterable) {
+ HeapVector<Member<Node>> nodes;
+ for (auto& node : iterable)
+ nodes.push_back(&node);
+ return nodes;
+}
+
+void RemoveWhiteSpaceOnlyTextNodes(ContainerNode& container) {
+ for (Node* descendant :
+ CollectFromIterable(NodeTraversal::InclusiveDescendantsOf(container))) {
+ if (auto* text = DynamicTo<Text>(descendant)) {
+ if (text->ContainsOnlyWhitespaceOrEmpty())
+ text->remove();
+ }
+ }
+}
+
+} // namespace
+
+class NodeTraversalTest : public PageTestBase {
+ public:
+ NodeTraversalTest() {}
+
+ protected:
+ void SetupSampleHTML(const char* html);
+};
+
+void NodeTraversalTest::SetupSampleHTML(const char* html) {
+ Element* body = GetDocument().body();
+ SetBodyInnerHTML(String::FromUTF8(html));
+ RemoveWhiteSpaceOnlyTextNodes(*body);
+}
+
+namespace {
+
+void TestCommonAncestor(Node* expected_result,
+ const Node& node_a,
+ const Node& node_b) {
+ Node* result1 = NodeTraversal::CommonAncestor(node_a, node_b);
+ EXPECT_EQ(expected_result, result1)
+ << "CommonAncestor(" << node_a.textContent() << ","
+ << node_b.textContent() << ")";
+ Node* result2 = NodeTraversal::CommonAncestor(node_b, node_a);
+ EXPECT_EQ(expected_result, result2)
+ << "CommonAncestor(" << node_b.textContent() << ","
+ << node_a.textContent() << ")";
+}
+
+} // namespace
+
+// Test case for
+// - Next
+// - NextSkippingChildren
+// - NextPostOrder
+TEST_F(NodeTraversalTest, NextFunctions) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <div id='c00'></div>
+ <div id='c01'></div>
+ </div>
+ <div id='c1'>
+ <div id='c10'></div>
+ </div>)");
+
+ Element* html = GetDocument().documentElement();
+ Element* body = GetDocument().body();
+ Element* c0 = body->QuerySelector("#c0");
+ Element* c1 = body->QuerySelector("#c1");
+ Element* c00 = body->QuerySelector("#c00");
+ Element* c01 = body->QuerySelector("#c01");
+ Element* c10 = body->QuerySelector("#c10");
+
+ EXPECT_EQ(c0, NodeTraversal::Next(*body));
+ EXPECT_EQ(c00, NodeTraversal::Next(*c0));
+ EXPECT_EQ(c01, NodeTraversal::Next(*c00));
+ EXPECT_EQ(c1, NodeTraversal::Next(*c01));
+ EXPECT_EQ(c10, NodeTraversal::Next(*c1));
+ EXPECT_EQ(nullptr, NodeTraversal::Next(*c10));
+
+ EXPECT_EQ(nullptr, NodeTraversal::NextSkippingChildren(*body));
+ EXPECT_EQ(c1, NodeTraversal::NextSkippingChildren(*c0));
+ EXPECT_EQ(c01, NodeTraversal::NextSkippingChildren(*c00));
+ EXPECT_EQ(c1, NodeTraversal::NextSkippingChildren(*c01));
+ EXPECT_EQ(nullptr, NodeTraversal::NextSkippingChildren(*c1));
+ EXPECT_EQ(nullptr, NodeTraversal::Next(*c10));
+
+ EXPECT_EQ(html, NodeTraversal::NextPostOrder(*body));
+ EXPECT_EQ(c10, NodeTraversal::NextPostOrder(*c0));
+ EXPECT_EQ(body, NodeTraversal::NextPostOrder(*c1));
+ EXPECT_EQ(c01, NodeTraversal::NextPostOrder(*c00));
+ EXPECT_EQ(c0, NodeTraversal::NextPostOrder(*c01));
+ EXPECT_EQ(c1, NodeTraversal::NextPostOrder(*c10));
+}
+
+// Test case for
+// - LastWithin
+// - LastWithinOrSelf
+TEST_F(NodeTraversalTest, LastWithin) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <div id='c00'></div>
+ </div>
+ <div id='c1'></div>)");
+
+ Element* body = GetDocument().body();
+ Element* c0 = body->QuerySelector("#c0");
+ Element* c1 = body->QuerySelector("#c1");
+ Element* c00 = body->QuerySelector("#c00");
+
+ EXPECT_EQ(c1, NodeTraversal::LastWithin(*body));
+ EXPECT_EQ(c1, NodeTraversal::LastWithinOrSelf(*body));
+
+ EXPECT_EQ(c00, NodeTraversal::LastWithin(*c0));
+ EXPECT_EQ(c00, NodeTraversal::LastWithinOrSelf(*c0));
+
+ EXPECT_EQ(nullptr, NodeTraversal::LastWithin(*c1));
+ EXPECT_EQ(c1, NodeTraversal::LastWithinOrSelf(*c1));
+}
+
+// Test case for
+// - Previous
+// - PreviousAbsoluteSibling
+// - PreviousPostOrder
+TEST_F(NodeTraversalTest, PreviousFunctions) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <div id='c00'></div>
+ <div id='c01'></div>
+ </div>
+ <div id='c1'>
+ <div id='c10'></div>
+ </div>)");
+
+ Element* html = GetDocument().documentElement();
+ Element* head = GetDocument().head();
+ Element* body = GetDocument().body();
+ Element* c0 = body->QuerySelector("#c0");
+ Element* c1 = body->QuerySelector("#c1");
+ Element* c00 = body->QuerySelector("#c00");
+ Element* c01 = body->QuerySelector("#c01");
+ Element* c10 = body->QuerySelector("#c10");
+
+ EXPECT_EQ(head, NodeTraversal::Previous(*body));
+ EXPECT_EQ(body, NodeTraversal::Previous(*c0));
+ EXPECT_EQ(c0, NodeTraversal::Previous(*c00));
+ EXPECT_EQ(c00, NodeTraversal::Previous(*c01));
+ EXPECT_EQ(c01, NodeTraversal::Previous(*c1));
+ EXPECT_EQ(c1, NodeTraversal::Previous(*c10));
+
+ EXPECT_EQ(nullptr, NodeTraversal::PreviousAbsoluteSibling(*html));
+ EXPECT_EQ(head, NodeTraversal::PreviousAbsoluteSibling(*body));
+ EXPECT_EQ(head, NodeTraversal::PreviousAbsoluteSibling(*c0));
+ EXPECT_EQ(head, NodeTraversal::PreviousAbsoluteSibling(*c00));
+ EXPECT_EQ(c00, NodeTraversal::PreviousAbsoluteSibling(*c01));
+ EXPECT_EQ(c0, NodeTraversal::PreviousAbsoluteSibling(*c1));
+ EXPECT_EQ(c0, NodeTraversal::PreviousAbsoluteSibling(*c10));
+
+ EXPECT_EQ(c1, NodeTraversal::PreviousPostOrder(*body));
+ EXPECT_EQ(c01, NodeTraversal::PreviousPostOrder(*c0));
+ EXPECT_EQ(c10, NodeTraversal::PreviousPostOrder(*c1));
+ EXPECT_EQ(head, NodeTraversal::PreviousPostOrder(*c00));
+ EXPECT_EQ(c00, NodeTraversal::PreviousPostOrder(*c01));
+ EXPECT_EQ(c0, NodeTraversal::PreviousPostOrder(*c10));
+}
+
+// Test case for
+// - ChildAt
+// - CountChildren
+// - HasChildren
+// - Index
+// - IsDescendantOf
+TEST_F(NodeTraversalTest, ChildAt) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <span id='c00'>c00</span>
+ </div>
+ <div id='c1'></div>
+ <div id='c2'></div>)");
+
+ Element* body = GetDocument().body();
+ Element* c0 = body->QuerySelector("#c0");
+ Element* c1 = body->QuerySelector("#c1");
+ Element* c2 = body->QuerySelector("#c2");
+ Element* c00 = body->QuerySelector("#c00");
+
+ const unsigned kNumberOfChildNodes = 3;
+ Node* expected_child_nodes[3] = {c0, c1, c2};
+
+ ASSERT_EQ(kNumberOfChildNodes, NodeTraversal::CountChildren(*body));
+ EXPECT_TRUE(NodeTraversal::HasChildren(*body));
+
+ for (unsigned index = 0; index < kNumberOfChildNodes; ++index) {
+ Node* child = NodeTraversal::ChildAt(*body, index);
+ EXPECT_EQ(index, NodeTraversal::Index(*child))
+ << "NodeTraversal::index(NodeTraversal(*body, " << index << "))";
+ EXPECT_TRUE(NodeTraversal::IsDescendantOf(*child, *body))
+ << "NodeTraversal::isDescendantOf(*NodeTraversal(*body, " << index
+ << "), *body)";
+ EXPECT_EQ(expected_child_nodes[index], child)
+ << "NodeTraversal::childAt(*body, " << index << ")";
+ }
+ EXPECT_EQ(nullptr, NodeTraversal::ChildAt(*body, kNumberOfChildNodes + 1))
+ << "Out of bounds childAt() returns nullptr.";
+
+ EXPECT_EQ(c00, NodeTraversal::FirstChild(*c0));
+}
+
+// Test case for
+// - FirstChild
+// - LastChild
+// - NextSibling
+// - PreviousSibling
+// - Parent
+TEST_F(NodeTraversalTest, Siblings) {
+ SetupSampleHTML(R"(
+ <div id='c0'></div>
+ <div id='c1'></div>
+ <div id='c2'></div>)");
+
+ Element* body = GetDocument().body();
+ Element* c0 = body->QuerySelector("#c0");
+ Element* c1 = body->QuerySelector("#c1");
+ Element* c2 = body->QuerySelector("#c2");
+
+ EXPECT_EQ(c0, NodeTraversal::FirstChild(*body));
+ EXPECT_EQ(c2, NodeTraversal::LastChild(*body));
+
+ EXPECT_EQ(body, NodeTraversal::Parent(*c0));
+ EXPECT_EQ(body, NodeTraversal::Parent(*c1));
+ EXPECT_EQ(body, NodeTraversal::Parent(*c2));
+
+ EXPECT_EQ(c1, NodeTraversal::NextSibling(*c0));
+ EXPECT_EQ(c2, NodeTraversal::NextSibling(*c1));
+ EXPECT_EQ(nullptr, NodeTraversal::NextSibling(*c2));
+
+ EXPECT_EQ(c1, NodeTraversal::PreviousSibling(*c2));
+ EXPECT_EQ(c0, NodeTraversal::PreviousSibling(*c1));
+ EXPECT_EQ(nullptr, NodeTraversal::PreviousSibling(*c0));
+}
+
+TEST_F(NodeTraversalTest, commonAncestor) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <div id='c00'>
+ <div id='c000'></div>
+ </div>
+ <div id='c01'></div>
+ </div>
+ <div id='c1'>
+ <div id='c10'></div>
+ </div>
+ <div id='c2'></div>)");
+
+ Element* body = GetDocument().body();
+ Element* c0 = body->QuerySelector("#c0");
+ Element* c1 = body->QuerySelector("#c1");
+ Element* c2 = body->QuerySelector("#c2");
+
+ Element* c00 = body->QuerySelector("#c00");
+ Element* c01 = body->QuerySelector("#c01");
+ Element* c10 = body->QuerySelector("#c10");
+ Element* c000 = body->QuerySelector("#c000");
+
+ TestCommonAncestor(body, *c0, *c1);
+ TestCommonAncestor(body, *c1, *c2);
+ TestCommonAncestor(body, *c00, *c10);
+ TestCommonAncestor(body, *c01, *c10);
+ TestCommonAncestor(body, *c2, *c10);
+ TestCommonAncestor(body, *c2, *c000);
+
+ TestCommonAncestor(c0, *c00, *c01);
+ TestCommonAncestor(c0, *c000, *c01);
+ TestCommonAncestor(c1, *c1, *c10);
+}
+
+TEST_F(NodeTraversalTest, AncestorsOf) {
+ SetupSampleHTML(R"(
+ <div>
+ <div>
+ <div id='child'></div>
+ </div>
+ </div>)");
+
+ Element* child = GetDocument().getElementById("child");
+
+ HeapVector<Member<Node>> expected_nodes;
+ for (Node* parent = NodeTraversal::Parent(*child); parent;
+ parent = NodeTraversal::Parent(*parent)) {
+ expected_nodes.push_back(parent);
+ }
+
+ HeapVector<Member<Node>> actual_nodes;
+ for (Node& ancestor : NodeTraversal::AncestorsOf(*child))
+ actual_nodes.push_back(&ancestor);
+
+ EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+TEST_F(NodeTraversalTest, InclusiveAncestorsOf) {
+ SetupSampleHTML(R"(
+ <div>
+ <div>
+ <div id='child'></div>
+ </div>
+ </div>)");
+
+ Element* child = GetDocument().getElementById("child");
+
+ HeapVector<Member<Node>> expected_nodes;
+ for (Node* parent = child; parent; parent = NodeTraversal::Parent(*parent)) {
+ expected_nodes.push_back(parent);
+ }
+
+ HeapVector<Member<Node>> actual_nodes;
+ for (Node& ancestor : NodeTraversal::InclusiveAncestorsOf(*child))
+ actual_nodes.push_back(&ancestor);
+
+ EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+TEST_F(NodeTraversalTest, ChildrenOf) {
+ SetupSampleHTML(R"(
+ <div id='c0'></div>
+ <div id='c1'></div>
+ <div id='c2'></div>)");
+
+ Element* body = GetDocument().body();
+
+ HeapVector<Member<Node>> expected_nodes;
+ for (Node* child = NodeTraversal::FirstChild(*body); child;
+ child = NodeTraversal::NextSibling(*child)) {
+ expected_nodes.push_back(child);
+ }
+
+ HeapVector<Member<Node>> actual_nodes;
+ for (Node& child : NodeTraversal::ChildrenOf(*body))
+ actual_nodes.push_back(&child);
+
+ EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+TEST_F(NodeTraversalTest, DescendantsOf) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <div id='c00'></div>
+ <div id='c01'></div>
+ </div>
+ <div id='c1'>
+ <div id='c10'></div>
+ </div>)");
+
+ Element* body = GetDocument().body();
+
+ HeapVector<Member<Node>> expected_nodes;
+ for (Node* child = NodeTraversal::FirstChild(*body); child;
+ child = NodeTraversal::Next(*child)) {
+ expected_nodes.push_back(child);
+ }
+
+ HeapVector<Member<Node>> actual_nodes;
+ for (Node& descendant : NodeTraversal::DescendantsOf(*body))
+ actual_nodes.push_back(&descendant);
+
+ EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+TEST_F(NodeTraversalTest, InclusiveDescendantsOf) {
+ SetupSampleHTML(R"(
+ <div id='c0'>
+ <div id='c00'></div>
+ <div id='c01'></div>
+ </div>
+ <div id='c1'>
+ <div id='c10'></div>
+ </div>)");
+
+ Element* body = GetDocument().body();
+
+ HeapVector<Member<Node>> expected_nodes;
+ for (Node* child = body; child; child = NodeTraversal::Next(*child)) {
+ expected_nodes.push_back(child);
+ }
+
+ HeapVector<Member<Node>> actual_nodes;
+ for (Node& descendant : NodeTraversal::InclusiveDescendantsOf(*body))
+ actual_nodes.push_back(&descendant);
+
+ EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+} // namespace node_traversal_test
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/nth_index_cache.cc b/chromium/third_party/blink/renderer/core/dom/nth_index_cache.cc
index 8a0b76be174..a5ab8169b45 100644
--- a/chromium/third_party/blink/renderer/core/dom/nth_index_cache.cc
+++ b/chromium/third_party/blink/renderer/core/dom/nth_index_cache.cc
@@ -83,8 +83,10 @@ unsigned NthIndexCache::NthChildIndex(Element& element) {
return 1;
NthIndexCache* nth_index_cache = element.GetDocument().GetNthIndexCache();
NthIndexData* nth_index_data = nullptr;
- if (nth_index_cache && nth_index_cache->parent_map_)
+ if (nth_index_cache && nth_index_cache->parent_map_ &&
+ nth_index_cache->parent_map_->Contains(element.parentNode())) {
nth_index_data = nth_index_cache->parent_map_->at(element.parentNode());
+ }
if (nth_index_data)
return nth_index_data->NthIndex(element);
unsigned index = UncachedNthChildIndex(element);
@@ -98,8 +100,10 @@ unsigned NthIndexCache::NthLastChildIndex(Element& element) {
return 1;
NthIndexCache* nth_index_cache = element.GetDocument().GetNthIndexCache();
NthIndexData* nth_index_data = nullptr;
- if (nth_index_cache && nth_index_cache->parent_map_)
+ if (nth_index_cache && nth_index_cache->parent_map_ &&
+ nth_index_cache->parent_map_->Contains(element.parentNode())) {
nth_index_data = nth_index_cache->parent_map_->at(element.parentNode());
+ }
if (nth_index_data)
return nth_index_data->NthLastIndex(element);
unsigned index = UncachedNthLastChildIndex(element);
@@ -112,8 +116,12 @@ NthIndexData* NthIndexCache::NthTypeIndexDataForParent(Element& element) const {
DCHECK(element.parentNode());
if (!parent_map_for_type_)
return nullptr;
- if (const IndexByType* map = parent_map_for_type_->at(element.parentNode()))
+ const IndexByType* map = parent_map_for_type_->Contains(element.parentNode())
+ ? parent_map_for_type_->at(element.parentNode())
+ : nullptr;
+ if (map && map->Contains(element.tagName())) {
return map->at(element.tagName());
+ }
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/parent_node.h b/chromium/third_party/blink/renderer/core/dom/parent_node.h
index f8edef75330..30c8866536b 100644
--- a/chromium/third_party/blink/renderer/core/dom/parent_node.h
+++ b/chromium/third_party/blink/renderer/core/dom/parent_node.h
@@ -65,33 +65,21 @@ class ParentNode {
static void prepend(
Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return node.Prepend(nodes, exception_state);
}
static void append(
Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return node.Append(nodes, exception_state);
}
static void replaceChildren(
Node& node,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<NodeOrStringOrTrustedScript>& nodes,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return node.ReplaceChildren(nodes, exception_state);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/parent_node.idl b/chromium/third_party/blink/renderer/core/dom/parent_node.idl
index 35e38c0100c..2427e1ecec8 100644
--- a/chromium/third_party/blink/renderer/core/dom/parent_node.idl
+++ b/chromium/third_party/blink/renderer/core/dom/parent_node.idl
@@ -33,10 +33,10 @@
[
LegacyTreatAsPartialInterface
] interface mixin ParentNode {
- [Affects=Nothing, SameObject, PerWorldBindings] readonly attribute HTMLCollection children;
- [Affects=Nothing, PerWorldBindings] readonly attribute Element? firstElementChild;
- [Affects=Nothing, PerWorldBindings] readonly attribute Element? lastElementChild;
- [Affects=Nothing] readonly attribute unsigned long childElementCount;
+ [SameObject, PerWorldBindings] readonly attribute HTMLCollection children;
+ [PerWorldBindings] readonly attribute Element? firstElementChild;
+ [PerWorldBindings] readonly attribute Element? lastElementChild;
+ readonly attribute unsigned long childElementCount;
[Unscopable, RaisesException, CEReactions] void prepend((Node or DOMString or TrustedScript)... nodes);
[Unscopable, RaisesException, CEReactions] void append((Node or DOMString or TrustedScript)... nodes);
diff --git a/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc b/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc
index e03b0d673bc..bda69a69e90 100644
--- a/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc
+++ b/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc
@@ -32,7 +32,6 @@
#include <algorithm>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/element.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
index 63f6777bcad..3be93978c63 100644
--- a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
+++ b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -120,12 +120,12 @@ bool ProcessingInstruction::CheckStyleSheet(String& href, String& charset) {
if (!is_css_ && !is_xsl_)
return false;
- href = attrs.at("href");
- charset = attrs.at("charset");
- String alternate = attrs.at("alternate");
+ href = attrs.Contains("href") ? attrs.at("href") : "";
+ charset = attrs.Contains("charset") ? attrs.at("charset") : "";
+ String alternate = attrs.Contains("alternate") ? attrs.at("alternate") : "";
alternate_ = alternate == "yes";
- title_ = attrs.at("title");
- media_ = attrs.at("media");
+ title_ = attrs.Contains("title") ? attrs.at("title") : "";
+ media_ = attrs.Contains("media") ? attrs.at("media") : "";
return !alternate_ || !title_.IsEmpty();
}
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 b3d24f01de1..0560cea9f18 100644
--- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -28,6 +28,7 @@
#include <utility>
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#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/dom/node_computed_style.h"
@@ -279,7 +280,7 @@ bool PseudoElementLayoutObjectIsNeeded(const ComputedStyle* pseudo_style,
return !pseudo_style->ContentPreventsBoxGeneration();
const ComputedStyle* parent_style =
originating_element->GetComputedStyle();
- return parent_style && (parent_style->GetListStyleType() ||
+ return parent_style && (parent_style->ListStyleType() ||
parent_style->GeneratesMarkerImage());
}
default:
diff --git a/chromium/third_party/blink/renderer/core/dom/range.cc b/chromium/third_party/blink/renderer/core/dom/range.cc
index 031a9b6e3d5..bc15153e6fd 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.cc
+++ b/chromium/third_party/blink/renderer/core/dom/range.cc
@@ -44,10 +44,12 @@
#include "third_party/blink/renderer/core/editing/set_selection_options.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/geometry/dom_rect_list.h"
+#include "third_party/blink/renderer/core/highlight/highlight_registry.h"
#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -93,6 +95,8 @@ class RangeUpdateScope {
range_->RemoveFromSelectionIfInDifferentRoot(*old_document_);
range_->UpdateSelectionIfAddedToSelection();
}
+
+ range_->ScheduleVisualUpdateIfInRegisteredHighlight();
#if DCHECK_IS_ON()
current_range_ = nullptr;
#endif
@@ -184,20 +188,6 @@ Node* Range::commonAncestorContainer(const Node* container_a,
return container_a->CommonAncestor(*container_b, NodeTraversal::Parent);
}
-static inline bool CheckForDifferentRootContainer(
- const RangeBoundaryPoint& start,
- const RangeBoundaryPoint& end) {
- Node* end_root_container = &end.Container();
- while (end_root_container->parentNode())
- end_root_container = end_root_container->parentNode();
- Node* start_root_container = &start.Container();
- while (start_root_container->parentNode())
- start_root_container = start_root_container->parentNode();
-
- return start_root_container != end_root_container ||
- (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0);
-}
-
void Range::setStart(Node* ref_node,
unsigned offset,
ExceptionState& exception_state) {
@@ -221,7 +211,9 @@ void Range::setStart(Node* ref_node,
start_.Set(*ref_node, offset, child_node);
- if (did_move_document || CheckForDifferentRootContainer(start_, end_))
+ if (did_move_document ||
+ HasDifferentRootContainer(&start_.Container(), &end_.Container()) ||
+ compareBoundaryPoints(start_, end_, ASSERT_NO_EXCEPTION) > 0)
collapse(true);
}
@@ -248,7 +240,9 @@ void Range::setEnd(Node* ref_node,
end_.Set(*ref_node, offset, child_node);
- if (did_move_document || CheckForDifferentRootContainer(start_, end_))
+ if (did_move_document ||
+ HasDifferentRootContainer(&start_.Container(), &end_.Container()) ||
+ compareBoundaryPoints(start_, end_, ASSERT_NO_EXCEPTION) > 0)
collapse(false);
}
@@ -490,27 +484,6 @@ static inline Node* ChildOfCommonRootBeforeOffset(Node* container,
return container;
}
-static unsigned LengthOfContents(const Node* node) {
- // This switch statement must be consistent with that of
- // Range::processContentsBetweenOffsets.
- switch (node->getNodeType()) {
- case Node::kTextNode:
- case Node::kCdataSectionNode:
- case Node::kCommentNode:
- case Node::kProcessingInstructionNode:
- return To<CharacterData>(node)->length();
- case Node::kElementNode:
- case Node::kDocumentNode:
- case Node::kDocumentFragmentNode:
- return To<ContainerNode>(node)->CountChildren();
- case Node::kAttributeNode:
- case Node::kDocumentTypeNode:
- return 0;
- }
- NOTREACHED();
- return 0;
-}
-
DocumentFragment* Range::ProcessContents(ActionType action,
ExceptionState& exception_state) {
DocumentFragment* fragment = nullptr;
@@ -568,7 +541,8 @@ DocumentFragment* Range::ProcessContents(ActionType action,
common_root->contains(&original_start.Container())) {
left_contents = ProcessContentsBetweenOffsets(
action, nullptr, &original_start.Container(), original_start.Offset(),
- LengthOfContents(&original_start.Container()), exception_state);
+ AbstractRange::LengthOfContents(&original_start.Container()),
+ exception_state);
left_contents = ProcessAncestorsAndTheirSiblings(
action, &original_start.Container(), kProcessContentsForward,
left_contents, common_root, exception_state);
@@ -914,12 +888,15 @@ void Range::insertNode(Node* new_node, ExceptionState& exception_state) {
// 10. Let newOffset be parent's length if referenceNode is null, and
// referenceNode's index otherwise.
- unsigned new_offset =
- reference_node ? reference_node->NodeIndex() : LengthOfContents(&parent);
+ unsigned new_offset = reference_node
+ ? reference_node->NodeIndex()
+ : AbstractRange::LengthOfContents(&parent);
// 11. Increase newOffset by node's length if node is a DocumentFragment node,
// and one otherwise.
- new_offset += new_node->IsDocumentFragment() ? LengthOfContents(new_node) : 1;
+ new_offset += new_node->IsDocumentFragment()
+ ? AbstractRange::LengthOfContents(new_node)
+ : 1;
// 12. Pre-insert node into parent before referenceNode.
parent.insertBefore(new_node, reference_node, exception_state);
@@ -1648,7 +1625,8 @@ void Range::GetBorderAndTextQuads(Vector<FloatQuad>& quads) const {
node = NodeTraversal::Next(*node)) {
if (!node->IsElementNode())
continue;
- if (selected_elements.Contains(node->parentNode()) ||
+ auto* parent_node = node->parentNode();
+ if ((parent_node && selected_elements.Contains(parent_node)) ||
(!node->contains(start_container) && !node->contains(end_container))) {
DCHECK_LE(StartPosition(), Position::BeforeNode(*node));
DCHECK_GE(EndPosition(), Position::AfterNode(*node));
@@ -1768,6 +1746,23 @@ void Range::UpdateSelectionIfAddedToSelection() {
selection.CacheRangeOfDocument(this);
}
+void Range::ScheduleVisualUpdateIfInRegisteredHighlight() {
+ if (LocalDOMWindow* window = OwnerDocument().domWindow()) {
+ if (HighlightRegistry* highlight_registry =
+ window->Supplementable<LocalDOMWindow>::RequireSupplement<
+ HighlightRegistry>()) {
+ for (const auto& highlight_registry_map_entry :
+ highlight_registry->GetHighlights()) {
+ const auto& highlight = highlight_registry_map_entry->highlight;
+ if (highlight->Contains(this)) {
+ highlight_registry->ScheduleRepaint();
+ return;
+ }
+ }
+ }
+ }
+}
+
void Range::RemoveFromSelectionIfInDifferentRoot(Document& old_document) {
if (!old_document.GetFrame())
return;
diff --git a/chromium/third_party/blink/renderer/core/dom/range.h b/chromium/third_party/blink/renderer/core/dom/range.h
index 4f8c6e88509..c31d07fe8b9 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.h
+++ b/chromium/third_party/blink/renderer/core/dom/range.h
@@ -66,7 +66,7 @@ class CORE_EXPORT Range final : public AbstractRange {
void Dispose();
- Document& OwnerDocument() const {
+ Document& OwnerDocument() const override {
DCHECK(owner_document_);
return *owner_document_.Get();
}
@@ -172,6 +172,7 @@ class CORE_EXPORT Range final : public AbstractRange {
static Node* CheckNodeWOffset(Node*, unsigned offset, ExceptionState&);
+ bool IsStaticRange() const override { return false; }
void Trace(Visitor*) const override;
private:
@@ -205,6 +206,7 @@ class CORE_EXPORT Range final : public AbstractRange {
Node* common_root,
ExceptionState&);
void UpdateSelectionIfAddedToSelection();
+ void ScheduleVisualUpdateIfInRegisteredHighlight();
void RemoveFromSelectionIfInDifferentRoot(Document& old_document);
Member<Document> owner_document_; // Cannot be null.
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 5223f996095..66fd77584dd 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
@@ -39,7 +39,8 @@ class RangeBoundaryPoint {
public:
explicit RangeBoundaryPoint(Node& container);
- explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
+ RangeBoundaryPoint(const RangeBoundaryPoint&);
+ RangeBoundaryPoint& operator=(const RangeBoundaryPoint&);
bool IsConnected() const;
const Position ToPosition() const;
@@ -83,11 +84,11 @@ inline RangeBoundaryPoint::RangeBoundaryPoint(Node& container)
dom_tree_version_(DomTreeVersion()),
offset_in_container_(0) {}
-inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
- : container_node_(other.Container()),
- child_before_boundary_(other.ChildBefore()),
- dom_tree_version_(other.dom_tree_version_),
- offset_in_container_(other.Offset()) {}
+inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint&) =
+ default;
+
+inline RangeBoundaryPoint& RangeBoundaryPoint::operator=(
+ const RangeBoundaryPoint& other) = default;
inline Node& RangeBoundaryPoint::Container() const {
return *container_node_;
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 e08d4717703..37095014ed3 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/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/bindings/core/v8/v8_font_face_descriptors.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.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 f3fdfbe2fba..45a2bea2bd6 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
@@ -80,7 +80,10 @@ void ScriptedAnimationController::ContextLifecycleStateChanged(
}
void ScriptedAnimationController::DispatchEventsAndCallbacksForPrinting() {
- DispatchEvents(event_interface_names::kMediaQueryListEvent);
+ DispatchEvents([](const Event* event) {
+ return event->InterfaceName() ==
+ event_interface_names::kMediaQueryListEvent;
+ });
CallMediaQueryListListeners();
}
@@ -114,16 +117,15 @@ void ScriptedAnimationController::RunTasks() {
std::move(task).Run();
}
-void ScriptedAnimationController::DispatchEvents(
- const AtomicString& event_interface_filter) {
+void ScriptedAnimationController::DispatchEvents(const DispatchFilter& filter) {
HeapVector<Member<Event>> events;
- if (event_interface_filter.IsEmpty()) {
+ if (!filter.has_value()) {
events.swap(event_queue_);
per_frame_events_.clear();
} else {
HeapVector<Member<Event>> remaining;
for (auto& event : event_queue_) {
- if (event && event->InterfaceName() == event_interface_filter) {
+ if (event && filter.value()(event)) {
EraseFromPerFrameEventsMap(event.Get());
events.push_back(event.Release());
} else {
@@ -192,13 +194,21 @@ PageAnimator* ScriptedAnimationController::GetPageAnimator() {
}
void ScriptedAnimationController::ServiceScriptedAnimations(
- base::TimeTicks monotonic_time_now) {
+ base::TimeTicks monotonic_time_now,
+ bool can_throttle) {
if (!GetExecutionContext() || GetExecutionContext()->IsContextPaused())
return;
auto* loader = GetWindow()->document()->Loader();
if (!loader)
return;
+ if (can_throttle) {
+ DispatchEvents([](const Event* event) {
+ return event->type() == event_type_names::kResize;
+ });
+ return;
+ }
+
current_frame_time_ms_ =
loader->GetTiming()
.MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now)
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 36ce95c418e..7507e3525c6 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
@@ -88,7 +88,8 @@ class CORE_EXPORT ScriptedAnimationController
// Invokes callbacks, dispatches events, etc. The order is defined by HTML:
// https://html.spec.whatwg.org/C/#event-loop-processing-model
- void ServiceScriptedAnimations(base::TimeTicks monotonic_time_now);
+ void ServiceScriptedAnimations(base::TimeTicks monotonic_time_now,
+ bool can_throttle = false);
void ContextLifecycleStateChanged(mojom::FrameLifecycleState) final;
void ContextDestroyed() final {}
@@ -99,8 +100,9 @@ class CORE_EXPORT ScriptedAnimationController
void ScheduleAnimationIfNeeded();
void RunTasks();
+ typedef absl::optional<bool (*)(const Event*)> DispatchFilter;
void DispatchEvents(
- const AtomicString& event_interface_filter = AtomicString());
+ const DispatchFilter& filter = DispatchFilter(absl::nullopt));
void ExecuteFrameCallbacks();
void ExecuteVideoFrameCallbacks();
void CallMediaQueryListListeners();
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 4c36b6b75ba..0444edfea70 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
@@ -29,7 +29,7 @@ class IdleTask : public GarbageCollected<IdleTask>, public NameClient {
public:
virtual void Trace(Visitor* visitor) const {}
const char* NameInHeapSnapshot() const override { return "IdleTask"; }
- virtual ~IdleTask() = default;
+ ~IdleTask() override = default;
virtual void invoke(IdleDeadline*) = 0;
probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
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 665db67a46d..46f96b65094 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -40,7 +40,6 @@
#include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.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/core/trustedtypes/trusted_types_util.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
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 6d6e78f267f..05aff69a16a 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
@@ -266,7 +266,7 @@ void SlotAssignment::RecalcAssignment() {
// during slot reassignment, so call ChildrenChanged() on all of them.
if (AXObjectCache* cache = owner_->GetDocument().ExistingAXObjectCache()) {
for (Member<HTMLSlotElement> slot : Slots())
- cache->ChildrenChanged(slot);
+ cache->SlotAssignmentWillChange(slot);
}
FlatTreeTraversalForbiddenScope forbid_flat_tree_traversal(
diff --git a/chromium/third_party/blink/renderer/core/dom/space_split_string.cc b/chromium/third_party/blink/renderer/core/dom/space_split_string.cc
index 3d5c2fb6239..c5fa9c74c24 100644
--- a/chromium/third_party/blink/renderer/core/dom/space_split_string.cc
+++ b/chromium/third_party/blink/renderer/core/dom/space_split_string.cc
@@ -212,4 +212,8 @@ SpaceSplitString::Data::Data(const SpaceSplitString::Data& other)
// there's nothing to be removed from the SharedDataMap().
}
+std::ostream& operator<<(std::ostream& ostream, const SpaceSplitString& str) {
+ return ostream << str.SerializeToString();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/space_split_string.h b/chromium/third_party/blink/renderer/core/dom/space_split_string.h
index 103cf9ebb31..bb6723f870e 100644
--- a/chromium/third_party/blink/renderer/core/dom/space_split_string.h
+++ b/chromium/third_party/blink/renderer/core/dom/space_split_string.h
@@ -113,6 +113,8 @@ class CORE_EXPORT SpaceSplitString {
scoped_refptr<Data> data_;
};
+CORE_EXPORT std::ostream& operator<<(std::ostream&, const SpaceSplitString&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SPACE_SPLIT_STRING_H_
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 bce0400dd95..f31ed4bd5fe 100644
--- a/chromium/third_party/blink/renderer/core/dom/static_range.cc
+++ b/chromium/third_party/blink/renderer/core/dom/static_range.cc
@@ -6,20 +6,15 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_static_range_init.h"
#include "third_party/blink/renderer/core/dom/range.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/frame/local_dom_window.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/script_state.h"
namespace blink {
-StaticRange::StaticRange(Document& document)
- : owner_document_(document),
- start_container_(document),
- start_offset_(0u),
- end_container_(document),
- end_offset_(0u) {}
-
StaticRange::StaticRange(Document& document,
Node* start_container,
unsigned start_offset,
@@ -62,14 +57,56 @@ StaticRange* StaticRange::Create(Document& document,
static_range_init->endOffset());
}
-void StaticRange::setStart(Node* container, unsigned offset) {
- start_container_ = container;
- start_offset_ = offset;
+namespace {
+
+// Returns the lowest ancestor of |node| in the tree that has a containment set.
+Node* GetLowestContainAncestor(const Node* node) {
+ for (Node& ancestor : NodeTraversal::InclusiveAncestorsOf(*node)) {
+ if (LayoutObject* node_layout_object = ancestor.GetLayoutObject()) {
+ if (node_layout_object->ShouldApplyAnyContainment()) {
+ return &ancestor;
+ }
+ }
+ }
+ return nullptr;
+}
+
+} // namespace
+
+// Returns true if the range crosses any css-contain subtree boundary.
+bool StaticRange::CrossesContainBoundary() const {
+ if (style_version_for_crosses_contain_boundary_ ==
+ owner_document_->StyleVersion())
+ return crosses_contain_boundary_;
+ style_version_for_crosses_contain_boundary_ = owner_document_->StyleVersion();
+
+ crosses_contain_boundary_ = GetLowestContainAncestor(start_container_) !=
+ GetLowestContainAncestor(end_container_);
+ return crosses_contain_boundary_;
}
-void StaticRange::setEnd(Node* container, unsigned offset) {
- end_container_ = container;
- end_offset_ = offset;
+bool StaticRange::IsValid() const {
+ if (dom_tree_version_for_is_valid_ == owner_document_->DomTreeVersion())
+ return is_valid_;
+ dom_tree_version_for_is_valid_ = owner_document_->DomTreeVersion();
+
+ // The full list of checks is:
+ // 1) The start offset is between 0 and the start container’s node length
+ // (inclusive).
+ // 2) The end offset is between 0 and the end container’s node length
+ // (inclusive).
+ // 3) The start and end containers of the static range are in the same DOM
+ // tree.
+ // 4) The position of the start boundary point is before or equal to the
+ // position of the end boundary point.
+ is_valid_ =
+ start_offset_ <= AbstractRange::LengthOfContents(start_container_) &&
+ end_offset_ <= AbstractRange::LengthOfContents(end_container_) &&
+ !HasDifferentRootContainer(start_container_, end_container_) &&
+ ComparePositionsInDOMTree(start_container_, start_offset_, end_container_,
+ end_offset_) <= 0;
+
+ return is_valid_;
}
Range* StaticRange::toRange(ExceptionState& exception_state) const {
diff --git a/chromium/third_party/blink/renderer/core/dom/static_range.h b/chromium/third_party/blink/renderer/core/dom/static_range.h
index a1e45bffb60..efe6d12e390 100644
--- a/chromium/third_party/blink/renderer/core/dom/static_range.h
+++ b/chromium/third_party/blink/renderer/core/dom/static_range.h
@@ -32,7 +32,6 @@ class CORE_EXPORT StaticRange final : public AbstractRange {
const StaticRangeInit*,
ExceptionState&);
- explicit StaticRange(Document&);
StaticRange(Document&,
Node* start_container,
unsigned start_offset,
@@ -40,40 +39,46 @@ class CORE_EXPORT StaticRange final : public AbstractRange {
unsigned end_offset);
Node* startContainer() const override { return start_container_.Get(); }
- void setStartContainer(Node* start_container) {
- start_container_ = start_container;
- }
-
unsigned startOffset() const override { return start_offset_; }
- void setStartOffset(unsigned start_offset) { start_offset_ = start_offset; }
Node* endContainer() const override { return end_container_.Get(); }
- void setEndContainer(Node* end_container) { end_container_ = end_container; }
-
unsigned endOffset() const override { return end_offset_; }
- void setEndOffset(unsigned end_offset) { end_offset_ = end_offset; }
bool collapsed() const override {
return start_container_ == end_container_ && start_offset_ == end_offset_;
}
- void setStart(Node* container, unsigned offset);
- void setEnd(Node* container, unsigned offset);
-
Range* toRange(ExceptionState& = ASSERT_NO_EXCEPTION) const;
+ bool IsValid() const;
+ bool CrossesContainBoundary() const;
+ bool IsStaticRange() const override { return true; }
+ Document& OwnerDocument() const override { return *owner_document_.Get(); }
+
void Trace(Visitor*) const override;
private:
Member<Document> owner_document_; // Required by |toRange()|.
Member<Node> start_container_;
- unsigned start_offset_;
+ unsigned start_offset_ = 0;
Member<Node> end_container_;
- unsigned end_offset_;
+ unsigned end_offset_ = 0;
+ mutable bool is_valid_ = false;
+ mutable bool crosses_contain_boundary_ = false;
+ mutable uint64_t dom_tree_version_for_is_valid_ = 0;
+ mutable uint64_t style_version_for_crosses_contain_boundary_ =
+ static_cast<uint64_t>(-1);
};
using StaticRangeVector = HeapVector<Member<StaticRange>>;
+template <>
+struct DowncastTraits<StaticRange> {
+ static bool AllowFrom(const AbstractRange& abstract_range) {
+ return abstract_range.IsStaticRange();
+ }
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_STATIC_RANGE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/text.cc b/chromium/third_party/blink/renderer/core/dom/text.cc
index 6ff0ca1c6b9..7d0debe47ff 100644
--- a/chromium/third_party/blink/renderer/core/dom/text.cc
+++ b/chromium/third_party/blink/renderer/core/dom/text.cc
@@ -438,8 +438,8 @@ static bool ShouldUpdateLayoutByReattaching(const Text& text_node,
return true;
}
if (text_layout_object->IsTextFragment()) {
- // Changes of |textNode| may change first letter part, so we should
- // reattach. Note: When |textNode| is empty or holds collapsed white spaces
+ // Changes of |text_node| may change first letter part, so we should
+ // reattach. Note: When |text_node| is empty or holds collapsed whitespaces
// |text_fragment_layout_object| represents first-letter part but it isn't
// inside first-letter-pseudo element. See http://crbug.com/978947
const auto& text_fragment_layout_object =
@@ -447,13 +447,24 @@ static bool ShouldUpdateLayoutByReattaching(const Text& text_node,
return text_fragment_layout_object.GetFirstLetterPseudoElement() ||
!text_fragment_layout_object.IsRemainingTextLayoutObject();
}
- if (auto* next = text_layout_object->NextSibling()) {
- if (IsA<FirstLetterPseudoElement>(next->GetNode())) {
- // This |Text| node is not a first-letter part, but it may be changed.
- // So, we should rebuild first-letter part and remaining part.
- // See FirstLetterPseudoElementTest.AppendDataToSpace
- return true;
- }
+ // If we force a re-attach for password inputs and other elements hiding text
+ // input via -webkit-text-security, the last character input will be hidden
+ // immediately, even if the passwordEchoEnabled setting is enabled.
+ // ::first-letter do not seem to apply to text inputs, so for those skipping
+ // the re-attachment should be safe.
+ // We can possibly still cause DCHECKs for mismatch of first letter text in
+ // editing with the combination of -webkit-text-security in author styles on
+ // other elements in combination with ::first-letter.
+ // See crbug.com/1240988
+ if (text_layout_object->IsSecure())
+ return false;
+ if (!FirstLetterPseudoElement::FirstLetterLength(
+ text_layout_object->GetText()) &&
+ FirstLetterPseudoElement::FirstLetterLength(text_node.data())) {
+ // We did not previously apply ::first-letter styles to this |text_node|,
+ // and if there was no first formatted letter, but now is, we may need to
+ // reattach.
+ return true;
}
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc b/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc
index f44ab4a28b5..2484d29229d 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc
@@ -115,10 +115,9 @@ inline Element* TreeOrderedMap::Get(const AtomicString& key,
const TreeScope& scope) const {
DCHECK(key);
- MapEntry* entry = map_.at(key);
- if (!entry)
+ if (!map_.Contains(key))
return nullptr;
-
+ MapEntry* entry = map_.at(key);
DCHECK(entry->count);
if (entry->element)
return entry->element;
@@ -197,9 +196,9 @@ HTMLSlotElement* TreeOrderedMap::GetSlotByName(const AtomicString& key,
Element* TreeOrderedMap::GetCachedFirstElementWithoutAccessingNodeTree(
const AtomicString& key) {
- MapEntry* entry = map_.at(key);
- if (!entry)
+ if (!map_.Contains(key))
return nullptr;
+ MapEntry* entry = map_.at(key);
DCHECK(entry->count);
return entry->element;
}
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 a2c60bebcc0..11a9f82b657 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/css/resolver/scoped_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/container_node.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/weak_identifier_map.h b/chromium/third_party/blink/renderer/core/dom/weak_identifier_map.h
index a78305b0967..245893ee282 100644
--- a/chromium/third_party/blink/renderer/core/dom/weak_identifier_map.h
+++ b/chromium/third_party/blink/renderer/core/dom/weak_identifier_map.h
@@ -28,12 +28,14 @@ class WeakIdentifierMap final
}
static IdentifierType Identifier(T* object) {
- IdentifierType result = Instance().object_to_identifier_.at(object);
+ IdentifierType result;
- if (WTF::IsHashTraitsEmptyValue<HashTraits<IdentifierType>>(result)) {
+ if (!Instance().object_to_identifier_.Contains(object)) {
do {
result = Next();
} while (!LIKELY(Instance().Put(object, result)));
+ } else {
+ result = Instance().object_to_identifier_.at(object);
}
return result;
}
@@ -43,7 +45,9 @@ class WeakIdentifierMap final
}
static T* Lookup(IdentifierType identifier) {
- return Instance().identifier_to_object_.at(identifier);
+ return Instance().identifier_to_object_.Contains(identifier)
+ ? Instance().identifier_to_object_.at(identifier)
+ : nullptr;
}
static void NotifyObjectDestroyed(T* object) {
diff --git a/chromium/third_party/blink/renderer/core/editing/build.gni b/chromium/third_party/blink/renderer/core/editing/build.gni
index 0ada2a056c0..b1164836af8 100644
--- a/chromium/third_party/blink/renderer/core/editing/build.gni
+++ b/chromium/third_party/blink/renderer/core/editing/build.gni
@@ -207,6 +207,10 @@ blink_core_sources_editing = [
"markers/grammar_marker.h",
"markers/grammar_marker_list_impl.cc",
"markers/grammar_marker_list_impl.h",
+ "markers/highlight_marker.cc",
+ "markers/highlight_marker.h",
+ "markers/highlight_marker_list_impl.cc",
+ "markers/highlight_marker_list_impl.h",
"markers/sorted_document_marker_list_editor.cc",
"markers/sorted_document_marker_list_editor.h",
"markers/spell_check_marker.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 faa4373bc78..cdafeca25e1 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
@@ -245,15 +245,20 @@ void CaretDisplayItemClient::PaintCaret(
GraphicsContext& context,
const PhysicalOffset& paint_offset,
DisplayItem::Type display_item_type) const {
- if (DrawingRecorder::UseCachedDrawingIfPossible(context, *this,
- display_item_type))
- return;
-
PhysicalRect drawing_rect = local_rect_;
drawing_rect.Move(paint_offset);
- DrawingRecorder recorder(context, *this, display_item_type,
- EnclosingIntRect(drawing_rect));
+ // When caret is in text-combine box with scaling, |context| is already
+ // associated to drawing record to apply affine transform.
+ absl::optional<DrawingRecorder> recorder;
+ if (LIKELY(!context.InDrawingRecorder())) {
+ if (DrawingRecorder::UseCachedDrawingIfPossible(context, *this,
+ display_item_type))
+ return;
+ recorder.emplace(context, *this, display_item_type,
+ EnclosingIntRect(drawing_rect));
+ }
+
IntRect paint_rect = PixelSnappedIntRect(drawing_rect);
context.FillRect(paint_rect, is_visible_if_active_ ? color_ : Color(),
DarkModeFilter::ElementRole::kText);
diff --git a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.h b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.h
index 274879b922a..0a83ae01edd 100644
--- a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.h
+++ b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_CARET_DISPLAY_ITEM_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_CARET_DISPLAY_ITEM_CLIENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
@@ -44,6 +43,8 @@ struct PaintInvalidatorContext;
class CORE_EXPORT CaretDisplayItemClient final : public DisplayItemClient {
public:
CaretDisplayItemClient();
+ CaretDisplayItemClient(const CaretDisplayItemClient&) = delete;
+ CaretDisplayItemClient& operator=(const CaretDisplayItemClient&) = delete;
~CaretDisplayItemClient() override;
// Called indirectly from LayoutBlock::willBeDestroyed().
@@ -110,8 +111,6 @@ class CORE_EXPORT CaretDisplayItemClient final : public DisplayItemClient {
bool needs_paint_invalidation_ = false;
bool is_visible_if_active_ = true;
-
- DISALLOW_COPY_AND_ASSIGN(CaretDisplayItemClient);
};
} // namespace blink
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 45bfc7ff97a..0f03e4ec621 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
@@ -7,6 +7,7 @@
#include "testing/gmock/include/gmock/gmock-matchers.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/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
index 5459bde0d6b..fd0021328f0 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
@@ -332,7 +332,12 @@ bool ClipboardCommands::ExecuteCut(LocalFrame& frame,
// 'beforeinput' event handler may destroy target frame.
if (frame.GetDocument()->GetFrame() != frame)
return true;
+
+ // No DOM mutation if EditContext is active.
+ if (frame.GetInputMethodController().GetActiveEditContext())
+ return true;
}
+
frame.GetEditor().DeleteSelectionWithSmartDelete(
ConvertSmartReplaceOptionToDeleteMode(GetSmartReplaceOption(frame)),
InputEvent::InputType::kDeleteByCut);
@@ -453,6 +458,10 @@ void ClipboardCommands::Paste(LocalFrame& frame, EditorCommandSource source) {
// 'beforeinput' event handler may destroy target frame.
if (frame.GetDocument()->GetFrame() != frame)
return;
+
+ // No DOM mutation if EditContext is active.
+ if (frame.GetInputMethodController().GetActiveEditContext())
+ return;
}
if (paste_mode == PasteMode::kAllMimeTypes) {
@@ -500,9 +509,27 @@ bool ClipboardCommands::ExecutePasteAndMatchStyle(LocalFrame& frame,
// before we obtain the selection.
frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
- if (source == EditorCommandSource::kMenuOrKeyBinding &&
- !frame.Selection().SelectionHasFocus())
- return false;
+ if (source == EditorCommandSource::kMenuOrKeyBinding) {
+ if (!frame.Selection().SelectionHasFocus())
+ return false;
+
+ DataTransfer* data_transfer = DataTransfer::Create(
+ DataTransfer::kCopyAndPaste, DataTransferAccessPolicy::kReadable,
+ DataObject::CreateFromClipboard(frame.GetSystemClipboard(),
+ PasteMode::kPlainTextOnly));
+ if (DispatchBeforeInputDataTransfer(
+ FindEventTargetForClipboardEvent(frame, source),
+ InputEvent::InputType::kInsertFromPaste,
+ data_transfer) != DispatchEventResult::kNotCanceled)
+ return true;
+ // 'beforeinput' event handler may destroy target frame.
+ if (frame.GetDocument()->GetFrame() != frame)
+ return true;
+
+ // No DOM mutation if EditContext is active.
+ if (frame.GetInputMethodController().GetActiveEditContext())
+ return true;
+ }
PasteAsPlainTextFromClipboard(frame, source);
return true;
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 b0955dadac9..1f8e05d7f94 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
@@ -2122,6 +2122,8 @@ void CompositeEditCommand::AppliedEditing() {
EnsureUndoStep()->EndingSelection());
last_edit_command->GetUndoStep()->SetSelectionIsDirectional(
GetUndoStep()->SelectionIsDirectional());
+ editor.GetUndoStack().DidSetEndingSelection(
+ last_edit_command->GetUndoStep());
last_edit_command->AppendCommandToUndoStep(this);
} else {
// Only register a new undo command if the command passed in is
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
index c39329c1d30..2460c32fa94 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
@@ -551,6 +551,129 @@ void DeleteSelectionCommand::RemoveNode(
should_assume_content_is_always_editable);
}
+void DeleteSelectionCommand::RemoveCompletelySelectedNodes(
+ Node* start_node,
+ EditingState* editing_state) {
+ HeapVector<Member<Node>> nodes_to_be_removed;
+ Node* node = start_node;
+
+ GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
+
+ // Collecting nodes that can be removed from |start_node|.
+ while (node && node != downstream_end_.AnchorNode()) {
+ if (ComparePositions(FirstPositionInOrBeforeNode(*node), downstream_end_) >=
+ 0)
+ break;
+
+ if (!downstream_end_.AnchorNode()->IsDescendantOf(node)) {
+ nodes_to_be_removed.push_back(node);
+ node = NodeTraversal::NextSkippingChildren(*node);
+ continue;
+ }
+
+ Node& last_within_or_self_node = NodeTraversal::LastWithinOrSelf(*node);
+ if (downstream_end_.AnchorNode() == last_within_or_self_node &&
+ downstream_end_.ComputeEditingOffset() >=
+ CaretMaxOffset(&last_within_or_self_node)) {
+ nodes_to_be_removed.push_back(node);
+ break;
+ }
+
+ node = NodeTraversal::Next(*node);
+ }
+
+ // Update leading, trailing whitespace position.
+ if (!nodes_to_be_removed.IsEmpty()) {
+ leading_whitespace_ = ComputePositionForNodeRemoval(
+ leading_whitespace_, *(nodes_to_be_removed[0].Get()));
+ trailing_whitespace_ = ComputePositionForNodeRemoval(
+ trailing_whitespace_,
+ *(nodes_to_be_removed[nodes_to_be_removed.size() - 1].Get()));
+ }
+
+ // Check if place holder is needed before actually removing nodes because
+ // this requires document.NeedsLayoutTreeUpdate() returning false.
+ if (!need_placeholder_) {
+ need_placeholder_ = std::any_of(
+ nodes_to_be_removed.begin(), nodes_to_be_removed.end(),
+ [&](Node* node) {
+ if (node == start_block_) {
+ VisiblePosition previous = PreviousPositionOf(
+ VisiblePosition::FirstPositionInNode(*start_block_.Get()));
+ if (previous.IsNotNull() && !IsEndOfBlock(previous))
+ return true;
+ }
+ if (node == end_block_) {
+ VisiblePosition next = NextPositionOf(
+ VisiblePosition::LastPositionInNode(*end_block_.Get()));
+ if (next.IsNotNull() && !IsStartOfBlock(next))
+ return true;
+ }
+ return false;
+ });
+ }
+
+ // Actually remove the nodes in |nodes_to_be_removed|.
+ for (Node* node_to_be_removed : nodes_to_be_removed) {
+ if (!downstream_end_.AnchorNode()->IsDescendantOf(node_to_be_removed)) {
+ downstream_end_ =
+ ComputePositionForNodeRemoval(downstream_end_, *(node_to_be_removed));
+ }
+
+ if (start_root_ != end_root_ &&
+ !(node_to_be_removed->IsDescendantOf(start_root_.Get()) &&
+ node_to_be_removed->IsDescendantOf(end_root_.Get()))) {
+ // If a node is not in both the start and end editable roots, remove it
+ // only if its inside an editable region.
+ if (!HasEditableStyle(*node_to_be_removed->parentNode())) {
+ // Don't remove non-editable atomic nodes.
+ if (!node_to_be_removed->hasChildren())
+ continue;
+ // Search this non-editable region for editable regions to empty.
+ // Don't remove editable regions that are inside non-editable ones, just
+ // clear them.
+ RemoveAllChildrenIfPossible(To<ContainerNode>(node_to_be_removed),
+ editing_state,
+ kDoNotAssumeContentIsAlwaysEditable);
+ if (editing_state->IsAborted())
+ return;
+
+ continue;
+ }
+ }
+
+ if (IsTableStructureNode(node_to_be_removed) ||
+ IsRootEditableElement(*node_to_be_removed)) {
+ // Do not remove an element of table structure; remove its contents.
+ // Likewise for the root editable element.
+ RemoveAllChildrenIfPossible(To<ContainerNode>(node_to_be_removed),
+ editing_state,
+ kDoNotAssumeContentIsAlwaysEditable);
+ if (editing_state->IsAborted())
+ return;
+
+ // Make sure empty cell has some height, if a placeholder can be inserted.
+ GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
+ LayoutObject* layout_obj = node_to_be_removed->GetLayoutObject();
+ if (layout_obj && layout_obj->IsTableCell() &&
+ To<LayoutBox>(layout_obj)->ContentHeight() <= 0) {
+ Position first_editable_position =
+ FirstEditablePositionInNode(node_to_be_removed);
+ if (first_editable_position.IsNotNull())
+ InsertBlockPlaceholder(first_editable_position, editing_state);
+ }
+ continue;
+ }
+
+ ending_position_ =
+ ComputePositionForNodeRemoval(ending_position_, *node_to_be_removed);
+ CompositeEditCommand::RemoveNode(node_to_be_removed, editing_state,
+ kDoNotAssumeContentIsAlwaysEditable);
+ if (editing_state->IsAborted())
+ return;
+ }
+}
+
static void UpdatePositionForTextRemoval(Text* node,
int offset,
int count,
@@ -690,36 +813,10 @@ void DeleteSelectionCommand::HandleGeneralDelete(EditingState* editing_state) {
upstream_end_.ComputeOffsetInContainerNode());
}
- // handle deleting all nodes that are completely selected
- while (node && node != downstream_end_.AnchorNode()) {
- if (ComparePositions(FirstPositionInOrBeforeNode(*node),
- downstream_end_) >= 0) {
- // NodeTraversal::nextSkippingChildren just blew past the end position,
- // so stop deleting
- node = nullptr;
- } else if (!downstream_end_.AnchorNode()->IsDescendantOf(node)) {
- Node* next_node = NodeTraversal::NextSkippingChildren(*node);
- // if we just removed a node from the end container, update end position
- // so the check above will work
- downstream_end_ = ComputePositionForNodeRemoval(downstream_end_, *node);
- RemoveNode(node, editing_state);
- if (editing_state->IsAborted())
- return;
- node = next_node;
- } else {
- GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
- Node& n = NodeTraversal::LastWithinOrSelf(*node);
- if (downstream_end_.AnchorNode() == n &&
- downstream_end_.ComputeEditingOffset() >= CaretMaxOffset(&n)) {
- RemoveNode(node, editing_state);
- if (editing_state->IsAborted())
- return;
- node = nullptr;
- } else {
- node = NodeTraversal::Next(*node);
- }
- }
- }
+ // Delete all nodes that are completely selected
+ RemoveCompletelySelectedNodes(node, editing_state);
+ if (editing_state->IsAborted())
+ return;
// TODO(editing-dev): Hoist UpdateStyleAndLayout
// to caller. See http://crbug.com/590369 for more details.
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h
index c7787fef003..2dccf496c38 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h
@@ -72,6 +72,8 @@ class CORE_EXPORT DeleteSelectionCommand final : public CompositeEditCommand {
EditingState*,
ShouldAssumeContentIsAlwaysEditable =
kDoNotAssumeContentIsAlwaysEditable) override;
+ void RemoveCompletelySelectedNodes(Node* start_node,
+ EditingState* editing_state);
void DeleteTextFromNode(Text*, unsigned, unsigned) override;
void RemoveRedundantBlocks(EditingState*);
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h
index aa569f165d3..556b04ceddd 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_DELETE_SELECTION_OPTIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_DELETE_SELECTION_OPTIONS_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
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 6672e690e44..e0c711b584d 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
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -94,6 +95,12 @@ bool Document::execCommand(const String& command_name,
TidyUpHTMLStructure(*this);
const EditorCommand editor_command = GetCommand(this, command_name);
+ // Count how often the error condition of crbug.com/1230567 occurs.
+ if (CodeUnitCompareIgnoringASCIICase(command_name, "insertHTML") == 0 &&
+ RequireTrustedTypesCheck(GetExecutionContext())) {
+ UseCounter::Count(*this, WebFeature::kExecCommandWithTrustedTypes);
+ }
+
base::UmaHistogramSparse("WebCore.Document.execCommand",
editor_command.IdForHistogram());
return editor_command.Execute(value);
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc
index 19b4238be31..eb863f9f683 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_command_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 "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/static_range.h"
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 5d720120359..560d4b18854 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
@@ -498,7 +498,7 @@ VisibleSelection SelectionForParagraphIteration(
const String& NonBreakingSpaceString() {
DEFINE_STATIC_LOCAL(String, non_breaking_space_string,
- (&kNoBreakSpaceCharacter, 1));
+ (&kNoBreakSpaceCharacter, 1u));
return non_breaking_space_string;
}
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h
index b8559cfb116..e37b62af804 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_EDITING_STATE_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.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 c1ecb6412f0..ed07e60106a 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
@@ -52,6 +52,7 @@
#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"
+#include "third_party/blink/renderer/core/editing/ime/edit_context.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"
@@ -1949,6 +1950,41 @@ bool EditorCommand::Execute(const String& parameter,
if (frame_->GetDocument()->GetFrame() != frame_)
return false;
}
+
+ // If EditContext is active, we may return early and not execute the
+ // command.
+ if (auto* edit_context =
+ frame_->GetInputMethodController().GetActiveEditContext()) {
+ // From EditContext's point of view, there are 3 kinds of commands:
+ switch (command_->command_type) {
+ case EditingCommandType::kToggleBold:
+ case EditingCommandType::kToggleItalic:
+ case EditingCommandType::kToggleUnderline:
+ case EditingCommandType::kInsertTab:
+ case EditingCommandType::kInsertBacktab:
+ case EditingCommandType::kInsertNewline:
+ case EditingCommandType::kInsertLineBreak:
+ // 1) BeforeInput event only, ex ctrl+B or <enter>.
+ return true;
+ case EditingCommandType::kDeleteBackward:
+ // 2) BeforeInput event + EditContext behavior, ex. backspace/delete.
+ edit_context->DeleteBackward();
+ return true;
+ case EditingCommandType::kDeleteForward:
+ edit_context->DeleteForward();
+ return true;
+ case EditingCommandType::kDeleteWordBackward:
+ edit_context->DeleteWordBackward();
+ return true;
+ case EditingCommandType::kDeleteWordForward:
+ edit_context->DeleteWordForward();
+ return true;
+ default:
+ // 3) BeforeInput event + default DOM behavior, ex. caret navigation.
+ // In this case, it's no-op for EditContext.
+ break;
+ }
+ }
}
GetFrame().GetDocument()->UpdateStyleAndLayout(
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc
index 88536708e2e..5eb8049a240 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc
@@ -197,4 +197,26 @@ TEST_F(InsertListCommandTest, ListifyInputInTableCell) {
"ruby>",
GetSelectionTextFromBody());
}
+
+TEST_F(InsertListCommandTest, ListifyInputInTableCell1) {
+ GetDocument().setDesignMode("on");
+ InsertStyleElement(
+ "rb { display: table-cell; }"
+ "input { float: left; }");
+ Selection().SetSelection(
+ SetSelectionTextToBody("<div contenteditable='true'><ol><li>^<br></li>"
+ "<li><ruby><rb><input></input></rb></ruby></li>"
+ "<li>XXX</li></ol><div>|</div>"),
+ SetSelectionOptions());
+ auto* command = MakeGarbageCollected<InsertListCommand>(
+ GetDocument(), InsertListCommand::kOrderedList);
+
+ // Crash happens here.
+ EXPECT_TRUE(command->Apply());
+ EXPECT_EQ(
+ "<div contenteditable=\"true\">^<br><ol><li><ruby><rb><ol><li><br></li>"
+ "<li><ruby><rb><input></rb></ruby></li><li><br></li><li><br></li></ol>"
+ "</rb></ruby></li></ol>|XXX<br><div></div></div>",
+ GetSelectionTextFromBody());
+}
}
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 12a6eddbcae..3c0090fcd32 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
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/editing/commands/replace_selection_command.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h b/chromium/third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h
index 08e33fad25d..fa96fa03dc8 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_SELECTION_FOR_UNDO_STEP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_SELECTION_FOR_UNDO_STEP_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/set_character_data_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/set_character_data_command_test.cc
index 0a4f682975b..c919d23acfb 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/set_character_data_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/set_character_data_command_test.cc
@@ -137,15 +137,23 @@ TEST_F(SetCharacterDataCommandTest, CombinedText) {
UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(text_node->GetLayoutObject());
- ASSERT_FALSE(sample_layout_object.IsLayoutNGObject());
- EXPECT_EQ(R"DUMP(
+ if (sample_layout_object.IsLayoutNGObject()) {
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="sample" (editable)
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutText #text ""
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ } else {
+ EXPECT_EQ(R"DUMP(
LayoutBlockFlow DIV id="sample" (editable)
+--LayoutTextCombine #text ""
)DUMP",
- ToSimpleLayoutTree(sample_layout_object));
- ASSERT_TRUE(text_node->GetLayoutObject()->IsCombineText());
- EXPECT_FALSE(
- To<LayoutTextCombine>(text_node->GetLayoutObject())->IsCombined());
+ ToSimpleLayoutTree(sample_layout_object));
+ ASSERT_TRUE(text_node->GetLayoutObject()->IsCombineText());
+ EXPECT_FALSE(
+ To<LayoutTextCombine>(text_node->GetLayoutObject())->IsCombined());
+ }
SimpleEditCommand* command =
MakeGarbageCollected<SetCharacterDataCommand>(text_node, 0, 0, "text");
@@ -153,29 +161,45 @@ LayoutBlockFlow DIV id="sample" (editable)
UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(text_node->GetLayoutObject());
- ASSERT_FALSE(sample_layout_object.IsLayoutNGObject());
- EXPECT_EQ(R"DUMP(
+ if (sample_layout_object.IsLayoutNGObject()) {
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="sample" (editable)
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutText #text "text"
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ } else {
+ EXPECT_EQ(R"DUMP(
LayoutBlockFlow DIV id="sample" (editable)
+--LayoutTextCombine #text "text"
)DUMP",
- ToSimpleLayoutTree(sample_layout_object));
- ASSERT_TRUE(text_node->GetLayoutObject()->IsCombineText());
- EXPECT_TRUE(
- To<LayoutTextCombine>(text_node->GetLayoutObject())->IsCombined());
+ ToSimpleLayoutTree(sample_layout_object));
+ ASSERT_TRUE(text_node->GetLayoutObject()->IsCombineText());
+ EXPECT_TRUE(
+ To<LayoutTextCombine>(text_node->GetLayoutObject())->IsCombined());
+ }
command->DoUnapply();
UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(text_node->GetLayoutObject());
- ASSERT_FALSE(sample_layout_object.IsLayoutNGObject());
- EXPECT_EQ(R"DUMP(
+ if (sample_layout_object.IsLayoutNGObject()) {
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="sample" (editable)
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutText #text ""
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ } else {
+ EXPECT_EQ(R"DUMP(
LayoutBlockFlow DIV id="sample" (editable)
+--LayoutTextCombine #text ""
)DUMP",
- ToSimpleLayoutTree(sample_layout_object));
- ASSERT_TRUE(text_node->GetLayoutObject()->IsCombineText());
- EXPECT_FALSE(
- To<LayoutTextCombine>(text_node->GetLayoutObject())->IsCombined());
+ ToSimpleLayoutTree(sample_layout_object));
+ ASSERT_TRUE(text_node->GetLayoutObject()->IsCombineText());
+ EXPECT_FALSE(
+ To<LayoutTextCombine>(text_node->GetLayoutObject())->IsCombined());
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/smart_replace.h b/chromium/third_party/blink/renderer/core/editing/commands/smart_replace.h
index 6e8f863a83c..6a4c121978f 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/smart_replace.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/smart_replace.h
@@ -29,7 +29,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_SMART_REPLACE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_SMART_REPLACE_H_
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.cc b/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.cc
index d41997e9405..b499ea00abc 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.cc
@@ -41,7 +41,6 @@ static const size_t kMaximumUndoStackDepth = 1000;
UndoStack::UndoStack() = default;
void UndoStack::RegisterUndoStep(UndoStep* step) {
- EnsureListeningMemoryPressure();
if (!undo_stack_.IsEmpty())
DCHECK_GE(step->SequenceNumber(), undo_stack_.back()->SequenceNumber());
if (undo_stack_.size() == kMaximumUndoStackDepth) {
@@ -51,10 +50,14 @@ void UndoStack::RegisterUndoStep(UndoStep* step) {
if (!in_redo_)
redo_stack_.clear();
undo_stack_.push_back(step);
+ DidSetEndingSelection(step);
}
void UndoStack::RegisterRedoStep(UndoStep* step) {
- EnsureListeningMemoryPressure();
+#if DCHECK_IS_ON()
+ if (auto* element = step->EndingRootEditableElement())
+ DCHECK(element->HasUndoStack()) << element;
+#endif
redo_stack_.push_back(step);
}
@@ -90,7 +93,6 @@ void UndoStack::Redo() {
void UndoStack::Clear() {
undo_stack_.clear();
redo_stack_.clear();
- StopListeningMemoryPressure();
}
void UndoStack::Trace(Visitor* visitor) const {
@@ -109,24 +111,13 @@ UndoStack::UndoStepRange UndoStack::UndoSteps() const {
return UndoStepRange(undo_stack_);
}
-void UndoStack::EnsureListeningMemoryPressure() {
- if (is_listen_memory_pressure_)
- return;
- MemoryPressureListenerRegistry::Instance().RegisterClient(this);
- is_listen_memory_pressure_ = true;
+void UndoStack::DidSetEndingSelection(UndoStep* step) {
+ if (auto* element = step->EndingRootEditableElement())
+ element->SetHasUndoStack(true);
}
-void UndoStack::StopListeningMemoryPressure() {
- if (!is_listen_memory_pressure_)
- return;
- DCHECK(undo_stack_.IsEmpty());
- DCHECK(redo_stack_.IsEmpty());
- MemoryPressureListenerRegistry::Instance().UnregisterClient(this);
- is_listen_memory_pressure_ = false;
-}
-
-void UndoStack::OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel) {
+void UndoStack::ElementRemoved(Element* element) {
+ DCHECK(element->HasUndoStack()) << element;
// In design mode, every root editable elements can be reinserted.
if (!undo_stack_.IsEmpty() &&
undo_stack_.front()->GetDocument().InDesignMode())
@@ -135,17 +126,19 @@ void UndoStack::OnMemoryPressure(
redo_stack_.front()->GetDocument().InDesignMode())
return;
- const auto is_disconnected = [](const UndoStep* undo_step) {
- return !undo_step->IsConnected();
+ const auto should_be_erased = [&element](const UndoStep* undo_step) {
+ return undo_step->IsOwnedBy(*element);
};
undo_stack_.erase(
- std::remove_if(undo_stack_.begin(), undo_stack_.end(), is_disconnected),
+ std::remove_if(undo_stack_.begin(), undo_stack_.end(), should_be_erased),
undo_stack_.end());
redo_stack_.erase(
- std::remove_if(redo_stack_.begin(), redo_stack_.end(), is_disconnected),
+ std::remove_if(redo_stack_.begin(), redo_stack_.end(), should_be_erased),
redo_stack_.end());
+
+ element->SetHasUndoStack(false);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.h b/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.h
index 4f3727b7335..1f6852154e8 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/undo_stack.h
@@ -31,26 +31,25 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_UNDO_STACK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_UNDO_STACK_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
-#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
+class Element;
class LocalFrame;
class UndoStep;
// |UndoStack| is owned by and always 1:1 to |Editor|. Since |Editor| is 1:1 to
// |LocalFrame|, |UndoStack| is also 1:1 to |LocalFrame|.
-class CORE_EXPORT UndoStack final : public GarbageCollected<UndoStack>,
- public MemoryPressureListener {
+class CORE_EXPORT UndoStack final : public GarbageCollected<UndoStack> {
using UndoStepStack = HeapVector<Member<UndoStep>>;
public:
UndoStack();
+ UndoStack(const UndoStack&) = delete;
+ UndoStack& operator=(const UndoStack&) = delete;
void RegisterUndoStep(UndoStep*);
void RegisterRedoStep(UndoStep*);
@@ -77,22 +76,19 @@ class CORE_EXPORT UndoStack final : public GarbageCollected<UndoStack>,
UndoStepRange RedoSteps() const;
UndoStepRange UndoSteps() const;
- void Trace(Visitor*) const final;
+ // Called when set ending selection inf |undo_step|.
+ void DidSetEndingSelection(UndoStep* step);
- private:
- void EnsureListeningMemoryPressure();
- void StopListeningMemoryPressure();
+ // Called when |element| is removed by |Node::RemovedFrom()|. |element|
+ // should be root editable element and be in undo/redo stack.
+ void ElementRemoved(Element* element);
- // Implementation of MemoryPressureListener
- void OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel) final;
+ void Trace(Visitor*) const;
+ private:
UndoStepStack undo_stack_;
UndoStepStack redo_stack_;
bool in_redo_ = false;
- bool is_listen_memory_pressure_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(UndoStack);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc b/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc
index 8f7fca43283..b6b97b014ef 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc
@@ -33,9 +33,8 @@ UndoStep::UndoStep(Document* document,
// See |TypingCommand::ForwardDeleteKeyPressed()|
}
-bool UndoStep::IsConnected() const {
- return EndingRootEditableElement() &&
- EndingRootEditableElement()->isConnected();
+bool UndoStep::IsOwnedBy(const Element& element) const {
+ return EndingRootEditableElement() == &element;
}
void UndoStep::Unapply() {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/undo_step.h b/chromium/third_party/blink/renderer/core/editing/commands/undo_step.h
index 3d8fbf386c7..62a60ab21f1 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/undo_step.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/undo_step.h
@@ -45,8 +45,8 @@ class UndoStep final : public GarbageCollected<UndoStep> {
const SelectionForUndoStep& starting_selection,
const SelectionForUndoStep& ending_selection);
- // Returns true if associated root editable elements are connected.
- bool IsConnected() const;
+ // Returns true if is owned by |element|
+ bool IsOwnedBy(const Element& element) const;
void Unapply();
void Reapply();
void Append(SimpleEditCommand*);
diff --git a/chromium/third_party/blink/renderer/core/editing/drag_caret.h b/chromium/third_party/blink/renderer/core/editing/drag_caret.h
index b0d392533aa..05855fe927c 100644
--- a/chromium/third_party/blink/renderer/core/editing/drag_caret.h
+++ b/chromium/third_party/blink/renderer/core/editing/drag_caret.h
@@ -29,7 +29,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
#include "third_party/blink/renderer/core/editing/caret_display_item_client.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
@@ -45,6 +44,8 @@ class DragCaret final : public GarbageCollected<DragCaret>,
public SynchronousMutationObserver {
public:
DragCaret();
+ DragCaret(const DragCaret&) = delete;
+ DragCaret& operator=(const DragCaret&) = delete;
virtual ~DragCaret();
// Paint invalidation methods delegating to CaretDisplayItemClient.
@@ -74,8 +75,6 @@ class DragCaret final : public GarbageCollected<DragCaret>,
PositionWithAffinity position_;
const std::unique_ptr<CaretDisplayItemClient> display_item_client_;
-
- DISALLOW_COPY_AND_ASSIGN(DragCaret);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc b/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc
index 38bb91fc94f..c3a7ecb2ebe 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc
@@ -237,14 +237,17 @@ const char* EditingBehavior::InterpretKeyEvent(
if (key_event->GetType() == WebInputEvent::Type::kRawKeyDown) {
int map_key = modifiers << 16 | event.keyCode();
- const char* name = map_key ? key_down_commands_map->at(map_key) : nullptr;
+ const char* name =
+ map_key ? key_down_commands_map->DeprecatedAtOrEmptyValue(map_key)
+ : nullptr;
if (!name)
name = LookupCommandNameFromDomKeyKeyDown(event.key(), modifiers);
return name;
}
int map_key = modifiers << 16 | event.charCode();
- return map_key ? key_press_commands_map->at(map_key) : nullptr;
+ return map_key ? key_press_commands_map->DeprecatedAtOrEmptyValue(map_key)
+ : nullptr;
}
bool EditingBehavior::ShouldInsertCharacter(const KeyboardEvent& event) const {
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 06401b2c25a..81ba282d7fa 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 "base/trace_event/trace_event.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"
@@ -300,9 +301,9 @@ int16_t ComparePositions(const Position& a, const Position& b) {
int16_t bias = 0;
if (node_a == node_b) {
if (has_descendent_a)
- bias = -1;
- else if (has_descendent_b)
bias = 1;
+ else if (has_descendent_b)
+ bias = -1;
}
int16_t result =
@@ -787,6 +788,14 @@ int FindNextBoundaryOffset(const String& str, int current) {
return current + machine.FinalizeAndGetBoundaryOffset();
}
+// Explicit instantiation to avoid link error for the usage in EditContext.
+template int FindNextBoundaryOffset<BackwardGraphemeBoundaryStateMachine>(
+ const String& str,
+ int current);
+template int FindNextBoundaryOffset<ForwardGraphemeBoundaryStateMachine>(
+ const String& str,
+ int current);
+
int PreviousGraphemeBoundaryOf(const Node& node, int current) {
// TODO(yosin): Need to support grapheme crossing |Node| boundary.
DCHECK_GE(current, 0);
diff --git a/chromium/third_party/blink/renderer/core/editing/editor.cc b/chromium/third_party/blink/renderer/core/editing/editor.cc
index 7f3250383ee..2e4c5340889 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor.cc
@@ -360,6 +360,10 @@ bool Editor::DeleteSelectionAfterDraggingWithEvents(
if (frame_->GetDocument()->GetFrame() != frame_)
return false;
+ // No DOM mutation if EditContext is active.
+ if (frame_->GetInputMethodController().GetActiveEditContext())
+ return true;
+
if (should_delete && drag_source->isConnected()) {
DeleteSelectionWithSmartDelete(delete_mode,
InputEvent::InputType::kDeleteByDrag,
@@ -394,6 +398,10 @@ bool Editor::ReplaceSelectionAfterDraggingWithEvents(
if (frame_->GetDocument()->GetFrame() != frame_)
return false;
+ // No DOM mutation if EditContext is active.
+ if (frame_->GetInputMethodController().GetActiveEditContext())
+ return true;
+
if (should_insert && drop_target->isConnected())
ReplaceSelectionAfterDragging(fragment, insert_mode, drag_source_type);
diff --git a/chromium/third_party/blink/renderer/core/editing/editor.h b/chromium/third_party/blink/renderer/core/editing/editor.h
index 8f8d1abd92e..b9bc273644b 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor.h
+++ b/chromium/third_party/blink/renderer/core/editing/editor.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "mojo/public/mojom/base/text_direction.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
@@ -67,6 +66,8 @@ enum class EditorCommandSource { kMenuOrKeyBinding, kDOM };
class CORE_EXPORT Editor final : public GarbageCollected<Editor> {
public:
explicit Editor(LocalFrame&);
+ Editor(const Editor&) = delete;
+ Editor& operator=(const Editor&) = delete;
~Editor();
CompositeEditCommand* LastEditCommand() { return last_edit_command_.Get(); }
@@ -251,8 +252,6 @@ class CORE_EXPORT Editor final : public GarbageCollected<Editor> {
FrameSelection& GetFrameSelection() const;
bool HandleEditingKeyboardEvent(KeyboardEvent*);
-
- DISALLOW_COPY_AND_ASSIGN(Editor);
};
inline void Editor::SetStartNewKillRingSequence(bool flag) {
diff --git a/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc b/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc
index 8cef9caa7cd..fdd4969033f 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc
@@ -66,9 +66,8 @@ bool Editor::HandleEditingKeyboardEvent(KeyboardEvent* evt) {
// If EditContext is active, redirect text to EditContext, otherwise, send
// text to the focused element.
- auto* edit_context =
- GetFrame().GetInputMethodController().GetActiveEditContext();
- if (edit_context) {
+ if (auto* edit_context =
+ GetFrame().GetInputMethodController().GetActiveEditContext()) {
if (DispatchBeforeInputInsertText(evt->target()->ToNode(),
key_event->text) !=
DispatchEventResult::kNotCanceled)
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 781a8a53626..709b2165260 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor_test.cc
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
-#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
@@ -140,14 +139,7 @@ TEST_F(EditorTest, RedoWithDisconnectedEditable) {
ASSERT_EQ(1, SizeOfRedoStack());
ASSERT_EQ(0, SizeOfUndoStack());
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
- ASSERT_EQ(1, SizeOfRedoStack());
- ASSERT_EQ(0, SizeOfUndoStack());
-
target.remove();
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
EXPECT_EQ(0, SizeOfRedoStack())
<< "We don't need to have redo steps for removed <input>";
EXPECT_EQ(0, SizeOfUndoStack());
@@ -167,14 +159,7 @@ TEST_F(EditorTest, RedoWithDisconnectedInput) {
ASSERT_EQ(1, SizeOfRedoStack());
ASSERT_EQ(0, SizeOfUndoStack());
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
- ASSERT_EQ(1, SizeOfRedoStack());
- ASSERT_EQ(0, SizeOfUndoStack());
-
input.remove();
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
EXPECT_EQ(0, SizeOfRedoStack())
<< "We don't need to have redo steps for removed <input>";
EXPECT_EQ(0, SizeOfUndoStack());
@@ -191,14 +176,7 @@ TEST_F(EditorTest, UndoWithDisconnectedEditable) {
ASSERT_EQ(0, SizeOfRedoStack());
ASSERT_EQ(1, SizeOfUndoStack());
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
- ASSERT_EQ(0, SizeOfRedoStack());
- ASSERT_EQ(1, SizeOfUndoStack());
-
target.remove();
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
EXPECT_EQ(0, SizeOfRedoStack());
EXPECT_EQ(0, SizeOfUndoStack())
<< "We don't need to have undo steps for removed editable";
@@ -214,14 +192,8 @@ TEST_F(EditorTest, UndoWithDisconnectedInput) {
ASSERT_EQ(0, SizeOfRedoStack());
ASSERT_EQ(1, SizeOfUndoStack());
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
- ASSERT_EQ(0, SizeOfRedoStack());
- ASSERT_EQ(1, SizeOfUndoStack());
input.remove();
- MemoryPressureListenerRegistry::Instance().OnMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
EXPECT_EQ(0, SizeOfRedoStack());
EXPECT_EQ(0, SizeOfUndoStack())
<< "We don't need to have undo steps for removed <input>";
diff --git a/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc b/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc
index 2571bab072f..e7999c3f65e 100644
--- a/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc
+++ b/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc
@@ -43,6 +43,9 @@ class ElementInnerTextCollector final {
public:
ElementInnerTextCollector() = default;
+ ElementInnerTextCollector(const ElementInnerTextCollector&) = delete;
+ ElementInnerTextCollector& operator=(const ElementInnerTextCollector&) =
+ delete;
String RunOn(const Element& element);
@@ -51,8 +54,9 @@ class ElementInnerTextCollector final {
class Result final {
public:
Result() = default;
+ Result(const Result&) = delete;
+ Result& operator=(const Result&) = delete;
- void EmitChar16(UChar code_point);
void EmitNewline();
void EmitRequiredLineBreak(int count);
void EmitTab();
@@ -64,8 +68,6 @@ class ElementInnerTextCollector final {
StringBuilder builder_;
int required_line_break_count_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(Result);
};
static bool HasDisplayContentsStyle(const Node& node);
@@ -87,8 +89,6 @@ class ElementInnerTextCollector final {
// Result character buffer.
Result result_;
-
- DISALLOW_COPY_AND_ASSIGN(ElementInnerTextCollector);
};
String ElementInnerTextCollector::RunOn(const Element& element) {
@@ -267,11 +267,8 @@ void ElementInnerTextCollector::ProcessNode(const Node& node) {
// 2. If the node is display locked, then we should not process it or its
// children, since they are not visible or accessible via innerText.
- if (auto* element = DynamicTo<Element>(node)) {
- auto* context = element->GetDisplayLockContext();
- if (context && context->IsLocked())
- return;
- }
+ if (DisplayLockUtilities::NearestLockedInclusiveAncestor(node))
+ return;
// 3. If node's computed value of 'visibility' is not 'visible', then return
// items.
@@ -405,12 +402,6 @@ void ElementInnerTextCollector::ProcessTextNode(const Text& node) {
// ----
-void ElementInnerTextCollector::Result::EmitChar16(UChar code_point) {
- FlushRequiredLineBreak();
- DCHECK_EQ(required_line_break_count_, 0);
- builder_.Append(code_point);
-}
-
void ElementInnerTextCollector::Result::EmitNewline() {
FlushRequiredLineBreak();
builder_.Append(kNewlineCharacter);
diff --git a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc
index d95b3918b26..9b4086f6b79 100644
--- a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include <ostream> // NOLINT
+#include "third_party/blink/renderer/core/dom/abstract_range.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"
@@ -58,6 +59,14 @@ EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(
: EphemeralRangeTemplate(position, position) {}
template <typename Strategy>
+EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(
+ const AbstractRange* range)
+ : EphemeralRangeTemplate(PositionTemplate<Strategy>(range->startContainer(),
+ range->startOffset()),
+ PositionTemplate<Strategy>(range->endContainer(),
+ range->endOffset())) {}
+
+template <typename Strategy>
EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(const Range* range) {
if (!range)
return;
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 1fcfbde40fa..ab7ea7d81c2 100644
--- a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h
+++ b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h
@@ -11,6 +11,7 @@
namespace blink {
class Document;
+class AbstractRange;
class Range;
// We should restrict access to the unwanted version of |TraversalRange::end()|
@@ -91,6 +92,7 @@ class EphemeralRangeTemplate final {
// |position| should be |Position::isNull()| or in-document.
explicit EphemeralRangeTemplate(
const PositionTemplate<Strategy>& /* position */);
+ explicit EphemeralRangeTemplate(const AbstractRange*);
// When |range| is nullptr, |EphemeralRangeTemplate| is |isNull()|.
explicit EphemeralRangeTemplate(const Range* /* range */);
EphemeralRangeTemplate();
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc b/chromium/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc
index 8163219c1fa..d43d50430f4 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/editing/finder/async_find_buffer.h"
+#include "base/metrics/histogram_macros.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/finder/find_buffer.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h
index 015789b7b72..f2b53a0059c 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
#include "third_party/blink/renderer/core/editing/finder/find_options.h"
#include "third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h"
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 17071c52296..bc6f53c4931 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
@@ -77,7 +77,7 @@ static FloatRect ToNormalizedRect(const FloatRect& absolute_rect,
// For scrolling we need to get where the actual origin is independently of
// the scroll.
if (container->IsScrollContainer())
- overflow_rect.Move(-PhysicalOffset(container->ScrolledContentOffset()));
+ overflow_rect.Move(-container->ScrolledContentOffset());
FloatRect container_rect(container->LocalToAbsoluteRect(overflow_rect));
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
index 872cb300e4e..fde9373b8b1 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
@@ -167,7 +167,9 @@ void FindTaskController::StartRequest(
int identifier,
const WebString& search_text,
const mojom::blink::FindOptions& options) {
- TRACE_EVENT_ASYNC_BEGIN0("blink", "FindInPageRequest", identifier);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+ "blink", "FindInPageRequest",
+ TRACE_ID_WITH_SCOPE("FindInPageRequest", identifier));
current_request_start_time_ = base::TimeTicks::Now();
total_task_duration_for_current_request_ = base::TimeDelta();
task_count_for_current_request_ = 0;
@@ -252,8 +254,10 @@ void FindTaskController::DidFinishTask(
void FindTaskController::RecordRequestMetrics(
RequestEndState request_end_state) {
bool aborted = (request_end_state == RequestEndState::ABORTED);
- TRACE_EVENT_ASYNC_END1("blink", "FindInPageRequest", current_find_identifier_,
- "aborted", aborted);
+ TRACE_EVENT_NESTABLE_ASYNC_END1(
+ "blink", "FindInPageRequest",
+ TRACE_ID_WITH_SCOPE("FindInPageRequest", current_find_identifier_),
+ "aborted", aborted);
if (aborted) {
UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.FindInPage.TotalTaskDuration.Aborted",
total_task_duration_for_current_request_);
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h
index 9e8d4277746..48827e0265b 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h
@@ -9,9 +9,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 13dd10f3e30..cb8e8e22354 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
@@ -58,6 +58,7 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/html_details_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -105,6 +106,43 @@ static void ScrollToVisible(Range* match) {
&first_node, DocumentUpdateReason::kFindInPage);
}
+ // If the active match is hidden inside a <details> element, then we should
+ // expand it so find-in-page can scroll to it.
+ if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) {
+ bool details_opened = false;
+
+ for (Node& parent : FlatTreeTraversal::AncestorsOf(first_node)) {
+ if (HTMLDetailsElement* details = DynamicTo<HTMLDetailsElement>(parent)) {
+ // If the active match is inside the <summary> of a <details>, then we
+ // shouldn't expand the <details> because the active match is already
+ // visible.
+ bool inside_summary = false;
+ Element& summary = *details->FindMainSummary();
+ for (Node& ancestor : FlatTreeTraversal::AncestorsOf(first_node)) {
+ if (&ancestor == &summary) {
+ inside_summary = true;
+ break;
+ }
+ }
+
+ if (!inside_summary &&
+ !details->FastHasAttribute(html_names::kOpenAttr)) {
+ details->setAttribute(html_names::kOpenAttr, g_empty_atom);
+ details_opened = true;
+ }
+ }
+ }
+
+ if (details_opened) {
+ // If we opened any details elements, we need to update style and layout
+ // to account for the new content to render inside the now-expanded
+ // details element before we scroll to it. The added open attribute may
+ // also affect style.
+ first_node.GetDocument().UpdateStyleAndLayoutForNode(
+ &first_node, DocumentUpdateReason::kFindInPage);
+ }
+ }
+
// We don't always have a LayoutObject for the node we're trying to scroll to
// after the async step: crbug.com/1129341
if (!first_node.GetLayoutObject())
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 db5ded570b1..ca26d049f57 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
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_TEXT_FINDER_H_
#include "base/cancelable_callback.h"
-#include "base/macros.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -118,6 +117,8 @@ class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> {
bool finished_whole_request);
explicit TextFinder(WebLocalFrameImpl& owner_frame);
+ TextFinder(const TextFinder&) = delete;
+ TextFinder& operator=(const TextFinder&) = delete;
class FindMatch {
DISALLOW_NEW();
@@ -278,8 +279,6 @@ class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> {
bool find_match_rects_are_valid_;
base::CancelableOnceClosure scroll_task_;
-
- DISALLOW_COPY_AND_ASSIGN(TextFinder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/frame_caret.h b/chromium/third_party/blink/renderer/core/editing/frame_caret.h
index e8aaf851835..a4f705b5af0 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_caret.h
+++ b/chromium/third_party/blink/renderer/core/editing/frame_caret.h
@@ -52,6 +52,8 @@ class SelectionEditor;
class CORE_EXPORT FrameCaret final : public GarbageCollected<FrameCaret> {
public:
FrameCaret(LocalFrame&, const SelectionEditor&);
+ FrameCaret(const FrameCaret&) = delete;
+ FrameCaret& operator=(const FrameCaret&) = delete;
~FrameCaret();
bool IsActive() const;
@@ -105,8 +107,6 @@ class CORE_EXPORT FrameCaret final : public GarbageCollected<FrameCaret> {
bool is_caret_enabled_ = false;
bool should_show_caret_ = false;
bool is_caret_blinking_suspended_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(FrameCaret);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc b/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc
index ffa64bcf6e9..e0788edea69 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/editing/frame_caret.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/core/editing/commands/typing_command.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
@@ -30,7 +31,13 @@ class FrameCaretTest : public EditingTestBase {
ScopedWebTestMode web_test_mode_{false};
};
-TEST_F(FrameCaretTest, BlinkAfterTyping) {
+#if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
+// https://crbug.com/1222649
+#define MAYBE_BlinkAfterTyping DISABLED_BlinkAfterTyping
+#else
+#define MAYBE_BlinkAfterTyping BlinkAfterTyping
+#endif
+TEST_F(FrameCaretTest, MAYBE_BlinkAfterTyping) {
FrameCaret& caret = Selection().FrameCaretForTesting();
scoped_refptr<scheduler::FakeTaskRunner> task_runner =
base::MakeRefCounted<scheduler::FakeTaskRunner>();
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 85cd04219d1..d72708af56d 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -145,7 +145,7 @@ Element* FrameSelection::RootEditableElementOrDocumentElement() const {
return selection_root ? selection_root : GetDocument().documentElement();
}
-size_t FrameSelection::CharacterIndexForPoint(const IntPoint& point) const {
+wtf_size_t FrameSelection::CharacterIndexForPoint(const IntPoint& point) const {
const EphemeralRange range = GetFrame()->GetEditor().RangeForPoint(point);
if (range.IsNull())
return kNotFound;
@@ -158,6 +158,10 @@ VisibleSelection FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated()
const {
// TODO(editing-dev): Hoist UpdateStyleAndLayout
// to caller. See http://crbug.com/590369 for more details.
+ DisplayLockUtilities::ScopedForcedUpdate base_scope(
+ GetSelectionInDOMTree().Base().AnchorNode());
+ DisplayLockUtilities::ScopedForcedUpdate extent_scope(
+ GetSelectionInDOMTree().Extent().AnchorNode());
GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
return ComputeVisibleSelectionInDOMTree();
}
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 79333a8ff80..3cbc564f365 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.h
@@ -30,8 +30,6 @@
#include <memory>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
#include "third_party/blink/renderer/core/editing/forward.h"
@@ -132,6 +130,8 @@ class CORE_EXPORT FrameSelection final
public SynchronousMutationObserver {
public:
explicit FrameSelection(LocalFrame&);
+ FrameSelection(const FrameSelection&) = delete;
+ FrameSelection& operator=(const FrameSelection&) = delete;
~FrameSelection();
bool IsAvailable() const;
@@ -139,7 +139,7 @@ class CORE_EXPORT FrameSelection final
Document& GetDocument() const;
LocalFrame* GetFrame() const { return frame_; }
Element* RootEditableElementOrDocumentElement() const;
- size_t CharacterIndexForPoint(const IntPoint&) const;
+ wtf_size_t CharacterIndexForPoint(const IntPoint&) const;
// An implementation of |WebFrame::moveCaretSelection()|
void MoveCaretSelection(const IntPoint&);
@@ -342,8 +342,6 @@ class CORE_EXPORT FrameSelection final
std::unique_ptr<GranularityStrategy> granularity_strategy_;
const Member<FrameCaret> frame_caret_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameSelection);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc b/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
index 1d0f2acdc21..56cc80681ed 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
@@ -61,6 +61,11 @@ void CachedTextInputInfo::ClearIfNeeded(const LayoutObject& layout_object) {
offset_map_.clear();
}
+void CachedTextInputInfo::DidChangeVisibility(
+ const LayoutObject& layout_object) {
+ DidLayoutSubtree(layout_object);
+}
+
void CachedTextInputInfo::DidLayoutSubtree(const LayoutObject& layout_object) {
// <div style="contain:strict; ...">abc</div> reaches here.
if (!container_)
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.h b/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.h
index 03f7e91b99d..255b3f32e7c 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.h
+++ b/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info.h
@@ -34,6 +34,7 @@ class CORE_EXPORT CachedTextInputInfo final {
bool IsValidFor(const ContainerNode& element) const;
// For cache invalidation
+ void DidChangeVisibility(const LayoutObject& layout_object);
void DidLayoutSubtree(const LayoutObject& layout_object);
void DidUpdateLayout(const LayoutObject& layout_object);
void LayoutObjectWillBeDestroyed(const LayoutObject& layout_object);
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info_test.cc b/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info_test.cc
index 1b8e8f83997..b90a84ff8a7 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/cached_text_input_info_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/editing/ime/cached_text_input_info.h"
#include "build/build_config.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.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"
@@ -97,4 +98,44 @@ TEST_F(CachedTextInputInfoTest, RelayoutBoundary) {
EXPECT_EQ("abX", GetCachedTextInputInfo().GetText());
}
+// http://crbug.com/1228635
+TEST_F(CachedTextInputInfoTest, VisibilityHiddenToVisible) {
+ GetFrame().Selection().SetSelectionAndEndTyping(SetSelectionTextToBody(
+ "<div contenteditable id=sample>"
+ "<b id=target style='visibility: hidden'>A</b><b>^Z|</b></div>"));
+
+ EXPECT_EQ(PlainTextRange(0, 1),
+ GetInputMethodController().GetSelectionOffsets());
+ EXPECT_EQ("Z", GetCachedTextInputInfo().GetText())
+ << "Texts within visibility:hidden are excluded";
+
+ Element& target = *GetElementById("target");
+ target.style()->setProperty(GetDocument().GetExecutionContext(), "visibility",
+ "visible", "", ASSERT_NO_EXCEPTION);
+
+ EXPECT_EQ(PlainTextRange(1, 2),
+ GetInputMethodController().GetSelectionOffsets());
+ EXPECT_EQ("AZ", GetCachedTextInputInfo().GetText());
+}
+
+// http://crbug.com/1228635
+TEST_F(CachedTextInputInfoTest, VisibilityVisibleToHidden) {
+ GetFrame().Selection().SetSelectionAndEndTyping(SetSelectionTextToBody(
+ "<div contenteditable id=sample>"
+ "<b id=target style='visibility: visible'>A</b><b>^Z|</b></div>"));
+
+ EXPECT_EQ(PlainTextRange(1, 2),
+ GetInputMethodController().GetSelectionOffsets());
+ EXPECT_EQ("AZ", GetCachedTextInputInfo().GetText());
+
+ Element& target = *GetElementById("target");
+ target.style()->setProperty(GetDocument().GetExecutionContext(), "visibility",
+ "hidden", "", ASSERT_NO_EXCEPTION);
+
+ EXPECT_EQ(PlainTextRange(0, 1),
+ GetInputMethodController().GetSelectionOffsets());
+ EXPECT_EQ("Z", GetCachedTextInputInfo().GetText())
+ << "Texts within visibility:hidden are excluded";
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc
index f2da69caa5a..3e00a834abc 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc
@@ -13,11 +13,14 @@
#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
#include "third_party/blink/renderer/core/editing/ime/text_format_update_event.h"
#include "third_party/blink/renderer/core/editing/ime/text_update_event.h"
+#include "third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h"
+#include "third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine.h"
#include "third_party/blink/renderer/core/events/composition_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
+#include "third_party/blink/renderer/platform/text/text_boundaries.h"
#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "ui/base/ime/ime_text_span.h"
@@ -417,7 +420,7 @@ bool EditContext::SetComposition(
selection_end_ = composition_range_start_ + selection_end;
DispatchTextUpdateEvent(update_text, update_range_start, update_range_end,
selection_start_, selection_end_);
- composition_range_end_ = composition_range_start_ + text.length();
+ composition_range_end_ = composition_range_start_ + update_text.length();
DispatchTextFormatEvent(ime_text_spans);
return true;
}
@@ -463,7 +466,7 @@ bool EditContext::InsertText(const WebString& text) {
text_.Substring(selection_end_);
uint32_t update_range_start = selection_start_;
uint32_t update_range_end = selection_end_;
- selection_start_ = selection_start_ + text.length();
+ selection_start_ = selection_start_ + update_text.length();
selection_end_ = selection_start_;
DispatchTextUpdateEvent(update_text, update_range_start, update_range_end,
@@ -471,6 +474,70 @@ bool EditContext::InsertText(const WebString& text) {
return true;
}
+void EditContext::DeleteCurrentSelection() {
+ if (selection_start_ == selection_end_)
+ return;
+
+ StringBuilder stringBuilder;
+ stringBuilder.Append(StringView(text_, 0, selection_start_));
+ stringBuilder.Append(StringView(text_, selection_end_));
+ text_ = stringBuilder.ToString();
+
+ DispatchTextUpdateEvent(String(), selection_start_, selection_end_,
+ selection_start_, selection_start_);
+
+ selection_end_ = selection_start_;
+}
+
+template <typename StateMachine>
+int FindNextBoundaryOffset(const String& str, int current);
+
+void EditContext::DeleteBackward() {
+ // If the current selection is collapsed, delete one grapheme, otherwise,
+ // delete whole selection.
+ if (selection_start_ == selection_end_) {
+ selection_start_ =
+ FindNextBoundaryOffset<BackwardGraphemeBoundaryStateMachine>(
+ text_, selection_start_);
+ }
+
+ DeleteCurrentSelection();
+}
+
+void EditContext::DeleteForward() {
+ if (selection_start_ == selection_end_) {
+ selection_end_ =
+ FindNextBoundaryOffset<ForwardGraphemeBoundaryStateMachine>(
+ text_, selection_start_);
+ }
+
+ DeleteCurrentSelection();
+}
+
+void EditContext::DeleteWordBackward() {
+ if (selection_start_ == selection_end_) {
+ String text16bit(text_);
+ text16bit.Ensure16Bit();
+ // TODO(shihken): implement platform behaviors when the spec is finalized.
+ selection_start_ = FindNextWordBackward(text16bit.Characters16(),
+ text16bit.length(), selection_end_);
+ }
+
+ DeleteCurrentSelection();
+}
+
+void EditContext::DeleteWordForward() {
+ if (selection_start_ == selection_end_) {
+ String text16bit(text_);
+ text16bit.Ensure16Bit();
+ // TODO(shihken): implement platform behaviors when the spec is finalized.
+ selection_end_ = FindNextWordForward(text16bit.Characters16(),
+ text16bit.length(), selection_start_);
+ }
+
+ DeleteCurrentSelection();
+}
+
bool EditContext::CommitText(const WebString& text,
const WebVector<ui::ImeTextSpan>& ime_text_spans,
const WebRange& replacement_range,
@@ -487,8 +554,8 @@ bool EditContext::CommitText(const WebString& text,
if (has_composition_) {
text_ = text_.Substring(0, composition_range_start_) + update_text +
text_.Substring(composition_range_end_);
- selection_start_ = composition_range_start_ + text.length();
- selection_end_ = composition_range_start_ + text.length();
+ selection_start_ = composition_range_start_ + update_text.length();
+ selection_end_ = composition_range_start_ + update_text.length();
update_range_start = composition_range_start_;
update_range_end = composition_range_end_;
} else {
@@ -496,8 +563,8 @@ bool EditContext::CommitText(const WebString& text,
text_.Substring(selection_end_);
update_range_start = selection_start_;
update_range_end = selection_end_;
- selection_start_ = selection_start_ + text.length();
- selection_end_ = selection_end_ + text.length();
+ selection_start_ = selection_start_ + update_text.length();
+ selection_end_ = selection_end_ + update_text.length();
}
new_selection_start = selection_start_;
new_selection_end = selection_end_;
@@ -515,7 +582,7 @@ bool EditContext::CommitText(const WebString& text,
bool EditContext::FinishComposingText(
ConfirmCompositionBehavior selection_behavior) {
- WebString text;
+ String text;
if (has_composition_) {
text = text_.Substring(composition_range_start_, composition_range_end_);
// Fire composition end event.
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h
index 6b40d5b8958..d328c50983d 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h
+++ b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_EDIT_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_EDIT_CONTEXT_H_
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_text_input_mode.h"
#include "third_party/blink/public/platform/web_text_input_type.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
@@ -176,6 +175,11 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData,
// For English typing.
bool InsertText(const WebString& text);
+ void DeleteBackward();
+ void DeleteForward();
+ void DeleteWordBackward();
+ void DeleteWordForward();
+
bool IsVirtualKeyboardPolicyManual() const override;
bool IsEditContextActive() const override;
// Returns whether show()/hide() API is called from virtualkeyboard or not.
@@ -200,6 +204,8 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData,
InputMethodController& GetInputMethodController() const;
+ void DeleteCurrentSelection();
+
// Events fired to JS.
// Fires compositionstart event to JS whenever user starts a composition.
bool DispatchCompositionStartEvent(const String& text);
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc
index 67e11cc344c..d8abfd883b1 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc
@@ -63,7 +63,7 @@ namespace {
Vector<String> ConvertStdVectorOfStdStringsToVectorOfStrings(
const std::vector<std::string>& input) {
Vector<String> output;
- output.ReserveInitialCapacity(input.size());
+ output.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(input.size()));
for (const std::string& val : input) {
output.UncheckedAppend(String::FromUTF8(val));
}
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
index f8bbf52f984..42e47ac1c4e 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
+#include "base/macros.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
@@ -1336,8 +1337,7 @@ bool InputMethodController::DeleteSelectionWithoutAdjustment() {
TypingCommand::UpdateSelectionIfDifferentFromCurrentSelection(
last_typing_command, &GetFrame());
- last_typing_command->DeleteSelection(TypingCommand::kSmartDelete,
- ASSERT_NO_EDITING_ABORT);
+ last_typing_command->DeleteSelection(true, ASSERT_NO_EDITING_ABORT);
return true;
}
@@ -1522,6 +1522,11 @@ void InputMethodController::GetLayoutBounds(gfx::Rect* control_bounds,
*control_bounds = element->BoundsInViewport();
}
+void InputMethodController::DidChangeVisibility(
+ const LayoutObject& layout_object) {
+ cached_text_input_info_.DidChangeVisibility(layout_object);
+}
+
void InputMethodController::DidLayoutSubtree(
const LayoutObject& layout_object) {
cached_text_input_info_.DidLayoutSubtree(layout_object);
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 03ff06b454c..74808e8c0f2 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
@@ -27,7 +27,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_INPUT_METHOD_CONTROLLER_H_
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#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"
@@ -62,6 +61,8 @@ class CORE_EXPORT InputMethodController final
};
explicit InputMethodController(LocalDOMWindow&, LocalFrame&);
+ InputMethodController(const InputMethodController&) = delete;
+ InputMethodController& operator=(const InputMethodController&) = delete;
~InputMethodController() override;
void Trace(Visitor*) const override;
@@ -113,6 +114,7 @@ class CORE_EXPORT InputMethodController final
void DeleteSurroundingText(int before, int after);
void DeleteSurroundingTextInCodePoints(int before, int after);
+ void DidChangeVisibility(const LayoutObject& layout_object);
void DidLayoutSubtree(const LayoutObject& layout_object);
void DidUpdateLayout(const LayoutObject& layout_object);
void LayoutObjectWillBeDestroyed(const LayoutObject& layout_object);
@@ -258,8 +260,6 @@ class CORE_EXPORT InputMethodController final
InputModeOfFocusedElement);
FRIEND_TEST_ALL_PREFIXES(InputMethodControllerTest,
VirtualKeyboardPolicyOfFocusedElement);
-
- DISALLOW_COPY_AND_ASSIGN(InputMethodController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.h b/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.h
index 3f012936cbb..4a0a88097dc 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.h
+++ b/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_FORMAT_UPDATE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_FORMAT_UPDATE_EVENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.h b/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.h
index c651b3a1d99..b7658afd794 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.h
+++ b/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_UPDATE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_UPDATE_EVENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc b/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc
index e86a5bd744e..2f19dc3412b 100644
--- a/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/editing/inline_box_position.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/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
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 aa3e4c1b503..4e1f37f858f 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
@@ -298,6 +298,14 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
return;
while (node_ && (node_ != past_end_node_ || shadow_depth_)) {
+#if DCHECK_IS_ON()
+ // |node_| shouldn't be after |past_end_node_|.
+ if (past_end_node_) {
+ DCHECK_LE(PositionTemplate<Strategy>(node_, 0),
+ PositionTemplate<Strategy>(past_end_node_, 0));
+ }
+#endif
+
if (!should_stop_ && StopsOnFormControls() &&
HTMLFormControlElement::EnclosingFormControlElement(node_))
should_stop_ = true;
@@ -405,60 +413,65 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
? Strategy::FirstChild(*node_)
: nullptr;
if (!next) {
- // 2. If we've already iterated children or they are not available, go to
- // the next sibling node.
- next = Strategy::NextSibling(*node_);
- if (!next) {
- // 3. If we are at the last child, go up the node tree until we find a
- // next sibling.
- ContainerNode* parent_node = Strategy::Parent(*node_);
- while (!next && parent_node) {
- if (node_ == end_node_ ||
- Strategy::IsDescendantOf(*end_container_, *parent_node))
- return;
- bool have_layout_object = node_->GetLayoutObject();
- node_ = parent_node;
- fully_clipped_stack_.Pop();
- parent_node = Strategy::Parent(*node_);
- if (have_layout_object)
- ExitNode();
- if (text_state_.PositionNode()) {
- iteration_progress_ = kHandledChildren;
- return;
+ // 2. If we are skipping children, check that |past_end_node_| is not a
+ // descendant, since we shouldn't iterate past it.
+ if (iteration_progress_ >= kHandledChildren || !past_end_node_ ||
+ !Strategy::IsDescendantOf(*past_end_node_, *node_)) {
+ // 3. If we've already iterated children or they are not available, go
+ // to the next sibling node.
+ next = Strategy::NextSibling(*node_);
+ if (!next) {
+ // 4. If we are at the last child, go up the node tree until we find a
+ // next sibling.
+ ContainerNode* parent_node = Strategy::Parent(*node_);
+ while (!next && parent_node) {
+ if (node_ == end_node_ ||
+ Strategy::IsDescendantOf(*end_container_, *parent_node))
+ return;
+ bool have_layout_object = node_->GetLayoutObject();
+ node_ = parent_node;
+ fully_clipped_stack_.Pop();
+ parent_node = Strategy::Parent(*node_);
+ if (have_layout_object)
+ ExitNode();
+ if (text_state_.PositionNode()) {
+ iteration_progress_ = kHandledChildren;
+ return;
+ }
+ next = Strategy::NextSibling(*node_);
}
- next = Strategy::NextSibling(*node_);
- }
- if (!next && !parent_node && shadow_depth_) {
- // 4. Reached the top of a shadow root. If it's created by author,
- // then try to visit the next
- // sibling shadow root, if any.
- const auto* shadow_root = DynamicTo<ShadowRoot>(node_);
- if (!shadow_root) {
- NOTREACHED();
- should_stop_ = true;
- return;
+ if (!next && !parent_node && shadow_depth_) {
+ // 5. Reached the top of a shadow root. If it's created by author,
+ // then try to visit the next
+ // sibling shadow root, if any.
+ const auto* shadow_root = DynamicTo<ShadowRoot>(node_);
+ if (!shadow_root) {
+ NOTREACHED();
+ should_stop_ = true;
+ return;
+ }
+ if (shadow_root->IsOpen()) {
+ // We are the shadow root; exit from here and go back to
+ // where we were.
+ node_ = &shadow_root->host();
+ iteration_progress_ = kHandledOpenShadowRoots;
+ --shadow_depth_;
+ fully_clipped_stack_.Pop();
+ } else {
+ // If we are in a closed or user-agent shadow root, then go back
+ // to the host.
+ // TODO(kochi): Make sure we treat closed shadow as user agent
+ // shadow here.
+ DCHECK(shadow_root->GetType() == ShadowRootType::kClosed ||
+ shadow_root->IsUserAgent());
+ node_ = &shadow_root->host();
+ iteration_progress_ = kHandledUserAgentShadowRoot;
+ --shadow_depth_;
+ fully_clipped_stack_.Pop();
+ }
+ continue;
}
- if (shadow_root->IsOpen()) {
- // We are the shadow root; exit from here and go back to
- // where we were.
- node_ = &shadow_root->host();
- iteration_progress_ = kHandledOpenShadowRoots;
- --shadow_depth_;
- fully_clipped_stack_.Pop();
- } else {
- // If we are in a closed or user-agent shadow root, then go back to
- // the host.
- // TODO(kochi): Make sure we treat closed shadow as user agent
- // shadow here.
- DCHECK(shadow_root->GetType() == ShadowRootType::kClosed ||
- shadow_root->IsUserAgent());
- node_ = &shadow_root->host();
- iteration_progress_ = kHandledUserAgentShadowRoot;
- --shadow_depth_;
- fully_clipped_stack_.Pop();
- }
- continue;
}
}
fully_clipped_stack_.Pop();
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h
index 24a77ba4693..7d2e109ee24 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_ITERATOR_BEHAVIOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_ITERATOR_BEHAVIOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -106,6 +105,8 @@ class CORE_EXPORT TextIteratorBehavior::Builder final {
public:
explicit Builder(const TextIteratorBehavior&);
Builder();
+ Builder(const Builder&) = delete;
+ Builder& operator=(const Builder&) = delete;
~Builder();
TextIteratorBehavior Build();
@@ -131,8 +132,6 @@ class CORE_EXPORT TextIteratorBehavior::Builder final {
private:
TextIteratorBehavior behavior_;
-
- DISALLOW_COPY_AND_ASSIGN(Builder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h
index 918f2635045..3faf137a419 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h
@@ -26,6 +26,9 @@ class TextIteratorTextNodeHandler {
public:
TextIteratorTextNodeHandler(const TextIteratorBehavior&,
TextIteratorTextState*);
+ TextIteratorTextNodeHandler(const TextIteratorTextNodeHandler&) = delete;
+ TextIteratorTextNodeHandler& operator=(const TextIteratorTextNodeHandler&) =
+ delete;
const Text* GetNode() const { return text_node_; }
@@ -111,8 +114,6 @@ class TextIteratorTextNodeHandler {
// Contains state of emitted text.
TextIteratorTextState& text_state_;
-
- DISALLOW_COPY_AND_ASSIGN(TextIteratorTextNodeHandler);
};
} // namespace blink
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 3c6b368ff8f..bdbb9211fc9 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
@@ -75,7 +75,7 @@ UChar TextIteratorTextState::CharacterAt(unsigned index) const {
String TextIteratorTextState::GetTextForTesting() const {
if (single_character_buffer_)
- return String(&single_character_buffer_, 1);
+ return String(&single_character_buffer_, 1u);
return text_.Substring(text_start_offset_, length());
}
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 29b509cb57f..366a8af03d7 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
@@ -44,6 +44,8 @@ class CORE_EXPORT TextIteratorTextState {
public:
explicit TextIteratorTextState(const TextIteratorBehavior&);
+ TextIteratorTextState(const TextIteratorTextState&) = delete;
+ TextIteratorTextState& operator=(const TextIteratorTextState&) = delete;
// Return properties of the current text.
unsigned length() const { return text_length_; }
@@ -157,8 +159,6 @@ class CORE_EXPORT TextIteratorTextState {
// any other content
bool has_emitted_ = false;
UChar last_character_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(TextIteratorTextState);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.cc
index 5b4cafee0df..09cebdd5202 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.cc
@@ -28,7 +28,6 @@
#include "third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h"
#include <unicode/usearch.h>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/text/text_boundaries.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.h"
@@ -61,6 +60,9 @@ class ICULockableSearcher {
STACK_ALLOCATED();
public:
+ ICULockableSearcher(const ICULockableSearcher&) = delete;
+ ICULockableSearcher& operator=(const ICULockableSearcher&) = delete;
+
static UStringSearch* AcquireSearcher() {
Instance().lock();
return Instance().searcher_;
@@ -95,17 +97,15 @@ class ICULockableSearcher {
#if DCHECK_IS_ON()
bool locked_ = false;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(ICULockableSearcher);
};
} // namespace
static bool IsWholeWordMatch(const UChar* text,
- int text_length,
+ unsigned text_length,
MatchResultICU& result) {
const wtf_size_t result_end = result.start + result.length;
- DCHECK_LE(result_end, static_cast<wtf_size_t>(text_length));
+ DCHECK_LE(result_end, text_length);
UChar32 first_character;
U16_GET(text, 0, result.start, result_end, first_character);
@@ -201,9 +201,10 @@ bool TextSearcherICU::NextMatchResultInternal(MatchResultICU& result) {
}
bool TextSearcherICU::ShouldSkipCurrentMatch(MatchResultICU& result) const {
- int32_t text_length;
- const UChar* text = usearch_getText(searcher_, &text_length);
- DCHECK_LE((int32_t)(result.start + result.length), text_length);
+ int32_t text_length_i32;
+ const UChar* text = usearch_getText(searcher_, &text_length_i32);
+ unsigned text_length = text_length_i32;
+ DCHECK_LE(result.start + result.length, text_length);
DCHECK_GT(result.length, 0u);
if (!normalized_search_text_.IsEmpty() && !IsCorrectKanaMatch(text, result))
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h
index 1f251e96514..31684295f9f 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h
@@ -5,12 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_SEARCHER_ICU_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_SEARCHER_ICU_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/finder/find_options.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
struct UStringSearch;
@@ -26,6 +25,8 @@ class CORE_EXPORT TextSearcherICU {
public:
TextSearcherICU();
+ TextSearcherICU(const TextSearcherICU&) = delete;
+ TextSearcherICU& operator=(const TextSearcherICU&) = delete;
~TextSearcherICU();
void SetPattern(const StringView& pattern, FindOptions options);
@@ -44,8 +45,6 @@ class CORE_EXPORT TextSearcherICU {
wtf_size_t text_length_ = 0;
Vector<UChar> normalized_search_text_;
FindOptions options_;
-
- DISALLOW_COPY_AND_ASSIGN(TextSearcherICU);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu_test.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu_test.cc
index 1bc9a279fd6..6b01bc60baa 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_searcher_icu_test.cc
@@ -118,13 +118,13 @@ TEST(TextSearcherICUTest, BrokenSurrogate) {
TextSearcherICU searcher;
UChar one[1];
one[0] = 0xDB00;
- const String pattern(one, 1);
+ const String pattern(one, 1u);
searcher.SetPattern(pattern, kWholeWord);
UChar two[2];
two[0] = 0x0022;
two[1] = 0xDB00;
- const String text(two, 2);
+ const String text(two, 2u);
searcher.SetText(text.Characters16(), text.length());
// Note: Because even if ICU find U+DB00 but ICU doesn't think U+DB00 as
diff --git a/chromium/third_party/blink/renderer/core/editing/kill_ring.h b/chromium/third_party/blink/renderer/core/editing/kill_ring.h
index 5a7977c6161..bc4899037a3 100644
--- a/chromium/third_party/blink/renderer/core/editing/kill_ring.h
+++ b/chromium/third_party/blink/renderer/core/editing/kill_ring.h
@@ -26,7 +26,6 @@
#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"
@@ -37,13 +36,13 @@ class CORE_EXPORT KillRing {
public:
KillRing() = default;
+ KillRing(const KillRing&) = delete;
+ KillRing& operator=(const KillRing&) = delete;
void Append(const String&);
void Prepend(const String&);
String Yank();
void StartNewSequence();
void SetToYankedState();
-
- DISALLOW_COPY_AND_ASSIGN(KillRing);
};
} // 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 ae7cc6e7871..11f94b6d6e0 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
@@ -173,11 +173,11 @@ struct OldSelectedNodes {
selected_map = std::move(other.selected_map);
}
+ OldSelectedNodes(const OldSelectedNodes&) = delete;
+ OldSelectedNodes& operator=(const OldSelectedNodes&) = delete;
+
SelectionPaintRange* paint_range;
HeapHashMap<Member<const Node>, SelectionState> selected_map;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(OldSelectedNodes);
};
std::ostream& operator<<(std::ostream&, const OldSelectedNodes&);
@@ -200,6 +200,10 @@ struct NewPaintRangeAndSelectedNodes {
selected_objects = std::move(other.selected_objects);
}
+ NewPaintRangeAndSelectedNodes(const NewPaintRangeAndSelectedNodes&) = delete;
+ NewPaintRangeAndSelectedNodes& operator=(
+ const NewPaintRangeAndSelectedNodes&) = delete;
+
void AssertSanity() const {
#if DCHECK_IS_ON()
paint_range->AssertSanity();
@@ -214,9 +218,6 @@ struct NewPaintRangeAndSelectedNodes {
SelectionPaintRange* paint_range;
HeapHashSet<Member<const Node>> selected_objects;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NewPaintRangeAndSelectedNodes);
};
std::ostream& operator<<(std::ostream&, const NewPaintRangeAndSelectedNodes&);
diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection.h b/chromium/third_party/blink/renderer/core/editing/layout_selection.h
index f9ef65d2552..9be39175f8c 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.h
@@ -22,7 +22,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_LAYOUT_SELECTION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_LAYOUT_SELECTION_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc b/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
index b5fd135966c..6ce9928e40c 100644
--- a/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
@@ -174,6 +174,26 @@ TEST_P(ParameterizedLocalCaretRectTest, RtlText) {
Position(foo, 3), TextAffinity::kDownstream)));
}
+TEST_P(ParameterizedLocalCaretRectTest, ClampingAndRounding) {
+ // crbug.com/1228620
+ LoadAhem();
+ SetBodyContent(R"HTML(
+ <style>
+ #root {
+ margin-left: 0.6px;
+ width: 150.6px;
+ text-align: right;
+ font: 30px/30px Ahem;
+ }
+ </style>
+ <div id=root>def</div>)HTML");
+ const Node* text = GetElementById("root")->firstChild();
+ EXPECT_EQ(
+ LocalCaretRect(text->GetLayoutObject(), PhysicalRect(149, 0, 1, 30)),
+ LocalCaretRectOfPosition(
+ PositionWithAffinity(Position(text, 3), TextAffinity::kDownstream)));
+}
+
TEST_P(ParameterizedLocalCaretRectTest, OverflowTextLtr) {
// This test only records the current behavior. Future changes are allowed.
@@ -1162,4 +1182,142 @@ TEST_P(ParameterizedLocalCaretRectTest, OptionWithDisplayContents) {
EXPECT_EQ(end, LocalCaretRectOfPosition(PositionWithAffinity(p)));
}
+TEST_P(ParameterizedLocalCaretRectTest, TextCombineOneTextNode) {
+ if (!LayoutNGEnabled())
+ return;
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "div {"
+ " font: 100px/110px Ahem;"
+ " writing-mode: vertical-rl;"
+ "}"
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML("<div>a<tcy id=target>01234</tcy>b</div>");
+ // LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+ // LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+ // LayoutNGBlockFlow {DIV} at (0,0) size 110x300
+ // LayoutText {#text} at (5,0) size 100x100
+ // text run at (5,0) width 100: "a"
+ // LayoutInline {TCY} at (5,100) size 100x100
+ // LayoutNGTextCombine (anonymous) at (5,100) size 100x100
+ // LayoutText {#text} at (-5,0) size 110x100
+ // text run at (0,0) width 500: "01234"
+ // LayoutText {#text} at (5,200) size 100x100
+ // text run at (5,200) width 100: "b"
+ const auto& target = *GetElementById("target");
+ const auto& text_a = *To<Text>(target.previousSibling());
+ const auto& text_01234 = *To<Text>(target.firstChild());
+ const auto& text_b = *To<Text>(target.nextSibling());
+
+ // text_a
+ EXPECT_EQ(
+ LocalCaretRect(text_a.GetLayoutObject(), PhysicalRect(5, 0, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_a, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_a.GetLayoutObject(), PhysicalRect(5, 100, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_a, 1))));
+
+ // text_01234
+ EXPECT_EQ(
+ LocalCaretRect(text_01234.GetLayoutObject(), PhysicalRect(0, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_01234, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_01234.GetLayoutObject(), PhysicalRect(17, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_01234, 1))));
+ EXPECT_EQ(
+ LocalCaretRect(text_01234.GetLayoutObject(), PhysicalRect(39, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_01234, 2))));
+ EXPECT_EQ(
+ LocalCaretRect(text_01234.GetLayoutObject(), PhysicalRect(61, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_01234, 3))));
+ EXPECT_EQ(
+ LocalCaretRect(text_01234.GetLayoutObject(), PhysicalRect(83, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_01234, 4))));
+ EXPECT_EQ(
+ LocalCaretRect(text_01234.GetLayoutObject(), PhysicalRect(99, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_01234, 5))));
+
+ // text_b
+ EXPECT_EQ(
+ LocalCaretRect(text_b.GetLayoutObject(), PhysicalRect(5, 200, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_b, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_b.GetLayoutObject(), PhysicalRect(5, 299, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_b, 1))));
+}
+
+TEST_P(ParameterizedLocalCaretRectTest, TextCombineTwoTextNodes) {
+ if (!LayoutNGEnabled())
+ return;
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "div {"
+ " font: 100px/110px Ahem;"
+ " writing-mode: vertical-rl;"
+ "}"
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML("<div>a<tcy id=target>012<!-- -->34</tcy>b</div>");
+ // LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+ // LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+ // LayoutNGBlockFlow {DIV} at (0,0) size 110x300
+ // LayoutText {#text} at (5,0) size 100x100
+ // text run at (5,0) width 100: "a"
+ // LayoutInline {TCY} at (5,100) size 100x100
+ // LayoutNGTextCombine (anonymous) at (5,100) size 100x100
+ // LayoutText {#text} at (-5,0) size 66x100
+ // text run at (0,0) width 300: "012"
+ // LayoutText {#text} at (61,0) size 44x100
+ // text run at (300,0) width 200: "34"
+ // LayoutText {#text} at (5,200) size 100x100
+ // text run at (5,200) width 100: "b"
+ const auto& target = *GetElementById("target");
+ const auto& text_a = *To<Text>(target.previousSibling());
+ const auto& text_012 = *To<Text>(target.firstChild());
+ const auto& text_34 = *To<Text>(target.lastChild());
+ const auto& text_b = *To<Text>(target.nextSibling());
+
+ // text_a
+ EXPECT_EQ(
+ LocalCaretRect(text_a.GetLayoutObject(), PhysicalRect(5, 0, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_a, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_a.GetLayoutObject(), PhysicalRect(5, 100, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_a, 1))));
+
+ // text_012
+ EXPECT_EQ(
+ LocalCaretRect(text_012.GetLayoutObject(), PhysicalRect(0, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_012, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_012.GetLayoutObject(), PhysicalRect(17, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_012, 1))));
+ EXPECT_EQ(
+ LocalCaretRect(text_012.GetLayoutObject(), PhysicalRect(39, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_012, 2))));
+ EXPECT_EQ(
+ LocalCaretRect(text_012.GetLayoutObject(), PhysicalRect(61, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_012, 3))));
+
+ // text_34
+ EXPECT_EQ(
+ LocalCaretRect(text_34.GetLayoutObject(), PhysicalRect(61, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_34, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_34.GetLayoutObject(), PhysicalRect(83, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_34, 1))));
+ EXPECT_EQ(
+ LocalCaretRect(text_34.GetLayoutObject(), PhysicalRect(99, 0, 1, 100)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_34, 2))));
+
+ // text_b
+ EXPECT_EQ(
+ LocalCaretRect(text_b.GetLayoutObject(), PhysicalRect(5, 200, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_b, 0))));
+ EXPECT_EQ(
+ LocalCaretRect(text_b.GetLayoutObject(), PhysicalRect(5, 299, 100, 1)),
+ LocalCaretRectOfPosition(PositionWithAffinity(Position(text_b, 1))));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h
index fdffb8129c7..06c6380684a 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h
@@ -21,12 +21,11 @@ class CORE_EXPORT ActiveSuggestionMarker final : public StyleableMarker {
ui::mojom::ImeTextSpanUnderlineStyle underline_style,
Color text_color,
Color background_color);
+ ActiveSuggestionMarker(const ActiveSuggestionMarker&) = delete;
+ ActiveSuggestionMarker& operator=(const ActiveSuggestionMarker&) = delete;
// DocumentMarker implementations
MarkerType GetType() const final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ActiveSuggestionMarker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h
index d4e3665f7ee..438a6361abe 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h
@@ -19,6 +19,10 @@ class CORE_EXPORT ActiveSuggestionMarkerListImpl final
: public DocumentMarkerList {
public:
ActiveSuggestionMarkerListImpl() = default;
+ ActiveSuggestionMarkerListImpl(const ActiveSuggestionMarkerListImpl&) =
+ delete;
+ ActiveSuggestionMarkerListImpl& operator=(
+ const ActiveSuggestionMarkerListImpl&) = delete;
// DocumentMarkerList implementations
DocumentMarker::MarkerType MarkerType() const final;
@@ -46,8 +50,6 @@ class CORE_EXPORT ActiveSuggestionMarkerListImpl final
private:
HeapVector<Member<DocumentMarker>> markers_;
-
- DISALLOW_COPY_AND_ASSIGN(ActiveSuggestionMarkerListImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h
index b3ff246a3c8..de40c9a156e 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h
@@ -23,12 +23,11 @@ class CORE_EXPORT CompositionMarker final : public StyleableMarker {
ui::mojom::ImeTextSpanUnderlineStyle,
Color text_color,
Color background_color);
+ CompositionMarker(const CompositionMarker&) = delete;
+ CompositionMarker& operator=(const CompositionMarker&) = delete;
// DocumentMarker implementations
MarkerType GetType() const final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompositionMarker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h
index a47b6e05559..155ee0e0031 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h
@@ -16,6 +16,9 @@ namespace blink {
class CORE_EXPORT CompositionMarkerListImpl final : public DocumentMarkerList {
public:
CompositionMarkerListImpl() = default;
+ CompositionMarkerListImpl(const CompositionMarkerListImpl&) = delete;
+ CompositionMarkerListImpl& operator=(const CompositionMarkerListImpl&) =
+ delete;
// DocumentMarkerList implementations
DocumentMarker::MarkerType MarkerType() const final;
@@ -43,8 +46,6 @@ class CORE_EXPORT CompositionMarkerListImpl final : public DocumentMarkerList {
private:
HeapVector<Member<DocumentMarker>> markers_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositionMarkerListImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/document_marker.h
index cf25dce4d00..a0523366bc0 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker.h
@@ -25,7 +25,6 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.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/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -46,6 +45,7 @@ class CORE_EXPORT DocumentMarker : public GarbageCollected<DocumentMarker> {
kActiveSuggestionMarkerIndex,
kSuggestionMarkerIndex,
kTextFragmentMarkerIndex,
+ kHighlightMarkerIndex,
kMarkerTypeIndexesCount
};
@@ -57,6 +57,7 @@ class CORE_EXPORT DocumentMarker : public GarbageCollected<DocumentMarker> {
kActiveSuggestion = 1 << kActiveSuggestionMarkerIndex,
kSuggestion = 1 << kSuggestionMarkerIndex,
kTextFragment = 1 << kTextFragmentMarkerIndex,
+ kHighlight = 1 << kHighlightMarkerIndex
};
class MarkerTypesIterator
@@ -125,6 +126,7 @@ class CORE_EXPORT DocumentMarker : public GarbageCollected<DocumentMarker> {
static MarkerTypes TextMatch() { return MarkerTypes(kTextMatch); }
static MarkerTypes Suggestion() { return MarkerTypes(kSuggestion); }
static MarkerTypes TextFragment() { return MarkerTypes(kTextFragment); }
+ static MarkerTypes Highlight() { return MarkerTypes(kHighlight); }
bool Contains(MarkerType type) const { return mask_ & type; }
bool Intersects(const MarkerTypes& types) const {
@@ -145,6 +147,8 @@ class CORE_EXPORT DocumentMarker : public GarbageCollected<DocumentMarker> {
unsigned mask_;
};
+ DocumentMarker(const DocumentMarker&) = delete;
+ DocumentMarker& operator=(const DocumentMarker&) = delete;
virtual ~DocumentMarker();
virtual MarkerType GetType() const = 0;
@@ -175,8 +179,6 @@ class CORE_EXPORT DocumentMarker : public GarbageCollected<DocumentMarker> {
private:
unsigned start_offset_;
unsigned end_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(DocumentMarker);
};
using DocumentMarkerVector = HeapVector<Member<DocumentMarker>>;
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 e567784ccc6..b4786b5a3c3 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
@@ -41,6 +41,8 @@
#include "third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/grammar_marker.h"
#include "third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h"
+#include "third_party/blink/renderer/core/editing/markers/highlight_marker.h"
+#include "third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h"
#include "third_party/blink/renderer/core/editing/markers/spelling_marker.h"
#include "third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h"
@@ -53,7 +55,9 @@
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/highlight/highlight_registry.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -78,6 +82,8 @@ DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(
return DocumentMarker::kSuggestionMarkerIndex;
case DocumentMarker::kTextFragment:
return DocumentMarker::kTextFragmentMarkerIndex;
+ case DocumentMarker::kHighlight:
+ return DocumentMarker::kHighlightMarkerIndex;
}
NOTREACHED();
@@ -100,6 +106,8 @@ DocumentMarkerList* CreateListForType(DocumentMarker::MarkerType type) {
return MakeGarbageCollected<TextMatchMarkerListImpl>();
case DocumentMarker::kTextFragment:
return MakeGarbageCollected<TextFragmentMarkerListImpl>();
+ case DocumentMarker::kHighlight:
+ return MakeGarbageCollected<HighlightMarkerListImpl>();
}
NOTREACHED();
@@ -252,6 +260,18 @@ void DocumentMarkerController::AddTextFragmentMarker(
});
}
+void DocumentMarkerController::AddHighlightMarker(
+ const EphemeralRange& range,
+ const String& highlight_name,
+ const Member<Highlight> highlight) {
+ DCHECK(!document_->NeedsLayoutTreeUpdate());
+ AddMarkerInternal(
+ range, [highlight_name, highlight](int start_offset, int end_offset) {
+ return MakeGarbageCollected<HighlightMarker>(start_offset, end_offset,
+ highlight_name, highlight);
+ });
+}
+
void DocumentMarkerController::PrepareForDestruction() {
Clear();
}
@@ -352,7 +372,7 @@ void DocumentMarkerController::MoveMarkers(const Text& src_node,
return;
DCHECK(!markers_.IsEmpty());
- MarkerLists* const src_markers = markers_.at(&src_node);
+ MarkerLists* const src_markers = markers_.DeprecatedAtOrEmptyValue(&src_node);
if (!src_markers)
return;
@@ -396,7 +416,7 @@ void DocumentMarkerController::RemoveMarkersInternal(
return;
DCHECK(!(markers_.IsEmpty()));
- MarkerLists* const markers = markers_.at(&text);
+ MarkerLists* const markers = markers_.DeprecatedAtOrEmptyValue(&text);
if (!markers)
return;
@@ -522,7 +542,7 @@ DocumentMarker* DocumentMarkerController::FirstMarkerIntersectingOffsetRange(
if (start_offset == node_length && end_offset == node_length)
return nullptr;
- MarkerLists* const markers = markers_.at(&node);
+ MarkerLists* const markers = markers_.DeprecatedAtOrEmptyValue(&node);
if (!markers)
return nullptr;
@@ -572,7 +592,8 @@ DocumentMarkerController::MarkersAroundPosition(
if (!text_node)
continue;
- MarkerLists* const marker_lists = markers_.at(text_node);
+ MarkerLists* const marker_lists =
+ markers_.DeprecatedAtOrEmptyValue(text_node);
if (!marker_lists)
continue;
@@ -625,7 +646,7 @@ DocumentMarkerController::MarkersIntersectingRange(
auto* text_node = DynamicTo<Text>(node);
if (!text_node)
continue;
- MarkerLists* const markers = markers_.at(text_node);
+ MarkerLists* const markers = markers_.DeprecatedAtOrEmptyValue(text_node);
if (!markers)
continue;
@@ -664,7 +685,7 @@ DocumentMarkerVector DocumentMarkerController::MarkersFor(
if (!PossiblyHasMarkers(marker_types))
return result;
- MarkerLists* markers = markers_.at(&text);
+ MarkerLists* markers = markers_.DeprecatedAtOrEmptyValue(&text);
if (!markers)
return result;
@@ -705,6 +726,69 @@ DocumentMarkerVector DocumentMarkerController::Markers() const {
DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
const Text& text) const {
+ DocumentMarkerVector markers_to_paint;
+
+ // Fix overlapping HighlightMarkers that share the same highlight name so
+ // their intersections are not painted twice.
+ // Note: DocumentMarkerController::MarkersFor() returns markers sorted by
+ // start offset.
+ DocumentMarkerVector highlight_markers =
+ MarkersFor(text, DocumentMarker::MarkerTypes(DocumentMarker::kHighlight));
+ HeapVector<Member<HighlightMarker>> highlight_markers_not_overlapping;
+ using NameToHighlightMarkerMap =
+ HashMap<String, Member<HighlightMarker>, StringHash>;
+ NameToHighlightMarkerMap name_to_last_highlight_marker_seen;
+
+ for (const auto& current_marker : highlight_markers) {
+ HighlightMarker* current_highlight_marker =
+ To<HighlightMarker>(current_marker.Get());
+
+ NameToHighlightMarkerMap::AddResult insert_result =
+ name_to_last_highlight_marker_seen.insert(
+ current_highlight_marker->GetHighlightName(),
+ current_highlight_marker);
+
+ if (!insert_result.is_new_entry) {
+ HighlightMarker* stored_highlight_marker =
+ insert_result.stored_value->value;
+ if (current_highlight_marker->StartOffset() >=
+ stored_highlight_marker->EndOffset()) {
+ // Markers don't intersect, so the stored one is fine to be painted.
+ highlight_markers_not_overlapping.push_back(stored_highlight_marker);
+ insert_result.stored_value->value = current_highlight_marker;
+ } else {
+ // Markers overlap, so expand the stored marker to cover both and
+ // discard the current one.
+ stored_highlight_marker->SetEndOffset(
+ std::max(stored_highlight_marker->EndOffset(),
+ current_highlight_marker->EndOffset()));
+ }
+ }
+ }
+
+ for (const auto& name_to_highlight_marker_iterator :
+ name_to_last_highlight_marker_seen) {
+ highlight_markers_not_overlapping.push_back(
+ name_to_highlight_marker_iterator.value.Get());
+ }
+
+ HighlightRegistry* highlight_registry =
+ document_->domWindow()->Supplementable<LocalDOMWindow>::
+ RequireSupplement<HighlightRegistry>();
+ std::sort(highlight_markers_not_overlapping.begin(),
+ highlight_markers_not_overlapping.end(),
+ [highlight_registry](const Member<HighlightMarker>& marker1,
+ const Member<HighlightMarker>& marker2) {
+ return highlight_registry->CompareOverlayStackingPosition(
+ marker1->GetHighlightName(), marker1->GetHighlight(),
+ marker2->GetHighlightName(),
+ marker2->GetHighlight()) ==
+ HighlightRegistry::OverlayStackingPosition::
+ kOverlayStackingPositionBelow;
+ });
+
+ markers_to_paint.AppendVector(highlight_markers_not_overlapping);
+
// We don't render composition or spelling markers that overlap suggestion
// markers.
// Note: DocumentMarkerController::MarkersFor() returns markers sorted by
@@ -714,9 +798,10 @@ DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
if (suggestion_markers.IsEmpty()) {
// If there are no suggestion markers, we can return early as a minor
// performance optimization.
- return MarkersFor(
- text, DocumentMarker::MarkerTypes::AllBut(
- DocumentMarker::MarkerTypes(DocumentMarker::kSuggestion)));
+ markers_to_paint.AppendVector(MarkersFor(
+ text, DocumentMarker::MarkerTypes::AllBut(DocumentMarker::MarkerTypes(
+ DocumentMarker::kSuggestion | DocumentMarker::kHighlight))));
+ return markers_to_paint;
}
const DocumentMarkerVector& markers_overridden_by_suggestion_markers =
@@ -738,7 +823,6 @@ DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
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] <=
@@ -773,7 +857,7 @@ DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
markers_to_paint.AppendVector(MarkersFor(
text, DocumentMarker::MarkerTypes::AllBut(DocumentMarker::MarkerTypes(
DocumentMarker::kComposition | DocumentMarker::kSpelling |
- DocumentMarker::kSuggestion))));
+ DocumentMarker::kSuggestion | DocumentMarker::kHighlight))));
return markers_to_paint;
}
@@ -818,7 +902,7 @@ static void InvalidatePaintForTickmarks(const Node& node) {
void DocumentMarkerController::InvalidateRectsForTextMatchMarkersInNode(
const Text& node) {
- MarkerLists* markers = markers_.at(&node);
+ MarkerLists* markers = markers_.DeprecatedAtOrEmptyValue(&node);
const DocumentMarkerList* const marker_list =
ListForType(markers, DocumentMarker::kTextMatch);
@@ -1081,7 +1165,7 @@ bool DocumentMarkerController::SetTextMatchMarkersActive(const Text& text,
unsigned start_offset,
unsigned end_offset,
bool active) {
- MarkerLists* markers = markers_.at(&text);
+ MarkerLists* markers = markers_.DeprecatedAtOrEmptyValue(&text);
if (!markers)
return false;
@@ -1141,7 +1225,7 @@ void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node,
auto* text_node = DynamicTo<Text>(node);
if (!text_node)
return;
- MarkerLists* markers = markers_.at(text_node);
+ MarkerLists* markers = markers_.DeprecatedAtOrEmptyValue(text_node);
if (!markers)
return;
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 8f5d104efd4..4f50d427fcc 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
@@ -32,7 +32,6 @@
#include <utility>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
#include "third_party/blink/renderer/core/editing/forward.h"
@@ -49,6 +48,7 @@
namespace blink {
class DocumentMarkerList;
+class Highlight;
class SuggestionMarkerProperties;
class CORE_EXPORT DocumentMarkerController final
@@ -56,6 +56,8 @@ class CORE_EXPORT DocumentMarkerController final
public SynchronousMutationObserver {
public:
explicit DocumentMarkerController(Document&);
+ DocumentMarkerController(const DocumentMarkerController&) = delete;
+ DocumentMarkerController& operator=(const DocumentMarkerController&) = delete;
void Clear();
void AddSpellingMarker(const EphemeralRange&,
@@ -78,6 +80,9 @@ class CORE_EXPORT DocumentMarkerController final
void AddSuggestionMarker(const EphemeralRange&,
const SuggestionMarkerProperties&);
void AddTextFragmentMarker(const EphemeralRange&);
+ void AddHighlightMarker(const EphemeralRange&,
+ const String& highlight_name,
+ const Member<Highlight> highlight);
void MoveMarkers(const Text& src_node, int length, const Text& dst_node);
@@ -210,8 +215,6 @@ class CORE_EXPORT DocumentMarkerController final
// without going through the map.
DocumentMarker::MarkerTypes possibly_existing_marker_types_;
const Member<Document> document_;
-
- DISALLOW_COPY_AND_ASSIGN(DocumentMarkerController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_list.h b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_list.h
index 3ca83a282ac..81da5a79160 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_list.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_list.h
@@ -21,6 +21,8 @@ class DocumentMarker;
class CORE_EXPORT DocumentMarkerList
: public GarbageCollected<DocumentMarkerList> {
public:
+ DocumentMarkerList(const DocumentMarkerList&) = delete;
+ DocumentMarkerList& operator=(const DocumentMarkerList&) = delete;
virtual ~DocumentMarkerList();
// Returns the single marker type supported by the list implementation.
@@ -65,9 +67,6 @@ class CORE_EXPORT DocumentMarkerList
protected:
DocumentMarkerList();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DocumentMarkerList);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker.h
index a195077d662..77d4e133e37 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker.h
@@ -18,12 +18,12 @@ class CORE_EXPORT GrammarMarker final : public SpellCheckMarker {
GrammarMarker(unsigned start_offset,
unsigned end_offset,
const String& description);
+ GrammarMarker(const GrammarMarker&) = delete;
+ GrammarMarker& operator=(const GrammarMarker&) = delete;
private:
// DocumentMarker implementations
MarkerType GetType() const final;
-
- DISALLOW_COPY_AND_ASSIGN(GrammarMarker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h
index 26e7ef8e57d..82714ba20b9 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h
@@ -14,11 +14,10 @@ class CORE_EXPORT GrammarMarkerListImpl final
: public SpellCheckMarkerListImpl {
public:
GrammarMarkerListImpl() = default;
+ GrammarMarkerListImpl(const GrammarMarkerListImpl&) = delete;
+ GrammarMarkerListImpl& operator=(const GrammarMarkerListImpl&) = delete;
DocumentMarker::MarkerType MarkerType() const final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GrammarMarkerListImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.cc
new file mode 100644
index 00000000000..d65cb1f324c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.cc
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/highlight_marker.h"
+
+#include "third_party/blink/renderer/core/highlight/highlight.h"
+
+namespace blink {
+
+HighlightMarker::HighlightMarker(unsigned start_offset,
+ unsigned end_offset,
+ const String& highlight_name,
+ const Member<Highlight> highlight)
+ : DocumentMarker(start_offset, end_offset),
+ highlight_name_(highlight_name),
+ highlight_(highlight) {}
+
+DocumentMarker::MarkerType HighlightMarker::GetType() const {
+ return DocumentMarker::kHighlight;
+}
+
+void HighlightMarker::Trace(blink::Visitor* visitor) const {
+ visitor->Trace(highlight_);
+ DocumentMarker::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.h
new file mode 100644
index 00000000000..8ed97be20b9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker.h
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_H_
+
+#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class Highlight;
+
+class CORE_EXPORT HighlightMarker final : public DocumentMarker {
+ public:
+ HighlightMarker(unsigned start_offset,
+ unsigned end_offset,
+ const String& highlight_name,
+ const Member<Highlight> highlight);
+ HighlightMarker(const HighlightMarker&) = delete;
+ HighlightMarker& operator=(const HighlightMarker&) = delete;
+
+ MarkerType GetType() const final;
+ const Highlight* GetHighlight() const { return highlight_; }
+ const AtomicString& GetHighlightName() const { return highlight_name_; }
+
+ void Trace(blink::Visitor*) const override;
+
+ private:
+ const AtomicString highlight_name_;
+ const Member<Highlight> highlight_;
+};
+
+template <>
+struct DowncastTraits<HighlightMarker> {
+ static bool AllowFrom(const DocumentMarker& document_marker) {
+ return document_marker.GetType() == DocumentMarker::kHighlight;
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.cc
new file mode 100644
index 00000000000..522b3b57b56
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.cc
@@ -0,0 +1,71 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h"
+
+#include "third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor.h"
+
+namespace blink {
+
+DocumentMarker::MarkerType HighlightMarkerListImpl::MarkerType() const {
+ return DocumentMarker::kHighlight;
+}
+
+bool HighlightMarkerListImpl::IsEmpty() const {
+ return markers_.IsEmpty();
+}
+
+void HighlightMarkerListImpl::Add(DocumentMarker* marker) {
+ DCHECK_EQ(DocumentMarker::kHighlight, marker->GetType());
+ markers_.push_back(marker);
+}
+
+void HighlightMarkerListImpl::Clear() {
+ markers_.clear();
+}
+
+const HeapVector<Member<DocumentMarker>>& HighlightMarkerListImpl::GetMarkers()
+ const {
+ return markers_;
+}
+
+DocumentMarker* HighlightMarkerListImpl::FirstMarkerIntersectingRange(
+ unsigned start_offset,
+ unsigned end_offset) const {
+ return UnsortedDocumentMarkerListEditor::FirstMarkerIntersectingRange(
+ markers_, start_offset, end_offset);
+}
+
+HeapVector<Member<DocumentMarker>>
+HighlightMarkerListImpl::MarkersIntersectingRange(unsigned start_offset,
+ unsigned end_offset) const {
+ return UnsortedDocumentMarkerListEditor::MarkersIntersectingRange(
+ markers_, start_offset, end_offset);
+}
+
+bool HighlightMarkerListImpl::MoveMarkers(int length,
+ DocumentMarkerList* dst_markers_) {
+ return UnsortedDocumentMarkerListEditor::MoveMarkers(&markers_, length,
+ dst_markers_);
+}
+
+bool HighlightMarkerListImpl::RemoveMarkers(unsigned start_offset, int length) {
+ return UnsortedDocumentMarkerListEditor::RemoveMarkers(&markers_,
+ start_offset, length);
+}
+
+bool HighlightMarkerListImpl::ShiftMarkers(const String&,
+ unsigned offset,
+ unsigned old_length,
+ unsigned new_length) {
+ return UnsortedDocumentMarkerListEditor::ShiftMarkersContentIndependent(
+ &markers_, offset, old_length, new_length);
+}
+
+void HighlightMarkerListImpl::Trace(blink::Visitor* visitor) const {
+ visitor->Trace(markers_);
+ DocumentMarkerList::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h
new file mode 100644
index 00000000000..9c9c40df772
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h
@@ -0,0 +1,48 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_LIST_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_LIST_IMPL_H_
+
+#include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+
+namespace blink {
+
+// Implementation of HighlightMarkerList for Highlight markers.
+class CORE_EXPORT HighlightMarkerListImpl final : public DocumentMarkerList {
+ public:
+ HighlightMarkerListImpl() = default;
+ HighlightMarkerListImpl(const HighlightMarkerListImpl&) = delete;
+ HighlightMarkerListImpl& operator=(const HighlightMarkerListImpl&) = delete;
+
+ DocumentMarker::MarkerType MarkerType() const final;
+
+ bool IsEmpty() const final;
+
+ void Add(DocumentMarker*) final;
+ void Clear() final;
+
+ const HeapVector<Member<DocumentMarker>>& GetMarkers() const final;
+ DocumentMarker* FirstMarkerIntersectingRange(unsigned start_offset,
+ unsigned end_offset) const final;
+ HeapVector<Member<DocumentMarker>> MarkersIntersectingRange(
+ unsigned start_offset,
+ unsigned end_offset) const final;
+
+ bool MoveMarkers(int length, DocumentMarkerList* dst_list) final;
+ bool RemoveMarkers(unsigned start_offset, int length) final;
+ bool ShiftMarkers(const String& node_text,
+ unsigned offset,
+ unsigned old_length,
+ unsigned new_length) final;
+
+ void Trace(blink::Visitor*) const override;
+
+ private:
+ HeapVector<Member<DocumentMarker>> markers_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_LIST_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker.h
index 09bdfc43b8e..7aff42079f1 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker.h
@@ -19,13 +19,13 @@ class CORE_EXPORT SpellCheckMarker : public DocumentMarker {
SpellCheckMarker(unsigned start_offset,
unsigned end_offset,
const String& description);
+ SpellCheckMarker(const SpellCheckMarker&) = delete;
+ SpellCheckMarker& operator=(const SpellCheckMarker&) = delete;
const String& Description() const { return description_; }
private:
const String description_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellCheckMarker);
};
bool CORE_EXPORT IsSpellCheckMarker(const DocumentMarker&);
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h
index e795b9c1b34..eb31ae9aff7 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h
@@ -17,6 +17,9 @@ namespace blink {
// to do this efficiently.
class CORE_EXPORT SpellCheckMarkerListImpl : public DocumentMarkerList {
public:
+ SpellCheckMarkerListImpl(const SpellCheckMarkerListImpl&) = delete;
+ SpellCheckMarkerListImpl& operator=(const SpellCheckMarkerListImpl&) = delete;
+
// DocumentMarkerList implementations
bool IsEmpty() const final;
@@ -49,8 +52,6 @@ class CORE_EXPORT SpellCheckMarkerListImpl : public DocumentMarkerList {
private:
HeapVector<Member<DocumentMarker>> markers_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellCheckMarkerListImpl);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker.h
index efe0bfa63a1..e59f09d8acc 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker.h
@@ -18,12 +18,12 @@ class CORE_EXPORT SpellingMarker final : public SpellCheckMarker {
SpellingMarker(unsigned start_offset,
unsigned end_offset,
const String& description);
+ SpellingMarker(const SpellingMarker&) = delete;
+ SpellingMarker& operator=(const SpellingMarker&) = delete;
private:
// DocumentMarker implementations
MarkerType GetType() const final;
-
- DISALLOW_COPY_AND_ASSIGN(SpellingMarker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h
index 3462d86d79f..4a5ffda2880 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h
@@ -14,11 +14,10 @@ class CORE_EXPORT SpellingMarkerListImpl final
: public SpellCheckMarkerListImpl {
public:
SpellingMarkerListImpl() = default;
+ SpellingMarkerListImpl(const SpellingMarkerListImpl&) = delete;
+ SpellingMarkerListImpl& operator=(const SpellingMarkerListImpl&) = delete;
DocumentMarker::MarkerType MarkerType() const final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpellingMarkerListImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h
index e5e94cac0b6..d860da2d5ec 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_STYLEABLE_MARKER_H_
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "ui/base/ime/mojom/ime_types.mojom-blink.h"
@@ -22,6 +23,8 @@ class CORE_EXPORT StyleableMarker : public DocumentMarker {
ui::mojom::ImeTextSpanUnderlineStyle,
Color text_color,
Color background_color);
+ StyleableMarker(const StyleableMarker&) = delete;
+ StyleableMarker& operator=(const StyleableMarker&) = delete;
// StyleableMarker-specific
Color UnderlineColor() const;
@@ -39,8 +42,6 @@ class CORE_EXPORT StyleableMarker : public DocumentMarker {
const ui::mojom::ImeTextSpanThickness thickness_;
const ui::mojom::ImeTextSpanUnderlineStyle underline_style_;
const Color text_color_;
-
- DISALLOW_COPY_AND_ASSIGN(StyleableMarker);
};
bool CORE_EXPORT IsStyleableMarker(const DocumentMarker&);
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.h
index 87fe667fd92..cfbde3410be 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.h
@@ -32,6 +32,8 @@ class CORE_EXPORT SuggestionMarker final : public StyleableMarker {
SuggestionMarker(unsigned start_offset,
unsigned end_offset,
const SuggestionMarkerProperties&);
+ SuggestionMarker(const SuggestionMarker&) = delete;
+ SuggestionMarker& operator=(const SuggestionMarker&) = delete;
// DocumentMarker implementations
MarkerType GetType() const final;
@@ -59,8 +61,6 @@ class CORE_EXPORT SuggestionMarker final : public StyleableMarker {
const SuggestionType suggestion_type_;
const RemoveOnFinishComposing remove_on_finish_composing_;
const Color suggestion_highlight_color_;
-
- DISALLOW_COPY_AND_ASSIGN(SuggestionMarker);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.cc
index 685ab9c6204..dd998f61f12 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker_replacement_scope.h"
#include "third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h
index 8b1931e790d..f08badfb869 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h
@@ -19,6 +19,8 @@ namespace blink {
class CORE_EXPORT SuggestionMarkerListImpl final : public DocumentMarkerList {
public:
SuggestionMarkerListImpl() = default;
+ SuggestionMarkerListImpl(const SuggestionMarkerListImpl&) = delete;
+ SuggestionMarkerListImpl& operator=(const SuggestionMarkerListImpl&) = delete;
// DocumentMarkerList implementations
DocumentMarker::MarkerType MarkerType() const final;
@@ -58,8 +60,6 @@ class CORE_EXPORT SuggestionMarkerListImpl final : public DocumentMarkerList {
unsigned new_length);
HeapVector<Member<DocumentMarker>> markers_;
-
- DISALLOW_COPY_AND_ASSIGN(SuggestionMarkerListImpl);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc
index 95e2fff765b..ad2a58b620e 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc
@@ -6,9 +6,11 @@
namespace blink {
+SuggestionMarkerProperties::SuggestionMarkerProperties() = default;
SuggestionMarkerProperties::SuggestionMarkerProperties(
const SuggestionMarkerProperties& other) = default;
-SuggestionMarkerProperties::SuggestionMarkerProperties() = default;
+SuggestionMarkerProperties& SuggestionMarkerProperties::operator=(
+ const SuggestionMarkerProperties& other) = default;
SuggestionMarkerProperties::Builder::Builder() = default;
SuggestionMarkerProperties::Builder::Builder(
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h
index e6d9d229be0..cf82e8fc957 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h
@@ -22,8 +22,9 @@ class CORE_EXPORT SuggestionMarkerProperties final {
public:
class CORE_EXPORT Builder;
- SuggestionMarkerProperties(const SuggestionMarkerProperties&);
SuggestionMarkerProperties();
+ SuggestionMarkerProperties(const SuggestionMarkerProperties&);
+ SuggestionMarkerProperties& operator=(const SuggestionMarkerProperties&);
SuggestionMarker::SuggestionType Type() const { return type_; }
SuggestionMarker::RemoveOnFinishComposing RemoveOnFinishComposing() const {
@@ -59,6 +60,8 @@ class CORE_EXPORT SuggestionMarkerProperties::Builder final {
public:
explicit Builder(const SuggestionMarkerProperties&);
Builder();
+ Builder(const Builder&) = delete;
+ Builder& operator=(const Builder&) = delete;
SuggestionMarkerProperties Build() const;
@@ -74,8 +77,6 @@ class CORE_EXPORT SuggestionMarkerProperties::Builder final {
private:
SuggestionMarkerProperties data_;
-
- DISALLOW_COPY_AND_ASSIGN(Builder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_replacement_scope.h b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_replacement_scope.h
index 3eb3b711398..f629fc74482 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_replacement_scope.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_replacement_scope.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_SUGGESTION_MARKER_REPLACEMENT_SCOPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_SUGGESTION_MARKER_REPLACEMENT_SCOPE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -16,14 +15,16 @@ class CORE_EXPORT SuggestionMarkerReplacementScope {
public:
SuggestionMarkerReplacementScope();
+ SuggestionMarkerReplacementScope(const SuggestionMarkerReplacementScope&) =
+ delete;
+ SuggestionMarkerReplacementScope& operator=(
+ const SuggestionMarkerReplacementScope&) = delete;
~SuggestionMarkerReplacementScope();
static bool CurrentlyInScope();
private:
static bool currently_in_scope_;
-
- DISALLOW_COPY_AND_ASSIGN(SuggestionMarkerReplacementScope);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h
index 0e4e3631813..4934f507464 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h
@@ -15,15 +15,14 @@ namespace blink {
class CORE_EXPORT TextFragmentMarker final : public TextMarkerBase {
public:
TextFragmentMarker(unsigned start_offset, unsigned end_offset);
+ TextFragmentMarker(const TextFragmentMarker&) = delete;
+ TextFragmentMarker& operator=(const TextFragmentMarker&) = delete;
// DocumentMarker implementations
MarkerType GetType() const final;
// TextMarkerBase implementations
bool IsActiveMatch() const final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextFragmentMarker);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h
index 33f8058c381..26936a8c98d 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h
@@ -15,12 +15,12 @@ class CORE_EXPORT TextFragmentMarkerListImpl final
: public TextMarkerBaseListImpl {
public:
TextFragmentMarkerListImpl() = default;
+ TextFragmentMarkerListImpl(const TextFragmentMarkerListImpl&) = delete;
+ TextFragmentMarkerListImpl& operator=(const TextFragmentMarkerListImpl&) =
+ delete;
// DocumentMarkerList implementations
DocumentMarker::MarkerType MarkerType() const final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextFragmentMarkerListImpl);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h
index 4e0b3558277..c6f9b590316 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h
@@ -15,11 +15,10 @@ namespace blink {
class CORE_EXPORT TextMarkerBase : public DocumentMarker {
public:
TextMarkerBase(unsigned start_offset, unsigned end_offset);
+ TextMarkerBase(const TextMarkerBase&) = delete;
+ TextMarkerBase& operator=(const TextMarkerBase&) = delete;
virtual bool IsActiveMatch() const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextMarkerBase);
};
bool CORE_EXPORT IsTextMarker(const DocumentMarker&);
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
index 466585300c9..6e3a4d4bc2c 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
@@ -15,6 +15,9 @@ namespace blink {
// TextFragmentMarkerListImpl to implement the MarkerType() method).
class CORE_EXPORT TextMarkerBaseListImpl : public DocumentMarkerList {
public:
+ TextMarkerBaseListImpl(const TextMarkerBaseListImpl&) = delete;
+ TextMarkerBaseListImpl& operator=(const TextMarkerBaseListImpl&) = delete;
+
// DocumentMarkerList implementations
bool IsEmpty() const final;
@@ -40,9 +43,6 @@ class CORE_EXPORT TextMarkerBaseListImpl : public DocumentMarkerList {
protected:
TextMarkerBaseListImpl() = default;
HeapVector<Member<DocumentMarker>> markers_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextMarkerBaseListImpl);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.h
index 519f9953b40..0577ab9ef47 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.h
@@ -46,6 +46,8 @@ class CORE_EXPORT TextMatchMarker final : public TextMarkerBase {
enum class MatchStatus { kInactive, kActive };
TextMatchMarker(unsigned start_offset, unsigned end_offset, MatchStatus);
+ TextMatchMarker(const TextMatchMarker&) = delete;
+ TextMatchMarker& operator=(const TextMatchMarker&) = delete;
// DocumentMarker implementations
MarkerType GetType() const final;
@@ -69,8 +71,6 @@ class CORE_EXPORT TextMatchMarker final : public TextMarkerBase {
MatchStatus match_status_;
LayoutStatus layout_status_ = LayoutStatus::kInvalid;
PhysicalRect rect_;
-
- DISALLOW_COPY_AND_ASSIGN(TextMatchMarker);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h
index df8e2edb25d..6a1b6d9b72a 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h
@@ -20,6 +20,8 @@ class CORE_EXPORT TextMatchMarkerListImpl final
: public TextMarkerBaseListImpl {
public:
TextMatchMarkerListImpl() = default;
+ TextMatchMarkerListImpl(const TextMatchMarkerListImpl&) = delete;
+ TextMatchMarkerListImpl& operator=(const TextMatchMarkerListImpl&) = delete;
// DocumentMarkerList implementations
DocumentMarker::MarkerType MarkerType() const final;
@@ -31,9 +33,6 @@ class CORE_EXPORT TextMatchMarkerListImpl final
bool SetTextMatchMarkersActive(unsigned start_offset,
unsigned end_offset,
bool);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextMatchMarkerListImpl);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/editing/position.cc b/chromium/third_party/blink/renderer/core/editing/position.cc
index c5404220f66..71721aa2ada 100644
--- a/chromium/third_party/blink/renderer/core/editing/position.cc
+++ b/chromium/third_party/blink/renderer/core/editing/position.cc
@@ -148,10 +148,11 @@ PositionTemplate<Strategy>::PositionTemplate(const Node& anchor_node,
: PositionTemplate(&anchor_node, offset) {}
template <typename Strategy>
-PositionTemplate<Strategy>::PositionTemplate(const PositionTemplate& other)
- : anchor_node_(other.anchor_node_),
- offset_(other.offset_),
- anchor_type_(other.anchor_type_) {}
+PositionTemplate<Strategy>::PositionTemplate(const PositionTemplate&) = default;
+
+template <typename Strategy>
+PositionTemplate<Strategy>& PositionTemplate<Strategy>::operator=(
+ const PositionTemplate&) = default;
// static
template <typename Strategy>
diff --git a/chromium/third_party/blink/renderer/core/editing/position.h b/chromium/third_party/blink/renderer/core/editing/position.h
index 334f13ceddd..37f10b04263 100644
--- a/chromium/third_party/blink/renderer/core/editing/position.h
+++ b/chromium/third_party/blink/renderer/core/editing/position.h
@@ -71,6 +71,7 @@ class PositionTemplate {
PositionTemplate(const Node* anchor_node, int offset);
PositionTemplate(const PositionTemplate&);
+ PositionTemplate& operator=(const PositionTemplate&);
// Returns a newly created |Position| with |kOffsetInAnchor|. |offset| can be
// out of bound. Out of bound position is used for computing undo/redo
diff --git a/chromium/third_party/blink/renderer/core/editing/position_test.cc b/chromium/third_party/blink/renderer/core/editing/position_test.cc
index beeef35fdc6..cb639b0f2b3 100644
--- a/chromium/third_party/blink/renderer/core/editing/position_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/position_test.cc
@@ -275,4 +275,29 @@ TEST_F(PositionTest, LastPositionInShadowHost) {
EXPECT_EQ(flat, ToPositionInFlatTree(dom));
}
+TEST_F(PositionTest, ComparePositionsAcrossShadowBoundary) {
+ SetBodyContent("<p id=host>foo</p>");
+ ShadowRoot* shadow_root = SetShadowContent("<div>bar</div>", "host");
+ Element* body = GetDocument().body();
+ Element* host = GetDocument().getElementById("host");
+ Node* child = shadow_root->firstChild();
+ Node* grandchild = child->firstChild();
+ std::array<Node*, 4> nodes = {body, host, child, grandchild};
+ unsigned size = nodes.size();
+ for (unsigned i = 0; i < size; ++i) {
+ for (unsigned j = 0; j < i; ++j) {
+ EXPECT_LT(Position(nodes[j], 0), Position(nodes[i], 0));
+ EXPECT_LT(PositionInFlatTree(nodes[j], 0),
+ PositionInFlatTree(nodes[i], 0));
+ }
+ EXPECT_EQ(Position(nodes[i], 0), Position(nodes[i], 0));
+ EXPECT_EQ(PositionInFlatTree(nodes[i], 0), PositionInFlatTree(nodes[i], 0));
+ for (unsigned j = i + 1; j < size; ++j) {
+ EXPECT_GT(Position(nodes[j], 0), Position(nodes[i], 0));
+ EXPECT_GT(PositionInFlatTree(nodes[j], 0),
+ PositionInFlatTree(nodes[i], 0));
+ }
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/range_in_flat_tree.h b/chromium/third_party/blink/renderer/core/editing/range_in_flat_tree.h
index c1091b5de97..edc941bbcdd 100644
--- a/chromium/third_party/blink/renderer/core/editing/range_in_flat_tree.h
+++ b/chromium/third_party/blink/renderer/core/editing/range_in_flat_tree.h
@@ -12,7 +12,8 @@ namespace blink {
// This is a wrapper class for a range in flat tree that is relocatable by
// relacating the start and end positions in DOM tree.
-class RangeInFlatTree final : public GarbageCollected<RangeInFlatTree> {
+class CORE_EXPORT RangeInFlatTree final
+ : public GarbageCollected<RangeInFlatTree> {
public:
RangeInFlatTree(const PositionInFlatTree& start,
const PositionInFlatTree& end);
diff --git a/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.h b/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.h
index 322212644fb..cc8f9bc9d26 100644
--- a/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.h
+++ b/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.h
@@ -30,7 +30,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_REVEAL_SELECTION_SCOPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_REVEAL_SELECTION_SCOPE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -43,6 +42,8 @@ class RevealSelectionScope {
public:
explicit RevealSelectionScope(LocalFrame&);
+ RevealSelectionScope(const RevealSelectionScope&) = delete;
+ RevealSelectionScope& operator=(const RevealSelectionScope&) = delete;
~RevealSelectionScope();
void Trace(Visitor*) const;
@@ -51,8 +52,6 @@ class RevealSelectionScope {
Editor& GetEditor();
Member<LocalFrame> frame_;
-
- DISALLOW_COPY_AND_ASSIGN(RevealSelectionScope);
};
} // 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 a0ca233b21f..dfe901c66b4 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -477,25 +477,6 @@ bool SelectionController::HandleTapInsideSelection(
return true;
}
-// Returns true if selection starts from |SVGText| node and |target_node| is
-// not the containing block of |SVGText| node.
-// See https://bugs.webkit.org/show_bug.cgi?id=12334 for details.
-static bool ShouldRespectSVGTextBoundaries(
- const Node& target_node,
- const FrameSelection& frame_selection) {
- const PositionInFlatTree& base =
- frame_selection.ComputeVisibleSelectionInFlatTree().Base();
- // TODO(editing-dev): We should use |ComputeContainerNode()|.
- const Node* const base_node = base.AnchorNode();
- if (!base_node)
- return false;
- LayoutObject* const base_layout_object = base_node->GetLayoutObject();
- if (!base_layout_object || !base_layout_object->IsSVGText())
- return false;
- return target_node.GetLayoutObject()->ContainingBlock() !=
- base_layout_object->ContainingBlock();
-}
-
void SelectionController::UpdateSelectionForMouseDrag(
const HitTestResult& hit_test_result,
const PhysicalOffset& drag_start_pos,
@@ -529,11 +510,6 @@ void SelectionController::UpdateSelectionForMouseDrag(
// done in handleMousePressEvent, but not if the mouse press was on an
// existing selection.
- // Special case to limit selection to the containing block for SVG text.
- // TODO(editing_dev): Isn't there a better non-SVG-specific way to do this?
- if (ShouldRespectSVGTextBoundaries(*target, Selection()))
- return;
-
if (selection_state_ == SelectionState::kHaveNotStartedSelection &&
DispatchSelectStart(target) != DispatchEventResult::kNotCanceled)
return;
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 2f68d8f64d0..f4ae79b1150 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SELECTION_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SELECTION_CONTROLLER_H_
-#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/editing/frame_selection.h"
@@ -47,6 +46,8 @@ class CORE_EXPORT SelectionController final
public ExecutionContextLifecycleObserver {
public:
explicit SelectionController(LocalFrame&);
+ SelectionController(const SelectionController&) = delete;
+ SelectionController& operator=(const SelectionController&) = delete;
~SelectionController() override;
void Trace(Visitor*) const override;
@@ -146,8 +147,6 @@ class CORE_EXPORT SelectionController final
kExtendedSelection
};
SelectionState selection_state_;
-
- DISALLOW_COPY_AND_ASSIGN(SelectionController);
};
bool IsSelectionOverLink(const MouseEventWithHitTestResults&);
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 55e2f92e020..3dbab1dc4d5 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
@@ -19,6 +19,10 @@
namespace blink {
class SelectionControllerTest : public EditingTestBase {
+ public:
+ SelectionControllerTest(const SelectionControllerTest&) = delete;
+ SelectionControllerTest& operator=(const SelectionControllerTest&) = delete;
+
protected:
using AppendTrailingWhitespace =
SelectionController::AppendTrailingWhitespace;
@@ -59,9 +63,6 @@ class SelectionControllerTest : public EditingTestBase {
void SetCaretAtHitTestResult(const HitTestResult&);
void SetNonDirectionalSelectionIfNeeded(const SelectionInFlatTree&,
TextGranularity);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SelectionControllerTest);
};
bool SelectionControllerTest::SelectClosestWordFromHitTestResult(
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_editor.h b/chromium/third_party/blink/renderer/core/editing/selection_editor.h
index 0e63030ea47..a1d0ec9f25c 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_editor.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_editor.h
@@ -28,7 +28,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SELECTION_EDITOR_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
@@ -44,6 +43,8 @@ class SelectionEditor final : public GarbageCollected<SelectionEditor>,
public SynchronousMutationObserver {
public:
explicit SelectionEditor(LocalFrame&);
+ SelectionEditor(const SelectionEditor&) = delete;
+ SelectionEditor& operator=(const SelectionEditor&) = delete;
virtual ~SelectionEditor();
void Dispose();
@@ -126,8 +127,6 @@ class SelectionEditor final : public GarbageCollected<SelectionEditor>,
mutable uint64_t style_version_for_absolute_bounds_ =
static_cast<uint64_t>(-1);
#endif
-
- DISALLOW_COPY_AND_ASSIGN(SelectionEditor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier.h b/chromium/third_party/blink/renderer/core/editing/selection_modifier.h
index 31e656096bd..9f028887f54 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SELECTION_MODIFIER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SELECTION_MODIFIER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/visible_selection.h"
@@ -51,6 +50,8 @@ class CORE_EXPORT SelectionModifier {
const SelectionInDOMTree&,
LayoutUnit);
SelectionModifier(const LocalFrame&, const SelectionInDOMTree&);
+ SelectionModifier(const SelectionModifier&) = delete;
+ SelectionModifier& operator=(const SelectionModifier&) = delete;
LayoutUnit XPosForVerticalArrowNavigation() const {
return x_pos_for_vertical_arrow_navigation_;
@@ -130,8 +131,6 @@ class CORE_EXPORT SelectionModifier {
SelectionInFlatTree current_selection_;
LayoutUnit x_pos_for_vertical_arrow_navigation_;
bool selection_is_directional_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(SelectionModifier);
};
LayoutUnit NoXPosForVerticalArrowNavigation();
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc
index e20c56f65c2..c6fbe6f423c 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc
@@ -114,10 +114,8 @@ class AbstractLineBox {
// TODO(yosin): Is kIgnoreTransforms correct here?
PhysicalOffset absolute_block_point = containing_block.LocalToAbsolutePoint(
PhysicalOffset(), kIgnoreTransforms);
- if (containing_block.IsScrollContainer()) {
- absolute_block_point -=
- PhysicalOffset(containing_block.ScrolledContentOffset());
- }
+ if (containing_block.IsScrollContainer())
+ absolute_block_point -= containing_block.ScrolledContentOffset();
if (containing_block.IsHorizontalWritingMode()) {
return PhysicalOffset(line_direction_point - absolute_block_point.left,
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier_test.cc
index 6d20038652b..c0d80faedde 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier_test.cc
@@ -210,7 +210,8 @@ TEST_F(SelectionModifierTest, MoveCaretWithShadow) {
for (Node* node : {a, b, c, d, e, f}) {
if (node == b || node == f) {
modifier.Modify(move, direction, granularity);
- EXPECT_EQ(Position(node, 0), modifier.Selection().Base());
+ EXPECT_EQ(node == b ? Position::BeforeNode(*node) : Position(node, 0),
+ modifier.Selection().Base());
}
modifier.Modify(move, direction, granularity);
EXPECT_EQ(Position(node, 1), modifier.Selection().Base());
@@ -233,7 +234,8 @@ TEST_F(SelectionModifierTest, MoveCaretWithShadow) {
EXPECT_EQ(Position(node, 1), modifier.Selection().Base());
modifier.Modify(move, direction, granularity);
if (node == f || node == b) {
- EXPECT_EQ(Position(node, 0), modifier.Selection().Base());
+ EXPECT_EQ(node == b ? Position::BeforeNode(*node) : Position(node, 0),
+ modifier.Selection().Base());
modifier.Modify(move, direction, granularity);
}
}
@@ -250,7 +252,8 @@ TEST_F(SelectionModifierTest, MoveCaretWithShadow) {
for (Node* node : {a, b, c, d, e, f}) {
if (node == b || node == f) {
modifier.Modify(move, direction, granularity);
- EXPECT_EQ(Position(node, 0), modifier.Selection().Base());
+ EXPECT_EQ(node == b ? Position::BeforeNode(*node) : Position(node, 0),
+ modifier.Selection().Base());
}
modifier.Modify(move, direction, granularity);
EXPECT_EQ(Position(node, skip_space ? 2 : 1),
@@ -274,7 +277,8 @@ TEST_F(SelectionModifierTest, MoveCaretWithShadow) {
EXPECT_EQ(Position(node, 2), modifier.Selection().Base());
modifier.Modify(move, direction, granularity);
if (node == f || node == b) {
- EXPECT_EQ(Position(node, 0), modifier.Selection().Base());
+ EXPECT_EQ(node == b ? Position::BeforeNode(*node) : Position(node, 0),
+ modifier.Selection().Base());
modifier.Modify(move, direction, granularity);
}
}
@@ -292,7 +296,9 @@ TEST_F(SelectionModifierTest, MoveCaretWithShadow) {
for (int i = 0; i <= 3; ++i) {
SelectionModifier modifier(GetFrame(), makeSelection(Position(a, i)));
for (Node* node : {a, b, c, d, e, f}) {
- EXPECT_EQ(Position(node, i), modifier.Selection().Base());
+ EXPECT_EQ(i == 0 && node == b ? Position::BeforeNode(*node)
+ : Position(node, i),
+ modifier.Selection().Base());
modifier.Modify(move, direction, granularity);
}
EXPECT_EQ(Position(f, 3), modifier.Selection().Base());
@@ -305,7 +311,9 @@ TEST_F(SelectionModifierTest, MoveCaretWithShadow) {
for (int i = 0; i <= 3; ++i) {
SelectionModifier modifier(GetFrame(), makeSelection(Position(f, i)));
for (Node* node : {f, e, d, c, b, a}) {
- EXPECT_EQ(Position(node, i), modifier.Selection().Base());
+ EXPECT_EQ(i == 0 && node == b ? Position::BeforeNode(*node)
+ : Position(node, i),
+ modifier.Selection().Base());
modifier.Modify(move, direction, granularity);
}
EXPECT_EQ(Position(a, 0), modifier.Selection().Base());
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 f319f182d5b..67e893bbbdd 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_template.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_template.h
@@ -8,7 +8,6 @@
#include <iosfwd>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/position.h"
@@ -30,10 +29,12 @@ class SelectionTemplate final {
public:
// |Builder| is a helper class for constructing |SelectionTemplate| object.
class CORE_EXPORT Builder final {
- DISALLOW_NEW();
+ STACK_ALLOCATED();
public:
explicit Builder(const SelectionTemplate&);
+ Builder(const Builder&) = delete;
+ Builder& operator=(const Builder&) = delete;
Builder();
SelectionTemplate Build() const;
@@ -72,8 +73,6 @@ class SelectionTemplate final {
private:
SelectionTemplate selection_;
-
- DISALLOW_COPY_AND_ASSIGN(Builder);
};
// Resets selection at end of life time of the object when base and extent
@@ -83,6 +82,9 @@ class SelectionTemplate final {
public:
explicit InvalidSelectionResetter(const SelectionTemplate&);
+ InvalidSelectionResetter(const InvalidSelectionResetter&) = delete;
+ InvalidSelectionResetter& operator=(const InvalidSelectionResetter&) =
+ delete;
~InvalidSelectionResetter();
void Trace(Visitor*) const;
@@ -90,8 +92,6 @@ class SelectionTemplate final {
private:
const Member<const Document> document_;
SelectionTemplate& selection_;
-
- DISALLOW_COPY_AND_ASSIGN(InvalidSelectionResetter);
};
SelectionTemplate(const SelectionTemplate& other);
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/html_interchange.cc b/chromium/third_party/blink/renderer/core/editing/serializers/html_interchange.cc
index 8910a081d57..9b2bb009bf8 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/html_interchange.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/html_interchange.cc
@@ -27,7 +27,6 @@
#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/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
index 6d44ced888c..45061ea4b7a 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
@@ -90,7 +90,8 @@ class MarkupAccumulator::NamespaceContext final {
}
AtomicString LookupNamespaceURI(const AtomicString& prefix) const {
- return prefix_ns_map_.at(prefix ? prefix : g_empty_atom);
+ return prefix_ns_map_.DeprecatedAtOrEmptyValue(prefix ? prefix
+ : g_empty_atom);
}
const AtomicString& ContextNamespace() const { return context_namespace_; }
@@ -108,7 +109,7 @@ class MarkupAccumulator::NamespaceContext final {
}
const Vector<AtomicString> PrefixList(const AtomicString& ns) const {
- return ns_prefixes_map_.at(ns ? ns : g_empty_atom);
+ return ns_prefixes_map_.DeprecatedAtOrEmptyValue(ns ? ns : g_empty_atom);
}
private:
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
index b464cec0d87..7ad28a47905 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
@@ -29,7 +29,6 @@
#include <utility>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/editing/editing_strategy.h"
#include "third_party/blink/renderer/core/editing/serializers/markup_formatter.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
@@ -50,6 +49,8 @@ class MarkupAccumulator {
SerializationType,
IncludeShadowRoots,
ClosedRootsSet = ClosedRootsSet());
+ MarkupAccumulator(const MarkupAccumulator&) = delete;
+ MarkupAccumulator& operator=(const MarkupAccumulator&) = delete;
virtual ~MarkupAccumulator();
template <typename Strategy>
@@ -123,8 +124,6 @@ class MarkupAccumulator {
// https://w3c.github.io/DOM-Parsing/#dfn-generated-namespace-prefix-index
uint32_t prefix_index_;
-
- DISALLOW_COPY_AND_ASSIGN(MarkupAccumulator);
};
extern template String MarkupAccumulator::SerializeNodes<EditingStrategy>(
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 43c14fe9019..35a9ef3f614 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
@@ -27,7 +27,7 @@
#include "third_party/blink/renderer/core/editing/serializers/markup_formatter.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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/document.h"
@@ -76,7 +76,8 @@ static inline void AppendCharactersReplacingEntitiesInternal(
result.Append(text + position_after_last_entity,
i - position_after_last_entity);
const std::string& replacement = entity_maps[entity_index].reference;
- result.Append(replacement.c_str(), replacement.length());
+ result.Append(replacement.c_str(),
+ base::checked_cast<unsigned>(replacement.length()));
position_after_last_entity = i + 1;
break;
}
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h
index bebcba438db..c3dd2753bf1 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_MARKUP_FORMATTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_MARKUP_FORMATTER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/editing/editing_strategy.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -93,6 +92,8 @@ class MarkupFormatter final {
static void AppendXMLDeclaration(StringBuilder&, const Document&);
MarkupFormatter(AbsoluteURLs, SerializationType);
+ MarkupFormatter(const MarkupFormatter&) = delete;
+ MarkupFormatter& operator=(const MarkupFormatter&) = delete;
void AppendStartMarkup(StringBuilder&, const Node&);
void AppendEndMarkup(StringBuilder&, const Element&);
@@ -119,8 +120,6 @@ class MarkupFormatter final {
private:
const AbsoluteURLs resolve_urls_method_;
SerializationType serialization_type_;
-
- DISALLOW_COPY_AND_ASSIGN(MarkupFormatter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h
index bb1f1d8ccb6..66f9699822a 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h
@@ -30,7 +30,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_STYLED_MARKUP_ACCUMULATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_STYLED_MARKUP_ACCUMULATOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/editing/editing_style.h"
#include "third_party/blink/renderer/core/editing/serializers/create_markup_options.h"
#include "third_party/blink/renderer/core/editing/serializers/markup_formatter.h"
@@ -51,6 +50,8 @@ class StyledMarkupAccumulator final {
const TextOffset& end,
Document*,
const CreateMarkupOptions& options);
+ StyledMarkupAccumulator(const StyledMarkupAccumulator&) = delete;
+ StyledMarkupAccumulator& operator=(const StyledMarkupAccumulator&) = delete;
void AppendEndTag(const Element&);
void AppendInterchangeNewline();
@@ -96,8 +97,6 @@ class StyledMarkupAccumulator final {
const CreateMarkupOptions options_;
StringBuilder result_;
Vector<String> reversed_preceding_markup_;
-
- DISALLOW_COPY_AND_ASSIGN(StyledMarkupAccumulator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc
index cebb9e190eb..5103518d216 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.h"
-#include "base/macros.h"
#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/element.h"
@@ -87,6 +86,8 @@ class StyledMarkupTraverser {
public:
StyledMarkupTraverser();
StyledMarkupTraverser(StyledMarkupAccumulator*, Node*);
+ StyledMarkupTraverser(const StyledMarkupTraverser&) = delete;
+ StyledMarkupTraverser& operator=(const StyledMarkupTraverser&) = delete;
Node* Traverse(Node*, Node*);
void WrapWithNode(ContainerNode&, EditingStyle*);
@@ -107,7 +108,6 @@ class StyledMarkupTraverser {
StyledMarkupAccumulator* accumulator_;
Node* last_closed_;
EditingStyle* wrapping_style_;
- DISALLOW_COPY_AND_ASSIGN(StyledMarkupTraverser);
};
template <typename Strategy>
diff --git a/chromium/third_party/blink/renderer/core/editing/set_selection_options.cc b/chromium/third_party/blink/renderer/core/editing/set_selection_options.cc
index fb288805ebd..861dbbae789 100644
--- a/chromium/third_party/blink/renderer/core/editing/set_selection_options.cc
+++ b/chromium/third_party/blink/renderer/core/editing/set_selection_options.cc
@@ -6,9 +6,11 @@
namespace blink {
+SetSelectionOptions::SetSelectionOptions() = default;
SetSelectionOptions::SetSelectionOptions(const SetSelectionOptions& other) =
default;
-SetSelectionOptions::SetSelectionOptions() = default;
+SetSelectionOptions& SetSelectionOptions::operator=(
+ const SetSelectionOptions& other) = default;
SetSelectionOptions::Builder::Builder() = default;
SetSelectionOptions::Builder::Builder(const SetSelectionOptions& data) {
diff --git a/chromium/third_party/blink/renderer/core/editing/set_selection_options.h b/chromium/third_party/blink/renderer/core/editing/set_selection_options.h
index 4d1ec501c82..81f0cc04aa6 100644
--- a/chromium/third_party/blink/renderer/core/editing/set_selection_options.h
+++ b/chromium/third_party/blink/renderer/core/editing/set_selection_options.h
@@ -22,8 +22,9 @@ class CORE_EXPORT SetSelectionOptions final {
public:
class CORE_EXPORT Builder;
- SetSelectionOptions(const SetSelectionOptions&);
SetSelectionOptions();
+ SetSelectionOptions(const SetSelectionOptions&);
+ SetSelectionOptions& operator=(const SetSelectionOptions&);
CursorAlignOnScroll GetCursorAlignOnScroll() const {
return cursor_align_on_scroll_;
@@ -58,6 +59,8 @@ class CORE_EXPORT SetSelectionOptions::Builder final {
public:
explicit Builder(const SetSelectionOptions&);
Builder();
+ Builder(const Builder&) = delete;
+ Builder& operator=(const Builder&) = delete;
SetSelectionOptions Build() const;
@@ -74,8 +77,6 @@ class CORE_EXPORT SetSelectionOptions::Builder final {
private:
SetSelectionOptions data_;
-
- DISALLOW_COPY_AND_ASSIGN(Builder);
};
} // 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 4729715e737..4a923004847 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
@@ -25,6 +25,9 @@ class ColdModeSpellCheckRequester
: public GarbageCollected<ColdModeSpellCheckRequester> {
public:
explicit ColdModeSpellCheckRequester(LocalDOMWindow&);
+ ColdModeSpellCheckRequester(const ColdModeSpellCheckRequester&) = delete;
+ ColdModeSpellCheckRequester& operator=(const ColdModeSpellCheckRequester&) =
+ delete;
void SetNeedsMoreInvocationForTesting() {
needs_more_invocation_for_testing_ = true;
@@ -60,8 +63,6 @@ class ColdModeSpellCheckRequester
// A test-only flag for forcing lifecycle advancing.
mutable bool needs_more_invocation_for_testing_;
-
- DISALLOW_COPY_AND_ASSIGN(ColdModeSpellCheckRequester);
};
}
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h
index 8e5966f432f..323a150c8c3 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h
@@ -21,13 +21,14 @@ class HotModeSpellCheckRequester {
public:
explicit HotModeSpellCheckRequester(SpellCheckRequester&);
+ HotModeSpellCheckRequester(const HotModeSpellCheckRequester&) = delete;
+ HotModeSpellCheckRequester& operator=(const HotModeSpellCheckRequester&) =
+ delete;
void CheckSpellingAt(const Position&);
private:
HeapVector<Member<const Element>> processed_root_editables_;
SpellCheckRequester* requester_;
-
- DISALLOW_COPY_AND_ASSIGN(HotModeSpellCheckRequester);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
index 9ee7d189a34..abc0625ec76 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
@@ -45,6 +45,8 @@ class IdleSpellCheckController::IdleCallback final : public IdleTask {
public:
explicit IdleCallback(IdleSpellCheckController* controller)
: controller_(controller) {}
+ IdleCallback(const IdleCallback&) = delete;
+ IdleCallback& operator=(const IdleCallback&) = delete;
void Trace(Visitor* visitor) const final {
visitor->Trace(controller_);
@@ -55,8 +57,6 @@ class IdleSpellCheckController::IdleCallback final : public IdleTask {
void invoke(IdleDeadline* deadline) final { controller_->Invoke(deadline); }
const Member<IdleSpellCheckController> controller_;
-
- DISALLOW_COPY_AND_ASSIGN(IdleCallback);
};
IdleSpellCheckController::~IdleSpellCheckController() = default;
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
index 2593305adc0..b3966cd163f 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
@@ -30,10 +30,10 @@ class SpellCheckRequester;
class CORE_EXPORT IdleSpellCheckController final
: public GarbageCollected<IdleSpellCheckController>,
public ExecutionContextLifecycleObserver {
- DISALLOW_COPY_AND_ASSIGN(IdleSpellCheckController);
-
public:
explicit IdleSpellCheckController(LocalDOMWindow&, SpellCheckRequester&);
+ IdleSpellCheckController(const IdleSpellCheckController&) = delete;
+ IdleSpellCheckController& operator=(const IdleSpellCheckController&) = delete;
~IdleSpellCheckController() override;
enum class State {
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 71904582cf9..cd4c61394d1 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
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_SPELL_CHECK_REQUESTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_SPELL_CHECK_REQUESTER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/range.h"
@@ -83,6 +82,8 @@ class CORE_EXPORT SpellCheckRequester final
: public GarbageCollected<SpellCheckRequester> {
public:
explicit SpellCheckRequester(LocalDOMWindow&);
+ SpellCheckRequester(const SpellCheckRequester&) = delete;
+ SpellCheckRequester& operator=(const SpellCheckRequester&) = delete;
~SpellCheckRequester();
void Trace(Visitor*) const;
@@ -124,8 +125,6 @@ class CORE_EXPORT SpellCheckRequester final
typedef HeapDeque<Member<SpellCheckRequest>> RequestQueue;
RequestQueue request_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellCheckRequester);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
index 5c6bbb214a3..0521358d7fc 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
@@ -522,6 +522,10 @@ void SpellChecker::ReplaceMisspelledRange(const String& text) {
if (current_document != GetFrame().GetDocument())
return;
+ // No DOM mutation if EditContext is active.
+ if (GetFrame().GetInputMethodController().GetActiveEditContext())
+ return;
+
// TODO(editing-dev): The use of UpdateStyleAndLayout
// needs to be audited. See http://crbug.com/590369 for more details.
GetFrame().GetDocument()->UpdateStyleAndLayout(
@@ -658,8 +662,9 @@ Vector<TextCheckingResult> SpellChecker::FindMisspellings(const String& text) {
DCHECK_LE(misspelling_location + misspelling_length, word_length);
TextCheckingResult misspelling;
misspelling.decoration = kTextDecorationTypeSpelling;
- misspelling.location = word_start + misspelling_location;
- misspelling.length = misspelling_length;
+ misspelling.location =
+ base::checked_cast<int>(word_start + misspelling_location);
+ misspelling.length = base::checked_cast<int>(misspelling_length);
results.push_back(misspelling);
}
word_start = word_end;
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
index 96cf311f0bd..8c07281a834 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_SPELL_CHECKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_SPELL_CHECKER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
@@ -51,6 +50,8 @@ class WebTextCheckClient;
class CORE_EXPORT SpellChecker final : public GarbageCollected<SpellChecker> {
public:
explicit SpellChecker(LocalDOMWindow&);
+ SpellChecker(const SpellChecker&) = delete;
+ SpellChecker& operator=(const SpellChecker&) = delete;
void Trace(Visitor*) const;
@@ -103,8 +104,6 @@ class CORE_EXPORT SpellChecker final : public GarbageCollected<SpellChecker> {
const Member<SpellCheckRequester> spell_check_requester_;
const Member<IdleSpellCheckController> idle_spell_check_controller_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellChecker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/backspace_state_machine.h b/chromium/third_party/blink/renderer/core/editing/state_machines/backspace_state_machine.h
index f07f5bc6178..4e189e08b95 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/backspace_state_machine.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/backspace_state_machine.h
@@ -7,11 +7,10 @@
#include <iosfwd>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/state_machines/text_segmentation_machine_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -20,6 +19,8 @@ class CORE_EXPORT BackspaceStateMachine {
public:
BackspaceStateMachine();
+ BackspaceStateMachine(const BackspaceStateMachine&) = delete;
+ BackspaceStateMachine& operator=(const BackspaceStateMachine&) = delete;
// Prepares by feeding preceding text.
// This method must not be called after feedFollowingCodeUnit().
@@ -63,8 +64,6 @@ class CORE_EXPORT BackspaceStateMachine {
// The internal state.
BackspaceState state_;
-
- DISALLOW_COPY_AND_ASSIGN(BackspaceStateMachine);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.cc
index a63484d5787..d96854e2dbd 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.cc
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.h"
+#include <unicode/utf16.h>
+
#include "base/notreached.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.h b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.h
index 6342023a5c4..775b982fe59 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_code_point_state_machine.h
@@ -5,11 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_BACKWARD_CODE_POINT_STATE_MACHINE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_BACKWARD_CODE_POINT_STATE_MACHINE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/state_machines/text_segmentation_machine_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -18,6 +17,9 @@ class CORE_EXPORT BackwardCodePointStateMachine {
public:
BackwardCodePointStateMachine();
+ BackwardCodePointStateMachine(const BackwardCodePointStateMachine&) = delete;
+ BackwardCodePointStateMachine& operator=(
+ const BackwardCodePointStateMachine&) = delete;
~BackwardCodePointStateMachine() = default;
// Prepares by feeding preceding text.
@@ -44,8 +46,6 @@ class CORE_EXPORT BackwardCodePointStateMachine {
// The internal state.
BackwardCodePointState state_;
-
- DISALLOW_COPY_AND_ASSIGN(BackwardCodePointStateMachine);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h
index fb40c94b060..9cd8a00c1a2 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h
@@ -7,11 +7,10 @@
#include <iosfwd>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/state_machines/text_segmentation_machine_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -20,6 +19,10 @@ class CORE_EXPORT BackwardGraphemeBoundaryStateMachine {
public:
BackwardGraphemeBoundaryStateMachine();
+ BackwardGraphemeBoundaryStateMachine(
+ const BackwardGraphemeBoundaryStateMachine&) = delete;
+ BackwardGraphemeBoundaryStateMachine& operator=(
+ const BackwardGraphemeBoundaryStateMachine&) = delete;
// Find boundary offset by feeding preceding text.
// This method must not be called after feedFollowingCodeUnit().
@@ -66,8 +69,6 @@ class CORE_EXPORT BackwardGraphemeBoundaryStateMachine {
// The internal state.
InternalState internal_state_;
-
- DISALLOW_COPY_AND_ASSIGN(BackwardGraphemeBoundaryStateMachine);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine_test.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine_test.cc
index ca89508aadc..fa08bc73665 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine_test.cc
@@ -39,12 +39,15 @@ const UChar32 kRisS = 0x1F1F8;
class BackwardGraphemeBoundaryStatemachineTest
: public GraphemeStateMachineTestBase {
+ public:
+ BackwardGraphemeBoundaryStatemachineTest(
+ const BackwardGraphemeBoundaryStatemachineTest&) = delete;
+ BackwardGraphemeBoundaryStatemachineTest& operator=(
+ const BackwardGraphemeBoundaryStatemachineTest&) = delete;
+
protected:
BackwardGraphemeBoundaryStatemachineTest() = default;
~BackwardGraphemeBoundaryStatemachineTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BackwardGraphemeBoundaryStatemachineTest);
};
TEST_F(BackwardGraphemeBoundaryStatemachineTest, DoNothingCase) {
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.cc
index 4ae08593bd7..283d5579fc3 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.cc
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.h"
+#include <unicode/utf16.h>
+
#include "base/notreached.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.h b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.h
index 966256cdd74..d27cd898ca3 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_code_point_state_machine.h
@@ -5,11 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_FORWARD_CODE_POINT_STATE_MACHINE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_FORWARD_CODE_POINT_STATE_MACHINE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/state_machines/text_segmentation_machine_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -18,6 +17,9 @@ class CORE_EXPORT ForwardCodePointStateMachine {
public:
ForwardCodePointStateMachine();
+ ForwardCodePointStateMachine(const ForwardCodePointStateMachine&) = delete;
+ ForwardCodePointStateMachine& operator=(const ForwardCodePointStateMachine&) =
+ delete;
~ForwardCodePointStateMachine() = default;
// Prepares by feeding preceding text.
@@ -44,8 +46,6 @@ class CORE_EXPORT ForwardCodePointStateMachine {
// The internal state.
ForwardCodePointState state_;
-
- DISALLOW_COPY_AND_ASSIGN(ForwardCodePointStateMachine);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine.h b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine.h
index 1cd386027cb..53520b09cba 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine.h
@@ -7,11 +7,10 @@
#include <iosfwd>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/state_machines/text_segmentation_machine_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -20,6 +19,10 @@ class CORE_EXPORT ForwardGraphemeBoundaryStateMachine {
public:
ForwardGraphemeBoundaryStateMachine();
+ ForwardGraphemeBoundaryStateMachine(
+ const ForwardGraphemeBoundaryStateMachine&) = delete;
+ ForwardGraphemeBoundaryStateMachine& operator=(
+ const ForwardGraphemeBoundaryStateMachine&) = delete;
// Find boundary offset by feeding preceding text.
// This method must not be called after feedFollowingCodeUnit().
@@ -69,8 +72,6 @@ class CORE_EXPORT ForwardGraphemeBoundaryStateMachine {
// The internal state.
InternalState internal_state_;
-
- DISALLOW_COPY_AND_ASSIGN(ForwardGraphemeBoundaryStateMachine);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine_test.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine_test.cc
index f12b603f506..bcdb89aac81 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/forward_grapheme_boundary_state_machine_test.cc
@@ -42,12 +42,15 @@ const UChar32 kRisS = 0x1F1F8;
class ForwardGraphemeBoundaryStatemachineTest
: public GraphemeStateMachineTestBase {
+ public:
+ ForwardGraphemeBoundaryStatemachineTest(
+ const ForwardGraphemeBoundaryStatemachineTest&) = delete;
+ ForwardGraphemeBoundaryStatemachineTest& operator=(
+ const ForwardGraphemeBoundaryStatemachineTest&) = delete;
+
protected:
ForwardGraphemeBoundaryStatemachineTest() = default;
~ForwardGraphemeBoundaryStatemachineTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ForwardGraphemeBoundaryStatemachineTest);
};
TEST_F(ForwardGraphemeBoundaryStatemachineTest, DoNothingCase) {
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_test_util.h b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_test_util.h
index 5da45148821..ffb37b5c26a 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_test_util.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_test_util.h
@@ -5,10 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_STATE_MACHINE_TEST_UTIL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_STATE_MACHINE_TEST_UTIL_H_
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.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/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -17,6 +16,11 @@ class BackwardGraphemeBoundaryStateMachine;
class ForwardGraphemeBoundaryStateMachine;
class GraphemeStateMachineTestBase : public testing::Test {
+ public:
+ GraphemeStateMachineTestBase(const GraphemeStateMachineTestBase&) = delete;
+ GraphemeStateMachineTestBase& operator=(const GraphemeStateMachineTestBase&) =
+ delete;
+
protected:
GraphemeStateMachineTestBase() = default;
~GraphemeStateMachineTestBase() override = default;
@@ -49,9 +53,6 @@ class GraphemeStateMachineTestBase : public testing::Test {
String ProcessSequenceForward(ForwardGraphemeBoundaryStateMachine*,
const Vector<UChar32>& preceding,
const Vector<UChar32>& following);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GraphemeStateMachineTestBase);
};
} // namespace blink
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 903dfbafb4b..044d610e30a 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
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/editing/state_machines/state_machine_util.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.h b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.h
index 816ae163ca5..d53c7a3d3be 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.h
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_STATE_MACHINES_STATE_MACHINE_UTIL_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/substring_util.h b/chromium/third_party/blink/renderer/core/editing/substring_util.h
index 362edfe00d1..e5d6a32d3db 100644
--- a/chromium/third_party/blink/renderer/core/editing/substring_util.h
+++ b/chromium/third_party/blink/renderer/core/editing/substring_util.h
@@ -34,6 +34,7 @@
#include <cstddef>
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
#if __OBJC__
@class NSAttributedString;
@@ -62,8 +63,10 @@ class SubstringUtil {
// Returns an autoreleased NSAttributedString that is a substring of the
// Frame at the given range, or nil on error.
- CORE_EXPORT static NSAttributedString*
- AttributedSubstringInRange(LocalFrame*, size_t location, size_t length);
+ CORE_EXPORT static NSAttributedString* AttributedSubstringInRange(
+ LocalFrame*,
+ wtf_size_t location,
+ wtf_size_t length);
// Returns an autoreleased NSAttributedString that is a substring of the
// Frame at the given range, or nil on error.
@@ -71,8 +74,8 @@ class SubstringUtil {
// dictionary lookup bubble.
CORE_EXPORT static NSAttributedString* AttributedSubstringInRange(
LocalFrame*,
- size_t location,
- size_t length,
+ wtf_size_t location,
+ wtf_size_t length,
gfx::Point* baseline_point);
};
diff --git a/chromium/third_party/blink/renderer/core/editing/substring_util.mm b/chromium/third_party/blink/renderer/core/editing/substring_util.mm
index ba676fcf705..af63b46b62c 100644
--- a/chromium/third_party/blink/renderer/core/editing/substring_util.mm
+++ b/chromium/third_party/blink/renderer/core/editing/substring_util.mm
@@ -179,17 +179,18 @@ NSAttributedString* SubstringUtil::AttributedWordAtPoint(
return string;
}
-NSAttributedString* SubstringUtil::AttributedSubstringInRange(LocalFrame* frame,
- size_t location,
- size_t length) {
+NSAttributedString* SubstringUtil::AttributedSubstringInRange(
+ LocalFrame* frame,
+ wtf_size_t location,
+ wtf_size_t length) {
return SubstringUtil::AttributedSubstringInRange(frame, location, length,
nil);
}
NSAttributedString* SubstringUtil::AttributedSubstringInRange(
LocalFrame* frame,
- size_t location,
- size_t length,
+ wtf_size_t location,
+ wtf_size_t length,
gfx::Point* baseline_point) {
frame->View()->UpdateStyleAndLayout();
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 4fedba44fdf..a3217f8b967 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
@@ -31,6 +31,8 @@ class CORE_EXPORT TextSuggestionController final
: public GarbageCollected<TextSuggestionController> {
public:
explicit TextSuggestionController(LocalDOMWindow&);
+ TextSuggestionController(const TextSuggestionController&) = delete;
+ TextSuggestionController& operator=(const TextSuggestionController&) = delete;
bool IsMenuOpen() const;
@@ -73,8 +75,6 @@ class CORE_EXPORT TextSuggestionController final
bool is_suggestion_menu_open_;
const Member<LocalDOMWindow> window_;
HeapMojoRemote<mojom::blink::TextSuggestionHost> text_suggestion_host_;
-
- DISALLOW_COPY_AND_ASSIGN(TextSuggestionController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc b/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc
index c2dab2267de..1a03410e04a 100644
--- a/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc
+++ b/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc
@@ -51,14 +51,15 @@ EphemeralRange ComputeRangeFromFrameSelection(LocalFrame* frame) {
} // namespace
-SurroundingText::SurroundingText(LocalFrame* frame, size_t max_length)
+SurroundingText::SurroundingText(LocalFrame* frame, wtf_size_t max_length)
: SurroundingText(ComputeRangeFromFrameSelection(frame), max_length) {}
-SurroundingText::SurroundingText(const EphemeralRange& range, size_t max_length)
+SurroundingText::SurroundingText(const EphemeralRange& range,
+ wtf_size_t max_length)
: start_offset_in_text_content_(0), end_offset_in_text_content_(0) {
const Position start_position = range.StartPosition();
const Position end_position = range.EndPosition();
- const unsigned half_max_length = max_length / 2;
+ const wtf_size_t half_max_length = max_length / 2;
Document* document = start_position.GetDocument();
@@ -126,11 +127,11 @@ String SurroundingText::TextContent() const {
return text_content_;
}
-size_t SurroundingText::StartOffsetInTextContent() const {
+wtf_size_t SurroundingText::StartOffsetInTextContent() const {
return start_offset_in_text_content_;
}
-size_t SurroundingText::EndOffsetInTextContent() const {
+wtf_size_t SurroundingText::EndOffsetInTextContent() const {
return end_offset_in_text_content_;
}
diff --git a/chromium/third_party/blink/renderer/core/editing/surrounding_text.h b/chromium/third_party/blink/renderer/core/editing/surrounding_text.h
index 1891bad6ef0..965ee74a279 100644
--- a/chromium/third_party/blink/renderer/core/editing/surrounding_text.h
+++ b/chromium/third_party/blink/renderer/core/editing/surrounding_text.h
@@ -43,10 +43,10 @@ class CORE_EXPORT SurroundingText {
// Initializes the object with the current selection in a given frame.
// The maximum length of the contents retrieved is defined by max_length.
// It does not include the text inside the range.
- SurroundingText(LocalFrame*, size_t max_length);
+ SurroundingText(LocalFrame*, wtf_size_t max_length);
#if INSIDE_BLINK
- SurroundingText(const EphemeralRange&, size_t max_length);
+ SurroundingText(const EphemeralRange&, wtf_size_t max_length);
#endif
bool IsEmpty() const;
@@ -55,15 +55,15 @@ class CORE_EXPORT SurroundingText {
String TextContent() const;
// Start offset of the initial text in the text content.
- size_t StartOffsetInTextContent() const;
+ wtf_size_t StartOffsetInTextContent() const;
// End offset of the initial text in the text content.
- size_t EndOffsetInTextContent() const;
+ wtf_size_t EndOffsetInTextContent() const;
private:
String text_content_;
- size_t start_offset_in_text_content_;
- size_t end_offset_in_text_content_;
+ wtf_size_t start_offset_in_text_content_;
+ wtf_size_t end_offset_in_text_content_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.h b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.h
index e3aca5b3669..406c9882a7b 100644
--- a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.h
+++ b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.h
@@ -7,7 +7,6 @@
#include <iosfwd>
#include <iterator>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/forward.h"
@@ -155,6 +154,8 @@ class CORE_EXPORT TextOffsetMapping final {
// Constructor |TextOffsetMapping| for the |inline_contents|.
explicit TextOffsetMapping(const InlineContents& inline_contents);
+ TextOffsetMapping(const TextOffsetMapping&) = delete;
+ TextOffsetMapping& operator=(const TextOffsetMapping&) = delete;
~TextOffsetMapping() = default;
@@ -210,8 +211,6 @@ class CORE_EXPORT TextOffsetMapping final {
const TextIteratorBehavior behavior_;
const EphemeralRangeInFlatTree range_;
const String text16_;
-
- DISALLOW_COPY_AND_ASSIGN(TextOffsetMapping);
};
CORE_EXPORT std::ostream& operator<<(std::ostream&,
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 6903907ea35..6ba3584a574 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
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
+#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -510,4 +511,28 @@ TEST_P(ParameterizedTextOffsetMappingTest, InlineContentsWithDocumentBoundary) {
TextOffsetMapping::InlineContents::NextOf(inline_contents).IsNull());
}
+// https://crbug.com/1224206
+TEST_P(ParameterizedTextOffsetMappingTest, ComputeTextOffsetWithBrokenImage) {
+ SetBodyContent("A<img alt='X'>B<div>C</div>D");
+ Element* img = GetDocument().QuerySelector("img");
+ To<HTMLImageElement>(img)->EnsureCollapsedOrFallbackContent();
+ UpdateAllLifecyclePhasesForTest();
+ ShadowRoot* shadow = img->UserAgentShadowRoot();
+ DCHECK(shadow);
+ const Element* alt_img = shadow->getElementById("alttext-image");
+ DCHECK(alt_img);
+
+ const PositionInFlatTree position = PositionInFlatTree::BeforeNode(*alt_img);
+ for (const TextOffsetMapping::InlineContents& inline_contents :
+ {TextOffsetMapping::FindForwardInlineContents(position),
+ TextOffsetMapping::FindBackwardInlineContents(position)}) {
+ const TextOffsetMapping mapping(inline_contents);
+ const String text = mapping.GetText();
+ const unsigned offset = mapping.ComputeTextOffset(position);
+ EXPECT_LE(offset, text.length());
+ EXPECT_EQ("A,B", text);
+ EXPECT_EQ(2u, offset);
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/text_segments.cc b/chromium/third_party/blink/renderer/core/editing/text_segments.cc
index 53ec44c5005..800dc880fd2 100644
--- a/chromium/third_party/blink/renderer/core/editing/text_segments.cc
+++ b/chromium/third_party/blink/renderer/core/editing/text_segments.cc
@@ -40,8 +40,7 @@ PositionInFlatTree TextSegments::FindBoundaryForward(
DCHECK(position.IsNotNull());
PositionInFlatTree last_position = position;
bool is_start_contents = true;
- for (const auto& inline_contents :
- TextOffsetMapping::ForwardRangeOf(position)) {
+ for (auto inline_contents : TextOffsetMapping::ForwardRangeOf(position)) {
const TextOffsetMapping mapping(inline_contents);
const String text = mapping.GetText();
const unsigned offset =
@@ -65,8 +64,7 @@ PositionInFlatTree TextSegments::FindBoundaryBackward(
DCHECK(position.IsNotNull());
PositionInFlatTree last_position = position;
bool is_start_contents = true;
- for (const auto& inline_contents :
- TextOffsetMapping::BackwardRangeOf(position)) {
+ for (auto inline_contents : TextOffsetMapping::BackwardRangeOf(position)) {
const TextOffsetMapping mapping(inline_contents);
const String text = mapping.GetText();
const unsigned offset = is_start_contents
diff --git a/chromium/third_party/blink/renderer/core/editing/text_segments.h b/chromium/third_party/blink/renderer/core/editing/text_segments.h
index 84685c7e1dc..415080b9348 100644
--- a/chromium/third_party/blink/renderer/core/editing/text_segments.h
+++ b/chromium/third_party/blink/renderer/core/editing/text_segments.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_TEXT_SEGMENTS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_TEXT_SEGMENTS_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc
index 39a434a9602..6eaa81304cf 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc
@@ -5,8 +5,10 @@
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/layout/layout_text.h"
namespace blink {
@@ -327,4 +329,52 @@ TEST_P(ParameterizedVisiblePositionTest, SpacesAroundLineBreak) {
}
}
+TEST_P(ParameterizedVisiblePositionTest, TextCombine) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(GetParam());
+ InsertStyleElement(
+ "div {"
+ " font: 100px/110px Ahem;"
+ " writing-mode: vertical-rl;"
+ "}"
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML("<div>a<tcy id=target>01234</tcy>b</div>");
+ const auto& target = *GetElementById("target");
+ const auto& text_a = *To<Text>(target.previousSibling());
+ const auto& text_01234 = *To<Text>(target.firstChild());
+ const auto& text_b = *To<Text>(target.nextSibling());
+
+ EXPECT_EQ(Position(text_a, 0),
+ CreateVisiblePosition(Position(text_a, 0)).DeepEquivalent());
+ EXPECT_EQ(Position(text_a, 1),
+ CreateVisiblePosition(Position(text_a, 1)).DeepEquivalent());
+
+ if (text_01234.GetLayoutObject()->Parent()->IsLayoutNGTextCombine()) {
+ EXPECT_EQ(Position(text_01234, 0),
+ CreateVisiblePosition(Position(text_01234, 0)).DeepEquivalent());
+ } else {
+ EXPECT_EQ(Position(text_a, 1),
+ CreateVisiblePosition(Position(text_01234, 0)).DeepEquivalent());
+ }
+ EXPECT_EQ(Position(text_01234, 1),
+ CreateVisiblePosition(Position(text_01234, 1)).DeepEquivalent());
+ EXPECT_EQ(Position(text_01234, 2),
+ CreateVisiblePosition(Position(text_01234, 2)).DeepEquivalent());
+ EXPECT_EQ(Position(text_01234, 3),
+ CreateVisiblePosition(Position(text_01234, 3)).DeepEquivalent());
+ EXPECT_EQ(Position(text_01234, 4),
+ CreateVisiblePosition(Position(text_01234, 4)).DeepEquivalent());
+ EXPECT_EQ(Position(text_01234, 5),
+ CreateVisiblePosition(Position(text_01234, 5)).DeepEquivalent());
+
+ if (text_01234.GetLayoutObject()->Parent()->IsLayoutNGTextCombine()) {
+ EXPECT_EQ(Position(text_b, 0),
+ CreateVisiblePosition(Position(text_b, 0)).DeepEquivalent());
+ } else {
+ EXPECT_EQ(Position(text_01234, 5),
+ CreateVisiblePosition(Position(text_b, 0)).DeepEquivalent());
+ }
+ EXPECT_EQ(Position(text_b, 1),
+ CreateVisiblePosition(Position(text_b, 1)).DeepEquivalent());
+}
+
} // namespace blink
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 4712a61eb1e..bd4a982e9a2 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -643,6 +644,7 @@ static PositionTemplate<Strategy> MostBackwardCaretPosition(
const bool start_editable = HasEditableStyle(*start_node);
Node* last_node = start_node;
bool boundary_crossed = false;
+ absl::optional<WritingMode> writing_mode;
for (PositionIteratorAlgorithm<Strategy> current_pos = last_visible;
!current_pos.AtStart(); current_pos.Decrement()) {
Node* current_node = current_pos.GetNode();
@@ -681,6 +683,12 @@ static PositionTemplate<Strategy> MostBackwardCaretPosition(
if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*layout_object))
continue;
+ if (!writing_mode.has_value()) {
+ writing_mode.emplace(layout_object->Style()->GetWritingMode());
+ } else if (*writing_mode != layout_object->Style()->GetWritingMode()) {
+ return last_visible.ComputePosition();
+ }
+
if (rule == kCanCrossEditingBoundary && boundary_crossed) {
last_visible = current_pos;
break;
@@ -786,6 +794,7 @@ PositionTemplate<Strategy> MostForwardCaretPosition(
const bool start_editable = HasEditableStyle(*start_node);
Node* last_node = start_node;
bool boundary_crossed = false;
+ absl::optional<WritingMode> writing_mode;
for (PositionIteratorAlgorithm<Strategy> current_pos = last_visible;
!current_pos.AtEnd(); current_pos.Increment()) {
Node* current_node = current_pos.GetNode();
@@ -833,6 +842,12 @@ PositionTemplate<Strategy> MostForwardCaretPosition(
if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*layout_object))
continue;
+ if (!writing_mode.has_value()) {
+ writing_mode.emplace(layout_object->Style()->GetWritingMode());
+ } else if (*writing_mode != layout_object->Style()->GetWritingMode()) {
+ return last_visible.ComputePosition();
+ }
+
if (rule == kCanCrossEditingBoundary && boundary_crossed)
return current_pos.DeprecatedComputePosition();
@@ -1092,6 +1107,13 @@ static VisiblePositionTemplate<Strategy> NextPositionOfAlgorithm(
return next;
}
+VisiblePosition NextPositionOf(const Position& position,
+ EditingBoundaryCrossingRule rule) {
+ DCHECK(position.IsValidFor(*position.GetDocument())) << position;
+ return NextPositionOfAlgorithm<EditingStrategy>(
+ PositionWithAffinityTemplate<EditingStrategy>(position), rule);
+}
+
VisiblePosition NextPositionOf(const VisiblePosition& visible_position,
EditingBoundaryCrossingRule rule) {
DCHECK(visible_position.IsValid()) << visible_position;
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 475f016f641..b276becf62c 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/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -101,6 +101,9 @@ CORE_EXPORT UChar32 CharacterBefore(const VisiblePosition&);
CORE_EXPORT UChar32 CharacterBefore(const VisiblePositionInFlatTree&);
CORE_EXPORT VisiblePosition
+NextPositionOf(const Position&,
+ EditingBoundaryCrossingRule = kCanCrossEditingBoundary);
+CORE_EXPORT VisiblePosition
NextPositionOf(const VisiblePosition&,
EditingBoundaryCrossingRule = kCanCrossEditingBoundary);
CORE_EXPORT VisiblePositionInFlatTree
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_paragraph.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
index 12b72217939..ab0d4fe9938 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
@@ -327,6 +327,11 @@ VisiblePosition EndOfParagraph(
return EndOfParagraphAlgorithm<EditingStrategy>(c, boundary_crossing_rule);
}
+Position EndOfParagraph(const Position& c,
+ EditingBoundaryCrossingRule boundary_crossing_rule) {
+ return EndOfParagraphAlgorithm<EditingStrategy>(c, boundary_crossing_rule);
+}
+
VisiblePositionInFlatTree EndOfParagraph(
const VisiblePositionInFlatTree& c,
EditingBoundaryCrossingRule boundary_crossing_rule) {
@@ -338,22 +343,26 @@ VisiblePositionInFlatTree EndOfParagraph(
// always true
VisiblePosition StartOfNextParagraph(const VisiblePosition& visible_position) {
DCHECK(visible_position.IsValid()) << visible_position;
- VisiblePosition paragraph_end(
- EndOfParagraph(visible_position, kCanSkipOverEditingBoundary));
+ Position paragraph_end(EndOfParagraph(visible_position.DeepEquivalent(),
+ kCanSkipOverEditingBoundary));
// EndOfParagraph preserves the candidate_type, so if we are already at the
// end node we must ensure we get the next position to avoid infinite loops.
- if (paragraph_end.DeepEquivalent() == visible_position.DeepEquivalent()) {
- paragraph_end = VisiblePosition::AfterNode(
- *visible_position.DeepEquivalent().AnchorNode());
+ if (paragraph_end == visible_position.DeepEquivalent()) {
+ paragraph_end =
+ Position::AfterNode(*visible_position.DeepEquivalent().AnchorNode());
}
+ DCHECK(!paragraph_end.IsBeforeAnchor());
+ DCHECK(visible_position.DeepEquivalent() < paragraph_end ||
+ visible_position.DeepEquivalent() == paragraph_end &&
+ paragraph_end.IsAfterAnchor());
VisiblePosition after_paragraph_end(
NextPositionOf(paragraph_end, kCannotCrossEditingBoundary));
// It may happen that an element's next visually equivalent candidate is set
// to such element when creating the VisualPosition. This may cause infinite
// loops when we are iterating over parapgrahs.
- if (after_paragraph_end.DeepEquivalent() == paragraph_end.DeepEquivalent()) {
- after_paragraph_end = VisiblePosition::AfterNode(
- *paragraph_end.DeepEquivalent().AnchorNode());
+ if (after_paragraph_end.DeepEquivalent() == paragraph_end) {
+ after_paragraph_end =
+ VisiblePosition::AfterNode(*paragraph_end.AnchorNode());
}
// The position after the last position in the last cell of a table
// is not the start of the next paragraph.
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 25ec9738ead..fcb366c160e 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
@@ -74,7 +74,6 @@
"click",
"close",
"closing",
- "colorselect",
"complete",
"compositionend",
"compositionstart",
diff --git a/chromium/third_party/blink/renderer/core/events/input_event.cc b/chromium/third_party/blink/renderer/core/events/input_event.cc
index b31ca8cc9dd..8abd93a8995 100644
--- a/chromium/third_party/blink/renderer/core/events/input_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/input_event.cc
@@ -9,7 +9,7 @@
// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
#pragma clang max_tokens_here 1250000
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/dom/range.h"
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 bdb4a6e210d..5fd436f276f 100644
--- a/chromium/third_party/blink/renderer/core/events/message_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/message_event.cc
@@ -29,7 +29,6 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_message_event_init.h"
#include "third_party/blink/renderer/core/event_interface_names.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
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 6148ec96e1c..e4719bf21f3 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
@@ -4,14 +4,15 @@
#include "third_party/blink/renderer/core/events/pointer_event_factory.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_pointer_event_init.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/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/pointer_type_names.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -138,6 +139,26 @@ void UpdateCommonPointerEventInit(const WebPointerEvent& web_pointer_event,
} // namespace
+// static
+const AtomicString& PointerEventFactory::PointerTypeNameForWebPointPointerType(
+ WebPointerProperties::PointerType type) {
+ // TODO(mustaq): Fix when the spec starts supporting hovering erasers.
+ // See spec https://github.com/w3c/pointerevents/issues/134
+ switch (type) {
+ case WebPointerProperties::PointerType::kUnknown:
+ return g_empty_atom;
+ case WebPointerProperties::PointerType::kTouch:
+ return pointer_type_names::kTouch;
+ case WebPointerProperties::PointerType::kPen:
+ return pointer_type_names::kPen;
+ case WebPointerProperties::PointerType::kMouse:
+ return pointer_type_names::kMouse;
+ default:
+ NOTREACHED();
+ return g_empty_atom;
+ }
+}
+
HeapVector<Member<PointerEvent>> PointerEventFactory::CreateEventSequence(
const WebPointerEvent& web_pointer_event,
const PointerEventInit* pointer_event_init,
@@ -196,6 +217,7 @@ HeapVector<Member<PointerEvent>> PointerEventFactory::CreateEventSequence(
return result;
}
+const PointerId PointerEventFactory::kReservedNonPointerId = -1;
const PointerId PointerEventFactory::kInvalidId = 0;
// Mouse id is 1 to behave the same as MS Edge for compatibility reasons.
@@ -618,24 +640,4 @@ PointerId PointerEventFactory::GetPointerEventId(
return kInvalidId;
}
-// static
-const char* PointerEventFactory::PointerTypeNameForWebPointPointerType(
- WebPointerProperties::PointerType type) {
- switch (type) {
- case WebPointerProperties::PointerType::kUnknown:
- return "";
- case WebPointerProperties::PointerType::kTouch:
- return "touch";
- case WebPointerProperties::PointerType::kPen:
- return "pen";
- case WebPointerProperties::PointerType::kMouse:
- return "mouse";
- default:
- // TODO(mustaq): Fix when the spec starts supporting hovering erasers.
- // See spec https://github.com/w3c/pointerevents/issues/134
- NOTREACHED();
- return "";
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event_factory.h b/chromium/third_party/blink/renderer/core/events/pointer_event_factory.h
index e52b13a3177..202ea15fc62 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event_factory.h
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event_factory.h
@@ -27,6 +27,10 @@ class CORE_EXPORT PointerEventFactory {
DISALLOW_NEW();
public:
+ // Returns the pointerType string for the PointerType enum.
+ static const AtomicString& PointerTypeNameForWebPointPointerType(
+ WebPointerProperties::PointerType type);
+
PointerEventFactory();
~PointerEventFactory();
@@ -81,6 +85,7 @@ class CORE_EXPORT PointerEventFactory {
static const PointerId kMouseId;
static const PointerId kInvalidId;
+ static const PointerId kReservedNonPointerId;
// Removes pointer_id from the map.
void RemoveLastPosition(const PointerId pointer_id);
@@ -96,9 +101,6 @@ class CORE_EXPORT PointerEventFactory {
const FloatPoint& position_in_screen,
WebInputEvent::Type event_type);
- static const char* PointerTypeNameForWebPointPointerType(
- WebPointerProperties::PointerType type);
-
private:
// We use int64_t to cover the whole range for PointerId with no
// deleted hash value.
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 5be5f1017e8..fc2825f2597 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
@@ -12,30 +12,10 @@
#include "third_party/blink/public/common/input/web_pointer_properties.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/pointer_type_names.h"
namespace blink {
-namespace {
-
-const char* PointerTypeNameForWebPointPointerType(
- WebPointerProperties::PointerType type) {
- switch (type) {
- case WebPointerProperties::PointerType::kUnknown:
- return "";
- case WebPointerProperties::PointerType::kTouch:
- return "touch";
- case WebPointerProperties::PointerType::kPen:
- case WebPointerProperties::PointerType::kEraser:
- return "pen";
- case WebPointerProperties::PointerType::kMouse:
- return "mouse";
- default:
- NOTREACHED();
- return "";
- }
-}
-}
-
class PointerEventFactoryTest : public testing::Test {
protected:
void SetUp() override;
@@ -79,8 +59,9 @@ class PointerEventFactoryTest : public testing::Test {
EXPECT_EQ(is_primary, pointer_event->isPrimary());
EXPECT_EQ(WebInputEvent::GetStaticTimeStampForTests(),
pointer_event->PlatformTimeStamp());
- const char* expected_pointer_type =
- PointerTypeNameForWebPointPointerType(pointer_type);
+ const String& expected_pointer_type =
+ PointerEventFactory::PointerTypeNameForWebPointPointerType(
+ pointer_type);
EXPECT_EQ(expected_pointer_type, pointer_event->pointerType());
EXPECT_EQ(!!(modifiers & WebInputEvent::kControlKey),
@@ -152,8 +133,9 @@ PointerEvent* PointerEventFactoryTest::CreateAndCheckPointerCancel(
EXPECT_EQ("pointercancel", pointer_event->type());
EXPECT_EQ(unique_id, pointer_event->pointerId());
EXPECT_EQ(is_primary, pointer_event->isPrimary());
- EXPECT_EQ(PointerTypeNameForWebPointPointerType(pointer_type),
- pointer_event->pointerType());
+ EXPECT_EQ(
+ PointerEventFactory::PointerTypeNameForWebPointPointerType(pointer_type),
+ pointer_event->pointerType());
EXPECT_EQ(WebInputEvent::GetStaticTimeStampForTests(),
pointer_event->PlatformTimeStamp());
@@ -637,42 +619,6 @@ TEST_F(PointerEventFactoryTest, PredictedEvents) {
0 /* coalesced_count */, 3 /* predicted_count */);
}
-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::Type::kPointerDown,
- WebPointerProperties::Button::kLeft);
- EXPECT_EQ(event_type_names::kPointerdown, 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::Type::kPointerDown, WebPointerProperties::Button::kRight);
- EXPECT_EQ(event_type_names::kPointermove, second_pointerdown_event->type());
-
- // Send the pointermove event when releasing any other button while the
- // 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::Type::kPointerUp,
- WebPointerProperties::Button::kRight);
- EXPECT_EQ(event_type_names::kPointermove, 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::Type::kPointerUp, WebPointerProperties::Button::kLeft);
- EXPECT_EQ(event_type_names::kPointerup, last_pointerup_event->type());
-}
-
TEST_F(PointerEventFactoryTest, MousePointerKeyStates) {
WebInputEvent::Modifiers modifiers = static_cast<WebInputEvent::Modifiers>(
WebInputEvent::kControlKey | WebInputEvent::kMetaKey);
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_type_names.json5 b/chromium/third_party/blink/renderer/core/events/pointer_type_names.json5
new file mode 100644
index 00000000000..48251ead7c9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/events/pointer_type_names.json5
@@ -0,0 +1,13 @@
+{
+ metadata: {
+ namespace: "pointer_type_names",
+ export: "CORE_EXPORT",
+ },
+
+ data: [
+ "mouse",
+ "pen",
+ "touch",
+ ],
+}
+
diff --git a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.idl b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.idl
index 3f53e019b34..594fbe98015 100644
--- a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.idl
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/domenic/unhandled-rejections-browser-spec
+// https://html.spec.whatwg.org/C/#promiserejectionevent
[
Exposed=(Window,Worker)
diff --git a/chromium/third_party/blink/renderer/core/events/promise_rejection_event_init.idl b/chromium/third_party/blink/renderer/core/events/promise_rejection_event_init.idl
index fc5c110adfa..a410b0be683 100644
--- a/chromium/third_party/blink/renderer/core/events/promise_rejection_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/events/promise_rejection_event_init.idl
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/domenic/unhandled-rejections-browser-spec
+// https://html.spec.whatwg.org/C/#promiserejectioneventinit
dictionary PromiseRejectionEventInit : EventInit {
required Promise<any> promise;
diff --git a/chromium/third_party/blink/renderer/core/events/simulated_event_util.cc b/chromium/third_party/blink/renderer/core/events/simulated_event_util.cc
index 32f26649686..86d9a67f4dc 100644
--- a/chromium/third_party/blink/renderer/core/events/simulated_event_util.cc
+++ b/chromium/third_party/blink/renderer/core/events/simulated_event_util.cc
@@ -26,6 +26,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/layout/map_coordinates_flags.h"
+#include "third_party/blink/renderer/core/pointer_type_names.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -123,9 +124,6 @@ MouseEvent* CreateMouseOrPointerEvent(
// any event attributes not initialized in the |PointerEventInit| below get
// their default values, all of which are appropriate for a simulated
// |PointerEvent|.
- //
- // TODO(mustaq): Set |pointerId| to -1 after we have a spec change to fix the
- // issue https://github.com/w3c/pointerevents/issues/343.
PointerEventInit* initializer = PointerEventInit::Create();
PopulateSimulatedMouseEventInit(event_type, node, underlying_event,
initializer, creation_scope);
@@ -157,8 +155,10 @@ MouseEvent* CreateMouseOrPointerEvent(
if (event_class_type == EventClassType::kPointer) {
if (creation_scope == SimulatedClickCreationScope::kFromAccessibility) {
initializer->setPointerId(PointerEventFactory::kMouseId);
- initializer->setPointerType("mouse");
+ initializer->setPointerType(pointer_type_names::kMouse);
initializer->setIsPrimary(true);
+ } else {
+ initializer->setPointerId(PointerEventFactory::kReservedNonPointerId);
}
created_event = MakeGarbageCollected<PointerEvent>(
event_type, initializer, timestamp, synthetic_type);
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 16d9a69d9cb..2b39d3ecf99 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
@@ -75,34 +75,16 @@ gfx::Vector2dF FrameTranslation(const LocalFrameView* frame_view) {
visual_viewport.Y() + overscroll_offset.Height());
}
-FloatPoint ConvertAbsoluteLocationForLayoutObjectFloat(
- const DoublePoint& location,
- const LayoutObject* layout_object) {
- return layout_object->AbsoluteToLocalFloatPoint(FloatPoint(location));
-}
-
-// FIXME: Change |LocalFrameView| to const FrameView& after RemoteFrames get
-// RemoteFrameViews.
void UpdateWebMouseEventFromCoreMouseEvent(const MouseEvent& event,
- const LocalFrameView* plugin_parent,
const LayoutObject* layout_object,
WebMouseEvent& web_event) {
web_event.SetTimeStamp(event.PlatformTimeStamp());
web_event.SetModifiers(event.GetModifiers());
-
- // TODO(bokan): If plugin_parent == nullptr, pointInRootFrame will really be
- // pointInRootContent.
- // TODO(bokan): This conversion is wrong for RLS. https://crbug.com/781431.
- IntPoint point_in_root_frame(event.AbsoluteLocation().X(),
- event.AbsoluteLocation().Y());
- if (plugin_parent) {
- point_in_root_frame =
- plugin_parent->ConvertToRootFrame(point_in_root_frame);
- }
web_event.SetPositionInScreen(event.screenX(), event.screenY());
- FloatPoint local_point = ConvertAbsoluteLocationForLayoutObjectFloat(
- event.AbsoluteLocation(), layout_object);
- web_event.SetPositionInWidget(local_point.X(), local_point.Y());
+
+ FloatPoint local_point = layout_object->AbsoluteToLocalFloatPoint(
+ FloatPoint(event.AbsoluteLocation()));
+ web_event.SetPositionInWidget(local_point);
}
unsigned ToWebInputEventModifierFrom(WebMouseEvent::Button button) {
@@ -170,8 +152,7 @@ WebPointerEvent TransformWebPointerEvent(LocalFrameView* frame_view,
FrameTranslation(frame_view), event);
}
-WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
- const LayoutObject* layout_object,
+WebMouseEventBuilder::WebMouseEventBuilder(const LayoutObject* layout_object,
const MouseEvent& event) {
// Code below here can be removed once OOPIF ships.
// OOPIF will prevent synthetic events being dispatched into
@@ -194,8 +175,7 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
time_stamp_ = event.PlatformTimeStamp();
modifiers_ = event.GetModifiers();
- UpdateWebMouseEventFromCoreMouseEvent(event, plugin_parent, layout_object,
- *this);
+ UpdateWebMouseEventFromCoreMouseEvent(event, layout_object, *this);
switch (event.button()) {
case int16_t(WebPointerProperties::Button::kLeft):
@@ -244,8 +224,7 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
// Generate a synthetic WebMouseEvent given a TouchEvent (eg. for emulating a
// mouse with touch input for plugins that don't support touch input).
-WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
- const LayoutObject* layout_object,
+WebMouseEventBuilder::WebMouseEventBuilder(const LayoutObject* layout_object,
const TouchEvent& event) {
if (!event.touches())
return;
@@ -278,13 +257,6 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
// The mouse event co-ordinates should be generated from the co-ordinates of
// the touch point.
- // FIXME: if plugin_parent == nullptr, pointInRootFrame will really be
- // pointInAbsolute.
- IntPoint point_in_root_frame = RoundedIntPoint(touch->AbsoluteLocation());
- if (plugin_parent) {
- point_in_root_frame =
- plugin_parent->ConvertToRootFrame(point_in_root_frame);
- }
FloatPoint screen_point = touch->ScreenLocation();
SetPositionInScreen(screen_point.X(), screen_point.Y());
@@ -293,9 +265,9 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
click_count = (type_ == WebInputEvent::Type::kMouseDown ||
type_ == WebInputEvent::Type::kMouseUp);
- FloatPoint local_point = ConvertAbsoluteLocationForLayoutObjectFloat(
- DoublePoint(touch->AbsoluteLocation()), layout_object);
- SetPositionInWidget(local_point.X(), local_point.Y());
+ FloatPoint local_point = layout_object->AbsoluteToLocalFloatPoint(
+ FloatPoint(touch->AbsoluteLocation()));
+ SetPositionInWidget(local_point);
pointer_type = WebPointerProperties::PointerType::kTouch;
}
diff --git a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h
index 4f60e8cf7a2..ca836ab0dac 100644
--- a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h
+++ b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h
@@ -59,12 +59,8 @@ class CORE_EXPORT WebMouseEventBuilder : public WebMouseEvent {
// NOTE: This is only implemented for mousemove, mouseover, mouseout,
// mousedown and mouseup. If the event mapping fails, the event type will
// be set to Undefined.
- WebMouseEventBuilder(const LocalFrameView*,
- const LayoutObject*,
- const MouseEvent&);
- WebMouseEventBuilder(const LocalFrameView*,
- const LayoutObject*,
- const TouchEvent&);
+ WebMouseEventBuilder(const LayoutObject*, const MouseEvent&);
+ WebMouseEventBuilder(const LayoutObject*, const TouchEvent&);
};
// Converts a KeyboardEvent to a corresponding WebKeyboardEvent.
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 5deebbd866f..db5a8bc974f 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
@@ -109,7 +109,7 @@ TEST(WebInputEventConversionTest, WebKeyboardEventBuilder) {
TEST(WebInputEventConversionTest, WebMouseEventBuilder) {
TouchEvent* event = TouchEvent::Create();
- WebMouseEventBuilder mouse(nullptr, nullptr, *event);
+ WebMouseEventBuilder mouse(nullptr, *event);
EXPECT_EQ(WebInputEvent::Type::kUndefined, mouse.GetType());
}
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 e80d0a99d48..cafe51d0503 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
@@ -33,7 +33,9 @@
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/public/mojom/permissions_policy/policy_disposition.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions_policy/policy_value.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/public/web/web_local_frame.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/core/dom/events/event_target.h"
@@ -42,12 +44,16 @@
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/loader/document_loader.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_impl.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/core/workers/worklet_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -119,6 +125,29 @@ ExecutionContext* ExecutionContext::ForRelevantRealm(
return ToExecutionContext(ctx);
}
+// static
+blink::mojom::CodeCacheHost* ExecutionContext::GetCodeCacheHostFromContext(
+ ExecutionContext* execution_context) {
+ DCHECK_NE(execution_context, nullptr);
+ if (execution_context->IsWindow()) {
+ auto* window = To<LocalDOMWindow>(execution_context);
+ if (!window->GetFrame() ||
+ !window->GetFrame()->Loader().GetDocumentLoader()) {
+ return nullptr;
+ }
+ return window->GetFrame()->Loader().GetDocumentLoader()->GetCodeCacheHost();
+ }
+
+ if (execution_context->IsWorkerGlobalScope()) {
+ auto* global_scope =
+ DynamicTo<WorkerOrWorkletGlobalScope>(execution_context);
+ return global_scope->GetCodeCacheHost();
+ }
+
+ DCHECK(execution_context->IsWorkletGlobalScope());
+ return nullptr;
+}
+
void ExecutionContext::SetIsInBackForwardCache(bool value) {
is_in_back_forward_cache_ = value;
}
@@ -152,6 +181,10 @@ void ExecutionContext::NotifyContextDestroyed() {
ContextLifecycleNotifier::NotifyContextDestroyed();
}
+void ExecutionContext::CountDeprecation(WebFeature feature) {
+ Deprecation::CountDeprecation(this, feature);
+}
+
HeapObserverSet<ContextLifecycleObserver>&
ExecutionContext::ContextLifecycleObserverSet() {
return ContextLifecycleNotifier::observers();
@@ -187,6 +220,17 @@ bool ExecutionContext::SharedArrayBufferTransferAllowed() const {
return true;
}
+ // Check if the SharedArrayBuffer is always allowed for this origin. For
+ // worklets use the origin of the main document (consistent with how origin is
+ // verified in origin trials).
+ const SecurityOrigin* origin;
+ if (auto* worklet_scope = DynamicTo<WorkletGlobalScope>(this))
+ origin = worklet_scope->DocumentSecurityOrigin();
+ else
+ origin = GetSecurityOrigin();
+ if (SecurityPolicy::IsSharedArrayBufferAlwaysAllowedForOrigin(origin))
+ return true;
+
#if defined(OS_ANDROID)
return false;
#else
@@ -312,15 +356,15 @@ bool ExecutionContext::IsContextPaused() const {
return lifecycle_state_ == mojom::blink::FrameLifecycleState::kPaused;
}
-WebURLLoader::DeferType ExecutionContext::DeferType() const {
+LoaderFreezeMode ExecutionContext::GetLoaderFreezeMode() const {
if (is_in_back_forward_cache_) {
DCHECK_EQ(lifecycle_state_, mojom::blink::FrameLifecycleState::kFrozen);
- return WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ return LoaderFreezeMode::kBufferIncoming;
} else if (lifecycle_state_ == mojom::blink::FrameLifecycleState::kFrozen ||
lifecycle_state_ == mojom::blink::FrameLifecycleState::kPaused) {
- return WebURLLoader::DeferType::kDeferred;
+ return LoaderFreezeMode::kStrict;
}
- return WebURLLoader::DeferType::kNotDeferred;
+ return LoaderFreezeMode::kNone;
}
bool ExecutionContext::IsLoadDeferred() const {
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 73e17bfac0b..3f7ffa2e54c 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
@@ -30,7 +30,6 @@
#include <memory>
-#include "base/macros.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
@@ -39,19 +38,21 @@
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-forward.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions_policy/policy_disposition.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
-#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/frame/dom_timer_coordinator.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/platform/heap_observer_set.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
#include "third_party/blink/renderer/platform/loader/fetch/https_state.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -141,6 +142,12 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
static ExecutionContext* ForRelevantRealm(
const v8::PropertyCallbackInfo<v8::Value>&);
+ // Returns the CodeCacheHost interface associated with the execution
+ // context. This could return nullptr if there is no CodeCacheHost associated
+ // with the current execution context.
+ static blink::mojom::CodeCacheHost* GetCodeCacheHostFromContext(
+ ExecutionContext*);
+
virtual bool IsWindow() const { return false; }
virtual bool IsWorkerOrWorkletGlobalScope() const { return false; }
virtual bool IsWorkerGlobalScope() const { return false; }
@@ -160,6 +167,9 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
virtual bool ShouldInstallV8Extensions() const { return false; }
+ virtual void CountUseOnlyInCrossSiteIframe(mojom::blink::WebFeature feature) {
+ }
+
const SecurityOrigin* GetSecurityOrigin() const;
SecurityOrigin* GetMutableSecurityOrigin();
@@ -203,7 +213,7 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
return &timers_;
}
- virtual ResourceFetcher* Fetcher() const = 0;
+ virtual ResourceFetcher* Fetcher() = 0;
SecurityContext& GetSecurityContext() { return security_context_; }
const SecurityContext& GetSecurityContext() const {
@@ -245,8 +255,10 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
virtual void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) = 0;
virtual void AddInspectorIssue(AuditsIssue) = 0;
+ void CountDeprecation(WebFeature feature) override;
+
bool IsContextPaused() const;
- WebURLLoader::DeferType DeferType() const;
+ LoaderFreezeMode GetLoaderFreezeMode() const;
bool IsContextDestroyed() const { return is_context_destroyed_; }
mojom::FrameLifecycleState ContextPauseState() const {
return lifecycle_state_;
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 a33d82a16fa..a8a01e13f9f 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,7 +29,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions_policy/document_policy_feature.mojom-blink-forward.h"
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc
index 5672460b941..7342a674af2 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc
@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/core/permissions_policy/document_policy_parser.h"
#include "third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
namespace {
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h
index b137fe98091..5c45de8c6f7 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_SECURITY_CONTEXT_INIT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_SECURITY_CONTEXT_INIT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/common/permissions_policy/document_policy.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
diff --git a/chromium/third_party/blink/renderer/core/execution_context/window_agent_factory.cc b/chromium/third_party/blink/renderer/core/execution_context/window_agent_factory.cc
index 16a8476d3be..3438cdd3c53 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/window_agent_factory.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/window_agent_factory.cc
@@ -3,8 +3,10 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/execution_context/window_agent_factory.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/renderer/core/execution_context/window_agent.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin_hash.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
@@ -71,7 +73,7 @@ WindowAgent* WindowAgentFactory::GetAgentForOrigin(
// All chrome extensions need to share the same agent because they can
// access each other's windows directly.
- if (origin->Protocol() == "chrome-extension") {
+ if (CommonSchemeRegistry::IsExtensionScheme(origin->Protocol().Ascii())) {
DEFINE_STATIC_LOCAL(Persistent<TupleOriginAgents>, static_origin_agents,
(MakeGarbageCollected<TupleOriginAgents>()));
tuple_origin_agents = static_origin_agents;
diff --git a/chromium/third_party/blink/renderer/core/exported/BUILD.gn b/chromium/third_party/blink/renderer/core/exported/BUILD.gn
index a5be18f271d..b8bca807733 100644
--- a/chromium/third_party/blink/renderer/core/exported/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/exported/BUILD.gn
@@ -101,7 +101,6 @@ blink_core_sources("exported") {
"//build:chromeos_buildflags",
"//third_party/blink/renderer/core:core_generated",
"//third_party/blink/renderer/core/probe",
- "//third_party/blink/renderer/core/typed_arrays:typed_arrays",
"//ui/base/cursor:cursor_base",
"//ui/base/cursor/mojom:cursor_type_blink",
]
diff --git a/chromium/third_party/blink/renderer/core/exported/DEPS b/chromium/third_party/blink/renderer/core/exported/DEPS
index 71b99d72431..0469eabfc17 100644
--- a/chromium/third_party/blink/renderer/core/exported/DEPS
+++ b/chromium/third_party/blink/renderer/core/exported/DEPS
@@ -14,4 +14,25 @@ specific_include_rules = {
"+third_party/icu/source/common/unicode/uscript.h",
"+ui/gfx/font_render_params.h",
],
+ "web_media_player_impl_unittest.cc": [
+ "+base/command_line.h",
+ "+base/memory/ref_counted.h",
+ "+base/run_loop.h",
+ "+base/strings/string_number_conversions.h",
+ "+base/strings/string_split.h",
+ "+base/strings/utf_string_conversions.h",
+ "+base/task/current_thread.h",
+ "+base/task_runner_util.h",
+ "+base/threading/thread.h",
+ "+components/viz/test",
+ "+media/base",
+ "+media/filters",
+ "+media/mojo/services",
+ "+media/renderers",
+ "+gin/v8_initializer.h",
+ "+mojo/core/embedder/embedder.h",
+
+ # Allow test support dependencies.
+ "+third_party/blink/renderer/platform/media/testing",
+ ],
}
diff --git a/chromium/third_party/blink/renderer/core/exported/OWNERS b/chromium/third_party/blink/renderer/core/exported/OWNERS
index f02458f2ba3..8cd9cfd2e3a 100644
--- a/chromium/third_party/blink/renderer/core/exported/OWNERS
+++ b/chromium/third_party/blink/renderer/core/exported/OWNERS
@@ -1,2 +1,3 @@
per-file web_shared_worker_impl.h=file://third_party/blink/renderer/core/workers/OWNERS
per-file web_shared_worker_impl.cc=file://third_party/blink/renderer/core/workers/OWNERS
+per-file web_media_player_impl_unittest.cc=file://media/OWNERS
diff --git a/chromium/third_party/blink/renderer/core/exported/test_web_frame_content_dumper.cc b/chromium/third_party/blink/renderer/core/exported/test_web_frame_content_dumper.cc
index 2a4e363dd3e..2f877a06fae 100644
--- a/chromium/third_party/blink/renderer/core/exported/test_web_frame_content_dumper.cc
+++ b/chromium/third_party/blink/renderer/core/exported/test_web_frame_content_dumper.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html_element_type_helpers.h"
#include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -26,7 +27,7 @@ WebString TestWebFrameContentDumper::DumpWebViewAsText(WebView* web_view,
DCHECK(web_view);
WebLocalFrame* frame = web_view->MainFrame()->ToWebLocalFrame();
- WebViewImpl* web_view_impl = static_cast<WebViewImpl*>(web_view);
+ WebViewImpl* web_view_impl = To<WebViewImpl>(web_view);
DCHECK(web_view_impl->MainFrameViewWidget());
// Updating the document lifecycle isn't enough, the BeginFrame() step
// should come first which runs events such as notifying of media query
@@ -36,7 +37,8 @@ WebString TestWebFrameContentDumper::DumpWebViewAsText(WebView* web_view,
DocumentUpdateReason::kTest);
StringBuilder text;
- FrameContentAsText(max_chars, To<WebLocalFrameImpl>(frame)->GetFrame(), text);
+ FrameContentAsText(static_cast<wtf_size_t>(max_chars),
+ To<WebLocalFrameImpl>(frame)->GetFrame(), text);
return text.ToString();
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc b/chromium/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc
index b3da4e68418..0008abc4903 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc
@@ -30,7 +30,9 @@
#include "third_party/blink/public/web/web_array_buffer_converter.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -48,10 +50,12 @@ v8::Local<v8::Value> WebArrayBufferConverter::ToV8Value(
WebArrayBuffer* WebArrayBufferConverter::CreateFromV8Value(
v8::Local<v8::Value> value,
- v8::Isolate*) {
+ v8::Isolate* isolate) {
if (!value->IsArrayBuffer())
return nullptr;
- return new WebArrayBuffer(V8ArrayBuffer::ToImpl(value.As<v8::Object>()));
+ NonThrowableExceptionState exception_state;
+ return new WebArrayBuffer(NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ isolate, value, exception_state));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_content_holder.cc b/chromium/third_party/blink/renderer/core/exported/web_content_holder.cc
index be38d01092e..8b725c1fa9d 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_content_holder.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_content_holder.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/renderer/core/content_capture/content_holder.h"
#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
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 ce027d46fb0..f44404ad3d0 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
@@ -281,7 +281,8 @@ void WebDevToolsAgentImpl::AttachSession(DevToolsSession* session,
&inspected_frames->Root()->GetPage()->GetInspectorIssueStorage(),
inspected_frames));
- session->Append(MakeGarbageCollected<InspectorMediaAgent>(inspected_frames));
+ session->Append(MakeGarbageCollected<InspectorMediaAgent>(
+ inspected_frames, /*worker_global_scope=*/nullptr));
// TODO(dgozman): we should actually pass the view instead of frame, but
// during remote->local transition we cannot access mainFrameImpl() yet, so
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 e22dfa014f6..2194e0a49e9 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_document.cc
@@ -59,9 +59,6 @@
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/plugin_document.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/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -110,8 +107,8 @@ WebString WebDocument::GetReferrer() const {
return ConstUnwrap<Document>()->referrer();
}
-absl::optional<SkColor> WebDocument::ThemeColor() const {
- absl::optional<Color> color = ConstUnwrap<Document>()->ThemeColor();
+absl::optional<SkColor> WebDocument::ThemeColor() {
+ absl::optional<Color> color = Unwrap<Document>()->ThemeColor();
if (color)
return color->Rgb();
return absl::nullopt;
@@ -177,8 +174,9 @@ WebString WebDocument::ContentAsTextForTesting() const {
return document_element->innerText();
}
-WebElementCollection WebDocument::All() {
- return WebElementCollection(Unwrap<Document>()->all());
+WebElementCollection WebDocument::All() const {
+ return WebElementCollection(
+ const_cast<Document*>(ConstUnwrap<Document>())->all());
}
WebVector<WebFormElement> WebDocument::Forms() const {
@@ -240,7 +238,8 @@ void WebDocument::WatchCSSSelectors(const WebVector<WebString>& web_selectors) {
if (!watch && web_selectors.empty())
return;
Vector<String> selectors;
- selectors.Append(web_selectors.Data(), web_selectors.size());
+ selectors.Append(web_selectors.Data(),
+ base::checked_cast<wtf_size_t>(web_selectors.size()));
CSSSelectorWatch::From(*document).WatchCSSSelectors(selectors);
}
@@ -250,7 +249,7 @@ WebVector<WebDraggableRegion> WebDocument::DraggableRegions() const {
if (document->HasAnnotatedRegions()) {
const Vector<AnnotatedRegionValue>& regions = document->AnnotatedRegions();
draggable_regions = WebVector<WebDraggableRegion>(regions.size());
- for (size_t i = 0; i < regions.size(); i++) {
+ for (wtf_size_t i = 0; i < regions.size(); i++) {
const AnnotatedRegionValue& value = regions[i];
draggable_regions[i].draggable = value.draggable;
draggable_regions[i].bounds = PixelSnappedIntRect(value.bounds);
@@ -291,6 +290,26 @@ bool WebDocument::IsLoaded() {
return !ConstUnwrap<Document>()->Parser();
}
+bool WebDocument::IsPrerendering() {
+ return ConstUnwrap<Document>()->IsPrerendering();
+}
+
+bool WebDocument::IsAccessibilityEnabled() {
+ return ConstUnwrap<Document>()->IsAccessibilityEnabled();
+}
+
+void WebDocument::AddPostPrerenderingActivationStep(
+ base::OnceClosure callback) {
+ return Unwrap<Document>()->AddPostPrerenderingActivationStep(
+ std::move(callback));
+}
+
+void WebDocument::SetCookieManager(
+ CrossVariantMojoRemote<network::mojom::RestrictedCookieManagerInterfaceBase>
+ cookie_manager) {
+ Unwrap<Document>()->SetCookieManager(std::move(cookie_manager));
+}
+
WebDocument::WebDocument(Document* elem) : WebNode(elem) {}
DEFINE_WEB_NODE_TYPE_CASTS(WebDocument, ConstUnwrap<Node>()->IsDocumentNode())
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 ce32db0a125..0c4f6284fa1 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
@@ -93,10 +93,6 @@ WebURL WebDocumentLoaderImpl::UnreachableURL() const {
return DocumentLoader::UnreachableURL();
}
-void WebDocumentLoaderImpl::RedirectChain(WebVector<WebURL>& result) const {
- result.Assign(redirect_chain_);
-}
-
bool WebDocumentLoaderImpl::IsClientRedirect() const {
return DocumentLoader::IsClientRedirect();
}
@@ -205,6 +201,11 @@ bool WebDocumentLoaderImpl::IsListingFtpDirectory() const {
return DocumentLoader::IsListingFtpDirectory();
}
+void WebDocumentLoaderImpl::SetCodeCacheHost(
+ mojo::PendingRemote<mojom::CodeCacheHost> code_cache_host) {
+ DocumentLoader::SetCodeCacheHost(std::move(code_cache_host));
+}
+
void WebDocumentLoaderImpl::Trace(Visitor* visitor) const {
DocumentLoader::Trace(visitor);
}
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 dd2d0ddbf19..1aa3027890e 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
@@ -71,7 +71,6 @@ class CORE_EXPORT WebDocumentLoaderImpl final : public DocumentLoader,
const WebURLResponse& GetResponse() const override;
bool HasUnreachableURL() const override;
WebURL UnreachableURL() const override;
- void RedirectChain(WebVector<WebURL>&) const override;
bool IsClientRedirect() const override;
bool ReplacesCurrentHistoryItem() const override;
WebNavigationType GetNavigationType() const override;
@@ -89,6 +88,8 @@ class CORE_EXPORT WebDocumentLoaderImpl final : public DocumentLoader,
WebArchiveInfo GetArchiveInfo() const override;
bool LastNavigationHadTransientUserActivation() const override;
bool IsListingFtpDirectory() const override;
+ void SetCodeCacheHost(
+ mojo::PendingRemote<mojom::CodeCacheHost> code_cache_host) override;
void Trace(Visitor*) const override;
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 9e4267a4391..8285025842d 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,10 +6,9 @@
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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/common/origin_trials/scoped_test_origin_trial_policy.h"
#include "third_party/blink/public/web/web_origin_trials.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
@@ -128,73 +127,23 @@ TEST_F(WebDocumentTest, InsertAndRemoveStyleSheet) {
style_after_removing.VisitedDependentColor(GetCSSPropertyColor()));
}
-namespace {
-
-// 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,
-};
-
-} // anonymous namespace
-
-// Origin Trial Policy which vends the test public key so that the token
-// can be validated.
-class TestOriginTrialPolicy : public blink::OriginTrialPolicy {
- public:
- TestOriginTrialPolicy() {
- public_keys_.push_back(base::StringPiece(
- reinterpret_cast<const char*>(kOriginTrialPublicKey),
- base::size(kOriginTrialPublicKey)));
- }
- bool IsOriginTrialsSupported() const override { return true; }
- std::vector<base::StringPiece> GetPublicKeys() const override {
- return public_keys_;
- }
- bool IsOriginSecure(const GURL& url) const override { return true; }
-
- private:
- std::vector<base::StringPiece> public_keys_;
-};
-
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)));
+ blink::ScopedTestOriginTrialPolicy 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)));
-
+ blink::ScopedTestOriginTrialPolicy 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 {
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 1829c4f850c..b1d1c8bb418 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_element.cc
@@ -148,6 +148,13 @@ WebNode WebElement::ShadowRoot() const {
return WebNode(root);
}
+WebElement WebElement::OwnerShadowHost() const {
+ if (auto* host = ConstUnwrap<Element>()->OwnerShadowHost()) {
+ return WebElement(host);
+ }
+ return WebElement();
+}
+
WebNode WebElement::OpenOrClosedShadowRoot() {
if (IsNull())
return WebNode();
@@ -169,7 +176,7 @@ SkBitmap WebElement::ImageContents() {
std::vector<uint8_t> WebElement::CopyOfImageData() {
Image* image = GetImage();
- if (!image || !image->Data())
+ if (!image || !image->HasData())
return std::vector<uint8_t>();
return image->Data()->CopyAs<std::vector<uint8_t>>();
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_form_element.cc b/chromium/third_party/blink/renderer/core/exported/web_form_element.cc
index 39408830520..a0bd1676582 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_form_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_form_element.cc
@@ -66,7 +66,8 @@ WebVector<WebFormControlElement> WebFormElement::GetFormControlElements()
const {
const HTMLFormElement* form = ConstUnwrap<HTMLFormElement>();
Vector<WebFormControlElement> form_control_elements;
- for (const auto& element : form->ListedElements()) {
+ for (const auto& element :
+ form->ListedElements(/*include_shadow_trees=*/true)) {
if (auto* form_control =
blink::DynamicTo<HTMLFormControlElement>(element.Get())) {
form_control_elements.push_back(form_control);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.h b/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.h
index 814d48511a0..3ac51d2dd42 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_FORM_ELEMENT_OBSERVER_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_FORM_ELEMENT_OBSERVER_IMPL_H_
-#include "base/macros.h"
#include "base/types/pass_key.h"
#include "third_party/blink/public/web/modules/autofill/web_form_element_observer.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -24,6 +23,9 @@ class CORE_EXPORT WebFormElementObserverImpl final
WebFormElementObserverImpl(base::PassKey<WebFormElementObserver>,
HTMLElement&,
base::OnceClosure);
+ WebFormElementObserverImpl(const WebFormElementObserverImpl&) = delete;
+ WebFormElementObserverImpl& operator=(const WebFormElementObserverImpl&) =
+ delete;
~WebFormElementObserverImpl() override;
// WebFormElementObserver implementation.
@@ -38,8 +40,6 @@ class CORE_EXPORT WebFormElementObserverImpl final
// WebFormElementObserverImpl must remain alive until Disconnect() is called.
SelfKeepAlive<WebFormElementObserverImpl> self_keep_alive_;
-
- DISALLOW_COPY_AND_ASSIGN(WebFormElementObserverImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
index c756d0ad26e..47fcf33d8ab 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
@@ -16,7 +16,8 @@ namespace blink {
WebString WebFrameContentDumper::DumpFrameTreeAsText(WebLocalFrame* frame,
size_t max_chars) {
StringBuilder text;
- FrameContentAsText(max_chars, To<WebLocalFrameImpl>(frame)->GetFrame(), text);
+ FrameContentAsText(base::checked_cast<wtf_size_t>(max_chars),
+ To<WebLocalFrameImpl>(frame)->GetFrame(), text);
return text.ToString();
}
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 ab6da00d68f..e6646c3ff33 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
@@ -30,7 +30,6 @@
#include "third_party/blink/public/web/web_frame_serializer.h"
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_response.h"
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 66af4db1076..0f0f8c1cd9d 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
@@ -48,11 +48,11 @@ namespace blink {
namespace {
// Returns the count of match for substring |pattern| in string |str|.
-int MatchSubstring(const String& str, const char* pattern, size_t size) {
+int MatchSubstring(const String& str, const char* pattern, wtf_size_t size) {
int matches = 0;
- size_t start = 0;
+ wtf_size_t start = 0;
while (true) {
- size_t pos = str.Find(pattern, start);
+ wtf_size_t pos = str.Find(pattern, start);
if (pos == WTF::kNotFound)
break;
matches++;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc
index 1eb449d191f..9fb1261b53e 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc
@@ -55,7 +55,7 @@ class SimpleWebFrameSerializerClient final : public WebFrameSerializerClient {
private:
void DidSerializeDataForFrame(const WebVector<char>& data,
FrameSerializationStatus) final {
- builder_.Append(data.Data(), data.size());
+ builder_.Append(data.Data(), static_cast<unsigned>(data.size()));
}
StringBuilder builder_;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test_helper.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test_helper.cc
index b21916744df..cd10dd166b8 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test_helper.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_test_helper.cc
@@ -52,18 +52,20 @@ String GenerateMHTMLHelper(WebLocalFrameImpl* frame,
if (!only_body_parts) {
WebThreadSafeData header_result = WebFrameSerializer::GenerateMHTMLHeader(
boundary, frame, &mhtml_delegate);
- mhtml.Append(header_result.Data(), header_result.size());
+ mhtml.Append(header_result.Data(),
+ static_cast<unsigned>(header_result.size()));
}
WebThreadSafeData body_result =
WebFrameSerializer::GenerateMHTMLParts(boundary, frame, &mhtml_delegate);
- mhtml.Append(body_result.Data(), body_result.size());
+ mhtml.Append(body_result.Data(), static_cast<unsigned>(body_result.size()));
if (!only_body_parts) {
scoped_refptr<RawData> footer_data = RawData::Create();
MHTMLArchive::GenerateMHTMLFooterForTesting(boundary,
*footer_data->MutableData());
- mhtml.Append(footer_data->data(), footer_data->length());
+ mhtml.Append(footer_data->data(),
+ static_cast<unsigned>(footer_data->length()));
}
String mhtml_string = mhtml.ToString();
diff --git a/chromium/third_party/blink/renderer/core/exported/web_history_item.cc b/chromium/third_party/blink/renderer/core/exported/web_history_item.cc
index 7579bbdf8b7..6bc5190d360 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_history_item.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_history_item.cc
@@ -189,7 +189,7 @@ WebVector<WebString> WebHistoryItem::GetReferencedFilePaths() const {
HashSet<String> file_paths;
const EncodedFormData* form_data = private_->FormData();
if (form_data) {
- for (size_t i = 0; i < form_data->Elements().size(); ++i) {
+ for (wtf_size_t i = 0; i < form_data->Elements().size(); ++i) {
const FormDataElement& element = form_data->Elements()[i];
if (element.type_ == FormDataElement::kEncodedFile)
file_paths.insert(element.filename_);
@@ -198,7 +198,7 @@ WebVector<WebString> WebHistoryItem::GetReferencedFilePaths() const {
const Vector<String>& referenced_file_paths =
private_->GetReferencedFilePaths();
- for (size_t i = 0; i < referenced_file_paths.size(); ++i)
+ for (wtf_size_t i = 0; i < referenced_file_paths.size(); ++i)
file_paths.insert(referenced_file_paths[i]);
Vector<String> results;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_image.cc b/chromium/third_party/blink/renderer/core/exported/web_image.cc
index bb0e68019bd..99d36936754 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_image.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_image.cc
@@ -56,10 +56,10 @@ SkBitmap WebImage::FromData(const WebData& data,
// Frames are arranged by decreasing size, then decreasing bit depth.
// Pick the frame closest to |desiredSize|'s area without being smaller,
// which has the highest bit depth.
- const size_t frame_count = decoder->FrameCount();
- size_t index = 0; // Default to first frame if none are large enough.
+ const wtf_size_t frame_count = decoder->FrameCount();
+ wtf_size_t index = 0; // Default to first frame if none are large enough.
int frame_area_at_index = 0;
- for (size_t i = 0; i < frame_count; ++i) {
+ for (wtf_size_t i = 0; i < frame_count; ++i) {
const IntSize frame_size = decoder->FrameSizeAtIndex(i);
if (gfx::Size(frame_size) == desired_size) {
index = i;
@@ -79,7 +79,17 @@ SkBitmap WebImage::FromData(const WebData& data,
ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(index);
if (!frame || decoder->Failed())
return {};
- return frame->Bitmap();
+
+ if (decoder->Orientation().Orientation() == ImageOrientationEnum::kDefault)
+ return frame->Bitmap();
+
+ cc::PaintImage paint_image(Image::ResizeAndOrientImage(
+ cc::PaintImage::CreateFromBitmap(frame->Bitmap()),
+ decoder->Orientation()));
+
+ SkBitmap bitmap;
+ paint_image.GetSwSkImage()->asLegacyBitmap(&bitmap);
+ return bitmap;
}
SkBitmap WebImage::DecodeSVG(const WebData& data,
@@ -112,7 +122,7 @@ SkBitmap WebImage::DecodeSVG(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 wtf_size_t kMaxFrameCount = 8;
const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
@@ -123,11 +133,11 @@ WebVector<SkBitmap> WebImage::FramesFromData(const WebData& data) {
// 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();
+ const wtf_size_t frame_count = decoder->FrameCount();
IntSize last_size;
WebVector<SkBitmap> frames;
- for (size_t i = 0; i < std::min(frame_count, kMaxFrameCount); ++i) {
+ for (wtf_size_t i = 0; i < std::min(frame_count, kMaxFrameCount); ++i) {
const IntSize frame_size = decoder->FrameSizeAtIndex(i);
if (frame_size == last_size)
continue;
@@ -154,12 +164,12 @@ WebVector<WebImage::AnimationFrame> WebImage::AnimationFromData(
if (!decoder || !decoder->IsSizeAvailable() || decoder->FrameCount() == 0)
return {};
- const size_t frame_count = decoder->FrameCount();
+ const wtf_size_t frame_count = decoder->FrameCount();
IntSize last_size = decoder->FrameSizeAtIndex(0);
WebVector<WebImage::AnimationFrame> frames;
frames.reserve(frame_count);
- for (size_t i = 0; i < frame_count; ++i) {
+ for (wtf_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
diff --git a/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
index 02740e2d77a..86b058013a1 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
@@ -231,11 +231,11 @@ bool WebInputMethodControllerImpl::GetCompositionCharacterBounds(
if (range.IsEmpty())
return false;
- size_t character_count = range.length();
- size_t offset = range.StartOffset();
- WebVector<gfx::Rect> result(character_count);
+ int character_count = range.length();
+ int offset = range.StartOffset();
+ WebVector<gfx::Rect> result(static_cast<size_t>(character_count));
gfx::Rect rect;
- for (size_t i = 0; i < character_count; ++i) {
+ for (int i = 0; i < character_count; ++i) {
if (!web_frame_->FirstRectForCharacterRange(offset + i, 1, rect)) {
DLOG(ERROR) << "Could not retrieve character rectangle at " << i;
return false;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.h b/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.h
index 4e9e85dad83..5fe93a24bc8 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_input_method_controller_impl.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_INPUT_METHOD_CONTROLLER_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_INPUT_METHOD_CONTROLLER_IMPL_H_
-#include "base/macros.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -30,6 +29,9 @@ class CORE_EXPORT WebInputMethodControllerImpl
public:
explicit WebInputMethodControllerImpl(WebLocalFrameImpl& web_frame);
+ WebInputMethodControllerImpl(const WebInputMethodControllerImpl&) = delete;
+ WebInputMethodControllerImpl& operator=(const WebInputMethodControllerImpl&) =
+ delete;
~WebInputMethodControllerImpl() override;
// WebInputMethodController overrides.
@@ -70,8 +72,6 @@ class CORE_EXPORT WebInputMethodControllerImpl
WebPlugin* FocusedPluginIfInputMethodSupported() const;
const Member<WebLocalFrameImpl> web_frame_;
-
- DISALLOW_COPY_AND_ASSIGN(WebInputMethodControllerImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc b/chromium/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
new file mode 100644
index 00000000000..398f95ce890
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
@@ -0,0 +1,2439 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/web_media_player_impl.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
+#include "base/test/bind.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/threading/thread.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "build/build_config.h"
+#include "cc/layers/layer.h"
+#include "components/viz/test/test_context_provider.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/media_content_type.h"
+#include "media/base/media_log.h"
+#include "media/base/media_switches.h"
+#include "media/base/memory_dump_provider_proxy.h"
+#include "media/base/mock_audio_renderer_sink.h"
+#include "media/base/mock_filters.h"
+#include "media/base/mock_media_log.h"
+#include "media/base/test_data_util.h"
+#include "media/base/test_helpers.h"
+#include "media/filters/pipeline_controller.h"
+#include "media/mojo/services/media_metrics_provider.h"
+#include "media/mojo/services/video_decode_stats_recorder.h"
+#include "media/mojo/services/watch_time_recorder.h"
+#include "media/renderers/default_decoder_factory.h"
+#include "media/renderers/default_renderer_factory.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/public/platform/media/web_media_player_params.h"
+#include "third_party/blink/public/platform/media/webmediaplayer_delegate.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
+#include "third_party/blink/public/platform/web_media_player.h"
+#include "third_party/blink/public/platform/web_media_player_client.h"
+#include "third_party/blink/public/platform/web_media_player_encrypted_media_client.h"
+#include "third_party/blink/public/platform/web_media_player_source.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
+#include "third_party/blink/public/platform/web_url_response.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_testing_support.h"
+#include "third_party/blink/public/web/web_view.h"
+#include "third_party/blink/public/web/web_widget.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h"
+#include "third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h"
+#include "third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h"
+#include "third_party/blink/renderer/platform/media/video_decode_stats_reporter.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace blink {
+namespace {
+
+using ::base::test::RunClosure;
+using ::base::test::RunOnceCallback;
+using ::media::TestAudioConfig;
+using ::media::TestVideoConfig;
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::Eq;
+using ::testing::Gt;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::NiceMock;
+using ::testing::NotNull;
+using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::StrictMock;
+using ::testing::WithArg;
+using ::testing::WithoutArgs;
+
+constexpr char kAudioOnlyTestFile[] = "sfx-opus-441.webm";
+constexpr char kVideoOnlyTestFile[] = "bear-320x240-video-only.webm";
+constexpr char kVideoAudioTestFile[] = "bear-320x240-16x9-aspect.webm";
+constexpr char kEncryptedVideoOnlyTestFile[] = "bear-320x240-av_enc-v.webm";
+
+constexpr base::TimeDelta kAudioOnlyTestFileDuration =
+ base::TimeDelta::FromMilliseconds(296);
+
+MATCHER(WmpiDestroyed, "") {
+ return CONTAINS_STRING(arg, "{\"event\":\"kWebMediaPlayerDestroyed\"}");
+}
+
+MATCHER_P2(PlaybackRateChanged, old_rate_string, new_rate_string, "") {
+ return CONTAINS_STRING(arg, "Effective playback rate changed from " +
+ std::string(old_rate_string) + " to " +
+ std::string(new_rate_string));
+}
+
+class MockWebMediaPlayerClient : public WebMediaPlayerClient {
+ public:
+ MockWebMediaPlayerClient() = default;
+
+ MOCK_METHOD0(NetworkStateChanged, void());
+ MOCK_METHOD0(ReadyStateChanged, void());
+ MOCK_METHOD0(TimeChanged, void());
+ MOCK_METHOD0(Repaint, void());
+ MOCK_METHOD0(DurationChanged, void());
+ MOCK_METHOD0(SizeChanged, void());
+ MOCK_METHOD1(SetCcLayer, void(cc::Layer*));
+ MOCK_METHOD5(AddAudioTrack,
+ WebMediaPlayer::TrackId(const WebString&,
+ WebMediaPlayerClient::AudioTrackKind,
+ const WebString&,
+ const WebString&,
+ bool));
+ MOCK_METHOD1(RemoveAudioTrack, void(WebMediaPlayer::TrackId));
+ MOCK_METHOD5(AddVideoTrack,
+ WebMediaPlayer::TrackId(const WebString&,
+ WebMediaPlayerClient::VideoTrackKind,
+ const WebString&,
+ const WebString&,
+ bool));
+ MOCK_METHOD1(RemoveVideoTrack, void(WebMediaPlayer::TrackId));
+ MOCK_METHOD1(AddTextTrack, void(WebInbandTextTrack*));
+ MOCK_METHOD1(RemoveTextTrack, void(WebInbandTextTrack*));
+ MOCK_METHOD1(MediaSourceOpened, void(WebMediaSource*));
+ MOCK_METHOD2(RemotePlaybackCompatibilityChanged, void(const WebURL&, bool));
+ MOCK_METHOD0(WasAlwaysMuted, bool());
+ MOCK_METHOD0(HasSelectedVideoTrack, bool());
+ MOCK_METHOD0(GetSelectedVideoTrackId, WebMediaPlayer::TrackId());
+ MOCK_METHOD0(HasNativeControls, bool());
+ MOCK_METHOD0(IsAudioElement, bool());
+ MOCK_CONST_METHOD0(GetDisplayType, DisplayType());
+ MOCK_CONST_METHOD0(IsInAutoPIP, bool());
+ MOCK_METHOD1(MediaRemotingStarted, void(const WebString&));
+ MOCK_METHOD1(MediaRemotingStopped, void(int));
+ MOCK_METHOD0(PictureInPictureStopped, void());
+ MOCK_METHOD0(OnPictureInPictureStateChange, void());
+ MOCK_CONST_METHOD0(CouldPlayIfEnoughData, bool());
+ MOCK_METHOD0(ResumePlayback, void());
+ MOCK_METHOD0(PausePlayback, void());
+ MOCK_METHOD0(DidPlayerStartPlaying, void());
+ MOCK_METHOD1(DidPlayerPaused, void(bool));
+ MOCK_METHOD1(DidPlayerMutedStatusChange, void(bool));
+ MOCK_METHOD3(DidMediaMetadataChange,
+ void(bool, bool, media::MediaContentType));
+ MOCK_METHOD4(DidPlayerMediaPositionStateChange,
+ void(double,
+ base::TimeDelta,
+ base::TimeDelta position,
+ bool end_of_media));
+ MOCK_METHOD0(DidDisableAudioOutputSinkChanges, void());
+ MOCK_METHOD1(DidUseAudioServiceChange, void(bool uses_audio_service));
+ MOCK_METHOD1(DidPlayerSizeChange, void(const gfx::Size&));
+ MOCK_METHOD0(DidBufferUnderflow, void());
+ MOCK_METHOD0(DidSeek, void());
+ MOCK_METHOD0(GetFeatures, Features(void));
+ MOCK_METHOD0(OnRequestVideoFrameCallback, void());
+ MOCK_METHOD0(GetTextTrackMetadata, std::vector<TextTrackMetadata>());
+
+ bool was_always_muted_ = false;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockWebMediaPlayerClient);
+};
+
+class MockWebMediaPlayerEncryptedMediaClient
+ : public WebMediaPlayerEncryptedMediaClient {
+ public:
+ MockWebMediaPlayerEncryptedMediaClient() = default;
+
+ MOCK_METHOD3(Encrypted,
+ void(media::EmeInitDataType, const unsigned char*, unsigned));
+ MOCK_METHOD0(DidBlockPlaybackWaitingForKey, void());
+ MOCK_METHOD0(DidResumePlaybackBlockedForKey, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockWebMediaPlayerEncryptedMediaClient);
+};
+
+class MockWebMediaPlayerDelegate : public WebMediaPlayerDelegate {
+ public:
+ MockWebMediaPlayerDelegate() = default;
+ ~MockWebMediaPlayerDelegate() override = default;
+
+ // WebMediaPlayerDelegate implementation.
+ int AddObserver(Observer* observer) override {
+ DCHECK_EQ(nullptr, observer_);
+ observer_ = observer;
+ return player_id_;
+ }
+
+ void RemoveObserver(int player_id) override {
+ DCHECK_EQ(player_id_, player_id);
+ observer_ = nullptr;
+ }
+
+ MOCK_METHOD4(DidMediaMetadataChange,
+ void(int, bool, bool, media::MediaContentType));
+
+ void DidPlay(int player_id) override { DCHECK_EQ(player_id_, player_id); }
+
+ void DidPause(int player_id, bool reached_end_of_stream) override {
+ DCHECK_EQ(player_id_, player_id);
+ }
+
+ void PlayerGone(int player_id) override { DCHECK_EQ(player_id_, player_id); }
+
+ void SetIdle(int player_id, bool is_idle) override {
+ DCHECK_EQ(player_id_, player_id);
+ is_idle_ = is_idle;
+ is_stale_ &= is_idle;
+ }
+
+ bool IsIdle(int player_id) override {
+ DCHECK_EQ(player_id_, player_id);
+ return is_idle_;
+ }
+
+ void ClearStaleFlag(int player_id) override {
+ DCHECK_EQ(player_id_, player_id);
+ is_stale_ = false;
+ }
+
+ bool IsStale(int player_id) override {
+ DCHECK_EQ(player_id_, player_id);
+ return is_stale_;
+ }
+
+ bool IsFrameHidden() override { return is_hidden_; }
+
+ void SetIdleForTesting(bool is_idle) { is_idle_ = is_idle; }
+
+ void SetStaleForTesting(bool is_stale) {
+ is_idle_ |= is_stale;
+ is_stale_ = is_stale;
+ }
+
+ // Returns true if the player does in fact expire.
+ bool ExpireForTesting() {
+ if (is_idle_ && !is_stale_) {
+ is_stale_ = true;
+ observer_->OnIdleTimeout();
+ }
+
+ return is_stale_;
+ }
+
+ void SetFrameHiddenForTesting(bool is_hidden) { is_hidden_ = is_hidden; }
+
+ int player_id() { return player_id_; }
+
+ private:
+ Observer* observer_ = nullptr;
+ int player_id_ = 1234;
+ bool is_idle_ = false;
+ bool is_stale_ = false;
+ bool is_hidden_ = false;
+};
+
+class MockSurfaceLayerBridge : public WebSurfaceLayerBridge {
+ public:
+ MOCK_CONST_METHOD0(GetCcLayer, cc::Layer*());
+ MOCK_CONST_METHOD0(GetFrameSinkId, const viz::FrameSinkId&());
+ MOCK_CONST_METHOD0(GetSurfaceId, const viz::SurfaceId&());
+ MOCK_METHOD0(ClearSurfaceId, void());
+ MOCK_METHOD1(SetContentsOpaque, void(bool));
+ MOCK_METHOD0(CreateSurfaceLayer, void());
+ MOCK_METHOD0(ClearObserver, void());
+};
+
+class MockVideoFrameCompositor : public VideoFrameCompositor {
+ public:
+ MockVideoFrameCompositor(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+ : VideoFrameCompositor(task_runner, nullptr) {}
+ ~MockVideoFrameCompositor() override = default;
+
+ // MOCK_METHOD doesn't like OnceCallback.
+ MOCK_METHOD1(SetOnFramePresentedCallback, void(OnNewFramePresentedCB));
+ MOCK_METHOD1(SetIsPageVisible, void(bool));
+ MOCK_METHOD0(
+ GetLastPresentedFrameMetadata,
+ std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata>());
+ MOCK_METHOD0(GetCurrentFrameOnAnyThread, scoped_refptr<media::VideoFrame>());
+ MOCK_METHOD1(UpdateCurrentFrameIfStale,
+ void(VideoFrameCompositor::UpdateType));
+ MOCK_METHOD3(EnableSubmission,
+ void(const viz::SurfaceId&, media::VideoTransformation, bool));
+};
+
+} // namespace
+
+class WebMediaPlayerImplTest
+ : public testing::Test,
+ private WebTestingSupport::WebScopedMockScrollbars {
+ public:
+ WebMediaPlayerImplTest()
+ : media_thread_("MediaThreadForTest"),
+ context_provider_(viz::TestContextProvider::Create()),
+ audio_parameters_(media::TestAudioParameters::Normal()),
+ memory_dump_manager_(
+ base::trace_event::MemoryDumpManager::CreateInstanceForTesting()) {
+ web_view_helper_.Initialize();
+ media_thread_.StartAndWaitForTesting();
+ }
+
+ void InitializeSurfaceLayerBridge() {
+ surface_layer_bridge_ =
+ std::make_unique<NiceMock<MockSurfaceLayerBridge>>();
+ surface_layer_bridge_ptr_ = surface_layer_bridge_.get();
+
+ EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
+ ON_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
+ .WillByDefault(ReturnRef(surface_id_));
+ }
+
+ void InitializeWebMediaPlayerImpl() {
+ InitializeWebMediaPlayerImplInternal(nullptr);
+ }
+
+ ~WebMediaPlayerImplTest() override {
+ if (!wmpi_)
+ return;
+ EXPECT_CALL(client_, SetCcLayer(nullptr));
+ EXPECT_CALL(client_, MediaRemotingStopped(_));
+
+ // Destruct WebMediaPlayerImpl and pump the message loop to ensure that
+ // objects passed to the message loop for destruction are released.
+ //
+ // NOTE: This should be done before any other member variables are
+ // destructed since WMPI may reference them during destruction.
+ wmpi_.reset();
+
+ CycleThreads();
+ }
+
+ protected:
+ void InitializeWebMediaPlayerImplInternal(
+ std::unique_ptr<media::Demuxer> demuxer_override) {
+ auto media_log = std::make_unique<NiceMock<media::MockMediaLog>>();
+ InitializeSurfaceLayerBridge();
+
+ // Retain a raw pointer to |media_log| for use by tests. Meanwhile, give its
+ // ownership to |wmpi_|. Reject attempts to reinitialize to prevent orphaned
+ // expectations on previous |media_log_|.
+ ASSERT_FALSE(media_log_) << "Reinitialization of media_log_ is disallowed";
+ media_log_ = media_log.get();
+
+ auto factory_selector = std::make_unique<media::RendererFactorySelector>();
+ renderer_factory_selector_ = factory_selector.get();
+ decoder_factory_ = std::make_unique<media::DefaultDecoderFactory>(nullptr);
+#if defined(OS_ANDROID)
+ factory_selector->AddBaseFactory(
+ media::RendererType::kDefault,
+ std::make_unique<media::DefaultRendererFactory>(
+ media_log.get(), decoder_factory_.get(),
+ media::DefaultRendererFactory::GetGpuFactoriesCB()));
+ factory_selector->StartRequestRemotePlayStateCB(base::DoNothing());
+#else
+ factory_selector->AddBaseFactory(
+ media::RendererType::kDefault,
+ std::make_unique<media::DefaultRendererFactory>(
+ media_log.get(), decoder_factory_.get(),
+ media::DefaultRendererFactory::GetGpuFactoriesCB(), nullptr));
+#endif
+
+ mojo::Remote<media::mojom::MediaMetricsProvider> provider;
+ media::MediaMetricsProvider::Create(
+ media::MediaMetricsProvider::BrowsingMode::kNormal,
+ media::MediaMetricsProvider::FrameStatus::kNotTopFrame,
+ ukm::kInvalidSourceId, media::learning::FeatureValue(0),
+ media::VideoDecodePerfHistory::SaveCallback(),
+ media::MediaMetricsProvider::GetLearningSessionCallback(),
+ base::BindRepeating(
+ &WebMediaPlayerImplTest::GetRecordAggregateWatchTimeCallback,
+ base::Unretained(this)),
+ provider.BindNewPipeAndPassReceiver());
+
+ // Initialize provider since none of the tests below actually go through the
+ // full loading/pipeline initialize phase. If this ever changes the provider
+ // will start DCHECK failing.
+ provider->Initialize(false, media::mojom::MediaURLScheme::kHttp,
+ media::mojom::MediaStreamType::kNone);
+
+ audio_sink_ =
+ base::WrapRefCounted(new NiceMock<media::MockAudioRendererSink>());
+
+ url_index_ = std::make_unique<UrlIndex>(&mock_resource_fetch_context_,
+ media_thread_.task_runner());
+
+ auto params = std::make_unique<WebMediaPlayerParams>(
+ std::move(media_log), WebMediaPlayerParams::DeferLoadCB(), audio_sink_,
+ media_thread_.task_runner(), media_thread_.task_runner(),
+ media_thread_.task_runner(), media_thread_.task_runner(),
+ base::BindRepeating(&WebMediaPlayerImplTest::OnAdjustAllocatedMemory,
+ base::Unretained(this)),
+ nullptr, media::RequestRoutingTokenCallback(), nullptr, false, false,
+ provider.Unbind(),
+ base::BindOnce(&WebMediaPlayerImplTest::CreateMockSurfaceLayerBridge,
+ base::Unretained(this)),
+ viz::TestContextProvider::Create(),
+ WebMediaPlayer::SurfaceLayerMode::kAlways,
+ is_background_suspend_enabled_, is_background_video_playback_enabled_,
+ true, std::move(demuxer_override), nullptr);
+
+ auto compositor = std::make_unique<NiceMock<MockVideoFrameCompositor>>(
+ params->video_frame_compositor_task_runner());
+ compositor_ = compositor.get();
+
+ wmpi_ = std::make_unique<WebMediaPlayerImpl>(
+ GetWebLocalFrame(), &client_, &encrypted_client_, &delegate_,
+ std::move(factory_selector), url_index_.get(), std::move(compositor),
+ std::move(params));
+ }
+
+ std::unique_ptr<WebSurfaceLayerBridge> CreateMockSurfaceLayerBridge(
+ WebSurfaceLayerBridgeObserver*,
+ cc::UpdateSubmissionStateCB) {
+ return std::move(surface_layer_bridge_);
+ }
+
+ WebLocalFrame* GetWebLocalFrame() {
+ return web_view_helper_.LocalMainFrame();
+ }
+
+ int64_t OnAdjustAllocatedMemory(int64_t delta) {
+ reported_memory_ += delta;
+ return 0;
+ }
+
+ void SetNetworkState(WebMediaPlayer::NetworkState state) {
+ EXPECT_CALL(client_, NetworkStateChanged());
+ wmpi_->SetNetworkState(state);
+ }
+
+ void SetReadyState(WebMediaPlayer::ReadyState state) {
+ EXPECT_CALL(client_, ReadyStateChanged());
+ wmpi_->SetReadyState(state);
+ }
+
+ void SetDuration(base::TimeDelta value) {
+ wmpi_->SetPipelineMediaDurationForTest(value);
+ wmpi_->OnDurationChange();
+ }
+
+ media::MediaMetricsProvider::RecordAggregateWatchTimeCallback
+ GetRecordAggregateWatchTimeCallback() {
+ return base::NullCallback();
+ }
+
+ base::TimeDelta GetCurrentTimeInternal() {
+ return wmpi_->GetCurrentTimeInternal();
+ }
+
+ void SetPaused(bool is_paused) { wmpi_->paused_ = is_paused; }
+ void SetSeeking(bool is_seeking) { wmpi_->seeking_ = is_seeking; }
+ void SetEnded(bool is_ended) { wmpi_->ended_ = is_ended; }
+ void SetTickClock(const base::TickClock* clock) {
+ wmpi_->SetTickClockForTest(clock);
+ }
+ void SetWasSuspendedForFrameClosed(bool is_suspended) {
+ wmpi_->was_suspended_for_frame_closed_ = is_suspended;
+ }
+
+ void SetFullscreen(bool is_fullscreen) {
+ wmpi_->overlay_enabled_ = is_fullscreen;
+ wmpi_->overlay_info_.is_fullscreen = is_fullscreen;
+ }
+
+ void SetMetadata(bool has_audio, bool has_video) {
+ wmpi_->SetNetworkState(WebMediaPlayer::kNetworkStateLoaded);
+
+ EXPECT_CALL(client_, ReadyStateChanged());
+ wmpi_->SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
+ wmpi_->pipeline_metadata_.has_audio = has_audio;
+ wmpi_->pipeline_metadata_.has_video = has_video;
+
+ if (has_video) {
+ wmpi_->pipeline_metadata_.video_decoder_config =
+ TestVideoConfig::Normal();
+ }
+
+ if (has_audio) {
+ wmpi_->pipeline_metadata_.audio_decoder_config =
+ TestAudioConfig::Normal();
+ }
+ }
+
+ void SetError(media::PipelineStatus status = media::PIPELINE_ERROR_DECODE) {
+ wmpi_->OnError(status);
+ }
+
+ void OnMetadata(const media::PipelineMetadata& metadata) {
+ wmpi_->OnMetadata(metadata);
+ }
+
+ void OnWaiting(media::WaitingReason reason) { wmpi_->OnWaiting(reason); }
+
+ void OnVideoNaturalSizeChange(const gfx::Size& size) {
+ wmpi_->OnVideoNaturalSizeChange(size);
+ }
+
+ void OnVideoConfigChange(const media::VideoDecoderConfig& config) {
+ wmpi_->OnVideoConfigChange(config);
+ }
+
+ WebMediaPlayerImpl::PlayState ComputePlayState() {
+ return wmpi_->UpdatePlayState_ComputePlayState(false, true, false, false);
+ }
+
+ WebMediaPlayerImpl::PlayState ComputePlayState_FrameHidden() {
+ return wmpi_->UpdatePlayState_ComputePlayState(false, true, false, true);
+ }
+
+ WebMediaPlayerImpl::PlayState ComputePlayState_Suspended() {
+ return wmpi_->UpdatePlayState_ComputePlayState(false, true, true, false);
+ }
+
+ WebMediaPlayerImpl::PlayState ComputePlayState_Flinging() {
+ return wmpi_->UpdatePlayState_ComputePlayState(true, true, false, false);
+ }
+
+ WebMediaPlayerImpl::PlayState ComputePlayState_BackgroundedStreaming() {
+ return wmpi_->UpdatePlayState_ComputePlayState(false, false, false, true);
+ }
+
+ bool IsSuspended() { return wmpi_->pipeline_controller_->IsSuspended(); }
+
+ int64_t GetDataSourceMemoryUsage() const {
+ return wmpi_->data_source_->GetMemoryUsage();
+ }
+
+ void AddBufferedRanges() {
+ wmpi_->buffered_data_source_host_->AddBufferedByteRange(0, 1);
+ }
+
+ void SetDelegateState(WebMediaPlayerImpl::DelegateState state) {
+ wmpi_->SetDelegateState(state, false);
+ }
+
+ void SetUpMediaSuspend(bool enable) {
+ is_background_suspend_enabled_ = enable;
+ }
+
+ void SetUpBackgroundVideoPlayback(bool enable) {
+ is_background_video_playback_enabled_ = enable;
+ }
+
+ bool IsVideoLockedWhenPausedWhenHidden() const {
+ return wmpi_->video_locked_when_paused_when_hidden_;
+ }
+
+ void BackgroundPlayer() {
+ base::RunLoop loop;
+ EXPECT_CALL(*compositor_, SetIsPageVisible(false))
+ .WillOnce(RunClosure(loop.QuitClosure()));
+
+ delegate_.SetFrameHiddenForTesting(true);
+ SetWasSuspendedForFrameClosed(false);
+
+ wmpi_->OnFrameHidden();
+
+ loop.Run();
+
+ // Clear the mock so it doesn't have a stale QuitClosure.
+ testing::Mock::VerifyAndClearExpectations(compositor_);
+ }
+
+ void ForegroundPlayer() {
+ base::RunLoop loop;
+ EXPECT_CALL(*compositor_, SetIsPageVisible(true))
+ .WillOnce(RunClosure(loop.QuitClosure()));
+
+ delegate_.SetFrameHiddenForTesting(false);
+ SetWasSuspendedForFrameClosed(false);
+
+ wmpi_->OnFrameShown();
+
+ loop.Run();
+
+ // Clear the mock so it doesn't have a stale QuitClosure.
+ testing::Mock::VerifyAndClearExpectations(compositor_);
+ }
+
+ void Play() { wmpi_->Play(); }
+
+ void Pause() { wmpi_->Pause(); }
+
+ void ScheduleIdlePauseTimer() { wmpi_->ScheduleIdlePauseTimer(); }
+ void FireIdlePauseTimer() { wmpi_->background_pause_timer_.FireNow(); }
+
+ bool IsIdlePauseTimerRunning() {
+ return wmpi_->background_pause_timer_.IsRunning();
+ }
+
+ void SetSuspendState(bool is_suspended) {
+ wmpi_->SetSuspendState(is_suspended);
+ }
+
+ void SetLoadType(WebMediaPlayer::LoadType load_type) {
+ wmpi_->load_type_ = load_type;
+ }
+
+ bool IsVideoTrackDisabled() const { return wmpi_->video_track_disabled_; }
+
+ bool IsDisableVideoTrackPending() const {
+ return !wmpi_->is_background_status_change_cancelled_;
+ }
+
+ gfx::Size GetNaturalSize() const {
+ return wmpi_->pipeline_metadata_.natural_size;
+ }
+
+ VideoDecodeStatsReporter* GetVideoStatsReporter() const {
+ return wmpi_->video_decode_stats_reporter_.get();
+ }
+
+ media::VideoCodecProfile GetVideoStatsReporterCodecProfile() const {
+ DCHECK(GetVideoStatsReporter());
+ return GetVideoStatsReporter()->codec_profile_;
+ }
+
+ bool ShouldCancelUponDefer() const {
+ return wmpi_->mb_data_source_->cancel_on_defer_for_testing();
+ }
+
+ bool IsDataSourceMarkedAsPlaying() const {
+ return wmpi_->mb_data_source_->media_has_played();
+ }
+
+ scoped_refptr<media::VideoFrame> CreateFrame() {
+ gfx::Size size(8, 8);
+ return media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_I420, size,
+ gfx::Rect(size), size,
+ base::TimeDelta());
+ }
+
+ void RequestVideoFrameCallback() { wmpi_->RequestVideoFrameCallback(); }
+ void GetVideoFramePresentationMetadata() {
+ wmpi_->GetVideoFramePresentationMetadata();
+ }
+ void UpdateFrameIfStale() { wmpi_->UpdateFrameIfStale(); }
+
+ void OnNewFramePresentedCallback() { wmpi_->OnNewFramePresentedCallback(); }
+
+ scoped_refptr<media::VideoFrame> GetCurrentFrameFromCompositor() {
+ return wmpi_->GetCurrentFrameFromCompositor();
+ }
+
+ enum class LoadType { kFullyBuffered, kStreaming };
+ void Load(std::string data_file,
+ LoadType load_type = LoadType::kFullyBuffered) {
+ const bool is_streaming = load_type == LoadType::kStreaming;
+
+ // The URL is used by MultiBufferDataSource to determine if it should assume
+ // the resource is fully buffered locally. We can use a fake one here since
+ // we're injecting the response artificially. It's value is unknown to the
+ // underlying demuxer.
+ const KURL kTestURL(
+ String::FromUTF8(std::string(is_streaming ? "http" : "file") +
+ "://example.com/sample.webm"));
+
+ // This block sets up a fetch context which ultimately provides us a pointer
+ // to the WebAssociatedURLLoaderClient handed out by the DataSource after it
+ // requests loading of a resource. We then use that client as if we are the
+ // network stack and "serve" an in memory file to the DataSource.
+ WebAssociatedURLLoaderClient* client = nullptr;
+ EXPECT_CALL(mock_resource_fetch_context_, CreateUrlLoader(_))
+ .WillRepeatedly(Invoke([&client](const WebAssociatedURLLoaderOptions&) {
+ auto a = std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
+ EXPECT_CALL(*a, LoadAsynchronously(_, _))
+ .WillRepeatedly(testing::SaveArg<1>(&client));
+ return a;
+ }));
+
+ wmpi_->Load(WebMediaPlayer::kLoadTypeURL,
+ WebMediaPlayerSource(WebURL(kTestURL)),
+ WebMediaPlayer::kCorsModeUnspecified,
+ /*is_cache_disabled=*/false);
+
+ base::RunLoop().RunUntilIdle();
+
+ // Load a real media file into memory.
+ scoped_refptr<media::DecoderBuffer> data =
+ media::ReadTestDataFile(data_file);
+
+ // "Serve" the file to the DataSource. Note: We respond with 200 okay, which
+ // will prevent range requests or partial responses from being used. For
+ // streaming responses, we'll pretend we don't know the content length.
+ WebURLResponse response(kTestURL);
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Length"),
+ WebString::FromUTF8(
+ is_streaming ? "-1" : base::NumberToString(data->data_size())));
+ response.SetExpectedContentLength(is_streaming ? -1 : data->data_size());
+ response.SetHttpStatusCode(200);
+ client->DidReceiveResponse(response);
+
+ // Copy over the file data.
+ client->DidReceiveData(reinterpret_cast<const char*>(data->data()),
+ static_cast<int>(data->data_size()));
+
+ // If we're pretending to be a streaming resource, don't complete the load;
+ // otherwise the DataSource will not be marked as streaming.
+ if (!is_streaming)
+ client->DidFinishLoading();
+ }
+
+ // This runs until we reach the |ready_state_|. Attempting to wait for ready
+ // states < kReadyStateHaveCurrentData in non-startup-suspend test cases is
+ // unreliable due to asynchronous execution of tasks on the
+ // base::test:TaskEnvironment.
+ void LoadAndWaitForReadyState(std::string data_file,
+ WebMediaPlayer::ReadyState ready_state) {
+ Load(data_file);
+ while (wmpi_->GetReadyState() < ready_state) {
+ base::RunLoop loop;
+ EXPECT_CALL(client_, ReadyStateChanged())
+ .WillRepeatedly(RunClosure(loop.QuitClosure()));
+ loop.Run();
+
+ // Clear the mock so it doesn't have a stale QuitClosure.
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ }
+
+ // Verify we made it through pipeline startup.
+ EXPECT_TRUE(wmpi_->data_source_);
+ EXPECT_TRUE(wmpi_->demuxer_);
+
+ if (ready_state > WebMediaPlayer::kReadyStateHaveCurrentData)
+ EXPECT_FALSE(wmpi_->seeking_);
+ }
+
+ void LoadAndWaitForCurrentData(std::string data_file) {
+ LoadAndWaitForReadyState(data_file,
+ WebMediaPlayer::kReadyStateHaveCurrentData);
+ }
+
+ void CycleThreads() {
+ // Ensure any tasks waiting to be posted to the media thread are posted.
+ base::RunLoop().RunUntilIdle();
+
+ // Flush all media tasks.
+ media_thread_.FlushForTesting();
+
+ // Cycle anything that was posted back from the media thread.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void OnProgress() { wmpi_->OnProgress(); }
+
+ void OnCdmCreated(base::RepeatingClosure quit_closure,
+ WebContentDecryptionModule* cdm,
+ const std::string& error_message) {
+ LOG_IF(ERROR, !error_message.empty()) << error_message;
+ EXPECT_TRUE(cdm);
+ web_cdm_.reset(cdm);
+ quit_closure.Run();
+ }
+
+ void CreateCdm() {
+ // Must use a supported key system on a secure context.
+ std::u16string key_system = u"org.w3.clearkey";
+ auto test_origin = WebSecurityOrigin::CreateFromString(
+ WebString::FromUTF8("https://test.origin"));
+
+ base::RunLoop run_loop;
+ WebContentDecryptionModuleImpl::Create(
+ &mock_cdm_factory_, key_system, test_origin, media::CdmConfig(),
+ base::BindOnce(&WebMediaPlayerImplTest::OnCdmCreated,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ EXPECT_TRUE(web_cdm_);
+ }
+
+ void SetCdm() {
+ DCHECK(web_cdm_);
+ EXPECT_CALL(*mock_cdm_, GetCdmContext())
+ .WillRepeatedly(Return(&mock_cdm_context_));
+ wmpi_->SetCdmInternal(web_cdm_.get());
+ }
+
+ media::MemoryDumpProviderProxy* GetMainThreadMemDumper() {
+ return wmpi_->main_thread_mem_dumper_.get();
+ }
+ media::MemoryDumpProviderProxy* GetMediaThreadMemDumper() {
+ return wmpi_->media_thread_mem_dumper_.get();
+ }
+
+ int32_t GetMediaLogId() { return media_log_->id(); }
+
+ // "Media" thread. This is necessary because WMPI destruction waits on a
+ // WaitableEvent.
+ base::Thread media_thread_;
+
+ // Blink state.
+ frame_test_helpers::WebViewHelper web_view_helper_;
+
+ scoped_refptr<viz::TestContextProvider> context_provider_;
+ NiceMock<MockVideoFrameCompositor>* compositor_;
+
+ scoped_refptr<NiceMock<media::MockAudioRendererSink>> audio_sink_;
+ MockResourceFetchContext mock_resource_fetch_context_;
+ std::unique_ptr<UrlIndex> url_index_;
+
+ // Audio hardware configuration.
+ media::AudioParameters audio_parameters_;
+
+ bool is_background_suspend_enabled_ = false;
+ bool is_background_video_playback_enabled_ = true;
+
+ // The client interface used by |wmpi_|.
+ NiceMock<MockWebMediaPlayerClient> client_;
+ MockWebMediaPlayerEncryptedMediaClient encrypted_client_;
+
+ // Used to create the media::MockCdm to test encrypted playback.
+ scoped_refptr<media::MockCdm> mock_cdm_ =
+ base::MakeRefCounted<media::MockCdm>();
+ media::MockCdmFactory mock_cdm_factory_{mock_cdm_};
+ std::unique_ptr<WebContentDecryptionModule> web_cdm_;
+ media::MockCdmContext mock_cdm_context_;
+
+ viz::FrameSinkId frame_sink_id_ = viz::FrameSinkId(1, 1);
+ viz::LocalSurfaceId local_surface_id_ =
+ viz::LocalSurfaceId(11, base::UnguessableToken::Deserialize(0x111111, 0));
+ viz::SurfaceId surface_id_ =
+ viz::SurfaceId(frame_sink_id_, local_surface_id_);
+
+ NiceMock<MockWebMediaPlayerDelegate> delegate_;
+
+ // Use NiceMock since most tests do not care about this.
+ std::unique_ptr<NiceMock<MockSurfaceLayerBridge>> surface_layer_bridge_;
+ NiceMock<MockSurfaceLayerBridge>* surface_layer_bridge_ptr_ = nullptr;
+
+ // Only valid once set by InitializeWebMediaPlayerImpl(), this is for
+ // verifying a subset of potential media logs.
+ NiceMock<media::MockMediaLog>* media_log_ = nullptr;
+
+ // Total memory in bytes allocated by the WebMediaPlayerImpl instance.
+ int64_t reported_memory_ = 0;
+
+ // Raw pointer of the media::RendererFactorySelector owned by |wmpi_|.
+ media::RendererFactorySelector* renderer_factory_selector_ = nullptr;
+
+ // default decoder factory for WMPI
+ std::unique_ptr<media::DecoderFactory> decoder_factory_;
+
+ // The WebMediaPlayerImpl instance under test.
+ std::unique_ptr<WebMediaPlayerImpl> wmpi_;
+
+ std::unique_ptr<base::trace_event::MemoryDumpManager> memory_dump_manager_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImplTest);
+};
+
+TEST_F(WebMediaPlayerImplTest, ConstructAndDestroy) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_FALSE(IsSuspended());
+}
+
+// Verify LoadAndWaitForCurrentData() functions without issue.
+TEST_F(WebMediaPlayerImplTest, LoadAndDestroy) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_FALSE(IsSuspended());
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+ LoadAndWaitForCurrentData(kAudioOnlyTestFile);
+ EXPECT_FALSE(IsSuspended());
+ CycleThreads();
+
+ // The data source contains the entire file, so subtract it from the memory
+ // usage to ensure we're getting audio buffer and demuxer usage too.
+ const int64_t data_source_size = GetDataSourceMemoryUsage();
+ EXPECT_GT(data_source_size, 0);
+ EXPECT_GT(reported_memory_ - data_source_size, 0);
+}
+
+// Verify LoadAndWaitForCurrentData() functions without issue.
+TEST_F(WebMediaPlayerImplTest, LoadAndDestroyDataUrl) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_FALSE(IsSuspended());
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+
+ const KURL kMp3DataUrl(
+ "data://audio/mp3;base64,SUQzAwAAAAAAFlRFTkMAAAAMAAAAQW1hZGV1cyBQcm//"
+ "+5DEAAAAAAAAAAAAAAAAAAAAAABYaW5nAAAADwAAAAwAAAftABwcHBwcHBwcMTExMTExMTFG"
+ "RkZGRkZGRlpaWlpaWlpaWm9vb29vb29vhISEhISEhISYmJiYmJiYmJitra2tra2trcLCwsLC"
+ "wsLC3t7e3t7e3t7e7+/v7+/v7+///////////"
+ "wAAADxMQU1FMy45OHIErwAAAAAudQAANCAkCK9BAAHMAAAHbZV/"
+ "jdYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/"
+ "+0DEAAABcAOH1AAAIhcbaLc80EgAAAAAAPAAAP/"
+ "0QfAAQdBwGBwf8AwGAgAAMBYxgxBgaTANj4NBIJgwVX+"
+ "jXKCAMFgC8LgBGBmB3KTAhAT8wIQFjATAWhyLf4TUFdHcW4WkdwwxdMT3EaJEeo4UknR8dww"
+ "wlxIj1RZJJ98S0khhhhiaPX/8LqO4YYS4kRhRhf/8nD2HsYj1HqZF4vf9YKiIKgqIlQAMA3/"
+ "kQAMHsToyV0cDdv/"
+ "7IMQHgEgUaSld4QAg1A0lde4cXDskP7w0MysiKzEUARMCEBQwLQPAwC8VADBwCsOwF+v///"
+ "6ydVW3tR1HNzg22xv+3Z9gAAOgA//"
+ "pg1gxGG0G6aJdDp5LCgnFycZmDJi0ADQhRrZGzKGQAqP//3t3Xe3pUv19yF6v7FIAAiMAb/"
+ "3/"
+ "+yDEAwBGpBsprn9gIN0NZOn9lFyAAGa1QaI6ZhLqtGY3QFgnJ4BlymYWTBYNQ4LcX88rfX/"
+ "1Yu+8WKLoSm09u7Fd1QADgbfwwBECUMBpB+TDDGAUySsMLO80jP18xowMNGTBgotYkm3gPv/"
+ "/6P1v2pspRShZJjXgT7V1AAAoAG/9//"
+ "sgxAMCxzRpKa9k5KDODOUR7ihciAAsEwYdoVZqATrn1uJSYowIBg9gKn0MboJlBF3Fh4YAfX"
+ "//9+52v6qhZt7o244rX/JfRoADB+B5MPsQ401sRj4pGKOeGUzuJDGwHEhUhAvBuMNAM1b//"
+ "t9kSl70NlDrbJecU/t99aoAACMAD//7IMQCggY0Gymuf2Ag7A0k9f2UXPwAAGaFSZ/"
+ "7BhFSu4Yy2FjHCYZlKoYQTiEMTLaGxV5nNu/8UddjmtWbl6r/SYAN/pAADACAI8wHQHwMM/"
+ "XrDJuAv48nRNEXDHS8w4YMJCy0aSDbgm3//26S0noiIgkPfZn1Sa9V16dNAAAgAA//"
+ "+yDEAoBHCGkpr2SkoMgDZXW/cAT4iAA8FEYeASxqGx/H20IYYpYHJg+AHH2GbgBlgl/"
+ "1yQ2AFP///YpK32okeasc/f/+xXsAAJ1AA/"
+ "9Ntaj1Pc0K7Yzw6FrOHlozEHzFYEEg6NANZbIn9a8p//j7HC6VvlmStt3o+pUAACMADfyA//"
+ "sgxAOCRkwbKa5/YCDUDWU1/ZxcAGZVQZ27Zg/KweYuMFmm74hkSqYKUCINS0ZoxZ5XOv/"
+ "8X7EgE4lCZDu7fc4AN/6BQHQwG0GpMMAUczI/wpM7iuM9TTGCQwsRMEBi8Cl7yAnv//"
+ "2+belL59SGkk1ENqvyagAAKAAP/aAAEBGmGv/"
+ "7IMQGAobYaSuvcOLgzA1lNe4cXGDeaOzj56RhnnIBMZrA4GMAKF4GBCJjK4gC+v///"
+ "uh3b1WWRQNv2e/syS7ABAADCACBMPUSw0sNqj23G4OZHMzmKjGgLDBMkAzxpMNAE1b///"
+ "od72VdCOtlpw1/764AAhwAf/0AAGUkeZb0Bgz/"
+ "+yDEB4CGMBsrrn9gINgNJXX9qFxCcAYkOE7GsVJi6QBCEZCEEav2owqE3f4+KbGKLWKN29/"
+ "YsAAC0AUAARAL5gMgLQYWGjRGQkBGh1MmZseGKjpgwUYCBoprUgcDlG//7372tX0y/"
+ "zl33dN2ugIf/yIADoERhDlqm9CtAfsRzhlK//"
+ "tAxAoAB7RpKPXhACHRkia3PPAAEkGL4EUFgCTA3BTMDkAcEgMgoCeefz/////"
+ "oxOy73ryRx97nI2//YryIAhX0mveu/"
+ "3tEgAAAABh2nnnBAAOYOK6ZtxB4mEYkiaDwX5gzgHGAkAUYGwB0kMGQFaKGBEAwDgHAUAcvP"
+ "KwDfJeHEGqcMk3iN5blKocU8c6FA4FxhTqXf/OtXzv37ErkOYWXP/"
+ "93kTV91+YNo3Lh8ECwliUABv7/"
+ "+xDEAYPIREMrXcMAKAAAP8AAAARfwAADHinN1RU5NKTjkHN1Mc08dTJQjL4GBwgYEAK/"
+ "X2a8/1qZjMtcFCUTiSXmteUeFNBWIqEKCioLiKyO10VVTEFNRTMuOTguMlVVVVVVVVVVVf/"
+ "7EMQJg8AAAaQAAAAgAAA0gAAABFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
+ "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVEFHAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAP8=");
+
+ wmpi_->Load(WebMediaPlayer::kLoadTypeURL,
+ WebMediaPlayerSource(WebURL(kMp3DataUrl)),
+ WebMediaPlayer::kCorsModeUnspecified,
+ /*is_cache_disabled=*/false);
+
+ base::RunLoop().RunUntilIdle();
+
+ // This runs until we reach the have current data state. Attempting to wait
+ // for states < kReadyStateHaveCurrentData is unreliable due to asynchronous
+ // execution of tasks on the base::test:TaskEnvironment.
+ while (wmpi_->GetReadyState() < WebMediaPlayer::kReadyStateHaveCurrentData) {
+ base::RunLoop loop;
+ EXPECT_CALL(client_, ReadyStateChanged())
+ .WillRepeatedly(RunClosure(loop.QuitClosure()));
+ loop.Run();
+
+ // Clear the mock so it doesn't have a stale QuitClosure.
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ }
+
+ EXPECT_FALSE(IsSuspended());
+ CycleThreads();
+}
+
+// Verify that preload=metadata suspend works properly.
+TEST_F(WebMediaPlayerImplTest, LoadPreloadMetadataSuspend) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(false));
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadMetaData);
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveMetadata);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(AnyNumber());
+ CycleThreads();
+ EXPECT_TRUE(IsSuspended());
+ EXPECT_TRUE(ShouldCancelUponDefer());
+
+ // The data source contains the entire file, so subtract it from the memory
+ // usage to ensure there's no other memory usage.
+ const int64_t data_source_size = GetDataSourceMemoryUsage();
+ EXPECT_GT(data_source_size, 0);
+ EXPECT_EQ(reported_memory_ - data_source_size, 0);
+}
+
+// Verify that Play() before kReadyStateHaveEnough doesn't increase buffer size.
+TEST_F(WebMediaPlayerImplTest, NoBufferSizeIncreaseUntilHaveEnough) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(true));
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveMetadata);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(AnyNumber());
+ wmpi_->Play();
+ EXPECT_FALSE(IsDataSourceMarkedAsPlaying());
+
+ while (wmpi_->GetReadyState() < WebMediaPlayer::kReadyStateHaveEnoughData) {
+ // Clear the mock so it doesn't have a stale QuitClosure.
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ base::RunLoop loop;
+ EXPECT_CALL(client_, ReadyStateChanged())
+ .WillRepeatedly(RunClosure(loop.QuitClosure()));
+ loop.Run();
+ }
+
+ EXPECT_TRUE(IsDataSourceMarkedAsPlaying());
+}
+
+// Verify that preload=metadata suspend works properly for streaming sources.
+TEST_F(WebMediaPlayerImplTest, LoadPreloadMetadataSuspendNoStreaming) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(false));
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadMetaData);
+
+ // This test needs a file which is larger than the MultiBuffer block size;
+ // otherwise we'll never complete initialization of the MultiBufferDataSource.
+ constexpr char kLargeAudioOnlyTestFile[] = "bear_192kHz.wav";
+ Load(kLargeAudioOnlyTestFile, LoadType::kStreaming);
+
+ // This runs until we reach the metadata state.
+ while (wmpi_->GetReadyState() < WebMediaPlayer::kReadyStateHaveMetadata) {
+ base::RunLoop loop;
+ EXPECT_CALL(client_, ReadyStateChanged())
+ .WillRepeatedly(RunClosure(loop.QuitClosure()));
+ loop.Run();
+
+ // Clear the mock so it doesn't have a stale QuitClosure.
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ }
+
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(AnyNumber());
+ CycleThreads();
+ EXPECT_FALSE(IsSuspended());
+}
+
+// Verify that lazy load for preload=metadata works properly.
+TEST_F(WebMediaPlayerImplTest, LazyLoadPreloadMetadataSuspend) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(media::kPreloadMetadataLazyLoad);
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(false));
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadMetaData);
+
+ // Don't set poster, but ensure we still reach suspended state.
+
+ LoadAndWaitForReadyState(kVideoOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveMetadata);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(AnyNumber());
+ CycleThreads();
+ EXPECT_TRUE(IsSuspended());
+ EXPECT_TRUE(wmpi_->DidLazyLoad());
+ EXPECT_FALSE(ShouldCancelUponDefer());
+
+ // The data source contains the entire file, so subtract it from the memory
+ // usage to ensure there's no other memory usage.
+ const int64_t data_source_size = GetDataSourceMemoryUsage();
+ EXPECT_GT(data_source_size, 0);
+ EXPECT_EQ(reported_memory_ - data_source_size, 0);
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+// Verify that preload=metadata suspend video w/ poster uses zero video memory.
+TEST_F(WebMediaPlayerImplTest, LoadPreloadMetadataSuspendNoVideoMemoryUsage) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(false));
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadMetaData);
+ wmpi_->SetPoster(WebURL(KURL("file://example.com/sample.jpg")));
+
+ LoadAndWaitForReadyState(kVideoOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveMetadata);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(AnyNumber());
+ CycleThreads();
+ EXPECT_TRUE(IsSuspended());
+
+ // The data source contains the entire file, so subtract it from the memory
+ // usage to ensure there's no other memory usage.
+ const int64_t data_source_size = GetDataSourceMemoryUsage();
+ EXPECT_GT(data_source_size, 0);
+ EXPECT_EQ(reported_memory_ - data_source_size, 0);
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+// Verify that preload=metadata suspend is aborted if we know the element will
+// play as soon as we reach kReadyStateHaveFutureData.
+TEST_F(WebMediaPlayerImplTest, LoadPreloadMetadataSuspendCouldPlay) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(true));
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadMetaData);
+ LoadAndWaitForCurrentData(kAudioOnlyTestFile);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(AnyNumber());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(IsSuspended());
+}
+
+TEST_F(WebMediaPlayerImplTest, IdleSuspendBeforeLoadingBegins) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_FALSE(delegate_.ExpireForTesting());
+}
+
+TEST_F(WebMediaPlayerImplTest,
+ IdleSuspendIsDisabledIfLoadingProgressedRecently) {
+ InitializeWebMediaPlayerImpl();
+ base::SimpleTestTickClock clock;
+ clock.Advance(base::TimeDelta::FromSeconds(1));
+ SetTickClock(&clock);
+ AddBufferedRanges();
+ wmpi_->DidLoadingProgress();
+ // Advance less than the loading timeout.
+ clock.Advance(base::TimeDelta::FromSeconds(1));
+ EXPECT_FALSE(delegate_.ExpireForTesting());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(IsSuspended());
+}
+
+TEST_F(WebMediaPlayerImplTest, IdleSuspendIsEnabledIfLoadingHasStalled) {
+ InitializeWebMediaPlayerImpl();
+ SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
+ base::SimpleTestTickClock clock;
+ clock.Advance(base::TimeDelta::FromSeconds(1));
+ SetTickClock(&clock);
+ AddBufferedRanges();
+ wmpi_->DidLoadingProgress();
+ // Advance more than the loading timeout.
+ clock.Advance(base::TimeDelta::FromSeconds(4));
+ EXPECT_TRUE(delegate_.ExpireForTesting());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(IsSuspended());
+}
+
+TEST_F(WebMediaPlayerImplTest, DidLoadingProgressTriggersResume) {
+ // Same setup as IdleSuspendIsEnabledBeforeLoadingBegins.
+ InitializeWebMediaPlayerImpl();
+ SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
+ EXPECT_TRUE(delegate_.ExpireForTesting());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(IsSuspended());
+
+ // Like IdleSuspendIsDisabledIfLoadingProgressedRecently, the idle timeout
+ // should be rejected if it hasn't been long enough.
+ AddBufferedRanges();
+ wmpi_->DidLoadingProgress();
+ EXPECT_FALSE(delegate_.ExpireForTesting());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(IsSuspended());
+}
+
+TEST_F(WebMediaPlayerImplTest, RequestVideoFrameCallback) {
+ InitializeWebMediaPlayerImpl();
+
+ EXPECT_CALL(*compositor_, SetOnFramePresentedCallback(_));
+ RequestVideoFrameCallback();
+}
+
+TEST_F(WebMediaPlayerImplTest, UpdateFrameIfStale) {
+ InitializeWebMediaPlayerImpl();
+
+ base::RunLoop loop;
+ EXPECT_CALL(*compositor_,
+ UpdateCurrentFrameIfStale(
+ VideoFrameCompositor::UpdateType::kBypassClient))
+ .WillOnce(RunClosure(loop.QuitClosure()));
+
+ UpdateFrameIfStale();
+
+ loop.Run();
+
+ testing::Mock::VerifyAndClearExpectations(compositor_);
+}
+
+TEST_F(WebMediaPlayerImplTest, GetVideoFramePresentationMetadata) {
+ InitializeWebMediaPlayerImpl();
+
+ EXPECT_CALL(*compositor_, GetLastPresentedFrameMetadata());
+ GetVideoFramePresentationMetadata();
+}
+
+TEST_F(WebMediaPlayerImplTest, OnNewFramePresentedCallback) {
+ InitializeWebMediaPlayerImpl();
+ EXPECT_CALL(client_, OnRequestVideoFrameCallback());
+
+ OnNewFramePresentedCallback();
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Constructed) {
+ InitializeWebMediaPlayerImpl();
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_HaveMetadata) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_HaveFutureData) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+// Ensure memory reporting is not running after an error.
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_PlayingError) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+ SetError();
+ state = ComputePlayState();
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Playing) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_PlayingVideoOnly) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(false, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Underflow) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveCurrentData);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameHidden) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_FrameHidden();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameHiddenAudioOnly) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+
+ SetMetadata(true, false);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_FrameHidden();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameHiddenSuspendNoResume) {
+ SetUpMediaSuspend(true);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(media::kResumeBackgroundVideo);
+
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_FrameHidden();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+
+ SetPaused(true);
+ state = ComputePlayState_FrameHidden();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_TRUE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameHiddenSuspendWithResume) {
+ SetUpMediaSuspend(true);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(media::kResumeBackgroundVideo);
+
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_FrameHidden();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameClosed) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ SetWasSuspendedForFrameClosed(true);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_TRUE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_PausedSeek) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetSeeking(true);
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Ended) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(false);
+ SetEnded(true);
+
+ // Before Blink pauses us (or seeks for looping content), the media session
+ // should be preserved.
+ WebMediaPlayerImpl::PlayState state;
+ state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PLAYING, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_TRUE(state.is_memory_reporting_enabled);
+
+ SetPaused(true);
+ state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_DoesNotStaySuspended) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
+
+ // Should stay suspended even though not stale or backgrounded.
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_Suspended();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_StaysSuspended) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+
+ // Should stay suspended even though not stale or backgrounded.
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_Suspended();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_TRUE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_ResumeForNeedFirstFrame) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+
+ // Should stay suspended even though not stale or backgrounded.
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_Suspended();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_TRUE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+
+ wmpi_->OnBecameVisible();
+ state = ComputePlayState_Suspended();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Flinging) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+
+ // Remote media via the FlingingRenderer should not be idle.
+ WebMediaPlayerImpl::PlayState state = ComputePlayState_Flinging();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_FALSE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Fullscreen) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetFullscreen(true);
+ SetPaused(true);
+ delegate_.SetStaleForTesting(true);
+
+ // Fullscreen media is never suspended (Android only behavior).
+ WebMediaPlayerImpl::PlayState state = ComputePlayState();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ComputePlayState_Streaming) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ SetPaused(true);
+ delegate_.SetStaleForTesting(true);
+
+ // Streaming media should not suspend, even if paused, stale, and
+ // backgrounded.
+ WebMediaPlayerImpl::PlayState state;
+ state = ComputePlayState_BackgroundedStreaming();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::PAUSED, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_FALSE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+
+ // Streaming media should suspend when the tab is closed, regardless.
+ SetWasSuspendedForFrameClosed(true);
+ state = ComputePlayState_BackgroundedStreaming();
+ EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state);
+ EXPECT_TRUE(state.is_idle);
+ EXPECT_TRUE(state.is_suspended);
+ EXPECT_FALSE(state.is_memory_reporting_enabled);
+}
+
+TEST_F(WebMediaPlayerImplTest, ResumeEnded) {
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = TestVideoConfig::Normal();
+ metadata.has_audio = true;
+ metadata.audio_decoder_config = TestAudioConfig::Normal();
+
+ SetUpMediaSuspend(true);
+ InitializeWebMediaPlayerImpl();
+
+ EXPECT_CALL(delegate_, DidMediaMetadataChange(_, true, true, _)).Times(2);
+
+ OnMetadata(metadata);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ Play();
+ // Cause PlayerGone
+ Pause();
+ BackgroundPlayer();
+
+ testing::Mock::VerifyAndClearExpectations(&delegate_);
+
+ // DidMediaMetadataChange should be called again after player gone.
+ EXPECT_CALL(delegate_, DidMediaMetadataChange(_, true, true, _));
+
+ ForegroundPlayer();
+ Play();
+}
+
+TEST_F(WebMediaPlayerImplTest, AutoplayMuted) {
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = TestVideoConfig::Normal();
+ metadata.has_audio = true;
+ metadata.audio_decoder_config = TestAudioConfig::Normal();
+
+ EXPECT_CALL(client_, WasAlwaysMuted()).WillRepeatedly(Return(true));
+
+ InitializeWebMediaPlayerImpl();
+ SetPaused(false);
+
+ EXPECT_CALL(delegate_, DidMediaMetadataChange(_, false, true, _));
+ OnMetadata(metadata);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ testing::Mock::VerifyAndClearExpectations(&delegate_);
+
+ EXPECT_CALL(client_, WasAlwaysMuted()).WillRepeatedly(Return(false));
+ EXPECT_CALL(delegate_, DidMediaMetadataChange(_, true, true, _));
+ wmpi_->SetVolume(1.0);
+}
+
+TEST_F(WebMediaPlayerImplTest, MediaPositionState_Playing) {
+ InitializeWebMediaPlayerImpl();
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveFutureData);
+ wmpi_->SetRate(1.0);
+ Play();
+
+ EXPECT_CALL(client_, DidPlayerMediaPositionStateChange(
+ 1.0, kAudioOnlyTestFileDuration, base::TimeDelta(),
+ /*end_of_media=*/false));
+ wmpi_->OnTimeUpdate();
+}
+
+TEST_F(WebMediaPlayerImplTest, MediaPositionState_Paused) {
+ InitializeWebMediaPlayerImpl();
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveFutureData);
+ wmpi_->SetRate(1.0);
+
+ // The effective playback rate is 0.0 while paused.
+ EXPECT_CALL(client_, DidPlayerMediaPositionStateChange(
+ 0.0, kAudioOnlyTestFileDuration, base::TimeDelta(),
+ /*end_of_media=*/false));
+ wmpi_->OnTimeUpdate();
+}
+
+TEST_F(WebMediaPlayerImplTest, MediaPositionState_PositionChange) {
+ InitializeWebMediaPlayerImpl();
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveFutureData);
+ wmpi_->SetRate(0.5);
+ Play();
+
+ testing::Sequence sequence;
+ EXPECT_CALL(client_,
+ DidPlayerMediaPositionStateChange(
+ 0.0, kAudioOnlyTestFileDuration,
+ base::TimeDelta::FromSecondsD(0.1), /*end_of_media=*/false))
+ .InSequence(sequence);
+ wmpi_->Seek(0.1);
+ wmpi_->OnTimeUpdate();
+
+ // If we load enough data to resume playback the position should be updated.
+ EXPECT_CALL(client_,
+ DidPlayerMediaPositionStateChange(
+ 0.5, kAudioOnlyTestFileDuration,
+ base::TimeDelta::FromSecondsD(0.1), /*end_of_media=*/false))
+ .InSequence(sequence);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+ wmpi_->OnTimeUpdate();
+
+ // No media time progress -> no MediaPositionState change.
+ wmpi_->OnTimeUpdate();
+}
+
+TEST_F(WebMediaPlayerImplTest, MediaPositionState_EndOfMedia) {
+ InitializeWebMediaPlayerImpl();
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveFutureData);
+ wmpi_->SetRate(1.0);
+ Play();
+ SetReadyState(WebMediaPlayer::kReadyStateHaveFutureData);
+
+ testing::Sequence sequence;
+ EXPECT_CALL(client_, DidPlayerMediaPositionStateChange(
+ 1.0, kAudioOnlyTestFileDuration, base::TimeDelta(),
+ /*end_of_media=*/false))
+ .InSequence(sequence);
+ wmpi_->OnTimeUpdate();
+
+ // If we play through to the end of media the position should be updated.
+ EXPECT_CALL(client_, DidPlayerMediaPositionStateChange(
+ 1.0, kAudioOnlyTestFileDuration, base::TimeDelta(),
+ /*end_of_media=*/true))
+ .InSequence(sequence);
+ SetEnded(true);
+ wmpi_->OnTimeUpdate();
+}
+
+TEST_F(WebMediaPlayerImplTest, MediaPositionState_Underflow) {
+ InitializeWebMediaPlayerImpl();
+ LoadAndWaitForReadyState(kAudioOnlyTestFile,
+ WebMediaPlayer::kReadyStateHaveFutureData);
+ wmpi_->SetRate(1.0);
+ Play();
+
+ // Underflow will set the effective playback rate to 0.0.
+ EXPECT_CALL(client_, DidPlayerMediaPositionStateChange(
+ 0.0, kAudioOnlyTestFileDuration, base::TimeDelta(),
+ /*end_of_media=*/false));
+ SetReadyState(WebMediaPlayer::kReadyStateHaveCurrentData);
+ wmpi_->OnTimeUpdate();
+}
+
+// It's possible for current time to be infinite if the page seeks to
+// |media::kInfiniteDuration| (2**64 - 1) when duration is infinite.
+TEST_F(WebMediaPlayerImplTest, MediaPositionState_InfiniteCurrentTime) {
+ InitializeWebMediaPlayerImpl();
+ SetDuration(media::kInfiniteDuration);
+ wmpi_->OnTimeUpdate();
+
+ EXPECT_CALL(client_,
+ DidPlayerMediaPositionStateChange(0.0, media::kInfiniteDuration,
+ media::kInfiniteDuration,
+ /*end_of_media=*/false));
+ wmpi_->Seek(media::kInfiniteDuration.InSecondsF());
+ wmpi_->OnTimeUpdate();
+
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ EXPECT_CALL(client_, DidPlayerMediaPositionStateChange(_, _, _, _)).Times(0);
+ wmpi_->OnTimeUpdate();
+}
+
+TEST_F(WebMediaPlayerImplTest, NoStreams) {
+ InitializeWebMediaPlayerImpl();
+ media::PipelineMetadata metadata;
+
+ EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
+ EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()).Times(0);
+ EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()).Times(0);
+ EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)).Times(0);
+
+ // Since there is no audio nor video to play, OnError should occur with
+ // resulting network state error update, and transition to HAVE_METADATA
+ // should not occur.
+ EXPECT_CALL(client_, NetworkStateChanged()).Times(1);
+ EXPECT_CALL(client_, ReadyStateChanged()).Times(0);
+
+ // No assertions in the production code should fail.
+ OnMetadata(metadata);
+
+ EXPECT_EQ(wmpi_->GetNetworkState(), WebMediaPlayer::kNetworkStateFormatError);
+ EXPECT_EQ(wmpi_->GetReadyState(), WebMediaPlayer::kReadyStateHaveNothing);
+}
+
+TEST_F(WebMediaPlayerImplTest, Encrypted) {
+ InitializeWebMediaPlayerImpl();
+
+ // To avoid PreloadMetadataLazyLoad.
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(encrypted_client_,
+ Encrypted(media::EmeInitDataType::WEBM, NotNull(), Gt(0u)));
+ EXPECT_CALL(encrypted_client_, DidBlockPlaybackWaitingForKey());
+ EXPECT_CALL(encrypted_client_, DidResumePlaybackBlockedForKey())
+ .WillRepeatedly(RunClosure(run_loop.QuitClosure()));
+ Load(kEncryptedVideoOnlyTestFile);
+ run_loop.Run();
+ }
+
+ CreateCdm();
+
+ // The CDM doesn't support Decryptor nor CDM ID. Pipeline startup will fail.
+ EXPECT_CALL(mock_cdm_context_, GetDecryptor())
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(nullptr));
+
+ {
+ // Wait for kNetworkStateFormatError caused by Renderer initialization
+ // error.
+ base::RunLoop run_loop;
+ EXPECT_CALL(client_, NetworkStateChanged()).WillOnce(Invoke([&] {
+ if (wmpi_->GetNetworkState() == WebMediaPlayer::kNetworkStateFormatError)
+ run_loop.QuitClosure().Run();
+ }));
+ SetCdm();
+ run_loop.Run();
+ }
+}
+
+TEST_F(WebMediaPlayerImplTest, Waiting_NoDecryptionKey) {
+ InitializeWebMediaPlayerImpl();
+
+ // Use non-encrypted file here since we don't have a CDM. Otherwise pipeline
+ // initialization will stall waiting for a CDM to be set.
+ LoadAndWaitForCurrentData(kVideoOnlyTestFile);
+
+ EXPECT_CALL(encrypted_client_, DidBlockPlaybackWaitingForKey());
+ EXPECT_CALL(encrypted_client_, DidResumePlaybackBlockedForKey());
+
+ OnWaiting(media::WaitingReason::kNoDecryptionKey);
+}
+
+ACTION(ReportHaveEnough) {
+ arg0->OnBufferingStateChange(media::BUFFERING_HAVE_ENOUGH,
+ media::BUFFERING_CHANGE_REASON_UNKNOWN);
+}
+
+#if defined(OS_WIN)
+TEST_F(WebMediaPlayerImplTest, FallbackToMediaFoundationRenderer) {
+ InitializeWebMediaPlayerImpl();
+ // To avoid PreloadMetadataLazyLoad.
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+
+ // Use MockRendererFactory for kMediaFoundation where the created Renderer
+ // will take the CDM, complete Renderer initialization and report HAVE_ENOUGH
+ // so that WMPI can reach kReadyStateHaveCurrentData.
+ auto mock_renderer_factory = std::make_unique<media::MockRendererFactory>();
+ EXPECT_CALL(*mock_renderer_factory, CreateRenderer(_, _, _, _, _, _))
+ .WillOnce(testing::WithoutArgs(Invoke([]() {
+ auto mock_renderer = std::make_unique<NiceMock<media::MockRenderer>>();
+ EXPECT_CALL(*mock_renderer, OnSetCdm(_, _))
+ .WillOnce(RunOnceCallback<1>(true));
+ EXPECT_CALL(*mock_renderer, OnInitialize(_, _, _))
+ .WillOnce(DoAll(RunOnceCallback<2>(media::PIPELINE_OK),
+ WithArg<1>(ReportHaveEnough())));
+ return mock_renderer;
+ })));
+
+ renderer_factory_selector_->AddFactory(media::RendererType::kMediaFoundation,
+ std::move(mock_renderer_factory));
+
+ // Create and set CDM. The CDM doesn't support a Decryptor and requires Media
+ // Foundation Renderer.
+ EXPECT_CALL(mock_cdm_context_, GetDecryptor())
+ .WillRepeatedly(Return(nullptr));
+ EXPECT_CALL(mock_cdm_context_, RequiresMediaFoundationRenderer())
+ .WillRepeatedly(Return(true));
+
+ CreateCdm();
+ SetCdm();
+
+ // Load encrypted media and expect encrypted event.
+ EXPECT_CALL(encrypted_client_,
+ Encrypted(media::EmeInitDataType::WEBM, NotNull(), Gt(0u)));
+
+ base::RunLoop run_loop;
+ // MediaFoundationRenderer doesn't use AudioService.
+ EXPECT_CALL(client_, DidUseAudioServiceChange(/*uses_audio_service=*/false))
+ .WillOnce(RunClosure(run_loop.QuitClosure()));
+ Load(kEncryptedVideoOnlyTestFile);
+ run_loop.Run();
+}
+#endif // defined(OS_WIN)
+
+TEST_F(WebMediaPlayerImplTest, VideoConfigChange) {
+ InitializeWebMediaPlayerImpl();
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = TestVideoConfig::NormalCodecProfile(
+ media::kCodecVP9, media::VP9PROFILE_PROFILE0);
+ metadata.natural_size = gfx::Size(320, 240);
+
+ // Arrival of metadata should trigger creation of reporter with video config
+ // with profile matching test config.
+ OnMetadata(metadata);
+ VideoDecodeStatsReporter* last_reporter = GetVideoStatsReporter();
+ ASSERT_NE(nullptr, last_reporter);
+ ASSERT_EQ(media::VP9PROFILE_PROFILE0, GetVideoStatsReporterCodecProfile());
+
+ // Changing the codec profile should trigger recreation of the reporter.
+ auto new_profile_config = TestVideoConfig::NormalCodecProfile(
+ media::kCodecVP9, media::VP9PROFILE_PROFILE1);
+ OnVideoConfigChange(new_profile_config);
+ ASSERT_EQ(media::VP9PROFILE_PROFILE1, GetVideoStatsReporterCodecProfile());
+ ASSERT_NE(last_reporter, GetVideoStatsReporter());
+ last_reporter = GetVideoStatsReporter();
+
+ // Changing the codec (implies changing profile) should similarly trigger
+ // recreation of the reporter.
+ auto new_codec_config = TestVideoConfig::NormalCodecProfile(media::kCodecVP8);
+ OnVideoConfigChange(new_codec_config);
+ ASSERT_EQ(media::VP8PROFILE_MIN, GetVideoStatsReporterCodecProfile());
+ ASSERT_NE(last_reporter, GetVideoStatsReporter());
+ last_reporter = GetVideoStatsReporter();
+
+ // Changing other aspects of the config (like colorspace) should not trigger
+ // recreation of the reporter
+ media::VideoDecoderConfig new_color_config =
+ TestVideoConfig::NormalWithColorSpace(media::kCodecVP8,
+ media::VideoColorSpace::REC709());
+ ASSERT_EQ(media::VP8PROFILE_MIN, new_color_config.profile());
+ OnVideoConfigChange(new_color_config);
+ ASSERT_EQ(last_reporter, GetVideoStatsReporter());
+ ASSERT_EQ(media::VP8PROFILE_MIN, GetVideoStatsReporterCodecProfile());
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, NaturalSizeChange) {
+ InitializeWebMediaPlayerImpl();
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = TestVideoConfig::NormalCodecProfile(
+ media::kCodecVP8, media::VP8PROFILE_MIN);
+ metadata.natural_size = gfx::Size(320, 240);
+
+ OnMetadata(metadata);
+ ASSERT_EQ(gfx::Size(320, 240), wmpi_->NaturalSize());
+
+ // Arrival of metadata should trigger creation of reporter with original size.
+ VideoDecodeStatsReporter* orig_stats_reporter = GetVideoStatsReporter();
+ ASSERT_NE(nullptr, orig_stats_reporter);
+ ASSERT_TRUE(
+ orig_stats_reporter->MatchesBucketedNaturalSize(gfx::Size(320, 240)));
+
+ EXPECT_CALL(client_, SizeChanged());
+ OnVideoNaturalSizeChange(gfx::Size(1920, 1080));
+ ASSERT_EQ(gfx::Size(1920, 1080), wmpi_->NaturalSize());
+
+ // New natural size triggers new reporter to be created.
+ ASSERT_NE(orig_stats_reporter, GetVideoStatsReporter());
+ ASSERT_TRUE(GetVideoStatsReporter()->MatchesBucketedNaturalSize(
+ gfx::Size(1920, 1080)));
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, NaturalSizeChange_Rotated) {
+ InitializeWebMediaPlayerImpl();
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config =
+ TestVideoConfig::NormalRotated(media::VIDEO_ROTATION_90);
+ metadata.natural_size = gfx::Size(320, 240);
+
+ OnMetadata(metadata);
+ ASSERT_EQ(gfx::Size(320, 240), wmpi_->NaturalSize());
+
+ // Arrival of metadata should trigger creation of reporter with original size.
+ VideoDecodeStatsReporter* orig_stats_reporter = GetVideoStatsReporter();
+ ASSERT_NE(nullptr, orig_stats_reporter);
+ ASSERT_TRUE(
+ orig_stats_reporter->MatchesBucketedNaturalSize(gfx::Size(320, 240)));
+
+ EXPECT_CALL(client_, SizeChanged());
+ // For 90/270deg rotations, the natural size should be transposed.
+ OnVideoNaturalSizeChange(gfx::Size(1920, 1080));
+ ASSERT_EQ(gfx::Size(1080, 1920), wmpi_->NaturalSize());
+
+ // New natural size triggers new reporter to be created.
+ ASSERT_NE(orig_stats_reporter, GetVideoStatsReporter());
+ ASSERT_TRUE(GetVideoStatsReporter()->MatchesBucketedNaturalSize(
+ gfx::Size(1080, 1920)));
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, VideoLockedWhenPausedWhenHidden) {
+ InitializeWebMediaPlayerImpl();
+
+ // Setting metadata initializes |watch_time_reporter_| used in play().
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = TestVideoConfig::Normal();
+
+ OnMetadata(metadata);
+
+ EXPECT_FALSE(IsVideoLockedWhenPausedWhenHidden());
+
+ // Backgrounding the player sets the lock.
+ BackgroundPlayer();
+ EXPECT_TRUE(IsVideoLockedWhenPausedWhenHidden());
+
+ // Play without a user gesture doesn't unlock the player.
+ Play();
+ EXPECT_TRUE(IsVideoLockedWhenPausedWhenHidden());
+
+ // With a user gesture it does unlock the player.
+ GetWebLocalFrame()->NotifyUserActivation(
+ mojom::UserActivationNotificationType::kTest);
+ Play();
+ EXPECT_FALSE(IsVideoLockedWhenPausedWhenHidden());
+
+ // Pause without a user gesture doesn't lock the player.
+ GetWebLocalFrame()->ConsumeTransientUserActivation();
+ Pause();
+ EXPECT_FALSE(IsVideoLockedWhenPausedWhenHidden());
+
+ // With a user gesture, pause does lock the player.
+ GetWebLocalFrame()->NotifyUserActivation(
+ mojom::UserActivationNotificationType::kTest);
+ Pause();
+ EXPECT_TRUE(IsVideoLockedWhenPausedWhenHidden());
+
+ // Foregrounding the player unsets the lock.
+ ForegroundPlayer();
+ EXPECT_FALSE(IsVideoLockedWhenPausedWhenHidden());
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, BackgroundIdlePauseTimerDependsOnAudio) {
+ InitializeWebMediaPlayerImpl();
+ SetSuspendState(true);
+ SetPaused(false);
+
+ ASSERT_TRUE(IsSuspended());
+
+ // Video-only players are not paused when suspended.
+ SetMetadata(false, true);
+ ScheduleIdlePauseTimer();
+ EXPECT_FALSE(IsIdlePauseTimerRunning());
+
+ SetMetadata(true, true);
+ ScheduleIdlePauseTimer();
+ EXPECT_TRUE(IsIdlePauseTimerRunning());
+
+ EXPECT_CALL(client_, PausePlayback());
+ FireIdlePauseTimer();
+ base::RunLoop().RunUntilIdle();
+}
+
+// Verifies that an infinite duration doesn't muck up GetCurrentTimeInternal.
+TEST_F(WebMediaPlayerImplTest, InfiniteDuration) {
+ InitializeWebMediaPlayerImpl();
+ SetDuration(media::kInfiniteDuration);
+
+ // Send metadata so we have a watch time reporter created.
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = TestVideoConfig::Normal();
+ metadata.has_audio = true;
+ metadata.audio_decoder_config = TestAudioConfig::Normal();
+ metadata.natural_size = gfx::Size(400, 400);
+
+ OnMetadata(metadata);
+
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), wmpi_->Duration());
+ EXPECT_EQ(0, wmpi_->CurrentTime());
+ EXPECT_EQ(base::TimeDelta(), GetCurrentTimeInternal());
+
+ SetEnded(true);
+ EXPECT_EQ(0, wmpi_->CurrentTime());
+ EXPECT_EQ(base::TimeDelta(), GetCurrentTimeInternal());
+
+ // Pause should not pick up infinity for the current time.
+ wmpi_->Pause();
+ EXPECT_EQ(0, wmpi_->CurrentTime());
+ EXPECT_EQ(base::TimeDelta(), GetCurrentTimeInternal());
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, SetContentsLayerGetsWebLayerFromBridge) {
+ InitializeWebMediaPlayerImpl();
+
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config =
+ TestVideoConfig::NormalRotated(media::VIDEO_ROTATION_90);
+ metadata.natural_size = gfx::Size(320, 240);
+
+ EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
+ EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
+ EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
+ .WillOnce(ReturnRef(surface_id_));
+ EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
+ EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
+
+ // We only call the callback to create the bridge in OnMetadata, so we need
+ // to call it.
+ OnMetadata(metadata);
+
+ scoped_refptr<cc::Layer> layer = cc::Layer::Create();
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, GetCcLayer())
+ .WillRepeatedly(Return(layer.get()));
+ EXPECT_CALL(client_, SetCcLayer(Eq(layer.get())));
+ EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
+ wmpi_->RegisterContentsLayer(layer.get());
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, PlaybackRateChangeMediaLogs) {
+ InitializeWebMediaPlayerImpl();
+
+ {
+ InSequence s;
+
+ // Expect precisely one rate change log from this test case.
+ EXPECT_MEDIA_LOG_ON(*media_log_, PlaybackRateChanged("0", "0.8"));
+ EXPECT_MEDIA_LOG_ON(*media_log_, WmpiDestroyed());
+
+ wmpi_->SetRate(0.0); // No change from initial rate, so no log.
+ wmpi_->SetRate(0.8); // This should log change from 0 -> 0.8
+ wmpi_->SetRate(0.8); // No change from previous rate, so no log.
+ }
+}
+
+// Tests that updating the surface id calls OnPictureInPictureStateChange.
+TEST_F(WebMediaPlayerImplTest, PictureInPictureStateChange) {
+ InitializeWebMediaPlayerImpl();
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
+ EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
+ .WillRepeatedly(ReturnRef(surface_id_));
+ EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
+ EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
+
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ OnMetadata(metadata);
+
+ EXPECT_CALL(client_, GetDisplayType())
+ .WillRepeatedly(Return(DisplayType::kPictureInPicture));
+ EXPECT_CALL(client_, OnPictureInPictureStateChange()).Times(1);
+
+ wmpi_->OnSurfaceIdUpdated(surface_id_);
+
+ EXPECT_CALL(*surface_layer_bridge_ptr_, ClearObserver());
+}
+
+TEST_F(WebMediaPlayerImplTest, OnProgressClearsStale) {
+ InitializeWebMediaPlayerImpl();
+ SetMetadata(true, true);
+
+ for (auto rs = WebMediaPlayer::kReadyStateHaveNothing;
+ rs <= WebMediaPlayer::kReadyStateHaveEnoughData;
+ rs = static_cast<WebMediaPlayer::ReadyState>(static_cast<int>(rs) + 1)) {
+ SetReadyState(rs);
+ delegate_.SetStaleForTesting(true);
+ OnProgress();
+ EXPECT_EQ(delegate_.IsStale(delegate_.player_id()),
+ rs >= WebMediaPlayer::kReadyStateHaveFutureData);
+ }
+}
+
+// Disabled due to flakiness: crbug.com/1223150
+#if defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER)
+#define MAYBE_MemDumpProvidersRegistration DISABLED_MemDumpProvidersRegistration
+#else
+#define MAYBE_MemDumpProvidersRegistration MemDumpProvidersRegistration
+#endif
+TEST_F(WebMediaPlayerImplTest, MAYBE_MemDumpProvidersRegistration) {
+ auto* dump_manager = base::trace_event::MemoryDumpManager::GetInstance();
+ InitializeWebMediaPlayerImpl();
+
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+ auto* main_dumper = GetMainThreadMemDumper();
+ EXPECT_TRUE(dump_manager->IsDumpProviderRegisteredForTesting(main_dumper));
+ LoadAndWaitForCurrentData(kVideoAudioTestFile);
+
+ auto* media_dumper = GetMediaThreadMemDumper();
+ EXPECT_TRUE(dump_manager->IsDumpProviderRegisteredForTesting(media_dumper));
+ CycleThreads();
+
+ wmpi_.reset();
+ CycleThreads();
+
+ EXPECT_FALSE(dump_manager->IsDumpProviderRegisteredForTesting(main_dumper));
+ EXPECT_FALSE(dump_manager->IsDumpProviderRegisteredForTesting(media_dumper));
+}
+
+TEST_F(WebMediaPlayerImplTest, MemDumpReporting) {
+ InitializeWebMediaPlayerImpl();
+
+ wmpi_->SetPreload(WebMediaPlayer::kPreloadAuto);
+ LoadAndWaitForCurrentData(kVideoAudioTestFile);
+
+ CycleThreads();
+
+ base::trace_event::MemoryDumpRequestArgs args = {
+ 1 /* dump_guid*/, base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED,
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+
+ int32_t id = GetMediaLogId();
+ int dump_count = 0;
+
+ auto on_memory_dump_done = base::BindLambdaForTesting(
+ [&](bool success, uint64_t dump_guid,
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> pmd) {
+ ASSERT_TRUE(success);
+ const auto& dumps = pmd->allocator_dumps();
+
+ std::vector<const char*> allocations = {"audio", "video", "data_source",
+ "demuxer"};
+
+ for (const char* name : allocations) {
+ auto it = dumps.find(base::StringPrintf(
+ "media/webmediaplayer/%s/player_0x%x", name, id));
+ ASSERT_NE(dumps.end(), it) << name;
+ ASSERT_GT(it->second->GetSizeInternal(), 0u) << name;
+ }
+
+ auto it = dumps.find(
+ base::StringPrintf("media/webmediaplayer/player_0x%x", id));
+ ASSERT_NE(dumps.end(), it);
+ auto* player_dump = it->second.get();
+ const auto& entries = player_dump->entries();
+
+ auto instance_counter_it =
+ std::find_if(entries.begin(), entries.end(), [](const auto& e) {
+ auto* name =
+ base::trace_event::MemoryAllocatorDump::kNameObjectCount;
+ return e.name == name && e.value_uint64 == 1;
+ });
+ ASSERT_NE(entries.end(), instance_counter_it);
+
+ if (args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {
+ auto player_state_it =
+ std::find_if(entries.begin(), entries.end(), [](const auto& e) {
+ return e.name == "player_state" && !e.value_string.empty();
+ });
+ ASSERT_NE(entries.end(), player_state_it);
+ }
+ dump_count++;
+ });
+
+ auto* dump_manager = base::trace_event::MemoryDumpManager::GetInstance();
+
+ dump_manager->CreateProcessDump(args, on_memory_dump_done);
+
+ args.level_of_detail = base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND;
+ args.dump_guid++;
+ dump_manager->CreateProcessDump(args, on_memory_dump_done);
+
+ args.level_of_detail = base::trace_event::MemoryDumpLevelOfDetail::LIGHT;
+ args.dump_guid++;
+ dump_manager->CreateProcessDump(args, on_memory_dump_done);
+
+ CycleThreads();
+ EXPECT_EQ(dump_count, 3);
+}
+
+// Verify that a demuxer override is used when specified.
+// TODO(https://crbug.com/1084476): This test is flaky.
+TEST_F(WebMediaPlayerImplTest, DISABLED_DemuxerOverride) {
+ std::unique_ptr<media::MockDemuxer> demuxer =
+ std::make_unique<NiceMock<media::MockDemuxer>>();
+ StrictMock<media::MockDemuxerStream> stream(media::DemuxerStream::AUDIO);
+ stream.set_audio_decoder_config(TestAudioConfig::Normal());
+ std::vector<media::DemuxerStream*> streams;
+ streams.push_back(&stream);
+
+ EXPECT_CALL(stream, SupportsConfigChanges()).WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*demuxer.get(), OnInitialize(_, _))
+ .WillOnce(RunOnceCallback<1>(media::PIPELINE_OK));
+ EXPECT_CALL(*demuxer.get(), GetAllStreams()).WillRepeatedly(Return(streams));
+ // Called when WebMediaPlayerImpl is destroyed.
+ EXPECT_CALL(*demuxer.get(), Stop());
+
+ InitializeWebMediaPlayerImplInternal(std::move(demuxer));
+
+ EXPECT_FALSE(IsSuspended());
+ wmpi_->Load(WebMediaPlayer::kLoadTypeURL,
+ WebMediaPlayerSource(WebURL(KURL("data://test"))),
+ WebMediaPlayer::kCorsModeUnspecified,
+ /*is_cache_disabled=*/false);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(IsSuspended());
+}
+
+class WebMediaPlayerImplBackgroundBehaviorTest
+ : public WebMediaPlayerImplTest,
+ public ::testing::WithParamInterface<
+ std::tuple<bool, int, int, bool, bool, bool, bool, bool, bool>> {
+ public:
+ // Indices of the tuple parameters.
+ static const int kIsMediaSuspendEnabled = 0;
+ static const int kDurationSec = 1;
+ static const int kAverageKeyframeDistanceSec = 2;
+ static const int kIsResumeBackgroundVideoEnabled = 3;
+ static const int kIsMediaSource = 4;
+ static const int kIsBackgroundPauseEnabled = 5;
+ static const int kIsPictureInPictureEnabled = 6;
+ static const int kIsBackgroundVideoPlaybackEnabled = 7;
+ static const int kIsVideoBeingCaptured = 8;
+
+ void SetUp() override {
+ WebMediaPlayerImplTest::SetUp();
+ SetUpMediaSuspend(IsMediaSuspendOn());
+ SetUpBackgroundVideoPlayback(IsBackgroundVideoPlaybackEnabled());
+
+ std::string enabled_features;
+ std::string disabled_features;
+
+ if (IsBackgroundPauseOn()) {
+ if (!enabled_features.empty())
+ enabled_features += ",";
+ enabled_features += media::kBackgroundVideoPauseOptimization.name;
+ } else {
+ if (!disabled_features.empty())
+ disabled_features += ",";
+ disabled_features += media::kBackgroundVideoPauseOptimization.name;
+ }
+
+ if (IsResumeBackgroundVideoEnabled()) {
+ if (!enabled_features.empty())
+ enabled_features += ",";
+ enabled_features += media::kResumeBackgroundVideo.name;
+ } else {
+ if (!disabled_features.empty())
+ disabled_features += ",";
+ disabled_features += media::kResumeBackgroundVideo.name;
+ }
+
+ feature_list_.InitFromCommandLine(enabled_features, disabled_features);
+
+ InitializeWebMediaPlayerImpl();
+ bool is_media_source = std::get<kIsMediaSource>(GetParam());
+ SetLoadType(is_media_source ? WebMediaPlayer::kLoadTypeMediaSource
+ : WebMediaPlayer::kLoadTypeURL);
+ SetVideoKeyframeDistanceAverage(
+ base::TimeDelta::FromSeconds(GetAverageKeyframeDistanceSec()));
+ SetDuration(base::TimeDelta::FromSeconds(GetDurationSec()));
+
+ if (IsPictureInPictureOn()) {
+ EXPECT_CALL(client_, GetDisplayType())
+ .WillRepeatedly(Return(DisplayType::kPictureInPicture));
+
+ wmpi_->OnSurfaceIdUpdated(surface_id_);
+ }
+
+ if (IsVideoBeingCaptured())
+ wmpi_->GetCurrentFrame();
+
+ BackgroundPlayer();
+ }
+
+ void SetVideoKeyframeDistanceAverage(base::TimeDelta value) {
+ media::PipelineStatistics statistics;
+ statistics.video_keyframe_distance_average = value;
+ wmpi_->SetPipelineStatisticsForTest(statistics);
+ }
+
+ bool IsMediaSuspendOn() {
+ return std::get<kIsMediaSuspendEnabled>(GetParam());
+ }
+
+ bool IsResumeBackgroundVideoEnabled() {
+ return std::get<kIsResumeBackgroundVideoEnabled>(GetParam());
+ }
+
+ bool IsBackgroundPauseOn() {
+ return std::get<kIsBackgroundPauseEnabled>(GetParam());
+ }
+
+ bool IsPictureInPictureOn() {
+ return std::get<kIsPictureInPictureEnabled>(GetParam());
+ }
+
+ bool IsBackgroundVideoPlaybackEnabled() {
+ return std::get<kIsBackgroundVideoPlaybackEnabled>(GetParam());
+ }
+
+ bool IsVideoBeingCaptured() {
+ return std::get<kIsVideoBeingCaptured>(GetParam());
+ }
+
+ int GetDurationSec() const { return std::get<kDurationSec>(GetParam()); }
+
+ int GetAverageKeyframeDistanceSec() const {
+ return std::get<kAverageKeyframeDistanceSec>(GetParam());
+ }
+
+ int GetMaxKeyframeDistanceSec() const {
+ return WebMediaPlayerImpl::kMaxKeyframeDistanceToDisableBackgroundVideoMs /
+ base::Time::kMillisecondsPerSecond;
+ }
+
+ bool IsAndroid() {
+#if defined(OS_ANDROID)
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ bool ShouldDisableVideoWhenHidden() const {
+ return wmpi_->ShouldDisableVideoWhenHidden();
+ }
+
+ bool ShouldPausePlaybackWhenHidden() const {
+ return wmpi_->ShouldPausePlaybackWhenHidden();
+ }
+
+ bool IsBackgroundOptimizationCandidate() const {
+ return wmpi_->IsBackgroundOptimizationCandidate();
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_P(WebMediaPlayerImplBackgroundBehaviorTest, AudioOnly) {
+ // Never optimize or pause an audio-only player.
+ SetMetadata(true, false);
+ EXPECT_FALSE(IsBackgroundOptimizationCandidate());
+ EXPECT_FALSE(ShouldPausePlaybackWhenHidden());
+ EXPECT_FALSE(ShouldDisableVideoWhenHidden());
+}
+
+TEST_P(WebMediaPlayerImplBackgroundBehaviorTest, VideoOnly) {
+ // Video only.
+ SetMetadata(false, true);
+
+ // Never disable video track for a video only stream.
+ EXPECT_FALSE(ShouldDisableVideoWhenHidden());
+
+ // There's no optimization criteria for video only in Picture-in-Picture.
+ bool matches_requirements =
+ !IsPictureInPictureOn() && !IsVideoBeingCaptured();
+ EXPECT_EQ(matches_requirements, IsBackgroundOptimizationCandidate());
+
+ // Video is always paused when suspension is on and only if matches the
+ // optimization criteria if the optimization is on.
+ bool should_pause = !IsBackgroundVideoPlaybackEnabled() ||
+ IsMediaSuspendOn() ||
+ (IsBackgroundPauseOn() && matches_requirements);
+ EXPECT_EQ(should_pause, ShouldPausePlaybackWhenHidden());
+}
+
+TEST_P(WebMediaPlayerImplBackgroundBehaviorTest, AudioVideo) {
+ SetMetadata(true, true);
+
+ // Optimization requirements are the same for all platforms.
+ bool matches_requirements =
+ !IsPictureInPictureOn() && !IsVideoBeingCaptured() &&
+ ((GetDurationSec() < GetMaxKeyframeDistanceSec()) ||
+ (GetAverageKeyframeDistanceSec() < GetMaxKeyframeDistanceSec()));
+
+ EXPECT_EQ(matches_requirements, IsBackgroundOptimizationCandidate());
+ EXPECT_EQ(matches_requirements, ShouldDisableVideoWhenHidden());
+
+ // Only pause audible videos if both media suspend and resume background
+ // videos is on and background video playback is disabled. Background video
+ // playback is enabled by default. Both media suspend and resume background
+ // videos are on by default on Android and off on desktop.
+ EXPECT_EQ(!IsBackgroundVideoPlaybackEnabled() ||
+ (IsMediaSuspendOn() && IsResumeBackgroundVideoEnabled()),
+ ShouldPausePlaybackWhenHidden());
+
+ if (!matches_requirements || !ShouldDisableVideoWhenHidden() ||
+ IsMediaSuspendOn()) {
+ return;
+ }
+
+ // These tests start in background mode prior to having metadata, so put the
+ // test back into a normal state.
+ EXPECT_TRUE(IsDisableVideoTrackPending());
+
+ ForegroundPlayer();
+ EXPECT_FALSE(IsVideoTrackDisabled());
+ EXPECT_FALSE(IsDisableVideoTrackPending());
+
+ // Should start background disable timer, but not disable immediately.
+ BackgroundPlayer();
+ if (ShouldPausePlaybackWhenHidden()) {
+ EXPECT_FALSE(IsVideoTrackDisabled());
+ EXPECT_FALSE(IsDisableVideoTrackPending());
+ } else {
+ // Testing IsVideoTrackDisabled() leads to flakyness even though there
+ // should be a 10 minutes delay until it happens. Given that it doesn't
+ // provides much of a benefit at the moment, this is being ignored.
+ EXPECT_TRUE(IsDisableVideoTrackPending());
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ BackgroundBehaviorTestInstances,
+ WebMediaPlayerImplBackgroundBehaviorTest,
+ ::testing::Combine(
+ ::testing::Bool(),
+ ::testing::Values(
+ WebMediaPlayerImpl::kMaxKeyframeDistanceToDisableBackgroundVideoMs /
+ base::Time::kMillisecondsPerSecond -
+ 1,
+ 300),
+ ::testing::Values(
+ WebMediaPlayerImpl::kMaxKeyframeDistanceToDisableBackgroundVideoMs /
+ base::Time::kMillisecondsPerSecond -
+ 1,
+ 100),
+ ::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Bool()));
+
+} // 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 83c3510146a..18bfde4bb2f 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_node.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_node.cc
@@ -49,10 +49,10 @@
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.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/layout/layout_embedded_content.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_box.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/bindings/to_v8.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 bd6d49a8124..bba1deca18b 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
@@ -204,12 +204,12 @@ class PagePopupChromeClient final : public EmptyChromeClient {
timeline->GetAnimationTimeline());
}
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
// LocalFrame is ignored since there is only 1 frame in a popup.
return popup_->GetScreenInfo();
}
- const ScreenInfos& GetScreenInfos(LocalFrame&) const override {
+ const display::ScreenInfos& GetScreenInfos(LocalFrame&) const override {
// LocalFrame is ignored since there is only 1 frame in a popup.
return popup_->GetScreenInfos();
}
@@ -252,6 +252,13 @@ class PagePopupChromeClient final : public EmptyChromeClient {
popup_->widget_base_->UpdateTooltipUnderCursor(tooltip_text, dir);
}
+ void UpdateTooltipFromKeyboard(LocalFrame&,
+ const String& tooltip_text,
+ TextDirection dir,
+ const gfx::Rect& bounds) override {
+ popup_->widget_base_->UpdateTooltipFromKeyboard(tooltip_text, dir, bounds);
+ }
+
void InjectGestureScrollEvent(LocalFrame& local_frame,
WebGestureDevice device,
const gfx::Vector2dF& delta,
@@ -411,10 +418,8 @@ void WebPagePopupImpl::Initialize(WebViewImpl* opener_web_view,
DCHECK(frame->DomWindow());
DCHECK_EQ(popup_client_->OwnerElement().GetDocument().ExistingAXObjectCache(),
frame->GetDocument()->ExistingAXObjectCache());
- if (AXObjectCache* cache = frame->GetDocument()->ExistingAXObjectCache()) {
- cache->InitializePopup(frame->GetDocument());
+ if (AXObjectCache* cache = frame->GetDocument()->ExistingAXObjectCache())
cache->ChildrenChanged(&popup_client_->OwnerElement());
- }
page_->AnimationHostInitialized(*widget_base_->AnimationHost(), nullptr);
@@ -444,7 +449,7 @@ void WebPagePopupImpl::DidSetBounds() {
void WebPagePopupImpl::InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const cc::LayerTreeSettings* settings) {
// Careful Initialize() is called after InitializeCompositing, so don't do
// much work here.
@@ -515,19 +520,19 @@ void WebPagePopupImpl::ApplyVisualProperties(
widget_base_->UpdateVisualProperties(visual_properties);
}
-const ScreenInfo& WebPagePopupImpl::GetScreenInfo() {
+const display::ScreenInfo& WebPagePopupImpl::GetScreenInfo() {
return widget_base_->GetScreenInfo();
}
-const ScreenInfos& WebPagePopupImpl::GetScreenInfos() {
+const display::ScreenInfos& WebPagePopupImpl::GetScreenInfos() {
return widget_base_->screen_infos();
}
-const ScreenInfo& WebPagePopupImpl::GetOriginalScreenInfo() {
+const display::ScreenInfo& WebPagePopupImpl::GetOriginalScreenInfo() {
return widget_base_->GetScreenInfo();
}
-const ScreenInfos& WebPagePopupImpl::GetOriginalScreenInfos() {
+const display::ScreenInfos& WebPagePopupImpl::GetOriginalScreenInfos() {
return widget_base_->screen_infos();
}
@@ -706,9 +711,8 @@ void WebPagePopupImpl::BeginMainFrame(base::TimeTicks last_frame_time) {
PageWidgetDelegate::Animate(*page_, base::TimeTicks::Now());
}
-bool WebPagePopupImpl::WillHandleGestureEvent(const WebGestureEvent& event) {
- return false;
-}
+void WebPagePopupImpl::WillHandleGestureEvent(const WebGestureEvent& event,
+ bool* suppress) {}
void WebPagePopupImpl::WillHandleMouseEvent(const WebMouseEvent& event) {}
@@ -971,9 +975,6 @@ void WebPagePopupImpl::ClosePopup() {
closing_ = true;
- if (AXObjectCache* cache = MainFrame().GetDocument()->ExistingAXObjectCache())
- cache->DisposePopup(MainFrame().GetDocument());
-
{
// This function can be called in EventDispatchForbiddenScope for the main
// document, and the following operations dispatch some events. It's safe
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 4e25100f681..5958171205d 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
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
-#include "base/macros.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "third_party/blink/public/mojom/input/pointer_lock_context.mojom-blink-forward.h"
@@ -71,6 +70,8 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
USING_FAST_MALLOC(WebPagePopupImpl);
public:
+ WebPagePopupImpl(const WebPagePopupImpl&) = delete;
+ WebPagePopupImpl& operator=(const WebPagePopupImpl&) = delete;
~WebPagePopupImpl() override;
void Initialize(WebViewImpl*, PagePopupClient*);
@@ -124,7 +125,8 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
void BeginMainFrame(base::TimeTicks last_frame_time) override;
void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
WebInputEventResult DispatchBufferedTouchEvents() override;
- bool WillHandleGestureEvent(const WebGestureEvent& event) override;
+ void WillHandleGestureEvent(const WebGestureEvent& event,
+ bool* suppress) override;
void WillHandleMouseEvent(const WebMouseEvent& event) override;
void ObserveGestureEventAndResult(
const WebGestureEvent& gesture_event,
@@ -160,7 +162,7 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
WebHitTestResult HitTestResultAt(const gfx::PointF&) override { return {}; }
void InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const cc::LayerTreeSettings* settings) override;
scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
override;
@@ -176,10 +178,10 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
void CancelCompositionForPepper() override;
void ApplyVisualProperties(
const VisualProperties& visual_properties) override;
- const ScreenInfo& GetScreenInfo() override;
- const ScreenInfos& GetScreenInfos() override;
- const ScreenInfo& GetOriginalScreenInfo() override;
- const ScreenInfos& GetOriginalScreenInfos() override;
+ const display::ScreenInfo& GetScreenInfo() override;
+ const display::ScreenInfos& GetScreenInfos() override;
+ const display::ScreenInfo& GetOriginalScreenInfo() override;
+ const display::ScreenInfos& GetOriginalScreenInfos() override;
gfx::Rect WindowRect() override;
gfx::Rect ViewRect() override;
void SetScreenRects(const gfx::Rect& widget_screen_rect,
@@ -278,8 +280,6 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
friend class WebPagePopup;
friend class PagePopupChromeClient;
-
- DISALLOW_COPY_AND_ASSIGN(WebPagePopupImpl);
};
// WebPagePopupImpl is the only implementation of WebPagePopup and PagePopup, so
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 99a7e8f403b..8f02c971bc9 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_performance.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_performance.cc
@@ -75,13 +75,13 @@ WebPerformance::BackForwardCacheRestore() const {
private_->timing()->BackForwardCacheRestore();
WebVector<BackForwardCacheRestoreTiming> timings(restore_timings.size());
- for (size_t i = 0; i < restore_timings.size(); i++) {
+ for (wtf_size_t i = 0; i < restore_timings.size(); i++) {
timings[i].navigation_start =
MillisecondsToSeconds(restore_timings[i].navigation_start);
timings[i].first_paint =
MillisecondsToSeconds(restore_timings[i].first_paint);
- for (size_t j = 0; j < restore_timings[i].request_animation_frames.size();
- j++) {
+ for (wtf_size_t j = 0;
+ j < restore_timings[i].request_animation_frames.size(); j++) {
timings[i].request_animation_frames[j] =
MillisecondsToSeconds(restore_timings[i].request_animation_frames[j]);
}
@@ -308,6 +308,11 @@ absl::optional<base::TimeTicks> WebPerformance::LastPortalActivatedPaint()
return private_->timing()->LastPortalActivatedPaint();
}
+absl::optional<base::TimeDelta> WebPerformance::PrerenderActivationStart()
+ const {
+ return private_->timing()->PrerenderActivationStart();
+}
+
absl::optional<base::TimeTicks> WebPerformance::UnloadStart() const {
return private_->timing()->UnloadStart();
}
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 881210a2679..b21bc31aa25 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
@@ -176,10 +176,10 @@ void WebPluginContainerImpl::Paint(GraphicsContext& context,
IntRect visual_rect = FrameRect();
visual_rect.Move(paint_offset);
- if (WantsWheelEvents()) {
- context.GetPaintController().RecordScrollHitTestData(
- *GetLayoutEmbeddedContent(), DisplayItem::kPluginScrollHitTest, nullptr,
- visual_rect);
+ if (WantsWheelEvents() &&
+ base::FeatureList::IsEnabled(::features::kWheelEventRegions)) {
+ context.GetPaintController().RecordHitTestData(
+ *GetLayoutEmbeddedContent(), visual_rect, TouchAction::kAuto, true);
}
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && layer_) {
@@ -809,17 +809,16 @@ void WebPluginContainerImpl::Trace(Visitor* visitor) const {
}
void WebPluginContainerImpl::HandleMouseEvent(MouseEvent& event) {
- // We cache the parent LocalFrameView here as the plugin widget could be
- // deleted in the call to HandleEvent. See http://b/issue?id=1362948
- LocalFrameView* parent = ParentFrameView();
-
// TODO(dtapuska): Move WebMouseEventBuilder into the anonymous namespace
// in this class.
- WebMouseEventBuilder transformed_event(parent, element_->GetLayoutObject(),
- event);
+ WebMouseEventBuilder transformed_event(element_->GetLayoutObject(), event);
if (transformed_event.GetType() == WebInputEvent::Type::kUndefined)
return;
+ // We cache the parent LocalFrameView here as the plugin widget could be
+ // deleted in the call to HandleEvent. See http://b/issue?id=1362948
+ LocalFrameView* parent = ParentFrameView();
+
if (event.type() == event_type_names::kMousedown)
FocusPlugin();
@@ -1047,8 +1046,7 @@ void WebPluginContainerImpl::HandleGestureEvent(GestureEvent& event) {
}
void WebPluginContainerImpl::SynthesizeMouseEventIfPossible(TouchEvent& event) {
- WebMouseEventBuilder web_event(ParentFrameView(), element_->GetLayoutObject(),
- event);
+ WebMouseEventBuilder web_event(element_->GetLayoutObject(), event);
if (web_event.GetType() == WebInputEvent::Type::kUndefined)
return;
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 8ee95622039..f6782f50e4c 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
@@ -31,6 +31,7 @@
#include "third_party/blink/public/web/web_security_policy.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -144,4 +145,17 @@ void WebSecurityPolicy::RegisterURLSchemeAsError(const WebString& scheme) {
SchemeRegistry::RegisterURLSchemeAsError(scheme);
}
+void WebSecurityPolicy::RegisterURLSchemeAsExtension(const WebString& scheme) {
+ CommonSchemeRegistry::RegisterURLSchemeAsExtension(scheme.Ascii());
+}
+
+void WebSecurityPolicy::RegisterURLSchemeAsWebUI(const WebString& scheme) {
+ SchemeRegistry::RegisterURLSchemeAsWebUI(scheme);
+}
+
+void WebSecurityPolicy::RegisterURLSchemeAsCodeCacheWithHashing(
+ const WebString& scheme) {
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(scheme);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_select_element.cc b/chromium/third_party/blink/renderer/core/exported/web_select_element.cc
index 36ef39dc614..59e657a0f53 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_select_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_select_element.cc
@@ -41,7 +41,7 @@ WebVector<WebElement> WebSelectElement::GetListItems() const {
const HeapVector<Member<HTMLElement>>& source_items =
ConstUnwrap<HTMLSelectElement>()->GetListItems();
WebVector<WebElement> items(source_items.size());
- for (size_t i = 0; i < source_items.size(); ++i)
+ for (wtf_size_t i = 0; i < source_items.size(); ++i)
items[i] = WebElement(source_items[i].Get());
return items;
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 b644fb71443..8580bfa33fd 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
@@ -537,12 +537,6 @@ void WebSettingsImpl::SetStrictlyBlockBlockableMixedContent(bool enabled) {
settings_->SetStrictlyBlockBlockableMixedContent(enabled);
}
-void WebSettingsImpl::SetPassiveEventListenerDefault(
- PassiveEventListenerDefault default_value) {
- settings_->SetPassiveListenerDefault(
- static_cast<PassiveListenerDefault>(default_value));
-}
-
void WebSettingsImpl::SetPasswordEchoEnabled(bool flag) {
settings_->SetPasswordEchoEnabled(flag);
}
@@ -815,4 +809,9 @@ void WebSettingsImpl::SetWebXRImmersiveArAllowed(
settings_->SetWebXRImmersiveArAllowed(webxr_immersive_ar_allowed);
}
+void WebSettingsImpl::SetLitePageSubresourceRedirectOrigin(
+ const WebString& origin) {
+ settings_->SetLitePageSubresourceRedirectOrigin(origin);
+}
+
} // 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 1c5a728a6d4..f4468e25997 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
@@ -123,7 +123,6 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
void SetMinimumLogicalFontSize(int) override;
void SetHideScrollbars(bool) override;
void SetOfflineWebApplicationCacheEnabled(bool) override;
- void SetPassiveEventListenerDefault(PassiveEventListenerDefault) override;
void SetPasswordEchoDurationInSeconds(double) override;
void SetPasswordEchoEnabled(bool) override;
void SetPictographFontFamily(const WebString&,
@@ -233,6 +232,7 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
void SetSelectionClipboardBufferAvailable(bool) override;
void SetAccessibilityIncludeSvgGElement(bool) override;
void SetWebXRImmersiveArAllowed(bool webxr_immersive_ar_allowed) override;
+ void SetLitePageSubresourceRedirectOrigin(const WebString&) override;
bool RenderVSyncNotificationEnabled() const {
return render_v_sync_notification_enabled_;
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 0fce76809ef..6d545313abf 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
@@ -37,6 +37,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
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 efb33160ba4..7995eb16a7c 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
@@ -170,6 +170,7 @@
#include "third_party/blink/renderer/platform/theme/web_theme_engine_helper.h"
#include "third_party/blink/renderer/platform/weborigin/known_ports.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/icu/source/common/unicode/uscript.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/skia_util.h"
@@ -346,18 +347,6 @@ void ApplyCommandLineToSettings(WebSettings* settings) {
selection_strategy = WebSettings::SelectionStrategyType::kCharacter;
settings->SetSelectionStrategy(selection_strategy);
- WebString passive_listeners_default = WebString::FromUTF8(
- command_line.GetSwitchValueASCII(switches::kPassiveListenersDefault));
- if (!passive_listeners_default.IsEmpty()) {
- WebSettings::PassiveEventListenerDefault passive_default =
- WebSettings::PassiveEventListenerDefault::kFalse;
- if (passive_listeners_default == "true")
- passive_default = WebSettings::PassiveEventListenerDefault::kTrue;
- else if (passive_listeners_default == "forcealltrue")
- passive_default = WebSettings::PassiveEventListenerDefault::kForceAllTrue;
- settings->SetPassiveEventListenerDefault(passive_default);
- }
-
WebString network_quiet_timeout = WebString::FromUTF8(
command_line.GetSwitchValueASCII(switches::kNetworkQuietTimeout));
if (!network_quiet_timeout.IsEmpty()) {
@@ -457,6 +446,7 @@ SkFontHinting RendererPreferencesToSkiaHinting(
WebView* WebView::Create(
WebViewClient* client,
bool is_hidden,
+ bool is_prerendering,
bool is_inside_portal,
bool compositing_enabled,
bool widgets_never_composited,
@@ -464,36 +454,45 @@ WebView* WebView::Create(
CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase>
page_handle,
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const SessionStorageNamespaceId& session_storage_namespace_id) {
+ const SessionStorageNamespaceId& session_storage_namespace_id,
+ absl::optional<SkColor> page_base_background_color) {
return WebViewImpl::Create(
client,
is_hidden ? mojom::blink::PageVisibilityState::kHidden
: mojom::blink::PageVisibilityState::kVisible,
- is_inside_portal, compositing_enabled, widgets_never_composited,
- static_cast<WebViewImpl*>(opener), std::move(page_handle),
- agent_group_scheduler, session_storage_namespace_id);
+ is_prerendering, is_inside_portal, compositing_enabled,
+ widgets_never_composited, To<WebViewImpl>(opener), std::move(page_handle),
+ agent_group_scheduler, session_storage_namespace_id,
+ std::move(page_base_background_color));
}
WebViewImpl* WebViewImpl::Create(
WebViewClient* client,
mojom::blink::PageVisibilityState visibility,
+ bool is_prerendering,
bool is_inside_portal,
bool compositing_enabled,
bool widgets_never_composited,
WebViewImpl* opener,
mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const SessionStorageNamespaceId& session_storage_namespace_id) {
+ const SessionStorageNamespaceId& session_storage_namespace_id,
+ absl::optional<SkColor> page_base_background_color) {
// Take a self-reference for WebViewImpl that is released by calling Close(),
// then return a raw pointer to the caller.
- auto web_view = base::AdoptRef(
- new WebViewImpl(client, visibility, is_inside_portal, compositing_enabled,
- widgets_never_composited, opener, std::move(page_handle),
- agent_group_scheduler, session_storage_namespace_id));
+ auto web_view = base::AdoptRef(new WebViewImpl(
+ client, visibility, is_prerendering, is_inside_portal,
+ compositing_enabled, widgets_never_composited, opener,
+ std::move(page_handle), agent_group_scheduler,
+ session_storage_namespace_id, std::move(page_base_background_color)));
web_view->AddRef();
return web_view.get();
}
+size_t WebView::GetWebViewCount() {
+ return WebViewImpl::AllInstances().size();
+}
+
void WebView::UpdateVisitedLinkState(uint64_t link_hash) {
Page::VisitedStateChanged(link_hash);
}
@@ -543,13 +542,15 @@ void WebViewImpl::DoDeferredCloseWindowSoon() {
WebViewImpl::WebViewImpl(
WebViewClient* client,
mojom::blink::PageVisibilityState visibility,
+ bool is_prerendering,
bool is_inside_portal,
bool does_composite,
bool widgets_never_composited,
WebViewImpl* opener,
mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const SessionStorageNamespaceId& session_storage_namespace_id)
+ const SessionStorageNamespaceId& session_storage_namespace_id,
+ absl::optional<SkColor> page_base_background_color)
: widgets_never_composited_(widgets_never_composited),
web_view_client_(client),
chrome_client_(MakeGarbageCollected<ChromeClientImpl>(this)),
@@ -557,6 +558,8 @@ WebViewImpl::WebViewImpl(
maximum_zoom_level_(PageZoomFactorToZoomLevel(kMaximumPageZoomFactor)),
does_composite_(does_composite),
fullscreen_controller_(std::make_unique<FullscreenController>(this)),
+ page_base_background_color_(
+ page_base_background_color.value_or(SK_ColorWHITE)),
receiver_(this,
std::move(page_handle),
agent_group_scheduler.DefaultTaskRunner()),
@@ -570,6 +573,7 @@ WebViewImpl::WebViewImpl(
*page_, session_storage_namespace_id_);
SetVisibilityState(visibility, /*is_initial_state=*/true);
+ page_->SetIsPrerendering(is_prerendering);
// We pass this state to Page, but it's only used by the main frame in the
// page.
@@ -996,9 +1000,6 @@ WebPagePopupImpl* WebViewImpl::OpenPagePopup(PagePopupClient* client) {
opener_widget->GetOriginalScreenInfos(),
/*settings=*/nullptr);
- // CreatePopup returns nullptr if this renderer process is about to die.
- if (!popup_widget)
- return nullptr;
page_popup_ = To<WebPagePopupImpl>(popup_widget);
page_popup_->Initialize(this, client);
EnablePopupMouseWheelEventListener(web_opener_frame->LocalRoot());
@@ -1104,6 +1105,11 @@ void WebViewImpl::ResizeVisualViewport(const gfx::Size& new_size) {
GetPage()->GetVisualViewport().ClampToBoundaries();
}
+void WebViewImpl::DidFirstVisuallyNonEmptyPaint() {
+ DCHECK(MainFrameImpl());
+ local_main_frame_host_remote_->DidFirstVisuallyNonEmptyPaint();
+}
+
void WebViewImpl::UpdateICBAndResizeViewport(
const IntSize& visible_viewport_size) {
// We'll keep the initial containing block size from changing when the top
@@ -1314,7 +1320,7 @@ void WebViewImpl::Resize(const gfx::Size& new_size) {
}
void WebViewImpl::SetScreenOrientationOverrideForTesting(
- absl::optional<blink::mojom::ScreenOrientation> orientation) {
+ absl::optional<display::mojom::blink::ScreenOrientation> orientation) {
screen_orientation_override_ = orientation;
// Since we updated the override value, notify all widgets.
@@ -1337,7 +1343,7 @@ void WebViewImpl::SetWindowRectSynchronouslyForTesting(
web_widget_->SetWindowRectSynchronouslyForTesting(new_window_rect);
}
-absl::optional<mojom::blink::ScreenOrientation>
+absl::optional<display::mojom::blink::ScreenOrientation>
WebViewImpl::ScreenOrientationOverride() {
return screen_orientation_override_;
}
@@ -1398,7 +1404,7 @@ void WebViewImpl::PaintContent(cc::PaintCanvas* canvas, const gfx::Rect& rect) {
// static
void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
WebView* web_view) {
- WebViewImpl* web_view_impl = static_cast<WebViewImpl*>(web_view);
+ WebViewImpl* web_view_impl = To<WebViewImpl>(web_view);
WebSettings* settings = web_view->GetSettings();
ApplyFontsFromMap(prefs.standard_font_family_map,
SetStandardFontFamilyWrapper, settings);
@@ -1475,6 +1481,9 @@ void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
RuntimeEnabledFeatures::SetNewCanvas2DAPIEnabled(
prefs.new_canvas_2d_api_enabled);
+ RuntimeEnabledFeatures::SetCanvas2dLayersEnabled(
+ prefs.canvas_2d_layers_enabled);
+
// Disable antialiasing for 2d canvas if requested on the command line.
settings->SetAntialiased2dCanvasEnabled(
!prefs.antialiased_2d_canvas_disabled);
@@ -1776,6 +1785,8 @@ void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
settings->SetTouchDragDropEnabled(prefs.touch_drag_drop_enabled);
settings->SetTouchDragEndContextMenu(prefs.touch_dragend_context_menu);
settings->SetWebXRImmersiveArAllowed(prefs.webxr_immersive_ar_allowed);
+ settings->SetLitePageSubresourceRedirectOrigin(WebString::FromASCII(
+ prefs.litepage_subresource_redirect_origin.Serialize()));
#if defined(OS_MAC)
web_view_impl->SetMaximumLegibleScale(
@@ -1947,6 +1958,8 @@ void WebViewImpl::DidAttachLocalMainFrame() {
if (does_composite_) {
// When attaching a local main frame, set up any state on the compositor.
MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor());
+ MainFrameImpl()->FrameWidgetImpl()->SetPrefersReducedMotion(
+ web_preferences_.prefers_reduced_motion);
auto& viewport = GetPage()->GetVisualViewport();
MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
viewport.Scale(), viewport.IsPinchGestureActive(),
@@ -2356,8 +2369,18 @@ void WebViewImpl::SetPageLifecycleStateInternal(
if (storing_in_bfcache) {
Scheduler()->SetPageBackForwardCached(new_state->is_in_back_forward_cache);
}
- if (freezing_page)
+
+ if (freezing_page) {
+ // Notify all local frames that we are about to freeze.
+ for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) {
+ if (frame->IsWebLocalFrame()) {
+ frame->ToWebLocalFrame()->Client()->WillFreezePage();
+ }
+ }
+
SetPageFrozen(true);
+ }
+
if (restoring_from_bfcache) {
DCHECK(page_restore_params);
// Update the history offset and length value, as pages that are kept in
@@ -3028,14 +3051,17 @@ Color WebViewImpl::BaseBackgroundColor() const {
return SK_ColorTRANSPARENT;
if (base_background_color_override_for_inspector_)
return base_background_color_override_for_inspector_.value();
- return base_background_color_;
+ // Use the page background color if this is the WebView of the main frame.
+ if (MainFrameImpl())
+ return page_base_background_color_;
+ return Color::kWhite;
}
-void WebViewImpl::SetBaseBackgroundColor(SkColor color) {
- if (base_background_color_ == color)
+void WebViewImpl::SetPageBaseBackgroundColor(absl::optional<SkColor> color) {
+ SkColor new_color = color.value_or(SK_ColorWHITE);
+ if (page_base_background_color_ == new_color)
return;
-
- base_background_color_ = color;
+ page_base_background_color_ = new_color;
UpdateBaseBackgroundColor();
}
@@ -3117,6 +3143,41 @@ void WebViewImpl::UpdateFontRenderingFromRendererPrefs() {
#endif // !defined(OS_MAC)
}
+void WebViewImpl::ActivatePrerenderedPage(
+ base::TimeTicks activation_start,
+ ActivatePrerenderedPageCallback callback) {
+ DCHECK(features::IsPrerender2Enabled());
+
+ // From here all new documents will have prerendering false.
+ GetPage()->SetIsPrerendering(false);
+
+ // Collect local documents. This is because we are about to run the
+ // prerenderchange event and post-prerendering activation steps on each
+ // document, which could mutate the frame tree and make iteration over it
+ // complicated.
+ HeapVector<Member<Document>> documents;
+ for (Frame* frame = GetPage()->MainFrame(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ if (auto* local_frame = DynamicTo<LocalFrame>(frame))
+ documents.push_back(local_frame->GetDocument());
+ }
+
+ // A null `activation_start` is sent to the WebViewImpl that does not host the
+ // main frame, in which case we expect that it does not have any documents
+ // since cross-origin documents are not loaded during prerendering.
+ DCHECK(documents.size() == 0 || !activation_start.is_null());
+
+ // While the spec says to post a task on the networking task source for each
+ // document, we don't post a task here for simplicity. This allows dispatching
+ // the event on all documents without a chance for other IPCs from the browser
+ // to arrive in the intervening time, resulting in an unclear state.
+ for (auto& document : documents) {
+ document->ActivateForPrerendering(activation_start);
+ }
+
+ std::move(callback).Run();
+}
+
void WebViewImpl::SetInsidePortal(bool inside_portal) {
GetPage()->SetInsidePortal(inside_portal);
@@ -3170,8 +3231,7 @@ void WebViewImpl::UpdateRendererPreferences(
}
#endif
- if (::features::IsFormControlsRefreshEnabled() &&
- renderer_preferences_.use_custom_colors) {
+ if (renderer_preferences_.use_custom_colors) {
SetFocusRingColor(renderer_preferences_.focus_ring_color);
}
@@ -3240,6 +3300,12 @@ const web_pref::WebPreferences& WebViewImpl::GetWebPreferences() {
void WebViewImpl::UpdateWebPreferences(
const blink::web_pref::WebPreferences& preferences) {
web_preferences_ = preferences;
+
+ if (MainFrameImpl()) {
+ MainFrameImpl()->FrameWidgetImpl()->SetPrefersReducedMotion(
+ web_preferences_.prefers_reduced_motion);
+ }
+
ApplyWebPreferences(preferences, this);
ApplyCommandLineToSettings(SettingsImpl());
}
@@ -3605,7 +3671,6 @@ LocalFrame* WebViewImpl::FocusedLocalFrameInWidget() const {
void WebViewImpl::SetPageFrozen(bool frozen) {
Scheduler()->SetPageFrozen(frozen);
- web_view_client_->OnPageFrozenChanged(frozen);
}
WebFrameWidget* WebViewImpl::MainFrameWidget() {
diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_impl.h b/chromium/third_party/blink/renderer/core/exported/web_view_impl.h
index c2e704e745d..e7b0409bd60 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
@@ -114,13 +114,15 @@ class CORE_EXPORT WebViewImpl final : public WebView,
static WebViewImpl* Create(
WebViewClient*,
mojom::blink::PageVisibilityState visibility,
+ bool is_prerendering,
bool is_inside_portal,
bool compositing_enabled,
bool widgets_never_composited,
WebViewImpl* opener,
mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const SessionStorageNamespaceId& session_storage_namespace_id);
+ const SessionStorageNamespaceId& session_storage_namespace_id,
+ absl::optional<SkColor> page_base_background_color);
// All calls to Create() should be balanced with a call to Close(). This
// synchronously destroys the WebViewImpl.
@@ -171,7 +173,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
gfx::PointF VisualViewportOffset() const override;
gfx::SizeF VisualViewportSize() const override;
void SetScreenOrientationOverrideForTesting(
- absl::optional<blink::mojom::ScreenOrientation> orientation) override;
+ absl::optional<display::mojom::blink::ScreenOrientation> orientation)
+ override;
void UseSynchronousResizeModeForTesting(bool enable) override;
void SetWindowRectSynchronouslyForTesting(
const gfx::Rect& new_window_rect) override;
@@ -198,7 +201,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebPagePopupImpl* GetPagePopup() const override { return page_popup_.get(); }
void SetPageFrozen(bool frozen) override;
WebFrameWidget* MainFrameWidget() override;
- void SetBaseBackgroundColor(SkColor) override;
void SetDeviceColorSpaceForTesting(
const gfx::ColorSpace& color_space) override;
void PaintContent(cc::PaintCanvas*, const gfx::Rect&) override;
@@ -215,6 +217,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void IncreaseHistoryListFromNavigation() override;
int32_t HistoryBackListCount() const override;
int32_t HistoryForwardListCount() const override;
+ int32_t HistoryListLength() const { return history_list_length_; }
const SessionStorageNamespaceId& GetSessionStorageNamespaceId() override;
// Functions to add and remove observers for this object.
@@ -276,6 +279,9 @@ class CORE_EXPORT WebViewImpl final : public WebView,
mojom::blink::PageRestoreParamsPtr page_restore_params,
SetPageLifecycleStateCallback callback) override;
void AudioStateChanged(bool is_audio_playing) override;
+ void ActivatePrerenderedPage(
+ base::TimeTicks activation_start,
+ ActivatePrerenderedPageCallback callback) override;
void SetInsidePortal(bool is_inside_portal) override;
void UpdateWebPreferences(
const blink::web_pref::WebPreferences& preferences) override;
@@ -283,6 +289,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
const RendererPreferences& preferences) override;
void SetHistoryOffsetAndLength(int32_t history_offset,
int32_t history_length) override;
+ void SetPageBaseBackgroundColor(absl::optional<SkColor> color) override;
void DispatchPageshow(base::TimeTicks navigation_start);
void DispatchPagehide(mojom::blink::PagehideDispatch pagehide_dispatch);
@@ -292,7 +299,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
float DefaultMaximumPageScaleFactor() const;
float ClampPageScaleFactorToLimits(float) const;
void ResetScaleStateImmediately();
- absl::optional<mojom::blink::ScreenOrientation> ScreenOrientationOverride();
+ absl::optional<display::mojom::blink::ScreenOrientation>
+ ScreenOrientationOverride();
// This is only for non-composited WebViewPlugin.
void InvalidateContainer();
@@ -571,6 +579,10 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// virtual keyboard to overlay over content but allow scrolling it into view.
void ResizeVisualViewport(const gfx::Size&);
+ // Called once a paint happens after the first non empty layout. In other
+ // words, after the frame has painted something.
+ void DidFirstVisuallyNonEmptyPaint();
+
private:
FRIEND_TEST_ALL_PREFIXES(WebFrameTest, DivScrollIntoEditableTest);
FRIEND_TEST_ALL_PREFIXES(WebFrameTest,
@@ -630,13 +642,15 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebViewImpl(
WebViewClient*,
mojom::blink::PageVisibilityState visibility,
+ bool is_prerendering,
bool is_inside_portal,
bool does_composite,
bool widgets_never_composite,
WebViewImpl* opener,
mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const SessionStorageNamespaceId& session_storage_namespace_id);
+ const SessionStorageNamespaceId& session_storage_namespace_id,
+ absl::optional<SkColor> page_base_background_color);
~WebViewImpl() override;
void ConfigureAutoResizeMode();
@@ -824,7 +838,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
absl::optional<SkColor> background_color_override_for_fullscreen_controller_;
bool override_base_background_color_to_transparent_ = false;
absl::optional<SkColor> base_background_color_override_for_inspector_;
- SkColor base_background_color_ = Color::kWhite;
+ SkColor page_base_background_color_; // Only applies to main frame.
float zoom_factor_override_ = 0.f;
@@ -876,7 +890,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
mojo::AssociatedRemote<mojom::blink::RemoteMainFrameHost>
remote_main_frame_host_remote_;
- absl::optional<mojom::blink::ScreenOrientation> screen_orientation_override_;
+ absl::optional<display::mojom::blink::ScreenOrientation>
+ screen_orientation_override_;
mojo::AssociatedReceiver<mojom::blink::PageBroadcast> receiver_;
@@ -896,6 +911,13 @@ class CORE_EXPORT WebViewImpl final : public WebView,
base::WeakPtrFactory<WebViewImpl> weak_ptr_factory_{this};
};
+// WebView is always implemented by WebViewImpl, so explicitly allow the
+// downcast.
+template <>
+struct DowncastTraits<WebViewImpl> {
+ static bool AllowFrom(const WebView& web_view) { return true; }
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_VIEW_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_observer.cc b/chromium/third_party/blink/renderer/core/exported/web_view_observer.cc
index c206c59a4a1..274c49a9246 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_view_observer.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_view_observer.cc
@@ -5,11 +5,12 @@
#include "third_party/blink/public/web/web_view_observer.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
WebViewObserver::WebViewObserver(WebView* web_view)
- : web_view_(static_cast<WebViewImpl*>(web_view)) {
+ : web_view_(To<WebViewImpl>(web_view)) {
// |web_view_| can be null on unit testing or if Observe() is used.
if (web_view_) {
web_view_->AddObserver(this);
@@ -29,7 +30,7 @@ void WebViewObserver::Observe(WebView* web_view) {
web_view_->RemoveObserver(this);
}
- web_view_ = static_cast<WebViewImpl*>(web_view);
+ web_view_ = To<WebViewImpl>(web_view);
if (web_view_) {
web_view_->AddObserver(this);
}
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 10af02c08f2..92d781a1a0f 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,7 +35,7 @@
#include <string>
#include "base/callback_helpers.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -84,6 +84,7 @@
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/css/media_query_list_listener.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -153,6 +154,7 @@
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/cursor/cursor.h"
@@ -186,9 +188,7 @@ enum VerticalScrollbarState {
class TestData {
public:
- void SetWebView(WebView* web_view) {
- web_view_ = static_cast<WebViewImpl*>(web_view);
- }
+ void SetWebView(WebView* web_view) { web_view_ = To<WebViewImpl>(web_view); }
void SetSize(const gfx::Size& new_size) { size_ = new_size; }
HorizontalScrollbarState GetHorizontalScrollbarState() const {
return web_view_->HasHorizontalScrollbar() ? kVisibleHorizontalScrollbar
@@ -432,7 +432,7 @@ TEST_F(WebViewTest, SetBaseBackgroundColor) {
WebViewImpl* web_view = web_view_helper_.Initialize();
EXPECT_EQ(SK_ColorWHITE, web_view->BackgroundColor());
- web_view->SetBaseBackgroundColor(SK_ColorBLUE);
+ web_view->SetPageBaseBackgroundColor(SK_ColorBLUE);
EXPECT_EQ(SK_ColorBLUE, web_view->BackgroundColor());
WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
@@ -452,11 +452,11 @@ TEST_F(WebViewTest, SetBaseBackgroundColor) {
// Expected: red (50% alpha) blended atop base of SK_ColorBLUE.
EXPECT_EQ(0xFF80007F, web_view->BackgroundColor());
- web_view->SetBaseBackgroundColor(kTranslucentPutty);
+ web_view->SetPageBaseBackgroundColor(kTranslucentPutty);
// Expected: red (50% alpha) blended atop kTranslucentPutty. Note the alpha.
EXPECT_EQ(0xBFE93A31, web_view->BackgroundColor());
- web_view->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
+ web_view->SetPageBaseBackgroundColor(SK_ColorTRANSPARENT);
frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
"<html><head><style>body "
"{background-color:transparent}</style></"
@@ -485,21 +485,24 @@ TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame) {
// Note: this test doesn't use WebViewHelper since it intentionally runs
// initialization code between WebView and WebLocalFrame creation.
frame_test_helpers::TestWebViewClient web_view_client;
- WebViewImpl* web_view = static_cast<WebViewImpl*>(
+ WebViewImpl* web_view = To<WebViewImpl>(
WebView::Create(&web_view_client,
/*is_hidden=*/false,
+ /*is_prerendering=*/false,
/*is_inside_portal=*/false,
/*compositing_enabled=*/true,
/*widgets_never_composited=*/false,
/*opener=*/nullptr, mojo::NullAssociatedReceiver(),
web_view_helper_.GetAgentGroupScheduler(),
- /*session_storage_namespace_id=*/base::EmptyString()));
+ /*session_storage_namespace_id=*/base::EmptyString(),
+ /*page_base_background_color=*/absl::nullopt));
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.
- web_view->SetBaseBackgroundColor(SK_ColorBLUE);
- EXPECT_EQ(SK_ColorBLUE, web_view->BackgroundColor());
+ // WebView does not have a frame yet; while it's possible to set the page
+ // background color, it won't have any effect until a local main frame is
+ // attached.
+ web_view->SetPageBaseBackgroundColor(SK_ColorBLUE);
+ EXPECT_NE(SK_ColorBLUE, web_view->BackgroundColor());
frame_test_helpers::TestWebFrameClient web_frame_client;
WebLocalFrame* frame = WebLocalFrame::CreateMainFrame(
@@ -527,7 +530,7 @@ TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent) {
WebViewImpl* web_view = web_view_helper_.Initialize();
// Set WebView background to green with alpha.
- web_view->SetBaseBackgroundColor(kAlphaGreen);
+ web_view->SetPageBaseBackgroundColor(kAlphaGreen);
web_view->GetSettings()->SetShouldClearDocumentBackground(false);
web_view->MainFrameViewWidget()->Resize(gfx::Size(kWidth, kHeight));
UpdateAllLifecyclePhases();
@@ -568,7 +571,7 @@ TEST_F(WebViewTest, SetBaseBackgroundColorWithColorScheme) {
ColorSchemeHelper color_scheme_helper(*(web_view->GetPage()));
color_scheme_helper.SetPreferredColorScheme(
mojom::blink::PreferredColorScheme::kLight);
- web_view->SetBaseBackgroundColor(SK_ColorBLUE);
+ web_view->SetPageBaseBackgroundColor(SK_ColorBLUE);
WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
frame_test_helpers::LoadHTMLString(
@@ -585,9 +588,9 @@ TEST_F(WebViewTest, SetBaseBackgroundColorWithColorScheme) {
EXPECT_EQ(Color(0x12, 0x12, 0x12), frame_view->BaseBackgroundColor());
// Don't let dark color-scheme override a transparent background.
- web_view->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
+ web_view->SetPageBaseBackgroundColor(SK_ColorTRANSPARENT);
EXPECT_EQ(Color::kTransparent, frame_view->BaseBackgroundColor());
- web_view->SetBaseBackgroundColor(SK_ColorBLUE);
+ web_view->SetPageBaseBackgroundColor(SK_ColorBLUE);
EXPECT_EQ(Color(0x12, 0x12, 0x12), frame_view->BaseBackgroundColor());
color_scheme_helper.SetForcedColors(*(web_view->GetPage()),
@@ -2604,24 +2607,24 @@ TEST_F(WebViewTest, FullscreenBackgroundColor) {
EXPECT_EQ(SK_ColorYELLOW, web_view_impl->BackgroundColor());
}
-class PrintWebViewClient : public frame_test_helpers::TestWebViewClient {
+class PrintWebFrameClient : public frame_test_helpers::TestWebFrameClient {
public:
- PrintWebViewClient() : print_called_(false) {}
+ PrintWebFrameClient() = default;
- // WebViewClient methods
- void PrintPage(WebLocalFrame*) override { print_called_ = true; }
+ // WebLocalFrameClient overrides:
+ void ScriptedPrint() override { print_called_ = true; }
bool PrintCalled() const { return print_called_; }
private:
- bool print_called_;
+ bool print_called_ = false;
};
TEST_F(WebViewTest, PrintWithXHRInFlight) {
- PrintWebViewClient client;
+ PrintWebFrameClient client;
RegisterMockedHttpURLLoad("print_with_xhr_inflight.html");
WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(
- base_url_ + "print_with_xhr_inflight.html", nullptr, &client);
+ base_url_ + "print_with_xhr_inflight.html", &client, nullptr);
ASSERT_TRUE(To<LocalFrame>(web_view_impl->GetPage()->MainFrame())
->GetDocument()
@@ -2733,13 +2736,15 @@ ExternalDateTimeChooser* WebViewTest::GetExternalDateTimeChooser(
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(
- /*client=*/nullptr, /*is_hidden=*/false, /*is_inside_portal=*/false,
+ WebViewImpl* web_view = To<WebViewImpl>(WebView::Create(
+ /*client=*/nullptr, /*is_hidden=*/false, /*is_prerendering=*/false,
+ /*is_inside_portal=*/false,
/*compositing_enabled=*/false,
/*widgets_never_composited=*/false,
/*opener=*/nullptr, mojo::NullAssociatedReceiver(),
web_view_helper_.GetAgentGroupScheduler(),
- /*session_storage_namespace_id=*/base::EmptyString()));
+ /*session_storage_namespace_id=*/base::EmptyString(),
+ /*page_base_background_color=*/absl::nullopt));
frame_test_helpers::TestWebFrameClient web_frame_client;
WebLocalFrame* local_frame = WebLocalFrame::CreateMainFrame(
web_view, &web_frame_client, nullptr, LocalFrameToken(), nullptr);
@@ -3703,7 +3708,7 @@ TEST_F(WebViewTest, FinishComposingTextDoesntTriggerAutofillTextChange) {
WebVector<ui::ImeTextSpan> empty_ime_text_spans;
active_input_method_controller->SetComposition(
WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans,
- WebRange(), 0, composition_text.length());
+ WebRange(), 0, static_cast<int>(composition_text.length()));
WebTextInputInfo info = active_input_method_controller->TextInputInfo();
EXPECT_EQ(0, info.selection_start);
@@ -4117,7 +4122,7 @@ TEST_F(WebViewTest, AddFrameInCloseURLUnload) {
web_view_helper_.InitializeAndLoad(base_url_ + "add_frame_in_unload.html",
&frame_client);
// Dispatch unload event.
- web_view_helper_.LocalMainFrame()->GetFrame()->ClosePage(base::DoNothing());
+ web_view_helper_.LocalMainFrame()->GetFrame()->ClosePageForTesting();
EXPECT_EQ(0, frame_client.Count());
web_view_helper_.Reset();
}
@@ -4653,10 +4658,48 @@ TEST_F(WebViewTest, PreferredSizeWithGrid) {
base_url);
gfx::Size size = web_view->ContentsPreferredMinimumSize();
- EXPECT_EQ(100, size.width());
+ if (RuntimeEnabledFeatures::LayoutNGEnabled())
+ EXPECT_EQ(0, size.width());
+ else
+ EXPECT_EQ(100, size.width());
+
EXPECT_EQ(100, size.height());
}
+TEST_F(WebViewTest, PreferredSizeWithNGGridSkipped) {
+ WebViewImpl* web_view = web_view_helper_.Initialize();
+ WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
+ frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
+ R"HTML(<!DOCTYPE html>
+ <style>
+ body { margin: 0px; }
+ </style>
+ <div style="display: inline-grid;
+ padding: 1%;
+ border: 5px solid black;
+ grid-template-rows: 1fr 2fr">
+ <svg id="target" viewBox="0 0 1 1" style="background: green;
+ height: 100%;" >
+ <circle id="c1" cx="50" cy="50" r="50"/>
+ </svg>
+ </div>
+ )HTML",
+ base_url);
+
+ LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
+ Document* document = main_frame->GetDocument();
+ Element* element = document->getElementById("target");
+
+ // Note: Not entirely clear how we get into this state in release builds, we
+ // *should* be layout clean and have cached results for the preferred size
+ // query. See https://crbug.com/1245654 for how we saw this issue in the wild.
+ element->GetLayoutBox()->ClearLayoutResults();
+
+ gfx::Size size = web_view->ContentsPreferredMinimumSize();
+ EXPECT_EQ(10, size.width());
+ EXPECT_EQ(10, size.height());
+}
+
TEST_F(WebViewTest, PreferredSizeWithGridMinWidth) {
WebViewImpl* web_view = web_view_helper_.Initialize();
WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
@@ -6126,7 +6169,7 @@ TEST_F(WebViewTest, EmulatingPopupRect) {
gfx::Rect widget_screen_rect(5, 7, 57, 59);
blink::VisualProperties visual_properties;
- visual_properties.screen_infos = ScreenInfos(ScreenInfo());
+ visual_properties.screen_infos = display::ScreenInfos(display::ScreenInfo());
visual_properties.new_size = gfx::Size(400, 300);
visual_properties.visible_viewport_size = gfx::Size(400, 300);
visual_properties.screen_infos.mutable_current().rect = gfx::Rect(800, 600);
diff --git a/chromium/third_party/blink/renderer/core/fetch/OWNERS b/chromium/third_party/blink/renderer/core/fetch/OWNERS
index 0f061320cce..acbf93af41e 100644
--- a/chromium/third_party/blink/renderer/core/fetch/OWNERS
+++ b/chromium/third_party/blink/renderer/core/fetch/OWNERS
@@ -1,3 +1 @@
-hiroshige@chromium.org
-horo@chromium.org
yhirano@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.cc b/chromium/third_party/blink/renderer/core/fetch/body.cc
index aadd3d4bfaf..d880fc43562 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/body.cc
@@ -10,7 +10,6 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/abseil-cpp/absl/types/optional.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"
#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"
@@ -40,6 +39,9 @@ class BodyConsumerBase : public GarbageCollected<BodyConsumerBase>,
: resolver_(resolver),
task_runner_(ExecutionContext::From(resolver_->GetScriptState())
->GetTaskRunner(TaskType::kNetworking)) {}
+ BodyConsumerBase(const BodyConsumerBase&) = delete;
+ BodyConsumerBase& operator=(const BodyConsumerBase&) = delete;
+
ScriptPromiseResolver* Resolver() { return resolver_; }
void DidFetchDataLoadFailed() override {
ScriptState::Scope scope(Resolver()->GetScriptState());
@@ -75,37 +77,40 @@ class BodyConsumerBase : public GarbageCollected<BodyConsumerBase>,
const Member<ScriptPromiseResolver> resolver_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- DISALLOW_COPY_AND_ASSIGN(BodyConsumerBase);
};
class BodyBlobConsumer final : public BodyConsumerBase {
public:
explicit BodyBlobConsumer(ScriptPromiseResolver* resolver)
: BodyConsumerBase(resolver) {}
+ BodyBlobConsumer(const BodyBlobConsumer&) = delete;
+ BodyBlobConsumer& operator=(const BodyBlobConsumer&) = delete;
void DidFetchDataLoadedBlobHandle(
scoped_refptr<BlobDataHandle> blob_data_handle) override {
ResolveLater(WrapPersistent(
MakeGarbageCollected<Blob>(std::move(blob_data_handle))));
}
- DISALLOW_COPY_AND_ASSIGN(BodyBlobConsumer);
};
class BodyArrayBufferConsumer final : public BodyConsumerBase {
public:
explicit BodyArrayBufferConsumer(ScriptPromiseResolver* resolver)
: BodyConsumerBase(resolver) {}
+ BodyArrayBufferConsumer(const BodyArrayBufferConsumer&) = delete;
+ BodyArrayBufferConsumer& operator=(const BodyArrayBufferConsumer&) = delete;
void DidFetchDataLoadedArrayBuffer(DOMArrayBuffer* array_buffer) override {
ResolveLater(WrapPersistent(array_buffer));
}
- DISALLOW_COPY_AND_ASSIGN(BodyArrayBufferConsumer);
};
class BodyFormDataConsumer final : public BodyConsumerBase {
public:
explicit BodyFormDataConsumer(ScriptPromiseResolver* resolver)
: BodyConsumerBase(resolver) {}
+ BodyFormDataConsumer(const BodyFormDataConsumer&) = delete;
+ BodyFormDataConsumer& operator=(const BodyFormDataConsumer&) = delete;
void DidFetchDataLoadedFormData(FormData* formData) override {
ResolveLater(WrapPersistent(formData));
@@ -117,24 +122,26 @@ class BodyFormDataConsumer final : public BodyConsumerBase {
formData->append(pair.first, pair.second);
DidFetchDataLoadedFormData(formData);
}
- DISALLOW_COPY_AND_ASSIGN(BodyFormDataConsumer);
};
class BodyTextConsumer final : public BodyConsumerBase {
public:
explicit BodyTextConsumer(ScriptPromiseResolver* resolver)
: BodyConsumerBase(resolver) {}
+ BodyTextConsumer(const BodyTextConsumer&) = delete;
+ BodyTextConsumer& operator=(const BodyTextConsumer&) = delete;
void DidFetchDataLoadedString(const String& string) override {
ResolveLater(string);
}
- DISALLOW_COPY_AND_ASSIGN(BodyTextConsumer);
};
class BodyJsonConsumer final : public BodyConsumerBase {
public:
explicit BodyJsonConsumer(ScriptPromiseResolver* resolver)
: BodyConsumerBase(resolver) {}
+ BodyJsonConsumer(const BodyJsonConsumer&) = delete;
+ BodyJsonConsumer& operator=(const BodyJsonConsumer&) = delete;
void DidFetchDataLoadedString(const String& string) override {
if (!Resolver()->GetExecutionContext() ||
@@ -153,7 +160,6 @@ class BodyJsonConsumer final : public BodyConsumerBase {
} else
Resolver()->Reject(trycatch.Exception());
}
- DISALLOW_COPY_AND_ASSIGN(BodyJsonConsumer);
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.h b/chromium/third_party/blink/renderer/core/fetch/body.h
index 3db2c704600..93d44421a52 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.h
+++ b/chromium/third_party/blink/renderer/core/fetch/body.h
@@ -32,6 +32,8 @@ class ScriptState;
class CORE_EXPORT Body : public ExecutionContextClient {
public:
explicit Body(ExecutionContext*);
+ Body(const Body&) = delete;
+ Body& operator=(const Body&) = delete;
ScriptPromise arrayBuffer(ScriptState*, ExceptionState&);
ScriptPromise blob(ScriptState*, ExceptionState&);
@@ -65,7 +67,6 @@ class CORE_EXPORT Body : public ExecutionContextClient {
// an exception if consumption cannot proceed. The caller must check
// |exception_state| on return.
void RejectInvalidConsumption(ExceptionState& exception_state) const;
- DISALLOW_COPY_AND_ASSIGN(Body);
};
} // namespace blink
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 a9d0073357c..f53700a7efe 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
@@ -39,6 +39,8 @@ class BodyStreamBuffer::LoaderClient final
: ExecutionContextLifecycleObserver(execution_context),
buffer_(buffer),
client_(client) {}
+ LoaderClient(const LoaderClient&) = delete;
+ LoaderClient& operator=(const LoaderClient&) = delete;
void DidFetchDataLoadedBlobHandle(
scoped_refptr<BlobDataHandle> blob_data_handle) override {
@@ -95,7 +97,6 @@ class BodyStreamBuffer::LoaderClient final
Member<BodyStreamBuffer> buffer_;
Member<FetchDataLoader::Client> client_;
- DISALLOW_COPY_AND_ASSIGN(LoaderClient);
};
// Use a Create() method to split construction from initialisation.
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 763d83eb633..5dc22d93949 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
@@ -58,6 +58,9 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
ScriptCachedMetadataHandler* cached_metadata_handler,
scoped_refptr<BlobDataHandle> side_data_blob = nullptr);
+ BodyStreamBuffer(const BodyStreamBuffer&) = delete;
+ BodyStreamBuffer& operator=(const BodyStreamBuffer&) = delete;
+
ReadableStream* Stream() { return stream_; }
// Callable only when neither locked nor disturbed.
@@ -155,8 +158,6 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
// TODO(ricea): Remove remaining uses of |stream_broken_|.
bool stream_broken_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(BodyStreamBuffer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/bytes_uploader.cc b/chromium/third_party/blink/renderer/core/fetch/bytes_uploader.cc
index eed6dde9461..38be3de9e38 100644
--- a/chromium/third_party/blink/renderer/core/fetch/bytes_uploader.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/bytes_uploader.cc
@@ -45,10 +45,10 @@ void BytesUploader::GetSize(GetSizeCallback get_size_callback) {
void BytesUploader::StartReading(
mojo::ScopedDataPipeProducerHandle upload_pipe) {
DVLOG(3) << this << " StartReading()";
- DCHECK(get_size_callback_);
DCHECK(upload_pipe);
- if (upload_pipe_) {
- // Replay was asked by net/ service.
+ if (!get_size_callback_ || upload_pipe_) {
+ // When StartReading() is called while |upload_pipe_| is valid, it means
+ // replay was asked by the network service.
CloseOnError();
return;
}
@@ -88,8 +88,6 @@ void BytesUploader::OnPipeWriteable(MojoResult unused) {
void BytesUploader::WriteDataOnPipe() {
DVLOG(3) << this << " WriteDataOnPipe(). consumer_->GetPublicState()="
<< consumer_->GetPublicState();
- DCHECK(upload_pipe_);
- DCHECK(get_size_callback_);
if (!upload_pipe_.is_valid())
return;
@@ -116,8 +114,7 @@ void BytesUploader::WriteDataOnPipe() {
const MojoResult mojo_result = upload_pipe_->WriteData(
buffer, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
DVLOG(3) << " upload_pipe_->WriteData()=" << mojo_result
- << ", mojo_written=" << written_bytes
- << ", consumer_->EndRead()=" << consumer_result;
+ << ", mojo_written=" << written_bytes;
if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
// Wait for the pipe to have more capacity available
consumer_result = consumer_->EndRead(0);
@@ -130,6 +127,8 @@ void BytesUploader::WriteDataOnPipe() {
}
consumer_result = consumer_->EndRead(written_bytes);
+ DVLOG(3) << " consumer_->EndRead()=" << consumer_result;
+
if (!base::CheckAdd(total_size_, written_bytes)
.AssignIfValid(&total_size_)) {
CloseOnError();
@@ -154,16 +153,16 @@ void BytesUploader::WriteDataOnPipe() {
void BytesUploader::Close() {
DVLOG(3) << this << " Close(). total_size=" << total_size_;
- DCHECK(get_size_callback_);
- std::move(get_size_callback_).Run(net::OK, total_size_);
+ if (get_size_callback_)
+ std::move(get_size_callback_).Run(net::OK, total_size_);
consumer_->Cancel();
Dispose();
}
void BytesUploader::CloseOnError() {
DVLOG(3) << this << " CloseOnError(). total_size=" << total_size_;
- DCHECK(get_size_callback_);
- std::move(get_size_callback_).Run(net::ERR_FAILED, total_size_);
+ if (get_size_callback_)
+ std::move(get_size_callback_).Run(net::ERR_FAILED, total_size_);
consumer_->Cancel();
Dispose();
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/bytes_uploader_test.cc b/chromium/third_party/blink/renderer/core/fetch/bytes_uploader_test.cc
index 88bc06098f4..627c8e830b4 100644
--- a/chromium/third_party/blink/renderer/core/fetch/bytes_uploader_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/bytes_uploader_test.cc
@@ -17,7 +17,10 @@ using network::mojom::blink::ChunkedDataPipeGetter;
using testing::_;
using testing::InSequence;
using testing::Invoke;
+using testing::NiceMock;
using testing::Return;
+using testing::StrictMock;
+
namespace blink {
typedef testing::StrictMock<testing::MockFunction<void(int)>> Checkpoint;
@@ -32,20 +35,21 @@ class MockBytesConsumer : public BytesConsumer {
MOCK_METHOD1(SetClient, void(Client*));
MOCK_METHOD0(ClearClient, void());
MOCK_METHOD0(Cancel, void());
- MOCK_CONST_METHOD0(GetPublicState, PublicState());
+ PublicState GetPublicState() const override { return state_; }
+ void SetPublicState(PublicState state) { state_ = state; }
MOCK_CONST_METHOD0(GetError, Error());
MOCK_CONST_METHOD0(DebugName, String());
+
+ private:
+ PublicState state_ = PublicState::kReadableOrWaiting;
};
class BytesUploaderTest : public ::testing::Test {
public:
- void InitializeBytesUploader(uint32_t capacity = 100u) {
- mock_bytes_consumer_ = MakeGarbageCollected<MockBytesConsumer>();
- EXPECT_CALL(*mock_bytes_consumer_, GetPublicState())
- .WillRepeatedly(Return(BytesConsumer::PublicState::kReadableOrWaiting));
-
+ void InitializeBytesUploader(MockBytesConsumer* mock_bytes_consumer,
+ uint32_t capacity = 100u) {
bytes_uploader_ = MakeGarbageCollected<BytesUploader>(
- mock_bytes_consumer_, remote_.BindNewPipeAndPassReceiver(),
+ mock_bytes_consumer, remote_.BindNewPipeAndPassReceiver(),
Thread::Current()->GetTaskRunner());
const MojoCreateDataPipeOptions data_pipe_options{
@@ -55,29 +59,27 @@ class BytesUploaderTest : public ::testing::Test {
mojo::CreateDataPipe(&data_pipe_options, writable_, readable_));
}
- MockBytesConsumer& Mock() const { return *mock_bytes_consumer_; }
mojo::ScopedDataPipeProducerHandle& Writable() { return writable_; }
mojo::ScopedDataPipeConsumerHandle& Readable() { return readable_; }
mojo::Remote<ChunkedDataPipeGetter>& Remote() { return remote_; }
- private:
+ protected:
Persistent<BytesUploader> bytes_uploader_;
- Persistent<MockBytesConsumer> mock_bytes_consumer_;
+ private:
mojo::ScopedDataPipeProducerHandle writable_;
mojo::ScopedDataPipeConsumerHandle readable_;
mojo::Remote<ChunkedDataPipeGetter> remote_;
};
TEST_F(BytesUploaderTest, Create) {
- MockBytesConsumer* mock_bytes_consumer =
- MakeGarbageCollected<MockBytesConsumer>();
+ auto* mock_bytes_consumer =
+ MakeGarbageCollected<StrictMock<MockBytesConsumer>>();
+
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
- EXPECT_CALL(*mock_bytes_consumer, GetPublicState())
- .WillRepeatedly(Return(BytesConsumer::PublicState::kReadableOrWaiting));
}
checkpoint.Call(1);
@@ -91,8 +93,8 @@ TEST_F(BytesUploaderTest, Create) {
// TODO(yoichio): Needs BytesConsumer state tests.
TEST_F(BytesUploaderTest, ReadEmpty) {
- InitializeBytesUploader();
-
+ auto* mock_bytes_consumer =
+ MakeGarbageCollected<StrictMock<MockBytesConsumer>>();
base::MockCallback<ChunkedDataPipeGetter::GetSizeCallback> get_size_callback;
Checkpoint checkpoint;
{
@@ -100,18 +102,17 @@ TEST_F(BytesUploaderTest, ReadEmpty) {
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(checkpoint, Call(2));
- EXPECT_CALL(Mock(), SetClient(_));
- EXPECT_CALL(Mock(), GetPublicState())
- .WillRepeatedly(Return(BytesConsumer::PublicState::kReadableOrWaiting));
- EXPECT_CALL(Mock(), BeginRead(_, _))
+ EXPECT_CALL(*mock_bytes_consumer, SetClient(_));
+ EXPECT_CALL(*mock_bytes_consumer, BeginRead(_, _))
.WillOnce(Return(BytesConsumer::Result::kDone));
- EXPECT_CALL(Mock(), Cancel());
+ EXPECT_CALL(*mock_bytes_consumer, Cancel());
EXPECT_CALL(get_size_callback, Run(net::OK, 0u));
EXPECT_CALL(checkpoint, Call(3));
}
checkpoint.Call(1);
+ InitializeBytesUploader(mock_bytes_consumer);
Remote()->GetSize(get_size_callback.Get());
Remote()->StartReading(std::move(Writable()));
@@ -127,32 +128,31 @@ TEST_F(BytesUploaderTest, ReadEmpty) {
}
TEST_F(BytesUploaderTest, ReadSmall) {
- InitializeBytesUploader();
-
+ auto* mock_bytes_consumer =
+ MakeGarbageCollected<StrictMock<MockBytesConsumer>>();
base::MockCallback<ChunkedDataPipeGetter::GetSizeCallback> get_size_callback;
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(checkpoint, Call(2));
- EXPECT_CALL(Mock(), SetClient(_));
- EXPECT_CALL(Mock(), GetPublicState())
- .WillRepeatedly(Return(BytesConsumer::PublicState::kReadableOrWaiting));
- EXPECT_CALL(Mock(), BeginRead(_, _))
+ EXPECT_CALL(*mock_bytes_consumer, SetClient(_));
+ EXPECT_CALL(*mock_bytes_consumer, BeginRead(_, _))
.WillOnce(Invoke([](const char** buffer, size_t* size) {
*size = 6;
*buffer = "foobar";
return BytesConsumer::Result::kOk;
}));
- EXPECT_CALL(Mock(), EndRead(6u))
+ EXPECT_CALL(*mock_bytes_consumer, EndRead(6u))
.WillOnce(Return(BytesConsumer::Result::kDone));
- EXPECT_CALL(Mock(), Cancel());
+ EXPECT_CALL(*mock_bytes_consumer, Cancel());
EXPECT_CALL(get_size_callback, Run(net::OK, 6u));
EXPECT_CALL(checkpoint, Call(3));
}
checkpoint.Call(1);
+ InitializeBytesUploader(mock_bytes_consumer);
Remote()->GetSize(get_size_callback.Get());
Remote()->StartReading(std::move(Writable()));
@@ -169,8 +169,8 @@ TEST_F(BytesUploaderTest, ReadSmall) {
}
TEST_F(BytesUploaderTest, ReadOverPipeCapacity) {
- InitializeBytesUploader(10u);
-
+ auto* mock_bytes_consumer =
+ MakeGarbageCollected<StrictMock<MockBytesConsumer>>();
base::MockCallback<ChunkedDataPipeGetter::GetSizeCallback> get_size_callback;
Checkpoint checkpoint;
{
@@ -178,42 +178,41 @@ TEST_F(BytesUploaderTest, ReadOverPipeCapacity) {
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(checkpoint, Call(2));
- EXPECT_CALL(Mock(), SetClient(_));
- EXPECT_CALL(Mock(), GetPublicState())
- .WillRepeatedly(Return(BytesConsumer::PublicState::kReadableOrWaiting));
- EXPECT_CALL(Mock(), BeginRead(_, _))
+ EXPECT_CALL(*mock_bytes_consumer, SetClient(_));
+ EXPECT_CALL(*mock_bytes_consumer, BeginRead(_, _))
.WillOnce(Invoke([](const char** buffer, size_t* size) {
*size = 12;
*buffer = "foobarFOOBAR";
return BytesConsumer::Result::kOk;
}));
- EXPECT_CALL(Mock(), EndRead(10u))
+ EXPECT_CALL(*mock_bytes_consumer, EndRead(10u))
.WillOnce(Return(BytesConsumer::Result::kOk));
- EXPECT_CALL(Mock(), BeginRead(_, _))
+ EXPECT_CALL(*mock_bytes_consumer, BeginRead(_, _))
.WillOnce(Invoke([](const char** buffer, size_t* size) {
*size = 2;
*buffer = "AR";
return BytesConsumer::Result::kOk;
}));
- EXPECT_CALL(Mock(), EndRead(0u))
+ EXPECT_CALL(*mock_bytes_consumer, EndRead(0u))
.WillOnce(Return(BytesConsumer::Result::kOk));
EXPECT_CALL(checkpoint, Call(3));
EXPECT_CALL(checkpoint, Call(4));
- EXPECT_CALL(Mock(), BeginRead(_, _))
+ EXPECT_CALL(*mock_bytes_consumer, BeginRead(_, _))
.WillOnce(Invoke([](const char** buffer, size_t* size) {
*size = 2;
*buffer = "AR";
return BytesConsumer::Result::kOk;
}));
- EXPECT_CALL(Mock(), EndRead(2u))
+ EXPECT_CALL(*mock_bytes_consumer, EndRead(2u))
.WillOnce(Return(BytesConsumer::Result::kDone));
- EXPECT_CALL(Mock(), Cancel());
+ EXPECT_CALL(*mock_bytes_consumer, Cancel());
EXPECT_CALL(get_size_callback, Run(net::OK, 12u));
}
checkpoint.Call(1);
+ InitializeBytesUploader(mock_bytes_consumer, 10u);
Remote()->GetSize(get_size_callback.Get());
Remote()->StartReading(std::move(Writable()));
@@ -238,4 +237,15 @@ TEST_F(BytesUploaderTest, ReadOverPipeCapacity) {
EXPECT_STREQ("AR", buffer2);
}
+TEST_F(BytesUploaderTest, StartReadingWithoutGetSize) {
+ auto* mock_bytes_consumer =
+ MakeGarbageCollected<NiceMock<MockBytesConsumer>>();
+ InitializeBytesUploader(mock_bytes_consumer);
+
+ Remote()->StartReading(std::move(Writable()));
+ test::RunPendingTasks();
+ // The operation is rejected, and the connection is shut down.
+ EXPECT_FALSE(Remote().is_connected());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
index 17a00760aa1..8aac2caa151 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
@@ -6,8 +6,8 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h
index b26b4c93584..18a48183e05 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h
@@ -5,7 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_FETCH_HEADER_LIST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_FETCH_HEADER_LIST_H_
+#include <map>
#include <utility>
+
#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/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list_test.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list_test.cc
index 200e8fc9aeb..4ebde114996 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list_test.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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/wtf_string.h"
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 92617164387..9062172c626 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -11,11 +11,14 @@
#include "base/metrics/histogram_functions.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/strcat.h"
+#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/request_mode.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -37,7 +40,9 @@
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h"
+#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
@@ -77,6 +82,7 @@
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "v8.h"
using network::mojom::CredentialsMode;
using network::mojom::FetchResponseType;
@@ -135,13 +141,15 @@ class FetchManager::Loader final
void Trace(Visitor*) const override;
// ThreadableLoaderClient implementation.
- bool WillFollowRedirect(const KURL&, const ResourceResponse&) override;
+ bool WillFollowRedirect(uint64_t,
+ const KURL&,
+ const ResourceResponse&) override;
void DidReceiveResponse(uint64_t, const ResourceResponse&) override;
void DidReceiveCachedMetadata(mojo_base::BigBuffer) override;
void DidStartLoadingResponseBody(BytesConsumer&) override;
void DidFinishLoading(uint64_t) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t, const ResourceError&) override;
+ void DidFailRedirectCheck(uint64_t) override;
void Start();
void Dispose();
@@ -255,14 +263,19 @@ class FetchManager::Loader final
private:
void PerformSchemeFetch();
- void PerformNetworkError(const String& message);
+ void PerformNetworkError(
+ const String& message,
+ absl::optional<base::UnguessableToken> issue_id = absl::nullopt);
void FileIssueAndPerformNetworkError(RendererCorsIssueCode,
int64_t identifier);
void PerformHTTPFetch();
void PerformDataFetch();
// If |dom_exception| is provided, throws the specified DOMException instead
// of the usual "Failed to fetch" TypeError.
- void Failed(const String& message, DOMException* dom_exception);
+ void Failed(const String& message,
+ DOMException* dom_exception,
+ absl::optional<String> devtools_request_id = absl::nullopt,
+ absl::optional<base::UnguessableToken> issue_id = absl::nullopt);
void NotifyFinished();
ExecutionContext* GetExecutionContext() { return execution_context_; }
@@ -281,6 +294,7 @@ class FetchManager::Loader final
Vector<KURL> url_list_;
Member<ExecutionContext> execution_context_;
Member<ScriptCachedMetadataHandler> cached_metadata_handler_;
+ TraceWrapperV8Reference<v8::Value> exception_;
};
FetchManager::Loader::Loader(ExecutionContext* execution_context,
@@ -301,6 +315,15 @@ FetchManager::Loader::Loader(ExecutionContext* execution_context,
execution_context_(execution_context) {
DCHECK(world_);
url_list_.push_back(fetch_request_data->Url());
+ ScriptState* state = resolver_->GetScriptState();
+ v8::Isolate* isolate = state->GetIsolate();
+ // Only use a handle scope as we should be in the right context already.
+ v8::HandleScope scope(isolate);
+ // Create the exception at this point so we get the stack-trace that belongs
+ // to the fetch() call.
+ v8::Local<v8::Value> exception =
+ V8ThrowException::CreateTypeError(isolate, "Failed to fetch");
+ exception_.Set(isolate, exception);
}
FetchManager::Loader::~Loader() {
@@ -317,15 +340,17 @@ void FetchManager::Loader::Trace(Visitor* visitor) const {
visitor->Trace(signal_);
visitor->Trace(execution_context_);
visitor->Trace(cached_metadata_handler_);
+ visitor->Trace(exception_);
ThreadableLoaderClient::Trace(visitor);
}
bool FetchManager::Loader::WillFollowRedirect(
+ uint64_t identifier,
const KURL& url,
const ResourceResponse& response) {
const auto redirect_mode = fetch_request_data_->Redirect();
if (redirect_mode == network::mojom::RedirectMode::kError) {
- DidFailRedirectCheck();
+ DidFailRedirectCheck(identifier);
Dispose();
return false;
}
@@ -487,7 +512,8 @@ void FetchManager::Loader::DidFinishLoading(uint64_t) {
NotifyFinished();
}
-void FetchManager::Loader::DidFail(const ResourceError& error) {
+void FetchManager::Loader::DidFail(uint64_t identifier,
+ const ResourceError& error) {
if (fetch_request_data_ && fetch_request_data_->TrustTokenParams()) {
HistogramNetErrorForTrustTokensOperation(
fetch_request_data_->TrustTokenParams()->type, error.ErrorCode());
@@ -496,15 +522,22 @@ void FetchManager::Loader::DidFail(const ResourceError& error) {
if (error.TrustTokenOperationError() !=
network::mojom::blink::TrustTokenOperationStatus::kOk) {
Failed(String(),
- TrustTokenErrorToDOMException(error.TrustTokenOperationError()));
+ TrustTokenErrorToDOMException(error.TrustTokenOperationError()),
+ IdentifiersFactory::SubresourceRequestId(identifier));
return;
}
- Failed(String(), nullptr);
+ auto issue_id = error.CorsErrorStatus()
+ ? absl::optional<base::UnguessableToken>(
+ error.CorsErrorStatus()->issue_id)
+ : absl::nullopt;
+ Failed(String(), nullptr,
+ IdentifiersFactory::SubresourceRequestId(identifier), issue_id);
}
-void FetchManager::Loader::DidFailRedirectCheck() {
- Failed(String(), nullptr);
+void FetchManager::Loader::DidFailRedirectCheck(uint64_t identifier) {
+ Failed(String(), nullptr,
+ IdentifiersFactory::SubresourceRequestId(identifier));
}
void FetchManager::Loader::Start() {
@@ -661,45 +694,56 @@ void FetchManager::Loader::PerformSchemeFetch() {
void FetchManager::Loader::FileIssueAndPerformNetworkError(
RendererCorsIssueCode network_error,
int64_t identifier) {
+ auto issue_id = base::UnguessableToken::Create();
switch (network_error) {
- case RendererCorsIssueCode::kCorsDisabledScheme:
+ case RendererCorsIssueCode::kCorsDisabledScheme: {
+ AuditsIssue::ReportCorsIssue(
+ GetExecutionContext(), identifier, network_error,
+ fetch_request_data_->Url().GetString(),
+ fetch_request_data_->Origin()->ToString(),
+ fetch_request_data_->Url().Protocol(), issue_id);
+ PerformNetworkError(
+ "Fetch API cannot load " + fetch_request_data_->Url().GetString() +
+ ". URL scheme \"" + fetch_request_data_->Url().Protocol() +
+ "\" is not supported.",
+ issue_id);
+ break;
+ }
+ case RendererCorsIssueCode::kDisallowedByMode: {
AuditsIssue::ReportCorsIssue(GetExecutionContext(), identifier,
network_error,
fetch_request_data_->Url().GetString(),
fetch_request_data_->Origin()->ToString(),
- fetch_request_data_->Url().Protocol());
+ WTF::g_empty_string, issue_id);
PerformNetworkError(
"Fetch API cannot load " + fetch_request_data_->Url().GetString() +
- ". URL scheme \"" + fetch_request_data_->Url().Protocol() +
- "\" is not supported.");
- break;
- case RendererCorsIssueCode::kDisallowedByMode:
- AuditsIssue::ReportCorsIssue(
- GetExecutionContext(), identifier, network_error,
- fetch_request_data_->Url().GetString(),
- fetch_request_data_->Origin()->ToString(), WTF::g_empty_string);
- PerformNetworkError("Fetch API cannot load " +
- fetch_request_data_->Url().GetString() +
- ". Request mode is \"same-origin\" but the URL\'s "
- "origin is not same as the request origin " +
- fetch_request_data_->Origin()->ToString() + ".");
+ ". Request mode is \"same-origin\" but the URL\'s "
+ "origin is not same as the request origin " +
+ fetch_request_data_->Origin()->ToString() + ".",
+ issue_id);
break;
- case RendererCorsIssueCode::kNoCorsRedirectModeNotFollow:
- AuditsIssue::ReportCorsIssue(
- GetExecutionContext(), identifier, network_error,
- fetch_request_data_->Url().GetString(),
- fetch_request_data_->Origin()->ToString(), WTF::g_empty_string);
- PerformNetworkError("Fetch API cannot load " +
- fetch_request_data_->Url().GetString() +
- ". Request mode is \"no-cors\" but the redirect mode "
- "is not \"follow\".");
+ }
+ case RendererCorsIssueCode::kNoCorsRedirectModeNotFollow: {
+ AuditsIssue::ReportCorsIssue(GetExecutionContext(), identifier,
+ network_error,
+ fetch_request_data_->Url().GetString(),
+ fetch_request_data_->Origin()->ToString(),
+ WTF::g_empty_string, issue_id);
+ PerformNetworkError(
+ "Fetch API cannot load " + fetch_request_data_->Url().GetString() +
+ ". Request mode is \"no-cors\" but the redirect mode "
+ "is not \"follow\".",
+ issue_id);
break;
+ }
}
}
-void FetchManager::Loader::PerformNetworkError(const String& message) {
- Failed(message, nullptr);
+void FetchManager::Loader::PerformNetworkError(
+ const String& message,
+ absl::optional<base::UnguessableToken> issue_id) {
+ Failed(message, nullptr, absl::nullopt, issue_id);
}
void FetchManager::Loader::PerformHTTPFetch() {
@@ -842,14 +886,22 @@ void FetchManager::Loader::PerformDataFetch() {
threadable_loader_->Start(std::move(request));
}
-void FetchManager::Loader::Failed(const String& message,
- DOMException* dom_exception) {
+void FetchManager::Loader::Failed(
+ const String& message,
+ DOMException* dom_exception,
+ absl::optional<String> devtools_request_id,
+ absl::optional<base::UnguessableToken> issue_id) {
if (failed_ || finished_)
return;
failed_ = true;
if (execution_context_->IsContextDestroyed())
return;
- if (!message.IsEmpty()) {
+ bool issue_only =
+ base::FeatureList::IsEnabled(blink::features::kCORSErrorsIssueOnly) &&
+ issue_id;
+ if (!message.IsEmpty() && !issue_only) {
+ // CORS issues are reported via network service instrumentation, with the
+ // exception of early errors reported in FileIssueAndPerformNetworkError.
execution_context_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kJavaScript,
mojom::ConsoleMessageLevel::kError, message));
@@ -860,8 +912,25 @@ void FetchManager::Loader::Failed(const String& message,
if (dom_exception) {
resolver_->Reject(dom_exception);
} else {
- resolver_->Reject(V8ThrowException::CreateTypeError(state->GetIsolate(),
- "Failed to fetch"));
+ v8::Local<v8::Value> value = exception_.NewLocal(state->GetIsolate());
+ exception_.Clear();
+ if (RuntimeEnabledFeatures::ExceptionMetaDataForDevToolsEnabled()) {
+ ThreadDebugger* debugger = ThreadDebugger::From(state->GetIsolate());
+ if (devtools_request_id) {
+ debugger->GetV8Inspector()->associateExceptionData(
+ state->GetContext(), value,
+ V8AtomicString(state->GetIsolate(), "requestId"),
+ V8String(state->GetIsolate(), *devtools_request_id));
+ }
+ if (issue_id) {
+ debugger->GetV8Inspector()->associateExceptionData(
+ state->GetContext(), value,
+ V8AtomicString(state->GetIsolate(), "issueId"),
+ V8String(state->GetIsolate(),
+ IdentifiersFactory::IdFromToken(*issue_id)));
+ }
+ }
+ resolver_->Reject(value);
}
}
NotifyFinished();
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 65d47eef3ca..02b690998d3 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_FETCH_REQUEST_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_FETCH_REQUEST_DATA_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -13,6 +12,7 @@
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
@@ -45,6 +45,8 @@ class CORE_EXPORT FetchRequestData final
FetchRequestData* Pass(ScriptState*);
explicit FetchRequestData(ExecutionContext* execution_context);
+ FetchRequestData(const FetchRequestData&) = delete;
+ FetchRequestData& operator=(const FetchRequestData&) = delete;
~FetchRequestData();
void SetMethod(AtomicString method) { method_ = method; }
@@ -182,8 +184,6 @@ class CORE_EXPORT FetchRequestData final
base::UnguessableToken window_id_;
Member<ExecutionContext> execution_context_;
bool allow_http1_for_streaming_upload_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(FetchRequestData);
};
} // namespace blink
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 35c2aa55b26..41bc14e8033 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
@@ -174,6 +174,11 @@ String FetchResponseData::InternalMIMEType() const {
return mime_type_;
}
+bool FetchResponseData::RequestIncludeCredentials() const {
+ return internal_response_ ? internal_response_->RequestIncludeCredentials()
+ : request_include_credentials_;
+}
+
void FetchResponseData::SetURLList(const Vector<KURL>& url_list) {
url_list_ = url_list;
}
@@ -208,6 +213,7 @@ FetchResponseData* FetchResponseData::Clone(ScriptState* script_state,
new_response->alpn_negotiated_protocol_ = alpn_negotiated_protocol_;
new_response->was_fetched_via_spdy_ = was_fetched_via_spdy_;
new_response->has_range_requested_ = has_range_requested_;
+ new_response->request_include_credentials_ = request_include_credentials_;
if (auth_challenge_info_) {
new_response->auth_challenge_info_ =
std::make_unique<net::AuthChallengeInfo>(*auth_challenge_info_);
@@ -286,6 +292,7 @@ mojom::blink::FetchAPIResponsePtr FetchResponseData::PopulateFetchAPIResponse(
response->alpn_negotiated_protocol = alpn_negotiated_protocol_;
response->was_fetched_via_spdy = was_fetched_via_spdy_;
response->has_range_requested = has_range_requested_;
+ response->request_include_credentials = request_include_credentials_;
for (const auto& header : HeaderList()->List())
response->headers.insert(header.first, header.second);
response->parsed_headers = ParseHeaders(
@@ -367,6 +374,7 @@ void FetchResponseData::InitFromResourceResponse(
}
SetAuthChallengeInfo(response.AuthChallengeInfo());
+ SetRequestIncludeCredentials(response.RequestIncludeCredentials());
}
FetchResponseData::FetchResponseData(Type type,
@@ -383,7 +391,8 @@ FetchResponseData::FetchResponseData(Type type,
connection_info_(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
alpn_negotiated_protocol_("unknown"),
was_fetched_via_spdy_(false),
- has_range_requested_(false) {}
+ has_range_requested_(false),
+ request_include_credentials_(true) {}
void FetchResponseData::SetAuthChallengeInfo(
const absl::optional<net::AuthChallengeInfo>& auth_challenge_info) {
@@ -393,6 +402,12 @@ void FetchResponseData::SetAuthChallengeInfo(
}
}
+void FetchResponseData::SetRequestIncludeCredentials(
+ bool request_include_credentials) {
+ DCHECK(!internal_response_);
+ request_include_credentials_ = request_include_credentials;
+}
+
void FetchResponseData::ReplaceBodyStreamBuffer(BodyStreamBuffer* buffer) {
if (type_ == Type::kBasic || type_ == Type::kCors) {
DCHECK(internal_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 d5e11918daf..473687334b7 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "net/http/http_response_info.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
@@ -48,6 +47,8 @@ class CORE_EXPORT FetchResponseData final
network::mojom::FetchResponseSource,
uint16_t,
AtomicString);
+ FetchResponseData(const FetchResponseData&) = delete;
+ FetchResponseData& operator=(const FetchResponseData&) = delete;
FetchResponseData* CreateBasicFilteredResponse() const;
FetchResponseData* CreateCorsFilteredResponse(
@@ -84,6 +85,7 @@ class CORE_EXPORT FetchResponseData final
return cors_exposed_header_names_;
}
bool HasRangeRequested() const { return has_range_requested_; }
+ bool RequestIncludeCredentials() const;
int64_t GetPadding() const { return padding_; }
void SetPadding(int64_t padding) { padding_ = padding; }
@@ -126,6 +128,7 @@ class CORE_EXPORT FetchResponseData final
}
void SetAuthChallengeInfo(
const absl::optional<net::AuthChallengeInfo>& auth_challenge_info);
+ void SetRequestIncludeCredentials(bool request_include_credentials);
// If the type is Default, replaces |buffer_|.
// If the type is Basic or CORS, replaces |buffer_| and
@@ -166,13 +169,16 @@ class CORE_EXPORT FetchResponseData final
HTTPHeaderSet cors_exposed_header_names_;
net::HttpResponseInfo::ConnectionInfo connection_info_;
AtomicString alpn_negotiated_protocol_;
- bool was_fetched_via_spdy_;
- bool has_range_requested_;
// |auth_challenge_info_| is a std::unique_ptr instead of absl::optional
// |because this member is empty in most cases.
std::unique_ptr<net::AuthChallengeInfo> auth_challenge_info_;
- DISALLOW_COPY_AND_ASSIGN(FetchResponseData);
+ bool was_fetched_via_spdy_ : 1;
+ bool has_range_requested_ : 1;
+ // The request's |includeCredentials| value from the "HTTP-network fetch"
+ // algorithm.
+ // See: https://fetch.spec.whatwg.org/#concept-http-network-fetch
+ bool request_include_credentials_ : 1;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
index 7654befd00e..946e1107390 100644
--- a/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
+#include "base/cxx17_backports.h"
#include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
@@ -48,6 +48,8 @@ class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
&SimpleDataPipeGetter::OnMojoDisconnect, WTF::Unretained(this)));
receivers_.Add(this, std::move(receiver));
}
+ SimpleDataPipeGetter(const SimpleDataPipeGetter&) = delete;
+ SimpleDataPipeGetter& operator=(const SimpleDataPipeGetter&) = delete;
~SimpleDataPipeGetter() override = default;
// network::mojom::DataPipeGetter implementation:
@@ -70,8 +72,6 @@ class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
private:
String str_;
mojo::ReceiverSet<network::mojom::blink::DataPipeGetter> receivers_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleDataPipeGetter);
};
scoped_refptr<EncodedFormData> ComplexFormData() {
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 34cb98c9687..b55f86121ac 100644
--- a/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
@@ -56,11 +56,7 @@ class GlobalFetchImpl final : public GarbageCollected<GlobalFetchImpl<T>>,
fetch_manager_(MakeGarbageCollected<FetchManager>(execution_context)) {}
ScriptPromise Fetch(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestInfo& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const RequestInit* init,
ExceptionState& exception_state) override {
fetch_count_ += 1;
@@ -127,11 +123,7 @@ void GlobalFetch::ScopedFetcher::Trace(Visitor* visitor) const {}
ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
LocalDOMWindow& window,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestInfo& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const RequestInit* init,
ExceptionState& exception_state) {
UseCounter::Count(window.GetExecutionContext(), WebFeature::kFetch);
@@ -145,11 +137,7 @@ ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
WorkerGlobalScope& worker,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestInfo& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const RequestInit* init,
ExceptionState& exception_state) {
UseCounter::Count(worker.GetExecutionContext(), WebFeature::kFetch);
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 611fcf3d959..e0df4feac90 100644
--- a/chromium/third_party/blink/renderer/core/fetch/global_fetch.h
+++ b/chromium/third_party/blink/renderer/core/fetch/global_fetch.h
@@ -27,11 +27,7 @@ class CORE_EXPORT GlobalFetch {
virtual ~ScopedFetcher();
virtual ScriptPromise Fetch(ScriptState*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestInfo&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const RequestInit*,
ExceptionState&) = 0;
@@ -45,7 +41,6 @@ class CORE_EXPORT GlobalFetch {
void Trace(Visitor*) const override;
};
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static ScriptPromise fetch(ScriptState* script_state,
LocalDOMWindow& window,
const V8RequestInfo* input,
@@ -56,18 +51,6 @@ class CORE_EXPORT GlobalFetch {
const V8RequestInfo* input,
const RequestInit* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static ScriptPromise fetch(ScriptState*,
- LocalDOMWindow&,
- const RequestInfo&,
- const RequestInit*,
- ExceptionState&);
- static ScriptPromise fetch(ScriptState*,
- WorkerGlobalScope&,
- const RequestInfo&,
- const RequestInit*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/headers.cc b/chromium/third_party/blink/renderer/core/fetch/headers.cc
index 380a6fdc16e..a74e40990a7 100644
--- a/chromium/third_party/blink/renderer/core/fetch/headers.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/headers.cc
@@ -4,7 +4,6 @@
#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/v8_iterator_result_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_bytestringbytestringrecord_bytestringsequencesequence.h"
#include "third_party/blink/renderer/core/dom/iterator.h"
@@ -50,7 +49,6 @@ Headers* Headers::Create(ExceptionState&) {
return MakeGarbageCollected<Headers>();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Headers* Headers::Create(const V8HeadersInit* init,
ExceptionState& exception_state) {
// "The Headers(|init|) constructor, when invoked, must run these steps:"
@@ -61,18 +59,6 @@ Headers* Headers::Create(const V8HeadersInit* init,
// "3. Return |headers|."
return headers;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-Headers* Headers::Create(const HeadersInit& init,
- ExceptionState& exception_state) {
- // "The Headers(|init|) constructor, when invoked, must run these steps:"
- // "1. Let |headers| be a new Headers object whose guard is "none".
- Headers* headers = Create(exception_state);
- // "2. If |init| is given, fill headers with |init|. Rethrow any exception."
- headers->FillWith(init, exception_state);
- // "3. Return |headers|."
- return headers;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Headers* Headers::Create(FetchHeaderList* header_list) {
return MakeGarbageCollected<Headers>(header_list);
@@ -271,7 +257,6 @@ void Headers::FillWith(const Headers* object, ExceptionState& exception_state) {
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Headers::FillWith(const V8HeadersInit* init,
ExceptionState& exception_state) {
DCHECK_EQ(header_list_->size(), 0U);
@@ -288,20 +273,6 @@ void Headers::FillWith(const V8HeadersInit* init,
NOTREACHED();
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-// TODO(crbug.com/1181288): Remove the old IDL union version.
-void Headers::FillWith(const HeadersInit& init,
- ExceptionState& exception_state) {
- DCHECK_EQ(header_list_->size(), 0U);
- if (init.IsByteStringSequenceSequence()) {
- FillWith(init.GetAsByteStringSequenceSequence(), exception_state);
- } else if (init.IsByteStringByteStringRecord()) {
- FillWith(init.GetAsByteStringByteStringRecord(), exception_state);
- } else {
- NOTREACHED();
- }
-}
void Headers::FillWith(const Vector<Vector<String>>& object,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/core/fetch/headers.h b/chromium/third_party/blink/renderer/core/fetch/headers.h
index c91fb204af9..feccbaedc61 100644
--- a/chromium/third_party/blink/renderer/core/fetch/headers.h
+++ b/chromium/third_party/blink/renderer/core/fetch/headers.h
@@ -35,12 +35,8 @@ class CORE_EXPORT Headers final : public ScriptWrappable,
};
static Headers* Create(ExceptionState& exception_state);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Headers* Create(const V8HeadersInit* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Headers* Create(const HeadersInit&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Shares the FetchHeaderList. Called when creating a Request or Response.
static Headers* Create(FetchHeaderList*);
@@ -63,11 +59,7 @@ class CORE_EXPORT Headers final : public ScriptWrappable,
// These methods should only be called when size() would return 0.
void FillWith(const Headers*, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void FillWith(const V8HeadersInit* init, ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- // TODO(crbug.com/1181288): Remove the old IDL union version.
- void FillWith(const HeadersInit&, ExceptionState&);
// https://fetch.spec.whatwg.org/#concept-headers-remove-privileged-no-cors-request-headers
void RemovePrivilegedNoCorsRequestHeaders();
diff --git a/chromium/third_party/blink/renderer/core/fetch/multipart_parser.cc b/chromium/third_party/blink/renderer/core/fetch/multipart_parser.cc
index 43024b42f90..4564267228c 100644
--- a/chromium/third_party/blink/renderer/core/fetch/multipart_parser.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/multipart_parser.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/fetch/multipart_parser.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/multipart_parser.h b/chromium/third_party/blink/renderer/core/fetch/multipart_parser.h
index 259f76be0fb..76d4e5712aa 100644
--- a/chromium/third_party/blink/renderer/core/fetch/multipart_parser.h
+++ b/chromium/third_party/blink/renderer/core/fetch/multipart_parser.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_MULTIPART_PARSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_MULTIPART_PARSER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
@@ -43,6 +42,8 @@ class CORE_EXPORT MultipartParser final
};
MultipartParser(Vector<char> boundary, Client*);
+ MultipartParser(const MultipartParser&) = delete;
+ MultipartParser& operator=(const MultipartParser&) = delete;
bool AppendData(const char* bytes, size_t);
void Cancel();
bool Finish();
@@ -107,8 +108,6 @@ class CORE_EXPORT MultipartParser final
kCancelled,
kFinished
} state_;
-
- DISALLOW_COPY_AND_ASSIGN(MultipartParser);
};
} // namespace blink
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 29490358956..2e6626b769f 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
@@ -8,10 +8,11 @@
#include <algorithm>
+#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_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.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/scoped_persistent.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
@@ -53,7 +54,11 @@ class ReadableStreamBytesConsumer::OnFulfilled final : public ScriptFunction {
consumer_->OnRejected();
return ScriptValue();
}
- consumer_->OnRead(V8Uint8Array::ToImpl(value.As<v8::Object>()));
+ NonThrowableExceptionState exception_state;
+ consumer_->OnRead(
+ NativeValueTraits<MaybeShared<DOMUint8Array>>::NativeValue(
+ GetScriptState()->GetIsolate(), value, exception_state)
+ .Get());
return v;
}
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 5d948cae7fa..9382ee300bb 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
@@ -25,6 +25,9 @@ class ScriptState;
class CORE_EXPORT ReadableStreamBytesConsumer final : public BytesConsumer {
public:
ReadableStreamBytesConsumer(ScriptState*, ReadableStream*);
+ ReadableStreamBytesConsumer(const ReadableStreamBytesConsumer&) = delete;
+ ReadableStreamBytesConsumer& operator=(const ReadableStreamBytesConsumer&) =
+ delete;
~ReadableStreamBytesConsumer() override;
Result BeginRead(const char** buffer, size_t* available) override;
@@ -56,7 +59,6 @@ class CORE_EXPORT ReadableStreamBytesConsumer final : public BytesConsumer {
size_t pending_offset_ = 0;
PublicState state_ = PublicState::kReadableOrWaiting;
bool is_reading_ = false;
- DISALLOW_COPY_AND_ASSIGN(ReadableStreamBytesConsumer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.cc b/chromium/third_party/blink/renderer/core/fetch/request.cc
index f34116314d9..9cf7fe8c115 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request.cc
@@ -17,8 +17,6 @@
#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_readable_stream.h"
@@ -131,7 +129,11 @@ static BodyStreamBuffer* ExtractBody(ScriptState* script_state,
} 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>());
+ DOMArrayBuffer* array_buffer =
+ NativeValueTraits<DOMArrayBuffer>::NativeValue(isolate, body,
+ exception_state);
+ if (exception_state.HadException())
+ return nullptr;
if (!base::CheckedNumeric<wtf_size_t>(array_buffer->ByteLength())
.IsValid()) {
exception_state.ThrowRangeError(
@@ -145,7 +147,11 @@ static BodyStreamBuffer* ExtractBody(ScriptState* script_state,
// Avoid calling into V8 from the following constructor parameters, which
// is potentially unsafe.
DOMArrayBufferView* array_buffer_view =
- V8ArrayBufferView::ToImpl(body.As<v8::Object>());
+ NativeValueTraits<MaybeShared<DOMArrayBufferView>>::NativeValue(
+ isolate, body, exception_state)
+ .Get();
+ if (exception_state.HadException())
+ return nullptr;
if (!base::CheckedNumeric<wtf_size_t>(array_buffer_view->byteLength())
.IsValid()) {
exception_state.ThrowRangeError(
@@ -711,7 +717,6 @@ Request* Request::CreateRequestWithRequestOrString(
return r;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Request* Request::Create(ScriptState* script_state,
const V8RequestInfo* input,
const RequestInit* init,
@@ -729,17 +734,6 @@ Request* Request::Create(ScriptState* script_state,
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-Request* Request::Create(ScriptState* script_state,
- const RequestInfo& input,
- const RequestInit* init,
- ExceptionState& exception_state) {
- DCHECK(!input.IsNull());
- if (input.IsUSVString())
- return Create(script_state, input.GetAsUSVString(), init, exception_state);
- return Create(script_state, input.GetAsRequest(), init, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Request* Request::Create(ScriptState* script_state,
const String& input,
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.h b/chromium/third_party/blink/renderer/core/fetch/request.h
index a4f40dbe22c..2d583b97e24 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.h
+++ b/chromium/third_party/blink/renderer/core/fetch/request.h
@@ -10,7 +10,6 @@
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.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/request_or_usv_string.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/fetch/body.h"
@@ -28,8 +27,6 @@ class BodyStreamBuffer;
class ExceptionState;
class RequestInit;
-using RequestInfo = RequestOrUSVString;
-
class CORE_EXPORT Request final : public ScriptWrappable,
public ActiveScriptWrappable<Request>,
public Body {
@@ -42,17 +39,10 @@ class CORE_EXPORT Request final : public ScriptWrappable,
// These "create" function must be called with entering an appropriate
// V8 context.
// From Request.idl:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Request* Create(ScriptState* script_state,
const V8RequestInfo* input,
const RequestInit* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Request* Create(ScriptState*,
- const RequestInfo&,
- const RequestInit*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Request* Create(ScriptState*, const String&, ExceptionState&);
static Request* Create(ScriptState*,
@@ -71,6 +61,8 @@ class CORE_EXPORT Request final : public ScriptWrappable,
Request(ScriptState*, FetchRequestData*, Headers*, AbortSignal*);
Request(ScriptState*, FetchRequestData*);
+ Request(const Request&) = delete;
+ Request& operator=(const Request&) = delete;
static absl::optional<network::mojom::CredentialsMode> ParseCredentialsMode(
const String& credentials_mode);
@@ -126,7 +118,6 @@ class CORE_EXPORT Request final : public ScriptWrappable,
const Member<FetchRequestData> request_;
const Member<Headers> headers_;
const Member<AbortSignal> signal_;
- DISALLOW_COPY_AND_ASSIGN(Request);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.idl b/chromium/third_party/blink/renderer/core/fetch/request.idl
index c91e6366305..da29c735e0f 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/request.idl
@@ -51,7 +51,7 @@ enum ReferrerPolicy {
[MeasureAs=RequestIsHistoryNavigation] readonly attribute boolean isHistoryNavigation;
[RaisesException, CallWith=ScriptState, DoNotTestNewObject, NewObject] Request clone();
- [RuntimeEnabled=FetchUploadStreaming] readonly attribute ReadableStream? body;
+ [Affects=Everything, RuntimeEnabled=FetchUploadStreaming] readonly attribute ReadableStream? body;
};
Request includes Body;
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.cc b/chromium/third_party/blink/renderer/core/fetch/response.cc
index e2ce5c1ddd5..f2433442bec 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/response.cc
@@ -12,8 +12,6 @@
#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_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_readable_stream.h"
@@ -158,11 +156,16 @@ Response* Response::Create(ScriptState* script_state,
} 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>());
+ DOMArrayBuffer* array_buffer =
+ NativeValueTraits<DOMArrayBuffer>::NativeValue(isolate, body,
+ exception_state);
+ if (exception_state.HadException())
+ return nullptr;
if (!base::CheckedNumeric<wtf_size_t>(array_buffer->ByteLength())
.IsValid()) {
exception_state.ThrowRangeError(
"The provided ArrayBuffer exceeds the maximum supported size");
+ return nullptr;
} else {
body_buffer = BodyStreamBuffer::Create(
script_state,
@@ -173,11 +176,16 @@ Response* Response::Create(ScriptState* script_state,
// Avoid calling into V8 from the following constructor parameters, which
// is potentially unsafe.
DOMArrayBufferView* array_buffer_view =
- V8ArrayBufferView::ToImpl(body.As<v8::Object>());
+ NativeValueTraits<MaybeShared<DOMArrayBufferView>>::NativeValue(
+ isolate, body, exception_state)
+ .Get();
+ if (exception_state.HadException())
+ return nullptr;
if (!base::CheckedNumeric<wtf_size_t>(array_buffer_view->byteLength())
.IsValid()) {
exception_state.ThrowRangeError(
"The provided ArrayBufferView exceeds the maximum supported size");
+ return nullptr;
} else {
body_buffer = BodyStreamBuffer::Create(
script_state,
@@ -390,6 +398,8 @@ FetchResponseData* Response::CreateUnfilteredFetchResponseDataWithoutBody(
WTF::AtomicString(fetch_api_response.alpn_negotiated_protocol));
response->SetWasFetchedViaSpdy(fetch_api_response.was_fetched_via_spdy);
response->SetHasRangeRequested(fetch_api_response.has_range_requested);
+ response->SetRequestIncludeCredentials(
+ fetch_api_response.request_include_credentials);
for (const auto& header : fetch_api_response.headers)
response->HeaderList()->Append(header.key, header.value);
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.h b/chromium/third_party/blink/renderer/core/fetch/response.h
index d984c40c1cf..bf2ff859a19 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.h
+++ b/chromium/third_party/blink/renderer/core/fetch/response.h
@@ -69,6 +69,8 @@ class CORE_EXPORT Response final : public ScriptWrappable,
explicit Response(ExecutionContext*);
Response(ExecutionContext*, FetchResponseData*);
Response(ExecutionContext*, FetchResponseData*, Headers*);
+ Response(const Response&) = delete;
+ Response& operator=(const Response&) = delete;
const FetchResponseData* GetResponse() const { return response_; }
@@ -128,7 +130,6 @@ class CORE_EXPORT Response final : public ScriptWrappable,
private:
const Member<FetchResponseData> response_;
const Member<Headers> headers_;
- DISALLOW_COPY_AND_ASSIGN(Response);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.idl b/chromium/third_party/blink/renderer/core/fetch/response.idl
index 1ae9071c6c5..b5508d672a7 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/response.idl
@@ -25,7 +25,7 @@ enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredire
[RaisesException, CallWith=ScriptState, DoNotTestNewObject, NewObject] Response clone();
- [MeasureAs=FetchBodyStream] readonly attribute ReadableStream? body;
+ [Affects=Everything, MeasureAs=FetchBodyStream] readonly attribute ReadableStream? body;
};
Response includes Body;
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.cc b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
index a441676e87f..067c3527d67 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/blob.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
@@ -114,13 +114,7 @@ Blob::~Blob() = default;
// static
Blob* Blob::Create(ExecutionContext* context,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8BlobPart>>& blob_parts,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<
- ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&
- blob_parts,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const BlobPropertyBag* options) {
DCHECK(options->hasType());
DCHECK(options->hasEndings());
@@ -154,7 +148,6 @@ Blob* Blob::Create(const unsigned char* data,
BlobDataHandle::Create(std::move(blob_data), blob_size));
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
void Blob::PopulateBlobData(BlobData* blob_data,
const HeapVector<Member<V8BlobPart>>& parts,
@@ -185,31 +178,6 @@ void Blob::PopulateBlobData(BlobData* blob_data,
}
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-void Blob::PopulateBlobData(
- BlobData* blob_data,
- const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& parts,
- bool normalize_line_endings_to_native) {
- for (const auto& item : parts) {
- if (item.IsArrayBuffer()) {
- DOMArrayBuffer* array_buffer = item.GetAsArrayBuffer();
- blob_data->AppendBytes(array_buffer->Data(), array_buffer->ByteLength());
- } else if (item.IsArrayBufferView()) {
- auto&& array_buffer_view = item.GetAsArrayBufferView();
- blob_data->AppendBytes(array_buffer_view->BaseAddress(),
- array_buffer_view->byteLength());
- } else if (item.IsBlob()) {
- item.GetAsBlob()->AppendTo(*blob_data);
- } else if (item.IsUSVString()) {
- blob_data->AppendText(item.GetAsUSVString(),
- normalize_line_endings_to_native);
- } else {
- NOTREACHED();
- }
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
void Blob::ClampSliceOffsets(uint64_t size, int64_t& start, int64_t& end) {
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.h b/chromium/third_party/blink/renderer/core/fileapi/blob.h
index 10740b72522..2b3331d6a89 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/blob.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.h
@@ -33,7 +33,6 @@
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/bindings/pending_remote.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/v8_typedefs.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
@@ -62,16 +61,9 @@ class CORE_EXPORT Blob : public ScriptWrappable,
return MakeGarbageCollected<Blob>(BlobDataHandle::Create());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Blob* Create(ExecutionContext* execution_context,
const HeapVector<Member<V8BlobPart>>& blob_parts,
const BlobPropertyBag* options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Blob* Create(
- ExecutionContext*,
- const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&,
- const BlobPropertyBag*);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static Blob* Create(const unsigned char* data,
size_t size,
@@ -128,16 +120,9 @@ class CORE_EXPORT Blob : public ScriptWrappable,
bool IsBlob() const override { return true; }
protected:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static void PopulateBlobData(BlobData* blob_data,
const HeapVector<Member<V8BlobPart>>& parts,
bool normalize_line_endings_to_native);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static void PopulateBlobData(
- BlobData*,
- const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& parts,
- bool normalize_line_endings_to_native);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static void ClampSliceOffsets(uint64_t size, int64_t& start, int64_t& end);
// Called by the Blob and File constructors when processing the 'type'
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file.cc b/chromium/third_party/blink/renderer/core/fileapi/file.cc
index 8e402841405..7603f3d85f3 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file.cc
@@ -126,13 +126,7 @@ static std::unique_ptr<BlobData> CreateBlobDataForFileSystemURL(
// static
File* File::Create(ExecutionContext* context,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8BlobPart>>& file_bits,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<
- ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&
- file_bits,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& file_name,
const FilePropertyBag* options) {
DCHECK(options->hasType());
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file.h b/chromium/third_party/blink/renderer/core/fileapi/file.h
index 7c21e6bc889..d70a95cc9b2 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/file.h
@@ -30,7 +30,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.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/core/core_export.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -63,18 +62,10 @@ class CORE_EXPORT File final : public Blob {
enum UserVisibility { kIsUserVisible, kIsNotUserVisible };
// Constructor in File.idl
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static File* Create(ExecutionContext*,
const HeapVector<Member<V8BlobPart>>& file_bits,
const String& file_name,
const FilePropertyBag* options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static File* Create(
- ExecutionContext*,
- const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&,
- const String& file_name,
- const FilePropertyBag*);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// For deserialization.
static File* CreateFromSerialization(
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 8a8d09ac33b..cb0c89444e3 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
@@ -33,7 +33,6 @@
#include "base/auto_reset.h"
#include "base/timer/elapsed_timer.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_string.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -359,7 +358,6 @@ void FileReader::abort() {
ThrottlingController::FinishReader(GetExecutionContext(), this, final_step);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionArrayBufferOrString* FileReader::result() const {
if (error_ || !loader_)
return nullptr;
@@ -378,24 +376,6 @@ V8UnionArrayBufferOrString* FileReader::result() const {
return MakeGarbageCollected<V8UnionArrayBufferOrString>(
loader_->StringResult());
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void FileReader::result(StringOrArrayBuffer& result_attribute) const {
- if (error_ || !loader_)
- return;
-
- // Only set the result after |loader_| has finished loading which means that
- // FileReader::DidFinishLoading() has also been called. This ensures that the
- // result is not available until just before the kLoad event is fired.
- if (!loader_->HasFinishedLoading() || state_ != ReadyState::kDone) {
- return;
- }
-
- if (read_type_ == FileReaderLoader::kReadAsArrayBuffer)
- result_attribute.SetArrayBuffer(loader_->ArrayBufferResult());
- else
- result_attribute.SetString(loader_->StringResult());
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void FileReader::Terminate() {
if (loader_) {
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader.h b/chromium/third_party/blink/renderer/core/fileapi/file_reader.h
index 5217b9ee846..6b2f64c13b4 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.h
@@ -49,7 +49,6 @@ namespace blink {
class Blob;
class ExceptionState;
class ExecutionContext;
-class StringOrArrayBuffer;
class V8UnionArrayBufferOrString;
enum class FileErrorCode;
@@ -76,11 +75,7 @@ class CORE_EXPORT FileReader final : public EventTargetWithInlineData,
ReadyState getReadyState() const { return state_; }
DOMException* error() { return error_; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionArrayBufferOrString* result() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void result(StringOrArrayBuffer& result_attribute) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
// ExecutionContextLifecycleObserver
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 10cf001b137..eead04ffbf7 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
@@ -27,9 +27,11 @@
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "base/metrics/histogram_macros.h"
+#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.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/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -77,7 +79,8 @@ String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
mojo::PendingRemote<mojom::blink::Blob> blob_remote;
mojo::PendingReceiver<mojom::blink::Blob> blob_receiver =
blob_remote.InitWithNewPipeAndPassReceiver();
- url_store_->Register(std::move(blob_remote), url);
+ url_store_->Register(std::move(blob_remote), url,
+ GetExecutionContext()->GetAgentClusterID());
mojo_urls_.insert(url_string);
registrable->CloneMojoBlob(std::move(blob_receiver));
} else {
@@ -122,7 +125,20 @@ void PublicURLManager::Resolve(
return;
DCHECK(url.ProtocolIs("blob"));
- url_store_->ResolveAsURLLoaderFactory(url, std::move(factory_receiver));
+ url_store_->ResolveAsURLLoaderFactory(
+ url, std::move(factory_receiver),
+ WTF::Bind(
+ [](ExecutionContext* execution_context,
+ const absl::optional<base::UnguessableToken>&
+ unsafe_agent_cluster_id) {
+ if (execution_context->GetAgentClusterID() !=
+ unsafe_agent_cluster_id) {
+ execution_context->CountUse(
+ WebFeature::
+ kBlobStoreAccessAcrossAgentClustersInResolveAsURLLoaderFactory);
+ }
+ },
+ WrapPersistent(GetExecutionContext())));
}
void PublicURLManager::Resolve(
@@ -132,7 +148,20 @@ void PublicURLManager::Resolve(
return;
DCHECK(url.ProtocolIs("blob"));
- url_store_->ResolveForNavigation(url, std::move(token_receiver));
+ url_store_->ResolveForNavigation(
+ url, std::move(token_receiver),
+ WTF::Bind(
+ [](ExecutionContext* execution_context,
+ const absl::optional<base::UnguessableToken>&
+ unsafe_agent_cluster_id) {
+ if (execution_context->GetAgentClusterID() !=
+ unsafe_agent_cluster_id) {
+ execution_context->CountUse(
+ WebFeature::
+ kBlobStoreAccessAcrossAgentClustersInResolveForNavigation);
+ }
+ },
+ WrapPersistent(GetExecutionContext())));
}
void PublicURLManager::ContextDestroyed() {
diff --git a/chromium/third_party/blink/renderer/core/frame/DEPS b/chromium/third_party/blink/renderer/core/frame/DEPS
index 0f676c48676..dfc678526a1 100644
--- a/chromium/third_party/blink/renderer/core/frame/DEPS
+++ b/chromium/third_party/blink/renderer/core/frame/DEPS
@@ -27,8 +27,12 @@ specific_include_rules = {
"local_frame\.cc": [
"+ui/gfx/transform.h"
],
+ "local_frame_ukm_aggregator_test\.cc": [
+ "+base/metrics/statistics_recorder.h"
+ ],
"local_frame_view\.cc": [
"+base/timer/lap_timer.h",
+ "+cc/document_transition/document_transition_request.h",
"+cc/tiles/frame_viewer_instrumentation.h",
"+components/paint_preview/common/paint_preview_tracker.h",
],
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 e93aa2de5cd..6a30198f1e7 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_AD_TRACKER_H_
#include "base/feature_list.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/probe/async_task_id.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
@@ -89,6 +88,8 @@ class CORE_EXPORT AdTracker : public GarbageCollected<AdTracker> {
void Shutdown();
explicit AdTracker(LocalFrame*);
+ AdTracker(const AdTracker&) = delete;
+ AdTracker& operator=(const AdTracker&) = delete;
virtual ~AdTracker();
protected:
@@ -132,8 +133,6 @@ class CORE_EXPORT AdTracker : public GarbageCollected<AdTracker> {
// but also at the previous asynchronous stacks that caused this current
// callstack to run (e.g., registered callbacks).
const bool async_stack_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(AdTracker);
};
} // namespace blink
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 fa6c51724f3..372c808af6c 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
@@ -173,6 +173,16 @@ class TestAdTracker : public AdTracker {
String url_to_wait_for_;
};
+void SetIsAdSubframe(LocalFrame* frame) {
+ DCHECK(frame);
+ blink::FrameAdEvidence ad_evidence(frame->Parent() &&
+ frame->Parent()->IsAdSubframe());
+ ad_evidence.set_created_by_ad_script(
+ mojom::FrameCreationStackEvidence::kCreatedByAdScript);
+ ad_evidence.set_is_complete();
+ frame->SetAdEvidence(ad_evidence);
+}
+
} // namespace
class AdTrackerTest : public testing::Test {
@@ -435,7 +445,7 @@ TEST_F(AdTrackerSimTest, ScriptDetectedByContext) {
main_resource_->Complete("<body><iframe></iframe></body>");
auto* child_frame =
To<LocalFrame>(GetDocument().GetFrame()->Tree().FirstChild());
- child_frame->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ SetIsAdSubframe(child_frame);
// Now run unknown script in the child's context. It should be considered an
// ad based on context alone.
@@ -523,7 +533,7 @@ TEST_F(AdTrackerSimTest, AdResourceDetectedByContext) {
"<body><iframe src='ad_frame.html'></iframe></body>");
auto* child_frame =
To<LocalFrame>(GetDocument().GetFrame()->Tree().FirstChild());
- child_frame->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ SetIsAdSubframe(child_frame);
// Load a resource from the frame. It should be detected as an ad resource due
// to its context.
@@ -562,7 +572,7 @@ TEST_F(AdTrackerSimTest, InlineAdScriptRunningInNonAdContext) {
// Verify that the new frame is considered created by ad script then set it
// as an ad subframe. This emulates the embedder tagging a frame as an ad.
EXPECT_TRUE(child_frame->IsSubframeCreatedByAdScript());
- child_frame->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ SetIsAdSubframe(child_frame);
// Create a new sibling frame to the ad frame. The ad context calls the non-ad
// context's (top frame) appendChild.
@@ -757,7 +767,7 @@ TEST_F(AdTrackerSimTest, FrameLoadedWhileExecutingAdScript) {
// Verify that the new frame is considered created by ad script then set it
// as an ad subframe. This emulates the SubresourceFilterAgent's tagging.
EXPECT_TRUE(child_frame->IsSubframeCreatedByAdScript());
- child_frame->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ SetIsAdSubframe(child_frame);
vanilla_page.Complete("<img src=vanilla_img.jpg></img>");
vanilla_image.Complete("");
@@ -979,7 +989,7 @@ TEST_P(AdTrackerVanillaOrAdSimTest, ExternalStylesheetInFrame) {
if (IsAdRun()) {
auto* subframe =
To<LocalFrame>(GetDocument().GetFrame()->Tree().FirstChild());
- subframe->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ SetIsAdSubframe(subframe);
}
frame.Complete(kPageWithVanillaExternalStylesheet);
@@ -1062,7 +1072,7 @@ TEST_P(AdTrackerVanillaOrAdSimTest, StyleTagInSubframe) {
if (IsAdRun()) {
auto* subframe =
To<LocalFrame>(GetDocument().GetFrame()->Tree().FirstChild());
- subframe->SetIsAdSubframe(blink::mojom::AdFrameType::kRootAd);
+ SetIsAdSubframe(subframe);
}
frame.Complete(kPageWithStyleTagLoadingVanillaResources);
diff --git a/chromium/third_party/blink/renderer/core/frame/attribution_reporting.cc b/chromium/third_party/blink/renderer/core/frame/attribution_reporting.cc
new file mode 100644
index 00000000000..5f9e28486e6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/attribution_reporting.cc
@@ -0,0 +1,112 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/frame/attribution_reporting.h"
+
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/navigation/impression.h"
+#include "third_party/blink/public/platform/impression_conversions.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_attribution_source_params.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/html/conversion_measurement_parsing.h"
+
+namespace blink {
+
+namespace {
+
+void HandleRegisterImpressionError(
+ ExceptionState& exception_state,
+ mojom::blink::RegisterImpressionError error) {
+ switch (error) {
+ case mojom::blink::RegisterImpressionError::kNotAllowed:
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotAllowedError,
+ "Not allowed.");
+ break;
+ case mojom::blink::RegisterImpressionError::kInsecureContext:
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotAllowedError,
+ "Cannot execute in an insecure context.");
+ break;
+ case mojom::blink::RegisterImpressionError::kInsecureAttributionDestination:
+ exception_state.ThrowTypeError(
+ "attributionDestination must be a trustworthy origin.");
+ break;
+ case mojom::blink::RegisterImpressionError::kInsecureAttributionReportTo:
+ exception_state.ThrowTypeError(
+ "attributionReportTo must be a trustworthy origin.");
+ break;
+ case mojom::blink::RegisterImpressionError::
+ kInvalidAttributionSourceEventId:
+ exception_state.ThrowTypeError(
+ "attributionSourceEventId must be parsable as an unsigned 64-bit "
+ "base-10 integer.");
+ break;
+ }
+}
+
+} // namespace
+
+// static
+const char AttributionReporting::kSupplementName[] = "AttributionReporting";
+
+// static
+AttributionReporting& AttributionReporting::attributionReporting(
+ LocalDOMWindow& window) {
+ AttributionReporting* attribution_reporting =
+ Supplement<LocalDOMWindow>::From<AttributionReporting>(window);
+ if (!attribution_reporting) {
+ attribution_reporting = MakeGarbageCollected<AttributionReporting>(window);
+ Supplement<LocalDOMWindow>::ProvideTo<AttributionReporting>(
+ window, attribution_reporting);
+ }
+ return *attribution_reporting;
+}
+
+AttributionReporting::AttributionReporting(LocalDOMWindow& window)
+ : Supplement<LocalDOMWindow>(window), conversion_host_(&window) {}
+
+void AttributionReporting::Trace(Visitor* visitor) const {
+ visitor->Trace(conversion_host_);
+ ScriptWrappable::Trace(visitor);
+ Supplement<LocalDOMWindow>::Trace(visitor);
+}
+
+ScriptPromise AttributionReporting::registerAttributionSource(
+ ScriptState* script_state,
+ const AttributionSourceParams* params,
+ ExceptionState& exception_state) {
+ // The PermissionsPolicy check, etc., occurs in the call to
+ // `GetImpressionForParams()`.
+ WebImpressionOrError web_impression_or_err =
+ GetImpressionForParams(GetSupplementable(), params);
+
+ if (auto* err = absl::get_if<mojom::blink::RegisterImpressionError>(
+ &web_impression_or_err)) {
+ HandleRegisterImpressionError(exception_state, *err);
+ return ScriptPromise();
+ }
+
+ const WebImpression* web_impression =
+ absl::get_if<WebImpression>(&web_impression_or_err);
+ DCHECK(web_impression);
+ blink::Impression impression =
+ ConvertWebImpressionToImpression(*web_impression);
+
+ if (!conversion_host_.is_bound()) {
+ GetSupplementable()
+ ->GetFrame()
+ ->GetRemoteNavigationAssociatedInterfaces()
+ ->GetInterface(conversion_host_.BindNewEndpointAndPassReceiver(
+ GetSupplementable()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ }
+
+ conversion_host_->RegisterImpression(impression);
+ return ScriptPromise::CastUndefined(script_state);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/attribution_reporting.h b/chromium/third_party/blink/renderer/core/frame/attribution_reporting.h
new file mode 100644
index 00000000000..ebc54d4f6b6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/attribution_reporting.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ATTRIBUTION_REPORTING_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ATTRIBUTION_REPORTING_H_
+
+#include "third_party/blink/public/mojom/conversions/conversions.mojom-blink.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/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class AttributionSourceParams;
+class LocalDOMWindow;
+
+class CORE_EXPORT AttributionReporting final
+ : public ScriptWrappable,
+ public Supplement<LocalDOMWindow> {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static const char kSupplementName[];
+
+ static AttributionReporting& attributionReporting(LocalDOMWindow&);
+
+ explicit AttributionReporting(LocalDOMWindow&);
+
+ void Trace(Visitor*) const override;
+
+ ScriptPromise registerAttributionSource(ScriptState* script_state,
+ const AttributionSourceParams* params,
+ ExceptionState& exception_state);
+
+ private:
+ HeapMojoAssociatedRemote<mojom::blink::ConversionHost> conversion_host_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ATTRIBUTION_REPORTING_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/attribution_reporting.idl b/chromium/third_party/blink/renderer/core/frame/attribution_reporting.idl
new file mode 100644
index 00000000000..ee7f789f8b0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/attribution_reporting.idl
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Interface for the Attribution Reporting API:
+//
+// https://github.com/WICG/conversion-measurement-api/
+[
+ Exposed=Window,
+ RuntimeEnabled=ConversionMeasurementEventSources,
+ SecureContext
+] interface AttributionReporting {
+ [CallWith=ScriptState, RaisesException] Promise<void> registerAttributionSource(AttributionSourceParams params);
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/attribution_source_params.idl b/chromium/third_party/blink/renderer/core/frame/attribution_source_params.idl
index 14c5ef90906..c05559567b5 100644
--- a/chromium/third_party/blink/renderer/core/frame/attribution_source_params.idl
+++ b/chromium/third_party/blink/renderer/core/frame/attribution_source_params.idl
@@ -7,6 +7,6 @@ dictionary AttributionSourceParams {
required USVString attributionDestination;
required DOMString attributionSourceEventId;
USVString attributionReportTo;
- unsigned long long attributionExpiry;
+ long long attributionExpiry;
long long attributionSourcePriority;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/build.gni b/chromium/third_party/blink/renderer/core/frame/build.gni
index 3aab0713c1a..b3a4168d966 100644
--- a/chromium/third_party/blink/renderer/core/frame/build.gni
+++ b/chromium/third_party/blink/renderer/core/frame/build.gni
@@ -5,6 +5,8 @@
blink_core_sources_frame = [
"ad_tracker.cc",
"ad_tracker.h",
+ "attribution_reporting.cc",
+ "attribution_reporting.h",
"bar_prop.cc",
"bar_prop.h",
"browser_controls.cc",
@@ -31,8 +33,6 @@ blink_core_sources_frame = [
"dactyloscoper.h",
"frame_content_as_text.h",
"frame_content_as_text.cc",
- "deprecated_schedule_style_recalc_during_layout.cc",
- "deprecated_schedule_style_recalc_during_layout.h",
"deprecation.cc",
"deprecation.h",
"deprecation_report_body.cc",
@@ -97,6 +97,8 @@ blink_core_sources_frame = [
"local_frame.cc",
"local_frame.h",
"local_frame_client.h",
+ "local_frame_mojo_handler.cc",
+ "local_frame_mojo_handler.h",
"local_frame_ukm_aggregator.cc",
"local_frame_ukm_aggregator.h",
"local_frame_view.cc",
diff --git a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc
index 8ccf309a539..0cd306a2c5e 100644
--- a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc
+++ b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc
@@ -95,12 +95,12 @@ ChildFrameCompositingHelper::PaintContentsToDisplayList() {
SkBitmap* sad_bitmap = child_frame_compositor_->GetSadPageBitmap();
if (sad_bitmap) {
- int paint_width = sad_bitmap->width() * device_scale_factor_;
- int paint_height = sad_bitmap->height() * device_scale_factor_;
+ float paint_width = sad_bitmap->width() * device_scale_factor_;
+ float paint_height = sad_bitmap->height() * device_scale_factor_;
if (layer_size.width() >= paint_width &&
layer_size.height() >= paint_height) {
- int x = (layer_size.width() - paint_width) / 2;
- int y = (layer_size.height() - paint_height) / 2;
+ float x = (layer_size.width() - paint_width) / 2.0f;
+ float y = (layer_size.height() - paint_height) / 2.0f;
if (device_scale_factor_ != 1.f) {
display_list->push<cc::SaveOp>();
display_list->push<cc::TranslateOp>(x, y);
diff --git a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h
index d6c4d87e000..9a9e84a2646 100644
--- a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h
+++ b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include "base/macros.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/surface_layer.h"
#include "components/viz/common/surfaces/surface_id.h"
@@ -25,6 +24,9 @@ class CORE_EXPORT ChildFrameCompositingHelper : public cc::ContentLayerClient {
public:
explicit ChildFrameCompositingHelper(
ChildFrameCompositor* child_frame_compositor);
+ ChildFrameCompositingHelper(const ChildFrameCompositingHelper&) = delete;
+ ChildFrameCompositingHelper& operator=(const ChildFrameCompositingHelper&) =
+ delete;
~ChildFrameCompositingHelper() override;
void SetSurfaceId(const viz::SurfaceId& surface_id,
@@ -46,8 +48,6 @@ class CORE_EXPORT ChildFrameCompositingHelper : public cc::ContentLayerClient {
scoped_refptr<cc::SurfaceLayer> surface_layer_;
scoped_refptr<cc::PictureLayer> crash_ui_layer_;
float device_scale_factor_ = 1.f;
-
- DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositingHelper);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
index a88021eeb68..8b18edffd06 100644
--- a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
@@ -19,6 +19,8 @@ class MockChildFrameCompositor : public ChildFrameCompositor {
constexpr int height = 32;
sad_page_bitmap_.allocN32Pixels(width, height);
}
+ MockChildFrameCompositor(const MockChildFrameCompositor&) = delete;
+ MockChildFrameCompositor& operator=(const MockChildFrameCompositor&) = delete;
const scoped_refptr<cc::Layer>& GetCcLayer() override { return layer_; }
@@ -32,8 +34,6 @@ class MockChildFrameCompositor : public ChildFrameCompositor {
private:
scoped_refptr<cc::Layer> layer_;
SkBitmap sad_page_bitmap_;
-
- DISALLOW_COPY_AND_ASSIGN(MockChildFrameCompositor);
};
viz::SurfaceId MakeSurfaceId(const viz::FrameSinkId& frame_sink_id,
@@ -50,6 +50,10 @@ viz::SurfaceId MakeSurfaceId(const viz::FrameSinkId& frame_sink_id,
class ChildFrameCompositingHelperTest : public testing::Test {
public:
ChildFrameCompositingHelperTest() : compositing_helper_(&compositor_) {}
+ ChildFrameCompositingHelperTest(const ChildFrameCompositingHelperTest&) =
+ delete;
+ ChildFrameCompositingHelperTest& operator=(
+ const ChildFrameCompositingHelperTest&) = delete;
~ChildFrameCompositingHelperTest() override {}
@@ -60,7 +64,6 @@ class ChildFrameCompositingHelperTest : public testing::Test {
private:
MockChildFrameCompositor compositor_;
ChildFrameCompositingHelper compositing_helper_;
- DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositingHelperTest);
};
// This test verifies that the fallback surfaceId is cleared when the child
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 ef20d0f9985..dced602f025 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
@@ -31,6 +31,7 @@
#include "base/debug/dump_without_crashing.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
@@ -763,11 +764,12 @@ bool ContentSecurityPolicy::AllowTrustedTypePolicy(
bool ContentSecurityPolicy::AllowTrustedTypeAssignmentFailure(
const String& message,
const String& sample,
- const String& sample_prefix) {
+ const String& sample_prefix,
+ absl::optional<base::UnguessableToken> issue_id) {
bool allow = true;
for (const auto& policy : policies_) {
allow &= CSPDirectiveListAllowTrustedTypeAssignmentFailure(
- *policy, this, message, sample, sample_prefix);
+ *policy, this, message, sample, sample_prefix, issue_id);
}
return allow;
}
@@ -988,7 +990,8 @@ void ContentSecurityPolicy::ReportViolation(
RedirectStatus redirect_status,
Element* element,
const String& source,
- const String& source_prefix) {
+ const String& source_prefix,
+ absl::optional<base::UnguessableToken> issue_id) {
DCHECK(violation_type == kURLViolation || blocked_url.IsEmpty());
// TODO(lukasza): Support sending reports from OOPIFs -
@@ -1042,7 +1045,7 @@ void ContentSecurityPolicy::ReportViolation(
ReportContentSecurityPolicyIssue(*violation_data, header_type, violation_type,
context_frame, element,
- source_location.get());
+ source_location.get(), issue_id);
}
void ContentSecurityPolicy::PostViolationReport(
@@ -1174,7 +1177,8 @@ void ContentSecurityPolicy::ReportContentSecurityPolicyIssue(
ContentSecurityPolicyViolationType violation_type,
LocalFrame* frame_ancestor,
Element* element,
- SourceLocation* source_location) {
+ SourceLocation* source_location,
+ absl::optional<base::UnguessableToken> issue_id) {
auto cspDetails = mojom::blink::ContentSecurityPolicyIssueDetails::New();
cspDetails->is_report_only =
header_type == ContentSecurityPolicyType::kReport;
@@ -1209,6 +1213,9 @@ void ContentSecurityPolicy::ReportContentSecurityPolicyIssue(
auto details = mojom::blink::InspectorIssueDetails::New();
details->csp_issue_details = std::move(cspDetails);
+ if (issue_id) {
+ details->issue_id = issue_id;
+ }
mojom::blink::InspectorIssueInfoPtr info =
mojom::blink::InspectorIssueInfo::New(
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 ad14f794ea7..17ca9a3ebd6 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
@@ -31,6 +31,7 @@
#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
@@ -294,7 +295,8 @@ class CORE_EXPORT ContentSecurityPolicy final
bool AllowTrustedTypeAssignmentFailure(
const String& message,
const String& sample = String(),
- const String& sample_prefix = String());
+ const String& sample_prefix = String(),
+ absl::optional<base::UnguessableToken> issue_id = absl::nullopt);
void UsesScriptHashAlgorithms(uint8_t content_security_policy_hash_algorithm);
void UsesStyleHashAlgorithms(uint8_t content_security_policy_hash_algorithm);
@@ -319,21 +321,26 @@ class CORE_EXPORT ContentSecurityPolicy final
// available).
// If |sourceLocation| is not set, the source location will be the context's
// current location.
- void ReportViolation(const String& directive_text,
- CSPDirectiveName effective_type,
- const String& console_message,
- const KURL& blocked_url,
- const Vector<String>& report_endpoints,
- bool use_reporting_api,
- const String& header,
- network::mojom::ContentSecurityPolicyType,
- ContentSecurityPolicyViolationType,
- std::unique_ptr<SourceLocation>,
- LocalFrame* = nullptr,
- RedirectStatus = RedirectStatus::kFollowedRedirect,
- Element* = nullptr,
- const String& source = g_empty_string,
- const String& source_prefix = g_empty_string);
+ // If an inspector issue is reported, and |issue_id| is present, it will be
+ // reported on the issue. This is useful to provide a link from the
+ // JavaScript TypeError to the inspector issue in the DevTools front-end.
+ void ReportViolation(
+ const String& directive_text,
+ CSPDirectiveName effective_type,
+ const String& console_message,
+ const KURL& blocked_url,
+ const Vector<String>& report_endpoints,
+ bool use_reporting_api,
+ const String& header,
+ network::mojom::ContentSecurityPolicyType,
+ ContentSecurityPolicyViolationType,
+ std::unique_ptr<SourceLocation>,
+ LocalFrame* = nullptr,
+ RedirectStatus = RedirectStatus::kFollowedRedirect,
+ Element* = nullptr,
+ const String& source = g_empty_string,
+ const String& source_prefix = g_empty_string,
+ absl::optional<base::UnguessableToken> issue_id = absl::nullopt);
// 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
@@ -483,7 +490,8 @@ class CORE_EXPORT ContentSecurityPolicy final
ContentSecurityPolicyViolationType violation_type,
LocalFrame*,
Element*,
- SourceLocation*);
+ SourceLocation*,
+ absl::optional<base::UnguessableToken> issue_id);
Member<ContentSecurityPolicyDelegate> delegate_;
bool override_inline_style_allowed_ = false;
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 48cd4d39bfe..463e1059148 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
@@ -1243,7 +1243,7 @@ TEST_F(ContentSecurityPolicyTest, WasmEvalCSPEnable) {
csp->BindToDelegate(execution_context->GetContentSecurityPolicyDelegate());
csp->AddPolicies(ParseContentSecurityPolicies(
- "script-src 'wasm-eval'", ContentSecurityPolicyType::kEnforce,
+ "script-src 'wasm-unsafe-eval'", ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kHTTP, *secure_origin));
EXPECT_EQ(enabled, csp->AllowWasmCodeGeneration(
@@ -1256,6 +1256,29 @@ TEST_F(ContentSecurityPolicyTest, WasmEvalCSPEnable) {
test_wasm_eval_enabled(false);
}
+// Tests that WasmCSP runtime feature properly governs support for
+// WasmUnsafeEval.
+TEST_F(ContentSecurityPolicyTest, WasmUnsafeEvalCSPEnable) {
+ auto test_wasm_unsafe_eval_enabled = [&](bool enabled) {
+ ScopedWebAssemblyCSPForTest enable_wasp(enabled);
+
+ csp = MakeGarbageCollected<ContentSecurityPolicy>();
+ csp->BindToDelegate(execution_context->GetContentSecurityPolicyDelegate());
+
+ csp->AddPolicies(ParseContentSecurityPolicies(
+ "script-src 'wasm-unsafe-eval'", ContentSecurityPolicyType::kEnforce,
+ ContentSecurityPolicySource::kHTTP, *secure_origin));
+
+ EXPECT_EQ(enabled, csp->AllowWasmCodeGeneration(
+ ReportingDisposition::kReport,
+ ContentSecurityPolicy::kWillNotThrowException,
+ g_empty_string));
+ };
+
+ test_wasm_unsafe_eval_enabled(true);
+ test_wasm_unsafe_eval_enabled(false);
+}
+
TEST_F(ContentSecurityPolicyTest, OpaqueOriginBeforeBind) {
const KURL url("https://example.test");
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/conversion_util.cc b/chromium/third_party/blink/renderer/core/frame/csp/conversion_util.cc
index 75b240adee0..e63fc57cab0 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/conversion_util.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/conversion_util.cc
@@ -32,10 +32,10 @@ WebCSPHashSource ConvertToPublic(
WebCSPSourceList ConvertToPublic(
network::mojom::blink::CSPSourceListPtr source_list) {
WebVector<WebCSPSource> sources(source_list->sources.size());
- for (size_t i = 0; i < sources.size(); ++i)
+ for (wtf_size_t i = 0; i < source_list->sources.size(); ++i)
sources[i] = ConvertToPublic(std::move(source_list->sources[i]));
WebVector<WebCSPHashSource> hashes(source_list->hashes.size());
- for (size_t i = 0; i < hashes.size(); ++i)
+ for (wtf_size_t i = 0; i < source_list->hashes.size(); ++i)
hashes[i] = ConvertToPublic(std::move(source_list->hashes[i]));
return {std::move(sources),
std::move(source_list->nonces),
@@ -46,6 +46,7 @@ WebCSPSourceList ConvertToPublic(
source_list->allow_inline,
source_list->allow_eval,
source_list->allow_wasm_eval,
+ source_list->allow_wasm_unsafe_eval,
source_list->allow_dynamic,
source_list->allow_unsafe_hashes,
source_list->report_sample};
@@ -107,8 +108,8 @@ network::mojom::blink::CSPSourceListPtr ConvertToMojoBlink(
source_list.allow_self, source_list.allow_star,
source_list.allow_response_redirects, source_list.allow_inline,
source_list.allow_eval, source_list.allow_wasm_eval,
- source_list.allow_dynamic, source_list.allow_unsafe_hashes,
- source_list.report_sample);
+ source_list.allow_wasm_unsafe_eval, source_list.allow_dynamic,
+ source_list.allow_unsafe_hashes, source_list.report_sample);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_fuzzer.cc b/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_fuzzer.cc
index 596997b645e..92d7c35aef5 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_fuzzer.cc
@@ -36,8 +36,8 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return EXIT_SUCCESS;
}
- String url = String(data, it - 1 - data);
- String header = String(it, size - (it - data));
+ String url = String(data, static_cast<unsigned>(it - 1 - data));
+ String header = String(it, static_cast<unsigned>(size - (it - data)));
unsigned hash = header.IsNull() ? 0 : header.Impl()->GetHash();
// Use the 'hash' value to pick header_type and header_source input.
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_test.cc b/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_test.cc
index 89823c266d1..b7f0bada88a 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/conversion_util_test.cc
@@ -145,6 +145,9 @@ TEST(ContentSecurityPolicyConversionUtilTest,
[](CSPSourceList& source_list) { source_list.allow_inline = true; },
[](CSPSourceList& source_list) { source_list.allow_eval = true; },
[](CSPSourceList& source_list) { source_list.allow_wasm_eval = true; },
+ [](CSPSourceList& source_list) {
+ source_list.allow_wasm_unsafe_eval = true;
+ },
[](CSPSourceList& source_list) { source_list.allow_dynamic = true; },
[](CSPSourceList& source_list) {
source_list.allow_unsafe_hashes = true;
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 2f0b7705608..25132171ef4 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
@@ -163,17 +163,19 @@ CSPOperativeDirective OperativeDirective(
original_type);
}
-void ReportViolation(const network::mojom::blink::ContentSecurityPolicy& csp,
- ContentSecurityPolicy* policy,
- const String& directive_text,
- CSPDirectiveName effective_type,
- const String& console_message,
- const KURL& blocked_url,
- ResourceRequest::RedirectStatus redirect_status,
- ContentSecurityPolicy::ContentSecurityPolicyViolationType
- violation_type = ContentSecurityPolicy::kURLViolation,
- const String& sample = String(),
- const String& sample_prefix = String()) {
+void ReportViolation(
+ const network::mojom::blink::ContentSecurityPolicy& csp,
+ ContentSecurityPolicy* policy,
+ const String& directive_text,
+ CSPDirectiveName effective_type,
+ const String& console_message,
+ const KURL& blocked_url,
+ ResourceRequest::RedirectStatus redirect_status,
+ ContentSecurityPolicy::ContentSecurityPolicyViolationType violation_type =
+ ContentSecurityPolicy::kURLViolation,
+ const String& sample = String(),
+ const String& sample_prefix = String(),
+ absl::optional<base::UnguessableToken> issue_id = absl::nullopt) {
String message = CSPDirectiveListIsReportOnly(csp)
? "[Report Only] " + console_message
: console_message;
@@ -187,7 +189,7 @@ void ReportViolation(const network::mojom::blink::ContentSecurityPolicy& csp,
nullptr, // localFrame
redirect_status,
nullptr, // Element*
- sample, sample_prefix);
+ sample, sample_prefix, issue_id);
}
void ReportViolationWithLocation(
@@ -253,8 +255,7 @@ bool CheckEval(const network::mojom::blink::CSPSourceList* directive) {
bool SupportsWasmEval(const network::mojom::blink::ContentSecurityPolicy& csp,
const ContentSecurityPolicy* policy) {
- return RuntimeEnabledFeatures::WebAssemblyCSPEnabled() ||
- policy->SupportsWasmEval() ||
+ return policy->SupportsWasmEval() ||
SchemeRegistry::SchemeSupportsWasmEvalCSP(csp.self_origin->scheme);
}
@@ -263,7 +264,9 @@ bool CheckWasmEval(const network::mojom::blink::ContentSecurityPolicy& csp,
const network::mojom::blink::CSPSourceList* directive =
OperativeDirective(csp, CSPDirectiveName::ScriptSrc).source_list;
return !directive || directive->allow_eval ||
- (SupportsWasmEval(csp, policy) && directive->allow_wasm_eval);
+ (SupportsWasmEval(csp, policy) && directive->allow_wasm_eval) ||
+ (RuntimeEnabledFeatures::WebAssemblyCSPEnabled() &&
+ directive->allow_wasm_unsafe_eval);
}
bool CheckHash(const network::mojom::blink::CSPSourceList* directive,
@@ -569,7 +572,8 @@ bool CSPDirectiveListAllowTrustedTypeAssignmentFailure(
ContentSecurityPolicy* policy,
const String& message,
const String& sample,
- const String& sample_prefix) {
+ const String& sample_prefix,
+ absl::optional<base::UnguessableToken> issue_id) {
if (!CSPDirectiveListRequiresTrustedTypes(csp))
return true;
@@ -579,7 +583,7 @@ bool CSPDirectiveListAllowTrustedTypeAssignmentFailure(
CSPDirectiveName::RequireTrustedTypesFor, message, KURL(),
RedirectStatus::kNoRedirect,
ContentSecurityPolicy::kTrustedTypesSinkViolation, sample,
- sample_prefix);
+ sample_prefix, issue_id);
return CSPDirectiveListIsReportOnly(csp);
}
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 df303b694f3..5a589239617 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
@@ -45,7 +45,8 @@ bool CSPDirectiveListAllowTrustedTypeAssignmentFailure(
ContentSecurityPolicy* policy,
const String& message,
const String& sample,
- const String& sample_prefix);
+ const String& sample_prefix,
+ absl::optional<base::UnguessableToken> issue_id);
CORE_EXPORT
bool CSPDirectiveListAllowTrustedTypePolicy(
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc b/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
index c21dc62a839..a5bccdb77f2 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/loader/ping_loader.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -167,13 +168,12 @@ void ExecutionContextCSPDelegate::PostViolationReport(
ContentSecurityPolicy::GetDirectiveType(
violation_data.effectiveDirective()));
- // TODO(crbug/929370): Support POSTing violation reports from a Worker.
- Document* document = GetDocument();
- if (!document)
- return;
-
- LocalFrame* frame = document->GetFrame();
- if (!frame)
+ // We do not support reporting for worklets, since they don't have a
+ // ResourceFetcher.
+ //
+ // TODO(https://crbug.com/1222576): Send CSP reports for worklets using the
+ // owner document's ResourceFetcher.
+ if (DynamicTo<WorkletGlobalScope>(execution_context_.Get()))
return;
scoped_refptr<EncodedFormData> report =
@@ -195,7 +195,8 @@ void ExecutionContextCSPDelegate::PostViolationReport(
return;
for (const auto& report_endpoint : report_endpoints) {
- PingLoader::SendViolationReport(frame, KURL(report_endpoint), report);
+ PingLoader::SendViolationReport(execution_context_.Get(),
+ KURL(report_endpoint), report);
}
}
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 47f4337c272..9d900bac780 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
@@ -90,8 +90,9 @@ bool CSPSourceListIsNone(
return !source_list.sources.size() && !source_list.allow_self &&
!source_list.allow_star && !source_list.allow_inline &&
!source_list.allow_unsafe_hashes && !source_list.allow_eval &&
- !source_list.allow_wasm_eval && !source_list.allow_dynamic &&
- !source_list.nonces.size() && !source_list.hashes.size();
+ !source_list.allow_wasm_eval && !source_list.allow_wasm_unsafe_eval &&
+ !source_list.allow_dynamic && !source_list.nonces.size() &&
+ !source_list.hashes.size();
}
bool CSPSourceListIsSelf(
@@ -99,8 +100,9 @@ bool CSPSourceListIsSelf(
return source_list.allow_self && !source_list.sources.size() &&
!source_list.allow_star && !source_list.allow_inline &&
!source_list.allow_unsafe_hashes && !source_list.allow_eval &&
- !source_list.allow_wasm_eval && !source_list.allow_dynamic &&
- !source_list.nonces.size() && !source_list.hashes.size();
+ !source_list.allow_wasm_eval && !source_list.allow_wasm_unsafe_eval &&
+ !source_list.allow_dynamic && !source_list.nonces.size() &&
+ !source_list.hashes.size();
}
bool CSPSourceListIsHashOrNoncePresent(
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 7ab196494af..96e779d8ddb 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_CSP_SOURCE_LIST_DIRECTIVE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_CSP_SOURCE_LIST_DIRECTIVE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/csp_source.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/dactyloscoper.h b/chromium/third_party/blink/renderer/core/frame/dactyloscoper.h
index 1d2519ffc19..d34d731b94a 100644
--- a/chromium/third_party/blink/renderer/core/frame/dactyloscoper.h
+++ b/chromium/third_party/blink/renderer/core/frame/dactyloscoper.h
@@ -26,6 +26,8 @@ class CORE_EXPORT Dactyloscoper {
public:
Dactyloscoper();
+ Dactyloscoper(const Dactyloscoper&) = delete;
+ Dactyloscoper& operator=(const Dactyloscoper&) = delete;
void Record(WebFeature);
@@ -70,9 +72,6 @@ class CORE_EXPORT Dactyloscoper {
IdentifiableTokenBuilder().GetToken());
}
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Dactyloscoper);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.cc b/chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.cc
deleted file mode 100644
index dc3496638d9..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.cc
+++ /dev/null
@@ -1,29 +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/frame/deprecated_schedule_style_recalc_during_layout.h"
-
-
-namespace blink {
-
-DeprecatedScheduleStyleRecalcDuringLayout::
- DeprecatedScheduleStyleRecalcDuringLayout(DocumentLifecycle& lifecycle)
- : lifecycle_(lifecycle),
- deprecated_transition_(DocumentLifecycle::kInPerformLayout,
- DocumentLifecycle::kVisualUpdatePending),
- was_in_perform_layout_(lifecycle.GetState() ==
- DocumentLifecycle::kInPerformLayout) {}
-
-DeprecatedScheduleStyleRecalcDuringLayout::
- ~DeprecatedScheduleStyleRecalcDuringLayout() {
- // This block of code is intended to restore the state machine to the
- // proper state. The style recalc will still have been schedule, however.
- if (was_in_perform_layout_ &&
- lifecycle_.GetState() != DocumentLifecycle::kInPerformLayout) {
- DCHECK_EQ(lifecycle_.GetState(), DocumentLifecycle::kVisualUpdatePending);
- lifecycle_.AdvanceTo(DocumentLifecycle::kInPerformLayout);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.h b/chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.h
deleted file mode 100644
index 6fda6239b12..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.h
+++ /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.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATED_SCHEDULE_STYLE_RECALC_DURING_LAYOUT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATED_SCHEDULE_STYLE_RECALC_DURING_LAYOUT_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class DeprecatedScheduleStyleRecalcDuringLayout {
- STACK_ALLOCATED();
-
- public:
- explicit DeprecatedScheduleStyleRecalcDuringLayout(DocumentLifecycle&);
- ~DeprecatedScheduleStyleRecalcDuringLayout();
-
- private:
- DocumentLifecycle& lifecycle_;
- DocumentLifecycle::DeprecatedTransition deprecated_transition_;
- bool was_in_perform_layout_;
- DISALLOW_COPY_AND_ASSIGN(DeprecatedScheduleStyleRecalcDuringLayout);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATED_SCHEDULE_STYLE_RECALC_DURING_LAYOUT_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.cc b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
index ae969ddf50a..01f11bef416 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
@@ -523,44 +523,6 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
" for more details.",
MilestoneString(kM92).Ascii().c_str())};
- case WebFeature::kV8RTCRtpSender_CreateEncodedAudioStreams_Method:
- return {"V8RTCRtpSender_CreateEncodedAudioStreams_Method", kM88,
- ReplacedWillBeRemoved("RTCRtpSender.createEncodedAudioStreams",
- "RTCRtpSender.createEncodedStreams", kM88,
- "6321945865879552")};
-
- case WebFeature::kV8RTCRtpSender_CreateEncodedVideoStreams_Method:
- return {"V8RTCRtpSender_CreateEncodedVideoStreams_Method", kM88,
- ReplacedWillBeRemoved("RTCRtpSender.createEncodedVideoStreams",
- "RTCRtpSender.createEncodedStreams", kM88,
- "6321945865879552")};
-
- case WebFeature::kV8RTCRtpReceiver_CreateEncodedAudioStreams_Method:
- return {"V8RTCRtpReceiver_CreateEncodedAudioStreams_Method", kM88,
- ReplacedWillBeRemoved("RTCRtpReceiver.createEncodedAudioStreams",
- "RTCRtpReceiver.createEncodedStreams", kM88,
- "6321945865879552")};
-
- case WebFeature::kV8RTCRtpReceiver_CreateEncodedVideoStreams_Method:
- return {"V8RTCRtpReceiver_CreateEncodedVideoStreams_Method", kM88,
- ReplacedWillBeRemoved("RTCRtpReceiver.createEncodedVideoStreams",
- "RTCRtpReceiver.createEncodedStreams", kM88,
- "6321945865879552")};
-
- case WebFeature::kForceEncodedAudioInsertableStreams:
- return {"ForceEncodedAudioInsertableStreams", kM88,
- ReplacedWillBeRemoved(
- "RTCConfiguration.forceEncodedAudioInsertableStreams",
- "RTCConfiguration.encodedInsertableStreams", kM88,
- "6321945865879552")};
-
- case WebFeature::kForceEncodedVideoInsertableStreams:
- return {"ForceEncodedVideoInsertableStreams", kM88,
- ReplacedWillBeRemoved(
- "RTCConfiguration.forceEncodedVideoInsertableStreams",
- "RTCConfiguration.encodedInsertableStreams", kM88,
- "6321945865879552")};
-
case WebFeature::kRTCConstraintEnableRtpDataChannelsFalse:
case WebFeature::kRTCConstraintEnableRtpDataChannelsTrue:
return {
@@ -578,7 +540,9 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"format, \"unified-plan\", has been used by default since M72 "
"(January, 2019). Dropping support for Plan B is targeted for "
"M93. See https://www.chromestatus.com/feature/5823036655665152 "
- "for more details."};
+ "for more details, including the possibility of registering for "
+ "a Deprecation Trial in order to extend the Plan B deprecation "
+ "deadline for a limited amount of time."};
case WebFeature::kRTCPeerConnectionSdpSemanticsPlanBWithReverseOriginTrial:
return {"RTCPeerConnectionSdpSemanticsPlanBWithReverseOriginTrial", kM96,
@@ -608,15 +572,21 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"contexts, and will start blocking them in Chrome 92 (July "
"2021). See https://chromestatus.com/feature/5436853517811712 "
"for more details."};
- case WebFeature::kRTCPeerConnectionOfferAllowExtmapMixedFalse:
- return {"RTCPeerConnectionOfferExtmapAllowMixedFalse", kM93,
- "The RTCPeerConnection offerAllowExtmapMixed option is a "
- "non-standard feature. This feature will be removed in M93 "
- "(Canary: July 15, 2021; Stable: August 24, 2021). For "
- "interoperability with legacy WebRTC versions that throw "
- "errors when attempting to parse the a=extmap-allow-mixed "
- "line in the SDP remove the line from the SDP during "
- "signalling."};
+ case WebFeature::kXHRJSONEncodingDetection:
+ return {"XHRJSONEncodingDetection", kM93,
+ "UTF-16 is not supported by response json in XMLHttpRequest"};
+
+ case WebFeature::kAuthorizationCoveredByWildcard:
+ return {"AuthorizationCoveredByWildcard", kM97,
+ "\"Authorization\" will not be covered by the wildcard symbol (*)"
+ "in CORS \"Access-Control-Allow-Headers\" handling."};
+
+ case WebFeature::kOpenWebDatabaseThirdPartyContext:
+ return {"OpenWebDatabaseThirdPartyContext", kM97,
+ ReplacedWillBeRemoved(
+ "WebSQL in third-party contexts (i.e. cross-site iframes)",
+ "Web Storage or Indexed Database", kM97, "5684870116278272")};
+
// Features that aren't deprecated don't have a deprecation message.
default:
return {"NotDeprecated", kUnknown, ""};
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.h b/chromium/third_party/blink/renderer/core/frame/deprecation.h
index 5041e7894a6..d7c04bc7d31 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.h
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.h
@@ -7,7 +7,6 @@
#include <bitset>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -27,6 +26,8 @@ class CORE_EXPORT Deprecation final {
public:
Deprecation();
+ Deprecation(const Deprecation&) = delete;
+ Deprecation& operator=(const Deprecation&) = delete;
static void WarnOnDeprecatedProperties(const LocalFrame*,
CSSPropertyID unresolved_property);
@@ -65,8 +66,6 @@ class CORE_EXPORT Deprecation final {
features_deprecation_bits_;
std::bitset<kNumCSSPropertyIDs> css_property_deprecation_bits_;
unsigned mute_count_;
-
- DISALLOW_COPY_AND_ASSIGN(Deprecation);
};
} // 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
index 07a2b21e5a7..f32c6940ed6 100644
--- 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
@@ -28,6 +28,8 @@ class CORE_EXPORT DisplayCutoutClientImpl final
DisplayCutoutClientImpl(
LocalFrame*,
mojo::PendingAssociatedReceiver<mojom::blink::DisplayCutoutClient>);
+ DisplayCutoutClientImpl(const DisplayCutoutClientImpl&) = delete;
+ DisplayCutoutClientImpl& operator=(const DisplayCutoutClientImpl&) = delete;
// Notify the renderer that the safe areas have changed.
void SetSafeArea(mojom::blink::DisplayCutoutSafeAreaPtr safe_area) override;
@@ -38,8 +40,6 @@ class CORE_EXPORT DisplayCutoutClientImpl final
Member<LocalFrame> frame_;
mojo::AssociatedReceiver<mojom::blink::DisplayCutoutClient> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(DisplayCutoutClientImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_timer_coordinator.h b/chromium/third_party/blink/renderer/core/frame/dom_timer_coordinator.h
index 7cada0380c4..1c65ff96229 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_timer_coordinator.h
+++ b/chromium/third_party/blink/renderer/core/frame/dom_timer_coordinator.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DOM_TIMER_COORDINATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DOM_TIMER_COORDINATOR_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -25,6 +24,8 @@ class DOMTimerCoordinator {
public:
DOMTimerCoordinator() = default;
+ DOMTimerCoordinator(const DOMTimerCoordinator&) = delete;
+ DOMTimerCoordinator& operator=(const DOMTimerCoordinator&) = delete;
// Creates and installs a new timer. Returns the assigned ID.
int InstallNewTimeout(ExecutionContext*,
@@ -57,8 +58,6 @@ class DOMTimerCoordinator {
int circular_sequential_id_ = 0;
int timer_nesting_level_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(DOMTimerCoordinator);
};
} // namespace blink
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 3aa427eac1a..9fec4d763db 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.cc
@@ -10,6 +10,7 @@
#include "base/metrics/histogram_macros.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/action_after_pagehide.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.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"
@@ -25,6 +26,7 @@
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/frame_owner.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/core/frame/report.h"
@@ -131,6 +133,29 @@ DOMWindow* DOMWindow::top() const {
if (!GetFrame())
return nullptr;
+ // TODO(crbug.com/1123606): Remove this once we use MPArch as the underlying
+ // fenced frames implementation, instead of the
+ // `FencedFrameShadowDOMDelegate`. This is the version of `top()` specifically
+ // for fenced frames implemented with the ShadowDOM, because it provides
+ // top-most DOMWindow within the "fenced" frame tree. That is, the closest
+ // DOMWindow to this window that is marked as fenced, if one such frame
+ // exists (see the early-break below). See
+ // https://docs.google.com/document/d/1ijTZJT3DHQ1ljp4QQe4E4XCCRaYAxmInNzN1SzeJM8s/edit#heading=h.jztjmd6vstll.
+ if (RuntimeEnabledFeatures::FencedFramesEnabled(GetExecutionContext()) &&
+ features::kFencedFramesImplementationTypeParam.Get() ==
+ features::FencedFramesImplementationType::kShadowDOM) {
+ Frame* frame = GetFrame();
+ while (frame->Parent()) {
+ if (frame->Owner() && frame->Owner()->GetFramePolicy().is_fenced) {
+ break;
+ }
+ frame = frame->Parent();
+ }
+
+ DCHECK(frame);
+ return frame->DomWindow();
+ }
+
return GetFrame()->Tree().Top().DomWindow();
}
@@ -223,8 +248,6 @@ String DOMWindow::CrossDomainAccessErrorMessage(
if (accessing_window_url.IsNull())
return String();
- // FIXME: This message, and other console messages, have extra newlines.
- // Should remove them.
const SecurityOrigin* active_origin = accessing_window->GetSecurityOrigin();
const SecurityOrigin* target_origin =
GetFrame()->GetSecurityContext()->GetSecurityOrigin();
@@ -284,7 +307,7 @@ String DOMWindow::CrossDomainAccessErrorMessage(
return message + " The frame requesting access has a protocol of \"" +
active_url.Protocol() +
"\", the frame being accessed has a protocol of \"" +
- target_url.Protocol() + "\". Protocols must match.\n";
+ target_url.Protocol() + "\". Protocols must match.";
// 'document.domain' errors.
if (target_origin->DomainWasSetInDOM() && active_origin->DomainWasSetInDOM())
@@ -683,18 +706,50 @@ void DOMWindow::DoPostMessage(scoped_refptr<SerializedScriptValue> message,
if (RuntimeEnabledFeatures::CapabilityDelegationPaymentRequestEnabled(
GetExecutionContext()) &&
LocalFrame::HasTransientUserActivation(source_frame) &&
- options->hasCreateToken()) {
+ options->hasDelegate()) {
Vector<String> capability_list;
- options->createToken().Split(' ', capability_list);
+ options->delegate().Split(' ', capability_list);
delegate_payment_request = capability_list.Contains("paymentrequest");
}
- MessageEvent* event =
- MessageEvent::Create(std::move(channels), std::move(message),
- source->GetSecurityOrigin()->ToString(), String(),
- source, user_activation, delegate_payment_request);
+ PostedMessage* posted_message = MakeGarbageCollected<PostedMessage>();
+ posted_message->source_origin = source->GetSecurityOrigin();
+ posted_message->target_origin = std::move(target);
+ posted_message->data = std::move(message);
+ posted_message->channels = std::move(channels);
+ posted_message->source = source;
+ posted_message->user_activation = user_activation;
+ posted_message->delegate_payment_request = delegate_payment_request;
+ SchedulePostMessage(posted_message);
+}
+
+void DOMWindow::PostedMessage::Trace(Visitor* visitor) const {
+ visitor->Trace(source);
+ visitor->Trace(user_activation);
+}
+
+BlinkTransferableMessage
+DOMWindow::PostedMessage::ToBlinkTransferableMessage() && {
+ BlinkTransferableMessage result;
+
+ // Message data and cluster ID (optional).
+ result.message = std::move(data);
+ if (result.message->IsLockedToAgentCluster())
+ result.locked_agent_cluster_id = source->GetAgentClusterID();
+
+ // Ports
+ result.ports = std::move(channels);
+
+ // User activation
+ if (user_activation) {
+ result.user_activation = mojom::blink::UserActivationSnapshot::New(
+ user_activation->hasBeenActive(), user_activation->isActive());
+ }
+
+ // Capability delegation
+ result.delegate_payment_request = delegate_payment_request;
- SchedulePostMessage(event, std::move(target), source);
+ return result;
}
void DOMWindow::Trace(Visitor* visitor) const {
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 9c935c8db06..1f382084e83 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.h
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.h
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -22,13 +23,15 @@ namespace blink {
class InputDeviceCapabilitiesConstants;
class LocalDOMWindow;
class Location;
-class MessageEvent;
class ScriptValue;
class SecurityOrigin;
class SerializedScriptValue;
+class UserActivation;
class WindowPostMessageOptions;
class WindowProxyManager;
+struct BlinkTransferableMessage;
+
// DOMWindow is an abstract class of Window interface implementations.
// We have two derived implementation classes; LocalDOMWindow and
// RemoteDOMWindow.
@@ -154,9 +157,19 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData {
protected:
explicit DOMWindow(Frame&);
- virtual void SchedulePostMessage(MessageEvent*,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source) = 0;
+ struct PostedMessage final : GarbageCollected<PostedMessage> {
+ void Trace(Visitor* visitor) const;
+ BlinkTransferableMessage ToBlinkTransferableMessage() &&;
+
+ scoped_refptr<const SecurityOrigin> source_origin;
+ scoped_refptr<const SecurityOrigin> target_origin;
+ scoped_refptr<SerializedScriptValue> data;
+ Vector<MessagePortChannel> channels;
+ Member<LocalDOMWindow> source;
+ Member<UserActivation> user_activation;
+ bool delegate_payment_request = false;
+ };
+ virtual void SchedulePostMessage(PostedMessage* message) = 0;
void DisconnectFromFrame() { frame_ = nullptr; }
diff --git a/chromium/third_party/blink/renderer/core/frame/embedded_content_view.cc b/chromium/third_party/blink/renderer/core/frame/embedded_content_view.cc
index 9e609f6f983..c7cb1853da6 100644
--- a/chromium/third_party/blink/renderer/core/frame/embedded_content_view.cc
+++ b/chromium/third_party/blink/renderer/core/frame/embedded_content_view.cc
@@ -31,9 +31,9 @@ IntPoint EmbeddedContentView::Location() const {
if (owner_layout_view->IsScrollContainer()) {
// Floored because the frame_rect in a content view is an IntRect. We may
// want to reevaluate that since scroll offsets/layout can be fractional.
- IntSize scroll_offset(
- FlooredIntSize(owner_layout_view->ScrolledContentOffset()));
- location.SaturatedMove(-scroll_offset.Width(), -scroll_offset.Height());
+ IntPoint scroll_offset(
+ FlooredIntPoint(owner_layout_view->ScrolledContentOffset()));
+ location.SaturatedMove(-scroll_offset.X(), -scroll_offset.Y());
}
}
return location;
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 56729585cd8..549ed53a28e 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
@@ -15,6 +15,7 @@
#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"
+#include "third_party/blink/renderer/platform/heap/thread_state_scopes.h"
namespace blink {
@@ -360,22 +361,28 @@ void EventHandlerRegistry::DocumentDetached(Document& document) {
EventHandlerClass handler_class =
static_cast<EventHandlerClass>(handler_class_index);
HeapVector<Member<EventTarget>> targets_to_remove;
- const EventTargetSet* targets = &targets_[handler_class];
- for (const auto& event_target : *targets) {
- if (Node* node = event_target.key->ToNode()) {
- for (Document* doc = &node->GetDocument(); doc;
- doc = doc->LocalOwner() ? &doc->LocalOwner()->GetDocument()
- : nullptr) {
- if (doc == &document) {
- targets_to_remove.push_back(event_target.key);
- break;
+ {
+ // TODO(keishi): If a GC happens while iterating a EventTargetSet, the
+ // custom weak processing may remove elements from it. Remove this scope
+ // when we get rid of the custom weak processing. crbug.com/123531
+ ThreadState::GCForbiddenScope gc_forbidden(ThreadState::Current());
+ const EventTargetSet* targets = &targets_[handler_class];
+ for (const auto& event_target : *targets) {
+ if (Node* node = event_target.key->ToNode()) {
+ for (Document* doc = &node->GetDocument(); doc;
+ doc = doc->LocalOwner() ? &doc->LocalOwner()->GetDocument()
+ : nullptr) {
+ if (doc == &document) {
+ targets_to_remove.push_back(event_target.key);
+ break;
+ }
}
+ } else if (event_target.key->ToLocalDOMWindow()) {
+ // DOMWindows may outlive their documents, so we shouldn't remove
+ // their handlers here.
+ } else {
+ NOTREACHED();
}
- } else if (event_target.key->ToLocalDOMWindow()) {
- // DOMWindows may outlive their documents, so we shouldn't remove their
- // handlers here.
- } else {
- NOTREACHED();
}
}
for (wtf_size_t i = 0; i < targets_to_remove.size(); ++i)
@@ -387,6 +394,10 @@ void EventHandlerRegistry::DocumentDetached(Document& document) {
void EventHandlerRegistry::CheckConsistency(
EventHandlerClass handler_class) const {
#if DCHECK_IS_ON()
+ // TODO(keishi): If a GC happens while iterating a EventTargetSet, the
+ // custom weak processing may remove elements from it. Remove this scope
+ // when we get rid of the custom weak processing. crbug.com/123531
+ ThreadState::GCForbiddenScope gc_forbidden(ThreadState::Current());
const EventTargetSet* targets = &targets_[handler_class];
for (const auto& event_target : *targets) {
if (Node* node = event_target.key->ToNode()) {
diff --git a/chromium/third_party/blink/renderer/core/frame/find_in_page.h b/chromium/third_party/blink/renderer/core/frame/find_in_page.h
index 7b7bcbe0fa7..ed8bfa7f2d9 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
@@ -29,6 +29,8 @@ class CORE_EXPORT FindInPage final : public GarbageCollected<FindInPage>,
public mojom::blink::FindInPage {
public:
FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry);
+ FindInPage(const FindInPage&) = delete;
+ FindInPage& operator=(const FindInPage&) = delete;
bool FindInternal(int identifier,
const WebString& search_text,
@@ -110,8 +112,6 @@ class CORE_EXPORT FindInPage final : public GarbageCollected<FindInPage>,
mojo::Remote<mojom::blink::FindInPageClient> client_;
mojo::AssociatedReceiver<mojom::blink::FindInPage> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(FindInPage);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.cc b/chromium/third_party/blink/renderer/core/frame/frame.cc
index a190fd8233e..8bf6b4bc077 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame.cc
@@ -337,14 +337,6 @@ void Frame::SetOwner(FrameOwner* owner) {
UpdateInheritedEffectiveTouchActionIfPossible();
}
-bool Frame::IsAdSubframe() const {
- return ad_frame_type_ != mojom::blink::AdFrameType::kNonAd;
-}
-
-bool Frame::IsAdRoot() const {
- return ad_frame_type_ == mojom::blink::AdFrameType::kRootAd;
-}
-
void Frame::UpdateInertIfPossible() {
if (auto* frame_owner_element =
DynamicTo<HTMLFrameOwnerElement>(owner_.Get())) {
@@ -415,7 +407,6 @@ Frame::Frame(FrameClient* client,
: tree_node_(this),
page_(&page),
owner_(owner),
- ad_frame_type_(mojom::blink::AdFrameType::kNonAd),
client_(client),
window_proxy_manager_(window_proxy_manager),
parent_(parent),
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.h b/chromium/third_party/blink/renderer/core/frame/frame.h
index 42498855a4b..ecc1409edb9 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame.h
@@ -33,12 +33,12 @@
#include "base/unguessable_token.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/frame/frame_ad_evidence.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/common/permissions_policy/document_policy_features.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy_features.h"
#include "third_party/blink/public/common/tokens/tokens.h"
-#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/input/scroll_direction.mojom-blink-forward.h"
@@ -228,12 +228,15 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
return lifecycle_.GetState() == FrameLifecycle::kAttached;
}
+ // Note that IsAttached() and IsDetached() are not strict opposites: frames
+ // that are detaching are considered to be in neither state.
+ bool IsDetached() const {
+ return lifecycle_.GetState() == FrameLifecycle::kDetached;
+ }
+
// Whether the frame is considered to be an ad subframe by Ad Tagging. Returns
// true for both root and child ad subframes.
- bool IsAdSubframe() const;
-
- // Whether the frame is considered to be a root ad subframe by Ad Tagging.
- bool IsAdRoot() const;
+ virtual bool IsAdSubframe() const = 0;
// Called to make a frame inert or non-inert. A frame is inert when there
// is a modal dialog displayed within an ancestor frame, and this frame
@@ -398,12 +401,6 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
// See `Detach()` for more information.
virtual bool DetachImpl(FrameDetachType) = 0;
- // Note that IsAttached() and IsDetached() are not strict opposites: frames
- // that are detaching are considered to be in neither state.
- bool IsDetached() const {
- return lifecycle_.GetState() == FrameLifecycle::kDetached;
- }
-
virtual void DidChangeVisibleToHitTesting() = 0;
void FocusImpl();
@@ -436,19 +433,6 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
bool visible_to_hit_testing_ = true;
- // Type of frame detected by heuristics checking if the frame was created
- // for advertising purposes. It's per-frame (as opposed to per-document)
- // because when an iframe is created on behalf of ad script that same frame is
- // not typically reused for non-ad purposes.
- //
- // For LocalFrame, it might be (1) calculated directly in the renderer based
- // on script in the stack in the case of an initial synchronous commit, or (2)
- // replicated from the browser process, or (3) signaled from the browser
- // process at ready-to-commit time. For RemoteFrame, it might be (1)
- // replicated from the browser process or (2) signaled from the browser
- // process at ready-to-commit time.
- mojom::blink::AdFrameType ad_frame_type_;
-
private:
// Inserts the given frame as a child of this frame, so that it is the next
// child after |previous_sibling|, or first child if |previous_sibling| is
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_console.cc b/chromium/third_party/blink/renderer/core/frame/frame_console.cc
index 2b4eff733cc..9fbf419f42b 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_console.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_console.cc
@@ -30,6 +30,7 @@
#include <memory>
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -122,6 +123,12 @@ void FrameConsole::DidFailLoading(DocumentLoader* loader,
if (error.IsCancellation() || error.IsUnactionableTrustTokensStatus())
return;
+ if (error.CorsErrorStatus() &&
+ base::FeatureList::IsEnabled(blink::features::kCORSErrorsIssueOnly)) {
+ // CORS issues are reported via network service instrumentation.
+ return;
+ }
+
StringBuilder message;
message.Append("Failed to load resource");
if (!error.LocalizedDescription().IsEmpty()) {
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.cc b/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.cc
index 0dc762f65c3..ed3683afe07 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/frame/frame_content_as_text.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -15,7 +15,7 @@
namespace blink {
-void FrameContentAsText(size_t max_chars,
+void FrameContentAsText(wtf_size_t max_chars,
LocalFrame* frame,
StringBuilder& output) {
Document* document = frame->GetDocument();
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.h b/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.h
index ebe0d5b64af..6d9a4cb5bcc 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_content_as_text.h
@@ -16,7 +16,7 @@ class LocalFrame;
// Recursively dumps the text inside |frame| and its local subtree to
// |output|, up to the length of |max_chars|.
-CORE_EXPORT void FrameContentAsText(size_t max_chars,
+CORE_EXPORT void FrameContentAsText(wtf_size_t max_chars,
LocalFrame* frame,
StringBuilder& output);
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_lifecycle.h b/chromium/third_party/blink/renderer/core/frame/frame_lifecycle.h
index 37f82165170..b0ede763b6d 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_lifecycle.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_lifecycle.h
@@ -5,8 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_LIFECYCLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_LIFECYCLE_H_
-#include "base/macros.h"
-
namespace blink {
class FrameLifecycle {
@@ -18,14 +16,14 @@ class FrameLifecycle {
};
FrameLifecycle();
+ FrameLifecycle(const FrameLifecycle&) = delete;
+ FrameLifecycle& operator=(const FrameLifecycle&) = delete;
State GetState() const { return state_; }
void AdvanceTo(State);
private:
State state_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameLifecycle);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc b/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc
index 0ddaf4687ae..f32836fa8c1 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc
@@ -17,6 +17,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/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.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"
@@ -114,9 +115,10 @@ TEST_P(FrameOverlayTest, AcceleratedCompositing) {
EXPECT_EQ(PropertyTreeState::Root(),
graphics_layer->GetPropertyTreeState());
Vector<PreCompositedLayerInfo> pre_composited_layers;
- graphics_layer->PaintRecursively(builder.Context(), pre_composited_layers);
+ PaintController::CycleScope cycle_scope;
+ graphics_layer->PaintRecursively(builder.Context(), pre_composited_layers,
+ cycle_scope);
ASSERT_EQ(1u, pre_composited_layers.size());
- graphics_layer->GetPaintController().FinishCycle();
SkiaPaintCanvas(&canvas).drawPicture(
graphics_layer->GetPaintController().GetPaintArtifact().GetPaintRecord(
PropertyTreeState::Root()));
@@ -170,9 +172,10 @@ TEST_P(FrameOverlayTest, DeviceEmulationScale) {
EXPECT_FALSE(graphics_layer->IsHitTestable());
EXPECT_EQ(state, graphics_layer->GetPropertyTreeState());
Vector<PreCompositedLayerInfo> pre_composited_layers;
- graphics_layer->PaintRecursively(context, pre_composited_layers);
+ PaintController::CycleScope cycle_scope;
+ graphics_layer->PaintRecursively(context, pre_composited_layers,
+ cycle_scope);
check_paint_results(graphics_layer->GetPaintController());
- graphics_layer->GetPaintController().FinishCycle();
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_owner.h b/chromium/third_party/blink/renderer/core/frame/frame_owner.h
index b8f83ab1cf6..956f138293f 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_owner.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_owner.h
@@ -4,9 +4,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_OWNER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_OWNER_H_
-#include "third_party/blink/public/mojom/frame/color_scheme.mojom-shared.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/mojom/frame/color_scheme.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -68,7 +68,7 @@ class CORE_EXPORT FrameOwner : public GarbageCollectedMixin {
protected:
virtual void FrameOwnerPropertiesChanged() {}
- virtual void CSPAttributeChanged() {}
+ virtual void DidChangeAttributes() {}
private:
virtual void SetIsSwappingFrames(bool) {}
@@ -97,7 +97,7 @@ class FrameSwapScope {
if (frame_owner_) {
frame_owner_->SetIsSwappingFrames(false);
frame_owner_->FrameOwnerPropertiesChanged();
- frame_owner_->CSPAttributeChanged();
+ frame_owner_->DidChangeAttributes();
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h b/chromium/third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h
index d9c82cfa0e5..b1baeae2d2d 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h
@@ -32,6 +32,9 @@ class FrameSerializerDelegateImpl final : public FrameSerializer::Delegate {
FrameSerializerDelegateImpl(WebFrameSerializer::MHTMLPartsGenerationDelegate&,
HeapHashSet<WeakMember<const Element>>&);
+ FrameSerializerDelegateImpl(const FrameSerializerDelegateImpl&) = delete;
+ FrameSerializerDelegateImpl& operator=(const FrameSerializerDelegateImpl&) =
+ delete;
~FrameSerializerDelegateImpl() override = default;
// FrameSerializer::Delegate implementation.
@@ -53,8 +56,6 @@ class FrameSerializerDelegateImpl final : public FrameSerializer::Delegate {
WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate_;
HeapHashSet<WeakMember<const Element>>& shadow_template_elements_;
bool popup_overlays_skipped_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameSerializerDelegateImpl);
};
} // 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 68c463e239f..cbb7547f10d 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
@@ -46,7 +46,9 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/platform.h"
@@ -74,6 +76,7 @@
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -332,6 +335,7 @@ WebViewHelper::WebViewHelper(
agent_group_scheduler_(
blink::ThreadScheduler::Current()->CreateAgentGroupScheduler()),
platform_(Platform::Current()) {
+ DocumentLoader::DisableCodeCacheForTesting();
CreateTestWebFrameWidgetCallback create_callback =
std::move(create_web_frame_callback);
if (!create_callback) {
@@ -422,6 +426,7 @@ WebViewImpl* WebViewHelper::InitializeAndLoad(
TestWebFrameClient* web_frame_client,
TestWebViewClient* web_view_client,
void (*update_settings_func)(WebSettings*)) {
+ DocumentLoader::DisableCodeCacheForTesting();
Initialize(web_frame_client, web_view_client, update_settings_func);
LoadFrame(GetWebView()->MainFrameImpl(), url);
@@ -556,7 +561,8 @@ TestWebFrameWidget* WebViewHelper::CreateFrameWidgetAndInitializeCompositing(
// The WebWidget requires the compositor to be set before it is used.
cc::LayerTreeSettings layer_tree_settings =
GetSynchronousSingleThreadLayerTreeSettings();
- ScreenInfos initial_screen_infos(frame_widget->GetInitialScreenInfo());
+ display::ScreenInfos initial_screen_infos(
+ frame_widget->GetInitialScreenInfo());
frame_widget->InitializeCompositing(frame_widget->GetAgentGroupScheduler(),
initial_screen_infos,
&layer_tree_settings);
@@ -610,15 +616,17 @@ void WebViewHelper::InitializeWebView(TestWebViewClient* web_view_client,
class WebView* opener) {
test_web_view_client_ =
CreateDefaultClientIfNeeded(web_view_client, owned_test_web_view_client_);
- web_view_ = static_cast<WebViewImpl*>(
+ web_view_ = To<WebViewImpl>(
WebView::Create(test_web_view_client_,
/*is_hidden=*/false,
+ /*is_prerendering=*/false,
/*is_inside_portal=*/false,
/*compositing_enabled=*/true,
/*widgets_never_composited=*/false,
/*opener=*/opener, mojo::NullAssociatedReceiver(),
*agent_group_scheduler_,
- /*session_storage_namespace_id=*/base::EmptyString()));
+ /*session_storage_namespace_id=*/base::EmptyString(),
+ /*page_base_background_color=*/absl::nullopt));
// This property must be set at initialization time, it is not supported to be
// changed afterward, and does nothing.
web_view_->GetSettings()->SetViewportEnabled(viewport_enabled_);
@@ -634,7 +642,7 @@ void WebViewHelper::InitializeWebView(TestWebViewClient* web_view_client,
// If a test turned off this settings, opened WebViews should propagate that.
if (opener) {
web_view_->GetSettings()->SetAllowUniversalAccessFromFileURLs(
- static_cast<WebViewImpl*>(opener)
+ To<WebViewImpl>(opener)
->GetPage()
->GetSettings()
.GetAllowUniversalAccessFromFileURLs());
@@ -802,8 +810,8 @@ TestWidgetInputHandlerHost* TestWebFrameWidget::GetInputHandlerHost() {
return widget_input_handler_host_.get();
}
-ScreenInfo TestWebFrameWidget::GetInitialScreenInfo() {
- return ScreenInfo();
+display::ScreenInfo TestWebFrameWidget::GetInitialScreenInfo() {
+ return display::ScreenInfo();
}
cc::FakeLayerTreeFrameSink* TestWebFrameWidget::LastCreatedFrameSink() {
@@ -854,6 +862,11 @@ void TestWebFrameWidgetHost::UpdateTooltipUnderCursor(
const String& tooltip_text,
base::i18n::TextDirection text_direction_hint) {}
+void TestWebFrameWidgetHost::UpdateTooltipFromKeyboard(
+ const String& tooltip_text,
+ base::i18n::TextDirection text_direction_hint,
+ const gfx::Rect& bounds) {}
+
void TestWebFrameWidgetHost::TextInputStateChanged(
ui::mojom::blink::TextInputStatePtr state) {
if (state->show_ime_if_needed)
@@ -899,8 +912,6 @@ void TestWebFrameWidgetHost::AutoscrollFling(const gfx::Vector2dF& position) {}
void TestWebFrameWidgetHost::AutoscrollEnd() {}
-void TestWebFrameWidgetHost::DidFirstVisuallyNonEmptyPaint() {}
-
void TestWebFrameWidgetHost::StartDragging(
const blink::WebDragData& drag_data,
blink::DragOperationsMask operations_allowed,
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 94d0ba5e52b..5673bda64fb 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,7 +37,6 @@
#include <string>
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host.h"
@@ -188,6 +187,9 @@ class TestWebFrameWidgetHost : public mojom::blink::WidgetHost,
void UpdateTooltipUnderCursor(
const String& tooltip_text,
base::i18n::TextDirection text_direction_hint) override;
+ void UpdateTooltipFromKeyboard(const String& tooltip_text,
+ base::i18n::TextDirection text_direction_hint,
+ const gfx::Rect& bounds) override;
void TextInputStateChanged(
ui::mojom::blink::TextInputStatePtr state) override;
void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
@@ -218,7 +220,6 @@ class TestWebFrameWidgetHost : public mojom::blink::WidgetHost,
void AutoscrollStart(const gfx::PointF& position) override;
void AutoscrollFling(const gfx::Vector2dF& position) override;
void AutoscrollEnd() override;
- void DidFirstVisuallyNonEmptyPaint() override;
void StartDragging(const blink::WebDragData& drag_data,
blink::DragOperationsMask operations_allowed,
const SkBitmap& bitmap,
@@ -267,7 +268,7 @@ class TestWebFrameWidget : public WebFrameWidgetImpl {
// threaded compositor, such as SimCompositor tests.
cc::FakeLayerTreeFrameSink* LastCreatedFrameSink();
- virtual ScreenInfo GetInitialScreenInfo();
+ virtual display::ScreenInfo GetInitialScreenInfo();
virtual std::unique_ptr<TestWebFrameWidgetHost> CreateWidgetHost();
void BindWidgetChannels(
@@ -348,6 +349,8 @@ class WebViewHelper : public ScopedMockOverlayScrollbars {
public:
explicit WebViewHelper(CreateTestWebFrameWidgetCallback
create_web_frame_callback = base::NullCallback());
+ WebViewHelper(const WebViewHelper&) = delete;
+ WebViewHelper& operator=(const WebViewHelper&) = delete;
~WebViewHelper();
// Helpers for creating the main frame. All methods that accept raw
@@ -483,8 +486,6 @@ class WebViewHelper : public ScopedMockOverlayScrollbars {
// The Platform should not change during the lifetime of the test!
Platform* const platform_;
-
- DISALLOW_COPY_AND_ASSIGN(WebViewHelper);
};
// Minimal implementation of WebLocalFrameClient needed for unit tests that load
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_view.cc b/chromium/third_party/blink/renderer/core/frame/frame_view.cc
index 3842fbbf42f..427942a4461 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_view.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_view.cc
@@ -80,10 +80,11 @@ void FrameView::UpdateViewportIntersection(unsigned flags,
LayoutEmbeddedContent* owner_layout_object =
owner_element->GetLayoutEmbeddedContent();
- if (!owner_layout_object || owner_layout_object->ContentSize().IsEmpty()) {
- // The frame is detached from layout, not visible, or zero size; leave
- // viewport_intersection empty, and signal the frame as occluded if
- // necessary.
+ if (!owner_layout_object || owner_layout_object->ContentSize().IsEmpty() ||
+ (flags & IntersectionObservation::kAncestorFrameIsDetachedFromLayout)) {
+ // The frame, or an ancestor frame, is detached from layout, not visible, or
+ // zero size; leave viewport_intersection empty, and signal the frame as
+ // occluded if necessary.
occlusion_state = mojom::blink::FrameOcclusionState::kPossiblyOccluded;
} else if (parent_lifecycle_state >= DocumentLifecycle::kLayoutClean &&
!owner_document.View()->NeedsLayout()) {
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 3d89323433e..80defea0058 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_view.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_view.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_VIEW_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/frame/embedded_content_view.h"
@@ -24,7 +25,9 @@ class CORE_EXPORT FrameView : public EmbeddedContentView {
// parent_flags is the result of calling GetIntersectionObservationFlags on
// the LocalFrameView parent of this FrameView (if any). It contains dirty
// bits based on whether geometry may have changed in the parent frame.
- virtual bool UpdateViewportIntersectionsForSubtree(unsigned parent_flags) = 0;
+ virtual bool UpdateViewportIntersectionsForSubtree(
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>& monotonic_time) = 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.h b/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.h
index 0748fe5fc62..4ea8e460b14 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_VIEW_AUTO_SIZE_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_VIEW_AUTO_SIZE_INFO_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -19,6 +18,8 @@ class FrameViewAutoSizeInfo final
: public GarbageCollected<FrameViewAutoSizeInfo> {
public:
explicit FrameViewAutoSizeInfo(LocalFrameView*);
+ FrameViewAutoSizeInfo(const FrameViewAutoSizeInfo&) = delete;
+ FrameViewAutoSizeInfo& operator=(const FrameViewAutoSizeInfo&) = delete;
void ConfigureAutoSizeMode(const IntSize& min_size, const IntSize& max_size);
// Returns true if the LocalFrameView was resized.
@@ -42,8 +43,6 @@ class FrameViewAutoSizeInfo final
// Clear();
bool running_first_autosize_ = false;
uint32_t num_passes_ = 0u;
-
- DISALLOW_COPY_AND_ASSIGN(FrameViewAutoSizeInfo);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/history.cc b/chromium/third_party/blink/renderer/core/frame/history.cc
index 48f34f5d4d3..4ad6068a5ee 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.cc
+++ b/chromium/third_party/blink/renderer/core/frame/history.cc
@@ -211,13 +211,13 @@ void History::pushState(v8::Isolate* isolate,
const String& url,
ExceptionState& exception_state) {
WebFrameLoadType load_type = WebFrameLoadType::kStandard;
- // Navigations in portal contexts do not create back/forward entries.
- if (DomWindow() && DomWindow()->GetFrame()->GetPage()->InsidePortal()) {
+ if (DomWindow() &&
+ DomWindow()->GetFrame()->ShouldMaintainTrivialSessionHistory()) {
DomWindow()->AddConsoleMessage(
MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kWarning,
- "Use of history.pushState in a portal context "
+ mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "Use of history.pushState in a prerender context "
"is treated as history.replaceState."),
/* discard_duplicates */ true);
load_type = WebFrameLoadType::kReplaceCurrentItem;
@@ -302,15 +302,17 @@ void History::StateObjectAdded(
}
if (auto* app_history = AppHistory::appHistory(*DomWindow())) {
- if (!app_history->DispatchNavigateEvent(
+ if (app_history->DispatchNavigateEvent(
full_url, nullptr, NavigateEventType::kHistoryApi, type,
- UserNavigationInvolvement::kNone, data.get())) {
+ UserNavigationInvolvement::kNone,
+ data.get()) != AppHistory::DispatchResult::kContinue) {
return;
}
}
DomWindow()->document()->Loader()->RunURLAndHistoryUpdateSteps(
- full_url, std::move(data), type, restoration_type);
+ full_url, mojom::blink::SameDocumentNavigationType::kHistoryApi,
+ std::move(data), type, restoration_type);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/history_util.cc b/chromium/third_party/blink/renderer/core/frame/history_util.cc
index c858bcf9530..223c8ff53f9 100644
--- a/chromium/third_party/blink/renderer/core/frame/history_util.cc
+++ b/chromium/third_party/blink/renderer/core/frame/history_util.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/frame/history_util.h"
+#include "base/metrics/histogram_functions.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -29,26 +30,32 @@ bool CanChangeToUrlForHistoryApi(const KURL& url,
if (!url.IsValid())
return false;
- if (document_origin->IsGrantedUniversalAccess())
- return true;
+ bool can_change = true;
+ scoped_refptr<const SecurityOrigin> requested_origin =
+ SecurityOrigin::Create(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->IsOpaque() || document_origin->IsLocal())
- return EqualIgnoringQueryAndFragment(url, document_url);
-
- if (!EqualIgnoringPathQueryAndFragment(url, document_url))
- return false;
-
- scoped_refptr<const SecurityOrigin> requested_origin =
- SecurityOrigin::Create(url);
- if (requested_origin->IsOpaque() ||
- !requested_origin->IsSameOriginWith(document_origin)) {
- return false;
+ if (document_origin->IsOpaque() || document_origin->IsLocal()) {
+ can_change = EqualIgnoringQueryAndFragment(url, document_url);
+ } else if (!EqualIgnoringPathQueryAndFragment(url, document_url)) {
+ can_change = false;
+ } else if (requested_origin->IsOpaque() ||
+ !requested_origin->IsSameOriginWith(document_origin)) {
+ can_change = false;
}
- return true;
+ if (document_origin->IsGrantedUniversalAccess()) {
+ // Log the case when 'pushState'/'replaceState' is allowed only because
+ // of IsGrantedUniversalAccess ie there is no other condition which should
+ // allow the change (!can_change).
+ base::UmaHistogramBoolean(
+ "Android.WebView.UniversalAccess.OriginUrlMismatchInHistoryUtil",
+ !can_change);
+ return true;
+ }
+ return can_change;
}
} // 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 7e8858bb5c6..bb15eafe288 100644
--- a/chromium/third_party/blink/renderer/core/frame/intervention.h
+++ b/chromium/third_party/blink/renderer/core/frame/intervention.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -19,6 +18,8 @@ class CORE_EXPORT Intervention {
public:
Intervention() = default;
+ Intervention(const Intervention&) = delete;
+ Intervention& operator=(const Intervention&) = delete;
~Intervention() = default;
// Generates a intervention report, to be routed to the Reporting API and any
@@ -26,8 +27,6 @@ class CORE_EXPORT Intervention {
static void GenerateReport(LocalFrame*,
const String& id,
const String& message);
-
- DISALLOW_COPY_AND_ASSIGN(Intervention);
};
} // namespace blink
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 06983193aa1..229eba91cdf 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
@@ -38,7 +38,6 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/action_after_pagehide.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/mojom/permissions_policy/policy_disposition.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -132,10 +131,12 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/widget/frame_widget.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "ui/display/screen_info.h"
#include "v8/include/v8.h"
namespace blink {
@@ -258,6 +259,15 @@ bool LocalDOMWindow::IsCrossSiteSubframe() const {
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
}
+bool LocalDOMWindow::IsCrossSiteSubframeIncludingScheme() const {
+ return GetFrame() && top()->GetFrame() &&
+ !top()
+ ->GetFrame()
+ ->GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->IsSameSiteWith(GetSecurityContext().GetSecurityOrigin());
+}
+
LocalDOMWindow* LocalDOMWindow::From(const ScriptState* script_state) {
v8::HandleScope scope(script_state->GetIsolate());
return blink::ToLocalDOMWindow(script_state->GetContext());
@@ -330,7 +340,7 @@ HttpsState LocalDOMWindow::GetHttpsState() const {
return CalculateHttpsState(GetSecurityOrigin());
}
-ResourceFetcher* LocalDOMWindow::Fetcher() const {
+ResourceFetcher* LocalDOMWindow::Fetcher() {
return document()->Fetcher();
}
@@ -437,6 +447,11 @@ void LocalDOMWindow::ReportPermissionsPolicyViolation(
mojom::blink::PermissionsPolicyFeature feature,
mojom::blink::PolicyDisposition disposition,
const String& message) const {
+ if (disposition == mojom::blink::PolicyDisposition::kEnforce) {
+ const_cast<LocalDOMWindow*>(this)->CountPermissionsPolicyUsage(
+ feature, UseCounterImpl::PermissionsPolicyUsageType::kViolation);
+ }
+
if (!RuntimeEnabledFeatures::FeaturePolicyReportingEnabled(this))
return;
if (!GetFrame())
@@ -463,8 +478,6 @@ void LocalDOMWindow::ReportPermissionsPolicyViolation(
GetFrame()->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kViolation,
mojom::blink::ConsoleMessageLevel::kError, body->message()));
-
- CountPermissionsPolicyViolation(feature);
}
}
@@ -598,13 +611,14 @@ void LocalDOMWindow::CountUse(mojom::WebFeature feature) {
loader->CountUse(feature);
}
-void LocalDOMWindow::CountPermissionsPolicyViolation(
- mojom::blink::PermissionsPolicyFeature feature) const {
+void LocalDOMWindow::CountPermissionsPolicyUsage(
+ mojom::blink::PermissionsPolicyFeature feature,
+ UseCounterImpl::PermissionsPolicyUsageType type) {
if (!GetFrame())
return;
if (auto* loader = GetFrame()->Loader().GetDocumentLoader()) {
- loader->GetUseCounter().CountPermissionsPolicyViolation(feature,
- *GetFrame());
+ loader->GetUseCounter().CountPermissionsPolicyUsage(feature, type,
+ *GetFrame());
}
}
@@ -616,17 +630,8 @@ void LocalDOMWindow::CountUseOnlyInCrossOriginIframe(
void LocalDOMWindow::CountUseOnlyInCrossSiteIframe(
mojom::blink::WebFeature feature) {
- if (!GetFrame())
- return;
-
- if (top()->GetFrame() &&
- !top()
- ->GetFrame()
- ->GetSecurityContext()
- ->GetSecurityOrigin()
- ->IsSameSiteWith(GetSecurityContext().GetSecurityOrigin())) {
+ if (IsCrossSiteSubframeIncludingScheme())
CountUse(feature);
- }
}
bool LocalDOMWindow::HasInsecureContextInAncestors() {
@@ -971,10 +976,9 @@ Navigator* LocalDOMWindow::navigator() {
return navigator_.Get();
}
-void LocalDOMWindow::SchedulePostMessage(
- MessageEvent* event,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source) {
+void LocalDOMWindow::SchedulePostMessage(PostedMessage* posted_message) {
+ LocalDOMWindow* source = posted_message->source;
+
// Record UKM metrics for postMessage event.
ukm::SourceId source_frame_ukm_source_id = source->UkmSourceID();
if (ShouldRecordPostMessageIncomingFrameUkmEvent(
@@ -984,6 +988,14 @@ void LocalDOMWindow::SchedulePostMessage(
.Record(UkmRecorder());
}
+ // Convert the posted message to a MessageEvent so it can be unpacked for
+ // local dispatch.
+ MessageEvent* event = MessageEvent::Create(
+ std::move(posted_message->channels), std::move(posted_message->data),
+ posted_message->source_origin->ToString(), String(),
+ posted_message->source, posted_message->user_activation,
+ posted_message->delegate_payment_request);
+
// Allowing unbounded amounts of messages to build up for a suspended context
// is problematic; consider imposing a limit or other restriction if this
// surfaces often as a problem (see crbug.com/587012).
@@ -992,7 +1004,8 @@ void LocalDOMWindow::SchedulePostMessage(
->PostTask(
FROM_HERE,
WTF::Bind(&LocalDOMWindow::DispatchPostMessage, WrapPersistent(this),
- WrapPersistent(event), std::move(target),
+ WrapPersistent(event),
+ std::move(posted_message->target_origin),
std::move(location), source->GetAgent()->cluster_id()));
probe::AsyncTaskScheduled(this, "postMessage", event->async_task_id());
}
@@ -1638,7 +1651,7 @@ void LocalDOMWindow::scrollTo(const ScrollToOptions* scroll_to_options) const {
}
void LocalDOMWindow::moveBy(int x, int y) const {
- if (!GetFrame() || !GetFrame()->IsMainFrame())
+ if (!GetFrame() || !GetFrame()->IsMainFrame() || document()->IsPrerendering())
return;
LocalFrame* frame = GetFrame();
@@ -1654,7 +1667,7 @@ void LocalDOMWindow::moveBy(int x, int y) const {
}
void LocalDOMWindow::moveTo(int x, int y) const {
- if (!GetFrame() || !GetFrame()->IsMainFrame())
+ if (!GetFrame() || !GetFrame()->IsMainFrame() || document()->IsPrerendering())
return;
LocalFrame* frame = GetFrame();
@@ -1670,7 +1683,7 @@ void LocalDOMWindow::moveTo(int x, int y) const {
}
void LocalDOMWindow::resizeBy(int x, int y) const {
- if (!GetFrame() || !GetFrame()->IsMainFrame())
+ if (!GetFrame() || !GetFrame()->IsMainFrame() || document()->IsPrerendering())
return;
LocalFrame* frame = GetFrame();
@@ -1685,7 +1698,7 @@ void LocalDOMWindow::resizeBy(int x, int y) const {
}
void LocalDOMWindow::resizeTo(int width, int height) const {
- if (!GetFrame() || !GetFrame()->IsMainFrame())
+ if (!GetFrame() || !GetFrame()->IsMainFrame() || document()->IsPrerendering())
return;
LocalFrame* frame = GetFrame();
@@ -2113,4 +2126,8 @@ ukm::SourceId LocalDOMWindow::UkmSourceID() const {
return document_->UkmSourceID();
}
+void LocalDOMWindow::SetStorageKey(const BlinkStorageKey& storage_key) {
+ storage_key_ = storage_key;
+}
+
} // 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 32a0a0568a5..ee1dcc002f0 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
@@ -43,10 +43,12 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/use_counter_impl.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -154,7 +156,7 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
String UserAgent() const final;
UserAgentMetadata GetUserAgentMetadata() const final;
HttpsState GetHttpsState() const final;
- ResourceFetcher* Fetcher() const final;
+ ResourceFetcher* Fetcher() final;
bool CanExecuteScripts(ReasonForCallingCanExecuteScripts) final;
void ExceptionThrown(ErrorEvent*) final;
void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
@@ -192,7 +194,12 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// Count |feature| only when this window is associated with a cross-site
// iframe. A "site" is a scheme and registrable domain.
- void CountUseOnlyInCrossSiteIframe(mojom::blink::WebFeature feature);
+ void CountUseOnlyInCrossSiteIframe(mojom::blink::WebFeature feature) override;
+
+ // Count permissions policy feature usage through use counter.
+ void CountPermissionsPolicyUsage(
+ mojom::blink::PermissionsPolicyFeature feature,
+ UseCounterImpl::PermissionsPolicyUsageType type);
Document* InstallNewDocument(const DocumentInit&);
@@ -405,11 +412,12 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// Returns true if this window is cross-site to the main frame. Defaults to
// false in a detached window.
// Note: This uses an outdated definition of "site" which only includes the
- // registrable domain and not the scheme. For recording metrics in 3rd party
- // contexts, prefer CountUseOnlyInCrossSiteIframe() which uses HTML's
- // definition of "site" as a registrable domain and scheme.
+ // registrable domain and not the scheme. IsCrossSiteSubframeIncludingScheme()
+ // uses HTML's definition of "site" as a registrable domain and scheme.
bool IsCrossSiteSubframe() const;
+ bool IsCrossSiteSubframeIncludingScheme() const;
+
void DispatchPersistedPageshowEvent(base::TimeTicks navigation_start);
void DispatchPagehideEvent(PageTransitionEventPersistence persistence);
@@ -431,6 +439,9 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
ukm::UkmRecorder* UkmRecorder() override;
ukm::SourceId UkmSourceID() const override;
+ const BlinkStorageKey& GetStorageKey() const { return storage_key_; }
+ void SetStorageKey(const BlinkStorageKey& storage_key);
+
protected:
// EventTarget overrides.
void AddedEventListener(const AtomicString& event_type,
@@ -439,9 +450,7 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
const RegisteredEventListener&) override;
// Protected DOMWindow overrides.
- void SchedulePostMessage(MessageEvent*,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source) override;
+ void SchedulePostMessage(PostedMessage*) override;
private:
// Intentionally private to prevent redundant checks when the type is
@@ -458,12 +467,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// Return the viewport size including scrollbars.
IntSize GetViewportSize() const;
- // Count feature disabled by Permissions Policy through use counter.
- // The method is marked const as its caller |ReportPermissionsPolicyViolation|
- // is marked const.
- void CountPermissionsPolicyViolation(
- mojom::blink::PermissionsPolicyFeature feature) const;
-
Member<ScriptController> script_controller_;
Member<Document> document_;
@@ -548,6 +551,9 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// this UKM is logged.
// TODO(crbug.com/1112491): Remove when no longer needed.
Deque<ukm::SourceId> post_message_ukm_recorded_source_ids_;
+
+ // The storage key for this LocalDomWindow.
+ BlinkStorageKey storage_key_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/frame/local_dom_window_test.cc b/chromium/third_party/blink/renderer/core/frame/local_dom_window_test.cc
index f598a010e51..6c3627369a6 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_dom_window_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_dom_window_test.cc
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/threading.h"
namespace blink {
@@ -192,6 +193,9 @@ TEST_F(LocalDOMWindowTest, EnforceSandboxFlags) {
{
url::ScopedSchemeRegistryForTests scoped_registry;
url::AddStandardScheme("very-special-scheme", url::SCHEME_WITH_HOST);
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RegisterURLSchemeBypassingSecureContextCheck(
"very-special-scheme");
NavigateWithSandbox(KURL("very-special-scheme://example.test"));
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 fab2d2cbc44..1dd636810e0 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.cc
@@ -50,7 +50,6 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_input_event_attribution.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
-#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
@@ -73,16 +72,15 @@
#include "third_party/blink/public/web/web_content_capture_client.h"
#include "third_party/blink/public/web/web_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/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/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/clipboard/raw_system_clipboard.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/core_probe_sink.h"
#include "third_party/blink/renderer/core/css/background_color_paint_image_generator.h"
+#include "third_party/blink/renderer/core/css/clip_path_paint_image_generator.h"
#include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/child_frame_disconnector.h"
@@ -112,9 +110,9 @@
#include "third_party/blink/renderer/core/frame/frame_overlay.h"
#include "third_party/blink/renderer/core/frame/frame_serializer.h"
#include "third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.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_client.h"
+#include "third_party/blink/renderer/core/frame/local_frame_mojo_handler.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/pausable_script_executor.h"
@@ -125,7 +123,6 @@
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
-#include "third_party/blink/renderer/core/frame/savable_resources.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/smart_clip.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
@@ -134,7 +131,6 @@
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/frame/window_controls_overlay.h"
-#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
@@ -143,25 +139,20 @@
#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/portal/dom_window_portal_host.h"
-#include "third_party/blink/renderer/core/html/portal/portal_activate_event.h"
-#include "third_party/blink/renderer/core/html/portal/portal_host.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/inspector_issue_reporter.h"
#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/inspector_task_runner.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.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/layout/text_autosizer.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/idleness_detector.h"
-#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
+#include "third_party/blink/renderer/core/loader/prerender_handle.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -176,7 +167,6 @@
#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/paint_layer_scrollable_area.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/core/script/classic_script.h"
#include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
@@ -228,9 +218,6 @@ namespace blink {
namespace {
-constexpr char kInvalidWorldID[] =
- "JavaScriptExecuteRequestInIsolatedWorld gets an invalid world id.";
-
// Maintain a global (statically-allocated) hash map indexed by the the result
// of hashing the |frame_token| passed on creation of a LocalFrame object.
using LocalFramesByTokenMap = HeapHashMap<uint64_t, WeakMember<LocalFrame>>;
@@ -288,9 +275,9 @@ class BackForwardCacheBufferLimitTracker {
};
BackForwardCacheBufferLimitTracker& GetBackForwardCacheBufferLimitTracker() {
- static base::NoDestructor<BackForwardCacheBufferLimitTracker>
+ static BackForwardCacheBufferLimitTracker
back_forward_cache_buffer_limit_tracker;
- return *back_forward_cache_buffer_limit_tracker;
+ return back_forward_cache_buffer_limit_tracker;
}
inline float ParentPageZoomFactor(LocalFrame* frame) {
@@ -303,14 +290,6 @@ inline float ParentTextZoomFactor(LocalFrame* frame) {
return parent_local_frame ? parent_local_frame->TextZoomFactor() : 1;
}
-#if defined(OS_MAC)
-uint32_t GetCurrentCursorPositionInFrame(LocalFrame* local_frame) {
- blink::WebRange range =
- WebLocalFrameImpl::FromFrame(local_frame)->SelectionRange();
- return range.IsNull() ? 0U : static_cast<uint32_t>(range.StartOffset());
-}
-#endif
-
// Convert a data url to a message pipe handle that corresponds to a remote
// blob, so that it can be passed across processes.
mojo::PendingRemote<mojom::blink::Blob> DataURLToBlob(const String& data_url) {
@@ -322,19 +301,6 @@ mojo::PendingRemote<mojom::blink::Blob> DataURLToBlob(const String& data_url) {
return blob_data_handle->CloneBlobRemote();
}
-HitTestResult HitTestResultForRootFramePos(
- LocalFrame* main_frame,
- const PhysicalOffset& pos_in_root_frame) {
- DCHECK(main_frame->IsMainFrame());
-
- HitTestLocation location(
- main_frame->View()->ConvertFromRootFrame(pos_in_root_frame));
- HitTestResult result = main_frame->GetEventHandler().HitTestResultAtLocation(
- location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
- result.SetToShadowHostIfInRestrictedShadowRoot();
- return result;
-}
-
RemoteFrame* SourceFrameForOptionalToken(
const absl::optional<RemoteFrameToken>& source_frame_token) {
if (!source_frame_token)
@@ -342,167 +308,6 @@ RemoteFrame* SourceFrameForOptionalToken(
return RemoteFrame::FromFrameToken(source_frame_token.value());
}
-class WebBundleGenerationDelegate
- : public WebFrameSerializer::MHTMLPartsGenerationDelegate {
- STACK_ALLOCATED();
-
- public:
- WebBundleGenerationDelegate() = default;
- ~WebBundleGenerationDelegate() = default;
-
- WebBundleGenerationDelegate(const WebBundleGenerationDelegate&) = delete;
- WebBundleGenerationDelegate& operator=(const WebBundleGenerationDelegate&) =
- delete;
-
- bool ShouldSkipResource(const WebURL& url) override { return false; }
- bool UseBinaryEncoding() override { return false; }
- bool RemovePopupOverlay() override { return false; }
- bool UsePageProblemDetectors() override { return false; }
-};
-
-class ResourceSnapshotForWebBundleImpl
- : public data_decoder::mojom::blink::ResourceSnapshotForWebBundle {
- public:
- explicit ResourceSnapshotForWebBundleImpl(Deque<SerializedResource> resources)
- : resources_(std::move(resources)) {}
- ~ResourceSnapshotForWebBundleImpl() override = default;
-
- ResourceSnapshotForWebBundleImpl(const ResourceSnapshotForWebBundleImpl&) =
- delete;
- ResourceSnapshotForWebBundleImpl& operator=(
- const ResourceSnapshotForWebBundleImpl&) = delete;
-
- // data_decoder::mojom::blink::ResourceSnapshotForWebBundle:
- void GetResourceCount(GetResourceCountCallback callback) override {
- std::move(callback).Run(resources_.size());
- }
- void GetResourceInfo(uint64_t index,
- GetResourceInfoCallback callback) override {
- if (index >= resources_.size()) {
- std::move(callback).Run(nullptr);
- return;
- }
- const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
- auto info = data_decoder::mojom::blink::SerializedResourceInfo::New();
- info->url = resource.url;
- info->mime_type = resource.mime_type;
- info->size = resource.data ? resource.data->size() : 0;
- std::move(callback).Run(std::move(info));
- }
- void GetResourceBody(uint64_t index,
- GetResourceBodyCallback callback) override {
- if (index >= resources_.size()) {
- std::move(callback).Run(absl::nullopt);
- return;
- }
- const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
- if (!resource.data) {
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::move(callback).Run(
- mojo_base::BigBuffer(resource.data->CopyAs<std::vector<uint8_t>>()));
- }
-
- private:
- const Deque<SerializedResource> resources_;
-};
-
-class ActiveURLMessageFilter : public mojo::MessageFilter {
- public:
- explicit ActiveURLMessageFilter(LocalFrame* local_frame)
- : local_frame_(local_frame) {}
-
- ~ActiveURLMessageFilter() override {
- if (debug_url_set_) {
- Platform::Current()->SetActiveURL(WebURL(), WebString());
- }
- }
-
- // mojo::MessageFilter overrides.
- bool WillDispatch(mojo::Message* message) override {
- // We expect local_frame_ always to be set because this MessageFilter
- // is owned by the LocalFrame. We do not want to introduce a Persistent
- // reference so we don't cause a cycle. If you hit this CHECK then you
- // likely didn't reset your mojo receiver in Detach.
- CHECK(local_frame_);
- debug_url_set_ = true;
- Platform::Current()->SetActiveURL(local_frame_->GetDocument()->Url(),
- local_frame_->Top()
- ->GetSecurityContext()
- ->GetSecurityOrigin()
- ->ToString());
- return true;
- }
-
- void DidDispatchOrReject(mojo::Message* message, bool accepted) override {
- Platform::Current()->SetActiveURL(WebURL(), WebString());
- debug_url_set_ = false;
- }
-
- private:
- WeakPersistent<LocalFrame> local_frame_;
- bool debug_url_set_ = false;
-};
-
-v8::Local<v8::Context> MainWorldScriptContext(LocalFrame* local_frame) {
- ScriptState* script_state = ToScriptStateForMainWorld(local_frame);
- DCHECK(script_state);
- return script_state->GetContext();
-}
-
-base::Value GetJavaScriptExecutionResult(v8::Local<v8::Value> result,
- LocalFrame* local_frame,
- WebV8ValueConverter* converter) {
- if (!result.IsEmpty()) {
- v8::Local<v8::Context> context = MainWorldScriptContext(local_frame);
- v8::Context::Scope context_scope(context);
- std::unique_ptr<base::Value> new_value =
- converter->FromV8Value(result, context);
- if (new_value)
- return std::move(*new_value);
- }
- return base::Value();
-}
-
-v8::MaybeLocal<v8::Value> GetProperty(v8::Local<v8::Context> context,
- v8::Local<v8::Value> object,
- const String& name) {
- v8::Isolate* isolate = context->GetIsolate();
- v8::Local<v8::String> name_str = V8String(isolate, name);
- v8::Local<v8::Object> object_obj;
- if (!object->ToObject(context).ToLocal(&object_obj)) {
- return v8::MaybeLocal<v8::Value>();
- }
- return object_obj->Get(context, name_str);
-}
-
-v8::MaybeLocal<v8::Value> CallMethodOnFrame(LocalFrame* local_frame,
- const String& object_name,
- const String& method_name,
- base::Value arguments,
- WebV8ValueConverter* converter) {
- v8::Local<v8::Context> context = MainWorldScriptContext(local_frame);
-
- v8::Context::Scope context_scope(context);
- WTF::Vector<v8::Local<v8::Value>> args;
- for (auto const& argument : arguments.GetList()) {
- args.push_back(converter->ToV8Value(&argument, context));
- }
-
- v8::Local<v8::Value> object;
- v8::Local<v8::Value> method;
- if (!GetProperty(context, context->Global(), object_name).ToLocal(&object) ||
- !GetProperty(context, object, method_name).ToLocal(&method)) {
- return v8::MaybeLocal<v8::Value>();
- }
-
- return local_frame->DomWindow()
- ->GetScriptController()
- .EvaluateMethodInMainWorld(v8::Local<v8::Function>::Cast(method), object,
- static_cast<int>(args.size()), args.data());
-}
-
} // namespace
template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
@@ -521,26 +326,10 @@ void LocalFrame::Init(Frame* opener,
CoreInitializer::GetInstance().InitLocalFrame(*this);
- GetRemoteNavigationAssociatedInterfaces()->GetInterface(
- local_frame_host_remote_.BindNewEndpointAndPassReceiver(
- GetTaskRunner(blink::TaskType::kInternalDefault)));
- GetRemoteNavigationAssociatedInterfaces()->GetInterface(
- back_forward_cache_controller_host_remote_.BindNewEndpointAndPassReceiver(
- GetTaskRunner(blink::TaskType::kInternalDefault)));
- GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
- &LocalFrame::BindToReceiver, WrapWeakPersistent(this)));
- GetInterfaceRegistry()->AddInterface(
- WTF::BindRepeating(&LocalFrame::BindToHighPriorityReceiver,
- WrapWeakPersistent(this)),
- GetTaskRunner(blink::TaskType::kInternalHighPriorityLocalFrame));
- GetInterfaceRegistry()->AddAssociatedInterface(
- WTF::BindRepeating(&LocalFrame::BindFullscreenVideoElementReceiver,
- WrapWeakPersistent(this)));
-
- if (IsMainFrame()) {
- GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
- &LocalFrame::BindTextFragmentReceiver, WrapWeakPersistent(this)));
- }
+ GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
+ &LocalFrame::BindTextFragmentReceiver, WrapWeakPersistent(this)));
+ DCHECK(!mojo_handler_);
+ mojo_handler_ = MakeGarbageCollected<LocalFrameMojoHandler>(*this);
SetOpenerDoNotNotify(opener);
loader_.Init(std::move(policy_container));
@@ -627,22 +416,13 @@ void LocalFrame::Trace(Visitor* visitor) const {
visitor->Trace(smooth_scroll_sequencer_);
visitor->Trace(content_capture_manager_);
visitor->Trace(system_clipboard_);
- visitor->Trace(raw_system_clipboard_);
visitor->Trace(virtual_keyboard_overlay_changed_observers_);
visitor->Trace(pause_handle_receivers_);
- visitor->Trace(reporting_service_);
-#if defined(OS_MAC)
- visitor->Trace(text_input_host_);
-#endif
- visitor->Trace(local_frame_host_remote_);
- visitor->Trace(back_forward_cache_controller_host_remote_);
- visitor->Trace(receiver_);
- visitor->Trace(main_frame_receiver_);
- visitor->Trace(high_priority_frame_receiver_);
- visitor->Trace(fullscreen_video_receiver_);
+ visitor->Trace(mojo_handler_);
visitor->Trace(text_fragment_handler_);
visitor->Trace(saved_scroll_offsets_);
visitor->Trace(background_color_paint_image_generator_);
+ visitor->Trace(clip_path_paint_image_generator_);
Frame::Trace(visitor);
Supplementable<LocalFrame>::Trace(visitor);
}
@@ -666,27 +446,13 @@ void LocalFrame::Navigate(FrameLoadRequest& request,
request.GetResourceRequest().Url().GetString().Utf8(),
"load_type", static_cast<int>(frame_load_type));
- if (request.ClientRedirectReason() != ClientNavigationReason::kNone) {
+ if (request.ClientRedirectReason() != ClientNavigationReason::kNone)
probe::FrameScheduledNavigation(this, request.GetResourceRequest().Url(),
base::TimeDelta(),
request.ClientRedirectReason());
- // Non-user navigation before the page has finished firing onload should not
- // create a new back/forward item. The spec only explicitly mentions this in
- // the context of navigating an iframe.
- if (!GetDocument()->LoadEventFinished() &&
- !HasTransientUserActivation(this) &&
- request.ClientRedirectReason() !=
- ClientNavigationReason::kAnchorClick) {
- frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
- }
- }
- // Navigations in portal contexts do not create back/forward entries.
- // TODO(mcnee): Similarly, we need to restrict orphaned contexts.
- if (GetPage()->InsidePortal() &&
- frame_load_type == WebFrameLoadType::kStandard) {
+ if (NavigationShouldReplaceCurrentHistoryEntry(request, frame_load_type))
frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
- }
const ClientNavigationReason client_redirect_reason =
request.ClientRedirectReason();
@@ -696,38 +462,33 @@ void LocalFrame::Navigate(FrameLoadRequest& request,
probe::FrameClearedScheduledNavigation(this);
}
-LocalFrame::JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
- LocalFrame* local_frame,
- bool wants_result,
- JavaScriptExecuteRequestInIsolatedWorldCallback callback)
- : local_frame_(local_frame),
- wants_result_(wants_result),
- callback_(std::move(callback)) {}
-
-LocalFrame::JavaScriptIsolatedWorldRequest::~JavaScriptIsolatedWorldRequest() =
- default;
-
-void LocalFrame::JavaScriptIsolatedWorldRequest::Completed(
- const WebVector<v8::Local<v8::Value>>& result) {
- base::Value value;
- if (!result.empty() && !result.begin()->IsEmpty() && wants_result_) {
- // It's safe to always use the main world context when converting
- // here. V8ValueConverter shouldn't actually care about the context
- // scope, and it switches to v8::Object's creation context when
- // encountered. (from extensions/renderer/script_injection.cc)
- v8::Local<v8::Context> context = MainWorldScriptContext(local_frame_);
- v8::Context::Scope context_scope(context);
- std::unique_ptr<WebV8ValueConverter> converter =
- Platform::Current()->CreateWebV8ValueConverter();
- converter->SetDateAllowed(true);
- converter->SetRegExpAllowed(true);
- std::unique_ptr<base::Value> new_value =
- converter->FromV8Value(*result.begin(), context);
- if (new_value)
- value = base::Value::FromUniquePtrValue(std::move(new_value));
- }
-
- std::move(callback_).Run(std::move(value));
+bool LocalFrame::NavigationShouldReplaceCurrentHistoryEntry(
+ const FrameLoadRequest& request,
+ WebFrameLoadType frame_load_type) {
+ // Non-user navigation before the page has finished firing onload should not
+ // create a new back/forward item. The spec only explicitly mentions this in
+ // the context of navigating an iframe.
+ if (request.ClientRedirectReason() != ClientNavigationReason::kNone &&
+ !GetDocument()->LoadEventFinished() &&
+ !HasTransientUserActivation(this) &&
+ request.ClientRedirectReason() != ClientNavigationReason::kAnchorClick)
+ return true;
+ return frame_load_type == WebFrameLoadType::kStandard &&
+ ShouldMaintainTrivialSessionHistory();
+
+ // TODO(http://crbug.com/1197384): We may want to assert that
+ // WebFrameLoadType is never kStandard in prerendered pages/portals before
+ // commit. DCHECK can be in FrameLoader::CommitNavigation or somewhere
+ // similar.
+}
+
+bool LocalFrame::ShouldMaintainTrivialSessionHistory() const {
+ // TODO(https://crbug.com/1197384): We may have to add fenced frames. This
+ // should be kept in sync with NavigationControllerImpl version,
+ // NavigationControllerImpl::ShouldMaintainTrivialSessionHistory.
+ //
+ // TODO(mcnee): Similarly, we need to restrict orphaned contexts.
+ return GetPage()->InsidePortal() || GetDocument()->IsPrerendering();
}
bool LocalFrame::DetachImpl(FrameDetachType type) {
@@ -764,6 +525,13 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
GetDocument());
loader_.DispatchUnloadEvent(nullptr, nullptr);
+ if (evict_cached_session_storage_on_freeze_or_unload_) {
+ // Evicts the cached data of Session Storage to avoid reusing old data in
+ // the cache after the session storage has been modified by another renderer
+ // process.
+ CoreInitializer::GetInstance().EvictSessionStorageCachedData(
+ GetDocument()->GetPage());
+ }
if (!Client())
return false;
@@ -810,6 +578,8 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
// was created on LocalRoot.
if (background_color_paint_image_generator_)
background_color_paint_image_generator_->Shutdown();
+ if (clip_path_paint_image_generator_)
+ clip_path_paint_image_generator_->Shutdown();
}
idleness_detector_->Shutdown();
if (inspector_issue_reporter_)
@@ -823,9 +593,8 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
content_capture_manager_ = nullptr;
}
- if (text_fragment_handler_) {
- text_fragment_handler_->GetTextFragmentSelectorGenerator()->Detach();
- }
+ if (text_fragment_handler_)
+ text_fragment_handler_->DidDetachDocumentOrFrame();
GetBackForwardCacheBufferLimitTracker().DidRemoveFrameFromBackForwardCache(
total_bytes_buffered_while_in_back_forward_cache_);
@@ -844,9 +613,7 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
supplements_.clear();
frame_scheduler_.reset();
- receiver_.reset();
- main_frame_receiver_.reset();
- high_priority_frame_receiver_.reset();
+ mojo_handler_->DidDetachFrame();
WeakIdentifierMap<LocalFrame>::NotifyObjectDestroyed(this);
return true;
@@ -862,6 +629,10 @@ void LocalFrame::CheckCompleted() {
BackgroundColorPaintImageGenerator*
LocalFrame::GetBackgroundColorPaintImageGenerator() {
+ // There is no compositor thread in certain testing environment, and we should
+ // not composite background color animation in those cases.
+ if (!Thread::CompositorThread())
+ return nullptr;
LocalFrame& local_root = LocalFrameRoot();
// One background color paint worklet per root frame.
if (!local_root.background_color_paint_image_generator_) {
@@ -871,6 +642,16 @@ LocalFrame::GetBackgroundColorPaintImageGenerator() {
return local_root.background_color_paint_image_generator_.Get();
}
+ClipPathPaintImageGenerator* LocalFrame::GetClipPathPaintImageGenerator() {
+ LocalFrame& local_root = LocalFrameRoot();
+ // One clip path paint worklet per root frame.
+ if (!local_root.clip_path_paint_image_generator_) {
+ local_root.clip_path_paint_image_generator_ =
+ ClipPathPaintImageGenerator::Create(local_root);
+ }
+ return local_root.clip_path_paint_image_generator_.Get();
+}
+
const SecurityContext* LocalFrame::GetSecurityContext() const {
return DomWindow() ? &DomWindow()->GetSecurityContext() : nullptr;
}
@@ -977,17 +758,6 @@ bool LocalFrame::ConsumePaymentRequestToken() {
return payment_request_token_.ConsumeIfActive();
}
-void LocalFrame::SetOptimizationGuideHints(
- mojom::blink::BlinkOptimizationGuideHintsPtr hints) {
- DCHECK(hints);
- optimization_guide_hints_ = std::move(hints);
- if (optimization_guide_hints_->delay_competing_low_priority_requests_hints) {
- GetDocument()->Fetcher()->SetOptimizationGuideHints(
- std::move(optimization_guide_hints_
- ->delay_competing_low_priority_requests_hints));
- }
-}
-
void LocalFrame::Reload(WebFrameLoadType load_type) {
DCHECK(IsReloadLoadType(load_type));
if (!loader_.GetDocumentLoader()->GetHistoryItem())
@@ -1022,13 +792,11 @@ void LocalFrame::SetDOMWindow(LocalDOMWindow* dom_window) {
DCHECK(dom_window);
if (DomWindow()) {
DomWindow()->Reset();
- // SystemClipboard and RawSystemClipboard uses HeapMojo wrappers. HeapMojo
+ // SystemClipboard uses HeapMojo wrappers. HeapMojo
// wrappers uses LocalDOMWindow (ExecutionContext) to reset the mojo
// objects when the ExecutionContext was destroyed. So when new
- // LocalDOMWindow was set, we need to create new SystemClipboard and
- // RawSystemClipboard.
+ // LocalDOMWindow was set, we need to create new SystemClipboard.
system_clipboard_ = nullptr;
- raw_system_clipboard_ = nullptr;
}
GetWindowProxyManager()->ClearForNavigation();
dom_window_ = dom_window;
@@ -1086,11 +854,9 @@ void LocalFrame::RemoveBackForwardCacheEviction() {
->SetAbortScriptExecution(nullptr);
// The page is being restored, and from this point eviction should not happen
- // for any reason. Change the deferring state from
- // |kDeferredWithBackForwardCache| to |kDeferred| so that network related
- // eviction cannot happen.
- GetDocument()->Fetcher()->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferred);
+ // for any reason. Change the deferring state from |kBufferIncoming| to
+ // |kStrict| so that network related eviction cannot happen.
+ GetDocument()->Fetcher()->SetDefersLoading(LoaderFreezeMode::kStrict);
}
void LocalFrame::SetTextDirection(base::i18n::TextDirection direction) {
@@ -1241,10 +1007,13 @@ void LocalFrame::DidFocus() {
GetLocalFrameHostRemote().DidFocusFrame();
}
-void LocalFrame::DidChangeThemeColor() {
+void LocalFrame::DidChangeThemeColor(bool update_theme_color_cache) {
if (Tree().Parent())
return;
+ if (update_theme_color_cache)
+ GetDocument()->UpdateThemeColorCache();
+
absl::optional<Color> color = GetDocument()->ThemeColor();
absl::optional<SkColor> sk_color;
if (color)
@@ -1583,6 +1352,10 @@ void LocalFrame::UpdateCSSFoldEnvironmentVariables(
}
}
+device::mojom::blink::DevicePostureType LocalFrame::GetDevicePosture() {
+ return mojo_handler_->GetDevicePosture();
+}
+
double LocalFrame::DevicePixelRatio() const {
if (!page_)
return 0;
@@ -1739,19 +1512,12 @@ LocalFrame::LocalFrame(LocalFrameClient* client,
!IsMainFrame() && ad_tracker_ &&
ad_tracker_->IsAdScriptInStack(AdTracker::StackType::kBottomAndTop);
if (IsMainFrame()) {
- text_fragment_handler_ = MakeGarbageCollected<TextFragmentHandler>(this);
+ CreateTextFragmentHandler();
}
Initialize();
probe::FrameAttachedToParent(this);
-#if defined(OS_MAC)
- // It should be bound before accessing TextInputHost which is the interface to
- // respond to GetCharacterIndexAtPoint.
- GetBrowserInterfaceBroker().GetInterface(
- text_input_host_.BindNewPipeAndPassReceiver(
- GetTaskRunner(blink::TaskType::kInternalDefault)));
-#endif
}
FrameScheduler* LocalFrame::GetFrameScheduler() {
@@ -2355,16 +2121,18 @@ void LocalFrame::ForceSynchronousDocumentInstall(
scoped_refptr<const SharedBuffer> data) {
CHECK(GetDocument()->IsInitialEmptyDocument());
DCHECK(!Client()->IsLocalFrameClientImpl());
+ DCHECK(GetPage());
// Any Document requires Shutdown() before detach, even the initial empty
// document.
GetDocument()->Shutdown();
DomWindow()->ClearForReuse();
- Document* document =
- DomWindow()->InstallNewDocument(DocumentInit::Create()
- .WithWindow(DomWindow(), nullptr)
- .WithTypeFrom(mime_type));
+ Document* document = DomWindow()->InstallNewDocument(
+ DocumentInit::Create()
+ .WithWindow(DomWindow(), nullptr)
+ .WithTypeFrom(mime_type)
+ .ForPrerendering(GetPage()->IsPrerendering()));
DocumentParser* parser = document->OpenForNavigation(
kForceSynchronousParsing, mime_type, AtomicString("UTF-8"));
for (const auto& segment : *data)
@@ -2391,13 +2159,45 @@ bool LocalFrame::IsProvisional() const {
return Owner()->ContentFrame() != this;
}
-void LocalFrame::SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) {
+bool LocalFrame::IsAdSubframe() const {
+ return ad_evidence_ && ad_evidence_->IndicatesAdSubframe();
+}
+
+bool LocalFrame::IsAdRoot() const {
+ return IsAdSubframe() && !ad_evidence_->parent_is_ad();
+}
+
+void LocalFrame::SetAdEvidence(const blink::FrameAdEvidence& ad_evidence) {
DCHECK(!IsMainFrame());
+ DCHECK(ad_evidence.is_complete());
+
+ // Once set, `is_subframe_created_by_ad_script_` should not be unset.
+ DCHECK(!is_subframe_created_by_ad_script_ ||
+ ad_evidence.created_by_ad_script() ==
+ blink::mojom::FrameCreationStackEvidence::kCreatedByAdScript);
+ is_subframe_created_by_ad_script_ =
+ ad_evidence.created_by_ad_script() ==
+ blink::mojom::FrameCreationStackEvidence::kCreatedByAdScript;
+
+ if (ad_evidence_.has_value()) {
+ // Check that replacing with the new ad evidence doesn't violate invariants.
+ // The parent frame's ad status should not change as it can only change due
+ // to a cross-document commit, which would remove this child frame.
+ DCHECK_EQ(ad_evidence_->parent_is_ad(), ad_evidence.parent_is_ad());
+
+ // The most restrictive filter list result cannot become less restrictive,
+ // by definition.
+ DCHECK_LE(ad_evidence_->most_restrictive_filter_list_result(),
+ ad_evidence.most_restrictive_filter_list_result());
+ }
+
+ bool was_ad_subframe = IsAdSubframe();
+ bool is_ad_subframe = ad_evidence.IndicatesAdSubframe();
+ ad_evidence_ = ad_evidence;
- if (ad_frame_type_ == ad_frame_type)
+ if (was_ad_subframe == is_ad_subframe)
return;
- bool is_ad_subframe = ad_frame_type != blink::mojom::AdFrameType::kNonAd;
if (auto* document = GetDocument()) {
// TODO(fdoray): It is possible for the document not to be installed when
// this method is called. Consider inheriting frame bit in the graph instead
@@ -2407,7 +2207,6 @@ void LocalFrame::SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) {
document_resource_coordinator->SetIsAdFrame(is_ad_subframe);
}
- ad_frame_type_ = ad_frame_type;
UpdateAdHighlight();
frame_scheduler_->SetIsAdFrame(is_ad_subframe);
@@ -2419,21 +2218,6 @@ void LocalFrame::SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) {
}
}
-void LocalFrame::SetAdEvidence(const blink::FrameAdEvidence& ad_evidence) {
- DCHECK(!IsMainFrame());
-
- if (ad_evidence_.has_value()) {
- // Check that replacing with the new ad evidence doesn't violate invariants.
- DCHECK_EQ(ad_evidence_->parent_is_ad(), ad_evidence.parent_is_ad());
- DCHECK_LE(ad_evidence_->is_complete(), ad_evidence.is_complete());
- DCHECK_LE(ad_evidence_->created_by_ad_script(),
- ad_evidence.created_by_ad_script());
- DCHECK_LE(ad_evidence_->most_restrictive_filter_list_result(),
- ad_evidence.most_restrictive_filter_list_result());
- }
- ad_evidence_ = ad_evidence;
-}
-
void LocalFrame::UpdateAdHighlight() {
if (IsMainFrame())
return;
@@ -2501,12 +2285,7 @@ const base::UnguessableToken& LocalFrame::GetAgentClusterId() const {
}
mojom::blink::ReportingServiceProxy* LocalFrame::GetReportingService() {
- if (!reporting_service_.is_bound()) {
- GetBrowserInterfaceBroker().GetInterface(
- reporting_service_.BindNewPipeAndPassReceiver(
- GetTaskRunner(blink::TaskType::kInternalDefault)));
- }
- return reporting_service_.get();
+ return mojo_handler_->ReportingService();
}
// static
@@ -2660,26 +2439,17 @@ void LocalFrame::SetContextPaused(bool is_paused) {
return;
paused_ = is_paused;
- GetDocument()->Fetcher()->SetDefersLoading(GetLoadDeferType());
- Loader().SetDefersLoading(GetLoadDeferType());
+ GetDocument()->Fetcher()->SetDefersLoading(GetLoaderFreezeMode());
+ Loader().SetDefersLoading(GetLoaderFreezeMode());
// TODO(altimin): Move this to PageScheduler level.
GetFrameScheduler()->SetPaused(is_paused);
}
-bool LocalFrame::IsLoadDeferred() {
- return frozen_ || paused_;
-}
-
bool LocalFrame::SwapIn() {
WebLocalFrameClient* client = Client()->GetWebFrame()->Client();
return client->SwapIn(WebFrame::FromCoreFrame(GetProvisionalOwnerFrame()));
}
-void LocalFrame::DidActivateForPrerendering() {
- DCHECK(RuntimeEnabledFeatures::Prerender2Enabled());
- GetLocalFrameHostRemote().DidActivateForPrerendering();
-}
-
void LocalFrame::LoadJavaScriptURL(const KURL& url) {
// Protect privileged pages against bookmarklets and other JavaScript
// manipulations.
@@ -2696,20 +2466,37 @@ void LocalFrame::LoadJavaScriptURL(const KURL& url) {
&DOMWrapperWorld::MainWorld());
}
-WebURLLoader::DeferType LocalFrame::GetLoadDeferType() {
+void LocalFrame::SetEvictCachedSessionStorageOnFreezeOrUnload() {
+ DCHECK(RuntimeEnabledFeatures::Prerender2Enabled(
+ GetDocument()->GetExecutionContext()));
+ evict_cached_session_storage_on_freeze_or_unload_ = true;
+}
+
+LocalFrameToken LocalFrame::GetLocalFrameToken() const {
+ return GetFrameToken().GetAs<LocalFrameToken>();
+}
+
+LoaderFreezeMode LocalFrame::GetLoaderFreezeMode() {
if (GetPage()->GetPageScheduler()->IsInBackForwardCache() &&
IsInflightNetworkRequestBackForwardCacheSupportEnabled()) {
- return WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ return LoaderFreezeMode::kBufferIncoming;
}
if (paused_ || frozen_)
- return WebURLLoader::DeferType::kDeferred;
- return WebURLLoader::DeferType::kNotDeferred;
+ return LoaderFreezeMode::kStrict;
+ return LoaderFreezeMode::kNone;
}
void LocalFrame::DidFreeze() {
TRACE_EVENT0("blink", "LocalFrame::DidFreeze");
DCHECK(IsAttached());
GetDocument()->DispatchFreezeEvent();
+ if (evict_cached_session_storage_on_freeze_or_unload_) {
+ // Evicts the cached data of Session Storage to avoid reusing old data in
+ // the cache after the session storage has been modified by another renderer
+ // process.
+ CoreInitializer::GetInstance().EvictSessionStorageCachedData(
+ GetDocument()->GetPage());
+ }
// DispatchFreezeEvent dispatches JS events, which may detach |this|.
if (!IsAttached())
return;
@@ -2725,9 +2512,9 @@ void LocalFrame::DidFreeze() {
DomWindow()->SetIsInBackForwardCache(true);
}
- WebURLLoader::DeferType defer = GetLoadDeferType();
- GetDocument()->Fetcher()->SetDefersLoading(defer);
- Loader().SetDefersLoading(defer);
+ LoaderFreezeMode freeze_mode = GetLoaderFreezeMode();
+ GetDocument()->Fetcher()->SetDefersLoading(freeze_mode);
+ Loader().SetDefersLoading(freeze_mode);
}
void LocalFrame::DidResume() {
@@ -2746,10 +2533,9 @@ void LocalFrame::DidResume() {
performance_manager::mojom::LifecycleState::kRunning);
}
- // TODO(yuzus): Figure out if we should call GetLoadDeferType().
- GetDocument()->Fetcher()->SetDefersLoading(
- WebURLLoader::DeferType::kNotDeferred);
- Loader().SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ // TODO(yuzus): Figure out if we should call GetLoaderFreezeMode().
+ GetDocument()->Fetcher()->SetDefersLoading(LoaderFreezeMode::kNone);
+ Loader().SetDefersLoading(LoaderFreezeMode::kNone);
DomWindow()->SetIsInBackForwardCache(false);
GetBackForwardCacheBufferLimitTracker().DidRemoveFrameFromBackForwardCache(
@@ -2844,16 +2630,8 @@ SystemClipboard* LocalFrame::GetSystemClipboard() {
return system_clipboard_.Get();
}
-RawSystemClipboard* LocalFrame::GetRawSystemClipboard() {
- if (!raw_system_clipboard_)
- raw_system_clipboard_ = MakeGarbageCollected<RawSystemClipboard>(this);
-
- return raw_system_clipboard_.Get();
-}
-
void LocalFrame::WasAttachedAsLocalMainFrame() {
- GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
- &LocalFrame::BindToMainFrameReceiver, WrapWeakPersistent(this)));
+ mojo_handler_->WasAttachedAsLocalMainFrame();
}
void LocalFrame::EvictFromBackForwardCache(
@@ -2873,11 +2651,6 @@ bool LocalFrame::CanContinueBufferingWhileInBackForwardCache() {
return GetBackForwardCacheBufferLimitTracker().IsUnderPerProcessBufferLimit();
}
-void LocalFrame::AnimateDoubleTapZoom(const gfx::Point& point,
- const gfx::Rect& rect) {
- GetPage()->GetChromeClient().AnimateDoubleTapZoom(point, rect);
-}
-
void LocalFrame::SetScaleFactor(float scale_factor) {
DCHECK(IsMainFrame());
@@ -2889,64 +2662,8 @@ void LocalFrame::SetScaleFactor(float scale_factor) {
GetPage()->GetVisualViewport().SetScale(scale_factor);
}
-void LocalFrame::ClosePage(
- mojom::blink::LocalMainFrame::ClosePageCallback completion_callback) {
- SECURITY_CHECK(IsMainFrame());
-
- // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done.
- VLOG(1) << "LocalFrame::ClosePage() URL = " << GetDocument()->Url();
-
- // There are two ways to close a page:
- //
- // 1/ Via webview()->Close() that currently sets the WebView's delegate_ to
- // NULL, and prevent any JavaScript dialogs in the onunload handler from
- // appearing.
- //
- // 2/ Calling the FrameLoader's CloseURL method directly.
- //
- // TODO(creis): Having a single way to close that can run onunload is also
- // useful for fixing http://b/issue?id=753080.
-
- SubframeLoadingDisabler disabler(GetDocument());
- // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document
- // The ignore-opens-during-unload counter of a Document must be incremented
- // when unloading itself.
- IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
- GetDocument());
- Loader().DispatchUnloadEvent(nullptr, nullptr);
-
- std::move(completion_callback).Run();
-}
-
-void LocalFrame::PluginActionAt(const gfx::Point& location,
- mojom::blink::PluginActionType action) {
- SECURITY_CHECK(IsMainFrame());
-
- // TODO(bokan): Location is probably in viewport coordinates
- HitTestResult result =
- HitTestResultForRootFramePos(this, PhysicalOffset(IntPoint(location)));
- Node* node = result.InnerNode();
- if (!IsA<HTMLObjectElement>(*node) && !IsA<HTMLEmbedElement>(*node))
- return;
-
- auto* embedded = DynamicTo<LayoutEmbeddedContent>(node->GetLayoutObject());
- if (!embedded)
- return;
-
- WebPluginContainerImpl* plugin_view = embedded->Plugin();
- if (!plugin_view)
- return;
-
- switch (action) {
- case mojom::blink::PluginActionType::kRotate90Clockwise:
- plugin_view->Plugin()->RotateView(WebPlugin::kRotationType90Clockwise);
- return;
- case mojom::blink::PluginActionType::kRotate90Counterclockwise:
- plugin_view->Plugin()->RotateView(
- WebPlugin::kRotationType90Counterclockwise);
- return;
- }
- NOTREACHED();
+void LocalFrame::ClosePageForTesting() {
+ mojo_handler_->ClosePageForTesting();
}
void LocalFrame::SetInitialFocus(bool reverse) {
@@ -2956,14 +2673,6 @@ void LocalFrame::SetInitialFocus(bool reverse) {
: mojom::blink::FocusType::kForward);
}
-void LocalFrame::EnablePreferredSizeChangedMode() {
- GetPage()->GetChromeClient().EnablePreferredSizeChangedMode();
-}
-
-void LocalFrame::ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) {
- GetPage()->GetChromeClient().ZoomToFindInPageRect(rect_in_root_frame);
-}
-
#if defined(OS_MAC)
void LocalFrame::GetCharacterIndexAtPoint(const gfx::Point& point) {
HitTestLocation location(View()->ViewportToFrame(IntPoint(point)));
@@ -2971,157 +2680,76 @@ void LocalFrame::GetCharacterIndexAtPoint(const gfx::Point& point) {
location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
uint32_t index =
Selection().CharacterIndexForPoint(result.RoundedPointInInnerNodeFrame());
- GetTextInputHost().GotCharacterIndexAtPoint(index);
-}
-
-void LocalFrame::GetFirstRectForRange(const gfx::Range& range) {
- gfx::Rect rect;
- WebLocalFrameClient* client = WebLocalFrameImpl::FromFrame(this)->Client();
- if (!client)
- return;
-
- if (!client->GetCaretBoundsFromFocusedPlugin(rect)) {
- // When request range is invalid we will try to obtain it from current
- // frame selection. The fallback value will be 0.
- uint32_t start =
- range.IsValid() ? range.start() : GetCurrentCursorPositionInFrame(this);
-
- WebLocalFrameImpl::FromFrame(this)->FirstRectForCharacterRange(
- start, range.length(), rect);
- }
-
- GetTextInputHost().GotFirstRectForRange(rect);
-}
-
-void LocalFrame::GetStringForRange(const gfx::Range& range,
- GetStringForRangeCallback callback) {
- gfx::Point baseline_point;
- ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
- NSAttributedString* string = SubstringUtil::AttributedSubstringInRange(
- this, range.start(), range.length(), &baseline_point);
- if (string)
- attributed_string = ui::mojom::blink::AttributedString::From(string);
-
- std::move(callback).Run(std::move(attributed_string), baseline_point);
+ mojo_handler_->TextInputHost().GotCharacterIndexAtPoint(index);
}
#endif
-void LocalFrame::InstallCoopAccessMonitor(
- network::mojom::blink::CoopAccessReportType report_type,
- const FrameToken& accessed_window,
- mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter>
- reporter,
- bool endpoint_defined,
- const WTF::String& reported_window_url) {
- blink::Frame* accessed_frame = Frame::ResolveFrame(accessed_window);
- // The Frame might have been deleted during the cross-process communication.
- if (!accessed_frame)
+void LocalFrame::UpdateWindowControlsOverlay(
+ const gfx::Rect& bounding_rect_in_dips) {
+ if (!RuntimeEnabledFeatures::WebAppWindowControlsOverlayEnabled(
+ GetDocument()->GetExecutionContext())) {
return;
+ }
- accessed_frame->DomWindow()->InstallCoopAccessMonitor(
- report_type, this, std::move(reporter), endpoint_defined,
- std::move(reported_window_url));
-}
-
-void LocalFrame::OnPortalActivated(
- const PortalToken& portal_token,
- mojo::PendingAssociatedRemote<mojom::blink::Portal> portal,
- mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client,
- BlinkTransferableMessage data,
- uint64_t trace_id,
- OnPortalActivatedCallback callback) {
- DCHECK(GetDocument());
- PaintTiming::From(*GetDocument()).OnPortalActivate();
-
- TRACE_EVENT_WITH_FLOW0("navigation", "LocalFrame::OnPortalActivated",
- TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN);
-
- DOMWindowPortalHost::portalHost(*DomWindow())->OnPortalActivated();
- GetPage()->SetInsidePortal(false);
-
- DCHECK(!data.locked_agent_cluster_id)
- << "portal activation is always cross-agent-cluster and should be "
- "diagnosed early";
- MessagePortArray* ports =
- MessagePort::EntanglePorts(*DomWindow(), std::move(data.ports));
-
- PortalActivateEvent* event = PortalActivateEvent::Create(
- this, portal_token, std::move(portal), std::move(portal_client),
- std::move(data.message), ports, std::move(callback));
-
- ThreadDebugger* debugger = MainThreadDebugger::Instance();
- if (debugger)
- debugger->ExternalAsyncTaskStarted(data.sender_stack_trace_id);
- DomWindow()->DispatchEvent(*event);
- if (debugger)
- debugger->ExternalAsyncTaskFinished(data.sender_stack_trace_id);
- event->ExpireAdoptionLifetime();
-}
-
-void LocalFrame::ForwardMessageFromHost(
- BlinkTransferableMessage message,
- const scoped_refptr<const SecurityOrigin>& source_origin) {
- PortalHost::From(*DomWindow())
- .ReceiveMessage(std::move(message), source_origin);
-}
-
-void LocalFrame::UpdateBrowserControlsState(
- cc::BrowserControlsState constraints,
- cc::BrowserControlsState current,
- bool animate) {
- DCHECK(IsMainFrame());
- TRACE_EVENT2("renderer", "LocalFrame::UpdateBrowserControlsState",
- "Constraint", static_cast<int>(constraints), "Current",
- static_cast<int>(current));
- TRACE_EVENT_INSTANT1("renderer", "is_animated", TRACE_EVENT_SCOPE_THREAD,
- "animated", animate);
-
- GetWidgetForLocalRoot()->UpdateBrowserControlsState(constraints, current,
- animate);
-}
+ // The rect passed to us from content is in DIP screen space, relative to the
+ // main frame, and needs to move to CSS space. This doesn't take the page's
+ // zoom factor into account so we must scale by the inverse of the page zoom
+ // in order to get correct CSS space coordinates. Note that when
+ // use-zoom-for-dsf is enabled, WindowToViewportScalar will be the true device
+ // scale factor, and PageZoomFactor will be the combination of the device
+ // scale factor and the zoom percent of the page. It is preferable to compute
+ // a rect that is slightly larger than one that would render smaller than the
+ // window control overlay.
+ LocalFrame& local_frame_root = LocalFrameRoot();
+ const float window_to_viewport_factor =
+ GetPage()->GetChromeClient().WindowToViewportScalar(&local_frame_root,
+ 1.0f);
+ const float zoom_factor = local_frame_root.PageZoomFactor();
+ const float scale_factor = zoom_factor / window_to_viewport_factor;
+ gfx::Rect window_controls_overlay_rect =
+ gfx::ScaleToEnclosingRectSafe(bounding_rect_in_dips, 1.0f / scale_factor);
-void LocalFrame::UpdateWindowControlsOverlay(
- const gfx::Rect& window_controls_overlay_rect) {
+ bool fire_event =
+ (window_controls_overlay_rect != window_controls_overlay_rect_);
is_window_controls_overlay_visible_ = !window_controls_overlay_rect.IsEmpty();
window_controls_overlay_rect_ = window_controls_overlay_rect;
DocumentStyleEnvironmentVariables& vars =
GetDocument()->GetStyleEngine().EnsureEnvironmentVariables();
- vars.SetVariable(
- UADefinedVariable::kTitlebarAreaX,
- StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.x()));
- vars.SetVariable(
- UADefinedVariable::kTitlebarAreaY,
- StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.y()));
- vars.SetVariable(UADefinedVariable::kTitlebarAreaWidth,
- StyleEnvironmentVariables::FormatPx(
- window_controls_overlay_rect_.width()));
- vars.SetVariable(UADefinedVariable::kTitlebarAreaHeight,
- StyleEnvironmentVariables::FormatPx(
- window_controls_overlay_rect_.height()));
-
- auto* window_controls_overlay =
- WindowControlsOverlay::FromIfExists(*DomWindow()->navigator());
-
- if (window_controls_overlay) {
- window_controls_overlay->WindowControlsOverlayChanged(
- window_controls_overlay_rect);
- }
-}
-
-void LocalFrame::RequestFullscreenVideoElement() {
- // Find the first video element of the frame.
- for (auto* child = GetDocument()->documentElement(); child;
- child = Traversal<HTMLElement>::Next(*child)) {
- if (IsA<HTMLVideoElement>(child)) {
- // This is always initiated from browser side (which should require the
- // user interacting with ui) which suffices for a user gesture even though
- // there will have been no input to the frame at this point.
- NotifyUserActivation(
- mojom::blink::UserActivationNotificationType::kInteraction);
-
- Fullscreen::RequestFullscreen(*child);
- return;
+
+ if (is_window_controls_overlay_visible_) {
+ vars.SetVariable(
+ UADefinedVariable::kTitlebarAreaX,
+ StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.x()));
+ vars.SetVariable(
+ UADefinedVariable::kTitlebarAreaY,
+ StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.y()));
+ vars.SetVariable(UADefinedVariable::kTitlebarAreaWidth,
+ StyleEnvironmentVariables::FormatPx(
+ window_controls_overlay_rect_.width()));
+ vars.SetVariable(UADefinedVariable::kTitlebarAreaHeight,
+ StyleEnvironmentVariables::FormatPx(
+ window_controls_overlay_rect_.height()));
+ } else {
+ const UADefinedVariable vars_to_remove[] = {
+ UADefinedVariable::kTitlebarAreaX,
+ UADefinedVariable::kTitlebarAreaY,
+ UADefinedVariable::kTitlebarAreaWidth,
+ UADefinedVariable::kTitlebarAreaHeight,
+ };
+ for (auto var_to_remove : vars_to_remove) {
+ vars.RemoveVariable(StyleEnvironmentVariables::GetVariableName(
+ var_to_remove, vars.GetFeatureContext()));
+ }
+ }
+
+ if (fire_event) {
+ auto* window_controls_overlay =
+ WindowControlsOverlay::FromIfExists(*DomWindow()->navigator());
+
+ if (window_controls_overlay) {
+ window_controls_overlay->WindowControlsOverlayChanged(
+ window_controls_overlay_rect_);
}
}
}
@@ -3169,47 +2797,12 @@ void LocalFrame::SetPrescientNetworkingForTesting(
}
mojom::blink::LocalFrameHost& LocalFrame::GetLocalFrameHostRemote() const {
- return *local_frame_host_remote_.get();
+ return mojo_handler_->LocalFrameHostRemote();
}
mojom::blink::BackForwardCacheControllerHost&
LocalFrame::GetBackForwardCacheControllerHostRemote() {
- return *back_forward_cache_controller_host_remote_.get();
-}
-
-void LocalFrame::GetTextSurroundingSelection(
- uint32_t max_length,
- GetTextSurroundingSelectionCallback callback) {
- blink::SurroundingText surrounding_text(this, max_length);
-
- // |surrounding_text| might not be correctly initialized, for example if
- // |frame_->SelectionRange().IsNull()|, in other words, if there was no
- // selection.
- if (surrounding_text.IsEmpty()) {
- // Don't use WTF::String's default constructor so that we make sure that we
- // always send a valid empty string over the wire instead of a null pointer.
- std::move(callback).Run(g_empty_string, 0, 0);
- return;
- }
-
- std::move(callback).Run(surrounding_text.TextContent(),
- surrounding_text.StartOffsetInTextContent(),
- surrounding_text.EndOffsetInTextContent());
-}
-
-void LocalFrame::SendInterventionReport(const String& id,
- const String& message) {
- Intervention::GenerateReport(this, id, message);
-}
-
-void LocalFrame::SetFrameOwnerProperties(
- mojom::blink::FrameOwnerPropertiesPtr properties) {
- GetDocument()->WillChangeFrameOwnerProperties(
- properties->margin_width, properties->margin_height,
- properties->scrollbar_mode, properties->is_display_none,
- properties->color_scheme);
-
- Frame::ApplyFrameOwnerProperties(std::move(properties));
+ return mojo_handler_->BackForwardCacheControllerHostRemote();
}
void LocalFrame::NotifyUserActivation(
@@ -3230,40 +2823,6 @@ void LocalFrame::NotifyVirtualKeyboardOverlayRectObservers(
observer->VirtualKeyboardOverlayChanged(rect);
}
-void LocalFrame::NotifyVirtualKeyboardOverlayRect(
- const gfx::Rect& keyboard_rect) {
- Page* page = GetPage();
- if (!page)
- return;
-
- // The rect passed to us from content is in DIP, relative to the main frame.
- // This doesn't take the page's zoom factor into account so we must scale by
- // the inverse of the page zoom in order to get correct client coordinates.
- // Note that when use-zoom-for-dsf is enabled, WindowToViewportScalar will
- // be the true device scale factor, and PageZoomFactor will be the combination
- // of the device scale factor and the zoom percent of the page.
- LocalFrame& local_frame_root = LocalFrameRoot();
- const float window_to_viewport_factor =
- page->GetChromeClient().WindowToViewportScalar(&local_frame_root, 1.0f);
- const float zoom_factor = local_frame_root.PageZoomFactor();
- const float scale_factor = zoom_factor / window_to_viewport_factor;
- gfx::Rect scaled_rect(keyboard_rect.x() / scale_factor,
- keyboard_rect.y() / scale_factor,
- keyboard_rect.width() / scale_factor,
- keyboard_rect.height() / scale_factor);
-
- NotifyVirtualKeyboardOverlayRectObservers(scaled_rect);
-}
-
-void LocalFrame::AddMessageToConsole(mojom::blink::ConsoleMessageLevel level,
- const WTF::String& message,
- bool discard_duplicates) {
- GetDocument()->AddConsoleMessage(
- MakeGarbageCollected<ConsoleMessage>(mojom::ConsoleMessageSource::kOther,
- level, message),
- discard_duplicates);
-}
-
void LocalFrame::AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr info) {
if (GetPage()) {
GetPage()->GetInspectorIssueStorage().AddInspectorIssue(DomWindow(),
@@ -3271,81 +2830,6 @@ void LocalFrame::AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr info) {
}
}
-void LocalFrame::SwapInImmediately() {
- SwapIn();
- // Normally, this happens as part of committing a cross-Document navigation.
- // However, there is no navigation being committed here. Instead, the browser
- // navigation code is optimistically early-swapping in this frame to replace a
- // crashed subframe after starting a navigation.
- //
- // While the provisional frame has a unique opaque origin, the Blink bindings
- // code still expects the WindowProxy to be initialized for the access check
- // failed callbacks.
- DomWindow()->GetScriptController().UpdateDocument();
-}
-
-void LocalFrame::StopLoading() {
- Loader().StopAllLoaders(/*abort_client=*/true);
-
- // The stopLoading handler may run script, which may cause this frame to be
- // detached/deleted. If that happens, return immediately.
- if (!IsAttached())
- return;
-
- // Notify RenderFrame observers.
- WebLocalFrameClient* client = Client()->GetWebFrame()->Client();
- if (client)
- client->OnStopLoading();
-}
-
-void LocalFrame::Collapse(bool collapsed) {
- FrameOwner* owner = Owner();
- To<HTMLFrameOwnerElement>(owner)->SetCollapsed(collapsed);
-}
-
-void LocalFrame::EnableViewSourceMode() {
- DCHECK(!Tree().Parent());
- SetInViewSourceMode(true);
-}
-
-void LocalFrame::Focus() {
- FocusImpl();
-}
-
-void LocalFrame::ClearFocusedElement() {
- Document* document = GetDocument();
- Element* old_focused_element = document->FocusedElement();
- document->ClearFocusedElement();
- if (!old_focused_element)
- return;
-
- // If a text field has focus, we need to make sure the selection controller
- // knows to remove selection from it. Otherwise, the text field is still
- // processing keyboard events even though focus has been moved to the page and
- // keystrokes get eaten as a result.
- document->UpdateStyleAndLayoutTree();
- if (HasEditableStyle(*old_focused_element) ||
- old_focused_element->IsTextControl())
- Selection().Clear();
-}
-
-void LocalFrame::GetResourceSnapshotForWebBundle(
- mojo::PendingReceiver<
- data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver) {
- Deque<SerializedResource> resources;
-
- HeapHashSet<WeakMember<const Element>> shadow_template_elements;
- WebBundleGenerationDelegate web_delegate;
- FrameSerializerDelegateImpl core_delegate(web_delegate,
- shadow_template_elements);
- FrameSerializer serializer(resources, core_delegate);
- serializer.SerializeFrame(*this);
-
- mojo::MakeSelfOwnedReceiver(
- std::make_unique<ResourceSnapshotForWebBundleImpl>(std::move(resources)),
- std::move(receiver));
-}
-
void LocalFrame::CopyImageAtViewportPoint(const IntPoint& viewport_point) {
HitTestResult result = HitTestResultForVisualViewportPos(viewport_point);
if (!IsA<HTMLCanvasElement>(result.InnerNodeOrImageMapImage()) &&
@@ -3367,12 +2851,6 @@ void LocalFrame::CopyImageAtViewportPoint(const IntPoint& viewport_point) {
GetEditor().CopyImage(result);
}
-void LocalFrame::CopyImageAt(const gfx::Point& window_point) {
- gfx::Point viewport_position =
- GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
- CopyImageAtViewportPoint(IntPoint(viewport_position));
-}
-
void LocalFrame::SaveImageAt(const gfx::Point& window_point) {
gfx::Point viewport_position =
GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
@@ -3392,48 +2870,6 @@ void LocalFrame::SaveImageAt(const gfx::Point& window_point) {
GetLocalFrameHostRemote().DownloadURL(std::move(params));
}
-void LocalFrame::ReportBlinkFeatureUsage(
- const Vector<mojom::blink::WebFeature>& features) {
- DCHECK(!features.IsEmpty());
-
- // Assimilate all features used/performed by the browser into UseCounter.
- auto* document = GetDocument();
- DCHECK(document);
- for (const auto& feature : features)
- document->CountUse(feature);
-}
-
-void LocalFrame::RenderFallbackContent() {
- Frame::RenderFallbackContent();
-}
-
-void LocalFrame::RenderFallbackContentWithResourceTiming(
- mojom::blink::ResourceTimingInfoPtr timing,
- const String& server_timing_value) {
- Frame::RenderFallbackContentWithResourceTiming(std::move(timing),
- server_timing_value);
-}
-
-void LocalFrame::BeforeUnload(bool is_reload, BeforeUnloadCallback callback) {
- base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
-
- // This will execute the BeforeUnload event in this frame and all of its
- // local descendant frames, including children of remote frames. The browser
- // process will send separate IPCs to dispatch beforeunload in any
- // out-of-process child frames.
- bool proceed = Loader().ShouldClose(is_reload);
-
- DCHECK(!callback.is_null());
- base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
- std::move(callback).Run(proceed, before_unload_start_time,
- before_unload_end_time);
-}
-
-void LocalFrame::DispatchBeforeUnload(bool is_reload,
- BeforeUnloadCallback callback) {
- BeforeUnload(is_reload, std::move(callback));
-}
-
void LocalFrame::MediaPlayerActionAtViewportPoint(
const IntPoint& viewport_position,
const blink::mojom::blink::MediaPlayerActionType type,
@@ -3514,33 +2950,11 @@ void LocalFrame::DownloadURL(
params->suggested_name = *request.GetSuggestedFilename();
params->cross_origin_redirects = cross_origin_redirect_behavior;
params->blob_url_token = std::move(blob_url_token);
+ params->has_user_gesture = request.HasUserGesture();
GetLocalFrameHostRemote().DownloadURL(std::move(params));
}
-void LocalFrame::MediaPlayerActionAt(
- const gfx::Point& window_point,
- blink::mojom::blink::MediaPlayerActionPtr action) {
- gfx::Point viewport_position =
- GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
- IntPoint location(viewport_position);
-
- MediaPlayerActionAtViewportPoint(location, action->type, action->enable);
-}
-
-void LocalFrame::AdvanceFocusInFrame(
- mojom::blink::FocusType focus_type,
- const absl::optional<RemoteFrameToken>& source_frame_token) {
- RemoteFrame* source_frame = SourceFrameForOptionalToken(source_frame_token);
- if (!source_frame) {
- SetInitialFocus(focus_type == mojom::blink::FocusType::kBackward);
- return;
- }
-
- GetPage()->GetFocusController().AdvanceFocusAcrossFrames(focus_type,
- source_frame, this);
-}
-
void LocalFrame::AdvanceFocusInForm(mojom::blink::FocusType focus_type) {
auto* focused_frame = GetPage()->GetFocusController().FocusedFrame();
if (focused_frame != this)
@@ -3561,51 +2975,6 @@ void LocalFrame::AdvanceFocusInForm(mojom::blink::FocusType focus_type) {
next_element->focus();
}
-void LocalFrame::ReportContentSecurityPolicyViolation(
- network::mojom::blink::CSPViolationPtr violation) {
- auto source_location = std::make_unique<SourceLocation>(
- violation->source_location->url, violation->source_location->line,
- violation->source_location->column, nullptr);
-
- console_->AddMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kSecurity,
- mojom::ConsoleMessageLevel::kError, violation->console_message,
- source_location->Clone()));
-
- auto directive_type =
- ContentSecurityPolicy::GetDirectiveType(violation->effective_directive);
- LocalFrame* context_frame =
- directive_type == network::mojom::blink::CSPDirectiveName::FrameAncestors
- ? this
- : nullptr;
-
- DomWindow()->GetContentSecurityPolicy()->ReportViolation(
- violation->directive, directive_type, violation->console_message,
- violation->blocked_url, violation->report_endpoints,
- violation->use_reporting_api, violation->header, violation->type,
- ContentSecurityPolicy::ContentSecurityPolicyViolationType::kURLViolation,
- std::move(source_location), context_frame,
- violation->after_redirect ? RedirectStatus::kFollowedRedirect
- : RedirectStatus::kNoRedirect,
- nullptr /* Element */);
-}
-
-void LocalFrame::DidUpdateFramePolicy(const FramePolicy& frame_policy) {
- // At the moment, this is only used to replicate sandbox flags and container
- // policy for frames with a remote owner.
- SECURITY_CHECK(IsA<RemoteFrameOwner>(Owner()));
- To<RemoteFrameOwner>(Owner())->SetFramePolicy(frame_policy);
-}
-
-void LocalFrame::OnScreensChange() {
- if (RuntimeEnabledFeatures::WindowPlacementEnabled(DomWindow())) {
- // Allow fullscreen requests shortly after user-generated screens changes.
- transient_allow_fullscreen_.Activate();
- DomWindow()->DispatchEvent(
- *Event::Create(event_type_names::kScreenschange));
- }
-}
-
void LocalFrame::PostMessageEvent(
const absl::optional<RemoteFrameToken>& source_frame_token,
const String& source_origin,
@@ -3661,254 +3030,6 @@ void LocalFrame::PostMessageEvent(
: base::UnguessableToken());
}
-void LocalFrame::JavaScriptMethodExecuteRequest(
- const String& object_name,
- const String& method_name,
- base::Value arguments,
- bool wants_result,
- JavaScriptMethodExecuteRequestCallback callback) {
- TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptMethodExecuteRequest",
- TRACE_EVENT_SCOPE_THREAD);
-
- std::unique_ptr<WebV8ValueConverter> converter =
- Platform::Current()->CreateWebV8ValueConverter();
- converter->SetDateAllowed(true);
- converter->SetRegExpAllowed(true);
-
- v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
- v8::Local<v8::Value> result;
- if (!CallMethodOnFrame(this, object_name, method_name, std::move(arguments),
- converter.get())
- .ToLocal(&result)) {
- std::move(callback).Run({});
- return;
- }
-
- if (wants_result) {
- std::move(callback).Run(
- GetJavaScriptExecutionResult(result, this, converter.get()));
- } else {
- std::move(callback).Run({});
- }
-}
-
-void LocalFrame::JavaScriptExecuteRequest(
- const String& javascript,
- bool wants_result,
- JavaScriptExecuteRequestCallback callback) {
- TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequest",
- TRACE_EVENT_SCOPE_THREAD);
-
- v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
- v8::Local<v8::Value> result =
- ClassicScript::CreateUnspecifiedScript(javascript)
- ->RunScriptAndReturnValue(DomWindow());
-
- if (wants_result) {
- std::unique_ptr<WebV8ValueConverter> converter =
- Platform::Current()->CreateWebV8ValueConverter();
- converter->SetDateAllowed(true);
- converter->SetRegExpAllowed(true);
-
- std::move(callback).Run(
- GetJavaScriptExecutionResult(result, this, converter.get()));
- } else {
- std::move(callback).Run({});
- }
-}
-
-void LocalFrame::JavaScriptExecuteRequestForTests(
- const String& javascript,
- bool wants_result,
- bool has_user_gesture,
- int32_t world_id,
- JavaScriptExecuteRequestForTestsCallback callback) {
- TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests",
- TRACE_EVENT_SCOPE_THREAD);
-
- // A bunch of tests expect to run code in the context of a user gesture, which
- // can grant additional privileges (e.g. the ability to create popups).
- if (has_user_gesture)
- NotifyUserActivation(mojom::blink::UserActivationNotificationType::kTest);
-
- v8::HandleScope handle_scope(V8PerIsolateData::MainThreadIsolate());
- v8::Local<v8::Value> result;
- if (world_id == DOMWrapperWorld::kMainWorldId) {
- result = ClassicScript::CreateUnspecifiedScript(javascript)
- ->RunScriptAndReturnValue(DomWindow());
- } else {
- CHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
- CHECK_LT(world_id, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit);
- // Note: An error event in an isolated world will never be dispatched to
- // a foreign world.
- result =
- ClassicScript::CreateUnspecifiedScript(
- javascript, SanitizeScriptErrors::kDoNotSanitize)
- ->RunScriptInIsolatedWorldAndReturnValue(DomWindow(), world_id);
- }
-
- if (wants_result) {
- std::unique_ptr<WebV8ValueConverter> converter =
- Platform::Current()->CreateWebV8ValueConverter();
- converter->SetDateAllowed(true);
- converter->SetRegExpAllowed(true);
-
- std::move(callback).Run(
- GetJavaScriptExecutionResult(result, this, converter.get()));
- } else {
- std::move(callback).Run({});
- }
-}
-
-void LocalFrame::JavaScriptExecuteRequestInIsolatedWorld(
- const String& javascript,
- bool wants_result,
- int32_t world_id,
- JavaScriptExecuteRequestInIsolatedWorldCallback callback) {
- TRACE_EVENT_INSTANT0("test_tracing",
- "JavaScriptExecuteRequestInIsolatedWorld",
- TRACE_EVENT_SCOPE_THREAD);
-
- if (world_id <= DOMWrapperWorld::kMainWorldId ||
- world_id > DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit) {
- // Returns if the world_id is not valid. world_id is passed as a plain int
- // over IPC and needs to be verified here, in the IPC endpoint.
- std::move(callback).Run(base::Value());
- mojo::ReportBadMessage(kInvalidWorldID);
- return;
- }
-
- v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
- scoped_refptr<DOMWrapperWorld> isolated_world =
- DOMWrapperWorld::EnsureIsolatedWorld(ToIsolate(this), world_id);
- ScriptSourceCode source_code = ScriptSourceCode(javascript);
- HeapVector<ScriptSourceCode> sources;
- sources.Append(&source_code, 1);
- auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
- DomWindow(), std::move(isolated_world), sources, false /* user_gesture */,
- MakeGarbageCollected<JavaScriptIsolatedWorldRequest>(
- this, wants_result, std::move(callback)));
- executor->Run();
-}
-
-void LocalFrame::BindReportingObserver(
- mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) {
- ReportingContext::From(DomWindow())->Bind(std::move(receiver));
-}
-
-void LocalFrame::UpdateOpener(
- const absl::optional<blink::FrameToken>& opener_frame_token) {
- if (auto* web_frame = WebFrame::FromCoreFrame(this)) {
- Frame* opener_frame = nullptr;
- if (opener_frame_token)
- opener_frame = Frame::ResolveFrame(opener_frame_token.value());
- SetOpenerDoNotNotify(opener_frame);
- }
-}
-
-void LocalFrame::GetSavableResourceLinks(
- GetSavableResourceLinksCallback callback) {
- Vector<KURL> resources_list;
- Vector<mojom::blink::SavableSubframePtr> subframes;
- SavableResources::Result result(&resources_list, &subframes);
-
- if (!SavableResources::GetSavableResourceLinksForFrame(this, &result)) {
- std::move(callback).Run(nullptr);
- return;
- }
-
- auto referrer = mojom::blink::Referrer::New(GetDocument()->Url(),
- DomWindow()->GetReferrerPolicy());
-
- auto reply = mojom::blink::GetSavableResourceLinksReply::New();
- reply->resources_list = std::move(resources_list);
- reply->referrer = std::move(referrer);
- reply->subframes = std::move(subframes);
-
- std::move(callback).Run(std::move(reply));
-}
-
-void LocalFrame::MixedContentFound(
- const KURL& main_resource_url,
- const KURL& mixed_content_url,
- mojom::blink::RequestContextType request_context,
- bool was_allowed,
- const KURL& url_before_redirects,
- bool had_redirect,
- network::mojom::blink::SourceLocationPtr source_location) {
- std::unique_ptr<SourceLocation> source;
- if (source_location) {
- source = std::make_unique<SourceLocation>(source_location->url,
- source_location->line,
- source_location->column, nullptr);
- }
- MixedContentChecker::MixedContentFound(
- this, main_resource_url, mixed_content_url, request_context, was_allowed,
- url_before_redirects, had_redirect, std::move(source));
-}
-
-void LocalFrame::ActivateForPrerendering() {
- DCHECK(features::IsPrerender2Enabled());
-
- // https://jeremyroman.github.io/alternate-loading-modes/#prerendering-browsing-context-activate
- // Step 8.2. "Let inclusiveDescendants be successorBC extended with
- // successorBC's active document's list of the descendant browsing contexts."
- // Step 8.3. "For each bc of inclusiveDescendants, queue a global task on the
- // networking task source, given bc's active window, to perform the following
- // steps:"
- GetTaskRunner(TaskType::kNetworking)
- ->PostTask(FROM_HERE, WTF::Bind(&Document::ActivateForPrerendering,
- WrapPersistent(GetDocument())));
-}
-
-void LocalFrame::BindDevToolsAgent(
- mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host,
- mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver) {
- DCHECK(Client());
- Client()->BindDevToolsAgent(std::move(host), std::move(receiver));
-}
-
-#if defined(OS_ANDROID)
-void LocalFrame::ExtractSmartClipData(const gfx::Rect& rect,
- ExtractSmartClipDataCallback callback) {
- String clip_text;
- String clip_html;
- gfx::Rect clip_rect;
- ExtractSmartClipDataInternal(rect, clip_text, clip_html, clip_rect);
- std::move(callback).Run(clip_text.IsNull() ? g_empty_string : clip_text,
- clip_html.IsNull() ? g_empty_string : clip_html,
- clip_rect);
-}
-#endif // defined(OS_ANDROID)
-
-void LocalFrame::HandleRendererDebugURL(const KURL& url) {
- DCHECK(IsRendererDebugURL(url));
- if (url.ProtocolIs("javascript")) {
- // JavaScript URLs should be sent to Blink for handling.
- LoadJavaScriptURL(url);
- } else {
- // This is a Chrome Debug URL. Handle it.
- HandleChromeDebugURL(url);
- }
-
- // The browser sets its status as loading before calling this IPC. Inform it
- // that the load stopped if needed, while leaving the debug URL visible in the
- // address bar.
- if (!IsLoading())
- Client()->DidStopLoading();
-}
-
-void LocalFrame::GetCanonicalUrlForSharing(
- GetCanonicalUrlForSharingCallback callback) {
- KURL canonical_url;
- HTMLLinkElement* link_element = GetDocument()->LinkCanonical();
- if (link_element)
- canonical_url = link_element->Href();
- std::move(callback).Run(canonical_url.IsNull()
- ? absl::nullopt
- : absl::make_optional(canonical_url));
-}
-
bool LocalFrame::ShouldThrottleDownload() {
const auto now = base::TimeTicks::Now();
if (num_burst_download_requests_ == 0) {
@@ -3929,9 +3050,12 @@ bool LocalFrame::ShouldThrottleDownload() {
}
#if defined(OS_MAC)
-mojom::blink::TextInputHost& LocalFrame::GetTextInputHost() {
- DCHECK(text_input_host_.is_bound());
- return *text_input_host_.get();
+void LocalFrame::ResetTextInputHostForTesting() {
+ mojo_handler_->ResetTextInputHostForTesting();
+}
+
+void LocalFrame::RebindTextInputHostForTesting() {
+ mojo_handler_->RebindTextInputHostForTesting();
}
#endif
@@ -3992,55 +3116,8 @@ void LocalFrame::ExtractSmartClipDataInternal(const gfx::Rect& rect_in_viewport,
View()->ViewportToFrame(end_point));
}
-void LocalFrame::BindToReceiver(
- blink::LocalFrame* frame,
- mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver) {
- DCHECK(frame);
- if (frame->IsDetached())
- return;
-
- frame->receiver_.Bind(
- std::move(receiver),
- frame->GetTaskRunner(blink::TaskType::kInternalDefault));
- frame->receiver_.SetFilter(std::make_unique<ActiveURLMessageFilter>(frame));
-}
-
-void LocalFrame::BindToMainFrameReceiver(
- blink::LocalFrame* frame,
- mojo::PendingAssociatedReceiver<mojom::blink::LocalMainFrame> receiver) {
- DCHECK(frame);
- if (frame->IsDetached())
- return;
-
- frame->main_frame_receiver_.Bind(
- std::move(receiver),
- frame->GetTaskRunner(blink::TaskType::kInternalDefault));
- frame->main_frame_receiver_.SetFilter(
- std::make_unique<ActiveURLMessageFilter>(frame));
-}
-
-void LocalFrame::BindToHighPriorityReceiver(
- mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver) {
- if (IsDetached())
- return;
-
- high_priority_frame_receiver_.Bind(
- std::move(receiver),
- GetTaskRunner(blink::TaskType::kInternalHighPriorityLocalFrame));
- high_priority_frame_receiver_.SetFilter(
- std::make_unique<ActiveURLMessageFilter>(this));
-}
-
-void LocalFrame::BindFullscreenVideoElementReceiver(
- mojo::PendingAssociatedReceiver<mojom::blink::FullscreenVideoElementHandler>
- receiver) {
- if (IsDetached())
- return;
-
- fullscreen_video_receiver_.Bind(
- std::move(receiver), GetTaskRunner(blink::TaskType::kInternalDefault));
- fullscreen_video_receiver_.SetFilter(
- std::make_unique<ActiveURLMessageFilter>(this));
+void LocalFrame::CreateTextFragmentHandler() {
+ text_fragment_handler_ = MakeGarbageCollected<TextFragmentHandler>(this);
}
void LocalFrame::BindTextFragmentReceiver(
@@ -4066,11 +3143,4 @@ TextSuggestionController& LocalFrame::GetTextSuggestionController() const {
return DomWindow()->GetTextSuggestionController();
}
-TextFragmentSelectorGenerator* LocalFrame::GetTextFragmentSelectorGenerator()
- const {
- if (!text_fragment_handler_)
- return nullptr;
- return text_fragment_handler_->GetTextFragmentSelectorGenerator();
-}
-
} // 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 777647d822d..ee6dc15d3d8 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.h
@@ -31,29 +31,31 @@
#include <memory>
-#include "base/macros.h"
#include "base/time/default_tick_clock.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "services/device/public/mojom/device_posture_provider.mojom-blink-forward.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "third_party/blink/public/common/frame/frame_ad_evidence.h"
#include "third_party/blink/public/common/frame/payment_request_token.h"
#include "third_party/blink/public/common/frame/transient_allow_fullscreen.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink.h"
-#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/media_player_action.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/reporting_observer.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/sudden_termination_disabler_type.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/media/fullscreen_video_element.mojom-blink.h"
-#include "third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom-blink.h"
-#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
+#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink-forward.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/web/web_script_execution_callback.h"
@@ -67,18 +69,14 @@
#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/loader/fetch/client_hints_preferences.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#if defined(OS_MAC)
-#include "third_party/blink/public/mojom/input/text_input_host.mojom-blink.h"
-#endif
#include "ui/gfx/transform.h"
namespace base {
@@ -88,7 +86,7 @@ class SingleThreadTaskRunner;
namespace gfx {
class Point;
class Range;
-}
+} // namespace gfx
namespace blink {
@@ -119,18 +117,18 @@ class LayoutView;
class LocalDOMWindow;
class LocalWindowProxy;
class LocalFrameClient;
+class LocalFrameMojoHandler;
class BackgroundColorPaintImageGenerator;
+class ClipPathPaintImageGenerator;
class Node;
class NodeTraversal;
class PerformanceMonitor;
class PolicyContainer;
class PluginData;
-class RawSystemClipboard;
class SystemClipboard;
class SmoothScrollSequencer;
class SpellChecker;
class TextFragmentHandler;
-class TextFragmentSelectorGenerator;
class TextSuggestionController;
class VirtualKeyboardOverlayChangedObserver;
class WebContentSettingsClient;
@@ -138,18 +136,23 @@ class WebInputEventAttribution;
class WebPluginContainerImpl;
class WebPrescientNetworking;
class WebURLLoaderFactory;
+struct BlinkTransferableMessage;
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<LocalFrame>;
// A LocalFrame is a frame hosted inside this process.
-class CORE_EXPORT LocalFrame final
- : public Frame,
- public FrameScheduler::Delegate,
- public Supplementable<LocalFrame>,
- public mojom::blink::LocalFrame,
- public mojom::blink::LocalMainFrame,
- public mojom::blink::FullscreenVideoElementHandler,
- public mojom::blink::HighPriorityLocalFrame {
+//
+// LocalFrame should not inherit from Mojo interfaces, and should not have
+// data members for Mojo remotes in order to avoid including full mojom headers
+// from local_frame.h. LocalFrameMojoHandler should do them instead.
+//
+// Blink code should not directly use LocalFrameMojoHandler. If Blink code
+// needs to call a function that is exposed as a Mojo method, the function
+// implementation should be in LocalFrame, and LocalFrameMojoHandler should
+// delegate to LocalFrame's implementation.
+class CORE_EXPORT LocalFrame final : public Frame,
+ public FrameScheduler::Delegate,
+ public Supplementable<LocalFrame> {
public:
// Returns the LocalFrame instance for the given |frame_token|.
static LocalFrame* FromFrameToken(const LocalFrameToken& frame_token);
@@ -194,7 +197,6 @@ class CORE_EXPORT LocalFrame final
void DidChangeVisibilityState() override;
void HookBackForwardCacheEviction() override;
void RemoveBackForwardCacheEviction() override;
-
void SetTextDirection(base::i18n::TextDirection direction) override;
// This sets the is_inert_ flag and also recurses through this frame's
// subtree, updating the inert bit on all descendant frames.
@@ -205,6 +207,7 @@ class CORE_EXPORT LocalFrame final
ScrollGranularity granularity,
Frame* child) override;
void DidFocus() override;
+ bool IsAdSubframe() const override;
// Triggers eviction of this frame by notifying the browser side.
void EvictFromBackForwardCache(mojom::blink::RendererEvictionReason reason);
@@ -219,7 +222,7 @@ class CORE_EXPORT LocalFrame final
// false otherwise.
bool CanContinueBufferingWhileInBackForwardCache();
- void DidChangeThemeColor();
+ void DidChangeThemeColor(bool update_theme_color_cache);
void DidChangeBackgroundColor(SkColor background_color, bool color_adjust);
// Returns false if detaching child frames reentrantly detached `this`.
@@ -255,6 +258,7 @@ class CORE_EXPORT LocalFrame final
SpellChecker& GetSpellChecker() const;
FrameConsole& Console() const;
BackgroundColorPaintImageGenerator* GetBackgroundColorPaintImageGenerator();
+ ClipPathPaintImageGenerator* GetClipPathPaintImageGenerator();
// A local root is the root of a connected subtree that contains only
// LocalFrames. The local root is responsible for coordinating input, layout,
@@ -356,6 +360,8 @@ class CORE_EXPORT LocalFrame final
void UpdateCSSFoldEnvironmentVariables(
const WebVector<gfx::Rect>& window_segments);
+ device::mojom::blink::DevicePostureType GetDevicePosture();
+
String SelectedText() const;
String SelectedTextForClipboard() const;
void TextSelectionChanged(const WTF::String& selection_text,
@@ -501,11 +507,8 @@ class CORE_EXPORT LocalFrame final
// be removed.
bool IsProvisional() const;
- // Called by the embedder according to whether the evidence indicates the
- // frame is an ad subframe. Called on creation of the initial empty document
- // or, for LocalFrames created on behalf of OOPIF, just before commit
- // (ReadyToCommitNavigation time).
- void SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type);
+ // Whether the frame is considered to be a root ad subframe by Ad Tagging.
+ bool IsAdRoot() const;
// Called by the embedder on creation of the initial empty document and, for
// all other documents, just before commit (ReadyToCommitNavigation time).
@@ -627,153 +630,27 @@ class CORE_EXPORT LocalFrame final
network::mojom::blink::RedirectMode cross_origin_redirect_behavior,
mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token);
- // blink::mojom::LocalFrame overrides:
- void GetTextSurroundingSelection(
- uint32_t max_length,
- GetTextSurroundingSelectionCallback callback) final;
- void SendInterventionReport(const String& id, const String& message) final;
- void SetFrameOwnerProperties(
- mojom::blink::FrameOwnerPropertiesPtr properties) final;
void NotifyUserActivation(
- mojom::blink::UserActivationNotificationType notification_type) final;
- void NotifyVirtualKeyboardOverlayRect(const gfx::Rect& keyboard_rect) final;
- void AddMessageToConsole(mojom::blink::ConsoleMessageLevel level,
- const WTF::String& message,
- bool discard_duplicates) final;
- void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
- void SwapInImmediately() final;
- void StopLoading() final;
- void Collapse(bool collapsed) final;
- void EnableViewSourceMode() final;
- void Focus() final;
- void ClearFocusedElement() final;
- void GetResourceSnapshotForWebBundle(
- mojo::PendingReceiver<
- data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver)
- final;
- void CopyImageAt(const gfx::Point& window_point) final;
- void SaveImageAt(const gfx::Point& window_point) final;
- void ReportBlinkFeatureUsage(const Vector<mojom::blink::WebFeature>&) final;
- void RenderFallbackContent() final;
- void RenderFallbackContentWithResourceTiming(
- mojom::blink::ResourceTimingInfoPtr timing,
- const String& server_timing_values) final;
- void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) final;
- void DispatchBeforeUnload(bool is_reload,
- BeforeUnloadCallback callback) final;
- void MediaPlayerActionAt(
- const gfx::Point& window_point,
- blink::mojom::blink::MediaPlayerActionPtr action) final;
- void AdvanceFocusInFrame(
- mojom::blink::FocusType focus_type,
- const absl::optional<RemoteFrameToken>& source_frame_token) final;
- void AdvanceFocusInForm(mojom::blink::FocusType focus_type) final;
- void ReportContentSecurityPolicyViolation(
- network::mojom::blink::CSPViolationPtr csp_violation) final;
- // Updates the snapshotted policy attributes (sandbox flags and permissions
- // policy container policy) in the frame's FrameOwner. This is used when this
- // frame's parent is in another process and it dynamically updates this
- // frame's sandbox flags or container policy. The new policy won't take effect
- // until the next navigation.
- void DidUpdateFramePolicy(const FramePolicy& frame_policy) final;
- void OnScreensChange() final;
+ mojom::blink::UserActivationNotificationType notification_type);
+ void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr);
+ void SaveImageAt(const gfx::Point& window_point);
+ void AdvanceFocusInForm(mojom::blink::FocusType focus_type);
void PostMessageEvent(
const absl::optional<RemoteFrameToken>& source_frame_token,
const String& source_origin,
const String& target_origin,
- BlinkTransferableMessage message) final;
- void JavaScriptMethodExecuteRequest(
- const String& object_name,
- const String& method_name,
- base::Value arguments,
- bool wants_result,
- JavaScriptMethodExecuteRequestCallback callback) final;
- void JavaScriptExecuteRequest(
- const String& javascript,
- bool wants_result,
- JavaScriptExecuteRequestCallback callback) final;
- void JavaScriptExecuteRequestForTests(
- const String& javascript,
- bool wants_result,
- bool has_user_gesture,
- int32_t world_id,
- JavaScriptExecuteRequestForTestsCallback callback) final;
- void JavaScriptExecuteRequestInIsolatedWorld(
- const String& javascript,
- bool wants_result,
- int32_t world_id,
- JavaScriptExecuteRequestInIsolatedWorldCallback callback) final;
- void BindReportingObserver(
- mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) final;
- void UpdateOpener(
- const absl::optional<blink::FrameToken>& opener_routing_id) final;
- void GetSavableResourceLinks(GetSavableResourceLinksCallback callback) final;
- void MixedContentFound(
- const KURL& main_resource_url,
- const KURL& mixed_content_url,
- mojom::blink::RequestContextType request_context,
- bool was_allowed,
- const KURL& url_before_redirects,
- bool had_redirect,
- network::mojom::blink::SourceLocationPtr source_location) final;
- void ActivateForPrerendering() final;
- void BindDevToolsAgent(
- mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host,
- mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver)
- final;
-#if defined(OS_ANDROID)
- void ExtractSmartClipData(const gfx::Rect& rect,
- ExtractSmartClipDataCallback callback) final;
-#endif
- void HandleRendererDebugURL(const KURL& url) final;
- void GetCanonicalUrlForSharing(
- GetCanonicalUrlForSharingCallback callback) final;
-
- // blink::mojom::LocalMainFrame overrides:
- void AnimateDoubleTapZoom(const gfx::Point& point,
- const gfx::Rect& rect) override;
- void SetScaleFactor(float scale) override;
- void ClosePage(
- mojom::blink::LocalMainFrame::ClosePageCallback callback) override;
- void PluginActionAt(const gfx::Point& location,
- mojom::blink::PluginActionType action) override;
- void SetInitialFocus(bool reverse) override;
- void EnablePreferredSizeChangedMode() override;
- void ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) override;
+ BlinkTransferableMessage message);
+
+ void SetScaleFactor(float scale);
+ void ClosePageForTesting();
+ void SetInitialFocus(bool reverse);
+
#if defined(OS_MAC)
- void GetCharacterIndexAtPoint(const gfx::Point& point) final;
- void GetFirstRectForRange(const gfx::Range& range) final;
- void GetStringForRange(const gfx::Range& range,
- GetStringForRangeCallback callback) final;
+ void GetCharacterIndexAtPoint(const gfx::Point& point);
#endif
- void InstallCoopAccessMonitor(
- network::mojom::blink::CoopAccessReportType report_type,
- const FrameToken& accessed_window,
- mojo::PendingRemote<
- network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter,
- bool endpoint_defined,
- const WTF::String& reported_window_url) final;
- void OnPortalActivated(
- const PortalToken& portal_token,
- mojo::PendingAssociatedRemote<mojom::blink::Portal> portal,
- mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client,
- BlinkTransferableMessage data,
- uint64_t trace_id,
- OnPortalActivatedCallback callback) final;
- void ForwardMessageFromHost(
- BlinkTransferableMessage message,
- const scoped_refptr<const SecurityOrigin>& source_origin) final;
- void UpdateBrowserControlsState(cc::BrowserControlsState constraints,
- cc::BrowserControlsState current,
- bool animate) override;
- void UpdateWindowControlsOverlay(
- const gfx::Rect& window_controls_overlay_rect) override;
-
- // mojom::FullscreenVideoElementHandler implementation:
- void RequestFullscreenVideoElement() final;
+ void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect_in_dips);
SystemClipboard* GetSystemClipboard();
- RawSystemClipboard* GetRawSystemClipboard();
// Indicate that this frame was attached as a MainFrame.
void WasAttachedAsLocalMainFrame();
@@ -792,15 +669,7 @@ class CORE_EXPORT LocalFrame final
// Consumes the |PaymentRequestToken| of the current |Frame| if it was active.
bool ConsumePaymentRequestToken();
- void SetOptimizationGuideHints(
- mojom::blink::BlinkOptimizationGuideHintsPtr hints);
- mojom::blink::BlinkOptimizationGuideHints* GetOptimizationGuideHints() {
- return optimization_guide_hints_.get();
- }
-
- LocalFrameToken GetLocalFrameToken() const {
- return GetFrameToken().GetAs<LocalFrameToken>();
- }
+ LocalFrameToken GetLocalFrameToken() const;
TextFragmentHandler* GetTextFragmentHandler() const {
// |text_fragment_handler_| is always set on the main frame, and null
@@ -808,10 +677,7 @@ class CORE_EXPORT LocalFrame final
return text_fragment_handler_;
}
- TextFragmentSelectorGenerator* GetTextFragmentSelectorGenerator() const;
-
- WebURLLoader::DeferType GetLoadDeferType();
- bool IsLoadDeferred();
+ LoaderFreezeMode GetLoaderFreezeMode();
bool SwapIn();
@@ -825,14 +691,32 @@ class CORE_EXPORT LocalFrame final
return window_controls_overlay_rect_;
}
- // Called after the document in this frame dispatched the prerenderingchange
- // event.
- void DidActivateForPrerendering();
-
void LoadJavaScriptURL(const KURL& url);
+ void SetEvictCachedSessionStorageOnFreezeOrUnload();
+
+ // Whether to maintain a trivial session history.
+ //
+ // One example is prerender.
+ // Explainer:
+ // https://github.com/jeremyroman/alternate-loading-modes/blob/main/browsing-context.md#session-history
+ bool ShouldMaintainTrivialSessionHistory() const;
+
+ void BindTextFragmentReceiver(
+ mojo::PendingReceiver<mojom::blink::TextFragmentReceiver> receiver);
+
+ void CreateTextFragmentHandler();
+
+#if defined(OS_MAC)
+ void ResetTextInputHostForTesting();
+ void RebindTextInputHostForTesting();
+#endif
+
private:
friend class FrameNavigationDisabler;
+ // LocalFrameMojoHandler is a part of LocalFrame.
+ friend class LocalFrameMojoHandler;
+
FRIEND_TEST_ALL_PREFIXES(LocalFrameTest, CharacterIndexAtPointWithPinchZoom);
FRIEND_TEST_ALL_PREFIXES(WebFrameTest, SmartClipData);
FRIEND_TEST_ALL_PREFIXES(WebFrameTest, SmartClipDataWithPinchZoom);
@@ -840,33 +724,6 @@ class CORE_EXPORT LocalFrame final
SmartClipReturnsEmptyStringsWhenUserSelectIsNone);
FRIEND_TEST_ALL_PREFIXES(WebFrameTest, SmartClipDoesNotCrashPositionReversed);
- // A wrapper class used as the callback for JavaScript executed
- // in an isolated world.
- class JavaScriptIsolatedWorldRequest
- : public GarbageCollected<JavaScriptIsolatedWorldRequest>,
- public WebScriptExecutionCallback {
- public:
- JavaScriptIsolatedWorldRequest(
- LocalFrame* local_frame,
- bool wants_result,
- JavaScriptExecuteRequestInIsolatedWorldCallback callback);
- JavaScriptIsolatedWorldRequest(const JavaScriptIsolatedWorldRequest&) =
- delete;
- JavaScriptIsolatedWorldRequest& operator=(
- const JavaScriptIsolatedWorldRequest&) = delete;
- ~JavaScriptIsolatedWorldRequest() override;
-
- // WebScriptExecutionCallback:
- void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
-
- void Trace(Visitor* visitor) const { visitor->Trace(local_frame_); }
-
- private:
- Member<LocalFrame> local_frame_;
- bool wants_result_;
- JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
- };
-
// Frame protected overrides:
bool DetachImpl(FrameDetachType) override;
@@ -922,10 +779,6 @@ class CORE_EXPORT LocalFrame final
bool ShouldThrottleDownload();
-#if defined(OS_MAC)
- mojom::blink::TextInputHost& GetTextInputHost();
-#endif
-
// Returns the `Frame` for which `provisional_frame_ == this`. May only be
// called on a provisional frame.
Frame* GetProvisionalOwnerFrame();
@@ -935,19 +788,12 @@ class CORE_EXPORT LocalFrame final
String& clip_html,
gfx::Rect& clip_rect);
- static void BindToReceiver(
- blink::LocalFrame* frame,
- mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver);
- static void BindToMainFrameReceiver(
- blink::LocalFrame* frame,
- mojo::PendingAssociatedReceiver<mojom::blink::LocalMainFrame> receiver);
- void BindToHighPriorityReceiver(
- mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver);
- void BindFullscreenVideoElementReceiver(
- mojo::PendingAssociatedReceiver<
- mojom::blink::FullscreenVideoElementHandler> receiver);
- void BindTextFragmentReceiver(
- mojo::PendingReceiver<mojom::blink::TextFragmentReceiver> receiver);
+ // Whether a navigation should replace the current history entry or not.
+ // Note this isn't exhaustive; there are other cases where a navigation does a
+ // replacement which this function doesn't cover.
+ bool NavigationShouldReplaceCurrentHistoryEntry(
+ const FrameLoadRequest& request,
+ WebFrameLoadType frame_load_type);
std::unique_ptr<FrameScheduler> frame_scheduler_;
@@ -1015,17 +861,6 @@ class CORE_EXPORT LocalFrame final
Member<ContentCaptureManager> content_capture_manager_;
InterfaceRegistry* const interface_registry_;
- // This is declared mutable so that the service endpoint can be cached by
- // const methods.
- //
- // LocalFrame can be reused by multiple ExecutionContext.
- mutable HeapMojoRemote<mojom::blink::ReportingServiceProxy>
- reporting_service_{nullptr};
-
-#if defined(OS_MAC)
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoRemote<mojom::blink::TextInputHost> text_input_host_{nullptr};
-#endif
mojom::blink::ViewportIntersectionState intersection_state_;
@@ -1054,25 +889,7 @@ class CORE_EXPORT LocalFrame final
std::unique_ptr<WebPrescientNetworking> prescient_networking_;
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoAssociatedRemote<mojom::blink::LocalFrameHost>
- local_frame_host_remote_{nullptr};
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoAssociatedRemote<mojom::blink::BackForwardCacheControllerHost>
- back_forward_cache_controller_host_remote_{nullptr};
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoAssociatedReceiver<mojom::blink::LocalFrame, LocalFrame> receiver_{
- this, nullptr};
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoAssociatedReceiver<mojom::blink::LocalMainFrame, LocalFrame>
- main_frame_receiver_{this, nullptr};
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoReceiver<mojom::blink::HighPriorityLocalFrame, LocalFrame>
- high_priority_frame_receiver_{this, nullptr};
- // LocalFrame can be reused by multiple ExecutionContext.
- HeapMojoAssociatedReceiver<mojom::blink::FullscreenVideoElementHandler,
- LocalFrame>
- fullscreen_video_receiver_{this, nullptr};
+ Member<LocalFrameMojoHandler> mojo_handler_;
// Variable to control burst of download requests.
int num_burst_download_requests_ = 0;
@@ -1080,17 +897,19 @@ class CORE_EXPORT LocalFrame final
// Access to the global sanitized system clipboard.
Member<SystemClipboard> system_clipboard_;
- // Access to the global raw/unsanitized system clipboard
- Member<RawSystemClipboard> raw_system_clipboard_;
+ // Access to background-color paint image generator. Initialized per local
+ // root and reused among sub frames.
Member<BackgroundColorPaintImageGenerator>
background_color_paint_image_generator_;
+ // Access to clip-path paint image generator. Initialized per local root and
+ // reused among sub frames.
+ Member<ClipPathPaintImageGenerator> clip_path_paint_image_generator_;
+
using SavedScrollOffsets = HeapHashMap<Member<Node>, ScrollOffset>;
Member<SavedScrollOffsets> saved_scroll_offsets_;
- mojom::blink::BlinkOptimizationGuideHintsPtr optimization_guide_hints_;
-
// Always non-null for the main frame; null otherwise.
Member<TextFragmentHandler> text_fragment_handler_;
@@ -1114,11 +933,11 @@ class CORE_EXPORT LocalFrame final
absl::optional<blink::FrameAdEvidence> ad_evidence_;
// True if this frame is a subframe that had a script tagged as an ad on the
- // v8 stack at the time of creation. This is not currently propagated when a
- // frame navigates cross-origin.
- // TODO(crbug.com/1145634): propagate this bit for a frame that navigates
- // cross-origin.
+ // v8 stack at the time of creation. This is updated in `SetAdEvidence()`,
+ // allowing the bit to be propagated when a frame navigates cross-origin.
bool is_subframe_created_by_ad_script_ = false;
+
+ bool evict_cached_session_storage_on_freeze_or_unload_ = false;
};
inline FrameLoader& LocalFrame::Loader() const {
@@ -1166,12 +985,12 @@ class FrameNavigationDisabler {
public:
explicit FrameNavigationDisabler(LocalFrame&);
+ FrameNavigationDisabler(const FrameNavigationDisabler&) = delete;
+ FrameNavigationDisabler& operator=(const FrameNavigationDisabler&) = delete;
~FrameNavigationDisabler();
private:
LocalFrame* frame_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameNavigationDisabler);
};
// A helper class for attributing cost inside a scope to a LocalFrame, with
@@ -1197,6 +1016,8 @@ class ScopedFrameBlamer {
public:
explicit ScopedFrameBlamer(LocalFrame*);
+ ScopedFrameBlamer(const ScopedFrameBlamer&) = delete;
+ ScopedFrameBlamer& operator=(const ScopedFrameBlamer&) = delete;
~ScopedFrameBlamer() {
if (UNLIKELY(frame_))
LeaveContext();
@@ -1206,8 +1027,6 @@ class ScopedFrameBlamer {
void LeaveContext();
LocalFrame* frame_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedFrameBlamer);
};
} // namespace blink
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 549a8f00a63..fd9d33e9ee3 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
@@ -81,6 +81,7 @@ namespace blink {
class AssociatedInterfaceProvider;
class DocumentLoader;
+class HTMLFencedFrameElement;
class HTMLFormElement;
class HTMLFrameOwnerElement;
class HTMLMediaElement;
@@ -129,11 +130,13 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
const ResourceResponse&) = 0;
virtual void DispatchDidHandleOnloadEvents() = 0;
- virtual void DidFinishSameDocumentNavigation(HistoryItem*,
- WebHistoryCommitType,
- bool is_synchronously_committed,
- bool is_history_api_navigation,
- bool is_client_redirect) {}
+ virtual void DidFinishSameDocumentNavigation(
+ HistoryItem*,
+ WebHistoryCommitType,
+ bool is_synchronously_committed,
+ mojom::blink::SameDocumentNavigationType,
+ bool is_client_redirect) {}
+ virtual void DispatchDidOpenDocumentInputStream(const KURL&) {}
virtual void DispatchDidReceiveTitle(const String&) = 0;
virtual void DispatchDidCommitLoad(
HistoryItem* item,
@@ -198,11 +201,6 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidObserveLayoutShift(double score, bool after_input_or_scroll) {
}
- // Reports input timestamps for segmenting layout shifts by users inputs to
- // create Session window.
- virtual void DidObserveInputForLayoutShiftTracking(
- base::TimeTicks timestamp) {}
-
// Reports the number of LayoutBlock creation, and LayoutObject::UpdateLayout
// calls. All values are deltas since the last calls of this function.
virtual void DidObserveLayoutNg(uint32_t all_block_count,
@@ -268,6 +266,10 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
// portal, allowing instantaneous back and forward activations.
virtual RemoteFrame* AdoptPortal(HTMLPortalElement* portal) = 0;
+ // Creates a remote fenced frame hosted by an MPArch frame tree for the
+ // |HTMLFencedFrameElement|.
+ virtual RemoteFrame* CreateFencedFrame(HTMLFencedFrameElement*) = 0;
+
// Whether or not plugin creation should fail if the HTMLPlugInElement isn't
// in the DOM after plugin initialization.
enum DetachedPluginPolicy {
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
index 5ec09513780..96aea6ae2dc 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -88,6 +88,7 @@
#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/loader/history_item.h"
+#include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/plugin_data.h"
@@ -308,7 +309,7 @@ bool LocalFrameClientImpl::HasWebView() const {
}
bool LocalFrameClientImpl::InShadowTree() const {
- return web_frame_->InShadowTree();
+ return web_frame_->GetTreeScopeType() == mojom::blink::TreeScopeType::kShadow;
}
void LocalFrameClientImpl::WillBeDetached() {
@@ -382,18 +383,22 @@ void LocalFrameClientImpl::DidFinishSameDocumentNavigation(
HistoryItem* item,
WebHistoryCommitType commit_type,
bool is_synchronously_committed,
- bool is_history_api_navigation,
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type,
bool is_client_redirect) {
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(
- commit_type, is_synchronously_committed, is_history_api_navigation,
+ commit_type, is_synchronously_committed, same_document_navigation_type,
is_client_redirect);
}
}
+void LocalFrameClientImpl::DispatchDidOpenDocumentInputStream(const KURL& url) {
+ web_frame_->Client()->DidOpenDocumentInputStream(url);
+}
+
void LocalFrameClientImpl::DispatchDidReceiveTitle(const String& title) {
if (web_frame_->Client()) {
web_frame_->Client()->DidReceiveTitle(title);
@@ -709,12 +714,6 @@ void LocalFrameClientImpl::DidObserveLayoutShift(double score,
client->DidObserveLayoutShift(score, after_input_or_scroll);
}
-void LocalFrameClientImpl::DidObserveInputForLayoutShiftTracking(
- base::TimeTicks timestamp) {
- if (WebLocalFrameClient* client = web_frame_->Client())
- client->DidObserveInputForLayoutShiftTracking(timestamp);
-}
-
void LocalFrameClientImpl::DidObserveLayoutNg(uint32_t all_block_count,
uint32_t ng_block_count,
uint32_t all_call_count,
@@ -835,6 +834,11 @@ RemoteFrame* LocalFrameClientImpl::AdoptPortal(HTMLPortalElement* portal) {
return web_frame_->AdoptPortal(portal);
}
+RemoteFrame* LocalFrameClientImpl::CreateFencedFrame(
+ HTMLFencedFrameElement* fenced_frame) {
+ return web_frame_->CreateFencedFrame(fenced_frame);
+}
+
WebPluginContainerImpl* LocalFrameClientImpl::CreatePlugin(
HTMLPlugInElement& element,
const KURL& url,
@@ -912,10 +916,7 @@ void LocalFrameClientImpl::DispatchDidChangeManifest() {
unsigned LocalFrameClientImpl::BackForwardLength() {
WebViewImpl* webview = web_frame_->ViewImpl();
- if (!webview)
- return 0;
- return webview->HistoryBackListCount() + 1 +
- webview->HistoryForwardListCount();
+ return webview ? webview->HistoryListLength() : 0;
}
BlameContext* LocalFrameClientImpl::GetFrameBlameContext() {
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.h
index dd342c654a2..b66e501d692 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -94,8 +94,9 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
void DidFinishSameDocumentNavigation(HistoryItem*,
WebHistoryCommitType,
bool is_handled_within_agent,
- bool is_history_api_navigation,
+ mojom::blink::SameDocumentNavigationType,
bool is_client_redirect) override;
+ void DispatchDidOpenDocumentInputStream(const KURL& url) override;
void DispatchDidReceiveTitle(const String&) override;
void DispatchDidCommitLoad(
HistoryItem*,
@@ -139,8 +140,6 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
void DidObserveLoadingBehavior(LoadingBehaviorFlag) override;
void DidObserveNewFeatureUsage(const UseCounterFeature&) override;
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
- void DidObserveInputForLayoutShiftTracking(
- base::TimeTicks timestamp) override;
void DidObserveLayoutNg(uint32_t all_block_count,
uint32_t ng_block_count,
uint32_t all_call_count,
@@ -182,6 +181,9 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
mojo::PendingAssociatedReceiver<mojom::blink::Portal>,
mojo::PendingAssociatedRemote<mojom::blink::PortalClient>) override;
RemoteFrame* AdoptPortal(HTMLPortalElement*) override;
+
+ RemoteFrame* CreateFencedFrame(HTMLFencedFrameElement*) override;
+
WebPluginContainerImpl* CreatePlugin(HTMLPlugInElement&,
const KURL&,
const Vector<WTF::String>&,
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
new file mode 100644
index 00000000000..71653584749
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -0,0 +1,1264 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/frame/local_frame_mojo_handler.h"
+
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom-blink.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/media_player_action.mojom-blink.h"
+#include "third_party/blink/public/platform/interface_registry.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/web/web_frame_serializer.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/renderer/bindings/core/v8/script_controller.h"
+#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.h"
+#include "third_party/blink/renderer/core/editing/surrounding_text.h"
+#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
+#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.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"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/frame/pausable_script_executor.h"
+#include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
+#include "third_party/blink/renderer/core/frame/reporting_context.h"
+#include "third_party/blink/renderer/core/frame/savable_resources.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/html_element.h"
+#include "third_party/blink/renderer/core/html/html_link_element.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h"
+#include "third_party/blink/renderer/core/html/portal/portal_activate_event.h"
+#include "third_party/blink/renderer/core/html/portal/portal_host.h"
+#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
+#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
+#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/paint_timing.h"
+#include "third_party/blink/renderer/core/script/classic_script.h"
+#include "third_party/blink/renderer/platform/mhtml/serialized_resource.h"
+#include "third_party/blink/renderer/platform/widget/frame_widget.h"
+
+#if defined(OS_MAC)
+#include "third_party/blink/renderer/core/editing/substring_util.h"
+#include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
+#include "ui/base/mojom/attributed_string.mojom-blink.h"
+#endif
+
+namespace blink {
+
+namespace {
+
+constexpr char kInvalidWorldID[] =
+ "JavaScriptExecuteRequestInIsolatedWorld gets an invalid world id.";
+
+#if defined(OS_MAC)
+uint32_t GetCurrentCursorPositionInFrame(LocalFrame* local_frame) {
+ blink::WebRange range =
+ WebLocalFrameImpl::FromFrame(local_frame)->SelectionRange();
+ return range.IsNull() ? 0U : static_cast<uint32_t>(range.StartOffset());
+}
+#endif
+
+RemoteFrame* SourceFrameForOptionalToken(
+ const absl::optional<RemoteFrameToken>& source_frame_token) {
+ if (!source_frame_token)
+ return nullptr;
+ return RemoteFrame::FromFrameToken(source_frame_token.value());
+}
+
+class WebBundleGenerationDelegate
+ : public WebFrameSerializer::MHTMLPartsGenerationDelegate {
+ STACK_ALLOCATED();
+
+ public:
+ WebBundleGenerationDelegate() = default;
+ ~WebBundleGenerationDelegate() = default;
+
+ WebBundleGenerationDelegate(const WebBundleGenerationDelegate&) = delete;
+ WebBundleGenerationDelegate& operator=(const WebBundleGenerationDelegate&) =
+ delete;
+
+ bool ShouldSkipResource(const WebURL& url) override { return false; }
+ bool UseBinaryEncoding() override { return false; }
+ bool RemovePopupOverlay() override { return false; }
+ bool UsePageProblemDetectors() override { return false; }
+};
+
+class ResourceSnapshotForWebBundleImpl
+ : public data_decoder::mojom::blink::ResourceSnapshotForWebBundle {
+ public:
+ explicit ResourceSnapshotForWebBundleImpl(Deque<SerializedResource> resources)
+ : resources_(std::move(resources)) {}
+ ~ResourceSnapshotForWebBundleImpl() override = default;
+
+ ResourceSnapshotForWebBundleImpl(const ResourceSnapshotForWebBundleImpl&) =
+ delete;
+ ResourceSnapshotForWebBundleImpl& operator=(
+ const ResourceSnapshotForWebBundleImpl&) = delete;
+
+ // data_decoder::mojom::blink::ResourceSnapshotForWebBundle:
+ void GetResourceCount(GetResourceCountCallback callback) override {
+ std::move(callback).Run(resources_.size());
+ }
+ void GetResourceInfo(uint64_t index,
+ GetResourceInfoCallback callback) override {
+ if (index >= resources_.size()) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+ const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
+ auto info = data_decoder::mojom::blink::SerializedResourceInfo::New();
+ info->url = resource.url;
+ info->mime_type = resource.mime_type;
+ info->size = resource.data ? resource.data->size() : 0;
+ std::move(callback).Run(std::move(info));
+ }
+ void GetResourceBody(uint64_t index,
+ GetResourceBodyCallback callback) override {
+ if (index >= resources_.size()) {
+ std::move(callback).Run(absl::nullopt);
+ return;
+ }
+ const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
+ if (!resource.data) {
+ std::move(callback).Run(absl::nullopt);
+ return;
+ }
+ std::move(callback).Run(
+ mojo_base::BigBuffer(resource.data->CopyAs<std::vector<uint8_t>>()));
+ }
+
+ private:
+ const Deque<SerializedResource> resources_;
+};
+
+v8::Local<v8::Context> MainWorldScriptContext(LocalFrame* local_frame) {
+ ScriptState* script_state = ToScriptStateForMainWorld(local_frame);
+ DCHECK(script_state);
+ return script_state->GetContext();
+}
+
+base::Value GetJavaScriptExecutionResult(v8::Local<v8::Value> result,
+ LocalFrame* local_frame,
+ WebV8ValueConverter* converter) {
+ if (!result.IsEmpty()) {
+ v8::Local<v8::Context> context = MainWorldScriptContext(local_frame);
+ v8::Context::Scope context_scope(context);
+ std::unique_ptr<base::Value> new_value =
+ converter->FromV8Value(result, context);
+ if (new_value)
+ return std::move(*new_value);
+ }
+ return base::Value();
+}
+
+v8::MaybeLocal<v8::Value> GetProperty(v8::Local<v8::Context> context,
+ v8::Local<v8::Value> object,
+ const String& name) {
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::Local<v8::String> name_str = V8String(isolate, name);
+ v8::Local<v8::Object> object_obj;
+ if (!object->ToObject(context).ToLocal(&object_obj)) {
+ return v8::MaybeLocal<v8::Value>();
+ }
+ return object_obj->Get(context, name_str);
+}
+
+v8::MaybeLocal<v8::Value> CallMethodOnFrame(LocalFrame* local_frame,
+ const String& object_name,
+ const String& method_name,
+ base::Value arguments,
+ WebV8ValueConverter* converter) {
+ v8::Local<v8::Context> context = MainWorldScriptContext(local_frame);
+
+ v8::Context::Scope context_scope(context);
+ WTF::Vector<v8::Local<v8::Value>> args;
+ for (auto const& argument : arguments.GetList()) {
+ args.push_back(converter->ToV8Value(&argument, context));
+ }
+
+ v8::Local<v8::Value> object;
+ v8::Local<v8::Value> method;
+ if (!GetProperty(context, context->Global(), object_name).ToLocal(&object) ||
+ !GetProperty(context, object, method_name).ToLocal(&method)) {
+ return v8::MaybeLocal<v8::Value>();
+ }
+
+ return local_frame->DomWindow()
+ ->GetScriptController()
+ .EvaluateMethodInMainWorld(v8::Local<v8::Function>::Cast(method), object,
+ static_cast<int>(args.size()), args.data());
+}
+
+// A wrapper class used as the callback for JavaScript executed
+// in an isolated world.
+class JavaScriptIsolatedWorldRequest
+ : public GarbageCollected<JavaScriptIsolatedWorldRequest>,
+ public WebScriptExecutionCallback {
+ using JavaScriptExecuteRequestInIsolatedWorldCallback =
+ mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback;
+
+ public:
+ JavaScriptIsolatedWorldRequest(
+ LocalFrame* local_frame,
+ bool wants_result,
+ mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback
+ callback);
+ JavaScriptIsolatedWorldRequest(const JavaScriptIsolatedWorldRequest&) =
+ delete;
+ JavaScriptIsolatedWorldRequest& operator=(
+ const JavaScriptIsolatedWorldRequest&) = delete;
+ ~JavaScriptIsolatedWorldRequest() override;
+
+ // WebScriptExecutionCallback:
+ void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
+
+ void Trace(Visitor* visitor) const { visitor->Trace(local_frame_); }
+
+ private:
+ Member<LocalFrame> local_frame_;
+ bool wants_result_;
+ JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
+};
+
+JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
+ LocalFrame* local_frame,
+ bool wants_result,
+ JavaScriptExecuteRequestInIsolatedWorldCallback callback)
+ : local_frame_(local_frame),
+ wants_result_(wants_result),
+ callback_(std::move(callback)) {}
+
+JavaScriptIsolatedWorldRequest::~JavaScriptIsolatedWorldRequest() = default;
+
+void JavaScriptIsolatedWorldRequest::Completed(
+ const WebVector<v8::Local<v8::Value>>& result) {
+ base::Value value;
+ if (!result.empty() && !result.begin()->IsEmpty() && wants_result_) {
+ // It's safe to always use the main world context when converting
+ // here. V8ValueConverter shouldn't actually care about the context
+ // scope, and it switches to v8::Object's creation context when
+ // encountered. (from extensions/renderer/script_injection.cc)
+ v8::Local<v8::Context> context = MainWorldScriptContext(local_frame_);
+ v8::Context::Scope context_scope(context);
+ std::unique_ptr<WebV8ValueConverter> converter =
+ Platform::Current()->CreateWebV8ValueConverter();
+ converter->SetDateAllowed(true);
+ converter->SetRegExpAllowed(true);
+ std::unique_ptr<base::Value> new_value =
+ converter->FromV8Value(*result.begin(), context);
+ if (new_value)
+ value = base::Value::FromUniquePtrValue(std::move(new_value));
+ }
+
+ std::move(callback_).Run(std::move(value));
+}
+
+HitTestResult HitTestResultForRootFramePos(
+ LocalFrame* main_frame,
+ const PhysicalOffset& pos_in_root_frame) {
+ DCHECK(main_frame->IsMainFrame());
+
+ HitTestLocation location(
+ main_frame->View()->ConvertFromRootFrame(pos_in_root_frame));
+ HitTestResult result = main_frame->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ result.SetToShadowHostIfInRestrictedShadowRoot();
+ return result;
+}
+
+} // namespace
+
+ActiveURLMessageFilter::~ActiveURLMessageFilter() {
+ if (debug_url_set_) {
+ Platform::Current()->SetActiveURL(WebURL(), WebString());
+ }
+}
+
+bool ActiveURLMessageFilter::WillDispatch(mojo::Message* message) {
+ // We expect local_frame_ always to be set because this MessageFilter
+ // is owned by the LocalFrame. We do not want to introduce a Persistent
+ // reference so we don't cause a cycle. If you hit this CHECK then you
+ // likely didn't reset your mojo receiver in Detach.
+ CHECK(local_frame_);
+ debug_url_set_ = true;
+ Platform::Current()->SetActiveURL(local_frame_->GetDocument()->Url(),
+ local_frame_->Top()
+ ->GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->ToString());
+ return true;
+}
+
+void ActiveURLMessageFilter::DidDispatchOrReject(mojo::Message* message,
+ bool accepted) {
+ Platform::Current()->SetActiveURL(WebURL(), WebString());
+ debug_url_set_ = false;
+}
+
+LocalFrameMojoHandler::LocalFrameMojoHandler(blink::LocalFrame& frame)
+ : frame_(frame) {
+ frame.GetRemoteNavigationAssociatedInterfaces()->GetInterface(
+ back_forward_cache_controller_host_remote_.BindNewEndpointAndPassReceiver(
+ frame.GetTaskRunner(TaskType::kInternalDefault)));
+#if defined(OS_MAC)
+ // It should be bound before accessing TextInputHost which is the interface to
+ // respond to GetCharacterIndexAtPoint.
+ frame.GetBrowserInterfaceBroker().GetInterface(
+ text_input_host_.BindNewPipeAndPassReceiver(
+ frame.GetTaskRunner(TaskType::kInternalDefault)));
+#endif
+
+ frame.GetRemoteNavigationAssociatedInterfaces()->GetInterface(
+ local_frame_host_remote_.BindNewEndpointAndPassReceiver(
+ frame.GetTaskRunner(TaskType::kInternalDefault)));
+
+ auto* registry = frame.GetInterfaceRegistry();
+ registry->AddAssociatedInterface(
+ WTF::BindRepeating(&LocalFrameMojoHandler::BindToLocalFrameReceiver,
+ WrapWeakPersistent(this)));
+ registry->AddInterface(
+ WTF::BindRepeating(&LocalFrameMojoHandler::BindToHighPriorityReceiver,
+ WrapWeakPersistent(this)),
+ frame.GetTaskRunner(TaskType::kInternalHighPriorityLocalFrame));
+ registry->AddAssociatedInterface(WTF::BindRepeating(
+ &LocalFrameMojoHandler::BindFullscreenVideoElementReceiver,
+ WrapWeakPersistent(this)));
+}
+
+void LocalFrameMojoHandler::Trace(Visitor* visitor) const {
+ visitor->Trace(frame_);
+ visitor->Trace(back_forward_cache_controller_host_remote_);
+#if defined(OS_MAC)
+ visitor->Trace(text_input_host_);
+#endif
+ visitor->Trace(reporting_service_);
+ visitor->Trace(device_posture_provider_service_);
+ visitor->Trace(local_frame_host_remote_);
+ visitor->Trace(local_frame_receiver_);
+ visitor->Trace(main_frame_receiver_);
+ visitor->Trace(high_priority_frame_receiver_);
+ visitor->Trace(fullscreen_video_receiver_);
+ visitor->Trace(device_posture_receiver_);
+}
+
+void LocalFrameMojoHandler::WasAttachedAsLocalMainFrame() {
+ frame_->GetInterfaceRegistry()->AddAssociatedInterface(
+ WTF::BindRepeating(&LocalFrameMojoHandler::BindToMainFrameReceiver,
+ WrapWeakPersistent(this)));
+}
+
+void LocalFrameMojoHandler::DidDetachFrame() {
+ // We reset receivers explicitly because HeapMojoReceiver does not
+ // automatically reset on context destruction.
+ local_frame_receiver_.reset();
+ main_frame_receiver_.reset();
+ high_priority_frame_receiver_.reset();
+ // TODO(tkent): Should we reset other receivers?
+}
+
+void LocalFrameMojoHandler::ClosePageForTesting() {
+ ClosePage(base::DoNothing());
+}
+
+mojom::blink::BackForwardCacheControllerHost&
+LocalFrameMojoHandler::BackForwardCacheControllerHostRemote() {
+ return *back_forward_cache_controller_host_remote_.get();
+}
+
+#if defined(OS_MAC)
+mojom::blink::TextInputHost& LocalFrameMojoHandler::TextInputHost() {
+ DCHECK(text_input_host_.is_bound());
+ return *text_input_host_.get();
+}
+
+void LocalFrameMojoHandler::ResetTextInputHostForTesting() {
+ text_input_host_.reset();
+}
+
+void LocalFrameMojoHandler::RebindTextInputHostForTesting() {
+ frame_->GetBrowserInterfaceBroker().GetInterface(
+ text_input_host_.BindNewPipeAndPassReceiver(
+ frame_->GetTaskRunner(TaskType::kInternalDefault)));
+}
+#endif
+
+mojom::blink::ReportingServiceProxy* LocalFrameMojoHandler::ReportingService() {
+ if (!reporting_service_.is_bound()) {
+ frame_->GetBrowserInterfaceBroker().GetInterface(
+ reporting_service_.BindNewPipeAndPassReceiver(
+ frame_->GetTaskRunner(TaskType::kInternalDefault)));
+ }
+ return reporting_service_.get();
+}
+
+device::mojom::blink::DevicePostureType
+LocalFrameMojoHandler::GetDevicePosture() {
+ if (device_posture_provider_service_.is_bound())
+ return current_device_posture_;
+
+ auto task_runner = frame_->GetTaskRunner(TaskType::kInternalDefault);
+ frame_->GetBrowserInterfaceBroker().GetInterface(
+ device_posture_provider_service_.BindNewPipeAndPassReceiver(task_runner));
+
+ device_posture_provider_service_->AddListenerAndGetCurrentPosture(
+ device_posture_receiver_.BindNewPipeAndPassRemote(task_runner),
+ WTF::Bind(&LocalFrameMojoHandler::OnPostureChanged,
+ WrapPersistent(this)));
+ return current_device_posture_;
+}
+
+Page* LocalFrameMojoHandler::GetPage() const {
+ return frame_->GetPage();
+}
+
+LocalDOMWindow* LocalFrameMojoHandler::DomWindow() const {
+ return frame_->DomWindow();
+}
+
+Document* LocalFrameMojoHandler::GetDocument() const {
+ return frame_->GetDocument();
+}
+
+void LocalFrameMojoHandler::BindToLocalFrameReceiver(
+ mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver) {
+ if (frame_->IsDetached())
+ return;
+
+ local_frame_receiver_.Bind(std::move(receiver),
+ frame_->GetTaskRunner(TaskType::kInternalDefault));
+ local_frame_receiver_.SetFilter(
+ std::make_unique<ActiveURLMessageFilter>(frame_));
+}
+
+void LocalFrameMojoHandler::BindToMainFrameReceiver(
+ mojo::PendingAssociatedReceiver<mojom::blink::LocalMainFrame> receiver) {
+ if (frame_->IsDetached())
+ return;
+
+ main_frame_receiver_.Bind(std::move(receiver),
+ frame_->GetTaskRunner(TaskType::kInternalDefault));
+ main_frame_receiver_.SetFilter(
+ std::make_unique<ActiveURLMessageFilter>(frame_));
+}
+
+void LocalFrameMojoHandler::BindToHighPriorityReceiver(
+ mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver) {
+ if (frame_->IsDetached())
+ return;
+
+ high_priority_frame_receiver_.Bind(
+ std::move(receiver),
+ frame_->GetTaskRunner(TaskType::kInternalHighPriorityLocalFrame));
+ high_priority_frame_receiver_.SetFilter(
+ std::make_unique<ActiveURLMessageFilter>(frame_));
+}
+
+void LocalFrameMojoHandler::BindFullscreenVideoElementReceiver(
+ mojo::PendingAssociatedReceiver<mojom::blink::FullscreenVideoElementHandler>
+ receiver) {
+ if (frame_->IsDetached())
+ return;
+
+ fullscreen_video_receiver_.Bind(
+ std::move(receiver), frame_->GetTaskRunner(TaskType::kInternalDefault));
+ fullscreen_video_receiver_.SetFilter(
+ std::make_unique<ActiveURLMessageFilter>(frame_));
+}
+
+void LocalFrameMojoHandler::GetTextSurroundingSelection(
+ uint32_t max_length,
+ GetTextSurroundingSelectionCallback callback) {
+ SurroundingText surrounding_text(frame_, max_length);
+
+ // |surrounding_text| might not be correctly initialized, for example if
+ // |frame_->SelectionRange().IsNull()|, in other words, if there was no
+ // selection.
+ if (surrounding_text.IsEmpty()) {
+ // Don't use WTF::String's default constructor so that we make sure that we
+ // always send a valid empty string over the wire instead of a null pointer.
+ std::move(callback).Run(g_empty_string, 0, 0);
+ return;
+ }
+
+ std::move(callback).Run(surrounding_text.TextContent(),
+ surrounding_text.StartOffsetInTextContent(),
+ surrounding_text.EndOffsetInTextContent());
+}
+
+void LocalFrameMojoHandler::SendInterventionReport(const String& id,
+ const String& message) {
+ Intervention::GenerateReport(frame_, id, message);
+}
+
+void LocalFrameMojoHandler::SetFrameOwnerProperties(
+ mojom::blink::FrameOwnerPropertiesPtr properties) {
+ GetDocument()->WillChangeFrameOwnerProperties(
+ properties->margin_width, properties->margin_height,
+ properties->scrollbar_mode, properties->is_display_none,
+ properties->color_scheme);
+
+ frame_->ApplyFrameOwnerProperties(std::move(properties));
+}
+
+void LocalFrameMojoHandler::NotifyUserActivation(
+ mojom::blink::UserActivationNotificationType notification_type) {
+ frame_->NotifyUserActivation(notification_type);
+}
+
+void LocalFrameMojoHandler::NotifyVirtualKeyboardOverlayRect(
+ const gfx::Rect& keyboard_rect) {
+ Page* page = GetPage();
+ if (!page)
+ return;
+
+ // The rect passed to us from content is in DIP, relative to the main frame.
+ // This doesn't take the page's zoom factor into account so we must scale by
+ // the inverse of the page zoom in order to get correct client coordinates.
+ // Note that when use-zoom-for-dsf is enabled, WindowToViewportScalar will
+ // be the true device scale factor, and PageZoomFactor will be the combination
+ // of the device scale factor and the zoom percent of the page.
+ blink::LocalFrame& local_frame_root = frame_->LocalFrameRoot();
+ const float window_to_viewport_factor =
+ page->GetChromeClient().WindowToViewportScalar(&local_frame_root, 1.0f);
+ const float zoom_factor = local_frame_root.PageZoomFactor();
+ const float scale_factor = zoom_factor / window_to_viewport_factor;
+ gfx::Rect scaled_rect(keyboard_rect.x() / scale_factor,
+ keyboard_rect.y() / scale_factor,
+ keyboard_rect.width() / scale_factor,
+ keyboard_rect.height() / scale_factor);
+
+ frame_->NotifyVirtualKeyboardOverlayRectObservers(scaled_rect);
+}
+
+void LocalFrameMojoHandler::AddMessageToConsole(
+ mojom::blink::ConsoleMessageLevel level,
+ const WTF::String& message,
+ bool discard_duplicates) {
+ GetDocument()->AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther, level, message),
+ discard_duplicates);
+}
+
+void LocalFrameMojoHandler::AddInspectorIssue(
+ mojom::blink::InspectorIssueInfoPtr info) {
+ if (auto* page = GetPage()) {
+ page->GetInspectorIssueStorage().AddInspectorIssue(DomWindow(),
+ std::move(info));
+ }
+}
+
+void LocalFrameMojoHandler::SwapInImmediately() {
+ frame_->SwapIn();
+ // Normally, this happens as part of committing a cross-Document navigation.
+ // However, there is no navigation being committed here. Instead, the browser
+ // navigation code is optimistically early-swapping in this frame to replace a
+ // crashed subframe after starting a navigation.
+ //
+ // While the provisional frame has a unique opaque origin, the Blink bindings
+ // code still expects the WindowProxy to be initialized for the access check
+ // failed callbacks.
+ DomWindow()->GetScriptController().UpdateDocument();
+}
+
+void LocalFrameMojoHandler::CheckCompleted() {
+ frame_->CheckCompleted();
+}
+
+void LocalFrameMojoHandler::StopLoading() {
+ frame_->Loader().StopAllLoaders(/*abort_client=*/true);
+
+ // The stopLoading handler may run script, which may cause this frame to be
+ // detached/deleted. If that happens, return immediately.
+ if (!frame_->IsAttached())
+ return;
+
+ // Notify RenderFrame observers.
+ WebLocalFrameClient* client = frame_->Client()->GetWebFrame()->Client();
+ if (client)
+ client->OnStopLoading();
+}
+
+void LocalFrameMojoHandler::Collapse(bool collapsed) {
+ FrameOwner* owner = frame_->Owner();
+ To<HTMLFrameOwnerElement>(owner)->SetCollapsed(collapsed);
+}
+
+void LocalFrameMojoHandler::EnableViewSourceMode() {
+ DCHECK(!frame_->Tree().Parent());
+ frame_->SetInViewSourceMode(true);
+}
+
+void LocalFrameMojoHandler::Focus() {
+ frame_->FocusImpl();
+}
+
+void LocalFrameMojoHandler::ClearFocusedElement() {
+ Document* document = GetDocument();
+ Element* old_focused_element = document->FocusedElement();
+ document->ClearFocusedElement();
+ if (!old_focused_element)
+ return;
+
+ // If a text field has focus, we need to make sure the selection controller
+ // knows to remove selection from it. Otherwise, the text field is still
+ // processing keyboard events even though focus has been moved to the page and
+ // keystrokes get eaten as a result.
+ document->UpdateStyleAndLayoutTree();
+ if (HasEditableStyle(*old_focused_element) ||
+ old_focused_element->IsTextControl())
+ frame_->Selection().Clear();
+}
+
+void LocalFrameMojoHandler::GetResourceSnapshotForWebBundle(
+ mojo::PendingReceiver<
+ data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver) {
+ Deque<SerializedResource> resources;
+
+ HeapHashSet<WeakMember<const Element>> shadow_template_elements;
+ WebBundleGenerationDelegate web_delegate;
+ FrameSerializerDelegateImpl core_delegate(web_delegate,
+ shadow_template_elements);
+ FrameSerializer serializer(resources, core_delegate);
+ serializer.SerializeFrame(*frame_);
+
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<ResourceSnapshotForWebBundleImpl>(std::move(resources)),
+ std::move(receiver));
+}
+
+void LocalFrameMojoHandler::CopyImageAt(const gfx::Point& window_point) {
+ gfx::Point viewport_position =
+ frame_->GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
+ frame_->CopyImageAtViewportPoint(IntPoint(viewport_position));
+}
+
+void LocalFrameMojoHandler::SaveImageAt(const gfx::Point& window_point) {
+ frame_->SaveImageAt(window_point);
+}
+
+void LocalFrameMojoHandler::ReportBlinkFeatureUsage(
+ const Vector<mojom::blink::WebFeature>& features) {
+ DCHECK(!features.IsEmpty());
+
+ // Assimilate all features used/performed by the browser into UseCounter.
+ auto* document = GetDocument();
+ DCHECK(document);
+ for (const auto& feature : features)
+ document->CountUse(feature);
+}
+
+void LocalFrameMojoHandler::RenderFallbackContent() {
+ frame_->RenderFallbackContent();
+}
+
+void LocalFrameMojoHandler::RenderFallbackContentWithResourceTiming(
+ mojom::blink::ResourceTimingInfoPtr timing,
+ const String& server_timing_value) {
+ frame_->RenderFallbackContentWithResourceTiming(std::move(timing),
+ server_timing_value);
+}
+
+void LocalFrameMojoHandler::BeforeUnload(bool is_reload,
+ BeforeUnloadCallback callback) {
+ base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
+
+ // This will execute the BeforeUnload event in this frame and all of its
+ // local descendant frames, including children of remote frames. The browser
+ // process will send separate IPCs to dispatch beforeunload in any
+ // out-of-process child frames.
+ bool proceed = frame_->Loader().ShouldClose(is_reload);
+
+ DCHECK(!callback.is_null());
+ base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
+ std::move(callback).Run(proceed, before_unload_start_time,
+ before_unload_end_time);
+}
+
+void LocalFrameMojoHandler::MediaPlayerActionAt(
+ const gfx::Point& window_point,
+ blink::mojom::blink::MediaPlayerActionPtr action) {
+ gfx::Point viewport_position =
+ frame_->GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
+ IntPoint location(viewport_position);
+
+ frame_->MediaPlayerActionAtViewportPoint(location, action->type,
+ action->enable);
+}
+
+void LocalFrameMojoHandler::AdvanceFocusInFrame(
+ mojom::blink::FocusType focus_type,
+ const absl::optional<RemoteFrameToken>& source_frame_token) {
+ RemoteFrame* source_frame =
+ source_frame_token ? SourceFrameForOptionalToken(*source_frame_token)
+ : nullptr;
+ if (!source_frame) {
+ SetInitialFocus(focus_type == mojom::blink::FocusType::kBackward);
+ return;
+ }
+
+ GetPage()->GetFocusController().AdvanceFocusAcrossFrames(
+ focus_type, source_frame, frame_);
+}
+
+void LocalFrameMojoHandler::AdvanceFocusInForm(
+ mojom::blink::FocusType focus_type) {
+ auto* focused_frame = GetPage()->GetFocusController().FocusedFrame();
+ if (focused_frame != frame_)
+ return;
+
+ DCHECK(GetDocument());
+ Element* element = GetDocument()->FocusedElement();
+ if (!element)
+ return;
+
+ Element* next_element =
+ GetPage()->GetFocusController().NextFocusableElementInForm(element,
+ focus_type);
+ if (!next_element)
+ return;
+
+ next_element->scrollIntoViewIfNeeded(true /*centerIfNeeded*/);
+ next_element->focus();
+}
+
+void LocalFrameMojoHandler::ReportContentSecurityPolicyViolation(
+ network::mojom::blink::CSPViolationPtr violation) {
+ auto source_location = std::make_unique<SourceLocation>(
+ violation->source_location->url, violation->source_location->line,
+ violation->source_location->column, nullptr);
+
+ frame_->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kSecurity,
+ mojom::blink::ConsoleMessageLevel::kError, violation->console_message,
+ source_location->Clone()));
+
+ auto directive_type =
+ ContentSecurityPolicy::GetDirectiveType(violation->effective_directive);
+ blink::LocalFrame* context_frame =
+ directive_type == network::mojom::blink::CSPDirectiveName::FrameAncestors
+ ? frame_
+ : nullptr;
+
+ DomWindow()->GetContentSecurityPolicy()->ReportViolation(
+ violation->directive, directive_type, violation->console_message,
+ violation->blocked_url, violation->report_endpoints,
+ violation->use_reporting_api, violation->header, violation->type,
+ ContentSecurityPolicy::ContentSecurityPolicyViolationType::kURLViolation,
+ std::move(source_location), context_frame,
+ violation->after_redirect ? RedirectStatus::kFollowedRedirect
+ : RedirectStatus::kNoRedirect,
+ nullptr /* Element */);
+}
+
+void LocalFrameMojoHandler::DidUpdateFramePolicy(
+ const FramePolicy& frame_policy) {
+ // At the moment, this is only used to replicate sandbox flags and container
+ // policy for frames with a remote owner.
+ SECURITY_CHECK(IsA<RemoteFrameOwner>(frame_->Owner()));
+ To<RemoteFrameOwner>(frame_->Owner())->SetFramePolicy(frame_policy);
+}
+
+void LocalFrameMojoHandler::OnScreensChange() {
+ if (RuntimeEnabledFeatures::WindowPlacementEnabled(DomWindow())) {
+ // Allow fullscreen requests shortly after user-generated screens changes.
+ frame_->transient_allow_fullscreen_.Activate();
+ }
+}
+
+void LocalFrameMojoHandler::OnPostureChanged(
+ device::mojom::blink::DevicePostureType posture) {
+ if (!RuntimeEnabledFeatures::DevicePostureEnabled())
+ return;
+ current_device_posture_ = posture;
+ // A change of the device posture requires re-evaluation of media queries
+ // for the local frame subtree (the device posture affect the
+ // "device-posture" feature).
+ frame_->MediaQueryAffectingValueChangedForLocalSubtree(
+ MediaValueChange::kOther);
+}
+
+void LocalFrameMojoHandler::PostMessageEvent(
+ const absl::optional<RemoteFrameToken>& source_frame_token,
+ const String& source_origin,
+ const String& target_origin,
+ BlinkTransferableMessage message) {
+ frame_->PostMessageEvent(source_frame_token, source_origin, target_origin,
+ std::move(message));
+}
+
+void LocalFrameMojoHandler::JavaScriptMethodExecuteRequest(
+ const String& object_name,
+ const String& method_name,
+ base::Value arguments,
+ bool wants_result,
+ JavaScriptMethodExecuteRequestCallback callback) {
+ TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptMethodExecuteRequest",
+ TRACE_EVENT_SCOPE_THREAD);
+
+ std::unique_ptr<WebV8ValueConverter> converter =
+ Platform::Current()->CreateWebV8ValueConverter();
+ converter->SetDateAllowed(true);
+ converter->SetRegExpAllowed(true);
+
+ v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
+ v8::Local<v8::Value> result;
+ if (!CallMethodOnFrame(frame_, object_name, method_name, std::move(arguments),
+ converter.get())
+ .ToLocal(&result)) {
+ std::move(callback).Run({});
+ return;
+ }
+
+ if (wants_result) {
+ std::move(callback).Run(
+ GetJavaScriptExecutionResult(result, frame_, converter.get()));
+ } else {
+ std::move(callback).Run({});
+ }
+}
+
+void LocalFrameMojoHandler::JavaScriptExecuteRequest(
+ const String& javascript,
+ bool wants_result,
+ JavaScriptExecuteRequestCallback callback) {
+ TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequest",
+ TRACE_EVENT_SCOPE_THREAD);
+
+ v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
+ v8::Local<v8::Value> result =
+ ClassicScript::CreateUnspecifiedScript(javascript)
+ ->RunScriptAndReturnValue(DomWindow());
+
+ if (wants_result) {
+ std::unique_ptr<WebV8ValueConverter> converter =
+ Platform::Current()->CreateWebV8ValueConverter();
+ converter->SetDateAllowed(true);
+ converter->SetRegExpAllowed(true);
+
+ std::move(callback).Run(
+ GetJavaScriptExecutionResult(result, frame_, converter.get()));
+ } else {
+ std::move(callback).Run({});
+ }
+}
+
+void LocalFrameMojoHandler::JavaScriptExecuteRequestForTests(
+ const String& javascript,
+ bool wants_result,
+ bool has_user_gesture,
+ int32_t world_id,
+ JavaScriptExecuteRequestForTestsCallback callback) {
+ TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests",
+ TRACE_EVENT_SCOPE_THREAD);
+
+ // A bunch of tests expect to run code in the context of a user gesture, which
+ // can grant additional privileges (e.g. the ability to create popups).
+ if (has_user_gesture)
+ NotifyUserActivation(mojom::blink::UserActivationNotificationType::kTest);
+
+ v8::HandleScope handle_scope(V8PerIsolateData::MainThreadIsolate());
+ v8::Local<v8::Value> result;
+ if (world_id == DOMWrapperWorld::kMainWorldId) {
+ result = ClassicScript::CreateUnspecifiedScript(javascript)
+ ->RunScriptAndReturnValue(DomWindow());
+ } else {
+ CHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
+ CHECK_LT(world_id, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit);
+ // Note: An error event in an isolated world will never be dispatched to
+ // a foreign world.
+ result =
+ ClassicScript::CreateUnspecifiedScript(
+ javascript, SanitizeScriptErrors::kDoNotSanitize)
+ ->RunScriptInIsolatedWorldAndReturnValue(DomWindow(), world_id);
+ }
+
+ if (wants_result) {
+ std::unique_ptr<WebV8ValueConverter> converter =
+ Platform::Current()->CreateWebV8ValueConverter();
+ converter->SetDateAllowed(true);
+ converter->SetRegExpAllowed(true);
+
+ std::move(callback).Run(
+ GetJavaScriptExecutionResult(result, frame_, converter.get()));
+ } else {
+ std::move(callback).Run({});
+ }
+}
+
+void LocalFrameMojoHandler::JavaScriptExecuteRequestInIsolatedWorld(
+ const String& javascript,
+ bool wants_result,
+ int32_t world_id,
+ JavaScriptExecuteRequestInIsolatedWorldCallback callback) {
+ TRACE_EVENT_INSTANT0("test_tracing",
+ "JavaScriptExecuteRequestInIsolatedWorld",
+ TRACE_EVENT_SCOPE_THREAD);
+
+ if (world_id <= DOMWrapperWorld::kMainWorldId ||
+ world_id > DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit) {
+ // Returns if the world_id is not valid. world_id is passed as a plain int
+ // over IPC and needs to be verified here, in the IPC endpoint.
+ std::move(callback).Run(base::Value());
+ mojo::ReportBadMessage(kInvalidWorldID);
+ return;
+ }
+
+ v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
+ scoped_refptr<DOMWrapperWorld> isolated_world =
+ DOMWrapperWorld::EnsureIsolatedWorld(ToIsolate(frame_), world_id);
+ ScriptSourceCode source_code = ScriptSourceCode(javascript);
+ HeapVector<ScriptSourceCode> sources;
+ sources.Append(&source_code, 1);
+ auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
+ DomWindow(), std::move(isolated_world), sources, false /* user_gesture */,
+ MakeGarbageCollected<JavaScriptIsolatedWorldRequest>(
+ frame_, wants_result, std::move(callback)));
+ executor->Run();
+}
+
+#if defined(OS_MAC)
+void LocalFrameMojoHandler::GetCharacterIndexAtPoint(const gfx::Point& point) {
+ frame_->GetCharacterIndexAtPoint(point);
+}
+
+void LocalFrameMojoHandler::GetFirstRectForRange(const gfx::Range& range) {
+ gfx::Rect rect;
+ WebLocalFrameClient* client = WebLocalFrameImpl::FromFrame(frame_)->Client();
+ if (!client)
+ return;
+
+ if (!client->GetCaretBoundsFromFocusedPlugin(rect)) {
+ // When request range is invalid we will try to obtain it from current
+ // frame selection. The fallback value will be 0.
+ uint32_t start = range.IsValid() ? range.start()
+ : GetCurrentCursorPositionInFrame(frame_);
+
+ WebLocalFrameImpl::FromFrame(frame_)->FirstRectForCharacterRange(
+ start, range.length(), rect);
+ }
+
+ TextInputHost().GotFirstRectForRange(rect);
+}
+
+void LocalFrameMojoHandler::GetStringForRange(
+ const gfx::Range& range,
+ GetStringForRangeCallback callback) {
+ gfx::Point baseline_point;
+ ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
+ NSAttributedString* string = SubstringUtil::AttributedSubstringInRange(
+ frame_, range.start(), range.length(), &baseline_point);
+ if (string)
+ attributed_string = ui::mojom::blink::AttributedString::From(string);
+
+ std::move(callback).Run(std::move(attributed_string), baseline_point);
+}
+#endif
+
+void LocalFrameMojoHandler::BindReportingObserver(
+ mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) {
+ ReportingContext::From(DomWindow())->Bind(std::move(receiver));
+}
+
+void LocalFrameMojoHandler::UpdateOpener(
+ const absl::optional<blink::FrameToken>& opener_frame_token) {
+ if (auto* web_frame = WebFrame::FromCoreFrame(frame_)) {
+ Frame* opener_frame = nullptr;
+ if (opener_frame_token)
+ opener_frame = Frame::ResolveFrame(opener_frame_token.value());
+ frame_->SetOpenerDoNotNotify(opener_frame);
+ }
+}
+
+void LocalFrameMojoHandler::GetSavableResourceLinks(
+ GetSavableResourceLinksCallback callback) {
+ Vector<KURL> resources_list;
+ Vector<mojom::blink::SavableSubframePtr> subframes;
+ SavableResources::Result result(&resources_list, &subframes);
+
+ if (!SavableResources::GetSavableResourceLinksForFrame(frame_, &result)) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ auto referrer = mojom::blink::Referrer::New(GetDocument()->Url(),
+ DomWindow()->GetReferrerPolicy());
+
+ auto reply = mojom::blink::GetSavableResourceLinksReply::New();
+ reply->resources_list = std::move(resources_list);
+ reply->referrer = std::move(referrer);
+ reply->subframes = std::move(subframes);
+
+ std::move(callback).Run(std::move(reply));
+}
+
+void LocalFrameMojoHandler::MixedContentFound(
+ const KURL& main_resource_url,
+ const KURL& mixed_content_url,
+ mojom::blink::RequestContextType request_context,
+ bool was_allowed,
+ const KURL& url_before_redirects,
+ bool had_redirect,
+ network::mojom::blink::SourceLocationPtr source_location) {
+ std::unique_ptr<SourceLocation> source;
+ if (source_location) {
+ source = std::make_unique<SourceLocation>(source_location->url,
+ source_location->line,
+ source_location->column, nullptr);
+ }
+ MixedContentChecker::MixedContentFound(
+ frame_, main_resource_url, mixed_content_url, request_context,
+ was_allowed, url_before_redirects, had_redirect, std::move(source));
+}
+
+void LocalFrameMojoHandler::BindDevToolsAgent(
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host,
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver) {
+ DCHECK(frame_->Client());
+ frame_->Client()->BindDevToolsAgent(std::move(host), std::move(receiver));
+}
+
+#if defined(OS_ANDROID)
+void LocalFrameMojoHandler::ExtractSmartClipData(
+ const gfx::Rect& rect,
+ ExtractSmartClipDataCallback callback) {
+ String clip_text;
+ String clip_html;
+ gfx::Rect clip_rect;
+ frame_->ExtractSmartClipDataInternal(rect, clip_text, clip_html, clip_rect);
+ std::move(callback).Run(clip_text.IsNull() ? g_empty_string : clip_text,
+ clip_html.IsNull() ? g_empty_string : clip_html,
+ clip_rect);
+}
+#endif // defined(OS_ANDROID)
+
+void LocalFrameMojoHandler::HandleRendererDebugURL(const KURL& url) {
+ DCHECK(IsRendererDebugURL(url));
+ if (url.ProtocolIs("javascript")) {
+ // JavaScript URLs should be sent to Blink for handling.
+ frame_->LoadJavaScriptURL(url);
+ } else {
+ // This is a Chrome Debug URL. Handle it.
+ HandleChromeDebugURL(url);
+ }
+
+ // The browser sets its status as loading before calling this IPC. Inform it
+ // that the load stopped if needed, while leaving the debug URL visible in the
+ // address bar.
+ if (!frame_->IsLoading())
+ frame_->Client()->DidStopLoading();
+}
+
+void LocalFrameMojoHandler::GetCanonicalUrlForSharing(
+ GetCanonicalUrlForSharingCallback callback) {
+ KURL canonical_url;
+ HTMLLinkElement* link_element = GetDocument()->LinkCanonical();
+ if (link_element)
+ canonical_url = link_element->Href();
+ std::move(callback).Run(canonical_url.IsNull()
+ ? absl::nullopt
+ : absl::make_optional(canonical_url));
+}
+
+void LocalFrameMojoHandler::AnimateDoubleTapZoom(const gfx::Point& point,
+ const gfx::Rect& rect) {
+ frame_->GetPage()->GetChromeClient().AnimateDoubleTapZoom(point, rect);
+}
+
+void LocalFrameMojoHandler::SetScaleFactor(float scale_factor) {
+ frame_->SetScaleFactor(scale_factor);
+}
+
+void LocalFrameMojoHandler::ClosePage(
+ mojom::blink::LocalMainFrame::ClosePageCallback completion_callback) {
+ SECURITY_CHECK(frame_->IsMainFrame());
+
+ // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done.
+ VLOG(1) << "LocalFrame::ClosePage() URL = " << frame_->GetDocument()->Url();
+
+ // There are two ways to close a page:
+ //
+ // 1/ Via webview()->Close() that currently sets the WebView's delegate_ to
+ // NULL, and prevent any JavaScript dialogs in the onunload handler from
+ // appearing.
+ //
+ // 2/ Calling the FrameLoader's CloseURL method directly.
+ //
+ // TODO(creis): Having a single way to close that can run onunload is also
+ // useful for fixing http://b/issue?id=753080.
+
+ SubframeLoadingDisabler disabler(frame_->GetDocument());
+ // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document
+ // The ignore-opens-during-unload counter of a Document must be incremented
+ // when unloading itself.
+ IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
+ frame_->GetDocument());
+ frame_->Loader().DispatchUnloadEvent(nullptr, nullptr);
+
+ std::move(completion_callback).Run();
+}
+
+void LocalFrameMojoHandler::PluginActionAt(
+ const gfx::Point& location,
+ mojom::blink::PluginActionType action) {
+ SECURITY_CHECK(frame_->IsMainFrame());
+
+ // TODO(bokan): Location is probably in viewport coordinates
+ HitTestResult result =
+ HitTestResultForRootFramePos(frame_, PhysicalOffset(IntPoint(location)));
+ Node* node = result.InnerNode();
+ if (!IsA<HTMLObjectElement>(*node) && !IsA<HTMLEmbedElement>(*node))
+ return;
+
+ auto* embedded = DynamicTo<LayoutEmbeddedContent>(node->GetLayoutObject());
+ if (!embedded)
+ return;
+
+ WebPluginContainerImpl* plugin_view = embedded->Plugin();
+ if (!plugin_view)
+ return;
+
+ switch (action) {
+ case mojom::blink::PluginActionType::kRotate90Clockwise:
+ plugin_view->Plugin()->RotateView(WebPlugin::RotationType::k90Clockwise);
+ return;
+ case mojom::blink::PluginActionType::kRotate90Counterclockwise:
+ plugin_view->Plugin()->RotateView(
+ WebPlugin::RotationType::k90Counterclockwise);
+ return;
+ }
+ NOTREACHED();
+}
+
+void LocalFrameMojoHandler::SetInitialFocus(bool reverse) {
+ frame_->SetInitialFocus(reverse);
+}
+
+void LocalFrameMojoHandler::EnablePreferredSizeChangedMode() {
+ frame_->GetPage()->GetChromeClient().EnablePreferredSizeChangedMode();
+}
+
+void LocalFrameMojoHandler::ZoomToFindInPageRect(
+ const gfx::Rect& rect_in_root_frame) {
+ frame_->GetPage()->GetChromeClient().ZoomToFindInPageRect(rect_in_root_frame);
+}
+
+void LocalFrameMojoHandler::InstallCoopAccessMonitor(
+ network::mojom::blink::CoopAccessReportType report_type,
+ const FrameToken& accessed_window,
+ mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter>
+ reporter,
+ bool endpoint_defined,
+ const WTF::String& reported_window_url) {
+ blink::Frame* accessed_frame = Frame::ResolveFrame(accessed_window);
+ // The Frame might have been deleted during the cross-process communication.
+ if (!accessed_frame)
+ return;
+
+ accessed_frame->DomWindow()->InstallCoopAccessMonitor(
+ report_type, frame_, std::move(reporter), endpoint_defined,
+ std::move(reported_window_url));
+}
+
+void LocalFrameMojoHandler::OnPortalActivated(
+ const PortalToken& portal_token,
+ mojo::PendingAssociatedRemote<mojom::blink::Portal> portal,
+ mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client,
+ BlinkTransferableMessage data,
+ uint64_t trace_id,
+ OnPortalActivatedCallback callback) {
+ DCHECK(frame_->GetDocument());
+ LocalDOMWindow* dom_window = frame_->DomWindow();
+ PaintTiming::From(*frame_->GetDocument()).OnPortalActivate();
+
+ TRACE_EVENT_WITH_FLOW0("navigation", "LocalFrame::OnPortalActivated",
+ TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN);
+
+ DOMWindowPortalHost::portalHost(*dom_window)->OnPortalActivated();
+ frame_->GetPage()->SetInsidePortal(false);
+
+ DCHECK(!data.locked_agent_cluster_id)
+ << "portal activation is always cross-agent-cluster and should be "
+ "diagnosed early";
+ MessagePortArray* ports =
+ MessagePort::EntanglePorts(*dom_window, std::move(data.ports));
+
+ PortalActivateEvent* event = PortalActivateEvent::Create(
+ frame_, portal_token, std::move(portal), std::move(portal_client),
+ std::move(data.message), ports, std::move(callback));
+
+ ThreadDebugger* debugger = MainThreadDebugger::Instance();
+ if (debugger)
+ debugger->ExternalAsyncTaskStarted(data.sender_stack_trace_id);
+ dom_window->DispatchEvent(*event);
+ if (debugger)
+ debugger->ExternalAsyncTaskFinished(data.sender_stack_trace_id);
+ event->ExpireAdoptionLifetime();
+}
+
+void LocalFrameMojoHandler::ForwardMessageFromHost(
+ BlinkTransferableMessage message,
+ const scoped_refptr<const SecurityOrigin>& source_origin) {
+ PortalHost::From(*frame_->DomWindow())
+ .ReceiveMessage(std::move(message), source_origin);
+}
+
+void LocalFrameMojoHandler::UpdateBrowserControlsState(
+ cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
+ bool animate) {
+ DCHECK(frame_->IsMainFrame());
+ TRACE_EVENT2("renderer", "LocalFrame::UpdateBrowserControlsState",
+ "Constraint", static_cast<int>(constraints), "Current",
+ static_cast<int>(current));
+ TRACE_EVENT_INSTANT1("renderer", "is_animated", TRACE_EVENT_SCOPE_THREAD,
+ "animated", animate);
+
+ frame_->GetWidgetForLocalRoot()->UpdateBrowserControlsState(constraints,
+ current, animate);
+}
+
+void LocalFrameMojoHandler::DispatchBeforeUnload(
+ bool is_reload,
+ mojom::blink::LocalFrame::BeforeUnloadCallback callback) {
+ BeforeUnload(is_reload, std::move(callback));
+}
+
+void LocalFrameMojoHandler::RequestFullscreenVideoElement() {
+ // Find the first video element of the frame.
+ for (auto* child = frame_->GetDocument()->documentElement(); child;
+ child = Traversal<HTMLElement>::Next(*child)) {
+ if (IsA<HTMLVideoElement>(child)) {
+ // This is always initiated from browser side (which should require the
+ // user interacting with ui) which suffices for a user gesture even though
+ // there will have been no input to the frame at this point.
+ frame_->NotifyUserActivation(
+ mojom::blink::UserActivationNotificationType::kInteraction);
+
+ Fullscreen::RequestFullscreen(*child);
+ return;
+ }
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
new file mode 100644
index 00000000000..1efce654465
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -0,0 +1,297 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_MOJO_HANDLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_MOJO_HANDLER_H_
+
+#include "build/build_config.h"
+#include "services/device/public/mojom/device_posture_provider.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/public/mojom/media/fullscreen_video_element.mojom-blink.h"
+#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+
+#if defined(OS_MAC)
+#include "third_party/blink/public/mojom/input/text_input_host.mojom-blink.h"
+#endif
+
+namespace blink {
+
+class Document;
+class LocalDOMWindow;
+class LocalFrame;
+class Page;
+
+// LocalFrameMojoHandler is a part of LocalFrame, and is responsible for having
+// Mojo-related stuff in order to avoid including full mojom headers from
+// local_frame.h.
+//
+// This class should have:
+// - Mojo receivers
+// - Mojo remotes
+// - Data members of which types are defined by mojom.
+//
+// A single LocalFrame instance owns a single LocalFrameMojoHandler instance.
+class LocalFrameMojoHandler
+ : public GarbageCollected<LocalFrameMojoHandler>,
+ public mojom::blink::LocalFrame,
+ public mojom::blink::LocalMainFrame,
+ public mojom::blink::HighPriorityLocalFrame,
+ public mojom::blink::FullscreenVideoElementHandler,
+ public device::mojom::blink::DevicePostureProviderClient {
+ public:
+ explicit LocalFrameMojoHandler(blink::LocalFrame& frame);
+ void Trace(Visitor* visitor) const;
+
+ void WasAttachedAsLocalMainFrame();
+ void DidDetachFrame();
+
+ void ClosePageForTesting();
+
+ mojom::blink::LocalFrameHost& LocalFrameHostRemote() const {
+ return *local_frame_host_remote_.get();
+ }
+
+ mojom::blink::ReportingServiceProxy* ReportingService();
+ mojom::blink::BackForwardCacheControllerHost&
+ BackForwardCacheControllerHostRemote();
+
+#if defined(OS_MAC)
+ mojom::blink::TextInputHost& TextInputHost();
+ void ResetTextInputHostForTesting();
+ void RebindTextInputHostForTesting();
+#endif
+
+ device::mojom::blink::DevicePostureType GetDevicePosture();
+
+ private:
+ Page* GetPage() const;
+ LocalDOMWindow* DomWindow() const;
+ Document* GetDocument() const;
+
+ void BindToLocalFrameReceiver(
+ mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver);
+ void BindToMainFrameReceiver(
+ mojo::PendingAssociatedReceiver<mojom::blink::LocalMainFrame> receiver);
+ void BindToHighPriorityReceiver(
+ mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver);
+ void BindFullscreenVideoElementReceiver(
+ mojo::PendingAssociatedReceiver<
+ mojom::blink::FullscreenVideoElementHandler> receiver);
+
+ // blink::mojom::LocalFrame overrides:
+ void GetTextSurroundingSelection(
+ uint32_t max_length,
+ GetTextSurroundingSelectionCallback callback) final;
+ void SendInterventionReport(const String& id, const String& message) final;
+ void SetFrameOwnerProperties(
+ mojom::blink::FrameOwnerPropertiesPtr properties) final;
+ void NotifyUserActivation(
+ mojom::blink::UserActivationNotificationType notification_type) final;
+ void NotifyVirtualKeyboardOverlayRect(const gfx::Rect& keyboard_rect) final;
+ void AddMessageToConsole(mojom::blink::ConsoleMessageLevel level,
+ const WTF::String& message,
+ bool discard_duplicates) final;
+ void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
+ void SwapInImmediately() final;
+ void CheckCompleted() final;
+ void StopLoading() final;
+ void Collapse(bool collapsed) final;
+ void EnableViewSourceMode() final;
+ void Focus() final;
+ void ClearFocusedElement() final;
+ void GetResourceSnapshotForWebBundle(
+ mojo::PendingReceiver<
+ data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver)
+ final;
+ void CopyImageAt(const gfx::Point& window_point) final;
+ void SaveImageAt(const gfx::Point& window_point) final;
+ void ReportBlinkFeatureUsage(const Vector<mojom::blink::WebFeature>&) final;
+ void RenderFallbackContent() final;
+ void RenderFallbackContentWithResourceTiming(
+ mojom::blink::ResourceTimingInfoPtr timing,
+ const String& server_timing_values) final;
+ void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) final;
+ void MediaPlayerActionAt(
+ const gfx::Point& window_point,
+ blink::mojom::blink::MediaPlayerActionPtr action) final;
+ void AdvanceFocusInFrame(
+ mojom::blink::FocusType focus_type,
+ const absl::optional<RemoteFrameToken>& source_frame_token) final;
+ void AdvanceFocusInForm(mojom::blink::FocusType focus_type) final;
+ void ReportContentSecurityPolicyViolation(
+ network::mojom::blink::CSPViolationPtr csp_violation) final;
+ // Updates the snapshotted policy attributes (sandbox flags and permissions
+ // policy container policy) in the frame's FrameOwner. This is used when this
+ // frame's parent is in another process and it dynamically updates this
+ // frame's sandbox flags or container policy. The new policy won't take effect
+ // until the next navigation.
+ void DidUpdateFramePolicy(const FramePolicy& frame_policy) final;
+ void OnScreensChange() final;
+ void PostMessageEvent(
+ const absl::optional<RemoteFrameToken>& source_frame_token,
+ const String& source_origin,
+ const String& target_origin,
+ BlinkTransferableMessage message) final;
+ void JavaScriptMethodExecuteRequest(
+ const String& object_name,
+ const String& method_name,
+ base::Value arguments,
+ bool wants_result,
+ JavaScriptMethodExecuteRequestCallback callback) final;
+ void JavaScriptExecuteRequest(
+ const String& javascript,
+ bool wants_result,
+ JavaScriptExecuteRequestCallback callback) final;
+ void JavaScriptExecuteRequestForTests(
+ const String& javascript,
+ bool wants_result,
+ bool has_user_gesture,
+ int32_t world_id,
+ JavaScriptExecuteRequestForTestsCallback callback) final;
+ void JavaScriptExecuteRequestInIsolatedWorld(
+ const String& javascript,
+ bool wants_result,
+ int32_t world_id,
+ JavaScriptExecuteRequestInIsolatedWorldCallback callback) final;
+#if defined(OS_MAC)
+ void GetCharacterIndexAtPoint(const gfx::Point& point) final;
+ void GetFirstRectForRange(const gfx::Range& range) final;
+ void GetStringForRange(const gfx::Range& range,
+ GetStringForRangeCallback callback) final;
+#endif
+ void BindReportingObserver(
+ mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) final;
+ void UpdateOpener(
+ const absl::optional<blink::FrameToken>& opener_routing_id) final;
+ void GetSavableResourceLinks(GetSavableResourceLinksCallback callback) final;
+ void MixedContentFound(
+ const KURL& main_resource_url,
+ const KURL& mixed_content_url,
+ mojom::blink::RequestContextType request_context,
+ bool was_allowed,
+ const KURL& url_before_redirects,
+ bool had_redirect,
+ network::mojom::blink::SourceLocationPtr source_location) final;
+ void BindDevToolsAgent(
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host,
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver)
+ final;
+#if defined(OS_ANDROID)
+ void ExtractSmartClipData(const gfx::Rect& rect,
+ ExtractSmartClipDataCallback callback) final;
+#endif
+ void HandleRendererDebugURL(const KURL& url) final;
+ void GetCanonicalUrlForSharing(
+ GetCanonicalUrlForSharingCallback callback) final;
+
+ // blink::mojom::LocalMainFrame overrides:
+ void AnimateDoubleTapZoom(const gfx::Point& point,
+ const gfx::Rect& rect) override;
+ void SetScaleFactor(float scale) override;
+ void ClosePage(
+ mojom::blink::LocalMainFrame::ClosePageCallback callback) override;
+ void PluginActionAt(const gfx::Point& location,
+ mojom::blink::PluginActionType action) override;
+ void SetInitialFocus(bool reverse) override;
+ void EnablePreferredSizeChangedMode() override;
+ void ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) override;
+ void InstallCoopAccessMonitor(
+ network::mojom::blink::CoopAccessReportType report_type,
+ const FrameToken& accessed_window,
+ mojo::PendingRemote<
+ network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter,
+ bool endpoint_defined,
+ const WTF::String& reported_window_url) final;
+ void OnPortalActivated(
+ const PortalToken& portal_token,
+ mojo::PendingAssociatedRemote<mojom::blink::Portal> portal,
+ mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client,
+ BlinkTransferableMessage data,
+ uint64_t trace_id,
+ OnPortalActivatedCallback callback) final;
+ void ForwardMessageFromHost(
+ BlinkTransferableMessage message,
+ const scoped_refptr<const SecurityOrigin>& source_origin) final;
+ void UpdateBrowserControlsState(cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
+ bool animate) override;
+
+ // mojom::blink::HighPriorityLocalFrame implementation:
+ void DispatchBeforeUnload(
+ bool is_reload,
+ mojom::blink::LocalFrame::BeforeUnloadCallback callback) final;
+
+ // mojom::FullscreenVideoElementHandler implementation:
+ void RequestFullscreenVideoElement() final;
+
+ // DevicePostureServiceClient implementation:
+ void OnPostureChanged(device::mojom::blink::DevicePostureType posture) final;
+
+ Member<blink::LocalFrame> frame_;
+
+ HeapMojoAssociatedRemote<mojom::blink::BackForwardCacheControllerHost>
+ back_forward_cache_controller_host_remote_{nullptr};
+
+#if defined(OS_MAC)
+ HeapMojoRemote<mojom::blink::TextInputHost> text_input_host_{nullptr};
+#endif
+
+ HeapMojoRemote<mojom::blink::ReportingServiceProxy> reporting_service_{
+ nullptr};
+
+ HeapMojoRemote<device::mojom::blink::DevicePostureProvider>
+ device_posture_provider_service_{nullptr};
+
+ HeapMojoAssociatedRemote<mojom::blink::LocalFrameHost>
+ local_frame_host_remote_{nullptr};
+
+ // LocalFrameMojoHandler can be reused by multiple ExecutionContext.
+ HeapMojoAssociatedReceiver<mojom::blink::LocalFrame, LocalFrameMojoHandler>
+ local_frame_receiver_{this, nullptr};
+ // LocalFrameMojoHandler can be reused by multiple ExecutionContext.
+ HeapMojoAssociatedReceiver<mojom::blink::LocalMainFrame,
+ LocalFrameMojoHandler>
+ main_frame_receiver_{this, nullptr};
+ // LocalFrameMojoHandler can be reused by multiple ExecutionContext.
+ HeapMojoReceiver<mojom::blink::HighPriorityLocalFrame, LocalFrameMojoHandler>
+ high_priority_frame_receiver_{this, nullptr};
+ // LocalFrameMojoHandler can be reused by multiple ExecutionContext.
+ HeapMojoAssociatedReceiver<mojom::blink::FullscreenVideoElementHandler,
+ LocalFrameMojoHandler>
+ fullscreen_video_receiver_{this, nullptr};
+
+ // LocalFrameMojoHandler can be reused by multiple ExecutionContext.
+ HeapMojoReceiver<device::mojom::blink::DevicePostureProviderClient,
+ LocalFrameMojoHandler>
+ device_posture_receiver_{this, nullptr};
+
+ device::mojom::blink::DevicePostureType current_device_posture_ =
+ device::mojom::blink::DevicePostureType::kContinuous;
+};
+
+class ActiveURLMessageFilter : public mojo::MessageFilter {
+ public:
+ explicit ActiveURLMessageFilter(LocalFrame* local_frame)
+ : local_frame_(local_frame) {}
+
+ ~ActiveURLMessageFilter() override;
+
+ // mojo::MessageFilter overrides.
+ bool WillDispatch(mojo::Message* message) override;
+ void DidDispatchOrReject(mojo::Message* message, bool accepted) override;
+
+ private:
+ WeakPersistent<LocalFrame> local_frame_;
+ bool debug_url_set_ = false;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_MOJO_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc
index da509e09162..aa958d76579 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc
@@ -254,14 +254,12 @@ TEST_F(LocalFrameTest, CharacterIndexAtPointWithPinchZoom) {
Page* page = web_view_helper.GetWebView()->GetPage();
LocalFrame* main_frame = DynamicTo<LocalFrame>(page->MainFrame());
- main_frame->text_input_host_.reset();
+ main_frame->ResetTextInputHostForTesting();
base::RunLoop run_loop;
TestTextInputHostWaiter waiter;
waiter.Init(run_loop.QuitClosure(), main_frame->GetBrowserInterfaceBroker());
- main_frame->GetBrowserInterfaceBroker().GetInterface(
- main_frame->text_input_host_.BindNewPipeAndPassReceiver(
- main_frame->GetTaskRunner(blink::TaskType::kInternalDefault)));
+ main_frame->RebindTextInputHostForTesting();
// Since we're zoomed in to 2X, each char of Ahem is 20px wide/tall in
// viewport space. We expect to hit the fifth char on the first line.
main_frame->GetCharacterIndexAtPoint(gfx::Point(100, 15));
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc
index 8e83b077085..6d6891eb2dc 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc
@@ -11,14 +11,36 @@
#include "base/rand_util.h"
#include "base/time/default_tick_clock.h"
#include "cc/metrics/begin_main_frame_metrics.h"
+#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+namespace {
+
+inline base::HistogramBase::Sample ToSample(int64_t value) {
+ return base::saturated_cast<base::HistogramBase::Sample>(value);
+}
+
+inline int64_t ApplyBucket(int64_t value) {
+ return ukm::GetExponentialBucketMinForCounts1000(value);
+}
+
+} // namespace
+
namespace blink {
+int64_t LocalFrameUkmAggregator::ApplyBucketIfNecessary(int64_t value,
+ unsigned metric_id) {
+ if (metric_id >= kIntersectionObservationInternalCount &&
+ metric_id <= kIntersectionObservationJavascriptCount) {
+ return ApplyBucket(value);
+ }
+ return value;
+}
+
LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer(
scoped_refptr<LocalFrameUkmAggregator> aggregator,
size_t metric_index,
@@ -40,13 +62,43 @@ LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer(
LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::
~ScopedUkmHierarchicalTimer() {
if (aggregator_ && base::TimeTicks::IsHighResolution()) {
- aggregator_->RecordSample(metric_index_, start_time_, clock_->NowTicks());
+ aggregator_->RecordTimerSample(metric_index_, start_time_,
+ clock_->NowTicks());
+ }
+}
+
+LocalFrameUkmAggregator::IterativeTimer::IterativeTimer(
+ LocalFrameUkmAggregator& aggregator)
+ : aggregator_(base::TimeTicks::IsHighResolution() ? &aggregator : nullptr) {
+}
+
+LocalFrameUkmAggregator::IterativeTimer::~IterativeTimer() {
+ if (aggregator_.get() && metric_index_ != -1)
+ Record();
+}
+
+void LocalFrameUkmAggregator::IterativeTimer::StartInterval(
+ int64_t metric_index) {
+ if (aggregator_.get() && metric_index != metric_index_) {
+ Record();
+ metric_index_ = metric_index;
+ }
+}
+
+void LocalFrameUkmAggregator::IterativeTimer::Record() {
+ DCHECK(aggregator_.get());
+ base::TimeTicks now = aggregator_->GetClock()->NowTicks();
+ if (metric_index_ != -1) {
+ aggregator_->RecordTimerSample(base::saturated_cast<size_t>(metric_index_),
+ start_time_, now);
}
+ metric_index_ = -1;
+ start_time_ = now;
}
void LocalFrameUkmAggregator::AbsoluteMetricRecord::reset() {
- interval_duration = base::TimeDelta();
- main_frame_duration = base::TimeDelta();
+ interval_count = 0;
+ main_frame_count = 0;
}
LocalFrameUkmAggregator::LocalFrameUkmAggregator(int64_t source_id,
@@ -57,9 +109,9 @@ LocalFrameUkmAggregator::LocalFrameUkmAggregator(int64_t source_id,
event_name_("Blink.UpdateTime") {
// All of these are assumed to have one entry per sub-metric.
DCHECK_EQ(base::size(absolute_metric_records_), metrics_data().size());
- DCHECK_EQ(base::size(current_sample_.sub_metrics_durations),
+ DCHECK_EQ(base::size(current_sample_.sub_metrics_counts),
metrics_data().size());
- DCHECK_EQ(base::size(current_sample_.sub_main_frame_durations),
+ DCHECK_EQ(base::size(current_sample_.sub_main_frame_counts),
metrics_data().size());
// Record average and worst case for the primary metric.
@@ -67,12 +119,12 @@ LocalFrameUkmAggregator::LocalFrameUkmAggregator(int64_t source_id,
// Define the UMA for the primary metric.
primary_metric_.pre_fcp_uma_counter = std::make_unique<CustomCountHistogram>(
- "Blink.MainFrame.UpdateTime.PreFCP", 0, 10000000, 50);
+ "Blink.MainFrame.UpdateTime.PreFCP", 1, 10000000, 50);
primary_metric_.post_fcp_uma_counter = std::make_unique<CustomCountHistogram>(
- "Blink.MainFrame.UpdateTime.PostFCP", 0, 10000000, 50);
+ "Blink.MainFrame.UpdateTime.PostFCP", 1, 10000000, 50);
primary_metric_.uma_aggregate_counter =
std::make_unique<CustomCountHistogram>(
- "Blink.MainFrame.UpdateTime.AggregatedPreFCP", 0, 10000000, 50);
+ "Blink.MainFrame.UpdateTime.AggregatedPreFCP", 1, 10000000, 50);
// Set up the substrings to create the UMA names
const char* const uma_preamble = "Blink.";
@@ -90,7 +142,7 @@ LocalFrameUkmAggregator::LocalFrameUkmAggregator(int64_t source_id,
// They have an associated UMA too that we own and allocate here.
auto& absolute_record = absolute_metric_records_[metric_index];
absolute_record.reset();
- absolute_record.pre_fcp_aggregate = base::TimeDelta();
+ absolute_record.pre_fcp_aggregate = 0;
if (metric_data.has_uma) {
StringBuilder uma_name;
uma_name.Append(uma_preamble);
@@ -101,19 +153,19 @@ LocalFrameUkmAggregator::LocalFrameUkmAggregator(int64_t source_id,
pre_fcp_uma_name.Append(uma_prefcp_postscript);
absolute_record.pre_fcp_uma_counter =
std::make_unique<CustomCountHistogram>(
- pre_fcp_uma_name.ToString().Utf8().c_str(), 0, 10000000, 50);
+ pre_fcp_uma_name.ToString().Utf8().c_str(), 1, 10000000, 50);
StringBuilder post_fcp_uma_name;
post_fcp_uma_name.Append(uma_name);
post_fcp_uma_name.Append(uma_postfcp_postscript);
absolute_record.post_fcp_uma_counter =
std::make_unique<CustomCountHistogram>(
- post_fcp_uma_name.ToString().Utf8().c_str(), 0, 10000000, 50);
+ post_fcp_uma_name.ToString().Utf8().c_str(), 1, 10000000, 50);
StringBuilder aggregated_uma_name;
aggregated_uma_name.Append(uma_name);
aggregated_uma_name.Append(uma_pre_fcp_aggregated_postscript);
absolute_record.uma_aggregate_counter =
std::make_unique<CustomCountHistogram>(
- aggregated_uma_name.ToString().Utf8().c_str(), 0, 10000000, 50);
+ aggregated_uma_name.ToString().Utf8().c_str(), 1, 10000000, 50);
}
metric_index++;
@@ -144,37 +196,37 @@ LocalFrameUkmAggregator::GetBeginMainFrameMetrics() {
// metrics and would result in double counting.
std::unique_ptr<cc::BeginMainFrameMetrics> metrics_data =
std::make_unique<cc::BeginMainFrameMetrics>();
- metrics_data->handle_input_events =
+ metrics_data->handle_input_events = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(
MetricId::kHandleInputEvents)]
- .main_frame_duration;
- metrics_data->animate =
+ .main_frame_count);
+ metrics_data->animate = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(MetricId::kAnimate)]
- .main_frame_duration;
- metrics_data->style_update =
+ .main_frame_count);
+ metrics_data->style_update = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(MetricId::kStyle)]
- .main_frame_duration;
- metrics_data->layout_update =
+ .main_frame_count);
+ metrics_data->layout_update = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(MetricId::kLayout)]
- .main_frame_duration;
- metrics_data->prepaint =
+ .main_frame_count);
+ metrics_data->prepaint = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(MetricId::kPrePaint)]
- .main_frame_duration;
- metrics_data->compositing_assignments =
+ .main_frame_count);
+ metrics_data->compositing_assignments = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(
MetricId::kCompositingAssignments)]
- .main_frame_duration;
- metrics_data->compositing_inputs =
+ .main_frame_count);
+ metrics_data->compositing_inputs = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(
MetricId::kCompositingInputs)]
- .main_frame_duration;
- metrics_data->paint =
+ .main_frame_count);
+ metrics_data->paint = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(MetricId::kPaint)]
- .main_frame_duration;
- metrics_data->composite_commit =
+ .main_frame_count);
+ metrics_data->composite_commit = base::TimeDelta::FromMicroseconds(
absolute_metric_records_[static_cast<unsigned>(
MetricId::kCompositingCommit)]
- .main_frame_duration;
+ .main_frame_count);
metrics_data->should_measure_smoothness =
(fcp_state_ >= kThisFrameReachedFCP);
return metrics_data;
@@ -197,34 +249,37 @@ void LocalFrameUkmAggregator::DidReachFirstContentfulPaint(
fcp_state_ = kThisFrameReachedFCP;
}
-void LocalFrameUkmAggregator::RecordSample(size_t metric_index,
- base::TimeTicks start,
- base::TimeTicks end) {
+void LocalFrameUkmAggregator::RecordTimerSample(size_t metric_index,
+ base::TimeTicks start,
+ base::TimeTicks end) {
+ RecordCountSample(metric_index, (end - start).InMicroseconds());
+}
+
+void LocalFrameUkmAggregator::RecordCountSample(size_t metric_index,
+ int64_t count) {
// Always use RecordForcedLayoutSample for the kForcedStyleAndLayout
// metric id.
DCHECK_NE(metric_index, static_cast<size_t>(kForcedStyleAndLayout));
- base::TimeDelta duration = end - start;
bool is_pre_fcp = (fcp_state_ != kHavePassedFCP);
// Accumulate for UKM and record the UMA
DCHECK_LT(metric_index, base::size(absolute_metric_records_));
auto& record = absolute_metric_records_[metric_index];
- record.interval_duration += duration;
+ record.interval_count += count;
if (in_main_frame_update_)
- record.main_frame_duration += duration;
+ record.main_frame_count += count;
if (is_pre_fcp)
- record.pre_fcp_aggregate += duration;
+ record.pre_fcp_aggregate += count;
// Record the UMA
// ForcedStyleAndLayout happen so frequently on some pages that we overflow
// the signed 32 counter for number of events in a 30 minute period. So
// randomly record with probability 1/100.
if (record.pre_fcp_uma_counter) {
- if (is_pre_fcp) {
- record.pre_fcp_uma_counter->CountMicroseconds(duration);
- } else {
- record.post_fcp_uma_counter->CountMicroseconds(duration);
- }
+ if (is_pre_fcp)
+ record.pre_fcp_uma_counter->Count(ToSample(count));
+ else
+ record.post_fcp_uma_counter->Count(ToSample(count));
}
}
@@ -232,7 +287,7 @@ void LocalFrameUkmAggregator::RecordForcedLayoutSample(
DocumentUpdateReason reason,
base::TimeTicks start,
base::TimeTicks end) {
- base::TimeDelta duration = end - start;
+ int64_t count = (end - start).InMicroseconds();
bool is_pre_fcp = (fcp_state_ != kHavePassedFCP);
// Accumulate for UKM always, but only record the UMA for a subset of cases to
@@ -248,17 +303,17 @@ void LocalFrameUkmAggregator::RecordForcedLayoutSample(
auto& record =
absolute_metric_records_[static_cast<size_t>(kForcedStyleAndLayout)];
- record.interval_duration += duration;
+ record.interval_count += count;
if (in_main_frame_update_)
- record.main_frame_duration += duration;
+ record.main_frame_count += count;
if (is_pre_fcp)
- record.pre_fcp_aggregate += duration;
+ record.pre_fcp_aggregate += count;
if (should_report_uma_this_frame) {
if (is_pre_fcp)
- record.pre_fcp_uma_counter->CountMicroseconds(duration);
+ record.pre_fcp_uma_counter->Count(ToSample(count));
else
- record.post_fcp_uma_counter->CountMicroseconds(duration);
+ record.post_fcp_uma_counter->Count(ToSample(count));
}
// Record a variety of DocumentUpdateReasons as distinct metrics
@@ -322,16 +377,16 @@ void LocalFrameUkmAggregator::RecordForcedLayoutSample(
if (sub_metric != kCount) {
auto& sub_record =
absolute_metric_records_[static_cast<size_t>(sub_metric)];
- sub_record.interval_duration += duration;
+ sub_record.interval_count += count;
if (in_main_frame_update_)
- sub_record.main_frame_duration += duration;
+ sub_record.main_frame_count += count;
if (is_pre_fcp)
- sub_record.pre_fcp_aggregate += duration;
+ sub_record.pre_fcp_aggregate += count;
if (should_report_uma_this_frame) {
if (is_pre_fcp)
- sub_record.pre_fcp_uma_counter->CountMicroseconds(duration);
+ sub_record.pre_fcp_uma_counter->Count(ToSample(count));
else
- sub_record.post_fcp_uma_counter->CountMicroseconds(duration);
+ sub_record.post_fcp_uma_counter->Count(ToSample(count));
}
}
}
@@ -348,10 +403,10 @@ void LocalFrameUkmAggregator::RecordImplCompositorSample(
// all time to the compositor commit so as to not imply that wait time was
// consumed.
if (started == base::TimeTicks()) {
- RecordSample(kImplCompositorCommit, requested, completed);
+ RecordTimerSample(kImplCompositorCommit, requested, completed);
} else {
- RecordSample(kWaitForCommit, requested, started);
- RecordSample(kImplCompositorCommit, started, completed);
+ RecordTimerSample(kWaitForCommit, requested, started);
+ RecordTimerSample(kImplCompositorCommit, started, completed);
}
}
@@ -359,14 +414,14 @@ void LocalFrameUkmAggregator::RecordEndOfFrameMetrics(
base::TimeTicks start,
base::TimeTicks end,
cc::ActiveFrameSequenceTrackers trackers) {
- const base::TimeDelta duration = end - start;
+ const int64_t count = (end - start).InMicroseconds();
const bool have_valid_metrics =
// Any of the early outs in LocalFrameView::UpdateLifecyclePhases() will
// mean we are not in a main frame update. Recording is triggered higher
// in the stack, so we cannot know to avoid calling this method.
in_main_frame_update_ &&
// In tests it's possible to reach here with zero duration.
- (duration > base::TimeDelta());
+ (count > 0);
in_main_frame_update_ = false;
if (!have_valid_metrics) {
@@ -381,14 +436,14 @@ void LocalFrameUkmAggregator::RecordEndOfFrameMetrics(
// Record UMA
if (report_as_pre_fcp)
- primary_metric_.pre_fcp_uma_counter->CountMicroseconds(duration);
+ primary_metric_.pre_fcp_uma_counter->Count(ToSample(count));
else
- primary_metric_.post_fcp_uma_counter->CountMicroseconds(duration);
+ primary_metric_.post_fcp_uma_counter->Count(ToSample(count));
// Record primary time information
- primary_metric_.interval_duration = duration;
+ primary_metric_.interval_count = count;
if (report_as_pre_fcp)
- primary_metric_.pre_fcp_aggregate += duration;
+ primary_metric_.pre_fcp_aggregate += count;
UpdateEventTimeAndUpdateSampleIfNeeded(trackers);
@@ -430,68 +485,75 @@ void LocalFrameUkmAggregator::UpdateEventTimeAndUpdateSampleIfNeeded(
void LocalFrameUkmAggregator::UpdateSample(
cc::ActiveFrameSequenceTrackers trackers) {
- current_sample_.primary_metric_duration = primary_metric_.interval_duration;
+ current_sample_.primary_metric_count = primary_metric_.interval_count;
for (size_t i = 0; i < metrics_data().size(); ++i) {
- current_sample_.sub_metrics_durations[i] =
- absolute_metric_records_[i].interval_duration;
- current_sample_.sub_main_frame_durations[i] =
- absolute_metric_records_[i].main_frame_duration;
+ current_sample_.sub_metrics_counts[i] =
+ absolute_metric_records_[i].interval_count;
+ current_sample_.sub_main_frame_counts[i] =
+ absolute_metric_records_[i].main_frame_count;
}
current_sample_.trackers = trackers;
}
void LocalFrameUkmAggregator::ReportPreFCPEvent() {
-#define CASE_FOR_ID(name) \
- case k##name: \
- builder.Set##name(absolute_record.pre_fcp_aggregate.InMicroseconds()); \
- break
+#define RECORD_METRIC(name) \
+ { \
+ auto& absolute_record = absolute_metric_records_[k##name]; \
+ if (absolute_record.uma_aggregate_counter) { \
+ absolute_record.uma_aggregate_counter->Count( \
+ ToSample(absolute_record.pre_fcp_aggregate)); \
+ } \
+ builder.Set##name(ToSample(absolute_record.pre_fcp_aggregate)); \
+ }
+
+#define RECORD_BUCKETED_METRIC(name) \
+ { \
+ auto& absolute_record = absolute_metric_records_[k##name]; \
+ if (absolute_record.uma_aggregate_counter) { \
+ absolute_record.uma_aggregate_counter->Count( \
+ ToSample(absolute_record.pre_fcp_aggregate)); \
+ } \
+ builder.Set##name( \
+ ToSample(ApplyBucket(absolute_record.pre_fcp_aggregate))); \
+ }
ukm::builders::Blink_PageLoad builder(source_id_);
- builder.SetMainFrame(primary_metric_.pre_fcp_aggregate.InMicroseconds());
- primary_metric_.uma_aggregate_counter->CountMicroseconds(
- primary_metric_.pre_fcp_aggregate);
- for (size_t i = 0; i < metrics_data().size(); ++i) {
- auto& absolute_record = absolute_metric_records_[i];
- if (absolute_record.uma_aggregate_counter) {
- absolute_record.uma_aggregate_counter->CountMicroseconds(
- absolute_record.pre_fcp_aggregate);
- }
+ primary_metric_.uma_aggregate_counter->Count(
+ ToSample(primary_metric_.pre_fcp_aggregate));
+ builder.SetMainFrame(ToSample(primary_metric_.pre_fcp_aggregate));
+
+ RECORD_METRIC(CompositingAssignments);
+ RECORD_METRIC(CompositingCommit);
+ RECORD_METRIC(CompositingInputs);
+ RECORD_METRIC(ImplCompositorCommit);
+ RECORD_METRIC(IntersectionObservation);
+ RECORD_BUCKETED_METRIC(IntersectionObservationInternalCount);
+ RECORD_BUCKETED_METRIC(IntersectionObservationJavascriptCount);
+ RECORD_METRIC(Paint);
+ RECORD_METRIC(PrePaint);
+ RECORD_METRIC(Style);
+ RECORD_METRIC(Layout);
+ RECORD_METRIC(ForcedStyleAndLayout);
+ RECORD_METRIC(HandleInputEvents);
+ RECORD_METRIC(Animate);
+ RECORD_METRIC(UpdateLayers);
+ RECORD_METRIC(WaitForCommit);
+ RECORD_METRIC(DisplayLockIntersectionObserver);
+ RECORD_METRIC(JavascriptIntersectionObserver);
+ RECORD_METRIC(LazyLoadIntersectionObserver);
+ RECORD_METRIC(MediaIntersectionObserver);
+ RECORD_METRIC(AnchorElementMetricsIntersectionObserver);
+ RECORD_METRIC(UpdateViewportIntersection);
+ RECORD_METRIC(UserDrivenDocumentUpdate);
+ RECORD_METRIC(ServiceDocumentUpdate);
+ RECORD_METRIC(ContentDocumentUpdate);
+ RECORD_METRIC(ScrollDocumentUpdate);
+ RECORD_METRIC(HitTestDocumentUpdate);
+ RECORD_METRIC(JavascriptDocumentUpdate);
- switch (static_cast<MetricId>(i)) {
- CASE_FOR_ID(CompositingAssignments);
- CASE_FOR_ID(CompositingCommit);
- CASE_FOR_ID(CompositingInputs);
- CASE_FOR_ID(ImplCompositorCommit);
- CASE_FOR_ID(IntersectionObservation);
- CASE_FOR_ID(Paint);
- CASE_FOR_ID(PrePaint);
- CASE_FOR_ID(Style);
- CASE_FOR_ID(Layout);
- CASE_FOR_ID(ForcedStyleAndLayout);
- CASE_FOR_ID(HandleInputEvents);
- CASE_FOR_ID(Animate);
- CASE_FOR_ID(UpdateLayers);
- CASE_FOR_ID(WaitForCommit);
- CASE_FOR_ID(DisplayLockIntersectionObserver);
- CASE_FOR_ID(JavascriptIntersectionObserver);
- CASE_FOR_ID(LazyLoadIntersectionObserver);
- CASE_FOR_ID(MediaIntersectionObserver);
- CASE_FOR_ID(AnchorElementMetricsIntersectionObserver);
- CASE_FOR_ID(UpdateViewportIntersection);
- CASE_FOR_ID(UserDrivenDocumentUpdate);
- CASE_FOR_ID(ServiceDocumentUpdate);
- CASE_FOR_ID(ContentDocumentUpdate);
- CASE_FOR_ID(ScrollDocumentUpdate);
- CASE_FOR_ID(HitTestDocumentUpdate);
- CASE_FOR_ID(JavascriptDocumentUpdate);
- case kCount:
- case kMainFrame:
- NOTREACHED();
- break;
- }
- }
builder.Record(recorder_);
-#undef CASE_FOR_ID
+#undef RECORD_METRIC
+#undef RECORD_BUCKETED_METRIC
}
void LocalFrameUkmAggregator::ReportUpdateTimeEvent() {
@@ -499,56 +561,52 @@ void LocalFrameUkmAggregator::ReportUpdateTimeEvent() {
if (!frames_since_last_report_)
return;
-#define CASE_FOR_ID(name, index) \
- case k##name: \
- builder \
- .Set##name( \
- current_sample_.sub_metrics_durations[index].InMicroseconds()) \
- .Set##name##BeginMainFrame( \
- current_sample_.sub_main_frame_durations[index].InMicroseconds()); \
- break
+#define RECORD_METRIC(name) \
+ builder.Set##name(current_sample_.sub_metrics_counts[k##name]) \
+ .Set##name##BeginMainFrame( \
+ current_sample_.sub_main_frame_counts[k##name]);
+
+#define RECORD_BUCKETED_METRIC(name) \
+ builder.Set##name(ApplyBucket(current_sample_.sub_metrics_counts[k##name])) \
+ .Set##name##BeginMainFrame( \
+ ApplyBucket(current_sample_.sub_main_frame_counts[k##name]));
ukm::builders::Blink_UpdateTime builder(source_id_);
- builder.SetMainFrame(
- current_sample_.primary_metric_duration.InMicroseconds());
+ builder.SetMainFrame(current_sample_.primary_metric_count);
builder.SetMainFrameIsBeforeFCP(fcp_state_ != kHavePassedFCP);
builder.SetMainFrameReasons(current_sample_.trackers);
- for (size_t i = 0; i < metrics_data().size(); ++i) {
- switch (static_cast<MetricId>(i)) {
- CASE_FOR_ID(CompositingAssignments, i);
- CASE_FOR_ID(CompositingCommit, i);
- CASE_FOR_ID(CompositingInputs, i);
- CASE_FOR_ID(ImplCompositorCommit, i);
- CASE_FOR_ID(IntersectionObservation, i);
- CASE_FOR_ID(Paint, i);
- CASE_FOR_ID(PrePaint, i);
- CASE_FOR_ID(Style, i);
- CASE_FOR_ID(Layout, i);
- CASE_FOR_ID(ForcedStyleAndLayout, i);
- CASE_FOR_ID(HandleInputEvents, i);
- CASE_FOR_ID(Animate, i);
- CASE_FOR_ID(UpdateLayers, i);
- CASE_FOR_ID(WaitForCommit, i);
- CASE_FOR_ID(DisplayLockIntersectionObserver, i);
- CASE_FOR_ID(JavascriptIntersectionObserver, i);
- CASE_FOR_ID(LazyLoadIntersectionObserver, i);
- CASE_FOR_ID(MediaIntersectionObserver, i);
- CASE_FOR_ID(AnchorElementMetricsIntersectionObserver, i);
- CASE_FOR_ID(UpdateViewportIntersection, i);
- CASE_FOR_ID(UserDrivenDocumentUpdate, i);
- CASE_FOR_ID(ServiceDocumentUpdate, i);
- CASE_FOR_ID(ContentDocumentUpdate, i);
- CASE_FOR_ID(ScrollDocumentUpdate, i);
- CASE_FOR_ID(HitTestDocumentUpdate, i);
- CASE_FOR_ID(JavascriptDocumentUpdate, i);
- case kCount:
- case kMainFrame:
- NOTREACHED();
- break;
- }
- }
+ RECORD_METRIC(CompositingAssignments);
+ RECORD_METRIC(CompositingCommit);
+ RECORD_METRIC(CompositingInputs);
+ RECORD_METRIC(ImplCompositorCommit);
+ RECORD_METRIC(IntersectionObservation);
+ RECORD_BUCKETED_METRIC(IntersectionObservationInternalCount);
+ RECORD_BUCKETED_METRIC(IntersectionObservationJavascriptCount);
+ RECORD_METRIC(Paint);
+ RECORD_METRIC(PrePaint);
+ RECORD_METRIC(Style);
+ RECORD_METRIC(Layout);
+ RECORD_METRIC(ForcedStyleAndLayout);
+ RECORD_METRIC(HandleInputEvents);
+ RECORD_METRIC(Animate);
+ RECORD_METRIC(UpdateLayers);
+ RECORD_METRIC(WaitForCommit);
+ RECORD_METRIC(DisplayLockIntersectionObserver);
+ RECORD_METRIC(JavascriptIntersectionObserver);
+ RECORD_METRIC(LazyLoadIntersectionObserver);
+ RECORD_METRIC(MediaIntersectionObserver);
+ RECORD_METRIC(AnchorElementMetricsIntersectionObserver);
+ RECORD_METRIC(UpdateViewportIntersection);
+ RECORD_METRIC(UserDrivenDocumentUpdate);
+ RECORD_METRIC(ServiceDocumentUpdate);
+ RECORD_METRIC(ContentDocumentUpdate);
+ RECORD_METRIC(ScrollDocumentUpdate);
+ RECORD_METRIC(HitTestDocumentUpdate);
+ RECORD_METRIC(JavascriptDocumentUpdate);
+
builder.Record(recorder_);
-#undef CASE_FOR_ID
+#undef RECORD_METRIC
+#undef RECORD_BUCKETED_METRIC
// Reset the frames since last report to ensure correct sampling.
frames_since_last_report_ = 0;
@@ -561,13 +619,13 @@ void LocalFrameUkmAggregator::ResetAllMetrics() {
}
bool LocalFrameUkmAggregator::AllMetricsAreZero() {
- if (!primary_metric_.interval_duration.is_zero())
+ if (primary_metric_.interval_count != 0)
return false;
for (auto& record : absolute_metric_records_) {
- if (!record.interval_duration.is_zero()) {
+ if (record.interval_count != 0) {
return false;
}
- if (!record.main_frame_duration.is_zero()) {
+ if (record.main_frame_count != 0) {
return false;
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
index 569e6a77967..df94f56139b 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
@@ -127,6 +127,8 @@ class CORE_EXPORT LocalFrameUkmAggregator
kCompositingInputs,
kImplCompositorCommit,
kIntersectionObservation,
+ kIntersectionObservationInternalCount,
+ kIntersectionObservationJavascriptCount,
kPaint,
kPrePaint,
kStyle,
@@ -152,6 +154,10 @@ class CORE_EXPORT LocalFrameUkmAggregator
kMainFrame
};
+ // For metrics that require it, this converts the input value to use
+ // exponential bucketing.
+ static int64_t ApplyBucketIfNecessary(int64_t value, unsigned metric_id);
+
typedef struct MetricInitializationData {
const char* const name;
bool has_uma;
@@ -159,6 +165,7 @@ class CORE_EXPORT LocalFrameUkmAggregator
private:
friend class LocalFrameUkmAggregatorTest;
+ friend class LocalFrameUkmAggregatorSimTest;
// Primary metric name
static const char* primary_metric_name() { return "MainFrame"; }
@@ -171,6 +178,8 @@ class CORE_EXPORT LocalFrameUkmAggregator
{"CompositingInputs", true},
{"ImplCompositorCommit", true},
{"IntersectionObservation", true},
+ {"IntersectionObservationInternalCount", true},
+ {"IntersectionObservationJavascriptCount", true},
{"Paint", true},
{"PrePaint", true},
{"Style", true},
@@ -206,6 +215,9 @@ class CORE_EXPORT LocalFrameUkmAggregator
public:
ScopedUkmHierarchicalTimer(ScopedUkmHierarchicalTimer&&);
+ ScopedUkmHierarchicalTimer(const ScopedUkmHierarchicalTimer&) = delete;
+ ScopedUkmHierarchicalTimer& operator=(const ScopedUkmHierarchicalTimer&) =
+ delete;
~ScopedUkmHierarchicalTimer();
private:
@@ -219,13 +231,38 @@ class CORE_EXPORT LocalFrameUkmAggregator
const size_t metric_index_;
const base::TickClock* clock_;
const base::TimeTicks start_time_;
+ };
+
+ // This is an optimization for the case where we would otherwise instantiate a
+ // ScopedUkmHierarchicalTimer in the body of a loop. On some platforms,
+ // TickClock::NowTicks() is weirdly expensive. Compared to
+ // ScopedUkmHierarchicalTimer, this class makes fewer calls to NowTicks() by
+ // reusing a single timestamp as the end of one measurement and the beginning
+ // of the next.
+ class CORE_EXPORT IterativeTimer {
+ STACK_ALLOCATED();
+
+ public:
+ IterativeTimer(LocalFrameUkmAggregator&);
+ ~IterativeTimer();
+ // Start a time interval measurement for the given metric, completing the
+ // prior interval measurement if necessary.
+ void StartInterval(int64_t metric_index);
- DISALLOW_COPY_AND_ASSIGN(ScopedUkmHierarchicalTimer);
+ private:
+ void Record();
+ scoped_refptr<LocalFrameUkmAggregator> aggregator_;
+ base::TimeTicks start_time_;
+ int64_t metric_index_ = -1;
};
LocalFrameUkmAggregator(int64_t source_id, ukm::UkmRecorder*);
+ LocalFrameUkmAggregator(const LocalFrameUkmAggregator&) = delete;
+ LocalFrameUkmAggregator& operator=(const LocalFrameUkmAggregator&) = delete;
~LocalFrameUkmAggregator();
+ const base::TickClock* GetClock() const { return clock_; }
+
// Create a scoped timer with the index of the metric. Note the index must
// correspond to the matching index in metric_names.
ScopedUkmHierarchicalTimer GetScopedTimer(size_t metric_index);
@@ -242,9 +279,12 @@ class CORE_EXPORT LocalFrameUkmAggregator
// Record a sample for a sub-metric. This should only be used when
// a ScopedUkmHierarchicalTimer cannot be used (such as when the timed
// interval does not fall inside a single calling function).
- void RecordSample(size_t metric_index,
- base::TimeTicks start,
- base::TimeTicks end);
+ void RecordTimerSample(size_t metric_index,
+ base::TimeTicks start,
+ base::TimeTicks end);
+
+ // Record a sample for a count-based sub-metric.
+ void RecordCountSample(size_t metric_index, int64_t count);
// Record a ForcedLayout sample. The reason will determine which, if any,
// additional metrics are reported in order to diagnose the cause of
@@ -287,22 +327,22 @@ class CORE_EXPORT LocalFrameUkmAggregator
// Accumulated at each sample, then reset with a call to
// RecordEndOfFrameMetrics.
- base::TimeDelta interval_duration;
+ int64_t interval_count = 0;
// Accumulated at each sample when within a BeginMainFrame,
// reset with a call to RecordEndOfFrameMetrics.
- base::TimeDelta main_frame_duration;
+ int64_t main_frame_count = 0;
// Accumulated at each sample up to the time of First Contentful Paint.
- base::TimeDelta pre_fcp_aggregate;
+ int64_t pre_fcp_aggregate = 0;
void reset();
};
struct SampleToRecord {
- base::TimeDelta primary_metric_duration;
- std::array<base::TimeDelta, kCount> sub_metrics_durations;
- std::array<base::TimeDelta, kCount> sub_main_frame_durations;
+ int64_t primary_metric_count;
+ std::array<int64_t, kCount> sub_metrics_counts;
+ std::array<int64_t, kCount> sub_main_frame_counts;
cc::ActiveFrameSequenceTrackers trackers;
};
@@ -372,8 +412,6 @@ class CORE_EXPORT LocalFrameUkmAggregator
kMustNotChooseNextFrame
};
SampleControlForTest next_frame_sample_control_for_test_ = kNoPreference;
-
- DISALLOW_COPY_AND_ASSIGN(LocalFrameUkmAggregator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc
index b02feae721f..6851f4c26fe 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc
@@ -4,11 +4,16 @@
#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
+#include "base/metrics/statistics_recorder.h"
#include "base/test/test_mock_time_task_runner.h"
#include "cc/metrics/begin_main_frame_metrics.h"
#include "components/ukm/test_ukm_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_init.h"
+#include "third_party/blink/renderer/core/testing/intersection_observer_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"
namespace blink {
@@ -52,6 +57,10 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
return GetMetricName(index) + "BeginMainFrame";
}
+ int64_t GetIntervalCount(int index) {
+ return aggregator_->absolute_metric_records_[index].interval_count;
+ }
+
void ChooseNextFrameForTest() { aggregator().ChooseNextFrameForTest(); }
void DoNotChooseNextFrameForTest() {
aggregator().DoNotChooseNextFrameForTest();
@@ -76,7 +85,7 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
ukm::TestUkmRecorder::EntryHasMetric(entry, GetPrimaryMetricName()));
const int64_t* primary_metric_value =
ukm::TestUkmRecorder::GetEntryMetric(entry, GetPrimaryMetricName());
- EXPECT_NEAR(*primary_metric_value / 1e3, expected_primary_metric, 0.001);
+ EXPECT_NEAR(*primary_metric_value, expected_primary_metric * 1e3, 1);
// All tests using this method check through kForcedStyleAndLayout because
// kForcedStyleAndLayout and subsequent metrics report and record
// differently.
@@ -85,15 +94,20 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
ukm::TestUkmRecorder::EntryHasMetric(entry, GetMetricName(i)));
const int64_t* metric_value =
ukm::TestUkmRecorder::GetEntryMetric(entry, GetMetricName(i));
- EXPECT_NEAR(*metric_value / 1e3, expected_sub_metric, 0.001);
+ EXPECT_NEAR(*metric_value,
+ LocalFrameUkmAggregator::ApplyBucketIfNecessary(
+ expected_sub_metric * 1e3, i),
+ 1);
EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(
entry, GetBeginMainFrameMetricName(i)));
const int64_t* metric_begin_main_frame =
ukm::TestUkmRecorder::GetEntryMetric(entry,
GetBeginMainFrameMetricName(i));
- EXPECT_NEAR(*metric_begin_main_frame / 1e3, expected_begin_main_frame,
- 0.001);
+ EXPECT_NEAR(*metric_begin_main_frame,
+ LocalFrameUkmAggregator::ApplyBucketIfNecessary(
+ expected_begin_main_frame * 1e3, i),
+ 1);
}
EXPECT_TRUE(
ukm::TestUkmRecorder::EntryHasMetric(entry, "MainFrameIsBeforeFCP"));
@@ -116,7 +130,7 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
ukm::TestUkmRecorder::EntryHasMetric(entry, GetPrimaryMetricName()));
const int64_t* primary_metric_value =
ukm::TestUkmRecorder::GetEntryMetric(entry, GetPrimaryMetricName());
- EXPECT_NEAR(*primary_metric_value / 1e3, expected_primary_metric, 0.001);
+ EXPECT_NEAR(*primary_metric_value, expected_primary_metric * 1e3, 1);
// All tests using this method check through kForcedStyleAndLayout because
// kForcedStyleAndLayout and subsequent metrics report and record
// differently.
@@ -125,7 +139,10 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
ukm::TestUkmRecorder::EntryHasMetric(entry, GetMetricName(i)));
const int64_t* metric_value =
ukm::TestUkmRecorder::GetEntryMetric(entry, GetMetricName(i));
- EXPECT_NEAR(*metric_value / 1e3, expected_sub_metric, 0.001);
+ EXPECT_NEAR(*metric_value,
+ LocalFrameUkmAggregator::ApplyBucketIfNecessary(
+ expected_sub_metric * 1e3, i),
+ 1);
}
}
}
@@ -181,14 +198,14 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
entry, GetMetricName(LocalFrameUkmAggregator::kForcedStyleAndLayout)));
const int64_t* metric_value = ukm::TestUkmRecorder::GetEntryMetric(
entry, GetMetricName(LocalFrameUkmAggregator::kForcedStyleAndLayout));
- EXPECT_NEAR(*metric_value / 1e3, 10, 0.001);
+ EXPECT_NEAR(*metric_value, 10000, 1);
if (target_metric != LocalFrameUkmAggregator::kCount) {
EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(
entry, GetMetricName(target_metric)));
metric_value = ukm::TestUkmRecorder::GetEntryMetric(
entry, GetMetricName(target_metric));
- EXPECT_NEAR(*metric_value / 1e3, 10, 0.001);
+ EXPECT_NEAR(*metric_value, 10000, 1);
}
for (int i = LocalFrameUkmAggregator::kForcedStyleAndLayout + 1;
i < LocalFrameUkmAggregator::kCount; ++i) {
@@ -204,9 +221,8 @@ class LocalFrameUkmAggregatorTest : public testing::Test {
}
bool SampleMatchesIteration(int64_t iteration_count) {
- return aggregator()
- .current_sample_.sub_metrics_durations[0]
- .InMilliseconds() == iteration_count;
+ return aggregator().current_sample_.sub_metrics_counts[0] / 1000 ==
+ iteration_count;
}
private:
@@ -539,4 +555,89 @@ TEST_F(LocalFrameUkmAggregatorTest, SampleDoesChange) {
EXPECT_LT(iteration_count, 100000u);
}
+TEST_F(LocalFrameUkmAggregatorTest, IterativeTimer) {
+ {
+ LocalFrameUkmAggregator::IterativeTimer timer(aggregator());
+ timer.StartInterval(LocalFrameUkmAggregator::kStyle);
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(5));
+ timer.StartInterval(LocalFrameUkmAggregator::kLayout);
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(7));
+ timer.StartInterval(LocalFrameUkmAggregator::kLayout);
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(11));
+ timer.StartInterval(LocalFrameUkmAggregator::kPrePaint);
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(13));
+ }
+ EXPECT_EQ(GetIntervalCount(LocalFrameUkmAggregator::kStyle), 5);
+ EXPECT_EQ(GetIntervalCount(LocalFrameUkmAggregator::kLayout), 18);
+ EXPECT_EQ(GetIntervalCount(LocalFrameUkmAggregator::kPrePaint), 13);
+}
+
+class LocalFrameUkmAggregatorSimTest : public SimTest {
+ protected:
+ void ChooseNextFrameForTest() {
+ LocalFrameRoot()
+ .GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .ChooseNextFrameForTest();
+ }
+};
+
+TEST_F(LocalFrameUkmAggregatorSimTest, IntersectionObserverCounts) {
+ WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ .target { width: 50px; height: 50px; }
+ .spacer { height: 1000px; }
+ </style>
+ <div id=target1 class=target></div>
+ <div id=target2 class=target></div>
+ <div class=spacer></div>
+ )HTML");
+ Compositor().BeginFrame();
+ ChooseNextFrameForTest();
+
+ Element* target1 = GetDocument().getElementById("target1");
+ Element* target2 = GetDocument().getElementById("target2");
+
+ // Create internal observer
+ IntersectionObserverInit* observer_init = IntersectionObserverInit::Create();
+ TestIntersectionObserverDelegate* internal_delegate =
+ MakeGarbageCollected<TestIntersectionObserverDelegate>(
+ GetDocument(),
+ LocalFrameUkmAggregator::kLazyLoadIntersectionObserver);
+ IntersectionObserver* internal_observer =
+ IntersectionObserver::Create(observer_init, *internal_delegate);
+ internal_observer->observe(target1);
+ internal_observer->observe(target2);
+ Compositor().BeginFrame();
+ base::HistogramBase* internal_count_histogram =
+ base::StatisticsRecorder::FindHistogram(
+ "Blink.IntersectionObservationInternalCount.UpdateTime.PreFCP");
+ ASSERT_TRUE(internal_count_histogram);
+ EXPECT_EQ(internal_count_histogram->SnapshotSamples()->GetCount(2), 1);
+ base::HistogramBase* javascript_count_histogram =
+ base::StatisticsRecorder::FindHistogram(
+ "Blink.IntersectionObservationJavascriptCount.UpdateTime.PreFCP");
+ ASSERT_TRUE(javascript_count_histogram);
+ EXPECT_EQ(javascript_count_histogram->SnapshotSamples()->sum(), 0);
+
+ TestIntersectionObserverDelegate* javascript_delegate =
+ MakeGarbageCollected<TestIntersectionObserverDelegate>(
+ GetDocument(),
+ LocalFrameUkmAggregator::kJavascriptIntersectionObserver);
+ IntersectionObserver* javascript_observer =
+ IntersectionObserver::Create(observer_init, *javascript_delegate);
+ javascript_observer->observe(target1);
+ javascript_observer->observe(target2);
+ Compositor().BeginFrame();
+ EXPECT_EQ(internal_count_histogram->SnapshotSamples()->GetCount(2), 2);
+ EXPECT_EQ(javascript_count_histogram->SnapshotSamples()->GetCount(2), 1);
+}
} // namespace blink
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 411783814a6..45882fbeabd 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
@@ -37,6 +37,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/timer/lap_timer.h"
#include "cc/animation/animation_host.h"
+#include "cc/document_transition/document_transition_request.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/layers/picture_layer.h"
#include "cc/tiles/frame_viewer_instrumentation.h"
@@ -77,6 +78,7 @@
#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/fullscreen/fullscreen.h"
+#include "third_party/blink/renderer/core/highlight/highlight_registry.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/html/html_frame_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
@@ -100,6 +102,7 @@
#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/ng/ng_block_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/style_retain_scope.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
@@ -143,6 +146,7 @@
#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/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/font_performance.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"
@@ -163,6 +167,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
+#include "third_party/blink/renderer/platform/widget/frame_widget.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/cursor.h"
@@ -269,9 +274,7 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect)
layout_shift_tracker_(MakeGarbageCollected<LayoutShiftTracker>(this)),
paint_timing_detector_(MakeGarbageCollected<PaintTimingDetector>(this)),
mobile_friendliness_checker_(
- frame_->IsMainFrame()
- ? MakeGarbageCollected<MobileFriendlinessChecker>(*this)
- : nullptr)
+ MakeGarbageCollected<MobileFriendlinessChecker>(*this))
#if DCHECK_IS_ON()
,
is_updating_descendant_dependent_flags_(false),
@@ -531,7 +534,7 @@ cc::AnimationHost* LocalFrameView::GetCompositorAnimationHost() const {
return GetScrollingContext()->GetCompositorAnimationHost();
if (!GetFrame().LocalFrameRoot().IsMainFrame())
- return nullptr;
+ return frame_->GetWidgetForLocalRoot()->AnimationHost();
// TODO(kenrb): Compositor animation host and timeline for the main frame
// still live on ScrollingCoordinator. https://crbug.com/680606.
@@ -784,20 +787,30 @@ void LocalFrameView::PerformLayout() {
analyzer_->Increment(LayoutAnalyzer::kPerformLayoutRootLayoutObjects,
layout_subtree_root_list_.size());
}
- HashSet<LayoutBlock*> fragment_tree_spines;
+ // This map will be used to avoid rebuilding several times the fragment
+ // tree spine of a common ancestor.
+ HashMap<const LayoutBlock*, unsigned> fragment_tree_spines;
+ for (LayoutObject* root : layout_subtree_root_list_.Unordered()) {
+ const LayoutBlock* cb = root->ContainingBlock();
+ if (cb->PhysicalFragmentCount()) {
+ auto add_result = fragment_tree_spines.insert(cb, 0);
+ ++add_result.stored_value->value;
+ }
+ }
for (auto& root : layout_subtree_root_list_.Ordered()) {
+ LayoutBlock* cb = root->ContainingBlock();
+ auto it = fragment_tree_spines.find(cb);
+ DCHECK(it == fragment_tree_spines.end() || it->value > 0);
+ // Ensure fragment-tree consistency just after all the cb's
+ // descendants have completed their subtree layout.
+ bool should_rebuild_fragments =
+ it != fragment_tree_spines.end() && --it->value == 0;
+
if (!LayoutFromRootObject(*root))
continue;
- // TODO(jfernandez): Perhaps we should store the whole spine instead of
- // the immediate ancestor, so that we could avoid rebuilding the common
- // ancestors fragments.
- if (To<LayoutBox>(*root).PhysicalFragmentCount()) {
- LayoutBlock* cb = root->ContainingBlock();
- if (NGBlockNode::CanUseNewLayout(*cb) && !cb->NeedsLayout()) {
- fragment_tree_spines.insert(cb);
- }
- }
+ if (should_rebuild_fragments)
+ cb->RebuildFragmentTreeSpine();
// We need to ensure that we mark up all layoutObjects up to the
// LayoutView for paint invalidation. This simplifies our code as we
@@ -806,9 +819,17 @@ void LocalFrameView::PerformLayout() {
container->SetShouldCheckForPaintInvalidation();
}
layout_subtree_root_list_.Clear();
+#if DCHECK_IS_ON()
// Ensure fragment-tree consistency after a subtree layout.
- for (auto* cb : fragment_tree_spines)
- cb->RebuildFragmentTreeSpine();
+ for (const auto& p : fragment_tree_spines) {
+ // |LayoutNGMixin::UpdateInFlowBlockLayout| may |SetNeedsLayout| to its
+ // containing block. Don't check if it will be re-laid out.
+ if (!p.key->NeedsLayout()) {
+ p.key->AssertFragmentTree();
+ }
+ DCHECK_EQ(p.value, 0u);
+ }
+#endif
fragment_tree_spines.clear();
} else {
if (HasOrthogonalWritingModeRoots())
@@ -1007,7 +1028,11 @@ void LocalFrameView::RunIntersectionObserverSteps() {
SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
LocalFrameUkmAggregator::kIntersectionObservation);
- bool needs_occlusion_tracking = UpdateViewportIntersectionsForSubtree(0);
+ // Populating monotonic_time may be expensive, and may be unnecessary, so
+ // allow it to be populated on demand.
+ absl::optional<base::TimeTicks> monotonic_time;
+ bool needs_occlusion_tracking =
+ UpdateViewportIntersectionsForSubtree(0, monotonic_time);
if (FrameOwner* owner = frame_->Owner())
owner->SetNeedsOcclusionTracking(needs_occlusion_tracking);
#if DCHECK_IS_ON()
@@ -1023,9 +1048,11 @@ void LocalFrameView::ForceUpdateViewportIntersections() {
DisallowThrottlingScope disallow_throttling(*this);
UpdateLifecycleToPrePaintClean(
DocumentUpdateReason::kIntersectionObservation);
+ absl::optional<base::TimeTicks> monotonic_time;
UpdateViewportIntersectionsForSubtree(
IntersectionObservation::kImplicitRootObserversNeedUpdate |
- IntersectionObservation::kIgnoreDelay);
+ IntersectionObservation::kIgnoreDelay,
+ monotonic_time);
}
LayoutSVGRoot* LocalFrameView::EmbeddedReplacedContent() const {
@@ -1570,7 +1597,8 @@ bool LocalFrameView::RunPostLayoutIntersectionObserverSteps() {
DCHECK(frame_->IsLocalRoot());
DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
- ComputePostLayoutIntersections(0);
+ absl::optional<base::TimeTicks> monotonic_time;
+ ComputePostLayoutIntersections(0, monotonic_time);
bool needs_more_lifecycle_steps = false;
ForAllNonThrottledLocalFrameViews(
@@ -1590,7 +1618,9 @@ bool LocalFrameView::RunPostLayoutIntersectionObserverSteps() {
return needs_more_lifecycle_steps;
}
-void LocalFrameView::ComputePostLayoutIntersections(unsigned parent_flags) {
+void LocalFrameView::ComputePostLayoutIntersections(
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>& monotonic_time) {
if (ShouldThrottleRendering())
return;
@@ -1599,7 +1629,8 @@ void LocalFrameView::ComputePostLayoutIntersections(unsigned parent_flags) {
if (auto* controller =
GetFrame().GetDocument()->GetIntersectionObserverController()) {
- controller->ComputeIntersections(flags, EnsureUkmAggregator());
+ controller->ComputeIntersections(flags, EnsureUkmAggregator(),
+ monotonic_time);
}
for (Frame* child = frame_->Tree().FirstChild(); child;
@@ -1608,7 +1639,7 @@ void LocalFrameView::ComputePostLayoutIntersections(unsigned parent_flags) {
if (!child_local_frame)
continue;
if (LocalFrameView* child_view = child_local_frame->View())
- child_view->ComputePostLayoutIntersections(flags);
+ child_view->ComputePostLayoutIntersections(flags, monotonic_time);
}
}
@@ -2332,7 +2363,7 @@ bool LocalFrameView::UpdateLifecyclePhases(
// in preparation for a hit test.
if (reason == DocumentUpdateReason::kHitTest) {
LocalFrameUkmAggregator& aggregator = EnsureUkmAggregator();
- aggregator.RecordSample(
+ aggregator.RecordTimerSample(
static_cast<size_t>(LocalFrameUkmAggregator::kHitTestDocumentUpdate),
lifecycle_data_.start_time, base::TimeTicks::Now());
}
@@ -2472,7 +2503,7 @@ void LocalFrameView::UpdateLifecyclePhasesInternal(
#endif
DCHECK_EQ(target_state, DocumentLifecycle::kPaintClean);
- RunPaintLifecyclePhase();
+ RunPaintLifecyclePhase(PaintBenchmarkMode::kNormal);
DCHECK(ShouldThrottleRendering() || AnyFrameIsPrintingOrPaintingPreview() ||
Lifecycle().GetState() == DocumentLifecycle::kPaintClean);
@@ -2694,6 +2725,7 @@ bool LocalFrameView::AnyFrameIsPrintingOrPaintingPreview() {
}
void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
+ DCHECK(LocalFrameTreeAllowsThrottling());
TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase");
// While printing or capturing a paint preview of a document, the paint walk
// is done into a special canvas. There is no point doing a normal paint step
@@ -2701,20 +2733,37 @@ void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
if (AnyFrameIsPrintingOrPaintingPreview())
return;
- bool repainted = PaintTree(benchmark_mode);
+ // Validate all HighlightMarkers of all non-throttled LocalFrameViews before
+ // the call to PaintTree() so they're updated during this lifecycle.
+ ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
+ if (LocalDOMWindow* window = frame_view.GetFrame().DomWindow()) {
+ if (HighlightRegistry* highlight_registry =
+ window->Supplementable<LocalDOMWindow>::RequireSupplement<
+ HighlightRegistry>()) {
+ highlight_registry->ValidateHighlightMarkers();
+ }
+ }
+ });
- if (paint_artifact_compositor_ &&
- benchmark_mode ==
- PaintBenchmarkMode::kForcePaintArtifactCompositorUpdate) {
- paint_artifact_compositor_->SetNeedsUpdate();
+ bool needed_update;
+ {
+ PaintController::CycleScope cycle_scope;
+ bool repainted = PaintTree(benchmark_mode, cycle_scope);
+
+ if (paint_artifact_compositor_ &&
+ benchmark_mode ==
+ PaintBenchmarkMode::kForcePaintArtifactCompositorUpdate) {
+ paint_artifact_compositor_->SetNeedsUpdate();
+ }
+ needed_update = !paint_artifact_compositor_ ||
+ paint_artifact_compositor_->NeedsUpdate();
+ PushPaintArtifactToCompositor(repainted);
}
- bool needed_update =
- !paint_artifact_compositor_ || paint_artifact_compositor_->NeedsUpdate();
- PushPaintArtifactToCompositor(repainted);
size_t total_animations_count = 0;
ForAllNonThrottledLocalFrameViews(
- [this, &total_animations_count](LocalFrameView& frame_view) {
+ [this, &needed_update,
+ &total_animations_count](LocalFrameView& frame_view) {
if (auto* scrollable_area = frame_view.GetScrollableArea())
scrollable_area->UpdateCompositorScrollAnimations();
if (const auto* animating_scrollable_areas =
@@ -2722,18 +2771,16 @@ void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
for (PaintLayerScrollableArea* area : *animating_scrollable_areas)
area->UpdateCompositorScrollAnimations();
}
+ Document& document = frame_view.GetLayoutView()->GetDocument();
{
// Updating animations can notify ready promises which could mutate
// the DOM. We should delay these until we have finished the lifecycle
// update. https://crbug.com/1196781
ScriptForbiddenScope forbid_script;
- frame_view.GetLayoutView()
- ->GetDocument()
- .GetDocumentAnimations()
- .UpdateAnimations(DocumentLifecycle::kPaintClean,
- paint_artifact_compositor_.get());
+ document.GetDocumentAnimations().UpdateAnimations(
+ DocumentLifecycle::kPaintClean, paint_artifact_compositor_.get(),
+ needed_update);
}
- Document& document = frame_view.GetLayoutView()->GetDocument();
total_animations_count +=
document.GetDocumentAnimations().GetAnimationsCount();
});
@@ -2753,22 +2800,6 @@ void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
}
}
- // Notify the controller that the artifact has been pushed and some
- // lifecycle state can be freed (such as raster invalidations).
- if (paint_controller_)
- paint_controller_->FinishCycle();
-
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
- if (root) {
- ForAllPaintingGraphicsLayers(*root, [](GraphicsLayer& layer) {
- // Notify the paint controller that the artifact has been pushed and
- // some lifecycle state can be freed (such as raster invalidations).
- layer.GetPaintController().FinishCycle();
- });
- }
- }
-
if (paint_artifact_compositor_)
paint_artifact_compositor_->ClearPropertyTreeChangedState();
@@ -2834,7 +2865,8 @@ void LocalFrameView::EnqueueScrollEvents() {
});
}
-bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
+bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode,
+ PaintController::CycleScope& cycle_scope) {
SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
LocalFrameUkmAggregator::kPaint);
@@ -2842,6 +2874,10 @@ bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
auto* layout_view = GetLayoutView();
DCHECK(layout_view);
+
+ if (RuntimeEnabledFeatures::CullRectUpdateEnabled())
+ CullRectUpdater(*layout_view->Layer()).Update();
+
paint_frame_count_++;
ForAllNonThrottledLocalFrameViews(
[](LocalFrameView& frame_view) {
@@ -2878,7 +2914,11 @@ bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
bool needs_clear_repaint_flags = false;
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // TODO(paint-dev): We should be able to get rid of AddController entirely
+ // after non-CAP code is removed. The call to EnsurePaintController() will
+ // need to be moved up the call stack.
EnsurePaintController();
+ cycle_scope.AddController(*paint_controller_);
PaintChunkSubset previous_chunks(
paint_controller_->GetPaintArtifactShared());
@@ -2886,12 +2926,11 @@ bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
PaintController::ScopedBenchmarkMode scoped_benchmark(*paint_controller_,
benchmark_mode);
- if (!paint_controller_->ShouldForcePaintForBenchmark() &&
- !GetLayoutView()->Layer()->SelfOrDescendantNeedsRepaint() &&
- !visual_viewport_or_overlay_needs_repaint_) {
- paint_controller_->UpdateUMACountsOnFullyCached();
- } else {
+ if (paint_controller_->ShouldForcePaintForBenchmark() ||
+ GetLayoutView()->Layer()->SelfOrDescendantNeedsRepaint() ||
+ visual_viewport_or_overlay_needs_repaint_) {
GraphicsContext graphics_context(*paint_controller_);
+
if (Settings* settings = frame_->GetSettings()) {
graphics_context.SetDarkModeEnabled(
settings->GetForceDarkModeEnabled() &&
@@ -2950,6 +2989,8 @@ bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
// parented into the main frame tree, or when the LocalFrameView is the main
// 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.
+ // Note that paint_controller_ is not added to cycle_scope, because it is
+ // transient and may be deleted before cycle_scope.
paint_controller_ =
std::make_unique<PaintController>(PaintController::kTransient);
pre_composited_layers_.clear();
@@ -2957,8 +2998,9 @@ bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
if (GraphicsLayer* root =
layout_view->Compositor()->PaintRootGraphicsLayer()) {
- repainted = root->PaintRecursively(
- graphics_context, pre_composited_layers_, benchmark_mode);
+ repainted =
+ root->PaintRecursively(graphics_context, pre_composited_layers_,
+ cycle_scope, benchmark_mode);
if (visual_viewport_or_overlay_needs_repaint_ &&
paint_artifact_compositor_)
paint_artifact_compositor_->SetNeedsUpdate();
@@ -2995,7 +3037,6 @@ bool LocalFrameView::PaintTree(PaintBenchmarkMode benchmark_mode) {
frame_view.GetPaintTimingDetector().NotifyPaintFinished();
});
- PaintController::ReportUMACounts();
return repainted;
}
@@ -3025,6 +3066,9 @@ void LocalFrameView::PushPaintArtifactToCompositor(bool repainted) {
paint_artifact_compositor_->RootLayer(), &GetFrame());
}
+ paint_artifact_compositor_->SetPrefersLCDText(
+ page->GetSettings().GetPreferCompositingToLCDTextEnabled());
+
SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
LocalFrameUkmAggregator::kCompositingCommit);
@@ -3044,6 +3088,8 @@ void LocalFrameView::PushPaintArtifactToCompositor(bool repainted) {
PaintArtifactCompositor::ViewportProperties viewport_properties;
if (GetFrame().IsMainFrame()) {
const auto& viewport = page->GetVisualViewport();
+ viewport_properties.overscroll_elasticity_effect =
+ viewport.GetOverscrollElasticityEffectNode();
viewport_properties.overscroll_elasticity_transform =
viewport.GetOverscrollElasticityTransformNode();
viewport_properties.page_scale = viewport.GetPageScaleNode();
@@ -3162,6 +3208,7 @@ void LocalFrameView::UpdateStyleAndLayoutIfNeededRecursive() {
CheckDoesNotNeedLayout();
#if DCHECK_IS_ON()
frame_->GetDocument()->GetLayoutView()->AssertLaidOut();
+ frame_->GetDocument()->GetLayoutView()->AssertFragmentTree();
#endif
if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
@@ -3229,6 +3276,7 @@ void LocalFrameView::UpdateStyleAndLayout() {
if (did_layout)
GetLayoutView()->AssertSubtreeIsLaidOut();
}
+ frame_->GetDocument()->GetDocumentAnimations().AssertNoPendingUpdates();
#endif
if (did_layout) {
@@ -3249,8 +3297,6 @@ void LocalFrameView::UpdateStyleAndLayout() {
bool LocalFrameView::UpdateStyleAndLayoutInternal() {
{
- SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
- LocalFrameUkmAggregator::kStyle);
frame_->GetDocument()->UpdateStyleAndLayoutTreeForThisDocument();
// Update style for all embedded SVG documents underneath this frame, so
@@ -3617,34 +3663,38 @@ void LocalFrameView::SetTracksRasterInvalidations(
}
void LocalFrameView::ServiceScriptedAnimations(base::TimeTicks start_time) {
+ bool can_throttle = CanThrottleRendering();
// Disallow throttling in case any script needs to do a synchronous
// lifecycle update in other frames which are throttled.
DisallowThrottlingScope disallow_throttling(*this);
- if (ScrollableArea* scrollable_area = GetScrollableArea()) {
- scrollable_area->ServiceScrollAnimations(
- start_time.since_origin().InSecondsF());
- }
- if (const ScrollableAreaSet* animating_scrollable_areas =
- AnimatingScrollableAreas()) {
- // Iterate over a copy, since ScrollableAreas may deregister
- // themselves during the iteration.
- HeapVector<Member<PaintLayerScrollableArea>>
- animating_scrollable_areas_copy;
- CopyToVector(*animating_scrollable_areas, animating_scrollable_areas_copy);
- for (PaintLayerScrollableArea* scrollable_area :
- animating_scrollable_areas_copy) {
+ Document* document = GetFrame().GetDocument();
+ DCHECK(document);
+ if (!can_throttle) {
+ if (ScrollableArea* scrollable_area = GetScrollableArea()) {
scrollable_area->ServiceScrollAnimations(
start_time.since_origin().InSecondsF());
}
+ if (const ScrollableAreaSet* animating_scrollable_areas =
+ AnimatingScrollableAreas()) {
+ // Iterate over a copy, since ScrollableAreas may deregister
+ // themselves during the iteration.
+ HeapVector<Member<PaintLayerScrollableArea>>
+ animating_scrollable_areas_copy;
+ CopyToVector(*animating_scrollable_areas,
+ animating_scrollable_areas_copy);
+ for (PaintLayerScrollableArea* scrollable_area :
+ animating_scrollable_areas_copy) {
+ scrollable_area->ServiceScrollAnimations(
+ start_time.since_origin().InSecondsF());
+ }
+ }
+ GetFrame().AnimateSnapFling(start_time);
+ if (SVGDocumentExtensions::ServiceSmilOnAnimationFrame(*document))
+ GetPage()->Animator().SetHasSmilAnimation();
+ SVGDocumentExtensions::ServiceWebAnimationsOnAnimationFrame(*document);
+ document->GetDocumentAnimations().UpdateAnimationTimingForAnimationFrame();
}
- GetFrame().AnimateSnapFling(start_time);
- Document* document = GetFrame().GetDocument();
- DCHECK(document);
- if (SVGDocumentExtensions::ServiceSmilOnAnimationFrame(*document))
- GetPage()->Animator().SetHasSmilAnimation();
- SVGDocumentExtensions::ServiceWebAnimationsOnAnimationFrame(*document);
- document->GetDocumentAnimations().UpdateAnimationTimingForAnimationFrame();
- document->ServiceScriptedAnimations(start_time);
+ document->ServiceScriptedAnimations(start_time, can_throttle);
}
void LocalFrameView::ScheduleAnimation(base::TimeDelta delay) {
@@ -3695,6 +3745,13 @@ void LocalFrameView::AttachToLayout() {
parent_view->CanThrottleRendering(),
IsDisplayLocked());
+ // This is to handle a special case: a display:none iframe may have a fully
+ // populated layout tree if it contains an <embed>. In that case, we must
+ // ensure that the embed's compositing layer is properly reattached.
+ // crbug.com/749737 for context.
+ if (auto* layout_view = GetLayoutView())
+ layout_view->Layer()->SetNeedsCompositingInputsUpdate();
+
// We may have updated paint properties in detached frame subtree for
// printing (see UpdateLifecyclePhasesForPrinting()). The paint properties
// may change after the frame is attached.
@@ -3804,10 +3861,8 @@ void LocalFrameView::SetLayoutSizeInternal(const IntSize& size) {
if (!document || !document->IsActive())
return;
document->LayoutViewportWasResized();
- if (frame_->IsMainFrame()) {
+ if (frame_->IsMainFrame())
TextAutosizer::UpdatePageInfoInAllFrames(frame_);
- probe::DidResizeMainFrame(frame_.Get());
- }
}
void LocalFrameView::DidChangeScrollOffset() {
@@ -3922,6 +3977,12 @@ LocalFrameView::DisallowThrottlingScope::DisallowThrottlingScope(
: value_(&frame_view.GetFrame().LocalFrameRoot().View()->allow_throttling_,
false) {}
+PaintController& LocalFrameView::EnsurePaintController() {
+ if (!paint_controller_)
+ paint_controller_ = std::make_unique<PaintController>();
+ return *paint_controller_;
+}
+
bool LocalFrameView::CapturePaintPreview(GraphicsContext& context,
const IntSize& paint_offset) const {
absl::optional<base::UnguessableToken> maybe_embedding_token =
@@ -4023,7 +4084,8 @@ void LocalFrameView::PaintOutsideOfLifecycle(
});
{
- OverriddenCullRectScope force_cull_rect(*this, cull_rect);
+ OverriddenCullRectScope force_cull_rect(*GetLayoutView()->Layer(),
+ cull_rect);
PaintInternal(context, global_paint_flags, cull_rect);
}
@@ -4046,7 +4108,8 @@ void LocalFrameView::PaintContentsOutsideOfLifecycle(
});
{
- OverriddenCullRectScope force_cull_rect(*this, cull_rect);
+ OverriddenCullRectScope force_cull_rect(*GetLayoutView()->Layer(),
+ cull_rect);
FramePainter(*this).PaintContents(context, global_paint_flags, cull_rect);
}
@@ -4058,20 +4121,19 @@ void LocalFrameView::PaintContentsOutsideOfLifecycle(
void LocalFrameView::PaintContentsForTest(const CullRect& cull_rect) {
AllowThrottlingScope allow_throttling(*this);
Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint);
- OverriddenCullRectScope force_cull_rect(*this, cull_rect);
+ OverriddenCullRectScope force_cull_rect(*GetLayoutView()->Layer(), cull_rect);
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
PaintController& paint_controller = EnsurePaintController();
if (GetLayoutView()->Layer()->SelfOrDescendantNeedsRepaint()) {
+ PaintController::CycleScope cycle_scope(paint_controller);
GraphicsContext graphics_context(paint_controller);
Paint(graphics_context, kGlobalPaintNormalPhase, cull_rect);
paint_controller.CommitNewDisplayItems();
}
- paint_controller.FinishCycle();
} else {
GraphicsLayer* graphics_layer =
GetLayoutView()->Layer()->GraphicsLayerBacking();
graphics_layer->PaintForTesting(cull_rect.Rect());
- graphics_layer->GetPaintController().FinishCycle();
}
Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean);
}
@@ -4246,7 +4308,8 @@ void LocalFrameView::CollectAnnotatedRegions(
}
bool LocalFrameView::UpdateViewportIntersectionsForSubtree(
- unsigned parent_flags) {
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>& monotonic_time) {
// 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
@@ -4262,8 +4325,8 @@ bool LocalFrameView::UpdateViewportIntersectionsForSubtree(
// Notify javascript IntersectionObservers
if (IntersectionObserverController* controller =
GetFrame().GetDocument()->GetIntersectionObserverController()) {
- needs_occlusion_tracking |=
- controller->ComputeIntersections(flags, EnsureUkmAggregator());
+ needs_occlusion_tracking |= controller->ComputeIntersections(
+ flags, EnsureUkmAggregator(), monotonic_time);
}
intersection_observation_state_ = kNotNeeded;
}
@@ -4278,14 +4341,16 @@ bool LocalFrameView::UpdateViewportIntersectionsForSubtree(
for (Frame* child = frame_->Tree().FirstChild(); child;
child = child->Tree().NextSibling()) {
needs_occlusion_tracking |=
- child->View()->UpdateViewportIntersectionsForSubtree(flags);
+ child->View()->UpdateViewportIntersectionsForSubtree(flags,
+ monotonic_time);
}
for (PortalContents* portal :
DocumentPortals::From(*frame_->GetDocument()).GetPortals()) {
if (Frame* frame = portal->GetFrame()) {
needs_occlusion_tracking |=
- frame->View()->UpdateViewportIntersectionsForSubtree(flags);
+ frame->View()->UpdateViewportIntersectionsForSubtree(flags,
+ monotonic_time);
}
}
@@ -4352,17 +4417,24 @@ void LocalFrameView::RenderThrottlingStatusChanged() {
// Ensure we'll recompute viewport intersection for the frame subtree during
// the scheduled visual update.
SetIntersectionObservationState(kRequired);
- // When a frame is throttled, we typically delete its previous painted
- // output, so it will need to be repainted, even if nothing else has
- // changed.
- if (LayoutView* layout_view = GetLayoutView())
- layout_view->Layer()->SetNeedsRepaint();
} else if (GetFrame().IsLocalRoot()) {
// By this point, every frame in the local frame tree has become throttled,
// so painting the tree should just clear the previous painted output.
DCHECK(!IsUpdatingLifecycle());
AllowThrottlingScope allow_throtting(*this);
- RunPaintLifecyclePhase();
+ RunPaintLifecyclePhase(PaintBenchmarkMode::kNormal);
+ }
+
+ // When a frame is throttled, we typically delete its previous painted
+ // output, so it will need to be repainted, even if nothing else has
+ // changed.
+ if (LayoutView* layout_view = GetLayoutView())
+ layout_view->Layer()->SetNeedsRepaint();
+ // The painted output of the frame may be included in a cached subsequence
+ // associated with the embedding document, so invalidate the owner.
+ if (auto* owner = GetFrame().OwnerLayoutObject()) {
+ if (PaintLayer* owner_layer = owner->Layer())
+ owner_layer->SetNeedsRepaint();
}
#if DCHECK_IS_ON()
@@ -4432,6 +4504,9 @@ unsigned LocalFrameView::GetIntersectionObservationFlags(
flags |= IntersectionObservation::kReportImplicitRootBounds;
}
+ if (!target_frame.IsLocalRoot() && !target_frame.OwnerLayoutObject())
+ flags |= IntersectionObservation::kAncestorFrameIsDetachedFromLayout;
+
// Observers with explicit roots only need to be checked on the same frame,
// since in this case target and root must be in the same document.
if (intersection_observation_state_ != kNotNeeded) {
@@ -4537,7 +4612,6 @@ void LocalFrameView::BeginLifecycleUpdates() {
if (!GetFrame().IsMainFrame())
return;
- Document* document = GetFrame().GetDocument();
ChromeClient& chrome_client = GetFrame().GetPage()->GetChromeClient();
// Determine if we want to defer commits to the compositor once lifecycle
@@ -4548,16 +4622,22 @@ void LocalFrameView::BeginLifecycleUpdates() {
// over HTTP/HTTPs. And only defer commits once. This method gets called
// multiple times, and we do not want to defer a second time if we have
// already done so once and resumed commits already.
- if (document && document->DeferredCompositorCommitIsAllowed() &&
- !have_deferred_commits_) {
- chrome_client.StartDeferringCommits(
- GetFrame(), base::TimeDelta::FromMilliseconds(kCommitDelayDefaultInMs));
+ if (WillDoPaintHoldingForFCP()) {
have_deferred_commits_ = true;
+ chrome_client.StartDeferringCommits(
+ GetFrame(), base::TimeDelta::FromMilliseconds(kCommitDelayDefaultInMs),
+ cc::PaintHoldingReason::kFirstContentfulPaint);
}
chrome_client.BeginLifecycleUpdates(GetFrame());
}
+bool LocalFrameView::WillDoPaintHoldingForFCP() const {
+ Document* document = GetFrame().GetDocument();
+ return document && document->DeferredCompositorCommitIsAllowed() &&
+ !have_deferred_commits_;
+}
+
void LocalFrameView::SetInitialViewportSize(const IntSize& viewport_size) {
if (viewport_size == initial_viewport_size_)
return;
@@ -4687,7 +4767,17 @@ LocalFrameUkmAggregator& LocalFrameView::EnsureUkmAggregator() {
void LocalFrameView::OnFirstContentfulPaint() {
GetPage()->GetChromeClient().StopDeferringCommits(
*frame_, cc::PaintHoldingCommitTrigger::kFirstContentfulPaint);
- EnsureUkmAggregator().DidReachFirstContentfulPaint(frame_->IsMainFrame());
+ const bool is_main_frame = frame_->IsMainFrame();
+ if (is_main_frame) {
+ UMA_HISTOGRAM_TIMES("Renderer.Font.PrimaryFont.FCP",
+ FontPerformance::PrimaryFontTime());
+ UMA_HISTOGRAM_TIMES("Renderer.Font.PrimaryFont.FCP.Style",
+ FontPerformance::PrimaryFontTimeInStyle());
+ UMA_HISTOGRAM_TIMES("Renderer.Font.SystemFallback.FCP",
+ FontPerformance::SystemFallbackFontTime());
+ FontPerformance::DidReachFirstContentfulPaint();
+ }
+ EnsureUkmAggregator().DidReachFirstContentfulPaint(is_main_frame);
}
void LocalFrameView::RegisterForLifecycleNotifications(
@@ -4866,6 +4956,8 @@ PaintLayer* LocalFrameView::GetFullScreenOverlayLayer() const {
void LocalFrameView::RunPaintBenchmark(int repeat_count,
cc::PaintBenchmarkResult& result) {
DCHECK_EQ(Lifecycle().GetState(), DocumentLifecycle::kPaintClean);
+ DCHECK(GetFrame().IsLocalRoot());
+ AllowThrottlingScope allow_throttling(*this);
auto run_benchmark = [&](PaintBenchmarkMode mode) -> double {
constexpr int kTimeCheckInterval = 1;
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 5836ce195ef..92b108c62f6 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
@@ -32,7 +32,7 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/document_transition/document_transition.h"
@@ -48,7 +48,6 @@
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
-#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -94,6 +93,8 @@ class LayoutView;
class LocalFrame;
class MobileFriendlinessChecker;
class Page;
+class PaintArtifactCompositor;
+class PaintController;
class PaintLayer;
class PaintLayerScrollableArea;
class PaintTimingDetector;
@@ -111,6 +112,9 @@ struct IntrinsicSizingInfo;
struct MobileFriendliness;
struct PhysicalOffset;
struct PhysicalRect;
+struct PreCompositedLayerInfo;
+
+enum class PaintBenchmarkMode;
typedef uint64_t DOMTimeStamp;
using LayerTreeFlags = unsigned;
@@ -182,6 +186,9 @@ class CORE_EXPORT LocalFrameView final
void ScheduleOrthogonalWritingModeRootsForLayout();
void MarkOrthogonalWritingModeRootsForLayout();
+ // Returns true if commits will be deferred for first contentful paint.
+ bool WillDoPaintHoldingForFCP() const;
+
unsigned LayoutCountForTesting() const { return layout_count_for_testing_; }
unsigned LifecycleUpdateCountForTesting() const {
return lifecycle_update_count_for_testing_;
@@ -801,11 +808,7 @@ class CORE_EXPORT LocalFrameView final
friend class AllowThrottlingScope;
friend class DisallowThrottlingScope;
- PaintController& EnsurePaintController() {
- if (!paint_controller_)
- paint_controller_ = std::make_unique<PaintController>();
- return *paint_controller_;
- }
+ PaintController& EnsurePaintController();
// A paint preview is a copy of the visual contents of a webpage recorded as
// a set of SkPictures. This sends an IPC to the browser to trigger a
@@ -852,7 +855,7 @@ class CORE_EXPORT LocalFrameView final
DocumentLifecycle::LifecycleState target_state);
bool RunPrePaintLifecyclePhase(
DocumentLifecycle::LifecycleState target_state);
- void RunPaintLifecyclePhase(PaintBenchmarkMode = PaintBenchmarkMode::kNormal);
+ void RunPaintLifecyclePhase(PaintBenchmarkMode);
void UpdateStyleAndLayoutIfNeededRecursive();
bool UpdateStyleAndLayoutInternal();
@@ -860,7 +863,7 @@ class CORE_EXPORT LocalFrameView final
void PerformLayout();
void PerformPostLayoutTasks(bool view_size_changed);
- bool PaintTree(PaintBenchmarkMode);
+ bool PaintTree(PaintBenchmarkMode, PaintController::CycleScope&);
void PushPaintArtifactToCompositor(bool repainted);
void ClearLayoutSubtreeRootsAndMarkContainingBlocks();
@@ -926,7 +929,9 @@ class CORE_EXPORT LocalFrameView final
template <typename Function>
void ForAllRemoteFrameViews(const Function&);
- bool UpdateViewportIntersectionsForSubtree(unsigned parent_flags) override;
+ bool UpdateViewportIntersectionsForSubtree(
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>& monotonic_time) override;
void DeliverSynchronousIntersectionObservations();
bool RunScrollTimelineSteps();
@@ -944,7 +949,9 @@ class CORE_EXPORT LocalFrameView final
bool RunPostLayoutIntersectionObserverSteps();
// This is a recursive helper for determining intersection observations which
// need to happen in post-layout.
- void ComputePostLayoutIntersections(unsigned parent_flags);
+ void ComputePostLayoutIntersections(
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>& monotonic_time);
// Returns true if the root object was laid out. Returns false if the layout
// was prevented (e.g. by ancestor display-lock) or not needed.
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 83a0cc1bfdc..4e0f36db473 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
@@ -8,6 +8,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/html/html_anchor_element.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/location.idl b/chromium/third_party/blink/renderer/core/frame/location.idl
index dd572ee0998..de03a7204b9 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.idl
+++ b/chromium/third_party/blink/renderer/core/frame/location.idl
@@ -46,7 +46,7 @@
// TODO(foolip): |ancestorOrigins| should have [LegacyUnforgeable, SameObject].
[LegacyUnforgeable] readonly attribute DOMStringList ancestorOrigins;
- [Affects=Nothing, SetterCallWith=Isolate, CrossOrigin=Setter, RaisesException=Setter, LegacyUnforgeable] attribute USVString href;
+ [SetterCallWith=Isolate, CrossOrigin=Setter, RaisesException=Setter, LegacyUnforgeable] attribute USVString href;
// TODO(yukishiino): Use [LegacyUnforgeable] stringifier instead of toString.
[LegacyUnforgeable] DOMString toString();
[MeasureAs=LocationOrigin, LegacyUnforgeable] readonly attribute USVString origin;
diff --git a/chromium/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc b/chromium/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc
index 768fe10160a..6a3d8f75523 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc
@@ -53,7 +53,7 @@ bool NavigationRateLimiter::CanProceed() {
mojom::ConsoleMessageSource::kJavaScript,
mojom::ConsoleMessageLevel::kWarning,
"Throttling navigation to prevent the browser from hanging. See "
- "https://crbug.com/882238. Command line switch "
+ "https://crbug.com/1038223. Command line switch "
"--disable-ipc-flooding-protection can be used to bypass the "
"protection"));
}
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator.cc b/chromium/third_party/blink/renderer/core/frame/navigator.cc
index ff2573f855a..be67aa399f5 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator.cc
@@ -59,7 +59,7 @@ String Navigator::vendorSub() const {
String Navigator::platform() const {
// TODO(955620): Consider changing devtools overrides to only allow overriding
// the platform with a frozen platform to distinguish between
- // mobile and desktop when FreezeUserAgent is enabled.
+ // mobile and desktop when ReduceUserAgent is enabled.
if (!DomWindow())
return NavigatorID::platform();
const String& platform_override =
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_id.cc b/chromium/third_party/blink/renderer/core/frame/navigator_id.cc
index 01a5a61552d..a19e3fbe376 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_id.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_id.cc
@@ -65,13 +65,15 @@ String NavigatorID::platform() const {
// If the User-Agent string is frozen, platform should be a value
// matching the frozen string per https://github.com/WICG/ua-client-hints. See
// content::frozen_user_agent_strings.
- if (base::FeatureList::IsEnabled(features::kFreezeUserAgent)) {
+ if (base::FeatureList::IsEnabled(features::kReduceUserAgent)) {
#if defined(OS_ANDROID)
- // Matches the frozen mobile User-Agent string (arbitrary Android device).
- return "Linux armv8l";
-#else
- // Matches the frozen desktop User-Agent string (Windows).
+ return "Linux armv81";
+#elif defined(OS_MAC)
+ return "MacIntel";
+#elif defined(OS_WIN)
return "Win32";
+#else
+ return "Linux x86_64";
#endif
}
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_id.idl b/chromium/third_party/blink/renderer/core/frame/navigator_id.idl
index c7217f80a00..ed29e5095a3 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_id.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_id.idl
@@ -38,5 +38,5 @@ interface mixin NavigatorID {
readonly attribute DOMString product; // constant "Gecko"
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=22555
// boolean taintEnabled(); // constant false
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=NavigatorUserAgent] readonly attribute DOMString userAgent;
+ [HighEntropy=Direct, MeasureAs=NavigatorUserAgent] readonly attribute DOMString userAgent;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_language.cc b/chromium/third_party/blink/renderer/core/frame/navigator_language.cc
index 14883715ff9..ceb4feee0e7 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_language.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_language.cc
@@ -18,7 +18,7 @@ Vector<String> ParseAndSanitize(const String& accept_languages) {
// Sanitizing tokens. We could do that more extensively but we should assume
// that the accept languages are already sane and support BCP47. It is
// likely a waste of time to make sure the tokens matches that spec here.
- for (size_t i = 0; i < languages.size(); ++i) {
+ for (wtf_size_t i = 0; i < languages.size(); ++i) {
String& token = languages[i];
token = token.StripWhiteSpace();
if (token.length() >= 3 && token[2] == '_')
@@ -56,7 +56,7 @@ AtomicString NavigatorLanguage::SerializeLanguagesForClientHintHeader() {
EnsureUpdatedLanguage();
StringBuilder builder;
- for (size_t i = 0; i < languages_.size(); i++) {
+ for (wtf_size_t i = 0; i < languages_.size(); i++) {
if (i)
builder.Append(", ");
builder.Append('"');
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc b/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc
index 3d03eb2f8df..269e267b9a9 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc
@@ -28,6 +28,7 @@ NavigatorUAData* NavigatorUA::userAgentData() {
ua_data->SetArchitecture(String::FromUTF8(metadata.architecture));
ua_data->SetModel(String::FromUTF8(metadata.model));
ua_data->SetUAFullVersion(String::FromUTF8(metadata.full_version));
+ ua_data->SetBitness(String::FromUTF8(metadata.bitness));
MaybeRecordMetrics(*ua_data);
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc
index a696f0c804a..aad450b37ff 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc
@@ -84,6 +84,10 @@ void NavigatorUAData::SetUAFullVersion(const String& ua_full_version) {
ua_full_version_ = ua_full_version;
}
+void NavigatorUAData::SetBitness(const String& bitness) {
+ bitness_ = bitness;
+}
+
bool NavigatorUAData::mobile() const {
if (GetExecutionContext()) {
return is_mobile_;
@@ -99,6 +103,13 @@ const HeapVector<Member<NavigatorUABrandVersion>>& NavigatorUAData::brands()
return empty_brand_set_;
}
+const String& NavigatorUAData::platform() const {
+ if (GetExecutionContext()) {
+ return platform_;
+ }
+ return WTF::g_empty_string;
+}
+
ScriptPromise NavigatorUAData::getHighEntropyValues(
ScriptState* script_state,
Vector<String>& hints) const {
@@ -113,6 +124,8 @@ ScriptPromise NavigatorUAData::getHighEntropyValues(
IdentifiableSurface::Type::kNavigatorUAData_GetHighEntropyValues);
UADataValues* values = MakeGarbageCollected<UADataValues>();
for (const String& hint : hints) {
+ values->setBrands(brand_set_);
+ values->setMobile(is_mobile_);
if (hint == "platform") {
values->setPlatform(platform_);
MaybeRecordMetric(record_identifiability, hint, platform_,
@@ -133,6 +146,10 @@ ScriptPromise NavigatorUAData::getHighEntropyValues(
values->setUaFullVersion(ua_full_version_);
MaybeRecordMetric(record_identifiability, hint, ua_full_version_,
execution_context);
+ } else if (hint == "bitness") {
+ values->setBitness(bitness_);
+ MaybeRecordMetric(record_identifiability, hint, bitness_,
+ execution_context);
}
}
@@ -146,6 +163,13 @@ ScriptPromise NavigatorUAData::getHighEntropyValues(
return promise;
}
+ScriptValue NavigatorUAData::toJSON(ScriptState* script_state) const {
+ V8ObjectBuilder builder(script_state);
+ builder.Add("brands", brands());
+ builder.Add("mobile", mobile());
+ return builder.GetScriptValue();
+}
+
void NavigatorUAData::Trace(Visitor* visitor) const {
visitor->Trace(brand_set_);
visitor->Trace(empty_brand_set_);
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h
index 986c9cf9628..9781d79ab3a 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h
@@ -8,6 +8,7 @@
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_navigator_ua_brand_version.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -33,11 +34,14 @@ class NavigatorUAData : public ScriptWrappable, ExecutionContextClient {
void SetArchitecture(const String& architecture);
void SetModel(const String& model);
void SetUAFullVersion(const String& uaFullVersion);
+ void SetBitness(const String& bitness);
// IDL implementation
const HeapVector<Member<NavigatorUABrandVersion>>& brands() const;
bool mobile() const;
+ const String& platform() const;
ScriptPromise getHighEntropyValues(ScriptState*, Vector<String>&) const;
+ ScriptValue toJSON(ScriptState*) const;
void Trace(Visitor* visitor) const final;
@@ -50,6 +54,7 @@ class NavigatorUAData : public ScriptWrappable, ExecutionContextClient {
String architecture_;
String model_;
String ua_full_version_;
+ String bitness_;
void AddBrandVersion(const String& brand, const String& version);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl
index 17d29118034..018b84e87ab 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl
@@ -10,5 +10,7 @@
] interface NavigatorUAData {
readonly attribute FrozenArray<NavigatorUABrandVersion> brands;
readonly attribute boolean mobile;
+ readonly attribute DOMString platform;
[CallWith=ScriptState] Promise<UADataValues> getHighEntropyValues(sequence<DOMString> hints);
+ [CallWith=ScriptState] object toJSON();
};
diff --git a/chromium/third_party/blink/renderer/core/frame/opened_frame_tracker.h b/chromium/third_party/blink/renderer/core/frame/opened_frame_tracker.h
index 6c98ad5f200..84112555f87 100644
--- a/chromium/third_party/blink/renderer/core/frame/opened_frame_tracker.h
+++ b/chromium/third_party/blink/renderer/core/frame/opened_frame_tracker.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OPENED_FRAME_TRACKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OPENED_FRAME_TRACKER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -22,6 +21,8 @@ class OpenedFrameTracker {
public:
OpenedFrameTracker();
+ OpenedFrameTracker(const OpenedFrameTracker&) = delete;
+ OpenedFrameTracker& operator=(const OpenedFrameTracker&) = delete;
~OpenedFrameTracker();
void Trace(Visitor*) const;
@@ -35,8 +36,6 @@ class OpenedFrameTracker {
private:
HeapHashSet<WeakMember<Frame>> opened_frames_;
-
- DISALLOW_COPY_AND_ASSIGN(OpenedFrameTracker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h b/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
index 5e46f8f09be..205239a99e6 100644
--- a/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
+++ b/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_
-#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -49,6 +48,9 @@ class LocalFrame;
class CORE_EXPORT OverlayInterstitialAdDetector {
public:
OverlayInterstitialAdDetector() = default;
+ OverlayInterstitialAdDetector(const OverlayInterstitialAdDetector&) = delete;
+ OverlayInterstitialAdDetector& operator=(
+ const OverlayInterstitialAdDetector&) = delete;
~OverlayInterstitialAdDetector() = default;
void MaybeFireDetection(LocalFrame* main_frame);
@@ -85,8 +87,6 @@ class CORE_EXPORT OverlayInterstitialAdDetector {
bool popup_detected_ = false;
bool popup_ad_detected_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(OverlayInterstitialAdDetector);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/page_dismissal_scope.h b/chromium/third_party/blink/renderer/core/frame/page_dismissal_scope.h
index 0981de5e11c..de2c1c7626e 100644
--- a/chromium/third_party/blink/renderer/core/frame/page_dismissal_scope.h
+++ b/chromium/third_party/blink/renderer/core/frame/page_dismissal_scope.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_PAGE_DISMISSAL_SCOPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_PAGE_DISMISSAL_SCOPE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -16,11 +15,11 @@ class CORE_EXPORT PageDismissalScope final {
public:
PageDismissalScope();
+ PageDismissalScope(const PageDismissalScope&) = delete;
+ PageDismissalScope& operator=(const PageDismissalScope&) = delete;
~PageDismissalScope();
static bool IsActive();
-
- DISALLOW_COPY_AND_ASSIGN(PageDismissalScope);
};
} // namespace blink
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 67f1a24b162..8a5290af69e 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
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_script_execution_callback.h"
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 bd0b12ff0ca..1ca549560e5 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
@@ -85,11 +85,16 @@ void PerformanceMonitor::Subscribe(Violation violation,
base::TimeDelta threshold,
Client* client) {
DCHECK(violation < kAfterLast);
- ClientThresholds* client_thresholds = subscriptions_.at(violation);
- if (!client_thresholds) {
+ ClientThresholds* client_thresholds = nullptr;
+
+ auto it = subscriptions_.find(violation);
+ if (it == subscriptions_.end()) {
client_thresholds = MakeGarbageCollected<ClientThresholds>();
subscriptions_.Set(violation, client_thresholds);
+ } else {
+ client_thresholds = it->value;
}
+
client_thresholds->Set(client, threshold);
UpdateInstrumentation();
}
@@ -300,13 +305,18 @@ void PerformanceMonitor::DidProcessTask(base::TimeTicks start_time,
if (!thresholds_[kLongTask].is_zero()) {
base::TimeDelta task_time = end_time - start_time;
if (task_time > thresholds_[kLongTask]) {
- ClientThresholds* client_thresholds = subscriptions_.at(kLongTask);
- for (const auto& it : *client_thresholds) {
- if (it.value < task_time) {
- it.key->ReportLongTask(
- start_time, end_time,
- task_has_multiple_contexts_ ? nullptr : task_execution_context_,
- task_has_multiple_contexts_);
+ auto subscriptions_it = subscriptions_.find(kLongTask);
+ if (subscriptions_it != subscriptions_.end()) {
+ ClientThresholds* client_thresholds = subscriptions_it->value;
+ DCHECK(client_thresholds);
+
+ for (const auto& it : *client_thresholds) {
+ if (it.value < task_time) {
+ it.key->ReportLongTask(
+ start_time, end_time,
+ task_has_multiple_contexts_ ? nullptr : task_execution_context_,
+ task_has_multiple_contexts_);
+ }
}
}
}
@@ -333,11 +343,14 @@ void PerformanceMonitor::InnerReportGenericViolation(
const String& text,
base::TimeDelta time,
std::unique_ptr<SourceLocation> location) {
- ClientThresholds* client_thresholds = subscriptions_.at(violation);
- if (!client_thresholds)
+ auto subscriptions_it = subscriptions_.find(violation);
+ if (subscriptions_it == subscriptions_.end())
return;
+
if (!location)
location = SourceLocation::Capture(context);
+
+ ClientThresholds* client_thresholds = subscriptions_it->value;
for (const auto& it : *client_thresholds) {
if (it.value < time)
it.key->ReportGenericViolation(violation, text, time, location.get());
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 46205d7cfd1..3763e1c0f07 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_PERFORMANCE_MONITOR_H_
#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/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -103,6 +102,8 @@ class CORE_EXPORT PerformanceMonitor final
void Shutdown();
PerformanceMonitor(LocalFrame*, v8::Isolate*);
+ PerformanceMonitor(const PerformanceMonitor&) = delete;
+ PerformanceMonitor& operator=(const PerformanceMonitor&) = delete;
~PerformanceMonitor() override;
virtual void Trace(Visitor*) const;
@@ -163,8 +164,6 @@ class CORE_EXPORT PerformanceMonitor final
typename DefaultHash<size_t>::Hash,
WTF::UnsignedWithZeroKeyHashTraits<size_t>>
subscriptions_;
-
- DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor);
};
} // namespace blink
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 fe83d0bd533..81a97d01d3e 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
@@ -26,6 +26,9 @@ class CORE_EXPORT PictureInPictureController
public:
static const char kSupplementName[];
+ PictureInPictureController(const PictureInPictureController&) = delete;
+ PictureInPictureController& operator=(const PictureInPictureController&) =
+ delete;
virtual ~PictureInPictureController() = default;
// Should be called before any other call to make sure a document is attached.
@@ -87,8 +90,6 @@ class CORE_EXPORT PictureInPictureController
// It is protected so that clients use the static method
// IsElementInPictureInPicture() that avoids creating the controller.
virtual bool IsPictureInPictureElement(const Element*) const = 0;
-
- DISALLOW_COPY_AND_ASSIGN(PictureInPictureController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/policy_container.cc b/chromium/third_party/blink/renderer/core/frame/policy_container.cc
index b841a9011b4..2d0d82f983e 100644
--- a/chromium/third_party/blink/renderer/core/frame/policy_container.cc
+++ b/chromium/third_party/blink/renderer/core/frame/policy_container.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/frame/policy_container.h"
+
+#include "base/macros.h"
#include "third_party/blink/renderer/core/frame/csp/conversion_util.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_dom_window.cc b/chromium/third_party/blink/renderer/core/frame/remote_dom_window.cc
index 12f154fc6b2..2b0f52d31a9 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_dom_window.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_dom_window.cc
@@ -31,10 +31,7 @@ void RemoteDOMWindow::FrameDetached() {
DisconnectFromFrame();
}
-void RemoteDOMWindow::SchedulePostMessage(
- MessageEvent* event,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source) {
+void RemoteDOMWindow::SchedulePostMessage(PostedMessage* posted_message) {
// To match same-process behavior, the IPC to forward postMessage
// cross-process should only be sent after the current script finishes
// running, to preserve relative ordering of IPCs. See
@@ -45,27 +42,27 @@ void RemoteDOMWindow::SchedulePostMessage(
// should also be observable by the target frame prior to receiving the
// postMessage. We might consider forcing layout in ForwardPostMessage or
// further delaying postMessage forwarding until after the next BeginFrame.
- source->GetTaskRunner(TaskType::kPostedMessage)
- ->PostTask(FROM_HERE,
- WTF::Bind(&RemoteDOMWindow::ForwardPostMessage,
- WrapPersistent(this), WrapPersistent(event),
- std::move(target), WrapPersistent(source)));
+ posted_message->source
+ ->GetTaskRunner(TaskType::kInternalPostMessageForwarding)
+ ->PostTask(FROM_HERE, WTF::Bind(&RemoteDOMWindow::ForwardPostMessage,
+ WrapPersistent(this),
+ WrapPersistent(posted_message)));
}
-void RemoteDOMWindow::ForwardPostMessage(
- MessageEvent* event,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source) {
+void RemoteDOMWindow::ForwardPostMessage(PostedMessage* posted_message) {
// If the target frame was detached after the message was scheduled,
// don't deliver the message.
if (!GetFrame())
return;
- absl::optional<base::UnguessableToken> agent_cluster;
- if (event->IsLockedToAgentCluster())
- agent_cluster = source->GetAgentClusterID();
- GetFrame()->ForwardPostMessage(event, agent_cluster, std::move(target),
- source->GetFrame());
+ LocalFrame* source_frame = posted_message->source->GetFrame();
+ scoped_refptr<const SecurityOrigin> source_origin =
+ posted_message->source_origin;
+ scoped_refptr<const SecurityOrigin> target_origin =
+ posted_message->target_origin;
+ GetFrame()->ForwardPostMessage(
+ std::move(*posted_message).ToBlinkTransferableMessage(), source_frame,
+ std::move(source_origin), std::move(target_origin));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_dom_window.h b/chromium/third_party/blink/renderer/core/frame/remote_dom_window.h
index 109548b3188..4787e12bbc2 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_dom_window.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_dom_window.h
@@ -30,9 +30,7 @@ class RemoteDOMWindow final : public DOMWindow {
protected:
// Protected DOMWindow overrides:
- void SchedulePostMessage(MessageEvent*,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source) override;
+ void SchedulePostMessage(PostedMessage*) override;
private:
// Intentionally private to prevent redundant checks when the type is
@@ -40,9 +38,7 @@ class RemoteDOMWindow final : public DOMWindow {
bool IsLocalDOMWindow() const override { return false; }
bool IsRemoteDOMWindow() const override { return true; }
- void ForwardPostMessage(MessageEvent*,
- scoped_refptr<const SecurityOrigin> target,
- LocalDOMWindow* source);
+ void ForwardPostMessage(PostedMessage*);
};
template <>
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 83560e3db3e..b5b269409e1 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/referrer.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
@@ -62,6 +63,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "ui/base/window_open_disposition.h"
namespace blink {
@@ -218,11 +220,8 @@ void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
window->GetFrame() ? window->GetFrame()->GetContentSettingsClient()
: nullptr);
- // Navigations in portal contexts do not create back/forward entries.
- if (GetPage()->InsidePortal() &&
- frame_load_type == WebFrameLoadType::kStandard) {
+ if (NavigationShouldReplaceCurrentHistoryEntry(frame_load_type))
frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
- }
bool is_opener_navigation = false;
bool initiator_frame_has_download_sandbox_flag = false;
@@ -316,6 +315,15 @@ void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
GetRemoteFrameHostRemote().OpenURL(std::move(params));
}
+bool RemoteFrame::NavigationShouldReplaceCurrentHistoryEntry(
+ WebFrameLoadType frame_load_type) const {
+ // Portal contexts do not create back/forward entries.
+ // TODO(https:/crbug.com/1197384, https://crbug.com/1190644): We may want to
+ // support a prerender in RemoteFrame.
+ return frame_load_type == WebFrameLoadType::kStandard &&
+ GetPage()->InsidePortal();
+}
+
bool RemoteFrame::DetachImpl(FrameDetachType type) {
PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
@@ -362,15 +370,6 @@ void RemoteFrame::SetCcLayer(scoped_refptr<cc::Layer> layer,
HTMLFrameOwnerElement* owner = To<HTMLFrameOwnerElement>(Owner());
owner->SetNeedsCompositingUpdate();
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // New layers for remote frames are controlled by Blink's embedder.
- // To ensure the new surface is painted, we need to repaint the frame
- // owner's PaintLayer.
- LayoutBoxModelObject* layout_object = owner->GetLayoutBoxModelObject();
- if (layout_object && layout_object->Layer())
- layout_object->Layer()->SetNeedsRepaint();
- }
-
// Schedule an animation so that a new frame is produced with the updated
// layer, otherwise this local root's visible content may not be up to date.
owner->GetDocument().GetFrame()->View()->ScheduleAnimation();
@@ -487,22 +486,24 @@ void RemoteFrame::CreateView() {
}
void RemoteFrame::ForwardPostMessage(
- MessageEvent* message_event,
- absl::optional<base::UnguessableToken> cluster_id,
- scoped_refptr<const SecurityOrigin> target_security_origin,
- LocalFrame* source_frame) {
+ BlinkTransferableMessage transferable_message,
+ LocalFrame* source_frame,
+ scoped_refptr<const SecurityOrigin> source_security_origin,
+ scoped_refptr<const SecurityOrigin> target_security_origin) {
absl::optional<blink::LocalFrameToken> source_token;
if (source_frame)
source_token = source_frame->GetLocalFrameToken();
- String source_origin = message_event->origin();
- String target_origin = g_empty_string;
- if (target_security_origin)
- target_origin = target_security_origin->ToString();
+ String source_origin = source_security_origin
+ ? source_security_origin->ToString()
+ : g_empty_string;
+ String target_origin = target_security_origin
+ ? target_security_origin->ToString()
+ : g_empty_string;
- GetRemoteFrameHostRemote().RouteMessageEvent(
- source_token, source_origin, target_origin,
- BlinkTransferableMessage::FromMessageEvent(message_event, cluster_id));
+ GetRemoteFrameHostRemote().RouteMessageEvent(source_token, source_origin,
+ target_origin,
+ std::move(transferable_message));
}
mojom::blink::RemoteFrameHost& RemoteFrame::GetRemoteFrameHostRemote() {
@@ -618,9 +619,12 @@ void RemoteFrame::SetReplicatedOrigin(
}
}
-void RemoteFrame::SetReplicatedAdFrameType(
- mojom::blink::AdFrameType ad_frame_type) {
- ad_frame_type_ = ad_frame_type;
+bool RemoteFrame::IsAdSubframe() const {
+ return is_ad_subframe_;
+}
+
+void RemoteFrame::SetReplicatedIsAdSubframe(bool is_ad_subframe) {
+ is_ad_subframe_ = is_ad_subframe;
}
void RemoteFrame::SetReplicatedName(const String& name,
@@ -687,7 +691,7 @@ void RemoteFrame::SetEmbeddingToken(
}
void RemoteFrame::SetPageFocus(bool is_focused) {
- static_cast<WebViewImpl*>(WebFrame::FromCoreFrame(this)->View())
+ To<WebViewImpl>(WebFrame::FromCoreFrame(this)->View())
->SetPageFocus(is_focused);
}
@@ -744,7 +748,7 @@ void RemoteFrame::ScrollRectToVisible(
// view on Android which also requires an automatic zoom into legible scale.
// This is handled by main frame's WebView.
WebViewImpl* web_view =
- static_cast<WebViewImpl*>(WebFrame::FromCoreFrame(this)->View());
+ To<WebViewImpl>(WebFrame::FromCoreFrame(this)->View());
web_view->ZoomAndScrollToFocusedEditableElementRect(
element_bounds_in_document, caret_bounds_in_document, true);
}
@@ -791,7 +795,7 @@ void RemoteFrame::DidSetFramePolicyHeaders(
// ParsedPermissionsPolicy to operate over Vector
ParsedPermissionsPolicy parsed_permissions_policy_copy(
parsed_permissions_policy.size());
- for (size_t i = 0; i < parsed_permissions_policy.size(); ++i)
+ for (wtf_size_t i = 0; i < parsed_permissions_policy.size(); ++i)
parsed_permissions_policy_copy[i] = parsed_permissions_policy[i];
SetReplicatedPermissionsPolicyHeader(parsed_permissions_policy_copy);
}
@@ -886,6 +890,11 @@ const viz::LocalSurfaceId& RemoteFrame::GetLocalSurfaceId() const {
return parent_local_surface_id_allocator_->GetCurrentLocalSurfaceId();
}
+void RemoteFrame::SetCcLayerForTesting(scoped_refptr<cc::Layer> layer,
+ bool is_surface_layer) {
+ SetCcLayer(layer, is_surface_layer);
+}
+
viz::FrameSinkId RemoteFrame::GetFrameSinkId() {
return frame_sink_id_;
}
@@ -1073,7 +1082,7 @@ void RemoteFrame::SetViewportIntersection(
intersection_state.Clone(), visual_properties);
}
-void RemoteFrame::DidChangeScreenInfo(const ScreenInfo& screen_info) {
+void RemoteFrame::DidChangeScreenInfo(const display::ScreenInfo& screen_info) {
pending_visual_properties_.screen_info = screen_info;
SynchronizeVisualProperties();
}
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 0125d2d1d61..47c96720ad0 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.h
@@ -33,14 +33,15 @@ class FrameSinkId;
namespace blink {
class AssociatedInterfaceProvider;
+class ChildFrameCompositingHelper;
class InterfaceRegistry;
class LocalFrame;
-class MessageEvent;
class RemoteFrameClient;
-struct FrameLoadRequest;
-class ChildFrameCompositingHelper;
class WebFrameWidget;
+struct BlinkTransferableMessage;
+struct FrameLoadRequest;
+
// A RemoteFrame is a frame that is possibly hosted outside this process.
class CORE_EXPORT RemoteFrame final : public Frame,
public ChildFrameCompositor,
@@ -85,6 +86,7 @@ class CORE_EXPORT RemoteFrame final : public Frame,
void DidFocus() override;
void AddResourceTimingFromChild(
mojom::blink::ResourceTimingInfoPtr timing) override;
+ bool IsAdSubframe() const override;
// ChildFrameCompositor:
const scoped_refptr<cc::Layer>& GetCcLayer() override;
@@ -95,10 +97,10 @@ class CORE_EXPORT RemoteFrame final : public Frame,
void CreateView();
void ForwardPostMessage(
- MessageEvent* message_event,
- absl::optional<base::UnguessableToken> cluster_id,
- scoped_refptr<const SecurityOrigin> target_security_origin,
- LocalFrame* source_frame);
+ BlinkTransferableMessage,
+ LocalFrame* source_frame,
+ scoped_refptr<const SecurityOrigin> source_security_origin,
+ scoped_refptr<const SecurityOrigin> target_security_origin);
mojom::blink::RemoteFrameHost& GetRemoteFrameHostRemote();
@@ -126,7 +128,7 @@ class CORE_EXPORT RemoteFrame final : public Frame,
void SetViewportIntersection(const mojom::blink::ViewportIntersectionState&);
// Called when the local root's screen info changes.
- void DidChangeScreenInfo(const ScreenInfo& screen_info);
+ void DidChangeScreenInfo(const display::ScreenInfo& screen_info);
// Called when the main frame's zoom level is changed and should be propagated
// to the remote's associated view.
void ZoomLevelChanged(double zoom_level);
@@ -156,8 +158,7 @@ class CORE_EXPORT RemoteFrame final : public Frame,
void SetReplicatedOrigin(
const scoped_refptr<const SecurityOrigin>& origin,
bool is_potentially_trustworthy_unique_origin) override;
- void SetReplicatedAdFrameType(
- mojom::blink::AdFrameType ad_frame_type) override;
+ void SetReplicatedIsAdSubframe(bool is_ad_subframe) override;
void SetReplicatedName(const String& name,
const String& unique_name) override;
void DispatchLoadEventForFrameOwner() override;
@@ -230,6 +231,12 @@ class CORE_EXPORT RemoteFrame final : public Frame,
viz::FrameSinkId GetFrameSinkId();
+ void SetCcLayerForTesting(scoped_refptr<cc::Layer>, bool is_surface_layer);
+
+ // Whether a navigation should replace the current history entry or not.
+ bool NavigationShouldReplaceCurrentHistoryEntry(
+ WebFrameLoadType frame_load_type) const;
+
private:
// Frame protected overrides:
bool DetachImpl(FrameDetachType) override;
@@ -280,6 +287,9 @@ class CORE_EXPORT RemoteFrame final : public Frame,
// Will be nullptr when this RemoteFrame's parent is not a LocalFrame.
std::unique_ptr<ChildFrameCompositingHelper> compositing_helper_;
+ // Whether the frame is considered to be an ad subframe by Ad Tagging.
+ bool is_ad_subframe_;
+
mojo::AssociatedRemote<mojom::blink::RemoteFrameHost>
remote_frame_host_remote_;
mojo::AssociatedReceiver<mojom::blink::RemoteFrame> receiver_{this};
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 40dc21c5a66..81e201c63b4 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_CLIENT_H_
#include "cc/paint/paint_canvas.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/policy_container.mojom-blink-forward.h"
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 9a78fa1e2e7..ede5f2822d7 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
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
#include "third_party/blink/renderer/core/events/wheel_event.h"
+#include "third_party/blink/renderer/core/exported/web_view_impl.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/web_local_frame_impl.h"
@@ -34,7 +35,7 @@ void RemoteFrameClientImpl::Trace(Visitor* visitor) const {
}
bool RemoteFrameClientImpl::InShadowTree() const {
- return web_frame_->InShadowTree();
+ return web_frame_->GetTreeScopeType() == mojom::blink::TreeScopeType::kShadow;
}
void RemoteFrameClientImpl::Detached(FrameDetachType type) {
@@ -65,11 +66,7 @@ void RemoteFrameClientImpl::Detached(FrameDetachType type) {
}
unsigned RemoteFrameClientImpl::BackForwardLength() {
- // TODO(creis,japhet): This method should return the real value for the
- // session history length. For now, return static value for the initial
- // navigation and the subsequent one moving the frame out-of-process.
- // See https://crbug.com/501116.
- return 2;
+ return To<WebViewImpl>(web_frame_->View())->HistoryListLength();
}
AssociatedInterfaceProvider*
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 14fd51bdc3a..5b854e08440 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
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/frame/remote_frame_view.h"
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
@@ -47,8 +47,11 @@ LocalFrameView* RemoteFrameView::ParentFrameView() const {
HTMLFrameOwnerElement* owner = remote_frame_->DeprecatedLocalOwner();
if (owner &&
- owner->OwnerType() == mojom::blink::FrameOwnerElementType::kPortal)
+ (owner->OwnerType() == mojom::blink::FrameOwnerElementType::kPortal ||
+ owner->OwnerType() ==
+ mojom::blink::FrameOwnerElementType::kFencedframe)) {
return owner->GetDocument().GetFrame()->View();
+ }
// |is_attached_| is only set from AttachToLayout(), which ensures that the
// parent is a local frame.
@@ -96,7 +99,8 @@ void RemoteFrameView::DetachFromLayout() {
}
bool RemoteFrameView::UpdateViewportIntersectionsForSubtree(
- unsigned parent_flags) {
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>&) {
UpdateViewportIntersection(parent_flags, needs_occlusion_tracking_);
return needs_occlusion_tracking_;
}
@@ -226,8 +230,8 @@ void RemoteFrameView::UpdateCompositingScaleFactor() {
constexpr float kMinCompositingScaleFactor = 0.25f;
constexpr float kMaxCompositingScaleFactor = 5.0f;
compositing_scale_factor_ =
- base::ClampToRange(compositing_scale_factor_, kMinCompositingScaleFactor,
- kMaxCompositingScaleFactor);
+ base::clamp(compositing_scale_factor_, kMinCompositingScaleFactor,
+ kMaxCompositingScaleFactor);
if (compositing_scale_factor_ != previous_scale_factor)
remote_frame_->SynchronizeVisualProperties();
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 5163732904d..bcd0eeabc4c 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
@@ -51,7 +51,9 @@ class RemoteFrameView final : public GarbageCollected<RemoteFrameView>,
void Hide() override;
void Show() override;
- bool UpdateViewportIntersectionsForSubtree(unsigned parent_flags) override;
+ bool UpdateViewportIntersectionsForSubtree(
+ unsigned parent_flags,
+ absl::optional<base::TimeTicks>&) override;
void SetNeedsOcclusionTracking(bool);
bool NeedsOcclusionTracking() const { return needs_occlusion_tracking_; }
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 c27fcf95bff..bf39e84a1e1 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -155,7 +155,7 @@ void ReportingContext::NotifyInternal(Report* report) {
if (!report_buffer_.Contains(report->type())) {
report_buffer_.insert(
report->type(),
- MakeGarbageCollected<HeapListHashSet<Member<Report>>>());
+ MakeGarbageCollected<HeapLinkedHashSet<Member<Report>>>());
}
report_buffer_.find(report->type())->value->insert(report);
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 51bee8be0e3..c2f7760de52 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.h
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.h
@@ -61,8 +61,8 @@ class CORE_EXPORT ReportingContext : public GarbageCollected<ReportingContext>,
// Send |report| via the Reporting API to |endpoint|.
void SendToReportingAPI(Report* report, const String& endpoint) const;
- HeapListHashSet<Member<blink::ReportingObserver>> observers_;
- HeapHashMap<String, Member<HeapListHashSet<Member<Report>>>> report_buffer_;
+ HeapLinkedHashSet<Member<blink::ReportingObserver>> observers_;
+ HeapHashMap<String, Member<HeapLinkedHashSet<Member<Report>>>> report_buffer_;
Member<ExecutionContext> execution_context_;
// This is declared mutable so that the service endpoint can be cached by
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc b/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc
index 4d7c0bf8651..0e045f63f48 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc
@@ -18,13 +18,13 @@
namespace blink {
class ReportingContextTest : public testing::Test {
+ public:
+ ReportingContextTest(const ReportingContextTest&) = delete;
+ ReportingContextTest& operator=(const ReportingContextTest&) = delete;
+
protected:
ReportingContextTest() = default;
-
~ReportingContextTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ReportingContextTest);
};
class MockReportingServiceProxy : public mojom::blink::ReportingServiceProxy {
diff --git a/chromium/third_party/blink/renderer/core/frame/resize_viewport_anchor.h b/chromium/third_party/blink/renderer/core/frame/resize_viewport_anchor.h
index c4c5ad66e69..717a4150ec5 100644
--- a/chromium/third_party/blink/renderer/core/frame/resize_viewport_anchor.h
+++ b/chromium/third_party/blink/renderer/core/frame/resize_viewport_anchor.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_RESIZE_VIEWPORT_ANCHOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_RESIZE_VIEWPORT_ANCHOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
@@ -24,7 +23,9 @@ class LocalFrameView;
class CORE_EXPORT ResizeViewportAnchor final
: public GarbageCollected<ResizeViewportAnchor> {
public:
- ResizeViewportAnchor(Page& page) : page_(page), scope_count_(0) {}
+ explicit ResizeViewportAnchor(Page& page) : page_(page), scope_count_(0) {}
+ ResizeViewportAnchor(const ResizeViewportAnchor&) = delete;
+ ResizeViewportAnchor& operator=(const ResizeViewportAnchor&) = delete;
class ResizeScope {
STACK_ALLOCATED();
@@ -54,8 +55,6 @@ class CORE_EXPORT ResizeViewportAnchor final
ScrollOffset drift_;
Member<Page> page_;
int scope_count_;
-
- DISALLOW_COPY_AND_ASSIGN(ResizeViewportAnchor);
};
} // namespace blink
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 a4597b551b8..25c21b04cd5 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
@@ -479,6 +479,10 @@ IntSize RootFrameViewport::ContentsSize() const {
return LayoutViewport().ContentsSize();
}
+bool RootFrameViewport::UsesCompositedScrolling() const {
+ return LayoutViewport().UsesCompositedScrolling();
+}
+
bool RootFrameViewport::ShouldScrollOnMainThread() const {
return LayoutViewport().ShouldScrollOnMainThread();
}
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 b70469a11be..d786225eb2b 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
@@ -86,6 +86,7 @@ class CORE_EXPORT RootFrameViewport final
IntSize ClampScrollOffset(const IntSize&) const override;
ScrollOffset ClampScrollOffset(const ScrollOffset&) const override;
IntSize ContentsSize() const override;
+ bool UsesCompositedScrolling() const override;
bool ShouldScrollOnMainThread() const override;
bool ScrollbarsCanBeActive() const override;
bool UserInputScrollable(ScrollbarOrientation) const override;
diff --git a/chromium/third_party/blink/renderer/core/frame/savable_resources.h b/chromium/third_party/blink/renderer/core/frame/savable_resources.h
index d2729f384a5..2f83b6c6287 100644
--- a/chromium/third_party/blink/renderer/core/frame/savable_resources.h
+++ b/chromium/third_party/blink/renderer/core/frame/savable_resources.h
@@ -5,8 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SAVABLE_RESOURCES_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SAVABLE_RESOURCES_H_
-#include "base/macros.h"
-
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.cc b/chromium/third_party/blink/renderer/core/frame/screen.cc
index f46aba9f7b1..07f39f475a3 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.cc
+++ b/chromium/third_party/blink/renderer/core/frame/screen.cc
@@ -28,23 +28,19 @@
#include "third_party/blink/renderer/core/frame/screen.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/event_target_names.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/page/chrome_client.h"
-#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_statics.h"
+#include "ui/display/screen_info.h"
namespace blink {
namespace {
-const ScreenInfo& GetScreenInfo(LocalFrame& frame) {
+const display::ScreenInfo& GetScreenInfo(LocalFrame& frame) {
return frame.GetChromeClient().GetScreenInfo(frame);
}
@@ -53,12 +49,10 @@ const ScreenInfo& GetScreenInfo(LocalFrame& frame) {
Screen::Screen(LocalDOMWindow* window) : ExecutionContextClient(window) {}
int Screen::height() const {
- if (display_)
- return display_->bounds.height();
if (!DomWindow())
return 0;
LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = GetScreenInfo(*frame);
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(
lroundf(screen_info.rect.height() * screen_info.device_scale_factor));
@@ -67,12 +61,10 @@ int Screen::height() const {
}
int Screen::width() const {
- if (display_)
- return display_->bounds.width();
if (!DomWindow())
return 0;
LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = GetScreenInfo(*frame);
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(
lroundf(screen_info.rect.width() * screen_info.device_scale_factor));
@@ -81,8 +73,6 @@ int Screen::width() const {
}
unsigned Screen::colorDepth() const {
- if (display_)
- return display_->color_depth;
if (!DomWindow())
return 0;
return static_cast<unsigned>(GetScreenInfo(*DomWindow()->GetFrame()).depth);
@@ -93,12 +83,10 @@ unsigned Screen::pixelDepth() const {
}
int Screen::availLeft() const {
- if (display_)
- return display_->work_area.x();
if (!DomWindow())
return 0;
LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = GetScreenInfo(*frame);
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(lroundf(screen_info.available_rect.x() *
screen_info.device_scale_factor));
@@ -107,12 +95,10 @@ int Screen::availLeft() const {
}
int Screen::availTop() const {
- if (display_)
- return display_->work_area.y();
if (!DomWindow())
return 0;
LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = GetScreenInfo(*frame);
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(lroundf(screen_info.available_rect.y() *
screen_info.device_scale_factor));
@@ -121,12 +107,10 @@ int Screen::availTop() const {
}
int Screen::availHeight() const {
- if (display_)
- return display_->work_area.height();
if (!DomWindow())
return 0;
LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = GetScreenInfo(*frame);
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(lroundf(screen_info.available_rect.height() *
screen_info.device_scale_factor));
@@ -135,12 +119,10 @@ int Screen::availHeight() const {
}
int Screen::availWidth() const {
- if (display_)
- return display_->work_area.width();
if (!DomWindow())
return 0;
LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = GetScreenInfo(*frame);
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(lroundf(screen_info.available_rect.width() *
screen_info.device_scale_factor));
@@ -176,93 +158,7 @@ bool Screen::isExtended() const {
return GetScreenInfo(*frame).is_extended;
}
-Screen::Screen(display::mojom::blink::DisplayPtr display,
- bool internal,
- bool primary,
- const String& id)
- : ExecutionContextClient(static_cast<ExecutionContext*>(nullptr)),
- display_(std::move(display)),
- internal_(internal),
- primary_(primary),
- id_(id) {}
-
-int Screen::left() const {
- if (display_)
- return display_->bounds.x();
- if (!DomWindow())
- return 0;
- LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
- if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
- return static_cast<int>(
- lroundf(screen_info.rect.x() * screen_info.device_scale_factor));
- }
- return screen_info.rect.x();
-}
-
-int Screen::top() const {
- if (display_)
- return display_->bounds.y();
- if (!DomWindow())
- return 0;
- LocalFrame* frame = DomWindow()->GetFrame();
- const ScreenInfo& screen_info = GetScreenInfo(*frame);
- if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
- return static_cast<int>(
- lroundf(screen_info.rect.y() * screen_info.device_scale_factor));
- }
- return screen_info.rect.y();
-}
-
-bool Screen::internal() const {
- if (display_)
- return internal_.has_value() && internal_.value();
- // TODO(crbug.com/1116528): Move permission-gated attributes to an interface
- // that inherits from Screen: https://github.com/webscreens/window-placement
- NOTIMPLEMENTED_LOG_ONCE();
- return false;
-}
-
-bool Screen::primary() const {
- if (display_)
- return primary_.has_value() && primary_.value();
- // TODO(crbug.com/1116528): Move permission-gated attributes to an interface
- // that inherits from Screen: https://github.com/webscreens/window-placement
- NOTIMPLEMENTED_LOG_ONCE();
- return false;
-}
-
-float Screen::scaleFactor() const {
- if (display_)
- return display_->device_scale_factor;
- if (!DomWindow())
- return 0;
- return GetScreenInfo(*DomWindow()->GetFrame()).device_scale_factor;
-}
-
-const String& Screen::id() const {
- if (display_)
- return id_;
- // TODO(crbug.com/1116528): Move permission-gated attributes to an interface
- // that inherits from Screen: https://github.com/webscreens/window-placement
- NOTIMPLEMENTED_LOG_ONCE();
- return g_empty_string;
-}
-
-bool Screen::touchSupport() const {
- if (display_) {
- return display_->touch_support ==
- display::mojom::blink::TouchSupport::AVAILABLE;
- }
- // TODO(crbug.com/1116528): Move permission-gated attributes to an interface
- // that inherits from Screen: https://github.com/webscreens/window-placement
- NOTIMPLEMENTED_LOG_ONCE();
- return false;
-}
-
int64_t Screen::DisplayId() const {
- if (display_)
- return display_->id;
if (!DomWindow())
return kInvalidDisplayId;
return GetScreenInfo(*DomWindow()->GetFrame()).display_id;
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.h b/chromium/third_party/blink/renderer/core/frame/screen.h
index e0d8200d7dd..6d0fb0edfb2 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.h
+++ b/chromium/third_party/blink/renderer/core/frame/screen.h
@@ -29,16 +29,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SCREEN_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SCREEN_H_
-#include "third_party/abseil-cpp/absl/types/optional.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/execution_context/execution_context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/frame/web_feature_forward.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/supplementable.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "ui/display/mojom/display.mojom-blink.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -72,41 +68,10 @@ class CORE_EXPORT Screen : public EventTargetWithInlineData,
virtual bool isExtended() const;
// An event fired when Screen attributes change.
DEFINE_ATTRIBUTE_EVENT_LISTENER(change, kChange)
- // TODO(crbug.com/1116528): Move permission-gated attributes to an interface
- // that inherits from Screen: https://github.com/webscreens/window-placement
- Screen(display::mojom::blink::DisplayPtr display,
- bool internal,
- bool primary,
- const String& id);
- virtual int left() const;
- virtual int top() const;
- virtual bool internal() const;
- virtual bool primary() const;
- virtual float scaleFactor() const;
- virtual const String& id() const;
- virtual bool touchSupport() const;
// Not web-exposed; for internal usage only.
static constexpr int64_t kInvalidDisplayId = -1;
virtual int64_t DisplayId() const;
-
- private:
- // A static snapshot of the display's information, provided upon construction.
- // This member is only non-null for Screen objects obtained via the
- // experimental Window Placement API.
- const display::mojom::blink::DisplayPtr display_;
- // True if this is an internal display of the device; it is a static value
- // provided upon construction. This member is only valid for Screen objects
- // obtained via the experimental Window Placement API.
- const absl::optional<bool> internal_;
- // True if this is the primary screen of the operating system; it is a static
- // value provided upon construction. This member is only valid for Screen
- // objects obtained via the experimental Window Placement API.
- const absl::optional<bool> primary_;
- // A web-exposed device id; it is a static value provided upon construction.
- // This member is only valid for Screen objects obtained via the experimental
- // Window Placement API.
- const String id_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.idl b/chromium/third_party/blink/renderer/core/frame/screen.idl
index e0ab73348cf..2e8089222c6 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.idl
+++ b/chromium/third_party/blink/renderer/core/frame/screen.idl
@@ -51,12 +51,4 @@
[RuntimeEnabled=WindowPlacement] void addEventListener(DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options);
[RuntimeEnabled=WindowPlacement] void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options);
[ImplementedAs=dispatchEventForBindings, RaisesException, RuntimeCallStatsCounter=EventTargetDispatchEvent, RuntimeEnabled=WindowPlacement] boolean dispatchEvent(Event event);
- // TODO(crbug.com/1116528): Move permission-gated attributes to an interface that inherits from Screen.
- [HighEntropy=Direct, MeasureAs=WindowScreenLeft, RuntimeEnabled=WindowPlacement] readonly attribute long left;
- [HighEntropy=Direct, MeasureAs=WindowScreenTop, RuntimeEnabled=WindowPlacement] readonly attribute long top;
- [HighEntropy=Direct, MeasureAs=WindowScreenInternal, RuntimeEnabled=WindowPlacement] readonly attribute boolean internal;
- [HighEntropy=Direct, MeasureAs=WindowScreenPrimary, RuntimeEnabled=WindowPlacement] readonly attribute boolean primary;
- [RuntimeEnabled=WindowPlacement] readonly attribute float scaleFactor;
- [HighEntropy=Direct, MeasureAs=WindowScreenId, RuntimeEnabled=WindowPlacement] readonly attribute DOMString id;
- [HighEntropy=Direct, MeasureAs=WindowScreenTouchSupport, RuntimeEnabled=WindowPlacement] readonly attribute boolean touchSupport;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc b/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
index 8585b4c5d1f..16810663272 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
+++ b/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
@@ -12,7 +12,7 @@ namespace blink {
ScreenMetricsEmulator::ScreenMetricsEmulator(
WebFrameWidgetImpl* frame_widget,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const gfx::Size& widget_size,
const gfx::Size& visible_viewport_size,
const gfx::Rect& view_screen_rect,
@@ -24,7 +24,8 @@ ScreenMetricsEmulator::ScreenMetricsEmulator(
original_view_screen_rect_(view_screen_rect),
original_window_screen_rect_(window_screen_rect) {}
-const ScreenInfo& ScreenMetricsEmulator::GetOriginalScreenInfo() const {
+const display::ScreenInfo& ScreenMetricsEmulator::GetOriginalScreenInfo()
+ const {
return original_screen_infos_.current();
}
@@ -99,7 +100,8 @@ void ScreenMetricsEmulator::Apply() {
window_pos = widget_pos;
}
- const ScreenInfo& original_screen_info = original_screen_infos_.current();
+ const display::ScreenInfo& original_screen_info =
+ original_screen_infos_.current();
gfx::Rect screen_rect = original_screen_info.rect;
if (!emulation_params_.screen_size.IsEmpty()) {
@@ -117,11 +119,11 @@ void ScreenMetricsEmulator::Apply() {
if (emulation_params_.device_scale_factor)
device_scale_factor = emulation_params_.device_scale_factor;
- mojom::blink::ScreenOrientation orientation_type =
+ display::mojom::blink::ScreenOrientation orientation_type =
original_screen_info.orientation_type;
uint16_t orientation_angle = original_screen_info.orientation_angle;
if (emulation_params_.screen_orientation_type !=
- mojom::blink::ScreenOrientation::kUndefined) {
+ display::mojom::blink::ScreenOrientation::kUndefined) {
orientation_type = emulation_params_.screen_orientation_type;
orientation_angle = emulation_params_.screen_orientation_angle;
}
@@ -150,8 +152,9 @@ void ScreenMetricsEmulator::Apply() {
frame_widget_->SetWindowSegments(emulated_segments);
}
- ScreenInfos emulated_screen_infos = original_screen_infos_;
- ScreenInfo& emulated_screen_info = emulated_screen_infos.mutable_current();
+ display::ScreenInfos emulated_screen_infos = original_screen_infos_;
+ display::ScreenInfo& emulated_screen_info =
+ emulated_screen_infos.mutable_current();
emulated_screen_info.device_scale_factor = device_scale_factor;
emulated_screen_info.rect = screen_rect;
emulated_screen_info.available_rect = screen_rect;
diff --git a/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.h b/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
index ab68491ba5f..bb38ae9aaf6 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
+++ b/chromium/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
@@ -8,12 +8,12 @@
#include <memory>
#include "third_party/blink/public/common/widget/device_emulation_params.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
-#include "third_party/blink/public/common/widget/screen_infos.h"
#include "third_party/blink/public/mojom/widget/device_emulation_params.mojom-blink.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/visitor.h"
+#include "ui/display/screen_info.h"
+#include "ui/display/screen_infos.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -29,15 +29,17 @@ class WebFrameWidgetImpl;
class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
public:
ScreenMetricsEmulator(WebFrameWidgetImpl* frame_widget,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const gfx::Size& widget_size,
const gfx::Size& visible_viewport_size,
const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
+ ScreenMetricsEmulator(const ScreenMetricsEmulator&) = delete;
+ ScreenMetricsEmulator& operator=(const ScreenMetricsEmulator&) = delete;
virtual ~ScreenMetricsEmulator() = default;
- const ScreenInfo& GetOriginalScreenInfo() const;
- const ScreenInfos& original_screen_infos() const {
+ const display::ScreenInfo& GetOriginalScreenInfo() const;
+ const display::ScreenInfos& original_screen_infos() const {
return original_screen_infos_;
}
@@ -88,14 +90,12 @@ class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
DeviceEmulationParams emulation_params_;
// Original values to restore back after emulation ends.
- ScreenInfos original_screen_infos_;
+ display::ScreenInfos original_screen_infos_;
gfx::Size original_widget_size_;
gfx::Size original_visible_viewport_size_;
gfx::Rect original_view_screen_rect_;
gfx::Rect original_window_screen_rect_;
std::vector<gfx::Rect> original_root_window_segments_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenMetricsEmulator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.h b/chromium/third_party/blink/renderer/core/frame/settings.h
index e9fe6914b95..54b68461f69 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.h
+++ b/chromium/third_party/blink/renderer/core/frame/settings.h
@@ -28,7 +28,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SETTINGS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SETTINGS_H_
-#include "base/macros.h"
#include "third_party/blink/public/common/css/navigation_controls.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
@@ -56,6 +55,8 @@ class CORE_EXPORT Settings {
public:
Settings();
+ Settings(const Settings&) = delete;
+ Settings& operator=(const Settings&) = delete;
GenericFontFamilySettings& GetGenericFontFamilySettings() {
return generic_font_family_settings_;
@@ -76,8 +77,6 @@ class CORE_EXPORT Settings {
GenericFontFamilySettings generic_font_family_settings_;
SETTINGS_MEMBER_VARIABLES
-
- DISALLOW_COPY_AND_ASSIGN(Settings);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.json5 b/chromium/third_party/blink/renderer/core/frame/settings.json5
index 4c5ad792de9..aa180d11943 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.json5
+++ b/chromium/third_party/blink/renderer/core/frame/settings.json5
@@ -836,16 +836,6 @@
initial: false,
},
- // Ability to override the default 'passive' value in AddEventListenerOptions. This
- // is useful to demonstrate the power of passive event listeners. This can be removed
- // when there is greater adoption, interventions to force it on and associated devtools
- // to enable it have been shipped.
- {
- name: "passiveListenerDefault",
- initial: "PassiveListenerDefault::kFalse",
- type: "PassiveListenerDefault",
- },
-
{
name: "hideScrollbars",
initial: false,
@@ -1103,5 +1093,11 @@
initial: true,
type: "bool",
},
+ // LitePage origin the subresources such as images should be redirected to
+ // when the kSubresourceRedirect feature is enabled.
+ {
+ name: "LitePageSubresourceRedirectOrigin",
+ type: "String",
+ },
],
}
diff --git a/chromium/third_party/blink/renderer/core/frame/sticky_ad_detector.h b/chromium/third_party/blink/renderer/core/frame/sticky_ad_detector.h
index b86136990ae..0509e48f365 100644
--- a/chromium/third_party/blink/renderer/core/frame/sticky_ad_detector.h
+++ b/chromium/third_party/blink/renderer/core/frame/sticky_ad_detector.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_STICKY_AD_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_STICKY_AD_DETECTOR_H_
-#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -38,6 +37,8 @@ class LocalFrame;
class CORE_EXPORT StickyAdDetector {
public:
StickyAdDetector() = default;
+ StickyAdDetector(const StickyAdDetector&) = delete;
+ StickyAdDetector& operator=(const StickyAdDetector&) = delete;
~StickyAdDetector() = default;
void MaybeFireDetection(LocalFrame* main_frame);
@@ -52,8 +53,6 @@ class CORE_EXPORT StickyAdDetector {
int candidate_start_main_frame_scroll_offset_;
bool done_detection_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(StickyAdDetector);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl b/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl
index 095981d5ffc..42c40b4ea55 100644
--- a/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl
+++ b/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl
@@ -5,9 +5,12 @@
// https://github.com/WICG/ua-client-hints
dictionary UADataValues {
+ FrozenArray<NavigatorUABrandVersion> brands;
+ boolean mobile;
DOMString platform;
DOMString platformVersion;
DOMString architecture;
DOMString model;
DOMString uaFullVersion;
+ DOMString bitness;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter_impl.cc b/chromium/third_party/blink/renderer/core/frame/use_counter_impl.cc
index 3dacfcce543..eaea9c36b07 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter_impl.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/frame/use_counter_impl.h"
#include "base/metrics/histogram_macros.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
@@ -54,6 +55,20 @@ mojom::blink::UseCounterFeatureType ToFeatureType(
return mojom::blink::UseCounterFeatureType::kAnimatedCssProperty;
}
}
+
+mojom::blink::UseCounterFeatureType ToFeatureType(
+ UseCounterImpl::PermissionsPolicyUsageType type) {
+ switch (type) {
+ case UseCounterImpl::PermissionsPolicyUsageType::kViolation:
+ return mojom::blink::UseCounterFeatureType::
+ kPermissionsPolicyViolationEnforce;
+ case UseCounterImpl::PermissionsPolicyUsageType::kHeader:
+ return mojom::blink::UseCounterFeatureType::kPermissionsPolicyHeader;
+ case UseCounterImpl::PermissionsPolicyUsageType::kIframeAttribute:
+ return mojom::blink::UseCounterFeatureType::
+ kPermissionsPolicyIframeAttribute;
+ }
+}
} // namespace
UseCounterMuteScope::UseCounterMuteScope(const Element& element)
@@ -104,10 +119,16 @@ void UseCounterImpl::Trace(Visitor* visitor) const {
void UseCounterImpl::DidCommitLoad(const LocalFrame* frame) {
const KURL url = frame->GetDocument()->Url();
- if (url.ProtocolIs("chrome-extension"))
+ if (CommonSchemeRegistry::IsExtensionScheme(url.Protocol().Ascii())) {
context_ = kExtensionContext;
- if (url.ProtocolIs("file"))
+ } else if (url.ProtocolIs("file")) {
context_ = kFileContext;
+ } else if (url.ProtocolIsInHTTPFamily()) {
+ context_ = kDefaultContext;
+ } else {
+ // UseCounter is disabled for all other URL schemes.
+ context_ = kDisabledContext;
+ }
DCHECK_EQ(kPreCommit, commit_state_);
commit_state_ = kCommited;
@@ -123,7 +144,6 @@ void UseCounterImpl::DidCommitLoad(const LocalFrame* frame) {
TraceMeasurement(feature);
}
- // TODO(crbug.com/1196402): move extension histogram to the browser side.
if (context_ == kExtensionContext || context_ == kFileContext) {
CountFeature(WebFeature::kPageVisits);
}
@@ -192,14 +212,14 @@ void UseCounterImpl::Count(WebFeature web_feature,
source_frame);
}
-void UseCounterImpl::CountPermissionsPolicyViolation(
+void UseCounterImpl::CountPermissionsPolicyUsage(
mojom::blink::PermissionsPolicyFeature feature,
+ PermissionsPolicyUsageType usage_type,
const LocalFrame& source_frame) {
DCHECK_NE(mojom::blink::PermissionsPolicyFeature::kNotFound, feature);
- Count(
- {mojom::blink::UseCounterFeatureType::kPermissionsPolicyViolationEnforce,
- static_cast<uint32_t>(feature)},
- &source_frame);
+
+ Count({ToFeatureType(usage_type), static_cast<uint32_t>(feature)},
+ &source_frame);
}
void UseCounterImpl::NotifyFeatureCounted(WebFeature feature) {
@@ -213,8 +233,6 @@ void UseCounterImpl::NotifyFeatureCounted(WebFeature feature) {
observers_.RemoveAll(to_be_removed);
}
-// TODO(crbug.com/1196402): Remove this method after all histograms are
-// counted on browser side.
void UseCounterImpl::CountFeature(WebFeature feature) const {
switch (context_) {
case kDefaultContext:
@@ -246,26 +264,24 @@ bool UseCounterImpl::ReportMeasurement(const UseCounterFeature& feature,
return false;
auto* client = frame->Client();
- switch (feature.type()) {
- case mojom::blink::UseCounterFeatureType::kWebFeature: {
- WebFeature web_feature = static_cast<WebFeature>(feature.value());
- if (context_ != kDefaultContext)
- CountFeature(web_feature);
- NotifyFeatureCounted(web_feature);
- break;
- }
- case mojom::blink::UseCounterFeatureType::kAnimatedCssProperty:
- case mojom::blink::UseCounterFeatureType::kCssProperty:
- if (context_ == kExtensionContext)
- return false;
- break;
- case mojom::blink::UseCounterFeatureType::
- kPermissionsPolicyViolationEnforce:
- break;
+ if (feature.type() == mojom::blink::UseCounterFeatureType::kWebFeature)
+ NotifyFeatureCounted(static_cast<WebFeature>(feature.value()));
+
+ // Report to browser about observed event only when URL is HTTP/HTTPS,
+ // as other URL schemes are filtered out in
+ // |MetricsWebContentsObserver::DoesTimingUpdateHaveError| anyway.
+ if (context_ == kDefaultContext) {
+ client->DidObserveNewFeatureUsage(feature);
+ return true;
+ }
+
+ // WebFeatures in non-default contexts are counted on renderer side.
+ if (feature.type() == mojom::blink::UseCounterFeatureType::kWebFeature) {
+ CountFeature(static_cast<WebFeature>(feature.value()));
+ return true;
}
- client->DidObserveNewFeatureUsage(feature);
- return true;
+ return false;
}
// Note that HTTPArchive tooling looks specifically for this event - see
@@ -284,6 +300,8 @@ void UseCounterImpl::TraceMeasurement(const UseCounterFeature& feature) {
break;
case mojom::blink::UseCounterFeatureType::
kPermissionsPolicyViolationEnforce:
+ case mojom::blink::UseCounterFeatureType::kPermissionsPolicyHeader:
+ case mojom::blink::UseCounterFeatureType::kPermissionsPolicyIframeAttribute:
// TODO(crbug.com/1206004): Add trace event for permissions policy metrics
// gathering.
return;
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter_impl.h b/chromium/third_party/blink/renderer/core/frame/use_counter_impl.h
index d7ea7dcb8fe..05e2a97d91f 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter_impl.h
@@ -27,7 +27,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_USE_COUNTER_IMPL_H_
#include <bitset>
-#include "base/macros.h"
#include "third_party/blink/public/common/use_counter/use_counter_feature_tracker.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -88,7 +87,16 @@ class CORE_EXPORT UseCounterImpl final {
// distinguish them.
enum class CSSPropertyType { kDefault, kAnimation };
+ enum class PermissionsPolicyUsageType {
+ kViolation, // Feature request denied by permissions policy.
+ kHeader, // Feature used in either Permissions-Policy or Feature-Policy
+ // HTTP header.
+ kIframeAttribute, // Feature used in 'allow' attribute on iframe element.
+ };
+
explicit UseCounterImpl(Context = kDefaultContext, CommitState = kPreCommit);
+ UseCounterImpl(const UseCounterImpl&) = delete;
+ UseCounterImpl& operator=(const UseCounterImpl&) = delete;
// An interface to observe UseCounterImpl changes. Note that this is never
// notified when the counter is disabled by |m_muteCount| or when |m_context|
@@ -106,8 +114,9 @@ class CORE_EXPORT UseCounterImpl final {
// Repeated calls are ignored.
void Count(CSSPropertyID, CSSPropertyType, const LocalFrame*);
void Count(WebFeature, const LocalFrame*);
- void CountPermissionsPolicyViolation(mojom::blink::PermissionsPolicyFeature,
- const LocalFrame&);
+ void CountPermissionsPolicyUsage(mojom::blink::PermissionsPolicyFeature,
+ PermissionsPolicyUsageType,
+ const LocalFrame&);
// Return whether the feature has been seen since the last page load
// (except when muted). Does include features seen in documents which have
@@ -164,8 +173,6 @@ class CORE_EXPORT UseCounterImpl final {
UseCounterFeatureTracker feature_tracker_;
HeapHashSet<Member<Observer>> observers_;
-
- DISALLOW_COPY_AND_ASSIGN(UseCounterImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter_impl_test.cc b/chromium/third_party/blink/renderer/core/frame/use_counter_impl_test.cc
index c08488615e0..a4496b9fdff 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter_impl_test.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
@@ -12,6 +13,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.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/loader/empty_clients.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/instrumentation/use_counter.h"
@@ -19,6 +21,7 @@
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
namespace {
const char kExtensionFeaturesHistogramName[] =
@@ -41,7 +44,26 @@ using WebFeature = mojom::WebFeature;
class UseCounterImplTest : public testing::Test {
public:
- UseCounterImplTest() : dummy_(std::make_unique<DummyPageHolder>()) {
+ class DummyLocalFrameClient : public EmptyLocalFrameClient {
+ public:
+ DummyLocalFrameClient() = default;
+ const std::vector<UseCounterFeature>& observed_features() const {
+ return observed_features_;
+ }
+
+ private:
+ void DidObserveNewFeatureUsage(const UseCounterFeature& feature) override {
+ observed_features_.push_back(feature);
+ }
+ std::vector<UseCounterFeature> observed_features_;
+ };
+
+ UseCounterImplTest()
+ : dummy_(std::make_unique<DummyPageHolder>(
+ /* initial_view_size= */ IntSize(),
+ /* chrome_client= */ nullptr,
+ /* local_frame_client= */
+ MakeGarbageCollected<DummyLocalFrameClient>())) {
Page::InsertOrdinaryPageForTesting(&dummy_->GetPage());
}
@@ -67,11 +89,49 @@ class UseCounterImplTest : public testing::Test {
}
};
+class UseCounterImplBrowserReportTest
+ : public UseCounterImplTest,
+ public ::testing::WithParamInterface</* URL */ const char*> {};
+
+INSTANTIATE_TEST_SUITE_P(All,
+ UseCounterImplBrowserReportTest,
+ ::testing::Values("chrome-extension://dummysite/",
+ "file://dummyfile",
+ "data:;base64,",
+ "ftp://ftp.dummy/dummy.txt",
+ "http://foo.com",
+ "https://bar.com"));
+
+// UseCounter should not send events to browser when handling page with
+// Non HTTP Family URLs, as these events will be discarded on the browser side
+// in |MetricsWebContentsObserver::DoesTimingUpdateHaveError|.
+TEST_P(UseCounterImplBrowserReportTest, ReportOnlyHTTPFamily) {
+ KURL url = url_test_helpers::ToKURL(GetParam());
+ SetURL(url);
+ UseCounterImpl use_counter;
+ use_counter.DidCommitLoad(GetFrame());
+
+ // Count every feature types in UseCounterFeatureType.
+ use_counter.Count(mojom::WebFeature::kFetch, GetFrame());
+ use_counter.Count(CSSPropertyID::kHeight,
+ UseCounterImpl::CSSPropertyType::kDefault, GetFrame());
+ use_counter.Count(CSSPropertyID::kHeight,
+ UseCounterImpl::CSSPropertyType::kAnimation, GetFrame());
+
+ auto* dummy_client =
+ static_cast<UseCounterImplBrowserReportTest::DummyLocalFrameClient*>(
+ GetFrame()->Client());
+
+ EXPECT_EQ(!dummy_client->observed_features().empty(),
+ url.ProtocolIsInHTTPFamily());
+}
+
TEST_F(UseCounterImplTest, RecordingExtensions) {
const std::string histogram = kExtensionFeaturesHistogramName;
constexpr auto item = mojom::WebFeature::kFetch;
constexpr auto second_item = WebFeature::kFetchBodyStream;
const std::string url = kExtensionUrl;
+ CommonSchemeRegistry::RegisterURLSchemeAsExtension("chrome-extension");
UseCounterImpl::Context context = UseCounterImpl::kExtensionContext;
int page_visits_bucket = GetPageVisitsBucketforHistogram(histogram);
@@ -113,6 +173,7 @@ TEST_F(UseCounterImplTest, RecordingExtensions) {
EXPECT_TRUE(use_counter1.IsCounted(item));
histogram_tester_.ExpectBucketCount(histogram, static_cast<int>(item), 2);
histogram_tester_.ExpectTotalCount(histogram, 4);
+ CommonSchemeRegistry::RemoveURLSchemeAsExtensionForTest("chrome-extension");
}
TEST_F(UseCounterImplTest, CSSSelectorPseudoWhere) {
@@ -204,135 +265,78 @@ TEST_F(UseCounterImplTest, CSSGridLayoutPercentageColumnIndefiniteWidth) {
EXPECT_FALSE(document.IsUseCounted(feature));
}
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight1) {
+TEST_F(UseCounterImplTest, CSSFlexibleBox) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
+ WebFeature feature = WebFeature::kCSSFlexibleBox;
EXPECT_FALSE(document.IsUseCounted(feature));
document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; grid-template-rows: 50%;'>"
- "</div>");
+ "<div style='display: flex;'>flexbox</div>");
UpdateAllLifecyclePhases(document);
EXPECT_TRUE(document.IsUseCounted(feature));
}
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight2) {
+TEST_F(UseCounterImplTest, CSSFlexibleBoxInline) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
+ WebFeature feature = WebFeature::kCSSFlexibleBox;
EXPECT_FALSE(document.IsUseCounted(feature));
document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; grid-template-rows: 50% 50%;'>"
- "</div>");
+ "<div style='display: inline-flex;'>flexbox</div>");
UpdateAllLifecyclePhases(document);
EXPECT_TRUE(document.IsUseCounted(feature));
}
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight3) {
+TEST_F(UseCounterImplTest, CSSFlexibleBoxButton) {
+ // LayoutButton is a subclass of LayoutFlexibleBox, however we don't want it
+ // to be counted as usage of flexboxes as it's an implementation detail.
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
+ WebFeature feature = WebFeature::kCSSFlexibleBox;
EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; grid-template-rows: 100% 100%;'>"
- "</div>");
+ document.documentElement()->setInnerHTML("<button>button</button>");
UpdateAllLifecyclePhases(document);
- EXPECT_TRUE(document.IsUseCounted(feature));
-}
-
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight4) {
- auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
- Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; grid-template-rows: minmax(50%, "
- "100%);'>"
- "</div>");
- UpdateAllLifecyclePhases(document);
- EXPECT_TRUE(document.IsUseCounted(feature));
}
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight5) {
+TEST_F(UseCounterImplTest, HTMLRootContained) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
+ WebFeature feature = WebFeature::kHTMLRootContained;
EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; max-height: 0; grid-template-rows: "
- "100%;'>"
- "</div>");
- UpdateAllLifecyclePhases(document);
- EXPECT_TRUE(document.IsUseCounted(feature));
-}
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight6) {
- auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
- Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
- EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; grid-template-rows: 100%;'>"
- "</div>");
+ document.documentElement()->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+ "none");
+ document.documentElement()->SetInlineStyleProperty(CSSPropertyID::kContain,
+ "paint");
UpdateAllLifecyclePhases(document);
EXPECT_FALSE(document.IsUseCounted(feature));
-}
-TEST_F(UseCounterImplTest, CSSGridLayoutPercentageRowIndefiniteHeight7) {
- auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
- Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
- EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: inline-grid; grid-template-rows: minmax(100%, "
- "100%);'>"
- "</div>");
- UpdateAllLifecyclePhases(document);
- EXPECT_FALSE(document.IsUseCounted(feature));
-}
-
-TEST_F(UseCounterImplTest, CSSFlexibleBox) {
- auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
- Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kCSSFlexibleBox;
- EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: flex;'>flexbox</div>");
+ document.documentElement()->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+ "block");
UpdateAllLifecyclePhases(document);
EXPECT_TRUE(document.IsUseCounted(feature));
}
-TEST_F(UseCounterImplTest, CSSFlexibleBoxInline) {
+TEST_F(UseCounterImplTest, HTMLBodyContained) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kCSSFlexibleBox;
+ WebFeature feature = WebFeature::kHTMLBodyContained;
EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML(
- "<div style='display: inline-flex;'>flexbox</div>");
- UpdateAllLifecyclePhases(document);
- EXPECT_TRUE(document.IsUseCounted(feature));
-}
-TEST_F(UseCounterImplTest, CSSFlexibleBoxButton) {
- // LayoutButton is a subclass of LayoutFlexibleBox, however we don't want it
- // to be counted as usage of flexboxes as it's an implementation detail.
- auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
- Document& document = dummy_page_holder->GetDocument();
- WebFeature feature = WebFeature::kCSSFlexibleBox;
- EXPECT_FALSE(document.IsUseCounted(feature));
- document.documentElement()->setInnerHTML("<button>button</button>");
+ document.body()->SetInlineStyleProperty(CSSPropertyID::kDisplay, "none");
+ document.body()->SetInlineStyleProperty(CSSPropertyID::kContain, "paint");
UpdateAllLifecyclePhases(document);
EXPECT_FALSE(document.IsUseCounted(feature));
+
+ document.body()->SetInlineStyleProperty(CSSPropertyID::kDisplay, "block");
+ UpdateAllLifecyclePhases(document);
+ EXPECT_TRUE(document.IsUseCounted(feature));
}
class DeprecationTest : public testing::Test {
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 34d66a104cb..bdebcfc8ff1 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -33,9 +33,11 @@
#include <memory>
#include "base/metrics/histogram_functions.h"
+#include "build/build_config.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/layers/solid_color_scrollbar_layer.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -70,6 +72,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
+#include "ui/base/ui_base_features.h"
namespace blink {
@@ -88,6 +91,8 @@ VisualViewport::VisualViewport(Page& owner)
unique_id, CompositorElementIdNamespace::kPrimary);
scroll_element_id_ = CompositorElementIdFromUniqueObjectId(
unique_id, CompositorElementIdNamespace::kScroll);
+ elasticity_effect_node_id_ = CompositorElementIdFromUniqueObjectId(
+ unique_id, CompositorElementIdNamespace::kEffectFilter);
Reset();
}
@@ -101,6 +106,11 @@ VisualViewport::GetOverscrollElasticityTransformNode() const {
return overscroll_elasticity_transform_node_.get();
}
+EffectPaintPropertyNode* VisualViewport::GetOverscrollElasticityEffectNode()
+ const {
+ return overscroll_elasticity_effect_node_.get();
+}
+
TransformPaintPropertyNode* VisualViewport::GetPageScaleNode() const {
return page_scale_node_.get();
}
@@ -287,6 +297,40 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
}
}
+#if defined(OS_ANDROID)
+ // TODO(https://crbug.com/1226115): Remove this forced effect node creation
+ // once we have completed the experiment to measure additional memory usage.
+ bool force_overscroll_effect_node =
+ base::GetFieldTrialParamValueByFeature(
+ ::features::kElasticOverscroll, ::features::kElasticOverscrollType) ==
+ ::features::kElasticOverscrollTypeFilter;
+ if (force_overscroll_effect_node ||
+ (Platform::Current()->IsElasticOverscrollEnabled() &&
+ base::GetFieldTrialParamValueByFeature(
+ ::features::kElasticOverscroll,
+ ::features::kElasticOverscrollType) !=
+ ::features::kElasticOverscrollTypeTransform)) {
+ bool needs_overscroll_effect_node = !MaximumScrollOffset().IsZero();
+ if (needs_overscroll_effect_node && !overscroll_elasticity_effect_node_) {
+ EffectPaintPropertyNode::State state;
+ state.output_clip = context.current.clip;
+ state.local_transform_space = transform_parent;
+ state.direct_compositing_reasons =
+ CompositingReason::kActiveFilterAnimation;
+ state.compositor_element_id = elasticity_effect_node_id_;
+ // The filter will be animated on the compositor in response to
+ // overscroll.
+ state.has_active_filter_animation = true;
+ overscroll_elasticity_effect_node_ =
+ EffectPaintPropertyNode::Create(*effect_parent, std::move(state));
+ }
+ if (overscroll_elasticity_effect_node_) {
+ context.current_effect = effect_parent =
+ overscroll_elasticity_effect_node_.get();
+ }
+ }
+#endif
+
if (scrollbar_layer_horizontal_) {
EffectPaintPropertyNode::State state;
state.local_transform_space = transform_parent;
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 4687c8fb206..ae3e3ec12cb 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -90,6 +90,7 @@ struct PaintPropertyTreeBuilderFragmentContext;
// +- scroll_translation_node_ (scroll: scroll_node_)
// Effect tree:
// parent effect state
+// +- overscroll_elasticity_effect_node_
// +- horizontal_scrollbar_effect_node_
// +- vertical_scrollbar_effect_node_
//
@@ -217,6 +218,7 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
cc::Layer* LayerForHorizontalScrollbar() const override;
cc::Layer* LayerForVerticalScrollbar() const override;
bool ScheduleAnimation() override;
+ bool UsesCompositedScrolling() const override { return true; }
cc::AnimationHost* GetCompositorAnimationHost() const override;
CompositorAnimationTimeline* GetCompositorAnimationTimeline() const override;
IntRect VisibleContentRect(
@@ -226,9 +228,10 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
mojom::blink::ColorScheme UsedColorScheme() const override;
// 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 FloatPoint&) final { NOTREACHED(); }
+ // WebViewImpl explicitly rather than via
+ // ScrollingCoordinator::DidCompositorScroll() since it needs to be set in
+ // tandem with the page scale delta.
+ void DidCompositorScroll(const FloatPoint&) final { NOTREACHED(); }
// Visual Viewport API implementation.
double OffsetLeft() const;
@@ -257,6 +260,7 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
TransformPaintPropertyNode* GetDeviceEmulationTransformNode() const;
TransformPaintPropertyNode* GetOverscrollElasticityTransformNode() const;
+ EffectPaintPropertyNode* GetOverscrollElasticityEffectNode() const;
TransformPaintPropertyNode* GetPageScaleNode() const;
TransformPaintPropertyNode* GetScrollTranslationNode() const;
ScrollPaintPropertyNode* GetScrollNode() const;
@@ -321,6 +325,7 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
scoped_refptr<TransformPaintPropertyNode> page_scale_node_;
scoped_refptr<TransformPaintPropertyNode> scroll_translation_node_;
scoped_refptr<ScrollPaintPropertyNode> scroll_node_;
+ scoped_refptr<EffectPaintPropertyNode> overscroll_elasticity_effect_node_;
scoped_refptr<EffectPaintPropertyNode> horizontal_scrollbar_effect_node_;
scoped_refptr<EffectPaintPropertyNode> vertical_scrollbar_effect_node_;
@@ -354,6 +359,8 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
// For scrolling, on scroll_layer_, scroll_node_, and scroll element ids of
// scrollbar layers.
CompositorElementId scroll_element_id_;
+ // For overscroll elasticity.
+ CompositorElementId elasticity_effect_node_id_;
bool needs_paint_property_update_;
};
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 302590c8f15..f4337e7761f 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
@@ -60,6 +60,7 @@
#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#include "ui/accessibility/ax_mode.h"
#include <string>
@@ -1963,7 +1964,7 @@ TEST_P(VisualViewportTest, AccessibilityHitTestWhileZoomedIn) {
WebDocument web_doc = WebView()->MainFrameImpl()->GetDocument();
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
- WebAXContext ax_context(web_doc);
+ WebAXContext ax_context(web_doc, ui::kAXModeComplete);
WebView()->SetPageScaleFactor(2);
WebView()->SetVisualViewportOffset(gfx::PointF(200, 230));
@@ -2799,8 +2800,6 @@ TEST_P(VisualViewportTest, InSubtreeOfPageScale) {
}
TEST_F(VisualViewportSimTest, UsedColorSchemeFromRootElement) {
- ScopedCSSColorSchemeUARenderingForTest color_scheme_ua_enabled(true);
-
ColorSchemeHelper color_scheme_helper(*(WebView().GetPage()));
color_scheme_helper.SetPreferredColorScheme(
mojom::blink::PreferredColorScheme::kDark);
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
index d01a042a3ff..adbc3c224e6 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
@@ -420,16 +420,19 @@ void WebFrameSerializerImpl::EndTagToString(Element* element,
void WebFrameSerializerImpl::BuildContentForNode(Node* node,
SerializeDomParam* param) {
switch (node->getNodeType()) {
- case Node::kElementNode:
+ case Node::kElementNode: {
+ auto* element = To<Element>(node);
// Process open tag of element.
- OpenTagToString(To<Element>(node), param);
+ OpenTagToString(element, param);
// Walk through the children nodes and process it.
- for (Node* child = node->firstChild(); child;
- child = child->nextSibling())
+ for (Node* child = element->firstChild(); child;
+ child = child->nextSibling()) {
BuildContentForNode(child, param);
+ }
// Process end tag of element.
- EndTagToString(To<Element>(node), param);
+ EndTagToString(element, param);
break;
+ }
case Node::kTextNode:
SaveHTMLContentToBuffer(CreateMarkup(node), param);
break;
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_test.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_test.cc
index 5052708af81..e9c1681a516 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -35,7 +35,8 @@
#include <memory>
#include "base/callback_helpers.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
+#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
@@ -61,6 +62,7 @@
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/public/common/messaging/transferable_message.h"
+#include "third_party/blink/public/common/navigation/navigation_params.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/public/common/widget/device_emulation_params.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
@@ -69,10 +71,12 @@
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink.h"
#include "third_party/blink/public/mojom/page_state/page_state.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_cache.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -124,6 +128,7 @@
#include "third_party/blink/renderer/core/editing/finder/text_finder.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/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h"
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
@@ -158,6 +163,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/renderer/core/messaging/blink_cloneable_message.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_image.h"
@@ -200,9 +206,11 @@
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.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/casting.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/hash_set.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
#include "ui/base/ime/mojom/text_input_state.mojom-blink.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/events/keycodes/dom/dom_key.h"
@@ -278,8 +286,7 @@ class WebFrameTest : public testing::Test {
// Make sure that the RendererScheduler is foregrounded to avoid getting
// throttled.
if (kLaunchingProcessIsBackgrounded) {
- ThreadScheduler::Current()
- ->GetWebMainThreadSchedulerForTest()
+ blink::scheduler::WebThreadScheduler::MainThreadScheduler()
->SetRendererBackgrounded(false);
}
}
@@ -737,7 +744,7 @@ TEST_F(WebFrameTest, CapabilityDelegationMessageEventTest) {
WebString("window.frames[0].postMessage('0', {targetOrigin: '*'});"));
WebScriptSource post_message_w_payment_request(
WebString("window.frames[0].postMessage("
- "'1', {targetOrigin: '*', createToken: 'paymentrequest'});"));
+ "'1', {targetOrigin: '*', delegate: 'paymentrequest'});"));
// The delegation info is not passed through a postMessage that is sent
// without either user activation or the delegation option.
@@ -1245,23 +1252,25 @@ TEST_F(WebFrameTest, PostMessageEvent) {
auto* frame =
To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
- scoped_refptr<SerializedScriptValue> data = SerializedScriptValue::Create();
- MessageEvent* message_event = MessageEvent::Create(
- /*ports=*/nullptr, std::move(data), "http://origin.com");
+ auto make_message = []() {
+ BlinkTransferableMessage message;
+ message.message = SerializedScriptValue::NullValue();
+ message.sender_origin =
+ SecurityOrigin::CreateFromString("https://origin.com");
+ return message;
+ };
// Send a message with the correct origin.
scoped_refptr<SecurityOrigin> correct_origin =
SecurityOrigin::Create(ToKURL(base_url_));
- frame->PostMessageEvent(
- absl::nullopt, g_empty_string, correct_origin->ToString(),
- BlinkTransferableMessage::FromMessageEvent(message_event));
+ frame->PostMessageEvent(absl::nullopt, g_empty_string,
+ correct_origin->ToString(), make_message());
// Send another message with incorrect origin.
scoped_refptr<SecurityOrigin> incorrect_origin =
SecurityOrigin::Create(ToKURL(chrome_url_));
- frame->PostMessageEvent(
- absl::nullopt, g_empty_string, incorrect_origin->ToString(),
- BlinkTransferableMessage::FromMessageEvent(message_event));
+ frame->PostMessageEvent(absl::nullopt, g_empty_string,
+ incorrect_origin->ToString(), make_message());
// Verify that only the first addition is in the body of the page.
std::string content = TestWebFrameContentDumper::DumpWebViewAsText(
@@ -1341,8 +1350,8 @@ bool CheckTextAutosizingMultiplier(Document* document, float multiplier) {
void UpdateScreenInfoAndResizeView(
frame_test_helpers::WebViewHelper* web_view_helper,
- const ScreenInfo& screen_info) {
- ScreenInfos screen_infos(screen_info);
+ const display::ScreenInfo& screen_info) {
+ display::ScreenInfos screen_infos(screen_info);
web_view_helper->GetWebView()->MainFrameViewWidget()->UpdateScreenInfo(
screen_infos);
web_view_helper->Resize(screen_info.rect.size());
@@ -1352,7 +1361,7 @@ void UpdateScreenInfoAndResizeView(
frame_test_helpers::WebViewHelper* web_view_helper,
int viewport_width,
int viewport_height) {
- ScreenInfo screen_info =
+ display::ScreenInfo screen_info =
web_view_helper->GetMainFrameWidget()->GetOriginalScreenInfo();
screen_info.rect = gfx::Rect(viewport_width, viewport_height);
UpdateScreenInfoAndResizeView(web_view_helper, screen_info);
@@ -1493,9 +1502,19 @@ TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag) {
->SetDeviceScaleFactorForTesting(2.f);
web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
- EXPECT_EQ(
- 2,
- web_view_helper.GetWebView()->GetPage()->DeviceScaleFactorDeprecated());
+ if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+ EXPECT_EQ(
+ 1,
+ web_view_helper.GetWebView()->GetPage()->DeviceScaleFactorDeprecated());
+ auto* frame =
+ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+ DCHECK(frame);
+ EXPECT_EQ(2, frame->DevicePixelRatio());
+ } else {
+ EXPECT_EQ(
+ 2,
+ web_view_helper.GetWebView()->GetPage()->DeviceScaleFactorDeprecated());
+ }
// Device scale factor should be independent of page scale.
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(1, 2);
@@ -2623,6 +2642,7 @@ TEST_F(WebFrameTest, targetDensityDpiDevice) {
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-target-densitydpi-device.html", nullptr, nullptr,
ConfigureAndroid);
+ web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
web_view_helper.GetWebView()
->MainFrameWidget()
->SetDeviceScaleFactorForTesting(device_scale_factors[i]);
@@ -2631,7 +2651,6 @@ TEST_F(WebFrameTest, targetDensityDpiDevice) {
web_view_helper.GetWebView()
->GetSettings()
->SetSupportDeprecatedTargetDensityDPI(true);
- web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
EXPECT_NEAR(viewport_width * device_scale_factors[i],
web_view_helper.GetWebView()
@@ -2647,8 +2666,16 @@ TEST_F(WebFrameTest, targetDensityDpiDevice) {
->GetLayoutSize()
.Height(),
1.0f);
- EXPECT_NEAR(1.0f / device_scale_factors[i],
- web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+ EXPECT_NEAR(1.0f, web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ auto* frame =
+ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+ DCHECK(frame);
+ EXPECT_EQ(device_scale_factors[i], frame->DevicePixelRatio());
+ } else {
+ EXPECT_NEAR(1.0f / device_scale_factors[i],
+ web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ }
}
}
@@ -2706,6 +2733,7 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne) {
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, nullptr,
ConfigureAndroid);
+ web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
web_view_helper.GetWebView()
->MainFrameWidget()
->SetDeviceScaleFactorForTesting(device_scale_factor);
@@ -2715,7 +2743,6 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne) {
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
- web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
EXPECT_NEAR(viewport_width * device_scale_factor,
web_view_helper.GetWebView()
@@ -2731,8 +2758,16 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne) {
->GetLayoutSize()
.Height(),
1.0f);
- EXPECT_NEAR(1.0f / device_scale_factor,
- web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+ EXPECT_NEAR(0.25f, web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ auto* frame =
+ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+ DCHECK(frame);
+ EXPECT_EQ(device_scale_factor, frame->DevicePixelRatio());
+ } else {
+ EXPECT_NEAR(1.0f / device_scale_factor,
+ web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ }
}
TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
@@ -2747,6 +2782,7 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-initial-scale-less-than-1-device-width.html",
nullptr, nullptr, ConfigureAndroid);
+ web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
web_view_helper.GetWebView()
->MainFrameWidget()
->SetDeviceScaleFactorForTesting(device_scale_factor);
@@ -2756,8 +2792,8 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
- web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
+ // We use 4.0f in EXPECT_NEAR to account for a rounding error.
const float kPageZoom = 0.25f;
EXPECT_NEAR(viewport_width * device_scale_factor / kPageZoom,
web_view_helper.GetWebView()
@@ -2765,16 +2801,25 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
->GetFrameView()
->GetLayoutSize()
.Width(),
- 1.0f);
+ 4.0f);
EXPECT_NEAR(viewport_height * device_scale_factor / kPageZoom,
web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
->GetLayoutSize()
.Height(),
- 1.0f);
- EXPECT_NEAR(1.0f / device_scale_factor,
- web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ 4.0f);
+ if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+ EXPECT_NEAR(kPageZoom, web_view_helper.GetWebView()->PageScaleFactor(),
+ 0.01f);
+ auto* frame =
+ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+ DCHECK(frame);
+ EXPECT_EQ(device_scale_factor, frame->DevicePixelRatio());
+ } else {
+ EXPECT_NEAR(1.0f / device_scale_factor,
+ web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ }
}
TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride) {
@@ -2857,6 +2902,7 @@ TEST_F(WebFrameTest,
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
nullptr, ConfigureAndroid);
+ web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
web_view_helper.GetWebView()
->MainFrameWidget()
->SetDeviceScaleFactorForTesting(device_scale_factor);
@@ -2869,7 +2915,6 @@ TEST_F(WebFrameTest,
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
- web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
EXPECT_NEAR(viewport_width * device_scale_factor,
web_view_helper.GetWebView()
@@ -2885,8 +2930,16 @@ TEST_F(WebFrameTest,
->GetLayoutSize()
.Height(),
1.0f);
- EXPECT_NEAR(1.0f / device_scale_factor,
- web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+ EXPECT_NEAR(2.0f, web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ auto* frame =
+ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+ DCHECK(frame);
+ EXPECT_EQ(device_scale_factor, frame->DevicePixelRatio());
+ } else {
+ EXPECT_NEAR(1.0f / device_scale_factor,
+ web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+ }
}
TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport) {
@@ -4292,47 +4345,6 @@ TEST_F(WebFrameTest, ReloadWhileProvisional) {
KURL(document_loader->GetUrl()));
}
-TEST_F(WebFrameTest, RedirectChainContainsInitialUrl) {
- const std::string first_url = "data:text/html,foo";
-
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(first_url);
-
- WebDocumentLoader* document_loader =
- web_view_helper.LocalMainFrame()->GetDocumentLoader();
- ASSERT_TRUE(document_loader);
-
- WebVector<WebURL> redirects;
- document_loader->RedirectChain(redirects);
- ASSERT_EQ(1U, redirects.size());
- EXPECT_EQ(ToKURL(first_url), KURL(redirects[0]));
-}
-
-TEST_F(WebFrameTest, IframeRedirect) {
- RegisterMockedHttpURLLoad("iframe_redirect.html");
- RegisterMockedHttpURLLoad("visible_iframe.html");
-
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "iframe_redirect.html");
- // Pump pending requests one more time. The test page loads script that
- // navigates.
- frame_test_helpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.LocalMainFrame());
-
- WebFrame* iframe = web_view_helper.LocalMainFrame()->FindFrameByName(
- WebString::FromUTF8("ifr"));
- ASSERT_TRUE(iframe && iframe->IsWebLocalFrame());
- WebDocumentLoader* iframe_document_loader =
- iframe->ToWebLocalFrame()->GetDocumentLoader();
- ASSERT_TRUE(iframe_document_loader);
- WebVector<WebURL> redirects;
- iframe_document_loader->RedirectChain(redirects);
- ASSERT_EQ(2U, redirects.size());
- EXPECT_EQ(ToKURL("about:blank"), KURL(redirects[0]));
- EXPECT_EQ(ToKURL("http://internal.test/visible_iframe.html"),
- KURL(redirects[1]));
-}
-
TEST_F(WebFrameTest, ClearFocusedNodeTest) {
RegisterMockedHttpURLLoad("iframe_clear_focused_node_test.html");
RegisterMockedHttpURLLoad("autofocus_input_field_iframe.html");
@@ -4563,7 +4575,7 @@ TEST_F(WebFrameTest, ContextNotificationsReload) {
// The two release notifications we got should be exactly the same as the
// first two create notifications.
- for (size_t i = 0; i < release_notifications.size(); ++i) {
+ for (wtf_size_t i = 0; i < release_notifications.size(); ++i) {
EXPECT_TRUE(release_notifications[i]->Equals(
create_notifications[create_notifications.size() - 3 - i].get()));
}
@@ -4636,7 +4648,7 @@ TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds) {
// And one of them should be exactly the same as the create notification for
// the isolated context.
int match_count = 0;
- for (size_t i = 0; i < release_notifications.size(); ++i) {
+ for (wtf_size_t i = 0; i < release_notifications.size(); ++i) {
if (release_notifications[i]->Equals(create_notifications[0].get()))
++match_count;
}
@@ -6422,6 +6434,7 @@ TEST_P(CompositedSelectionBoundsTest, Iframe) {
{"composited_selection_bounds_basic.html"});
}
TEST_P(CompositedSelectionBoundsTest, Editable) {
+ web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(16);
RunTest("composited_selection_bounds_editable.html");
}
TEST_P(CompositedSelectionBoundsTest, EditableDiv) {
@@ -6436,9 +6449,11 @@ TEST_P(CompositedSelectionBoundsTest, SVGTextWithFragments) {
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
#if !defined(OS_ANDROID)
TEST_P(CompositedSelectionBoundsTest, Input) {
+ web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(16);
RunTest("composited_selection_bounds_input.html");
}
TEST_P(CompositedSelectionBoundsTest, InputScrolled) {
+ web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(16);
RunTest("composited_selection_bounds_input_scrolled.html");
}
#endif
@@ -6480,11 +6495,11 @@ INSTANTIATE_TEST_SUITE_P(All,
testing::Bool(),
CompositedSelectionBoundsTestPassToString());
-class TestWillInsertBodyWebFrameClient
+class TestWillInsertBodyWebFrameClient final
: public frame_test_helpers::TestWebFrameClient {
public:
TestWillInsertBodyWebFrameClient() = default;
- ~TestWillInsertBodyWebFrameClient() final = default;
+ ~TestWillInsertBodyWebFrameClient() override = default;
bool did_load() const { return did_load_; }
@@ -6648,7 +6663,7 @@ static void GetSpellingMarkerOffsets(WebVector<unsigned>* offsets,
const Document& document) {
Vector<unsigned> result;
const DocumentMarkerVector& document_markers = document.Markers().Markers();
- for (size_t i = 0; i < document_markers.size(); ++i)
+ for (wtf_size_t i = 0; i < document_markers.size(); ++i)
result.push_back(document_markers[i]->StartOffset());
offsets->Assign(result);
}
@@ -7080,7 +7095,7 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
auto* scrollable_area = frame_impl->GetFrameView()->LayoutViewport();
// Do a compositor scroll, verify that this is counted as a user scroll.
- scrollable_area->DidScroll(FloatPoint(0, 1));
+ scrollable_area->DidCompositorScroll(FloatPoint(0, 1));
web_view_helper.GetWebView()
->MainFrameWidget()
->ApplyViewportChangesForTesting({gfx::ScrollOffset(), gfx::Vector2dF(),
@@ -7093,7 +7108,7 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
initial_scroll_state.was_scrolled_by_user = false;
// The page scale 1.0f and scroll.
- scrollable_area->DidScroll(FloatPoint(0, 2));
+ scrollable_area->DidCompositorScroll(FloatPoint(0, 2));
web_view_helper.GetWebView()
->MainFrameWidget()
->ApplyViewportChangesForTesting({gfx::ScrollOffset(), gfx::Vector2dF(),
@@ -7105,7 +7120,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(FloatPoint(0, 2));
+ scrollable_area->DidCompositorScroll(FloatPoint(0, 2));
web_view_helper.GetWebView()
->MainFrameWidget()
->ApplyViewportChangesForTesting({gfx::ScrollOffset(), gfx::Vector2dF(),
@@ -7116,7 +7131,7 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
client.Reset();
// Non zero page scale and scroll.
- scrollable_area->DidScroll(FloatPoint(9, 15));
+ scrollable_area->DidCompositorScroll(FloatPoint(9, 15));
web_view_helper.GetWebView()
->MainFrameWidget()
->ApplyViewportChangesForTesting({gfx::ScrollOffset(), gfx::Vector2dF(),
@@ -7329,10 +7344,10 @@ class TestCachePolicyWebFrameClient
mojom::FetchCacheMode GetCacheMode() const { return cache_mode_; }
int BeginNavigationCallCount() const { return begin_navigation_call_count_; }
- TestCachePolicyWebFrameClient& ChildClient(size_t i) {
+ TestCachePolicyWebFrameClient& ChildClient(wtf_size_t i) {
return *child_clients_[i].get();
}
- size_t ChildFrameCreationCount() const { return child_clients_.size(); }
+ wtf_size_t ChildFrameCreationCount() const { return child_clients_.size(); }
// frame_test_helpers::TestWebFrameClient:
WebLocalFrame* CreateChildFrame(
@@ -7400,45 +7415,6 @@ TEST_F(WebFrameTest, ReloadIframe) {
EXPECT_EQ(mojom::FetchCacheMode::kDefault, new_child_client->GetCacheMode());
}
-class TestSameDocumentWebFrameClient
- : public frame_test_helpers::TestWebFrameClient {
- public:
- TestSameDocumentWebFrameClient() : frame_load_type_reload_seen_(false) {}
- ~TestSameDocumentWebFrameClient() override = default;
-
- // frame_test_helpers::TestWebFrameClient:
- void BeginNavigation(std::unique_ptr<WebNavigationInfo> info) override {
- if (info->frame_load_type == WebFrameLoadType::kReload)
- frame_load_type_reload_seen_ = true;
- TestWebFrameClient::BeginNavigation(std::move(info));
- }
-
- bool FrameLoadTypeReloadSeen() const { return frame_load_type_reload_seen_; }
-
- private:
- bool frame_load_type_reload_seen_;
-};
-
-TEST_F(WebFrameTest, NavigateToSame) {
- RegisterMockedHttpURLLoad("navigate_to_same.html");
- TestSameDocumentWebFrameClient client;
- frame_test_helpers::WebViewHelper web_view_helper;
- WebViewImpl* web_view = web_view_helper.InitializeAndLoad(
- base_url_ + "navigate_to_same.html", &client);
- web_view->SetHistoryListFromNavigation(0, 1);
- EXPECT_FALSE(client.FrameLoadTypeReloadSeen());
-
- auto* local_frame =
- To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
- FrameLoadRequest frame_request(
- nullptr, ResourceRequest(local_frame->GetDocument()->Url()));
- local_frame->Loader().StartNavigation(frame_request);
- frame_test_helpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.LocalMainFrame());
-
- EXPECT_TRUE(client.FrameLoadTypeReloadSeen());
-}
-
class TestMainFrameIntersectionChanged
: public frame_test_helpers::TestWebFrameClient {
public:
@@ -7676,6 +7652,39 @@ TEST_F(WebFrameTest, IPAddressSpace) {
}
}
+TEST_F(WebFrameTest,
+ CommitSynchronousNavigationForAboutBlankAndCheckStorageKeyNonce) {
+ frame_test_helpers::WebViewHelper web_view_helper;
+ web_view_helper.InitializeAndLoad("data:text/html,<iframe></iframe>");
+
+ StorageKey storage_key = StorageKey::CreateWithNonce(
+ url::Origin(), base::UnguessableToken::Create());
+
+ auto* child_frame =
+ To<WebLocalFrameImpl>(web_view_helper.LocalMainFrame()->FirstChild());
+ child_frame->GetFrame()->DomWindow()->SetStorageKey(storage_key);
+
+ auto params = std::make_unique<WebNavigationParams>();
+ params->url = url_test_helpers::ToKURL("about:blank");
+ params->navigation_timings.navigation_start = base::TimeTicks::Now();
+ params->navigation_timings.fetch_start = base::TimeTicks::Now();
+ params->is_browser_initiated = true;
+ MockPolicyContainerHost mock_policy_container_host;
+ params->policy_container = std::make_unique<WebPolicyContainer>(
+ WebPolicyContainerPolicies(),
+ mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
+ params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
+ params->is_synchronous_commit_for_bug_778318 = true;
+
+ params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
+ child_frame->CommitNavigation(std::move(params), nullptr);
+ frame_test_helpers::PumpPendingRequestsForFrameToLoad(child_frame);
+
+ // The synchronous commit for bug 778318 should not change the storage key.
+ EXPECT_EQ(storage_key.nonce(),
+ child_frame->GetFrame()->DomWindow()->GetStorageKey().GetNonce());
+}
+
class TestDidNavigateCommitTypeWebFrameClient
: public frame_test_helpers::TestWebFrameClient {
public:
@@ -7686,7 +7695,7 @@ class TestDidNavigateCommitTypeWebFrameClient
// frame_test_helpers::TestWebFrameClient:
void DidFinishSameDocumentNavigation(WebHistoryCommitType type,
bool is_synchronously_committed,
- bool is_history_api_navigation,
+ mojom::blink::SameDocumentNavigationType,
bool is_client_redirect) override {
last_commit_type_ = type;
}
@@ -7718,33 +7727,6 @@ TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType) {
EXPECT_EQ(kWebBackForwardCommit, client.LastCommitType());
}
-// Tests that the first navigation in an initially blank subframe will result in
-// a history entry being replaced and not a new one being added.
-TEST_F(WebFrameTest, FirstBlankSubframeNavigation) {
- RegisterMockedHttpURLLoad("history.html");
- RegisterMockedHttpURLLoad("find.html");
-
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad("about:blank");
-
- WebLocalFrame* frame = web_view_helper.LocalMainFrame();
-
- frame->ExecuteScript(WebScriptSource(WebString::FromUTF8(
- "document.body.appendChild(document.createElement('iframe'))")));
-
- auto* iframe = To<WebLocalFrameImpl>(frame->FirstChild());
-
- std::string url1 = base_url_ + "history.html";
- frame_test_helpers::LoadFrame(iframe, url1);
- EXPECT_EQ(url1, iframe->GetDocument().Url().GetString().Utf8());
- EXPECT_TRUE(iframe->GetDocumentLoader()->ReplacesCurrentHistoryItem());
-
- std::string url2 = base_url_ + "find.html";
- frame_test_helpers::LoadFrame(iframe, url2);
- EXPECT_EQ(url2, iframe->GetDocument().Url().GetString().Utf8());
- EXPECT_FALSE(iframe->GetDocumentLoader()->ReplacesCurrentHistoryItem());
-}
-
// Tests that a navigation in a frame with a non-blank initial URL will create
// a new history item, unlike the case above.
TEST_F(WebFrameTest, FirstNonBlankSubframeNavigation) {
@@ -9077,7 +9059,7 @@ TEST_F(WebFrameSwapTest, ValidateSizeOnRemoteToLocalMainFrameSwap) {
WebRemoteFrame* remote_frame = frame_test_helpers::CreateRemote();
MainFrame()->Swap(remote_frame);
- static_cast<WebViewImpl*>(remote_frame->View())->Resize(size);
+ To<WebViewImpl>(remote_frame->View())->Resize(size);
WebLocalFrame* local_frame =
web_view_helper_.CreateProvisional(*remote_frame);
@@ -9085,10 +9067,8 @@ TEST_F(WebFrameSwapTest, ValidateSizeOnRemoteToLocalMainFrameSwap) {
// Verify that the size that was set with a remote main frame is correct
// after swapping to a local frame.
- Page* page = static_cast<WebViewImpl*>(local_frame->View())
- ->GetPage()
- ->MainFrame()
- ->GetPage();
+ Page* page =
+ To<WebViewImpl>(local_frame->View())->GetPage()->MainFrame()->GetPage();
EXPECT_EQ(size.width(), page->GetVisualViewport().Size().Width());
EXPECT_EQ(size.height(), page->GetVisualViewport().Size().Height());
}
@@ -9105,7 +9085,7 @@ TEST_F(WebFrameSwapTest,
WebLocalFrame* local_frame =
web_view_helper_.CreateProvisional(*remote_frame);
- WebViewImpl* web_view = static_cast<WebViewImpl*>(local_frame->View());
+ WebViewImpl* web_view = To<WebViewImpl>(local_frame->View());
EXPECT_TRUE(web_view->MainFrame() &&
web_view->MainFrame()->IsWebRemoteFrame());
@@ -9119,10 +9099,8 @@ TEST_F(WebFrameSwapTest,
// Swap the provisional frame in and verify that the browser controls size is
// correct.
remote_frame->Swap(local_frame);
- Page* page = static_cast<WebViewImpl*>(local_frame->View())
- ->GetPage()
- ->MainFrame()
- ->GetPage();
+ Page* page =
+ To<WebViewImpl>(local_frame->View())->GetPage()->MainFrame()->GetPage();
EXPECT_EQ(top_browser_controls_height,
page->GetBrowserControls().TopHeight());
EXPECT_EQ(bottom_browser_controls_height,
@@ -9652,29 +9630,6 @@ class RemoteToLocalSwapWebFrameClient
absl::optional<WebHistoryCommitType> history_commit_type_;
};
-// The commit type should be Initial if we are swapping a RemoteFrame to a
-// LocalFrame as it is first being created. This happens when another frame
-// exists in the same process, such that we create the RemoteFrame before the
-// first navigation occurs.
-TEST_F(WebFrameSwapTest, HistoryCommitTypeAfterNewRemoteToLocalSwap) {
- WebRemoteFrame* remote_frame = frame_test_helpers::CreateRemote();
- WebFrame* target_frame = MainFrame()->FirstChild();
- ASSERT_TRUE(target_frame);
- target_frame->Swap(remote_frame);
- ASSERT_TRUE(MainFrame()->FirstChild());
- ASSERT_EQ(MainFrame()->FirstChild(), remote_frame);
-
- RemoteToLocalSwapWebFrameClient client;
- WebLocalFrame* local_frame =
- web_view_helper_.CreateProvisional(*remote_frame, &client);
- frame_test_helpers::LoadFrame(local_frame, base_url_ + "subframe-hello.html");
- EXPECT_EQ(kWebHistoryInertCommit, client.HistoryCommitType());
-
- // Manually reset to break WebViewHelper's dependency on the stack allocated
- // TestWebFrameClient.
- Reset();
-}
-
// The commit type should be Standard if we are swapping a RemoteFrame to a
// LocalFrame after commits have already happened in the frame. The browser
// process will inform us via setCommittedFirstRealLoad.
@@ -9894,10 +9849,11 @@ TEST_F(WebFrameTest, SwapWithOpenerCycle) {
EXPECT_EQ(local_frame, local_frame->Opener());
}
-class CommitTypeWebFrameClient : public frame_test_helpers::TestWebFrameClient {
+class CommitTypeWebFrameClient final
+ : public frame_test_helpers::TestWebFrameClient {
public:
CommitTypeWebFrameClient() = default;
- ~CommitTypeWebFrameClient() final = default;
+ ~CommitTypeWebFrameClient() override = default;
WebHistoryCommitType HistoryCommitType() const {
return history_commit_type_;
@@ -9916,24 +9872,6 @@ class CommitTypeWebFrameClient : public frame_test_helpers::TestWebFrameClient {
WebHistoryCommitType history_commit_type_ = kWebHistoryInertCommit;
};
-TEST_F(WebFrameTest, RemoteFrameInitialCommitType) {
- frame_test_helpers::WebViewHelper helper;
- helper.InitializeRemote(nullptr, SecurityOrigin::CreateFromString(
- WebString::FromUTF8(base_url_)));
-
- // If an iframe has a remote main frame, ensure the inital commit is correctly
- // identified as kWebHistoryInertCommit.
- CommitTypeWebFrameClient child_frame_client;
- WebLocalFrame* child_frame = helper.CreateLocalChild(
- *helper.RemoteMainFrame(), "frameName", WebFrameOwnerProperties(),
- nullptr, &child_frame_client);
- RegisterMockedHttpURLLoad("foo.html");
- frame_test_helpers::LoadFrame(child_frame, base_url_ + "foo.html");
- EXPECT_EQ(kWebHistoryInertCommit, child_frame_client.HistoryCommitType());
-
- helper.Reset();
-}
-
TEST_F(WebFrameTest, DetachRemoteFrame) {
frame_test_helpers::WebViewHelper helper;
helper.InitializeRemote();
@@ -10017,7 +9955,7 @@ TEST_F(WebFrameTest, ResizeInvalidatesDeviceMediaQueries) {
Element* element = frame->GetDocument()->getElementById("test");
ASSERT_TRUE(element);
- ScreenInfo screen_info =
+ display::ScreenInfo screen_info =
web_view_helper.GetMainFrameWidget()->GetOriginalScreenInfo();
screen_info.rect = screen_info.available_rect = gfx::Rect(700, 500);
UpdateScreenInfoAndResizeView(&web_view_helper, screen_info);
@@ -10059,7 +9997,7 @@ class DeviceEmulationTest : public WebFrameTest {
}
void TestResize(const gfx::Size& size, const String& expected_size) {
- ScreenInfo screen_info =
+ display::ScreenInfo screen_info =
web_view_helper_.GetMainFrameWidget()->GetOriginalScreenInfo();
screen_info.rect = screen_info.available_rect = gfx::Rect(size);
UpdateScreenInfoAndResizeView(&web_view_helper_, screen_info);
@@ -12995,6 +12933,9 @@ class ContextMenuWebFrameClient
: public frame_test_helpers::TestWebFrameClient {
public:
ContextMenuWebFrameClient() = default;
+ ContextMenuWebFrameClient(const ContextMenuWebFrameClient&) = delete;
+ ContextMenuWebFrameClient& operator=(const ContextMenuWebFrameClient&) =
+ delete;
~ContextMenuWebFrameClient() override = default;
// WebLocalFrameClient:
@@ -13008,7 +12949,6 @@ class ContextMenuWebFrameClient
private:
ContextMenuData menu_data_;
- DISALLOW_COPY_AND_ASSIGN(ContextMenuWebFrameClient);
};
bool TestSelectAll(const std::string& html) {
@@ -13204,7 +13144,8 @@ TEST_F(WebFrameTest, RecordSameDocumentNavigationToHistogram) {
SerializeString("message", ToScriptStateForMainWorld(frame));
tester.ExpectTotalCount(histogramName, 0);
document_loader.UpdateForSameDocumentNavigation(
- ToKURL("about:blank"), kSameDocumentNavigationHistoryApi, message,
+ ToKURL("about:blank"),
+ mojom::blink::SameDocumentNavigationType::kHistoryApi, message,
mojom::blink::ScrollRestorationType::kAuto,
WebFrameLoadType::kReplaceCurrentItem,
frame->DomWindow()->GetSecurityOrigin(),
@@ -13214,23 +13155,25 @@ TEST_F(WebFrameTest, RecordSameDocumentNavigationToHistogram) {
tester.ExpectBucketCount(histogramName,
kSPANavTypeHistoryPushStateOrReplaceState, 1);
document_loader.UpdateForSameDocumentNavigation(
- ToKURL("about:blank"), kSameDocumentNavigationDefault, message,
+ ToKURL("about:blank"),
+ mojom::blink::SameDocumentNavigationType::kFragment, message,
mojom::blink::ScrollRestorationType::kManual,
WebFrameLoadType::kBackForward, frame->DomWindow()->GetSecurityOrigin(),
/*is_synchronously_committed=*/true);
tester.ExpectBucketCount(histogramName,
kSPANavTypeSameDocumentBackwardOrForward, 1);
document_loader.UpdateForSameDocumentNavigation(
- ToKURL("about:blank"), kSameDocumentNavigationDefault, message,
+ ToKURL("about:blank"),
+ mojom::blink::SameDocumentNavigationType::kFragment, message,
mojom::blink::ScrollRestorationType::kManual,
WebFrameLoadType::kReplaceCurrentItem,
frame->DomWindow()->GetSecurityOrigin(),
/*is_synchronously_committed=*/true);
tester.ExpectBucketCount(histogramName, kSPANavTypeOtherFragmentNavigation,
1);
- // kSameDocumentNavigationHistoryApi and WebFrameLoadType::kBackForward is an
- // illegal combination, which has been caught by DCHECK in
- // UpdateForSameDocumentNavigation().
+ // mojom::blink::SameDocumentNavigationType::kHistoryApi and
+ // WebFrameLoadType::kBackForward is an illegal combination, which has been
+ // caught by DCHECK in UpdateForSameDocumentNavigation().
tester.ExpectTotalCount(histogramName, 3);
}
@@ -13614,7 +13557,8 @@ TEST_F(WebFrameTest, MediaQueriesInLocalFrameInsideRemote) {
frame_test_helpers::TestWebFrameWidget* local_frame_widget =
static_cast<frame_test_helpers::TestWebFrameWidget*>(
local_frame->FrameWidgetImpl());
- ScreenInfos screen_infos(local_frame_widget->GetOriginalScreenInfo());
+ display::ScreenInfos screen_infos(
+ local_frame_widget->GetOriginalScreenInfo());
screen_infos.mutable_current().is_monochrome = false;
screen_infos.mutable_current().depth_per_component = 8;
local_frame_widget->UpdateScreenInfo(screen_infos);
@@ -14002,7 +13946,8 @@ TEST_F(WebFrameTest, RemoteFrameCompositingScaleFactor) {
// The compositing scale factor tells the OOPIF compositor to raster at a
// lower scale since the frame is scaled down in the parent webview.
EXPECT_EQ(remote_frame->GetCompositingRect(), gfx::Rect(0, 0, 1600, 1200));
- EXPECT_EQ(remote_frame->GetCompositingScaleFactor(), 0.5f);
+ EXPECT_EQ(remote_frame->GetFrame()->View()->GetCompositingScaleFactor(),
+ 0.5f);
}
TEST_F(WebFrameTest, RotatedRemoteFrameCompositingScaleFactor) {
@@ -14040,7 +13985,8 @@ TEST_F(WebFrameTest, RotatedRemoteFrameCompositingScaleFactor) {
// The compositing scale factor tells the OOPIF compositor to raster at a
// lower scale since the frame is scaled down in the parent webview.
EXPECT_EQ(remote_frame->GetCompositingRect(), gfx::Rect(0, 0, 1600, 1200));
- EXPECT_EQ(remote_frame->GetCompositingScaleFactor(), 0.5f);
+ EXPECT_EQ(remote_frame->GetFrame()->View()->GetCompositingScaleFactor(),
+ 0.5f);
}
TEST_F(WebFrameTest, ZeroScaleRemoteFrameCompositingScaleFactor) {
@@ -14077,7 +14023,8 @@ TEST_F(WebFrameTest, ZeroScaleRemoteFrameCompositingScaleFactor) {
// The compositing scale factor tells the OOPIF compositor to raster at a
// reasonable minimum scale even though the iframe's transform scale is zero.
- EXPECT_EQ(remote_frame->GetCompositingScaleFactor(), 0.25f);
+ EXPECT_EQ(remote_frame->GetFrame()->View()->GetCompositingScaleFactor(),
+ 0.25f);
}
TEST_F(WebFrameTest, LargeScaleRemoteFrameCompositingScaleFactor) {
@@ -14113,38 +14060,8 @@ TEST_F(WebFrameTest, LargeScaleRemoteFrameCompositingScaleFactor) {
RunPendingTasks();
// The compositing scale factor is at most 5.0 irrespective of iframe scale.
- EXPECT_EQ(remote_frame->GetCompositingScaleFactor(), 5.0f);
-}
-
-TEST_F(WebFrameTest, IsPrerendering) {
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize();
- auto params = std::make_unique<WebNavigationParams>();
- params->url = KURL("about:blank");
- params->is_prerendering = false;
- web_view_helper.LocalMainFrame()->CommitNavigation(std::move(params),
- nullptr);
- WebViewImpl* web_view = web_view_helper.GetWebView();
-
- EXPECT_FALSE(web_view->MainFrameImpl()
- ->GetFrame()
- ->GetDocument()
- ->Fetcher()
- ->Context()
- .IsPrerendering());
-
- params = std::make_unique<WebNavigationParams>();
- params->url = KURL("about:blank");
- params->is_prerendering = true;
- web_view_helper.LocalMainFrame()->CommitNavigation(std::move(params),
- nullptr);
-
- EXPECT_TRUE(web_view->MainFrameImpl()
- ->GetFrame()
- ->GetDocument()
- ->Fetcher()
- ->Context()
- .IsPrerendering());
+ EXPECT_EQ(remote_frame->GetFrame()->View()->GetCompositingScaleFactor(),
+ 5.0f);
}
} // namespace blink
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 3dd4e255bd0..eeec156e231 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
@@ -45,6 +45,7 @@
#include "cc/trees/swap_promise.h"
#include "cc/trees/ukm_manager.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
#include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
@@ -78,6 +79,7 @@
#include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/battery_savings.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
@@ -114,6 +116,7 @@
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
@@ -1216,6 +1219,13 @@ void WebFrameWidgetImpl::SetOverscrollBehavior(
widget_base_->LayerTreeHost()->SetOverscrollBehavior(overscroll_behavior);
}
+void WebFrameWidgetImpl::SetPrefersReducedMotion(bool prefers_reduced_motion) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->SetPrefersReducedMotion(
+ prefers_reduced_motion);
+}
+
void WebFrameWidgetImpl::RegisterSelection(cc::LayerSelection selection) {
if (!View()->does_composite())
return;
@@ -1508,6 +1518,10 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
widget_base_->VisibleViewportSizeInDIPs()),
visual_properties.browser_controls_params);
}
+
+ LocalRootImpl()->GetFrame()->UpdateWindowControlsOverlay(
+ visual_properties.window_controls_overlay_rect);
+
} else {
// Widgets in a WebView's frame tree without a local main frame
// set the size of the WebView to be the |visible_viewport_size|, in order
@@ -1606,10 +1620,11 @@ const WebVector<gfx::Rect>& WebFrameWidgetImpl::WindowSegments() const {
return window_segments_;
}
-void WebFrameWidgetImpl::StartDeferringCommits(base::TimeDelta timeout) {
+bool WebFrameWidgetImpl::StartDeferringCommits(base::TimeDelta timeout,
+ cc::PaintHoldingReason reason) {
if (!View()->does_composite())
- return;
- widget_base_->LayerTreeHost()->StartDeferringCommits(timeout);
+ return false;
+ return widget_base_->LayerTreeHost()->StartDeferringCommits(timeout, reason);
}
void WebFrameWidgetImpl::StopDeferringCommits(
@@ -1651,8 +1666,8 @@ void WebFrameWidgetImpl::SetDeviceColorSpaceForTesting(
// new viz::LocalSurfaceId to avoid surface invariants violations in tests.
widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
- blink::ScreenInfos screen_infos = widget_base_->screen_infos();
- for (blink::ScreenInfo& screen_info : screen_infos.screen_infos)
+ display::ScreenInfos screen_infos = widget_base_->screen_infos();
+ for (display::ScreenInfo& screen_info : screen_infos.screen_infos)
screen_info.display_color_spaces = gfx::DisplayColorSpaces(color_space);
widget_base_->UpdateScreenInfo(screen_infos);
}
@@ -1910,7 +1925,7 @@ void WebFrameWidgetImpl::ResetMeaningfulLayoutStateForMainFrame() {
void WebFrameWidgetImpl::InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const cc::LayerTreeSettings* settings) {
DCHECK(View()->does_composite());
DCHECK(!non_composited_client_); // Assure only one initialize is called.
@@ -2018,6 +2033,13 @@ void WebFrameWidgetImpl::BeginCommitCompositorFrame() {
void WebFrameWidgetImpl::EndCommitCompositorFrame(
base::TimeTicks commit_start_time) {
DCHECK(commit_compositor_frame_start_time_.has_value());
+ if (ForTopMostMainFrame()) {
+ Document* doc = local_root_->GetFrame()->GetDocument();
+ if (doc->GetSettings()->GetViewportMetaEnabled() &&
+ !LayerTreeHost()->IsMobileOptimized()) {
+ UseCounter::Count(doc, WebFeature::kTapDelayEnabled);
+ }
+ }
if (ForMainFrame()) {
View()->DidCommitCompositorFrameForLocalMainFrame();
View()->UpdatePreferredSize();
@@ -2081,9 +2103,13 @@ void WebFrameWidgetImpl::RecordManipulationTypeCounts(
void WebFrameWidgetImpl::RecordDispatchRafAlignedInputTime(
base::TimeTicks raf_aligned_input_start_time) {
if (LocalRootImpl()) {
- LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
- LocalFrameUkmAggregator::kHandleInputEvents,
- raf_aligned_input_start_time, base::TimeTicks::Now());
+ LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .RecordTimerSample(LocalFrameUkmAggregator::kHandleInputEvents,
+ raf_aligned_input_start_time,
+ base::TimeTicks::Now());
}
}
@@ -2171,9 +2197,13 @@ void WebFrameWidgetImpl::BeginUpdateLayers() {
void WebFrameWidgetImpl::EndUpdateLayers() {
if (LocalRootImpl()) {
DCHECK(update_layers_start_time_);
- LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
- LocalFrameUkmAggregator::kUpdateLayers,
- update_layers_start_time_.value(), base::TimeTicks::Now());
+ LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .RecordTimerSample(LocalFrameUkmAggregator::kUpdateLayers,
+ update_layers_start_time_.value(),
+ base::TimeTicks::Now());
probe::LayerTreeDidChange(LocalRootImpl()->GetFrame());
}
update_layers_start_time_.reset();
@@ -2200,28 +2230,30 @@ void WebFrameWidgetImpl::RecordEndOfFrameMetrics(
trackers);
}
-bool WebFrameWidgetImpl::WillHandleGestureEvent(const WebGestureEvent& event) {
+void WebFrameWidgetImpl::WillHandleGestureEvent(const WebGestureEvent& event,
+ bool* suppress) {
possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kTouch;
possible_drag_event_info_.location =
gfx::ToFlooredPoint(event.PositionInScreen());
- bool move_cursor = false;
+ bool handle_as_cursor_control = false;
switch (event.GetType()) {
case WebInputEvent::Type::kGestureScrollBegin: {
if (event.data.scroll_begin.cursor_control) {
swipe_to_move_cursor_activated_ = true;
- move_cursor = true;
+ handle_as_cursor_control = true;
}
break;
}
case WebInputEvent::Type::kGestureScrollUpdate: {
if (swipe_to_move_cursor_activated_)
- move_cursor = true;
+ handle_as_cursor_control = true;
break;
}
case WebInputEvent::Type::kGestureScrollEnd: {
if (swipe_to_move_cursor_activated_) {
swipe_to_move_cursor_activated_ = false;
+ handle_as_cursor_control = true;
}
break;
}
@@ -2230,16 +2262,15 @@ bool WebFrameWidgetImpl::WillHandleGestureEvent(const WebGestureEvent& event) {
}
// TODO(crbug.com/1140106): Place cursor for scroll begin other than just move
// cursor.
- if (move_cursor) {
+ if (handle_as_cursor_control) {
WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
if (focused_frame) {
gfx::Point base(event.PositionInWidget().x(),
event.PositionInWidget().y());
focused_frame->MoveCaretSelection(base);
}
- return true;
+ *suppress = true;
}
- return false;
}
void WebFrameWidgetImpl::WillHandleMouseEvent(const WebMouseEvent& event) {
@@ -2561,12 +2592,13 @@ float WebFrameWidgetImpl::PageScaleInMainFrame() {
void WebFrameWidgetImpl::UpdateSurfaceAndScreenInfo(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect,
- const ScreenInfos& new_screen_infos) {
+ const display::ScreenInfos& new_screen_infos) {
widget_base_->UpdateSurfaceAndScreenInfo(
new_local_surface_id, compositor_viewport_pixel_rect, new_screen_infos);
}
-void WebFrameWidgetImpl::UpdateScreenInfo(const ScreenInfos& new_screen_infos) {
+void WebFrameWidgetImpl::UpdateScreenInfo(
+ const display::ScreenInfos& new_screen_infos) {
widget_base_->UpdateScreenInfo(new_screen_infos);
}
@@ -2582,21 +2614,21 @@ void WebFrameWidgetImpl::UpdateCompositorViewportRect(
widget_base_->UpdateCompositorViewportRect(compositor_viewport_pixel_rect);
}
-const ScreenInfo& WebFrameWidgetImpl::GetScreenInfo() {
+const display::ScreenInfo& WebFrameWidgetImpl::GetScreenInfo() {
return widget_base_->GetScreenInfo();
}
-const ScreenInfos& WebFrameWidgetImpl::GetScreenInfos() {
+const display::ScreenInfos& WebFrameWidgetImpl::GetScreenInfos() {
return widget_base_->screen_infos();
}
-const ScreenInfo& WebFrameWidgetImpl::GetOriginalScreenInfo() {
+const display::ScreenInfo& WebFrameWidgetImpl::GetOriginalScreenInfo() {
if (device_emulator_)
return device_emulator_->GetOriginalScreenInfo();
return widget_base_->GetScreenInfo();
}
-const ScreenInfos& WebFrameWidgetImpl::GetOriginalScreenInfos() {
+const display::ScreenInfos& WebFrameWidgetImpl::GetOriginalScreenInfos() {
if (device_emulator_)
return device_emulator_->original_screen_infos();
return widget_base_->screen_infos();
@@ -2666,7 +2698,7 @@ void WebFrameWidgetImpl::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
NotifySwapAndPresentationTime(
base::NullCallback(),
WTF::Bind(&WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout,
- WrapPersistent(this)));
+ WrapWeakPersistent(this)));
}
ForEachLocalFrameControlledByWidget(
@@ -2681,7 +2713,10 @@ void WebFrameWidgetImpl::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
void WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout(
blink::WebSwapResult,
base::TimeTicks) {
- GetAssociatedFrameWidgetHost()->DidFirstVisuallyNonEmptyPaint();
+ // |local_root_| may be null if the widget has shut down between when this
+ // callback was requested and when it was resolved by the compositor.
+ if (local_root_)
+ local_root_->ViewImpl()->DidFirstVisuallyNonEmptyPaint();
}
void WebFrameWidgetImpl::RequestAnimationAfterDelay(
@@ -2775,6 +2810,8 @@ class ReportTimeSwapPromise : public cc::SwapPromise {
presentation_time_callback_(std::move(presentation_time_callback)),
task_runner_(std::move(task_runner)),
widget_(widget) {}
+ ReportTimeSwapPromise(const ReportTimeSwapPromise&) = delete;
+ ReportTimeSwapPromise& operator=(const ReportTimeSwapPromise&) = delete;
~ReportTimeSwapPromise() override = default;
void DidActivate() override {}
@@ -2887,8 +2924,6 @@ class ReportTimeSwapPromise : public cc::SwapPromise {
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
CrossThreadWeakPersistent<WebFrameWidgetImpl> widget_;
uint32_t frame_token_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise);
};
void WebFrameWidgetImpl::NotifyPresentationTimeInBlink(
@@ -3086,6 +3121,12 @@ void WebFrameWidgetImpl::UpdateTooltipUnderCursor(const String& tooltip_text,
widget_base_->UpdateTooltipUnderCursor(tooltip_text, dir);
}
+void WebFrameWidgetImpl::UpdateTooltipFromKeyboard(const String& tooltip_text,
+ TextDirection dir,
+ const gfx::Rect& bounds) {
+ widget_base_->UpdateTooltipFromKeyboard(tooltip_text, dir, bounds);
+}
+
void WebFrameWidgetImpl::DidOverscroll(
const gfx::Vector2dF& overscroll_delta,
const gfx::Vector2dF& accumulated_overscroll,
@@ -3687,7 +3728,7 @@ void WebFrameWidgetImpl::SetScreenMetricsEmulationParameters(
}
void WebFrameWidgetImpl::SetScreenInfoAndSize(
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const gfx::Size& widget_size_in_dips,
const gfx::Size& visible_viewport_size_in_dips) {
// Emulation happens on regular main frames which don't use auto-resize mode.
@@ -3792,8 +3833,8 @@ void WebFrameWidgetImpl::OrientationChanged() {
}
void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
- const ScreenInfo& previous_original_screen_info) {
- ScreenInfo screen_info = widget_base_->GetScreenInfo();
+ const display::ScreenInfo& previous_original_screen_info) {
+ display::ScreenInfo screen_info = widget_base_->GetScreenInfo();
if (Platform::Current()->IsUseZoomForDSFEnabled()) {
View()->SetZoomFactorForDeviceScaleFactor(screen_info.device_scale_factor);
} else {
@@ -3814,7 +3855,7 @@ void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
// When the device scale changes, the size and position of the popup would
// need to be adjusted, which we can't do. Just close the popup, which is
// also consistent with page zoom and resize behavior.
- ScreenInfo original_screen_info = GetOriginalScreenInfo();
+ display::ScreenInfo original_screen_info = GetOriginalScreenInfo();
if (previous_original_screen_info.device_scale_factor !=
original_screen_info.device_scale_factor) {
View()->CancelPagePopup();
@@ -3839,7 +3880,8 @@ void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
// Propagate changes down to child local root RenderWidgets and
// BrowserPlugins in other frame trees/processes.
ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
- [](const ScreenInfo& original_screen_info, RemoteFrame* remote_frame) {
+ [](const display::ScreenInfo& original_screen_info,
+ RemoteFrame* remote_frame) {
remote_frame->DidChangeScreenInfo(original_screen_info);
},
original_screen_info));
@@ -3854,7 +3896,7 @@ gfx::Rect WebFrameWidgetImpl::ViewportVisibleRect() {
}
}
-absl::optional<blink::mojom::ScreenOrientation>
+absl::optional<display::mojom::blink::ScreenOrientation>
WebFrameWidgetImpl::ScreenOrientationOverride() {
return View()->ScreenOrientationOverride();
}
@@ -4000,7 +4042,7 @@ void WebFrameWidgetImpl::SetDeviceScaleFactorForTesting(float factor) {
// new viz::LocalSurfaceId to avoid surface invariants violations in tests.
widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
- ScreenInfos screen_infos = widget_base_->screen_infos();
+ display::ScreenInfos screen_infos = widget_base_->screen_infos();
screen_infos.mutable_current().device_scale_factor = factor;
gfx::Size size_with_dsf = gfx::ScaleToCeiledSize(size_in_dips, factor);
widget_base_->UpdateCompositorViewportAndScreenInfo(gfx::Rect(size_with_dsf),
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 3475cad430b..7ccca2f7f12 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
@@ -39,6 +39,7 @@
#include "cc/input/layer_selection_bound.h"
#include "cc/input/overscroll_behavior.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "services/viz/public/mojom/hit_test/input_target_client.mojom-blink.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_gesture_device.h"
@@ -336,7 +337,7 @@ class CORE_EXPORT WebFrameWidgetImpl
// WebWidget overrides.
void InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const cc::LayerTreeSettings* settings) override;
void SetCompositorVisible(bool visible) override;
gfx::Size Size() override;
@@ -359,10 +360,10 @@ class CORE_EXPORT WebFrameWidgetImpl
const VisualProperties& visual_properties) override;
bool PinchGestureActiveInMainFrame() override;
float PageScaleInMainFrame() override;
- const ScreenInfo& GetScreenInfo() override;
- const ScreenInfos& GetScreenInfos() override;
- const ScreenInfo& GetOriginalScreenInfo() override;
- const ScreenInfos& GetOriginalScreenInfos() override;
+ const display::ScreenInfo& GetScreenInfo() override;
+ const display::ScreenInfos& GetScreenInfos() override;
+ const display::ScreenInfo& GetOriginalScreenInfo() override;
+ const display::ScreenInfos& GetOriginalScreenInfos() override;
gfx::Rect WindowRect() override;
gfx::Rect ViewRect() override;
void SetScreenRects(const gfx::Rect& widget_screen_rect,
@@ -429,6 +430,9 @@ class CORE_EXPORT WebFrameWidgetImpl
// paint into another widget which has a background color of its own.
void SetBackgroundColor(SkColor color);
+ // Sets whether the prefers-reduced-motion hint has been enabled.
+ void SetPrefersReducedMotion(bool prefers_reduced_motion);
+
// Starts an animation of the page scale to a target scale factor and scroll
// offset.
// If use_anchor is true, destination is a point on the screen that will
@@ -446,7 +450,8 @@ class CORE_EXPORT WebFrameWidgetImpl
// updates without committing the layer tree. Commits are deferred
// until at most the given |timeout| has passed. If multiple calls are made
// when deferral is active then the initial timeout applies.
- void StartDeferringCommits(base::TimeDelta timeout);
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ cc::PaintHoldingReason reason);
// Immediately stop deferring commits.
void StopDeferringCommits(cc::PaintHoldingCommitTrigger);
@@ -496,6 +501,9 @@ class CORE_EXPORT WebFrameWidgetImpl
void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
void UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir);
+ void UpdateTooltipFromKeyboard(const String& tooltip_text,
+ TextDirection dir,
+ const gfx::Rect& bounds);
void ShowVirtualKeyboardOnElementFocus();
void ProcessTouchAction(WebTouchAction touch_action);
@@ -547,7 +555,7 @@ class CORE_EXPORT WebFrameWidgetImpl
void SetScreenMetricsEmulationParameters(
bool enabled,
const blink::DeviceEmulationParams& params);
- void SetScreenInfoAndSize(const ScreenInfos& screen_infos,
+ void SetScreenInfoAndSize(const display::ScreenInfos& screen_infos,
const gfx::Size& widget_size,
const gfx::Size& visible_viewport_size);
@@ -556,10 +564,10 @@ class CORE_EXPORT WebFrameWidgetImpl
void UpdateSurfaceAndScreenInfo(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect,
- const ScreenInfos& screen_infos);
+ const display::ScreenInfos& screen_infos);
// Similar to UpdateSurfaceAndScreenInfo but the surface allocation
// and compositor viewport rect remains the same.
- void UpdateScreenInfo(const ScreenInfos& screen_infos);
+ void UpdateScreenInfo(const display::ScreenInfos& screen_infos);
void UpdateSurfaceAndCompositorRect(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect);
@@ -631,7 +639,8 @@ class CORE_EXPORT WebFrameWidgetImpl
base::TimeTicks first_scroll_timestamp) override;
void DidCompletePageScaleAnimation() override;
void FocusChangeComplete() override;
- bool WillHandleGestureEvent(const WebGestureEvent& event) override;
+ void WillHandleGestureEvent(const WebGestureEvent& event,
+ bool* suppress) override;
void WillHandleMouseEvent(const WebMouseEvent& event) override;
void ObserveGestureEventAndResult(
const WebGestureEvent& gesture_event,
@@ -651,10 +660,10 @@ class CORE_EXPORT WebFrameWidgetImpl
const gfx::Rect& window_screen_rect) override;
void OrientationChanged() override;
void DidUpdateSurfaceAndScreen(
- const ScreenInfo& previous_original_screen_info) override;
+ const display::ScreenInfo& previous_original_screen_info) override;
gfx::Rect ViewportVisibleRect() override;
- absl::optional<blink::mojom::ScreenOrientation> ScreenOrientationOverride()
- override;
+ absl::optional<display::mojom::blink::ScreenOrientation>
+ ScreenOrientationOverride() override;
void WasHidden() override;
void WasShown(bool was_evicted) override;
void RunPaintBenchmark(int repeat_count,
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_test.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
index 9a47b7555be..7e16a2c8978 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
@@ -6,6 +6,7 @@
#include "base/callback_helpers.h"
#include "base/run_loop.h"
+#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "cc/layers/solid_color_layer.h"
@@ -61,7 +62,7 @@ TEST_F(WebFrameWidgetSimTest, AutoResizeAllocatedLocalSurfaceId) {
// Enable auto-resize.
VisualProperties visual_properties;
- visual_properties.screen_infos = ScreenInfos(ScreenInfo());
+ visual_properties.screen_infos = display::ScreenInfos(display::ScreenInfo());
visual_properties.auto_resize_enabled = true;
visual_properties.min_size_for_auto_resize = gfx::Size(100, 100);
visual_properties.max_size_for_auto_resize = gfx::Size(200, 200);
@@ -165,7 +166,7 @@ TEST_F(WebFrameWidgetImplRemoteFrameSimTest,
LocalFrameRootWidget()->LayerTreeHostForTesting();
EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing());
VisualProperties visual_properties;
- visual_properties.screen_infos = ScreenInfos(ScreenInfo());
+ visual_properties.screen_infos = display::ScreenInfos(display::ScreenInfo());
// Sync visual properties on a child widget.
visual_properties.is_pinch_gesture_active = true;
@@ -203,6 +204,8 @@ enum {
class MockHandledEventCallback {
public:
MockHandledEventCallback() = default;
+ MockHandledEventCallback(const MockHandledEventCallback&) = delete;
+ MockHandledEventCallback& operator=(const MockHandledEventCallback&) = delete;
MOCK_METHOD4_T(Run,
void(mojom::InputEventResultState,
const ui::LatencyInfo&,
@@ -222,8 +225,6 @@ class MockHandledEventCallback {
absl::optional<cc::TouchAction> touch_action) {
Run(ack_state, latency_info, overscroll.get(), touch_action);
}
-
- DISALLOW_COPY_AND_ASSIGN(MockHandledEventCallback);
};
class MockWebFrameWidgetImpl : public SimWebFrameWidget {
@@ -242,7 +243,8 @@ class MockWebFrameWidgetImpl : public SimWebFrameWidget {
const cc::OverscrollBehavior& overscroll_behavior,
bool event_processed));
- MOCK_METHOD1(WillHandleGestureEvent, bool(const WebGestureEvent& event));
+ MOCK_METHOD2(WillHandleGestureEvent,
+ void(const WebGestureEvent& event, bool* suppress));
// mojom::blink::WidgetHost overrides:
using SimWebFrameWidget::SetCursor;
@@ -284,7 +286,8 @@ class WebFrameWidgetImplSimTest : public SimTest {
WebCoalescedInputEvent(event.Clone(), {}, {}, ui::LatencyInfo()),
std::move(callback));
}
- bool OverscrollGestureEvent(const blink::WebGestureEvent& event) {
+ void WillHandleGestureEvent(const blink::WebGestureEvent& event,
+ bool* suppress) {
if (event.GetType() == WebInputEvent::Type::kGestureScrollUpdate) {
MockMainFrameWidget()->DidOverscroll(
gfx::Vector2dF(event.data.scroll_update.delta_x,
@@ -294,9 +297,8 @@ class WebFrameWidgetImplSimTest : public SimTest {
event.PositionInWidget(),
gfx::Vector2dF(event.data.scroll_update.velocity_x,
event.data.scroll_update.velocity_y));
- return true;
+ *suppress = true;
}
- return false;
}
const base::HistogramTester& histogram_tester() const {
@@ -335,9 +337,9 @@ TEST_F(WebFrameWidgetImplSimTest, CursorChange) {
}
TEST_F(WebFrameWidgetImplSimTest, EventOverscroll) {
- ON_CALL(*MockMainFrameWidget(), WillHandleGestureEvent(_))
+ ON_CALL(*MockMainFrameWidget(), WillHandleGestureEvent(_, _))
.WillByDefault(testing::Invoke(
- this, &WebFrameWidgetImplSimTest::OverscrollGestureEvent));
+ this, &WebFrameWidgetImplSimTest::WillHandleGestureEvent));
EXPECT_CALL(*MockMainFrameWidget(), HandleInputEvent(_))
.WillRepeatedly(::testing::Return(WebInputEventResult::kNotHandled));
@@ -493,7 +495,7 @@ class NotifySwapTimesWebFrameWidgetTest : public SimTest {
base::RunLoop swap_run_loop;
base::RunLoop presentation_run_loop;
- // Register callbacks for presentation time.
+ // Register callbacks for swap and presentation times.
base::TimeTicks swap_time;
MainFrame().FrameWidget()->NotifySwapAndPresentationTime(
base::BindOnce(
@@ -519,9 +521,9 @@ class NotifySwapTimesWebFrameWidgetTest : public SimTest {
// Present and wait for it to complete.
viz::FrameTimingDetails timing_details;
if (!swap_to_presentation.is_zero()) {
- timing_details.presentation_feedback = gfx::PresentationFeedback(
- /*presentation_time=*/swap_time + swap_to_presentation,
- base::TimeDelta::FromMilliseconds(16), 0);
+ timing_details.presentation_feedback =
+ gfx::PresentationFeedback(swap_time + swap_to_presentation,
+ base::TimeDelta::FromMilliseconds(16), 0);
}
auto* last_frame_sink = GetWebFrameWidget().LastCreatedFrameSink();
last_frame_sink->NotifyDidPresentCompositorFrame(1, timing_details);
@@ -572,6 +574,89 @@ TEST_F(NotifySwapTimesWebFrameWidgetTest,
testing::IsEmpty());
}
+// Verifies that the presentation callback is called after the first successful
+// presentation (skips failed presentations in between).
+TEST_F(NotifySwapTimesWebFrameWidgetTest, NotifyOnSuccessfulPresentation) {
+ base::HistogramTester histograms;
+
+ constexpr base::TimeDelta swap_to_failed =
+ base::TimeDelta::FromMicroseconds(2);
+ constexpr base::TimeDelta failed_to_successful =
+ base::TimeDelta::FromMicroseconds(3);
+
+ base::RunLoop swap_run_loop;
+ base::RunLoop presentation_run_loop;
+
+ base::TimeTicks failed_presentation_time;
+ base::TimeTicks successful_presentation_time;
+
+ // Register callbacks for swap and presentation times.
+ MainFrame().FrameWidget()->NotifySwapAndPresentationTime(
+ base::BindLambdaForTesting(
+ [&](blink::WebSwapResult result, base::TimeTicks timestamp) {
+ DCHECK(!timestamp.is_null());
+
+ // Now that the swap time is known, we can determine what timestamps
+ // should we use for the failed and the subsequent successful
+ // presentations.
+ DCHECK(failed_presentation_time.is_null());
+ failed_presentation_time = timestamp + swap_to_failed;
+ DCHECK(successful_presentation_time.is_null());
+ successful_presentation_time =
+ failed_presentation_time + failed_to_successful;
+
+ swap_run_loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](blink::WebSwapResult result, base::TimeTicks timestamp) {
+ DCHECK(!timestamp.is_null());
+ DCHECK(!failed_presentation_time.is_null());
+ DCHECK(!successful_presentation_time.is_null());
+
+ // Verify that this callback is run in response to the successful
+ // presentation, not the failed one before that.
+ EXPECT_NE(timestamp, failed_presentation_time);
+ EXPECT_EQ(timestamp, successful_presentation_time);
+
+ presentation_run_loop.Quit();
+ }));
+
+ // Composite and wait for the swap to complete.
+ Compositor().BeginFrame(/*time_delta_in_seconds=*/0.016, /*raster=*/true);
+ swap_run_loop.Run();
+
+ // Respond with a failed presentation feedback.
+ DCHECK(!failed_presentation_time.is_null());
+ viz::FrameTimingDetails failed_timing_details;
+ failed_timing_details.presentation_feedback = gfx::PresentationFeedback(
+ failed_presentation_time, base::TimeDelta::FromMilliseconds(16),
+ gfx::PresentationFeedback::kFailure);
+ GetWebFrameWidget().LastCreatedFrameSink()->NotifyDidPresentCompositorFrame(
+ 1, failed_timing_details);
+
+ // Respond with a successful presentation feedback.
+ DCHECK(!successful_presentation_time.is_null());
+ viz::FrameTimingDetails successful_timing_details;
+ successful_timing_details.presentation_feedback = gfx::PresentationFeedback(
+ successful_presentation_time, base::TimeDelta::FromMilliseconds(16), 0);
+ GetWebFrameWidget().LastCreatedFrameSink()->NotifyDidPresentCompositorFrame(
+ 2, successful_timing_details);
+
+ // Wait for the presentation callback to be called. It should be called with
+ // the timestamp of the successful presentation.
+ presentation_run_loop.Run();
+
+ EXPECT_THAT(histograms.GetAllSamples(
+ "PageLoad.Internal.Renderer.PresentationTime.Valid"),
+ testing::ElementsAre(base::Bucket(true, 1)));
+ const auto expected_sample = static_cast<base::HistogramBase::Sample>(
+ (swap_to_failed + failed_to_successful).InMilliseconds());
+ EXPECT_THAT(
+ histograms.GetAllSamples(
+ "PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
+ testing::ElementsAre(base::Bucket(expected_sample, 1)));
+}
+
// Tests that the value of VisualProperties::is_pinch_gesture_active is
// not propagated to the LayerTreeHost when properties are synced for main
// frame.
@@ -580,7 +665,7 @@ TEST_F(WebFrameWidgetSimTest, ActivePinchGestureUpdatesLayerTreeHost) {
WebView().MainFrameViewWidget()->LayerTreeHostForTesting();
EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing());
VisualProperties visual_properties;
- visual_properties.screen_infos = ScreenInfos(ScreenInfo());
+ visual_properties.screen_infos = display::ScreenInfos(display::ScreenInfo());
// Sync visual properties on a mainframe RenderWidget.
visual_properties.is_pinch_gesture_active = true;
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 6ccbeca2b19..13d8f8849c1 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
@@ -91,7 +91,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
@@ -195,6 +194,7 @@
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
+#include "third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.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"
@@ -260,6 +260,7 @@
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -284,6 +285,8 @@ class ChromePrintContext : public PrintContext {
public:
ChromePrintContext(LocalFrame* frame, bool use_printing_layout)
: PrintContext(frame, use_printing_layout), printed_page_width_(0) {}
+ ChromePrintContext(const ChromePrintContext&) = delete;
+ ChromePrintContext& operator=(const ChromePrintContext&) = delete;
~ChromePrintContext() override = default;
@@ -464,8 +467,6 @@ class ChromePrintContext : public PrintContext {
// Set when printing.
float printed_page_width_;
float printed_page_height_;
-
- DISALLOW_COPY_AND_ASSIGN(ChromePrintContext);
};
// Simple class to override some of PrintContext behavior. This is used when
@@ -527,7 +528,10 @@ class ChromePluginPrintContext final : public ChromePrintContext {
class PaintPreviewContext : public PrintContext {
public:
- PaintPreviewContext(LocalFrame* frame) : PrintContext(frame, false) {}
+ explicit PaintPreviewContext(LocalFrame* frame)
+ : PrintContext(frame, false) {}
+ PaintPreviewContext(const PaintPreviewContext&) = delete;
+ PaintPreviewContext& operator=(const PaintPreviewContext&) = delete;
~PaintPreviewContext() override = default;
bool Capture(cc::PaintCanvas* canvas,
@@ -577,9 +581,6 @@ class PaintPreviewContext : public PrintContext {
canvas->drawPicture(builder.EndRecording(property_tree_state.Unalias()));
return true;
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PaintPreviewContext);
};
static WebDocumentLoader* DocumentLoaderForDocLoader(DocumentLoader* loader) {
@@ -652,31 +653,6 @@ bool WebLocalFrameImpl::ConsumeTransientUserActivation(
return LocalFrame::ConsumeTransientUserActivation(GetFrame(), update_source);
}
-void WebLocalFrameImpl::SetOptimizationGuideHints(
- const WebOptimizationGuideHints& web_hints) {
- if (!GetFrame())
- return;
- // Re-build the optimization hints.
- // TODO(https://crbug.com/1113980): Onion-soupify the optimization guide for
- // Blink so that we can directly pass the hints without mojom variant
- // conversion.
- auto hints = mojom::blink::BlinkOptimizationGuideHints::New();
- if (web_hints.delay_async_script_execution_delay_type) {
- hints->delay_async_script_execution_hints =
- mojom::blink::DelayAsyncScriptExecutionHints::New(
- *web_hints.delay_async_script_execution_delay_type);
- }
- if (web_hints.delay_competing_low_priority_requests_delay_type &&
- web_hints.delay_competing_low_priority_requests_priority_threshold) {
- hints->delay_competing_low_priority_requests_hints =
- mojom::blink::DelayCompetingLowPriorityRequestsHints::New(
- *web_hints.delay_competing_low_priority_requests_delay_type,
- *web_hints
- .delay_competing_low_priority_requests_priority_threshold);
- }
- GetFrame()->SetOptimizationGuideHints(std::move(hints));
-}
-
WebLocalFrame* WebLocalFrame::FrameForContext(v8::Local<v8::Context> context) {
return WebLocalFrameImpl::FromFrame(ToLocalFrameIfNotDetached(context));
}
@@ -859,15 +835,6 @@ void WebLocalFrameImpl::SetAdEvidence(
const blink::FrameAdEvidence& ad_evidence) {
DCHECK(GetFrame());
GetFrame()->SetAdEvidence(ad_evidence);
-
- // TODO(alexmt): Remove when AdFrameType is replaced.
- blink::mojom::AdFrameType ad_frame_type = blink::mojom::AdFrameType::kNonAd;
- if (ad_evidence.IndicatesAdSubframe()) {
- ad_frame_type = ad_evidence.parent_is_ad()
- ? blink::mojom::AdFrameType::kChildAd
- : blink::mojom::AdFrameType::kRootAd;
- }
- GetFrame()->SetIsAdSubframe(ad_frame_type);
}
const absl::optional<blink::FrameAdEvidence>& WebLocalFrameImpl::AdEvidence() {
@@ -1084,6 +1051,14 @@ int32_t WebLocalFrameImpl::GetScriptContextWorldId(
return DOMWrapperWorld::World(script_context).GetWorldId();
}
+v8::Local<v8::Context> WebLocalFrameImpl::GetScriptContextFromWorldId(
+ v8::Isolate* isolate,
+ int world_id) const {
+ scoped_refptr<DOMWrapperWorld> world =
+ DOMWrapperWorld::EnsureIsolatedWorld(isolate, world_id);
+ return ToScriptState(GetFrame(), *world)->GetContext();
+}
+
v8::Local<v8::Object> WebLocalFrameImpl::GlobalProxy() const {
return MainWorldScriptContext()->Global();
}
@@ -1901,7 +1876,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateMainFrame(
base::PassKey<WebLocalFrameImpl>(),
mojom::blink::TreeScopeType::kDocument, client, interface_registry,
frame_token);
- Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage();
+ Page& page = *To<WebViewImpl>(web_view)->GetPage();
DCHECK(!page.MainFrame());
frame->InitializeCoreFrame(
page, nullptr, nullptr, nullptr, FrameInsertType::kInsertInConstructor,
@@ -1922,10 +1897,8 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
DCHECK(name.IsEmpty() || name.Equals(previous_frame->Tree().GetName()));
auto* web_frame = MakeGarbageCollected<WebLocalFrameImpl>(
base::PassKey<WebLocalFrameImpl>(),
- previous_web_frame->InShadowTree()
- ? mojom::blink::TreeScopeType::kShadow
- : mojom::blink::TreeScopeType::kDocument,
- client, interface_registry, frame_token);
+ previous_web_frame->GetTreeScopeType(), client, interface_registry,
+ frame_token);
network::mojom::blink::WebSandboxFlags sandbox_flags =
network::mojom::blink::WebSandboxFlags::kNone;
PermissionsPolicyFeatureState feature_state;
@@ -1949,10 +1922,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
web_frame->InitializeCoreFrame(
*previous_frame->GetPage(), MakeGarbageCollected<DummyFrameOwner>(),
previous_web_frame->Parent(), nullptr, FrameInsertType::kInsertLater,
- name,
- frame_policy.disallow_document_access
- ? nullptr
- : &ToCoreFrame(*previous_web_frame)->window_agent_factory(),
+ name, &ToCoreFrame(*previous_web_frame)->window_agent_factory(),
previous_web_frame->Opener(), /* policy_container */ nullptr,
sandbox_flags);
@@ -2143,10 +2113,8 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
webframe_child->InitializeCoreFrameInternal(
*GetFrame()->GetPage(), owner_element, this, LastChild(),
FrameInsertType::kInsertInConstructor, name,
- owner_element->GetFramePolicy().disallow_document_access
- ? nullptr
- : &GetFrame()->window_agent_factory(),
- nullptr, std::move(policy_container));
+ &GetFrame()->window_agent_factory(), nullptr,
+ std::move(policy_container));
webframe_child->Client()->InitializeAsChildFrame(/*parent=*/this);
@@ -2171,6 +2139,12 @@ RemoteFrame* WebLocalFrameImpl::AdoptPortal(HTMLPortalElement* portal) {
return portal_frame->GetFrame();
}
+RemoteFrame* WebLocalFrameImpl::CreateFencedFrame(
+ HTMLFencedFrameElement* fenced_frame) {
+ WebRemoteFrame* frame = client_->CreateFencedFrame(fenced_frame);
+ return To<WebRemoteFrameImpl>(frame)->GetFrame();
+}
+
void WebLocalFrameImpl::DidChangeContentsSize(const IntSize& size) {
if (GetTextFinder() && GetTextFinder()->TotalMatchCount() > 0)
GetTextFinder()->IncreaseMarkerVersion();
@@ -2355,6 +2329,10 @@ void WebLocalFrameImpl::CommitNavigation(
std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) {
DCHECK(GetFrame());
DCHECK(!navigation_params->url.ProtocolIs("javascript"));
+ if (navigation_params->is_synchronous_commit_for_bug_778318) {
+ DCHECK(WebDocumentLoader::WillLoadUrlAsEmpty(navigation_params->url));
+ navigation_params->storage_key = GetFrame()->DomWindow()->GetStorageKey();
+ }
if (GetTextFinder())
GetTextFinder()->ClearActiveFindMatch();
GetFrame()->Loader().CommitNavigation(std::move(navigation_params),
@@ -2792,6 +2770,20 @@ const WebHistoryItem& WebLocalFrameImpl::GetCurrentHistoryItem() const {
return current_history_item_;
}
+void WebLocalFrameImpl::SetLocalStorageArea(
+ CrossVariantMojoRemote<mojom::StorageAreaInterfaceBase>
+ local_storage_area) {
+ CoreInitializer::GetInstance().SetLocalStorageArea(
+ *GetFrame(), std::move(local_storage_area));
+}
+
+void WebLocalFrameImpl::SetSessionStorageArea(
+ CrossVariantMojoRemote<mojom::StorageAreaInterfaceBase>
+ session_storage_area) {
+ CoreInitializer::GetInstance().SetSessionStorageArea(
+ *GetFrame(), std::move(session_storage_area));
+}
+
void WebLocalFrameImpl::SetTargetToCurrentHistoryItem(const WebString& target) {
current_history_item_.SetTarget(target);
}
@@ -2833,4 +2825,12 @@ void WebLocalFrameImpl::ResetHasScrolledFocusedEditableIntoView() {
has_scrolled_focused_editable_node_into_rect_ = false;
}
+bool WebLocalFrameImpl::ServiceWorkerSubresourceFilterEnabled() {
+ if (GetFrame() && GetFrame()->GetDocument()) {
+ return RuntimeEnabledFeatures::ServiceWorkerSubresourceFilterEnabled(
+ GetFrame()->GetDocument()->GetExecutionContext());
+ }
+ return false;
+}
+
} // namespace blink
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 07f69460ec6..3136ab74e0c 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
@@ -70,6 +70,7 @@ namespace blink {
class ChromePrintContext;
struct ContextMenuData;
class FindInPage;
+class HTMLFencedFrameElement;
class HTMLPortalElement;
class IntSize;
class LocalFrameClientImpl;
@@ -170,6 +171,9 @@ class CORE_EXPORT WebLocalFrameImpl final
v8::Local<v8::Context> MainWorldScriptContext() const override;
int32_t GetScriptContextWorldId(
v8::Local<v8::Context> script_context) const override;
+ v8::Local<v8::Context> GetScriptContextFromWorldId(
+ v8::Isolate* isolate,
+ int world_id) const override;
void RequestExecuteScriptAndReturnValue(const WebScriptSource&,
bool user_gesture,
WebScriptExecutionCallback*) override;
@@ -323,11 +327,17 @@ class CORE_EXPORT WebLocalFrameImpl final
bool HasStickyUserActivation() override;
bool HasTransientUserActivation() override;
bool ConsumeTransientUserActivation(UserActivationUpdateSource) override;
- void SetOptimizationGuideHints(const WebOptimizationGuideHints&) override;
void SetTargetToCurrentHistoryItem(const WebString& target) override;
void UpdateCurrentHistoryItem() override;
PageState CurrentHistoryItemToPageState() override;
const WebHistoryItem& GetCurrentHistoryItem() const override;
+ bool ServiceWorkerSubresourceFilterEnabled() override;
+ void SetLocalStorageArea(
+ CrossVariantMojoRemote<mojom::StorageAreaInterfaceBase>
+ local_storage_area) override;
+ void SetSessionStorageArea(
+ CrossVariantMojoRemote<mojom::StorageAreaInterfaceBase>
+ session_storage_area) override;
// WebNavigationControl overrides:
bool DispatchBeforeUnloadEvent(bool) override;
@@ -407,6 +417,8 @@ class CORE_EXPORT WebLocalFrameImpl final
mojo::PendingAssociatedRemote<mojom::blink::PortalClient>);
RemoteFrame* AdoptPortal(HTMLPortalElement*);
+ RemoteFrame* CreateFencedFrame(HTMLFencedFrameElement*);
+
void DidChangeContentsSize(const IntSize&);
bool HasDevToolsOverlays() const;
diff --git a/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc
index 999fb678b05..bd1307ca65b 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -54,6 +55,7 @@ WebRemoteFrame* WebRemoteFrame::Create(
frame_token);
}
+// static
WebRemoteFrame* WebRemoteFrame::CreateMainFrame(
WebView* web_view,
WebRemoteFrameClient* client,
@@ -67,17 +69,18 @@ WebRemoteFrame* WebRemoteFrame::CreateMainFrame(
frame_token, devtools_frame_token, opener);
}
-WebRemoteFrame* WebRemoteFrame::CreateForPortal(
+// static
+WebRemoteFrame* WebRemoteFrame::CreateForPortalOrFencedFrame(
mojom::blink::TreeScopeType scope,
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
const RemoteFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token,
- const WebElement& portal_element) {
- return WebRemoteFrameImpl::CreateForPortal(
+ const WebElement& frame_owner) {
+ return WebRemoteFrameImpl::CreateForPortalOrFencedFrame(
scope, client, interface_registry, associated_interface_provider,
- frame_token, devtools_frame_token, portal_element);
+ frame_token, devtools_frame_token, frame_owner);
}
// static
@@ -92,7 +95,7 @@ WebRemoteFrameImpl* WebRemoteFrameImpl::CreateMainFrame(
WebRemoteFrameImpl* frame = MakeGarbageCollected<WebRemoteFrameImpl>(
mojom::blink::TreeScopeType::kDocument, client, interface_registry,
associated_interface_provider, frame_token);
- Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage();
+ Page& page = *To<WebViewImpl>(web_view)->GetPage();
// It would be nice to DCHECK that the main frame is not set yet here.
// Unfortunately, there is an edge case with a pending RenderFrameHost that
// violates this: the embedder may create a pending RenderFrameHost for
@@ -111,28 +114,34 @@ WebRemoteFrameImpl* WebRemoteFrameImpl::CreateMainFrame(
return frame;
}
-WebRemoteFrameImpl* WebRemoteFrameImpl::CreateForPortal(
+WebRemoteFrameImpl* WebRemoteFrameImpl::CreateForPortalOrFencedFrame(
mojom::blink::TreeScopeType scope,
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
const RemoteFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token,
- const WebElement& portal_element) {
+ const WebElement& frame_owner) {
auto* frame = MakeGarbageCollected<WebRemoteFrameImpl>(
scope, client, interface_registry, associated_interface_provider,
frame_token);
- Element* element = portal_element;
- DCHECK(element->HasTagName(html_names::kPortalTag));
- DCHECK(
- RuntimeEnabledFeatures::PortalsEnabled(element->GetExecutionContext()));
- HTMLPortalElement* portal = static_cast<HTMLPortalElement*>(element);
- LocalFrame* host_frame = portal->GetDocument().GetFrame();
- frame->InitializeCoreFrame(*host_frame->GetPage(), portal, nullptr, nullptr,
- FrameInsertType::kInsertInConstructor, g_null_atom,
- &host_frame->window_agent_factory(),
- devtools_frame_token);
+ // We first convert this to a raw blink::Element*, and manually convert this
+ // to an HTMLElement*. That is the only way the IsA<> and To<> casts below
+ // will work.
+ Element* element = frame_owner;
+ DCHECK(IsA<HTMLPortalElement>(element) ||
+ IsA<HTMLFencedFrameElement>(element));
+ ExecutionContext* execution_context = element->GetExecutionContext();
+ DCHECK(RuntimeEnabledFeatures::PortalsEnabled(execution_context) ||
+ RuntimeEnabledFeatures::FencedFramesEnabled(execution_context));
+ HTMLFrameOwnerElement* frame_owner_element =
+ To<HTMLFrameOwnerElement>(element);
+ LocalFrame* host_frame = frame_owner_element->GetDocument().GetFrame();
+ frame->InitializeCoreFrame(
+ *host_frame->GetPage(), frame_owner_element, nullptr, nullptr,
+ FrameInsertType::kInsertInConstructor, g_null_atom,
+ &host_frame->window_agent_factory(), devtools_frame_token);
return frame;
}
@@ -204,7 +213,7 @@ WebLocalFrame* WebRemoteFrameImpl::CreateLocalChild(
WindowAgentFactory* window_agent_factory = nullptr;
if (opener) {
window_agent_factory = &ToCoreFrame(*opener)->window_agent_factory();
- } else if (!frame_policy.disallow_document_access) {
+ } else {
window_agent_factory = &GetFrame()->window_agent_factory();
}
@@ -241,9 +250,11 @@ void WebRemoteFrameImpl::InitializeCoreFrame(
To<WebLocalFrameImpl>(parent)->LocalRoot()->FrameWidget();
}
} else if (owner && owner->IsLocal()) {
- // Never gets to this point without |owner| being a portal element.
- auto* owner_element = To<HTMLFrameOwnerElement>(owner);
- DCHECK(owner_element->IsHTMLPortalElement());
+ // Never gets to this point unless |owner| is a <portal> or <fencedframe>
+ // element.
+ HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(owner);
+ DCHECK(owner_element->IsHTMLPortalElement() ||
+ owner_element->IsHTMLFencedFrameElement());
LocalFrame& local_frame =
owner_element->GetDocument().GetFrame()->LocalFrameRoot();
ancestor_widget = WebLocalFrameImpl::FromFrame(local_frame)->FrameWidget();
@@ -280,7 +291,7 @@ WebRemoteFrame* WebRemoteFrameImpl::CreateRemoteChild(
WindowAgentFactory* window_agent_factory = nullptr;
if (opener) {
window_agent_factory = &ToCoreFrame(*opener)->window_agent_factory();
- } else if (!frame_policy.disallow_document_access) {
+ } else {
window_agent_factory = &GetFrame()->window_agent_factory();
}
@@ -360,20 +371,15 @@ void WebRemoteFrameImpl::SetReplicatedInsecureNavigationsSet(
GetFrame()->SetInsecureNavigationsSet(set);
}
-void WebRemoteFrameImpl::SetReplicatedAdFrameType(
- mojom::blink::AdFrameType ad_frame_type) {
+void WebRemoteFrameImpl::SetReplicatedIsAdSubframe(bool is_ad_subframe) {
DCHECK(GetFrame());
- GetFrame()->SetReplicatedAdFrameType(ad_frame_type);
+ GetFrame()->SetReplicatedIsAdSubframe(is_ad_subframe);
}
void WebRemoteFrameImpl::DidStartLoading() {
GetFrame()->DidStartLoading();
}
-bool WebRemoteFrameImpl::IsIgnoredForHitTest() const {
- return GetFrame()->IsIgnoredForHitTest();
-}
-
void WebRemoteFrameImpl::UpdateUserActivationState(
mojom::blink::UserActivationUpdateType update_type,
mojom::blink::UserActivationNotificationType notification_type) {
@@ -395,18 +401,6 @@ gfx::Rect WebRemoteFrameImpl::GetCompositingRect() {
return GetFrame()->View()->GetCompositingRect();
}
-void WebRemoteFrameImpl::SynchronizeVisualProperties() {
- GetFrame()->SynchronizeVisualProperties();
-}
-
-void WebRemoteFrameImpl::ResendVisualProperties() {
- GetFrame()->ResendVisualProperties();
-}
-
-float WebRemoteFrameImpl::GetCompositingScaleFactor() {
- return GetFrame()->View()->GetCompositingScaleFactor();
-}
-
WebString WebRemoteFrameImpl::UniqueName() const {
return GetFrame()->UniqueName();
}
diff --git a/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.h b/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.h
index de4ed32c2f3..ae8fb34a59c 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_remote_frame_impl.h
@@ -39,14 +39,14 @@ class CORE_EXPORT WebRemoteFrameImpl final
const RemoteFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token,
WebFrame* opener);
- static WebRemoteFrameImpl* CreateForPortal(
+ static WebRemoteFrameImpl* CreateForPortalOrFencedFrame(
mojom::blink::TreeScopeType,
WebRemoteFrameClient*,
InterfaceRegistry*,
AssociatedInterfaceProvider*,
const RemoteFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token,
- const WebElement& portal_element);
+ const WebElement& frame_owner);
WebRemoteFrameImpl(mojom::blink::TreeScopeType,
WebRemoteFrameClient*,
@@ -93,18 +93,13 @@ class CORE_EXPORT WebRemoteFrameImpl final
void SetReplicatedInsecureRequestPolicy(
mojom::blink::InsecureRequestPolicy) override;
void SetReplicatedInsecureNavigationsSet(const WebVector<unsigned>&) override;
- void SetReplicatedAdFrameType(
- mojom::blink::AdFrameType ad_frame_type) override;
+ void SetReplicatedIsAdSubframe(bool is_ad_subframe) override;
void DidStartLoading() override;
- bool IsIgnoredForHitTest() const override;
void UpdateUserActivationState(
mojom::blink::UserActivationUpdateType update_type,
mojom::blink::UserActivationNotificationType notification_type) override;
void SetHadStickyUserActivationBeforeNavigation(bool value) override;
v8::Local<v8::Object> GlobalProxy() const override;
- void SynchronizeVisualProperties() override;
- void ResendVisualProperties() override;
- float GetCompositingScaleFactor() override;
WebString UniqueName() const override;
const FrameVisualProperties& GetPendingVisualPropertiesForTesting()
const override;
diff --git a/chromium/third_party/blink/renderer/core/frame/window.idl b/chromium/third_party/blink/renderer/core/frame/window.idl
index cb4e77730dd..070635f5a49 100644
--- a/chromium/third_party/blink/renderer/core/frame/window.idl
+++ b/chromium/third_party/blink/renderer/core/frame/window.idl
@@ -35,13 +35,13 @@
] interface Window : EventTarget {
// the current browsing context
// FIXME: The spec uses the WindowProxy type for this and many other attributes.
- [Affects=Nothing, LegacyUnforgeable, CrossOrigin, CachedAccessor=kWindowProxy] readonly attribute Window window;
+ [LegacyUnforgeable, CrossOrigin, CachedAccessor=kWindowProxy] readonly attribute Window window;
[Replaceable, CrossOrigin, CachedAccessor=kWindowProxy] readonly attribute Window self;
- [Affects=Nothing, LegacyUnforgeable, CachedAccessor=kWindowDocument] readonly attribute Document document;
+ [LegacyUnforgeable, CachedAccessor=kWindowDocument] readonly attribute Document document;
attribute DOMString name;
- [Affects=Nothing, PutForwards=href, LegacyUnforgeable, CrossOrigin=(Getter,Setter), Custom=Getter] readonly attribute Location location;
+ [PutForwards=href, LegacyUnforgeable, CrossOrigin=(Getter,Setter), Custom=Getter] readonly attribute Location location;
[CallWith=ScriptState] readonly attribute CustomElementRegistry customElements;
- [Affects=Nothing] readonly attribute History history;
+ readonly attribute History history;
[Replaceable, MeasureAs=BarPropLocationbar] readonly attribute BarProp locationbar;
[Replaceable, MeasureAs=BarPropMenubar] readonly attribute BarProp menubar;
[Replaceable, MeasureAs=BarPropPersonalbar] readonly attribute BarProp personalbar;
@@ -74,7 +74,7 @@
[Custom, NotEnumerable, CrossOrigin] getter object (DOMString name);
// the user agent
- [Affects=Nothing, LogActivity=GetterOnly] readonly attribute Navigator navigator;
+ [LogActivity=GetterOnly] readonly attribute Navigator navigator;
[LogActivity=GetterOnly, SecureContext, RuntimeEnabled=AppCache] readonly attribute ApplicationCache applicationCache;
[RuntimeEnabled=OriginIsolationHeader] readonly attribute boolean originAgentCluster;
@@ -130,8 +130,8 @@
[MeasureAs=WindowResize] void resizeBy(long x, long y);
// viewport
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowInnerWidth, Replaceable] readonly attribute long innerWidth;
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowInnerHeight, Replaceable] readonly attribute long innerHeight;
+ [HighEntropy=Direct, MeasureAs=WindowInnerWidth, Replaceable] readonly attribute long innerWidth;
+ [HighEntropy=Direct, MeasureAs=WindowInnerHeight, Replaceable] readonly attribute long innerHeight;
// viewport scrolling
[HighEntropy=Direct, MeasureAs=WindowScrollX, Replaceable] readonly attribute double scrollX;
@@ -150,11 +150,11 @@
[Replaceable, SameObject] readonly attribute VisualViewport visualViewport;
// client
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowScreenX, Replaceable] readonly attribute long screenX;
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowScreenY, Replaceable] readonly attribute long screenY;
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowOuterWidth, Replaceable] readonly attribute long outerWidth;
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowOuterHeight, Replaceable] readonly attribute long outerHeight;
- [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowDevicePixelRatio, Replaceable] readonly attribute double devicePixelRatio;
+ [HighEntropy=Direct, MeasureAs=WindowScreenX, Replaceable] readonly attribute long screenX;
+ [HighEntropy=Direct, MeasureAs=WindowScreenY, Replaceable] readonly attribute long screenY;
+ [HighEntropy=Direct, MeasureAs=WindowOuterWidth, Replaceable] readonly attribute long outerWidth;
+ [HighEntropy=Direct, MeasureAs=WindowOuterHeight, Replaceable] readonly attribute long outerHeight;
+ [HighEntropy=Direct, MeasureAs=WindowDevicePixelRatio, Replaceable] readonly attribute double devicePixelRatio;
// Window Segments API
// https://github.com/webscreens/window-segments
diff --git a/chromium/third_party/blink/renderer/core/frame/window_attribution_reporting.idl b/chromium/third_party/blink/renderer/core/frame/window_attribution_reporting.idl
new file mode 100644
index 00000000000..631fd9c4e89
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/window_attribution_reporting.idl
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Attribution Reporting API: https://github.com/wicg/conversion-measurement-api
+[
+ ImplementedAs=AttributionReporting,
+ RuntimeEnabled=ConversionMeasurementEventSources,
+ SecureContext
+] partial interface Window {
+ readonly attribute AttributionReporting attributionReporting;
+};
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
index 56b513f3324..07f845ceba0 100644
--- 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
@@ -6,5 +6,5 @@
dictionary WindowPostMessageOptions : PostMessageOptions {
USVString targetOrigin = "/";
- [RuntimeEnabled = CapabilityDelegation] DOMString createToken = "";
+ [RuntimeEnabled = CapabilityDelegation] DOMString delegate = "";
};
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index 7360bbeeff7..f5a8a0bef91 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
-#include "base/macros.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -134,11 +133,11 @@ class MetaParams : public GarbageCollected<MetaParams> {
MetaParams(FullscreenRequestType request_type,
const FullscreenOptions* options)
: request_type_(request_type), options_(options) {}
- virtual ~MetaParams() = default;
-
MetaParams(const MetaParams&) = delete;
MetaParams& operator=(const MetaParams&) = delete;
+ virtual ~MetaParams() = default;
+
virtual void Trace(Visitor* visitor) const { visitor->Trace(options_); }
FullscreenRequestType request_type() const { return request_type_; }
@@ -277,7 +276,7 @@ bool AllowedToUseFullscreen(const Document& document,
mojom::blink::PermissionsPolicyFeature::kFullscreen, report_on_failure);
}
-bool AllowedToRequestFullscreen(Document& document) {
+bool AllowedToRequestFullscreen(Document& document, Element& element) {
// WebXR DOM Overlay integration, cf.
// https://immersive-web.github.io/dom-overlays/
//
@@ -308,6 +307,12 @@ bool AllowedToRequestFullscreen(Document& document) {
return false;
}
+ // If the element is already fullscreen, then it is allowed to repeat a
+ // request to fullscreen (possibly on another display) without requiring
+ // user activation.
+ if (element == Fullscreen::FullscreenElementFrom(document))
+ return true;
+
// An algorithm is allowed to request fullscreen if one of the following is
// true:
@@ -390,7 +395,7 @@ bool RequestFullscreenConditionsMet(Element& pending, Document& document) {
return false;
// This algorithm is allowed to request fullscreen.
- if (!AllowedToRequestFullscreen(document))
+ if (!AllowedToRequestFullscreen(document, pending))
return false;
return true;
@@ -407,6 +412,8 @@ class RequestFullscreenScope {
DCHECK(!running_request_fullscreen_);
running_request_fullscreen_ = true;
}
+ RequestFullscreenScope(const RequestFullscreenScope&) = delete;
+ RequestFullscreenScope& operator=(const RequestFullscreenScope&) = delete;
~RequestFullscreenScope() {
DCHECK(running_request_fullscreen_);
@@ -417,7 +424,6 @@ class RequestFullscreenScope {
private:
static bool running_request_fullscreen_;
- DISALLOW_COPY_AND_ASSIGN(RequestFullscreenScope);
};
bool RequestFullscreenScope::running_request_fullscreen_ = false;
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
index 34c1d12d736..e40ed2d7796 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
@@ -122,6 +122,8 @@ class CORE_EXPORT Fullscreen final : public GarbageCollected<Fullscreen>,
FullscreenRequestType type,
const FullscreenOptions* options,
ScriptPromiseResolver* resolver);
+ PendingRequest(const PendingRequest&) = delete;
+ PendingRequest& operator=(const PendingRequest&) = delete;
virtual ~PendingRequest();
virtual void Trace(Visitor* visitor) const;
@@ -135,8 +137,6 @@ class CORE_EXPORT Fullscreen final : public GarbageCollected<Fullscreen>,
FullscreenRequestType type_;
Member<const FullscreenOptions> options_;
Member<ScriptPromiseResolver> resolver_;
-
- DISALLOW_COPY_AND_ASSIGN(PendingRequest);
};
using PendingRequests = HeapVector<Member<PendingRequest>>;
PendingRequests pending_requests_;
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h
index cc7575730e9..2e06a648613 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_SCOPED_ALLOW_FULLSCREEN_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_SCOPED_ALLOW_FULLSCREEN_H_
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -20,13 +19,13 @@ class CORE_EXPORT ScopedAllowFullscreen {
static absl::optional<Reason> FullscreenAllowedReason();
explicit ScopedAllowFullscreen(Reason);
+ ScopedAllowFullscreen(const ScopedAllowFullscreen&) = delete;
+ ScopedAllowFullscreen& operator=(const ScopedAllowFullscreen&) = delete;
~ScopedAllowFullscreen();
private:
static absl::optional<Reason> reason_;
absl::optional<Reason> previous_reason_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedAllowFullscreen);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_matrix.cc b/chromium/third_party/blink/renderer/core/geometry/dom_matrix.cc
index d89695edcda..4e341d09c71 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_matrix.cc
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_matrix.cc
@@ -20,7 +20,6 @@ DOMMatrix* DOMMatrix::Create(ExecutionContext* execution_context,
return MakeGarbageCollected<DOMMatrix>(TransformationMatrix());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMMatrix* DOMMatrix::Create(
ExecutionContext* execution_context,
const V8UnionStringOrUnrestrictedDoubleSequence* init,
@@ -58,45 +57,13 @@ DOMMatrix* DOMMatrix::Create(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-DOMMatrix* DOMMatrix::Create(ExecutionContext* execution_context,
- StringOrUnrestrictedDoubleSequence& init,
- ExceptionState& exception_state) {
- if (init.IsString()) {
- if (!execution_context->IsWindow()) {
- exception_state.ThrowTypeError(
- "DOMMatrix can't be constructed with strings on workers.");
- return nullptr;
- }
-
- DOMMatrix* matrix = MakeGarbageCollected<DOMMatrix>(TransformationMatrix());
- matrix->SetMatrixValueFromString(execution_context, init.GetAsString(),
- exception_state);
- return matrix;
- }
-
- if (init.IsUnrestrictedDoubleSequence()) {
- const Vector<double>& sequence = init.GetAsUnrestrictedDoubleSequence();
- if (sequence.size() != 6 && sequence.size() != 16) {
- exception_state.ThrowTypeError(
- "The sequence must contain 6 elements for a 2D matrix or 16 elements "
- "for a 3D matrix.");
- return nullptr;
- }
- return MakeGarbageCollected<DOMMatrix>(sequence, sequence.size());
- }
-
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMMatrix* DOMMatrix::Create(DOMMatrixReadOnly* other,
ExceptionState& exception_state) {
return MakeGarbageCollected<DOMMatrix>(other->Matrix(), other->is2D());
}
-DOMMatrix* DOMMatrix::Create(const SkMatrix44& matrix,
+DOMMatrix* DOMMatrix::Create(const skia::Matrix44& matrix,
ExceptionState& exception_state) {
TransformationMatrix transformation_matrix(matrix);
return MakeGarbageCollected<DOMMatrix>(transformation_matrix,
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 168c5e6219f..aad3056fe4f 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_matrix.h
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_matrix.h
@@ -5,7 +5,6 @@
#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/string_or_unrestricted_double_sequence.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"
@@ -13,6 +12,7 @@
namespace blink {
class DOMMatrixInit;
+class ExecutionContext;
class V8UnionStringOrUnrestrictedDoubleSequence;
class CORE_EXPORT DOMMatrix : public DOMMatrixReadOnly {
@@ -21,20 +21,14 @@ class CORE_EXPORT DOMMatrix : public DOMMatrixReadOnly {
public:
static DOMMatrix* Create();
static DOMMatrix* Create(ExecutionContext*, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static DOMMatrix* Create(
ExecutionContext* execution_context,
const V8UnionStringOrUnrestrictedDoubleSequence* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static DOMMatrix* Create(ExecutionContext*,
- StringOrUnrestrictedDoubleSequence&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// TODO(fserb): double check those two bellow are needed:
static DOMMatrix* Create(DOMMatrixReadOnly*,
ExceptionState& = ASSERT_NO_EXCEPTION);
- static DOMMatrix* Create(const SkMatrix44&, ExceptionState&);
+ static DOMMatrix* Create(const skia::Matrix44&, ExceptionState&);
static DOMMatrix* fromFloat32Array(NotShared<DOMFloat32Array>,
ExceptionState&);
static DOMMatrix* fromFloat64Array(NotShared<DOMFloat64Array>,
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 084f5526d6c..9b79beb66fa 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
@@ -107,7 +107,6 @@ DOMMatrixReadOnly* DOMMatrixReadOnly::Create(
return MakeGarbageCollected<DOMMatrixReadOnly>(TransformationMatrix());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMMatrixReadOnly* DOMMatrixReadOnly::Create(
ExecutionContext* execution_context,
const V8UnionStringOrUnrestrictedDoubleSequence* init,
@@ -145,40 +144,6 @@ DOMMatrixReadOnly* DOMMatrixReadOnly::Create(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-DOMMatrixReadOnly* DOMMatrixReadOnly::Create(
- ExecutionContext* execution_context,
- const StringOrUnrestrictedDoubleSequence& init,
- ExceptionState& exception_state) {
- if (init.IsString()) {
- if (!execution_context->IsWindow()) {
- exception_state.ThrowTypeError(
- "DOMMatrix can't be constructed with strings on workers.");
- return nullptr;
- }
-
- DOMMatrixReadOnly* matrix =
- MakeGarbageCollected<DOMMatrixReadOnly>(TransformationMatrix());
- matrix->SetMatrixValueFromString(execution_context, init.GetAsString(),
- exception_state);
- return matrix;
- }
-
- if (init.IsUnrestrictedDoubleSequence()) {
- const Vector<double>& sequence = init.GetAsUnrestrictedDoubleSequence();
- if (sequence.size() != 6 && sequence.size() != 16) {
- exception_state.ThrowTypeError(
- "The sequence must contain 6 elements for a 2D matrix or 16 elements "
- "for a 3D matrix.");
- return nullptr;
- }
- return MakeGarbageCollected<DOMMatrixReadOnly>(sequence, sequence.size());
- }
-
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMMatrixReadOnly* DOMMatrixReadOnly::CreateForSerialization(double sequence[],
int size) {
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 ec6fd99306f..ceb753ce130 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_GEOMETRY_DOM_MATRIX_READ_ONLY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_GEOMETRY_DOM_MATRIX_READ_ONLY_H_
-#include "third_party/blink/renderer/bindings/core/v8/string_or_unrestricted_double_sequence.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.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"
@@ -21,6 +21,7 @@ class DOMMatrix;
class DOMMatrixInit;
class DOMPoint;
class DOMPointInit;
+class ExecutionContext;
class V8UnionStringOrUnrestrictedDoubleSequence;
class CORE_EXPORT DOMMatrixReadOnly : public ScriptWrappable {
@@ -28,16 +29,10 @@ class CORE_EXPORT DOMMatrixReadOnly : public ScriptWrappable {
public:
static DOMMatrixReadOnly* Create(ExecutionContext*, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static DOMMatrixReadOnly* Create(
ExecutionContext* execution_context,
const V8UnionStringOrUnrestrictedDoubleSequence* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static DOMMatrixReadOnly* Create(ExecutionContext*,
- const StringOrUnrestrictedDoubleSequence&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static DOMMatrixReadOnly* fromFloat32Array(NotShared<DOMFloat32Array>,
ExceptionState&);
static DOMMatrixReadOnly* fromFloat64Array(NotShared<DOMFloat64Array>,
diff --git a/chromium/third_party/blink/renderer/core/highlight/build.gni b/chromium/third_party/blink/renderer/core/highlight/build.gni
index cb29959aa75..8d2206216dd 100644
--- a/chromium/third_party/blink/renderer/core/highlight/build.gni
+++ b/chromium/third_party/blink/renderer/core/highlight/build.gni
@@ -9,4 +9,5 @@ blink_core_sources_highlight = [
"highlight.h",
"highlight_registry.cc",
"highlight_registry.h",
+ "highlight_registry_map_entry.h",
]
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight.cc b/chromium/third_party/blink/renderer/core/highlight/highlight.cc
index 07d2fdcec26..4c019d3d8e7 100644
--- a/chromium/third_party/blink/renderer/core/highlight/highlight.cc
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight.cc
@@ -11,14 +11,11 @@
namespace blink {
-Highlight* Highlight::Create(const String& name,
- HeapVector<Member<AbstractRange>>& ranges) {
- return MakeGarbageCollected<Highlight>(name, ranges);
+Highlight* Highlight::Create(const HeapVector<Member<AbstractRange>>& ranges) {
+ return MakeGarbageCollected<Highlight>(ranges);
}
-Highlight::Highlight(const String& name,
- HeapVector<Member<AbstractRange>>& ranges)
- : name_(name) {
+Highlight::Highlight(const HeapVector<Member<AbstractRange>>& ranges) {
for (const auto& range : ranges)
highlight_ranges_.insert(range);
}
@@ -27,18 +24,29 @@ Highlight::~Highlight() = default;
void Highlight::Trace(blink::Visitor* visitor) const {
visitor->Trace(highlight_ranges_);
+ visitor->Trace(containing_highlight_registries_);
ScriptWrappable::Trace(visitor);
}
+void Highlight::ScheduleRepaintsInContainingHighlightRegistries() const {
+ for (const auto& entry : containing_highlight_registries_) {
+ DCHECK_GT(entry.value, 0u);
+ Member<HighlightRegistry> highlight_registry = entry.key;
+ highlight_registry->ScheduleRepaint();
+ }
+}
+
Highlight* Highlight::addForBinding(ScriptState*,
AbstractRange* range,
ExceptionState&) {
- highlight_ranges_.insert(range);
+ if (highlight_ranges_.insert(range).is_new_entry)
+ ScheduleRepaintsInContainingHighlightRegistries();
return this;
}
void Highlight::clearForBinding(ScriptState*, ExceptionState&) {
highlight_ranges_.clear();
+ ScheduleRepaintsInContainingHighlightRegistries();
}
bool Highlight::deleteForBinding(ScriptState*,
@@ -47,6 +55,7 @@ bool Highlight::deleteForBinding(ScriptState*,
auto iterator = highlight_ranges_.find(range);
if (iterator != highlight_ranges_.end()) {
highlight_ranges_.erase(iterator);
+ ScheduleRepaintsInContainingHighlightRegistries();
return true;
}
return false;
@@ -55,13 +64,40 @@ bool Highlight::deleteForBinding(ScriptState*,
bool Highlight::hasForBinding(ScriptState*,
AbstractRange* range,
ExceptionState&) const {
- return highlight_ranges_.Contains(range);
+ return Contains(range);
}
wtf_size_t Highlight::size() const {
return highlight_ranges_.size();
}
+void Highlight::setPriority(const int32_t& priority) {
+ priority_ = priority;
+ ScheduleRepaintsInContainingHighlightRegistries();
+}
+
+bool Highlight::Contains(AbstractRange* range) const {
+ return highlight_ranges_.Contains(range);
+}
+
+void Highlight::RegisterIn(HighlightRegistry* highlight_registry) {
+ auto map_iterator = containing_highlight_registries_.find(highlight_registry);
+ if (map_iterator == containing_highlight_registries_.end()) {
+ containing_highlight_registries_.insert(highlight_registry, 1);
+ } else {
+ DCHECK_GT(map_iterator->value, 0u);
+ map_iterator->value++;
+ }
+}
+
+void Highlight::DeregisterFrom(HighlightRegistry* highlight_registry) {
+ auto map_iterator = containing_highlight_registries_.find(highlight_registry);
+ DCHECK_NE(map_iterator, containing_highlight_registries_.end());
+ DCHECK_GT(map_iterator->value, 0u);
+ if (--map_iterator->value == 0)
+ containing_highlight_registries_.erase(map_iterator);
+}
+
Highlight::IterationSource::IterationSource(const Highlight& highlight)
: index_(0) {
highlight_ranges_snapshot_.ReserveInitialCapacity(
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight.h b/chromium/third_party/blink/renderer/core/highlight/highlight.h
index 98f66d5d828..035cba90a6b 100644
--- a/chromium/third_party/blink/renderer/core/highlight/highlight.h
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight.h
@@ -15,15 +15,16 @@
namespace blink {
using HighlightSetIterable = SetlikeIterable<Member<AbstractRange>>;
+class HighlightRegistry;
class CORE_EXPORT Highlight : public ScriptWrappable,
public HighlightSetIterable {
DEFINE_WRAPPERTYPEINFO();
public:
- static Highlight* Create(const String&, HeapVector<Member<AbstractRange>>&);
+ static Highlight* Create(const HeapVector<Member<AbstractRange>>&);
- Highlight(const String&, HeapVector<Member<AbstractRange>>&);
+ explicit Highlight(const HeapVector<Member<AbstractRange>>&);
~Highlight() override;
void Trace(blink::Visitor*) const override;
@@ -34,9 +35,10 @@ class CORE_EXPORT Highlight : public ScriptWrappable,
bool hasForBinding(ScriptState*, AbstractRange*, ExceptionState&) const;
wtf_size_t size() const;
- const String& name() const { return name_; }
const int32_t& priority() const { return priority_; }
- void setPriority(const int32_t& priority) { priority_ = priority; }
+ void setPriority(const int32_t&);
+
+ bool Contains(AbstractRange*) const;
class IterationSource final : public HighlightSetIterable::IterationSource {
public:
@@ -58,10 +60,23 @@ class CORE_EXPORT Highlight : public ScriptWrappable,
ScriptState*,
ExceptionState&) override;
+ const HeapLinkedHashSet<Member<AbstractRange>>& GetRanges() const {
+ return highlight_ranges_;
+ }
+
+ void RegisterIn(HighlightRegistry* highlight_registry);
+ void DeregisterFrom(HighlightRegistry* highlight_registry);
+
private:
HeapLinkedHashSet<Member<AbstractRange>> highlight_ranges_;
int32_t priority_ = 0;
- AtomicString name_;
+ // Since a Highlight can be registered many times under different names in
+ // many HighlightRegistries, we need to keep track of the number of times
+ // it's present in each registry. If the Highlight is not registered anywhere,
+ // then we avoid scheduling repaints in case of modifications to it.
+ HeapHashMap<Member<HighlightRegistry>, unsigned>
+ containing_highlight_registries_;
+ void ScheduleRepaintsInContainingHighlightRegistries() const;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight.idl b/chromium/third_party/blink/renderer/core/highlight/highlight.idl
index 37b03f0480a..931241a1d11 100644
--- a/chromium/third_party/blink/renderer/core/highlight/highlight.idl
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight.idl
@@ -6,8 +6,7 @@
RuntimeEnabled = HighlightAPI,
Exposed = Window
] interface Highlight {
- constructor(CSSOMString name, AbstractRange... initRanges);
+ constructor(AbstractRange... initRanges);
setlike<AbstractRange>;
- readonly attribute CSSOMString name;
attribute long priority;
};
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight_registry.cc b/chromium/third_party/blink/renderer/core/highlight/highlight_registry.cc
index 1bb667ad1eb..54fb8abae9a 100644
--- a/chromium/third_party/blink/renderer/core/highlight/highlight_registry.cc
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight_registry.cc
@@ -4,7 +4,11 @@
#include "third_party/blink/renderer/core/highlight/highlight_registry.h"
+#include "third_party/blink/renderer/core/dom/abstract_range.h"
+#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
namespace blink {
@@ -19,7 +23,7 @@ HighlightRegistry* HighlightRegistry::From(LocalDOMWindow& window) {
}
HighlightRegistry::HighlightRegistry(LocalDOMWindow& window)
- : Supplement<LocalDOMWindow>(window) {}
+ : Supplement<LocalDOMWindow>(window), frame_(window.GetFrame()) {}
HighlightRegistry::~HighlightRegistry() = default;
@@ -27,47 +31,115 @@ const char HighlightRegistry::kSupplementName[] = "HighlightRegistry";
void HighlightRegistry::Trace(blink::Visitor* visitor) const {
visitor->Trace(highlights_);
+ visitor->Trace(frame_);
ScriptWrappable::Trace(visitor);
Supplement<LocalDOMWindow>::Trace(visitor);
}
-HighlightRegistry* HighlightRegistry::addForBinding(
- ScriptState*,
- Highlight* highlight,
- ExceptionState& exception_state) {
- if (!registered_highlight_names_.insert(highlight->name()).is_new_entry) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kOperationError,
- "Cannot add a Highlight with the same name as an existing one.");
- } else {
- highlights_.insert(highlight);
+// Deletes all HighlightMarkers and rebuilds them with the contents of
+// highlights_.
+void HighlightRegistry::ValidateHighlightMarkers() {
+ Document* document = frame_->GetDocument();
+ if (!document)
+ return;
+
+ document->Markers().RemoveMarkersOfTypes(
+ DocumentMarker::MarkerTypes::Highlight());
+
+ for (const auto& highlight_registry_map_entry : highlights_) {
+ const auto& highlight_name = highlight_registry_map_entry->highlight_name;
+ const auto& highlight = highlight_registry_map_entry->highlight;
+ for (const auto& abstract_range : highlight->GetRanges()) {
+ if (abstract_range->OwnerDocument() == document &&
+ !abstract_range->collapsed()) {
+ auto* static_range = DynamicTo<StaticRange>(*abstract_range);
+ if (static_range && (!static_range->IsValid() ||
+ static_range->CrossesContainBoundary()))
+ continue;
+
+ EphemeralRange eph_range(abstract_range);
+ document->Markers().AddHighlightMarker(eph_range, highlight_name,
+ highlight);
+ }
+ }
}
+}
+
+void HighlightRegistry::ScheduleRepaint() const {
+ if (LocalFrameView* local_frame_view = frame_->View()) {
+ local_frame_view->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
+ }
+}
+HighlightRegistry* HighlightRegistry::setForBinding(
+ ScriptState* script_state,
+ AtomicString highlight_name,
+ Member<Highlight> highlight,
+ ExceptionState& exception_state) {
+ auto highlights_iterator = GetMapIterator(highlight_name);
+ if (highlights_iterator != highlights_.end()) {
+ highlights_iterator->Get()->highlight->DeregisterFrom(this);
+ // It's necessary to delete it and insert a new entry to the registry
+ // instead of just modifying the existing one so the insertion order is
+ // preserved.
+ highlights_.erase(highlights_iterator);
+ }
+ highlights_.insert(MakeGarbageCollected<HighlightRegistryMapEntry>(
+ highlight_name, highlight));
+ highlight->RegisterIn(this);
+ ScheduleRepaint();
return this;
}
void HighlightRegistry::clearForBinding(ScriptState*, ExceptionState&) {
- registered_highlight_names_.clear();
+ for (const auto& highlight_registry_map_entry : highlights_) {
+ highlight_registry_map_entry->highlight->DeregisterFrom(this);
+ }
highlights_.clear();
+ ScheduleRepaint();
}
bool HighlightRegistry::deleteForBinding(ScriptState*,
- Highlight* highlight,
+ const AtomicString& highlight_name,
ExceptionState&) {
- auto name_iterator = registered_highlight_names_.find(highlight->name());
- if (name_iterator != registered_highlight_names_.end()) {
- registered_highlight_names_.erase(name_iterator);
- highlights_.erase(highlight);
+ auto highlights_iterator = GetMapIterator(highlight_name);
+ if (highlights_iterator != highlights_.end()) {
+ highlights_iterator->Get()->highlight->DeregisterFrom(this);
+ highlights_.erase(highlights_iterator);
+ ScheduleRepaint();
return true;
}
return false;
}
-bool HighlightRegistry::hasForBinding(ScriptState*,
- Highlight* highlight,
- ExceptionState&) const {
- return highlights_.Contains(highlight);
+int8_t HighlightRegistry::CompareOverlayStackingPosition(
+ const AtomicString& highlight_name1,
+ const Highlight* highlight1,
+ const AtomicString& highlight_name2,
+ const Highlight* highlight2) const {
+ if (highlight_name1 == highlight_name2)
+ return kOverlayStackingPositionEquivalent;
+
+ if (highlight1->priority() == highlight2->priority()) {
+ for (const auto& highlight_registry_map_entry : highlights_) {
+ const auto& highlight_name = highlight_registry_map_entry->highlight_name;
+ if (highlight_name == highlight_name1) {
+ DCHECK(highlight1 == highlight_registry_map_entry->highlight);
+ return kOverlayStackingPositionBelow;
+ }
+ if (highlight_name == highlight_name2) {
+ DCHECK(highlight2 == highlight_registry_map_entry->highlight);
+ return kOverlayStackingPositionAbove;
+ }
+ }
+ NOTREACHED();
+ return kOverlayStackingPositionEquivalent;
+ }
+
+ return highlight1->priority() > highlight2->priority()
+ ? kOverlayStackingPositionAbove
+ : kOverlayStackingPositionBelow;
}
HighlightRegistry::IterationSource::IterationSource(
@@ -75,27 +147,31 @@ HighlightRegistry::IterationSource::IterationSource(
: index_(0) {
highlights_snapshot_.ReserveInitialCapacity(
highlight_registry.highlights_.size());
- for (const auto& highlight : highlight_registry.highlights_) {
- highlights_snapshot_.push_back(highlight);
+ for (const auto& highlight_registry_map_entry :
+ highlight_registry.highlights_) {
+ highlights_snapshot_.push_back(
+ MakeGarbageCollected<HighlightRegistryMapEntry>(
+ highlight_registry_map_entry));
}
}
bool HighlightRegistry::IterationSource::Next(ScriptState*,
- Member<Highlight>& key,
+ AtomicString& key,
Member<Highlight>& value,
ExceptionState&) {
if (index_ >= highlights_snapshot_.size())
return false;
- key = value = highlights_snapshot_[index_++];
+ key = highlights_snapshot_[index_]->highlight_name;
+ value = highlights_snapshot_[index_++]->highlight;
return true;
}
void HighlightRegistry::IterationSource::Trace(blink::Visitor* visitor) const {
visitor->Trace(highlights_snapshot_);
- HighlightRegistrySetIterable::IterationSource::Trace(visitor);
+ HighlightRegistryMapIterable::IterationSource::Trace(visitor);
}
-HighlightRegistrySetIterable::IterationSource*
+HighlightRegistryMapIterable::IterationSource*
HighlightRegistry::StartIteration(ScriptState*, ExceptionState&) {
return MakeGarbageCollected<IterationSource>(*this);
}
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight_registry.h b/chromium/third_party/blink/renderer/core/highlight/highlight_registry.h
index 61a89820680..8427555ceb0 100644
--- a/chromium/third_party/blink/renderer/core/highlight/highlight_registry.h
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight_registry.h
@@ -5,20 +5,31 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HIGHLIGHT_HIGHLIGHT_REGISTRY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HIGHLIGHT_HIGHLIGHT_REGISTRY_H_
-#include "third_party/blink/renderer/bindings/core/v8/iterable.h"
+#include "third_party/blink/renderer/bindings/core/v8/maplike.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/highlight/highlight.h"
+#include "third_party/blink/renderer/core/highlight/highlight_registry_map_entry.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
namespace blink {
-using HighlightRegistrySetIterable = SetlikeIterable<Member<Highlight>>;
+// Using LinkedHashSet<HighlightRegistryMapEntry> to store the map entries
+// because order of insertion needs to be preserved (for iteration and breaking
+// priority ties during painting) and there's no generic LinkedHashMap. Note
+// that the hash functions for HighlightRegistryMapEntry don't allow storing
+// more than one entry with the same key (highlight name).
+using HighlightRegistryMap =
+ HeapLinkedHashSet<Member<HighlightRegistryMapEntry>,
+ HashTraits<Member<HighlightRegistryMapEntry>>>;
+using HighlightRegistryMapIterable = Maplike<AtomicString, Member<Highlight>>;
+class LocalFrame;
class CORE_EXPORT HighlightRegistry : public ScriptWrappable,
public Supplement<LocalDOMWindow>,
- public HighlightRegistrySetIterable {
+ public HighlightRegistryMapIterable {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -30,20 +41,36 @@ class CORE_EXPORT HighlightRegistry : public ScriptWrappable,
void Trace(blink::Visitor*) const override;
- HighlightRegistry* addForBinding(ScriptState*, Highlight*, ExceptionState&);
+ HighlightRegistry* setForBinding(ScriptState*,
+ AtomicString,
+ Member<Highlight>,
+ ExceptionState&);
void clearForBinding(ScriptState*, ExceptionState&);
- bool deleteForBinding(ScriptState*, Highlight*, ExceptionState&);
- bool hasForBinding(ScriptState*, Highlight*, ExceptionState&) const;
+ bool deleteForBinding(ScriptState*, const AtomicString&, ExceptionState&);
wtf_size_t size() const { return highlights_.size(); }
- public:
+ const HighlightRegistryMap& GetHighlights() const { return highlights_; }
+ void ValidateHighlightMarkers();
+ void ScheduleRepaint() const;
+
+ enum OverlayStackingPosition {
+ kOverlayStackingPositionBelow = -1,
+ kOverlayStackingPositionEquivalent = 0,
+ kOverlayStackingPositionAbove = 1,
+ };
+
+ int8_t CompareOverlayStackingPosition(const AtomicString& highlight_name1,
+ const Highlight* highlight1,
+ const AtomicString& highlight_name2,
+ const Highlight* highlight2) const;
+
class IterationSource final
- : public HighlightRegistrySetIterable::IterationSource {
+ : public HighlightRegistryMapIterable::IterationSource {
public:
explicit IterationSource(const HighlightRegistry& highlight_registry);
bool Next(ScriptState*,
- Member<Highlight>&,
+ AtomicString&,
Member<Highlight>&,
ExceptionState&) override;
@@ -51,16 +78,31 @@ class CORE_EXPORT HighlightRegistry : public ScriptWrappable,
private:
wtf_size_t index_;
- HeapVector<Member<Highlight>> highlights_snapshot_;
+ HeapVector<Member<HighlightRegistryMapEntry>> highlights_snapshot_;
};
private:
- // Keeps all the names of Highlights added to the registry (in highlights_) so
- // it can be determined in O(1) if a name is already present.
- HashSet<String, StringHash> registered_highlight_names_;
- HeapLinkedHashSet<Member<Highlight>> highlights_;
-
- HighlightRegistrySetIterable::IterationSource* StartIteration(
+ HighlightRegistryMap highlights_;
+ Member<LocalFrame> frame_;
+
+ HighlightRegistryMap::iterator GetMapIterator(const AtomicString& key) {
+ return highlights_.find(
+ MakeGarbageCollected<HighlightRegistryMapEntry>(key));
+ }
+
+ bool GetMapEntry(ScriptState*,
+ const AtomicString& key,
+ Member<Highlight>& value,
+ ExceptionState&) override {
+ auto iterator = GetMapIterator(key);
+ if (iterator == highlights_.end())
+ return false;
+
+ value = iterator->Get()->highlight;
+ return true;
+ }
+
+ HighlightRegistryMapIterable::IterationSource* StartIteration(
ScriptState*,
ExceptionState&) override;
};
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight_registry.idl b/chromium/third_party/blink/renderer/core/highlight/highlight_registry.idl
index d0d51db0a4e..5d3b2facc6b 100644
--- a/chromium/third_party/blink/renderer/core/highlight/highlight_registry.idl
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight_registry.idl
@@ -6,5 +6,5 @@
RuntimeEnabled = HighlightAPI,
Exposed = Window
] interface HighlightRegistry {
- setlike<Highlight>;
+ maplike<DOMString, Highlight>;
};
diff --git a/chromium/third_party/blink/renderer/core/highlight/highlight_registry_map_entry.h b/chromium/third_party/blink/renderer/core/highlight/highlight_registry_map_entry.h
new file mode 100644
index 00000000000..1233f7cef15
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/highlight/highlight_registry_map_entry.h
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HIGHLIGHT_HIGHLIGHT_REGISTRY_MAP_ENTRY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HIGHLIGHT_HIGHLIGHT_REGISTRY_MAP_ENTRY_H_
+
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+
+namespace blink {
+
+class Highlight;
+
+struct HighlightRegistryMapEntry final
+ : public GarbageCollected<HighlightRegistryMapEntry> {
+ explicit HighlightRegistryMapEntry(const AtomicString& highlight_name)
+ : highlight_name(highlight_name) {}
+ HighlightRegistryMapEntry(const AtomicString& highlight_name,
+ Member<Highlight> highlight)
+ : highlight(highlight), highlight_name(highlight_name) {}
+ explicit HighlightRegistryMapEntry(const HighlightRegistryMapEntry* entry)
+ : HighlightRegistryMapEntry(entry->highlight_name, entry->highlight) {}
+
+ void Trace(blink::Visitor* visitor) const { visitor->Trace(highlight); }
+
+ Member<Highlight> highlight = nullptr;
+ AtomicString highlight_name = g_null_atom;
+};
+
+} // namespace blink
+
+namespace WTF {
+
+template <>
+struct DefaultHash<blink::Member<blink::HighlightRegistryMapEntry>> {
+ struct Hash {
+ STATIC_ONLY(Hash);
+
+ // Note that GetHash and Equal only take into account the |highlight_name|
+ // because |HighlightRegistryMapEntry| is used for storing map entries
+ // inside a set (i.e. there can only be one map entry in the set with the
+ // same key which is |highlight_name|).
+ static inline unsigned GetHash(
+ const blink::Member<blink::HighlightRegistryMapEntry>& key) {
+ DCHECK(key);
+ return AtomicStringHash::GetHash(key->highlight_name);
+ }
+ static inline bool Equal(
+ const blink::Member<blink::HighlightRegistryMapEntry>& a,
+ const blink::Member<blink::HighlightRegistryMapEntry>& b) {
+ DCHECK(a && b);
+ return AtomicStringHash::Equal(a->highlight_name, b->highlight_name);
+ }
+
+ static const bool safe_to_compare_to_empty_or_deleted = false;
+ };
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HIGHLIGHT_HIGHLIGHT_REGISTRY_MAP_ENTRY_H_
diff --git a/chromium/third_party/blink/renderer/core/html/DEPS b/chromium/third_party/blink/renderer/core/html/DEPS
index 3b16d4e209a..85efefce7ee 100644
--- a/chromium/third_party/blink/renderer/core/html/DEPS
+++ b/chromium/third_party/blink/renderer/core/html/DEPS
@@ -1,4 +1,7 @@
specific_include_rules = {
+ "canvas_image_source.cc": [
+ "+gpu/command_buffer/client/shared_image_interface.h",
+ ],
"canvas_rendering_context.cc": [
"+services/metrics/public/cpp/ukm_builders.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
index 65e052da13b..53a29879502 100644
--- a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
@@ -28,7 +28,7 @@
namespace blink {
namespace {
-static double INTERSECTION_RATIO_THRESHOLD = 0.5;
+static float INTERSECTION_RATIO_THRESHOLD = 0.5f;
} // namespace
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
index 4e820305d0b..f90711eff51 100644
--- 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
@@ -5,7 +5,6 @@
#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/core/core_export.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -54,6 +53,9 @@ class CORE_EXPORT AnchorElementMetricsSender final
static const char kSupplementName[];
explicit AnchorElementMetricsSender(Document&);
+ AnchorElementMetricsSender(const AnchorElementMetricsSender&) = delete;
+ AnchorElementMetricsSender& operator=(const AnchorElementMetricsSender&) =
+ delete;
virtual ~AnchorElementMetricsSender();
// LocalFrameView::LifecycleNotificationObserver
@@ -105,8 +107,6 @@ class CORE_EXPORT AnchorElementMetricsSender final
WTF::Vector<mojom::blink::AnchorElementEnteredViewportPtr>
entered_viewport_messages_;
WTF::Vector<mojom::blink::AnchorElementClickPtr> clicked_messages_;
-
- DISALLOW_COPY_AND_ASSIGN(AnchorElementMetricsSender);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/build.gni b/chromium/third_party/blink/renderer/core/html/build.gni
index 69bb5d026f9..c2eaea6bfe1 100644
--- a/chromium/third_party/blink/renderer/core/html/build.gni
+++ b/chromium/third_party/blink/renderer/core/html/build.gni
@@ -16,6 +16,7 @@ blink_core_sources_html = [
"canvas/canvas_draw_listener.h",
"canvas/canvas_font_cache.cc",
"canvas/canvas_font_cache.h",
+ "canvas/canvas_image_source.cc",
"canvas/canvas_image_source.h",
"canvas/canvas_performance_monitor.cc",
"canvas/canvas_performance_monitor.h",
@@ -24,6 +25,8 @@ blink_core_sources_html = [
"canvas/canvas_rendering_context_factory.h",
"canvas/canvas_rendering_context_host.cc",
"canvas/canvas_rendering_context_host.h",
+ "canvas/canvas_resource_tracker.cc",
+ "canvas/canvas_resource_tracker.h",
"canvas/html_canvas_element.cc",
"canvas/html_canvas_element.h",
"canvas/image_data.cc",
@@ -70,6 +73,8 @@ blink_core_sources_html = [
"document_all_name_collection.h",
"document_name_collection.cc",
"document_name_collection.h",
+ "fenced_frame/fenced_frame_mparch_delegate.cc",
+ "fenced_frame/fenced_frame_mparch_delegate.h",
"fenced_frame/fenced_frame_shadow_dom_delegate.cc",
"fenced_frame/fenced_frame_shadow_dom_delegate.h",
"fenced_frame/html_fenced_frame_element.cc",
@@ -634,6 +639,7 @@ blink_core_tests_html = [
"canvas/canvas_async_blob_creator_test.cc",
"canvas/canvas_font_cache_test.cc",
"canvas/canvas_rendering_api_ukm_metrics_test.cc",
+ "canvas/canvas_resource_tracker_test.cc",
"canvas/html_canvas_element_test.cc",
"canvas/image_data_test.cc",
"custom/custom_element_definition_test.cc",
@@ -654,6 +660,7 @@ blink_core_tests_html = [
"forms/form_controller_test.cc",
"forms/form_data_test.cc",
"forms/html_data_list_element_test.cc",
+ "forms/html_field_set_element_test.cc",
"forms/html_form_control_element_test.cc",
"forms/html_form_element_test.cc",
"forms/html_input_element_test.cc",
@@ -662,7 +669,6 @@ blink_core_tests_html = [
"forms/html_text_area_element_test.cc",
"forms/internal_popup_menu_test.cc",
"forms/option_list_test.cc",
- "forms/password_input_type_test.cc",
"forms/step_range_test.cc",
"forms/text_control_element_test.cc",
"forms/type_ahead_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.cc
new file mode 100644
index 00000000000..f96458f4847
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.cc
@@ -0,0 +1,108 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
+
+#include "gpu/command_buffer/client/shared_image_interface.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
+
+namespace blink {
+namespace {
+
+std::unique_ptr<CanvasResourceProvider> CreateProvider(
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
+ const SkImageInfo& info,
+ const scoped_refptr<StaticBitmapImage>& source_image,
+ bool fallback_to_software) {
+ IntSize size(info.width(), info.height());
+
+ const cc::PaintFlags::FilterQuality filter_quality =
+ cc::PaintFlags::FilterQuality::kLow;
+ const CanvasResourceParams resource_params(info);
+
+ if (context_provider) {
+ uint32_t usage_flags =
+ context_provider->ContextProvider()
+ ->SharedImageInterface()
+ ->UsageForMailbox(source_image->GetMailboxHolder().mailbox);
+ auto resource_provider = CanvasResourceProvider::CreateSharedImageProvider(
+ size, filter_quality, resource_params,
+ CanvasResourceProvider::ShouldInitialize::kNo, context_provider,
+ RasterMode::kGPU, source_image->IsOriginTopLeft(), usage_flags);
+ if (resource_provider)
+ return resource_provider;
+
+ if (!fallback_to_software)
+ return nullptr;
+ }
+
+ return CanvasResourceProvider::CreateBitmapProvider(
+ size, filter_quality, resource_params,
+ CanvasResourceProvider::ShouldInitialize::kNo);
+}
+
+} // anonymous namespace
+
+scoped_refptr<StaticBitmapImage> GetImageWithAlphaDisposition(
+ scoped_refptr<StaticBitmapImage>&& image,
+ const AlphaDisposition alpha_disposition) {
+ if (!image)
+ return nullptr;
+
+ SkAlphaType alpha_type = (alpha_disposition == kPremultiplyAlpha)
+ ? kPremul_SkAlphaType
+ : kUnpremul_SkAlphaType;
+ PaintImage paint_image = image->PaintImageForCurrentFrame();
+ if (!paint_image)
+ return nullptr;
+
+ // Only if the content alphaType is not important or it will be recorded and
+ // be handled in following step, kDontChangeAlpha could be provided to save
+ // the conversion here.
+ if (paint_image.GetAlphaType() == alpha_type ||
+ alpha_disposition == kDontChangeAlpha)
+ return std::move(image);
+
+ SkImageInfo info =
+ image->PaintImageForCurrentFrame().GetSkImageInfo().makeAlphaType(
+ alpha_type);
+
+ // To premul, draw the unpremul image on a surface to avoid GPU read back if
+ // image is texture backed.
+ if (alpha_type == kPremul_SkAlphaType) {
+ auto resource_provider = CreateProvider(
+ image->IsTextureBacked() ? image->ContextProviderWrapper() : nullptr,
+ info, image, true /* fallback_to_software */);
+ if (!resource_provider)
+ return nullptr;
+
+ cc::PaintFlags paint;
+ paint.setBlendMode(SkBlendMode::kSrc);
+ resource_provider->Canvas()->drawImage(image->PaintImageForCurrentFrame(),
+ 0, 0, SkSamplingOptions(), &paint);
+ return resource_provider->Snapshot(image->CurrentFrameOrientation());
+ }
+
+ // To unpremul, read back the pixels.
+ // TODO(crbug.com/1197369): we should try to keep the output resource(image)
+ // in GPU when premultiply-alpha or unpremultiply-alpha transforms is
+ // required.
+ if (paint_image.GetSkImageInfo().isEmpty())
+ return nullptr;
+
+ sk_sp<SkData> dst_pixels = TryAllocateSkData(info.computeMinByteSize());
+ if (!dst_pixels)
+ return nullptr;
+
+ uint8_t* writable_pixels = static_cast<uint8_t*>(dst_pixels->writable_data());
+ size_t image_row_bytes = static_cast<size_t>(info.minRowBytes64());
+ bool read_successful =
+ paint_image.readPixels(info, writable_pixels, image_row_bytes, 0, 0);
+ DCHECK(read_successful);
+ return StaticBitmapImage::Create(std::move(dst_pixels), info,
+ image->CurrentFrameOrientation());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.h
index cd7d65ec15b..827648a6e2a 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_image_source.h
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
+#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
@@ -47,10 +48,18 @@ enum SourceImageStatus {
kInvalidSourceImageStatus,
};
+// This is the helper function to get the canvas image with a
+// specific alpha op requirements.
+scoped_refptr<StaticBitmapImage> GetImageWithAlphaDisposition(
+ scoped_refptr<StaticBitmapImage>&&,
+ const AlphaDisposition);
+
class CORE_EXPORT CanvasImageSource {
public:
- virtual scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) = 0;
+ virtual scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) = 0;
// IMPORTANT: Result must be independent of whether destinationContext is
// already tainted because this function may be used to determine whether
@@ -67,6 +76,16 @@ class CORE_EXPORT CanvasImageSource {
virtual bool IsOffscreenCanvas() const { return false; }
virtual bool IsVideoFrame() const { return false; }
+ // TODO(crbug.com/dawn/1197369): Implement check
+ // the usability of the image argument.
+ // Ref the spec here:
+ // https://html.spec.whatwg.org/multipage/canvas.html#check-the-usability-of-the-image-argument
+ virtual bool IsNeutered() const { return false; }
+
+ // Spec about placeholder context:
+ // https://html.spec.whatwg.org/multipage/canvas.html#offscreencanvas-placeholder
+ virtual bool IsPlaceholder() const { return false; }
+
virtual FloatSize ElementSize(const FloatSize& default_object_size,
const RespectImageOrientationEnum) const = 0;
virtual FloatSize DefaultDestinationSize(
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc
index 41dc7fbadfd..a7e6ea145ae 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h"
#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
@@ -18,27 +19,26 @@ using blink::CanvasResourceProvider;
const char* const kHostTypeName_Canvas = ".Canvas";
const char* const kHostTypeName_OffscreenCanvas = ".OffscreenCanvas";
-const char* const kThreadTypeName_Main = ".MainThread";
-const char* const kThreadTypeName_Worker = ".Worker";
-
-const char* const kContextTypeName_2D = ".2D";
+const char* const kContextTypeName_2D_Accelerated = ".2D.Accelerated";
+const char* const kContextTypeName_2D_Unaccelerated = ".2D.Unaccelerated";
const char* const kContextTypeName_WebGL = ".WebGL";
const char* const kContextTypeName_WebGL2 = ".WebGL2";
const char* const kContextTypeName_WebGPU = ".WebGPU";
const char* const kContextTypeName_ImageBitmap = ".ImageBitmap";
-const char* const kResourceTypeName_Bitmap = ".Bitmap";
-const char* const kResourceTypeName_SharedBitmap = ".SharedBitmap";
-const char* const kResourceTypeName_SharedImage = ".SharedImage";
-const char* const kResourceTypeName_PassThrough = ".PassThrough";
-const char* const kResourceTypeName_SwapChain = ".SwapChain";
-const char* const kResourceTypeName_SkiaDawnSharedImage =
- ".SkiaDawnSharedImage";
-
const char* const kFilterName_All = ".All";
const char* const kFilterName_Animation = ".Animation";
+const char* const kFilterName_Path = ".Path";
+const char* const kFilterName_Image = ".Image";
+const char* const kFilterName_ImageData = ".ImageData";
+const char* const kFilterName_Rectangle = ".Rectangle";
+const char* const kFilterName_Text = ".Text";
+const char* const kFilterName_DrawArrays = ".DrawArrays";
+const char* const kFilterName_DrawElements = ".DrawElements";
const char* const kMeasurementName_RenderTaskDuration = ".RenderTaskDuration";
+const char* const kMeasurementName_PartitionAlloc = ".PartitionAlloc";
+const char* const kMeasurementName_BlinkGC = ".BlinkGC";
// The inverse of the probability that a given task will be measured.
// I.e. a value of X means that each task has a probability 1/X of being
@@ -53,22 +53,20 @@ class RenderingContextDescriptionCodec {
explicit RenderingContextDescriptionCodec(const uint32_t& key);
bool IsOffscreen() const { return key_.get<IsOffscreenField>(); }
+ bool IsAccelerated() const { return key_.get<IsAcceleratedField>(); }
CanvasRenderingContext::ContextType ContextType() const;
- CanvasResourceProvider::ResourceProviderType ResourceType() const;
uint32_t GetKey() const { return key_.bits(); }
bool IsValid() const { return is_valid_; }
const char* GetHostTypeName() const;
- const char* GetThreadTypeName() const;
const char* GetContextTypeName() const;
- const char* GetResourceTypeName() const;
private:
using Key = WTF::SingleThreadedBitField<uint32_t>;
using IsOffscreenField = Key::DefineFirstValue<bool, 1>;
- using ContextTypeField = IsOffscreenField::DefineNextValue<uint32_t, 8>;
- using ResourceTypeField = ContextTypeField::DefineNextValue<uint32_t, 8>;
- using PaddingField = ResourceTypeField::DefineNextValue<bool, 1>;
+ using IsAcceleratedField = IsOffscreenField::DefineNextValue<bool, 1>;
+ using ContextTypeField = IsAcceleratedField::DefineNextValue<uint32_t, 8>;
+ using PaddingField = ContextTypeField::DefineNextValue<bool, 1>;
Key key_;
bool is_valid_;
@@ -76,13 +74,13 @@ class RenderingContextDescriptionCodec {
RenderingContextDescriptionCodec::RenderingContextDescriptionCodec(
const CanvasRenderingContext* context) {
- is_valid_ = context->Host() && context->Host()->ResourceProvider();
+ is_valid_ = context->Host();
if (!is_valid_)
return;
key_.set<IsOffscreenField>(context->Host()->IsOffscreenCanvas());
+ key_.set<IsAcceleratedField>(context->IsAccelerated());
key_.set<ContextTypeField>(context->GetContextType());
- key_.set<ResourceTypeField>(context->Host()->ResourceProvider()->GetType());
// The padding field ensures at least one bit is set in the key in order
// to avoid a key == 0, which is not supported by WTF::HashSet
key_.set<PaddingField>(true);
@@ -98,30 +96,21 @@ RenderingContextDescriptionCodec::ContextType() const {
key_.get<ContextTypeField>());
}
-CanvasResourceProvider::ResourceProviderType
-RenderingContextDescriptionCodec::ResourceType() const {
- return static_cast<CanvasResourceProvider::ResourceProviderType>(
- key_.get<ResourceTypeField>());
-}
-
const char* RenderingContextDescriptionCodec::GetHostTypeName() const {
return IsOffscreen() ? kHostTypeName_OffscreenCanvas : kHostTypeName_Canvas;
}
-const char* RenderingContextDescriptionCodec::GetThreadTypeName() const {
- return WTF::IsMainThread() ? kThreadTypeName_Main : kThreadTypeName_Worker;
-}
-
const char* RenderingContextDescriptionCodec::GetContextTypeName() const {
switch (ContextType()) {
case CanvasRenderingContext::kContext2D:
- return kContextTypeName_2D;
+ return IsAccelerated() ? kContextTypeName_2D_Accelerated
+ : kContextTypeName_2D_Unaccelerated;
case CanvasRenderingContext::kContextExperimentalWebgl:
case CanvasRenderingContext::kContextWebgl:
return kContextTypeName_WebGL;
case CanvasRenderingContext::kContextWebgl2:
return kContextTypeName_WebGL2;
- case CanvasRenderingContext::kContextGPUPresent:
+ case CanvasRenderingContext::kContextWebGPU:
return kContextTypeName_WebGPU;
case CanvasRenderingContext::kContextImageBitmap:
return kContextTypeName_ImageBitmap;
@@ -131,26 +120,6 @@ const char* RenderingContextDescriptionCodec::GetContextTypeName() const {
}
}
-const char* RenderingContextDescriptionCodec::GetResourceTypeName() const {
- switch (ResourceType()) {
- case CanvasResourceProvider::kBitmap:
- return kResourceTypeName_Bitmap;
- case CanvasResourceProvider::kSharedBitmap:
- return kResourceTypeName_SharedBitmap;
- case CanvasResourceProvider::kSharedImage:
- return kResourceTypeName_SharedImage;
- case CanvasResourceProvider::kPassThrough:
- return kResourceTypeName_PassThrough;
- case CanvasResourceProvider::kSwapChain:
- return kResourceTypeName_SwapChain;
- case CanvasResourceProvider::kSkiaDawnSharedImage:
- return kResourceTypeName_SkiaDawnSharedImage;
- default:
- NOTREACHED();
- return "";
- }
-}
-
} // unnamed namespace
namespace blink {
@@ -169,15 +138,17 @@ void CanvasPerformanceMonitor::CurrentTaskDrawsToContext(
// canvases per render task.
measure_current_task_ = !(task_counter_++ % kSamplingProbabilityInv);
- if (context->Host() && context->Host()->GetTopExecutionContext() &&
- context->Host()
- ->GetTopExecutionContext()
- ->IsInRequestAnimationFrame()) {
- call_type_ = CallType::kAnimation;
- } else {
- // TODO(crbug.com/1206028): Add support for CallType::kUserInput
- call_type_ = CallType::kOther;
+ if (LIKELY(!measure_current_task_))
+ return;
+
+ call_type_ = CallType::kOther;
+ if (context->Host()) {
+ ExecutionContext* ec = context->Host()->GetTopExecutionContext();
+ if (ec && ec->IsInRequestAnimationFrame()) {
+ call_type_ = CallType::kAnimation;
+ }
}
+ // TODO(crbug.com/1206028): Add support for CallType::kUserInput
}
if (LIKELY(!measure_current_task_))
@@ -204,6 +175,11 @@ void CanvasPerformanceMonitor::RecordMetrics(TimeTicks start_time,
TimeTicks end_time) {
TRACE_EVENT0("blink", "CanvasPerformanceMonitor::RecordMetrics");
TimeDelta elapsed_time = end_time - start_time;
+ constexpr size_t kKiloByte = 1024;
+ size_t partition_alloc_kb = WTF::Partitions::TotalActiveBytes() / kKiloByte;
+ size_t blink_gc_alloc_kb =
+ ProcessHeap::TotalAllocatedObjectSize() / kKiloByte;
+
while (!rendering_context_descriptions_.IsEmpty()) {
RenderingContextDescriptionCodec desc(
rendering_context_descriptions_.TakeAny());
@@ -213,10 +189,9 @@ void CanvasPerformanceMonitor::RecordMetrics(TimeTicks start_time,
// info.
WTF::String histogram_name_prefix =
WTF::String("Blink") + desc.GetHostTypeName();
- WTF::String histogram_name_radical = WTF::String(desc.GetThreadTypeName()) +
- desc.GetContextTypeName() +
- desc.GetResourceTypeName();
+ WTF::String histogram_name_radical = WTF::String(desc.GetContextTypeName());
+ // Render task duration metric for all render tasks.
{
WTF::String histogram_name = histogram_name_prefix +
kMeasurementName_RenderTaskDuration +
@@ -225,6 +200,7 @@ void CanvasPerformanceMonitor::RecordMetrics(TimeTicks start_time,
elapsed_time);
}
+ // Render task duration metric for rAF callbacks only.
if (call_type_ == CallType::kAnimation) {
WTF::String histogram_name =
histogram_name_prefix + kMeasurementName_RenderTaskDuration +
@@ -232,7 +208,85 @@ void CanvasPerformanceMonitor::RecordMetrics(TimeTicks start_time,
base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
elapsed_time);
}
+
+ // Filtered histograms that apply to 2D canvases
+ if (desc.ContextType() == CanvasRenderingContext::kContext2D) {
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kPath)) {
+ WTF::String histogram_name = histogram_name_prefix +
+ kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_Path;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kImage)) {
+ WTF::String histogram_name = histogram_name_prefix +
+ kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_Image;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kImageData)) {
+ WTF::String histogram_name =
+ histogram_name_prefix + kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_ImageData;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kText)) {
+ WTF::String histogram_name = histogram_name_prefix +
+ kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_Text;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kRectangle)) {
+ WTF::String histogram_name =
+ histogram_name_prefix + kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_Rectangle;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ } else if (desc.ContextType() == CanvasRenderingContext::kContextWebgl ||
+ desc.ContextType() == CanvasRenderingContext::kContextWebgl2 ||
+ desc.ContextType() ==
+ CanvasRenderingContext::kContextExperimentalWebgl) {
+ // Filtered histograms that apply to WebGL canvases
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kDrawArrays)) {
+ WTF::String histogram_name =
+ histogram_name_prefix + kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_DrawArrays;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ if (draw_types_ & static_cast<uint32_t>(DrawType::kDrawElements)) {
+ WTF::String histogram_name =
+ histogram_name_prefix + kMeasurementName_RenderTaskDuration +
+ histogram_name_radical + kFilterName_DrawElements;
+ base::UmaHistogramMicrosecondsTimes(histogram_name.Latin1(),
+ elapsed_time);
+ }
+ }
+ // TODO(junov) Add filtered histograms that apply to WebGPU canvases
+
+ // PartitionAlloc heap size metric
+ {
+ WTF::String histogram_name = histogram_name_prefix +
+ kMeasurementName_PartitionAlloc +
+ histogram_name_radical;
+ base::UmaHistogramMemoryKB(histogram_name.Latin1(),
+ static_cast<int>(partition_alloc_kb));
+ }
+
+ // Blink garbage collected heap size metric
+ {
+ WTF::String histogram_name = histogram_name_prefix +
+ kMeasurementName_BlinkGC +
+ histogram_name_radical;
+ base::UmaHistogramMemoryKB(histogram_name.Latin1(),
+ static_cast<int>(blink_gc_alloc_kb));
+ }
}
+
}
void CanvasPerformanceMonitor::DidProcessTask(TimeTicks start_time,
@@ -244,14 +298,14 @@ void CanvasPerformanceMonitor::DidProcessTask(TimeTicks start_time,
RecordMetrics(start_time, end_time);
is_render_task_ = false;
- draw_flags_ = 0;
+ draw_types_ = 0;
}
void CanvasPerformanceMonitor::ResetForTesting() {
if (is_render_task_)
Thread::Current()->RemoveTaskTimeObserver(this);
is_render_task_ = false;
- draw_flags_ = 0;
+ draw_types_ = 0;
rendering_context_descriptions_.clear();
call_type_ = CallType::kOther;
task_counter_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h
index acccbedc3c8..c487142c1d9 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h
@@ -19,9 +19,30 @@ class CanvasRenderingContext;
class CORE_EXPORT CanvasPerformanceMonitor
: public base::sequence_manager::TaskTimeObserver {
public:
+ // Flag bits that can be passed to DidDraw.
+ enum class DrawType {
+ kOther = 0,
+
+ // It is allowed to re-number the elements of this enum
+
+ // 2D context draw types
+ kPath = 1 << 0,
+ kImage = 1 << 1,
+ kText = 1 << 2,
+ kRectangle = 1 << 3,
+ kImageData = 1 << 4,
+
+ // WebGL draw types
+ kDrawArrays = 1 << 5,
+ kDrawElements = 1 << 6,
+ };
+
CanvasPerformanceMonitor() = default;
void CurrentTaskDrawsToContext(CanvasRenderingContext*);
+ ALWAYS_INLINE void DidDraw(DrawType draw_type) {
+ draw_types_ |= static_cast<uint32_t>(draw_type);
+ }
// Call this at the end of unit tests that use CanvasRenderingContext, to
// reset state that may otherwise be leaked between tests.
@@ -42,7 +63,7 @@ class CORE_EXPORT CanvasPerformanceMonitor
};
HashSet<uint32_t> rendering_context_descriptions_;
- uint32_t draw_flags_ = 0;
+ uint32_t draw_types_ = 0;
CallType call_type_ = CallType::kOther;
uint32_t task_counter_ = 0;
bool is_render_task_ = false;
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 ddb3721cd27..f404040c338 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
@@ -38,10 +38,12 @@ namespace blink {
CanvasRenderingContext::CanvasRenderingContext(
CanvasRenderingContextHost* host,
- const CanvasContextCreationAttributesCore& attrs)
+ const CanvasContextCreationAttributesCore& attrs,
+ CanvasRenderingAPI canvas_rendering_API)
: host_(host),
color_params_(attrs.color_space, attrs.pixel_format, attrs.alpha),
- creation_attributes_(attrs) {}
+ creation_attributes_(attrs),
+ canvas_rendering_type_(canvas_rendering_API) {}
void CanvasRenderingContext::Dispose() {
RenderTaskEnded();
@@ -58,14 +60,19 @@ void CanvasRenderingContext::Dispose() {
}
}
-void CanvasRenderingContext::DidDraw(const SkIRect& dirty_rect) {
- Host()->DidDraw(SkRect::Make(dirty_rect));
- DidDrawCommon();
-}
+void CanvasRenderingContext::DidDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType draw_type) {
+ Host()->DidDraw(dirty_rect);
+
+ auto& monitor = GetCanvasPerformanceMonitor();
+ monitor.DidDraw(draw_type);
+ if (did_draw_in_current_task_)
+ return;
-void CanvasRenderingContext::DidDraw() {
- Host()->DidDraw();
- DidDrawCommon();
+ monitor.CurrentTaskDrawsToContext(this);
+ did_draw_in_current_task_ = true;
+ Thread::Current()->AddTaskObserver(this);
}
void CanvasRenderingContext::DidProcessTask(
@@ -81,34 +88,33 @@ void CanvasRenderingContext::DidProcessTask(
Host()->PostFinalizeFrame();
}
-void CanvasRenderingContext::RecordUKMCanvasRenderingAPI(
- CanvasRenderingAPI canvasRenderingAPI) {
+void CanvasRenderingContext::RecordUKMCanvasRenderingAPI() {
DCHECK(Host());
const auto& ukm_params = Host()->GetUkmParameters();
if (Host()->IsOffscreenCanvas()) {
ukm::builders::ClientRenderingAPI(ukm_params.source_id)
.SetOffscreenCanvas_RenderingContext(
- static_cast<int>(canvasRenderingAPI))
+ static_cast<int>(canvas_rendering_type_))
.Record(ukm_params.ukm_recorder);
} else {
ukm::builders::ClientRenderingAPI(ukm_params.source_id)
- .SetCanvas_RenderingContext(static_cast<int>(canvasRenderingAPI))
+ .SetCanvas_RenderingContext(static_cast<int>(canvas_rendering_type_))
.Record(ukm_params.ukm_recorder);
}
}
-void CanvasRenderingContext::RecordUKMCanvasDrawnToRenderingAPI(
- CanvasRenderingAPI canvasRenderingAPI) {
+void CanvasRenderingContext::RecordUKMCanvasDrawnToRenderingAPI() {
DCHECK(Host());
const auto& ukm_params = Host()->GetUkmParameters();
if (Host()->IsOffscreenCanvas()) {
ukm::builders::ClientRenderingAPI(ukm_params.source_id)
.SetOffscreenCanvas_RenderingContextDrawnTo(
- static_cast<int>(canvasRenderingAPI))
+ static_cast<int>(canvas_rendering_type_))
.Record(ukm_params.ukm_recorder);
} else {
ukm::builders::ClientRenderingAPI(ukm_params.source_id)
- .SetCanvas_RenderingContextDrawnTo(static_cast<int>(canvasRenderingAPI))
+ .SetCanvas_RenderingContextDrawnTo(
+ static_cast<int>(canvas_rendering_type_))
.Record(ukm_params.ukm_recorder);
}
}
@@ -126,9 +132,10 @@ CanvasRenderingContext::ContextType CanvasRenderingContext::ContextTypeFromId(
return kContextWebgl2;
if (id == "bitmaprenderer")
return kContextImageBitmap;
- if (id == "gpupresent" &&
+ // TODO(crbug.com/1229274): Remove 'gpupresent' type after deprecation period.
+ if ((id == "webgpu" || id == "gpupresent") &&
RuntimeEnabledFeatures::WebGPUEnabled(execution_context))
- return kContextGPUPresent;
+ return kContextWebGPU;
return kContextTypeUnknown;
}
@@ -159,15 +166,7 @@ bool CanvasRenderingContext::WouldTaintOrigin(CanvasImageSource* image_source) {
void CanvasRenderingContext::Trace(Visitor* visitor) const {
visitor->Trace(host_);
ScriptWrappable::Trace(visitor);
-}
-
-void CanvasRenderingContext::DidDrawCommon() {
- if (did_draw_in_current_task_)
- return;
-
- GetCanvasPerformanceMonitor().CurrentTaskDrawsToContext(this);
- did_draw_in_current_task_ = true;
- Thread::Current()->AddTaskObserver(this);
+ ActiveScriptWrappable::Trace(visitor);
}
void CanvasRenderingContext::RenderTaskEnded() {
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 e5af3dfca32..f591ed405a2 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
@@ -26,8 +26,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_H_
-#include "base/macros.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
+#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/html/canvas/canvas_context_creation_attributes_core.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.h"
@@ -51,11 +51,15 @@ class
class
V8UnionGPUCanvasContextOrImageBitmapRenderingContextOrOffscreenCanvasRenderingContext2DOrWebGL2RenderingContextOrWebGLRenderingContext;
-class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
- public Thread::TaskObserver {
+class CORE_EXPORT CanvasRenderingContext
+ : public ScriptWrappable,
+ public ActiveScriptWrappable<CanvasRenderingContext>,
+ public Thread::TaskObserver {
USING_PRE_FINALIZER(CanvasRenderingContext, Dispose);
public:
+ CanvasRenderingContext(const CanvasRenderingContext&) = delete;
+ CanvasRenderingContext& operator=(const CanvasRenderingContext&) = delete;
~CanvasRenderingContext() override = default;
// A Canvas can either be "2D" or "webgl" but never both. Requesting a context
@@ -71,14 +75,14 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
kContextImageBitmap = 5,
kContextXRPresent = 6,
// WebGL2Compute used to be 7.
- kContextGPUPresent = 8,
+ kContextWebGPU = 8, // WebGPU
kContextTypeUnknown = 9,
kMaxValue = kContextTypeUnknown,
};
// Correspond to CanvasRenderingAPI defined in
// tools/metrics/histograms/enums.xml
- enum CanvasRenderingAPI {
+ enum class CanvasRenderingAPI {
k2D = 0,
kWebgl = 1,
kWebgl2 = 2,
@@ -86,9 +90,39 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
kWebgpu = 4,
};
- void RecordUKMCanvasRenderingAPI(CanvasRenderingAPI canvasRenderingAPI);
- void RecordUKMCanvasDrawnToRenderingAPI(
- CanvasRenderingAPI canvasRenderingAPI);
+ bool IsRenderingContext2D() const {
+ return canvas_rendering_type_ == CanvasRenderingAPI::k2D;
+ }
+ bool IsImageBitmapRenderingContext() const {
+ return canvas_rendering_type_ == CanvasRenderingAPI::kBitmaprenderer;
+ }
+ bool IsWebGL() const {
+ return canvas_rendering_type_ == CanvasRenderingAPI::kWebgl ||
+ canvas_rendering_type_ == CanvasRenderingAPI::kWebgl2;
+ }
+ bool IsWebGL2() const {
+ return canvas_rendering_type_ == CanvasRenderingAPI::kWebgl2;
+ }
+ bool IsWebGPU() const {
+ return canvas_rendering_type_ == CanvasRenderingAPI::kWebgpu;
+ }
+
+ // ActiveScriptWrappable
+ // As this class inherits from ActiveScriptWrappable, as long as
+ // HasPendingActivity returns true, we can ensure that the Garbage Collector
+ // won't try to collect this class. This is needed specifically for the
+ // offscreencanvas use case.
+ bool HasPendingActivity() const override { return false; }
+ ExecutionContext* GetExecutionContext() const {
+ if (!Host())
+ return nullptr;
+ return Host()->GetTopExecutionContext();
+ }
+
+ void RecordUKMCanvasRenderingAPI();
+
+ // This is only used in WebGL
+ void RecordUKMCanvasDrawnToRenderingAPI();
static ContextType ContextTypeFromId(
const String& id,
@@ -126,7 +160,6 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
// called when the context is first displayed.
virtual void SetIsBeingDisplayed(bool) = 0;
virtual bool isContextLost() const { return true; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// TODO(fserb): remove AsV8RenderingContext and AsV8OffscreenRenderingContext.
virtual V8UnionCanvasRenderingContext2DOrGPUCanvasContextOrImageBitmapRenderingContextOrWebGL2RenderingContextOrWebGLRenderingContext*
AsV8RenderingContext() {
@@ -138,22 +171,24 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- // TODO(fserb): remove SetCanvasGetContextResult.
- virtual void SetCanvasGetContextResult(RenderingContext&) { NOTREACHED(); }
- virtual void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) {
- NOTREACHED();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual bool IsPaintable() const = 0;
- virtual void DidDraw(const SkIRect& dirty_rect);
- virtual void DidDraw();
+ void DidDraw(CanvasPerformanceMonitor::DrawType draw_type) {
+ return DidDraw(Host() ? SkIRect::MakeWH(Host()->width(), Host()->height())
+ : SkIRect::MakeEmpty(),
+ draw_type);
+ }
+ void DidDraw(const SkIRect& dirty_rect, CanvasPerformanceMonitor::DrawType);
// Return true if the content is updated.
virtual bool PaintRenderingResultsToCanvas(SourceDrawingBuffer) {
return false;
}
+ virtual bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
+ SourceDrawingBuffer) {
+ return false;
+ }
+
virtual cc::Layer* CcLayer() const { return nullptr; }
enum LostContextMode {
@@ -169,6 +204,7 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
kSyntheticLostContext,
};
virtual void LoseContext(LostContextMode) {}
+ virtual void SendContextLostEventIfNeeded() {}
// This method gets called at the end of script tasks that modified
// the contents of the canvas (called didDraw). It marks the completion
@@ -180,7 +216,6 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
void WillProcessTask(const base::PendingTask&, bool) final {}
// Canvas2D-specific interface
- virtual bool IsRenderingContext2D() const { return false; }
virtual void RestoreCanvasMatrixClipStack(cc::PaintCanvas*) const {}
virtual void Reset() {}
virtual void ClearRect(double x, double y, double width, double height) {}
@@ -199,9 +234,8 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
virtual void ResetUsageTracking() {}
// WebGL-specific interface
- virtual bool Is3d() const { return false; }
virtual bool UsingSwapChain() const { return false; }
- virtual void SetFilterQuality(SkFilterQuality) { NOTREACHED(); }
+ virtual void SetFilterQuality(cc::PaintFlags::FilterQuality) { NOTREACHED(); }
virtual void Reshape(int width, int height) {}
virtual void MarkLayerComposited() { NOTREACHED(); }
virtual sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer) {
@@ -217,10 +251,11 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
return IntSize(0, 0);
}
- // OffscreenCanvas-specific methods
+ // OffscreenCanvas-specific methods.
virtual bool PushFrame() { return false; }
virtual ImageBitmap* TransferToImageBitmap(ScriptState*) { return nullptr; }
+
bool WouldTaintOrigin(CanvasImageSource*);
void DidMoveToNewDocument(Document*);
@@ -244,9 +279,14 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
static CanvasPerformanceMonitor& GetCanvasPerformanceMonitor();
+ virtual bool IdentifiabilityEncounteredPartiallyDigestedImage() const {
+ return false;
+ }
+
protected:
CanvasRenderingContext(CanvasRenderingContextHost*,
- const CanvasContextCreationAttributesCore&);
+ const CanvasContextCreationAttributesCore&,
+ CanvasRenderingAPI);
private:
void Dispose();
@@ -255,11 +295,10 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
CanvasColorParams color_params_;
CanvasContextCreationAttributesCore creation_attributes_;
- void DidDrawCommon();
void RenderTaskEnded();
bool did_draw_in_current_task_ = false;
- DISALLOW_COPY_AND_ASSIGN(CanvasRenderingContext);
+ const CanvasRenderingAPI canvas_rendering_type_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h
index dff8ab7ce2e..7dc60640e95 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_FACTORY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_FACTORY_H_
-#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"
@@ -23,6 +22,9 @@ class CORE_EXPORT CanvasRenderingContextFactory {
public:
CanvasRenderingContextFactory() = default;
+ CanvasRenderingContextFactory(const CanvasRenderingContextFactory&) = delete;
+ CanvasRenderingContextFactory& operator=(
+ const CanvasRenderingContextFactory&) = delete;
virtual ~CanvasRenderingContextFactory() = default;
virtual CanvasRenderingContext* Create(
@@ -32,8 +34,6 @@ class CORE_EXPORT CanvasRenderingContextFactory {
virtual CanvasRenderingContext::ContextType GetContextType() const = 0;
virtual void OnError(HTMLCanvasElement*, const String& error) {}
virtual void OnError(OffscreenCanvas*, const String& error) {}
-
- DISALLOW_COPY_AND_ASSIGN(CanvasRenderingContextFactory);
};
} // namespace blink
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 b2327a95a9c..f3ce73c806b 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
@@ -75,14 +75,23 @@ void CanvasRenderingContextHost::RestoreCanvasMatrixClipStack(
RenderingContext()->RestoreCanvasMatrixClipStack(canvas);
}
-bool CanvasRenderingContextHost::Is3d() const {
- return RenderingContext() && RenderingContext()->Is3d();
+bool CanvasRenderingContextHost::IsWebGL() const {
+ return RenderingContext() && RenderingContext()->IsWebGL();
+}
+
+bool CanvasRenderingContextHost::IsWebGPU() const {
+ return RenderingContext() && RenderingContext()->IsWebGPU();
}
bool CanvasRenderingContextHost::IsRenderingContext2D() const {
return RenderingContext() && RenderingContext()->IsRenderingContext2D();
}
+bool CanvasRenderingContextHost::IsImageBitmapRenderingContext() const {
+ return RenderingContext() &&
+ RenderingContext()->IsImageBitmapRenderingContext();
+}
+
CanvasResourceProvider*
CanvasRenderingContextHost::GetOrCreateCanvasResourceProvider(
RasterModeHint hint) {
@@ -94,9 +103,12 @@ CanvasRenderingContextHost::GetOrCreateCanvasResourceProviderImpl(
RasterModeHint hint) {
if (!ResourceProvider() && !did_fail_to_create_resource_provider_) {
if (IsValidImageSize(Size())) {
- if (Is3d()) {
- CreateCanvasResourceProvider3D();
+ if (IsWebGPU()) {
+ CreateCanvasResourceProviderWebGPU();
+ } else if (IsWebGL()) {
+ CreateCanvasResourceProviderWebGL();
} else {
+ DCHECK(IsRenderingContext2D());
CreateCanvasResourceProvider2D(hint);
}
}
@@ -106,8 +118,24 @@ CanvasRenderingContextHost::GetOrCreateCanvasResourceProviderImpl(
return ResourceProvider();
}
-void CanvasRenderingContextHost::CreateCanvasResourceProvider3D() {
- DCHECK(Is3d());
+void CanvasRenderingContextHost::CreateCanvasResourceProviderWebGPU() {
+ std::unique_ptr<CanvasResourceProvider> provider;
+ if (SharedGpuContext::IsGpuCompositingEnabled()) {
+ provider = CanvasResourceProvider::CreateWebGPUImageProvider(
+ Size(), ColorParams().GetAsResourceParams(),
+ /*is_origin_top_left=*/true);
+ }
+ ReplaceResourceProvider(std::move(provider));
+ if (ResourceProvider() && ResourceProvider()->IsValid()) {
+ base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
+ ResourceProvider()->IsAccelerated());
+ base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
+ ResourceProvider()->GetType());
+ }
+}
+
+void CanvasRenderingContextHost::CreateCanvasResourceProviderWebGL() {
+ DCHECK(IsWebGL());
base::WeakPtr<CanvasResourceDispatcher> dispatcher =
GetOrCreateResourceDispatcher()
@@ -365,31 +393,19 @@ IdentifiableToken CanvasRenderingContextHost::IdentifiabilityInputDigest(
const CanvasRenderingContext* const context) const {
const uint64_t context_digest =
context ? context->IdentifiableTextToken().ToUkmMetricValue() : 0;
- const IdentifiabilityPaintOpDigest* const identifiability_paintop_digest =
- ResourceProvider()
- ? &(ResourceProvider()->GetIdentifiablityPaintOpDigest())
- : nullptr;
- const uint64_t canvas_digest =
- identifiability_paintop_digest
- ? identifiability_paintop_digest->GetToken().ToUkmMetricValue()
- : 0;
const uint64_t context_type =
context ? context->GetContextType()
: CanvasRenderingContext::kContextTypeUnknown;
const bool encountered_skipped_ops =
- (context && context->IdentifiabilityEncounteredSkippedOps()) ||
- (identifiability_paintop_digest &&
- identifiability_paintop_digest->encountered_skipped_ops());
+ context && context->IdentifiabilityEncounteredSkippedOps();
const bool encountered_sensitive_ops =
context && context->IdentifiabilityEncounteredSensitiveOps();
const bool encountered_partially_digested_image =
- identifiability_paintop_digest &&
- identifiability_paintop_digest->encountered_partially_digested_image();
+ context && context->IdentifiabilityEncounteredPartiallyDigestedImage();
// Bits [0-3] are the context type, bits [4-6] are skipped ops, sensitive
// ops, and partial image ops bits, respectively. The remaining bits are
// for the canvas digest.
- uint64_t final_digest =
- ((context_digest ^ canvas_digest) << 7) | context_type;
+ uint64_t final_digest = (context_digest << 7) | context_type;
if (encountered_skipped_ops)
final_digest |= IdentifiableSurface::CanvasTaintBit::kSkipped;
if (encountered_sensitive_ops)
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 5a4c9de1d28..9c66ade6af6 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
@@ -46,8 +46,8 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual void DetachContext() = 0;
- virtual void DidDraw(const FloatRect& rect) = 0;
- virtual void DidDraw() = 0;
+ virtual void DidDraw(const SkIRect& rect) = 0;
+ void DidDraw() { DidDraw(SkIRect::MakeWH(width(), height())); }
virtual void PreFinalizeFrame() = 0;
virtual void PostFinalizeFrame() = 0;
@@ -76,8 +76,6 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual bool ShouldAccelerate2dContext() const = 0;
- virtual bool IsNeutered() const { return false; }
-
virtual void Commit(scoped_refptr<CanvasResource> canvas_resource,
const SkIRect& damage_rect);
@@ -103,8 +101,10 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
CanvasResourceProvider* GetOrCreateCanvasResourceProvider(
RasterModeHint hint) override;
- bool Is3d() const;
+ bool IsWebGL() const;
+ bool IsWebGPU() const;
bool IsRenderingContext2D() const;
+ bool IsImageBitmapRenderingContext() const;
CanvasColorParams ColorParams() const;
// blink::CanvasImageSource
@@ -116,7 +116,8 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
scoped_refptr<StaticBitmapImage> CreateTransparentImage(const IntSize&) const;
void CreateCanvasResourceProvider2D(RasterModeHint hint);
- void CreateCanvasResourceProvider3D();
+ void CreateCanvasResourceProviderWebGL();
+ void CreateCanvasResourceProviderWebGPU();
// Computes the digest that corresponds to the "input" of this canvas,
// including the context type, and if applicable, canvas digest, and taint
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.cc
new file mode 100644
index 00000000000..470a13144c6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.cc
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+CanvasResourceTracker* CanvasResourceTracker::For(v8::Isolate* isolate) {
+ auto* isolate_data = V8PerIsolateData::From(isolate);
+ auto* canvas_resource_tracker = static_cast<CanvasResourceTracker*>(
+ isolate_data->CanvasResourceTracker());
+ if (!canvas_resource_tracker) {
+ canvas_resource_tracker = MakeGarbageCollected<CanvasResourceTracker>();
+ isolate_data->SetCanvasResourceTracker(canvas_resource_tracker);
+ }
+ return canvas_resource_tracker;
+}
+
+void CanvasResourceTracker::Add(CanvasRenderingContextHost* resource,
+ ExecutionContext* execution_context) {
+ resource_map_.insert(resource, execution_context);
+}
+
+const CanvasResourceTracker::ResourceMap&
+CanvasResourceTracker::GetResourceMap() const {
+ return resource_map_;
+}
+
+void CanvasResourceTracker::Trace(Visitor* visitor) const {
+ V8PerIsolateData::GarbageCollectedData::Trace(visitor);
+ visitor->Trace(resource_map_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h
new file mode 100644
index 00000000000..5c92a1509f5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RESOURCE_TRACKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RESOURCE_TRACKER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+
+namespace v8 {
+class Isolate;
+}
+
+namespace blink {
+
+class CanvasRenderingContextHost;
+class ExecutionContext;
+
+class CORE_EXPORT CanvasResourceTracker final
+ : public V8PerIsolateData::GarbageCollectedData {
+ public:
+ using ResourceMap = HeapHashMap<WeakMember<CanvasRenderingContextHost>,
+ WeakMember<ExecutionContext>>;
+
+ static CanvasResourceTracker* For(v8::Isolate*);
+
+ void Add(CanvasRenderingContextHost*, ExecutionContext*);
+ const ResourceMap& GetResourceMap() const;
+
+ void Trace(Visitor*) const override;
+
+ private:
+ ResourceMap resource_map_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RESOURCE_TRACKER_H_
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc
new file mode 100644
index 00000000000..cc0069c16cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h"
+
+#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+
+namespace blink {
+
+class HTMLCanvasResourceTrackerTest : public RenderingTest {
+ public:
+ HTMLCanvasResourceTrackerTest()
+ : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
+};
+
+TEST_F(HTMLCanvasResourceTrackerTest, AddCanvasElement) {
+ GetDocument().GetSettings()->SetScriptEnabled(true);
+ SetBodyInnerHTML("<canvas id='canvas'></canvas>");
+ auto* canvas = To<HTMLCanvasElement>(GetDocument().getElementById("canvas"));
+ auto* context = GetDocument().GetExecutionContext();
+ const auto& resource_map =
+ CanvasResourceTracker::For(context->GetIsolate())->GetResourceMap();
+ // The map may hold more than a single entry as CanvasResourceTracker is
+ // instantiated per v8::Isolate which is reused across tests.
+ const auto it = resource_map.find(canvas);
+ EXPECT_NE(resource_map.end(), it);
+ EXPECT_EQ(context, it->value);
+}
+
+} // 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 01097a03d36..aa958af9852 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
@@ -37,6 +37,7 @@
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
@@ -72,6 +73,7 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_font_cache.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h"
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
@@ -80,6 +82,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#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/hit_test_canvas_result.h"
#include "third_party/blink/renderer/core/layout/layout_html_canvas.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -134,6 +137,11 @@ HTMLCanvasElement::HTMLCanvasElement(Document& document)
externally_allocated_memory_(0) {
UseCounter::Count(document, WebFeature::kHTMLCanvasElement);
GetDocument().IncrementNumberOfCanvases();
+ auto* execution_context = GetExecutionContext();
+ if (execution_context) {
+ CanvasResourceTracker::For(execution_context->GetIsolate())
+ ->Add(this, execution_context);
+ }
}
HTMLCanvasElement::~HTMLCanvasElement() {
@@ -306,7 +314,8 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContext(
UseCounter::Count(doc, WebFeature::kNewCanvas2DAPI);
if (ContentsCcLayer() != old_contents_cc_layer)
- OnContentsCcLayerChanged();
+ SetNeedsCompositingUpdate();
+
return result;
}
@@ -321,6 +330,15 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContextInternal(
return nullptr;
}
+ // TODO(crbug.com/1229274): Remove 'gpupresent' type after deprecation period.
+ if (type == "gpupresent") {
+ auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "The context type 'gpupresent' is deprecated. Use 'webgpu' instead.");
+ GetExecutionContext()->AddConsoleMessage(console_message);
+ }
+
// Log the aliased context type used.
if (!context_) {
UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.ContextType", context_type);
@@ -356,6 +374,7 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContextInternal(
if (!context_)
return nullptr;
+ context_->RecordUKMCanvasRenderingAPI();
// Since the |context_| is created, free the transparent image,
// |transparent_image_| created for this canvas if it exists.
if (transparent_image_.get()) {
@@ -366,7 +385,7 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContextInternal(
probe::DidCreateCanvasContext(&GetDocument());
- if (Is3d())
+ if (IsWebGL())
UpdateMemoryUsage();
LayoutObject* layout_object = GetLayoutObject();
@@ -447,8 +466,8 @@ bool HTMLCanvasElement::IsWebGLBlocked() const {
return blocked;
}
-void HTMLCanvasElement::DidDraw(const FloatRect& rect) {
- if (rect.IsEmpty())
+void HTMLCanvasElement::DidDraw(const SkIRect& rect) {
+ if (rect.isEmpty())
return;
if (GetLayoutObject() && GetLayoutObject()->PreviousVisibilityVisible() &&
GetDocument().GetPage())
@@ -458,18 +477,14 @@ void HTMLCanvasElement::DidDraw(const FloatRect& rect) {
GetLayoutObject()->SetShouldCheckForPaintInvalidation();
if (IsRenderingContext2D() && context_->ShouldAntialias() && GetPage() &&
GetPage()->DeviceScaleFactorDeprecated() > 1.0f) {
- FloatRect inflated_rect = rect;
+ FloatRect inflated_rect = FloatRect(IntRect(rect));
inflated_rect.Inflate(1);
dirty_rect_.Unite(inflated_rect);
} else {
- dirty_rect_.Unite(rect);
+ dirty_rect_.Unite(FloatRect(IntRect(rect)));
}
if (IsRenderingContext2D() && canvas2d_bridge_)
- canvas2d_bridge_->DidDraw(rect);
-}
-
-void HTMLCanvasElement::DidDraw() {
- DidDraw(FloatRect(0, 0, Size().Width(), Size().Height()));
+ canvas2d_bridge_->DidDraw();
}
void HTMLCanvasElement::PreFinalizeFrame() {
@@ -580,8 +595,10 @@ void HTMLCanvasElement::DoDeferredPaintInvalidation() {
if (dirty_rect_.IsEmpty())
return;
- if (canvas2d_bridge_)
- canvas2d_bridge_->DoPaintInvalidation(invalidation_rect);
+ if (canvas2d_bridge_) {
+ canvas2d_bridge_->DoPaintInvalidation(
+ EnclosingIntRect(invalidation_rect));
+ }
}
if (context_ && HasImageBitmapContext() && context_->CcLayer())
@@ -643,7 +660,7 @@ void HTMLCanvasElement::Reset() {
SetSurfaceSize(new_size);
- if (Is3d() && old_size != Size())
+ if (IsWebGL() && old_size != Size())
context_->Reshape(width(), height());
if (LayoutObject* layout_object = GetLayoutObject()) {
@@ -724,12 +741,13 @@ bool HTMLCanvasElement::LowLatencyEnabled() const {
return !!frame_dispatcher_;
}
-void HTMLCanvasElement::SetFilterQuality(SkFilterQuality filter_quality) {
+void HTMLCanvasElement::SetFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) {
CanvasResourceHost::SetFilterQuality(filter_quality);
if (IsOffscreenCanvasRegistered())
UpdateOffscreenCanvasFilterQuality(filter_quality);
- if (context_ && Is3d())
+ if (context_ && (IsWebGL() || IsWebGPU()))
context_->SetFilterQuality(filter_quality);
else if (canvas2d_bridge_)
canvas2d_bridge_->SetFilterQuality(filter_quality);
@@ -798,10 +816,10 @@ void HTMLCanvasElement::PaintInternal(GraphicsContext& context,
// display list rendering: we replay the last full PaintRecord, if Canvas
// has been redraw since beginprint happened.
- if (IsPrinting() && !Is3d() && canvas2d_bridge_) {
+ if (IsPrinting() && IsRenderingContext2D() && canvas2d_bridge_) {
canvas2d_bridge_->FlushRecording();
if (canvas2d_bridge_->getLastRecord()) {
- if (FilterQuality() != kNone_SkFilterQuality) {
+ if (FilterQuality() != cc::PaintFlags::FilterQuality::kNone) {
context.Canvas()->save();
context.Canvas()->translate(r.X(), r.Y());
context.Canvas()->scale(r.Width() / Size().Width(),
@@ -831,8 +849,7 @@ void HTMLCanvasElement::PaintInternal(GraphicsContext& context,
const ComputedStyle* style = GetComputedStyle();
context.DrawImage(snapshot.get(), Image::kSyncDecode,
FloatRect(PixelSnappedIntRect(r)), &src_rect,
- style && style->HasFilterInducingProperty(),
- composite_operator);
+ style && style->DisableForceDark(), composite_operator);
}
} else {
// When alpha is false, we should draw to opaque black.
@@ -840,7 +857,7 @@ void HTMLCanvasElement::PaintInternal(GraphicsContext& context,
context.FillRect(FloatRect(r), Color(0, 0, 0));
}
- if (Is3d() && PaintsIntoCanvasBuffer())
+ if (IsWebGL() && PaintsIntoCanvasBuffer())
context_->MarkLayerComposited();
}
@@ -876,7 +893,7 @@ scoped_refptr<StaticBitmapImage> HTMLCanvasElement::Snapshot(
if (OffscreenCanvasFrame()) { // Offscreen Canvas
DCHECK(OffscreenCanvasFrame()->OriginClean());
image_bitmap = OffscreenCanvasFrame()->Bitmap();
- } else if (Is3d()) { // WebGL or WebGL2 canvas
+ } else if (IsWebGL()) {
if (context_->CreationAttributes().premultiplied_alpha) {
context_->PaintRenderingResultsToCanvas(source_buffer);
if (ResourceProvider())
@@ -898,10 +915,9 @@ scoped_refptr<StaticBitmapImage> HTMLCanvasElement::Snapshot(
image_bitmap = StaticBitmapImage::Create(std::move(pixel_data), info);
}
}
- } else if (canvas2d_bridge_) {
- DCHECK(IsRenderingContext2D());
- image_bitmap = canvas2d_bridge_->NewImageSnapshot();
- } else if (context_) { // Bitmap renderer canvas
+ } else if (context_) {
+ DCHECK(IsRenderingContext2D() || IsImageBitmapRenderingContext() ||
+ IsWebGPU());
image_bitmap = context_->GetImage();
}
@@ -1242,8 +1258,11 @@ void HTMLCanvasElement::PageVisibilityChanged() {
return;
context_->SetIsInHiddenPage(hidden);
- if (hidden && Is3d())
+ if (hidden && (IsWebGL() || IsWebGPU()))
DiscardResourceProvider();
+
+ if (!hidden)
+ context_->SendContextLostEventIfNeeded();
}
void HTMLCanvasElement::ContextDestroyed() {
@@ -1255,7 +1274,7 @@ bool HTMLCanvasElement::StyleChangeNeedsDidDraw(
const ComputedStyle* old_style,
const ComputedStyle& new_style) {
// It will only need to redraw for a style change, if the new imageRendering
- // is different than the previous one, and only if one of the two ir
+ // is different than the previous one, and only if one of the two are
// pixelated.
return old_style &&
old_style->ImageRendering() != new_style.ImageRendering() &&
@@ -1265,9 +1284,10 @@ bool HTMLCanvasElement::StyleChangeNeedsDidDraw(
void HTMLCanvasElement::StyleDidChange(const ComputedStyle* old_style,
const ComputedStyle& new_style) {
- SkFilterQuality filter_quality = kLow_SkFilterQuality;
+ cc::PaintFlags::FilterQuality filter_quality =
+ cc::PaintFlags::FilterQuality::kLow;
if (new_style.ImageRendering() == EImageRendering::kPixelated)
- filter_quality = kNone_SkFilterQuality;
+ filter_quality = cc::PaintFlags::FilterQuality::kNone;
SetFilterQuality(filter_quality);
style_is_visible_ = new_style.Visibility() == EVisibility::kVisible;
if (context_) {
@@ -1307,12 +1327,16 @@ void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) {
scoped_refptr<Image> HTMLCanvasElement::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize&) {
- return GetSourceImageForCanvasInternal(status);
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition) {
+
+ return GetSourceImageForCanvasInternal(status, alpha_disposition);
}
scoped_refptr<StaticBitmapImage>
-HTMLCanvasElement::GetSourceImageForCanvasInternal(SourceImageStatus* status) {
+HTMLCanvasElement::GetSourceImageForCanvasInternal(
+ SourceImageStatus* status,
+ const AlphaDisposition alpha_disposition) {
if (!width() || !height()) {
*status = kZeroSizeCanvasSourceImageStatus;
return nullptr;
@@ -1323,34 +1347,25 @@ HTMLCanvasElement::GetSourceImageForCanvasInternal(SourceImageStatus* status) {
return nullptr;
}
+ scoped_refptr<StaticBitmapImage> image;
+
if (OffscreenCanvasFrame()) {
- // This may be false even if this HTMLCanvasElement has been transferred
+ // This may be false to set status to normal if a valid image can be got
+ // even if this HTMLCanvasElement has been transferred
// control to an offscreenCanvas. As offscreencanvas with the
// TransferControlToOffscreen is asynchronous, this will need to finish the
// first Frame in order to have a first OffscreenCanvasFrame.
- *status = kNormalSourceImageStatus;
- return OffscreenCanvasFrame()->Bitmap();
- }
-
- if (!context_) {
- scoped_refptr<StaticBitmapImage> result = GetTransparentImage();
- *status = result ? kNormalSourceImageStatus : kInvalidSourceImageStatus;
- return result;
- }
-
- if (HasImageBitmapContext()) {
- *status = kNormalSourceImageStatus;
- scoped_refptr<StaticBitmapImage> result = context_->GetImage();
- if (!result)
- result = GetTransparentImage();
- *status = result ? kNormalSourceImageStatus : kInvalidSourceImageStatus;
- return result;
- }
+ image = OffscreenCanvasFrame()->Bitmap();
+ } else if (!context_) {
+ image = GetTransparentImage();
+ } else if (HasImageBitmapContext()) {
+ image = context_->GetImage();
- scoped_refptr<StaticBitmapImage> image;
- // TODO(ccameron): Canvas should produce sRGB images.
- // https://crbug.com/672299
- if (Is3d()) {
+ if (!image)
+ image = GetTransparentImage();
+ } else if (IsWebGL()) {
+ // TODO(ccameron): Canvas should produce sRGB images.
+ // https://crbug.com/672299
// Because WebGL sources always require making a copy of the back buffer, we
// use paintRenderingResultsToCanvas instead of getImage in order to keep a
// cached copy of the backing in the canvas's resource provider.
@@ -1365,11 +1380,15 @@ HTMLCanvasElement::GetSourceImageForCanvasInternal(SourceImageStatus* status) {
image = GetTransparentImage();
}
- if (image)
- *status = kNormalSourceImageStatus;
- else
+ if (!image) {
+ // All other possible error statuses were checked earlier.
*status = kInvalidSourceImageStatus;
- return image;
+ return image;
+ }
+
+ *status = kNormalSourceImageStatus;
+ // If the alpha_disposition is already correct, this is a no-op.
+ return GetImageWithAlphaDisposition(std::move(image), alpha_disposition);
}
bool HTMLCanvasElement::WouldTaintOrigin() const {
@@ -1417,6 +1436,10 @@ bool HTMLCanvasElement::IsOpaque() const {
return context_ && !context_->CreationAttributes().alpha;
}
+bool HTMLCanvasElement::IsVisible() const {
+ return GetPage() && GetPage()->IsPageVisible();
+}
+
bool HTMLCanvasElement::IsSupportedInteractiveCanvasFallback(
const Element& element) {
if (!element.IsDescendantOf(this))
@@ -1521,11 +1544,11 @@ void HTMLCanvasElement::OnWebLayerUpdated() {
}
void HTMLCanvasElement::RegisterContentsLayer(cc::Layer* layer) {
- OnContentsCcLayerChanged();
+ SetNeedsCompositingUpdate();
}
void HTMLCanvasElement::UnregisterContentsLayer(cc::Layer* layer) {
- OnContentsCcLayerChanged();
+ SetNeedsCompositingUpdate();
}
FontSelector* HTMLCanvasElement::GetFontSelector() {
@@ -1536,7 +1559,7 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
int non_gpu_buffer_count = 0;
int gpu_buffer_count = 0;
- if (!IsRenderingContext2D() && !Is3d())
+ if (!IsRenderingContext2D() && !IsWebGL())
return;
if (ResourceProvider()) {
non_gpu_buffer_count++;
@@ -1549,7 +1572,7 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
}
}
- if (Is3d())
+ if (IsWebGL())
non_gpu_buffer_count += context_->ExternallyAllocatedBufferCountPerPixel();
const int bytes_per_pixel = ColorParams().BytesPerPixel();
@@ -1584,6 +1607,10 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
externally_allocated_memory_ = externally_allocated_memory;
}
+size_t HTMLCanvasElement::GetMemoryUsage() const {
+ return base::saturated_cast<size_t>(externally_allocated_memory_);
+}
+
void HTMLCanvasElement::ReplaceExisting2dLayerBridge(
std::unique_ptr<Canvas2DLayerBridge> new_layer_bridge) {
scoped_refptr<StaticBitmapImage> image;
@@ -1678,14 +1705,6 @@ cc::Layer* HTMLCanvasElement::ContentsCcLayer() const {
return nullptr;
}
-void HTMLCanvasElement::OnContentsCcLayerChanged() {
- // We need to repaint the layer because the foreign layer display item may
- // appear, disappear or change.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
- GetLayoutObject() && GetLayoutObject()->HasLayer())
- GetLayoutBoxModelObject()->Layer()->SetNeedsRepaint();
-}
-
RespectImageOrientationEnum HTMLCanvasElement::RespectImageOrientation() const {
// TODO(junov): Computing style here will be problematic for applying the
// NoAllocDirectCall IDL attribute to drawImage.
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 905b0acc561..5b3439d7633 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
@@ -85,8 +85,6 @@ typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextO
// It can be a 3D Context (WebGL or WebGL2), 2D Context,
// BitmapRenderingContext or it can have no context (Offscreen placeholder).
// To check the no context case is good to check if there is a placeholder.
-// For 3D and 2D contexts there are Is3D or IsRenderingContext2D functions.
-// The remaining case is BitmaprenderingContext.
//
// TODO (juanmihd): Study if a refactor of context could help in simplifying
// this class and without overcomplicating context.
@@ -153,8 +151,8 @@ class CORE_EXPORT HTMLCanvasElement final
bool HasCanvasCapture() const final { return !listeners_.IsEmpty(); }
// Used for rendering
- void DidDraw(const FloatRect&) override;
- void DidDraw() override;
+ void DidDraw(const SkIRect&) override;
+ using CanvasRenderingContextHost::DidDraw;
void Paint(GraphicsContext&,
const PhysicalRect&,
@@ -183,6 +181,7 @@ class CORE_EXPORT HTMLCanvasElement final
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
bool IsDirty() { return !dirty_rect_.IsEmpty(); }
+ bool IsVisible() const;
void DoDeferredPaintInvalidation();
@@ -201,8 +200,10 @@ class CORE_EXPORT HTMLCanvasElement final
void PageVisibilityChanged() override;
// CanvasImageSource implementation
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) override;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) override;
bool WouldTaintOrigin() const override;
FloatSize ElementSize(const FloatSize&,
const RespectImageOrientationEnum) const override;
@@ -219,12 +220,13 @@ class CORE_EXPORT HTMLCanvasElement final
void NotifyGpuContextLost() override;
void SetNeedsCompositingUpdate() override;
void UpdateMemoryUsage() override;
+ size_t GetMemoryUsage() const override;
bool ShouldAccelerate2dContext() const override;
bool LowLatencyEnabled() const override;
CanvasResourceProvider* GetOrCreateCanvasResourceProvider(
RasterModeHint hint) override;
bool IsPrinting() const override;
- void SetFilterQuality(SkFilterQuality filter_quality) override;
+ void SetFilterQuality(cc::PaintFlags::FilterQuality filter_quality) override;
// CanvasRenderingContextHost implementation.
UkmParameters GetUkmParameters() override;
@@ -321,6 +323,8 @@ class CORE_EXPORT HTMLCanvasElement final
bool IsCanvasClear() { return canvas_is_clear_; }
+ bool IsPlaceholder() const override { return IsOffscreenCanvasRegistered(); }
+
protected:
void DidMoveToNewDocument(Document& old_document) override;
@@ -376,9 +380,8 @@ class CORE_EXPORT HTMLCanvasElement final
const CanvasContextCreationAttributesCore&);
scoped_refptr<StaticBitmapImage> GetSourceImageForCanvasInternal(
- SourceImageStatus*);
-
- void OnContentsCcLayerChanged();
+ SourceImageStatus*,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha);
HeapHashSet<WeakMember<CanvasDrawListener>> listeners_;
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 d8f04c404a2..3a6ff316fd3 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,7 +40,7 @@
[HighEntropy, MeasureAs=CanvasToBlob, RaisesException] void toBlob(BlobCallback _callback, optional DOMString type = "image/png", optional any quality);
- [HighEntropy, RuntimeEnabled=CanvasColorManagement, MeasureAs=CanvasConvertToBlob, RaisesException, CallWith=ScriptState] Promise<Blob> convertToBlob(optional ImageEncodeOptions options = {});
+ [HighEntropy, RuntimeEnabled=CanvasColorManagementV2, MeasureAs=CanvasConvertToBlob, RaisesException, CallWith=ScriptState] Promise<Blob> convertToBlob(optional ImageEncodeOptions options = {});
};
// https://html.spec.whatwg.org/C/#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 ac778379026..188f7c5df88 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
@@ -31,7 +31,6 @@
#include "base/sys_byteorder.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_clamped_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_float32array_uint16array_uint8clampedarray.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/html/canvas/predefined_color_space.h"
@@ -73,6 +72,11 @@ ImageData* ImageData::ValidateAndCreate(
exception_state.ThrowTypeError("Overload resolution failed.");
return nullptr;
}
+ if (params.require_canvas_color_management_v2 &&
+ !RuntimeEnabledFeatures::CanvasColorManagementV2Enabled()) {
+ exception_state.ThrowTypeError("Overload resolution failed.");
+ return nullptr;
+ }
if (settings && settings->hasColorSpace()) {
if (!ColorSpaceNameIsValid(settings->colorSpace(), exception_state))
return nullptr;
@@ -374,7 +378,6 @@ ImageDataSettings* ImageData::getSettings() const {
}
bool ImageData::IsBufferBaseDetached() const {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (data_->GetContentType()) {
case V8ImageDataArray::ContentType::kFloat32Array:
return data_->GetAsFloat32Array()->BufferBase()->IsDetached();
@@ -386,22 +389,12 @@ bool ImageData::IsBufferBaseDetached() const {
NOTREACHED();
return false;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (data_.IsUint8ClampedArray())
- return data_.GetAsUint8ClampedArray()->BufferBase()->IsDetached();
- if (data_.IsUint16Array())
- return data_.GetAsUint16Array()->BufferBase()->IsDetached();
- if (data_.IsFloat32Array())
- return data_.GetAsFloat32Array()->BufferBase()->IsDetached();
- return false;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
SkPixmap ImageData::GetSkPixmap() const {
CHECK(!IsBufferBaseDetached());
SkColorType color_type = kRGBA_8888_SkColorType;
const void* data = nullptr;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (data_->GetContentType()) {
case V8ImageDataArray::ContentType::kFloat32Array:
color_type = kRGBA_F32_SkColorType;
@@ -416,18 +409,6 @@ SkPixmap ImageData::GetSkPixmap() const {
data = data_->GetAsUint8ClampedArray()->Data();
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (data_.IsUint8ClampedArray()) {
- color_type = kRGBA_8888_SkColorType;
- data = data_.GetAsUint8ClampedArray()->Data();
- } else if (data_.IsUint16Array()) {
- color_type = kR16G16B16A16_unorm_SkColorType;
- data = data_.GetAsUint16Array()->Data();
- } else if (data_.IsFloat32Array()) {
- color_type = kRGBA_F32_SkColorType;
- data = data_.GetAsFloat32Array()->Data();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
SkImageInfo info =
SkImageInfo::Make(width(), height(), color_type, kUnpremul_SkAlphaType,
CanvasColorSpaceToSkColorSpace(GetCanvasColorSpace()));
@@ -450,7 +431,6 @@ v8::Local<v8::Object> ImageData::AssociateWithWrapper(
wrapper = ScriptWrappable::AssociateWithWrapper(isolate, wrapper_type_info,
wrapper);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (data_->IsUint8ClampedArray()) {
// Create a V8 object with |data_| and set the "data" property
// of the ImageData object to the created v8 object, eliminating the
@@ -473,30 +453,6 @@ v8::Local<v8::Object> ImageData::AssociateWithWrapper(
return wrapper;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (data_.IsUint8ClampedArray()) {
- // Create a V8 object with |data_| and set the "data" property
- // of the ImageData object to the created v8 object, eliminating the
- // C++ callback when accessing the "data" property.
- //
- // This is a perf hack breaking the web interop.
-
- v8::Local<v8::Value> v8_data;
- ScriptState* script_state = ScriptState::From(wrapper->CreationContext());
- if (!ToV8Traits<IDLUnionNotINT<ImageDataArray>>::ToV8(script_state, data_)
- .ToLocal(&v8_data)) {
- return wrapper;
- }
- bool defined_property;
- if (!wrapper
- ->DefineOwnProperty(isolate->GetCurrentContext(),
- V8AtomicString(isolate, "data"), v8_data,
- v8::ReadOnly)
- .To(&defined_property)) {
- return wrapper;
- }
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return wrapper;
}
@@ -531,11 +487,7 @@ ImageData::ImageData(const IntSize& size,
SECURITY_CHECK(
(base::CheckedNumeric<size_t>(size.Width()) * size.Height() * 4)
.ValueOrDie() <= data_u8_->length());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
data_ = MakeGarbageCollected<V8ImageDataArray>(data_u8_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- data_.SetUint8ClampedArray(data_u8_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
break;
case kUint16ArrayStorageFormat:
@@ -545,11 +497,7 @@ ImageData::ImageData(const IntSize& size,
SECURITY_CHECK(
(base::CheckedNumeric<size_t>(size.Width()) * size.Height() * 4)
.ValueOrDie() <= data_u16_->length());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
data_ = MakeGarbageCollected<V8ImageDataArray>(data_u16_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- data_.SetUint16Array(data_u16_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
break;
case kFloat32ArrayStorageFormat:
@@ -559,11 +507,7 @@ ImageData::ImageData(const IntSize& size,
SECURITY_CHECK(
(base::CheckedNumeric<size_t>(size.Width()) * size.Height() * 4)
.ValueOrDie() <= data_f32_->length());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
data_ = MakeGarbageCollected<V8ImageDataArray>(data_f32_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- data_.SetFloat32Array(data_f32_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
break;
default:
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 e2b7fa76512..f4db41fce14 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
@@ -30,7 +30,6 @@
#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/bindings/core/v8/v8_image_data_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -52,8 +51,6 @@ namespace blink {
class ExceptionState;
class ImageBitmapOptions;
-typedef Uint8ClampedArrayOrUint16ArrayOrFloat32Array ImageDataArray;
-
constexpr const char* kUint8ClampedArrayStorageFormatName = "uint8";
constexpr const char* kUint16ArrayStorageFormatName = "uint16";
constexpr const char* kFloat32ArrayStorageFormatName = "float32";
@@ -70,16 +67,24 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
DEFINE_WRAPPERTYPEINFO();
public:
- // Constructor that takes width, height, and an optional ImageDataSettings.
+ // Constructors that take width, height, and an optional ImageDataSettings.
static ImageData* Create(unsigned width,
unsigned height,
- const ImageDataSettings* settings,
ExceptionState& exception_state) {
- return ValidateAndCreate(width, height, absl::nullopt, settings,
+ return ValidateAndCreate(width, height, absl::nullopt, /*settings=*/nullptr,
ValidateAndCreateParams(), exception_state);
}
+ static ImageData* Create(unsigned width,
+ unsigned height,
+ const ImageDataSettings* settings,
+ ExceptionState& exception_state) {
+ ValidateAndCreateParams params;
+ params.require_canvas_color_management = true;
+ return ValidateAndCreate(width, height, absl::nullopt, settings, params,
+ exception_state);
+ }
- // Constructor that takes Uint8ClampedArray, width, optional height, and
+ // Constructors that take Uint8ClampedArray, width, optional height, and
// optional ImageDataSettings.
static ImageData* Create(NotShared<DOMUint8ClampedArray> data,
unsigned width,
@@ -90,11 +95,20 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
static ImageData* Create(NotShared<DOMUint8ClampedArray> data,
unsigned width,
unsigned height,
- const ImageDataSettings* settings,
ExceptionState& exception_state) {
- return ValidateAndCreate(width, height, data, settings,
+ return ValidateAndCreate(width, height, data, /*settings=*/nullptr,
ValidateAndCreateParams(), exception_state);
}
+ static ImageData* Create(NotShared<DOMUint8ClampedArray> data,
+ unsigned width,
+ unsigned height,
+ const ImageDataSettings* settings,
+ ExceptionState& exception_state) {
+ ValidateAndCreateParams params;
+ params.require_canvas_color_management = true;
+ return ValidateAndCreate(width, height, data, settings, params,
+ exception_state);
+ }
// Constructor that takes DOMUint16Array, width, optional height, and optional
// ImageDataSettings.
@@ -102,7 +116,7 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
unsigned width,
ExceptionState& exception_state) {
ValidateAndCreateParams params;
- params.require_canvas_color_management = true;
+ params.require_canvas_color_management_v2 = true;
return ValidateAndCreate(width, absl::nullopt, data, nullptr, params,
exception_state);
}
@@ -112,7 +126,7 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
const ImageDataSettings* settings,
ExceptionState& exception_state) {
ValidateAndCreateParams params;
- params.require_canvas_color_management = true;
+ params.require_canvas_color_management_v2 = true;
return ValidateAndCreate(width, height, data, settings, params,
exception_state);
}
@@ -123,7 +137,7 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
unsigned width,
ExceptionState& exception_state) {
ValidateAndCreateParams params;
- params.require_canvas_color_management = true;
+ params.require_canvas_color_management_v2 = true;
return ValidateAndCreate(width, absl::nullopt, data, nullptr, params,
exception_state);
}
@@ -133,7 +147,7 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
const ImageDataSettings* settings,
ExceptionState& exception_state) {
ValidateAndCreateParams params;
- params.require_canvas_color_management = true;
+ params.require_canvas_color_management_v2 = true;
return ValidateAndCreate(width, height, data, settings, params,
exception_state);
}
@@ -151,6 +165,10 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
// This argument is passed by Create functions that should require that the
// CanvasColorManagement feature be enabled.
bool require_canvas_color_management = false;
+ // Constructors in IDL files cannot specify RuntimeEnabled restrictions.
+ // This argument is passed by Create functions that should require that the
+ // CanvasColorManagementV2 feature be enabled.
+ bool require_canvas_color_management_v2 = false;
// If the caller is guaranteed to write over the result in its entirety,
// then this flag may be used to skip initialization of the result's
// data.
@@ -194,13 +212,7 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
// TODO(https://crbug.com/1198606): Remove this.
ImageDataSettings* getSettings() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageDataArray* data() const { return data_; }
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ImageDataArray& data() { return data_; }
- const ImageDataArray& data() const { return data_; }
- void data(ImageDataArray& result) { result = data_; }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool IsBufferBaseDetached() const;
CanvasColorSpace GetCanvasColorSpace() const;
@@ -227,11 +239,7 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
IntSize size_;
// TODO(https://crbug.com/1198606): Remove this.
Member<ImageDataSettings> settings_;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<V8ImageDataArray> data_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ImageDataArray data_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
NotShared<DOMUint8ClampedArray> data_u8_;
NotShared<DOMUint16Array> data_u16_;
NotShared<DOMFloat32Array> data_f32_;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_data.idl b/chromium/third_party/blink/renderer/core/html/canvas/image_data.idl
index 1d65418c1d9..f5bd844ead8 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_data.idl
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_data.idl
@@ -34,17 +34,18 @@ typedef (Uint8ClampedArray or Uint16Array or Float32Array) ImageDataArray;
Exposed=(Window,Worker),
Serializable
] interface ImageData {
- [RaisesException] constructor(unsigned long sw, unsigned long sh, optional ImageDataSettings settings = {});
+ [RaisesException] constructor(unsigned long sw, unsigned long sh);
+ [RaisesException] constructor(unsigned long sw, unsigned long sh, ImageDataSettings settings);
[RaisesException] constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh, optional ImageDataSettings settings = {});
[RaisesException] constructor(Uint16Array data, unsigned long sw, optional unsigned long sh, optional ImageDataSettings settings = {});
[RaisesException] constructor(Float32Array data, unsigned long sw, optional unsigned long sh, optional ImageDataSettings settings = {});
// TODO(crbug.com/1198606): Remove this.
- [RuntimeEnabled=CanvasColorManagement] ImageDataSettings getSettings();
+ [RuntimeEnabled=CanvasColorManagementV2] ImageDataSettings getSettings();
readonly attribute unsigned long width;
readonly attribute unsigned long height;
- readonly attribute PredefinedColorSpace colorSpace;
- [RuntimeEnabled=CanvasColorManagement] readonly attribute ImageDataStorageFormat storageFormat;
+ [RuntimeEnabled=CanvasColorManagement] readonly attribute PredefinedColorSpace colorSpace;
+ [RuntimeEnabled=CanvasColorManagementV2] readonly attribute ImageDataStorageFormat storageFormat;
readonly attribute ImageDataArray data;
};
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_data_settings.idl b/chromium/third_party/blink/renderer/core/html/canvas/image_data_settings.idl
index 08914ae7be6..6a2cbf58ce1 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_data_settings.idl
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_data_settings.idl
@@ -16,5 +16,5 @@ enum ImageDataStorageFormat {
dictionary ImageDataSettings {
PredefinedColorSpace colorSpace;
- [RuntimeEnabled=CanvasColorManagement] ImageDataStorageFormat storageFormat = "uint8";
+ [RuntimeEnabled=CanvasColorManagementV2] ImageDataStorageFormat storageFormat = "uint8";
};
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 1b8ca46a6dd..673d2a08cc9 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
@@ -47,7 +47,11 @@ bool ImageElementBase::IsImageElement() const {
scoped_refptr<Image> ImageElementBase::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize& default_object_size) {
+ const FloatSize& default_object_size,
+ const AlphaDisposition alpha_disposition) {
+ // UnpremultiplyAlpha is not implemented yet.
+ DCHECK_EQ(alpha_disposition, kPremultiplyAlpha);
+
ImageResourceContent* image_content = CachedImage();
if (!GetImageLoader().ImageComplete() || !image_content) {
*status = kIncompleteSourceImageStatus;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h b/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h
index 76ef21172e5..fb4af938d22 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h
@@ -32,8 +32,10 @@ class CORE_EXPORT ImageElementBase : public CanvasImageSource,
const ImageBitmapOptions*,
ExceptionState&) override;
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) override;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) override;
bool WouldTaintOrigin() const override;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.cc b/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.cc
index 3334575b05e..12350c735ef 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.cc
@@ -11,8 +11,8 @@ namespace blink {
bool ColorSpaceNameIsValid(const String& color_space_name,
ExceptionState& exception_state) {
- if (!RuntimeEnabledFeatures::CanvasColorManagementEnabled()) {
- // The enum value 'rec2020' is not valid unless CanvasColorManagement is
+ if (!RuntimeEnabledFeatures::CanvasColorManagementV2Enabled()) {
+ // The enum value 'rec2020' is not valid unless CanvasColorManagementV2 is
// enabled.
if (color_space_name == kRec2020CanvasColorSpaceName) {
exception_state.ThrowTypeError(
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.h b/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.h
index 685abd76be9..2a5db337763 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/predefined_color_space.h
@@ -12,9 +12,9 @@
namespace blink {
// Some values for PredefinedColorSpace are specified in the IDL but are
-// supposed to be guarded behind the CanvasColorManagement feature (e.g,
+// supposed to be guarded behind the CanvasColorManagementV2 feature (e.g,
// 'rec2020'). This function will throw the exception that the IDL would
-// have thrown, if CanvasColorManagement is not enabled.
+// have thrown, if CanvasColorManagementV2 is not enabled.
bool CORE_EXPORT ColorSpaceNameIsValid(const String& color_space_name,
ExceptionState& exception_state);
diff --git a/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc b/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
index fa79940c0da..677c3bcf6c7 100644
--- a/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
+++ b/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/core/html/conversion_measurement_parsing.h"
+#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_attribution_source_params.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
@@ -15,7 +16,6 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/html_anchor_element.h"
#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -25,9 +25,9 @@ namespace blink {
namespace {
-absl::optional<uint64_t> ParseExpiry(const String& expiry) {
+absl::optional<int64_t> ParseExpiry(const String& expiry) {
bool expiry_is_valid = false;
- uint64_t parsed_expiry = expiry.ToUInt64Strict(&expiry_is_valid);
+ int64_t parsed_expiry = expiry.ToInt64Strict(&expiry_is_valid);
return expiry_is_valid ? absl::make_optional(parsed_expiry) : absl::nullopt;
}
@@ -38,40 +38,56 @@ absl::optional<int64_t> ParsePriority(const String& priority) {
: absl::nullopt;
}
-absl::optional<WebImpression> GetImpression(
+absl::optional<WebImpression> WebImpressionOrErrorToWebImpression(
+ WebImpressionOrError v) {
+ if (auto* impression = absl::get_if<WebImpression>(&v))
+ return std::move(*impression);
+
+ return absl::nullopt;
+}
+
+// If `allow_invalid_impression_data` is `true` and `impression_data_string` is
+// not parsable as an unsigned 64-bit base-10 integer, the impression data is
+// defaulted to 0. If `allow_invalid_impression_data` is `false` and
+// `impression_data_string` fails to parse, `GetImpression()` returns an error.
+WebImpressionOrError GetImpression(
ExecutionContext* execution_context,
const String& impression_data_string,
const String& conversion_destination_string,
const absl::optional<String>& reporting_origin_string,
- absl::optional<uint64_t> impression_expiry_milliseconds,
+ absl::optional<int64_t> impression_expiry_milliseconds,
absl::optional<int64_t> attribution_source_priority,
- HTMLAnchorElement* element) {
- if (!RuntimeEnabledFeatures::ConversionMeasurementEnabled(execution_context))
- return absl::nullopt;
+ HTMLAnchorElement* element,
+ bool allow_invalid_impression_data) {
+ if (!RuntimeEnabledFeatures::ConversionMeasurementEnabled(
+ execution_context)) {
+ // TODO(crbug.com/1202170): It shouldn't be possible for this branch to be
+ // taken when this function is invoked from `registerAttributionSource` in
+ // JS, as that method is only supposed to exist when the runtime feature is
+ // enabled. Consider moving this check elsewhere to avoid redundancy.
+ return mojom::blink::RegisterImpressionError::kNotAllowed;
+ }
LocalFrame* frame = nullptr;
- if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context))
frame = window->GetFrame();
- } else {
- return absl::nullopt;
+
+ if (!frame) {
+ // TODO(apaseltiner): Perhaps this should be something like `kUnknown`.
+ return mojom::blink::RegisterImpressionError::kNotAllowed;
}
- if (!execution_context->IsFeatureEnabled(
- mojom::blink::PermissionsPolicyFeature::kAttributionReporting)) {
+ const bool feature_policy_enabled = execution_context->IsFeatureEnabled(
+ mojom::blink::PermissionsPolicyFeature::kAttributionReporting);
+ UMA_HISTOGRAM_BOOLEAN("Conversions.ImpressionIgnoredByFeaturePolicy",
+ !feature_policy_enabled);
+
+ if (!feature_policy_enabled) {
AuditsIssue::ReportAttributionIssue(
frame->DomWindow(),
AttributionReportingIssueType::kPermissionPolicyDisabled,
frame->GetDevToolsFrameToken(), element);
-
- // TODO(crbug.com/1178400): Remove console message once the issue reported
- // above is actually shown in DevTools.
- String message =
- "The 'attribution-reporting' permissions policy must be enabled to "
- "declare an attribution source.";
- execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::blink::ConsoleMessageSource::kOther,
- mojom::blink::ConsoleMessageLevel::kError, message));
- return absl::nullopt;
+ return mojom::blink::RegisterImpressionError::kNotAllowed;
}
// Conversion measurement is only allowed when both the frame and the main
@@ -85,7 +101,7 @@ absl::optional<WebImpression> GetImpression(
AttributionReportingIssueType::kAttributionSourceUntrustworthyOrigin,
main_frame.GetDevToolsFrameToken(), element, absl::nullopt,
main_frame.GetSecurityContext()->GetSecurityOrigin()->ToString());
- return absl::nullopt;
+ return mojom::blink::RegisterImpressionError::kInsecureContext;
}
if (!frame->IsMainFrame() && !frame->GetSecurityContext()
@@ -96,7 +112,7 @@ absl::optional<WebImpression> GetImpression(
AttributionReportingIssueType::kAttributionSourceUntrustworthyOrigin,
frame->GetDevToolsFrameToken(), element, absl::nullopt,
frame->GetSecurityContext()->GetSecurityOrigin()->ToString());
- return absl::nullopt;
+ return mojom::blink::RegisterImpressionError::kInsecureContext;
}
scoped_refptr<const SecurityOrigin> conversion_destination =
@@ -106,19 +122,28 @@ absl::optional<WebImpression> GetImpression(
frame->DomWindow(),
AttributionReportingIssueType::kAttributionSourceUntrustworthyOrigin,
absl::nullopt, element, absl::nullopt, conversion_destination_string);
- return absl::nullopt;
+ return mojom::blink::RegisterImpressionError::
+ kInsecureAttributionDestination;
}
bool impression_data_is_valid = false;
uint64_t impression_data =
impression_data_string.ToUInt64Strict(&impression_data_is_valid);
+ // For source registrations where there is no mechanism to raise an error,
+ // such as on an anchor element, it is more useful to log the source with
+ // default data so that a reporting origin can learn the failure mode.
if (!impression_data_is_valid) {
AuditsIssue::ReportAttributionIssue(
frame->DomWindow(),
AttributionReportingIssueType::kInvalidAttributionSourceEventId,
frame->GetDevToolsFrameToken(), element, absl::nullopt,
impression_data_string);
+
+ if (!allow_invalid_impression_data) {
+ return mojom::blink::RegisterImpressionError::
+ kInvalidAttributionSourceEventId;
+ }
}
// Provide a default of 0 if the impression data was not valid.
@@ -136,7 +161,8 @@ absl::optional<WebImpression> GetImpression(
frame->DomWindow(),
AttributionReportingIssueType::kAttributionSourceUntrustworthyOrigin,
absl::nullopt, element, absl::nullopt, *reporting_origin_string);
- return absl::nullopt;
+ return mojom::blink::RegisterImpressionError::
+ kInsecureAttributionReportTo;
}
}
@@ -160,7 +186,7 @@ absl::optional<WebImpression> GetImpression(
absl::optional<WebImpression> GetImpressionForAnchor(
HTMLAnchorElement* element) {
- absl::optional<uint64_t> expiry;
+ absl::optional<int64_t> expiry;
if (element->hasAttribute(html_names::kAttributionexpiryAttr)) {
expiry = ParseExpiry(
element->FastGetAttribute(html_names::kAttributionexpiryAttr)
@@ -177,7 +203,7 @@ absl::optional<WebImpression> GetImpressionForAnchor(
DCHECK(element->hasAttribute(html_names::kAttributiondestinationAttr));
DCHECK(element->hasAttribute(html_names::kAttributionsourceeventidAttr));
- return GetImpression(
+ return WebImpressionOrErrorToWebImpression(GetImpression(
element->GetExecutionContext(),
element->FastGetAttribute(html_names::kAttributionsourceeventidAttr)
.GetString(),
@@ -188,7 +214,7 @@ absl::optional<WebImpression> GetImpressionForAnchor(
element->FastGetAttribute(html_names::kAttributionreporttoAttr)
.GetString())
: absl::nullopt,
- expiry, priority, element);
+ expiry, priority, element, /*allow_invalid_impression_data=*/true));
}
absl::optional<WebImpression> GetImpressionFromWindowFeatures(
@@ -198,7 +224,7 @@ absl::optional<WebImpression> GetImpressionFromWindowFeatures(
features.conversion_destination.IsNull())
return absl::nullopt;
- return GetImpression(
+ return WebImpressionOrErrorToWebImpression(GetImpression(
execution_context, features.impression_data,
features.conversion_destination,
!features.reporting_origin.IsNull()
@@ -207,10 +233,11 @@ absl::optional<WebImpression> GetImpressionFromWindowFeatures(
!features.expiry.IsNull() ? ParseExpiry(features.expiry) : absl::nullopt,
!features.priority.IsNull() ? ParsePriority(features.priority)
: absl::nullopt,
- nullptr);
+ nullptr,
+ /*allow_invalid_impression_data=*/true));
}
-absl::optional<WebImpression> GetImpressionForParams(
+WebImpressionOrError GetImpressionForParams(
ExecutionContext* execution_context,
const AttributionSourceParams* params) {
return GetImpression(
@@ -225,7 +252,8 @@ absl::optional<WebImpression> GetImpressionForParams(
params->hasAttributionSourcePriority()
? absl::make_optional(params->attributionSourcePriority())
: absl::nullopt,
- nullptr);
+ nullptr,
+ /*allow_invalid_impression_data=*/false);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.h b/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.h
index c6409c5d3d2..11c62ff1f6d 100644
--- a/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.h
+++ b/chromium/third_party/blink/renderer/core/html/conversion_measurement_parsing.h
@@ -8,6 +8,8 @@
#include <stdint.h>
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/blink/public/mojom/conversions/conversions.mojom-blink.h"
#include "third_party/blink/public/platform/web_impression.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -39,9 +41,12 @@ absl::optional<WebImpression> GetImpressionFromWindowFeatures(
ExecutionContext* execution_context,
const ImpressionFeatures& features);
+using WebImpressionOrError =
+ absl::variant<WebImpression, mojom::blink::RegisterImpressionError>;
+
// Same as GetImpressionForAnchor(), but gets an impression specified by an
// AttributionSourceParams dictionary associated with a window.open call.
-absl::optional<WebImpression> GetImpressionForParams(
+WebImpressionOrError GetImpressionForParams(
ExecutionContext* execution_context,
const AttributionSourceParams* params);
diff --git a/chromium/third_party/blink/renderer/core/html/custom/ce_reactions_scope.h b/chromium/third_party/blink/renderer/core/html/custom/ce_reactions_scope.h
index c3bf1ee0507..9f24787fc81 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/ce_reactions_scope.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/ce_reactions_scope.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CE_REACTIONS_SCOPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CE_REACTIONS_SCOPE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -27,6 +26,9 @@ class CORE_EXPORT CEReactionsScope final {
top_of_stack_ = this;
}
+ CEReactionsScope(const CEReactionsScope&) = delete;
+ CEReactionsScope& operator=(const CEReactionsScope&) = delete;
+
~CEReactionsScope() {
if (work_to_do_)
InvokeReactions();
@@ -42,8 +44,6 @@ class CORE_EXPORT CEReactionsScope final {
CEReactionsScope* prev_;
bool work_to_do_;
-
- DISALLOW_COPY_AND_ASSIGN(CEReactionsScope);
};
} // namespace blink
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 26115f16314..be64441338d 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
@@ -272,7 +272,6 @@ void CustomElement::EnqueueFormDisabledCallback(Element& element,
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void CustomElement::EnqueueFormStateRestoreCallback(Element& element,
const V8ControlValue* value,
const String& mode) {
@@ -282,18 +281,6 @@ void CustomElement::EnqueueFormStateRestoreCallback(Element& element,
definition, value, mode));
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void CustomElement::EnqueueFormStateRestoreCallback(
- Element& element,
- const FileOrUSVStringOrFormData& value,
- const String& mode) {
- auto& definition = *DefinitionForElementWithoutCheck(element);
- if (definition.HasFormStateRestoreCallback()) {
- Enqueue(element, CustomElementReactionFactory::CreateFormStateRestore(
- definition, value, mode));
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void CustomElement::TryToUpgrade(Element& element) {
// Try to upgrade an element
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element.h
index d320afef0d1..80c7bf4238a 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element.h
@@ -18,7 +18,6 @@ namespace blink {
class Document;
class Element;
-class FileOrUSVStringOrFormData;
class HTMLElement;
class HTMLFormElement;
class QualifiedName;
@@ -112,16 +111,9 @@ class CORE_EXPORT CustomElement {
HTMLFormElement* nullable_form);
static void EnqueueFormResetCallback(Element& element);
static void EnqueueFormDisabledCallback(Element& element, bool is_disabled);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static void EnqueueFormStateRestoreCallback(Element& element,
const V8ControlValue* value,
const String& mode);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static void EnqueueFormStateRestoreCallback(
- Element& element,
- const FileOrUSVStringOrFormData& value,
- const String& mode);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static void TryToUpgrade(Element&);
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h
index 2e2e5573cb8..ddb53031134 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_DEFINITION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_DEFINITION_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -23,7 +22,6 @@ namespace blink {
class Document;
class Element;
class ExceptionState;
-class FileOrUSVStringOrFormData;
class HTMLElement;
class HTMLFormElement;
class QualifiedName;
@@ -41,7 +39,9 @@ class CORE_EXPORT CustomElementDefinition
// CustomElementRegistry that created it.
using Id = uint32_t;
- virtual ~CustomElementDefinition();
+ CustomElementDefinition(const CustomElementDefinition&) = delete;
+ CustomElementDefinition& operator=(const CustomElementDefinition&) = delete;
+ ~CustomElementDefinition() override;
virtual void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override {
@@ -94,16 +94,9 @@ class CORE_EXPORT CustomElementDefinition
HTMLFormElement* nullable_form) = 0;
virtual void RunFormResetCallback(Element& element) = 0;
virtual void RunFormDisabledCallback(Element& element, bool is_disabled) = 0;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual void RunFormStateRestoreCallback(Element& element,
const V8ControlValue* value,
const String& mode) = 0;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void RunFormStateRestoreCallback(
- Element& element,
- const FileOrUSVStringOrFormData& value,
- const String& mode) = 0;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void EnqueueUpgradeReaction(Element&);
void EnqueueConnectedCallback(Element&);
@@ -134,10 +127,11 @@ class CORE_EXPORT CustomElementDefinition
class CORE_EXPORT ConstructionStackScope final {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(ConstructionStackScope);
public:
ConstructionStackScope(CustomElementDefinition&, Element&);
+ ConstructionStackScope(const ConstructionStackScope&) = delete;
+ ConstructionStackScope& operator=(const ConstructionStackScope&) = delete;
~ConstructionStackScope();
private:
@@ -176,8 +170,6 @@ class CORE_EXPORT CustomElementDefinition
HeapVector<Member<CSSStyleSheet>> default_style_sheets_;
void EnqueueAttributeChangedCallbackForAllAttributes(Element&);
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementDefinition);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h
index 6a61667fac6..dacfce199b5 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_DEFINITION_BUILDER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_DEFINITION_BUILDER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
@@ -23,6 +22,11 @@ class CORE_EXPORT CustomElementDefinitionBuilder {
STACK_ALLOCATED();
public:
+ CustomElementDefinitionBuilder(const CustomElementDefinitionBuilder&) =
+ delete;
+ CustomElementDefinitionBuilder& operator=(
+ const CustomElementDefinitionBuilder&) = delete;
+
// This API necessarily sounds JavaScript specific; this implements
// some steps of the CustomElementRegistry.define process, which
// are defined in terms of JavaScript.
@@ -45,8 +49,6 @@ class CORE_EXPORT CustomElementDefinitionBuilder {
protected:
CustomElementDefinitionBuilder() = default;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementDefinitionBuilder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_test.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_test.cc
index 87469ef7065..6e46a078dae 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition_test.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/node.h" // CustomElementState
#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
@@ -20,10 +19,10 @@ class ConstructorFails : public TestCustomElementDefinition {
public:
ConstructorFails(const CustomElementDescriptor& descriptor)
: TestCustomElementDefinition(descriptor) {}
+ ConstructorFails(const ConstructorFails&) = delete;
+ ConstructorFails& operator=(const ConstructorFails&) = delete;
~ConstructorFails() override = default;
bool RunConstructor(Element&) override { return false; }
-
- DISALLOW_COPY_AND_ASSIGN(ConstructorFails);
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction.h
index 59c30538f23..fb7af93fc20 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -18,6 +17,8 @@ class CORE_EXPORT CustomElementReaction
: public GarbageCollected<CustomElementReaction> {
public:
CustomElementReaction(CustomElementDefinition&);
+ CustomElementReaction(const CustomElementReaction&) = delete;
+ CustomElementReaction& operator=(const CustomElementReaction&) = delete;
virtual ~CustomElementReaction() = default;
virtual void Invoke(Element&) = 0;
@@ -26,8 +27,6 @@ class CORE_EXPORT CustomElementReaction
protected:
Member<CustomElementDefinition> definition_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementReaction);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc
index 5cb60c955a3..94ba1aae435 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h"
-#include "third_party/blink/renderer/bindings/core/v8/file_or_usv_string_or_form_data.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_file_formdata_usvstring.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
@@ -17,6 +16,9 @@ class CustomElementUpgradeReaction final : public CustomElementReaction {
public:
explicit CustomElementUpgradeReaction(CustomElementDefinition& definition)
: CustomElementReaction(definition) {}
+ CustomElementUpgradeReaction(const CustomElementUpgradeReaction&) = delete;
+ CustomElementUpgradeReaction& operator=(const CustomElementUpgradeReaction&) =
+ delete;
private:
void Invoke(Element& element) override {
@@ -26,8 +28,6 @@ class CustomElementUpgradeReaction final : public CustomElementReaction {
if (element.GetCustomElementState() == CustomElementState::kUndefined)
definition_->Upgrade(element);
}
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementUpgradeReaction);
};
// ----------------------------------------------------------------
@@ -39,13 +39,15 @@ class CustomElementConnectedCallbackReaction final
: CustomElementReaction(definition) {
DCHECK(definition.HasConnectedCallback());
}
+ CustomElementConnectedCallbackReaction(
+ const CustomElementConnectedCallbackReaction&) = delete;
+ CustomElementConnectedCallbackReaction& operator=(
+ const CustomElementConnectedCallbackReaction&) = delete;
private:
void Invoke(Element& element) override {
definition_->RunConnectedCallback(element);
}
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementConnectedCallbackReaction);
};
// ----------------------------------------------------------------
@@ -57,13 +59,15 @@ class CustomElementDisconnectedCallbackReaction final
: CustomElementReaction(definition) {
DCHECK(definition.HasDisconnectedCallback());
}
+ CustomElementDisconnectedCallbackReaction(
+ const CustomElementDisconnectedCallbackReaction&) = delete;
+ CustomElementDisconnectedCallbackReaction& operator=(
+ const CustomElementDisconnectedCallbackReaction&) = delete;
private:
void Invoke(Element& element) override {
definition_->RunDisconnectedCallback(element);
}
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementDisconnectedCallbackReaction);
};
// ----------------------------------------------------------------
@@ -80,6 +84,11 @@ class CustomElementAdoptedCallbackReaction final
DCHECK(definition.HasAdoptedCallback());
}
+ CustomElementAdoptedCallbackReaction(
+ const CustomElementAdoptedCallbackReaction&) = delete;
+ CustomElementAdoptedCallbackReaction& operator=(
+ const CustomElementAdoptedCallbackReaction&) = delete;
+
void Trace(Visitor* visitor) const override {
visitor->Trace(old_owner_);
visitor->Trace(new_owner_);
@@ -93,8 +102,6 @@ class CustomElementAdoptedCallbackReaction final
Member<Document> old_owner_;
Member<Document> new_owner_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementAdoptedCallbackReaction);
};
// ----------------------------------------------------------------
@@ -114,6 +121,11 @@ class CustomElementAttributeChangedCallbackReaction final
DCHECK(definition.HasAttributeChangedCallback(name));
}
+ CustomElementAttributeChangedCallbackReaction(
+ const CustomElementAttributeChangedCallbackReaction&) = delete;
+ CustomElementAttributeChangedCallbackReaction& operator=(
+ const CustomElementAttributeChangedCallbackReaction&) = delete;
+
private:
void Invoke(Element& element) override {
definition_->RunAttributeChangedCallback(element, name_, old_value_,
@@ -123,8 +135,6 @@ class CustomElementAttributeChangedCallbackReaction final
QualifiedName name_;
AtomicString old_value_;
AtomicString new_value_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementAttributeChangedCallbackReaction);
};
// ----------------------------------------------------------------
@@ -139,6 +149,11 @@ class CustomElementFormAssociatedCallbackReaction final
DCHECK(definition.HasFormAssociatedCallback());
}
+ CustomElementFormAssociatedCallbackReaction(
+ const CustomElementFormAssociatedCallbackReaction&) = delete;
+ CustomElementFormAssociatedCallbackReaction& operator=(
+ const CustomElementFormAssociatedCallbackReaction&) = delete;
+
void Trace(Visitor* visitor) const override {
visitor->Trace(form_);
CustomElementReaction::Trace(visitor);
@@ -150,8 +165,6 @@ class CustomElementFormAssociatedCallbackReaction final
}
Member<HTMLFormElement> form_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementFormAssociatedCallbackReaction);
};
// ----------------------------------------------------------------
@@ -164,12 +177,15 @@ class CustomElementFormResetCallbackReaction final
DCHECK(definition.HasFormResetCallback());
}
+ CustomElementFormResetCallbackReaction(
+ const CustomElementFormResetCallbackReaction&) = delete;
+ CustomElementFormResetCallbackReaction& operator=(
+ const CustomElementFormResetCallbackReaction&) = delete;
+
private:
void Invoke(Element& element) override {
definition_->RunFormResetCallback(element);
}
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementFormResetCallbackReaction);
};
// ----------------------------------------------------------------
@@ -183,19 +199,21 @@ class CustomElementFormDisabledCallbackReaction final
DCHECK(definition.HasFormDisabledCallback());
}
+ CustomElementFormDisabledCallbackReaction(
+ const CustomElementFormDisabledCallbackReaction&) = delete;
+ CustomElementFormDisabledCallbackReaction& operator=(
+ const CustomElementFormDisabledCallbackReaction&) = delete;
+
private:
void Invoke(Element& element) override {
definition_->RunFormDisabledCallback(element, is_disabled_);
}
bool is_disabled_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementFormDisabledCallbackReaction);
};
// ----------------------------------------------------------------
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
class CustomElementFormStateRestoreCallbackReaction final
: public CustomElementReaction {
public:
@@ -208,33 +226,10 @@ class CustomElementFormStateRestoreCallbackReaction final
DCHECK(mode == "restore" || mode == "autocomplete");
}
- void Trace(Visitor* visitor) const override {
- visitor->Trace(value_);
- CustomElementReaction::Trace(visitor);
- }
-
- private:
- void Invoke(Element& element) override {
- definition_->RunFormStateRestoreCallback(element, value_, mode_);
- }
-
- Member<const V8ControlValue> value_;
- String mode_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementFormStateRestoreCallbackReaction);
-};
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-class CustomElementFormStateRestoreCallbackReaction final
- : public CustomElementReaction {
- public:
CustomElementFormStateRestoreCallbackReaction(
- CustomElementDefinition& definition,
- const FileOrUSVStringOrFormData& value,
- const String& mode)
- : CustomElementReaction(definition), value_(value), mode_(mode) {
- DCHECK(definition.HasFormStateRestoreCallback());
- DCHECK(mode == "restore" || mode == "autocomplete");
- }
+ const CustomElementFormStateRestoreCallbackReaction&) = delete;
+ CustomElementFormStateRestoreCallbackReaction& operator=(
+ const CustomElementFormStateRestoreCallbackReaction&) = delete;
void Trace(Visitor* visitor) const override {
visitor->Trace(value_);
@@ -246,12 +241,9 @@ class CustomElementFormStateRestoreCallbackReaction final
definition_->RunFormStateRestoreCallback(element, value_, mode_);
}
- FileOrUSVStringOrFormData value_;
+ Member<const V8ControlValue> value_;
String mode_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementFormStateRestoreCallbackReaction);
};
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// ----------------------------------------------------------------
@@ -309,7 +301,6 @@ CustomElementReaction& CustomElementReactionFactory::CreateFormDisabled(
definition, is_disabled);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CustomElementReaction& CustomElementReactionFactory::CreateFormStateRestore(
CustomElementDefinition& definition,
const V8ControlValue* value,
@@ -317,14 +308,5 @@ CustomElementReaction& CustomElementReactionFactory::CreateFormStateRestore(
return *MakeGarbageCollected<CustomElementFormStateRestoreCallbackReaction>(
definition, value, mode);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CustomElementReaction& CustomElementReactionFactory::CreateFormStateRestore(
- CustomElementDefinition& definition,
- const FileOrUSVStringOrFormData& value,
- const String& mode) {
- return *MakeGarbageCollected<CustomElementFormStateRestoreCallbackReaction>(
- definition, value, mode);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
index 479eeb0dbe4..2b48c67cf7a 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
@@ -14,7 +14,6 @@ namespace blink {
class CustomElementDefinition;
class CustomElementReaction;
class Document;
-class FileOrUSVStringOrFormData;
class HTMLFormElement;
class QualifiedName;
@@ -45,17 +44,10 @@ class CustomElementReactionFactory {
static CustomElementReaction& CreateFormDisabled(
CustomElementDefinition& definition,
bool is_disabled);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CustomElementReaction& CreateFormStateRestore(
CustomElementDefinition& definition,
const V8ControlValue* value,
const String& mode);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CustomElementReaction& CreateFormStateRestore(
- CustomElementDefinition& definition,
- const FileOrUSVStringOrFormData& value,
- const String& mode);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h
index 383236bc063..cc3e4ef9efd 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_QUEUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_QUEUE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -18,6 +17,9 @@ class CORE_EXPORT CustomElementReactionQueue final
: public GarbageCollected<CustomElementReactionQueue> {
public:
CustomElementReactionQueue();
+ CustomElementReactionQueue(const CustomElementReactionQueue&) = delete;
+ CustomElementReactionQueue& operator=(const CustomElementReactionQueue&) =
+ delete;
~CustomElementReactionQueue();
void Trace(Visitor*) const;
@@ -30,8 +32,6 @@ class CORE_EXPORT CustomElementReactionQueue final
private:
HeapVector<Member<CustomElementReaction>, 1> reactions_;
wtf_size_t index_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementReactionQueue);
};
} // namespace blink
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 828b7c84da8..aa05b3e2a94 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
@@ -48,7 +48,8 @@ void CustomElementReactionStack::PopInvokingReactions() {
void CustomElementReactionStack::InvokeReactions(ElementQueue& queue) {
for (wtf_size_t i = 0; i < queue.size(); ++i) {
Element* element = queue[i];
- if (CustomElementReactionQueue* reactions = map_.at(element)) {
+ if (CustomElementReactionQueue* reactions =
+ map_.DeprecatedAtOrEmptyValue(element)) {
reactions->InvokeReactions(*element);
CHECK(reactions->IsEmpty());
map_.erase(element);
@@ -69,7 +70,8 @@ void CustomElementReactionStack::Enqueue(Member<ElementQueue>& queue,
queue = MakeGarbageCollected<ElementQueue>();
queue->push_back(&element);
- CustomElementReactionQueue* reactions = map_.at(&element);
+ CustomElementReactionQueue* reactions =
+ map_.DeprecatedAtOrEmptyValue(&element);
if (!reactions) {
reactions = MakeGarbageCollected<CustomElementReactionQueue>();
map_.insert(&element, reactions);
@@ -98,8 +100,10 @@ void CustomElementReactionStack::EnqueueToBackupQueue(
}
void CustomElementReactionStack::ClearQueue(Element& element) {
- if (CustomElementReactionQueue* reactions = map_.at(&element))
+ if (CustomElementReactionQueue* reactions =
+ map_.DeprecatedAtOrEmptyValue(&element)) {
reactions->Clear();
+ }
}
void CustomElementReactionStack::InvokeBackupQueue() {
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 44b6a986005..5da2b003ee6 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_STACK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_STACK_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -22,6 +21,10 @@ class CORE_EXPORT CustomElementReactionStack final
public NameClient {
public:
CustomElementReactionStack();
+ CustomElementReactionStack(const CustomElementReactionStack&) = delete;
+ CustomElementReactionStack& operator=(const CustomElementReactionStack&) =
+ delete;
+ ~CustomElementReactionStack() override = default;
void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override {
@@ -50,8 +53,6 @@ class CORE_EXPORT CustomElementReactionStack final
void InvokeBackupQueue();
void InvokeReactions(ElementQueue&);
void Enqueue(Member<ElementQueue>&, Element&, CustomElementReaction&);
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementReactionStack);
};
class CORE_EXPORT CustomElementReactionStackTestSupport final {
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack_test.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack_test.cc
index a515720ba83..cc3cc1c8078 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack_test.cc
@@ -6,7 +6,6 @@
#include <initializer_list>
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_reaction.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h"
@@ -187,6 +186,8 @@ class EnqueueToStack : public Command {
Element& element,
CustomElementReaction* reaction)
: stack_(stack), element_(element), reaction_(reaction) {}
+ EnqueueToStack(const EnqueueToStack&) = delete;
+ EnqueueToStack& operator=(const EnqueueToStack&) = delete;
~EnqueueToStack() override = default;
void Trace(Visitor* visitor) const override {
Command::Trace(visitor);
@@ -202,8 +203,6 @@ class EnqueueToStack : public Command {
Member<CustomElementReactionStack> stack_;
Member<Element> element_;
Member<CustomElementReaction> reaction_;
-
- DISALLOW_COPY_AND_ASSIGN(EnqueueToStack);
};
TEST(CustomElementReactionStackTest, enqueueFromReaction) {
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h
index a9417d1f27b..01c5c618938 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h
@@ -10,7 +10,6 @@
#include <initializer_list>
#include <memory>
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h"
@@ -25,54 +24,57 @@ class Element;
class Command : public GarbageCollected<Command> {
public:
Command() = default;
+ Command(const Command&) = delete;
+ Command& operator=(const Command&) = delete;
virtual ~Command() = default;
virtual void Trace(Visitor* visitor) const {}
virtual void Run(Element&) = 0;
- DISALLOW_COPY_AND_ASSIGN(Command);
};
class Call : public Command {
public:
using Callback = base::OnceCallback<void(Element&)>;
Call(Callback callback) : callback_(std::move(callback)) {}
+ Call(const Call&) = delete;
+ Call& operator=(const Call&) = delete;
~Call() override = default;
void Run(Element& element) override { std::move(callback_).Run(element); }
private:
Callback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(Call);
};
class Unreached : public Command {
public:
Unreached(const char* message) : message_(message) {}
+ Unreached(const Unreached&) = delete;
+ Unreached& operator=(const Unreached&) = delete;
~Unreached() override = default;
void Run(Element&) override { EXPECT_TRUE(false) << message_; }
private:
const char* message_;
-
- DISALLOW_COPY_AND_ASSIGN(Unreached);
};
class Log : public Command {
public:
Log(char what, Vector<char>& where) : what_(what), where_(where) {}
+ Log(const Log&) = delete;
+ Log& operator=(const Log&) = delete;
~Log() override = default;
void Run(Element&) override { where_.push_back(what_); }
private:
char what_;
Vector<char>& where_;
-
- DISALLOW_COPY_AND_ASSIGN(Log);
};
class Recurse : public Command {
public:
Recurse(CustomElementReactionQueue* queue) : queue_(queue) {}
+ Recurse(const Recurse&) = delete;
+ Recurse& operator=(const Recurse&) = delete;
~Recurse() override = default;
void Trace(Visitor* visitor) const override {
Command::Trace(visitor);
@@ -82,14 +84,14 @@ class Recurse : public Command {
private:
Member<CustomElementReactionQueue> queue_;
-
- DISALLOW_COPY_AND_ASSIGN(Recurse);
};
class Enqueue : public Command {
public:
Enqueue(CustomElementReactionQueue* queue, CustomElementReaction* reaction)
: queue_(queue), reaction_(reaction) {}
+ Enqueue(const Enqueue&) = delete;
+ Enqueue& operator=(const Enqueue&) = delete;
~Enqueue() override = default;
void Trace(Visitor* visitor) const override {
Command::Trace(visitor);
@@ -101,8 +103,6 @@ class Enqueue : public Command {
private:
Member<CustomElementReactionQueue> queue_;
Member<CustomElementReaction> reaction_;
-
- DISALLOW_COPY_AND_ASSIGN(Enqueue);
};
class TestReaction : public CustomElementReaction {
@@ -112,6 +112,8 @@ class TestReaction : public CustomElementReaction {
*MakeGarbageCollected<TestCustomElementDefinition>(
CustomElementDescriptor("mock-element", "mock-element"))),
commands_(std::move(commands)) {}
+ TestReaction(const TestReaction&) = delete;
+ TestReaction& operator=(const TestReaction&) = delete;
~TestReaction() override = default;
void Trace(Visitor* visitor) const override {
CustomElementReaction::Trace(visitor);
@@ -124,8 +126,6 @@ class TestReaction : public CustomElementReaction {
private:
HeapVector<Member<Command>> commands_;
-
- DISALLOW_COPY_AND_ASSIGN(TestReaction);
};
class ResetCustomElementReactionStackForTest final {
@@ -135,6 +135,10 @@ class ResetCustomElementReactionStackForTest final {
: stack_(MakeGarbageCollected<CustomElementReactionStack>()),
old_stack_(
CustomElementReactionStackTestSupport::SetCurrentForTest(stack_)) {}
+ ResetCustomElementReactionStackForTest(
+ const ResetCustomElementReactionStackForTest&) = delete;
+ ResetCustomElementReactionStackForTest& operator=(
+ const ResetCustomElementReactionStackForTest&) = delete;
~ResetCustomElementReactionStackForTest() {
CustomElementReactionStackTestSupport::SetCurrentForTest(old_stack_);
@@ -145,8 +149,6 @@ class ResetCustomElementReactionStackForTest final {
private:
CustomElementReactionStack* stack_;
CustomElementReactionStack* old_stack_;
-
- DISALLOW_COPY_AND_ASSIGN(ResetCustomElementReactionStackForTest);
};
} // namespace blink
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 29196fe5e89..68a19e9f8f5 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
@@ -259,7 +259,7 @@ bool CustomElementRegistry::NameIsDefined(const AtomicString& name) const {
CustomElementDefinition* CustomElementRegistry::DefinitionForName(
const AtomicString& name) const {
- return DefinitionForId(name_id_map_.at(name));
+ return DefinitionForId(name_id_map_.DeprecatedAtOrEmptyValue(name));
}
CustomElementDefinition* CustomElementRegistry::DefinitionForId(
@@ -298,7 +298,8 @@ ScriptPromise CustomElementRegistry::whenDefined(
CustomElementDefinition* definition = DefinitionForName(name);
if (definition)
return ScriptPromise::CastUndefined(script_state);
- ScriptPromiseResolver* resolver = when_defined_promise_map_.at(name);
+ ScriptPromiseResolver* resolver =
+ when_defined_promise_map_.DeprecatedAtOrEmptyValue(name);
if (resolver)
return resolver->Promise();
auto* new_resolver =
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 9f268126991..f051bfc06ff 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REGISTRY_H_
#include "base/gtest_prod_util.h"
-#include "base/macros.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/html/custom/custom_element_definition.h"
@@ -34,6 +33,8 @@ class CORE_EXPORT CustomElementRegistry final : public ScriptWrappable {
public:
CustomElementRegistry(const LocalDOMWindow*);
+ CustomElementRegistry(const CustomElementRegistry&) = delete;
+ CustomElementRegistry& operator=(const CustomElementRegistry&) = delete;
~CustomElementRegistry() override = default;
CustomElementDefinition* define(ScriptState*,
@@ -96,8 +97,6 @@ class CORE_EXPORT CustomElementRegistry final : public ScriptWrappable {
CustomElementTest,
CreateElement_TagNameCaseHandlingCreatingCustomElement);
friend class CustomElementRegistryTest;
-
- DISALLOW_COPY_AND_ASSIGN(CustomElementRegistry);
};
} // namespace blink
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 b927a750fd3..108829b3b49 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
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/web/web_custom_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -173,6 +172,8 @@ class LogUpgradeDefinition : public TestCustomElementDefinition {
"attr1", "attr2", html_names::kContenteditableAttr.LocalName(),
},
{}) {}
+ LogUpgradeDefinition(const LogUpgradeDefinition&) = delete;
+ LogUpgradeDefinition& operator=(const LogUpgradeDefinition&) = delete;
void Trace(Visitor* visitor) const override {
TestCustomElementDefinition::Trace(visitor);
@@ -254,8 +255,6 @@ class LogUpgradeDefinition : public TestCustomElementDefinition {
EXPECT_EQ(&element, element_);
attribute_changed_.push_back(AttributeChanged{name, old_value, new_value});
}
-
- DISALLOW_COPY_AND_ASSIGN(LogUpgradeDefinition);
};
class LogUpgradeBuilder final : public TestCustomElementDefinitionBuilder {
@@ -263,13 +262,13 @@ class LogUpgradeBuilder final : public TestCustomElementDefinitionBuilder {
public:
LogUpgradeBuilder() = default;
+ LogUpgradeBuilder(const LogUpgradeBuilder&) = delete;
+ LogUpgradeBuilder& operator=(const LogUpgradeBuilder&) = delete;
CustomElementDefinition* Build(const CustomElementDescriptor& descriptor,
CustomElementDefinition::Id) override {
return MakeGarbageCollected<LogUpgradeDefinition>(descriptor);
}
-
- DISALLOW_COPY_AND_ASSIGN(LogUpgradeBuilder);
};
TEST_F(CustomElementRegistryTest, define_upgradesInDocumentElements) {
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 423c9fe499e..c5da95311d5 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
@@ -5,7 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_TEST_HELPERS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_TEST_HELPERS_H_
-#include "base/macros.h"
+#include <utility>
+
#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/qualified_name.h"
@@ -18,8 +19,6 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include <utility>
-
namespace blink {
class CustomElementDescriptor;
@@ -30,16 +29,16 @@ class TestCustomElementDefinitionBuilder
public:
TestCustomElementDefinitionBuilder() = default;
+ TestCustomElementDefinitionBuilder(
+ const TestCustomElementDefinitionBuilder&) = delete;
+ TestCustomElementDefinitionBuilder& operator=(
+ const TestCustomElementDefinitionBuilder&) = delete;
bool CheckConstructorIntrinsics() override { return true; }
bool CheckConstructorNotRegistered() override { return true; }
bool RememberOriginalProperties() override { return true; }
CustomElementDefinition* Build(const CustomElementDescriptor&,
CustomElementDefinition::Id) override;
-
- private:
-
- DISALLOW_COPY_AND_ASSIGN(TestCustomElementDefinitionBuilder);
};
class TestCustomElementDefinition : public CustomElementDefinition {
@@ -55,6 +54,10 @@ class TestCustomElementDefinition : public CustomElementDefinition {
disabled_features,
FormAssociationFlag::kNo) {}
+ TestCustomElementDefinition(const TestCustomElementDefinition&) = delete;
+ TestCustomElementDefinition& operator=(const TestCustomElementDefinition&) =
+ delete;
+
~TestCustomElementDefinition() override = default;
ScriptValue GetConstructorForScript() override { return ScriptValue(); }
@@ -114,21 +117,11 @@ class TestCustomElementDefinition : public CustomElementDefinition {
NOTREACHED() << "definition does not have disabledStateChangedCallback";
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void RunFormStateRestoreCallback(Element& element,
const V8ControlValue* value,
const String& mode) override {
NOTREACHED() << "definition does not have restoreValueCallback";
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void RunFormStateRestoreCallback(Element& element,
- const FileOrUSVStringOrFormData& value,
- const String& mode) override {
- NOTREACHED() << "definition does not have restoreValueCallback";
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- DISALLOW_COPY_AND_ASSIGN(TestCustomElementDefinition);
};
class CreateElement {
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 b3c9ba9be14..468e20a862c 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
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_element_creation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -27,13 +26,8 @@ class CustomElementUpgradeSorterTest : public PageTestBase {
Element* CreateElementWithId(const char* local_name, const char* id) {
NonThrowableExceptionState no_exceptions;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Element* element = GetDocument().CreateElementForBinding(
local_name, nullptr, no_exceptions);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Element* element = GetDocument().CreateElementForBinding(
- local_name, StringOrElementCreationOptions(), no_exceptions);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
element->setAttribute(html_names::kIdAttr, id);
return element;
}
@@ -45,13 +39,8 @@ class CustomElementUpgradeSorterTest : public PageTestBase {
TEST_F(CustomElementUpgradeSorterTest, inOtherDocument_notInSet) {
NonThrowableExceptionState no_exceptions;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Element* element =
GetDocument().CreateElementForBinding("a-a", nullptr, no_exceptions);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Element* element = GetDocument().CreateElementForBinding(
- "a-a", StringOrElementCreationOptions(), no_exceptions);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* other_document = HTMLDocument::CreateForTest();
other_document->AppendChild(element);
@@ -69,13 +58,8 @@ TEST_F(CustomElementUpgradeSorterTest, inOtherDocument_notInSet) {
TEST_F(CustomElementUpgradeSorterTest, oneCandidate) {
NonThrowableExceptionState no_exceptions;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Element* element =
GetDocument().CreateElementForBinding("a-a", nullptr, no_exceptions);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Element* element = GetDocument().CreateElementForBinding(
- "a-a", StringOrElementCreationOptions(), no_exceptions);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
GetDocument().documentElement()->AppendChild(element);
CustomElementUpgradeSorter sorter;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc b/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc
index 4c00ccf7c32..1add646c653 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc
@@ -21,6 +21,7 @@
namespace blink {
namespace {
+
bool IsValidityStateFlagsValid(const ValidityStateFlags* flags) {
if (!flags)
return true;
@@ -31,7 +32,8 @@ bool IsValidityStateFlagsValid(const ValidityStateFlags* flags) {
return false;
return true;
}
-} // anonymous namespace
+
+} // namespace
ElementInternals::ElementInternals(HTMLElement& target) : target_(target) {
}
@@ -48,8 +50,6 @@ void ElementInternals::Trace(Visitor* visitor) const {
ScriptWrappable::Trace(visitor);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void ElementInternals::setFormValue(const V8ControlValue* value,
ExceptionState& exception_state) {
setFormValue(value, value, exception_state);
@@ -83,43 +83,6 @@ void ElementInternals::setFormValue(const V8ControlValue* value,
NotifyFormStateChanged();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void ElementInternals::setFormValue(const ControlValue& value,
- ExceptionState& exception_state) {
- setFormValue(value, value, exception_state);
-}
-
-void ElementInternals::setFormValue(const ControlValue& value,
- const ControlValue& state,
- ExceptionState& exception_state) {
- if (!IsTargetFormAssociated()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "The target element is not a form-associated custom element.");
- return;
- }
-
- if (value.IsFormData()) {
- value_ = ControlValue::FromFormData(
- MakeGarbageCollected<FormData>(*value.GetAsFormData()));
- } else {
- value_ = value;
- }
-
- if (&value == &state) {
- state_ = value_;
- } else if (state.IsFormData()) {
- state_ = ControlValue::FromFormData(
- MakeGarbageCollected<FormData>(*state.GetAsFormData()));
- } else {
- state_ = state;
- }
- NotifyFormStateChanged();
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
HTMLFormElement* ElementInternals::form(ExceptionState& exception_state) const {
if (!IsTargetFormAssociated()) {
exception_state.ThrowDOMException(
@@ -273,7 +236,7 @@ ShadowRoot* ElementInternals::shadowRoot() const {
const AtomicString& ElementInternals::FastGetAttribute(
const QualifiedName& attribute) const {
- return accessibility_semantics_map_.at(attribute);
+ return accessibility_semantics_map_.DeprecatedAtOrEmptyValue(attribute);
}
const HashMap<QualifiedName, AtomicString>& ElementInternals::GetAttributes()
@@ -333,11 +296,11 @@ Element* ElementInternals::GetElementAttribute(const QualifiedName& name) {
return *(stored_elements->begin());
}
-absl::optional<HeapVector<Member<Element>>>
-ElementInternals::GetElementArrayAttribute(const QualifiedName& name) const {
+HeapVector<Member<Element>>* ElementInternals::GetElementArrayAttribute(
+ const QualifiedName& name) const {
const auto& iter = explicitly_set_attr_elements_map_.find(name);
if (iter == explicitly_set_attr_elements_map_.end()) {
- return absl::nullopt;
+ return nullptr;
}
// Convert from our internal HeapLinkedHashSet of weak references to a
@@ -352,12 +315,12 @@ ElementInternals::GetElementArrayAttribute(const QualifiedName& name) const {
results->push_back(item);
}
- return *results;
+ return results;
}
void ElementInternals::SetElementArrayAttribute(
const QualifiedName& name,
- const absl::optional<HeapVector<Member<Element>>>& given_elements) {
+ const HeapVector<Member<Element>>* given_elements) {
if (!given_elements) {
explicitly_set_attr_elements_map_.erase(name);
return;
@@ -374,7 +337,7 @@ void ElementInternals::SetElementArrayAttribute(
stored_elements.stored_value->value->clear();
}
- for (auto element : given_elements.value()) {
+ for (auto element : *given_elements) {
stored_elements.stored_value->value->insert(element);
}
}
@@ -413,7 +376,6 @@ bool ElementInternals::IsEnumeratable() const {
return true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void ElementInternals::AppendToFormData(FormData& form_data) {
if (Target().IsDisabledFormControl())
return;
@@ -445,29 +407,6 @@ void ElementInternals::AppendToFormData(FormData& form_data) {
}
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ElementInternals::AppendToFormData(FormData& form_data) {
- if (Target().IsDisabledFormControl())
- return;
- const AtomicString& name = Target().FastGetAttribute(html_names::kNameAttr);
- if (!value_.IsFormData()) {
- if (name.IsEmpty())
- return;
- if (value_.IsFile())
- form_data.AppendFromElement(name, value_.GetAsFile());
- else if (value_.IsUSVString())
- form_data.AppendFromElement(name, value_.GetAsUSVString());
- // Append nothing for null value.
- return;
- }
- for (const auto& entry : value_.GetAsFormData()->Entries()) {
- if (entry->isFile())
- form_data.append(entry->name(), entry->GetFile());
- else
- form_data.append(entry->name(), entry->Value());
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void ElementInternals::DidChangeForm() {
ListedElement::DidChangeForm();
@@ -531,7 +470,6 @@ bool ElementInternals::ShouldSaveAndRestoreFormControlState() const {
return Target().isConnected() && (!Form() || Form()->ShouldAutocomplete());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FormControlState ElementInternals::SaveFormControlState() const {
FormControlState state;
@@ -557,26 +495,7 @@ FormControlState ElementInternals::SaveFormControlState() const {
}
return state;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-FormControlState ElementInternals::SaveFormControlState() const {
- FormControlState state;
- if (value_.IsUSVString()) {
- state.Append("USVString");
- state.Append(value_.GetAsUSVString());
- } else if (value_.IsFile()) {
- state.Append("File");
- File* file = value_.GetAsFile();
- file->AppendToControlState(state);
- } else if (value_.IsFormData()) {
- state.Append("FormData");
- value_.GetAsFormData()->AppendToControlState(state);
- }
- // Add nothing if value_.IsNull().
- return state;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void ElementInternals::RestoreFormControlState(const FormControlState& state) {
if (state.ValueSize() < 2)
return;
@@ -594,24 +513,5 @@ void ElementInternals::RestoreFormControlState(const FormControlState& state) {
if (value_)
CustomElement::EnqueueFormStateRestoreCallback(Target(), value_, "restore");
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ElementInternals::RestoreFormControlState(const FormControlState& state) {
- if (state.ValueSize() < 2)
- return;
- if (state[0] == "USVString") {
- value_ = ControlValue::FromUSVString(state[1]);
- } else if (state[0] == "File") {
- wtf_size_t i = 1;
- if (auto* file = File::CreateFromControlState(state, i))
- value_ = ControlValue::FromFile(file);
- } else if (state[0] == "FormData") {
- wtf_size_t i = 1;
- if (auto* form_data = FormData::CreateFromControlState(state, i))
- value_ = ControlValue::FromFormData(form_data);
- }
- if (!value_.IsNull())
- CustomElement::EnqueueFormStateRestoreCallback(Target(), value_, "restore");
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/element_internals.h b/chromium/third_party/blink/renderer/core/html/custom/element_internals.h
index f114ba1f0b2..7bf844896b0 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/element_internals.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/element_internals.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_ELEMENT_INTERNALS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_ELEMENT_INTERNALS_H_
-#include "third_party/blink/renderer/bindings/core/v8/file_or_usv_string_or_form_data.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/html/forms/labels_node_list.h"
@@ -26,25 +25,18 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
public:
ElementInternals(HTMLElement& target);
+ ElementInternals(const ElementInternals&) = delete;
+ ElementInternals& operator=(const ElementInternals&) = delete;
void Trace(Visitor* visitor) const override;
HTMLElement& Target() const { return *target_; }
void DidUpgrade();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setFormValue(const V8ControlValue* value,
ExceptionState& exception_state);
void setFormValue(const V8ControlValue* value,
const V8ControlValue* state,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- using ControlValue = FileOrUSVStringOrFormData;
- // IDL attributes/operations
- void setFormValue(const ControlValue& value, ExceptionState& exception_state);
- void setFormValue(const ControlValue& value,
- const ControlValue& state,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HTMLFormElement* form(ExceptionState& exception_state) const;
void setValidity(ValidityStateFlags* flags, ExceptionState& exception_state);
void setValidity(ValidityStateFlags* flags,
@@ -73,11 +65,10 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
void SetElementAttribute(const QualifiedName& name, Element* element);
Element* GetElementAttribute(const QualifiedName& name);
- absl::optional<HeapVector<Member<Element>>> GetElementArrayAttribute(
+ HeapVector<Member<Element>>* GetElementArrayAttribute(
const QualifiedName& name) const;
- void SetElementArrayAttribute(
- const QualifiedName& name,
- const absl::optional<HeapVector<Member<Element>>>& elements);
+ void SetElementArrayAttribute(const QualifiedName& name,
+ const HeapVector<Member<Element>>* elements);
bool HasAttribute(const QualifiedName& attribute) const;
const HashMap<QualifiedName, AtomicString>& GetAttributes() const;
@@ -111,13 +102,8 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
Member<HTMLElement> target_;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<const V8ControlValue> value_;
Member<const V8ControlValue> state_;
-#else
- ControlValue value_;
- ControlValue state_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool is_disabled_ = false;
Member<ValidityStateFlags> validity_flags_;
Member<Element> validation_anchor_;
@@ -130,8 +116,6 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
// https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:element
HeapHashMap<QualifiedName, Member<HeapLinkedHashSet<WeakMember<Element>>>>
explicitly_set_attr_elements_map_;
-
- DISALLOW_COPY_AND_ASSIGN(ElementInternals);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/OWNERS b/chromium/third_party/blink/renderer/core/html/fenced_frame/OWNERS
new file mode 100644
index 00000000000..f63b6eecdde
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/OWNERS
@@ -0,0 +1,2 @@
+dom@chromium.org
+shivanisha@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc
new file mode 100644
index 00000000000..4070f1eba25
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h"
+
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/frame/remote_frame.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+FencedFrameMPArchDelegate::FencedFrameMPArchDelegate(
+ HTMLFencedFrameElement* outer_element)
+ : HTMLFencedFrameElement::FencedFrameDelegate(outer_element) {
+ DCHECK_EQ(features::kFencedFramesImplementationTypeParam.Get(),
+ features::FencedFramesImplementationType::kMPArch);
+}
+
+void FencedFrameMPArchDelegate::DidGetInserted() {
+ RemoteFrame* remote_frame =
+ GetElement().GetDocument().GetFrame()->Client()->CreateFencedFrame(
+ &GetElement());
+ DCHECK_EQ(remote_frame, GetElement().ContentFrame());
+}
+
+void FencedFrameMPArchDelegate::Navigate(const KURL& url) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h
new file mode 100644
index 00000000000..210a74e9dec
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FENCED_FRAME_FENCED_FRAME_MPARCH_DELEGATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FENCED_FRAME_FENCED_FRAME_MPARCH_DELEGATE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h"
+
+namespace blink {
+
+class KURL;
+
+// This is one of the underlying implementations of the `HTMLFencedFrameElement`
+// interface. It can be activated by enabling the
+// `blink::features::kFencedFrames` feature, and setting its feature param value
+// to `FencedFramesImplementationType::kMPArch`. See the documentation above
+// `FencedFrameDelegate`.
+class CORE_EXPORT FencedFrameMPArchDelegate
+ : public HTMLFencedFrameElement::FencedFrameDelegate {
+ public:
+ explicit FencedFrameMPArchDelegate(HTMLFencedFrameElement* outer_element);
+
+ void DidGetInserted() override;
+ void Navigate(const KURL&) override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FENCED_FRAME_FENCED_FRAME_MPARCH_DELEGATE_H_
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate.h b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate.h
index 64a06123445..a1729e80464 100644
--- a/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate.h
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate.h
@@ -12,6 +12,11 @@ namespace blink {
class KURL;
+// This is one of the underlying implementations of the `HTMLFencedFrameElement`
+// interface. It can be activated by enabling the
+// `blink::features::kFencedFrames` feature, and setting its feature param value
+// to `FencedFramesImplementationType::kShadowDOM`. See the documentation above
+// `FencedFrameDelegate`.
class CORE_EXPORT FencedFrameShadowDOMDelegate
: public HTMLFencedFrameElement::FencedFrameDelegate {
public:
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate_test.cc b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate_test.cc
index 3e8afd807cb..b6500d183ab 100644
--- a/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate_test.cc
@@ -68,6 +68,7 @@ TEST_F(FencedFrameShadowDOMDelegateTest, CreateRaw) {
EXPECT_NE(nullptr, fenced_frame->UserAgentShadowRoot());
EXPECT_EQ("<iframe></iframe>",
fenced_frame->UserAgentShadowRoot()->innerHTML());
+ EXPECT_TRUE(ShadowIFrame().GetFramePolicy().is_fenced);
}
TEST_F(FencedFrameShadowDOMDelegateTest, CreateViasetInnerHTML) {
@@ -77,6 +78,7 @@ TEST_F(FencedFrameShadowDOMDelegateTest, CreateViasetInnerHTML) {
EXPECT_NE(nullptr, fenced_frame.UserAgentShadowRoot());
EXPECT_EQ("<iframe></iframe>",
fenced_frame.UserAgentShadowRoot()->innerHTML());
+ EXPECT_TRUE(ShadowIFrame().GetFramePolicy().is_fenced);
}
TEST_F(FencedFrameShadowDOMDelegateTest, AppendRemoveAppend) {
@@ -121,6 +123,7 @@ TEST_F(FencedFrameShadowDOMDelegateTest, NavigationWithInsertionAndRemoval) {
fenced_frame->setAttribute(html_names::kSrcAttr, "https://example-2.com");
EXPECT_EQ("<iframe src=\"https://example-2.com/\"></iframe>",
fenced_frame->UserAgentShadowRoot()->innerHTML());
+ EXPECT_TRUE(ShadowIFrame().GetFramePolicy().is_fenced);
// Removal does not remove the internal iframe, or change its `src`.
GetDocument().body()->RemoveChild(fenced_frame);
@@ -139,6 +142,7 @@ TEST_F(FencedFrameShadowDOMDelegateTest, NavigationWithInsertionAndRemoval) {
AssertInternalIFrameExists(fenced_frame);
EXPECT_EQ("<iframe src=\"https://example-3.com/\"></iframe>",
fenced_frame->UserAgentShadowRoot()->innerHTML());
+ EXPECT_TRUE(ShadowIFrame().GetFramePolicy().is_fenced);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc b/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
index 9dd23c81c04..520d42c6ce7 100644
--- a/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
@@ -8,8 +8,10 @@
#include "third_party/blink/public/mojom/web_feature/web_feature.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/html/fenced_frame/fenced_frame_mparch_delegate.h"
#include "third_party/blink/renderer/core/html/fenced_frame/fenced_frame_shadow_dom_delegate.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/layout_iframe.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -17,7 +19,7 @@
namespace blink {
HTMLFencedFrameElement::HTMLFencedFrameElement(Document& document)
- : HTMLElement(html_names::kFencedframeTag, document),
+ : HTMLFrameOwnerElement(html_names::kFencedframeTag, document),
frame_delegate_(FencedFrameDelegate::Create(this)) {
DCHECK(RuntimeEnabledFeatures::FencedFramesEnabled(GetExecutionContext()));
UseCounter::Count(document, WebFeature::kHTMLFencedFrameElement);
@@ -26,7 +28,7 @@ HTMLFencedFrameElement::HTMLFencedFrameElement(Document& document)
HTMLFencedFrameElement::~HTMLFencedFrameElement() = default;
void HTMLFencedFrameElement::Trace(Visitor* visitor) const {
- HTMLElement::Trace(visitor);
+ HTMLFrameOwnerElement::Trace(visitor);
visitor->Trace(frame_delegate_);
}
@@ -42,16 +44,7 @@ HTMLFencedFrameElement::FencedFrameDelegate::Create(
return MakeGarbageCollected<FencedFrameShadowDOMDelegate>(outer_element);
}
- // TODO(domfarolino): Once we land testable parts of the MPArch
- // implementation, remove this and return the correct delegate. Note that this
- // should be a NOTREACHED(), but for extra consistency we need to trip this on
- // non-debug builds as well, since it is technically possible to hit this code
- // path in a production build with the kFencedFrames feature enabled, and the
- // param set to kMPArch.
- CHECK(false) << "The MPArch path for fenced frames is currently not "
- "implemented, please do not use the kMPArch feature "
- "parameter as it is not supported at this time.";
- return nullptr;
+ return MakeGarbageCollected<FencedFrameMPArchDelegate>(outer_element);
}
HTMLFencedFrameElement::FencedFrameDelegate::~FencedFrameDelegate() = default;
@@ -65,7 +58,7 @@ void HTMLFencedFrameElement::FencedFrameDelegate::Trace(
Node::InsertionNotificationRequest HTMLFencedFrameElement::InsertedInto(
ContainerNode& insertion_point) {
- HTMLElement::InsertedInto(insertion_point);
+ HTMLFrameOwnerElement::InsertedInto(insertion_point);
return kInsertionShouldCallDidNotifySubtreeInsertions;
}
@@ -74,12 +67,18 @@ void HTMLFencedFrameElement::DidNotifySubtreeInsertionsToDocument() {
Navigate();
}
+void HTMLFencedFrameElement::RemovedFrom(ContainerNode& node) {
+ // We should verify that the underlying frame has already been disconnected.
+ DCHECK_EQ(ContentFrame(), nullptr);
+ HTMLFrameOwnerElement::RemovedFrom(node);
+}
+
void HTMLFencedFrameElement::ParseAttribute(
const AttributeModificationParams& params) {
if (params.name == html_names::kSrcAttr) {
Navigate();
} else {
- HTMLElement::ParseAttribute(params);
+ HTMLFrameOwnerElement::ParseAttribute(params);
}
}
@@ -97,4 +96,26 @@ void HTMLFencedFrameElement::Navigate() {
frame_delegate_->Navigate(url);
}
+void HTMLFencedFrameElement::AttachLayoutTree(AttachContext& context) {
+ HTMLFrameOwnerElement::AttachLayoutTree(context);
+
+ if (features::kFencedFramesImplementationTypeParam.Get() ==
+ features::FencedFramesImplementationType::kMPArch) {
+ if (GetLayoutEmbeddedContent() && ContentFrame()) {
+ SetEmbeddedContentView(ContentFrame()->View());
+ }
+ }
+}
+
+LayoutObject* HTMLFencedFrameElement::CreateLayoutObject(
+ const ComputedStyle& style,
+ LegacyLayout legacy_layout) {
+ if (features::kFencedFramesImplementationTypeParam.Get() ==
+ features::FencedFramesImplementationType::kMPArch) {
+ return new LayoutIFrame(this);
+ }
+
+ return HTMLFrameOwnerElement::CreateLayoutObject(style, legacy_layout);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h b/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
index fc305b21bd8..d4c8aeab399 100644
--- a/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
+++ b/chromium/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/core_export.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/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -21,7 +21,7 @@ class KURL;
// not exposed by default, but can be enabled by one of the following:
// - Enabling the Fenced Frames about:flags entry
// - Passing --enable-features=FencedFrames
-class CORE_EXPORT HTMLFencedFrameElement : public HTMLElement {
+class CORE_EXPORT HTMLFencedFrameElement : public HTMLFrameOwnerElement {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -33,7 +33,8 @@ class CORE_EXPORT HTMLFencedFrameElement : public HTMLElement {
// For as long as both of these implementations need to exist, we abstract a
// common API from them which is neatly captured by `FencedFrameDelegate`. The
// actual implementation of this interface will be one of the options listed
- // above.
+ // above. See documentation above `FencedFrameMPArchDelegate` and
+ // `FencedFrameShadowDOMDelegate`.
class CORE_EXPORT FencedFrameDelegate
: public GarbageCollected<FencedFrameDelegate> {
public:
@@ -57,6 +58,15 @@ class CORE_EXPORT HTMLFencedFrameElement : public HTMLElement {
~HTMLFencedFrameElement() override;
void Trace(Visitor* visitor) const override;
+ // HTMLFrameOwnerElement overrides.
+ mojom::blink::FrameOwnerElementType OwnerType() const override {
+ return mojom::blink::FrameOwnerElementType::kFencedframe;
+ }
+ ParsedPermissionsPolicy ConstructContainerPolicy() const override {
+ NOTREACHED();
+ return ParsedPermissionsPolicy();
+ }
+
// HTMLElement overrides.
bool IsHTMLFencedFrameElement() const final { return true; }
@@ -68,10 +78,13 @@ class CORE_EXPORT HTMLFencedFrameElement : public HTMLElement {
// Node overrides.
Node::InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void DidNotifySubtreeInsertionsToDocument() override;
+ void RemovedFrom(ContainerNode& node) override;
// Element overrides.
void ParseAttribute(const AttributeModificationParams&) override;
bool IsURLAttribute(const Attribute&) const override;
+ LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
+ void AttachLayoutTree(AttachContext& context) override;
// The underlying <fencedframe> implementation that we delegate all of the
// important bits to. See the comment above this class declaration.
@@ -95,6 +108,11 @@ struct DowncastTraits<HTMLFencedFrameElement> {
return html_element->IsHTMLFencedFrameElement();
return false;
}
+ static bool AllowFrom(const Element& element) {
+ if (const HTMLElement* html_element = DynamicTo<HTMLElement>(element))
+ return html_element->IsHTMLFencedFrameElement();
+ return false;
+ }
};
} // namespace blink
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 022b2504465..638b0d3aea7 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
@@ -69,7 +69,7 @@ class BaseTemporalInputType : public InputType {
bool has_hour,
bool has_minute,
bool has_second) const = 0;
- virtual String AriaRoleForPickerIndicator() const = 0;
+ virtual String AriaLabelForPickerIndicator() const = 0;
protected:
BaseTemporalInputType(HTMLInputElement& element) : InputType(element) {}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.cc b/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.cc
index 61f4faf8d04..f2813d49830 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.cc
@@ -29,15 +29,6 @@ Vector<char> ChooserResourceLoader::GetSuggestionPickerJS() {
#endif
}
-Vector<char> ChooserResourceLoader::GetPickerButtonStyleSheet() {
-#if !defined(OS_ANDROID)
- return UncompressResourceAsBinary(IDR_PICKER_BUTTON_CSS);
-#else
- NOTREACHED();
- return Vector<char>();
-#endif
-}
-
Vector<char> ChooserResourceLoader::GetPickerCommonStyleSheet() {
#if !defined(OS_ANDROID)
return UncompressResourceAsBinary(IDR_PICKER_COMMON_CSS);
@@ -137,15 +128,6 @@ Vector<char> ChooserResourceLoader::GetColorPickerStyleSheet() {
#endif
}
-Vector<char> ChooserResourceLoader::GetCalendarPickerRefreshStyleSheet() {
-#if !defined(OS_ANDROID)
- return UncompressResourceAsBinary(IDR_CALENDAR_PICKER_REFRESH_CSS);
-#else
- NOTREACHED();
- return Vector<char>();
-#endif
-}
-
Vector<char> ChooserResourceLoader::GetColorPickerJS() {
#if !defined(OS_ANDROID)
return UncompressResourceAsBinary(IDR_COLOR_PICKER_JS);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.h b/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.h
index b61aec6ea36..9ebcee719fe 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.h
@@ -20,9 +20,6 @@ class ChooserResourceLoader {
// Returns the picker common javascript as a string.
static Vector<char> GetPickerCommonJS();
- // Returns the picker button stylesheet as a string.
- static Vector<char> GetPickerButtonStyleSheet();
-
// Returns the suggestion picker stylesheet as a string.
static Vector<char> GetSuggestionPickerStyleSheet();
@@ -32,9 +29,6 @@ class ChooserResourceLoader {
// Returns the suggestion picker stylesheet as a string.
static Vector<char> GetCalendarPickerStyleSheet();
- // Returns the calendar picker refresh stylesheet as a string.
- static Vector<char> GetCalendarPickerRefreshStyleSheet();
-
// Returns the suggestion picker javascript as a string.
static Vector<char> GetCalendarPickerJS();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
index b6b50c9e9bf..47101ea38c7 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
@@ -44,7 +44,6 @@ namespace blink {
// Keep in sync with Actions in colorSuggestionPicker.js.
enum ColorPickerPopupAction {
- kColorPickerPopupActionChooseOtherColor = -2,
kColorPickerPopupActionCancel = -1,
kColorPickerPopupActionSetValue = 0
};
@@ -70,11 +69,7 @@ void ColorChooserPopupUIController::Trace(Visitor* visitor) const {
}
void ColorChooserPopupUIController::OpenUI() {
- if (client_->ShouldShowSuggestions() ||
- features::IsFormControlsRefreshEnabled())
- OpenPopup();
- else
- OpenColorChooser();
+ OpenPopup();
}
void ColorChooserPopupUIController::EndChooser() {
@@ -96,8 +91,6 @@ void ColorChooserPopupUIController::WriteDocument(SharedBuffer* data) {
void ColorChooserPopupUIController::WriteColorPickerDocument(
SharedBuffer* data) {
- DCHECK(features::IsFormControlsRefreshEnabled());
-
IntRect anchor_rect_in_screen = chrome_client_->ViewportToScreen(
client_->ElementRectRelativeToViewport(), frame_->View());
@@ -119,8 +112,7 @@ void ColorChooserPopupUIController::WriteColorPickerDocument(
AddProperty("shouldShowColorSuggestionPicker", false, data);
AddProperty("isEyeDropperEnabled", features::IsEyeDropperEnabled(), data);
#if defined(OS_MAC)
- AddProperty("isBorderTransparent", features::IsFormControlsRefreshEnabled(),
- data);
+ AddProperty("isBorderTransparent", true, data);
#endif
// We don't create PagePopups on Android, so these strings are excluded
// from blink_strings.grd on Android to save binary size. We have to
@@ -169,8 +161,7 @@ void ColorChooserPopupUIController::WriteColorSuggestionPickerDocument(
data);
data->Append(ChooserResourceLoader::GetPickerCommonStyleSheet());
data->Append(ChooserResourceLoader::GetColorSuggestionPickerStyleSheet());
- if (features::IsFormControlsRefreshEnabled())
- data->Append(ChooserResourceLoader::GetColorPickerStyleSheet());
+ data->Append(ChooserResourceLoader::GetColorPickerStyleSheet());
PagePopupClient::AddString(
"</style></head><body>\n"
"<div id='main'>Loading...</div><script>\n"
@@ -179,25 +170,19 @@ void ColorChooserPopupUIController::WriteColorSuggestionPickerDocument(
PagePopupClient::AddProperty("values", suggestion_values, data);
PagePopupClient::AddLocalizedProperty("otherColorLabel",
IDS_FORM_OTHER_COLOR_LABEL, data);
- if (features::IsFormControlsRefreshEnabled()) {
- PagePopupClient::AddProperty("selectedColor",
- client_->CurrentColor().Serialized(), data);
- }
+ PagePopupClient::AddProperty("selectedColor",
+ client_->CurrentColor().Serialized(), data);
AddProperty("anchorRectInScreen", anchor_rect_in_screen, data);
AddProperty("zoomFactor", ScaledZoomFactor(), data);
AddProperty("shouldShowColorSuggestionPicker", true, data);
- AddProperty("isFormControlsRefreshEnabled",
- features::IsFormControlsRefreshEnabled(), data);
AddProperty("isEyeDropperEnabled", features::IsEyeDropperEnabled(), data);
#if defined(OS_MAC)
- AddProperty("isBorderTransparent", features::IsFormControlsRefreshEnabled(),
- data);
+ AddProperty("isBorderTransparent", true, data);
#endif
PagePopupClient::AddString("};\n", data);
data->Append(ChooserResourceLoader::GetPickerCommonJS());
data->Append(ChooserResourceLoader::GetColorSuggestionPickerJS());
- if (features::IsFormControlsRefreshEnabled())
- data->Append(ChooserResourceLoader::GetColorPickerJS());
+ data->Append(ChooserResourceLoader::GetColorPickerJS());
data->Append(ChooserResourceLoader::GetColorPickerCommonJS());
PagePopupClient::AddString("</script></body>\n", data);
}
@@ -213,10 +198,6 @@ void ColorChooserPopupUIController::SetValueAndClosePopup(
DCHECK(client_);
if (num_value == kColorPickerPopupActionSetValue)
SetValue(string_value);
- if (num_value == kColorPickerPopupActionChooseOtherColor) {
- DCHECK(!features::IsFormControlsRefreshEnabled());
- OpenColorChooser();
- }
CancelPopup();
}
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 e94e4ff79df..e779fe1cc98 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
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h"
+#include "build/build_config.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -52,7 +53,11 @@ void ColorChooserUIController::Trace(Visitor* visitor) const {
}
void ColorChooserUIController::OpenUI() {
+#if defined(OS_ANDROID)
OpenColorChooser();
+#else
+ NOTREACHED() << "ColorChooserUIController should only be used on Android";
+#endif
}
void ColorChooserUIController::SetSelectedColor(const Color& color) {
@@ -74,6 +79,7 @@ void ColorChooserUIController::DidChooseColor(uint32_t color) {
client_->DidChooseColor(color);
}
+#if defined(OS_ANDROID)
void ColorChooserUIController::OpenColorChooser() {
DCHECK(!chooser_);
frame_->GetBrowserInterfaceBroker().GetInterface(
@@ -87,5 +93,6 @@ void ColorChooserUIController::OpenColorChooser() {
receiver_.set_disconnect_handler(WTF::Bind(
&ColorChooserUIController::EndChooser, WrapWeakPersistent(this)));
}
+#endif
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h
index 0ba2bcb5466..c1b34bb3e30 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_COLOR_CHOOSER_UI_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_COLOR_CHOOSER_UI_CONTROLLER_H_
+#include "build/build_config.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/choosers/color_chooser.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -62,7 +63,9 @@ class CORE_EXPORT ColorChooserUIController
void DidChooseColor(uint32_t color) final;
protected:
+#if defined(OS_ANDROID)
void OpenColorChooser();
+#endif
mojo::Remote<mojom::blink::ColorChooser> chooser_;
Member<blink::ColorChooserClient> client_;
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 4acb2d8106d..300cfff1ac9 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
@@ -160,8 +160,7 @@ void ColorInputType::HandleDOMActivateEvent(Event& event) {
: WebFeature::kColorInputTypeChooserByUntrustedClick);
chooser_ = chrome_client->OpenColorChooser(document.GetFrame(), this,
ValueAsColor());
- if (::features::IsFormControlsRefreshEnabled() &&
- GetElement().GetLayoutObject()) {
+ if (GetElement().GetLayoutObject()) {
// Invalidate paint to ensure that the focus ring is removed.
GetElement().GetLayoutObject()->SetShouldDoFullPaintInvalidation();
}
@@ -213,8 +212,7 @@ void ColorInputType::DidChooseColor(const Color& color) {
void ColorInputType::DidEndChooser() {
GetElement().EnqueueChangeEvent();
chooser_.Clear();
- if (::features::IsFormControlsRefreshEnabled() &&
- GetElement().GetLayoutObject()) {
+ if (GetElement().GetLayoutObject()) {
// Invalidate paint to ensure that the focus ring is shown.
GetElement().GetLayoutObject()->SetShouldDoFullPaintInvalidation();
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/date_input_type.cc
index b0008e357be..005a8704740 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_input_type.cc
@@ -134,7 +134,7 @@ bool DateInputType::IsValidFormat(bool has_year,
return has_year && has_month && has_day;
}
-String DateInputType::AriaRoleForPickerIndicator() const {
+String DateInputType::AriaLabelForPickerIndicator() const {
return GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_DATE_PICKER);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/date_input_type.h
index e2758b1e561..f653363a932 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_input_type.h
@@ -60,7 +60,7 @@ class DateInputType final : public BaseTemporalInputType {
bool has_hour,
bool has_minute,
bool has_second) const override;
- String AriaRoleForPickerIndicator() const override;
+ String AriaLabelForPickerIndicator() const override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser.h
index f3799353b40..d6628c68a14 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_CHOOSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_CHOOSER_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/choosers/date_time_chooser.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -46,6 +45,10 @@ class AXObject;
struct DateTimeChooserParameters {
DISALLOW_NEW();
CORE_EXPORT DateTimeChooserParameters();
+ // DateTimeSuggestionPtr is not copyable.
+ DateTimeChooserParameters(const DateTimeChooserParameters&) = delete;
+ DateTimeChooserParameters& operator=(const DateTimeChooserParameters&) =
+ delete;
CORE_EXPORT ~DateTimeChooserParameters();
AtomicString type;
@@ -70,10 +73,6 @@ struct DateTimeChooserParameters {
bool has_second = false;
bool has_millisecond = false;
int focused_field_index = 0;
-
- private:
- // DateTimeSuggestionPtr is not copyable.
- DISALLOW_COPY_AND_ASSIGN(DateTimeChooserParameters);
};
// For pickers like color pickers and date pickers.
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
index 6855e102e43..15d250490e9 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
@@ -129,16 +129,11 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data);
data->Append(ChooserResourceLoader::GetPickerCommonStyleSheet());
- if (!features::IsFormControlsRefreshEnabled())
- data->Append(ChooserResourceLoader::GetPickerButtonStyleSheet());
data->Append(ChooserResourceLoader::GetSuggestionPickerStyleSheet());
data->Append(ChooserResourceLoader::GetCalendarPickerStyleSheet());
- if (features::IsFormControlsRefreshEnabled()) {
- data->Append(ChooserResourceLoader::GetCalendarPickerRefreshStyleSheet());
- if (parameters_->type == input_type_names::kTime ||
- parameters_->type == input_type_names::kDatetimeLocal) {
- data->Append(ChooserResourceLoader::GetTimePickerStyleSheet());
- }
+ if (parameters_->type == input_type_names::kTime ||
+ parameters_->type == input_type_names::kDatetimeLocal) {
+ data->Append(ChooserResourceLoader::GetTimePickerStyleSheet());
}
AddString(
"</style></head><body><div id=main>Loading...</div><script>\n"
@@ -182,11 +177,8 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
AddProperty("ampmLabels", locale_->TimeAMPMLabels(), data);
AddProperty("isLocaleRTL", locale_->IsRTL(), data);
AddProperty("isRTL", parameters_->is_anchor_element_rtl, data);
- AddProperty("isFormControlsRefreshEnabled",
- features::IsFormControlsRefreshEnabled(), data);
#if defined(OS_MAC)
- AddProperty("isBorderTransparent", features::IsFormControlsRefreshEnabled(),
- data);
+ AddProperty("isBorderTransparent", true, data);
#endif
AddProperty("mode", parameters_->type.GetString(), data);
AddProperty("isAMPMFirst", parameters_->is_ampm_first, data);
@@ -236,14 +228,12 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data->Append(ChooserResourceLoader::GetPickerCommonJS());
data->Append(ChooserResourceLoader::GetSuggestionPickerJS());
- if (features::IsFormControlsRefreshEnabled()) {
- data->Append(ChooserResourceLoader::GetMonthPickerJS());
- if (parameters_->type == input_type_names::kTime) {
- data->Append(ChooserResourceLoader::GetTimePickerJS());
- } else if (parameters_->type == input_type_names::kDatetimeLocal) {
- data->Append(ChooserResourceLoader::GetTimePickerJS());
- data->Append(ChooserResourceLoader::GetDateTimeLocalPickerJS());
- }
+ data->Append(ChooserResourceLoader::GetMonthPickerJS());
+ if (parameters_->type == input_type_names::kTime) {
+ data->Append(ChooserResourceLoader::GetTimePickerJS());
+ } else if (parameters_->type == input_type_names::kDatetimeLocal) {
+ data->Append(ChooserResourceLoader::GetTimePickerJS());
+ data->Append(ChooserResourceLoader::GetDateTimeLocalPickerJS());
}
data->Append(ChooserResourceLoader::GetCalendarPickerJS());
AddString("</script></body>\n", data);
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 a44a6df44e0..b87ca328fd8 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
@@ -486,9 +486,10 @@ void DateTimeEditBuilder::VisitLiteral(const String& text) {
WTF::unicode::CharDirection dir = WTF::unicode::Direction(text[0]);
if (dir == WTF::unicode::kSegmentSeparator ||
dir == WTF::unicode::kWhiteSpaceNeutral ||
- dir == WTF::unicode::kOtherNeutral)
- element->AppendChild(Text::Create(EditElement().GetDocument(),
- String(&kRightToLeftMarkCharacter, 1)));
+ dir == WTF::unicode::kOtherNeutral) {
+ element->AppendChild(Text::Create(
+ EditElement().GetDocument(), String(&kRightToLeftMarkCharacter, 1u)));
+ }
}
element->AppendChild(Text::Create(EditElement().GetDocument(), text));
EditElement().FieldsWrapperElement()->AppendChild(element);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.h
index 5acb2aafaba..2446f9fe7b2 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_EDIT_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_EDIT_ELEMENT_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/html/forms/date_time_field_element.h"
#include "third_party/blink/renderer/core/html/forms/step_range.h"
@@ -82,6 +81,8 @@ class DateTimeEditElement final : public HTMLDivElement,
};
DateTimeEditElement(Document&, EditControlOwner&);
+ DateTimeEditElement(const DateTimeEditElement&) = delete;
+ DateTimeEditElement& operator=(const DateTimeEditElement&) = delete;
~DateTimeEditElement() override;
void Trace(Visitor*) const override;
@@ -157,8 +158,6 @@ class DateTimeEditElement final : public HTMLDivElement,
HeapVector<Member<DateTimeFieldElement>, kMaximumNumberOfFields> fields_;
Member<EditControlOwner> edit_control_owner_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeEditElement);
};
template <>
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 eea338def62..1886523c9f7 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
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_FIELD_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_FIELD_ELEMENT_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
@@ -74,6 +73,9 @@ class DateTimeFieldElement : public HTMLSpanElement {
virtual void FieldDidChangeValueByKeyboard() = 0;
};
+ DateTimeFieldElement(const DateTimeFieldElement&) = delete;
+ DateTimeFieldElement& operator=(const DateTimeFieldElement&) = delete;
+
void DefaultEventHandler(Event&) override;
virtual bool HasValue() const = 0;
bool IsDisabled() const;
@@ -122,8 +124,6 @@ class DateTimeFieldElement : public HTMLSpanElement {
Member<FieldOwner> field_owner_;
DateTimeField type_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeFieldElement);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.h
index 32effdb54de..e3810af7d43 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_FIELD_ELEMENTS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_FIELD_ELEMENTS_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h"
#include "third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -36,14 +35,14 @@ namespace blink {
class DateTimeAMPMFieldElement final : public DateTimeSymbolicFieldElement {
public:
DateTimeAMPMFieldElement(Document&, FieldOwner&, const Vector<String>&);
+ DateTimeAMPMFieldElement(const DateTimeAMPMFieldElement&) = delete;
+ DateTimeAMPMFieldElement& operator=(const DateTimeAMPMFieldElement&) = delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeAMPMFieldElement);
};
class DateTimeDayFieldElement final : public DateTimeNumericFieldElement {
@@ -52,17 +51,22 @@ class DateTimeDayFieldElement final : public DateTimeNumericFieldElement {
FieldOwner&,
const String& placeholder,
const Range&);
+ DateTimeDayFieldElement(const DateTimeDayFieldElement&) = delete;
+ DateTimeDayFieldElement& operator=(const DateTimeDayFieldElement&) = delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeDayFieldElement);
};
class DateTimeHourFieldElementBase : public DateTimeNumericFieldElement {
+ public:
+ DateTimeHourFieldElementBase(const DateTimeHourFieldElementBase&) = delete;
+ DateTimeHourFieldElementBase& operator=(const DateTimeHourFieldElementBase&) =
+ delete;
+
protected:
DateTimeHourFieldElementBase(Document&,
FieldOwner&,
@@ -75,8 +79,6 @@ class DateTimeHourFieldElementBase : public DateTimeNumericFieldElement {
// DateTimeFieldElement functions.
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeHourFieldElementBase);
};
class DateTimeHour11FieldElement final : public DateTimeHourFieldElementBase {
@@ -85,13 +87,14 @@ class DateTimeHour11FieldElement final : public DateTimeHourFieldElementBase {
FieldOwner&,
const Range& hour23_range,
const Step&);
+ DateTimeHour11FieldElement(const DateTimeHour11FieldElement&) = delete;
+ DateTimeHour11FieldElement& operator=(const DateTimeHour11FieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsInteger(int, EventBehavior = kDispatchNoEvent) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeHour11FieldElement);
};
class DateTimeHour12FieldElement final : public DateTimeHourFieldElementBase {
@@ -100,6 +103,9 @@ class DateTimeHour12FieldElement final : public DateTimeHourFieldElementBase {
FieldOwner&,
const Range& hour23_range,
const Step&);
+ DateTimeHour12FieldElement(const DateTimeHour12FieldElement&) = delete;
+ DateTimeHour12FieldElement& operator=(const DateTimeHour12FieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
@@ -113,8 +119,6 @@ class DateTimeHour12FieldElement final : public DateTimeHourFieldElementBase {
Step step,
int old_value,
int new_value) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeHour12FieldElement);
};
class DateTimeHour23FieldElement final : public DateTimeHourFieldElementBase {
@@ -123,13 +127,14 @@ class DateTimeHour23FieldElement final : public DateTimeHourFieldElementBase {
FieldOwner&,
const Range& hour23_range,
const Step&);
+ DateTimeHour23FieldElement(const DateTimeHour23FieldElement&) = delete;
+ DateTimeHour23FieldElement& operator=(const DateTimeHour23FieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsInteger(int, EventBehavior = kDispatchNoEvent) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeHour23FieldElement);
};
class DateTimeHour24FieldElement final : public DateTimeHourFieldElementBase {
@@ -138,13 +143,14 @@ class DateTimeHour24FieldElement final : public DateTimeHourFieldElementBase {
FieldOwner&,
const Range& hour23_range,
const Step&);
+ DateTimeHour24FieldElement(const DateTimeHour24FieldElement&) = delete;
+ DateTimeHour24FieldElement& operator=(const DateTimeHour24FieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsInteger(int, EventBehavior = kDispatchNoEvent) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeHour24FieldElement);
};
class DateTimeMillisecondFieldElement final
@@ -154,27 +160,30 @@ class DateTimeMillisecondFieldElement final
FieldOwner&,
const Range&,
const Step&);
+ DateTimeMillisecondFieldElement(const DateTimeMillisecondFieldElement&) =
+ delete;
+ DateTimeMillisecondFieldElement& operator=(
+ const DateTimeMillisecondFieldElement&) = delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeMillisecondFieldElement);
};
class DateTimeMinuteFieldElement final : public DateTimeNumericFieldElement {
public:
DateTimeMinuteFieldElement(Document&, FieldOwner&, const Range&, const Step&);
+ DateTimeMinuteFieldElement(const DateTimeMinuteFieldElement&) = delete;
+ DateTimeMinuteFieldElement& operator=(const DateTimeMinuteFieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeMinuteFieldElement);
};
class DateTimeMonthFieldElement final : public DateTimeNumericFieldElement {
@@ -183,27 +192,29 @@ class DateTimeMonthFieldElement final : public DateTimeNumericFieldElement {
FieldOwner&,
const String& placeholder,
const Range&);
+ DateTimeMonthFieldElement(const DateTimeMonthFieldElement&) = delete;
+ DateTimeMonthFieldElement& operator=(const DateTimeMonthFieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeMonthFieldElement);
};
class DateTimeSecondFieldElement final : public DateTimeNumericFieldElement {
public:
DateTimeSecondFieldElement(Document&, FieldOwner&, const Range&, const Step&);
+ DateTimeSecondFieldElement(const DateTimeSecondFieldElement&) = delete;
+ DateTimeSecondFieldElement& operator=(const DateTimeSecondFieldElement&) =
+ delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeSecondFieldElement);
};
class DateTimeSymbolicMonthFieldElement final
@@ -214,6 +225,10 @@ class DateTimeSymbolicMonthFieldElement final
const Vector<String>&,
int minimum,
int maximum);
+ DateTimeSymbolicMonthFieldElement(const DateTimeSymbolicMonthFieldElement&) =
+ delete;
+ DateTimeSymbolicMonthFieldElement& operator=(
+ const DateTimeSymbolicMonthFieldElement&) = delete;
private:
// DateTimeFieldElement functions.
@@ -221,20 +236,19 @@ class DateTimeSymbolicMonthFieldElement final
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
- DISALLOW_COPY_AND_ASSIGN(DateTimeSymbolicMonthFieldElement);
};
class DateTimeWeekFieldElement final : public DateTimeNumericFieldElement {
public:
DateTimeWeekFieldElement(Document&, FieldOwner&, const Range&);
+ DateTimeWeekFieldElement(const DateTimeWeekFieldElement&) = delete;
+ DateTimeWeekFieldElement& operator=(const DateTimeWeekFieldElement&) = delete;
private:
// DateTimeFieldElement functions.
void PopulateDateTimeFieldsState(DateTimeFieldsState&) override;
void SetValueAsDate(const DateComponents&) override;
void SetValueAsDateTimeFieldsState(const DateTimeFieldsState&) override;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeWeekFieldElement);
};
class DateTimeYearFieldElement final : public DateTimeNumericFieldElement {
@@ -257,6 +271,8 @@ class DateTimeYearFieldElement final : public DateTimeNumericFieldElement {
};
DateTimeYearFieldElement(Document&, FieldOwner&, const Parameters&);
+ DateTimeYearFieldElement(const DateTimeYearFieldElement&) = delete;
+ DateTimeYearFieldElement& operator=(const DateTimeYearFieldElement&) = delete;
private:
// DateTimeFieldElement functions.
@@ -270,8 +286,6 @@ class DateTimeYearFieldElement final : public DateTimeNumericFieldElement {
bool min_is_specified_;
bool max_is_specified_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeYearFieldElement);
};
} // namespace blink
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 2f411a459bc..eb8c4a62714 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
@@ -191,7 +191,7 @@ bool DateTimeLocalInputType::IsValidFormat(bool has_year,
return has_year && has_month && has_day && has_ampm && has_hour && has_minute;
}
-String DateTimeLocalInputType::AriaRoleForPickerIndicator() const {
+String DateTimeLocalInputType::AriaLabelForPickerIndicator() const {
return GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_DATE_TIME_LOCAL_PICKER);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h
index d9c679ac3c5..445599116ca 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h
@@ -67,7 +67,7 @@ class DateTimeLocalInputType final : public BaseTemporalInputType {
bool has_hour,
bool has_minute,
bool has_second) const override;
- String AriaRoleForPickerIndicator() const override;
+ String AriaLabelForPickerIndicator() const override;
};
} // namespace blink
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 5fb6190b255..60e51662873 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
@@ -123,7 +123,7 @@ void DateTimeNumericFieldElement::HandleKeyboardEvent(
UChar char_code = static_cast<UChar>(keyboard_event.charCode());
String number =
- LocaleForOwner().ConvertFromLocalizedNumber(String(&char_code, 1));
+ LocaleForOwner().ConvertFromLocalizedNumber(String(&char_code, 1u));
const int digit = number[0] - '0';
if (digit < 0 || digit > 9)
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 b537726d798..4249f3694c3 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
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_NUMERIC_FIELD_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_NUMERIC_FIELD_ELEMENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/forms/date_time_field_element.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -61,6 +60,10 @@ class DateTimeNumericFieldElement : public DateTimeFieldElement {
int maximum;
};
+ DateTimeNumericFieldElement(const DateTimeNumericFieldElement&) = delete;
+ DateTimeNumericFieldElement& operator=(const DateTimeNumericFieldElement&) =
+ delete;
+
protected:
DateTimeNumericFieldElement(Document&,
FieldOwner&,
@@ -116,8 +119,6 @@ class DateTimeNumericFieldElement : public DateTimeFieldElement {
int value_;
bool has_value_;
mutable StringBuilder type_ahead_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeNumericFieldElement);
};
} // namespace blink
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 9c752d5cce4..55c7a3897f5 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
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_SYMBOLIC_FIELD_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_DATE_TIME_SYMBOLIC_FIELD_ELEMENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/forms/date_time_field_element.h"
#include "third_party/blink/renderer/core/html/forms/type_ahead.h"
@@ -36,6 +35,11 @@ namespace blink {
// format, such as: AM/PM, and month.
class DateTimeSymbolicFieldElement : public DateTimeFieldElement,
public TypeAheadDataSource {
+ public:
+ DateTimeSymbolicFieldElement(const DateTimeSymbolicFieldElement&) = delete;
+ DateTimeSymbolicFieldElement& operator=(const DateTimeSymbolicFieldElement&) =
+ delete;
+
protected:
DateTimeSymbolicFieldElement(Document&,
FieldOwner&,
@@ -82,8 +86,6 @@ class DateTimeSymbolicFieldElement : public DateTimeFieldElement,
TypeAhead type_ahead_;
const int minimum_index_;
const int maximum_index_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeSymbolicFieldElement);
};
} // namespace blink
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 2ef63564e4f..3dffebdb9f8 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
@@ -34,6 +34,7 @@
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/events/current_input_event.h"
@@ -54,6 +55,23 @@
namespace blink {
+namespace {
+
+float GetDprForSizeAdjustment(const Element& owner_element) {
+ float dpr = 1.0f;
+ // Android doesn't need these adjustments and it makes tests fail.
+#ifndef OS_ANDROID
+ LocalFrame* frame = owner_element.GetDocument().GetFrame();
+ const Page* page = frame ? frame->GetPage() : nullptr;
+ if (Platform::Current()->IsUseZoomForDSFEnabled() && page) {
+ dpr = page->GetChromeClient().GetScreenInfo(*frame).device_scale_factor;
+ }
+#endif
+ return dpr;
+}
+
+} // namespace
+
ExternalPopupMenu::ExternalPopupMenu(LocalFrame& frame,
HTMLSelectElement& owner_element)
: owner_element_(owner_element),
@@ -106,6 +124,11 @@ bool ExternalPopupMenu::ShowInternal() {
->LocalRootFrameWidget()
->GetEmulatorScale();
+ // rect_in_viewport needs to be in CSS pixels.
+ float dpr = GetDprForSizeAdjustment(*owner_element_);
+ if (dpr != 1.0)
+ rect_in_viewport.Scale(1 / dpr);
+
gfx::Rect bounds =
gfx::Rect(rect_in_viewport.X() * scale_for_emulation,
rect_in_viewport.Y() * scale_for_emulation,
@@ -278,9 +301,11 @@ void ExternalPopupMenu::GetPopupMenuInfo(
: *owner_element.EnsureComputedStyle();
const SimpleFontData* font_data = menu_style.GetFont().PrimaryFont();
DCHECK(font_data);
- *item_height = font_data ? font_data->GetFontMetrics().Height() : 0;
+ // These coordinates need to be in CSS pixels.
+ float dpr = GetDprForSizeAdjustment(owner_element);
+ *item_height = font_data ? font_data->GetFontMetrics().Height() / dpr : 0;
*font_size = static_cast<int>(
- menu_style.GetFont().GetFontDescription().ComputedSize());
+ menu_style.GetFont().GetFontDescription().ComputedSize() / dpr);
*selected_item = ToExternalPopupMenuItemIndex(
owner_element.SelectedListIndex(), owner_element);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
index e382fdf7311..624336f94c6 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "content/test/test_blink_web_unit_test_support.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/choosers/popup_menu.mojom-blink.h"
@@ -219,6 +220,39 @@ TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportTransform) {
EXPECT_EQ(expected_y, ShownBounds().y());
}
+// Android doesn't use this position data and we don't adjust it for DPR there..
+#ifdef OS_ANDROID
+#define MAYBE_PopupAccountsForDeviceScaleFactor \
+ DISABLED_PopupAccountsForDeviceScaleFactor
+#else
+#define MAYBE_PopupAccountsForDeviceScaleFactor \
+ PopupAccountsForDeviceScaleFactor
+#endif
+
+TEST_F(ExternalPopupMenuTest, MAYBE_PopupAccountsForDeviceScaleFactor) {
+ content::TestBlinkWebUnitTestSupport::SetUseZoomForDsfEnabled(true);
+
+ RegisterMockedURLLoad("select_mid_screen.html");
+ LoadFrame("select_mid_screen.html");
+
+ constexpr float kScaleFactor = 2.0f;
+ WebView()->MainFrameWidget()->SetDeviceScaleFactorForTesting(kScaleFactor);
+ WebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
+ DocumentUpdateReason::kTest);
+
+ auto* select = To<HTMLSelectElement>(
+ MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
+ auto* layout_object = select->GetLayoutObject();
+ ASSERT_TRUE(layout_object);
+
+ select->ShowPopup();
+ WaitUntilShowedPopup();
+
+ // The test file has no body margins but 50px of padding.
+ EXPECT_EQ(50, ShownBounds().x());
+ EXPECT_EQ(50, ShownBounds().y());
+}
+
TEST_F(ExternalPopupMenuTest, DidAcceptIndex) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_controller.cc b/chromium/third_party/blink/renderer/core/html/forms/form_controller.cc
index d5bb69c7003..1fece3fb719 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_controller.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_controller.cc
@@ -23,7 +23,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -212,6 +211,8 @@ class SavedFormState {
public:
SavedFormState() : control_state_count_(0) {}
+ SavedFormState(const SavedFormState&) = delete;
+ SavedFormState& operator=(const SavedFormState&) = delete;
static std::unique_ptr<SavedFormState> Deserialize(const Vector<String>&,
wtf_size_t& index);
@@ -232,8 +233,6 @@ class SavedFormState {
ControlKeyHashTraits>;
ControlStateMap state_for_new_controls_;
wtf_size_t control_state_count_;
-
- DISALLOW_COPY_AND_ASSIGN(SavedFormState);
};
static bool IsNotFormControlTypeCharacter(UChar ch) {
@@ -333,6 +332,8 @@ Vector<String> SavedFormState::GetReferencedFilePaths() const {
class FormKeyGenerator final : public GarbageCollected<FormKeyGenerator> {
public:
FormKeyGenerator() = default;
+ FormKeyGenerator(const FormKeyGenerator&) = delete;
+ FormKeyGenerator& operator=(const FormKeyGenerator&) = delete;
void Trace(Visitor* visitor) const { visitor->Trace(form_to_key_map_); }
const AtomicString& FormKey(const ListedElement&);
@@ -343,8 +344,6 @@ class FormKeyGenerator final : public GarbageCollected<FormKeyGenerator> {
using FormSignatureToNextIndexMap = HashMap<String, unsigned>;
FormToKeyMap form_to_key_map_;
FormSignatureToNextIndexMap form_signature_to_next_index_map_;
-
- DISALLOW_COPY_AND_ASSIGN(FormKeyGenerator);
};
static inline void RecordFormStructure(const HTMLFormElement& form,
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 b7f8ab79752..68bf88449fc 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
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/forms/form_data.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_file_usvstring.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
@@ -49,14 +50,15 @@ namespace blink {
namespace {
class FormDataIterationSource final
- : public PairIterable<String, FormDataEntryValue>::IterationSource {
+ : public PairIterable<String,
+ Member<V8FormDataEntryValue>>::IterationSource {
public:
FormDataIterationSource(FormData* form_data)
: form_data_(form_data), current_(0) {}
bool Next(ScriptState* script_state,
String& name,
- FormDataEntryValue& value,
+ Member<V8FormDataEntryValue>& value,
ExceptionState& exception_state) override {
if (current_ >= form_data_->size())
return false;
@@ -64,17 +66,18 @@ class FormDataIterationSource final
const FormData::Entry& entry = *form_data_->Entries()[current_++];
name = entry.name();
if (entry.IsString()) {
- value.SetUSVString(entry.Value());
+ value = MakeGarbageCollected<V8FormDataEntryValue>(entry.Value());
} else {
DCHECK(entry.isFile());
- value.SetFile(entry.GetFile());
+ value = MakeGarbageCollected<V8FormDataEntryValue>(entry.GetFile());
}
return true;
}
void Trace(Visitor* visitor) const override {
visitor->Trace(form_data_);
- PairIterable<String, FormDataEntryValue>::IterationSource::Trace(visitor);
+ PairIterable<String, Member<V8FormDataEntryValue>>::IterationSource::Trace(
+ visitor);
}
private:
@@ -143,7 +146,6 @@ void FormData::deleteEntry(const String& name) {
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8FormDataEntryValue* FormData::get(const String& name) {
for (const auto& entry : Entries()) {
if (entry->name() == name) {
@@ -157,23 +159,7 @@ V8FormDataEntryValue* FormData::get(const String& name) {
}
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void FormData::get(const String& name, FormDataEntryValue& result) {
- for (const auto& entry : Entries()) {
- if (entry->name() == name) {
- if (entry->IsString()) {
- result.SetUSVString(entry->Value());
- } else {
- DCHECK(entry->isFile());
- result.SetFile(entry->GetFile());
- }
- return;
- }
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8FormDataEntryValue>> FormData::getAll(const String& name) {
HeapVector<Member<V8FormDataEntryValue>> results;
@@ -191,25 +177,6 @@ HeapVector<Member<V8FormDataEntryValue>> FormData::getAll(const String& name) {
}
return results;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-HeapVector<FormDataEntryValue> FormData::getAll(const String& name) {
- HeapVector<FormDataEntryValue> results;
-
- for (const auto& entry : Entries()) {
- if (entry->name() != name)
- continue;
- FormDataEntryValue value;
- if (entry->IsString()) {
- value.SetUSVString(entry->Value());
- } else {
- DCHECK(entry->isFile());
- value.SetFile(entry->GetFile());
- }
- results.push_back(value);
- }
- return results;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool FormData::has(const String& name) {
for (const auto& entry : Entries()) {
@@ -346,7 +313,9 @@ scoped_refptr<EncodedFormData> FormData::EncodeMultiPartFormData() {
}
} else {
std::string encoded_value = Encode(entry->Value());
- form_data->AppendData(encoded_value.c_str(), encoded_value.length());
+ form_data->AppendData(
+ encoded_value.c_str(),
+ base::checked_cast<wtf_size_t>(encoded_value.length()));
}
form_data->AppendData("\r\n", 2);
}
@@ -356,7 +325,7 @@ scoped_refptr<EncodedFormData> FormData::EncodeMultiPartFormData() {
return form_data;
}
-PairIterable<String, FormDataEntryValue>::IterationSource*
+PairIterable<String, Member<V8FormDataEntryValue>>::IterationSource*
FormData::StartIteration(ScriptState*, ExceptionState&) {
return MakeGarbageCollected<FormDataIterationSource>(this);
}
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 b5c66420c3e..ff014fcdc56 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
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_FORM_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_FORM_DATA_H_
-#include "third_party/blink/renderer/bindings/core/v8/file_or_usv_string.h"
#include "third_party/blink/renderer/bindings/core/v8/iterable.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -43,16 +42,14 @@
namespace blink {
class Blob;
+class File;
class FormControlState;
class HTMLFormElement;
class ScriptState;
-// Typedef from form_data.idl:
-typedef FileOrUSVString FormDataEntryValue;
-
class CORE_EXPORT FormData final
: public ScriptWrappable,
- public PairIterable<String, FormDataEntryValue> {
+ public PairIterable<String, Member<V8FormDataEntryValue>> {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -76,13 +73,8 @@ class CORE_EXPORT FormData final
Blob*,
const String& filename = String());
void deleteEntry(const String& name);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8FormDataEntryValue* get(const String& name);
HeapVector<Member<V8FormDataEntryValue>> getAll(const String& name);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void get(const String& name, FormDataEntryValue& result);
- HeapVector<FormDataEntryValue> getAll(const String& name);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool has(const String& name);
void set(const String& name, const String& value);
void set(const String& name, Blob*, const String& filename = String());
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_data_event.cc b/chromium/third_party/blink/renderer/core/html/forms/form_data_event.cc
index 6f5fac010fd..b9e46fce16e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_data_event.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_data_event.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_form_data_event_init.h"
#include "third_party/blink/renderer/core/event_interface_names.h"
+#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/html/forms/form_data.h"
namespace blink {
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 09df547b308..6c78b675e47 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
@@ -58,16 +58,9 @@ TEST(FormDataTest, get) {
auto* fd = MakeGarbageCollected<FormData>(UTF8Encoding());
fd->append("name1", "value1");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionFileOrUSVString* result = fd->get("name1");
EXPECT_TRUE(result->IsUSVString());
EXPECT_EQ("value1", result->GetAsUSVString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- FileOrUSVString result;
- fd->get("name1", result);
- EXPECT_TRUE(result.IsUSVString());
- EXPECT_EQ("value1", result.GetAsUSVString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const FormData::Entry& entry = *fd->Entries()[0];
EXPECT_EQ("name1", entry.name());
@@ -78,17 +71,10 @@ TEST(FormDataTest, getAll) {
auto* fd = MakeGarbageCollected<FormData>(UTF8Encoding());
fd->append("name1", "value1");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8FormDataEntryValue>>& results = fd->getAll("name1");
EXPECT_EQ(1u, results.size());
EXPECT_TRUE(results[0]->IsUSVString());
EXPECT_EQ("value1", results[0]->GetAsUSVString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<FormDataEntryValue> results = fd->getAll("name1");
- EXPECT_EQ(1u, results.size());
- EXPECT_TRUE(results[0].IsUSVString());
- EXPECT_EQ("value1", results[0].GetAsUSVString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ(1u, fd->size());
}
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 93ab4d09739..df3d42856f6 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
@@ -26,6 +26,8 @@
#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/layout_tree_builder_traversal.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/html/forms/html_legend_element.h"
@@ -33,12 +35,33 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
+namespace {
+
+bool WillReattachChildLayoutObject(const Node& parent) {
+ for (const Node* child = LayoutTreeBuilderTraversal::FirstChild(parent);
+ child; child = LayoutTreeBuilderTraversal::NextSibling(*child)) {
+ if (child->NeedsReattachLayoutTree())
+ return true;
+ if (child->ChildNeedsReattachLayoutTree() && child->GetComputedStyle() &&
+ child->GetComputedStyle()->Display() == EDisplay::kContents &&
+ WillReattachChildLayoutObject(*child))
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
HTMLFieldSetElement::HTMLFieldSetElement(Document& document)
- : HTMLFormControlElement(html_names::kFieldsetTag, document) {}
+ : HTMLFormControlElement(html_names::kFieldsetTag, document) {
+ // This class has DidRecalcStyle().
+ SetHasCustomStyleCallbacks();
+}
bool HTMLFieldSetElement::MatchesValidityPseudoClasses() const {
return true;
@@ -125,15 +148,18 @@ LayoutObject* HTMLFieldSetElement::CreateLayoutObject(
}
LayoutBox* HTMLFieldSetElement::GetLayoutBoxForScrolling() const {
- auto* layout_box = GetLayoutBox();
- if (!layout_box || !layout_box->IsLayoutNGFieldset())
- return HTMLFormControlElement::GetLayoutBoxForScrolling();
- LayoutObject* child = layout_box->SlowFirstChild();
- if (child && child->IsAnonymous())
- return To<LayoutBox>(child);
+ if (const auto* ng_fieldset = DynamicTo<LayoutNGFieldset>(GetLayoutBox())) {
+ if (auto* content = ng_fieldset->FindAnonymousFieldsetContentBox())
+ return content;
+ }
return HTMLFormControlElement::GetLayoutBoxForScrolling();
}
+void HTMLFieldSetElement::DidRecalcStyle(const StyleRecalcChange change) {
+ if (ChildNeedsReattachLayoutTree() && WillReattachChildLayoutObject(*this))
+ SetNeedsReattachLayoutTree();
+}
+
HTMLLegendElement* HTMLFieldSetElement::Legend() const {
return Traversal<HTMLLegendElement>::FirstChild(*this);
}
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 b5f62447fd1..f812ff3845f 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 SupportsFocus() const override;
LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
LayoutBox* GetLayoutBoxForScrolling() const override;
+ void DidRecalcStyle(const StyleRecalcChange change) override;
const AtomicString& FormControlType() const override;
bool RecalcWillValidate() const override { return false; }
bool MatchesValidityPseudoClasses() const final;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element_test.cc
new file mode 100644
index 00000000000..2f015f7b43c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element_test.cc
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
+
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+
+namespace blink {
+
+class HTMLFieldSetElementTest : public RenderingTest {};
+
+// crbug.com/1240414
+TEST_F(HTMLFieldSetElementTest, DidRecalcStyleWithDescendantReattach) {
+ SetBodyInnerHTML(R"HTML(
+<fieldset id="fieldset">
+ <legend>legend</legend>
+ <div><span id="span" style="display:none">span</span></div>
+</fieldset>)HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ // Reattach of a fieldset descendant should not reattach the fieldset.
+ auto* previous_layout_box = GetLayoutBoxByElementId("fieldset");
+ auto* descendant = GetElementById("span");
+ descendant->removeAttribute(html_names::kStyleAttr);
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_EQ(previous_layout_box, GetLayoutBoxByElementId("fieldset"));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.cc b/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.cc
index 04973ff6ba8..44f88e16c7d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.cc
@@ -24,7 +24,6 @@
#include "third_party/blink/renderer/core/html/forms/html_form_controls_collection.h"
-#include "third_party/blink/renderer/bindings/core/v8/radio_node_list_or_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_element_radionodelist.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
@@ -173,7 +172,6 @@ void HTMLFormControlsCollection::UpdateIdNameCache() const {
SetNamedItemCache(cache);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionElementOrRadioNodeList* HTMLFormControlsCollection::namedGetter(
const AtomicString& name) {
HeapVector<Member<Element>> named_items;
@@ -195,27 +193,6 @@ V8UnionElementOrRadioNodeList* HTMLFormControlsCollection::namedGetter(
return MakeGarbageCollected<V8UnionElementOrRadioNodeList>(
ownerNode().GetRadioNodeList(name));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLFormControlsCollection::namedGetter(
- const AtomicString& name,
- RadioNodeListOrElement& return_value) {
- HeapVector<Member<Element>> named_items;
- NamedItems(name, named_items);
-
- if (named_items.IsEmpty())
- return;
-
- if (named_items.size() == 1) {
- if (!IsA<HTMLImageElement>(*named_items[0]))
- return_value.SetElement(named_items.at(0));
- return;
- }
-
- // This path never returns a RadioNodeList for <img> because
- // onlyMatchingImgElements flag is false by default.
- return_value.SetRadioNodeList(ownerNode().GetRadioNodeList(name));
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLFormControlsCollection::SupportedPropertyNames(Vector<String>& names) {
// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlformcontrolscollection-0:
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.h b/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.h
index 2306b4d5f10..346d619c307 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_controls_collection.h
@@ -33,7 +33,6 @@
namespace blink {
class HTMLImageElement;
-class RadioNodeListOrElement;
class V8UnionElementOrRadioNodeList;
// This class is just a big hack to find form elements even in malformed HTML
@@ -53,11 +52,7 @@ class HTMLFormControlsCollection final : public HTMLCollection {
}
HTMLElement* namedItem(const AtomicString& name) const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionElementOrRadioNodeList* namedGetter(const AtomicString& name);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void namedGetter(const AtomicString& name, RadioNodeListOrElement&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
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 5a4f06cc7a2..5c02b66b46f 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
@@ -30,7 +30,6 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/common/security_context/insecure_request_policy.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/radio_node_list_or_element.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_submit_event_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_element_radionodelist.h"
@@ -73,9 +72,28 @@
namespace blink {
+namespace {
+
+bool HasFormInBetween(const Node* root, const Node* descendant) {
+ DCHECK(!IsA<HTMLFormElement>(descendant));
+ // |descendant| might not actually be a descendant of |root|.
+ if (!descendant->IsDescendantOf(root))
+ return false;
+ for (ContainerNode* parent = descendant->parentNode();
+ parent && parent != root; parent = parent->parentNode()) {
+ if (DynamicTo<HTMLFormElement>(parent)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
HTMLFormElement::HTMLFormElement(Document& document)
: HTMLElement(html_names::kFormTag, document),
listed_elements_are_dirty_(false),
+ listed_elements_including_shadow_trees_are_dirty_(false),
image_elements_are_dirty_(false),
has_elements_associated_by_parser_(false),
has_elements_associated_by_form_attribute_(false),
@@ -93,6 +111,7 @@ void HTMLFormElement::Trace(Visitor* visitor) const {
visitor->Trace(past_names_map_);
visitor->Trace(radio_button_group_scope_);
visitor->Trace(listed_elements_);
+ visitor->Trace(listed_elements_including_shadow_trees_);
visitor->Trace(image_elements_);
HTMLElement::Trace(visitor);
}
@@ -636,6 +655,8 @@ void HTMLFormElement::ParseAttribute(
void HTMLFormElement::Associate(ListedElement& e) {
listed_elements_are_dirty_ = true;
listed_elements_.clear();
+ listed_elements_including_shadow_trees_are_dirty_ = true;
+ listed_elements_including_shadow_trees_.clear();
if (e.ToHTMLElement().FastHasAttribute(html_names::kFormAttr))
has_elements_associated_by_form_attribute_ = true;
}
@@ -643,6 +664,8 @@ void HTMLFormElement::Associate(ListedElement& e) {
void HTMLFormElement::Disassociate(ListedElement& e) {
listed_elements_are_dirty_ = true;
listed_elements_.clear();
+ listed_elements_including_shadow_trees_are_dirty_ = true;
+ listed_elements_including_shadow_trees_.clear();
RemoveFromPastNamesMap(e.ToHTMLElement());
}
@@ -679,31 +702,67 @@ HTMLFormControlsCollection* HTMLFormElement::elements() {
}
void HTMLFormElement::CollectListedElements(
- Node& root,
- ListedElement::List& elements) const {
- elements.clear();
+ const Node& root,
+ ListedElement::List& elements,
+ ListedElement::List* elements_including_shadow_trees,
+ bool in_shadow_tree) const {
+ DCHECK(!in_shadow_tree || elements_including_shadow_trees);
+ if (!in_shadow_tree)
+ elements.clear();
for (HTMLElement& element : Traversal<HTMLElement>::StartsAfter(root)) {
- ListedElement* listed_element = ListedElement::From(element);
- if (listed_element && listed_element->Form() == this)
- elements.push_back(listed_element);
+ if (ListedElement* listed_element = ListedElement::From(element)) {
+ // If there is a <form> in between |root| and |listed_element|, then we
+ // shouldn't include it in |elements_including_shadow_trees| in order to
+ // prevent multiple forms from "owning" the same |listed_element| as shown
+ // by their |elements_including_shadow_trees|. |elements| doesn't have
+ // this problem because it can check |listed_element->Form()|.
+ if (in_shadow_tree && !HasFormInBetween(&root, &element)) {
+ elements_including_shadow_trees->push_back(listed_element);
+ } else if (listed_element->Form() == this) {
+ elements.push_back(listed_element);
+ if (elements_including_shadow_trees)
+ elements_including_shadow_trees->push_back(listed_element);
+ }
+ }
+ if (elements_including_shadow_trees && element.AuthorShadowRoot() &&
+ !HasFormInBetween(&root, &element)) {
+ const Node& shadow = *element.AuthorShadowRoot();
+ CollectListedElements(shadow, elements, elements_including_shadow_trees,
+ /*in_shadow_tree=*/true);
+ }
}
}
// This function should be const conceptually. However we update some fields
// because of lazy evaluation.
-const ListedElement::List& HTMLFormElement::ListedElements() const {
- if (!listed_elements_are_dirty_)
- return listed_elements_;
- HTMLFormElement* mutable_this = const_cast<HTMLFormElement*>(this);
- Node* scope = mutable_this;
- if (has_elements_associated_by_parser_)
- scope = &NodeTraversal::HighestAncestorOrSelf(*mutable_this);
- if (isConnected() && has_elements_associated_by_form_attribute_)
- scope = &GetTreeScope().RootNode();
- DCHECK(scope);
- CollectListedElements(*scope, mutable_this->listed_elements_);
- mutable_this->listed_elements_are_dirty_ = false;
- return listed_elements_;
+const ListedElement::List& HTMLFormElement::ListedElements(
+ bool include_shadow_trees) const {
+ if (!RuntimeEnabledFeatures::AutofillShadowDOMEnabled())
+ include_shadow_trees = false;
+ bool collect_shadow_inputs =
+ include_shadow_trees && listed_elements_including_shadow_trees_are_dirty_;
+
+ if (listed_elements_are_dirty_ || collect_shadow_inputs) {
+ HTMLFormElement* mutable_this = const_cast<HTMLFormElement*>(this);
+ Node* scope = mutable_this;
+ if (has_elements_associated_by_parser_)
+ scope = &NodeTraversal::HighestAncestorOrSelf(*mutable_this);
+ if (isConnected() && has_elements_associated_by_form_attribute_)
+ scope = &GetTreeScope().RootNode();
+ DCHECK(scope);
+ mutable_this->listed_elements_.clear();
+ mutable_this->listed_elements_including_shadow_trees_.clear();
+ CollectListedElements(
+ *scope, mutable_this->listed_elements_,
+ collect_shadow_inputs
+ ? &mutable_this->listed_elements_including_shadow_trees_
+ : nullptr);
+ mutable_this->listed_elements_are_dirty_ = false;
+ mutable_this->listed_elements_including_shadow_trees_are_dirty_ =
+ !collect_shadow_inputs;
+ }
+ return include_shadow_trees ? listed_elements_including_shadow_trees_
+ : listed_elements_;
}
void HTMLFormElement::CollectImageElements(
@@ -812,7 +871,7 @@ Element* HTMLFormElement::ElementFromPastNamesMap(
const AtomicString& past_name) {
if (past_name.IsEmpty() || !past_names_map_)
return nullptr;
- Element* element = past_names_map_->at(past_name);
+ Element* element = past_names_map_->DeprecatedAtOrEmptyValue(past_name);
#if DCHECK_IS_ON()
if (!element)
return nullptr;
@@ -876,27 +935,8 @@ void HTMLFormElement::FinishParsingChildren() {
did_finish_parsing_children_ = true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionElementOrRadioNodeList* HTMLFormElement::AnonymousNamedGetter(
const AtomicString& name) {
- RadioNodeListOrElement return_value;
- // Delegate to the old IDL union implementation for the time being.
- AnonymousNamedGetter(name, return_value);
- if (return_value.IsElement()) {
- return MakeGarbageCollected<V8UnionElementOrRadioNodeList>(
- return_value.GetAsElement());
- }
- if (return_value.IsRadioNodeList()) {
- return MakeGarbageCollected<V8UnionElementOrRadioNodeList>(
- return_value.GetAsRadioNodeList());
- }
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void HTMLFormElement::AnonymousNamedGetter(
- const AtomicString& name,
- RadioNodeListOrElement& return_value) {
// Call getNamedElements twice, first time check if it has a value
// and let HTMLFormElement update its cache.
// See issue: 867404
@@ -904,7 +944,7 @@ void HTMLFormElement::AnonymousNamedGetter(
HeapVector<Member<Element>> elements;
GetNamedElements(name, elements);
if (elements.IsEmpty())
- return;
+ return nullptr;
}
// Second call may return different results from the first call,
@@ -930,11 +970,10 @@ void HTMLFormElement::AnonymousNamedGetter(
}
}
if (elements.size() == 1) {
- return_value.SetElement(elements.at(0));
- return;
+ return MakeGarbageCollected<V8UnionElementOrRadioNodeList>(elements[0]);
}
-
- return_value.SetRadioNodeList(GetRadioNodeList(name, only_match_img));
+ return MakeGarbageCollected<V8UnionElementOrRadioNodeList>(
+ GetRadioNodeList(name, only_match_img));
}
void HTMLFormElement::InvalidateDefaultButtonStyle() const {
@@ -949,4 +988,8 @@ void HTMLFormElement::InvalidateDefaultButtonStyle() const {
}
}
+void HTMLFormElement::InvalidateListedElementsIncludingShadowTrees() {
+ listed_elements_including_shadow_trees_are_dirty_ = true;
+}
+
} // namespace blink
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 7c89b71c7e4..08b09564fc0 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
@@ -38,7 +38,6 @@ class HTMLFormControlElement;
class HTMLFormControlsCollection;
class HTMLImageElement;
class ListedElement;
-class RadioNodeListOrElement;
class V8UnionElementOrRadioNodeList;
class CORE_EXPORT HTMLFormElement final : public HTMLElement {
@@ -89,6 +88,7 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
String method() const;
void setMethod(const AtomicString&);
+ FormSubmission::SubmitMethod Method() const { return attributes_.Method(); }
// Find the 'default button.'
// https://html.spec.whatwg.org/C/#default-button
@@ -103,13 +103,11 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
return radio_button_group_scope_;
}
- const ListedElement::List& ListedElements() const;
+ const ListedElement::List& ListedElements(
+ bool include_shadow_trees = false) const;
const HeapVector<Member<HTMLImageElement>>& ImageElements();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionElementOrRadioNodeList* AnonymousNamedGetter(const AtomicString& name);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void AnonymousNamedGetter(const AtomicString& name, RadioNodeListOrElement&);
void InvalidateDefaultButtonStyle() const;
// 'construct the entry list'
@@ -120,6 +118,8 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
unsigned UniqueRendererFormId() const { return unique_renderer_form_id_; }
+ void InvalidateListedElementsIncludingShadowTrees();
+
private:
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
@@ -139,7 +139,11 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
void ScheduleFormSubmission(const Event*,
HTMLFormControlElement* submit_button);
- void CollectListedElements(Node& root, ListedElement::List&) const;
+ void CollectListedElements(
+ const Node& root,
+ ListedElement::List& elements,
+ ListedElement::List* elements_including_shadow_trees = nullptr,
+ bool in_shadow_tree = false) const;
void CollectImageElements(Node& root, HeapVector<Member<HTMLImageElement>>&);
// Returns true if the submission should proceed.
@@ -163,6 +167,9 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
// Do not access listed_elements_ directly. Use ListedElements() instead.
ListedElement::List listed_elements_;
+ // Do not access listed_elements_including_shadow_trees_ directly. Use
+ // ListedElements(true) instead.
+ ListedElement::List listed_elements_including_shadow_trees_;
// Do not access image_elements_ directly. Use ImageElements() instead.
HeapVector<Member<HTMLImageElement>> image_elements_;
@@ -173,6 +180,7 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
bool is_constructing_entry_list_ = false;
bool listed_elements_are_dirty_ : 1;
+ bool listed_elements_including_shadow_trees_are_dirty_ : 1;
bool image_elements_are_dirty_ : 1;
bool has_elements_associated_by_parser_ : 1;
bool has_elements_associated_by_form_attribute_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
index 1f79394e93c..a2a79e10979 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
@@ -5,6 +5,9 @@
#include "third_party/blink/renderer/core/html/forms/html_form_element.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/forms/html_input_element.h"
+#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
namespace blink {
@@ -31,4 +34,262 @@ TEST_F(HTMLFormElementTest, UniqueRendererFormId) {
EXPECT_EQ(first_id + 2, form3->UniqueRendererFormId());
}
+// This tree is created manually because the HTML parser removes nested forms.
+// The created tree looks like this:
+// <body>
+// <form id=form1>
+// <form id=form2>
+// <input>
+TEST_F(HTMLFormElementTest, ListedElementsNestedForms) {
+ HTMLBodyElement* body = GetDocument().FirstBodyElement();
+
+ HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ body->AppendChild(form1);
+
+ HTMLFormElement* form2 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ form1->AppendChild(form2);
+
+ HTMLInputElement* input = MakeGarbageCollected<HTMLInputElement>(
+ GetDocument(), CreateElementFlags::ByCreateElement());
+ form2->AppendChild(input);
+
+ ListedElement::List form1elements = form1->ListedElements();
+ ListedElement::List form2elements = form2->ListedElements();
+ EXPECT_EQ(form1elements.size(), 0u);
+ ASSERT_EQ(form2elements.size(), 1u);
+ EXPECT_EQ(form2elements.at(0)->ToHTMLElement(), input);
+}
+
+TEST_F(HTMLFormElementTest, ListedElementsDetachedForm) {
+ HTMLBodyElement* body = GetDocument().FirstBodyElement();
+
+ HTMLFormElement* form = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ body->AppendChild(form);
+
+ HTMLInputElement* input = MakeGarbageCollected<HTMLInputElement>(
+ GetDocument(), CreateElementFlags::ByCreateElement());
+ form->AppendChild(input);
+
+ ListedElement::List listed_elements = form->ListedElements();
+ ASSERT_EQ(listed_elements.size(), 1u);
+ EXPECT_EQ(listed_elements.at(0)->ToHTMLElement(), input);
+
+ form->remove();
+ listed_elements = form->ListedElements();
+ ASSERT_EQ(listed_elements.size(), 1u);
+ EXPECT_EQ(listed_elements.at(0)->ToHTMLElement(), input);
+}
+
+// This tree is created manually because the HTML parser removes nested forms.
+// The created tree looks like this:
+// <body>
+// <form id=form1>
+// <div id=form1div>
+// <template shadowroot=open>
+// <form id=form2>
+// <form id=form3>
+// <div id=form3div>
+// <template shadowroot=open>
+//
+// An <input> element is appended at the bottom and moved up one node at a time
+// in this tree, and each step of the way, ListedElements is checked on all
+// forms.
+TEST_F(HTMLFormElementTest, ListedElementsIncludeShadowTrees) {
+ HTMLBodyElement* body = GetDocument().FirstBodyElement();
+
+ HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ body->AppendChild(form1);
+
+ HTMLDivElement* form1div =
+ MakeGarbageCollected<HTMLDivElement>(GetDocument());
+ form1->AppendChild(form1div);
+ ShadowRoot& form1root =
+ form1div->AttachShadowRootInternal(ShadowRootType::kOpen);
+
+ HTMLFormElement* form2 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ form1root.AppendChild(form2);
+
+ HTMLFormElement* form3 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ form2->AppendChild(form3);
+
+ HTMLDivElement* form3div =
+ MakeGarbageCollected<HTMLDivElement>(GetDocument());
+ form3->AppendChild(form3div);
+ ShadowRoot& form3root =
+ form3div->AttachShadowRootInternal(ShadowRootType::kOpen);
+
+ HTMLInputElement* input = MakeGarbageCollected<HTMLInputElement>(
+ GetDocument(), CreateElementFlags::ByCreateElement());
+
+ form3root.AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+
+ input->remove();
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ form3div->AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{input});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+
+ form3->AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{input});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+
+ input->remove();
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ form2->AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{input});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ input->remove();
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ form1root.AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ input->remove();
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ form1div->AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{input});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ form1->AppendChild(input);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{input});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{input});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+
+ input->remove();
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
+ EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
+ ListedElement::List{});
+}
+
+// This tree is created manually because innerHTML assignment doesn't invoke the
+// parser for declarative ShadowDOM. The created tree looks like this:
+// <form id=form1>
+// <input id=input1>
+// <div id=div1>
+// <template shadowroot=open>
+// <input id=input2>
+// </template>
+// </div>
+// </form>
+TEST_F(HTMLFormElementTest, ListedElementsAfterIncludeShadowTrees) {
+ HTMLBodyElement* body = GetDocument().FirstBodyElement();
+
+ HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+ body->AppendChild(form1);
+
+ HTMLInputElement* input1 = MakeGarbageCollected<HTMLInputElement>(
+ GetDocument(), CreateElementFlags::ByCreateElement());
+ form1->AppendChild(input1);
+
+ HTMLDivElement* form1div =
+ MakeGarbageCollected<HTMLDivElement>(GetDocument());
+ form1->AppendChild(form1div);
+ ShadowRoot& form1root =
+ form1div->AttachShadowRootInternal(ShadowRootType::kOpen);
+
+ HTMLInputElement* input2 = MakeGarbageCollected<HTMLInputElement>(
+ GetDocument(), CreateElementFlags::ByCreateElement());
+ form1root.AppendChild(input2);
+
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{input1});
+ ListedElement::List list;
+ list.push_back(input1);
+ list.push_back(input2);
+ EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true), list);
+ EXPECT_EQ(form1->ListedElements(), ListedElement::List{input1});
+}
+
} // 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 ce0e6394bec..2a91960c631 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
@@ -305,10 +305,8 @@ bool HTMLInputElement::MayTriggerVirtualKeyboard() const {
}
bool HTMLInputElement::ShouldHaveFocusAppearance() const {
- // For FormControlsRefresh don't draw focus ring for an input that has its
- // popup open.
- if (::features::IsFormControlsRefreshEnabled() &&
- input_type_view_->HasOpenedPopup())
+ // Don't draw focus ring for an input that has its popup open.
+ if (input_type_view_->HasOpenedPopup())
return false;
return TextControlElement::ShouldHaveFocusAppearance();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_label_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_label_element.cc
index 1b30722decd..7e4d7ac3233 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_label_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_label_element.cc
@@ -146,10 +146,9 @@ void HTMLLabelElement::DefaultEventHandler(Event& evt) {
// event, then there's no need for us to do anything.
if (!element)
return;
- if (evt.target()) {
- Node* target_node = evt.target()->ToNode();
- if (target_node &&
- element->IsShadowIncludingInclusiveAncestorOf(*target_node))
+ Node* target_node = evt.target() ? evt.target()->ToNode() : nullptr;
+ if (target_node) {
+ if (element->IsShadowIncludingInclusiveAncestorOf(*target_node))
return;
if (IsInInteractiveContent(target_node))
@@ -184,16 +183,18 @@ void HTMLLabelElement::DefaultEventHandler(Event& evt) {
!frame->GetEventHandler()
.GetSelectionController()
.MouseDownWasSingleClickInSelection() &&
- evt.target()->ToNode()->CanStartSelection())
+ target_node->CanStartSelection()) {
is_label_text_selected = true;
- // If selection is there and is single click i.e. text is
- // selected by dragging over label text, then return.
- // Click count >=2, meaning double click or triple click,
- // should pass click event to control element.
- // Only in case of drag, *neither* we pass the click event,
- // *nor* we focus the control element.
- if (is_label_text_selected && mouse_event->ClickCount() == 1)
- return;
+
+ // If selection is there and is single click i.e. text is
+ // selected by dragging over label text, then return.
+ // Click count >=2, meaning double click or triple click,
+ // should pass click event to control element.
+ // Only in case of drag, *neither* we pass the click event,
+ // *nor* we focus the control element.
+ if (mouse_event->ClickCount() == 1)
+ return;
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.cc
index 6a6aa820fef..e242ca6752b 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -44,6 +45,13 @@ HTMLFormElement* HTMLLegendElement::form() const {
return nullptr;
}
+void HTMLLegendElement::DetachLayoutTree(bool performing_reattach) {
+ LayoutObject* object = GetLayoutObject();
+ if (!performing_reattach && object && object->IsRenderedLegend())
+ object->Parent()->GetNode()->SetForceReattachLayoutTree();
+ HTMLElement::DetachLayoutTree(performing_reattach);
+}
+
LayoutObject* HTMLLegendElement::CreateLayoutObject(const ComputedStyle& style,
LegacyLayout legacy) {
// Count text-align property which does not mapped from 'align' content
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.h
index b1ea409cecd..dcbe4bc6a01 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_legend_element.h
@@ -37,6 +37,7 @@ class HTMLLegendElement final : public HTMLElement {
HTMLFormElement* form() const;
private:
+ void DetachLayoutTree(bool performing_reattach) override;
LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
};
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 09915da962a..82d2a905b93 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,8 +21,6 @@
#include "third_party/blink/renderer/core/html/forms/html_options_collection.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"
@@ -70,21 +68,12 @@ void HTMLOptionsCollection::SupportedPropertyNames(Vector<String>& names) {
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLOptionsCollection::add(
const V8UnionHTMLOptGroupElementOrHTMLOptionElement* element,
const V8UnionHTMLElementOrLong* before,
ExceptionState& exception_state) {
To<HTMLSelectElement>(ownerNode()).add(element, before, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLOptionsCollection::add(
- const HTMLOptionElementOrHTMLOptGroupElement& element,
- const HTMLElementOrLong& before,
- ExceptionState& exception_state) {
- To<HTMLSelectElement>(ownerNode()).add(element, before, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLOptionsCollection::remove(int index) {
To<HTMLSelectElement>(ownerNode()).remove(index);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.h b/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.h
index 4c41e48bd17..e2f14fe9eaa 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.h
@@ -32,8 +32,6 @@
namespace blink {
class ExceptionState;
-class HTMLElementOrLong;
-class HTMLOptionElementOrHTMLOptGroupElement;
class V8UnionHTMLElementOrLong;
class V8UnionHTMLOptGroupElementOrHTMLOptionElement;
@@ -48,15 +46,9 @@ class HTMLOptionsCollection final : public HTMLCollection {
return To<HTMLOptionElement>(HTMLCollection::item(offset));
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void add(const V8UnionHTMLOptGroupElementOrHTMLOptionElement* element,
const V8UnionHTMLElementOrLong* before,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void add(const HTMLOptionElementOrHTMLOptGroupElement&,
- const HTMLElementOrLong&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void remove(int index);
int selectedIndex() const;
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 88e95ee5f02..620399bec8d 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
@@ -33,12 +33,11 @@
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/strings/grit/blink_strings.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/bindings/core/v8/v8_union_htmlelement_long.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmloptgroupelement_htmloptionelement.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/style_engine.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/events/scoped_event_queue.h"
@@ -235,7 +234,6 @@ HTMLOptionElement* HTMLSelectElement::ActiveSelectionEnd() const {
return select_type_->ActiveSelectionEnd();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLSelectElement::add(
const V8UnionHTMLOptGroupElementOrHTMLOptionElement* element,
const V8UnionHTMLElementOrLong* before,
@@ -269,30 +267,6 @@ void HTMLSelectElement::add(
InsertBefore(element_to_insert, before_element, exception_state);
SetNeedsValidityCheck();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLSelectElement::add(
- const HTMLOptionElementOrHTMLOptGroupElement& element,
- const HTMLElementOrLong& before,
- ExceptionState& exception_state) {
- HTMLElement* element_to_insert;
- DCHECK(!element.IsNull());
- if (element.IsHTMLOptionElement())
- element_to_insert = element.GetAsHTMLOptionElement();
- else
- element_to_insert = element.GetAsHTMLOptGroupElement();
-
- HTMLElement* before_element;
- if (before.IsHTMLElement())
- before_element = before.GetAsHTMLElement();
- else if (before.IsLong())
- before_element = options()->item(before.GetAsLong());
- else
- before_element = nullptr;
-
- InsertBefore(element_to_insert, before_element, exception_state);
- SetNeedsValidityCheck();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLSelectElement::remove(int option_index) {
if (HTMLOptionElement* option = item(option_index))
@@ -390,9 +364,8 @@ bool HTMLSelectElement::MayTriggerVirtualKeyboard() const {
}
bool HTMLSelectElement::ShouldHaveFocusAppearance() const {
- // For FormControlsRefresh don't draw focus ring for a select that has its
- // popup open.
- if (::features::IsFormControlsRefreshEnabled() && PopupIsVisible())
+ // Don't draw focus ring for a select that has its popup open.
+ if (PopupIsVisible())
return false;
return HTMLFormControlElementWithState::ShouldHaveFocusAppearance();
@@ -460,7 +433,6 @@ void HTMLSelectElement::SetOption(unsigned index,
index, kMaxListItems)));
return;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* element =
MakeGarbageCollected<V8UnionHTMLOptGroupElementOrHTMLOptionElement>(
option);
@@ -479,24 +451,6 @@ void HTMLSelectElement::SetOption(unsigned index,
// Finally add the new element.
EventQueueScope scope;
add(element, before, exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HTMLOptionElementOrHTMLOptGroupElement element;
- element.SetHTMLOptionElement(option);
- HTMLElementOrLong before;
- // Out of array bounds? First insert empty dummies.
- if (diff > 0) {
- setLength(index, exception_state);
- // Replace an existing entry?
- } else if (diff < 0) {
- before.SetHTMLElement(options()->item(index + 1));
- remove(index);
- }
- if (exception_state.HadException())
- return;
- // Finally add the new element.
- EventQueueScope scope;
- add(element, before, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException())
return;
if (diff >= 0 && option->Selected())
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 801db452873..48dd20ee591 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
@@ -42,11 +42,9 @@ namespace blink {
class AXObject;
class AutoscrollController;
class ExceptionState;
-class HTMLElementOrLong;
class HTMLHRElement;
class HTMLOptGroupElement;
class HTMLOptionElement;
-class HTMLOptionElementOrHTMLOptGroupElement;
class LayoutUnit;
class PopupMenu;
class SelectType;
@@ -87,15 +85,9 @@ class CORE_EXPORT HTMLSelectElement final
bool UsesMenuList() const { return uses_menu_list_; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void add(const V8UnionHTMLOptGroupElementOrHTMLOptionElement* element,
const V8UnionHTMLElementOrLong* before,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void add(const HTMLOptionElementOrHTMLOptGroupElement&,
- const HTMLElementOrLong&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
using Node::remove;
void remove(int index);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
index 5e73a4876bd..10d22d8ef79 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
@@ -22,6 +22,100 @@
namespace blink {
+// Used by <selectmenu> to find child parts. The <selectmenu> parts search
+// pierces into shadow roots, but ignores all children of nested <selectmenu>
+// and <select> elements. So this traversal is similar to a FlatTreeTraversal,
+// except that when a <selectmenu> or <select> element is encountered, that
+// element and its children are skipped over.
+class CORE_EXPORT SelectMenuPartTraversal {
+ STATIC_ONLY(SelectMenuPartTraversal);
+
+ public:
+ // Returns the first non-<select> or <selectmenu> child of node in a flat tree
+ // traversal.
+ static Node* FirstChild(const Node& node);
+ // Returns the next non-<select> or <selectmenu> sibling of node in a flat
+ // tree traversal.
+ static Node* NextSibling(const Node& node);
+ // Returns the next Node in a flat tree pre-order traversal that skips
+ // <select> and <selectemenu> elements and their children.
+ static Node* Next(const Node& node, const Node* stay_within);
+
+ // Returns true if other is an ancestor of node, and there are no <select> or
+ // <selectmenu> ancestors in the parent chain between node and other.
+ static bool IsDescendantOf(const Node& node, const Node& other);
+
+ private:
+ static Node* NextSkippingChildren(const Node&, const Node* stay_within);
+ static bool IsNestedSelectMenu(const Node& node);
+};
+
+Node* SelectMenuPartTraversal::NextSibling(const Node& node) {
+ Node* next = FlatTreeTraversal::NextSibling(node);
+ while (next && SelectMenuPartTraversal::IsNestedSelectMenu(*next)) {
+ next = FlatTreeTraversal::NextSibling(*next);
+ }
+ return next;
+}
+
+Node* SelectMenuPartTraversal::FirstChild(const Node& node) {
+ Node* first = FlatTreeTraversal::FirstChild(node);
+ while (first && SelectMenuPartTraversal::IsNestedSelectMenu(*first)) {
+ first = SelectMenuPartTraversal::NextSibling(*first);
+ }
+ return first;
+}
+
+namespace {
+
+static Node* NextAncestorSibling(const Node& node, const Node* stay_within) {
+ DCHECK(!SelectMenuPartTraversal::NextSibling(node));
+ DCHECK_NE(node, stay_within);
+ for (Node* parent_node = FlatTreeTraversal::Parent(node); parent_node;
+ parent_node = FlatTreeTraversal::Parent(*parent_node)) {
+ if (parent_node == stay_within)
+ return nullptr;
+ if (Node* next_node = SelectMenuPartTraversal::NextSibling(*parent_node))
+ return next_node;
+ }
+ return nullptr;
+}
+
+} // namespace
+
+Node* SelectMenuPartTraversal::NextSkippingChildren(const Node& node,
+ const Node* stay_within) {
+ if (node == stay_within)
+ return nullptr;
+ if (Node* next_node = NextSibling(node))
+ return next_node;
+ return NextAncestorSibling(node, stay_within);
+}
+
+Node* SelectMenuPartTraversal::Next(const Node& node, const Node* stay_within) {
+ if (Node* child = FirstChild(node))
+ return child;
+ return NextSkippingChildren(node, stay_within);
+}
+
+bool SelectMenuPartTraversal::IsDescendantOf(const Node& node,
+ const Node& other) {
+ for (const Node* ancestor = FlatTreeTraversal::Parent(node); ancestor;
+ ancestor = FlatTreeTraversal::Parent(*ancestor)) {
+ if (ancestor == other)
+ return true;
+ if (IsNestedSelectMenu(*ancestor))
+ return false;
+ }
+ return false;
+}
+
+bool SelectMenuPartTraversal::IsNestedSelectMenu(const Node& node) {
+ // When searching for parts of a given <selectmenu>, don't look
+ // inside nested <selectmenu> or <select> elements.
+ return IsA<HTMLSelectMenuElement>(node) || IsA<HTMLSelectElement>(node);
+}
+
class HTMLSelectMenuElement::SelectMutationCallback
: public MutationObserver::Delegate {
public:
@@ -161,8 +255,13 @@ void HTMLSelectMenuElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
// is to get named slots working in UA shadow DOM (crbug.com/1179356), and
// then we can switch to that and use the -webkit pseudo-id selectors.
- auto* button_slot = MakeGarbageCollected<HTMLSlotElement>(document);
- button_slot->setAttribute(html_names::kNameAttr, kButtonPartName);
+ button_slot_ = MakeGarbageCollected<HTMLSlotElement>(document);
+ button_slot_->setAttribute(html_names::kNameAttr, kButtonPartName);
+ slotchange_listener_ =
+ MakeGarbageCollected<HTMLSelectMenuElement::SlotChangeEventListener>(
+ this);
+ button_slot_->addEventListener(event_type_names::kSlotchange,
+ slotchange_listener_, /*use_capture=*/false);
button_part_ = MakeGarbageCollected<HTMLButtonElement>(document);
button_part_->setAttribute(html_names::kPartAttr, kButtonPartName);
@@ -180,7 +279,7 @@ void HTMLSelectMenuElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
MakeGarbageCollected<HTMLSelectMenuElement::ButtonPartEventListener>(
this);
button_part_->addEventListener(event_type_names::kClick,
- button_part_listener_, false);
+ button_part_listener_, /*use_capture=*/false);
selected_value_part_ = MakeGarbageCollected<HTMLDivElement>(document);
selected_value_part_->setAttribute(html_names::kPartAttr,
@@ -208,8 +307,10 @@ void HTMLSelectMenuElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
width: 1.2em;
)CSS");
- auto* listbox_slot = MakeGarbageCollected<HTMLSlotElement>(document);
- listbox_slot->setAttribute(html_names::kNameAttr, kListboxPartName);
+ listbox_slot_ = MakeGarbageCollected<HTMLSlotElement>(document);
+ listbox_slot_->setAttribute(html_names::kNameAttr, kListboxPartName);
+ listbox_slot_->addEventListener(event_type_names::kSlotchange,
+ slotchange_listener_, /*use_capture=*/false);
SetListboxPart(MakeGarbageCollected<HTMLPopupElement>(document));
listbox_part_->setAttribute(html_names::kPartAttr, kListboxPartName);
@@ -219,13 +320,13 @@ void HTMLSelectMenuElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
button_part_->AppendChild(selected_value_part_);
button_part_->AppendChild(button_icon);
- button_slot->AppendChild(button_part_);
+ button_slot_->AppendChild(button_part_);
listbox_part_->appendChild(options_slot);
- listbox_slot->appendChild(listbox_part_);
+ listbox_slot_->appendChild(listbox_part_);
- root.AppendChild(button_slot);
- root.AppendChild(listbox_slot);
+ root.AppendChild(button_slot_);
+ root.AppendChild(listbox_slot_);
option_part_listener_ =
MakeGarbageCollected<HTMLSelectMenuElement::OptionPartEventListener>(
@@ -250,7 +351,7 @@ void HTMLSelectMenuElement::setValue(const String& value, bool send_events) {
}
}
-bool HTMLSelectMenuElement::IsOpen() const {
+bool HTMLSelectMenuElement::open() const {
// TODO(crbug.com/1121840) listbox_part_ can be null if
// the author has filled the listbox slot without including
// a replacement listbox part. Instead of null checks like this,
@@ -259,41 +360,53 @@ bool HTMLSelectMenuElement::IsOpen() const {
return listbox_part_ != nullptr && listbox_part_->open();
}
-void HTMLSelectMenuElement::Open() {
- if (listbox_part_ != nullptr && !IsOpen()) {
+void HTMLSelectMenuElement::OpenListbox() {
+ if (listbox_part_ != nullptr && !open()) {
listbox_part_->SetNeedsRepositioningForSelectMenu(true);
listbox_part_->show();
}
}
-void HTMLSelectMenuElement::Close() {
- if (listbox_part_ != nullptr && IsOpen()) {
+void HTMLSelectMenuElement::CloseListbox() {
+ if (listbox_part_ != nullptr && open()) {
listbox_part_->hide();
}
}
-void HTMLSelectMenuElement::SetListboxPart(HTMLPopupElement* listbox_part) {
- if (listbox_part_ == listbox_part)
+void HTMLSelectMenuElement::SetListboxPart(HTMLPopupElement* new_listbox_part) {
+ if (listbox_part_ == new_listbox_part)
return;
if (listbox_part_) {
listbox_part_->SetOwnerSelectMenuElement(nullptr);
listbox_part_->SetNeedsRepositioningForSelectMenu(false);
}
- listbox_part_ = listbox_part;
- listbox_part_->SetOwnerSelectMenuElement(this);
+
+ if (new_listbox_part) {
+ new_listbox_part->SetOwnerSelectMenuElement(this);
+ } else {
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "<selectmenu>'s default listbox was removed by an element labeled "
+ "slot=\"listbox\", and a new one was not provided. This <selectmenu> "
+ "will not be fully functional."));
+ }
+
+ listbox_part_ = new_listbox_part;
}
bool HTMLSelectMenuElement::IsValidButtonPart(const Element* part,
bool show_warning) const {
- bool is_valid = !FlatTreeTraversal::IsDescendantOf(*part, *listbox_part_);
+ bool is_valid = !listbox_part_ ||
+ !FlatTreeTraversal::IsDescendantOf(*part, *listbox_part_);
if (!is_valid && show_warning) {
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kRendering,
mojom::blink::ConsoleMessageLevel::kWarning,
- "A <selectmenu> must not contain an element labeled with "
- "part=\"button\" that is also a descendant of the \"listbox\" part. "
- "This <selectmenu> will not be fully functional."));
+ "To receive button part controller code, an element labeled as a "
+ "button must not be a descendant of the <selectmenu>'s listbox "
+ "part. This <selectmenu> will not be fully functional."));
}
return is_valid;
@@ -313,7 +426,7 @@ bool HTMLSelectMenuElement::IsValidListboxPart(const Element* part,
return false;
}
- if (FlatTreeTraversal::IsDescendantOf(*part, *button_part_)) {
+ if (button_part_ && FlatTreeTraversal::IsDescendantOf(*part, *button_part_)) {
if (show_warning) {
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kRendering,
@@ -330,7 +443,8 @@ bool HTMLSelectMenuElement::IsValidListboxPart(const Element* part,
bool HTMLSelectMenuElement::IsValidOptionPart(const Element* part,
bool show_warning) const {
- bool is_valid = FlatTreeTraversal::IsDescendantOf(*part, *listbox_part_);
+ bool is_valid = listbox_part_ && SelectMenuPartTraversal::IsDescendantOf(
+ *part, *listbox_part_);
if (!is_valid && show_warning) {
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kRendering,
@@ -342,24 +456,53 @@ bool HTMLSelectMenuElement::IsValidOptionPart(const Element* part,
return is_valid;
}
+Element* HTMLSelectMenuElement::FirstValidButtonPart() const {
+ for (Node* node = SelectMenuPartTraversal::FirstChild(*this); node;
+ node = SelectMenuPartTraversal::Next(*node, this)) {
+ auto* element = DynamicTo<Element>(node);
+ if (!element) {
+ continue;
+ }
+
+ if (element->getAttribute(html_names::kPartAttr) == kButtonPartName &&
+ IsValidButtonPart(element, /*show_warning=*/false)) {
+ return element;
+ }
+ }
+
+ return nullptr;
+}
+
+void HTMLSelectMenuElement::SetButtonPart(Element* new_button_part) {
+ if (button_part_ == new_button_part)
+ return;
+
+ if (button_part_) {
+ button_part_->removeEventListener(event_type_names::kClick,
+ button_part_listener_, false);
+ }
+
+ if (new_button_part) {
+ new_button_part->addEventListener(
+ event_type_names::kClick, button_part_listener_, /*use_capture=*/false);
+ } else {
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "<selectmenu>'s default button was removed by an element labeled "
+ "slot=\"button\", and a new one was not provided. This <selectmenu> "
+ "will not be fully functional."));
+ }
+
+ button_part_ = new_button_part;
+}
+
void HTMLSelectMenuElement::ButtonPartInserted(Element* new_button_part) {
if (!IsValidButtonPart(new_button_part, /*show_warning=*/true)) {
return;
}
- // TODO(crbug.com/1191121) Decide which part gets controller code when there
- // are multiple parts available.
- if (button_part_ != new_button_part) {
- if (button_part_) {
- button_part_->removeEventListener(event_type_names::kClick,
- button_part_listener_, false);
- }
- if (new_button_part) {
- new_button_part->addEventListener(event_type_names::kClick,
- button_part_listener_, false);
- }
- button_part_ = new_button_part;
- }
+ UpdateButtonPart();
}
void HTMLSelectMenuElement::ButtonPartRemoved(Element* button_part) {
@@ -367,64 +510,68 @@ void HTMLSelectMenuElement::ButtonPartRemoved(Element* button_part) {
return;
}
- button_part_->removeEventListener(event_type_names::kClick,
- button_part_listener_, false);
+ UpdateButtonPart();
+}
+
+void HTMLSelectMenuElement::UpdateButtonPart() {
+ SetButtonPart(FirstValidButtonPart());
+}
- // Try to find a new button part by choosing the one that comes first in the
- // flat tree traversal.
- Element* new_button_part = nullptr;
- for (Node* node = FlatTreeTraversal::FirstChild(*this); node != nullptr;
- node = FlatTreeTraversal::Next(*node, this)) {
+Element* HTMLSelectMenuElement::FirstValidSelectedValuePart() const {
+ for (Node* node = SelectMenuPartTraversal::FirstChild(*this); node;
+ node = SelectMenuPartTraversal::Next(*node, this)) {
auto* element = DynamicTo<Element>(node);
if (!element) {
continue;
}
- if (element->getAttribute(html_names::kPartAttr) == kButtonPartName &&
- IsValidButtonPart(element, /*show_warning=*/false)) {
- new_button_part = element;
- break;
+ if (element->getAttribute(html_names::kPartAttr) ==
+ kSelectedValuePartName) {
+ return element;
}
}
+ return nullptr;
+}
- if (new_button_part) {
- new_button_part->addEventListener(event_type_names::kClick,
- button_part_listener_, false);
- }
- button_part_ = new_button_part;
+HTMLSlotElement* HTMLSelectMenuElement::ButtonSlot() const {
+ return button_slot_;
+}
+
+HTMLSlotElement* HTMLSelectMenuElement::ListboxSlot() const {
+ return listbox_slot_;
}
void HTMLSelectMenuElement::SelectedValuePartInserted(
Element* new_selected_value_part) {
- // TODO(crbug.com/1191121) Decide which part gets controller code when there
- // are multiple parts available.
- selected_value_part_ = new_selected_value_part;
+ UpdateSelectedValuePart();
}
void HTMLSelectMenuElement::SelectedValuePartRemoved(
Element* selected_value_part) {
- if (selected_value_part_ != selected_value_part) {
+ if (selected_value_part != selected_value_part_) {
return;
}
+ UpdateSelectedValuePart();
+}
+
+void HTMLSelectMenuElement::UpdateSelectedValuePart() {
+ selected_value_part_ = FirstValidSelectedValuePart();
+}
- // Try to find a new selected value part by choosing the one that comes first
- // in the flat tree traversal.
- Element* new_selected_value_part = nullptr;
- for (Node* node = FlatTreeTraversal::FirstChild(*this); node != nullptr;
- node = FlatTreeTraversal::Next(*node, this)) {
+Element* HTMLSelectMenuElement::FirstValidListboxPart() const {
+ for (Node* node = SelectMenuPartTraversal::FirstChild(*this); node;
+ node = SelectMenuPartTraversal::Next(*node, this)) {
auto* element = DynamicTo<Element>(node);
if (!element) {
continue;
}
- if (element->getAttribute(html_names::kPartAttr) ==
- kSelectedValuePartName) {
- new_selected_value_part = element;
- break;
+ if (element->getAttribute(html_names::kPartAttr) == kListboxPartName &&
+ IsValidListboxPart(element, /*show_warning=*/false)) {
+ return element;
}
}
-
- selected_value_part_ = new_selected_value_part;
+ return nullptr;
}
void HTMLSelectMenuElement::ListboxPartInserted(Element* new_listbox_part) {
@@ -432,10 +579,7 @@ void HTMLSelectMenuElement::ListboxPartInserted(Element* new_listbox_part) {
return;
}
- // TODO(crbug.com/1191121) Decide which part gets controller code when there
- // are multiple parts available.
- SetListboxPart(DynamicTo<HTMLPopupElement>(new_listbox_part));
- // TODO(crbug.com/1121840) Should the current option parts be revalidated?
+ UpdateListboxPart();
}
void HTMLSelectMenuElement::ListboxPartRemoved(Element* listbox_part) {
@@ -443,24 +587,11 @@ void HTMLSelectMenuElement::ListboxPartRemoved(Element* listbox_part) {
return;
}
- // Try to find a new listbox part by choosing the one that comes first in the
- // flat tree traversal.
- Element* new_listbox_part = nullptr;
- for (Node* node = FlatTreeTraversal::FirstChild(*this); node != nullptr;
- node = FlatTreeTraversal::Next(*node, this)) {
- auto* element = DynamicTo<Element>(node);
- if (!element) {
- continue;
- }
-
- if (element->getAttribute(html_names::kPartAttr) == kListboxPartName &&
- IsValidListboxPart(element, /*show_warning=*/false)) {
- new_listbox_part = element;
- break;
- }
- }
+ UpdateListboxPart();
+}
- SetListboxPart(DynamicTo<HTMLPopupElement>(new_listbox_part));
+void HTMLSelectMenuElement::UpdateListboxPart() {
+ SetListboxPart(DynamicTo<HTMLPopupElement>(FirstValidListboxPart()));
// TODO(crbug.com/1121840) Should the current option parts be revalidated?
}
@@ -478,8 +609,8 @@ void HTMLSelectMenuElement::OptionPartInserted(Element* new_option_part) {
new_option_element->OptionInsertedIntoSelectMenuElement();
}
- new_option_part->addEventListener(event_type_names::kClick,
- option_part_listener_, false);
+ new_option_part->addEventListener(
+ event_type_names::kClick, option_part_listener_, /*use_capture=*/false);
// TODO(crbug.com/1121840) We don't want to actually change the attribute,
// and if tabindex is already set we shouldn't override it. So we need to
// come up with something else here.
@@ -526,8 +657,8 @@ Element* HTMLSelectMenuElement::FirstOptionPart() const {
// TODO(crbug.com/1121840) This is going to be replaced by an option part
// list iterator, or we could reuse OptionListIterator if we decide that just
// <option>s are supported as option parts.
- for (Node* node = FlatTreeTraversal::FirstChild(*this); node != nullptr;
- node = FlatTreeTraversal::Next(*node, this)) {
+ for (Node* node = SelectMenuPartTraversal::FirstChild(*this); node;
+ node = SelectMenuPartTraversal::Next(*node, this)) {
auto* element = DynamicTo<Element>(node);
if (!element) {
continue;
@@ -584,8 +715,8 @@ void HTMLSelectMenuElement::UpdateSelectedValuePartContents() {
void HTMLSelectMenuElement::ButtonPartEventListener::Invoke(ExecutionContext*,
Event* event) {
if (event->type() == event_type_names::kClick &&
- !select_menu_element_->IsOpen()) {
- select_menu_element_->Open();
+ !select_menu_element_->open()) {
+ select_menu_element_->OpenListbox();
}
}
@@ -601,14 +732,28 @@ void HTMLSelectMenuElement::OptionPartEventListener::Invoke(ExecutionContext*,
}
}
+void HTMLSelectMenuElement::SlotChangeEventListener::Invoke(ExecutionContext*,
+ Event* event) {
+ DCHECK_EQ(event->type(), event_type_names::kSlotchange);
+ if (event->target() == select_menu_element_->ListboxSlot()) {
+ select_menu_element_->UpdateListboxPart();
+ } else if (event->target() == select_menu_element_->ButtonSlot()) {
+ select_menu_element_->UpdateButtonPart();
+ select_menu_element_->UpdateSelectedValuePart();
+ }
+}
+
void HTMLSelectMenuElement::Trace(Visitor* visitor) const {
visitor->Trace(button_part_listener_);
visitor->Trace(option_part_listener_);
+ visitor->Trace(slotchange_listener_);
visitor->Trace(select_mutation_callback_);
visitor->Trace(button_part_);
visitor->Trace(selected_value_part_);
visitor->Trace(listbox_part_);
visitor->Trace(option_parts_);
+ visitor->Trace(button_slot_);
+ visitor->Trace(listbox_slot_);
visitor->Trace(selected_option_);
HTMLElement::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.h
index 8fedaeef8e0..7e2ce81dfd1 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.h
@@ -28,8 +28,7 @@ class HTMLSelectMenuElement final : public HTMLElement {
String value();
void setValue(const String&, bool send_events = false);
-
- bool IsOpen() const;
+ bool open() const;
void Trace(Visitor*) const override;
@@ -37,11 +36,16 @@ class HTMLSelectMenuElement final : public HTMLElement {
class SelectMutationCallback;
void DidAddUserAgentShadowRoot(ShadowRoot&) override;
- void Open();
- void Close();
+ void OpenListbox();
+ void CloseListbox();
void UpdatePartElements();
Element* FirstOptionPart() const;
+ Element* FirstValidButtonPart() const;
+ Element* FirstValidListboxPart() const;
+ Element* FirstValidSelectedValuePart() const;
+ HTMLSlotElement* ButtonSlot() const;
+ HTMLSlotElement* ListboxSlot() const;
void EnsureSelectedOptionIsValid();
Element* SelectedOption();
void SetSelectedOption(Element* selected_option);
@@ -49,10 +53,13 @@ class HTMLSelectMenuElement final : public HTMLElement {
void ButtonPartInserted(Element*);
void ButtonPartRemoved(Element*);
+ void UpdateButtonPart();
void SelectedValuePartInserted(Element*);
void SelectedValuePartRemoved(Element*);
+ void UpdateSelectedValuePart();
void ListboxPartInserted(Element*);
void ListboxPartRemoved(Element*);
+ void UpdateListboxPart();
void OptionPartInserted(Element*);
void OptionPartRemoved(Element*);
@@ -60,7 +67,8 @@ class HTMLSelectMenuElement final : public HTMLElement {
bool IsValidListboxPart(const Element* part, bool show_warning) const;
bool IsValidOptionPart(const Element* part, bool show_warning) const;
- void SetListboxPart(HTMLPopupElement* listbox_part);
+ void SetButtonPart(Element* new_button_part);
+ void SetListboxPart(HTMLPopupElement* new_listbox_part);
class ButtonPartEventListener : public NativeEventListener {
public:
@@ -92,6 +100,21 @@ class HTMLSelectMenuElement final : public HTMLElement {
Member<HTMLSelectMenuElement> select_menu_element_;
};
+ class SlotChangeEventListener : public NativeEventListener {
+ public:
+ explicit SlotChangeEventListener(HTMLSelectMenuElement* select_menu_element)
+ : select_menu_element_(select_menu_element) {}
+ void Invoke(ExecutionContext*, Event*) override;
+
+ void Trace(Visitor* visitor) const override {
+ visitor->Trace(select_menu_element_);
+ NativeEventListener::Trace(visitor);
+ }
+
+ private:
+ Member<HTMLSelectMenuElement> select_menu_element_;
+ };
+
static constexpr char kButtonPartName[] = "button";
static constexpr char kSelectedValuePartName[] = "selected-value";
static constexpr char kListboxPartName[] = "listbox";
@@ -99,6 +122,7 @@ class HTMLSelectMenuElement final : public HTMLElement {
Member<ButtonPartEventListener> button_part_listener_;
Member<OptionPartEventListener> option_part_listener_;
+ Member<SlotChangeEventListener> slotchange_listener_;
Member<SelectMutationCallback> select_mutation_callback_;
@@ -106,6 +130,8 @@ class HTMLSelectMenuElement final : public HTMLElement {
Member<Element> selected_value_part_;
Member<HTMLPopupElement> listbox_part_;
HeapLinkedHashSet<Member<Element>> option_parts_;
+ Member<HTMLSlotElement> button_slot_;
+ Member<HTMLSlotElement> listbox_slot_;
Member<Element> selected_option_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.idl b/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.idl
index b11883770f7..bf284ca07e8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_menu_element.idl
@@ -4,6 +4,8 @@
[Exposed=Window,HTMLConstructor,RuntimeEnabled=HTMLSelectMenuElement]
interface HTMLSelectMenuElement : HTMLElement {
+ readonly attribute boolean open;
+
attribute DOMString value;
// TODO(crbug.com/1121840) Fill this out.
// Open question: do we want to replicate the interface of
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 bb301489f2b..44daf89d5b5 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
@@ -72,8 +72,6 @@ class CORE_EXPORT HTMLTextAreaElement final : public TextControlElement {
enum WrapMethod { kNoWrap, kSoftWrap, kHardWrap };
void DidAddUserAgentShadowRoot(ShadowRoot&) override;
- // FIXME: Author shadows should be allowed
- // https://bugs.webkit.org/show_bug.cgi?id=92608
bool AreAuthorShadowsAllowed() const override { return false; }
void HandleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) const;
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 f70a84fce9b..eae70876639 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
@@ -107,12 +107,8 @@ void ImageInputType::HandleDOMActivateEvent(Event& event) {
LayoutObject* ImageInputType::CreateLayoutObject(const ComputedStyle& style,
LegacyLayout legacy) const {
- if (use_fallback_content_) {
- if (style.Display() == EDisplay::kInline)
- return new LayoutInline(&GetElement());
-
- return LayoutObjectFactory::CreateBlockFlow(GetElement(), style, legacy);
- }
+ if (use_fallback_content_)
+ return LayoutObject::CreateObject(&GetElement(), style, legacy);
LayoutImage* image = new LayoutImage(&GetElement());
image->SetImageResource(MakeGarbageCollected<LayoutImageResource>());
return image;
@@ -149,9 +145,6 @@ void ImageInputType::OnAttachWithLayoutObject() {
HTMLImageLoader& image_loader = GetElement().EnsureImageLoader();
image_loader.UpdateFromElement();
- LayoutImageResource* image_resource =
- To<LayoutImage>(layout_object)->ImageResource();
- image_resource->SetImageResource(image_loader.GetContent());
}
bool ImageInputType::ShouldRespectAlignAttribute() {
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 d88735fc31d..8637e84688a 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
@@ -33,7 +33,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_INPUT_TYPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_INPUT_TYPE_H_
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
#include "third_party/blink/renderer/core/html/forms/color_chooser_client.h"
@@ -56,6 +56,8 @@ class CORE_EXPORT InputType : public GarbageCollected<InputType> {
public:
static InputType* Create(HTMLInputElement&, const AtomicString&);
static const AtomicString& NormalizeTypeName(const AtomicString&);
+ InputType(const InputType&) = delete;
+ InputType& operator=(const InputType&) = delete;
virtual ~InputType();
virtual void Trace(Visitor*) const;
@@ -275,8 +277,6 @@ class CORE_EXPORT InputType : public GarbageCollected<InputType> {
bool supports_reversed_range) const;
Member<HTMLInputElement> element_;
-
- DISALLOW_COPY_AND_ASSIGN(InputType);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/input_type_view.h b/chromium/third_party/blink/renderer/core/html/forms/input_type_view.h
index 282e1ad1ab6..fa83959c1ad 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/input_type_view.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -33,7 +33,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_INPUT_TYPE_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_INPUT_TYPE_VIEW_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
@@ -75,6 +74,8 @@ class CORE_EXPORT InputTypeView : public GarbageCollectedMixin {
// Called by the owner HTMLInputElement when this InputType is disconnected
// from the HTMLInputElement.
void WillBeDestroyed();
+ InputTypeView(const InputTypeView&) = delete;
+ InputTypeView& operator=(const InputTypeView&) = delete;
virtual ~InputTypeView();
void Trace(Visitor*) const override;
@@ -157,8 +158,6 @@ class CORE_EXPORT InputTypeView : public GarbageCollectedMixin {
private:
Member<HTMLInputElement> element_;
-
- DISALLOW_COPY_AND_ASSIGN(InputTypeView);
};
} // namespace blink
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 118400626b9..8c28d6708dc 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
@@ -54,6 +54,10 @@ const char* TextTransformToString(ETextTransform transform) {
return getValueName(PlatformEnumToCSSValueID(transform));
}
+const char* TextAlignToString(ETextAlign align) {
+ return getValueName(PlatformEnumToCSSValueID(align));
+}
+
const String SerializeComputedStyleForProperty(const ComputedStyle& style,
CSSPropertyID id) {
const CSSProperty& property = CSSProperty::Get(id);
@@ -179,6 +183,9 @@ class InternalPopupMenu::ItemIterationContext {
AddProperty("textTransform",
String(TextTransformToString(BaseStyle().TextTransform())),
buffer_);
+ AddProperty("textAlign",
+ String(TextAlignToString(BaseStyle().GetTextAlign(false))),
+ buffer_);
AddProperty("fontSize", BaseFont().ComputedPixelSize(), buffer_);
AddProperty("fontStyle", String(FontStyleToString(BaseFont().Style())),
buffer_);
@@ -357,8 +364,6 @@ void InternalPopupMenu::WriteDocument(SharedBuffer* data) {
AddProperty("scaleFactor", scale_factor, data);
bool is_rtl = !owner_style->IsLeftToRightDirection();
AddProperty("isRTL", is_rtl, data);
- AddProperty("isFormControlsRefreshEnabled",
- features::IsFormControlsRefreshEnabled(), data);
AddProperty("paddingStart",
is_rtl ? owner_element.ClientPaddingRight().ToDouble()
: owner_element.ClientPaddingLeft().ToDouble(),
@@ -434,6 +439,10 @@ void InternalPopupMenu::AddElementStyle(ItemIterationContext& context,
AddProperty("textTransform",
String(TextTransformToString(style->TextTransform())), data);
}
+ if (base_style.GetTextAlign(false) != style->GetTextAlign(false)) {
+ AddProperty("textAlign",
+ String(TextAlignToString(style->GetTextAlign(false))), data);
+ }
PagePopupClient::AddString("},\n", data);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/listed_element.cc b/chromium/third_party/blink/renderer/core/html/forms/listed_element.cc
index a55a83f6742..f41608023ee 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/listed_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/listed_element.cc
@@ -51,6 +51,27 @@
namespace blink {
+namespace {
+
+void InvalidateShadowIncludingAncestorForms(ContainerNode& insertion_point) {
+ if (!RuntimeEnabledFeatures::AutofillShadowDOMEnabled())
+ return;
+
+ // Let any forms in the shadow including ancestors know that this
+ // ListedElement has changed. Don't include any forms inside the same
+ // TreeScope know because that relationship isn't tracked by listed elements
+ // including shadow trees.
+ for (ContainerNode* parent = insertion_point.OwnerShadowHost(); parent;
+ parent = parent->ParentOrShadowHostNode()) {
+ if (HTMLFormElement* form = DynamicTo<HTMLFormElement>(parent)) {
+ form->InvalidateListedElementsIncludingShadowTrees();
+ return;
+ }
+ }
+}
+
+} // namespace
+
class FormAttributeTargetObserver : public IdTargetObserver {
public:
FormAttributeTargetObserver(const AtomicString& id, ListedElement*);
@@ -123,6 +144,8 @@ void ListedElement::InsertedInto(ContainerNode& insertion_point) {
// Trigger for elements outside of forms.
if (!form_ && insertion_point.isConnected())
element.GetDocument().DidAssociateFormControl(&element);
+
+ InvalidateShadowIncludingAncestorForms(insertion_point);
}
void ListedElement::RemovedFrom(ContainerNode& insertion_point) {
@@ -156,6 +179,8 @@ void ListedElement::RemovedFrom(ContainerNode& insertion_point) {
.GetFormController()
.InvalidateStatefulFormControlList();
}
+
+ InvalidateShadowIncludingAncestorForms(insertion_point);
}
HTMLFormElement* ListedElement::FindAssociatedForm(
diff --git a/chromium/third_party/blink/renderer/core/html/forms/menu_list_inner_element.cc b/chromium/third_party/blink/renderer/core/html/forms/menu_list_inner_element.cc
index 66f27a6ef83..7e5eb9b612c 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/menu_list_inner_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/menu_list_inner_element.cc
@@ -62,14 +62,13 @@ scoped_refptr<ComputedStyle> MenuListInnerElement::CustomStyleForLayoutObject(
Length margin_end = Length::Fixed(
theme.PopupInternalPaddingEnd(GetDocument().GetFrame(), parent_style));
if (parent_style.IsLeftToRightDirection()) {
- style->SetTextAlign(ETextAlign::kLeft);
style->SetMarginLeft(margin_start);
style->SetMarginRight(margin_end);
} else {
- style->SetTextAlign(ETextAlign::kRight);
style->SetMarginLeft(margin_end);
style->SetMarginRight(margin_start);
}
+ style->SetTextAlign(parent_style.GetTextAlign(true));
style->SetPaddingTop(
Length::Fixed(theme.PopupInternalPaddingTop(parent_style)));
style->SetPaddingBottom(
diff --git a/chromium/third_party/blink/renderer/core/html/forms/month_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/month_input_type.cc
index 3596c9e2011..49c6515699b 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/month_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/month_input_type.cc
@@ -169,7 +169,7 @@ bool MonthInputType::IsValidFormat(bool has_year,
return has_year && has_month;
}
-String MonthInputType::AriaRoleForPickerIndicator() const {
+String MonthInputType::AriaLabelForPickerIndicator() const {
return GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_MONTH_PICKER);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/month_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/month_input_type.h
index f644caf60fe..15bb08df364 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/month_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/month_input_type.h
@@ -66,7 +66,7 @@ class MonthInputType final : public BaseTemporalInputType {
bool has_hour,
bool has_minute,
bool has_second) const override;
- String AriaRoleForPickerIndicator() const override;
+ String AriaLabelForPickerIndicator() const override;
};
} // namespace blink
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 31176b7fe90..9da054b792c 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
@@ -296,9 +296,8 @@ void MultipleFieldsTemporalInputTypeView::PickerIndicatorChooseValue(
if (input_type_->FormControlType() == input_type_names::kTime) {
if (date.ParseTime(value, 0, end) && end == value.length())
edit->SetOnlyTime(date);
- } else if (features::IsFormControlsRefreshEnabled() &&
- input_type_->FormControlType() ==
- input_type_names::kDatetimeLocal) {
+ } else if (input_type_->FormControlType() ==
+ input_type_names::kDatetimeLocal) {
if (date.ParseDateTimeLocal(value, 0, end) && end == value.length())
edit->SetDateTimeLocal(date);
} else {
@@ -347,8 +346,9 @@ void MultipleFieldsTemporalInputTypeView::DidEndChooser() {
GetElement().EnqueueChangeEvent();
}
-String MultipleFieldsTemporalInputTypeView::AriaRoleForPickerIndicator() const {
- return input_type_->AriaRoleForPickerIndicator();
+String MultipleFieldsTemporalInputTypeView::AriaLabelForPickerIndicator()
+ const {
+ return input_type_->AriaLabelForPickerIndicator();
}
MultipleFieldsTemporalInputTypeView::MultipleFieldsTemporalInputTypeView(
@@ -397,18 +397,6 @@ void MultipleFieldsTemporalInputTypeView::CreateShadowSubtree() {
MakeGarbageCollected<DateTimeEditElement, Document&,
DateTimeEditElement::EditControlOwner&>(document,
*this));
- if (!features::IsFormControlsRefreshEnabled()) {
- GetElement().UpdateView();
- container->AppendChild(
- MakeGarbageCollected<ClearButtonElement, Document&,
- ClearButtonElement::ClearButtonOwner&>(document,
- *this));
- container->AppendChild(
- MakeGarbageCollected<SpinButtonElement, Document&,
- SpinButtonElement::SpinButtonOwner&>(document,
- *this));
- }
-
if (LayoutTheme::GetTheme().SupportsCalendarPicker(
input_type_->FormControlType()))
picker_indicator_is_always_visible_ = true;
@@ -497,8 +485,7 @@ void MultipleFieldsTemporalInputTypeView::HandleKeydownEvent(
return;
if (picker_indicator_is_visible_ &&
((event.key() == "ArrowDown" && event.getModifierState("Alt")) ||
- (event.key() == "F4") ||
- (features::IsFormControlsRefreshEnabled() && event.key() == " "))) {
+ event.key() == "F4" || event.key() == " ")) {
if (PickerIndicatorElement* element = GetPickerIndicatorElement())
element->OpenPopup();
event.SetDefaultHandled();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.h b/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.h
index 98267a9af73..b4988f40a51 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.h
@@ -85,7 +85,7 @@ class MultipleFieldsTemporalInputTypeView final
Element& PickerOwnerElement() const final;
bool SetupDateTimeChooserParameters(DateTimeChooserParameters&) final;
void DidEndChooser() final;
- String AriaRoleForPickerIndicator() const final;
+ String AriaLabelForPickerIndicator() const final;
// ClearButtonElement::ClearButtonOwner functions.
void FocusAndSelectClearButtonOwner() override;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc
index 16a695818aa..864fb3176d7 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc
@@ -35,6 +35,7 @@
#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/node_computed_style.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/keyboard_event.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
diff --git a/chromium/third_party/blink/renderer/core/html/forms/password_input_type_test.cc b/chromium/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
deleted file mode 100644
index 025beb3b59f..00000000000
--- a/chromium/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
+++ /dev/null
@@ -1,89 +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/html/forms/password_input_type.h"
-
-#include <memory>
-#include <utility>
-
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.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/testing/dummy_page_holder.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-namespace blink {
-
-class MockInsecureInputService : public mojom::blink::InsecureInputService {
- public:
- explicit MockInsecureInputService(LocalFrame& frame) {
- frame.GetBrowserInterfaceBroker().SetBinderForTesting(
- mojom::blink::InsecureInputService::Name_,
- WTF::BindRepeating(&MockInsecureInputService::BindReceiver,
- WTF::Unretained(this)));
- }
-
- ~MockInsecureInputService() override = default;
-
- void BindReceiver(mojo::ScopedMessagePipeHandle handle) {
- receiver_set_.Add(this,
- mojo::PendingReceiver<mojom::blink::InsecureInputService>(
- std::move(handle)));
- }
-
- unsigned DidEditFieldCalls() const { return num_did_edit_field_calls_; }
-
- private:
- void DidEditFieldInInsecureContext() override { ++num_did_edit_field_calls_; }
-
- mojo::ReceiverSet<InsecureInputService> receiver_set_;
-
- unsigned num_did_edit_field_calls_ = 0;
-};
-
-// Tests that a Mojo message is sent when a password field is edited
-// on the page.
-TEST(PasswordInputTypeTest, DidEditFieldEvent) {
- auto page_holder = std::make_unique<DummyPageHolder>(IntSize(2000, 2000));
- MockInsecureInputService mock_service(page_holder->GetFrame());
- page_holder->GetDocument().body()->setInnerHTML("<input type='password'>");
- page_holder->GetDocument().View()->UpdateAllLifecyclePhasesForTest();
- blink::test::RunPendingTasks();
- EXPECT_EQ(0u, mock_service.DidEditFieldCalls());
- // Simulate a text field edit.
- page_holder->GetDocument().MaybeQueueSendDidEditFieldInInsecureContext();
- blink::test::RunPendingTasks();
- EXPECT_EQ(1u, mock_service.DidEditFieldCalls());
- // Ensure additional edits do not trigger additional notifications.
- page_holder->GetDocument().MaybeQueueSendDidEditFieldInInsecureContext();
- blink::test::RunPendingTasks();
- EXPECT_EQ(1u, mock_service.DidEditFieldCalls());
-}
-
-// Tests that a Mojo message is not sent when a password field is edited
-// in a secure context.
-TEST(PasswordInputTypeTest, DidEditFieldEventNotSentFromSecureContext) {
- auto page_holder = std::make_unique<DummyPageHolder>(IntSize(2000, 2000));
- page_holder->GetFrame().Loader().CommitNavigation(
- WebNavigationParams::CreateWithHTMLBufferForTesting(
- SharedBuffer::Create(), KURL("https://example.test")),
- nullptr /* extra_data */);
- blink::test::RunPendingTasks();
- MockInsecureInputService mock_service(page_holder->GetFrame());
- page_holder->GetDocument().body()->setInnerHTML("<input type='password'>");
- page_holder->GetDocument().View()->UpdateAllLifecyclePhasesForTest();
- // Simulate a text field edit.
- page_holder->GetDocument().MaybeQueueSendDidEditFieldInInsecureContext();
- // No message should have been sent from a secure context.
- blink::test::RunPendingTasks();
- EXPECT_EQ(0u, mock_service.DidEditFieldCalls());
-}
-
-} // namespace blink
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 4ae4dabac82..d48c20825c8 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
@@ -51,13 +51,6 @@ PickerIndicatorElement::PickerIndicatorElement(
picker_indicator_owner_(&picker_indicator_owner) {
SetShadowPseudoId(AtomicString("-webkit-calendar-picker-indicator"));
setAttribute(html_names::kIdAttr, shadow_element_names::kIdPickerIndicator);
- if (!features::IsFormControlsRefreshEnabled()) {
- setAttribute(html_names::kStyleAttr,
- "display:list-item; list-style:disclosure-open inside; "
- "block-size:1em;");
- // Do not expose list-item role.
- setAttribute(html_names::kAriaHiddenAttr, "true");
- }
}
PickerIndicatorElement::~PickerIndicatorElement() {
@@ -109,8 +102,7 @@ void PickerIndicatorElement::DidChooseValue(double value) {
void PickerIndicatorElement::DidEndChooser() {
chooser_.Clear();
picker_indicator_owner_->DidEndChooser();
- if (::features::IsFormControlsRefreshEnabled() &&
- OwnerElement().GetLayoutObject()) {
+ if (OwnerElement().GetLayoutObject()) {
// Invalidate paint to ensure that the focus ring is shown.
OwnerElement().GetLayoutObject()->SetShouldDoFullPaintInvalidation();
}
@@ -128,8 +120,7 @@ void PickerIndicatorElement::OpenPopup() {
return;
chooser_ = GetDocument().GetPage()->GetChromeClient().OpenDateTimeChooser(
GetDocument().GetFrame(), this, parameters);
- if (::features::IsFormControlsRefreshEnabled() &&
- OwnerElement().GetLayoutObject()) {
+ if (OwnerElement().GetLayoutObject()) {
// Invalidate paint to ensure that the focus ring is removed.
OwnerElement().GetLayoutObject()->SetShouldDoFullPaintInvalidation();
}
@@ -184,7 +175,7 @@ void PickerIndicatorElement::DidNotifySubtreeInsertionsToDocument() {
setAttribute(
html_names::kAriaLabelAttr,
AtomicString(
- this->picker_indicator_owner_->AriaRoleForPickerIndicator()));
+ this->picker_indicator_owner_->AriaLabelForPickerIndicator()));
}
void PickerIndicatorElement::Trace(Visitor* visitor) const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.h b/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.h
index 058f4bb5f11..42f239a62b5 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.h
@@ -52,7 +52,7 @@ class PickerIndicatorElement final : public HTMLDivElement,
virtual Element& PickerOwnerElement() const = 0;
virtual bool SetupDateTimeChooserParameters(DateTimeChooserParameters&) = 0;
virtual void DidEndChooser() = 0;
- virtual String AriaRoleForPickerIndicator() const = 0;
+ virtual String AriaLabelForPickerIndicator() const = 0;
};
PickerIndicatorElement(Document&, PickerIndicatorOwner&);
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 2a4bbe5c47c..e1d0d6bdd3b 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
@@ -215,7 +215,8 @@ void RadioButtonGroupScope::UpdateCheckedState(HTMLInputElement* element) {
DCHECK(name_to_group_map_);
if (!name_to_group_map_)
return;
- RadioButtonGroup* group = name_to_group_map_->at(element->GetName());
+ RadioButtonGroup* group =
+ name_to_group_map_->DeprecatedAtOrEmptyValue(element->GetName());
DCHECK(group);
group->UpdateCheckedState(element);
}
@@ -228,7 +229,8 @@ void RadioButtonGroupScope::RequiredAttributeChanged(
DCHECK(name_to_group_map_);
if (!name_to_group_map_)
return;
- RadioButtonGroup* group = name_to_group_map_->at(element->GetName());
+ RadioButtonGroup* group =
+ name_to_group_map_->DeprecatedAtOrEmptyValue(element->GetName());
DCHECK(group);
group->RequiredAttributeChanged(element);
}
@@ -237,7 +239,7 @@ HTMLInputElement* RadioButtonGroupScope::CheckedButtonForGroup(
const AtomicString& name) const {
if (!name_to_group_map_)
return nullptr;
- RadioButtonGroup* group = name_to_group_map_->at(name);
+ RadioButtonGroup* group = name_to_group_map_->DeprecatedAtOrEmptyValue(name);
return group ? group->CheckedButton() : nullptr;
}
@@ -247,7 +249,8 @@ bool RadioButtonGroupScope::IsInRequiredGroup(HTMLInputElement* element) const {
return false;
if (!name_to_group_map_)
return false;
- RadioButtonGroup* group = name_to_group_map_->at(element->GetName());
+ RadioButtonGroup* group =
+ name_to_group_map_->DeprecatedAtOrEmptyValue(element->GetName());
return group && group->IsRequired() && group->Contains(element);
}
@@ -256,7 +259,8 @@ unsigned RadioButtonGroupScope::GroupSizeFor(
if (!name_to_group_map_)
return 0;
- RadioButtonGroup* group = name_to_group_map_->at(element->GetName());
+ RadioButtonGroup* group =
+ name_to_group_map_->DeprecatedAtOrEmptyValue(element->GetName());
if (!group)
return 0;
return group->size();
@@ -269,7 +273,8 @@ void RadioButtonGroupScope::RemoveButton(HTMLInputElement* element) {
if (!name_to_group_map_)
return;
- RadioButtonGroup* group = name_to_group_map_->at(element->GetName());
+ RadioButtonGroup* group =
+ name_to_group_map_->DeprecatedAtOrEmptyValue(element->GetName());
if (!group)
return;
group->Remove(element);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py b/chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py
index 26b84f5fb5d..af7341a68a9 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py
@@ -3,6 +3,9 @@
# found in the LICENSE file.
+USE_PYTHON3 = True
+
+
def _CheckChangeOnUploadOrCommit(input_api, output_api):
return input_api.canned_checks.CheckPatchFormatted(
input_api, output_api, check_js=True)
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.css
index 18ad0d5b3b0..b29c2520313 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.css
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.css
@@ -64,8 +64,8 @@ body {
box-sizing: border-box;
display: inline-block;
cursor: default;
- transition: color 1s;
padding: 1px;
+ transition: color 0s;
}
.week-number-cell {
@@ -74,10 +74,19 @@ body {
padding-right: 0;
box-shadow: 1px 0 0 #bfbfbf;
margin-right: 1px;
+ border: 1px solid transparent !important;
}
.day-cell {
- color: #bfbfbf;
+ background-color: #ffffff;
+ border: 1px solid transparent !important;
+ border-radius: 2px;
+ color: #767676;
+ padding: 1px !important;
+}
+
+.day-cell.current-month {
+ color: #101010;
}
.day-cell.highlighted.today,
@@ -86,6 +95,11 @@ body {
padding: 0;
}
+.day-cell.today,
+.month-button.today {
+ border-color: #767676 !important;
+}
+
.week-number-cell.highlighted,
.day-cell.highlighted {
background-color: #e5ecf8;
@@ -97,23 +111,35 @@ body {
padding: 0;
}
-.week-number-cell.selected,
-.day-cell.selected {
- background-color: #bccdec;
+.day-cell.selected,
+.month-button.selected,
+.week-number-cell.selected {
+ background-color: #0075FF;
+ color: #FFFFFF;
+ font-weight: bold;
}
+
.week-number-cell.disabled,
.day-cell.disabled {
- background-color: #f5f5f5;
pointer-events: none;
}
-.day-cell.current-month {
- color: #000000;
+.month-button[aria-disabled="true"] {
+ color: GrayText;
+ pointer-events: none;
+}
+
+.day-cell.disabled,
+.day-cell.disabled.today,
+.month-button[aria-disabled="true"],
+.week-number-cell.disabled {
+ background-color: #FFFFFF;
+ color: rgba(16, 16, 16, 0.3);
}
.calendar-table-view {
- border: 1px solid #bfbfbf;
+ border: 0;
outline: none;
}
@@ -126,15 +152,19 @@ body {
box-sizing: padding-box;
}
+.week-day-label {
+ line-height: 28px;
+}
+
.week-number-label {
box-sizing: border-box;
border-right: 1px solid #bfbfbf;
}
.calendar-table-header-view {
- background-color: #f5f5f5;
- border-bottom: 1px solid #bfbfbf;
- height: 24px;
+ background-color: #ffffff;
+ border: 0;
+ height: 29px;
}
.calendar-picker {
@@ -154,7 +184,7 @@ body {
}
.calendar-title {
- -webkit-align-self: center;
+ -webkit-align-self: flex-start;
flex: 1;
text-align: left;
}
@@ -163,6 +193,16 @@ body {
text-align: right;
}
+.month-popup-button {
+ font-size: 12px;
+ display: inline-block;
+ cursor: default;
+ height: 24px !important;
+ border: 0 !important;
+ font-weight: bold;
+ padding: 0;
+}
+
.month-popup-button,
.month-popup-button:hover,
.month-popup-button:disabled {
@@ -174,54 +214,72 @@ body {
.month-popup-button:disabled {
opacity: 0.7;
+ background-color: #FFFFFF;
+ color: rgba(16, 16, 16, 0.3);
}
-.month-popup-button {
- font-size: 12px;
- padding: 4px;
- display: inline-block;
- cursor: default;
- border: 1px solid transparent !important;
- height: 24px !important;
+.month-popup-button:disabled polygon {
+ fill: rgba(16, 16, 16, 0.3) !important;
+}
+
+.month-button:hover {
+ background-color: rgba(0, 117, 255, 0.3);
+}
+
+.month-popup-button:focus {
+ outline: auto 1px -webkit-focus-ring-color !important;
}
.month-popup-button .disclosure-triangle {
- margin: 0 6px;
+ margin: 0;
+ margin-inline-start: 4px;
+ margin-inline-end: 1px;
}
.month-popup-button .disclosure-triangle svg {
padding-bottom: 2px;
}
-.today-button::after {
- content: "";
- display: block;
- border-radius: 3px;
- width: 6px;
- height: 6px;
- background-color: #6e6e6e;
- margin: 0 auto;
-}
-
.calendar-navigation-button {
-webkit-align-self: center;
- width: 24px;
+ width: 28px;
height: 24px;
min-width: 0 !important;
+ padding: 0;
padding-left: 0 !important;
padding-right: 0 !important;
margin-inline-start: 4px !important;
+ background-color: #ffffff;
+ border: 1px solid transparent;
+ color: #101010;
+ text-align: center;
+}
+
+.calendar-navigation-button svg {
+ padding-top: 4px;
+}
+
+.calendar-navigation-button:hover {
+ background-color: rgba(0, 117, 255, 0.3);
+}
+
+.calendar-navigation-button:disabled {
+ background-color: #FFFFFF;
+}
+
+.calendar-navigation-button:disabled path {
+ fill: rgba(16, 16, 16, 0.3);
}
.year-list-view {
- border: 1px solid #bfbfbf;
+ border: 0;
background-color: white;
position: absolute;
}
.year-list-cell {
box-sizing: border-box;
- border-bottom: 1px solid #bfbfbf;
+ border: 0;
background-color: white;
overflow: hidden;
}
@@ -230,8 +288,9 @@ body {
height: 24px;
line-height: 24px;
padding-inline-start: 8px;
- background-color: #f5f5f5;
- border-bottom: 1px solid #bfbfbf;
+ border-bottom: 1px solid #CECECE;
+ background-color: #EFEFEF;
+ margin-bottom: 1px;
}
.year-list-cell .month-chooser {
@@ -250,31 +309,28 @@ body {
margin: 0 !important;
background-image: none !important;
background-color: #ffffff;
- border-width: 0 !important;
box-shadow: none !important;
text-align: center;
+ border: 1px solid transparent !important;
+ border-radius: 2px;
+ color: #101010;
}
.month-button.highlighted {
background-color: #e5ecf8;
}
-.month-button[aria-disabled="true"] {
- color: GrayText;
- pointer-events: none;
-}
-
.scrubby-scroll-bar {
width: 14px;
height: 60px;
background-color: white;
- border-left: 1px solid #bfbfbf;
+ border: 0;
position: absolute;
top: 0;
}
.scrubby-scroll-thumb {
- width: 10px;
+ width: 4px;
margin: 2px;
height: 30px;
background-color: #d8d8d8;
@@ -324,3 +380,412 @@ body {
.preparing .calendar-table-view:focus {
transition: none;
}
+
+/*
+* Highlight-when-hovered for day cells except if this is a week picker
+*/
+:not(.week-picker) > .calendar-table-view > .scroll-view > .scroll-view-content
+ > .calendar-row-cell > .day-cell:not(.selected):hover {
+ background-color: rgba(0, 117, 255, 0.3);
+}
+
+/*
+* Highlight-when-hovered for the week picker:
+* 1. Highlight the week number cell for the hovered week.
+* 2. If the first date column is Monday, highlight all cells in the row
+* because the week picker considers Monday to be the first day
+* of the week regardless of locale.
+* 3a. If the first date column is Sunday, highlight all cells in the hovered
+* row except for Sunday, because Sunday belongs to the previous week.
+* 3b. If the first date column is Sunday, highlight Sunday of the row after
+* the hovered row, because that Sunday belongs to the hovered week.
+*/
+.calendar-row-cell:hover .week-number-cell:not(.selected):not(.disabled),
+.week-picker .calendar-row-cell:not(.week-starts-on-sunday):hover
+ .day-cell:not(.selected):not(.disabled),
+.week-picker .calendar-row-cell.week-starts-on-sunday:hover
+ .day-cell:not(.selected):not(.disabled):not(:nth-child(2)),
+.week-picker .calendar-row-cell.week-starts-on-sunday:hover + .calendar-row-cell
+ .day-cell:not(.selected):not(.disabled):nth-child(2) {
+ background-color: rgba(0, 117, 255, 0.3);
+}
+
+.calendar-table-view:focus .day-cell.selected,
+.year-list-view:focus .month-button.selected,
+.calendar-table-view:focus .week-number-cell.selected {
+ outline: solid 2px -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.clear-button, .today-button {
+ -webkit-align-self: center;
+ background-color: #ffffff;
+ border: 1px solid transparent;
+ bottom: 12px;
+ color: #0078D4;
+ font-size: 12px;
+ height: 20px;
+ padding: 4px 0 4px 0;
+ position: absolute;
+ text-align: center;
+ width: auto;
+}
+
+.clear-button {
+ left: 20px;
+ margin-inline-end: 4px !important;
+}
+
+.today-button {
+ right: 20px;
+}
+
+.clear-button:hover,
+.today-button:hover {
+ background-color: rgba(0, 117, 255, 0.3);
+}
+
+.today-button:disabled {
+ background-color: #FFFFFF;
+ color: rgba(16, 16, 16, 0.3);
+}
+
+.datetimelocal-picker .calendar-picker {
+ border: 0;
+ border-right: 1px solid #CECECE;
+}
+
+.datetimelocal-picker .time-picker {
+ border: 0;
+ height: 254px;
+ position: absolute;
+ right: 3px;
+ top: 12px;
+}
+
+/* These forced colors mode styles override the default styling for elements
+ * when forced colors mode is enabled.
+ */
+@media (forced-colors: active) {
+ .calendar-navigation-button {
+ background-color: Window;
+ color: WindowText;
+ forced-color-adjust: none;
+ }
+
+ .calendar-navigation-button:hover {
+ background-color: Window;
+ border-color: Highlight;
+ }
+
+ .calendar-navigation-button:disabled {
+ background-color: Window;
+ border-color: transparent;
+ }
+
+ .calendar-navigation-button path {
+ fill: WindowText;
+ }
+
+ .calendar-navigation-button:disabled path {
+ fill: GrayText;
+ }
+
+ .month-popup-button,
+ .month-popup-button:hover,
+ .month-popup-button:disabled {
+ background-color: Canvas;
+ color: CanvasText;
+ forced-color-adjust: none;
+ opacity: 1.0;
+ }
+
+ .month-popup-button:disabled {
+ color: GrayText !important;
+ }
+
+ .month-popup-button polygon {
+ fill: WindowText !important;
+ }
+
+ .month-popup-button:disabled polygon {
+ fill: GrayText !important;
+ }
+
+ .week-number-cell {
+ background-color: Window;
+ color: WindowText;
+ forced-color-adjust: none;
+ }
+
+ .day-cell {
+ background-color: Window;
+ color: GrayText;
+ forced-color-adjust: none;
+ }
+
+ .month-button {
+ background-color: Window;
+ color: WindowText;
+ forced-color-adjust: none;
+ }
+
+ .day-cell.current-month {
+ color: WindowText;
+ }
+
+ /*
+ * Highlight-when-hovered for cells in the month picker menu and standalone
+ * month control
+ */
+ .month-button:not(.selected):hover {
+ background-color: Window !important;
+ border-color: Highlight !important;
+ }
+
+ /*
+ * Highlight-when-hovered for day cells except if this is a week picker
+ */
+ :not(.week-picker) > .calendar-table-view > .scroll-view > .scroll-view-content
+ > .calendar-row-cell > .day-cell:not(.selected):hover {
+ background-color: Window !important;
+ border-color: Highlight !important;
+ }
+
+
+ /*
+ * Highlight-when-hovered for the week picker:
+ * 1. Highlight the week number cell for the hovered week.
+ * 2. If the first date column is Monday, highlight all cells in the row
+ * because the week picker considers Monday to be the first day
+ * of the week regardless of locale.
+ * 3a. If the first date column is Sunday, highlight all cells in the hovered
+ * row except for Sunday, because Sunday belongs to the previous week.
+ * 3b. If the first date column is Sunday, highlight Sunday of the row after
+ * the hovered row, because that Sunday belongs to the hovered week.
+ */
+ .calendar-row-cell:hover .week-number-cell:not(.selected):not(.disabled),
+ .week-picker .calendar-row-cell:not(.week-starts-on-sunday):hover
+ .day-cell:not(.selected):not(.disabled),
+ .week-picker .calendar-row-cell.week-starts-on-sunday:hover
+ .day-cell:not(.selected):not(.disabled):not(:nth-child(2)),
+ .week-picker .calendar-row-cell.week-starts-on-sunday:hover + .calendar-row-cell
+ .day-cell:not(.selected):not(.disabled):nth-child(2) {
+ border-color: Highlight !important;
+ background-color: Window !important;
+ }
+
+ .day-cell.selected,
+ .month-button.selected,
+ .week-number-cell.selected {
+ background-color: Highlight;
+ color: Window;
+ }
+
+ .calendar-table-view:focus .day-cell.selected,
+ .year-list-view:focus .month-button.selected,
+ .calendar-table-view:focus .week-number-cell.selected {
+ outline: none;
+ }
+
+ .day-cell.today,
+ .month-button.today {
+ border-color: WindowText !important;
+ }
+
+ .day-cell.disabled,
+ .day-cell.disabled.today,
+ .month-button[aria-disabled="true"],
+ .week-number-cell.disabled {
+ background-color: Window;
+ border: 0 !important;
+ color: GrayText;
+ }
+
+ .clear-button,
+ .today-button {
+ background-color: Window;
+ color: LinkText;
+ forced-color-adjust: none;
+ }
+
+ .clear-button:hover,
+ .today-button:hover {
+ background-color: Window;
+ border-color: Highlight;
+ }
+
+ .today-button:disabled {
+ background-color: Window;
+ border-color: transparent;
+ color: GrayText;
+ forced-color-adjust: none;
+ }
+
+ .scrubby-scroll-thumb {
+ background-color: WindowText;
+ forced-color-adjust: none;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ .calendar-picker {
+ background-color: #3B3B3B;
+ color:#ffffff;
+ border: 1px solid #858585;
+ }
+
+ .disclosure-triangle polygon,
+ .month-popup-button .disclosure-triangle polygon {
+ fill: #FFFFFF !important;
+ }
+
+ .calendar-table-header-view {
+ background-color: #3B3B3B;
+ }
+
+ .calendar-navigation-button {
+ background-color: #3B3B3B;
+ color: #ffffff;
+ }
+
+ .calendar-navigation-button:hover {
+ background-color: #545454;
+ }
+
+ .calendar-navigation-button:disabled {
+ background-color: #3B3B3B;
+ }
+
+ .month-popup-button:disabled {
+ background-color: #3B3B3B;
+ color: rgba(255, 255, 255, 0.3);
+ }
+
+ .week-number-cell,
+ .day-cell {
+ background-color: #3B3B3B;
+ color: #FFFFFF;
+ }
+
+ .day-cell.current-month {
+ color: #ffffff;
+ }
+
+ .month-button:hover {
+ background-color: #D1E6FF;
+ color: #3B3B3B;
+ }
+
+ :not(.week-picker) > .calendar-table-view > .scroll-view > .scroll-view-content
+ > .calendar-row-cell > .day-cell:not(.selected):hover {
+ background-color: #D1E6FF;
+ color: #3B3B3B;
+ }
+
+ /*
+ * Highlight-when-hovered for the week picker:
+ * 1. Highlight the week number cell for the hovered week.
+ * 2. If the first date column is Monday, highlight all cells in the row
+ * because the week picker considers Monday to be the first day
+ * of the week regardless of locale.
+ * 3a. If the first date column is Sunday, highlight all cells in the hovered
+ * row except for Sunday, because Sunday belongs to the previous week.
+ * 3b. If the first date column is Sunday, highlight Sunday of the row after
+ * the hovered row, because that Sunday belongs to the hovered week.
+ */
+ .calendar-row-cell:hover .week-number-cell:not(.selected):not(.disabled),
+ .week-picker .calendar-row-cell:not(.week-starts-on-sunday):hover
+ .day-cell:not(.selected):not(.disabled),
+ .week-picker .calendar-row-cell.week-starts-on-sunday:hover
+ .day-cell:not(.selected):not(.disabled):not(:nth-child(2)),
+ .week-picker .calendar-row-cell.week-starts-on-sunday:hover + .calendar-row-cell
+ .day-cell:not(.selected):not(.disabled):nth-child(2) {
+ background-color: #D1E6FF;
+ color: #3B3B3B;
+ }
+
+ .calendar-table-view:focus .day-cell.selected,
+ .year-list-view:focus .month-button.selected,
+ .calendar-table-view:focus .week-number-cell.selected {
+ outline: solid 1px #FFFFFF;
+ outline-offset: -1px;
+ }
+
+ .day-cell.selected,
+ .month-button.selected,
+ .week-number-cell.selected {
+ background-color: #99C8FF;
+ color: #3B3B3B;
+ border-color: #FFFFFF;
+ }
+
+ .day-cell.disabled,
+ .day-cell.disabled.today,
+ .month-button[aria-disabled="true"],
+ .week-number-cell.disabled {
+ background-color: #3B3B3B;
+ color: rgba(255, 255, 255, 0.3);
+ }
+
+ .clear-button,
+ .today-button {
+ background-color: #3B3B3B;
+ color: #99C8FF;
+ }
+
+ .clear-button:hover,
+ .today-button:hover {
+ color: #D1E6FF;
+ background-color: #545454;
+ }
+
+ .today-button:disabled {
+ color: rgba(255, 255, 255, 0.3);
+ }
+
+ .year-list-cell .label {
+ background-color: #3B3B3B;
+ color: #ffffff;
+ }
+
+ body {
+ background-color: #3B3B3B;
+ }
+
+ .month-popup-button,
+ .month-popup-button:hover,
+ .month-popup-button:disabled {
+ color: #ffffff;
+ }
+
+ .scrubby-scroll-bar {
+ background-color: #3B3B3B;
+ border-left: 1px solid #3B3B3B;
+ }
+
+ .scrubby-scroll-thumb {
+ background-color: #d8d8d8;
+ }
+
+ .calendar-navigation-button path {
+ fill: #ffffff;
+ }
+
+ .month-popup-button polygon {
+ fill: #ffffff;
+ }
+
+ .month-popup-button:disabled polygon {
+ fill: #ffffff;
+ }
+
+ .year-list-cell .month-chooser {
+ background-color: #3B3B3B;
+ }
+
+ .month-button {
+ background-color: #3B3B3B;
+ color: #ffffff;
+ }
+}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
index b3cdaae92d0..5451fc02a7a 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
@@ -58,7 +58,6 @@ var global = {
'Nov', 'Dec'
],
isLocaleRTL: false,
- isFormControlsRefreshEnabled: false,
isBorderTransparent: false,
mode: 'date',
isAMPMFirst: false,
@@ -1011,22 +1010,17 @@ function closePicker() {
function openSuggestionPicker() {
closePicker();
- if (global.params.isFormControlsRefreshEnabled) {
- document.body.classList.add('controls-refresh');
- }
global.picker = new SuggestionPicker($('main'), global.params);
};
function openCalendarPicker() {
closePicker();
- if (global.params.isFormControlsRefreshEnabled) {
- if (global.params.mode == 'month') {
- return initializeMonthPicker(global.params);
- } else if (global.params.mode == 'time') {
- return initializeTimePicker(global.params);
- } else if (global.params.mode == 'datetime-local') {
- return initializeDateTimeLocalPicker(global.params);
- }
+ if (global.params.mode == 'month') {
+ return initializeMonthPicker(global.params);
+ } else if (global.params.mode == 'time') {
+ return initializeTimePicker(global.params);
+ } else if (global.params.mode == 'datetime-local') {
+ return initializeDateTimeLocalPicker(global.params);
}
global.picker = new CalendarPicker(global.params.mode, global.params);
@@ -1816,14 +1810,10 @@ ListCell.prototype.setSelected = function(selected) {
this._selected = selected;
if (this._selected) {
this.element.classList.add('selected');
- if (global.params.isFormControlsRefreshEnabled) {
- this.element.setAttribute('aria-selected', true);
- }
+ this.element.setAttribute('aria-selected', true);
} else {
this.element.classList.remove('selected');
- if (global.params.isFormControlsRefreshEnabled) {
- this.element.setAttribute('aria-selected', false);
- }
+ this.element.setAttribute('aria-selected', false);
}
};
@@ -2513,22 +2503,15 @@ function YearListCell(shortMonthLabels) {
YearListCell.prototype = Object.create(ListCell.prototype);
YearListCell._Height = hasInaccuratePointingDevice() ? 31 : 25;
-YearListCell._HeightRefresh = 25;
+YearListCell._Height = 25;
YearListCell.GetHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return YearListCell._HeightRefresh;
- }
return YearListCell._Height;
};
YearListCell.BorderBottomWidth = 1;
YearListCell.ButtonRows = 3;
YearListCell.ButtonColumns = 4;
-YearListCell._SelectedHeight = hasInaccuratePointingDevice() ? 127 : 121;
-YearListCell._SelectedHeightRefresh = 128;
+YearListCell._SelectedHeight = 128;
YearListCell.GetSelectedHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return YearListCell._SelectedHeightRefresh;
- }
return YearListCell._SelectedHeight;
};
YearListCell.ClassNameYearListCell = 'year-list-cell';
@@ -2594,12 +2577,6 @@ function YearListView(minimumMonth, maximumMonth, config) {
/**
* @type {?Month}
*/
- if (!global.params.isFormControlsRefreshEnabled) {
- this.highlightedMonth = null;
- }
- /**
- * @type {?Month}
- */
this._selectedMonth = null;
/**
* @type {!Month}
@@ -2646,14 +2623,8 @@ function YearListView(minimumMonth, maximumMonth, config) {
this.scrubbyScrollBar.attachTo(this);
this.element.addEventListener('keydown', this.onKeyDown, false);
- if (!global.params.isFormControlsRefreshEnabled) {
- this.element.addEventListener('mouseover', this.onMouseOver, false);
- this.element.addEventListener('mouseout', this.onMouseOut, false);
- this.element.addEventListener('touchstart', this.onTouchStart, false);
- }
- if (global.params.isFormControlsRefreshEnabled && config &&
- config.mode == 'month') {
+ if (config && config.mode == 'month') {
this.type = 'month';
this._dateTypeConstructor = Month;
@@ -2674,7 +2645,7 @@ function YearListView(minimumMonth, maximumMonth, config) {
}
this._initialSelectedMonth = this._selectedMonth;
- } else if (global.params.isFormControlsRefreshEnabled) {
+ } else {
// This is a month switcher menu embedded in another calendar control.
// Set up our config so that getNearestValidRangeLookingForward(Backward)
// when called on this YearListView will navigate by month.
@@ -2690,65 +2661,16 @@ function YearListView(minimumMonth, maximumMonth, config) {
YearListView.prototype = Object.create(ListView.prototype);
Object.assign(YearListView.prototype, DateRangeManager);
-YearListView._Height = YearListCell._SelectedHeight - 1;
-YearListView._VisibleYearsRefresh = 4;
-YearListView._HeightRefresh = YearListCell._SelectedHeightRefresh - 1 +
- YearListView._VisibleYearsRefresh * YearListCell._HeightRefresh;
+YearListView._VisibleYears = 4;
+YearListView._Height = YearListCell._SelectedHeight - 1 +
+ YearListView._VisibleYears * YearListCell._Height;
YearListView.GetHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return YearListView._HeightRefresh;
- }
return YearListView._Height;
};
YearListView.EventTypeYearListViewDidHide = 'yearListViewDidHide';
YearListView.EventTypeYearListViewDidSelectMonth = 'yearListViewDidSelectMonth';
/**
- * @param {?Event} event
- */
-YearListView.prototype.onTouchStart = function(event) {
- var touch = event.touches[0];
- var monthButtonElement = enclosingNodeOrSelfWithClass(
- touch.target, YearListCell.ClassNameMonthButton);
- if (!monthButtonElement)
- return;
- var cellElement = enclosingNodeOrSelfWithClass(
- monthButtonElement, YearListCell.ClassNameYearListCell);
- var cell = cellElement.$view;
- this.highlightMonth(
- new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
-};
-
-/**
- * @param {?Event} event
- */
-YearListView.prototype.onMouseOver = function(event) {
- var monthButtonElement = enclosingNodeOrSelfWithClass(
- event.target, YearListCell.ClassNameMonthButton);
- if (!monthButtonElement)
- return;
- var cellElement = enclosingNodeOrSelfWithClass(
- monthButtonElement, YearListCell.ClassNameYearListCell);
- var cell = cellElement.$view;
- this.highlightMonth(
- new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
- this._ignoreMouseOutUntillNextMouseOver = false;
-};
-
-/**
- * @param {?Event} event
- */
-YearListView.prototype.onMouseOut = function(event) {
- if (this._ignoreMouseOutUntillNextMouseOver)
- return;
- var monthButtonElement = enclosingNodeOrSelfWithClass(
- event.target, YearListCell.ClassNameMonthButton);
- if (!monthButtonElement) {
- this.dehighlightMonth();
- }
-};
-
-/**
* @param {!number} width Width in pixels.
* @override
*/
@@ -2836,11 +2758,6 @@ YearListView.prototype.onClick = function(event) {
if (this.selectedRow !== oldSelectedRow) {
// Always start with first month when changing the year.
const month = new Month(year, 0);
- if (!global.params.isFormControlsRefreshEnabled) {
- this.highlightMonth(month);
- this.dispatchEvent(
- YearListView.EventTypeYearListViewDidSelectMonth, this, month);
- }
this.scrollView.scrollTo(this.selectedRow * YearListCell.GetHeight(), true);
} else {
var monthButton = enclosingNodeOrSelfWithClass(
@@ -2851,9 +2768,6 @@ YearListView.prototype.onClick = function(event) {
this.dispatchEvent(
YearListView.EventTypeYearListViewDidSelectMonth, this,
new Month(year, month));
- if (!global.params.isFormControlsRefreshEnabled) {
- this.hide();
- }
}
};
@@ -2924,7 +2838,7 @@ YearListView.prototype.prepareNewCell = function(row) {
for (var i = 0; i < cell.monthButtons.length; ++i) {
var month = new Month(row + 1, i);
cell.monthButtons[i].id = month.toString();
- if (global.params.isFormControlsRefreshEnabled && this.type === 'month') {
+ if (this.type === 'month') {
cell.monthButtons[i].setAttribute(
'aria-disabled', this.isValid(month) ? 'false' : 'true');
} else {
@@ -2936,24 +2850,11 @@ YearListView.prototype.prepareNewCell = function(row) {
cell.monthButtons[i].setAttribute('aria-label', month.toLocaleString());
cell.monthButtons[i].setAttribute('aria-selected', false);
}
- if (!global.params.isFormControlsRefreshEnabled && this.highlightedMonth &&
- row === this.highlightedMonth.year - 1) {
- var monthButton = cell.monthButtons[this.highlightedMonth.month];
- monthButton.classList.add(YearListCell.ClassNameHighlighted);
- // aria-activedescendant assumes both elements have layoutObjects, and
- // |monthButton| might have no layoutObject yet.
- var element = this.element;
- setTimeout(function() {
- element.setAttribute('aria-activedescendant', monthButton.id);
- }, 0);
- }
if (this._selectedMonth && (this._selectedMonth.year - 1) === row) {
var monthButton = cell.monthButtons[this._selectedMonth.month];
monthButton.classList.add(YearListCell.ClassNameSelected);
- if (global.params.isFormControlsRefreshEnabled) {
- this.element.setAttribute('aria-activedescendant', monthButton.id);
- monthButton.setAttribute('aria-selected', true);
- }
+ this.element.setAttribute('aria-activedescendant', monthButton.id);
+ monthButton.setAttribute('aria-selected', true);
}
const todayMonth = Month.createFromToday();
if ((todayMonth.year - 1) === row) {
@@ -3038,10 +2939,6 @@ YearListView.prototype.select = function(row) {
this.selectedRow, YearListView.RowAnimationDirection.Opening);
if (selectedCell)
selectedCell.setSelected(true);
- if (!global.params.isFormControlsRefreshEnabled) {
- var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
- this.highlightMonth(new Month(this.selectedRow + 1, month));
- }
}
this.setNeedsUpdateCells(true);
};
@@ -3149,9 +3046,6 @@ YearListView.prototype.show = function(month) {
this.scrollToRow(month.year - 1, false);
this.selectWithoutAnimating(month.year - 1);
- if (!global.params.isFormControlsRefreshEnabled) {
- this.highlightMonth(month);
- }
this.showSelectedMonth();
};
@@ -3165,12 +3059,6 @@ YearListView.prototype.hide = function() {
YearListView.prototype._moveHighlightTo = function(month) {
this.highlightMonth(month);
this.select(this.highlightedMonth.year - 1);
-
- if (!global.params.isFormControlsRefreshEnabled) {
- this.dispatchEvent(
- YearListView.EventTypeYearListViewDidSelectMonth, this, month);
- }
-
this.scrollView.scrollTo(this.selectedRow * YearListCell.GetHeight(), true);
return true;
};
@@ -3181,17 +3069,7 @@ YearListView.prototype._moveHighlightTo = function(month) {
YearListView.prototype.onKeyDown = function(event) {
var key = event.key;
var eventHandled = false;
- if (key == 't') {
- if (!global.params.isFormControlsRefreshEnabled) {
- eventHandled = this._moveHighlightTo(Month.createFromToday());
- if (global.params.isFormControlsRefreshEnabled) {
- this.dispatchEvent(
- YearListView.EventTypeYearListViewDidSelectMonth, this,
- this.highlightedMonth);
- }
- }
- } else if (
- global.params.isFormControlsRefreshEnabled && this._selectedMonth) {
+ if (this._selectedMonth) {
if (global.params.isLocaleRTL ? key == 'ArrowRight' : key == 'ArrowLeft') {
var newSelection = this.getNearestValidRangeLookingBackward(
this._selectedMonth.previous());
@@ -3256,32 +3134,6 @@ YearListView.prototype.onKeyDown = function(event) {
eventHandled = true;
}
}
- } else if (
- !global.params.isFormControlsRefreshEnabled && this.highlightedMonth) {
- if (global.params.isLocaleRTL ? key == 'ArrowRight' : key == 'ArrowLeft')
- eventHandled = this._moveHighlightTo(this.highlightedMonth.previous());
- else if (key == 'ArrowUp')
- eventHandled = this._moveHighlightTo(
- this.highlightedMonth.previous(YearListCell.ButtonColumns));
- else if (
- global.params.isLocaleRTL ? key == 'ArrowLeft' : key == 'ArrowRight')
- eventHandled = this._moveHighlightTo(this.highlightedMonth.next());
- else if (key == 'ArrowDown')
- eventHandled = this._moveHighlightTo(
- this.highlightedMonth.next(YearListCell.ButtonColumns));
- else if (key == 'PageUp')
- eventHandled =
- this._moveHighlightTo(this.highlightedMonth.previous(MonthsPerYear));
- else if (key == 'PageDown')
- eventHandled =
- this._moveHighlightTo(this.highlightedMonth.next(MonthsPerYear));
- else if (key == 'Enter') {
- this.dispatchEvent(
- YearListView.EventTypeYearListViewDidSelectMonth, this,
- this.highlightedMonth);
- this.hide();
- eventHandled = true;
- }
} else if (key == 'ArrowUp') {
this.scrollView.scrollBy(-YearListCell.GetHeight(), true);
eventHandled = true;
@@ -3332,8 +3184,7 @@ MonthPopupView.ClassNameMonthPopupView = 'month-popup-view';
MonthPopupView.prototype.show = function(initialMonth, calendarTableRect) {
this.isVisible = true;
- if (global.params.isFormControlsRefreshEnabled &&
- global.params.mode == 'datetime-local') {
+ if (global.params.mode == 'datetime-local') {
// Place the month popup under the datetimelocal-picker element so that the
// datetimelocal-picker element receives its keyboard and click events.
// For other calendar control types, these events are handled via the body element.
@@ -3452,6 +3303,27 @@ MonthPopupButton.prototype.onClick = function(event) {
* @constructor
* @extends View
*/
+function ClearButton() {
+ View.call(this, createElement('button', ClearButton.ClassNameClearButton));
+ this.element.addEventListener('click', this.onClick, false);
+};
+
+ClearButton.prototype = Object.create(View.prototype);
+
+ClearButton.ClassNameClearButton = 'clear-button';
+ClearButton.EventTypeButtonClick = 'buttonClick';
+
+/**
+ * @param {?Event} event
+ */
+ClearButton.prototype.onClick = function(event) {
+ this.dispatchEvent(ClearButton.EventTypeButtonClick, this);
+};
+
+/**
+ * @constructor
+ * @extends View
+ */
function CalendarNavigationButton() {
View.call(
this,
@@ -3618,31 +3490,6 @@ function CalendarHeaderView(calendarPicker) {
this._previousMonthButton.element.setAttribute(
'aria-label', global.params.axShowPreviousMonth);
- if (!global.params.isFormControlsRefreshEnabled) {
- /**
- * @type {!CalendarNavigationButton}
- * @const
- */
- this._todayButton = new CalendarNavigationButton();
- this._todayButton.attachTo(this);
- this._todayButton.on(
- CalendarNavigationButton.EventTypeButtonClick,
- this.onNavigationButtonClick);
- this._todayButton.element.classList.add(
- CalendarHeaderView.GetClassNameTodayButton());
- if (this.calendarPicker.type === 'week') {
- this._todayButton.setDisabled(isWeekOutsideOfRange(
- Week.createFromToday(), this.calendarPicker.config.minimum,
- this.calendarPicker.config.maximum));
- } else {
- this._todayButton.setDisabled(isDayOutsideOfRange(
- Day.createFromToday(), this.calendarPicker.config.minimum,
- this.calendarPicker.config.maximum));
- }
- this._todayButton.element.setAttribute(
- 'aria-label', global.params.todayLabel);
- }
-
/**
* @type {!CalendarNavigationButton}
* @const
@@ -3675,46 +3522,32 @@ CalendarHeaderView.prototype = Object.create(View.prototype);
CalendarHeaderView.Height = 24;
CalendarHeaderView.BottomMargin = 10;
-CalendarHeaderView.ClassNameCalendarNavigationButtonIconRefresh =
- 'navigation-button-icon-refresh';
-CalendarHeaderView._ForwardTriangle =
- '<svg width=\'4\' height=\'7\'><polygon points=\'0,7 0,0, 4,3.5\' style=\'fill:#6e6e6e;\' /></svg>';
-CalendarHeaderView._ForwardTriangleRefresh = `<svg class="${
+CalendarHeaderView.ClassNameCalendarNavigationButtonIcon =
+ 'navigation-button-icon';
+CalendarHeaderView._ForwardTriangle = `<svg class="${
CalendarHeaderView
- .ClassNameCalendarNavigationButtonIconRefresh}" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+ .ClassNameCalendarNavigationButtonIcon}" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="${
CalendarHeaderView
- .ClassNameCalendarNavigationButtonIconRefresh}" d="M15.3516 8.60156L8 15.9531L0.648438 8.60156L1.35156 7.89844L7.5 14.0469V0H8.5V14.0469L14.6484 7.89844L15.3516 8.60156Z" fill="#101010"/>
+ .ClassNameCalendarNavigationButtonIcon}" d="M15.3516 8.60156L8 15.9531L0.648438 8.60156L1.35156 7.89844L7.5 14.0469V0H8.5V14.0469L14.6484 7.89844L15.3516 8.60156Z" fill="#101010"/>
</svg>`;
CalendarHeaderView.GetForwardTriangle = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarHeaderView._ForwardTriangleRefresh;
- }
return CalendarHeaderView._ForwardTriangle;
};
-CalendarHeaderView._BackwardTriangle =
- '<svg width=\'4\' height=\'7\'><polygon points=\'0,3.5 4,7 4,0\' style=\'fill:#6e6e6e;\' /></svg>';
-CalendarHeaderView._BackwardTriangleRefresh = `<svg class="${
+CalendarHeaderView._BackwardTriangle = `<svg class="${
CalendarHeaderView
- .ClassNameCalendarNavigationButtonIconRefresh}" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+ .ClassNameCalendarNavigationButtonIcon}" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="${
CalendarHeaderView
- .ClassNameCalendarNavigationButtonIconRefresh}" d="M14.6484 8.10156L8.5 1.95312V16H7.5V1.95312L1.35156 8.10156L0.648438 7.39844L8 0.046875L15.3516 7.39844L14.6484 8.10156Z" fill="#101010"/>
+ .ClassNameCalendarNavigationButtonIcon}" d="M14.6484 8.10156L8.5 1.95312V16H7.5V1.95312L1.35156 8.10156L0.648438 7.39844L8 0.046875L15.3516 7.39844L14.6484 8.10156Z" fill="#101010"/>
</svg>`;
CalendarHeaderView.GetBackwardTriangle = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarHeaderView._BackwardTriangleRefresh;
- }
return CalendarHeaderView._BackwardTriangle;
};
CalendarHeaderView.ClassNameCalendarHeaderView = 'calendar-header-view';
CalendarHeaderView.ClassNameCalendarTitle = 'calendar-title';
CalendarHeaderView.ClassNameTodayButton = 'today-button';
-CalendarHeaderView.ClassNameTodayButtonRefresh = 'today-button-refresh';
CalendarHeaderView.GetClassNameTodayButton = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarHeaderView.ClassNameTodayButtonRefresh;
- }
return CalendarHeaderView.ClassNameTodayButton;
};
@@ -3748,13 +3581,10 @@ CalendarHeaderView.prototype.onNavigationButtonClick = function(sender) {
*/
CalendarHeaderView.prototype.setDisabled = function(disabled) {
this.disabled = disabled;
- if (global.params.isFormControlsRefreshEnabled) {
- this._previousMonthButton.element.style.visibility =
- this.disabled ? 'hidden' : 'visible';
- this._nextMonthButton.element.style.visibility =
- this.disabled ? 'hidden' : 'visible';
- }
-
+ this._previousMonthButton.element.style.visibility =
+ this.disabled ? 'hidden' : 'visible';
+ this._nextMonthButton.element.style.visibility =
+ this.disabled ? 'hidden' : 'visible';
this.monthPopupButton.element.disabled = this.disabled;
this._previousMonthButton.setDisabled(
this.disabled ||
@@ -3797,20 +3627,12 @@ function DayCell() {
DayCell.prototype = Object.create(ListCell.prototype);
-DayCell._Width = 34;
-DayCell._WidthRefresh = 28;
+DayCell._Width = 28;
DayCell.GetWidth = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return DayCell._WidthRefresh;
- }
return DayCell._Width;
};
-DayCell._Height = hasInaccuratePointingDevice() ? 34 : 20;
-DayCell._HeightRefresh = 28;
+DayCell._Height = 28;
DayCell.GetHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return DayCell._HeightRefresh;
- }
return DayCell._Height;
};
DayCell.PaddingSize = 1;
@@ -3918,11 +3740,7 @@ WeekNumberCell.prototype = Object.create(ListCell.prototype);
WeekNumberCell.Width = 48;
WeekNumberCell._Height = DayCell._Height;
-WeekNumberCell._HeightRefresh = DayCell._HeightRefresh;
WeekNumberCell.GetHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return WeekNumberCell._HeightRefresh;
- }
return WeekNumberCell._Height;
};
WeekNumberCell.SeparatorWidth = 1;
@@ -4018,12 +3836,8 @@ function CalendarTableHeaderView(hasWeekNumberColumn) {
CalendarTableHeaderView.prototype = Object.create(View.prototype);
-CalendarTableHeaderView._Height = 25;
-CalendarTableHeaderView._HeightRefresh = 29;
+CalendarTableHeaderView._Height = 29;
CalendarTableHeaderView.GetHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarTableHeaderView._HeightRefresh;
- }
return CalendarTableHeaderView._Height;
};
@@ -4035,6 +3849,9 @@ function CalendarRowCell() {
ListCell.call(this);
this.element.classList.add(CalendarRowCell.ClassNameCalendarRowCell);
+ if (global.params.weekStartDay === WeekDay.Sunday) {
+ this.element.classList.add(CalendarRowCell.ClassNameWeekStartsOnSunday);
+ }
this.element.style.height = CalendarRowCell.GetHeight() + 'px';
this.element.setAttribute('role', 'row');
@@ -4056,14 +3873,11 @@ function CalendarRowCell() {
CalendarRowCell.prototype = Object.create(ListCell.prototype);
CalendarRowCell._Height = DayCell._Height;
-CalendarRowCell._HeightRefresh = DayCell._HeightRefresh;
CalendarRowCell.GetHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarRowCell._HeightRefresh;
- }
return CalendarRowCell._Height;
};
CalendarRowCell.ClassNameCalendarRowCell = 'calendar-row-cell';
+CalendarRowCell.ClassNameWeekStartsOnSunday = 'week-starts-on-sunday';
CalendarRowCell._recycleBin = [];
@@ -4138,30 +3952,37 @@ function CalendarTableView(calendarPicker) {
var headerView = new CalendarTableHeaderView(this.hasWeekNumberColumn);
headerView.attachTo(this, this.scrollView);
- if (global.params.isFormControlsRefreshEnabled) {
- /**
- * @type {!CalendarNavigationButton}
- * @const
- */
- var todayButton = new CalendarNavigationButton();
- todayButton.attachTo(this);
- todayButton.on(
- CalendarNavigationButton.EventTypeButtonClick, this.onTodayButtonClick);
- todayButton.element.textContent = global.params.todayLabel;
- todayButton.element.classList.add(
- CalendarHeaderView.GetClassNameTodayButton());
- if (this.calendarPicker.type === 'week') {
- todayButton.setDisabled(isWeekOutsideOfRange(
- Week.createFromToday(), this.calendarPicker.config.minimum,
- this.calendarPicker.config.maximum));
- } else {
- todayButton.setDisabled(isDayOutsideOfRange(
- Day.createFromToday(), this.calendarPicker.config.minimum,
- this.calendarPicker.config.maximum));
- }
- todayButton.element.setAttribute('aria-label', global.params.todayLabel);
- }
+ /**
+ * @type {!ClearButton}
+ * @const
+ */
+ var clearButton = new ClearButton();
+ clearButton.attachTo(this);
+ clearButton.on(ClearButton.EventTypeButtonClick, this.onClearButtonClick);
+ clearButton.element.textContent = global.params.clearLabel;
+ clearButton.element.setAttribute('aria-label', global.params.clearLabel);
+ /**
+ * @type {!CalendarNavigationButton}
+ * @const
+ */
+ var todayButton = new CalendarNavigationButton();
+ todayButton.attachTo(this);
+ todayButton.on(
+ CalendarNavigationButton.EventTypeButtonClick, this.onTodayButtonClick);
+ todayButton.element.textContent = global.params.todayLabel;
+ todayButton.element.classList.add(
+ CalendarHeaderView.GetClassNameTodayButton());
+ if (this.calendarPicker.type === 'week') {
+ todayButton.setDisabled(isWeekOutsideOfRange(
+ Week.createFromToday(), this.calendarPicker.config.minimum,
+ this.calendarPicker.config.maximum));
+ } else {
+ todayButton.setDisabled(isDayOutsideOfRange(
+ Day.createFromToday(), this.calendarPicker.config.minimum,
+ this.calendarPicker.config.maximum));
+ }
+ todayButton.element.setAttribute('aria-label', global.params.todayLabel);
if (this.hasWeekNumberColumn) {
this.setWidth(DayCell.GetWidth() * DaysPerWeek + WeekNumberCell.Width);
@@ -4181,10 +4002,6 @@ function CalendarTableView(calendarPicker) {
this._ignoreMouseOutUntillNextMouseOver = false;
this.element.addEventListener('click', this.onClick, false);
- if (!global.params.isFormControlsRefreshEnabled) {
- this.element.addEventListener('mouseover', this.onMouseOver, false);
- this.element.addEventListener('mouseout', this.onMouseOut, false);
- }
// You shouldn't be able to use the mouse wheel to scroll.
this.scrollView.element.removeEventListener(
@@ -4196,20 +4013,12 @@ function CalendarTableView(calendarPicker) {
CalendarTableView.prototype = Object.create(ListView.prototype);
-CalendarTableView._BorderWidth = 1;
-CalendarTableView._BorderWidthRefresh = 0;
+CalendarTableView._BorderWidth = 0;
CalendarTableView.GetBorderWidth = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarTableView._BorderWidthRefresh;
- }
return CalendarTableView._BorderWidth;
};
-CalendarTableView._TodayButtonHeight = 0;
-CalendarTableView._TodayButtonHeightRefresh = 28;
+CalendarTableView._TodayButtonHeight = 28;
CalendarTableView.GetTodayButtonHeight = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- return CalendarTableView._TodayButtonHeightRefresh;
- }
return CalendarTableView._TodayButtonHeight;
};
CalendarTableView.ClassNameCalendarTableView = 'calendar-table-view';
@@ -4252,45 +4061,12 @@ CalendarTableView.prototype.onClick = function(event) {
this.calendarPicker.selectRangeContainingDay(dayCell.day);
};
-CalendarTableView.prototype.onTodayButtonClick = function(sender) {
- this.calendarPicker.selectRangeContainingDay(Day.createFromToday());
-};
-
-/**
- * @param {?Event} event
- */
-CalendarTableView.prototype.onMouseOver = function(event) {
- if (this.hasWeekNumberColumn) {
- var weekNumberCellElement = enclosingNodeOrSelfWithClass(
- event.target, WeekNumberCell.ClassNameWeekNumberCell);
- if (weekNumberCellElement) {
- var weekNumberCell = weekNumberCellElement.$view;
- this.calendarPicker.highlightRangeContainingDay(
- weekNumberCell.week.firstDay());
- this._ignoreMouseOutUntillNextMouseOver = false;
- return;
- }
- }
- var dayCellElement =
- enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
- if (!dayCellElement)
- return;
- var dayCell = dayCellElement.$view;
- this.calendarPicker.highlightRangeContainingDay(dayCell.day);
- this._ignoreMouseOutUntillNextMouseOver = false;
+CalendarTableView.prototype.onClearButtonClick = function() {
+ window.pagePopupController.setValueAndClosePopup(0, '');
};
-/**
- * @param {?Event} event
- */
-CalendarTableView.prototype.onMouseOut = function(event) {
- if (this._ignoreMouseOutUntillNextMouseOver)
- return;
- var dayCellElement =
- enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
- if (!dayCellElement) {
- this.calendarPicker.highlightRangeContainingDay(null);
- }
+CalendarTableView.prototype.onTodayButtonClick = function(sender) {
+ this.calendarPicker.selectRangeContainingDay(Day.createFromToday());
};
/**
@@ -4320,9 +4096,7 @@ CalendarTableView.prototype.setHeight = function(height) {
height - CalendarTableHeaderView.GetHeight() -
CalendarTableView.GetBorderWidth() * 2 -
CalendarTableView.GetTodayButtonHeight());
- if (global.params.isFormControlsRefreshEnabled) {
- this.element.style.height = height + 'px';
- }
+ this.element.style.height = height + 'px';
};
/**
@@ -4398,21 +4172,8 @@ CalendarTableView.prototype.updateCells = function() {
dayCell.setIsToday(Day.createFromToday().equals(day));
var isSelected = (day >= firstDayInSelection && day <= lastDayInSelection);
dayCell.setSelected(isSelected);
- if (global.params.isFormControlsRefreshEnabled) {
- if (isSelected && firstDayInSelection == lastDayInSelection) {
- activeCell = dayCell;
- }
- } else {
- var isHighlighted =
- day >= firstDayInHighlight && day <= lastDayInHighlight;
- dayCell.setHighlighted(isHighlighted);
- if (isHighlighted) {
- if (firstDayInHighlight == lastDayInHighlight)
- activeCell = dayCell;
- else if (
- this.calendarPicker.type == 'month' && day == firstDayInHighlight)
- activeCell = dayCell;
- }
+ if (isSelected && firstDayInSelection == lastDayInSelection) {
+ activeCell = dayCell;
}
dayCell.setIsInCurrentMonth(
day >= firstDayInCurrentMonth && day <= lastDayInCurrentMonth);
@@ -4424,15 +4185,8 @@ CalendarTableView.prototype.updateCells = function() {
var week = weekNumberCell.week;
var isSelected = (selection && selection.equals(week));
weekNumberCell.setSelected(isSelected);
- if (global.params.isFormControlsRefreshEnabled) {
- if (isSelected) {
- activeCell = weekNumberCell;
- }
- } else {
- var isWeekHighlighted = highlight && highlight.equals(week);
- weekNumberCell.setHighlighted(isWeekHighlighted);
- if (isWeekHighlighted)
- activeCell = weekNumberCell;
+ if (isSelected) {
+ activeCell = weekNumberCell;
}
weekNumberCell.setDisabled(!this.calendarPicker.isValid(week));
}
@@ -4512,7 +4266,7 @@ function CalendarPicker(type, config) {
this._setValidDateConfig(config);
- if (global.params.isFormControlsRefreshEnabled && this.type === 'week') {
+ if (this.type === 'week') {
this.element.classList.add(CalendarPicker.ClassNameWeekPicker);
}
@@ -4565,20 +4319,8 @@ function CalendarPicker(type, config) {
*/
this._selection = null;
- /**
- * @type {?DateType}
- * @protected
- */
- if (!global.params.isFormControlsRefreshEnabled) {
- this._highlight = null;
- }
-
this.calendarTableView.element.addEventListener(
- 'keydown',
- global.params.isFormControlsRefreshEnabled ?
- this.onCalendarTableKeyDownRefresh :
- this.onCalendarTableKeyDown,
- false);
+ 'keydown', this.onCalendarTableKeyDown, false);
document.body.addEventListener('click', this.onBodyClick, false);
document.body.addEventListener('keydown', this.onBodyKeyDown, false);
@@ -4600,24 +4342,18 @@ function CalendarPicker(type, config) {
Month.createFromDay(initialSelection.middleDay()),
CalendarPicker.NavigationBehavior.None);
- if (global.params.isFormControlsRefreshEnabled) {
- this._hadValidValueWhenOpened = this.isValid(initialSelection);
- this.setSelection(this.getNearestValidRange(
- initialSelection, /*lookForwardFirst*/ true));
- } else {
- this.setSelection(initialSelection);
- }
+ this._hadValidValueWhenOpened = this.isValid(initialSelection);
+ this.setSelection(
+ this.getNearestValidRange(initialSelection, /*lookForwardFirst*/ true));
} else {
this.setCurrentMonth(
Month.createFromToday(), CalendarPicker.NavigationBehavior.None);
- if (global.params.isFormControlsRefreshEnabled) {
- // Ensure that the next date closest to today is selected to start with so that
- // the user can simply submit the popup to choose it.
- this.setSelection(this.getValidRangeNearestToDay(
- this._dateTypeConstructor.createFromToday(),
- /*lookForwardFirst*/ true));
- }
+ // Ensure that the next date closest to today is selected to start with so that
+ // the user can simply submit the popup to choose it.
+ this.setSelection(this.getValidRangeNearestToDay(
+ this._dateTypeConstructor.createFromToday(),
+ /*lookForwardFirst*/ true));
}
/**
@@ -4637,7 +4373,7 @@ CalendarPicker.ClassNameWeekPicker = 'week-picker';
CalendarPicker.ClassNamePreparing = 'preparing';
CalendarPicker.EventTypeCurrentMonthChanged = 'currentMonthChanged';
CalendarPicker.commitDelayMs = 100;
-CalendarPicker.VisibleRowsRefresh = 6;
+CalendarPicker.VisibleRows = 6;
/**
* @param {!Event} event
@@ -4657,12 +4393,8 @@ CalendarPicker.prototype.resetToInitialValue = function() {
CalendarPicker.prototype.onYearListViewDidHide = function(sender) {
this.monthPopupView.hide();
this.calendarHeaderView.setDisabled(false);
- if (global.params.isFormControlsRefreshEnabled) {
- this.calendarTableView.element.style.visibility = 'visible';
- this.calendarTableView.element.focus();
- } else {
- this.adjustHeight();
- }
+ this.calendarTableView.element.style.visibility = 'visible';
+ this.calendarTableView.element.focus();
};
/**
@@ -4673,10 +4405,8 @@ CalendarPicker.prototype.onYearListViewDidSelectMonth = function(
sender, month) {
this.setCurrentMonth(month, CalendarPicker.NavigationBehavior.None);
- if (global.params.isFormControlsRefreshEnabled) {
- this.ensureSelectionIsWithinCurrentMonth();
- this.onYearListViewDidHide();
- }
+ this.ensureSelectionIsWithinCurrentMonth();
+ this.onYearListViewDidHide();
};
/**
@@ -4708,11 +4438,7 @@ CalendarPicker.prototype.onMonthPopupButtonClick = function(sender) {
clientRect.height);
this.monthPopupView.show(this.currentMonth(), calendarTableRect);
this.calendarHeaderView.setDisabled(true);
- if (global.params.isFormControlsRefreshEnabled) {
- this.calendarTableView.element.style.visibility = 'hidden';
- } else {
- this.adjustHeight();
- }
+ this.calendarTableView.element.style.visibility = 'hidden';
};
/**
@@ -4758,19 +4484,14 @@ CalendarPicker.prototype.adjustHeight = function() {
var rowForLastDayInMonth =
this.calendarTableView.columnAndRowForDay(this._currentMonth.lastDay())
.row;
- var numberOfRows = global.params.isFormControlsRefreshEnabled ?
- CalendarPicker.VisibleRowsRefresh :
- rowForLastDayInMonth - rowForFirstDayInMonth + 1;
+ var numberOfRows = CalendarPicker.VisibleRows;
var calendarTableViewHeight = CalendarTableHeaderView.GetHeight() +
numberOfRows * DayCell.GetHeight() +
CalendarTableView.GetBorderWidth() * 2 +
CalendarTableView.GetTodayButtonHeight();
- var height = (this.monthPopupView.isVisible &&
- !global.params.isFormControlsRefreshEnabled ?
- YearListView.GetHeight() :
- calendarTableViewHeight) +
- CalendarHeaderView.Height + CalendarHeaderView.BottomMargin +
- CalendarPicker.Padding * 2 + CalendarPicker.BorderWidth * 2;
+ var height = calendarTableViewHeight + CalendarHeaderView.Height +
+ CalendarHeaderView.BottomMargin + CalendarPicker.Padding * 2 +
+ CalendarPicker.BorderWidth * 2;
this.setHeight(height);
};
@@ -4803,12 +4524,10 @@ CalendarPicker.prototype.lastVisibleDay = function() {
var lastVisibleRow =
this.calendarTableView.columnAndRowForDay(this.currentMonth().lastDay())
.row;
- if (global.params.isFormControlsRefreshEnabled) {
- lastVisibleRow = this.calendarTableView
- .columnAndRowForDay(this.currentMonth().firstDay())
- .row +
- CalendarPicker.VisibleRowsRefresh - 1;
- }
+ lastVisibleRow =
+ this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay())
+ .row +
+ CalendarPicker.VisibleRows - 1;
var lastVisibleDay =
this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
if (!lastVisibleDay)
@@ -4843,9 +4562,6 @@ CalendarPicker.prototype.setSelection = function(dayOrWeekOrMonth) {
return;
if (this._selection && !dayOrWeekOrMonth) {
this._selection = null;
- if (!global.params.isFormControlsRefreshEnabled) {
- this._setHighlight(null);
- }
return;
}
var firstDayInSelection = dayOrWeekOrMonth.firstDay();
@@ -4879,9 +4595,6 @@ CalendarPicker.prototype.setSelection = function(dayOrWeekOrMonth) {
candidateCurrentMonth,
CalendarPicker.NavigationBehavior.WithAnimation);
}
- if (!global.params.isFormControlsRefreshEnabled) {
- this._setHighlight(dayOrWeekOrMonth);
- }
if (!this.isValid(dayOrWeekOrMonth))
return;
this._selection = dayOrWeekOrMonth;
@@ -4905,8 +4618,7 @@ CalendarPicker.prototype.setSelectionAndCommit = function(dayOrWeekOrMonth) {
this.element.offsetLeft;
// CalendarPicker doesn't handle the submission when used for datetime-local.
- if (global.params.isFormControlsRefreshEnabled &&
- this.type == 'datetime-local')
+ if (this.type == 'datetime-local')
return;
var value = this._selection.toString();
@@ -5039,11 +4751,12 @@ CalendarPicker.prototype._moveHighlight = function(dateRange) {
/**
* @param {?Event} event
*/
-CalendarPicker.prototype.onCalendarTableKeyDownRefresh = function(event) {
+CalendarPicker.prototype.onCalendarTableKeyDown = function(event) {
var key = event.key;
var offset = 0;
- if (!event.target.matches('.today-button-refresh') && this._selection) {
+ if (!event.target.matches('.today-button, .clear-button') &&
+ this._selection) {
switch (key) {
case 'PageUp':
var previousMonth = this.currentMonth().previous();
@@ -5114,65 +4827,9 @@ CalendarPicker.prototype.onCalendarTableKeyDownRefresh = function(event) {
break;
};
}
- // else if there is no selection it must be the case that there are no
- // valid values (because min >= max). Otherwise we would have set the selection
- // during initialization. In this case there's nothing to do.
-};
-
-/**
- * @param {?Event} event
- */
-CalendarPicker.prototype.onCalendarTableKeyDown = function(event) {
- var key = event.key;
- var eventHandled = false;
-
- if (key == 't') {
- this.selectRangeContainingDay(Day.createFromToday());
- eventHandled = true;
- } else if (key == 'PageUp') {
- var previousMonth = this.currentMonth().previous();
- if (previousMonth && previousMonth >= this.config.minimumValue) {
- this.setCurrentMonth(
- previousMonth, CalendarPicker.NavigationBehavior.WithAnimation);
- eventHandled = true;
- }
- } else if (key == 'PageDown') {
- var nextMonth = this.currentMonth().next();
- if (nextMonth && nextMonth >= this.config.minimumValue) {
- this.setCurrentMonth(
- nextMonth, CalendarPicker.NavigationBehavior.WithAnimation);
- eventHandled = true;
- }
- } else if (this._highlight) {
- var upOrDownArrowStepSize =
- this.type === 'date' || this.type === 'datetime-local' ? DaysPerWeek :
- 1;
- if (global.params.isLocaleRTL ? key == 'ArrowRight' : key == 'ArrowLeft') {
- eventHandled = this._moveHighlight(this._highlight.previous());
- } else if (key == 'ArrowUp') {
- eventHandled =
- this._moveHighlight(this._highlight.previous(upOrDownArrowStepSize));
- } else if (
- global.params.isLocaleRTL ? key == 'ArrowLeft' : key == 'ArrowRight') {
- eventHandled = this._moveHighlight(this._highlight.next());
- } else if (key == 'ArrowDown') {
- eventHandled =
- this._moveHighlight(this._highlight.next(upOrDownArrowStepSize));
- } else if (key == 'Enter') {
- this.setSelectionAndCommit(this._highlight);
- }
- } else if (
- key == 'ArrowLeft' || key == 'ArrowUp' || key == 'ArrowRight' ||
- key == 'ArrowDown') {
- // Highlight range near the middle.
- this.highlightRangeContainingDay(this.currentMonth().middleDay());
- eventHandled = true;
- }
-
- if (eventHandled) {
- event.stopPropagation();
- event.preventDefault();
- }
+ // else if there is no selection it must be the case that there are no
+ // valid values (because min >= max). Otherwise we would have set the selection
+ // during initialization. In this case there's nothing to do.
};
/**
@@ -5210,10 +4867,9 @@ CalendarPicker.prototype.setHeight = function(height) {
* @param {?Event} event
*/
CalendarPicker.prototype.onBodyClick = function(event) {
- if (global.params.isFormControlsRefreshEnabled &&
- this.type !== 'datetime-local') {
+ if (this.type !== 'datetime-local') {
if (event.target.matches(
- '.calendar-navigation-button, .navigation-button-icon-refresh, .month-button')) {
+ '.calendar-navigation-button, .navigation-button-icon, .month-button')) {
window.pagePopupController.setValue(this.getSelectedValue());
}
}
@@ -5225,28 +4881,22 @@ CalendarPicker.prototype.onBodyClick = function(event) {
CalendarPicker.prototype.onBodyKeyDown = function(event) {
var key = event.key;
var eventHandled = false;
- var offset = 0;
switch (key) {
case 'Escape':
// The datetime-local control handles submission/cancellation at
// the top level, so if we're in a datetime-local let event bubble
// up instead of handling it here.
- if (global.params.isFormControlsRefreshEnabled) {
- if (this.type !== 'datetime-local') {
- if (!this._selection ||
- (this._selection.equals(this._initialSelection))) {
- window.pagePopupController.closePopup();
- } else {
- this.resetToInitialValue();
- window.pagePopupController.setValue(
- this._hadValidValueWhenOpened ?
- this._initialSelection.toString() :
- '');
- }
+ if (this.type !== 'datetime-local') {
+ if (!this._selection ||
+ (this._selection.equals(this._initialSelection))) {
+ window.pagePopupController.closePopup();
+ } else {
+ this.resetToInitialValue();
+ window.pagePopupController.setValue(
+ this._hadValidValueWhenOpened ?
+ this._initialSelection.toString() :
+ '');
}
- } else {
- window.pagePopupController.closePopup();
- eventHandled = true;
}
break;
case 'ArrowUp':
@@ -5257,20 +4907,18 @@ CalendarPicker.prototype.onBodyKeyDown = function(event) {
case 'PageDown':
case 'Home':
case 'End':
- if (global.params.isFormControlsRefreshEnabled &&
- this.type !== 'datetime-local' &&
+ if (this.type !== 'datetime-local' &&
event.target.matches('.calendar-table-view') && this._selection) {
window.pagePopupController.setValue(this.getSelectedValue());
}
break;
case 'Enter':
// Submit the popup for an Enter keypress except when the user is
- // hitting Enter to activate the month switcher button, Today button,
- // or previous/next month arrows.
- if (global.params.isFormControlsRefreshEnabled &&
- this.type !== 'datetime-local') {
+ // hitting Enter to activate the month switcher button, Clear button,
+ // Today button, or previous/next month arrows.
+ if (this.type !== 'datetime-local') {
if (!event.target.matches(
- '.calendar-navigation-button, .month-popup-button, .year-list-view')) {
+ '.calendar-navigation-button, .clear-button, .month-popup-button, .year-list-view')) {
if (this._selection) {
window.pagePopupController.setValueAndClosePopup(
0, this.getSelectedValue());
@@ -5289,38 +4937,6 @@ CalendarPicker.prototype.onBodyKeyDown = function(event) {
}
}
break;
- case 'm':
- case 'M':
- offset = offset || 1;
- // Fall-through.
- case 'y':
- case 'Y':
- offset = offset || MonthsPerYear;
- // Fall-through.
- case 'd':
- case 'D':
- if (!global.params.isFormControlsRefreshEnabled) {
- offset = offset || MonthsPerYear * 10;
- var oldFirstVisibleRow =
- this.calendarTableView
- .columnAndRowForDay(this.currentMonth().firstDay())
- .row;
- this.setCurrentMonth(
- event.shiftKey ? this.currentMonth().previous(offset) :
- this.currentMonth().next(offset),
- CalendarPicker.NavigationBehavior.WithAnimation);
- var newFirstVisibleRow =
- this.calendarTableView
- .columnAndRowForDay(this.currentMonth().firstDay())
- .row;
- if (this._highlight) {
- var highlightMiddleDay = this._highlight.middleDay();
- this.highlightRangeContainingDay(highlightMiddleDay.next(
- (newFirstVisibleRow - oldFirstVisibleRow) * DaysPerWeek));
- }
- eventHandled = true;
- }
- break;
}
if (eventHandled) {
event.stopPropagation();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css b/chromium/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css
deleted file mode 100644
index 1d203780c8f..00000000000
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css
+++ /dev/null
@@ -1,531 +0,0 @@
-/* Copyright (C) 2019 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-body {
- font-size: 12px;
-}
-
-.calendar-picker {
- background-color: #ffffff;
- border-radius: 2px;
-}
-
-.calendar-table-view {
- border: 0;
-}
-
-.calendar-table-header-view {
- background-color: #ffffff;
- border: 0;
- height: 29px;
-}
-
-.week-day-label {
- line-height: 28px;
-}
-
-.calendar-navigation-button {
- -webkit-align-self: center;
- background-color: #ffffff;
- border: 1px solid transparent;
- color: #101010;
- padding: 0;
- text-align: center;
- width: 28px;
-}
-
-.calendar-navigation-button svg {
- padding-top: 4px;
-}
-
-.calendar-navigation-button:hover {
- background-color: rgba(0, 117, 255, 0.3);
-}
-
-.calendar-navigation-button:disabled {
- background-color: #FFFFFF;
-}
-
-.calendar-navigation-button:disabled path {
- fill: rgba(16, 16, 16, 0.3);
-}
-
-.calendar-title {
- -webkit-align-self: flex-start;
- flex: 1;
- text-align: left;
-}
-
-.month-popup-button {
- border: 0 !important;
- font-weight: bold;
- padding: 0;
-}
-
-.month-popup-button:focus {
- outline: auto 1px -webkit-focus-ring-color !important;
-}
-
-.month-popup-button:disabled {
- background-color: #FFFFFF;
- color: rgba(16, 16, 16, 0.3);
-}
-
-.month-popup-button:disabled polygon {
- fill: rgba(16, 16, 16, 0.3) !important;
-}
-
-.month-popup-button .disclosure-triangle {
- margin: 0;
- margin-inline-start: 4px;
- margin-inline-end: 1px;
-}
-
-.week-number-cell {
- border: 1px solid transparent !important;
-}
-
-.day-cell {
- background-color: #ffffff;
- border: 1px solid transparent !important;
- border-radius: 2px;
- color: #767676;
- padding: 1px !important;
- text-align: center;
-}
-
-.day-cell.current-month {
- color: #101010;
-}
-
-.week-number-cell,
-.day-cell {
- transition: color 0s;
-}
-
-/*
-* Highlight-when-hovered for cells in the month picker menu and standalone
-* month control
-*/
-.month-button:hover {
- background-color: rgba(0, 117, 255, 0.3);
-}
-
-/*
-* Highlight-when-hovered for day cells except if this is a week picker
-*/
-:not(.week-picker) > .calendar-table-view > .scroll-view > .scroll-view-content
- > .calendar-row-cell > .day-cell:not(.selected):hover {
- background-color: rgba(0, 117, 255, 0.3);
-}
-
-/*
-* Highlight-when-hovered for week picker, in 3 parts:
-* 1. Highlight all cells in the hovered row except for Monday, because it
-* belongs to the previous week.
-* 2. Highlight Monday of the row after the hovered row, because it belongs to
-* this week
-* 3. Highlight the week number cell for the hovered week
-*/
-.week-picker .calendar-row-cell:hover
- .day-cell:not(.selected):not(.disabled):not(:nth-child(2)),
-.week-picker .calendar-row-cell:hover + .calendar-row-cell
- .day-cell:not(.selected):not(.disabled):nth-child(2),
-.calendar-row-cell:hover .week-number-cell:not(.selected):not(.disabled) {
- background-color: rgba(0, 117, 255, 0.3);
-}
-
-.day-cell.selected,
-.month-button.selected,
-.week-number-cell.selected {
- background-color: #0075FF;
- color: #FFFFFF;
- font-weight: bold;
-}
-
-.calendar-table-view:focus .day-cell.selected,
-.year-list-view:focus .month-button.selected,
-.calendar-table-view:focus .week-number-cell.selected {
- outline: solid 2px -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-
-.day-cell.today,
-.month-button.today {
- border-color: #767676 !important;
-}
-
-.day-cell.disabled,
-.day-cell.disabled.today,
-.month-button[aria-disabled="true"],
-.week-number-cell.disabled {
- background-color: #FFFFFF;
- color: rgba(16, 16, 16, 0.3);
-}
-
-.today-button-refresh {
- border: 1px solid transparent;
- bottom: 12px;
- color: #0078D4;
- font-size: 12px;
- height: 20px;
- padding: 4px;
- position: absolute;
- right: 20px;
- width: auto;
-}
-
-.today-button-refresh:hover {
- background-color: rgba(0, 117, 255, 0.3);
-}
-
-.today-button-refresh:disabled {
- background-color: #FFFFFF;
- color: rgba(16, 16, 16, 0.3);
-}
-
-.year-list-view {
- border: 0;
-}
-
-.scrubby-scroll-bar {
- border: 0;
-}
-
-.scrubby-scroll-thumb {
- width: 4px;
-}
-
-.year-list-cell {
- border: 0;
-}
-
-.year-list-cell .label {
- background-color: #EFEFEF;
- border-color: #CECECE;
- margin-bottom: 1px;
-}
-
-.month-button {
- border: 1px solid transparent !important;
- border-radius: 2px;
- color: #101010;
-}
-
-.datetimelocal-picker .calendar-picker {
- border: 0;
- border-right: 1px solid #CECECE;
-}
-
-.datetimelocal-picker .time-picker {
- border: 0;
- height: 254px;
- position: absolute;
- right: 3px;
- top: 12px;
-}
-
-/* These forced colors mode styles override the default styling for elements
- * when forced colors mode is enabled.
- */
-@media (forced-colors: active) {
- .calendar-navigation-button {
- background-color: Window;
- color: WindowText;
- forced-color-adjust: none;
- }
-
- .calendar-navigation-button:hover {
- background-color: Window;
- border-color: Highlight;
- }
-
- .calendar-navigation-button:disabled {
- background-color: Window;
- border-color: transparent;
- }
-
- .calendar-navigation-button path {
- fill: WindowText;
- }
-
- .calendar-navigation-button:disabled path {
- fill: GrayText;
- }
-
- .month-popup-button,
- .month-popup-button:hover,
- .month-popup-button:disabled {
- background-color: Canvas;
- color: CanvasText;
- forced-color-adjust: none;
- opacity: 1.0;
- }
-
- .month-popup-button:disabled {
- color: GrayText !important;
- }
-
- .month-popup-button polygon {
- fill: WindowText !important;
- }
-
- .month-popup-button:disabled polygon {
- fill: GrayText !important;
- }
-
- .week-number-cell {
- background-color: Window;
- color: WindowText;
- forced-color-adjust: none;
- }
-
- .day-cell {
- background-color: Window;
- color: GrayText;
- forced-color-adjust: none;
- }
-
- .month-button {
- background-color: Window;
- color: WindowText;
- forced-color-adjust: none;
- }
-
- .day-cell.current-month {
- color: WindowText;
- }
-
- /*
- * Highlight-when-hovered for cells in the month picker menu and standalone
- * month control
- */
- .month-button:not(.selected):hover {
- background-color: Window !important;
- border-color: Highlight !important;
- }
-
- /*
- * Highlight-when-hovered for day cells except if this is a week picker
- */
- :not(.week-picker) > .calendar-table-view > .scroll-view > .scroll-view-content
- > .calendar-row-cell > .day-cell:not(.selected):hover {
- background-color: Window !important;
- border-color: Highlight !important;
- }
-
- /*
- * Highlight-when-hovered for week picker, in 3 parts:
- * 1. Highlight all cells in the hovered row except for Monday, because it
- * belongs to the previous week.
- * 2. Highlight Monday of the row after the hovered row, because it belongs to
- * this week
- * 3. Highlight the week number cell for the hovered week
- */
- .week-picker .calendar-row-cell:hover
- .day-cell:not(.selected):not(.disabled):not(:nth-child(2)),
- .week-picker .calendar-row-cell:hover + .calendar-row-cell
- .day-cell:not(.selected):not(.disabled):nth-child(2),
- .calendar-row-cell:hover .week-number-cell:not(.selected):not(.disabled) {
- border-color: Highlight !important;
- background-color: Window !important;
- }
-
- .day-cell.selected,
- .month-button.selected,
- .week-number-cell.selected {
- background-color: Highlight;
- color: Window;
- }
-
- .calendar-table-view:focus .day-cell.selected,
- .year-list-view:focus .month-button.selected,
- .calendar-table-view:focus .week-number-cell.selected {
- outline: none;
- }
-
- .day-cell.today,
- .month-button.today {
- border-color: WindowText !important;
- }
-
- .day-cell.disabled,
- .day-cell.disabled.today,
- .month-button[aria-disabled="true"],
- .week-number-cell.disabled {
- background-color: Window;
- border: 0 !important;
- color: GrayText;
- }
-
- .today-button-refresh {
- background-color: Window;
- color: LinkText;
- forced-color-adjust: none;
- }
-
- .today-button-refresh:hover {
- background-color: Window;
- border-color: Highlight;
- }
-
- .today-button-refresh:disabled {
- background-color: Window;
- border-color: transparent;
- color: GrayText;
- forced-color-adjust: none;
- }
-
- .scrubby-scroll-thumb {
- background-color: WindowText;
- forced-color-adjust: none;
- }
-}
-
-@media (prefers-color-scheme: dark) {
- .calendar-picker {
- background-color: #3B3B3B;
- color:#ffffff;
- border: 1px solid #858585;
- }
-
- .disclosure-triangle polygon,
- .month-popup-button .disclosure-triangle polygon {
- fill: #FFFFFF !important;
- }
-
- .calendar-table-header-view {
- background-color: #3B3B3B;
- }
-
- .calendar-navigation-button {
- background-color: #3B3B3B;
- color: #ffffff;
- }
-
- .calendar-navigation-button:hover {
- background-color: #545454;
- }
-
- .calendar-navigation-button:disabled {
- background-color: #3B3B3B;
- }
-
- .month-popup-button:disabled {
- background-color: #3B3B3B;
- color: rgba(255, 255, 255, 0.3);
- }
-
- .week-number-cell,
- .day-cell {
- background-color: #3B3B3B;
- color: #FFFFFF;
- }
-
- .day-cell.current-month {
- color: #ffffff;
- }
-
- .month-button:hover {
- background-color: #D1E6FF;
- color: #3B3B3B;
- }
-
- :not(.week-picker) > .calendar-table-view > .scroll-view > .scroll-view-content
- > .calendar-row-cell > .day-cell:not(.selected):hover {
- background-color: #D1E6FF;
- color: #3B3B3B;
- }
-
- .week-picker .calendar-row-cell:hover
- .day-cell:not(.selected):not(.disabled):not(:nth-child(2)),
- .week-picker .calendar-row-cell:hover + .calendar-row-cell
- .day-cell:not(.selected):not(.disabled):nth-child(2),
- .calendar-row-cell:hover .week-number-cell:not(.selected):not(.disabled) {
- background-color: #D1E6FF;
- color: #3B3B3B;
- }
-
- .calendar-table-view:focus .day-cell.selected,
- .year-list-view:focus .month-button.selected,
- .calendar-table-view:focus .week-number-cell.selected {
- outline: solid 1px #FFFFFF;
- outline-offset: -1px;
- }
-
- .day-cell.selected,
- .month-button.selected,
- .week-number-cell.selected {
- background-color: #99C8FF;
- color: #3B3B3B;
- border-color: #FFFFFF;
- }
-
- .day-cell.disabled,
- .day-cell.disabled.today,
- .month-button[aria-disabled="true"],
- .week-number-cell.disabled {
- background-color: #3B3B3B;
- color: rgba(255, 255, 255, 0.3);
- }
-
- .today-button-refresh {
- color: #99C8FF;
- }
-
- .today-button-refresh:hover {
- color: #D1E6FF;
- background-color: #545454;
- }
-
- .today-button-refresh:disabled {
- color: rgba(255, 255, 255, 0.3);
- }
-
- .year-list-cell .label {
- background-color: #3B3B3B;
- color: #ffffff;
- }
-
- body {
- background-color: #3B3B3B;
- }
-
- .month-popup-button,
- .month-popup-button:hover,
- .month-popup-button:disabled {
- color: #ffffff;
- }
-
- .scrubby-scroll-bar {
- background-color: #3B3B3B;
- border-left: 1px solid #3B3B3B;
- }
-
- .scrubby-scroll-thumb {
- background-color: #d8d8d8;
- }
-
- .calendar-navigation-button path {
- fill: #ffffff;
- }
-
- .month-popup-button polygon {
- fill: #ffffff;
- }
-
- .month-popup-button:disabled polygon {
- fill: #ffffff;
- }
-
- .year-list-cell .month-chooser {
- background-color: #3B3B3B;
- }
-
- .month-button {
- background-color: #3B3B3B;
- color: #ffffff;
- }
-}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.css
index 55cd2b4e1c7..2ac53f54435 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.css
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.css
@@ -25,10 +25,11 @@
body {
--color-swatch-border-width: 1px;
- --color-swatch-margin: 1px;
- --color-swatch-height: 20px;
--color-swatch-padding: 0;
- --color-swatch-width: 20px;
+ --color-swatch-margin: 3px;
+ --color-swatch-height: 18px;
+ --color-swatch-width: 18px;
+ --scrollbar-width: 4px;
-webkit-user-select: none;
background-color: white;
font: -webkit-small-control;
@@ -36,23 +37,9 @@ body {
overflow: hidden;
}
-body.controls-refresh {
- --color-swatch-margin: 3px;
- --color-swatch-height: 18px;
- --color-swatch-width: 18px;
- --scrollbar-width: 4px;
-}
-
.color-suggestion-picker-main {
background-color: white;
- border: solid 1px #8899aa;
- box-shadow: inset 2px 2px 2px white,
- inset -2px -2px 1px rgba(0,0,0,0.1);
- padding: 6px;
float: left;
-}
-
-.controls-refresh .color-suggestion-picker-main {
border: 1px solid #bfbfbf;
box-shadow: none;
padding: 8px 8px 4px 8px;
@@ -64,19 +51,15 @@ body.controls-refresh {
height: var(--color-swatch-height);
margin: var(--color-swatch-margin);
padding: var(--color-swatch-padding);
- border: var(--color-swatch-border-width) solid #e0e0e0;
- border-radius: 0;
box-sizing: content-box;
-}
-
-.controls-refresh .color-swatch {
border: var(--color-swatch-border-width) solid rgba(0, 0, 0, 0.19);
border-radius: 2px;
}
.color-swatch:focus {
border: var(--color-swatch-border-width) solid #000000;
- outline: none;
+ outline: solid 2px -webkit-focus-ring-color;
+ outline-offset: -2px;
}
.color-swatch-container {
@@ -86,17 +69,14 @@ body.controls-refresh {
display: flex;
flex-flow: row wrap;
align-items: center;
-}
-
-.controls-refresh .color-swatch-container {
margin: 4px;
}
-.controls-refresh .color-swatch-container::-webkit-scrollbar {
+.color-swatch-container::-webkit-scrollbar {
width: var(--scrollbar-width);
}
-.controls-refresh .color-swatch-container::-webkit-scrollbar-thumb {
+.color-swatch-container::-webkit-scrollbar-thumb {
background-color: #cecece;
border-radius: 2px;
height: 47px;
@@ -104,17 +84,8 @@ body.controls-refresh {
width: 4px;
}
-.controls-refresh .color-swatch:focus {
- outline: solid 2px -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-
.other-color {
width: 100%;
- margin: 4px 0 0 0;
-}
-
-.controls-refresh .other-color {
background-color: #ffffff;
border-color: transparent;
border-radius: 2px;
@@ -125,61 +96,61 @@ body.controls-refresh {
text-align: left;
}
-.controls-refresh .other-color:hover {
+.other-color:hover {
background-color: #f3f3f3;
}
@media (forced-colors: active) {
- .controls-refresh .color-suggestion-picker-main {
+ .color-suggestion-picker-main {
border: 1px solid WindowText;
}
- .controls-refresh .color-swatch {
+ .color-swatch {
forced-color-adjust: none;
border-color: WindowText;
}
- .controls-refresh .color-swatch:focus {
+ .color-swatch:focus {
outline-color: Highlight;
}
- .controls-refresh .color-swatch-container {
+ .color-swatch-container {
forced-color-adjust: none;
}
- .controls-refresh .color-swatch-container::-webkit-scrollbar-thumb {
+ .color-swatch-container::-webkit-scrollbar-thumb {
background-color: WindowText;
}
}
@media (prefers-color-scheme: dark) {
- .controls-refresh .color-suggestion-picker-main {
+ .color-suggestion-picker-main {
background: #3B3B3B;
color: #FFFFFF;
border: 1px solid #858585;
box-shadow: none;
}
- .controls-refresh .color-swatch {
+ .color-swatch {
border-color: #858585;
}
- .controls-refresh .color-swatch:focus {
+ .color-swatch:focus {
outline-color: Highlight;
}
- .controls-refresh .other-color,
- .controls-refresh .other-color:hover {
+ .other-color,
+ .other-color:hover {
background: #3B3B3B;
color: #FFFFFF;
border: 1px solid #858585;
}
- .controls-refresh .other-color:hover{
+ .other-color:hover{
border: 1px solid #ACACAC;
}
- .controls-refresh .color-swatch-container::-webkit-scrollbar-thumb {
+ .color-swatch-container::-webkit-scrollbar-thumb {
background-color: WindowText;
}
} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.js
index e5c54cc5ea0..b1322ceb2de 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.js
@@ -129,17 +129,15 @@ Object.defineProperty(ColorSuggestionPicker, 'SwatchesPerRow', {
Object.defineProperty(ColorSuggestionPicker, 'SwatchesMaxRow', {
get: function() {
- return global.params.isFormControlsRefreshEnabled ? 3 : 4;
+ return 3;
}
});
Object.defineProperty(ColorSuggestionPicker, 'ScrollbarWidth', {
get: function() {
- return !global.params.isFormControlsRefreshEnabled ?
- getScrollbarWidth() :
- Number(window.getComputedStyle(document.body)
- .getPropertyValue('--scrollbar-width')
- .replace('px', ''));
+ return Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--scrollbar-width')
+ .replace('px', ''));
}
});
@@ -178,19 +176,15 @@ ColorSuggestionPicker.prototype._layout = function() {
};
ColorSuggestionPicker.prototype._onOtherButtonClick = function() {
- if (global.params.isFormControlsRefreshEnabled) {
- var main = $('main');
- main.innerHTML = '';
- main.classList.remove('color-suggestion-picker-main');
- main.classList.add('color-picker-main');
- // Replace document.body with a deep clone to drop all event listeners.
- var oldBody = document.body;
- var newBody = oldBody.cloneNode(true);
- oldBody.parentElement.replaceChild(newBody, oldBody);
- initializeColorPicker();
- } else {
- this.chooseOtherColor();
- }
+ var main = $('main');
+ main.innerHTML = '';
+ main.classList.remove('color-suggestion-picker-main');
+ main.classList.add('color-picker-main');
+ // Replace document.body with a deep clone to drop all event listeners.
+ var oldBody = document.body;
+ var newBody = oldBody.cloneNode(true);
+ oldBody.parentElement.replaceChild(newBody, oldBody);
+ initializeColorPicker();
};
ColorSuggestionPicker.prototype.selectColorAtIndex = function(index) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js
index 653de81fffc..d78da8a9c49 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js
@@ -40,9 +40,6 @@ function initialize(args) {
main.innerHTML = '';
var errorString;
if (global.params.shouldShowColorSuggestionPicker) {
- if (global.params.isFormControlsRefreshEnabled) {
- document.body.classList.add('controls-refresh');
- }
main.classList.add('color-suggestion-picker-main');
if (global.params.isBorderTransparent) {
main.style.borderColor = 'transparent';
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/datetimelocal_picker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/datetimelocal_picker.js
index 84828a16fd5..8c71aabf5e3 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/datetimelocal_picker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/datetimelocal_picker.js
@@ -99,7 +99,7 @@ class DateTimeLocalPicker extends HTMLElement {
onClick_ = (event) => {
if (event.target.matches(
- '.day-cell, .time-cell, .today-button-refresh, .calendar-navigation-button, .year-list-view, .calendar-navigation-button, .navigation-button-icon-refresh, .month-button') &&
+ '.day-cell, .time-cell, .today-button, .calendar-navigation-button, .year-list-view, .calendar-navigation-button, .navigation-button-icon, .month-button') &&
this.hasSelectedDate) {
window.pagePopupController.setValue(this.selectedValue);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css
index b0e435ff75e..fb19ba79cc5 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css
@@ -1,6 +1,8 @@
select {
display: block;
overflow-y: auto;
+ border-radius: 0px;
+ outline: none;
}
select hr {
@@ -16,8 +18,3 @@ option, optgroup {
.wrap option {
white-space: pre-wrap;
}
-
-.controls-refresh select {
- border-radius: 0px;
- outline: none;
-}
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 d292c47c997..8a30c4706d7 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
@@ -21,9 +21,6 @@ function initialize(args) {
global.params = args;
var main = $('main');
main.innerHTML = '';
- if (global.params.isFormControlsRefreshEnabled) {
- document.body.classList.add('controls-refresh');
- }
global.picker = new ListPicker(main, args);
}
@@ -316,6 +313,8 @@ ListPicker.prototype._layout = function() {
this._config.baseStyle.fontFamily.map(s => '"' + s + '"').join(',');
this._selectElement.style.fontStyle = this._config.baseStyle.fontStyle;
this._selectElement.style.fontVariant = this._config.baseStyle.fontVariant;
+ if (this._config.baseStyle.textAlign)
+ this._selectElement.style.textAlign = this._config.baseStyle.textAlign;
this._updateChildren(this._selectElement, this._config);
};
@@ -456,6 +455,7 @@ ListPicker.prototype._applyItemStyle = function(element, styleConfig) {
style.fontVariant = styleConfig.fontVariant ? styleConfig.fontVariant : '';
style.textTransform =
styleConfig.textTransform ? styleConfig.textTransform : '';
+ style.textAlign = styleConfig.textAlign ? styleConfig.textAlign : '';
};
ListPicker.prototype._configureItem = function(element, config, inGroup) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js
index 14e5346ae3c..9d6051af474 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js
@@ -36,6 +36,10 @@ class MonthPicker extends HTMLElement {
this.append(this.yearListView_.element);
this.initializeYearListView_();
+ this.clearButton_ = new ClearButton();
+ this.append(this.clearButton_.element);
+ this.initializeClearButton_();
+
this.todayButton_ = new CalendarNavigationButton();
this.append(this.todayButton_.element);
this.initializeTodayButton_();
@@ -85,6 +89,18 @@ class MonthPicker extends HTMLElement {
window.pagePopupController.setValueAndClosePopup(0, selectedValue);
};
+ initializeClearButton_ = () => {
+ this.clearButton_.element.textContent = global.params.clearLabel;
+ this.clearButton_.element.setAttribute(
+ 'aria-label', global.params.clearLabel);
+ this.clearButton_.on(
+ ClearButton.EventTypeButtonClick, this.onClearButtonClick_);
+ };
+
+ onClearButtonClick_ = () => {
+ window.pagePopupController.setValueAndClosePopup(0, '');
+ };
+
initializeTodayButton_ = () => {
this.todayButton_.element.textContent = global.params.todayLabel;
this.todayButton_.element.setAttribute(
@@ -106,9 +122,11 @@ class MonthPicker extends HTMLElement {
onKeyDown_ = (event) => {
switch (event.key) {
case 'Enter':
- // Don't do anything here if user has hit Enter on 'This month'
- // button. We'll handle that in this.onTodayButtonClick_.
- if (!event.target.matches('.calendar-navigation-button')) {
+ // Don't do anything here if user has hit Enter on 'Clear' or
+ // 'This month' buttons. We'll handle that respectively in
+ // this.onClearButtonClick_ and this.onTodayButtonClick_.
+ if (!event.target.matches(
+ '.calendar-navigation-button, .clear-button')) {
if (this.selectedMonth) {
window.pagePopupController.setValueAndClosePopup(
0, this.selectedMonth.toString());
@@ -170,5 +188,5 @@ MonthPicker.YearWidth = 194;
MonthPicker.YearHeight = 128;
MonthPicker.YearPadding = 12;
MonthPicker.Height = 182;
-MonthPicker.ClassNameTodayButton = 'today-button-refresh';
+MonthPicker.ClassNameTodayButton = 'today-button';
window.customElements.define('month-picker', MonthPicker);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/pickerButton.css b/chromium/third_party/blink/renderer/core/html/forms/resources/pickerButton.css
deleted file mode 100644
index 396d2788023..00000000000
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/pickerButton.css
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE 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.
- */
-
-input[type='button'],
-button {
- -webkit-appearance: none;
- -webkit-user-select: none;
- background-image: linear-gradient(#ededed, #ededed 38%, #dedede);
- border: 1px solid rgba(0, 0, 0, 0.25);
- border-radius: 2px;
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
- inset 0 1px 2px rgba(255, 255, 255, 0.75);
- color: #444;
- font: inherit;
- text-shadow: 0 1px 0 rgb(240, 240, 240);
- min-height: 2em;
- min-width: 4em;
- padding-inline-end: 10px;
- padding-inline-start: 10px;
- margin: 0;
-}
-
-:enabled:hover:-webkit-any(button, input[type='button']) {
- background-image: linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
- border-color: rgba(0, 0, 0, 0.3);
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95);
- color: black;
-}
-
-:enabled:active:-webkit-any(button, input[type='button']) {
- background-image: linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
- box-shadow: none;
- text-shadow: none;
-}
-
-:disabled:-webkit-any(button, input[type='button']) {
- background-image: linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);
- border-color: rgba(80, 80, 80, 0.2);
- box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75);
- color: #aaa;
-}
-
-:enabled:focus:-webkit-any(button, input[type='button']) {
- transition: border-color 200ms;
- /* We use border color because it follows the border radius (unlike outline).
- * This is particularly noticeable on mac. */
- border-color: rgb(77, 144, 254);
- outline: none;
-}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js b/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js
index ae3504dd303..b72800b4e0b 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js
@@ -148,13 +148,7 @@ function _adjustWindowRectVertically(
availableSpaceBelow =
Math.max(0, Math.min(availRect.height, availableSpaceBelow));
- // In some situations, there may be no space available. This can happen on
- // Linux when using a buggy window manager (https://crbug.com/774232). When
- // this happens, don't try to constrain the window at all.
- if (availableSpaceAbove == 0 && availableSpaceBelow == 0) {
- windowRect.height = Math.max(minHeight, windowRect.height);
- windowRect.y = anchorRect.maxY;
- } else if (
+ if (
windowRect.height > availableSpaceBelow &&
availableSpaceBelow < availableSpaceAbove) {
windowRect.height = Math.min(windowRect.height, availableSpaceAbove);
@@ -172,11 +166,6 @@ function _adjustWindowRectVertically(
*/
function _adjustWindowRectHorizontally(
windowRect, availRect, anchorRect, minWidth) {
- if (anchorRect.maxX <= availRect.x || availRect.maxX <= anchorRect.x) {
- windowRect.width = Math.max(minWidth, windowRect.width);
- windowRect.x = anchorRect.x
- return;
- }
windowRect.width = Math.min(windowRect.width, availRect.width);
windowRect.width = Math.max(windowRect.width, minWidth);
windowRect.x = anchorRect.x;
@@ -331,7 +320,6 @@ Picker.prototype = Object.create(EventEmitter.prototype);
Picker.Actions = {
SetValue: 0,
Cancel: -1,
- ChooseOtherColor: -2
};
/**
@@ -346,11 +334,6 @@ Picker.prototype.handleCancel = function() {
window.pagePopupController.closePopup();
};
-Picker.prototype.chooseOtherColor = function() {
- window.pagePopupController.setValueAndClosePopup(
- Picker.Actions.ChooseOtherColor, '');
-};
-
Picker.prototype.cleanup = function() {};
window.addEventListener('keyup', function(event) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.css
index 30837f148de..335cc327189 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.css
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.css
@@ -1,23 +1,28 @@
.suggestion-list {
list-style: none;
- padding: 0;
margin: 0;
font: -webkit-small-control;
- border: 1px solid #7f9db9;
+ border: 1px solid #bfbfbf;
background-color: white;
overflow: hidden;
+ padding: 4px;
}
+
.suggestion-list-entry {
white-space: nowrap;
- height: 1.73em;
- line-height: 1.73em;
-webkit-select: none;
cursor: default;
+ border-radius: 2px;
+ font-size: 14px;
+ height: 32px;
+ line-height: 32px;
}
.suggestion-list-entry:focus {
- outline: none;
+ background-color: #E5E5E5 !important;
+ outline: solid 2px -webkit-focus-ring-color;
+ outline-offset: -2px;
}
.suggestion-list-entry .content {
@@ -26,9 +31,9 @@
.suggestion-list-entry .label {
text-align: right;
- color: #737373;
float: right;
padding: 0 4px 0 20px;
+ color: rgba(16, 16, 16, 0.6) !important;
}
.rtl .suggestion-list-entry .label {
@@ -39,6 +44,7 @@
.suggestion-list-entry .title {
direction: ltr;
display: inline-block;
+ color: #101010;
}
.locale-rtl .suggestion-list-entry .title {
@@ -55,45 +61,19 @@
height: 0;
}
-.controls-refresh .suggestion-list {
- border-color: #bfbfbf;
- padding: 4px;
-}
-
-.controls-refresh .suggestion-list-entry {
- border-radius: 2px;
- font-size: 14px;
- height: 32px;
- line-height: 32px;
-}
-
-.controls-refresh .suggestion-list-entry:focus {
- background-color: #E5E5E5;
- outline: solid 2px -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-
-.controls-refresh .suggestion-list-entry .title {
- color: #101010;
-}
-
-.controls-refresh .suggestion-list-entry .label {
- color: rgba(16, 16, 16, 0.6) !important;
-}
-
@media (forced-colors: active) {
- .controls-refresh .suggestion-list-entry:focus {
+ .suggestion-list-entry:focus {
background-color: Highlight !important;
forced-color-adjust: none;
}
- .controls-refresh .suggestion-list-entry:focus .label,
- .controls-refresh .suggestion-list-entry:focus .title {
+ .suggestion-list-entry:focus .label,
+ .suggestion-list-entry:focus .title {
color: HighlightText !important;
}
- .controls-refresh .suggestion-list-entry .label,
- .controls-refresh .suggestion-list-entry .title {
+ .suggestion-list-entry .label,
+ .suggestion-list-entry .title {
color: WindowText !important;
}
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.js
index 760c04e1022..af4986978ab 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.js
@@ -211,12 +211,6 @@ SuggestionPicker.prototype._layout = function() {
this._config.suggestionLabels[i], this._config.suggestionValues[i]));
}
if (this._config.showOtherDateEntry) {
- // Add separator
- if (!global.params.isFormControlsRefreshEnabled) {
- var separator = createElement('div', 'separator');
- this._containerElement.appendChild(separator);
- }
-
// Add "Other..." entry
var otherEntry = this._createActionEntryElement(
this._config.otherDateLabel,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/select_type.cc b/chromium/third_party/blink/renderer/core/html/forms/select_type.cc
index 53830fb55b0..541a3e56671 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/select_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -357,8 +357,6 @@ bool MenuListSelectType::PopupIsVisible() const {
void MenuListSelectType::SetPopupIsVisible(bool popup_is_visible) {
popup_is_visible_ = popup_is_visible;
- if (!::features::IsFormControlsRefreshEnabled())
- return;
if (auto* layout_object = select_->GetLayoutObject()) {
// Invalidate paint to ensure that the focus ring is updated.
layout_object->SetShouldDoFullPaintInvalidation();
@@ -486,11 +484,13 @@ String MenuListSelectType::UpdateTextStyleInternal() {
const ComputedStyle* inner_style = inner_element.GetComputedStyle();
if (inner_style && option_style &&
((option_style->Direction() != inner_style->Direction() ||
- option_style->GetUnicodeBidi() != inner_style->GetUnicodeBidi()))) {
+ option_style->GetUnicodeBidi() != inner_style->GetUnicodeBidi() ||
+ option_style->GetTextAlign(true) != inner_style->GetTextAlign(true)))) {
scoped_refptr<ComputedStyle> cloned_style =
ComputedStyle::Clone(*inner_style);
cloned_style->SetDirection(option_style->Direction());
cloned_style->SetUnicodeBidi(option_style->GetUnicodeBidi());
+ cloned_style->SetTextAlign(option_style->GetTextAlign(true));
if (auto* inner_layout = inner_element.GetLayoutObject()) {
inner_layout->SetModifiedStyleOutsideStyleRecalc(
std::move(cloned_style), LayoutObject::ApplyStyleChanges::kYes);
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 21676c674ac..5bad6de0975 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
@@ -63,12 +63,10 @@ void SliderThumbElement::SetPositionFromValue() {
if (GetLayoutObject()) {
GetLayoutObject()->SetNeedsLayoutAndFullPaintInvalidation(
layout_invalidation_reason::kSliderValueChanged);
- if (features::IsFormControlsRefreshEnabled()) {
- HTMLInputElement* input(HostInput());
- if (input && input->GetLayoutObject()) {
- // the slider track selected value needs to be updated.
- input->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
- }
+ HTMLInputElement* input(HostInput());
+ if (input && input->GetLayoutObject()) {
+ // the slider track selected value needs to be updated.
+ input->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
}
}
}
@@ -238,7 +236,7 @@ void SliderThumbElement::DefaultEventHandler(Event& event) {
HTMLDivElement::DefaultEventHandler(event);
}
-bool SliderThumbElement::WillRespondToMouseMoveEvents() {
+bool SliderThumbElement::WillRespondToMouseMoveEvents() const {
const HTMLInputElement* input = HostInput();
if (input && !input->IsDisabledFormControl() && in_drag_mode_)
return true;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.h b/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.h
index a554003af68..6eb2976e2ff 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.h
@@ -52,7 +52,7 @@ class SliderThumbElement final : public HTMLDivElement {
void DragFrom(const LayoutPoint&);
void DefaultEventHandler(Event&) override;
- bool WillRespondToMouseMoveEvents() override;
+ bool WillRespondToMouseMoveEvents() const override;
bool WillRespondToMouseClickEvents() override;
void DetachLayoutTree(bool performing_reattach) override;
const AtomicString& ShadowPseudoId() const override;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc
index b70a2b407a0..4d383573ffe 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc
@@ -146,7 +146,7 @@ void SpinButtonElement::ForwardEvent(Event& event) {
event.SetDefaultHandled();
}
-bool SpinButtonElement::WillRespondToMouseMoveEvents() {
+bool SpinButtonElement::WillRespondToMouseMoveEvents() const {
if (GetLayoutBox() && ShouldRespondToMouseEvents())
return true;
@@ -216,7 +216,7 @@ void SpinButtonElement::RepeatingTimerFired(TimerBase*) {
Step(up_down_state_ == kUp ? 1 : -1);
}
-bool SpinButtonElement::ShouldRespondToMouseEvents() {
+bool SpinButtonElement::ShouldRespondToMouseEvents() const {
return !spin_button_owner_ ||
spin_button_owner_->ShouldSpinButtonRespondToMouseEvents();
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h
index dad46a74870..d6079335a8b 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
@@ -67,7 +67,7 @@ class CORE_EXPORT SpinButtonElement final : public HTMLDivElement,
void Step(int amount);
- bool WillRespondToMouseMoveEvents() override;
+ bool WillRespondToMouseMoveEvents() const override;
bool WillRespondToMouseClickEvents() override;
void ForwardEvent(Event&);
@@ -88,7 +88,7 @@ class CORE_EXPORT SpinButtonElement final : public HTMLDivElement,
void StartRepeatingTimer();
void StopRepeatingTimer();
void RepeatingTimerFired(TimerBase*);
- bool ShouldRespondToMouseEvents();
+ bool ShouldRespondToMouseEvents() const;
bool IsMouseFocusable() const override { return false; }
Member<SpinButtonOwner> spin_button_owner_;
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 17ead81c6ba..4f9f1c9197d 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
@@ -158,6 +158,9 @@ TextControlInnerEditorElement::CreateInnerEditorStyle() const {
// The inner block, if present, always has its direction set to LTR,
// so we need to inherit the direction and unicode-bidi style from the
// element.
+ // TODO(https://crbug.com/1101564): The custom inheritance done here means we
+ // need to mark for style recalc inside style recalc. See the workaround in
+ // LayoutTextControl::StyleDidChange.
text_block_style->SetDirection(start_style.Direction());
text_block_style->SetUnicodeBidi(start_style.GetUnicodeBidi());
text_block_style->SetUserSelect(EUserSelect::kText);
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 f217138591e..d0e17f104c2 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
@@ -89,7 +89,13 @@ class DataListIndicatorElement final : public HTMLDivElement {
}
public:
- DataListIndicatorElement(Document& document) : HTMLDivElement(document) {
+ explicit DataListIndicatorElement(Document& document)
+ : HTMLDivElement(document) {}
+
+ // This function should be called after appending |this| to a UA ShadowRoot.
+ void InitializeInShadowTree() {
+ DCHECK(ContainingShadowRoot());
+ DCHECK(ContainingShadowRoot()->IsUserAgent());
SetShadowPseudoId(AtomicString("-webkit-calendar-picker-indicator"));
setAttribute(html_names::kIdAttr, shadow_element_names::kIdPickerIndicator);
setAttribute(html_names::kStyleAttr,
@@ -320,8 +326,9 @@ void TextFieldInputType::CreateShadowSubtree() {
container->AppendChild(editing_view_port);
if (should_have_data_list_indicator) {
- container->AppendChild(
- MakeGarbageCollected<DataListIndicatorElement>(document));
+ auto* data_list = MakeGarbageCollected<DataListIndicatorElement>(document);
+ container->AppendChild(data_list);
+ data_list->InitializeInShadowTree();
}
// FIXME: Because of a special handling for a spin button in
// LayoutTextControlSingleLine, we need to put it to the last position. It's
@@ -360,9 +367,10 @@ void TextFieldInputType::ListAttributeTargetChanged() {
if (will_have_picker_indicator) {
Document& document = GetElement().GetDocument();
if (Element* container = ContainerElement()) {
- container->InsertBefore(
- MakeGarbageCollected<DataListIndicatorElement>(document),
- GetSpinButtonElement());
+ auto* data_list =
+ MakeGarbageCollected<DataListIndicatorElement>(document);
+ container->InsertBefore(data_list, GetSpinButtonElement());
+ data_list->InitializeInShadowTree();
} else {
// FIXME: The following code is similar to createShadowSubtree(),
// but they are different. We should simplify the code by making
@@ -377,8 +385,10 @@ void TextFieldInputType::ListAttributeTargetChanged() {
MakeGarbageCollected<EditingViewPortElement>(document);
editing_view_port->AppendChild(inner_editor);
rp_container->AppendChild(editing_view_port);
- rp_container->AppendChild(
- MakeGarbageCollected<DataListIndicatorElement>(document));
+ auto* data_list =
+ MakeGarbageCollected<DataListIndicatorElement>(document);
+ rp_container->AppendChild(data_list);
+ data_list->InitializeInShadowTree();
if (GetElement().GetDocument().FocusedElement() == GetElement())
GetElement().UpdateFocusAppearance(SelectionBehaviorOnFocus::kRestore);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/time_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/time_input_type.cc
index e56c81b5b43..3e5cd6df6cc 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/time_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/time_input_type.cc
@@ -124,8 +124,7 @@ String TimeInputType::FormatDateTimeFieldsState(
if (!date_time_fields_state.HasHour() ||
!date_time_fields_state.HasMinute() || !date_time_fields_state.HasAMPM())
return g_empty_string;
- if (date_time_fields_state.HasMillisecond() &&
- date_time_fields_state.Millisecond()) {
+ if (date_time_fields_state.HasMillisecond()) {
return String::Format(
"%02u:%02u:%02u.%03u", date_time_fields_state.Hour23(),
date_time_fields_state.Minute(),
@@ -133,7 +132,7 @@ String TimeInputType::FormatDateTimeFieldsState(
: 0,
date_time_fields_state.Millisecond());
}
- if (date_time_fields_state.HasSecond() && date_time_fields_state.Second()) {
+ if (date_time_fields_state.HasSecond()) {
return String::Format("%02u:%02u:%02u", date_time_fields_state.Hour23(),
date_time_fields_state.Minute(),
date_time_fields_state.Second());
@@ -174,7 +173,7 @@ bool TimeInputType::IsValidFormat(bool has_year,
return has_hour && has_minute && has_ampm;
}
-String TimeInputType::AriaRoleForPickerIndicator() const {
+String TimeInputType::AriaLabelForPickerIndicator() const {
return GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_TIME_PICKER);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/time_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/time_input_type.h
index 2b520a8899d..420e37e402e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/time_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/time_input_type.h
@@ -62,7 +62,7 @@ class TimeInputType final : public BaseTemporalInputType {
bool has_hour,
bool has_minute,
bool has_second) const override;
- String AriaRoleForPickerIndicator() const override;
+ String AriaLabelForPickerIndicator() const override;
String ReversedRangeOutOfRangeText(const Decimal& minimum,
const Decimal& maximum) const override;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/type_ahead.cc b/chromium/third_party/blink/renderer/core/html/forms/type_ahead.cc
index d1593e080c7..7f09009bf95 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/type_ahead.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/type_ahead.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
@@ -79,7 +80,7 @@ int TypeAhead::HandleEvent(const KeyboardEvent& event,
if (match_mode & kCycleFirstChar && c == repeating_char_) {
// The user is likely trying to cycle through all the items starting
// with this character, so just search on the character.
- prefix = String(&c, 1);
+ prefix = String(&c, 1u);
repeating_char_ = c;
} else if (match_mode & kMatchPrefix) {
prefix = buffer_.ToString();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/type_ahead.h b/chromium/third_party/blink/renderer/core/html/forms/type_ahead.h
index 3d52675a5db..78da97b6ce4 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/type_ahead.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/type_ahead.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_TYPE_AHEAD_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_TYPE_AHEAD_H_
+#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/html/forms/validity_state.h b/chromium/third_party/blink/renderer/core/html/forms/validity_state.h
index 73453e61f04..8369f961355 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/validity_state.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/validity_state.h
@@ -24,7 +24,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_VALIDITY_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_VALIDITY_STATE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/forms/listed_element.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -35,6 +34,8 @@ class ValidityState final : public ScriptWrappable {
public:
explicit ValidityState(ListedElement* control) : control_(control) {}
+ ValidityState(const ValidityState&) = delete;
+ ValidityState& operator=(const ValidityState&) = delete;
void Trace(Visitor* visitor) const override {
visitor->Trace(control_);
@@ -59,8 +60,6 @@ class ValidityState final : public ScriptWrappable {
private:
Member<ListedElement> control_;
-
- DISALLOW_COPY_AND_ASSIGN(ValidityState);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/week_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/week_input_type.cc
index 0501230b551..a15a466e52e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/week_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/week_input_type.cc
@@ -126,7 +126,7 @@ bool WeekInputType::IsValidFormat(bool has_year,
return has_year && has_week;
}
-String WeekInputType::AriaRoleForPickerIndicator() const {
+String WeekInputType::AriaLabelForPickerIndicator() const {
return GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_WEEK_PICKER);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/week_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/week_input_type.h
index b8b176bbaad..66fd23b06c8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/week_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/week_input_type.h
@@ -61,7 +61,7 @@ class WeekInputType final : public BaseTemporalInputType {
bool has_hour,
bool has_minute,
bool has_second) const override;
- String AriaRoleForPickerIndicator() const override;
+ String AriaLabelForPickerIndicator() const override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_all_collection.cc b/chromium/third_party/blink/renderer/core/html/html_all_collection.cc
index 8d105e144a4..33a480503be 100644
--- a/chromium/third_party/blink/renderer/core/html/html_all_collection.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_all_collection.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/html/html_all_collection.h"
-#include "third_party/blink/renderer/bindings/core/v8/html_collection_or_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_element_htmlcollection.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -45,7 +44,6 @@ Element* HTMLAllCollection::AnonymousIndexedGetter(unsigned index) {
return HTMLCollection::item(index);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionElementOrHTMLCollection* HTMLAllCollection::NamedGetter(
const AtomicString& name) {
HTMLCollection* items = GetDocument().DocumentAllNamedItems(name);
@@ -59,21 +57,5 @@ V8UnionElementOrHTMLCollection* HTMLAllCollection::NamedGetter(
return MakeGarbageCollected<V8UnionElementOrHTMLCollection>(items);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLAllCollection::NamedGetter(const AtomicString& name,
- HTMLCollectionOrElement& return_value) {
- HTMLCollection* items = GetDocument().DocumentAllNamedItems(name);
-
- if (!items->length())
- return;
-
- if (items->length() == 1) {
- return_value.SetElement(items->item(0));
- return;
- }
-
- return_value.SetHTMLCollection(items);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_all_collection.h b/chromium/third_party/blink/renderer/core/html/html_all_collection.h
index 15783e52b96..ab0d6c4b35e 100644
--- a/chromium/third_party/blink/renderer/core/html/html_all_collection.h
+++ b/chromium/third_party/blink/renderer/core/html/html_all_collection.h
@@ -31,7 +31,6 @@
namespace blink {
class Element;
-class HTMLCollectionOrElement;
class V8UnionElementOrHTMLCollection;
class HTMLAllCollection final : public HTMLCollection {
@@ -43,11 +42,7 @@ class HTMLAllCollection final : public HTMLCollection {
~HTMLAllCollection() override;
Element* AnonymousIndexedGetter(unsigned index);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionElementOrHTMLCollection* NamedGetter(const AtomicString& name);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void NamedGetter(const AtomicString& name, HTMLCollectionOrElement&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
} // namespace blink
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 3d29663674d..07e67aef1a6 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
@@ -332,7 +332,7 @@ String HTMLAnchorElement::Input() const {
return FastGetAttribute(html_names::kHrefAttr);
}
-void HTMLAnchorElement::SetInput(const String& value) {
+void HTMLAnchorElement::setHref(const String& value) {
SetHref(AtomicString(value));
}
@@ -446,9 +446,11 @@ void HTMLAnchorElement::HandleClick(Event& event) {
request.SetReferrerPolicy(policy);
}
- // Ignore the download attribute if we either can't read the content, or
- // the event is an alt-click or similar.
LocalFrame* frame = window->GetFrame();
+ request.SetHasUserGesture(LocalFrame::HasTransientUserActivation(frame));
+
+ // Respect the download attribute only if we can read the content, and the
+ // event is not an alt-click or similar.
if (FastHasAttribute(html_names::kDownloadAttr) &&
NavigationPolicyFromEvent(&event) != kNavigationPolicyDownload &&
window->GetSecurityOrigin()->CanReadContent(completed_url)) {
@@ -471,7 +473,6 @@ void HTMLAnchorElement::HandleClick(Event& event) {
}
request.SetRequestContext(mojom::blink::RequestContextType::HYPERLINK);
- request.SetHasUserGesture(LocalFrame::HasTransientUserActivation(frame));
const AtomicString& target = GetEffectiveTarget();
FrameLoadRequest frame_request(window, request);
frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(&event));
diff --git a/chromium/third_party/blink/renderer/core/html/html_anchor_element.h b/chromium/third_party/blink/renderer/core/html/html_anchor_element.h
index 6b389dd38d6..c9e4b450a91 100644
--- a/chromium/third_party/blink/renderer/core/html/html_anchor_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -24,7 +24,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_ANCHOR_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_ANCHOR_ELEMENT_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_impression.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -71,6 +70,7 @@ class CORE_EXPORT HTMLAnchorElement : public HTMLElement, public DOMURLUtils {
KURL Href() const;
void SetHref(const AtomicString&);
+ void setHref(const String&);
const AtomicString& GetName() const;
@@ -82,7 +82,6 @@ class CORE_EXPORT HTMLAnchorElement : public HTMLElement, public DOMURLUtils {
void SetURL(const KURL&) final;
String Input() const final;
- void SetInput(const String&) final;
bool IsLiveLink() const final;
diff --git a/chromium/third_party/blink/renderer/core/html/html_anchor_element.idl b/chromium/third_party/blink/renderer/core/html/html_anchor_element.idl
index 03676cede30..c7c31dafe0e 100644
--- a/chromium/third_party/blink/renderer/core/html/html_anchor_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_anchor_element.idl
@@ -40,7 +40,7 @@
[RuntimeEnabled=ConversionMeasurement, CEReactions,Reflect] attribute USVString attributionDestination;
[RuntimeEnabled=ConversionMeasurement, CEReactions,Reflect] attribute USVString attributionReportTo;
[RuntimeEnabled=ConversionMeasurement, CEReactions,Reflect] attribute DOMString attributionExpiry;
- [RuntimeEnabled=ConversionMeasurement, CEReactions,Reflect] attribute boolean registerAttributionSource;
+ [RuntimeEnabled=ConversionMeasurementEventSources, CEReactions,Reflect] attribute boolean registerAttributionSource;
[RuntimeEnabled=ConversionMeasurement, CEReactions,Reflect] attribute DOMString attributionSourcePriority;
// obsolete members
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 712ae07e6be..04210d127da 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
@@ -20,6 +20,7 @@
"allowpaymentrequest",
"alt",
"anchor",
+ "anonymous",
"archive",
"as",
"async",
@@ -79,7 +80,6 @@
"disabled",
"disablepictureinpicture",
"disableremoteplayback",
- "disallowdocumentaccess",
"download",
"draggable",
"elementtiming",
diff --git a/chromium/third_party/blink/renderer/core/html/html_collection.idl b/chromium/third_party/blink/renderer/core/html/html_collection.idl
index 9efafff6f56..f072f5cbc25 100644
--- a/chromium/third_party/blink/renderer/core/html/html_collection.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_collection.idl
@@ -25,7 +25,7 @@
Exposed=Window,
LegacyUnenumerableNamedProperties
] interface HTMLCollection {
- [Affects=Nothing] readonly attribute unsigned long length;
+ readonly attribute unsigned long length;
[Affects=Nothing] getter Element? item(unsigned long index);
getter Element? namedItem(DOMString name);
};
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 011742c04d2..1b8de6b983e 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
@@ -92,8 +92,16 @@ void HTMLDetailsElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
HTMLSlotElement* content_slot =
HTMLSlotElement::CreateUserAgentDefaultSlot(GetDocument());
content_slot->SetIdAttribute(shadow_element_names::kIdDetailsContent);
- content_slot->SetInlineStyleProperty(CSSPropertyID::kDisplay,
- CSSValueID::kNone);
+ if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) {
+ content_slot->SetInlineStyleProperty(CSSPropertyID::kContentVisibility,
+ CSSValueID::kHidden);
+ content_slot->EnsureDisplayLockContext().SetForDetailsElement(true);
+ content_slot->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+ CSSValueID::kBlock);
+ } else {
+ content_slot->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+ CSSValueID::kNone);
+ }
root.AppendChild(content_slot);
auto* default_summary_style = MakeGarbageCollected<HTMLStyleElement>(
@@ -143,11 +151,25 @@ void HTMLDetailsElement::ParseAttribute(
Element* content = EnsureUserAgentShadowRoot().getElementById(
shadow_element_names::kIdDetailsContent);
DCHECK(content);
- if (is_open_) {
- content->RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
+
+ if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) {
+ if (is_open_) {
+ content->RemoveInlineStyleProperty(CSSPropertyID::kContentVisibility);
+ content->RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
+ } else {
+ content->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+ CSSValueID::kBlock);
+ content->SetInlineStyleProperty(CSSPropertyID::kContentVisibility,
+ CSSValueID::kHidden);
+ content->EnsureDisplayLockContext().SetForDetailsElement(true);
+ }
} else {
- content->SetInlineStyleProperty(CSSPropertyID::kDisplay,
- CSSValueID::kNone);
+ if (is_open_) {
+ content->RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
+ } else {
+ content->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+ CSSValueID::kNone);
+ }
}
return;
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 553fd3f5397..82a99c1357e 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,6 +25,7 @@
#include "third_party/blink/renderer/core/html/html_dialog_element.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_focus_options.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/flat_tree_traversal.h"
@@ -109,7 +110,8 @@ static void InertSubtreesChanged(Document& document) {
HTMLDialogElement::HTMLDialogElement(Document& document)
: HTMLElement(html_names::kDialogTag, document),
is_modal_(false),
- return_value_("") {
+ return_value_(""),
+ previously_focused_element_(nullptr) {
UseCounter::Count(document, WebFeature::kDialogElement);
}
@@ -130,6 +132,17 @@ void HTMLDialogElement::close(const String& return_value) {
return_value_ = return_value;
ScheduleCloseEvent();
+
+ // We should call focus() last since it will fire a focus event which could
+ // modify this element.
+ if (RuntimeEnabledFeatures::DialogFocusNewSpecBehaviorEnabled() &&
+ previously_focused_element_) {
+ FocusOptions* focus_options = FocusOptions::Create();
+ focus_options->setPreventScroll(true);
+ Element* previously_focused_element = previously_focused_element_;
+ previously_focused_element_ = nullptr;
+ previously_focused_element->focus(focus_options);
+ }
}
void HTMLDialogElement::SetIsModal(bool is_modal) {
@@ -158,6 +171,8 @@ void HTMLDialogElement::show() {
// Element::isFocusable, which requires an up-to-date layout.
GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kJavaScript);
+ previously_focused_element_ = GetDocument().FocusedElement();
+
SetFocusForDialog(this);
}
@@ -197,6 +212,8 @@ void HTMLDialogElement::showModal(ExceptionState& exception_state) {
// is thrown away.
InertSubtreesChanged(GetDocument());
+ previously_focused_element_ = GetDocument().FocusedElement();
+
SetFocusForDialog(this);
}
@@ -215,4 +232,9 @@ void HTMLDialogElement::DefaultEventHandler(Event& event) {
HTMLElement::DefaultEventHandler(event);
}
+void HTMLDialogElement::Trace(Visitor* visitor) const {
+ visitor->Trace(previously_focused_element_);
+ HTMLElement::Trace(visitor);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_dialog_element.h b/chromium/third_party/blink/renderer/core/html/html_dialog_element.h
index 605672be06b..56c6579327d 100644
--- a/chromium/third_party/blink/renderer/core/html/html_dialog_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_dialog_element.h
@@ -40,6 +40,8 @@ class HTMLDialogElement final : public HTMLElement {
public:
explicit HTMLDialogElement(Document&);
+ void Trace(Visitor*) const override;
+
void close(const String& return_value = String());
void show();
void showModal(ExceptionState&);
@@ -60,6 +62,7 @@ class HTMLDialogElement final : public HTMLElement {
bool is_modal_;
String return_value_;
+ WeakMember<Element> previously_focused_element_;
};
} // namespace blink
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 0dc17182bdc..f7ebe93f21b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_document.cc
@@ -20,7 +20,7 @@
* Boston, MA 02110-1301, USA.
*
* Portions are Copyright (C) 2002 Netscape Communications Corporation.
- * Other contributors: David Baron <dbaron@fas.harvard.edu>
+ * Other contributors: David Baron <dbaron@dbaron.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -53,7 +53,7 @@
#include "third_party/blink/renderer/core/html/html_document.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#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"
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 d1994f67a82..46185c32520 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_element.cc
@@ -25,10 +25,8 @@
#include "third_party/blink/renderer/core/html/html_element.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_treat_null_as_empty_string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_stringtreatnullasemptystring_trustedscript.h"
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
@@ -81,6 +79,7 @@
#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/layout/layout_object.h"
+#include "third_party/blink/renderer/core/mathml/mathml_element.h"
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -110,37 +109,41 @@ struct AttributeTriggers {
namespace {
-// https://w3c.github.io/editing/execCommand.html#editing-host
-bool IsEditingHost(const Node& node) {
- auto* html_element = DynamicTo<HTMLElement>(node);
- if (!html_element)
- return false;
- String normalized_value = html_element->contentEditable();
- if (normalized_value == "true" || normalized_value == "plaintext-only")
- return true;
- return node.GetDocument().InDesignMode() &&
- node.GetDocument().documentElement() == &node;
-}
-
+// https://html.spec.whatwg.org/multipage/interaction.html#editing-host
+// An editing host is either an HTML element with its contenteditable attribute
+// in the true state, or a child HTML element of a Document whose design mode
+// enabled is true.
// https://w3c.github.io/editing/execCommand.html#editable
-bool IsEditable(const Node& node) {
- if (IsEditingHost(node))
- return false;
+// Something is editable if it is a node; it is not an editing host; it does not
+// have a contenteditable attribute set to the false state; its parent is an
+// editing host or editable; and either it is an HTML element, or it is an svg
+// or math element, or it is not an Element and its parent is an HTML element.
+bool IsEditableOrEditingHost(const Node& node) {
auto* html_element = DynamicTo<HTMLElement>(node);
- if (html_element && html_element->contentEditable() == "false")
- return false;
+ if (html_element) {
+ ContentEditableType content_editable =
+ html_element->contentEditableNormalized();
+ if (content_editable == ContentEditableType::kContentEditable ||
+ content_editable == ContentEditableType::kPlaintextOnly)
+ return true;
+ if (html_element->GetDocument().InDesignMode() &&
+ html_element->isConnected()) {
+ return true;
+ }
+ if (content_editable == ContentEditableType::kNotContentEditable)
+ return false;
+ }
if (!node.parentNode())
return false;
- if (!IsEditingHost(*node.parentNode()) && !IsEditable(*node.parentNode()))
+ if (!IsEditableOrEditingHost(*node.parentNode()))
return false;
if (html_element)
return true;
if (IsA<SVGSVGElement>(node))
return true;
- auto* element = DynamicTo<Element>(node);
- if (element && element->HasTagName(mathml_names::kMathTag))
- return true;
- return !element && node.parentNode()->IsHTMLElement();
+ if (auto* mathml_element = DynamicTo<MathMLElement>(node))
+ return mathml_element->HasTagName(mathml_names::kMathTag);
+ return !IsA<Element>(node) && node.parentNode()->IsHTMLElement();
}
const WebFeature kNoWebFeature = static_cast<WebFeature>(0);
@@ -839,7 +842,6 @@ DocumentFragment* HTMLElement::TextToFragment(const String& text,
return fragment;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionStringTreatNullAsEmptyStringOrTrustedScript*
HTMLElement::innerTextForBinding() {
return MakeGarbageCollected<
@@ -863,23 +865,6 @@ void HTMLElement::setInnerTextForBinding(
}
setInnerText(value, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLElement::innerTextForBinding(
- StringTreatNullAsEmptyStringOrTrustedScript& result) {
- result.SetString(innerText());
-}
-
-void HTMLElement::setInnerTextForBinding(
- const StringTreatNullAsEmptyStringOrTrustedScript& string_or_trusted_script,
- ExceptionState& exception_state) {
- String value;
- if (string_or_trusted_script.IsString())
- value = string_or_trusted_script.GetAsString();
- else if (string_or_trusted_script.IsTrustedScript())
- value = string_or_trusted_script.GetAsTrustedScript()->toString();
- setInnerText(value, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String HTMLElement::innerText() {
return Element::innerText();
@@ -924,14 +909,6 @@ void HTMLElement::setOuterText(const String& text,
else
new_child = Text::Create(GetDocument(), text);
- // textToFragment might cause mutation events.
- if (!parentNode()) {
- // TODO(crbug.com/1206014) We can likely remove this entire if() block.
- NOTREACHED();
- exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
- "The element has no parent.");
- }
-
if (exception_state.HadException())
return;
@@ -1017,20 +994,33 @@ bool HTMLElement::HasCustomFocusLogic() const {
return false;
}
-String HTMLElement::contentEditable() const {
+ContentEditableType HTMLElement::contentEditableNormalized() const {
const AtomicString& value =
FastGetAttribute(html_names::kContenteditableAttr);
if (value.IsNull())
- return "inherit";
+ return ContentEditableType::kInherit;
if (value.IsEmpty() || EqualIgnoringASCIICase(value, "true"))
- return "true";
+ return ContentEditableType::kContentEditable;
if (EqualIgnoringASCIICase(value, "false"))
- return "false";
+ return ContentEditableType::kNotContentEditable;
if (EqualIgnoringASCIICase(value, "plaintext-only"))
- return "plaintext-only";
+ return ContentEditableType::kPlaintextOnly;
+
+ return ContentEditableType::kInherit;
+}
- return "inherit";
+String HTMLElement::contentEditable() const {
+ switch (contentEditableNormalized()) {
+ case ContentEditableType::kInherit:
+ return "inherit";
+ case ContentEditableType::kContentEditable:
+ return "true";
+ case ContentEditableType::kNotContentEditable:
+ return "false";
+ case ContentEditableType::kPlaintextOnly:
+ return "plaintext-only";
+ }
}
void HTMLElement::setContentEditable(const String& enabled,
@@ -1077,7 +1067,7 @@ void HTMLElement::setAutocapitalize(const AtomicString& value) {
}
bool HTMLElement::isContentEditableForBinding() const {
- return IsEditingHost(*this) || IsEditable(*this);
+ return IsEditableOrEditingHost(*this);
}
bool HTMLElement::draggable() const {
@@ -1208,8 +1198,10 @@ bool HTMLElement::HasDirectionAuto() const {
EqualIgnoringASCIICase(direction, "auto");
}
-TextDirection HTMLElement::ResolveAutoDirectionality(bool& is_deferred,
- Node* stay_within) const {
+template <typename Traversal>
+absl::optional<TextDirection> HTMLElement::ResolveAutoDirectionality(
+ bool& is_deferred,
+ Node* stay_within) const {
is_deferred = false;
if (auto* input_element = DynamicTo<HTMLInputElement>(*this)) {
bool has_strong_directionality;
@@ -1217,7 +1209,11 @@ TextDirection HTMLElement::ResolveAutoDirectionality(bool& is_deferred,
&has_strong_directionality);
}
- Node* node = FlatTreeTraversal::FirstChild(*this);
+ // For <textarea>, the heuristic is applied on a per-paragraph level, and
+ // we should traverse the flat tree.
+ Node* node = (IsA<HTMLTextAreaElement>(*this) || IsA<HTMLSlotElement>(*this))
+ ? FlatTreeTraversal::FirstChild(*this)
+ : Traversal::FirstChild(*this);
while (node) {
// Skip bdi, script, style and text form controls.
auto* element = DynamicTo<Element>(node);
@@ -1226,11 +1222,12 @@ TextDirection HTMLElement::ResolveAutoDirectionality(bool& is_deferred,
(element && element->IsTextControl()) ||
(element && element->ShadowPseudoId() ==
shadow_element_names::kPseudoInputPlaceholder)) {
- node = FlatTreeTraversal::NextSkippingChildren(*node, stay_within);
+ node = Traversal::NextSkippingChildren(*node, stay_within);
continue;
}
- if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(node)) {
+ auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(node);
+ if (slot) {
ShadowRoot* root = slot->ContainingShadowRoot();
// Defer to adjust the directionality to avoid recalcuating slot
// assignment in FlatTreeTraversal when updating slot.
@@ -1247,7 +1244,7 @@ TextDirection HTMLElement::ResolveAutoDirectionality(bool& is_deferred,
AtomicString dir_attribute_value =
element_node->FastGetAttribute(html_names::kDirAttr);
if (IsValidDirAttribute(dir_attribute_value)) {
- node = FlatTreeTraversal::NextSkippingChildren(*node, stay_within);
+ node = Traversal::NextSkippingChildren(*node, stay_within);
continue;
}
}
@@ -1259,16 +1256,27 @@ TextDirection HTMLElement::ResolveAutoDirectionality(bool& is_deferred,
if (has_strong_directionality)
return text_direction;
}
- node = FlatTreeTraversal::Next(*node, stay_within);
+
+ if (slot) {
+ absl::optional<TextDirection> text_direction =
+ slot->ResolveAutoDirectionality<FlatTreeTraversal>(is_deferred,
+ stay_within);
+ if (text_direction.has_value())
+ return text_direction;
+ }
+
+ node = Traversal::Next(*node, stay_within);
}
- return TextDirection::kLtr;
+ return absl::nullopt;
}
void HTMLElement::AdjustDirectionalityIfNeededAfterChildAttributeChanged(
Element* child) {
DCHECK(SelfOrAncestorHasDirAutoAttribute());
bool is_deferred;
- TextDirection text_direction = ResolveAutoDirectionality(is_deferred, this);
+ TextDirection text_direction =
+ ResolveAutoDirectionality<NodeTraversal>(is_deferred, this)
+ .value_or(TextDirection::kLtr);
if (CachedDirectionality() != text_direction && !is_deferred) {
SetCachedDirectionality(text_direction);
@@ -1294,7 +1302,8 @@ void HTMLElement::AdjustDirectionalityIfNeededAfterChildAttributeChanged(
bool HTMLElement::CalculateAndAdjustAutoDirectionality(Node* stay_within) {
bool is_deferred = false;
TextDirection text_direction =
- ResolveAutoDirectionality(is_deferred, stay_within);
+ ResolveAutoDirectionality<NodeTraversal>(is_deferred, stay_within)
+ .value_or(TextDirection::kLtr);
if (CachedDirectionality() != text_direction && !is_deferred) {
UpdateDirectionalityAndDescendant(text_direction);
@@ -1384,21 +1393,14 @@ void HTMLElement::AdjustCandidateDirectionalityForSlot(
for (auto& node : candidate_set) {
Node* node_to_adjust = node.Get();
if (!node->SelfOrAncestorHasDirAutoAttribute()) {
- auto* slot = node->AssignedSlot();
- auto* parent =
- DynamicTo<HTMLElement>(FlatTreeTraversal::ParentElement(*node));
if (ElementAffectsDirectionality(node))
continue;
+ auto* slot = node->AssignedSlot();
if (slot && slot->SelfOrAncestorHasDirAutoAttribute()) {
node_to_adjust = slot;
- } else if (parent && parent->SelfOrAncestorHasDirAutoAttribute()) {
- node_to_adjust = parent;
} else {
- if (ElementAffectsDirectionality(slot)) {
+ if (slot && !slot->NeedsInheritDirectionalityFromParent()) {
node->SetCachedDirectionality(slot->CachedDirectionality());
- } else if (parent && !parent->NeedsInheritDirectionalityFromParent() &&
- node->NeedsInheritDirectionalityFromParent()) {
- node->SetCachedDirectionality(parent->CachedDirectionality());
}
continue;
}
@@ -1647,20 +1649,11 @@ bool HTMLElement::MatchesReadOnlyPseudoClass() const {
return !MatchesReadWritePseudoClass();
}
+// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-write
+// The :read-write pseudo-class must match ... elements that are editing hosts
+// or editable and are neither input elements nor textarea elements
bool HTMLElement::MatchesReadWritePseudoClass() const {
- if (FastHasAttribute(html_names::kContenteditableAttr)) {
- const AtomicString& value =
- FastGetAttribute(html_names::kContenteditableAttr);
-
- if (value.IsEmpty() || EqualIgnoringASCIICase(value, "true") ||
- EqualIgnoringASCIICase(value, "plaintext-only"))
- return true;
- if (EqualIgnoringASCIICase(value, "false"))
- return false;
- // All other values should be treated as "inherit".
- }
-
- return parentElement() && HasEditableStyle(*parentElement());
+ return IsEditableOrEditingHost(*this);
}
void HTMLElement::HandleKeypressEvent(KeyboardEvent& event) {
@@ -2046,4 +2039,5 @@ void dumpInnerHTML(blink::HTMLElement*);
void dumpInnerHTML(blink::HTMLElement* element) {
printf("%s\n", element->innerHTML().Ascii().c_str());
}
+
#endif
diff --git a/chromium/third_party/blink/renderer/core/html/html_element.h b/chromium/third_party/blink/renderer/core/html/html_element.h
index b3fce1aef40..5f18f3773b3 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_element.h
@@ -23,6 +23,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_ELEMENT_H_
+#include "third_party/abseil-cpp/absl/types/optional.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/dom/events/simulated_click_options.h"
@@ -40,8 +41,6 @@ class ExceptionState;
class FormAssociated;
class HTMLFormElement;
class KeyboardEvent;
-class StringOrTrustedScript;
-class StringTreatNullAsEmptyStringOrTrustedScript;
class V8UnionStringTreatNullAsEmptyStringOrTrustedScript;
enum TranslateAttributeMode {
@@ -50,6 +49,13 @@ enum TranslateAttributeMode {
kTranslateAttributeInherit
};
+enum class ContentEditableType {
+ kInherit,
+ kContentEditable,
+ kNotContentEditable,
+ kPlaintextOnly,
+};
+
class CORE_EXPORT HTMLElement : public Element {
DEFINE_WRAPPERTYPEINFO();
@@ -65,22 +71,16 @@ class CORE_EXPORT HTMLElement : public Element {
String innerText();
void setInnerText(const String&, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionStringTreatNullAsEmptyStringOrTrustedScript* innerTextForBinding();
virtual void setInnerTextForBinding(
const V8UnionStringTreatNullAsEmptyStringOrTrustedScript*
string_or_trusted_script,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void innerTextForBinding(StringTreatNullAsEmptyStringOrTrustedScript& result);
- virtual void setInnerTextForBinding(
- const StringTreatNullAsEmptyStringOrTrustedScript&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setOuterText(const String&, ExceptionState&);
virtual bool HasCustomFocusLogic() const;
+ ContentEditableType contentEditableNormalized() const;
String contentEditable() const;
void setContentEditable(const String&, ExceptionState&);
// For HTMLElement.prototype.isContentEditable. This matches to neither
@@ -228,8 +228,11 @@ class CORE_EXPORT HTMLElement : public Element {
void AdjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child);
void AdjustDirectionalityIfNeededAfterChildrenChanged(
const ChildrenChange& change);
- TextDirection ResolveAutoDirectionality(bool& is_deferred,
- Node* stay_within) const;
+
+ template <typename Traversal>
+ absl::optional<TextDirection> ResolveAutoDirectionality(
+ bool& is_deferred,
+ Node* stay_within) const;
TranslateAttributeMode GetTranslateAttributeMode() const;
diff --git a/chromium/third_party/blink/renderer/core/html/html_element.idl b/chromium/third_party/blink/renderer/core/html/html_element.idl
index 3b149427bf3..243bb1f522d 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_element.idl
@@ -30,7 +30,7 @@
[CEReactions] attribute DOMString dir;
// user interaction
- [Affects=Nothing, CEReactions, Reflect] attribute boolean hidden;
+ [CEReactions, Reflect] attribute boolean hidden;
[RuntimeCallStatsCounter=HTMLElementClick] void click();
[CEReactions, RuntimeEnabled=InertAttribute, Reflect] attribute boolean inert;
[CEReactions, Reflect] attribute DOMString accessKey;
@@ -54,19 +54,19 @@
// CSSOM View Module
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
- [Affects=Nothing, PerWorldBindings, ImplementedAs=unclosedOffsetParent] readonly attribute Element? offsetParent;
- [Affects=Nothing, ImplementedAs=offsetTopForBinding] readonly attribute long offsetTop;
- [Affects=Nothing, ImplementedAs=offsetLeftForBinding] readonly attribute long offsetLeft;
- [Affects=Nothing, ImplementedAs=offsetWidthForBinding] readonly attribute long offsetWidth;
- [Affects=Nothing, ImplementedAs=offsetHeightForBinding] readonly attribute long offsetHeight;
+ [PerWorldBindings, ImplementedAs=unclosedOffsetParent] readonly attribute Element? offsetParent;
+ [ImplementedAs=offsetTopForBinding] readonly attribute long offsetTop;
+ [ImplementedAs=offsetLeftForBinding] readonly attribute long offsetLeft;
+ [ImplementedAs=offsetWidthForBinding] readonly attribute long offsetWidth;
+ [ImplementedAs=offsetHeightForBinding] readonly attribute long offsetHeight;
// CSS Object Model (CSSOM)
// https://drafts.csswg.org/cssom/#the-elementcssinlinestyle-interface
- [Affects=Nothing, SameObject, PerWorldBindings, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
+ [SameObject, PerWorldBindings, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
// Non-standard APIs
- [Affects=Nothing, CEReactions, RaisesException=Setter, MeasureAs=HTMLElementInnerText, ImplementedAs=innerTextForBinding] attribute ([TreatNullAs=EmptyString] DOMString or TrustedScript) innerText;
- [Affects=Nothing, CEReactions, RaisesException=Setter, MeasureAs=HTMLElementOuterText] attribute [TreatNullAs=EmptyString] DOMString outerText;
+ [CEReactions, RaisesException=Setter, MeasureAs=HTMLElementInnerText, ImplementedAs=innerTextForBinding] attribute ([TreatNullAs=EmptyString] DOMString or TrustedScript) innerText;
+ [CEReactions, RaisesException=Setter, MeasureAs=HTMLElementOuterText] attribute [TreatNullAs=EmptyString] DOMString outerText;
};
HTMLElement includes GlobalEventHandlers;
diff --git a/chromium/third_party/blink/renderer/core/html/html_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_element_test.cc
index b1552b3b260..057f7c41fa1 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_element_test.cc
@@ -262,4 +262,23 @@ TEST_F(HTMLElementTest, DirAutoByChildChanged) {
EXPECT_EQ(element->GetComputedStyle()->Direction(), TextDirection::kLtr);
}
+TEST_F(HTMLElementTest, SlotDirAutoBySingleSlottedNodeRemoved) {
+ ScopedCSSPseudoDirForTest scoped_feature(false);
+
+ SetBodyInnerHTML("<div id='host'>slotted text</div>");
+ auto* element = GetDocument().getElementById("host");
+ ShadowRoot& shadow_root =
+ element->AttachShadowRootInternal(ShadowRootType::kOpen);
+ shadow_root.setInnerHTML(
+ "<slot id='inner' dir='auto'><div>&#1571;</div></slot>");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* slot = shadow_root.getElementById("inner");
+ EXPECT_EQ(slot->GetComputedStyle()->Direction(), TextDirection::kLtr);
+
+ element->RemoveChildren();
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(slot->GetComputedStyle()->Direction(), TextDirection::kRtl);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index a1a4a7fee14..c91b266e70b 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
@@ -41,6 +41,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/html/fenced_frame/html_fenced_frame_element.h"
#include "third_party/blink/renderer/core/html/lazy_load_frame_observer.h"
#include "third_party/blink/renderer/core/html/loading_attribute.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -305,16 +306,6 @@ void HTMLFrameOwnerElement::SetSandboxFlags(
}
}
-void HTMLFrameOwnerElement::SetDisallowDocumentAccesss(bool disallowed) {
- frame_policy_.disallow_document_access = disallowed;
- // Don't notify about updates if ContentFrame() is null, for example when
- // the subframe hasn't been created yet.
- if (ContentFrame()) {
- GetDocument().GetFrame()->GetLocalFrameHostRemote().DidChangeFramePolicy(
- ContentFrame()->GetFrameToken(), frame_policy_);
- }
-}
-
bool HTMLFrameOwnerElement::IsKeyboardFocusable() const {
return content_frame_ && HTMLElement::IsKeyboardFocusable();
}
@@ -490,6 +481,17 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
bool replace_current_item) {
TRACE_EVENT0("navigation", "HTMLFrameOwnerElement::LoadOrRedirectSubframe");
+ // TODO(crbug.com/1123606): Remove this once we move to the MPArch
+ // implementation. If this is the "top-level" internal <iframe> hosted within
+ // a <fencedframe> element using the ShadowDOM implementation, then we need to
+ // mark |frame_policy_| as `is_fenced=true`, so that the LocalFrame inside
+ // this frame can react accordingly. See
+ // https://docs.google.com/document/d/1ijTZJT3DHQ1ljp4QQe4E4XCCRaYAxmInNzN1SzeJM8s/edit.
+ if (ContainingShadowRoot() && ContainingShadowRoot()->IsUserAgent() &&
+ IsA<HTMLFencedFrameElement>(ContainingShadowRoot()->host())) {
+ frame_policy_.is_fenced = true;
+ }
+
// Update the |should_lazy_load_children_| value according to the "loading"
// attribute immediately, so that it still gets respected even if the "src"
// attribute gets parsed in ParseAttribute() before the "loading" attribute
@@ -517,6 +519,20 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
if (ContentFrame()) {
FrameLoadRequest frame_load_request(GetDocument().domWindow(), request);
+ // TODO(crbug.com/1123606): This is how we're temporarily restricting the
+ // referrer string on top-level frenced frame requests initiated from
+ // outside of the frame. The intention here is to redact the ultimate value
+ // of `document.referrer` so that it is consistent with what the MPArch
+ // version of fenced frames will show. We'll remove this after we've moved
+ // to the MPArch version and away from the ShadowDOM implementation. The
+ // reason we have this check here is because we only want to take this
+ // action for navigations initiated by the fenced frame's embedder. We don't
+ // need this for the initial about:blank document (i.e., when
+ // `ContentFrame()` is null) because that is taken care of for us with the
+ // shadow DOM.
+ if (frame_policy_.is_fenced) {
+ frame_load_request.GetResourceRequest().SetReferrerString("");
+ }
frame_load_request.SetClientRedirectReason(
ClientNavigationReason::kFrameNavigation);
WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard;
@@ -566,11 +582,15 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
if (!child_frame)
return false;
- // Send 'csp' attribute to the browser.
- CSPAttributeChanged();
+ // Propagate attributes like 'csp' or 'anonymous' to the browser process.
+ DidChangeAttributes();
WebFrameLoadType child_load_type = WebFrameLoadType::kReplaceCurrentItem;
- if (!GetDocument().LoadEventFinished() &&
+ // If the frame URL is not about:blank, see if it should do a
+ // kReloadBypassingCache navigation, following the parent frame. If the frame
+ // URL is about:blank, it should be committed synchronously as a
+ // kReplaceCurrentItem navigation (see https://crbug.com/778318).
+ if (url != BlankURL() && !GetDocument().LoadEventFinished() &&
GetDocument().Loader()->LoadType() ==
WebFrameLoadType::kReloadBypassingCache) {
child_load_type = WebFrameLoadType::kReloadBypassingCache;
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 ea9cd9af5c3..55e12d5b94f 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
@@ -135,7 +135,6 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
HTMLFrameOwnerElement(const QualifiedName& tag_name, Document&);
void SetSandboxFlags(network::mojom::blink::WebSandboxFlags);
- void SetDisallowDocumentAccesss(bool disallowed);
bool LoadOrRedirectSubframe(const KURL&,
const AtomicString& frame_name,
diff --git a/chromium/third_party/blink/renderer/core/html/html_html_element.cc b/chromium/third_party/blink/renderer/core/html/html_html_element.cc
index da95b0ed475..42e8cbe15d6 100644
--- a/chromium/third_party/blink/renderer/core/html/html_html_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_html_element.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h"
@@ -133,7 +134,13 @@ scoped_refptr<const ComputedStyle> HTMLHtmlElement::LayoutStyleForElement(
scoped_refptr<const ComputedStyle> style) {
DCHECK(style);
DCHECK(GetDocument().InStyleRecalc());
- if (const Element* body_element = GetDocument().body()) {
+ DCHECK(GetLayoutObject());
+ StyleResolver& resolver = GetDocument().GetStyleResolver();
+ if (resolver.ShouldStopBodyPropagation(*this))
+ return style;
+ if (const Element* body_element = GetDocument().FirstBodyElement()) {
+ if (resolver.ShouldStopBodyPropagation(*body_element))
+ return style;
if (const ComputedStyle* body_style = body_element->GetComputedStyle()) {
if (NeedsLayoutStylePropagation(*style, *body_style))
return CreateLayoutStyle(*style, *body_style);
@@ -143,25 +150,21 @@ scoped_refptr<const ComputedStyle> HTMLHtmlElement::LayoutStyleForElement(
}
void HTMLHtmlElement::PropagateWritingModeAndDirectionFromBody() {
- // Will be propagated in HTMLHtmlElement::AttachLayoutTree().
- if (NeedsReattachLayoutTree())
+ if (NeedsReattachLayoutTree()) {
+ // This means we are being called from RecalcStyle(). Since we need to
+ // reattach the layout tree, we will re-enter this method from
+ // RebuildLayoutTree().
return;
- LayoutObject* layout_object = GetLayoutObject();
- if (!layout_object)
- return;
- const ComputedStyle* style = GetComputedStyle();
- // If we have a layout object, and we are not marked for re-attachment, we are
- // guaranteed to have a non-null ComputedStyle.
- DCHECK(style);
- const ComputedStyle* propagated_style = nullptr;
- if (const Element* body = GetDocument().body())
- propagated_style = body->GetComputedStyle();
- if (!propagated_style)
- propagated_style = style;
- if (NeedsLayoutStylePropagation(layout_object->StyleRef(),
- *propagated_style)) {
+ }
+ if (Element* body_element = GetDocument().FirstBodyElement()) {
+ // Same as above.
+ if (body_element->NeedsReattachLayoutTree())
+ return;
+ }
+
+ if (auto* layout_object = GetLayoutObject()) {
scoped_refptr<const ComputedStyle> new_style =
- CreateLayoutStyle(*style, *propagated_style);
+ LayoutStyleForElement(layout_object->Style());
layout_object->SetStyle(new_style);
// We need to propagate the style to text children because the used
// writing-mode and direction affects text children. Child elements,
@@ -176,15 +179,4 @@ void HTMLHtmlElement::PropagateWritingModeAndDirectionFromBody() {
}
}
-void HTMLHtmlElement::AttachLayoutTree(AttachContext& context) {
- scoped_refptr<const ComputedStyle> original_style = GetComputedStyle();
- if (original_style)
- SetComputedStyle(LayoutStyleForElement(original_style));
-
- Element::AttachLayoutTree(context);
-
- if (original_style)
- SetComputedStyle(original_style);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_html_element.h b/chromium/third_party/blink/renderer/core/html/html_html_element.h
index a9054ded91e..c0df6a0a2e7 100644
--- a/chromium/third_party/blink/renderer/core/html/html_html_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_html_element.h
@@ -47,7 +47,6 @@ class CORE_EXPORT HTMLHtmlElement final : public HTMLElement {
bool IsURLAttribute(const Attribute&) const override;
const CSSPropertyValueSet* AdditionalPresentationAttributeStyle() override;
- void AttachLayoutTree(AttachContext&) override;
};
} // namespace blink
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 bc068328850..c60e3281ea9 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
@@ -219,9 +219,16 @@ void HTMLIFrameElement::ParseAttribute(
}
if (required_csp_ != value) {
required_csp_ = value;
- CSPAttributeChanged();
+ DidChangeAttributes();
UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute);
}
+ } else if (name == html_names::kAnonymousAttr &&
+ RuntimeEnabledFeatures::AnonymousIframeEnabled()) {
+ bool new_value = !value.IsNull();
+ if (anonymous_ != new_value) {
+ anonymous_ = new_value;
+ DidChangeAttributes();
+ }
} else if (name == html_names::kAllowAttr) {
if (allow_ != value) {
allow_ = value;
@@ -231,12 +238,6 @@ void HTMLIFrameElement::ParseAttribute(
WebFeature::kFeaturePolicyAllowAttribute);
}
}
- } else if (name == html_names::kDisallowdocumentaccessAttr &&
- RuntimeEnabledFeatures::DisallowDocumentAccessEnabled()) {
- UseCounter::Count(GetDocument(), WebFeature::kDisallowDocumentAccess);
- SetDisallowDocumentAccesss(!value.IsNull());
- // We don't need to call tell the client frame properties
- // changed since this attribute only stays inside the renderer.
} else if (name == html_names::kPolicyAttr) {
if (required_policy_ != value) {
required_policy_ = value;
@@ -467,7 +468,7 @@ HTMLIFrameElement::ConstructTrustTokenParams() const {
return parsed_params;
}
-void HTMLIFrameElement::CSPAttributeChanged() {
+void HTMLIFrameElement::DidChangeAttributes() {
// Don't notify about updates if ContentFrame() is null, for example when
// the subframe hasn't been created yet; or if we are in the middle of
// swapping one frame for another, in which case the final state
@@ -488,9 +489,9 @@ void HTMLIFrameElement::CSPAttributeChanged() {
network::mojom::blink::ContentSecurityPolicySource::kHTTP, KURL());
DCHECK_LE(csp.size(), 1u);
- GetDocument().GetFrame()->GetLocalFrameHostRemote().DidChangeCSPAttribute(
+ GetDocument().GetFrame()->GetLocalFrameHostRemote().DidChangeIframeAttributes(
ContentFrame()->GetFrameToken(),
- csp.IsEmpty() ? nullptr : std::move(csp[0]));
+ csp.IsEmpty() ? nullptr : std::move(csp[0]), anonymous_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element.h b/chromium/third_party/blink/renderer/core/html/html_iframe_element.h
index dc8bf2accd3..2e9627778a7 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element.h
@@ -87,7 +87,7 @@ class CORE_EXPORT HTMLIFrameElement final
// FrameOwner overrides:
bool AllowFullscreen() const override { return allow_fullscreen_; }
bool AllowPaymentRequest() const override { return allow_payment_request_; }
- void CSPAttributeChanged() override;
+ void DidChangeAttributes() override;
AtomicString name_;
AtomicString required_csp_;
@@ -100,6 +100,7 @@ class CORE_EXPORT HTMLIFrameElement final
bool allow_fullscreen_;
bool allow_payment_request_;
bool collapsed_by_client_;
+ bool anonymous_ = false;
Member<HTMLIFrameElementSandbox> sandbox_;
Member<DOMFeaturePolicy> policy_;
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element.idl b/chromium/third_party/blink/renderer/core/html/html_iframe_element.idl
index ad42fda233b..44f575aec7b 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
@@ -33,7 +33,6 @@
[PutForwards=value] readonly attribute DOMTokenList sandbox;
// Note: The seamless attribute was once supported, but was removed.
[CEReactions, Reflect] attribute boolean allowFullscreen;
- [RuntimeEnabled=DisallowDocumentAccess, CEReactions, Reflect] attribute boolean disallowDocumentAccess;
[CEReactions, Reflect] attribute DOMString width;
[CEReactions, Reflect] attribute DOMString height;
@@ -57,6 +56,10 @@
// Trust Tokens request parameters (https://github.com/wicg/trust-token-api)
[RuntimeEnabled=TrustTokens, SecureContext, Reflect, MeasureAs=TrustTokenIframe] attribute DOMString trustToken;
+ // Anonymous iframes
+ // https://github.com/camillelamy/explainers/blob/master/anonymous_iframes.md
+ [CEReactions, Reflect, RuntimeEnabled=AnonymousIframe] attribute boolean anonymous;
+
// obsolete members
// https://html.spec.whatwg.org/C/#HTMLIFrameElement-partial
[CEReactions, Reflect] attribute DOMString align;
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 94abdb74b2f..08493b854cd 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
@@ -26,6 +26,7 @@
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/css/media_values_dynamic.h"
#include "third_party/blink/renderer/core/css/parser/sizes_attribute_parser.h"
@@ -400,13 +401,13 @@ bool HTMLImageElement::SupportedImageType(
// http://picture.responsiveimages.org/#update-source-set
ImageCandidate HTMLImageElement::FindBestFitImageFromPictureParent() {
DCHECK(IsMainThread());
- Node* parent = parentNode();
source_ = nullptr;
- if (!parent || !IsA<HTMLPictureElement>(*parent))
+ auto* picture_parent = DynamicTo<HTMLPictureElement>(parentNode());
+ if (!picture_parent)
return ImageCandidate();
HashSet<String> disabled_image_types;
probe::GetDisabledImageTypes(GetExecutionContext(), &disabled_image_types);
- for (Node* child = parent->firstChild(); child;
+ for (Node* child = picture_parent->firstChild(); child;
child = child->nextSibling()) {
if (child == this)
return ImageCandidate();
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 75c995b68b8..87dbc049af7 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
@@ -152,6 +152,7 @@ void HTMLImageFallbackHelper::CustomStyleForAltText(Element& element,
if (!fallback.HasContentElements())
return;
+ // TODO(crbug.com/953707):
// This method is called during style recalc, and it is generally not allowed
// to mark nodes style dirty during recalc. The code below modifies inline
// style in the UA shadow tree below based on the computed style for the image
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 6cbe3784dd8..cf6e14aef74 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
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_html_marquee_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
@@ -82,6 +83,9 @@ class HTMLMarqueeElement::RequestAnimationFrameCallback final
public:
explicit RequestAnimationFrameCallback(HTMLMarqueeElement* marquee)
: marquee_(marquee) {}
+ RequestAnimationFrameCallback(const RequestAnimationFrameCallback&) = delete;
+ RequestAnimationFrameCallback& operator=(
+ const RequestAnimationFrameCallback&) = delete;
void Invoke(double) override {
marquee_->continue_callback_request_id_ = 0;
@@ -95,8 +99,6 @@ class HTMLMarqueeElement::RequestAnimationFrameCallback final
private:
Member<HTMLMarqueeElement> marquee_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestAnimationFrameCallback);
};
class HTMLMarqueeElement::AnimationFinished final : public NativeEventListener {
@@ -293,7 +295,7 @@ void HTMLMarqueeElement::ContinueAnimation() {
OptionalEffectTiming* effect_timing = OptionalEffectTiming::Create();
effect_timing->setFill("forwards");
effect_timing->setDuration(
- UnrestrictedDoubleOrString::FromUnrestrictedDouble(duration));
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(duration));
TimingInput::Update(timing, effect_timing, nullptr, ASSERT_NO_EXCEPTION);
auto* keyframe_effect =
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 6c8c01dcec8..675f8c90cef 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
@@ -201,11 +201,12 @@ Length HTMLMetaElement::ParseViewportValueAsLength(Document* document,
if (value < 0)
return Length(); // auto
+ value = ClampLengthValue(value);
if (document && document->GetPage()) {
value = document->GetPage()->GetChromeClient().WindowToViewportScalar(
document->GetFrame(), value);
}
- return Length::Fixed(ClampLengthValue(value));
+ return Length::Fixed(value);
}
float HTMLMetaElement::ParseViewportValueAsZoom(
@@ -482,7 +483,8 @@ void HTMLMetaElement::NameRemoved(const AtomicString& name_value) {
return;
if (EqualIgnoringASCIICase(name_value, "theme-color") &&
GetDocument().GetFrame()) {
- GetDocument().GetFrame()->DidChangeThemeColor();
+ GetDocument().GetFrame()->DidChangeThemeColor(
+ /*update_theme_color_cache=*/true);
} else if (EqualIgnoringASCIICase(name_value, "color-scheme")) {
GetDocument().ColorSchemeMetaChanged();
} else if (EqualIgnoringASCIICase(name_value, "battery-savings")) {
@@ -501,6 +503,8 @@ void HTMLMetaElement::ParseAttribute(
ProcessHttpEquiv();
} else if (params.name == html_names::kHttpEquivAttr) {
ProcessHttpEquiv();
+ } else if (params.name == html_names::kMediaAttr) {
+ ProcessContent();
} else {
HTMLElement::ParseAttribute(params);
}
@@ -561,7 +565,8 @@ void HTMLMetaElement::ProcessContent() {
if (EqualIgnoringASCIICase(name_value, "theme-color") &&
GetDocument().GetFrame()) {
- GetDocument().GetFrame()->DidChangeThemeColor();
+ GetDocument().GetFrame()->DidChangeThemeColor(
+ /*update_theme_color_cache=*/true);
return;
}
if (EqualIgnoringASCIICase(name_value, "color-scheme")) {
@@ -626,6 +631,10 @@ const AtomicString& HTMLMetaElement::HttpEquiv() const {
return FastGetAttribute(html_names::kHttpEquivAttr);
}
+const AtomicString& HTMLMetaElement::Media() const {
+ return FastGetAttribute(html_names::kMediaAttr);
+}
+
const AtomicString& HTMLMetaElement::GetName() const {
return FastGetAttribute(html_names::kNameAttr);
}
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 75ac90b2574..eeb87ad87c0 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
@@ -57,6 +57,7 @@ class CORE_EXPORT HTMLMetaElement final : public HTMLElement {
const AtomicString& Content() const;
const AtomicString& HttpEquiv() const;
+ const AtomicString& Media() const;
const AtomicString& GetName() const;
private:
diff --git a/chromium/third_party/blink/renderer/core/html/html_meta_element.idl b/chromium/third_party/blink/renderer/core/html/html_meta_element.idl
index 09148a8fe84..150fbfb6129 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meta_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_meta_element.idl
@@ -25,6 +25,7 @@
[CEReactions, Reflect] attribute DOMString name;
[CEReactions, Reflect=http_equiv] attribute DOMString httpEquiv;
[CEReactions, Reflect] attribute DOMString content;
+ [CEReactions, Reflect, MeasureAs=MediaMetaThemeColor, RuntimeEnabled=MediaMetaThemeColor] attribute DOMString media;
// obsolete members
// https://html.spec.whatwg.org/C/#HTMLMetaElement-partial
diff --git a/chromium/third_party/blink/renderer/core/html/html_or_foreign_element.idl b/chromium/third_party/blink/renderer/core/html/html_or_foreign_element.idl
index 486da823b35..e15efe2f853 100644
--- a/chromium/third_party/blink/renderer/core/html/html_or_foreign_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_or_foreign_element.idl
@@ -10,8 +10,7 @@ interface mixin HTMLOrForeignElement {
[CEReactions] attribute DOMString nonce;
[CEReactions, Reflect] attribute boolean autofocus;
- [Affects=Nothing, CEReactions] attribute long tabIndex;
+ [CEReactions] attribute long tabIndex;
void focus(optional FocusOptions options = {});
void blur();
};
-
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 604c09930ae..7f51cc30ae7 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,8 @@ void PluginParameters::MapDataParamToSrc() {
});
if (data != names_.end()) {
- AppendNameWithValue("src", values_[data - names_.begin()]);
+ AppendNameWithValue(
+ "src", values_[base::checked_cast<wtf_size_t>(data - names_.begin())]);
}
}
@@ -265,6 +266,13 @@ void HTMLPlugInElement::UpdatePlugin() {
}
}
+Node::InsertionNotificationRequest HTMLPlugInElement::InsertedInto(
+ ContainerNode& insertion_point) {
+ if (insertion_point.isConnected())
+ GetDocument().DelayLoadEventUntilLayoutTreeUpdate();
+ return HTMLFrameOwnerElement::InsertedInto(insertion_point);
+}
+
void HTMLPlugInElement::RemovedFrom(ContainerNode& insertion_point) {
// Plugins can persist only through reattachment during a lifecycle
// update. This method shouldn't be called in that lifecycle phase.
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 b3fb2feabad..a13a29c4b90 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
@@ -103,6 +103,8 @@ class CORE_EXPORT HTMLPlugInElement
const CreateElementFlags);
// Node functions:
+ InsertionNotificationRequest InsertedInto(
+ ContainerNode& insertion_point) override;
void RemovedFrom(ContainerNode& insertion_point) override;
void DidMoveToNewDocument(Document& old_document) override;
void AttachLayoutTree(AttachContext&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_popup_element.cc b/chromium/third_party/blink/renderer/core/html/html_popup_element.cc
index ef3574bdc06..51c11d05bd1 100644
--- a/chromium/third_party/blink/renderer/core/html/html_popup_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_popup_element.cc
@@ -94,7 +94,6 @@ void HTMLPopupElement::Invoke(Element* invoker) {
void HTMLPopupElement::show() {
if (open_ || !isConnected())
return;
-
// Only hide popups up to this popup's ancestral popup.
GetDocument().HideAllPopupsUntil(NearestOpenAncestralPopup(this));
open_ = true;
@@ -104,6 +103,13 @@ void HTMLPopupElement::show() {
SetFocus();
being_shown_ = true;
resize_observer_->observe(this);
+ // We need to update lifecycle phases to ensure the initial resize
+ // observation gets fired before the popup.show() call returns. Otherwise
+ // code like this will fail to work properly:
+ // popup.show();
+ // popup.style.width = change; // Should light-dismiss popup, but won't
+ GetDocument().GetFrame()->View()->UpdateAllLifecyclePhases(
+ DocumentUpdateReason::kPagePopup);
}
bool HTMLPopupElement::IsKeyboardFocusable() const {
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 9e8b91e9d45..b08d20ddca9 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
@@ -24,8 +24,6 @@
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/public/mojom/script/script_type.mojom-blink.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/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlscriptelement_svgscriptelement.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -133,11 +131,6 @@ void HTMLScriptElement::setText(const String& string) {
setTextContent(string);
}
-void HTMLScriptElement::text(StringOrTrustedScript& result) {
- result.SetString(TextFromChildren());
-}
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLScriptElement::setInnerTextForBinding(
const V8UnionStringTreatNullAsEmptyStringOrTrustedScript*
string_or_trusted_script,
@@ -152,23 +145,7 @@ void HTMLScriptElement::setInnerTextForBinding(
HTMLElement::setInnerText(value, exception_state);
script_text_internal_slot_ = ParkableString(value.Impl());
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLScriptElement::setInnerTextForBinding(
- const StringTreatNullAsEmptyStringOrTrustedScript& string_or_trusted_script,
- ExceptionState& exception_state) {
- String value = TrustedTypesCheckForScript(
- string_or_trusted_script, GetExecutionContext(), exception_state);
- if (!exception_state.HadException()) {
- // https://w3c.github.io/webappsec-trusted-types/dist/spec/#setting-slot-values
- // On setting, the innerText [...] perform the regular steps, and then set
- // content object's [[ScriptText]] internal slot value [...].
- HTMLElement::setInnerText(value, exception_state);
- script_text_internal_slot_ = ParkableString(value.Impl());
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLScriptElement::setTextContentForBinding(
const V8UnionStringOrTrustedScript* value,
ExceptionState& exception_state) {
@@ -182,21 +159,6 @@ void HTMLScriptElement::setTextContentForBinding(
Node::setTextContent(string);
script_text_internal_slot_ = ParkableString(string.Impl());
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLScriptElement::setTextContentForBinding(
- const StringOrTrustedScript& string_or_trusted_script,
- ExceptionState& exception_state) {
- String value = TrustedTypesCheckForScript(
- string_or_trusted_script, GetExecutionContext(), exception_state);
- if (!exception_state.HadException()) {
- // https://w3c.github.io/webappsec-trusted-types/dist/spec/#setting-slot-values
- // On setting, [..] textContent [..] perform the regular steps, and then set
- // content object's [[ScriptText]] internal slot value [...].
- Node::setTextContent(value);
- script_text_internal_slot_ = ParkableString(value.Impl());
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLScriptElement::setTextContent(const String& string) {
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#setting-slot-values
@@ -324,19 +286,15 @@ ExecutionContext* HTMLScriptElement::GetExecutionContext() const {
return Node::GetExecutionContext();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8HTMLOrSVGScriptElement* HTMLScriptElement::AsV8HTMLOrSVGScriptElement() {
if (IsInShadowTree())
return nullptr;
return MakeGarbageCollected<V8HTMLOrSVGScriptElement>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLScriptElement::SetScriptElementForBinding(
- HTMLScriptElementOrSVGScriptElement& element) {
- if (!IsInShadowTree())
- element.SetHTMLScriptElement(this);
+
+DOMNodeId HTMLScriptElement::GetDOMNodeId() {
+ return DOMNodeIds::IdForNode(this);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void HTMLScriptElement::DispatchLoadEvent() {
DispatchEvent(*Event::Create(event_type_names::kLoad));
diff --git a/chromium/third_party/blink/renderer/core/html/html_script_element.h b/chromium/third_party/blink/renderer/core/html/html_script_element.h
index 31b748a093e..d8f7c0accfc 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
@@ -35,7 +35,6 @@
namespace blink {
-class StringOrTrustedScript;
class ExceptionState;
class CORE_EXPORT HTMLScriptElement final : public HTMLElement,
@@ -48,23 +47,14 @@ class CORE_EXPORT HTMLScriptElement final : public HTMLElement,
// Returns attributes that should be checked against Trusted Types
const AttrNameToTrustedType& GetCheckedAttributeTypes() const override;
- void text(StringOrTrustedScript& result);
String text() { return TextFromChildren(); }
void setText(const String&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setInnerTextForBinding(
const V8UnionStringTreatNullAsEmptyStringOrTrustedScript*
string_or_trusted_script,
ExceptionState& exception_state) override;
void setTextContentForBinding(const V8UnionStringOrTrustedScript* value,
ExceptionState& exception_state) override;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setInnerTextForBinding(
- const StringTreatNullAsEmptyStringOrTrustedScript&,
- ExceptionState&) override;
- void setTextContentForBinding(const StringOrTrustedScript&,
- ExceptionState&) override;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setTextContent(const String&) override;
void setAsync(bool);
@@ -76,12 +66,8 @@ class CORE_EXPORT HTMLScriptElement final : public HTMLElement,
Document& GetDocument() const override;
ExecutionContext* GetExecutionContext() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8HTMLOrSVGScriptElement* AsV8HTMLOrSVGScriptElement() override;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetScriptElementForBinding(
- HTMLScriptElementOrSVGScriptElement&) override;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ DOMNodeId GetDOMNodeId() override;
void Trace(Visitor*) const override;
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 afb4e5c9ec5..5073101c86b 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
@@ -15,7 +15,7 @@ namespace blink {
namespace {
constexpr int kTableSize = 16;
using Seq = Vector<char>;
-using Backtrack = std::pair<size_t, size_t>;
+using Backtrack = std::pair<wtf_size_t, wtf_size_t>;
}
class HTMLSlotElementTest : public testing::Test {
@@ -33,8 +33,8 @@ Vector<char> HTMLSlotElementTest::LongestCommonSubsequence(const Seq& seq1,
HTMLSlotElement::FillLongestCommonSubsequenceDynamicProgrammingTable(
seq1, seq2, lcs_table_, backtrack_table_);
Seq lcs;
- size_t r = seq1.size();
- size_t c = seq2.size();
+ wtf_size_t r = seq1.size();
+ wtf_size_t c = seq2.size();
while (r > 0 && c > 0) {
Backtrack backtrack = backtrack_table_[r][c];
if (backtrack == std::make_pair(r - 1, c - 1)) {
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 2cbed912ebc..958da7eb701 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
@@ -68,7 +68,6 @@ void HTMLTemplateElement::CloneNonAttributePropertiesFrom(
CloneChildrenFlag flag) {
if (flag == CloneChildrenFlag::kSkip || !GetExecutionContext())
return;
- DCHECK_NE(flag, CloneChildrenFlag::kCloneWithShadows);
auto& html_template_element = To<HTMLTemplateElement>(source);
if (html_template_element.content())
content()->CloneChildNodesFrom(*html_template_element.content(), flag);
diff --git a/chromium/third_party/blink/renderer/core/html/html_template_element.idl b/chromium/third_party/blink/renderer/core/html/html_template_element.idl
index bf5200b02d2..e984ae9d812 100644
--- a/chromium/third_party/blink/renderer/core/html/html_template_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_template_element.idl
@@ -43,5 +43,5 @@
// }
// See https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md#feature-detection-and-polyfilling
// for more detail.
- [RuntimeEnabled=DeclarativeShadowDOM, Affects=Nothing, ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
+ [RuntimeEnabled=DeclarativeShadowDOM, ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
};
diff --git a/chromium/third_party/blink/renderer/core/html/html_view_source_document.cc b/chromium/third_party/blink/renderer/core/html/html_view_source_document.cc
index 35fd1369011..1575b5c4249 100644
--- a/chromium/third_party/blink/renderer/core/html/html_view_source_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_view_source_document.cc
@@ -100,7 +100,6 @@ void HTMLViewSourceDocument::CreateContainingTable() {
body->ParserAppendChild(div);
auto* table = MakeGarbageCollected<HTMLTableElement>(*this);
- body->ParserAppendChild(table);
tbody_ = MakeGarbageCollected<HTMLTableSectionElement>(html_names::kTbodyTag,
*this);
table->ParserAppendChild(tbody_);
@@ -115,6 +114,8 @@ void HTMLViewSourceDocument::CreateContainingTable() {
event_type_names::kChange,
MakeGarbageCollected<ViewSourceEventListener>(table, checkbox),
/*use_capture=*/false);
+ checkbox->setAttribute(html_names::kAriaLabelAttr, WTF::AtomicString(Locale::DefaultLocale().QueryString(
+ IDS_VIEW_SOURCE_LINE_WRAP)));
auto* label = MakeGarbageCollected<HTMLLabelElement>(*this);
label->ParserAppendChild(
Text::Create(*this, WTF::AtomicString(Locale::DefaultLocale().QueryString(
@@ -126,14 +127,8 @@ void HTMLViewSourceDocument::CreateContainingTable() {
auto* form = MakeGarbageCollected<HTMLFormElement>(*this);
form->setAttribute(html_names::kAutocompleteAttr, "off");
form->ParserAppendChild(label);
- auto* tr = MakeGarbageCollected<HTMLTableRowElement>(*this);
- auto* td =
- MakeGarbageCollected<HTMLTableCellElement>(html_names::kTdTag, *this);
- td->setAttribute(html_names::kColspanAttr, "2");
- td->setAttribute(html_names::kClassAttr, "line-wrap-cell");
- td->ParserAppendChild(form);
- tr->ParserAppendChild(td);
- tbody_->ParserAppendChild(tr);
+ body->ParserAppendChild(form);
+ body->ParserAppendChild(table);
}
void HTMLViewSourceDocument::AddSource(const String& source, HTMLToken& token) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_view_source_document_test.cc b/chromium/third_party/blink/renderer/core/html/html_view_source_document_test.cc
index 5a507e73c2d..a3e728cbec3 100644
--- a/chromium/third_party/blink/renderer/core/html/html_view_source_document_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_view_source_document_test.cc
@@ -37,13 +37,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource1) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> <span "
"class=\"html-doctype\">&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML "
@@ -94,13 +91,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource2) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> <span "
"class=\"html-tag\">&lt;script&gt;</span></td></tr><tr><td "
@@ -150,13 +144,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource3) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> <span "
"class=\"html-tag\">&lt;head&gt;</span><span class=\"html-tag\">&lt;base "
@@ -219,13 +210,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource4) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> <span "
"class=\"html-tag\">&lt;HEAD&gt;</span><span class=\"html-tag\">&lt;BASE "
@@ -291,13 +279,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource5) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"><br></td></tr><tr><td "
"class=\"line-number\" value=\"3\"></td><td "
@@ -327,13 +312,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource6) {
std::string many_spaces(32760, ' ');
LoadMainResource((many_spaces + std::string(" <b>A</b> ")).c_str());
std::string expected_beginning(
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\">"
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\">"
"</td><td class=\"line-content\"> ");
std::string expected_ending(
" <span class=\"html-tag\">&lt;b&gt;</span>A<span "
@@ -347,16 +329,13 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource6) {
TEST_F(HTMLViewSourceDocumentTest, ViewSource7) {
LoadMainResource("1234567");
EXPECT_EQ(GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
- "class=\"line-content\">1234567<span "
- "class=\"html-end-of-file\"></span></td></tr></tbody></table></"
- "body></html>");
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\">"
+ "</td><td class=\"line-content\">1234567<span "
+ "class=\"html-end-of-file\"></span></td></tr></tbody></table></"
+ "body></html>");
}
TEST_F(HTMLViewSourceDocumentTest, ViewSource8) {
@@ -373,13 +352,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource8) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form></td></tr>"
- "<tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> <span "
"class=\"html-doctype\">&lt;!DOCTYPE html&gt;</span></td></tr><tr><td "
@@ -444,13 +420,10 @@ TEST_F(HTMLViewSourceDocumentTest, ViewSource9) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> <span "
"class=\"html-doctype\">&lt;!DOCTYPE html&gt;</span></td></tr><tr><td "
@@ -479,13 +452,10 @@ TEST_F(HTMLViewSourceDocumentTest, IncompleteToken) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td "
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td><td "
"class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" "
"value=\"2\"></td><td class=\"line-content\"> Incomplete token "
"test</td></tr><tr><td class=\"line-number\" value=\"3\"></td><td "
@@ -505,13 +475,10 @@ TEST_F(HTMLViewSourceDocumentTest, UnfinishedTextarea) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td>"
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td>"
"<td class=\"line-content\"><span "
"class=\"html-tag\">&lt;textarea&gt;</span>foobar in "
"textarea</td></tr><tr><td class=\"line-number\" value=\"2\"></td><td "
@@ -525,13 +492,10 @@ TEST_F(HTMLViewSourceDocumentTest, UnfinishedScript) {
)HTML");
EXPECT_EQ(
GetDocument().documentElement()->outerHTML(),
- "<html><head></head><body><div "
- "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td "
- "colspan=\"2\" class=\"line-wrap-cell\"><form "
- "autocomplete=\"off\"><label "
- "class=\"line-wrap-control\"><input "
- "type=\"checkbox\"></label></form>"
- "</td></tr><tr><td class=\"line-number\" value=\"1\"></td>"
+ "<html><head></head><body><div class=\"line-gutter-backdrop\"></div><form "
+ "autocomplete=\"off\"><label class=\"line-wrap-control\">"
+ "<input type=\"checkbox\"></label>"
+ "</form><table><tbody><tr><td class=\"line-number\" value=\"1\"></td>"
"<td class=\"line-content\"><span "
"class=\"html-tag\">&lt;script&gt;</span>foobar in "
"script</td></tr><tr><td class=\"line-number\" value=\"2\"></td><td "
diff --git a/chromium/third_party/blink/renderer/core/html/link_resource.h b/chromium/third_party/blink/renderer/core/html/link_resource.h
index 27191f86e89..e5978dfc241 100644
--- a/chromium/third_party/blink/renderer/core/html/link_resource.h
+++ b/chromium/third_party/blink/renderer/core/html/link_resource.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LINK_RESOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LINK_RESOURCE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
@@ -48,6 +47,8 @@ class CORE_EXPORT LinkResource : public GarbageCollected<LinkResource> {
enum LinkResourceType { kStyle, kManifest, kOther };
explicit LinkResource(HTMLLinkElement*);
+ LinkResource(const LinkResource&) = delete;
+ LinkResource& operator=(const LinkResource&) = delete;
virtual ~LinkResource();
bool ShouldLoadResource() const;
@@ -70,8 +71,6 @@ class CORE_EXPORT LinkResource : public GarbageCollected<LinkResource> {
ExecutionContext* GetExecutionContext();
Member<HTMLLinkElement> owner_;
-
- DISALLOW_COPY_AND_ASSIGN(LinkResource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/link_web_bundle.cc b/chromium/third_party/blink/renderer/core/html/link_web_bundle.cc
index 78dec6071bb..2cb44c32b00 100644
--- a/chromium/third_party/blink/renderer/core/html/link_web_bundle.cc
+++ b/chromium/third_party/blink/renderer/core/html/link_web_bundle.cc
@@ -100,8 +100,8 @@ class WebBundleLoader : public GarbageCollected<WebBundleLoader>,
// Drain |consumer| so that DidFinishLoading is surely called later.
consumer.DrainAsDataPipe();
}
- void DidFail(const ResourceError&) override { DidFailInternal(); }
- void DidFailRedirectCheck() override { DidFailInternal(); }
+ void DidFail(uint64_t, const ResourceError&) override { DidFailInternal(); }
+ void DidFailRedirectCheck(uint64_t) override { DidFailInternal(); }
// network::mojom::WebBundleHandle
void Clone(mojo::PendingReceiver<network::mojom::WebBundleHandle> receiver)
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 f179d196a5c..2be3171bb0f 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/list_item_ordinal.h"
#include "base/numerics/safe_conversions.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/html/html_olist_element.h"
diff --git a/chromium/third_party/blink/renderer/core/html/media/DEPS b/chromium/third_party/blink/renderer/core/html/media/DEPS
index a8906ade4a0..3cc770b5dad 100644
--- a/chromium/third_party/blink/renderer/core/html/media/DEPS
+++ b/chromium/third_party/blink/renderer/core/html/media/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+media/base/media_switches.h",
"+media/base/video_frame.h",
"+media/mojo/mojom/media_player.mojom-blink.h",
+ "+services/media_session/public/mojom/media_session.mojom-blink.h",
]
specific_include_rules = {
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 a1f48032a4e..2d8dc569e46 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
@@ -57,6 +57,8 @@ class CORE_EXPORT AutoplayPolicy final
static bool DocumentIsCapturingUserMedia(const Document&);
explicit AutoplayPolicy(HTMLMediaElement*);
+ AutoplayPolicy(const AutoplayPolicy&) = delete;
+ AutoplayPolicy& operator=(const AutoplayPolicy&) = delete;
void VideoWillBeDrawnToCanvas() const;
@@ -153,8 +155,6 @@ class CORE_EXPORT AutoplayPolicy final
Member<AutoplayUmaHelper> autoplay_uma_helper_;
absl::optional<bool> autoplay_initiated_;
-
- DISALLOW_COPY_AND_ASSIGN(AutoplayPolicy);
};
} // namespace blink
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 2c4bff5c46a..cfcb19002a1 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
@@ -39,11 +39,11 @@
#include "media/base/logging_override_if_enabled.h"
#include "media/base/media_content_type.h"
#include "media/base/media_switches.h"
+#include "services/media_session/public/mojom/media_session.mojom-blink.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-shared.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream.h"
#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_client.h"
@@ -60,6 +60,7 @@
#include "third_party/blink/renderer/core/core_probes_inl.h"
#include "third_party/blink/renderer/core/css/media_list.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/attribute.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
@@ -127,6 +128,7 @@
#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/math_extras.h"
+#include "ui/display/screen_info.h"
#ifndef LOG_MEDIA_EVENTS
// Default to not logging events because so many are generated they can
@@ -479,7 +481,7 @@ bool HTMLMediaElement::IsHLSURL(const KURL& url) {
if (!url.IsLocalFile() && !url.ProtocolIs("http") && !url.ProtocolIs("https"))
return false;
- return url.GetString().Contains("m3u8");
+ return url.GetPath().EndsWith(".m3u8");
}
bool HTMLMediaElement::MediaTracksEnabledInternally() {
@@ -2828,6 +2830,14 @@ bool HTMLMediaElement::ShouldShowControls(
return false;
}
+bool HTMLMediaElement::ShouldShowAllControls() const {
+ // If the user has explicitly shown or hidden the controls, then force that
+ // choice. Otherwise returns whether controls should be shown and no controls
+ // are meant to be hidden.
+ return user_wants_controls_visible_.value_or(
+ ShouldShowControls() && !ControlsListInternal()->CanShowAllControls());
+}
+
DOMTokenList* HTMLMediaElement::controlsList() const {
return controls_list_.Get();
}
@@ -2919,6 +2929,10 @@ void HTMLMediaElement::SetUserWantsControlsVisible(bool visible) {
UpdateControlsVisibility();
}
+bool HTMLMediaElement::UserWantsControlsVisible() const {
+ return user_wants_controls_visible_.value_or(false);
+}
+
double HTMLMediaElement::EffectiveMediaVolume() const {
if (muted_)
return 0;
@@ -4432,7 +4446,7 @@ void HTMLMediaElement::AudioSourceProviderImpl::SetClient(
void HTMLMediaElement::AudioSourceProviderImpl::ProvideInput(
AudioBus* bus,
- uint32_t frames_to_process) {
+ int frames_to_process) {
DCHECK(bus);
MutexTryLocker try_locker(provide_input_lock);
@@ -4525,11 +4539,13 @@ void HTMLMediaElement::DidMediaMetadataChange(
void HTMLMediaElement::DidPlayerMediaPositionStateChange(
double playback_rate,
base::TimeDelta duration,
- base::TimeDelta position) {
+ base::TimeDelta position,
+ bool end_of_media) {
for (auto& observer : media_player_observer_remote_set_->Value()) {
observer->OnMediaPositionStateChanged(
media_session::mojom::blink::MediaPosition::New(
- playback_rate, duration, position, base::TimeTicks::Now()));
+ playback_rate, duration, position, base::TimeTicks::Now(),
+ end_of_media));
}
}
@@ -4538,6 +4554,12 @@ void HTMLMediaElement::DidDisableAudioOutputSinkChanges() {
observer->OnAudioOutputSinkChangingDisabled();
}
+void HTMLMediaElement::DidUseAudioServiceChange(bool uses_audio_service) {
+ for (auto& observer : media_player_observer_remote_set_->Value()) {
+ observer->OnUseAudioServiceChanged(uses_audio_service);
+ }
+}
+
void HTMLMediaElement::DidPlayerSizeChange(const gfx::Size& size) {
for (auto& observer : media_player_observer_remote_set_->Value())
observer->OnMediaSizeChanged(size);
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 a4bf53108f7..4af2fe7c1c0 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
@@ -243,6 +243,7 @@ class CORE_EXPORT HTMLMediaElement
// controls
bool ShouldShowControls(
const RecordMetricsBehavior = RecordMetricsBehavior::kDoNotRecord) const;
+ bool ShouldShowAllControls() const;
DOMTokenList* controlsList() const;
HTMLMediaElementControlsList* ControlsListInternal() const;
double volume() const;
@@ -251,6 +252,7 @@ class CORE_EXPORT HTMLMediaElement
void setMuted(bool);
virtual bool SupportsPictureInPicture() const { return false; }
void SetUserWantsControlsVisible(bool visible);
+ bool UserWantsControlsVisible() const;
void TogglePlayState();
@@ -495,8 +497,10 @@ class CORE_EXPORT HTMLMediaElement
media::MediaContentType media_content_type) override;
void DidPlayerMediaPositionStateChange(double playback_rate,
base::TimeDelta duration,
- base::TimeDelta position) override;
+ base::TimeDelta position,
+ bool end_of_media) override;
void DidDisableAudioOutputSinkChanges() override;
+ void DidUseAudioServiceChange(bool uses_audio_service) override;
void DidPlayerSizeChange(const gfx::Size& size) override;
void DidBufferUnderflow() override;
void DidSeek() override;
@@ -813,7 +817,7 @@ class CORE_EXPORT HTMLMediaElement
// AudioSourceProvider
void SetClient(AudioSourceProviderClient*) override;
- void ProvideInput(AudioBus*, uint32_t frames_to_process) override;
+ void ProvideInput(AudioBus*, int frames_to_process) override;
void Trace(Visitor*) const;
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc b/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc
index 1f552d45d06..72e75ab124e 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc
@@ -12,10 +12,11 @@ namespace {
const char kNoDownload[] = "nodownload";
const char kNoFullscreen[] = "nofullscreen";
+const char kNoPlaybackRate[] = "noplaybackrate";
const char kNoRemotePlayback[] = "noremoteplayback";
const char* const kSupportedTokens[] = {kNoDownload, kNoFullscreen,
- kNoRemotePlayback};
+ kNoPlaybackRate, kNoRemotePlayback};
} // namespace
@@ -41,8 +42,17 @@ bool HTMLMediaElementControlsList::ShouldHideFullscreen() const {
return contains(kNoFullscreen);
}
+bool HTMLMediaElementControlsList::ShouldHidePlaybackRate() const {
+ return contains(kNoPlaybackRate);
+}
+
bool HTMLMediaElementControlsList::ShouldHideRemotePlayback() const {
return contains(kNoRemotePlayback);
}
+bool HTMLMediaElementControlsList::CanShowAllControls() const {
+ return ShouldHideDownload() || ShouldHideFullscreen() ||
+ ShouldHidePlaybackRate() || ShouldHideRemotePlayback();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h b/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h
index e5af347e6f2..1d1b56f5ad2 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h
@@ -20,8 +20,11 @@ class CORE_EXPORT HTMLMediaElementControlsList final : public DOMTokenList {
// Whether the list dictates to hide a certain control.
bool ShouldHideDownload() const;
bool ShouldHideFullscreen() const;
+ bool ShouldHidePlaybackRate() const;
bool ShouldHideRemotePlayback() const;
+ bool CanShowAllControls() const;
+
private:
bool ValidateTokenValue(const AtomicString&, ExceptionState&) const override;
};
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 3957918054f..cfbe85ac657 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
@@ -219,6 +219,7 @@ TEST_F(HTMLMediaElementEventListenersTest, RemovingFromDocumentCollectsAll) {
EXPECT_TRUE(persistent_video->HasEventListeners());
}
+ UpdateAllLifecyclePhasesForTest();
test::RunPendingTasks();
ThreadState::Current()->CollectAllGarbageForTesting();
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 f0aed9853a3..bac895edd27 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
@@ -8,6 +8,7 @@
#include "base/test/gtest_util.h"
#include "media/base/media_content_type.h"
#include "media/mojo/mojom/media_player.mojom-blink.h"
+#include "services/media_session/public/mojom/media_session.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/autoplay/autoplay.mojom-blink.h"
@@ -173,6 +174,11 @@ class TestMediaPlayerObserver final
void OnAudioOutputSinkChanged(const WTF::String& hashed_device_id) override {}
+ void OnUseAudioServiceChanged(bool uses_audio_service) override {
+ received_uses_audio_service_ = uses_audio_service;
+ run_loop_->Quit();
+ }
+
void OnAudioOutputSinkChangingDisabled() override {}
void OnBufferUnderflow() override {
@@ -200,6 +206,10 @@ class TestMediaPlayerObserver final
gfx::Size received_media_size() const { return received_media_size_; }
+ bool received_use_audio_service_changed(bool uses_audio_service) const {
+ return received_uses_audio_service_.value() == uses_audio_service;
+ }
+
bool received_buffer_underflow() const { return received_buffer_underflow_; }
private:
@@ -209,6 +219,7 @@ class TestMediaPlayerObserver final
absl::optional<bool> received_muted_status_type_;
absl::optional<OnMetadataChangedResult> received_metadata_changed_result_;
gfx::Size received_media_size_{0, 0};
+ absl::optional<bool> received_uses_audio_service_;
bool received_buffer_underflow_{false};
};
@@ -327,6 +338,10 @@ class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
bool ControlsVisible() const { return Media()->ShouldShowControls(); }
+ bool MediaShouldShowAllControls() const {
+ return Media()->ShouldShowAllControls();
+ }
+
ExecutionContext* GetExecutionContext() const {
return dummy_page_holder_->GetFrame().DomWindow();
}
@@ -387,6 +402,16 @@ class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
return media_player_observer().received_media_size() == size;
}
+ void NotifyUseAudioServiceChanged(bool uses_audio_service) {
+ media_->DidUseAudioServiceChange(uses_audio_service);
+ media_player_observer().WaitUntilReceivedMessage();
+ }
+
+ bool ReceivedMessageUseAudioServiceChanged(bool uses_audio_service) {
+ return media_player_observer().received_use_audio_service_changed(
+ uses_audio_service);
+ }
+
void NotifyBufferUnderflowEvent() {
media_->DidBufferUnderflow();
media_player_observer().WaitUntilReceivedMessage();
@@ -1065,6 +1090,16 @@ TEST_P(HTMLMediaElementTest, SendMediaSizeChangeToObserver) {
EXPECT_TRUE(ReceivedMessageMediaSizeChange(kTestMediaSizeChangedValue));
}
+TEST_P(HTMLMediaElementTest, SendUseAudioServiceChangedToObserver) {
+ WaitForPlayer();
+
+ NotifyUseAudioServiceChanged(false);
+ EXPECT_TRUE(ReceivedMessageUseAudioServiceChanged(false));
+
+ NotifyUseAudioServiceChanged(true);
+ EXPECT_TRUE(ReceivedMessageUseAudioServiceChanged(true));
+}
+
TEST_P(HTMLMediaElementTest, SendBufferOverflowToObserver) {
WaitForPlayer();
@@ -1104,4 +1139,37 @@ TEST_P(HTMLMediaElementTest,
EXPECT_FALSE(ControlsVisible());
}
+TEST_P(HTMLMediaElementTest,
+ MediaShouldShowAllControlsDependsOnControlslistAttr) {
+ // Enable scripts to prevent controls being shown due to no scripts.
+ Media()->GetDocument().GetSettings()->SetScriptEnabled(true);
+
+ // Setting the controls attribute to true should show the controls.
+ Media()->SetBooleanAttribute(html_names::kControlsAttr, true);
+ EXPECT_TRUE(MediaShouldShowAllControls());
+
+ // Setting the controlsList attribute to a valid value should not show the
+ // controls.
+ Media()->setAttribute(blink::html_names::kControlslistAttr, "nofullscreen");
+ EXPECT_FALSE(MediaShouldShowAllControls());
+
+ // Removing the controlsList attribute should show the controls.
+ Media()->removeAttribute(blink::html_names::kControlslistAttr);
+ EXPECT_TRUE(MediaShouldShowAllControls());
+
+ // Setting the controlsList attribute to an invalid value should still show
+ // the controls.
+ Media()->setAttribute(blink::html_names::kControlslistAttr, "foo");
+ EXPECT_TRUE(MediaShouldShowAllControls());
+
+ // Setting the controlsList attribute to another valid value should not show
+ // the controls.
+ Media()->setAttribute(blink::html_names::kControlslistAttr, "noplaybackrate");
+ EXPECT_FALSE(MediaShouldShowAllControls());
+
+ // If the user explicitly shows them, that should override the controlsList
+ // attribute.
+ Media()->SetUserWantsControlsVisible(true);
+ EXPECT_TRUE(MediaShouldShowAllControls());
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_test_helper.h b/chromium/third_party/blink/renderer/core/html/media/html_media_test_helper.h
index 0981db7c3a0..b90b78d1069 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_test_helper.h
@@ -19,6 +19,9 @@ class MediaStubLocalFrameClient : public EmptyLocalFrameClient {
explicit MediaStubLocalFrameClient(std::unique_ptr<WebMediaPlayer>);
MediaStubLocalFrameClient(std::unique_ptr<WebMediaPlayer>,
bool allow_empty_player);
+ MediaStubLocalFrameClient(const MediaStubLocalFrameClient&) = delete;
+ MediaStubLocalFrameClient& operator=(const MediaStubLocalFrameClient&) =
+ delete;
std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer(
HTMLMediaElement&,
@@ -28,8 +31,6 @@ class MediaStubLocalFrameClient : public EmptyLocalFrameClient {
private:
std::unique_ptr<WebMediaPlayer> player_;
bool allow_empty_player_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MediaStubLocalFrameClient);
};
} // namespace test
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 0b551aacf8c..12a93f064e1 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
@@ -391,7 +391,7 @@ void HTMLVideoElement::PaintCurrentFrame(cc::PaintCanvas* canvas,
media_flags = *flags;
} else {
media_flags.setAlpha(0xFF);
- media_flags.setFilterQuality(kLow_SkFilterQuality);
+ media_flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
media_flags.setBlendMode(SkBlendMode::kSrc);
}
@@ -556,7 +556,11 @@ scoped_refptr<StaticBitmapImage> HTMLVideoElement::CreateStaticBitmapImage(
scoped_refptr<Image> HTMLVideoElement::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize&) {
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition) {
+ // UnpremultiplyAlpha is not implemented yet.
+ DCHECK_EQ(alpha_disposition, kPremultiplyAlpha);
+
scoped_refptr<Image> snapshot = CreateStaticBitmapImage();
if (!snapshot) {
*status = kInvalidSourceImageStatus;
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 151ef7b1572..4296694a639 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
@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
-#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
class ImageBitmapOptions;
@@ -110,8 +109,10 @@ class CORE_EXPORT HTMLVideoElement final
bool allow_accelerated_images = true);
// CanvasImageSource implementation
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) override;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) override;
bool IsVideoElement() const override { return true; }
bool WouldTaintOrigin() const override;
FloatSize ElementSize(const FloatSize&,
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
index 5c5cf97e510..3e9f26b99d8 100644
--- 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
@@ -16,9 +16,11 @@
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/loader/empty_clients.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/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
using testing::_;
@@ -33,10 +35,10 @@ class HTMLVideoElementMockMediaPlayer : public EmptyWebMediaPlayer {
MOCK_METHOD1(OnDisplayTypeChanged, void(DisplayType));
MOCK_CONST_METHOD0(HasAvailableVideoFrame, bool());
};
-
} // namespace
-class HTMLVideoElementTest : public PageTestBase {
+class HTMLVideoElementTest : public PaintTestConfigurations,
+ public RenderingTest {
public:
void SetUp() override {
auto mock_media_player =
@@ -64,8 +66,9 @@ class HTMLVideoElementTest : public PageTestBase {
// Owned by HTMLVideoElementFrameClient.
HTMLVideoElementMockMediaPlayer* media_player_;
};
+INSTANTIATE_PAINT_TEST_SUITE_P(HTMLVideoElementTest);
-TEST_F(HTMLVideoElementTest, PictureInPictureInterstitialAndTextContainer) {
+TEST_P(HTMLVideoElementTest, PictureInPictureInterstitialAndTextContainer) {
scoped_refptr<cc::Layer> layer = cc::Layer::Create();
SetFakeCcLayer(layer.get());
@@ -92,7 +95,7 @@ TEST_F(HTMLVideoElementTest, PictureInPictureInterstitialAndTextContainer) {
SetFakeCcLayer(nullptr);
}
-TEST_F(HTMLVideoElementTest, PictureInPictureInterstitial_Reattach) {
+TEST_P(HTMLVideoElementTest, PictureInPictureInterstitial_Reattach) {
scoped_refptr<cc::Layer> layer = cc::Layer::Create();
SetFakeCcLayer(layer.get());
@@ -117,7 +120,7 @@ TEST_F(HTMLVideoElementTest, PictureInPictureInterstitial_Reattach) {
GetDocument().body()->removeChild(video());
}
-TEST_F(HTMLVideoElementTest, EffectivelyFullscreen_DisplayType) {
+TEST_P(HTMLVideoElementTest, EffectivelyFullscreen_DisplayType) {
video()->SetSrc("http://example.com/foo.mp4");
test::RunPendingTasks();
UpdateAllLifecyclePhasesForTest();
@@ -150,7 +153,7 @@ TEST_F(HTMLVideoElementTest, EffectivelyFullscreen_DisplayType) {
}
}
-TEST_F(HTMLVideoElementTest, ChangeLayerNeedsCompositingUpdate) {
+TEST_P(HTMLVideoElementTest, ChangeLayerNeedsCompositingUpdate) {
video()->SetSrc("http://example.com/foo.mp4");
test::RunPendingTasks();
UpdateAllLifecyclePhasesForTest();
@@ -160,25 +163,43 @@ TEST_F(HTMLVideoElementTest, ChangeLayerNeedsCompositingUpdate) {
ASSERT_TRUE(video()->GetLayoutObject()->HasLayer());
auto* paint_layer =
To<LayoutBoxModelObject>(video()->GetLayoutObject())->Layer();
- EXPECT_TRUE(paint_layer->NeedsCompositingInputsUpdate());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ EXPECT_TRUE(paint_layer->SelfNeedsRepaint());
+ else
+ EXPECT_TRUE(paint_layer->NeedsCompositingInputsUpdate());
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(paint_layer->NeedsCompositingInputsUpdate());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ EXPECT_FALSE(paint_layer->SelfNeedsRepaint());
+ else
+ EXPECT_FALSE(paint_layer->NeedsCompositingInputsUpdate());
// Change to another cc layer.
auto layer2 = cc::Layer::Create();
SetFakeCcLayer(layer2.get());
- EXPECT_TRUE(paint_layer->NeedsCompositingInputsUpdate());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ EXPECT_TRUE(paint_layer->SelfNeedsRepaint());
+ else
+ EXPECT_TRUE(paint_layer->NeedsCompositingInputsUpdate());
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(paint_layer->NeedsCompositingInputsUpdate());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ EXPECT_FALSE(paint_layer->SelfNeedsRepaint());
+ else
+ EXPECT_FALSE(paint_layer->NeedsCompositingInputsUpdate());
// Remove cc layer.
SetFakeCcLayer(nullptr);
- EXPECT_TRUE(paint_layer->NeedsCompositingInputsUpdate());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ EXPECT_TRUE(paint_layer->SelfNeedsRepaint());
+ else
+ EXPECT_TRUE(paint_layer->NeedsCompositingInputsUpdate());
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(paint_layer->NeedsCompositingInputsUpdate());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ EXPECT_FALSE(paint_layer->SelfNeedsRepaint());
+ else
+ EXPECT_FALSE(paint_layer->NeedsCompositingInputsUpdate());
}
-TEST_F(HTMLVideoElementTest, HasAvailableVideoFrameChecksWMP) {
+TEST_P(HTMLVideoElementTest, HasAvailableVideoFrameChecksWMP) {
video()->SetSrc("http://example.com/foo.mp4");
test::RunPendingTasks();
UpdateAllLifecyclePhasesForTest();
@@ -190,7 +211,7 @@ TEST_F(HTMLVideoElementTest, HasAvailableVideoFrameChecksWMP) {
EXPECT_TRUE(video()->HasAvailableVideoFrame());
}
-TEST_F(HTMLVideoElementTest, AutoPIPExitPIPTest) {
+TEST_P(HTMLVideoElementTest, AutoPIPExitPIPTest) {
video()->SetSrc("http://example.com/foo.mp4");
test::RunPendingTasks();
@@ -207,7 +228,7 @@ TEST_F(HTMLVideoElementTest, AutoPIPExitPIPTest) {
// Blink embedders (such as Webview) can set the default poster image for a
// video using `blink::Settings`. In some cases we still need to distinguish
// between a "real" poster image and the default poster image.
-TEST_F(HTMLVideoElementTest, DefaultPosterImage) {
+TEST_P(HTMLVideoElementTest, DefaultPosterImage) {
String const kDefaultPosterImage = "http://www.example.com/foo.jpg";
// Override the default poster image
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 4b0a51f7180..08c374f7c70 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
@@ -25,8 +25,6 @@
#include "third_party/blink/renderer/core/html/media/media_document.h"
-#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/add_event_listener_options_or_boolean.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"
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_fragment_uri_parser.cc b/chromium/third_party/blink/renderer/core/html/media/media_fragment_uri_parser.cc
index efb81e3e2bb..4b8fe0c4c42 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_fragment_uri_parser.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_fragment_uri_parser.cc
@@ -170,7 +170,8 @@ void MediaFragmentURIParser::ParseTimeFragment() {
double start = std::numeric_limits<double>::quiet_NaN();
double end = std::numeric_limits<double>::quiet_NaN();
- if (ParseNPTFragment(fragment.second.data(), fragment.second.length(),
+ if (ParseNPTFragment(fragment.second.data(),
+ base::checked_cast<unsigned>(fragment.second.length()),
start, end)) {
start_time_ = start;
end_time_ = end;
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_source_attachment.h b/chromium/third_party/blink/renderer/core/html/media/media_source_attachment.h
index 851c43abfa8..ff088095a00 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_source_attachment.h
+++ b/chromium/third_party/blink/renderer/core/html/media/media_source_attachment.h
@@ -33,9 +33,6 @@ class WebMediaSource;
// increased complexity for handling the latter. Concrete implementations of
// this interface are reference counted to ensure they are available potentially
// cross-thread and from the registry.
-//
-// TODO(https://crbug.com/878133): This is not yet implementing the multi-thread
-// aspect.
class CORE_EXPORT MediaSourceAttachment
: public URLRegistrable,
public WTF::ThreadSafeRefCounted<MediaSourceAttachment> {
@@ -51,6 +48,8 @@ class CORE_EXPORT MediaSourceAttachment
const String& url);
MediaSourceAttachment();
+ MediaSourceAttachment(const MediaSourceAttachment&) = delete;
+ MediaSourceAttachment& operator=(const MediaSourceAttachment&) = delete;
~MediaSourceAttachment() override;
// This is called on the main thread when the URLRegistry unregisters the
@@ -136,8 +135,6 @@ class CORE_EXPORT MediaSourceAttachment
friend class WTF::ThreadSafeRefCounted<MediaSourceAttachment>;
static URLRegistry* registry_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaSourceAttachment);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_frame_callback_requester.h b/chromium/third_party/blink/renderer/core/html/media/video_frame_callback_requester.h
index 0a411483aff..90d3b1fa748 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_frame_callback_requester.h
+++ b/chromium/third_party/blink/renderer/core/html/media/video_frame_callback_requester.h
@@ -23,6 +23,9 @@ class CORE_EXPORT VideoFrameCallbackRequester
static VideoFrameCallbackRequester* From(HTMLVideoElement&);
+ VideoFrameCallbackRequester(const VideoFrameCallbackRequester&) = delete;
+ VideoFrameCallbackRequester& operator=(const VideoFrameCallbackRequester&) =
+ delete;
virtual ~VideoFrameCallbackRequester() = default;
void Trace(Visitor*) const override;
@@ -33,7 +36,6 @@ class CORE_EXPORT VideoFrameCallbackRequester
protected:
explicit VideoFrameCallbackRequester(HTMLVideoElement&);
- DISALLOW_COPY_AND_ASSIGN(VideoFrameCallbackRequester);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
index 13a209fb71a..c5a1093aa2d 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
@@ -33,7 +33,7 @@ namespace blink {
// The VideoWakeLockPictureInPictureSession implements a PictureInPicture
// session in the same process as the test and guarantees that the callbacks are
// called in order for the events to be fired.
-class VideoWakeLockPictureInPictureSession
+class VideoWakeLockPictureInPictureSession final
: public mojom::blink::PictureInPictureSession {
public:
explicit VideoWakeLockPictureInPictureSession(
@@ -41,14 +41,13 @@ class VideoWakeLockPictureInPictureSession
: receiver_(this, std::move(receiver)) {}
~VideoWakeLockPictureInPictureSession() override = default;
- void Stop(StopCallback callback) final { std::move(callback).Run(); }
-
+ void Stop(StopCallback callback) override { std::move(callback).Run(); }
void Update(uint32_t player_id,
mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>
player_remote,
- const absl::optional<viz::SurfaceId>&,
+ const viz::SurfaceId&,
const gfx::Size&,
- bool show_play_pause_button) final {}
+ bool show_play_pause_button) override {}
private:
mojo::Receiver<mojom::blink::PictureInPictureSession> receiver_;
@@ -57,7 +56,7 @@ class VideoWakeLockPictureInPictureSession
// The VideoWakeLockPictureInPictureService implements the PictureInPicture
// service in the same process as the test and guarantees that the callbacks are
// called in order for the events to be fired.
-class VideoWakeLockPictureInPictureService
+class VideoWakeLockPictureInPictureService final
: public mojom::blink::PictureInPictureService {
public:
VideoWakeLockPictureInPictureService() : receiver_(this) {}
@@ -71,11 +70,11 @@ class VideoWakeLockPictureInPictureService
void StartSession(
uint32_t,
mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>,
- const absl::optional<viz::SurfaceId>&,
+ const viz::SurfaceId&,
const gfx::Size&,
bool,
mojo::PendingRemote<mojom::blink::PictureInPictureSessionObserver>,
- StartSessionCallback callback) final {
+ StartSessionCallback callback) override {
mojo::PendingRemote<mojom::blink::PictureInPictureSession> session_remote;
session_ = std::make_unique<VideoWakeLockPictureInPictureSession>(
session_remote.InitWithNewPipeAndPassReceiver());
@@ -90,17 +89,27 @@ class VideoWakeLockPictureInPictureService
class VideoWakeLockMediaPlayer final : public EmptyWebMediaPlayer {
public:
- ReadyState GetReadyState() const final { return kReadyStateHaveMetadata; }
- bool HasVideo() const final { return true; }
+ ReadyState GetReadyState() const override { return kReadyStateHaveMetadata; }
+ bool HasVideo() const override { return true; }
+ void OnRequestPictureInPicture() override {
+ // Use a fake but valid viz::SurfaceId.
+ surface_id_ = viz::SurfaceId(
+ viz::FrameSinkId(1, 1),
+ viz::LocalSurfaceId(11,
+ base::UnguessableToken::Deserialize(0x111111, 0)));
+ }
+ absl::optional<viz::SurfaceId> GetSurfaceId() override { return surface_id_; }
+
+ private:
+ absl::optional<viz::SurfaceId> surface_id_;
};
class VideoWakeLockFrameClient : public test::MediaStubLocalFrameClient {
public:
explicit VideoWakeLockFrameClient(std::unique_ptr<WebMediaPlayer> player)
: test::MediaStubLocalFrameClient(std::move(player)) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VideoWakeLockFrameClient);
+ VideoWakeLockFrameClient(const VideoWakeLockFrameClient&) = delete;
+ VideoWakeLockFrameClient& operator=(const VideoWakeLockFrameClient&) = delete;
};
class VideoWakeLockTest : public PageTestBase {
diff --git a/chromium/third_party/blink/renderer/core/html/parser/atomic_html_token.h b/chromium/third_party/blink/renderer/core/html/parser/atomic_html_token.h
index 912f26ac7b0..f5274034feb 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/atomic_html_token.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/atomic_html_token.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/html/parser/compact_html_token.h"
@@ -189,6 +188,9 @@ class CORE_EXPORT AtomicHTMLToken {
DCHECK(UsesName());
}
+ AtomicHTMLToken(const AtomicHTMLToken&) = delete;
+ AtomicHTMLToken& operator=(const AtomicHTMLToken&) = delete;
+
#ifndef NDEBUG
void Show() const;
#endif
@@ -218,8 +220,6 @@ class CORE_EXPORT AtomicHTMLToken {
bool duplicate_attribute_ = false;
Vector<Attribute> attributes_;
-
- DISALLOW_COPY_AND_ASSIGN(AtomicHTMLToken);
};
inline void AtomicHTMLToken::InitializeAttributes(
diff --git a/chromium/third_party/blink/renderer/core/html/parser/background_html_input_stream.h b/chromium/third_party/blink/renderer/core/html/parser/background_html_input_stream.h
index 970bbf526a4..f11a4c02c3d 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/background_html_input_stream.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/background_html_input_stream.h
@@ -27,7 +27,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_BACKGROUND_HTML_INPUT_STREAM_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/text/segmented_string.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -42,6 +41,9 @@ class BackgroundHTMLInputStream {
public:
BackgroundHTMLInputStream();
+ BackgroundHTMLInputStream(const BackgroundHTMLInputStream&) = delete;
+ BackgroundHTMLInputStream& operator=(const BackgroundHTMLInputStream&) =
+ delete;
void Append(const String&);
void Close();
@@ -93,8 +95,6 @@ class BackgroundHTMLInputStream {
wtf_size_t total_checkpoint_token_count_;
void UpdateTotalCheckpointTokenCount();
-
- DISALLOW_COPY_AND_ASSIGN(BackgroundHTMLInputStream);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h b/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h
index 608b467fa4a..c867f152a1a 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -69,6 +68,9 @@ class BackgroundHTMLParser {
const MediaValuesCached::MediaValuesCachedData&,
bool priority_hints_origin_trial_enabled);
+ BackgroundHTMLParser(const BackgroundHTMLParser&) = delete;
+ BackgroundHTMLParser& operator=(const BackgroundHTMLParser&) = delete;
+
struct Checkpoint {
USING_FAST_MALLOC(Checkpoint);
@@ -128,8 +130,6 @@ class BackgroundHTMLParser {
bool starting_script_;
base::WeakPtrFactory<BackgroundHTMLParser> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(BackgroundHTMLParser);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.h b/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.h
index db259a95ce9..8ae23d7c64f 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_CSS_PRELOAD_SCANNER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_CSS_PRELOAD_SCANNER_H_
-#include "base/macros.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/platform/wtf/text/string_builder.h"
@@ -41,6 +40,8 @@ class CSSPreloadScanner {
public:
CSSPreloadScanner();
+ CSSPreloadScanner(const CSSPreloadScanner&) = delete;
+ CSSPreloadScanner& operator=(const CSSPreloadScanner&) = delete;
~CSSPreloadScanner();
void Reset();
@@ -96,8 +97,6 @@ class CSSPreloadScanner {
PreloadRequestStream* requests_ = nullptr;
const KURL* predicted_base_element_url_ = nullptr;
const PreloadRequest::ExclusionInfo* exclusion_info_;
-
- DISALLOW_COPY_AND_ASSIGN(CSSPreloadScanner);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
index 5c1866b4730..e0922589c25 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
@@ -396,6 +396,7 @@ HTMLConstructionSite::~HTMLConstructionSite() {
}
void HTMLConstructionSite::Trace(Visitor* visitor) const {
+ visitor->Trace(reentry_permit_);
visitor->Trace(document_);
visitor->Trace(attachment_root_);
visitor->Trace(head_);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h
index faff875c9c1..9ac353a3a9b 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_CONSTRUCTION_SITE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_CONSTRUCTION_SITE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/parser_content_policy.h"
#include "third_party/blink/renderer/core/html/parser/html_element_stack.h"
@@ -111,6 +110,8 @@ class HTMLConstructionSite final {
HTMLConstructionSite(HTMLParserReentryPermit*,
Document&,
ParserContentPolicy);
+ HTMLConstructionSite(const HTMLConstructionSite&) = delete;
+ HTMLConstructionSite& operator=(const HTMLConstructionSite&) = delete;
~HTMLConstructionSite();
void Trace(Visitor*) const;
@@ -222,7 +223,6 @@ class HTMLConstructionSite final {
class RedirectToFosterParentGuard {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(RedirectToFosterParentGuard);
public:
RedirectToFosterParentGuard(HTMLConstructionSite& tree)
@@ -231,6 +231,10 @@ class HTMLConstructionSite final {
tree_.redirect_attach_to_foster_parent_ = true;
}
+ RedirectToFosterParentGuard(const RedirectToFosterParentGuard&) = delete;
+ RedirectToFosterParentGuard& operator=(const RedirectToFosterParentGuard&) =
+ delete;
+
~RedirectToFosterParentGuard() {
tree_.redirect_attach_to_foster_parent_ = was_redirecting_before_;
}
@@ -269,7 +273,7 @@ class HTMLConstructionSite final {
const QualifiedName&,
const AtomicString& is);
- HTMLParserReentryPermit* reentry_permit_;
+ Member<HTMLParserReentryPermit> reentry_permit_;
Member<Document> document_;
// This is the root ContainerNode to which the parser attaches all newly
@@ -346,8 +350,6 @@ class HTMLConstructionSite final {
bool redirect_attach_to_foster_parent_;
bool in_quirks_mode_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLConstructionSite);
};
} // namespace blink
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 97df3a9628d..f2761665bc5 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
@@ -30,6 +30,7 @@
#include "base/auto_reset.h"
#include "base/numerics/safe_conversions.h"
+#include "base/stl_util.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
@@ -56,7 +57,6 @@
#include "third_party/blink/renderer/core/loader/preload_helper.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/html_parser_script_runner.h"
-#include "third_party/blink/renderer/core/script/script_runner.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/heap/handle.h"
@@ -89,13 +89,6 @@ size_t GetDiscardedTokenCountForTesting() {
// value exists.
constexpr int kDefaultMaxTokenizationBudget = 250;
-// The parser can temporarily defer execution of async scripts for successive
-// <script> tags (this is to reduce site breakage). This constant controls the
-// number of elements that have to be in between two <script> tags for them to
-// be considered "adjacent" for this heuristic. TODO(Richard.Townsend@arm.com,
-// https://crbug.com/1204178): remove this heuristic.
-constexpr int kTokensBetweenAdjacentScripts = 6;
-
class EndIfDelayedForbiddenScope;
class ShouldCompleteScope;
class AttemptToEndForbiddenScope;
@@ -144,6 +137,7 @@ class HTMLDocumentParserState
end_if_delayed_forbidden_(0),
should_complete_(0),
should_attempt_to_end_on_eof_(0),
+ times_yielded_(0),
needs_link_header_dispatch_(true),
have_seen_first_byte_(false) {}
@@ -197,6 +191,9 @@ class HTMLDocumentParserState
}
ParserSynchronizationPolicy GetMode() const { return mode_; }
+ void MarkYield() { times_yielded_++; }
+ int TimesYielded() const { return times_yielded_; }
+
void SetSeenCSPMetaTag(const bool seen) {
if (meta_csp_state_ == MetaCSPTokenState::kUnenforceable)
return;
@@ -239,6 +236,7 @@ class HTMLDocumentParserState
// Set to non-zero if Document::Finish has been called and we're operating
// asynchronously.
int should_attempt_to_end_on_eof_;
+ int times_yielded_;
bool needs_link_header_dispatch_;
bool have_seen_first_byte_;
};
@@ -384,22 +382,12 @@ HTMLDocumentParser::HTMLDocumentParser(
context_element, report_errors, options_));
}
-namespace {
-int GetMaxTokenizationBudget() {
- static int max = base::GetFieldTrialParamByFeatureAsInt(
- features::kForceSynchronousHTMLParsing, "MaxTokenizationBudget",
- kDefaultMaxTokenizationBudget);
- return max;
-}
-} // namespace
-
HTMLDocumentParser::HTMLDocumentParser(Document& document,
ParserContentPolicy content_policy,
ParserSynchronizationPolicy sync_policy,
ParserPrefetchPolicy prefetch_policy)
: ScriptableDocumentParser(document, content_policy),
options_(&document),
- reentry_permit_(HTMLParserReentryPermit::Create()),
token_(sync_policy != kAllowAsynchronousParsing
? std::make_unique<HTMLToken>()
: nullptr),
@@ -451,8 +439,6 @@ HTMLDocumentParser::HTMLDocumentParser(Document& document,
document.UkmSourceID(), document.UkmRecorder());
}
- max_tokenization_budget_ = GetMaxTokenizationBudget();
-
// Don't create preloader for parsing clipboard content.
if (content_policy == kDisallowScriptingAndPluginContent)
return;
@@ -478,6 +464,7 @@ void HTMLDocumentParser::Dispose() {
}
void HTMLDocumentParser::Trace(Visitor* visitor) const {
+ visitor->Trace(reentry_permit_);
visitor->Trace(tree_builder_);
visitor->Trace(parser_scheduler_);
visitor->Trace(script_runner_);
@@ -500,7 +487,8 @@ void HTMLDocumentParser::Detach() {
DocumentParser::Detach();
if (script_runner_)
script_runner_->Detach();
- tree_builder_->Detach();
+ if (tree_builder_)
+ tree_builder_->Detach();
// FIXME: It seems wrong that we would have a preload scanner here. Yet during
// fast/dom/HTMLScriptElement/script-load-events.html we do.
preload_scanner_.reset();
@@ -560,10 +548,6 @@ void HTMLDocumentParser::PrepareToStopParsing() {
if (IsDetached())
return;
- // If we suspended script async execution for https://crbug.com/1204178,
- // signal that it's OK to start processing them again.
- GetDocument()->GetScriptRunner()->ResumeAsyncScriptExecution();
-
AttemptToRunDeferredScriptsAndEnd();
}
@@ -865,7 +849,7 @@ void HTMLDocumentParser::DiscardSpeculationsAndResumeFrom(
background_parser_, std::move(checkpoint)));
}
-size_t HTMLDocumentParser::ProcessTokenizedChunkFromBackgroundParser(
+wtf_size_t HTMLDocumentParser::ProcessTokenizedChunkFromBackgroundParser(
std::unique_ptr<TokenizedChunk> pop_chunk,
bool* reached_end_of_file) {
TRACE_EVENT_WITH_FLOW0(
@@ -887,7 +871,7 @@ size_t HTMLDocumentParser::ProcessTokenizedChunkFromBackgroundParser(
std::unique_ptr<TokenizedChunk> chunk(std::move(pop_chunk));
const CompactHTMLTokenStream& tokens = chunk->tokens;
- size_t element_token_count = 0;
+ wtf_size_t element_token_count = 0;
loading_task_runner_->PostTask(
FROM_HERE, WTF::Bind(&BackgroundHTMLParser::StartedChunkWithCheckpoint,
@@ -978,7 +962,7 @@ void HTMLDocumentParser::PumpPendingSpeculations() {
bool reached_end_of_file = false;
while (!speculations_.IsEmpty()) {
DCHECK(!IsScheduledForUnpause());
- size_t element_token_count = ProcessTokenizedChunkFromBackgroundParser(
+ wtf_size_t element_token_count = ProcessTokenizedChunkFromBackgroundParser(
speculations_.TakeFirst(), &reached_end_of_file);
session.AddedElementTokens(element_token_count);
@@ -1042,8 +1026,13 @@ bool HTMLDocumentParser::PumpTokenizer() {
probe::ParseHTML probe(GetDocument(), this);
bool should_yield = false;
- bool should_pause_async_script_execution = false;
- int budget = max_tokenization_budget_;
+ // If we've yielded more than 2 times, then set the budget to a very large
+ // number, to attempt to consume all available tokens in one go. This
+ // heuristic is intended to allow a quick first contentful paint, followed by
+ // a larger rendering lifecycle that processes the remainder of the page.
+ int budget = (task_runner_state_->TimesYielded() <= 2)
+ ? kDefaultMaxTokenizationBudget
+ : 1e7;
base::ElapsedTimer chunk_parsing_timer_;
unsigned tokens_parsed = 0;
@@ -1051,28 +1040,13 @@ bool HTMLDocumentParser::PumpTokenizer() {
const auto next_token_status = CanTakeNextToken();
if (next_token_status == NoTokens) {
// No tokens left to process in this pump, so break
- if ((tokens_parsed <= kTokensBetweenAdjacentScripts) && !IsDetached() &&
- GetDocument()->GetScriptRunner()) {
- should_pause_async_script_execution =
- GetDocument()->GetScriptRunner()->AsyncScriptExecutionPaused();
- }
break;
} else if (next_token_status == HaveTokensAfterScript &&
task_runner_state_->HaveExitedHeader()) {
- // Just executed a parser-blocking script in the body (which is usually
- // very expensive), so expire the budget, yield, and permit paint if
- // needed.
- budget = 0;
- if (!should_run_until_completion) {
- // If we're yielding here, temporarily block async script execution.
- // There are some sites which assume
- // <script>...</script><script>...</script> run in a single parser pump
- // and can't handle an async script running in between. See
- // crbug.com/1197376 for details.
- should_yield = true;
- should_pause_async_script_execution = true;
- break;
- }
+ // Just executed a parser-blocking script in the body. We'd probably like
+ // to yield at some point soon, especially if we're in "extended budget"
+ // mode. So reduce the budget back to at most the default.
+ budget = std::min(budget, kDefaultMaxTokenizationBudget);
}
{
RUNTIME_CALL_TIMER_SCOPE(
@@ -1095,15 +1069,6 @@ bool HTMLDocumentParser::PumpTokenizer() {
DCHECK(IsStopped() || Token().IsUninitialized());
}
- if (LIKELY(!IsDetached())) {
- auto* script_runner = GetDocument()->GetScriptRunner();
- if (LIKELY(script_runner)) {
- if (should_pause_async_script_execution)
- script_runner->PauseAsyncScriptExecution();
- else
- script_runner->ResumeAsyncScriptExecution();
- }
- }
if (IsStopped()) {
if (metrics_reporter_ && tokens_parsed) {
@@ -1137,6 +1102,8 @@ bool HTMLDocumentParser::PumpTokenizer() {
// should_run_until_completion implies that we should not yield
CHECK(!should_run_until_completion || !should_yield);
+ if (should_yield)
+ task_runner_state_->MarkYield();
return should_yield;
}
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 adaa1510454..9f651d0a46d 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
@@ -122,7 +122,7 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
bool IsParsingAtLineNumber() const final;
OrdinalNumber LineNumber() const final;
- HTMLParserReentryPermit* ReentryPermit() { return reentry_permit_.get(); }
+ HTMLParserReentryPermit* ReentryPermit() { return reentry_permit_.Get(); }
struct TokenizedChunk {
USING_FAST_MALLOC(TokenizedChunk);
@@ -150,10 +150,6 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
void Flush() final;
void SetDecoder(std::unique_ptr<TextResourceDecoder>) final;
- void SetMaxTokenizationBudgetForTesting(int budget) {
- max_tokenization_budget_ = budget;
- }
-
protected:
void insert(const String&) final;
void Append(const String&) override;
@@ -202,7 +198,7 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
std::unique_ptr<TokenizedChunk> last_chunk,
std::unique_ptr<HTMLToken>,
std::unique_ptr<HTMLTokenizer>);
- size_t ProcessTokenizedChunkFromBackgroundParser(
+ wtf_size_t ProcessTokenizedChunkFromBackgroundParser(
std::unique_ptr<TokenizedChunk>,
bool*);
void PumpPendingSpeculations();
@@ -250,7 +246,8 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
HTMLParserOptions options_;
HTMLInputStream input_;
- scoped_refptr<HTMLParserReentryPermit> reentry_permit_;
+ Member<HTMLParserReentryPermit> reentry_permit_ =
+ MakeGarbageCollected<HTMLParserReentryPermit>();
std::unique_ptr<HTMLToken> token_;
std::unique_ptr<HTMLTokenizer> tokenizer_;
@@ -291,7 +288,6 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
// would require keeping track of token positions of preload requests.
CompactHTMLToken* pending_csp_meta_token_;
- int max_tokenization_budget_;
bool can_parse_asynchronously_;
bool end_was_delayed_;
bool have_background_parser_;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc
index ac0059c0c02..abbfadca2d6 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc
@@ -200,134 +200,6 @@ TEST_P(HTMLDocumentParserLoadingTest,
}
TEST_P(HTMLDocumentParserLoadingTest,
- AsyncScriptsShouldNotRunBetweenSyncScripts) {
- // This is a Chromium-specific quirk for async <script>s. The spec says that
- // async scripts can execute whenever they're ready, in practice some sites
- // assume that async scripts won't run during a block of <script> tags.
- // These sites can break under the synchronous, budgeted HTML parser because
- // it yields after <script> tags, creating a gap where async scripts can run
- // out of the previous sequence.
- SimRequest::Params params;
- // Only relevant for the foreground parser
- if (GetParam() != kAllowDeferredParsing) {
- return;
- }
- params.response_http_status = 200;
- SimRequest main_resource("https://example.com/test.html", "text/html");
- SimRequest async_js("https://example.com/async-script.js",
- "application/javascript", params);
- SimRequest sync_js("https://example.com/sync-script.js",
- "application/javascript", params);
-
- LoadURL("https://example.com/test.html");
- // The first write/run-until-idle cycle backs all the simulated requests via
- // preloads and fetches the async script.
- main_resource.Write(R"HTML(
- <!DOCTYPE html>
- <html>
- <head>
- <link rel="preload" href="async-script.js" as="script">
- <link rel="preload" href="sync-script.js" as="script">
- <script src="async-script.js" async></script>
- </head>
- <body>
- <script>var x = 'something';</script>
- <script src="sync-script.js"></script>
- </body>
- </html>
- )HTML");
- platform_->RunUntilIdle();
- // Complete the async script so that it's ready to execute.
- async_js.Complete(R"JS(
- if (typeof x === 'undefined') {
- document.body.innerHTML='<div id="test-failed-x">x undefined</div>';
- }
- if (typeof y === 'undefined') {
- document.body.innerHTML='<div id="test-failed-y">y undefined</div>';
- }
- )JS");
- // The async script should not execute inside this event pump.
- platform_->RunUntilIdle();
- main_resource.Complete(); // Finish the main page
- // Finish the second sync script.
- sync_js.Complete(R"JS(
- var y = 'something';
- )JS");
- // Expecting the sync script to execute before the async one.
- platform_->RunUntilIdle();
- EXPECT_FALSE(GetDocument().getElementById("test-failed-x"));
- EXPECT_FALSE(GetDocument().getElementById("test-failed-y"));
-}
-
-TEST_P(HTMLDocumentParserLoadingTest,
- AsyncScriptsShouldRunBetweenSyncScriptsAndOtherElements) {
- // To preserve reasonable async performance (despite the above quirk), Chrome
- // deactivates this async script suspension when there's a few elements
- // between adjacent <script> tags.
- SimRequest::Params params;
-
- // Only relevant for parsers which load pages.
- if (GetParam() == kForceSynchronousParsing) {
- return;
- }
-
- params.response_http_status = 200;
- SimRequest main_resource("https://example.com/test.html", "text/html");
- SimRequest async_js("https://example.com/async-script.js",
- "application/javascript", params);
- SimRequest sync_js("https://example.com/sync-script.js",
- "application/javascript", params);
-
- LoadURL("https://example.com/test.html");
- WTF::StringBuilder sb;
- sb.Append(R"HTML(
- <html>
- <head>
- <!DOCTYPE html>
- <html>
- <head>
- <link rel="preload" href="async-script.js" as="script">
- <link rel="preload" href="sync-script.js" as="script">
- <script src="async-script.js" async></script>
- </head>
- <body>
- <script>var x = 'something';</script>
- )HTML");
- for (int i = 0; i < 16; i++) {
- sb.Append(
- "<p>Within this region, the async script block should be lifted.</p>");
- }
- sb.Append(R"HTML(
- <p>A lot of distinct paragraphs and stuff</p>
- <script src="sync-script.js"></script>
- </body>
- </html>
- )HTML");
- main_resource.Complete(sb.ToString());
- platform_->RunUntilIdle();
- // The parser should now have processed up to the second sync script,
- // dispatched the async one. Next, complete the async script.
- async_js.Complete(R"JS(
- if (typeof x === 'undefined') {
- document.body.innerHTML='<div id="test-failed">';
- }
- if (typeof y === 'undefined') {
- document.body.innerHTML='<div id="test-passed">';
- }
- )JS");
- // Async script should run inside this event pump.
- platform_->RunUntilIdle();
- // Finally, complete the sync script.
- sync_js.Complete(R"JS(
- var y = 'something';
- )JS");
- platform_->RunUntilIdle();
-
- EXPECT_FALSE(GetDocument().getElementById("test-failed"));
- EXPECT_TRUE(GetDocument().getElementById("test-passed"));
-}
-
-TEST_P(HTMLDocumentParserLoadingTest,
ShouldPauseParsingForExternalStylesheetsInBodyIncremental) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimSubresourceRequest css_head_resource("https://example.com/testHead.css",
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc
index b730ff66b0a..8d25695f9d4 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc
@@ -34,8 +34,7 @@ class MockNoStatePrefetchClient : public NoStatePrefetchClient {
class HTMLDocumentParserTest
: public PageTestBase,
- public testing::WithParamInterface<
- testing::tuple<ParserSynchronizationPolicy, int>>,
+ public testing::WithParamInterface<ParserSynchronizationPolicy>,
private ScopedForceSynchronousHTMLParsingForTest {
protected:
HTMLDocumentParserTest()
@@ -59,9 +58,8 @@ class HTMLDocumentParserTest
}
HTMLDocumentParser* CreateParser(HTMLDocument& document) {
- auto* parser = MakeGarbageCollected<HTMLDocumentParser>(
- document, testing::get<0>(GetParam()));
- parser->SetMaxTokenizationBudgetForTesting(testing::get<1>(GetParam()));
+ auto* parser =
+ MakeGarbageCollected<HTMLDocumentParser>(document, GetParam());
std::unique_ptr<TextResourceDecoder> decoder(
BuildTextResourceDecoderFor(&document, "text/html", g_null_atom));
parser->SetDecoder(std::move(decoder));
@@ -69,21 +67,17 @@ class HTMLDocumentParserTest
}
private:
- ParserSynchronizationPolicy Policy() const {
- return testing::get<0>(GetParam());
- }
+ ParserSynchronizationPolicy Policy() const { return GetParam(); }
bool original_threaded_parsing_;
};
} // namespace
-INSTANTIATE_TEST_SUITE_P(
- HTMLDocumentParserTest,
- HTMLDocumentParserTest,
- testing::Combine(testing::Values(kForceSynchronousParsing,
- kAllowDeferredParsing),
- testing::Values(250, 500, 1000)));
+INSTANTIATE_TEST_SUITE_P(HTMLDocumentParserTest,
+ HTMLDocumentParserTest,
+ testing::Values(kForceSynchronousParsing,
+ kAllowDeferredParsing));
TEST_P(HTMLDocumentParserTest, StopThenPrepareToStopShouldNotCrash) {
auto& document = To<HTMLDocument>(GetDocument());
@@ -165,7 +159,7 @@ TEST_P(HTMLDocumentParserTest, AppendNoPrefetch) {
HTMLParserScriptRunnerHost* script_runner_host =
parser->AsHTMLParserScriptRunnerHostForTesting();
EXPECT_EQ(script_runner_host->HasPreloadScanner(),
- testing::get<0>(GetParam()) == kAllowDeferredParsing);
+ GetParam() == kAllowDeferredParsing);
EXPECT_EQ(HTMLTokenizer::kTagNameState, parser->Tokenizer()->GetState());
// Cancel any pending work to make sure that RuntimeFeatures DCHECKs do not
// fire.
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h
index 8380d7c87ab..fc50b2acb60 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_ELEMENT_STACK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_ELEMENT_STACK_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/html/parser/html_stack_item.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -45,10 +44,14 @@ class HTMLElementStack {
public:
HTMLElementStack();
+ HTMLElementStack(const HTMLElementStack&) = delete;
+ HTMLElementStack& operator=(const HTMLElementStack&) = delete;
class ElementRecord final : public GarbageCollected<ElementRecord> {
public:
ElementRecord(HTMLStackItem*, ElementRecord*);
+ ElementRecord(const ElementRecord&) = delete;
+ ElementRecord& operator=(const ElementRecord&) = delete;
Element* GetElement() const { return item_->GetElement(); }
ContainerNode* GetNode() const { return item_->GetNode(); }
@@ -70,8 +73,6 @@ class HTMLElementStack {
Member<HTMLStackItem> item_;
Member<ElementRecord> next_;
-
- DISALLOW_COPY_AND_ASSIGN(ElementRecord);
};
unsigned StackDepth() const { return stack_depth_; }
@@ -187,8 +188,6 @@ class HTMLElementStack {
Member<Element> head_element_;
Member<Element> body_element_;
unsigned stack_depth_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLElementStack);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h b/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h
index bb2f43f327a..05106741a91 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_FORMATTING_ELEMENT_LIST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_FORMATTING_ELEMENT_LIST_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/html/parser/html_stack_item.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -42,6 +41,9 @@ class HTMLFormattingElementList {
public:
HTMLFormattingElementList();
+ HTMLFormattingElementList(const HTMLFormattingElementList&) = delete;
+ HTMLFormattingElementList& operator=(const HTMLFormattingElementList&) =
+ delete;
// Ideally Entry would be private, but HTMLTreeBuilder has to coordinate
// between the HTMLFormattingElementList and HTMLElementStack and needs access
@@ -138,8 +140,6 @@ class HTMLFormattingElementList {
void EnsureNoahsArkCondition(HTMLStackItem*);
HeapVector<Entry> entries_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLFormattingElementList);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_input_stream.h b/chromium/third_party/blink/renderer/core/html/parser/html_input_stream.h
index 61791f4f215..8b1c9b3acbc 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_input_stream.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_input_stream.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_INPUT_STREAM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_INPUT_STREAM_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h"
#include "third_party/blink/renderer/platform/text/segmented_string.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -54,6 +53,8 @@ class HTMLInputStream {
public:
HTMLInputStream() : last_(&first_) {}
+ HTMLInputStream(const HTMLInputStream&) = delete;
+ HTMLInputStream& operator=(const HTMLInputStream&) = delete;
void AppendToEnd(const SegmentedString& string) { last_->Append(string); }
@@ -104,8 +105,6 @@ class HTMLInputStream {
private:
SegmentedString first_;
SegmentedString* last_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLInputStream);
};
class InsertionPointRecord {
@@ -123,6 +122,9 @@ class InsertionPointRecord {
input_stream_->Current().SetCurrentPosition(line_, column_, 0);
}
+ InsertionPointRecord(const InsertionPointRecord&) = delete;
+ InsertionPointRecord& operator=(const InsertionPointRecord&) = delete;
+
~InsertionPointRecord() {
// Some inserted text may have remained in input stream. E.g. if script has
// written "&amp" or "<table", it stays in buffer because it cannot be
@@ -140,8 +142,6 @@ class InsertionPointRecord {
SegmentedString next_;
OrdinalNumber line_;
OrdinalNumber column_;
-
- DISALLOW_COPY_AND_ASSIGN(InsertionPointRecord);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h b/chromium/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h
index 62f13afbebe..835b3dd8126 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/html/parser/html_token.h"
#include "third_party/blink/renderer/platform/text/segmented_string.h"
@@ -44,6 +43,8 @@ class HTMLMetaCharsetParser {
public:
HTMLMetaCharsetParser();
+ HTMLMetaCharsetParser(const HTMLMetaCharsetParser&) = delete;
+ HTMLMetaCharsetParser& operator=(const HTMLMetaCharsetParser&) = delete;
~HTMLMetaCharsetParser();
// Returns true if done checking, regardless whether an encoding is found.
@@ -62,8 +63,6 @@ class HTMLMetaCharsetParser {
bool done_checking_;
WTF::TextEncoding encoding_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLMetaCharsetParser);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc
index bb4b9afb713..3b9073e0d76 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc
@@ -68,6 +68,8 @@ void HTMLParserMetrics::ReportBackgroundParsingUMA() {
min_tokens_parsed_);
UMA_HISTOGRAM_COUNTS_1M("Blink.HTMLParsing.TokensParsedAverage",
total_tokens_parsed_ / chunk_count_);
+ UMA_HISTOGRAM_COUNTS_10M("Blink.HTMLParsing.TokensParsedTotal",
+ total_tokens_parsed_);
// Only report yield data if we actually yielded.
if (max_yield_interval_ != base::TimeDelta()) {
@@ -107,6 +109,8 @@ void HTMLParserMetrics::ReportForcedSynchronousParsingUMA() {
min_tokens_parsed_);
UMA_HISTOGRAM_COUNTS_1M("Blink.HTMLParsing.TokensParsedAverage2",
total_tokens_parsed_ / chunk_count_);
+ UMA_HISTOGRAM_COUNTS_10M("Blink.HTMLParsing.TokensParsedTotal2",
+ total_tokens_parsed_);
// Only report yield data if we actually yielded.
if (max_yield_interval_ != base::TimeDelta()) {
@@ -147,6 +151,7 @@ void HTMLParserMetrics::ReportMetricsAtParseEnd(bool background_parsing) {
builder.SetTokensParsedMax(max_tokens_parsed_);
builder.SetTokensParsedMin(min_tokens_parsed_);
builder.SetTokensParsedAverage(total_tokens_parsed_ / chunk_count_);
+ builder.SetTokensParsedTotal(total_tokens_parsed_);
if (accumulated_yield_intervals_ != base::TimeDelta()) {
builder.SetYieldedTimeMax(max_yield_interval_.InMicroseconds());
builder.SetYieldedTimeMin(min_yield_interval_.InMicroseconds());
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h
index 98760a879a7..40db75a0a08 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h
@@ -19,6 +19,8 @@ namespace blink {
class CORE_EXPORT HTMLParserMetrics {
public:
HTMLParserMetrics(int64_t source_id, ukm::UkmRecorder*);
+ HTMLParserMetrics(const HTMLParserMetrics&) = delete;
+ HTMLParserMetrics& operator=(const HTMLParserMetrics&) = delete;
~HTMLParserMetrics() = default;
void AddChunk(base::TimeDelta elapsed_time, unsigned tokens_parsed);
@@ -56,8 +58,6 @@ class CORE_EXPORT HTMLParserMetrics {
// Track total number of characters parsed in one instantiation of the
// parser.
unsigned input_character_count = 0;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLParserMetrics);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc
index 2b4112f8e5f..c15a5db31aa 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc
@@ -6,6 +6,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/test_mock_time_task_runner.h"
+#include "build/build_config.h"
#include "components/ukm/test_ukm_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -86,6 +87,7 @@ TEST_F(HTMLBackgroundParserMetricsTest, ReportSingleChunk) {
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMax", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMin", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedAverage", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedTotal", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMax", 0);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMin", 0);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeAverage", 0);
@@ -98,6 +100,8 @@ TEST_F(HTMLBackgroundParserMetricsTest, ReportSingleChunk) {
1);
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedAverage",
2, 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedTotal", 2,
+ 1);
// Expect that the times have moved from the default and the max and min
// and total are all the same (within the same bucket)
@@ -115,7 +119,13 @@ TEST_F(HTMLBackgroundParserMetricsTest, ReportSingleChunk) {
EXPECT_GT(parsing_time_total_buckets[0].min, 0);
}
-TEST_F(HTMLBackgroundParserMetricsTest, HistogramReportsTwoChunks) {
+#if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
+// https://crbug.com/1222653
+#define MAYBE_HistogramReportsTwoChunks DISABLED_HistogramReportsTwoChunks
+#else
+#define MAYBE_HistogramReportsTwoChunks HistogramReportsTwoChunks
+#endif
+TEST_F(HTMLBackgroundParserMetricsTest, MAYBE_HistogramReportsTwoChunks) {
// Although the tests use a mock clock, the metrics recorder checks if the
// system has a high resolution clock before recording results. As a result,
// the tests will fail if the system does not have a high resolution clock.
@@ -127,21 +137,20 @@ TEST_F(HTMLBackgroundParserMetricsTest, HistogramReportsTwoChunks) {
// This content exceeds the number of tokens before a script tag used as
// the yield threshold. If the yield threshold changes, this test will fail
// and/or need changing. See the HTMLParserScheduler::ShouldYield method for
- // the current value of the constant.
+ // the current value of the constant. The code below assumes 50 tokens.
LoadHTML(R"HTML(
<head></head>
<div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div>
- <div></div><div></div><div></div><div></div><div></div><div></div>
- <div></div><div></div><div></div><div></div><div></div><div></div>
- <div></div><div></div><div></div><div></div><div></div><div></div>
- <div></div><div></div><div></div><div></div><div></div><div></div>
- <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div> 63 tokens including this text token
<script>document.offsetTop</script>
)HTML");
+ // Comment this back in to see histogram values:
+ // LOG(ERROR) << histogram_tester.GetAllHistogramsRecorded();
+
// Should have one of each metric.
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ChunkCount", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeMax", 1);
@@ -150,18 +159,21 @@ TEST_F(HTMLBackgroundParserMetricsTest, HistogramReportsTwoChunks) {
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMax", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMin", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedAverage", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedTotal", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMax", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMin", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeAverage", 1);
// Expect specific values for the chunks and tokens counts
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.ChunkCount", 2, 1);
- histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMax", 110,
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMax", 49,
1);
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMin", 0,
1);
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedAverage",
- 55, 1);
+ 28, 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedTotal", 55,
+ 1);
// For parse times, expect that the times have moved from the default.
std::vector<base::Bucket> parsing_time_max_buckets =
@@ -193,7 +205,13 @@ TEST_F(HTMLBackgroundParserMetricsTest, HistogramReportsTwoChunks) {
EXPECT_GT(yield_time_average_buckets[0].min, 0);
}
-TEST_F(HTMLForceSynchronousParserMetricsTest, ReportSingleChunk) {
+#if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
+// https://crbug.com/1222653
+#define MAYBE_ReportSingleChunk DISABLED_ReportSingleChunk
+#else
+#define MAYBE_ReportSingleChunk ReportSingleChunk
+#endif
+TEST_F(HTMLForceSynchronousParserMetricsTest, MAYBE_ReportSingleChunk) {
// Although the tests use a mock clock, the metrics recorder checks if the
// system has a high resolution clock before recording results. As a result,
// the tests will fail if the system does not have a high resolution clock.
@@ -217,6 +235,7 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, ReportSingleChunk) {
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMin2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedAverage2",
1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedTotal2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMax2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMin2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeAverage2", 1);
@@ -229,6 +248,8 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, ReportSingleChunk) {
1);
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedAverage2",
5, 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedTotal2", 5,
+ 1);
// Expect that the times have moved from the default and the max and min
// and total are all the same (within the same bucket)
@@ -249,7 +270,7 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, ReportSingleChunk) {
19, 1);
}
-TEST_F(HTMLForceSynchronousParserMetricsTest, HistogramReportsTwoChunks) {
+TEST_F(HTMLForceSynchronousParserMetricsTest, MAYBE_HistogramReportsTwoChunks) {
// Although the tests use a mock clock, the metrics recorder checks if the
// system has a high resolution clock before recording results. As a result,
// the tests will fail if the system does not have a high resolution clock.
@@ -262,6 +283,8 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, HistogramReportsTwoChunks) {
// This content processes many tokens before a script tag used as the yield
// threshold. If the yield behavior changes this test may need updating.
+ // See the HTMLDocumentParser::PumpTokenizer method for the current yielding
+ // behavior. The code below assumes that 250+ tokens is enough to yield.
LoadHTML(R"HTML(
<head></head>
<div></div><div></div><div></div><div></div><div></div><div></div>
@@ -272,10 +295,24 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, HistogramReportsTwoChunks) {
<div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>111 tokens to here
<div></div><div></div><div></div><div></div><div></div><div></div>
- <script>document.offsetTop</script>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>220 tokens to here
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>257 tokens to here
)HTML");
+ // Comment this back in to see histogram values:
+ // LOG(ERROR) << histogram_tester.GetAllHistogramsRecorded();
+
// Should have one of each metric.
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ChunkCount2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeMax2", 1);
@@ -285,18 +322,21 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, HistogramReportsTwoChunks) {
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMin2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedAverage2",
1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedTotal2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMax2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMin2", 1);
histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeAverage2", 1);
// Expect specific values for the chunks and tokens counts
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.ChunkCount2", 2, 1);
- histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMax2", 124,
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMax2", 196,
1);
- histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMin2", 2,
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMin2", 24,
1);
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedAverage2",
- 63, 1);
+ 113, 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedTotal2",
+ 203, 1);
// For parse times, expect that the times have moved from the default.
std::vector<base::Bucket> parsing_time_max_buckets =
@@ -328,7 +368,7 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, HistogramReportsTwoChunks) {
EXPECT_GT(yield_time_average_buckets[0].min, 0);
histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.InputCharacterCount",
- 700, 1);
+ 1447, 1);
}
TEST_F(HTMLForceSynchronousParserMetricsTest, UkmStoresValuesCorrectly) {
@@ -404,6 +444,12 @@ TEST_F(HTMLForceSynchronousParserMetricsTest, UkmStoresValuesCorrectly) {
*metric_value,
(first_tokens_parsed + second_tokens_parsed + third_tokens_parsed) / 3);
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "TokensParsedTotal"));
+ metric_value =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, "TokensParsedTotal");
+ EXPECT_EQ(*metric_value,
+ first_tokens_parsed + second_tokens_parsed + third_tokens_parsed);
+
EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "YieldedTimeMax"));
metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "YieldedTimeMax");
EXPECT_EQ(*metric_value, first_yield_time.InMicroseconds());
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.cc
index fdf8955dba5..1d453990867 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.cc
@@ -6,11 +6,6 @@
namespace blink {
-scoped_refptr<HTMLParserReentryPermit> HTMLParserReentryPermit::Create() {
- return base::AdoptRef(new HTMLParserReentryPermit());
-}
-
-HTMLParserReentryPermit::HTMLParserReentryPermit()
- : script_nesting_level_(0), parser_pause_flag_(false) {}
+HTMLParserReentryPermit::HTMLParserReentryPermit() = default;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h
index 60d6a66e754..2372eb10fc8 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h
@@ -5,9 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_PARSER_REENTRY_PERMIT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_PARSER_REENTRY_PERMIT_H_
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
@@ -36,9 +35,11 @@ namespace blink {
// flag. However recursively parsing end script tags, or running
// custom element constructors, does set the parser pause flag.
class HTMLParserReentryPermit final
- : public RefCounted<HTMLParserReentryPermit> {
+ : public GarbageCollected<HTMLParserReentryPermit> {
public:
- static scoped_refptr<HTMLParserReentryPermit> Create();
+ HTMLParserReentryPermit();
+ HTMLParserReentryPermit(const HTMLParserReentryPermit&) = delete;
+ HTMLParserReentryPermit& operator=(const HTMLParserReentryPermit&) = delete;
~HTMLParserReentryPermit() = default;
unsigned ScriptNestingLevel() const { return script_nesting_level_; }
@@ -57,6 +58,11 @@ class HTMLParserReentryPermit final
permit_->script_nesting_level_++;
}
+ ScriptNestingLevelIncrementer(const ScriptNestingLevelIncrementer&) =
+ delete;
+ ScriptNestingLevelIncrementer& operator=(
+ const ScriptNestingLevelIncrementer&) = delete;
+
ScriptNestingLevelIncrementer(ScriptNestingLevelIncrementer&&) = default;
~ScriptNestingLevelIncrementer() {
@@ -67,24 +73,20 @@ class HTMLParserReentryPermit final
private:
HTMLParserReentryPermit* permit_;
-
- DISALLOW_COPY_AND_ASSIGN(ScriptNestingLevelIncrementer);
};
ScriptNestingLevelIncrementer IncrementScriptNestingLevel() {
return ScriptNestingLevelIncrementer(this);
}
- private:
- HTMLParserReentryPermit();
+ void Trace(Visitor*) const {}
+ private:
// https://html.spec.whatwg.org/C/#script-nesting-level
- unsigned script_nesting_level_;
+ unsigned script_nesting_level_ = 0;
// https://html.spec.whatwg.org/C/#parser-pause-flag
- bool parser_pause_flag_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLParserReentryPermit);
+ bool parser_pause_flag_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc
index 871214fd6b1..e9ecf38a495 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc
@@ -40,7 +40,7 @@ SpeculationsPumpSession::SpeculationsPumpSession(unsigned& nesting_level)
SpeculationsPumpSession::~SpeculationsPumpSession() = default;
-void SpeculationsPumpSession::AddedElementTokens(size_t count) {
+void SpeculationsPumpSession::AddedElementTokens(wtf_size_t count) {
processed_element_tokens_ += count;
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h
index 8196c63cb6c..633af84081e 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_PARSER_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_PARSER_SCHEDULER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
#include "base/timer/elapsed_timer.h"
@@ -46,18 +45,22 @@ class SpeculationsPumpSession : public NestingLevelIncrementer {
~SpeculationsPumpSession();
base::TimeDelta ElapsedTime() const { return start_time_.Elapsed(); }
- void AddedElementTokens(size_t count);
- size_t ProcessedElementTokens() const { return processed_element_tokens_; }
+ void AddedElementTokens(wtf_size_t count);
+ wtf_size_t ProcessedElementTokens() const {
+ return processed_element_tokens_;
+ }
private:
base::ElapsedTimer start_time_;
- size_t processed_element_tokens_;
+ wtf_size_t processed_element_tokens_;
};
class HTMLParserScheduler final : public GarbageCollected<HTMLParserScheduler> {
public:
HTMLParserScheduler(HTMLDocumentParser*,
scoped_refptr<base::SingleThreadTaskRunner>);
+ HTMLParserScheduler(const HTMLParserScheduler&) = delete;
+ HTMLParserScheduler& operator=(const HTMLParserScheduler&) = delete;
~HTMLParserScheduler();
bool IsScheduledForUnpause() const;
@@ -76,8 +79,6 @@ class HTMLParserScheduler final : public GarbageCollected<HTMLParserScheduler> {
scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
TaskHandle cancellable_continue_parse_task_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLParserScheduler);
};
} // namespace blink
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 c5535ca14cd..81f3ba53680 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
@@ -1118,8 +1118,9 @@ void TokenPreloadScanner::UpdatePredictedBaseURL(const Token& token) {
token.GetAttributeItem(html_names::kHrefAttr)) {
KURL url(document_url_, StripLeadingAndTrailingHTMLSpaces(
href_attribute->Value8BitIfNecessary()));
- predicted_base_element_url_ =
- url.IsValid() && !url.ProtocolIsData() ? url.Copy() : KURL();
+ bool is_valid_base_url =
+ url.IsValid() && !url.ProtocolIsData() && !url.ProtocolIsJavaScript();
+ predicted_base_element_url_ = is_valid_base_url ? url.Copy() : KURL();
}
}
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 fc5e997a9aa..b966086daac 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
@@ -30,7 +30,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -86,6 +85,8 @@ class TokenPreloadScanner {
const MediaValuesCached::MediaValuesCachedData&,
const ScannerType,
bool priority_hints_origin_trial_enabled);
+ TokenPreloadScanner(const TokenPreloadScanner&) = delete;
+ TokenPreloadScanner& operator=(const TokenPreloadScanner&) = delete;
~TokenPreloadScanner();
void Scan(const HTMLToken&,
@@ -174,8 +175,6 @@ class TokenPreloadScanner {
bool did_rewind_ = false;
Vector<Checkpoint> checkpoints_;
-
- DISALLOW_COPY_AND_ASSIGN(TokenPreloadScanner);
};
class CORE_EXPORT HTMLPreloadScanner {
@@ -187,6 +186,8 @@ class CORE_EXPORT HTMLPreloadScanner {
std::unique_ptr<CachedDocumentParameters>,
const MediaValuesCached::MediaValuesCachedData&,
const TokenPreloadScanner::ScannerType);
+ HTMLPreloadScanner(const HTMLPreloadScanner&) = delete;
+ HTMLPreloadScanner& operator=(const HTMLPreloadScanner&) = delete;
~HTMLPreloadScanner();
void AppendToEnd(const SegmentedString&);
@@ -199,8 +200,6 @@ class CORE_EXPORT HTMLPreloadScanner {
SegmentedString source_;
HTMLToken token_;
std::unique_ptr<HTMLTokenizer> tokenizer_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLPreloadScanner);
};
} // namespace blink
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 edd5afda6d8..ab628dd22db 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
@@ -6,8 +6,8 @@
#include <memory>
#include "base/strings/stringprintf.h"
+#include "services/network/public/mojom/web_client_hints_types.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_client_hints_type.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
@@ -1511,4 +1511,17 @@ TEST_F(HTMLPreloadScannerTest, TemplateInteractions) {
Test(test);
}
+// Regression test for https://crbug.com/1181291
+TEST_F(HTMLPreloadScannerTest, JavascriptBaseUrl) {
+ PreloadScannerTestCase test_cases[] = {
+ {"",
+ "<base href='javascript:'><base href='javascript:notallowed'><base "
+ "href='http://example.test/'><link rel=preload href=bla as=SCRIPT>",
+ "bla", "http://example.test/", ResourceType::kScript, 0},
+ };
+
+ for (const auto& test_case : test_cases)
+ Test(test_case);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.h b/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.h
index fbd91f7574b..de2dce801cc 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/parser/preload_request.h"
#include "third_party/blink/renderer/core/html/parser/resource_preloader.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -45,6 +44,8 @@ class CORE_EXPORT HTMLResourcePreloader
public:
explicit HTMLResourcePreloader(Document&);
+ HTMLResourcePreloader(const HTMLResourcePreloader&) = delete;
+ HTMLResourcePreloader& operator=(const HTMLResourcePreloader&) = delete;
void Trace(Visitor*) const;
@@ -57,8 +58,6 @@ class CORE_EXPORT HTMLResourcePreloader
bool AllowPreloadRequest(PreloadRequest* preload) const;
Member<Document> document_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLResourcePreloader);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_token.h b/chromium/third_party/blink/renderer/core/html/parser/html_token.h
index f6bac9cda6a..9a8043dee13 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_token.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_token.h
@@ -30,7 +30,6 @@
#include <utility>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/parser/literal_buffer.h"
@@ -46,14 +45,14 @@ class DoctypeData {
: has_public_identifier_(false),
has_system_identifier_(false),
force_quirks_(false) {}
+ DoctypeData(const DoctypeData&) = delete;
+ DoctypeData& operator=(const DoctypeData&) = delete;
bool has_public_identifier_;
bool has_system_identifier_;
WTF::Vector<UChar> public_identifier_;
WTF::Vector<UChar> system_identifier_;
bool force_quirks_;
-
- DISALLOW_COPY_AND_ASSIGN(DoctypeData);
};
static inline Attribute* FindAttributeInVector(Vector<Attribute>& attributes,
@@ -156,6 +155,8 @@ class HTMLToken {
typedef LiteralBuffer<UChar, 256> DataVector;
HTMLToken() { Clear(); }
+ HTMLToken(const HTMLToken&) = delete;
+ HTMLToken& operator=(const HTMLToken&) = delete;
void Clear() {
type_ = kUninitialized;
@@ -438,8 +439,6 @@ class HTMLToken {
// For DOCTYPE
std::unique_ptr<DoctypeData> doctype_data_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLToken);
};
#ifndef NDEBUG
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
index ca62cd2f5be..bed4a53bc4e 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
@@ -61,12 +61,20 @@ enum class ScanFlags : uint8_t {
kNullCharacter = 1 << 0,
kNewlineOrCarriageReturn = 1 << 1,
kWhitespaceNotNewline = 1 << 2,
- kAmpersandAndOpenTag = 1 << 3,
+ kAmpersand = 1 << 3,
+ kOpenTag = 1 << 4,
+ kSlashAndCloseTag = 1 << 5,
+ kEqual = 1 << 6,
+ kQuotes = 1 << 7,
// Compound flags
kWhitespace = kWhitespaceNotNewline | kNewlineOrCarriageReturn,
kCharacterTokenSpecial =
- kNullCharacter | kNewlineOrCarriageReturn | kAmpersandAndOpenTag,
+ kNullCharacter | kNewlineOrCarriageReturn | kAmpersand | kOpenTag,
kNullOrNewline = kNullCharacter | kNewlineOrCarriageReturn,
+ kRCDATASpecial = kNullCharacter | kAmpersand | kOpenTag,
+ kTagNameSpecial = kWhitespace | kSlashAndCloseTag | kNullCharacter,
+ kAttributeNameSpecial = kWhitespace | kSlashAndCloseTag | kNullCharacter |
+ kEqual | kOpenTag | kQuotes,
};
static constexpr uint8_t CreateScanFlags(UChar cc) {
@@ -79,8 +87,16 @@ static constexpr uint8_t CreateScanFlags(UChar cc) {
scan_flag = SCAN_FLAG(kNewlineOrCarriageReturn);
else if (cc == ' ' || cc == '\x09' || cc == '\x0C')
scan_flag = SCAN_FLAG(kWhitespaceNotNewline);
- else if (cc == '&' || cc == '<')
- scan_flag = SCAN_FLAG(kAmpersandAndOpenTag);
+ else if (cc == '&')
+ scan_flag = SCAN_FLAG(kAmpersand);
+ else if (cc == '<')
+ scan_flag = SCAN_FLAG(kOpenTag);
+ else if (cc == '/' || cc == '>')
+ scan_flag = SCAN_FLAG(kSlashAndCloseTag);
+ else if (cc == '=')
+ scan_flag = SCAN_FLAG(kEqual);
+ else if (cc == '"' || cc == '\'')
+ scan_flag = SCAN_FLAG(kQuotes);
return scan_flag;
#undef SCAN_FLAG
}
@@ -240,16 +256,19 @@ bool HTMLTokenizer::NextToken(SegmentedString& source, HTMLToken& token) {
END_STATE()
HTML_BEGIN_STATE(kRCDATAState) {
+ while (!CheckScanFlag(cc, ScanFlags::kRCDATASpecial)) {
+ BufferCharacter(cc);
+ if (!input_stream_preprocessor_.Advance(source, cc))
+ return HaveBufferedCharacterToken();
+ }
if (cc == '&')
HTML_ADVANCE_PAST_NON_NEWLINE_TO(kCharacterReferenceInRCDATAState);
else if (cc == '<')
HTML_ADVANCE_PAST_NON_NEWLINE_TO(kRCDATALessThanSignState);
else if (cc == kEndOfFileMarker)
return EmitEndOfFile(source);
- else {
- BufferCharacter(cc);
- HTML_CONSUME(kRCDATAState);
- }
+ else
+ NOTREACHED();
}
END_STATE()
@@ -334,9 +353,12 @@ bool HTMLTokenizer::NextToken(SegmentedString& source, HTMLToken& token) {
END_STATE()
HTML_BEGIN_STATE(kTagNameState) {
- if (IsTokenizerWhitespace(cc)) {
- HTML_ADVANCE_TO(kBeforeAttributeNameState);
- } else if (cc == '/') {
+ while (!CheckScanFlag(cc, ScanFlags::kTagNameSpecial)) {
+ token_->AppendToName(ToLowerCaseIfAlpha(cc));
+ if (!input_stream_preprocessor_.AdvancePastNonNewline(source, cc))
+ return HaveBufferedCharacterToken();
+ }
+ if (cc == '/') {
HTML_ADVANCE_PAST_NON_NEWLINE_TO(kSelfClosingStartTagState);
} else if (cc == '>') {
return EmitAndResumeIn(source, HTMLTokenizer::kDataState);
@@ -344,8 +366,8 @@ bool HTMLTokenizer::NextToken(SegmentedString& source, HTMLToken& token) {
ParseError();
HTML_RECONSUME_IN(kDataState);
} else {
- token_->AppendToName(ToLowerCaseIfAlpha(cc));
- HTML_CONSUME_NON_NEWLINE(kTagNameState);
+ DCHECK(IsTokenizerWhitespace(cc));
+ HTML_ADVANCE_TO(kBeforeAttributeNameState);
}
}
END_STATE()
@@ -778,6 +800,11 @@ bool HTMLTokenizer::NextToken(SegmentedString& source, HTMLToken& token) {
END_STATE()
HTML_BEGIN_STATE(kAttributeNameState) {
+ while (!CheckScanFlag(cc, ScanFlags::kAttributeNameSpecial)) {
+ token_->AppendToAttributeName(ToLowerCaseIfAlpha(cc));
+ if (!input_stream_preprocessor_.AdvancePastNonNewline(source, cc))
+ return HaveBufferedCharacterToken();
+ }
if (IsTokenizerWhitespace(cc)) {
token_->EndAttributeName(source.NumberOfCharactersConsumed());
HTML_ADVANCE_TO(kAfterAttributeNameState);
@@ -795,8 +822,8 @@ bool HTMLTokenizer::NextToken(SegmentedString& source, HTMLToken& token) {
token_->EndAttributeName(source.NumberOfCharactersConsumed());
HTML_RECONSUME_IN(kDataState);
} else {
- if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
- ParseError();
+ DCHECK(cc == '"' || cc == '\'' || cc == '<' || cc == '=');
+ ParseError();
token_->AppendToAttributeName(ToLowerCaseIfAlpha(cc));
HTML_CONSUME_NON_NEWLINE(kAttributeNameState);
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.h b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.h
index e261abf052c..90bb10f4320 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_TOKENIZER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_TOKENIZER_H_
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_options.h"
@@ -42,6 +41,8 @@ class CORE_EXPORT HTMLTokenizer {
public:
explicit HTMLTokenizer(const HTMLParserOptions&);
+ HTMLTokenizer(const HTMLTokenizer&) = delete;
+ HTMLTokenizer& operator=(const HTMLTokenizer&) = delete;
~HTMLTokenizer();
void Reset();
@@ -283,8 +284,6 @@ class CORE_EXPORT HTMLTokenizer {
LiteralBuffer<LChar, 32> buffered_end_tag_name_;
HTMLParserOptions options_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLTokenizer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index c8e08bff8a9..ba9356dad53 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
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.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"
@@ -140,6 +139,9 @@ class HTMLTreeBuilder::CharacterTokenBuffer {
DCHECK(!IsEmpty());
}
+ CharacterTokenBuffer(const CharacterTokenBuffer&) = delete;
+ CharacterTokenBuffer& operator=(const CharacterTokenBuffer&) = delete;
+
~CharacterTokenBuffer() { DCHECK(IsEmpty()); }
bool IsEmpty() const { return current_ == end_; }
@@ -225,8 +227,6 @@ class HTMLTreeBuilder::CharacterTokenBuffer {
scoped_refptr<StringImpl> characters_;
unsigned current_;
unsigned end_;
-
- DISALLOW_COPY_AND_ASSIGN(CharacterTokenBuffer);
};
HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser,
@@ -485,7 +485,8 @@ static void AdjustSVGTagNameCase(AtomicHTMLToken* token) {
MapLoweredLocalNameToName(case_map, svg_tags.get(), svg_names::kTagsCount);
}
- const QualifiedName& cased_name = case_map->at(token->GetName());
+ const QualifiedName& cased_name =
+ case_map->DeprecatedAtOrEmptyValue(token->GetName());
if (cased_name.LocalName().IsNull())
return;
token->SetName(cased_name.LocalName());
@@ -501,7 +502,8 @@ static void AdjustAttributes(AtomicHTMLToken* token) {
}
for (auto& token_attribute : token->Attributes()) {
- const QualifiedName& cased_name = case_map->at(token_attribute.LocalName());
+ const QualifiedName& cased_name =
+ case_map->DeprecatedAtOrEmptyValue(token_attribute.LocalName());
if (!cased_name.LocalName().IsNull())
token_attribute.ParserSetName(cased_name);
}
@@ -550,7 +552,8 @@ static void AdjustForeignAttributes(AtomicHTMLToken* token) {
for (unsigned i = 0; i < token->Attributes().size(); ++i) {
Attribute& token_attribute = token->Attributes().at(i);
- const QualifiedName& name = map->at(token_attribute.LocalName());
+ const QualifiedName& name =
+ map->DeprecatedAtOrEmptyValue(token_attribute.LocalName());
if (!name.LocalName().IsNull())
token_attribute.ParserSetName(name);
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.h b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.h
index 18c19c91b81..535be831bcf 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.h
@@ -28,7 +28,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_TREE_BUILDER_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/html/parser/html_construction_site.h"
#include "third_party/blink/renderer/core/html/parser/html_element_stack.h"
@@ -63,6 +62,8 @@ class HTMLTreeBuilder final : public GarbageCollected<HTMLTreeBuilder> {
ParserContentPolicy,
const HTMLParserOptions&,
bool include_shadow_roots);
+ HTMLTreeBuilder(const HTMLTreeBuilder&) = delete;
+ HTMLTreeBuilder& operator=(const HTMLTreeBuilder&) = delete;
~HTMLTreeBuilder();
void Trace(Visitor*) const;
@@ -207,6 +208,8 @@ class HTMLTreeBuilder final : public GarbageCollected<HTMLTreeBuilder> {
public:
FragmentParsingContext() = default;
+ FragmentParsingContext(const FragmentParsingContext&) = delete;
+ FragmentParsingContext& operator=(const FragmentParsingContext&) = delete;
void Init(DocumentFragment*, Element* context_element);
DocumentFragment* Fragment() const { return fragment_; }
@@ -224,8 +227,6 @@ class HTMLTreeBuilder final : public GarbageCollected<HTMLTreeBuilder> {
private:
Member<DocumentFragment> fragment_;
Member<HTMLStackItem> context_element_stack_item_;
-
- DISALLOW_COPY_AND_ASSIGN(FragmentParsingContext);
};
// https://html.spec.whatwg.org/C/#frameset-ok-flag
@@ -263,8 +264,6 @@ class HTMLTreeBuilder final : public GarbageCollected<HTMLTreeBuilder> {
TextPosition script_to_process_start_position_;
HTMLParserOptions options_;
-
- DISALLOW_COPY_AND_ASSIGN(HTMLTreeBuilder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h b/chromium/third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h
index c4e65fe3101..afebe8e75be 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h
@@ -28,7 +28,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_INPUT_STREAM_PREPROCESSOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_INPUT_STREAM_PREPROCESSOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/text/segmented_string.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -47,6 +46,8 @@ class InputStreamPreprocessor {
public:
explicit InputStreamPreprocessor(Tokenizer* tokenizer)
: tokenizer_(tokenizer) {}
+ InputStreamPreprocessor(const InputStreamPreprocessor&) = delete;
+ InputStreamPreprocessor& operator=(const InputStreamPreprocessor&) = delete;
// http://www.whatwg.org/specs/web-apps/current-work/#next-input-character
// Returns whether we succeeded in peeking at the next character.
@@ -166,8 +167,6 @@ class InputStreamPreprocessor {
Tokenizer* tokenizer_;
bool skip_next_new_line_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(InputStreamPreprocessor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/literal_buffer.h b/chromium/third_party/blink/renderer/core/html/parser/literal_buffer.h
index e0bad993d69..b63ea841651 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/literal_buffer.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/literal_buffer.h
@@ -10,7 +10,6 @@
#include <type_traits>
#include "base/bits.h"
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
@@ -81,7 +80,9 @@ class LiteralBuffer {
}
ALWAYS_INLINE const T* data() const { return begin_; }
- ALWAYS_INLINE size_t size() const { return end_ - begin_; }
+ ALWAYS_INLINE wtf_size_t size() const {
+ return base::checked_cast<wtf_size_t>(end_ - begin_);
+ }
ALWAYS_INLINE bool IsEmpty() const { return size() == 0; }
diff --git a/chromium/third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h b/chromium/third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h
index af380da0ccb..082d0886dba 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_NESTING_LEVEL_INCREMENTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_NESTING_LEVEL_INCREMENTER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -40,12 +39,13 @@ class NestingLevelIncrementer {
++(*nesting_level_);
}
+ NestingLevelIncrementer(const NestingLevelIncrementer&) = delete;
+ NestingLevelIncrementer& operator=(const NestingLevelIncrementer&) = delete;
+
~NestingLevelIncrementer() { --(*nesting_level_); }
private:
unsigned* nesting_level_;
-
- DISALLOW_COPY_AND_ASSIGN(NestingLevelIncrementer);
};
} // namespace blink
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 c24aeb0330f..cfc09d1f680 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
@@ -85,7 +85,7 @@ static int Find(const char* subject, int subject_length, const char* target) {
}
}
if (match)
- return i;
+ return static_cast<int>(i);
}
return -1;
}
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 98733157496..7c19e9ac49d 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
@@ -25,7 +25,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
@@ -59,6 +58,8 @@ class CORE_EXPORT TextResourceDecoder {
};
explicit TextResourceDecoder(const TextResourceDecoderOptions&);
+ TextResourceDecoder(const TextResourceDecoder&) = delete;
+ TextResourceDecoder& operator=(const TextResourceDecoder&) = delete;
~TextResourceDecoder();
void SetEncoding(const WTF::TextEncoding&, EncodingSource);
@@ -100,8 +101,6 @@ class CORE_EXPORT TextResourceDecoder {
bool detection_completed_;
std::unique_ptr<HTMLMetaCharsetParser> charset_parser_;
-
- DISALLOW_COPY_AND_ASSIGN(TextResourceDecoder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_builder.cc b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_builder.cc
index df3ca415b4f..58b0bd56bc5 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_builder.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_builder.cc
@@ -32,7 +32,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
diff --git a/chromium/third_party/blink/renderer/core/html/portal/OWNERS b/chromium/third_party/blink/renderer/core/html/portal/OWNERS
index 15decd27f75..4fee46cd5d7 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/OWNERS
+++ b/chromium/third_party/blink/renderer/core/html/portal/OWNERS
@@ -1,4 +1,3 @@
adithyas@chromium.org
jbroman@chromium.org
-lfg@chromium.org
mcnee@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.cc
index b554a4c9021..4a960e158fc 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -328,8 +328,9 @@ ScriptPromise HTMLPortalElement::activate(ScriptState* script_state,
ScriptPromiseResolver* resolver =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- portal->Activate(std::move(data), PortalActivationDelegate::ForPromise(
- resolver, exception_state));
+ portal->Activate(std::move(data),
+ PortalActivationDelegate::ForPromise(
+ resolver, exception_state.GetContext()));
return promise;
}
diff --git a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h
index f9262fd46a8..fcead59ff34 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h
+++ b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -8,7 +8,6 @@
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -172,6 +171,11 @@ struct DowncastTraits<HTMLPortalElement> {
return html_element->IsHTMLPortalElement();
return false;
}
+ static bool AllowFrom(const Element& element) {
+ if (const HTMLElement* html_element = DynamicTo<HTMLElement>(element))
+ return html_element->IsHTMLPortalElement();
+ return false;
+ }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.cc
index 0b1a9a72018..74a72dd3585 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.cc
@@ -20,19 +20,16 @@ class PromiseActivationDelegate
public PortalActivationDelegate {
public:
PromiseActivationDelegate(ScriptPromiseResolver* resolver,
- const ExceptionState& exception_state)
- : resolver_(resolver),
- context_(exception_state.Context()),
- interface_name_(exception_state.InterfaceName()),
- property_name_(exception_state.PropertyName()) {}
+ const ExceptionContext& exception_context)
+ : resolver_(resolver), exception_context_(exception_context) {}
void ActivationDidSucceed() final { resolver_->Resolve(); }
void ActivationDidFail(const String& message) final {
ScriptState* script_state = resolver_->GetScriptState();
ScriptState::Scope scope(script_state);
- ExceptionState exception_state(script_state->GetIsolate(), context_,
- interface_name_, property_name_);
+ ExceptionState exception_state(script_state->GetIsolate(),
+ exception_context_);
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
message);
resolver_->Reject(exception_state);
@@ -47,18 +44,16 @@ class PromiseActivationDelegate
// Needed to reconstruct ExceptionState. Ideally these would be bundled.
// See https://crbug.com/991544.
- ExceptionState::ContextType context_;
- const char* interface_name_;
- const char* property_name_;
+ ExceptionContext exception_context_;
};
} // namespace
PortalActivationDelegate* PortalActivationDelegate::ForPromise(
ScriptPromiseResolver* resolver,
- const ExceptionState& exception_state) {
+ const ExceptionContext& exception_context) {
return MakeGarbageCollected<PromiseActivationDelegate>(resolver,
- exception_state);
+ exception_context);
}
namespace {
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.h b/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.h
index eb6123c1240..98ff2e1ff22 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.h
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activation_delegate.h
@@ -15,16 +15,16 @@ class String;
namespace blink {
class ConsoleLogger;
-class ExceptionState;
+class ExceptionContext;
class ScriptPromiseResolver;
// Handles the result of portal activation, reporting it in a suitable way.
class PortalActivationDelegate : public GarbageCollectedMixin {
public:
// Creates a delegate which reports completion through promise resolution.
- // Copies the metadata from the supplied ExceptionState.
+ // Copies the metadata from the supplied ExceptionContext.
static PortalActivationDelegate* ForPromise(ScriptPromiseResolver*,
- const ExceptionState&);
+ const ExceptionContext&);
// Creates a delegate which logs errors to the console.
static PortalActivationDelegate* ForConsole(ConsoleLogger*);
diff --git a/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css b/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
deleted file mode 100644
index e09e7102cb2..00000000000
--- a/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ /dev/null
@@ -1,263 +0,0 @@
-/* Copyright 2019 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* These styles adjust the default styling for HTML elements as defined in
- * core/html/resources/html.css in order to provide an updated style when
- * using the refreshed controls UI.
- */
-
-/* This sheet is appended to html.css before parsing which means the selectors
- below are in the default html namespace:
-
- @namespace "http://www.w3.org/1999/xhtml"
-*/
-
-select,
-select:-internal-list-box,
-input,
-textarea {
- background-color: -internal-light-dark(#ffffff, #3B3B3B);
- border-color: -internal-light-dark(#767676, #858585);
-}
-
-a:-webkit-any-link:focus-visible {
- outline-offset: 1px;
-}
-
-input:focus-visible, textarea:focus-visible, select:focus-visible {
- outline-offset: 0;
-}
-
-input[type="checkbox" i]:focus-visible,
-input[type="radio" i]:focus-visible {
- outline-offset: 2px;
-}
-
-input,
-input[type="email" i],
-input[type="number" i],
-input[type="password" i],
-input[type="search" i],
-input[type="tel" i],
-input[type="text" i],
-input[type="url" i] {
- padding: 1px 2px;
-}
-
-input:disabled,
-select:disabled,
-textarea:disabled {
- border-color: rgba(118, 118, 118, 0.3);
-}
-
-input:disabled,
-textarea:disabled {
- background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
- color: -internal-light-dark(default, rgba(255, 255, 255, 0.6));
-}
-
-select:disabled {
- opacity: 0.7;
-}
-
-input[type="button" i],
-input[type="submit" i],
-input[type="reset" i],
-input[type="color" i],
-input[type="file" i]::-webkit-file-upload-button,
-button {
- background-color: -internal-light-dark(#efefef, #3B3B3B);
- border-color: -internal-light-dark(#767676, #858585);
- color: -internal-light-dark(black, white);
-}
-
-input[type="button" i]:disabled,
-input[type="submit" i]:disabled,
-input[type="reset" i]:disabled,
-input[type="color" i]:disabled,
-input[type="file" i]:disabled::-webkit-file-upload-button,
-button:disabled {
- background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(19, 1, 1, 0.3));
- border-color: -internal-light-dark(rgba(118, 118, 118, 0.3), rgba(195, 195, 195, 0.3));
- color: -internal-light-dark(rgba(16, 16, 16, 0.3), rgba(255, 255, 255, 0.3));
-}
-
-input[type="password" i]::-internal-reveal {
- width: 1.3em;
- height: 1.3em;
- cursor: default;
- flex: none;
- background-image: -webkit-image-set(url(images/password_reveal_on.svg) 1x);
- background-repeat: no-repeat;
- background-position: center;
- background-size: contain;
- margin-left: 3px;
- margin-right: 3px;
-}
-
-input[type="password" i]::-internal-reveal.reveal {
- background-image: -webkit-image-set(url(images/password_reveal_off.svg) 1x);
-}
-
-input[type="password" i]::-internal-reveal:hover,
-input[type="password" i]::-internal-reveal:focus {
- border-radius: 1px;
- cursor: pointer;
-}
-
-input[type="range" i] {
- color: -internal-light-dark(#101010, #ffffff);
-}
-
-input[type="range" i]:disabled {
- color: #c5c5c5;
-}
-
-meter::-webkit-meter-inner-element:-internal-shadow-host-has-appearance {
- display: grid;
- grid-template-rows: 1fr [line1] 2fr [line2] 1fr;
-}
-
-meter::-webkit-meter-bar {
- background: -internal-light-dark(#efefef, #3B3B3B);
- border-width: thin;
- grid-row-start: line1;
- grid-row-end: line2;
- border-style: solid;
- border-color: -internal-light-dark(rgba(118, 118, 118, 0.3), #858585);
- border-radius: 20px;
- box-sizing: border-box;
- overflow: hidden;
-}
-
-meter::-webkit-meter-optimum-value {
- background: -internal-light-dark(#107c10, #74b374)
-}
-
-meter::-webkit-meter-suboptimum-value {
- background: -internal-light-dark(#ffb900, #f2c812)
-}
-
-meter::-webkit-meter-even-less-good-value {
- background: -internal-light-dark(#d83b01, #e98f6d)
-}
-
-input[type="date" i]::-webkit-calendar-picker-indicator,
-input[type="datetime-local" i]::-webkit-calendar-picker-indicator,
-input[type="month" i]::-webkit-calendar-picker-indicator,
-input[type="week" i]::-webkit-calendar-picker-indicator {
- background-image: -internal-light-dark(-webkit-image-set(url(images/calendar_icon.svg) 1x), -webkit-image-set(url(images/calendar_icon_white.svg) 1x));
- background-origin: content-box;
- background-repeat: no-repeat;
- background-size: contain;
- height: 1.2em;
- margin-inline-start: 24px;
- opacity: 1;
- outline: none;
- padding-bottom: 2px;
- padding-inline-start: 3px;
- padding-inline-end: 3px;
- padding-top: 2px;
- width: 1.2em;
-}
-
-input[type="date" i]::-webkit-calendar-picker-indicator:focus-visible,
-input[type="datetime-local" i]::-webkit-calendar-picker-indicator:focus-visible,
-input[type="month" i]::-webkit-calendar-picker-indicator:focus-visible,
-input[type="week" i]::-webkit-calendar-picker-indicator:focus-visible {
- outline: solid 2px -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-
-input[type="time" i]::-webkit-calendar-picker-indicator {
- background-image: -internal-light-dark(-webkit-image-set(url(images/time_icon.svg) 1x), -webkit-image-set(url(images/time_icon_white.svg) 1x));
- background-origin: content-box;
- background-repeat: no-repeat;
- background-size: contain;
- height: 1.05em;
- margin-inline-start: 8px;
- opacity: 1;
- outline: none;
- padding-bottom: 3px;
- padding-inline-start: 3px;
- padding-inline-end: 3px;
- padding-top: 3px;
- width: 1.05em;
-}
-
-input[type="time" i]::-webkit-calendar-picker-indicator:focus-visible {
- outline: solid 2px -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-
-input::-webkit-calendar-picker-indicator:hover {
- background-color: initial;
-}
-
-/* -internal-list-box is how we specify select[multiple] */
-/* select[multiple] is an exception to the prohibition on sizes here
- because it is one of the few controls with borders that grow on zoom
- (to solve a nasty scrollbar location problem) */
-select:-internal-list-box {
- border-radius: 2px;
-}
-
-select:-internal-list-box option:hover {
- background-color: initial;
-}
-
-/* option selected, list-box not focused */
-select:-internal-list-box option:checked,
-select:-internal-list-box option:checked:hover {
- background-color: -internal-light-dark(#cecece, #545454) !important;
- color: -internal-light-dark(#101010, #FFFFFF) !important;
-}
-
-/* option selected, list-box focused */
-select:-internal-list-box:focus option:checked,
-select:-internal-list-box:focus option:checked:hover {
- /* TODO(crbug.com/1129658): The dark mode color here should be handled
- within LayoutTheme::ActiveListBoxSelectionBackgroundColor(). */
- background-color: -internal-light-dark(-internal-active-list-box-selection, #99C8FF) !important;
- color: -internal-light-dark(-internal-active-list-box-selection-text, #3B3B3B) !important;
-}
-
-select:-internal-list-box:focus option:checked:disabled {
- /* TODO(crbug.com/1129658): The dark mode color here should be handled
- within LayoutTheme::ActiveListBoxSelectionBackgroundColor(). */
- background-color: -internal-light-dark(-internal-inactive-list-box-selection, rgba(59, 59, 59, 0.3)) !important;
-}
-
-select:-internal-list-box:disabled option:checked,
-select:-internal-list-box option:checked:disabled,
-select:-internal-list-box option:checked:disabled:hover {
- color: -internal-light-dark(gray, #aaa) !important;
-}
-
-input::-webkit-datetime-edit-ampm-field:focus,
-input::-webkit-datetime-edit-day-field:focus,
-input::-webkit-datetime-edit-hour-field:focus,
-input::-webkit-datetime-edit-millisecond-field:focus,
-input::-webkit-datetime-edit-minute-field:focus,
-input::-webkit-datetime-edit-month-field:focus,
-input::-webkit-datetime-edit-second-field:focus,
-input::-webkit-datetime-edit-week-field:focus,
-input::-webkit-datetime-edit-year-field:focus {
- background-color: -internal-light-dark(highlight, #99C8FF);
- color: -internal-light-dark(highlighttext, #000000);
- outline: none;
-}
-
-input::-webkit-datetime-edit-year-field[disabled],
-input::-webkit-datetime-edit-month-field[disabled],
-input::-webkit-datetime-edit-week-field[disabled],
-input::-webkit-datetime-edit-day-field[disabled],
-input::-webkit-datetime-edit-ampm-field[disabled],
-input::-webkit-datetime-edit-hour-field[disabled],
-input::-webkit-datetime-edit-millisecond-field[disabled],
-input::-webkit-datetime-edit-minute-field[disabled],
-input::-webkit-datetime-edit-second-field[disabled] {
- color: -internal-light-dark(GrayText, #000000);
-}
diff --git a/chromium/third_party/blink/renderer/core/html/resources/html.css b/chromium/third_party/blink/renderer/core/html/resources/html.css
index 0e7e25a8bbd..5bc0aaf3278 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/html.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/html.css
@@ -27,31 +27,6 @@ html {
display: block;
}
-/* children of the <head> element all have display:none */
-head {
- display: none
-}
-
-meta {
- display: none
-}
-
-title {
- display: none
-}
-
-link {
- display: none
-}
-
-style {
- display: none
-}
-
-script {
- display: none
-}
-
/* generic block-level elements */
body {
@@ -445,17 +420,27 @@ input, textarea, select, button {
text-align: start;
}
-input[type="hidden" i] {
- display: none
+textarea {
+ appearance: auto;
+ border: 1px solid -internal-light-dark(#767676, #858585);
+ column-count: initial !important;
+ -webkit-rtl-ordering: logical;
+ resize: auto;
+ cursor: text;
+ padding: 2px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ background-color: -internal-light-dark(#ffffff, #3B3B3B);
+ font-family: monospace;
}
input {
appearance: auto;
- padding: 1px;
- background-color: -internal-light-dark(white, black);
- border: 2px inset;
+ padding:1px 0;
+ border: 2px inset -internal-light-dark(#767676, #858585);
-webkit-rtl-ordering: logical;
cursor: text;
+ background-color: -internal-light-dark(#ffffff, #3B3B3B);
}
input[type="search" i] {
@@ -495,6 +480,7 @@ input[type="search" i]::-webkit-search-cancel-button {
flex: none;
-webkit-user-modify: read-only !important;
margin-inline-start: 1px;
+ margin-right: 3px;
opacity: 0;
pointer-events: none;
user-select: none !important;
@@ -505,6 +491,21 @@ input[type="search" i]:enabled:read-write:-webkit-any(:focus,:hover)::-webkit-se
pointer-events: auto;
}
+input[type="search" i]::-webkit-search-results-decoration {
+ margin: auto 3px auto 2px;
+}
+
+input,
+input[type="email" i],
+input[type="number" i],
+input[type="password" i],
+input[type="search" i],
+input[type="tel" i],
+input[type="text" i],
+input[type="url" i] {
+ padding: 1px 2px;
+}
+
input::-webkit-inner-spin-button {
appearance: auto;
display: inline-block;
@@ -521,24 +522,6 @@ input:enabled:read-write:-webkit-any(:focus,:hover)::-webkit-inner-spin-button {
pointer-events: auto;
}
-select {
- border-radius: 5px;
-}
-
-textarea {
- appearance: auto;
- background-color: -internal-light-dark(white, black);
- border: 1px solid;
- column-count: initial !important;
- -webkit-rtl-ordering: logical;
- flex-direction: column;
- resize: auto;
- cursor: text;
- padding: 2px;
- white-space: pre-wrap;
- word-wrap: break-word;
-}
-
::-webkit-input-placeholder {
-webkit-text-security: none;
color: #757575;
@@ -574,6 +557,10 @@ textarea::-internal-input-suggested {
overflow-anchor: none;
}
+textarea::-internal-input-suggested {
+ font-family: monospace !important;
+}
+
input[type="password" i] {
-webkit-text-security: disc !important;
}
@@ -582,6 +569,29 @@ input[type="password" i]::-internal-input-suggested {
-webkit-text-security: disc !important;
}
+input[type="password" i]::-internal-reveal {
+ width: 1.3em;
+ height: 1.3em;
+ cursor: default;
+ flex: none;
+ background-image: -webkit-image-set(url(images/password_reveal_on.svg) 1x);
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
+ margin-left: 3px;
+ margin-right: 3px;
+}
+
+input[type="password" i]::-internal-reveal.reveal {
+ background-image: -webkit-image-set(url(images/password_reveal_off.svg) 1x);
+}
+
+input[type="password" i]::-internal-reveal:hover,
+input[type="password" i]::-internal-reveal:focus {
+ border-radius: 1px;
+ cursor: pointer;
+}
+
input[type="hidden" i], input[type="image" i], input[type="file" i] {
appearance: none;
padding: initial;
@@ -606,31 +616,30 @@ input[type="image" i] {
/* TODO(crbug.com/880258): Use different styles for
`-internal-autofill-previewed` and `-internal-autofill-selected`. */
input:-internal-autofill-previewed,
-textarea:-internal-autofill-previewed,
-select:-internal-autofill-previewed {
- appearance: menulist-button;
- background-color: #E8F0FE !important;
- background-image:none !important;
- color: -internal-light-dark(black, white) !important;
-}
-
input:-internal-autofill-selected,
+textarea:-internal-autofill-previewed,
textarea:-internal-autofill-selected,
+select:-internal-autofill-previewed,
select:-internal-autofill-selected {
appearance: menulist-button;
- background-color: #E8F0FE !important;
background-image:none !important;
+ background-color: -internal-light-dark(#E8F0FE, rgba(70,90,126,0.4)) !important;
color: -internal-light-dark(black, white) !important;
}
-input[type="radio" i], input[type="checkbox" i] {
- margin: 3px 0.5ex;
+input[type="radio" i],
+input[type="checkbox" i] {
+ margin:3px 3px 3px 4px;
padding: initial;
background-color: initial;
border: initial;
cursor: default;
}
+input[type="radio" i] {
+ margin:3px 3px 0 5px;
+}
+
input[type="button" i], input[type="submit" i], input[type="reset" i] {
-internal-empty-line-height: fabricated;
appearance: auto;
@@ -647,15 +656,28 @@ input[type="file" i]::-webkit-file-upload-button {
font-size: inherit;
}
-input[type="button" i], input[type="submit" i], input[type="reset" i], input[type="file" i]::-webkit-file-upload-button, button {
+input[type="button" i],
+input[type="submit" i],
+input[type="reset" i],
+input[type="file" i]::-webkit-file-upload-button,
+button {
align-items: flex-start;
text-align: center;
cursor: default;
- color: -internal-light-dark(ButtonText, #AAAAAA);
- padding: 2px 6px 3px 6px;
- border: 2px outset ButtonFace;
- background-color: ButtonFace;
- box-sizing: border-box
+ padding: 1px 6px;
+ border: 2px outset -internal-light-dark(#767676, #858585);
+ box-sizing: border-box;
+ background-color: -internal-light-dark(#efefef, #3B3B3B);
+ color: -internal-light-dark(black, white);
+}
+
+input[type="checkbox" i]:disabled,
+input[type="file" i]:disabled,
+input[type="hidden" i]:disabled,
+input[type="image" i]:disabled,
+input[type="radio" i]:disabled,
+input[type="range" i]:disabled {
+ background-color: initial;
}
input[type="range" i] {
@@ -663,11 +685,12 @@ input[type="range" i] {
padding: initial;
border: initial;
margin: 2px;
- color: #909090;
cursor: default;
+ color: -internal-light-dark(#101010, #ffffff);
}
-input[type="range" i]::-webkit-slider-container, input[type="range" i]::-webkit-media-slider-container {
+input[type="range" i]::-webkit-slider-container,
+input[type="range" i]::-webkit-media-slider-container {
appearance: inherit;
flex: 1;
min-inline-size: 0;
@@ -694,16 +717,32 @@ input[type="range" i]::-webkit-slider-runnable-track {
display: block;
}
-input[type="range" i]::-webkit-slider-thumb, input[type="range" i]::-webkit-media-slider-thumb {
+input[type="range" i]::-webkit-slider-thumb,
+input[type="range" i]::-webkit-media-slider-thumb {
appearance: auto;
box-sizing: border-box;
-webkit-user-modify: read-only !important;
display: block;
}
-input[type="button" i]:disabled, input[type="submit" i]:disabled, input[type="reset" i]:disabled,
-input[type="file" i]:disabled::-webkit-file-upload-button, button:disabled,
-select:disabled, optgroup:disabled, option:disabled,
+input[type="range" i]:disabled {
+ color: #c5c5c5;
+}
+
+input[type="button" i]:disabled,
+input[type="submit" i]:disabled,
+input[type="reset" i]:disabled,
+input[type="color" i]:disabled,
+input[type="file" i]:disabled::-webkit-file-upload-button,
+button:disabled {
+ background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(19, 1, 1, 0.3));
+ border-color: -internal-light-dark(rgba(118, 118, 118, 0.3), rgba(195, 195, 195, 0.3));
+ color: -internal-light-dark(rgba(16, 16, 16, 0.3), rgba(255, 255, 255, 0.3));
+}
+
+select:disabled,
+optgroup:disabled,
+option:disabled,
select[disabled]>option {
color: -internal-light-dark(GrayText, #aaa);
}
@@ -717,8 +756,15 @@ input[type="button" i]:active:disabled, input[type="submit" i]:active:disabled,
}
input:disabled, textarea:disabled {
- color: -internal-light-dark(#545454, #aaa);
cursor: default;
+ background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
+ color: -internal-light-dark(#545454, #aaaaaa);
+}
+
+input:disabled,
+select:disabled,
+textarea:disabled {
+ border-color: rgba(118, 118, 118, 0.3);
}
option:-internal-spatial-navigation-focus {
@@ -726,22 +772,23 @@ option:-internal-spatial-navigation-focus {
outline-offset: -1px;
}
-datalist {
- display: none
-}
-
+/* https://html.spec.whatwg.org/multipage/rendering.html#hidden-elements */
+/* TODO(crbug.com/1231263): <area> should be display:none. */
area {
- display: inline;
+ display: inline;
+}
+base, basefont, datalist, head, link, meta, noembed,
+noframes, param, rp, script, style, template, title {
+ display: none;
+}
+input[type="hidden" i] {
+ display: none !important;
}
area:-webkit-any-link {
cursor: pointer;
}
-param {
- display: none
-}
-
input[type="checkbox" i] {
appearance: auto;
box-sizing: border-box;
@@ -754,13 +801,15 @@ input[type="radio" i] {
input[type="color" i] {
appearance: auto;
- width: 44px;
- height: 23px;
- background-color: ButtonFace;
+ width: 50px;
+ height: 27px;
/* Same as native_theme_base. */
- border: 1px #a9a9a9 solid;
+ border: 1px solid -internal-light-dark(#767676, #858585);
padding: 1px 2px;
cursor: default;
+ box-sizing: border-box;
+ background-color: -internal-light-dark(#efefef, #3B3B3B);
+ color: -internal-light-dark(black, white);
}
input[type="color" i]::-webkit-color-swatch-wrapper {
@@ -782,8 +831,8 @@ input[type="color" i]::-webkit-color-swatch {
input[type="color" i][list] {
appearance: auto;
- width: 88px;
- height: 23px
+ width: 94px;
+ height: 27px
}
input[type="color" i][list]::-webkit-color-swatch-wrapper {
@@ -841,40 +890,35 @@ select {
appearance: auto;
box-sizing: border-box;
align-items: center;
- border: 1px solid;
white-space: pre;
-webkit-rtl-ordering: logical;
color: -internal-light-dark(black, white);
- background-color: -internal-light-dark(white, black);
+ background-color: -internal-light-dark(#ffffff, #3B3B3B);
+ border: 1px solid -internal-light-dark(#767676, #858585);
cursor: default;
+ border-radius: 0;
}
-select:not(:-internal-list-box) {
- overflow: visible !important;
+select:disabled {
+ opacity: 0.7;
}
+/* -internal-list-box is how we specify select[multiple] */
+/* select[multiple] is an exception to the prohibition on sizes here
+ because it is one of the few controls with borders that grow on zoom
+ (to solve a nasty scrollbar location problem) */
select:-internal-list-box {
appearance: auto;
align-items: flex-start;
- border: 1px inset gray;
- border-radius: initial;
overflow-x: hidden;
overflow-y: scroll;
vertical-align: text-bottom;
white-space: nowrap;
+ border-radius: 2px;
}
-optgroup {
- font-weight: bolder;
- display: block;
-}
-
-option {
- font-weight: normal;
- display: block;
- padding: 0 2px 1px 2px;
- white-space: nowrap;
- min-height: 1.2em;
+select:not(:-internal-list-box) {
+ overflow: visible !important;
}
select:-internal-list-box optgroup option:before {
@@ -886,23 +930,32 @@ select:-internal-list-box optgroup {
line-height: initial !important;
}
-select:-internal-list-box:focus option:checked {
- background-color: -internal-active-list-box-selection !important;
- color: -internal-active-list-box-selection-text !important;
+/* option selected, list-box focused */
+select:-internal-list-box:focus option:checked,
+select:-internal-list-box:focus option:checked:hover {
+ /* TODO(crbug.com/1129658): The dark mode color here should be handled
+ within LayoutTheme::ActiveListBoxSelectionBackgroundColor(). */
+ background-color: -internal-light-dark(-internal-active-list-box-selection, #99C8FF) !important;
+ color: -internal-light-dark(-internal-active-list-box-selection-text, #3B3B3B) !important;
}
select:-internal-list-box:focus option:checked:disabled {
- background-color: -internal-inactive-list-box-selection !important;
+ /* TODO(crbug.com/1129658): The dark mode color here should be handled
+ within LayoutTheme::ActiveListBoxSelectionBackgroundColor(). */
+ background-color: -internal-light-dark(-internal-inactive-list-box-selection, rgba(59, 59, 59, 0.3)) !important;
}
-select:-internal-list-box option:checked {
- background-color: -internal-inactive-list-box-selection !important;
- color: -internal-inactive-list-box-selection-text !important;
+/* option selected, list-box not focused */
+select:-internal-list-box option:checked,
+select:-internal-list-box option:checked:hover {
+ background-color: -internal-light-dark(#cecece, #545454) !important;
+ color: -internal-light-dark(#101010, #FFFFFF) !important;
}
select:-internal-list-box:disabled option:checked,
-select:-internal-list-box option:checked:disabled {
- color: gray !important;
+select:-internal-list-box option:checked:disabled,
+select:-internal-list-box option:checked:disabled:hover {
+ color: -internal-light-dark(gray, #aaa) !important;
}
select:-internal-list-box hr {
@@ -916,6 +969,23 @@ select:-internal-list-box:focus-visible option:-internal-multi-select-focus {
outline-offset: -1px;
}
+select:-internal-list-box option:hover {
+ background-color: initial;
+}
+
+optgroup {
+ font-weight: bolder;
+ display: block;
+}
+
+option {
+ font-weight: normal;
+ display: block;
+ padding: 0 2px 1px 2px;
+ white-space: nowrap;
+ min-height: 1.2em;
+}
+
/* selectmenu */
selectmenu {
@@ -959,7 +1029,9 @@ meter::-webkit-meter-inner-element {
}
meter::-webkit-meter-inner-element:-internal-shadow-host-has-appearance {
- display: block;
+ display: grid;
+ grid-template-rows: 1fr [line1] 2fr [line2] 1fr;
+ position: relative;
}
meter::-internal-fallback:-internal-shadow-host-has-appearance {
@@ -967,32 +1039,39 @@ meter::-internal-fallback:-internal-shadow-host-has-appearance {
}
meter::-webkit-meter-bar {
- background: linear-gradient(to bottom, #ddd, #eee 20%, #ccc 45%, #ccc 55%, #ddd);
height: 100%;
width: 100%;
-webkit-user-modify: read-only !important;
+ background: -internal-light-dark(#efefef, #3B3B3B);
+ border: thin solid -internal-light-dark(rgba(118, 118, 118, 0.3), #858585);
+ grid-row-start: line1;
+ grid-row-end: line2;
+ border-radius: 20px;
box-sizing: border-box;
+ align-self: unsafe center;
+ position: absolute;
+ overflow: hidden;
}
meter::-webkit-meter-optimum-value {
- background: linear-gradient(to bottom, #ad7, #cea 20%, #7a3 45%, #7a3 55%, #ad7);
height: 100%;
-webkit-user-modify: read-only !important;
box-sizing: border-box;
+ background: -internal-light-dark(#107c10, #74b374)
}
meter::-webkit-meter-suboptimum-value {
- background: linear-gradient(to bottom, #fe7, #ffc 20%, #db3 45%, #db3 55%, #fe7);
height: 100%;
-webkit-user-modify: read-only !important;
box-sizing: border-box;
+ background: -internal-light-dark(#ffb900, #f2c812)
}
meter::-webkit-meter-even-less-good-value {
- background: linear-gradient(to bottom, #f77, #fcc 20%, #d44 45%, #d44 55%, #f77);
height: 100%;
-webkit-user-modify: read-only !important;
box-sizing: border-box;
+ background: -internal-light-dark(#d83b01, #e98f6d)
}
/* progress */
@@ -1109,21 +1188,103 @@ embed:focus-visible, iframe:focus-visible, object:focus-visible {
}
input:focus-visible, textarea:focus-visible, select:focus-visible {
- outline-offset: -2px
+ outline-offset: 0;
}
input[type="button" i]:focus-visible,
-input[type="checkbox" i]:focus-visible,
input[type="file" i]:focus-visible,
input[type="hidden" i]:focus-visible,
input[type="image" i]:focus-visible,
-input[type="radio" i]:focus-visible,
input[type="reset" i]:focus-visible,
input[type="submit" i]:focus-visible,
input[type="file" i]:focus-visible::-webkit-file-upload-button {
outline-offset: 0
}
+input[type="checkbox" i]:focus-visible,
+input[type="radio" i]:focus-visible {
+ outline-offset: 2px;
+}
+
+
+input[type="date" i]::-webkit-calendar-picker-indicator,
+input[type="datetime-local" i]::-webkit-calendar-picker-indicator,
+input[type="month" i]::-webkit-calendar-picker-indicator,
+input[type="week" i]::-webkit-calendar-picker-indicator {
+ background-image: -internal-light-dark(-webkit-image-set(url(images/calendar_icon.svg) 1x), -webkit-image-set(url(images/calendar_icon_white.svg) 1x));
+ background-origin: content-box;
+ background-repeat: no-repeat;
+ background-size: contain;
+ height: 1.2em;
+ margin-inline-start: 24px;
+ opacity: 1;
+ outline: none;
+ padding-bottom: 2px;
+ padding-inline-start: 3px;
+ padding-inline-end: 3px;
+ padding-top: 2px;
+ width: 1.2em;
+}
+
+input[type="date" i]::-webkit-calendar-picker-indicator:focus-visible,
+input[type="datetime-local" i]::-webkit-calendar-picker-indicator:focus-visible,
+input[type="month" i]::-webkit-calendar-picker-indicator:focus-visible,
+input[type="week" i]::-webkit-calendar-picker-indicator:focus-visible {
+ outline: solid 2px -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+input[type="time" i]::-webkit-calendar-picker-indicator {
+ background-image: -internal-light-dark(-webkit-image-set(url(images/time_icon.svg) 1x), -webkit-image-set(url(images/time_icon_white.svg) 1x));
+ background-origin: content-box;
+ background-repeat: no-repeat;
+ background-size: contain;
+ height: 1.05em;
+ margin-inline-start: 8px;
+ opacity: 1;
+ outline: none;
+ padding-bottom: 3px;
+ padding-inline-start: 3px;
+ padding-inline-end: 3px;
+ padding-top: 3px;
+ width: 1.05em;
+}
+
+input[type="time" i]::-webkit-calendar-picker-indicator:focus-visible {
+ outline: solid 2px -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+input::-webkit-calendar-picker-indicator:hover {
+ background-color: initial;
+}
+
+input::-webkit-datetime-edit-ampm-field:focus,
+input::-webkit-datetime-edit-day-field:focus,
+input::-webkit-datetime-edit-hour-field:focus,
+input::-webkit-datetime-edit-millisecond-field:focus,
+input::-webkit-datetime-edit-minute-field:focus,
+input::-webkit-datetime-edit-month-field:focus,
+input::-webkit-datetime-edit-second-field:focus,
+input::-webkit-datetime-edit-week-field:focus,
+input::-webkit-datetime-edit-year-field:focus {
+ background-color: -internal-light-dark(highlight, #99C8FF);
+ color: -internal-light-dark(highlighttext, #000000);
+ outline: none;
+}
+
+input::-webkit-datetime-edit-year-field[disabled],
+input::-webkit-datetime-edit-month-field[disabled],
+input::-webkit-datetime-edit-week-field[disabled],
+input::-webkit-datetime-edit-day-field[disabled],
+input::-webkit-datetime-edit-ampm-field[disabled],
+input::-webkit-datetime-edit-hour-field[disabled],
+input::-webkit-datetime-edit-millisecond-field[disabled],
+input::-webkit-datetime-edit-minute-field[disabled],
+input::-webkit-datetime-edit-second-field[disabled] {
+ color: -internal-light-dark(GrayText, #000000);
+}
+
a:-webkit-any-link {
color: -webkit-link;
text-decoration: underline;
@@ -1138,6 +1299,10 @@ a:-webkit-any-link:read-write {
cursor: text;
}
+a:-webkit-any-link:focus-visible {
+ outline-offset: 1px;
+}
+
/* HTML5 ruby elements */
ruby, rt {
@@ -1155,16 +1320,8 @@ ruby > rt {
text-align: start;
}
-rp {
- display: none;
-}
-
/* other elements */
-noframes {
- display: none
-}
-
frameset, frame {
display: block
}
@@ -1204,10 +1361,6 @@ details[open] > summary:first-of-type {
list-style-type: disclosure-open;
}
-template {
- display: none
-}
-
bdi, output {
unicode-bidi: isolate;
}
diff --git a/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css b/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
index a42f7837204..e7d62ed3dea 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
@@ -56,32 +56,6 @@ input::-webkit-datetime-edit-year-field {
padding: 1px;
}
-/* Use highlight color. */
-input::-webkit-datetime-edit-ampm-field:focus,
-input::-webkit-datetime-edit-day-field:focus,
-input::-webkit-datetime-edit-hour-field:focus,
-input::-webkit-datetime-edit-millisecond-field:focus,
-input::-webkit-datetime-edit-minute-field:focus,
-input::-webkit-datetime-edit-month-field:focus,
-input::-webkit-datetime-edit-second-field:focus,
-input::-webkit-datetime-edit-week-field:focus,
-input::-webkit-datetime-edit-year-field:focus {
- background-color: highlight;
- color: highlighttext;
-}
-
-input::-webkit-datetime-edit-year-field[disabled],
-input::-webkit-datetime-edit-month-field[disabled],
-input::-webkit-datetime-edit-week-field[disabled],
-input::-webkit-datetime-edit-day-field[disabled],
-input::-webkit-datetime-edit-ampm-field[disabled],
-input::-webkit-datetime-edit-hour-field[disabled],
-input::-webkit-datetime-edit-millisecond-field[disabled],
-input::-webkit-datetime-edit-minute-field[disabled],
-input::-webkit-datetime-edit-second-field[disabled] {
- color: GrayText;
-}
-
/* If you update padding, border, or margin in the following ruleset, update
DateTimeEditElement::customStyelForRenderer too. */
input::-webkit-datetime-edit-text {
diff --git a/chromium/third_party/blink/renderer/core/html/resources/win.css b/chromium/third_party/blink/renderer/core/html/resources/win.css
deleted file mode 100644
index 8c9c1c3aa62..00000000000
--- a/chromium/third_party/blink/renderer/core/html/resources/win.css
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-/* These styles override the default styling for HTML elements as defined in
- core/html/resources/tml.css. So far we have used this file exclusively
- for making our form elements match Firefox's. */
-
-/* This sheet is appended to html.css before parsing which means the selectors
- below are in the default html namespace:
-
- @namespace "http://www.w3.org/1999/xhtml"
-*/
-
-/*
- * Update padding for all text-like types including unknown types.
- * Non-text types have input[type="foo" i] with padding properties in
- * html.css or input_multiple_fields.css.
- */
-input {
- padding:1px 0;
-}
-
-input[type="search" i] {
- padding:1px;
-}
-
-input[type="checkbox" i] {
- margin:3px 3px 3px 4px;
-}
-
-input[type="radio" i] {
- margin:3px 3px 0 5px;
-}
-
-input[type="range" i] {
- color: #c4c4c4;
-}
-
-/* Not sure this is the right color. #EBEBE4 is what Firefox uses. */
-textarea:disabled,
-input:disabled {
- background-color: -internal-light-dark(#ebebe4, #2d2d2d);
-}
-
-/* Cancel the above rule set for some input types. */
-input[type="button" i]:disabled,
-input[type="reset" i]:disabled,
-input[type="submit" i]:disabled {
- background-color: ButtonFace;
-}
-input[type="checkbox" i]:disabled,
-input[type="file" i]:disabled,
-input[type="hidden" i]:disabled,
-input[type="image" i]:disabled,
-input[type="radio" i]:disabled,
-input[type="range" i]:disabled {
- background-color: initial;
-}
-
-input[type="search" i]::-webkit-search-cancel-button {
- margin-right: 3px;
-}
-
-input[type="search" i]::-webkit-search-results-decoration {
- margin: auto 3px auto 2px;
-}
-
-input[type="button" i], input[type="submit" i], input[type="reset" i], input[type="file" i]::-webkit-file-upload-button, button {
- padding: 1px 6px;
-}
-
-/* Windows selects are not rounded. Custom borders for them shouldn't be either. */
-select {
- border-radius: 0;
- /* Same as native_theme_base. */
- border-color: #a9a9a9;
-}
-
-select:-internal-list-box {
- /* Same as native_theme_base. */
- border: 1px solid #a9a9a9;
-}
-
-textarea {
- font-family: monospace;
- /* Same as native_theme_base. */
- border-color: #a9a9a9;
-}
-
-textarea::-internal-input-suggested {
- font-family: monospace !important;
-}
diff --git a/chromium/third_party/blink/renderer/core/html/subresource_redirect_test.cc b/chromium/third_party/blink/renderer/core/html/subresource_redirect_test.cc
index 9b994366e44..1d012209b22 100644
--- a/chromium/third_party/blink/renderer/core/html/subresource_redirect_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/subresource_redirect_test.cc
@@ -86,7 +86,8 @@ class SubresourceRedirectSimTest
// Scroll down until the image is visible.
GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, 10000), mojom::blink::ScrollType::kProgrammatic);
- Compositor().BeginFrame();
+ if (Compositor().NeedsBeginFrame())
+ Compositor().BeginFrame();
test::RunPendingTasks();
image_resource.Complete(ReadTestImage());
}
@@ -304,6 +305,12 @@ class SubresourceRedirectCSPSimTest : public ::testing::WithParamInterface<
GetNetworkStateNotifier().SetSaveDataEnabled(true);
}
+ void SetUp() override {
+ SimTest::SetUp();
+ WebView().GetPage()->GetSettings().SetLitePageSubresourceRedirectOrigin(
+ "https://litepages.googlezip.net");
+ }
+
bool allow_csp_restricted_images() const { return GetParam(); }
void LoadMainResource(const String& html_body) {
diff --git a/chromium/third_party/blink/renderer/core/html/track/track_event.cc b/chromium/third_party/blink/renderer/core/html/track/track_event.cc
index fb1f252d2da..6e3c6b5d223 100644
--- a/chromium/third_party/blink/renderer/core/html/track/track_event.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/track_event.cc
@@ -28,7 +28,6 @@
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_track_event_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_audiotrack_texttrack_videotrack.h"
-#include "third_party/blink/renderer/bindings/core/v8/video_track_or_audio_track_or_text_track.h"
#include "third_party/blink/renderer/core/event_interface_names.h"
#include "third_party/blink/renderer/core/html/track/audio_track.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
@@ -41,18 +40,21 @@ TrackEvent::TrackEvent() = default;
TrackEvent::TrackEvent(const AtomicString& type,
const TrackEventInit* initializer)
: Event(type, initializer) {
- if (!initializer->hasTrack())
+ if (!(initializer->hasTrack() && initializer->track()))
return;
- const VideoTrackOrAudioTrackOrTextTrack& track = initializer->track();
- if (track.IsVideoTrack())
- track_ = track.GetAsVideoTrack();
- else if (track.IsAudioTrack())
- track_ = track.GetAsAudioTrack();
- else if (track.IsTextTrack())
- track_ = track.GetAsTextTrack();
- else
- NOTREACHED();
+ const V8UnionAudioTrackOrTextTrackOrVideoTrack* track = initializer->track();
+ switch (track->GetContentType()) {
+ case V8UnionAudioTrackOrTextTrackOrVideoTrack::ContentType::kAudioTrack:
+ track_ = track->GetAsAudioTrack();
+ break;
+ case V8UnionAudioTrackOrTextTrackOrVideoTrack::ContentType::kTextTrack:
+ track_ = track->GetAsTextTrack();
+ break;
+ case V8UnionAudioTrackOrTextTrackOrVideoTrack::ContentType::kVideoTrack:
+ track_ = track->GetAsVideoTrack();
+ break;
+ }
}
TrackEvent::~TrackEvent() = default;
@@ -61,7 +63,6 @@ const AtomicString& TrackEvent::InterfaceName() const {
return event_interface_names::kTrackEvent;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionAudioTrackOrTextTrackOrVideoTrack* TrackEvent::track() {
if (!track_)
return nullptr;
@@ -81,26 +82,6 @@ V8UnionAudioTrackOrTextTrackOrVideoTrack* TrackEvent::track() {
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void TrackEvent::track(VideoTrackOrAudioTrackOrTextTrack& return_value) {
- if (!track_)
- return;
-
- switch (track_->GetType()) {
- case WebMediaPlayer::kTextTrack:
- return_value.SetTextTrack(To<TextTrack>(track_.Get()));
- break;
- case WebMediaPlayer::kAudioTrack:
- return_value.SetAudioTrack(To<AudioTrack>(track_.Get()));
- break;
- case WebMediaPlayer::kVideoTrack:
- return_value.SetVideoTrack(To<VideoTrack>(track_.Get()));
- break;
- default:
- NOTREACHED();
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void TrackEvent::Trace(Visitor* visitor) const {
visitor->Trace(track_);
diff --git a/chromium/third_party/blink/renderer/core/html/track/track_event.h b/chromium/third_party/blink/renderer/core/html/track/track_event.h
index 69e7ae70507..272f6b3d28c 100644
--- a/chromium/third_party/blink/renderer/core/html/track/track_event.h
+++ b/chromium/third_party/blink/renderer/core/html/track/track_event.h
@@ -33,7 +33,6 @@ namespace blink {
class TrackEventInit;
class V8UnionAudioTrackOrTextTrackOrVideoTrack;
-class VideoTrackOrAudioTrackOrTextTrack;
class CORE_EXPORT TrackEvent final : public Event {
DEFINE_WRAPPERTYPEINFO();
@@ -58,11 +57,7 @@ class CORE_EXPORT TrackEvent final : public Event {
const AtomicString& InterfaceName() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionAudioTrackOrTextTrackOrVideoTrack* track();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void track(VideoTrackOrAudioTrackOrTextTrack&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader.h b/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader.h
index 6827e3ce49d..faee892d111 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader.h
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_BUFFERED_LINE_READER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_BUFFERED_LINE_READER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/text/segmented_string.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -50,6 +49,8 @@ class CORE_EXPORT BufferedLineReader {
public:
BufferedLineReader() : end_of_stream_(false), maybe_skip_lf_(false) {}
+ BufferedLineReader(const BufferedLineReader&) = delete;
+ BufferedLineReader& operator=(const BufferedLineReader&) = delete;
// Append data to the internal buffer.
void Append(const String& data) {
@@ -81,8 +82,6 @@ class CORE_EXPORT BufferedLineReader {
StringBuilder line_buffer_;
bool end_of_stream_;
bool maybe_skip_lf_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedLineReader);
};
} // namespace blink
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 9e06b5e2d4e..aefb9050c2d 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
@@ -30,7 +30,7 @@
#include "third_party/blink/renderer/core/html/track/vtt/buffered_line_reader.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 cbc075ffed8..ef7e216900f 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
@@ -29,8 +29,7 @@
#include "third_party/blink/renderer/core/html/track/vtt/vtt_cue.h"
-#include "base/stl_util.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_auto_keyword.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_autokeyword_double.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
@@ -74,13 +73,6 @@ static_assert(base::size(kDisplayAlignmentMap) == VTTCue::kNumberOfAlignments,
"displayAlignmentMap should have the same number of elements as "
"VTTCue::NumberOfAlignments");
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-static const String& AutoKeyword() {
- DEFINE_STATIC_LOCAL(const String, auto_string, ("auto"));
- return auto_string;
-}
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
static const String& StartKeyword() {
DEFINE_STATIC_LOCAL(const String, start, ("start"));
return start;
@@ -323,8 +315,6 @@ bool VTTCue::LineIsAuto() const {
return std::isnan(line_position_);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionAutoKeywordOrDouble* VTTCue::line() const {
if (LineIsAuto()) {
return MakeGarbageCollected<V8UnionAutoKeywordOrDouble>(
@@ -359,44 +349,10 @@ void VTTCue::setLine(const V8UnionAutoKeywordOrDouble* position) {
CueDidChange();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void VTTCue::line(DoubleOrAutoKeyword& result) const {
- if (LineIsAuto())
- result.SetAutoKeyword(AutoKeyword());
- else
- result.SetDouble(line_position_);
-}
-
-void VTTCue::setLine(const DoubleOrAutoKeyword& position) {
- // http://dev.w3.org/html5/webvtt/#dfn-vttcue-line
- // On setting, the WebVTT cue line must be set to the new value; if the new
- // value is the string "auto", then it must be interpreted as the special
- // value auto. ("auto" is translated to NaN.)
- double line_position;
- if (position.IsAutoKeyword()) {
- if (LineIsAuto())
- return;
- line_position = std::numeric_limits<double>::quiet_NaN();
- } else {
- DCHECK(position.IsDouble());
- line_position = position.GetAsDouble();
- if (line_position_ == line_position)
- return;
- }
- CueWillChange();
- line_position_ = line_position;
- CueDidChange();
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
bool VTTCue::TextPositionIsAuto() const {
return std::isnan(text_position_);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionAutoKeywordOrDouble* VTTCue::position() const {
if (TextPositionIsAuto()) {
return MakeGarbageCollected<V8UnionAutoKeywordOrDouble>(
@@ -435,43 +391,6 @@ void VTTCue::setPosition(const V8UnionAutoKeywordOrDouble* position,
CueDidChange();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void VTTCue::position(DoubleOrAutoKeyword& result) const {
- if (TextPositionIsAuto())
- result.SetAutoKeyword(AutoKeyword());
- else
- result.SetDouble(text_position_);
-}
-
-void VTTCue::setPosition(const DoubleOrAutoKeyword& position,
- ExceptionState& exception_state) {
- // http://dev.w3.org/html5/webvtt/#dfn-vttcue-position
- // On setting, if the new value is negative or greater than 100, then an
- // IndexSizeError exception must be thrown. Otherwise, the WebVTT cue
- // position must be set to the new value; if the new value is the string
- // "auto", then it must be interpreted as the special value auto.
- double text_position;
- if (position.IsAutoKeyword()) {
- if (TextPositionIsAuto())
- return;
- text_position = std::numeric_limits<double>::quiet_NaN();
- } else {
- DCHECK(position.IsDouble());
- if (IsInvalidPercentage(position.GetAsDouble(), exception_state))
- return;
- text_position = position.GetAsDouble();
- if (text_position_ == text_position)
- return;
- }
-
- CueWillChange();
- text_position_ = text_position;
- CueDidChange();
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void VTTCue::setSize(double size, ExceptionState& exception_state) {
// http://dev.w3.org/html5/webvtt/#dfn-vttcue-size
// On setting, if the new value is negative or greater than 100, then throw
@@ -1205,8 +1124,10 @@ void VTTCue::ParseSettings(const VTTRegionMap* region_map,
break;
}
case kRegionId:
- if (region_map)
- region_ = region_map->at(input.ExtractString(value_run));
+ if (region_map) {
+ auto it = region_map->find(input.ExtractString(value_run));
+ region_ = it != region_map->end() ? it->value : nullptr;
+ }
break;
case kNone:
break;
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h
index aefe50f7552..04cab19c06d 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h
@@ -38,7 +38,6 @@
namespace blink {
class Document;
-class DoubleOrAutoKeyword;
class ExecutionContext;
class V8UnionAutoKeywordOrDouble;
class VTTCue;
@@ -119,22 +118,12 @@ class CORE_EXPORT VTTCue final : public TextTrackCue {
bool snapToLines() const { return snap_to_lines_; }
void setSnapToLines(bool);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionAutoKeywordOrDouble* line() const;
void setLine(const V8UnionAutoKeywordOrDouble* position);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void line(DoubleOrAutoKeyword&) const;
- void setLine(const DoubleOrAutoKeyword&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionAutoKeywordOrDouble* position() const;
void setPosition(const V8UnionAutoKeywordOrDouble* position,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void position(DoubleOrAutoKeyword&) const;
- void setPosition(const DoubleOrAutoKeyword&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
double size() const { return cue_size_; }
void setSize(double, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h
index 1a548cad887..c0b4a8e28d3 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h
@@ -30,7 +30,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_VTT_SCANNER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_VTT_SCANNER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
@@ -54,6 +53,8 @@ class CORE_EXPORT VTTScanner {
public:
explicit VTTScanner(const String& line);
+ VTTScanner(const VTTScanner&) = delete;
+ VTTScanner& operator=(const VTTScanner&) = delete;
typedef const LChar* Position;
@@ -162,8 +163,6 @@ class CORE_EXPORT VTTScanner {
const UChar* characters16;
} end_;
bool is_8bit_;
-
- DISALLOW_COPY_AND_ASSIGN(VTTScanner);
};
inline wtf_size_t VTTScanner::Run::length() const {
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_tokenizer.h b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_tokenizer.h
index e10ae68710c..0b12beb7f84 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_tokenizer.h
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_tokenizer.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_VTT_TOKENIZER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_VTT_TOKENIZER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_token.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -43,6 +42,8 @@ class VTTTokenizer {
public:
explicit VTTTokenizer(const String& input);
+ VTTTokenizer(const VTTTokenizer&) = delete;
+ VTTTokenizer& operator=(const VTTTokenizer&) = delete;
bool NextToken(VTTToken&);
@@ -53,8 +54,6 @@ class VTTTokenizer {
// ://www.whatwg.org/specs/web-apps/current-work/#preprocessing-the-input-stream
InputStreamPreprocessor<VTTTokenizer> input_stream_preprocessor_;
-
- DISALLOW_COPY_AND_ASSIGN(VTTTokenizer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc
index 1b6241bcf28..986aede0515 100644
--- a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc
+++ b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc
@@ -110,7 +110,7 @@ network::mojom::blink::TrustTokenParamsPtr TrustTokenParamsFromJson(
// Because of the characteristics of the Trust Tokens protocol, we expect
// under 5 elements in this array.
- for (size_t i = 0; i < issuers_array->size(); ++i) {
+ for (wtf_size_t i = 0; i < issuers_array->size(); ++i) {
String str_issuer;
if (!issuers_array->at(i)->AsString(&str_issuer))
return nullptr;
@@ -136,7 +136,7 @@ network::mojom::blink::TrustTokenParamsPtr TrustTokenParamsFromJson(
// Because of the characteristics of the Trust Tokens protocol, we expect
// roughly 2-5 elements in this array.
- for (size_t i = 0; i < signed_headers_array->size(); ++i) {
+ for (wtf_size_t i = 0; i < signed_headers_array->size(); ++i) {
String next;
if (!signed_headers_array->at(i)->AsString(&next))
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h
index 981fc4fcc8e..41b65ed6ae8 100644
--- a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h
+++ b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h
@@ -8,7 +8,6 @@
#include <memory>
#include "services/network/public/mojom/trust_tokens.mojom-blink-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing_test.cc b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing_test.cc
index d8bfdfa63ea..55901cc1a29 100644
--- a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing_test.cc
@@ -88,7 +88,7 @@ TEST_P(TrustTokenAttributeParsingSuccess, Roundtrip) {
expectation->include_timestamp_header);
EXPECT_EQ(result->issuers.size(), expectation->issuers.size());
- for (size_t i = 0; i < result->issuers.size(); ++i) {
+ for (wtf_size_t i = 0; i < result->issuers.size(); ++i) {
EXPECT_EQ(!!result->issuers.at(i), !!expectation->issuers.at(i));
if (result->issuers.at(i)) {
EXPECT_EQ(result->issuers.at(i)->ToString(),
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 72b420153ac..d5b5f0ac2fa 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
@@ -131,13 +132,13 @@ ImageBitmap::ParsedOptions ParseOptions(const ImageBitmapOptions* options,
parsed_options.should_scale_input = true;
if (options->resizeQuality() == kImageBitmapOptionResizeQualityHigh)
- parsed_options.resize_quality = kHigh_SkFilterQuality;
+ parsed_options.resize_quality = cc::PaintFlags::FilterQuality::kHigh;
else if (options->resizeQuality() == kImageBitmapOptionResizeQualityMedium)
- parsed_options.resize_quality = kMedium_SkFilterQuality;
+ parsed_options.resize_quality = cc::PaintFlags::FilterQuality::kMedium;
else if (options->resizeQuality() == kImageBitmapOptionResizeQualityPixelated)
- parsed_options.resize_quality = kNone_SkFilterQuality;
+ parsed_options.resize_quality = cc::PaintFlags::FilterQuality::kNone;
else
- parsed_options.resize_quality = kLow_SkFilterQuality;
+ parsed_options.resize_quality = cc::PaintFlags::FilterQuality::kLow;
return parsed_options;
}
@@ -218,7 +219,8 @@ std::unique_ptr<CanvasResourceProvider> CreateProvider(
bool fallback_to_software) {
IntSize size(info.width(), info.height());
- const SkFilterQuality filter_quality = kLow_SkFilterQuality;
+ const cc::PaintFlags::FilterQuality filter_quality =
+ cc::PaintFlags::FilterQuality::kLow;
const CanvasResourceParams resource_params(info);
if (context_provider) {
@@ -300,56 +302,6 @@ scoped_refptr<StaticBitmapImage> FlipImageVertically(
return resource_provider->Snapshot(input->CurrentFrameOrientation());
}
-scoped_refptr<StaticBitmapImage> GetImageWithAlphaDisposition(
- scoped_refptr<StaticBitmapImage>&& image,
- AlphaDisposition alpha_disposition) {
- DCHECK(alpha_disposition != kDontChangeAlpha);
- if (alpha_disposition == kDontChangeAlpha)
- return std::move(image);
- SkAlphaType alpha_type = (alpha_disposition == kPremultiplyAlpha)
- ? kPremul_SkAlphaType
- : kUnpremul_SkAlphaType;
- PaintImage paint_image = image->PaintImageForCurrentFrame();
- if (!paint_image)
- return nullptr;
- if (paint_image.GetAlphaType() == alpha_type)
- return std::move(image);
-
- SkImageInfo info = GetSkImageInfo(image.get()).makeAlphaType(alpha_type);
- // To premul, draw the unpremul image on a surface to avoid GPU read back if
- // image is texture backed.
- if (alpha_type == kPremul_SkAlphaType) {
- auto resource_provider = CreateProvider(
- image->IsTextureBacked() ? image->ContextProviderWrapper() : nullptr,
- info, image, true /* fallback_to_software */);
- if (!resource_provider)
- return nullptr;
-
- cc::PaintFlags paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- resource_provider->Canvas()->drawImage(image->PaintImageForCurrentFrame(),
- 0, 0, SkSamplingOptions(), &paint);
- return resource_provider->Snapshot(image->CurrentFrameOrientation());
- }
-
- // To unpremul, read back the pixels.
-
- if (paint_image.GetSkImageInfo().isEmpty())
- return nullptr;
-
- sk_sp<SkData> dst_pixels = TryAllocateSkData(info.computeMinByteSize());
- if (!dst_pixels)
- return nullptr;
-
- uint8_t* writable_pixels = static_cast<uint8_t*>(dst_pixels->writable_data());
- size_t image_row_bytes = static_cast<size_t>(info.minRowBytes64());
- bool read_successful =
- paint_image.readPixels(info, writable_pixels, image_row_bytes, 0, 0);
- DCHECK(read_successful);
- return StaticBitmapImage::Create(std::move(dst_pixels), info,
- image->CurrentFrameOrientation());
-}
-
scoped_refptr<StaticBitmapImage> ScaleImage(
scoped_refptr<StaticBitmapImage>&& image,
const ImageBitmap::ParsedOptions& parsed_options) {
@@ -473,7 +425,7 @@ static scoped_refptr<StaticBitmapImage> CropImageAndApplyColorSpaceConversion(
scoped_refptr<StaticBitmapImage>&& image,
ImageBitmap::ParsedOptions& parsed_options) {
DCHECK(image);
- DCHECK(!image->Data());
+ DCHECK(!image->HasData());
IntRect img_rect(IntPoint(), IntSize(image->width(), image->height()));
const IntRect& src_rect{parsed_options.crop_rect};
@@ -585,7 +537,7 @@ ImageBitmap::ImageBitmap(ImageElementBase* image,
DCHECK(!paint_image.IsTextureBacked());
if (input->IsBitmapImage()) {
// A BitmapImage indicates that this is a coded backed image.
- if (!input->Data())
+ if (!input->HasData())
return;
DCHECK(paint_image.IsLazyGenerated());
@@ -992,13 +944,14 @@ ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
canvas->translate(0, draw_dst_rect.Height());
canvas->scale(1, -1);
}
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
SVGImageForContainer::Create(To<SVGImage>(input.get()),
FloatSize(input_rect.Size()), 1, NullURL())
->Draw(canvas, cc::PaintFlags(), FloatRect(draw_dst_rect),
- FloatRect(draw_src_rect), SkSamplingOptions(),
+ FloatRect(draw_src_rect), draw_options,
// The following will all be ignored.
- kRespectImageOrientation, Image::kDoNotClampImageToSourceRect,
- Image::kSyncDecode);
+ Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
sk_sp<PaintRecord> paint_record = recorder.finishRecordingAsPicture();
std::unique_ptr<ParsedOptions> passed_parsed_options =
@@ -1076,15 +1029,16 @@ ScriptPromise ImageBitmap::CreateImageBitmap(ScriptState* script_state,
scoped_refptr<Image> ImageBitmap::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize&) {
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition) {
*status = kNormalSourceImageStatus;
if (!image_)
return nullptr;
- if (image_->IsPremultiplied())
- return image_;
- // Skia does not support drawing unpremul SkImage on SkCanvas.
- // Premultiply and return.
- return GetImageWithAlphaDisposition(std::move(image_), kPremultiplyAlpha);
+
+ scoped_refptr<StaticBitmapImage> image = image_;
+
+ // If the alpha_disposition is already correct, this is a no-op.
+ return GetImageWithAlphaDisposition(std::move(image), alpha_disposition);
}
FloatSize ImageBitmap::ElementSize(
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 7263d77aba8..74e14eb7f29 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -88,7 +88,7 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
unsigned height() const;
IntSize Size() const;
- bool IsNeutered() const { return is_neutered_; }
+ bool IsNeutered() const override { return is_neutered_; }
bool OriginClean() const { return image_->OriginClean(); }
bool IsPremultiplied() const { return image_->IsPremultiplied(); }
scoped_refptr<StaticBitmapImage> Transfer();
@@ -97,8 +97,10 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
~ImageBitmap() override;
// CanvasImageSource implementation
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) override;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) override;
bool WouldTaintOrigin() const override { return !image_->OriginClean(); }
FloatSize ElementSize(const FloatSize&,
const RespectImageOrientationEnum) const override;
@@ -121,7 +123,8 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
unsigned resize_width = 0;
unsigned resize_height = 0;
IntRect crop_rect;
- SkFilterQuality resize_quality = kLow_SkFilterQuality;
+ cc::PaintFlags::FilterQuality resize_quality =
+ cc::PaintFlags::FilterQuality::kLow;
};
private:
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 47184d7512a..8e83e336742 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
@@ -255,7 +255,7 @@ TEST_F(ImageBitmapTest, AvoidGPUReadback) {
SharedGpuContext::ContextProviderWrapper();
CanvasResourceParams resource_params;
auto resource_provider = CanvasResourceProvider::CreateSharedImageProvider(
- IntSize(100, 100), kLow_SkFilterQuality, resource_params,
+ IntSize(100, 100), cc::PaintFlags::FilterQuality::kLow, resource_params,
CanvasResourceProvider::ShouldInitialize::kNo, context_provider_wrapper,
RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
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 379e1f2353b..813efb301f0 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.cc
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.cc
@@ -765,8 +765,10 @@ WebInputEventResult EventHandler::HandlePointerEvent(
const WebPointerEvent& web_pointer_event,
const Vector<WebPointerEvent>& coalesced_events,
const Vector<WebPointerEvent>& predicted_events) {
- return pointer_event_manager_->HandlePointerEvent(
+ WebInputEventResult event_result = pointer_event_manager_->HandlePointerEvent(
web_pointer_event, coalesced_events, predicted_events);
+ gesture_manager_->NotifyPointerEventHandled(web_pointer_event);
+ return event_result;
}
WebInputEventResult EventHandler::HandleMousePressEvent(
@@ -1004,6 +1006,12 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
mouse_event_manager_->ClearDragHeuristicState();
capturing_mouse_events_element_ = nullptr;
ReleaseMouseCaptureFromLocalRoot();
+
+ // If the scrollbar still thinks it's being dragged, tell it to stop.
+ // Can happen on Win if we lose focus (e.g. from Alt-Tab) mid-drag.
+ if (last_scrollbar_under_mouse_ &&
+ last_scrollbar_under_mouse_->PressedPart() != ScrollbarPart::kNoPart)
+ last_scrollbar_under_mouse_->MouseUp(mouse_event);
}
if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled()) {
@@ -1485,18 +1493,9 @@ void EventHandler::ReleasePointerCapture(PointerId pointer_id,
// approach for removing mouse subframe capture. It must be re-write
// before enable the flag.
if (RuntimeEnabledFeatures::MouseSubframeNoImplicitCaptureEnabled()) {
- LocalFrame* frame = frame_;
LocalFrame* parent = DynamicTo<LocalFrame>(frame_->Tree().Parent());
while (parent) {
- Element* subframe_element = nullptr;
- if (frame->OwnerLayoutObject() &&
- frame->OwnerLayoutObject()->GetNode()) {
- subframe_element =
- DynamicTo<Element>(frame->OwnerLayoutObject()->GetNode());
- }
-
parent->GetEventHandler().capturing_subframe_element_ = nullptr;
- frame = parent;
parent = DynamicTo<LocalFrame>(parent->Tree().Parent());
}
}
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 5ec4ca907b0..7dc0bacc600 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
@@ -14,6 +14,7 @@
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/range.h"
@@ -974,6 +975,25 @@ TEST_F(EventHandlerTest, MisspellingContextMenuEvent) {
ASSERT_TRUE(Selection().IsHandleVisible());
}
+// Tests that touch adjustment algorithm can handle editable elements without
+// layout objects.
+//
+// TODO(mustaq): A fix for https://crbug.com/1230045 can make this test
+// obsolete.
+TEST_F(EventHandlerTest, TouchAdjustmentOnEditableDisplayContents) {
+ SetHtmlInnerHTML(
+ "<div style='display:contents' contenteditable='true'>TEXT</div>");
+ TapEventBuilder single_tap_event(FloatPoint(1, 1), 1);
+ GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
+ single_tap_event);
+
+ LongPressEventBuilder long_press_event(FloatPoint(1, 1));
+ GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
+ long_press_event);
+
+ // This test passes if it doesn't crash.
+}
+
TEST_F(EventHandlerTest, dragEndInNewDrag) {
SetHtmlInnerHTML(
"<style>.box { width: 100px; height: 100px; display: block; }</style>"
@@ -1142,8 +1162,11 @@ TEST_F(EventHandlerTooltipTest, mouseLeaveClearsTooltip) {
#endif
TEST_F(EventHandlerTooltipTest, MAYBE_FocusSetFromKeyboardUpdatesTooltip) {
SetHtmlInnerHTML(
- "<button id='b1' title='my tooltip 1'>button 1</button><button id='b2' "
- "title='my tooltip 2' accessKey='a'>button 2</button>");
+ R"HTML(
+ <button id='b1' title='my tooltip 1'>button 1</button>
+ <button id='b2'>button 2</button>
+ <button id='b3' title='my tooltip 3' accessKey='a'>button 3</button>
+ )HTML");
EXPECT_EQ(WTF::String(), LastToolTipText());
EXPECT_EQ(gfx::Rect(), LastToolTipBounds());
@@ -1160,6 +1183,14 @@ TEST_F(EventHandlerTooltipTest, MAYBE_FocusSetFromKeyboardUpdatesTooltip) {
Element* element = GetDocument().getElementById("b1");
EXPECT_EQ("my tooltip 1", LastToolTipText());
EXPECT_EQ(element->BoundsInViewport(), LastToolTipBounds());
+
+ // Doing the same but for a button that doesn't have a tooltip text should
+ // still trigger a tooltip update. The browser-side TooltipController will
+ // handle this case.
+ GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
+ element = GetDocument().getElementById("b2");
+ EXPECT_TRUE(LastToolTipText().IsNull());
+ EXPECT_EQ(element->BoundsInViewport(), LastToolTipBounds());
}
ResetTooltip();
@@ -1172,8 +1203,8 @@ TEST_F(EventHandlerTooltipTest, MAYBE_FocusSetFromKeyboardUpdatesTooltip) {
e.unmodified_text[0] = 'a';
GetDocument().GetFrame()->GetEventHandler().HandleAccessKey(e);
- Element* element = GetDocument().getElementById("b2");
- EXPECT_EQ("my tooltip 2", LastToolTipText());
+ Element* element = GetDocument().getElementById("b3");
+ EXPECT_EQ("my tooltip 3", LastToolTipText());
EXPECT_EQ(element->BoundsInViewport(), LastToolTipBounds());
}
@@ -1208,10 +1239,10 @@ TEST_F(EventHandlerTooltipTest, MAYBE_FocusSetFromKeyboardUpdatesTooltip) {
ResetTooltip();
- // 5. Setting the focus to an element with a script action (FocusType::kNone
+ // 5. Moving the focus to an element with a script action (FocusType::kNone
// means that the focus was set from a script) shouldn't update the tooltip.
{
- Element* element = GetDocument().getElementById("b2");
+ Element* element = GetDocument().getElementById("b3");
element->focus();
EXPECT_EQ("", LastToolTipText());
@@ -1811,7 +1842,7 @@ TEST_F(EventHandlerSimTest, TestUpdateHoverAfterCompositorScrollAtBeginFrame) {
// Do a compositor scroll and set |hover_needs_update_at_scroll_end| to be
// true in WebViewImpl.
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewport()->DidScroll(FloatPoint(0, 500));
+ frame_view->LayoutViewport()->DidCompositorScroll(FloatPoint(0, 500));
WebView().MainFrameWidget()->ApplyViewportChangesForTesting(
{gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, false, 0, 0,
cc::BrowserControlsState::kBoth, true});
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 84ee89cffd0..3cca8dcede5 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/input/event_handling_util.h"
#include "third_party/blink/public/common/input/web_mouse_event.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/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
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 62856d5838b..fb6b2c13fe1 100644
--- a/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -5,12 +5,16 @@
#include "third_party/blink/renderer/core/input/gesture_manager.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/input/web_pointer_event.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/public/public_buildflags.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/editing/selection_controller.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/events/gesture_event.h"
+#include "third_party/blink/renderer/core/events/pointer_event_factory.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"
@@ -25,6 +29,7 @@
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
+#include "third_party/blink/renderer/platform/wtf/deque.h"
#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
@@ -110,6 +115,16 @@ WebInputEventResult GestureManager::HandleGestureEventInFrame(
const GestureEventWithHitTestResults& targeted_event) {
DCHECK(!targeted_event.Event().IsScrollEvent());
+ // Remove all tap down touch id, pointer id pairs that have a
+ // lower touch id than the targeted event's primary_unique_touch_event_id
+ // because all gesture sequences prior to the current one have been already
+ // handled.
+ while (!recent_pointerdown_pointer_ids_.empty() &&
+ recent_pointerdown_pointer_ids_.front().first <
+ targeted_event.Event().primary_unique_touch_event_id) {
+ recent_pointerdown_pointer_ids_.pop_front();
+ }
+
Node* event_target = targeted_event.GetHitTestResult().InnerNode();
const WebGestureEvent& gesture_event = targeted_event.Event();
@@ -302,10 +317,23 @@ WebInputEventResult GestureManager::HandleGestureTap(
Node* click_target_node = current_hit_test.InnerNode()->CommonAncestor(
*tapped_element, event_handling_util::ParentForClickEvent);
auto* click_target_element = DynamicTo<Element>(click_target_node);
-
- // TODO(crbug.com/1206108): Find a better approach to associate
- // pointerdown pointerId with gesture tap
- fake_mouse_up.id = last_pointerdown_event_pointer_id_;
+ // When tests send GestureTap directly (e.g. from eventSender) there is no
+ // primary_unique_touch_event_id populated.
+ if (gesture_event.primary_unique_touch_event_id != 0) {
+ // If everything works correctly, the first touch id, pointer id pair
+ // in the deque is the one we are interested in.
+ if (!recent_pointerdown_pointer_ids_.empty()) {
+ if (gesture_event.primary_unique_touch_event_id ==
+ recent_pointerdown_pointer_ids_.front().first) {
+ fake_mouse_up.id = recent_pointerdown_pointer_ids_.front().second;
+ } else {
+ // Getting here means either we saw no pointerdown for the gesture,
+ // or that the gestures were not generated in order resulting in
+ // prematurely clearing pointerdown id in HandleGestureEventInFrame.
+ NOTREACHED();
+ }
+ }
+ }
fake_mouse_up.pointer_type = gesture_event.primary_pointer_type;
click_event_result =
mouse_event_manager_->SetMousePositionAndDispatchMouseEvent(
@@ -328,8 +356,11 @@ WebInputEventResult GestureManager::HandleGestureTap(
click_event_result);
if (RuntimeEnabledFeatures::TextFragmentTapOpensContextMenuEnabled() &&
- TextFragmentHandler::IsOverTextFragment(current_hit_test)) {
- if (event_result == WebInputEventResult::kNotHandled) {
+ current_hit_test.InnerNodeFrame()) {
+ current_hit_test.InnerNodeFrame()->View()->UpdateLifecycleToPrePaintClean(
+ DocumentUpdateReason::kHitTest);
+ if (TextFragmentHandler::IsOverTextFragment(current_hit_test) &&
+ event_result == WebInputEventResult::kNotHandled) {
return SendContextMenuEventForGesture(targeted_event);
}
}
@@ -540,18 +571,25 @@ void GestureManager::ShowUnhandledTapUIIfNeeded(
#endif // BUILDFLAG(ENABLE_UNHANDLED_TAP)
}
-void GestureManager::NotifyCurrentPointerDownId(PointerId pointer_id) {
- // TODO(crbug.com/1206108): Find a better approach to associate
- // pointerdown pointerId with gesture tap
- // Pointerdown, pointerup events and tapdown and tap gestures are not fully
- // ordered. It is guaranteed that tapdown follows pointerdown and tap
- // follows pointerup. However, because pointer events and gestures are
- // asynchronous, we can have the situation in which 2
- // pointerdown/pointerup pairs are executed before any of their
- // corresponding tapdown/tap pairs are executed.
- // In that case, we would use the pointerId of pointerdown/pointerup set 2
- // for the tapdown/tap pair of set 1. Which is wrong.
- last_pointerdown_event_pointer_id_ = pointer_id;
+void GestureManager::NotifyPointerEventHandled(
+ const WebPointerEvent& web_pointer_event) {
+ if (web_pointer_event.GetType() != WebInputEvent::Type::kPointerDown)
+ return;
+ PointerId pointer_id =
+ pointer_event_manager_->GetPointerEventId(web_pointer_event);
+ if (web_pointer_event.unique_touch_event_id == 0 ||
+ pointer_id == PointerEventFactory::kInvalidId)
+ return;
+
+ if (!recent_pointerdown_pointer_ids_.empty()) {
+ // Pointerdown events should occur in order of their unique_touch_event_ids.
+ DCHECK_LT(recent_pointerdown_pointer_ids_.back().first,
+ web_pointer_event.unique_touch_event_id);
+ }
+ // Associate unique_touch_event_id for pointerdown with pointer_id of the
+ // pointerdown event.
+ recent_pointerdown_pointer_ids_.push_back<TouchIdPointerId>(
+ {web_pointer_event.unique_touch_event_id, pointer_id});
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/input/gesture_manager.h b/chromium/third_party/blink/renderer/core/input/gesture_manager.h
index 87874be9871..523b2b0e80d 100644
--- a/chromium/third_party/blink/renderer/core/input/gesture_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/gesture_manager.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/hit_test_request.h"
#include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
+#include "third_party/blink/renderer/platform/wtf/deque.h"
namespace blink {
@@ -19,6 +20,7 @@ class ScrollManager;
class SelectionController;
class PointerEventManager;
class MouseEventManager;
+class WebPointerEvent;
// This class takes care of gestures and delegating the action based on the
// gesture to the responsible class.
@@ -55,12 +57,11 @@ class CORE_EXPORT GestureManager final
// position.
void SendContextMenuEventTouchDragEnd(const WebMouseEvent&);
- // Used by PointerEventManager to notify GestureManager when a pointerdown
- // pointerevent is dispatched. GestureManager is interested in knowing
- // the pointerId of pointerdown event because it uses this pointer id
- // to populate the pointerId for click and auxclick pointer events it
- // generates.
- void NotifyCurrentPointerDownId(PointerId pointer_id);
+ // Gesture Manager receives notification when Pointer Events are dispatched.
+ // GestureManager is interested in knowing the pointerId of pointerdown
+ // event because it uses this pointer id to populate the pointerId for
+ // click and auxclick pointer events it generates.
+ void NotifyPointerEventHandled(const WebPointerEvent& web_pointer_event);
private:
WebInputEventResult HandleGestureShowPress();
@@ -101,9 +102,15 @@ class CORE_EXPORT GestureManager final
gfx::PointF long_press_position_in_root_frame_;
- // The pointerId remapped by PointerEventFactory for the pointer event
- // stream that generated the last pointerdown event
- PointerId last_pointerdown_event_pointer_id_;
+ // Pair of the unique_touch_id for the first gesture in the sequence and
+ // the pointerId associated.
+ using TouchIdPointerId = std::pair<uint32_t, PointerId>;
+ // The mapping between unique_touch_event_id for tap down and pointer Id
+ // for pointerdown. We will keep the pointerId for a pointerevents sequence
+ // until we know that the pointerevents will not turn into gestures anymore.
+ // We will not keep track of the mapping for unique_touch_event_id = 0
+ // (unknown id) which will be the case for mouse pointer events for example.
+ Deque<TouchIdPointerId> recent_pointerdown_pointer_ids_;
const Member<SelectionController> selection_controller_;
};
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 692b26ce48a..426b11135d4 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
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/core/input/mouse_event_manager.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_drag_event_init.h"
@@ -47,8 +48,10 @@
#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/core/timing/event_timing.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -294,8 +297,9 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
mouse_event_type == event_type_names::kClick ||
mouse_event_type == event_type_names::kAuxclick);
- if (target && target->ToNode() &&
- (!check_for_listener || target->HasEventListeners(mouse_event_type))) {
+ WebInputEventResult input_event_result = WebInputEventResult::kNotHandled;
+
+ if (target && target->ToNode()) {
Node* target_node = target->ToNode();
int click_count = 0;
if (mouse_event_type == event_type_names::kMouseup ||
@@ -304,9 +308,9 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
mouse_event_type == event_type_names::kAuxclick) {
click_count = click_count_;
}
-
- DispatchEventResult dispatch_result;
-
+ std::unique_ptr<EventTiming> event_timing;
+ bool should_dispatch =
+ !check_for_listener || target->HasEventListeners(mouse_event_type);
if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
(mouse_event_type == event_type_names::kContextmenu ||
mouse_event_type == event_type_names::kClick ||
@@ -322,7 +326,12 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
mouse_event.FromTouch() ? MouseEvent::kFromTouch
: MouseEvent::kRealOrIndistinguishable,
mouse_event.menu_source_type);
- dispatch_result = target->DispatchEvent(*event);
+ if (frame_ && frame_->DomWindow())
+ event_timing = EventTiming::Create(frame_->DomWindow(), *event);
+ if (should_dispatch) {
+ input_event_result = event_handling_util::ToWebInputEventResult(
+ target->DispatchEvent(*event));
+ }
} else {
MouseEventInit* initializer = MouseEventInit::Create();
SetMouseEventAttributes(initializer, target_node, mouse_event_type,
@@ -333,13 +342,16 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
mouse_event.FromTouch() ? MouseEvent::kFromTouch
: MouseEvent::kRealOrIndistinguishable,
mouse_event.menu_source_type);
-
- dispatch_result = target->DispatchEvent(*event);
+ if (frame_ && frame_->DomWindow())
+ event_timing = EventTiming::Create(frame_->DomWindow(), *event);
+ if (should_dispatch) {
+ input_event_result = event_handling_util::ToWebInputEventResult(
+ target->DispatchEvent(*event));
+ }
}
-
- return event_handling_util::ToWebInputEventResult(dispatch_result);
}
- return WebInputEventResult::kNotHandled;
+
+ return input_event_result;
}
WebInputEventResult MouseEventManager::SetMousePositionAndDispatchMouseEvent(
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 7a765a3d112..af3453d2ac4 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
@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/metrics/field_trial_params.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#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/flat_tree_traversal.h"
@@ -182,14 +183,9 @@ WebInputEventResult PointerEventManager::DispatchPointerEvent(
bool should_filter = ShouldFilterEvent(pointer_event);
// We are about to dispatch this event. It has to be trusted at this point.
pointer_event->SetTrusted(true);
-
- if (frame_ && frame_->DomWindow()) {
- WindowPerformance* performance =
- DOMWindowPerformance::performance(*(frame_->DomWindow()));
- if (performance && EventTiming::IsEventTypeForEventTiming(*pointer_event)) {
- performance->eventCounts()->Add(event_type);
- }
- }
+ std::unique_ptr<EventTiming> event_timing;
+ if (frame_ && frame_->DomWindow())
+ event_timing = EventTiming::Create(frame_->DomWindow(), *pointer_event);
if (should_filter &&
!HasPointerEventListener(frame_->GetEventHandlerRegistry()))
@@ -271,7 +267,8 @@ void PointerEventManager::SetElementUnderPointer(PointerEvent* pointer_event,
Element* target) {
if (element_under_pointer_.Contains(pointer_event->pointerId())) {
EventTargetAttributes* node =
- element_under_pointer_.at(pointer_event->pointerId());
+ element_under_pointer_.DeprecatedAtOrEmptyValue(
+ pointer_event->pointerId());
if (!target) {
element_under_pointer_.erase(pointer_event->pointerId());
} else if (target != node->target) {
@@ -324,7 +321,9 @@ void PointerEventManager::HandlePointerInterruption(
// target before.
Element* target = nullptr;
if (element_under_pointer_.Contains(pointer_event->pointerId())) {
- target = element_under_pointer_.at(pointer_event->pointerId())->target;
+ target = element_under_pointer_
+ .DeprecatedAtOrEmptyValue(pointer_event->pointerId())
+ ->target;
}
DispatchPointerEvent(
@@ -454,7 +453,7 @@ PointerEventManager::ComputePointerEventTarget(
// pointer is captured otherwise it would have gone to the |if| block
// and perform a hit-test.
pointer_event_target.target_element =
- pending_pointer_capture_target_.at(pointer_id);
+ pending_pointer_capture_target_.DeprecatedAtOrEmptyValue(pointer_id);
pointer_event_target.target_frame =
pointer_event_target.target_element->GetDocument().GetFrame();
}
@@ -482,12 +481,6 @@ WebInputEventResult PointerEventManager::DispatchTouchPointerEvent(
: nullptr);
if (pointer_event) {
- if (pointer_event->type() == event_type_names::kPointerdown) {
- if (gesture_manager_.Get()) {
- gesture_manager_->NotifyCurrentPointerDownId(
- pointer_event->pointerId());
- }
- }
result = SendTouchPointerEvent(pointer_event_target.target_element,
pointer_event, web_pointer_event.hovering);
} else {
@@ -1013,7 +1006,7 @@ void PointerEventManager::RemoveTargetFromPointerCapturingMapping(
Element* PointerEventManager::GetCapturingElement(PointerId pointer_id) {
if (pointer_capture_target_.Contains(pointer_id))
- return pointer_capture_target_.at(pointer_id);
+ return pointer_capture_target_.DeprecatedAtOrEmptyValue(pointer_id);
return nullptr;
}
@@ -1063,7 +1056,8 @@ bool PointerEventManager::ReleasePointerCapture(PointerId pointer_id,
// but |m_pendingPointerCaptureTarget| indicated the element that gets the
// very next pointer event. They will be the same if there was no change in
// capturing of a particular |pointerId|. See crbug.com/614481.
- if (pending_pointer_capture_target_.at(pointer_id) == target) {
+ if (pending_pointer_capture_target_.DeprecatedAtOrEmptyValue(pointer_id) ==
+ target) {
ReleasePointerCapture(pointer_id);
return true;
}
@@ -1076,7 +1070,8 @@ void PointerEventManager::ReleaseMousePointerCapture() {
bool PointerEventManager::HasPointerCapture(PointerId pointer_id,
const Element* target) const {
- return pending_pointer_capture_target_.at(pointer_id) == target;
+ return pending_pointer_capture_target_.DeprecatedAtOrEmptyValue(pointer_id) ==
+ target;
}
void PointerEventManager::ReleasePointerCapture(PointerId pointer_id) {
@@ -1084,8 +1079,10 @@ void PointerEventManager::ReleasePointerCapture(PointerId pointer_id) {
}
Element* PointerEventManager::GetMouseCaptureTarget() {
- if (pending_pointer_capture_target_.Contains(PointerEventFactory::kMouseId))
- return pending_pointer_capture_target_.at(PointerEventFactory::kMouseId);
+ if (pending_pointer_capture_target_.Contains(PointerEventFactory::kMouseId)) {
+ return pending_pointer_capture_target_.DeprecatedAtOrEmptyValue(
+ PointerEventFactory::kMouseId);
+ }
return nullptr;
}
@@ -1101,7 +1098,7 @@ bool PointerEventManager::IsPointerIdActiveOnFrame(PointerId pointer_id,
LocalFrame* frame) const {
Element* last_element_receiving_event =
element_under_pointer_.Contains(pointer_id)
- ? element_under_pointer_.at(pointer_id)->target
+ ? element_under_pointer_.DeprecatedAtOrEmptyValue(pointer_id)->target
: nullptr;
return last_element_receiving_event &&
last_element_receiving_event->GetDocument().GetFrame() == frame;
@@ -1132,9 +1129,10 @@ void PointerEventManager::SetLastPointerPositionForFrameBoundary(
Element* new_target) {
PointerId pointer_id =
pointer_event_factory_.GetPointerEventId(web_pointer_event);
- Element* last_target = element_under_pointer_.Contains(pointer_id)
- ? element_under_pointer_.at(pointer_id)->target
- : nullptr;
+ Element* last_target =
+ element_under_pointer_.Contains(pointer_id)
+ ? element_under_pointer_.DeprecatedAtOrEmptyValue(pointer_id)->target
+ : nullptr;
if (!new_target) {
pointer_event_factory_.RemoveLastPosition(pointer_id);
} else if (!last_target || new_target->GetDocument().GetFrame() !=
@@ -1153,4 +1151,9 @@ void PointerEventManager::SetGestureManager(GestureManager* gesture_manager) {
gesture_manager_ = Member<GestureManager>(gesture_manager);
}
+int PointerEventManager::GetPointerEventId(
+ const WebPointerProperties& web_pointer_properties) const {
+ return pointer_event_factory_.GetPointerEventId(web_pointer_properties);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/input/pointer_event_manager.h b/chromium/third_party/blink/renderer/core/input/pointer_event_manager.h
index e43d9bcd889..fa2c3e4fe3d 100644
--- a/chromium/third_party/blink/renderer/core/input/pointer_event_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/pointer_event_manager.h
@@ -5,15 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_POINTER_EVENT_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_POINTER_EVENT_MANAGER_H_
-#include "third_party/blink/public/common/input/web_pointer_properties.h"
-#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/events/pointer_event.h"
-#include "third_party/blink/renderer/core/events/pointer_event_factory.h"
#include "third_party/blink/renderer/core/input/boundary_event_dispatcher.h"
#include "third_party/blink/renderer/core/input/touch_event_manager.h"
#include "third_party/blink/renderer/core/page/touch_adjustment.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -21,6 +16,7 @@ namespace blink {
class LocalFrame;
class MouseEventManager;
class GestureManager;
+class WebPointerProperties;
// This class takes care of dispatching all pointer events and keeps track of
// properties of active pointer events.
@@ -114,6 +110,11 @@ class CORE_EXPORT PointerEventManager final
void SetGestureManager(GestureManager* gesture_manager);
+ // Returns the id of the pointer event corresponding to the given pointer
+ // properties if exists otherwise s_invalidId.
+ int GetPointerEventId(
+ const WebPointerProperties& web_pointer_properties) const;
+
private:
class EventTargetAttributes : public GarbageCollected<EventTargetAttributes> {
public:
diff --git a/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc b/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
index fafa81c7277..2f49ce096a9 100644
--- a/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/pointer_type_names.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -26,11 +27,11 @@ class CheckPointerEventListenerCallback final : public NativeEventListener {
const String pointer_type =
static_cast<PointerEvent*>(event)->pointerType();
- if (pointer_type == "mouse")
+ if (pointer_type == pointer_type_names::kMouse)
num_type_mouse_received_++;
- else if (pointer_type == "touch")
+ else if (pointer_type == pointer_type_names::kTouch)
num_type_touch_received_++;
- else if (pointer_type == "pen")
+ else if (pointer_type == pointer_type_names::kPen)
num_type_pen_received_++;
}
diff --git a/chromium/third_party/blink/renderer/core/input/touch_action_util.cc b/chromium/third_party/blink/renderer/core/input/touch_action_util.cc
index b0c40e12501..507d99bbe0e 100644
--- a/chromium/third_party/blink/renderer/core/input/touch_action_util.cc
+++ b/chromium/third_party/blink/renderer/core/input/touch_action_util.cc
@@ -6,9 +6,6 @@
#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/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
namespace touch_action_util {
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 b93fdc8e31b..5fd1213b1a9 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_TOUCH_EVENT_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_TOUCH_EVENT_MANAGER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_pointer_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
diff --git a/chromium/third_party/blink/renderer/core/inspector/BUILD.gn b/chromium/third_party/blink/renderer/core/inspector/BUILD.gn
index ae8bfda8024..f1e81bba935 100644
--- a/chromium/third_party/blink/renderer/core/inspector/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/inspector/BUILD.gn
@@ -108,7 +108,6 @@ source_set("generated") {
deps = [
":protocol_sources",
"//skia",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
"//third_party/blink/renderer/core:all_generators",
"//third_party/blink/renderer/core/probe:generated",
"//third_party/blink/renderer/platform:make_platform_generated",
diff --git a/chromium/third_party/blink/renderer/core/inspector/OWNERS b/chromium/third_party/blink/renderer/core/inspector/OWNERS
index b27e270f617..f173073c4bc 100644
--- a/chromium/third_party/blink/renderer/core/inspector/OWNERS
+++ b/chromium/third_party/blink/renderer/core/inspector/OWNERS
@@ -1,5 +1,4 @@
alexrudenko@chromium.org
-alph@chromium.org
caseq@chromium.org
dgozman@chromium.org
pfeldman@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/inspector/console_message_storage.cc b/chromium/third_party/blink/renderer/core/inspector/console_message_storage.cc
index ccb13e88a7b..9d959afe809 100644
--- a/chromium/third_party/blink/renderer/core/inspector/console_message_storage.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/console_message_storage.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
+#include "base/trace_event/trace_event.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/instrumentation/tracing/traced_value.h"
diff --git a/chromium/third_party/blink/renderer/core/inspector/console_message_storage.h b/chromium/third_party/blink/renderer/core/inspector/console_message_storage.h
index 1ea2efe53a4..e011f65d05a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/console_message_storage.h
+++ b/chromium/third_party/blink/renderer/core/inspector/console_message_storage.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_CONSOLE_MESSAGE_STORAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_CONSOLE_MESSAGE_STORAGE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -19,6 +18,8 @@ class CORE_EXPORT ConsoleMessageStorage
: public GarbageCollected<ConsoleMessageStorage> {
public:
ConsoleMessageStorage();
+ ConsoleMessageStorage(const ConsoleMessageStorage&) = delete;
+ ConsoleMessageStorage& operator=(const ConsoleMessageStorage&) = delete;
// If |discard_duplicates| is set, the message will only be added if no
// console message with the same text has exists in |messages_|. Returns
@@ -36,8 +37,6 @@ class CORE_EXPORT ConsoleMessageStorage
private:
int expired_count_;
HeapDeque<Member<ConsoleMessage>> messages_;
-
- DISALLOW_COPY_AND_ASSIGN(ConsoleMessageStorage);
};
} // 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 f9dde2d7f76..244afefa7a2 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
@@ -120,8 +120,6 @@ void DevToolsHost::Trace(Visitor* visitor) const {
void DevToolsHost::EvaluateScript(const String& expression) {
if (ScriptForbiddenScope::IsScriptForbidden())
return;
- if (!frontend_frame_)
- return;
ScriptState* script_state = ToScriptStateForMainWorld(frontend_frame_);
if (!script_state)
return;
diff --git a/chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc b/chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc
index 1cd6ee12ff7..2b6fdfaf9c0 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc
@@ -86,6 +86,9 @@ class DevToolsAgent::IOAgent : public mojom::blink::DevToolsAgent {
CrossThreadUnretained(this), std::move(receiver)));
}
+ IOAgent(const IOAgent&) = delete;
+ IOAgent& operator=(const IOAgent&) = delete;
+
void BindInterface(
mojo::PendingReceiver<mojom::blink::DevToolsAgent> receiver) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
@@ -154,8 +157,6 @@ class DevToolsAgent::IOAgent : public mojom::blink::DevToolsAgent {
scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
CrossThreadWeakPersistent<::blink::DevToolsAgent> agent_;
mojo::Receiver<mojom::blink::DevToolsAgent> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(IOAgent);
};
DevToolsAgent::DevToolsAgent(
diff --git a/chromium/third_party/blink/renderer/core/inspector/devtools_session.cc b/chromium/third_party/blink/renderer/core/inspector/devtools_session.cc
index 242653b4e72..b28a69f901a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_session.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_session.cc
@@ -64,6 +64,9 @@ class DevToolsSession::IOSession : public mojom::blink::DevToolsSession {
CrossThreadUnretained(this), std::move(receiver)));
}
+ IOSession(const IOSession&) = delete;
+ IOSession& operator=(const IOSession&) = delete;
+
~IOSession() override = default;
void BindInterface(
@@ -87,7 +90,8 @@ class DevToolsSession::IOSession : public mojom::blink::DevToolsSession {
// Post a task to the worker or main renderer thread that will interrupt V8
// and be run immediately. Only methods that do not run JS code are safe.
Vector<uint8_t> message_copy;
- message_copy.Append(message.data(), message.size());
+ message_copy.Append(message.data(),
+ base::checked_cast<wtf_size_t>(message.size()));
if (ShouldInterruptForMethod(method)) {
inspector_task_runner_->AppendTask(CrossThreadBindOnce(
&::blink::DevToolsSession::DispatchProtocolCommandImpl, session_,
@@ -104,8 +108,6 @@ class DevToolsSession::IOSession : public mojom::blink::DevToolsSession {
scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
CrossThreadWeakPersistent<::blink::DevToolsSession> session_;
mojo::Receiver<mojom::blink::DevToolsSession> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(IOSession);
};
DevToolsSession::DevToolsSession(
diff --git a/chromium/third_party/blink/renderer/core/inspector/devtools_session.h b/chromium/third_party/blink/renderer/core/inspector/devtools_session.h
index 1fb9aa9ea75..6410f3af7be 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_session.h
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_session.h
@@ -7,7 +7,6 @@
#include <memory>
#include "base/callback.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -48,6 +47,8 @@ class CORE_EXPORT DevToolsSession : public GarbageCollected<DevToolsSession>,
bool client_expects_binary_responses,
const String& session_id,
scoped_refptr<base::SequencedTaskRunner> mojo_task_runner);
+ DevToolsSession(const DevToolsSession&) = delete;
+ DevToolsSession& operator=(const DevToolsSession&) = delete;
~DevToolsSession() override;
void ConnectToV8(v8_inspector::V8Inspector*, int context_group_id);
@@ -123,8 +124,6 @@ class CORE_EXPORT DevToolsSession : public GarbageCollected<DevToolsSession>,
InspectorAgentState v8_session_state_;
InspectorAgentState::Bytes v8_session_state_cbor_;
const String session_id_;
-
- DISALLOW_COPY_AND_ASSIGN(DevToolsSession);
};
} // namespace blink
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 c75fe54d5d8..de08cccaf93 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dom_editor.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_editor.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/core/inspector/dom_editor.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -53,6 +52,8 @@ class DOMEditor::RemoveChildAction final : public InspectorHistory::Action {
: InspectorHistory::Action("RemoveChild"),
parent_node_(parent_node),
node_(node) {}
+ RemoveChildAction(const RemoveChildAction&) = delete;
+ RemoveChildAction& operator=(const RemoveChildAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
anchor_node_ = node_->nextSibling();
@@ -81,7 +82,6 @@ class DOMEditor::RemoveChildAction final : public InspectorHistory::Action {
Member<ContainerNode> parent_node_;
Member<Node> node_;
Member<Node> anchor_node_;
- DISALLOW_COPY_AND_ASSIGN(RemoveChildAction);
};
class DOMEditor::InsertBeforeAction final : public InspectorHistory::Action {
@@ -91,6 +91,8 @@ class DOMEditor::InsertBeforeAction final : public InspectorHistory::Action {
parent_node_(parent_node),
node_(node),
anchor_node_(anchor_node) {}
+ InsertBeforeAction(const InsertBeforeAction&) = delete;
+ InsertBeforeAction& operator=(const InsertBeforeAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
if (node_->parentNode()) {
@@ -134,7 +136,6 @@ class DOMEditor::InsertBeforeAction final : public InspectorHistory::Action {
Member<Node> node_;
Member<Node> anchor_node_;
Member<RemoveChildAction> remove_child_action_;
- DISALLOW_COPY_AND_ASSIGN(InsertBeforeAction);
};
class DOMEditor::RemoveAttributeAction final : public InspectorHistory::Action {
@@ -143,6 +144,8 @@ class DOMEditor::RemoveAttributeAction final : public InspectorHistory::Action {
: InspectorHistory::Action("RemoveAttribute"),
element_(element),
name_(name) {}
+ RemoveAttributeAction(const RemoveAttributeAction&) = delete;
+ RemoveAttributeAction& operator=(const RemoveAttributeAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
value_ = element_->getAttribute(name_);
@@ -168,7 +171,6 @@ class DOMEditor::RemoveAttributeAction final : public InspectorHistory::Action {
Member<Element> element_;
AtomicString name_;
AtomicString value_;
- DISALLOW_COPY_AND_ASSIGN(RemoveAttributeAction);
};
class DOMEditor::SetAttributeAction final : public InspectorHistory::Action {
@@ -181,6 +183,8 @@ class DOMEditor::SetAttributeAction final : public InspectorHistory::Action {
name_(name),
value_(value),
had_attribute_(false) {}
+ SetAttributeAction(const SetAttributeAction&) = delete;
+ SetAttributeAction& operator=(const SetAttributeAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
const AtomicString& value = element_->getAttribute(name_);
@@ -214,7 +218,6 @@ class DOMEditor::SetAttributeAction final : public InspectorHistory::Action {
AtomicString value_;
bool had_attribute_;
AtomicString old_value_;
- DISALLOW_COPY_AND_ASSIGN(SetAttributeAction);
};
class DOMEditor::SetOuterHTMLAction final : public InspectorHistory::Action {
@@ -227,6 +230,8 @@ class DOMEditor::SetOuterHTMLAction final : public InspectorHistory::Action {
new_node_(nullptr),
history_(MakeGarbageCollected<InspectorHistory>()),
dom_editor_(MakeGarbageCollected<DOMEditor>(history_.Get())) {}
+ SetOuterHTMLAction(const SetOuterHTMLAction&) = delete;
+ SetOuterHTMLAction& operator=(const SetOuterHTMLAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
old_html_ = CreateMarkup(node_.Get());
@@ -268,7 +273,6 @@ class DOMEditor::SetOuterHTMLAction final : public InspectorHistory::Action {
Member<Node> new_node_;
Member<InspectorHistory> history_;
Member<DOMEditor> dom_editor_;
- DISALLOW_COPY_AND_ASSIGN(SetOuterHTMLAction);
};
class DOMEditor::ReplaceWholeTextAction final
@@ -278,6 +282,8 @@ class DOMEditor::ReplaceWholeTextAction final
: InspectorHistory::Action("ReplaceWholeText"),
text_node_(text_node),
text_(text) {}
+ ReplaceWholeTextAction(const ReplaceWholeTextAction&) = delete;
+ ReplaceWholeTextAction& operator=(const ReplaceWholeTextAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
old_text_ = text_node_->wholeText();
@@ -303,7 +309,6 @@ class DOMEditor::ReplaceWholeTextAction final
Member<Text> text_node_;
String text_;
String old_text_;
- DISALLOW_COPY_AND_ASSIGN(ReplaceWholeTextAction);
};
class DOMEditor::ReplaceChildNodeAction final
@@ -316,6 +321,8 @@ class DOMEditor::ReplaceChildNodeAction final
parent_node_(parent_node),
new_node_(new_node),
old_node_(old_node) {}
+ ReplaceChildNodeAction(const ReplaceChildNodeAction&) = delete;
+ ReplaceChildNodeAction& operator=(const ReplaceChildNodeAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
return Redo(exception_state);
@@ -342,13 +349,14 @@ class DOMEditor::ReplaceChildNodeAction final
Member<ContainerNode> parent_node_;
Member<Node> new_node_;
Member<Node> old_node_;
- DISALLOW_COPY_AND_ASSIGN(ReplaceChildNodeAction);
};
class DOMEditor::SetNodeValueAction final : public InspectorHistory::Action {
public:
SetNodeValueAction(Node* node, const String& value)
: InspectorHistory::Action("SetNodeValue"), node_(node), value_(value) {}
+ SetNodeValueAction(const SetNodeValueAction&) = delete;
+ SetNodeValueAction& operator=(const SetNodeValueAction&) = delete;
bool Perform(ExceptionState&) override {
old_value_ = node_->nodeValue();
@@ -374,7 +382,6 @@ class DOMEditor::SetNodeValueAction final : public InspectorHistory::Action {
Member<Node> node_;
String value_;
String old_value_;
- DISALLOW_COPY_AND_ASSIGN(SetNodeValueAction);
};
DOMEditor::DOMEditor(InspectorHistory* history) : history_(history) {}
diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_editor.h b/chromium/third_party/blink/renderer/core/inspector/dom_editor.h
index 76de15b60dc..43ba5e4ba0f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dom_editor.h
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_editor.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_EDITOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_EDITOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/inspector/protocol/Forward.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -48,6 +47,8 @@ class Text;
class DOMEditor final : public GarbageCollected<DOMEditor> {
public:
explicit DOMEditor(InspectorHistory*);
+ DOMEditor(const DOMEditor&) = delete;
+ DOMEditor& operator=(const DOMEditor&) = delete;
void Trace(Visitor*) const;
@@ -95,8 +96,6 @@ class DOMEditor final : public GarbageCollected<DOMEditor> {
class SetNodeValueAction;
Member<InspectorHistory> history_;
-
- DISALLOW_COPY_AND_ASSIGN(DOMEditor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.h b/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.h
index 5160f97c4d4..3c5f6c74530 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.h
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_PATCH_SUPPORT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_PATCH_SUPPORT_H_
-#include "base/macros.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/text/wtf_string.h"
@@ -50,6 +49,8 @@ class DOMPatchSupport final {
public:
DOMPatchSupport(DOMEditor*, Document&);
+ DOMPatchSupport(const DOMPatchSupport&) = delete;
+ DOMPatchSupport& operator=(const DOMPatchSupport&) = delete;
void PatchDocument(const String& markup);
Node* PatchNode(Node*, const String& markup, ExceptionState&);
@@ -90,8 +91,6 @@ class DOMPatchSupport final {
Document* document_;
UnusedNodesMap unused_nodes_map_;
-
- DISALLOW_COPY_AND_ASSIGN(DOMPatchSupport);
};
} // namespace blink
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 0106a8acbbb..ca1b318108b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc
@@ -100,7 +100,7 @@ int IdentifiersFactory::IntIdForNode(Node* node) {
// static
String IdentifiersFactory::AddProcessIdPrefixTo(uint64_t id) {
- uint32_t process_id = base::GetUniqueIdForProcess().GetUnsafeValue();
+ auto process_id = base::GetUniqueIdForProcess().GetUnsafeValue();
StringBuilder builder;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc
index cef38f0813f..9db014a302c 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc
@@ -434,7 +434,7 @@ String PersistentTool::GetOverlayName() {
bool PersistentTool::IsEmpty() {
return !grid_node_highlights_.size() && !flex_container_configs_.size() &&
- !scroll_snap_configs_.size();
+ !scroll_snap_configs_.size() && !container_query_configs_.size();
}
void PersistentTool::SetGridConfigs(GridConfigs configs) {
@@ -449,6 +449,10 @@ void PersistentTool::SetScrollSnapConfigs(ScrollSnapConfigs configs) {
scroll_snap_configs_ = std::move(configs);
}
+void PersistentTool::SetContainerQueryConfigs(ContainerQueryConfigs configs) {
+ container_query_configs_ = std::move(configs);
+}
+
bool PersistentTool::ForwardEventsToOverlay() {
return false;
}
@@ -485,6 +489,14 @@ void PersistentTool::Draw(float scale) {
overlay_->EvaluateInOverlay("drawScrollSnapHighlight",
std::move(highlight));
}
+ for (auto& entry : container_query_configs_) {
+ std::unique_ptr<protocol::Value> highlight =
+ InspectorContainerQueryHighlight(entry.first.Get(), *(entry.second));
+ if (!highlight)
+ continue;
+ overlay_->EvaluateInOverlay("drawContainerQueryHighlight",
+ std::move(highlight));
+ }
}
std::unique_ptr<protocol::DictionaryValue>
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h
index dbe9c78e4fb..3c9d885d555 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h
@@ -8,7 +8,6 @@
#include <vector>
#include <v8-inspector.h>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/inspector/inspector_overlay_agent.h"
#include "third_party/blink/renderer/core/inspector/node_content_visibility_state.h"
@@ -26,6 +25,8 @@ class SearchingForNodeTool : public InspectTool {
InspectorDOMAgent* dom_agent,
bool ua_shadow,
const std::vector<uint8_t>& highlight_config);
+ SearchingForNodeTool(const SearchingForNodeTool&) = delete;
+ SearchingForNodeTool& operator=(const SearchingForNodeTool&) = delete;
void Trace(Visitor* visitor) const override;
@@ -54,7 +55,6 @@ class SearchingForNodeTool : public InspectTool {
std::unique_ptr<InspectorHighlightConfig> highlight_config_;
InspectorHighlightContrastInfo contrast_info_;
bool omit_tooltip_ = false;
- DISALLOW_COPY_AND_ASSIGN(SearchingForNodeTool);
};
// -----------------------------------------------------------------------------
@@ -66,6 +66,8 @@ class QuadHighlightTool : public InspectTool {
std::unique_ptr<FloatQuad> quad,
Color color,
Color outline_color);
+ QuadHighlightTool(const QuadHighlightTool&) = delete;
+ QuadHighlightTool& operator=(const QuadHighlightTool&) = delete;
private:
bool ForwardEventsToOverlay() override;
@@ -75,7 +77,6 @@ class QuadHighlightTool : public InspectTool {
std::unique_ptr<FloatQuad> quad_;
Color color_;
Color outline_color_;
- DISALLOW_COPY_AND_ASSIGN(QuadHighlightTool);
};
// -----------------------------------------------------------------------------
@@ -87,6 +88,8 @@ class NodeHighlightTool : public InspectTool {
Member<Node> node,
String selector_list,
std::unique_ptr<InspectorHighlightConfig> highlight_config);
+ NodeHighlightTool(const NodeHighlightTool&) = delete;
+ NodeHighlightTool& operator=(const NodeHighlightTool&) = delete;
std::unique_ptr<protocol::DictionaryValue> GetNodeInspectorHighlightAsJson(
bool append_element_info,
@@ -110,7 +113,6 @@ class NodeHighlightTool : public InspectTool {
String selector_list_;
std::unique_ptr<InspectorHighlightConfig> highlight_config_;
InspectorHighlightContrastInfo contrast_info_;
- DISALLOW_COPY_AND_ASSIGN(NodeHighlightTool);
};
// -----------------------------------------------------------------------------
@@ -122,6 +124,8 @@ class SourceOrderTool : public InspectTool {
OverlayFrontend* frontend,
Node* node,
std::unique_ptr<InspectorSourceOrderConfig> source_order_config);
+ SourceOrderTool(const SourceOrderTool&) = delete;
+ SourceOrderTool& operator=(const SourceOrderTool&) = delete;
std::unique_ptr<protocol::DictionaryValue>
GetNodeInspectorSourceOrderHighlightAsJson() const;
@@ -137,7 +141,6 @@ class SourceOrderTool : public InspectTool {
Member<Node> node_;
std::unique_ptr<InspectorSourceOrderConfig> source_order_config_;
- DISALLOW_COPY_AND_ASSIGN(SourceOrderTool);
};
// -----------------------------------------------------------------------------
@@ -151,15 +154,23 @@ using ScrollSnapConfigs = Vector<
std::pair<Member<Node>,
std::unique_ptr<InspectorScrollSnapContainerHighlightConfig>>>;
+using ContainerQueryConfigs = Vector<std::pair<
+ Member<Node>,
+ std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>>>;
+
class PersistentTool : public InspectTool {
using InspectTool::InspectTool;
public:
+ PersistentTool(const PersistentTool&) = delete;
+ PersistentTool& operator=(const PersistentTool&) = delete;
+
void Draw(float scale) override;
bool IsEmpty();
void SetGridConfigs(GridConfigs);
void SetFlexContainerConfigs(FlexContainerConfigs);
void SetScrollSnapConfigs(ScrollSnapConfigs);
+ void SetContainerQueryConfigs(ContainerQueryConfigs);
std::unique_ptr<protocol::DictionaryValue> GetGridInspectorHighlightsAsJson()
const;
@@ -173,13 +184,15 @@ class PersistentTool : public InspectTool {
GridConfigs grid_node_highlights_;
FlexContainerConfigs flex_container_configs_;
ScrollSnapConfigs scroll_snap_configs_;
- DISALLOW_COPY_AND_ASSIGN(PersistentTool);
+ ContainerQueryConfigs container_query_configs_;
};
// -----------------------------------------------------------------------------
class NearbyDistanceTool : public InspectTool {
public:
+ NearbyDistanceTool(const NearbyDistanceTool&) = delete;
+ NearbyDistanceTool& operator=(const NearbyDistanceTool&) = delete;
void Trace(Visitor* visitor) const override;
private:
@@ -193,7 +206,6 @@ class NearbyDistanceTool : public InspectTool {
String GetOverlayName() override;
Member<Node> hovered_node_;
- DISALLOW_COPY_AND_ASSIGN(NearbyDistanceTool);
};
// -----------------------------------------------------------------------------
@@ -201,11 +213,14 @@ class NearbyDistanceTool : public InspectTool {
class ShowViewSizeTool : public InspectTool {
using InspectTool::InspectTool;
+ public:
+ ShowViewSizeTool(const ShowViewSizeTool&) = delete;
+ ShowViewSizeTool& operator=(const ShowViewSizeTool&) = delete;
+
private:
bool ForwardEventsToOverlay() override;
void Draw(float scale) override;
String GetOverlayName() override;
- DISALLOW_COPY_AND_ASSIGN(ShowViewSizeTool);
};
// -----------------------------------------------------------------------------
@@ -213,12 +228,12 @@ class ShowViewSizeTool : public InspectTool {
class ScreenshotTool : public InspectTool {
public:
ScreenshotTool(InspectorOverlayAgent* overlay, OverlayFrontend* frontend);
+ ScreenshotTool(const ScreenshotTool&) = delete;
+ ScreenshotTool& operator=(const ScreenshotTool&) = delete;
private:
void Dispatch(const String& message) override;
String GetOverlayName() override;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenshotTool);
};
// -----------------------------------------------------------------------------
@@ -232,6 +247,8 @@ class PausedInDebuggerTool : public InspectTool {
: InspectTool(overlay, frontend),
v8_session_(v8_session),
message_(message) {}
+ PausedInDebuggerTool(const PausedInDebuggerTool&) = delete;
+ PausedInDebuggerTool& operator=(const PausedInDebuggerTool&) = delete;
private:
void Draw(float scale) override;
@@ -239,7 +256,6 @@ class PausedInDebuggerTool : public InspectTool {
String GetOverlayName() override;
v8_inspector::V8InspectorSession* v8_session_;
String message_;
- DISALLOW_COPY_AND_ASSIGN(PausedInDebuggerTool);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspected_frames.h b/chromium/third_party/blink/renderer/core/inspector/inspected_frames.h
index 763bc91531b..71c2e619e7a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspected_frames.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspected_frames.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTED_FRAMES_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTED_FRAMES_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -37,6 +36,8 @@ class CORE_EXPORT InspectedFrames final
};
explicit InspectedFrames(LocalFrame*);
+ InspectedFrames(const InspectedFrames&) = delete;
+ InspectedFrames& operator=(const InspectedFrames&) = delete;
LocalFrame* Root() { return root_; }
bool Contains(LocalFrame*) const;
@@ -48,7 +49,6 @@ class CORE_EXPORT InspectedFrames final
private:
Member<LocalFrame> root_;
- DISALLOW_COPY_AND_ASSIGN(InspectedFrames);
};
} // namespace blink
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 909349838e0..da7e1794cf6 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
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_computed_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddouble.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
#include "third_party/blink/renderer/core/animation/css/css_animation.h"
@@ -103,7 +104,7 @@ static std::unique_ptr<protocol::Animation::AnimationEffect>
BuildObjectForAnimationEffect(KeyframeEffect* effect) {
ComputedEffectTiming* computed_timing = effect->getComputedTiming();
double delay = computed_timing->delay();
- double duration = computed_timing->duration().GetAsUnrestrictedDouble();
+ double duration = computed_timing->duration()->GetAsUnrestrictedDouble();
String easing = effect->SpecifiedTiming().timing_function->ToString();
std::unique_ptr<protocol::Animation::AnimationEffect> animation_object =
@@ -228,8 +229,8 @@ Response InspectorAnimationAgent::getCurrentTime(const String& id,
Response response = AssertAnimation(id, animation);
if (!response.IsSuccess())
return response;
- if (id_to_animation_clone_.at(id))
- animation = id_to_animation_clone_.at(id);
+ if (id_to_animation_clone_.DeprecatedAtOrEmptyValue(id))
+ animation = id_to_animation_clone_.DeprecatedAtOrEmptyValue(id);
*current_time = Timing::NullValue();
if (animation->Paused() || !animation->timeline()->IsActive()) {
@@ -295,7 +296,7 @@ Response InspectorAnimationAgent::setPaused(
blink::Animation* InspectorAnimationAgent::AnimationClone(
blink::Animation* animation) {
const String id = String::Number(animation->SequenceNumber());
- if (!id_to_animation_clone_.at(id)) {
+ if (!id_to_animation_clone_.DeprecatedAtOrEmptyValue(id)) {
auto* old_effect = To<KeyframeEffect>(animation->effect());
DCHECK(old_effect->Model()->IsKeyframeEffectModel());
KeyframeEffectModelBase* old_model = old_effect->Model();
@@ -331,17 +332,11 @@ blink::Animation* InspectorAnimationAgent::AnimationClone(
id_to_animation_clone_.Set(id, clone);
id_to_animation_.Set(String::Number(clone->SequenceNumber()), clone);
clone->play();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
clone->setStartTime(animation->startTime(), ASSERT_NO_EXCEPTION);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CSSNumberish start_time;
- animation->startTime(start_time);
- clone->setStartTime(start_time);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
animation->SetEffectSuppressed(true);
}
- return id_to_animation_clone_.at(id);
+ return id_to_animation_clone_.DeprecatedAtOrEmptyValue(id);
}
Response InspectorAnimationAgent::seekAnimations(
@@ -366,10 +361,12 @@ Response InspectorAnimationAgent::seekAnimations(
Response InspectorAnimationAgent::releaseAnimations(
std::unique_ptr<protocol::Array<String>> animation_ids) {
for (const String& animation_id : *animation_ids) {
- blink::Animation* animation = id_to_animation_.at(animation_id);
+ blink::Animation* animation =
+ id_to_animation_.DeprecatedAtOrEmptyValue(animation_id);
if (animation)
animation->SetEffectSuppressed(false);
- blink::Animation* clone = id_to_animation_clone_.at(animation_id);
+ blink::Animation* clone =
+ id_to_animation_clone_.DeprecatedAtOrEmptyValue(animation_id);
if (clone)
clone->cancel();
id_to_animation_clone_.erase(animation_id);
@@ -391,9 +388,8 @@ Response InspectorAnimationAgent::setTiming(const String& animation_id,
NonThrowableExceptionState exception_state;
OptionalEffectTiming* timing = OptionalEffectTiming::Create();
- UnrestrictedDoubleOrString unrestricted_duration;
- unrestricted_duration.SetUnrestrictedDouble(duration);
- timing->setDuration(unrestricted_duration);
+ timing->setDuration(
+ MakeGarbageCollected<V8UnionStringOrUnrestrictedDouble>(duration));
timing->setDelay(delay);
animation->effect()->updateTiming(timing, exception_state);
return Response::Success();
@@ -407,14 +403,13 @@ Response InspectorAnimationAgent::resolveAnimation(
Response response = AssertAnimation(animation_id, animation);
if (!response.IsSuccess())
return response;
- if (id_to_animation_clone_.at(animation_id))
- animation = id_to_animation_clone_.at(animation_id);
+ if (id_to_animation_clone_.DeprecatedAtOrEmptyValue(animation_id))
+ animation = id_to_animation_clone_.DeprecatedAtOrEmptyValue(animation_id);
const Element* element =
To<KeyframeEffect>(animation->effect())->EffectTarget();
Document* document = element->ownerDocument();
LocalFrame* frame = document ? document->GetFrame() : nullptr;
- ScriptState* script_state =
- frame ? ToScriptStateForMainWorld(frame) : nullptr;
+ ScriptState* script_state = ToScriptStateForMainWorld(frame);
if (!script_state)
return Response::ServerError("Element not associated with a document.");
@@ -526,7 +521,7 @@ void InspectorAnimationAgent::DidClearDocumentOfWindowObject(
Response InspectorAnimationAgent::AssertAnimation(const String& id,
blink::Animation*& result) {
- result = id_to_animation_.at(id);
+ result = id_to_animation_.DeprecatedAtOrEmptyValue(id);
if (!result)
return Response::ServerError("Could not find animation with given id");
return Response::Success();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.h
index 4cf66c2b5d0..ede0395b5e6 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_ANIMATION_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_ANIMATION_AGENT_H_
-#include "base/macros.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/css/css_keyframes_rule.h"
@@ -26,6 +25,8 @@ class CORE_EXPORT InspectorAnimationAgent final
InspectorAnimationAgent(InspectedFrames*,
InspectorCSSAgent*,
v8_inspector::V8InspectorSession*);
+ InspectorAnimationAgent(const InspectorAnimationAgent&) = delete;
+ InspectorAnimationAgent& operator=(const InspectorAnimationAgent&) = delete;
// Base agent methods.
void Restore() override;
@@ -91,7 +92,6 @@ class CORE_EXPORT InspectorAnimationAgent final
HashSet<String> cleared_animations_;
InspectorAgentState::Boolean enabled_;
InspectorAgentState::Double playback_rate_;
- DISALLOW_COPY_AND_ASSIGN(InspectorAnimationAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h
index 73e63e2dc1e..799dd6aac80 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_APPLICATION_CACHE_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_APPLICATION_CACHE_AGENT_H_
-#include "base/macros.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/ApplicationCache.h"
@@ -41,6 +40,10 @@ class CORE_EXPORT InspectorApplicationCacheAgent final
: public InspectorBaseAgent<protocol::ApplicationCache::Metainfo> {
public:
explicit InspectorApplicationCacheAgent(InspectedFrames*);
+ InspectorApplicationCacheAgent(const InspectorApplicationCacheAgent&) =
+ delete;
+ InspectorApplicationCacheAgent& operator=(
+ const InspectorApplicationCacheAgent&) = delete;
~InspectorApplicationCacheAgent() override = default;
void Trace(Visitor*) const override;
@@ -86,7 +89,6 @@ class CORE_EXPORT InspectorApplicationCacheAgent final
Member<InspectedFrames> inspected_frames_;
InspectorAgentState::Boolean enabled_;
- DISALLOW_COPY_AND_ASSIGN(InspectorApplicationCacheAgent);
};
} // namespace blink
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 bfd207c13ef..6ec7589fadf 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_audits_agent.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/web/web_image.h"
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.h
index 5c5f4e89044..ed8b2209098 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_AUDITS_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_AUDITS_AGENT_H_
-#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/inspector/inspected_frames.h"
@@ -24,6 +23,8 @@ class CORE_EXPORT InspectorAuditsAgent final
explicit InspectorAuditsAgent(InspectorNetworkAgent*,
InspectorIssueStorage*,
InspectedFrames*);
+ InspectorAuditsAgent(const InspectorAuditsAgent&) = delete;
+ InspectorAuditsAgent& operator=(const InspectorAuditsAgent&) = delete;
~InspectorAuditsAgent() override;
void Trace(Visitor*) const override;
@@ -54,8 +55,6 @@ class CORE_EXPORT InspectorAuditsAgent final
InspectorAgentState::Boolean enabled_;
Member<InspectorNetworkAgent> network_agent_;
Member<InspectedFrames> inspected_frames_;
-
- DISALLOW_COPY_AND_ASSIGN(InspectorAuditsAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
index be77b020424..33f2df7953f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h"
+#include "base/unguessable_token.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -78,12 +79,14 @@ std::unique_ptr<protocol::Audits::SourceCodeLocation> CreateProtocolLocation(
return protocol_location;
}
-void AuditsIssue::ReportCorsIssue(ExecutionContext* execution_context,
- int64_t identifier,
- RendererCorsIssueCode code,
- String url,
- String initiator_origin,
- String failedParameter) {
+void AuditsIssue::ReportCorsIssue(
+ ExecutionContext* execution_context,
+ int64_t identifier,
+ RendererCorsIssueCode code,
+ String url,
+ String initiator_origin,
+ String failedParameter,
+ absl::optional<base::UnguessableToken> issue_id) {
String devtools_request_id =
IdentifiersFactory::SubresourceRequestId(identifier);
std::unique_ptr<protocol::Audits::AffectedRequest> affected_request =
@@ -114,6 +117,9 @@ void AuditsIssue::ReportCorsIssue(ExecutionContext* execution_context,
.setCode(protocol::Audits::InspectorIssueCodeEnum::CorsIssue)
.setDetails(std::move(details))
.build();
+ if (issue_id) {
+ issue->setIssueId(IdentifiersFactory::IdFromToken(*issue_id));
+ }
execution_context->AddInspectorIssue(AuditsIssue(std::move(issue)));
}
@@ -219,4 +225,30 @@ void AuditsIssue::ReportNavigatorUserAgentAccess(
.build();
execution_context->AddInspectorIssue(AuditsIssue(std::move(issue)));
}
+
+void AuditsIssue::ReportCrossOriginWasmModuleSharingIssue(
+ ExecutionContext* execution_context,
+ const std::string& wasm_source_url,
+ WTF::String source_origin,
+ WTF::String target_origin,
+ bool is_warning) {
+ auto details =
+ protocol::Audits::WasmCrossOriginModuleSharingIssueDetails::create()
+ .setWasmModuleUrl(WTF::String::FromUTF8(wasm_source_url))
+ .setSourceOrigin(source_origin)
+ .setTargetOrigin(target_origin)
+ .setIsWarning(is_warning)
+ .build();
+
+ auto issue_details =
+ protocol::Audits::InspectorIssueDetails::create()
+ .setWasmCrossOriginModuleSharingIssue(std::move(details))
+ .build();
+ auto issue = protocol::Audits::InspectorIssue::create()
+ .setCode(protocol::Audits::InspectorIssueCodeEnum::
+ WasmCrossOriginModuleSharingIssue)
+ .setDetails(std::move(issue_details))
+ .build();
+ execution_context->AddInspectorIssue(AuditsIssue(std::move(issue)));
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.h b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
index 41d249b1f02..37700eaea7a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
@@ -7,6 +7,7 @@
#include <memory>
#include "base/unguessable_token.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
@@ -77,7 +78,8 @@ class CORE_EXPORT AuditsIssue {
RendererCorsIssueCode code,
WTF::String url,
WTF::String initiator_origin,
- WTF::String failedParameter);
+ WTF::String failedParameter,
+ absl::optional<base::UnguessableToken> issue_id);
// Reports an Attribution Reporting API issue to DevTools.
// |reporting_execution_context| is the current execution context in which the
// issue happens and is reported in (the "target" in DevTools terms).
@@ -98,6 +100,13 @@ class CORE_EXPORT AuditsIssue {
ExecutionContext* execution_context,
WTF::String url);
+ static void ReportCrossOriginWasmModuleSharingIssue(
+ ExecutionContext* execution_context,
+ const std::string& wasm_source_url,
+ WTF::String source_origin,
+ WTF::String target_origin,
+ bool is_warning);
+
private:
explicit AuditsIssue(std::unique_ptr<protocol::Audits::InspectorIssue> issue);
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.cc
index 2c67724778d..19cfa437b05 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_contrast.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_gradient_value.h"
@@ -150,10 +151,11 @@ void InspectorContrast::CollectNodesAndBuildRTreeIfNeeded() {
rtree_.Build(
elements_,
[](const HeapVector<Member<Node>>& items, size_t index) {
- return PixelSnappedIntRect(GetNodeRect(items[index]));
+ return PixelSnappedIntRect(
+ GetNodeRect(items[static_cast<wtf_size_t>(index)]));
},
[](const HeapVector<Member<Node>>& items, size_t index) {
- return items[index];
+ return items[static_cast<wtf_size_t>(index)];
});
rtree_built_ = true;
@@ -284,11 +286,10 @@ Vector<Color> InspectorContrast::GetBackgroundColors(Element* element,
}
// Get the elements which overlap the given rectangle.
-std::vector<Member<Node>> InspectorContrast::ElementsFromRect(
- const PhysicalRect& rect,
- Document& document) {
+std::vector<Node*> InspectorContrast::ElementsFromRect(const PhysicalRect& rect,
+ Document& document) {
CollectNodesAndBuildRTreeIfNeeded();
- std::vector<Member<Node>> overlapping_elements;
+ std::vector<Node*> overlapping_elements;
rtree_.Search(PixelSnappedIntRect(rect), &overlapping_elements);
return overlapping_elements;
}
@@ -298,8 +299,7 @@ bool InspectorContrast::GetColorsFromRect(PhysicalRect rect,
Element* top_element,
Vector<Color>& colors,
float* text_opacity) {
- std::vector<Member<Node>> elements_under_rect =
- ElementsFromRect(rect, document);
+ std::vector<Node*> elements_under_rect = ElementsFromRect(rect, document);
bool found_opaque_color = false;
bool found_top_element = false;
@@ -308,7 +308,7 @@ bool InspectorContrast::GetColorsFromRect(PhysicalRect rect,
for (auto e = elements_under_rect.begin();
!found_top_element && e != elements_under_rect.end(); ++e) {
- const Element* element = To<Element>(e->Get());
+ const Element* element = To<Element>(*e);
if (element == top_element)
found_top_element = true;
@@ -366,7 +366,7 @@ bool InspectorContrast::GetColorsFromRect(PhysicalRect rect,
AddColorsFromImageStyle(*style, *layout_object, colors, found_opaque_color,
found_non_transparent_color);
- bool contains = found_top_element || GetNodeRect(e->Get()).Contains(rect);
+ bool contains = found_top_element || GetNodeRect(*e).Contains(rect);
if (!contains && found_non_transparent_color) {
// Only return colors if some opaque element covers up this one.
colors.clear();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.h b/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.h
index ac8db30e6b1..c30144e7fa5 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_contrast.h
@@ -45,8 +45,8 @@ class CORE_EXPORT InspectorContrast {
private:
void SortElementsByPaintOrder(HeapVector<Member<Node>>&, Document*);
- std::vector<Member<Node>> ElementsFromRect(const PhysicalRect& rect,
- Document& document);
+ std::vector<Node*> ElementsFromRect(const PhysicalRect& rect,
+ Document& document);
bool GetColorsFromRect(PhysicalRect rect,
Document& document,
Element* top_element,
@@ -54,7 +54,11 @@ class CORE_EXPORT InspectorContrast {
float* text_opacity);
void CollectNodesAndBuildRTreeIfNeeded();
- cc::RTree<Member<Node>> rtree_;
+ // It is safe to keep raw pointers to Node because rtree_
+ // only operates on nodes retained in the elements_ HeapVector below.
+ // See InspectorContrast::CollectNodesAndBuildRTreeIfNeeded and
+ // crbug.com/1222445.
+ cc::RTree<Node*> rtree_;
HeapVector<Member<Node>> elements_;
Document* document_;
bool rtree_built_ = 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 2fa62e6b537..979b3eaedad 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
@@ -27,10 +27,10 @@
#include <utility>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
+#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
#include "third_party/blink/renderer/core/css/css_font_face.h"
#include "third_party/blink/renderer/core/css/css_font_face_source.h"
@@ -49,6 +49,7 @@
#include "third_party/blink/renderer/core/css/css_variable_data.h"
#include "third_party/blink/renderer/core/css/font_face.h"
#include "third_party/blink/renderer/core/css/font_size_functions.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/media_query.h"
#include "third_party/blink/renderer/core/css/media_values.h"
@@ -229,13 +230,12 @@ static unsigned ComputePseudoClassMask(
class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action {
public:
StyleSheetAction(const String& name) : InspectorHistory::Action(name) {}
+ StyleSheetAction(const StyleSheetAction&) = delete;
+ StyleSheetAction& operator=(const StyleSheetAction&) = delete;
virtual std::unique_ptr<protocol::CSS::CSSStyle> TakeSerializedStyle() {
return nullptr;
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(StyleSheetAction);
};
class InspectorCSSAgent::SetStyleSheetTextAction final
@@ -246,6 +246,8 @@ class InspectorCSSAgent::SetStyleSheetTextAction final
: InspectorCSSAgent::StyleSheetAction("SetStyleSheetText"),
style_sheet_(style_sheet),
text_(text) {}
+ SetStyleSheetTextAction(const SetStyleSheetTextAction&) = delete;
+ SetStyleSheetTextAction& operator=(const SetStyleSheetTextAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
if (!style_sheet_->GetText(&old_text_))
@@ -283,7 +285,6 @@ class InspectorCSSAgent::SetStyleSheetTextAction final
Member<InspectorStyleSheetBase> style_sheet_;
String text_;
String old_text_;
- DISALLOW_COPY_AND_ASSIGN(SetStyleSheetTextAction);
};
class InspectorCSSAgent::ModifyRuleAction final
@@ -293,6 +294,7 @@ class InspectorCSSAgent::ModifyRuleAction final
kSetRuleSelector,
kSetStyleText,
kSetMediaRuleText,
+ kSetContainerRuleText,
kSetKeyframeKey
};
@@ -306,6 +308,8 @@ class InspectorCSSAgent::ModifyRuleAction final
new_text_(text),
old_range_(range),
css_rule_(nullptr) {}
+ ModifyRuleAction(const ModifyRuleAction&) = delete;
+ ModifyRuleAction& operator=(const ModifyRuleAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
return Redo(exception_state);
@@ -322,6 +326,9 @@ class InspectorCSSAgent::ModifyRuleAction final
case kSetMediaRuleText:
return style_sheet_->SetMediaRuleText(new_range_, old_text_, nullptr,
nullptr, exception_state);
+ case kSetContainerRuleText:
+ return style_sheet_->SetContainerRuleText(
+ new_range_, old_text_, nullptr, nullptr, exception_state);
case kSetKeyframeKey:
return style_sheet_->SetKeyframeKey(new_range_, old_text_, nullptr,
nullptr, exception_state);
@@ -345,6 +352,10 @@ class InspectorCSSAgent::ModifyRuleAction final
css_rule_ = style_sheet_->SetMediaRuleText(
old_range_, new_text_, &new_range_, &old_text_, exception_state);
break;
+ case kSetContainerRuleText:
+ css_rule_ = style_sheet_->SetContainerRuleText(
+ old_range_, new_text_, &new_range_, &old_text_, exception_state);
+ break;
case kSetKeyframeKey:
css_rule_ = style_sheet_->SetKeyframeKey(
old_range_, new_text_, &new_range_, &old_text_, exception_state);
@@ -401,7 +412,6 @@ class InspectorCSSAgent::ModifyRuleAction final
SourceRange old_range_;
SourceRange new_range_;
Member<CSSRule> css_rule_;
- DISALLOW_COPY_AND_ASSIGN(ModifyRuleAction);
};
class InspectorCSSAgent::SetElementStyleAction final
@@ -412,6 +422,8 @@ class InspectorCSSAgent::SetElementStyleAction final
: InspectorCSSAgent::StyleSheetAction("SetElementStyleAction"),
style_sheet_(style_sheet),
text_(text) {}
+ SetElementStyleAction(const SetElementStyleAction&) = delete;
+ SetElementStyleAction& operator=(const SetElementStyleAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
return Redo(exception_state);
@@ -452,7 +464,6 @@ class InspectorCSSAgent::SetElementStyleAction final
Member<InspectorStyleSheetForInlineStyle> style_sheet_;
String text_;
String old_text_;
- DISALLOW_COPY_AND_ASSIGN(SetElementStyleAction);
};
class InspectorCSSAgent::AddRuleAction final
@@ -465,6 +476,8 @@ class InspectorCSSAgent::AddRuleAction final
style_sheet_(style_sheet),
rule_text_(rule_text),
location_(location) {}
+ AddRuleAction(const AddRuleAction&) = delete;
+ AddRuleAction& operator=(const AddRuleAction&) = delete;
bool Perform(ExceptionState& exception_state) override {
return Redo(exception_state);
@@ -503,7 +516,6 @@ class InspectorCSSAgent::AddRuleAction final
String old_text_;
SourceRange location_;
SourceRange added_range_;
- DISALLOW_COPY_AND_ASSIGN(AddRuleAction);
};
// static
@@ -516,6 +528,11 @@ CSSMediaRule* InspectorCSSAgent::AsCSSMediaRule(CSSRule* rule) {
return DynamicTo<CSSMediaRule>(rule);
}
+// static
+CSSContainerRule* InspectorCSSAgent::AsCSSContainerRule(CSSRule* rule) {
+ return DynamicTo<CSSContainerRule>(rule);
+}
+
InspectorCSSAgent::InspectorCSSAgent(
InspectorDOMAgent* dom_agent,
InspectedFrames* inspected_frames,
@@ -699,7 +716,7 @@ void InspectorCSSAgent::SetActiveStyleSheets(
Document* document,
const HeapVector<Member<CSSStyleSheet>>& all_sheets_vector) {
HeapHashSet<Member<CSSStyleSheet>>* document_css_style_sheets =
- document_to_css_style_sheets_.at(document);
+ document_to_css_style_sheets_.DeprecatedAtOrEmptyValue(document);
if (!document_css_style_sheets) {
document_css_style_sheets =
MakeGarbageCollected<HeapHashSet<Member<CSSStyleSheet>>>();
@@ -728,7 +745,8 @@ void InspectorCSSAgent::SetActiveStyleSheets(
for (CSSStyleSheet* css_style_sheet : removed_sheets) {
InspectorStyleSheet* inspector_style_sheet =
- css_style_sheet_to_inspector_style_sheet_.at(css_style_sheet);
+ css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
+ css_style_sheet);
DCHECK(inspector_style_sheet);
document_css_style_sheets->erase(css_style_sheet);
@@ -874,6 +892,7 @@ Response InspectorCSSAgent::getMatchedStylesForNode(
stylesheet->SyncTextIfNeeded();
}
+ HasMatchedCacheScope has_matched_cache_scope(&document);
InspectorStyleResolver resolver(element, element_pseudo_id);
// Matched rules.
@@ -1471,6 +1490,37 @@ Response InspectorCSSAgent::setMediaText(
return InspectorDOMAgent::ToResponse(exception_state);
}
+Response InspectorCSSAgent::setContainerQueryText(
+ const String& style_sheet_id,
+ std::unique_ptr<protocol::CSS::SourceRange> range,
+ const String& text,
+ std::unique_ptr<protocol::CSS::CSSContainerQuery>* result) {
+ FrontendOperationScope scope;
+ InspectorStyleSheet* inspector_style_sheet = nullptr;
+ Response response =
+ AssertInspectorStyleSheetForId(style_sheet_id, inspector_style_sheet);
+ if (!response.IsSuccess())
+ return response;
+ SourceRange text_range;
+ response =
+ JsonRangeToSourceRange(inspector_style_sheet, range.get(), &text_range);
+ if (!response.IsSuccess())
+ return response;
+
+ DummyExceptionStateForTesting exception_state;
+ ModifyRuleAction* action = MakeGarbageCollected<ModifyRuleAction>(
+ ModifyRuleAction::kSetContainerRuleText, inspector_style_sheet,
+ text_range, text);
+ bool success = dom_agent_->History()->Perform(action, exception_state);
+ if (success) {
+ CSSContainerRule* rule =
+ InspectorCSSAgent::AsCSSContainerRule(action->TakeRule());
+ *result = BuildContainerQueryObject(rule->container(),
+ rule->parentStyleSheet(), rule->Name());
+ }
+ return InspectorDOMAgent::ToResponse(exception_state);
+}
+
Response InspectorCSSAgent::createStyleSheet(
const String& frame_id,
protocol::CSS::StyleSheetId* out_style_sheet_id) {
@@ -1645,7 +1695,8 @@ std::unique_ptr<protocol::CSS::CSSMedia> InspectorCSSAgent::BuildMediaObject(
InspectorStyleSheet* inspector_style_sheet =
parent_style_sheet
- ? css_style_sheet_to_inspector_style_sheet_.at(parent_style_sheet)
+ ? css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
+ parent_style_sheet)
: nullptr;
auto media_list_array =
std::make_unique<protocol::Array<protocol::CSS::MediaQuery>>();
@@ -1802,6 +1853,67 @@ InspectorCSSAgent::BuildMediaListChain(CSSRule* rule) {
return media_array;
}
+std::unique_ptr<protocol::CSS::CSSContainerQuery>
+InspectorCSSAgent::BuildContainerQueryObject(const MediaList* media,
+ CSSStyleSheet* parent_style_sheet,
+ const AtomicString& name) {
+ // The |mediaText()| getter does not require an ExecutionContext as it is
+ // only used for setting/parsing new media queries and features.
+ std::unique_ptr<protocol::CSS::CSSContainerQuery> container_query_object =
+ protocol::CSS::CSSContainerQuery::create()
+ .setText(media->mediaText(/*execution_context=*/nullptr))
+ .build();
+
+ InspectorStyleSheet* inspector_style_sheet =
+ parent_style_sheet
+ ? css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
+ parent_style_sheet)
+ : nullptr;
+ if (inspector_style_sheet)
+ container_query_object->setStyleSheetId(inspector_style_sheet->Id());
+
+ CSSRule* parent_rule = media->ParentRule();
+ if (!parent_rule)
+ return container_query_object;
+
+ inspector_style_sheet = BindStyleSheet(parent_rule->parentStyleSheet());
+ container_query_object->setRange(
+ inspector_style_sheet->RuleHeaderSourceRange(parent_rule));
+
+ if (!name.IsEmpty())
+ container_query_object->setName(name);
+
+ return container_query_object;
+}
+
+void InspectorCSSAgent::CollectContainerQueriesFromRule(
+ CSSRule* rule,
+ protocol::Array<protocol::CSS::CSSContainerQuery>* container_queries) {
+ if (auto* container_rule = DynamicTo<CSSContainerRule>(rule)) {
+ MediaList* media_list = container_rule->container();
+ if (!media_list || !media_list->length())
+ return;
+
+ container_queries->emplace_back(BuildContainerQueryObject(
+ media_list, container_rule->parentStyleSheet(),
+ container_rule->Name()));
+ }
+}
+
+std::unique_ptr<protocol::Array<protocol::CSS::CSSContainerQuery>>
+InspectorCSSAgent::BuildContainerQueries(CSSRule* rule) {
+ if (!rule)
+ return nullptr;
+ auto container_queries =
+ std::make_unique<protocol::Array<protocol::CSS::CSSContainerQuery>>();
+ CSSRule* parent_rule = rule;
+ while (parent_rule) {
+ CollectContainerQueriesFromRule(parent_rule, container_queries.get());
+ parent_rule = parent_rule->parentRule();
+ }
+ return container_queries;
+}
+
InspectorStyleSheetForInlineStyle* InspectorCSSAgent::AsInspectorStyleSheet(
Element* element) {
NodeToInspectorStyleSheet::iterator it =
@@ -1848,7 +1960,8 @@ void InspectorCSSAgent::CollectStyleSheets(
InspectorStyleSheet* InspectorCSSAgent::BindStyleSheet(
CSSStyleSheet* style_sheet) {
InspectorStyleSheet* inspector_style_sheet =
- css_style_sheet_to_inspector_style_sheet_.at(style_sheet);
+ css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
+ style_sheet);
if (!inspector_style_sheet) {
Document* document = style_sheet->OwnerDocument();
inspector_style_sheet = MakeGarbageCollected<InspectorStyleSheet>(
@@ -1907,7 +2020,8 @@ InspectorStyleSheet* InspectorCSSAgent::ViaInspectorStyleSheet(
FlushPendingProtocolNotifications();
- return css_style_sheet_to_inspector_style_sheet_.at(&inspector_sheet);
+ return css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
+ &inspector_sheet);
}
Response InspectorCSSAgent::AssertEnabled() {
@@ -1975,6 +2089,8 @@ std::unique_ptr<protocol::CSS::CSSRule> InspectorCSSAgent::BuildObjectForRule(
std::unique_ptr<protocol::CSS::CSSRule> result =
inspector_style_sheet->BuildObjectForRuleWithoutMedia(rule);
result->setMedia(BuildMediaListChain(rule));
+ if (RuntimeEnabledFeatures::CSSContainerQueriesEnabled())
+ result->setContainerQueries(BuildContainerQueries(rule));
return result;
}
@@ -2104,7 +2220,8 @@ void InspectorCSSAgent::DidModifyDOMAttr(Element* element) {
void InspectorCSSAgent::DidMutateStyleSheet(CSSStyleSheet* css_style_sheet) {
InspectorStyleSheet* style_sheet =
- css_style_sheet_to_inspector_style_sheet_.at(css_style_sheet);
+ css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
+ css_style_sheet);
if (!style_sheet)
return;
style_sheet->MarkForSync();
@@ -2392,7 +2509,7 @@ void InspectorCSSAgent::BuildRulesMap(
if (css_rule->GetType() == CSSRule::kImportRule) {
CSSImportRule* css_import_rule = DynamicTo<CSSImportRule>(css_rule.Get());
InspectorStyleSheet* imported_style_sheet =
- css_style_sheet_to_inspector_style_sheet_.at(
+ css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
const_cast<CSSStyleSheet*>(css_import_rule->styleSheet()));
if (!imported_style_sheet)
continue;
@@ -2418,7 +2535,7 @@ Response InspectorCSSAgent::takeCoverageDelta(
for (const auto& entry : coverage_delta) {
const CSSStyleSheet* css_style_sheet = entry.key.Get();
InspectorStyleSheet* style_sheet =
- css_style_sheet_to_inspector_style_sheet_.at(
+ css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
const_cast<CSSStyleSheet*>(css_style_sheet));
if (!style_sheet)
continue;
@@ -2433,7 +2550,7 @@ Response InspectorCSSAgent::takeCoverageDelta(
// If the rule comes from an @import'ed file, the `rule_style_sheet` is
// different from `style_sheet`.
InspectorStyleSheet* rule_style_sheet =
- css_style_sheet_to_inspector_style_sheet_.at(
+ css_style_sheet_to_inspector_style_sheet_.DeprecatedAtOrEmptyValue(
const_cast<CSSStyleSheet*>(css_style_rule->parentStyleSheet()));
if (!rule_style_sheet)
continue;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h
index 93ca98f3856..54847dd6bce 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_CSS_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_CSS_AGENT_H_
-#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/css/css_rule_list.h"
@@ -98,6 +97,7 @@ class CORE_EXPORT InspectorCSSAgent final
static CSSStyleRule* AsCSSStyleRule(CSSRule*);
static CSSMediaRule* AsCSSMediaRule(CSSRule*);
+ static CSSContainerRule* AsCSSContainerRule(CSSRule*);
static void CollectAllDocumentStyleSheets(Document*,
HeapVector<Member<CSSStyleSheet>>&);
@@ -113,6 +113,8 @@ class CORE_EXPORT InspectorCSSAgent final
InspectorNetworkAgent*,
InspectorResourceContentLoader*,
InspectorResourceContainer*);
+ InspectorCSSAgent(const InspectorCSSAgent&) = delete;
+ InspectorCSSAgent& operator=(const InspectorCSSAgent&) = delete;
~InspectorCSSAgent() override;
void Trace(Visitor*) const override;
@@ -186,6 +188,11 @@ class CORE_EXPORT InspectorCSSAgent final
std::unique_ptr<protocol::CSS::SourceRange>,
const String& text,
std::unique_ptr<protocol::CSS::CSSMedia>*) override;
+ protocol::Response setContainerQueryText(
+ const String& style_sheet_id,
+ std::unique_ptr<protocol::CSS::SourceRange>,
+ const String& text,
+ std::unique_ptr<protocol::CSS::CSSContainerQuery>*) override;
protocol::Response createStyleSheet(const String& frame_id,
String* style_sheet_id) override;
protocol::Response addRule(const String& style_sheet_id,
@@ -321,6 +328,17 @@ class CORE_EXPORT InspectorCSSAgent final
std::unique_ptr<protocol::Array<int>>
BuildArrayForComputedStyleUpdatedNodes();
+ // Container Queries implementation
+ std::unique_ptr<protocol::CSS::CSSContainerQuery> BuildContainerQueryObject(
+ const MediaList*,
+ CSSStyleSheet*,
+ const AtomicString&);
+ void CollectContainerQueriesFromRule(
+ CSSRule*,
+ protocol::Array<protocol::CSS::CSSContainerQuery>*);
+ std::unique_ptr<protocol::Array<protocol::CSS::CSSContainerQuery>>
+ BuildContainerQueries(CSSRule*);
+
// InspectorDOMAgent::DOMListener implementation
void DidAddDocument(Document*) override;
void WillRemoveDOMNode(Node*) override;
@@ -375,7 +393,6 @@ class CORE_EXPORT InspectorCSSAgent final
friend class InspectorResourceContentLoaderCallback;
friend class StyleSheetBinder;
- DISALLOW_COPY_AND_ASSIGN(InspectorCSSAgent);
};
} // namespace blink
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 44b44559606..68300594fce 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
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_file.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
+#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/character_data.h"
@@ -47,6 +48,7 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -71,6 +73,7 @@
#include "third_party/blink/renderer/core/inspector/dom_patch_support.h"
#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/inspector_css_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_highlight.h"
#include "third_party/blink/renderer/core/inspector/inspector_history.h"
#include "third_party/blink/renderer/core/inspector/resolve_node.h"
@@ -183,6 +186,8 @@ protocol::DOM::PseudoType InspectorDOMAgent::ProtocolPseudoElementType(
return protocol::DOM::PseudoTypeEnum::SpellingError;
case kPseudoIdGrammarError:
return protocol::DOM::PseudoTypeEnum::GrammarError;
+ case kPseudoIdHighlight:
+ return protocol::DOM::PseudoTypeEnum::Highlight;
case kPseudoIdFirstLineInherited:
return protocol::DOM::PseudoTypeEnum::FirstLineInherited;
case kPseudoIdScrollbar:
@@ -202,8 +207,6 @@ protocol::DOM::PseudoType InspectorDOMAgent::ProtocolPseudoElementType(
case kPseudoIdInputListButton:
return protocol::DOM::PseudoTypeEnum::InputListButton;
case kAfterLastInternalPseudoId:
- case kPseudoIdHighlight:
- // TODO(http://crbug.com/1195196)
case kPseudoIdNone:
CHECK(false);
return "";
@@ -311,7 +314,7 @@ void InspectorDOMAgent::ReleaseDanglingNodes() {
int InspectorDOMAgent::Bind(Node* node, NodeToIdMap* nodes_map) {
if (!nodes_map)
return 0;
- int id = nodes_map->at(node);
+ int id = nodes_map->DeprecatedAtOrEmptyValue(node);
if (id)
return id;
id = last_node_id_++;
@@ -322,7 +325,7 @@ int InspectorDOMAgent::Bind(Node* node, NodeToIdMap* nodes_map) {
}
void InspectorDOMAgent::Unbind(Node* node) {
- int id = document_node_to_id_map_->at(node);
+ int id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(node);
if (!id)
return;
@@ -623,7 +626,7 @@ void InspectorDOMAgent::PushChildNodesToFrontend(int node_id,
depth--;
for (node = InnerFirstChild(node); node; node = InnerNextSibling(node)) {
- int child_node_id = node_map->at(node);
+ int child_node_id = node_map->DeprecatedAtOrEmptyValue(node);
DCHECK(child_node_id);
PushChildNodesToFrontend(child_node_id, depth, pierce);
}
@@ -762,7 +765,7 @@ int InspectorDOMAgent::PushNodePathToFrontend(Node* node_to_push,
return 0;
// Return id in case the node is known.
- int result = node_map->at(node_to_push);
+ int result = node_map->DeprecatedAtOrEmptyValue(node_to_push);
if (result)
return result;
@@ -774,17 +777,17 @@ int InspectorDOMAgent::PushNodePathToFrontend(Node* node_to_push,
if (!parent)
return 0;
path.push_back(parent);
- if (node_map->at(parent))
+ if (node_map->DeprecatedAtOrEmptyValue(parent))
break;
node = parent;
}
for (int i = path.size() - 1; i >= 0; --i) {
- int node_id = node_map->at(path.at(i).Get());
+ int node_id = node_map->DeprecatedAtOrEmptyValue(path.at(i).Get());
DCHECK(node_id);
PushChildNodesToFrontend(node_id);
}
- return node_map->at(node_to_push);
+ return node_map->DeprecatedAtOrEmptyValue(node_to_push);
}
int InspectorDOMAgent::PushNodePathToFrontend(Node* node_to_push) {
@@ -812,7 +815,7 @@ int InspectorDOMAgent::PushNodePathToFrontend(Node* node_to_push) {
}
int InspectorDOMAgent::BoundNodeId(Node* node) {
- return document_node_to_id_map_->at(node);
+ return document_node_to_id_map_->DeprecatedAtOrEmptyValue(node);
}
Response InspectorDOMAgent::setAttributeValue(int element_id,
@@ -833,27 +836,46 @@ Response InspectorDOMAgent::setAttributesAsText(int element_id,
if (!response.IsSuccess())
return response;
- String markup = "<span " + text + "></span>";
- DocumentFragment* fragment = element->GetDocument().createDocumentFragment();
+ bool is_html_document = IsA<HTMLDocument>(element->GetDocument());
+
+ auto getContextElement = [](Element* element,
+ bool is_html_document) -> Element* {
+ // Not all elements can represent the context (e.g. <iframe>). Use
+ // the owner <svg> element if there is any, falling back to <body>,
+ // falling back to nullptr (in the case of non-SVG XML documents).
+ if (auto* svg_element = DynamicTo<SVGElement>(element)) {
+ SVGSVGElement* owner = svg_element->ownerSVGElement();
+ if (owner)
+ return owner;
+ }
+
+ if (is_html_document)
+ return element->GetDocument().body();
- bool should_ignore_case =
- IsA<HTMLDocument>(element->GetDocument()) && element->IsHTMLElement();
- // Not all elements can represent the context (i.e. IFRAME), hence using
- // document.body.
- if (should_ignore_case && element->GetDocument().body()) {
- fragment->ParseHTML(markup, element->GetDocument().body(),
- kAllowScriptingContent);
- } else {
- Element* contextElement = nullptr;
- if (auto* svg_element = DynamicTo<SVGElement>(element))
- contextElement = svg_element->ownerSVGElement();
- fragment->ParseXML(markup, contextElement, kAllowScriptingContent);
- }
+ return nullptr;
+ };
+
+ Element* contextElement = getContextElement(element, is_html_document);
+
+ auto getParsedElement = [](Element* element, Element* contextElement,
+ const String& text, bool is_html_document) {
+ String markup = element->IsSVGElement() ? "<svg " + text + "></svg>"
+ : "<span " + text + "></span>";
+ DocumentFragment* fragment =
+ element->GetDocument().createDocumentFragment();
+ if (is_html_document && contextElement)
+ fragment->ParseHTML(markup, contextElement, kAllowScriptingContent);
+ else
+ fragment->ParseXML(markup, contextElement, kAllowScriptingContent);
+ return DynamicTo<Element>(fragment->firstChild());
+ };
- Element* parsed_element = DynamicTo<Element>(fragment->firstChild());
+ Element* parsed_element =
+ getParsedElement(element, contextElement, text, is_html_document);
if (!parsed_element)
return Response::ServerError("Could not parse value as attributes");
+ bool should_ignore_case = is_html_document && element->IsHTMLElement();
String case_adjusted_name = should_ignore_case
? name.fromMaybe("").DeprecatedLower()
: name.fromMaybe("");
@@ -1520,6 +1542,85 @@ Response InspectorDOMAgent::requestNode(const String& object_id, int* node_id) {
return Response::Success();
}
+Response InspectorDOMAgent::getContainerForNode(
+ int node_id,
+ protocol::Maybe<String> container_name,
+ Maybe<int>* container_node_id) {
+ Element* element = nullptr;
+ Response response = AssertElement(node_id, element);
+ if (!response.IsSuccess())
+ return response;
+
+ element->GetDocument().UpdateStyleAndLayoutTreeForNode(element);
+ StyleResolver& style_resolver = element->GetDocument().GetStyleResolver();
+ Element* container = style_resolver.FindContainerForElement(
+ element, AtomicString(container_name.fromMaybe(g_null_atom)));
+ if (container)
+ *container_node_id = PushNodePathToFrontend(container);
+ return Response::Success();
+}
+
+Response InspectorDOMAgent::getQueryingDescendantsForContainer(
+ int node_id,
+ std::unique_ptr<protocol::Array<int>>* node_ids) {
+ Element* container = nullptr;
+ Response response = AssertElement(node_id, container);
+ if (!response.IsSuccess())
+ return response;
+
+ *node_ids = std::make_unique<protocol::Array<int>>();
+ NodeToIdMap* nodes_map = document_node_to_id_map_.Get();
+ for (Element* descendant : GetContainerQueryingDescendants(container)) {
+ int id = PushNodePathToFrontend(descendant, nodes_map);
+ (*node_ids)->push_back(id);
+ }
+
+ return Response::Success();
+}
+
+// static
+const HeapVector<Member<Element>>
+InspectorDOMAgent::GetContainerQueryingDescendants(Element* container) {
+ // This won't work for edge cases with display locking
+ // (https://crbug.com/1235306).
+ container->GetDocument().UpdateStyleAndLayoutTreeForSubtree(container);
+
+ HeapVector<Member<Element>> querying_descendants;
+ for (Element& element : ElementTraversal::DescendantsOf(*container)) {
+ if (ContainerQueriedByElement(container, &element))
+ querying_descendants.push_back(element);
+ }
+
+ return querying_descendants;
+}
+
+// static
+bool InspectorDOMAgent::ContainerQueriedByElement(Element* container,
+ Element* element) {
+ const ComputedStyle* style = element->GetComputedStyle();
+ if (!style || !style->DependsOnContainerQueries())
+ return false;
+
+ StyleResolver& style_resolver = element->GetDocument().GetStyleResolver();
+ RuleIndexList* matched_rules =
+ style_resolver.CssRulesForElement(element, StyleResolver::kAllCSSRules);
+ for (auto it = matched_rules->rbegin(); it != matched_rules->rend(); ++it) {
+ CSSRule* parent_rule = it->first;
+ while (parent_rule) {
+ auto* container_rule = DynamicTo<CSSContainerRule>(parent_rule);
+ if (container_rule) {
+ if (container == style_resolver.FindContainerForElement(
+ element, container_rule->Name()))
+ return true;
+ }
+
+ parent_rule = parent_rule->parentRule();
+ }
+ }
+
+ return false;
+}
+
// static
String InspectorDOMAgent::DocumentURLString(Document* document) {
if (!document || document->Url().IsNull())
@@ -1901,7 +2002,8 @@ void InspectorDOMAgent::InvalidateFrameOwnerElement(
if (!frame_owner)
return;
- int frame_owner_id = document_node_to_id_map_->at(frame_owner);
+ int frame_owner_id =
+ document_node_to_id_map_->DeprecatedAtOrEmptyValue(frame_owner);
if (!frame_owner_id)
return;
@@ -1914,7 +2016,9 @@ void InspectorDOMAgent::InvalidateFrameOwnerElement(
BuildObjectForNode(frame_owner, 0, false, document_node_to_id_map_.Get());
Node* previous_sibling = InnerPreviousSibling(frame_owner);
int prev_id =
- previous_sibling ? document_node_to_id_map_->at(previous_sibling) : 0;
+ previous_sibling
+ ? document_node_to_id_map_->DeprecatedAtOrEmptyValue(previous_sibling)
+ : 0;
GetFrontend()->childNodeInserted(parent_id, prev_id, std::move(value));
}
@@ -1955,20 +2059,23 @@ void InspectorDOMAgent::DidInsertDOMNode(Node* node) {
ContainerNode* parent = node->parentNode();
if (!parent)
return;
- int parent_id = document_node_to_id_map_->at(parent);
+ int parent_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(parent);
// Return if parent is not mapped yet.
if (!parent_id)
return;
if (!children_requested_.Contains(parent_id)) {
// No children are mapped yet -> only notify on changes of child count.
- int count = cached_child_count_.at(parent_id) + 1;
+ int count = cached_child_count_.DeprecatedAtOrEmptyValue(parent_id) + 1;
cached_child_count_.Set(parent_id, count);
GetFrontend()->childNodeCountUpdated(parent_id, count);
} else {
// Children have been requested -> return value of a new child.
Node* prev_sibling = InnerPreviousSibling(node);
- int prev_id = prev_sibling ? document_node_to_id_map_->at(prev_sibling) : 0;
+ int prev_id =
+ prev_sibling
+ ? document_node_to_id_map_->DeprecatedAtOrEmptyValue(prev_sibling)
+ : 0;
std::unique_ptr<protocol::DOM::Node> value =
BuildObjectForNode(node, 0, false, document_node_to_id_map_.Get());
GetFrontend()->childNodeInserted(parent_id, prev_id, std::move(value));
@@ -1988,7 +2095,7 @@ void InspectorDOMAgent::DOMNodeRemoved(Node* node) {
if (!document_node_to_id_map_->Contains(parent))
return;
- int parent_id = document_node_to_id_map_->at(parent);
+ int parent_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(parent);
if (!children_requested_.Contains(parent_id)) {
// No children are mapped yet -> only notify on changes of child count.
@@ -1996,8 +2103,8 @@ void InspectorDOMAgent::DOMNodeRemoved(Node* node) {
cached_child_count_.Set(parent_id, count);
GetFrontend()->childNodeCountUpdated(parent_id, count);
} else {
- GetFrontend()->childNodeRemoved(parent_id,
- document_node_to_id_map_->at(node));
+ GetFrontend()->childNodeRemoved(
+ parent_id, document_node_to_id_map_->DeprecatedAtOrEmptyValue(node));
}
Unbind(node);
}
@@ -2055,7 +2162,7 @@ void InspectorDOMAgent::StyleAttributeInvalidated(
}
void InspectorDOMAgent::CharacterDataModified(CharacterData* character_data) {
- int id = document_node_to_id_map_->at(character_data);
+ int id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(character_data);
if (IsWhitespace(character_data) && id) {
DOMNodeRemoved(character_data);
return;
@@ -2075,7 +2182,7 @@ InspectorRevalidateDOMTask* InspectorDOMAgent::RevalidateTask() {
}
void InspectorDOMAgent::DidInvalidateStyleAttr(Node* node) {
- int id = document_node_to_id_map_->at(node);
+ int id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(node);
// If node is not mapped yet -> ignore the event.
if (!id)
return;
@@ -2087,7 +2194,7 @@ void InspectorDOMAgent::DidPushShadowRoot(Element* host, ShadowRoot* root) {
if (!host->ownerDocument())
return;
- int host_id = document_node_to_id_map_->at(host);
+ int host_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(host);
if (!host_id)
return;
@@ -2101,15 +2208,16 @@ void InspectorDOMAgent::WillPopShadowRoot(Element* host, ShadowRoot* root) {
if (!host->ownerDocument())
return;
- int host_id = document_node_to_id_map_->at(host);
- int root_id = document_node_to_id_map_->at(root);
+ int host_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(host);
+ int root_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(root);
if (host_id && root_id)
GetFrontend()->shadowRootPopped(host_id, root_id);
}
void InspectorDOMAgent::DidPerformSlotDistribution(
HTMLSlotElement* slot_element) {
- int insertion_point_id = document_node_to_id_map_->at(slot_element);
+ int insertion_point_id =
+ document_node_to_id_map_->DeprecatedAtOrEmptyValue(slot_element);
if (insertion_point_id)
GetFrontend()->distributedNodesUpdated(
insertion_point_id, BuildDistributedNodesForSlot(slot_element));
@@ -2148,7 +2256,7 @@ void InspectorDOMAgent::PseudoElementCreated(PseudoElement* pseudo_element) {
return;
if (!PseudoElement::IsWebExposed(pseudo_element->GetPseudoId(), parent))
return;
- int parent_id = document_node_to_id_map_->at(parent);
+ int parent_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(parent);
if (!parent_id)
return;
@@ -2159,14 +2267,15 @@ void InspectorDOMAgent::PseudoElementCreated(PseudoElement* pseudo_element) {
}
void InspectorDOMAgent::PseudoElementDestroyed(PseudoElement* pseudo_element) {
- int pseudo_element_id = document_node_to_id_map_->at(pseudo_element);
+ int pseudo_element_id =
+ document_node_to_id_map_->DeprecatedAtOrEmptyValue(pseudo_element);
if (!pseudo_element_id)
return;
// If a PseudoElement is bound, its parent element must be bound, too.
Element* parent = pseudo_element->ParentOrShadowHostElement();
DCHECK(parent);
- int parent_id = document_node_to_id_map_->at(parent);
+ int parent_id = document_node_to_id_map_->DeprecatedAtOrEmptyValue(parent);
DCHECK(parent_id);
Unbind(pseudo_element);
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 826fa8bc620..d09d2e959c1 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
@@ -32,7 +32,6 @@
#include <memory>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -102,6 +101,8 @@ class CORE_EXPORT InspectorDOMAgent final
InspectorDOMAgent(v8::Isolate*,
InspectedFrames*,
v8_inspector::V8InspectorSession*);
+ InspectorDOMAgent(const InspectorDOMAgent&) = delete;
+ InspectorDOMAgent& operator=(const InspectorDOMAgent&) = delete;
~InspectorDOMAgent() override;
void Trace(Visitor*) const override;
@@ -253,6 +254,16 @@ class CORE_EXPORT InspectorDOMAgent final
protocol::Response getFileInfo(const String& object_id,
String* path) override;
+ protocol::Response getContainerForNode(
+ int node_id,
+ protocol::Maybe<String> container_name,
+ protocol::Maybe<int>* container_node_id) override;
+ protocol::Response getQueryingDescendantsForContainer(
+ int node_id,
+ std::unique_ptr<protocol::Array<int>>* node_ids) override;
+ static const HeapVector<Member<Element>> GetContainerQueryingDescendants(
+ Element* container);
+
bool Enabled() const;
void ReleaseDanglingNodes();
@@ -367,6 +378,8 @@ class CORE_EXPORT InspectorDOMAgent final
std::unique_ptr<protocol::Array<protocol::DOM::BackendNode>>
BuildDistributedNodesForSlot(HTMLSlotElement*);
+ static bool ContainerQueriedByElement(Element* container, Element* element);
+
Node* NodeForPath(const String& path);
void DiscardFrontendBindings();
@@ -397,7 +410,6 @@ class CORE_EXPORT InspectorDOMAgent final
bool suppress_attribute_modified_event_;
InspectorAgentState::Boolean enabled_;
InspectorAgentState::Boolean capture_node_stack_traces_;
- DISALLOW_COPY_AND_ASSIGN(InspectorDOMAgent);
};
} // namespace blink
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 20c93e0dddb..326a8bf8b79 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
@@ -286,8 +286,8 @@ void InspectorDOMDebuggerAgent::DidInvalidateStyleAttr(Node* node) {
void InspectorDOMDebuggerAgent::DidInsertDOMNode(Node* node) {
if (dom_breakpoints_.size()) {
- uint32_t mask =
- dom_breakpoints_.at(InspectorDOMAgent::InnerParentNode(node));
+ uint32_t mask = dom_breakpoints_.DeprecatedAtOrEmptyValue(
+ InspectorDOMAgent::InnerParentNode(node));
uint32_t inheritable_types_mask =
(mask | (mask >> domBreakpointDerivedTypeShift)) &
inheritableDOMBreakpointTypesMask;
@@ -390,7 +390,8 @@ Response InspectorDOMDebuggerAgent::setDOMBreakpoint(
return response;
uint32_t root_bit = 1 << type;
- dom_breakpoints_.Set(node, dom_breakpoints_.at(node) | root_bit);
+ dom_breakpoints_.Set(
+ node, dom_breakpoints_.DeprecatedAtOrEmptyValue(node) | root_bit);
if (root_bit & inheritableDOMBreakpointTypesMask) {
for (Node* child = InspectorDOMAgent::InnerFirstChild(node); child;
child = InspectorDOMAgent::InnerNextSibling(child))
@@ -414,7 +415,7 @@ Response InspectorDOMDebuggerAgent::removeDOMBreakpoint(
return response;
uint32_t root_bit = 1 << type;
- uint32_t mask = dom_breakpoints_.at(node) & ~root_bit;
+ uint32_t mask = dom_breakpoints_.DeprecatedAtOrEmptyValue(node) & ~root_bit;
if (mask)
dom_breakpoints_.Set(node, mask);
else
@@ -526,6 +527,11 @@ void InspectorDOMDebuggerAgent::WillInsertDOMNode(Node* parent) {
BreakProgramOnDOMEvent(parent, SubtreeModified, true);
}
+void InspectorDOMDebuggerAgent::CharacterDataModified(CharacterData* node) {
+ if (HasBreakpoint(node, SubtreeModified))
+ BreakProgramOnDOMEvent(node, SubtreeModified, false);
+}
+
void InspectorDOMDebuggerAgent::WillRemoveDOMNode(Node* node) {
Node* parent_node = InspectorDOMAgent::InnerParentNode(node);
if (HasBreakpoint(node, NodeRemoved))
@@ -561,7 +567,8 @@ void InspectorDOMDebuggerAgent::BreakProgramOnDOMEvent(Node* target,
if (!insertion)
breakpoint_owner = InspectorDOMAgent::InnerParentNode(target);
DCHECK(breakpoint_owner);
- while (!(dom_breakpoints_.at(breakpoint_owner) & (1 << breakpoint_type))) {
+ while (!(dom_breakpoints_.DeprecatedAtOrEmptyValue(breakpoint_owner) &
+ (1 << breakpoint_type))) {
Node* parent_node = InspectorDOMAgent::InnerParentNode(breakpoint_owner);
if (!parent_node)
break;
@@ -589,13 +596,14 @@ bool InspectorDOMDebuggerAgent::HasBreakpoint(Node* node, int type) {
return false;
uint32_t root_bit = 1 << type;
uint32_t derived_bit = root_bit << domBreakpointDerivedTypeShift;
- return dom_breakpoints_.at(node) & (root_bit | derived_bit);
+ return dom_breakpoints_.DeprecatedAtOrEmptyValue(node) &
+ (root_bit | derived_bit);
}
void InspectorDOMDebuggerAgent::UpdateSubtreeBreakpoints(Node* node,
uint32_t root_mask,
bool set) {
- uint32_t old_mask = dom_breakpoints_.at(node);
+ uint32_t old_mask = dom_breakpoints_.DeprecatedAtOrEmptyValue(node);
uint32_t derived_mask = root_mask << domBreakpointDerivedTypeShift;
uint32_t new_mask = set ? old_mask | derived_mask : old_mask & ~derived_mask;
if (new_mask)
@@ -793,13 +801,21 @@ void InspectorDOMDebuggerAgent::DidRemoveBreakpoint() {
}
void InspectorDOMDebuggerAgent::SetEnabled(bool enabled) {
- enabled_.Set(enabled);
- if (enabled)
+ if (enabled && !enabled_.Get()) {
instrumenting_agents_->AddInspectorDOMDebuggerAgent(this);
- else
+ dom_agent_->AddDOMListener(this);
+ enabled_.Set(true);
+ } else if (!enabled && enabled_.Get()) {
instrumenting_agents_->RemoveInspectorDOMDebuggerAgent(this);
+ dom_agent_->RemoveDOMListener(this);
+ enabled_.Set(false);
+ }
}
+void InspectorDOMDebuggerAgent::DidAddDocument(Document* document) {}
+
+void InspectorDOMDebuggerAgent::DidModifyDOMAttr(Element* element) {}
+
void InspectorDOMDebuggerAgent::DidCommitLoadForLocalFrame(LocalFrame*) {
dom_breakpoints_.clear();
}
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 c822806948a..484c72a9932 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
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_DOM_DEBUGGER_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_DOM_DEBUGGER_AGENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_event_listener_info.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -58,7 +57,8 @@ class DictionaryValue;
}
class CORE_EXPORT InspectorDOMDebuggerAgent final
- : public InspectorBaseAgent<protocol::DOMDebugger::Metainfo> {
+ : public InspectorBaseAgent<protocol::DOMDebugger::Metainfo>,
+ public InspectorDOMAgent::DOMListener {
public:
static void EventListenersInfoForTarget(v8::Isolate*,
v8::Local<v8::Value>,
@@ -67,6 +67,9 @@ class CORE_EXPORT InspectorDOMDebuggerAgent final
InspectorDOMDebuggerAgent(v8::Isolate*,
InspectorDOMAgent*,
v8_inspector::V8InspectorSession*);
+ InspectorDOMDebuggerAgent(const InspectorDOMDebuggerAgent&) = delete;
+ InspectorDOMDebuggerAgent& operator=(const InspectorDOMDebuggerAgent&) =
+ delete;
~InspectorDOMDebuggerAgent() override;
void Trace(Visitor*) const override;
@@ -99,7 +102,7 @@ class CORE_EXPORT InspectorDOMDebuggerAgent final
void WillInsertDOMNode(Node* parent);
void DidInvalidateStyleAttr(Node*);
void DidInsertDOMNode(Node*);
- void WillRemoveDOMNode(Node*);
+ void CharacterDataModified(CharacterData*);
void DidRemoveDOMNode(Node*);
void WillModifyDOMAttr(Element*, const AtomicString&, const AtomicString&);
void WillSendXMLHttpOrFetchNetworkRequest(const String& url);
@@ -169,6 +172,11 @@ class CORE_EXPORT InspectorDOMDebuggerAgent final
void DidRemoveBreakpoint();
void SetEnabled(bool);
+ // InspectorDOMAgent::DOMListener implementation
+ void DidAddDocument(Document*) override;
+ void WillRemoveDOMNode(Node*) override;
+ void DidModifyDOMAttr(Element*) override;
+
std::unique_ptr<protocol::DOMDebugger::EventListener>
BuildObjectForEventListener(v8::Local<v8::Context>,
const V8EventListenerInfo&,
@@ -183,7 +191,6 @@ class CORE_EXPORT InspectorDOMDebuggerAgent final
InspectorAgentState::BooleanMap xhr_breakpoints_;
InspectorAgentState::BooleanMap event_listener_breakpoints_;
InspectorAgentState::BooleanMap csp_violation_breakpoints_;
- DISALLOW_COPY_AND_ASSIGN(InspectorDOMDebuggerAgent);
};
} // namespace blink
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 e6b149c3123..69e5d8c0b2b 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
@@ -61,7 +61,8 @@ std::unique_ptr<protocol::Array<double>> BuildRectForLayout(const int x,
const int width,
const int height) {
return std::make_unique<std::vector<double>, std::initializer_list<double>>(
- {x, y, width, height});
+ {static_cast<double>(x), static_cast<double>(y),
+ static_cast<double>(width), static_cast<double>(height)});
}
Document* GetEmbeddedDocument(PaintLayer* layer) {
@@ -398,6 +399,7 @@ void InspectorDOMSnapshotAgent::VisitDocument(Document* document) {
.setParentIndex(std::make_unique<protocol::Array<int>>())
.setNodeType(std::make_unique<protocol::Array<int>>())
.setNodeName(std::make_unique<protocol::Array<int>>())
+ .setShadowRootType(StringData())
.setNodeValue(std::make_unique<protocol::Array<int>>())
.setBackendNodeId(std::make_unique<protocol::Array<int>>())
.setAttributes(
@@ -464,8 +466,11 @@ void InspectorDOMSnapshotAgent::VisitDocument(Document* document) {
}
auto* node_names = document_->getNodes()->getNodeName(nullptr);
- for (DOMTreeIterator it(document, node_names->size()); it.CurrentNode();
- it.Advance(node_names->size())) {
+ // Note: node_names->size() changes as the loop runs.
+ for (DOMTreeIterator it(document,
+ base::checked_cast<int>(node_names->size()));
+ it.CurrentNode();
+ it.Advance(base::checked_cast<int>(node_names->size()))) {
DCHECK(!it.CurrentNode()->IsInUserAgentShadowRoot());
VisitNode(it.CurrentNode(), it.ParentNodeId(), contrast);
}
@@ -500,6 +505,10 @@ void InspectorDOMSnapshotAgent::VisitNode(Node* node,
static_cast<int>(node->getNodeType()));
nodes->getNodeName(nullptr)->emplace_back(AddString(node->nodeName()));
nodes->getNodeValue(nullptr)->emplace_back(AddString(node_value));
+ if (node->IsInShadowTree()) {
+ SetRare(nodes->getShadowRootType(nullptr), index,
+ InspectorDOMAgent::GetShadowRootType(node->ContainingShadowRoot()));
+ }
nodes->getBackendNodeId(nullptr)->emplace_back(
IdentifiersFactory::IntIdForNode(node));
nodes->getAttributes(nullptr)->emplace_back(
@@ -507,11 +516,13 @@ void InspectorDOMSnapshotAgent::VisitNode(Node* node,
BuildLayoutTreeNode(node->GetLayoutObject(), node, index, contrast);
if (origin_url_map_ && origin_url_map_->Contains(backend_node_id)) {
- String origin_url = origin_url_map_->at(backend_node_id);
+ String origin_url =
+ origin_url_map_->DeprecatedAtOrEmptyValue(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) {
+ if (!node->parentNode() ||
+ origin_url_map_->DeprecatedAtOrEmptyValue(
+ DOMNodeIds::IdForNode(node->parentNode())) != origin_url) {
SetRare(nodes->getOriginURL(nullptr), index, origin_url);
}
}
@@ -524,7 +535,7 @@ void InspectorDOMSnapshotAgent::VisitNode(Node* node,
if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
if (Document* doc = frame_owner->contentDocument()) {
SetRare(nodes->getContentDocumentIndex(nullptr), index,
- document_order_map_.at(doc));
+ document_order_map_.DeprecatedAtOrEmptyValue(doc));
}
}
@@ -665,7 +676,7 @@ int InspectorDOMSnapshotAgent::BuildLayoutTreeNode(
if (paint_order_map_) {
PaintLayer* paint_layer = layout_object->EnclosingLayer();
DCHECK(paint_order_map_->Contains(paint_layer));
- int paint_order = paint_order_map_->at(paint_layer);
+ int paint_order = paint_order_map_->DeprecatedAtOrEmptyValue(paint_layer);
layout_tree_snapshot->getPaintOrders(nullptr)->emplace_back(paint_order);
}
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 6bc2083c6da..258ed898557 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_DOM_SNAPSHOT_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_DOM_SNAPSHOT_AGENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
@@ -29,6 +28,9 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
: public InspectorBaseAgent<protocol::DOMSnapshot::Metainfo> {
public:
InspectorDOMSnapshotAgent(InspectedFrames*, InspectorDOMDebuggerAgent*);
+ InspectorDOMSnapshotAgent(const InspectorDOMSnapshotAgent&) = delete;
+ InspectorDOMSnapshotAgent& operator=(const InspectorDOMSnapshotAgent&) =
+ delete;
~InspectorDOMSnapshotAgent() override;
void Trace(Visitor*) const override;
@@ -135,8 +137,6 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
Member<InspectedFrames> inspected_frames_;
Member<InspectorDOMDebuggerAgent> dom_debugger_agent_;
InspectorAgentState::Boolean enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(InspectorDOMSnapshotAgent);
};
} // namespace blink
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 77f145b6b33..7edd19f008f 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
@@ -20,6 +20,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/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h"
@@ -55,9 +56,7 @@ InspectorEmulationAgent::InspectorEmulationAgent(
/*default_value=*/WTF::String()),
locale_override_(&agent_state_, /*default_value=*/WTF::String()),
virtual_time_budget_(&agent_state_, /*default_value*/ 0.0),
- virtual_time_budget_initial_offset_(&agent_state_, /*default_value=*/0.0),
initial_virtual_time_(&agent_state_, /*default_value=*/0.0),
- virtual_time_offset_(&agent_state_, /*default_value=*/0.0),
virtual_time_policy_(&agent_state_, /*default_value=*/WTF::String()),
virtual_time_task_starvation_count_(&agent_state_, /*default_value=*/0),
wait_for_navigation_(&agent_state_, /*default_value=*/false),
@@ -123,11 +122,6 @@ void InspectorEmulationAgent::Restore() {
if (virtual_time_policy_.Get().IsNull())
return;
- // Tell the scheduler about the saved virtual time progress to ensure that
- // virtual time monotonically advances despite the cross origin navigation.
- // This should be done regardless of the virtual time mode.
- web_local_frame_->View()->Scheduler()->SetInitialVirtualTimeOffset(
- base::TimeDelta::FromMillisecondsD(virtual_time_offset_.Get()));
// Preserve wait for navigation in all modes.
bool wait_for_navigation = wait_for_navigation_.Get();
@@ -146,9 +140,7 @@ void InspectorEmulationAgent::Restore() {
}
// Calculate remaining budget for the advancing modes.
- double budget_remaining = virtual_time_budget_.Get() +
- virtual_time_budget_initial_offset_.Get() -
- virtual_time_offset_.Get();
+ double budget_remaining = virtual_time_budget_.Get();
DCHECK_GE(budget_remaining, 0);
setVirtualTimePolicy(virtual_time_policy_.Get(), budget_remaining,
@@ -375,9 +367,6 @@ Response InspectorEmulationAgent::setVirtualTimePolicy(
if (virtual_time_budget_ms.isJust()) {
new_policy.virtual_time_budget_ms = virtual_time_budget_ms.fromJust();
virtual_time_budget_.Set(*new_policy.virtual_time_budget_ms);
- // Record the current virtual time offset so Restore can compute how much
- // budget is left.
- virtual_time_budget_initial_offset_.Set(virtual_time_offset_.Get());
} else {
virtual_time_budget_.Clear();
}
@@ -435,7 +424,7 @@ void InspectorEmulationAgent::ApplyVirtualTimePolicy(
WTF::Bind(&InspectorEmulationAgent::VirtualTimeBudgetExpired,
WrapWeakPersistent(this)));
for (DocumentLoader* loader : pending_document_loaders_)
- loader->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kNone);
pending_document_loaders_.clear();
}
if (new_policy.max_virtual_time_task_starvation_count) {
@@ -695,7 +684,7 @@ void InspectorEmulationAgent::WillCommitLoad(LocalFrame*,
protocol::Emulation::VirtualTimePolicyEnum::Pause) {
return;
}
- loader->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kStrict);
pending_document_loaders_.push_back(loader);
}
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 6faa428b6f7..8e0335fba50 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_EMULATION_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_EMULATION_AGENT_H_
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -34,6 +33,8 @@ class CORE_EXPORT InspectorEmulationAgent final
: public InspectorBaseAgent<protocol::Emulation::Metainfo> {
public:
explicit InspectorEmulationAgent(WebLocalFrameImpl*);
+ InspectorEmulationAgent(const InspectorEmulationAgent&) = delete;
+ InspectorEmulationAgent& operator=(const InspectorEmulationAgent&) = delete;
~InspectorEmulationAgent() override;
// protocol::Dispatcher::EmulationCommandHandler implementation.
@@ -150,16 +151,13 @@ class CORE_EXPORT InspectorEmulationAgent final
InspectorAgentState::String accept_language_override_;
InspectorAgentState::String locale_override_;
InspectorAgentState::Double virtual_time_budget_;
- InspectorAgentState::Double virtual_time_budget_initial_offset_;
InspectorAgentState::Double initial_virtual_time_;
- InspectorAgentState::Double virtual_time_offset_;
InspectorAgentState::String virtual_time_policy_;
InspectorAgentState::Integer virtual_time_task_starvation_count_;
InspectorAgentState::Boolean wait_for_navigation_;
InspectorAgentState::Boolean emulate_focus_;
InspectorAgentState::String timezone_id_override_;
InspectorAgentState::BooleanMap disabled_image_types_;
- DISALLOW_COPY_AND_ASSIGN(InspectorEmulationAgent);
};
} // namespace blink
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 01bd3002faa..16a0c57498f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_grid_auto_repeat_value.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
@@ -56,6 +56,8 @@ class PathBuilder {
public:
PathBuilder() : path_(protocol::ListValue::create()) {}
+ PathBuilder(const PathBuilder&) = delete;
+ PathBuilder& operator=(const PathBuilder&) = delete;
virtual ~PathBuilder() = default;
std::unique_ptr<protocol::ListValue> Release() { return std::move(path_); }
@@ -81,7 +83,6 @@ class PathBuilder {
size_t length);
std::unique_ptr<protocol::ListValue> path_;
- DISALLOW_COPY_AND_ASSIGN(PathBuilder);
};
void PathBuilder::AppendPathCommandAndPoints(const char* command,
@@ -289,7 +290,7 @@ void AppendStyleInfo(Node* node,
properties.push_back(CSSPropertyID::kMargin);
properties.push_back(CSSPropertyID::kBackgroundColor);
- for (size_t i = 0; i < properties.size(); ++i) {
+ for (wtf_size_t i = 0; i < properties.size(); ++i) {
const CSSValue* value = style->GetPropertyCSSValue(properties[i]);
if (!value)
continue;
@@ -522,6 +523,20 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridHighlightConfigInfo(
return grid_config_info;
}
+std::unique_ptr<protocol::DictionaryValue>
+BuildContainerQueryContainerHighlightConfigInfo(
+ const InspectorContainerQueryContainerHighlightConfig& container_config) {
+ std::unique_ptr<protocol::DictionaryValue> container_config_info =
+ protocol::DictionaryValue::create();
+
+ AppendLineStyleConfig(container_config.container_border,
+ container_config_info, "containerBorder");
+ AppendLineStyleConfig(container_config.descendant_border,
+ container_config_info, "descendantBorder");
+
+ return container_config_info;
+}
+
// Swaps |left| and |top| of an offset.
PhysicalOffset Transpose(PhysicalOffset& offset) {
return PhysicalOffset(offset.top, offset.left);
@@ -549,7 +564,7 @@ LayoutUnit TranslateRTLCoordinate(const LayoutObject* layout_object,
}
LayoutUnit GetPositionForTrackAt(const LayoutObject* layout_object,
- size_t index,
+ wtf_size_t index,
GridTrackSizingDirection direction,
const Vector<LayoutUnit>& positions) {
if (direction == kForRows)
@@ -570,7 +585,7 @@ LayoutUnit GetPositionForFirstTrack(const LayoutObject* layout_object,
LayoutUnit GetPositionForLastTrack(const LayoutObject* layout_object,
GridTrackSizingDirection direction,
const Vector<LayoutUnit>& positions) {
- size_t index = positions.size() - 1;
+ wtf_size_t index = positions.size() - 1;
return GetPositionForTrackAt(layout_object, index, direction, positions);
}
@@ -644,20 +659,22 @@ std::unique_ptr<protocol::ListValue> BuildGridTrackSizes(
GridTrackSizingDirection direction,
float scale,
LayoutUnit gap,
+ LayoutUnit rtl_offset,
const Vector<LayoutUnit>& positions,
const Vector<LayoutUnit>& alt_axis_positions,
const Vector<String>* authored_values) {
LayoutObject* layout_object = node->GetLayoutObject();
- bool is_rtl = direction == kForColumns &&
- !layout_object->StyleRef().IsLeftToRightDirection();
+ bool is_rtl = !layout_object->StyleRef().IsLeftToRightDirection();
std::unique_ptr<protocol::ListValue> sizes = protocol::ListValue::create();
- size_t track_count = positions.size();
+ wtf_size_t track_count = positions.size();
LayoutUnit alt_axis_pos = GetPositionForFirstTrack(
layout_object, direction == kForRows ? kForColumns : kForRows,
alt_axis_positions);
+ if (is_rtl && direction == kForRows)
+ alt_axis_pos += rtl_offset;
- for (size_t i = 1; i < track_count; i++) {
+ for (wtf_size_t i = 1; i < track_count; i++) {
LayoutUnit current_position =
GetPositionForTrackAt(layout_object, i, direction, positions);
LayoutUnit prev_position =
@@ -665,11 +682,11 @@ std::unique_ptr<protocol::ListValue> BuildGridTrackSizes(
LayoutUnit gap_offset = i < track_count - 1 ? gap : LayoutUnit();
LayoutUnit width = current_position - prev_position - gap_offset;
- if (is_rtl)
+ if (is_rtl && direction == kForColumns)
width = prev_position - current_position - gap_offset;
LayoutUnit main_axis_pos = prev_position + width / 2;
- if (is_rtl)
- main_axis_pos = prev_position - width / 2;
+ if (is_rtl && direction == kForColumns)
+ main_axis_pos = rtl_offset + prev_position - width / 2;
auto adjusted_size = AdjustForAbsoluteZoom::AdjustFloat(
width * scale, layout_object->StyleRef());
PhysicalOffset track_size_pos(main_axis_pos, alt_axis_pos);
@@ -692,30 +709,33 @@ std::unique_ptr<protocol::ListValue> BuildGridPositiveLineNumberPositions(
const LayoutUnit& grid_gap,
GridTrackSizingDirection direction,
float scale,
+ LayoutUnit rtl_offset,
const Vector<LayoutUnit>& positions,
const Vector<LayoutUnit>& alt_axis_positions) {
LayoutObject* layout_object = node->GetLayoutObject();
auto* grid_interface = ToInterface<LayoutNGGridInterface>(layout_object);
- bool is_rtl = direction == kForColumns &&
- !layout_object->StyleRef().IsLeftToRightDirection();
+ bool is_rtl = !layout_object->StyleRef().IsLeftToRightDirection();
std::unique_ptr<protocol::ListValue> number_positions =
protocol::ListValue::create();
- size_t track_count = positions.size();
+ wtf_size_t track_count = positions.size();
LayoutUnit alt_axis_pos = GetPositionForFirstTrack(
layout_object, direction == kForRows ? kForColumns : kForRows,
alt_axis_positions);
+ if (is_rtl && direction == kForRows)
+ alt_axis_pos += rtl_offset;
+
// Find index of the first explicit Grid Line.
- size_t first_explicit_index =
+ wtf_size_t first_explicit_index =
grid_interface->ExplicitGridStartForDirection(direction);
// Go line by line, calculating the offset to fall in the middle of gaps
// if needed.
- for (size_t i = first_explicit_index; i < track_count; ++i) {
+ for (wtf_size_t i = first_explicit_index; i < track_count; ++i) {
LayoutUnit gapOffset = grid_gap / 2;
- if (is_rtl)
+ if (is_rtl && direction == kForColumns)
gapOffset *= -1;
// No need for a gap offset if there is no gap, or the first line is
// explicit, or this is the last line.
@@ -724,6 +744,8 @@ std::unique_ptr<protocol::ListValue> BuildGridPositiveLineNumberPositions(
}
LayoutUnit offset =
GetPositionForTrackAt(layout_object, i, direction, positions);
+ if (is_rtl && direction == kForColumns)
+ offset += rtl_offset;
PhysicalOffset number_position(offset - gapOffset, alt_axis_pos);
if (direction == kForRows)
number_position = Transpose(number_position);
@@ -739,20 +761,22 @@ std::unique_ptr<protocol::ListValue> BuildGridNegativeLineNumberPositions(
const LayoutUnit& grid_gap,
GridTrackSizingDirection direction,
float scale,
+ LayoutUnit rtl_offset,
const Vector<LayoutUnit>& positions,
const Vector<LayoutUnit>& alt_axis_positions) {
LayoutObject* layout_object = node->GetLayoutObject();
auto* grid_interface = ToInterface<LayoutNGGridInterface>(layout_object);
- bool is_rtl = direction == kForColumns &&
- !layout_object->StyleRef().IsLeftToRightDirection();
+ bool is_rtl = !layout_object->StyleRef().IsLeftToRightDirection();
std::unique_ptr<protocol::ListValue> number_positions =
protocol::ListValue::create();
- size_t track_count = positions.size();
+ wtf_size_t track_count = positions.size();
LayoutUnit alt_axis_pos = GetPositionForLastTrack(
layout_object, direction == kForRows ? kForColumns : kForRows,
alt_axis_positions);
+ if (is_rtl && direction == kForRows)
+ alt_axis_pos += rtl_offset;
// This is the number of tracks from the start of the grid, to the end of the
// explicit grid (including any leading implicit tracks).
@@ -762,6 +786,8 @@ std::unique_ptr<protocol::ListValue> BuildGridNegativeLineNumberPositions(
{
LayoutUnit first_offset =
GetPositionForFirstTrack(layout_object, direction, positions);
+ if (is_rtl && direction == kForColumns)
+ first_offset += rtl_offset;
// Always start negative numbers at the first line.
std::unique_ptr<protocol::DictionaryValue> pos =
@@ -775,9 +801,9 @@ std::unique_ptr<protocol::ListValue> BuildGridNegativeLineNumberPositions(
// Then go line by line, calculating the offset to fall in the middle of gaps
// if needed.
- for (size_t i = 1; i <= explicit_grid_end_track_count; i++) {
+ for (wtf_size_t i = 1; i <= explicit_grid_end_track_count; i++) {
LayoutUnit gapOffset = grid_gap / 2;
- if (is_rtl)
+ if (is_rtl && direction == kForColumns)
gapOffset *= -1;
if (grid_gap == 0 ||
(i == explicit_grid_end_track_count && i == track_count - 1)) {
@@ -785,6 +811,8 @@ std::unique_ptr<protocol::ListValue> BuildGridNegativeLineNumberPositions(
}
LayoutUnit offset =
GetPositionForTrackAt(layout_object, i, direction, positions);
+ if (is_rtl && direction == kForColumns)
+ offset += rtl_offset;
PhysicalOffset number_position(offset - gapOffset, alt_axis_pos);
if (direction == kForRows)
number_position = Transpose(number_position);
@@ -886,7 +914,7 @@ std::unique_ptr<protocol::ListValue> BuildGridLineNames(
for (const auto& item : named_lines_map) {
const String& name = item.key;
- for (const size_t index : item.value) {
+ for (const wtf_size_t index : item.value) {
LayoutUnit track =
GetPositionForTrackAt(layout_object, index, direction, positions);
@@ -1210,6 +1238,13 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
auto column_gap = grid_interface->GridGap(kForColumns) +
grid_interface->GridItemOffset(kForColumns);
+ // In legacy grid the last column in rtl will go to the extent of the grid,
+ // all the way to the left. In NG, this is not the case, and will stop sooner
+ // if the tracks don't take up the full size of the grid.
+ LayoutUnit rtl_offset;
+ if (layout_object->IsLayoutNGGrid())
+ rtl_offset = To<LayoutBox>(layout_object)->LogicalWidth() - columns.back();
+
if (grid_highlight_config.show_track_sizes) {
Element* element = DynamicTo<Element>(node);
DCHECK(element);
@@ -1217,28 +1252,34 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
HeapHashMap<CSSPropertyName, Member<const CSSValue>> cascaded_values =
style_resolver.CascadedValuesForElement(element, kPseudoIdNone);
Vector<String> column_authored_values = GetAuthoredGridTrackSizes(
- cascaded_values.at(
+ cascaded_values.DeprecatedAtOrEmptyValue(
CSSPropertyName(CSSPropertyID::kGridTemplateColumns)),
grid_interface->AutoRepeatCountForDirection(kForColumns));
Vector<String> row_authored_values = GetAuthoredGridTrackSizes(
- cascaded_values.at(CSSPropertyName(CSSPropertyID::kGridTemplateRows)),
+ cascaded_values.DeprecatedAtOrEmptyValue(
+ CSSPropertyName(CSSPropertyID::kGridTemplateRows)),
grid_interface->AutoRepeatCountForDirection(kForRows));
grid_info->setValue(
"columnTrackSizes",
- BuildGridTrackSizes(node, kForColumns, scale, column_gap, columns, rows,
- &column_authored_values));
+ BuildGridTrackSizes(node, kForColumns, scale, column_gap, rtl_offset,
+ columns, rows, &column_authored_values));
grid_info->setValue(
"rowTrackSizes",
- BuildGridTrackSizes(node, kForRows, scale, row_gap, rows, columns,
- &row_authored_values));
+ BuildGridTrackSizes(node, kForRows, scale, row_gap, rtl_offset, rows,
+ columns, &row_authored_values));
}
+ bool is_ltr = layout_object->StyleRef().IsLeftToRightDirection();
+
PathBuilder row_builder;
PathBuilder row_gap_builder;
LayoutUnit row_left = columns.front();
+ if (!is_ltr) {
+ row_left += rtl_offset;
+ }
LayoutUnit row_width = columns.back() - columns.front();
- for (size_t i = 1; i < rows.size(); ++i) {
+ for (wtf_size_t i = 1; i < rows.size(); ++i) {
// Rows
PhysicalOffset position(row_left, rows.at(i - 1));
PhysicalSize size(row_width, rows.at(i) - rows.at(i - 1));
@@ -1266,15 +1307,15 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
PathBuilder column_gap_builder;
LayoutUnit column_top = rows.front();
LayoutUnit column_height = rows.back() - rows.front();
- bool is_ltr = layout_object->StyleRef().IsLeftToRightDirection();
- for (size_t i = 1; i < columns.size(); ++i) {
+ for (wtf_size_t i = 1; i < columns.size(); ++i) {
PhysicalSize size(columns.at(i) - columns.at(i - 1), column_height);
if (i != columns.size() - 1)
size.width -= column_gap;
LayoutUnit line_left =
GetPositionForTrackAt(layout_object, i - 1, kForColumns, columns);
- if (!is_ltr)
- line_left -= size.width;
+ if (!is_ltr) {
+ line_left += rtl_offset - size.width;
+ }
PhysicalOffset position(line_left, column_top);
PhysicalRect column(position, size);
FloatQuad column_quad = layout_object->LocalRectToAbsoluteQuad(column);
@@ -1288,6 +1329,8 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
GetPositionForTrackAt(layout_object, i, kForColumns, columns);
if (is_ltr)
gap_left -= column_gap;
+ else
+ gap_left += rtl_offset;
PhysicalOffset gap_position(gap_left, column_top);
PhysicalSize gap_size(column_gap, column_height);
PhysicalRect gap(gap_position, gap_size);
@@ -1301,24 +1344,26 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
// Positive Row and column Line positions
if (grid_highlight_config.show_positive_line_numbers) {
- grid_info->setValue("positiveRowLineNumberPositions",
- BuildGridPositiveLineNumberPositions(
- node, row_gap, kForRows, scale, rows, columns));
+ grid_info->setValue(
+ "positiveRowLineNumberPositions",
+ BuildGridPositiveLineNumberPositions(node, row_gap, kForRows, scale,
+ rtl_offset, rows, columns));
grid_info->setValue(
"positiveColumnLineNumberPositions",
BuildGridPositiveLineNumberPositions(node, column_gap, kForColumns,
- scale, columns, rows));
+ scale, rtl_offset, columns, rows));
}
// Negative Row and column Line positions
if (grid_highlight_config.show_negative_line_numbers) {
- grid_info->setValue("negativeRowLineNumberPositions",
- BuildGridNegativeLineNumberPositions(
- node, row_gap, kForRows, scale, rows, columns));
+ grid_info->setValue(
+ "negativeRowLineNumberPositions",
+ BuildGridNegativeLineNumberPositions(node, row_gap, kForRows, scale,
+ rtl_offset, rows, columns));
grid_info->setValue(
"negativeColumnLineNumberPositions",
BuildGridNegativeLineNumberPositions(node, column_gap, kForColumns,
- scale, columns, rows));
+ scale, rtl_offset, columns, rows));
}
// Area names
@@ -1637,8 +1682,8 @@ InspectorHighlight::InspectorHighlight(
show_extension_lines_(highlight_config.show_extension_lines),
show_accessibility_info_(highlight_config.show_accessibility_info),
color_format_(highlight_config.color_format) {
- DCHECK(node->GetDocument().Lifecycle().GetState() >=
- DocumentLifecycle::kLayoutClean);
+ DCHECK_GE(node->GetDocument().Lifecycle().GetState(),
+ DocumentLifecycle::kLayoutClean);
AppendPathsForShapeOutside(node, highlight_config);
AppendNodeHighlight(node, highlight_config);
auto* text_node = DynamicTo<Text>(node);
@@ -1688,7 +1733,7 @@ void InspectorHighlight::AppendDistanceInfo(Node* node) {
CSSComputedStyleDeclaration* style =
MakeGarbageCollected<CSSComputedStyleDeclaration>(node, true);
- for (size_t i = 0; i < style->length(); ++i) {
+ for (unsigned i = 0; i < style->length(); ++i) {
AtomicString name(style->item(i));
const CSSValue* value = style->GetPropertyCSSValue(
CssPropertyID(node->GetExecutionContext(), name));
@@ -1859,6 +1904,13 @@ void InspectorHighlight::AppendNodeHighlight(
node, *(highlight_config.flex_item_highlight_config), scale_));
}
}
+
+ if (highlight_config.container_query_container_highlight_config) {
+ container_query_container_info_ = protocol::ListValue::create();
+ container_query_container_info_->pushValue(BuildContainerQueryContainerInfo(
+ node, *(highlight_config.container_query_container_highlight_config),
+ scale_));
+ }
}
std::unique_ptr<protocol::DictionaryValue> InspectorHighlight::AsProtocolValue()
@@ -1908,6 +1960,11 @@ std::unique_ptr<protocol::DictionaryValue> InspectorHighlight::AsProtocolValue()
object->setValue("flexInfo", flex_container_info_->clone());
if (flex_item_info_ && flex_item_info_->size() > 0)
object->setValue("flexItemInfo", flex_item_info_->clone());
+ if (container_query_container_info_ &&
+ container_query_container_info_->size() > 0) {
+ object->setValue("containerQueryInfo",
+ container_query_container_info_->clone());
+ }
return object;
}
@@ -2180,6 +2237,93 @@ std::unique_ptr<protocol::DictionaryValue> InspectorScrollSnapHighlight(
return scroll_snap_info;
}
+Vector<FloatQuad> GetContainerQueryingDescendantQuads(Element* container) {
+ Vector<FloatQuad> descendant_quads;
+ for (Element* descendant :
+ InspectorDOMAgent::GetContainerQueryingDescendants(container)) {
+ LayoutBox* layout_box = descendant->GetLayoutBox();
+ if (!layout_box)
+ continue;
+ auto content_box = layout_box->PhysicalContentBoxRect();
+ FloatQuad content_quad = layout_box->LocalRectToAbsoluteQuad(content_box);
+ descendant_quads.push_back(content_quad);
+ }
+
+ return descendant_quads;
+}
+
+std::unique_ptr<protocol::DictionaryValue> BuildContainerQueryContainerInfo(
+ Node* node,
+ const InspectorContainerQueryContainerHighlightConfig&
+ container_query_container_highlight_config,
+ float scale) {
+ if (!node)
+ return nullptr;
+
+ LayoutBox* layout_box = node->GetLayoutBox();
+ if (!layout_box)
+ return nullptr;
+
+ LocalFrameView* containing_view = node->GetDocument().View();
+ if (!containing_view)
+ return nullptr;
+
+ std::unique_ptr<protocol::DictionaryValue> container_query_container_info =
+ protocol::DictionaryValue::create();
+
+ PathBuilder container_builder;
+ auto content_box = layout_box->PhysicalContentBoxRect();
+ FloatQuad content_quad = layout_box->LocalRectToAbsoluteQuad(content_box);
+ FrameQuadToViewport(containing_view, content_quad);
+ container_builder.AppendPath(QuadToPath(content_quad), scale);
+ container_query_container_info->setValue("containerBorder",
+ container_builder.Release());
+
+ auto* element = DynamicTo<Element>(node);
+ bool include_descendants =
+ container_query_container_highlight_config.descendant_border &&
+ !container_query_container_highlight_config.descendant_border
+ ->IsTransparent();
+ if (element && include_descendants) {
+ std::unique_ptr<protocol::ListValue> descendants_info =
+ protocol::ListValue::create();
+ for (auto& descendant_quad : GetContainerQueryingDescendantQuads(element)) {
+ std::unique_ptr<protocol::DictionaryValue> descendant_info =
+ protocol::DictionaryValue::create();
+ descendant_info->setValue(
+ "descendantBorder",
+ BuildPathFromQuad(containing_view, descendant_quad));
+ descendants_info->pushValue(std::move(descendant_info));
+ }
+ container_query_container_info->setArray("queryingDescendants",
+ std::move(descendants_info));
+ }
+
+ container_query_container_info->setValue(
+ "containerQueryContainerHighlightConfig",
+ BuildContainerQueryContainerHighlightConfigInfo(
+ container_query_container_highlight_config));
+
+ return container_query_container_info;
+}
+
+std::unique_ptr<protocol::DictionaryValue> InspectorContainerQueryHighlight(
+ Node* node,
+ const InspectorContainerQueryContainerHighlightConfig& config) {
+ LocalFrameView* frame_view = node->GetDocument().View();
+ if (!frame_view)
+ return nullptr;
+
+ std::unique_ptr<protocol::DictionaryValue> container_query_container_info =
+ BuildContainerQueryContainerInfo(node, config,
+ DeviceScaleFromFrameView(frame_view));
+
+ if (!container_query_container_info)
+ return nullptr;
+
+ return container_query_container_info;
+}
+
// static
InspectorHighlightConfig InspectorHighlight::DefaultConfig() {
InspectorHighlightConfig config;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
index 5fa97abda61..2c29962611f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
@@ -115,6 +115,16 @@ struct CORE_EXPORT InspectorScrollSnapContainerHighlightConfig {
Color scroll_padding_color;
};
+struct CORE_EXPORT InspectorContainerQueryContainerHighlightConfig {
+ USING_FAST_MALLOC(InspectorContainerQueryContainerHighlightConfig);
+
+ public:
+ InspectorContainerQueryContainerHighlightConfig() = default;
+
+ absl::optional<LineStyle> container_border;
+ absl::optional<LineStyle> descendant_border;
+};
+
struct CORE_EXPORT InspectorFlexItemHighlightConfig {
USING_FAST_MALLOC(InspectorFlexItemHighlightConfig);
@@ -156,6 +166,8 @@ struct CORE_EXPORT InspectorHighlightConfig {
std::unique_ptr<InspectorFlexContainerHighlightConfig>
flex_container_highlight_config;
std::unique_ptr<InspectorFlexItemHighlightConfig> flex_item_highlight_config;
+ std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>
+ container_query_container_highlight_config;
};
struct InspectorHighlightContrastInfo {
@@ -252,6 +264,7 @@ class CORE_EXPORT InspectorHighlight : public InspectorHighlightBase {
std::unique_ptr<protocol::ListValue> grid_info_;
std::unique_ptr<protocol::ListValue> flex_container_info_;
std::unique_ptr<protocol::ListValue> flex_item_info_;
+ std::unique_ptr<protocol::ListValue> container_query_container_info_;
bool show_rulers_;
bool show_extension_lines_;
bool show_accessibility_info_;
@@ -270,10 +283,21 @@ std::unique_ptr<protocol::DictionaryValue> InspectorScrollSnapHighlight(
Node* node,
const InspectorScrollSnapContainerHighlightConfig& config);
-// CORE_EXPORT is required to make the function available for unit tests.
+std::unique_ptr<protocol::DictionaryValue> InspectorContainerQueryHighlight(
+ Node* node,
+ const InspectorContainerQueryContainerHighlightConfig& config);
+
+// CORE_EXPORT is required to make these functions available for unit tests.
std::unique_ptr<protocol::DictionaryValue> CORE_EXPORT
BuildSnapContainerInfo(Node* node);
+std::unique_ptr<protocol::DictionaryValue> CORE_EXPORT
+BuildContainerQueryContainerInfo(
+ Node* node,
+ const InspectorContainerQueryContainerHighlightConfig&
+ container_query_container_highlight_config,
+ float scale);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_HIGHLIGHT_H_
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight_test.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight_test.cc
index 74232f63a4e..0075997a9af 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight_test.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight_test.cc
@@ -10,6 +10,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/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/inspector_protocol/crdtp/json.h"
#include "third_party/inspector_protocol/crdtp/span.h"
@@ -34,7 +35,11 @@ void AssertValueEqualsJSON(const std::unique_ptr<protocol::Value>& actual_value,
} // namespace
-class InspectorHighlightTest : public testing::Test {
+class InspectorHighlightTest : public testing::Test,
+ private ScopedCSSContainerQueriesForTest {
+ public:
+ InspectorHighlightTest() : ScopedCSSContainerQueriesForTest(true) {}
+
protected:
void SetUp() override;
@@ -151,4 +156,84 @@ TEST_F(InspectorHighlightTest, BuildSnapContainerInfoTopLevelSnapAreas) {
expected_container);
}
+TEST_F(InspectorHighlightTest,
+ BuildContainerQueryContainerInfoWithoutDescendants) {
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ #container {
+ width: 400px;
+ height: 500px;
+ container-type: inline-size;
+ }
+ </style>
+ <div id="container"></div>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhasesForTest();
+ Element* container = GetDocument().getElementById("container");
+ auto info = BuildContainerQueryContainerInfo(
+ container, InspectorContainerQueryContainerHighlightConfig(), 1.0f);
+ EXPECT_TRUE(info);
+
+ protocol::ErrorSupport errors;
+ std::string expected_container = R"JSON(
+ {
+ "containerBorder":["M",8,8,"L",408,8,"L",408,508,"L",8,508,"Z"],
+ "containerQueryContainerHighlightConfig": {}
+ }
+ )JSON";
+ AssertValueEqualsJSON(protocol::ValueConversions<protocol::Value>::fromValue(
+ info.get(), &errors),
+ expected_container);
+}
+
+TEST_F(InspectorHighlightTest,
+ BuildContainerQueryContainerInfoWithDescendants) {
+ GetDocument().body()->setInnerHTML(R"HTML(
+ <style>
+ #container {
+ width: 400px;
+ height: 500px;
+ container-type: inline-size;
+ }
+ @container (min-width: 100px) {
+ .item {
+ width: 100px;
+ height: 100px;
+ }
+ }
+ </style>
+ <div id="container"><div class="item"></div></div>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhasesForTest();
+
+ Element* container = GetDocument().getElementById("container");
+
+ LineStyle line_style;
+ line_style.color = Color(1, 1, 1);
+ InspectorContainerQueryContainerHighlightConfig highlight_config;
+ highlight_config.descendant_border = line_style;
+ auto info =
+ BuildContainerQueryContainerInfo(container, highlight_config, 1.0f);
+ EXPECT_TRUE(info);
+
+ protocol::ErrorSupport errors;
+ std::string expected_container = R"JSON(
+ {
+ "containerBorder":["M",8,8,"L",408,8,"L",408,508,"L",8,508,"Z"],
+ "containerQueryContainerHighlightConfig": {
+ "descendantBorder": {
+ "color": "#010101",
+ "pattern": ""
+ }
+ },
+ "queryingDescendants": [ {
+ "descendantBorder": [ "M", 8, 8, "L", 108, 8, "L", 108, 108, "L", 8, 108, "Z" ]
+ } ]
+ }
+ )JSON";
+ AssertValueEqualsJSON(protocol::ValueConversions<protocol::Value>::fromValue(
+ info.get(), &errors),
+ expected_container);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_history.h b/chromium/third_party/blink/renderer/core/inspector/inspector_history.h
index 05ae27cec4f..11dcb0822cb 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_history.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_history.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_HISTORY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_HISTORY_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -69,6 +68,8 @@ class CORE_EXPORT InspectorHistory final
};
InspectorHistory();
+ InspectorHistory(const InspectorHistory&) = delete;
+ InspectorHistory& operator=(const InspectorHistory&) = delete;
void Trace(Visitor*) const;
bool Perform(Action*, ExceptionState&);
@@ -82,8 +83,6 @@ class CORE_EXPORT InspectorHistory final
private:
HeapVector<Member<Action>> history_;
wtf_size_t after_last_action_index_;
-
- DISALLOW_COPY_AND_ASSIGN(InspectorHistory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_io_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_io_agent.h
index 61a5a96117d..f0613edbb0f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_io_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_io_agent.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_IO_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_IO_AGENT_H_
-#include "base/macros.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/IO.h"
@@ -25,6 +24,8 @@ class CORE_EXPORT InspectorIOAgent final
: public InspectorBaseAgent<protocol::IO::Metainfo> {
public:
InspectorIOAgent(v8::Isolate*, v8_inspector::V8InspectorSession*);
+ InspectorIOAgent(const InspectorIOAgent&) = delete;
+ InspectorIOAgent& operator=(const InspectorIOAgent&) = delete;
~InspectorIOAgent() override;
private:
@@ -36,7 +37,6 @@ class CORE_EXPORT InspectorIOAgent final
v8::Isolate* isolate_;
v8_inspector::V8InspectorSession* v8_session_;
- DISALLOW_COPY_AND_ASSIGN(InspectorIOAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc
index 5f05fb0146e..782b4050a7d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_issue_conversion.h"
#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -431,10 +432,15 @@ ConvertInspectorIssueToProtocolFormat(InspectorIssue* issue) {
issueDetails.setLowTextContrastIssueDetails(std::move(lowContrastDetails));
}
- return protocol::Audits::InspectorIssue::create()
- .setCode(InspectorIssueCodeValue(issue->Code()))
- .setDetails(issueDetails.build())
- .build();
+ auto final_issue = protocol::Audits::InspectorIssue::create()
+ .setCode(InspectorIssueCodeValue(issue->Code()))
+ .setDetails(issueDetails.build())
+ .build();
+ if (issue->Details()->issue_id) {
+ String issue_id = String::FromUTF8(issue->Details()->issue_id->ToString());
+ final_issue->setIssueId(issue_id);
+ }
+ return final_issue;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc
index d543b027215..cbd625ccdec 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc
@@ -60,12 +60,12 @@ void InspectorIssueStorage::Clear() {
issues_.clear();
}
-size_t InspectorIssueStorage::size() const {
+wtf_size_t InspectorIssueStorage::size() const {
return issues_.size();
}
protocol::Audits::InspectorIssue* InspectorIssueStorage::at(
- size_t index) const {
+ wtf_size_t index) const {
return issues_[index].get();
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h
index c8ea667e0f5..ac3c1973115 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_ISSUE_STORAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_ISSUE_STORAGE_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -27,6 +26,8 @@ class InspectorIssue;
class CORE_EXPORT InspectorIssueStorage {
public:
InspectorIssueStorage();
+ InspectorIssueStorage(const InspectorIssueStorage&) = delete;
+ InspectorIssueStorage& operator=(const InspectorIssueStorage&) = delete;
void AddInspectorIssue(CoreProbeSink*, InspectorIssue*);
void AddInspectorIssue(CoreProbeSink*, mojom::blink::InspectorIssueInfoPtr);
@@ -36,8 +37,8 @@ class CORE_EXPORT InspectorIssueStorage {
void AddInspectorIssue(CoreProbeSink*, AuditsIssue);
void Clear();
- size_t size() const;
- protocol::Audits::InspectorIssue* at(size_t index) const;
+ wtf_size_t size() const;
+ protocol::Audits::InspectorIssue* at(wtf_size_t index) const;
virtual ~InspectorIssueStorage();
@@ -45,8 +46,6 @@ class CORE_EXPORT InspectorIssueStorage {
void AddInspectorIssue(CoreProbeSink*,
std::unique_ptr<protocol::Audits::InspectorIssue>);
Deque<std::unique_ptr<protocol::Audits::InspectorIssue>> issues_;
-
- DISALLOW_COPY_AND_ASSIGN(InspectorIssueStorage);
};
} // 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 eb7eb584ee3..30f7e52d7ed 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
@@ -33,7 +33,6 @@
#include <memory>
-#include "base/stl_util.h"
#include "cc/base/features.h"
#include "cc/base/region.h"
#include "cc/layers/picture_layer.h"
@@ -114,7 +113,7 @@ BuildScrollRectsForLayer(const cc::Layer* layer, bool report_wheel_scrollers) {
std::make_unique<protocol::Array<protocol::LayerTree::ScrollRect>>();
const cc::Region& non_fast_scrollable_rects =
layer->non_fast_scrollable_region();
- for (const gfx::Rect& rect : non_fast_scrollable_rects) {
+ for (gfx::Rect rect : non_fast_scrollable_rects) {
scroll_rects->emplace_back(BuildScrollRect(
IntRect(rect),
protocol::LayerTree::ScrollRect::TypeEnum::RepaintsOnScroll));
@@ -122,7 +121,7 @@ BuildScrollRectsForLayer(const cc::Layer* layer, bool report_wheel_scrollers) {
const cc::Region& touch_event_handler_regions =
layer->touch_action_region().GetAllRegions();
- for (const gfx::Rect& rect : touch_event_handler_regions) {
+ for (gfx::Rect rect : touch_event_handler_regions) {
scroll_rects->emplace_back(BuildScrollRect(
IntRect(rect),
protocol::LayerTree::ScrollRect::TypeEnum::TouchEventHandler));
@@ -130,7 +129,7 @@ BuildScrollRectsForLayer(const cc::Layer* layer, bool report_wheel_scrollers) {
if (base::FeatureList::IsEnabled(::features::kWheelEventRegions)) {
const cc::Region& wheel_event_handler_region = layer->wheel_event_region();
- for (const gfx::Rect& rect : wheel_event_handler_region) {
+ for (gfx::Rect rect : wheel_event_handler_region) {
scroll_rects->emplace_back(BuildScrollRect(
IntRect(rect),
protocol::LayerTree::ScrollRect::TypeEnum::WheelEventHandler));
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h
index 6dd56908ea4..93681c339db 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h
@@ -30,7 +30,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_LAYER_TREE_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_LAYER_TREE_AGENT_H_
-#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/inspector/inspector_base_agent.h"
@@ -58,6 +57,8 @@ class CORE_EXPORT InspectorLayerTreeAgent final
};
InspectorLayerTreeAgent(InspectedFrames*, Client*);
+ InspectorLayerTreeAgent(const InspectorLayerTreeAgent&) = delete;
+ InspectorLayerTreeAgent& operator=(const InspectorLayerTreeAgent&) = delete;
~InspectorLayerTreeAgent() override;
void Trace(Visitor*) const override;
@@ -121,7 +122,6 @@ class CORE_EXPORT InspectorLayerTreeAgent final
typedef HashMap<String, scoped_refptr<PictureSnapshot>> SnapshotById;
SnapshotById snapshot_by_id_;
bool suppress_layer_paint_events_;
- DISALLOW_COPY_AND_ASSIGN(InspectorLayerTreeAgent);
};
} // namespace blink
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 70f4b344e0a..6e0f99d3173 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_LOG_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_LOG_AGENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
@@ -27,6 +26,8 @@ class CORE_EXPORT InspectorLogAgent
InspectorLogAgent(ConsoleMessageStorage*,
PerformanceMonitor*,
v8_inspector::V8InspectorSession*);
+ InspectorLogAgent(const InspectorLogAgent&) = delete;
+ InspectorLogAgent& operator=(const InspectorLogAgent&) = delete;
~InspectorLogAgent() override;
void Trace(Visitor*) const override;
@@ -58,7 +59,6 @@ class CORE_EXPORT InspectorLogAgent
v8_inspector::V8InspectorSession* v8_session_;
InspectorAgentState::Boolean enabled_;
InspectorAgentState::DoubleMap violation_thresholds_;
- DISALLOW_COPY_AND_ASSIGN(InspectorLogAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
index 4993ce62e62..69b2b3be001 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
namespace blink {
@@ -80,12 +81,21 @@ std::unique_ptr<protocol::Array<To>> ConvertVector(const Vector<From>& from) {
} // namespace
-InspectorMediaAgent::InspectorMediaAgent(InspectedFrames* inspected_frames)
- : frame_(inspected_frames->Root()),
- enabled_(&agent_state_, /*default_value = */ false) {}
+InspectorMediaAgent::InspectorMediaAgent(InspectedFrames* inspected_frames,
+ WorkerGlobalScope* worker_global_scope)
+ : inspected_frames_(inspected_frames),
+ worker_global_scope_(worker_global_scope),
+ enabled_(&agent_state_, /* default_value = */ false) {}
InspectorMediaAgent::~InspectorMediaAgent() = default;
+ExecutionContext* InspectorMediaAgent::GetTargetExecutionContext() const {
+ if (worker_global_scope_)
+ return worker_global_scope_;
+ DCHECK(inspected_frames_);
+ return inspected_frames_->Root()->DomWindow()->GetExecutionContext();
+}
+
void InspectorMediaAgent::Restore() {
if (!enabled_.Get())
return;
@@ -94,8 +104,7 @@ void InspectorMediaAgent::Restore() {
void InspectorMediaAgent::RegisterAgent() {
instrumenting_agents_->AddInspectorMediaAgent(this);
- auto* cache = MediaInspectorContextImpl::From(
- *frame_->DomWindow()->GetExecutionContext());
+ auto* cache = MediaInspectorContextImpl::From(*GetTargetExecutionContext());
Vector<WebString> players = cache->AllPlayerIdsAndMarkSent();
PlayersCreated(players);
for (const auto& player_id : players) {
@@ -165,7 +174,8 @@ void InspectorMediaAgent::PlayersCreated(const Vector<WebString>& player_ids) {
}
void InspectorMediaAgent::Trace(Visitor* visitor) const {
- visitor->Trace(frame_);
+ visitor->Trace(inspected_frames_);
+ visitor->Trace(worker_global_scope_);
InspectorBaseAgent::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h
index 4203e3bd03c..5d4c59d6f2c 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h
@@ -12,14 +12,20 @@
namespace blink {
-class LocalFrame;
+class InspectedFrames;
+class WorkerGlobalScope;
+class ExecutionContext;
class CORE_EXPORT InspectorMediaAgent final
: public InspectorBaseAgent<protocol::Media::Metainfo> {
public:
- explicit InspectorMediaAgent(InspectedFrames*);
+ explicit InspectorMediaAgent(InspectedFrames*, WorkerGlobalScope*);
+ InspectorMediaAgent(const InspectorMediaAgent&) = delete;
+ InspectorMediaAgent& operator=(const InspectorMediaAgent&) = delete;
~InspectorMediaAgent() override;
+ ExecutionContext* GetTargetExecutionContext() const;
+
// BaseAgent methods.
void Restore() override;
@@ -43,9 +49,12 @@ class CORE_EXPORT InspectorMediaAgent final
private:
void RegisterAgent();
- Member<LocalFrame> frame_;
+ // This is null while inspecting workers.
+ Member<InspectedFrames> inspected_frames_;
+ // This is null while inspecting frames.
+ Member<WorkerGlobalScope> worker_global_scope_;
+
InspectorAgentState::Boolean enabled_;
- DISALLOW_COPY_AND_ASSIGN(InspectorMediaAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
index a7ff21b43a6..4457f0ea5e2 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
@@ -189,14 +189,15 @@ void MediaInspectorContextImpl::SetPlayerProperties(
WebString playerId,
const InspectorPlayerProperties& props) {
const auto& player = players_.find(playerId);
+ Vector<InspectorPlayerProperty> properties;
if (player != players_.end()) {
for (const auto& property : props)
- player->value->properties.insert(property.name, property);
- }
+ player->value->properties.Set(property.name, property);
- Vector<InspectorPlayerProperty> vector =
- Iter2Vector<InspectorPlayerProperty>(props);
- probe::PlayerPropertiesChanged(GetSupplementable(), playerId, vector);
+ properties.AppendRange(player->value->properties.Values().begin(),
+ player->value->properties.Values().end());
+ }
+ probe::PlayerPropertiesChanged(GetSupplementable(), playerId, properties);
}
void MediaInspectorContextImpl::NotifyPlayerMessages(
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.cc
index 8f2ae0088b5..04e97ce21a1 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.cc
@@ -200,13 +200,13 @@ Vector<String> InspectorMemoryAgent::Symbolize(
.ToString()
.c_str());
// Populate cache with new entries.
- size_t next_pos;
- for (size_t pos = 0, i = 0;; pos = next_pos + 1, ++i) {
+ wtf_size_t next_pos;
+ for (wtf_size_t pos = 0, i = 0;; pos = next_pos + 1, ++i) {
next_pos = text.find('\n', pos);
if (next_pos == kNotFound)
break;
String line = text.Substring(pos, next_pos - pos);
- size_t space_pos = line.ReverseFind(' ');
+ wtf_size_t space_pos = line.ReverseFind(' ');
String name = line.Substring(space_pos == kNotFound ? 0 : space_pos + 1);
symbols_cache_.insert(addresses_to_symbolize[i], name);
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.h
index 451a5cf7876..00a28033500 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_memory_agent.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_MEMORY_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_MEMORY_AGENT_H_
-#include "base/macros.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/Memory.h"
@@ -44,6 +43,8 @@ class CORE_EXPORT InspectorMemoryAgent final
: public InspectorBaseAgent<protocol::Memory::Metainfo> {
public:
explicit InspectorMemoryAgent(InspectedFrames*);
+ InspectorMemoryAgent(const InspectorMemoryAgent&) = delete;
+ InspectorMemoryAgent& operator=(const InspectorMemoryAgent&) = delete;
~InspectorMemoryAgent() override;
void Trace(Visitor*) const override;
@@ -75,7 +76,6 @@ class CORE_EXPORT InspectorMemoryAgent final
HashMap<void*, String> symbols_cache_;
InspectorAgentState::Integer sampling_profile_interval_;
- DISALLOW_COPY_AND_ASSIGN(InspectorMemoryAgent);
};
} // namespace blink
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 7dc28895d81..d62b005900e 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
@@ -34,7 +34,6 @@
#include <utility>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "net/base/ip_address.h"
@@ -82,7 +81,6 @@
#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/loader/fetch/resource_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -190,6 +188,11 @@ class InspectorFileReaderLoaderClient final : public FileReaderLoaderClient {
FileReaderLoader::kReadByClient, this, std::move(task_runner));
}
+ InspectorFileReaderLoaderClient(const InspectorFileReaderLoaderClient&) =
+ delete;
+ InspectorFileReaderLoaderClient& operator=(
+ const InspectorFileReaderLoaderClient&) = delete;
+
~InspectorFileReaderLoaderClient() override = default;
void Start() {
@@ -222,7 +225,6 @@ class InspectorFileReaderLoaderClient final : public FileReaderLoaderClient {
base::OnceCallback<void(scoped_refptr<SharedBuffer>)> callback_;
std::unique_ptr<FileReaderLoader> loader_;
scoped_refptr<SharedBuffer> raw_data_;
- DISALLOW_COPY_AND_ASSIGN(InspectorFileReaderLoaderClient);
};
static void ResponseBodyFileReaderLoaderDone(
@@ -254,6 +256,9 @@ class InspectorPostBodyParser
task_runner_(std::move(task_runner)),
error_(false) {}
+ InspectorPostBodyParser(const InspectorPostBodyParser&) = delete;
+ InspectorPostBodyParser& operator=(const InspectorPostBodyParser&) = delete;
+
void Parse(EncodedFormData* request_body) {
if (!request_body || request_body->IsEmpty())
return;
@@ -314,7 +319,6 @@ class InspectorPostBodyParser
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
bool error_;
Vector<String> parts_;
- DISALLOW_COPY_AND_ASSIGN(InspectorPostBodyParser);
};
KURL UrlWithoutFragment(const KURL& url) {
@@ -799,22 +803,9 @@ BuildObjectForResourceResponse(const ResourceResponse& response,
if (response.IsNull())
return nullptr;
- int status;
- String status_text;
- if (response.GetResourceLoadInfo() &&
- response.GetResourceLoadInfo()->http_status_code) {
- status = response.GetResourceLoadInfo()->http_status_code;
- status_text = response.GetResourceLoadInfo()->http_status_text;
- } else {
- status = response.HttpStatusCode();
- status_text = response.HttpStatusText();
- }
- HTTPHeaderMap headers_map;
- if (response.GetResourceLoadInfo() &&
- response.GetResourceLoadInfo()->response_headers.size())
- headers_map = response.GetResourceLoadInfo()->response_headers;
- else
- headers_map = response.HttpHeaderFields();
+ int status = response.HttpStatusCode();
+ String status_text = response.HttpStatusText();
+ HTTPHeaderMap headers_map = response.HttpHeaderFields();
int64_t encoded_data_length = response.EncodedDataLength();
@@ -879,21 +870,6 @@ BuildObjectForResourceResponse(const ResourceResponse& response,
response_object->setTiming(
BuildObjectForTiming(*response.GetResourceLoadTiming()));
- if (response.GetResourceLoadInfo()) {
- if (!response.GetResourceLoadInfo()->response_headers_text.IsEmpty()) {
- response_object->setHeadersText(
- response.GetResourceLoadInfo()->response_headers_text);
- }
- if (response.GetResourceLoadInfo()->request_headers.size()) {
- response_object->setRequestHeaders(BuildObjectForHeaders(
- response.GetResourceLoadInfo()->request_headers));
- }
- if (!response.GetResourceLoadInfo()->request_headers_text.IsEmpty()) {
- response_object->setRequestHeadersText(
- response.GetResourceLoadInfo()->request_headers_text);
- }
- }
-
const net::IPEndPoint& remote_ip_endpoint = response.RemoteIPEndpoint();
if (remote_ip_endpoint.address().IsValid()) {
response_object->setRemoteIPAddress(
@@ -1127,6 +1103,11 @@ void InspectorNetworkAgent::WillSendRequestInternal(
Maybe<String> maybe_frame_id;
if (!frame_id.IsEmpty())
maybe_frame_id = frame_id;
+ if (loader && loader->GetFrame() && loader->GetFrame()->GetDocument()) {
+ request_info->setIsSameSite(
+ loader->GetFrame()->GetDocument()->SiteForCookies().IsFirstParty(
+ request.Url()));
+ }
GetFrontend()->requestWillBeSent(
request_id, loader_id, documentURL, std::move(request_info),
timestamp.since_origin().InSecondsF(), base::Time::Now().ToDoubleT(),
@@ -1211,8 +1192,6 @@ void InspectorNetworkAgent::PrepareRequest(DocumentLoader* loader,
}
}
- request.SetReportRawHeaders(true);
-
if (cache_disabled_.Get()) {
if (LoadsFromCacheOnly(request) &&
request.GetRequestContext() !=
@@ -1610,11 +1589,13 @@ InspectorNetworkAgent::BuildInitiatorObject(
.build();
}
-void InspectorNetworkAgent::DidCreateWebSocket(
+void InspectorNetworkAgent::WillCreateWebSocket(
ExecutionContext* execution_context,
uint64_t identifier,
const KURL& request_url,
- const String&) {
+ const String&,
+ absl::optional<base::UnguessableToken>* devtools_token) {
+ *devtools_token = devtools_token_;
std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
current_stack_trace =
SourceLocation::Capture(execution_context)->BuildInspectorObject();
@@ -2015,12 +1996,6 @@ Response InspectorNetworkAgent::setBypassServiceWorker(bool bypass) {
return Response::Success();
}
-Response InspectorNetworkAgent::setDataSizeLimitsForTest(int max_total,
- int max_resource) {
- resources_data_->SetResourcesDataSizeLimits(max_total, max_resource);
- return Response::Success();
-}
-
Response InspectorNetworkAgent::getCertificate(
const String& origin,
std::unique_ptr<protocol::Array<String>>* certificate) {
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 ec7404011da..7516802cf04 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
@@ -175,10 +175,11 @@ class CORE_EXPORT InspectorNetworkAgent final
ClientNavigationReason);
void FrameClearedScheduledNavigation(LocalFrame*);
- void DidCreateWebSocket(ExecutionContext*,
- uint64_t identifier,
- const KURL& request_url,
- const String&);
+ void WillCreateWebSocket(ExecutionContext*,
+ uint64_t identifier,
+ const KURL& request_url,
+ const String&,
+ absl::optional<base::UnguessableToken>*);
void WillSendWebSocketHandshakeRequest(
ExecutionContext*,
uint64_t identifier,
@@ -241,8 +242,6 @@ class CORE_EXPORT InspectorNetworkAgent final
Maybe<String> connection_type) override;
protocol::Response setCacheDisabled(bool) override;
protocol::Response setBypassServiceWorker(bool) override;
- protocol::Response setDataSizeLimitsForTest(int max_total_size,
- int max_resource_size) override;
protocol::Response getCertificate(
const String& origin,
std::unique_ptr<protocol::Array<String>>* certificate) override;
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 1eb2e9aafec..98ed4cbfb52 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
@@ -74,6 +74,7 @@
#include "third_party/blink/renderer/core/script/classic_script.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/data_resource_helper.h"
+#include "third_party/blink/renderer/platform/geometry/double_size.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/paint/cull_rect.h"
@@ -83,6 +84,7 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/inspector_protocol/crdtp/json.h"
+#include "ui/accessibility/ax_mode.h"
#include "v8/include/v8.h"
using crdtp::SpanFrom;
@@ -436,7 +438,7 @@ Response InspectorOverlayAgent::enable() {
void InspectorOverlayAgent::EnsureAXContext(Node* node) {
Document& document = node->GetDocument();
if (!document_to_ax_context_.Contains(&document)) {
- auto context = std::make_unique<AXContext>(document);
+ auto context = std::make_unique<AXContext>(document, ui::kAXModeComplete);
document_to_ax_context_.Set(&document, std::move(context));
}
}
@@ -677,6 +679,11 @@ Response InspectorOverlayAgent::highlightNode(
if (!response.IsSuccess())
return response;
+ if (node->GetDocument().Lifecycle().GetState() <=
+ DocumentLifecycle::LifecycleState::kInactive) {
+ return Response::InvalidRequest("The node's document is not active");
+ }
+
std::unique_ptr<InspectorHighlightConfig> highlight_config;
response = HighlightConfigFromInspectorObject(
std::move(highlight_inspector_object), &highlight_config);
@@ -778,6 +785,38 @@ Response InspectorOverlayAgent::setShowScrollSnapOverlays(
return Response::Success();
}
+Response InspectorOverlayAgent::setShowContainerQueryOverlays(
+ std::unique_ptr<
+ protocol::Array<protocol::Overlay::ContainerQueryHighlightConfig>>
+ container_query_highlight_configs) {
+ if (!persistent_tool_) {
+ persistent_tool_ =
+ MakeGarbageCollected<PersistentTool>(this, GetFrontend());
+ }
+
+ Vector<std::pair<
+ Member<Node>,
+ std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>>>
+ configs;
+
+ for (std::unique_ptr<protocol::Overlay::ContainerQueryHighlightConfig>&
+ config : *container_query_highlight_configs) {
+ Node* node = nullptr;
+ Response response = dom_agent_->AssertNode(config->getNodeId(), node);
+ if (!response.IsSuccess())
+ return response;
+ configs.push_back(std::make_pair(
+ node, InspectorOverlayAgent::ToContainerQueryContainerHighlightConfig(
+ config->getContainerQueryContainerHighlightConfig())));
+ }
+
+ persistent_tool_->SetContainerQueryConfigs(std::move(configs));
+
+ PickTheRightTool();
+
+ return Response::Success();
+}
+
Response InspectorOverlayAgent::highlightSourceOrder(
std::unique_ptr<protocol::Overlay::SourceOrderConfig>
source_order_inspector_object,
@@ -1049,7 +1088,9 @@ void InspectorOverlayAgent::PaintOverlayPage() {
return;
LocalFrame* overlay_frame = OverlayMainFrame();
- IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
+ blink::VisualViewport& visual_viewport =
+ frame->GetPage()->GetVisualViewport();
+ IntSize viewport_size = visual_viewport.Size();
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
// To make overlay render the same size text with any emulation scale,
// compensate the emulation scale using page scale.
@@ -1064,7 +1105,9 @@ void InspectorOverlayAgent::PaintOverlayPage() {
overlay_frame->SetPageZoomFactor(WindowToViewportScale());
overlay_frame->View()->Resize(viewport_size);
- Reset(viewport_size);
+ DoubleSize visual_viewport_size(visual_viewport.VisibleWidthCSSPx(),
+ visual_viewport.VisibleHeightCSSPx());
+ Reset(viewport_size, visual_viewport_size);
float scale = WindowToViewportScale();
@@ -1094,6 +1137,15 @@ static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
return result;
}
+static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
+ const DoubleSize& size) {
+ std::unique_ptr<protocol::DictionaryValue> result =
+ protocol::DictionaryValue::create();
+ result->setDouble("width", size.Width());
+ result->setDouble("height", size.Height());
+ return result;
+}
+
float InspectorOverlayAgent::WindowToViewportScale() const {
LocalFrame* frame = GetFrame();
if (!frame)
@@ -1190,7 +1242,8 @@ LocalFrame* InspectorOverlayAgent::OverlayMainFrame() {
return To<LocalFrame>(overlay_page_->MainFrame());
}
-void InspectorOverlayAgent::Reset(const IntSize& viewport_size) {
+void InspectorOverlayAgent::Reset(const IntSize& viewport_size,
+ const DoubleSize& visual_viewport_size) {
std::unique_ptr<protocol::DictionaryValue> reset_data =
protocol::DictionaryValue::create();
reset_data->setDouble("deviceScaleFactor",
@@ -1206,6 +1259,8 @@ void InspectorOverlayAgent::Reset(const IntSize& viewport_size) {
IntRect(IntPoint(), viewport_size), GetFrame()->View());
reset_data->setObject("viewportSize",
BuildObjectForSize(viewport_in_screen.Size()));
+ reset_data->setObject("visualViewportSize",
+ BuildObjectForSize(visual_viewport_size));
// The zoom factor in the overlay frame already has been multiplied by the
// window to viewport scale (aka device scale factor), so cancel it.
@@ -1601,6 +1656,24 @@ InspectorOverlayAgent::ToScrollSnapContainerHighlightConfig(
}
// static
+std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>
+InspectorOverlayAgent::ToContainerQueryContainerHighlightConfig(
+ protocol::Overlay::ContainerQueryContainerHighlightConfig* config) {
+ if (!config) {
+ return nullptr;
+ }
+ std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>
+ highlight_config =
+ std::make_unique<InspectorContainerQueryContainerHighlightConfig>();
+ highlight_config->container_border =
+ InspectorOverlayAgent::ToLineStyle(config->getContainerBorder(nullptr));
+ highlight_config->descendant_border =
+ InspectorOverlayAgent::ToLineStyle(config->getDescendantBorder(nullptr));
+
+ return highlight_config;
+}
+
+// static
std::unique_ptr<InspectorFlexItemHighlightConfig>
InspectorOverlayAgent::ToFlexItemHighlightConfig(
protocol::Overlay::FlexItemHighlightConfig* config) {
@@ -1716,6 +1789,10 @@ InspectorOverlayAgent::ToHighlightConfig(
InspectorOverlayAgent::ToFlexItemHighlightConfig(
config->getFlexItemHighlightConfig(nullptr));
+ highlight_config->container_query_container_highlight_config =
+ InspectorOverlayAgent::ToContainerQueryContainerHighlightConfig(
+ config->getContainerQueryContainerHighlightConfig(nullptr));
+
return highlight_config;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
index 8bc6701c0ad..0461b82fe46 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
@@ -31,7 +31,6 @@
#include <v8-inspector.h>
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
@@ -127,6 +126,8 @@ class CORE_EXPORT Hinge final : public GarbageCollected<Hinge> {
Color color,
Color outline_color,
InspectorOverlayAgent* overlay);
+ Hinge(const Hinge&) = delete;
+ Hinge& operator=(const Hinge&) = delete;
~Hinge() = default;
String GetOverlayName();
void Draw(float scale);
@@ -137,7 +138,6 @@ class CORE_EXPORT Hinge final : public GarbageCollected<Hinge> {
Color content_color_;
Color outline_color_;
Member<InspectorOverlayAgent> overlay_;
- DISALLOW_COPY_AND_ASSIGN(Hinge);
};
class CORE_EXPORT InspectorOverlayAgent final
@@ -152,6 +152,9 @@ class CORE_EXPORT InspectorOverlayAgent final
static std::unique_ptr<InspectorScrollSnapContainerHighlightConfig>
ToScrollSnapContainerHighlightConfig(
protocol::Overlay::ScrollSnapContainerHighlightConfig*);
+ static std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>
+ ToContainerQueryContainerHighlightConfig(
+ protocol::Overlay::ContainerQueryContainerHighlightConfig*);
static std::unique_ptr<InspectorFlexItemHighlightConfig>
ToFlexItemHighlightConfig(protocol::Overlay::FlexItemHighlightConfig*);
static absl::optional<LineStyle> ToLineStyle(protocol::Overlay::LineStyle*);
@@ -162,6 +165,8 @@ class CORE_EXPORT InspectorOverlayAgent final
InspectedFrames*,
v8_inspector::V8InspectorSession*,
InspectorDOMAgent*);
+ InspectorOverlayAgent(const InspectorOverlayAgent&) = delete;
+ InspectorOverlayAgent& operator=(const InspectorOverlayAgent&) = delete;
~InspectorOverlayAgent() override;
void Trace(Visitor*) const override;
@@ -236,6 +241,10 @@ class CORE_EXPORT InspectorOverlayAgent final
std::unique_ptr<
protocol::Array<protocol::Overlay::ScrollSnapHighlightConfig>>
scroll_snap_highlight_configs) override;
+ protocol::Response setShowContainerQueryOverlays(
+ std::unique_ptr<
+ protocol::Array<protocol::Overlay::ContainerQueryHighlightConfig>>
+ container_query_highlight_configs) override;
// InspectorBaseAgent overrides.
void Restore() override;
@@ -273,7 +282,8 @@ class CORE_EXPORT InspectorOverlayAgent final
bool IsEmpty();
LocalFrame* OverlayMainFrame();
- void Reset(const IntSize& viewport_size);
+ void Reset(const IntSize& viewport_size,
+ const DoubleSize& visual_viewport_size);
void OnResizeTimer(TimerBase*);
void PaintOverlayPage();
@@ -332,8 +342,6 @@ class CORE_EXPORT InspectorOverlayAgent final
InspectorAgentState::String paused_in_debugger_message_;
InspectorAgentState::String inspect_mode_;
InspectorAgentState::Bytes inspect_mode_protocol_config_;
-
- DISALLOW_COPY_AND_ASSIGN(InspectorOverlayAgent);
};
} // namespace blink
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 ae249656668..b5c0fea328e 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,8 +35,9 @@
#include "base/containers/span.h"
#include "build/build_config.h"
+#include "third_party/blink/public/common/frame/frame_ad_evidence.h"
#include "third_party/blink/public/common/origin_trials/trial_token.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
+#include "third_party/blink/public/mojom/ad_tagging/ad_evidence.mojom-blink.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"
@@ -88,6 +89,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "ui/display/screen_info.h"
#include "v8/include/v8-inspector.h"
namespace blink {
@@ -1327,6 +1329,43 @@ CreateOriginTrials(LocalDOMWindow* window) {
return trials;
}
+protocol::Page::AdFrameType BuildAdFrameType(LocalFrame* frame) {
+ if (frame->IsAdRoot())
+ return protocol::Page::AdFrameTypeEnum::Root;
+ if (frame->IsAdSubframe())
+ return protocol::Page::AdFrameTypeEnum::Child;
+ return protocol::Page::AdFrameTypeEnum::None;
+}
+
+std::unique_ptr<protocol::Page::AdFrameStatus> BuildAdFrameStatus(
+ LocalFrame* frame) {
+ if (!frame->AdEvidence() || !frame->AdEvidence()->is_complete()) {
+ return protocol::Page::AdFrameStatus::create()
+ .setAdFrameType(protocol::Page::AdFrameTypeEnum::None)
+ .build();
+ }
+ const FrameAdEvidence& evidence = *frame->AdEvidence();
+ auto explanations =
+ std::make_unique<protocol::Array<protocol::Page::AdFrameExplanation>>();
+ if (evidence.parent_is_ad()) {
+ explanations->push_back(protocol::Page::AdFrameExplanationEnum::ParentIsAd);
+ }
+ if (evidence.created_by_ad_script() ==
+ mojom::blink::FrameCreationStackEvidence::kCreatedByAdScript) {
+ explanations->push_back(
+ protocol::Page::AdFrameExplanationEnum::CreatedByAdScript);
+ }
+ if (evidence.most_restrictive_filter_list_result() ==
+ mojom::blink::FilterListResult::kMatchedBlockingRule) {
+ explanations->push_back(
+ protocol::Page::AdFrameExplanationEnum::MatchedBlockingRule);
+ }
+ return protocol::Page::AdFrameStatus::create()
+ .setAdFrameType(BuildAdFrameType(frame))
+ .setExplanations(std::move(explanations))
+ .build();
+}
+
} // namespace
std::unique_ptr<protocol::Page::Frame> InspectorPageAgent::BuildObjectForFrame(
@@ -1366,13 +1405,7 @@ std::unique_ptr<protocol::Page::Frame> InspectorPageAgent::BuildObjectForFrame(
}
if (loader && !loader->UnreachableURL().IsEmpty())
frame_object->setUnreachableUrl(loader->UnreachableURL().GetString());
- if (frame->IsAdRoot()) {
- frame_object->setAdFrameType(protocol::Page::AdFrameTypeEnum::Root);
- } else if (frame->IsAdSubframe()) {
- frame_object->setAdFrameType(protocol::Page::AdFrameTypeEnum::Child);
- } else {
- frame_object->setAdFrameType(protocol::Page::AdFrameTypeEnum::None);
- }
+ frame_object->setAdFrameStatus(BuildAdFrameStatus(frame));
auto origin_trials = CreateOriginTrials(frame->DomWindow());
if (!origin_trials->empty())
frame_object->setOriginTrials(std::move(origin_trials));
@@ -1672,7 +1705,8 @@ void InspectorPageAgent::ApplyCompilationModeOverride(
}
const protocol::Binary& data = it->value;
*cached_data = new v8::ScriptCompiler::CachedData(
- data.data(), data.size(), v8::ScriptCompiler::CachedData::BufferNotOwned);
+ data.data(), base::checked_cast<int>(data.size()),
+ v8::ScriptCompiler::CachedData::BufferNotOwned);
}
void InspectorPageAgent::DidProduceCompilationCache(
@@ -1790,4 +1824,19 @@ void InspectorPageAgent::Trace(Visitor* visitor) const {
InspectorBaseAgent::Trace(visitor);
}
+Response InspectorPageAgent::getOriginTrials(
+ const String& frame_id,
+ std::unique_ptr<protocol::Array<protocol::Page::OriginTrial>>*
+ originTrials) {
+ LocalFrame* frame =
+ IdentifiersFactory::FrameById(inspected_frames_, frame_id);
+
+ if (!frame)
+ return Response::InvalidParams("Invalid frame id");
+
+ *originTrials = CreateOriginTrials(frame->DomWindow());
+
+ return Response::Success();
+}
+
} // namespace blink
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 271ac0804c3..db5592537ac 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
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_PAGE_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_PAGE_AGENT_H_
-#include "base/macros.h"
#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
@@ -105,6 +104,8 @@ class CORE_EXPORT InspectorPageAgent final
Client*,
InspectorResourceContentLoader*,
v8_inspector::V8InspectorSession*);
+ InspectorPageAgent(const InspectorPageAgent&) = delete;
+ InspectorPageAgent& operator=(const InspectorPageAgent&) = delete;
// Page API for frontend
protocol::Response enable() override;
@@ -147,6 +148,9 @@ class CORE_EXPORT InspectorPageAgent final
std::unique_ptr<
protocol::Array<protocol::Page::PermissionsPolicyFeatureState>>*)
override;
+ protocol::Response getOriginTrials(
+ const String& frame_id,
+ std::unique_ptr<protocol::Array<protocol::Page::OriginTrial>>*) override;
protocol::Response startScreencast(Maybe<String> format,
Maybe<int> quality,
@@ -294,7 +298,6 @@ class CORE_EXPORT InspectorPageAgent final
InspectorAgentState::Integer standard_font_size_;
InspectorAgentState::Integer fixed_font_size_;
InspectorAgentState::Boolean produce_compilation_cache_;
- DISALLOW_COPY_AND_ASSIGN(InspectorPageAgent);
};
} // namespace blink
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 12748642000..f5d02c12260 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
@@ -6,9 +6,9 @@
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/process/process.h"
#include "base/process/process_metrics.h"
-#include "base/stl_util.h"
#include "base/time/time_override.h"
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
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 0fa45182c9e..37abe1fbe98 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
@@ -7,7 +7,6 @@
#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"
@@ -34,6 +33,9 @@ class CORE_EXPORT InspectorPerformanceAgent final
void Trace(Visitor*) const override;
explicit InspectorPerformanceAgent(InspectedFrames*);
+ InspectorPerformanceAgent(const InspectorPerformanceAgent&) = delete;
+ InspectorPerformanceAgent& operator=(const InspectorPerformanceAgent&) =
+ delete;
~InspectorPerformanceAgent() override;
void Restore() override;
@@ -95,7 +97,6 @@ class CORE_EXPORT InspectorPerformanceAgent final
int layout_depth_ = 0;
InspectorAgentState::Boolean enabled_;
InspectorAgentState::Boolean use_thread_ticks_;
- DISALLOW_COPY_AND_ASSIGN(InspectorPerformanceAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.h
index 94c106d2b30..9f480eaa0f7 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.h
@@ -7,7 +7,6 @@
#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"
@@ -24,6 +23,10 @@ class CORE_EXPORT InspectorPerformanceTimelineAgent final
: public InspectorBaseAgent<protocol::PerformanceTimeline::Metainfo> {
public:
explicit InspectorPerformanceTimelineAgent(InspectedFrames*);
+ InspectorPerformanceTimelineAgent(const InspectorPerformanceTimelineAgent&) =
+ delete;
+ InspectorPerformanceTimelineAgent& operator=(
+ const InspectorPerformanceTimelineAgent&) = delete;
~InspectorPerformanceTimelineAgent() override;
// PerformanceTimeline probes implementation.
@@ -47,7 +50,6 @@ class CORE_EXPORT InspectorPerformanceTimelineAgent final
Member<InspectedFrames> inspected_frames_;
InspectorAgentState::Integer enabled_types_;
- DISALLOW_COPY_AND_ASSIGN(InspectorPerformanceTimelineAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_container.h b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_container.h
index 235bd6a86a2..450fac78f9d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_container.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_container.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_RESOURCE_CONTAINER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_RESOURCE_CONTAINER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -23,6 +22,9 @@ class CORE_EXPORT InspectorResourceContainer final
: public GarbageCollected<InspectorResourceContainer> {
public:
explicit InspectorResourceContainer(InspectedFrames*);
+ InspectorResourceContainer(const InspectorResourceContainer&) = delete;
+ InspectorResourceContainer& operator=(const InspectorResourceContainer&) =
+ delete;
~InspectorResourceContainer();
void Trace(Visitor*) const;
@@ -40,7 +42,6 @@ class CORE_EXPORT InspectorResourceContainer final
Member<InspectedFrames> inspected_frames_;
HashMap<String, String> style_sheet_contents_;
HashMap<DOMNodeId, String> style_element_contents_;
- DISALLOW_COPY_AND_ASSIGN(InspectorResourceContainer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc
index 266f428062c..fc88de696d2 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc
@@ -31,6 +31,22 @@ bool ShouldSkipFetchingUrl(const KURL& url) {
return !url.IsValid() || url.IsAboutBlankURL() || url.IsAboutSrcdocURL();
}
+bool IsServiceWorkerPresent(Document* document) {
+ DocumentLoader* loader = document->Loader();
+ if (!loader)
+ return false;
+
+ if (loader->GetResponse().WasFetchedViaServiceWorker())
+ return true;
+
+ WebServiceWorkerNetworkProvider* provider =
+ loader->GetServiceWorkerNetworkProvider();
+ if (!provider)
+ return false;
+
+ return provider->ControllerServiceWorkerID() >= 0;
+}
+
} // namespace
// NOTE: While this is a RawResourceClient, it loads both raw and css stylesheet
@@ -96,8 +112,12 @@ void InspectorResourceContentLoader::Start() {
}
resource_request.SetRequestContext(
mojom::blink::RequestContextType::INTERNAL);
- if (document->Loader() &&
- document->Loader()->GetResponse().WasFetchedViaServiceWorker()) {
+
+ if (IsServiceWorkerPresent(document)) {
+ // If the request is going to be intercepted by a service worker, then
+ // don't use only-if-cached. only-if-cached will cause the service worker
+ // to throw an exception if it repeats the request, which is a problem:
+ // crbug.com/823392 crbug.com/1098389
resource_request.SetCacheMode(mojom::FetchCacheMode::kDefault);
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h
index eee476bba99..d5a0ced0b19 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_RESOURCE_CONTENT_LOADER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_RESOURCE_CONTENT_LOADER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -23,6 +22,10 @@ class CORE_EXPORT InspectorResourceContentLoader final
: public GarbageCollected<InspectorResourceContentLoader> {
public:
explicit InspectorResourceContentLoader(LocalFrame*);
+ InspectorResourceContentLoader(const InspectorResourceContentLoader&) =
+ delete;
+ InspectorResourceContentLoader& operator=(
+ const InspectorResourceContentLoader&) = delete;
~InspectorResourceContentLoader();
void Dispose();
void Trace(Visitor*) const;
@@ -53,7 +56,6 @@ class CORE_EXPORT InspectorResourceContentLoader final
int last_client_id_;
friend class ResourceClient;
- DISALLOW_COPY_AND_ASSIGN(InspectorResourceContentLoader);
};
} // namespace blink
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 bf07c43d7b3..5c70b1ea1ed 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
@@ -27,6 +27,7 @@
#include <algorithm>
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
+#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/css_import_rule.h"
#include "third_party/blink/renderer/core/css/css_keyframe_rule.h"
#include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
@@ -482,6 +483,47 @@ bool VerifyMediaText(Document* document, const String& media_text) {
return true;
}
+bool VerifyContainerQueryText(Document* document,
+ const String& container_query_text) {
+ DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee"));
+ auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(
+ ParserContextForDocument(document));
+ CSSRuleSourceDataList* source_data =
+ MakeGarbageCollected<CSSRuleSourceDataList>();
+ String text = "@container " + container_query_text + " { div { " +
+ bogus_property_name + ": none; } }";
+ StyleSheetHandler handler(text, document, source_data);
+ CSSParser::ParseSheetForInspector(ParserContextForDocument(document),
+ style_sheet, text, handler);
+
+ // TODO(crbug.com/1146422): for now these checks are identical to
+ // those for media queries. We should enforce container-query-specific
+ // checks once the spec is finalized.
+ // Exactly one container rule should be parsed.
+ unsigned rule_count = source_data->size();
+ if (rule_count != 1 || source_data->at(0)->type != StyleRule::kContainer)
+ return false;
+
+ // Container rule should have exactly one style rule child.
+ CSSRuleSourceDataList& child_source_data = source_data->at(0)->child_rules;
+ rule_count = child_source_data.size();
+ if (rule_count != 1 || !child_source_data.at(0)->HasProperties())
+ return false;
+
+ // Exactly one property should be in style rule.
+ Vector<CSSPropertySourceData>& property_data =
+ child_source_data.at(0)->property_data;
+ unsigned property_count = property_data.size();
+ if (property_count != 1)
+ return false;
+
+ // Check for the property name.
+ if (property_data.at(0).name != bogus_property_name)
+ return false;
+
+ return true;
+}
+
void FlattenSourceData(const CSSRuleSourceDataList& data_list,
CSSRuleSourceDataList* result) {
for (CSSRuleSourceData* data : data_list) {
@@ -499,6 +541,7 @@ void FlattenSourceData(const CSSRuleSourceDataList& data_list,
case StyleRule::kMedia:
case StyleRule::kSupports:
case StyleRule::kKeyframes:
+ case StyleRule::kContainer:
result->push_back(data);
FlattenSourceData(data->child_rules, result);
break;
@@ -521,6 +564,9 @@ CSSRuleList* AsCSSRuleList(CSSRule* rule) {
if (auto* keyframes_rule = DynamicTo<CSSKeyframesRule>(rule))
return keyframes_rule->cssRules();
+ if (auto* container_rule = DynamicTo<CSSContainerRule>(rule))
+ return container_rule->cssRules();
+
return nullptr;
}
@@ -547,6 +593,7 @@ void CollectFlatRules(RuleList rule_list, CSSRuleVector* result) {
case CSSRule::kMediaRule:
case CSSRule::kSupportsRule:
case CSSRule::kKeyframesRule:
+ case CSSRule::kContainerRule:
result->push_back(rule);
CollectFlatRules(AsCSSRuleList(rule), result);
break;
@@ -775,22 +822,15 @@ bool InspectorStyle::TextForRange(const SourceRange& range, String* result) {
void InspectorStyle::PopulateAllProperties(
Vector<CSSPropertySourceData>& result) {
- HashSet<String> source_property_names;
-
if (source_data_ && source_data_->HasProperties()) {
Vector<CSSPropertySourceData>& source_property_data =
source_data_->property_data;
- for (const auto& data : source_property_data) {
+ for (const auto& data : source_property_data)
result.push_back(data);
- source_property_names.insert(data.name.DeprecatedLower());
- }
}
for (int i = 0, size = style_->length(); i < size; ++i) {
String name = style_->item(i);
- if (!source_property_names.insert(name.DeprecatedLower()).is_new_entry)
- continue;
-
if (!IsValidCSSPropertyID(
CssPropertyID(style_->GetExecutionContext(), name)))
continue;
@@ -1165,6 +1205,47 @@ CSSMediaRule* InspectorStyleSheet::SetMediaRuleText(
return media_rule;
}
+CSSContainerRule* InspectorStyleSheet::SetContainerRuleText(
+ const SourceRange& range,
+ const String& text,
+ SourceRange* new_range,
+ String* old_text,
+ ExceptionState& exception_state) {
+ if (!VerifyContainerQueryText(page_style_sheet_->OwnerDocument(), text)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kSyntaxError,
+ "Selector or container query text is not valid.");
+ return nullptr;
+ }
+
+ CSSRuleSourceData* source_data = FindRuleByHeaderRange(range);
+ if (!source_data || !source_data->HasContainer()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotFoundError,
+ "Source range didn't match existing source range");
+ return nullptr;
+ }
+
+ CSSRule* rule = RuleForSourceData(source_data);
+ if (!rule || !rule->parentStyleSheet() ||
+ rule->GetType() != CSSRule::kContainerRule) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotFoundError,
+ "CQ Source range didn't match existing style source range");
+ return nullptr;
+ }
+
+ CSSContainerRule* container_rule =
+ InspectorCSSAgent::AsCSSContainerRule(rule);
+ container_rule->container()->setMediaText(
+ page_style_sheet_->OwnerDocument()->GetExecutionContext(), text);
+
+ ReplaceText(source_data->rule_header_range, text, new_range, old_text);
+ OnStyleSheetTextChanged();
+
+ return container_rule;
+}
+
CSSRuleSourceData* InspectorStyleSheet::RuleSourceDataAfterSourceRange(
const SourceRange& source_range) {
DCHECK(source_data_);
@@ -1532,12 +1613,25 @@ InspectorStyleSheet::BuildObjectForStyleSheetInfo() {
text_length, *line_endings, start);
}
+ // DevTools needs to be able to distinguish between constructed
+ // stylesheets created with `new` and constructed stylesheets
+ // imported as a CSS module. Only the latter have a separate
+ // source file to display.
+ // For constructed stylesheets created with `new`, Url()
+ // returns the URL of the document in which the sheet was created,
+ // which may confuse the client. Only set the URL if we have a
+ // proper URL of the source of the stylesheet.
+ const String& source_url =
+ (style_sheet->IsConstructed() && !style_sheet->IsForCSSModuleScript())
+ ? String()
+ : Url();
+
std::unique_ptr<protocol::CSS::CSSStyleSheetHeader> result =
protocol::CSS::CSSStyleSheetHeader::create()
.setStyleSheetId(Id())
.setOrigin(origin_)
.setDisabled(style_sheet->disabled())
- .setSourceURL(Url())
+ .setSourceURL(source_url)
.setTitle(style_sheet->title())
.setFrameId(frame ? IdentifiersFactory::FrameId(frame) : "")
.setIsInline(style_sheet->IsInline() && !StartsAtZero())
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.h b/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
index 36c476aa18b..4aeef014944 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
@@ -40,6 +40,7 @@ namespace blink {
class CSSKeyframeRule;
class CSSMediaRule;
+class CSSContainerRule;
class CSSStyleDeclaration;
class CSSStyleRule;
class CSSStyleSheet;
@@ -162,6 +163,11 @@ class InspectorStyleSheet : public InspectorStyleSheetBase {
SourceRange* new_range,
String* old_selector,
ExceptionState&);
+ CSSContainerRule* SetContainerRuleText(const SourceRange&,
+ const String& selector,
+ SourceRange* new_range,
+ String* old_selector,
+ ExceptionState&);
CSSStyleRule* AddRule(const String& rule_text,
const SourceRange& location,
SourceRange* added_range,
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.h b/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.h
index 7fe34311479..37ea5249e13 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_TASK_RUNNER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_TASK_RUNNER_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_annotations.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -35,6 +34,9 @@ class CORE_EXPORT InspectorTaskRunner final
return base::AdoptRef(new InspectorTaskRunner(isolate_task_runner));
}
+ InspectorTaskRunner(const InspectorTaskRunner&) = delete;
+ InspectorTaskRunner& operator=(const InspectorTaskRunner&) = delete;
+
// Must be called on the isolate's thread.
void InitIsolate(v8::Isolate*) LOCKS_EXCLUDED(mutex_);
// Can be disposed from any thread.
@@ -78,7 +80,6 @@ class CORE_EXPORT InspectorTaskRunner final
v8::Isolate* isolate_ GUARDED_BY(mutex_) = nullptr;
Deque<Task> interrupting_task_queue_;
bool disposed_ GUARDED_BY(mutex_) = false;
- DISALLOW_COPY_AND_ASSIGN(InspectorTaskRunner);
};
} // 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 995ab53e9e5..f6bc8c36f28 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
@@ -391,6 +391,8 @@ const char* PseudoTypeToString(CSSSelector::PseudoType pseudo_type) {
DEFINE_STRING_MAPPING(PseudoHighlight)
DEFINE_STRING_MAPPING(PseudoSpellingError)
DEFINE_STRING_MAPPING(PseudoGrammarError)
+ DEFINE_STRING_MAPPING(PseudoHas)
+ DEFINE_STRING_MAPPING(PseudoRelativeLeftmost)
#undef DEFINE_STRING_MAPPING
}
@@ -793,18 +795,9 @@ void inspector_change_resource_priority_event::Data(
dict.Add("priority", ResourcePriorityString(load_priority));
}
-void inspector_send_request_event::Data(
- perfetto::TracedValue context,
- DocumentLoader* loader,
- uint64_t identifier,
- LocalFrame* frame,
- const ResourceRequest& request,
+namespace {
+String GetRenderBlockingStringFromBehavior(
RenderBlockingBehavior render_blocking_behavior) {
- auto dict = std::move(context).WriteDictionary();
- dict.Add("requestId", IdentifiersFactory::RequestId(loader, identifier));
- dict.Add("frame", IdentifiersFactory::FrameId(frame));
- dict.Add("url", request.Url().GetString());
- dict.Add("requestMethod", request.HttpMethod());
String render_blocking_string;
switch (render_blocking_behavior) {
case RenderBlockingBehavior::kUnset:
@@ -827,6 +820,25 @@ void inspector_send_request_event::Data(
default:
NOTREACHED();
}
+ return render_blocking_string;
+}
+
+} // namespace
+
+void inspector_send_request_event::Data(
+ perfetto::TracedValue context,
+ DocumentLoader* loader,
+ uint64_t identifier,
+ LocalFrame* frame,
+ const ResourceRequest& request,
+ RenderBlockingBehavior render_blocking_behavior) {
+ auto dict = std::move(context).WriteDictionary();
+ dict.Add("requestId", IdentifiersFactory::RequestId(loader, identifier));
+ dict.Add("frame", IdentifiersFactory::FrameId(frame));
+ dict.Add("url", request.Url().GetString());
+ dict.Add("requestMethod", request.HttpMethod());
+ String render_blocking_string =
+ GetRenderBlockingStringFromBehavior(render_blocking_behavior);
if (!render_blocking_string.IsNull()) {
dict.Add("renderBlocking", render_blocking_string);
}
@@ -836,6 +848,24 @@ void inspector_send_request_event::Data(
SetCallStack(dict);
}
+void inspector_change_render_blocking_behavior_event::Data(
+ perfetto::TracedValue context,
+ DocumentLoader* loader,
+ uint64_t identifier,
+ const ResourceRequestHead& request,
+ RenderBlockingBehavior render_blocking_behavior) {
+ String request_id = IdentifiersFactory::RequestId(loader, identifier);
+
+ auto dict = std::move(context).WriteDictionary();
+ dict.Add("requestId", request_id);
+ dict.Add("url", request.Url().GetString());
+ String render_blocking_string =
+ GetRenderBlockingStringFromBehavior(render_blocking_behavior);
+ if (!render_blocking_string.IsNull()) {
+ dict.Add("renderBlocking", render_blocking_string);
+ }
+}
+
void inspector_send_navigation_request_event::Data(
perfetto::TracedValue context,
DocumentLoader* loader,
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 1976e6cc7ab..9b54ad9b7be 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include "third_party/blink/renderer/core/animation/compositor_animations.h"
@@ -69,6 +68,7 @@ class Resource;
class ResourceError;
struct ResourceLoaderOptions;
class ResourceRequest;
+class ResourceRequestHead;
class ResourceResponse;
class StyleChangeReasonForTracing;
class StyleImage;
@@ -86,6 +86,8 @@ class CORE_EXPORT InspectorTraceEvents
: public GarbageCollected<InspectorTraceEvents> {
public:
InspectorTraceEvents() = default;
+ InspectorTraceEvents(const InspectorTraceEvents&) = delete;
+ InspectorTraceEvents& operator=(const InspectorTraceEvents&) = delete;
void WillSendRequest(DocumentLoader*,
const KURL& fetch_context_url,
@@ -136,9 +138,6 @@ class CORE_EXPORT InspectorTraceEvents
void FrameStartedLoading(LocalFrame*);
void Trace(Visitor*) const {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InspectorTraceEvents);
};
// Helper macros for emitting devtools.timeline events, taking the name of the
@@ -325,6 +324,14 @@ void Data(perfetto::TracedValue context,
RenderBlockingBehavior);
}
+namespace inspector_change_render_blocking_behavior_event {
+void Data(perfetto::TracedValue context,
+ DocumentLoader*,
+ uint64_t identifier,
+ const ResourceRequestHead&,
+ RenderBlockingBehavior);
+}
+
namespace inspector_send_navigation_request_event {
void Data(perfetto::TracedValue context,
DocumentLoader*,
diff --git a/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc b/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
index 28f0fe6cae2..1d6499eac80 100644
--- a/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
@@ -185,13 +185,15 @@ int LegacyDOMSnapshotAgent::VisitNode(Node* node,
.build();
if (origin_url_map_ &&
origin_url_map_->Contains(owned_value->getBackendNodeId())) {
- String origin_url = origin_url_map_->at(owned_value->getBackendNodeId());
+ String origin_url = origin_url_map_->DeprecatedAtOrEmptyValue(
+ owned_value->getBackendNodeId());
// 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) {
- owned_value->setOriginURL(
- origin_url_map_->at(owned_value->getBackendNodeId()));
+ if (!node->parentNode() ||
+ origin_url_map_->DeprecatedAtOrEmptyValue(
+ DOMNodeIds::IdForNode(node->parentNode())) != origin_url) {
+ owned_value->setOriginURL(origin_url_map_->DeprecatedAtOrEmptyValue(
+ owned_value->getBackendNodeId()));
}
}
protocol::DOMSnapshot::DOMNode* value = owned_value.get();
@@ -397,7 +399,8 @@ int LegacyDOMSnapshotAgent::VisitLayoutTreeNode(LayoutObject* layout_object,
// We visited all PaintLayers when building |paint_order_map_|.
DCHECK(paint_order_map_->Contains(paint_layer));
- if (int paint_order = paint_order_map_->at(paint_layer))
+ if (int paint_order =
+ paint_order_map_->DeprecatedAtOrEmptyValue(paint_layer))
layout_tree_node->setPaintOrder(paint_order);
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.h b/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.h
index 245b7845ce0..f0f94754d6b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_LEGACY_DOM_SNAPSHOT_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_LEGACY_DOM_SNAPSHOT_AGENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
@@ -26,6 +25,8 @@ class CORE_EXPORT LegacyDOMSnapshotAgent {
public:
using OriginUrlMap = WTF::HashMap<DOMNodeId, String>;
LegacyDOMSnapshotAgent(InspectorDOMDebuggerAgent*, OriginUrlMap*);
+ LegacyDOMSnapshotAgent(const LegacyDOMSnapshotAgent&) = delete;
+ LegacyDOMSnapshotAgent& operator=(const LegacyDOMSnapshotAgent&) = delete;
~LegacyDOMSnapshotAgent();
void Restore();
@@ -99,7 +100,6 @@ class CORE_EXPORT LegacyDOMSnapshotAgent {
OriginUrlMap* origin_url_map_;
using DocumentOrderMap = HeapHashMap<Member<Document>, int>;
InspectorDOMDebuggerAgent* dom_debugger_agent_;
- DISALLOW_COPY_AND_ASSIGN(LegacyDOMSnapshotAgent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/locale_controller.h b/chromium/third_party/blink/renderer/core/inspector/locale_controller.h
index a432c7feb78..5b5ecdf9e1a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/locale_controller.h
+++ b/chromium/third_party/blink/renderer/core/inspector/locale_controller.h
@@ -13,6 +13,9 @@ class LocaleController {
public:
static LocaleController& instance();
+ LocaleController(const LocaleController&) = delete;
+ LocaleController& operator=(const LocaleController&) = delete;
+
String SetLocaleOverride(const String& locale);
bool has_locale_override() const;
@@ -22,7 +25,6 @@ class LocaleController {
String embedder_locale_;
String locale_override_;
- DISALLOW_COPY_AND_ASSIGN(LocaleController);
};
} // namespace blink
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 747c18668f4..dd48c12f8aa 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
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_MAIN_THREAD_DEBUGGER_H_
#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"
@@ -61,6 +60,8 @@ class CORE_EXPORT MainThreadDebugger final : public ThreadDebugger {
};
explicit MainThreadDebugger(v8::Isolate*);
+ MainThreadDebugger(const MainThreadDebugger&) = delete;
+ MainThreadDebugger& operator=(const MainThreadDebugger&) = delete;
~MainThreadDebugger() override;
static MainThreadDebugger* Instance();
@@ -120,7 +121,6 @@ class CORE_EXPORT MainThreadDebugger final : public ThreadDebugger {
static MainThreadDebugger* instance_;
std::unique_ptr<DocumentLifecycle::PostponeTransitionScope>
postponed_transition_scope_;
- DISALLOW_COPY_AND_ASSIGN(MainThreadDebugger);
};
} // namespace blink
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 d36df061d6e..752731f8c3d 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
@@ -91,31 +91,36 @@ void NetworkResourcesData::ResourceData::SetContent(const String& content,
base64_encoded_ = base64_encoded;
}
-size_t NetworkResourcesData::ResourceData::RemoveContent() {
- size_t result = 0;
+size_t NetworkResourcesData::ResourceData::ContentSize() const {
+ size_t size = 0;
if (HasData()) {
DCHECK(!HasContent());
- result = data_buffer_->size();
- data_buffer_ = nullptr;
+ size = data_buffer_->size();
}
-
if (HasContent()) {
DCHECK(!HasData());
- result = content_.CharactersSizeInBytes();
- content_ = String();
- }
-
- if (post_data_ && post_data_->SizeInBytes()) {
- result += post_data_->SizeInBytes();
- post_data_ = nullptr;
+ size = content_.CharactersSizeInBytes();
}
+ if (post_data_)
+ size += post_data_->SizeInBytes();
+ return size;
+}
- return result;
+size_t NetworkResourcesData::ResourceData::RemoveResponseContent() {
+ DCHECK(HasContent());
+ DCHECK(!HasData());
+ const size_t size = content_.CharactersSizeInBytes();
+ content_ = String();
+ return size;
}
size_t NetworkResourcesData::ResourceData::EvictContent() {
+ size_t size = ContentSize();
is_content_evicted_ = true;
- return RemoveContent();
+ data_buffer_ = nullptr;
+ content_ = String();
+ post_data_ = nullptr;
+ return size;
}
void NetworkResourcesData::ResourceData::SetResource(
@@ -161,17 +166,6 @@ void NetworkResourcesData::ResourceData::FontResourceDataWillBeCleared() {
network_resources_data_->MaybeDecodeDataToContent(RequestId());
}
-uint64_t NetworkResourcesData::ResourceData::DataLength() const {
- uint64_t data_length = 0;
- if (data_buffer_)
- data_length += data_buffer_->size();
-
- if (post_data_)
- data_length += post_data_->SizeInBytes();
-
- return data_length;
-}
-
void NetworkResourcesData::ResourceData::AppendData(const char* data,
size_t data_length) {
DCHECK(!HasContent());
@@ -274,7 +268,7 @@ void NetworkResourcesData::SetResourceContent(const String& request_id,
// We can not be sure that we didn't try to save this request data while it
// was loading, so remove it, if any.
if (resource_data->HasContent())
- content_size_ -= resource_data->RemoveContent();
+ content_size_ -= resource_data->RemoveResponseContent();
request_ids_deque_.push_back(request_id);
resource_data->SetContent(content, base64_encoded);
content_size_ += data_length;
@@ -288,9 +282,10 @@ NetworkResourcesData::PrepareToAddResourceData(const String& request_id,
if (!resource_data)
return nullptr;
- if (resource_data->DataLength() + data_length >
- maximum_single_resource_content_size_)
+ if (resource_data->ContentSize() + data_length >
+ maximum_single_resource_content_size_) {
content_size_ -= resource_data->EvictContent();
+ }
if (resource_data->IsContentEvicted())
return nullptr;
if (!EnsureFreeSpace(data_length) || resource_data->IsContentEvicted())
@@ -417,8 +412,10 @@ void NetworkResourcesData::Clear(const String& preserved_loader_id) {
for (auto& resource : request_id_to_resource_data_map_) {
ResourceData* resource_data = resource.value;
if (!preserved_loader_id.IsNull() &&
- resource_data->LoaderId() == preserved_loader_id)
+ resource_data->LoaderId() == preserved_loader_id) {
preserved_map.Set(resource.key, resource.value);
+ content_size_ += resource_data->ContentSize();
+ }
}
request_id_to_resource_data_map_.swap(preserved_map);
}
@@ -426,16 +423,20 @@ void NetworkResourcesData::Clear(const String& preserved_loader_id) {
void NetworkResourcesData::SetResourcesDataSizeLimits(
size_t resources_content_size,
size_t single_resource_content_size) {
- Clear();
maximum_resources_content_size_ = resources_content_size;
maximum_single_resource_content_size_ = single_resource_content_size;
+ for (auto& entry : request_id_to_resource_data_map_) {
+ if (entry.value->ContentSize() > maximum_single_resource_content_size_)
+ content_size_ -= entry.value->EvictContent();
+ }
+ EnsureFreeSpace(0);
}
NetworkResourcesData::ResourceData*
NetworkResourcesData::ResourceDataForRequestId(const String& request_id) const {
if (request_id.IsNull())
return nullptr;
- return request_id_to_resource_data_map_.at(request_id);
+ return request_id_to_resource_data_map_.DeprecatedAtOrEmptyValue(request_id);
}
void NetworkResourcesData::EnsureNoDataForRequestId(const String& request_id) {
diff --git a/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h b/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h
index 11bf1c75e25..1340ae33012 100644
--- a/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h
+++ b/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h
@@ -100,15 +100,17 @@ class NetworkResourcesData final
KURL RequestedURL() const { return requested_url_; }
+ // Returns the size of request and response content.
+ size_t ContentSize() const;
bool HasContent() const { return !content_.IsNull(); }
String Content() const { return content_; }
void SetContent(const String&, bool base64_encoded);
bool Base64Encoded() const { return base64_encoded_; }
- size_t RemoveContent();
bool IsContentEvicted() const { return is_content_evicted_; }
- size_t EvictContent();
+ // Evicts the post data and the respone content.
+ WARN_UNUSED_RESULT size_t EvictContent();
InspectorPageAgent::ResourceType GetType() const { return type_; }
void SetType(InspectorPageAgent::ResourceType type) { type_ = type; }
@@ -172,8 +174,9 @@ class NetworkResourcesData final
private:
bool HasData() const { return data_buffer_.get(); }
- uint64_t DataLength() const;
void AppendData(const char* data, size_t data_length);
+ // Removes just the response content.
+ WARN_UNUSED_RESULT size_t RemoveResponseContent();
size_t DecodeDataToContent();
void ProcessCustomWeakness(const LivenessBroker&);
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 8be6ecb2376..d8aa716d492 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
@@ -463,14 +463,14 @@ TEST(ProtocolParserTest, Reading) {
EXPECT_EQ(Value::TypeString, root->type());
EXPECT_TRUE(root->asString(&str_val));
UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34};
- EXPECT_EQ(String(tmp2, 5), str_val);
+ EXPECT_EQ(String(tmp2, 5u), str_val);
root = ParseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(Value::TypeString, root->type());
EXPECT_TRUE(root->asString(&str_val));
UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c};
- EXPECT_EQ(String(tmp3, 4), str_val);
+ EXPECT_EQ(String(tmp3, 4u), str_val);
// Test literal root objects.
root = ParseJSON("null");
diff --git a/chromium/third_party/blink/renderer/core/inspector/protocol_unittest.cc b/chromium/third_party/blink/renderer/core/inspector/protocol_unittest.cc
index 017e00a7acd..9627f112da6 100644
--- a/chromium/third_party/blink/renderer/core/inspector/protocol_unittest.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/protocol_unittest.cc
@@ -16,7 +16,7 @@ TEST(ProtocolBinaryTest, base64EmptyArgs) {
Binary decoded = Binary::fromBase64("", &success);
EXPECT_TRUE(success);
Vector<uint8_t> decoded_bytes;
- decoded_bytes.Append(decoded.data(), decoded.size());
+ decoded_bytes.Append(decoded.data(), static_cast<wtf_size_t>(decoded.size()));
EXPECT_EQ(Vector<uint8_t>(), decoded_bytes);
}
@@ -29,14 +29,15 @@ TEST(ProtocolStringTest, AllBytesBase64Roundtrip) {
Binary decoded = Binary::fromBase64(binary.toBase64(), &success);
EXPECT_TRUE(success);
Vector<uint8_t> decoded_bytes;
- decoded_bytes.Append(decoded.data(), decoded.size());
+ decoded_bytes.Append(decoded.data(), static_cast<wtf_size_t>(decoded.size()));
EXPECT_EQ(all_bytes, decoded_bytes);
}
TEST(ProtocolStringTest, HelloWorldBase64Roundtrip) {
const char* kMsg = "Hello, world.";
Vector<uint8_t> msg;
- msg.Append(reinterpret_cast<const uint8_t*>(kMsg), strlen(kMsg));
+ msg.Append(reinterpret_cast<const uint8_t*>(kMsg),
+ static_cast<wtf_size_t>(strlen(kMsg)));
EXPECT_EQ(strlen(kMsg), msg.size());
protocol::String encoded = Binary::fromVector(msg).toBase64();
@@ -45,7 +46,8 @@ TEST(ProtocolStringTest, HelloWorldBase64Roundtrip) {
Binary decoded_binary = Binary::fromBase64(encoded, &success);
EXPECT_TRUE(success);
Vector<uint8_t> decoded;
- decoded.Append(decoded_binary.data(), decoded_binary.size());
+ decoded.Append(decoded_binary.data(),
+ static_cast<wtf_size_t>(decoded_binary.size()));
EXPECT_EQ(msg, decoded);
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/resolve_node.cc b/chromium/third_party/blink/renderer/core/inspector/resolve_node.cc
index ad273cda4b6..3604e5563fb 100644
--- a/chromium/third_party/blink/renderer/core/inspector/resolve_node.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/resolve_node.cc
@@ -63,9 +63,6 @@ std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>
NullRemoteObject(v8_inspector::V8InspectorSession* v8_session,
LocalFrame* frame,
const String& object_group) {
- if (!frame)
- return nullptr;
-
ScriptState* script_state = ToScriptStateForMainWorld(frame);
if (!script_state)
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc
index ef054606736..0476d6675e4 100644
--- a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/rand_util.h"
-
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.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/v8_binding_for_core.h"
@@ -34,7 +34,9 @@
#include "third_party/blink/renderer/core/inspector/v8_inspector_string.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_dom_wrapper.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -250,10 +252,6 @@ ThreadDebugger::descriptionForValueSubtype(v8::Local<v8::Context> context,
return nullptr;
}
-bool ThreadDebugger::formatAccessorsAsProperties(v8::Local<v8::Value> value) {
- return V8DOMWrapper::IsWrapper(isolate_, value);
-}
-
double ThreadDebugger::currentTimeMS() {
return base::Time::Now().ToDoubleT() * 1000.0;
}
@@ -485,6 +483,8 @@ void ThreadDebugger::GetAccessibleNameCallback(
v8::Local<v8::Value> value = info[0];
Node* node = V8Node::ToImplWithTypeCheck(isolate, value);
+ if (node && !node->GetLayoutObject())
+ return;
if (auto* element = DynamicTo<Element>(node)) {
V8SetReturnValueString(info, element->computedName(), isolate);
}
@@ -500,6 +500,8 @@ void ThreadDebugger::GetAccessibleRoleCallback(
v8::Local<v8::Value> value = info[0];
Node* node = V8Node::ToImplWithTypeCheck(isolate, value);
+ if (node && !node->GetLayoutObject())
+ return;
if (auto* element = DynamicTo<Element>(node)) {
V8SetReturnValueString(info, element->computedRole(), isolate);
}
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 b9014a67440..26b90137755 100644
--- a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
+++ b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_THREAD_DEBUGGER_H_
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -26,6 +25,8 @@ class CORE_EXPORT ThreadDebugger : public v8_inspector::V8InspectorClient,
public V8PerIsolateData::Data {
public:
explicit ThreadDebugger(v8::Isolate*);
+ ThreadDebugger(const ThreadDebugger&) = delete;
+ ThreadDebugger& operator=(const ThreadDebugger&) = delete;
~ThreadDebugger() override;
static ThreadDebugger* From(v8::Isolate*);
@@ -88,7 +89,6 @@ class CORE_EXPORT ThreadDebugger : public v8_inspector::V8InspectorClient,
std::unique_ptr<v8_inspector::StringBuffer> descriptionForValueSubtype(
v8::Local<v8::Context>,
v8::Local<v8::Value>) override;
- bool formatAccessorsAsProperties(v8::Local<v8::Value>) override;
double currentTimeMS() override;
bool isInspectableHeapObject(v8::Local<v8::Object>) override;
void consoleTime(const v8_inspector::StringView& title) override;
@@ -120,7 +120,6 @@ class CORE_EXPORT ThreadDebugger : public v8_inspector::V8InspectorClient,
Vector<std::unique_ptr<TaskRunnerTimer<ThreadDebugger>>> timers_;
Vector<v8_inspector::V8InspectorClient::TimerCallback> timer_callbacks_;
Vector<void*> timer_data_;
- DISALLOW_COPY_AND_ASSIGN(ThreadDebugger);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.cc b/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
index c895b5f98f6..56aaacdef9c 100644
--- a/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
@@ -125,7 +125,7 @@ Binary Binary::fromVector(Vector<uint8_t> in) {
// static
Binary Binary::fromSpan(const uint8_t* data, size_t size) {
Vector<uint8_t> in;
- in.Append(data, size);
+ in.Append(data, base::checked_cast<wtf_size_t>(size));
return Binary::fromVector(std::move(in));
}
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 379dbd545de..773673c2ce8 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
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_emulation_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_issue_reporter.h"
#include "third_party/blink/renderer/core/inspector/inspector_log_agent.h"
+#include "third_party/blink/renderer/core/inspector/inspector_media_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_network_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/inspector/protocol/Protocol.h"
@@ -125,6 +126,8 @@ void WorkerInspectorController::AttachSession(DevToolsSession* session,
session->Append(MakeGarbageCollected<InspectorEmulationAgent>(nullptr));
session->Append(MakeGarbageCollected<InspectorAuditsAgent>(
network_agent, thread_->GetInspectorIssueStorage(), nullptr));
+ session->Append(MakeGarbageCollected<InspectorMediaAgent>(
+ inspected_frames_.Get(), scope));
}
++session_count_;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.h b/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
index 4473f86f3b7..ce1ff5ced4d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
+++ b/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_WORKER_INSPECTOR_CONTROLLER_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/unguessable_token.h"
#include "third_party/blink/renderer/core/inspector/devtools_agent.h"
@@ -69,6 +68,9 @@ class WorkerInspectorController final
WorkerThreadDebugger*,
scoped_refptr<InspectorTaskRunner>,
std::unique_ptr<WorkerDevToolsParams>);
+ WorkerInspectorController(const WorkerInspectorController&) = delete;
+ WorkerInspectorController& operator=(const WorkerInspectorController&) =
+ delete;
~WorkerInspectorController() override;
void Trace(Visitor*) const;
@@ -110,8 +112,6 @@ class WorkerInspectorController final
base::UnguessableToken parent_devtools_token_;
KURL url_;
const PlatformThreadId worker_thread_id_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerInspectorController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/worker_thread_debugger.h b/chromium/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
index 0730ec7119d..2a132e01c19 100644
--- a/chromium/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
+++ b/chromium/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_WORKER_THREAD_DEBUGGER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_WORKER_THREAD_DEBUGGER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
@@ -45,6 +44,8 @@ class WorkerThread;
class CORE_EXPORT WorkerThreadDebugger final : public ThreadDebugger {
public:
explicit WorkerThreadDebugger(v8::Isolate*);
+ WorkerThreadDebugger(const WorkerThreadDebugger&) = delete;
+ WorkerThreadDebugger& operator=(const WorkerThreadDebugger&) = delete;
~WorkerThreadDebugger() override;
static WorkerThreadDebugger* From(v8::Isolate*);
@@ -92,8 +93,6 @@ class CORE_EXPORT WorkerThreadDebugger final : public ThreadDebugger {
int paused_context_group_id_;
WTF::HashMap<int, WorkerThread*> worker_threads_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThreadDebugger);
};
} // namespace blink
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 701e1408643..129ca189d18 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
@@ -61,9 +61,10 @@ void ElementIntersectionObserverData::StopTrackingWithController(
bool ElementIntersectionObserverData::ComputeIntersectionsForTarget(
unsigned flags) {
bool needs_occlusion_tracking = false;
+ absl::optional<base::TimeTicks> monotonic_time;
for (auto& entry : observations_) {
needs_occlusion_tracking |= entry.key->NeedsOcclusionTracking();
- entry.value->ComputeIntersection(flags);
+ entry.value->ComputeIntersection(flags, monotonic_time);
}
return needs_occlusion_tracking;
}
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 92682df732a..2733008588d 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
@@ -21,6 +21,7 @@ class CORE_EXPORT ElementIntersectionObserverData final
public NameClient {
public:
ElementIntersectionObserverData();
+ ~ElementIntersectionObserverData() final = default;
// If the argument observer is observing this Element, this method will return
// the observation.
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
index 5d29116e158..32c71582e0b 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -307,6 +307,7 @@ void IntersectionGeometry::ComputeGeometry(const RootGeometry& root_geometry,
const Vector<Length>& target_margin,
CachedRects* cached_rects) {
DCHECK(cached_rects || !ShouldUseCachedRects());
+ flags_ |= kDidComputeGeometry;
// Initially:
// target_rect_ is in target's coordinate system
// root_rect_ is in root's coordinate system
@@ -513,9 +514,10 @@ bool IntersectionGeometry::ClipToRoot(const LayoutObject* root,
intersection_rect = unclipped_intersection_rect;
if (local_ancestor) {
if (local_ancestor->IsScrollContainer()) {
- PhysicalOffset scroll_offset = -PhysicalOffset(
- LayoutPoint(local_ancestor->ScrollOrigin()) +
- local_ancestor->PixelSnappedScrolledContentOffset());
+ PhysicalOffset scroll_offset =
+ -(PhysicalOffset(local_ancestor->ScrollOrigin()) +
+ PhysicalOffset(
+ local_ancestor->PixelSnappedScrolledContentOffset()));
intersection_rect.Move(scroll_offset);
unclipped_intersection_rect.Move(scroll_offset);
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
index 660514a8e83..ff662ebf215 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
@@ -42,7 +42,8 @@ class CORE_EXPORT IntersectionGeometry {
// These flags will be computed
kRootIsImplicit = 1 << 7,
- kIsVisible = 1 << 8
+ kDidComputeGeometry = 1 << 8,
+ kIsVisible = 1 << 9
};
struct RootGeometry {
@@ -125,6 +126,7 @@ class CORE_EXPORT IntersectionGeometry {
unsigned ThresholdIndex() const { return threshold_index_; }
bool RootIsImplicit() const { return flags_ & kRootIsImplicit; }
+ bool DidComputeGeometry() const { return flags_ & kDidComputeGeometry; }
bool IsIntersecting() const { return threshold_index_ > 0; }
bool IsVisible() const { return flags_ & kIsVisible; }
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 9da5dbd6755..1cc42dcea42 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
@@ -41,27 +41,58 @@ IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
cached_rects_ = std::make_unique<IntersectionGeometry::CachedRects>();
}
-void IntersectionObservation::ComputeIntersection(
+int64_t IntersectionObservation::ComputeIntersection(
const IntersectionGeometry::RootGeometry& root_geometry,
- unsigned compute_flags) {
+ unsigned compute_flags,
+ absl::optional<base::TimeTicks>& monotonic_time) {
+ DCHECK(Observer());
+ if (compute_flags &
+ (observer_->RootIsImplicit() ? kImplicitRootObserversNeedUpdate
+ : kExplicitRootObserversNeedUpdate)) {
+ needs_update_ = true;
+ }
if (!ShouldCompute(compute_flags))
- return;
+ return 0;
+ if (!monotonic_time.has_value())
+ monotonic_time = base::DefaultTickClock::GetInstance()->NowTicks();
+ DOMHighResTimeStamp timestamp = observer_->GetTimeStamp(*monotonic_time);
+ if (MaybeDelayAndReschedule(compute_flags, timestamp))
+ return 0;
DCHECK(observer_->root());
unsigned geometry_flags = GetIntersectionGeometryFlags(compute_flags);
IntersectionGeometry geometry(
root_geometry, *observer_->root(), *Target(), observer_->thresholds(),
observer_->TargetMargin(), geometry_flags, cached_rects_.get());
- ProcessIntersectionGeometry(geometry);
+ ProcessIntersectionGeometry(geometry, timestamp);
+ last_run_time_ = timestamp;
+ needs_update_ = false;
+ return geometry.DidComputeGeometry() ? 1 : 0;
}
-void IntersectionObservation::ComputeIntersection(unsigned compute_flags) {
+int64_t IntersectionObservation::ComputeIntersection(
+ unsigned compute_flags,
+ absl::optional<base::TimeTicks>& monotonic_time) {
+ DCHECK(Observer());
+ if (compute_flags &
+ (observer_->RootIsImplicit() ? kImplicitRootObserversNeedUpdate
+ : kExplicitRootObserversNeedUpdate)) {
+ needs_update_ = true;
+ }
if (!ShouldCompute(compute_flags))
- return;
+ return 0;
+ if (!monotonic_time.has_value())
+ monotonic_time = base::DefaultTickClock::GetInstance()->NowTicks();
+ DOMHighResTimeStamp timestamp = observer_->GetTimeStamp(*monotonic_time);
+ if (MaybeDelayAndReschedule(compute_flags, timestamp))
+ return 0;
unsigned geometry_flags = GetIntersectionGeometryFlags(compute_flags);
IntersectionGeometry geometry(
observer_->root(), *Target(), observer_->RootMargin(),
observer_->thresholds(), observer_->TargetMargin(), geometry_flags);
- ProcessIntersectionGeometry(geometry);
+ ProcessIntersectionGeometry(geometry, timestamp);
+ last_run_time_ = timestamp;
+ needs_update_ = false;
+ return geometry.DidComputeGeometry() ? 1 : 0;
}
void IntersectionObservation::TakeRecords(
@@ -99,11 +130,9 @@ void IntersectionObservation::Trace(Visitor* visitor) const {
visitor->Trace(target_);
}
-bool IntersectionObservation::ShouldCompute(unsigned flags) {
- DCHECK(Observer());
+bool IntersectionObservation::ShouldCompute(unsigned flags) const {
if (!target_ || !observer_->RootIsValid() | !observer_->GetExecutionContext())
return false;
-
// If we're processing post-layout deliveries only and we don't have a
// post-layout delivery observer, then return early. Likewise, return if we
// need to compute non-post-layout-delivery observations but the observer
@@ -114,23 +143,8 @@ bool IntersectionObservation::ShouldCompute(unsigned flags) {
IntersectionObserver::kDeliverDuringPostLayoutSteps;
if (post_layout_delivery_only != is_post_layout_delivery_observer)
return false;
-
- if (flags &
- (observer_->RootIsImplicit() ? kImplicitRootObserversNeedUpdate
- : kExplicitRootObserversNeedUpdate)) {
- needs_update_ = true;
- }
if (!needs_update_)
return false;
- DOMHighResTimeStamp timestamp = observer_->GetTimeStamp();
- if (timestamp == -1)
- return false;
- base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
- observer_->GetEffectiveDelay() - (timestamp - last_run_time_));
- if (!(flags & kIgnoreDelay) && delay > base::TimeDelta()) {
- TrackingDocument(this).View()->ScheduleAnimation(delay);
- return false;
- }
if (target_->isConnected() && Observer()->trackVisibility()) {
mojom::blink::FrameOcclusionState occlusion_state =
target_->GetDocument().GetFrame()->GetOcclusionState();
@@ -140,11 +154,23 @@ bool IntersectionObservation::ShouldCompute(unsigned flags) {
if (occlusion_state == mojom::blink::FrameOcclusionState::kUnknown)
return false;
}
- last_run_time_ = timestamp;
- needs_update_ = false;
return true;
}
+bool IntersectionObservation::MaybeDelayAndReschedule(
+ unsigned flags,
+ DOMHighResTimeStamp timestamp) {
+ if (timestamp == -1)
+ return true;
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
+ observer_->GetEffectiveDelay() - (timestamp - last_run_time_));
+ if (!(flags & kIgnoreDelay) && delay > base::TimeDelta()) {
+ TrackingDocument(this).View()->ScheduleAnimation(delay);
+ return true;
+ }
+ return false;
+}
+
bool IntersectionObservation::CanUseCachedRects() const {
if (!cached_rects_ || !cached_rects_->valid ||
!observer_->CanUseCachedRects()) {
@@ -206,15 +232,15 @@ unsigned IntersectionObservation::GetIntersectionGeometryFlags(
}
void IntersectionObservation::ProcessIntersectionGeometry(
- const IntersectionGeometry& geometry) {
- // TODO(tkent): We can't use CHECK_LT due to a compile error.
- CHECK(geometry.ThresholdIndex() < kMaxThresholdIndex - 1);
+ const IntersectionGeometry& geometry,
+ DOMHighResTimeStamp timestamp) {
+ CHECK_LT(geometry.ThresholdIndex(), kMaxThresholdIndex - 1);
if (last_threshold_index_ != geometry.ThresholdIndex() ||
last_is_visible_ != geometry.IsVisible()) {
entries_.push_back(MakeGarbageCollected<IntersectionObserverEntry>(
- geometry, last_run_time_, Target()));
- Observer()->SetNeedsDelivery();
+ geometry, timestamp, Target()));
+ Observer()->ReportUpdates(*this);
SetLastThresholdIndex(geometry.ThresholdIndex());
SetWasVisible(geometry.IsVisible());
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
index 308a555bb47..8ab358e0ac1 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_INTERSECTION_OBSERVATION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_INTERSECTION_OBSERVATION_H_
+#include "third_party/abseil-cpp/absl/types/optional.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/core/intersection_observer/intersection_geometry.h"
@@ -36,18 +37,24 @@ class CORE_EXPORT IntersectionObservation final
// If this bit is set, and observer_->RootIsImplicit() is true, then
// Compute() should update the observation.
kImplicitRootObserversNeedUpdate = 1 << 2,
+ // If this bit is set, it indicates that at least one LocalFrameView
+ // ancestor is detached from the LayoutObject tree of its parent. Usually,
+ // this is unnecessary -- if an ancestor FrameView is detached, then all
+ // descendant frames are detached. There is, however, at least one exception
+ // to this rule; see crbug.com/749737 for details.
+ kAncestorFrameIsDetachedFromLayout = 1 << 3,
// If this bit is set, then the observer.delay parameter is ignored; i.e.,
// the computation will run even if the previous run happened within the
// delay parameter.
- kIgnoreDelay = 1 << 3,
+ kIgnoreDelay = 1 << 4,
// If this bit is set, we can skip tracking the sticky frame during
// UpdateViewportIntersectionsForSubtree.
- kCanSkipStickyFrameTracking = 1 << 4,
+ kCanSkipStickyFrameTracking = 1 << 5,
// If this bit is set, we only process intersection observations that
// require post-layout delivery.
- kPostLayoutDeliveryOnly = 1 << 5,
+ kPostLayoutDeliveryOnly = 1 << 6,
// If this is set, the overflow clip edge is used.
- kUseOverflowClipEdge = 1 << 6,
+ kUseOverflowClipEdge = 1 << 7,
};
IntersectionObservation(IntersectionObserver&, Element&);
@@ -55,10 +62,14 @@ class CORE_EXPORT IntersectionObservation final
IntersectionObserver* Observer() const { return observer_.Get(); }
Element* Target() const { return target_; }
unsigned LastThresholdIndex() const { return last_threshold_index_; }
- void ComputeIntersection(unsigned flags);
- void ComputeIntersection(
+ // Returns 1 if the geometry was recalculated, otherwise 0. This could be a
+ // bool, but int64_t matches IntersectionObserver::ComputeIntersections().
+ int64_t ComputeIntersection(unsigned flags,
+ absl::optional<base::TimeTicks>& monotonic_time);
+ int64_t ComputeIntersection(
const IntersectionGeometry::RootGeometry& root_geometry,
- unsigned flags);
+ unsigned flags,
+ absl::optional<base::TimeTicks>& monotonic_time);
void TakeRecords(HeapVector<Member<IntersectionObserverEntry>>&);
void Disconnect();
void InvalidateCachedRects();
@@ -68,12 +79,14 @@ class CORE_EXPORT IntersectionObservation final
bool CanUseCachedRectsForTesting() const { return CanUseCachedRects(); }
private:
- bool ShouldCompute(unsigned flags);
+ bool ShouldCompute(unsigned flags) const;
+ bool MaybeDelayAndReschedule(unsigned flags, DOMHighResTimeStamp timestamp);
bool CanUseCachedRects() const;
unsigned GetIntersectionGeometryFlags(unsigned compute_flags) const;
// Inspect the geometry to see if there has been a transition event; if so,
// generate a notification and schedule it for delivery.
- void ProcessIntersectionGeometry(const IntersectionGeometry& geometry);
+ void ProcessIntersectionGeometry(const IntersectionGeometry& geometry,
+ DOMHighResTimeStamp timestamp);
void SetLastThresholdIndex(unsigned index) { last_threshold_index_ = index; }
void SetWasVisible(bool last_is_visible) {
last_is_visible_ = last_is_visible ? 1 : 0;
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 16227057273..cf0bd7c21ca 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
@@ -12,6 +12,8 @@
#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/bindings/core/v8/v8_intersection_observer_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_element.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_doublesequence.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"
@@ -133,15 +135,19 @@ void ParseMargin(String margin_parameter,
}
}
-void ParseThresholds(const DoubleOrDoubleSequence& threshold_parameter,
- Vector<float>& thresholds,
- ExceptionState& exception_state) {
- if (threshold_parameter.IsDouble()) {
- thresholds.push_back(
- base::MakeClampedNum<float>(threshold_parameter.GetAsDouble()));
- } else {
- for (auto threshold_value : threshold_parameter.GetAsDoubleSequence())
- thresholds.push_back(base::MakeClampedNum<float>(threshold_value));
+void ParseThresholds(
+ const V8UnionDoubleOrDoubleSequence* threshold_parameter,
+ Vector<float>& thresholds,
+ ExceptionState& exception_state) {
+ switch (threshold_parameter->GetContentType()) {
+ case V8UnionDoubleOrDoubleSequence::ContentType::kDouble:
+ thresholds.push_back(
+ base::MakeClampedNum<float>(threshold_parameter->GetAsDouble()));
+ break;
+ case V8UnionDoubleOrDoubleSequence::ContentType::kDoubleSequence:
+ for (auto threshold_value : threshold_parameter->GetAsDoubleSequence())
+ thresholds.push_back(base::MakeClampedNum<float>(threshold_value));
+ break;
}
if (thresholds.IsEmpty())
@@ -174,10 +180,15 @@ IntersectionObserver* IntersectionObserver::Create(
IntersectionObserverDelegate& delegate,
ExceptionState& exception_state) {
Node* root = nullptr;
- if (observer_init->root().IsElement()) {
- root = observer_init->root().GetAsElement();
- } else if (observer_init->root().IsDocument()) {
- root = observer_init->root().GetAsDocument();
+ if (observer_init->root()) {
+ switch (observer_init->root()->GetContentType()) {
+ case V8UnionDocumentOrElement::ContentType::kDocument:
+ root = observer_init->root()->GetAsDocument();
+ break;
+ case V8UnionDocumentOrElement::ContentType::kElement:
+ root = observer_init->root()->GetAsElement();
+ break;
+ }
}
DOMHighResTimeStamp delay = 0;
@@ -272,7 +283,6 @@ IntersectionObserver::IntersectionObserver(
track_visibility_(track_visibility),
track_fraction_of_root_(semantics == kFractionOfRoot),
always_report_root_bounds_(always_report_root_bounds),
- needs_delivery_(0),
can_use_cached_rects_(0),
use_overflow_clip_edge_(use_overflow_clip_edge) {
switch (margin.size()) {
@@ -356,12 +366,15 @@ void IntersectionObserver::observe(Element* target,
} else {
// The IntersectionObsever spec requires that at least one observation
// be recorded after observe() is called, even if the target is detached.
+ absl::optional<base::TimeTicks> monotonic_time;
observation->ComputeIntersection(
IntersectionObservation::kImplicitRootObserversNeedUpdate |
- IntersectionObservation::kExplicitRootObserversNeedUpdate |
- IntersectionObservation::kIgnoreDelay |
- (use_overflow_clip_edge_ ? IntersectionObservation::kUseOverflowClipEdge
- : 0));
+ IntersectionObservation::kExplicitRootObserversNeedUpdate |
+ IntersectionObservation::kIgnoreDelay |
+ (use_overflow_clip_edge_
+ ? IntersectionObservation::kUseOverflowClipEdge
+ : 0),
+ monotonic_time);
}
}
@@ -377,6 +390,7 @@ void IntersectionObserver::unobserve(Element* target,
observation->Disconnect();
observations_.erase(observation);
+ active_observations_.erase(observation);
if (root() && root()->isConnected() && observations_.IsEmpty()) {
root()
->GetDocument()
@@ -389,6 +403,7 @@ void IntersectionObserver::disconnect(ExceptionState& exception_state) {
for (auto& observation : observations_)
observation->Disconnect();
observations_.clear();
+ active_observations_.clear();
if (root() && root()->isConnected()) {
root()
->GetDocument()
@@ -399,10 +414,10 @@ void IntersectionObserver::disconnect(ExceptionState& exception_state) {
HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords(
ExceptionState& exception_state) {
- needs_delivery_ = 0;
HeapVector<Member<IntersectionObserverEntry>> entries;
for (auto& observation : observations_)
observation->TakeRecords(entries);
+ active_observations_.clear();
return entries;
}
@@ -436,16 +451,19 @@ DOMHighResTimeStamp IntersectionObserver::GetEffectiveDelay() const {
return throttle_delay_enabled ? delay_ : 0;
}
-DOMHighResTimeStamp IntersectionObserver::GetTimeStamp() const {
+DOMHighResTimeStamp IntersectionObserver::GetTimeStamp(
+ base::TimeTicks monotonic_time) const {
return DOMWindowPerformance::performance(
*To<LocalDOMWindow>(delegate_->GetExecutionContext()))
- ->now();
+ ->MonotonicTimeToDOMHighResTimeStamp(monotonic_time);
}
-bool IntersectionObserver::ComputeIntersections(unsigned flags) {
+int64_t IntersectionObserver::ComputeIntersections(
+ unsigned flags,
+ absl::optional<base::TimeTicks>& monotonic_time) {
DCHECK(!RootIsImplicit());
if (!RootIsValid() || !GetExecutionContext() || observations_.IsEmpty())
- return false;
+ return 0;
// If we're processing post-layout deliveries only and we're not a post-layout
// delivery observer, then return early. Likewise, return if we need to
@@ -457,7 +475,7 @@ bool IntersectionObserver::ComputeIntersections(unsigned flags) {
GetDeliveryBehavior() ==
IntersectionObserver::kDeliverDuringPostLayoutSteps;
if (post_layout_delivery_only != is_post_layout_delivery_observer)
- return false;
+ return 0;
if (use_overflow_clip_edge_)
flags |= IntersectionObservation::kUseOverflowClipEdge;
@@ -469,25 +487,35 @@ bool IntersectionObserver::ComputeIntersections(unsigned flags) {
HeapVector<Member<IntersectionObservation>> observations_to_process;
// TODO(szager): Is this copy necessary?
CopyToVector(observations_, observations_to_process);
+ int64_t result = 0;
for (auto& observation : observations_to_process) {
- observation->ComputeIntersection(root_geometry, flags);
+ result +=
+ observation->ComputeIntersection(root_geometry, flags, monotonic_time);
}
can_use_cached_rects_ = 1;
- return trackVisibility();
+ return result;
+}
+
+bool IntersectionObserver::IsInternal() const {
+ return GetUkmMetricId() !=
+ LocalFrameUkmAggregator::kJavascriptIntersectionObserver;
}
LocalFrameUkmAggregator::MetricId IntersectionObserver::GetUkmMetricId() const {
return delegate_->GetUkmMetricId();
}
-void IntersectionObserver::SetNeedsDelivery() {
- if (needs_delivery_)
- return;
- needs_delivery_ = 1;
- To<LocalDOMWindow>(GetExecutionContext())
- ->document()
- ->EnsureIntersectionObserverController()
- .ScheduleIntersectionObserverForDelivery(*this);
+void IntersectionObserver::ReportUpdates(IntersectionObservation& observation) {
+ DCHECK_EQ(observation.Observer(), this);
+ bool needs_scheduling = active_observations_.IsEmpty();
+ active_observations_.insert(&observation);
+
+ if (needs_scheduling) {
+ To<LocalDOMWindow>(GetExecutionContext())
+ ->document()
+ ->EnsureIntersectionObserverController()
+ .ScheduleIntersectionObserverForDelivery(*this);
+ }
}
IntersectionObserver::DeliveryBehavior
@@ -496,18 +524,18 @@ IntersectionObserver::GetDeliveryBehavior() const {
}
void IntersectionObserver::Deliver() {
- if (!needs_delivery_)
+ if (!NeedsDelivery())
return;
- needs_delivery_ = 0;
HeapVector<Member<IntersectionObserverEntry>> entries;
for (auto& observation : observations_)
observation->TakeRecords(entries);
+ active_observations_.clear();
if (entries.size())
delegate_->Deliver(entries, *this);
}
bool IntersectionObserver::HasPendingActivity() const {
- return !observations_.IsEmpty();
+ return NeedsDelivery();
}
void IntersectionObserver::Trace(Visitor* visitor) const {
@@ -515,6 +543,7 @@ void IntersectionObserver::Trace(Visitor* visitor) const {
IntersectionObserver, &IntersectionObserver::ProcessCustomWeakness>(this);
visitor->Trace(delegate_);
visitor->Trace(observations_);
+ visitor->Trace(active_observations_);
ScriptWrappable::Trace(visitor);
ExecutionContextClient::Trace(visitor);
}
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 222c30f6f32..feb1cd02e00 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
@@ -156,7 +156,7 @@ class CORE_EXPORT IntersectionObserver final
return trackVisibility() && !observations_.IsEmpty();
}
- DOMHighResTimeStamp GetTimeStamp() const;
+ DOMHighResTimeStamp GetTimeStamp(base::TimeTicks monotonic_time) const;
DOMHighResTimeStamp GetEffectiveDelay() const;
Vector<Length> RootMargin() const {
return margin_target_ == kApplyMarginToRoot ? margin_ : Vector<Length>();
@@ -165,11 +165,14 @@ class CORE_EXPORT IntersectionObserver final
return margin_target_ == kApplyMarginToTarget ? margin_ : Vector<Length>();
}
- bool ComputeIntersections(unsigned flags);
+ // Returns the number of IntersectionObservations that recomputed geometry.
+ int64_t ComputeIntersections(unsigned flags,
+ absl::optional<base::TimeTicks>& monotonic_time);
+ bool IsInternal() const;
LocalFrameUkmAggregator::MetricId GetUkmMetricId() const;
- void SetNeedsDelivery();
+ void ReportUpdates(IntersectionObservation&);
DeliveryBehavior GetDeliveryBehavior() const;
void Deliver();
@@ -191,6 +194,7 @@ class CORE_EXPORT IntersectionObserver final
static void SetThrottleDelayEnabledForTesting(bool);
private:
+ bool NeedsDelivery() const { return !active_observations_.IsEmpty(); }
void ProcessCustomWeakness(const LivenessBroker&);
const Member<IntersectionObserverDelegate> delegate_;
@@ -199,6 +203,8 @@ class CORE_EXPORT IntersectionObserver final
UntracedMember<Node> root_;
HeapLinkedHashSet<WeakMember<IntersectionObservation>> observations_;
+ // Observations that have updates waiting to be delivered
+ HeapHashSet<Member<IntersectionObservation>> active_observations_;
Vector<float> thresholds_;
DOMHighResTimeStamp delay_;
Vector<Length> margin_;
@@ -207,7 +213,6 @@ class CORE_EXPORT IntersectionObserver final
unsigned track_visibility_ : 1;
unsigned track_fraction_of_root_ : 1;
unsigned always_report_root_bounds_ : 1;
- unsigned needs_delivery_ : 1;
unsigned can_use_cached_rects_ : 1;
unsigned use_overflow_clip_edge_ : 1;
};
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 eebd60c431d..9d85096e384 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
@@ -62,31 +62,53 @@ void IntersectionObserverController::DeliverNotifications(
bool IntersectionObserverController::ComputeIntersections(
unsigned flags,
- LocalFrameUkmAggregator& ukm_aggregator) {
+ LocalFrameUkmAggregator& ukm_aggregator,
+ absl::optional<base::TimeTicks>& monotonic_time) {
needs_occlusion_tracking_ = false;
- if (GetExecutionContext()) {
- TRACE_EVENT0("blink,devtools.timeline",
- "IntersectionObserverController::"
- "computeIntersections");
- HeapVector<Member<IntersectionObserver>> observers_to_process;
- CopyToVector(tracked_explicit_root_observers_, observers_to_process);
+ if (!GetExecutionContext())
+ return false;
+ TRACE_EVENT0("blink,devtools.timeline",
+ "IntersectionObserverController::"
+ "computeIntersections");
+ HeapVector<Member<IntersectionObserver>> observers_to_process;
+ CopyToVector(tracked_explicit_root_observers_, observers_to_process);
+ HeapVector<Member<IntersectionObservation>> observations_to_process;
+ CopyToVector(tracked_implicit_root_observations_, observations_to_process);
+ int64_t internal_observation_count = 0;
+ int64_t javascript_observation_count = 0;
+ {
+ LocalFrameUkmAggregator::IterativeTimer ukm_timer(ukm_aggregator);
for (auto& observer : observers_to_process) {
if (observer->HasObservations()) {
- SCOPED_UMA_AND_UKM_TIMER(ukm_aggregator, observer->GetUkmMetricId());
- needs_occlusion_tracking_ |= observer->ComputeIntersections(flags);
+ ukm_timer.StartInterval(observer->GetUkmMetricId());
+ int64_t count = observer->ComputeIntersections(flags, monotonic_time);
+ if (observer->IsInternal())
+ internal_observation_count += count;
+ else
+ javascript_observation_count += count;
+ needs_occlusion_tracking_ |= observer->trackVisibility();
} else {
tracked_explicit_root_observers_.erase(observer);
}
}
- HeapVector<Member<IntersectionObservation>> observations_to_process;
- CopyToVector(tracked_implicit_root_observations_, observations_to_process);
for (auto& observation : observations_to_process) {
- SCOPED_UMA_AND_UKM_TIMER(ukm_aggregator,
- observation->Observer()->GetUkmMetricId());
- observation->ComputeIntersection(flags);
+ ukm_timer.StartInterval(observation->Observer()->GetUkmMetricId());
+ int64_t count = observation->ComputeIntersection(flags, monotonic_time);
+ if (observation->Observer()->IsInternal())
+ internal_observation_count += count;
+ else
+ javascript_observation_count += count;
needs_occlusion_tracking_ |= observation->Observer()->trackVisibility();
}
}
+
+ ukm_aggregator.RecordCountSample(
+ LocalFrameUkmAggregator::kIntersectionObservationInternalCount,
+ internal_observation_count);
+ ukm_aggregator.RecordCountSample(
+ LocalFrameUkmAggregator::kIntersectionObservationJavascriptCount,
+ javascript_observation_count);
+
return needs_occlusion_tracking_;
}
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 1283d139b34..cc4947d5fd3 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
@@ -24,7 +24,7 @@ class IntersectionObserverController
public NameClient {
public:
explicit IntersectionObserverController(ExecutionContext*);
- virtual ~IntersectionObserverController();
+ ~IntersectionObserverController() override;
void ScheduleIntersectionObserverForDelivery(IntersectionObserver&);
@@ -38,7 +38,8 @@ class IntersectionObserverController
// communicates whether observer->trackVisibility() is true for any tracked
// observer.
bool ComputeIntersections(unsigned flags,
- LocalFrameUkmAggregator& ukm_aggregator);
+ LocalFrameUkmAggregator& ukm_aggregator,
+ absl::optional<base::TimeTicks>& monotonic_time);
// The second argument indicates whether the Element is a target of any
// observers for which observer->trackVisibility() is true.
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 7d5c2eec647..890c4b24883 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
@@ -19,7 +19,7 @@ class IntersectionObserverDelegate
: public GarbageCollected<IntersectionObserverDelegate>,
public NameClient {
public:
- virtual ~IntersectionObserverDelegate() = default;
+ ~IntersectionObserverDelegate() override = default;
virtual LocalFrameUkmAggregator::MetricId GetUkmMetricId() const = 0;
virtual IntersectionObserver::DeliveryBehavior GetDeliveryBehavior()
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 ecced036db2..09645c44371 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
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "build/build_config.h"
-
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.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_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_element.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"
@@ -87,7 +87,7 @@ TEST_F(IntersectionObserverTest, NotificationSentWhenRootRemoved) {
Element* root = GetDocument().getElementById("root");
ASSERT_TRUE(root);
IntersectionObserverInit* observer_init = IntersectionObserverInit::Create();
- observer_init->setRoot(ElementOrDocument::FromElement(root));
+ observer_init->setRoot(MakeGarbageCollected<V8UnionDocumentOrElement>(root));
DummyExceptionStateForTesting exception_state;
TestIntersectionObserverDelegate* observer_delegate =
MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
@@ -133,7 +133,8 @@ TEST_F(IntersectionObserverTest, DocumentRootClips) {
->GetFrame()
->GetDocument();
IntersectionObserverInit* observer_init = IntersectionObserverInit::Create();
- observer_init->setRoot(ElementOrDocument::FromDocument(iframe_document));
+ observer_init->setRoot(
+ MakeGarbageCollected<V8UnionDocumentOrElement>(iframe_document));
DummyExceptionStateForTesting exception_state;
TestIntersectionObserverDelegate* observer_delegate =
MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
@@ -545,7 +546,7 @@ TEST_F(IntersectionObserverTest, TrackedRootBookkeeping) {
Persistent<Element> target = GetDocument().getElementById("target1");
Persistent<IntersectionObserverInit> observer_init =
IntersectionObserverInit::Create();
- observer_init->setRoot(ElementOrDocument::FromElement(root));
+ observer_init->setRoot(MakeGarbageCollected<V8UnionDocumentOrElement>(root));
Persistent<TestIntersectionObserverDelegate> observer_delegate =
MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
Persistent<IntersectionObserver> observer =
@@ -640,6 +641,103 @@ TEST_F(IntersectionObserverTest, TrackedRootBookkeeping) {
EXPECT_EQ(controller.GetTrackedObservationCountForTesting(), 0u);
}
+TEST_F(IntersectionObserverTest, InaccessibleTarget) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <div id=target></div>
+ )HTML");
+
+ Persistent<TestIntersectionObserverDelegate> observer_delegate =
+ MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
+ Persistent<IntersectionObserver> observer = IntersectionObserver::Create(
+ IntersectionObserverInit::Create(), *observer_delegate);
+
+ Persistent<Element> target = GetDocument().getElementById("target");
+ ASSERT_EQ(observer_delegate->CallCount(), 0);
+ ASSERT_FALSE(observer->HasPendingActivity());
+
+ // When we start observing a target, we should queue up a task to deliver the
+ // observation. The observer should have pending activity.
+ observer->observe(target);
+ Compositor().BeginFrame();
+ ASSERT_EQ(observer_delegate->CallCount(), 0);
+ EXPECT_TRUE(observer->HasPendingActivity());
+
+ // After the observation is delivered, the observer no longer has activity
+ // pending.
+ test::RunPendingTasks();
+ ASSERT_EQ(observer_delegate->CallCount(), 1);
+ EXPECT_FALSE(observer->HasPendingActivity());
+
+ WeakPersistent<TestIntersectionObserverDelegate> observer_delegate_weak =
+ observer_delegate.Get();
+ WeakPersistent<IntersectionObserver> observer_weak = observer.Get();
+ WeakPersistent<Element> target_weak = target.Get();
+ ASSERT_TRUE(target_weak);
+ ASSERT_TRUE(observer_weak);
+ ASSERT_TRUE(observer_delegate_weak);
+
+ // When |target| is no longer live, and |observer| has no more pending tasks,
+ // both should be garbage-collected.
+ target->remove();
+ target = nullptr;
+ observer = nullptr;
+ observer_delegate = nullptr;
+ test::RunPendingTasks();
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_FALSE(target_weak);
+ EXPECT_FALSE(observer_weak);
+ EXPECT_FALSE(observer_delegate_weak);
+}
+
+TEST_F(IntersectionObserverTest, InaccessibleTargetBeforeDelivery) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <div id=target></div>
+ )HTML");
+
+ Persistent<TestIntersectionObserverDelegate> observer_delegate =
+ MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
+ Persistent<IntersectionObserver> observer = IntersectionObserver::Create(
+ IntersectionObserverInit::Create(), *observer_delegate);
+
+ Persistent<Element> target = GetDocument().getElementById("target");
+ ASSERT_EQ(observer_delegate->CallCount(), 0);
+ ASSERT_FALSE(observer->HasPendingActivity());
+
+ WeakPersistent<TestIntersectionObserverDelegate> observer_delegate_weak =
+ observer_delegate.Get();
+ WeakPersistent<IntersectionObserver> observer_weak = observer.Get();
+ WeakPersistent<Element> target_weak = target.Get();
+ ASSERT_TRUE(target_weak);
+ ASSERT_TRUE(observer_weak);
+ ASSERT_TRUE(observer_delegate_weak);
+
+ // When we start observing |target|, a task should be queued to call the
+ // callback with |target| and other information. So even if we remove
+ // |target| in the same tick, |observer| would be kept alive.
+ observer->observe(target);
+ target->remove();
+ target = nullptr;
+ observer = nullptr;
+ observer_delegate = nullptr;
+ Compositor().BeginFrame();
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_TRUE(target_weak);
+ EXPECT_TRUE(observer_weak);
+ EXPECT_TRUE(observer_delegate_weak);
+
+ // Once we run the callback, the observer has no more pending tasks, and so
+ // it should be garbage-collected along with the target.
+ test::RunPendingTasks();
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_FALSE(target_weak);
+ EXPECT_FALSE(observer_weak);
+ EXPECT_FALSE(observer_delegate_weak);
+}
+
TEST_F(IntersectionObserverTest, RootMarginDevicePixelRatio) {
WebView().SetZoomFactorForDeviceScaleFactor(3.5f);
WebView().MainFrameViewWidget()->Resize(gfx::Size(2800, 2100));
@@ -707,7 +805,7 @@ TEST_F(IntersectionObserverTest, CachedRectsTest) {
Element* target2 = GetDocument().getElementById("target2");
IntersectionObserverInit* observer_init = IntersectionObserverInit::Create();
- observer_init->setRoot(ElementOrDocument::FromElement(root));
+ observer_init->setRoot(MakeGarbageCollected<V8UnionDocumentOrElement>(root));
DummyExceptionStateForTesting exception_state;
TestIntersectionObserverDelegate* observer_delegate =
MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
diff --git a/chromium/third_party/blink/renderer/core/layout/OWNERS b/chromium/third_party/blink/renderer/core/layout/OWNERS
index ddf235e82c9..ae456c6ebda 100644
--- a/chromium/third_party/blink/renderer/core/layout/OWNERS
+++ b/chromium/third_party/blink/renderer/core/layout/OWNERS
@@ -1,12 +1,10 @@
atotic@chromium.org
cbiesinger@chromium.org
chrishtr@chromium.org
-fmalita@chromium.org
fs@opera.com
pdr@chromium.org
schenney@chromium.org
skobes@chromium.org
-svillar@igalia.com
tkent@chromium.org
wangxianzhu@chromium.org
xiaochengh@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h b/chromium/third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h
index 7008563d988..e7c0126f378 100644
--- a/chromium/third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h
+++ b/chromium/third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_ADJUST_FOR_ABSOLUTE_ZOOM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_ADJUST_FOR_ABSOLUTE_ZOOM_H_
+#include "third_party/blink/renderer/core/layout/geometry/physical_size.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/geometry/layout_unit.h"
@@ -79,6 +80,11 @@ class AdjustForAbsoluteZoom {
LayoutObject& layout_object) {
return AdjustLayoutUnit(value, layout_object.StyleRef());
}
+ inline static PhysicalSize AdjustPhysicalSize(PhysicalSize size,
+ const ComputedStyle& style) {
+ return PhysicalSize(AdjustLayoutUnit(size.width, style),
+ AdjustLayoutUnit(size.height, style));
+ }
inline static void AdjustFloatQuad(FloatQuad& quad,
const LayoutObject& layout_object) {
diff --git a/chromium/third_party/blink/renderer/core/layout/api/line_layout_box.h b/chromium/third_party/blink/renderer/core/layout/api/line_layout_box.h
index 663b29fc51f..309a9cfb3c4 100644
--- a/chromium/third_party/blink/renderer/core/layout/api/line_layout_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/api/line_layout_box.h
@@ -79,7 +79,7 @@ class LineLayoutBox : public LineLayoutBoxModel {
void SetSize(const LayoutSize& size) { return ToBox()->SetSize(size); }
- LayoutSize ScrolledContentOffset() const {
+ PhysicalOffset ScrolledContentOffset() const {
return ToBox()->ScrolledContentOffset();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.cc b/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.cc
new file mode 100644
index 00000000000..fcf45236ecf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.cc
@@ -0,0 +1,67 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
+
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
+#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
+#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
+
+namespace blink {
+
+Node* LineLayoutItem::GetNodeForOwnerNodeId() const {
+ auto* layout_text_fragment = DynamicTo<LayoutTextFragment>(layout_object_);
+ if (layout_text_fragment)
+ return layout_text_fragment->AssociatedTextNode();
+ return layout_object_->GetNode();
+}
+
+const ComputedStyle* LineLayoutItem::Style(bool first_line) const {
+ return layout_object_->Style(first_line);
+}
+
+const ComputedStyle& LineLayoutItem::StyleRef(bool first_line) const {
+ return layout_object_->StyleRef(first_line);
+}
+
+bool LineLayoutItem::IsEmptyText() const {
+ return IsText() && To<LayoutText>(layout_object_)->GetText().IsEmpty();
+}
+
+int LineLayoutItem::CaretMaxOffset() const {
+ if (layout_object_->IsAtomicInlineLevel()) {
+ if (Node* const node = layout_object_->GetNode())
+ return std::max(1u, GetNode()->CountChildren());
+ return 1;
+ }
+ if (layout_object_->IsHR())
+ return 1;
+ return 0;
+}
+
+PositionWithAffinity LineLayoutItem::PositionForPoint(
+ const PhysicalOffset& point) {
+ return layout_object_->PositionForPoint(point);
+}
+
+PositionWithAffinity LineLayoutItem::CreatePositionWithAffinity(
+ int offset,
+ TextAffinity affinity) const {
+ return layout_object_->CreatePositionWithAffinity(offset, affinity);
+}
+
+PositionWithAffinity LineLayoutItem::PositionAfterThis() const {
+ return layout_object_->PositionAfterThis();
+}
+
+PositionWithAffinity LineLayoutItem::PositionBeforeThis() const {
+ return layout_object_->PositionBeforeThis();
+}
+
+void LineLayoutItem::SlowSetPaintingLayerNeedsRepaint() {
+ ObjectPaintInvalidator(*layout_object_).SlowSetPaintingLayerNeedsRepaint();
+}
+
+} // namespace blink
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 07fb907c449..fafd5606b7e 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
@@ -6,15 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_ITEM_H_
#include "base/dcheck_is_on.h"
-#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-#include "third_party/blink/renderer/core/layout/layout_text.h"
-#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
namespace blink {
@@ -22,7 +14,6 @@ class ComputedStyle;
class Document;
class HitTestRequest;
class HitTestLocation;
-class LayoutObject;
class LineLayoutBox;
class LineLayoutAPIShim;
@@ -65,12 +56,7 @@ class LineLayoutItem {
Node* NonPseudoNode() const { return layout_object_->NonPseudoNode(); }
- Node* GetNodeForOwnerNodeId() const {
- auto* layout_text_fragment = DynamicTo<LayoutTextFragment>(layout_object_);
- if (layout_text_fragment)
- return layout_text_fragment->AssociatedTextNode();
- return layout_object_->GetNode();
- }
+ Node* GetNodeForOwnerNodeId() const;
LineLayoutItem Parent() const {
return LineLayoutItem(layout_object_->Parent());
@@ -115,13 +101,9 @@ class LineLayoutItem {
const ComputedStyle& StyleRef() const { return layout_object_->StyleRef(); }
- const ComputedStyle* Style(bool first_line) const {
- return layout_object_->Style(first_line);
- }
+ const ComputedStyle* Style(bool first_line) const;
- const ComputedStyle& StyleRef(bool first_line) const {
- return layout_object_->StyleRef(first_line);
- }
+ const ComputedStyle& StyleRef(bool first_line) const;
Document& GetDocument() const { return layout_object_->GetDocument(); }
@@ -212,9 +194,7 @@ class LineLayoutItem {
bool IsText() const { return layout_object_->IsText(); }
- bool IsEmptyText() const {
- return IsText() && To<LayoutText>(layout_object_)->GetText().IsEmpty();
- }
+ bool IsEmptyText() const;
bool HasLayer() const { return layout_object_->HasLayer(); }
@@ -231,16 +211,7 @@ class LineLayoutItem {
// TODO(yosin): We should not use |CaretMaxOffset()|, because this function
// may be used for creating invalid pointer, e.g. <hr>@1.
- int CaretMaxOffset() const {
- if (layout_object_->IsAtomicInlineLevel()) {
- if (Node* const node = layout_object_->GetNode())
- return std::max(1u, GetNode()->CountChildren());
- return 1;
- }
- if (layout_object_->IsHR())
- return 1;
- return 0;
- }
+ int CaretMaxOffset() const;
bool HasFlippedBlocksWritingMode() const {
return layout_object_->HasFlippedBlocksWritingMode();
@@ -273,22 +244,14 @@ class LineLayoutItem {
// TODO(dgrogan/eae): Can we change this to GlobalToLocal and vice versa
// instead of having 4 methods? See localToAbsoluteQuad below.
- PositionWithAffinity PositionForPoint(const PhysicalOffset& point) {
- return layout_object_->PositionForPoint(point);
- }
+ PositionWithAffinity PositionForPoint(const PhysicalOffset& point);
PositionWithAffinity CreatePositionWithAffinity(int offset,
- TextAffinity affinity) {
- return layout_object_->CreatePositionWithAffinity(offset, affinity);
- }
+ TextAffinity affinity) const;
- PositionWithAffinity PositionAfterThis() const {
- return layout_object_->PositionAfterThis();
- }
+ PositionWithAffinity PositionAfterThis() const;
- PositionWithAffinity PositionBeforeThis() const {
- return layout_object_->PositionBeforeThis();
- }
+ PositionWithAffinity PositionBeforeThis() const;
LineLayoutItem PreviousInPreOrder(const LayoutObject* stay_within) const {
return LineLayoutItem(layout_object_->PreviousInPreOrder(stay_within));
@@ -310,9 +273,7 @@ class LineLayoutItem {
layout_object_->SetShouldDoFullPaintInvalidation();
}
- void SlowSetPaintingLayerNeedsRepaint() {
- ObjectPaintInvalidator(*layout_object_).SlowSetPaintingLayerNeedsRepaint();
- }
+ void SlowSetPaintingLayerNeedsRepaint();
void SetIsTruncated(bool set_truncation) {
layout_object_->SetIsTruncated(set_truncation);
diff --git a/chromium/third_party/blink/renderer/core/layout/build.gni b/chromium/third_party/blink/renderer/core/layout/build.gni
index dff46b0bfe3..e3a803eb5eb 100644
--- a/chromium/third_party/blink/renderer/core/layout/build.gni
+++ b/chromium/third_party/blink/renderer/core/layout/build.gni
@@ -11,6 +11,7 @@ blink_core_sources_layout = [
"api/line_layout_br.h",
"api/line_layout_inline.h",
"api/line_layout_item.h",
+ "api/line_layout_item.cc",
"api/line_layout_list_marker.h",
"api/line_layout_ruby_base.h",
"api/line_layout_ruby_run.h",
@@ -259,8 +260,6 @@ blink_core_sources_layout = [
"line/word_measurement.h",
"list_marker.cc",
"list_marker.h",
- "list_marker_text.cc",
- "list_marker_text.h",
"map_coordinates_flags.h",
"min_max_sizes.cc",
"min_max_sizes.h",
@@ -323,8 +322,6 @@ blink_core_sources_layout = [
"ng/grid/layout_ng_grid.cc",
"ng/grid/layout_ng_grid.h",
"ng/grid/layout_ng_grid_interface.h",
- "ng/grid/ng_grid_child_iterator.cc",
- "ng/grid/ng_grid_child_iterator.h",
"ng/grid/ng_grid_data.h",
"ng/grid/ng_grid_layout_algorithm.cc",
"ng/grid/ng_grid_layout_algorithm.h",
@@ -333,9 +330,14 @@ blink_core_sources_layout = [
"ng/grid/ng_grid_track_collection.cc",
"ng/grid/ng_grid_track_collection.h",
"ng/inline/empty_offset_mapping_builder.h",
+ "ng/inline/inline_containing_block_utils.cc",
+ "ng/inline/inline_containing_block_utils.h",
"ng/inline/layout_ng_br.h",
+ "ng/inline/layout_ng_counter.h",
"ng/inline/layout_ng_text.h",
"ng/inline/layout_ng_text_fragment.h",
+ "ng/inline/layout_ng_text_combine.cc",
+ "ng/inline/layout_ng_text_combine.h",
"ng/inline/layout_ng_word_break.h",
"ng/inline/ng_abstract_inline_text_box.cc",
"ng/inline/ng_abstract_inline_text_box.h",
@@ -399,6 +401,7 @@ blink_core_sources_layout = [
"ng/inline/ng_text_type.h",
"ng/layout_box_utils.cc",
"ng/layout_box_utils.h",
+ "ng/layout_ng_block.h",
"ng/layout_ng_block_flow.cc",
"ng/layout_ng_block_flow.h",
"ng/layout_ng_block_flow_mixin.cc",
@@ -485,6 +488,8 @@ blink_core_sources_layout = [
"ng/ng_constraint_space_builder.h",
"ng/ng_container_fragment_builder.cc",
"ng/ng_container_fragment_builder.h",
+ "ng/ng_disable_side_effects_scope.cc",
+ "ng/ng_disable_side_effects_scope.h",
"ng/ng_early_break.h",
"ng/ng_fieldset_layout_algorithm.cc",
"ng/ng_fieldset_layout_algorithm.h",
@@ -492,8 +497,6 @@ blink_core_sources_layout = [
"ng/ng_floats_utils.h",
"ng/ng_fragment.h",
"ng/ng_fragment_builder.h",
- "ng/ng_fragment_child_iterator.cc",
- "ng/ng_fragment_child_iterator.h",
"ng/ng_fragmentation_utils.cc",
"ng/ng_fragmentation_utils.h",
"ng/ng_ink_overflow.cc",
@@ -544,6 +547,9 @@ blink_core_sources_layout = [
"ng/svg/ng_svg_text_layout_algorithm.h",
"ng/svg/ng_svg_text_layout_attributes_builder.cc",
"ng/svg/ng_svg_text_layout_attributes_builder.h",
+ "ng/svg/ng_svg_text_query.cc",
+ "ng/svg/ng_svg_text_query.h",
+ "ng/svg/resolved_text_layout_attributes_iterator.h",
"ng/svg/svg_inline_node_data.h",
"ng/table/interface_casting.h",
"ng/table/layout_ng_table.cc",
diff --git a/chromium/third_party/blink/renderer/core/layout/column_balancer.cc b/chromium/third_party/blink/renderer/core/layout/column_balancer.cc
index 7de53893ace..43b88908488 100644
--- a/chromium/third_party/blink/renderer/core/layout/column_balancer.cc
+++ b/chromium/third_party/blink/renderer/core/layout/column_balancer.cc
@@ -322,9 +322,9 @@ unsigned InitialColumnHeightFinder::ContentRunIndexWithTallestColumns() const {
unsigned index_with_largest_height = 0;
LayoutUnit largest_height;
LayoutUnit previous_offset = LogicalTopInFlowThread();
- size_t run_count = content_runs_.size();
+ wtf_size_t run_count = content_runs_.size();
DCHECK(run_count);
- for (size_t i = FirstContentRunIndexInLastRow(); i < run_count; i++) {
+ for (unsigned i = FirstContentRunIndexInLastRow(); i < run_count; i++) {
const ContentRun& run = content_runs_[i];
LayoutUnit height = run.ColumnLogicalHeight(previous_offset);
if (largest_height < height) {
diff --git a/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc
index 1a16d622143..002d176fd66 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/layout/custom_scrollbar.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_request.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h"
@@ -171,8 +172,9 @@ void CustomScrollbar::UpdateScrollbarParts() {
bool is_horizontal = Orientation() == kHorizontalScrollbar;
int old_thickness = is_horizontal ? Height() : Width();
int new_thickness = 0;
- if (auto* part = parts_.at(kScrollbarBGPart))
- new_thickness = part->ComputeThickness();
+ auto it = parts_.find(kScrollbarBGPart);
+ if (it != parts_.end())
+ new_thickness = it->value->ComputeThickness();
if (new_thickness != old_thickness) {
SetFrameRect(
@@ -259,7 +261,9 @@ void CustomScrollbar::UpdateScrollbarPart(ScrollbarPart part_type) {
}
}
- LayoutCustomScrollbarPart* part_layout_object = parts_.at(part_type);
+ auto it = parts_.find(part_type);
+ LayoutCustomScrollbarPart* part_layout_object =
+ it != parts_.end() ? it->value : nullptr;
if (!part_layout_object && need_layout_object && scrollable_area_) {
part_layout_object = LayoutCustomScrollbarPart::CreateAnonymous(
&StyleSource()->GetDocument(), scrollable_area_, this, part_type);
@@ -277,12 +281,12 @@ void CustomScrollbar::UpdateScrollbarPart(ScrollbarPart part_type) {
}
IntRect CustomScrollbar::ButtonRect(ScrollbarPart part_type) const {
- LayoutCustomScrollbarPart* part_layout_object = parts_.at(part_type);
- if (!part_layout_object)
+ auto it = parts_.find(part_type);
+ if (it == parts_.end())
return IntRect();
bool is_horizontal = Orientation() == kHorizontalScrollbar;
- int button_length = part_layout_object->ComputeLength();
+ int button_length = it->value->ComputeLength();
IntRect button_rect(Location(), is_horizontal
? IntSize(button_length, Height())
: IntSize(Width(), button_length));
diff --git a/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h
index 3bc6d300752..bcdf1361511 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h
@@ -65,10 +65,12 @@ class CORE_EXPORT CustomScrollbar final : public Scrollbar {
void PositionScrollbarParts();
LayoutCustomScrollbarPart* GetPart(ScrollbarPart part_type) {
- return parts_.at(part_type);
+ auto it = parts_.find(part_type);
+ return it != parts_.end() ? it->value : nullptr;
}
const LayoutCustomScrollbarPart* GetPart(ScrollbarPart part_type) const {
- return parts_.at(part_type);
+ auto it = parts_.find(part_type);
+ return it != parts_.end() ? it->value : nullptr;
}
void InvalidateDisplayItemClientsOfScrollbarParts();
diff --git a/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
index 95a6e507c06..12bd565d298 100644
--- a/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
@@ -295,6 +295,16 @@ LayoutUnit FlexItem::AlignmentOffset(LayoutUnit available_free_space,
case ItemPosition::kNormal:
NOTREACHED();
break;
+ case ItemPosition::kSelfStart:
+ case ItemPosition::kSelfEnd:
+ case ItemPosition::kStart:
+ case ItemPosition::kEnd:
+ case ItemPosition::kLeft:
+ case ItemPosition::kRight:
+ NOTREACHED() << static_cast<int>(position)
+ << " AlignmentForChild should have transformed this "
+ "position value to something we handle below.";
+ break;
case ItemPosition::kStretch:
// Actual stretching must be handled by the caller. Since wrap-reverse
// flips cross start and cross end, stretch children should be aligned
@@ -319,20 +329,14 @@ LayoutUnit FlexItem::AlignmentOffset(LayoutUnit available_free_space,
// https://bugs.webkit.org/show_bug.cgi?id=98076
return max_ascent - ascent;
case ItemPosition::kLastBaseline:
- case ItemPosition::kSelfStart:
- case ItemPosition::kSelfEnd:
- case ItemPosition::kStart:
- case ItemPosition::kEnd:
- case ItemPosition::kLeft:
- case ItemPosition::kRight:
- // TODO(jfernandez): Implement these (https://crbug.com/722287).
+ // TODO(crbug.com/885175): Implement last baseline.
break;
}
return LayoutUnit();
}
void FlexLine::FreezeViolations(ViolationsVector& violations) {
const ComputedStyle& flex_box_style = algorithm_->StyleRef();
- for (size_t i = 0; i < violations.size(); ++i) {
+ for (wtf_size_t i = 0; i < violations.size(); ++i) {
DCHECK(!violations[i]->frozen_) << i;
const ComputedStyle& child_style = violations[i]->style_;
LayoutUnit child_size = violations[i]->flexed_content_size_;
@@ -362,7 +366,7 @@ void FlexLine::FreezeInflexibleItems() {
ViolationsVector new_inflexible_items;
const ComputedStyle& flex_box_style = algorithm_->StyleRef();
- for (size_t i = 0; i < line_items_.size(); ++i) {
+ for (wtf_size_t i = 0; i < line_items_.size(); ++i) {
FlexItem& flex_item = line_items_[i];
DCHECK(!flex_item.frozen_) << i;
float flex_factor =
@@ -402,7 +406,7 @@ bool FlexLine::ResolveFlexibleLengths() {
}
const ComputedStyle& flex_box_style = algorithm_->StyleRef();
- for (size_t i = 0; i < line_items_.size(); ++i) {
+ for (wtf_size_t i = 0; i < line_items_.size(); ++i) {
FlexItem& flex_item = line_items_[i];
// This check also covers out-of-flow children.
@@ -456,7 +460,7 @@ LayoutUnit FlexLine::ApplyMainAxisAutoMarginAdjustment() {
int number_of_auto_margins = 0;
bool is_horizontal = algorithm_->IsHorizontalFlow();
- for (size_t i = 0; i < line_items_.size(); ++i) {
+ for (wtf_size_t i = 0; i < line_items_.size(); ++i) {
const ComputedStyle& style = line_items_[i].style_;
if (is_horizontal) {
if (style.MarginLeft().IsAuto())
@@ -489,7 +493,7 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
// Recalculate the remaining free space. The adjustment for flex factors
// between 0..1 means we can't just use remainingFreeSpace here.
LayoutUnit total_item_size;
- for (size_t i = 0; i < line_items_.size(); ++i)
+ for (wtf_size_t i = 0; i < line_items_.size(); ++i)
total_item_size += line_items_[i].FlexedMarginBoxSize();
remaining_free_space_ =
container_main_inner_size_ - total_item_size -
@@ -500,10 +504,12 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
const LayoutUnit auto_margin_offset = ApplyMainAxisAutoMarginAdjustment();
const LayoutUnit available_free_space = remaining_free_space_;
+ const bool is_reversed = style.ResolvedIsRowReverseFlexDirection() ||
+ style.ResolvedIsColumnReverseFlexDirection();
const LayoutUnit initial_position =
FlexLayoutAlgorithm::InitialContentPositionOffset(
- style, available_free_space, justify_content, line_items_.size());
- sum_justify_adjustments_ += initial_position;
+ style, available_free_space, justify_content, line_items_.size(),
+ is_reversed);
LayoutUnit main_axis_offset = initial_position + main_axis_start_offset;
bool should_flip_main_axis;
@@ -528,7 +534,7 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
LayoutUnit max_descent; // Used when align-items: baseline.
LayoutUnit max_child_cross_axis_extent;
- for (size_t i = 0; i < line_items_.size(); ++i) {
+ for (wtf_size_t i = 0; i < line_items_.size(); ++i) {
FlexItem& flex_item = line_items_[i];
flex_item.UpdateAutoMarginsInMainAxis(auto_margin_offset);
@@ -571,9 +577,6 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
FlexLayoutAlgorithm::ContentDistributionSpaceBetweenChildren(
available_free_space, justify_content, line_items_.size());
main_axis_offset += space_between + algorithm_->gap_between_items_;
- // The gap is included in the intrinsic content block size, so don't add
- // it to sum_justify_adjustments.
- sum_justify_adjustments_ += space_between;
}
}
@@ -800,9 +803,10 @@ void FlexLayoutAlgorithm::AlignFlexLines(LayoutUnit cross_axis_content_extent) {
for (const FlexLine& line : flex_lines_)
available_cross_axis_space -= line.cross_axis_extent_;
- LayoutUnit line_offset =
- InitialContentPositionOffset(StyleRef(), available_cross_axis_space,
- align_content, flex_lines_.size());
+ const bool is_reversed = StyleRef().FlexWrap() == EFlexWrap::kWrapReverse;
+ LayoutUnit line_offset = InitialContentPositionOffset(
+ StyleRef(), available_cross_axis_space, align_content, flex_lines_.size(),
+ is_reversed);
for (FlexLine& line_context : flex_lines_) {
line_context.cross_axis_offset_ += line_offset;
@@ -952,6 +956,34 @@ StyleContentAlignmentData FlexLayoutAlgorithm::ResolvedJustifyContent(
position =
style.ResolvedJustifyContentPosition(ContentAlignmentNormalBehavior());
}
+ if (position == ContentPosition::kLeft ||
+ position == ContentPosition::kRight) {
+ if (IsColumnFlow(style)) {
+ if (style.IsHorizontalWritingMode()) {
+ // Main axis is perpendicular to both the physical left<->right and
+ // inline start<->end axes, so kLeft and kRight behave as kStart.
+ position = ContentPosition::kStart;
+ } else if ((position == ContentPosition::kLeft &&
+ style.IsFlippedBlocksWritingMode()) ||
+ (position == ContentPosition::kRight &&
+ style.IsFlippedLinesWritingMode())) {
+ position = ContentPosition::kEnd;
+ } else {
+ position = ContentPosition::kStart;
+ }
+ } else if ((position == ContentPosition::kLeft &&
+ !style.IsLeftToRightDirection()) ||
+ (position == ContentPosition::kRight &&
+ style.IsLeftToRightDirection())) {
+ DCHECK(!FlexLayoutAlgorithm::IsColumnFlow(style));
+ position = ContentPosition::kEnd;
+ } else {
+ position = ContentPosition::kStart;
+ }
+ }
+ DCHECK_NE(position, ContentPosition::kLeft);
+ DCHECK_NE(position, ContentPosition::kRight);
+
ContentDistributionType distribution =
is_webkit_box ? BoxPackToContentDistribution(style.BoxPack())
: style.ResolvedJustifyContentDistribution(
@@ -989,6 +1021,31 @@ ItemPosition FlexLayoutAlgorithm::AlignmentForChild(
.GetPosition();
DCHECK_NE(align, ItemPosition::kAuto);
DCHECK_NE(align, ItemPosition::kNormal);
+ DCHECK_NE(align, ItemPosition::kLeft) << "left, right are only for justify";
+ DCHECK_NE(align, ItemPosition::kRight) << "left, right are only for justify";
+
+ if (align == ItemPosition::kStart)
+ return ItemPosition::kFlexStart;
+ if (align == ItemPosition::kEnd)
+ return ItemPosition::kFlexEnd;
+
+ if (align == ItemPosition::kSelfStart || align == ItemPosition::kSelfEnd) {
+ LogicalToPhysical<ItemPosition> physical(
+ child_style.GetWritingDirection(), ItemPosition::kFlexStart,
+ ItemPosition::kFlexEnd, ItemPosition::kFlexStart,
+ ItemPosition::kFlexEnd);
+
+ PhysicalToLogical<ItemPosition> logical(flexbox_style.GetWritingDirection(),
+ physical.Top(), physical.Right(),
+ physical.Bottom(), physical.Left());
+
+ if (flexbox_style.ResolvedIsColumnFlexDirection()) {
+ return align == ItemPosition::kSelfStart ? logical.InlineStart()
+ : logical.InlineEnd();
+ }
+ return align == ItemPosition::kSelfStart ? logical.BlockStart()
+ : logical.BlockEnd();
+ }
if (align == ItemPosition::kBaseline &&
IsHorizontalFlow(flexbox_style) != child_style.IsHorizontalWritingMode())
@@ -1009,13 +1066,22 @@ LayoutUnit FlexLayoutAlgorithm::InitialContentPositionOffset(
const ComputedStyle& style,
LayoutUnit available_free_space,
const StyleContentAlignmentData& data,
- unsigned number_of_items) {
+ unsigned number_of_items,
+ bool is_reversed) {
if (available_free_space <= 0 && style.IsDeprecatedWebkitBox()) {
// -webkit-box only considers |available_free_space| if > 0.
return LayoutUnit();
}
- if (data.GetPosition() == ContentPosition::kFlexEnd)
+ ContentPosition position = data.GetPosition();
+ DCHECK_NE(position, ContentPosition::kLeft)
+ << "ResolvedJustifyContent was supposed to translate this to kStart/End";
+ DCHECK_NE(position, ContentPosition::kRight)
+ << "ResolvedJustifyContent was supposed to translate this to kStart/End";
+ if (position == ContentPosition::kFlexEnd ||
+ (position == ContentPosition::kEnd && !is_reversed) ||
+ (position == ContentPosition::kStart && is_reversed)) {
return available_free_space;
+ }
if (data.GetPosition() == ContentPosition::kCenter)
return available_free_space / 2;
if (data.Distribution() == ContentDistributionType::kSpaceAround) {
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 2e707a84202..9a78adefd58 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
@@ -47,6 +47,7 @@ namespace blink {
class FlexItem;
class FlexLine;
class FlexLayoutAlgorithm;
+class NGFlexLayoutAlgorithm;
class LayoutBox;
struct MinMaxSizes;
@@ -338,7 +339,6 @@ class FlexLine {
LayoutUnit cross_axis_offset_;
LayoutUnit cross_axis_extent_;
LayoutUnit max_ascent_;
- LayoutUnit sum_justify_adjustments_;
};
// This class implements the CSS Flexbox layout algorithm:
@@ -433,7 +433,8 @@ class FlexLayoutAlgorithm {
const ComputedStyle& style,
LayoutUnit available_free_space,
const StyleContentAlignmentData&,
- unsigned number_of_items);
+ unsigned number_of_items,
+ bool is_reversed = false);
static LayoutUnit ContentDistributionSpaceBetweenChildren(
LayoutUnit available_free_space,
const StyleContentAlignmentData&,
@@ -451,13 +452,14 @@ class FlexLayoutAlgorithm {
const LayoutUnit gap_between_lines_;
private:
+ friend class NGFlexLayoutAlgorithm;
EOverflow MainAxisOverflowForChild(const LayoutBox& child) const;
const ComputedStyle* style_;
const LayoutUnit line_break_length_;
FlexItemVector all_items_;
Vector<FlexLine> flex_lines_;
- size_t next_item_index_;
+ wtf_size_t next_item_index_;
};
inline const FlexLine* FlexItem::Line() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/logical_offset.h b/chromium/third_party/blink/renderer/core/layout/geometry/logical_offset.h
index 5c9d96f27fe..5142d95fa9d 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/logical_offset.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/logical_offset.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_LOGICAL_OFFSET_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_LOGICAL_OFFSET_H_
+#include <tuple>
+
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/text/writing_direction_mode.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect.h b/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect.h
index 514ebe0ca84..0806a793a93 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect.h
@@ -28,7 +28,7 @@ struct CORE_EXPORT LogicalRect {
LayoutUnit block_size)
: offset(inline_offset, block_offset), size(inline_size, block_size) {}
- // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
+ // For testing only. It's defined in core/testing/core_unit_test_helper.h.
inline LogicalRect(int inline_offset,
int block_offset,
int inline_size,
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect_test.cc b/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect_test.cc
index 0d1ae1beead..e82fdd6975a 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/logical_rect_test.cc
@@ -25,11 +25,11 @@ struct LogicalRectUniteTestData {
{"saturated width",
{-1000, 0, 200, 200},
{33554402, 500, 30, 100},
- {0, 0, 99999999.0f, 600}},
+ {0, 0, 99999999, 600}},
{"saturated height",
{0, -1000, 200, 200},
{0, 33554402, 100, 30},
- {0, 0, 200, 99999999.0f}},
+ {0, 0, 200, 99999999}},
};
std::ostream& operator<<(std::ostream& os,
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/logical_size.h b/chromium/third_party/blink/renderer/core/layout/geometry/logical_size.h
index b5262d54e41..826d9717b0a 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/logical_size.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/logical_size.h
@@ -24,7 +24,7 @@ struct CORE_EXPORT LogicalSize {
constexpr LogicalSize(LayoutUnit inline_size, LayoutUnit block_size)
: inline_size(inline_size), block_size(block_size) {}
- // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
+ // For testing only. It's defined in core/testing/core_unit_test_helper.h.
inline LogicalSize(int inline_size, int block_size);
// Use ToPhysicalSize to convert to a physical size.
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/physical_offset.h b/chromium/third_party/blink/renderer/core/layout/geometry/physical_offset.h
index fae47b1a09e..300a4c6fed6 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/physical_offset.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/physical_offset.h
@@ -27,7 +27,7 @@ struct CORE_EXPORT PhysicalOffset {
constexpr PhysicalOffset(LayoutUnit left, LayoutUnit top)
: left(left), top(top) {}
- // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
+ // For testing only. It's defined in core/testing/core_unit_test_helper.h.
inline PhysicalOffset(int left, int top);
LayoutUnit left;
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.cc b/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.cc
index 3a749050d74..00a6001b4a8 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.cc
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.cc
@@ -27,6 +27,13 @@ PhysicalSize PhysicalRect::DistanceAsSize(PhysicalOffset target) const {
return distance;
}
+LayoutUnit PhysicalRect::SquaredDistanceTo(const PhysicalOffset& point) const {
+ LayoutUnit diff_x =
+ point.left - clampTo<LayoutUnit>(point.left, X(), Right());
+ LayoutUnit diff_y = point.top - clampTo<LayoutUnit>(point.top, Y(), Bottom());
+ return diff_x * diff_x + diff_y * diff_y;
+}
+
bool PhysicalRect::Contains(const PhysicalRect& other) const {
return offset.left <= other.offset.left && offset.top <= other.offset.top &&
Right() >= other.Right() && Bottom() >= other.Bottom();
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.h b/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.h
index e37c5dbf9ce..0ff388cdc91 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect.h
@@ -42,7 +42,7 @@ struct CORE_EXPORT PhysicalRect {
LayoutUnit height)
: offset(left, top), size(width, height) {}
- // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
+ // For testing only. It's defined in core/testing/core_unit_test_helper.h.
inline PhysicalRect(int left, int top, int width, int height);
PhysicalOffset offset;
@@ -82,6 +82,10 @@ struct CORE_EXPORT PhysicalRect {
// Each distance is zero if |this| contains |target| in that direction.
PhysicalSize DistanceAsSize(PhysicalOffset target) const;
+ // Returns square of the distance from |point| to the closest edge of |this|.
+ // This function returns 0 if |this| contains |point|.
+ LayoutUnit SquaredDistanceTo(const PhysicalOffset& point) const;
+
bool Contains(const PhysicalRect&) const;
bool Contains(LayoutUnit px, LayoutUnit py) const {
return px >= offset.left && px < Right() && py >= offset.top &&
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect_test.cc b/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect_test.cc
index c7248194a29..b9bd748ea12 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/physical_rect_test.cc
@@ -25,11 +25,11 @@ struct PhysicalOffsetRectUniteTestData {
{"saturated width",
{-1000, 0, 200, 200},
{33554402, 500, 30, 100},
- {0, 0, 99999999.0f, 600}},
+ {0, 0, 99999999, 600}},
{"saturated height",
{0, -1000, 200, 200},
{0, 33554402, 100, 30},
- {0, 0, 200, 99999999.0f}},
+ {0, 0, 200, 99999999}},
};
std::ostream& operator<<(std::ostream& os,
@@ -66,6 +66,44 @@ TEST_P(PhysicalRectUniteTest, Data) {
EXPECT_EQ(expected, actual);
}
+TEST(PhysicalRectTest, SquaredDistanceTo) {
+ PhysicalRect rect(0, 0, 200, 200);
+ EXPECT_EQ(200, rect.SquaredDistanceTo(PhysicalOffset(-10, -10)))
+ << "over the top-left corner";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(0, 0)))
+ << "on the top-left corner";
+ EXPECT_EQ(100, rect.SquaredDistanceTo(PhysicalOffset(10, -10)))
+ << "over the top edge";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(10, 0)))
+ << "on the top edge";
+ EXPECT_EQ(200, rect.SquaredDistanceTo(PhysicalOffset(210, -10)))
+ << "over the top-right corner";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(200, 0)))
+ << "on the top-right corner";
+ EXPECT_EQ(100, rect.SquaredDistanceTo(PhysicalOffset(210, 10)))
+ << "over the right edge";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(200, 10)))
+ << "on the right edge";
+ EXPECT_EQ(200, rect.SquaredDistanceTo(PhysicalOffset(210, 210)))
+ << "over the bottom-right corner";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(200, 200)))
+ << "on the bottom-right corner";
+ EXPECT_EQ(10000, rect.SquaredDistanceTo(PhysicalOffset(100, 300)))
+ << "over the bottom edge";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(100, 200)))
+ << "on the bottom edge";
+ EXPECT_EQ(401, rect.SquaredDistanceTo(PhysicalOffset(-20, 201)))
+ << "over the bottom-left corner";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(0, 200)))
+ << "on the bottom-left corner";
+ EXPECT_EQ(9, rect.SquaredDistanceTo(PhysicalOffset(-3, 100)))
+ << "over the left edge";
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(0, 3)))
+ << "on the left edge";
+
+ EXPECT_EQ(0, rect.SquaredDistanceTo(PhysicalOffset(10, 190))) << "contained";
+}
+
TEST(PhysicalRectTest, InclusiveIntersect) {
PhysicalRect rect(11, 12, 0, 0);
EXPECT_TRUE(rect.InclusiveIntersect(PhysicalRect(11, 12, 13, 14)));
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/physical_size.h b/chromium/third_party/blink/renderer/core/layout/geometry/physical_size.h
index 33f7709c122..7d8f3aa6f0d 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/physical_size.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/physical_size.h
@@ -27,7 +27,7 @@ struct CORE_EXPORT PhysicalSize {
constexpr PhysicalSize(LayoutUnit width, LayoutUnit height)
: width(width), height(height) {}
- // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
+ // For testing only. It's defined in core/testing/core_unit_test_helper.h.
inline PhysicalSize(int width, int height);
LayoutUnit width;
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.cc b/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.cc
index f367b0d6027..0143f908aaa 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.cc
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.cc
@@ -35,7 +35,6 @@ TransformState& TransformState::operator=(const TransformState& other) {
last_planar_point_ = other.last_planar_point_;
if (map_quad_)
last_planar_quad_ = other.last_planar_quad_;
- accumulating_transform_ = other.accumulating_transform_;
force_accumulating_transform_ = other.force_accumulating_transform_;
direction_ = other.direction_;
@@ -77,7 +76,7 @@ void TransformState::Move(const PhysicalOffset& offset,
accumulated_offset_ += offset;
} else {
ApplyAccumulatedOffset();
- if (accumulating_transform_ && accumulated_transform_) {
+ if (accumulated_transform_) {
// If we're accumulating into an existing transform, apply the
// translation.
TranslateTransform(offset);
@@ -86,7 +85,6 @@ void TransformState::Move(const PhysicalOffset& offset,
TranslateMappedCoordinates(offset);
}
}
- accumulating_transform_ = accumulate == kAccumulateTransform;
}
void TransformState::ApplyAccumulatedOffset() {
@@ -146,8 +144,6 @@ void TransformState::ApplyTransform(
FlattenWithTransform(*final_transform);
}
}
- accumulating_transform_ =
- accumulate == kAccumulateTransform || force_accumulating_transform_;
}
void TransformState::Flatten() {
@@ -156,7 +152,6 @@ void TransformState::Flatten() {
ApplyAccumulatedOffset();
if (!accumulated_transform_) {
- accumulating_transform_ = false;
return;
}
@@ -192,7 +187,6 @@ FloatQuad TransformState::MappedQuad() const {
const TransformationMatrix& TransformState::AccumulatedTransform() const {
DCHECK(force_accumulating_transform_);
- DCHECK(accumulating_transform_);
return *accumulated_transform_;
}
@@ -216,7 +210,6 @@ void TransformState::FlattenWithTransform(const TransformationMatrix& t) {
// preserve-3d and flat elements.
if (accumulated_transform_)
accumulated_transform_->MakeIdentity();
- accumulating_transform_ = false;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.h b/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.h
index 9866efdaa74..03824c76f9e 100644
--- a/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.h
+++ b/chromium/third_party/blink/renderer/core/layout/geometry/transform_state.h
@@ -44,6 +44,8 @@ namespace blink {
// This is mainly used by other layout geometry mapping functions/classes (e.g.
// LayoutObject::LocalToAncestorPoint() and LayoutGeometryMap). In most cases
// other code should not use this class directly.
+// TODO(crbug.com/1222769): This class should go away and its users should use
+// GeometryMapper instead.
class CORE_EXPORT TransformState {
STACK_ALLOCATED();
@@ -59,7 +61,6 @@ class CORE_EXPORT TransformState {
const FloatQuad& quad)
: last_planar_point_(p),
last_planar_quad_(quad),
- accumulating_transform_(false),
force_accumulating_transform_(false),
map_point_(true),
map_quad_(true),
@@ -67,7 +68,6 @@ class CORE_EXPORT TransformState {
TransformState(TransformDirection mapping_direction, const FloatPoint& p)
: last_planar_point_(p),
- accumulating_transform_(false),
force_accumulating_transform_(false),
map_point_(true),
map_quad_(false),
@@ -75,7 +75,6 @@ class CORE_EXPORT TransformState {
TransformState(TransformDirection mapping_direction, const FloatQuad& quad)
: last_planar_quad_(quad),
- accumulating_transform_(false),
force_accumulating_transform_(false),
map_point_(false),
map_quad_(true),
@@ -84,7 +83,6 @@ class CORE_EXPORT TransformState {
// Accumulate a transform but don't map any points directly.
TransformState(TransformDirection mapping_direction)
: accumulated_transform_(std::make_unique<TransformationMatrix>()),
- accumulating_transform_(true),
force_accumulating_transform_(true),
map_point_(false),
map_quad_(false),
@@ -97,7 +95,7 @@ class CORE_EXPORT TransformState {
// Note: this overrides the quad and ignores any accumulatedOffset.
// If it's desired to include the offset, call flatten() first.
void SetQuad(const FloatQuad& quad) {
- DCHECK(!accumulating_transform_);
+ DCHECK(!accumulated_transform_ || accumulated_transform_->IsIdentity());
// FIXME: this assumes that the quad being added is in the coordinate system
// of the current state. This breaks if we're simultaneously mapping a
// point. https://bugs.webkit.org/show_bug.cgi?id=106680
@@ -137,7 +135,6 @@ class CORE_EXPORT TransformState {
// We only allocate the transform if we need to
std::unique_ptr<TransformationMatrix> accumulated_transform_;
PhysicalOffset accumulated_offset_;
- bool accumulating_transform_;
bool force_accumulating_transform_;
bool map_point_, map_quad_;
TransformDirection direction_;
diff --git a/chromium/third_party/blink/renderer/core/layout/grid.cc b/chromium/third_party/blink/renderer/core/layout/grid.cc
index db83431a5e4..6041703ee35 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid.cc
+++ b/chromium/third_party/blink/renderer/core/layout/grid.cc
@@ -28,12 +28,12 @@ std::unique_ptr<Grid> Grid::Create(const LayoutGrid* layout_grid) {
Grid::Grid(const LayoutGrid* grid) : order_iterator_(grid) {}
-void Grid::SetExplicitGridStart(size_t row_start, size_t column_start) {
+void Grid::SetExplicitGridStart(wtf_size_t row_start, wtf_size_t column_start) {
explicit_row_start_ = row_start;
explicit_column_start_ = column_start;
}
-size_t Grid::ExplicitGridStart(GridTrackSizingDirection direction) const {
+wtf_size_t Grid::ExplicitGridStart(GridTrackSizingDirection direction) const {
return direction == kForRows ? explicit_row_start_ : explicit_column_start_;
}
@@ -46,11 +46,11 @@ void Grid::SetGridItemArea(const LayoutBox& item, GridArea area) {
grid_item_area_.Set(&item, area);
}
-size_t Grid::GridItemPaintOrder(const LayoutBox& item) const {
+wtf_size_t Grid::GridItemPaintOrder(const LayoutBox& item) const {
return grid_items_indexes_map_.at(&item);
}
-void Grid::SetGridItemPaintOrder(const LayoutBox& item, size_t order) {
+void Grid::SetGridItemPaintOrder(const LayoutBox& item, wtf_size_t order) {
grid_items_indexes_map_.Set(&item, order);
}
@@ -60,17 +60,17 @@ bool Grid::HasAnyGridItemPaintOrder() const {
}
#endif
-void Grid::SetAutoRepeatTracks(size_t auto_repeat_rows,
- size_t auto_repeat_columns) {
- DCHECK_GE(static_cast<unsigned>(kGridMaxTracks),
+void Grid::SetAutoRepeatTracks(wtf_size_t auto_repeat_rows,
+ wtf_size_t auto_repeat_columns) {
+ DCHECK_GE(static_cast<wtf_size_t>(kGridMaxTracks),
NumTracks(kForRows) + auto_repeat_rows);
- DCHECK_GE(static_cast<unsigned>(kGridMaxTracks),
+ DCHECK_GE(static_cast<wtf_size_t>(kGridMaxTracks),
NumTracks(kForColumns) + auto_repeat_columns);
auto_repeat_rows_ = auto_repeat_rows;
auto_repeat_columns_ = auto_repeat_columns;
}
-size_t Grid::AutoRepeatTracks(GridTrackSizingDirection direction) const {
+wtf_size_t Grid::AutoRepeatTracks(GridTrackSizingDirection direction) const {
return direction == kForRows ? auto_repeat_rows_ : auto_repeat_columns_;
}
@@ -90,7 +90,7 @@ bool Grid::HasAutoRepeatEmptyTracks(GridTrackSizingDirection direction) const {
}
bool Grid::IsEmptyAutoRepeatTrack(GridTrackSizingDirection direction,
- size_t line) const {
+ wtf_size_t line) const {
DCHECK(HasAutoRepeatEmptyTracks(direction));
return AutoRepeatEmptyTracks(direction)->Contains(line);
}
@@ -128,8 +128,8 @@ void Grid::SetNeedsItemsPlacement(bool needs_items_placement) {
}
Grid::GridIterator::GridIterator(GridTrackSizingDirection direction,
- size_t fixed_track_index,
- size_t varying_track_index)
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index)
: direction_(direction),
row_index_((direction == kForColumns) ? varying_track_index
: fixed_track_index),
@@ -137,11 +137,11 @@ Grid::GridIterator::GridIterator(GridTrackSizingDirection direction,
: varying_track_index),
child_index_(0) {}
-ListGrid::GridCell* ListGrid::GridTrack::Find(size_t index) const {
+ListGrid::GridCell* ListGrid::GridTrack::Find(wtf_size_t index) const {
auto orthogonal_axis = OrthogonalDirection(direction_);
for (auto* cell = cells_.Head(); cell;
cell = cell->NextInDirection(direction_)) {
- size_t cell_index = cell->Index(orthogonal_axis);
+ wtf_size_t cell_index = cell->Index(orthogonal_axis);
if (cell_index == index)
return cell;
if (cell_index > index)
@@ -150,7 +150,7 @@ ListGrid::GridCell* ListGrid::GridTrack::Find(size_t index) const {
return nullptr;
}
-static int ComparePositions(size_t first, size_t second) {
+static int ComparePositions(wtf_size_t first, wtf_size_t second) {
return first < second ? -1 : (first != second);
}
@@ -183,8 +183,8 @@ DoublyLinkedList<ListGrid::GridCell>::AddResult ListGrid::GridTrack::Insert(
second->Index(ortho_direction));
};
- size_t col_index = direction_ == kForColumns ? Index() : span.StartLine();
- size_t row_index = direction_ == kForColumns ? span.StartLine() : Index();
+ wtf_size_t col_index = direction_ == kForColumns ? Index() : span.StartLine();
+ wtf_size_t row_index = direction_ == kForColumns ? span.StartLine() : Index();
auto result = cells_.Insert(
base::WrapUnique(new GridCell(row_index, col_index)), compare_cells);
@@ -199,8 +199,10 @@ DoublyLinkedList<ListGrid::GridCell>::AddResult ListGrid::GridTrack::Insert(
auto ortho_direction = OrthogonalDirection(direction_);
if (!cell->Next() ||
(cell->Next()->Index(ortho_direction) != (index + 1))) {
- size_t next_col_index = direction_ == kForColumns ? Index() : index + 1;
- size_t next_row_index = direction_ == kForColumns ? index + 1 : Index();
+ wtf_size_t next_col_index =
+ direction_ == kForColumns ? Index() : index + 1;
+ wtf_size_t next_row_index =
+ direction_ == kForColumns ? index + 1 : Index();
auto next_cell =
base::WrapUnique(new GridCell(next_row_index, next_col_index));
if (InsertAfter(next_cell.get(), cell).is_new_entry)
@@ -244,8 +246,8 @@ ListGrid::GridTrack::~GridTrack() {
}
}
-const GridItemList& ListGrid::Cell(size_t row_index,
- size_t column_index) const {
+const GridItemList& ListGrid::Cell(wtf_size_t row_index,
+ wtf_size_t column_index) const {
DEFINE_STATIC_LOCAL(const GridItemList, empty_vector, ());
for (auto* row = rows_.Head(); row; row = row->Next()) {
if (row->Index() == row_index) {
@@ -267,8 +269,8 @@ ListGrid::GridTrack* ListGrid::InsertTracks(
return ComparePositions(first->Index(), second->Index());
};
- size_t start_line = span.StartLine();
- size_t end_line = span.EndLine();
+ wtf_size_t start_line = span.StartLine();
+ wtf_size_t end_line = span.EndLine();
DoublyLinkedList<ListGrid::GridTrack>::AddResult result = tracks.Insert(
base::WrapUnique(new GridTrack(start_line, direction)), compare_tracks);
@@ -276,7 +278,7 @@ ListGrid::GridTrack* ListGrid::InsertTracks(
DCHECK(track);
auto* iter = track;
- for (size_t track_index = start_line + 1; iter && track_index < end_line;
+ for (wtf_size_t track_index = start_line + 1; iter && track_index < end_line;
++track_index) {
if (!iter->Next() || track_index < iter->Next()->Index()) {
tracks.InsertAfter(
@@ -327,8 +329,8 @@ void ListGrid::Insert(LayoutBox& item, const GridArea& area) {
SetGridItemArea(item, area);
}
-void ListGrid::EnsureGridSize(size_t maximum_row_size,
- size_t maximum_column_size) {
+void ListGrid::EnsureGridSize(wtf_size_t maximum_row_size,
+ wtf_size_t maximum_column_size) {
num_rows_ = std::max(num_rows_, maximum_row_size);
num_columns_ = std::max(num_columns_, maximum_column_size);
}
@@ -362,16 +364,16 @@ ListGrid::GridCell* ListGrid::GridCell::NextInDirection(
std::unique_ptr<Grid::GridIterator> ListGrid::CreateIterator(
GridTrackSizingDirection direction,
- size_t fixed_track_index,
- size_t varying_track_index) const {
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index) const {
return base::WrapUnique(new ListGridIterator(
*this, direction, fixed_track_index, varying_track_index));
}
ListGridIterator::ListGridIterator(const ListGrid& grid,
GridTrackSizingDirection direction,
- size_t fixed_track_index,
- size_t varying_track_index)
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index)
: GridIterator(direction, fixed_track_index, varying_track_index),
grid_(grid) {}
@@ -383,7 +385,7 @@ LayoutBox* ListGridIterator::NextGridItem() {
if (!cell_node_) {
auto* track = is_row_axis ? grid_.columns_.Head() : grid_.rows_.Head();
DCHECK(track);
- const size_t fixed_index = is_row_axis ? column_index_ : row_index_;
+ const wtf_size_t fixed_index = is_row_axis ? column_index_ : row_index_;
while (track && track->Index() != fixed_index)
track = track->Next();
@@ -420,11 +422,11 @@ LayoutBox* ListGridIterator::NextGridItem() {
}
std::unique_ptr<GridArea> ListGridIterator::NextEmptyGridArea(
- size_t fixed_track_span,
- size_t varying_track_span) {
+ wtf_size_t fixed_track_span,
+ wtf_size_t varying_track_span) {
auto FindCellOrClosest = [](ListGrid::GridCell* cell_node,
GridTrackSizingDirection direction,
- size_t index) {
+ wtf_size_t index) {
auto ortho_direction = OrthogonalDirection(direction);
while (cell_node && cell_node->Index(direction) < index)
cell_node = cell_node->NextInDirection(ortho_direction);
@@ -434,8 +436,9 @@ std::unique_ptr<GridArea> ListGridIterator::NextEmptyGridArea(
auto CreateUniqueGridArea = [this, fixed_track_span, varying_track_span]() {
bool is_row_axis = direction_ == kForColumns;
- size_t row_span = is_row_axis ? varying_track_span : fixed_track_span;
- size_t column_span = is_row_axis ? fixed_track_span : varying_track_span;
+ wtf_size_t row_span = is_row_axis ? varying_track_span : fixed_track_span;
+ wtf_size_t column_span =
+ is_row_axis ? fixed_track_span : varying_track_span;
return std::make_unique<GridArea>(
GridSpan::TranslatedDefiniteGridSpan(row_index_, row_index_ + row_span),
GridSpan::TranslatedDefiniteGridSpan(column_index_,
@@ -443,10 +446,10 @@ std::unique_ptr<GridArea> ListGridIterator::NextEmptyGridArea(
};
auto CellIsInsideSpan = [](ListGrid::GridCell* cell_node,
- GridTrackSizingDirection direction, size_t start,
- size_t end) {
+ GridTrackSizingDirection direction,
+ wtf_size_t start, wtf_size_t end) {
DCHECK(cell_node);
- size_t cell_index = cell_node->Index(direction);
+ wtf_size_t cell_index = cell_node->Index(direction);
return cell_index >= start && cell_index <= end;
};
@@ -455,8 +458,8 @@ std::unique_ptr<GridArea> ListGridIterator::NextEmptyGridArea(
bool is_row_axis = direction_ == kForColumns;
auto& varying_index = is_row_axis ? row_index_ : column_index_;
- const size_t fixed_index = is_row_axis ? column_index_ : row_index_;
- const size_t end_fixed_span = fixed_index + fixed_track_span - 1;
+ const wtf_size_t fixed_index = is_row_axis ? column_index_ : row_index_;
+ const wtf_size_t end_fixed_span = fixed_index + fixed_track_span - 1;
auto* track_node = tracks.Head();
while (track_node && track_node->Index() < varying_index)
track_node = track_node->Next();
diff --git a/chromium/third_party/blink/renderer/core/layout/grid.h b/chromium/third_party/blink/renderer/core/layout/grid.h
index d902a63a5bf..4cf646f667e 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid.h
+++ b/chromium/third_party/blink/renderer/core/layout/grid.h
@@ -17,19 +17,21 @@
namespace blink {
-struct OrderedTrackIndexSetHashTraits : public HashTraits<size_t> {
+struct OrderedTrackIndexSetHashTraits : public HashTraits<wtf_size_t> {
static const bool kEmptyValueIsZero = false;
- static size_t EmptyValue() { return UINT_MAX; }
+ static wtf_size_t EmptyValue() { return UINT_MAX; }
- static void ConstructDeletedValue(size_t& slot, bool) { slot = UINT_MAX - 1; }
- static bool IsDeletedValue(const size_t& value) {
+ static void ConstructDeletedValue(wtf_size_t& slot, bool) {
+ slot = UINT_MAX - 1;
+ }
+ static bool IsDeletedValue(const wtf_size_t& value) {
return value == UINT_MAX - 1;
}
};
// TODO(svillar): Perhaps we should use references here.
typedef Vector<LayoutBox*, 1> GridItemList;
-typedef LinkedHashSet<size_t, OrderedTrackIndexSetHashTraits>
+typedef LinkedHashSet<wtf_size_t, OrderedTrackIndexSetHashTraits>
OrderedTrackIndexSet;
class LayoutGrid;
@@ -46,13 +48,13 @@ class CORE_EXPORT Grid {
public:
static std::unique_ptr<Grid> Create(const LayoutGrid*);
- virtual size_t NumTracks(GridTrackSizingDirection) const = 0;
+ virtual wtf_size_t NumTracks(GridTrackSizingDirection) const = 0;
- virtual void EnsureGridSize(size_t maximum_row_size,
- size_t maximum_column_size) = 0;
+ virtual void EnsureGridSize(wtf_size_t maximum_row_size,
+ wtf_size_t maximum_column_size) = 0;
virtual void Insert(LayoutBox&, const GridArea&) = 0;
- virtual const GridItemList& Cell(size_t row, size_t column) const = 0;
+ virtual const GridItemList& Cell(wtf_size_t row, wtf_size_t column) const = 0;
virtual ~Grid() {}
@@ -64,20 +66,21 @@ class CORE_EXPORT Grid {
GridSpan GridItemSpan(const LayoutBox&, GridTrackSizingDirection) const;
- size_t GridItemPaintOrder(const LayoutBox&) const;
- void SetGridItemPaintOrder(const LayoutBox&, size_t order);
+ wtf_size_t GridItemPaintOrder(const LayoutBox&) const;
+ void SetGridItemPaintOrder(const LayoutBox&, wtf_size_t order);
- size_t ExplicitGridStart(GridTrackSizingDirection) const;
- void SetExplicitGridStart(size_t row_start, size_t column_start);
+ wtf_size_t ExplicitGridStart(GridTrackSizingDirection) const;
+ void SetExplicitGridStart(wtf_size_t row_start, wtf_size_t column_start);
- size_t AutoRepeatTracks(GridTrackSizingDirection) const;
- void SetAutoRepeatTracks(size_t auto_repeat_rows, size_t auto_repeat_columns);
+ wtf_size_t AutoRepeatTracks(GridTrackSizingDirection) const;
+ void SetAutoRepeatTracks(wtf_size_t auto_repeat_rows,
+ wtf_size_t auto_repeat_columns);
void SetAutoRepeatEmptyColumns(std::unique_ptr<OrderedTrackIndexSet>);
void SetAutoRepeatEmptyRows(std::unique_ptr<OrderedTrackIndexSet>);
bool HasAutoRepeatEmptyTracks(GridTrackSizingDirection) const;
- bool IsEmptyAutoRepeatTrack(GridTrackSizingDirection, size_t) const;
+ bool IsEmptyAutoRepeatTrack(GridTrackSizingDirection, wtf_size_t) const;
OrderedTrackIndexSet* AutoRepeatEmptyTracks(GridTrackSizingDirection) const;
@@ -97,8 +100,8 @@ class CORE_EXPORT Grid {
virtual LayoutBox* NextGridItem() = 0;
virtual std::unique_ptr<GridArea> NextEmptyGridArea(
- size_t fixed_track_span,
- size_t varying_track_span) = 0;
+ wtf_size_t fixed_track_span,
+ wtf_size_t varying_track_span) = 0;
GridIterator(const GridIterator&) = delete;
GridIterator& operator=(const GridIterator&) = delete;
@@ -109,19 +112,19 @@ class CORE_EXPORT Grid {
// 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);
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index);
GridTrackSizingDirection direction_;
- size_t row_index_;
- size_t column_index_;
- size_t child_index_;
+ wtf_size_t row_index_;
+ wtf_size_t column_index_;
+ wtf_size_t child_index_;
};
virtual std::unique_ptr<GridIterator> CreateIterator(
GridTrackSizingDirection,
- size_t fixed_track_index,
- size_t varying_track_index = 0) const = 0;
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index = 0) const = 0;
protected:
Grid(const LayoutGrid*);
@@ -134,16 +137,16 @@ class CORE_EXPORT Grid {
OrderIterator order_iterator_;
- size_t explicit_column_start_{0};
- size_t explicit_row_start_{0};
+ wtf_size_t explicit_column_start_{0};
+ wtf_size_t explicit_row_start_{0};
- size_t auto_repeat_columns_{0};
- size_t auto_repeat_rows_{0};
+ wtf_size_t auto_repeat_columns_{0};
+ wtf_size_t auto_repeat_rows_{0};
bool needs_items_placement_{true};
HashMap<const LayoutBox*, GridArea> grid_item_area_;
- HashMap<const LayoutBox*, size_t> grid_items_indexes_map_;
+ HashMap<const LayoutBox*, wtf_size_t> grid_items_indexes_map_;
std::unique_ptr<OrderedTrackIndexSet> auto_repeat_empty_columns_{nullptr};
std::unique_ptr<OrderedTrackIndexSet> auto_repeat_empty_rows_{nullptr};
@@ -158,13 +161,13 @@ class CORE_EXPORT ListGrid final : public Grid {
public:
explicit ListGrid(const LayoutGrid* grid) : Grid(grid) {}
- size_t NumTracks(GridTrackSizingDirection direction) const override {
+ wtf_size_t NumTracks(GridTrackSizingDirection direction) const override {
return direction == kForRows ? num_rows_ : num_columns_;
}
- const GridItemList& Cell(size_t row, size_t column) const override;
+ const GridItemList& Cell(wtf_size_t row, wtf_size_t column) const override;
void Insert(LayoutBox&, const GridArea&) override;
- void EnsureGridSize(size_t maximum_row_size,
- size_t maximum_column_size) override;
+ void EnsureGridSize(wtf_size_t maximum_row_size,
+ wtf_size_t maximum_column_size) override;
~ListGrid() final;
@@ -177,9 +180,9 @@ class CORE_EXPORT ListGrid final : public Grid {
friend class WTF::DoublyLinkedListNode<GridCell>;
public:
- GridCell(size_t row, size_t column) : row_(row), column_(column) {}
+ GridCell(wtf_size_t row, wtf_size_t column) : row_(row), column_(column) {}
- size_t Index(GridTrackSizingDirection direction) const {
+ wtf_size_t Index(GridTrackSizingDirection direction) const {
return direction == kForRows ? row_ : column_;
}
@@ -217,8 +220,8 @@ class CORE_EXPORT ListGrid final : public Grid {
GridTrackSizingDirection direction_{kForColumns};
GridItemList items_;
- size_t row_;
- size_t column_;
+ wtf_size_t row_;
+ wtf_size_t column_;
};
// This class represents a track (column or row) of the grid. Each
@@ -235,16 +238,16 @@ class CORE_EXPORT ListGrid final : public Grid {
friend class WTF::DoublyLinkedListNode<GridTrack>;
public:
- GridTrack(size_t index, GridTrackSizingDirection direction)
+ GridTrack(wtf_size_t index, GridTrackSizingDirection direction)
: index_(index), direction_(direction) {}
- size_t Index() const { return index_; }
+ wtf_size_t Index() const { return index_; }
DoublyLinkedList<GridCell>::AddResult Insert(GridCell*);
DoublyLinkedList<GridCell>::AddResult InsertAfter(
GridCell* cell,
GridCell* insertion_point);
DoublyLinkedList<GridCell>::AddResult Insert(LayoutBox&, const GridSpan&);
- GridCell* Find(size_t cell_index) const;
+ GridCell* Find(wtf_size_t cell_index) const;
const DoublyLinkedList<GridCell>& Cells() const { return cells_; }
@@ -252,7 +255,7 @@ class CORE_EXPORT ListGrid final : public Grid {
private:
DoublyLinkedList<GridCell> cells_;
- size_t index_;
+ wtf_size_t index_;
GridTrackSizingDirection direction_;
GridTrack* prev_;
@@ -277,11 +280,11 @@ class CORE_EXPORT ListGrid final : public Grid {
std::unique_ptr<GridIterator> CreateIterator(
GridTrackSizingDirection,
- size_t fixed_track_index,
- size_t varying_track_index = 0) const override;
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index = 0) const override;
- size_t num_rows_{0};
- size_t num_columns_{0};
+ wtf_size_t num_rows_{0};
+ wtf_size_t num_columns_{0};
DoublyLinkedList<GridTrack> columns_;
DoublyLinkedList<GridTrack> rows_;
@@ -293,15 +296,15 @@ class ListGridIterator final : public Grid::GridIterator {
public:
ListGridIterator(const ListGrid& grid,
GridTrackSizingDirection,
- size_t fixed_track_index,
- size_t varying_track_index = 0);
+ wtf_size_t fixed_track_index,
+ wtf_size_t varying_track_index = 0);
ListGridIterator(const ListGridIterator&) = delete;
ListGridIterator& operator=(const ListGridIterator&) = delete;
LayoutBox* NextGridItem() override;
std::unique_ptr<GridArea> NextEmptyGridArea(
- size_t fixed_track_span,
- size_t varying_track_span) override;
+ wtf_size_t fixed_track_span,
+ wtf_size_t varying_track_span) override;
private:
const ListGrid& grid_;
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_test.cc b/chromium/third_party/blink/renderer/core/layout/grid_test.cc
index f4ba478914f..cbc0a34ea50 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/grid_test.cc
@@ -104,17 +104,17 @@ TEST_F(GridTest, OverlappingChildren) {
auto* grid = layout_grid->InternalGrid();
ASSERT_NE(grid, nullptr);
- size_t num_rows = grid->NumTracks(kForRows);
- size_t num_cols = grid->NumTracks(kForColumns);
+ wtf_size_t num_rows = grid->NumTracks(kForRows);
+ wtf_size_t num_cols = grid->NumTracks(kForColumns);
EXPECT_EQ(3u, num_rows);
EXPECT_EQ(3u, num_cols);
EXPECT_TRUE(grid->HasGridItems());
- size_t index = 0;
- Vector<size_t> expected_items_per_cell = {1, 2, 1, 2, 4, 2, 1, 2, 1};
- for (size_t row = 0; row < num_rows; ++row) {
- for (size_t col = 0; col < num_cols; ++col)
+ wtf_size_t index = 0;
+ Vector<wtf_size_t> expected_items_per_cell = {1, 2, 1, 2, 4, 2, 1, 2, 1};
+ for (wtf_size_t row = 0; row < num_rows; ++row) {
+ for (wtf_size_t col = 0; col < num_cols; ++col)
EXPECT_EQ(expected_items_per_cell[index++], grid->Cell(row, col).size());
}
}
@@ -140,16 +140,16 @@ TEST_F(GridTest, PartiallyOverlappingChildren) {
auto* grid = layout_grid->InternalGrid();
ASSERT_NE(grid, nullptr);
- size_t num_rows = grid->NumTracks(kForRows);
- size_t num_cols = grid->NumTracks(kForColumns);
+ wtf_size_t num_rows = grid->NumTracks(kForRows);
+ wtf_size_t num_cols = grid->NumTracks(kForColumns);
EXPECT_EQ(1u, num_rows);
EXPECT_EQ(3u, num_cols);
EXPECT_TRUE(grid->HasGridItems());
- size_t index = 0;
- Vector<size_t> expected_items_per_cell = {2, 1, 1};
- for (size_t col = 0; col < num_cols; ++col)
+ wtf_size_t index = 0;
+ Vector<wtf_size_t> expected_items_per_cell = {2, 1, 1};
+ for (wtf_size_t col = 0; col < num_cols; ++col)
EXPECT_EQ(expected_items_per_cell[index++], grid->Cell(0, col).size());
}
@@ -230,7 +230,7 @@ TEST_F(GridTest, AutoFit) {
ASSERT_NE(empty_tracks, nullptr);
ASSERT_EQ(empty_tracks->size(), 5u);
Vector<size_t> expected_empty_tracks = {0, 5, 6, 7, 9};
- size_t index = 0;
+ wtf_size_t index = 0;
for (auto track : *empty_tracks) {
EXPECT_EQ(expected_empty_tracks[index++], track);
EXPECT_TRUE(grid->IsEmptyAutoRepeatTrack(kForColumns, track));
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 9ab89205259..e9309399be3 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
@@ -93,12 +93,12 @@ static GridTrackSizingDirection GridDirectionForAxis(GridAxis axis) {
template <typename F>
static void IterateGridItemsInTrackIndices(const Grid& grid,
GridTrackSizingDirection direction,
- Vector<size_t>& track_indices,
+ Vector<wtf_size_t>& track_indices,
F callback) {
#if DCHECK_IS_ON()
HashSet<LayoutBox*> items_set;
#endif
- for (size_t i = 0; i < track_indices.size(); ++i) {
+ for (wtf_size_t i = 0; i < track_indices.size(); ++i) {
auto iterator = grid.CreateIterator(direction, track_indices[i]);
while (LayoutBox* grid_item = iterator->NextGridItem()) {
const GridSpan& span = grid.GridItemSpan(*grid_item, direction);
@@ -128,11 +128,10 @@ class IndefiniteSizeStrategy final : public GridTrackSizingAlgorithmStrategy {
void MaximizeTracks(Vector<GridTrack>&,
absl::optional<LayoutUnit>& free_space) override;
double FindUsedFlexFraction(
- Vector<size_t>& flexible_sized_tracks_index,
+ Vector<wtf_size_t>& flexible_sized_tracks_index,
GridTrackSizingDirection,
absl::optional<LayoutUnit> free_space) const override;
bool RecomputeUsedFlexFractionIfNeeded(
- Vector<size_t>& flexible_sized_tracks_index,
double& flex_fraction,
Vector<LayoutUnit>& increments,
LayoutUnit& total_growth) const override;
@@ -154,11 +153,10 @@ class DefiniteSizeStrategy final : public GridTrackSizingAlgorithmStrategy {
void MaximizeTracks(Vector<GridTrack>&,
absl::optional<LayoutUnit>& free_space) override;
double FindUsedFlexFraction(
- Vector<size_t>& flexible_sized_tracks_index,
+ Vector<wtf_size_t>& flexible_sized_tracks_index,
GridTrackSizingDirection,
absl::optional<LayoutUnit> free_space) const override;
bool RecomputeUsedFlexFractionIfNeeded(
- Vector<size_t>& flexible_sized_tracks_index,
double& flex_fraction,
Vector<LayoutUnit>& increments,
LayoutUnit& total_growth) const override {
@@ -294,7 +292,7 @@ LayoutUnit GridTrackSizingAlgorithm::GridAreaBreadthForChild(
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 (auto track_position : span)
grid_area_breadth += all_tracks[track_position].BaseSize();
if (add_content_alignment_offset) {
@@ -314,7 +312,7 @@ bool GridTrackSizingAlgorithm::IsIntrinsicSizedGridArea(const LayoutBox& child,
DCHECK(WasSetup());
GridTrackSizingDirection direction = GridDirectionForAxis(axis);
const GridSpan& span = grid_.GridItemSpan(child, direction);
- for (const auto& track_position : span) {
+ for (auto track_position : span) {
const GridTrackSize& track_size =
RawGridTrackSize(direction, track_position);
// We consider fr units as 'auto' for the min sizing function.
@@ -452,7 +450,7 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MinSizeForChild(
algorithm_.GetGrid().GridItemSpan(child, Direction());
LayoutUnit max_breadth;
const Vector<GridTrack>& all_tracks = algorithm_.Tracks(Direction());
- for (const auto& track_position : span) {
+ for (auto track_position : span) {
const GridTrackSize& track_size =
all_tracks[track_position].CachedTrackSize();
if (!track_size.HasFixedMaxTrackBreadth())
@@ -511,9 +509,12 @@ bool GridTrackSizingAlgorithm::CanParticipateInBaselineAlignment(
bool GridTrackSizingAlgorithm::ParticipateInBaselineAlignment(
const LayoutBox& child,
GridAxis baseline_axis) const {
- return baseline_axis == kGridColumnAxis
- ? column_baseline_items_map_.at(&child)
- : row_baseline_items_map_.at(&child);
+ if (baseline_axis == kGridColumnAxis) {
+ auto it = column_baseline_items_map_.find(&child);
+ return it != column_baseline_items_map_.end() ? it->value : false;
+ }
+ auto it = row_baseline_items_map_.find(&child);
+ return it != row_baseline_items_map_.end() ? it->value : false;
}
void GridTrackSizingAlgorithm::UpdateBaselineAlignmentContext(
@@ -643,9 +644,9 @@ void DefiniteSizeStrategy::LayoutGridItemForMinSizeComputation(
void DefiniteSizeStrategy::MaximizeTracks(
Vector<GridTrack>& tracks,
absl::optional<LayoutUnit>& free_space) {
- size_t tracks_size = tracks.size();
+ wtf_size_t tracks_size = tracks.size();
Vector<GridTrack*> tracks_for_distribution(tracks_size);
- for (size_t i = 0; i < tracks_size; ++i) {
+ for (wtf_size_t i = 0; i < tracks_size; ++i) {
tracks_for_distribution[i] = tracks.data() + i;
tracks_for_distribution[i]->SetPlannedSize(
tracks_for_distribution[i]->BaseSize());
@@ -659,7 +660,7 @@ void DefiniteSizeStrategy::MaximizeTracks(
}
double DefiniteSizeStrategy::FindUsedFlexFraction(
- Vector<size_t>& flexible_sized_tracks_index,
+ Vector<wtf_size_t>& flexible_sized_tracks_index,
GridTrackSizingDirection direction,
absl::optional<LayoutUnit> free_space) const {
GridSpan all_tracks_span = GridSpan::TranslatedDefiniteGridSpan(
@@ -709,7 +710,7 @@ static inline double NormalizedFlexFraction(const GridTrack& track) {
}
double IndefiniteSizeStrategy::FindUsedFlexFraction(
- Vector<size_t>& flexible_sized_tracks_index,
+ Vector<wtf_size_t>& flexible_sized_tracks_index,
GridTrackSizingDirection direction,
absl::optional<LayoutUnit>) const {
auto all_tracks = algorithm_.Tracks(direction);
@@ -742,7 +743,6 @@ double IndefiniteSizeStrategy::FindUsedFlexFraction(
}
bool IndefiniteSizeStrategy::RecomputeUsedFlexFractionIfNeeded(
- Vector<size_t>& flexible_sized_tracks_index,
double& flex_fraction,
Vector<LayoutUnit>& increments,
LayoutUnit& total_growth) const {
@@ -771,7 +771,7 @@ bool IndefiniteSizeStrategy::RecomputeUsedFlexFractionIfNeeded(
layout_grid->GuttersSize(grid, kForRows, 0, grid.NumTracks(kForRows),
AvailableSpace());
- size_t number_of_tracks = algorithm_.Tracks(Direction()).size();
+ wtf_size_t number_of_tracks = algorithm_.Tracks(Direction()).size();
flex_fraction = FindFrUnitSize(
GridSpan::TranslatedDefiniteGridSpan(0, number_of_tracks), free_space);
return true;
@@ -875,33 +875,34 @@ void GridTrackSizingAlgorithm::SetFreeSpace(
const GridTrackSize& GridTrackSizingAlgorithm::RawGridTrackSize(
GridTrackSizingDirection direction,
- size_t translated_index) const {
+ wtf_size_t translated_index) const {
bool is_row_axis = direction == kForColumns;
- const Vector<GridTrackSize>& track_styles =
+ const Vector<GridTrackSize, 1>& track_styles =
is_row_axis
? layout_grid_->StyleRef().GridTemplateColumns().LegacyTrackList()
: layout_grid_->StyleRef().GridTemplateRows().LegacyTrackList();
- const Vector<GridTrackSize>& auto_repeat_track_styles =
+ const Vector<GridTrackSize, 1>& auto_repeat_track_styles =
is_row_axis ? layout_grid_->StyleRef().GridAutoRepeatColumns()
: layout_grid_->StyleRef().GridAutoRepeatRows();
- const Vector<GridTrackSize>& auto_track_styles =
+ const Vector<GridTrackSize, 1>& auto_track_styles =
is_row_axis ? layout_grid_->StyleRef().GridAutoColumns().LegacyTrackList()
: layout_grid_->StyleRef().GridAutoRows().LegacyTrackList();
- size_t insertion_point =
+ wtf_size_t insertion_point =
is_row_axis
? layout_grid_->StyleRef().GridAutoRepeatColumnsInsertionPoint()
: layout_grid_->StyleRef().GridAutoRepeatRowsInsertionPoint();
- size_t auto_repeat_tracks_count = grid_.AutoRepeatTracks(direction);
+ wtf_size_t auto_repeat_tracks_count = grid_.AutoRepeatTracks(direction);
// We should not use GridPositionsResolver::explicitGridXXXCount() for this
// because the explicit grid might be larger than the number of tracks in
// grid-template-rows|columns (if grid-template-areas is specified for
// example).
- size_t explicit_tracks_count = track_styles.size() + auto_repeat_tracks_count;
+ wtf_size_t explicit_tracks_count =
+ track_styles.size() + auto_repeat_tracks_count;
int untranslated_index_as_int =
- translated_index - grid_.ExplicitGridStart(direction);
- size_t auto_track_styles_size = auto_track_styles.size();
+ static_cast<int>(translated_index - grid_.ExplicitGridStart(direction));
+ wtf_size_t auto_track_styles_size = auto_track_styles.size();
if (untranslated_index_as_int < 0) {
int index =
untranslated_index_as_int % static_cast<int>(auto_track_styles_size);
@@ -911,7 +912,8 @@ const GridTrackSize& GridTrackSizingAlgorithm::RawGridTrackSize(
return auto_track_styles[index];
}
- size_t untranslated_index = static_cast<size_t>(untranslated_index_as_int);
+ wtf_size_t untranslated_index =
+ static_cast<wtf_size_t>(untranslated_index_as_int);
if (untranslated_index >= explicit_tracks_count) {
return auto_track_styles[(untranslated_index - explicit_tracks_count) %
auto_track_styles_size];
@@ -921,8 +923,7 @@ const GridTrackSize& GridTrackSizingAlgorithm::RawGridTrackSize(
return track_styles[untranslated_index];
if (untranslated_index < (insertion_point + auto_repeat_tracks_count)) {
- size_t auto_repeat_local_index =
- untranslated_index_as_int - insertion_point;
+ wtf_size_t auto_repeat_local_index = untranslated_index - insertion_point;
return auto_repeat_track_styles[auto_repeat_local_index %
auto_repeat_track_styles.size()];
}
@@ -948,7 +949,7 @@ bool GridTrackSizingAlgorithm::IsRelativeSizedTrackAsAuto(
GridTrackSize GridTrackSizingAlgorithm::CalculateGridTrackSize(
GridTrackSizingDirection direction,
- size_t translated_index) const {
+ wtf_size_t translated_index) const {
DCHECK(WasSetup());
// Collapse empty auto repeat tracks if auto-fit.
if (grid_.HasAutoRepeatEmptyTracks(direction) &&
@@ -1050,8 +1051,8 @@ void GridTrackSizingAlgorithm::InitializeTrackSizes() {
Vector<GridTrack>& track_list = Tracks(direction_);
bool indefinite_height =
direction_ == kForRows && !layout_grid_->CachedHasDefiniteLogicalHeight();
- size_t num_tracks = track_list.size();
- for (size_t i = 0; i < num_tracks; ++i) {
+ wtf_size_t num_tracks = track_list.size();
+ for (wtf_size_t i = 0; i < num_tracks; ++i) {
const GridTrackSize& track_size = CalculateGridTrackSize(direction_, i);
GridTrack& track = track_list[i];
track.SetCachedTrackSize(track_size);
@@ -1085,7 +1086,7 @@ void GridTrackSizingAlgorithm::SizeTrackToFitNonSpanningItem(
const GridSpan& span,
LayoutBox& grid_item,
GridTrack& track) {
- const size_t track_position = span.StartLine();
+ const wtf_size_t track_position = span.StartLine();
const GridTrackSize& track_size =
Tracks(direction_)[track_position].CachedTrackSize();
@@ -1118,7 +1119,7 @@ void GridTrackSizingAlgorithm::SizeTrackToFitNonSpanningItem(
bool GridTrackSizingAlgorithm::SpanningItemCrossesFlexibleSizedTracks(
const GridSpan& span) const {
const Vector<GridTrack>& track_list = Tracks(direction_);
- for (const auto& track_position : span) {
+ for (auto track_position : span) {
const GridTrackSize& track_size =
track_list[track_position].CachedTrackSize();
if (track_size.MinTrackBreadth().IsFlex() ||
@@ -1351,8 +1352,8 @@ void GridTrackSizingAlgorithm::DistributeSpaceToTracks(
if (available_logical_space > 0) {
std::sort(tracks.begin(), tracks.end(), SortByGridTrackGrowthPotential);
- size_t tracks_size = tracks.size();
- for (size_t i = 0; i < tracks_size; ++i) {
+ wtf_size_t tracks_size = tracks.size();
+ for (wtf_size_t i = 0; i < tracks_size; ++i) {
GridTrack& track = *tracks[i];
LayoutUnit available_logical_space_share =
available_logical_space / (tracks_size - i);
@@ -1382,9 +1383,9 @@ void GridTrackSizingAlgorithm::DistributeSpaceToTracks(
SortByGridTrackGrowthPotential);
}
- size_t tracks_growing_above_max_breadth_size =
+ wtf_size_t tracks_growing_above_max_breadth_size =
grow_beyond_growth_limits_tracks->size();
- for (size_t i = 0; i < tracks_growing_above_max_breadth_size; ++i) {
+ for (wtf_size_t i = 0; i < tracks_growing_above_max_breadth_size; ++i) {
GridTrack* track = grow_beyond_growth_limits_tracks->at(i);
LayoutUnit growth_share =
available_logical_space / (tracks_growing_above_max_breadth_size - i);
@@ -1426,7 +1427,7 @@ void GridTrackSizingAlgorithm::IncreaseSizesToAccommodateSpanningItems(
grow_beyond_growth_limits_tracks.Shrink(0);
filtered_tracks.Shrink(0);
LayoutUnit spanning_tracks_size;
- for (const auto& track_position : item_span) {
+ for (auto track_position : item_span) {
GridTrack& track = all_tracks[track_position];
const GridTrackSize& track_size = track.CachedTrackSize();
spanning_tracks_size +=
@@ -1550,8 +1551,8 @@ double GridTrackSizingAlgorithm::FindFrUnitSize(
const Vector<GridTrack>& all_tracks = Tracks(direction_);
double flex_factor_sum = 0;
- Vector<size_t, 8> flexible_tracks_indexes;
- for (const auto& track_index : tracks_span) {
+ Vector<wtf_size_t, 8> flexible_tracks_indexes;
+ for (auto track_index : tracks_span) {
const GridTrackSize& track_size = all_tracks[track_index].CachedTrackSize();
if (!track_size.MaxTrackBreadth().IsFlex()) {
left_over_space -= all_tracks[track_index].BaseSize();
@@ -1574,7 +1575,7 @@ double GridTrackSizingAlgorithm::ComputeFlexFactorUnitSize(
const Vector<GridTrack>& tracks,
double flex_factor_sum,
LayoutUnit& left_over_space,
- const Vector<size_t, 8>& flexible_tracks_indexes,
+ const Vector<wtf_size_t, 8>& flexible_tracks_indexes,
std::unique_ptr<TrackIndexSet> tracks_to_treat_as_inflexible) const {
// We want to avoid the effect of flex factors sum below 1 making the factor
// unit size to grow exponentially.
@@ -1617,11 +1618,11 @@ void GridTrackSizingAlgorithm::ComputeFlexSizedTracksGrowth(
double flex_fraction,
Vector<LayoutUnit>& increments,
LayoutUnit& total_growth) const {
- size_t num_flex_tracks = flexible_sized_tracks_index_.size();
+ wtf_size_t num_flex_tracks = flexible_sized_tracks_index_.size();
DCHECK_EQ(increments.size(), num_flex_tracks);
const Vector<GridTrack>& all_tracks = Tracks(direction_);
- for (size_t i = 0; i < num_flex_tracks; ++i) {
- size_t track_index = flexible_sized_tracks_index_[i];
+ for (wtf_size_t i = 0; i < num_flex_tracks; ++i) {
+ wtf_size_t track_index = flexible_sized_tracks_index_[i];
const GridTrackSize& track_size = all_tracks[track_index].CachedTrackSize();
DCHECK(track_size.MaxTrackBreadth().IsFlex());
LayoutUnit old_base_size = all_tracks[track_index].BaseSize();
@@ -1646,14 +1647,13 @@ void GridTrackSizingAlgorithm::StretchFlexibleTracks(
increments.Grow(flexible_sized_tracks_index_.size());
ComputeFlexSizedTracksGrowth(flex_fraction, increments, total_growth);
- if (strategy_->RecomputeUsedFlexFractionIfNeeded(flexible_sized_tracks_index_,
- flex_fraction, increments,
+ if (strategy_->RecomputeUsedFlexFractionIfNeeded(flex_fraction, increments,
total_growth)) {
total_growth = LayoutUnit(0);
ComputeFlexSizedTracksGrowth(flex_fraction, increments, total_growth);
}
- size_t i = 0;
+ wtf_size_t i = 0;
Vector<GridTrack>& all_tracks = Tracks(direction_);
for (auto track_index : flexible_sized_tracks_index_) {
auto& track = all_tracks[track_index];
@@ -1720,7 +1720,7 @@ bool GridTrackSizingAlgorithm::IsValidTransition() const {
void GridTrackSizingAlgorithm::Setup(
GridTrackSizingDirection direction,
- size_t num_tracks,
+ wtf_size_t num_tracks,
absl::optional<LayoutUnit> available_space) {
DCHECK(needs_setup_);
direction_ = direction;
@@ -1832,7 +1832,7 @@ void GridTrackSizingAlgorithm::Reset() {
#if DCHECK_IS_ON()
bool GridTrackSizingAlgorithm::TracksAreWiderThanMinTrackBreadth() const {
const Vector<GridTrack>& all_tracks = Tracks(direction_);
- for (size_t i = 0; i < all_tracks.size(); ++i) {
+ for (wtf_size_t i = 0; i < all_tracks.size(); ++i) {
const GridTrackSize& track_size = all_tracks[i].CachedTrackSize();
if (InitialBaseSize(track_size) > all_tracks[i].BaseSize())
return false;
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 74d9a00b73c..b03a57abb52 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
@@ -98,7 +98,7 @@ class GridTrackSizingAlgorithm final {
// Setup() must be run before calling Run() as it configures the behaviour of
// the algorithm.
void Setup(GridTrackSizingDirection,
- size_t num_tracks,
+ wtf_size_t num_tracks,
absl::optional<LayoutUnit> available_space);
void Run();
void Reset();
@@ -145,9 +145,9 @@ class GridTrackSizingAlgorithm final {
bool IsRelativeSizedTrackAsAuto(const GridTrackSize&,
GridTrackSizingDirection) const;
GridTrackSize CalculateGridTrackSize(GridTrackSizingDirection,
- size_t translated_index) const;
+ wtf_size_t translated_index) const;
const GridTrackSize& RawGridTrackSize(GridTrackSizingDirection,
- size_t translated_index) const;
+ wtf_size_t translated_index) const;
// Helper methods for step 1. initializeTrackSizes().
LayoutUnit InitialBaseSize(const GridTrackSize&) const;
@@ -192,7 +192,7 @@ class GridTrackSizingAlgorithm final {
const Vector<GridTrack>& tracks,
double flex_factor_sum,
LayoutUnit& left_over_space,
- const Vector<size_t, 8>& flexible_tracks_indexes,
+ const Vector<wtf_size_t, 8>& flexible_tracks_indexes,
std::unique_ptr<TrackIndexSet> tracks_to_treat_as_inflexible =
nullptr) const;
void ComputeFlexSizedTracksGrowth(double flex_fraction,
@@ -227,9 +227,9 @@ class GridTrackSizingAlgorithm final {
// writing modes.
Vector<GridTrack> columns_;
Vector<GridTrack> rows_;
- Vector<size_t> content_sized_tracks_index_;
- Vector<size_t> flexible_sized_tracks_index_;
- Vector<size_t> auto_sized_tracks_for_stretch_index_;
+ Vector<wtf_size_t> content_sized_tracks_index_;
+ Vector<wtf_size_t> flexible_sized_tracks_index_;
+ Vector<wtf_size_t> auto_sized_tracks_for_stretch_index_;
GridTrackSizingDirection direction_;
@@ -290,11 +290,10 @@ class GridTrackSizingAlgorithmStrategy {
virtual void MaximizeTracks(Vector<GridTrack>&,
absl::optional<LayoutUnit>& free_space) = 0;
virtual double FindUsedFlexFraction(
- Vector<size_t>& flexible_sized_tracks_index,
+ Vector<wtf_size_t>& flexible_sized_tracks_index,
GridTrackSizingDirection,
absl::optional<LayoutUnit> initial_free_space) const = 0;
virtual bool RecomputeUsedFlexFractionIfNeeded(
- Vector<size_t>& flexible_sized_tracks_index,
double& flex_fraction,
Vector<LayoutUnit>& increments,
LayoutUnit& total_growth) const = 0;
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_request.h b/chromium/third_party/blink/renderer/core/layout/hit_test_request.h
index 315a8c111fc..7cbefe1ef6c 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_request.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_request.h
@@ -78,6 +78,11 @@ class HitTestRequest {
bool IsChildFrameHitTest() const {
return request_type_ & kChildFrameHitTest;
}
+ // Returns true if this request is used for occlusion.
+ // See |LayoutObject::HitTestForOcclusion()|
+ bool IsHitTestVisualOverflow() const {
+ return request_type_ & kHitTestVisualOverflow;
+ }
bool IgnorePointerEventsNone() const {
return request_type_ & kIgnorePointerEventsNone;
}
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 1a8f35dae41..06e0ec83cd9 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
@@ -42,7 +42,9 @@
#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_block.h"
+#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#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/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
@@ -257,7 +259,10 @@ CompositorElementId HitTestResult::GetScrollableContainer() const {
cur_box->UniqueId(), CompositorElementIdNamespace::kScroll);
}
- cur_box = cur_box->ContainingBlock();
+ if (IsA<LayoutView>(cur_box))
+ cur_box = cur_box->GetFrame()->OwnerLayoutObject();
+ else
+ cur_box = cur_box->ContainingBlock();
}
return InnerNode()
@@ -508,26 +513,40 @@ bool HitTestResult::IsContentEditable() const {
return HasEditableStyle(*inner_node_);
}
-ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
+std::tuple<bool, ListBasedHitTestBehavior>
+HitTestResult::AddNodeToListBasedTestResultInternal(
Node* node,
- const HitTestLocation& location,
- const PhysicalRect& rect) {
+ const HitTestLocation& location) {
// If we are in the process of retargeting for `inert`, continue.
if (GetHitTestRequest().RetargetForInert() && InertNode() && !InnerNode())
- return kContinueHitTesting;
+ return std::make_tuple(false, kContinueHitTesting);
// If not a list-based test, stop testing because the hit has been found.
if (!GetHitTestRequest().ListBased())
- return kStopHitTesting;
+ return std::make_tuple(false, kStopHitTesting);
if (!node)
- return kContinueHitTesting;
+ return std::make_tuple(false, kContinueHitTesting);
MutableListBasedTestResult().insert(node);
if (GetHitTestRequest().PenetratingList())
- return kContinueHitTesting;
+ return std::make_tuple(false, kContinueHitTesting);
+ // The second argument will be ignored.
+ return std::make_tuple(true, kContinueHitTesting);
+}
+
+ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
+ Node* node,
+ const HitTestLocation& location,
+ const PhysicalRect& rect) {
+ bool should_check_containment;
+ ListBasedHitTestBehavior behavior;
+ std::tie(should_check_containment, behavior) =
+ AddNodeToListBasedTestResultInternal(node, location);
+ if (!should_check_containment)
+ return behavior;
return rect.Contains(location.BoundingBox()) ? kStopHitTesting
: kContinueHitTesting;
}
@@ -535,23 +554,28 @@ ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
Node* node,
const HitTestLocation& location,
- const Region& region) {
- // If we are in the process of retargeting for `inert`, continue.
- if (GetHitTestRequest().RetargetForInert() && InertNode() && !InnerNode())
- return kContinueHitTesting;
-
- // If not a list-based test, stop testing because the hit has been found.
- if (!GetHitTestRequest().ListBased())
- return kStopHitTesting;
-
- if (!node)
- return kContinueHitTesting;
-
- MutableListBasedTestResult().insert(node);
-
- if (GetHitTestRequest().PenetratingList())
- return kContinueHitTesting;
+ const FloatQuad& quad) {
+ bool should_check_containment;
+ ListBasedHitTestBehavior behavior;
+ std::tie(should_check_containment, behavior) =
+ AddNodeToListBasedTestResultInternal(node, location);
+ if (!should_check_containment)
+ return behavior;
+ return quad.ContainsQuad(FloatRect(location.BoundingBox()))
+ ? kStopHitTesting
+ : kContinueHitTesting;
+}
+ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
+ Node* node,
+ const HitTestLocation& location,
+ const Region& region) {
+ bool should_check_containment;
+ ListBasedHitTestBehavior behavior;
+ std::tie(should_check_containment, behavior) =
+ AddNodeToListBasedTestResultInternal(node, location);
+ if (!should_check_containment)
+ return behavior;
return region.Contains(location.EnclosingIntRect()) ? kStopHitTesting
: kContinueHitTesting;
}
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 4a61ec20a64..7bf8474b44a 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
@@ -22,6 +22,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_HIT_TEST_RESULT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_HIT_TEST_RESULT_H_
+#include <tuple>
+
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
@@ -180,6 +182,9 @@ class CORE_EXPORT HitTestResult {
const PhysicalRect& = PhysicalRect());
ListBasedHitTestBehavior AddNodeToListBasedTestResult(Node*,
const HitTestLocation&,
+ const FloatQuad& quad);
+ ListBasedHitTestBehavior AddNodeToListBasedTestResult(Node*,
+ const HitTestLocation&,
const Region&);
void Append(const HitTestResult&);
@@ -200,6 +205,9 @@ class CORE_EXPORT HitTestResult {
private:
NodeSet& MutableListBasedTestResult(); // See above.
HTMLMediaElement* MediaElement() const;
+ std::tuple<bool, ListBasedHitTestBehavior>
+ AddNodeToListBasedTestResultInternal(Node* node,
+ const HitTestLocation& location);
HitTestRequest hit_test_request_;
bool cacheable_;
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc b/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc
index 958da2c32c5..639be108f85 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.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/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_testing_transform_state.h b/chromium/third_party/blink/renderer/core/layout/hit_testing_transform_state.h
index a6f040ec7ec..10929a4982c 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_testing_transform_state.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_testing_transform_state.h
@@ -53,12 +53,9 @@ class HitTestingTransformState {
last_planar_area_(area),
accumulating_transform_(false) {}
- HitTestingTransformState(const HitTestingTransformState& other)
- : last_planar_point_(other.last_planar_point_),
- last_planar_quad_(other.last_planar_quad_),
- last_planar_area_(other.last_planar_area_),
- accumulated_transform_(other.accumulated_transform_),
- accumulating_transform_(other.accumulating_transform_) {}
+ HitTestingTransformState(const HitTestingTransformState&) = default;
+ HitTestingTransformState& operator=(const HitTestingTransformState&) =
+ default;
enum TransformAccumulation { kFlattenTransform, kAccumulateTransform };
void Translate(int x, int y, TransformAccumulation);
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 bddde616799..29b5e12670b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block.cc
@@ -55,6 +55,7 @@
#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_object_inlines.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"
@@ -1020,12 +1021,13 @@ void LayoutBlock::PaintObject(const PaintInfo& paint_info,
TrackedLayoutBoxListHashSet* LayoutBlock::PositionedObjectsInternal() const {
NOT_DESTROYED();
- return GetPositionedDescendantsMap().at(this);
+ auto it = GetPositionedDescendantsMap().find(this);
+ return it != GetPositionedDescendantsMap().end() ? &*it->value : nullptr;
}
void LayoutBlock::InsertPositionedObject(LayoutBox* o) {
NOT_DESTROYED();
- DCHECK(!IsAnonymousBlock());
+ DCHECK(!IsAnonymousBlock() || IsAnonymousNGMulticolInlineWrapper());
DCHECK_EQ(o->ContainingBlock(), this);
o->ClearOverrideContainingBlockContentSize();
@@ -1042,8 +1044,9 @@ void LayoutBlock::InsertPositionedObject(LayoutBox* o) {
}
GetPositionedContainerMap().Set(o, this);
+ auto it = GetPositionedDescendantsMap().find(this);
TrackedLayoutBoxListHashSet* descendant_set =
- GetPositionedDescendantsMap().at(this);
+ it != GetPositionedDescendantsMap().end() ? &*it->value : nullptr;
if (!descendant_set) {
descendant_set = new TrackedLayoutBoxListHashSet;
GetPositionedDescendantsMap().Set(this, base::WrapUnique(descendant_set));
@@ -1071,7 +1074,7 @@ void LayoutBlock::RemovePositionedObject(LayoutBox* o) {
bool LayoutBlock::IsAnonymousNGFieldsetContentWrapper() const {
NOT_DESTROYED();
- return Parent() && Parent()->IsLayoutNGFieldset();
+ return Parent() && Parent()->IsLayoutNGFieldset() && IsAnonymous();
}
void LayoutBlock::InvalidatePaint(
@@ -1190,8 +1193,9 @@ void LayoutBlock::AddPercentHeightDescendant(LayoutBox* descendant) {
cb = cb->ContainingBlock();
}
+ auto it = GetPercentHeightDescendantsMap().find(this);
TrackedLayoutBoxListHashSet* descendant_set =
- GetPercentHeightDescendantsMap().at(this);
+ it != GetPercentHeightDescendantsMap().end() ? &*it->value : nullptr;
if (!descendant_set) {
descendant_set = new TrackedLayoutBoxListHashSet;
GetPercentHeightDescendantsMap().Set(this,
@@ -1217,7 +1221,8 @@ void LayoutBlock::RemovePercentHeightDescendant(LayoutBox* descendant) {
TrackedLayoutBoxListHashSet* LayoutBlock::PercentHeightDescendantsInternal()
const {
NOT_DESTROYED();
- return GetPercentHeightDescendantsMap().at(this);
+ auto it = GetPercentHeightDescendantsMap().find(this);
+ return it != GetPercentHeightDescendantsMap().end() ? &*it->value : nullptr;
}
void LayoutBlock::DirtyForLayoutFromPercentageHeightDescendants(
@@ -1295,12 +1300,6 @@ bool LayoutBlock::HitTestChildren(HitTestResult& result,
result, hit_test_location, accumulated_offset, hit_test_action);
}
- // We may use legacy code to hit-test the anonymous fieldset content wrapper
- // child. The layout object for the rendered legend will be a child of that
- // one, and has to be skipped here, since its fragment is actually laid out on
- // the outside and is a sibling of the anonymous wrapper.
- bool may_contain_rendered_legend = IsAnonymousNGFieldsetContentWrapper();
-
PhysicalOffset scrolled_offset = accumulated_offset;
if (IsScrollContainer())
scrolled_offset -= PhysicalOffset(PixelSnappedScrolledContentOffset());
@@ -1309,8 +1308,7 @@ bool LayoutBlock::HitTestChildren(HitTestResult& result,
child_hit_test = kHitTestChildBlockBackground;
for (LayoutBox* child = LastChildBox(); child;
child = child->PreviousSiblingBox()) {
- if (child->HasSelfPaintingLayer() || child->IsColumnSpanAll() ||
- (may_contain_rendered_legend && child->IsRenderedLegend()))
+ if (child->HasSelfPaintingLayer() || child->IsColumnSpanAll())
continue;
PhysicalOffset child_accumulated_offset =
@@ -2312,11 +2310,11 @@ RecalcLayoutOverflowResult LayoutBlock::RecalcChildLayoutOverflow() {
}
void LayoutBlock::RebuildFragmentTreeSpine() {
- DCHECK(PhysicalFragmentCount() && NGBlockNode::CanUseNewLayout(*this));
+ DCHECK(PhysicalFragmentCount());
// If this box has an associated layout-result, rebuild the spine of the
// fragment-tree to ensure consistency.
LayoutBlock* cb = this;
- while (NGBlockNode::CanUseNewLayout(*cb) && !cb->NeedsLayout()) {
+ while (cb->PhysicalFragmentCount() && !cb->NeedsLayout()) {
// Create and set a new identical results.
for (auto& layout_result : cb->layout_results_) {
layout_result =
@@ -2455,9 +2453,13 @@ void LayoutBlock::CheckPositionedObjectsNeedLayout() {
positioned_descendant_set->begin();
it != end; ++it) {
LayoutBox* curr_box = *it;
- DCHECK(!curr_box->SelfNeedsLayout());
+ // An OOF positioned object may still need to be laid out in NG once it
+ // reaches its containing block if it is inside a fragmentation context.
+ // In such cases, we wait to perform layout of the OOF at the
+ // fragmentation context root instead.
+ DCHECK(!curr_box->SelfNeedsLayout() || curr_box->IsInsideFlowThread());
DCHECK(curr_box->ChildLayoutBlockedByDisplayLock() ||
- !curr_box->NeedsLayout());
+ !curr_box->NeedsLayout() || curr_box->IsInsideFlowThread());
}
}
}
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 7303f534eb3..9bf2e1c497c 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
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/editing/editing_behavior.h"
#include "third_party/blink/renderer/core/editing/editor.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
@@ -46,6 +47,7 @@
#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_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/line/glyph_overflow.h"
#include "third_party/blink/renderer/core/layout/line/inline_iterator.h"
@@ -1253,15 +1255,33 @@ void LayoutBlockFlow::AdjustLinePositionForPagination(RootInlineBox& line_box,
return;
if (!IsPageLogicalHeightKnown())
return;
- LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
+ // Ruby annotations do not affect the size of the line box. Instead,
+ // before-annotations are placed above the line's logical top, and
+ // after-annotations are placed below the line's logical bottom. We need to
+ // take this into consideration when block-fragmenting, so that we don't allow
+ // breaking in the middle of an annotation.
+ LayoutUnit logical_offset_with_annotations = logical_offset;
+ LayoutUnit line_height_with_annotations = line_height;
+ if (line_box.HasAnnotationsBefore()) {
+ LayoutUnit adjustment =
+ line_box.ComputeOverAnnotationAdjustment(logical_offset);
+ logical_offset_with_annotations -= adjustment;
+ line_height_with_annotations += adjustment;
+ }
+ if (line_box.HasAnnotationsAfter()) {
+ line_height_with_annotations +=
+ line_box.ComputeUnderAnnotationAdjustment(logical_offset + line_height);
+ }
+ LayoutUnit page_logical_height =
+ PageLogicalHeightForOffset(logical_offset_with_annotations);
LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
- logical_offset, kAssociateWithLatterPage);
+ logical_offset_with_annotations, kAssociateWithLatterPage);
int line_index = LineCount(&line_box);
- if (remaining_logical_height < line_height ||
+ if (remaining_logical_height < line_height_with_annotations ||
(ShouldBreakAtLineToAvoidWidow() &&
LineBreakToAvoidWidow() == line_index)) {
- LayoutUnit pagination_strut =
- CalculatePaginationStrutToFitContent(logical_offset, line_height);
+ LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
+ logical_offset_with_annotations, line_height_with_annotations);
LayoutUnit new_logical_offset = logical_offset + pagination_strut;
// Moving to a different page or column may mean that its height is
// different.
@@ -1482,8 +1502,9 @@ void LayoutBlockFlow::RebuildFloatsFromIntruding() {
for (FloatingObjectSetIterator it = floating_object_set.begin();
it != end; ++it) {
const FloatingObject& floating_object = *it->get();
+ auto it_map = float_map.find(floating_object.GetLayoutObject());
FloatingObject* old_floating_object =
- float_map.at(floating_object.GetLayoutObject());
+ it_map != float_map.end() ? &*it_map->value : nullptr;
LayoutUnit logical_bottom = LogicalBottomForFloat(floating_object);
if (old_floating_object) {
LayoutUnit old_logical_bottom =
@@ -3001,6 +3022,8 @@ void LayoutBlockFlow::AddChild(LayoutObject* new_child,
if (new_child->IsInline() && !new_child->IsLayoutNGOutsideListMarker()) {
// No suitable existing anonymous box - create a new one.
auto* new_block = To<LayoutBlockFlow>(CreateAnonymousBlock());
+ if (new_block->IsLayoutNGObject() && IsLayoutFlowThread())
+ new_block->SetIsAnonymousNGMulticolInlineWrapper();
LayoutBox::AddChild(new_block, before_child);
// Reparent adjacent floating or out-of-flow siblings to the new box.
new_block->ReparentPrecedingFloatingOrOutOfFlowSiblings();
@@ -4280,6 +4303,26 @@ void LayoutBlockFlow::UpdateAncestorShouldPaintFloatingObject(
}
}
+bool LayoutBlockFlow::AllowsColumns() const {
+ // Ruby elements manage child insertion in a special way, and would mess up
+ // insertion of the flow thread. The flow thread needs to be a direct child of
+ // the multicol block (|this|).
+ if (IsRuby())
+ return false;
+
+ // We don't allow custom layout and multicol on the same object. This is
+ // similar to not allowing it for flexbox, grids and tables (although those
+ // don't create LayoutBlockFlow, so we don't need to check for those here).
+ if (StyleRef().IsDisplayLayoutCustomBox())
+ return false;
+
+ // MathML layout objects don't support multicol.
+ if (IsMathML())
+ return false;
+
+ return true;
+}
+
bool LayoutBlockFlow::AllowsPaginationStrut() const {
NOT_DESTROYED();
// The block needs to be contained by a LayoutBlockFlow (and not by e.g. a
@@ -4463,10 +4506,7 @@ void LayoutBlockFlow::CreateOrDestroyMultiColumnFlowThreadIfNeeded(
if (IsListItemIncludingNG())
UseCounter::Count(GetDocument(), WebFeature::kMultiColAndListItem);
- // Ruby elements manage child insertion in a special way, and would mess up
- // insertion of the flow thread. The flow thread needs to be a direct child of
- // the multicol block (|this|).
- if (IsRuby())
+ if (!AllowsColumns())
return;
// Fieldsets look for a legend special child (layoutSpecialExcludedChild()).
@@ -4484,18 +4524,18 @@ void LayoutBlockFlow::CreateOrDestroyMultiColumnFlowThreadIfNeeded(
if (element && element->IsFormControlElement())
return;
- // We don't allow custom layout and multicol on the same object. This is
- // similar to not allowing it for flexbox, grids and tables (although those
- // don't create LayoutBlockFlow, so we don't need to check for those here).
- if (IsLayoutNGCustom())
- return;
-
- // MathML layout objects don't support multicol.
- if (IsMathML())
- return;
+ // Make sure that we don't attempt to create a LayoutNG multicol container
+ // when the feature isn't enabled. There is a mechanism that causes us to fall
+ // back to legacy layout if columns are specified when
+ // LayoutNGBlockFragmentation is disabled, but then there are cases where
+ // we'll override this and force NG anyway (if the layout type isn't
+ // implemented in the legacy engine, which is the case for things like custom
+ // layout).
+ DCHECK(!IsLayoutNGObject() ||
+ RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled());
auto* flow_thread = LayoutMultiColumnFlowThread::CreateAnonymous(
- GetDocument(), StyleRef(), !CanTraversePhysicalFragments());
+ GetDocument(), StyleRef(), !IsLayoutNGObject());
AddChild(flow_thread);
pagination_state_changed_ = true;
if (IsLayoutNGObject()) {
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 0b1b8643599..8c8e0ecba7e 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
@@ -363,6 +363,9 @@ class CORE_EXPORT LayoutBlockFlow : public LayoutBlock {
void ComputeInlinePreferredLogicalWidths(LayoutUnit& min_logical_width,
LayoutUnit& max_logical_width);
+ // Return true if this object is allowed to establish a multicol container.
+ bool AllowsColumns() const;
+
bool AllowsPaginationStrut() const;
// Pagination strut caused by the first line or child block inside this
// block-level object.
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 0fa4693004d..35991f6fa86 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
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/layout/bidi_run_for_line.h"
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h"
@@ -59,7 +60,8 @@ class ExpansionOpportunities {
unsigned opportunities_in_run;
if (text.Is8Bit()) {
opportunities_in_run = Character::ExpansionOpportunityCount(
- {text.Characters8() + run.start_, run.stop_ - run.start_},
+ {text.Characters8() + run.start_,
+ static_cast<size_t>(run.stop_ - run.start_)},
run.box_->Direction(), is_after_expansion, text_justify);
} else if (run.line_layout_item_.IsCombineText()) {
// Justfication applies to before and after the combined text as if
@@ -69,7 +71,8 @@ class ExpansionOpportunities {
is_after_expansion = true;
} else {
opportunities_in_run = Character::ExpansionOpportunityCount(
- {text.Characters16() + run.start_, run.stop_ - run.start_},
+ {text.Characters16() + run.start_,
+ static_cast<size_t>(run.stop_ - run.start_)},
run.box_->Direction(), is_after_expansion, text_justify);
}
runs_with_expansions_.push_back(opportunities_in_run);
@@ -84,8 +87,6 @@ class ExpansionOpportunities {
unsigned Count() { return total_opportunities_; }
- unsigned OpportunitiesInRun(size_t run) { return runs_with_expansions_[run]; }
-
void ComputeExpansionsForJustifiedText(BidiRun* first_run,
BidiRun* trailing_space_run,
LayoutUnit& total_logical_width,
@@ -93,7 +94,7 @@ class ExpansionOpportunities {
if (!total_opportunities_ || available_logical_width <= total_logical_width)
return;
- size_t i = 0;
+ wtf_size_t i = 0;
for (BidiRun* r = first_run; r; r = r->Next()) {
if (!r->box_ || r == trailing_space_run)
continue;
@@ -498,14 +499,14 @@ void LayoutBlockFlow::SetMarginsForRubyRun(BidiRun* run,
SetMarginEndForChild(*layout_ruby_run, LayoutUnit(-end_overhang));
}
-static inline size_t FindWordMeasurement(
+static inline wtf_size_t FindWordMeasurement(
LineLayoutText layout_text,
int offset,
const WordMeasurements& word_measurements,
- size_t last_index) {
+ wtf_size_t last_index) {
// In LTR, lastIndex should match since the order of BidiRun (visual) and
// WordMeasurement (logical) are the same.
- size_t size = word_measurements.size();
+ wtf_size_t size = word_measurements.size();
if (last_index < size) {
const WordMeasurement& word_measurement = word_measurements[last_index];
if (word_measurement.layout_text == layout_text &&
@@ -514,7 +515,7 @@ static inline size_t FindWordMeasurement(
}
// In RTL, scan the whole array because they are not the same.
- for (size_t i = 0; i < size; ++i) {
+ for (wtf_size_t i = 0; i < size; ++i) {
const WordMeasurement& word_measurement = word_measurements[i];
if (word_measurement.layout_text != layout_text)
continue;
@@ -540,7 +541,7 @@ static inline void SetLogicalWidthForTextRun(
GlyphOverflowAndFallbackFontsMap& text_box_data_map,
VerticalPositionCache& vertical_position_cache,
const WordMeasurements& word_measurements,
- size_t& word_measurements_index) {
+ wtf_size_t& word_measurements_index) {
HashSet<const SimpleFontData*> fallback_fonts;
GlyphOverflow glyph_overflow;
@@ -569,9 +570,10 @@ static inline void SetLogicalWidthForTextRun(
if (can_use_cached_word_measurements) {
int last_end_offset = run->start_;
- size_t i = FindWordMeasurement(layout_text, last_end_offset,
- word_measurements, word_measurements_index);
- for (size_t size = word_measurements.size();
+ wtf_size_t i =
+ FindWordMeasurement(layout_text, last_end_offset, word_measurements,
+ word_measurements_index);
+ for (wtf_size_t size = word_measurements.size();
i < size && last_end_offset < run->stop_; ++i) {
const WordMeasurement& word_measurement = word_measurements[i];
if (word_measurement.start_offset == word_measurement.end_offset)
@@ -737,7 +739,8 @@ 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
- return !(IsAnonymousBlock() && PreviousSibling());
+ return !IsAnonymousBlock() || !PreviousSibling() ||
+ IsFlexItemIncludingDeprecatedAndNG() || IsGridItemIncludingNG();
}
static void UpdateLogicalInlinePositions(LayoutBlockFlow* block,
@@ -817,7 +820,7 @@ BidiRun* LayoutBlockFlow::ComputeInlineDirectionPositionsForSegment(
TextJustify text_justify = StyleRef().GetTextJustify();
BidiRun* r = first_run;
- size_t word_measurements_index = 0;
+ wtf_size_t word_measurements_index = 0;
for (; r; r = r->Next()) {
if (!r->box_ || r->line_layout_item_.IsOutOfFlowPositioned() ||
r->box_->IsLineBreak()) {
@@ -1449,11 +1452,11 @@ void LayoutBlockFlow::LinkToEndLineIfNeeded(LineLayoutState& layout_state) {
void LayoutBlockFlow::MarkDirtyFloatsForPaintInvalidation(
Vector<FloatWithRect>& floats) {
NOT_DESTROYED();
- size_t float_count = floats.size();
+ wtf_size_t float_count = floats.size();
// Floats that did not have layout did not paint invalidations when we laid
// them out. They would have painted by now if they had moved, but if they
// stayed at (0, 0), they still need to be painted.
- for (size_t i = 0; i < float_count; ++i) {
+ for (wtf_size_t i = 0; i < float_count; ++i) {
LayoutBox* f = floats[i].object;
if (!floats[i].ever_had_layout) {
if (!f->Location().X() && !f->Location().Y())
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 0bdd34e80ad..bc3358ef288 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
@@ -4,10 +4,11 @@
#include "build/build_config.h"
-#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.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"
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 e090ff10074..ab94970db7f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.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"
@@ -59,6 +60,7 @@
#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
#include "third_party/blink/renderer/core/layout/box_layout_extra_input.h"
+#include "third_party/blink/renderer/core/layout/custom_scrollbar.h"
#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_deprecated_flexible_box.h"
@@ -84,6 +86,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_utils.h"
@@ -99,6 +102,7 @@
#include "third_party/blink/renderer/core/paint/box_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#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/paint/rounded_border_geometry.h"
@@ -158,17 +162,18 @@ LayoutUnit TextFieldIntrinsicInlineSize(const HTMLInputElement& input,
factor = 20;
const float char_width = LayoutTextControl::GetAvgCharWidth(box.StyleRef());
- LayoutUnit result = LayoutUnit::FromFloatCeil(char_width * factor);
+ float float_result = char_width * factor;
float max_char_width = 0.f;
const Font& font = box.StyleRef().GetFont();
if (LayoutTextControl::HasValidAvgCharWidth(font))
- max_char_width = roundf(font.PrimaryFont()->MaxCharWidth());
+ max_char_width = font.PrimaryFont()->MaxCharWidth();
// For text inputs, IE adds some extra width.
if (max_char_width > 0.f)
- result += max_char_width - char_width;
+ float_result += max_char_width - char_width;
+ LayoutUnit result(ceilf(float_result));
if (includes_decoration) {
const auto* spin_button =
To<HTMLElement>(input.UserAgentShadowRoot()->getElementById(
@@ -237,7 +242,7 @@ LayoutUnit FileUploadControlIntrinsicInlineSize(const HTMLInputElement& input,
// characters (using "0" as the nominal character).
constexpr int kDefaultWidthNumChars = 34;
constexpr UChar kCharacter = '0';
- const String character_as_string = String(&kCharacter, 1);
+ const String character_as_string = String(&kCharacter, 1u);
const Font& font = box.StyleRef().GetFont();
const float min_default_label_width =
kDefaultWidthNumChars *
@@ -437,17 +442,13 @@ LayoutBox::~LayoutBox() = default;
PaintLayerType LayoutBox::LayerTypeRequired() const {
NOT_DESTROYED();
if (IsStacked() || HasHiddenBackface() ||
- (StyleRef().SpecifiesColumns() && !CanTraversePhysicalFragments()) ||
+ (StyleRef().SpecifiesColumns() && !IsLayoutNGObject()) ||
IsEffectiveRootScroller())
return kNormalPaintLayer;
if (HasNonVisibleOverflow())
return kOverflowClipPaintLayer;
- if (StyleRef().IsScrollbarGutterForce() &&
- StyleRef().HasPseudoElementStyle(kPseudoIdScrollbar))
- return kNormalPaintLayer;
-
return kNoPaintLayer;
}
@@ -1021,7 +1022,8 @@ LayoutUnit LayoutBox::ScrollWidth() const {
NOT_DESTROYED();
if (IsScrollContainer())
return GetScrollableArea()->ScrollWidth();
- if (StyleRef().IsScrollbarGutterForce()) {
+ if (StyleRef().IsScrollbarGutterStable() &&
+ StyleRef().OverflowBlockDirection() == EOverflow::kHidden) {
if (auto* scrollable_area = GetScrollableArea())
return scrollable_area->ScrollWidth();
else
@@ -1039,7 +1041,8 @@ LayoutUnit LayoutBox::ScrollHeight() const {
NOT_DESTROYED();
if (IsScrollContainer())
return GetScrollableArea()->ScrollHeight();
- if (StyleRef().IsScrollbarGutterForce()) {
+ if (StyleRef().IsScrollbarGutterStable() &&
+ StyleRef().OverflowBlockDirection() == EOverflow::kHidden) {
if (auto* scrollable_area = GetScrollableArea())
return scrollable_area->ScrollHeight();
else
@@ -1188,7 +1191,11 @@ void LayoutBox::UpdateAfterLayout() {
// We also want to make sure that if our entrance point into layout changes,
// e.g. an OOF-positioned object is laid out by an NG containing block, then
// Legacy, then NG again, NG won't use a stale layout result.
- if (IsOutOfFlowPositioned() && !IsLayoutNGObject())
+ if (IsOutOfFlowPositioned() && !IsLayoutNGObject() &&
+ // When side effects are disabled, it's not possible to disable side
+ // effects completely for |RunLegacyLayout|, but at least keep the
+ // fragment tree unaffected.
+ !NGDisableSideEffectsScope::IsDisabled())
ClearLayoutResults();
Document& document = GetDocument();
@@ -1587,28 +1594,24 @@ bool LayoutBox::HasScrollbarGutters(ScrollbarOrientation orientation) const {
if (StyleRef().IsScrollbarGutterAuto())
return false;
- bool is_stable = StyleRef().IsScrollbarGutterStable();
- bool is_always = StyleRef().IsScrollbarGutterAlways();
-
- if (!is_stable && !is_always)
- return false;
+ DCHECK(StyleRef().IsScrollbarGutterStable());
// Scrollbar-gutter propagates to the viewport
// (see:|StyleResolver::PropagateStyleToViewport|).
if (orientation == kVerticalScrollbar) {
EOverflow overflow = StyleRef().OverflowY();
- return (StyleRef().IsScrollbarGutterForce() ||
- overflow == EOverflow::kAuto || overflow == EOverflow::kScroll) &&
- StyleRef().IsHorizontalWritingMode() &&
- GetNode() != GetDocument().ViewportDefiningElement() &&
- !(is_stable && UsesOverlayScrollbars());
+ return StyleRef().IsHorizontalWritingMode() &&
+ (overflow == EOverflow::kAuto || overflow == EOverflow::kScroll ||
+ overflow == EOverflow::kHidden) &&
+ !UsesOverlayScrollbars() &&
+ GetNode() != GetDocument().ViewportDefiningElement();
} else {
EOverflow overflow = StyleRef().OverflowX();
- return (StyleRef().IsScrollbarGutterForce() ||
- overflow == EOverflow::kAuto || overflow == EOverflow::kScroll) &&
- !StyleRef().IsHorizontalWritingMode() &&
- GetNode() != GetDocument().ViewportDefiningElement() &&
- !(is_stable && UsesOverlayScrollbars());
+ return !StyleRef().IsHorizontalWritingMode() &&
+ (overflow == EOverflow::kAuto || overflow == EOverflow::kScroll ||
+ overflow == EOverflow::kHidden) &&
+ !UsesOverlayScrollbars() &&
+ GetNode() != GetDocument().ViewportDefiningElement();
}
}
@@ -1626,11 +1629,11 @@ NGPhysicalBoxStrut LayoutBox::ComputeScrollbarsInternal(
*this, kVerticalScrollbar, /* include_overlay_thickness */ true));
if (ShouldPlaceVerticalScrollbarOnLeft()) {
scrollbars.left = gutter_size;
- if (StyleRef().IsScrollbarGutterBoth())
+ if (StyleRef().IsScrollbarGutterBothEdges())
scrollbars.right = gutter_size;
} else {
scrollbars.right = gutter_size;
- if (StyleRef().IsScrollbarGutterBoth())
+ if (StyleRef().IsScrollbarGutterBothEdges())
scrollbars.left = gutter_size;
}
} else if (scrollable_area) {
@@ -1649,7 +1652,7 @@ NGPhysicalBoxStrut LayoutBox::ComputeScrollbarsInternal(
HypotheticalScrollbarThickness(*this, kHorizontalScrollbar,
/* include_overlay_thickness */ true));
scrollbars.bottom = gutter_size;
- if (StyleRef().IsScrollbarGutterBoth())
+ if (StyleRef().IsScrollbarGutterBothEdges())
scrollbars.top = gutter_size;
} else if (scrollable_area) {
scrollbars.bottom = LayoutUnit(scrollable_area->HorizontalScrollbarHeight(
@@ -1860,18 +1863,19 @@ IntPoint LayoutBox::ScrollOrigin() const {
return GetScrollableArea() ? GetScrollableArea()->ScrollOrigin() : IntPoint();
}
-LayoutSize LayoutBox::ScrolledContentOffset() const {
+PhysicalOffset LayoutBox::ScrolledContentOffset() const {
NOT_DESTROYED();
DCHECK(IsScrollContainer());
DCHECK(GetScrollableArea());
- return LayoutSize(GetScrollableArea()->GetScrollOffset());
+ return PhysicalOffset::FromFloatSizeFloor(
+ GetScrollableArea()->GetScrollOffset());
}
-LayoutSize LayoutBox::PixelSnappedScrolledContentOffset() const {
+IntPoint LayoutBox::PixelSnappedScrolledContentOffset() const {
NOT_DESTROYED();
DCHECK(IsScrollContainer());
DCHECK(GetScrollableArea());
- return LayoutSize(GetScrollableArea()->ScrollOffsetInt());
+ return IntPoint(GetScrollableArea()->ScrollOffsetInt());
}
PhysicalRect LayoutBox::ClippingRect(const PhysicalOffset& location) const {
@@ -1920,7 +1924,13 @@ bool LayoutBox::MapVisualRectToContainer(
VisualRectFlags visual_rect_flags,
TransformState& transform_state) const {
NOT_DESTROYED();
- bool container_preserve_3d = container_object->StyleRef().Preserves3D();
+ // TODO(dbaron): When TransformInteropEnabled is false, this doesn't
+ // really match rendering. It needs to consider
+ // PaintPropertyTreeBuilder::NeedsTransform().
+ bool container_preserve_3d =
+ container_object->StyleRef().Preserves3D() &&
+ (!RuntimeEnabledFeatures::TransformInteropEnabled() ||
+ container_object == NearestAncestorForElement());
TransformState::TransformAccumulation accumulation =
container_preserve_3d ? TransformState::kAccumulateTransform
@@ -1954,6 +1964,11 @@ bool LayoutBox::MapVisualRectToContainer(
// snapping for painted elements within the transform since we don't know
// the desired subpixel accumulation at this point, and the transform may
// include a scale. This only makes sense for non-preserve3D.
+ //
+ // TODO(dbaron): With the TransformInterop feature enabled, does the
+ // flattening here need to be done for the early return case above as well?
+ // (Why is this flattening needed in addition to the flattening done by
+ // using TransformState::kAccumulateTransform?)
if (!StyleRef().Preserves3D()) {
transform_state.Flatten();
transform_state.SetQuad(
@@ -1973,16 +1988,24 @@ bool LayoutBox::MapVisualRectToContainer(
// c) Container scroll offset.
if (container_object->IsBox() && container_object != ancestor &&
To<LayoutBox>(container_object)->ContainedContentsScroll(*this)) {
- LayoutSize offset(
+ PhysicalOffset offset(
-To<LayoutBox>(container_object)->ScrolledContentOffset());
- transform.PostTranslate(offset.Width(), offset.Height());
+ transform.PostTranslate(offset.left, offset.top);
}
bool has_perspective = container_object && container_object->HasLayer() &&
container_object->StyleRef().HasPerspective();
- if (has_perspective && RuntimeEnabledFeatures::TransformInteropEnabled() &&
- container_object != NonAnonymousAncestor())
- has_perspective = false;
+ if (has_perspective && container_object != NearestAncestorForElement()) {
+ if (RuntimeEnabledFeatures::TransformInteropEnabled()) {
+ has_perspective = false;
+ }
+
+ if (StyleRef().Preserves3D() || transform.M13() != 0.0 ||
+ transform.M23() != 0.0 || transform.M43() != 0.0) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kDifferentPerspectiveCBOrParent);
+ }
+ }
// d) Perspective applied by container.
if (has_perspective) {
@@ -1994,7 +2017,7 @@ bool LayoutBox::MapVisualRectToContainer(
TransformationMatrix perspective_matrix;
perspective_matrix.ApplyPerspective(
- container_object->StyleRef().Perspective());
+ container_object->StyleRef().UsedPerspective());
perspective_matrix.ApplyTransformOrigin(perspective_origin.X(),
perspective_origin.Y(), 0);
@@ -2026,7 +2049,7 @@ bool LayoutBox::MapContentsRectToBoxSpace(
return true;
if (ContainedContentsScroll(contents))
- transform_state.Move(PhysicalOffset(-ScrolledContentOffset()));
+ transform_state.Move(-ScrolledContentOffset());
return ApplyBoxClips(transform_state, accumulation, visual_rect_flags);
}
@@ -2389,8 +2412,7 @@ bool LayoutBox::MayIntersect(const HitTestResult& result,
return true;
PhysicalRect overflow_box;
- if (result.GetHitTestRequest().GetType() &
- HitTestRequest::kHitTestVisualOverflow) {
+ if (UNLIKELY(result.GetHitTestRequest().IsHitTestVisualOverflow())) {
overflow_box = PhysicalVisualOverflowRectIncludingFilters();
} else {
overflow_box = PhysicalBorderBoxRect();
@@ -2465,8 +2487,7 @@ bool LayoutBox::NodeAtPoint(HitTestResult& result,
if (should_hit_test_self &&
VisibleToHitTestRequest(result.GetHitTestRequest())) {
PhysicalRect bounds_rect;
- if (result.GetHitTestRequest().GetType() &
- HitTestRequest::kHitTestVisualOverflow) {
+ if (UNLIKELY(result.GetHitTestRequest().IsHitTestVisualOverflow())) {
bounds_rect = PhysicalVisualOverflowRectIncludingFilters();
} else {
bounds_rect = PhysicalBorderBoxRect();
@@ -3281,6 +3302,8 @@ void LayoutBox::AddLayoutResult(scoped_refptr<const NGLayoutResult> result,
void LayoutBox::AddLayoutResult(scoped_refptr<const NGLayoutResult> result) {
const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+ // |layout_results_| is particularly critical when side effects are disabled.
+ DCHECK(!NGDisableSideEffectsScope::IsDisabled());
layout_results_.push_back(std::move(result));
CheckDidAddFragment(*this, fragment);
@@ -3316,6 +3339,8 @@ void LayoutBox::ReplaceLayoutResult(scoped_refptr<const NGLayoutResult> result,
NGFragmentItems::ClearAssociatedFragments(this);
}
}
+ // |layout_results_| is particularly critical when side effects are disabled.
+ DCHECK(!NGDisableSideEffectsScope::IsDisabled());
layout_results_[index] = std::move(result);
CheckDidAddFragment(*this, fragment);
@@ -3361,6 +3386,8 @@ void LayoutBox::ShrinkLayoutResults(wtf_size_t results_to_keep) {
NGFragmentItems::ClearAssociatedFragments(this);
}
}
+ // |layout_results_| is particularly critical when side effects are disabled.
+ DCHECK(!NGDisableSideEffectsScope::IsDisabled());
layout_results_.Shrink(results_to_keep);
}
@@ -3433,17 +3460,6 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
if (early_break)
return nullptr;
- // We'll never re-use the layout result of a fieldset contents wrapper. If the
- // current rendered legend ceased to be one, and any next legend child became
- // the rendered legend instead, we need to lay out the fieldset contents
- // wrapper, to get rid of the fragment for the former regular block child
- // legend (now rendered legend). When this happens, the contents wrapper won't
- // necessarily be marked for layout, since we don't detect that anything in
- // there has changed (and detecting that would be more expensive). So just
- // refuse to hit the cache, so that we force re-layout.
- if (UNLIKELY(IsAnonymous() && Parent() && Parent()->IsLayoutNGFieldset()))
- return nullptr;
-
DCHECK_EQ(cached_layout_result->Status(), NGLayoutResult::kSuccess);
// Set our initial temporary cache status to "hit".
@@ -3533,8 +3549,7 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
cache_status = NGLayoutCacheStatus::kNeedsSimplifiedLayout;
// Only allow simplified layout for non-replaced boxes.
- if (RuntimeEnabledFeatures::LayoutNGReplacedEnabled() &&
- cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout &&
+ if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout &&
IsLayoutReplaced())
return nullptr;
@@ -3685,16 +3700,22 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
end_margin_strut, bfc_line_offset,
bfc_block_offset, block_offset_delta));
- if (needs_cached_result_update)
+ if (needs_cached_result_update && !NGDisableSideEffectsScope::IsDisabled())
SetCachedLayoutResult(new_result);
return new_result;
}
+scoped_refptr<const NGLayoutResult> LayoutBox::GetLayoutResult(
+ wtf_size_t i) const {
+ NOT_DESTROYED();
+ return layout_results_[i];
+}
+
const NGPhysicalBoxFragment* LayoutBox::GetPhysicalFragment(
- wtf_size_t index) const {
+ wtf_size_t i) const {
NOT_DESTROYED();
- return &To<NGPhysicalBoxFragment>(layout_results_[index]->PhysicalFragment());
+ return &To<NGPhysicalBoxFragment>(layout_results_[i]->PhysicalFragment());
}
const NGPhysicalBoxFragment&
@@ -4168,8 +4189,7 @@ bool LayoutBox::ShouldComputeLogicalWidthFromAspectRatio(
if (StyleRef().AspectRatio().IsAuto())
return false;
- if (IsGridItem() &&
- StyleRef().JustifySelf().GetPosition() == ItemPosition::kStretch)
+ if (IsGridItem() && HasStretchedLogicalWidth(StretchingMode::Explicit))
return false;
if (!HasOverrideLogicalHeight() &&
@@ -4273,8 +4293,8 @@ void LayoutBox::ComputeLogicalWidth(
computed_values.extent_ =
ComputeReplacedLogicalWidth() + BorderAndPaddingLogicalWidth();
} else if (StyleRef().LogicalWidth().IsAuto() &&
- (!IsGridItem() || !HasStretchedLogicalWidth() ||
- !HasStretchedLogicalHeight()) &&
+ (!IsGridItem() || !ShouldComputeSizeAsReplaced() ||
+ !HasStretchedLogicalWidth() || !HasStretchedLogicalHeight()) &&
ComputeLogicalWidthFromAspectRatio(&computed_values.extent_)) {
/* we're good */
} else {
@@ -4489,7 +4509,7 @@ bool LayoutBox::IsStretchingColumnFlexItem() const {
// TODO (lajava) Can/Should we move this inside specific layout classes (flex.
// grid)? Can we refactor columnFlexItemHasStretchAlignment logic?
-bool LayoutBox::HasStretchedLogicalWidth() const {
+bool LayoutBox::HasStretchedLogicalWidth(StretchingMode stretchingMode) const {
NOT_DESTROYED();
const ComputedStyle& style = StyleRef();
if (!style.LogicalWidth().IsAuto() || style.MarginStart().IsAuto() ||
@@ -4502,15 +4522,14 @@ bool LayoutBox::HasStretchedLogicalWidth() const {
// Flexbox Items, which obviously should have a container.
return false;
}
+ auto defaultItemPosition = stretchingMode == StretchingMode::Any
+ ? cb->SelfAlignmentNormalBehavior(this)
+ : ItemPosition::kNormal;
if (cb->IsHorizontalWritingMode() != IsHorizontalWritingMode()) {
- return style
- .ResolvedAlignSelf(cb->SelfAlignmentNormalBehavior(this),
- cb->Style())
+ return style.ResolvedAlignSelf(defaultItemPosition, cb->Style())
.GetPosition() == ItemPosition::kStretch;
}
- return style
- .ResolvedJustifySelf(cb->SelfAlignmentNormalBehavior(this),
- cb->Style())
+ return style.ResolvedJustifySelf(defaultItemPosition, cb->Style())
.GetPosition() == ItemPosition::kStretch;
}
@@ -5284,6 +5303,7 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalWidthUsing(
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
+ case Length::kContent:
break;
}
@@ -5519,12 +5539,11 @@ LayoutUnit LayoutBox::AvailableLogicalHeightUsing(
if (const auto* previous_result = GetCachedLayoutResult()) {
const NGConstraintSpace& space =
previous_result->GetConstraintSpaceForCaching();
- if (space.IsFixedBlockSize() && !space.IsFixedBlockSizeIndefinite())
+ if (space.IsFixedBlockSize() && !space.IsInitialBlockSizeIndefinite())
return space.AvailableSize().block_size;
}
}
}
-
if (ShouldComputeLogicalHeightFromAspectRatio()) {
NGBoxStrut border_padding(BorderStart() + ComputedCSSPaddingStart(),
BorderEnd() + ComputedCSSPaddingEnd(),
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 81ffa52cdaa..96fb1044be4 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.h
@@ -1272,6 +1272,7 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
NOT_DESTROYED();
return NGPhysicalFragmentList(layout_results_);
}
+ scoped_refptr<const NGLayoutResult> GetLayoutResult(wtf_size_t i) const;
const NGPhysicalBoxFragment* GetPhysicalFragment(wtf_size_t i) const;
const FragmentData* FragmentDataFromPhysicalFragment(
const NGPhysicalBoxFragment&) const;
@@ -1806,14 +1807,14 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
// See README.md for an explanation of scroll origin.
IntSize OriginAdjustmentForScrollbars() const;
IntPoint ScrollOrigin() const;
- LayoutSize ScrolledContentOffset() const;
+ PhysicalOffset ScrolledContentOffset() const;
// Scroll offset as snapped to physical pixels. This value should be used in
// any values used after layout and inside "layout code" that cares about
// where the content is displayed, rather than what the ideal offset is. For
// most other cases ScrolledContentOffset is probably more appropriate. This
// is the offset that's actually drawn to the screen.
- LayoutSize PixelSnappedScrolledContentOffset() const;
+ IntPoint PixelSnappedScrolledContentOffset() const;
// Maps from scrolling contents space to box space and apply overflow
// clip if needed. Returns true if no clipping applied or the flattened quad
@@ -2130,7 +2131,8 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
bool ColumnFlexItemHasStretchAlignment() const;
bool IsStretchingColumnFlexItem() const;
- bool HasStretchedLogicalWidth() const;
+ enum class StretchingMode { Any, Explicit };
+ bool HasStretchedLogicalWidth(StretchingMode = StretchingMode::Any) const;
bool HasStretchedLogicalHeight() const;
void ExcludeScrollbars(
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 6562226a31a..f20eab8a580 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
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
@@ -102,8 +103,15 @@ LayoutBoxModelObject::LayoutBoxModelObject(ContainerNode* node)
bool LayoutBoxModelObject::UsesCompositedScrolling() const {
NOT_DESTROYED();
- return IsScrollContainer() && HasLayer() &&
- Layer()->GetScrollableArea()->UsesCompositedScrolling();
+
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ return IsScrollContainer() && HasLayer() &&
+ Layer()->GetScrollableArea()->UsesCompositedScrolling();
+ }
+
+ const auto* properties = FirstFragment().PaintProperties();
+ return properties && properties->ScrollTranslation() &&
+ properties->ScrollTranslation()->HasDirectCompositingReasons();
}
static bool HasInsetBoxShadow(const ComputedStyle& style) {
@@ -785,7 +793,7 @@ bool LayoutBoxModelObject::HasAutoHeightOrContainingBlockWithAutoHeight(
// BoxLayoutExtraInput that we could add a flag to.
const NGConstraintSpace& space =
this_box->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- if (space.IsFixedBlockSize() && !space.IsFixedBlockSizeIndefinite())
+ if (space.IsFixedBlockSize() && !space.IsInitialBlockSizeIndefinite())
return false;
}
}
@@ -1314,7 +1322,8 @@ LayoutUnit LayoutBoxModelObject::ContainingBlockLogicalWidthForContent() const {
LayoutBoxModelObject* LayoutBoxModelObject::Continuation() const {
NOT_DESTROYED();
- return GetContinuationMap().at(this);
+ auto it = GetContinuationMap().find(this);
+ return it != GetContinuationMap().end() ? it->value : nullptr;
}
void LayoutBoxModelObject::SetContinuation(LayoutBoxModelObject* continuation) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_box_test.cc
index 8690524d8f0..92baef863e8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box_test.cc
@@ -1433,7 +1433,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsNonScrollable) {
#define EXPECT_ZERO_SCROLL(box) \
do { \
- EXPECT_EQ(LayoutSize(), box->ScrolledContentOffset()); \
+ EXPECT_EQ(PhysicalOffset(), box->ScrolledContentOffset()); \
const auto* scrollable_area = box->GetScrollableArea(); \
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt()); \
EXPECT_EQ(IntPoint(), scrollable_area->ScrollOrigin()); \
@@ -1538,7 +1538,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsScrollable) {
const auto* normal = GetLayoutBoxByElementId("normal");
const auto* scrollable_area = normal->GetScrollableArea();
- EXPECT_EQ(LayoutSize(), normal->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), normal->ScrolledContentOffset());
EXPECT_EQ(IntSize(), normal->OriginAdjustmentForScrollbars());
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt());
// 50 = border_left, 20 = border_top
@@ -1560,7 +1560,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsScrollable) {
const auto* vlr = GetLayoutBoxByElementId("vlr");
scrollable_area = vlr->GetScrollableArea();
- EXPECT_EQ(LayoutSize(), vlr->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), vlr->ScrolledContentOffset());
EXPECT_EQ(IntSize(), vlr->OriginAdjustmentForScrollbars());
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt());
// 2060 = child_width + padding_left + padding_right
@@ -1581,7 +1581,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsScrollable) {
const auto* vrl = GetLayoutBoxByElementId("vrl");
scrollable_area = vrl->GetScrollableArea();
- EXPECT_EQ(LayoutSize(), vrl->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), vrl->ScrolledContentOffset());
EXPECT_EQ(IntSize(), vrl->OriginAdjustmentForScrollbars());
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt());
// Same as "vlr" except for flipping.
@@ -1598,7 +1598,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsScrollable) {
const auto* rtl = GetLayoutBoxByElementId("rtl");
scrollable_area = rtl->GetScrollableArea();
- EXPECT_EQ(LayoutSize(), rtl->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), rtl->ScrolledContentOffset());
EXPECT_EQ(IntSize(15, 0), rtl->OriginAdjustmentForScrollbars());
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt());
// The contents overflow to the left.
@@ -1618,7 +1618,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsScrollable) {
const auto* rtl_vlr = GetLayoutBoxByElementId("rtl-vlr");
scrollable_area = rtl_vlr->GetScrollableArea();
- EXPECT_EQ(LayoutSize(), rtl_vlr->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), rtl_vlr->ScrolledContentOffset());
EXPECT_EQ(IntSize(), rtl_vlr->OriginAdjustmentForScrollbars());
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt());
// 2060 = child_width + padding_left + padding_right
@@ -1637,7 +1637,7 @@ TEST_P(LayoutBoxTest, GeometriesWithScrollbarsScrollable) {
const auto* rtl_vrl = GetLayoutBoxByElementId("rtl-vrl");
scrollable_area = rtl_vrl->GetScrollableArea();
- EXPECT_EQ(LayoutSize(), rtl_vrl->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), rtl_vrl->ScrolledContentOffset());
EXPECT_EQ(IntSize(), rtl_vrl->OriginAdjustmentForScrollbars());
EXPECT_EQ(IntSize(), scrollable_area->ScrollOffsetInt());
// Same as "vlr" except for flipping.
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 a51d17f5c81..bbbe7b3504b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -26,8 +26,10 @@
#include "base/memory/ptr_util.h"
#include "base/numerics/clamped_math.h"
#include "third_party/blink/renderer/core/css/counter_style.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.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/pseudo_element.h"
#include "third_party/blink/renderer/core/html/html_olist_element.h"
@@ -35,7 +37,6 @@
#include "third_party/blink/renderer/core/layout/counter_node.h"
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -391,9 +392,11 @@ CounterNode* MakeCounterNodeIfNeeded(LayoutObject& object,
const AtomicString& identifier,
bool always_create_counter) {
if (object.HasCounterNodeMap()) {
- if (CounterMap* node_map = GetCounterMaps().at(&object)) {
- if (CounterNode* node = node_map->at(identifier))
- return node;
+ auto it_counter = GetCounterMaps().find(&object);
+ if (it_counter != GetCounterMaps().end()) {
+ auto it_node = it_counter->value->find(identifier);
+ if (it_node != it_counter->value->end())
+ return &*it_node->value;
}
}
@@ -464,8 +467,10 @@ CounterNode* MakeCounterNodeIfNeeded(LayoutObject& object,
skip_descendants = current_layout_object->ShouldApplyStyleContainment();
if (!current_layout_object->HasCounterNodeMap())
continue;
+ auto* current_object = maps.at(current_layout_object);
+ auto it = current_object->find(identifier);
CounterNode* current_counter =
- maps.at(current_layout_object)->at(identifier);
+ it != current_object->end() ? &*it->value : nullptr;
if (!current_counter)
continue;
// At this point we found a counter to reparent. So we don't need to descend
@@ -483,14 +488,10 @@ CounterNode* MakeCounterNodeIfNeeded(LayoutObject& object,
}
String GenerateCounterText(const CounterStyle* counter_style,
- EListStyleType deprecated_list_style_type,
int value) {
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- if (!counter_style)
- return g_empty_string;
- return counter_style->GenerateRepresentation(value);
- }
- return list_marker_text::GetText(deprecated_list_style_type, value);
+ if (!counter_style)
+ return g_empty_string;
+ return counter_style->GenerateRepresentation(value);
}
} // namespace
@@ -598,20 +599,15 @@ scoped_refptr<StringImpl> LayoutCounter::OriginalText() const {
int value = ValueForText(child);
const CounterStyle* counter_style = nullptr;
- EListStyleType list_style = EListStyleType::kNone;
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- // Note: CSS3 spec doesn't allow 'none' but CSS2.1 allows it. We currently
- // allow it for backward compatibility.
- // See https://github.com/w3c/csswg-drafts/issues/5795 for details.
- if (counter_->ListStyle() != "none") {
- counter_style =
- &GetDocument().GetStyleEngine().FindCounterStyleAcrossScopes(
- counter_->ListStyle(), counter_->GetTreeScope());
- }
- } else {
- list_style = counter_->ToDeprecatedListStyleTypeEnum();
+ // Note: CSS3 spec doesn't allow 'none' but CSS2.1 allows it. We currently
+ // allow it for backward compatibility.
+ // See https://github.com/w3c/csswg-drafts/issues/5795 for details.
+ if (counter_->ListStyle() != "none") {
+ counter_style =
+ &GetDocument().GetStyleEngine().FindCounterStyleAcrossScopes(
+ counter_->ListStyle(), counter_->GetTreeScope());
}
- String text = GenerateCounterText(counter_style, list_style, value);
+ String text = GenerateCounterText(counter_style, value);
// If the separator exists, we need to append all of the parent values as well,
// including the ones that cross the style containment boundary.
if (!counter_->Separator().IsNull()) {
@@ -622,7 +618,7 @@ scoped_refptr<StringImpl> LayoutCounter::OriginalText() const {
child->ParentCrossingStyleContainment(counter_->Identifier())) {
int next_value = next_result_uses_parent_value ? ValueForText(parent)
: child->CountInParent();
- text = GenerateCounterText(counter_style, list_style, next_value) +
+ text = GenerateCounterText(counter_style, next_value) +
counter_->Separator() + text;
child = parent;
next_result_uses_parent_value = !child->Parent();
@@ -679,7 +675,8 @@ void LayoutCounter::DestroyCounterNodes(LayoutObject& owner) {
void LayoutCounter::DestroyCounterNode(LayoutObject& owner,
const AtomicString& identifier) {
- CounterMap* map = GetCounterMaps().at(&owner);
+ auto it = GetCounterMaps().find(&owner);
+ CounterMap* map = it != GetCounterMaps().end() ? &*it->value : nullptr;
if (!map)
return;
CounterMap::iterator map_iterator = map->find(identifier);
@@ -732,11 +729,15 @@ static void UpdateCounters(LayoutObject& layout_object) {
MakeCounterNodeIfNeeded(layout_object, it->key, false);
return;
}
- CounterMap* counter_map = GetCounterMaps().at(&layout_object);
+ auto it_counter = GetCounterMaps().find(&layout_object);
+ CounterMap* counter_map =
+ it_counter != GetCounterMaps().end() ? &*it_counter->value : nullptr;
DCHECK(counter_map);
for (CounterDirectiveMap::const_iterator it = directive_map->begin();
it != end; ++it) {
- scoped_refptr<CounterNode> node = counter_map->at(it->key);
+ auto it_node = counter_map->find(it->key);
+ scoped_refptr<CounterNode> node =
+ it_node != counter_map->end() ? it_node->value : nullptr;
if (!node) {
MakeCounterNodeIfNeeded(layout_object, it->key, false);
continue;
@@ -746,7 +747,8 @@ static void UpdateCounters(LayoutObject& layout_object) {
FindPlaceForCounter(layout_object, it->key, node->HasResetType(),
new_parent, new_previous_sibling);
- if (node != counter_map->at(it->key))
+ auto it_node2 = counter_map->find(it->key);
+ if (it_node2 == counter_map->end() || (node != it_node2->value))
continue;
CounterNode* parent = node->Parent();
if (new_parent == parent && new_previous_sibling == node->PreviousSibling())
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_counter.h b/chromium/third_party/blink/renderer/core/layout/layout_counter.h
index 0d8b79ceeeb..cdee61fcf3e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_counter.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_counter.h
@@ -51,7 +51,7 @@ using CounterMap = HashMap<AtomicString, scoped_refptr<CounterNode>>;
//
// Keeping the map up to date is the reason why LayoutObjects need to call into
// LayoutCounter during their lifetime (see the static functions below).
-class LayoutCounter final : public LayoutText {
+class LayoutCounter : public LayoutText {
public:
LayoutCounter(PseudoElement&, const CounterContentData&);
~LayoutCounter() override;
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 0ea14964b01..cc5499514f6 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
@@ -27,6 +27,7 @@
#include <algorithm>
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/layout/text_run_constructor.h"
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 cb2f706966c..0a84363b7fb 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
@@ -417,8 +417,7 @@ void LayoutEmbeddedContent::UpdateGeometry(
// which is a float-type but frame_rect in a content view is an IntRect. We
// may want to reevaluate the use of pixel snapping that since scroll
// offsets/layout can be fractional.
- frame_rect.Move(
- FlooredIntSize(layout_view->PixelSnappedScrolledContentOffset()));
+ frame_rect.MoveBy(layout_view->PixelSnappedScrolledContentOffset());
}
embedded_content_view.SetFrameRect(frame_rect);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
index f7ec645c662..ff2a48b56fa 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -143,19 +143,7 @@ LayoutObject* LayoutFieldset::LayoutSpecialExcludedChild(bool relayout_children,
LayoutBox* LayoutFieldset::FindInFlowLegend(const LayoutBlock& fieldset) {
DCHECK(fieldset.IsFieldset() || fieldset.IsLayoutNGFieldset());
- const LayoutBlock* parent = &fieldset;
- if (fieldset.IsLayoutNGFieldset()) {
- // If there is a rendered legend, it will be found inside the anonymous
- // fieldset wrapper.
- parent = To<LayoutBlock>(fieldset.FirstChild());
- if (!parent)
- return nullptr;
- // If the anonymous fieldset wrapper is a multi-column, the rendered
- // legend will be found inside the multi-column flow thread.
- if (parent->FirstChild() && parent->FirstChild()->IsLayoutFlowThread())
- parent = To<LayoutBlock>(parent->FirstChild());
- }
- for (LayoutObject* legend = parent->FirstChild(); legend;
+ for (LayoutObject* legend = fieldset.FirstChild(); legend;
legend = legend->NextSibling()) {
if (legend->IsRenderedLegendCandidate())
return To<LayoutBox>(legend);
@@ -163,33 +151,6 @@ LayoutBox* LayoutFieldset::FindInFlowLegend(const LayoutBlock& fieldset) {
return nullptr;
}
-LayoutBlock* LayoutFieldset::FindLegendContainingBlock(
- const LayoutBox& legend,
- AncestorSkipInfo* skip_info) {
- DCHECK(legend.IsRenderedLegend());
- LayoutObject* parent = legend.Parent();
- if (!parent->IsAnonymous())
- return To<LayoutBlock>(parent);
-
- if (skip_info)
- skip_info->Update(*parent);
-
- // In LayoutNG all children of a fieldset are wrapped inside an anonymous
- // block. This also includes the rendered legend, even if that one really
- // belongs on the outside as a direct fieldset child. Skip the anonymous
- // wrapper in such cases.
- if (parent->IsLayoutFlowThread()) {
- // If the fieldset also establishes a multicol container, we need to skip
- // the flow thread as well.
- parent = parent->Parent();
- if (skip_info)
- skip_info->Update(*parent);
- DCHECK(parent->IsAnonymous());
- }
- DCHECK(parent->Parent()->IsLayoutNGFieldset());
- return To<LayoutBlock>(parent->Parent());
-}
-
void LayoutFieldset::PaintBoxDecorationBackground(
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const {
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 c79f846e4c7..b257882c986 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.h
@@ -38,9 +38,6 @@ class LayoutFieldset final : public LayoutBlockFlow {
return FindInFlowLegend(*this);
}
- static LayoutBlock* FindLegendContainingBlock(const LayoutBox& legend,
- AncestorSkipInfo* = nullptr);
-
const char* GetName() const override {
NOT_DESTROYED();
return "LayoutFieldset";
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 6d5cef981aa..e7ddce3a609 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
@@ -860,7 +860,9 @@ bool LayoutFlexibleBox::MainAxisLengthIsDefinite(const LayoutBox& child,
const Length& flex_basis,
bool add_to_cb) const {
NOT_DESTROYED();
- if (flex_basis.IsAuto())
+ // 'content' isn't actually supported in legacy flex. Checking IsContent() and
+ // returning false on the next line prevents a DCHECK though.
+ if (flex_basis.IsAuto() || flex_basis.IsContent())
return false;
if (IsColumnFlow() && flex_basis.IsContentOrIntrinsicOrFillAvailable())
return false;
@@ -960,7 +962,7 @@ bool LayoutFlexibleBox::CanAvoidLayoutForNGChild(const LayoutBox& child) const {
return false;
if (old_space.IsFixedBlockSize() != child.HasOverrideLogicalHeight())
return false;
- if (!old_space.IsFixedBlockSizeIndefinite() !=
+ if (!old_space.IsInitialBlockSizeIndefinite() !=
UseOverrideLogicalHeightForPerentageResolution(child))
return false;
if (child.HasOverrideLogicalWidth() &&
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc
index f00b19df5a8..1f6b0d367c9 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc
@@ -76,7 +76,7 @@ static void CheckFlexBoxPhysicalGeometries(const LayoutBox* flex_box) {
flex_box->PhysicalContentBoxRect());
}
- EXPECT_EQ(LayoutSize(), flex_box->ScrolledContentOffset());
+ EXPECT_EQ(PhysicalOffset(), flex_box->ScrolledContentOffset());
EXPECT_EQ(ScrollOffset(), flex_box->GetScrollableArea()->GetScrollOffset());
}
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 d26607e7b67..fd4a04cd62a 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
@@ -332,10 +332,10 @@ void LayoutFrameSet::ComputeEdgeInfo() {
if (!child)
return;
- size_t rows = rows_.sizes_.size();
- size_t cols = cols_.sizes_.size();
- for (size_t r = 0; r < rows; ++r) {
- for (size_t c = 0; c < cols; ++c) {
+ wtf_size_t rows = rows_.sizes_.size();
+ wtf_size_t cols = cols_.sizes_.size();
+ for (wtf_size_t r = 0; r < rows; ++r) {
+ for (wtf_size_t c = 0; c < cols; ++c) {
FrameEdgeInfo edge_info;
if (child->IsFrameSet())
edge_info = To<LayoutFrameSet>(child)->EdgeInfo();
@@ -569,15 +569,15 @@ int LayoutFrameSet::HitTestSplit(const GridAxis& axis, int position) const {
if (border_thickness <= 0)
return kNoSplit;
- size_t size = axis.sizes_.size();
+ wtf_size_t size = axis.sizes_.size();
if (!size)
return kNoSplit;
int split_position = axis.sizes_[0];
- for (size_t i = 1; i < size; ++i) {
+ for (wtf_size_t i = 1; i < size; ++i) {
if (position >= split_position &&
position < split_position + border_thickness)
- return i;
+ return static_cast<int>(i);
split_position += border_thickness + axis.sizes_[i];
}
return kNoSplit;
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 33b2277e56f..888f29c392c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -453,8 +453,8 @@ LayoutUnit LayoutGrid::GridGap(GridTrackSizingDirection direction) const {
LayoutUnit LayoutGrid::GuttersSize(
const Grid& grid,
GridTrackSizingDirection direction,
- size_t start_line,
- size_t span,
+ wtf_size_t start_line,
+ wtf_size_t span,
absl::optional<LayoutUnit> available_size) const {
NOT_DESTROYED();
if (span <= 1)
@@ -473,9 +473,9 @@ LayoutUnit LayoutGrid::GuttersSize(
// becomes 0) or there is a non empty track before that.
LayoutUnit gap_accumulator;
- size_t end_line = start_line + span;
+ wtf_size_t end_line = start_line + span;
- for (size_t line = start_line; line < end_line - 1; ++line) {
+ for (wtf_size_t line = start_line; line < end_line - 1; ++line) {
if (!grid.IsEmptyAutoRepeatTrack(direction, line))
gap_accumulator += gap;
}
@@ -562,7 +562,7 @@ MinMaxSizes LayoutGrid::ComputeIntrinsicLogicalWidths() const {
ComputeTrackSizesForIndefiniteSize(algorithm, kForColumns);
- size_t number_of_tracks = algorithm.Tracks(kForColumns).size();
+ wtf_size_t number_of_tracks = algorithm.Tracks(kForColumns).size();
LayoutUnit total_gutters_size = GuttersSize(
algorithm.GetGrid(), kForColumns, 0, number_of_tracks, absl::nullopt);
@@ -610,7 +610,7 @@ static absl::optional<LayoutUnit> ConvertLayoutUnitToOptional(LayoutUnit size) {
return size;
}
-size_t LayoutGrid::ComputeAutoRepeatTracksCount(
+wtf_size_t LayoutGrid::ComputeAutoRepeatTracksCount(
GridTrackSizingDirection direction,
absl::optional<LayoutUnit> available_size) const {
NOT_DESTROYED();
@@ -628,7 +628,7 @@ size_t LayoutGrid::ComputeAutoRepeatTracksCount(
const auto& auto_repeat_tracks = is_row_axis
? StyleRef().GridAutoRepeatColumns()
: StyleRef().GridAutoRepeatRows();
- size_t auto_repeat_track_list_length = auto_repeat_tracks.size();
+ wtf_size_t auto_repeat_track_list_length = auto_repeat_tracks.size();
if (!auto_repeat_track_list_length)
return 0;
@@ -728,7 +728,7 @@ size_t LayoutGrid::ComputeAutoRepeatTracksCount(
// There will be always at least 1 auto-repeat track, so take it already into
// account when computing the total track size.
LayoutUnit tracks_size = auto_repeat_tracks_size;
- const Vector<GridTrackSize>& track_sizes =
+ const Vector<GridTrackSize, 1>& track_sizes =
is_row_axis ? StyleRef().GridTemplateColumns().LegacyTrackList()
: StyleRef().GridTemplateRows().LegacyTrackList();
@@ -758,7 +758,7 @@ size_t LayoutGrid::ComputeAutoRepeatTracksCount(
LayoutUnit auto_repeat_size_with_gap =
auto_repeat_tracks_size + gap_size * auto_repeat_track_list_length;
- size_t repetitions = 1 + (free_space / auto_repeat_size_with_gap).ToInt();
+ int repetitions = 1 + (free_space / auto_repeat_size_with_gap).ToInt();
free_space -= auto_repeat_size_with_gap * (repetitions - 1);
// Provided the grid container does not have a definite size or max-size in
@@ -786,21 +786,21 @@ LayoutGrid::ComputeEmptyTracksForAutoRepeat(
return nullptr;
std::unique_ptr<OrderedTrackIndexSet> empty_track_indexes;
- size_t insertion_point =
+ wtf_size_t insertion_point =
is_row_axis ? StyleRef().GridAutoRepeatColumnsInsertionPoint()
: StyleRef().GridAutoRepeatRowsInsertionPoint();
- size_t first_auto_repeat_track =
+ wtf_size_t first_auto_repeat_track =
insertion_point + grid.ExplicitGridStart(direction);
- size_t last_auto_repeat_track =
+ wtf_size_t last_auto_repeat_track =
first_auto_repeat_track + grid.AutoRepeatTracks(direction);
if (!grid.HasGridItems()) {
empty_track_indexes = std::make_unique<OrderedTrackIndexSet>();
- for (size_t track_index = first_auto_repeat_track;
+ for (wtf_size_t track_index = first_auto_repeat_track;
track_index < last_auto_repeat_track; ++track_index)
empty_track_indexes->insert(track_index);
} else {
- for (size_t track_index = first_auto_repeat_track;
+ for (wtf_size_t track_index = first_auto_repeat_track;
track_index < last_auto_repeat_track; ++track_index) {
auto iterator = grid.CreateIterator(direction, track_index);
if (!iterator->NextGridItem()) {
@@ -813,25 +813,26 @@ LayoutGrid::ComputeEmptyTracksForAutoRepeat(
return empty_track_indexes;
}
-size_t LayoutGrid::ClampAutoRepeatTracks(GridTrackSizingDirection direction,
- size_t auto_repeat_tracks) const {
+wtf_size_t LayoutGrid::ClampAutoRepeatTracks(
+ GridTrackSizingDirection direction,
+ wtf_size_t auto_repeat_tracks) const {
NOT_DESTROYED();
if (!auto_repeat_tracks)
return 0;
- size_t insertion_point =
+ wtf_size_t insertion_point =
direction == kForColumns
? StyleRef().GridAutoRepeatColumnsInsertionPoint()
: StyleRef().GridAutoRepeatRowsInsertionPoint();
if (insertion_point == 0)
- return std::min<size_t>(auto_repeat_tracks, kGridMaxTracks);
+ return std::min<wtf_size_t>(auto_repeat_tracks, kGridMaxTracks);
if (insertion_point >= kGridMaxTracks)
return 0;
return std::min(auto_repeat_tracks,
- static_cast<size_t>(kGridMaxTracks) - insertion_point);
+ static_cast<wtf_size_t>(kGridMaxTracks) - insertion_point);
}
// TODO(svillar): we shouldn't have to pass the available logical width as
@@ -844,10 +845,10 @@ void LayoutGrid::PlaceItemsOnGrid(
absl::optional<LayoutUnit> available_logical_width) const {
NOT_DESTROYED();
Grid& grid = algorithm.GetMutableGrid();
- size_t auto_repeat_rows = ComputeAutoRepeatTracksCount(
+ wtf_size_t auto_repeat_rows = ComputeAutoRepeatTracksCount(
kForRows, ConvertLayoutUnitToOptional(
AvailableLogicalHeightForPercentageComputation()));
- size_t auto_repeat_columns =
+ wtf_size_t auto_repeat_columns =
ComputeAutoRepeatTracksCount(kForColumns, available_logical_width);
auto_repeat_rows = ClampAutoRepeatTracks(kForRows, auto_repeat_rows);
@@ -870,7 +871,7 @@ void LayoutGrid::PlaceItemsOnGrid(
#if DCHECK_IS_ON()
DCHECK(!grid.HasAnyGridItemPaintOrder());
#endif
- size_t child_index = 0;
+ wtf_size_t child_index = 0;
for (LayoutBox* child = grid.GetOrderIterator().First(); child;
child = grid.GetOrderIterator().Next()) {
if (child->IsOutOfFlowPositioned())
@@ -994,15 +995,16 @@ void LayoutGrid::PerformGridItemsPreLayout(
void LayoutGrid::PopulateExplicitGridAndOrderIterator(Grid& grid) const {
NOT_DESTROYED();
OrderIteratorPopulator populator(grid.GetOrderIterator());
- size_t explicit_row_start = 0;
- size_t explicit_column_start = 0;
+ wtf_size_t explicit_row_start = 0;
+ wtf_size_t explicit_column_start = 0;
- size_t auto_repeat_rows = grid.AutoRepeatTracks(kForRows);
- size_t auto_repeat_columns = grid.AutoRepeatTracks(kForColumns);
- size_t maximum_row_index =
+ wtf_size_t auto_repeat_rows = grid.AutoRepeatTracks(kForRows);
+ wtf_size_t auto_repeat_columns = grid.AutoRepeatTracks(kForColumns);
+ wtf_size_t maximum_row_index =
GridPositionsResolver::ExplicitGridRowCount(StyleRef(), auto_repeat_rows);
- size_t maximum_column_index = GridPositionsResolver::ExplicitGridColumnCount(
- StyleRef(), auto_repeat_columns);
+ wtf_size_t maximum_column_index =
+ GridPositionsResolver::ExplicitGridColumnCount(StyleRef(),
+ auto_repeat_columns);
for (LayoutBox* child = FirstInFlowChildBox(); child;
child = child->NextInFlowSiblingBox()) {
@@ -1027,7 +1029,7 @@ void LayoutGrid::PopulateExplicitGridAndOrderIterator(Grid& grid) const {
} else {
// Grow the grid for items with a definite row span, getting the largest
// such span.
- size_t span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
+ wtf_size_t span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
child->StyleRef(), kForRows);
maximum_row_index = std::max(maximum_row_index, span_size);
}
@@ -1040,7 +1042,7 @@ void LayoutGrid::PopulateExplicitGridAndOrderIterator(Grid& grid) const {
} else {
// Grow the grid for items with a definite column span, getting the
// largest such span.
- size_t span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
+ wtf_size_t span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
child->StyleRef(), kForColumns);
maximum_column_index = std::max(maximum_column_index, span_size);
}
@@ -1060,8 +1062,8 @@ LayoutGrid::CreateEmptyGridAreaAtSpecifiedPositionsOutsideGrid(
NOT_DESTROYED();
GridTrackSizingDirection cross_direction =
specified_direction == kForColumns ? kForRows : kForColumns;
- const size_t end_of_cross_direction = grid.NumTracks(cross_direction);
- size_t cross_direction_span_size =
+ const wtf_size_t end_of_cross_direction = grid.NumTracks(cross_direction);
+ wtf_size_t cross_direction_span_size =
GridPositionsResolver::SpanSizeForAutoPlacedItem(grid_item.StyleRef(),
cross_direction);
GridSpan cross_direction_positions = GridSpan::TranslatedDefiniteGridSpan(
@@ -1096,16 +1098,19 @@ void LayoutGrid::PlaceSpecifiedMajorAxisItemsOnGrid(
DCHECK(
!grid.GridItemSpan(*auto_grid_item, AutoPlacementMinorAxisDirection())
.IsTranslatedDefinite());
- size_t minor_axis_span_size =
+ wtf_size_t minor_axis_span_size =
GridPositionsResolver::SpanSizeForAutoPlacedItem(
auto_grid_item->StyleRef(), AutoPlacementMinorAxisDirection());
unsigned major_axis_initial_position = 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));
+ auto minor_access_cursor = 0;
+ if (!is_grid_auto_flow_dense) {
+ auto it = minor_axis_cursors.find(major_axis_initial_position);
+ if (it != minor_axis_cursors.end())
+ minor_access_cursor = it->value;
+ }
+ auto iterator = grid.CreateIterator(AutoPlacementMajorAxisDirection(),
+ major_axis_positions.StartLine(),
+ minor_access_cursor);
std::unique_ptr<GridArea> empty_grid_area = iterator->NextEmptyGridArea(
major_axis_positions.IntegerSpan(), minor_axis_span_size);
DCHECK(empty_grid_area);
@@ -1124,7 +1129,8 @@ void LayoutGrid::PlaceAutoMajorAxisItemsOnGrid(
Grid& grid,
const Vector<LayoutBox*>& auto_grid_items) const {
NOT_DESTROYED();
- std::pair<size_t, size_t> auto_placement_cursor = std::make_pair(0, 0);
+ std::pair<wtf_size_t, wtf_size_t> auto_placement_cursor =
+ std::make_pair(0, 0);
bool is_grid_auto_flow_dense = StyleRef().IsGridAutoFlowAlgorithmDense();
for (auto* const auto_grid_item : auto_grid_items) {
@@ -1141,23 +1147,23 @@ void LayoutGrid::PlaceAutoMajorAxisItemsOnGrid(
void LayoutGrid::PlaceAutoMajorAxisItemOnGrid(
Grid& grid,
LayoutBox& grid_item,
- std::pair<size_t, size_t>& auto_placement_cursor) const {
+ std::pair<wtf_size_t, wtf_size_t>& auto_placement_cursor) const {
NOT_DESTROYED();
GridSpan minor_axis_positions =
grid.GridItemSpan(grid_item, AutoPlacementMinorAxisDirection());
DCHECK(!grid.GridItemSpan(grid_item, AutoPlacementMajorAxisDirection())
.IsTranslatedDefinite());
- size_t major_axis_span_size =
+ wtf_size_t major_axis_span_size =
GridPositionsResolver::SpanSizeForAutoPlacedItem(
grid_item.StyleRef(), AutoPlacementMajorAxisDirection());
- const size_t end_of_major_axis =
+ const wtf_size_t end_of_major_axis =
grid.NumTracks(AutoPlacementMajorAxisDirection());
- size_t major_axis_auto_placement_cursor =
+ wtf_size_t major_axis_auto_placement_cursor =
AutoPlacementMajorAxisDirection() == kForColumns
? auto_placement_cursor.second
: auto_placement_cursor.first;
- size_t minor_axis_auto_placement_cursor =
+ wtf_size_t minor_axis_auto_placement_cursor =
AutoPlacementMajorAxisDirection() == kForColumns
? auto_placement_cursor.first
: auto_placement_cursor.second;
@@ -1183,11 +1189,11 @@ void LayoutGrid::PlaceAutoMajorAxisItemOnGrid(
minor_axis_positions);
}
} else {
- size_t minor_axis_span_size =
+ wtf_size_t minor_axis_span_size =
GridPositionsResolver::SpanSizeForAutoPlacedItem(
grid_item.StyleRef(), AutoPlacementMinorAxisDirection());
- for (size_t major_axis_index = major_axis_auto_placement_cursor;
+ for (wtf_size_t major_axis_index = major_axis_auto_placement_cursor;
major_axis_index < end_of_major_axis; ++major_axis_index) {
auto iterator = grid.CreateIterator(AutoPlacementMajorAxisDirection(),
major_axis_index,
@@ -1203,7 +1209,7 @@ void LayoutGrid::PlaceAutoMajorAxisItemOnGrid(
AutoPlacementMinorAxisDirection() == kForColumns
? empty_grid_area->columns.EndLine()
: empty_grid_area->rows.EndLine();
- const size_t end_of_minor_axis =
+ const wtf_size_t end_of_minor_axis =
grid.NumTracks(AutoPlacementMinorAxisDirection());
if (minor_axis_final_position_index <= end_of_minor_axis)
break;
@@ -1248,17 +1254,17 @@ void LayoutGrid::DirtyGrid() {
grid_->SetNeedsItemsPlacement(true);
}
-Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle(
+Vector<LayoutUnit, 1> LayoutGrid::TrackSizesForComputedStyle(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
bool is_row_axis = direction == kForColumns;
auto& positions = is_row_axis ? column_positions_ : row_positions_;
- size_t num_positions = positions.size();
+ wtf_size_t num_positions = positions.size();
LayoutUnit offset_between_tracks =
is_row_axis ? offset_between_columns_.distribution_offset
: offset_between_rows_.distribution_offset;
- Vector<LayoutUnit> tracks;
+ Vector<LayoutUnit, 1> tracks;
if (num_positions < 2)
return tracks;
@@ -1266,7 +1272,7 @@ Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle(
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)
+ for (wtf_size_t i = 0; i < num_positions - 2; ++i)
tracks.push_back(positions[i + 1] - positions[i] - offset_between_tracks -
gap);
tracks.push_back(positions[num_positions - 1] - positions[num_positions - 2]);
@@ -1274,11 +1280,11 @@ Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle(
if (!has_collapsed_tracks)
return tracks;
- size_t remaining_empty_tracks =
+ wtf_size_t remaining_empty_tracks =
grid_->AutoRepeatEmptyTracks(direction)->size();
- size_t last_line = tracks.size();
+ wtf_size_t last_line = tracks.size();
gap = GridGap(direction);
- for (size_t i = 1; i < last_line; ++i) {
+ for (wtf_size_t i = 1; i < last_line; ++i) {
if (grid_->IsEmptyAutoRepeatTrack(direction, i - 1)) {
--remaining_empty_tracks;
} else {
@@ -1481,11 +1487,11 @@ void LayoutGrid::PopulateGridPositionsForDirection(
// inline-axis direction.
bool is_row_axis = direction == kForColumns;
auto& tracks = track_sizing_algorithm_.Tracks(direction);
- size_t number_of_tracks = tracks.size();
- size_t number_of_lines = number_of_tracks + 1;
- size_t last_line = number_of_lines - 1;
+ wtf_size_t number_of_tracks = tracks.size();
+ wtf_size_t number_of_lines = number_of_tracks + 1;
+ wtf_size_t last_line = number_of_lines - 1;
bool has_collapsed_tracks = grid_->HasAutoRepeatEmptyTracks(direction);
- size_t number_of_collapsed_tracks =
+ wtf_size_t number_of_collapsed_tracks =
has_collapsed_tracks ? grid_->AutoRepeatEmptyTracks(direction)->size()
: 0;
const auto& offset =
@@ -1510,8 +1516,8 @@ void LayoutGrid::PopulateGridPositionsForDirection(
// as we might not compute the gap between two consecutive tracks without
// examining the surrounding ones.
LayoutUnit gap = !has_collapsed_tracks ? GridGap(direction) : LayoutUnit();
- size_t next_to_last_line = number_of_lines - 2;
- for (size_t i = 0; i < next_to_last_line; ++i)
+ wtf_size_t next_to_last_line = number_of_lines - 2;
+ for (wtf_size_t i = 0; i < next_to_last_line; ++i)
positions[i + 1] = positions[i] + offset.distribution_offset +
tracks[i].BaseSize() + gap;
positions[last_line] =
@@ -1522,10 +1528,10 @@ void LayoutGrid::PopulateGridPositionsForDirection(
// they become 0.
if (has_collapsed_tracks) {
gap = GridGap(direction);
- size_t remaining_empty_tracks = number_of_collapsed_tracks;
+ wtf_size_t remaining_empty_tracks = number_of_collapsed_tracks;
LayoutUnit offset_accumulator;
LayoutUnit gap_accumulator;
- for (size_t i = 1; i < last_line; ++i) {
+ for (wtf_size_t i = 1; i < last_line; ++i) {
if (grid_->IsEmptyAutoRepeatTrack(direction, i - 1)) {
--remaining_empty_tracks;
offset_accumulator += offset.distribution_offset;
@@ -1599,6 +1605,29 @@ StyleSelfAlignmentData LayoutGrid::JustifySelfForChild(
SelfAlignmentNormalBehavior(&child), style);
}
+bool LayoutGrid::AspectRatioPrefersInline(const LayoutBox& child,
+ bool block_flow_is_column_axis) {
+ if (child.StyleRef().AspectRatio().IsAuto())
+ return false;
+ // Not using AlignSelfForChild/JustifySelfForChild here since we are only
+ // interested in explicit stretch, not normal behavior.
+ bool has_explicit_inline_stretch =
+ child.StyleRef()
+ .ResolvedJustifySelf(ItemPosition::kNormal, Style())
+ .GetPosition() == ItemPosition::kStretch;
+ bool has_explicit_block_stretch =
+ child.StyleRef()
+ .ResolvedAlignSelf(ItemPosition::kNormal, Style())
+ .GetPosition() == ItemPosition::kStretch;
+ if (!block_flow_is_column_axis)
+ std::swap(has_explicit_inline_stretch, has_explicit_block_stretch);
+ if (has_explicit_inline_stretch && has_explicit_block_stretch)
+ return false;
+ if (has_explicit_inline_stretch)
+ return true;
+ return !has_explicit_block_stretch;
+}
+
// FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to
// LayoutBox.
void LayoutGrid::ApplyStretchAlignmentToChildIfNeeded(LayoutBox& child) {
@@ -1609,7 +1638,8 @@ void LayoutGrid::ApplyStretchAlignmentToChildIfNeeded(LayoutBox& child) {
bool allowed_to_stretch_child_block_size =
block_flow_is_column_axis ? AllowedToStretchChildAlongColumnAxis(child)
: AllowedToStretchChildAlongRowAxis(child);
- if (allowed_to_stretch_child_block_size) {
+ if (allowed_to_stretch_child_block_size &&
+ !AspectRatioPrefersInline(child, block_flow_is_column_axis)) {
LayoutUnit stretched_logical_height =
AvailableAlignmentSpaceForChildBeforeStretching(
OverrideContainingBlockContentSizeForChild(child,
@@ -1808,11 +1838,11 @@ LayoutUnit LayoutGrid::FirstLineBoxBaseline() const {
const LayoutBox* first_child = nullptr;
bool is_baseline_aligned = false;
// Finding the first grid item in grid order.
- for (size_t column = 0;
+ for (wtf_size_t column = 0;
!is_baseline_aligned && column < grid_->NumTracks(kForColumns);
column++) {
const GridItemList& cell = grid_->Cell(0, column);
- for (size_t index = 0; index < cell.size(); index++) {
+ for (wtf_size_t index = 0; index < cell.size(); index++) {
const LayoutBox* child = cell[index];
DCHECK(!child->IsOutOfFlowPositioned());
// If an item participates in baseline alignment, we select such item.
@@ -2118,7 +2148,7 @@ LayoutUnit LayoutGrid::ResolveAutoStartGridPosition(
if (direction == kForRows || StyleRef().IsLeftToRightDirection())
return LayoutUnit();
- int last_line = NumTracks(kForColumns, *grid_);
+ wtf_size_t last_line = NumTracks(kForColumns, *grid_);
ContentPosition position = StyleRef().ResolvedJustifyContentPosition(
ContentAlignmentNormalBehavior());
if (position == ContentPosition::kEnd)
@@ -2139,7 +2169,7 @@ LayoutUnit LayoutGrid::ResolveAutoEndGridPosition(
if (StyleRef().IsLeftToRightDirection())
return ClientLogicalWidth();
- int last_line = NumTracks(kForColumns, *grid_);
+ wtf_size_t last_line = NumTracks(kForColumns, *grid_);
ContentPosition position = StyleRef().ResolvedJustifyContentPosition(
ContentAlignmentNormalBehavior());
if (position == ContentPosition::kEnd)
@@ -2166,10 +2196,10 @@ LayoutUnit LayoutGrid::GridAreaBreadthForOutOfFlowChild(
if (span.IsIndefinite())
return is_row_axis ? ClientLogicalWidth() : ClientLogicalHeight();
- size_t explicit_start = grid_->ExplicitGridStart(direction);
- size_t start_line = span.UntranslatedStartLine() + explicit_start;
- size_t end_line = span.UntranslatedEndLine() + explicit_start;
- size_t last_line = NumTracks(direction, *grid_);
+ wtf_size_t explicit_start = grid_->ExplicitGridStart(direction);
+ wtf_size_t start_line = span.UntranslatedStartLine() + explicit_start;
+ wtf_size_t end_line = span.UntranslatedEndLine() + explicit_start;
+ wtf_size_t last_line = NumTracks(direction, *grid_);
GridPosition start_position = direction == kForColumns
? child.StyleRef().GridColumnStart()
: child.StyleRef().GridRowStart();
@@ -2264,9 +2294,10 @@ void LayoutGrid::GridAreaPositionForOutOfFlowChild(
auto& line_of_positioned_item =
is_row_axis ? column_of_positioned_item_ : row_of_positioned_item_;
start = is_row_axis ? BorderLogicalLeft() : BorderBefore();
- if (absl::optional<size_t> line = line_of_positioned_item.at(&child)) {
+ auto it = line_of_positioned_item.find(&child);
+ if (it != line_of_positioned_item.end() && it->value) {
auto& positions = is_row_axis ? column_positions_ : row_positions_;
- start = positions[line.value()];
+ start = positions[it->value.value()];
}
start += LogicalOffsetForOutOfFlowChild(child, direction, track_breadth);
end = start + track_breadth;
@@ -2481,7 +2512,8 @@ LayoutUnit LayoutGrid::TranslateOutOfFlowRTLCoordinate(
DCHECK(child.IsOutOfFlowPositioned());
DCHECK(!StyleRef().IsLeftToRightDirection());
- if (column_of_positioned_item_.at(&child))
+ auto it = column_of_positioned_item_.find(&child);
+ if (it != column_of_positioned_item_.end() && it->value)
return TranslateRTLCoordinate(coordinate);
return BorderLogicalLeft() + BorderLogicalRight() + ClientLogicalWidth() -
@@ -2580,20 +2612,20 @@ bool LayoutGrid::CachedHasDefiniteLogicalHeight() const {
return has_definite_logical_height_.value();
}
-size_t LayoutGrid::NonCollapsedTracks(
+wtf_size_t LayoutGrid::NonCollapsedTracks(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
auto& tracks = track_sizing_algorithm_.Tracks(direction);
- size_t number_of_tracks = tracks.size();
+ wtf_size_t number_of_tracks = tracks.size();
bool has_collapsed_tracks = grid_->HasAutoRepeatEmptyTracks(direction);
- size_t number_of_collapsed_tracks =
+ wtf_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 {
+wtf_size_t LayoutGrid::NumTracks(GridTrackSizingDirection direction,
+ const Grid& grid) const {
NOT_DESTROYED();
// Due to limitations in our internal representation, we cannot know the
// number of columns from m_grid *if* there is no row (because m_grid would be
@@ -2611,18 +2643,20 @@ size_t LayoutGrid::NumTracks(GridTrackSizingDirection direction,
StyleRef(), grid.AutoRepeatTracks(kForColumns));
}
-size_t LayoutGrid::ExplicitGridEndForDirection(
+wtf_size_t LayoutGrid::ExplicitGridEndForDirection(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
- size_t leading = ExplicitGridStartForDirection(direction);
+ wtf_size_t leading = ExplicitGridStartForDirection(direction);
if (direction == kForRows) {
- return leading + GridPositionsResolver::ExplicitGridRowCount(
- StyleRef(), grid_->AutoRepeatTracks(direction));
+ return base::checked_cast<wtf_size_t>(
+ leading + GridPositionsResolver::ExplicitGridRowCount(
+ StyleRef(), grid_->AutoRepeatTracks(direction)));
}
- return leading + GridPositionsResolver::ExplicitGridColumnCount(
- StyleRef(), grid_->AutoRepeatTracks(direction));
+ return base::checked_cast<wtf_size_t>(
+ leading + GridPositionsResolver::ExplicitGridColumnCount(
+ StyleRef(), grid_->AutoRepeatTracks(direction)));
}
LayoutUnit LayoutGrid::GridItemOffset(
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 3e321f741e6..6c45fb8f889 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_grid.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_grid.h
@@ -73,7 +73,7 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
return this;
}
- Vector<LayoutUnit> TrackSizesForComputedStyle(
+ Vector<LayoutUnit, 1> TrackSizesForComputedStyle(
GridTrackSizingDirection) const final;
Vector<LayoutUnit> ColumnPositions() const final {
@@ -96,14 +96,14 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
return grid_->Cell(row, column);
}
- size_t AutoRepeatCountForDirection(
+ wtf_size_t AutoRepeatCountForDirection(
GridTrackSizingDirection direction) const final {
- return grid_->AutoRepeatTracks(direction);
+ return base::checked_cast<wtf_size_t>(grid_->AutoRepeatTracks(direction));
}
- size_t ExplicitGridStartForDirection(
+ wtf_size_t ExplicitGridStartForDirection(
GridTrackSizingDirection direction) const final {
- return grid_->ExplicitGridStart(direction);
+ return base::checked_cast<wtf_size_t>(grid_->ExplicitGridStart(direction));
}
LayoutUnit TranslateRTLCoordinate(LayoutUnit) const;
@@ -115,8 +115,8 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
// it out how to remove this dependency.
LayoutUnit GuttersSize(const Grid&,
GridTrackSizingDirection,
- size_t start_line,
- size_t span,
+ wtf_size_t start_line,
+ wtf_size_t span,
absl::optional<LayoutUnit> available_size) const;
bool CachedHasDefiniteLogicalHeight() const;
bool IsBaselineAlignmentForChild(const LayoutBox& child) const;
@@ -134,7 +134,7 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
StyleContentAlignmentData ContentAlignment(GridTrackSizingDirection) const;
- size_t ExplicitGridEndForDirection(GridTrackSizingDirection) const final;
+ wtf_size_t ExplicitGridEndForDirection(GridTrackSizingDirection) const final;
// Exposed for testing *ONLY*.
Grid* InternalGrid() const {
@@ -174,11 +174,11 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
bool ExplicitGridDidResize(const ComputedStyle&) const;
bool NamedGridLinesDefinitionDidChange(const ComputedStyle&) const;
- size_t ComputeAutoRepeatTracksCount(
+ wtf_size_t ComputeAutoRepeatTracksCount(
GridTrackSizingDirection,
absl::optional<LayoutUnit> available_size) const;
- size_t ClampAutoRepeatTracks(GridTrackSizingDirection,
- size_t auto_repeat_tracks) const;
+ wtf_size_t ClampAutoRepeatTracks(GridTrackSizingDirection,
+ wtf_size_t auto_repeat_tracks) const;
std::unique_ptr<OrderedTrackIndexSet> ComputeEmptyTracksForAutoRepeat(
Grid&,
@@ -201,7 +201,7 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
void PlaceAutoMajorAxisItemOnGrid(
Grid&,
LayoutBox&,
- std::pair<size_t, size_t>& auto_placement_cursor) const;
+ std::pair<wtf_size_t, wtf_size_t>& auto_placement_cursor) const;
GridTrackSizingDirection AutoPlacementMajorAxisDirection() const;
GridTrackSizingDirection AutoPlacementMinorAxisDirection() const;
@@ -311,8 +311,8 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
size_t GridItemSpan(const LayoutBox&, GridTrackSizingDirection);
- size_t NonCollapsedTracks(GridTrackSizingDirection) const;
- size_t NumTracks(GridTrackSizingDirection, const Grid&) const;
+ wtf_size_t NonCollapsedTracks(GridTrackSizingDirection) const;
+ wtf_size_t NumTracks(GridTrackSizingDirection, const Grid&) const;
static LayoutUnit OverrideContainingBlockContentSizeForChild(
const LayoutBox& child,
@@ -321,6 +321,9 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
LineDirectionMode);
static const StyleContentAlignmentData& ContentAlignmentNormalBehavior();
+ bool AspectRatioPrefersInline(const LayoutBox& child,
+ bool block_flow_is_column_axis);
+
std::unique_ptr<Grid> grid_;
GridTrackSizingAlgorithm track_sizing_algorithm_;
@@ -329,7 +332,7 @@ class LayoutGrid final : public LayoutBlock, public LayoutNGGridInterface {
ContentAlignmentData offset_between_columns_;
ContentAlignmentData offset_between_rows_;
- typedef HashMap<const LayoutBox*, absl::optional<size_t>>
+ typedef HashMap<const LayoutBox*, absl::optional<wtf_size_t>>
OutOfFlowPositionsMap;
OutOfFlowPositionsMap column_of_positioned_item_;
OutOfFlowPositionsMap row_of_positioned_item_;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc
deleted file mode 100644
index 69120c925bb..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-
-namespace blink {
-
-class LayoutGridTest : public RenderingTest {};
-
-TEST_F(LayoutGridTest, RowGapUseCounter) {
- SetBodyInnerHTML(R"HTML(
- <div style="display: grid; gap: 20%;">
- <div></div>
- <div></div>
- </div>
- )HTML");
- RunDocumentLifecycle();
-
- EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kGridRowGapPercent));
- EXPECT_TRUE(
- GetDocument().IsUseCounted(WebFeature::kGridRowGapPercentIndefinite));
-}
-
-TEST_F(LayoutGridTest, RowGapUseCounterOneTrack) {
- SetBodyInnerHTML(R"HTML(
- <div style="display: grid; gap: 20%;">
- <div></div>
- </div>
- )HTML");
- RunDocumentLifecycle();
-
- EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kGridRowGapPercent));
- EXPECT_FALSE(
- GetDocument().IsUseCounted(WebFeature::kGridRowGapPercentIndefinite));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image.cc b/chromium/third_party/blink/renderer/core/layout/layout_image.cc
index 4e2fb9a4def..9884b5011a5 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/media/media_element_parser_helpers.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.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_video.h"
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 ac6e978e7cc..480ef73cb8e 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
@@ -83,7 +83,7 @@ FloatSize LayoutImageResourceStyleImage::ImageSizeWithDefaultSize(
float multiplier,
const FloatSize& default_size) const {
return style_image_->ImageSize(
- layout_object_->GetDocument(), multiplier, default_size,
+ multiplier, default_size,
LayoutObject::ShouldRespectImageOrientation(layout_object_));
}
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 574129e253b..17a581817f6 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/layout/geometry/transform_state.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_object_inlines.h"
#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/line/inline_text_box.h"
@@ -44,6 +45,7 @@
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/inline_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
+#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
@@ -383,6 +385,15 @@ void LayoutInline::UpdateAlwaysCreateLineBoxes(bool full_layout) {
bool LayoutInline::ComputeInitialShouldCreateBoxFragment(
const ComputedStyle& style) const {
NOT_DESTROYED();
+
+ // We'd like to use ScopedSVGPaintState in
+ // NGInlineBoxFragmentPainter::Paint().
+ // TODO(layout-dev): Improve the below condition so that we a create box
+ // fragment only if this requires ScopedSVGPaintState, instead of
+ // creating box fragments for all LayoutSVGInlines.
+ if (IsSVGInline())
+ return true;
+
if (style.HasBoxDecorationBackground() || style.MayHavePadding() ||
style.MayHaveMargin())
return true;
@@ -521,7 +532,24 @@ void LayoutInline::AddChildIgnoringContinuation(LayoutObject* new_child,
if (!new_child->IsInline() && !new_child->IsFloatingOrOutOfFlowPositioned() &&
!new_child->IsTablePart()) {
- LayoutBlockFlow* new_box = CreateAnonymousContainerForBlockChildren();
+ if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGBlockInInlineEnabled()) &&
+ !ForceLegacyLayout()) {
+ // TODO(crbug.com/716930): This logic is still at the prototype level and
+ // to be re-written, but landed under the runtime flag to allow us working
+ // on dependent code in parallel.
+ DCHECK(!new_child->IsInline());
+ auto* anonymous_box = DynamicTo<LayoutBlockFlow>(
+ before_child ? before_child->PreviousSibling() : LastChild());
+ if (!anonymous_box || !anonymous_box->IsAnonymous()) {
+ anonymous_box =
+ CreateAnonymousContainerForBlockChildren(/* split_flow */ false);
+ LayoutBoxModelObject::AddChild(anonymous_box, before_child);
+ }
+ anonymous_box->AddChild(new_child);
+ return;
+ }
+ LayoutBlockFlow* new_box =
+ CreateAnonymousContainerForBlockChildren(/* split_flow */ true);
LayoutBoxModelObject* old_continuation = Continuation();
SetContinuation(new_box);
@@ -574,15 +602,13 @@ void LayoutInline::SplitInlines(LayoutBlockFlow* from_block,
// nest to a much greater depth (see bugzilla bug 13430) but for now we have a
// limit. This *will* result in incorrect rendering, but the alternative is to
// hang forever.
- const unsigned kCMaxSplitDepth = 200;
Vector<LayoutInline*> inlines_to_clone;
LayoutInline* top_most_inline = this;
for (LayoutObject* o = this; o != from_block; o = o->Parent()) {
if (o->IsLayoutNGInsideListMarker())
continue;
top_most_inline = To<LayoutInline>(o);
- if (inlines_to_clone.size() < kCMaxSplitDepth)
- inlines_to_clone.push_back(top_most_inline);
+ inlines_to_clone.push_back(top_most_inline);
// Keep walking up the chain to ensure |topMostInline| is a child of
// |fromBlock|, to avoid assertion failure when |fromBlock|'s children are
// moved to |toBlock| below.
@@ -716,7 +742,8 @@ void LayoutInline::SplitFlow(LayoutObject* before_child,
layout_invalidation_reason::kAnonymousBlockChange);
}
-LayoutBlockFlow* LayoutInline::CreateAnonymousContainerForBlockChildren() {
+LayoutBlockFlow* LayoutInline::CreateAnonymousContainerForBlockChildren(
+ bool split_flow) {
NOT_DESTROYED();
// We are placing a block inside an inline. We have to perform a split of this
// inline into continuations. This involves creating an anonymous block box to
@@ -738,11 +765,14 @@ LayoutBlockFlow* LayoutInline::CreateAnonymousContainerForBlockChildren() {
// for continuations.
new_style->SetDirection(containing_block->StyleRef().Direction());
- // If inside an inline affected by in-flow positioning the block needs to be
- // affected by it too. Giving the block a layer like this allows it to collect
- // the x/y offsets from inline parents later.
- if (LayoutObject* positioned_ancestor = InFlowPositionedInlineAncestor(this))
- new_style->SetPosition(positioned_ancestor->StyleRef().GetPosition());
+ if (split_flow) {
+ // If inside an inline affected by in-flow positioning the block needs to be
+ // affected by it too. Giving the block a layer like this allows it to
+ // collect the x/y offsets from inline parents later.
+ if (LayoutObject* positioned_ancestor =
+ InFlowPositionedInlineAncestor(this))
+ new_style->SetPosition(positioned_ancestor->StyleRef().GetPosition());
+ }
LegacyLayout legacy = containing_block->ForceLegacyLayout()
? LegacyLayout::kForce
@@ -1583,8 +1613,17 @@ PaintLayerType LayoutInline::LayerTypeRequired() const {
void LayoutInline::ChildBecameNonInline(LayoutObject* child) {
NOT_DESTROYED();
+ if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGBlockInInlineEnabled()) &&
+ !ForceLegacyLayout()) {
+ DCHECK(!child->IsInline());
+ // TODO(crbug.com/716930): Add anonymous blocks as
+ // |AddChildIgnoringContinuation| does.
+ NOTIMPLEMENTED();
+ return;
+ }
// We have to split the parent flow.
- LayoutBlockFlow* new_box = CreateAnonymousContainerForBlockChildren();
+ LayoutBlockFlow* new_box =
+ CreateAnonymousContainerForBlockChildren(/* split_flow */ true);
LayoutBoxModelObject* old_continuation = Continuation();
SetContinuation(new_box);
LayoutObject* before_child = child->NextSibling();
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 9d67e886275..0af47525a6e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.h
@@ -367,8 +367,8 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
LayoutObject* new_child,
LayoutBoxModelObject* old_cont);
- // Create an anoymous block for block children of this inline.
- LayoutBlockFlow* CreateAnonymousContainerForBlockChildren();
+ // Create an anonymous block for block children of this inline.
+ LayoutBlockFlow* CreateAnonymousContainerForBlockChildren(bool split_flow);
void UpdateLayout() final {
NOT_DESTROYED();
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 b6e16ae7cec..6e513c488b0 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
@@ -9,6 +9,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -30,6 +32,19 @@ class ParameterizedLayoutInlineTest : public testing::WithParamInterface<bool>,
bool LayoutNGEnabled() const {
return RuntimeEnabledFeatures::LayoutNGEnabled();
}
+
+ bool HitTestAllPhases(LayoutObject& object,
+ HitTestResult& result,
+ const HitTestLocation& location,
+ const PhysicalOffset& offset) {
+ if (!LayoutNGEnabled() || !object.IsBox())
+ return object.HitTestAllPhases(result, location, offset);
+ const LayoutBox& box = To<LayoutBox>(object);
+ DCHECK_EQ(box.PhysicalFragmentCount(), 1u);
+ const NGPhysicalBoxFragment& fragment = *box.GetPhysicalFragment(0);
+ return NGBoxFragmentPainter(fragment).HitTestAllPhases(result, location,
+ offset);
+ }
};
INSTANTIATE_TEST_SUITE_P(All, ParameterizedLayoutInlineTest, testing::Bool());
@@ -177,7 +192,7 @@ TEST_P(ParameterizedLayoutInlineTest, RelativePositionedHitTest) {
LayoutObject* layout_div = div->GetLayoutObject();
HitTestResult hit_result(hit_request, location);
bool hit_outcome =
- layout_div->HitTestAllPhases(hit_result, location, container_offset);
+ HitTestAllPhases(*layout_div, hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(div, hit_result.InnerNode());
}
@@ -188,7 +203,7 @@ TEST_P(ParameterizedLayoutInlineTest, RelativePositionedHitTest) {
LayoutObject* layout_span = span->GetLayoutObject();
HitTestResult hit_result(hit_request, location);
bool hit_outcome =
- layout_span->HitTestAllPhases(hit_result, location, container_offset);
+ HitTestAllPhases(*layout_span, hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(text, hit_result.InnerNode());
}
@@ -227,7 +242,7 @@ TEST_P(ParameterizedLayoutInlineTest, MultilineRelativePositionedHitTest) {
HitTestResult hit_result(hit_request, location);
bool hit_outcome =
- layout_span->HitTestAllPhases(hit_result, location, container_offset);
+ HitTestAllPhases(*layout_span, hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(target, hit_result.InnerNode());
@@ -247,7 +262,7 @@ TEST_P(ParameterizedLayoutInlineTest, MultilineRelativePositionedHitTest) {
HitTestResult hit_result(hit_request, location);
bool hit_outcome =
- layout_span->HitTestAllPhases(hit_result, location, container_offset);
+ HitTestAllPhases(*layout_span, hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(target, hit_result.InnerNode());
@@ -267,7 +282,7 @@ TEST_P(ParameterizedLayoutInlineTest, MultilineRelativePositionedHitTest) {
HitTestResult hit_result(hit_request, location);
bool hit_outcome =
- layout_span->HitTestAllPhases(hit_result, location, container_offset);
+ HitTestAllPhases(*layout_span, hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(target, hit_result.InnerNode());
@@ -301,7 +316,7 @@ TEST_P(ParameterizedLayoutInlineTest, HitTestCulledInlinePreWrap) {
HitTestLocation location(hit_location);
HitTestResult hit_result(hit_request, location);
LayoutObject* container = GetLayoutObjectByElementId("container");
- container->HitTestAllPhases(hit_result, location, PhysicalOffset());
+ HitTestAllPhases(*container, hit_result, location, PhysicalOffset());
Element* span = GetElementById("span");
Node* text_node = span->firstChild();
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 5cd7442f270..5a905684746 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
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/html/html_li_element.h"
#include "third_party/blink/renderer/core/html/html_olist_element.h"
#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_outside_list_marker.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/list_marker.h"
@@ -60,7 +61,7 @@ void LayoutListItem::StyleDidChange(StyleDifference diff,
LayoutBlockFlow::StyleDidChange(diff, old_style);
StyleImage* current_image = StyleRef().ListStyleImage();
- if (StyleRef().GetListStyleType() ||
+ if (StyleRef().ListStyleType() ||
(current_image && !current_image->ErrorOccurred())) {
NotifyOfSubtreeChange();
}
@@ -79,10 +80,8 @@ void LayoutListItem::StyleDidChange(StyleDifference diff,
list_marker->UpdateMarkerContentIfNeeded(*marker);
if (old_style) {
- const ListStyleTypeData* old_list_style_type =
- old_style->GetListStyleType();
- const ListStyleTypeData* new_list_style_type =
- StyleRef().GetListStyleType();
+ const ListStyleTypeData* old_list_style_type = old_style->ListStyleType();
+ const ListStyleTypeData* new_list_style_type = StyleRef().ListStyleType();
if (old_list_style_type != new_list_style_type &&
(!old_list_style_type || !new_list_style_type ||
*old_list_style_type != *new_list_style_type)) {
@@ -97,12 +96,8 @@ void LayoutListItem::StyleDidChange(StyleDifference diff,
void LayoutListItem::UpdateCounterStyle() {
NOT_DESTROYED();
- if (!RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled())
- return;
-
- if (!StyleRef().GetListStyleType() ||
- StyleRef().GetListStyleType()->IsCounterStyleReferenceValid(
- GetDocument())) {
+ if (!StyleRef().ListStyleType() ||
+ StyleRef().ListStyleType()->IsCounterStyleReferenceValid(GetDocument())) {
return;
}
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 4cbdc402ae4..06be8cb9c42 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
@@ -26,11 +26,11 @@
#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
#include "third_party/blink/renderer/core/css/counter_style.h"
+#include "third_party/blink/renderer/core/html/html_li_element.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/list_marker.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
#include "third_party/blink/renderer/core/paint/list_marker_painter.h"
#include "third_party/blink/renderer/core/style/list_style_type_data.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
@@ -73,10 +73,9 @@ LayoutSize LayoutListMarker::ImageBulletSize() const {
// marker pseudoclass to allow control over the width and height of the
// marker box.
float bullet_width = font_data->GetFontMetrics().Ascent() / 2.0f;
- return RoundedLayoutSize(
- image_->ImageSize(GetDocument(), StyleRef().EffectiveZoom(),
- FloatSize(bullet_width, bullet_width),
- LayoutObject::ShouldRespectImageOrientation(this)));
+ return RoundedLayoutSize(image_->ImageSize(
+ StyleRef().EffectiveZoom(), FloatSize(bullet_width, bullet_width),
+ LayoutObject::ShouldRespectImageOrientation(this)));
}
void LayoutListMarker::ListStyleTypeChanged() {
@@ -186,19 +185,10 @@ void LayoutListMarker::UpdateContent() {
break;
case ListMarker::ListStyleCategory::kSymbol:
// value is ignored for these types
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- text_ = GetCounterStyle().GenerateRepresentation(0);
- } else {
- text_ = list_marker_text::GetText(StyleRef().ListStyleType(), 0);
- }
+ text_ = GetCounterStyle().GenerateRepresentation(0);
break;
case ListMarker::ListStyleCategory::kLanguage:
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- text_ = GetCounterStyle().GenerateRepresentation(ListItem()->Value());
- } else {
- text_ = list_marker_text::GetText(StyleRef().ListStyleType(),
- ListItem()->Value());
- }
+ text_ = GetCounterStyle().GenerateRepresentation(ListItem()->Value());
break;
case ListMarker::ListStyleCategory::kStaticString:
text_ = StyleRef().ListStyleStringValue();
@@ -213,18 +203,11 @@ String LayoutListMarker::TextAlternative() const {
// Return prefix, marker text and then suffix even in RTL, reflecting speech
// order.
+ if (GetListStyleCategory() == ListMarker::ListStyleCategory::kNone)
+ return "";
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- if (GetListStyleCategory() == ListMarker::ListStyleCategory::kNone)
- return "";
-
- const CounterStyle& counter_style = GetCounterStyle();
- return counter_style.GetPrefix() + text_ + counter_style.GetSuffix();
- }
-
- UChar suffix =
- list_marker_text::Suffix(StyleRef().ListStyleType(), ListItem()->Value());
- return text_ + suffix + ' ';
+ const CounterStyle& counter_style = GetCounterStyle();
+ return counter_style.GetPrefix() + text_ + counter_style.GetSuffix();
}
LayoutUnit LayoutListMarker::GetWidthOfText(
@@ -240,26 +223,14 @@ LayoutUnit LayoutListMarker::GetWidthOfText(
return item_width;
}
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- // This doesn't seem correct, e.g., ligatures. We don't fix it since it's
- // legacy layout.
- const CounterStyle& counter_style = GetCounterStyle();
- if (counter_style.GetPrefix())
- item_width += LayoutUnit(font.Width(TextRun(counter_style.GetPrefix())));
- if (counter_style.GetSuffix())
- item_width += LayoutUnit(font.Width(TextRun(counter_style.GetSuffix())));
- return item_width;
- }
-
- // TODO(wkorman): Look into constructing a text run for both text and suffix
- // and painting them together.
- UChar suffix[2] = {
- list_marker_text::Suffix(StyleRef().ListStyleType(), ListItem()->Value()),
- ' '};
- TextRun run =
- ConstructTextRun(font, suffix, 2, StyleRef(), StyleRef().Direction());
- LayoutUnit suffix_space_width = LayoutUnit(font.Width(run));
- return item_width + suffix_space_width;
+ // This doesn't seem correct, e.g., ligatures. We don't fix it since it's
+ // legacy layout.
+ const CounterStyle& counter_style = GetCounterStyle();
+ if (counter_style.GetPrefix())
+ item_width += LayoutUnit(font.Width(TextRun(counter_style.GetPrefix())));
+ if (counter_style.GetSuffix())
+ item_width += LayoutUnit(font.Width(TextRun(counter_style.GetSuffix())));
+ return item_width;
}
MinMaxSizes LayoutListMarker::ComputeIntrinsicLogicalWidths() const {
@@ -351,7 +322,7 @@ ListMarker::ListStyleCategory LayoutListMarker::GetListStyleCategory() const {
const CounterStyle& LayoutListMarker::GetCounterStyle() const {
NOT_DESTROYED();
- const ListStyleTypeData* list_style_data = StyleRef().GetListStyleType();
+ const ListStyleTypeData* list_style_data = StyleRef().ListStyleType();
DCHECK(list_style_data);
DCHECK(list_style_data->IsCounterStyle());
return list_style_data->GetCounterStyle(GetDocument());
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_marker_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_list_marker_test.cc
index 9f117257d29..c1df2655bf2 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_marker_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_marker_test.cc
@@ -19,8 +19,6 @@ class LayoutListMarkerTest : public RenderingTest,
// https://crbug.com/1167174
TEST_F(LayoutListMarkerTest, ListStyleTypeNoneTextAlternative) {
- ScopedCSSAtRuleCounterStyleForTest scope(true);
-
SetBodyInnerHTML(R"HTML(
<style>
li {
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 aad826a522c..87089219f32 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_media.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_media.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MEDIA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MEDIA_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
index 6297bb04fbd..b0df98a7268 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -103,8 +104,10 @@ static inline bool IsMultiColumnContainer(const LayoutObject& object) {
// other formatting contexts in-between). We also require that there be no
// transforms, since transforms insist on being in the containing block chain
// for everything inside it, which conflicts with a spanners's need to have the
-// multicol container as its direct containing block. We may also not put
-// spanners inside objects that don't support fragmentation.
+// multicol container as its direct containing block. However, the containing
+// block chain goes directly from the column spanner to the multicol container
+// for an NG multicol, so it is safe to skip this rule in such cases. We may
+// also not put spanners inside objects that don't support fragmentation.
bool LayoutMultiColumnFlowThread::CanContainSpannerInParentFragmentationContext(
const LayoutObject& object) const {
NOT_DESTROYED();
@@ -112,7 +115,8 @@ bool LayoutMultiColumnFlowThread::CanContainSpannerInParentFragmentationContext(
if (!block_flow)
return false;
return !block_flow->CreatesNewFormattingContext() &&
- !block_flow->CanContainFixedPositionObjects() &&
+ (!block_flow->CanContainFixedPositionObjects() ||
+ MultiColumnBlockFlow()->IsLayoutNGObject()) &&
block_flow->GetPaginationBreakability(fragmentation_engine_) !=
LayoutBox::kForbidBreaks &&
!IsMultiColumnContainer(*block_flow);
@@ -239,8 +243,14 @@ LayoutMultiColumnSet* LayoutMultiColumnFlowThread::MapDescendantToColumnSet(
DCHECK(!ContainingColumnSpannerPlaceholder(layout_object));
DCHECK_NE(layout_object, this);
DCHECK(layout_object->IsDescendantOf(this));
- // Out-of-flow objects don't belong in column sets.
- DCHECK(layout_object->ContainingBlock()->IsDescendantOf(this));
+ // Out-of-flow objects don't belong in column sets. DHCECK that the object is
+ // contained by the flow thread, except for legends ("rendered" or
+ // not). Although a rendered legend isn't part of the fragmentation context,
+ // we'll let it contribute to creation of a column set, for the sake of
+ // simplicity. Style and DOM changes may later on change which LEGEND child is
+ // the rendered legend, and we don't want to keep track of that.
+ DCHECK(layout_object->IsRenderedLegend() ||
+ layout_object->ContainingBlock()->IsDescendantOf(this));
DCHECK_EQ(layout_object->FlowThreadContainingBlock(), this);
DCHECK(!layout_object->IsLayoutMultiColumnSet());
DCHECK(!layout_object->IsLayoutMultiColumnSpannerPlaceholder());
@@ -1340,6 +1350,9 @@ void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleWillChange(
if (NeedsToRemoveFromFlowThread(*descendant, descendant->StyleRef(),
new_style)) {
FlowThreadDescendantWillBeRemoved(descendant);
+#if DCHECK_IS_ON()
+ style_changed_box_ = nullptr;
+#endif
return;
}
#if DCHECK_IS_ON()
@@ -1359,6 +1372,12 @@ void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleDidChange(
StyleDifference diff,
const ComputedStyle& old_style) {
NOT_DESTROYED();
+
+#if DCHECK_IS_ON()
+ const auto* style_changed_box = style_changed_box_;
+ style_changed_box_ = nullptr;
+#endif
+
bool toggle_spanners_if_needed = toggle_spanners_if_needed_;
toggle_spanners_if_needed_ = false;
@@ -1385,16 +1404,20 @@ void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleDidChange(
if (!toggle_spanners_if_needed)
return;
+
+ if (could_contain_spanners_ ==
+ CanContainSpannerInParentFragmentationContext(*descendant))
+ return;
+
#if DCHECK_IS_ON()
// Make sure that we were preceded by a call to
// flowThreadDescendantStyleWillChange() with the same descendant as we have
// now.
- DCHECK_EQ(style_changed_box_, descendant);
+ if (style_changed_box)
+ DCHECK_EQ(style_changed_box, descendant);
#endif
- if (could_contain_spanners_ !=
- CanContainSpannerInParentFragmentationContext(*descendant))
- ToggleSpannersInSubtree(descendant);
+ ToggleSpannersInSubtree(descendant);
}
void LayoutMultiColumnFlowThread::ToggleSpannersInSubtree(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_set.cc b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
index 436183e8f6e..275f5d9e73e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h"
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 d23c4c47f52..bd2a64559a2 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
namespace blink {
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 564d5504dee..64e159fcea8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.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_adjuster.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"
@@ -47,11 +48,11 @@
#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/frame_selection.h"
+#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
#include "third_party/blink/renderer/core/editing/layout_selection.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/editing/visible_units.h"
-#include "third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.h"
#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"
@@ -64,6 +65,7 @@
#include "third_party/blink/renderer/core/html/html_table_element.h"
#include "third_party/blink/renderer/core/html/image_document.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
#include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
@@ -82,10 +84,13 @@
#include "third_party/blink/renderer/core/layout/layout_list_marker.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_object_inlines.h"
+#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#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/custom/layout_ng_custom.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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/ng_block_node.h"
@@ -101,6 +106,7 @@
#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/paint/paint_property_tree_builder.h"
#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
#include "third_party/blink/renderer/core/style/content_data.h"
@@ -146,24 +152,7 @@ LayoutObject* FindAncestorByPredicate(const LayoutObject* descendant,
if (skip_info)
skip_info->Update(*object);
- if (UNLIKELY(object->IsRenderedLegend())) {
- // According to the HTML standard, a rendered legend is a child of a
- // fieldset. However a rendered legend is a child of an anonymous fieldset
- // content box in a LayoutObject tree. NG fragment trees follow the
- // structure of the standard.
- //
- // The following code resolves this inconsistency, and we skip anonymous
- // fieldset content boxes if |descendant| is in a rendered legend. We also
- // need to skip flow threads, in case the containing fieldset also
- // establishes a multicol container.
- LayoutObject* legend_parent = object->Parent();
- while (legend_parent->IsAnonymous()) {
- if (skip_info)
- skip_info->Update(*legend_parent);
- object = legend_parent;
- legend_parent = legend_parent->Parent();
- }
- } else if (UNLIKELY(object->IsColumnSpanAll())) {
+ if (UNLIKELY(object->IsColumnSpanAll())) {
// The containing block chain goes directly from the column spanner to the
// multi-column container.
const auto* multicol_container =
@@ -180,6 +169,40 @@ LayoutObject* FindAncestorByPredicate(const LayoutObject* descendant,
return nullptr;
}
+inline bool MightTraversePhysicalFragments(const LayoutObject& obj) {
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled())
+ return false;
+ if (!obj.IsLayoutNGObject()) {
+ // Non-NG objects should be painted, hit-tested, etc. by legacy.
+ if (obj.IsBox())
+ return false;
+ // Non-LayoutBox objects (such as LayoutInline) don't necessarily create NG
+ // LayoutObjects. If they are laid out by an NG container, though, we may be
+ // allowed to traverse their fragments. We can't check that at this point
+ // (potentially before initial layout), though. Unless there are other
+ // reasons that prevent us from allowing fragment traversal, we'll
+ // optimistically return true now, and check later.
+ }
+ // The NG paint system currently doesn't support replaced content.
+ if (obj.IsLayoutReplaced())
+ return false;
+ // The NG paint system currently doesn't support table-cells.
+ if (obj.IsTableCellLegacy())
+ return false;
+ // Text controls have some logic in the layout objects that will be missed if
+ // we traverse the fragment tree when hit-testing.
+ if (obj.IsTextControlIncludingNG())
+ return false;
+ // If this object participates in legacy block fragmentation (but still is a
+ // LayoutNG object, which may happen if we're using a layout type not
+ // supported in the legacy engine, such as custom layout), do not attempt to
+ // fragment-traverse it.
+ if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled() &&
+ obj.IsInsideFlowThread())
+ return false;
+ return true;
+}
+
} // namespace
static int g_allow_destroying_layout_object_in_finalizer = 0;
@@ -424,18 +447,35 @@ bool LayoutObject::RequiresAnonymousTableWrappers(
#if DCHECK_IS_ON()
+void LayoutObject::AssertFragmentTree(bool display_locked) const {
+ NOT_DESTROYED();
+ for (const LayoutObject* layout_object = this; layout_object;) {
+ // If display-locked, fragments may not be removed from the tree even after
+ // the |LayoutObject| was destroyed, but still they should be consistent.
+ if (!display_locked && layout_object->ChildLayoutBlockedByDisplayLock()) {
+ layout_object->AssertFragmentTree(
+ /* display_locked */ true);
+ layout_object = layout_object->NextInPreOrderAfterChildren(this);
+ continue;
+ }
+
+ // Check the direct children of the fragment. Grand-children and further
+ // descendants will be checked by descendant LayoutObjects.
+ if (const auto* box = DynamicTo<LayoutBox>(layout_object)) {
+ for (const NGPhysicalBoxFragment& fragment : box->PhysicalFragments()) {
+ DCHECK_EQ(box, fragment.OwnerLayoutBox());
+ fragment.AssertFragmentTreeChildren(
+ /* allow_destroyed */ display_locked);
+ }
+ }
+ layout_object = layout_object->NextInPreOrder(this);
+ }
+}
+
void LayoutObject::AssertClearedPaintInvalidationFlags() const {
NOT_DESTROYED();
if (!PaintInvalidationStateIsDirty() || ChildPrePaintBlockedByDisplayLock())
return;
- // NG text objects are exempt, as pre-paint walking doesn't visit those with
- // no paint effects (only white-space, for instance).
- if ((IsText() && IsLayoutNGObject()) ||
- // and culled inline boxes too.
- (IsInLayoutNGInlineFormattingContext() && IsLayoutInline()) ||
- // TablesNG columns are also not visited.
- (IsLayoutTableCol() && IsLayoutNGObject()))
- return;
ShowLayoutTreeForThis();
NOTREACHED();
}
@@ -470,7 +510,42 @@ void LayoutObject::AddChild(LayoutObject* new_child,
children->InsertChildNode(this, table, before_child);
}
table->AddChild(new_child);
+ } else if (LIKELY(new_child->IsHorizontalWritingMode()) ||
+ !new_child->IsText()) {
+ children->InsertChildNode(this, new_child, before_child);
+ } else if (IsA<LayoutNGTextCombine>(*this)) {
+ DCHECK(LayoutNGTextCombine::ShouldBeParentOf(*new_child)) << new_child;
+ new_child->SetStyle(Style());
+ children->InsertChildNode(this, new_child, before_child);
+ } else if (LayoutNGTextCombine::ShouldBeParentOf(*new_child)) {
+ if (before_child) {
+ if (IsA<LayoutNGTextCombine>(before_child)) {
+ DCHECK(!DynamicTo<LayoutNGTextCombine>(before_child->PreviousSibling()))
+ << before_child->PreviousSibling();
+ before_child->AddChild(new_child, before_child->SlowFirstChild());
+ } else if (auto* const previous_sibling = DynamicTo<LayoutNGTextCombine>(
+ before_child->PreviousSibling())) {
+ previous_sibling->AddChild(new_child);
+ } else {
+ children->InsertChildNode(
+ this,
+ LayoutNGTextCombine::CreateAnonymous(To<LayoutText>(new_child)),
+ before_child);
+ }
+ } else if (auto* const last_child =
+ DynamicTo<LayoutNGTextCombine>(SlowLastChild())) {
+ last_child->AddChild(new_child);
+ } else if (UNLIKELY(IsHorizontalWritingMode())) {
+ // In case of <br style="writing-mode:vertical-rl">
+ // See http://crbug.com/1222121
+ children->InsertChildNode(this, new_child, before_child);
+ } else {
+ children->AppendChildNode(this, LayoutNGTextCombine::CreateAnonymous(
+ To<LayoutText>(new_child)));
+ }
} else {
+ DCHECK(!new_child->IsHorizontalWritingMode()) << new_child;
+ DCHECK(new_child->IsText()) << new_child;
children->InsertChildNode(this, new_child, before_child);
}
@@ -535,13 +610,7 @@ void LayoutObject::NotifyOfSubtreeChange() {
return;
if (bitfields_.NotifiedOfSubtreeChange())
return;
-
NotifyAncestorsOfSubtreeChange();
-
- // We can modify the layout tree during layout which means that we may
- // try to schedule this during performLayout. This should no longer
- // happen when crbug.com/370457 is fixed.
- DeprecatedScheduleStyleRecalcDuringLayout marker(GetDocument().Lifecycle());
GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}
@@ -571,6 +640,30 @@ LayoutObject* LayoutObject::NextInPreOrder() const {
return NextInPreOrderAfterChildren();
}
+bool LayoutObject::IsForElement() const {
+ if (!IsAnonymous()) {
+ return true;
+ }
+
+ // When a block is inside of an inline, the part of the inline that
+ // wraps the block is represented in the layout tree by a block that
+ // is marked as anonymous, but has a continuation that's not
+ // anonymous.
+
+ if (!IsBox()) {
+ return false;
+ }
+
+ auto* continuation = To<LayoutBox>(this)->Continuation();
+ if (!continuation || continuation->IsAnonymous()) {
+ return false;
+ }
+
+ DCHECK(continuation->IsInline());
+ DCHECK(IsLayoutBlockFlow());
+ return true;
+}
+
bool LayoutObject::HasClipRelatedProperty() const {
NOT_DESTROYED();
// This function detects a bunch of properties that can potentially affect
@@ -608,14 +701,6 @@ bool LayoutObject::IsRenderedLegendInternal() const {
if (!parent)
return false;
- // If there is a rendered legend, it will be found inside the anonymous
- // fieldset wrapper. If the anonymous fieldset wrapper is a multi-column,
- // the rendered legend will be found inside the multi-column flow thread.
- if (parent->IsLayoutFlowThread())
- parent = parent->Parent();
- if (parent->IsAnonymous() && parent->Parent()->IsLayoutNGFieldset())
- parent = parent->Parent();
-
const auto* parent_layout_block = DynamicTo<LayoutBlock>(parent);
return parent_layout_block && IsA<HTMLFieldSetElement>(parent->GetNode()) &&
LayoutFieldset::FindInFlowLegend(*parent_layout_block) == this;
@@ -632,7 +717,7 @@ bool LayoutObject::IsListMarkerForSummary() const {
ListMarker::ListStyleCategory::kSymbol)
return false;
const AtomicString& name =
- StyleRef().GetListStyleType()->GetCounterStyleName();
+ StyleRef().ListStyleType()->GetCounterStyleName();
return name == "disclosure-open" || name == "disclosure-closed";
}
return false;
@@ -862,9 +947,6 @@ PaintLayer* LayoutObject::PaintingLayer() const {
// be accessed through the associated out-of-flow placeholder's parent.
if (object.IsColumnSpanAll())
return object.SpannerPlaceholder();
- // Rendered legends paint through their fieldset container.
- if (object.IsRenderedLegend())
- return LayoutFieldset::FindLegendContainingBlock(To<LayoutBox>(object));
// Use ContainingBlock() instead of Parent() for floating objects to omit
// any self-painting layers of inline objects that don't paint the floating
// object. This is only needed for inline-level floats not managed by
@@ -1028,17 +1110,6 @@ static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
(style->HasAutoLeftAndRight() || style->HasAutoTopAndBottom()))
return false;
- if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled() &&
- object->IsLayoutNGObject())) {
- // We need to rebuild the entire NG fragment spine all the way from the root
- // (or at least the nearest self-painting paint layer), since we traverse
- // the fragments, and not objects. Fragment painting is initiated at
- // self-painting layers, but we cannot check if it's a self-painting layer
- // now, because it may cease to be one during layout (an object with clipped
- // overflow that no longer has content that requires it to clip).
- return false;
- }
-
if (const auto* layout_box = DynamicTo<LayoutBox>(object)) {
// In general we can't relayout a flex item independently of its container;
// not only is the result incorrect due to the override size that's set, it
@@ -1046,6 +1117,13 @@ static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
if (layout_box->IsFlexItemIncludingNG())
return false;
+ // Similarly to flex items, we can't relayout a grid item independently of
+ // its container. This also applies to out of flow items of the grid, as we
+ // need the cached information of the grid to recompute the out of flow
+ // item's containing block rect.
+ if (layout_box->ContainingBlock()->IsLayoutGridIncludingNG())
+ return false;
+
// In LayoutNG, if box has any OOF descendants, they are propagated to
// parent. Therefore, we must mark parent chain for layout.
if (const NGLayoutResult* layout_result =
@@ -1446,9 +1524,6 @@ LayoutBlock* LayoutObject::ContainingBlock(AncestorSkipInfo* skip_info) const {
LayoutObject* object;
if (IsColumnSpanAll()) {
object = SpannerPlaceholder()->ContainingBlock();
- } else if (IsRenderedLegend()) {
- return LayoutFieldset::FindLegendContainingBlock(To<LayoutBox>(*this),
- skip_info);
} else {
object = Parent();
if (!object && IsLayoutCustomScrollbarPart()) {
@@ -1475,6 +1550,14 @@ LayoutObject* LayoutObject::NonAnonymousAncestor() const {
return ancestor;
}
+LayoutObject* LayoutObject::NearestAncestorForElement() const {
+ NOT_DESTROYED();
+ LayoutObject* ancestor = Parent();
+ while (ancestor && !ancestor->IsForElement())
+ ancestor = ancestor->Parent();
+ return ancestor;
+}
+
LayoutBlock* LayoutObject::FindNonAnonymousContainingBlock(
LayoutObject* container,
AncestorSkipInfo* skip_info) {
@@ -1487,7 +1570,12 @@ LayoutBlock* LayoutObject::FindNonAnonymousContainingBlock(
if (container && !container->IsLayoutBlock())
container = container->ContainingBlock(skip_info);
- while (container && container->IsAnonymousBlock())
+ // Allow an NG anonymous wrapper of an inline to be the containing block if it
+ // is the direct child of a multicol. This avoids the multicol from
+ // incorrectly becoming the containing block in the case of an inline
+ // container.
+ while (container && container->IsAnonymousBlock() &&
+ !container->IsAnonymousNGMulticolInlineWrapper())
container = container->ContainingBlock(skip_info);
return DynamicTo<LayoutBlock>(container);
@@ -1517,17 +1605,15 @@ bool LayoutObject::ComputeIsFixedContainer(const ComputedStyle* style) const {
return true;
// https://www.w3.org/TR/css-transforms-1/#containing-block-for-all-descendants
- if (RuntimeEnabledFeatures::TransformInteropEnabled() &&
- style->TransformStyle3D() == ETransformStyle3D::kPreserve3d)
- return true;
-
if (style->HasTransformRelatedProperty()) {
if (!IsInline() || IsAtomicInlineLevel())
return true;
}
// https://www.w3.org/TR/css-contain-1/#containment-layout
- if (ShouldApplyPaintContainment(*style) ||
- ShouldApplyLayoutContainment(*style))
+ if (IsEligibleForPaintOrLayoutContainment() &&
+ (ShouldApplyPaintContainment(*style) ||
+ ShouldApplyLayoutContainment(*style) ||
+ style->WillChangeProperties().Contains(CSSPropertyID::kContain)))
return true;
// We intend to change behavior to set containing block based on computed
@@ -1535,10 +1621,14 @@ bool LayoutObject::ComputeIsFixedContainer(const ComputedStyle* style) const {
// above will return true if the *used* value of transform-style is
// preserve-3d, so to estimate compat we need to count if the line below is
// reached.
- if (style->TransformStyle3D() == ETransformStyle3D::kPreserve3d) {
+ if (style->TransformStyle3D() == ETransformStyle3D::kPreserve3d &&
+ (!IsInline() || IsAtomicInlineLevel())) {
UseCounter::Count(
GetDocument(),
WebFeature::kTransformStyleContainingBlockComputedUsedMismatch);
+ if (RuntimeEnabledFeatures::TransformInteropEnabled()) {
+ return true;
+ }
}
return false;
@@ -1839,13 +1929,6 @@ void LayoutObject::InvalidateDisplayItemClients(
ObjectPaintInvalidator(*this).InvalidateDisplayItemClient(*this, reason);
}
-bool LayoutObject::CompositedScrollsWithRespectTo(
- const LayoutBoxModelObject& paint_invalidation_container) const {
- NOT_DESTROYED();
- return paint_invalidation_container.UsesCompositedScrolling() &&
- this != &paint_invalidation_container;
-}
-
PhysicalRect LayoutObject::AbsoluteSelectionRect() const {
NOT_DESTROYED();
PhysicalRect selection_rect = LocalSelectionVisualRect();
@@ -2153,6 +2236,8 @@ const ComputedStyle& LayoutObject::SlowEffectiveStyle(
case NGStyleVariant::kStandard:
return StyleRef();
case NGStyleVariant::kFirstLine:
+ if (IsInline() && IsAtomicInlineLevel())
+ return StyleRef();
return FirstLineStyleRef();
case NGStyleVariant::kEllipsis:
// The ellipsis is styled according to the line style.
@@ -2295,6 +2380,16 @@ void LayoutObject::SetPseudoElementStyle(
return;
}
+ if (IsText() && UNLIKELY(IsA<LayoutNGTextCombine>(Parent()))) {
+ // See http://crbug.com/1222640
+ scoped_refptr<ComputedStyle> combined_text_style =
+ GetDocument().GetStyleResolver().CreateComputedStyle();
+ combined_text_style->InheritFrom(*pseudo_style);
+ StyleAdjuster::AdjustStyleForCombinedText(*combined_text_style);
+ SetStyle(std::move(combined_text_style));
+ return;
+ }
+
SetStyle(std::move(pseudo_style));
}
@@ -2652,6 +2747,8 @@ void LayoutObject::StyleWillChange(StyleDifference diff,
layer->DirtyVisibleContentStatus();
if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
cache->ChildrenChanged(this);
+ GetDocument().GetFrame()->GetInputMethodController().DidChangeVisibility(
+ *this);
}
if (IsFloating() &&
@@ -2720,16 +2817,6 @@ void LayoutObject::StyleWillChange(StyleDifference diff,
}
}
-void LayoutObject::ClearBaseComputedStyle() {
- NOT_DESTROYED();
- auto* element = DynamicTo<Element>(GetNode());
- if (!element)
- return;
-
- if (ElementAnimations* animations = element->GetElementAnimations())
- animations->ClearBaseComputedStyle();
-}
-
static bool AreNonIdenticalCursorListsEqual(const ComputedStyle* a,
const ComputedStyle* b) {
DCHECK_NE(a->Cursors(), b->Cursors());
@@ -2779,16 +2866,26 @@ void LayoutObject::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
NOT_DESTROYED();
if (HasHiddenBackface()) {
- bool preserve_3d =
- (Parent() && Parent()->StyleRef().UsedTransformStyle3D() ==
- ETransformStyle3D::kPreserve3d);
- if (style_->HasTransform() || preserve_3d) {
+ if (Parent() && Parent()->StyleRef().UsedTransformStyle3D() ==
+ ETransformStyle3D::kPreserve3d) {
UseCounter::Count(GetDocument(),
WebFeature::kHiddenBackfaceWithPossible3D);
- }
- if (preserve_3d) {
+ UseCounter::Count(GetDocument(), WebFeature::kHiddenBackfaceWith3D);
UseCounter::Count(GetDocument(),
WebFeature::kHiddenBackfaceWithPreserve3D);
+ } else if (style_->HasTransform()) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kHiddenBackfaceWithPossible3D);
+ // For consistency with existing code usage, this uses
+ // Has3DTransformOperation rather than the slightly narrower
+ // HasNonTrivial3DTransformOperation (which is only web-exposed for
+ // compositing decisions on low-end devices). However, given the
+ // discussion in https://github.com/w3c/csswg-drafts/issues/3305 it's
+ // possible we may want to tie backface-visibility behavior to something
+ // closer to the latter.
+ if (style_->Has3DTransformOperation()) {
+ UseCounter::Count(GetDocument(), WebFeature::kHiddenBackfaceWith3D);
+ }
}
}
@@ -2945,6 +3042,11 @@ void LayoutObject::PropagateStyleToAnonymousChildren() {
child_block_flow->IsAnonymousBlockContinuation())
new_style->SetPosition(child->StyleRef().GetPosition());
+ if (UNLIKELY(IsA<LayoutNGTextCombine>(child))) {
+ // "text-combine-width-after-style-change.html" reaches here.
+ StyleAdjuster::AdjustStyleForTextCombine(*new_style);
+ }
+
UpdateAnonymousChildStyle(child, *new_style);
child->SetStyle(std::move(new_style));
@@ -3149,10 +3251,21 @@ void LayoutObject::MapLocalToAncestor(const LayoutBoxModelObject* ancestor,
// Text objects just copy their parent's computed style, so we need to ignore
// them.
bool use_transforms = !(mode & kIgnoreTransforms);
- bool preserve3d =
- use_transforms &&
- ((container->StyleRef().Preserves3D() && !container->IsText()) ||
- (StyleRef().Preserves3D() && !IsText()));
+
+ const bool container_preserves_3d =
+ container->StyleRef().Preserves3D() ||
+ (!RuntimeEnabledFeatures::TransformInteropEnabled() &&
+ !PaintPropertyTreeBuilder::NeedsTransform(*container,
+ CompositingReasons()));
+ // Just because container and this have preserve-3d doesn't mean all
+ // the DOM elements between them do. (We know they don't have a
+ // transform, though, since otherwise they'd be the container.)
+ const bool path_preserves_3d =
+ !RuntimeEnabledFeatures::TransformInteropEnabled() ||
+ container == NearestAncestorForElement();
+ const bool preserve3d = use_transforms && container_preserves_3d &&
+ !container->IsText() && path_preserves_3d;
+
if (use_transforms && ShouldUseTransformFromContainer(container)) {
TransformationMatrix t;
GetTransformFromContainer(container, container_offset, t);
@@ -3202,8 +3315,20 @@ void LayoutObject::MapAncestorToLocal(const LayoutBoxModelObject* ancestor,
PhysicalOffset container_offset = OffsetFromContainer(container);
bool use_transforms = !(mode & kIgnoreTransforms);
- bool preserve3d = use_transforms && (container->StyleRef().Preserves3D() ||
- StyleRef().Preserves3D());
+
+ // Just because container and this have preserve-3d doesn't mean all
+ // the DOM elements between them do. (We know they don't have a
+ // transform, though, since otherwise they'd be the container.)
+ if (RuntimeEnabledFeatures::TransformInteropEnabled() &&
+ container != NearestAncestorForElement()) {
+ transform_state.Move(PhysicalOffset(), TransformState::kFlattenTransform);
+ }
+
+ const bool preserve3d =
+ use_transforms && (StyleRef().Preserves3D() ||
+ (!RuntimeEnabledFeatures::TransformInteropEnabled() &&
+ !PaintPropertyTreeBuilder::NeedsTransform(
+ *this, CompositingReasons())));
if (use_transforms && ShouldUseTransformFromContainer(container)) {
TransformationMatrix t;
GetTransformFromContainer(container, container_offset, t);
@@ -3267,9 +3392,17 @@ void LayoutObject::GetTransformFromContainer(
bool has_perspective = container_object && container_object->HasLayer() &&
container_object->StyleRef().HasPerspective();
- if (has_perspective && RuntimeEnabledFeatures::TransformInteropEnabled() &&
- container_object != NonAnonymousAncestor())
- has_perspective = false;
+ if (has_perspective && container_object != NearestAncestorForElement()) {
+ if (RuntimeEnabledFeatures::TransformInteropEnabled()) {
+ has_perspective = false;
+ }
+
+ if (StyleRef().Preserves3D() || transform.M13() != 0.0 ||
+ transform.M23() != 0.0 || transform.M43() != 0.0) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kDifferentPerspectiveCBOrParent);
+ }
+ }
if (has_perspective) {
// Perspective on the container affects us, so we have to factor it in here.
@@ -3280,7 +3413,7 @@ void LayoutObject::GetTransformFromContainer(
TransformationMatrix perspective_matrix;
perspective_matrix.ApplyPerspective(
- container_object->StyleRef().Perspective());
+ container_object->StyleRef().UsedPerspective());
perspective_matrix.ApplyTransformOrigin(perspective_origin.X(),
perspective_origin.Y(), 0);
@@ -3442,7 +3575,7 @@ PhysicalOffset LayoutObject::OffsetFromScrollableContainer(
DCHECK(container->IsScrollContainer());
const auto* box = To<LayoutBox>(container);
if (!ignore_scroll_offset)
- return -PhysicalOffset(box->ScrolledContentOffset());
+ return -box->ScrolledContentOffset();
// ScrollOrigin accounts for other writing modes whose content's origin is not
// at the top-left.
@@ -3544,8 +3677,7 @@ LayoutObject* LayoutObject::Container(AncestorSkipInfo* skip_info) const {
return multicol_container;
}
- if ((IsFloating() && !IsInLayoutNGInlineFormattingContext()) ||
- IsRenderedLegend())
+ if (IsFloating() && !IsInLayoutNGInlineFormattingContext())
return ContainingBlock(skip_info);
return Parent();
@@ -3624,6 +3756,9 @@ void LayoutObject::InsertedIntoTree() {
// FIXME: We should DCHECK(isRooted()) here but generated content makes some
// out-of-order insertion.
+ bitfields_.SetMightTraversePhysicalFragments(
+ MightTraversePhysicalFragments(*this));
+
// Keep our layer hierarchy updated. Optimize for the common case where we
// don't have any children and don't have a layer attached to ourselves.
PaintLayer* layer = nullptr;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object.h b/chromium/third_party/blink/renderer/core/layout/layout_object.h
index 1b455af12f9..930ce9f4c04 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.h
@@ -506,6 +506,13 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
}
+ // This function checks if the fragment tree is consistent with the
+ // |LayoutObject| tree. This consistency is critical, as sometimes we traverse
+ // the fragment tree, sometimes the |LayoutObject| tree, or mix the
+ // traversals. Also we rely on the consistency to avoid using fragments whose
+ // |LayoutObject| were destroyed.
+ void AssertFragmentTree(bool display_locked = false) const;
+
void AssertClearedPaintInvalidationFlags() const;
void AssertSubtreeClearedPaintInvalidationFlags() const {
@@ -581,10 +588,15 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return fragment_.UniqueId();
}
+ inline bool IsEligibleForPaintOrLayoutContainment() const {
+ NOT_DESTROYED();
+ return (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() &&
+ (!IsTablePart() || IsLayoutBlockFlow());
+ }
+
inline bool ShouldApplyPaintContainment(const ComputedStyle& style) const {
NOT_DESTROYED();
- return style.ContainsPaint() && (!IsInline() || IsAtomicInlineLevel()) &&
- !IsRubyText() && (!IsTablePart() || IsLayoutBlockFlow());
+ return style.ContainsPaint() && IsEligibleForPaintOrLayoutContainment();
}
inline bool ShouldApplyPaintContainment() const {
@@ -594,8 +606,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
inline bool ShouldApplyLayoutContainment(const ComputedStyle& style) const {
NOT_DESTROYED();
- return style.ContainsLayout() && (!IsInline() || IsAtomicInlineLevel()) &&
- !IsRubyText() && (!IsTablePart() || IsLayoutBlockFlow());
+ return style.ContainsLayout() && IsEligibleForPaintOrLayoutContainment();
}
inline bool ShouldApplyLayoutContainment() const {
@@ -614,13 +625,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
inline bool ShouldApplyInlineSizeContainment() const {
NOT_DESTROYED();
- return (StyleRef().ContainsInlineSize() || StyleRef().ContainsSize()) &&
- IsEligibleForSizeContainment();
+ return StyleRef().ContainsInlineSize() && IsEligibleForSizeContainment();
}
inline bool ShouldApplyBlockSizeContainment() const {
NOT_DESTROYED();
- return (StyleRef().ContainsBlockSize() || StyleRef().ContainsSize()) &&
- IsEligibleForSizeContainment();
+ return StyleRef().ContainsBlockSize() && IsEligibleForSizeContainment();
}
inline bool ShouldApplyStyleContainment() const {
NOT_DESTROYED();
@@ -628,18 +637,24 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
inline bool ShouldApplyContentContainment() const {
NOT_DESTROYED();
- return ShouldApplyPaintContainment() && ShouldApplyLayoutContainment();
+ return ShouldApplyStyleContainment() && ShouldApplyPaintContainment() &&
+ ShouldApplyLayoutContainment();
}
inline bool ShouldApplyStrictContainment() const {
NOT_DESTROYED();
- return ShouldApplyPaintContainment() && ShouldApplyLayoutContainment() &&
- ShouldApplySizeContainment();
+ return ShouldApplyStyleContainment() && ShouldApplyPaintContainment() &&
+ ShouldApplyLayoutContainment() && ShouldApplySizeContainment();
}
+ inline bool ShouldApplyAnyContainment() const {
+ NOT_DESTROYED();
+ return ShouldApplyPaintContainment() || ShouldApplyLayoutContainment() ||
+ ShouldApplyStyleContainment() || ShouldApplyBlockSizeContainment() ||
+ ShouldApplyInlineSizeContainment();
+ }
+
inline bool IsContainerForContainerQueries() const {
NOT_DESTROYED();
- return ShouldApplyLayoutContainment() && ShouldApplyStyleContainment() &&
- (ShouldApplyInlineSizeContainment() ||
- ShouldApplyBlockSizeContainment());
+ return StyleRef().IsContainerForContainerQueries();
}
inline bool IsStackingContext() const {
@@ -849,6 +864,10 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
NOT_DESTROYED();
return IsOfType(kLayoutObjectNGText);
}
+ bool IsLayoutNGTextCombine() const {
+ NOT_DESTROYED();
+ return IsOfType(kLayoutObjectNGTextCombine);
+ }
bool IsLayoutTableCol() const {
NOT_DESTROYED();
return IsOfType(kLayoutObjectTableCol);
@@ -1335,6 +1354,14 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
StyleRef().StyleType() == kPseudoIdNone && IsLayoutBlock() &&
!IsLayoutFlowThread() && !IsLayoutMultiColumnSet();
}
+ // This is similar to the negation of IsAnonymous, with a single difference.
+ // When a block is inside an inline, there is an anonymous block that is a
+ // continuation of the inline, wrapping the block that is inside it, as
+ // https://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level describes.
+ // That anonymous block also returns true here. This allows us to track
+ // when layout object parent-child relationships correspond to DOM
+ // parent-child relationships.
+ bool IsForElement() const;
// If node has been split into continuations, it returns the first layout
// object generated for the node.
const LayoutObject* ContinuationRoot() const {
@@ -1998,11 +2025,19 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// object, when it comes to painting, hit-testing and other layout read
// operations. If false is returned, we need to traverse the layout object
// tree instead.
- //
- // It is not allowed to call this method on a non-LayoutBox object, unless its
- // containing block is an NG object (e.g. not allowed to call it on a
- // LayoutInline that's contained by a legacy LayoutBlockFlow).
- inline bool CanTraversePhysicalFragments() const;
+ bool CanTraversePhysicalFragments() const {
+ NOT_DESTROYED();
+
+ if (!bitfields_.MightTraversePhysicalFragments())
+ return false;
+
+ // Non-LayoutBox objects (such as LayoutInline) don't necessarily create NG
+ // LayoutObjects. We'll allow traversing their fragments if they are laid
+ // out by an NG container.
+ if (!IsBox())
+ return IsInLayoutNGInlineFormattingContext();
+ return true;
+ }
// Return true if |this| produces one or more inline fragments, including
// whitespace-only text fragments.
@@ -2237,8 +2272,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
void SetModifiedStyleOutsideStyleRecalc(scoped_refptr<const ComputedStyle>,
ApplyStyleChanges);
- void ClearBaseComputedStyle();
-
// This function returns an enclosing non-anonymous LayoutBlock for this
// element. This function is not always returning the containing block as
// defined by CSS. In particular:
@@ -2265,10 +2298,14 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
LayoutObject* container,
AncestorSkipInfo* = nullptr);
- // Returns the nearest anceestor in the layout tree that is not anonymous,
+ // Returns the nearest ancestor in the layout tree that is not anonymous,
// or null if there is none.
LayoutObject* NonAnonymousAncestor() const;
+ // Returns the nearest ancestor in the layout tree that IsForElement(),
+ // or null if there is none.
+ LayoutObject* NearestAncestorForElement() const;
+
const LayoutBlock* InclusiveContainingBlock() const;
const LayoutBlock* EnclosingScrollportBox() const;
@@ -3261,9 +3298,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bitfields_.SetScrollAnchorDisablingStyleChanged(changed);
}
- bool CompositedScrollsWithRespectTo(
- const LayoutBoxModelObject& paint_invalidation_container) const;
-
BackgroundPaintLocation GetBackgroundPaintLocation() const {
NOT_DESTROYED();
return bitfields_.GetBackgroundPaintLocation();
@@ -3452,6 +3486,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectNGOutsideListMarker,
kLayoutObjectNGProgress,
kLayoutObjectNGText,
+ kLayoutObjectNGTextCombine,
kLayoutObjectNGTextControlMultiLine,
kLayoutObjectNGTextControlSingleLine,
kLayoutObjectOutsideListMarker,
@@ -3621,6 +3656,15 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bitfields_.SetBackgroundIsKnownToBeObscured(b);
}
+ bool IsAnonymousNGMulticolInlineWrapper() const {
+ NOT_DESTROYED();
+ return bitfields_.IsAnonymousNGMulticolInlineWrapper();
+ }
+ void SetIsAnonymousNGMulticolInlineWrapper() {
+ NOT_DESTROYED();
+ bitfields_.SetIsAnonymousNGMulticolInlineWrapper(true);
+ }
+
// Returns ContainerForAbsolutePosition() if it's a LayoutBlock, or the
// containing LayoutBlock of it.
LayoutBlock* ContainingBlockForAbsolutePosition(
@@ -3847,6 +3891,8 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
should_skip_next_layout_shift_tracking_(true),
should_assume_paint_offset_translation_for_layout_shift_tracking_(
false),
+ might_traverse_physical_fragments_(false),
+ is_anonymous_ng_multicol_inline_wrapper_(false),
positioned_state_(kIsStaticallyPositioned),
selection_state_(static_cast<unsigned>(SelectionState::kNone)),
subtree_paint_property_update_reasons_(
@@ -4176,6 +4222,16 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
should_assume_paint_offset_translation_for_layout_shift_tracking_,
ShouldAssumePaintOffsetTranslationForLayoutShiftTracking);
+ // True if there's a possibility that we can walk NG fragment children of
+ // this object. False if we definitely need to walk the LayoutObject tree.
+ ADD_BOOLEAN_BITFIELD(might_traverse_physical_fragments_,
+ MightTraversePhysicalFragments);
+
+ // True if this is an anonymous inline wrapper created for NG, and the
+ // wrapper is a direct child of a multicol.
+ ADD_BOOLEAN_BITFIELD(is_anonymous_ng_multicol_inline_wrapper_,
+ IsAnonymousNGMulticolInlineWrapper);
+
private:
// This is the cached 'position' value of this object
// (see ComputedStyle::position).
@@ -4360,32 +4416,6 @@ inline bool LayoutObject::IsBeforeOrAfterContent() const {
return IsBeforeContent() || IsAfterContent();
}
-inline bool LayoutObject::CanTraversePhysicalFragments() const {
- if (LIKELY(!RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled()))
- return false;
- // Non-NG objects should be painted by legacy.
- if (!IsLayoutNGObject()) {
- if (IsBox())
- return false;
- // Non-LayoutBox objects (such as LayoutInline) don't necessarily create NG
- // LayoutObjects. If they are laid out by an NG container, though, we may be
- // allowed to traverse their fragments. Otherwise, bail now.
- if (!IsInLayoutNGInlineFormattingContext())
- return false;
- }
- // The NG paint system currently doesn't support replaced content.
- if (IsLayoutReplaced())
- return false;
- // The NG paint system currently doesn't support table-cells.
- if (IsTableCellLegacy())
- return false;
- // Text controls have some logic in the layout objects that will be missed if
- // we traverse the fragment tree when hit-testing.
- if (IsTextControlIncludingNG())
- return false;
- return true;
-}
-
// setNeedsLayout() won't cause full paint invalidations as
// setNeedsLayoutAndFullPaintInvalidation() does. Otherwise the two methods are
// identical.
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 c4bd22a942e..9f639415066 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
@@ -28,6 +28,7 @@
#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/html/html_element.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"
@@ -271,8 +272,11 @@ void LayoutObjectChildList::InsertChildNode(LayoutObject* owner,
void LayoutObjectChildList::InvalidatePaintOnRemoval(LayoutObject& old_child) {
if (!old_child.IsRooted())
return;
- if (old_child.IsBody() && old_child.View())
+ if (old_child.View() &&
+ (old_child.IsBody() || old_child.IsDocumentElement())) {
old_child.View()->SetShouldDoFullPaintInvalidation();
+ old_child.View()->SetBackgroundNeedsFullPaintInvalidation();
+ }
ObjectPaintInvalidator paint_invalidator(old_child);
paint_invalidator.SlowSetPaintingLayerNeedsRepaint();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
index abc044d9399..3bf1b87e5c7 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
@@ -4,11 +4,13 @@
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_button.h"
+#include "third_party/blink/renderer/core/layout/layout_counter.h"
#include "third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h"
#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
#include "third_party/blink/renderer/core/layout/layout_file_upload_control.h"
@@ -34,6 +36,7 @@
#include "third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h"
#include "third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_br.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_counter.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_word_break.h"
@@ -249,6 +252,22 @@ LayoutObject* LayoutObjectFactory::CreateButton(Node& node,
return CreateObject<LayoutBlock, LayoutNGButton, LayoutButton>(node, legacy);
}
+LayoutObject* LayoutObjectFactory::CreateCounter(
+ PseudoElement& pseduo,
+ const CounterContentData& counter,
+ LegacyLayout legacy) {
+ bool force_legacy = false;
+ if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+ force_legacy = legacy == LegacyLayout::kForce;
+ if (!force_legacy)
+ return new LayoutNGCounter(pseduo, counter);
+ }
+ auto* const new_object = new LayoutCounter(pseduo, counter);
+ if (force_legacy)
+ new_object->SetForceLegacyLayout();
+ return new_object;
+}
+
LayoutBlock* LayoutObjectFactory::CreateFieldset(Node& node,
const ComputedStyle& style,
LegacyLayout legacy) {
@@ -314,7 +333,16 @@ LayoutText* LayoutObjectFactory::CreateTextCombine(
Node* node,
scoped_refptr<StringImpl> str,
LegacyLayout legacy) {
- return new LayoutTextCombine(node, str);
+ bool force_legacy = false;
+ if (RuntimeEnabledFeatures::LayoutNGTextCombineEnabled()) {
+ force_legacy = legacy == LegacyLayout::kForce;
+ if (!force_legacy)
+ return new LayoutNGText(node, str);
+ }
+ LayoutText* const layout_text = new LayoutTextCombine(node, str);
+ if (force_legacy)
+ layout_text->SetForceLegacyLayout();
+ return layout_text;
}
LayoutTextFragment* LayoutObjectFactory::CreateTextFragment(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
index 19fb64c0b5b..7eb5911b3dd 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
@@ -12,6 +12,7 @@
namespace blink {
class ComputedStyle;
+class CounterContentData;
class HTMLElement;
class LayoutBlock;
class LayoutBlockFlow;
@@ -24,6 +25,7 @@ class LayoutTableCaption;
class LayoutText;
class LayoutTextFragment;
class Node;
+class PseudoElement;
// 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
@@ -70,6 +72,9 @@ class LayoutObjectFactory {
static LayoutObject* CreateButton(Node& node,
const ComputedStyle& style,
LegacyLayout legacy);
+ static LayoutObject* CreateCounter(PseudoElement& pseduo,
+ const CounterContentData& counter,
+ LegacyLayout legacy);
static LayoutBlock* CreateFieldset(Node&, const ComputedStyle&, LegacyLayout);
static LayoutBlockFlow* CreateFileUploadControl(Node& node,
const ComputedStyle& style,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_factory_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_object_factory_test.cc
index c1e8762c8da..76b4e0ec5ba 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_factory_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory_test.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
+#include "third_party/blink/renderer/core/layout/layout_counter.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -35,30 +37,82 @@ TEST_P(LayoutObjectFactoryTest, BR) {
EXPECT_FALSE(layout_object.IsLayoutNGObject());
}
+// http://crbug.com/1060007
+TEST_P(LayoutObjectFactoryTest, Counter) {
+ InsertStyleElement(
+ "li::before { content: counter(i, upper-roman); }"
+ "ol { list-style: none; ");
+ SetBodyInnerHTML("<ol><li id=sample>one</li></ol>");
+ const auto& sample_layout_object = *GetLayoutObjectByElementId("sample");
+ const auto& sample = *GetElementById("sample");
+ const auto& psedo = *sample.GetPseudoElement(kPseudoIdBefore);
+ const auto& counter_layout_object =
+ *To<LayoutCounter>(psedo.GetLayoutObject()->SlowFirstChild());
+
+ if (LayoutNGEnabled()) {
+ EXPECT_EQ(R"DUMP(
+LayoutNGListItem LI id="sample"
+ +--LayoutInline ::before
+ | +--LayoutCounter (anonymous) "0"
+ +--LayoutText #text "one"
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ EXPECT_TRUE(counter_layout_object.IsLayoutNGObject());
+ } else {
+ EXPECT_EQ(R"DUMP(
+LayoutListItem LI id="sample"
+ +--LayoutInline ::before
+ | +--LayoutCounter (anonymous) "0"
+ +--LayoutText #text "one"
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ EXPECT_FALSE(counter_layout_object.IsLayoutNGObject());
+ }
+}
+
TEST_P(LayoutObjectFactoryTest, TextCombineInHorizontal) {
InsertStyleElement(
"div { writing-mode: horizontal-tb; }"
- "tyc { text-combine-upright: all; }");
- SetBodyInnerHTML("<div><tyc id=sample>ab</tyc></div>");
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML("<div><tcy id=sample>ab</tcy></div>");
const auto& sample_layout_object = *GetLayoutObjectByElementId("sample");
- EXPECT_EQ(R"DUMP(
-LayoutInline TYC id="sample"
+
+ if (RuntimeEnabledFeatures::LayoutNGTextCombineEnabled()) {
+ EXPECT_EQ(R"DUMP(
+LayoutInline TCY id="sample"
+ +--LayoutText #text "ab"
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ } else {
+ EXPECT_EQ(R"DUMP(
+LayoutInline TCY id="sample"
+--LayoutTextCombine #text "ab"
)DUMP",
- ToSimpleLayoutTree(sample_layout_object));
+ ToSimpleLayoutTree(sample_layout_object));
+ }
}
TEST_P(LayoutObjectFactoryTest, TextCombineInVertical) {
InsertStyleElement(
"div { writing-mode: vertical-rl; }"
- "tyc { text-combine-upright: all; }");
- SetBodyInnerHTML("<div><tyc id=sample>ab</tyc></div>");
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML("<div><tcy id=sample>ab</tcy></div>");
const auto& sample_layout_object = *GetLayoutObjectByElementId("sample");
- EXPECT_EQ(R"DUMP(
-LayoutInline TYC id="sample"
+
+ if (RuntimeEnabledFeatures::LayoutNGTextCombineEnabled()) {
+ EXPECT_EQ(R"DUMP(
+LayoutInline TCY id="sample"
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutText #text "ab"
+)DUMP",
+ ToSimpleLayoutTree(sample_layout_object));
+ } else {
+ EXPECT_EQ(R"DUMP(
+LayoutInline TCY id="sample"
+--LayoutTextCombine #text "ab"
)DUMP",
- ToSimpleLayoutTree(sample_layout_object));
+ ToSimpleLayoutTree(sample_layout_object));
+ }
}
TEST_P(LayoutObjectFactoryTest, WordBreak) {
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 a8fcf6aa55f..f47b54f869d 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
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.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/loader/resource/image_resource_content.h"
@@ -40,6 +41,17 @@ class LayoutObjectTest : public RenderingTest {
void ExpectAnonymousInlineWrapperFor(Node*);
};
+class LayoutObjectTestWithCompositing : public LayoutObjectTest {
+ public:
+ LayoutObjectTestWithCompositing() = default;
+
+ protected:
+ void SetUp() override {
+ EnableCompositing();
+ LayoutObjectTest::SetUp();
+ }
+};
+
template <bool should_have_wrapper>
void LayoutObjectTest::ExpectAnonymousInlineWrapperFor(Node* node) {
ASSERT_TRUE(node);
@@ -234,9 +246,8 @@ TEST_F(LayoutObjectTest, UseCountContainWithoutContentVisibility) {
target->classList().Add("strict");
UpdateAllLifecyclePhasesForTest();
- // Strict should register, but without style containment the "all" bucket is
- // not counted.
- EXPECT_FALSE(GetDocument().IsUseCounted(
+ // Strict should register, and all is counted.
+ EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kCSSContainAllWithoutContentVisibility));
EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kCSSContainStrictWithoutContentVisibility));
@@ -253,6 +264,7 @@ TEST_F(LayoutObjectTest, UseCountContainWithoutContentVisibility) {
}
TEST_F(LayoutObjectTest, UseCountContainingBlockFixedPosUnderFlattened3D) {
+ ScopedTransformInteropForTest disabled(false);
SetBodyInnerHTML(R"HTML(
<div style='transform-style: preserve-3d; opacity: 0.9'>
<div id=target style='position:fixed'></div>
@@ -266,6 +278,22 @@ TEST_F(LayoutObjectTest, UseCountContainingBlockFixedPosUnderFlattened3D) {
WebFeature::kTransformStyleContainingBlockComputedUsedMismatch));
}
+TEST_F(LayoutObjectTest,
+ UseCountContainingBlockFixedPosUnderFlattened3DTransformInterop) {
+ ScopedTransformInteropForTest enabled(true);
+ SetBodyInnerHTML(R"HTML(
+ <div style='transform-style: preserve-3d; opacity: 0.9'>
+ <div id=target style='position:fixed'></div>
+ </div>
+ )HTML");
+
+ LayoutObject* target = GetLayoutObjectByElementId("target");
+ EXPECT_EQ(target->View(), target->GetDocument().GetLayoutView());
+
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kTransformStyleContainingBlockComputedUsedMismatch));
+}
+
// Containing block test.
TEST_F(LayoutObjectTest, ContainingBlockLayoutViewShouldBeNull) {
EXPECT_EQ(nullptr, GetLayoutView().ContainingBlock());
@@ -1589,4 +1617,83 @@ TEST_F(LayoutObjectTest,
target->LocalToAncestorRect(rect, nullptr, 0));
}
+static const char* const kTransformsWith3D[] = {"transform: rotateX(20deg)",
+ "transform: translateZ(30px)"};
+static const char kTransformWithout3D[] =
+ "transform: matrix(2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2)";
+static const char kPreserve3D[] = "transform-style: preserve-3d";
+
+TEST_F(LayoutObjectTestWithCompositing,
+ UseCountDifferentPerspectiveCBOrParent) {
+ // Start with a case that has no containing block / parent difference.
+ SetBodyInnerHTML(R"HTML(
+ <div style='perspective: 200px'>
+ <div id=target></div>
+ </div>
+ )HTML");
+
+ auto* target = GetDocument().getElementById("target");
+
+ target->setAttribute(html_names::kStyleAttr, kTransformsWith3D[0]);
+ UpdateAllLifecyclePhasesForTest();
+ target->scrollIntoView();
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+
+ target->setAttribute(html_names::kStyleAttr, kPreserve3D);
+ UpdateAllLifecyclePhasesForTest();
+ target->scrollIntoView();
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+
+ target = nullptr;
+
+ // Switch to a case that has a difference between containing block and parent.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .abs { position: absolute; top: 0; left: 0; }
+ </style>
+ <div style='perspective: 200px; position: relative'>
+ <div>
+ <div class=abs id=target></div>
+ </div>
+ </div>
+ )HTML");
+
+ target = GetDocument().getElementById("target");
+
+ target->setAttribute(html_names::kStyleAttr, kTransformWithout3D);
+ UpdateAllLifecyclePhasesForTest();
+ target->scrollIntoView();
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+
+ target->setAttribute(html_names::kStyleAttr, kTransformsWith3D[0]);
+ UpdateAllLifecyclePhasesForTest();
+ target->scrollIntoView();
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+ GetDocument().ClearUseCounterForTesting(
+ WebFeature::kDifferentPerspectiveCBOrParent);
+
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+
+ target->setAttribute(html_names::kStyleAttr, kTransformsWith3D[1]);
+ UpdateAllLifecyclePhasesForTest();
+ target->scrollIntoView();
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+ GetDocument().ClearUseCounterForTesting(
+ WebFeature::kDifferentPerspectiveCBOrParent);
+
+ target->setAttribute(html_names::kStyleAttr, kPreserve3D);
+ UpdateAllLifecyclePhasesForTest();
+ target->scrollIntoView();
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kDifferentPerspectiveCBOrParent));
+ GetDocument().ClearUseCounterForTesting(
+ WebFeature::kDifferentPerspectiveCBOrParent);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_quote.cc b/chromium/third_party/blink/renderer/core/layout/layout_quote.cc
index bbcd2f71390..2d7b07bd233 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_quote.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_quote.cc
@@ -23,10 +23,11 @@
#include <algorithm>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.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/layout_ng_text_combine.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -287,7 +288,9 @@ void LayoutQuote::UpdateText() {
LayoutTextFragment* fragment = FindFragmentChild();
if (fragment) {
- fragment->SetStyle(Style());
+ fragment->SetStyle(IsA<LayoutNGTextCombine>(fragment->Parent())
+ ? fragment->Parent()->Style()
+ : Style());
fragment->SetContentString(text_.Impl());
} else {
LegacyLayout legacy =
@@ -301,13 +304,13 @@ void LayoutQuote::UpdateText() {
LayoutTextFragment* LayoutQuote::FindFragmentChild() const {
NOT_DESTROYED();
- // We walk from the end of the child list because, if we've had a first-letter
- // LayoutObject inserted then the remaining text will be at the end.
- while (LayoutObject* child = LastChild()) {
- if (auto* fragment = DynamicTo<LayoutTextFragment>(child))
- return fragment;
- }
-
+ // TODO(yosin): Once we support ::first-letter for <q>, we should change
+ // this function. See http://crbug.com/1206577
+ auto* const last_child = LastChild();
+ if (auto* fragment = DynamicTo<LayoutTextFragment>(last_child))
+ return fragment;
+ if (auto* combine = DynamicTo<LayoutNGTextCombine>(last_child))
+ return DynamicTo<LayoutTextFragment>(combine->FirstChild());
return nullptr;
}
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 8f9f6f4122d..f9255674d5d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -147,7 +147,7 @@ bool LayoutReplaced::HasReplacedLogicalHeight() const {
}
if (StyleRef().LogicalHeight().IsContentOrIntrinsicOrFillAvailable())
- return true;
+ return StyleRef().AspectRatio().IsAuto();
return false;
}
@@ -645,9 +645,9 @@ PhysicalRect LayoutReplaced::ComputeObjectFit(
// intrinsic ratio but no intrinsic size. In order to maintain aspect ratio,
// the intrinsic size for SVG might be faked from the aspect ratio,
// see SVGImage::containerSize().
- LayoutSize intrinsic_size =
- overridden_intrinsic_size ? *overridden_intrinsic_size : IntrinsicSize();
- if (!intrinsic_size.Width() || !intrinsic_size.Height())
+ PhysicalSize intrinsic_size(
+ overridden_intrinsic_size ? *overridden_intrinsic_size : IntrinsicSize());
+ if (intrinsic_size.IsEmpty())
return content_rect;
PhysicalSize scaled_intrinsic_size(intrinsic_size);
@@ -664,9 +664,9 @@ PhysicalRect LayoutReplaced::ComputeObjectFit(
case EObjectFit::kContain:
case EObjectFit::kCover:
final_rect.size = final_rect.size.FitToAspectRatio(
- scaled_intrinsic_size, object_fit == EObjectFit::kCover
- ? kAspectRatioFitGrow
- : kAspectRatioFitShrink);
+ intrinsic_size, object_fit == EObjectFit::kCover
+ ? kAspectRatioFitGrow
+ : kAspectRatioFitShrink);
if (object_fit != EObjectFit::kScaleDown ||
final_rect.Width() <= scaled_intrinsic_size.width)
break;
@@ -714,8 +714,10 @@ void LayoutReplaced::ComputeIntrinsicSizingInfo(
aspect_ratio.GetRatio().Width());
intrinsic_sizing_info.aspect_ratio.SetHeight(
aspect_ratio.GetRatio().Height());
- if (!IsHorizontalWritingMode())
- intrinsic_sizing_info.Transpose();
+ if (!IsHorizontalWritingMode()) {
+ intrinsic_sizing_info.aspect_ratio =
+ intrinsic_sizing_info.aspect_ratio.TransposedSize();
+ }
}
if (aspect_ratio.GetType() == EAspectRatioType::kRatio)
return;
@@ -882,10 +884,20 @@ LayoutUnit LayoutReplaced::ComputeReplacedLogicalHeight(
return ComputeReplacedLogicalHeightRespectingMinMaxHeight(
LayoutUnit(constrained_size.Height()));
+ absl::optional<double> aspect_ratio;
+ if (!intrinsic_sizing_info.aspect_ratio.IsEmpty()) {
+ aspect_ratio = intrinsic_sizing_info.aspect_ratio.Height() /
+ intrinsic_sizing_info.aspect_ratio.Width();
+ } else if (!StyleRef().AspectRatio().IsAuto() &&
+ !intrinsic_sizing_info.has_height &&
+ intrinsic_sizing_info.has_width) {
+ aspect_ratio = StyleRef().AspectRatio().GetRatio().Height() /
+ StyleRef().AspectRatio().GetRatio().Width();
+ }
// Otherwise, if 'height' has a computed value of 'auto', and the element has
// an intrinsic ratio then the used value of 'height' is:
// (used width) / (intrinsic ratio)
- if (!intrinsic_sizing_info.aspect_ratio.IsEmpty()) {
+ if (aspect_ratio) {
LayoutUnit used_width =
estimated_used_width ? estimated_used_width : AvailableLogicalWidth();
NGBoxStrut border_padding(BorderStart() + ComputedCSSPaddingStart(),
@@ -898,10 +910,8 @@ LayoutUnit LayoutReplaced::ComputeReplacedLogicalHeight(
used_width += border_padding.InlineSum();
if (StyleRef().AspectRatio().GetType() == EAspectRatioType::kRatio)
box_sizing = StyleRef().BoxSizing();
- double aspect_ratio = intrinsic_sizing_info.aspect_ratio.Height() /
- intrinsic_sizing_info.aspect_ratio.Width();
return ComputeReplacedLogicalHeightRespectingMinMaxHeight(
- BlockSizeFromAspectRatio(border_padding, aspect_ratio, box_sizing,
+ BlockSizeFromAspectRatio(border_padding, *aspect_ratio, box_sizing,
used_width) -
border_padding.BlockSum());
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc b/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc
index 59a1a01a033..07d52240ca2 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
index db4ebbddeed..b3ab9bc9a45 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -143,8 +143,6 @@ LayoutShiftTracker::LayoutShiftTracker(LocalFrameView* frame_view)
// SVGImage::DataChanged.
is_active_(
!frame_view->GetFrame().GetChromeClient().IsSVGImageChromeClient()),
- enable_m90_improvements_(
- base::FeatureList::IsEnabled(features::kCLSM90Improvements)),
score_(0.0),
weighted_score_(0.0),
timer_(frame_view->GetFrame().GetTaskRunner(TaskType::kInternalDefault),
@@ -175,13 +173,11 @@ bool LayoutShiftTracker::NeedsToTrack(const LayoutObject& object) const {
return false;
if (object.IsBR())
return false;
- if (enable_m90_improvements_) {
- if (To<LayoutText>(object).ContainsOnlyWhitespaceOrNbsp() ==
- OnlyWhitespaceOrNbsp::kYes)
- return false;
- if (object.StyleRef().GetFont().ShouldSkipDrawing())
- return false;
- }
+ if (To<LayoutText>(object).ContainsOnlyWhitespaceOrNbsp() ==
+ OnlyWhitespaceOrNbsp::kYes)
+ return false;
+ if (object.StyleRef().GetFont().ShouldSkipDrawing())
+ return false;
return true;
}
@@ -216,7 +212,7 @@ bool LayoutShiftTracker::NeedsToTrack(const LayoutObject& object) const {
return false;
}
- if (enable_m90_improvements_ && box.IsLayoutBlock()) {
+ if (box.IsLayoutBlock()) {
// Just check the simplest case. For more complex cases, we should suggest
// the developer to use visibility:hidden.
if (To<LayoutBlock>(box).FirstChild())
@@ -238,6 +234,7 @@ void LayoutShiftTracker::ObjectShifted(
const FloatPoint& old_starting_point,
const FloatSize& translation_delta,
const FloatSize& scroll_delta,
+ const FloatSize& scroll_anchor_adjustment,
const FloatPoint& new_starting_point) {
// The caller should ensure these conditions.
DCHECK(!old_rect.IsEmpty());
@@ -246,25 +243,30 @@ void LayoutShiftTracker::ObjectShifted(
float threshold_physical_px =
kMovementThreshold * object.StyleRef().EffectiveZoom();
- if (enable_m90_improvements_) {
- // Check shift of starting point, including 2d-translation and scroll
- // deltas.
- if (EqualWithinMovementThreshold(old_starting_point, new_starting_point,
- threshold_physical_px))
- return;
+ // Check shift of starting point, including 2d-translation and scroll
+ // deltas.
+ if (EqualWithinMovementThreshold(old_starting_point, new_starting_point,
+ threshold_physical_px))
+ return;
- // Check shift of 2d-translation-indifferent starting point.
- if (!translation_delta.IsZero() &&
- EqualWithinMovementThreshold(old_starting_point + translation_delta,
- new_starting_point, threshold_physical_px))
- return;
+ // Check shift of 2d-translation-indifferent starting point.
+ if (!translation_delta.IsZero() &&
+ EqualWithinMovementThreshold(old_starting_point + translation_delta,
+ new_starting_point, threshold_physical_px))
+ return;
- // Check shift of scroll-indifferent starting point.
- if (!scroll_delta.IsZero() &&
- EqualWithinMovementThreshold(old_starting_point + scroll_delta,
- new_starting_point, threshold_physical_px))
- return;
- }
+ // Check shift of scroll-indifferent starting point.
+ if (!scroll_delta.IsZero() &&
+ EqualWithinMovementThreshold(old_starting_point + scroll_delta,
+ new_starting_point, threshold_physical_px))
+ return;
+
+ if (RuntimeEnabledFeatures::CLSScrollAnchoringEnabled() &&
+ !scroll_anchor_adjustment.IsZero() &&
+ EqualWithinMovementThreshold(
+ old_starting_point + scroll_delta + scroll_anchor_adjustment,
+ new_starting_point, threshold_physical_px))
+ return;
// Check shift of 2d-translation-and-scroll-indifferent starting point.
FloatSize translation_and_scroll_delta = scroll_delta + translation_delta;
@@ -293,9 +295,8 @@ void LayoutShiftTracker::ObjectShifted(
property_tree_state.Transform(), root_state.Transform());
// TODO(crbug.com/1187979): Shift by |scroll_delta| to keep backward
// compatibility in https://crrev.com/c/2754969. See the bug for details.
- FloatPoint old_starting_point_in_root = transform.MapPoint(
- old_starting_point +
- (enable_m90_improvements_ ? scroll_delta : translation_and_scroll_delta));
+ FloatPoint old_starting_point_in_root =
+ transform.MapPoint(old_starting_point + scroll_delta);
FloatPoint new_starting_point_in_root =
transform.MapPoint(new_starting_point);
@@ -304,22 +305,10 @@ void LayoutShiftTracker::ObjectShifted(
threshold_physical_px))
return;
- if (enable_m90_improvements_) {
- DCHECK(frame_scroll_delta_.IsZero());
- } else if (EqualWithinMovementThreshold(
- old_starting_point_in_root + frame_scroll_delta_,
- new_starting_point_in_root, threshold_physical_px)) {
- // TODO(skobes): Checking frame_scroll_delta_ is an imperfect solution to
- // allowing counterscrolled layout shifts. Ideally, we would map old_rect
- // to viewport coordinates using the previous frame's scroll tree.
- return;
- }
-
FloatRect old_rect_in_root(old_rect);
// TODO(crbug.com/1187979): Shift by |scroll_delta| to keep backward
// compatibility in https://crrev.com/c/2754969. See the bug for details.
- old_rect_in_root.Move(
- enable_m90_improvements_ ? scroll_delta : translation_and_scroll_delta);
+ old_rect_in_root.Move(scroll_delta);
transform.MapRect(old_rect_in_root);
FloatRect new_rect_in_root(new_rect);
transform.MapRect(new_rect_in_root);
@@ -333,8 +322,7 @@ void LayoutShiftTracker::ObjectShifted(
// If the object moved from or to out of view, ignore the shift if it's in
// the inline direction only.
- if (enable_m90_improvements_ &&
- (visible_old_rect.IsEmpty() || visible_new_rect.IsEmpty())) {
+ if (visible_old_rect.IsEmpty() || visible_new_rect.IsEmpty()) {
FloatPoint old_inline_direction_indifferent_starting_point_in_root =
old_starting_point_in_root;
if (object.IsHorizontalWritingMode()) {
@@ -441,11 +429,12 @@ void LayoutShiftTracker::NotifyBoxPrePaint(
const PhysicalOffset& old_paint_offset,
const FloatSize& translation_delta,
const FloatSize& scroll_delta,
+ const FloatSize& scroll_anchor_adjustment,
const PhysicalOffset& new_paint_offset) {
DCHECK(NeedsToTrack(box));
ObjectShifted(box, property_tree_state, old_rect, new_rect,
StartingPoint(old_paint_offset, box, box.PreviousSize()),
- translation_delta, scroll_delta,
+ translation_delta, scroll_delta, scroll_anchor_adjustment,
StartingPoint(new_paint_offset, box, box.Size()));
}
@@ -457,6 +446,7 @@ void LayoutShiftTracker::NotifyTextPrePaint(
const PhysicalOffset& old_paint_offset,
const FloatSize& translation_delta,
const FloatSize& scroll_delta,
+ const FloatSize& scroll_anchor_adjustment,
const PhysicalOffset& new_paint_offset,
LayoutUnit logical_height) {
DCHECK(NeedsToTrack(text));
@@ -486,7 +476,8 @@ void LayoutShiftTracker::NotifyTextPrePaint(
ObjectShifted(text, property_tree_state, old_rect, new_rect,
FloatPoint(old_physical_starting_point), translation_delta,
- scroll_delta, FloatPoint(new_physical_starting_point));
+ scroll_delta, scroll_anchor_adjustment,
+ FloatPoint(new_physical_starting_point));
}
double LayoutShiftTracker::SubframeWeightingFactor() const {
@@ -551,7 +542,8 @@ void LayoutShiftTracker::NotifyPrePaintFinishedInternal() {
<< SubframeWeightingFactor();
}
- if (pointerdown_pending_data_.saw_pointerdown) {
+ if (pointerdown_pending_data_.num_pointerdowns > 0 ||
+ pointerdown_pending_data_.num_pressed_mouse_buttons > 0) {
pointerdown_pending_data_.score_delta += score_delta;
pointerdown_pending_data_.weighted_score_delta += weighted_score_delta;
} else {
@@ -568,7 +560,6 @@ void LayoutShiftTracker::NotifyPrePaintFinished() {
// Reset accumulated state.
region_.Reset();
frame_max_distance_ = 0.0;
- frame_scroll_delta_ = ScrollOffset();
attributions_.fill(Attribution());
}
@@ -633,11 +624,21 @@ void LayoutShiftTracker::ReportShift(double score_delta,
void LayoutShiftTracker::NotifyInput(const WebInputEvent& event) {
const WebInputEvent::Type type = event.GetType();
- const bool saw_pointerdown = pointerdown_pending_data_.saw_pointerdown;
- const bool pointerdown_became_tap =
- saw_pointerdown && type == WebInputEvent::Type::kPointerUp;
+ bool release_all_mouse_buttons = false;
+ if (type == WebInputEvent::Type::kMouseUp) {
+ if (pointerdown_pending_data_.num_pressed_mouse_buttons > 0)
+ pointerdown_pending_data_.num_pressed_mouse_buttons--;
+ release_all_mouse_buttons =
+ pointerdown_pending_data_.num_pressed_mouse_buttons == 0;
+ }
+ bool release_all_pointers = false;
+ if (type == WebInputEvent::Type::kPointerUp) {
+ if (pointerdown_pending_data_.num_pointerdowns > 0)
+ pointerdown_pending_data_.num_pointerdowns--;
+ release_all_pointers = pointerdown_pending_data_.num_pointerdowns == 0;
+ }
+
const bool event_type_stops_pointerdown_buffering =
- type == WebInputEvent::Type::kPointerUp ||
type == WebInputEvent::Type::kPointerCausedUaAction ||
type == WebInputEvent::Type::kPointerCancel;
@@ -653,7 +654,7 @@ void LayoutShiftTracker::NotifyInput(const WebInputEvent& event) {
// We need to explicitly include tap, as if there are no listeners, we
// won't receive the pointer events.
type == WebInputEvent::Type::kGestureTap || is_hovering_pointerdown ||
- pointerdown_became_tap;
+ release_all_pointers || release_all_mouse_buttons;
if (should_trigger_shift_exclusion) {
observed_input_or_scroll_ = true;
@@ -663,14 +664,17 @@ void LayoutShiftTracker::NotifyInput(const WebInputEvent& event) {
UpdateInputTimestamp(event.TimeStamp());
}
- if (saw_pointerdown && event_type_stops_pointerdown_buffering) {
+ if (event_type_stops_pointerdown_buffering || release_all_mouse_buttons ||
+ release_all_pointers) {
double score_delta = pointerdown_pending_data_.score_delta;
if (score_delta > 0)
ReportShift(score_delta, pointerdown_pending_data_.weighted_score_delta);
pointerdown_pending_data_ = PointerdownPendingData();
}
if (type == WebInputEvent::Type::kPointerDown && !is_hovering_pointerdown)
- pointerdown_pending_data_.saw_pointerdown = true;
+ pointerdown_pending_data_.num_pointerdowns++;
+ if (type == WebInputEvent::Type::kMouseDown)
+ pointerdown_pending_data_.num_pressed_mouse_buttons++;
}
void LayoutShiftTracker::UpdateInputTimestamp(base::TimeTicks timestamp) {
@@ -680,15 +684,10 @@ void LayoutShiftTracker::UpdateInputTimestamp(base::TimeTicks timestamp) {
} else if (timestamp > most_recent_input_timestamp_) {
most_recent_input_timestamp_ = timestamp;
}
- LocalFrame& frame = frame_view_->GetFrame();
- frame.Client()->DidObserveInputForLayoutShiftTracking(timestamp);
}
void LayoutShiftTracker::NotifyScroll(mojom::blink::ScrollType scroll_type,
ScrollOffset delta) {
- if (!enable_m90_improvements_)
- frame_scroll_delta_ += delta;
-
// Only set observed_input_or_scroll_ for user-initiated scrolls, and not
// other scrolls such as hash fragment navigations.
if (scroll_type == mojom::blink::ScrollType::kUser ||
@@ -795,6 +794,10 @@ void LayoutShiftTracker::SendLayoutShiftRectsToHud(
}
}
+void LayoutShiftTracker::ResetTimerForTesting() {
+ timer_.Stop();
+}
+
void LayoutShiftTracker::Trace(Visitor* visitor) const {
visitor->Trace(frame_view_);
visitor->Trace(timer_);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h
index 8a7d2be368f..8392f5e56f8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h
@@ -59,6 +59,7 @@ class CORE_EXPORT LayoutShiftTracker final
const PhysicalOffset& old_paint_offset,
const FloatSize& translation_delta,
const FloatSize& scroll_delta,
+ const FloatSize& scroll_anchor_adjustment,
const PhysicalOffset& new_paint_offset);
void NotifyTextPrePaint(const LayoutText& text,
@@ -68,6 +69,7 @@ class CORE_EXPORT LayoutShiftTracker final
const PhysicalOffset& old_paint_offset,
const FloatSize& translation_delta,
const FloatSize& scroll_delta,
+ const FloatSize& scroll_anchor_adjustment,
const PhysicalOffset& new_paint_offset,
const LayoutUnit logical_height);
@@ -87,6 +89,7 @@ class CORE_EXPORT LayoutShiftTracker final
base::TimeTicks MostRecentInputTimestamp() {
return most_recent_input_timestamp_;
}
+ void ResetTimerForTesting();
void Trace(Visitor* visitor) const;
// Saves and restores geometry on layout boxes when a layout tree is rebuilt
@@ -160,6 +163,7 @@ class CORE_EXPORT LayoutShiftTracker final
const FloatPoint& old_starting_point,
const FloatSize& translation_delta,
const FloatSize& scroll_offset_delta,
+ const FloatSize& scroll_anchor_adjustment,
const FloatPoint& new_starting_point);
void ReportShift(double score_delta, double weighted_score_delta);
@@ -184,7 +188,6 @@ class CORE_EXPORT LayoutShiftTracker final
Member<LocalFrameView> frame_view_;
bool is_active_;
- bool enable_m90_improvements_;
// The document cumulative layout shift (DCLS) score for this LocalFrame,
// unweighted, with move distance applied.
@@ -203,11 +206,11 @@ class CORE_EXPORT LayoutShiftTracker final
// treatment is known, the pending layout shifts are reported appropriately
// and the PointerdownPendingData object is reset.
struct PointerdownPendingData {
- PointerdownPendingData()
- : saw_pointerdown(false), score_delta(0), weighted_score_delta(0) {}
- bool saw_pointerdown;
- double score_delta;
- double weighted_score_delta;
+ PointerdownPendingData() = default;
+ int num_pointerdowns = 0;
+ int num_pressed_mouse_buttons = 0;
+ double score_delta = 0;
+ double weighted_score_delta = 0;
};
PointerdownPendingData pointerdown_pending_data_;
@@ -228,10 +231,6 @@ class CORE_EXPORT LayoutShiftTracker final
// frames.
float overall_max_distance_;
- // Sum of all scroll deltas that occurred in the current animation frame.
- // TODO(wangxianzhu): Remove when enabling CLSM90Improvements permanently.
- ScrollOffset frame_scroll_delta_;
-
// Whether either a user input or document scroll have been observed during
// the session. (This is only tracked so UkmPageLoadMetricsObserver to report
// LayoutInstability.CumulativeShiftScore.MainFrame.BeforeInputOrScroll. It's
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
index 7c7ac49f69f..46348e1acfa 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
@@ -333,6 +333,356 @@ TEST_F(LayoutShiftTrackerPointerdownTest, PointerdownBecomesScroll) {
false /* expect_exclusion */);
}
+TEST_F(LayoutShiftTrackerSimTest, MouseMoveDraggingAction) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ body { margin: 0; height: 1500px; }
+ #box {
+ left: 0px;
+ top: 0px;
+ width: 400px;
+ height: 600px;
+ background: yellow;
+ position: absolute;
+ }
+ </style>
+ <div id="box"></div>
+ <script>
+ box.addEventListener("mousemove", (e) => {
+ box.style.top = "50px";
+ e.preventDefault();
+ });
+ box.addEventListener("mouseup", (e) => {
+ box.style.top = "100px";
+ e.preventDefault();
+ });
+ </script>
+ )HTML");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ WebMouseEvent event1(WebInputEvent::Type::kMouseDown, gfx::PointF(),
+ gfx::PointF(), WebPointerProperties::Button::kLeft, 0,
+ WebInputEvent::Modifiers::kLeftButtonDown,
+ base::TimeTicks::Now());
+ WebMouseEvent event2(WebInputEvent::Type::kMouseMove, gfx::PointF(),
+ gfx::PointF(), WebPointerProperties::Button::kLeft, 1,
+ WebInputEvent::Modifiers::kLeftButtonDown,
+ base::TimeTicks::Now());
+ WebMouseEvent event3(WebInputEvent::Type::kMouseUp, gfx::PointF(),
+ gfx::PointF(), WebPointerProperties::Button::kLeft, 1,
+ WebInputEvent::Modifiers::kLeftButtonDown,
+ base::TimeTicks::Now());
+
+ // Coordinates inside #box.
+ event1.SetPositionInWidget(50, 150);
+ event2.SetPositionInWidget(50, 160);
+ event3.SetPositionInWidget(50, 160);
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event1, ui::LatencyInfo()));
+
+ WindowPerformance& perf = *DOMWindowPerformance::performance(Window());
+ auto& tracker = MainFrame().GetFrameView()->GetLayoutShiftTracker();
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+ tracker.ResetTimerForTesting();
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event2, ui::LatencyInfo()));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+ tracker.ResetTimerForTesting();
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event3, ui::LatencyInfo()));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ auto entries = perf.getBufferedEntriesByType("layout-shift");
+ EXPECT_EQ(2u, entries.size());
+ LayoutShift* shift = static_cast<LayoutShift*>(entries.back().Get());
+
+ EXPECT_TRUE(shift->hadRecentInput());
+ EXPECT_GT(shift->value(), 0);
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+}
+
+TEST_F(LayoutShiftTrackerSimTest, TouchDraggingAction) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ body { margin: 0; height: 1500px; }
+ #box {
+ left: 0px;
+ top: 0px;
+ width: 400px;
+ height: 600px;
+ background: yellow;
+ position: absolute;
+ }
+ </style>
+ <div id="box"></div>
+ <script>
+ box.addEventListener("pointermove", (e) => {
+ box.style.top = "100px";
+ e.preventDefault();
+ });
+ </script>
+ )HTML");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ WebPointerProperties pointer_properties = WebPointerProperties(
+ 1 /* PointerId */, WebPointerProperties::PointerType::kTouch,
+ WebPointerProperties::Button::kLeft);
+
+ WebPointerEvent event1(WebInputEvent::Type::kPointerDown, pointer_properties,
+ 5, 5);
+ WebPointerEvent event2(WebInputEvent::Type::kPointerMove, pointer_properties,
+ 5, 5);
+ WebPointerEvent event3(WebInputEvent::Type::kPointerUp, pointer_properties, 5,
+ 5);
+
+ // Coordinates inside #box.
+ event1.SetPositionInWidget(100, 160);
+ event2.SetPositionInWidget(100, 180);
+ event3.SetPositionInWidget(100, 180);
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event1, ui::LatencyInfo()));
+
+ WindowPerformance& perf = *DOMWindowPerformance::performance(Window());
+ auto& tracker = MainFrame().GetFrameView()->GetLayoutShiftTracker();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event2, ui::LatencyInfo()));
+
+ // Executes the BeginMainFrame processing steps and calls ReportShift in
+ // LayoutShiftTracker to get the latest layout shift score.
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event3, ui::LatencyInfo()));
+
+ // region fraction 50%, distance fraction 1/8
+ const double expected_shift = 0.5 * 0.125;
+
+ auto entries = perf.getBufferedEntriesByType("layout-shift");
+ EXPECT_EQ(1u, entries.size());
+ LayoutShift* shift = static_cast<LayoutShift*>(entries.back().Get());
+
+ EXPECT_TRUE(shift->hadRecentInput());
+ EXPECT_FLOAT_EQ(expected_shift, shift->value());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+}
+
+TEST_F(LayoutShiftTrackerSimTest, TouchScrollingAction) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ body { margin: 0; height: 1500px; }
+ #box {
+ left: 0px;
+ top: 0px;
+ width: 400px;
+ height: 600px;
+ background: yellow;
+ position: absolute;
+ }
+ </style>
+ <div id="box"></div>
+ <script>
+ box.addEventListener("pointermove", (e) => {
+ box.style.top = e.clientY;
+ e.preventDefault();
+ });
+ </script>
+ )HTML");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ WebPointerProperties pointer_properties = WebPointerProperties(
+ 1 /* PointerId */, WebPointerProperties::PointerType::kTouch,
+ WebPointerProperties::Button::kLeft);
+
+ WebPointerEvent event1(WebInputEvent::Type::kPointerDown, pointer_properties,
+ 5, 5);
+ WebPointerEvent event2(WebInputEvent::Type::kPointerMove, pointer_properties,
+ 5, 5);
+ WebPointerEvent event3(WebInputEvent::Type::kPointerCancel,
+ pointer_properties, 5, 5);
+ WebPointerEvent event4(WebInputEvent::Type::kPointerMove, pointer_properties,
+ 5, 5);
+
+ // Coordinates inside #box.
+ event1.SetPositionInWidget(80, 90);
+ event2.SetPositionInWidget(80, 100);
+ event3.SetPositionInWidget(80, 100);
+ event4.SetPositionInWidget(80, 150);
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event1, ui::LatencyInfo()));
+
+ WindowPerformance& perf = *DOMWindowPerformance::performance(Window());
+ auto& tracker = MainFrame().GetFrameView()->GetLayoutShiftTracker();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event2, ui::LatencyInfo()));
+
+ // Executes the BeginMainFrame processing steps and calls ReportShift in
+ // LayoutShiftTracker to get the latest layout shift score.
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event3, ui::LatencyInfo()));
+
+ // region fraction 50%, distance fraction 1/8
+ const double expected_shift = 0.5 * 0.125;
+ auto entries = perf.getBufferedEntriesByType("layout-shift");
+ EXPECT_EQ(1u, entries.size());
+ LayoutShift* shift = static_cast<LayoutShift*>(entries.back().Get());
+
+ // For touch scroll, hasRecentInput is false, and the layout shift score is
+ // reported when a PointerCancel event is received.
+ EXPECT_FALSE(shift->hadRecentInput());
+ EXPECT_FLOAT_EQ(expected_shift, shift->value());
+ EXPECT_FLOAT_EQ(expected_shift, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event4, ui::LatencyInfo()));
+
+ // Executes the BeginMainFrame processing steps and calls ReportShift in
+ // LayoutShiftTracker to get the latest layout shift score.
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ entries = perf.getBufferedEntriesByType("layout-shift");
+ EXPECT_EQ(2u, entries.size());
+ shift = static_cast<LayoutShift*>(entries.back().Get());
+
+ EXPECT_FALSE(shift->hadRecentInput());
+ EXPECT_GT(shift->value(), 0);
+ EXPECT_GT(tracker.Score(), expected_shift);
+}
+
+TEST_F(LayoutShiftTrackerSimTest, MultiplePointerDownUps) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ body { margin: 0; height: 1500px; }
+ #box {
+ left: 0px;
+ top: 0px;
+ width: 400px;
+ height: 600px;
+ background: yellow;
+ position: absolute;
+ }
+ </style>
+ <div id="box"></div>
+ <script>
+ box.addEventListener("pointerup", (e) => {
+ box.style.top = "100px";
+ e.preventDefault();
+ });
+ </script>
+ )HTML");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ WebPointerProperties pointer_properties = WebPointerProperties(
+ 1 /* PointerId */, WebPointerProperties::PointerType::kTouch,
+ WebPointerProperties::Button::kLeft);
+
+ WebPointerEvent event1(WebInputEvent::Type::kPointerDown, pointer_properties,
+ 5, 5);
+ WebPointerEvent event2(WebInputEvent::Type::kPointerDown, pointer_properties,
+ 5, 5);
+ WebPointerEvent event3(WebInputEvent::Type::kPointerUp, pointer_properties, 5,
+ 5);
+ WebPointerEvent event4(WebInputEvent::Type::kPointerUp, pointer_properties, 5,
+ 5);
+
+ // Coordinates inside #box.
+ event1.SetPositionInWidget(90, 110);
+ event2.SetPositionInWidget(90, 110);
+ event3.SetPositionInWidget(90, 110);
+ event4.SetPositionInWidget(90, 110);
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event1, ui::LatencyInfo()));
+
+ WindowPerformance& perf = *DOMWindowPerformance::performance(Window());
+ auto& tracker = MainFrame().GetFrameView()->GetLayoutShiftTracker();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event2, ui::LatencyInfo()));
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event3, ui::LatencyInfo()));
+
+ // Executes the BeginMainFrame processing steps and calls ReportShift in
+ // LayoutShiftTracker to get the latest layout shift score.
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+ EXPECT_FLOAT_EQ(0, tracker.Score());
+
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event4, ui::LatencyInfo()));
+
+ // region fraction 50%, distance fraction 1/8
+ const double expected_shift = 0.5 * 0.125;
+ auto entries = perf.getBufferedEntriesByType("layout-shift");
+ EXPECT_EQ(1u, entries.size());
+ LayoutShift* shift = static_cast<LayoutShift*>(entries.back().Get());
+
+ EXPECT_TRUE(shift->hadRecentInput());
+ EXPECT_FLOAT_EQ(expected_shift, shift->value());
+ EXPECT_FLOAT_EQ(0.0, tracker.Score());
+}
+
TEST_F(LayoutShiftTrackerTest, StableCompositingChanges) {
SetBodyInnerHTML(R"HTML(
<style>
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.h b/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.h
index 4561e0bc363..02a8722e528 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.h
@@ -67,7 +67,7 @@ class CORE_EXPORT LayoutTableBoxComponent : public LayoutBox {
protected:
explicit LayoutTableBoxComponent(Element* element)
- : LayoutBox(element), last_paint_result_(kFullyPainted) {
+ : LayoutBox(element), last_paint_result_(kMayBeClippedByCullRect) {
NOT_DESTROYED();
}
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 3b4382d5f7c..45de2fb7b75 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "build/build_config.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
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 e8e987b69f9..cc3ee939381 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.cc
@@ -32,10 +32,12 @@
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/bidi_adjustment.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/frame_selection.h"
#include "third_party/blink/renderer/core/editing/inline_box_position.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.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/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -46,6 +48,7 @@
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_text_combine.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -54,6 +57,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/inline/layout_ng_text.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
@@ -61,7 +65,9 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
+#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/platform/fonts/character_range.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -410,10 +416,12 @@ Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const {
// Compute start of the legacy text box.
if (unit.AssociatedNode()) {
// In case of |text_| comes from DOM node.
- const absl::optional<unsigned> box_start =
- CaretOffsetForPosition(mapping->GetLastPosition(clamped_start));
- DCHECK(box_start.has_value());
- results.push_back(TextBoxInfo{rect, *box_start, box_length});
+ if (const absl::optional<unsigned> box_start = CaretOffsetForPosition(
+ mapping->GetLastPosition(clamped_start))) {
+ results.push_back(TextBoxInfo{rect, *box_start, box_length});
+ continue;
+ }
+ NOTREACHED();
continue;
}
// Handle CSS generated content, e.g. ::before/::after
@@ -657,9 +665,6 @@ void LayoutText::AbsoluteQuadsForRange(Vector<FloatQuad>& quads,
// Find fragments that have text for the specified range.
DCHECK_LE(start, end);
- const LayoutBlock* block_for_flipping = nullptr;
- if (UNLIKELY(HasFlippedBlocksWritingMode()))
- block_for_flipping = ContainingBlock();
NGInlineCursor cursor;
bool is_last_end_included = false;
for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) {
@@ -826,12 +831,17 @@ PositionWithAffinity CreatePositionWithAffinityForBox(
: TextAffinity::kDownstream;
break;
}
- int text_start_offset =
- box->GetLineLayoutItem().IsText()
- ? LineLayoutText(box->GetLineLayoutItem()).TextStartOffset()
- : 0;
- return box->GetLineLayoutItem().CreatePositionWithAffinity(
- offset + text_start_offset, affinity);
+ const LineLayoutItem& layout_item = box->GetLineLayoutItem();
+ if (!layout_item.IsText()) {
+ if (const Node* node = layout_item.NonPseudoNode()) {
+ if (offset && UNLIKELY(offset > Position::LastOffsetInNode(*node)))
+ return layout_item.PositionAfterThis();
+ }
+ return layout_item.CreatePositionWithAffinity(offset, affinity);
+ }
+ int text_start_offset = LineLayoutText(layout_item).TextStartOffset();
+ return layout_item.CreatePositionWithAffinity(offset + text_start_offset,
+ affinity);
}
PositionWithAffinity
@@ -879,27 +889,29 @@ PositionWithAffinity LayoutText::PositionForPoint(
point_in_contents += PhysicalOffset(
containing_block_flow->PixelSnappedScrolledContentOffset());
}
+ const auto* const text_combine = DynamicTo<LayoutNGTextCombine>(Parent());
const NGPhysicalBoxFragment* container_fragment = nullptr;
PhysicalOffset point_in_container_fragment;
+ DCHECK(!IsSVGInlineText());
for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
DCHECK(&cursor.ContainerFragment());
if (container_fragment != &cursor.ContainerFragment()) {
container_fragment = &cursor.ContainerFragment();
point_in_container_fragment =
point_in_contents - container_fragment->OffsetFromOwnerLayoutBox();
+ if (UNLIKELY(text_combine)) {
+ point_in_container_fragment =
+ text_combine->AdjustOffsetForHitTest(point_in_container_fragment);
+ }
}
if (!EnclosingIntRect(cursor.Current().RectInContainerFragment())
.Contains(FlooredIntPoint(point_in_container_fragment)))
continue;
if (auto position_with_affinity =
cursor.PositionForPointInChild(point_in_container_fragment)) {
- // Note: Due by Bidi adjustment, |position| isn't relative to this.
- const Position& position = position_with_affinity.GetPosition();
- DCHECK(position.IsOffsetInAnchor()) << position;
- return position.ComputeContainerNode()
- ->GetLayoutObject()
- ->CreatePositionWithAffinity(position.OffsetInContainerNode(),
- position_with_affinity.Affinity());
+ // Note: Due by Bidi adjustment, |position_with_affinity| isn't
+ // relative to this.
+ return AdjustForEditingBoundary(position_with_affinity);
}
}
// Try for leading and trailing spaces between lines.
@@ -2110,7 +2122,9 @@ void LayoutText::SecureText(UChar mask) {
int last_typed_character_offset_to_reveal = -1;
UChar revealed_text;
- SecureTextTimer* secure_text_timer = GetSecureTextTimers().at(this);
+ auto it = GetSecureTextTimers().find(this);
+ SecureTextTimer* secure_text_timer =
+ it != GetSecureTextTimers().end() ? it->value : nullptr;
if (secure_text_timer && secure_text_timer->IsActive()) {
last_typed_character_offset_to_reveal =
secure_text_timer->LastTypedCharacterOffset();
@@ -2121,7 +2135,7 @@ void LayoutText::SecureText(UChar mask) {
text_.Fill(mask);
if (last_typed_character_offset_to_reveal >= 0) {
text_.replace(last_typed_character_offset_to_reveal, 1,
- String(&revealed_text, 1));
+ String(&revealed_text, 1u));
// m_text may be updated later before timer fires. We invalidate the
// lastTypedCharacterOffset to avoid inconsistency.
secure_text_timer->Invalidate();
@@ -2144,6 +2158,21 @@ void LayoutText::ForceSetText(scoped_refptr<StringImpl> text) {
TextDidChange();
}
+void LayoutText::SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ LayoutInvalidationReasonForTracing reason) {
+ auto* const text_combine = DynamicTo<LayoutNGTextCombine>(Parent());
+ if (UNLIKELY(text_combine)) {
+ // Number of characters in text may change compressed font or scaling of
+ // text combine. So, we should invalidate |LayoutNGTextCombine| to repaint.
+ text_combine
+ ->SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ reason);
+ return;
+ }
+ LayoutObject::SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ reason);
+}
+
void LayoutText::TextDidChange() {
NOT_DESTROYED();
// If preferredLogicalWidthsDirty() of an orphan child is true,
@@ -2317,6 +2346,10 @@ PhysicalRect LayoutText::PhysicalLinesBoundingBox() const {
// Some callers expect correct offset even if the rect is empty.
if (result == PhysicalRect())
result.offset = FirstLineBoxTopLeft();
+ // Note: |result.offset| is relative to container fragment.
+ const auto* const text_combine = DynamicTo<LayoutNGTextCombine>(Parent());
+ if (UNLIKELY(text_combine))
+ return text_combine->AdjustRectForBoundingBox(result);
return result;
}
@@ -2385,6 +2418,9 @@ PhysicalRect LayoutText::LocalSelectionVisualRect() const {
const FrameSelection& frame_selection = GetFrame()->Selection();
if (IsInLayoutNGInlineFormattingContext()) {
+ const auto* svg_inline_text = DynamicTo<LayoutSVGInlineText>(this);
+ float scaling_factor =
+ svg_inline_text ? svg_inline_text->ScalingFactor() : 1.0f;
PhysicalRect rect;
NGInlineCursor cursor(*ContainingNGBlockFlow());
for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) {
@@ -2395,7 +2431,20 @@ PhysicalRect LayoutText::LocalSelectionVisualRect() const {
if (status.start == status.end)
continue;
PhysicalRect item_rect = cursor.CurrentLocalSelectionRectForText(status);
- item_rect.offset += cursor.Current().OffsetInContainerFragment();
+ if (svg_inline_text) {
+ FloatRect float_rect(item_rect);
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ float_rect.MoveBy(item.SvgFragmentData()->rect.Location());
+ if (item.HasSvgTransformForBoundingBox()) {
+ float_rect =
+ item.BuildSvgTransformForBoundingBox().MapRect(float_rect);
+ }
+ if (scaling_factor != 1.0f)
+ float_rect.Scale(1 / scaling_factor);
+ item_rect = PhysicalRect::EnclosingRect(float_rect);
+ } else {
+ item_rect.offset += cursor.Current().OffsetInContainerFragment();
+ }
rect.Unite(item_rect);
}
return rect;
@@ -2699,7 +2748,9 @@ bool LayoutText::IsAfterNonCollapsedCharacter(unsigned text_offset) const {
void LayoutText::MomentarilyRevealLastTypedCharacter(
unsigned last_typed_character_offset) {
NOT_DESTROYED();
- SecureTextTimer* secure_text_timer = GetSecureTextTimers().at(this);
+ auto it = GetSecureTextTimers().find(this);
+ SecureTextTimer* secure_text_timer =
+ it != GetSecureTextTimers().end() ? it->value : nullptr;
if (!secure_text_timer) {
secure_text_timer = new SecureTextTimer(this);
GetSecureTextTimers().insert(this, secure_text_timer);
@@ -2752,16 +2803,21 @@ void LayoutText::InvalidateDisplayItemClients(
const DisplayItemClient* LayoutText::GetSelectionDisplayItemClient() const {
NOT_DESTROYED();
+ if (UNLIKELY(!IsInLayoutNGInlineFormattingContext()))
+ return nullptr;
+ // When |this| is in text-combine box, we should use text-combine box as
+ // display client item to paint caret with affine transform.
+ const auto* const text_combine = DynamicTo<LayoutNGTextCombine>(Parent());
+ if (UNLIKELY(text_combine) && text_combine->NeedsAffineTransformInPaint())
+ return text_combine;
if (!IsSelected())
return nullptr;
- if (IsInLayoutNGInlineFormattingContext()) {
- if (const auto* client = GetSelectionDisplayItemClientMap().at(this))
- return client;
- return GetSelectionDisplayItemClientMap()
- .insert(this, std::make_unique<SelectionDisplayItemClient>())
- .stored_value->value.get();
- }
- return nullptr;
+ auto it = GetSelectionDisplayItemClientMap().find(this);
+ if (it != GetSelectionDisplayItemClientMap().end())
+ return &*it->value;
+ return GetSelectionDisplayItemClientMap()
+ .insert(this, std::make_unique<SelectionDisplayItemClient>())
+ .stored_value->value.get();
}
PhysicalRect LayoutText::DebugRect() const {
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 415a7dde543..c6d7b233894 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.h
@@ -123,7 +123,7 @@ class CORE_EXPORT LayoutText : public LayoutObject {
NOT_DESTROYED();
return 0;
}
- String PlainText() const;
+ virtual String PlainText() const;
// Returns first letter part of |LayoutTextFragment|.
virtual LayoutText* GetFirstLetterPart() const {
@@ -466,6 +466,11 @@ class CORE_EXPORT LayoutText : public LayoutObject {
return true;
}
+ // Override |LayoutObject| implementation to invalidate |LayoutNGtextCombine|.
+ // Note: This isn't a virtual function.
+ void SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ LayoutInvalidationReasonForTracing reason);
+
private:
InlineTextBoxList& MutableTextBoxes();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_combine.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_combine.cc
index a0a1cf29aa8..f4cb1c362c6 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_combine.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_combine.cc
@@ -20,7 +20,7 @@
#include "third_party/blink/renderer/core/layout/layout_text_combine.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
namespace blink {
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 67d8e78407c..251f01abfa5 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
@@ -22,11 +22,12 @@
#include "third_party/blink/renderer/core/layout/layout_text_control.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.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/scroll/scrollbar_theme.h"
@@ -66,6 +67,7 @@ void LayoutTextControl::StyleDidChange(HTMLElement* inner_editor,
LayoutBlock* inner_editor_layout_object =
To<LayoutBlock>(inner_editor->GetLayoutObject());
if (inner_editor_layout_object) {
+ // TODO(https://crbug.com/1101564):
// This is necessary to update the style on the inner_editor based on the
// changes in the input element ComputedStyle.
// (See TextControlInnerEditorElement::CreateInnerEditorStyle()).
@@ -155,7 +157,6 @@ static const char* const kFontFamiliesWithInvalidCharWidth[] = {
// number of Mac fonts, but, in order to get similar rendering across platforms,
// we do this check for all platforms.
bool LayoutTextControl::HasValidAvgCharWidth(const Font& font) {
- const AtomicString family = font.GetFontDescription().Family().Family();
const SimpleFontData* font_data = font.PrimaryFont();
DCHECK(font_data);
if (!font_data)
@@ -170,6 +171,7 @@ bool LayoutTextControl::HasValidAvgCharWidth(const Font& font) {
static HashSet<AtomicString>* font_families_with_invalid_char_width_map =
nullptr;
+ const AtomicString& family = font.GetFontDescription().Family().Family();
if (family.IsEmpty())
return false;
@@ -188,11 +190,18 @@ bool LayoutTextControl::HasValidAvgCharWidth(const Font& font) {
float LayoutTextControl::GetAvgCharWidth(const ComputedStyle& style) {
const Font& font = style.GetFont();
const SimpleFontData* primary_font = font.PrimaryFont();
- if (primary_font && HasValidAvgCharWidth(font))
- return roundf(primary_font->AvgCharWidth());
+ if (primary_font && HasValidAvgCharWidth(font)) {
+ const float width = primary_font->AvgCharWidth();
+ // We apply roundf() only if the fractional part of |width| is >= 0.5
+ // because:
+ // * We have done it for a long time.
+ // * Removing roundf() would make the intrinsic width smaller, and it
+ // would have a compatibility risk.
+ return std::max(width, roundf(width));
+ }
const UChar kCh = '0';
- const String str = String(&kCh, 1);
+ const String str = String(&kCh, 1u);
TextRun text_run =
ConstructTextRun(font, str, style, TextRun::kAllowTrailingExpansion);
return font.Width(text_run);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc
index 1c291416c5b..f389feec9f4 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc
@@ -24,27 +24,11 @@ TEST_F(LayoutTextControlSingleLineTest, VisualOverflowCleared) {
<input id=input type="text"></input.
)HTML");
auto* input = To<LayoutBox>(GetLayoutObjectByElementId("input"));
- if (::features::IsFormControlsRefreshEnabled()) {
- EXPECT_EQ(LayoutRect(-3, -3, 74, 72), input->SelfVisualOverflowRect());
- } else {
-#if defined(OS_MAC)
- EXPECT_EQ(LayoutRect(-3, -3, 72, 72), input->SelfVisualOverflowRect());
-#else
- EXPECT_EQ(LayoutRect(-3, -3, 70, 72), input->SelfVisualOverflowRect());
-#endif
- }
+ EXPECT_EQ(LayoutRect(-3, -3, 74, 72), input->SelfVisualOverflowRect());
To<Element>(input->GetNode())
->setAttribute(html_names::kStyleAttr, "box-shadow: initial");
UpdateAllLifecyclePhasesForTest();
- if (::features::IsFormControlsRefreshEnabled()) {
- EXPECT_EQ(LayoutRect(0, 0, 58, 56), input->SelfVisualOverflowRect());
- } else {
-#if defined(OS_MAC)
- EXPECT_EQ(LayoutRect(0, 0, 56, 56), input->SelfVisualOverflowRect());
-#else
- EXPECT_EQ(LayoutRect(0, 0, 54, 56), input->SelfVisualOverflowRect());
-#endif
- }
+ EXPECT_EQ(LayoutRect(0, 0, 58, 56), input->SelfVisualOverflowRect());
}
} // anonymous namespace
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 ca5a08ac6b6..5c24efeaee9 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
@@ -257,4 +257,23 @@ absl::optional<unsigned> LayoutTextFragment::CaretOffsetForPosition(
return dom_offset - Start();
}
+String LayoutTextFragment::PlainText() const {
+ // Special handling for floating ::first-letter in LayoutNG to ensure that
+ // PlainText() returns the full text of the node, not just the remaining text.
+ // See also ElementInnerTextCollector::ProcessTextNode(), which does the same.
+ NOT_DESTROYED();
+ if (!is_remaining_text_layout_object_ || !GetNode())
+ return LayoutText::PlainText();
+ LayoutText* first_letter = GetFirstLetterPart();
+ if (!first_letter)
+ return LayoutText::PlainText();
+ const NGOffsetMapping* remaining_text_mapping = GetNGOffsetMapping();
+ const NGOffsetMapping* first_letter_mapping =
+ first_letter->GetNGOffsetMapping();
+ if (first_letter_mapping && remaining_text_mapping &&
+ first_letter_mapping != remaining_text_mapping)
+ return first_letter_mapping->GetText() + LayoutText::PlainText();
+ return LayoutText::PlainText();
+}
+
} // namespace blink
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 88b53909e2f..884f4f6b91e 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
@@ -118,6 +118,8 @@ class CORE_EXPORT LayoutTextFragment : public LayoutText {
Text* AssociatedTextNode() const;
LayoutText* GetFirstLetterPart() const override;
+ String PlainText() const override;
+
protected:
friend class LayoutObjectFactory;
LayoutTextFragment(Node*, StringImpl*, int start_offset, int length);
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 72ecf39317c..becdb955613 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
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.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/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/testing/selection_sample.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
@@ -69,7 +70,8 @@ class LayoutTextTest : public RenderingTest {
std::string GetSnapCode(const LayoutText& layout_text,
const std::string& caret_text) {
- return GetSnapCode(layout_text, caret_text.find('|'));
+ return GetSnapCode(layout_text,
+ static_cast<unsigned>(caret_text.find('|')));
}
std::string GetSnapCode(const char* id, const std::string& caret_text) {
@@ -1051,6 +1053,45 @@ TEST_P(ParameterizedLayoutTextTest, PhysicalLinesBoundingBox) {
->PhysicalLinesBoundingBox());
}
+TEST_P(ParameterizedLayoutTextTest, PhysicalLinesBoundingBoxTextCombine) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "body { font: 100px/130px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div>a<c id=target>01234</c>b</div>");
+ const auto& target = *GetElementById("target");
+ const auto& text_a = *To<Text>(target.previousSibling())->GetLayoutObject();
+ const auto& text_01234 = *To<Text>(target.firstChild())->GetLayoutObject();
+ const auto& text_b = *To<Text>(target.nextSibling())->GetLayoutObject();
+
+ // LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+ // LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+ // LayoutNGBlockFlow {DIV} at (0,0) size 130x300
+ // LayoutText {#text} at (15,0) size 100x100
+ // text run at (15,0) width 100: "a"
+ // LayoutInline {C} at (15,100) size 100x100
+ // LayoutNGTextCombine (anonymous) at (15,100) size 100x100
+ // LayoutText {#text} at (-5,0) size 110x100
+ // text run at (0,0) width 500: "01234"
+ // LayoutText {#text} at (15,200) size 100x100
+ // text run at (15,200) width 100: "b"
+ //
+
+ EXPECT_EQ(PhysicalRect(15, 0, 100, 100), text_a.PhysicalLinesBoundingBox());
+ if (text_01234.Parent()->IsLayoutNGTextCombine()) {
+ // Note: Width 110 comes from |100px * kTextCombineMargin| in
+ // |LayoutNGTextCombine::DesiredWidth()|.
+ EXPECT_EQ(PhysicalRect(-5, 0, 110, 100),
+ text_01234.PhysicalLinesBoundingBox());
+ } else {
+ EXPECT_EQ(PhysicalRect(15, 100, 100, 100),
+ text_01234.PhysicalLinesBoundingBox());
+ }
+ EXPECT_EQ(PhysicalRect(15, 200, 100, 100), text_b.PhysicalLinesBoundingBox());
+}
+
TEST_P(ParameterizedLayoutTextTest, PhysicalLinesBoundingBoxVerticalRL) {
LoadAhem();
SetBasicBody(R"HTML(
@@ -1333,4 +1374,18 @@ TEST_P(ParameterizedLayoutTextTest, PositionForPointAtLeading) {
text->PositionForPoint({10, 55}).GetPosition());
}
+// https://crbug.com/2654312
+TEST_P(ParameterizedLayoutTextTest, FloatFirstLetterPlainText) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div::first-letter { float: left; }
+ </style>
+ <div id="target">Foo</div>
+ )HTML");
+
+ LayoutText* text =
+ To<LayoutText>(GetElementById("target")->firstChild()->GetLayoutObject());
+ EXPECT_EQ("Foo", text->PlainText());
+}
+
} // 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 3018b856f19..80c82f2ba29 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -148,7 +148,9 @@ LayoutTheme& LayoutTheme::GetTheme() {
return NativeTheme();
}
-LayoutTheme::LayoutTheme() : has_custom_focus_ring_color_(false) {}
+LayoutTheme::LayoutTheme() : has_custom_focus_ring_color_(false) {
+ UpdateForcedColorsState();
+}
ControlPart LayoutTheme::AdjustAppearanceWithAuthorStyle(
ControlPart part,
@@ -515,6 +517,7 @@ void LayoutTheme::AdjustSearchFieldStyle(ComputedStyle&) const {}
void LayoutTheme::AdjustSearchFieldCancelButtonStyle(ComputedStyle&) const {}
void LayoutTheme::PlatformColorsDidChange() {
+ UpdateForcedColorsState();
Page::PlatformColorsChanged();
}
@@ -572,27 +575,34 @@ static FontDescription& GetCachedFontDescription(CSSValueID system_font_id) {
}
void LayoutTheme::SystemFont(CSSValueID system_font_id,
- FontDescription& font_description) {
+ FontDescription& font_description,
+ const Document* document) {
font_description = GetCachedFontDescription(system_font_id);
if (font_description.IsAbsoluteSize())
return;
- FontSelectionValue font_slope = NormalSlopeValue();
- FontSelectionValue font_weight = NormalWeightValue();
- float font_size = 0;
- AtomicString font_family;
- LayoutThemeFontProvider::SystemFont(system_font_id, font_slope, font_weight,
- font_size, font_family);
- font_description.SetStyle(font_slope);
- font_description.SetWeight(font_weight);
- font_description.SetSpecifiedSize(font_size);
+ font_description.SetStyle(
+ LayoutThemeFontProvider::SystemFontStyle(system_font_id));
+ font_description.SetWeight(
+ LayoutThemeFontProvider::SystemFontWeight(system_font_id));
+ font_description.SetSpecifiedSize(
+ LayoutThemeFontProvider::SystemFontSize(system_font_id, document));
font_description.SetIsAbsoluteSize(true);
- font_description.FirstFamily().SetFamily(font_family);
+ font_description.FirstFamily().SetFamily(
+ LayoutThemeFontProvider::SystemFontFamily(system_font_id));
font_description.SetGenericFamily(FontDescription::kNoFamily);
}
Color LayoutTheme::SystemColor(CSSValueID css_value_id,
mojom::blink::ColorScheme color_scheme) const {
+ if (!WebTestSupport::IsRunningWebTest() && InForcedColorsMode())
+ return SystemColorFromNativeTheme(css_value_id, color_scheme);
+ return DefaultSystemColor(css_value_id, color_scheme);
+}
+
+Color LayoutTheme::DefaultSystemColor(
+ CSSValueID css_value_id,
+ mojom::blink::ColorScheme color_scheme) const {
switch (css_value_id) {
case CSSValueID::kActiveborder:
return 0xFFFFFFFF;
@@ -693,12 +703,57 @@ Color LayoutTheme::SystemColor(CSSValueID css_value_id,
return Color();
}
+Color LayoutTheme::SystemColorFromNativeTheme(
+ CSSValueID css_value_id,
+ mojom::blink::ColorScheme color_scheme) const {
+ blink::WebThemeEngine::SystemThemeColor theme_color;
+ switch (css_value_id) {
+ case CSSValueID::kActivetext:
+ case CSSValueID::kLinktext:
+ case CSSValueID::kVisitedtext:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kHotlight;
+ break;
+ case CSSValueID::kButtonface:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonFace;
+ break;
+ case CSSValueID::kButtontext:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonText;
+ break;
+ case CSSValueID::kGraytext:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kGrayText;
+ break;
+ case CSSValueID::kHighlight:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlight;
+ break;
+ case CSSValueID::kHighlighttext:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlightText;
+ break;
+ case CSSValueID::kWindow:
+ case CSSValueID::kCanvas:
+ case CSSValueID::kField:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kWindow;
+ break;
+ case CSSValueID::kWindowtext:
+ case CSSValueID::kCanvastext:
+ case CSSValueID::kFieldtext:
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kWindowText;
+ break;
+ default:
+ return DefaultSystemColor(css_value_id, color_scheme);
+ }
+ DCHECK(Platform::Current() && Platform::Current()->ThemeEngine());
+ const absl::optional<SkColor> system_color =
+ Platform::Current()->ThemeEngine()->GetSystemColor(theme_color);
+ if (system_color)
+ return Color(system_color.value());
+ return DefaultSystemColor(css_value_id, color_scheme);
+}
+
Color LayoutTheme::PlatformTextSearchHighlightColor(
bool active_match,
- bool in_forced_colors_mode,
mojom::blink::ColorScheme color_scheme) const {
if (active_match) {
- if (in_forced_colors_mode)
+ if (InForcedColorsMode())
return GetTheme().SystemColor(CSSValueID::kHighlight, color_scheme);
return Color(255, 150, 50); // Orange.
}
@@ -707,9 +762,8 @@ Color LayoutTheme::PlatformTextSearchHighlightColor(
Color LayoutTheme::PlatformTextSearchColor(
bool active_match,
- bool in_forced_colors_mode,
mojom::blink::ColorScheme color_scheme) const {
- if (in_forced_colors_mode && active_match)
+ if (InForcedColorsMode() && active_match)
return GetTheme().SystemColor(CSSValueID::kHighlighttext, color_scheme);
return Color::kBlack;
}
@@ -743,8 +797,7 @@ String LayoutTheme::DisplayNameForFile(const File& file) const {
bool LayoutTheme::SupportsCalendarPicker(const AtomicString& type) const {
DCHECK(RuntimeEnabledFeatures::InputMultipleFieldsUIEnabled());
- if (features::IsFormControlsRefreshEnabled() &&
- type == input_type_names::kTime)
+ if (type == input_type_names::kTime)
return true;
return type == input_type_names::kDate ||
@@ -780,4 +833,11 @@ Color LayoutTheme::GetCustomFocusRingColor() const {
return custom_focus_ring_color_;
}
+void LayoutTheme::UpdateForcedColorsState() {
+ in_forced_colors_mode_ =
+ Platform::Current() && Platform::Current()->ThemeEngine() &&
+ Platform::Current()->ThemeEngine()->GetForcedColors() !=
+ ForcedColors::kNone;
+}
+
} // namespace blink
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 0185d72ea1a..bdc3f5d3579 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.h
@@ -42,6 +42,7 @@
namespace blink {
class ComputedStyle;
+class Document;
class Element;
class File;
class FontDescription;
@@ -122,10 +123,8 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
// Highlight and text colors for TextMatches.
Color PlatformTextSearchHighlightColor(
bool active_match,
- bool in_forced_colors_mode,
mojom::blink::ColorScheme color_scheme) const;
Color PlatformTextSearchColor(bool active_match,
- bool in_forced_colors_mode,
mojom::blink::ColorScheme color_scheme) const;
virtual Color FocusRingColor(mojom::blink::ColorScheme color_scheme) const;
@@ -146,7 +145,7 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
virtual base::TimeDelta CaretBlinkInterval() const;
// System fonts and colors for CSS.
- void SystemFont(CSSValueID system_font_id, FontDescription&);
+ void SystemFont(CSSValueID system_font_id, FontDescription&, const Document*);
virtual Color SystemColor(CSSValueID,
mojom::blink::ColorScheme color_scheme) const;
@@ -193,6 +192,8 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
return Color();
}
+ bool InForcedColorsMode() const { return in_forced_colors_mode_; }
+
protected:
// The platform selection color.
virtual Color PlatformActiveSelectionBackgroundColor(
@@ -233,6 +234,12 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
bool HasCustomFocusRingColor() const;
Color GetCustomFocusRingColor() const;
+ Color DefaultSystemColor(CSSValueID,
+ mojom::blink::ColorScheme color_scheme) const;
+ Color SystemColorFromNativeTheme(
+ CSSValueID,
+ mojom::blink::ColorScheme color_scheme) const;
+
private:
// This function is to be implemented in your platform-specific theme
// implementation to hand back the appropriate platform theme.
@@ -244,12 +251,15 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
ControlPart AdjustAppearanceWithElementType(const ComputedStyle& style,
const Element* element);
+ void UpdateForcedColorsState();
+
Color custom_focus_ring_color_;
bool has_custom_focus_ring_color_;
base::TimeDelta caret_blink_interval_ =
base::TimeDelta::FromMilliseconds(500);
bool delegates_menu_list_rendering_ = false;
+ bool in_forced_colors_mode_ = false;
// This color is expected to be drawn on a semi-transparent overlay,
// making it more transparent than its alpha value indicates.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_android.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_android.cc
index 0a82087b899..4e437e67e77 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_android.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_android.cc
@@ -19,19 +19,6 @@ LayoutTheme& LayoutTheme::NativeTheme() {
LayoutThemeAndroid::~LayoutThemeAndroid() {}
-String LayoutThemeAndroid::ExtraDefaultStyleSheet() {
- String extra_sheet = LayoutThemeMobile::ExtraDefaultStyleSheet();
- if (features::IsFormControlsRefreshEnabled())
- return extra_sheet;
-
- // "32px" comes from
- // 2 * -LayoutThemeDefault::SliderTickOffsetFromTrackCenter().
- return extra_sheet + R"CSS(
-input[type="range" i]:-internal-has-datalist::-webkit-slider-container {
- min-block-size: 32px;
-})CSS";
-}
-
Color LayoutThemeAndroid::PlatformActiveSelectionBackgroundColor(
mojom::blink::ColorScheme color_scheme) const {
return color_scheme == mojom::blink::ColorScheme::kDark
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_android.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_android.h
index ed6a72b4f0d..d3cd0dd9929 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_android.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_android.h
@@ -13,7 +13,6 @@ class LayoutThemeAndroid final : public LayoutThemeMobile {
public:
static scoped_refptr<LayoutTheme> Create();
bool DelegatesMenuListRendering() const override { return true; }
- String ExtraDefaultStyleSheet() override;
Color PlatformActiveSelectionBackgroundColor(
mojom::blink::ColorScheme color_scheme) const override;
Color PlatformActiveSelectionForegroundColor(
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 4f4845e7c44..f03e948e228 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
@@ -63,21 +63,11 @@ String LayoutThemeDefault::ExtraDefaultStyleSheet() {
? UncompressResourceAsASCIIString(
IDR_UASTYLE_THEME_INPUT_MULTIPLE_FIELDS_CSS)
: String();
- String windows_style_sheet =
- UncompressResourceAsASCIIString(IDR_UASTYLE_THEME_WIN_CSS);
- String controls_refresh_style_sheet =
- features::IsFormControlsRefreshEnabled()
- ? UncompressResourceAsASCIIString(
- IDR_UASTYLE_THEME_CONTROLS_REFRESH_CSS)
- : String();
StringBuilder builder;
- builder.ReserveCapacity(
- extra_style_sheet.length() + multiple_fields_style_sheet.length() +
- windows_style_sheet.length() + controls_refresh_style_sheet.length());
+ builder.ReserveCapacity(extra_style_sheet.length() +
+ multiple_fields_style_sheet.length());
builder.Append(extra_style_sheet);
builder.Append(multiple_fields_style_sheet);
- builder.Append(windows_style_sheet);
- builder.Append(controls_refresh_style_sheet);
return builder.ToString();
}
@@ -108,19 +98,13 @@ Color LayoutThemeDefault::PlatformInactiveSelectionForegroundColor(
IntSize LayoutThemeDefault::SliderTickSize() const {
// The value should be synchronized with a -webkit-slider-container rule in
// html.css.
- if (features::IsFormControlsRefreshEnabled())
- return IntSize(1, 4);
- else
- return IntSize(1, 6);
+ return IntSize(1, 4);
}
int LayoutThemeDefault::SliderTickOffsetFromTrackCenter() const {
// The value should be synchronized with a -webkit-slider-container rule in
// html.css and LayoutThemeAndroid::ExtraDefaultStyleSheet().
- if (features::IsFormControlsRefreshEnabled())
- return 7;
- else
- return -16;
+ return 7;
}
void LayoutThemeDefault::AdjustSliderThumbSize(ComputedStyle& style) const {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc
index fe3c34ef54b..87ececf815e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc
@@ -25,11 +25,16 @@
#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
+#include "third_party/blink/renderer/core/css/font_size_functions.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
+constexpr float kDefaultFontSizeFallback = 16.0;
+
// We aim to match IE here.
// -IE uses a font based on the encoding as the default font for form controls.
// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
@@ -44,4 +49,17 @@ const AtomicString& LayoutThemeFontProvider::DefaultGUIFont() {
return font_face;
}
+float LayoutThemeFontProvider::DefaultFontSize(const Document* document) {
+ const Settings* settings = document ? document->GetSettings() : nullptr;
+
+ // The default font size setting may be uninitialized in some cases, like
+ // in the calendar picker of an <input type=date> widget.
+ if (!settings || !settings->GetDefaultFontSize())
+ return kDefaultFontSizeFallback;
+
+ static const unsigned keyword = FontSizeFunctions::InitialKeywordSize();
+ static const bool is_monospace = false;
+ return FontSizeFunctions::FontSizeForKeyword(document, keyword, is_monospace);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.h
index d76f8905dbf..32e472add6c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider.h
@@ -34,18 +34,21 @@
namespace blink {
+class Document;
+
class CORE_EXPORT LayoutThemeFontProvider {
STATIC_ONLY(LayoutThemeFontProvider);
public:
- static void SystemFont(CSSValueID system_font_id,
- FontSelectionValue& slope,
- FontSelectionValue& weight,
- float& font_size,
- AtomicString& font_family);
+ static const FontSelectionValue& SystemFontStyle(CSSValueID system_font_id);
+ static const FontSelectionValue& SystemFontWeight(CSSValueID system_font_id);
+ static const AtomicString& SystemFontFamily(CSSValueID system_font_id);
+ static float SystemFontSize(CSSValueID system_font_id,
+ const Document* document);
protected:
static const WTF::AtomicString& DefaultGUIFont();
+ static float DefaultFontSize(const Document*);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc
index 744790ab906..0119c5d52a0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc
@@ -33,19 +33,27 @@
namespace blink {
-constexpr float kDefaultFontSize = 16.0;
+// static
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontStyle(
+ CSSValueID system_font_id) {
+ return NormalSlopeValue();
+}
// static
-void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
- FontSelectionValue& font_slope,
- FontSelectionValue& font_weight,
- float& font_size,
- AtomicString& font_family) {
- font_weight = NormalWeightValue();
- font_slope = NormalSlopeValue();
- font_size = kDefaultFontSize;
- font_family = DefaultGUIFont();
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontWeight(
+ CSSValueID system_font_id) {
+ return NormalWeightValue();
+}
+// static
+const AtomicString& LayoutThemeFontProvider::SystemFontFamily(
+ CSSValueID system_font_id) {
+ return DefaultGUIFont();
+}
+
+// static
+float LayoutThemeFontProvider::SystemFontSize(CSSValueID system_font_id,
+ const Document* document) {
switch (system_font_id) {
case CSSValueID::kWebkitMiniControl:
case CSSValueID::kWebkitSmallControl:
@@ -55,10 +63,10 @@ void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
// Windows.
static const float kPointsPerInch = 72.0f;
static const float kPixelsPerInch = 96.0f;
- font_size -= (2.0f / kPointsPerInch) * kPixelsPerInch;
- break;
+ return DefaultFontSize(document) -
+ (2.0f / kPointsPerInch) * kPixelsPerInch;
default:
- break;
+ return DefaultFontSize(document);
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc
index 0d690783e4e..b806f1ac5b9 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc
@@ -32,8 +32,6 @@
namespace blink {
-constexpr float kDefaultFontSize = 16.0;
-
// Converts |points| to pixels. One point is 1/72 of an inch.
static float PointsToPixels(float points) {
const float kPixelsPerInch = 96.0f;
@@ -42,38 +40,49 @@ static float PointsToPixels(float points) {
}
// static
-void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
- FontSelectionValue& font_style,
- FontSelectionValue& font_weight,
- float& font_size,
- AtomicString& font_family) {
- font_style = NormalSlopeValue();
- font_weight = NormalWeightValue();
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontStyle(
+ CSSValueID system_font_id) {
+ return NormalSlopeValue();
+}
+
+// static
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontWeight(
+ CSSValueID system_font_id) {
+ return NormalWeightValue();
+}
+// static
+const AtomicString& LayoutThemeFontProvider::SystemFontFamily(
+ CSSValueID system_font_id) {
+ switch (system_font_id) {
+ case CSSValueID::kSmallCaption:
+ return FontCache::SmallCaptionFontFamily();
+ case CSSValueID::kMenu:
+ return FontCache::MenuFontFamily();
+ case CSSValueID::kStatusBar:
+ return FontCache::StatusFontFamily();
+ default:
+ return DefaultGUIFont();
+ }
+}
+
+// static
+float LayoutThemeFontProvider::SystemFontSize(CSSValueID system_font_id,
+ const Document* document) {
switch (system_font_id) {
case CSSValueID::kSmallCaption:
- font_size = FontCache::SmallCaptionFontHeight();
- font_family = FontCache::SmallCaptionFontFamily();
- break;
+ return FontCache::SmallCaptionFontHeight();
case CSSValueID::kMenu:
- font_size = FontCache::MenuFontHeight();
- font_family = FontCache::MenuFontFamily();
- break;
+ return FontCache::MenuFontHeight();
case CSSValueID::kStatusBar:
- font_size = FontCache::StatusFontHeight();
- font_family = FontCache::StatusFontFamily();
- break;
+ return FontCache::StatusFontHeight();
case CSSValueID::kWebkitMiniControl:
case CSSValueID::kWebkitSmallControl:
case CSSValueID::kWebkitControl:
// Why 2 points smaller? Because that's what Gecko does.
- font_size = kDefaultFontSize - PointsToPixels(2);
- font_family = DefaultGUIFont();
- break;
+ return DefaultFontSize(document) - PointsToPixels(2);
default:
- font_size = kDefaultFontSize;
- font_family = DefaultGUIFont();
- break;
+ return DefaultFontSize(document);
}
}
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 6ee2b55438e..165d0637ef4 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
@@ -36,6 +36,9 @@ namespace blink {
namespace {
Color GetSystemColor(MacSystemColorID color_id,
mojom::blink::ColorScheme color_scheme) {
+ // TODO(almaher): Consider using the mac light and dark high-contrast themes
+ // here instead if forced colors mode is enabled.
+
// In tests, a WebSandboxSupport may not be set up. Just return a dummy
// color, in this case, black.
auto* sandbox_support = Platform::Current()->GetSandboxSupport();
@@ -86,7 +89,7 @@ bool LayoutThemeMac::IsAccentColorCustomized(
return false;
}
} else {
- int user_custom_color = [[NSUserDefaults standardUserDefaults]
+ NSInteger user_custom_color = [[NSUserDefaults standardUserDefaults]
integerForKey:@"AppleAquaColorVariant"];
if (user_custom_color == NSBlueControlTint ||
user_custom_color == NSDefaultControlTint) {
@@ -101,8 +104,8 @@ Color LayoutThemeMac::GetAccentColor(
if (@available(macOS 10.14, *)) {
return GetSystemColor(MacSystemColorID::kControlAccentColor, color_scheme);
} else {
- return [[NSUserDefaults standardUserDefaults]
- integerForKey:@"AppleAquaColorVariant"];
+ return static_cast<RGBA32>([[NSUserDefaults standardUserDefaults]
+ integerForKey:@"AppleAquaColorVariant"]);
}
}
@@ -150,7 +153,6 @@ bool LayoutThemeMac::UsesTestModeFocusRingColor() const {
}
LayoutTheme& LayoutTheme::NativeTheme() {
- DCHECK(features::IsFormControlsRefreshEnabled());
DEFINE_STATIC_REF(LayoutTheme, layout_theme, (LayoutThemeMac::Create()));
return *layout_theme;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_test.cc
index 10d1803e85d..b540de3217a 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_test.cc
@@ -19,14 +19,11 @@
#include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
-class LayoutThemeTest : public PageTestBase,
- private ScopedCSSColorSchemeUARenderingForTest {
+class LayoutThemeTest : public PageTestBase {
protected:
- LayoutThemeTest() : ScopedCSSColorSchemeUARenderingForTest(true) {}
void SetHtmlInnerHTML(const char* html_content);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_win.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_win.cc
index d86479e8183..6de3166cfb8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_win.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_win.cc
@@ -23,55 +23,14 @@ LayoutTheme& LayoutTheme::NativeTheme() {
Color LayoutThemeWin::SystemColor(
CSSValueID css_value_id,
mojom::blink::ColorScheme color_scheme) const {
- blink::WebThemeEngine::SystemThemeColor theme_color;
- switch (css_value_id) {
- case CSSValueID::kActivetext:
- case CSSValueID::kLinktext:
- case CSSValueID::kVisitedtext:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kHotlight;
- break;
- case CSSValueID::kButtonface:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonFace;
- break;
- case CSSValueID::kButtontext:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonText;
- break;
- case CSSValueID::kGraytext:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kGrayText;
- break;
- case CSSValueID::kHighlight:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlight;
- break;
- case CSSValueID::kHighlighttext:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlightText;
- break;
- case CSSValueID::kWindow:
- case CSSValueID::kCanvas:
- case CSSValueID::kField:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kWindow;
- break;
- case CSSValueID::kWindowtext:
- case CSSValueID::kCanvastext:
- case CSSValueID::kFieldtext:
- theme_color = blink::WebThemeEngine::SystemThemeColor::kWindowText;
- break;
- default:
- return LayoutThemeDefault::SystemColor(css_value_id, color_scheme);
- }
-
// Fall back to the default system colors if the color scheme is dark and
// forced colors is not enabled.
- if (!WebTestSupport::IsRunningWebTest() && Platform::Current() &&
- Platform::Current()->ThemeEngine() &&
- (color_scheme != mojom::blink::ColorScheme::kDark ||
- Platform::Current()->ThemeEngine()->GetForcedColors() !=
- ForcedColors::kNone)) {
- const absl::optional<SkColor> system_color =
- Platform::Current()->ThemeEngine()->GetSystemColor(theme_color);
- if (system_color)
- return Color(system_color.value());
+ if (WebTestSupport::IsRunningWebTest() ||
+ (color_scheme == mojom::blink::ColorScheme::kDark &&
+ !InForcedColorsMode())) {
+ return DefaultSystemColor(css_value_id, color_scheme);
}
- return LayoutThemeDefault::SystemColor(css_value_id, color_scheme);
+ return SystemColorFromNativeTheme(css_value_id, color_scheme);
}
} // namespace blink
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 0c43bb6dd5a..db90b9f7ee1 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
@@ -323,7 +323,7 @@ static void WriteInlineBox(WTF::TextStream& ts,
<< " pos=(" << box.X() << "," << box.Y() << ")"
<< " size=(" << box.Width() << "," << box.Height() << ")"
<< " baseline=" << box.BaselinePosition(kAlphabeticBaseline) << "/"
- << box.BaselinePosition(kIdeographicBaseline);
+ << box.BaselinePosition(kCentralBaseline);
}
static void WriteInlineTextBox(WTF::TextStream& ts,
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 284b62d0356..c60c3f89546 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_video.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_video.cc
@@ -198,18 +198,6 @@ void LayoutVideo::UpdatePlayer(bool is_in_layout) {
VideoElement()->SetNeedsCompositingUpdate();
}
-LayoutUnit LayoutVideo::ComputeReplacedLogicalWidth(
- ShouldComputePreferred should_compute_preferred) const {
- NOT_DESTROYED();
- return LayoutReplaced::ComputeReplacedLogicalWidth(should_compute_preferred);
-}
-
-LayoutUnit LayoutVideo::ComputeReplacedLogicalHeight(
- LayoutUnit estimated_used_width) const {
- NOT_DESTROYED();
- return LayoutReplaced::ComputeReplacedLogicalHeight(estimated_used_width);
-}
-
LayoutUnit LayoutVideo::MinimumReplacedHeight() const {
NOT_DESTROYED();
return LayoutReplaced::MinimumReplacedHeight();
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 ba3fce88dc7..745bfe41e63 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_video.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_video.h
@@ -79,10 +79,6 @@ class LayoutVideo final : public LayoutMedia {
void UpdateLayout() override;
- LayoutUnit ComputeReplacedLogicalWidth(
- ShouldComputePreferred = kComputeActual) const override;
- LayoutUnit ComputeReplacedLogicalHeight(
- LayoutUnit estimated_used_width = LayoutUnit()) const override;
LayoutUnit MinimumReplacedHeight() const override;
bool CanHaveAdditionalCompositingReasons() const override {
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 0095ca858c8..1e1dba5cbf1 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.cc
@@ -25,9 +25,9 @@
#include "build/build_config.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/public/platform/platform.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/editing/frame_selection.h"
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/plugin_document.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_counter.h"
@@ -61,6 +62,7 @@
#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/runtime_enabled_features.h"
+#include "ui/display/screen_info.h"
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
@@ -566,8 +568,7 @@ bool LayoutView::MapToVisualRectInAncestorSpaceInternal(
PhysicalOffset LayoutView::OffsetForFixedPosition() const {
NOT_DESTROYED();
- return IsScrollContainer() ? PhysicalOffset(ScrolledContentOffset())
- : PhysicalOffset();
+ return IsScrollContainer() ? ScrolledContentOffset() : PhysicalOffset();
}
PhysicalOffset LayoutView::PixelSnappedOffsetForFixedPosition() const {
@@ -780,11 +781,6 @@ LayoutUnit LayoutView::ViewLogicalHeightForPercentages() const {
return LayoutUnit(ViewLogicalHeight());
}
-float LayoutView::ZoomFactor() const {
- NOT_DESTROYED();
- return frame_view_->GetFrame().PageZoomFactor();
-}
-
const LayoutBox& LayoutView::RootBox() const {
NOT_DESTROYED();
Element* document_element = GetDocument().documentElement();
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 ff7eed31b7c..7da0732c4ca 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.h
@@ -134,8 +134,6 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
LayoutUnit ViewLogicalHeightForPercentages() const;
- float ZoomFactor() const;
-
LocalFrameView* GetFrameView() const {
NOT_DESTROYED();
return frame_view_;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc
index 1ee52224a0f..9300a517404 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.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/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/page/named_pages_mapper.h"
@@ -209,6 +210,43 @@ TEST_P(LayoutViewHitTestTest, EmptySpan) {
EXPECT_EQ(after_ab, HitTest(55, 5));
}
+// http://crbug.com/1233862
+TEST_P(LayoutViewHitTestTest, FlexBlockChildren) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { margin: 0px; font: 10px/10px Ahem; }"
+ "#t { display: flex; }");
+ SetBodyInnerHTML("<div id=t><div id=ab>ab</div><div id=xy>XY</div></div>");
+
+ const auto& ab = *To<Text>(GetElementById("ab")->firstChild());
+ const auto& xy = *To<Text>(GetElementById("xy")->firstChild());
+
+ EXPECT_EQ(PositionWithAffinity(Position(ab, 0)), HitTest(0, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(ab, 0)), HitTest(5, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(ab, 1),
+ LayoutNG() ? TextAffinity::kDownstream
+ : TextAffinity::kUpstream),
+ HitTest(10, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(ab, 1),
+ LayoutNG() ? TextAffinity::kDownstream
+ : TextAffinity::kUpstream),
+ HitTest(15, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(xy, 0)), HitTest(20, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(xy, 0)), HitTest(25, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(xy, 1),
+ LayoutNG() ? TextAffinity::kDownstream
+ : TextAffinity::kUpstream),
+ HitTest(30, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(xy, 1),
+ LayoutNG() ? TextAffinity::kDownstream
+ : TextAffinity::kUpstream),
+ HitTest(35, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(xy, 2), TextAffinity::kUpstream),
+ HitTest(40, 5));
+ EXPECT_EQ(PositionWithAffinity(Position(xy, 2), TextAffinity::kUpstream),
+ HitTest(45, 5));
+}
+
// http://crbug.com/1171070
// See also, FloatLeft*, DOM order of "float" should not affect hit testing.
TEST_P(LayoutViewHitTestTest, FloatLeftLeft) {
@@ -1042,4 +1080,256 @@ TEST_P(LayoutViewHitTestTest, PseudoElementAfterBlockWithMargin) {
EXPECT_EQ(expected, HitTest(55, 5)) << "after XY";
}
+TEST_P(LayoutViewHitTestTest, TextAndInputsWithRtlDirection) {
+ LoadAhem();
+ InsertStyleElement(R"CSS(
+ body {
+ margin: 0 auto 0 0;
+ direction: rtl;
+ width: 200px;
+ font: 50px/1 Ahem;
+ }
+ input {
+ width: 100px;
+ height: 50px;
+ box-sizing: border-box;
+ vertical-align: top;
+ }
+ )CSS");
+ SetBodyInnerHTML("ab<input><input>cd");
+
+ Element* body = GetDocument().body();
+ Node* text_ab = body->firstChild();
+ Node* input_1 = text_ab->nextSibling();
+ Node* input_2 = input_1->nextSibling();
+ Node* text_cd = input_2->nextSibling();
+ Node* shadow_div_1 = input_1->GetShadowRoot()->firstChild();
+ Node* shadow_div_2 = input_2->GetShadowRoot()->firstChild();
+ TextAffinity downstream_if_ng =
+ LayoutNG() ? TextAffinity::kDownstream : TextAffinity::kUpstream;
+
+ // Note: This is a crash test. The expectations only reflect the current
+ // behavior, which may change.
+ for (int y : {0, 25, 49}) {
+ for (int x : {0, 25}) {
+ EXPECT_EQ(PositionWithAffinity(Position::AfterNode(*input_1),
+ LayoutNG() ? TextAffinity::kUpstream
+ : TextAffinity::kDownstream),
+ HitTest(x, y));
+ }
+ for (int x : {26, 50, 75}) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_ab, 1), downstream_if_ng),
+ HitTest(x, y));
+ }
+ for (int x : {76, 99}) {
+ EXPECT_EQ(
+ PositionWithAffinity(Position(text_ab, 2), TextAffinity::kUpstream),
+ HitTest(x, y));
+ }
+ for (int x : {100, 125, 150, 175, 199}) {
+ EXPECT_EQ(PositionWithAffinity(Position(shadow_div_1, 0)), HitTest(x, y));
+ }
+ EXPECT_EQ(PositionWithAffinity(Position::AfterNode(*input_1)),
+ HitTest(200, y));
+ }
+ for (int y : {50, 75, 99}) {
+ for (int x : {0, 25, 50, 75, 99}) {
+ EXPECT_EQ(PositionWithAffinity(Position(shadow_div_2, 0)), HitTest(x, y));
+ }
+ for (int x : {100, 125}) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 0)), HitTest(x, y));
+ }
+ for (int x : {126, 150, 175}) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 1), downstream_if_ng),
+ HitTest(x, y));
+ }
+ for (int x : {176, 200}) {
+ EXPECT_EQ(PositionWithAffinity(LayoutNG() ? Position::BeforeNode(*input_2)
+ : Position(input_2, 0)),
+ HitTest(x, y));
+ }
+ }
+ if (IsAndroidOrWindowsEditingBehavior()) {
+ for (int x : {0, 25, 50, 75, 99}) {
+ EXPECT_EQ(PositionWithAffinity(Position::AfterNode(*input_2)),
+ HitTest(x, 100));
+ }
+ for (int x : {100, 125}) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 0)), HitTest(x, 100));
+ }
+ for (int x : {126, 150, 175}) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 1), downstream_if_ng),
+ HitTest(x, 100));
+ }
+ for (int x : {176, 200}) {
+ EXPECT_EQ(PositionWithAffinity(LayoutNG() ? Position::BeforeNode(*input_2)
+ : Position(input_2, 0)),
+ HitTest(x, 100));
+ }
+ } else {
+ for (int x : {0, 25, 50, 75, 100, 125, 150, 175, 200}) {
+ EXPECT_EQ(PositionWithAffinity(LayoutNG() ? Position::AfterNode(*input_2)
+ : Position(text_cd, 2)),
+ HitTest(x, 100));
+ }
+ }
+}
+
+TEST_P(LayoutViewHitTestTest, TextCombineOneTextNode) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "body { margin: 0px; font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div>a<c id=target>01234</c>b</div>");
+ // LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+ // LayoutNGBlockFlow {BODY} at (0,0) size 800x600
+ // LayoutNGBlockFlow {DIV} at (0,0) size 110x300
+ // LayoutText {#text} at (5,0) size 100x100
+ // text run at (5,0) width 100: "a"
+ // LayoutInline {C} at (5,100) size 100x100
+ // LayoutNGTextCombine (anonymous) at (5,100) size 100x100
+ // LayoutText {#text} at (-5,0) size 110x100
+ // text run at (0,0) width 500: "01234"
+ // LayoutText {#text} at (5,200) size 100x100
+ // text run at (5,200) width 100: "b"
+ const auto& target = *GetElementById("target");
+ const auto& text_01234 = *To<Text>(target.firstChild());
+ const auto& text_a = *To<Text>(target.previousSibling());
+ const auto& text_b = *To<Text>(target.nextSibling());
+
+ if (LayoutNG()) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(0, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(10, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 1)), HitTest(20, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 1)), HitTest(30, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 2)), HitTest(40, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 2)), HitTest(50, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 3)), HitTest(60, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 3)), HitTest(70, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 4)), HitTest(80, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 4)), HitTest(90, 150));
+ EXPECT_EQ(
+ PositionWithAffinity(Position(text_01234, 5), TextAffinity::kUpstream),
+ HitTest(100, 150));
+ // TODO(yosin): should be text_01234@5
+ if (IsAndroidOrWindowsEditingBehavior()) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_b, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_b, 0)), HitTest(120, 150));
+ } else {
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(120, 150));
+ }
+ } else {
+ // Note: Hit test for legacy layout is broken. This is just record of
+ // current behavior.
+ if (IsAndroidOrWindowsEditingBehavior())
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(0, 150));
+ else
+ EXPECT_EQ(PositionWithAffinity(Position(text_b, 1)), HitTest(0, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(10, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(20, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(30, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(40, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(50, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(60, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(70, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(80, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(90, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)), HitTest(100, 150));
+ if (IsAndroidOrWindowsEditingBehavior()) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)),
+ HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_01234, 0)),
+ HitTest(120, 150));
+ } else {
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(120, 150));
+ }
+ }
+}
+
+TEST_P(LayoutViewHitTestTest, TextCombineTwoTextNodes) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "body { margin: 0px; font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div>a<c id=target>012<wbr>34</c>b</div>");
+ // LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+ // LayoutNGBlockFlow {BODY} at (0,0) size 800x600
+ // LayoutNGBlockFlow {DIV} at (0,0) size 110x300
+ // LayoutText {#text} at (5,0) size 100x100
+ // text run at (5,0) width 100: "a"
+ // LayoutInline {C} at (5,100) size 100x100
+ // LayoutNGTextCombine (anonymous) at (5,100) size 100x100
+ // LayoutText {#text} at (-5,0) size 66x100
+ // text run at (0,0) width 300: "012"
+ // LayoutWordBreak {WBR} at (61,0) size 0x100
+ // text run at (300,0) width 0: "\x{200B}"
+ // LayoutText {#text} at (61,0) size 44x100
+ // text run at (300,0) width 200: "34"
+ // LayoutInline {B} at (5,200) size 100x100
+ // LayoutText {#text} at (5,200) size 100x100
+ // text run at (5,200) width 100: "b"
+ // const auto& target = *GetElementById("target");
+ const auto& target = *GetElementById("target");
+ const auto& text_012 = *To<Text>(target.firstChild());
+ const auto& text_34 = *To<Text>(target.lastChild());
+ const auto& text_a = *To<Text>(target.previousSibling());
+ const auto& text_b = *To<Text>(target.nextSibling());
+
+ if (LayoutNG()) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(0, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(10, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 1)), HitTest(20, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 1)), HitTest(30, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 2)), HitTest(40, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 2)), HitTest(50, 150));
+ EXPECT_EQ(
+ PositionWithAffinity(Position(text_012, 3), TextAffinity::kUpstream),
+ HitTest(60, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_34, 0)), HitTest(70, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_34, 1)), HitTest(80, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_34, 1)), HitTest(90, 150));
+ EXPECT_EQ(
+ PositionWithAffinity(Position(text_34, 2), TextAffinity::kUpstream),
+ HitTest(100, 150));
+ // TODO(yosin): should be text_012@5
+ if (IsAndroidOrWindowsEditingBehavior()) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_b, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_b, 0)), HitTest(120, 150));
+ } else {
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(120, 150));
+ }
+ } else {
+ // Note: Hit test for legacy layout is broken. This is just record of
+ // current behavior.
+ if (IsAndroidOrWindowsEditingBehavior())
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(0, 150));
+ else
+ EXPECT_EQ(PositionWithAffinity(Position(text_b, 1)), HitTest(0, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(10, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(20, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(30, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(40, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(50, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(60, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(70, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(80, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(90, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(100, 150));
+ if (IsAndroidOrWindowsEditingBehavior()) {
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_012, 0)), HitTest(120, 150));
+ } else {
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(110, 150));
+ EXPECT_EQ(PositionWithAffinity(Position(text_a, 0)), HitTest(120, 150));
+ }
+ }
+}
+
} // namespace blink
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 cbf40a2cfa8..25645ebba1f 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
@@ -172,7 +172,7 @@ unsigned LegacyAbstractInlineTextBox::TextOffsetInFormattingContext(
// return a more exact offset in our formatting context. Otherwise, we need to
// approximate the offset using our associated layout object.
if (node && node->IsTextNode()) {
- const Position position(node, int{offset_in_parent});
+ const Position position(node, static_cast<int>(offset_in_parent));
LayoutBlockFlow* formatting_context =
NGOffsetMapping::GetInlineFormattingContextOf(position);
// If "formatting_context" is not a Layout NG object, the offset mappings
@@ -253,8 +253,11 @@ void AbstractInlineTextBox::GetWordBoundaries(
return;
TextBreakIterator* it = WordBreakIterator(text, 0, text.length());
+ if (!it)
+ return;
absl::optional<int> word_start;
- for (int offset = 0; offset != kTextBreakDone && offset < int{text.length()};
+ for (int offset = 0;
+ offset != kTextBreakDone && offset < static_cast<int>(text.length());
offset = it->following(offset)) {
// Unlike in ICU's WordBreakIterator, a word boundary is valid only if it is
// before, or immediately preceded by, an alphanumeric character, a series
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 51891cf041f..17f3102122b 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
@@ -147,7 +147,7 @@ void InlineBox::DumpBox(StringBuilder& string_inlinebox) const {
GetLineLayoutItem().DebugPointer(), X().ToFloat(), Y().ToFloat(),
Width().ToFloat(), Height().ToFloat(),
BaselinePosition(kAlphabeticBaseline).ToInt(),
- BaselinePosition(kIdeographicBaseline).ToInt());
+ BaselinePosition(kCentralBaseline).ToInt());
}
#endif // DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.cc b/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
index f98ae0fa882..0ce63a8e55d 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
@@ -556,7 +556,7 @@ FontBaseline InlineFlowBox::DominantBaseline() const {
.Style(IsFirstLineStyle())
->GetFontDescription()
.IsVerticalAnyUpright())
- return kIdeographicBaseline;
+ return kCentralBaseline;
return kAlphabeticBaseline;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.h b/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.h
index 00fd78bec68..655d0a2570d 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_flow_box.h
@@ -491,7 +491,7 @@ class InlineFlowBox : public InlineBox {
// Whether or not this line uses alphabetic or ideographic baselines by
// default.
- unsigned baseline_type_ : 1; // FontBaseline
+ unsigned baseline_type_ : 3; // FontBaseline
// If the line contains any ruby runs, then this will be true.
unsigned has_annotations_before_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box_test.cc b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box_test.cc
index 69caeb4f3ed..5956a1ec5d5 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
namespace blink {
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 3d772959c38..0f3925a2ae6 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
@@ -295,8 +295,6 @@ LayoutUnit RootInlineBox::AlignBoxesInBlockDirection(
LayoutUnit annotations_adjustment = BeforeAnnotationsAdjustment();
if (annotations_adjustment) {
- // FIXME: Need to handle pagination here. We might have to move to the next
- // page/column as a result of the ruby expansion.
MoveInBlockDirection(annotations_adjustment);
height_of_block += annotations_adjustment;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/list_marker.cc b/chromium/third_party/blink/renderer/core/layout/list_marker.cc
index 398cc5f37bc..2bd411926b8 100644
--- a/chromium/third_party/blink/renderer/core/layout/list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/list_marker.cc
@@ -5,12 +5,13 @@
#include "third_party/blink/renderer/core/layout/list_marker.h"
#include "third_party/blink/renderer/core/css/counter_style.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h"
#include "third_party/blink/renderer/core/layout/layout_inside_list_marker.h"
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_list_marker_image.h"
#include "third_party/blink/renderer/core/layout/layout_outside_list_marker.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
@@ -106,7 +107,6 @@ void ListMarker::ListStyleTypeChanged(LayoutObject& marker) {
// If the @counter-style in use has changed, we need to update the marker text.
void ListMarker::CounterStyleChanged(LayoutObject& marker) {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
DCHECK_EQ(Get(&marker), this);
if (marker_text_type_ == kNotText || marker_text_type_ == kUnresolved)
return;
@@ -125,14 +125,29 @@ void ListMarker::OrdinalValueChanged(LayoutObject& marker) {
}
}
+LayoutObject* ListMarker::GetContentChild(const LayoutObject& marker) const {
+ DCHECK_EQ(Get(&marker), this);
+ LayoutObject* const first_child = marker.SlowFirstChild();
+ if (IsA<LayoutNGTextCombine>(first_child))
+ return first_child->SlowFirstChild();
+ return first_child;
+}
+
+LayoutText& ListMarker::GetTextChild(const LayoutObject& marker) const {
+ auto& text = *To<LayoutText>(GetContentChild(marker));
+ // There should be a single text child
+ DCHECK(!text.NextSibling());
+ return text;
+}
+
void ListMarker::UpdateMarkerText(LayoutObject& marker) {
DCHECK_EQ(Get(&marker), this);
+ auto& text = GetTextChild(marker);
DCHECK_EQ(marker_text_type_, kUnresolved);
- LayoutText* const text = To<LayoutText>(marker.SlowFirstChild());
StringBuilder marker_text_builder;
marker_text_type_ =
MarkerText(marker, &marker_text_builder, kWithPrefixSuffix);
- text->SetTextIfNeeded(marker_text_builder.ToString().ReleaseImpl());
+ text.SetTextIfNeeded(marker_text_builder.ToString().ReleaseImpl());
DCHECK_NE(marker_text_type_, kNotText);
DCHECK_NE(marker_text_type_, kUnresolved);
}
@@ -158,38 +173,25 @@ ListMarker::MarkerTextType ListMarker::MarkerText(
case ListStyleCategory::kStaticString:
text->Append(style.ListStyleStringValue());
return kStatic;
- case ListStyleCategory::kSymbol:
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- const CounterStyle& counter_style =
- GetCounterStyle(marker.GetDocument(), style);
- if (format == kWithPrefixSuffix)
- text->Append(counter_style.GetPrefix());
- text->Append(counter_style.GenerateRepresentation(0));
- if (format == kWithPrefixSuffix)
- text->Append(counter_style.GetSuffix());
- } else {
- text->Append(list_marker_text::GetText(style.ListStyleType(), 0));
- if (format == kWithPrefixSuffix)
- text->Append(' ');
- }
+ case ListStyleCategory::kSymbol: {
+ const CounterStyle& counter_style =
+ GetCounterStyle(marker.GetDocument(), style);
+ if (format == kWithPrefixSuffix)
+ text->Append(counter_style.GetPrefix());
+ text->Append(counter_style.GenerateRepresentation(0));
+ if (format == kWithPrefixSuffix)
+ text->Append(counter_style.GetSuffix());
return kSymbolValue;
+ }
case ListStyleCategory::kLanguage: {
int value = ListItemValue(*list_item);
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- const CounterStyle& counter_style =
- GetCounterStyle(marker.GetDocument(), style);
- if (format == kWithPrefixSuffix)
- text->Append(counter_style.GetPrefix());
- text->Append(counter_style.GenerateRepresentation(value));
- if (format == kWithPrefixSuffix)
- text->Append(counter_style.GetSuffix());
- } else {
- text->Append(list_marker_text::GetText(style.ListStyleType(), value));
- if (format == kWithPrefixSuffix) {
- text->Append(list_marker_text::Suffix(style.ListStyleType(), value));
- text->Append(' ');
- }
- }
+ const CounterStyle& counter_style =
+ GetCounterStyle(marker.GetDocument(), style);
+ if (format == kWithPrefixSuffix)
+ text->Append(counter_style.GetPrefix());
+ text->Append(counter_style.GenerateRepresentation(value));
+ if (format == kWithPrefixSuffix)
+ text->Append(counter_style.GetSuffix());
return kOrdinalValue;
}
}
@@ -219,14 +221,7 @@ String ListMarker::TextAlternative(const LayoutObject& marker) const {
// RTL, reflecting speech order.
return MarkerTextWithSuffix(marker);
}
-
- LayoutObject* child = marker.SlowFirstChild();
-
- // There should be a single text child
- DCHECK(child);
- DCHECK(!child->NextSibling());
-
- return To<LayoutText>(child)->PlainText();
+ return GetTextChild(marker).PlainText();
}
void ListMarker::UpdateMarkerContentIfNeeded(LayoutObject& marker) {
@@ -237,8 +232,7 @@ void ListMarker::UpdateMarkerContentIfNeeded(LayoutObject& marker) {
}
// There should be at most one child.
- LayoutObject* child = marker.SlowFirstChild();
- DCHECK(!child || !child->NextSibling());
+ LayoutObject* child = GetContentChild(marker);
const ComputedStyle& style = ListItem(marker)->StyleRef();
if (IsMarkerImage(marker)) {
@@ -248,7 +242,10 @@ void ListMarker::UpdateMarkerContentIfNeeded(LayoutObject& marker) {
if (!child->IsLayoutImage() ||
To<LayoutImage>(child)->ImageResource()->ImagePtr() !=
list_style_image->Data()) {
- child->Destroy();
+ if (UNLIKELY(IsA<LayoutNGTextCombine>(child->Parent())))
+ child->Parent()->Destroy();
+ else
+ child->Destroy();
child = nullptr;
}
}
@@ -273,7 +270,7 @@ void ListMarker::UpdateMarkerContentIfNeeded(LayoutObject& marker) {
return;
}
- if (!style.GetListStyleType()) {
+ if (!style.ListStyleType()) {
marker_text_type_ = kNotText;
return;
}
@@ -281,9 +278,10 @@ void ListMarker::UpdateMarkerContentIfNeeded(LayoutObject& marker) {
// |text_style| should be as same as style propagated in
// |LayoutObject::PropagateStyleToAnonymousChildren()| to avoid unexpected
// full layout due by style difference. See http://crbug.com/980399
+ const auto& style_parent = child ? *child->Parent() : marker;
scoped_refptr<ComputedStyle> text_style =
marker.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
- marker.StyleRef(), marker.StyleRef().Display());
+ style_parent.StyleRef(), marker.StyleRef().Display());
if (IsA<LayoutText>(child))
return child->SetStyle(text_style);
if (child)
@@ -300,7 +298,7 @@ LayoutObject* ListMarker::SymbolMarkerLayoutText(
DCHECK_EQ(Get(&marker), this);
if (marker_text_type_ != kSymbolValue)
return nullptr;
- return marker.SlowFirstChild();
+ return GetContentChild(marker);
}
bool ListMarker::IsMarkerImage(const LayoutObject& marker) const {
@@ -315,7 +313,11 @@ LayoutUnit ListMarker::WidthOfSymbol(const ComputedStyle& style) {
DCHECK(font_data);
if (!font_data)
return LayoutUnit();
- const AtomicString& name = style.GetListStyleType()->GetCounterStyleName();
+ if (UNLIKELY(style.SpecifiedFontSize() == 0)) {
+ // See http://crbug.com/1228157
+ return LayoutUnit();
+ }
+ const AtomicString& name = style.ListStyleType()->GetCounterStyleName();
if (name == "disclosure-open" || name == "disclosure-closed")
return DisclosureSymbolSize(style);
return LayoutUnit((font_data->GetFontMetrics().Ascent() * 2 / 3 + 1) / 2 + 2);
@@ -332,7 +334,7 @@ std::pair<LayoutUnit, LayoutUnit> ListMarker::InlineMarginsForInside(
switch (GetListStyleCategory(document, list_item_style)) {
case ListStyleCategory::kSymbol: {
const AtomicString& name =
- list_item_style.GetListStyleType()->GetCounterStyleName();
+ list_item_style.ListStyleType()->GetCounterStyleName();
if (name == "disclosure-open" || name == "disclosure-closed") {
return {LayoutUnit(), LayoutUnit(kClosureMarkerMarginEm *
marker_style.SpecifiedFontSize())};
@@ -369,7 +371,7 @@ std::pair<LayoutUnit, LayoutUnit> ListMarker::InlineMarginsForOutside(
return {};
const FontMetrics& font_metrics = font_data->GetFontMetrics();
const AtomicString& name =
- list_item_style.GetListStyleType()->GetCounterStyleName();
+ list_item_style.ListStyleType()->GetCounterStyleName();
LayoutUnit offset =
(name == "disclosure-open" || name == "disclosure-closed")
? DisclosureSymbolSize(marker_style)
@@ -398,7 +400,7 @@ LayoutRect ListMarker::RelativeSymbolMarkerRect(const ComputedStyle& style,
// http://crbug.com/543193
const FontMetrics& font_metrics = font_data->GetFontMetrics();
const int ascent = font_metrics.Ascent();
- const AtomicString& name = style.GetListStyleType()->GetCounterStyleName();
+ const AtomicString& name = style.ListStyleType()->GetCounterStyleName();
if (name == "disclosure-open" || name == "disclosure-closed") {
LayoutUnit marker_size = DisclosureSymbolSize(style);
relative_rect = LayoutRect(LayoutUnit(), ascent - marker_size, marker_size,
@@ -417,96 +419,23 @@ LayoutRect ListMarker::RelativeSymbolMarkerRect(const ComputedStyle& style,
const CounterStyle& ListMarker::GetCounterStyle(Document& document,
const ComputedStyle& style) {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
- DCHECK(style.GetListStyleType());
- DCHECK(style.GetListStyleType()->IsCounterStyle());
- return style.GetListStyleType()->GetCounterStyle(document);
+ DCHECK(style.ListStyleType());
+ DCHECK(style.ListStyleType()->IsCounterStyle());
+ return style.ListStyleType()->GetCounterStyle(document);
}
ListMarker::ListStyleCategory ListMarker::GetListStyleCategory(
Document& document,
const ComputedStyle& style) {
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- const ListStyleTypeData* list_style = style.GetListStyleType();
- if (!list_style)
- return ListStyleCategory::kNone;
- if (list_style->IsString())
- return ListStyleCategory::kStaticString;
- DCHECK(list_style->IsCounterStyle());
- return GetCounterStyle(document, style).IsPredefinedSymbolMarker()
- ? ListStyleCategory::kSymbol
- : ListStyleCategory::kLanguage;
- }
-
- EListStyleType type = style.ListStyleType();
- switch (type) {
- case EListStyleType::kNone:
- return ListStyleCategory::kNone;
- case EListStyleType::kString:
- return ListStyleCategory::kStaticString;
- case EListStyleType::kDisc:
- case EListStyleType::kCircle:
- case EListStyleType::kSquare:
- case EListStyleType::kDisclosureOpen:
- case EListStyleType::kDisclosureClosed:
- return ListStyleCategory::kSymbol;
- case EListStyleType::kArabicIndic:
- case EListStyleType::kArmenian:
- case EListStyleType::kBengali:
- case EListStyleType::kCambodian:
- case EListStyleType::kCjkIdeographic:
- case EListStyleType::kCjkEarthlyBranch:
- case EListStyleType::kCjkHeavenlyStem:
- case EListStyleType::kDecimalLeadingZero:
- case EListStyleType::kDecimal:
- case EListStyleType::kDevanagari:
- case EListStyleType::kEthiopicHalehame:
- case EListStyleType::kEthiopicHalehameAm:
- case EListStyleType::kEthiopicHalehameTiEr:
- case EListStyleType::kEthiopicHalehameTiEt:
- case EListStyleType::kGeorgian:
- case EListStyleType::kGujarati:
- case EListStyleType::kGurmukhi:
- case EListStyleType::kHangul:
- case EListStyleType::kHangulConsonant:
- case EListStyleType::kHebrew:
- case EListStyleType::kHiragana:
- case EListStyleType::kHiraganaIroha:
- case EListStyleType::kKannada:
- case EListStyleType::kKatakana:
- case EListStyleType::kKatakanaIroha:
- case EListStyleType::kKhmer:
- case EListStyleType::kKoreanHangulFormal:
- case EListStyleType::kKoreanHanjaFormal:
- case EListStyleType::kKoreanHanjaInformal:
- case EListStyleType::kLao:
- case EListStyleType::kLowerAlpha:
- case EListStyleType::kLowerArmenian:
- case EListStyleType::kLowerGreek:
- case EListStyleType::kLowerLatin:
- case EListStyleType::kLowerRoman:
- case EListStyleType::kMalayalam:
- case EListStyleType::kMongolian:
- case EListStyleType::kMyanmar:
- case EListStyleType::kOriya:
- case EListStyleType::kPersian:
- case EListStyleType::kSimpChineseFormal:
- case EListStyleType::kSimpChineseInformal:
- case EListStyleType::kTelugu:
- case EListStyleType::kThai:
- case EListStyleType::kTibetan:
- case EListStyleType::kTradChineseFormal:
- case EListStyleType::kTradChineseInformal:
- case EListStyleType::kUpperAlpha:
- case EListStyleType::kUpperArmenian:
- case EListStyleType::kUpperLatin:
- case EListStyleType::kUpperRoman:
- case EListStyleType::kUrdu:
- return ListStyleCategory::kLanguage;
- default:
- NOTREACHED();
- return ListStyleCategory::kLanguage;
- }
+ const ListStyleTypeData* list_style = style.ListStyleType();
+ if (!list_style)
+ return ListStyleCategory::kNone;
+ if (list_style->IsString())
+ return ListStyleCategory::kStaticString;
+ DCHECK(list_style->IsCounterStyle());
+ return GetCounterStyle(document, style).IsPredefinedSymbolMarker()
+ ? ListStyleCategory::kSymbol
+ : ListStyleCategory::kLanguage;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/list_marker.h b/chromium/third_party/blink/renderer/core/layout/list_marker.h
index 95237735404..b6e024eeaef 100644
--- a/chromium/third_party/blink/renderer/core/layout/list_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/list_marker.h
@@ -97,6 +97,9 @@ class CORE_EXPORT ListMarker {
int ListItemValue(const LayoutObject&) const;
+ LayoutText& GetTextChild(const LayoutObject& marker) const;
+ LayoutObject* GetContentChild(const LayoutObject& marker) const;
+
unsigned marker_text_type_ : 3; // MarkerTextType
};
diff --git a/chromium/third_party/blink/renderer/core/layout/list_marker_test.cc b/chromium/third_party/blink/renderer/core/layout/list_marker_test.cc
index 8eb2aeb26a9..b2cf8699d87 100644
--- a/chromium/third_party/blink/renderer/core/layout/list_marker_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/list_marker_test.cc
@@ -11,11 +11,7 @@ namespace blink {
// We don't test legacy layout because it's deprecated, and we don't want to
// complicate the test with the legacy LayoutListMarker here.
-class ListMarkerTest : private ScopedCSSAtRuleCounterStyleForTest,
- public NGLayoutTest {
- public:
- ListMarkerTest() : ScopedCSSAtRuleCounterStyleForTest(true) {}
-
+class ListMarkerTest : public NGLayoutTest {
protected:
LayoutObject* GetMarker(const char* list_item_id) {
LayoutNGListItem* list_item =
@@ -315,4 +311,14 @@ TEST_F(ListMarkerTest, ModifyShadowDOMWithOwnCounterStyles) {
EXPECT_EQ("D. ", GetMarkerText(shadow2, "shadow-foo"));
}
+TEST_F(ListMarkerTest, WidthOfSymbolForFontSizeZero) {
+ InsertStyleElement("li { font-size: 0px; }");
+ SetBodyInnerHTML("<li id=target>a</li>");
+ const auto& target = *GetElementById("target");
+ const auto& target_layout_object = *target.GetLayoutObject();
+
+ EXPECT_EQ(LayoutUnit(),
+ ListMarker::WidthOfSymbol(target_layout_object.StyleRef()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/list_marker_text.cc b/chromium/third_party/blink/renderer/core/layout/list_marker_text.cc
deleted file mode 100644
index 0fff3c31e7b..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/list_marker_text.cc
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights
- * reserved.
- * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
- * Copyright (C) 2010 Daniel Bates (dbates@intudata.com)
- *
- * 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/layout/list_marker_text.h"
-
-#include "third_party/blink/renderer/core/layout/text_run_constructor.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-namespace list_marker_text {
-
-enum SequenceType { kNumericSequence, kAlphabeticSequence };
-
-static String ToRoman(int number, bool upper) {
- // FIXME: CSS3 describes how to make this work for much larger numbers,
- // using overbars and special characters. It also specifies the characters
- // in the range U+2160 to U+217F instead of standard ASCII ones.
- DCHECK_GE(number, 1);
- DCHECK_LE(number, 3999);
-
- // Big enough to store largest roman number less than 3999 which
- // is 3888 (MMMDCCCLXXXVIII)
- const int kLettersSize = 15;
- LChar letters[kLettersSize];
-
- int length = 0;
- const LChar kLdigits[] = {'i', 'v', 'x', 'l', 'c', 'd', 'm'};
- const LChar kUdigits[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
- const LChar* digits = upper ? kUdigits : kLdigits;
- int d = 0;
- do {
- int num = number % 10;
- if (num % 5 < 4)
- for (int i = num % 5; i > 0; i--)
- letters[kLettersSize - ++length] = digits[d];
- if (num >= 4 && num <= 8)
- letters[kLettersSize - ++length] = digits[d + 1];
- if (num == 9)
- letters[kLettersSize - ++length] = digits[d + 2];
- if (num % 5 == 4)
- letters[kLettersSize - ++length] = digits[d];
- number /= 10;
- d += 2;
- } while (number);
-
- DCHECK_LE(length, kLettersSize);
- return String(&letters[kLettersSize - length], length);
-}
-
-// The typedef is needed because taking sizeof(number) in the const expression
-// below doesn't work with some compilers. This is likely the case because of
-// the template.
-typedef int numberType;
-
-template <typename CharacterType>
-static inline String ToAlphabeticOrNumeric(numberType number,
- const CharacterType* sequence,
- unsigned sequence_size,
- SequenceType type) {
- DCHECK_GE(sequence_size, 2u);
-
- // Binary is the worst case; requires one character per bit plus a minus sign.
- const int kLettersSize = sizeof(numberType) * 8 + 1;
-
- CharacterType letters[kLettersSize];
-
- bool is_negative_number = false;
- unsigned number_shadow = number;
- if (type == kAlphabeticSequence) {
- DCHECK_GT(number, 0);
- --number_shadow;
- } else if (number < 0) {
- number_shadow = -number;
- is_negative_number = true;
- }
- letters[kLettersSize - 1] = sequence[number_shadow % sequence_size];
- int length = 1;
-
- if (type == kAlphabeticSequence) {
- while ((number_shadow /= sequence_size) > 0) {
- --number_shadow;
- letters[kLettersSize - ++length] =
- sequence[number_shadow % sequence_size];
- }
- } else {
- while ((number_shadow /= sequence_size) > 0)
- letters[kLettersSize - ++length] =
- sequence[number_shadow % sequence_size];
- }
- if (is_negative_number)
- letters[kLettersSize - ++length] = kHyphenMinusCharacter;
-
- DCHECK_LE(length, kLettersSize);
- return String(&letters[kLettersSize - length], length);
-}
-
-template <typename CharacterType>
-static String ToAlphabetic(int number,
- const CharacterType* alphabet,
- unsigned alphabet_size) {
- return ToAlphabeticOrNumeric(number, alphabet, alphabet_size,
- kAlphabeticSequence);
-}
-
-template <typename CharacterType>
-static String ToNumeric(int number,
- const CharacterType* numerals,
- unsigned numerals_size) {
- return ToAlphabeticOrNumeric(number, numerals, numerals_size,
- kNumericSequence);
-}
-
-template <typename CharacterType, size_t size>
-static inline String ToAlphabetic(int number,
- const CharacterType (&alphabet)[size]) {
- return ToAlphabetic(number, alphabet, size);
-}
-
-template <typename CharacterType, size_t size>
-static inline String ToNumeric(int number,
- const CharacterType (&alphabet)[size]) {
- return ToNumeric(number, alphabet, size);
-}
-
-static void ToHebrewUnder1000(int number, Vector<UChar>& letters) {
- // FIXME: CSS3 mentions various refinements not implemented here.
- // FIXME: Should take a look at Mozilla's HebrewToText function (in
- // nsBulletFrame).
- DCHECK_GE(number, 0);
- DCHECK_LT(number, 1000);
- int four_hundreds = number / 400;
- for (int i = 0; i < four_hundreds; i++)
- letters.push_front(1511 + 3);
- number %= 400;
- if (number / 100)
- letters.push_front(1511 + (number / 100) - 1);
- number %= 100;
- if (number == 15 || number == 16) {
- letters.push_front(1487 + 9);
- letters.push_front(1487 + number - 9);
- } else {
- if (int tens = number / 10) {
- static const UChar kHebrewTens[9] = {1497, 1499, 1500, 1502, 1504,
- 1505, 1506, 1508, 1510};
- letters.push_front(kHebrewTens[tens - 1]);
- }
- if (int ones = number % 10)
- letters.push_front(1487 + ones);
- }
-}
-
-static String ToHebrew(int number) {
- // FIXME: CSS3 mentions ways to make this work for much larger numbers.
- DCHECK_GE(number, 0);
- DCHECK_LE(number, 999999);
-
- Vector<UChar> letters;
-
- if (number == 0) {
- static const UChar kHebrewZero[3] = {0x05E1, 0x05E4, 0x05D0};
- letters.Append(kHebrewZero, 3);
- } else {
- if (number > 999) {
- ToHebrewUnder1000(number / 1000, letters);
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled())
- letters.push_front(kHebrewPunctuationGereshCharacter);
- else
- letters.push_front('\'');
- number = number % 1000;
- }
- ToHebrewUnder1000(number, letters);
- }
-
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- // Since Hebrew is RTL, legacy implementation generates letters in the
- // reversed ordering, which is actually wrong because characters in a String
- // should always be in the logical ordering. We re-reverse it so that the
- // output ordering is correct.
- std::reverse(letters.begin(), letters.end());
- }
-
- return String(letters);
-}
-
-static int ToArmenianUnder10000(int number,
- bool upper,
- bool add_circumflex,
- UChar letters[9]) {
- DCHECK_GE(number, 0);
- DCHECK_LT(number, 10000);
- int length = 0;
-
- int lower_offset = upper ? 0 : 0x0030;
-
- if (int thousands = number / 1000) {
- if (thousands == 7) {
- letters[length++] = 0x0552 + lower_offset;
- if (add_circumflex)
- letters[length++] = 0x0302;
- } else {
- letters[length++] = (0x054C - 1 + lower_offset) + thousands;
- if (add_circumflex)
- letters[length++] = 0x0302;
- }
- }
-
- if (int hundreds = (number / 100) % 10) {
- letters[length++] = (0x0543 - 1 + lower_offset) + hundreds;
- if (add_circumflex)
- letters[length++] = 0x0302;
- }
-
- if (int tens = (number / 10) % 10) {
- letters[length++] = (0x053A - 1 + lower_offset) + tens;
- if (add_circumflex)
- letters[length++] = 0x0302;
- }
-
- if (int ones = number % 10) {
- letters[length++] = (0x531 - 1 + lower_offset) + ones;
- if (add_circumflex)
- letters[length++] = 0x0302;
- }
-
- return length;
-}
-
-static String ToArmenian(int number, bool upper) {
- DCHECK_GE(number, 1);
- DCHECK_LE(number, 99999999);
-
- const int kLettersSize = 18; // twice what toArmenianUnder10000 needs
- UChar letters[kLettersSize];
-
- int length = ToArmenianUnder10000(number / 10000, upper, true, letters);
- length +=
- ToArmenianUnder10000(number % 10000, upper, false, letters + length);
-
- DCHECK_LE(length, kLettersSize);
- return String(letters, length);
-}
-
-static String ToGeorgian(int number) {
- DCHECK_GE(number, 1);
- DCHECK_LE(number, 19999);
-
- const int kLettersSize = 5;
- UChar letters[kLettersSize];
-
- int length = 0;
-
- if (number > 9999)
- letters[length++] = 0x10F5;
-
- if (int thousands = (number / 1000) % 10) {
- static const UChar kGeorgianThousands[9] = {
- 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0};
- letters[length++] = kGeorgianThousands[thousands - 1];
- }
-
- if (int hundreds = (number / 100) % 10) {
- static const UChar kGeorgianHundreds[9] = {
- 0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8};
- letters[length++] = kGeorgianHundreds[hundreds - 1];
- }
-
- if (int tens = (number / 10) % 10) {
- static const UChar kGeorgianTens[9] = {
- 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF};
- letters[length++] = kGeorgianTens[tens - 1];
- }
-
- if (int ones = number % 10) {
- static const UChar kGeorgianOnes[9] = {
- 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7};
- letters[length++] = kGeorgianOnes[ones - 1];
- }
-
- DCHECK_LE(length, kLettersSize);
- return String(letters, length);
-}
-
-enum CJKLang { kChinese = 1, kKorean, kJapanese };
-
-enum CJKStyle { kFormal, kInformal };
-
-// The table uses the order from the CSS3 specification:
-// first 3 group markers, then 3 digit markers, then ten digits, then negative
-// symbols.
-static String ToCJKIdeographic(int number,
- const UChar table[26],
- CJKStyle cjk_style) {
- enum AbstractCJKChar {
- kNoChar = 0,
- kLang = 0,
- // FourthGroupMarker for simplified chinese has two codepoints, to simplify
- // the main algorithm below use two codepoints for all group markers.
- kSecondGroupMarker = 1,
- kThirdGroupMarker = 3,
- kFourthGroupMarker = 5,
- kSecondDigitMarker = 7,
- kThirdDigitMarker,
- kFourthDigitMarker,
- kDigit0,
- kDigit1,
- kDigit2,
- kDigit3,
- kDigit4,
- kDigit5,
- kDigit6,
- kDigit7,
- kDigit8,
- kDigit9,
- kNeg1,
- kNeg2,
- kNeg3,
- kNeg4,
- kNeg5
- };
-
- if (number == 0)
- return String(&table[kDigit0], 1);
-
- const bool negative = number < 0;
- if (negative) {
- // Negating the most negative integer (INT_MIN) doesn't work, since it has
- // no positive counterpart. Deal with that here, manually.
- if (UNLIKELY(number == INT_MIN))
- number = INT_MAX;
- else
- number = -number;
- }
-
- const int kGroupLength =
- 9; // 4 digits, 3 digit markers, group marker of size 2.
- const int kBufferLength = 4 * kGroupLength;
- AbstractCJKChar buffer[kBufferLength] = {kNoChar};
-
- for (int i = 0; i < 4; ++i) {
- int group_value = number % 10000;
- number /= 10000;
-
- // Process least-significant group first, but put it in the buffer last.
- AbstractCJKChar* group = &buffer[(3 - i) * kGroupLength];
-
- if (group_value && i) {
- group[8] = static_cast<AbstractCJKChar>(kSecondGroupMarker + i);
- group[7] = static_cast<AbstractCJKChar>(kSecondGroupMarker - 1 + i);
- }
-
- // Put in the four digits and digit markers for any non-zero digits.
- int digit_value = (group_value % 10);
- bool trailing_zero = table[kLang] == kChinese && !digit_value;
- if (digit_value) {
- bool drop_one = table[kLang] == kKorean && cjk_style == kInformal &&
- digit_value == 1 && i > 0;
- if (!drop_one)
- group[6] = static_cast<AbstractCJKChar>(kDigit0 + (group_value % 10));
- }
- if (number != 0 || group_value > 9) {
- digit_value = ((group_value / 10) % 10);
- bool drop_one =
- table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
- if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
- group[4] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
- trailing_zero &= !digit_value;
- if (digit_value)
- group[5] = kSecondDigitMarker;
- }
- if (number != 0 || group_value > 99) {
- digit_value = ((group_value / 100) % 10);
- bool drop_one =
- table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
- if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
- group[2] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
- trailing_zero &= !digit_value;
- if (digit_value)
- group[3] = kThirdDigitMarker;
- }
- if (number != 0 || group_value > 999) {
- digit_value = group_value / 1000;
- bool drop_one =
- table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
- if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
- group[0] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
- if (digit_value)
- group[1] = kFourthDigitMarker;
- }
-
- if (trailing_zero && i > 0) {
- group[6] = group[7];
- group[7] = group[8];
- group[8] = kDigit0;
- }
-
- // Remove the tens digit, but leave the marker, for any group that has
- // a value of less than 20.
- if (table[kLang] == kChinese && cjk_style == kInformal &&
- group_value < 20) {
- DCHECK(group[4] == kNoChar || group[4] == kDigit0 || group[4] == kDigit1);
- group[4] = kNoChar;
- }
-
- if (number == 0)
- break;
- }
-
- // Convert into characters, omitting consecutive runs of Digit0 and
- // any trailing Digit0.
- int length = 0;
- const int kMaxLengthForNegativeSymbols = 5;
- UChar characters[kBufferLength + kMaxLengthForNegativeSymbols];
- AbstractCJKChar last = kNoChar;
- if (negative) {
- while (UChar a = table[kNeg1 + length])
- characters[length++] = a;
- }
- for (int i = 0; i < kBufferLength; ++i) {
- AbstractCJKChar a = buffer[i];
- if (a != kNoChar) {
- if (a != kDigit0 || (table[kLang] == kChinese && last != kDigit0)) {
- UChar new_char = table[a];
- if (new_char != kNoChar) {
- characters[length++] = table[a];
- if (table[kLang] == kKorean &&
- (a == kSecondGroupMarker || a == kThirdGroupMarker ||
- a == kFourthGroupMarker))
- characters[length++] = ' ';
- }
- }
- last = a;
- }
- }
- if ((table[kLang] == kChinese && last == kDigit0) ||
- characters[length - 1] == ' ')
- --length;
-
- return String(characters, length);
-}
-
-static EListStyleType EffectiveListMarkerType(EListStyleType type, int count) {
- // Note, the following switch statement has been explicitly grouped
- // by list-style-type ordinal range.
- switch (type) {
- case EListStyleType::kArabicIndic:
- case EListStyleType::kBengali:
- case EListStyleType::kCambodian:
- case EListStyleType::kCircle:
- case EListStyleType::kDecimalLeadingZero:
- case EListStyleType::kDecimal:
- case EListStyleType::kDevanagari:
- case EListStyleType::kDisc:
- case EListStyleType::kDisclosureClosed:
- case EListStyleType::kDisclosureOpen:
- case EListStyleType::kGujarati:
- case EListStyleType::kGurmukhi:
- case EListStyleType::kKannada:
- case EListStyleType::kKhmer:
- case EListStyleType::kLao:
- case EListStyleType::kMalayalam:
- case EListStyleType::kMongolian:
- case EListStyleType::kMyanmar:
- case EListStyleType::kNone:
- case EListStyleType::kOriya:
- case EListStyleType::kPersian:
- case EListStyleType::kSquare:
- case EListStyleType::kTelugu:
- case EListStyleType::kThai:
- case EListStyleType::kTibetan:
- case EListStyleType::kUrdu:
- case EListStyleType::kKoreanHangulFormal:
- case EListStyleType::kKoreanHanjaFormal:
- case EListStyleType::kKoreanHanjaInformal:
- case EListStyleType::kCjkIdeographic:
- case EListStyleType::kSimpChineseFormal:
- case EListStyleType::kSimpChineseInformal:
- case EListStyleType::kTradChineseFormal:
- case EListStyleType::kTradChineseInformal:
- return type; // Can represent all ordinals.
- case EListStyleType::kArmenian:
- case EListStyleType::kLowerArmenian:
- case EListStyleType::kUpperArmenian:
- return (count < 1 || count > 99999999) ? EListStyleType::kDecimal : type;
- case EListStyleType::kGeorgian:
- return (count < 1 || count > 19999) ? EListStyleType::kDecimal : type;
- case EListStyleType::kHebrew:
- return (count < 0 || count > 999999) ? EListStyleType::kDecimal : type;
- case EListStyleType::kLowerRoman:
- case EListStyleType::kUpperRoman:
- return (count < 1 || count > 3999) ? EListStyleType::kDecimal : type;
- case EListStyleType::kCjkEarthlyBranch:
- case EListStyleType::kCjkHeavenlyStem:
- case EListStyleType::kEthiopicHalehameAm:
- case EListStyleType::kEthiopicHalehame:
- case EListStyleType::kEthiopicHalehameTiEr:
- case EListStyleType::kEthiopicHalehameTiEt:
- case EListStyleType::kHangul:
- case EListStyleType::kHangulConsonant:
- case EListStyleType::kHiragana:
- case EListStyleType::kHiraganaIroha:
- case EListStyleType::kKatakana:
- case EListStyleType::kKatakanaIroha:
- case EListStyleType::kLowerAlpha:
- case EListStyleType::kLowerGreek:
- case EListStyleType::kLowerLatin:
- case EListStyleType::kUpperAlpha:
- case EListStyleType::kUpperLatin:
- return (count < 1) ? EListStyleType::kDecimal : type;
- case EListStyleType::kString:
- NOTREACHED();
- break;
- }
-
- NOTREACHED();
- return type;
-}
-
-UChar Suffix(EListStyleType type, int count) {
- // If the list-style-type cannot represent |count| because it's outside its
- // ordinal range then we fall back to some list style that can represent
- // |count|.
- EListStyleType effective_type = EffectiveListMarkerType(type, count);
-
- // Note, the following switch statement has been explicitly
- // grouped by list-style-type suffix.
- switch (effective_type) {
- case EListStyleType::kCircle:
- case EListStyleType::kDisc:
- case EListStyleType::kDisclosureClosed:
- case EListStyleType::kDisclosureOpen:
- case EListStyleType::kNone:
- case EListStyleType::kSquare:
- return ' ';
- case EListStyleType::kEthiopicHalehame:
- case EListStyleType::kEthiopicHalehameAm:
- case EListStyleType::kEthiopicHalehameTiEr:
- case EListStyleType::kEthiopicHalehameTiEt:
- return kEthiopicPrefaceColonCharacter;
- case EListStyleType::kArmenian:
- case EListStyleType::kArabicIndic:
- case EListStyleType::kBengali:
- case EListStyleType::kCambodian:
- case EListStyleType::kCjkIdeographic:
- case EListStyleType::kCjkEarthlyBranch:
- case EListStyleType::kCjkHeavenlyStem:
- case EListStyleType::kDecimalLeadingZero:
- case EListStyleType::kDecimal:
- case EListStyleType::kDevanagari:
- case EListStyleType::kGeorgian:
- case EListStyleType::kGujarati:
- case EListStyleType::kGurmukhi:
- case EListStyleType::kHangul:
- case EListStyleType::kHangulConsonant:
- case EListStyleType::kHebrew:
- case EListStyleType::kHiragana:
- case EListStyleType::kHiraganaIroha:
- case EListStyleType::kKannada:
- case EListStyleType::kKatakana:
- case EListStyleType::kKatakanaIroha:
- case EListStyleType::kKhmer:
- case EListStyleType::kLao:
- case EListStyleType::kLowerAlpha:
- case EListStyleType::kLowerArmenian:
- case EListStyleType::kLowerGreek:
- case EListStyleType::kLowerLatin:
- case EListStyleType::kLowerRoman:
- case EListStyleType::kMalayalam:
- case EListStyleType::kMongolian:
- case EListStyleType::kMyanmar:
- case EListStyleType::kOriya:
- case EListStyleType::kPersian:
- case EListStyleType::kTelugu:
- case EListStyleType::kThai:
- case EListStyleType::kTibetan:
- case EListStyleType::kUpperAlpha:
- case EListStyleType::kUpperArmenian:
- case EListStyleType::kUpperLatin:
- case EListStyleType::kUpperRoman:
- case EListStyleType::kUrdu:
- return '.';
- case EListStyleType::kSimpChineseFormal:
- case EListStyleType::kSimpChineseInformal:
- case EListStyleType::kTradChineseFormal:
- case EListStyleType::kTradChineseInformal:
- case EListStyleType::kKoreanHangulFormal:
- case EListStyleType::kKoreanHanjaFormal:
- case EListStyleType::kKoreanHanjaInformal:
- return 0x3001;
- case EListStyleType::kString:
- NOTREACHED();
- break;
- }
-
- NOTREACHED();
- return '.';
-}
-
-String GetText(EListStyleType type, int count) {
- // If the list-style-type, say hebrew, cannot represent |count| because it's
- // outside its ordinal range then we fallback to some list style that can
- // represent |count|.
- switch (EffectiveListMarkerType(type, count)) {
- case EListStyleType::kNone:
- return "";
-
- // We use the same characters for text security.
- // See LayoutText::setInternalString.
- case EListStyleType::kCircle:
- return String(&kWhiteBulletCharacter, 1);
- case EListStyleType::kDisc:
- return String(&kBulletCharacter, 1);
-
- // TODO(layout-dev): Text for disclosure-* should not depend on physical
- // shape?
- case EListStyleType::kDisclosureClosed:
- return String(&kBlackRightPointingSmallTriangle, 1);
- case EListStyleType::kDisclosureOpen:
- return String(&kBlackDownPointingSmallTriangle, 1);
-
- case EListStyleType::kSquare:
- // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE
- // instead, but I think this looks better.
- return String(&kBlackSquareCharacter, 1);
-
- case EListStyleType::kDecimal:
- return String::Number(count);
- case EListStyleType::kDecimalLeadingZero:
- if (count < -9 || count > 9)
- return String::Number(count);
- if (count < 0)
- return "-0" + String::Number(-count); // -01 to -09
- return "0" + String::Number(count); // 00 to 09
-
- case EListStyleType::kArabicIndic: {
- static const UChar kArabicIndicNumerals[10] = {
- 0x0660, 0x0661, 0x0662, 0x0663, 0x0664,
- 0x0665, 0x0666, 0x0667, 0x0668, 0x0669};
- return ToNumeric(count, kArabicIndicNumerals);
- }
- case EListStyleType::kBengali: {
- static const UChar kBengaliNumerals[10] = {0x09E6, 0x09E7, 0x09E8, 0x09E9,
- 0x09EA, 0x09EB, 0x09EC, 0x09ED,
- 0x09EE, 0x09EF};
- return ToNumeric(count, kBengaliNumerals);
- }
- case EListStyleType::kCambodian:
- case EListStyleType::kKhmer: {
- static const UChar kKhmerNumerals[10] = {0x17E0, 0x17E1, 0x17E2, 0x17E3,
- 0x17E4, 0x17E5, 0x17E6, 0x17E7,
- 0x17E8, 0x17E9};
- return ToNumeric(count, kKhmerNumerals);
- }
- case EListStyleType::kDevanagari: {
- static const UChar kDevanagariNumerals[10] = {
- 0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
- 0x096B, 0x096C, 0x096D, 0x096E, 0x096F};
- return ToNumeric(count, kDevanagariNumerals);
- }
- case EListStyleType::kGujarati: {
- static const UChar kGujaratiNumerals[10] = {
- 0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
- 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF};
- return ToNumeric(count, kGujaratiNumerals);
- }
- case EListStyleType::kGurmukhi: {
- static const UChar kGurmukhiNumerals[10] = {
- 0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
- 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F};
- return ToNumeric(count, kGurmukhiNumerals);
- }
- case EListStyleType::kKannada: {
- static const UChar kKannadaNumerals[10] = {0x0CE6, 0x0CE7, 0x0CE8, 0x0CE9,
- 0x0CEA, 0x0CEB, 0x0CEC, 0x0CED,
- 0x0CEE, 0x0CEF};
- return ToNumeric(count, kKannadaNumerals);
- }
- case EListStyleType::kLao: {
- static const UChar kLaoNumerals[10] = {0x0ED0, 0x0ED1, 0x0ED2, 0x0ED3,
- 0x0ED4, 0x0ED5, 0x0ED6, 0x0ED7,
- 0x0ED8, 0x0ED9};
- return ToNumeric(count, kLaoNumerals);
- }
- case EListStyleType::kMalayalam: {
- static const UChar kMalayalamNumerals[10] = {
- 0x0D66, 0x0D67, 0x0D68, 0x0D69, 0x0D6A,
- 0x0D6B, 0x0D6C, 0x0D6D, 0x0D6E, 0x0D6F};
- return ToNumeric(count, kMalayalamNumerals);
- }
- case EListStyleType::kMongolian: {
- static const UChar kMongolianNumerals[10] = {
- 0x1810, 0x1811, 0x1812, 0x1813, 0x1814,
- 0x1815, 0x1816, 0x1817, 0x1818, 0x1819};
- return ToNumeric(count, kMongolianNumerals);
- }
- case EListStyleType::kMyanmar: {
- static const UChar kMyanmarNumerals[10] = {0x1040, 0x1041, 0x1042, 0x1043,
- 0x1044, 0x1045, 0x1046, 0x1047,
- 0x1048, 0x1049};
- return ToNumeric(count, kMyanmarNumerals);
- }
- case EListStyleType::kOriya: {
- static const UChar kOriyaNumerals[10] = {0x0B66, 0x0B67, 0x0B68, 0x0B69,
- 0x0B6A, 0x0B6B, 0x0B6C, 0x0B6D,
- 0x0B6E, 0x0B6F};
- return ToNumeric(count, kOriyaNumerals);
- }
- case EListStyleType::kPersian:
- case EListStyleType::kUrdu: {
- static const UChar kUrduNumerals[10] = {0x06F0, 0x06F1, 0x06F2, 0x06F3,
- 0x06F4, 0x06F5, 0x06F6, 0x06F7,
- 0x06F8, 0x06F9};
- return ToNumeric(count, kUrduNumerals);
- }
- case EListStyleType::kTelugu: {
- static const UChar kTeluguNumerals[10] = {0x0C66, 0x0C67, 0x0C68, 0x0C69,
- 0x0C6A, 0x0C6B, 0x0C6C, 0x0C6D,
- 0x0C6E, 0x0C6F};
- return ToNumeric(count, kTeluguNumerals);
- }
- case EListStyleType::kTibetan: {
- static const UChar kTibetanNumerals[10] = {0x0F20, 0x0F21, 0x0F22, 0x0F23,
- 0x0F24, 0x0F25, 0x0F26, 0x0F27,
- 0x0F28, 0x0F29};
- return ToNumeric(count, kTibetanNumerals);
- }
- case EListStyleType::kThai: {
- static const UChar kThaiNumerals[10] = {0x0E50, 0x0E51, 0x0E52, 0x0E53,
- 0x0E54, 0x0E55, 0x0E56, 0x0E57,
- 0x0E58, 0x0E59};
- return ToNumeric(count, kThaiNumerals);
- }
-
- case EListStyleType::kLowerAlpha:
- case EListStyleType::kLowerLatin: {
- static const LChar kLowerLatinAlphabet[26] = {
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
- return ToAlphabetic(count, kLowerLatinAlphabet);
- }
- case EListStyleType::kUpperAlpha:
- case EListStyleType::kUpperLatin: {
- static const LChar kUpperLatinAlphabet[26] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
- return ToAlphabetic(count, kUpperLatinAlphabet);
- }
- case EListStyleType::kLowerGreek: {
- static const UChar kLowerGreekAlphabet[24] = {
- 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
- 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
- 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9};
- return ToAlphabetic(count, kLowerGreekAlphabet);
- }
-
- case EListStyleType::kHiragana: {
- // FIXME: This table comes from the CSS3 draft, and is probably
- // incorrect, given the comments in that draft.
- static const UChar kHiraganaAlphabet[48] = {
- 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F,
- 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, 0x305F,
- 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D,
- 0x306E, 0x306F, 0x3072, 0x3075, 0x3078, 0x307B, 0x307E, 0x307F,
- 0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x308A,
- 0x308B, 0x308C, 0x308D, 0x308F, 0x3090, 0x3091, 0x3092, 0x3093};
- return ToAlphabetic(count, kHiraganaAlphabet);
- }
- case EListStyleType::kHiraganaIroha: {
- // FIXME: This table comes from the CSS3 draft, and is probably
- // incorrect, given the comments in that draft.
- static const UChar kHiraganaIrohaAlphabet[47] = {
- 0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068, 0x3061,
- 0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B, 0x3088, 0x305F,
- 0x308C, 0x305D, 0x3064, 0x306D, 0x306A, 0x3089, 0x3080, 0x3046,
- 0x3090, 0x306E, 0x304A, 0x304F, 0x3084, 0x307E, 0x3051, 0x3075,
- 0x3053, 0x3048, 0x3066, 0x3042, 0x3055, 0x304D, 0x3086, 0x3081,
- 0x307F, 0x3057, 0x3091, 0x3072, 0x3082, 0x305B, 0x3059};
- return ToAlphabetic(count, kHiraganaIrohaAlphabet);
- }
- case EListStyleType::kKatakana: {
- // FIXME: This table comes from the CSS3 draft, and is probably
- // incorrect, given the comments in that draft.
- static const UChar kKatakanaAlphabet[48] = {
- 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF,
- 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF,
- 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD,
- 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, 0x30DF,
- 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA,
- 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0x30F3};
- return ToAlphabetic(count, kKatakanaAlphabet);
- }
- case EListStyleType::kKatakanaIroha: {
- // FIXME: This table comes from the CSS3 draft, and is probably
- // incorrect, given the comments in that draft.
- static const UChar kKatakanaIrohaAlphabet[47] = {
- 0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8, 0x30C1,
- 0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB, 0x30E8, 0x30BF,
- 0x30EC, 0x30BD, 0x30C4, 0x30CD, 0x30CA, 0x30E9, 0x30E0, 0x30A6,
- 0x30F0, 0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE, 0x30B1, 0x30D5,
- 0x30B3, 0x30A8, 0x30C6, 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1,
- 0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x30B9};
- return ToAlphabetic(count, kKatakanaIrohaAlphabet);
- }
-
- case EListStyleType::kCjkEarthlyBranch: {
- static const UChar kCjkEarthlyBranchAlphabet[12] = {
- 0x5B50, 0x4E11, 0x5BC5, 0x536F, 0x8FB0, 0x5DF3,
- 0x5348, 0x672A, 0x7533, 0x9149, 0x620C, 0x4EA5};
- return ToAlphabetic(count, kCjkEarthlyBranchAlphabet);
- }
- case EListStyleType::kCjkHeavenlyStem: {
- static const UChar kCjkHeavenlyStemAlphabet[10] = {
- 0x7532, 0x4E59, 0x4E19, 0x4E01, 0x620A,
- 0x5DF1, 0x5E9A, 0x8F9B, 0x58EC, 0x7678};
- return ToAlphabetic(count, kCjkHeavenlyStemAlphabet);
- }
- case EListStyleType::kHangulConsonant: {
- static const UChar kHangulConsonantAlphabet[14] = {
- 0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142, 0x3145,
- 0x3147, 0x3148, 0x314A, 0x314B, 0x314C, 0x314D, 0x314E};
- return ToAlphabetic(count, kHangulConsonantAlphabet);
- }
- case EListStyleType::kHangul: {
- static const UChar kHangulAlphabet[14] = {
- 0xAC00, 0xB098, 0xB2E4, 0xB77C, 0xB9C8, 0xBC14, 0xC0AC,
- 0xC544, 0xC790, 0xCC28, 0xCE74, 0xD0C0, 0xD30C, 0xD558};
- return ToAlphabetic(count, kHangulAlphabet);
- }
- case EListStyleType::kEthiopicHalehame: {
- static const UChar kEthiopicHalehameGezAlphabet[26] = {
- 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230,
- 0x1240, 0x1260, 0x1270, 0x1280, 0x1290, 0x12A0, 0x12A8,
- 0x12C8, 0x12D0, 0x12D8, 0x12E8, 0x12F0, 0x1308, 0x1320,
- 0x1330, 0x1338, 0x1340, 0x1348, 0x1350};
- return ToAlphabetic(count, kEthiopicHalehameGezAlphabet);
- }
- case EListStyleType::kEthiopicHalehameAm: {
- static const UChar kEthiopicHalehameAmAlphabet[33] = {
- 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230,
- 0x1238, 0x1240, 0x1260, 0x1270, 0x1278, 0x1280, 0x1290,
- 0x1298, 0x12A0, 0x12A8, 0x12B8, 0x12C8, 0x12D0, 0x12D8,
- 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320, 0x1328,
- 0x1330, 0x1338, 0x1340, 0x1348, 0x1350};
- return ToAlphabetic(count, kEthiopicHalehameAmAlphabet);
- }
- case EListStyleType::kEthiopicHalehameTiEr: {
- static const UChar kEthiopicHalehameTiErAlphabet[31] = {
- 0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240,
- 0x1250, 0x1260, 0x1270, 0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8,
- 0x12B8, 0x12C8, 0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300,
- 0x1308, 0x1320, 0x1328, 0x1330, 0x1338, 0x1348, 0x1350};
- return ToAlphabetic(count, kEthiopicHalehameTiErAlphabet);
- }
- case EListStyleType::kEthiopicHalehameTiEt: {
- static const UChar kEthiopicHalehameTiEtAlphabet[34] = {
- 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230,
- 0x1238, 0x1240, 0x1250, 0x1260, 0x1270, 0x1278, 0x1280,
- 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12B8, 0x12C8, 0x12D0,
- 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320,
- 0x1328, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350};
- return ToAlphabetic(count, kEthiopicHalehameTiEtAlphabet);
- }
- case EListStyleType::kKoreanHangulFormal: {
- static const UChar kKoreanHangulFormalTable[26] = {
- kKorean, 0xB9CC, 0x0000, 0xC5B5, 0x0000, 0xC870, 0x0000,
- 0xC2ED, 0xBC31, 0xCC9C, 0xC601, 0xC77C, 0xC774, 0xC0BC,
- 0xC0AC, 0xC624, 0xC721, 0xCE60, 0xD314, 0xAD6C, 0xB9C8,
- 0xC774, 0xB108, 0xC2A4, 0x0020, 0x0000};
- return ToCJKIdeographic(count, kKoreanHangulFormalTable, kFormal);
- }
- case EListStyleType::kKoreanHanjaFormal: {
- static const UChar kKoreanHanjaFormalTable[26] = {
- kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
- 0x62FE, 0x767E, 0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3,
- 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0xB9C8,
- 0xC774, 0xB108, 0xC2A4, 0x0020, 0x0000};
- return ToCJKIdeographic(count, kKoreanHanjaFormalTable, kFormal);
- }
- case EListStyleType::kKoreanHanjaInformal: {
- static const UChar kKoreanHanjaInformalTable[26] = {
- kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
- 0x5341, 0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09,
- 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0xB9C8,
- 0xC774, 0xB108, 0xC2A4, 0x0020, 0x0000};
- return ToCJKIdeographic(count, kKoreanHanjaInformalTable, kInformal);
- }
- case EListStyleType::kCjkIdeographic:
- case EListStyleType::kTradChineseInformal: {
- static const UChar kTraditionalChineseInformalTable[22] = {
- kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000, 0x5341,
- 0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94,
- 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x8CA0, 0x0000};
- return ToCJKIdeographic(count, kTraditionalChineseInformalTable,
- kInformal);
- }
- case EListStyleType::kSimpChineseInformal: {
- static const UChar kSimpleChineseInformalTable[22] = {
- kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF, 0x5341,
- 0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94,
- 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x8D1F, 0x0000};
- return ToCJKIdeographic(count, kSimpleChineseInformalTable, kInformal);
- }
- case EListStyleType::kTradChineseFormal: {
- static const UChar kTraditionalChineseFormalTable[22] = {
- kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000, 0x62FE,
- 0x4F70, 0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3, 0x8086, 0x4F0D,
- 0x9678, 0x67D2, 0x634C, 0x7396, 0x8CA0, 0x0000};
- return ToCJKIdeographic(count, kTraditionalChineseFormalTable, kFormal);
- }
- case EListStyleType::kSimpChineseFormal: {
- static const UChar kSimpleChineseFormalTable[22] = {
- kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF, 0x62FE,
- 0x4F70, 0x4EDF, 0x96F6, 0x58F9, 0x8D30, 0x53C1, 0x8086, 0x4F0D,
- 0x9646, 0x67D2, 0x634C, 0x7396, 0x8D1F, 0x0000};
- return ToCJKIdeographic(count, kSimpleChineseFormalTable, kFormal);
- }
-
- case EListStyleType::kLowerRoman:
- return ToRoman(count, false);
- case EListStyleType::kUpperRoman:
- return ToRoman(count, true);
-
- case EListStyleType::kArmenian:
- case EListStyleType::kUpperArmenian:
- // CSS3 says "armenian" means "lower-armenian".
- // But the CSS2.1 test suite contains uppercase test results for
- // "armenian", so we'll match the test suite.
- return ToArmenian(count, true);
- case EListStyleType::kLowerArmenian:
- return ToArmenian(count, false);
- case EListStyleType::kGeorgian:
- return ToGeorgian(count);
- case EListStyleType::kHebrew:
- return ToHebrew(count);
-
- case EListStyleType::kString:
- NOTREACHED();
- break;
- }
-
- NOTREACHED();
- return "";
-}
-
-} // namespace list_marker_text
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/list_marker_text.h b/chromium/third_party/blink/renderer/core/layout/list_marker_text.h
deleted file mode 100644
index ea030c85fa9..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/list_marker_text.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 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_CORE_LAYOUT_LIST_MARKER_TEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LIST_MARKER_TEXT_H_
-
-#include "third_party/blink/renderer/core/style/computed_style_constants.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-// Utility routines for working with lists. Encapsulates complex
-// language-specific logic including fallback to alternate languages when
-// counter values cannot be represented in a particular language.
-namespace list_marker_text {
-
-// Returns the suffix character, such as '.', for the given list type and
-// item count number.
-UChar Suffix(EListStyleType, int count);
-
-// Returns the text, such as arabic or roman numerals, for the given list
-// type and item count number. Does not include any suffix character.
-String GetText(EListStyleType, int count);
-
-} // namespace list_marker_text
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LIST_MARKER_TEXT_H_
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 a7abad512d9..01abf4cbe7f 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
@@ -1023,6 +1023,52 @@ TEST_F(MapCoordinatesTest, MulticolWithAbsPosInRelPos) {
EXPECT_EQ(PhysicalOffset(29, 139), mapped_point);
}
+TEST_F(MapCoordinatesTest, MulticolWithAbsPosInInlineRelPos) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='multicol' style='columns:3; column-gap:0; column-fill:auto;
+ width:300px; height:100px; border:8px solid; padding:7px;'>
+ <div style='height:110px;'></div>
+ <div id='container'>
+ <span id='relpos' style='position:relative; left:4px; top:4px;'>
+ <div id='target' style='position:absolute; left:15px; top:15px;
+ margin:10px; border:13px; padding:13px;'></div>
+ </span>
+ </div>
+ </div>
+ )HTML");
+
+ auto* target = GetLayoutBoxByElementId("target");
+ auto* multicol = GetLayoutBoxByElementId("multicol");
+
+ PhysicalOffset mapped_point =
+ MapLocalToAncestor(target, multicol, PhysicalOffset());
+ EXPECT_EQ(PhysicalOffset(144, 54), mapped_point);
+ mapped_point = MapAncestorToLocal(target, multicol, mapped_point);
+ EXPECT_EQ(PhysicalOffset(), mapped_point);
+
+ // Walk each ancestor in the chain separately, to verify each step on the way.
+ auto* container = GetLayoutBoxByElementId("container");
+ LayoutBox* flow_thread = container->ParentBox();
+ ASSERT_TRUE(flow_thread->IsLayoutFlowThread());
+
+ mapped_point = MapLocalToAncestor(target, container, PhysicalOffset());
+ EXPECT_EQ(PhysicalOffset(29, 29), mapped_point);
+ mapped_point = MapAncestorToLocal(target, container, mapped_point);
+ EXPECT_EQ(PhysicalOffset(), mapped_point);
+
+ mapped_point =
+ MapLocalToAncestor(container, flow_thread, PhysicalOffset(25, 25));
+ EXPECT_EQ(PhysicalOffset(25, 135), mapped_point);
+ mapped_point = MapAncestorToLocal(container, flow_thread, mapped_point);
+ EXPECT_EQ(PhysicalOffset(25, 25), mapped_point);
+
+ mapped_point =
+ MapLocalToAncestor(flow_thread, multicol, PhysicalOffset(29, 139));
+ EXPECT_EQ(PhysicalOffset(144, 54), mapped_point);
+ mapped_point = MapAncestorToLocal(flow_thread, multicol, mapped_point);
+ EXPECT_EQ(PhysicalOffset(29, 139), mapped_point);
+}
+
TEST_F(MapCoordinatesTest, MulticolWithAbsPosNotContained) {
SetBodyInnerHTML(R"HTML(
<div id='container' style='position:relative; margin:666px; border:7px
@@ -1677,29 +1723,30 @@ TEST_F(MapCoordinatesTest, LocalToAbsoluteTransformFlattens) {
// With child1, the rotations cancel and points should map basically back to
// themselves.
- EXPECT_NEAR(100.0, matrix.ProjectPoint(FloatPoint(100.0, 50.0)).X(),
+ EXPECT_NEAR(100.0, matrix.MapPoint(FloatPoint(100.0, 50.0)).X(),
LayoutUnit::Epsilon());
- EXPECT_NEAR(50.0, matrix.ProjectPoint(FloatPoint(100.0, 50.0)).Y(),
+ EXPECT_NEAR(50.0, matrix.MapPoint(FloatPoint(100.0, 50.0)).Y(),
LayoutUnit::Epsilon());
- EXPECT_NEAR(50.0, matrix.ProjectPoint(FloatPoint(50.0, 100.0)).X(),
+ EXPECT_NEAR(50.0, matrix.MapPoint(FloatPoint(50.0, 100.0)).X(),
LayoutUnit::Epsilon());
- EXPECT_NEAR(100.0, matrix.ProjectPoint(FloatPoint(50.0, 100.0)).Y(),
+ EXPECT_NEAR(100.0, matrix.MapPoint(FloatPoint(50.0, 100.0)).Y(),
LayoutUnit::Epsilon());
// With child2, each rotation gets flattened and the end result is
- // approximately a 90-degree rotation.
+ // approximately a scale(1.0, 0.5).
matrix = child2->LocalToAbsoluteTransform();
- EXPECT_NEAR(50.0, matrix.ProjectPoint(FloatPoint(100.0, 50.0)).X(),
+ EXPECT_NEAR(50.0, matrix.MapPoint(FloatPoint(100.0, 50.0)).X(),
LayoutUnit::Epsilon());
- EXPECT_NEAR(50.0, matrix.ProjectPoint(FloatPoint(100.0, 50.0)).Y(),
+ EXPECT_NEAR(50.0, matrix.MapPoint(FloatPoint(100.0, 50.0)).Y(),
LayoutUnit::Epsilon());
- EXPECT_NEAR(25.0, matrix.ProjectPoint(FloatPoint(50.0, 100.0)).X(),
+ EXPECT_NEAR(25.0, matrix.MapPoint(FloatPoint(50.0, 100.0)).X(),
LayoutUnit::Epsilon());
- EXPECT_NEAR(100.0, matrix.ProjectPoint(FloatPoint(50.0, 100.0)).Y(),
+ EXPECT_NEAR(100.0, matrix.MapPoint(FloatPoint(50.0, 100.0)).Y(),
LayoutUnit::Epsilon());
}
TEST_F(MapCoordinatesTest, Transform3DWithOffset) {
+ ScopedTransformInteropForTest disabled(false);
SetBodyInnerHTML(R"HTML(
<style>
body { margin: 0; }
@@ -1721,6 +1768,75 @@ TEST_F(MapCoordinatesTest, Transform3DWithOffset) {
MapLocalToAncestor(target, nullptr, FloatRect(0, 0, 100, 100)));
}
+TEST_F(MapCoordinatesTest, Transform3DWithOffset2) {
+ ScopedTransformInteropForTest disabled(false);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ body { margin: 0; }
+ </style>
+ <div style="perspective: 400px; width: 0; height: 0">
+ <div style="transform-style: preserve-3d">
+ <div style="height: 100px"></div>
+ <div style="transform-style: preserve-3d; transform: rotateY(0deg)">
+ <div id="target" style="width: 100px; height: 100px;
+ transform: translateZ(200px)">
+ </div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* target = GetLayoutObjectByElementId("target");
+ EXPECT_EQ(FloatRect(0, 200, 200, 200),
+ MapLocalToAncestor(target, nullptr, FloatRect(0, 0, 100, 100)));
+}
+
+TEST_F(MapCoordinatesTest, Transform3DWithOffsetTransformInterop) {
+ ScopedTransformInteropForTest enabled(true);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ body { margin: 0; }
+ </style>
+ <div style="perspective: 400px; width: 0; height: 0">
+ <div>
+ <div style="height: 100px"></div>
+ <div style="transform-style: preserve-3d; transform: rotateY(0deg)">
+ <div id="target" style="width: 100px; height: 100px;
+ transform: translateZ(200px)">
+ </div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* target = GetLayoutObjectByElementId("target");
+ EXPECT_EQ(FloatRect(0, 100, 100, 100),
+ MapLocalToAncestor(target, nullptr, FloatRect(0, 0, 100, 100)));
+}
+
+TEST_F(MapCoordinatesTest, Transform3DWithOffset2TransformInterop) {
+ ScopedTransformInteropForTest enabled(true);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ body { margin: 0; }
+ </style>
+ <div style="perspective: 400px; width: 0; height: 0">
+ <div style="transform-style: preserve-3d">
+ <div style="height: 100px"></div>
+ <div style="transform-style: preserve-3d; transform: rotateY(0deg)">
+ <div id="target" style="width: 100px; height: 100px;
+ transform: translateZ(200px)">
+ </div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* target = GetLayoutObjectByElementId("target");
+ EXPECT_EQ(FloatRect(0, 200, 200, 200),
+ MapLocalToAncestor(target, nullptr, FloatRect(0, 0, 100, 100)));
+}
+
// This test verifies that the mapped location of a div within a scroller
// remains the same after scroll when ignoring scroll offset.
TEST_F(MapCoordinatesTest, IgnoreScrollOffset) {
diff --git a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
index aee79c33aeb..f808c669e5c 100644
--- a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
+++ b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
@@ -329,11 +329,25 @@ unsigned MultiColumnFragmentainerGroup::ActualColumnCount() const {
void MultiColumnFragmentainerGroup::SetColumnBlockSizeFromNG(
LayoutUnit block_size) {
- DCHECK(!is_logical_height_known_ || logical_height_ == block_size);
+ // We clamp the fragmentainer block size from 0 to 1 for legacy write-back
+ // if there is content that overflows the zero-height fragmentainer. However,
+ // if the last fragmentainer contains no overflow, while previous
+ // fragmentainers do, the known height may be different than the |block_size|
+ // passed in. Don't override the stored height if this is the case.
+ DCHECK(!is_logical_height_known_ || logical_height_ == block_size ||
+ block_size == LayoutUnit());
+ if (is_logical_height_known_)
+ return;
logical_height_ = block_size;
is_logical_height_known_ = true;
}
+void MultiColumnFragmentainerGroup::ExtendColumnBlockSizeFromNG(
+ LayoutUnit block_size) {
+ DCHECK(is_logical_height_known_);
+ logical_height_ += block_size;
+}
+
LayoutUnit MultiColumnFragmentainerGroup::HeightAdjustedForRowOffset(
LayoutUnit height) const {
LayoutUnit adjusted_height =
diff --git a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
index 67866cdf625..d3d45cefb39 100644
--- a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
+++ b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
@@ -87,6 +87,9 @@ class CORE_EXPORT MultiColumnFragmentainerGroup {
void SetLogicalBottomInFlowThread(LayoutUnit logical_bottom_in_flow_thread) {
logical_bottom_in_flow_thread_ = logical_bottom_in_flow_thread;
}
+ void ExtendLogicalBottomInFlowThread(LayoutUnit block_size) {
+ logical_bottom_in_flow_thread_ += block_size;
+ }
// The height of the flow thread portion for the entire fragmentainer group.
LayoutUnit LogicalHeightInFlowThread() const {
@@ -160,6 +163,7 @@ class CORE_EXPORT MultiColumnFragmentainerGroup {
unsigned ActualColumnCount() const;
void SetColumnBlockSizeFromNG(LayoutUnit);
+ void ExtendColumnBlockSizeFromNG(LayoutUnit);
private:
LayoutUnit HeightAdjustedForRowOffset(LayoutUnit height) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
index ed3dea2fd2a..1b7e4902efc 100644
--- a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.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"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
index 2dcc2abc6cd..78e8cbcf323 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
@@ -44,7 +44,7 @@ class CSSLayoutDefinition final : public GarbageCollected<CSSLayoutDefinition>,
const Vector<AtomicString>& custom_invalidation_properties,
const Vector<CSSPropertyID>& child_native_invalidation_properties,
const Vector<AtomicString>& child_custom_invalidation_properties);
- virtual ~CSSLayoutDefinition();
+ ~CSSLayoutDefinition() final;
// This class represents an instance of the layout class defined by the
// CSSLayoutDefinition.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc
index dad70ced44b..dc95b3a3dd5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.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/core/css/cssom/prepopulated_computed_style_property_map.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h
index 2ff02e66e3e..42a660bb546 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_CUSTOM_CUSTOM_LAYOUT_CONSTRAINTS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_CUSTOM_CUSTOM_LAYOUT_CONSTRAINTS_H_
+#include "third_party/abseil-cpp/absl/types/optional.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"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
index 9609cd06547..99b9cbfd372 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.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/core/layout/ng/custom/custom_intrinsic_sizes.h"
#include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
index 2bc5a7f1ea8..de50c9062c5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
@@ -60,8 +60,8 @@ class LayoutWorkletTest : public PageTestBase, public ParametrizedModuleTest {
EXPECT_TRUE(script_state);
KURL js_url("https://example.com/worklet.js");
- v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- script_state->GetIsolate(), source_code, js_url);
+ v8::Local<v8::Module> module =
+ ModuleTestBase::CompileModule(script_state, source_code, js_url);
EXPECT_FALSE(module.IsEmpty());
ScriptValue exception =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
index 3cb3d8dd2b0..6cbce0fd784 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/pending_layout_registry.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/pending_layout_registry.cc
index 8c9b1e0f2c8..cab01cd1ee4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/pending_layout_registry.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/pending_layout_registry.cc
@@ -13,9 +13,9 @@
namespace blink {
void PendingLayoutRegistry::NotifyLayoutReady(const AtomicString& name) {
- PendingSet* set = pending_layouts_.at(name);
- if (set) {
- for (const auto& node : *set) {
+ auto it = pending_layouts_.find(name);
+ if (it != pending_layouts_.end()) {
+ for (const auto& node : *it->value) {
// If the node hasn't been gc'd, trigger a reattachment so that the
// children are correctly blockified.
//
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h b/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h
index 706ddd2e45b..2ed02092b33 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h
@@ -6,8 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_LAYOUT_NG_FLEXIBLE_BOX_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
namespace blink {
@@ -27,7 +26,7 @@ struct DevtoolsFlexInfo {
Vector<Line> lines;
};
-class CORE_EXPORT LayoutNGFlexibleBox : public LayoutNGMixin<LayoutBlock> {
+class CORE_EXPORT LayoutNGFlexibleBox : public LayoutNGBlock {
public:
explicit LayoutNGFlexibleBox(Element*);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index 2eaee00d1f7..5006760dfc8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -92,6 +92,8 @@ AxisEdge MainAxisStaticPositionEdge(const ComputedStyle& style,
? style.ResolvedIsColumnReverseFlexDirection()
: style.ResolvedIsRowReverseFlexDirection();
+ DCHECK_NE(content_position, ContentPosition::kLeft);
+ DCHECK_NE(content_position, ContentPosition::kRight);
if (content_position == ContentPosition::kFlexEnd)
return is_reverse_flex ? AxisEdge::kStart : AxisEdge::kEnd;
@@ -100,6 +102,11 @@ AxisEdge MainAxisStaticPositionEdge(const ComputedStyle& style,
justify.Distribution() == ContentDistributionType::kSpaceEvenly)
return AxisEdge::kCenter;
+ if (content_position == ContentPosition::kStart)
+ return AxisEdge::kStart;
+ if (content_position == ContentPosition::kEnd)
+ return AxisEdge::kEnd;
+
return is_reverse_flex ? AxisEdge::kEnd : AxisEdge::kStart;
}
@@ -209,9 +216,13 @@ bool NGFlexLayoutAlgorithm::IsItemFlexBasisDefinite(
DCHECK(!flex_basis.IsAuto())
<< "This is never called with flex_basis.IsAuto, but it'd be trivial to "
"support.";
- if (!is_column_)
- return true;
- return !BlockLengthUnresolvable(BuildSpaceForFlexBasis(child), flex_basis);
+ DCHECK(!flex_basis.IsContent())
+ << "This is never called with flex_basis.IsContent, but it'd be trivial "
+ "to support.";
+ const NGConstraintSpace& space = BuildSpaceForFlexBasis(child);
+ if (MainAxisIsInlineAxis(child))
+ return !InlineLengthUnresolvable(space, flex_basis);
+ return !BlockLengthUnresolvable(space, flex_basis);
}
// This behavior is under discussion: the item's pre-flexing main size
@@ -299,11 +310,13 @@ NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize(
space_builder.SetCacheSlot(NGCacheSlot::kMeasure);
space_builder.SetIsPaintedAtomically(true);
- if (WillChildCrossSizeBeContainerCrossSize(flex_item)) {
- if (is_column_)
- space_builder.SetStretchInlineSizeIfAuto(true);
- else
- space_builder.SetStretchBlockSizeIfAuto(true);
+ if (!flex_item.IsReplaced()) {
+ if (WillChildCrossSizeBeContainerCrossSize(flex_item)) {
+ if (is_column_)
+ space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchExplicit);
+ else
+ space_builder.SetBlockAutoBehavior(NGAutoBehavior::kStretchExplicit);
+ }
}
// For determining the intrinsic block-size we make %-block-sizes resolve
@@ -311,7 +324,7 @@ NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize(
LogicalSize child_percentage_size = child_percentage_size_;
if (is_column_) {
child_percentage_size.block_size = kIndefiniteSize;
- space_builder.SetIsFixedBlockSizeIndefinite(true);
+ space_builder.SetIsInitialBlockSizeIndefinite(true);
}
space_builder.SetAvailableSize(ChildAvailableSize());
@@ -337,141 +350,6 @@ NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForFlexBasis(
return space_builder.ToConstraintSpace();
}
-namespace {
-
-// This function will be superseded by
-// NGReplacedLayoutAlgorithm.ComputeMinMaxSizes, when such method exists.
-LayoutUnit ComputeIntrinsicInlineSizeForAspectRatioElement(
- const NGBlockNode& node,
- const NGConstraintSpace& space,
- const absl::optional<LayoutUnit> definite_block_size,
- const MinMaxSizes& used_min_max_block_sizes) {
- DCHECK(node.HasAspectRatio());
- LogicalSize aspect_ratio = node.GetAspectRatio();
- const ComputedStyle& style = node.Style();
- NGBoxStrut border_padding =
- ComputeBorders(space, node) + ComputePadding(space, style);
-
- absl::optional<LayoutUnit> intrinsic_inline;
- absl::optional<LayoutUnit> intrinsic_block;
-
- absl::optional<LayoutUnit> block_size_border_box;
- if (definite_block_size.has_value()) {
- block_size_border_box = definite_block_size;
- } else {
- node.IntrinsicSize(&intrinsic_inline, &intrinsic_block);
- if (intrinsic_block) {
- block_size_border_box = *intrinsic_block + border_padding.BlockSum();
- }
- }
-
- if (block_size_border_box) {
- LayoutUnit clamped_intrinsic_block_border_box =
- used_min_max_block_sizes.ClampSizeToMinAndMax(*block_size_border_box);
- return InlineSizeFromAspectRatio(border_padding, aspect_ratio,
- EBoxSizing::kContentBox,
- clamped_intrinsic_block_border_box);
- }
-
- MinMaxSizes inline_min_max = ComputeTransferredMinMaxInlineSizes(
- aspect_ratio, used_min_max_block_sizes, border_padding,
- EBoxSizing::kContentBox);
-
- if (intrinsic_inline) {
- LayoutUnit intrinsic_inline_border_box =
- *intrinsic_inline + border_padding.InlineSum();
- return inline_min_max.ClampSizeToMinAndMax(intrinsic_inline_border_box);
- }
-
- // If control flow reaches here, the item has aspect ratio only, no natural
- // sizes. Spec says:
- // * If the available space is definite in the inline axis, use the stretch
- // fit into that size for the inline size and calculate the block size using
- // the aspect ratio.
- // https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes
- DCHECK_NE(space.AvailableSize().inline_size, kIndefiniteSize);
- NGBoxStrut margins = ComputeMarginsForSelf(space, style);
- return inline_min_max
- .ClampSizeToMinAndMax(space.AvailableSize().inline_size -
- margins.InlineSum())
- .ClampNegativeToZero();
-}
-
-// The value produced by this function will be available via
-// replaced_node.Layout()->IntrinsicBlockSize(), once NGReplacedLayoutAlgorithm
-// exists.
-LayoutUnit ComputeIntrinsicBlockSizeForAspectRatioElement(
- const NGBlockNode& node,
- const NGConstraintSpace& space,
- const absl::optional<LayoutUnit> definite_inline_size,
- const MinMaxSizes& used_min_max_inline_sizes) {
- DCHECK(node.HasAspectRatio());
- LogicalSize aspect_ratio = node.GetAspectRatio();
- const ComputedStyle& style = node.Style();
- NGBoxStrut border_padding =
- ComputeBorders(space, node) + ComputePadding(space, style);
-
- absl::optional<LayoutUnit> intrinsic_inline;
- absl::optional<LayoutUnit> intrinsic_block;
-
- absl::optional<LayoutUnit> inline_size_border_box;
- if (definite_inline_size.has_value()) {
- inline_size_border_box = definite_inline_size;
- } else {
- node.IntrinsicSize(&intrinsic_inline, &intrinsic_block);
- if (intrinsic_inline) {
- inline_size_border_box = *intrinsic_inline + border_padding.InlineSum();
- }
- }
-
- if (inline_size_border_box) {
- LayoutUnit clamped_intrinsic_inline_border_box =
- used_min_max_inline_sizes.ClampSizeToMinAndMax(*inline_size_border_box);
- return BlockSizeFromAspectRatio(border_padding, aspect_ratio,
- EBoxSizing::kContentBox,
- clamped_intrinsic_inline_border_box);
- }
-
- MinMaxSizes transferred_block_min_max = {LayoutUnit(), LayoutUnit::Max()};
- if (used_min_max_inline_sizes.min_size > LayoutUnit()) {
- transferred_block_min_max.min_size = BlockSizeFromAspectRatio(
- border_padding, aspect_ratio, EBoxSizing::kContentBox,
- used_min_max_inline_sizes.min_size);
- }
- if (used_min_max_inline_sizes.max_size != LayoutUnit::Max()) {
- transferred_block_min_max.max_size = BlockSizeFromAspectRatio(
- border_padding, aspect_ratio, EBoxSizing::kContentBox,
- used_min_max_inline_sizes.max_size);
- }
- if (intrinsic_block) {
- // Minimum size wins over maximum size.
- transferred_block_min_max.max_size = std::max(
- transferred_block_min_max.max_size, transferred_block_min_max.min_size);
- LayoutUnit intrinsic_block_border_box =
- *intrinsic_block + border_padding.BlockSum();
- return transferred_block_min_max.ClampSizeToMinAndMax(
- intrinsic_block_border_box);
- }
-
- // If control flow reaches here, the item has aspect ratio only, no natural
- // sizes. Spec says:
- // * If the available space is definite in the inline axis, use the stretch
- // fit into that size for the inline size and calculate the block size using
- // the aspect ratio.
- // https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes
- DCHECK_NE(space.AvailableSize().inline_size, kIndefiniteSize);
- NGBoxStrut margins = ComputeMarginsForSelf(space, style);
- LayoutUnit stretch_into_available_inline_size(
- (space.AvailableSize().inline_size - margins.InlineSum())
- .ClampNegativeToZero());
- return transferred_block_min_max.ClampSizeToMinAndMax(
- BlockSizeFromAspectRatio(border_padding, aspect_ratio,
- EBoxSizing::kContentBox,
- stretch_into_available_inline_size));
-}
-
-} // namespace
-
void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
NGFlexChildIterator iterator(Node());
for (NGBlockNode child = iterator.NextChild(); child;
@@ -540,15 +418,14 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
MinMaxSizesFunc);
}
- absl::optional<LayoutUnit> calculated_intrinsic_block_size;
+ scoped_refptr<const NGLayoutResult> layout_result;
auto IntrinsicBlockSizeFunc = [&]() -> LayoutUnit {
- if (!calculated_intrinsic_block_size) {
+ if (!layout_result) {
NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(child);
- scoped_refptr<const NGLayoutResult> layout_result =
- child.Layout(child_space, /* break_token */ nullptr);
- calculated_intrinsic_block_size = layout_result->IntrinsicBlockSize();
+ layout_result = child.Layout(child_space, /* break_token */ nullptr);
+ DCHECK(layout_result);
}
- return *calculated_intrinsic_block_size;
+ return layout_result->IntrinsicBlockSize();
};
auto ComputeTransferredMainSize = [&]() -> LayoutUnit {
@@ -597,9 +474,13 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
(Style().BoxOrient() == EBoxOrient::kHorizontal ||
Style().BoxAlign() != EBoxAlignment::kStretch))
length_to_resolve = Length::FitContent();
- } else if (IsItemFlexBasisDefinite(child)) {
+ } else if (!flex_basis.IsContent() && IsItemFlexBasisDefinite(child)) {
length_to_resolve = flex_basis;
}
+ DCHECK(!length_to_resolve.IsContent());
+ DCHECK(!flex_basis.IsContent() || length_to_resolve.IsAuto())
+ << "The code below expects flex-basis:content to be translated to "
+ "length_to_resolve.IsAuto()";
if (length_to_resolve.IsAuto()) {
// This block means that the used flex-basis is 'content'. In here we
@@ -615,44 +496,11 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
// containers AND children) row flex containers. I _think_ the C and D
// cases are correctly handled by this code, which was originally
// written for case E.
-
- // Non-replaced AspectRatio items work fine using
- // MinMaxSizesFunc(MinMaxSizesType::kContent).sizes.max_size below, so
- // they don't need to use
- // ComputeIntrinsicInlineSizeForAspectRatioElement.
- if (child.HasAspectRatio() && child.IsReplaced()) {
- // Legacy uses child.PreferredLogicalWidths() for this case, which is
- // not exactly correct.
- // ComputeIntrinsicInlineSizeForAspectRatioElement would honor the
- // definite block size parameter by multipying it by the aspect ratio,
- // but if control flow reaches here, we know we don't have a definite
- // inline size. If we did, we would have fallen into the "part B"
- // section above, not this "part C, D, E" section.
- flex_base_border_box =
- ComputeIntrinsicInlineSizeForAspectRatioElement(
- child, flex_basis_space, /* definite_block_size */
- absl::nullopt, min_max_sizes_in_cross_axis_direction);
- } else {
- flex_base_border_box =
- MinMaxSizesFunc(MinMaxSizesType::kContent).sizes.max_size;
- }
+ flex_base_border_box =
+ MinMaxSizesFunc(MinMaxSizesType::kContent).sizes.max_size;
} else {
// Parts C, D, and E for what are usually column flex containers.
- if (child.HasAspectRatio() && child.IsReplaced()) {
- // Legacy uses the post-layout size for this case, which isn't always
- // correct.
- // With regard to |absl::nullopt| in the next line:
- // ComputeIntrinsicBlockSizeForAspectRatioElement would honor a
- // definite inline size by multipying it by the aspect ratio, but if
- // control flow reaches here, we know we don't have a definite inline
- // size. If we did, we would have fallen into the "part B" section
- // above, not this "part C, D, E" section.
- flex_base_border_box = ComputeIntrinsicBlockSizeForAspectRatioElement(
- child, flex_basis_space, absl::nullopt /* definite_inline_size */,
- min_max_sizes_in_cross_axis_direction);
- } else {
- flex_base_border_box = IntrinsicBlockSizeFunc();
- }
+ flex_base_border_box = IntrinsicBlockSizeFunc();
}
} else {
// Part A of 9.2.3 https://drafts.csswg.org/css-flexbox/#algo-main-item
@@ -693,57 +541,10 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
if (algorithm_.ShouldApplyMinSizeAutoForChild(*child.GetLayoutBox())) {
LayoutUnit content_size_suggestion;
if (MainAxisIsInlineAxis(child)) {
- if (child.IsReplaced() && child.HasAspectRatio()) {
- absl::optional<LayoutUnit> definite_block_size;
- if (!BlockLengthUnresolvable(flex_basis_space,
- child_style.LogicalHeight())) {
- definite_block_size = ResolveMainBlockLength(
- flex_basis_space, child_style,
- border_padding_in_child_writing_mode,
- child_style.LogicalHeight(), IntrinsicBlockSizeFunc);
- }
-
- content_size_suggestion =
- ComputeIntrinsicInlineSizeForAspectRatioElement(
- child, flex_basis_space, definite_block_size,
- min_max_sizes_in_cross_axis_direction);
- } else {
- content_size_suggestion =
- MinMaxSizesFunc(MinMaxSizesType::kContent).sizes.min_size;
- }
+ content_size_suggestion =
+ MinMaxSizesFunc(MinMaxSizesType::kContent).sizes.min_size;
} else {
- LayoutUnit intrinsic_block_size;
- if (child.IsReplaced()) {
- if (child.HasAspectRatio()) {
- absl::optional<LayoutUnit> definite_inline_size;
- if (!child_style.LogicalWidth().IsAuto()) {
- definite_inline_size = ResolveMainInlineLength(
- flex_basis_space, child_style,
- border_padding_in_child_writing_mode, MinMaxSizesFunc,
- child_style.LogicalWidth());
- }
- intrinsic_block_size =
- ComputeIntrinsicBlockSizeForAspectRatioElement(
- child, flex_basis_space, definite_inline_size,
- min_max_sizes_in_cross_axis_direction);
- } else {
- // This code block is needed to make
- // flex-aspect-ratio-img-column-017.html pass, but the test may be
- // wrong. https://github.com/web-platform-tests/wpt/issues/27653
- absl::optional<LayoutUnit> computed_inline_size;
- absl::optional<LayoutUnit> computed_block_size;
- child.IntrinsicSize(&computed_inline_size, &computed_block_size);
-
- // The 150 is for replaced elements that have no size, which SVG
- // can have (maybe others?).
- intrinsic_block_size =
- computed_block_size.value_or(LayoutUnit(150)) +
- border_padding_in_child_writing_mode.BlockSum();
- }
- } else {
- intrinsic_block_size = IntrinsicBlockSizeFunc();
- }
- content_size_suggestion = intrinsic_block_size;
+ content_size_suggestion = IntrinsicBlockSizeFunc();
}
DCHECK_GE(content_size_suggestion, main_axis_border_padding);
@@ -824,6 +625,11 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
physical_child_margins, scrollbars,
min_max_sizes.has_value())
.ng_input_node_ = child;
+ // Save the layout result so that we can maybe reuse it later.
+ if (layout_result) {
+ DCHECK(!MainAxisIsInlineAxis(child));
+ algorithm_.all_items_.back().layout_result_ = layout_result;
+ }
}
}
@@ -944,73 +750,40 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() {
space_builder.SetIsPaintedAtomically(true);
LogicalSize available_size;
- LayoutUnit fixed_aspect_ratio_cross_size = kIndefiniteSize;
- if (flex_item.ng_input_node_.HasAspectRatio() &&
- flex_item.ng_input_node_.IsReplaced()) {
- // This code derives the cross axis size from the flexed main size and
- // the aspect ratio. We can delete this code when
- // NGReplacedLayoutAlgorithm exists, because it will do this for us.
- NGConstraintSpace flex_basis_space =
- BuildSpaceForFlexBasis(flex_item.ng_input_node_);
- const Length& cross_axis_length =
- is_horizontal_flow_ ? child_style.Height() : child_style.Width();
- // Only derive the cross axis size from the aspect ratio if the computed
- // cross axis length might be indefinite. The item's cross axis length
- // might still be definite if it is stretched, but that is checked in
- // the |WillChildCrossSizeBeContainerCrossSize| calls below.
- if (cross_axis_length.IsAuto() ||
- (MainAxisIsInlineAxis(flex_item.ng_input_node_) &&
- BlockLengthUnresolvable(flex_basis_space, cross_axis_length))) {
- LogicalSize aspect_ratio =
- GetMainOverCrossAspectRatio(flex_item.ng_input_node_);
- aspect_ratio.Transpose();
- fixed_aspect_ratio_cross_size =
- flex_item.min_max_cross_sizes_->ClampSizeToMinAndMax(
- flex_item.cross_axis_border_padding_ +
- ComputeSizeFromAspectRatio(flex_item.flexed_content_size_,
- aspect_ratio));
- }
- }
if (is_column_) {
available_size.inline_size = ChildAvailableSize().inline_size;
available_size.block_size = flex_item.flexed_content_size_ +
flex_item.main_axis_border_padding_;
space_builder.SetIsFixedBlockSize(true);
- if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_)) {
- space_builder.SetStretchInlineSizeIfAuto(true);
- } else if (fixed_aspect_ratio_cross_size != kIndefiniteSize) {
- space_builder.SetIsFixedInlineSize(true);
- available_size.inline_size = fixed_aspect_ratio_cross_size;
- }
+ if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_))
+ space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchExplicit);
// https://drafts.csswg.org/css-flexbox/#definite-sizes
// If the flex container has a definite main size, a flex item's
// post-flexing main size is treated as definite, even though it can
// rely on the indefinite sizes of any flex items in the same line.
if (!IsColumnContainerMainSizeDefinite() &&
!IsItemMainSizeDefinite(flex_item.ng_input_node_)) {
- space_builder.SetIsFixedBlockSizeIndefinite(true);
+ space_builder.SetIsInitialBlockSizeIndefinite(true);
}
} else {
available_size.inline_size = flex_item.flexed_content_size_ +
flex_item.main_axis_border_padding_;
available_size.block_size = ChildAvailableSize().block_size;
space_builder.SetIsFixedInlineSize(true);
- if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_)) {
- space_builder.SetStretchBlockSizeIfAuto(true);
- } else if (fixed_aspect_ratio_cross_size != kIndefiniteSize) {
- space_builder.SetIsFixedBlockSize(true);
- available_size.block_size = fixed_aspect_ratio_cross_size;
- } else if (DoesItemStretch(flex_item.ng_input_node_)) {
- // If we are in a row flexbox, and we don't have a fixed block-size
- // (yet), use the "measure" cache slot. This will be the first
- // layout, and we will use the "layout" cache slot if this gets
- // stretched later.
- //
- // Setting the "measure" cache slot on the space writes the result
- // into both the "measure", and "layout" cache slots. If a subsequent
- // "layout" occurs, it'll just get written into the "layout" slot.
- space_builder.SetCacheSlot(NGCacheSlot::kMeasure);
- }
+ if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_))
+ space_builder.SetBlockAutoBehavior(NGAutoBehavior::kStretchExplicit);
+ }
+ if (DoesItemStretch(flex_item.ng_input_node_)) {
+ // For stretched items, the goal of this layout is determine the
+ // post-flexed, pre-stretched cross-axis size. Stretched items will
+ // later get a final layout with a potentially different cross size so
+ // use the "measure" slot for this layout. We will use the "layout"
+ // cache slot for the item's final layout.
+ //
+ // Setting the "measure" cache slot on the space writes the result
+ // into both the "measure" and "layout" cache slots. So the stretch
+ // layout will reuse this "measure" result if it can.
+ space_builder.SetCacheSlot(NGCacheSlot::kMeasure);
}
space_builder.SetAvailableSize(available_size);
@@ -1027,16 +800,44 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() {
}
NGConstraintSpace child_space = space_builder.ToConstraintSpace();
- flex_item.layout_result_ =
- flex_item.ng_input_node_.Layout(child_space, nullptr /*break token*/);
-
- // TODO(layout-dev): Handle abortions caused by block fragmentation.
- DCHECK_EQ(flex_item.layout_result_->Status(), NGLayoutResult::kSuccess);
-
- flex_item.cross_axis_size_ =
- is_horizontal_flow_
- ? flex_item.layout_result_->PhysicalFragment().Size().height
- : flex_item.layout_result_->PhysicalFragment().Size().width;
+ // We need to get the item's cross axis size given its new main size. If
+ // the new main size is the item's inline size, then we have to do a
+ // layout to get its new block size. But if the new main size is the
+ // item's block size, we can skip layout in some cases and just calculate
+ // the inline size from the constraint space.
+ // Even when we only need inline size, we have to lay out the item if:
+ // * this is the item's last chance to layout (i.e. doesn't stretch), OR
+ // * the item has not yet been laid out. (ComputeLineItemsPosition
+ // relies on the fragment's baseline, which comes from the post-layout
+ // fragment)
+ if (DoesItemStretch(flex_item.ng_input_node_) &&
+ flex_item.layout_result_) {
+ DCHECK(!MainAxisIsInlineAxis(flex_item.ng_input_node_));
+ NGBoxStrut border =
+ ComputeBorders(child_space, flex_item.ng_input_node_);
+ NGBoxStrut padding = ComputePadding(child_space, child_style);
+ if (flex_item.ng_input_node_.IsReplaced()) {
+ LogicalSize logical_border_box_size = ComputeReplacedSize(
+ flex_item.ng_input_node_, child_space, border + padding);
+ flex_item.cross_axis_size_ = logical_border_box_size.inline_size;
+ } else {
+ flex_item.cross_axis_size_ = ComputeInlineSizeForFragment(
+ child_space, flex_item.ng_input_node_, border + padding);
+ }
+ } else {
+ DCHECK((child_space.CacheSlot() == NGCacheSlot::kLayout) ||
+ !flex_item.layout_result_)
+ << "If we already have a 'measure' result from "
+ "ConstructAndAppendFlexItems, we don't want to evict it.";
+ flex_item.layout_result_ = flex_item.ng_input_node_.Layout(
+ child_space, nullptr /*break token*/);
+ // TODO(layout-dev): Handle abortions caused by block fragmentation.
+ DCHECK_EQ(flex_item.layout_result_->Status(), NGLayoutResult::kSuccess);
+ flex_item.cross_axis_size_ =
+ is_horizontal_flow_
+ ? flex_item.layout_result_->PhysicalFragment().Size().height
+ : flex_item.layout_result_->PhysicalFragment().Size().width;
+ }
}
// cross_axis_offset is updated in each iteration of the loop, for passing
// in to the next iteration.
@@ -1047,7 +848,7 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() {
LayoutUnit intrinsic_block_size = BorderScrollbarPadding().BlockSum();
if (algorithm_.FlexLines().IsEmpty() && Node().HasLineIfEmpty()) {
- intrinsic_block_size += Node().GetLayoutBox()->LogicalHeightForEmptyLine();
+ intrinsic_block_size += Node().EmptyLineBlockSize();
} else {
intrinsic_block_size += algorithm_.IntrinsicContentBlockSize();
}
@@ -1092,7 +893,7 @@ void NGFlexLayoutAlgorithm::ApplyStretchAlignmentToChild(FlexItem& flex_item) {
available_size.Transpose();
if (!IsColumnContainerMainSizeDefinite() &&
!IsItemMainSizeDefinite(flex_item.ng_input_node_)) {
- space_builder.SetIsFixedBlockSizeIndefinite(true);
+ space_builder.SetIsInitialBlockSizeIndefinite(true);
}
}
@@ -1338,10 +1139,8 @@ MinMaxSizesResult NGFlexLayoutAlgorithm::ComputeMinMaxSizes(
builder.SetPercentageResolutionBlockSize(child_percentage_size_.block_size);
builder.SetReplacedPercentageResolutionBlockSize(
child_percentage_size_.block_size);
- if (is_column_)
- builder.SetIsFixedBlockSizeIndefinite(true);
- else if (WillChildCrossSizeBeContainerCrossSize(child))
- builder.SetStretchBlockSizeIfAuto(true);
+ if (!is_column_ && WillChildCrossSizeBeContainerCrossSize(child))
+ builder.SetBlockAutoBehavior(NGAutoBehavior::kStretchExplicit);
const auto space = builder.ToConstraintSpace();
MinMaxSizesResult child_result =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm_test.cc
index 9056eca4858..5907b037fed 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm_test.cc
@@ -150,5 +150,67 @@ TEST_F(NGFlexLayoutAlgorithmTest, DevtoolsOneImageItemCrash) {
EXPECT_EQ(devtools.lines.size(), 1u);
}
+TEST_F(NGFlexLayoutAlgorithmTest, DevtoolsColumnWrap) {
+ DevtoolsFlexInfo devtools = LayoutForDevtools(R"HTML(
+ <div style="display: flex; flex-flow: column wrap; width: 300px; height: 100px;" id=flexbox>
+ <div style="height: 200px">
+ <div style="height: 90%"></div>
+ </div>
+ </div>
+ )HTML");
+ EXPECT_EQ(devtools.lines.size(), 1u);
+}
+
+TEST_F(NGFlexLayoutAlgorithmTest, DevtoolsColumnWrapOrtho) {
+ DevtoolsFlexInfo devtools = LayoutForDevtools(R"HTML(
+ <div style="display: flex; flex-flow: column wrap; width: 300px; height: 100px;" id=flexbox>
+ <div style="height: 200px; writing-mode: vertical-lr;">
+ <div style="width: 90%"></div>
+ </div>
+ </div>
+ )HTML");
+ EXPECT_EQ(devtools.lines.size(), 1u);
+}
+
+TEST_F(NGFlexLayoutAlgorithmTest, DevtoolsRowWrapOrtho) {
+ DevtoolsFlexInfo devtools = LayoutForDevtools(R"HTML(
+ <div style="display: flex; flex-flow: wrap; width: 300px; height: 100px;" id=flexbox>
+ <div style="height: 200px; writing-mode: vertical-lr;">
+ <div style="width: 90%"></div>
+ <div style="height: 90%"></div>
+ </div>
+ </div>
+ )HTML");
+ EXPECT_EQ(devtools.lines.size(), 1u);
+}
+
+TEST_F(NGFlexLayoutAlgorithmTest, DevtoolsLegacyItem) {
+ DevtoolsFlexInfo devtools = LayoutForDevtools(R"HTML(
+ <div style="display: flex;" id=flexbox>
+ <div style="columns: 1"></div>
+ </div>
+ )HTML");
+ EXPECT_EQ(devtools.lines.size(), 1u);
+}
+
+TEST_F(NGFlexLayoutAlgorithmTest, DevtoolsFragmentedItemDoesntCrash) {
+ const String& body_content = R"HTML(
+ <div style="columns: 2; height: 300px; width: 300px; background: orange;">
+ <div style="display: flex; background: blue;" id=flexbox>
+ <div style="width: 100px; height: 300px; background: grey;"></div>
+ </div>
+ </div>
+ )HTML";
+ // TODO(crbug.com/660611): Remove next 6 lines when flex fragmentation ships.
+ SetBodyInnerHTML(body_content);
+ UpdateAllLifecyclePhasesForTest();
+ LayoutObject* flexbox = GetLayoutObjectByElementId("flexbox");
+ EXPECT_NE(flexbox, nullptr);
+ if (!flexbox->IsLayoutNGFlexibleBox())
+ return;
+ DevtoolsFlexInfo devtools = LayoutForDevtools(body_content);
+ EXPECT_EQ(devtools.lines.size(), 1u);
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h
index 91471c971f2..def39855a65 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BFC_OFFSET_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BFC_OFFSET_H_
+#include <tuple>
+
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc
index be5a629c744..b8b33b74826 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc
@@ -27,7 +27,7 @@ const LayoutNGGridInterface* LayoutNGGrid::ToLayoutNGGridInterface() const {
return this;
}
-size_t LayoutNGGrid::ExplicitGridStartForDirection(
+wtf_size_t LayoutNGGrid::ExplicitGridStartForDirection(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
const auto* grid_data = GetGridData();
@@ -37,7 +37,7 @@ size_t LayoutNGGrid::ExplicitGridStartForDirection(
: grid_data->column_start;
}
-size_t LayoutNGGrid::ExplicitGridEndForDirection(
+wtf_size_t LayoutNGGrid::ExplicitGridEndForDirection(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
const auto* grid_data = GetGridData();
@@ -47,7 +47,7 @@ size_t LayoutNGGrid::ExplicitGridEndForDirection(
: grid_data->column_geometry.total_track_count;
}
-size_t LayoutNGGrid::AutoRepeatCountForDirection(
+wtf_size_t LayoutNGGrid::AutoRepeatCountForDirection(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
const auto* grid_data = GetGridData();
@@ -69,17 +69,14 @@ LayoutUnit LayoutNGGrid::GridGap(GridTrackSizingDirection direction) const {
LayoutUnit LayoutNGGrid::GridItemOffset(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
- const auto* grid_data = GetGridData();
- const auto& geometry = (direction == kForRows) ? grid_data->row_geometry
- : grid_data->column_geometry;
- DCHECK(geometry.sets.size());
- return geometry.sets[0].offset;
+ // Distribution offset is baked into the gutter_size in GridNG.
+ return LayoutUnit();
}
-Vector<LayoutUnit> LayoutNGGrid::TrackSizesForComputedStyle(
+Vector<LayoutUnit, 1> LayoutNGGrid::TrackSizesForComputedStyle(
GridTrackSizingDirection direction) const {
NOT_DESTROYED();
- Vector<LayoutUnit> track_sizes;
+ Vector<LayoutUnit, 1> track_sizes;
const auto* grid_data = GetGridData();
if (!grid_data)
return track_sizes;
@@ -127,7 +124,7 @@ Vector<LayoutUnit> LayoutNGGrid::ComputeExpandedPositions(
LayoutUnit current_offset = geometry.sets[0].offset;
expanded_positions.ReserveInitialCapacity(
- std::min<wtf_size_t>(geometry.total_track_count + 1, kGridMaxTracks));
+ std::min<wtf_size_t>(geometry.total_track_count + 1, kGridMaxTracks + 1));
expanded_positions.emplace_back(current_offset);
bool is_last_range_collapsed = true;
@@ -143,9 +140,11 @@ Vector<LayoutUnit> LayoutNGGrid::ComputeExpandedPositions(
(range.IsCollapsed() ? LayoutUnit() : geometry.gutter_size);
expanded_positions.emplace_back(current_offset);
- // Respect total track count limit.
- DCHECK(expanded_positions.size() <= kGridMaxTracks);
- if (expanded_positions.size() == kGridMaxTracks)
+ // Respect total track count limit, don't forget to account for the
+ // initial offset.
+ DCHECK_LE(expanded_positions.size(),
+ static_cast<unsigned int>(kGridMaxTracks + 1));
+ if (expanded_positions.size() == kGridMaxTracks + 1)
return;
}
}
@@ -165,7 +164,7 @@ const NGGridData* LayoutNGGrid::GetGridData() const {
// See comment above |NGGridData| for explanation on why we can't just divide
// the set sizes by their track count.
Vector<LayoutUnit> LayoutNGGrid::ComputeTrackSizesInRange(
- const NGGridData::RangeData& range,
+ const NGGridLayoutAlgorithmTrackCollection::Range& range,
GridTrackSizingDirection direction) const {
Vector<LayoutUnit> track_sizes;
const auto* grid_data = GetGridData();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h
index 1e212089d8e..964ae483b1e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h
@@ -6,14 +6,14 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_LAYOUT_NG_GRID_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid_interface.h"
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
namespace blink {
-class CORE_EXPORT LayoutNGGrid : public LayoutNGMixin<LayoutBlock>,
+class CORE_EXPORT LayoutNGGrid : public LayoutNGBlock,
public LayoutNGGridInterface {
public:
explicit LayoutNGGrid(Element*);
@@ -24,15 +24,15 @@ class CORE_EXPORT LayoutNGGrid : public LayoutNGMixin<LayoutBlock>,
const LayoutNGGridInterface* ToLayoutNGGridInterface() const final;
- size_t ExplicitGridStartForDirection(
+ wtf_size_t ExplicitGridStartForDirection(
GridTrackSizingDirection direction) const final;
- size_t ExplicitGridEndForDirection(
+ wtf_size_t ExplicitGridEndForDirection(
GridTrackSizingDirection direction) const final;
- size_t AutoRepeatCountForDirection(
+ wtf_size_t AutoRepeatCountForDirection(
GridTrackSizingDirection direction) const final;
LayoutUnit GridGap(GridTrackSizingDirection) const final;
LayoutUnit GridItemOffset(GridTrackSizingDirection) const final;
- Vector<LayoutUnit> TrackSizesForComputedStyle(
+ Vector<LayoutUnit, 1> TrackSizesForComputedStyle(
GridTrackSizingDirection direction) const final;
Vector<LayoutUnit> RowPositions() const final;
Vector<LayoutUnit> ColumnPositions() const final;
@@ -46,7 +46,7 @@ class CORE_EXPORT LayoutNGGrid : public LayoutNGMixin<LayoutBlock>,
private:
const NGGridData* GetGridData() const;
Vector<LayoutUnit> ComputeTrackSizesInRange(
- const NGGridData::RangeData& range,
+ const NGGridLayoutAlgorithmTrackCollection::Range& range,
GridTrackSizingDirection direction) const;
Vector<LayoutUnit> ComputeExpandedPositions(
GridTrackSizingDirection direction) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid_interface.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid_interface.h
index dc8d0e7c18b..4aecc14dd7b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid_interface.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid_interface.h
@@ -5,22 +5,25 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_LAYOUT_NG_GRID_INTERFACE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_LAYOUT_NG_GRID_INTERFACE_H_
+#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/table/interface_casting.h"
namespace blink {
+class LayoutUnit;
+
// This class provides an abstraction between legacy and NG grid. This allows us
// to avoid forking behavior elsewhere.
class LayoutNGGridInterface {
public:
- virtual size_t ExplicitGridStartForDirection(
+ virtual wtf_size_t ExplicitGridStartForDirection(
GridTrackSizingDirection direction) const = 0;
- virtual size_t ExplicitGridEndForDirection(
+ virtual wtf_size_t ExplicitGridEndForDirection(
GridTrackSizingDirection direction) const = 0;
- virtual size_t AutoRepeatCountForDirection(
+ virtual wtf_size_t AutoRepeatCountForDirection(
GridTrackSizingDirection direction) const = 0;
- virtual Vector<LayoutUnit> TrackSizesForComputedStyle(
+ virtual Vector<LayoutUnit, 1> TrackSizesForComputedStyle(
GridTrackSizingDirection direction) const = 0;
virtual Vector<LayoutUnit> RowPositions() const = 0;
virtual Vector<LayoutUnit> ColumnPositions() const = 0;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.cc
deleted file mode 100644
index d0791c16dea..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h"
-
-namespace blink {
-
-NGGridChildIterator::NGGridChildIterator(const NGBlockNode node) {
- Setup(node);
-}
-
-void NGGridChildIterator::Setup(const NGBlockNode node) {
- const int initial_order = ComputedStyleInitialValues::InitialOrder();
- bool needs_sort = false;
-
- // Collect all our children, and order them by either their order property.
- for (NGLayoutInputNode child = node.FirstChild(); child;
- child = child.NextSibling()) {
- int order = child.Style().Order();
- needs_sort |= order != initial_order;
- children_.emplace_back(To<NGBlockNode>(child), order);
- }
-
- // We only need to sort this vector if we encountered a non-initial order
- // property.
- if (needs_sort) {
- std::stable_sort(children_.begin(), children_.end(),
- [](const ChildWithOrder& c1, const ChildWithOrder& c2) {
- return c1.order < c2.order;
- });
- }
-
- iterator_ = children_.begin();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h
deleted file mode 100644
index 440e4a8180f..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_CHILD_ITERATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_CHILD_ITERATOR_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-// A utility class which given the current grid node will iterate through its
-// children.
-//
-// TODO(layout-dev): Once LayoutNG supports NG-fragmentation this will need
-// to be updated to accept a break-token.
-//
-// This class does not handle modifications to its arguments after it has been
-// constructed.
-class CORE_EXPORT NGGridChildIterator {
- STACK_ALLOCATED();
-
- public:
- explicit NGGridChildIterator(const NGBlockNode node);
-
- // Returns the next block node which should be laid out.
- NGBlockNode NextChild() {
- if (iterator_ == children_.end())
- return nullptr;
-
- return (*iterator_++).child;
- }
-
- struct ChildWithOrder {
- DISALLOW_NEW();
- ChildWithOrder(NGBlockNode child, int order) : child(child), order(order) {}
- NGBlockNode child;
- int order;
- };
-
- protected:
- virtual void Setup(const NGBlockNode node);
- Vector<ChildWithOrder, 4> children_;
- Vector<ChildWithOrder, 4>::const_iterator iterator_;
-};
-
-} // namespace blink
-
-WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(
- blink::NGGridChildIterator::ChildWithOrder)
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_CHILD_ITERATOR_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator_test.cc
deleted file mode 100644
index 64ad7270ff9..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator_test.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
-
-namespace blink {
-namespace {
-
-TEST_F(NGLayoutTest, TestNGGridChildIterator) {
- SetBodyInnerHTML(R"HTML(
- <style>
- #parent {
- display: grid;
- grid-template-columns: 10px 10px;
- grid-template-rows: 10px 10px;
- }
- </style>
- <div id="parent">
- <div id="child1">Child 1</div>
- <div id="child2">Child 2</div>
- <div id="child3">Child 3</div>
- <div id="child4">Child 4</div>
- </div>
- )HTML");
-
- NGBlockNode parent_block(GetLayoutBoxByElementId("parent"));
-
- int index = 0;
- NGGridChildIterator iterator(parent_block);
- for (NGBlockNode child = iterator.NextChild(); child;
- child = iterator.NextChild()) {
- StringBuilder cell_id;
- cell_id.Append("child");
- cell_id.Append(AtomicString::Number(++index));
- NGBlockNode cell_block(
- GetLayoutBoxByElementId(cell_id.ToString().Ascii().c_str()));
- EXPECT_EQ(child, cell_block);
- }
-
- EXPECT_EQ(index, 4);
-}
-
-TEST_F(NGLayoutTest, TestNGGridChildIteratorWithOrderReversed) {
- SetBodyInnerHTML(R"HTML(
- <style>
- #parent {
- display: grid;
- grid-template-columns: 10px 10px;
- grid-template-rows: 10px 10px;
- }
- </style>
- <div id="parent">
- <div id="child1" style="order: 4">Child 1</div>
- <div id="child2" style="order: 3">Child 2</div>
- <div id="child3" style="order: 2">Child 3</div>
- <div id="child4" style="order: 1">Child 4</div>
- </div>
- )HTML");
-
- NGBlockNode parent_block(GetLayoutBoxByElementId("parent"));
-
- int index = 4;
- NGGridChildIterator iterator(parent_block);
- for (NGBlockNode child = iterator.NextChild(); child;
- child = iterator.NextChild()) {
- StringBuilder cell_id;
- cell_id.Append("child");
- cell_id.Append(AtomicString::Number(index));
- NGBlockNode cell_block(
- GetLayoutBoxByElementId(cell_id.ToString().Ascii().c_str()));
- EXPECT_EQ(child, cell_block);
- --index;
- }
-
- EXPECT_EQ(index, 0);
-}
-
-TEST_F(NGLayoutTest, TestNGGridChildIteratorWithOrderMixed) {
- SetBodyInnerHTML(R"HTML(
- <style>
- #parent {
- display: grid;
- grid-template-columns: 10px 10px;
- grid-template-rows: 10px 10px;
- }
- </style>
- <div id="parent"">
- <div id="child1" style="order: 3">Child 1</div>
- <div id="child2" style="order: 3">Child 2</div>
- <div id="child3" style="order: -1">Child 3</div>
- <div id="child4" style="order: 0">Child 4</div>
- </div>
- )HTML");
-
- NGBlockNode parent_block(GetLayoutBoxByElementId("parent"));
- int expected_order[] = {3, 4, 1, 2};
-
- int index = 0;
- NGGridChildIterator iterator(parent_block);
- for (NGBlockNode child = iterator.NextChild(); child;
- child = iterator.NextChild()) {
- StringBuilder cell_id;
- cell_id.Append("child");
- cell_id.Append(AtomicString::Number(expected_order[index]));
- NGBlockNode cell_block(
- GetLayoutBoxByElementId(cell_id.ToString().Ascii().c_str()));
- EXPECT_EQ(child, cell_block);
- ++index;
- }
-
- EXPECT_EQ(index, 4);
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
index 8aca9c5334b..83a76e30cfb 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_DATA_H_
+#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -19,40 +20,23 @@ namespace blink {
// This means that although splitting the sets by their track count would not
// give the correct result.
struct NGGridData {
+ using RangeData = NGGridLayoutAlgorithmTrackCollection::Range;
+
wtf_size_t row_start;
wtf_size_t column_start;
wtf_size_t row_auto_repeat_track_count;
wtf_size_t column_auto_repeat_track_count;
+
struct SetData {
SetData(LayoutUnit offset, wtf_size_t track_count)
: offset(offset), track_count(track_count) {}
LayoutUnit offset;
- // This is derived from other data in layout_ng_grid, can be removed if not
- // useful for out of flow elements.
wtf_size_t track_count;
};
- struct RangeData {
- RangeData(wtf_size_t track_count,
- wtf_size_t starting_set_index,
- wtf_size_t set_count)
- : starting_set_index(starting_set_index),
- track_count(track_count),
- set_count(set_count) {}
-
- // We don't store the |kIsCollapsed| flag from track collections here, but
- // collapsed ranges can be identified by their set count being zero.
- bool IsCollapsed() const { return !set_count; }
- // This is derived from other data in layout_ng_grid, can be removed if not
- // useful for out of flow elements.
- wtf_size_t starting_set_index;
- wtf_size_t track_count;
- wtf_size_t set_count;
- };
struct TrackCollectionGeometry {
Vector<SetData> sets;
Vector<RangeData> ranges;
-
LayoutUnit gutter_size;
wtf_size_t total_track_count;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 9b40e45c7f9..f15e8512df5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -4,10 +4,10 @@
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h"
-#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
@@ -29,6 +29,26 @@ NGGridLayoutAlgorithm::NGGridLayoutAlgorithm(
grid_available_size_ = grid_min_available_size_ = grid_max_available_size_ =
ChildAvailableSize();
+ // Firstly if block-size containment applies compute the block-size ignoring
+ // children (just based on the row definitions).
+ if (grid_available_size_.block_size == kIndefiniteSize &&
+ Node().ShouldApplyBlockSizeContainment()) {
+ // We always need a definite min block-size in order to run the track
+ // sizing algorithm.
+ grid_min_available_size_.block_size = BorderScrollbarPadding().BlockSum();
+ contain_intrinsic_block_size_ = ComputeIntrinsicBlockSizeIgnoringChildren();
+
+ // Resolve the block-size, and set the available sizes.
+ const LayoutUnit block_size = ComputeBlockSizeForFragment(
+ ConstraintSpace(), Style(), BorderPadding(),
+ *contain_intrinsic_block_size_, border_box_size_.inline_size);
+
+ grid_available_size_.block_size = grid_min_available_size_.block_size =
+ grid_max_available_size_.block_size =
+ (block_size - BorderScrollbarPadding().BlockSum())
+ .ClampNegativeToZero();
+ }
+
// Next if our inline-size is indefinite, compute the min/max inline-sizes.
if (grid_available_size_.inline_size == kIndefiniteSize) {
const LayoutUnit border_scrollbar_padding =
@@ -69,12 +89,48 @@ NGGridLayoutAlgorithm::NGGridLayoutAlgorithm(
}
}
+namespace {
+
+bool MayChangeOrthogonalItemContributions(
+ const NGGridLayoutAlgorithm::SetGeometry& old_row_geometry,
+ const NGGridLayoutAlgorithm::SetGeometry& new_row_geometry,
+ const NGGridLayoutAlgorithm::GridItems& grid_items,
+ const WritingMode container_writing_mode) {
+ auto GridItemRowSpanSize =
+ [](const NGGridLayoutAlgorithm::GridItemData& grid_item,
+ const NGGridLayoutAlgorithm::SetGeometry& set_geometry) -> LayoutUnit {
+ const auto& set_indices = grid_item.SetIndices(kForRows);
+ const wtf_size_t last_indefinite_index =
+ set_geometry.last_indefinite_indices.IsEmpty()
+ ? kNotFound
+ : set_geometry.last_indefinite_indices[set_indices.end];
+
+ DCHECK(last_indefinite_index == kNotFound ||
+ last_indefinite_index < set_indices.begin);
+ return set_geometry.sets[set_indices.end].offset -
+ set_geometry.sets[set_indices.begin].offset -
+ set_geometry.gutter_size;
+ };
+
+ for (const auto& grid_item : grid_items.item_data) {
+ if (!IsParallelWritingMode(container_writing_mode,
+ grid_item.node.Style().GetWritingMode()) &&
+ GridItemRowSpanSize(grid_item, old_row_geometry) !=
+ GridItemRowSpanSize(grid_item, new_row_geometry)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
scoped_refptr<const NGLayoutResult> NGGridLayoutAlgorithm::Layout() {
PaintLayerScrollableArea::DelayScrollOffsetClampScope delay_clamp_scope;
// Measure items.
GridItems grid_items;
- Vector<GridItemData> out_of_flow_items;
+ GridItemStorageVector out_of_flow_items;
ConstructAndAppendGridItems(&grid_items, &out_of_flow_items);
const auto& container_style = Style();
@@ -101,18 +157,16 @@ scoped_refptr<const NGLayoutResult> NGGridLayoutAlgorithm::Layout() {
row_block_track_collection,
grid_available_size_.block_size == kIndefiniteSize);
- // Cache track span properties for grid items.
- CacheGridItemsTrackSpanProperties(column_track_collection, &grid_items);
- CacheGridItemsTrackSpanProperties(row_track_collection, &grid_items);
-
- // Cache set indices and alignment fallbacks for grid items.
+ // Cache set indices for grid items.
for (auto& grid_item : grid_items.item_data) {
grid_item.ComputeSetIndices(column_track_collection);
grid_item.ComputeSetIndices(row_track_collection);
- grid_item.SetAlignmentFallback(column_track_collection, container_style);
- grid_item.SetAlignmentFallback(row_track_collection, container_style);
}
+ // Cache track span properties for grid items.
+ CacheGridItemsTrackSpanProperties(column_track_collection, &grid_items);
+ CacheGridItemsTrackSpanProperties(row_track_collection, &grid_items);
+
// We perform the track sizing algorithm using two methods. First
// |InitializeTrackSizes|, which we need to get an initial column and row
// set geometry. Then |ComputeUsedTrackSizes|, to finalize the sizing
@@ -122,84 +176,94 @@ scoped_refptr<const NGLayoutResult> NGGridLayoutAlgorithm::Layout() {
// Store column baselines, as these contributions can influence column
// sizing.
- CalculateAlignmentBaselines(grid_items, kForColumns, &grid_geometry);
+ bool needs_additional_pass = false;
+ CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items,
+ &needs_additional_pass);
// Resolve inline size.
- bool needs_additional_pass = false;
+ bool has_block_size_dependent_item = false;
grid_geometry.column_geometry = ComputeUsedTrackSizes(
SizingConstraint::kLayout, grid_geometry, &column_track_collection,
- &grid_items, &needs_additional_pass);
- CalculateAlignmentBaselines(grid_items, kForRows, &grid_geometry);
+ &grid_items, &needs_additional_pass, &has_block_size_dependent_item);
+
+ CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items,
+ &needs_additional_pass);
+
+ absl::optional<SetGeometry> initial_row_geometry;
+ if (!needs_additional_pass && has_block_size_dependent_item)
+ initial_row_geometry = grid_geometry.row_geometry;
// Resolve block size.
bool unused_needs_additional_pass = false;
grid_geometry.row_geometry = ComputeUsedTrackSizes(
SizingConstraint::kLayout, grid_geometry, &row_track_collection,
&grid_items, &unused_needs_additional_pass);
- DCHECK(!unused_needs_additional_pass);
- CalculateAlignmentBaselines(grid_items, kForColumns, &grid_geometry);
+
+ if (initial_row_geometry) {
+ DCHECK(!needs_additional_pass && has_block_size_dependent_item);
+ needs_additional_pass = MayChangeOrthogonalItemContributions(
+ *initial_row_geometry, grid_geometry.row_geometry, grid_items,
+ container_style.GetWritingMode());
+ }
// If we had an orthogonal item which may have depended on the resolved row
- // tracks, re-run computing the grid geometry.
+ // tracks, re-run the track sizing algorithm for both dimensions.
if (needs_additional_pass) {
- // Reset the column track-collection to its initial value, and re-run the
- // column sizing algorithm.
- column_track_collection = NGGridLayoutAlgorithmTrackCollection(
- column_block_track_collection,
- grid_available_size_.inline_size == kIndefiniteSize);
+ CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items,
+ &unused_needs_additional_pass);
+
grid_geometry.column_geometry =
InitializeTrackSizes(&column_track_collection);
-
grid_geometry.column_geometry = ComputeUsedTrackSizes(
SizingConstraint::kLayout, grid_geometry, &column_track_collection,
&grid_items, &unused_needs_additional_pass);
- DCHECK(!unused_needs_additional_pass);
- CalculateAlignmentBaselines(grid_items, kForRows, &grid_geometry);
- // Now reset the row track-collection to its initial value, and re-run the
- // row sizing algorithm.
- row_track_collection = NGGridLayoutAlgorithmTrackCollection(
- row_block_track_collection,
- grid_available_size_.block_size == kIndefiniteSize);
- grid_geometry.row_geometry = InitializeTrackSizes(&row_track_collection);
+ CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items,
+ &unused_needs_additional_pass);
+ grid_geometry.row_geometry = InitializeTrackSizes(&row_track_collection);
grid_geometry.row_geometry = ComputeUsedTrackSizes(
SizingConstraint::kLayout, grid_geometry, &row_track_collection,
&grid_items, &unused_needs_additional_pass);
- DCHECK(!unused_needs_additional_pass);
- CalculateAlignmentBaselines(grid_items, kForColumns, &grid_geometry);
}
+
+ CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items,
+ &unused_needs_additional_pass);
+ CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items,
+ &unused_needs_additional_pass);
+ DCHECK(!unused_needs_additional_pass);
};
ComputeGrid();
- // Intrinsic block size is based on the final row offset. Because gutters
- // are included in row offsets, subtract out the final gutter (if present).
- LayoutUnit intrinsic_block_size =
- grid_geometry.row_geometry.sets.back().offset -
- grid_geometry.row_geometry.FinalGutterSize() +
- BorderScrollbarPadding().block_end;
+ LayoutUnit intrinsic_block_size;
+ if (contain_intrinsic_block_size_) {
+ intrinsic_block_size = *contain_intrinsic_block_size_;
+ } else {
+ // Intrinsic block size is based on the final row offset. Because gutters
+ // are included in row offsets, subtract out the final gutter (if present).
+ intrinsic_block_size = grid_geometry.row_geometry.sets.back().offset -
+ grid_geometry.row_geometry.FinalGutterSize() +
+ BorderScrollbarPadding().block_end;
+
+ // TODO(layout-dev): This isn't great but matches legacy. Ideally this
+ // would only apply when we have only flexible track(s).
+ if (grid_items.IsEmpty() && Node().HasLineIfEmpty()) {
+ intrinsic_block_size =
+ std::max(intrinsic_block_size, BorderScrollbarPadding().BlockSum() +
+ Node().EmptyLineBlockSize());
+ }
- // TODO(layout-dev): ClampIntrinsicBlockSize might not be correct for grid.
- // Specifically do we need to run the sizing algorithm assuming no children
- // for size containment.
- intrinsic_block_size =
- ClampIntrinsicBlockSize(ConstraintSpace(), Node(),
- BorderScrollbarPadding(), intrinsic_block_size);
+ intrinsic_block_size =
+ ClampIntrinsicBlockSize(ConstraintSpace(), Node(),
+ BorderScrollbarPadding(), intrinsic_block_size);
+ }
const LayoutUnit block_size = ComputeBlockSizeForFragment(
ConstraintSpace(), container_style, BorderPadding(), intrinsic_block_size,
border_box_size_.inline_size);
- const bool depends_on_block_constraints =
- (Style().RowGap() && Style().RowGap()->IsPercentOrCalc()) ||
- row_track_collection.DependsOnAvailableSize();
-
- // If we have any rows, gaps which will resolve differently if we have a
- // definite |grid_available_size_| re-compute the grid using the |block_size|
- // calculated above.
- if (grid_available_size_.block_size == kIndefiniteSize &&
- depends_on_block_constraints) {
+ if (grid_available_size_.block_size == kIndefiniteSize) {
const LayoutUnit resolved_available_block_size =
(block_size - BorderScrollbarPadding().BlockSum())
.ClampNegativeToZero();
@@ -207,14 +271,43 @@ scoped_refptr<const NGLayoutResult> NGGridLayoutAlgorithm::Layout() {
grid_available_size_.block_size = grid_min_available_size_.block_size =
grid_max_available_size_.block_size = resolved_available_block_size;
- ComputeGrid();
+ // Re-compute the row geometry now that we have the resolved available
+ // block-size. "align-content: space-evenly" etc, require the resolved size.
+ if (container_style.AlignContent() !=
+ ComputedStyleInitialValues::InitialAlignContent()) {
+ grid_geometry.row_geometry = ComputeSetGeometry(row_track_collection);
+ }
+
+ // If we have any rows, gaps which will resolve differently if we have a
+ // definite |grid_available_size_| re-compute the grid using the
+ // |block_size| calculated above.
+ bool should_recompute_grid =
+ (container_style.RowGap() &&
+ container_style.RowGap()->IsPercentOrCalc()) ||
+ row_track_collection.DependsOnAvailableSize();
+
+ // If we are a flex-item, we may have our initial block-size forced to be
+ // indefinite, however grid layout always re-computes the grid using the
+ // final "used" block-size.
+ // We can detect this case by checking if computing our block-size (with an
+ // indefinite intrinsic size) is definite.
+ //
+ // TODO(layout-dev): A small optimization here would be to do this only if
+ // we have 'auto' tracks which fill the remaining available space.
+ if (ConstraintSpace().IsInitialBlockSizeIndefinite()) {
+ should_recompute_grid |=
+ ComputeBlockSizeForFragment(
+ ConstraintSpace(), container_style, BorderPadding(),
+ /* intrinsic_block_size */ kIndefiniteSize,
+ border_box_size_.inline_size) != kIndefiniteSize;
+ }
+
+ if (should_recompute_grid)
+ ComputeGrid();
}
PlaceGridItems(grid_items, grid_geometry, block_size);
- PlaceOutOfFlowDescendants(column_track_collection, row_track_collection,
- grid_geometry, grid_placement, block_size);
-
// Cache range placement data for out of flow items.
for (auto& out_of_flow_item : out_of_flow_items) {
out_of_flow_item.ComputeOutOfFlowItemPlacement(column_track_collection,
@@ -273,32 +366,22 @@ scoped_refptr<const NGLayoutResult> NGGridLayoutAlgorithm::Layout() {
return container_builder_.ToBoxFragment();
}
-namespace {
-
-LayoutUnit ComputeTotalTrackSize(
- const NGGridLayoutAlgorithmTrackCollection& track_collection,
- const LayoutUnit grid_gap) {
- LayoutUnit total_track_size;
- for (auto set_iterator = track_collection.GetSetIterator();
- !set_iterator.IsAtEnd(); set_iterator.MoveToNextSet()) {
- const auto& set = set_iterator.CurrentSet();
- total_track_size += set.BaseSize() + set.TrackCount() * grid_gap;
- }
- // Clamp to zero to avoid a negative |grid_gap| when there are no tracks.
- total_track_size -= grid_gap;
- return total_track_size.ClampNegativeToZero();
-}
-
-} // namespace
-
MinMaxSizesResult NGGridLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesFloatInput&) const {
- // TODO(janewman): Handle the cases typically done via:
- // CalculateMinMaxSizesIgnoringChildren.
+ const LayoutUnit override_intrinsic_inline_size =
+ Node().OverrideIntrinsicContentInlineSize();
+ if (override_intrinsic_inline_size != kIndefiniteSize) {
+ MinMaxSizes sizes;
+ sizes =
+ BorderScrollbarPadding().InlineSum() + override_intrinsic_inline_size;
+ return MinMaxSizesResult{sizes,
+ /* depends_on_block_constraints */ false};
+ }
- // Measure items.
+ // Measure items. If we have inline size containment, ignore all children.
GridItems grid_items;
- ConstructAndAppendGridItems(&grid_items);
+ if (!Node().ShouldApplyInlineSizeContainment())
+ ConstructAndAppendGridItems(&grid_items);
const auto& container_style = Style();
NGGridPlacement grid_placement(container_style,
@@ -312,52 +395,80 @@ MinMaxSizesResult NGGridLayoutAlgorithm::ComputeMinMaxSizes(
&row_block_track_collection, &grid_placement);
// Build algorithm track collections from the block track collections.
- NGGridLayoutAlgorithmTrackCollection column_track_collection_for_min_size(
+ NGGridLayoutAlgorithmTrackCollection column_track_collection(
column_block_track_collection,
grid_available_size_.inline_size == kIndefiniteSize);
NGGridLayoutAlgorithmTrackCollection row_track_collection(
row_block_track_collection,
grid_available_size_.block_size == kIndefiniteSize);
- // Cache track span properties for grid items.
- CacheGridItemsTrackSpanProperties(column_track_collection_for_min_size,
- &grid_items);
-
- // Cache set indices and alignment fallbacks for grid items.
+ // Cache set indices for grid items.
for (auto& grid_item : grid_items) {
- grid_item.ComputeSetIndices(column_track_collection_for_min_size);
+ grid_item.ComputeSetIndices(column_track_collection);
grid_item.ComputeSetIndices(row_track_collection);
- grid_item.SetAlignmentFallback(column_track_collection_for_min_size,
- container_style);
- grid_item.SetAlignmentFallback(row_track_collection, container_style);
}
- GridGeometry grid_geometry(
- InitializeTrackSizes(&column_track_collection_for_min_size),
- InitializeTrackSizes(&row_track_collection));
-
- // Store column baselines.
- CalculateAlignmentBaselines(grid_items, kForColumns, &grid_geometry);
-
- // Before the track sizing algorithm, create a copy of the column collection;
- // one will be used to compute the min size and the other for the max size.
- NGGridLayoutAlgorithmTrackCollection column_track_collection_for_max_size =
- column_track_collection_for_min_size;
-
- // Resolve inline size under a 'min-content' constraint.
- bool unused = false;
- ComputeUsedTrackSizes(SizingConstraint::kMinContent, grid_geometry,
- &column_track_collection_for_min_size, &grid_items,
- &unused);
- // Resolve inline size under a 'max-content' constraint.
- ComputeUsedTrackSizes(SizingConstraint::kMaxContent, grid_geometry,
- &column_track_collection_for_max_size, &grid_items,
- &unused);
-
- const LayoutUnit grid_gap = GridGap(kForColumns);
- MinMaxSizes sizes{
- ComputeTotalTrackSize(column_track_collection_for_min_size, grid_gap),
- ComputeTotalTrackSize(column_track_collection_for_max_size, grid_gap)};
+ // Cache track span properties for grid items.
+ CacheGridItemsTrackSpanProperties(column_track_collection, &grid_items);
+ CacheGridItemsTrackSpanProperties(row_track_collection, &grid_items);
+
+ auto ComputeTotalColumnSize =
+ [&](SizingConstraint sizing_constraint) -> LayoutUnit {
+ GridGeometry grid_geometry(InitializeTrackSizes(&column_track_collection),
+ InitializeTrackSizes(&row_track_collection));
+
+ bool needs_additional_pass = false;
+ CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items,
+ &needs_additional_pass);
+
+ bool has_block_size_dependent_item = false;
+ grid_geometry.column_geometry = ComputeUsedTrackSizes(
+ sizing_constraint, grid_geometry, &column_track_collection, &grid_items,
+ &needs_additional_pass, &has_block_size_dependent_item);
+
+ CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items,
+ &needs_additional_pass);
+
+ if (needs_additional_pass || has_block_size_dependent_item) {
+ absl::optional<SetGeometry> initial_row_geometry;
+ if (!needs_additional_pass && has_block_size_dependent_item)
+ initial_row_geometry = grid_geometry.row_geometry;
+
+ // https://drafts.csswg.org/css-sizing-3/#auto-box-sizes: both min-content
+ // and max-content block sizes are the size of the content after layout.
+ bool unused_needs_additional_pass = false;
+ grid_geometry.row_geometry = ComputeUsedTrackSizes(
+ SizingConstraint::kLayout, grid_geometry, &row_track_collection,
+ &grid_items, &unused_needs_additional_pass);
+
+ if (initial_row_geometry) {
+ DCHECK(!needs_additional_pass && has_block_size_dependent_item);
+ needs_additional_pass = MayChangeOrthogonalItemContributions(
+ *initial_row_geometry, grid_geometry.row_geometry, grid_items,
+ container_style.GetWritingMode());
+ }
+
+ if (needs_additional_pass) {
+ CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items,
+ &unused_needs_additional_pass);
+
+ grid_geometry.column_geometry =
+ InitializeTrackSizes(&column_track_collection);
+ grid_geometry.column_geometry = ComputeUsedTrackSizes(
+ sizing_constraint, grid_geometry, &column_track_collection,
+ &grid_items, &unused_needs_additional_pass);
+ }
+ DCHECK(!unused_needs_additional_pass);
+ }
+
+ DCHECK_GT(grid_geometry.column_geometry.sets.size(), 0u);
+ return grid_geometry.column_geometry.sets.back().offset -
+ grid_geometry.column_geometry.sets[0].offset -
+ grid_geometry.column_geometry.gutter_size;
+ };
+
+ MinMaxSizes sizes{ComputeTotalColumnSize(SizingConstraint::kMinContent),
+ ComputeTotalColumnSize(SizingConstraint::kMaxContent)};
// TODO(janewman): Confirm that |input.percentage_resolution_block_size|
// isn't used within grid layout.
@@ -367,19 +478,21 @@ MinMaxSizesResult NGGridLayoutAlgorithm::ComputeMinMaxSizes(
NGGridLayoutAlgorithm::AutoPlacementType
NGGridLayoutAlgorithm::GridItemData::AutoPlacement(
- GridTrackSizingDirection flow_direction) const {
- bool is_major_indefinite = Span(flow_direction).IsIndefinite();
- bool is_minor_indefinite =
- Span((flow_direction == kForColumns) ? kForRows : kForColumns)
- .IsIndefinite();
+ const GridTrackSizingDirection major_direction) const {
+ const GridTrackSizingDirection minor_direction =
+ (major_direction == kForColumns) ? kForRows : kForColumns;
+ DCHECK(!Span(major_direction).IsUntranslatedDefinite() &&
+ !Span(minor_direction).IsUntranslatedDefinite());
+
+ const bool is_major_indefinite = Span(major_direction).IsIndefinite();
+ const bool is_minor_indefinite = Span(minor_direction).IsIndefinite();
if (is_minor_indefinite && is_major_indefinite)
return AutoPlacementType::kBoth;
- else if (is_minor_indefinite)
+ if (is_minor_indefinite)
return AutoPlacementType::kMinor;
- else if (is_major_indefinite)
+ if (is_major_indefinite)
return AutoPlacementType::kMajor;
-
return AutoPlacementType::kNotNeeded;
}
@@ -459,70 +572,81 @@ bool NGGridLayoutAlgorithm::GridItemData::IsSpanningAutoMinimumTrack(
bool NGGridLayoutAlgorithm::GridItemData::IsBaselineAlignedForDirection(
GridTrackSizingDirection track_direction) const {
return (track_direction == kForColumns)
+ ? InlineAxisAlignment() == AxisEdge::kBaseline
+ : BlockAxisAlignment() == AxisEdge::kBaseline;
+}
+
+bool NGGridLayoutAlgorithm::GridItemData::IsBaselineSpecifiedForDirection(
+ GridTrackSizingDirection track_direction) const {
+ return (track_direction == kForColumns)
? inline_axis_alignment == AxisEdge::kBaseline
: block_axis_alignment == AxisEdge::kBaseline;
}
void NGGridLayoutAlgorithm::GridItemData::SetAlignmentFallback(
- const NGGridLayoutAlgorithmTrackCollection& track_collection,
- const ComputedStyle& container_style) {
- if (inline_axis_alignment == AxisEdge::kBaseline ||
- block_axis_alignment == AxisEdge::kBaseline) {
- auto CanParticipateInBaselineAlignment =
- [&](const ComputedStyle& container_style,
- const NGGridLayoutAlgorithmTrackCollection& track_collection)
- -> bool {
- const auto track_direction = track_collection.Direction();
-
- if (!IsBaselineAlignedForDirection(track_direction))
- return false;
-
- // "If baseline alignment is specified on a grid item whose size in that
- // axis depends on the size of an intrinsically-sized track (whose size is
- // therefore dependent on both the item’s size and baseline alignment,
- // creating a cyclic dependency), that item does not participate in
- // baseline alignment, and instead uses its fallback alignment as if that
- // were originally specified. For this purpose, <flex> track sizes count
- // as “intrinsically-sized” when the grid container has an indefinite size
- // in the relevant axis."
- // https://drafts.csswg.org/css-grid-2/#row-align
- // TODO(kschmi) - this is not complete, as flex items should also count if
- // the container has a definite size. These will require a second pass for
- // the remaining scenarios in grid-self-baseline-not-applied-if-sizing-
- // cyclic-dependency tests.
- if (!IsSpanningFlexibleTrack(track_direction) &&
- !IsSpanningIntrinsicTrack(track_direction)) {
- return true;
- }
+ const GridTrackSizingDirection track_direction,
+ const ComputedStyle& container_style,
+ const bool has_synthesized_baseline) {
+ // Alignment fallback is only possible when baseline alignment is specified.
+ if (!IsBaselineSpecifiedForDirection(track_direction))
+ return;
+ auto CanParticipateInBaselineAlignment =
+ [&](const ComputedStyle& container_style,
+ const GridTrackSizingDirection track_direction) -> bool {
+ // "If baseline alignment is specified on a grid item whose size in that
+ // axis depends on the size of an intrinsically-sized track (whose size is
+ // therefore dependent on both the item’s size and baseline alignment,
+ // creating a cyclic dependency), that item does not participate in
+ // baseline alignment, and instead uses its fallback alignment as if that
+ // were originally specified. For this purpose, <flex> track sizes count
+ // as “intrinsically-sized” when the grid container has an indefinite size
+ // in the relevant axis."
+ // https://drafts.csswg.org/css-grid-2/#row-align
+ if (has_synthesized_baseline &&
+ (IsSpanningIntrinsicTrack(track_direction) ||
+ IsSpanningFlexibleTrack(track_direction))) {
+ // Parallel grid items with a synthesized baseline support baseline
+ // alignment only of the height doesn't depend on the track size.
+ const auto& item_style = node.Style();
const bool is_parallel_to_baseline_axis =
(track_direction == kForRows) ==
IsParallelWritingMode(container_style.GetWritingMode(),
- node.Style().GetWritingMode());
-
- // TODO(kschmi) - should this also include 'fit-content'? And should
- // 'auto' sizing only apply here if the track size is indefinite?
+ item_style.GetWritingMode());
if (is_parallel_to_baseline_axis) {
- return !node.Style().LogicalHeight().IsPercentOrCalc() &&
- !node.Style().LogicalMinHeight().IsPercentOrCalc() &&
- !node.Style().LogicalMaxHeight().IsPercentOrCalc();
+ const bool logical_height_depends_on_container =
+ item_style.LogicalHeight().IsPercentOrCalc() ||
+ item_style.LogicalMinHeight().IsPercentOrCalc() ||
+ item_style.LogicalMaxHeight().IsPercentOrCalc() ||
+ item_style.LogicalHeight().IsAuto();
+ return !logical_height_depends_on_container;
} else {
- // TODO(kschmi) - the 'IsAuto' condition is not consistent between these
- // conditions, but matches legacy and passes the tests.
- return !node.Style().LogicalWidth().IsPercentOrCalc() &&
- !node.Style().LogicalMinWidth().IsPercentOrCalc() &&
- !node.Style().LogicalMaxWidth().IsPercentOrCalc() &&
- !node.Style().LogicalWidth().IsAuto();
+ // Orthogonal items with synthesized baselines never support baseline
+ // alignment when they span intrinsic or flex tracks.
+ return false;
}
- };
+ }
+ return true;
+ };
- // Revert to start edges if an item requests baseline alignment but does not
- // meet requirements for baseline alignment.
- if (!CanParticipateInBaselineAlignment(container_style, track_collection)) {
- if (track_collection.IsForColumns())
- inline_axis_alignment = AxisEdge::kStart;
- else
- block_axis_alignment = AxisEdge::kStart;
+ // Set fallback alignment to start edges if an item requests baseline
+ // alignment but does not meet requirements for it.
+ if (!CanParticipateInBaselineAlignment(container_style, track_direction)) {
+ if (track_direction == kForColumns &&
+ inline_axis_alignment == AxisEdge::kBaseline) {
+ inline_axis_alignment_fallback = AxisEdge::kStart;
+ } else if (track_direction == kForRows &&
+ block_axis_alignment == AxisEdge::kBaseline) {
+ block_axis_alignment_fallback = AxisEdge::kStart;
+ }
+ } else {
+ // Reset the alignment fallback if eligibility has changed.
+ if (track_direction == kForColumns &&
+ inline_axis_alignment_fallback.has_value()) {
+ inline_axis_alignment_fallback.reset();
+ } else if (track_direction == kForRows &&
+ block_axis_alignment_fallback.has_value()) {
+ block_axis_alignment_fallback.reset();
}
}
}
@@ -531,44 +655,56 @@ void NGGridLayoutAlgorithm::GridItemData::ComputeSetIndices(
const NGGridLayoutAlgorithmTrackCollection& track_collection) {
DCHECK_EQ(item_type, ItemType::kInGridFlow);
+ GridItemIndices range_indices = RangeIndices(track_collection.Direction());
+#if DCHECK_IS_ON()
wtf_size_t start_line = StartLine(track_collection.Direction());
wtf_size_t end_line = EndLine(track_collection.Direction());
DCHECK_LE(end_line, track_collection.EndLineOfImplicitGrid());
DCHECK_LT(start_line, end_line);
+ // Check the range index caching was correct by running a binary search.
+ DCHECK_EQ(track_collection.RangeIndexFromTrackNumber(start_line),
+ range_indices.begin);
+ DCHECK_EQ(track_collection.RangeIndexFromTrackNumber(end_line - 1),
+ range_indices.end);
+#endif
+
auto& set_indices =
track_collection.IsForColumns() ? column_set_indices : row_set_indices;
- wtf_size_t first_spanned_range =
- track_collection.RangeIndexFromTrackNumber(start_line);
set_indices.begin =
- track_collection.RangeStartingSetIndex(first_spanned_range);
- wtf_size_t last_spanned_range =
- track_collection.RangeIndexFromTrackNumber(end_line - 1);
- set_indices.end = track_collection.RangeStartingSetIndex(last_spanned_range) +
- track_collection.RangeSetCount(last_spanned_range);
+ track_collection.RangeStartingSetIndex(range_indices.begin);
+ set_indices.end = track_collection.RangeStartingSetIndex(range_indices.end) +
+ track_collection.RangeSetCount(range_indices.end);
DCHECK_LE(set_indices.end, track_collection.SetCount());
DCHECK_LT(set_indices.begin, set_indices.end);
}
-const NGGridLayoutAlgorithm::GridItemSetIndices&
+const NGGridLayoutAlgorithm::GridItemIndices&
NGGridLayoutAlgorithm::GridItemData::SetIndices(
GridTrackSizingDirection track_direction) const {
return (track_direction == kForColumns) ? column_set_indices
: row_set_indices;
}
+NGGridLayoutAlgorithm::GridItemIndices&
+NGGridLayoutAlgorithm::GridItemData::RangeIndices(
+ GridTrackSizingDirection track_direction) {
+ return (track_direction == kForColumns) ? column_range_indices
+ : row_range_indices;
+}
+
void NGGridLayoutAlgorithm::GridItemData::ComputeOutOfFlowItemPlacement(
const NGGridLayoutAlgorithmTrackCollection& track_collection,
const NGGridPlacement& grid_placement) {
DCHECK_EQ(item_type, ItemType::kOutOfFlow);
auto& start_offset = track_collection.IsForColumns()
- ? column_placement.start_offset_in_range
- : row_placement.start_offset_in_range;
+ ? column_placement.offset_in_range.begin
+ : row_placement.offset_in_range.begin;
auto& end_offset = track_collection.IsForColumns()
- ? column_placement.end_offset_in_range
- : row_placement.end_offset_in_range;
+ ? column_placement.offset_in_range.end
+ : row_placement.offset_in_range.end;
if (is_grid_containing_block) {
grid_placement.ResolveOutOfFlowItemGridLines(track_collection, node.Style(),
&start_offset, &end_offset);
@@ -591,29 +727,46 @@ void NGGridLayoutAlgorithm::GridItemData::ComputeOutOfFlowItemPlacement(
// We only calculate the range placement if the line was not defined as 'auto'
// and it is within the bounds of the grid, since an out of flow item cannot
// create grid lines.
+ const wtf_size_t range_count = track_collection.RangeCount();
auto& start_range_index = track_collection.IsForColumns()
- ? column_placement.start_range_index
- : row_placement.start_range_index;
+ ? column_placement.range_index.begin
+ : row_placement.range_index.begin;
if (start_offset != kNotFound) {
- // If a start line of an out of flow item is the last line of the grid, we
- // can just subtract one unit to the range count.
- start_range_index =
- (start_offset < track_collection.EndLineOfImplicitGrid())
- ? track_collection.RangeIndexFromTrackNumber(start_offset)
- : track_collection.RangeCount() - 1;
- start_offset -= track_collection.RangeTrackNumber(start_range_index);
+ if (!range_count) {
+ // An undefined and empty grid has a single start/end grid line and no
+ // ranges. Therefore, if the start offset isn't 'auto', the only valid
+ // offset is zero.
+ DCHECK_EQ(start_offset, 0u);
+ start_range_index = 0;
+ } else {
+ // If the start line of an out of flow item is the last line of the grid,
+ // we can just subtract one unit to the range count.
+ start_range_index =
+ (start_offset < track_collection.EndLineOfImplicitGrid())
+ ? track_collection.RangeIndexFromTrackNumber(start_offset)
+ : range_count - 1;
+ start_offset -= track_collection.RangeTrackNumber(start_range_index);
+ }
}
auto& end_range_index = track_collection.IsForColumns()
- ? column_placement.end_range_index
- : row_placement.end_range_index;
+ ? column_placement.range_index.end
+ : row_placement.range_index.end;
if (end_offset != kNotFound) {
- // If an end line of an out of flow item is the first line of the grid, then
- // |last_spanned_range| is set to zero.
- end_range_index =
- end_offset ? track_collection.RangeIndexFromTrackNumber(end_offset - 1)
- : 0;
- end_offset -= track_collection.RangeTrackNumber(end_range_index);
+ if (!range_count) {
+ // Similarly to the start offset, if we have an undefined, empty grid and
+ // the end offset isn't 'auto', the only valid offset is zero.
+ DCHECK_EQ(end_offset, 0u);
+ end_range_index = 0;
+ } else {
+ // If the end line of an out of flow item is the first line of the grid,
+ // then |last_spanned_range| is set to zero.
+ end_range_index =
+ end_offset
+ ? track_collection.RangeIndexFromTrackNumber(end_offset - 1)
+ : 0;
+ end_offset -= track_collection.RangeTrackNumber(end_range_index);
+ }
}
}
@@ -633,10 +786,6 @@ void NGGridLayoutAlgorithm::GridItems::Append(
item_data.emplace_back(new_item_data);
}
-bool NGGridLayoutAlgorithm::GridItems::IsEmpty() const {
- return item_data.IsEmpty();
-}
-
const NGGridLayoutAlgorithm::SetGeometry&
NGGridLayoutAlgorithm::GridGeometry::Geometry(
GridTrackSizingDirection track_direction) const {
@@ -669,8 +818,9 @@ LayoutUnit GetLogicalBaseline(const NGBoxFragment& fragment,
case WritingMode::kHorizontalTb:
switch (child_writing_mode) {
case WritingMode::kHorizontalTb:
- return is_for_columns ? LayoutUnit()
- : fragment.BaselineOrSynthesize();
+ return is_for_columns
+ ? LayoutUnit()
+ : fragment.Baseline().value_or(fragment.BlockSize());
case WritingMode::kVerticalLr:
return is_for_columns ? fragment.Baseline().value_or(LayoutUnit())
: fragment.InlineSize();
@@ -685,8 +835,9 @@ LayoutUnit GetLogicalBaseline(const NGBoxFragment& fragment,
case WritingMode::kVerticalLr:
switch (child_writing_mode) {
case WritingMode::kHorizontalTb:
- return is_for_columns ? fragment.BaselineOrSynthesize()
- : LayoutUnit();
+ return is_for_columns
+ ? fragment.Baseline().value_or(fragment.BlockSize())
+ : LayoutUnit();
case WritingMode::kVerticalLr:
return is_for_columns ? fragment.InlineSize()
: fragment.Baseline().value_or(LayoutUnit());
@@ -701,15 +852,18 @@ LayoutUnit GetLogicalBaseline(const NGBoxFragment& fragment,
case WritingMode::kVerticalRl:
switch (child_writing_mode) {
case WritingMode::kHorizontalTb:
- return is_for_columns ? fragment.BaselineOrSynthesize()
- : fragment.InlineSize();
+ return is_for_columns
+ ? fragment.Baseline().value_or(fragment.BlockSize())
+ : fragment.InlineSize();
case WritingMode::kVerticalLr:
return is_for_columns
? fragment.InlineSize()
- : (fragment.BlockSize() - fragment.BaselineOrSynthesize());
+ : (fragment.BlockSize() -
+ fragment.Baseline().value_or(fragment.BlockSize()));
case WritingMode::kVerticalRl:
- return is_for_columns ? fragment.InlineSize()
- : fragment.BaselineOrSynthesize();
+ return is_for_columns
+ ? fragment.InlineSize()
+ : fragment.Baseline().value_or(fragment.BlockSize());
default:
NOTREACHED();
return LayoutUnit();
@@ -720,6 +874,58 @@ LayoutUnit GetLogicalBaseline(const NGBoxFragment& fragment,
}
}
+bool HasSynthesizedBaseline(const GridTrackSizingDirection track_direction,
+ const NGBoxFragment& fragment,
+ const WritingMode writing_mode) {
+ const auto child_writing_mode =
+ fragment.GetWritingDirection().GetWritingMode();
+ const bool is_for_columns = (track_direction == kForColumns);
+
+ // TODO(kschmi): Reconcile this with layout experts to see if this makes
+ // sense. Some of the entries here are non-intuitive.
+ switch (writing_mode) {
+ case WritingMode::kHorizontalTb:
+ switch (child_writing_mode) {
+ case WritingMode::kHorizontalTb:
+ return is_for_columns ? true : !fragment.Baseline().has_value();
+ case WritingMode::kVerticalLr:
+ return is_for_columns ? !fragment.Baseline().has_value() : true;
+ case WritingMode::kVerticalRl:
+ return is_for_columns ? (!fragment.Baseline().has_value()) : true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+ case WritingMode::kVerticalLr:
+ switch (child_writing_mode) {
+ case WritingMode::kHorizontalTb:
+ return is_for_columns ? !fragment.Baseline().has_value() : true;
+ case WritingMode::kVerticalLr:
+ return is_for_columns ? true : !fragment.Baseline().has_value();
+ case WritingMode::kVerticalRl:
+ return is_for_columns ? true : !fragment.Baseline().has_value();
+ default:
+ NOTREACHED();
+ return false;
+ }
+ case WritingMode::kVerticalRl:
+ switch (child_writing_mode) {
+ case WritingMode::kHorizontalTb:
+ return is_for_columns ? !fragment.Baseline().has_value() : true;
+ case WritingMode::kVerticalLr:
+ return is_for_columns ? true : !fragment.Baseline().has_value();
+ case WritingMode::kVerticalRl:
+ return is_for_columns ? true : !fragment.Baseline().has_value();
+ default:
+ NOTREACHED();
+ return false;
+ }
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
} // namespace
void NGGridLayoutAlgorithm::GridGeometry::UpdateBaseline(
@@ -743,6 +949,7 @@ void NGGridLayoutAlgorithm::GridGeometry::UpdateBaseline(
? &major_block_baselines[set_index]
: &minor_block_baselines[set_index];
}
+
*track_baseline = std::max(*track_baseline, candidate_baseline);
}
@@ -767,12 +974,57 @@ LayoutUnit NGGridLayoutAlgorithm::GridGeometry::Baseline(
}
}
+LayoutUnit NGGridLayoutAlgorithm::ComputeIntrinsicBlockSizeIgnoringChildren()
+ const {
+ DCHECK(Node().ShouldApplyBlockSizeContainment());
+
+ // First check 'contain-intrinsic-size'.
+ const LayoutUnit override_intrinsic_block_size =
+ Node().OverrideIntrinsicContentBlockSize();
+ if (override_intrinsic_block_size != kIndefiniteSize)
+ return BorderScrollbarPadding().BlockSum() + override_intrinsic_block_size;
+
+ // Don't append any children for this calculation.
+ GridItems grid_items;
+ NGGridPlacement grid_placement(Style(),
+ ComputeAutomaticRepetitions(kForColumns),
+ ComputeAutomaticRepetitions(kForRows));
+
+ // Build block track collections.
+ NGGridBlockTrackCollection column_block_track_collection(kForColumns);
+ NGGridBlockTrackCollection row_block_track_collection(kForRows);
+ BuildBlockTrackCollections(&grid_items, &column_block_track_collection,
+ &row_block_track_collection, &grid_placement);
+
+ // Build algorithm row track collection from the block track collection.
+ NGGridLayoutAlgorithmTrackCollection row_track_collection(
+ row_block_track_collection,
+ grid_available_size_.block_size == kIndefiniteSize);
+
+ GridGeometry grid_geometry(SetGeometry(),
+ InitializeTrackSizes(&row_track_collection));
+
+ // Resolve the rows.
+ bool unused_needs_additional_pass = false;
+ grid_geometry.row_geometry = ComputeUsedTrackSizes(
+ SizingConstraint::kLayout, grid_geometry, &row_track_collection,
+ &grid_items, &unused_needs_additional_pass);
+
+ return grid_geometry.row_geometry.sets.back().offset -
+ grid_geometry.row_geometry.FinalGutterSize() +
+ BorderScrollbarPadding().block_end;
+}
+
LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
+ SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
const GridItemData& grid_item,
GridTrackSizingDirection track_direction,
GridItemContributionType contribution_type,
- bool* needs_additional_pass) const {
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const {
+ DCHECK(needs_additional_pass);
+
const NGBlockNode& node = grid_item.node;
const ComputedStyle& item_style = node.Style();
@@ -786,11 +1038,27 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
// track-sizing algorithm.
const auto space = CreateConstraintSpaceForMeasure(grid_geometry, grid_item,
track_direction);
- const auto margins =
- ComputeMarginsFor(space, node.Style(), ConstraintSpace());
+ const auto margins = ComputeMarginsFor(space, item_style, ConstraintSpace());
auto MinMaxContentSizes = [&]() -> MinMaxSizes {
- return ComputeMinAndMaxContentContributionForSelf(node, space).sizes;
+ const auto result = ComputeMinAndMaxContentContributionForSelf(node, space);
+
+ // The min/max contribution may depend on the block-size of the grid-area:
+ // <div style="display: inline-grid; grid-template-columns: auto auto;">
+ // <div style="height: 100%">
+ // <img style="height: 50%;" />
+ // </div>
+ // <div>
+ // <div style="height: 100px;"></div>
+ // </div>
+ // </div>
+ // Mark ourselves as requiring an additional pass to re-resolve the column
+ // tracks for this case.
+ if (is_parallel && result.depends_on_block_constraints &&
+ space.AvailableSize().block_size == kIndefiniteSize) {
+ *needs_additional_pass = true;
+ }
+ return result.sizes;
};
// This function will determine the correct block-size of a grid-item.
@@ -801,9 +1069,26 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
LayoutUnit baseline_shim;
auto BlockContributionSize = [&]() -> LayoutUnit {
DCHECK(!is_parallel_with_track_direction);
- scoped_refptr<const NGLayoutResult> result;
+ if (is_for_columns && !is_parallel && has_block_size_dependent_item)
+ *has_block_size_dependent_item = true;
+
+ // Disable side effects during MinMax computation to avoid potential
+ // "MinMax after layout" crashes. This is not necessary during layout, and
+ // will have a negative impact on performance if used there.
+ absl::optional<NGDisableSideEffectsScope> disable_side_effects;
+ if ((sizing_constraint != SizingConstraint::kLayout) &&
+ !node.GetLayoutBox()->NeedsLayout()) {
+ disable_side_effects.emplace();
+ }
+
+ scoped_refptr<const NGLayoutResult> result;
if (!is_parallel && space.AvailableSize().inline_size == kIndefiniteSize) {
+ // The only case where we will have an indefinite block size is for the
+ // first column resolution step; after that we will always have the used
+ // sizes of the previous step for the orthogonal direction.
+ DCHECK(is_for_columns);
+
// If we are orthogonal grid-item, resolving against an indefinite size,
// set our inline-size to our max content-contribution size.
const auto fallback_space = CreateConstraintSpaceForMeasure(
@@ -811,8 +1096,8 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
/* opt_fixed_block_size */ MinMaxContentSizes().max_size);
result = node.Layout(fallback_space);
- // TODO(ikilpatrick): This check is potentially too broad. If we have a
- // fixed inline-size, with no %-padding we don't need the additional pass.
+ // TODO(ikilpatrick): This check is potentially too broad, i.e. a fixed
+ // inline size with no %-padding doesn't need the additional pass.
*needs_additional_pass = true;
} else {
result = node.Layout(space);
@@ -823,25 +1108,29 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
if (grid_item.IsBaselineAlignedForDirection(track_direction)) {
+ LayoutUnit track_baseline =
+ grid_geometry.Baseline(grid_item, track_direction);
+
// The item's baseline alignment impacts the item's contribution as the
// difference between the track's baseline and the item's baseline.
- baseline_shim =
- grid_geometry.Baseline(grid_item, track_direction) -
- GetLogicalBaseline(
- fragment, track_direction,
- ConstraintSpace().GetWritingDirection().GetWritingMode());
-
- // Subtract out the start margin so it doesn't get added a second time at
- // the end of |NGGridLayoutAlgorithm::ContributionSizeForGridItem|.
- baseline_shim -=
- is_for_columns ? margins.inline_start : margins.block_start;
+ if (track_baseline != LayoutUnit::Min()) {
+ baseline_shim =
+ grid_geometry.Baseline(grid_item, track_direction) -
+ GetLogicalBaseline(
+ fragment, track_direction,
+ ConstraintSpace().GetWritingDirection().GetWritingMode());
+
+ // Subtract out the start margin so it doesn't get added a second time
+ // at the end of |NGGridLayoutAlgorithm::ContributionSizeForGridItem|.
+ baseline_shim -=
+ is_for_columns ? margins.inline_start : margins.block_start;
+ }
}
return fragment.BlockSize() + baseline_shim;
};
- const LayoutUnit clamped_margin_sum =
- (is_for_columns ? margins.InlineSum() : margins.BlockSum())
- .ClampNegativeToZero();
+ const LayoutUnit margin_sum =
+ is_for_columns ? margins.InlineSum() : margins.BlockSum();
LayoutUnit contribution;
switch (contribution_type) {
@@ -924,7 +1213,7 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
: grid_geometry.row_geometry;
const auto& set_indices = grid_item.SetIndices(track_direction);
const wtf_size_t last_indefinite_index =
- set_geometry.sets[set_indices.end].last_indefinite_index;
+ set_geometry.last_indefinite_indices[set_indices.end];
if (last_indefinite_index == kNotFound ||
last_indefinite_index < set_indices.begin) {
@@ -947,8 +1236,8 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
// computed margins, border, and padding in the given dimension,
// flooring at zero so that the inner size is not negative.
spanned_tracks_definite_max_size =
- (spanned_tracks_definite_max_size - baseline_shim -
- clamped_margin_sum - border_padding_sum)
+ (spanned_tracks_definite_max_size - baseline_shim - margin_sum -
+ border_padding_sum)
.ClampNegativeToZero();
// Add the baseline shim, border, and padding (margins will be added
@@ -968,11 +1257,9 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
// the special min-size treatment above. (They will all end up being
// the specified size).
if (is_parallel_with_track_direction) {
- // TODO(ikilpatrick): This is incorrect for replaced elements.
- const NGBoxStrut border_padding =
- ComputeBorders(space, node) + ComputePadding(space, item_style);
- contribution =
- ComputeInlineSizeForFragment(space, node, border_padding);
+ contribution = main_length.IsMaxContent()
+ ? MinMaxContentSizes().max_size
+ : MinMaxContentSizes().min_size;
} else {
contribution = BlockContributionSize();
}
@@ -982,6 +1269,7 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
case Length::kDeviceWidth:
case Length::kDeviceHeight:
case Length::kExtendToZoom:
+ case Length::kContent:
case Length::kNone:
NOTREACHED();
break;
@@ -1000,24 +1288,45 @@ LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem(
break;
}
- DCHECK_GE(contribution, 0);
- return contribution + clamped_margin_sum;
+ return (contribution + margin_sum).ClampNegativeToZero();
}
void NGGridLayoutAlgorithm::ConstructAndAppendGridItems(
GridItems* grid_items,
- Vector<GridItemData>* out_of_flow_items) const {
+ GridItemStorageVector* out_of_flow_items) const {
DCHECK(grid_items);
- NGGridChildIterator iterator(Node());
- for (NGBlockNode child = iterator.NextChild(); child;
- child = iterator.NextChild()) {
- GridItemData grid_item(MeasureGridItem(child));
- // If |out_of_flow_items| is provided, store out-of-flow items separately,
- // as they do not contribute to track sizing or auto-placement.
- if (grid_item.item_type == ItemType::kInGridFlow)
+
+ const auto& container_style = Style();
+ const auto container_writing_mode = ConstraintSpace().GetWritingMode();
+ const int initial_order = ComputedStyleInitialValues::InitialOrder();
+ bool should_sort_grid_items_by_order_property = false;
+
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ GridItemData grid_item(MeasureGridItem(
+ To<NGBlockNode>(child), container_style, container_writing_mode));
+
+ // Order all of our in-flow children by their order property. If
+ // |out_of_flow_items| is provided, store out-of-flow items separately, as
+ // they do not contribute to track sizing or auto-placement.
+ if (grid_item.item_type == ItemType::kInGridFlow) {
+ should_sort_grid_items_by_order_property |=
+ child.Style().Order() != initial_order;
grid_items->Append(grid_item);
- else if (out_of_flow_items)
+ } else if (out_of_flow_items) {
out_of_flow_items->emplace_back(grid_item);
+ }
+ }
+
+ // We only need to sort this when we encounter a non-initial order property.
+ auto CompareItemsByOrderProperty = [](const GridItemData& a,
+ const GridItemData& b) {
+ return a.node.Style().Order() < b.node.Style().Order();
+ };
+
+ if (should_sort_grid_items_by_order_property) {
+ std::stable_sort(grid_items->item_data.begin(), grid_items->item_data.end(),
+ CompareItemsByOrderProperty);
}
}
@@ -1138,36 +1447,46 @@ namespace {
using AxisEdge = NGGridLayoutAlgorithm::AxisEdge;
-// Given an |item_position| determines the correct |AxisEdge| alignment.
-// Additionally will determine if the grid-item should be stretched with the
-// |is_stretched| out-parameter.
+// Given an |alignment| determines the correct |AxisEdge| alignment.
+// Additionally will determine:
+// - The behavior of 'auto' via the |auto_behavior| out-parameter.
+// - If the alignment is safe via the |is_overflow_safe| out-parameter.
AxisEdge AxisEdgeFromItemPosition(const ComputedStyle& container_style,
const ComputedStyle& style,
- const ItemPosition item_position,
- bool is_inline_axis,
- bool* is_stretched) {
- DCHECK(is_stretched);
- *is_stretched = false;
+ const StyleSelfAlignmentData& alignment,
+ const bool is_replaced,
+ const bool is_inline_axis,
+ NGAutoBehavior* auto_behavior,
+ bool* is_overflow_safe) {
+ DCHECK(auto_behavior);
+ DCHECK(is_overflow_safe);
+ *auto_behavior = NGAutoBehavior::kFitContent;
+ *is_overflow_safe = alignment.Overflow() == OverflowAlignment::kSafe;
// Auto-margins take precedence over any alignment properties.
if (style.MayHaveMargin()) {
- bool start_auto = is_inline_axis
- ? style.MarginStartUsing(container_style).IsAuto()
- : style.MarginBeforeUsing(container_style).IsAuto();
- bool end_auto = is_inline_axis
- ? style.MarginEndUsing(container_style).IsAuto()
- : style.MarginAfterUsing(container_style).IsAuto();
-
- if (start_auto && end_auto)
+ bool is_start_auto =
+ is_inline_axis ? style.MarginStartUsing(container_style).IsAuto()
+ : style.MarginBeforeUsing(container_style).IsAuto();
+ bool is_end_auto = is_inline_axis
+ ? style.MarginEndUsing(container_style).IsAuto()
+ : style.MarginAfterUsing(container_style).IsAuto();
+
+ // 'auto' margin alignment is always "safe".
+ if (is_start_auto || is_end_auto)
+ *is_overflow_safe = true;
+
+ if (is_start_auto && is_end_auto)
return AxisEdge::kCenter;
- else if (start_auto)
+ else if (is_start_auto)
return AxisEdge::kEnd;
- else if (end_auto)
+ else if (is_end_auto)
return AxisEdge::kStart;
}
const auto container_writing_direction =
container_style.GetWritingDirection();
+ const auto item_position = alignment.GetPosition();
switch (item_position) {
case ItemPosition::kSelfStart:
@@ -1203,7 +1522,7 @@ AxisEdge AxisEdgeFromItemPosition(const ComputedStyle& container_style,
case ItemPosition::kEnd:
return AxisEdge::kEnd;
case ItemPosition::kStretch:
- *is_stretched = true;
+ *auto_behavior = NGAutoBehavior::kStretchExplicit;
return AxisEdge::kStart;
case ItemPosition::kBaseline:
case ItemPosition::kLastBaseline:
@@ -1216,9 +1535,12 @@ AxisEdge AxisEdgeFromItemPosition(const ComputedStyle& container_style,
DCHECK(is_inline_axis);
return container_writing_direction.IsRtl() ? AxisEdge::kStart
: AxisEdge::kEnd;
+ case ItemPosition::kNormal:
+ *auto_behavior = is_replaced ? NGAutoBehavior::kFitContent
+ : NGAutoBehavior::kStretchImplicit;
+ return AxisEdge::kStart;
case ItemPosition::kLegacy:
case ItemPosition::kAuto:
- case ItemPosition::kNormal:
NOTREACHED();
break;
}
@@ -1270,52 +1592,40 @@ NGGridLayoutAlgorithm::BaselineType DetermineBaselineType(
} // namespace
+// static
NGGridLayoutAlgorithm::GridItemData NGGridLayoutAlgorithm::MeasureGridItem(
- const NGBlockNode node) const {
- const auto& container_style = Style();
-
+ const NGBlockNode node,
+ const ComputedStyle& container_style,
+ const WritingMode container_writing_mode) {
// Before we take track sizing into account for column width contributions,
// have all child inline and min/max sizes measured for content-based width
// resolution.
GridItemData item(node);
const ComputedStyle& item_style = node.Style();
-
- const ItemPosition normal_behaviour =
- node.IsReplaced() ? ItemPosition::kStart : ItemPosition::kStretch;
+ const bool is_replaced = node.IsReplaced();
// Determine the alignment for the grid-item ahead of time (we may need to
// know if it stretches ahead of time to correctly determine any block-axis
// contribution).
- bool is_axis_stretched;
item.inline_axis_alignment = AxisEdgeFromItemPosition(
container_style, item_style,
- item_style.ResolvedJustifySelf(normal_behaviour, &container_style)
- .GetPosition(),
- /* is_inline_axis */ true, &is_axis_stretched);
- item.is_inline_axis_stretched = is_axis_stretched;
+ item_style.ResolvedJustifySelf(ItemPosition::kNormal, &container_style),
+ is_replaced,
+ /* is_inline_axis */ true, &item.inline_auto_behavior,
+ &item.is_inline_axis_overflow_safe);
item.block_axis_alignment = AxisEdgeFromItemPosition(
container_style, item_style,
- item_style.ResolvedAlignSelf(normal_behaviour, &container_style)
- .GetPosition(),
- /* is_inline_axis */ false, &is_axis_stretched);
- item.is_block_axis_stretched = is_axis_stretched;
-
- const auto item_writing_direction =
- item.node.Style().GetWritingDirection().GetWritingMode();
- const auto container_writing_direction = ConstraintSpace().GetWritingMode();
+ item_style.ResolvedAlignSelf(ItemPosition::kNormal, &container_style),
+ is_replaced,
+ /* is_inline_axis */ false, &item.block_auto_behavior,
+ &item.is_block_axis_overflow_safe);
+
+ const auto item_writing_mode =
+ item_style.GetWritingDirection().GetWritingMode();
item.row_baseline_type = DetermineBaselineType(
- kForRows, container_writing_direction, item_writing_direction);
+ kForRows, container_writing_mode, item_writing_mode);
item.column_baseline_type = DetermineBaselineType(
- kForColumns, container_writing_direction, item_writing_direction);
-
- // This bit reflects whether an item is eligible to be the grid container's
- // baseline. It needs to be pre-computed, as the grid item's alignment can
- // fall back to 'start' for alignment purposes, but in that case, the element
- // should still be considered for the container's alignment baseline. As per
- // spec, only the inline axis is considered for the container's baseline, so
- // 'justify' values are not considered even in vertical writing modes.
- item.has_baseline_alignment =
- (item.block_axis_alignment == AxisEdge::kBaseline);
+ kForColumns, container_writing_mode, item_writing_mode);
if (node.IsOutOfFlowPositioned()) {
item.item_type = ItemType::kOutOfFlow;
@@ -1336,6 +1646,7 @@ void NGGridLayoutAlgorithm::BuildBlockTrackCollections(
DCHECK(column_track_collection);
DCHECK(row_track_collection);
DCHECK(grid_placement);
+
const ComputedStyle& grid_style = Style();
auto BuildBlockTrackCollection =
@@ -1361,7 +1672,7 @@ void NGGridLayoutAlgorithm::BuildBlockTrackCollections(
&template_track_list, &auto_track_list, start_offset,
grid_placement->AutoRepetitions(track_direction),
named_grid_area_track_count);
- EnsureTrackCoverageForGridItems(*grid_items, track_collection);
+ EnsureTrackCoverageForGridItems(grid_items, track_collection);
track_collection->FinalizeRanges(start_offset);
};
@@ -1371,13 +1682,17 @@ void NGGridLayoutAlgorithm::BuildBlockTrackCollections(
}
void NGGridLayoutAlgorithm::EnsureTrackCoverageForGridItems(
- const GridItems& grid_items,
+ GridItems* grid_items,
NGGridBlockTrackCollection* track_collection) const {
- DCHECK(track_collection);
+ DCHECK(grid_items && track_collection);
+
const auto track_direction = track_collection->Direction();
- for (const auto& grid_item : grid_items.item_data) {
- track_collection->EnsureTrackCoverage(grid_item.StartLine(track_direction),
- grid_item.SpanSize(track_direction));
+ for (auto& grid_item : grid_items->item_data) {
+ track_collection->EnsureTrackCoverage(
+ grid_item.StartLine(track_direction),
+ grid_item.SpanSize(track_direction),
+ &grid_item.RangeIndices(track_direction).begin,
+ &grid_item.RangeIndices(track_direction).end);
}
}
@@ -1387,23 +1702,54 @@ void NGGridLayoutAlgorithm::CacheGridItemsTrackSpanProperties(
DCHECK(grid_items);
const auto track_direction = track_collection.Direction();
- auto CompareGridItemsByStartLine = [grid_items, track_direction](
- wtf_size_t a, wtf_size_t b) -> bool {
- return grid_items->item_data[a].StartLine(track_direction) <
- grid_items->item_data[b].StartLine(track_direction);
+ GridItemVector grid_items_spanning_multiple_ranges;
+
+ auto CacheTrackSpanProperty =
+ [&](GridItemData& grid_item, const wtf_size_t range_index,
+ const TrackSpanProperties::PropertyId property) {
+ if (track_collection.RangeHasTrackSpanProperty(range_index, property))
+ grid_item.SetTrackSpanProperty(property, track_direction);
+ };
+
+ for (auto& grid_item : *grid_items) {
+ GridItemIndices range_indices = grid_item.RangeIndices(track_direction);
+ // If a grid item spans only one range, then we can just cache the track
+ // span properties directly. On the contrary, if a grid item spans multiple
+ // tracks, it is added to |grid_items_spanning_multiple_ranges| as we need
+ // to do more work to cache its track span properties.
+ // TODO(layout-dev): Investigate applying this concept to spans > 1.
+ if (range_indices.begin == range_indices.end) {
+ CacheTrackSpanProperty(grid_item, range_indices.begin,
+ TrackSpanProperties::kHasFlexibleTrack);
+ CacheTrackSpanProperty(grid_item, range_indices.begin,
+ TrackSpanProperties::kHasIntrinsicTrack);
+ CacheTrackSpanProperty(grid_item, range_indices.begin,
+ TrackSpanProperties::kHasAutoMinimumTrack);
+ } else {
+ grid_items_spanning_multiple_ranges.emplace_back(&grid_item);
+ }
+ }
+
+ if (grid_items_spanning_multiple_ranges.IsEmpty())
+ return;
+
+ auto CompareGridItemsByStartLine =
+ [track_direction](const GridItemData* a, const GridItemData* b) -> bool {
+ return a->StartLine(track_direction) < b->StartLine(track_direction);
};
- std::sort(grid_items->reordered_item_indices.begin(),
- grid_items->reordered_item_indices.end(),
+ std::sort(grid_items_spanning_multiple_ranges.begin(),
+ grid_items_spanning_multiple_ranges.end(),
CompareGridItemsByStartLine);
auto CacheTrackSpanPropertyForAllGridItems =
[&](TrackSpanProperties::PropertyId property) {
- // At this point we have the grid items sorted by their start line in
- // the respective direction; this is important since we'll process both,
- // the ranges in the track collection and the grid items, incrementally.
+ // At this point we have the remaining grid items sorted by start line
+ // in the respective direction; this is important since we'll process
+ // both, the ranges in the track collection and the grid items,
+ // incrementally.
auto range_iterator = track_collection.RangeIterator();
- for (auto& grid_item : *grid_items) {
+ for (auto* grid_item : grid_items_spanning_multiple_ranges) {
// We want to find the first range in the collection that:
// - Spans tracks located AFTER the start line of the current grid
// item; this can be done by checking that the last track number of
@@ -1415,7 +1761,7 @@ void NGGridLayoutAlgorithm::CacheGridItemsTrackSpanProperties(
// - Contains a track that fulfills the specified property.
while (!range_iterator.IsAtEnd() &&
(range_iterator.RangeTrackEnd() <
- grid_item.StartLine(track_direction) ||
+ grid_item->StartLine(track_direction) ||
!track_collection.RangeHasTrackSpanProperty(
range_iterator.RangeIndex(), property))) {
range_iterator.MoveToNextRange();
@@ -1436,8 +1782,8 @@ void NGGridLayoutAlgorithm::CacheGridItemsTrackSpanProperties(
// range are excluded from the grid item's span, meaning that such
// item cannot satisfy the property we are looking for.
if (range_iterator.RangeTrackEnd() <
- grid_item.EndLine(track_direction)) {
- grid_item.SetTrackSpanProperty(property, track_direction);
+ grid_item->EndLine(track_direction)) {
+ grid_item->SetTrackSpanProperty(property, track_direction);
}
}
};
@@ -1449,10 +1795,44 @@ void NGGridLayoutAlgorithm::CacheGridItemsTrackSpanProperties(
TrackSpanProperties::kHasAutoMinimumTrack);
}
+bool NGGridLayoutAlgorithm::CanLayoutGridItem(
+ const GridItemData& grid_item,
+ const NGConstraintSpace& space,
+ const GridTrackSizingDirection track_direction) const {
+ // Baseline eligibility based on layout only applies to flex and intrinsic
+ // tracks.
+ const auto& item_style = grid_item.node.Style();
+ const bool logical_width_depends_on_container =
+ item_style.LogicalWidth().IsPercentOrCalc() ||
+ item_style.LogicalMinWidth().IsPercentOrCalc() ||
+ item_style.LogicalMaxWidth().IsPercentOrCalc();
+
+ const bool logical_height_depends_on_container =
+ item_style.LogicalHeight().IsPercentOrCalc() ||
+ item_style.LogicalMinHeight().IsPercentOrCalc() ||
+ item_style.LogicalMaxHeight().IsPercentOrCalc() ||
+ item_style.LogicalHeight().IsAuto();
+
+ // TODO(kschmi) - this should be using 'BlockLengthUnresolvable' and
+ // 'InlineLengthUnresolvable', however those are a too strict and don't
+ // end up laying out enough grid items.
+ const bool can_layout_block_axis =
+ space.AvailableSize().block_size != kIndefiniteSize ||
+ !logical_height_depends_on_container;
+ const bool can_layout_inline_axis =
+ space.AvailableSize().inline_size != kIndefiniteSize ||
+ !logical_width_depends_on_container;
+
+ return can_layout_inline_axis && can_layout_block_axis;
+}
+
void NGGridLayoutAlgorithm::CalculateAlignmentBaselines(
- const GridItems& grid_items,
- GridTrackSizingDirection track_direction,
- GridGeometry* grid_geometry) const {
+ const GridTrackSizingDirection track_direction,
+ GridGeometry* grid_geometry,
+ GridItems* grid_items,
+ bool* needs_additional_pass) const {
+ DCHECK(grid_geometry && grid_items && needs_additional_pass);
+
// Reset existing baselines from geometry so they are clean with each call to
// this method. Use 'WTF::Vector::Fill()' over 'WTF::Vector::clear()', as
// 'clear' will reset the capacity to zero and require re-allocations.
@@ -1466,18 +1846,34 @@ void NGGridLayoutAlgorithm::CalculateAlignmentBaselines(
// TODO(kschmi): Skip this loop (or method) entirely if we don't have any
// baseline-aligned grid-items.
- for (auto& grid_item : grid_items.item_data) {
- if (!grid_item.IsBaselineAlignedForDirection(track_direction))
+ for (auto& grid_item : grid_items->item_data) {
+ if (!grid_item.IsBaselineSpecifiedForDirection(track_direction))
continue;
- const NGConstraintSpace space = CreateConstraintSpaceForMeasure(
- *grid_geometry, grid_item, track_direction);
- scoped_refptr<const NGLayoutResult> result = grid_item.node.Layout(space);
+ LogicalRect unused_grid_area;
+ const auto space = CreateConstraintSpaceForLayout(*grid_geometry, grid_item,
+ &unused_grid_area);
+
+ // We cannot apply some of the baseline alignment rules for synthesized
+ // baselines until layout has been performed. However, layout cannot
+ // be performed in certain scenarios. So force an additional pass in
+ // these cases and skip layout for now.
+ if (!CanLayoutGridItem(grid_item, space, track_direction)) {
+ *needs_additional_pass = true;
+ continue;
+ }
+ scoped_refptr<const NGLayoutResult> result = grid_item.node.Layout(space);
NGBoxFragment fragment(
grid_item.node.Style().GetWritingDirection(),
To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+ const bool has_synthesized_baseline = HasSynthesizedBaseline(
+ track_direction, fragment,
+ ConstraintSpace().GetWritingDirection().GetWritingMode());
+ grid_item.SetAlignmentFallback(track_direction, Style(),
+ has_synthesized_baseline);
+
const auto margins =
ComputeMarginsFor(space, grid_item.node.Style(), ConstraintSpace());
LayoutUnit margin = (track_direction == kForColumns) ? margins.inline_start
@@ -1487,7 +1883,13 @@ void NGGridLayoutAlgorithm::CalculateAlignmentBaselines(
fragment, track_direction,
ConstraintSpace().GetWritingDirection().GetWritingMode());
- grid_geometry->UpdateBaseline(grid_item, baseline, track_direction);
+ // TODO(kschmi): The IsReplaced() check here is a bit strange, but is
+ // necessary to pass some of the tests. Follow-up to see if there's
+ // a better solution.
+ if (grid_item.IsBaselineAlignedForDirection(track_direction) ||
+ grid_item.node.IsReplaced()) {
+ grid_geometry->UpdateBaseline(grid_item, baseline, track_direction);
+ }
}
}
@@ -1496,6 +1898,8 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::InitializeTrackSizes(
NGGridLayoutAlgorithmTrackCollection* track_collection) const {
DCHECK(track_collection);
const auto track_direction = track_collection->Direction();
+ const wtf_size_t set_count = track_collection->SetCount() + 1;
+
LayoutUnit available_size = (track_direction == kForColumns)
? grid_available_size_.inline_size
: grid_available_size_.block_size;
@@ -1503,13 +1907,16 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::InitializeTrackSizes(
LayoutUnit set_offset = (track_direction == kForColumns)
? BorderScrollbarPadding().inline_start
: BorderScrollbarPadding().block_start;
- const LayoutUnit grid_gap = GridGap(track_direction);
- wtf_size_t last_indefinite_index = kNotFound;
- Vector<SetOffsetData> sets;
- sets.ReserveInitialCapacity(track_collection->SetCount() + 1);
- sets.emplace_back(set_offset, /* track_count */ kNotFound,
- last_indefinite_index);
+ SetGeometry set_geometry;
+ set_geometry.gutter_size = GridGap(track_direction);
+ set_geometry.sets.ReserveInitialCapacity(set_count);
+ set_geometry.sets.emplace_back(set_offset, /* track_count */ kNotFound);
+
+ // The initial last indefinite index is always kNotFound.
+ wtf_size_t last_indefinite_index = kNotFound;
+ set_geometry.last_indefinite_indices.ReserveInitialCapacity(set_count);
+ set_geometry.last_indefinite_indices.emplace_back(last_indefinite_index);
for (auto set_iterator = track_collection->GetSetIterator();
!set_iterator.IsAtEnd(); set_iterator.MoveToNextSet()) {
@@ -1528,23 +1935,6 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::InitializeTrackSizes(
current_set.TrackCount());
}
- if (track_size.HasFixedMinTrackBreadth()) {
- DCHECK(!track_size.MinTrackBreadth().HasPercentage() ||
- available_size != kIndefiniteSize);
-
- // A fixed sizing function: Resolve to an absolute length and use that
- // size as the track’s initial base size.
- LayoutUnit fixed_min_breadth = MinimumValueForLength(
- track_size.MinTrackBreadth().length(), available_size);
- current_set.SetBaseSize(fixed_min_breadth * current_set.TrackCount());
- } else {
- // An intrinsic sizing function: Use an initial base size of zero.
- DCHECK(track_size.HasIntrinsicMinTrackBreadth());
- current_set.SetBaseSize(LayoutUnit());
- }
-
- // Note that, since |NGGridSet| initializes its growth limit as indefinite,
- // an intrinsic or flexible sizing function needs no further resolution.
if (track_size.HasFixedMaxTrackBreadth()) {
DCHECK(!track_size.MaxTrackBreadth().HasPercentage() ||
available_size != kIndefiniteSize);
@@ -1554,30 +1944,44 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::InitializeTrackSizes(
// than the base size, increase the growth limit to match the base size.
LayoutUnit fixed_max_breadth = MinimumValueForLength(
track_size.MaxTrackBreadth().length(), available_size);
- current_set.SetGrowthLimit(
- std::max(current_set.BaseSize(),
- fixed_max_breadth * current_set.TrackCount()));
+ current_set.InitGrowthLimit(fixed_max_breadth * current_set.TrackCount());
+
+ // For the purposes of our "base" row set geometry, we only use any
+ // definite max track sizing functions. We will use this value later to
+ // measure orthogonal (or %-block-size) grid item contributions.
+ set_offset += (fixed_max_breadth + set_geometry.gutter_size) *
+ current_set.TrackCount();
+ } else {
+ // An intrinsic or flexible sizing function: Use an initial growth limit
+ // of infinity.
+ current_set.InitGrowthLimit(kIndefiniteSize);
+ last_indefinite_index = set_geometry.sets.size() - 1;
}
- // For the purposes of our "base" row set geometry, we only use any fixed
- // max-track breadth. We use this for sizing any orthogonal, (or
- // %-block-size) children.
- if (track_size.HasFixedMaxTrackBreadth()) {
- set_offset +=
- current_set.GrowthLimit() + current_set.TrackCount() * grid_gap;
+ if (track_size.HasFixedMinTrackBreadth()) {
+ DCHECK(!track_size.MinTrackBreadth().HasPercentage() ||
+ available_size != kIndefiniteSize);
+
+ // A fixed sizing function: Resolve to an absolute length and use that
+ // size as the track’s initial base size.
+ LayoutUnit fixed_min_breadth = MinimumValueForLength(
+ track_size.MinTrackBreadth().length(), available_size);
+ current_set.InitBaseSize(fixed_min_breadth * current_set.TrackCount());
} else {
- last_indefinite_index = sets.size() - 1;
+ // An intrinsic sizing function: Use an initial base size of zero.
+ DCHECK(track_size.HasIntrinsicMinTrackBreadth());
+ current_set.InitBaseSize(LayoutUnit());
}
- sets.emplace_back(set_offset, current_set.TrackCount(),
- last_indefinite_index);
+ set_geometry.sets.emplace_back(set_offset, current_set.TrackCount());
+ set_geometry.last_indefinite_indices.emplace_back(last_indefinite_index);
}
// If all of our tracks have a definite size upfront, we use
// |ComputeSetGeometry| which will apply alignment (if present).
return track_collection->IsSpanningOnlyDefiniteTracks()
? ComputeSetGeometry(*track_collection)
- : SetGeometry(sets, grid_gap);
+ : set_geometry;
}
// https://drafts.csswg.org/css-grid-2/#algo-track-sizing
@@ -1586,13 +1990,14 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::ComputeUsedTrackSizes(
const GridGeometry& grid_geometry,
NGGridLayoutAlgorithmTrackCollection* track_collection,
GridItems* grid_items,
- bool* needs_additional_pass) const {
- DCHECK(track_collection);
- DCHECK(grid_items);
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const {
+ DCHECK(track_collection && grid_items && needs_additional_pass);
// 2. Resolve intrinsic track sizing functions to absolute lengths.
- ResolveIntrinsicTrackSizes(grid_geometry, track_collection, grid_items,
- needs_additional_pass);
+ ResolveIntrinsicTrackSizes(sizing_constraint, grid_geometry, track_collection,
+ grid_items, needs_additional_pass,
+ has_block_size_dependent_item);
// 3. If the free space is positive, distribute it equally to the base sizes
// of all tracks, freezing tracks as they reach their growth limits (and
@@ -1602,12 +2007,12 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::ComputeUsedTrackSizes(
// 4. This step sizes flexible tracks using the largest value it can assign to
// an 'fr' without exceeding the available space.
ExpandFlexibleTracks(sizing_constraint, grid_geometry, track_collection,
- grid_items, needs_additional_pass);
+ grid_items, needs_additional_pass,
+ has_block_size_dependent_item);
// 5. Stretch tracks with an 'auto' max track sizing function.
- StretchAutoTracks(sizing_constraint, track_collection, needs_additional_pass);
+ StretchAutoTracks(sizing_constraint, track_collection);
- // Return the set geometry.
return ComputeSetGeometry(*track_collection);
}
@@ -1802,7 +2207,7 @@ bool AreEqual<double>(double a, double b) {
// notice that this method replaces the notion of "tracks" with "sets".
template <bool is_equal_distribution>
void DistributeExtraSpaceToSets(LayoutUnit extra_space,
- const double flex_factor_sum,
+ double flex_factor_sum,
GridItemContributionType contribution_type,
GridSetVector* sets_to_grow,
GridSetVector* sets_to_grow_beyond_limit) {
@@ -1848,6 +2253,15 @@ void DistributeExtraSpaceToSets(LayoutUnit extra_space,
growable_track_count += set->TrackCount();
}
+ using ShareRatioType = typename std::conditional<is_equal_distribution,
+ wtf_size_t, double>::type;
+ DCHECK(is_equal_distribution ||
+ !AreEqual<ShareRatioType>(flex_factor_sum, 0));
+ ShareRatioType share_ratio_sum =
+ is_equal_distribution ? growable_track_count : flex_factor_sum;
+ const bool is_flex_factor_sum_overflowing_limits =
+ share_ratio_sum >= std::numeric_limits<wtf_size_t>::max();
+
// We will sort the tracks by growth potential in non-decreasing order to
// distribute space up to limits; notice that if we start distributing space
// equally among all tracks we will eventually reach the limit of a track or
@@ -1879,13 +2293,6 @@ void DistributeExtraSpaceToSets(LayoutUnit extra_space,
CompareSetsByGrowthPotential);
}
- using ShareRatioType = typename std::conditional<is_equal_distribution,
- wtf_size_t, double>::type;
- DCHECK(is_equal_distribution ||
- !AreEqual<ShareRatioType>(flex_factor_sum, 0));
- ShareRatioType share_ratio_sum =
- is_equal_distribution ? growable_track_count : flex_factor_sum;
-
auto ExtraSpaceShare = [&](const NGGridSet& set,
LayoutUnit growth_potential) -> LayoutUnit {
DCHECK(growth_potential >= 0 || growth_potential == kIndefiniteSize);
@@ -1901,6 +2308,13 @@ void DistributeExtraSpaceToSets(LayoutUnit extra_space,
ShareRatioType set_share_ratio =
is_equal_distribution ? set_track_count : set.FlexFactor();
+ // Since |share_ratio_sum| can be greater than the wtf_size_t limit, cap the
+ // value of |set_share_ratio| to prevent overflows.
+ if (set_share_ratio > share_ratio_sum) {
+ DCHECK(is_flex_factor_sum_overflowing_limits);
+ set_share_ratio = share_ratio_sum;
+ }
+
LayoutUnit extra_space_share;
if (AreEqual(set_share_ratio, share_ratio_sum)) {
// If this set's share ratio and the remaining ratio sum are the same, it
@@ -1912,8 +2326,9 @@ void DistributeExtraSpaceToSets(LayoutUnit extra_space,
set_track_count = growable_track_count;
extra_space_share = extra_space;
} else {
- DCHECK(!AreEqual<double>(share_ratio_sum, 0) &&
- set_share_ratio < share_ratio_sum);
+ DCHECK(!AreEqual<ShareRatioType>(share_ratio_sum, 0));
+ DCHECK_LT(set_share_ratio, share_ratio_sum);
+
extra_space_share = LayoutUnit::FromRawValue(
(extra_space.RawValue() * set_share_ratio) / share_ratio_sum);
}
@@ -2041,14 +2456,16 @@ void DistributeExtraSpaceToWeightedSets(
} // namespace
void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems(
+ SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
GridItems::Iterator group_begin,
GridItems::Iterator group_end,
const bool is_group_spanning_flex_track,
GridItemContributionType contribution_type,
NGGridLayoutAlgorithmTrackCollection* track_collection,
- bool* needs_additional_pass) const {
- DCHECK(track_collection);
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const {
+ DCHECK(track_collection && needs_additional_pass);
const auto track_direction = track_collection->Direction();
for (auto set_iterator = track_collection->GetSetIterator();
@@ -2075,7 +2492,7 @@ void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems(
LayoutUnit spanned_tracks_size =
GridGap(track_direction) * (grid_item->SpanSize(track_direction) - 1);
- double flex_factor_sum = 0;
+ base::ClampedNumeric<double> flex_factor_sum = 0;
for (auto set_iterator =
GetSetIteratorForItem(*grid_item, *track_collection);
!set_iterator.IsAtEnd(); set_iterator.MoveToNextSet()) {
@@ -2111,9 +2528,10 @@ void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems(
// spanned track from the grid item's size contribution to find the item's
// remaining size contribution. For infinite growth limits, substitute with
// the track's base size. This is the space to distribute, floor it at zero.
- LayoutUnit extra_space =
- ContributionSizeForGridItem(grid_geometry, *grid_item, track_direction,
- contribution_type, needs_additional_pass);
+ LayoutUnit extra_space = ContributionSizeForGridItem(
+ sizing_constraint, grid_geometry, *grid_item, track_direction,
+ contribution_type, needs_additional_pass,
+ has_block_size_dependent_item);
extra_space = (extra_space - spanned_tracks_size).ClampNegativeToZero();
if (!extra_space)
@@ -2157,11 +2575,13 @@ void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems(
// https://drafts.csswg.org/css-grid-2/#algo-content
void NGGridLayoutAlgorithm::ResolveIntrinsicTrackSizes(
+ SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
NGGridLayoutAlgorithmTrackCollection* track_collection,
GridItems* grid_items,
- bool* needs_additional_pass) const {
- DCHECK(track_collection && grid_items);
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const {
+ DCHECK(track_collection && grid_items && needs_additional_pass);
const auto track_direction = track_collection->Direction();
// Reorder grid items to process them as follows:
@@ -2203,30 +2623,35 @@ void NGGridLayoutAlgorithm::ResolveIntrinsicTrackSizes(
current_group_span_size);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, current_group_end,
+ sizing_constraint, grid_geometry, current_group_begin,
+ current_group_end,
/* is_group_spanning_flex_track */ false,
GridItemContributionType::kForIntrinsicMinimums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, current_group_end,
+ sizing_constraint, grid_geometry, current_group_begin,
+ current_group_end,
/* is_group_spanning_flex_track */ false,
GridItemContributionType::kForContentBasedMinimums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, current_group_end,
+ sizing_constraint, grid_geometry, current_group_begin,
+ current_group_end,
/* is_group_spanning_flex_track */ false,
GridItemContributionType::kForMaxContentMinimums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, current_group_end,
+ sizing_constraint, grid_geometry, current_group_begin,
+ current_group_end,
/* is_group_spanning_flex_track */ false,
GridItemContributionType::kForIntrinsicMaximums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, current_group_end,
+ sizing_constraint, grid_geometry, current_group_begin,
+ current_group_end,
/* is_group_spanning_flex_track */ false,
GridItemContributionType::kForMaxContentMaximums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
// Move to the next group with greater span size.
current_group_begin = current_group_end;
@@ -2248,20 +2673,23 @@ void NGGridLayoutAlgorithm::ResolveIntrinsicTrackSizes(
// We can safely skip contributions for maximums since a <flex> definition
// does not have an intrinsic max track sizing function.
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, grid_items->end(),
+ sizing_constraint, grid_geometry, current_group_begin,
+ grid_items->end(),
/* is_group_spanning_flex_track */ true,
GridItemContributionType::kForIntrinsicMinimums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, grid_items->end(),
+ sizing_constraint, grid_geometry, current_group_begin,
+ grid_items->end(),
/* is_group_spanning_flex_track */ true,
GridItemContributionType::kForContentBasedMinimums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
IncreaseTrackSizesToAccommodateGridItems(
- grid_geometry, current_group_begin, grid_items->end(),
+ sizing_constraint, grid_geometry, current_group_begin,
+ grid_items->end(),
/* is_group_spanning_flex_track */ true,
GridItemContributionType::kForMaxContentMinimums, track_collection,
- needs_additional_pass);
+ needs_additional_pass, has_block_size_dependent_item);
}
// If any track still has an infinite growth limit (i.e. it had no items
@@ -2281,6 +2709,20 @@ void GrowSetsByItemIncurredIncrease(GridSetVector* sets_to_grow) {
set->SetBaseSize(set->BaseSize() + set->ItemIncurredIncrease());
}
+LayoutUnit ComputeTotalTrackSize(
+ const NGGridLayoutAlgorithmTrackCollection& track_collection,
+ const LayoutUnit grid_gap) {
+ LayoutUnit total_track_size;
+ for (auto set_iterator = track_collection.GetSetIterator();
+ !set_iterator.IsAtEnd(); set_iterator.MoveToNextSet()) {
+ const auto& set = set_iterator.CurrentSet();
+ total_track_size += set.BaseSize() + set.TrackCount() * grid_gap;
+ }
+ // Clamp to zero to avoid a negative |grid_gap| when there are no tracks.
+ total_track_size -= grid_gap;
+ return total_track_size.ClampNegativeToZero();
+}
+
} // namespace
// https://drafts.csswg.org/css-grid-2/#algo-grow-tracks
@@ -2312,8 +2754,7 @@ void NGGridLayoutAlgorithm::MaximizeTracks(
// https://drafts.csswg.org/css-grid-2/#algo-stretch
void NGGridLayoutAlgorithm::StretchAutoTracks(
SizingConstraint sizing_constraint,
- NGGridLayoutAlgorithmTrackCollection* track_collection,
- bool* needs_additional_pass) const {
+ NGGridLayoutAlgorithmTrackCollection* track_collection) const {
const auto track_direction = track_collection->Direction();
// Stretching auto tracks should only occur if we have a "stretch" (or
@@ -2373,7 +2814,9 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
const GridGeometry& grid_geometry,
NGGridLayoutAlgorithmTrackCollection* track_collection,
GridItems* grid_items,
- bool* needs_additional_pass) const {
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const {
+ DCHECK(track_collection && grid_items && needs_additional_pass);
if (!track_collection->IsSpanningFlexibleTrack())
return;
@@ -2395,12 +2838,13 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
SetIterator set_iterator,
LayoutUnit leftover_space) -> double {
flexible_sets.Shrink(0);
- double flex_factor_sum = 0;
+ base::ClampedNumeric<double> flex_factor_sum = 0;
wtf_size_t total_track_count = 0;
while (!set_iterator.IsAtEnd()) {
auto& set = set_iterator.CurrentSet();
- if (set.TrackSize().HasFlexMaxTrackBreadth()) {
+ if (set.TrackSize().HasFlexMaxTrackBreadth() &&
+ !AreEqual<double>(set.FlexFactor(), 0)) {
flex_factor_sum += set.FlexFactor();
flexible_sets.push_back(&set);
} else {
@@ -2436,15 +2880,16 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
// on the left changes whenever we restart the algorithm treating some of
// those sets as inflexible. Note that, if the expression above is false for
// a given set, any other set with a lesser (base size / flex factor) ratio
- // will also fulfill such expression.
+ // will also fail such expression.
//
- // Based on this observation, we can process the sets in non-decreasing
+ // Based on this observation, we can process the sets in non-increasing
// ratio, when the current set does not fulfill the expression, no further
// set will fulfill it either (and we can return the hypothetical fr size).
// Otherwise, determine which sets should be treated as inflexible, exclude
// them from the leftover space and flex factor sum computation, and keep
// checking the condition for sets with lesser ratios.
- auto CompareSetsByBaseSizeFlexFactorRatio = [](NGGridSet* a, NGGridSet* b) {
+ auto CompareSetsByBaseSizeFlexFactorRatio = [](NGGridSet* a,
+ NGGridSet* b) -> bool {
// Avoid divisions by reordering the terms of the comparison.
return a->BaseSize().RawValue() * b->FlexFactor() >
b->BaseSize().RawValue() * a->FlexFactor();
@@ -2454,7 +2899,7 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
GridSetVector::iterator current_set = flexible_sets.begin();
while (leftover_space > 0 && current_set != flexible_sets.end()) {
- flex_factor_sum = std::max(flex_factor_sum, 1.0);
+ flex_factor_sum = base::ClampMax(flex_factor_sum, 1.0);
GridSetVector::iterator next_set = current_set;
while (next_set != flexible_sets.end() &&
@@ -2482,7 +2927,7 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
return 0;
};
- double fr_size = 0;
+ base::ClampedNumeric<double> fr_size = 0;
if (free_space != kIndefiniteSize) {
// Otherwise, if the free space is a definite length, the used flex fraction
// is the result of finding the size of an fr using all of the grid tracks
@@ -2499,12 +2944,12 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
// crosses and a space to fill of the item’s max-content contribution.
for (auto& grid_item : grid_items->item_data) {
if (grid_item.IsSpanningFlexibleTrack(track_direction)) {
- double grid_item_fr_size =
- FindFrSize(GetSetIteratorForItem(grid_item, *track_collection),
- ContributionSizeForGridItem(
- grid_geometry, grid_item, track_direction,
- GridItemContributionType::kForMaxContentMaximums,
- needs_additional_pass));
+ base::ClampedNumeric<double> grid_item_fr_size = FindFrSize(
+ GetSetIteratorForItem(grid_item, *track_collection),
+ ContributionSizeForGridItem(
+ sizing_constraint, grid_geometry, grid_item, track_direction,
+ GridItemContributionType::kForMaxContentMaximums,
+ needs_additional_pass, has_block_size_dependent_item));
fr_size = std::max(grid_item_fr_size, fr_size);
}
}
@@ -2526,7 +2971,8 @@ void NGGridLayoutAlgorithm::ExpandFlexibleTracks(
flexible_sets.push_back(&set);
DCHECK_GT(set.TrackCount(), 0u);
- double flex_factor = std::max<double>(set.FlexFactor(), set.TrackCount());
+ base::ClampedNumeric<double> flex_factor =
+ std::max<double>(set.FlexFactor(), set.TrackCount());
fr_size = std::max(set.BaseSize().RawValue() / flex_factor, fr_size);
}
}
@@ -2598,7 +3044,7 @@ TrackAlignmentGeometry ComputeTrackAlignmentGeometry(
return geometry;
}
case ContentDistributionType::kSpaceAround: {
- // Default behaviour for 'space-around' is to center content.
+ // Default behavior for 'space-around' is to center content.
const wtf_size_t track_count = track_collection.NonCollapsedTrackCount();
const LayoutUnit free_space = FreeSpace();
if (track_count < 1 || free_space < LayoutUnit()) {
@@ -2612,7 +3058,7 @@ TrackAlignmentGeometry ComputeTrackAlignmentGeometry(
return geometry;
}
case ContentDistributionType::kSpaceEvenly: {
- // Default behaviour for 'space-evenly' is to center content.
+ // Default behavior for 'space-evenly' is to center content.
const wtf_size_t track_count = track_collection.NonCollapsedTrackCount();
const LayoutUnit free_space = FreeSpace();
if (free_space < LayoutUnit()) {
@@ -2646,7 +3092,6 @@ TrackAlignmentGeometry ComputeTrackAlignmentGeometry(
geometry.start_offset += FreeSpace();
return geometry;
- break;
}
case ContentPosition::kCenter: {
geometry.start_offset += FreeSpace() / 2;
@@ -2685,21 +3130,21 @@ NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::ComputeSetGeometry(
BorderScrollbarPadding().block_start,
GridGap(kForRows));
+ const wtf_size_t set_count = track_collection.SetCount() + 1;
LayoutUnit set_offset = track_alignment_geometry.start_offset;
- Vector<SetOffsetData> sets;
- sets.ReserveInitialCapacity(track_collection.SetCount() + 1);
- sets.emplace_back(set_offset, /* track_count */ kNotFound,
- /* last_indefinite_index */ kNotFound);
+
+ SetGeometry set_geometry;
+ set_geometry.gutter_size = track_alignment_geometry.gutter_size;
+ set_geometry.sets.ReserveInitialCapacity(set_count);
+ set_geometry.sets.emplace_back(set_offset, /* track_count */ kNotFound);
for (auto set_iterator = track_collection.GetSetIterator();
!set_iterator.IsAtEnd(); set_iterator.MoveToNextSet()) {
const auto& set = set_iterator.CurrentSet();
- set_offset += set.BaseSize() +
- set.TrackCount() * track_alignment_geometry.gutter_size;
- sets.emplace_back(set_offset, set.TrackCount(),
- /* last_indefinite_index */ kNotFound);
+ set_offset += set.BaseSize() + set.TrackCount() * set_geometry.gutter_size;
+ set_geometry.sets.emplace_back(set_offset, set.TrackCount());
}
- return {sets, track_alignment_geometry.gutter_size};
+ return set_geometry;
}
LayoutUnit NGGridLayoutAlgorithm::GridGap(
@@ -2758,12 +3203,12 @@ LayoutUnit AlignmentOffset(LayoutUnit container_size,
LayoutUnit margin_end,
LayoutUnit baseline_offset,
AxisEdge axis_edge,
- OverflowAlignment overflow) {
+ bool is_overflow_safe) {
LayoutUnit free_space = container_size - size - margin_start - margin_end;
// If overflow is 'safe', we have to make sure we don't overflow the
// 'start' edge (potentially cause some data loss as the overflow is
// unreachable).
- if (overflow == OverflowAlignment::kSafe)
+ if (is_overflow_safe)
free_space = free_space.ClampNegativeToZero();
switch (axis_edge) {
case AxisEdge::kStart:
@@ -2841,12 +3286,8 @@ const NGConstraintSpace NGGridLayoutAlgorithm::CreateConstraintSpace(
builder.SetAvailableSize(containing_grid_area_size);
}
builder.SetPercentageResolutionSize(containing_grid_area_size);
- builder.SetStretchInlineSizeIfAuto(grid_item.is_inline_axis_stretched &&
- containing_grid_area_size.inline_size !=
- kIndefiniteSize);
- builder.SetStretchBlockSizeIfAuto(grid_item.is_block_axis_stretched &&
- containing_grid_area_size.block_size !=
- kIndefiniteSize);
+ builder.SetInlineAutoBehavior(grid_item.inline_auto_behavior);
+ builder.SetBlockAutoBehavior(grid_item.block_auto_behavior);
return builder.ToConstraintSpace();
}
@@ -2890,7 +3331,6 @@ const NGConstraintSpace NGGridLayoutAlgorithm::CreateConstraintSpaceForMeasure(
void NGGridLayoutAlgorithm::PlaceGridItems(const GridItems& grid_items,
const GridGeometry& grid_geometry,
LayoutUnit block_size) {
- const auto& container_style = Style();
const auto& container_space = ConstraintSpace();
const auto container_writing_direction =
container_space.GetWritingDirection();
@@ -2928,9 +3368,14 @@ void NGGridLayoutAlgorithm::PlaceGridItems(const GridItems& grid_items,
if (grid_item.IsBaselineAlignedForDirection(track_direction)) {
// The baseline offset is the difference between the grid item's
// baseline and its track baseline.
- return grid_geometry.Baseline(grid_item, track_direction) -
- GetLogicalBaseline(logical_fragment, track_direction,
- container_writing_direction.GetWritingMode());
+ const LayoutUnit item_baseline = GetLogicalBaseline(
+ logical_fragment, track_direction,
+ ConstraintSpace().GetWritingDirection().GetWritingMode());
+ LayoutUnit track_baseline =
+ grid_geometry.Baseline(grid_item, track_direction);
+ return (track_baseline != LayoutUnit::Min())
+ ? (track_baseline - item_baseline)
+ : item_baseline;
}
return (track_direction == kForColumns) ? margins.inline_start
: margins.block_start;
@@ -2945,13 +3390,13 @@ void NGGridLayoutAlgorithm::PlaceGridItems(const GridItems& grid_items,
AlignmentOffset(containing_grid_area.size.inline_size,
fragment.InlineSize(), margins.inline_start,
margins.inline_end, inline_baseline_offset,
- grid_item.inline_axis_alignment,
- container_style.AlignItems().Overflow()),
+ grid_item.InlineAxisAlignment(),
+ grid_item.is_inline_axis_overflow_safe),
AlignmentOffset(containing_grid_area.size.block_size,
fragment.BlockSize(), margins.block_start,
margins.block_end, block_baseline_offset,
- grid_item.block_axis_alignment,
- container_style.JustifyItems().Overflow()));
+ grid_item.BlockAxisAlignment(),
+ grid_item.is_block_axis_overflow_safe));
// Grid is special in that %-based offsets resolve against the grid-area.
// Determine the relative offset here (instead of in the builder). This is
@@ -2980,9 +3425,9 @@ void NGGridLayoutAlgorithm::PlaceGridItems(const GridItems& grid_items,
return (a.rows < b.rows) || (a.rows == b.rows && (a.columns < b.columns));
};
- LayoutUnit baseline = fragment.BaselineOrSynthesize() +
+ LayoutUnit baseline = fragment.Baseline().value_or(fragment.BlockSize()) +
containing_grid_area.offset.block_offset;
- if (grid_item.has_baseline_alignment) {
+ if (grid_item.IsBaselineSpecifiedForDirection(kForRows)) {
if (!alignment_baseline ||
IsBeforeInGridOrder(grid_item.resolved_position,
alignment_baseline->resolved_position)) {
@@ -3010,7 +3455,7 @@ void NGGridLayoutAlgorithm::PlaceGridItems(const GridItems& grid_items,
void NGGridLayoutAlgorithm::PlaceOutOfFlowItems(
const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
- const Vector<GridItemData>& out_of_flow_items,
+ const GridItemStorageVector& out_of_flow_items,
const GridGeometry& grid_geometry,
LayoutUnit block_size) {
const LogicalSize fragment_size(container_builder_.InlineSize(), block_size);
@@ -3021,7 +3466,8 @@ void NGGridLayoutAlgorithm::PlaceOutOfFlowItems(
if (out_of_flow_item.is_grid_containing_block) {
containing_block_rect = ComputeContainingGridAreaRect(
column_track_collection, row_track_collection, grid_geometry,
- out_of_flow_item, block_size);
+ out_of_flow_item, container_builder_.Borders(), border_box_size_,
+ block_size);
}
NGLogicalStaticPosition::InlineEdge inline_edge;
NGLogicalStaticPosition::BlockEdge block_edge;
@@ -3031,59 +3477,95 @@ void NGGridLayoutAlgorithm::PlaceOutOfFlowItems(
const LogicalSize containing_block_size =
containing_block_rect ? containing_block_rect->size
: default_containing_block_size;
- AlignmentOffsetForOutOfFlow(out_of_flow_item.inline_axis_alignment,
- out_of_flow_item.block_axis_alignment,
+ AlignmentOffsetForOutOfFlow(out_of_flow_item.InlineAxisAlignment(),
+ out_of_flow_item.BlockAxisAlignment(),
containing_block_size, &inline_edge,
&block_edge, &child_offset);
container_builder_.AddOutOfFlowChildCandidate(
out_of_flow_item.node, child_offset, inline_edge, block_edge,
- /* needs_block_offset_adjustment */ false, containing_block_rect);
+ /* needs_block_offset_adjustment */ false);
}
}
-void NGGridLayoutAlgorithm::PlaceOutOfFlowDescendants(
- const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
- const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
- const GridGeometry& grid_geometry,
- const NGGridPlacement& grid_placement,
- LayoutUnit block_size) {
- // At this point, we'll have a list of OOF candidates from any inflow children
- // of the grid (which have been propagated up). These might have an assigned
- // 'grid-area', so we need to assign their correct 'containing block rect'.
- Vector<NGLogicalOutOfFlowPositionedNode>* out_of_flow_descendants =
- container_builder_.MutableOutOfFlowPositionedCandidates();
- DCHECK(out_of_flow_descendants);
+// static
+absl::optional<LogicalRect> NGGridLayoutAlgorithm::ComputeContainingBlockRect(
+ const NGBlockNode& node,
+ const NGGridData& grid_data,
+ const ComputedStyle& container_style,
+ const WritingMode container_writing_mode,
+ const NGBoxStrut& borders,
+ const LogicalSize& border_box_size,
+ const LayoutUnit block_size) {
+ // If the out of flow item has the grid container as a containing block, then
+ // we don't need to go through placement.
+ const auto& node_style = node.Style();
+ if (node_style.GridColumnStart().IsAuto() &&
+ node_style.GridColumnEnd().IsAuto() &&
+ node_style.GridRowStart().IsAuto() && node_style.GridRowEnd().IsAuto()) {
+ return absl::nullopt;
+ }
+
+ auto ComputeAutoRepetitions =
+ [](const wtf_size_t auto_repeat_track_count,
+ const wtf_size_t auto_repeat_size) -> wtf_size_t {
+ return auto_repeat_size ? auto_repeat_track_count / auto_repeat_size : 0;
+ };
- for (auto& out_of_flow_descendant : *out_of_flow_descendants) {
- GridItemData out_of_flow_item =
- MeasureGridItem(out_of_flow_descendant.Node());
+ NGGridPlacement grid_placement(
+ container_style,
+ ComputeAutoRepetitions(
+ grid_data.column_auto_repeat_track_count,
+ container_style.GridTemplateColumns().NGTrackList().AutoRepeatSize()),
+ ComputeAutoRepetitions(
+ grid_data.row_auto_repeat_track_count,
+ container_style.GridTemplateRows().NGTrackList().AutoRepeatSize()),
+ grid_data.column_start, grid_data.row_start);
+
+ const auto& column_geometry = grid_data.column_geometry;
+ const auto& row_geometry = grid_data.row_geometry;
+
+ NGGridLayoutAlgorithmTrackCollection column_placement_track_collection(
+ column_geometry.ranges, GridTrackSizingDirection::kForColumns);
+ NGGridLayoutAlgorithmTrackCollection row_placement_track_collection(
+ row_geometry.ranges, GridTrackSizingDirection::kForRows);
+
+ GridItemData out_of_flow_item =
+ MeasureGridItem(node, container_style, container_writing_mode);
+ out_of_flow_item.ComputeOutOfFlowItemPlacement(
+ column_placement_track_collection, grid_placement);
+ out_of_flow_item.ComputeOutOfFlowItemPlacement(row_placement_track_collection,
+ grid_placement);
- out_of_flow_item.ComputeOutOfFlowItemPlacement(column_track_collection,
- grid_placement);
- out_of_flow_item.ComputeOutOfFlowItemPlacement(row_track_collection,
- grid_placement);
+ GridGeometry grid_geometry(
+ SetGeometry(column_geometry.sets, column_geometry.gutter_size),
+ SetGeometry(row_geometry.sets, row_geometry.gutter_size));
- out_of_flow_descendant.containing_block_rect =
- ComputeContainingGridAreaRect(column_track_collection,
- row_track_collection, grid_geometry,
- out_of_flow_item, block_size);
- }
+ return ComputeContainingGridAreaRect(
+ column_placement_track_collection, row_placement_track_collection,
+ grid_geometry, out_of_flow_item, borders, border_box_size, block_size);
}
+// static
LogicalRect NGGridLayoutAlgorithm::ComputeContainingGridAreaRect(
const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
const GridGeometry& grid_geometry,
- const GridItemData& item,
+ const GridItemData& out_of_flow_item,
+ const NGBoxStrut& borders,
+ const LogicalSize& border_box_size,
LayoutUnit block_size) {
+ DCHECK_EQ(out_of_flow_item.item_type, ItemType::kOutOfFlow);
+
LogicalRect rect;
ComputeOutOfFlowOffsetAndSize(
- item, grid_geometry.column_geometry, column_track_collection, block_size,
- &rect.offset.inline_offset, &rect.size.inline_size);
- ComputeOutOfFlowOffsetAndSize(
- item, grid_geometry.row_geometry, row_track_collection, block_size,
- &rect.offset.block_offset, &rect.size.block_size);
+ out_of_flow_item, grid_geometry.column_geometry, column_track_collection,
+ borders, border_box_size, block_size, &rect.offset.inline_offset,
+ &rect.size.inline_size);
+ ComputeOutOfFlowOffsetAndSize(out_of_flow_item, grid_geometry.row_geometry,
+ row_track_collection, borders, border_box_size,
+ block_size, &rect.offset.block_offset,
+ &rect.size.block_size);
return rect;
}
@@ -3133,8 +3615,6 @@ LayoutUnit TrackOffset(
const NGGridLayoutAlgorithm::SetGeometry& set_geometry,
const wtf_size_t range_index,
const wtf_size_t offset_in_range) {
- LayoutUnit track_offset;
-
const wtf_size_t range_starting_set_index =
track_collection.RangeStartingSetIndex(range_index);
const wtf_size_t range_track_count =
@@ -3142,6 +3622,7 @@ LayoutUnit TrackOffset(
const wtf_size_t range_set_count =
track_collection.RangeSetCount(range_index);
+ LayoutUnit track_offset;
if (offset_in_range == range_track_count) {
DCHECK(snap_to_end_of_track);
track_offset =
@@ -3171,6 +3652,14 @@ LayoutUnit TrackStartOffset(
const NGGridLayoutAlgorithm::SetGeometry& set_geometry,
const wtf_size_t range_index,
const wtf_size_t offset_in_range) {
+ if (!track_collection.RangeCount()) {
+ // If the start line of an out of flow item is not 'auto' in an empty and
+ // undefined grid, start offset is the start border scrollbar padding.
+ DCHECK_EQ(range_index, 0u);
+ DCHECK_EQ(offset_in_range, 0u);
+ return set_geometry.sets[0].offset;
+ }
+
const wtf_size_t range_track_count =
track_collection.RangeTrackCount(range_index);
@@ -3193,6 +3682,14 @@ LayoutUnit TrackEndOffset(
const NGGridLayoutAlgorithm::SetGeometry& set_geometry,
const wtf_size_t range_index,
const wtf_size_t offset_in_range) {
+ if (!track_collection.RangeCount()) {
+ // If the end line of an out of flow item is not 'auto' in an empty and
+ // undefined grid, end offset is the start border scrollbar padding.
+ DCHECK_EQ(range_index, 0u);
+ DCHECK_EQ(offset_in_range, 0u);
+ return set_geometry.sets[0].offset;
+ }
+
if (!offset_in_range && !range_index) {
// Only allow the offset to be 0 for the first range in the collection,
// which is the start line of the implicit grid; don't snap to the end.
@@ -3235,28 +3732,43 @@ void NGGridLayoutAlgorithm::ComputeGridItemOffsetAndSize(
// which has an indefinite used size, if |start_index| is greater, then all
// the sets between it and |end_index| are definite.
const wtf_size_t last_indefinite_index =
- set_geometry.sets[end_index].last_indefinite_index;
+ set_geometry.last_indefinite_indices.IsEmpty()
+ ? kNotFound
+ : set_geometry.last_indefinite_indices[end_index];
if (last_indefinite_index == kNotFound ||
start_index > last_indefinite_index) {
- *size = set_geometry.sets[end_index].offset - *start_offset -
- set_geometry.gutter_size;
- }
+ // If we have run into the max LayoutUnit, the size calculation won't work,
+ // collapse all sizes from here on.
+ if (start_offset->MightBeSaturated() ||
+ set_geometry.sets[end_index].offset.MightBeSaturated() ||
+ set_geometry.gutter_size.MightBeSaturated()) {
+ *size = LayoutUnit();
+ } else {
+ *size = set_geometry.sets[end_index].offset - *start_offset -
+ set_geometry.gutter_size;
+ if (size->MightBeSaturated())
+ *size = LayoutUnit();
+ }
+ }
+ DCHECK(!size->MightBeSaturated());
DCHECK(*size >= 0 || *size == kIndefiniteSize);
}
+// static
void NGGridLayoutAlgorithm::ComputeOutOfFlowOffsetAndSize(
const GridItemData& out_of_flow_item,
const SetGeometry& set_geometry,
const NGGridLayoutAlgorithmTrackCollection& track_collection,
+ const NGBoxStrut& borders,
+ const LogicalSize& border_box_size,
LayoutUnit block_size,
LayoutUnit* start_offset,
- LayoutUnit* size) const {
+ LayoutUnit* size) {
DCHECK(start_offset && size);
DCHECK_EQ(out_of_flow_item.item_type, ItemType::kOutOfFlow);
OutOfFlowItemPlacement item_placement;
- const auto& borders = container_builder_.Borders();
LayoutUnit end_offset;
// The default padding box value for |size| is used for out of flow items in
@@ -3264,38 +3776,39 @@ void NGGridLayoutAlgorithm::ComputeOutOfFlowOffsetAndSize(
if (track_collection.IsForColumns()) {
item_placement = out_of_flow_item.column_placement;
*start_offset = borders.inline_start;
- end_offset = border_box_size_.inline_size - borders.inline_end;
+ end_offset = border_box_size.inline_size - borders.inline_end;
} else {
item_placement = out_of_flow_item.row_placement;
*start_offset = borders.block_start;
- end_offset = ((border_box_size_.block_size == kIndefiniteSize)
+ end_offset = ((border_box_size.block_size == kIndefiniteSize)
? block_size
- : border_box_size_.block_size) -
+ : border_box_size.block_size) -
borders.block_end;
}
// If the start line is defined, the size will be calculated by subtracting
// the offset at |start_index|; otherwise, use the computed border start.
- if (item_placement.start_range_index != kNotFound) {
- DCHECK_NE(item_placement.start_offset_in_range, kNotFound);
+ if (item_placement.range_index.begin != kNotFound) {
+ DCHECK_NE(item_placement.offset_in_range.begin, kNotFound);
+
*start_offset = TrackStartOffset(track_collection, set_geometry,
- item_placement.start_range_index,
- item_placement.start_offset_in_range);
+ item_placement.range_index.begin,
+ item_placement.offset_in_range.begin);
}
// If the end line is defined, the offset (which can be the offset at the
// start index or the start border) and the added grid gap after the spanned
// tracks are subtracted from the offset at the end index.
- if (item_placement.end_range_index != kNotFound) {
- DCHECK_NE(item_placement.end_offset_in_range, kNotFound);
+ if (item_placement.range_index.end != kNotFound) {
+ DCHECK_NE(item_placement.offset_in_range.end, kNotFound);
end_offset = TrackEndOffset(track_collection, set_geometry,
- item_placement.end_range_index,
- item_placement.end_offset_in_range);
+ item_placement.range_index.end,
+ item_placement.offset_in_range.end);
*size = end_offset - *start_offset;
} else {
// By the time we call this method, we shouldn't have indefinite tracks.
- DCHECK_EQ(set_geometry.sets.back().last_indefinite_index, kNotFound);
+ DCHECK(set_geometry.last_indefinite_indices.IsEmpty());
// |start_offset| can be greater than |end_offset| if the track sizes from
// the grid overflow the container's respective size.
@@ -3340,6 +3853,7 @@ NGGridData::TrackCollectionGeometry NGGridLayoutAlgorithm::ConvertSetGeometry(
const NGGridLayoutAlgorithmTrackCollection& track_collection) const {
NGGridData::TrackCollectionGeometry set_data;
set_data.gutter_size = set_geometry.gutter_size;
+
DCHECK(set_geometry.sets.size());
set_data.sets.ReserveInitialCapacity(set_geometry.sets.size());
// Account for the offset inserted into the beginning of the geometry. See
@@ -3358,10 +3872,8 @@ NGGridData::TrackCollectionGeometry NGGridLayoutAlgorithm::ConvertSetGeometry(
set_data.total_track_count += tracks_in_set;
}
// Add range data
- for (auto& range : track_collection.Ranges()) {
- set_data.ranges.emplace_back(range.track_count, range.starting_set_index,
- range.set_count);
- }
+ for (auto& range : track_collection.Ranges())
+ set_data.ranges.emplace_back(range);
return set_data;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
index 87f0a182a8b..f5adb66faab 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -21,9 +21,11 @@ class CORE_EXPORT NGGridLayoutAlgorithm
NGBoxFragmentBuilder,
NGBlockBreakToken> {
public:
+ using SetOffsetData = NGGridData::SetData;
+
enum class AutoPlacementType { kNotNeeded, kMajor, kMinor, kBoth };
- enum class AxisEdge { kStart, kCenter, kEnd, kBaseline };
- enum class ItemType { kInGridFlow, kOutOfFlow };
+ enum class AxisEdge : uint8_t { kStart, kCenter, kEnd, kBaseline };
+ enum class ItemType : uint8_t { kInGridFlow, kOutOfFlow };
// This enum corresponds to each step used to accommodate grid items across
// intrinsic tracks according to their min and max track sizing functions, as
@@ -37,23 +39,21 @@ class CORE_EXPORT NGGridLayoutAlgorithm
kForFreeSpace,
};
- enum class BaselineType {
+ enum class BaselineType : uint8_t {
kMajor,
kMinor,
};
- struct OutOfFlowItemPlacement {
- wtf_size_t start_range_index = kNotFound;
- wtf_size_t start_offset_in_range = kNotFound;
- wtf_size_t end_range_index = kNotFound;
- wtf_size_t end_offset_in_range = kNotFound;
- };
-
- struct GridItemSetIndices {
+ struct GridItemIndices {
wtf_size_t begin = kNotFound;
wtf_size_t end = kNotFound;
};
+ struct OutOfFlowItemPlacement {
+ GridItemIndices range_index;
+ GridItemIndices offset_in_range;
+ };
+
struct CORE_EXPORT GridItemData {
DISALLOW_NEW();
@@ -61,7 +61,7 @@ class CORE_EXPORT NGGridLayoutAlgorithm
explicit GridItemData(const NGBlockNode node) : node(node) {}
AutoPlacementType AutoPlacement(
- GridTrackSizingDirection flow_direction) const;
+ const GridTrackSizingDirection major_direction) const;
const GridSpan& Span(GridTrackSizingDirection track_direction) const;
void SetSpan(const GridSpan& span,
GridTrackSizingDirection track_direction);
@@ -84,17 +84,20 @@ class CORE_EXPORT NGGridLayoutAlgorithm
bool IsBaselineAlignedForDirection(
GridTrackSizingDirection track_direction) const;
- void SetAlignmentFallback(
- const NGGridLayoutAlgorithmTrackCollection& track_collection,
- const ComputedStyle& container_style);
+ bool IsBaselineSpecifiedForDirection(
+ GridTrackSizingDirection track_direction) const;
+ void SetAlignmentFallback(const GridTrackSizingDirection track_direction,
+ const ComputedStyle& container_style,
+ const bool has_synthesized_baseline);
// For this item and track direction, computes the pair of indices |begin|
// and |end| such that the item spans every set from the respective
// collection's |sets_| with an index in the range [begin, end).
void ComputeSetIndices(
const NGGridLayoutAlgorithmTrackCollection& track_collection);
- const GridItemSetIndices& SetIndices(
+ const GridItemIndices& SetIndices(
GridTrackSizingDirection track_direction) const;
+ GridItemIndices& RangeIndices(GridTrackSizingDirection track_direction);
// For this out of flow item and track collection, computes and stores its
// first and last spanned ranges, as well as the start and end track offset.
@@ -103,27 +106,42 @@ class CORE_EXPORT NGGridLayoutAlgorithm
const NGGridLayoutAlgorithmTrackCollection& track_collection,
const NGGridPlacement& grid_placement);
- const NGBlockNode node;
+ NGBlockNode node;
GridArea resolved_position;
+ AxisEdge InlineAxisAlignment() const {
+ return inline_axis_alignment_fallback.value_or(inline_axis_alignment);
+ }
+
+ AxisEdge BlockAxisAlignment() const {
+ return block_axis_alignment_fallback.value_or(block_axis_alignment);
+ }
+
AxisEdge inline_axis_alignment;
AxisEdge block_axis_alignment;
+ absl::optional<AxisEdge> inline_axis_alignment_fallback;
+ absl::optional<AxisEdge> block_axis_alignment_fallback;
+
+ bool is_inline_axis_overflow_safe;
+ bool is_block_axis_overflow_safe;
ItemType item_type;
- bool is_grid_containing_block : 1;
+ bool is_grid_containing_block;
- bool is_inline_axis_stretched : 1;
- bool is_block_axis_stretched : 1;
+ NGAutoBehavior inline_auto_behavior;
+ NGAutoBehavior block_auto_behavior;
- bool has_baseline_alignment : 1;
BaselineType row_baseline_type;
BaselineType column_baseline_type;
TrackSpanProperties column_span_properties;
TrackSpanProperties row_span_properties;
- GridItemSetIndices column_set_indices;
- GridItemSetIndices row_set_indices;
+ GridItemIndices column_set_indices;
+ GridItemIndices row_set_indices;
+
+ GridItemIndices column_range_indices;
+ GridItemIndices row_range_indices;
// These fields are only for out of flow items. They are used to store their
// start/end range indices, and offsets in range in the respective track
@@ -132,6 +150,9 @@ class CORE_EXPORT NGGridLayoutAlgorithm
OutOfFlowItemPlacement row_placement;
};
+ using GridItemVector = Vector<GridItemData*, 16>;
+ using GridItemStorageVector = Vector<GridItemData, 4>;
+
struct CORE_EXPORT GridItems {
DISALLOW_NEW();
@@ -140,7 +161,7 @@ class CORE_EXPORT NGGridLayoutAlgorithm
: public std::iterator<std::input_iterator_tag, GridItemData> {
STACK_ALLOCATED();
public:
- Iterator(Vector<GridItemData>* item_data,
+ Iterator(GridItemStorageVector* item_data,
Vector<wtf_size_t>::const_iterator current_index)
: item_data_(item_data), current_index_(current_index) {
DCHECK(item_data_);
@@ -167,7 +188,7 @@ class CORE_EXPORT NGGridLayoutAlgorithm
}
private:
- Vector<GridItemData>* item_data_;
+ GridItemStorageVector* item_data_;
Vector<wtf_size_t>::const_iterator current_index_;
};
@@ -176,38 +197,24 @@ class CORE_EXPORT NGGridLayoutAlgorithm
void Append(const GridItemData& new_item_data);
- bool IsEmpty() const;
+ wtf_size_t Size() const { return item_data.size(); }
+ bool IsEmpty() const { return item_data.IsEmpty(); }
- // Grid items are appended to |item_data_| in the same order provided by
- // |NGGridChildIterator|, which iterates over its children in order-modified
- // document order; we want to keep such order since auto-placement and
- // painting order rely on it later in the algorithm.
- Vector<GridItemData> item_data;
+ // Grid items are appended in document order, but we want to rearrange them
+ // in order-modified document order since auto-placement and painting rely
+ // on it later in the algorithm.
+ GridItemStorageVector item_data;
Vector<wtf_size_t> reordered_item_indices;
};
- // See |SetGeometry|.
- struct SetOffsetData {
- SetOffsetData(LayoutUnit offset,
- wtf_size_t track_count,
- wtf_size_t last_indefinite_index)
- : offset(offset),
- track_count(track_count),
- last_indefinite_index(last_indefinite_index) {}
-
- LayoutUnit offset;
- wtf_size_t track_count;
- wtf_size_t last_indefinite_index;
- };
-
// Represents the offsets for the sets, and the gutter-size.
//
// Initially we only know some of the set sizes - others will be indefinite.
- // To represent this we store both the offset for the set, and the last index
- // where there was an indefinite set (or kNotFound if everything so far has
- // been definite). This allows us to get the appropriate size if a grid item
- // spans only fixed tracks, but will allow us to return an indefinite size if
- // it spans any indefinite set.
+ // To represent this we store both the offset for the set, and a vector of all
+ // last indefinite indices (or kNotFound if everything so far has been
+ // definite). This allows us to get the appropriate size if a grid item spans
+ // only fixed tracks, but will allow us to return an indefinite size if it
+ // spans any indefinite set.
//
// As an example:
// grid-template-rows: auto auto 100px 100px auto 100px;
@@ -235,6 +242,7 @@ class CORE_EXPORT NGGridLayoutAlgorithm
return (sets.size() == 1) ? LayoutUnit() : gutter_size;
}
+ Vector<wtf_size_t> last_indefinite_indices;
Vector<SetOffsetData> sets;
LayoutUnit gutter_size;
};
@@ -279,6 +287,17 @@ class CORE_EXPORT NGGridLayoutAlgorithm
MinMaxSizesResult ComputeMinMaxSizes(
const MinMaxSizesFloatInput&) const override;
+ // Computes the containing block rect of out of flow items from stored data
+ // in |NGGridData|.
+ static absl::optional<LogicalRect> ComputeContainingBlockRect(
+ const NGBlockNode& node,
+ const NGGridData& grid_data,
+ const ComputedStyle& grid_style,
+ const WritingMode container_writing_mode,
+ const NGBoxStrut& borders,
+ const LogicalSize& border_box_size,
+ const LayoutUnit block_size);
+
// Helper that computes tracks sizes in a given range.
static Vector<std::div_t> ComputeTrackSizesInRange(
const SetGeometry& set_geometry,
@@ -290,22 +309,29 @@ class CORE_EXPORT NGGridLayoutAlgorithm
enum class SizingConstraint { kLayout, kMinContent, kMaxContent };
+ LayoutUnit ComputeIntrinsicBlockSizeIgnoringChildren() const;
+
// Returns the size that a grid item will distribute across the tracks with an
// intrinsic sizing function it spans in the relevant track direction.
LayoutUnit ContributionSizeForGridItem(
+ SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
const GridItemData& grid_item,
GridTrackSizingDirection track_direction,
GridItemContributionType contribution_type,
- bool* needs_additional_pass) const;
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const;
wtf_size_t ComputeAutomaticRepetitions(
GridTrackSizingDirection track_direction) const;
void ConstructAndAppendGridItems(
GridItems* grid_items,
- Vector<GridItemData>* out_of_flow_items = nullptr) const;
- GridItemData MeasureGridItem(const NGBlockNode node) const;
+ GridItemStorageVector* out_of_flow_items = nullptr) const;
+
+ static GridItemData MeasureGridItem(const NGBlockNode node,
+ const ComputedStyle& container_style,
+ const WritingMode container_writing_mode);
void BuildBlockTrackCollections(
GridItems* grid_items,
@@ -315,7 +341,7 @@ class CORE_EXPORT NGGridLayoutAlgorithm
// Ensure coverage in block collection after grid items have been placed.
void EnsureTrackCoverageForGridItems(
- const GridItems& grid_items,
+ GridItems* grid_items,
NGGridBlockTrackCollection* track_collection) const;
// For every grid item, caches properties of the track sizing functions it
@@ -324,11 +350,18 @@ class CORE_EXPORT NGGridLayoutAlgorithm
const NGGridLayoutAlgorithmTrackCollection& track_collection,
GridItems* grid_items) const;
+ // Returns 'true' if it's possible to layout a grid item.
+ bool CanLayoutGridItem(const GridItemData& grid_item,
+ const NGConstraintSpace& space,
+ const GridTrackSizingDirection track_direction) const;
+
// Determines the major/minor alignment baselines for each row/column based on
// each item in |grid_items|, and stores the results in |grid_geometry|.
- void CalculateAlignmentBaselines(const GridItems& grid_items,
- GridTrackSizingDirection track_direction,
- GridGeometry* grid_geometry) const;
+ void CalculateAlignmentBaselines(
+ const GridTrackSizingDirection track_direction,
+ GridGeometry* grid_geometry,
+ GridItems* grid_items,
+ bool* needs_additional_pass) const;
// Initializes the given track collection, and returns the base set geometry.
SetGeometry InitializeTrackSizes(
@@ -340,39 +373,45 @@ class CORE_EXPORT NGGridLayoutAlgorithm
const GridGeometry& grid_geometry,
NGGridLayoutAlgorithmTrackCollection* track_collection,
GridItems* grid_items,
- bool* needs_additional_pass) const;
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item = nullptr) const;
// These methods implement the steps of the algorithm for intrinsic track size
// resolution defined in https://drafts.csswg.org/css-grid-2/#algo-content.
void ResolveIntrinsicTrackSizes(
+ SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
NGGridLayoutAlgorithmTrackCollection* track_collection,
GridItems* grid_items,
- bool* needs_additional_pass) const;
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const;
void IncreaseTrackSizesToAccommodateGridItems(
+ SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
GridItems::Iterator group_begin,
GridItems::Iterator group_end,
const bool is_group_spanning_flex_track,
GridItemContributionType contribution_type,
NGGridLayoutAlgorithmTrackCollection* track_collection,
- bool* needs_additional_pass) const;
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const;
void MaximizeTracks(
SizingConstraint sizing_constraint,
NGGridLayoutAlgorithmTrackCollection* track_collection) const;
- void StretchAutoTracks(SizingConstraint sizing_constraint,
- NGGridLayoutAlgorithmTrackCollection* track_collection,
- bool* needs_additional_pass) const;
+ void StretchAutoTracks(
+ SizingConstraint sizing_constraint,
+ NGGridLayoutAlgorithmTrackCollection* track_collection) const;
void ExpandFlexibleTracks(
SizingConstraint sizing_constraint,
const GridGeometry& grid_geometry,
NGGridLayoutAlgorithmTrackCollection* track_collection,
GridItems* grid_items,
- bool* needs_additional_pass) const;
+ bool* needs_additional_pass,
+ bool* has_block_size_dependent_item) const;
SetGeometry ComputeSetGeometry(
const NGGridLayoutAlgorithmTrackCollection& track_collection) const;
@@ -411,26 +450,19 @@ class CORE_EXPORT NGGridLayoutAlgorithm
void PlaceOutOfFlowItems(
const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
- const Vector<GridItemData>& out_of_flow_items,
- const GridGeometry& grid_geometry,
- LayoutUnit block_size);
-
- // Gets the out of flow descendants from the container builder and computes
- // their containing block rect.
- void PlaceOutOfFlowDescendants(
- const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
- const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
+ const GridItemStorageVector& out_of_flow_items,
const GridGeometry& grid_geometry,
- const NGGridPlacement& grid_placement,
LayoutUnit block_size);
// Helper method to compute the containing block rect for out of flow
// elements.
- LogicalRect ComputeContainingGridAreaRect(
+ static LogicalRect ComputeContainingGridAreaRect(
const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
const GridGeometry& grid_geometry,
const GridItemData& item,
+ const NGBoxStrut& borders,
+ const LogicalSize& border_box_size,
LayoutUnit block_size);
void ComputeGridItemOffsetAndSize(
@@ -440,13 +472,15 @@ class CORE_EXPORT NGGridLayoutAlgorithm
LayoutUnit* start_offset,
LayoutUnit* size) const;
- void ComputeOutOfFlowOffsetAndSize(
+ static void ComputeOutOfFlowOffsetAndSize(
const GridItemData& out_of_flow_item,
const SetGeometry& set_geometry,
const NGGridLayoutAlgorithmTrackCollection& track_collection,
+ const NGBoxStrut& borders,
+ const LogicalSize& border_box_size,
LayoutUnit block_size,
LayoutUnit* start_offset,
- LayoutUnit* size) const;
+ LayoutUnit* size);
NGGridData::TrackCollectionGeometry ConvertSetGeometry(
const SetGeometry& set_geometry,
@@ -457,6 +491,8 @@ class CORE_EXPORT NGGridLayoutAlgorithm
LogicalSize grid_available_size_;
LogicalSize grid_min_available_size_;
LogicalSize grid_max_available_size_;
+
+ absl::optional<LayoutUnit> contain_intrinsic_block_size_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
index b602ce990a5..41a82d567a6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
@@ -68,17 +68,17 @@ class NGGridLayoutAlgorithmTest
row_block_track_collection,
algorithm.grid_available_size_.block_size == kIndefiniteSize);
+ for (auto& grid_item : grid_items_) {
+ grid_item.ComputeSetIndices(column_track_collection_);
+ grid_item.ComputeSetIndices(row_track_collection_);
+ }
+
// Cache track span properties for grid items.
algorithm.CacheGridItemsTrackSpanProperties(column_track_collection_,
&grid_items_);
algorithm.CacheGridItemsTrackSpanProperties(row_track_collection_,
&grid_items_);
- for (auto& grid_item : grid_items_) {
- grid_item.ComputeSetIndices(column_track_collection_);
- grid_item.ComputeSetIndices(row_track_collection_);
- }
-
grid_geometry_ = {algorithm.InitializeTrackSizes(&column_track_collection_),
algorithm.InitializeTrackSizes(&row_track_collection_)};
@@ -191,7 +191,7 @@ class NGGridLayoutAlgorithmTest
}
NGGridLayoutAlgorithm::GridItems grid_items_;
- Vector<NGGridLayoutAlgorithm::GridItemData> out_of_flow_items_;
+ NGGridLayoutAlgorithm::GridItemStorageVector out_of_flow_items_;
NGGridLayoutAlgorithmTrackCollection column_track_collection_;
NGGridLayoutAlgorithmTrackCollection row_track_collection_;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
index a2b759ad329..b4eccf5b8bc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
@@ -3,13 +3,14 @@
// found in the LICENSE file
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h"
-#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_child_iterator.h"
namespace blink {
NGGridPlacement::NGGridPlacement(const ComputedStyle& grid_style,
const wtf_size_t column_auto_repetitions,
- const wtf_size_t row_auto_repetitions)
+ const wtf_size_t row_auto_repetitions,
+ const wtf_size_t column_start_offset,
+ const wtf_size_t row_start_offset)
: grid_style_(grid_style),
packing_behavior_(grid_style.IsGridAutoFlowAlgorithmSparse()
? PackingBehavior::kSparse
@@ -27,300 +28,280 @@ NGGridPlacement::NGGridPlacement(const ComputedStyle& grid_style,
grid_style.GridTemplateRows().NGTrackList().AutoRepeatSize() *
row_auto_repetitions),
column_auto_repetitions_(column_auto_repetitions),
- row_auto_repetitions_(row_auto_repetitions) {}
+ row_auto_repetitions_(row_auto_repetitions),
+ column_start_offset_(column_start_offset),
+ row_start_offset_(row_start_offset) {}
// https://drafts.csswg.org/css-grid/#auto-placement-algo
void NGGridPlacement::RunAutoPlacementAlgorithm(GridItems* grid_items) {
DCHECK(grid_items);
- // We need these variables in order to use |GridPositionsResolver|.
- column_start_offset_ = DetermineTrackStartOffset(*grid_items, kForColumns);
- row_start_offset_ = DetermineTrackStartOffset(*grid_items, kForRows);
-
- minor_max_end_line_ =
- (minor_direction_ == kForColumns)
- ? GridPositionsResolver::ExplicitGridColumnCount(
- grid_style_, column_auto_repeat_track_count_) +
- column_start_offset_
- : GridPositionsResolver::ExplicitGridRowCount(
- grid_style_, row_auto_repeat_track_count_) +
- row_start_offset_;
-
// Step 1. Position anything that’s not auto-placed; if no items need
// auto-placement, then we are done.
- if (!PlaceNonAutoGridItems(grid_items))
+ PlacedGridItemsList placed_items;
+ GridItemVector items_locked_to_major_axis;
+ GridItemVector items_not_locked_to_major_axis;
+
+ if (!PlaceNonAutoGridItems(grid_items, &items_locked_to_major_axis,
+ &items_not_locked_to_major_axis, &placed_items)) {
return;
+ }
+ placed_items.AppendCurrentItemsToOrderedList();
// Step 2. Process the items locked to the major axis.
- PlaceGridItemsLockedToMajorAxis(grid_items);
+ PlaceGridItemsLockedToMajorAxis(items_locked_to_major_axis, &placed_items);
// Step 3. Determine the number of minor tracks in the implicit grid.
// This is already accomplished within the |PlaceNonAutoGridItems| and
// |PlaceGridItemsLockedToMajorAxis| methods; nothing else to do here.
// Step 4. Position remaining grid items.
- AutoPlacementCursor placement_cursor;
- for (GridItemData& grid_item : grid_items->item_data) {
- switch (grid_item.AutoPlacement(major_direction_)) {
+ AutoPlacementCursor placement_cursor(placed_items.FirstPlacedItem());
+ for (GridItemData* grid_item : items_not_locked_to_major_axis) {
+ switch (grid_item->AutoPlacement(major_direction_)) {
case AutoPlacementType::kBoth:
- PlaceAutoBothAxisGridItem(&grid_item, &placement_cursor, *grid_items);
+ PlaceAutoBothAxisGridItem(grid_item, &placed_items, &placement_cursor);
break;
case AutoPlacementType::kMajor:
- PlaceAutoMajorAxisGridItem(&grid_item, &placement_cursor, *grid_items);
+ PlaceAutoMajorAxisGridItem(grid_item, &placed_items, &placement_cursor);
break;
case AutoPlacementType::kMinor:
- NOTREACHED() << "Minor axis placement should've already occurred.";
- break;
case AutoPlacementType::kNotNeeded:
+ NOTREACHED() << "Placement of non-auto placed items and items locked "
+ "to a major axis should've already occurred.";
break;
}
+ if (!HasSparsePacking()) {
+ // For dense packing, set the cursor’s major and minor positions to the
+ // start-most row and column lines in the implicit grid.
+ placement_cursor = AutoPlacementCursor(placed_items.FirstPlacedItem());
+ }
}
}
-wtf_size_t NGGridPlacement::DetermineTrackStartOffset(
- const GridItems& grid_items,
- GridTrackSizingDirection track_direction) const {
- wtf_size_t track_start_offset = 0;
+bool NGGridPlacement::PlaceNonAutoGridItems(
+ GridItems* grid_items,
+ GridItemVector* items_locked_to_major_axis,
+ GridItemVector* items_not_locked_to_major_axis,
+ PlacedGridItemsList* placed_items) {
+ DCHECK(grid_items && items_locked_to_major_axis &&
+ items_not_locked_to_major_axis && placed_items);
- for (const auto& grid_item : grid_items.item_data) {
- GridSpan grid_item_span =
+ column_start_offset_ = row_start_offset_ = 0;
+ for (auto& grid_item : grid_items->item_data) {
+ const auto& item_style = grid_item.node.Style();
+
+ GridSpan item_column_span =
GridPositionsResolver::ResolveGridPositionsFromStyle(
- grid_style_, grid_item.node.Style(), track_direction,
- AutoRepeatTrackCount(track_direction));
+ grid_style_, item_style, kForColumns,
+ column_auto_repeat_track_count_);
+ DCHECK(!item_column_span.IsTranslatedDefinite());
+ grid_item.SetSpan(item_column_span, kForColumns);
- if (!grid_item_span.IsIndefinite()) {
- DCHECK(grid_item_span.IsUntranslatedDefinite());
- track_start_offset = std::max<int>(
- track_start_offset, -grid_item_span.UntranslatedStartLine());
+ GridSpan item_row_span =
+ GridPositionsResolver::ResolveGridPositionsFromStyle(
+ grid_style_, item_style, kForRows, row_auto_repeat_track_count_);
+ DCHECK(!item_row_span.IsTranslatedDefinite());
+ grid_item.SetSpan(item_row_span, kForRows);
+
+ // When we have negative indices that go beyond the start of the explicit
+ // grid we need to prepend tracks to it; count how many tracks are needed by
+ // checking the minimum negative start line of definite spans, the negative
+ // of that minimum is the number of tracks we need to prepend.
+ // Simplifying the logic above: maximize the negative value of start lines.
+ if (item_column_span.IsUntranslatedDefinite()) {
+ column_start_offset_ = std::max<int>(
+ column_start_offset_, -item_column_span.UntranslatedStartLine());
+ }
+ if (item_row_span.IsUntranslatedDefinite()) {
+ row_start_offset_ = std::max<int>(row_start_offset_,
+ -item_row_span.UntranslatedStartLine());
}
}
- return track_start_offset;
-}
-bool NGGridPlacement::PlaceNonAutoGridItems(GridItems* grid_items) {
- DCHECK(grid_items);
- bool has_auto_placed_items = false;
+ minor_max_end_line_ =
+ (minor_direction_ == kForColumns)
+ ? GridPositionsResolver::ExplicitGridColumnCount(
+ grid_style_, column_auto_repeat_track_count_) +
+ column_start_offset_
+ : GridPositionsResolver::ExplicitGridRowCount(
+ grid_style_, row_auto_repeat_track_count_) +
+ row_start_offset_;
+
+ placed_items->needs_to_sort_item_vector = false;
+ auto& non_auto_placed_items = placed_items->item_vector;
+ non_auto_placed_items.ReserveInitialCapacity(grid_items->Size());
- for (GridItemData& grid_item : grid_items->item_data) {
- bool has_definite_major_placement =
- PlaceGridItem(&grid_item, major_direction_);
- bool has_definite_minor_placement =
- PlaceGridItem(&grid_item, minor_direction_);
+ for (auto& grid_item : grid_items->item_data) {
+ GridSpan item_major_span = grid_item.Span(major_direction_);
+ GridSpan item_minor_span = grid_item.Span(minor_direction_);
- if (has_definite_minor_placement) {
- minor_max_end_line_ =
- std::max(minor_max_end_line_, grid_item.EndLine(minor_direction_));
+ const bool has_indefinite_major_span = item_major_span.IsIndefinite();
+ const bool has_indefinite_minor_span = item_minor_span.IsIndefinite();
+
+ if (!has_indefinite_major_span) {
+ item_major_span.Translate(StartOffset(major_direction_));
+ grid_item.SetSpan(item_major_span, major_direction_);
+ }
+ if (!has_indefinite_minor_span) {
+ item_minor_span.Translate(StartOffset(minor_direction_));
+ grid_item.SetSpan(item_minor_span, minor_direction_);
+ }
+
+ minor_max_end_line_ = std::max<wtf_size_t>(
+ minor_max_end_line_, has_indefinite_minor_span
+ ? item_minor_span.IndefiniteSpanSize()
+ : item_minor_span.EndLine());
+
+ if (!has_indefinite_major_span && !has_indefinite_minor_span) {
+ auto* placed_item =
+ new PlacedGridItem(grid_item, major_direction_, minor_direction_);
+
+ // We will need to sort the item vector if the new placed item should be
+ // inserted to the ordered list before the last item in the vector.
+ placed_items->needs_to_sort_item_vector |=
+ !non_auto_placed_items.IsEmpty() &&
+ *placed_item < *non_auto_placed_items.back();
+
+ non_auto_placed_items.emplace_back(placed_item);
} else {
- has_auto_placed_items = true;
- minor_max_end_line_ = std::max<wtf_size_t>(
- minor_max_end_line_, GridPositionsResolver::SpanSizeForAutoPlacedItem(
- grid_item.node.Style(), minor_direction_));
+ if (has_indefinite_major_span)
+ items_not_locked_to_major_axis->emplace_back(&grid_item);
+ else
+ items_locked_to_major_axis->emplace_back(&grid_item);
}
- has_auto_placed_items |= !has_definite_major_placement;
}
- return has_auto_placed_items;
+ return !items_not_locked_to_major_axis->IsEmpty() ||
+ !items_locked_to_major_axis->IsEmpty();
}
-void NGGridPlacement::PlaceGridItemsLockedToMajorAxis(GridItems* grid_items) {
- DCHECK(grid_items);
+void NGGridPlacement::PlaceGridItemsLockedToMajorAxis(
+ const GridItemVector& items_locked_to_major_axis,
+ PlacedGridItemsList* placed_items) {
+ DCHECK(placed_items);
// Mapping between the major axis tracks and the last auto-placed item's end
// line inserted on that track. This is needed to implement "sparse" packing
// for grid items locked to a given major axis track.
// See https://drafts.csswg.org/css-grid/#auto-placement-algo.
- HashMap<wtf_size_t, wtf_size_t> minor_cursors;
+ HashMap<wtf_size_t, wtf_size_t, DefaultHash<wtf_size_t>::Hash,
+ WTF::UnsignedWithZeroKeyHashTraits<wtf_size_t>>
+ minor_cursors;
- for (GridItemData& grid_item : grid_items->item_data) {
- // Only consider grid items that require minor axis auto-placement.
- if (grid_item.AutoPlacement(major_direction_) != AutoPlacementType::kMinor)
- continue;
+ for (GridItemData* grid_item : items_locked_to_major_axis) {
+ DCHECK_EQ(grid_item->AutoPlacement(major_direction_),
+ AutoPlacementType::kMinor);
- wtf_size_t minor_start;
- if (HasSparsePacking() &&
- minor_cursors.Contains(grid_item.StartLine(major_direction_) + 1)) {
- minor_start = minor_cursors.at(grid_item.StartLine(major_direction_) + 1);
- } else {
- minor_start = 0;
- }
+ const wtf_size_t minor_span_size =
+ grid_item->Span(minor_direction_).IndefiniteSpanSize();
+ const wtf_size_t major_start_line = grid_item->StartLine(major_direction_);
- wtf_size_t minor_span_size =
- GridPositionsResolver::SpanSizeForAutoPlacedItem(grid_item.node.Style(),
- minor_direction_);
- while (DoesItemOverlap(grid_item.StartLine(major_direction_),
- grid_item.EndLine(major_direction_), minor_start,
- minor_start + minor_span_size, *grid_items)) {
- ++minor_start;
- }
+ AutoPlacementCursor placement_cursor(placed_items->FirstPlacedItem());
+ placement_cursor.MoveToMajorLine(major_start_line);
+ if (HasSparsePacking() && minor_cursors.Contains(major_start_line))
+ placement_cursor.MoveToMinorLine(minor_cursors.at(major_start_line));
+
+ placement_cursor.MoveCursorToFitGridSpan(
+ grid_item->SpanSize(major_direction_), minor_span_size,
+ minor_max_end_line_, CursorMovementBehavior::kForceMajorLine);
- wtf_size_t minor_end = minor_start + minor_span_size;
+ wtf_size_t minor_end_line = placement_cursor.MinorLine() + minor_span_size;
if (HasSparsePacking())
- minor_cursors.Set(grid_item.StartLine(major_direction_) + 1, minor_end);
- minor_max_end_line_ = std::max(minor_max_end_line_, minor_end);
+ minor_cursors.Set(major_start_line, minor_end_line);
+ minor_max_end_line_ = std::max(minor_max_end_line_, minor_end_line);
// Update grid item placement for minor axis.
- GridSpan grid_item_span =
- GridSpan::TranslatedDefiniteGridSpan(minor_start, minor_end);
- grid_item.SetSpan(grid_item_span, minor_direction_);
+ GridSpan grid_item_span = GridSpan::TranslatedDefiniteGridSpan(
+ placement_cursor.MinorLine(), minor_end_line);
+ grid_item->SetSpan(grid_item_span, minor_direction_);
+
+ PlaceGridItemAtCursor(*grid_item, placed_items, &placement_cursor);
}
}
void NGGridPlacement::PlaceAutoMajorAxisGridItem(
GridItemData* grid_item,
- AutoPlacementCursor* placement_cursor,
- const GridItems& grid_items) {
- DCHECK(grid_item);
-
- if (HasSparsePacking()) {
- // For sparse packing, set the minor position of the cursor to the grid
- // item’s minor starting line. If this is less than the previous column
- // position of the cursor, increment the major position by 1.
- if (grid_item->StartLine(minor_direction_) <
- placement_cursor->minor_position) {
- ++placement_cursor->major_position;
- }
- } else {
- // Otherwise, for dense packing, reset the auto-placement cursor's major
- // position to the start-most major line in the implicit grid.
- placement_cursor->major_position = 0;
- }
+ PlacedGridItemsList* placed_items,
+ AutoPlacementCursor* placement_cursor) const {
+ DCHECK(grid_item && placed_items);
+ const wtf_size_t major_span_size =
+ grid_item->Span(major_direction_).IndefiniteSpanSize();
- placement_cursor->minor_position = grid_item->StartLine(minor_direction_);
- wtf_size_t major_span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
- grid_item->node.Style(), major_direction_);
-
- // Increment the cursor’s major position until a value is found where the
- // grid item does not overlap any occupied grid cells
- while (DoesItemOverlap(placement_cursor->major_position,
- placement_cursor->major_position + major_span_size,
- grid_item->StartLine(minor_direction_),
- grid_item->EndLine(minor_direction_), grid_items)) {
- ++placement_cursor->major_position;
- }
+ placement_cursor->MoveToMinorLine(grid_item->StartLine(minor_direction_));
+ placement_cursor->MoveCursorToFitGridSpan(
+ major_span_size, grid_item->SpanSize(minor_direction_),
+ minor_max_end_line_, CursorMovementBehavior::kForceMinorLine);
// Update grid item placement for major axis.
GridSpan grid_item_span = GridSpan::TranslatedDefiniteGridSpan(
- placement_cursor->major_position,
- placement_cursor->major_position + major_span_size);
+ placement_cursor->MajorLine(),
+ placement_cursor->MajorLine() + major_span_size);
grid_item->SetSpan(grid_item_span, major_direction_);
+
+ PlaceGridItemAtCursor(*grid_item, placed_items, placement_cursor);
}
void NGGridPlacement::PlaceAutoBothAxisGridItem(
GridItemData* grid_item,
- AutoPlacementCursor* placement_cursor,
- const GridItems& grid_items) {
- DCHECK(grid_item);
-
- // For dense packing, set the cursor’s major and minor positions to the
- // start-most row and column lines in the implicit grid.
- if (!HasSparsePacking()) {
- placement_cursor->major_position = 0;
- placement_cursor->minor_position = 0;
- }
+ PlacedGridItemsList* placed_items,
+ AutoPlacementCursor* placement_cursor) const {
+ DCHECK(grid_item && placed_items && placement_cursor);
- wtf_size_t major_span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
- grid_item->node.Style(), major_direction_);
- wtf_size_t minor_span_size = GridPositionsResolver::SpanSizeForAutoPlacedItem(
- grid_item->node.Style(), minor_direction_);
-
- // Check to see if there would be overlap if this item was placed at the
- // cursor. If overlap exists, increment minor position until no conflict
- // exists or the item would overflow the minor axis.
- while (DoesItemOverlap(placement_cursor->major_position,
- placement_cursor->major_position + major_span_size,
- placement_cursor->minor_position,
- placement_cursor->minor_position + minor_span_size,
- grid_items)) {
- ++placement_cursor->minor_position;
- if (placement_cursor->minor_position + minor_span_size >
- minor_max_end_line_) {
- // If the cursor overflows the minor axis, increment cursor on the major
- // axis and start from the beginning.
- ++placement_cursor->major_position;
- placement_cursor->minor_position = 0;
- }
- }
+ const wtf_size_t major_span_size =
+ grid_item->Span(major_direction_).IndefiniteSpanSize();
+ const wtf_size_t minor_span_size =
+ grid_item->Span(minor_direction_).IndefiniteSpanSize();
+
+ placement_cursor->MoveCursorToFitGridSpan(major_span_size, minor_span_size,
+ minor_max_end_line_,
+ CursorMovementBehavior::kAuto);
// Update grid item placement for both axis.
GridSpan grid_item_span = GridSpan::TranslatedDefiniteGridSpan(
- placement_cursor->major_position,
- placement_cursor->major_position + major_span_size);
+ placement_cursor->MajorLine(),
+ placement_cursor->MajorLine() + major_span_size);
grid_item->SetSpan(grid_item_span, major_direction_);
grid_item_span = GridSpan::TranslatedDefiniteGridSpan(
- placement_cursor->minor_position,
- placement_cursor->minor_position + minor_span_size);
+ placement_cursor->MinorLine(),
+ placement_cursor->MinorLine() + minor_span_size);
grid_item->SetSpan(grid_item_span, minor_direction_);
-}
-
-bool NGGridPlacement::PlaceGridItem(
- GridItemData* grid_item,
- GridTrackSizingDirection track_direction) const {
- DCHECK(grid_item);
- GridSpan span = GridPositionsResolver::ResolveGridPositionsFromStyle(
- grid_style_, grid_item->node.Style(), track_direction,
- AutoRepeatTrackCount(track_direction));
- if (span.IsIndefinite()) {
- DCHECK(grid_item->Span(track_direction).IsIndefinite());
- return false;
- }
-
- DCHECK(span.IsUntranslatedDefinite());
- span.Translate(StartOffset(track_direction));
- grid_item->SetSpan(span, track_direction);
- return true;
+ PlaceGridItemAtCursor(*grid_item, placed_items, placement_cursor);
}
-bool NGGridPlacement::DoesItemOverlap(wtf_size_t major_start,
- wtf_size_t major_end,
- wtf_size_t minor_start,
- wtf_size_t minor_end,
- const GridItems& grid_items) const {
- DCHECK_LE(major_start, major_end);
- DCHECK_LE(minor_start, minor_end);
- // TODO(janewman): Implement smarter collision detection, iterating over all
- // items is not ideal and has large performance implications.
- for (const auto& grid_item : grid_items.item_data) {
- if (grid_item.Span(major_direction_).IsIndefinite())
- continue;
- // Only test against definite positions.
- // No collision if both start and end are on the same side of the item.
- wtf_size_t item_major_start = grid_item.StartLine(major_direction_);
- wtf_size_t item_major_end = grid_item.EndLine(major_direction_);
- if (major_end <= item_major_start)
- continue;
- if (major_start >= item_major_end)
- continue;
+void NGGridPlacement::PlaceGridItemAtCursor(
+ const GridItemData& grid_item,
+ PlacedGridItemsList* placed_items,
+ AutoPlacementCursor* placement_cursor) const {
+ DCHECK(placed_items && placement_cursor);
- // Do the same for the minor axis.
- if (grid_item.Span(minor_direction_).IsIndefinite())
- continue;
- wtf_size_t item_minor_start = grid_item.StartLine(minor_direction_);
- wtf_size_t item_minor_end = grid_item.EndLine(minor_direction_);
- if (minor_end <= item_minor_start)
- continue;
- if (minor_start >= item_minor_end)
- continue;
+ auto* new_placed_item =
+ new PlacedGridItem(grid_item, major_direction_, minor_direction_);
+ placed_items->item_vector.emplace_back(new_placed_item);
- return true;
- }
- return false;
+ const auto* next_placed_item = placement_cursor->NextPlacedItem();
+ placed_items->ordered_list.InsertAfter(
+ new_placed_item, next_placed_item ? next_placed_item->Prev()
+ : placed_items->ordered_list.Tail());
+
+ placement_cursor->InsertPlacedItemAtCurrentPosition(new_placed_item);
}
wtf_size_t NGGridPlacement::AutoRepeatTrackCount(
- GridTrackSizingDirection track_direction) const {
+ const GridTrackSizingDirection track_direction) const {
return (track_direction == kForColumns) ? column_auto_repeat_track_count_
: row_auto_repeat_track_count_;
}
wtf_size_t NGGridPlacement::AutoRepetitions(
- GridTrackSizingDirection track_direction) const {
+ const GridTrackSizingDirection track_direction) const {
return (track_direction == kForColumns) ? column_auto_repetitions_
: row_auto_repetitions_;
}
wtf_size_t NGGridPlacement::StartOffset(
- GridTrackSizingDirection track_direction) const {
+ const GridTrackSizingDirection track_direction) const {
return (track_direction == kForColumns) ? column_start_offset_
: row_start_offset_;
}
@@ -329,6 +310,227 @@ bool NGGridPlacement::HasSparsePacking() const {
return packing_behavior_ == PackingBehavior::kSparse;
}
+// A grid position is defined as the intersection between a line from the major
+// axis and another from the minor axis. Following the auto-placement algorithm
+// convention, a position with lesser major axis line comes first; in case of
+// ties, a position with lesser minor axis line comes first.
+bool NGGridPlacement::GridPosition::operator<=(
+ const GridPosition& other) const {
+ return (major_line == other.major_line) ? minor_line <= other.minor_line
+ : major_line < other.major_line;
+}
+bool NGGridPlacement::GridPosition::operator<(const GridPosition& other) const {
+ return (major_line != other.major_line) ? major_line < other.major_line
+ : minor_line < other.minor_line;
+}
+
+NGGridPlacement::PlacedGridItem::PlacedGridItem(
+ const GridItemData& grid_item,
+ const GridTrackSizingDirection major_direction,
+ const GridTrackSizingDirection minor_direction)
+ : start_{grid_item.StartLine(major_direction),
+ grid_item.StartLine(minor_direction)},
+ end_{grid_item.EndLine(major_direction),
+ grid_item.EndLine(minor_direction)} {}
+
+NGGridPlacement::GridPosition
+NGGridPlacement::PlacedGridItem::EndOnPreviousMajorLine() const {
+ DCHECK_GT(end_.major_line, 0u);
+ return {end_.major_line - 1, end_.minor_line};
+}
+
+void NGGridPlacement::AutoPlacementCursor::MoveCursorToFitGridSpan(
+ const wtf_size_t major_span_size,
+ const wtf_size_t minor_span_size,
+ const wtf_size_t minor_max_end_line,
+ const CursorMovementBehavior movement_behavior) {
+ DCHECK_LE(minor_span_size, minor_max_end_line);
+
+ wtf_size_t next_minor_line;
+ const bool allow_minor_line_movement =
+ movement_behavior != CursorMovementBehavior::kForceMinorLine;
+
+ // If we want to force the current major line, it's okay to place this grid
+ // span beyond the implicit grid's maximum minor end line.
+ const wtf_size_t minor_max_start_line =
+ (movement_behavior == CursorMovementBehavior::kForceMajorLine)
+ ? minor_max_end_line
+ : minor_max_end_line - minor_span_size;
+
+ auto NeedsToMoveToNextMajorLine = [&]() -> bool {
+ // If we need to force the minor line, or the grid span would go beyond the
+ // maximum minor end line, there is no point to keep looking for overlapping
+ // items in the current major line, i.e. needs to move the major line.
+ return next_minor_line > minor_max_start_line ||
+ (!allow_minor_line_movement &&
+ next_minor_line != current_position_.minor_line);
+ };
+
+ auto DoesCurrentPositionFitGridSpan = [&]() -> bool {
+ if (NeedsToMoveToNextMajorLine()) {
+ MoveToNextMajorLine(allow_minor_line_movement);
+ } else {
+ // If the minor line didn't move, it means there was no overlap with any
+ // previously placed item, and we don't need to move any further.
+ if (current_position_.minor_line == next_minor_line)
+ return true;
+
+ DCHECK_LT(current_position_.minor_line, next_minor_line);
+ MoveToMinorLine(next_minor_line);
+ }
+ return false;
+ };
+
+ if (current_position_.minor_line > minor_max_start_line)
+ MoveToNextMajorLine(allow_minor_line_movement);
+
+ while (true) {
+ UpdateItemsOverlappingMajorLine();
+ next_minor_line = current_position_.minor_line;
+ for (const auto* placed_item : items_overlapping_major_line_) {
+ const wtf_size_t minor_span_end_line = next_minor_line + minor_span_size;
+ const wtf_size_t item_minor_end_line = placed_item->MinorEndLine();
+
+ // Since we know that this item will overlap with the current major line,
+ // we only need to check if the minor span will overlap too.
+ if (next_minor_line < item_minor_end_line &&
+ placed_item->MinorStartLine() < minor_span_end_line) {
+ next_minor_line = item_minor_end_line;
+ if (NeedsToMoveToNextMajorLine())
+ break;
+ }
+ }
+
+ // If the next minor line was moved because it overlapped with a placed
+ // item, we don't need to check for overlaps with the rest of the upcoming
+ // placed items; keep looking for a position that doesn't overlap with the
+ // set of items overlapping the current major line first.
+ if (!DoesCurrentPositionFitGridSpan())
+ continue;
+
+ const auto* upcoming_item = next_placed_item_;
+ while (upcoming_item) {
+ const wtf_size_t major_span_end_line =
+ current_position_.major_line + major_span_size;
+ const wtf_size_t minor_span_end_line = next_minor_line + minor_span_size;
+ const wtf_size_t item_minor_end_line = upcoming_item->MinorEndLine();
+
+ // Check if the cursor would overlap the upcoming placed item.
+ if (next_minor_line < item_minor_end_line &&
+ current_position_.major_line < upcoming_item->MajorEndLine() &&
+ upcoming_item->MajorStartLine() < major_span_end_line &&
+ upcoming_item->MinorStartLine() < minor_span_end_line) {
+ next_minor_line = item_minor_end_line;
+ if (NeedsToMoveToNextMajorLine())
+ break;
+ }
+ upcoming_item = upcoming_item->Next();
+ }
+
+ if (DoesCurrentPositionFitGridSpan()) {
+ // No overlap with any placed item.
+ break;
+ }
+ }
+}
+
+void NGGridPlacement::AutoPlacementCursor::UpdateItemsOverlappingMajorLine() {
+ DCHECK(std::is_heap(items_overlapping_major_line_.begin(),
+ items_overlapping_major_line_.end(),
+ ComparePlacedGridItemsByEnd));
+
+ // Notice that the |EndOnPreviousMajorLine| of an item "A" is the first
+ // position such that any upcoming grid position (located at a greater
+ // major/minor position) is guaranteed to not overlap with "A".
+ while (!items_overlapping_major_line_.IsEmpty() &&
+ items_overlapping_major_line_.front()->EndOnPreviousMajorLine() <=
+ current_position_) {
+ std::pop_heap(items_overlapping_major_line_.begin(),
+ items_overlapping_major_line_.end(),
+ ComparePlacedGridItemsByEnd);
+ items_overlapping_major_line_.pop_back();
+ }
+
+ while (next_placed_item_ && next_placed_item_->Start() <= current_position_) {
+ if (current_position_ < next_placed_item_->EndOnPreviousMajorLine()) {
+ items_overlapping_major_line_.emplace_back(next_placed_item_);
+ std::push_heap(items_overlapping_major_line_.begin(),
+ items_overlapping_major_line_.end(),
+ ComparePlacedGridItemsByEnd);
+ has_new_item_overlapping_major_line_ = true;
+ }
+ next_placed_item_ = next_placed_item_->Next();
+ }
+}
+
+void NGGridPlacement::AutoPlacementCursor::MoveToMajorLine(
+ const wtf_size_t major_line) {
+ DCHECK_LE(current_position_.major_line, major_line);
+ current_position_.major_line = major_line;
+}
+
+void NGGridPlacement::AutoPlacementCursor::MoveToMinorLine(
+ const wtf_size_t minor_line) {
+ // Since the auto-placement cursor only moves forward to the next minor line,
+ // if the cursor is located at a position after the minor line we want to
+ // force, cycle back to such minor line in the next major line.
+ if (minor_line < current_position_.minor_line)
+ ++current_position_.major_line;
+ current_position_.minor_line = minor_line;
+}
+
+void NGGridPlacement::AutoPlacementCursor::MoveToNextMajorLine(
+ const bool allow_minor_line_movement) {
+ ++current_position_.major_line;
+
+ if (!has_new_item_overlapping_major_line_ &&
+ !items_overlapping_major_line_.IsEmpty()) {
+ DCHECK_GE(items_overlapping_major_line_.front()->MajorEndLine(),
+ current_position_.major_line);
+ current_position_.major_line =
+ items_overlapping_major_line_.front()->MajorEndLine();
+ }
+
+ if (allow_minor_line_movement)
+ current_position_.minor_line = 0;
+ has_new_item_overlapping_major_line_ = false;
+}
+
+void NGGridPlacement::AutoPlacementCursor::InsertPlacedItemAtCurrentPosition(
+ const PlacedGridItem* new_placed_item) {
+ // This update must happen after the doubly linked list already updated its
+ // element links to keep the necessary order for the cursor's logic.
+#if DCHECK_IS_ON()
+ if (next_placed_item_) {
+ DCHECK_EQ(next_placed_item_->Prev(), new_placed_item);
+ DCHECK(*new_placed_item < *next_placed_item_);
+ }
+#endif
+ DCHECK_EQ(new_placed_item->Next(), next_placed_item_);
+ next_placed_item_ = new_placed_item;
+
+ MoveToMinorLine(new_placed_item->MinorEndLine());
+ has_new_item_overlapping_major_line_ = true;
+}
+
+void NGGridPlacement::PlacedGridItemsList::AppendCurrentItemsToOrderedList() {
+ DCHECK(ordered_list.IsEmpty());
+
+ auto ComparePlacedGridItemPointers =
+ [](const std::unique_ptr<PlacedGridItem>& lhs,
+ const std::unique_ptr<PlacedGridItem>& rhs) { return *lhs < *rhs; };
+
+ if (needs_to_sort_item_vector) {
+ std::sort(item_vector.begin(), item_vector.end(),
+ ComparePlacedGridItemPointers);
+ }
+ DCHECK(std::is_sorted(item_vector.begin(), item_vector.end(),
+ ComparePlacedGridItemPointers));
+
+ for (auto& placed_item : item_vector)
+ ordered_list.Append(placed_item.get());
+}
+
namespace {
bool IsStartLineAuto(const GridTrackSizingDirection track_direction,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h
index 7489eda814b..4fff6a1bc79 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h"
+#include "third_party/blink/renderer/platform/wtf/doubly_linked_list.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -22,11 +23,14 @@ class CORE_EXPORT NGGridPlacement {
using GridItems = NGGridLayoutAlgorithm::GridItems;
using GridItemData = NGGridLayoutAlgorithm::GridItemData;
+ using GridItemVector = NGGridLayoutAlgorithm::GridItemVector;
using AutoPlacementType = NGGridLayoutAlgorithm::AutoPlacementType;
NGGridPlacement(const ComputedStyle& grid_style,
const wtf_size_t column_auto_repetitions,
- const wtf_size_t row_auto_repetitions);
+ const wtf_size_t row_auto_repetitions,
+ const wtf_size_t column_start_offset = 0,
+ const wtf_size_t row_start_offset = 0);
void RunAutoPlacementAlgorithm(GridItems* grid_items);
// Helper function to resolve start and end lines of out of flow items.
@@ -37,49 +41,124 @@ class CORE_EXPORT NGGridPlacement {
wtf_size_t* end_line) const;
wtf_size_t AutoRepeatTrackCount(
- GridTrackSizingDirection track_direction) const;
- wtf_size_t AutoRepetitions(GridTrackSizingDirection track_direction) const;
- wtf_size_t StartOffset(GridTrackSizingDirection track_direction) const;
+ const GridTrackSizingDirection track_direction) const;
+ wtf_size_t AutoRepetitions(
+ const GridTrackSizingDirection track_direction) const;
+ wtf_size_t StartOffset(const GridTrackSizingDirection track_direction) const;
private:
- struct AutoPlacementCursor {
- wtf_size_t major_position{0};
- wtf_size_t minor_position{0};
+ enum class CursorMovementBehavior { kAuto, kForceMajorLine, kForceMinorLine };
+
+ struct GridPosition {
+ bool operator<=(const GridPosition& other) const;
+ bool operator<(const GridPosition& other) const;
+
+ wtf_size_t major_line{0};
+ wtf_size_t minor_line{0};
};
- // Compute the track start offset from the grid items positioned at negative
- // indices.
- wtf_size_t DetermineTrackStartOffset(
- const GridItems& grid_items,
- GridTrackSizingDirection track_direction) const;
+ class PlacedGridItem final : public DoublyLinkedListNode<PlacedGridItem> {
+ USING_FAST_MALLOC(PlacedGridItem);
+ friend class DoublyLinkedListNode<PlacedGridItem>;
+
+ public:
+ PlacedGridItem(const GridItemData& grid_item,
+ const GridTrackSizingDirection major_direction,
+ const GridTrackSizingDirection minor_direction);
+
+ bool operator<(const PlacedGridItem& rhs) const {
+ return start_ < rhs.start_;
+ }
+
+ GridPosition Start() const { return start_; }
+ GridPosition End() const { return end_; }
+ GridPosition EndOnPreviousMajorLine() const;
+
+ wtf_size_t MajorStartLine() const { return start_.major_line; }
+ wtf_size_t MinorStartLine() const { return start_.minor_line; }
+ wtf_size_t MajorEndLine() const { return end_.major_line; }
+ wtf_size_t MinorEndLine() const { return end_.minor_line; }
+
+ private:
+ GridPosition start_, end_;
+ PlacedGridItem* next_{nullptr};
+ PlacedGridItem* prev_{nullptr};
+ };
+
+ class AutoPlacementCursor {
+ public:
+ explicit AutoPlacementCursor(const PlacedGridItem* first_placed_item)
+ : has_new_item_overlapping_major_line_(false),
+ next_placed_item_(first_placed_item) {}
+
+ void MoveCursorToFitGridSpan(
+ const wtf_size_t major_span_size,
+ const wtf_size_t minor_span_size,
+ const wtf_size_t minor_max_end_line,
+ const CursorMovementBehavior movement_behavior);
+ void MoveToMajorLine(const wtf_size_t major_line);
+ void MoveToMinorLine(const wtf_size_t minor_line);
+
+ void InsertPlacedItemAtCurrentPosition(
+ const PlacedGridItem* new_placed_item);
+
+ wtf_size_t MajorLine() const { return current_position_.major_line; }
+ wtf_size_t MinorLine() const { return current_position_.minor_line; }
+
+ const PlacedGridItem* NextPlacedItem() const { return next_placed_item_; }
+
+ private:
+ // Comparer needed to use |items_overlapping_major_line_| as a heap.
+ struct {
+ bool operator()(const PlacedGridItem* lhs,
+ const PlacedGridItem* rhs) const {
+ return rhs->End() < lhs->End();
+ }
+ } ComparePlacedGridItemsByEnd;
+
+ void MoveToNextMajorLine(const bool allow_minor_line_movement);
+ void UpdateItemsOverlappingMajorLine();
+
+ Vector<const PlacedGridItem*, 16> items_overlapping_major_line_;
+ bool has_new_item_overlapping_major_line_ : 1;
+ const PlacedGridItem* next_placed_item_;
+ GridPosition current_position_;
+ };
+
+ struct PlacedGridItemsList {
+ void AppendCurrentItemsToOrderedList();
+ PlacedGridItem* FirstPlacedItem() { return ordered_list.Head(); }
+
+ Vector<std::unique_ptr<PlacedGridItem>, 16> item_vector;
+ DoublyLinkedList<PlacedGridItem> ordered_list;
+ bool needs_to_sort_item_vector : 1;
+ };
// Place non auto-positioned elements from |grid_items|; returns true if any
// item needs to resolve an automatic position. Otherwise, false.
- bool PlaceNonAutoGridItems(GridItems* grid_items);
+ bool PlaceNonAutoGridItems(GridItems* grid_items,
+ GridItemVector* items_locked_to_major_axis,
+ GridItemVector* items_not_locked_to_major_axis,
+ PlacedGridItemsList* placed_items);
// Place elements from |grid_items| that have a definite position on the major
// axis but need auto-placement on the minor axis.
- void PlaceGridItemsLockedToMajorAxis(GridItems* grid_items);
+ void PlaceGridItemsLockedToMajorAxis(
+ const GridItemVector& items_locked_to_major_axis,
+ PlacedGridItemsList* placed_items);
// Place an item that has a definite position on the minor axis but need
// auto-placement on the major axis.
void PlaceAutoMajorAxisGridItem(GridItemData* grid_item,
- AutoPlacementCursor* placement_cursor,
- const GridItems& grid_items);
+ PlacedGridItemsList* placed_items,
+ AutoPlacementCursor* placement_cursor) const;
// Place an item that needs auto-placement on both the major and minor axis.
void PlaceAutoBothAxisGridItem(GridItemData* grid_item,
- AutoPlacementCursor* placement_cursor,
- const GridItems& grid_items);
-
- // Places a grid item; returns true if it has a definite position in the given
- // direction, false if the item needs auto-placement.
- bool PlaceGridItem(GridItemData* grid_item,
- GridTrackSizingDirection track_direction) const;
-
- // Returns true if the given placement would overlap with a placed item.
- bool DoesItemOverlap(wtf_size_t major_start,
- wtf_size_t major_end,
- wtf_size_t minor_start,
- wtf_size_t minor_end,
- const GridItems& grid_items) const;
+ PlacedGridItemsList* placed_items,
+ AutoPlacementCursor* placement_cursor) const;
+ // Update the list of placed grid items and auto-placement cursor using the
+ // resolved position of the specified grid item.
+ void PlaceGridItemAtCursor(const GridItemData& grid_item,
+ PlacedGridItemsList* placed_items,
+ AutoPlacementCursor* placement_cursor) const;
bool HasSparsePacking() const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
index 9137a76abe4..c5c014183d7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
@@ -172,16 +172,18 @@ void NGGridBlockTrackCollection::SetSpecifiedTracks(
const wtf_size_t repeater_count = explicit_tracks_->RepeaterCount();
wtf_size_t current_repeater_start_line = start_offset;
-
+ // Add extra capacity for the extra lines needed for named grids.
+ start_lines_.ReserveCapacity(repeater_count + 1);
+ end_lines_.ReserveCapacity(repeater_count + 1);
for (wtf_size_t i = 0; i < repeater_count; ++i) {
wtf_size_t repeater_track_count =
explicit_tracks_->RepeatCount(i, auto_repetitions_) *
explicit_tracks_->RepeatSize(i);
DCHECK_NE(repeater_track_count, 0u);
- start_lines_.push_back(current_repeater_start_line);
+ start_lines_.emplace_back(current_repeater_start_line);
current_repeater_start_line += repeater_track_count;
- end_lines_.push_back(current_repeater_start_line);
+ end_lines_.emplace_back(current_repeater_start_line);
}
// There is a special scenario where named grid areas can be specified through
@@ -195,30 +197,40 @@ void NGGridBlockTrackCollection::SetSpecifiedTracks(
const wtf_size_t named_grid_area_end_line =
start_offset + named_grid_area_track_count;
if (current_repeater_start_line < named_grid_area_end_line) {
- start_lines_.push_back(current_repeater_start_line);
- end_lines_.push_back(named_grid_area_end_line);
+ start_lines_.emplace_back(current_repeater_start_line);
+ end_lines_.emplace_back(named_grid_area_end_line);
}
}
-void NGGridBlockTrackCollection::EnsureTrackCoverage(wtf_size_t track_number,
- wtf_size_t span_length) {
+void NGGridBlockTrackCollection::EnsureTrackCoverage(
+ wtf_size_t track_number,
+ wtf_size_t span_length,
+ wtf_size_t* grid_item_start_range_index,
+ wtf_size_t* grid_item_end_range_index) {
DCHECK_NE(kInvalidRangeIndex, track_number);
DCHECK_NE(kInvalidRangeIndex, span_length);
+ DCHECK(grid_item_start_range_index && grid_item_end_range_index);
+
track_indices_need_sort_ = true;
- start_lines_.push_back(track_number);
- end_lines_.push_back(track_number + span_length);
+ start_lines_.emplace_back(track_number, grid_item_start_range_index);
+ end_lines_.emplace_back(track_number + span_length,
+ grid_item_end_range_index);
}
void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
// Sort start and ending tracks from low to high.
if (track_indices_need_sort_) {
- std::sort(start_lines_.begin(), start_lines_.end());
- std::sort(end_lines_.begin(), end_lines_.end());
+ auto CompareTrackBoundaries = [](const TrackBoundaryToRangePair& a,
+ const TrackBoundaryToRangePair& b) {
+ return a.grid_line < b.grid_line;
+ };
+ std::sort(start_lines_.begin(), start_lines_.end(), CompareTrackBoundaries);
+ std::sort(end_lines_.begin(), end_lines_.end(), CompareTrackBoundaries);
}
ranges_.clear();
bool is_in_auto_fit_range = false;
- wtf_size_t current_range_start = 0u;
+ wtf_size_t current_range_start_line = 0u;
wtf_size_t open_items_or_repeaters = 0u;
wtf_size_t current_explicit_grid_line = start_offset;
wtf_size_t current_explicit_repeater_index = kInvalidRangeIndex;
@@ -237,14 +249,15 @@ void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
while (true) {
// Identify starting tracks index.
while (start_line_index < start_lines_.size() &&
- current_range_start >= start_lines_[start_line_index]) {
+ current_range_start_line >=
+ start_lines_[start_line_index].grid_line) {
++start_line_index;
++open_items_or_repeaters;
}
// Identify ending tracks index.
while (end_line_index < end_lines_.size() &&
- current_range_start >= end_lines_[end_line_index]) {
+ current_range_start_line >= end_lines_[end_line_index].grid_line) {
++end_line_index;
--open_items_or_repeaters;
DCHECK_GE(open_items_or_repeaters, 0u);
@@ -258,7 +271,7 @@ void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
// the repeaters, or are located at the end of the last repeater.
if (current_explicit_repeater_index != kInvalidRangeIndex) {
DCHECK_EQ(current_explicit_repeater_index, explicit_repeater_count - 1);
- DCHECK_EQ(current_range_start, next_explicit_repeater_start);
+ DCHECK_EQ(current_range_start_line, next_explicit_repeater_start);
}
#endif
break;
@@ -266,12 +279,12 @@ void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
// Determine the next starting and ending track index.
wtf_size_t next_start_line = (start_line_index < start_lines_.size())
- ? start_lines_[start_line_index]
+ ? start_lines_[start_line_index].grid_line
: kInvalidRangeIndex;
- wtf_size_t next_end_line = end_lines_[end_line_index];
+ wtf_size_t next_end_line = end_lines_[end_line_index].grid_line;
// Move to the start of the next explicit repeater.
- while (current_range_start == next_explicit_repeater_start) {
+ while (current_range_start_line == next_explicit_repeater_start) {
current_explicit_grid_line = next_explicit_repeater_start;
// No next repeater, break and use implicit grid tracks.
@@ -292,11 +305,11 @@ void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
// Determine track number and count of the range.
Range range;
- range.starting_track_number = current_range_start;
+ range.start_line = current_range_start_line;
DCHECK(next_start_line != kInvalidRangeIndex ||
next_end_line < next_start_line);
range.track_count =
- std::min(next_start_line, next_end_line) - current_range_start;
+ std::min(next_start_line, next_end_line) - current_range_start_line;
DCHECK_GT(range.track_count, 0u);
// Compute repeater index and offset.
@@ -306,7 +319,7 @@ void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
// such repeater.
range.repeater_index = current_explicit_repeater_index;
range.repeater_offset =
- (current_range_start - current_explicit_grid_line) %
+ (current_range_start_line - current_explicit_grid_line) %
explicit_tracks_->RepeatSize(current_explicit_repeater_index);
} else {
range.SetIsImplicit();
@@ -332,22 +345,55 @@ void NGGridBlockTrackCollection::FinalizeRanges(wtf_size_t start_offset) {
// receives the first specified size, and so on forwards.
//
// Note that for both scenarios we can use the following formula:
- // (current_range_start - current_explicit_grid_line) %
+ // (current_range_start_line - current_explicit_grid_line) %
// implicit_repeater_size
// The expression below is equivalent, but uses some modular arithmetic
// properties to avoid |wtf_size_t| underflow in scenario 1.
range.repeater_index = 0u;
wtf_size_t implicit_repeater_size = implicit_tracks_->RepeatSize(0u);
range.repeater_offset =
- (current_range_start + implicit_repeater_size -
+ (current_range_start_line + implicit_repeater_size -
current_explicit_grid_line % implicit_repeater_size) %
implicit_repeater_size;
}
}
+ // Cache range-start indices to avoid having to recompute them later.
+ // Loop backwards to find all other entries with the same track number. The
+ // |start_line_index| will always land 1 position after duplicate entries.
+ // Walk back to cache all duplicates until we are at the start of the vector
+ // or we have gone over all duplicate entries.
+ if (start_line_index != 0) {
+ DCHECK_LE(start_line_index, start_lines_.size());
+ for (wtf_size_t line_index = start_line_index - 1;
+ start_lines_[line_index].grid_line == range.start_line;
+ --line_index) {
+ if (start_lines_[line_index].grid_item_range_index_to_cache) {
+ *start_lines_[line_index].grid_item_range_index_to_cache =
+ ranges_.size();
+ }
+ // This is needed here to avoid underflow.
+ if (!line_index)
+ break;
+ }
+ }
+
+ // Cache range-end indices to avoid having to recompute them later. The
+ // |end_line_index| will always land at the start of duplicate entries.
+ // Cache all duplicate entries by walking forwards until we are at the end
+ // of the vector or we have gone over all duplicate entries.
+ const wtf_size_t track_number = range.start_line + range.track_count;
+ for (wtf_size_t line_index = end_line_index;
+ line_index < end_lines_.size() &&
+ end_lines_[line_index].grid_line == track_number;
+ ++line_index) {
+ if (end_lines_[line_index].grid_item_range_index_to_cache)
+ *end_lines_[line_index].grid_item_range_index_to_cache = ranges_.size();
+ }
+
if (is_in_auto_fit_range && open_items_or_repeaters == 1u)
range.SetIsCollapsed();
- current_range_start += range.track_count;
+ current_range_start_line += range.track_count;
ranges_.emplace_back(std::move(range));
}
@@ -392,13 +438,13 @@ String NGGridBlockTrackCollection::ToString() const {
builder.Append("], [Starting: {");
for (wtf_size_t i = 0; i < start_lines_.size(); ++i) {
- builder.AppendNumber<wtf_size_t>(start_lines_[i]);
+ builder.AppendNumber<wtf_size_t>(start_lines_[i].grid_line);
if (i + 1 != start_lines_.size())
builder.Append(", ");
}
builder.Append("} ], [Ending: {");
for (wtf_size_t i = 0; i < end_lines_.size(); ++i) {
- builder.AppendNumber<wtf_size_t>(end_lines_[i]);
+ builder.AppendNumber<wtf_size_t>(end_lines_[i].grid_line);
if (i + 1 != end_lines_.size())
builder.Append(", ");
}
@@ -421,7 +467,7 @@ wtf_size_t NGGridBlockTrackCollection::ImplicitRepeatSize() const {
wtf_size_t NGGridBlockTrackCollection::RangeTrackNumber(
wtf_size_t range_index) const {
DCHECK_LT(range_index, RangeCount());
- return ranges_[range_index].starting_track_number;
+ return ranges_[range_index].start_line;
}
wtf_size_t NGGridBlockTrackCollection::RangeTrackCount(
@@ -443,18 +489,14 @@ wtf_size_t NGGridBlockTrackCollection::RangeCount() const {
NGGridSet::NGGridSet(wtf_size_t track_count)
: track_count_(track_count),
track_size_(Length::Auto(), Length::Auto()),
- growth_limit_(kIndefiniteSize),
- fit_content_limit_(kIndefiniteSize),
- is_infinitely_growable_(false) {}
+ fit_content_limit_(kIndefiniteSize) {}
NGGridSet::NGGridSet(wtf_size_t track_count,
const GridTrackSize& track_size,
bool is_available_size_indefinite)
: track_count_(track_count),
track_size_(track_size),
- growth_limit_(kIndefiniteSize),
- fit_content_limit_(kIndefiniteSize),
- is_infinitely_growable_(false) {
+ fit_content_limit_(kIndefiniteSize) {
if (track_size_.IsFitContent()) {
DCHECK(track_size_.FitContentTrackBreadth().IsLength());
@@ -521,6 +563,12 @@ void NGGridSet::SetBaseSize(LayoutUnit base_size) {
EnsureGrowthLimitIsNotLessThanBaseSize();
}
+void NGGridSet::InitBaseSize(LayoutUnit base_size) {
+ DCHECK_NE(base_size, kIndefiniteSize);
+ base_size_ = base_size;
+ EnsureGrowthLimitIsNotLessThanBaseSize();
+}
+
LayoutUnit NGGridSet::GrowthLimit() const {
DCHECK(!IsGrowthLimitLessThanBaseSize());
return growth_limit_;
@@ -538,7 +586,7 @@ void NGGridSet::SetGrowthLimit(LayoutUnit growth_limit) {
NGGridLayoutAlgorithmTrackCollection::Range::Range(
const NGGridBlockTrackCollection::Range& block_track_range,
wtf_size_t starting_set_index)
- : starting_track_number(block_track_range.starting_track_number),
+ : start_line(block_track_range.start_line),
track_count(block_track_range.track_count),
starting_set_index(starting_set_index),
properties(block_track_range.properties) {}
@@ -567,6 +615,11 @@ NGGridLayoutAlgorithmTrackCollection::NGGridLayoutAlgorithmTrackCollection(
}
}
+NGGridLayoutAlgorithmTrackCollection::NGGridLayoutAlgorithmTrackCollection(
+ const Vector<Range>& ranges,
+ GridTrackSizingDirection direction)
+ : direction_(direction), ranges_(ranges) {}
+
void NGGridLayoutAlgorithmTrackCollection::AppendTrackRange(
const NGGridBlockTrackCollection::Range& block_track_range,
const NGGridTrackList& specified_track_list,
@@ -742,7 +795,7 @@ bool NGGridLayoutAlgorithmTrackCollection::RangeHasTrackSpanProperty(
wtf_size_t NGGridLayoutAlgorithmTrackCollection::RangeTrackNumber(
wtf_size_t range_index) const {
DCHECK_LT(range_index, RangeCount());
- return ranges_[range_index].starting_track_number;
+ return ranges_[range_index].start_line;
}
wtf_size_t NGGridLayoutAlgorithmTrackCollection::RangeTrackCount(
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
index 7b9ce3d9e95..e0650a902d1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
@@ -94,13 +94,27 @@ class CORE_EXPORT NGGridBlockTrackCollection
void SetIsImplicit();
void SetIsCollapsed();
- wtf_size_t starting_track_number;
+ wtf_size_t start_line;
wtf_size_t track_count;
wtf_size_t repeater_index;
wtf_size_t repeater_offset;
TrackSpanProperties properties;
};
+ // This structure represents the grid line boundaries of a repeater or item
+ // placed on the implicit grid. For the latter, a pointer to its respective
+ // range start/end index is provided to cache its value during
+ // |FinalizeRanges|.
+ struct TrackBoundaryToRangePair {
+ explicit TrackBoundaryToRangePair(
+ wtf_size_t grid_line,
+ wtf_size_t* grid_item_range_index_to_cache = nullptr)
+ : grid_line(grid_line),
+ grid_item_range_index_to_cache(grid_item_range_index_to_cache) {}
+ wtf_size_t grid_line;
+ wtf_size_t* grid_item_range_index_to_cache;
+ };
+
explicit NGGridBlockTrackCollection(
GridTrackSizingDirection track_direction = kForColumns);
@@ -111,8 +125,13 @@ class CORE_EXPORT NGGridBlockTrackCollection
const wtf_size_t auto_repetitions,
const wtf_size_t named_grid_area_track_count);
// Ensures that after FinalizeRanges is called, a range will start at the
- // |track_number|, and a range will end at |track_number| + |span_length|
- void EnsureTrackCoverage(wtf_size_t track_number, wtf_size_t span_length);
+ // |track_number|, a range will end at |track_number| + |span_length|.
+ // |grid_item_start_range_index| and |grid_item_end_range_index| will be
+ // written to during |FinalizeRanges|.
+ void EnsureTrackCoverage(wtf_size_t track_number,
+ wtf_size_t span_length,
+ wtf_size_t* grid_item_start_range_index,
+ wtf_size_t* grid_item_end_range_index);
// Build the collection of ranges based on information provided by
// SetSpecifiedTracks and EnsureTrackCoverage.
void FinalizeRanges(wtf_size_t start_offset);
@@ -149,9 +168,10 @@ class CORE_EXPORT NGGridBlockTrackCollection
const NGGridTrackList* implicit_tracks_;
// Starting and ending tracks mark where ranges will start and end.
+ // The corresponding range_index will be written to during |FinalizeRanges|.
// Once the ranges have been built in FinalizeRanges, these are cleared.
- Vector<wtf_size_t> start_lines_;
- Vector<wtf_size_t> end_lines_;
+ Vector<TrackBoundaryToRangePair> start_lines_;
+ Vector<TrackBoundaryToRangePair> end_lines_;
Vector<Range> ranges_;
};
@@ -214,7 +234,11 @@ class CORE_EXPORT NGGridSet {
bool IsInfinitelyGrowable() const { return is_infinitely_growable_; }
void SetBaseSize(LayoutUnit base_size);
+ void InitBaseSize(LayoutUnit base_size);
void SetGrowthLimit(LayoutUnit growth_limit);
+ void InitGrowthLimit(LayoutUnit growth_limit) {
+ growth_limit_ = growth_limit;
+ }
void SetPlannedIncrease(LayoutUnit planned_increase) {
planned_increase_ = planned_increase;
}
@@ -248,13 +272,14 @@ class CORE_EXPORT NGGridLayoutAlgorithmTrackCollection
: public NGGridTrackCollectionBase {
public:
struct Range {
+ Range(const Range& range) = default;
// Copies fields that are the same as in |GridBlockTrackCollection::Range|.
Range(const NGGridBlockTrackCollection::Range& block_track_range,
wtf_size_t starting_set_index);
bool IsCollapsed() const;
- wtf_size_t starting_track_number;
+ wtf_size_t start_line;
wtf_size_t track_count;
wtf_size_t starting_set_index;
wtf_size_t set_count;
@@ -313,6 +338,11 @@ class CORE_EXPORT NGGridLayoutAlgorithmTrackCollection
const NGGridBlockTrackCollection& block_track_collection,
bool is_available_size_indefinite);
+ // TODO(ansollan): Refactor the track collection abstraction so that we only
+ // pass what is needed for placing in flow and out of flow items.
+ NGGridLayoutAlgorithmTrackCollection(const Vector<Range>& ranges,
+ GridTrackSizingDirection direction);
+
wtf_size_t EndLineOfImplicitGrid() const;
bool IsGridLineWithinImplicitGrid(wtf_size_t grid_line) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc
index 757f379ca1d..df15e0d3339 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc
@@ -64,7 +64,7 @@ class NGGridTrackCollectionBaseTest : public NGGridTrackCollectionBase {
class NGGridTrackCollectionTest : public NGLayoutTest {
protected:
- Vector<GridTrackSize> CreateTrackSizes(wtf_size_t track_count) {
+ Vector<GridTrackSize, 1> CreateTrackSizes(wtf_size_t track_count) {
return {track_count, GridTrackSize(Length::Auto())};
}
@@ -250,9 +250,18 @@ TEST_F(NGGridTrackCollectionTest, TestNGGridBlockTrackCollectionImplicit) {
/* start_offset */ 0,
/* auto_repeat_count */ 3,
/* named_grid_area_track_count */ 0);
- block_collection.EnsureTrackCoverage(3, 40);
- block_collection.EnsureTrackCoverage(3, 40);
+ wtf_size_t range1_start;
+ wtf_size_t range1_end;
+ wtf_size_t range2_start;
+ wtf_size_t range2_end;
+ block_collection.EnsureTrackCoverage(3, 40, &range1_start, &range1_end);
+ block_collection.EnsureTrackCoverage(3, 40, &range2_start, &range2_end);
block_collection.FinalizeRanges(/* start_offset */ 0);
+ EXPECT_EQ(1u, range1_start);
+ EXPECT_EQ(4u, range1_end);
+ EXPECT_EQ(1u, range2_start);
+ EXPECT_EQ(4u, range2_end);
+
NGGridTrackCollectionBase::RangeRepeatIterator iterator(&block_collection,
0u);
EXPECT_RANGE(0u, 3u, iterator);
@@ -335,7 +344,7 @@ TEST_F(NGGridTrackCollectionTest,
wtf_size_t expected_set_count = 0;
NGGridTrackList explicit_tracks, implicit_tracks;
for (wtf_size_t set_count : set_counts) {
- Vector<GridTrackSize> track_sizes;
+ Vector<GridTrackSize, 1> track_sizes;
for (wtf_size_t i = 0; i < set_count; ++i)
track_sizes.emplace_back(GridLength(expected_set_count++));
ASSERT_TRUE(explicit_tracks.AddRepeater(track_sizes, 1));
@@ -386,9 +395,9 @@ TEST_F(NGGridTrackCollectionTest,
NGGridTrackList explicit_tracks, implicit_tracks;
// repeat(3, 1px 2px 3px)
- Vector<GridTrackSize> track_sizes = {GridTrackSize(Length::Fixed(1)),
- GridTrackSize(Length::Fixed(2)),
- GridTrackSize(Length::Fixed(3))};
+ Vector<GridTrackSize, 1> track_sizes = {GridTrackSize(Length::Fixed(1)),
+ GridTrackSize(Length::Fixed(2)),
+ GridTrackSize(Length::Fixed(3))};
ASSERT_TRUE(explicit_tracks.AddRepeater(track_sizes, 3));
// repeat(auto-fit, 4px 5px)
@@ -403,12 +412,29 @@ TEST_F(NGGridTrackCollectionTest,
/* start_offset */ 0,
/* auto_repeat_count */ 5,
/* named_grid_area_track_count */ 0);
- block_collection.EnsureTrackCoverage(2, 4);
- block_collection.EnsureTrackCoverage(12, 4);
- block_collection.EnsureTrackCoverage(17, 3);
- block_collection.EnsureTrackCoverage(22, 5);
+ wtf_size_t range1_start;
+ wtf_size_t range1_end;
+ wtf_size_t range2_start;
+ wtf_size_t range2_end;
+ wtf_size_t range3_start;
+ wtf_size_t range3_end;
+ wtf_size_t range4_start;
+ wtf_size_t range4_end;
+ block_collection.EnsureTrackCoverage(2, 4, &range1_start, &range1_end);
+ block_collection.EnsureTrackCoverage(12, 4, &range2_start, &range2_end);
+ block_collection.EnsureTrackCoverage(17, 3, &range3_start, &range3_end);
+ block_collection.EnsureTrackCoverage(22, 5, &range4_start, &range4_end);
block_collection.FinalizeRanges(/* start_offset */ 0);
+ EXPECT_EQ(1u, range1_start);
+ EXPECT_EQ(1u, range1_end);
+ EXPECT_EQ(4u, range2_start);
+ EXPECT_EQ(4u, range2_end);
+ EXPECT_EQ(6u, range3_start);
+ EXPECT_EQ(7u, range3_end);
+ EXPECT_EQ(9u, range4_start);
+ EXPECT_EQ(9u, range4_end);
+
NGGridLayoutAlgorithmTrackCollection algorithm_collection(
block_collection, /* is_content_box_size_defined */ false);
NGGridTrackCollectionBase::RangeRepeatIterator range_iterator =
@@ -503,7 +529,7 @@ TEST_F(NGGridTrackCollectionTest,
NGGridTrackList explicit_tracks, implicit_tracks;
// Explicit grid: 1px 2px 3px 4px
- Vector<GridTrackSize> track_sizes = {
+ Vector<GridTrackSize, 1> track_sizes = {
GridTrackSize(Length::Fixed(1)), GridTrackSize(Length::Fixed(2)),
GridTrackSize(Length::Fixed(3)), GridTrackSize(Length::Fixed(4))};
ASSERT_TRUE(explicit_tracks.AddRepeater(track_sizes, 1));
@@ -521,9 +547,17 @@ TEST_F(NGGridTrackCollectionTest,
/* start_offset */ 0,
/* auto_repeat_count */ 0,
/* named_grid_area_track_count */ 0);
- block_collection.EnsureTrackCoverage(2, 13);
- block_collection.EnsureTrackCoverage(23, 2);
+ wtf_size_t range1_start;
+ wtf_size_t range1_end;
+ wtf_size_t range2_start;
+ wtf_size_t range2_end;
+ block_collection.EnsureTrackCoverage(2, 13, &range1_start, &range1_end);
+ block_collection.EnsureTrackCoverage(23, 2, &range2_start, &range2_end);
block_collection.FinalizeRanges(/* start_offset */ 0);
+ EXPECT_EQ(1u, range1_start);
+ EXPECT_EQ(2u, range1_end);
+ EXPECT_EQ(4u, range2_start);
+ EXPECT_EQ(4u, range2_end);
NGGridLayoutAlgorithmTrackCollection algorithm_collection(
block_collection, /* is_content_box_size_defined */ false);
@@ -587,7 +621,7 @@ TEST_F(NGGridTrackCollectionTest,
NGGridTrackList explicit_tracks, implicit_tracks;
// repeat(2, min-content 1fr 2px 3px)
- Vector<GridTrackSize> track_sizes = {
+ Vector<GridTrackSize, 1> track_sizes = {
GridTrackSize(Length::MinContent()), GridTrackSize(GridLength(1.0)),
GridTrackSize(Length::Fixed(2)), GridTrackSize(Length::Fixed(3))};
ASSERT_TRUE(explicit_tracks.AddRepeater(track_sizes, 2));
@@ -598,10 +632,20 @@ TEST_F(NGGridTrackCollectionTest,
/* start_offset */ 0,
/* auto_repeat_count */ 0,
/* named_grid_area_track_count */ 0);
- block_collection.EnsureTrackCoverage(1, 2);
- block_collection.EnsureTrackCoverage(7, 4);
+ wtf_size_t range1_start;
+ wtf_size_t range1_end;
+ wtf_size_t range2_start;
+ wtf_size_t range2_end;
+ block_collection.EnsureTrackCoverage(1, 2, &range1_start, &range1_end);
+ block_collection.EnsureTrackCoverage(7, 4, &range2_start, &range2_end);
+
block_collection.FinalizeRanges(/* start_offset */ 0);
+ EXPECT_EQ(1u, range1_start);
+ EXPECT_EQ(1u, range1_end);
+ EXPECT_EQ(3u, range2_start);
+ EXPECT_EQ(4u, range2_end);
+
NGGridLayoutAlgorithmTrackCollection algorithm_collection(
block_collection, /* is_content_box_size_defined */ false);
NGGridTrackCollectionBase::RangeRepeatIterator range_iterator =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.cc
new file mode 100644
index 00000000000..7c1c972a67a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.cc
@@ -0,0 +1,232 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.h"
+
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
+
+namespace blink {
+
+namespace {
+
+// std::pair.first points to the start linebox fragment.
+// std::pair.second points to the end linebox fragment.
+// TODO(layout-dev): Update this to a struct for increased readability.
+using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*,
+ const NGPhysicalLineBoxFragment*>;
+
+// |fragment_converter| is the converter for the current containing block
+// fragment, and |containing_block_converter| is the converter of the
+// containing block where all fragments are stacked. These are used to
+// convert offsets to be relative to the full containing block rather
+// than the current containing block fragment.
+template <class Items>
+void GatherInlineContainerFragmentsFromItems(
+ const Items& items,
+ const PhysicalOffset& box_offset,
+ InlineContainingBlockUtils::InlineContainingBlockMap*
+ inline_containing_block_map,
+ HashMap<const LayoutObject*, LineBoxPair>* containing_linebox_map,
+ const WritingModeConverter* fragment_converter = nullptr,
+ const WritingModeConverter* containing_block_converter = nullptr) {
+ DCHECK_EQ(!!fragment_converter, !!containing_block_converter);
+ const NGPhysicalLineBoxFragment* linebox = nullptr;
+ for (const auto& item : items) {
+ // Track the current linebox.
+ if (const NGPhysicalLineBoxFragment* current_linebox =
+ item->LineBoxFragment()) {
+ linebox = current_linebox;
+ continue;
+ }
+
+ // We only care about inlines which have generated a box fragment.
+ const NGPhysicalBoxFragment* box = item->BoxFragment();
+ if (!box)
+ continue;
+
+ // The key for the inline is the continuation root if it exists.
+ const LayoutObject* key = box->GetLayoutObject();
+ if (key->IsLayoutInline() && key->GetNode())
+ key = key->ContinuationRoot();
+
+ // See if we need the containing block information for this inline.
+ auto it = inline_containing_block_map->find(key);
+ if (it == inline_containing_block_map->end())
+ continue;
+
+ absl::optional<InlineContainingBlockUtils::InlineContainingBlockGeometry>&
+ containing_block_geometry = it->value;
+ LineBoxPair& containing_lineboxes =
+ containing_linebox_map->insert(key, LineBoxPair{nullptr, nullptr})
+ .stored_value->value;
+ DCHECK(containing_block_geometry.has_value() ||
+ !containing_lineboxes.first);
+
+ PhysicalRect fragment_rect = item->RectInContainerFragment();
+ if (fragment_converter) {
+ // Convert the offset to be relative to the containing block such
+ // that all containing block fragments are stacked.
+ fragment_rect.offset = containing_block_converter->ToPhysical(
+ fragment_converter->ToLogical(fragment_rect.offset,
+ fragment_rect.size),
+ fragment_rect.size);
+ }
+ fragment_rect.offset += box_offset;
+
+ if (containing_lineboxes.first == linebox) {
+ // Unite the start rect with the fragment's rect.
+ containing_block_geometry->start_fragment_union_rect.Unite(fragment_rect);
+ } else if (!containing_lineboxes.first) {
+ DCHECK(!containing_lineboxes.second);
+ // This is the first linebox we've encountered, initialize the containing
+ // block geometry.
+ containing_lineboxes.first = linebox;
+ containing_lineboxes.second = linebox;
+ containing_block_geometry =
+ InlineContainingBlockUtils::InlineContainingBlockGeometry{
+ fragment_rect, fragment_rect,
+ containing_block_geometry->relative_offset};
+ }
+
+ if (containing_lineboxes.second == linebox) {
+ // Unite the end rect with the fragment's rect.
+ containing_block_geometry->end_fragment_union_rect.Unite(fragment_rect);
+ } else if (!linebox->IsEmptyLineBox()) {
+ // We've found a new "end" linebox, update the containing block geometry.
+ containing_lineboxes.second = linebox;
+ containing_block_geometry->end_fragment_union_rect = fragment_rect;
+ }
+ }
+}
+
+} // namespace
+
+void InlineContainingBlockUtils::ComputeInlineContainerGeometry(
+ InlineContainingBlockMap* inline_containing_block_map,
+ NGBoxFragmentBuilder* container_builder) {
+ if (inline_containing_block_map->IsEmpty())
+ return;
+
+ // This function requires that we have the final size of the fragment set
+ // upon the builder.
+ DCHECK_GE(container_builder->InlineSize(), LayoutUnit());
+ DCHECK_GE(container_builder->FragmentBlockSize(), LayoutUnit());
+
+#if DCHECK_IS_ON()
+ // Make sure all entries are a continuation root.
+ for (const auto& entry : *inline_containing_block_map)
+ DCHECK_EQ(entry.key, entry.key->ContinuationRoot());
+#endif
+
+ HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map;
+
+ if (container_builder->ItemsBuilder()) {
+ // To access the items correctly we need to convert them to the physical
+ // coordinate space.
+ DCHECK_EQ(container_builder->ItemsBuilder()->GetWritingMode(),
+ container_builder->GetWritingMode());
+ DCHECK_EQ(container_builder->ItemsBuilder()->Direction(),
+ container_builder->Direction());
+ GatherInlineContainerFragmentsFromItems(
+ container_builder->ItemsBuilder()->Items(ToPhysicalSize(
+ container_builder->Size(), container_builder->GetWritingMode())),
+ PhysicalOffset(), inline_containing_block_map, &containing_linebox_map);
+ return;
+ }
+
+ // If we have children which are anonymous block, we might contain split
+ // inlines, this can occur in the following example:
+ // <div>
+ // Some text <span style="position: relative;">text
+ // <div>block</div>
+ // text </span> text.
+ // </div>
+ for (const auto& child : container_builder->Children()) {
+ if (!child.fragment->IsAnonymousBlock())
+ continue;
+
+ const auto& child_fragment = To<NGPhysicalBoxFragment>(*child.fragment);
+ const auto* items = child_fragment.Items();
+ if (!items)
+ continue;
+
+ const PhysicalOffset child_offset = child.offset.ConvertToPhysical(
+ container_builder->GetWritingDirection(),
+ ToPhysicalSize(container_builder->Size(),
+ container_builder->GetWritingMode()),
+ child_fragment.Size());
+ GatherInlineContainerFragmentsFromItems(items->Items(), child_offset,
+ inline_containing_block_map,
+ &containing_linebox_map);
+ }
+}
+
+void InlineContainingBlockUtils::ComputeInlineContainerGeometryForFragmentainer(
+ const LayoutBox* box,
+ PhysicalSize accumulated_containing_block_size,
+ InlineContainingBlockMap* inline_containing_block_map) {
+ if (inline_containing_block_map->IsEmpty())
+ return;
+#if DCHECK_IS_ON()
+ // Make sure all entries are a continuation root.
+ for (const auto& entry : *inline_containing_block_map)
+ DCHECK_EQ(entry.key, entry.key->ContinuationRoot());
+#endif
+
+ WritingDirectionMode writing_direction =
+ box->StyleRef().GetWritingDirection();
+ WritingModeConverter containing_block_converter = WritingModeConverter(
+ writing_direction, accumulated_containing_block_size);
+
+ // Used to keep track of the block contribution from previous fragments
+ // so that the child offsets are relative to the top of the containing block,
+ // as if all fragments are stacked.
+ LayoutUnit current_block_offset;
+
+ HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map;
+ for (auto& physical_fragment : box->PhysicalFragments()) {
+ LogicalOffset logical_offset(LayoutUnit(), current_block_offset);
+ PhysicalOffset offset = containing_block_converter.ToPhysical(
+ logical_offset, accumulated_containing_block_size);
+
+ WritingModeConverter current_fragment_converter =
+ WritingModeConverter(writing_direction, physical_fragment.Size());
+ if (physical_fragment.HasItems()) {
+ GatherInlineContainerFragmentsFromItems(
+ physical_fragment.Items()->Items(), offset,
+ inline_containing_block_map, &containing_linebox_map,
+ &current_fragment_converter, &containing_block_converter);
+ } else {
+ // If we have children which are anonymous block, we might contain split
+ // inlines, this can occur in the following example:
+ // <div>
+ // Some text <span style="position: relative;">text
+ // <div>block</div>
+ // text </span> text.
+ // </div>
+ for (const auto& child : physical_fragment.Children()) {
+ if (!child.fragment->IsAnonymousBlock())
+ continue;
+
+ const auto& child_fragment = To<NGPhysicalBoxFragment>(*child.fragment);
+ if (!child_fragment.HasItems())
+ continue;
+
+ GatherInlineContainerFragmentsFromItems(
+ child_fragment.Items()->Items(), child.offset + offset,
+ inline_containing_block_map, &containing_linebox_map,
+ &current_fragment_converter, &containing_block_converter);
+ }
+ }
+ if (auto* break_token =
+ To<NGBlockBreakToken>(physical_fragment.BreakToken()))
+ current_block_offset = break_token->ConsumedBlockSize();
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.h
new file mode 100644
index 00000000000..a5961895a2a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.h
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_INLINE_CONTAINING_BLOCK_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_INLINE_CONTAINING_BLOCK_UTILS_H_
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+
+namespace blink {
+
+class LayoutBox;
+class LayoutObject;
+class NGBoxFragmentBuilder;
+
+class InlineContainingBlockUtils {
+ STATIC_ONLY(InlineContainingBlockUtils);
+
+ public:
+ // Inline containing block geometry is defined by two rectangles, generated
+ // by fragments of the LayoutInline.
+ struct InlineContainingBlockGeometry {
+ DISALLOW_NEW();
+ // Union of fragments generated on the first line.
+ PhysicalRect start_fragment_union_rect;
+ // Union of fragments generated on the last line.
+ PhysicalRect end_fragment_union_rect;
+ // The accumulated relative offset of the inline container to be applied to
+ // any descendants after fragmentation.
+ LogicalOffset relative_offset;
+ };
+
+ using InlineContainingBlockMap =
+ HashMap<const LayoutObject*,
+ absl::optional<InlineContainingBlockGeometry>>;
+
+ // Computes the geometry required for any inline containing blocks.
+ // |inline_containing_block_map| is a map whose keys specify which objects we
+ // need to calculate inline containing block geometry for. |container_builder|
+ // is the builder of the containing block of the inline containers.
+ static void ComputeInlineContainerGeometry(
+ InlineContainingBlockMap* inline_containing_block_map,
+ NGBoxFragmentBuilder* container_builder);
+
+ // Computes the geometry required for any inline containing blocks inside a
+ // fragmentation context. |box| is the containing block the inline containers
+ // are descendants of. |accumulated_containing_block_size| is the size of the
+ // containing block, including the total block size from all fragmentainers.
+ // |inline_containing_block_map| is a map whose keys specify which objects we
+ // need to calculate inline containing block geometry for.
+ static void ComputeInlineContainerGeometryForFragmentainer(
+ const LayoutBox* box,
+ PhysicalSize accumulated_containing_block_size,
+ InlineContainingBlockMap* inline_containing_block_map);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_INLINE_CONTAINING_BLOCK_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_counter.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_counter.h
new file mode 100644
index 00000000000..72c57c937e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_counter.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_COUNTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_COUNTER_H_
+
+#include "third_party/blink/renderer/core/layout/layout_counter.h"
+
+namespace blink {
+
+// This class is identical to |LayoutCounter| except for this class returns
+// true for |IsLayoutNGObject()| and |NGInlineItem| support, to become child of
+// |LayoutNGTextCombine|. See also |LayoutNGWordBreak|.
+// TODO(yosin): Once we get rid of |IsLayoutNGObject()|, we should unify this
+// class |LayoutCounter|.
+class CORE_EXPORT LayoutNGCounter final : public LayoutCounter {
+ public:
+ explicit LayoutNGCounter(PseudoElement& pseudo,
+ const CounterContentData& counter)
+ : LayoutCounter(pseudo, counter) {}
+
+ bool IsLayoutNGObject() const final {
+ NOT_DESTROYED();
+ return true;
+ }
+
+ private:
+ const base::span<NGInlineItem>* GetNGInlineItems() const final {
+ NOT_DESTROYED();
+ return &inline_items_;
+ }
+ base::span<NGInlineItem>* GetNGInlineItems() final {
+ NOT_DESTROYED();
+ return &inline_items_;
+ }
+
+ base::span<NGInlineItem> inline_items_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_COUNTER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc
new file mode 100644
index 00000000000..8cfd36f83cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc
@@ -0,0 +1,277 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
+
+#include "third_party/blink/renderer/core/css/resolver/style_adjuster.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
+#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.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/transforms/affine_transform.h"
+
+namespace blink {
+
+LayoutNGTextCombine::LayoutNGTextCombine() : LayoutNGBlockFlow(nullptr) {
+ SetIsAtomicInlineLevel(true);
+}
+
+LayoutNGTextCombine::~LayoutNGTextCombine() = default;
+
+// static
+LayoutNGTextCombine* LayoutNGTextCombine::CreateAnonymous(
+ LayoutText* text_child) {
+ DCHECK(ShouldBeParentOf(*text_child)) << text_child;
+ auto* const layout_object = new LayoutNGTextCombine();
+ auto& document = text_child->GetDocument();
+ layout_object->SetDocumentForAnonymous(&document);
+ scoped_refptr<ComputedStyle> new_style =
+ document.GetStyleResolver().CreateAnonymousStyleWithDisplay(
+ text_child->StyleRef(), EDisplay::kInlineBlock);
+ StyleAdjuster::AdjustStyleForTextCombine(*new_style);
+ layout_object->SetStyle(std::move(new_style));
+ layout_object->AddChild(text_child);
+ LayoutNGTextCombine::AssertStyleIsValid(text_child->StyleRef());
+ return layout_object;
+}
+
+String LayoutNGTextCombine::GetTextContent() const {
+ DCHECK(!NeedsCollectInlines() && HasNGInlineNodeData()) << this;
+ return GetNGInlineNodeData()->ItemsData(false).text_content;
+}
+
+// static
+void LayoutNGTextCombine::AssertStyleIsValid(const ComputedStyle& style) {
+ // See also |StyleAdjuster::AdjustStyleForTextCombine()|.
+#if DCHECK_IS_ON()
+ DCHECK_EQ(style.GetTextDecoration(), TextDecoration::kNone);
+ DCHECK_EQ(style.GetTextEmphasisMark(), TextEmphasisMark::kNone);
+ DCHECK_EQ(style.GetWritingMode(), WritingMode::kHorizontalTb);
+ DCHECK_EQ(style.LetterSpacing(), 0.0f);
+ DCHECK_EQ(style.TextDecorationsInEffect(), TextDecoration::kNone);
+ DCHECK_EQ(style.GetFont().GetFontDescription().Orientation(),
+ FontOrientation::kHorizontal);
+#endif
+}
+
+bool LayoutNGTextCombine::IsOfType(LayoutObjectType type) const {
+ NOT_DESTROYED();
+ return type == kLayoutObjectNGTextCombine ||
+ LayoutNGBlockFlow::IsOfType(type);
+}
+
+float LayoutNGTextCombine::DesiredWidth() const {
+ DCHECK_EQ(StyleRef().GetFont().GetFontDescription().Orientation(),
+ FontOrientation::kHorizontal);
+ const float one_em = StyleRef().ComputedFontSize();
+ if (EnumHasFlags(Parent()->StyleRef().TextDecorationsInEffect(),
+ TextDecoration::kUnderline | TextDecoration::kOverline))
+ return one_em;
+ // Allow em + 10% margin if there are no underline and overeline for
+ // better looking. This isn't specified in the spec[1], but EPUB group
+ // wants this.
+ // [1] https://www.w3.org/TR/css-writing-modes-3/
+ constexpr float kTextCombineMargin = 1.1f;
+ return one_em * kTextCombineMargin;
+}
+
+float LayoutNGTextCombine::ComputeInlineSpacing() const {
+ DCHECK_EQ(StyleRef().GetFont().GetFontDescription().Orientation(),
+ FontOrientation::kHorizontal);
+ DCHECK(scale_x_);
+ const LayoutUnit line_height = StyleRef().GetFontHeight().LineHeight();
+ return (line_height - DesiredWidth()) / 2;
+}
+
+PhysicalOffset LayoutNGTextCombine::ApplyScaleX(
+ const PhysicalOffset& offset) const {
+ DCHECK(scale_x_.has_value());
+ const float spacing = ComputeInlineSpacing();
+ return PhysicalOffset(LayoutUnit(offset.left * *scale_x_ + spacing),
+ offset.top);
+}
+
+PhysicalRect LayoutNGTextCombine::ApplyScaleX(const PhysicalRect& rect) const {
+ DCHECK(scale_x_.has_value());
+ return PhysicalRect(ApplyScaleX(rect.offset), ApplyScaleX(rect.size));
+}
+
+PhysicalSize LayoutNGTextCombine::ApplyScaleX(const PhysicalSize& size) const {
+ DCHECK(scale_x_.has_value());
+ return PhysicalSize(LayoutUnit(size.width * *scale_x_), size.height);
+}
+
+PhysicalOffset LayoutNGTextCombine::UnapplyScaleX(
+ const PhysicalOffset& offset) const {
+ DCHECK(scale_x_.has_value());
+ const float spacing = ComputeInlineSpacing();
+ return PhysicalOffset(LayoutUnit((offset.left - spacing) / *scale_x_),
+ offset.top);
+}
+
+PhysicalOffset LayoutNGTextCombine::AdjustOffsetForHitTest(
+ const PhysicalOffset& offset_in_container) const {
+ if (!scale_x_)
+ return offset_in_container;
+ return UnapplyScaleX(offset_in_container);
+}
+
+PhysicalOffset LayoutNGTextCombine::AdjustOffsetForLocalCaretRect(
+ const PhysicalOffset& offset_in_container) const {
+ if (!scale_x_)
+ return offset_in_container;
+ return ApplyScaleX(offset_in_container);
+}
+
+PhysicalRect LayoutNGTextCombine::AdjustRectForBoundingBox(
+ const PhysicalRect& rect) const {
+ if (!scale_x_)
+ return rect;
+ // See "text-combine-upright-compression-007.html"
+ return ApplyScaleX(rect);
+}
+
+PhysicalRect LayoutNGTextCombine::ComputeTextBoundsRectForHitTest(
+ const NGFragmentItem& text_item,
+ const PhysicalOffset& inline_root_offset) const {
+ DCHECK(text_item.IsText()) << text_item;
+ PhysicalRect rect = text_item.SelfInkOverflow();
+ rect.Move(text_item.OffsetInContainerFragment());
+ rect = AdjustRectForBoundingBox(rect);
+ rect.Move(inline_root_offset);
+ return rect;
+}
+
+void LayoutNGTextCombine::ResetLayout() {
+ compressed_font_.reset();
+ scale_x_.reset();
+}
+
+LayoutUnit LayoutNGTextCombine::AdjustTextLeftForPaint(
+ LayoutUnit position) const {
+ if (!scale_x_)
+ return position;
+ const float spacing = ComputeInlineSpacing();
+ return LayoutUnit(position + spacing / *scale_x_);
+}
+
+LayoutUnit LayoutNGTextCombine::AdjustTextTopForPaint(
+ LayoutUnit text_top) const {
+ DCHECK_EQ(StyleRef().GetFont().GetFontDescription().Orientation(),
+ FontOrientation::kHorizontal);
+ const SimpleFontData& font_data = *StyleRef().GetFont().PrimaryFont();
+ const float internal_leading = font_data.InternalLeading();
+ const float half_leading = internal_leading / 2;
+ const int ascent = font_data.GetFontMetrics().Ascent();
+ return LayoutUnit(text_top + ascent - half_leading);
+}
+
+AffineTransform LayoutNGTextCombine::ComputeAffineTransformForPaint(
+ const PhysicalOffset& paint_offset) const {
+ DCHECK(NeedsAffineTransformInPaint());
+ AffineTransform matrix;
+ if (UsingSyntheticOblique()) {
+ const LayoutUnit text_left = AdjustTextLeftForPaint(paint_offset.left);
+ const LayoutUnit text_top = AdjustTextTopForPaint(paint_offset.top);
+ matrix.Translate(text_left, text_top);
+ // TODO(yosin): We should use angle specified in CSS instead of
+ // constant value -15deg. See also |DrawBlobs()| in [1] for vertical
+ // upright oblique.
+ // [1] "third_party/blink/renderer/platform/fonts/font.cc"
+ constexpr float kSlantAngle = -15.0f;
+ matrix.SkewY(kSlantAngle);
+ matrix.Translate(-text_left, -text_top);
+ }
+ if (scale_x_.has_value()) {
+ matrix.Translate(paint_offset.left, paint_offset.top);
+ matrix.Scale(*scale_x_, 1.0f);
+ matrix.Translate(-paint_offset.left, -paint_offset.top);
+ }
+ return matrix;
+}
+
+bool LayoutNGTextCombine::NeedsAffineTransformInPaint() const {
+ return scale_x_.has_value() || UsingSyntheticOblique();
+}
+
+PhysicalRect LayoutNGTextCombine::ComputeTextFrameRect(
+ const PhysicalOffset paint_offset) const {
+ const ComputedStyle& style = Parent()->StyleRef();
+ DCHECK(style.GetFont().GetFontDescription().IsVerticalBaseline());
+
+ // Because we rotate the GraphicsContext to match the logical direction,
+ // transpose the |text_frame_rect| to match to it.
+ // See also |NGTextFragmentPainter::Paint()|
+ const LayoutUnit one_em = style.ComputedFontSizeAsFixed();
+ const FontHeight text_metrics = style.GetFontHeight();
+ const LayoutUnit line_height = text_metrics.LineHeight();
+ return PhysicalRect(PhysicalOffset(LayoutUnit(paint_offset.left),
+ LayoutUnit(paint_offset.top)),
+ PhysicalSize(one_em, line_height));
+}
+
+PhysicalRect LayoutNGTextCombine::RecalcContentsInkOverflow() const {
+ const ComputedStyle& style = Parent()->StyleRef();
+ DCHECK(style.GetFont().GetFontDescription().IsVerticalBaseline());
+
+ // Note: |text_rect| and |ink_overflow| are in logical direction.
+ const PhysicalRect text_rect = ComputeTextFrameRect(PhysicalOffset());
+ LayoutRect ink_overflow = text_rect.ToLayoutRect();
+
+ if (!style.AppliedTextDecorations().IsEmpty()) {
+ const LayoutRect decoration_rect =
+ NGInkOverflow::ComputeTextDecorationOverflow(style, ink_overflow);
+ ink_overflow.Unite(decoration_rect);
+ }
+
+ if (style.GetTextEmphasisMark() != TextEmphasisMark::kNone) {
+ ink_overflow = NGInkOverflow::ComputeEmphasisMarkOverflow(
+ style, text_rect.size, ink_overflow);
+ }
+
+ PhysicalRect local_ink_overflow =
+ WritingModeConverter({style.GetWritingMode(), TextDirection::kLtr},
+ text_rect.size)
+ .ToPhysical(LogicalRect(ink_overflow));
+ local_ink_overflow.ExpandEdgesToPixelBoundaries();
+ return local_ink_overflow;
+}
+
+IntRect LayoutNGTextCombine::VisualRectForPaint(
+ const PhysicalOffset& paint_offset) const {
+ PhysicalRect ink_overflow = CurrentFragment()->InkOverflow();
+ ink_overflow.Move(paint_offset);
+ return EnclosingIntRect(ink_overflow);
+}
+
+void LayoutNGTextCombine::SetScaleX(float new_scale_x) {
+ DCHECK_GT(new_scale_x, 0.0f);
+ DCHECK(!scale_x_.has_value());
+ DCHECK(!compressed_font_.has_value());
+ // Note: Even if rounding, e.g. LayoutUnit::FromFloatRound(), we still have
+ // gap between painted characters in text-combine-upright-value-all-002.html
+ scale_x_ = new_scale_x;
+}
+
+void LayoutNGTextCombine::SetCompressedFont(const Font& font) {
+ DCHECK(!compressed_font_.has_value());
+ DCHECK(!scale_x_.has_value());
+ compressed_font_ = font;
+}
+
+bool LayoutNGTextCombine::UsingSyntheticOblique() const {
+ return Parent()
+ ->StyleRef()
+ .GetFont()
+ .GetFontDescription()
+ .IsSyntheticOblique();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h
new file mode 100644
index 00000000000..7440a15b25b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h
@@ -0,0 +1,132 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_TEXT_COMBINE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_TEXT_COMBINE_H_
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
+
+namespace blink {
+
+class AffineTransform;
+class NGFragmentItem;
+
+// The layout object for the element having "text-combine-upright:all" in
+// vertical writing mode, e.g. <i style="text-upright:all"><b>12</b>34<i>.
+// Note: When the element is in horizontal writing mode, we don't use this.
+// Note: Children of this class must be |LayoutText| associated to |Text| node.
+class CORE_EXPORT LayoutNGTextCombine final : public LayoutNGBlockFlow {
+ public:
+ // Note: Mark constructor public for |MakeGarbageCollected|. We should not
+ // call this directly.
+ LayoutNGTextCombine();
+ ~LayoutNGTextCombine() override;
+
+ float DesiredWidth() const;
+ String GetTextContent() const;
+
+ // Compressed font
+ const Font& CompressedFont() const { return compressed_font_.value(); }
+ bool UsesCompressedFont() const { return compressed_font_.has_value(); }
+ void SetCompressedFont(const Font& font);
+
+ // Scaling
+
+ // Map scaled |offset_in_container| to non-scaled offset if |this| uses
+ // scale x, otherwise return |offset_in_container|.
+ PhysicalOffset AdjustOffsetForHitTest(
+ const PhysicalOffset& offset_in_container) const;
+
+ // Map non-scaled |offset_in_container| to scaled offset if |this| uses
+ // scale x, otherwise return |offset_in_container|.
+ PhysicalOffset AdjustOffsetForLocalCaretRect(
+ const PhysicalOffset& offset_in_container) const;
+
+ // Maps non-scaled |rect| to scaled rect for
+ // * |LayoutText::PhysicalLinesBoundingBox()| used by
+ // |LayoutObject::DebugRect()|, intersection observer, and scroll anchor.
+ // * |NGFragmentItem::RecalcInkOverflow()| for line box
+ // * |NGLayoutOverflowCalculator::AddItemsInternal()| for line box.
+ // * |NGPhysicalFragment::AddOutlineRectsForCursor()|
+ // * |NGPhysicalFragment::AddScrollableOverflowForInlineChild()|
+ PhysicalRect AdjustRectForBoundingBox(const PhysicalRect& rect) const;
+
+ PhysicalRect ComputeTextBoundsRectForHitTest(
+ const NGFragmentItem& text_item,
+ const PhysicalOffset& inline_root_offset) const;
+
+ // Returns ink overflow for text decorations and emphasis mark.
+ PhysicalRect RecalcContentsInkOverflow() const;
+
+ void ResetLayout();
+ void SetScaleX(float new_scale_x);
+ bool UsesScaleX() const { return scale_x_.has_value(); }
+
+ // Painting
+ // |AdjustText{Left,Top}()| are called within affine transformed
+ // |GraphicsContext|, e.g. |NGTextFragmentPainter::Paint()|.
+ LayoutUnit AdjustTextLeftForPaint(LayoutUnit text_left) const;
+ LayoutUnit AdjustTextTopForPaint(LayoutUnit text_top) const;
+
+ AffineTransform ComputeAffineTransformForPaint(
+ const PhysicalOffset& paint_offset) const;
+ bool NeedsAffineTransformInPaint() const;
+
+ // Returns text frame rect, in logical direction, used with text painters.
+ PhysicalRect ComputeTextFrameRect(const PhysicalOffset paint_offset) const;
+
+ // Returns visual rect for painting emphasis mark and text decoration for
+ // |NGBoxFragmentPainter|.
+ IntRect VisualRectForPaint(const PhysicalOffset& paint_offset) const;
+
+ static void AssertStyleIsValid(const ComputedStyle& style);
+
+ // Create anonymous wrapper having |text_child|.
+ static LayoutNGTextCombine* CreateAnonymous(LayoutText* text_child);
+
+ // Returns true if |layout_object| is a child of |LayoutNGTextCombine|.
+ static bool ShouldBeParentOf(const LayoutObject& layout_object);
+
+ private:
+ bool IsOfType(LayoutObjectType) const override;
+ const char* GetName() const override { return "LayoutNGTextCombine"; }
+
+ // Helper functions for scaling.
+ PhysicalOffset ApplyScaleX(const PhysicalOffset& offset) const;
+ PhysicalRect ApplyScaleX(const PhysicalRect& rect) const;
+ PhysicalSize ApplyScaleX(const PhysicalSize& offset) const;
+ PhysicalOffset UnapplyScaleX(const PhysicalOffset& offset) const;
+
+ float ComputeInlineSpacing() const;
+ bool UsingSyntheticOblique() const;
+
+ // |compressed_font_| hold width variant of |StyleRef().GetFont()|.
+ absl::optional<Font> compressed_font_;
+
+ // |scale_x_| holds scale factor to width of text content to 1em. When we
+ // use |scale_x_|, we use |StyleRef().GetFont()| instead of compressed font.
+ absl::optional<float> scale_x_;
+};
+
+// static
+inline bool LayoutNGTextCombine::ShouldBeParentOf(
+ const LayoutObject& layout_object) {
+ if (LIKELY(layout_object.IsHorizontalWritingMode()) ||
+ !layout_object.IsText())
+ return false;
+ return UNLIKELY(layout_object.StyleRef().HasTextCombine()) &&
+ layout_object.IsLayoutNGObject();
+}
+
+template <>
+struct DowncastTraits<LayoutNGTextCombine> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsLayoutNGTextCombine();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_TEXT_COMBINE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc
new file mode 100644
index 00000000000..ecd99b853d2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc
@@ -0,0 +1,1414 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
+
+#include <sstream>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.h"
+#include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+
+namespace blink {
+
+using ::testing::ElementsAre;
+
+class LayoutNGTextCombineTest : public NGLayoutTest,
+ private ScopedLayoutNGTextCombineForTest {
+ protected:
+ LayoutNGTextCombineTest() : ScopedLayoutNGTextCombineForTest(true) {}
+
+ std::string AsInkOverflowString(const LayoutBlockFlow& root) {
+ std::ostringstream ostream;
+ ostream << std::endl;
+ for (NGInlineCursor cursor(root); cursor; cursor.MoveToNext()) {
+ ostream << cursor.CurrentItem() << std::endl;
+ ostream << " Rect "
+ << cursor.CurrentItem()->RectInContainerFragment() << std::endl;
+ ostream << " InkOverflow " << cursor.CurrentItem()->InkOverflow()
+ << std::endl;
+ ostream << " SelfInkOverflow "
+ << cursor.CurrentItem()->SelfInkOverflow() << std::endl;
+ ostream << " ContentsInkOverflow "
+ << ContentsInkOverflow(*cursor.CurrentItem()) << std::endl;
+ }
+ return ostream.str();
+ }
+
+ static PhysicalRect ContentsInkOverflow(const NGFragmentItem& item) {
+ if (const NGPhysicalBoxFragment* box_fragment = item.BoxFragment())
+ return box_fragment->ContentsInkOverflow();
+ if (!item.HasInkOverflow())
+ return PhysicalRect();
+ return item.ink_overflow_.Contents(item.InkOverflowType(), item.Size());
+ }
+};
+
+TEST_F(LayoutNGTextCombineTest, AppendChild) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ GetElementById("combine")->appendChild(Text::Create(GetDocument(), "Z"));
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ | | +--LayoutText #text "Z"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, BoxBoundary) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>X<b>Y</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "X"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "Y"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, DeleteDataToEmpty) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ To<Text>(GetElementById("combine")->firstChild())
+ ->deleteData(0, 2, ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1228058
+TEST_F(LayoutNGTextCombineTest, ElementRecalcOwnStyle) {
+ InsertStyleElement(
+ "#root { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root><br id=target></div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutBR BR id="target"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ // Call |Element::RecalcOwnStyle()| for <br>
+ auto& target = *GetElementById("target");
+ target.style()->setProperty(GetDocument().GetExecutionContext(), "color",
+ "red", "", ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutBR BR id="target" style="color: red;"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, InkOverflow) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=combine>0123456789</c>b</div>");
+ const auto& root =
+ *To<LayoutBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=5 LTR Standard}
+ Rect "0,0 110x300"
+ InkOverflow "0,0 110x300"
+ SelfInkOverflow "0,0 110x300"
+ ContentsInkOverflow "0,0 0x0"
+{Text 0-1 LTR Standard}
+ Rect "5,0 100x100"
+ InkOverflow "0,0 100x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 0x0"
+{Box #descendants=2 Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Box #descendants=1 AtomicInlineLTR Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Text 2-3 LTR Standard}
+ Rect "5,200 100x100"
+ InkOverflow "0,0 100x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(root));
+
+ // Note: text item rect has non-scaled size.
+ const auto& text_combine = *To<LayoutNGTextCombine>(
+ GetElementById("combine")->GetLayoutObject()->SlowFirstChild());
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=2 LTR Standard}
+ Rect "0,0 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Text 0-10 LTR Standard}
+ Rect "0,0 1000x100"
+ InkOverflow "0,0 1000x100"
+ SelfInkOverflow "0,0 1000x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(text_combine));
+}
+
+TEST_F(LayoutNGTextCombineTest, InkOverflowEmphasisMark) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { -webkit-text-emphasis: dot; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=combine>0123456789</c>b</div>");
+ const auto& root =
+ *To<LayoutBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=5 LTR Standard}
+ Rect "0,0 155x300"
+ InkOverflow "0,0 155x300"
+ SelfInkOverflow "0,0 155x300"
+ ContentsInkOverflow "0,0 0x0"
+{Text 0-1 LTR Standard}
+ Rect "5,0 100x100"
+ InkOverflow "0,0 150x100"
+ SelfInkOverflow "0,0 150x100"
+ ContentsInkOverflow "0,0 0x0"
+{Box #descendants=2 Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-5,0 155x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 155x100"
+{Box #descendants=1 AtomicInlineLTR Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-5,0 155x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 155x100"
+{Text 2-3 LTR Standard}
+ Rect "5,200 100x100"
+ InkOverflow "0,0 150x100"
+ SelfInkOverflow "0,0 150x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(root));
+
+ // Note: Emphasis mark is part of text-combine box instead of combined text.
+ // Note: text item rect has non-scaled size.
+ const auto& text_combine = *To<LayoutNGTextCombine>(
+ GetElementById("combine")->GetLayoutObject()->SlowFirstChild());
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=2 LTR Standard}
+ Rect "0,0 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Text 0-10 LTR Standard}
+ Rect "0,0 1000x100"
+ InkOverflow "0,0 1000x100"
+ SelfInkOverflow "0,0 1000x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(text_combine));
+}
+
+TEST_F(LayoutNGTextCombineTest, InkOverflowOverline) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { text-decoration: overline; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=combine>0123456789</c>b</div>");
+ const auto& root =
+ *To<LayoutBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=5 LTR Standard}
+ Rect "0,0 110x300"
+ InkOverflow "0,0 115x300"
+ SelfInkOverflow "0,0 110x300"
+ ContentsInkOverflow "0,0 115x300"
+{Text 0-1 LTR Standard}
+ Rect "5,0 100x100"
+ InkOverflow "0,0 110x100"
+ SelfInkOverflow "0,0 110x100"
+ ContentsInkOverflow "0,0 0x0"
+{Box #descendants=2 Standard}
+ Rect "5,100 100x100"
+ InkOverflow "0,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 110x100"
+{Box #descendants=1 AtomicInlineLTR Standard}
+ Rect "5,100 100x100"
+ InkOverflow "0,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 110x100"
+{Text 2-3 LTR Standard}
+ Rect "5,200 100x100"
+ InkOverflow "0,0 110x100"
+ SelfInkOverflow "0,0 110x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(root));
+
+ const auto& text_combine = *To<LayoutNGTextCombine>(
+ GetElementById("combine")->GetLayoutObject()->SlowFirstChild());
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=2 LTR Standard}
+ Rect "0,0 100x100"
+ InkOverflow "0,0 100x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 0x0"
+{Text 0-10 LTR Standard}
+ Rect "0,0 1000x100"
+ InkOverflow "0,0 1000x100"
+ SelfInkOverflow "0,0 1000x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(text_combine));
+}
+
+TEST_F(LayoutNGTextCombineTest, InkOverflowUnderline) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { text-decoration: underline; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=combine>0123456789</c>b</div>");
+ const auto& root =
+ *To<LayoutBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=5 LTR Standard}
+ Rect "0,0 110x300"
+ InkOverflow "-6,0 116x300"
+ SelfInkOverflow "0,0 110x300"
+ ContentsInkOverflow "-6,0 116x300"
+{Text 0-1 LTR Standard}
+ Rect "5,0 100x100"
+ InkOverflow "-11,0 111x100"
+ SelfInkOverflow "-11,0 111x100"
+ ContentsInkOverflow "0,0 0x0"
+{Box #descendants=2 Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-11,0 111x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-11,0 111x100"
+{Box #descendants=1 AtomicInlineLTR Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-11,0 111x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-11,0 111x100"
+{Text 2-3 LTR Standard}
+ Rect "5,200 100x100"
+ InkOverflow "-11,0 111x100"
+ SelfInkOverflow "-11,0 111x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(root));
+
+ const auto& text_combine = *To<LayoutNGTextCombine>(
+ GetElementById("combine")->GetLayoutObject()->SlowFirstChild());
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=2 LTR Standard}
+ Rect "0,0 100x100"
+ InkOverflow "0,0 100x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 0x0"
+{Text 0-10 LTR Standard}
+ Rect "0,0 1000x100"
+ InkOverflow "0,0 1000x100"
+ SelfInkOverflow "0,0 1000x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(text_combine));
+}
+
+TEST_F(LayoutNGTextCombineTest, InkOverflowWBR) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=combine>01234<wbr>56789</c>b</div>");
+ const auto& root =
+ *To<LayoutBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=5 LTR Standard}
+ Rect "0,0 110x300"
+ InkOverflow "0,0 110x300"
+ SelfInkOverflow "0,0 110x300"
+ ContentsInkOverflow "0,0 0x0"
+{Text 0-1 LTR Standard}
+ Rect "5,0 100x100"
+ InkOverflow "0,0 100x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 0x0"
+{Box #descendants=2 Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Box #descendants=1 AtomicInlineLTR Standard}
+ Rect "5,100 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Text 2-3 LTR Standard}
+ Rect "5,200 100x100"
+ InkOverflow "0,0 100x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(root));
+
+ // Note: text item rect has non-scaled size.
+ const auto& text_combine = *To<LayoutNGTextCombine>(
+ GetElementById("combine")->GetLayoutObject()->SlowFirstChild());
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=4 LTR Standard}
+ Rect "0,0 100x100"
+ InkOverflow "-5,0 110x100"
+ SelfInkOverflow "0,0 100x100"
+ ContentsInkOverflow "-5,0 110x100"
+{Text 0-5 LTR Standard}
+ Rect "0,0 500x100"
+ InkOverflow "0,0 500x100"
+ SelfInkOverflow "0,0 500x100"
+ ContentsInkOverflow "0,0 0x0"
+{Text 5-6 LTR Standard}
+ Rect "500,0 0x100"
+ InkOverflow "0,0 0x100"
+ SelfInkOverflow "0,0 0x100"
+ ContentsInkOverflow "0,0 0x0"
+{Text 6-11 LTR Standard}
+ Rect "500,0 500x100"
+ InkOverflow "0,0 500x100"
+ SelfInkOverflow "0,0 500x100"
+ ContentsInkOverflow "0,0 0x0"
+)DUMP",
+ AsInkOverflowString(text_combine));
+}
+
+TEST_F(LayoutNGTextCombineTest, InsertBefore) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ auto& combine = *GetElementById("combine");
+ combine.insertBefore(Text::Create(GetDocument(), "Z"), combine.firstChild());
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "Z"
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1215026
+TEST_F(LayoutNGTextCombineTest, LegacyQuote) {
+ InsertStyleElement(
+ "q { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root><q>ab</q></div>");
+ auto& root = *GetElementById("root");
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutInline Q
+ | +--LayoutInline ::before
+ | | +--LayoutQuote (anonymous)
+ | | | +--LayoutNGTextCombine (anonymous)
+ | | | | +--LayoutTextFragment (anonymous) ("\"")
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "ab"
+ | +--LayoutInline ::after
+ | | +--LayoutQuote (anonymous)
+ | | | +--LayoutNGTextCombine (anonymous)
+ | | | | +--LayoutTextFragment (anonymous) ("\"")
+)DUMP",
+ ToSimpleLayoutTree(*root.GetLayoutObject()));
+
+ // Force legacy layout
+ root.SetStyleShouldForceLegacyLayout(true);
+ GetDocument().documentElement()->SetForceReattachLayoutTree();
+ RunDocumentLifecycle();
+
+ EXPECT_EQ(R"DUMP(
+LayoutBlockFlow DIV id="root"
+ +--LayoutInline Q
+ | +--LayoutInline ::before
+ | | +--LayoutQuote (anonymous)
+ | | | +--LayoutTextFragment (anonymous) ("\"")
+ | +--LayoutTextCombine #text "ab"
+ | +--LayoutInline ::after
+ | | +--LayoutQuote (anonymous)
+ | | | +--LayoutTextFragment (anonymous) ("\"")
+)DUMP",
+ ToSimpleLayoutTree(*root.GetLayoutObject()))
+ << "No more LayoutNGTextCombine";
+}
+
+TEST_F(LayoutNGTextCombineTest, LayoutOverflow) {
+ LoadAhem();
+ InsertStyleElement(
+ "div {"
+ " writing-mode: vertical-lr;"
+ " font: 100px/150px Ahem;"
+ "}"
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML(
+ "<div id=t1><tcy>abcefgh</tcy>X</div>"
+ "<div id=t2>aX</div>");
+
+ // Layout tree is
+ // LayoutNGBlockFlow {DIV} at (0,0) size 100x200
+ // LayoutInline {TCY} at (0,0) size 100x100
+ // LayoutNGTextCombine (anonymous) at (0,0) size 100x100
+ // LayoutText {#text} at (0,0) size 110x100
+ // text run at (0,0) width 700: "abcefgh"
+ // LayoutText {#text} at (0,100) size 100x100
+ // text run at (0,100) width 100: "X"
+ // LayoutNGBlockFlow {DIV} at (0,200) size 100x200
+ // LayoutText {#text} at (0,0) size 100x200
+ // text run at (0,0) width 200: "aX"
+
+ const auto& sample1 = *To<LayoutBlockFlow>(GetLayoutObjectByElementId("t1"));
+ const auto& sample_fragment1 = *sample1.CurrentFragment();
+ EXPECT_FALSE(sample_fragment1.HasLayoutOverflow());
+ EXPECT_EQ(PhysicalSize(150, 200), sample_fragment1.Size());
+ EXPECT_EQ(PhysicalRect(PhysicalOffset(), PhysicalSize(150, 200)),
+ sample_fragment1.LayoutOverflow());
+
+ const auto& sample2 = *To<LayoutBlockFlow>(GetLayoutObjectByElementId("t2"));
+ const auto& sample_fragment2 = *sample2.CurrentFragment();
+ EXPECT_FALSE(sample_fragment2.HasLayoutOverflow());
+ EXPECT_EQ(PhysicalSize(150, 200), sample_fragment2.Size());
+ EXPECT_EQ(PhysicalRect(PhysicalOffset(), PhysicalSize(150, 200)),
+ sample_fragment2.LayoutOverflow());
+}
+
+// http://crbug.com/1223015
+TEST_F(LayoutNGTextCombineTest, ListItemStyleToImage) {
+ InsertStyleElement(
+ "li { text-combine-upright: all; }"
+ "ol { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<ol id=root><li></li></ol>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow OL id="root"
+ +--LayoutNGListItem LI
+ | +--LayoutNGOutsideListMarker ::marker
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText (anonymous) "1. "
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ // Change list-marker to use image
+ root.style()->setProperty(
+ GetDocument().GetExecutionContext(), "list-style-image",
+ "url(data:image/"
+ "gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/"
+ "XBs/fNwfjZ0frl3/zy7////"
+ "wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAA"
+ "BAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QA"
+ "nQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)",
+ "", ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow OL id="root" style="list-style-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7\");"
+ +--LayoutNGListItem LI
+ | +--LayoutNGOutsideListMarker ::marker
+ | | +--LayoutImage (anonymous)
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, MultipleTextNode) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>X<!-- -->Y</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "X"
+ | | +--LayoutText #text "Y"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, Nested) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine><b>XY</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, Outline) {
+ LoadAhem();
+ InsertStyleElement(
+ "div {"
+ " writing-mode: vertical-lr;"
+ " text-combine-upright: all;"
+ " font: 100px/150px Ahem;"
+ "}"
+ "tcy { text-combine-upright: all; }");
+ SetBodyInnerHTML(
+ "<div id=t1><tcy>abcefgh</tcy>X</div>"
+ "<div id=t2>aX</div>");
+
+ // Layout tree is
+ // LayoutNGBlockFlow {DIV} at (0,0) size 100x200
+ // LayoutInline {TCY} at (0,0) size 100x100
+ // LayoutNGTextCombine (anonymous) at (0,0) size 100x100
+ // LayoutText {#text} at (0,0) size 110x100
+ // text run at (0,0) width 700: "abcefgh"
+ // LayoutText {#text} at (0,100) size 100x100
+ // text run at (0,100) width 100: "X"
+ // LayoutNGBlockFlow {DIV} at (0,200) size 100x200
+ // LayoutText {#text} at (0,0) size 100x200
+ // text run at (0,0) width 200: "aX"
+
+ // Sample 1 with text-combine-upright:all
+ const auto& sample1 = *GetLayoutObjectByElementId("t1");
+ Vector<PhysicalRect> standard_outlines1;
+ sample1.AddOutlineRects(standard_outlines1, PhysicalOffset(),
+ NGOutlineType::kDontIncludeBlockVisualOverflow);
+ EXPECT_THAT(
+ standard_outlines1,
+ ElementsAre(PhysicalRect(PhysicalOffset(0, 0), PhysicalSize(150, 200))));
+
+ Vector<PhysicalRect> focus_outlines1;
+ sample1.AddOutlineRects(focus_outlines1, PhysicalOffset(),
+ NGOutlineType::kIncludeBlockVisualOverflow);
+ EXPECT_THAT(
+ focus_outlines1,
+ ElementsAre(
+ PhysicalRect(PhysicalOffset(0, 0), PhysicalSize(150, 200)),
+ // tcy
+ PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)),
+ PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)),
+ PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)),
+ PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)),
+ // "X"
+ PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100)),
+ PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100))));
+
+ // Sample 1 without text-combine-upright:all
+ const auto& sample2 = *GetLayoutObjectByElementId("t2");
+ Vector<PhysicalRect> standard_outlines2;
+ sample2.AddOutlineRects(standard_outlines2, PhysicalOffset(),
+ NGOutlineType::kDontIncludeBlockVisualOverflow);
+ EXPECT_THAT(
+ standard_outlines2,
+ ElementsAre(PhysicalRect(PhysicalOffset(0, 0), PhysicalSize(150, 100))));
+
+ Vector<PhysicalRect> focus_outlines2;
+ sample1.AddOutlineRects(focus_outlines2, PhysicalOffset(),
+ NGOutlineType::kIncludeBlockVisualOverflow);
+ EXPECT_THAT(
+ focus_outlines2,
+ ElementsAre(
+ PhysicalRect(PhysicalOffset(0, 0), PhysicalSize(150, 200)),
+ // "a"
+ PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)),
+ PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)),
+ PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)),
+ PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)),
+ // "X"
+ PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100)),
+ PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100))));
+}
+
+// http://crbug.com/1222160
+TEST_F(LayoutNGTextCombineTest, RebuildLayoutTreeForDetails) {
+ InsertStyleElement(
+ "details { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<details id=root open>ab<summary>XY</summary>cd</details>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DETAILS id="root"
+ +--LayoutNGListItem SUMMARY
+ | +--LayoutNGInsideListMarker ::marker
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText (anonymous) "\u25BE "
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutNGBlockFlow (anonymous)
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "ab"
+ | | +--LayoutText #text "cd"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ // Rebuild layout tree of <details>
+ root.style()->setProperty(GetDocument().GetExecutionContext(), "color", "red",
+ "important", ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DETAILS id="root" style="color: red !important;"
+ +--LayoutNGListItem SUMMARY
+ | +--LayoutNGInsideListMarker ::marker
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText (anonymous) "\u25BE "
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutNGBlockFlow (anonymous)
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "ab"
+ | | +--LayoutText #text "cd"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http;//crbug.com/1233432
+TEST_F(LayoutNGTextCombineTest, RemoveBlockChild) {
+ InsertStyleElement(
+ "div { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<p id=block>XY</p>de</div>");
+ auto& root = *GetElementById("root");
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutNGBlockFlow (anonymous)
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "ab"
+ +--LayoutNGBlockFlow P id="block"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutNGBlockFlow (anonymous)
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(*root.GetLayoutObject()));
+
+ GetElementById("block")->remove();
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutNGTextCombine (anonymous)
+ | +--LayoutText #text "ab"
+ | +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(*root.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextCombineTest, RemoveChildCombine) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ GetElementById("combine")->remove();
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, RemoveChildToEmpty) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ GetElementById("combine")->firstChild()->remove();
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1227066
+TEST_F(LayoutNGTextCombineTest, RemoveChildToOneCombinedText) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root><c>a<b id=t>x</b>z</c></div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutInline C
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "a"
+ | +--LayoutInline B id="t"
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "x"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "z"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ GetElementById("t")->remove();
+ RunDocumentLifecycle();
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutInline C
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "a"
+ | | +--LayoutText #text "z"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1227066
+TEST_F(LayoutNGTextCombineTest, ReplaceChildToOneCombinedText) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root><c>a<b id=t>x</b>z</c></div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutInline C
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "a"
+ | +--LayoutInline B id="t"
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "x"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "z"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ auto& target = *GetElementById("t");
+ auto& new_text = *Text::Create(GetDocument(), "X");
+ target.parentNode()->replaceChild(&new_text, &target);
+ RunDocumentLifecycle();
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutInline C
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "a"
+ | | +--LayoutText #text "X"
+ | | +--LayoutText #text "z"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, SetDataToEmpty) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ To<Text>(GetElementById("combine")->firstChild())->setData("");
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object))
+ << "We should not have a wrapper.";
+}
+
+TEST_F(LayoutNGTextCombineTest, SplitText) {
+ V8TestingScope scope;
+
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ To<Text>(GetElementById("combine")->firstChild())
+ ->splitText(1, ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "X"
+ | | +--LayoutText #text "Y"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, SplitTextAtZero) {
+ V8TestingScope scope;
+
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ To<Text>(GetElementById("combine")->firstChild())
+ ->splitText(0, ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object))
+ << "There are no empty LayoutText.";
+}
+
+TEST_F(LayoutNGTextCombineTest, SplitTextBeforeBox) {
+ V8TestingScope scope;
+
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY<b>Z</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "Z"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ To<Text>(GetElementById("combine")->firstChild())
+ ->splitText(1, ASSERT_NO_EXCEPTION);
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "X"
+ | | +--LayoutText #text "Y"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "Z"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, StyleToTextCombineUprightAll) {
+ InsertStyleElement("div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine><b>XY</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object))
+ << "There are no wrapper.";
+
+ GetElementById("combine")->setAttribute("style", "text-combine-upright: all");
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine" style="text-combine-upright: all"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object))
+ << "There are no wrapper.";
+}
+
+TEST_F(LayoutNGTextCombineTest, StyleToTextCombineUprightNone) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine><b>XY</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ GetElementById("combine")->setAttribute("style",
+ "text-combine-upright: none");
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine" style="text-combine-upright: none"
+ | +--LayoutInline B
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object))
+ << "There are no wrapper.";
+}
+
+TEST_F(LayoutNGTextCombineTest, StyleToHorizontalWritingMode) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine><b>XY</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ root.setAttribute("style", "writing-mode: horizontal-tb");
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root" style="writing-mode: horizontal-tb"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object))
+ << "There are no wrapper.";
+}
+
+TEST_F(LayoutNGTextCombineTest, StyleToVerticalWritingMode) {
+ InsertStyleElement("c { text-combine-upright: all; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine><b>XY</b></c>de</div>");
+ auto& root = *GetElementById("root");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+
+ root.setAttribute("style", "writing-mode: vertical-rl");
+ RunDocumentLifecycle();
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root" style="writing-mode: vertical-rl"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutInline B
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1222121
+TEST_F(LayoutNGTextCombineTest, VerticalWritingModeByBR) {
+ InsertStyleElement(
+ "#sample { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<br id=sample>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetDocument().body()->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow BODY
+ +--LayoutBR BR id="sample"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1222121
+TEST_F(LayoutNGTextCombineTest, VerticalWritingModeByWBR) {
+ InsertStyleElement(
+ "#sample { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<wbr id=sample>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetDocument().body()->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow BODY
+ +--LayoutWordBreak WBR id="sample"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1222069
+TEST_F(LayoutNGTextCombineTest, WithBidiControl) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; -webkit-rtl-ordering: visual; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY</c>de</div>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, WithBR) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY<br>Z</c>de</div>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ | | +--LayoutBR BR
+ | | +--LayoutText #text "Z"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1060007
+TEST_F(LayoutNGTextCombineTest, WithMarker) {
+ InsertStyleElement(
+ "li { text-combine-upright: all; }"
+ "p {"
+ " counter-increment: my-counter;"
+ " display: list-item;"
+ " writing-mode: vertical-rl;"
+ "}"
+ "p::marker {"
+ " content: '<' counter(my-counter) '>';"
+ " text-combine-upright: all;"
+ "}");
+ SetBodyInnerHTML("<p id=root>ab</p>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+ EXPECT_EQ(R"DUMP(
+LayoutNGListItem P id="root"
+ +--LayoutNGOutsideListMarker ::marker
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutTextFragment (anonymous) ("<")
+ | | +--LayoutCounter (anonymous) "1"
+ | | +--LayoutTextFragment (anonymous) (">")
+ +--LayoutText #text "ab"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, WithOrderedList) {
+ InsertStyleElement(
+ "li { text-combine-upright: all; }"
+ "ol { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<ol id=root><li>ab</li></ol>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow OL id="root"
+ +--LayoutNGListItem LI
+ | +--LayoutNGOutsideListMarker ::marker
+ | | +--LayoutNGTextCombine (anonymous)
+ | | | +--LayoutText (anonymous) "1. "
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "ab"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, WithQuote) {
+ InsertStyleElement(
+ "q { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root><q>XY</q></div>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutInline Q
+ | +--LayoutInline ::before
+ | | +--LayoutQuote (anonymous)
+ | | | +--LayoutNGTextCombine (anonymous)
+ | | | | +--LayoutTextFragment (anonymous) ("\"")
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ | +--LayoutInline ::after
+ | | +--LayoutQuote (anonymous)
+ | | | +--LayoutNGTextCombine (anonymous)
+ | | | | +--LayoutTextFragment (anonymous) ("\"")
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+// http://crbug.com/1223423
+TEST_F(LayoutNGTextCombineTest, WithTab) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; white-space: pre; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>X\tY</c>de</div>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "X\tY"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+TEST_F(LayoutNGTextCombineTest, WithWordBreak) {
+ InsertStyleElement(
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>ab<c id=combine>XY<wbr>Z</c>de</div>");
+ const auto& root_layout_object =
+ *To<LayoutNGBlockFlow>(GetElementById("root")->GetLayoutObject());
+
+ EXPECT_EQ(R"DUMP(
+LayoutNGBlockFlow DIV id="root"
+ +--LayoutText #text "ab"
+ +--LayoutInline C id="combine"
+ | +--LayoutNGTextCombine (anonymous)
+ | | +--LayoutText #text "XY"
+ | | +--LayoutWordBreak WBR
+ | | +--LayoutText #text "Z"
+ +--LayoutText #text "de"
+)DUMP",
+ ToSimpleLayoutTree(root_layout_object));
+}
+
+} // namespace blink
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 646a189ce72..8820e0e5d8e 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.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/ng/inline/ng_inline_cursor.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
index 448f1f62524..94c8c55a09f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
@@ -8,8 +8,10 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -72,6 +74,14 @@ bool ShouldAlignCaretRight(ETextAlign text_align, TextDirection direction) {
return false;
}
+LayoutUnit ClampAndRound(LayoutUnit value, LayoutUnit min, LayoutUnit max) {
+ LayoutUnit min_ceil = LayoutUnit(min.Ceil());
+ LayoutUnit max_floor = LayoutUnit(max.Floor());
+ if (min_ceil >= max_floor)
+ return max_floor;
+ return LayoutUnit(clampTo<LayoutUnit>(value, min_ceil, max_floor).Round());
+}
+
PhysicalRect ComputeLocalCaretRectAtTextOffset(const NGInlineCursor& cursor,
unsigned offset) {
DCHECK(cursor.Current().IsText());
@@ -89,7 +99,7 @@ PhysicalRect ComputeLocalCaretRectAtTextOffset(const NGInlineCursor& cursor,
: cursor.Current().Size().width;
LayoutUnit caret_top;
- LayoutUnit caret_left = cursor.InlinePositionForOffset(offset);
+ LayoutUnit caret_left = cursor.CaretInlinePositionForOffset(offset);
if (!cursor.Current().IsLineBreak())
caret_left -= caret_width / 2;
@@ -101,6 +111,12 @@ PhysicalRect ComputeLocalCaretRectAtTextOffset(const NGInlineCursor& cursor,
// Adjust the location to be relative to the inline formatting context.
PhysicalOffset caret_location = PhysicalOffset(caret_left, caret_top) +
cursor.Current().OffsetInContainerFragment();
+ const auto* const text_combine = DynamicTo<LayoutNGTextCombine>(
+ cursor.Current().GetLayoutObject()->Parent());
+ if (UNLIKELY(text_combine)) {
+ caret_location =
+ text_combine->AdjustOffsetForLocalCaretRect(caret_location);
+ }
const PhysicalSize caret_size(caret_width, caret_height);
const NGPhysicalBoxFragment& fragment = cursor.ContainerFragment();
@@ -125,27 +141,23 @@ PhysicalRect ComputeLocalCaretRectAtTextOffset(const NGInlineCursor& cursor,
if (is_horizontal) {
if (should_align_caret_right) {
const LayoutUnit left_edge = std::min(LayoutUnit(), line_box_rect.X());
- caret_location.left = std::max(caret_location.left, left_edge);
+ const LayoutUnit right_limit = line_box_rect.Right() - caret_width;
caret_location.left =
- std::min(caret_location.left, line_box_rect.Right() - caret_width);
+ ClampAndRound(caret_location.left, left_edge, right_limit);
} else {
- const LayoutUnit right_edge =
- std::max(fragment.Size().width, line_box_rect.Right());
+ const LayoutUnit right_limit =
+ std::max(fragment.Size().width, line_box_rect.Right()) - caret_width;
caret_location.left =
- std::min(caret_location.left, right_edge - caret_width);
- caret_location.left = std::max(caret_location.left, line_box_rect.X());
+ ClampAndRound(caret_location.left, line_box_rect.X(), right_limit);
}
- caret_location.left = LayoutUnit(caret_location.left.Round());
return PhysicalRect(caret_location, caret_size);
}
// Similar adjustment and rounding for vertical text.
const LayoutUnit min_y = std::min(LayoutUnit(), line_box_offset.top);
- caret_location.top = std::max(caret_location.top, min_y);
- const LayoutUnit max_y =
- std::max(fragment.Size().height, line_box_rect.Bottom());
- caret_location.top = std::min(caret_location.top, max_y - caret_height);
- caret_location.top = LayoutUnit(caret_location.top.Round());
+ const LayoutUnit bottom_limit =
+ std::max(fragment.Size().height, line_box_rect.Bottom()) - caret_height;
+ caret_location.top = ClampAndRound(caret_location.top, min_y, bottom_limit);
return PhysicalRect(caret_location, caret_size);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 8e1a8ea3cfd..17a8ad3676c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/editing/bidi_adjustment.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
@@ -197,10 +198,10 @@ NGFragmentItem::NGFragmentItem(const NGFragmentItem& source)
case kText:
new (&text_) TextItem(source.text_);
break;
- case kSVGText:
- new (&svg_text_) SVGTextItem();
+ case kSvgText:
+ new (&svg_text_) SvgTextItem();
svg_text_.data =
- std::make_unique<NGSVGFragmentData>(*source.svg_text_.data);
+ std::make_unique<NGSvgFragmentData>(*source.svg_text_.data);
break;
case kGeneratedText:
new (&generated_text_) GeneratedTextItem(source.generated_text_);
@@ -239,8 +240,8 @@ NGFragmentItem::NGFragmentItem(NGFragmentItem&& source)
case kText:
new (&text_) TextItem(std::move(source.text_));
break;
- case kSVGText:
- new (&svg_text_) SVGTextItem(std::move(source.svg_text_));
+ case kSvgText:
+ new (&svg_text_) SvgTextItem(std::move(source.svg_text_));
break;
case kGeneratedText:
new (&generated_text_)
@@ -260,8 +261,8 @@ NGFragmentItem::~NGFragmentItem() {
case kText:
text_.~TextItem();
break;
- case kSVGText:
- svg_text_.~SVGTextItem();
+ case kSvgText:
+ svg_text_.~SvgTextItem();
break;
case kGeneratedText:
generated_text_.~GeneratedTextItem();
@@ -293,6 +294,14 @@ bool NGFragmentItem::IsAtomicInline() const {
return false;
}
+bool NGFragmentItem::IsBlockInInline() const {
+ if (Type() != kBox)
+ return false;
+ if (const NGPhysicalBoxFragment* box = BoxFragment())
+ return box->IsBlockInInline();
+ return false;
+}
+
bool NGFragmentItem::IsFloating() const {
if (const NGPhysicalBoxFragment* box = BoxFragment())
return box->IsFloating();
@@ -304,7 +313,7 @@ bool NGFragmentItem::IsEmptyLineBox() const {
}
bool NGFragmentItem::IsStyleGeneratedText() const {
- if (Type() == kText || Type() == kSVGText)
+ if (Type() == kText || Type() == kSvgText)
return GetLayoutObject()->IsStyleGenerated();
return false;
}
@@ -313,36 +322,85 @@ bool NGFragmentItem::IsGeneratedText() const {
return IsLayoutGeneratedText() || IsStyleGeneratedText();
}
+bool NGFragmentItem::IsFormattingContextRoot() const {
+ const NGPhysicalBoxFragment* box = BoxFragment();
+ return box && box->IsFormattingContextRoot();
+}
+
bool NGFragmentItem::IsListMarker() const {
return layout_object_ && layout_object_->IsLayoutNGOutsideListMarker();
}
-void NGFragmentItem::ConvertToSVGText(std::unique_ptr<NGSVGFragmentData> data,
+void NGFragmentItem::ConvertToSvgText(std::unique_ptr<NGSvgFragmentData> data,
const PhysicalRect& unscaled_rect,
bool is_hidden) {
DCHECK(RuntimeEnabledFeatures::SVGTextNGEnabled());
DCHECK_EQ(Type(), kText);
is_hidden_for_paint_ = is_hidden;
text_.~TextItem();
- new (&svg_text_) SVGTextItem();
+ new (&svg_text_) SvgTextItem();
svg_text_.data = std::move(data);
- type_ = kSVGText;
+ type_ = kSvgText;
+ rect_ = unscaled_rect;
+}
+
+void NGFragmentItem::SetSvgLineLocalRect(const PhysicalRect& unscaled_rect) {
+ DCHECK_EQ(Type(), kLine);
rect_ = unscaled_rect;
}
FloatRect NGFragmentItem::ObjectBoundingBox() const {
- if (Type() != kSVGText)
+ if (Type() != kSvgText)
return FloatRect(rect_);
- const float scaling_factor =
- To<LayoutSVGInlineText>(GetLayoutObject())->ScalingFactor();
- DCHECK_GT(scaling_factor, 0.0f);
- FloatRect item_rect = SVGFragmentData()->rect;
- if (HasSVGTransformForBoundingBox())
- item_rect = BuildSVGTransformForBoundingBox().MapRect(item_rect);
- item_rect.Scale(1 / scaling_factor);
+ FloatRect item_rect = SvgFragmentData()->rect;
+ if (HasSvgTransformForBoundingBox())
+ item_rect = BuildSvgTransformForBoundingBox().MapRect(item_rect);
+ item_rect.Scale(1 / SvgScalingFactor());
return item_rect;
}
+FloatQuad NGFragmentItem::SvgUnscaledQuad() const {
+ DCHECK_EQ(Type(), kSvgText);
+ FloatQuad quad =
+ BuildSvgTransformForBoundingBox().MapQuad(SvgFragmentData()->rect);
+ const float scaling_factor = SvgScalingFactor();
+ quad.Scale(1 / scaling_factor, 1 / scaling_factor);
+ return quad;
+}
+
+PhysicalOffset NGFragmentItem::MapPointInContainer(
+ const PhysicalOffset& point) const {
+ if (Type() != kSvgText || !HasSvgTransformForBoundingBox())
+ return point;
+ const float scaling_factor = SvgScalingFactor();
+ return PhysicalOffset::FromFloatPointRound(
+ BuildSvgTransformForBoundingBox()
+ .Inverse()
+ .MapPoint(FloatPoint(point).ScaledBy(scaling_factor))
+ .ScaledBy(1 / scaling_factor));
+}
+
+float NGFragmentItem::ScaleInlineOffset(LayoutUnit inline_offset) const {
+ if (Type() != kSvgText)
+ return inline_offset.ToFloat();
+ return inline_offset.ToFloat() * SvgScalingFactor() /
+ SvgFragmentData()->length_adjust_scale;
+}
+
+bool NGFragmentItem::Contains(const FloatPoint& position) const {
+ if (Type() != kSvgText)
+ return FloatRect(rect_).Contains(position);
+ const float scaling_factor = SvgScalingFactor();
+ FloatPoint scaled_position = position;
+ scaled_position.Scale(scaling_factor, scaling_factor);
+ FloatRect item_rect = SvgFragmentData()->rect;
+ if (!HasSvgTransformForBoundingBox())
+ return item_rect.Contains(scaled_position);
+ return BuildSvgTransformForBoundingBox()
+ .MapQuad(FloatQuad(item_rect))
+ .ContainsPoint(scaled_position);
+}
+
bool NGFragmentItem::HasNonVisibleOverflow() const {
if (const NGPhysicalBoxFragment* fragment = BoxFragment())
return fragment->HasNonVisibleOverflow();
@@ -412,14 +470,6 @@ PhysicalRect NGFragmentItem::SelfInkOverflow() const {
return ink_overflow_.Self(InkOverflowType(), Size());
}
-PhysicalRect NGFragmentItem::ContentsInkOverflow() const {
- if (const NGPhysicalBoxFragment* box_fragment = BoxFragment())
- return box_fragment->ContentsInkOverflow();
- if (!HasInkOverflow())
- return PhysicalRect();
- return ink_overflow_.Contents(InkOverflowType(), Size());
-}
-
PhysicalRect NGFragmentItem::InkOverflow() const {
if (const NGPhysicalBoxFragment* box_fragment = BoxFragment())
return box_fragment->InkOverflow();
@@ -433,7 +483,7 @@ PhysicalRect NGFragmentItem::InkOverflow() const {
const ShapeResultView* NGFragmentItem::TextShapeResult() const {
if (Type() == kText)
return text_.shape_result.get();
- if (Type() == kSVGText)
+ if (Type() == kSvgText)
return svg_text_.data->shape_result.get();
if (Type() == kGeneratedText)
return generated_text_.shape_result.get();
@@ -444,7 +494,7 @@ const ShapeResultView* NGFragmentItem::TextShapeResult() const {
NGTextOffset NGFragmentItem::TextOffset() const {
if (Type() == kText)
return text_.text_offset;
- if (Type() == kSVGText)
+ if (Type() == kSvgText)
return svg_text_.data->text_offset;
if (Type() == kGeneratedText)
return {0, generated_text_.text.length()};
@@ -477,7 +527,7 @@ StringView NGFragmentItem::Text(const NGFragmentItems& items) const {
return StringView(items.Text(UsesFirstLineStyle()), text_.text_offset.start,
text_.text_offset.Length());
}
- if (Type() == kSVGText) {
+ if (Type() == kSvgText) {
return StringView(items.Text(UsesFirstLineStyle()),
svg_text_.data->text_offset.start,
svg_text_.data->text_offset.Length());
@@ -494,7 +544,7 @@ NGTextFragmentPaintInfo NGFragmentItem::TextPaintInfo(
return {items.Text(UsesFirstLineStyle()), text_.text_offset.start,
text_.text_offset.end, text_.shape_result.get()};
}
- if (Type() == kSVGText) {
+ if (Type() == kSvgText) {
return {items.Text(UsesFirstLineStyle()), svg_text_.data->text_offset.start,
svg_text_.data->text_offset.end,
svg_text_.data->shape_result.get()};
@@ -517,13 +567,13 @@ TextDirection NGFragmentItem::ResolvedDirection() const {
return static_cast<TextDirection>(text_direction_);
}
-bool NGFragmentItem::HasSVGTransformForPaint() const {
- return Type() == kSVGText && (svg_text_.data->length_adjust_scale != 1.0f ||
+bool NGFragmentItem::HasSvgTransformForPaint() const {
+ return Type() == kSvgText && (svg_text_.data->length_adjust_scale != 1.0f ||
svg_text_.data->angle != 0.0f);
}
-bool NGFragmentItem::HasSVGTransformForBoundingBox() const {
- return Type() == kSVGText && svg_text_.data->angle != 0.0f;
+bool NGFragmentItem::HasSvgTransformForBoundingBox() const {
+ return Type() == kSvgText && svg_text_.data->angle != 0.0f;
}
// For non-<textPath>:
@@ -533,23 +583,23 @@ bool NGFragmentItem::HasSVGTransformForBoundingBox() const {
//
// (x, y) is the center of the rotation. The center points of a non-<textPath>
// character and a <textPath> character are different.
-AffineTransform NGFragmentItem::BuildSVGTransformForPaint() const {
- DCHECK_EQ(Type(), kSVGText);
+AffineTransform NGFragmentItem::BuildSvgTransformForPaint() const {
+ DCHECK_EQ(Type(), kSvgText);
if (svg_text_.data->in_text_path) {
if (svg_text_.data->angle == 0.0f)
- return BuildSVGTransformForLengthAdjust();
- return BuildSVGTransformForTextPath(BuildSVGTransformForLengthAdjust());
+ return BuildSvgTransformForLengthAdjust();
+ return BuildSvgTransformForTextPath(BuildSvgTransformForLengthAdjust());
}
- AffineTransform transform = BuildSVGTransformForBoundingBox();
- AffineTransform length_adjust = BuildSVGTransformForLengthAdjust();
+ AffineTransform transform = BuildSvgTransformForBoundingBox();
+ AffineTransform length_adjust = BuildSvgTransformForLengthAdjust();
if (!length_adjust.IsIdentity())
transform.PreMultiply(length_adjust);
return transform;
}
-AffineTransform NGFragmentItem::BuildSVGTransformForLengthAdjust() const {
- DCHECK_EQ(Type(), kSVGText);
- const NGSVGFragmentData& svg_data = *svg_text_.data;
+AffineTransform NGFragmentItem::BuildSvgTransformForLengthAdjust() const {
+ DCHECK_EQ(Type(), kSvgText);
+ const NGSvgFragmentData& svg_data = *svg_text_.data;
const bool is_horizontal = IsHorizontal();
AffineTransform scale_transform;
float scale = svg_data.length_adjust_scale;
@@ -572,10 +622,10 @@ AffineTransform NGFragmentItem::BuildSVGTransformForLengthAdjust() const {
return scale_transform;
}
-AffineTransform NGFragmentItem::BuildSVGTransformForTextPath(
+AffineTransform NGFragmentItem::BuildSvgTransformForTextPath(
const AffineTransform& length_adjust) const {
- DCHECK_EQ(Type(), kSVGText);
- const NGSVGFragmentData& svg_data = *svg_text_.data;
+ DCHECK_EQ(Type(), kSvgText);
+ const NGSvgFragmentData& svg_data = *svg_text_.data;
DCHECK(svg_data.in_text_path);
DCHECK_NE(svg_data.angle, 0.0f);
@@ -589,7 +639,7 @@ AffineTransform NGFragmentItem::BuildSVGTransformForTextPath(
// The rotation should be about the center of the baseline.
const auto font_baseline = Style().GetFontBaseline();
// |x| in the horizontal writing-mode and |y| in the vertical writing-mode
- // point the center of the baseline. See |NGSVGTextLayoutAlgorithm::
+ // point the center of the baseline. See |NGSvgTextLayoutAlgorithm::
// PositionOnPath()|.
float x = svg_data.rect.X();
float y = svg_data.rect.Y();
@@ -612,14 +662,14 @@ AffineTransform NGFragmentItem::BuildSVGTransformForTextPath(
//
// (x, y) is the center of the rotation. The center points of a non-<textPath>
// character and a <textPath> character are different.
-AffineTransform NGFragmentItem::BuildSVGTransformForBoundingBox() const {
- DCHECK_EQ(Type(), kSVGText);
- const NGSVGFragmentData& svg_data = *svg_text_.data;
+AffineTransform NGFragmentItem::BuildSvgTransformForBoundingBox() const {
+ DCHECK_EQ(Type(), kSvgText);
+ const NGSvgFragmentData& svg_data = *svg_text_.data;
AffineTransform transform;
if (svg_data.angle == 0.0f)
return transform;
if (svg_data.in_text_path)
- return BuildSVGTransformForTextPath(AffineTransform());
+ return BuildSvgTransformForTextPath(AffineTransform());
transform.Rotate(svg_data.angle);
const SimpleFontData* font_data =
@@ -639,6 +689,16 @@ AffineTransform NGFragmentItem::BuildSVGTransformForBoundingBox() const {
return transform;
}
+float NGFragmentItem::SvgScalingFactor() const {
+ const auto* svg_inline_text =
+ DynamicTo<LayoutSVGInlineText>(GetLayoutObject());
+ if (!svg_inline_text)
+ return 1.0f;
+ const float scaling_factor = svg_inline_text->ScalingFactor();
+ DCHECK_GT(scaling_factor, 0.0f);
+ return scaling_factor;
+}
+
String NGFragmentItem::ToString() const {
// TODO(yosin): Once |NGPaintFragment| is removed, we should get rid of
// following if-statements.
@@ -787,6 +847,10 @@ void NGFragmentItem::RecalcInkOverflow(
contents_rect.offset -= OffsetInContainerFragment();
if (Type() == kLine) {
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(GetLayoutObject());
+ if (UNLIKELY(text_combine))
+ contents_rect = text_combine->AdjustRectForBoundingBox(contents_rect);
// Line boxes don't have self overflow. Compute content overflow only.
*self_and_contents_rect_out = UnionRect(LocalRect(), contents_rect);
ink_overflow_type_ =
@@ -837,11 +901,15 @@ LayoutUnit NGFragmentItem::InlinePositionForOffset(
DCHECK_EQ(1u, text.length());
if (!offset || UNLIKELY(IsRtl(Style().Direction())))
return LayoutUnit();
+ if (Type() == kSvgText) {
+ return LayoutUnit(IsHorizontal() ? SvgFragmentData()->rect.Width()
+ : SvgFragmentData()->rect.Height());
+ }
return IsHorizontal() ? Size().width : Size().height;
}
-LayoutUnit NGFragmentItem::InlinePositionForOffset(StringView text,
- unsigned offset) const {
+LayoutUnit NGFragmentItem::CaretInlinePositionForOffset(StringView text,
+ unsigned offset) const {
return InlinePositionForOffset(text, offset, LayoutUnit::FromFloatRound,
AdjustMidCluster::kToEnd);
}
@@ -869,31 +937,63 @@ std::pair<LayoutUnit, LayoutUnit> NGFragmentItem::LineLeftAndRightForOffsets(
PhysicalRect NGFragmentItem::LocalRect(StringView text,
unsigned start_offset,
unsigned end_offset) const {
- if (start_offset == StartOffset() && end_offset == EndOffset())
- return LocalRect();
+ LayoutUnit width = Size().width;
+ LayoutUnit height = Size().height;
+ if (Type() == kSvgText) {
+ const NGSvgFragmentData& data = *SvgFragmentData();
+ if (IsHorizontal()) {
+ width = LayoutUnit(data.rect.Size().Width() / data.length_adjust_scale);
+ height = LayoutUnit(data.rect.Size().Height());
+ } else {
+ width = LayoutUnit(data.rect.Size().Width());
+ height = LayoutUnit(data.rect.Size().Height() / data.length_adjust_scale);
+ }
+ }
+ if (start_offset == StartOffset() && end_offset == EndOffset()) {
+ return {LayoutUnit(), LayoutUnit(), width, height};
+ }
LayoutUnit start_position, end_position;
std::tie(start_position, end_position) =
LineLeftAndRightForOffsets(text, start_offset, end_offset);
const LayoutUnit inline_size = end_position - start_position;
switch (GetWritingMode()) {
case WritingMode::kHorizontalTb:
- return {start_position, LayoutUnit(), inline_size, Size().height};
+ return {start_position, LayoutUnit(), inline_size, height};
case WritingMode::kVerticalRl:
case WritingMode::kVerticalLr:
case WritingMode::kSidewaysRl:
- return {LayoutUnit(), start_position, Size().width, inline_size};
+ return {LayoutUnit(), start_position, width, inline_size};
case WritingMode::kSidewaysLr:
- return {LayoutUnit(), Size().height - end_position, Size().width,
- inline_size};
+ return {LayoutUnit(), height - end_position, width, inline_size};
}
NOTREACHED();
return {};
}
+PhysicalRect NGFragmentItem::ComputeTextBoundsRectForHitTest(
+ const PhysicalOffset& inline_root_offset,
+ bool is_occlusion_test) const {
+ DCHECK(IsText());
+ const PhysicalOffset offset =
+ inline_root_offset + OffsetInContainerFragment();
+ const PhysicalRect border_rect(offset, Size());
+ if (UNLIKELY(is_occlusion_test)) {
+ PhysicalRect ink_overflow = SelfInkOverflow();
+ ink_overflow.Move(border_rect.offset);
+ return ink_overflow;
+ }
+ // We should not ignore fractional parts of border_rect in SVG because this
+ // item might have much larger screen size than border_rect.
+ // See svg/hittest/text-small-font-size.html.
+ if (Type() == kSvgText)
+ return border_rect;
+ return PhysicalRect(PixelSnappedIntRect(border_rect));
+}
+
PositionWithAffinity NGFragmentItem::PositionForPointInText(
const PhysicalOffset& point,
const NGInlineCursor& cursor) const {
- DCHECK(Type() == kText || Type() == kSVGText);
+ DCHECK(Type() == kText || Type() == kSvgText);
DCHECK_EQ(cursor.CurrentItem(), this);
if (IsGeneratedText())
return PositionWithAffinity();
@@ -904,7 +1004,7 @@ PositionWithAffinity NGFragmentItem::PositionForPointInText(
PositionWithAffinity NGFragmentItem::PositionForPointInText(
unsigned text_offset,
const NGInlineCursor& cursor) const {
- DCHECK(Type() == kText || Type() == kSVGText);
+ DCHECK(Type() == kText || Type() == kSvgText);
DCHECK_EQ(cursor.CurrentItem(), this);
DCHECK(!IsGeneratedText());
DCHECK_LE(text_offset, EndOffset());
@@ -921,15 +1021,16 @@ PositionWithAffinity NGFragmentItem::PositionForPointInText(
unsigned NGFragmentItem::TextOffsetForPoint(
const PhysicalOffset& point,
const NGFragmentItems& items) const {
- DCHECK(Type() == kText || Type() == kSVGText);
+ DCHECK(Type() == kText || Type() == kSvgText);
const ComputedStyle& style = Style();
const LayoutUnit& point_in_line_direction =
style.IsHorizontalWritingMode() ? point.left : point.top;
if (const ShapeResultView* shape_result = TextShapeResult()) {
+ float scaled_offset = ScaleInlineOffset(point_in_line_direction);
// TODO(layout-dev): Move caret logic out of ShapeResult into separate
// support class for code health and to avoid this copy.
return shape_result->CreateShapeResult()->CaretOffsetForHitTest(
- point_in_line_direction.ToFloat(), Text(items), BreakGlyphs) +
+ scaled_offset, Text(items), BreakGlyphs) +
StartOffset();
}
@@ -958,8 +1059,8 @@ std::ostream& operator<<(std::ostream& ostream, const NGFragmentItem& item) {
ostream << "Text " << item.StartOffset() << "-" << item.EndOffset() << " "
<< (IsLtr(item.ResolvedDirection()) ? "LTR" : "RTL");
break;
- case NGFragmentItem::kSVGText:
- ostream << "SVGText " << item.StartOffset() << "-" << item.EndOffset()
+ case NGFragmentItem::kSvgText:
+ ostream << "SvgText " << item.StartOffset() << "-" << item.EndOffset()
<< " " << (IsLtr(item.ResolvedDirection()) ? "LTR" : "RTL");
break;
case NGFragmentItem::kGeneratedText:
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
index 0502c7ac5fc..f0c12aa7b7a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -26,7 +26,7 @@ struct NGTextFragmentPaintInfo;
struct NGLogicalLineItem;
// Data for SVG text in addition to NGFragmentItem.
-struct NGSVGFragmentData {
+struct NGSvgFragmentData {
scoped_refptr<const ShapeResultView> shape_result;
NGTextOffset text_offset;
FloatRect rect;
@@ -50,8 +50,8 @@ class CORE_EXPORT NGFragmentItem {
const NGTextOffset text_offset;
};
// Represents text in SVG <text>.
- struct SVGTextItem {
- std::unique_ptr<NGSVGFragmentData> data;
+ struct SvgTextItem {
+ std::unique_ptr<NGSvgFragmentData> data;
};
// Represents text generated by the layout engine, e.g., hyphen or ellipsis.
struct GeneratedTextItem {
@@ -82,7 +82,7 @@ class CORE_EXPORT NGFragmentItem {
wtf_size_t descendants_count;
};
- enum ItemType { kText, kSVGText, kGeneratedText, kLine, kBox };
+ enum ItemType { kText, kSvgText, kGeneratedText, kLine, kBox };
// Create appropriate type for |line_item|.
NGFragmentItem(NGLogicalLineItem&& line_item, WritingMode writing_mode);
@@ -101,20 +101,22 @@ class CORE_EXPORT NGFragmentItem {
ItemType Type() const { return static_cast<ItemType>(type_); }
bool IsText() const {
- return Type() == kText || Type() == kSVGText || Type() == kGeneratedText;
+ return Type() == kText || Type() == kSvgText || Type() == kGeneratedText;
}
bool IsContainer() const { return Type() == kBox || Type() == kLine; }
bool IsInlineBox() const;
bool IsAtomicInline() const;
+ bool IsBlockInInline() const;
bool IsFloating() const;
bool IsEmptyLineBox() const;
bool IsHiddenForPaint() const { return is_hidden_for_paint_; }
bool IsListMarker() const;
- // Make this kSVGText type. |this| type must be kText.
- void ConvertToSVGText(std::unique_ptr<NGSVGFragmentData> data,
+ // Make this kSvgText type. |this| type must be kText.
+ void ConvertToSvgText(std::unique_ptr<NGSvgFragmentData> data,
const PhysicalRect& unscaled_rect,
bool is_hidden);
+ void SetSvgLineLocalRect(const PhysicalRect& unscaled_rect);
// A sequence number of fragments generated from a |LayoutObject|.
// For line boxes, please see |kInitialLineFragmentId|.
@@ -181,11 +183,25 @@ class CORE_EXPORT NGFragmentItem {
void SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const;
const PhysicalRect& RectInContainerFragment() const { return rect_; }
- // This function returns a transformed unscaled FloatRect for kSVGText
+ // This function returns a transformed unscaled FloatRect for kSvgText
// type, and returns a FloatRect just converted from
// RectInContainerFragment() for other types.
FloatRect ObjectBoundingBox() const;
+ // Returns a point transformed by the inverse of
+ // BuildSvgTransformForBoundingBox(). The return value can be compared with
+ // untransformed RectInContainerFragment().
+ PhysicalOffset MapPointInContainer(const PhysicalOffset& point) const;
+
+ // For kSvgText type, convert the specified inline offset in this item so
+ // that the result can be used with ShapeResult.
+ float ScaleInlineOffset(LayoutUnit inline_offset) const;
+
+ // Returns true if |position|, which is a point in the IFC's coordinate
+ // system, is in the transformed rectangle of this item.
+ // This works only for kSvgText type.
+ bool Contains(const FloatPoint& position) const;
+
const PhysicalOffset& OffsetInContainerFragment() const {
return rect_.offset;
}
@@ -195,7 +211,6 @@ class CORE_EXPORT NGFragmentItem {
PhysicalRect InkOverflow() const;
PhysicalRect SelfInkOverflow() const;
- PhysicalRect ContentsInkOverflow() const;
// Count of following items that are descendants of this item in the box tree,
// including this item. 1 means this is a box (box or line box) without
@@ -300,9 +315,9 @@ class CORE_EXPORT NGFragmentItem {
return Style().GetWritingMode();
}
- // Functions for |TextItem|, |SVGTextItem|, and |GeneratedTextItem|.
+ // Functions for |TextItem|, |SvgTextItem|, and |GeneratedTextItem|.
NGTextType TextType() const {
- if (Type() == kText || Type() == kSVGText)
+ if (Type() == kText || Type() == kSvgText)
return static_cast<NGTextType>(sub_type_);
if (Type() == kGeneratedText)
return NGTextType::kLayoutGenerated;
@@ -337,14 +352,12 @@ class CORE_EXPORT NGFragmentItem {
bool IsStyleGeneratedText() const;
bool IsGeneratedText() const;
+ bool IsFormattingContextRoot() const;
+
bool IsSymbolMarker() const {
return TextType() == NGTextType::kSymbolMarker;
}
- bool IsFormattingContextRoot() const {
- return BoxFragment() && !IsInlineBox();
- }
-
const ShapeResultView* TextShapeResult() const;
NGTextOffset TextOffset() const;
unsigned StartOffset() const { return TextOffset().start; }
@@ -364,16 +377,13 @@ class CORE_EXPORT NGFragmentItem {
NGTextFragmentPaintInfo TextPaintInfo(const NGFragmentItems& items) const;
// Compute the inline position from text offset, in logical coordinate
- // relative to this fragment.
- LayoutUnit InlinePositionForOffset(StringView text,
- unsigned offset,
- LayoutUnit (*round_function)(float),
- AdjustMidCluster) const;
-
- LayoutUnit InlinePositionForOffset(StringView text, unsigned offset) const;
+ // relative to this fragment suitable for |LocalCaretRect|.
+ LayoutUnit CaretInlinePositionForOffset(StringView text,
+ unsigned offset) const;
// Compute line-relative coordinates for given offsets, this is not
// flow-relative:
+ // This returns scaled values for kSVGText type.
// https://drafts.csswg.org/css-writing-modes-3/#line-directions
std::pair<LayoutUnit, LayoutUnit> LineLeftAndRightForOffsets(
StringView text,
@@ -382,6 +392,7 @@ class CORE_EXPORT NGFragmentItem {
// The layout box of text in (start, end) range in local coordinate.
// Start and end offsets must be between StartOffset() and EndOffset().
+ // This returns a scaled PhysicalRect for kSVGText type.
PhysicalRect LocalRect(StringView text,
unsigned start_offset,
unsigned end_offset) const;
@@ -396,6 +407,12 @@ class CORE_EXPORT NGFragmentItem {
// Note: <span> doesn't have text direction.
TextDirection ResolvedDirection() const;
+ // Returns |PhysicalRect| to intersect with hit test location for |this|
+ // text item. See |NGBoxFragmentPainter::HitTestTextItem()|.
+ PhysicalRect ComputeTextBoundsRectForHitTest(
+ const PhysicalOffset& inline_root_offset,
+ bool is_occlusion_test) const;
+
// Converts the given point, relative to the fragment itself, into a position
// in DOM tree.
PositionWithAffinity PositionForPointInText(
@@ -416,22 +433,30 @@ class CORE_EXPORT NGFragmentItem {
const NGFragmentItem* operator->() const { return this; }
- const NGSVGFragmentData* SVGFragmentData() const {
- return Type() == kSVGText ? svg_text_.data.get() : nullptr;
+ const NGSvgFragmentData* SvgFragmentData() const {
+ return Type() == kSvgText ? svg_text_.data.get() : nullptr;
}
- // Returns true if BuildSVGTransformForPaint() returns non-identity transform.
- bool HasSVGTransformForPaint() const;
+ // Returns true if BuildSvgTransformForPaint() returns non-identity transform.
+ bool HasSvgTransformForPaint() const;
// A transform which should be used on painting this fragment.
// This contains a transform for lengthAdjust=spacingAndGlyphs.
- AffineTransform BuildSVGTransformForPaint() const;
- // Returns true if BuildSVGTransformForBoundingBox() returns non-identity
+ AffineTransform BuildSvgTransformForPaint() const;
+ // Returns true if BuildSvgTransformForBoundingBox() returns non-identity
// transform.
- bool HasSVGTransformForBoundingBox() const;
+ bool HasSvgTransformForBoundingBox() const;
// A transform which should be used on computing a bounding box.
// This contains no transform for lengthAdjust=spacingAndGlyphs because
// FloatRectInContainerFragment() already takes into account of
// lengthAdjust=spacingAndGlyphs.
- AffineTransform BuildSVGTransformForBoundingBox() const;
+ AffineTransform BuildSvgTransformForBoundingBox() const;
+
+ // Returns a transformed text cell in the unscaled coordination system.
+ // This works only with kSvgText type.
+ FloatQuad SvgUnscaledQuad() const;
+
+ // Returns a font scaling factor for SVG <text>.
+ // This returns 1 for an NGFragmentItem not for LayoutSVGInlineText.
+ float SvgScalingFactor() const;
// Get a description of |this| for the debug purposes.
String ToString() const;
@@ -440,6 +465,7 @@ class CORE_EXPORT NGFragmentItem {
FRIEND_TEST_ALL_PREFIXES(NGFragmentItemTest, CopyMove);
FRIEND_TEST_ALL_PREFIXES(NGFragmentItemTest, SelfPaintingInlineBox);
FRIEND_TEST_ALL_PREFIXES(StyleChangeTest, NeedsCollectInlinesOnStyle);
+ friend class LayoutNGTextCombineTest;
// Create a text item.
NGFragmentItem(const NGInlineItem& inline_item,
@@ -481,9 +507,16 @@ class CORE_EXPORT NGFragmentItem {
void RecalcInkOverflow(const NGInlineCursor& cursor,
PhysicalRect* self_and_contents_rect_out);
- AffineTransform BuildSVGTransformForTextPath(
+ // Compute the inline position from text offset, in logical coordinate
+ // relative to this fragment.
+ LayoutUnit InlinePositionForOffset(StringView text,
+ unsigned offset,
+ LayoutUnit (*round_function)(float),
+ AdjustMidCluster) const;
+
+ AffineTransform BuildSvgTransformForTextPath(
const AffineTransform& length_adjust) const;
- AffineTransform BuildSVGTransformForLengthAdjust() const;
+ AffineTransform BuildSvgTransformForLengthAdjust() const;
const LayoutObject* layout_object_;
@@ -492,7 +525,7 @@ class CORE_EXPORT NGFragmentItem {
// cannot create a vector of this class.
union {
TextItem text_;
- SVGTextItem svg_text_;
+ SvgTextItem svg_text_;
GeneratedTextItem generated_text_;
LineItem line_;
BoxItem box_;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
index 9a2799320a7..982c01ccfba 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
@@ -394,6 +394,40 @@ TEST_F(NGFragmentItemTest, StartOffsetInContainer) {
EXPECT_EQ(12u, cursor.Current()->StartOffsetInContainer(cursor));
}
+TEST_F(NGFragmentItemTest, EllipsizedAtomicInline) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #container {
+ width: 100px;
+ white-space: pre;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ #atomic {
+ display: inline-block;
+ width: 200px;
+ }
+ </style>
+ <div id="container"><span id="atomic"> </span>XXXXXX</div>
+ )HTML");
+ auto* container =
+ To<LayoutBlockFlow>(GetLayoutObjectByElementId("container"));
+ auto* atomic = GetLayoutObjectByElementId("atomic");
+ NGInlineCursor cursor(*container);
+ cursor.MoveToNext();
+ EXPECT_EQ(cursor.Current().GetLayoutObject(), atomic);
+ EXPECT_EQ(cursor.Current()->Type(), NGFragmentItem::kBox);
+ // When atomic inline is ellipsized, |IsLastForNode| should be set to the last
+ // |kBox| item, even if ellipses follow.
+ EXPECT_TRUE(cursor.Current()->IsLastForNode());
+ cursor.MoveToNext();
+ EXPECT_EQ(cursor.Current()->Type(), NGFragmentItem::kText);
+ cursor.MoveToNext();
+ EXPECT_EQ(cursor.Current().GetLayoutObject(), atomic);
+ EXPECT_EQ(cursor.Current()->Type(), NGFragmentItem::kGeneratedText);
+ EXPECT_TRUE(cursor.Current()->IsLastForNode());
+}
+
// Various nodes/elements to test insertions.
using CreateNode = Node* (*)(Document&);
static CreateNode node_creators[] = {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
index 473e34bd69f..748cf6c7f60 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
@@ -30,7 +30,7 @@ void CheckNoItemsAreAssociated(const NGPhysicalBoxFragment& fragment) {
void CheckIsLast(const NGFragmentItem& item) {
if (const NGPhysicalBoxFragment* fragment = item.BoxFragment()) {
if (!fragment->IsInline()) {
- DCHECK(fragment->IsFloating());
+ DCHECK(!fragment->IsInlineBox());
DCHECK_EQ(item.IsLastForNode(), !fragment->BreakToken());
}
}
@@ -117,14 +117,16 @@ void NGFragmentItems::FinalizeAfterLayout(
DCHECK(layout_object->IsInLayoutNGInlineFormattingContext());
item.SetDeltaToNextForSameLayoutObject(0);
- if (UNLIKELY(layout_object->IsFloating())) {
+ const bool use_break_token =
+ layout_object->IsFloating() || !layout_object->IsInline();
+ if (UNLIKELY(use_break_token)) {
// Fragments that aren't really on a line, such as floats, will have
// block break tokens if they continue in a subsequent fragmentainer, so
// just check that. Floats in particular will continue as regular box
// fragment children in subsequent fragmentainers, i.e. they will not be
// fragment items (even if we're in an inline formatting context). So
// we're not going to find the last fragment by just looking for items.
- DCHECK(item.BoxFragment() && item.BoxFragment()->IsFloating());
+ DCHECK(item.BoxFragment() && !item.BoxFragment()->IsInlineBox());
item.SetIsLastForNode(!item.BoxFragment()->BreakToken());
} else {
DCHECK(layout_object->IsInline());
@@ -155,7 +157,13 @@ void NGFragmentItems::FinalizeAfterLayout(
DCHECK_LT(last_index, fragment_items->EndItemIndex());
DCHECK_LT(last_index, item_index);
last_item->SetDeltaToNextForSameLayoutObject(item_index - last_index);
- if (!layout_object->IsFloating())
+ // Because we found a following fragment, reset |IsLastForNode| for the
+ // last item except:
+ // a. |IsLastForNode| is computed from break token. The last item already
+ // has the correct value.
+ // b. Ellipses for atomic inlines. |IsLastForNode| of the last box item
+ // should be set to ease handling of this edge case.
+ if (!use_break_token && !(layout_object->IsBox() && item.IsEllipsis()))
last_item->SetIsLastForNode(false);
#if DCHECK_IS_ON()
CheckIsLast(*last_item);
@@ -221,9 +229,6 @@ const NGFragmentItem* NGFragmentItems::EndOfReusableItems(
if (item.Type() != NGFragmentItem::kLine)
return &item;
- const NGPhysicalLineBoxFragment* line_box_fragment = item.LineBoxFragment();
- DCHECK(line_box_fragment);
-
// If there is a dirty item in the middle of a line, its previous line is
// not reusable, because the dirty item may affect the previous line to wrap
// differently.
@@ -231,9 +236,17 @@ const NGFragmentItem* NGFragmentItems::EndOfReusableItems(
if (!CanReuseAll(&line))
return last_line_start;
+ const NGPhysicalLineBoxFragment& line_box_fragment =
+ *item.LineBoxFragment();
+
// Abort if the line propagated its descendants to outside of the line.
// They are propagated through NGLayoutResult, which we don't cache.
- if (line_box_fragment->HasPropagatedDescendants())
+ if (line_box_fragment.HasPropagatedDescendants())
+ return &item;
+
+ // Abort if we are an empty line-box. We don't have any content, and might
+ // resolve the BFC block-offset at the incorrect position.
+ if (line_box_fragment.IsEmptyLineBox())
return &item;
// TODO(kojii): Running the normal layout code at least once for this
@@ -241,7 +254,7 @@ const NGFragmentItem* NGFragmentItems::EndOfReusableItems(
// partial. Remove the last fragment if it is the end of the
// fragmentation to do so, but we should figure out how to setup the
// states without doing this.
- if (!line_box_fragment->BreakToken())
+ if (!line_box_fragment.BreakToken())
return &item;
last_line_start = &item;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
index adb1aa093b6..43b8c8dab59 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -222,7 +222,8 @@ NGFragmentItemsBuilder::AddPreviousItems(
DCHECK(items_.IsEmpty());
const NGFragmentItems::Span source_items = items.Items();
- const wtf_size_t estimated_size = source_items.size();
+ const wtf_size_t estimated_size =
+ base::checked_cast<wtf_size_t>(source_items.size());
items_.ReserveCapacity(estimated_size);
// Convert offsets to logical. The logic is opposite to |ConvertToPhysical|.
@@ -384,8 +385,8 @@ void NGFragmentItemsBuilder::ToFragmentItems(const PhysicalSize& outer_size,
void* data) {
DCHECK(text_content_);
ConvertToPhysical(outer_size);
- if (node_.IsSVGText()) {
- NGSVGTextLayoutAlgorithm(node_, GetWritingMode())
+ if (node_.IsSvgText()) {
+ NGSvgTextLayoutAlgorithm(node_, GetWritingMode())
.Layout(TextContent(false), items_);
}
new (data) NGFragmentItems(this);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
index 1a503dc79c5..17596d0969d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEMS_BUILDER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEMS_BUILDER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h"
@@ -69,6 +70,7 @@ class CORE_EXPORT NGFragmentItemsBuilder {
// |NGFragmentItemsBuilder| allocates new instance for each line, and keeps
// them alive until |AddLine|.
NGLogicalLineItems* AcquireLogicalLineItems();
+ void ReleaseCurrentLogicalLineItems();
void AssociateLogicalLineItems(NGLogicalLineItems* line_items,
const NGPhysicalFragment& line_fragment);
void AddLine(const NGPhysicalLineBoxFragment& line,
@@ -141,7 +143,6 @@ class CORE_EXPORT NGFragmentItemsBuilder {
void ToFragmentItems(const PhysicalSize& outer_size, void* data);
private:
- void ReleaseCurrentLogicalLineItems();
void MoveCurrentLogicalLineItemsToMap();
void AddItems(NGLogicalLineItem* child_begin, NGLogicalLineItem* child_end);
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 15407a3d50a..c42e1835449 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
@@ -7,6 +7,7 @@
#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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_line_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
@@ -14,6 +15,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
namespace blink {
@@ -35,31 +37,95 @@ FontHeight ComputeEmphasisMarkOutsets(const ComputedStyle& style,
} // namespace
-void NGInlineBoxState::InitializeFont(bool is_svg_text,
- const LayoutObject& layout_object) {
+NGInlineBoxState::NGInlineBoxState(const NGInlineBoxState&& state)
+ : fragment_start(state.fragment_start),
+ item(state.item),
+ style(state.style),
+ scaled_font(state.scaled_font),
+ scaling_factor(state.scaling_factor),
+ metrics(state.metrics),
+ text_metrics(state.text_metrics),
+ text_top(state.text_top),
+ text_height(state.text_height),
+ alignment_type(state.alignment_type),
+ has_start_edge(state.has_start_edge),
+ has_end_edge(state.has_end_edge),
+ margin_inline_start(state.margin_inline_start),
+ margin_inline_end(state.margin_inline_end),
+ borders(state.borders),
+ padding(state.padding),
+ pending_descendants(std::move(state.pending_descendants)),
+ include_used_fonts(state.include_used_fonts),
+ has_box_placeholder(state.has_box_placeholder),
+ needs_box_fragment(state.needs_box_fragment),
+ is_svg_text(state.is_svg_text) {
+ if (state.scaled_font)
+ font = &*scaled_font;
+ else
+ font = state.font;
+}
+
+void NGInlineBoxState::ResetStyle(const ComputedStyle& style_ref,
+ bool is_svg,
+ const LayoutObject& layout_object) {
+ style = &style_ref;
+ is_svg_text = is_svg;
if (!is_svg_text) {
+ scaling_factor = 1.0f;
font = &style->GetFont();
return;
}
scaled_font.emplace();
- float scaling_factor;
LayoutSVGInlineText::ComputeNewScaledFontForStyle(
layout_object, scaling_factor, *scaled_font);
- if (scaling_factor == 1.0f) {
- scaled_font = absl::nullopt;
- font = &style->GetFont();
- } else {
- font = &*scaled_font;
+ font = &*scaled_font;
+ switch (style_ref.AlignmentBaseline()) {
+ case EAlignmentBaseline::kAuto:
+ case EAlignmentBaseline::kBaseline:
+ alignment_type = style_ref.GetFontBaseline();
+ break;
+ case EAlignmentBaseline::kBeforeEdge:
+ case EAlignmentBaseline::kTextBeforeEdge:
+ alignment_type = FontBaseline::kTextOverBaseline;
+ break;
+ case EAlignmentBaseline::kMiddle:
+ alignment_type = FontBaseline::kXMiddleBaseline;
+ break;
+ case EAlignmentBaseline::kCentral:
+ alignment_type = FontBaseline::kCentralBaseline;
+ break;
+ case EAlignmentBaseline::kAfterEdge:
+ case EAlignmentBaseline::kTextAfterEdge:
+ alignment_type = FontBaseline::kTextUnderBaseline;
+ break;
+ case EAlignmentBaseline::kIdeographic:
+ alignment_type = FontBaseline::kIdeographicUnderBaseline;
+ break;
+ case EAlignmentBaseline::kAlphabetic:
+ alignment_type = FontBaseline::kAlphabeticBaseline;
+ break;
+ case EAlignmentBaseline::kHanging:
+ alignment_type = FontBaseline::kHangingBaseline;
+ break;
+ case EAlignmentBaseline::kMathematical:
+ alignment_type = FontBaseline::kMathBaseline;
+ break;
}
}
void NGInlineBoxState::ComputeTextMetrics(const ComputedStyle& styleref,
- const Font& fontref,
- FontBaseline baseline_type) {
- if (const SimpleFontData* font_data = fontref.PrimaryFont())
- text_metrics = font_data->GetFontMetrics().GetFontHeight(baseline_type);
- else
+ const Font& fontref) {
+ const auto baseline_type = styleref.GetFontBaseline();
+ if (const SimpleFontData* font_data = fontref.PrimaryFont()) {
+ if (is_svg_text) {
+ text_metrics =
+ font_data->GetFontMetrics().GetFloatFontHeight(baseline_type);
+ } else {
+ text_metrics = font_data->GetFontMetrics().GetFontHeight(baseline_type);
+ }
+ } else {
text_metrics = FontHeight();
+ }
text_top = -text_metrics.ascent;
text_height = text_metrics.LineHeight();
@@ -87,14 +153,14 @@ void NGInlineBoxState::ResetTextMetrics() {
}
void NGInlineBoxState::EnsureTextMetrics(const ComputedStyle& styleref,
- const Font& fontref,
- FontBaseline baseline_type) {
+ const Font& fontref) {
if (text_metrics.IsEmpty())
- ComputeTextMetrics(styleref, fontref, baseline_type);
+ ComputeTextMetrics(styleref, fontref);
}
-void NGInlineBoxState::AccumulateUsedFonts(const ShapeResultView* shape_result,
- FontBaseline baseline_type) {
+void NGInlineBoxState::AccumulateUsedFonts(
+ const ShapeResultView* shape_result) {
+ const auto baseline_type = style->GetFontBaseline();
HashSet<const SimpleFontData*> fallback_fonts;
shape_result->FallbackFonts(&fallback_fonts);
for (const SimpleFontData* const fallback_font : fallback_fonts) {
@@ -132,7 +198,7 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
FontBaseline baseline_type,
bool line_height_quirk,
NGLogicalLineItems* line_box) {
- is_svg_text_ = node.IsSVGText();
+ is_svg_text_ = node.IsSvgText();
if (stack_.IsEmpty()) {
// For the first line, push a box state for the line itself.
stack_.resize(1);
@@ -166,15 +232,14 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
// Initialize the box state for the line box.
NGInlineBoxState& line_box_state = LineBoxState();
if (line_box_state.style != &line_style) {
- line_box_state.style = &line_style;
- line_box_state.InitializeFont(node.IsSVGText(), *node.GetLayoutBox());
+ line_box_state.ResetStyle(line_style, node.IsSvgText(),
+ *node.GetLayoutBox());
// Use a "strut" (a zero-width inline box with the element's font and
// line height properties) as the initial metrics for the line box.
// https://drafts.csswg.org/css2/visudet.html#strut
if (!line_height_quirk) {
- line_box_state.ComputeTextMetrics(line_style, *line_box_state.font,
- baseline_type);
+ line_box_state.ComputeTextMetrics(line_style, *line_box_state.font);
}
}
@@ -204,8 +269,7 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
stack_.resize(stack_.size() + 1);
NGInlineBoxState* box = &stack_.back();
box->fragment_start = line_box.size();
- box->style = &style;
- box->InitializeFont(is_svg_text_, *item.GetLayoutObject());
+ box->ResetStyle(style, is_svg_text_, *item.GetLayoutObject());
box->item = &item;
box->has_start_edge = item_result.has_edge;
box->margin_inline_start = item_result.margins.inline_start;
@@ -234,12 +298,11 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnCloseTag(
void NGInlineLayoutStateStack::OnEndPlaceItems(const NGConstraintSpace& space,
NGLogicalLineItems* line_box,
FontBaseline baseline_type) {
- for (auto it = stack_.rbegin(); it != stack_.rend(); ++it) {
- NGInlineBoxState* box = &(*it);
- if (!box->has_end_edge && box->needs_box_fragment &&
- box->style->BoxDecorationBreak() == EBoxDecorationBreak::kClone)
- box->has_end_edge = true;
- EndBoxState(space, box, line_box, baseline_type);
+ for (auto& box : base::Reversed(stack_)) {
+ if (!box.has_end_edge && box.needs_box_fragment &&
+ box.style->BoxDecorationBreak() == EBoxDecorationBreak::kClone)
+ box.has_end_edge = true;
+ EndBoxState(space, &box, line_box, baseline_type);
}
// Up to this point, the offset of inline boxes are stored in placeholder so
@@ -283,8 +346,6 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
DCHECK(box != stack_.begin() &&
box->item->Type() != NGInlineItem::kAtomicInline);
box->has_box_placeholder = true;
- DCHECK(box->style);
- const ComputedStyle& style = *box->style;
LayoutUnit block_offset;
LayoutUnit block_size;
@@ -292,7 +353,13 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
// The inline box should have the height of the font metrics without the
// line-height property. Compute from style because |box->metrics| includes
// the line-height property.
- FontHeight metrics = style.GetFontHeight(baseline_type);
+ FontHeight metrics;
+ if (const auto* font_data = box->font->PrimaryFont()) {
+ metrics =
+ is_svg_text_
+ ? font_data->GetFontMetrics().GetFloatFontHeight(baseline_type)
+ : font_data->GetFontMetrics().GetFontHeight(baseline_type);
+ }
// Extend the block direction of the box by borders and paddings. Inline
// direction is already included into positions in NGLineBreaker.
@@ -349,15 +416,13 @@ void NGInlineLayoutStateStack::AddBoxData(const NGConstraintSpace& space,
// An empty box fragment is still flat that we do not have to defer.
// Also, placeholders cannot be reordred if empty.
placeholder.rect.offset.inline_offset += box_data.margin_line_left;
- // TODO(almaher): Handle inline relative positioning correctly for OOF
- // fragmentation.
placeholder.rect.offset +=
ComputeRelativeOffsetForInline(space, *box_data.item->Style());
LayoutUnit advance = box_data.margin_border_padding_line_left +
box_data.margin_border_padding_line_right;
box_data.rect.size.inline_size =
advance - box_data.margin_line_left - box_data.margin_line_right;
- placeholder.layout_result = box_data.CreateBoxFragment(line_box);
+ placeholder.layout_result = box_data.CreateBoxFragment(space, line_box);
placeholder.inline_size = advance;
DCHECK(!placeholder.children_count);
box_data_list_.pop_back();
@@ -564,7 +629,8 @@ void NGInlineLayoutStateStack::BoxData::UpdateFragmentEdges(
LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
NGLogicalLineItems* line_box,
- LayoutUnit position) {
+ LayoutUnit position,
+ bool ignore_box_margin_border_padding) {
// At this point, children are in the visual order, and they have their
// origins at (0, 0). Accumulate inline offset from left to right.
for (NGLogicalLineItem& child : *line_box) {
@@ -580,22 +646,24 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
if (box_data_list_.IsEmpty())
return position;
- // 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);
-
- if (box_data.margin_border_padding_line_left) {
- line_box->MoveInInlineDirection(box_data.margin_border_padding_line_left,
- start, line_box->size());
- position += box_data.margin_border_padding_line_left;
- }
+ if (!ignore_box_margin_border_padding) {
+ // 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);
+
+ if (box_data.margin_border_padding_line_left) {
+ line_box->MoveInInlineDirection(
+ box_data.margin_border_padding_line_left, start, line_box->size());
+ position += box_data.margin_border_padding_line_left;
+ }
- if (box_data.margin_border_padding_line_right) {
- line_box->MoveInInlineDirection(box_data.margin_border_padding_line_right,
- end, line_box->size());
- position += box_data.margin_border_padding_line_right;
+ if (box_data.margin_border_padding_line_right) {
+ line_box->MoveInInlineDirection(
+ box_data.margin_border_padding_line_right, end, line_box->size());
+ position += box_data.margin_border_padding_line_right;
+ }
}
}
@@ -617,8 +685,6 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
LayoutUnit line_left_offset =
start_child.rect.offset.inline_offset - start_child.margin_line_left;
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;
@@ -627,8 +693,16 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
last_child.margin_line_left +
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;
+
+ if (!ignore_box_margin_border_padding) {
+ start_padding.line_left += box_data.margin_border_padding_line_left;
+ last_padding.line_right += box_data.margin_border_padding_line_right;
+ line_left_offset += box_data.margin_line_left;
+ line_right_offset -= box_data.margin_line_right;
+ }
+
+ line_left_offset -= start_padding.line_left;
+ line_right_offset += last_padding.line_right;
box_data.rect.offset.inline_offset = line_left_offset;
box_data.rect.size.inline_size = line_right_offset - line_left_offset;
@@ -639,49 +713,66 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
void NGInlineLayoutStateStack::ApplyRelativePositioning(
const NGConstraintSpace& space,
- NGLogicalLineItems* line_box) {
+ NGLogicalLineItems* line_box,
+ Vector<LogicalOffset, 32>* oof_relative_offsets) {
if (box_data_list_.IsEmpty())
return;
+ DCHECK(oof_relative_offsets);
+ DCHECK_EQ(oof_relative_offsets->size(), box_data_list_.size());
+
// The final position of any inline boxes, (<span>, etc) are stored on
// |BoxData::rect|. As we don't have a mapping from |NGLogicalLineItem| to
// |BoxData| we store the accumulated relative offsets, and then apply the
// final adjustment at the end of this function.
Vector<LogicalOffset, 32> accumulated_offsets(line_box->size());
+ Vector<LogicalOffset, 32> oof_accumulated_offsets(line_box->size());
for (BoxData& box_data : box_data_list_) {
unsigned start = box_data.fragment_start;
unsigned end = box_data.fragment_end;
- // TODO(almaher): Handle inline relative positioning correctly for OOF
- // fragmentation.
const LogicalOffset relative_offset =
ComputeRelativeOffsetForInline(space, *box_data.item->Style());
+ const LogicalOffset relative_offset_for_oof =
+ ComputeRelativeOffsetForOOFInInline(space, *box_data.item->Style());
// Move all children for this box.
for (unsigned index = start; index < end; index++) {
auto& child = (*line_box)[index];
child.rect.offset += relative_offset;
accumulated_offsets[index] += relative_offset;
+ oof_accumulated_offsets[index] += relative_offset_for_oof;
}
}
// Apply the final accumulated relative position offset for each box.
- for (BoxData& box_data : box_data_list_)
+ for (wtf_size_t i = 0; i < box_data_list_.size(); i++) {
+ BoxData& box_data = box_data_list_[i];
box_data.rect.offset += accumulated_offsets[box_data.fragment_start];
+ (*oof_relative_offsets)[i] =
+ oof_accumulated_offsets[box_data.fragment_start];
+ }
}
void NGInlineLayoutStateStack::CreateBoxFragments(
- NGLogicalLineItems* line_box) {
+ const NGConstraintSpace& space,
+ NGLogicalLineItems* line_box,
+ bool is_opaque,
+ Vector<LogicalOffset, 32>* oof_relative_offsets) {
DCHECK(!box_data_list_.IsEmpty());
+ DCHECK(oof_relative_offsets);
+ DCHECK_EQ(oof_relative_offsets->size(), box_data_list_.size());
- for (BoxData& box_data : box_data_list_) {
+ for (wtf_size_t i = 0; i < box_data_list_.size(); i++) {
+ BoxData& box_data = box_data_list_[i];
unsigned start = box_data.fragment_start;
unsigned end = box_data.fragment_end;
DCHECK_GT(end, start);
NGLogicalLineItem* child = &(*line_box)[start];
DCHECK(box_data.item->ShouldCreateBoxFragment());
scoped_refptr<const NGLayoutResult> box_fragment =
- box_data.CreateBoxFragment(line_box);
+ box_data.CreateBoxFragment(space, line_box, is_opaque,
+ (*oof_relative_offsets)[i]);
if (child->IsPlaceholder()) {
child->layout_result = std::move(box_fragment);
child->rect = box_data.rect;
@@ -701,7 +792,10 @@ void NGInlineLayoutStateStack::CreateBoxFragments(
scoped_refptr<const NGLayoutResult>
NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
- NGLogicalLineItems* line_box) {
+ const NGConstraintSpace& space,
+ NGLogicalLineItems* line_box,
+ bool is_opaque,
+ LogicalOffset oof_relative_offset) {
DCHECK(item);
DCHECK(item->Style());
const ComputedStyle& style = *item->Style();
@@ -720,10 +814,16 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
box.SetBoxType(NGPhysicalFragment::kInlineBox);
box.SetStyleVariant(item->StyleVariant());
- // Inline boxes have block start/end borders, even when its containing block
- // was fragmented. Fragmenting a line box in block direction is not
- // supported today.
- box.SetSidesToInclude({true, has_line_right_edge, true, has_line_left_edge});
+ if (UNLIKELY(is_opaque)) {
+ box.SetIsOpaque();
+ box.SetSidesToInclude({false, false, false, false});
+ } else {
+ // Inline boxes have block start/end borders, even when its containing block
+ // was fragmented. Fragmenting a line box in block direction is not
+ // supported today.
+ box.SetSidesToInclude(
+ {true, has_line_right_edge, true, has_line_left_edge});
+ }
for (unsigned i = fragment_start; i < fragment_end; i++) {
NGLogicalLineItem& child = (*line_box)[i];
@@ -741,6 +841,7 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
// this as a child of an inline level fragment, we adjust the static
// position to be relative to this fragment.
LogicalOffset static_offset = child.rect.offset - rect.offset;
+ static_offset += oof_relative_offset;
box.AddOutOfFlowInlineChildCandidate(oof_box, static_offset,
child.container_direction);
@@ -750,10 +851,13 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
// Propagate any OOF-positioned descendants from any atomic-inlines, etc.
if (child.layout_result) {
- // TODO(almaher): Handle the inline case correctly for OOF fragmentation.
- // The relative offset should not always be set to LogicalOffset() here.
+ // An accumulated relative offset is applied to an OOF once it reaches its
+ // inline container. Subtract out the relative offset to avoid adding it
+ // twice.
box.PropagateChildData(child.layout_result->PhysicalFragment(),
- child.rect.offset - rect.offset,
+ child.rect.offset - rect.offset -
+ ComputeRelativeOffsetForInline(
+ space, child.PhysicalFragment()->Style()),
/* relative_offset */ LogicalOffset());
}
@@ -766,7 +870,7 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
// invalidations.
item->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
- box.MoveOutOfFlowDescendantCandidatesToDescendants();
+ box.MoveOutOfFlowDescendantCandidatesToDescendants(oof_relative_offset);
return box.ToInlineBoxFragment();
}
@@ -841,8 +945,60 @@ NGInlineLayoutStateStack::ApplyBaselineShift(NGInlineBoxState* box,
const ComputedStyle& style = *box->style;
EVerticalAlign vertical_align = style.VerticalAlign();
- if (vertical_align == EVerticalAlign::kBaseline)
+ if (!is_svg_text_ && vertical_align == EVerticalAlign::kBaseline)
+ return kPositionNotPending;
+
+ if (UNLIKELY(box->item &&
+ IsA<LayoutNGTextCombine>(box->item->GetLayoutObject()))) {
+ // Text content in text-combine-upright:all is layout in horizontally, so
+ // we don't need to move text combine box.
+ // See "text-combine-shrink-to-fit.html".
+ return kPositionNotPending;
+ }
+
+ // Check if there are any fragments to move.
+ unsigned fragment_end = line_box->size();
+ if (box->fragment_start == fragment_end)
+ return kPositionNotPending;
+
+ // SVG <text> supports not |vertical-align| but |baseline-shift|.
+ // https://drafts.csswg.org/css-inline/#propdef-vertical-align says
+ // |vertical-align| is a shorthand property of |baseline-shift| and
+ // |alignment-baseline|. However major browsers have never supported
+ // |vertical-align| in SVG <text>. Also, the shift amount computation
+ // for |baseline-shift| is not same as one for |vertical-align|.
+ // For now we follow the legacy behavior. If we'd like to follow the
+ // standard, first we should add a UseCounter for non-zero
+ // |baseline-shift|.
+ if (is_svg_text_) {
+ switch (style.BaselineShiftType()) {
+ case EBaselineShiftType::kLength: {
+ const Length& length = style.BaselineShift();
+ // ValueForLength() should be called with unscaled values.
+ baseline_shift =
+ LayoutUnit(-SVGLengthContext::ValueForLength(
+ length, style,
+ box->font->GetFontDescription().ComputedPixelSize() /
+ box->scaling_factor) *
+ box->scaling_factor);
+ break;
+ }
+ case EBaselineShiftType::kSub:
+ baseline_shift = LayoutUnit(
+ box->font->PrimaryFont()->GetFontMetrics().FloatHeight() / 2);
+ break;
+ case EBaselineShiftType::kSuper:
+ baseline_shift = LayoutUnit(
+ -box->font->PrimaryFont()->GetFontMetrics().FloatHeight() / 2);
+ break;
+ }
+ baseline_shift += ComputeAlignmentBaselineShift(box);
+ if (!box->metrics.IsEmpty())
+ box->metrics.Move(baseline_shift);
+ line_box->MoveInBlockDirection(baseline_shift, box->fragment_start,
+ fragment_end);
return kPositionNotPending;
+ }
// 'vertical-align' aligns boxes relative to themselves, to their parent
// boxes, or to the line box, depends on the value.
@@ -854,11 +1010,6 @@ NGInlineLayoutStateStack::ApplyBaselineShift(NGInlineBoxState* box,
return kPositionNotPending;
NGInlineBoxState& parent_box = box[-1];
- // Check if there are any fragments to move.
- unsigned fragment_end = line_box->size();
- if (box->fragment_start == fragment_end)
- return kPositionNotPending;
-
switch (vertical_align) {
case EVerticalAlign::kSub:
baseline_shift = parent_box.style->ComputedFontSizeAsFixed() / 5 + 1;
@@ -914,6 +1065,22 @@ NGInlineLayoutStateStack::ApplyBaselineShift(NGInlineBoxState* box,
return kPositionNotPending;
}
+LayoutUnit NGInlineLayoutStateStack::ComputeAlignmentBaselineShift(
+ const NGInlineBoxState* box) {
+ const FontMetrics& metrics = box->font->PrimaryFont()->GetFontMetrics();
+ LayoutUnit result = metrics.FixedAscent(box->style->GetFontBaseline()) -
+ metrics.FixedAscent(box->alignment_type);
+
+ if (box != stack_.begin()) {
+ const FontMetrics& parent_metrics =
+ box[-1].font->PrimaryFont()->GetFontMetrics();
+ result -= parent_metrics.FixedAscent(box[-1].style->GetFontBaseline()) -
+ parent_metrics.FixedAscent(box[-1].alignment_type);
+ }
+
+ return result;
+}
+
FontHeight NGInlineLayoutStateStack::MetricsForTopAndBottomAlign(
const NGInlineBoxState& box,
const NGLogicalLineItems& line_box) const {
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 870a9768624..4eb00ccec3c 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
@@ -48,6 +48,10 @@ struct NGInlineBoxState {
// InitializeFont().
absl::optional<Font> scaled_font;
+ // SVG scaling factor for this box. We use a font of which size is
+ // css-specified-size * scaling_factor.
+ float scaling_factor;
+
// The united metrics for the current box. This includes all objects in this
// box, including descendants, and adjusted by placement properties such as
// 'vertical-align'.
@@ -64,6 +68,9 @@ struct NGInlineBoxState {
// The height of the text fragments.
LayoutUnit text_height;
+ // SVG alignment-baseline presentation property resolved to a FontBaseline.
+ FontBaseline alignment_type = FontBaseline::kAlphabeticBaseline;
+
// These values are to create a box fragment. Set only when needs_box_fragment
// is set.
bool has_start_edge = false;
@@ -77,10 +84,21 @@ struct NGInlineBoxState {
bool include_used_fonts = false;
bool has_box_placeholder = false;
bool needs_box_fragment = false;
+ bool is_svg_text = false;
+
+ // If you add new data members, update the move constructor.
+
+ NGInlineBoxState() = default;
+ // Needs the move constructor for Vector<NGInlineBoxState>.
+ NGInlineBoxState(const NGInlineBoxState&& state);
+ NGInlineBoxState(const NGInlineBoxState&) = delete;
+ NGInlineBoxState& operator=(const NGInlineBoxState&) = delete;
- // Initialize |font| and |scaled_font|. This should be called after setting
- // |style|.
- void InitializeFont(bool is_svg_text, const LayoutObject& layout_object);
+ // Reset |style|, |is_svg_text|, |font|, |scaled_font|, |scaling_factor|, and
+ // |alignment_type|.
+ void ResetStyle(const ComputedStyle& style_ref,
+ bool is_svg,
+ const LayoutObject& layout_object);
// True if this box has a metrics, including pending ones. Pending metrics
// will be activated in |EndBoxState()|.
@@ -91,15 +109,11 @@ struct NGInlineBoxState {
// Compute text metrics for a box. All text in a box share the same
// metrics.
// The computed metrics is included into the line height of the current box.
- void ComputeTextMetrics(const ComputedStyle&,
- const Font& fontref,
- FontBaseline baseline_type);
- void EnsureTextMetrics(const ComputedStyle&,
- const Font& fontref,
- FontBaseline);
+ void ComputeTextMetrics(const ComputedStyle&, const Font& fontref);
+ void EnsureTextMetrics(const ComputedStyle&, const Font& fontref);
void ResetTextMetrics();
- void AccumulateUsedFonts(const ShapeResultView*, FontBaseline);
+ void AccumulateUsedFonts(const ShapeResultView*);
// 'text-top' offset for 'vertical-align'.
LayoutUnit TextTop(FontBaseline baseline_type) const;
@@ -160,6 +174,8 @@ class CORE_EXPORT NGInlineLayoutStateStack {
bool HasBoxFragments() const { return !box_data_list_.IsEmpty(); }
+ wtf_size_t NumBoxFragments() const { return box_data_list_.size(); }
+
// Notify when child is inserted at |index| to adjust child indexes.
void ChildInserted(unsigned index);
@@ -174,13 +190,22 @@ class CORE_EXPORT NGInlineLayoutStateStack {
void UpdateAfterReorder(NGLogicalLineItems*);
// Compute inline positions of fragments and boxes.
- LayoutUnit ComputeInlinePositions(NGLogicalLineItems*, LayoutUnit position);
-
- void ApplyRelativePositioning(const NGConstraintSpace&, NGLogicalLineItems*);
-
+ LayoutUnit ComputeInlinePositions(NGLogicalLineItems*,
+ LayoutUnit position,
+ bool ignore_box_margin_border_padding);
+
+ // |oof_relative_offsets| is an output variable for the accumulated
+ // relative positioning offsets to be applied to OOF positioned descendants.
+ void ApplyRelativePositioning(
+ const NGConstraintSpace&,
+ NGLogicalLineItems*,
+ Vector<LogicalOffset, 32>* oof_relative_offsets);
// Create box fragments. This function turns a flat list of children into
// a box tree.
- void CreateBoxFragments(NGLogicalLineItems*);
+ void CreateBoxFragments(const NGConstraintSpace&,
+ NGLogicalLineItems*,
+ bool is_opaque,
+ Vector<LogicalOffset, 32>* oof_relative_offsets);
#if DCHECK_IS_ON()
void CheckSame(const NGInlineLayoutStateStack&) const;
@@ -213,6 +238,11 @@ class CORE_EXPORT NGInlineLayoutStateStack {
NGLogicalLineItems*,
FontBaseline);
+ // Computes an offset that will align the |box| with its 'alignment-baseline'
+ // relative to the baseline of the line box. This takes into account both the
+ // 'dominant-baseline' and 'alignment-baseline' of |box| and its parent.
+ LayoutUnit ComputeAlignmentBaselineShift(const NGInlineBoxState* box);
+
// Compute the metrics for when 'vertical-align' is 'top' and 'bottom' from
// |pending_descendants|.
FontHeight MetricsForTopAndBottomAlign(const NGInlineBoxState&,
@@ -262,7 +292,11 @@ class CORE_EXPORT NGInlineLayoutStateStack {
void UpdateFragmentEdges(Vector<BoxData, 4>& list);
- scoped_refptr<const NGLayoutResult> CreateBoxFragment(NGLogicalLineItems*);
+ scoped_refptr<const NGLayoutResult> CreateBoxFragment(
+ const NGConstraintSpace&,
+ NGLogicalLineItems*,
+ bool is_opaque = false,
+ LogicalOffset oof_relative_offset = LogicalOffset());
};
// Update start/end of the first BoxData found at |index|.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc
index e97cebd882e..3a9ac0fd5b7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -20,21 +21,82 @@ ASSERT_SIZE(NGInlineBreakToken, SameSizeAsNGInlineBreakToken);
} // namespace
+const NGBlockBreakToken* const*
+NGInlineBreakToken::BlockInInlineBreakTokenAddress() const {
+ CHECK(flags_ & kHasBlockInInlineToken);
+ return block_in_inline_break_token_;
+}
+
+const NGBlockBreakToken* NGInlineBreakToken::BlockInInlineBreakToken() const {
+ if (!(flags_ & kHasBlockInInlineToken))
+ return nullptr;
+ const NGBlockBreakToken* const* ptr = BlockInInlineBreakTokenAddress();
+ DCHECK(*ptr);
+ return *ptr;
+}
+
+// static
+scoped_refptr<NGInlineBreakToken> NGInlineBreakToken::Create(
+ NGInlineNode node,
+ const ComputedStyle* style,
+ unsigned item_index,
+ unsigned text_offset,
+ unsigned flags /* NGInlineBreakTokenFlags */,
+ const NGBlockBreakToken* block_in_inline_break_token) {
+ // We store the children list inline in the break token as a flexible
+ // array. Therefore, we need to make sure to allocate enough space for that
+ // array here, which requires a manual allocation + placement new.
+ wtf_size_t size = sizeof(NGInlineBreakToken);
+ if (UNLIKELY(block_in_inline_break_token)) {
+ size += sizeof(NGBlockBreakToken*);
+ flags |= kHasBlockInInlineToken;
+ }
+
+ void* data = ::WTF::Partitions::FastMalloc(
+ size, ::WTF::GetStringWithTypeName<NGInlineBreakToken>());
+ new (data) NGInlineBreakToken(PassKey(), node, style, item_index, text_offset,
+ flags, block_in_inline_break_token);
+ return base::AdoptRef(static_cast<NGInlineBreakToken*>(data));
+}
+
NGInlineBreakToken::NGInlineBreakToken(
PassKey key,
NGInlineNode node,
const ComputedStyle* style,
unsigned item_index,
unsigned text_offset,
- unsigned flags /* NGInlineBreakTokenFlags */)
+ unsigned flags /* NGInlineBreakTokenFlags */,
+ const NGBlockBreakToken* block_in_inline_break_token)
: NGBreakToken(kInlineBreakToken, node),
style_(style),
item_index_(item_index),
text_offset_(text_offset) {
flags_ = flags;
+
+ if (UNLIKELY(block_in_inline_break_token)) {
+ block_in_inline_break_token->AddRef();
+ const NGBlockBreakToken* const* ptr = BlockInInlineBreakTokenAddress();
+ *const_cast<const NGBlockBreakToken**>(ptr) = block_in_inline_break_token;
+ }
}
-NGInlineBreakToken::~NGInlineBreakToken() = default;
+NGInlineBreakToken::~NGInlineBreakToken() {
+ if (UNLIKELY(flags_ & kHasBlockInInlineToken)) {
+ const NGBlockBreakToken* const* ptr = BlockInInlineBreakTokenAddress();
+ DCHECK(*ptr);
+ (*ptr)->Release();
+ }
+}
+
+bool NGInlineBreakToken::IsAfterBlockInInline() const {
+ if (!ItemIndex())
+ return false;
+ const auto node = To<NGInlineNode>(InputNode());
+ const NGInlineItemsData& items_data = node.ItemsData(/*is_first_line*/ false);
+ const NGInlineItem& last_item = items_data.items[ItemIndex() - 1];
+ return last_item.Type() == NGInlineItem::kBlockInInline &&
+ TextOffset() == last_item.EndOffset();
+}
#if DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h
index 31042360c62..517f4b115d3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h
@@ -13,14 +13,17 @@
namespace blink {
+class NGBlockBreakToken;
+
// Represents a break token for an inline node.
class CORE_EXPORT NGInlineBreakToken final : public NGBreakToken {
public:
enum NGInlineBreakTokenFlags {
kDefault = 0,
kIsForcedBreak = 1 << 0,
- kUseFirstLineStyle = 1 << 1,
- kHasClonedBoxDecorations = 1 << 2,
+ kHasBlockInInlineToken = 1 << 1,
+ kUseFirstLineStyle = 1 << 2,
+ kHasClonedBoxDecorations = 1 << 3,
// When adding values, ensure |flags_| has enough storage.
};
@@ -32,11 +35,8 @@ class CORE_EXPORT NGInlineBreakToken final : public NGBreakToken {
const ComputedStyle* style,
unsigned item_index,
unsigned text_offset,
- unsigned flags /* NGInlineBreakTokenFlags */) {
- return base::AdoptRef(new NGInlineBreakToken(
- PassKey(), node, style, item_index, text_offset, flags));
- }
-
+ unsigned flags /* NGInlineBreakTokenFlags */,
+ const NGBlockBreakToken* block_in_inline_break_token = nullptr);
~NGInlineBreakToken() override;
// The style at the end of this break token. The next line should start with
@@ -59,6 +59,12 @@ class CORE_EXPORT NGInlineBreakToken final : public NGBreakToken {
return flags_ & kIsForcedBreak;
}
+ // True if this is after a block-in-inline.
+ bool IsAfterBlockInInline() const;
+
+ // The BreakToken when a block-in-inline is block-fragmented.
+ const NGBlockBreakToken* BlockInInlineBreakToken() const;
+
// True if the current position has open tags that has `box-decoration-break:
// clone`. They should be cloned to the start of the next line.
bool HasClonedBoxDecorations() const {
@@ -71,7 +77,8 @@ class CORE_EXPORT NGInlineBreakToken final : public NGBreakToken {
const ComputedStyle*,
unsigned item_index,
unsigned text_offset,
- unsigned flags /* NGInlineBreakTokenFlags */);
+ unsigned flags /* NGInlineBreakTokenFlags */,
+ const NGBlockBreakToken* block_in_inline_break_token);
explicit NGInlineBreakToken(PassKey, NGLayoutInputNode node);
@@ -80,9 +87,14 @@ class CORE_EXPORT NGInlineBreakToken final : public NGBreakToken {
#endif
private:
+ const NGBlockBreakToken* const* BlockInInlineBreakTokenAddress() const;
+
scoped_refptr<const ComputedStyle> style_;
unsigned item_index_;
unsigned text_offset_;
+
+ // This is an array of one item if |kHasBlockInInlineToken|, or zero.
+ NGBlockBreakToken* block_in_inline_break_token_[];
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h
index 6d1d26f7570..7491c15d62f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_CHILD_LAYOUT_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_CHILD_LAYOUT_CONTEXT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
index 66b68bce21a..45c950b4251 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -5,9 +5,11 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
+#include "third_party/blink/renderer/core/html/html_br_element.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.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_block_break_token.h"
@@ -89,7 +91,7 @@ bool ShouldIgnoreForPositionForPoint(const NGFragmentItem& item) {
case NGFragmentItem::kGeneratedText:
return true;
case NGFragmentItem::kText:
- case NGFragmentItem::kSVGText:
+ case NGFragmentItem::kSvgText:
if (UNLIKELY(item.IsLayoutObjectDestroyedOrMoved())) {
// See http://crbug.com/1217079
NOTREACHED() << item;
@@ -243,7 +245,7 @@ NGInlineCursor NGInlineCursor::CursorForMovingAcrossFragmentainer() const {
return *this;
NGInlineCursor cursor(*GetLayoutBlockFlow());
const auto& item = *CurrentItem();
- while (cursor && !cursor.TryToMoveTo(item))
+ while (cursor && !cursor.TryMoveTo(item))
cursor.MoveToNextFragmentainer();
DCHECK(cursor) << *this;
return cursor;
@@ -251,9 +253,11 @@ NGInlineCursor NGInlineCursor::CursorForMovingAcrossFragmentainer() const {
void NGInlineCursor::ExpandRootToContainingBlock() {
if (fragment_items_) {
- const unsigned index_diff = items_.data() - fragment_items_->Items().data();
+ const unsigned index_diff = base::checked_cast<unsigned>(
+ items_.data() - fragment_items_->Items().data());
DCHECK_LT(index_diff, fragment_items_->Items().size());
- const unsigned item_index = current_.item_iter_ - items_.begin();
+ const unsigned item_index =
+ base::checked_cast<unsigned>(current_.item_iter_ - items_.begin());
items_ = fragment_items_->Items();
// Update the iterator to the one for the new span.
MoveToItem(items_.begin() + item_index + index_diff);
@@ -454,6 +458,8 @@ PhysicalRect NGInlineCursor::CurrentLocalSelectionRectForText(
const PhysicalRect selection_rect =
CurrentLocalRect(selection_status.start, selection_status.end);
LogicalRect logical_rect = Current().ConvertChildToLogical(selection_rect);
+ if (Current()->Type() == NGFragmentItem::kSvgText)
+ return Current().ConvertChildToPhysical(logical_rect);
// 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 (selection_status.start != selection_status.end &&
@@ -523,10 +529,10 @@ PhysicalRect NGInlineCursor::CurrentRectInBlockFlow() const {
return rect;
}
-LayoutUnit NGInlineCursor::InlinePositionForOffset(unsigned offset) const {
+LayoutUnit NGInlineCursor::CaretInlinePositionForOffset(unsigned offset) const {
DCHECK(Current().IsText());
if (current_.item_) {
- return current_.item_->InlinePositionForOffset(
+ return current_.item_->CaretInlinePositionForOffset(
current_.item_->Text(*fragment_items_), offset);
}
NOTREACHED();
@@ -574,7 +580,7 @@ PositionWithAffinity NGInlineCursor::PositionForPointInInlineFormattingContext(
const NGFragmentItem* child_item = CurrentItem();
DCHECK(child_item);
if (child_item->Type() == NGFragmentItem::kLine) {
- if (!CursorForDescendants().TryToMoveToFirstInlineLeafChild()) {
+ if (!CursorForDescendants().TryMoveToFirstInlineLeafChild()) {
// editing/selection/last-empty-inline.html requires this to skip
// empty <span> with padding.
MoveToNextSkippingChildren();
@@ -667,11 +673,16 @@ PositionWithAffinity NGInlineCursor::PositionForPointInInlineFormattingContext(
}
PositionWithAffinity NGInlineCursor::PositionForPointInInlineBox(
- const PhysicalOffset& point) const {
+ const PhysicalOffset& point_in) const {
const NGFragmentItem* container = CurrentItem();
DCHECK(container);
DCHECK(container->Type() == NGFragmentItem::kLine ||
container->Type() == NGFragmentItem::kBox);
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(container->GetLayoutObject());
+ const PhysicalOffset point =
+ UNLIKELY(text_combine) ? text_combine->AdjustOffsetForHitTest(point_in)
+ : point_in;
const auto writing_direction = container->Style().GetWritingDirection();
const PhysicalSize& container_size = container->Size();
const LayoutUnit point_inline_offset =
@@ -779,7 +790,7 @@ PositionWithAffinity NGInlineCursor::PositionForPointInChild(
const NGFragmentItem& child_item = *CurrentItem();
switch (child_item.Type()) {
case NGFragmentItem::kText:
- case NGFragmentItem::kSVGText:
+ case NGFragmentItem::kSvgText:
return child_item.PositionForPointInText(
point_in_container - child_item.OffsetInContainerFragment(), *this);
case NGFragmentItem::kGeneratedText:
@@ -872,7 +883,8 @@ inline wtf_size_t NGInlineCursor::SpanBeginItemIndex() const {
DCHECK(HasRoot());
DCHECK(!items_.empty());
DCHECK(fragment_items_->IsSubSpan(items_));
- const wtf_size_t delta = items_.data() - fragment_items_->Items().data();
+ const wtf_size_t delta = base::checked_cast<wtf_size_t>(
+ items_.data() - fragment_items_->Items().data());
DCHECK_LT(delta, fragment_items_->Items().size());
return delta;
}
@@ -883,19 +895,19 @@ inline wtf_size_t NGInlineCursor::SpanIndexFromItemIndex(unsigned index) const {
DCHECK(fragment_items_->IsSubSpan(items_));
if (items_.data() == fragment_items_->Items().data())
return index;
- const wtf_size_t span_index =
- fragment_items_->Items().data() - items_.data() + index;
+ const wtf_size_t span_index = base::checked_cast<wtf_size_t>(
+ fragment_items_->Items().data() - items_.data() + index);
DCHECK_LT(span_index, items_.size());
return span_index;
}
void NGInlineCursor::MoveTo(const NGFragmentItem& fragment_item) {
- if (TryToMoveTo(fragment_item))
+ if (TryMoveTo(fragment_item))
return;
NOTREACHED() << *this << " " << fragment_item;
}
-bool NGInlineCursor::TryToMoveTo(const NGFragmentItem& fragment_item) {
+bool NGInlineCursor::TryMoveTo(const NGFragmentItem& fragment_item) {
DCHECK(HasRoot());
// Note: We use address instead of iterator because we can't compare
// iterators in different span. See |base::CheckedContiguousIterator<T>|.
@@ -941,7 +953,7 @@ void NGInlineCursor::MoveToFirst() {
void NGInlineCursor::MoveToFirstChild() {
DCHECK(Current().CanHaveChildren());
- if (!TryToMoveToFirstChild())
+ if (!TryMoveToFirstChild())
MakeNull();
}
@@ -967,11 +979,11 @@ void NGInlineCursor::MoveToFirstLogicalLeaf() {
// TODO(yosin): We should check direction of each container instead of line
// box.
if (IsLtr(Current().Style().Direction())) {
- while (TryToMoveToFirstChild())
+ while (TryMoveToFirstChild())
continue;
return;
}
- while (TryToMoveToLastChild())
+ while (TryMoveToLastChild())
continue;
}
@@ -1004,7 +1016,7 @@ void NGInlineCursor::MoveToFirstNonPseudoLeaf() {
void NGInlineCursor::MoveToLastChild() {
DCHECK(Current().CanHaveChildren());
- if (!TryToMoveToLastChild())
+ if (!TryMoveToLastChild())
MakeNull();
}
@@ -1026,11 +1038,11 @@ void NGInlineCursor::MoveToLastLogicalLeaf() {
// TODO(yosin): We should check direction of each container instead of line
// box.
if (IsLtr(Current().Style().Direction())) {
- while (TryToMoveToLastChild())
+ while (TryMoveToLastChild())
continue;
return;
}
- while (TryToMoveToFirstChild())
+ while (TryMoveToFirstChild())
continue;
}
@@ -1165,14 +1177,14 @@ void NGInlineCursor::MoveToPreviousLine() {
NOTREACHED();
}
-bool NGInlineCursor::TryToMoveToFirstChild() {
+bool NGInlineCursor::TryMoveToFirstChild() {
if (!Current().HasChildren())
return false;
MoveToItem(current_.item_iter_ + 1);
return true;
}
-bool NGInlineCursor::TryToMoveToFirstInlineLeafChild() {
+bool NGInlineCursor::TryMoveToFirstInlineLeafChild() {
while (IsNotNull()) {
if (Current().IsInlineLeaf())
return true;
@@ -1181,7 +1193,7 @@ bool NGInlineCursor::TryToMoveToFirstInlineLeafChild() {
return false;
}
-bool NGInlineCursor::TryToMoveToLastChild() {
+bool NGInlineCursor::TryMoveToLastChild() {
if (!Current().HasChildren())
return false;
const auto end = current_.item_iter_ + CurrentItem()->DescendantsCount();
@@ -1336,10 +1348,8 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
DCHECK(!is_descendants_cursor);
while (item_index >= fragment_items_->EndItemIndex()) {
MoveToNextFragmentainer();
- if (!Current()) {
- NOTREACHED();
+ if (!Current())
return;
- }
}
item_index -= fragment_items_->SizeOfEarlierFragments();
#if DCHECK_IS_ON()
@@ -1363,8 +1373,8 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
return;
}
if (cursor.fragment_items_ == fragment_items_) {
- item_index =
- cursor.Current().Item() - fragment_items_->Items().data();
+ item_index = base::checked_cast<wtf_size_t>(
+ cursor.Current().Item() - fragment_items_->Items().data());
break;
}
}
@@ -1409,7 +1419,8 @@ void NGInlineCursor::MoveToNextForSameLayoutObjectExceptCulledInline() {
if (wtf_size_t delta = current_.item_->DeltaToNextForSameLayoutObject()) {
while (true) {
// Return if the next index is in the current range.
- const wtf_size_t delta_to_end = items_.end() - current_.item_iter_;
+ const wtf_size_t delta_to_end =
+ base::checked_cast<wtf_size_t>(items_.end() - current_.item_iter_);
if (delta < delta_to_end) {
MoveToItem(current_.item_iter_ + delta);
return;
@@ -1666,7 +1677,8 @@ void NGInlineCursor::CheckValid(const NGInlineCursorPosition& position) const {
if (position.Item()) {
DCHECK(HasRoot());
DCHECK_EQ(position.item_, &*position.item_iter_);
- const unsigned index = position.item_iter_ - items_.begin();
+ const unsigned index =
+ base::checked_cast<unsigned>(position.item_iter_ - items_.begin());
DCHECK_LT(index, items_.size());
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
index 342dbc23610..ee91605b7e4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
@@ -7,7 +7,6 @@
#include <unicode/ubidi.h>
-#include "base/containers/span.h"
#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
@@ -143,6 +142,7 @@ class CORE_EXPORT NGInlineCursorPosition {
const PhysicalRect RectInContainerFragment() const {
return item_->RectInContainerFragment();
}
+ FloatRect ObjectBoundingBox() const { return item_->ObjectBoundingBox(); }
const PhysicalOffset OffsetInContainerFragment() const {
return item_->OffsetInContainerFragment();
}
@@ -240,6 +240,7 @@ class CORE_EXPORT NGInlineCursor {
const NGFragmentItems& items);
explicit NGInlineCursor(const NGInlineBackwardCursor& backward_cursor);
NGInlineCursor(const NGInlineCursor& other) = default;
+ NGInlineCursor& operator=(const NGInlineCursor& other) = default;
// Creates an |NGInlineCursor| without the root. Even when callers don't know
// the root of the inline formatting context, this cursor can |MoveTo()|
@@ -358,9 +359,9 @@ class CORE_EXPORT NGInlineCursor {
return CurrentRectInBlockFlow().offset;
}
- // Relative to fragment of the current position. It is error to call other
- // than text.
- LayoutUnit InlinePositionForOffset(unsigned offset) const;
+ // Returns inline position relative to current text fragment for
+ // |LocalCaretRect|. It is error to call other than text.
+ LayoutUnit CaretInlinePositionForOffset(unsigned offset) const;
// Converts the given point, relative to the fragment itself, into a position
// in DOM tree within the range of |this|. This variation ignores the inline
@@ -410,7 +411,7 @@ class CORE_EXPORT NGInlineCursor {
// Move to first child of current container box. If the current position is
// at fragment without children, this cursor points nothing.
- // See also |TryToMoveToFirstChild()|.
+ // See also |TryMoveToFirstChild()|.
void MoveToFirstChild();
// Move to the first line.
@@ -427,7 +428,7 @@ class CORE_EXPORT NGInlineCursor {
// Move to last child of current container box. If the current position is
// at fragment without children, this cursor points nothing.
- // See also |TryToMoveToFirstChild()|.
+ // See also |TryMoveToFirstChild()|.
void MoveToLastChild();
// Move to the last line item. If there are no line items, the cursor becomes
@@ -484,13 +485,13 @@ class CORE_EXPORT NGInlineCursor {
void MoveToPreviousLine();
// Returns true if the current position moves to first child.
- bool TryToMoveToFirstChild();
+ bool TryMoveToFirstChild();
// Returns true if the current position moves to first inline leaf child.
- bool TryToMoveToFirstInlineLeafChild();
+ bool TryMoveToFirstInlineLeafChild();
// Returns true if the current position moves to last child.
- bool TryToMoveToLastChild();
+ bool TryMoveToLastChild();
//
// Moving across fragmentainers.
@@ -587,7 +588,7 @@ class CORE_EXPORT NGInlineCursor {
// Returns true and move to current position to |fragment_item|, otherwise
// returns false.
- bool TryToMoveTo(const NGFragmentItem& fragment_item);
+ bool TryMoveTo(const NGFragmentItem& fragment_item);
void MoveToItem(const ItemsSpan::iterator& iter);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
index 4b1f27109cf..9cf2e0310db 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
@@ -6,6 +6,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
@@ -314,7 +315,7 @@ TEST_P(NGInlineCursorTest, FirstChild) {
SetupCursor("<div id=root>abc<a>DEF<b>GHI</b></a>xyz</div>");
cursor.MoveToFirstChild();
EXPECT_EQ("abc", ToDebugString(cursor));
- EXPECT_FALSE(cursor.TryToMoveToFirstChild());
+ EXPECT_FALSE(cursor.TryMoveToFirstChild());
}
TEST_P(NGInlineCursorTest, FirstChild2) {
@@ -327,7 +328,7 @@ TEST_P(NGInlineCursorTest, FirstChild2) {
EXPECT_EQ("#first", ToDebugString(cursor));
cursor.MoveToFirstChild();
EXPECT_EQ("abc", ToDebugString(cursor));
- EXPECT_FALSE(cursor.TryToMoveToFirstChild());
+ EXPECT_FALSE(cursor.TryMoveToFirstChild());
}
TEST_P(NGInlineCursorTest, FirstLastLogicalLeafInSimpleText) {
@@ -430,7 +431,7 @@ TEST_P(NGInlineCursorTest, LastChild) {
SetupCursor("<div id=root>abc<a>DEF<b>GHI</b></a>xyz</div>");
cursor.MoveToLastChild();
EXPECT_EQ("xyz", ToDebugString(cursor));
- EXPECT_FALSE(cursor.TryToMoveToLastChild());
+ EXPECT_FALSE(cursor.TryMoveToLastChild());
}
TEST_P(NGInlineCursorTest, LastChild2) {
@@ -443,7 +444,7 @@ TEST_P(NGInlineCursorTest, LastChild2) {
EXPECT_EQ("#last", ToDebugString(cursor));
cursor.MoveToLastChild();
EXPECT_EQ("xyz", ToDebugString(cursor));
- EXPECT_FALSE(cursor.TryToMoveToLastChild());
+ EXPECT_FALSE(cursor.TryMoveToLastChild());
}
TEST_P(NGInlineCursorTest, Next) {
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 0cb6ef79e8a..5c24595d560 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
@@ -191,7 +191,7 @@ unsigned NGInlineItem::SetBidiLevel(Vector<NGInlineItem>& items,
return index + 1;
}
-const Font& NGInlineItem::FontWithSVGScaling() const {
+const Font& NGInlineItem::FontWithSvgScaling() const {
if (const auto* svg_text = DynamicTo<LayoutSVGInlineText>(layout_object_)) {
DCHECK(RuntimeEnabledFeatures::SVGTextNGEnabled());
// We don't need to care about StyleVariant(). SVG 1.1 doesn't support
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 d520533ede7..c089e5804d6 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
@@ -32,6 +32,7 @@ class CORE_EXPORT NGInlineItem {
kText,
kControl,
kAtomicInline,
+ kBlockInInline,
kOpenTag,
kCloseTag,
kFloating,
@@ -132,6 +133,9 @@ class CORE_EXPORT NGInlineItem {
bool IsRubyRun() const {
return GetLayoutObject() && GetLayoutObject()->IsRubyRun();
}
+ bool IsTextCombine() const {
+ return GetLayoutObject() && GetLayoutObject()->IsLayoutNGTextCombine();
+ }
void SetOffset(unsigned start, unsigned end) {
DCHECK_GE(end, start);
@@ -169,24 +173,26 @@ class CORE_EXPORT NGInlineItem {
// Use the |ComputedStyle| in |LayoutObject|, because not all style changes
// re-run |CollectInlines()|.
DCHECK(layout_object_);
- NGStyleVariant variant = StyleVariant();
- if (variant == NGStyleVariant::kStandard)
- return layout_object_->Style();
- DCHECK_EQ(variant, NGStyleVariant::kFirstLine);
- return layout_object_->FirstLineStyle();
+ return &layout_object_->EffectiveStyle(StyleVariant());
}
// Returns a screen-size font for SVG text.
// Returns Style()->GetFont() otherwise.
- const Font& FontWithSVGScaling() const;
+ const Font& FontWithSvgScaling() const;
// Get or set the whitespace collapse type at the end of this item.
NGCollapseType EndCollapseType() const {
return static_cast<NGCollapseType>(end_collapse_type_);
}
void SetEndCollapseType(NGCollapseType type) {
- DCHECK(Type() == NGInlineItem::kText || type == kOpaqueToCollapsing ||
- (Type() == NGInlineItem::kControl && type == kCollapsible));
+ // |kText| can set any types.
+ DCHECK(Type() == NGInlineItem::kText ||
+ // |kControl| and |kBlockInInline| are always |kCollapsible|.
+ ((Type() == NGInlineItem::kControl ||
+ Type() == NGInlineItem::kBlockInInline) &&
+ type == kCollapsible) ||
+ // Other types are |kOpaqueToCollapsing|.
+ type == kOpaqueToCollapsing);
end_collapse_type_ = type;
}
bool IsCollapsibleSpaceOnly() const {
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 e05524ccf97..75b39ee9cd0 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
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
namespace blink {
@@ -25,6 +26,17 @@ NGInlineItemResult::NGInlineItemResult(const NGInlineItem* item,
should_create_line_box(should_create_line_box),
has_unpositioned_floats(has_unpositioned_floats) {}
+void NGInlineItemResult::ShapeHyphen() {
+ DCHECK(!hyphen_string);
+ DCHECK(!hyphen_shape_result);
+ DCHECK(item);
+ DCHECK(item->Style());
+ const ComputedStyle& style = *item->Style();
+ hyphen_string = style.HyphenString();
+ HarfBuzzShaper shaper(hyphen_string);
+ hyphen_shape_result = shaper.Shape(&style.GetFont(), style.Direction());
+}
+
#if DCHECK_IS_ON()
void NGInlineItemResult::CheckConsistency(bool allow_null_shape_result) const {
DCHECK(item);
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 70d240eb703..f832343edf4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_RESULT_H_
#include "base/dcheck_is_on.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_offset.h"
#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
@@ -42,6 +43,8 @@ struct CORE_EXPORT NGInlineItemResult {
return hyphen_shape_result->SnappedWidth().ClampNegativeToZero();
}
+ // Compute/clear |hyphen_string| and |hyphen_shape_result|.
+ void ShapeHyphen();
void ClearHyphen() {
hyphen_string = String();
hyphen_shape_result = nullptr;
@@ -60,6 +63,10 @@ struct CORE_EXPORT NGInlineItemResult {
// Inline size of this item.
LayoutUnit inline_size;
+ // Non-zero if text-combine after non-ideographic character
+ // See "text-combine-justify.html".
+ LayoutUnit spacing_before;
+
// Pending inline-end overhang amount for RubyRun.
// This is committed if a following item meets conditions.
LayoutUnit pending_end_overhang;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
index 238c856b478..a0a671d3aa6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
@@ -143,6 +143,15 @@ NGInlineItemSegments::Iterator NGInlineItemSegments::Ranges(
return Iterator(start_offset, end_offset, segment);
}
+void NGInlineItemSegments::ComputeSegments(
+ RunSegmenter* segmenter,
+ RunSegmenter::RunSegmenterRange* range) {
+ segments_.Shrink(0);
+ do {
+ segments_.emplace_back(*range);
+ } while (segmenter->Consume(range));
+}
+
unsigned NGInlineItemSegments::AppendMixedFontOrientation(
const String& text_content,
unsigned start_offset,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
index 4f4cee81441..bf5d72c98f4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
@@ -89,6 +89,10 @@ class CORE_EXPORT NGInlineItemSegments {
segments_.emplace_back(std::forward<Args>(args)...);
}
+ // Compute segments from the given |RunSegmenter|.
+ void ComputeSegments(RunSegmenter* segmenter,
+ RunSegmenter::RunSegmenterRange* range);
+
// Append mixed-vertical font orientation segments for the specified range.
// This is separated from |ComputeSegments| because this result depends on
// fonts.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
index 71a44bb8f85..f661eb02b36 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
@@ -6,6 +6,8 @@
#include <type_traits>
+#include "base/containers/adapters.h"
+#include "third_party/blink/renderer/core/html/html_area_element.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
@@ -176,8 +178,7 @@ inline bool MoveToEndOfCollapsibleSpaces(const StringView& string,
// open/close or bidi controls are ignored.
// Returns nullptr if there were no previous items.
NGInlineItem* LastItemToCollapseWith(Vector<NGInlineItem>* items) {
- for (auto it = items->rbegin(); it != items->rend(); it++) {
- NGInlineItem& item = *it;
+ for (auto& item : base::Reversed(*items)) {
if (item.EndCollapseType() != NGInlineItem::kOpaqueToCollapsing)
return &item;
}
@@ -294,8 +295,9 @@ bool NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendTextReusing(
// TODO(layout-dev): This could likely be optimized further.
// TODO(layout-dev): Handle cases where the old items are not consecutive.
const ComputedStyle& new_style = layout_text->StyleRef();
- bool collapse_spaces = new_style.CollapseWhiteSpace();
- bool preserve_newlines = new_style.PreserveNewline();
+ const bool collapse_spaces = new_style.CollapseWhiteSpace();
+ const bool preserve_newlines =
+ new_style.PreserveNewline() && LIKELY(!is_text_combine_);
if (NGInlineItem* last_item = LastItemToCollapseWith(items_)) {
if (collapse_spaces) {
switch (last_item->EndCollapseType()) {
@@ -464,6 +466,13 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendText(
if (UNLIKELY(layout_text->IsWordBreak())) {
typename OffsetMappingBuilder::SourceNodeScope scope(&mapping_builder_,
layout_text);
+ if (UNLIKELY(is_text_combine_)) {
+ // We don't break text runs in text-combine-upright:all.
+ // Note: Even if we have overflow-wrap:normal and word-break:keep-all,
+ // <wbr> causes line break.
+ Append(NGInlineItem::kText, kZeroWidthSpaceCharacter, layout_text);
+ return;
+ }
AppendBreakOpportunity(layout_text);
return;
}
@@ -501,19 +510,58 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendText(
const ComputedStyle& style = layout_object->StyleRef();
EWhiteSpace whitespace = style.WhiteSpace();
- bool is_svg_text = layout_object && layout_object->IsSVGInlineText();
+ const bool should_not_preserve_newline =
+ (layout_object && layout_object->IsSVGInlineText()) ||
+ UNLIKELY(is_text_combine_);
RestoreTrailingCollapsibleSpaceIfRemoved();
+ if (text_chunk_offsets_ && AppendTextChunks(string, *layout_object))
+ return;
if (!ComputedStyle::CollapseWhiteSpace(whitespace))
AppendPreserveWhitespace(string, &style, layout_object);
- else if (ComputedStyle::PreserveNewline(whitespace) && !is_svg_text)
+ else if (ComputedStyle::PreserveNewline(whitespace) &&
+ !should_not_preserve_newline)
AppendPreserveNewline(string, &style, layout_object);
else
AppendCollapseWhitespace(string, &style, layout_object);
}
template <typename OffsetMappingBuilder>
+bool NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendTextChunks(
+ const String& string,
+ LayoutText& layout_text) {
+ auto iter = text_chunk_offsets_->find(&layout_text);
+ if (iter == text_chunk_offsets_->end())
+ return false;
+ const ComputedStyle& style = layout_text.StyleRef();
+ EWhiteSpace whitespace = style.WhiteSpace();
+ unsigned start = 0;
+ for (unsigned offset : iter->value) {
+ DCHECK_LE(offset, string.length());
+ if (start < offset) {
+ if (!ComputedStyle::CollapseWhiteSpace(whitespace)) {
+ AppendPreserveWhitespace(string.Substring(start, offset - start),
+ &style, &layout_text);
+ } else {
+ AppendCollapseWhitespace(StringView(string, start, offset - start),
+ &style, &layout_text);
+ }
+ }
+ ExitAndEnterSvgTextChunk(layout_text);
+ start = offset;
+ }
+ if (start >= string.length())
+ return true;
+ if (!ComputedStyle::CollapseWhiteSpace(whitespace)) {
+ AppendPreserveWhitespace(string.Substring(start), &style, &layout_text);
+ } else {
+ AppendCollapseWhitespace(StringView(string, start), &style, &layout_text);
+ }
+ return true;
+}
+
+template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<
OffsetMappingBuilder>::AppendCollapseWhitespace(const StringView string,
const ComputedStyle* style,
@@ -544,7 +592,11 @@ void NGInlineItemsBuilderTemplate<
// LayoutBR does not set preserve_newline, but should be preserved.
if (UNLIKELY(space_run_has_newline && string.length() == 1 &&
layout_object && layout_object->IsBR())) {
- AppendForcedBreakCollapseWhitespace(layout_object);
+ if (UNLIKELY(is_text_combine_)) {
+ AppendTextItem(" ", layout_object);
+ } else {
+ AppendForcedBreakCollapseWhitespace(layout_object);
+ }
return;
}
@@ -716,6 +768,8 @@ bool NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
const ComputedStyle& style,
unsigned index) const {
DCHECK_LE(index, string.length());
+ if (UNLIKELY(is_text_combine_))
+ return false;
// Check if we are at a preserved space character and auto-wrap is enabled.
if (style.CollapseWhiteSpace() || !style.AutoWrap() || !string.length() ||
index >= string.length() || string[index] != kSpaceCharacter)
@@ -771,6 +825,11 @@ void NGInlineItemsBuilderTemplate<
UChar c = string[start];
if (IsControlItemCharacter(c)) {
if (c == kNewlineCharacter) {
+ if (UNLIKELY(is_text_combine_)) {
+ start++;
+ AppendTextItem(" ", layout_object);
+ continue;
+ }
AppendForcedBreak(layout_object);
start++;
// A forced break is not a collapsible space, but following collapsible
@@ -835,6 +894,9 @@ template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak(
LayoutObject* layout_object) {
DCHECK(layout_object);
+ // Combined text should ignore force line break[1].
+ // [1] https://drafts.csswg.org/css-writing-modes-3/#text-combine-layout
+ DCHECK(!is_text_combine_);
// At the forced break, add bidi controls to pop all contexts.
// https://drafts.csswg.org/css-writing-modes-3/#bidi-embedding-breaks
if (!bidi_context_.IsEmpty()) {
@@ -842,8 +904,8 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak(
nullptr);
// These bidi controls need to be associated with the |layout_object| so
// that items from a LayoutObject are consecutive.
- for (auto it = bidi_context_.rbegin(); it != bidi_context_.rend(); ++it) {
- AppendOpaque(NGInlineItem::kBidiControl, it->exit, layout_object);
+ for (const auto& bidi : base::Reversed(bidi_context_)) {
+ AppendOpaque(NGInlineItem::kBidiControl, bidi.exit, layout_object);
}
}
@@ -887,6 +949,38 @@ NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendBreakOpportunity(
return item;
}
+// The logic is similar to AppendForcedBreak().
+template <typename OffsetMappingBuilder>
+void NGInlineItemsBuilderTemplate<
+ OffsetMappingBuilder>::ExitAndEnterSvgTextChunk(LayoutText& layout_text) {
+ DCHECK(block_flow_->IsNGSVGText());
+ DCHECK(text_chunk_offsets_);
+
+ if (bidi_context_.IsEmpty())
+ return;
+ typename OffsetMappingBuilder::SourceNodeScope scope(&mapping_builder_,
+ nullptr);
+ // These bidi controls need to be associated with the |layout_text| so
+ // that items from a LayoutObject are consecutive.
+ for (const auto& bidi : base::Reversed(bidi_context_))
+ AppendOpaque(NGInlineItem::kBidiControl, bidi.exit, &layout_text);
+
+ // Then re-add bidi controls to restore the bidi context.
+ for (const auto& bidi : bidi_context_)
+ AppendOpaque(NGInlineItem::kBidiControl, bidi.enter, &layout_text);
+}
+
+template <typename OffsetMappingBuilder>
+void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterSvgTextChunk(
+ const ComputedStyle* style) {
+ if (LIKELY(!block_flow_->IsNGSVGText() || !text_chunk_offsets_))
+ return;
+ EnterBidiContext(nullptr, style, kLeftToRightIsolateCharacter,
+ kRightToLeftIsolateCharacter,
+ kPopDirectionalIsolateCharacter);
+ // This context is automatically popped by Exit(nullptr) in ExitBlock().
+}
+
template <typename OffsetMappingBuilder>
NGInlineItem& NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append(
NGInlineItem::NGInlineItemType type,
@@ -927,6 +1021,19 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendAtomicInline(
}
template <typename OffsetMappingBuilder>
+void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendBlockInInline(
+ LayoutObject* layout_object) {
+ DCHECK(layout_object);
+ // Before a block-in-inline is like after a forced break.
+ RemoveTrailingCollapsibleSpaceIfExists();
+ NGInlineItem& item = Append(NGInlineItem::kBlockInInline,
+ kObjectReplacementCharacter, layout_object);
+ // After a block-in-inline is like after a forced break. See
+ // |AppendForcedBreak|.
+ item.SetEndCollapseType(NGInlineItem::kCollapsible, false);
+}
+
+template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendFloating(
LayoutObject* layout_object) {
AppendOpaque(NGInlineItem::kFloating, kObjectReplacementCharacter,
@@ -988,9 +1095,11 @@ void NGInlineItemsBuilderTemplate<
// A forced break pretends that it's a collapsible space, see
// |AppendForcedBreak()|. It should not be removed.
- if (item->Type() == NGInlineItem::kControl)
+ if (item->Type() != NGInlineItem::kText) {
+ DCHECK(item->Type() == NGInlineItem::kControl ||
+ item->Type() == NGInlineItem::kBlockInInline);
return;
- DCHECK_EQ(item->Type(), NGInlineItem::kText);
+ }
DCHECK_GT(item->EndOffset(), item->StartOffset());
unsigned space_offset = item->EndOffset() - 1;
@@ -1076,6 +1185,7 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterBlock(
const ComputedStyle* style) {
// Handle bidi-override on the block itself.
if (style->RtlOrdering() == EOrder::kLogical) {
+ EnterSvgTextChunk(style);
switch (style->GetUnicodeBidi()) {
case UnicodeBidi::kNormal:
case UnicodeBidi::kEmbed:
@@ -1109,7 +1219,7 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterBlock(
kPopDirectionalFormattingCharacter);
}
- if (style->Display() == EDisplay::kListItem && style->GetListStyleType()) {
+ if (style->Display() == EDisplay::kListItem && style->ListStyleType()) {
is_empty_inline_ = false;
is_block_level_ = false;
}
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 d0354cf76ed..9b2faf2ab4c 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
@@ -6,9 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEMS_BUILDER_H_
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/inline/empty_offset_mapping_builder.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h"
#include "third_party/blink/renderer/platform/fonts/font_height.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -44,9 +46,14 @@ class NGInlineItemsBuilderTemplate {
public:
// Create a builder that appends items to |items|.
- NGInlineItemsBuilderTemplate(LayoutBlockFlow* block_flow,
- Vector<NGInlineItem>* items)
- : block_flow_(block_flow), items_(items) {}
+ NGInlineItemsBuilderTemplate(
+ LayoutBlockFlow* block_flow,
+ Vector<NGInlineItem>* items,
+ const SvgTextChunkOffsets* chunk_offsets = nullptr)
+ : block_flow_(block_flow),
+ items_(items),
+ text_chunk_offsets_(chunk_offsets),
+ is_text_combine_(block_flow_->IsLayoutNGTextCombine()) {}
~NGInlineItemsBuilderTemplate();
LayoutBlockFlow* GetLayoutBlockFlow() const { return block_flow_; }
@@ -98,6 +105,7 @@ class NGInlineItemsBuilderTemplate {
// Append a unicode "object replacement character" for an atomic inline,
// signaling the presence of a non-text object to the unicode bidi algorithm.
void AppendAtomicInline(LayoutObject* layout_object);
+ void AppendBlockInInline(LayoutObject* layout_object);
// Append floats and positioned objects in the same way as atomic inlines.
// Because these objects need positions, they will be handled in
@@ -178,6 +186,9 @@ class NGInlineItemsBuilderTemplate {
};
Vector<BidiContext> bidi_context_;
+ const SvgTextChunkOffsets* text_chunk_offsets_;
+
+ const bool is_text_combine_;
bool has_bidi_controls_ = false;
bool has_ruby_ = false;
bool is_empty_inline_ = true;
@@ -202,6 +213,9 @@ class NGInlineItemsBuilderTemplate {
void AppendForcedBreakCollapseWhitespace(LayoutObject*);
void AppendForcedBreak(LayoutObject*);
+ bool AppendTextChunks(const String& string, LayoutText& layout_text);
+ void ExitAndEnterSvgTextChunk(LayoutText& layout_text);
+ void EnterSvgTextChunk(const ComputedStyle* style);
void RemoveTrailingCollapsibleSpaceIfExists();
void RemoveTrailingCollapsibleSpace(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 0b66c5bf673..9250d45b9f7 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
@@ -73,6 +74,13 @@ class NGInlineItemsBuilderTest : public NGLayoutTest {
builder->AppendAtomicInline(layout_block_flow);
}
+ void AppendBlockInInline(NGInlineItemsBuilder* builder) {
+ LayoutBlockFlow* layout_block_flow = LayoutBlockFlow::CreateAnonymous(
+ &GetDocument(), style_, LegacyLayout::kAuto);
+ anonymous_objects_.push_back(layout_block_flow);
+ builder->AppendBlockInInline(layout_block_flow);
+ }
+
void AppendRubyRun(NGInlineItemsBuilder* builder) {
LayoutNGRubyRun* ruby_run = new LayoutNGRubyRun();
ruby_run->SetDocumentForAnonymous(&GetDocument());
@@ -532,6 +540,16 @@ TEST_F(NGInlineItemsBuilderTest, BidiIsolateOverride) {
isolate_override_rtl->Destroy();
}
+TEST_F(NGInlineItemsBuilderTest, BlockInInline) {
+ Vector<NGInlineItem> items;
+ NGInlineItemsBuilder builder(GetLayoutBlockFlow(), &items);
+ AppendText("Hello ", &builder);
+ AppendBlockInInline(&builder);
+ AppendText(" World", &builder);
+ // Collapsible spaces before and after block-in-inline should be collapsed.
+ EXPECT_EQ(String(u"Hello\uFFFCWorld"), builder.ToString());
+}
+
TEST_F(NGInlineItemsBuilderTest, HasRuby) {
Vector<NGInlineItem> items;
NGInlineItemsBuilder builder(GetLayoutBlockFlow(), &items);
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 33301dacf3c..3bc20d9e26e 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
@@ -8,7 +8,9 @@
#include "base/compiler_specific.h"
#include "base/containers/adapters.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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_box_state.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
@@ -90,7 +92,7 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::HandleOpenTag(
// for the purpose of empty block calculation.
// https://drafts.csswg.org/css2/visudet.html#line-height
if (!quirks_mode_ || !item.IsEmptyItem())
- box->ComputeTextMetrics(*item.Style(), *box->font, baseline_type_);
+ box->ComputeTextMetrics(*item.Style(), *box->font);
if (item.Style()->HasMask()) {
// Layout may change the bounding box, which affects MaskClip.
@@ -107,7 +109,7 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::HandleCloseTag(
NGLogicalLineItems* line_box,
NGInlineBoxState* box) {
if (UNLIKELY(quirks_mode_ && !item.IsEmptyItem()))
- box->EnsureTextMetrics(*item.Style(), *box->font, baseline_type_);
+ box->EnsureTextMetrics(*item.Style(), *box->font);
box = box_states_->OnCloseTag(ConstraintSpace(), line_box, box,
baseline_type_, item.HasEndEdge());
// Just clear |NeedsLayout| flags. Culled inline boxes do not need paint
@@ -218,12 +220,17 @@ void NGInlineLayoutAlgorithm::CreateLine(
// have been to make sure that there's always room for the list item marker,
// but that doesn't explain why it's done for every line...
if (quirks_mode_ && line_style.Display() == EDisplay::kListItem)
- box->ComputeTextMetrics(line_style, *box->font, baseline_type_);
+ box->ComputeTextMetrics(line_style, *box->font);
- bool has_logical_text_items = false;
for (NGInlineItemResult& item_result : *line_items) {
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
+#if DCHECK_IS_ON()
+ if (line_info->IsBlockInInline()) {
+ DCHECK_EQ(line_items->size(), 1u);
+ DCHECK_EQ(item.Type(), NGInlineItem::kBlockInInline);
+ }
+#endif
if (item.Type() == NGInlineItem::kText) {
DCHECK(item.GetLayoutObject());
DCHECK(item.GetLayoutObject()->IsText() ||
@@ -231,13 +238,11 @@ void NGInlineLayoutAlgorithm::CreateLine(
DCHECK(item_result.shape_result);
if (UNLIKELY(quirks_mode_))
- box->EnsureTextMetrics(*item.Style(), *box->font, baseline_type_);
+ box->EnsureTextMetrics(*item.Style(), *box->font);
// Take all used fonts into account if 'line-height: normal'.
- if (box->include_used_fonts) {
- box->AccumulateUsedFonts(item_result.shape_result.get(),
- baseline_type_);
- }
+ if (box->include_used_fonts)
+ box->AccumulateUsedFonts(item_result.shape_result.get());
DCHECK(item.TextType() == NGTextType::kNormal ||
item.TextType() == NGTextType::kSymbolMarker);
@@ -250,19 +255,26 @@ void NGInlineLayoutAlgorithm::CreateLine(
item_result.inline_size - hyphen_inline_size,
box->text_height, item.BidiLevel());
PlaceHyphen(item_result, hyphen_inline_size, line_box, box);
+ } else if (UNLIKELY(Node().IsTextCombine())) {
+ // We make combined text at block offset 0 with 1em height.
+ // Painter paints text at block offset + |font.internal_leading / 2|.
+ const auto one_em = item.Style()->ComputedFontSizeAsFixed();
+ const auto text_height = one_em;
+ const auto text_top = LayoutUnit();
+ line_box->AddChild(item, item_result, item_result.TextOffset(),
+ text_top, item_result.inline_size, text_height,
+ item.BidiLevel());
} else {
line_box->AddChild(item, item_result, item_result.TextOffset(),
box->text_top, item_result.inline_size,
box->text_height, item.BidiLevel());
}
- has_logical_text_items = true;
// Text boxes always need full paint invalidations.
item.GetLayoutObject()->ClearNeedsLayoutWithFullPaintInvalidation();
} else if (item.Type() == NGInlineItem::kControl) {
PlaceControlItem(item, *line_info, &item_result, line_box, box);
- has_logical_text_items = true;
} else if (item.Type() == NGInlineItem::kOpenTag) {
box = HandleOpenTag(item, item_result, line_box, box_states_);
} else if (item.Type() == NGInlineItem::kCloseTag) {
@@ -271,6 +283,9 @@ void NGInlineLayoutAlgorithm::CreateLine(
box = PlaceAtomicInline(item, *line_info, &item_result, line_box);
has_relative_positioned_items |=
item.Style()->GetPosition() == EPosition::kRelative;
+ } else if (item.Type() == NGInlineItem::kBlockInInline) {
+ DCHECK(line_info->IsBlockInInline());
+ PlaceBlockInInline(item, *line_info, &item_result, line_box);
} else if (item.Type() == NGInlineItem::kListMarker) {
PlaceListMarker(item, &item_result, *line_info);
} else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) {
@@ -319,9 +334,11 @@ void NGInlineLayoutAlgorithm::CreateLine(
const LayoutUnit hang_width = line_info->HangWidth();
LayoutUnit inline_size;
if (IsLtr(line_info->BaseDirection())) {
- inline_size = box_states_->ComputeInlinePositions(line_box, LayoutUnit());
+ inline_size = box_states_->ComputeInlinePositions(
+ line_box, LayoutUnit(), line_info->IsBlockInInline());
} else {
- inline_size = box_states_->ComputeInlinePositions(line_box, -hang_width);
+ inline_size = box_states_->ComputeInlinePositions(
+ line_box, -hang_width, line_info->IsBlockInInline());
inline_size += hang_width;
}
if (UNLIKELY(hang_width)) {
@@ -361,10 +378,13 @@ void NGInlineLayoutAlgorithm::CreateLine(
container_builder_.SetBfcLineOffset(bfc_line_offset);
- const FontHeight& line_box_metrics =
- UNLIKELY(Node().HasLineEvenIfEmpty())
- ? line_info->LineStyle().GetFontHeight()
- : box_states_->LineBoxState().metrics;
+ // Force an editable empty line to have metrics, so that is has a height.
+ if (UNLIKELY(Node().HasLineEvenIfEmpty())) {
+ box_states_->LineBoxState().EnsureTextMetrics(
+ line_info->LineStyle(), *box_states_->LineBoxState().font);
+ }
+
+ const FontHeight& line_box_metrics = box_states_->LineBoxState().metrics;
// Place out-of-flow positioned objects.
// This adjusts the NGLogicalLineItem::offset member to contain
@@ -389,28 +409,35 @@ void NGInlineLayoutAlgorithm::CreateLine(
PlaceRelativePositionedItems(line_box);
// Apply any relative positioned offsets to any boxes (and their children).
- box_states_->ApplyRelativePositioning(ConstraintSpace(), line_box);
+ Vector<LogicalOffset, 32> oof_relative_offsets(
+ box_states_->NumBoxFragments());
+ box_states_->ApplyRelativePositioning(ConstraintSpace(), line_box,
+ &oof_relative_offsets);
// Create box fragments if needed. After this point forward, |line_box| is a
// tree structure.
// The individual children don't move position within the |line_box|, rather
// the children have their layout_result, fragment, (or similar) set to null,
// creating a "hole" in the array.
- if (box_states_->HasBoxFragments())
- box_states_->CreateBoxFragments(line_box);
+ if (box_states_->HasBoxFragments()) {
+ box_states_->CreateBoxFragments(ConstraintSpace(), line_box,
+ line_info->IsBlockInInline(),
+ &oof_relative_offsets);
+ }
// Update item index of the box states in the context.
context_->SetItemIndex(line_info->ItemsData().items,
line_info->EndItemIndex());
+ if (line_info->IsBlockInInline()) {
+ // |container_builder_| is already set up by |PlaceBlockInInline|.
+ return;
+ }
+
// 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()) {
- container_builder_.SetIsSelfCollapsing();
- container_builder_.SetIsEmptyLineBox();
- container_builder_.SetBaseDirection(line_info->BaseDirection());
+ if (line_info->IsEmptyLine())
return;
- }
DCHECK(!line_box_metrics.IsEmpty());
@@ -420,63 +447,31 @@ void NGInlineLayoutAlgorithm::CreateLine(
//
// For SVG <text>, the block offset of the initial 'current text position'
// should be 0. As for the inline offset, see
- // NGSVGTextLayoutAttributesBuilder::Build().
- if (!Node().IsSVGText())
+ // NGSvgTextLayoutAttributesBuilder::Build().
+ //
+ // For text-combine-upright:all, the block offset should be zero to make
+ // combined text in 1em x 1em box.
+ if (LIKELY(!Node().IsSvgText() && !Node().IsTextCombine()))
line_box->MoveInBlockDirection(line_box_metrics.ascent);
LayoutUnit block_offset = line_info->BfcOffset().block_offset;
if (Node().HasRuby()) {
- NGAnnotationMetrics annotation_metrics = ComputeAnnotationOverflow(
- *line_box, line_box_metrics, LayoutUnit(), line_info->LineStyle());
- LayoutUnit annotation_overflow_block_start;
- LayoutUnit annotation_overflow_block_end;
- LayoutUnit annotation_space_block_start;
- LayoutUnit annotation_space_block_end;
- if (!IsFlippedLinesWritingMode(line_info->LineStyle().GetWritingMode())) {
- annotation_overflow_block_start = annotation_metrics.overflow_over;
- annotation_overflow_block_end = annotation_metrics.overflow_under;
- annotation_space_block_start = annotation_metrics.space_over;
- annotation_space_block_end = annotation_metrics.space_under;
- } else {
- annotation_overflow_block_start = annotation_metrics.overflow_under;
- annotation_overflow_block_end = annotation_metrics.overflow_over;
- annotation_space_block_start = annotation_metrics.space_under;
- annotation_space_block_end = annotation_metrics.space_over;
- }
-
- LayoutUnit block_offset_shift = annotation_overflow_block_start;
- // If the previous line has block-end annotation overflow and this line has
- // block-start annotation space, shift up the block offset of this line.
- if (ConstraintSpace().BlockStartAnnotationSpace() < LayoutUnit() &&
- annotation_space_block_start) {
- const LayoutUnit overflow =
- -ConstraintSpace().BlockStartAnnotationSpace();
- block_offset_shift = -std::min(annotation_space_block_start, overflow);
- }
-
- // If this line has block-start annotation overflow and the previous line
- // has block-end annotation space, borrow the block-end space of the
- // previous line and shift down the block offset by |overflow - space|.
- if (annotation_overflow_block_start &&
- ConstraintSpace().BlockStartAnnotationSpace() > LayoutUnit()) {
- block_offset_shift = (annotation_overflow_block_start -
- ConstraintSpace().BlockStartAnnotationSpace())
- .ClampNegativeToZero();
- }
- block_offset += block_offset_shift;
-
- if (annotation_overflow_block_end)
- container_builder_.SetAnnotationOverflow(annotation_overflow_block_end);
- else if (annotation_space_block_end)
- container_builder_.SetBlockEndAnnotationSpace(annotation_space_block_end);
+ block_offset +=
+ SetAnnotationOverflow(*line_info, *line_box, line_box_metrics);
}
if (line_info->UseFirstLineStyle())
container_builder_.SetStyleVariant(NGStyleVariant::kFirstLine);
- container_builder_.SetBaseDirection(line_info->BaseDirection());
+ if (UNLIKELY(Node().IsTextCombine())) {
+ // The effective size of combined text is 1em square[1]
+ // [1] https://drafts.csswg.org/css-writing-modes-3/#text-combine-layout
+ const auto one_em = Node().Style().ComputedFontSizeAsFixed();
+ inline_size = std::min(inline_size, one_em);
+ }
container_builder_.SetInlineSize(inline_size);
container_builder_.SetMetrics(line_box_metrics);
container_builder_.SetBfcBlockOffset(block_offset);
+ container_builder_.SetLineBoxBfcBlockOffset(block_offset);
}
void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item,
@@ -517,7 +512,7 @@ void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item,
ClearNeedsLayoutIfNeeded(item.GetLayoutObject());
if (UNLIKELY(quirks_mode_ && !box->HasMetrics()))
- box->EnsureTextMetrics(*item.Style(), *box->font, baseline_type_);
+ box->EnsureTextMetrics(*item.Style(), *box->font);
line_box->AddChild(item, std::move(item_result->shape_result),
item_result->TextOffset(), box->text_top,
@@ -548,15 +543,34 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline(
NGLogicalLineItems* line_box) {
DCHECK(item_result->layout_result);
- // The input |position| is the line-left edge of the margin box.
- // Adjust it to the border box by adding the line-left margin.
- // const ComputedStyle& style = *item.Style();
- // position += item_result->margins.LineLeft(style.Direction());
+ // Reset the ellipsizing state. Atomic inline is monolithic.
+ LayoutObject* layout_object = item.GetLayoutObject();
+ DCHECK(layout_object);
+ DCHECK(layout_object->IsAtomicInlineLevel());
+ DCHECK_EQ(To<LayoutBox>(layout_object)->GetNGPaginationBreakability(),
+ LayoutBox::kForbidBreaks);
+ layout_object->SetIsTruncated(false);
item_result->has_edge = true;
NGInlineBoxState* box =
box_states_->OnOpenTag(item, *item_result, baseline_type_, *line_box);
- PlaceLayoutResult(item_result, line_box, box, box->margin_inline_start);
+
+ if (LIKELY(!IsA<LayoutNGTextCombine>(layout_object))) {
+ PlaceLayoutResult(item_result, line_box, box, box->margin_inline_start);
+ } else {
+ // The metrics should be as text instead of atomic inline box.
+ const auto& style = layout_object->Parent()->StyleRef();
+ box->ComputeTextMetrics(style, style.GetFont());
+ // Note: |item_result->spacing_before| is non-zero if this |item_result|
+ // is |LayoutNGTextCombine| and after CJK character.
+ // See "text-combine-justify.html".
+ const LayoutUnit inline_offset =
+ box->margin_inline_start + item_result->spacing_before;
+ line_box->AddChild(std::move(item_result->layout_result),
+ LogicalOffset{inline_offset, box->text_top},
+ item_result->inline_size, /* children_count */ 0,
+ item.BidiLevel());
+ }
return box_states_->OnCloseTag(ConstraintSpace(), line_box, box,
baseline_type_);
}
@@ -585,6 +599,59 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result,
item.BidiLevel());
}
+void NGInlineLayoutAlgorithm::PlaceBlockInInline(
+ const NGInlineItem& item,
+ const NGLineInfo& line_info,
+ NGInlineItemResult* item_result,
+ NGLogicalLineItems* line_box) {
+ DCHECK_EQ(item.Type(), NGInlineItem::kBlockInInline);
+ LayoutObject* layout_object = item.GetLayoutObject();
+ DCHECK(layout_object);
+ DCHECK(!layout_object->IsInline());
+ DCHECK(item_result->layout_result);
+ const NGLayoutResult& result = *item_result->layout_result;
+
+ // Setup |container_builder_|. Set it up here instead of in |CreateLine|,
+ // because there should be only one block-in-inline, and we need data from the
+ // |NGLayoutResult|.
+ container_builder_.SetBaseDirection(line_info.BaseDirection());
+ if (absl::optional<LayoutUnit> block_offset = result.BfcBlockOffset()) {
+ container_builder_.SetBfcBlockOffset(*block_offset);
+ container_builder_.SetLineBoxBfcBlockOffset(*block_offset);
+ container_builder_.SetEndMarginStrut(result.EndMarginStrut());
+ container_builder_.SetAdjoiningObjectTypes(result.AdjoiningObjectTypes());
+ const NGConstraintSpace& space = ConstraintSpace();
+ NGBoxFragment fragment(
+ space.GetWritingDirection(),
+ To<NGPhysicalBoxFragment>(result.PhysicalFragment()));
+ container_builder_.SetInlineSize(fragment.InlineSize());
+ // Block-in-inline is wrapped in an anonymous block that has no margins.
+ DCHECK(layout_object->IsAnonymous());
+ const FontHeight metrics = fragment.BaselineMetrics(
+ /* margins */ NGLineBoxStrut(), baseline_type_);
+ container_builder_.SetMetrics(metrics);
+ line_box->MoveInBlockDirection(metrics.ascent);
+
+ // If a spanner was found inside the child, we need to finish up and
+ // propagate the spanner to the column layout algorithm, so that it can take
+ // care of it.
+ if (UNLIKELY(ConstraintSpace().IsInColumnBfc())) {
+ if (NGBlockNode spanner_node =
+ item_result->layout_result->ColumnSpanner()) {
+ DCHECK(!container_builder_.FoundColumnSpanner());
+ container_builder_.SetColumnSpanner(spanner_node);
+ }
+ }
+ } else {
+ container_builder_.SetIsSelfCollapsing();
+ container_builder_.SetIsEmptyLineBox();
+ }
+
+ line_box->AddChild(std::move(item_result->layout_result),
+ /* offset */ LogicalOffset(), item_result->inline_size,
+ /* children_count */ 0, item.BidiLevel());
+}
+
// Place all out-of-flow objects in |line_box_|.
void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
const NGLineInfo& line_info,
@@ -593,8 +660,6 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
DCHECK(line_info.IsEmptyLine() || !line_box_metrics.IsEmpty())
<< "Non-empty lines must have a valid set of linebox metrics.";
- bool is_empty_inline = Node().IsEmptyInline();
-
// All children within the linebox are positioned relative to the baseline,
// then shifted later using NGLineBoxFragmentBuilder::MoveInBlockDirection.
LayoutUnit baseline_adjustment =
@@ -648,8 +713,7 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
// If we are an empty-inline we may not have the correct BFC block-offset
// yet. Due to this we need to mark this node as having adjoining
// objects, and perform a re-layout if our position shifts.
- if (is_empty_inline)
- container_builder_.AddAdjoiningObjectTypes(kAdjoiningInlineOutOfFlow);
+ container_builder_.AddAdjoiningObjectTypes(kAdjoiningInlineOutOfFlow);
} else {
// A block-level OOF element positions itself on the "next" line. However
// only shifts down if there is preceding inline-level content.
@@ -764,8 +828,6 @@ void NGInlineLayoutAlgorithm::PlaceRelativePositionedItems(
const auto* physical_fragment = child.PhysicalFragment();
if (!physical_fragment)
continue;
- // TODO(almaher): Handle inline relative positioning correctly for OOF
- // fragmentation.
child.rect.offset += ComputeRelativeOffsetForInline(
ConstraintSpace(), physical_fragment->Style());
}
@@ -776,8 +838,8 @@ void NGInlineLayoutAlgorithm::PlaceListMarker(const NGInlineItem& item,
NGInlineItemResult* item_result,
const NGLineInfo& line_info) {
if (UNLIKELY(quirks_mode_)) {
- box_states_->LineBoxState().EnsureTextMetrics(
- *item.Style(), item.Style()->GetFont(), baseline_type_);
+ box_states_->LineBoxState().EnsureTextMetrics(*item.Style(),
+ item.Style()->GetFont());
}
}
@@ -801,11 +863,33 @@ absl::optional<LayoutUnit> NGInlineLayoutAlgorithm::ApplyJustify(
if (end_offset == line_info->StartOffset())
return absl::nullopt;
+ const UChar kTextCombineItemMarker = 0x3042; // U+3042 Hiragana Letter A
+
// Construct the line text to compute spacing for.
StringBuilder line_text_builder;
- line_text_builder.Append(StringView(line_info->ItemsData().text_content,
- line_info->StartOffset(),
- end_offset - line_info->StartOffset()));
+ if (UNLIKELY(line_info->MayHaveTextCombineItem())) {
+ for (const NGInlineItemResult& item_result : line_info->Results()) {
+ if (item_result.StartOffset() >= end_offset)
+ break;
+ if (item_result.item->IsTextCombine()) {
+ // To apply justification before and after the combined text, we put
+ // ideographic character to increment |ShapeResultSpacing::
+ // expansion_opportunity_count_| for legacy layout compatibility.
+ // See "fast/writing-mode/text-combine-justify.html".
+ // Note: The spec[1] says we should treat combined text as U+FFFC.
+ // [1] https://drafts.csswg.org/css-writing-modes-3/#text-combine-layout
+ line_text_builder.Append(kTextCombineItemMarker);
+ continue;
+ }
+ line_text_builder.Append(StringView(line_info->ItemsData().text_content,
+ item_result.StartOffset(),
+ item_result.Length()));
+ }
+ } else {
+ line_text_builder.Append(StringView(line_info->ItemsData().text_content,
+ line_info->StartOffset(),
+ end_offset - line_info->StartOffset()));
+ }
// Append a hyphen if the last word is hyphenated. The hyphen is in
// |ShapeResult|, but not in text. |ShapeResultSpacing| needs the text that
@@ -819,7 +903,7 @@ absl::optional<LayoutUnit> NGInlineLayoutAlgorithm::ApplyJustify(
String line_text = line_text_builder.ToString();
DCHECK_GT(line_text.length(), 0u);
- ShapeResultSpacing<String> spacing(line_text);
+ ShapeResultSpacing<String> spacing(line_text, Node().IsSvgText());
spacing.SetExpansion(space, line_info->BaseDirection(),
line_info->LineStyle().GetTextJustify());
const LayoutObject* box = Node().GetLayoutBox();
@@ -865,15 +949,24 @@ absl::optional<LayoutUnit> NGInlineLayoutAlgorithm::ApplyJustify(
item_result.inline_size += item_result.HyphenInlineSize();
item_result.shape_result = ShapeResultView::Create(shape_result.get());
} else if (item_result.item->Type() == NGInlineItem::kAtomicInline) {
- float offset = 0.f;
+ float spacing_before = 0.0f;
DCHECK_LE(line_info->StartOffset(), item_result.StartOffset());
- unsigned line_text_offset =
+ const unsigned line_text_offset =
item_result.StartOffset() - line_info->StartOffset();
- DCHECK_EQ(kObjectReplacementCharacter, line_text[line_text_offset]);
- item_result.inline_size +=
- spacing.ComputeSpacing(line_text_offset, offset);
- // |offset| is non-zero only before CJK characters.
- DCHECK_EQ(offset, 0.f);
+ const float spacing_after =
+ spacing.ComputeSpacing(line_text_offset, spacing_before);
+ if (UNLIKELY(item_result.item->IsTextCombine())) {
+ // |spacing_before| is non-zero if this |item_result| is after
+ // non-CJK character. See "text-combine-justify.html".
+ DCHECK_EQ(kTextCombineItemMarker, line_text[line_text_offset]);
+ item_result.inline_size += spacing_after;
+ item_result.spacing_before = LayoutUnit(spacing_before);
+ } else {
+ DCHECK_EQ(kObjectReplacementCharacter, line_text[line_text_offset]);
+ item_result.inline_size += spacing_after;
+ // |spacing_before| is non-zero only before CJK characters.
+ DCHECK_EQ(spacing_before, 0.0f);
+ }
}
}
return inset / 2;
@@ -901,6 +994,55 @@ LayoutUnit NGInlineLayoutAlgorithm::ApplyTextAlign(NGLineInfo* line_info) {
return LineOffsetForTextAlign(text_align, line_info->BaseDirection(), space);
}
+LayoutUnit NGInlineLayoutAlgorithm::SetAnnotationOverflow(
+ const NGLineInfo& line_info,
+ const NGLogicalLineItems& line_box,
+ const FontHeight& line_box_metrics) {
+ NGAnnotationMetrics annotation_metrics = ComputeAnnotationOverflow(
+ line_box, line_box_metrics, LayoutUnit(), line_info.LineStyle());
+ LayoutUnit annotation_overflow_block_start;
+ LayoutUnit annotation_overflow_block_end;
+ LayoutUnit annotation_space_block_start;
+ LayoutUnit annotation_space_block_end;
+ if (!IsFlippedLinesWritingMode(line_info.LineStyle().GetWritingMode())) {
+ annotation_overflow_block_start = annotation_metrics.overflow_over;
+ annotation_overflow_block_end = annotation_metrics.overflow_under;
+ annotation_space_block_start = annotation_metrics.space_over;
+ annotation_space_block_end = annotation_metrics.space_under;
+ } else {
+ annotation_overflow_block_start = annotation_metrics.overflow_under;
+ annotation_overflow_block_end = annotation_metrics.overflow_over;
+ annotation_space_block_start = annotation_metrics.space_under;
+ annotation_space_block_end = annotation_metrics.space_over;
+ }
+
+ LayoutUnit block_offset_shift = annotation_overflow_block_start;
+ // If the previous line has block-end annotation overflow and this line has
+ // block-start annotation space, shift up the block offset of this line.
+ if (ConstraintSpace().BlockStartAnnotationSpace() < LayoutUnit() &&
+ annotation_space_block_start) {
+ const LayoutUnit overflow = -ConstraintSpace().BlockStartAnnotationSpace();
+ block_offset_shift = -std::min(annotation_space_block_start, overflow);
+ }
+
+ // If this line has block-start annotation overflow and the previous line
+ // has block-end annotation space, borrow the block-end space of the
+ // previous line and shift down the block offset by |overflow - space|.
+ if (annotation_overflow_block_start &&
+ ConstraintSpace().BlockStartAnnotationSpace() > LayoutUnit()) {
+ block_offset_shift = (annotation_overflow_block_start -
+ ConstraintSpace().BlockStartAnnotationSpace())
+ .ClampNegativeToZero();
+ }
+
+ if (annotation_overflow_block_end)
+ container_builder_.SetAnnotationOverflow(annotation_overflow_block_end);
+ else if (annotation_space_block_end)
+ container_builder_.SetBlockEndAnnotationSpace(annotation_space_block_end);
+
+ return block_offset_shift;
+}
+
LayoutUnit NGInlineLayoutAlgorithm::ComputeContentSize(
const NGLineInfo& line_info,
const NGExclusionSpace& exclusion_space,
@@ -921,12 +1063,14 @@ LayoutUnit NGInlineLayoutAlgorithm::ComputeContentSize(
// layout_object may be null in certain cases, e.g. if it's a kBidiControl.
if (layout_object && layout_object->IsBR()) {
- NGBfcOffset bfc_offset = {ContainerBfcOffset().line_offset,
- ContainerBfcOffset().block_offset + content_size};
+ const LayoutUnit line_box_bfc_block_offset =
+ *container_builder_.LineBoxBfcBlockOffset();
+ NGBfcOffset bfc_offset = {LayoutUnit(),
+ line_box_bfc_block_offset + content_size};
AdjustToClearance(
exclusion_space.ClearanceOffset(item.Style()->Clear(Style())),
&bfc_offset);
- content_size = bfc_offset.block_offset - ContainerBfcOffset().block_offset;
+ content_size = bfc_offset.block_offset - line_box_bfc_block_offset;
}
return content_size;
@@ -935,31 +1079,24 @@ LayoutUnit NGInlineLayoutAlgorithm::ComputeContentSize(
scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
NGExclusionSpace initial_exclusion_space(ConstraintSpace().ExclusionSpace());
- const 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 objects
- // will be affected by any subsequent block, until the BFC block offset is
- // resolved.
- container_builder_.AddAdjoiningObjectTypes(
- ConstraintSpace().AdjoiningObjectTypes());
+ container_builder_.SetAdjoiningObjectTypes(
+ ConstraintSpace().AdjoiningObjectTypes());
- // 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());
+ const bool is_empty_inline = Node().IsEmptyInline();
+#if DCHECK_IS_ON()
+ if (!is_empty_inline) {
// The BFC block-offset was determined before entering this algorithm. This
- // means that there should be no adjoining objects.
+ // means that there should be no adjoining objects, or margins.
+ DCHECK(ConstraintSpace().MarginStrut().IsEmpty() ||
+ (BreakToken() && BreakToken()->IsAfterBlockInInline()));
DCHECK(!ConstraintSpace().AdjoiningObjectTypes());
+ // Only empty-inlines should have the "forced"/"optimistic" BFC
+ // block-offset set.
+ DCHECK(!ConstraintSpace().ForcedBfcBlockOffset());
+ DCHECK(!ConstraintSpace().OptimisticBfcBlockOffset());
}
+#endif
// In order to get the correct list of layout opportunities, we need to
// position any "leading" floats within the exclusion space first.
@@ -967,9 +1104,6 @@ scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
unsigned handled_leading_floats_index =
PositionLeadingFloats(&initial_exclusion_space, &leading_floats);
- // Only empty-inlines should have the "forced" BFC block-offset set.
- DCHECK(is_empty_inline || !ConstraintSpace().ForcedBfcBlockOffset());
-
// 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 LayoutOpportunityVector& opportunities =
@@ -1027,6 +1161,8 @@ scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
leading_floats, handled_leading_floats_index,
break_token, &exclusion_space);
line_breaker.NextLine(&line_info);
+ if (UNLIKELY(line_info.AbortedLayoutResult()))
+ return line_info.AbortedLayoutResult();
// 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
@@ -1100,6 +1236,7 @@ scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
// Success!
container_builder_.SetBreakToken(line_breaker.CreateBreakToken(line_info));
+ container_builder_.SetBaseDirection(line_info.BaseDirection());
// Propagate any break tokens for floats that we fragmented before or inside
// to the block container.
@@ -1107,8 +1244,22 @@ scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
line_breaker.PropagatedBreakTokens())
context_->PropagateBreakToken(std::move(float_break_token));
- if (is_empty_inline) {
- DCHECK_EQ(container_builder_.BlockSize(), 0);
+ if (line_info.IsEmptyLine()) {
+ DCHECK_EQ(container_builder_.BlockSize(), LayoutUnit());
+ DCHECK(!container_builder_.BfcBlockOffset());
+
+ container_builder_.SetIsSelfCollapsing();
+ container_builder_.SetIsEmptyLineBox();
+
+ // Margins should collapse across "certain zero-height line boxes".
+ // https://drafts.csswg.org/css2/box.html#collapsing-margins
+ container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut());
+
+ // Finally respect the forced BFC block-offset if present.
+ if (auto bfc_block_offset = ConstraintSpace().ForcedBfcBlockOffset()) {
+ container_builder_.SetBfcBlockOffset(*bfc_block_offset);
+ container_builder_.SetLineBoxBfcBlockOffset(*bfc_block_offset);
+ }
} else {
// A <br clear=both> will strech the line-box height, such that the
// block-end edge will clear any floats.
@@ -1145,8 +1296,6 @@ scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
unsigned NGInlineLayoutAlgorithm::PositionLeadingFloats(
NGExclusionSpace* exclusion_space,
NGPositionedFloatVector* positioned_floats) {
- bool is_empty_inline = Node().IsEmptyInline();
-
const Vector<NGInlineItem>& items =
Node().ItemsData(/* is_first_line */ false).items;
@@ -1154,11 +1303,9 @@ unsigned NGInlineLayoutAlgorithm::PositionLeadingFloats(
for (; index < items.size(); ++index) {
const NGInlineItem& item = items[index];
- // Abort if we've found something that makes this a non-empty inline.
- if (!item.IsEmptyItem()) {
- DCHECK(!is_empty_inline);
+ // Abort if we've found something non-empty.
+ if (!item.IsEmptyItem())
break;
- }
if (item.Type() != NGInlineItem::kFloating)
continue;
@@ -1171,10 +1318,8 @@ unsigned NGInlineLayoutAlgorithm::PositionLeadingFloats(
// Place any floats at the "expected" BFC block-offset, this may be an
// optimistic guess.
- LayoutUnit origin_bfc_block_offset =
- is_empty_inline ? ConstraintSpace().ExpectedBfcBlockOffset()
- : ConstraintSpace().BfcOffset().block_offset;
-
+ const LayoutUnit origin_bfc_block_offset =
+ ConstraintSpace().ExpectedBfcBlockOffset();
NGPositionedFloat positioned_float = PositionFloat(
origin_bfc_block_offset, item.GetLayoutObject(), exclusion_space);
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 78875b591b4..92da513a2c4 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
@@ -97,6 +97,10 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
const NGLineInfo&,
NGInlineItemResult*,
NGLogicalLineItems* line_box);
+ void PlaceBlockInInline(const NGInlineItem&,
+ const NGLineInfo&,
+ NGInlineItemResult*,
+ NGLogicalLineItems* line_box);
void PlaceLayoutResult(NGInlineItemResult*,
NGLogicalLineItems* line_box,
NGInlineBoxState*,
@@ -121,6 +125,10 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
const NGExclusionSpace&,
LayoutUnit line_height);
+ LayoutUnit SetAnnotationOverflow(const NGLineInfo& line_info,
+ const NGLogicalLineItems& line_box,
+ const FontHeight& line_box_metrics);
+
NGInlineLayoutStateStack* box_states_;
NGInlineChildLayoutContext* context_;
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 4e87c6c3cf8..59fa5ecfbbf 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h"
+#include <sstream>
#include "third_party/blink/renderer/core/dom/tag_collection.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
@@ -20,7 +21,18 @@
namespace blink {
namespace {
-class NGInlineLayoutAlgorithmTest : public NGBaseLayoutAlgorithmTest {};
+class NGInlineLayoutAlgorithmTest : public NGBaseLayoutAlgorithmTest {
+ protected:
+ static std::string AsFragmentItemsString(const LayoutBlockFlow& root) {
+ std::ostringstream ostream;
+ ostream << std::endl;
+ for (NGInlineCursor cursor(root); cursor; cursor.MoveToNext()) {
+ const auto& item = *cursor.CurrentItem();
+ ostream << item << " " << item.RectInContainerFragment() << std::endl;
+ }
+ return ostream.str();
+ }
+};
TEST_F(NGInlineLayoutAlgorithmTest, BreakToken) {
LoadAhem();
@@ -457,6 +469,65 @@ TEST_F(NGInlineLayoutAlgorithmTest, InkOverflow) {
EXPECT_EQ(LayoutUnit(20), ink_overflow.size.height);
}
+// See also NGInlineLayoutAlgorithmTest.TextCombineFake
+TEST_F(NGInlineLayoutAlgorithmTest, TextCombineBasic) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "body { margin: 0px; font: 100px/110px Ahem; }"
+ "c { text-combine-upright: all; }"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=target>01234</c>b</div>");
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=5 LTR Standard} "0,0 110x300"
+{Text 0-1 LTR Standard} "5,0 100x100"
+{Box #descendants=2 Standard} "5,100 100x100"
+{Box #descendants=1 AtomicInlineLTR Standard} "5,100 100x100"
+{Text 2-3 LTR Standard} "5,200 100x100"
+)DUMP",
+ AsFragmentItemsString(
+ *To<LayoutBlockFlow>(GetLayoutObjectByElementId("root"))));
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=2 LTR Standard} "0,0 100x100"
+{Text 0-5 LTR Standard} "0,0 500x100"
+)DUMP",
+ AsFragmentItemsString(*To<LayoutBlockFlow>(
+ GetLayoutObjectByElementId("target")->SlowFirstChild())));
+}
+
+// See also NGInlineLayoutAlgorithmTest.TextCombineBasic
+TEST_F(NGInlineLayoutAlgorithmTest, TextCombineFake) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "body { margin: 0px; font: 100px/110px Ahem; }"
+ "c {"
+ " display: inline-block;"
+ " width: 1em; height: 1em;"
+ " writing-mode: horizontal-tb;"
+ "}"
+ "div { writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<div id=root>a<c id=target>0</c>b</div>");
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=4 LTR Standard} "0,0 110x300"
+{Text 0-1 LTR Standard} "5,0 100x100"
+{Box #descendants=1 AtomicInlineLTR Standard} "5,100 100x100"
+{Text 2-3 LTR Standard} "5,200 100x100"
+)DUMP",
+ AsFragmentItemsString(
+ *To<LayoutBlockFlow>(GetLayoutObjectByElementId("root"))));
+
+ EXPECT_EQ(R"DUMP(
+{Line #descendants=2 LTR Standard} "0,0 100x110"
+{Text 0-1 LTR Standard} "0,5 100x100"
+)DUMP",
+ AsFragmentItemsString(
+ *To<LayoutBlockFlow>(GetLayoutObjectByElementId("target"))));
+}
+
#undef MAYBE_VerticalAlignBottomReplaced
} // namespace
} // namespace blink
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 afd1765ef45..fa9c4d6537f 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
@@ -6,6 +6,7 @@
#include <algorithm>
#include <memory>
+#include <numeric>
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -13,9 +14,11 @@
#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_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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_item.h"
@@ -48,6 +51,22 @@ namespace blink {
namespace {
+// Returns sum of |ShapeResult::Width()| in |data.items|. Note: All items
+// should be text item other type of items are not allowed.
+float CalculateWidthForTextCombine(const NGInlineItemsData& data) {
+ return std::accumulate(
+ data.items.begin(), data.items.end(), 0.0f,
+ [](float sum, const NGInlineItem& item) {
+ DCHECK(item.Type() == NGInlineItem::kText ||
+ item.Type() == NGInlineItem::kBidiControl ||
+ item.Type() == NGInlineItem::kControl)
+ << item.Type();
+ if (auto* const shape_result = item.TextShapeResult())
+ return shape_result->Width() + sum;
+ return 0.0f;
+ });
+}
+
bool IsLeftAligned(const ComputedStyle& style) {
switch (style.GetTextAlign()) {
case ETextAlign::kStart:
@@ -161,22 +180,23 @@ class ReusingTextShaper final {
shaper_(data->text_content) {}
scoped_refptr<ShapeResult> Shape(const NGInlineItem& start_item,
+ const Font& font,
unsigned end_offset) {
const unsigned start_offset = start_item.StartOffset();
DCHECK_LT(start_offset, end_offset);
if (!reusable_items_)
- return Reshape(start_item, start_offset, end_offset);
+ return Reshape(start_item, font, start_offset, end_offset);
// TODO(yosin): We should support segment text
if (data_.segments)
- return Reshape(start_item, start_offset, end_offset);
+ return Reshape(start_item, font, start_offset, end_offset);
const Vector<const ShapeResult*> reusable_shape_results =
CollectReusableShapeResults(start_offset, end_offset,
start_item.Direction());
if (reusable_shape_results.IsEmpty())
- return Reshape(start_item, start_offset, end_offset);
+ return Reshape(start_item, font, start_offset, end_offset);
const scoped_refptr<ShapeResult> shape_result =
ShapeResult::CreateEmpty(*reusable_shape_results.front());
@@ -187,9 +207,9 @@ class ReusingTextShaper final {
// e.g. <div style="white-space:pre">&nbsp; abc</div>, deleteChar(0, 1)
// See xternal/wpt/editing/run/delete.html?993-993
if (offset < reusable_shape_result->StartIndex()) {
- AppendShapeResult(
- *Reshape(start_item, offset, reusable_shape_result->StartIndex()),
- shape_result.get());
+ AppendShapeResult(*Reshape(start_item, font, offset,
+ reusable_shape_result->StartIndex()),
+ shape_result.get());
offset = shape_result->EndIndex();
}
DCHECK_LT(offset, reusable_shape_result->EndIndex());
@@ -203,7 +223,7 @@ class ReusingTextShaper final {
return shape_result;
}
DCHECK_LT(offset, end_offset);
- AppendShapeResult(*Reshape(start_item, offset, end_offset),
+ AppendShapeResult(*Reshape(start_item, font, offset, end_offset),
shape_result.get());
return shape_result;
}
@@ -244,15 +264,15 @@ class ReusingTextShaper final {
}
scoped_refptr<ShapeResult> Reshape(const NGInlineItem& start_item,
+ const Font& font,
unsigned start_offset,
unsigned end_offset) {
DCHECK_LT(start_offset, end_offset);
const TextDirection direction = start_item.Direction();
- const Font& font = start_item.FontWithSVGScaling();
if (data_.segments) {
- return data_.segments->ShapeText(&shaper_, &font, direction, start_offset,
- end_offset,
- &start_item - data_.items.begin());
+ return data_.segments->ShapeText(
+ &shaper_, &font, direction, start_offset, end_offset,
+ base::checked_cast<unsigned>(&start_item - data_.items.begin()));
}
RunSegmenter::RunSegmenterRange range =
start_item.CreateRunSegmenterRange();
@@ -292,21 +312,18 @@ void CollectInlinesInternal(ItemsBuilder* builder,
builder->SetIsSymbolMarker();
builder->ClearNeedsLayout(layout_text);
-
} else if (node->IsFloating()) {
builder->AppendFloating(node);
if (builder->ShouldAbort())
return;
builder->ClearInlineFragment(node);
-
} else if (node->IsOutOfFlowPositioned()) {
builder->AppendOutOfFlowPositioned(node);
if (builder->ShouldAbort())
return;
builder->ClearInlineFragment(node);
-
} else if (node->IsAtomicInlineLevel()) {
if (node->IsBoxListMarkerIncludingNG()) {
// LayoutNGListItem produces the 'outside' list marker as an inline
@@ -320,13 +337,7 @@ void CollectInlinesInternal(ItemsBuilder* builder,
builder->AppendAtomicInline(node);
}
builder->ClearInlineFragment(node);
-
- } else {
- // Because we're collecting from LayoutObject tree, block-level children
- // should not appear. LayoutObject tree should have created an anonymous
- // box to prevent having inline/block-mixed children.
- DCHECK(node->IsInline());
- auto* layout_inline = To<LayoutInline>(node);
+ } else if (auto* layout_inline = DynamicTo<LayoutInline>(node)) {
builder->UpdateShouldCreateBoxFragment(layout_inline);
builder->EnterInline(layout_inline);
@@ -340,6 +351,11 @@ void CollectInlinesInternal(ItemsBuilder* builder,
// An empty inline node.
builder->ExitInline(layout_inline);
builder->ClearNeedsLayout(layout_inline);
+ } else {
+ DCHECK(!node->IsInline());
+ DCHECK(RuntimeEnabledFeatures::LayoutNGBlockInInlineEnabled());
+ builder->AppendBlockInInline(node);
+ builder->ClearInlineFragment(node);
}
// Find the next sibling, or parent, until we reach |block|.
@@ -485,7 +501,10 @@ void NGInlineNode::PrepareLayoutIfNeeded() const {
if (!block_flow->NeedsCollectInlines())
return;
- previous_data.reset(block_flow->TakeNGInlineNodeData());
+ // Note: For "text-combine-upright:all", we use a font calculated from
+ // text width, so we can't reuse previous data.
+ if (LIKELY(!IsTextCombine()))
+ previous_data.reset(block_flow->TakeNGInlineNodeData());
block_flow->ResetNGInlineNodeData();
}
@@ -508,6 +527,12 @@ void NGInlineNode::PrepareLayout(
LayoutBlockFlow* block_flow = GetLayoutBlockFlow();
block_flow->ClearNeedsCollectInlines();
+ if (UNLIKELY(IsTextCombine())) {
+ // To use |LayoutNGTextCombine::UsersScaleX()| in |NGFragmentItemsBuilder|,
+ // we adjust font here instead in |Layout()|,
+ AdjustFontForTextCombineUprightAll();
+ }
+
#if DCHECK_IS_ON()
// ComputeOffsetMappingIfNeeded() runs some integrity checks as part of
// creating offset mapping. Run the check, and discard the result.
@@ -545,6 +570,11 @@ class NGInlineNodeDataEditor final {
block_flow_->GetNGInlineNodeData()->items.IsEmpty())
return nullptr;
+ // For "text-combine-upright:all", we choose font to fit layout result in
+ // 1em, so font can be different than original font.
+ if (UNLIKELY(IsA<LayoutNGTextCombine>(block_flow_)))
+ return nullptr;
+
// Because of current text content has secured text, e.g. whole text is
// "***", all characters including collapsed white spaces are marker, and
// new text is original text, we can't reuse shape result.
@@ -920,13 +950,18 @@ void NGInlineNode::ComputeOffsetMapping(LayoutBlockFlow* layout_block_flow,
DCHECK(!layout_block_flow->GetDocument().NeedsLayoutTreeUpdate() ||
layout_block_flow->IsLayoutNGObjectForCanvasFormattedText());
+ const SvgTextChunkOffsets* chunk_offsets = nullptr;
+ if (data->svg_node_data_ && data->svg_node_data_->chunk_offsets.size() > 0)
+ chunk_offsets = &data->svg_node_data_->chunk_offsets;
+
// TODO(xiaochengh): ComputeOffsetMappingIfNeeded() discards the
// NGInlineItems and text content built by |builder|, because they are
// already there in NGInlineNodeData. For efficiency, we should make
// |builder| not construct items and text content.
Vector<NGInlineItem> items;
items.ReserveCapacity(EstimateInlineItemsCount(*layout_block_flow));
- NGInlineItemsBuilderForOffsetMapping builder(layout_block_flow, &items);
+ NGInlineItemsBuilderForOffsetMapping builder(layout_block_flow, &items,
+ chunk_offsets);
builder.GetOffsetMappingBuilder().ReserveCapacity(
EstimateOffsetMappingItemsCount(*layout_block_flow));
CollectInlinesInternal(&builder, nullptr);
@@ -990,33 +1025,15 @@ void NGInlineNode::CollectInlines(NGInlineNodeData* data,
LayoutBlockFlow* block = GetLayoutBlockFlow();
block->WillCollectInlines();
+ const SvgTextChunkOffsets* chunk_offsets = nullptr;
if (block->IsNGSVGText()) {
// SVG <text> doesn't support reusing the previous result now.
previous_data = nullptr;
-
- // Build NGInlineItems and NGOffsetMapping first. They are used only by
- // NGSVGTextLayoutAttributesBuilder, and are discarded because they might
- // be different from final ones.
- Vector<NGInlineItem> items;
- items.ReserveCapacity(EstimateInlineItemsCount(*block));
- NGInlineItemsBuilderForOffsetMapping items_builder(block, &items);
- items_builder.GetOffsetMappingBuilder().ReserveCapacity(
- EstimateOffsetMappingItemsCount(*block));
- CollectInlinesInternal(&items_builder, nullptr);
-
- NGSVGTextLayoutAttributesBuilder svg_attr_builder(*this);
- svg_attr_builder.Build(items_builder.ToString(), items);
-
- auto svg_data = std::make_unique<SVGInlineNodeData>();
- svg_data->character_data_list = svg_attr_builder.CharacterDataList();
- svg_data->text_path_range_list = svg_attr_builder.TextPathRangeList();
- data->svg_node_data_ = std::move(svg_data);
-
- // TODO(tkent): Pass "text chunk" information to NGInlineItemsBuilder.
+ chunk_offsets = FindSvgTextChunks(*block, *data);
}
data->items.ReserveCapacity(EstimateInlineItemsCount(*block));
- NGInlineItemsBuilder builder(block, &data->items);
+ NGInlineItemsBuilder builder(block, &data->items, chunk_offsets);
CollectInlinesInternal(&builder, previous_data);
builder.DidFinishCollectInlines(data);
@@ -1024,6 +1041,69 @@ void NGInlineNode::CollectInlines(NGInlineNodeData* data,
UseCounter::Count(GetDocument(), WebFeature::kUnicodeBidiPlainText);
}
+const SvgTextChunkOffsets* NGInlineNode::FindSvgTextChunks(
+ LayoutBlockFlow& block,
+ NGInlineNodeData& data) const {
+ TRACE_EVENT0("blink", "NGInlineNode::FindSvgTextChunks");
+ // Build NGInlineItems and NGOffsetMapping first. They are used only by
+ // NGSVGTextLayoutAttributesBuilder, and are discarded because they might
+ // be different from final ones.
+ Vector<NGInlineItem> items;
+ items.ReserveCapacity(EstimateInlineItemsCount(block));
+ NGInlineItemsBuilderForOffsetMapping items_builder(&block, &items);
+ NGOffsetMappingBuilder& mapping_builder =
+ items_builder.GetOffsetMappingBuilder();
+ mapping_builder.ReserveCapacity(EstimateOffsetMappingItemsCount(block));
+ CollectInlinesInternal(&items_builder, nullptr);
+ String ifc_text_content = items_builder.ToString();
+
+ NGSvgTextLayoutAttributesBuilder svg_attr_builder(*this);
+ svg_attr_builder.Build(ifc_text_content, items);
+
+ auto svg_data = std::make_unique<SvgInlineNodeData>();
+ svg_data->character_data_list = svg_attr_builder.CharacterDataList();
+ svg_data->text_length_range_list = svg_attr_builder.TextLengthRangeList();
+ svg_data->text_path_range_list = svg_attr_builder.TextPathRangeList();
+ data.svg_node_data_ = std::move(svg_data);
+
+ // Compute DOM offsets of text chunks.
+ mapping_builder.SetDestinationString(ifc_text_content);
+ std::unique_ptr<NGOffsetMapping> mapping = mapping_builder.Build();
+ // Index in a UTF-32 sequence
+ unsigned last_addressable = 0;
+ // Index in a UTF-16 sequence for last_addressable.
+ unsigned text_content_offset = 0;
+ StringView ifc_text_view(ifc_text_content);
+ for (const auto& char_data : data.svg_node_data_->character_data_list) {
+ if (!char_data.second.anchored_chunk)
+ continue;
+ unsigned addressable_offset = char_data.first;
+ if (addressable_offset == 0u)
+ continue;
+ while (last_addressable < addressable_offset) {
+ ++last_addressable;
+ text_content_offset =
+ ifc_text_view.NextCodePointOffset(text_content_offset);
+ }
+ const auto* unit = mapping->GetLastMappingUnit(text_content_offset);
+ // |text_content_offset| might point a control character not in any
+ // DOM nodes.
+ while (!unit) {
+ text_content_offset =
+ ifc_text_view.NextCodePointOffset(text_content_offset);
+ DCHECK_LT(text_content_offset, ifc_text_view.length());
+ unit = mapping->GetLastMappingUnit(text_content_offset);
+ }
+ auto result = data.svg_node_data_->chunk_offsets.insert(
+ To<LayoutText>(&unit->GetLayoutObject()), Vector<unsigned>());
+ result.stored_value->value.push_back(
+ unit->ConvertTextContentToFirstDOMOffset(text_content_offset));
+ }
+ return data.svg_node_data_->chunk_offsets.size() > 0
+ ? &data.svg_node_data_->chunk_offsets
+ : nullptr;
+}
+
void NGInlineNode::SegmentText(NGInlineNodeData* data) const {
SegmentBidiRuns(data);
SegmentScriptRuns(data);
@@ -1034,85 +1114,42 @@ void NGInlineNode::SegmentText(NGInlineNodeData* data) const {
// Segment NGInlineItem by script, Emoji, and orientation using RunSegmenter.
void NGInlineNode::SegmentScriptRuns(NGInlineNodeData* data) const {
- DCHECK_EQ(data->segments.get(), nullptr);
-
String& text_content = data->text_content;
if (text_content.IsEmpty()) {
- return;
- }
-
- Vector<NGInlineItem>& items = data->items;
- if (items.IsEmpty()) {
+ data->segments = nullptr;
return;
}
if (text_content.Is8Bit() && !data->is_bidi_enabled_) {
- RunSegmenter::RunSegmenterRange range = {
- 0u, data->text_content.length(), USCRIPT_LATIN,
- OrientationIterator::kOrientationKeep, FontFallbackPriority::kText};
- NGInlineItem::SetSegmentData(range, &items);
+ if (data->items.size()) {
+ RunSegmenter::RunSegmenterRange range = {
+ 0u, data->text_content.length(), USCRIPT_LATIN,
+ OrientationIterator::kOrientationKeep, FontFallbackPriority::kText};
+ NGInlineItem::SetSegmentData(range, &data->items);
+ }
+ data->segments = nullptr;
return;
}
// Segment by script and Emoji.
// Orientation is segmented separately, because it may vary by items.
text_content.Ensure16Bit();
-
- NGInlineItem* current_item = &items.front();
- unsigned range_length = current_item->Length();
+ RunSegmenter segmenter(text_content.Characters16(), text_content.length(),
+ FontOrientation::kHorizontal);
RunSegmenter::RunSegmenterRange range = RunSegmenter::NullRange();
- if (data->is_bidi_enabled_) {
- // run RunSegmenter for each bidi run
- for (wtf_size_t idx = 1; idx < items.size(); idx++) {
- NGInlineItem& item = items[idx];
- if (item.BidiLevel() == current_item->BidiLevel()) {
- // same bidi level as the previous item. We can merge
- range_length += item.Length();
- continue;
- }
-
- // We have reached the boundary of a bidi run. We need to run the script
- // segmenter.
- if (!data->segments) {
- data->segments = std::make_unique<NGInlineItemSegments>();
- }
- RunSegmenter segmenter(text_content.Characters16(), range_length,
- FontOrientation::kHorizontal,
- current_item->StartOffset());
- while (segmenter.Consume(&range)) {
- data->segments->Append(range);
- }
- range_length = item.Length();
- current_item = &item;
- }
- } else {
- range_length = text_content.length();
- }
-
- // We will now handle the last item. If the text is not bidirectional, it
- // will be the only one.
-
- if (range_length == 0) {
- return;
- }
-
- RunSegmenter segmenter(text_content.Characters16(), range_length,
- FontOrientation::kHorizontal,
- current_item->StartOffset());
bool consumed = segmenter.Consume(&range);
DCHECK(consumed);
- if (range.start == 0 && range.end == text_content.length()) {
- NGInlineItem::SetSegmentData(range, &items);
+ if (range.end == text_content.length()) {
+ NGInlineItem::SetSegmentData(range, &data->items);
+ data->segments = nullptr;
return;
}
- if (!data->segments) {
+ // This node has multiple segments.
+ if (!data->segments)
data->segments = std::make_unique<NGInlineItemSegments>();
- }
- do {
- data->segments->Append(range);
- } while (segmenter.Consume(&range));
+ data->segments->ComputeSegments(&segmenter, &range);
DCHECK_EQ(range.end, text_content.length());
}
@@ -1203,14 +1240,15 @@ void NGInlineNode::SegmentBidiRuns(NGInlineNodeData* data) const {
void NGInlineNode::ShapeText(NGInlineItemsData* data,
const String* previous_text,
- const Vector<NGInlineItem>* previous_items) const {
+ const Vector<NGInlineItem>* previous_items,
+ const Font* override_font) const {
TRACE_EVENT0("fonts", "NGInlineNode::ShapeText");
const String& text_content = data->text_content;
Vector<NGInlineItem>* items = &data->items;
// Provide full context of the entire node to the shaper.
ReusingTextShaper shaper(data, previous_items);
- ShapeResultSpacing<String> spacing(text_content);
+ ShapeResultSpacing<String> spacing(text_content, IsSvgText());
DCHECK(!data->segments ||
data->segments->EndOffset() == text_content.length());
@@ -1223,7 +1261,19 @@ void NGInlineNode::ShapeText(NGInlineItemsData* data,
}
const ComputedStyle& start_style = *start_item.Style();
- const Font& font = start_item.FontWithSVGScaling();
+ const Font& font =
+ override_font ? *override_font : start_item.FontWithSvgScaling();
+#if DCHECK_IS_ON()
+ if (!IsTextCombine()) {
+ DCHECK(!override_font);
+ } else {
+ DCHECK_EQ(font.GetFontDescription().Orientation(),
+ FontOrientation::kHorizontal);
+ LayoutNGTextCombine::AssertStyleIsValid(start_style);
+ DCHECK(!override_font ||
+ font.GetFontDescription().WidthVariant() != kRegularWidth);
+ }
+#endif
TextDirection direction = start_item.Direction();
unsigned end_index = index + 1;
unsigned end_offset = start_item.EndOffset();
@@ -1284,7 +1334,7 @@ void NGInlineNode::ShapeText(NGInlineItemsData* data,
// Shaping a single item. Skip if the existing results remain valid.
if (previous_text && end_offset == start_item.EndOffset() &&
- !NeedsShaping(start_item)) {
+ !NeedsShaping(start_item) && LIKELY(!IsTextCombine())) {
DCHECK_EQ(start_item.StartOffset(),
start_item.TextShapeResult()->StartIndex());
DCHECK_EQ(start_item.EndOffset(),
@@ -1322,9 +1372,10 @@ void NGInlineNode::ShapeText(NGInlineItemsData* data,
// Shape each item with the full context of the entire node.
scoped_refptr<ShapeResult> shape_result =
- shaper.Shape(start_item, end_offset);
+ shaper.Shape(start_item, font, end_offset);
- if (UNLIKELY(spacing.SetSpacing(font))) {
+ if (UNLIKELY(spacing.SetSpacing(font.GetFontDescription()))) {
+ DCHECK(!IsTextCombine()) << GetLayoutBlockFlow();
shape_result->ApplySpacing(spacing);
if (spacing.LetterSpacing() &&
ShouldReportLetterSpacingUseCounter(
@@ -1676,7 +1727,6 @@ static LayoutUnit ComputeContentSize(
is_after_break = false;
}
- bool has_forced_break = false;
for (const NGInlineItemResult& result : line_info.Results()) {
const NGInlineItem& item = *result.item;
if (item.Type() == NGInlineItem::kText) {
@@ -1685,22 +1735,24 @@ static LayoutUnit ComputeContentSize(
// NGInlineItem.
continue;
}
- if (item.Type() == NGInlineItem::kAtomicInline) {
+#if DCHECK_IS_ON()
+ if (item.Type() == NGInlineItem::kBlockInInline)
+ DCHECK(line_info.HasForcedBreak());
+#endif
+ if (item.Type() == NGInlineItem::kAtomicInline ||
+ item.Type() == NGInlineItem::kBlockInInline) {
// The max-size for atomic inlines are cached in |max_size_cache|.
- unsigned item_index = &item - items_data.items.begin();
+ unsigned item_index =
+ base::checked_cast<unsigned>(&item - items_data.items.begin());
position += max_size_cache[item_index];
continue;
}
if (item.Type() == NGInlineItem::kControl) {
UChar c = items_data.text_content[item.StartOffset()];
- if (c == kNewlineCharacter) {
- // Compute the forced break after all results were handled, because
- // when close tags appear after a forced break, they are included in
- // the line, and they may have inline sizes. crbug.com/991320.
- DCHECK(!has_forced_break);
- has_forced_break = true;
- continue;
- }
+#if DCHECK_IS_ON()
+ if (c == kNewlineCharacter)
+ DCHECK(line_info.HasForcedBreak());
+#endif
// Tabulation characters change the widths by their positions, so
// their widths for the max size may be different from the widths for
// the min size. Fall back to 2 pass for now.
@@ -1711,7 +1763,10 @@ static LayoutUnit ComputeContentSize(
}
position += result.inline_size;
}
- if (has_forced_break)
+ // Compute the forced break after all results were handled, because
+ // when close tags appear after a forced break, they are included in
+ // the line, and they may have inline sizes. crbug.com/991320.
+ if (line_info.HasForcedBreak())
ForceLineBreak(line_info);
}
};
@@ -1782,7 +1837,7 @@ static LayoutUnit ComputeContentSize(
if (mode == NGLineBreakerMode::kMinContent &&
can_compute_max_size_from_min_size) {
- if (node.IsSVGText()) {
+ if (node.IsSvgText()) {
*max_size_out = result;
return result;
// The following DCHECK_EQ() doesn't work well for SVG <text> because
@@ -1861,17 +1916,65 @@ bool NGInlineNode::ShouldReportLetterSpacingUseCounterForTesting(
block_flow);
}
-const Vector<std::pair<unsigned, NGSVGCharacterData>>&
-NGInlineNode::SVGCharacterDataList() const {
- DCHECK(IsSVGText());
+const Vector<std::pair<unsigned, NGSvgCharacterData>>&
+NGInlineNode::SvgCharacterDataList() const {
+ DCHECK(IsSvgText());
return Data().svg_node_data_->character_data_list;
}
-const Vector<SVGTextPathRange>& NGInlineNode::SVGTextPathRangeList() const {
- DCHECK(IsSVGText());
+const Vector<SvgTextContentRange>& NGInlineNode::SvgTextLengthRangeList()
+ const {
+ DCHECK(IsSvgText());
+ return Data().svg_node_data_->text_length_range_list;
+}
+
+const Vector<SvgTextContentRange>& NGInlineNode::SvgTextPathRangeList() const {
+ DCHECK(IsSvgText());
return Data().svg_node_data_->text_path_range_list;
}
+void NGInlineNode::AdjustFontForTextCombineUprightAll() const {
+ DCHECK(IsTextCombine()) << GetLayoutBlockFlow();
+ DCHECK(IsPrepareLayoutFinished()) << GetLayoutBlockFlow();
+
+ const float content_width = CalculateWidthForTextCombine(ItemsData(false));
+ if (UNLIKELY(content_width == 0.0f))
+ return; // See "fast/css/zero-font-size-crash.html".
+ auto& text_combine = *To<LayoutNGTextCombine>(GetLayoutBlockFlow());
+ const float desired_width = text_combine.DesiredWidth();
+ text_combine.ResetLayout();
+ if (UNLIKELY(desired_width == 0.0f)) {
+ NOTREACHED() << "We get the test case!";
+ return;
+ }
+ if (content_width <= desired_width)
+ return;
+
+ const Font& font = Style().GetFont();
+ FontSelector* const font_selector = font.GetFontSelector();
+ FontDescription description = font.GetFontDescription();
+
+ // Try compressed fonts.
+ static const std::array<FontWidthVariant, 3> kWidthVariants = {
+ kHalfWidth, kThirdWidth, kQuarterWidth};
+ for (const auto width_variant : kWidthVariants) {
+ description.SetWidthVariant(width_variant);
+ Font compressed_font(description, font_selector);
+ ShapeText(MutableData(), nullptr, nullptr, &compressed_font);
+ if (CalculateWidthForTextCombine(ItemsData(false)) <= desired_width) {
+ text_combine.SetCompressedFont(compressed_font);
+ return;
+ }
+ }
+
+ // There is no compressed font to fit within 1em. We use original font with
+ // scaling.
+ ShapeText(MutableData());
+ DCHECK_EQ(content_width, CalculateWidthForTextCombine(ItemsData(false)));
+ DCHECK_NE(content_width, 0.0f);
+ text_combine.SetScaleX(desired_width / content_width);
+}
+
bool NGInlineNode::NeedsShapingForTesting(const NGInlineItem& item) {
return NeedsShaping(item);
}
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 5f2e3f51850..cd1b4dd3b59 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
@@ -20,7 +20,7 @@ class NGInlineChildLayoutContext;
class NGLayoutResult;
class NGOffsetMapping;
struct NGInlineItemsData;
-struct SVGTextPathRange;
+struct SvgTextContentRange;
// Represents an anonymous block box to be laid out, that contains consecutive
// inline nodes and their descendants.
@@ -93,10 +93,14 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
bool IsBidiEnabled() const { return Data().is_bidi_enabled_; }
TextDirection BaseDirection() const { return Data().BaseDirection(); }
- bool HasLineEvenIfEmpty() { return EnsureData().has_line_even_if_empty_; }
+ bool HasLineEvenIfEmpty() const {
+ return EnsureData().has_line_even_if_empty_;
+ }
bool HasRuby() const { return Data().has_ruby_; }
- bool IsEmptyInline() { return EnsureData().is_empty_inline_; }
+ bool IsEmptyInline() const {
+ return !HasLineEvenIfEmpty() && EnsureData().is_empty_inline_;
+ }
bool IsBlockLevel() { return EnsureData().is_block_level_; }
@@ -116,10 +120,12 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
const LayoutBlockFlow* block_flow);
// This function is available after PrepareLayout(), only for SVG <text>.
- const Vector<std::pair<unsigned, NGSVGCharacterData>>& SVGCharacterDataList()
+ const Vector<std::pair<unsigned, NGSvgCharacterData>>& SvgCharacterDataList()
const;
// This function is available after PrepareLayout(), only for SVG <text>.
- const Vector<SVGTextPathRange>& SVGTextPathRangeList() const;
+ const Vector<SvgTextContentRange>& SvgTextLengthRangeList() const;
+ // This function is available after PrepareLayout(), only for SVG <text>.
+ const Vector<SvgTextContentRange>& SvgTextPathRangeList() const;
String ToString() const;
@@ -135,25 +141,29 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
static bool NeedsShapingForTesting(const NGInlineItem& item);
+ // Prepare inline and text content for layout. Must be called before
+ // calling the Layout method.
+ void PrepareLayoutIfNeeded() const;
+
protected:
FRIEND_TEST_ALL_PREFIXES(NGInlineNodeTest, SegmentBidiChangeSetsNeedsLayout);
bool IsPrepareLayoutFinished() const;
- // Prepare inline and text content for layout. Must be called before
- // calling the Layout method.
- void PrepareLayoutIfNeeded() const;
void PrepareLayout(std::unique_ptr<NGInlineNodeData> previous_data) const;
void CollectInlines(NGInlineNodeData*,
NGInlineNodeData* previous_data = nullptr) const;
+ const SvgTextChunkOffsets* FindSvgTextChunks(LayoutBlockFlow& block,
+ NGInlineNodeData& data) const;
void SegmentText(NGInlineNodeData*) const;
void SegmentScriptRuns(NGInlineNodeData*) const;
void SegmentFontOrientation(NGInlineNodeData*) const;
void SegmentBidiRuns(NGInlineNodeData*) const;
void ShapeText(NGInlineItemsData*,
const String* previous_text = nullptr,
- const Vector<NGInlineItem>* previous_items = nullptr) const;
+ const Vector<NGInlineItem>* previous_items = nullptr,
+ const Font* override_font = nullptr) const;
void ShapeTextForFirstLineIfNeeded(NGInlineNodeData*) const;
void AssociateItemsWithInlines(NGInlineNodeData*) const;
@@ -172,6 +182,8 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
}
const NGInlineNodeData& EnsureData() const;
+ void AdjustFontForTextCombineUprightAll() const;
+
static void ComputeOffsetMapping(LayoutBlockFlow* layout_block_flow,
NGInlineNodeData* data);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
index dc58dc3dc25..1424ac42674 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
@@ -54,7 +54,7 @@ struct CORE_EXPORT NGInlineNodeData : NGInlineItemsData {
// different.
std::unique_ptr<NGInlineItemsData> first_line_items_;
- std::unique_ptr<SVGInlineNodeData> svg_node_data_;
+ std::unique_ptr<SvgInlineNodeData> svg_node_data_;
unsigned is_bidi_enabled_ : 1;
unsigned base_direction_ : 1; // TextDirection
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 e01939420ee..b3982a57642 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
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h"
@@ -20,6 +21,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/svg_names.h"
@@ -93,7 +95,10 @@ class NGInlineNodeTest : public NGLayoutTest {
SetupHtml("t", "<div id=t style='font:10px Ahem'>test</div>");
}
- NGInlineNodeForTest CreateInlineNode() {
+ NGInlineNodeForTest CreateInlineNode(
+ LayoutNGBlockFlow* layout_block_flow = nullptr) {
+ if (layout_block_flow)
+ layout_block_flow_ = layout_block_flow;
if (!layout_block_flow_)
SetupHtml("t", "<div id=t style='font:10px'>test</div>");
NGInlineNodeForTest node(layout_block_flow_);
@@ -311,6 +316,76 @@ TEST_F(NGInlineNodeTest, CollectInlinesMixedTextEndWithON) {
EXPECT_EQ(6u, items.size());
}
+TEST_F(NGInlineNodeTest, CollectInlinesTextCombineBR) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ InsertStyleElement(
+ "#t { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetupHtml("t", u"<div id=t>a<br>z</div>");
+ NGInlineNodeForTest node =
+ CreateInlineNode(To<LayoutNGBlockFlow>(layout_object_));
+ node.CollectInlines();
+ EXPECT_EQ("a z", node.Text());
+ Vector<NGInlineItem>& items = node.Items();
+ ASSERT_EQ(3u, items.size());
+ TEST_ITEM_TYPE_OFFSET(items[0], kText, 0u, 1u);
+ TEST_ITEM_TYPE_OFFSET(items[1], kText, 1u, 2u) << "<br> isn't control";
+ TEST_ITEM_TYPE_OFFSET(items[2], kText, 2u, 3u);
+}
+
+// http://crbug.com/1222633
+TEST_F(NGInlineNodeTest, CollectInlinesTextCombineListItemMarker) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ InsertStyleElement(
+ "#t { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetupHtml("t", u"<li id=t>ab</li>");
+ // LayoutNGListItem {LI}
+ // LayoutNGOutsideListMarker {::marker}
+ // LayoutNGTextCombine (anonymous)
+ // LayoutText (anonymous) "\x{2022} "
+ // LayoutNGTextCombine (anonymous)
+ // LayoutText {#text} "a"
+ NGInlineNodeForTest node = CreateInlineNode(
+ To<LayoutNGTextCombine>(layout_object_->SlowFirstChild()));
+ node.CollectInlines();
+ EXPECT_EQ(u8"\u2022", node.Text());
+ Vector<NGInlineItem>& items = node.Items();
+ ASSERT_EQ(1u, items.size());
+ TEST_ITEM_TYPE_OFFSET(items[0], kText, 0u, 1u);
+ EXPECT_TRUE(items[0].IsSymbolMarker());
+}
+
+TEST_F(NGInlineNodeTest, CollectInlinesTextCombineNewline) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ InsertStyleElement(
+ "#t { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetupHtml("t", u"<pre id=t>a\nz</pre>");
+ NGInlineNodeForTest node =
+ CreateInlineNode(To<LayoutNGBlockFlow>(layout_object_));
+ node.CollectInlines();
+ EXPECT_EQ("a z", node.Text());
+ Vector<NGInlineItem>& items = node.Items();
+ ASSERT_EQ(3u, items.size());
+ TEST_ITEM_TYPE_OFFSET(items[0], kText, 0u, 1u);
+ TEST_ITEM_TYPE_OFFSET(items[1], kText, 1u, 2u) << "newline isn't control";
+ TEST_ITEM_TYPE_OFFSET(items[2], kText, 2u, 3u);
+}
+
+TEST_F(NGInlineNodeTest, CollectInlinesTextCombineWBR) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ InsertStyleElement(
+ "#t { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetupHtml("t", u"<div id=t>a<wbr>z</div>");
+ NGInlineNodeForTest node =
+ CreateInlineNode(To<LayoutNGBlockFlow>(layout_object_));
+ node.CollectInlines();
+ EXPECT_EQ(u8"a\u200Bz", node.Text());
+ Vector<NGInlineItem>& items = node.Items();
+ ASSERT_EQ(3u, items.size());
+ TEST_ITEM_TYPE_OFFSET(items[0], kText, 0u, 1u);
+ TEST_ITEM_TYPE_OFFSET(items[1], kText, 1u, 2u) << "<wbr> isn't control";
+ TEST_ITEM_TYPE_OFFSET(items[2], kText, 2u, 3u);
+}
+
TEST_F(NGInlineNodeTest, SegmentASCII) {
NGInlineNodeForTest node = CreateInlineNode();
node.Append("Hello", layout_object_);
@@ -871,9 +946,9 @@ TEST_F(NGInlineNodeTest, CollectInlinesShouldNotClearFirstInlineFragment) {
GetDocument().UpdateStyleAndLayoutTree();
EXPECT_TRUE(block_flow->NeedsCollectInlines());
- // |IsEmptyInline| should run |CollectInlines|.
+ // |IsBlockLevel| should run |CollectInlines|.
NGInlineNode node(block_flow);
- node.IsEmptyInline();
+ node.IsBlockLevel();
EXPECT_FALSE(block_flow->NeedsCollectInlines());
// Running |CollectInlines| should not clear |FirstInlineFragment|.
@@ -1486,4 +1561,80 @@ TEST_F(NGInlineNodeTest, LetterSpacingUseCounterUnderline) {
span->SlowFirstChild(), /* first_line */ false, p));
}
+TEST_F(NGInlineNodeTest, TextCombineUsesScalingX) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "div {"
+ " font: 10px/20px Ahem;"
+ " text-combine-upright: all;"
+ " writing-mode: vertical-rl;"
+ "}");
+ SetBodyInnerHTML("<div id=t1>0123456789</div><div id=t2>0</div>");
+
+ EXPECT_TRUE(To<LayoutNGTextCombine>(
+ GetLayoutObjectByElementId("t1")->SlowFirstChild())
+ ->UsesScaleX())
+ << "We paint combined text '0123456789' with scaling in X-axis.";
+ EXPECT_FALSE(To<LayoutNGTextCombine>(
+ GetLayoutObjectByElementId("t2")->SlowFirstChild())
+ ->UsesScaleX())
+ << "We paint combined text '0' without scaling in X-axis.";
+}
+
+// http://crbug.com/1226930
+TEST_F(NGInlineNodeTest, TextCombineWordSpacing) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "div {"
+ " font: 10px/20px Ahem;"
+ " letter-spacing: 1px;"
+ " text-combine-upright: all;"
+ " word-spacing: 1px;"
+ " writing-mode: vertical-rl;"
+ "}");
+ SetBodyInnerHTML("<div id=t1>ab</div>");
+ const auto& text =
+ *To<Text>(GetElementById("t1")->firstChild())->GetLayoutObject();
+ const auto& font_description = text.StyleRef().GetFont().GetFontDescription();
+
+ EXPECT_EQ(0, font_description.LetterSpacing());
+ EXPECT_EQ(0, font_description.WordSpacing());
+}
+
+// crbug.com/1034464 bad.svg
+TEST_F(NGInlineNodeTest, FindSvgTextChunksCrash1) {
+ ScopedSVGTextNGForTest enable_svg_text_ng(true);
+ SetBodyInnerHTML(
+ "<svg><text id='text' xml:space='preserve'>"
+ "<tspan unicode-bidi='embed' x='0'>(</tspan>"
+ "<tspan y='-2' unicode-bidi='embed' x='3'>)</tspan>"
+ "<tspan y='-2' x='6'>&#x05d2;</tspan>"
+ "<tspan y='-2' unicode-bidi='embed' x='10'>(</tspan>"
+ "</text></svg>");
+
+ auto* block_flow = To<LayoutNGSVGText>(GetLayoutObjectByElementId("text"));
+ const NGInlineNodeData* data = block_flow->GetNGInlineNodeData();
+ EXPECT_TRUE(data);
+ // Pass if no null pointer dereferences.
+}
+
+// crbug.com/1034464 good.svg
+TEST_F(NGInlineNodeTest, FindSvgTextChunksCrash2) {
+ ScopedSVGTextNGForTest enable_svg_text_ng(true);
+ SetBodyInnerHTML(
+ "<svg><text id='text' xml:space='preserve'>\n"
+ "<tspan unicode-bidi='embed' x='0'>(</tspan>\n"
+ "<tspan y='-2' unicode-bidi='embed' x='3'>)</tspan>\n"
+ "<tspan y='-2' x='6'>&#x05d2;</tspan>\n"
+ "<tspan y='-2' unicode-bidi='embed' x='10'>(</tspan>\n"
+ "</text></svg>");
+
+ auto* block_flow = To<LayoutNGSVGText>(GetLayoutObjectByElementId("text"));
+ const NGInlineNodeData* data = block_flow->GetNGInlineNodeData();
+ EXPECT_TRUE(data);
+ // Pass if no DCHECK() failures.
+}
+
} // namespace blink
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 984f06e7d8b..1b67ab8a75a 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
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
namespace blink {
@@ -24,6 +25,9 @@ void NGLineBoxFragmentBuilder::Reset() {
oof_positioned_candidates_.Shrink(0);
unpositioned_list_marker_ = NGUnpositionedListMarker();
+ bfc_block_offset_.reset();
+ line_box_bfc_block_offset_.reset();
+
size_.inline_size = LayoutUnit();
metrics_ = FontHeight::Empty();
line_box_type_ = NGPhysicalLineBoxFragment::kNormalLineBox;
@@ -43,11 +47,15 @@ void NGLineBoxFragmentBuilder::PropagateChildrenData(
for (unsigned index = 0; index < children.size(); ++index) {
auto& child = children[index];
if (child.layout_result) {
- // TODO(almaher): Handle the inline case correctly for OOF fragmentation.
- // The relative offset should not always be set to LogicalOffset() here.
- PropagateChildData(child.layout_result->PhysicalFragment(),
- child.Offset(),
- /* relative_offset */ LogicalOffset());
+ // An accumulated relative offset is applied to an OOF once it reaches its
+ // inline container. Subtract out the relative offset to avoid adding it
+ // twice.
+ PropagateChildData(
+ child.layout_result->PhysicalFragment(),
+ child.Offset() -
+ ComputeRelativeOffsetForInline(*ConstraintSpace(),
+ child.PhysicalFragment()->Style()),
+ /* reltaive_offset */ LogicalOffset());
// Skip over any children, the information should have already been
// propagated into this layout result.
@@ -65,7 +73,8 @@ void NGLineBoxFragmentBuilder::PropagateChildrenData(
}
DCHECK(oof_positioned_descendants_.IsEmpty());
- MoveOutOfFlowDescendantCandidatesToDescendants();
+ MoveOutOfFlowDescendantCandidatesToDescendants(
+ /* relative_offset */ LogicalOffset());
}
scoped_refptr<const NGLayoutResult>
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 6eded71012c..e84780e8721 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
@@ -59,6 +59,14 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
// Mark this line box is an "empty" line box. See NGLineBoxType.
void SetIsEmptyLineBox();
+ absl::optional<LayoutUnit> LineBoxBfcBlockOffset() const {
+ return line_box_bfc_block_offset_;
+ }
+ void SetLineBoxBfcBlockOffset(LayoutUnit offset) {
+ DCHECK(bfc_block_offset_);
+ line_box_bfc_block_offset_ = offset;
+ }
+
const FontHeight& Metrics() const { return metrics_; }
void SetMetrics(const FontHeight& metrics) { metrics_ = metrics; }
@@ -81,6 +89,7 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
scoped_refptr<const NGLayoutResult> ToLineBoxFragment();
private:
+ absl::optional<LayoutUnit> line_box_bfc_block_offset_;
FontHeight metrics_ = FontHeight::Empty();
LayoutUnit hang_inline_size_;
NGPhysicalLineBoxFragment::NGLineBoxType line_box_type_;
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 fe15c52f456..6a7e4d86f9d 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
#include "base/containers/adapters.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.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"
@@ -20,7 +21,9 @@
#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/ng/svg/resolved_text_layout_attributes_iterator.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/svg/svg_text_content_element.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h"
#include "third_party/blink/renderer/platform/text/character.h"
@@ -157,6 +160,24 @@ void CollectCharIndex(void* context,
index_list->push_back(char_index);
}
+float ComputeWordWidth(const ShapeResult& shape_result,
+ wtf_size_t start_offset,
+ wtf_size_t end_offset) {
+ const wtf_size_t offset_adjust = shape_result.StartIndex();
+ const float start_position =
+ shape_result.CachedPositionForOffset(start_offset - offset_adjust);
+ const float end_position =
+ shape_result.CachedPositionForOffset(end_offset - offset_adjust);
+ return IsLtr(shape_result.Direction()) ? end_position - start_position
+ : start_position - end_position;
+}
+
+inline LayoutNGTextCombine* MayBeTextCombine(const NGInlineItem* item) {
+ if (!item)
+ return nullptr;
+ return DynamicTo<LayoutNGTextCombine>(item->GetLayoutObject());
+}
+
} // namespace
inline void NGLineBreaker::ClearNeedsLayout(const NGInlineItem& item) {
@@ -167,6 +188,16 @@ inline void NGLineBreaker::ClearNeedsLayout(const NGInlineItem& item) {
layout_object->ClearNeedsLayout();
}
+inline bool NGLineBreaker::ShouldAutoWrap(const ComputedStyle& style) const {
+ // TODO(crbug.com/366553): SVG <text> should not be auto_wrap_ for now.
+ if (UNLIKELY(is_svg_text_))
+ return false;
+ // Combine text should not cause line break.
+ if (UNLIKELY(is_text_combine_))
+ return false;
+ return style.AutoWrap();
+}
+
LayoutUnit NGLineBreaker::ComputeAvailableWidth() const {
LayoutUnit available_width = line_opportunity_.AvailableInlineSize();
// Make sure it's at least the initial size, which is usually 0 but not so
@@ -190,7 +221,8 @@ NGLineBreaker::NGLineBreaker(NGInlineNode node,
: line_opportunity_(line_opportunity),
node_(node),
mode_(mode),
- is_svg_text_(node.IsSVGText()),
+ is_svg_text_(node.IsSvgText()),
+ is_text_combine_(node.IsTextCombine()),
is_first_formatted_line_((!break_token || (!break_token->ItemIndex() &&
!break_token->TextOffset())) &&
node.CanContainFirstFormattedLine()),
@@ -208,12 +240,17 @@ NGLineBreaker::NGLineBreaker(NGInlineNode node,
break_token_(break_token),
break_iterator_(text_content_),
shaper_(text_content_),
- spacing_(text_content_),
+ spacing_(text_content_, is_svg_text_),
leading_floats_(leading_floats),
handled_leading_floats_index_(handled_leading_floats_index),
base_direction_(node_.BaseDirection()) {
available_width_ = ComputeAvailableWidth();
break_iterator_.SetBreakSpace(BreakSpaceType::kAfterSpaceRun);
+ if (is_svg_text_) {
+ svg_resolved_iterator_ =
+ std::make_unique<ResolvedTextLayoutAttributesIterator>(
+ node_.SvgCharacterDataList());
+ }
if (!break_token)
return;
@@ -252,6 +289,8 @@ inline NGInlineItemResult* NGLineBreaker::AddItem(const NGInlineItem& item,
DCHECK_GE(offset_, item.StartOffset());
DCHECK_GE(end_offset, offset_);
DCHECK_LE(end_offset, item.EndOffset());
+ if (UNLIKELY(item.IsTextCombine()))
+ line_info->SetHaveTextCombineItem();
NGInlineItemResults* item_results = line_info->MutableResults();
return &item_results->emplace_back(
&item, item_index_, NGTextOffset(offset_, end_offset),
@@ -330,7 +369,8 @@ void NGLineBreaker::RecalcClonedBoxDecorations() {
has_cloned_box_decorations_ = true;
++cloned_box_decorations_count_;
NGInlineItemResult item_result;
- ComputeOpenTagResult(*item, constraint_space_, &item_result);
+ if (!is_svg_text_)
+ ComputeOpenTagResult(*item, constraint_space_, &item_result);
cloned_box_decorations_initial_size_ += item_result.inline_size;
cloned_box_decorations_end_size_ += item_result.margins.inline_end +
item_result.borders.inline_end +
@@ -351,8 +391,7 @@ void NGLineBreaker::RecalcClonedBoxDecorations() {
// |position_|
LayoutUnit NGLineBreaker::AddHyphen(NGInlineItemResults* item_results,
wtf_size_t index,
- NGInlineItemResult* item_result,
- const NGInlineItem& item) {
+ NGInlineItemResult* item_result) {
DCHECK(!HasHyphen());
DCHECK_EQ(index,
static_cast<wtf_size_t>(item_result - item_results->begin()));
@@ -360,14 +399,7 @@ LayoutUnit NGLineBreaker::AddHyphen(NGInlineItemResults* item_results,
hyphen_index_ = index;
if (!item_result->hyphen_string) {
- DCHECK(!item_result->hyphen_shape_result);
- DCHECK(item.Style());
- const ComputedStyle& style = *item.Style();
- DCHECK(!item_result->hyphen_string);
- item_result->hyphen_string = style.HyphenString();
- HarfBuzzShaper shaper(item_result->hyphen_string);
- item_result->hyphen_shape_result =
- shaper.Shape(&style.GetFont(), style.Direction());
+ item_result->ShapeHyphen();
has_any_hyphens_ = true;
}
DCHECK(item_result->hyphen_string);
@@ -383,14 +415,15 @@ LayoutUnit NGLineBreaker::AddHyphen(NGInlineItemResults* item_results,
wtf_size_t index) {
NGInlineItemResult* item_result = &(*item_results)[index];
DCHECK(item_result->item);
- return AddHyphen(item_results, index, item_result, *item_result->item);
+ return AddHyphen(item_results, index, item_result);
}
LayoutUnit NGLineBreaker::AddHyphen(NGInlineItemResults* item_results,
- NGInlineItemResult* item_result,
- const NGInlineItem& item) {
- return AddHyphen(item_results, item_result - item_results->begin(),
- item_result, item);
+ NGInlineItemResult* item_result) {
+ return AddHyphen(
+ item_results,
+ base::checked_cast<wtf_size_t>(item_result - item_results->begin()),
+ item_result);
}
// Remove the hyphen string from the |NGInlineItemResult|.
@@ -416,11 +449,11 @@ void NGLineBreaker::RestoreLastHyphen(NGInlineItemResults* item_results) {
DCHECK(has_any_hyphens_);
for (NGInlineItemResult& item_result : base::Reversed(*item_results)) {
DCHECK(item_result.item);
- const NGInlineItem& item = *item_result.item;
if (item_result.hyphen_string) {
- AddHyphen(item_results, &item_result, item);
+ AddHyphen(item_results, &item_result);
return;
}
+ const NGInlineItem& item = *item_result.item;
if (item.Type() == NGInlineItem::kText ||
item.Type() == NGInlineItem::kAtomicInline)
return;
@@ -590,6 +623,10 @@ void NGLineBreaker::BreakLine(
HandleBidiControlItem(item, line_info);
continue;
}
+ if (item.Type() == NGInlineItem::kBlockInInline) {
+ HandleBlockInInline(item, line_info);
+ continue;
+ }
// Items after this point are not trailable. If we're trailing, break before
// any non-trailable items
@@ -638,32 +675,137 @@ void NGLineBreaker::ComputeLineLocation(NGLineInfo* line_info) const {
}
// Atomic inlines have break opportunities before and after, even when the
-// adjacent character is U+00A0 NO-BREAK SPACE character.
-bool NGLineBreaker::ShouldForceCanBreakAfter(
- const NGInlineItemResult& item_result) const {
+// adjacent character is U+00A0 NO-BREAK SPACE character, except when sticky
+// images quirk is applied.
+// Note: We treat text combine as text content instead of atomic inline box[1].
+// [1] https://drafts.csswg.org/css-writing-modes-3/#text-combine-layout
+bool NGLineBreaker::CanBreakAfterAtomicInline(const NGInlineItem& item) const {
+ DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline);
+ if (!auto_wrap_ || item.EndOffset() == Text().length())
+ return false;
+ // We can not break before sticky images quirk was applied.
+ if (item.IsImage())
+ return !sticky_images_quirk_;
+
+ if (item.IsRubyRun())
+ return break_iterator_.IsBreakable(item.EndOffset());
+
+ // Handles text combine
+ // See "fast/writing-mode/text-combine-line-break.html".
+ auto* const text_combine = MayBeTextCombine(&item);
+ if (LIKELY(!text_combine))
+ return true;
+
+ // Populate |text_content| with |item| and text content after |item|.
+ StringBuilder text_content;
+ NGInlineNode(text_combine).PrepareLayoutIfNeeded();
+ text_content.Append(text_combine->GetTextContent());
+ const auto text_combine_end_offset = text_content.length();
+ auto* const atomic_inline_item = TryGetAtomicInlineItemAfter(item);
+ if (auto* next_text_combine = MayBeTextCombine(atomic_inline_item)) {
+ // Note: In |NGLineBreakerMode::k{Min,Max}Content|, we've not laid
+ // out atomic line box yet.
+ NGInlineNode(next_text_combine).PrepareLayoutIfNeeded();
+ text_content.Append(next_text_combine->GetTextContent());
+ } else {
+ text_content.Append(StringView(Text(), item.EndOffset(),
+ Text().length() - item.EndOffset()));
+ }
+
+ DCHECK_EQ(Text(), break_iterator_.GetString());
+ LazyLineBreakIterator break_iterator(text_content.ToString(),
+ break_iterator_.Locale(),
+ break_iterator_.BreakType());
+ break_iterator.SetBreakSpace(break_iterator_.BreakSpace());
+ return break_iterator.IsBreakable(text_combine_end_offset);
+}
+
+bool NGLineBreaker::CanBreakAfter(const NGInlineItem& item) const {
+ DCHECK_NE(item.Type(), NGInlineItem::kAtomicInline);
+ DCHECK(auto_wrap_);
+ const bool can_break_after = break_iterator_.IsBreakable(item.EndOffset());
+ if (item.Type() != NGInlineItem::kText) {
+ DCHECK_EQ(item.Type(), NGInlineItem::kControl) << "We get the test case!";
+ // Example: <div>12345\t\t678</div>
+ // NGInlineItem[0] kText "12345"
+ // NGInlineItem[1] kControl "\t\t"
+ // NGInlineItem[2] kText "678"
+ // See NGLineBreakerTest.OverflowTab
+ return can_break_after;
+ }
+ auto* const atomic_inline_item = TryGetAtomicInlineItemAfter(item);
+ if (!atomic_inline_item)
+ return can_break_after;
+
+ if (atomic_inline_item->IsRubyRun())
+ return can_break_after;
+
+ // We can not break before sticky images quirk was applied.
+ if (UNLIKELY(Text()[atomic_inline_item->StartOffset()] ==
+ kNoBreakSpaceCharacter)) {
+ // "One " <img> => We can break after "One ".
+ // "One" <img> => We can not break after "One".
+ // See "tables/mozilla/bugs/bug101674.html"
+ DCHECK(atomic_inline_item->IsImage() && sticky_images_quirk_);
+ return can_break_after;
+ }
+
+ // Handles text combine as its text contents followed by |item|.
+ // See "fast/writing-mode/text-combine-line-break.html".
+ auto* const text_combine = MayBeTextCombine(atomic_inline_item);
+ if (LIKELY(!text_combine))
+ return true;
+
+ // Populate |text_content| with |item| and |text_combine|.
+ // Following test reach here:
+ // * fast/writing-mode/text-combine-compress.html
+ // * virtual/text-antialias/international/text-combine-image-test.html
+ // * virtual/text-antialias/international/text-combine-text-transform.html
+ StringBuilder text_content;
+ text_content.Append(StringView(Text(), item.StartOffset(), item.Length()));
+ const auto item_end_offset = text_content.length();
+ // Note: In |NGLineBreakerMode::k{Min,Max}Content|, we've not laid out
+ // atomic line box yet.
+ NGInlineNode(text_combine).PrepareLayoutIfNeeded();
+ text_content.Append(text_combine->GetTextContent());
+
+ DCHECK_EQ(Text(), break_iterator_.GetString());
+ LazyLineBreakIterator break_iterator(text_content.ToString(),
+ break_iterator_.Locale(),
+ break_iterator_.BreakType());
+ break_iterator.SetBreakSpace(break_iterator_.BreakSpace());
+ return break_iterator.IsBreakable(item_end_offset);
+}
+
+bool NGLineBreaker::MayBeAtomicInline(wtf_size_t offset) const {
+ DCHECK_LT(offset, Text().length());
+ const auto char_code = Text()[offset];
+ if (char_code == kObjectReplacementCharacter)
+ return true;
+ return sticky_images_quirk_ && char_code == kNoBreakSpaceCharacter;
+}
+
+const NGInlineItem* NGLineBreaker::TryGetAtomicInlineItemAfter(
+ const NGInlineItem& item) const {
DCHECK(auto_wrap_);
- DCHECK_EQ(item_result.item->Type(), NGInlineItem::kText);
const String& text = Text();
- DCHECK_GE(text.length(), item_result.EndOffset());
- if (text.length() <= item_result.EndOffset() ||
- text[item_result.EndOffset()] != kObjectReplacementCharacter)
- return false;
+ if (item.EndOffset() == text.length())
+ return nullptr;
+ if (!MayBeAtomicInline(item.EndOffset()))
+ return nullptr;
+
// This kObjectReplacementCharacter can be any objects, such as a floating or
// an OOF object. Check if it's really an atomic inline.
const Vector<NGInlineItem>& items = Items();
- for (const NGInlineItem* item = std::next(item_result.item);
- item != items.end(); ++item) {
- DCHECK_EQ(item->StartOffset(), item_result.EndOffset());
- if (item->Type() == NGInlineItem::kAtomicInline) {
- // Except when sticky images quirk was applied.
- if (UNLIKELY(text[item->StartOffset()] == kNoBreakSpaceCharacter))
- return false;
- return !item->IsRubyRun();
- }
- if (item->EndOffset() > item_result.EndOffset())
- break;
+ for (const NGInlineItem* next_item = std::next(&item);
+ next_item != items.end(); ++next_item) {
+ DCHECK_EQ(next_item->StartOffset(), item.EndOffset());
+ if (next_item->Type() == NGInlineItem::kAtomicInline)
+ return next_item;
+ if (next_item->EndOffset() > item.EndOffset())
+ return nullptr;
}
- return false;
+ return nullptr;
}
void NGLineBreaker::HandleText(const NGInlineItem& item,
@@ -673,7 +815,7 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
(item.Type() == NGInlineItem::kControl &&
Text()[item.StartOffset()] == kTabulationCharacter));
DCHECK(&shape_result);
- DCHECK_EQ(auto_wrap_, !is_svg_text_ && item.Style()->AutoWrap());
+ DCHECK_EQ(auto_wrap_, ShouldAutoWrap(*item.Style()));
// If we're trailing, only trailing spaces can be included in this line.
if (UNLIKELY(state_ == LineBreakState::kTrailing)) {
@@ -781,7 +923,8 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
state_ = LineBreakState::kTrailing;
if (item_result->item->Style()->WhiteSpace() == EWhiteSpace::kPreWrap &&
IsBreakableSpace(Text()[item_result->EndOffset() - 1])) {
- unsigned end_index = item_result - line_info->Results().begin();
+ unsigned end_index = base::checked_cast<unsigned>(
+ item_result - line_info->Results().begin());
Rewind(end_index, line_info);
}
return;
@@ -805,7 +948,7 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
}
if (is_svg_text_) {
- SplitTextByGlyphs(item, line_info);
+ SplitTextIntoSegements(item, line_info);
return;
}
@@ -834,15 +977,14 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
MoveToNextOf(item);
}
-// In SVG <text>, we produce NGInlineItemResult split by glyphs for simplicity.
+// In SVG <text>, we produce NGInlineItemResult split into segments partitioned
+// by x/y/dx/dy/rotate attributes.
+//
// Split in PrepareLayout() or after producing NGFragmentItem would need
// additional memory overhead. So we split in NGLineBreaker while it converts
// NGInlineItems to NGInlineItemResults.
-//
-// TODO(crbug.com/1179585): Ideally we should split the text by segments
-// partitioned by x/y/dx/dy/rotate attributes.
-void NGLineBreaker::SplitTextByGlyphs(const NGInlineItem& item,
- NGLineInfo* line_info) {
+void NGLineBreaker::SplitTextIntoSegements(const NGInlineItem& item,
+ NGLineInfo* line_info) {
DCHECK(RuntimeEnabledFeatures::SVGTextNGEnabled());
DCHECK(is_svg_text_);
DCHECK_EQ(offset_, item.StartOffset());
@@ -854,15 +996,35 @@ void NGLineBreaker::SplitTextByGlyphs(const NGInlineItem& item,
if (shape.IsRtl())
index_list.Reverse();
wtf_size_t size = index_list.size();
+ unsigned glyph_start = offset_;
for (wtf_size_t i = 0; i < size; ++i) {
- DCHECK_EQ(offset_, index_list[i]);
+ DCHECK_EQ(glyph_start, index_list[i]);
unsigned glyph_end = i + 1 < size ? index_list[i + 1] : shape.EndIndex();
+ StringView text_view(Text());
+ bool should_split = i == size - 1;
+ for (; glyph_start < glyph_end;
+ glyph_start = text_view.NextCodePointOffset(glyph_start)) {
+ ++svg_addressable_offset_;
+ should_split = should_split || ShouldCreateNewSvgSegment();
+ }
+ if (!should_split)
+ continue;
NGInlineItemResult* result = AddItem(item, glyph_end, line_info);
result->should_create_line_box = true;
auto shape_result_view =
ShapeResultView::Create(&shape, offset_, glyph_end);
- result->inline_size =
- shape_result_view->SnappedWidth().ClampNegativeToZero();
+ // For general CSS text, we apply SnappedWidth().ClampNegativeToZero().
+ // However we need to remove ClampNegativeToZero() for SVG <text> in order
+ // to get similar character positioning.
+ //
+ // For general CSS text, a negative word-spacing value decreases
+ // inline_size of an NGInlineItemResult consisting of multiple characters,
+ // and the inline_size rarely becomes negative. However, for SVG <text>,
+ // it decreases inline_size of an NGInlineItemResult consisting of only a
+ // space character, and the inline_size becomes negative easily.
+ //
+ // See svg/W3C-SVG-1.1/text-spacing-01-b.svg.
+ result->inline_size = shape_result_view->SnappedWidth();
result->shape_result = std::move(shape_result_view);
offset_ = glyph_end;
position_ += result->inline_size;
@@ -871,6 +1033,28 @@ void NGLineBreaker::SplitTextByGlyphs(const NGInlineItem& item,
MoveToNextOf(item);
}
+bool NGLineBreaker::ShouldCreateNewSvgSegment() const {
+ DCHECK(is_svg_text_);
+ for (const auto& range : node_.SvgTextPathRangeList()) {
+ if (range.start_index <= svg_addressable_offset_ &&
+ svg_addressable_offset_ <= range.end_index)
+ return true;
+ }
+ for (const auto& range : node_.SvgTextLengthRangeList()) {
+ if (To<SVGTextContentElement>(range.layout_object->GetNode())
+ ->lengthAdjust()
+ ->CurrentEnumValue() == kSVGLengthAdjustSpacingAndGlyphs)
+ continue;
+ if (range.start_index <= svg_addressable_offset_ &&
+ svg_addressable_offset_ <= range.end_index)
+ return true;
+ }
+ const NGSvgCharacterData& char_data =
+ svg_resolved_iterator_->AdvanceTo(svg_addressable_offset_);
+ return char_data.HasRotate() || char_data.HasX() || char_data.HasY() ||
+ char_data.HasDx() || char_data.HasDy();
+}
+
NGLineBreaker::BreakResult NGLineBreaker::BreakText(
NGInlineItemResult* item_result,
const NGInlineItem& item,
@@ -960,7 +1144,7 @@ NGLineBreaker::BreakResult NGLineBreaker::BreakText(
if (UNLIKELY(result.is_hyphenated)) {
NGInlineItemResults* item_results = line_info->MutableResults();
const LayoutUnit hyphen_inline_size =
- AddHyphen(item_results, item_result, item);
+ AddHyphen(item_results, item_result);
// If the hyphen overflows, retry with the reduced available width.
if (!result.is_overflow && inline_size <= available_width) {
const LayoutUnit space_for_hyphen =
@@ -1000,11 +1184,7 @@ NGLineBreaker::BreakResult NGLineBreaker::BreakText(
}
} else {
DCHECK_EQ(item_result->EndOffset(), item.EndOffset());
- item_result->can_break_after =
- break_iterator_.IsBreakable(item_result->EndOffset());
- if (!item_result->can_break_after && item.Type() == NGInlineItem::kText &&
- ShouldForceCanBreakAfter(*item_result))
- item_result->can_break_after = true;
+ item_result->can_break_after = CanBreakAfter(item);
trailing_whitespace_ = WhitespaceState::kUnknown;
}
@@ -1027,6 +1207,7 @@ bool NGLineBreaker::BreakTextAtPreviousBreakOpportunity(
const NGInlineItem& item = *item_result->item;
DCHECK_EQ(item.Type(), NGInlineItem::kText);
DCHECK(item.Style() && item.Style()->AutoWrap());
+ DCHECK(!is_text_combine_);
// TODO(jfernandez): Should we use the non-hangable-run-end instead ?
unsigned break_opportunity = break_iterator_.PreviousBreakOpportunity(
@@ -1085,10 +1266,6 @@ bool NGLineBreaker::HandleTextForFastMinContent(NGInlineItemResult* item_result,
if (fast_min_content_item_ == &item)
return false;
- // Hyphenation is not supported yet.
- if (hyphenation_)
- return false;
-
absl::optional<LineBreakType> saved_line_break_type;
if (break_anywhere_if_overflow_ && !override_break_anywhere_) {
saved_line_break_type = break_iterator_.BreakType();
@@ -1102,9 +1279,11 @@ bool NGLineBreaker::HandleTextForFastMinContent(NGInlineItemResult* item_result,
const String& text = Text();
float min_width = 0;
unsigned last_end_offset = 0;
+ unsigned end_offset = start_offset + 1;
+ absl::optional<LayoutUnit> hyphen_inline_size;
while (start_offset < item.EndOffset()) {
- unsigned end_offset = break_iterator_.NextBreakOpportunity(
- start_offset + 1, item.EndOffset());
+ end_offset =
+ break_iterator_.NextBreakOpportunity(end_offset, item.EndOffset());
unsigned non_hangable_run_end = end_offset;
if (item.Style()->WhiteSpace() != EWhiteSpace::kBreakSpaces) {
@@ -1118,19 +1297,60 @@ bool NGLineBreaker::HandleTextForFastMinContent(NGInlineItemResult* item_result,
if (end_offset >= item.EndOffset())
break;
- // Inserting a hyphenation character is not supported yet.
- // TODO (jfernandez): Maybe we need to use 'end_offset' here ?
- if (text[non_hangable_run_end - 1] == kSoftHyphenCharacter)
- return false;
+ // Ignore soft-hyphen opportunities if `hyphens: none`.
+ bool has_hyphen = text[non_hangable_run_end - 1] == kSoftHyphenCharacter;
+ if (has_hyphen && !enable_soft_hyphen_) {
+ ++end_offset;
+ if (end_offset < item.EndOffset())
+ continue;
+ has_hyphen = false;
+ }
+
+ if (UNLIKELY(hyphenation_)) {
+ // When 'hyphens: auto', compute all hyphenation opportunities.
+ if (!hyphen_inline_size) {
+ if (!item_result->hyphen_shape_result)
+ item_result->ShapeHyphen();
+ hyphen_inline_size = item_result->HyphenInlineSize();
+ }
+ wtf_size_t word_len = non_hangable_run_end - start_offset;
+ const StringView word(text, start_offset, word_len);
+ Vector<wtf_size_t, 8> locations = hyphenation_->HyphenLocations(word);
+ // |locations| is a list of hyphenation points in the descending order.
+ // Append 0 to process all parts the same way.
+ DCHECK(std::is_sorted(locations.rbegin(), locations.rend()));
+ DCHECK(!locations.Contains(0u));
+ DCHECK(!locations.Contains(word_len));
+ locations.push_back(0);
+ LayoutUnit max_part_width;
+ for (const wtf_size_t location : locations) {
+ LayoutUnit part_width = LayoutUnit::FromFloatCeil(ComputeWordWidth(
+ shape_result, start_offset + location, start_offset + word_len));
+ if (has_hyphen)
+ part_width += *hyphen_inline_size;
+ max_part_width = std::max(part_width, max_part_width);
+ word_len = location;
+ has_hyphen = true;
+ }
+ min_width = std::max(max_part_width.ToFloat(), min_width);
+ } else {
+ float word_width =
+ ComputeWordWidth(shape_result, start_offset, non_hangable_run_end);
+
+ // Append hyphen-width to `word_width` if the word is hyphenated.
+ if (has_hyphen) {
+ if (!hyphen_inline_size) {
+ if (!item_result->hyphen_shape_result)
+ item_result->ShapeHyphen();
+ hyphen_inline_size = item_result->HyphenInlineSize();
+ }
+ word_width =
+ (LayoutUnit::FromFloatCeil(word_width) + *hyphen_inline_size)
+ .ToFloat();
+ }
- float start_position = shape_result.CachedPositionForOffset(
- start_offset - shape_result.StartIndex());
- float end_position = shape_result.CachedPositionForOffset(
- non_hangable_run_end - shape_result.StartIndex());
- float word_width = IsLtr(shape_result.Direction())
- ? end_position - start_position
- : start_position - end_position;
- min_width = std::max(word_width, min_width);
+ min_width = std::max(word_width, min_width);
+ }
last_end_offset = non_hangable_run_end;
// TODO (jfernandez): I think that having the non_hangable_run_end
@@ -1140,6 +1360,7 @@ bool NGLineBreaker::HandleTextForFastMinContent(NGInlineItemResult* item_result,
IsBreakableSpace(text[start_offset])) {
++start_offset;
}
+ end_offset = start_offset + 1;
}
if (saved_line_break_type.has_value())
@@ -1186,7 +1407,7 @@ scoped_refptr<ShapeResult> NGLineBreaker::ShapeText(const NGInlineItem& item,
} else {
shape_result = items_data_.segments->ShapeText(
&shaper_, &item.Style()->GetFont(), item.Direction(), start, end,
- &item - items_data_.items.begin());
+ base::checked_cast<unsigned>(&item - items_data_.items.begin()));
}
if (UNLIKELY(spacing_.HasSpacing()))
shape_result->ApplySpacing(spacing_);
@@ -1268,6 +1489,7 @@ void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
state_ = LineBreakState::kDone;
return;
}
+ DCHECK(!is_text_combine_);
if (style.CollapseWhiteSpace() &&
!Character::IsOtherSpaceSeparator(text[offset_])) {
@@ -1344,9 +1566,7 @@ void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
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) {
+void NGLineBreaker::RewindTrailingOpenTags(NGLineInfo* line_info) {
// Remove trailing open tags. Open tags are included as trailable items
// because they are ambiguous. When the line ends, and if the end of line has
// open tags, they are not trailable.
@@ -1357,7 +1577,8 @@ void NGLineBreaker::RemoveTrailingCollapsibleSpace(NGLineInfo* line_info) {
for (const NGInlineItemResult& item_result : base::Reversed(item_results)) {
DCHECK(item_result.item);
if (item_result.item->Type() != NGInlineItem::kOpenTag) {
- unsigned end_index = &item_result - item_results.begin() + 1;
+ unsigned end_index =
+ base::checked_cast<unsigned>(&item_result - item_results.begin() + 1);
if (end_index < item_results.size()) {
const NGInlineItemResult& end_item_result = item_results[end_index];
unsigned end_item_index = end_item_result.item_index;
@@ -1371,6 +1592,15 @@ void NGLineBreaker::RemoveTrailingCollapsibleSpace(NGLineInfo* line_info) {
break;
}
}
+}
+
+// Remove trailing collapsible spaces in |line_info|.
+// https://drafts.csswg.org/css-text-3/#white-space-phase-2
+void NGLineBreaker::RemoveTrailingCollapsibleSpace(NGLineInfo* line_info) {
+ // Rewind trailing open-tags to wrap before them, except when this line ends
+ // with a forced break, including the one implied by block-in-inline.
+ if (!is_after_forced_break_)
+ RewindTrailingOpenTags(line_info);
ComputeTrailingCollapsibleSpace(line_info);
if (!trailing_collapsible_space_.has_value()) {
@@ -1426,9 +1656,7 @@ void NGLineBreaker::ComputeTrailingCollapsibleSpace(NGLineInfo* line_info) {
trailing_whitespace_ = WhitespaceState::kNone;
const String& text = Text();
- NGInlineItemResults* item_results = line_info->MutableResults();
- for (auto it = item_results->rbegin(); it != item_results->rend(); ++it) {
- NGInlineItemResult& item_result = *it;
+ for (auto& item_result : base::Reversed(*line_info->MutableResults())) {
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
if (item.EndCollapseType() == NGInlineItem::kOpaqueToCollapsing)
@@ -1475,22 +1703,21 @@ void NGLineBreaker::ComputeTrailingCollapsibleSpace(NGLineInfo* line_info) {
trailing_collapsible_space_.reset();
}
-// Measure control items; new lines and tab, that are similar to text, affect
-// layout, but do not need shaping/painting.
-void NGLineBreaker::HandleControlItem(const NGInlineItem& item,
- NGLineInfo* line_info) {
- DCHECK_GE(item.Length(), 1u);
- if (item.TextType() == NGTextType::kForcedLineBreak) {
- DCHECK_EQ(Text()[item.StartOffset()], kNewlineCharacter);
+// |item| is |nullptr| if this is an implicit forced break.
+void NGLineBreaker::HandleForcedLineBreak(const NGInlineItem* item,
+ NGLineInfo* line_info) {
+ // Check overflow, because the last item may have overflowed.
+ if (HandleOverflowIfNeeded(line_info))
+ return;
- // Check overflow, because the last item may have overflowed.
- if (HandleOverflowIfNeeded(line_info))
- return;
+ if (item) {
+ DCHECK_EQ(item->TextType(), NGTextType::kForcedLineBreak);
+ DCHECK_EQ(Text()[item->StartOffset()], kNewlineCharacter);
- NGInlineItemResult* item_result = AddItem(item, line_info);
+ NGInlineItemResult* item_result = AddItem(*item, line_info);
item_result->should_create_line_box = true;
item_result->has_only_trailing_spaces = true;
- MoveToNextOf(item);
+ MoveToNextOf(*item);
// Include following close tags. The difference is visible when they have
// margin/border/padding.
@@ -1511,12 +1738,23 @@ void NGLineBreaker::HandleControlItem(const NGInlineItem& item,
}
break;
}
+ }
- if (UNLIKELY(HasHyphen()))
- position_ -= RemoveHyphen(line_info->MutableResults());
- is_after_forced_break_ = true;
- line_info->SetIsLastLine(true);
- state_ = LineBreakState::kDone;
+ if (UNLIKELY(HasHyphen()))
+ position_ -= RemoveHyphen(line_info->MutableResults());
+ is_after_forced_break_ = true;
+ line_info->SetHasForcedBreak();
+ line_info->SetIsLastLine(true);
+ state_ = LineBreakState::kDone;
+}
+
+// Measure control items; new lines and tab, that are similar to text, affect
+// layout, but do not need shaping/painting.
+void NGLineBreaker::HandleControlItem(const NGInlineItem& item,
+ NGLineInfo* line_info) {
+ DCHECK_GE(item.Length(), 1u);
+ if (item.TextType() == NGTextType::kForcedLineBreak) {
+ HandleForcedLineBreak(&item, line_info);
return;
}
@@ -1666,54 +1904,18 @@ void NGLineBreaker::HandleAtomicInline(
item_result->layout_result->PhysicalFragment())
.InlineSize();
item_result->inline_size += inline_margins;
- } else if (mode_ == NGLineBreakerMode::kMaxContent && max_size_cache_) {
- unsigned item_index = &item - Items().begin();
- item_result->inline_size = (*max_size_cache_)[item_index];
} else {
- DCHECK(mode_ == NGLineBreakerMode::kMinContent || !max_size_cache_);
- NGBlockNode child(To<LayoutBox>(item.GetLayoutObject()));
-
- NGMinMaxConstraintSpaceBuilder builder(constraint_space_, node_.Style(),
- child, /* is_new_fc */ true);
- builder.SetAvailableBlockSize(constraint_space_.AvailableSize().block_size);
- builder.SetPercentageResolutionBlockSize(
- constraint_space_.PercentageResolutionBlockSize());
- builder.SetReplacedPercentageResolutionBlockSize(
- constraint_space_.ReplacedPercentageResolutionBlockSize());
- const auto space = builder.ToConstraintSpace();
-
- MinMaxSizesResult result =
- ComputeMinAndMaxContentContribution(node_.Style(), child, space);
- if (mode_ == NGLineBreakerMode::kMinContent) {
- item_result->inline_size = result.sizes.min_size + inline_margins;
- if (depends_on_block_constraints_out_) {
- *depends_on_block_constraints_out_ |=
- result.depends_on_block_constraints;
- }
- if (max_size_cache_) {
- if (max_size_cache_->IsEmpty())
- max_size_cache_->resize(Items().size());
- unsigned item_index = &item - Items().begin();
- (*max_size_cache_)[item_index] = result.sizes.max_size + inline_margins;
- }
- } else {
- item_result->inline_size = result.sizes.max_size + inline_margins;
- }
+ DCHECK(mode_ == NGLineBreakerMode::kMaxContent ||
+ mode_ == NGLineBreakerMode::kMinContent);
+ ComputeMinMaxContentSizeForBlockChild(item, item_result);
}
item_result->should_create_line_box = true;
- // Atomic inlines have break opportunities before and after, even when the
- // adjacent character is U+00A0 NO-BREAK SPACE character, except when sticky
- // images quirk is applied.
- item_result->can_break_after =
- auto_wrap_ && !(sticky_images_quirk_ && item.IsImage());
+ item_result->can_break_after = CanBreakAfterAtomicInline(item);
position_ += item_result->inline_size;
if (item.IsRubyRun()) {
- // Overrides can_break_after.
- ComputeCanBreakAfter(item_result, auto_wrap_, break_iterator_);
-
NGAnnotationOverhang overhang = GetOverhang(*item_result);
if (overhang.end > LayoutUnit()) {
item_result->pending_end_overhang = overhang.end;
@@ -1732,6 +1934,100 @@ void NGLineBreaker::HandleAtomicInline(
MoveToNextOf(item);
}
+void NGLineBreaker::ComputeMinMaxContentSizeForBlockChild(
+ const NGInlineItem& item,
+ NGInlineItemResult* item_result) {
+ DCHECK(mode_ == NGLineBreakerMode::kMaxContent ||
+ mode_ == NGLineBreakerMode::kMinContent);
+ if (mode_ == NGLineBreakerMode::kMaxContent && max_size_cache_) {
+ const unsigned item_index =
+ base::checked_cast<unsigned>(&item - Items().begin());
+ item_result->inline_size = (*max_size_cache_)[item_index];
+ return;
+ }
+
+ DCHECK(mode_ == NGLineBreakerMode::kMinContent || !max_size_cache_);
+ NGBlockNode child(To<LayoutBox>(item.GetLayoutObject()));
+
+ NGMinMaxConstraintSpaceBuilder builder(constraint_space_, node_.Style(),
+ child, /* is_new_fc */ true);
+ builder.SetAvailableBlockSize(constraint_space_.AvailableSize().block_size);
+ builder.SetPercentageResolutionBlockSize(
+ constraint_space_.PercentageResolutionBlockSize());
+ builder.SetReplacedPercentageResolutionBlockSize(
+ constraint_space_.ReplacedPercentageResolutionBlockSize());
+ const auto space = builder.ToConstraintSpace();
+
+ const MinMaxSizesResult result =
+ ComputeMinAndMaxContentContribution(node_.Style(), child, space);
+ const LayoutUnit inline_margins = item_result->margins.InlineSum();
+ if (mode_ == NGLineBreakerMode::kMinContent) {
+ item_result->inline_size = result.sizes.min_size + inline_margins;
+ if (depends_on_block_constraints_out_)
+ *depends_on_block_constraints_out_ |= result.depends_on_block_constraints;
+ if (max_size_cache_) {
+ if (max_size_cache_->IsEmpty())
+ max_size_cache_->resize(Items().size());
+ const unsigned item_index =
+ base::checked_cast<unsigned>(&item - Items().begin());
+ (*max_size_cache_)[item_index] = result.sizes.max_size + inline_margins;
+ }
+ return;
+ }
+
+ DCHECK(mode_ == NGLineBreakerMode::kMaxContent && !max_size_cache_);
+ item_result->inline_size = result.sizes.max_size + inline_margins;
+}
+
+void NGLineBreaker::HandleBlockInInline(const NGInlineItem& item,
+ NGLineInfo* line_info) {
+ DCHECK_EQ(item.Type(), NGInlineItem::kBlockInInline);
+
+ if (!line_info->Results().IsEmpty()) {
+ // If there were any items, force a line break before this item.
+ HandleForcedLineBreak(nullptr, line_info);
+ return;
+ }
+
+ NGInlineItemResult* item_result = AddItem(item, line_info);
+ if (mode_ == NGLineBreakerMode::kContent) {
+ const NGBlockBreakToken* block_break_token =
+ break_token_ ? break_token_->BlockInInlineBreakToken() : nullptr;
+ scoped_refptr<const NGLayoutResult> layout_result =
+ NGBlockNode(To<LayoutBox>(item.GetLayoutObject()))
+ .Layout(constraint_space_, block_break_token);
+ if (layout_result->Status() != NGLayoutResult::kSuccess) {
+ line_info->SetAbortedLayoutResult(std::move(layout_result));
+ state_ = LineBreakState::kDone;
+ return;
+ }
+ const NGPhysicalFragment& fragment = layout_result->PhysicalFragment();
+ item_result->inline_size =
+ NGFragment(constraint_space_.GetWritingDirection(), fragment)
+ .InlineSize();
+
+ item_result->should_create_line_box = !layout_result->IsSelfCollapsing();
+ item_result->layout_result = std::move(layout_result);
+
+ DCHECK(!line_info->BlockInInlineBreakToken());
+ line_info->SetBlockInInlineBreakToken(
+ To<NGBlockBreakToken>(fragment.BreakToken()));
+ } else {
+ DCHECK(mode_ == NGLineBreakerMode::kMaxContent ||
+ mode_ == NGLineBreakerMode::kMinContent);
+ ComputeMinMaxContentSizeForBlockChild(item, item_result);
+ }
+
+ position_ += item_result->inline_size;
+ line_info->SetIsBlockInInline();
+ line_info->SetHasForcedBreak();
+ is_after_forced_break_ = true;
+ trailing_whitespace_ = WhitespaceState::kNone;
+ if (!line_info->BlockInInlineBreakToken())
+ MoveToNextOf(item);
+ state_ = LineBreakState::kDone;
+}
+
// Performs layout and positions a float.
//
// If there is a known available_width (e.g. something has resolved the
@@ -1907,7 +2203,8 @@ void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
NGInlineItemResult* item_result = AddItem(item, line_info);
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
- if (ComputeOpenTagResult(item, constraint_space_, item_result)) {
+ if (!is_svg_text_ &&
+ ComputeOpenTagResult(item, constraint_space_, item_result)) {
// Negative margins on open tags may bring the position back. Update
// |state_| if that happens.
if (UNLIKELY(item_result->inline_size < 0 &&
@@ -1955,7 +2252,7 @@ void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
NGInlineItemResult* item_result = AddItem(item, line_info);
item_result->has_edge = item.HasEndEdge();
- if (item_result->has_edge) {
+ if (item_result->has_edge && !is_svg_text_) {
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
item_result->inline_size = ComputeInlineEndSize(constraint_space_, &style);
@@ -1982,6 +2279,13 @@ void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
const NGInlineItemResults& item_results = line_info->Results();
if (item_results.size() >= 2) {
NGInlineItemResult* last = std::prev(item_result);
+ if (UNLIKELY(IsA<LayoutNGTextCombine>(last->item->GetLayoutObject()))) {
+ // |can_break_after| for close tag should be as same as text-combine box.
+ // See "text-combine-upright-break-inside-001a.html"
+ // e.g. A<tcy style="white-space: pre">x y</tcy>B
+ item_result->can_break_after = last->can_break_after;
+ return;
+ }
if (was_auto_wrap || last->can_break_after) {
item_result->can_break_after =
last->can_break_after ||
@@ -2197,7 +2501,7 @@ void NGLineBreaker::RewindOverflow(unsigned new_end, NGLineInfo* line_info) {
// controls are trailable.
DCHECK_NE(text[item_result.StartOffset()], kNewlineCharacter);
DCHECK(item.Style());
- EWhiteSpace white_space = item.Style()->WhiteSpace();
+ const EWhiteSpace white_space = item.Style()->WhiteSpace();
if (ComputedStyle::AutoWrap(white_space) &&
white_space != EWhiteSpace::kBreakSpaces)
continue;
@@ -2386,13 +2690,13 @@ void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
if (&style == current_style_.get()) {
#if DCHECK_IS_ON()
// Check that cache fields are already setup correctly.
- DCHECK_EQ(auto_wrap_, !is_svg_text_ && style.AutoWrap());
+ DCHECK_EQ(auto_wrap_, ShouldAutoWrap(style));
if (auto_wrap_) {
DCHECK_EQ(enable_soft_hyphen_, style.GetHyphens() != Hyphens::kNone);
DCHECK_EQ(break_iterator_.Locale(), style.LocaleForLineBreakIterator());
}
- ShapeResultSpacing<String> spacing(spacing_.Text());
- spacing.SetSpacing(style.GetFont());
+ ShapeResultSpacing<String> spacing(spacing_.Text(), is_svg_text_);
+ spacing.SetSpacing(style.GetFont().GetFontDescription());
DCHECK_EQ(spacing.LetterSpacing(), spacing_.LetterSpacing());
DCHECK_EQ(spacing.WordSpacing(), spacing_.WordSpacing());
#endif
@@ -2400,10 +2704,10 @@ void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
}
current_style_ = &style;
- // TODO(crbug.com/366553): SVG <text> should not be auto_wrap_ for now.
- auto_wrap_ = !is_svg_text_ && style.AutoWrap();
+ auto_wrap_ = ShouldAutoWrap(style);
if (auto_wrap_) {
+ DCHECK(!is_text_combine_);
LineBreakType line_break_type;
EWordBreak word_break = style.WordBreak();
switch (word_break) {
@@ -2442,7 +2746,7 @@ void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
break_iterator_.SetLocale(style.LocaleForLineBreakIterator());
}
- spacing_.SetSpacing(style.GetFont());
+ spacing_.SetSpacing(style.GetFont().GetFontDescription());
}
bool NGLineBreaker::IsPreviousItemOfType(NGInlineItem::NGInlineItemType type) {
@@ -2477,6 +2781,7 @@ scoped_refptr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken(
DCHECK_LE(item_index_, items.size());
if (item_index_ >= items.size())
return nullptr;
+ DCHECK_EQ(line_info.HasForcedBreak(), is_after_forced_break_);
return NGInlineBreakToken::Create(
node_, current_style_.get(), item_index_, offset_,
(is_after_forced_break_ ? NGInlineBreakToken::kIsForcedBreak : 0) |
@@ -2485,7 +2790,8 @@ scoped_refptr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken(
: 0) |
(cloned_box_decorations_count_
? NGInlineBreakToken::kHasClonedBoxDecorations
- : 0));
+ : 0),
+ line_info.BlockInInlineBreakToken());
}
void NGLineBreaker::PropagateBreakToken(
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 36f60e4f5bf..e17cbf04b61 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
@@ -22,6 +22,7 @@ class NGBlockBreakToken;
class NGInlineBreakToken;
class NGInlineItem;
class NGLineInfo;
+class ResolvedTextLayoutAttributesIterator;
// The line breaker needs to know which mode its in to properly handle floats.
enum class NGLineBreakerMode { kContent, kMinContent, kMaxContent };
@@ -107,6 +108,12 @@ class CORE_EXPORT NGLineBreaker {
void ComputeLineLocation(NGLineInfo*) const;
+ // Returns true if CSS property "white-space" specified in |style| allows
+ // wrap. Note: For "text-combine-upright:all", this function returns false
+ // event if "white-space" means wrap, because combined text should be laid
+ // out in one line.
+ bool ShouldAutoWrap(const ComputedStyle& style) const;
+
enum class LineBreakState {
// The line breaking is complete.
kDone,
@@ -125,9 +132,12 @@ class CORE_EXPORT NGLineBreaker {
};
void HandleText(const NGInlineItem& item, const ShapeResult&, NGLineInfo*);
- // Split |item| by glyphs, and add them to |line_info|.
+ // Split |item| into segments, and add them to |line_info|.
// This is for SVG <text>.
- void SplitTextByGlyphs(const NGInlineItem& item, NGLineInfo* line_info);
+ void SplitTextIntoSegements(const NGInlineItem& item, NGLineInfo* line_info);
+ // Returns true if we should split NGInlineItem before
+ // svg_addressable_offset_.
+ bool ShouldCreateNewSvgSegment() const;
enum BreakResult { kSuccess, kOverflow };
BreakResult BreakText(NGInlineItemResult*,
const NGInlineItem&,
@@ -158,13 +168,25 @@ class CORE_EXPORT NGLineBreaker {
void RemoveTrailingCollapsibleSpace(NGLineInfo*);
LayoutUnit TrailingCollapsibleSpaceWidth(NGLineInfo*);
void ComputeTrailingCollapsibleSpace(NGLineInfo*);
+ void RewindTrailingOpenTags(NGLineInfo*);
void HandleControlItem(const NGInlineItem&, NGLineInfo*);
+ void HandleForcedLineBreak(const NGInlineItem*, NGLineInfo*);
void HandleBidiControlItem(const NGInlineItem&, NGLineInfo*);
- void HandleAtomicInline(
- const NGInlineItem&,
- NGLineInfo*);
- bool ShouldForceCanBreakAfter(const NGInlineItemResult& item_result) const;
+ void HandleAtomicInline(const NGInlineItem&, NGLineInfo*);
+ void HandleBlockInInline(const NGInlineItem&, NGLineInfo*);
+ void ComputeMinMaxContentSizeForBlockChild(const NGInlineItem&,
+ NGInlineItemResult*);
+
+ bool CanBreakAfterAtomicInline(const NGInlineItem& item) const;
+ bool CanBreakAfter(const NGInlineItem& item) const;
+ // Returns true when text content at |offset| is
+ // kObjectReplacementCharacter (U+FFFC), or
+ // kNoBreakSpaceCharacter (U+00A0) if |sticky_images_quirk_|.
+ bool MayBeAtomicInline(wtf_size_t offset) const;
+ const NGInlineItem* TryGetAtomicInlineItemAfter(
+ const NGInlineItem& item) const;
+
void HandleFloat(const NGInlineItem&,
NGLineInfo*);
void HandleOutOfFlowPositioned(const NGInlineItem&, NGLineInfo*);
@@ -208,12 +230,10 @@ class CORE_EXPORT NGLineBreaker {
bool HasHyphen() const { return hyphen_index_.has_value(); }
LayoutUnit AddHyphen(NGInlineItemResults* item_results,
wtf_size_t index,
- NGInlineItemResult* item_result,
- const NGInlineItem& item);
+ NGInlineItemResult* item_result);
LayoutUnit AddHyphen(NGInlineItemResults* item_results, wtf_size_t index);
LayoutUnit AddHyphen(NGInlineItemResults* item_results,
- NGInlineItemResult* item_result,
- const NGInlineItem& item);
+ NGInlineItemResult* item_result);
LayoutUnit RemoveHyphen(NGInlineItemResults* item_results);
void RestoreLastHyphen(NGInlineItemResults* item_results);
void FinalizeHyphen(NGInlineItemResults* item_results);
@@ -222,6 +242,7 @@ class CORE_EXPORT NGLineBreaker {
LineBreakState state_;
unsigned item_index_ = 0;
unsigned offset_ = 0;
+ unsigned svg_addressable_offset_ = 0;
// |WhitespaceState| of the current end. When a line is broken, this indicates
// the state of trailing whitespaces.
@@ -240,6 +261,9 @@ class CORE_EXPORT NGLineBreaker {
// True if node_ is an SVG <text>.
const bool is_svg_text_;
+ // True if node_ is LayoutNGTextCombine.
+ const bool is_text_combine_;
+
// 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;
@@ -336,6 +360,9 @@ class CORE_EXPORT NGLineBreaker {
wtf_size_t to_index;
};
absl::optional<RewindIndex> last_rewind_;
+
+ // This has a valid object if is_svg_text_.
+ std::unique_ptr<ResolvedTextLayoutAttributesIterator> svg_resolved_iterator_;
};
} // 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 67d120d4d2c..b82d3f5036f 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
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.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/testing/mock_hyphenation.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -164,6 +165,91 @@ TEST_F(NGLineBreakerTest, SingleNode) {
EXPECT_EQ("789", lines[2].first);
}
+// For "text-combine-upright-break-inside-001a.html"
+TEST_F(NGLineBreakerTest, TextCombineCloseTag) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "#container {"
+ " font: 10px/2 Ahem;"
+ " writing-mode: vertical-lr;"
+ "}"
+ "tcy { text-combine-upright: all }");
+ NGInlineNode node = CreateInlineNode(
+ "<div id=container>"
+ "abc<tcy style='white-space:pre'>XYZ</tcy>def");
+
+ Vector<std::pair<String, unsigned>> lines;
+ lines = BreakLines(node, LayoutUnit(30));
+ EXPECT_EQ(1u, lines.size());
+ // |NGLineBreaker::auto_wrap_| doesn't care about CSS "white-space" property
+ // in the element with "text-combine-upright:all".
+ // NGInlineItemResult
+ // [0] kText 0-3 can_break_after_=false
+ // [1] kOpenTag 3-3 can_break_after_=false
+ // [2] kStartTag 3-3 can_break_after _= fasle
+ // [3] kAtomicInline 3-4 can_break_after _= false
+ // [4] kCloseTag 4-4 can_break_after _= false
+ EXPECT_EQ(String(u"abc\uFFFCdef"), lines[0].first);
+}
+
+TEST_F(NGLineBreakerTest, TextCombineBreak) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "#container {"
+ " font: 10px/2 Ahem;"
+ " writing-mode: vertical-lr;"
+ "}"
+ "tcy { text-combine-upright: all }");
+ NGInlineNode node = CreateInlineNode("<div id=container>abc<tcy>-</tcy>def");
+
+ Vector<std::pair<String, unsigned>> lines;
+ lines = BreakLines(node, LayoutUnit(30));
+ EXPECT_EQ(2u, lines.size());
+ // NGLineBreaker attempts to break line for "abc-def".
+ EXPECT_EQ(String(u"abc\uFFFC"), lines[0].first);
+ EXPECT_EQ(String(u"def"), lines[1].first);
+}
+
+TEST_F(NGLineBreakerTest, TextCombineNoBreak) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "#container {"
+ " font: 10px/2 Ahem;"
+ " writing-mode: vertical-lr;"
+ "}"
+ "tcy { text-combine-upright: all }");
+ NGInlineNode node =
+ CreateInlineNode("<div id=container>abc<tcy>XYZ</tcy>def");
+
+ Vector<std::pair<String, unsigned>> lines;
+ lines = BreakLines(node, LayoutUnit(30));
+ EXPECT_EQ(1u, lines.size());
+ // NGLineBreaker attempts to break line for "abcXYZdef".
+ EXPECT_EQ(String(u"abc\uFFFCdef"), lines[0].first);
+}
+
+TEST_F(NGLineBreakerTest, TextCombineNoBreakWithSpace) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ LoadAhem();
+ InsertStyleElement(
+ "#container {"
+ " font: 10px/2 Ahem;"
+ " writing-mode: vertical-lr;"
+ "}"
+ "tcy { text-combine-upright: all }");
+ NGInlineNode node =
+ CreateInlineNode("<div id=container>abc<tcy>X Z</tcy>def");
+
+ Vector<std::pair<String, unsigned>> lines;
+ lines = BreakLines(node, LayoutUnit(30));
+ EXPECT_EQ(1u, lines.size());
+ // NGLineBreaker checks whether can break after "Z" in "abcX Zdef".
+ EXPECT_EQ(String(u"abc\uFFFCdef"), lines[0].first);
+}
+
TEST_F(NGLineBreakerTest, OverflowWord) {
LoadAhem();
NGInlineNode node = CreateInlineNode(R"HTML(
@@ -587,6 +673,61 @@ TEST_F(NGLineBreakerTest, MinMaxWithTrailingSpaces) {
EXPECT_EQ(sizes.max_size, LayoutUnit(110));
}
+TEST_F(NGLineBreakerTest, MinMaxWithSoftHyphen) {
+ LoadAhem();
+ NGInlineNode node = CreateInlineNode(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ font: 10px/1 Ahem;
+ }
+ </style>
+ <div id=container>abcd&shy;ef xx</div>
+ )HTML");
+
+ const auto sizes = ComputeMinMaxSizes(node);
+ EXPECT_EQ(sizes.min_size, LayoutUnit(50));
+ EXPECT_EQ(sizes.max_size, LayoutUnit(90));
+}
+
+TEST_F(NGLineBreakerTest, MinMaxWithHyphensDisabled) {
+ LoadAhem();
+ NGInlineNode node = CreateInlineNode(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ font: 10px/1 Ahem;
+ hyphens: none;
+ }
+ </style>
+ <div id=container>abcd&shy;ef xx</div>
+ )HTML");
+
+ const auto sizes = ComputeMinMaxSizes(node);
+ EXPECT_EQ(sizes.min_size, LayoutUnit(60));
+ EXPECT_EQ(sizes.max_size, LayoutUnit(90));
+}
+
+TEST_F(NGLineBreakerTest, MinMaxWithHyphensAuto) {
+ LoadAhem();
+ LayoutLocale::SetHyphenationForTesting("en-us", MockHyphenation::Create());
+ NGInlineNode node = CreateInlineNode(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ font: 10px/1 Ahem;
+ hyphens: auto;
+ }
+ </style>
+ <div id=container lang="en-us">zz hyphenation xx</div>
+ )HTML");
+
+ const auto sizes = ComputeMinMaxSizes(node);
+ EXPECT_EQ(sizes.min_size, LayoutUnit(50));
+ EXPECT_EQ(sizes.max_size, LayoutUnit(170));
+ LayoutLocale::SetHyphenationForTesting("en-us", nullptr);
+}
+
// For http://crbug.com/1104534
TEST_F(NGLineBreakerTest, SplitTextZero) {
// Note: |V8TestingScope| is needed for |Text::splitText()|.
@@ -713,13 +854,13 @@ B AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// This test passes if no CHECK failures.
}
-TEST_F(NGLineBreakerTest, SplitTextByGlyphs) {
+TEST_F(NGLineBreakerTest, SplitTextIntoSegements) {
RuntimeEnabledFeaturesTestHelpers::ScopedSVGTextNG svg_text_ng(true);
NGInlineNode node = CreateInlineNode(
uR"HTML(
<!DOCTYPE html>
<svg viewBox="0 0 800 600">
- <text id="container" style="font-family:Times">AV)HTML"
+ <text id="container" rotate="1" style="font-family:Times">AV)HTML"
u"\U0001F197\u05E2\u05B4\u05D1\u05E8\u05B4\u05D9\u05EA</text></svg>)");
BreakLines(
node, LayoutUnit::Max(),
@@ -740,5 +881,25 @@ TEST_F(NGLineBreakerTest, SplitTextByGlyphs) {
});
}
+// crbug.com/1214232
+TEST_F(NGLineBreakerTest, GetOverhangCrash) {
+ NGInlineNode node = CreateInlineNode(
+ R"HTML(
+<!DOCTYPE html>
+<style>
+* { margin-inline-end: -7%; }
+rb { float: right; }
+rt { margin: 17179869191em; }
+</style>
+<div id="container">
+<ruby>
+<rb>
+C c
+<rt>
+)HTML");
+ // The test passes if we have no DCHECK failures in BreakLines().
+ BreakLines(node, LayoutUnit::Max());
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc
index 9bcfaa55124..869ea645c3e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h"
+#include "base/containers/adapters.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
@@ -87,9 +89,7 @@ bool NGLineInfo::ComputeNeedsAccurateEndPosition() const {
}
unsigned NGLineInfo::InflowEndOffset() const {
- const NGInlineItemResults& item_results = Results();
- for (auto it = item_results.rbegin(); it != item_results.rend(); ++it) {
- const NGInlineItemResult& item_result = *it;
+ for (const auto& item_result : base::Reversed(Results())) {
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
if (item.Type() == NGInlineItem::kText ||
@@ -140,10 +140,8 @@ LayoutUnit NGLineInfo::ComputeTrailingSpaceWidth(
return LayoutUnit();
}
- const NGInlineItemResults& item_results = Results();
LayoutUnit trailing_spaces_width;
- for (auto it = item_results.rbegin(); it != item_results.rend(); ++it) {
- const NGInlineItemResult& item_result = *it;
+ for (const auto& item_result : base::Reversed(Results())) {
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h
index 563767d3d7d..c1ea06fb35e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h
@@ -8,6 +8,8 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/style/computed_style_base_constants.h"
namespace blink {
@@ -51,12 +53,28 @@ class CORE_EXPORT NGLineInfo {
bool IsLastLine() const { return is_last_line_; }
void SetIsLastLine(bool is_last_line) { is_last_line_ = is_last_line; }
+ // Whether this line has ended with a forced break or not. Note, the forced
+ // break item may not be the last item if trailing items are included, or even
+ // does not exist if synthesized for block-in-inline.
+ bool HasForcedBreak() const { return has_forced_break_; }
+ void SetHasForcedBreak() { has_forced_break_ = true; }
+
// 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; }
+ // Returns true if this line is a block-in-inline.
+ bool IsBlockInInline() const { return is_block_in_inline_; }
+ void SetIsBlockInInline() { is_block_in_inline_ = true; }
+ const NGBlockBreakToken* BlockInInlineBreakToken() const {
+ return block_in_inline_break_token_.get();
+ }
+ void SetBlockInInlineBreakToken(const NGBlockBreakToken* break_token) {
+ block_in_inline_break_token_ = break_token;
+ }
+
// NGInlineItemResults for this line.
NGInlineItemResults* MutableResults() { return &results_; }
const NGInlineItemResults& Results() const { return results_; }
@@ -131,6 +149,20 @@ class CORE_EXPORT NGLineInfo {
// justify alignment.
bool NeedsAccurateEndPosition() const { return needs_accurate_end_position_; }
+ // Line breaker may abort if block-in-inline aborts the layout.
+ const NGLayoutResult* AbortedLayoutResult() const {
+ return aborted_layout_result_.get();
+ }
+ void SetAbortedLayoutResult(
+ scoped_refptr<const NGLayoutResult> layout_result) {
+ aborted_layout_result_ = std::move(layout_result);
+ }
+
+ // |MayHaveTextCombineItem()| is used for treating text-combine box as
+ // ideographic character during "text-align:justify".
+ bool MayHaveTextCombineItem() const { return may_have_text_combine_item_; }
+ void SetHaveTextCombineItem() { may_have_text_combine_item_ = true; }
+
private:
ETextAlign GetTextAlign(bool is_last_line = false) const;
bool ComputeNeedsAccurateEndPosition() const;
@@ -145,6 +177,9 @@ class CORE_EXPORT NGLineInfo {
NGBfcOffset bfc_offset_;
+ scoped_refptr<const NGBlockBreakToken> block_in_inline_break_token_;
+ scoped_refptr<const NGLayoutResult> aborted_layout_result_;
+
LayoutUnit available_width_;
LayoutUnit width_;
LayoutUnit hang_width_;
@@ -159,12 +194,20 @@ class CORE_EXPORT NGLineInfo {
bool use_first_line_style_ = false;
bool is_last_line_ = false;
+ bool has_forced_break_ = false;
bool is_empty_line_ = false;
+ bool is_block_in_inline_ = false;
bool has_overflow_ = false;
bool has_trailing_spaces_ = false;
bool needs_accurate_end_position_ = false;
bool is_ruby_base_ = false;
bool is_ruby_text_ = false;
+ // Even if text combine item causes line break, this variable is not reset.
+ // This variable is used to add spacing before/after text combine items if
+ // "text-align: justify".
+ // Note: To avoid scanning |NGInlineItemResults|, this variable is true
+ // when |NGInlineItemResult| to |results_|.
+ bool may_have_text_combine_item_ = false;
};
std::ostream& operator<<(std::ostream& ostream, const NGLineInfo& line_info);
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 e007e7522aa..29e77ae5876 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.h"
+#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.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_line_info.h"
@@ -50,7 +51,7 @@ void NGLineTruncator::SetupEllipsis() {
ellipsis_text_ =
ellipsis_font_data_ && ellipsis_font_data_->GlyphForCharacter(
kHorizontalEllipsisCharacter)
- ? String(&kHorizontalEllipsisCharacter, 1)
+ ? String(&kHorizontalEllipsisCharacter, 1u)
: String(u"...");
HarfBuzzShaper shaper(ellipsis_text_);
ellipsis_shape_result_ =
@@ -138,8 +139,7 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width,
absl::optional<NGLogicalLineItem> truncated_child;
if (IsLtr(line_direction_)) {
NGLogicalLineItem* first_child = line_box->FirstInFlowChild();
- for (auto it = line_box->rbegin(); it != line_box->rend(); it++) {
- auto& child = *it;
+ for (auto& child : base::Reversed(*line_box)) {
if (EllipsizeChild(line_width, ellipsis_width_, &child == first_child,
&child, &truncated_child)) {
ellipsized_child = &child;
@@ -165,7 +165,8 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width,
if (truncated_child) {
// In order to preserve layout information before truncated, hide the
// original fragment and insert a truncated one.
- size_t child_index_to_truncate = ellipsized_child - line_box->begin();
+ unsigned child_index_to_truncate =
+ base::checked_cast<unsigned>(ellipsized_child - line_box->begin());
line_box->InsertChild(child_index_to_truncate + 1,
std::move(*truncated_child));
box_states->ChildInserted(child_index_to_truncate + 1);
@@ -410,7 +411,12 @@ void NGLineTruncator::HideChild(NGLogicalLineItem* child) {
if (fragment.HasOutOfFlowPositionedDescendants())
return;
- child->layout_result = fragment.CloneAsHiddenForPaint();
+ // Truncate this object. Atomic inline is monolithic.
+ DCHECK(fragment.IsMonolithic());
+ LayoutObject* layout_object = fragment.GetMutableLayoutObject();
+ DCHECK(layout_object);
+ DCHECK(layout_object->IsAtomicInlineLevel());
+ layout_object->SetIsTruncated(true);
return;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc
index dcd82490e62..c1c0546bed8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h"
+#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
namespace blink {
@@ -63,8 +64,7 @@ NGLogicalLineItem* NGLogicalLineItems::FirstInFlowChild() {
}
NGLogicalLineItem* NGLogicalLineItems::LastInFlowChild() {
- for (auto it = rbegin(); it != rend(); it++) {
- auto& child = *it;
+ for (auto& child : base::Reversed(*this)) {
if (child.HasInFlowFragment())
return &child;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
index 3c0b9008c5b..ceeb61d4896 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
@@ -286,7 +286,9 @@ const NGOffsetMappingUnit* NGOffsetMapping::GetMappingUnitForPosition(
const unsigned offset = node_and_offset.second;
unsigned range_start;
unsigned range_end;
- std::tie(range_start, range_end) = ranges_.at(&node);
+ auto it = ranges_.find(&node);
+ std::tie(range_start, range_end) =
+ it != ranges_.end() ? it->value : std::pair<unsigned, unsigned>(0, 0);
if (range_start == range_end || units_[range_start].DOMStart() > offset)
return nullptr;
// Find the last unit where unit.dom_start <= offset
@@ -311,7 +313,9 @@ NGOffsetMapping::UnitVector NGOffsetMapping::GetMappingUnitsForDOMRange(
const unsigned end_offset = ToNodeOffsetPair(range.EndPosition()).second;
unsigned range_start;
unsigned range_end;
- std::tie(range_start, range_end) = ranges_.at(&node);
+ auto it = ranges_.find(&node);
+ std::tie(range_start, range_end) =
+ it != ranges_.end() ? it->value : std::pair<unsigned, unsigned>(0, 0);
if (range_start == range_end || units_[range_start].DOMStart() > end_offset ||
units_[range_end - 1].DOMEnd() < start_offset)
@@ -332,7 +336,7 @@ NGOffsetMapping::UnitVector NGOffsetMapping::GetMappingUnitsForDOMRange(
});
UnitVector result;
- result.ReserveCapacity(result_end - result_begin);
+ result.ReserveCapacity(static_cast<unsigned>(result_end - result_begin));
for (const auto& unit : base::make_span(result_begin, result_end)) {
// If the unit isn't fully within the range, create a new unit that's
// within the range.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc
index 5482cc8801e..89377f96dae 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc
@@ -160,10 +160,11 @@ void NGOffsetMappingBuilder::CollapseTrailingSpace(unsigned space_offset) {
}
// TODO(xiaochengh): Optimize if this becomes performance bottleneck.
- unsigned position = std::distance(mapping_units_.begin(), container_unit);
+ wtf_size_t position = base::checked_cast<wtf_size_t>(
+ std::distance(mapping_units_.begin(), container_unit));
mapping_units_.EraseAt(position);
mapping_units_.InsertVector(position, new_units);
- unsigned new_unit_end = position + new_units.size();
+ wtf_size_t new_unit_end = position + new_units.size();
while (new_unit_end && new_unit_end < mapping_units_.size() &&
mapping_units_[new_unit_end - 1].Concatenate(
mapping_units_[new_unit_end])) {
@@ -201,7 +202,8 @@ void NGOffsetMappingBuilder::RestoreTrailingCollapsibleSpace(
return;
// When we collapsed multiple spaces, e.g. <b> </b>.
mapping_units_.insert(
- std::distance(mapping_units_.begin(), &unit) + 1,
+ base::checked_cast<wtf_size_t>(
+ std::distance(mapping_units_.begin(), &unit) + 1),
NGOffsetMappingUnit(NGOffsetMappingUnitType::kCollapsed, layout_text,
unit.dom_end_, original_dom_end,
unit.text_content_end_, unit.text_content_end_));
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
index 7f49c910916..7a9402ef632 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
@@ -140,7 +140,7 @@ class NGOffsetMappingTest : public NGLayoutTest {
}
Vector<NGOffsetMappingUnit> GetFirstLast(const std::string& caret_text) {
- const auto offset = caret_text.find('|');
+ const unsigned offset = static_cast<unsigned>(caret_text.find('|'));
return {*GetOffsetMapping().GetFirstMappingUnit(offset),
*GetOffsetMapping().GetLastMappingUnit(offset)};
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
index 41e0187a92b..423af5cb64a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
@@ -104,9 +104,7 @@ NGAnnotationOverhang GetOverhang(const NGInlineItemResult& item) {
return overhang;
const auto& run_fragment = item.layout_result->PhysicalFragment();
- LayoutUnit start_overhang = LayoutUnit::Max();
- LayoutUnit end_overhang = LayoutUnit::Max();
- bool found_line = false;
+
const ComputedStyle* ruby_text_style = nullptr;
for (const auto& child_link : run_fragment.PostLayoutChildren()) {
const NGPhysicalFragment& child_fragment = *child_link.get();
@@ -115,43 +113,50 @@ NGAnnotationOverhang GetOverhang(const NGInlineItemResult& item) {
continue;
if (layout_object->IsRubyText()) {
ruby_text_style = layout_object->Style();
- continue;
- }
- if (layout_object->IsRubyBase()) {
- const ComputedStyle& base_style = child_fragment.Style();
- const auto writing_direction = base_style.GetWritingDirection();
- const LayoutUnit base_inline_size =
- NGFragment(writing_direction, child_fragment).InlineSize();
- // RubyBase's inline_size is always same as RubyRun's inline_size.
- // Overhang values are offsets from RubyBase's inline edges to
- // the outmost text.
- for (const auto& base_child_link : child_fragment.PostLayoutChildren()) {
- const LayoutUnit line_inline_size =
- NGFragment(writing_direction, *base_child_link).InlineSize();
- if (line_inline_size == LayoutUnit())
- continue;
- found_line = true;
- const LayoutUnit start =
- base_child_link.offset
- .ConvertToLogical(writing_direction, child_fragment.Size(),
- base_child_link.get()->Size())
- .inline_offset;
- const LayoutUnit end = base_inline_size - start - line_inline_size;
- start_overhang = std::min(start_overhang, start);
- end_overhang = std::min(end_overhang, end);
- }
+ break;
}
}
-
- if (!found_line || !ruby_text_style)
+ if (!ruby_text_style)
return overhang;
- DCHECK_NE(start_overhang, LayoutUnit::Max());
- DCHECK_NE(end_overhang, LayoutUnit::Max());
+
// We allow overhang up to the half of ruby text font size.
const LayoutUnit half_width_of_ruby_font =
LayoutUnit(ruby_text_style->FontSize()) / 2;
- overhang.start = std::min(start_overhang, half_width_of_ruby_font);
- overhang.end = std::min(end_overhang, half_width_of_ruby_font);
+ LayoutUnit start_overhang = half_width_of_ruby_font;
+ LayoutUnit end_overhang = half_width_of_ruby_font;
+ bool found_line = false;
+ for (const auto& child_link : run_fragment.PostLayoutChildren()) {
+ const NGPhysicalFragment& child_fragment = *child_link.get();
+ const LayoutObject* layout_object = child_fragment.GetLayoutObject();
+ if (!layout_object->IsRubyBase())
+ continue;
+ const ComputedStyle& base_style = child_fragment.Style();
+ const auto writing_direction = base_style.GetWritingDirection();
+ const LayoutUnit base_inline_size =
+ NGFragment(writing_direction, child_fragment).InlineSize();
+ // RubyBase's inline_size is always same as RubyRun's inline_size.
+ // Overhang values are offsets from RubyBase's inline edges to
+ // the outmost text.
+ for (const auto& base_child_link : child_fragment.PostLayoutChildren()) {
+ const LayoutUnit line_inline_size =
+ NGFragment(writing_direction, *base_child_link).InlineSize();
+ if (line_inline_size == LayoutUnit())
+ continue;
+ found_line = true;
+ const LayoutUnit start =
+ base_child_link.offset
+ .ConvertToLogical(writing_direction, child_fragment.Size(),
+ base_child_link.get()->Size())
+ .inline_offset;
+ const LayoutUnit end = base_inline_size - start - line_inline_size;
+ start_overhang = std::min(start_overhang, start);
+ end_overhang = std::min(end_overhang, end);
+ }
+ }
+ if (!found_line)
+ return overhang;
+ overhang.start = start_overhang;
+ overhang.end = end_overhang;
return overhang;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
index 4eccb618af1..c05dcabc054 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
@@ -170,6 +170,17 @@ bool LayoutBoxUtils::SkipContainingBlockForPercentHeightCalculation(
return LayoutBox::SkipContainingBlockForPercentHeightCalculation(cb);
}
+LayoutUnit LayoutBoxUtils::InlineSize(const LayoutBox& box) {
+ DCHECK_GT(box.PhysicalFragmentCount(), 0u);
+
+ // TODO(almaher): We can't assume all fragments will have the same inline
+ // size.
+ return box.GetPhysicalFragment(0u)
+ ->Size()
+ .ConvertToLogical(box.StyleRef().GetWritingMode())
+ .inline_size;
+}
+
LayoutUnit LayoutBoxUtils::TotalBlockSize(const LayoutBox& box) {
wtf_size_t num_fragments = box.PhysicalFragmentCount();
DCHECK_GT(num_fragments, 0u);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.h
index 497beeea6dc..36f7a8a3185 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.h
@@ -39,6 +39,8 @@ class LayoutBoxUtils {
static bool SkipContainingBlockForPercentHeightCalculation(
const LayoutBlock* cb);
+ static LayoutUnit InlineSize(const LayoutBox& box);
+
// The total block size of all fragments.
static LayoutUnit TotalBlockSize(const LayoutBox& box);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block.h
new file mode 100644
index 00000000000..d954fe0c007
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block.h
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+
+namespace blink {
+
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlock>;
+
+using LayoutNGBlock = LayoutNGMixin<LayoutBlock>;
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_H_
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 37d93eb3505..9c5e14385b5 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
@@ -11,6 +11,11 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutBlockFlow>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGMixin<LayoutBlockFlow>;
+
// This overrides the default layout block algorithm to use Layout NG.
class CORE_EXPORT LayoutNGBlockFlow
: public LayoutNGBlockFlowMixin<LayoutBlockFlow> {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
index 89b8f520640..640d4a7fd00 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
@@ -17,6 +17,12 @@
#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/layout_box_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.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"
@@ -24,6 +30,9 @@
#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/layout/ng/svg/layout_ng_svg_text.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h
index b06834a90ae..e62f05bed23 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h
@@ -8,16 +8,9 @@
#include <type_traits>
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
-#include "third_party/blink/renderer/core/layout/layout_progress.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
-#include "third_party/blink/renderer/core/layout/svg/layout_svg_block.h"
namespace blink {
@@ -25,6 +18,22 @@ enum class NGBaselineAlgorithmType;
struct NGInlineNodeData;
// This mixin holds code shared between LayoutNG subclasses of LayoutBlockFlow.
+//
+// If you'd like to make a LayoutNGFoo class inheriting from
+// LayoutNGBlockFlowMixin<LayoutBar>, you need to do:
+// * Add the following to the header for LayoutNGFoo.
+// extern template class CORE_EXTERN_TEMPLATE_EXPORT
+// LayoutNGBlockFlowMixin<LayoutBar>;
+// extern template class CORE_EXTERN_TEMPLATE_EXPORT
+// LayoutNGMixin<LayoutBar>;
+// * Add |#include "header for LayoutNGFoo"| to layout_ng_block_flow_mixin.cc
+// and layout_ng_mixin.cc.
+// It's the header for LayoutNGFoo, not for LayoutBar. The purpose is to
+// include the above |extern template| declarations.
+// * Add |template class CORE_TEMPLATE_EXPORT
+// LayoutNGBlockFlowMixin<LayoutBar>;| to layout_ng_block_flow_mixin.cc.
+// * Add |template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBar>;| to
+// layout_ng_mixin.cc.
template <typename Base>
class LayoutNGBlockFlowMixin : public LayoutNGMixin<Base> {
public:
@@ -73,27 +82,6 @@ class LayoutNGBlockFlowMixin : public LayoutNGMixin<Base> {
void AddScrollingOverflowFromChildren();
};
-// If you edit these export templates, also update templates in
-// layout_ng_mixin.h.
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutBlockFlow>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutProgress>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutRubyAsBlock>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutRubyBase>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutRubyRun>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutRubyText>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutSVGBlock>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutTableCaption>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGBlockFlowMixin<LayoutTableCell>;
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_FLOW_MIXIN_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
index cf4cd3d83c4..c564536a860 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
@@ -14,9 +15,50 @@ LayoutNGFieldset::LayoutNGFieldset(Element* element)
SetChildrenInline(false);
}
+LayoutBlock* LayoutNGFieldset::FindAnonymousFieldsetContentBox() const {
+ LayoutObject* first_child = FirstChild();
+ if (!first_child)
+ return nullptr;
+ if (first_child->IsAnonymous())
+ return To<LayoutBlock>(first_child);
+ LayoutObject* last_child = first_child->NextSibling();
+ DCHECK(!last_child || !last_child->NextSibling());
+ if (last_child && last_child->IsAnonymous())
+ return To<LayoutBlock>(last_child);
+ return nullptr;
+}
+
void LayoutNGFieldset::AddChild(LayoutObject* new_child,
LayoutObject* before_child) {
- LayoutBlock* fieldset_content = To<LayoutBlock>(FirstChild());
+ if (!new_child->IsText()) {
+ // Adding a child LayoutObject always causes reattach of <fieldset>. So
+ // |before_child| is always nullptr.
+ // See HTMLFieldSetElement::DidRecalcStyle().
+ DCHECK(!before_child);
+ } else if (before_child && before_child->IsRenderedLegend()) {
+ // Whitespace changes resulting from removed nodes are handled in
+ // MarkForWhitespaceReattachment(), and don't trigger
+ // HTMLFieldSetElement::DidRecalcStyle(). So the fieldset is not
+ // reattached. We adjust |before_child| instead.
+ Node* before_node =
+ LayoutTreeBuilderTraversal::NextLayoutSibling(*before_child->GetNode());
+ before_child = before_node ? before_node->GetLayoutObject() : nullptr;
+ }
+
+ // https://html.spec.whatwg.org/C/#the-fieldset-and-legend-elements
+ // > * If the element has a rendered legend, then that element is expected
+ // > to be the first child box.
+ // > * The anonymous fieldset content box is expected to appear after the
+ // > rendered legend and is expected to contain the content (including
+ // > the '::before' and '::after' pseudo-elements) of the fieldset
+ // > element except for the rendered legend, if there is one.
+
+ if (new_child->IsRenderedLegendCandidate() &&
+ !LayoutFieldset::FindInFlowLegend(*this)) {
+ LayoutNGBlockFlow::AddChild(new_child, FirstChild());
+ return;
+ }
+ LayoutBlock* fieldset_content = FindAnonymousFieldsetContentBox();
if (!fieldset_content) {
// We wrap everything inside an anonymous child, which will take care of the
// fieldset contents. This parent will only be responsible for the fieldset
@@ -76,7 +118,7 @@ void LayoutNGFieldset::UpdateAnonymousChildStyle(
child_style.SetPaddingBottom(StyleRef().PaddingBottom());
child_style.SetPaddingLeft(StyleRef().PaddingLeft());
- if (StyleRef().SpecifiesColumns()) {
+ if (StyleRef().SpecifiesColumns() && AllowsColumns()) {
child_style.SetColumnCount(StyleRef().ColumnCount());
child_style.SetColumnWidth(StyleRef().ColumnWidth());
} else {
@@ -100,12 +142,19 @@ void LayoutNGFieldset::UpdateAnonymousChildStyle(
child_style.SetGridColumnStart(StyleRef().GridColumnStart());
child_style.SetGridRowEnd(StyleRef().GridRowEnd());
child_style.SetGridRowStart(StyleRef().GridRowStart());
+
+ // grid-template-columns, grid-template-rows
child_style.SetGridTemplateColumns(StyleRef().GridTemplateColumns());
child_style.SetGridTemplateRows(StyleRef().GridTemplateRows());
child_style.SetNamedGridArea(StyleRef().NamedGridArea());
child_style.SetNamedGridAreaColumnCount(
StyleRef().NamedGridAreaColumnCount());
child_style.SetNamedGridAreaRowCount(StyleRef().NamedGridAreaRowCount());
+ child_style.SetImplicitNamedGridColumnLines(
+ StyleRef().ImplicitNamedGridColumnLines());
+ child_style.SetImplicitNamedGridRowLines(
+ StyleRef().ImplicitNamedGridRowLines());
+
child_style.SetRowGap(StyleRef().RowGap());
child_style.SetJustifyContent(StyleRef().JustifyContent());
@@ -171,16 +220,14 @@ bool LayoutNGFieldset::HitTestChildren(HitTestResult& result,
}
LayoutUnit LayoutNGFieldset::ScrollWidth() const {
- const LayoutObject* child = FirstChild();
- if (child && child->IsAnonymous())
- return To<LayoutBox>(child)->ScrollWidth();
+ if (const auto* content = FindAnonymousFieldsetContentBox())
+ return content->ScrollWidth();
return LayoutNGBlockFlow::ScrollWidth();
}
LayoutUnit LayoutNGFieldset::ScrollHeight() const {
- const LayoutObject* child = FirstChild();
- if (child && child->IsAnonymous())
- return To<LayoutBox>(child)->ScrollHeight();
+ if (const auto* content = FindAnonymousFieldsetContentBox())
+ return content->ScrollHeight();
return LayoutNGBlockFlow::ScrollHeight();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
index c5472ec5e46..2e187291cc9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
@@ -21,6 +21,8 @@ class CORE_EXPORT LayoutNGFieldset final : public LayoutNGBlockFlow {
bool CreatesNewFormattingContext() const final { return true; }
+ LayoutBlock* FindAnonymousFieldsetContentBox() const;
+
protected:
bool IsOfType(LayoutObjectType) const override;
void UpdateAnonymousChildStyle(const LayoutObject* child,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset_test.cc
new file mode 100644
index 00000000000..9120ed7d636
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset_test.cc
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h"
+
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
+
+namespace blink {
+
+class LayoutNGFieldsetTest : public NGLayoutTest {};
+
+TEST_F(LayoutNGFieldsetTest, AddChildWhitespaceCrash) {
+ SetBodyInnerHTML(R"HTML(
+<fieldset>
+<small>s</small>
+<!-- -->
+<legend></legend>
+</fieldset>)HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ Node* text = GetDocument().QuerySelector("small")->nextSibling();
+ ASSERT_TRUE(IsA<Text>(text));
+ text->remove();
+ UpdateAllLifecyclePhasesForTest();
+
+ // Passes if no crash in LayoutNGFieldset::AddChild().
+}
+
+} // namespace blink
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 ebd2c536d19..855b0b4b30c 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
@@ -9,6 +9,13 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/layout_box_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.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"
@@ -16,6 +23,9 @@
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -114,6 +124,9 @@ RecalcLayoutOverflowResult LayoutNGMixin<Base>::RecalcLayoutOverflow() {
// changed, or if we are marked as dirty.
if (should_recalculate_layout_overflow) {
const PhysicalRect old_layout_overflow = fragment.LayoutOverflow();
+#if DCHECK_IS_ON()
+ NGPhysicalBoxFragment::AllowPostLayoutScope allow_post_layout_scope;
+#endif
const PhysicalRect new_layout_overflow =
NGLayoutOverflowCalculator::RecalculateLayoutOverflowForFragment(
fragment);
@@ -152,12 +165,32 @@ RecalcLayoutOverflowResult LayoutNGMixin<Base>::RecalcLayoutOverflow() {
return {layout_overflow_changed, rebuild_fragment_tree};
}
+static void RecalcFragmentLayoutOverflow(RecalcLayoutOverflowResult& result,
+ const NGPhysicalFragment& fragment) {
+ for (const auto& child : fragment.PostLayoutChildren()) {
+ if (child->GetLayoutObject()) {
+ if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(child.get())) {
+ if (LayoutBox* owner_box = box->MutableOwnerLayoutBox())
+ result.Unite(owner_box->RecalcLayoutOverflow());
+ }
+ } else {
+ // We enter this branch when the |child| is a fragmentainer.
+ RecalcFragmentLayoutOverflow(result, *child.get());
+ }
+ }
+}
+
template <typename Base>
RecalcLayoutOverflowResult LayoutNGMixin<Base>::RecalcChildLayoutOverflow() {
DCHECK(RuntimeEnabledFeatures::LayoutNGLayoutOverflowRecalcEnabled());
DCHECK(Base::ChildNeedsLayoutOverflowRecalc());
Base::ClearChildNeedsLayoutOverflowRecalc();
+#if DCHECK_IS_ON()
+ // We use PostLayout methods to navigate the fragment tree and reach the
+ // corresponding LayoutObjects, so we need to use AllowPostLayoutScope here.
+ NGPhysicalBoxFragment::AllowPostLayoutScope allow_post_layout_scope;
+#endif
RecalcLayoutOverflowResult result;
for (auto& layout_result : Base::layout_results_) {
const auto& fragment =
@@ -174,12 +207,7 @@ RecalcLayoutOverflowResult LayoutNGMixin<Base>::RecalcChildLayoutOverflow() {
}
}
- for (const auto& child : fragment.PostLayoutChildren()) {
- if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(child.get())) {
- if (box->GetLayoutObject()->IsBox())
- result.Unite(box->MutableOwnerLayoutBox()->RecalcLayoutOverflow());
- }
- }
+ RecalcFragmentLayoutOverflow(result, fragment);
}
return result;
@@ -348,7 +376,8 @@ void LayoutNGMixin<Base>::UpdateOutOfFlowBlockLayout() {
// should get laid out by the actual containing block.
NGOutOfFlowLayoutPart(css_container->CanContainAbsolutePositionObjects(),
css_container->CanContainFixedPositionObjects(),
- *container_style, constraint_space, &container_builder,
+ css_container->IsLayoutGrid(), *container_style,
+ constraint_space, &container_builder,
initial_containing_block_fixed_size)
.Run(/* only_layout */ this);
scoped_refptr<const NGLayoutResult> result =
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 3d25be35ac9..5cf55f1c601 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
@@ -8,20 +8,23 @@
#include <type_traits>
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_progress.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/svg/layout_svg_block.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
namespace blink {
// This mixin holds code shared between LayoutNG subclasses of
// LayoutBlock.
+//
+// If you'd like to make a LayoutNGFoo class inheriting from
+// LayoutNGMixin<LayoutBar>, you need to do:
+// * Add the following to the header for LayoutNGFoo.
+// extern template class CORE_EXTERN_TEMPLATE_EXPORT
+// LayoutNGMixin<LayoutBar>;
+// * Add |#include "header for LayoutNGFoo"| to layout_ng_mixin.cc.
+// It's the header for LayoutNGFoo, not for LayoutBar. The purpose is to
+// include the above |extern template| declaration.
+// * Add |template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBar>;| to
+// layout_ng_mixin.cc.
template <typename Base>
class LayoutNGMixin : public Base {
public:
@@ -53,21 +56,6 @@ class LayoutNGMixin : public Base {
void UpdateMargins();
};
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlock>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGMixin<LayoutBlockFlow>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutProgress>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGMixin<LayoutRubyAsBlock>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyBase>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyRun>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyText>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutSVGBlock>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGMixin<LayoutTableCaption>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- LayoutNGMixin<LayoutTableCell>;
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_MIXIN_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h
index 86d6850fdd5..39d296786f2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h
@@ -11,6 +11,10 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutProgress>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutProgress>;
+
class CORE_EXPORT LayoutNGProgress
: public LayoutNGBlockFlowMixin<LayoutProgress> {
public:
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
index 7dff53b6eb7..1797f6d0002 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
@@ -11,6 +11,11 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyAsBlock>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGMixin<LayoutRubyAsBlock>;
+
// A NG version of LayoutRubyAsBlock.
// This adds anonymous block building to LayoutNGBlockFlow.
class CORE_EXPORT LayoutNGRubyAsBlock
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
index 8e0e73370cc..41e2f4efb70 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
@@ -11,6 +11,10 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyBase>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyBase>;
+
// A LayoutNG version of LayoutRubyBase.
class CORE_EXPORT LayoutNGRubyBase final
: public LayoutNGBlockFlowMixin<LayoutRubyBase> {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
index d5ff077683a..5dcb63646ba 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
@@ -11,6 +11,10 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyRun>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyRun>;
+
// A LayoutNG version of LayoutRubyRun.
class CORE_EXPORT LayoutNGRubyRun final
: public LayoutNGBlockFlowMixin<LayoutRubyRun> {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
index 51511b629b0..a51b923c024 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
@@ -11,6 +11,10 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyText>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyText>;
+
// A LayoutNG version of LayoutRubyText.
class CORE_EXPORT LayoutNGRubyText final
: public LayoutNGBlockFlowMixin<LayoutRubyText> {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.cc
index 8855fdfb2d4..b425de04782 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/layout/layout_text_control.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h b/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h
index 9b136feb6fd..e233b2ac37f 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
@@ -11,8 +11,7 @@
// container LayoutBlockFlow will consist of a LayoutFlowThread child, followed
// by zero or more siblings of type LayoutMultiColumnSet and/or
// LayoutMultiColumnSpannerPlaceholder. NG needs to skip these special
-// objects. The actual content is inside the flow thread. There are similar
-// complications for fieldset / legend.
+// objects. The actual content is inside the flow thread.
namespace blink {
@@ -25,13 +24,6 @@ inline LayoutObject* GetLayoutObjectForFirstChildNode(LayoutBlock* parent) {
return nullptr;
if (UNLIKELY(child->IsLayoutFlowThread()))
child = To<LayoutBlockFlow>(child)->FirstChild();
- // The rendered legend is a child of the anonymous wrapper, inside the
- // fieldset container. Or in the case of a multi-column, the rendered legend
- // is a child of the multi-column flow thread, inside the anonymous wrapper
- // and fieldset. If we find it, skip it. As far as NG is concerned, the
- // rendered legend is a child of the fieldset container.
- if (UNLIKELY(child && child->IsRenderedLegend()))
- return child->NextSibling();
return child;
}
@@ -53,32 +45,11 @@ inline Type GetLayoutObjectForParentNode(Type object) {
if (UNLIKELY(!parent))
return nullptr;
- // The parent of the rendered legend is the fieldset container, as far as NG
- // is concerned. Skip the anonymous wrapper in-between.
- if (UNLIKELY(object->IsRenderedLegend()))
- return parent->Parent();
-
if (UNLIKELY(parent->IsLayoutFlowThread()))
return parent->Parent();
return parent;
}
-// Return the layout object that should be the sibling NGLayoutInputNode of
-// |object|. Normally this will just be the next sibling layout object, but
-// there are certain layout objects that should be skipped for NG.
-inline LayoutObject* GetLayoutObjectForNextSiblingNode(LayoutObject* object) {
- // We don't expect to walk the layout tree starting at the rendered legend,
- // and we'll skip over it if we find it. The renderered legend will be handled
- // by a special algorithm, and should be invisible among siblings.
- DCHECK(!object->IsRenderedLegend());
- LayoutObject* next = object->NextSibling();
- if (!next)
- return nullptr;
- if (UNLIKELY(next->IsRenderedLegend()))
- return next->NextSibling();
- return next;
-}
-
// Return true if the NGLayoutInputNode children of the NGLayoutInputNode
// established by |block| will be inline; see LayoutObject::ChildrenInline().
inline bool AreNGBlockFlowChildrenInline(const LayoutBlock* block) {
@@ -105,6 +76,8 @@ inline bool IsLayoutNGContainingBlock(const LayoutBlock* containing_block) {
inline bool IsManagedByLayoutNG(const LayoutObject& object) {
if (!object.IsLayoutNGMixin())
return false;
+ if (object.IsOutOfFlowPositioned())
+ return true;
const auto* containing_block = object.ContainingBlock();
if (UNLIKELY(!containing_block))
return false;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
index 213d9ca11b7..a4d487dff01 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
namespace blink {
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 4a1a36d24ee..9b42dfe2b35 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
@@ -54,10 +54,8 @@ void LayoutNGListItem::StyleDidChange(StyleDifference diff,
list_marker->UpdateMarkerContentIfNeeded(*marker);
if (old_style) {
- const ListStyleTypeData* old_list_style_type =
- old_style->GetListStyleType();
- const ListStyleTypeData* new_list_style_type =
- StyleRef().GetListStyleType();
+ const ListStyleTypeData* old_list_style_type = old_style->ListStyleType();
+ const ListStyleTypeData* new_list_style_type = StyleRef().ListStyleType();
if (old_list_style_type != new_list_style_type &&
(!old_list_style_type || !new_list_style_type ||
*old_list_style_type != *new_list_style_type))
@@ -66,12 +64,8 @@ void LayoutNGListItem::StyleDidChange(StyleDifference diff,
}
void LayoutNGListItem::UpdateCounterStyle() {
- if (!RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled())
- return;
-
- if (!StyleRef().GetListStyleType() ||
- StyleRef().GetListStyleType()->IsCounterStyleReferenceValid(
- GetDocument())) {
+ if (!StyleRef().ListStyleType() ||
+ StyleRef().ListStyleType()->IsCounterStyleReferenceValid(GetDocument())) {
return;
}
@@ -136,6 +130,9 @@ const LayoutObject* LayoutNGListItem::FindSymbolMarkerLayoutText(
if (object->IsAnonymousBlock())
return FindSymbolMarkerLayoutText(GetLayoutObjectForParentNode(object));
+ if (object->IsLayoutNGTextCombine())
+ return FindSymbolMarkerLayoutText(object->Parent());
+
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item_test.cc
index a6eec169c2b..386b3ef0977 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
namespace blink {
@@ -13,6 +14,27 @@ class LayoutNGListItemTest : public NGLayoutTest {};
namespace {
+// http://crbug.com/1222633
+TEST_F(LayoutNGListItemTest, FindSymbolMarkerLayoutTextWithTextCombine) {
+ ScopedLayoutNGTextCombineForTest enable_layout_ng_text_combine(true);
+ InsertStyleElement(
+ "li { text-combine-upright: all; writing-mode: vertical-rl; }");
+ SetBodyInnerHTML("<li id=target>a</li>");
+ // LayoutNGListItem {LI}
+ // LayoutNGOutsideListMarker {::marker}
+ // LayoutNGTextCombine (anonymous)
+ // LayoutText (anonymous) "\x{2022} "
+ // LayoutNGTextCombine (anonymous)
+ // LayoutText {#text} "a"
+ const auto& target = *GetElementById("target");
+ const auto* const marker_layout_text =
+ LayoutNGListItem::FindSymbolMarkerLayoutText(target.GetLayoutObject());
+ const auto* const text_combine =
+ To<LayoutNGTextCombine>(marker_layout_text->Parent());
+ EXPECT_EQ(marker_layout_text,
+ LayoutNGListItem::FindSymbolMarkerLayoutText(text_combine));
+}
+
TEST_F(LayoutNGListItemTest, InsideWithFirstLine) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
index f3e9a06b564..928116f7982 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
+#include "third_party/blink/renderer/core/html/html_ulist_element.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
namespace blink {
@@ -33,8 +35,11 @@ bool LayoutNGOutsideListMarker::NeedsOccupyWholeLine() const {
if (!GetDocument().InQuirksMode())
return false;
+ // Apply the quirks when the next sibling is a block-level `<ul>` or `<ol>`.
LayoutObject* next_sibling = NextSibling();
- if (next_sibling && next_sibling->GetNode() &&
+ if (next_sibling && !next_sibling->IsInline() &&
+ !next_sibling->IsFloatingOrOutOfFlowPositioned() &&
+ next_sibling->GetNode() &&
(IsA<HTMLUListElement>(*next_sibling->GetNode()) ||
IsA<HTMLOListElement>(*next_sibling->GetNode())))
return true;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h
index 1de233b6d28..3c49cad506b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h
@@ -12,6 +12,11 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutBlockFlow>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGMixin<LayoutBlockFlow>;
+
// A LayoutObject subclass for outside-positioned list markers in LayoutNG.
class CORE_EXPORT LayoutNGOutsideListMarker final
: public LayoutNGBlockFlowMixin<LayoutBlockFlow> {
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 30bf763aefb..805de380122 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/dcheck_is_on.h"
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.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"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
index f5a03156bf9..d2cde006eae 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
@@ -5,11 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_BLOCK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_BLOCK_H_
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
namespace blink {
-class LayoutNGMathMLBlock : public LayoutNGMixin<LayoutBlock> {
+class LayoutNGMathMLBlock : public LayoutNGBlock {
public:
explicit LayoutNGMathMLBlock(Element*);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc
index abd787e5582..8f2cd11fcdc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+
namespace blink {
LayoutNGMathMLBlockWithAnonymousMrow::LayoutNGMathMLBlockWithAnonymousMrow(
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
index a9cc7817466..74134a6533d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
@@ -17,7 +17,7 @@ namespace {
// Describes the amount to shift the numerator/denominator of the fraction when
// a fraction bar is present. Data is populated from the OpenType MATH table.
// If the OpenType MATH table is not present fallback values are used.
-// https://mathml-refresh.github.io/mathml-core/#fraction-with-nonzero-line-thickness
+// https://w3c.github.io/mathml-core/#fraction-with-nonzero-line-thickness
struct FractionParameters {
LayoutUnit numerator_gap_min;
LayoutUnit denominator_gap_min;
@@ -72,7 +72,7 @@ FractionParameters GetFractionParameters(const ComputedStyle& style) {
// Describes the amount to shift the numerator/denominator of the fraction when
// a fraction bar is not present. Data is populated from the OpenType MATH
// table. If the OpenType MATH table is not present fallback values are used.
-// https://mathml-refresh.github.io/mathml-core/#fraction-with-zero-line-thickness
+// https://w3c.github.io/mathml-core/#fraction-with-zero-line-thickness
struct FractionStackParameters {
LayoutUnit gap_min;
LayoutUnit top_shift_up;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
index fef9f024f62..3bbd3b9e27c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
@@ -20,7 +20,11 @@ NGConstraintSpace CreateConstraintSpaceForMathChild(
const NGBlockNode& parent_node,
const LogicalSize& child_available_size,
const NGConstraintSpace& parent_space,
- const NGLayoutInputNode& child) {
+ const NGLayoutInputNode& child,
+ NGCacheSlot cache_slot,
+ const absl::optional<NGConstraintSpace::MathTargetStretchBlockSizes>
+ target_stretch_block_sizes,
+ const absl::optional<LayoutUnit> target_stretch_inline_size) {
const ComputedStyle& parent_style = parent_node.Style();
const ComputedStyle& child_style = child.Style();
DCHECK(child.CreatesNewFormattingContext());
@@ -29,8 +33,12 @@ NGConstraintSpace CreateConstraintSpaceForMathChild(
SetOrthogonalFallbackInlineSizeIfNeeded(parent_style, child, &builder);
builder.SetAvailableSize(child_available_size);
builder.SetPercentageResolutionSize(child_available_size);
+ builder.SetCacheSlot(cache_slot);
+ if (target_stretch_block_sizes)
+ builder.SetTargetStretchBlockSizes(*target_stretch_block_sizes);
+ if (target_stretch_inline_size)
+ builder.SetTargetStretchInlineSize(*target_stretch_inline_size);
- // TODO(crbug.com/1124301): add target stretch sizes.
// TODO(crbug.com/1125137): add ink metrics.
return builder.ToConstraintSpace();
}
@@ -90,7 +98,7 @@ static bool IsPrescriptDelimiter(const NGBlockNode& block_node) {
}
// Valid according to:
-// https://mathml-refresh.github.io/mathml-core/#prescripts-and-tensor-indices-mmultiscripts
+// https://w3c.github.io/mathml-core/#prescripts-and-tensor-indices-mmultiscripts
inline bool IsValidMultiscript(const NGBlockNode& node) {
auto child = To<NGBlockNode>(FirstChildInFlow(node));
if (!child || IsPrescriptDelimiter(child))
@@ -185,7 +193,7 @@ RadicalVerticalParameters GetRadicalVerticalParameters(
MinMaxSizes GetMinMaxSizesForVerticalStretchyOperator(
const ComputedStyle& style,
UChar character) {
- // https://mathml-refresh.github.io/mathml-core/#dfn-preferred-inline-size-of-a-glyph-stretched-along-the-block-axis
+ // https://w3c.github.io/mathml-core/#dfn-preferred-inline-size-of-a-glyph-stretched-along-the-block-axis
const SimpleFontData* font_data = style.GetFont().PrimaryFont();
MinMaxSizes sizes;
if (!font_data)
@@ -218,20 +226,15 @@ bool IsUnderOverLaidOutAsSubSup(const NGBlockNode& node) {
return false;
if (!node.IsBlock() || !node.IsMathML())
return false;
- auto base = To<NGBlockNode>(FirstChildInFlow(node));
- // TODO(crbug.com/1124298)):
- // https://mathml-refresh.github.io/mathml-core/#embellished-operators
- if (auto* element =
- DynamicTo<MathMLOperatorElement>(base.GetDOMNode())) {
- return element->HasBooleanProperty(MathMLOperatorElement::kMovableLimits);
- }
- return false;
+ const auto base = To<NGBlockNode>(FirstChildInFlow(node));
+ const auto base_properties = GetMathMLEmbellishedOperatorProperties(base);
+ return base_properties && base_properties->has_movablelimits;
}
bool IsOperatorWithSpecialShaping(const NGBlockNode& node) {
if (!node.IsBlock() || !node.IsMathML() || !node.FirstChild().IsInline())
return false;
- // https://mathml-refresh.github.io/mathml-core/#layout-of-operators
+ // https://w3c.github.io/mathml-core/#layout-of-operators
if (auto* element = DynamicTo<MathMLOperatorElement>(node.GetDOMNode())) {
UChar32 base_code_point = element->GetOperatorContent().code_point;
if (base_code_point == kNonCharacter ||
@@ -240,7 +243,8 @@ bool IsOperatorWithSpecialShaping(const NGBlockNode& node) {
base_code_point))
return false;
- // TODO(crbug.com/1124301) Implement stretchy operators.
+ if (element->HasBooleanProperty(MathMLOperatorElement::kStretchy))
+ return true;
if (element->HasBooleanProperty(MathMLOperatorElement::kLargeOp) &&
HasDisplayStyle(node.Style()))
@@ -275,4 +279,55 @@ LayoutUnit FractionLineThickness(const ComputedStyle& style) {
LayoutUnit());
}
+LayoutUnit MathTableBaseline(const ComputedStyle& style,
+ LayoutUnit block_offset) {
+ // The center of the table is aligned with the math axis.
+ // See: https://w3c.github.io/mathml-core/#table-or-matrix-mtable
+ return LayoutUnit(block_offset / 2 + MathAxisHeight(style));
+}
+
+namespace {
+
+MathMLOperatorElement* GetCoreOperator(const NGBlockNode& node) {
+ if (!node || !node.IsMathML())
+ return nullptr;
+
+ // See https://w3c.github.io/mathml-core/#embellished-operators
+ // TODO(crbug.com/1124298): Implement embellished operators.
+ auto* element = DynamicTo<MathMLElement>(node.GetDOMNode());
+ if (element && element->HasTagName(mathml_names::kMoTag)) {
+ // 1. An <mo> element;
+ return To<MathMLOperatorElement>(element);
+ }
+ return nullptr;
+}
+
+} // namespace
+
+absl::optional<MathMLEmbellishedOperatorProperties>
+GetMathMLEmbellishedOperatorProperties(const NGBlockNode& node) {
+ auto* core_operator = GetCoreOperator(node);
+ if (!core_operator)
+ return absl::nullopt;
+
+ MathMLEmbellishedOperatorProperties properties;
+
+ properties.has_movablelimits =
+ core_operator->HasBooleanProperty(MathMLOperatorElement::kMovableLimits);
+
+ LayoutUnit leading_space(core_operator->DefaultLeadingSpace() *
+ node.Style().FontSize());
+ properties.lspace =
+ ValueForLength(node.Style().GetMathLSpace(), leading_space)
+ .ClampNegativeToZero();
+
+ LayoutUnit trailing_space(core_operator->DefaultTrailingSpace() *
+ node.Style().FontSize());
+ properties.rspace =
+ ValueForLength(node.Style().GetMathRSpace(), trailing_space)
+ .ClampNegativeToZero();
+
+ return properties;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
index 0990a526e24..2cdd125adb0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_LAYOUT_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_LAYOUT_UTILS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h"
@@ -23,7 +25,12 @@ NGConstraintSpace CreateConstraintSpaceForMathChild(
const NGBlockNode& parent_node,
const LogicalSize& child_available_size,
const NGConstraintSpace& parent_constraint_space,
- const NGLayoutInputNode&);
+ const NGLayoutInputNode&,
+ const NGCacheSlot = NGCacheSlot::kLayout,
+ const absl::optional<NGConstraintSpace::MathTargetStretchBlockSizes>
+ target_stretch_block_sizes = absl::nullopt,
+ const absl::optional<LayoutUnit> target_stretch_inline_size =
+ absl::nullopt);
MinMaxSizesResult ComputeMinAndMaxContentContributionForMathChild(
const ComputedStyle& parent_style,
@@ -38,7 +45,7 @@ bool IsValidMathMLFraction(const NGBlockNode&);
bool IsValidMathMLScript(const NGBlockNode&);
bool IsValidMathMLRadical(const NGBlockNode&);
-// https://mathml-refresh.github.io/mathml-core/#dfn-default-rule-thickness
+// https://w3c.github.io/mathml-core/#dfn-default-rule-thickness
inline float RuleThicknessFallback(const ComputedStyle& style) {
const SimpleFontData* font_data = style.GetFont().PrimaryFont();
if (!font_data)
@@ -65,7 +72,7 @@ inline bool HasDisplayStyle(const ComputedStyle& style) {
// Get parameters for horizontal positioning of mroot.
// The parameters are defined here:
-// https://mathml-refresh.github.io/mathml-core/#layout-constants-mathconstants
+// https://w3c.github.io/mathml-core/#layout-constants-mathconstants
struct RadicalHorizontalParameters {
LayoutUnit kern_before_degree;
LayoutUnit kern_after_degree;
@@ -75,7 +82,7 @@ RadicalHorizontalParameters GetRadicalHorizontalParameters(
// Get parameters for vertical positioning of msqrt/mroot.
// The parameters are defined here:
-// https://mathml-refresh.github.io/mathml-core/#layout-constants-mathconstants
+// https://w3c.github.io/mathml-core/#layout-constants-mathconstants
struct RadicalVerticalParameters {
LayoutUnit vertical_gap;
LayoutUnit rule_thickness;
@@ -85,12 +92,25 @@ struct RadicalVerticalParameters {
RadicalVerticalParameters GetRadicalVerticalParameters(const ComputedStyle&,
bool has_index);
-// https://mathml-refresh.github.io/mathml-core/#dfn-preferred-inline-size-of-a-glyph-stretched-along-the-block-axis
+// https://w3c.github.io/mathml-core/#dfn-preferred-inline-size-of-a-glyph-stretched-along-the-block-axis
MinMaxSizes GetMinMaxSizesForVerticalStretchyOperator(const ComputedStyle&,
UChar character);
bool IsUnderOverLaidOutAsSubSup(const NGBlockNode& node);
bool IsOperatorWithSpecialShaping(const NGBlockNode& node);
+
+LayoutUnit MathTableBaseline(const ComputedStyle&, LayoutUnit block_offset);
+
+// For nodes corresponding to embellished operators, this function returns the
+// properties of its core operator. Otherwise, it returns a null optional.
+// See https://mathml-refresh.github.io/mathml-core/#embellished-operators
+struct MathMLEmbellishedOperatorProperties {
+ bool has_movablelimits;
+ LayoutUnit lspace;
+ LayoutUnit rspace;
+};
+absl::optional<MathMLEmbellishedOperatorProperties>
+GetMathMLEmbellishedOperatorProperties(const NGBlockNode&);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_LAYOUT_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc
index d15918216eb..1e0fe07ab0b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc
@@ -38,7 +38,7 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() {
// properly laid out but the glyph will actually be used to determine a
// "large" or "stretched" version, from which we perform measurement and
// painting.
- // See https://mathml-refresh.github.io/mathml-core/#layout-of-operators
+ // See https://w3c.github.io/mathml-core/#layout-of-operators
NGLayoutInputNode child = Node().FirstChild();
DCHECK(child && child.IsInline());
DCHECK(!child.NextSibling());
@@ -53,11 +53,86 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() {
To<NGInlineNode>(child).Layout(ConstraintSpace(), nullptr, &context);
container_builder_.AddResult(*child_layout_result, {});
- // TODO(http://crbug.com/1124301) Implement stretchy operators.
+ // https://w3c.github.io/mathml-core/#layout-of-operators
+ LayoutUnit operator_target_size;
+ LayoutUnit target_stretch_ascent, target_stretch_descent;
+ auto* element = DynamicTo<MathMLOperatorElement>(Node().GetDOMNode());
+ if (element->HasBooleanProperty(MathMLOperatorElement::kStretchy)) {
+ // "If the operator has the stretchy property:"
+ if (!element->GetOperatorContent().is_vertical) {
+ // "If the stretch axis of the operator is inline."
+ if (ConstraintSpace().HasTargetStretchInlineSize())
+ operator_target_size = ConstraintSpace().TargetStretchInlineSize();
+ } else {
+ // "Otherwise, the stretch axis of the operator is block."
+ if (auto target_stretch_block_sizes =
+ ConstraintSpace().TargetStretchBlockSizes()) {
+ target_stretch_ascent = target_stretch_block_sizes->ascent;
+ target_stretch_descent = target_stretch_block_sizes->descent;
+ if (element->HasBooleanProperty(MathMLOperatorElement::kSymmetric)) {
+ // "If the operator has the symmetric property then set the target
+ // sizes Tascent and Tdescent to Sascent and Sdescent respectively:
+ // Sascent = max( Uascent − AxisHeight, Udescent + AxisHeight ) +
+ // AxisHeight
+ // Sdescent = max( Uascent − AxisHeight, Udescent + AxisHeight ) −
+ // AxisHeight"
+ LayoutUnit axis = MathAxisHeight(Style());
+ LayoutUnit half_target_stretch_size = std::max(
+ target_stretch_ascent - axis, target_stretch_descent + axis);
+ target_stretch_ascent = half_target_stretch_size + axis;
+ target_stretch_descent = half_target_stretch_size - axis;
+ }
+ operator_target_size = target_stretch_ascent + target_stretch_descent;
+ // "If minsize < 0 then set minsize to 0."
+ LayoutUnit min_size =
+ (Style().GetMathMinSize().GetType() == Length::kAuto
+ ? LayoutUnit(Style().FontSize())
+ : ValueForLength(Style().GetMathMinSize(),
+ operator_target_size))
+ .ClampNegativeToZero();
+ // "If maxsize < minsize then set maxsize to minsize."
+ LayoutUnit max_size = std::max<LayoutUnit>(
+ (Style().GetMathMaxSize().GetType() == Length::kAuto
+ ? LayoutUnit(kIntMaxForLayoutUnit)
+ : ValueForLength(Style().GetMathMaxSize(),
+ operator_target_size)),
+ min_size);
+ // "Then 0 ≤ minsize ≤ maxsize:"
+ DCHECK(LayoutUnit() <= min_size && min_size <= max_size);
+ if (operator_target_size <= LayoutUnit()) {
+ // "If T ≤ 0 then set Tascent to minsize/2 and then set Tdescent to
+ // minsize - Tascent."
+ target_stretch_ascent = min_size / 2;
+ target_stretch_descent = min_size - target_stretch_ascent;
+ } else if (operator_target_size < min_size) {
+ // "Otherwise, if 0 < T < minsize then first multiply Tascent by
+ // minsize / T and then set Tdescent to minsize - Tascent."
+ target_stretch_ascent =
+ target_stretch_ascent.MulDiv(min_size, operator_target_size);
+ target_stretch_descent = min_size - target_stretch_ascent;
+ } else if (max_size < operator_target_size) {
+ // "Otherwise, if maxsize < T then first multiply Tascent by maxsize
+ // / T and then set Tdescent to maxsize − Tascent."
+ target_stretch_ascent =
+ target_stretch_descent.MulDiv(max_size, operator_target_size);
+ target_stretch_descent = max_size - target_stretch_ascent;
+ }
+ operator_target_size = target_stretch_ascent + target_stretch_descent;
+ }
+ }
+ } else {
+ // "If the operator has the largeop property and if math-style on the <mo>
+ // element is normal."
+ DCHECK(element->HasBooleanProperty(MathMLOperatorElement::kLargeOp));
+ DCHECK(HasDisplayStyle(Node().Style()));
+ operator_target_size = DisplayOperatorMinHeight(Style());
+ }
- float operator_target_size = DisplayOperatorMinHeight(Style());
- StretchyOperatorShaper shaper(GetBaseCodePoint(),
- OpenTypeMathStretchData::StretchAxis::Vertical);
+ StretchyOperatorShaper shaper(
+ GetBaseCodePoint(),
+ element->GetOperatorContent().is_vertical
+ ? OpenTypeMathStretchData::StretchAxis::Vertical
+ : OpenTypeMathStretchData::StretchAxis::Horizontal);
StretchyOperatorShaper::Metrics metrics;
scoped_refptr<ShapeResult> shape_result =
shaper.Shape(&Style().GetFont(), operator_target_size, &metrics);
@@ -69,6 +144,11 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() {
LayoutUnit(metrics.italic_correction));
}
+ // TODO(http://crbug.com/1124301): The spec says the inline size should be
+ // the one of the stretched glyph, but LayoutNG currently relies on the
+ // min-max sizes. This means there can be excessive gap around vertical
+ // stretchy operators and that unstretched size will be used for horizontal
+ // stretchy operators. See also NGMathMLPainter::PaintOperator.
LayoutUnit operator_ascent = LayoutUnit::FromFloatFloor(metrics.ascent);
LayoutUnit operator_descent = LayoutUnit::FromFloatFloor(metrics.descent);
@@ -78,6 +158,16 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() {
LayoutUnit ascent = BorderScrollbarPadding().block_start + operator_ascent;
LayoutUnit descent = operator_descent + BorderScrollbarPadding().block_end;
+ if (element->HasBooleanProperty(MathMLOperatorElement::kStretchy) &&
+ element->GetOperatorContent().is_vertical) {
+ // "The stretchy glyph is shifted towards the line-under by a value Δ so
+ // that its center aligns with the center of the target"
+ LayoutUnit delta = ((operator_ascent - operator_descent) -
+ (target_stretch_ascent - target_stretch_descent)) /
+ 2;
+ ascent -= delta;
+ descent += delta;
+ }
LayoutUnit intrinsic_block_size = ascent + descent;
LayoutUnit block_size = ComputeBlockSizeForFragment(
ConstraintSpace(), Style(), BorderPadding(), intrinsic_block_size,
@@ -92,15 +182,37 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() {
MinMaxSizesResult NGMathOperatorLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesFloatInput&) const {
- // TODO(http://crbug.com/1124301) Implement stretchy operators.
MinMaxSizes sizes;
- StretchyOperatorShaper shaper(GetBaseCodePoint(),
- OpenTypeMathStretchData::Vertical);
- StretchyOperatorShaper::Metrics metrics;
- float operator_target_size = DisplayOperatorMinHeight(Style());
- shaper.Shape(&Style().GetFont(), operator_target_size, &metrics);
- sizes.Encompass(LayoutUnit(metrics.advance));
+ // https://w3c.github.io/mathml-core/#layout-of-operators
+ auto* element = DynamicTo<MathMLOperatorElement>(Node().GetDOMNode());
+ if (element->HasBooleanProperty(MathMLOperatorElement::kStretchy)) {
+ // "If the operator has the stretchy property:"
+ if (!element->GetOperatorContent().is_vertical) {
+ // "If the stretch axis of the operator is inline."
+ // The spec current says we should rely on the layout algorithm of
+ // § 3.2.1.1 Layout of <mtext>. Instead, we perform horizontal stretching
+ // with target size of 0 so that the size of the base glyph is used.
+ StretchyOperatorShaper shaper(GetBaseCodePoint(),
+ OpenTypeMathStretchData::Horizontal);
+ StretchyOperatorShaper::Metrics metrics;
+ shaper.Shape(&Style().GetFont(), 0, &metrics);
+ sizes.Encompass(LayoutUnit(metrics.advance));
+ } else {
+ // "Otherwise, the stretch axis of the operator is block."
+ sizes = GetMinMaxSizesForVerticalStretchyOperator(Style(),
+ GetBaseCodePoint());
+ }
+ } else {
+ // "If the operator has the largeop property and if math-style on the <mo>
+ // element is normal."
+ StretchyOperatorShaper shaper(GetBaseCodePoint(),
+ OpenTypeMathStretchData::Vertical);
+ StretchyOperatorShaper::Metrics metrics;
+ LayoutUnit operator_target_size = DisplayOperatorMinHeight(Style());
+ shaper.Shape(&Style().GetFont(), operator_target_size, &metrics);
+ sizes.Encompass(LayoutUnit(metrics.advance));
+ }
sizes += BorderScrollbarPadding().InlineSum();
return MinMaxSizesResult(sizes, /* depends_on_block_constraints */ false);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
index 94d7ac1d88b..a5687e57e01 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_PADDED_LAYOUT_ALGORITHM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_PADDED_LAYOUT_ALGORITHM_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
index 3a5cfd1e7d9..d699b6fe843 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
@@ -93,7 +93,7 @@ scoped_refptr<const NGLayoutResult> NGMathRadicalLayoutAlgorithm::Layout() {
}
if (index) {
// Handle layout of index child.
- // (https://mathml-refresh.github.io/mathml-core/#root-with-index).
+ // (https://w3c.github.io/mathml-core/#root-with-index).
NGConstraintSpace constraint_space = CreateConstraintSpaceForMathChild(
Node(), ChildAvailableSize(), ConstraintSpace(), index);
scoped_refptr<const NGLayoutResult> index_layout_result =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
index 4287147874a..01709ddacaf 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
@@ -26,24 +26,24 @@ inline LayoutUnit InlineOffsetForDisplayMathCentering(
return LayoutUnit();
}
-static void DetermineOperatorSpacing(const NGLayoutInputNode& node,
+static void DetermineOperatorSpacing(const NGBlockNode& node,
LayoutUnit* lspace,
LayoutUnit* rspace) {
- auto* core_operator =
- DynamicTo<MathMLOperatorElement>(node.GetDOMNode());
- if (core_operator) {
+ if (auto properties = GetMathMLEmbellishedOperatorProperties(node)) {
+ *lspace = properties->lspace;
+ *rspace = properties->rspace;
+ }
+}
+
+static bool IsStretchyOperatorWithBlockStretchAxis(const NGBlockNode& node) {
+ if (auto* core_operator =
+ DynamicTo<MathMLOperatorElement>(node.GetDOMNode())) {
// TODO(crbug.com/1124298): Implement embellished operators.
- LayoutUnit leading_space(core_operator->DefaultLeadingSpace() *
- node.Style().FontSize());
- *lspace = std::max<LayoutUnit>(
- ValueForLength(node.Style().GetMathLSpace(), leading_space),
- LayoutUnit());
- LayoutUnit trailing_space(core_operator->DefaultTrailingSpace() *
- node.Style().FontSize());
- *rspace = std::max<LayoutUnit>(
- ValueForLength(node.Style().GetMathRSpace(), trailing_space),
- LayoutUnit());
+ return core_operator->HasBooleanProperty(
+ MathMLOperatorElement::kStretchy) &&
+ core_operator->GetOperatorContent().is_vertical;
}
+ return false;
}
} // namespace
@@ -60,6 +60,56 @@ void NGMathRowLayoutAlgorithm::LayoutRowItems(
LayoutUnit* max_row_block_baseline,
LogicalSize* row_total_size) {
LayoutUnit inline_offset, max_row_ascent, max_row_descent;
+
+ // https://w3c.github.io/mathml-core/#dfn-algorithm-for-stretching-operators-along-the-block-axis
+ NGConstraintSpace::MathTargetStretchBlockSizes stretch_sizes;
+ auto UpdateBlockStretchSizes =
+ [&](const scoped_refptr<const NGLayoutResult>& result) {
+ NGBoxFragment fragment(
+ ConstraintSpace().GetWritingDirection(),
+ To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+ LayoutUnit ascent = fragment.BaselineOrSynthesize();
+ stretch_sizes.ascent = std::max(stretch_sizes.ascent, ascent),
+ stretch_sizes.descent =
+ std::max(stretch_sizes.descent, fragment.BlockSize() - ascent);
+ };
+
+ // "Perform layout without any stretch size constraint on all the items of
+ // LNotToStretch."
+ bool should_layout_remaining_items_with_zero_block_stretch_size = true;
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ if (child.IsOutOfFlowPositioned() ||
+ IsStretchyOperatorWithBlockStretchAxis(To<NGBlockNode>(child)))
+ continue;
+ const auto child_constraint_space = CreateConstraintSpaceForMathChild(
+ Node(), ChildAvailableSize(), ConstraintSpace(), child,
+ NGCacheSlot::kMeasure);
+ const auto child_layout_result = To<NGBlockNode>(child).Layout(
+ child_constraint_space, nullptr /* break_token */);
+ UpdateBlockStretchSizes(child_layout_result);
+ should_layout_remaining_items_with_zero_block_stretch_size = false;
+ }
+
+ if (UNLIKELY(should_layout_remaining_items_with_zero_block_stretch_size)) {
+ // "If LNotToStretch is empty, perform layout with stretch size constraint
+ // 0 on all the items of LToStretch."
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ if (child.IsOutOfFlowPositioned())
+ continue;
+ DCHECK(IsStretchyOperatorWithBlockStretchAxis(To<NGBlockNode>(child)));
+ NGConstraintSpace::MathTargetStretchBlockSizes zero_stretch_sizes;
+ const auto child_constraint_space = CreateConstraintSpaceForMathChild(
+ Node(), ChildAvailableSize(), ConstraintSpace(), child,
+ NGCacheSlot::kMeasure, zero_stretch_sizes);
+ const auto child_layout_result = To<NGBlockNode>(child).Layout(
+ child_constraint_space, nullptr /* break_token */);
+ UpdateBlockStretchSizes(child_layout_result);
+ }
+ }
+
+ // Layout in-flow children in a row.
for (NGLayoutInputNode child = Node().FirstChild(); child;
child = child.NextSibling()) {
if (child.IsOutOfFlowPositioned()) {
@@ -70,19 +120,26 @@ void NGMathRowLayoutAlgorithm::LayoutRowItems(
To<NGBlockNode>(child), BorderScrollbarPadding().StartOffset());
continue;
}
+ // TODO(crbug.com/1124298): If there is already a stretch constraint, use
+ // for the child_constraint_space.
+ const auto child_constraint_space =
+ IsStretchyOperatorWithBlockStretchAxis(To<NGBlockNode>(child))
+ ? CreateConstraintSpaceForMathChild(
+ Node(), ChildAvailableSize(), ConstraintSpace(), child,
+ NGCacheSlot::kLayout, stretch_sizes)
+ : CreateConstraintSpaceForMathChild(Node(), ChildAvailableSize(),
+ ConstraintSpace(), child);
+ const auto child_layout_result = To<NGBlockNode>(child).Layout(
+ child_constraint_space, nullptr /* break_token */);
LayoutUnit lspace, rspace;
- DetermineOperatorSpacing(child, &lspace, &rspace);
- const ComputedStyle& child_style = child.Style();
- NGConstraintSpace child_space = CreateConstraintSpaceForMathChild(
- Node(), ChildAvailableSize(), ConstraintSpace(), child);
- scoped_refptr<const NGLayoutResult> result =
- To<NGBlockNode>(child).Layout(child_space, nullptr /* break token */);
- const NGPhysicalFragment& physical_fragment = result->PhysicalFragment();
+ DetermineOperatorSpacing(To<NGBlockNode>(child), &lspace, &rspace);
+ const NGPhysicalFragment& physical_fragment =
+ child_layout_result->PhysicalFragment();
NGBoxFragment fragment(ConstraintSpace().GetWritingDirection(),
To<NGPhysicalBoxFragment>(physical_fragment));
- NGBoxStrut margins =
- ComputeMarginsFor(child_space, child_style, ConstraintSpace());
+ NGBoxStrut margins = ComputeMarginsFor(child_constraint_space,
+ child.Style(), ConstraintSpace());
inline_offset += margins.inline_start;
LayoutUnit ascent = margins.block_start + fragment.BaselineOrSynthesize();
@@ -169,7 +226,7 @@ MinMaxSizesResult NGMathRowLayoutAlgorithm::ComputeMinMaxSizes(
sizes += child_result.sizes;
LayoutUnit lspace, rspace;
- DetermineOperatorSpacing(child, &lspace, &rspace);
+ DetermineOperatorSpacing(To<NGBlockNode>(child), &lspace, &rspace);
sizes += lspace + rspace;
depends_on_block_constraints |= child_result.depends_on_block_constraints;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
index 771d5a55af0..6eafa651541 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
@@ -29,9 +29,9 @@ LayoutUnit GetSpaceAfterScript(const ComputedStyle& style) {
// Describes the amount of shift to apply to the sub/sup boxes.
// Data is populated from the OpenType MATH table.
// If the OpenType MATH table is not present fallback values are used.
-// https://mathml-refresh.github.io/mathml-core/#base-with-subscript
-// https://mathml-refresh.github.io/mathml-core/#base-with-superscript
-// https://mathml-refresh.github.io/mathml-core/#base-with-subscript-and-superscript
+// https://w3c.github.io/mathml-core/#base-with-subscript
+// https://w3c.github.io/mathml-core/#base-with-superscript
+// https://w3c.github.io/mathml-core/#base-with-subscript-and-superscript
struct ScriptsVerticalParameters {
STACK_ALLOCATED();
@@ -146,7 +146,7 @@ void NGMathScriptsLayoutAlgorithm::GatherChildren(
continue;
case MathScriptType::kMultiscripts: {
// The structure of mmultiscripts is specified here:
- // https://mathml-refresh.github.io/mathml-core/#prescripts-and-tensor-indices-mmultiscripts
+ // https://w3c.github.io/mathml-core/#prescripts-and-tensor-indices-mmultiscripts
if (IsPrescriptDelimiter(block_child)) {
if (!number_of_scripts_is_even || *prescripts) {
NOTREACHED();
@@ -296,8 +296,9 @@ scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() {
GatherChildren(&base, &sub_sup_pairs, &prescripts, &first_prescript_index,
&container_builder_);
ChildrenAndMetrics sub_metrics, sup_metrics;
+ ChildAndMetrics prescripts_metrics;
if (prescripts)
- LayoutAndGetMetrics(prescripts);
+ prescripts_metrics = LayoutAndGetMetrics(prescripts);
for (auto sub_sup_pair : sub_sup_pairs) {
if (sub_sup_pair.sub)
sub_metrics.emplace_back(LayoutAndGetMetrics(sub_sup_pair.sub));
@@ -356,6 +357,14 @@ scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() {
container_builder_.AddChild(base_metrics.result->PhysicalFragment(),
base_offset);
base.StoreMargins(ConstraintSpace(), base_metrics.margins);
+ if (prescripts) {
+ LogicalOffset prescripts_offset(inline_offset,
+ ascent - prescripts_metrics.ascent +
+ prescripts_metrics.margins.block_start);
+ container_builder_.AddChild(prescripts_metrics.result->PhysicalFragment(),
+ prescripts_offset);
+ prescripts.StoreMargins(ConstraintSpace(), prescripts_metrics.margins);
+ }
inline_offset += base_metrics.inline_size + base_metrics.margins.inline_end;
// Position post scripts if needed.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
index b75412f5713..7e49a519b9f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
@@ -19,8 +19,8 @@ namespace {
// Describes the amount to shift to apply to the under/over boxes.
// Data is populated from the OpenType MATH table.
// If the OpenType MATH table is not present fallback values are used.
-// https://mathml-refresh.github.io/mathml-core/#base-with-underscript
-// https://mathml-refresh.github.io/mathml-core/#base-with-overscript
+// https://w3c.github.io/mathml-core/#base-with-underscript
+// https://w3c.github.io/mathml-core/#base-with-overscript
struct UnderOverVerticalParameters {
bool use_under_over_bar_fallback;
LayoutUnit under_gap_min;
@@ -41,7 +41,7 @@ UnderOverVerticalParameters GetUnderOverVerticalParameters(
if (!font_data)
return parameters;
- // https://mathml-refresh.github.io/mathml-core/#dfn-default-fallback-constant
+ // https://w3c.github.io/mathml-core/#dfn-default-fallback-constant
const float default_fallback_constant = 0;
if (is_base_large_operator) {
@@ -121,7 +121,7 @@ UnderOverVerticalParameters GetUnderOverVerticalParameters(
return parameters;
}
-// https://mathml-refresh.github.io/mathml-core/#underscripts-and-overscripts-munder-mover-munderover
+// https://w3c.github.io/mathml-core/#underscripts-and-overscripts-munder-mover-munderover
bool HasAccent(const NGBlockNode& node, bool accent_under) {
DCHECK(node);
auto* underover = To<MathMLUnderOverElement>(node.GetDOMNode());
@@ -135,6 +135,17 @@ bool HasAccent(const NGBlockNode& node, bool accent_under) {
return attribute_value && *attribute_value;
}
+static bool IsStretchyOperatorWithInlineStretchAxis(const NGBlockNode& node) {
+ if (auto* core_operator =
+ DynamicTo<MathMLOperatorElement>(node.GetDOMNode())) {
+ // TODO(crbug.com/1124298): Implement embellished operators.
+ return core_operator->HasBooleanProperty(
+ MathMLOperatorElement::kStretchy) &&
+ !core_operator->GetOperatorContent().is_vertical;
+ }
+ return false;
+}
+
} // namespace
NGMathUnderOverLayoutAlgorithm::NGMathUnderOverLayoutAlgorithm(
@@ -211,11 +222,67 @@ scoped_refptr<const NGLayoutResult> NGMathUnderOverLayoutAlgorithm::Layout() {
}
UnderOverVerticalParameters parameters = GetUnderOverVerticalParameters(
Style(), is_base_large_operator, is_base_stretchy_in_inline_axis);
- // TODO(crbug.com/1124301): handle stretchy operators.
+
+ // https://w3c.github.io/mathml-core/#dfn-algorithm-for-stretching-operators-along-the-inline-axis
+ LayoutUnit inline_stretch_size;
+ auto UpdateInlineStretchSize =
+ [&](const scoped_refptr<const NGLayoutResult>& result) {
+ NGFragment fragment(
+ ConstraintSpace().GetWritingDirection(),
+ To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+ inline_stretch_size =
+ std::max(inline_stretch_size, fragment.InlineSize());
+ };
+
+ // "Perform layout without any stretch size constraint on all the items of
+ // LNotToStretch"
+ bool layout_remaining_items_with_zero_inline_stretch_size = true;
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ if (child.IsOutOfFlowPositioned() ||
+ IsStretchyOperatorWithInlineStretchAxis(To<NGBlockNode>(child)))
+ continue;
+ const auto child_constraint_space = CreateConstraintSpaceForMathChild(
+ Node(), ChildAvailableSize(), ConstraintSpace(), child,
+ NGCacheSlot::kMeasure);
+ const auto child_layout_result = To<NGBlockNode>(child).Layout(
+ child_constraint_space, nullptr /* break_token */);
+ UpdateInlineStretchSize(child_layout_result);
+ layout_remaining_items_with_zero_inline_stretch_size = false;
+ }
+
+ if (UNLIKELY(layout_remaining_items_with_zero_inline_stretch_size)) {
+ // "If LNotToStretch is empty, perform layout with stretch size constraint 0
+ // on all the items of LToStretch.
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ if (child.IsOutOfFlowPositioned())
+ continue;
+ DCHECK(IsStretchyOperatorWithInlineStretchAxis(To<NGBlockNode>(child)));
+ LayoutUnit zero_stretch_size;
+ const auto child_constraint_space = CreateConstraintSpaceForMathChild(
+ Node(), ChildAvailableSize(), ConstraintSpace(), child,
+ NGCacheSlot::kMeasure, absl::nullopt, zero_stretch_size);
+ const auto child_layout_result = To<NGBlockNode>(child).Layout(
+ child_constraint_space, nullptr /* break_token */);
+ UpdateInlineStretchSize(child_layout_result);
+ }
+ }
+
+ auto CreateConstraintSpaceForUnderOverChild = [&](const NGBlockNode child) {
+ // TODO(crbug.com/1124298): If there is a stretch constraint, use it.
+ return IsStretchyOperatorWithInlineStretchAxis(child)
+ ? CreateConstraintSpaceForMathChild(
+ Node(), ChildAvailableSize(), ConstraintSpace(), child,
+ NGCacheSlot::kLayout, absl::nullopt, inline_stretch_size)
+ : CreateConstraintSpaceForMathChild(Node(), ChildAvailableSize(),
+ ConstraintSpace(), child,
+ NGCacheSlot::kLayout);
+ };
+
// TODO(crbug.com/1125136): take into account italic correction.
- auto base_space = CreateConstraintSpaceForMathChild(
- Node(), ChildAvailableSize(), ConstraintSpace(), base);
+ const auto base_space = CreateConstraintSpaceForUnderOverChild(base);
auto base_layout_result = base.Layout(base_space);
auto base_margins =
ComputeMarginsFor(base_space, base.Style(), ConstraintSpace());
@@ -228,8 +295,7 @@ scoped_refptr<const NGLayoutResult> NGMathUnderOverLayoutAlgorithm::Layout() {
// All children are positioned centered relative to the container (and
// therefore centered relative to themselves).
if (over) {
- auto over_space = CreateConstraintSpaceForMathChild(
- Node(), ChildAvailableSize(), ConstraintSpace(), over);
+ const auto over_space = CreateConstraintSpaceForUnderOverChild(over);
scoped_refptr<const NGLayoutResult> over_layout_result =
over.Layout(over_space);
NGBoxStrut over_margins =
@@ -277,8 +343,7 @@ scoped_refptr<const NGLayoutResult> NGMathUnderOverLayoutAlgorithm::Layout() {
block_offset += base_fragment.BlockSize() + base_margins.block_end;
if (under) {
- auto under_space = CreateConstraintSpaceForMathChild(
- Node(), ChildAvailableSize(), ConstraintSpace(), under);
+ const auto under_space = CreateConstraintSpaceForUnderOverChild(under);
scoped_refptr<const NGLayoutResult> under_layout_result =
under.Layout(under_space);
NGBoxStrut under_margins =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h
index 68012f71cc0..2f3992a0f0c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATHML_PAINT_INFO_H_
#include <unicode/uchar.h>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
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 ac778b2dee7..a2905a5e495 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
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
@@ -431,8 +432,7 @@ bool ComputeOutOfFlowInlineDimensions(
min_max_length_sizes = {LayoutUnit(), LayoutUnit::Max()};
} else {
min_max_length_sizes = ComputeMinMaxInlineSizes(
- space, node, border_padding, MinMaxSizesFunc, &min_inline_length,
- /* is_block_size_indefinite */ !can_compute_block_size_without_layout);
+ space, node, border_padding, MinMaxSizesFunc, &min_inline_length);
}
const auto writing_direction = style.GetWritingDirection();
@@ -490,6 +490,14 @@ scoped_refptr<const NGLayoutResult> ComputeOutOfFlowBlockDimensions(
{dimensions->size.inline_size, space.AvailableSize().block_size});
builder.SetIsFixedInlineSize(true);
builder.SetPercentageResolutionSize(space.PercentageResolutionSize());
+
+ if (space.IsInitialColumnBalancingPass()) {
+ // The |fragmentainer_offset_delta| will not make a difference in the
+ // initial column balancing pass.
+ SetupSpaceBuilderForFragmentation(
+ space, node, /* fragmentainer_offset_delta */ LayoutUnit(),
+ &builder, /* is_new_fc */ true);
+ }
result = node.Layout(builder.ToConstraintSpace());
}
@@ -531,6 +539,15 @@ scoped_refptr<const NGLayoutResult> ComputeOutOfFlowBlockDimensions(
min_max_length_sizes =
ComputeMinMaxBlockSizes(space, style, border_padding);
+ // Manually resolve any intrinsic/content min/max block-sizes.
+ // TODO(crbug.com/1135207): |ComputeMinMaxBlockSizes()| should handle this.
+ if (style.LogicalMinHeight().IsContentOrIntrinsic())
+ min_max_length_sizes.min_size = IntrinsicBlockSizeFunc();
+ if (style.LogicalMaxHeight().IsContentOrIntrinsic())
+ min_max_length_sizes.max_size = IntrinsicBlockSizeFunc();
+ min_max_length_sizes.max_size =
+ std::max(min_max_length_sizes.max_size, min_max_length_sizes.min_size);
+
// Tables are never allowed to go below their "auto" block-size.
if (is_table)
min_max_length_sizes.Encompass(IntrinsicBlockSizeFunc());
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 1ab02eec472..165da53bd67 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
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
#include "third_party/blink/renderer/core/layout/min_max_sizes.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
namespace blink {
@@ -65,6 +66,20 @@ CORE_EXPORT void AdjustOffsetForSplitInline(
const NGBoxFragmentBuilder* container_builder,
LogicalOffset& offset);
+// Figure out if the child has any out-of-flow positioned descendants, in which
+// case we'll need to propagate this to the fragment builder.
+inline bool NeedsOOFPositionedInfoPropagation(const NGPhysicalFragment& child) {
+ if (child.HasOutOfFlowPositionedDescendants())
+ return true;
+
+ const auto* box_fragment = DynamicTo<NGPhysicalBoxFragment>(&child);
+ if (!box_fragment)
+ return false;
+
+ return box_fragment->HasMulticolsWithPendingOOFs() ||
+ box_fragment->HasOutOfFlowPositionedFragmentainerDescendants();
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_ABSOLUTE_UTILS_H_
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 b6a1bd173f1..3175f200811 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
@@ -126,7 +126,9 @@ NGConstraintSpace ConstructBlockLayoutTestConstraintSpace(
is_new_formatting_context);
builder.SetAvailableSize(size);
builder.SetPercentageResolutionSize(size);
- builder.SetStretchInlineSizeIfAuto(stretch_inline_size_if_auto);
+ builder.SetInlineAutoBehavior(stretch_inline_size_if_auto
+ ? NGAutoBehavior::kStretchImplicit
+ : NGAutoBehavior::kFitContent);
builder.SetFragmentainerBlockSize(fragmentainer_space_available);
builder.SetFragmentationType(block_fragmentation);
return builder.ToConstraintSpace();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc
index 89110a9ffae..ae20253d52c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc
@@ -14,7 +14,7 @@ namespace blink {
namespace {
struct SameSizeAsNGBlockBreakToken : NGBreakToken {
- unsigned numbers[3];
+ unsigned numbers[4];
};
ASSERT_SIZE(NGBlockBreakToken, SameSizeAsNGBlockBreakToken);
@@ -38,6 +38,8 @@ NGBlockBreakToken::NGBlockBreakToken(PassKey key,
const NGBoxFragmentBuilder& builder)
: NGBreakToken(kBlockBreakToken, builder.node_),
consumed_block_size_(builder.consumed_block_size_),
+ consumed_block_size_legacy_adjustment_(
+ builder.consumed_block_size_legacy_adjustment_),
sequence_number_(builder.sequence_number_),
num_children_(builder.child_break_tokens_.size()) {
break_appeal_ = builder.break_appeal_;
@@ -89,6 +91,13 @@ String NGBlockBreakToken::ToString() const {
string_builder.Append(" consumed:");
string_builder.Append(consumed_block_size_.ToString());
string_builder.Append("px");
+
+ if (consumed_block_size_legacy_adjustment_) {
+ string_builder.Append(" legacy adjustment:");
+ string_builder.Append(consumed_block_size_legacy_adjustment_.ToString());
+ string_builder.Append("px");
+ }
+
return string_builder.ToString();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h
index d70d2ad3fba..6b7e39055a5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h
@@ -55,6 +55,17 @@ class CORE_EXPORT NGBlockBreakToken final : public NGBreakToken {
// the fragmentainer is shorter than 50px, for instance).
LayoutUnit ConsumedBlockSize() const { return consumed_block_size_; }
+ // The consumed block size when writing back to legacy layout. The only time
+ // this may be different than ConsumedBlockSize() is in the case of a
+ // fragmentainer. We clamp the fragmentainer block size from 0 to 1 for legacy
+ // write-back only in the case where there is content that overflows the
+ // zero-height fragmentainer. This can result in a different consumed block
+ // size when used for legacy. This difference is represented by
+ // |consumed_block_size_legacy_adjustment_|.
+ LayoutUnit ConsumedBlockSizeForLegacy() const {
+ return consumed_block_size_ + consumed_block_size_legacy_adjustment_;
+ }
+
// A unique identifier for a fragment that generates a break token. This is
// unique within the generating layout input node. The break token of the
// first fragment gets 0, then second 1, and so on. Note that we don't "count"
@@ -168,6 +179,7 @@ class CORE_EXPORT NGBlockBreakToken final : public NGBreakToken {
private:
LayoutUnit consumed_block_size_;
+ LayoutUnit consumed_block_size_legacy_adjustment_;
unsigned sequence_number_ = 0;
wtf_size_t num_children_;
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 bb03dee8226..b348142701c 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
@@ -761,9 +761,9 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
// <div contenteditable></div>, <input type="button" value="">
if (container_builder_.HasSeenAllChildren() &&
HasLineEvenIfEmpty(Node().GetLayoutBox())) {
- intrinsic_block_size_ +=
- std::max(intrinsic_block_size_,
- Node().GetLayoutBox()->LogicalHeightForEmptyLine());
+ intrinsic_block_size_ =
+ std::max(intrinsic_block_size_, BorderScrollbarPadding().block_start +
+ Node().EmptyLineBlockSize());
if (container_builder_.IsInitialColumnBalancingPass()) {
container_builder_.PropagateTallestUnbreakableBlockSize(
intrinsic_block_size_);
@@ -946,11 +946,7 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
if (ConstraintSpace().IsTableCell())
FinalizeForTableCell(unconstrained_intrinsic_block_size);
- // We only finalize for fragmentation if the fragment has a BFC block offset.
- // This may occur with a zero block size fragment. We need to know the BFC
- // block offset to determine where the fragmentation line is relative to us.
- if (UNLIKELY(container_builder_.BfcBlockOffset() &&
- InvolvedInBlockFragmentation(container_builder_))) {
+ if (UNLIKELY(InvolvedInBlockFragmentation(container_builder_))) {
NGBreakStatus status = FinalizeForFragmentation();
if (status != NGBreakStatus::kContinue) {
if (status == NGBreakStatus::kNeedsEarlierBreak)
@@ -989,10 +985,6 @@ bool NGBlockLayoutAlgorithm::TryReuseFragmentsFromCache(
NGPreviousInflowPosition* previous_inflow_position,
scoped_refptr<const NGInlineBreakToken>* inline_break_token_out) {
DCHECK(previous_result_);
- DCHECK(!inline_node.IsEmptyInline());
- DCHECK(container_builder_.BfcBlockOffset());
- DCHECK(previous_inflow_position->margin_strut.IsEmpty());
- DCHECK(!previous_inflow_position->self_collapsing_child_had_clearance);
const auto& previous_fragment =
To<NGPhysicalBoxFragment>(previous_result_->PhysicalFragment());
@@ -1033,6 +1025,13 @@ bool NGBlockLayoutAlgorithm::TryReuseFragmentsFromCache(
return false;
}
+ // To reach here we mustn't have any adjoining objects, and the first line
+ // must have content. Resolving the BFC block-offset here should never fail.
+ DCHECK(!abort_when_bfc_block_offset_updated_);
+ bool success = ResolveBfcBlockOffset(previous_inflow_position);
+ DCHECK(success);
+ DCHECK(container_builder_.BfcBlockOffset());
+
DCHECK_GT(result.line_count, 0u);
DCHECK(!max_lines || result.line_count <= max_lines);
if (lines_until_clamp_) {
@@ -1599,11 +1598,8 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::HandleInflow(
is_non_empty_inline = !child_inline_node->IsEmptyInline();
// Add reusable line boxes from |previous_result_| if any.
- if (is_non_empty_inline && !child_break_token && previous_result_) {
- if (!ResolveBfcBlockOffset(previous_inflow_position))
- return NGLayoutResult::kBfcBlockOffsetResolved;
- DCHECK(container_builder_.BfcBlockOffset());
-
+ if (!abort_when_bfc_block_offset_updated_ && !child_break_token &&
+ previous_result_) {
DCHECK(!*previous_inline_break_token);
if (TryReuseFragmentsFromCache(*child_inline_node,
previous_inflow_position,
@@ -1722,7 +1718,7 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow(
return NGLayoutResult::kBfcBlockOffsetResolved;
}
- // We have special behaviour for a self-collapsing child which gets pushed
+ // We have special behavior for a self-collapsing child which gets pushed
// down due to clearance, see comment inside |ComputeInflowPosition|.
bool self_collapsing_child_had_clearance =
is_self_collapsing && has_clearance_past_adjoining_floats;
@@ -1888,26 +1884,31 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow(
NGFragment fragment(ConstraintSpace().GetWritingDirection(),
physical_fragment);
- LogicalOffset logical_offset = CalculateLogicalOffset(
- fragment, layout_result->BfcLineOffset(), child_bfc_block_offset);
- if (UNLIKELY(child.IsSliderThumb()))
- logical_offset = AdjustSliderThumbInlineOffset(fragment, logical_offset);
+ const absl::optional<LayoutUnit> line_box_bfc_block_offset =
+ layout_result->LineBoxBfcBlockOffset();
- if (ConstraintSpace().HasBlockFragmentation() &&
- container_builder_.BfcBlockOffset() && child_bfc_block_offset) {
- // Floats only cause container separation for the outermost block child that
- // gets pushed down (the container and the child may have adjoining
- // block-start margins).
- bool has_container_separation =
- has_processed_first_child_ || (layout_result->IsPushedByFloats() &&
- !container_builder_.IsPushedByFloats());
- NGBreakStatus break_status = BreakBeforeChildIfNeeded(
- child, *layout_result, previous_inflow_position,
- *child_bfc_block_offset, has_container_separation);
- if (break_status == NGBreakStatus::kBrokeBefore)
- return NGLayoutResult::kSuccess;
- if (break_status == NGBreakStatus::kNeedsEarlierBreak)
- return NGLayoutResult::kNeedsEarlierBreak;
+ if (ConstraintSpace().HasBlockFragmentation()) {
+ if (container_builder_.BfcBlockOffset() && child_bfc_block_offset) {
+ bool is_line_box_pushed_by_floats =
+ line_box_bfc_block_offset &&
+ *line_box_bfc_block_offset > *child_bfc_block_offset;
+
+ // Floats only cause container separation for the outermost block child
+ // that gets pushed down (the container and the child may have adjoining
+ // block-start margins).
+ bool has_container_separation =
+ has_processed_first_child_ ||
+ (!container_builder_.IsPushedByFloats() &&
+ (layout_result->IsPushedByFloats() || is_line_box_pushed_by_floats));
+ NGBreakStatus break_status = BreakBeforeChildIfNeeded(
+ child, *layout_result, previous_inflow_position,
+ line_box_bfc_block_offset.value_or(*child_bfc_block_offset),
+ has_container_separation);
+ if (break_status == NGBreakStatus::kBrokeBefore)
+ return NGLayoutResult::kSuccess;
+ if (break_status == NGBreakStatus::kNeedsEarlierBreak)
+ return NGLayoutResult::kNeedsEarlierBreak;
+ }
if (inline_child_layout_context) {
for (auto token : inline_child_layout_context->PropagatedBreakTokens()) {
@@ -1918,6 +1919,14 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow(
}
}
+ if (line_box_bfc_block_offset)
+ child_bfc_block_offset = line_box_bfc_block_offset;
+
+ LogicalOffset logical_offset = CalculateLogicalOffset(
+ fragment, layout_result->BfcLineOffset(), child_bfc_block_offset);
+ if (UNLIKELY(child.IsSliderThumb()))
+ logical_offset = AdjustSliderThumbInlineOffset(fragment, logical_offset);
+
if (!PositionOrPropagateListMarker(*layout_result, &logical_offset,
previous_inflow_position))
return NGLayoutResult::kBfcBlockOffsetResolved;
@@ -1957,9 +1966,12 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow(
// the spanner to the column layout algorithm, so that it can take care of it.
if (UNLIKELY(ConstraintSpace().IsInColumnBfc())) {
if (NGBlockNode spanner_node = layout_result->ColumnSpanner()) {
- DCHECK(container_builder_.HasInflowChildBreakInside());
+ DCHECK(container_builder_.HasInflowChildBreakInside() ||
+ !physical_fragment.IsBox());
container_builder_.SetColumnSpanner(spanner_node);
}
+ } else {
+ DCHECK(!layout_result->ColumnSpanner());
}
// Update |lines_until_clamp_| from the LayoutResult.
@@ -2044,7 +2056,7 @@ NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition(
bool is_self_collapsing = layout_result.IsSelfCollapsing();
if (is_self_collapsing) {
- // The default behaviour for self-collapsing children is they just pass
+ // The default behavior for self-collapsing children is they just pass
// through the previous inflow position.
logical_block_offset = previous_inflow_position.logical_block_offset;
@@ -2257,9 +2269,9 @@ void NGBlockLayoutAlgorithm::FinalizeForTableCell(
}
LayoutUnit NGBlockLayoutAlgorithm::FragmentainerSpaceAvailable() const {
- DCHECK(container_builder_.BfcBlockOffset());
return FragmentainerSpaceAtBfcStart(ConstraintSpace()) -
- *container_builder_.BfcBlockOffset();
+ container_builder_.BfcBlockOffset().value_or(
+ ConstraintSpace().ExpectedBfcBlockOffset());
}
void NGBlockLayoutAlgorithm::ConsumeRemainingFragmentainerSpace(
@@ -2305,35 +2317,8 @@ NGBreakStatus NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
}
if (container_builder_.IsFragmentainerBoxType()) {
- // We're building fragmentainers. Finish fragmentation on our own, since
- // special-rules apply.
- LayoutUnit consumed_block_size =
- BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
- if (ConstraintSpace().HasKnownFragmentainerBlockSize()) {
- // Just copy the block-size from the constraint space. Calculating the
- // size the regular way would cause some problems with overflow. For one,
- // we don't want to produce a break token if there's no child content that
- // requires it. When we lay out, we use FragmentainerCapacity(), so this
- // is what we need to add to consumed block-size for the next break
- // token. The fragment block-size itself will be based directly on the
- // fragmentainer size from the constraint space, though.
- container_builder_.SetFragmentBlockSize(
- ConstraintSpace().FragmentainerBlockSize());
- container_builder_.SetConsumedBlockSize(
- consumed_block_size + FragmentainerCapacity(ConstraintSpace()));
- } else {
- // When we are in the initial column balancing pass, use the block-size
- // calculated by the algorithm. Since any previously consumed block-size
- // is already baked in (in order to correctly honor specified block-size
- // (which makes sense to everyone but fragmentainers)), we need to extract
- // it again now.
- LayoutUnit fragments_total_block_size =
- container_builder_.FragmentsTotalBlockSize();
- container_builder_.SetFragmentBlockSize(fragments_total_block_size -
- consumed_block_size);
- container_builder_.SetConsumedBlockSize(fragments_total_block_size);
- }
- return NGBreakStatus::kContinue;
+ return FinishFragmentationForFragmentainer(ConstraintSpace(),
+ &container_builder_);
}
LayoutUnit space_left = kIndefiniteSize;
@@ -2532,7 +2517,7 @@ NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
/* is_new_fc */ false);
builder.SetAvailableSize(ChildAvailableSize());
builder.SetPercentageResolutionSize(child_percentage_size_);
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
NGConstraintSpace space = builder.ToConstraintSpace();
const auto block_child = To<NGBlockNode>(child);
@@ -2557,11 +2542,8 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
const absl::optional<LayoutUnit> child_bfc_block_offset,
bool has_clearance_past_adjoining_floats,
LayoutUnit block_start_annotation_space) {
- const ComputedStyle& style = Style();
const ComputedStyle& child_style = child.Style();
- const auto child_writing_direction = child.IsInline()
- ? style.GetWritingDirection()
- : child_style.GetWritingDirection();
+ const auto child_writing_direction = child_style.GetWritingDirection();
NGConstraintSpaceBuilder builder(ConstraintSpace(), child_writing_direction,
is_new_fc);
@@ -2571,7 +2553,7 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
child_writing_direction.GetWritingMode())) {
if (!child.GetLayoutBox()->AutoWidthShouldFitContent() &&
!child.IsReplaced() && !child.IsTable())
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
}
builder.SetAvailableSize(child_available_size);
@@ -2581,20 +2563,20 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
if (ConstraintSpace().IsTableCell()) {
builder.SetIsTableCellChild(true);
- // Some scrollable percentage-sized children of table-cells (in the
- // "measure" phase) use their min-size (instead of sizing normally).
+ // Some scrollable percentage-sized children of table-cells use their
+ // min-size (instead of sizing normally).
//
// We only apply this rule if the block size of the containing table cell
- // is considered to be "restricted", though. Otherwise, especially if this
- // is the only child of the cell, and that is the only cell in the row,
- // we'd end up with zero block size.
+ // is considered to be "restricted". Otherwise, especially if this is the
+ // only child of the cell, and that is the only cell in the row, we'd end
+ // up with zero block size.
if (ConstraintSpace().IsRestrictedBlockSizeTableCell() &&
- !ConstraintSpace().IsFixedBlockSize() &&
+ child_percentage_size_.block_size == kIndefiniteSize &&
!child.ShouldBeConsideredAsReplaced() &&
child_style.LogicalHeight().IsPercentOrCalc() &&
(child_style.OverflowBlockDirection() == EOverflow::kAuto ||
child_style.OverflowBlockDirection() == EOverflow::kScroll))
- builder.SetIsMeasuringRestrictedBlockSizeTableCellChild();
+ builder.SetIsRestrictedBlockSizeTableCellChild();
}
bool has_bfc_block_offset = container_builder_.BfcBlockOffset().has_value();
@@ -2606,16 +2588,16 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
if (child_bfc_block_offset && !is_new_fc)
builder.SetForcedBfcBlockOffset(*child_bfc_block_offset);
- if (has_bfc_block_offset && child.IsBlock()) {
+ if (has_bfc_block_offset) {
// Typically we aren't allowed to look at the previous layout result within
// a layout algorithm. However this is fine (honest), as it is just a hint
// to the child algorithm for where floats should be placed. If it doesn't
// have this flag, or gets this estimate wrong, it'll relayout with the
// appropriate "forced" BFC block-offset.
- if (const NGLayoutResult* previous_result =
- child.GetLayoutBox()->GetCachedLayoutResult()) {
- const NGConstraintSpace& prev_space =
- previous_result->GetConstraintSpaceForCaching();
+ if (child.IsBlock() && child.GetLayoutBox()->GetCachedLayoutResult()) {
+ const auto& prev_space = child.GetLayoutBox()
+ ->GetCachedLayoutResult()
+ ->GetConstraintSpaceForCaching();
// To increase the hit-rate we adjust the previous "optimistic"/"forced"
// BFC block-offset by how much the child has shifted from the previous
@@ -2938,7 +2920,7 @@ void NGBlockLayoutAlgorithm::HandleRubyText(NGBlockNode ruby_text_child) {
builder.SetAvailableSize(ChildAvailableSize());
if (IsParallelWritingMode(ConstraintSpace().GetWritingMode(),
rt_style.GetWritingMode()))
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
scoped_refptr<const NGLayoutResult> result =
ruby_text_child.Layout(builder.ToConstraintSpace(), break_token.get());
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 075b0a660e3..5dd6b1e151b 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
@@ -186,7 +186,7 @@ TEST_F(NGBlockLayoutAlgorithmTest, MinInlineSizeCaching) {
}
TEST_F(NGBlockLayoutAlgorithmTest, PercentageBlockSizeQuirkDescendantsCaching) {
- // Quirks mode triggers the interesting parent-child %-resolution behaviour.
+ // Quirks mode triggers the interesting parent-child %-resolution behavior.
GetDocument().SetCompatibilityMode(Document::kQuirksMode);
SetBodyInnerHTML(R"HTML(
@@ -227,7 +227,7 @@ TEST_F(NGBlockLayoutAlgorithmTest, PercentageBlockSizeQuirkDescendantsCaching) {
/* is_new_formatting_context */ false);
builder.SetAvailableSize(size);
builder.SetPercentageResolutionSize(size);
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
return builder.ToConstraintSpace();
};
@@ -260,11 +260,11 @@ TEST_F(NGBlockLayoutAlgorithmTest, PercentageBlockSizeQuirkDescendantsCaching) {
EXPECT_EQ(run_test("box3"), nullptr);
// Test 4: A flexbox (legacy descendant), which doesn't use the quirks mode
- // behaviour.
+ // behavior.
EXPECT_NE(run_test("box4"), nullptr);
// Test 5: A flexbox (legacy descendant), which doesn't use the quirks mode
- // behaviour, but is %-sized.
+ // behavior, but is %-sized.
EXPECT_EQ(run_test("box5"), nullptr);
// Test 6: An OOF positioned descentant which has a %-height, should not
@@ -272,11 +272,11 @@ TEST_F(NGBlockLayoutAlgorithmTest, PercentageBlockSizeQuirkDescendantsCaching) {
EXPECT_NE(run_test("box6"), nullptr);
// Test 7: A replaced element (legacy descendant), shouldn't use the quirks
- // mode behaviour.
+ // mode behavior.
EXPECT_NE(run_test("box7"), nullptr);
// Test 8: A replaced element (legacy descendant), shouldn't use the quirks
- // mode behaviour, but is %-sized.
+ // mode behavior, but is %-sized.
EXPECT_EQ(run_test("box8"), nullptr);
}
@@ -856,7 +856,7 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase7) {
}
// An empty block level element (with margins collapsing through it) has
-// non-trivial behaviour with margins collapsing.
+// non-trivial behavior with margins collapsing.
TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsEmptyBlockWithClearance) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -969,15 +969,15 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsEmptyBlockWithClearance) {
// 40 = (90 + (-70 + 20)).
EXPECT_EQ(LayoutUnit(40), abs->Location().Y());
- // #inflow has similar behaviour to #abs, but includes its margin.
+ // #inflow has similar behavior to #abs, but includes its margin.
// 70 = (90 + (-70 + 50))
EXPECT_EQ(LayoutUnit(70), inflow->Location().Y());
// A margin strut which resolves to 60 (-10 + 70) means that #zero doesn't
- // get adjusted to clear the float, and we have normal behaviour.
+ // get adjusted to clear the float, and we have normal behavior.
//
// NOTE: This case below has wildly different results on different browsers,
- // we may have to change the behaviour here in the future for web compat.
+ // we may have to change the behavior here in the future for web compat.
run_test(
/* #zero-top margin-bottom */ Length::Fixed(0),
/* #zero-inner margin-top */ Length::Fixed(70),
@@ -992,7 +992,7 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsEmptyBlockWithClearance) {
// 50 = (0 + (-20 + 70)).
EXPECT_EQ(LayoutUnit(50), abs->Location().Y());
- // #inflow has similar behaviour to #abs, but includes its margin.
+ // #inflow has similar behavior to #abs, but includes its margin.
// 60 = (0 + (-20 + 80))
EXPECT_EQ(LayoutUnit(60), inflow->Location().Y());
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 b83dc8eeb6c..613e03abe92 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/css/style_engine.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/html_marquee_element.h"
@@ -30,6 +31,7 @@
#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.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/mathml/ng_math_fraction_layout_algorithm.h"
@@ -48,6 +50,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.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_disable_side_effects_scope.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
@@ -178,7 +181,6 @@ NOINLINE void DetermineAlgorithmAndRun(const NGLayoutAlgorithmParams& params,
RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
CreateAlgorithmAndRun<NGGridLayoutAlgorithm>(params, callback);
} else if (box.IsLayoutReplaced()) {
- DCHECK(RuntimeEnabledFeatures::LayoutNGReplacedEnabled());
CreateAlgorithmAndRun<NGReplacedLayoutAlgorithm>(params, callback);
} else if (box.IsLayoutNGFieldset()) {
CreateAlgorithmAndRun<NGFieldsetLayoutAlgorithm>(params, callback);
@@ -275,11 +277,11 @@ void SetupBoxLayoutExtraInput(const NGConstraintSpace& space,
if (space.IsFixedBlockSize()) {
input->override_block_size = space.AvailableSize().block_size;
input->is_override_block_size_definite =
- !space.IsFixedBlockSizeIndefinite();
+ !space.IsInitialBlockSizeIndefinite();
}
- input->stretch_inline_size_if_auto = space.StretchInlineSizeIfAuto();
+ input->stretch_inline_size_if_auto = space.IsInlineAutoBehaviorStretch();
input->stretch_block_size_if_auto =
- space.StretchBlockSizeIfAuto() &&
+ space.IsBlockAutoBehaviorStretch() &&
space.AvailableSize().block_size != kIndefiniteSize;
}
@@ -365,7 +367,8 @@ inline LayoutPoint ToLayoutPoint(
// Add the amount of block-size previously (in previous fragmentainers)
// consumed by the container fragment. This will map the child's offset
// nicely into the flow thread coordinate system used by the legacy engine.
- LayoutUnit consumed = previous_container_break_token->ConsumedBlockSize();
+ LayoutUnit consumed =
+ previous_container_break_token->ConsumedBlockSizeForLegacy();
if (container_fragment.Style().IsHorizontalWritingMode())
offset.top += consumed;
else
@@ -414,8 +417,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
// We may have to update the margins on box_; we reuse the layout result
// even if a percentage margin may have changed.
- if (UNLIKELY(Style().MayHaveMargin() && !constraint_space.IsTableCell()))
- box_->SetMargin(ComputePhysicalMargins(constraint_space, Style()));
+ UpdateMarginPaddingInfoIfNeeded(constraint_space);
UpdateShapeOutsideInfoIfNeeded(
*layout_result, constraint_space.PercentageResolutionInlineSize());
@@ -544,7 +546,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
FinishLayout(block_flow, constraint_space, break_token, layout_result);
#if DCHECK_IS_ON()
- scrollbar_changed.erase(box_);
+ scrollbar_changed.erase(box_);
#endif
}
@@ -672,6 +674,11 @@ void NGBlockNode::FinishLayout(
const NGConstraintSpace& constraint_space,
const NGBlockBreakToken* break_token,
scoped_refptr<const NGLayoutResult> layout_result) const {
+ // Computing MinMax after layout. Do not modify the |LayoutObject| tree, paint
+ // properties, and other global states.
+ if (NGDisableSideEffectsScope::IsDisabled())
+ return;
+
// If we abort layout and don't clear the cached layout-result, we can end
// up in a state where the layout-object tree doesn't match fragment tree
// referenced by this layout-result.
@@ -684,7 +691,6 @@ void NGBlockNode::FinishLayout(
To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
if (box_->IsLayoutReplaced()) {
- DCHECK(RuntimeEnabledFeatures::LayoutNGReplacedEnabled());
DCHECK(CanUseNewLayout());
// NG replaced elements are painted with legacy painters. We need to force
// a legacy "layout" so that paint invalidation flags are updated. But we
@@ -703,7 +709,10 @@ void NGBlockNode::FinishLayout(
input.override_inline_size = fragment.InlineSize();
input.override_block_size = fragment.BlockSize();
box_->ComputeAndSetBlockDirectionMargins(box_->ContainingBlock());
- box_->ForceLayout();
+ if (box_->NeedsLayout())
+ box_->LayoutIfNeeded();
+ else
+ box_->ForceLayout();
DCHECK_EQ(box_->Size(), physical_fragment.Size().ToLayoutSize())
<< "Legacy layout was supposed to use the size that NG computed";
}
@@ -766,6 +775,22 @@ MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
if (IsListItem())
To<LayoutNGListItem>(box_)->UpdateMarkerTextIfNeeded();
+ const bool is_in_perform_layout = box_->GetFrameView()->IsInPerformLayout();
+ // In some scenarios, GridNG will run layout on its children during
+ // MinMaxSizes computation. Instead of running (and possible caching incorrect
+ // results), when we're not performing layout, just use border + padding.
+ if (!is_in_perform_layout && IsGrid()) {
+ const NGFragmentGeometry fragment_geometry =
+ CalculateInitialFragmentGeometry(constraint_space, *this,
+ /* is_intrinsic */ true);
+ const NGBoxStrut border_padding =
+ fragment_geometry.border + fragment_geometry.padding;
+ MinMaxSizes sizes;
+ sizes.min_size = border_padding.InlineSum();
+ sizes.max_size = sizes.min_size;
+ return MinMaxSizesResult(sizes, /* depends_on_block_constraints */ false);
+ }
+
bool is_orthogonal_flow_root =
!IsParallelWritingMode(container_writing_mode, Style().GetWritingMode());
@@ -779,12 +804,19 @@ MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
// Some other areas of the code can query the intrinsic-sizes while outside
// of the layout phase.
// TODO(ikilpatrick): Remove this check.
- if (!box_->GetFrameView()->IsInPerformLayout()) {
+ if (!is_in_perform_layout) {
sizes = ComputeMinMaxSizesFromLegacy(type, constraint_space);
return MinMaxSizesResult(sizes,
/* depends_on_block_constraints */ false);
}
+ // If we're computing MinMax after layout, we need to disable side effects
+ // so that |Layout| does not update the |LayoutObject| tree and other global
+ // states.
+ absl::optional<NGDisableSideEffectsScope> disable_side_effects;
+ if (!GetLayoutBox()->NeedsLayout())
+ disable_side_effects.emplace();
+
scoped_refptr<const NGLayoutResult> layout_result =
Layout(constraint_space);
DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
@@ -801,7 +833,7 @@ MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
Style().LogicalMinHeight().IsPercentOrCalc() ||
Style().LogicalMaxHeight().IsPercentOrCalc() ||
(Style().LogicalHeight().IsAuto() &&
- constraint_space.StretchBlockSizeIfAuto());
+ constraint_space.IsBlockAutoBehaviorStretch());
};
if (!Style().AspectRatio().IsAuto() && !IsReplaced() &&
@@ -935,7 +967,7 @@ MinMaxSizes NGBlockNode::ComputeMinMaxSizesFromLegacy(
}
NGLayoutInputNode NGBlockNode::NextSibling() const {
- LayoutObject* next_sibling = GetLayoutObjectForNextSiblingNode(box_);
+ LayoutObject* next_sibling = box_->NextSibling();
// We may have some LayoutInline(s) still within the tree (due to treating
// inline-level floats and/or OOF-positioned nodes as block-level), we need
@@ -1001,19 +1033,15 @@ NGBlockNode NGBlockNode::GetRenderedLegend() const {
NGBlockNode NGBlockNode::GetFieldsetContent() const {
if (!IsFieldsetContainer())
return nullptr;
- auto* child = GetLayoutObjectForFirstChildNode(To<LayoutBlock>(box_));
- if (!child)
- return nullptr;
- return NGBlockNode(To<LayoutBox>(child));
+ return NGBlockNode(
+ To<LayoutNGFieldset>(box_)->FindAnonymousFieldsetContentBox());
}
bool NGBlockNode::CanUseNewLayout(const LayoutBox& box) {
DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled());
if (box.ForceLegacyLayout())
return false;
- return box.IsLayoutNGMixin() ||
- (box.IsLayoutReplaced() &&
- RuntimeEnabledFeatures::LayoutNGReplacedEnabled());
+ return box.IsLayoutNGMixin() || box.IsLayoutReplaced();
}
bool NGBlockNode::CanUseNewLayout() const {
@@ -1070,8 +1098,9 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
// Update logical height, unless this fragment is past the block-end of the
// generating node (happens with overflow).
if (previous_break_token && !previous_break_token->IsAtBlockEnd()) {
- box_->SetLogicalHeight(fragment_logical_size.block_size +
- previous_break_token->ConsumedBlockSize());
+ box_->SetLogicalHeight(
+ fragment_logical_size.block_size +
+ previous_break_token->ConsumedBlockSizeForLegacy());
} else {
DCHECK_EQ(fragment_logical_size.block_size, LayoutUnit());
}
@@ -1080,21 +1109,7 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
// 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.
- if (UNLIKELY(box_->IsTableCell())) {
- // Table-cell margins compute to zero.
- box_->SetMargin(NGPhysicalBoxStrut());
- } else {
- box_->SetMargin(ComputePhysicalMargins(constraint_space, Style()));
- }
-
- // We copy back the %-size so that |LayoutBoxModelObject::ComputedCSSPadding|
- // is able to return the correct value. This isn't ideal, but eventually
- // we'll answer these queries from the fragment.
- const auto* containing_block = box_->ContainingBlock();
- if (UNLIKELY(containing_block && containing_block->IsLayoutNGGrid())) {
- box_->SetOverrideContainingBlockContentLogicalWidth(
- constraint_space.PercentageResolutionInlineSizeForParentWritingMode());
- }
+ UpdateMarginPaddingInfoIfNeeded(constraint_space);
auto* block_flow = DynamicTo<LayoutBlockFlow>(box_);
LayoutMultiColumnFlowThread* flow_thread = GetFlowThread(block_flow);
@@ -1230,6 +1245,7 @@ void NGBlockNode::PlaceChildrenInFlowThread(
LayoutUnit flow_thread_offset;
bool has_processed_first_column_in_flow_thread = false;
bool should_append_fragmentainer_group = false;
+ bool should_expand_last_set = false;
if (IsResumingLayout(previous_container_break_token)) {
// This multicol container is nested inside another fragmentation context,
@@ -1244,7 +1260,8 @@ void NGBlockNode::PlaceChildrenInFlowThread(
// We also create break tokens for spanners, so we need to check.
if (token->InputNode() == *this) {
previous_column_break_token = token;
- flow_thread_offset = previous_column_break_token->ConsumedBlockSize();
+ flow_thread_offset =
+ previous_column_break_token->ConsumedBlockSizeForLegacy();
// We're usually resuming layout into a column set that has already been
// started in an earlier fragment, but in some cases the column set
@@ -1300,14 +1317,28 @@ void NGBlockNode::PlaceChildrenInFlowThread(
// found a spanner first, we won't do that, since we'll move to another
// column set (if there's more column content at all).
should_append_fragmentainer_group = false;
+
+ // If there is no column set after the spanner, we should expand the last
+ // column set to encompass any columns that were created after the
+ // spanner.
+ should_expand_last_set = !pending_column_set;
continue;
}
DCHECK(!child_box);
-
LogicalSize logical_size = converter.ToLogical(child_fragment.Size());
- logical_size.block_size =
- ClampedToValidFragmentainerCapacity(logical_size.block_size);
+
+ // TODO(layout-dev): This should really be checking if there are any
+ // descendants that take up block space rather than if it has overflow. In
+ // other words, we would still want to clamp a zero height fragmentainer if
+ // it had content with zero inline size and non-zero block size. This would
+ // likely require us to store an extra flag on NGPhysicalBoxFragment.
+ if (child_fragment.HasLayoutOverflow()) {
+ // Don't clamp the fragmentainer to a block size of 1 if it is truly a
+ // zero-height column.
+ logical_size.block_size =
+ ClampedToValidFragmentainerCapacity(logical_size.block_size);
+ }
if (has_processed_first_column_in_flow_thread) {
// Non-uniform fragmentainer widths not supported by legacy layout.
@@ -1357,6 +1388,15 @@ void NGBlockNode::PlaceChildrenInFlowThread(
// same column set as we used there.
flow_thread->AppendNewFragmentainerGroupFromNG();
should_append_fragmentainer_group = false;
+ } else if (should_expand_last_set) {
+ if (logical_size.block_size > LayoutUnit()) {
+ auto* last_set = flow_thread->LastMultiColumnSet();
+ last_set->LastFragmentainerGroup().ExtendColumnBlockSizeFromNG(
+ logical_size.block_size);
+ last_set->EndFlow(flow_thread_offset + logical_size.block_size);
+ last_set->FinishLayoutFromNG();
+ }
+ should_expand_last_set = false;
}
flow_thread->SetCurrentColumnBlockSizeFromNG(logical_size.block_size);
@@ -1401,13 +1441,25 @@ void NGBlockNode::CopyChildFragmentPosition(
layout_box->SetLocationAndUpdateOverflowControlsIfNeeded(point);
}
+void NGBlockNode::MakeRoomForExtraColumns(LayoutUnit block_size) const {
+ auto* block_flow = DynamicTo<LayoutBlockFlow>(GetLayoutBox());
+ DCHECK(block_flow && block_flow->MultiColumnFlowThread());
+ MultiColumnFragmentainerGroup& last_group =
+ block_flow->MultiColumnFlowThread()
+ ->LastMultiColumnSet()
+ ->LastFragmentainerGroup();
+ last_group.ExtendLogicalBottomInFlowThread(block_size);
+}
+
void NGBlockNode::CopyFragmentItemsToLayoutBox(
const NGPhysicalBoxFragment& container,
const NGFragmentItems& items,
const NGBlockBreakToken* previous_break_token) const {
LayoutUnit previously_consumed_block_size;
- if (previous_break_token)
- previously_consumed_block_size = previous_break_token->ConsumedBlockSize();
+ if (previous_break_token) {
+ previously_consumed_block_size =
+ previous_break_token->ConsumedBlockSizeForLegacy();
+ }
bool initial_container_is_flipped = Style().IsFlippedBlocksWritingMode();
for (NGInlineCursor cursor(container, items); cursor; cursor.MoveToNext()) {
if (const NGPhysicalBoxFragment* child = cursor.Current().BoxFragment()) {
@@ -1596,12 +1648,15 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
box_->GetNGPaginationBreakability() == LayoutBox::kForbidBreaks);
scoped_refptr<const NGLayoutResult> layout_result =
- box_->GetCachedLayoutResult();
+ constraint_space.CacheSlot() == NGCacheSlot::kMeasure
+ ? box_->GetCachedMeasureResult()
+ : box_->GetCachedLayoutResult();
+ if (constraint_space.CacheSlot() == NGCacheSlot::kLayout && !layout_result)
+ layout_result = box_->GetCachedMeasureResult();
if (UNLIKELY(DevtoolsReadonlyLayoutScope::InDevtoolsLayout())) {
DCHECK(layout_result);
DCHECK(!box_->NeedsLayout());
- DCHECK(!box_->NeedsLayoutOverflowRecalc());
DCHECK(MaySkipLegacyLayout(*this, *layout_result, constraint_space));
return layout_result;
}
@@ -1671,19 +1726,23 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
CopyBaselinesFromLegacyLayout(constraint_space, &builder);
layout_result = builder.ToBoxFragment();
- box_->SetCachedLayoutResult(layout_result);
+ // When side effects are disabled, it's not possible to disable side effects
+ // completely for legacy, but at least keep the fragment tree unaffected.
+ if (!NGDisableSideEffectsScope::IsDisabled()) {
+ box_->SetCachedLayoutResult(layout_result);
- // If |SetCachedLayoutResult| did not update cached |LayoutResult|,
- // |NeedsLayout()| flag should not be cleared.
- if (needed_layout) {
- if (layout_result != box_->GetCachedLayoutResult()) {
- // TODO(kojii): If we failed to update CachedLayoutResult for other
- // reasons, we'd like to review it.
- NOTREACHED();
- box_->SetNeedsLayout(layout_invalidation_reason::kUnknown);
+ // If |SetCachedLayoutResult| did not update cached |LayoutResult|,
+ // |NeedsLayout()| flag should not be cleared.
+ if (needed_layout) {
+ if (layout_result != box_->GetCachedLayoutResult()) {
+ // TODO(kojii): If we failed to update CachedLayoutResult for other
+ // reasons, we'd like to review it.
+ NOTREACHED();
+ box_->SetNeedsLayout(layout_invalidation_reason::kUnknown);
+ }
}
}
- } else if (layout_result) {
+ } else if (layout_result && !NGDisableSideEffectsScope::IsDisabled()) {
// OOF-positioned nodes have a two-tier cache, and their layout results
// must always contain the correct percentage resolution size.
// See |NGBlockNode::CachedLayoutResultForOutOfFlowPositioned|.
@@ -1769,7 +1828,28 @@ LayoutUnit NGBlockNode::AtomicInlineBaselineFromLegacyLayout(
return box_->InlineBlockBaseline(line_direction);
}
-// Floats can optionally have a shape area, specifed by "shape-outside". The
+void NGBlockNode::UpdateMarginPaddingInfoIfNeeded(
+ const NGConstraintSpace& space) const {
+ // Table-cells don't have margins, and aren't grid-items.
+ if (space.IsTableCell())
+ return;
+
+ if (Style().MayHaveMargin())
+ box_->SetMargin(ComputePhysicalMargins(space, Style()));
+
+ if (Style().MayHaveMargin() || Style().MayHavePadding()) {
+ // Copy back the %-size so that |LayoutBoxModelObject::ComputedCSSPadding|
+ // is able to return the correct value. This isn't ideal, but eventually
+ // we'll answer these queries from the fragment.
+ const auto* containing_block = box_->ContainingBlock();
+ if (UNLIKELY(containing_block && containing_block->IsLayoutNGGrid())) {
+ box_->SetOverrideContainingBlockContentLogicalWidth(
+ space.PercentageResolutionInlineSizeForParentWritingMode());
+ }
+ }
+}
+
+// Floats can optionally have a shape area, specified by "shape-outside". The
// current shape machinery requires setting the size of the float after layout
// in the parents writing mode.
void NGBlockNode::UpdateShapeOutsideInfoIfNeeded(
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 bb2aa7cd0f0..2963332d5fe 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_NODE_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
@@ -202,6 +203,9 @@ class CORE_EXPORT NGBlockNode : public NGLayoutInputNode {
return block->HasLineIfEmpty();
return false;
}
+ LayoutUnit EmptyLineBlockSize() const {
+ return box_->LogicalHeightForEmptyLine();
+ }
// After we run the layout algorithm, this function copies back the fragment
// position to the layout box.
@@ -211,6 +215,11 @@ class CORE_EXPORT NGBlockNode : public NGLayoutInputNode {
const NGPhysicalBoxFragment& container_fragment,
const NGBlockBreakToken* previous_container_break_token = nullptr) const;
+ // If extra columns are added after a multicol has been written back to
+ // legacy, for example for an OOF positioned element, we need to update the
+ // legacy flow thread to encompass those extra columns.
+ void MakeRoomForExtraColumns(LayoutUnit block_size) const;
+
String ToString() const;
private:
@@ -256,6 +265,8 @@ class CORE_EXPORT NGBlockNode : public NGLayoutInputNode {
LayoutUnit AtomicInlineBaselineFromLegacyLayout(
const NGConstraintSpace&) const;
+ void UpdateMarginPaddingInfoIfNeeded(const NGConstraintSpace&) const;
+
void UpdateShapeOutsideInfoIfNeeded(
const NGLayoutResult&,
LayoutUnit percentage_resolution_inline_size) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
index 211925fe467..909323a56c9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
@@ -13,9 +13,6 @@ namespace blink {
FontHeight NGBoxFragment::BaselineMetrics(const NGLineBoxStrut& margins,
FontBaseline baseline_type) const {
- DCHECK(physical_fragment_.IsAtomicInline() ||
- physical_fragment_.IsListMarker());
-
// For checkbox and radio controls, we always use the border edge instead of
// the margin edge.
if (physical_fragment_.Style().IsCheckboxOrRadioPart()) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
index d9ed1eee15a..d944e6aaeb9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.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"
@@ -28,7 +29,14 @@ class CORE_EXPORT NGBoxFragment final : public NGFragment {
}
LayoutUnit FirstBaselineOrSynthesize() const {
- return FirstBaseline().value_or(BlockSize());
+ if (auto first_baseline = FirstBaseline())
+ return *first_baseline;
+
+ // TODO(layout-dev): See |NGBoxFragment::BaselineOrSynthesize()|.
+ if (writing_direction_.GetWritingMode() == WritingMode::kHorizontalTb)
+ return BlockSize();
+
+ return BlockSize() / 2;
}
// Returns the baseline for this fragment wrt. the parent writing mode. Will
@@ -48,7 +56,16 @@ class CORE_EXPORT NGBoxFragment final : public NGFragment {
}
LayoutUnit BaselineOrSynthesize() const {
- return Baseline().value_or(BlockSize());
+ if (auto baseline = Baseline())
+ return *baseline;
+
+ // TODO(layout-dev): With a vertical writing-mode, and "text-orientation:
+ // sideways" we should also synthesize using the block-end border edge. We
+ // need to pass in the text-orientation (or just parent style) to do this.
+ if (writing_direction_.GetWritingMode() == WritingMode::kHorizontalTb)
+ return BlockSize();
+
+ return BlockSize() / 2;
}
// Compute baseline metrics (ascent/descent) for this box.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
index 3ae06967970..f8beaa4ed5f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -21,84 +21,13 @@
namespace blink {
-namespace {
-
-// std::pair.first points to the start linebox fragment.
-// std::pair.second points to the end linebox fragment.
-using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*,
- const NGPhysicalLineBoxFragment*>;
-
-template <class Items>
-void GatherInlineContainerFragmentsFromItems(
- const Items& items,
- const PhysicalOffset& box_offset,
- NGBoxFragmentBuilder::InlineContainingBlockMap* inline_containing_block_map,
- HashMap<const LayoutObject*, LineBoxPair>* containing_linebox_map) {
- const NGPhysicalLineBoxFragment* linebox = nullptr;
- for (const auto& item : items) {
- // Track the current linebox.
- if (const NGPhysicalLineBoxFragment* current_linebox =
- item->LineBoxFragment()) {
- linebox = current_linebox;
- continue;
- }
-
- // We only care about inlines which have generated a box fragment.
- const NGPhysicalBoxFragment* box = item->BoxFragment();
- if (!box)
- continue;
-
- // The key for the inline is the continuation root if it exists.
- const LayoutObject* key = box->GetLayoutObject();
- if (key->IsLayoutInline() && key->GetNode())
- key = key->ContinuationRoot();
-
- // See if we need the containing block information for this inline.
- auto it = inline_containing_block_map->find(key);
- if (it == inline_containing_block_map->end())
- continue;
-
- absl::optional<NGBoxFragmentBuilder::InlineContainingBlockGeometry>&
- containing_block_geometry = it->value;
- LineBoxPair& containing_lineboxes =
- containing_linebox_map->insert(key, LineBoxPair{nullptr, nullptr})
- .stored_value->value;
- DCHECK(containing_block_geometry.has_value() ||
- !containing_lineboxes.first);
-
- PhysicalRect fragment_rect = item->RectInContainerFragment();
- fragment_rect.offset += box_offset;
- if (containing_lineboxes.first == linebox) {
- // Unite the start rect with the fragment's rect.
- containing_block_geometry->start_fragment_union_rect.Unite(fragment_rect);
- } else if (!containing_lineboxes.first) {
- DCHECK(!containing_lineboxes.second);
- // This is the first linebox we've encountered, initialize the containing
- // block geometry.
- containing_lineboxes.first = linebox;
- containing_lineboxes.second = linebox;
- containing_block_geometry =
- NGBoxFragmentBuilder::InlineContainingBlockGeometry{fragment_rect,
- fragment_rect};
- }
-
- if (containing_lineboxes.second == linebox) {
- // Unite the end rect with the fragment's rect.
- containing_block_geometry->end_fragment_union_rect.Unite(fragment_rect);
- } else if (!linebox->IsEmptyLineBox()) {
- // We've found a new "end" linebox, update the containing block geometry.
- containing_lineboxes.second = linebox;
- containing_block_geometry->end_fragment_union_rect = fragment_rect;
- }
- }
-}
-
-} // namespace
-
void NGBoxFragmentBuilder::AddBreakBeforeChild(
NGLayoutInputNode child,
absl::optional<NGBreakAppeal> appeal,
bool is_forced_break) {
+ // If there's a pre-set break token, we shouldn't be here.
+ DCHECK(!break_token_);
+
if (appeal) {
break_appeal_ = *appeal;
// If we're violating any orphans / widows or
@@ -195,7 +124,7 @@ void NGBoxFragmentBuilder::AddResult(
void NGBoxFragmentBuilder::AddChild(
const NGPhysicalFragment& child,
const LogicalOffset& child_offset,
- const LayoutInline* inline_container,
+ const NGInlineContainer<LogicalOffset>* inline_container,
const NGMarginStrut* margin_strut,
bool is_self_collapsing,
absl::optional<LogicalOffset> relative_offset,
@@ -329,6 +258,9 @@ void NGBoxFragmentBuilder::AddChild(
void NGBoxFragmentBuilder::AddBreakToken(
scoped_refptr<const NGBreakToken> token,
bool is_in_parallel_flow) {
+ // If there's a pre-set break token, we shouldn't be here.
+ DCHECK(!break_token_);
+
DCHECK(token.get());
child_break_tokens_.push_back(std::move(token));
has_inflow_child_break_inside_ |= !is_in_parallel_flow;
@@ -338,10 +270,12 @@ void NGBoxFragmentBuilder::AddOutOfFlowLegacyCandidate(
NGBlockNode node,
const NGLogicalStaticPosition& static_position,
const LayoutInline* inline_container) {
+ if (inline_container)
+ inline_container = To<LayoutInline>(inline_container->ContinuationRoot());
oof_positioned_candidates_.emplace_back(
node, static_position,
- inline_container ? To<LayoutInline>(inline_container->ContinuationRoot())
- : nullptr);
+ NGInlineContainer<LogicalOffset>(inline_container,
+ /* relative_offset */ LogicalOffset()));
}
NGPhysicalFragment::NGBoxType NGBoxFragmentBuilder::BoxType() const {
@@ -452,7 +386,7 @@ scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::ToBoxFragment(
}
#endif
- if (UNLIKELY(node_ && has_block_fragmentation_)) {
+ if (UNLIKELY(has_block_fragmentation_ && !break_token_ && node_)) {
if (last_inline_break_token_)
child_break_tokens_.push_back(std::move(last_inline_break_token_));
if (DidBreakSelf() || HasChildBreakInside())
@@ -473,12 +407,6 @@ scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::ToBoxFragment(
std::move(fragment), this));
}
-scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::Abort(
- NGLayoutResult::EStatus status) {
- return base::AdoptRef(new NGLayoutResult(
- NGLayoutResult::NGBoxFragmentBuilderPassKey(), status, this));
-}
-
LogicalOffset NGBoxFragmentBuilder::GetChildOffset(
const LayoutObject* object) const {
DCHECK(object);
@@ -514,60 +442,6 @@ LogicalOffset NGBoxFragmentBuilder::GetChildOffset(
return LogicalOffset();
}
-void NGBoxFragmentBuilder::ComputeInlineContainerGeometry(
- InlineContainingBlockMap* inline_containing_block_map) {
- if (inline_containing_block_map->IsEmpty())
- return;
-
- // This function requires that we have the final size of the fragment set
- // upon the builder.
- DCHECK_GE(InlineSize(), LayoutUnit());
- DCHECK_GE(FragmentBlockSize(), LayoutUnit());
-
-#if DCHECK_IS_ON()
- // Make sure all entries are a continuation root.
- for (const auto& entry : *inline_containing_block_map)
- DCHECK_EQ(entry.key, entry.key->ContinuationRoot());
-#endif
-
- HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map;
-
- if (items_builder_) {
- // To access the items correctly we need to convert them to the physical
- // coordinate space.
- DCHECK_EQ(items_builder_->GetWritingMode(), GetWritingMode());
- DCHECK_EQ(items_builder_->Direction(), Direction());
- GatherInlineContainerFragmentsFromItems(
- items_builder_->Items(ToPhysicalSize(Size(), GetWritingMode())),
- PhysicalOffset(), inline_containing_block_map, &containing_linebox_map);
- return;
- }
-
- // If we have children which are anonymous block, we might contain split
- // inlines, this can occur in the following example:
- // <div>
- // Some text <span style="position: relative;">text
- // <div>block</div>
- // text </span> text.
- // </div>
- for (const auto& child : children_) {
- if (!child.fragment->IsAnonymousBlock())
- continue;
-
- const auto& child_fragment = To<NGPhysicalBoxFragment>(*child.fragment);
- const auto* items = child_fragment.Items();
- if (!items)
- continue;
-
- const PhysicalOffset child_offset = child.offset.ConvertToPhysical(
- GetWritingDirection(), ToPhysicalSize(Size(), GetWritingMode()),
- child_fragment.Size());
- GatherInlineContainerFragmentsFromItems(items->Items(), child_offset,
- inline_containing_block_map,
- &containing_linebox_map);
- }
-}
-
void NGBoxFragmentBuilder::SetLastBaselineToBlockEndMarginEdgeIfNeeded() {
if (ConstraintSpace()->BaselineAlgorithmType() !=
NGBaselineAlgorithmType::kInlineBlock)
@@ -666,6 +540,7 @@ void NGBoxFragmentBuilder::CheckNoBlockFragmentation() const {
DCHECK(!DidBreakSelf());
DCHECK(!has_forced_break_);
DCHECK_EQ(consumed_block_size_, LayoutUnit());
+ DCHECK_EQ(consumed_block_size_legacy_adjustment_, LayoutUnit());
DCHECK_EQ(minimal_space_shortage_, LayoutUnit::Max());
DCHECK(!initial_break_before_);
DCHECK_EQ(previous_break_after_, EBreakBetween::kAuto);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
index caca2f245ee..f3d74544f92 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_BUILDER_H_
#include "base/dcheck_is_on.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/geometry/box_sides.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
@@ -22,7 +23,6 @@
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -137,8 +137,8 @@ class CORE_EXPORT NGBoxFragmentBuilder final
LayoutUnit FragmentBlockSize() const {
#if DCHECK_IS_ON()
- if (has_block_fragmentation_)
- DCHECK(!block_size_is_for_all_fragments_);
+ DCHECK(!block_size_is_for_all_fragments_ || !has_block_fragmentation_ ||
+ IsInitialColumnBalancingPass());
DCHECK(size_.block_size != kIndefiniteSize);
#endif
return size_.block_size;
@@ -210,7 +210,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
void AddChild(
const NGPhysicalFragment&,
const LogicalOffset&,
- const LayoutInline* inline_container = nullptr,
+ const NGInlineContainer<LogicalOffset>* inline_container = nullptr,
const NGMarginStrut* margin_strut = nullptr,
bool is_self_collapsing = false,
absl::optional<LogicalOffset> relative_offset = absl::nullopt,
@@ -233,6 +233,12 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// building now.
void SetConsumedBlockSize(LayoutUnit size) { consumed_block_size_ = size; }
+ // Set how much to adjust |consumed_block_size_| for legacy write-back. See
+ // NGBlockBreakToken::ConsumedBlockSizeForLegacy() for more details.
+ void SetConsumedBlockSizeLegacyAdjustment(LayoutUnit adjustment) {
+ consumed_block_size_legacy_adjustment_ = adjustment;
+ }
+
// Set how much of the column block-size we've used so far. This will be used
// to determine the block-size of any new columns added by descendant
// out-of-flow positioned elements.
@@ -247,6 +253,18 @@ class CORE_EXPORT NGBoxFragmentBuilder final
sequence_number_ = sequence_number;
}
+ // During regular layout a break token is created at the end of layout, if
+ // required. When re-using a previous fragment and its children, though, we
+ // may want to just re-use the break token as well.
+ void PresetNextBreakToken(scoped_refptr<const NGBreakToken> break_token) {
+ // We should either do block fragmentation as part of normal layout, or
+ // pre-set a break token.
+ DCHECK(!did_break_self_);
+ DCHECK(child_break_tokens_.IsEmpty());
+
+ break_token_ = std::move(break_token);
+ }
+
// Return true if we broke inside this node on our own initiative (typically
// not because of a child break, but rather due to the size of this node).
bool DidBreakSelf() const { return did_break_self_; }
@@ -376,9 +394,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
may_have_descendant_above_block_start_ = b;
}
- void SetColumnSpanner(NGBlockNode spanner) { column_spanner_ = spanner; }
- bool FoundColumnSpanner() const { return !!column_spanner_; }
-
void SetLinesUntilClamp(const absl::optional<int>& value) {
lines_until_clamp_ = value;
}
@@ -417,8 +432,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
}
- scoped_refptr<const NGLayoutResult> Abort(NGLayoutResult::EStatus);
-
NGPhysicalFragment::NGBoxType BoxType() const;
void SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
box_type_ = box_type;
@@ -535,6 +548,11 @@ class CORE_EXPORT NGBoxFragmentBuilder final
grid_data_ = std::move(grid_data);
}
+ const NGGridData& GetNGGridData() const {
+ DCHECK(grid_data_);
+ return *grid_data_.get();
+ }
+
// The |NGFragmentItemsBuilder| for the inline formatting context of this box.
NGFragmentItemsBuilder* ItemsBuilder() { return items_builder_; }
void SetItemsBuilder(NGFragmentItemsBuilder* builder) {
@@ -545,26 +563,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// Warning: Do not call unless necessary.
LogicalOffset GetChildOffset(const LayoutObject* child) const;
- // Inline containing block geometry is defined by two rectangles, generated
- // by fragments of the LayoutInline.
- struct InlineContainingBlockGeometry {
- DISALLOW_NEW();
- // Union of fragments generated on the first line.
- PhysicalRect start_fragment_union_rect;
- // Union of fragments generated on the last line.
- PhysicalRect end_fragment_union_rect;
- };
-
- using InlineContainingBlockMap =
- HashMap<const LayoutObject*,
- absl::optional<InlineContainingBlockGeometry>>;
-
- // Computes the geometry required for any inline containing blocks.
- // |inline_containing_block_map| is a map whose keys specify which inline
- // containing block geometry is required.
- void ComputeInlineContainerGeometry(
- InlineContainingBlockMap* inline_containing_block_map);
-
#if DCHECK_IS_ON()
// If we don't participate in a fragmentation context, this method can check
// that all block fragmentation related fields have their initial value.
@@ -618,8 +616,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
NGFragmentItemsBuilder* items_builder_ = nullptr;
- NGBlockNode column_spanner_ = nullptr;
-
NGPhysicalFragment::NGBoxType box_type_;
bool may_have_descendant_above_block_start_ = false;
bool is_fieldset_container_ = false;
@@ -639,6 +635,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
bool is_at_block_end_ = false;
bool has_violating_break_ = false;
LayoutUnit consumed_block_size_;
+ LayoutUnit consumed_block_size_legacy_adjustment_;
LayoutUnit block_offset_for_additional_columns_;
unsigned sequence_number_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_break_token.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_break_token.h
index 425499d563f..3ba26c03a14 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_break_token.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_break_token.h
@@ -89,7 +89,7 @@ class CORE_EXPORT NGBreakToken : public RefCounted<NGBreakToken> {
// The following bitfields are only to be used by NGInlineBreakToken (it's
// defined here to save memory, since that class has no bitfields).
- unsigned flags_ : 3; // NGInlineBreakTokenFlags
+ unsigned flags_ : 4; // NGInlineBreakTokenFlags
// The following bitfields are only to be used by NGBlockBreakToken (it's
// defined here to save memory, since that class has no bitfields).
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 6faf92cee9f..edfc73a4dac 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
@@ -109,6 +109,11 @@ class MulticolPartWalker {
// Push a break token for the column content to resume at.
void AddNextColumnBreakToken(const NGBlockBreakToken& next_column_token);
+ // If a column was added for an OOF before a spanner, we need to update the
+ // column break token so that the content is resumed at the correct spot.
+ void UpdateNextColumnBreakToken(
+ const NGContainerFragmentBuilder::ChildrenVector& children);
+
private:
void MoveToNext();
void UpdateCurrent();
@@ -151,6 +156,20 @@ void MulticolPartWalker::AddNextColumnBreakToken(
UpdateCurrent();
}
+void MulticolPartWalker::UpdateNextColumnBreakToken(
+ const NGContainerFragmentBuilder::ChildrenVector& children) {
+ if (children.IsEmpty())
+ return;
+ const scoped_refptr<const blink::NGPhysicalFragment> last_child =
+ children[children.size() - 1].fragment;
+ if (!last_child->IsColumnBox())
+ return;
+ const auto* child_break_token =
+ To<NGBlockBreakToken>(last_child->BreakToken());
+ if (child_break_token && child_break_token != next_column_token_)
+ next_column_token_ = child_break_token;
+}
+
void MulticolPartWalker::UpdateCurrent() {
DCHECK(!is_finished_);
if (parent_break_token_) {
@@ -301,7 +320,7 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
container_builder_.SetFragmentsTotalBlockSize(block_size);
container_builder_.SetIntrinsicBlockSize(intrinsic_block_size_);
container_builder_.SetBlockOffsetForAdditionalColumns(
- CurrentContentBlockOffset());
+ CurrentContentBlockOffset(intrinsic_block_size_));
PositionAnyUnclaimedListMarker();
@@ -484,6 +503,12 @@ NGBreakStatus NGColumnLayoutAlgorithm::LayoutChildren() {
IsEarlyBreakTarget(*early_break_, container_builder_, spanner_node))
break;
+ // Handle any OOF fragmentainer descendants that were found before the
+ // spanner.
+ NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), &container_builder_)
+ .HandleFragmentation();
+ walker.UpdateNextColumnBreakToken(container_builder_.Children());
+
NGBreakStatus break_status =
LayoutSpanner(spanner_node, child_break_token, &margin_strut);
@@ -542,10 +567,12 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
NGMarginStrut* margin_strut) {
LogicalSize column_size(column_inline_size_, column_block_size_);
- // We're adding a row. Incorporate the trailing margin from any preceding
- // column spanner into the layout position.
- intrinsic_block_size_ += margin_strut->Sum();
- *margin_strut = NGMarginStrut();
+ // Calculate the block-offset by including any trailing margin from a previous
+ // adjacent column spanner. We will not reset the margin strut just yet, as we
+ // first need to figure out if there's any content at all inside the columns.
+ // If there isn't, it should be possible to collapse the margin through the
+ // row (and as far as the spec is concerned, the row won't even exist then).
+ LayoutUnit row_offset = intrinsic_block_size_ + margin_strut->Sum();
// If block-size is non-auto, subtract the space for content we've consumed in
// previous fragments. This is necessary when we're nested inside another
@@ -556,7 +583,7 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// Subtract the space already taken in the current fragment (spanners and
// earlier column rows).
- column_size.block_size -= CurrentContentBlockOffset();
+ column_size.block_size -= CurrentContentBlockOffset(row_offset);
column_size.block_size = column_size.block_size.ClampNegativeToZero();
}
@@ -566,7 +593,7 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
LayoutUnit available_outer_space = kIndefiniteSize;
if (is_constrained_by_outer_fragmentation_context_) {
available_outer_space =
- FragmentainerSpaceAtBfcStart(ConstraintSpace()) - intrinsic_block_size_;
+ FragmentainerSpaceAtBfcStart(ConstraintSpace()) - row_offset;
if (available_outer_space <= LayoutUnit()) {
if (available_outer_space < LayoutUnit()) {
@@ -600,8 +627,8 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
!is_constrained_by_outer_fragmentation_context_);
if (balance_columns) {
- column_size.block_size =
- CalculateBalancedColumnBlockSize(column_size, next_column_token);
+ column_size.block_size = CalculateBalancedColumnBlockSize(
+ column_size, row_offset, next_column_token);
} else if (available_outer_space != kIndefiniteSize) {
// Finally, resolve any remaining auto block-size, and make sure that we
// don't take up more space than there's room for in the outer fragmentation
@@ -669,7 +696,7 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// Add the new column fragment to the list, but don't commit anything to
// the fragment builder until we know whether these are the final columns.
- LogicalOffset logical_offset(column_inline_offset, intrinsic_block_size_);
+ LogicalOffset logical_offset(column_inline_offset, row_offset);
new_columns.emplace_back(result, logical_offset);
LayoutUnit space_shortage = result->MinimalSpaceShortage();
@@ -678,14 +705,15 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
std::min(minimal_space_shortage, space_shortage);
}
actual_column_count++;
- if (result->HasForcedBreak())
- forced_break_count++;
+
+ if (result->ColumnSpanner())
+ break;
has_violating_break |= result->HasViolatingBreak();
column_inline_offset += column_inline_progression_;
- if (result->ColumnSpanner())
- break;
+ if (result->HasForcedBreak())
+ forced_break_count++;
column_break_token = To<NGBlockBreakToken>(column.BreakToken());
@@ -720,8 +748,8 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// and lay out again.
balance_columns = true;
new_columns.clear();
- column_size.block_size =
- CalculateBalancedColumnBlockSize(column_size, next_column_token);
+ column_size.block_size = CalculateBalancedColumnBlockSize(
+ column_size, row_offset, next_column_token);
continue;
}
@@ -752,11 +780,11 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// We also need at least one soft break opportunity. If forced breaks cause
// too many breaks, there's no stretch amount that could prevent the columns
// from overflowing.
- if (actual_column_count <= forced_break_count + 1)
+ if (used_column_count_ <= forced_break_count + 1)
break;
- LayoutUnit new_column_block_size =
- StretchColumnBlockSize(minimal_space_shortage, column_size.block_size);
+ LayoutUnit new_column_block_size = StretchColumnBlockSize(
+ minimal_space_shortage, column_size.block_size, row_offset);
// Give up if we cannot get taller columns. The multicol container may have
// a specified block-size preventing taller columns, for instance.
@@ -782,8 +810,12 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// incorrectly consider this to be a class A breakpoint. A fragmentainer may
// end up empty if there's no in-flow content at all inside the multicol
// container, or if the multicol container starts with a spanner.
- bool is_empty =
- new_columns.size() == 1 && new_columns[0].Fragment().Children().empty();
+ //
+ // If the size of the fragment is non-zero, we shouldn't consider it to be
+ // empty (even if there's nothing inside). This happens with contenteditable,
+ // which in some cases makes room for a line box that isn't there.
+ bool is_empty = !column_size.block_size && new_columns.size() == 1 &&
+ new_columns[0].Fragment().Children().empty();
if (!is_empty) {
has_processed_first_child_ = true;
@@ -800,17 +832,22 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// TODO(layout-dev): It might make sense to look for baselines inside
// every column that's first in a row, not just the first column in the
// multicol container.
- PropagateBaselineFromChild(first_column, intrinsic_block_size_);
+ PropagateBaselineFromChild(first_column, row_offset);
}
// Only the first column in a row may attempt to place any unpositioned
// list-item. This matches the behavior in Gecko, and also to some extent
// with how baselines are propagated inside a multicol container.
- AttemptToPositionListMarker(first_column, intrinsic_block_size_);
+ AttemptToPositionListMarker(first_column, row_offset);
+
+ // We're adding a row with content. We can update the intrinsic block-size
+ // (which will also be used as layout position for subsequent content), and
+ // reset the margin strut (it has already been incorporated into the
+ // offset).
+ intrinsic_block_size_ = row_offset + column_size.block_size;
+ *margin_strut = NGMarginStrut();
}
- intrinsic_block_size_ += column_size.block_size;
-
// Commit all column fragments to the fragment builder.
const NGBlockBreakToken* incoming_column_token = next_column_token;
for (auto result_with_offset : new_columns) {
@@ -965,6 +1002,7 @@ void NGColumnLayoutAlgorithm::PropagateBaselineFromChild(
// Distribute as many implicit breaks into the content runs as we need.
LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
const LogicalSize& column_size,
+ LayoutUnit row_offset,
const NGBlockBreakToken* child_break_token) {
// To calculate a balanced column size for one row of columns, we need to
// figure out how tall our content is. To do that we need to lay out. Create a
@@ -1055,6 +1093,7 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
ContentRuns content_runs;
scoped_refptr<const NGBlockBreakToken> break_token = child_break_token;
tallest_unbreakable_block_size_ = LayoutUnit();
+ int forced_break_count = 0;
do {
NGBlockLayoutAlgorithm balancing_algorithm(
{Node(), fragment_geometry, space, break_token.get()});
@@ -1066,29 +1105,35 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
const NGPhysicalBoxFragment& fragment =
To<NGPhysicalBoxFragment>(result->PhysicalFragment());
- LayoutUnit column_block_size =
- CalculateColumnContentBlockSize(fragment, space.GetWritingDirection());
-
- // Encompass the block-size of the (single-strip column) fragment, to
- // account for any trailing margins. We let them affect the column
- // block-size, for compatibility reasons, if nothing else. The initial
- // column balancing pass (i.e. here) is our opportunity to do that fairly
- // easily. But note that this doesn't guarantee that no margins will ever
- // get truncated. To avoid that we'd need to add some sort of mechanism that
- // is invoked in *every* column balancing layout pass, where we'd
- // essentially have to treat every margin as unbreakable (which kind of
- // sounds both bad and difficult).
- //
- // We might want to revisit this approach, if it's worth it: Maybe it's
- // better to not make any room at all for margins that might end up getting
- // truncated. After all, they don't really require any space, so what we're
- // doing currently might be seen as unnecessary (and slightly unpredictable)
- // column over-stretching.
- NGFragment logical_fragment(ConstraintSpace().GetWritingDirection(),
- fragment);
- column_block_size =
- std::max(column_block_size, logical_fragment.BlockSize());
- content_runs.AddRun(column_block_size);
+
+ // Add a content run, as long as we have soft break opportunities. Ignore
+ // content that's doomed to end up in overflowing columns (because of too
+ // many forced breaks).
+ if (forced_break_count < used_column_count_) {
+ LayoutUnit column_block_size = CalculateColumnContentBlockSize(
+ fragment, space.GetWritingDirection());
+
+ // Encompass the block-size of the (single-strip column) fragment, to
+ // account for any trailing margins. We let them affect the column
+ // block-size, for compatibility reasons, if nothing else. The initial
+ // column balancing pass (i.e. here) is our opportunity to do that fairly
+ // easily. But note that this doesn't guarantee that no margins will ever
+ // get truncated. To avoid that we'd need to add some sort of mechanism
+ // that is invoked in *every* column balancing layout pass, where we'd
+ // essentially have to treat every margin as unbreakable (which kind of
+ // sounds both bad and difficult).
+ //
+ // We might want to revisit this approach, if it's worth it: Maybe it's
+ // better to not make any room at all for margins that might end up
+ // getting truncated. After all, they don't really require any space, so
+ // what we're doing currently might be seen as unnecessary (and slightly
+ // unpredictable) column over-stretching.
+ NGFragment logical_fragment(ConstraintSpace().GetWritingDirection(),
+ fragment);
+ column_block_size =
+ std::max(column_block_size, logical_fragment.BlockSize());
+ content_runs.AddRun(column_block_size);
+ }
tallest_unbreakable_block_size_ = std::max(
tallest_unbreakable_block_size_, result->TallestUnbreakableBlockSize());
@@ -1097,6 +1142,9 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
if (result->ColumnSpanner())
break;
+ if (result->HasForcedBreak())
+ forced_break_count++;
+
break_token = To<NGBlockBreakToken>(fragment.BreakToken());
} while (break_token);
@@ -1117,30 +1165,35 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
// stretch and retry if not). Also honor {,min-,max-}block-size properties
// before returning, and also try to not become shorter than the tallest piece
// of unbreakable content.
- if (tallest_unbreakable_block_size_ >= content_runs.TallestContentBlockSize())
- return ConstrainColumnBlockSize(tallest_unbreakable_block_size_);
+ if (tallest_unbreakable_block_size_ >=
+ content_runs.TallestContentBlockSize()) {
+ return ConstrainColumnBlockSize(tallest_unbreakable_block_size_,
+ row_offset);
+ }
- content_runs.DistributeImplicitBreaks(
- ResolveUsedColumnCount(ChildAvailableSize().inline_size, Style()));
- return ConstrainColumnBlockSize(content_runs.TallestColumnBlockSize());
+ content_runs.DistributeImplicitBreaks(used_column_count_);
+ return ConstrainColumnBlockSize(content_runs.TallestColumnBlockSize(),
+ row_offset);
}
LayoutUnit NGColumnLayoutAlgorithm::StretchColumnBlockSize(
LayoutUnit minimal_space_shortage,
- LayoutUnit current_column_size) const {
+ LayoutUnit current_column_size,
+ LayoutUnit row_offset) const {
LayoutUnit length = current_column_size + minimal_space_shortage;
// Honor {,min-,max-}{height,width} properties.
- return ConstrainColumnBlockSize(length);
+ return ConstrainColumnBlockSize(length, row_offset);
}
// Constrain a balanced column block size to not overflow the multicol
// container.
LayoutUnit NGColumnLayoutAlgorithm::ConstrainColumnBlockSize(
- LayoutUnit size) const {
+ LayoutUnit size,
+ LayoutUnit row_offset) const {
if (is_constrained_by_outer_fragmentation_context_) {
// Don't become too tall to fit in the outer fragmentation context.
LayoutUnit available_outer_space =
- FragmentainerSpaceAtBfcStart(ConstraintSpace()) - intrinsic_block_size_;
+ FragmentainerSpaceAtBfcStart(ConstraintSpace()) - row_offset;
DCHECK_GE(available_outer_space, LayoutUnit());
size = std::min(size, available_outer_space);
}
@@ -1186,7 +1239,7 @@ LayoutUnit NGColumnLayoutAlgorithm::ConstrainColumnBlockSize(
// We may already have used some of the available space in earlier column rows
// or spanners.
- max -= CurrentContentBlockOffset();
+ max -= CurrentContentBlockOffset(row_offset);
// Constrain and convert the value back to content-box.
size = std::min(size, max);
@@ -1199,7 +1252,7 @@ NGConstraintSpace NGColumnLayoutAlgorithm::CreateConstraintSpaceForBalancing(
ConstraintSpace(), Style().GetWritingDirection(), /* is_new_fc */ true);
space_builder.SetFragmentationType(kFragmentColumn);
space_builder.SetAvailableSize({column_size.inline_size, kIndefiniteSize});
- space_builder.SetStretchInlineSizeIfAuto(true);
+ space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
space_builder.SetPercentageResolutionSize(ColumnPercentageResolutionSize());
space_builder.SetIsAnonymous(true);
space_builder.SetIsInColumnBfc();
@@ -1214,7 +1267,7 @@ NGConstraintSpace NGColumnLayoutAlgorithm::CreateConstraintSpaceForSpanner(
NGConstraintSpaceBuilder space_builder(
ConstraintSpace(), Style().GetWritingDirection(), /* is_new_fc */ true);
space_builder.SetAvailableSize(ChildAvailableSize());
- space_builder.SetStretchInlineSizeIfAuto(true);
+ space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
space_builder.SetPercentageResolutionSize(ChildAvailableSize());
space_builder.SetBaselineAlgorithmType(
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
index ee6610f50e2..9b5044b3e29 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
@@ -76,16 +76,19 @@ class CORE_EXPORT NGColumnLayoutAlgorithm
LayoutUnit CalculateBalancedColumnBlockSize(
const LogicalSize& column_size,
+ LayoutUnit row_offset,
const NGBlockBreakToken* child_break_token);
// Stretch the column length. We do this during column balancing, when we
// discover that the current length isn't large enough to fit all content.
LayoutUnit StretchColumnBlockSize(LayoutUnit minimal_space_shortage,
- LayoutUnit current_column_size) const;
+ LayoutUnit current_column_size,
+ LayoutUnit row_offset) const;
- LayoutUnit ConstrainColumnBlockSize(LayoutUnit size) const;
- LayoutUnit CurrentContentBlockOffset() const {
- return intrinsic_block_size_ - BorderScrollbarPadding().block_start;
+ LayoutUnit ConstrainColumnBlockSize(LayoutUnit size,
+ LayoutUnit row_offset) const;
+ LayoutUnit CurrentContentBlockOffset(LayoutUnit border_box_row_offset) const {
+ return border_box_row_offset - BorderScrollbarPadding().block_start;
}
// Get the percentage resolution size to use for column content (i.e. not
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 b1615012e40..4c29a72b16a 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
@@ -14,6 +14,8 @@
#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/table/layout_ng_table_cell_interface.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
namespace blink {
@@ -49,20 +51,20 @@ NGConstraintSpace NGConstraintSpace::CreateFromLayoutObject(
available_logical_height};
LogicalSize available_size = percentage_size;
- bool fixed_inline = false, fixed_block = false;
- bool fixed_block_is_definite = true;
+ bool is_fixed_inline_size = false, is_fixed_block_size = false;
+ bool is_initial_block_size_definite = true;
if (block.HasOverrideLogicalWidth()) {
available_size.inline_size = block.OverrideLogicalWidth();
- fixed_inline = true;
+ is_fixed_inline_size = true;
}
if (block.HasOverrideLogicalHeight()) {
available_size.block_size = block.OverrideLogicalHeight();
- fixed_block = true;
+ is_fixed_block_size = true;
}
- if (block.IsFlexItem() && fixed_block) {
+ if (block.IsFlexItem() && is_fixed_block_size) {
// The flexbox-specific behavior is in addition to regular definite-ness, so
// if the flex item would normally have a definite height it should keep it.
- fixed_block_is_definite =
+ is_initial_block_size_definite =
To<LayoutFlexibleBox>(block.Parent())
->UseOverrideLogicalHeightForPerentageResolution(block) ||
block.HasDefiniteLogicalHeight();
@@ -97,9 +99,11 @@ NGConstraintSpace NGConstraintSpace::CreateFromLayoutObject(
!cell_style.LogicalHeight().IsAuto() ||
!table_style.LogicalHeight().IsAuto());
const LayoutBlock& cell_block = To<LayoutBlock>(*cell.ToLayoutObject());
- if (fixed_block) {
- fixed_block_is_definite = cell_block.HasDefiniteLogicalHeight() ||
- !table_style.LogicalHeight().IsAuto();
+ if (is_fixed_block_size) {
+ is_initial_block_size_definite = cell_block.HasDefiniteLogicalHeight() ||
+ !table_style.LogicalHeight().IsAuto();
+ } else {
+ is_initial_block_size_definite = false;
}
builder.SetTableCellBorders(
{cell_block.BorderStart(), cell_block.BorderEnd(),
@@ -121,14 +125,16 @@ NGConstraintSpace NGConstraintSpace::CreateFromLayoutObject(
builder.SetAvailableSize(available_size);
builder.SetPercentageResolutionSize(percentage_size);
- builder.SetIsFixedInlineSize(fixed_inline);
- builder.SetIsFixedBlockSize(fixed_block);
- builder.SetIsFixedBlockSizeIndefinite(!fixed_block_is_definite);
+ builder.SetIsFixedInlineSize(is_fixed_inline_size);
+ builder.SetIsFixedBlockSize(is_fixed_block_size);
+ builder.SetIsInitialBlockSizeIndefinite(!is_initial_block_size_definite);
// HTML element with display:table is shrink-to-fit.
bool shrink_to_fit =
block.SizesLogicalWidthToFitContent(style.LogicalWidth()) ||
(block.IsTable() && block.Parent() && block.Parent()->IsLayoutView());
- builder.SetStretchInlineSizeIfAuto(!shrink_to_fit);
+ builder.SetInlineAutoBehavior(shrink_to_fit
+ ? NGAutoBehavior::kFitContent
+ : NGAutoBehavior::kStretchImplicit);
return builder.ToConstraintSpace();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index 689aed04ea8..4a89a33fa34 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -35,7 +35,7 @@ enum NGFragmentationType {
// "adjoining" objects (either floats or inline-level OOF-positioned nodes) are
// used to indicate that a particular node might need a relayout once its BFC
-// block-offset is resvoled. E.g. their position depends on the final BFC
+// block-offset is resolved. E.g. their position depends on the final BFC
// block-offset being known.
enum NGAdjoiningObjectTypeValue {
kAdjoiningNone = 0b000,
@@ -60,6 +60,20 @@ enum class NGBaselineAlgorithmType {
kInlineBlock
};
+// The behavior of the 'auto' keyword when used with a main-size.
+enum class NGAutoBehavior : uint8_t {
+ // We should shrink-to-fit within the available space.
+ kFitContent,
+ // We should stretch to the available space, but if there is an aspect-ratio
+ // with a definite size in the opposite axis, we should transfer the definite
+ // size through the aspect-ratio, and be the resulting size. This is a "weak"
+ // stretch constraint.
+ kStretchImplicit,
+ // We should *always* stretch to the available space, even if we have an
+ // aspect-ratio. This is a "strong" stretch constraint.
+ kStretchExplicit
+};
+
// Some layout algorithms have multiple layout passes. Between passes they
// typically have different results which we need to cache separately for
// performance reasons.
@@ -137,6 +151,14 @@ class CORE_EXPORT NGConstraintSpace final {
return *this;
}
+ NGConstraintSpace CloneWithoutFragmentation() const {
+ DCHECK(HasBlockFragmentation());
+ NGConstraintSpace copy = *this;
+ DCHECK(copy.rare_data_);
+ copy.rare_data_->block_direction_fragmentation_type = kFragmentNone;
+ return copy;
+ }
+
~NGConstraintSpace() {
if (HasRareData())
delete rare_data_;
@@ -176,7 +198,7 @@ class CORE_EXPORT NGConstraintSpace final {
bitfields_.percentage_inline_storage)) {
default:
NOTREACHED();
- U_FALLTHROUGH;
+ FALLTHROUGH;
case kSameAsAvailable:
return available_size_.inline_size;
case kZero:
@@ -194,7 +216,7 @@ class CORE_EXPORT NGConstraintSpace final {
static_cast<NGPercentageStorage>(bitfields_.percentage_block_storage)) {
default:
NOTREACHED();
- U_FALLTHROUGH;
+ FALLTHROUGH;
case kSameAsAvailable:
return available_size_.block_size;
case kZero:
@@ -255,7 +277,7 @@ class CORE_EXPORT NGConstraintSpace final {
// Inline/block target stretch size constraints.
// See:
- // https://mathml-refresh.github.io/mathml-core/#dfn-inline-stretch-size-constraint
+ // https://w3c.github.io/mathml-core/#dfn-inline-stretch-size-constraint
LayoutUnit TargetStretchInlineSize() const {
return HasRareData() ? rare_data_->TargetStretchInlineSize()
: kIndefiniteSize;
@@ -265,22 +287,14 @@ class CORE_EXPORT NGConstraintSpace final {
return TargetStretchInlineSize() != kIndefiniteSize;
}
- LayoutUnit TargetStretchAscentSize() const {
- return HasRareData() ? rare_data_->TargetStretchAscentSize()
- : kIndefiniteSize;
- }
-
- bool HasTargetStretchAscentSize() const {
- return TargetStretchAscentSize() != kIndefiniteSize;
- }
-
- LayoutUnit TargetStretchDescentSize() const {
- return HasRareData() ? rare_data_->TargetStretchDescentSize()
- : kIndefiniteSize;
- }
+ struct MathTargetStretchBlockSizes {
+ LayoutUnit ascent;
+ LayoutUnit descent;
+ };
- bool HasTargetStretchDescentSize() const {
- return TargetStretchDescentSize() != kIndefiniteSize;
+ absl::optional<MathTargetStretchBlockSizes> TargetStretchBlockSizes() const {
+ return HasRareData() ? rare_data_->TargetStretchBlockSizes()
+ : absl::nullopt;
}
// Return the borders which should be used for a table-cell.
@@ -380,7 +394,9 @@ class CORE_EXPORT NGConstraintSpace final {
bool IsTableCell() const { return bitfields_.is_table_cell; }
// True if node is either LayoutTableCell or LayoutNGTableCellLegacy
- bool IsLegacyTableCell() const { return bitfields_.is_legacy_table_cell; }
+ bool IsLegacyTableCell() const {
+ return HasRareData() && rare_data_->is_legacy_table_cell;
+ }
// Whether the table-cell fragment should be hidden (not painted) if it has
// no children.
@@ -434,13 +450,13 @@ class CORE_EXPORT NGConstraintSpace final {
bool IsFixedBlockSize() const { return bitfields_.is_fixed_block_size; }
// The constraint space can have any of the combinations:
- // (1) !IsFixedBlockSize && !IsFixedBlockSizeIndefinite -- default
- // (2) !IsFixedBlockSize && IsFixedBlockSizeIndefinite -- Treat your height as
- // indefinite when calculating your intrinsic block size.
- // (3) IsFixedBlockSize && !IsFixedBlockSizeIndefinite -- You must be this
+ // (1) !IsFixedBlockSize && !IsInitialBlockSizeIndefinite -- default
+ // (2) !IsFixedBlockSize && IsInitialBlockSizeIndefinite -- Treat your height
+ // as indefinite when calculating your intrinsic block size.
+ // (3) IsFixedBlockSize && !IsInitialBlockSizeIndefinite -- You must be this
// size and your children can resolve % block size against it.
- // (4) IsFixedBlockSize && IsFixedBlockSizeIndefinite -- You must be this
- // size but your children canNOT resolve % block size against it.
+ // (4) IsFixedBlockSize && IsInitialBlockSizeIndefinite -- You must be this
+ // size but your children *cannot* resolve % block size against it.
//
// The layout machinery (CalculateChildPercentageSize,
// CalculateInitialFragmentGeometry, etc) handles all this, so individual
@@ -448,28 +464,31 @@ class CORE_EXPORT NGConstraintSpace final {
// specified block sizes influence the value passed to
// SetIntrinsicBlock(intrinsic_block_size). If that happens, they need to
// explicitly handle case 2 above.
- // TODO(dgrogan): This method needs a new name now that #2 above exists.
- bool IsFixedBlockSizeIndefinite() const {
- return bitfields_.is_fixed_block_size_indefinite;
+ bool IsInitialBlockSizeIndefinite() const {
+ return bitfields_.is_initial_block_size_indefinite;
}
- // Return true if the respective size property when 'auto' should stretch to
- // consume the available space. If false, it behaves as "shrink-to-fit".
- bool StretchInlineSizeIfAuto() const {
- return bitfields_.stretch_inline_size_if_auto;
+ // Returns the behavior of an 'auto' inline/block main-size.
+ NGAutoBehavior InlineAutoBehavior() const {
+ return static_cast<NGAutoBehavior>(bitfields_.inline_auto_behavior);
+ }
+ NGAutoBehavior BlockAutoBehavior() const {
+ return static_cast<NGAutoBehavior>(bitfields_.block_auto_behavior);
}
- bool StretchBlockSizeIfAuto() const {
- return bitfields_.stretch_block_size_if_auto;
+ bool IsInlineAutoBehaviorStretch() const {
+ return InlineAutoBehavior() != NGAutoBehavior::kFitContent;
+ }
+ bool IsBlockAutoBehaviorStretch() const {
+ return BlockAutoBehavior() != NGAutoBehavior::kFitContent;
}
// If this is a child of a table-cell.
bool IsTableCellChild() const { return bitfields_.is_table_cell_child; }
- // If we should apply the restricted block-size measuring behaviour. See
- // where this is set within |NGBlockLayoutAlgorithm| for the conditions when
- // this applies.
- bool IsMeasuringRestrictedBlockSizeTableCellChild() const {
- return bitfields_.is_measuring_restricted_block_size_table_cell_child;
+ // If we should apply the restricted block-size behavior. See where this is
+ // set within |NGBlockLayoutAlgorithm| for the conditions when this applies.
+ bool IsRestrictedBlockSizeTableCellChild() const {
+ return bitfields_.is_restricted_block_size_table_cell_child;
}
bool IsPaintedAtomically() const { return bitfields_.is_painted_atomically; }
@@ -615,7 +634,9 @@ class CORE_EXPORT NGConstraintSpace final {
}
// Return true if this is participating within a -webkit-line-clamp context.
- bool IsLineClampContext() const { return bitfields_.is_line_clamp_context; }
+ bool IsLineClampContext() const {
+ return HasRareData() && rare_data_->is_line_clamp_context;
+ }
absl::optional<int> LinesUntilClamp() const {
return HasRareData() ? rare_data_->LinesUntilClamp() : absl::nullopt;
@@ -739,6 +760,8 @@ class CORE_EXPORT NGConstraintSpace final {
explicit RareData(const NGBfcOffset bfc_offset)
: bfc_offset(bfc_offset),
data_union_type(static_cast<unsigned>(kNone)),
+ is_line_clamp_context(false),
+ is_legacy_table_cell(false),
is_restricted_block_size_table_cell(false),
hide_table_cell_if_empty(false),
block_direction_fragmentation_type(
@@ -754,6 +777,8 @@ class CORE_EXPORT NGConstraintSpace final {
fragmentainer_block_size(other.fragmentainer_block_size),
fragmentainer_offset_at_bfc(other.fragmentainer_offset_at_bfc),
data_union_type(other.data_union_type),
+ is_line_clamp_context(other.is_line_clamp_context),
+ is_legacy_table_cell(other.is_legacy_table_cell),
is_restricted_block_size_table_cell(
other.is_restricted_block_size_table_cell),
hide_table_cell_if_empty(other.hide_table_cell_if_empty),
@@ -818,6 +843,8 @@ class CORE_EXPORT NGConstraintSpace final {
if (fragmentainer_block_size != other.fragmentainer_block_size ||
fragmentainer_offset_at_bfc != other.fragmentainer_offset_at_bfc ||
data_union_type != other.data_union_type ||
+ is_line_clamp_context != other.is_line_clamp_context ||
+ is_legacy_table_cell != other.is_legacy_table_cell ||
is_restricted_block_size_table_cell !=
other.is_restricted_block_size_table_cell ||
hide_table_cell_if_empty != other.hide_table_cell_if_empty ||
@@ -850,7 +877,8 @@ class CORE_EXPORT NGConstraintSpace final {
// Must be kept in sync with members checked within |MaySkipLayout|.
bool IsInitialForMaySkipLayout() const {
if (fragmentainer_block_size != kIndefiniteSize ||
- fragmentainer_offset_at_bfc || is_restricted_block_size_table_cell ||
+ fragmentainer_offset_at_bfc || is_line_clamp_context ||
+ is_legacy_table_cell || is_restricted_block_size_table_cell ||
hide_table_cell_if_empty ||
block_direction_fragmentation_type != kFragmentNone ||
is_inside_balanced_columns || is_in_column_bfc)
@@ -1063,26 +1091,17 @@ class CORE_EXPORT NGConstraintSpace final {
target_stretch_inline_size;
}
- LayoutUnit TargetStretchAscentSize() const {
+ absl::optional<MathTargetStretchBlockSizes> TargetStretchBlockSizes()
+ const {
return data_union_type == kStretchData
- ? stretch_data_.target_stretch_ascent_size
- : kIndefiniteSize;
- }
-
- void SetTargetStretchAscentSize(LayoutUnit target_stretch_ascent_size) {
- EnsureStretchData()->target_stretch_ascent_size =
- target_stretch_ascent_size;
- }
-
- LayoutUnit TargetStretchDescentSize() const {
- return data_union_type == kStretchData
- ? stretch_data_.target_stretch_descent_size
- : kIndefiniteSize;
+ ? stretch_data_.target_stretch_block_sizes
+ : absl::nullopt;
}
- void SetTargetStretchDescentSize(LayoutUnit target_stretch_descent_size) {
- EnsureStretchData()->target_stretch_descent_size =
- target_stretch_descent_size;
+ void SetTargetStretchBlockSizes(
+ MathTargetStretchBlockSizes target_stretch_block_sizes) {
+ EnsureStretchData()->target_stretch_block_sizes =
+ target_stretch_block_sizes;
}
LogicalSize percentage_resolution_size;
@@ -1095,6 +1114,9 @@ class CORE_EXPORT NGConstraintSpace final {
unsigned data_union_type : 3;
+ unsigned is_line_clamp_context : 1;
+
+ unsigned is_legacy_table_cell : 1;
unsigned is_restricted_block_size_table_cell : 1;
unsigned hide_table_cell_if_empty : 1;
@@ -1190,19 +1212,22 @@ class CORE_EXPORT NGConstraintSpace final {
struct StretchData {
bool MaySkipLayout(const StretchData& other) const {
return target_stretch_inline_size == other.target_stretch_inline_size &&
- target_stretch_ascent_size == other.target_stretch_ascent_size &&
- target_stretch_descent_size == other.target_stretch_descent_size;
+ target_stretch_block_sizes.has_value() ==
+ other.target_stretch_block_sizes.has_value() &&
+ (!target_stretch_block_sizes ||
+ (target_stretch_block_sizes->ascent ==
+ other.target_stretch_block_sizes->ascent &&
+ target_stretch_block_sizes->descent ==
+ other.target_stretch_block_sizes->descent));
}
bool IsInitialForMaySkipLayout() const {
return target_stretch_inline_size == kIndefiniteSize &&
- target_stretch_ascent_size == kIndefiniteSize &&
- target_stretch_descent_size == kIndefiniteSize;
+ !target_stretch_block_sizes;
}
LayoutUnit target_stretch_inline_size = kIndefiniteSize;
- LayoutUnit target_stretch_ascent_size = kIndefiniteSize;
- LayoutUnit target_stretch_descent_size = kIndefiniteSize;
+ absl::optional<MathTargetStretchBlockSizes> target_stretch_block_sizes;
};
BlockData* EnsureBlockData() {
@@ -1286,24 +1311,24 @@ class CORE_EXPORT NGConstraintSpace final {
static_cast<unsigned>(writing_direction.GetWritingMode())),
direction(static_cast<unsigned>(writing_direction.Direction())),
is_table_cell(false),
- is_legacy_table_cell(false),
is_anonymous(false),
is_new_formatting_context(false),
is_orthogonal_writing_mode_root(false),
- is_line_clamp_context(false),
is_painted_atomically(false),
use_first_line_style(false),
ancestor_has_clearance_past_adjoining_floats(false),
baseline_algorithm_type(
static_cast<unsigned>(NGBaselineAlgorithmType::kFirstLine)),
cache_slot(static_cast<unsigned>(NGCacheSlot::kLayout)),
- stretch_inline_size_if_auto(false),
- stretch_block_size_if_auto(false),
+ inline_auto_behavior(
+ static_cast<unsigned>(NGAutoBehavior::kFitContent)),
+ block_auto_behavior(
+ static_cast<unsigned>(NGAutoBehavior::kFitContent)),
is_fixed_inline_size(false),
is_fixed_block_size(false),
- is_fixed_block_size_indefinite(false),
+ is_initial_block_size_indefinite(false),
is_table_cell_child(false),
- is_measuring_restricted_block_size_table_cell_child(false),
+ is_restricted_block_size_table_cell_child(false),
percentage_inline_storage(kSameAsAvailable),
percentage_block_storage(kSameAsAvailable),
replaced_percentage_block_storage(kSameAsAvailable) {}
@@ -1313,12 +1338,10 @@ class CORE_EXPORT NGConstraintSpace final {
writing_mode == other.writing_mode &&
direction == other.direction &&
is_table_cell == other.is_table_cell &&
- is_legacy_table_cell == other.is_legacy_table_cell &&
is_anonymous == other.is_anonymous &&
is_new_formatting_context == other.is_new_formatting_context &&
is_orthogonal_writing_mode_root ==
other.is_orthogonal_writing_mode_root &&
- is_line_clamp_context == other.is_line_clamp_context &&
is_painted_atomically == other.is_painted_atomically &&
use_first_line_style == other.use_first_line_style &&
ancestor_has_clearance_past_adjoining_floats ==
@@ -1327,17 +1350,17 @@ class CORE_EXPORT NGConstraintSpace final {
}
bool AreInlineSizeConstraintsEqual(const Bitfields& other) const {
- return stretch_inline_size_if_auto == other.stretch_inline_size_if_auto &&
+ return inline_auto_behavior == other.inline_auto_behavior &&
is_fixed_inline_size == other.is_fixed_inline_size;
}
bool AreBlockSizeConstraintsEqual(const Bitfields& other) const {
- return stretch_block_size_if_auto == other.stretch_block_size_if_auto &&
+ return block_auto_behavior == other.block_auto_behavior &&
is_fixed_block_size == other.is_fixed_block_size &&
- is_fixed_block_size_indefinite ==
- other.is_fixed_block_size_indefinite &&
+ is_initial_block_size_indefinite ==
+ other.is_initial_block_size_indefinite &&
is_table_cell_child == other.is_table_cell_child &&
- is_measuring_restricted_block_size_table_cell_child ==
- other.is_measuring_restricted_block_size_table_cell_child;
+ is_restricted_block_size_table_cell_child ==
+ other.is_restricted_block_size_table_cell_child;
}
unsigned has_rare_data : 1;
@@ -1346,12 +1369,10 @@ class CORE_EXPORT NGConstraintSpace final {
unsigned direction : 1;
unsigned is_table_cell : 1;
- unsigned is_legacy_table_cell : 1;
unsigned is_anonymous : 1;
unsigned is_new_formatting_context : 1;
unsigned is_orthogonal_writing_mode_root : 1;
- unsigned is_line_clamp_context : 1;
unsigned is_painted_atomically : 1;
unsigned use_first_line_style : 1;
@@ -1362,13 +1383,13 @@ class CORE_EXPORT NGConstraintSpace final {
unsigned cache_slot : 1;
// Size constraints.
- unsigned stretch_inline_size_if_auto : 1;
- unsigned stretch_block_size_if_auto : 1;
+ unsigned inline_auto_behavior : 2; // NGAutoBehavior
+ unsigned block_auto_behavior : 2; // NGAutoBehavior
unsigned is_fixed_inline_size : 1;
unsigned is_fixed_block_size : 1;
- unsigned is_fixed_block_size_indefinite : 1;
+ unsigned is_initial_block_size_indefinite : 1;
unsigned is_table_cell_child : 1;
- unsigned is_measuring_restricted_block_size_table_cell_child : 1;
+ unsigned is_restricted_block_size_table_cell_child : 1;
unsigned percentage_inline_storage : 2; // NGPercentageStorage
unsigned percentage_block_storage : 2; // NGPercentageStorage
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
index 0311c8fe00c..944477133b6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
@@ -143,23 +143,29 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
space_.bitfields_.is_fixed_inline_size = b;
}
- void SetIsFixedBlockSizeIndefinite(bool b) {
+ void SetIsInitialBlockSizeIndefinite(bool b) {
if (LIKELY(is_in_parallel_flow_ || !force_orthogonal_writing_mode_root_))
- space_.bitfields_.is_fixed_block_size_indefinite = b;
+ space_.bitfields_.is_initial_block_size_indefinite = b;
}
- void SetStretchInlineSizeIfAuto(bool b) {
- if (LIKELY(is_in_parallel_flow_))
- space_.bitfields_.stretch_inline_size_if_auto = b;
- else
- space_.bitfields_.stretch_block_size_if_auto = b;
+ void SetInlineAutoBehavior(NGAutoBehavior auto_behavior) {
+ if (LIKELY(is_in_parallel_flow_)) {
+ space_.bitfields_.inline_auto_behavior =
+ static_cast<unsigned>(auto_behavior);
+ } else {
+ space_.bitfields_.block_auto_behavior =
+ static_cast<unsigned>(auto_behavior);
+ }
}
- void SetStretchBlockSizeIfAuto(bool b) {
- if (LIKELY(is_in_parallel_flow_))
- space_.bitfields_.stretch_block_size_if_auto = b;
- else
- space_.bitfields_.stretch_inline_size_if_auto = b;
+ void SetBlockAutoBehavior(NGAutoBehavior auto_behavior) {
+ if (LIKELY(is_in_parallel_flow_)) {
+ space_.bitfields_.block_auto_behavior =
+ static_cast<unsigned>(auto_behavior);
+ } else {
+ space_.bitfields_.inline_auto_behavior =
+ static_cast<unsigned>(auto_behavior);
+ }
}
void SetIsPaintedAtomically(bool b) {
@@ -183,10 +189,16 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
void SetIsInColumnBfc() { space_.EnsureRareData()->is_in_column_bfc = true; }
- // is_legacy_table_cell must always be assigned if is_table_cell is true.
void SetIsTableCell(bool is_table_cell, bool is_legacy_table_cell) {
+#if DCHECK_IS_ON()
+ DCHECK(!is_table_cell_set_);
+ is_table_cell_set_ = true;
+#endif
space_.bitfields_.is_table_cell = is_table_cell;
- space_.bitfields_.is_legacy_table_cell = is_legacy_table_cell;
+ if (is_legacy_table_cell) {
+ DCHECK(is_table_cell);
+ space_.EnsureRareData()->is_legacy_table_cell = is_legacy_table_cell;
+ }
}
void SetIsRestrictedBlockSizeTableCell(bool b) {
@@ -358,9 +370,8 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
space_.bitfields_.is_table_cell_child = b;
}
- void SetIsMeasuringRestrictedBlockSizeTableCellChild() {
- space_.bitfields_.is_measuring_restricted_block_size_table_cell_child =
- true;
+ void SetIsRestrictedBlockSizeTableCellChild() {
+ space_.bitfields_.is_restricted_block_size_table_cell_child = true;
}
void SetExclusionSpace(const NGExclusionSpace& exclusion_space) {
@@ -402,7 +413,12 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
void SetIsLineClampContext(bool is_line_clamp_context) {
DCHECK(!is_new_fc_);
- space_.bitfields_.is_line_clamp_context = is_line_clamp_context;
+#if DCHECK_IS_ON()
+ DCHECK(!is_line_clamp_context_set_);
+ is_line_clamp_context_set_ = true;
+#endif
+ if (is_line_clamp_context)
+ space_.EnsureRareData()->is_line_clamp_context = true;
}
void SetLinesUntilClamp(const absl::optional<int>& clamp) {
@@ -421,16 +437,12 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
target_stretch_inline_size);
}
- void SetTargetStretchAscentSize(LayoutUnit target_stretch_ascent_size) {
- DCHECK_GE(target_stretch_ascent_size, LayoutUnit());
- space_.EnsureRareData()->SetTargetStretchAscentSize(
- target_stretch_ascent_size);
- }
-
- void SetTargetStretchDescentSize(LayoutUnit target_stretch_descent_size) {
- DCHECK_GE(target_stretch_descent_size, LayoutUnit());
- space_.EnsureRareData()->SetTargetStretchDescentSize(
- target_stretch_descent_size);
+ void SetTargetStretchBlockSizes(NGConstraintSpace::MathTargetStretchBlockSizes
+ target_stretch_block_sizes) {
+ DCHECK_GE(target_stretch_block_sizes.ascent, LayoutUnit());
+ DCHECK_GE(target_stretch_block_sizes.descent, LayoutUnit());
+ space_.EnsureRareData()->SetTargetStretchBlockSizes(
+ target_stretch_block_sizes);
}
// Creates a new constraint space.
@@ -453,15 +465,6 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
return std::move(space_);
}
- static NGConstraintSpace CloneWithoutFragmentation(
- const NGConstraintSpace& other) {
- DCHECK(other.HasBlockFragmentation());
- NGConstraintSpace copy = other;
- DCHECK(copy.rare_data_);
- copy.rare_data_->block_direction_fragmentation_type = kFragmentNone;
- return copy;
- }
-
private:
NGConstraintSpace space_;
@@ -485,6 +488,7 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
bool is_optimistic_bfc_block_offset_set_ = false;
bool is_forced_bfc_block_offset_set_ = false;
bool is_clearance_offset_set_ = false;
+ bool is_table_cell_set_ = false;
bool is_table_cell_borders_set_ = false;
bool is_table_cell_intrinsic_padding_set_ = false;
bool is_table_cell_alignment_baseline_set_ = false;
@@ -495,6 +499,7 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
bool is_lines_until_clamp_set_ = false;
bool is_table_row_data_set_ = false;
bool is_table_section_data_set_ = false;
+ bool is_line_clamp_context_set_ = false;
bool to_constraint_space_called_ = false;
#endif
@@ -533,12 +538,8 @@ class CORE_EXPORT NGMinMaxConstraintSpaceBuilder final {
{kIndefiniteSize, block_size});
}
- void SetStretchBlockSizeIfAuto(bool b) {
- delegate_.SetStretchBlockSizeIfAuto(b);
- }
-
- void SetIsFixedBlockSizeIndefinite(bool b) {
- delegate_.SetIsFixedBlockSizeIndefinite(b);
+ void SetBlockAutoBehavior(NGAutoBehavior auto_behavior) {
+ delegate_.SetBlockAutoBehavior(auto_behavior);
}
const NGConstraintSpace ToConstraintSpace() {
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 d292db63133..e127ff648ca 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
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.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"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
@@ -39,9 +40,10 @@ void NGContainerFragmentBuilder::PropagateChildData(
const NGPhysicalFragment& child,
LogicalOffset child_offset,
LogicalOffset relative_offset,
- const LayoutInline* inline_container,
+ const NGInlineContainer<LogicalOffset>* inline_container,
absl::optional<LayoutUnit> adjustment_for_oof_propagation) {
- if (adjustment_for_oof_propagation) {
+ if (adjustment_for_oof_propagation &&
+ NeedsOOFPositionedInfoPropagation(child)) {
PropagateOOFPositionedInfo(child, child_offset, relative_offset,
/* offset_adjustment */ LogicalOffset(),
inline_container,
@@ -95,8 +97,9 @@ void NGContainerFragmentBuilder::PropagateChildData(
// Collect any (block) break tokens, but skip break tokens for fragmentainers,
// as they should only escape a fragmentation context at the discretion of the
- // fragmentation context.
- if (has_block_fragmentation_ && !child.IsFragmentainerBox()) {
+ // fragmentation context. Also skip this if there's a pre-set break token.
+ if (has_block_fragmentation_ && !child.IsFragmentainerBox() &&
+ !break_token_) {
const NGBreakToken* child_break_token = child.BreakToken();
switch (child.Type()) {
case NGPhysicalFragment::kFragmentBox:
@@ -144,8 +147,7 @@ void NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
const LogicalOffset& child_offset,
NGLogicalStaticPosition::InlineEdge inline_edge,
NGLogicalStaticPosition::BlockEdge block_edge,
- bool needs_block_offset_adjustment,
- const absl::optional<LogicalRect> containing_block_rect) {
+ bool needs_block_offset_adjustment) {
DCHECK(child);
// If an OOF-positioned candidate has a static-position which uses a
@@ -158,10 +160,9 @@ void NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
oof_positioned_candidates_.emplace_back(
child, NGLogicalStaticPosition{child_offset, inline_edge, block_edge},
- /* inline_container */ nullptr, needs_block_offset_adjustment,
+ NGInlineContainer<LogicalOffset>(), needs_block_offset_adjustment,
/* containing_block */ NGContainingBlock<LogicalOffset>(),
- /* fixedpos_containing_block */ NGContainingBlock<LogicalOffset>(),
- containing_block_rect);
+ /* fixedpos_containing_block */ NGContainingBlock<LogicalOffset>());
}
void NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
@@ -268,8 +269,8 @@ void NGContainerFragmentBuilder::TransferOutOfFlowCandidates(
oof_positioned_candidates_.clear();
}
-void NGContainerFragmentBuilder::
- MoveOutOfFlowDescendantCandidatesToDescendants() {
+void NGContainerFragmentBuilder::MoveOutOfFlowDescendantCandidatesToDescendants(
+ LogicalOffset relative_offset) {
DCHECK(oof_positioned_descendants_.IsEmpty());
std::swap(oof_positioned_candidates_, oof_positioned_descendants_);
@@ -283,14 +284,16 @@ void NGContainerFragmentBuilder::
//
// This checks if the object creating this box will be the container for
// the given descendant.
- if (!candidate.inline_container &&
- IsInlineContainerForNode(candidate.Node(), layout_object_))
- candidate.inline_container = To<LayoutInline>(layout_object_);
+ if (!candidate.inline_container.container &&
+ IsInlineContainerForNode(candidate.Node(), layout_object_)) {
+ candidate.inline_container = NGInlineContainer<LogicalOffset>(
+ To<LayoutInline>(layout_object_), relative_offset);
+ }
// Ensure that the inline_container is a continuation root.
- if (candidate.inline_container) {
- candidate.inline_container =
- To<LayoutInline>(candidate.inline_container->ContinuationRoot());
+ if (candidate.inline_container.container) {
+ candidate.inline_container.container = To<LayoutInline>(
+ candidate.inline_container.container->ContinuationRoot());
}
}
}
@@ -300,11 +303,16 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
LogicalOffset offset,
LogicalOffset relative_offset,
LogicalOffset offset_adjustment,
- const LayoutInline* inline_container,
+ const NGInlineContainer<LogicalOffset>* inline_container,
LayoutUnit containing_block_adjustment,
const NGContainingBlock<LogicalOffset>* fixedpos_containing_block,
LogicalOffset additional_fixedpos_offset) {
- LogicalOffset adjusted_offset = offset + relative_offset + offset_adjustment;
+ // Calling this method without any work to do is expensive, even if it ends up
+ // skipping all its parts (probably due to its size). Make sure that we have a
+ // reason to be here.
+ DCHECK(NeedsOOFPositionedInfoPropagation(fragment));
+
+ LogicalOffset adjusted_offset = offset + offset_adjustment + relative_offset;
// Collect the child's out of flow descendants.
const WritingModeConverter converter(GetWritingDirection(), fragment.Size());
@@ -313,10 +321,17 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
NGLogicalStaticPosition static_position =
descendant.StaticPosition().ConvertToLogical(converter);
- const LayoutInline* new_inline_container = descendant.inline_container;
- if (!new_inline_container &&
- IsInlineContainerForNode(node, inline_container))
- new_inline_container = inline_container;
+ NGInlineContainer<LogicalOffset> new_inline_container;
+ if (descendant.inline_container.container) {
+ new_inline_container.container = descendant.inline_container.container;
+ new_inline_container.relative_offset =
+ converter.ToLogical(descendant.inline_container.relative_offset,
+ PhysicalSize()) +
+ relative_offset;
+ } else if (inline_container &&
+ IsInlineContainerForNode(node, inline_container->container)) {
+ new_inline_container = *inline_container;
+ }
// If an OOF element is inside a fragmentation context, it will be laid out
// once it reaches the fragmentation context root. However, if such OOF
@@ -334,6 +349,12 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
additional_fixedpos_offset != LogicalOffset()) &&
node.Style().GetPosition() == EPosition::kFixed) {
static_position.offset += additional_fixedpos_offset;
+ // Relative offsets should be applied after fragmentation. However, if
+ // there is any relative offset that occurrend before the fixedpos reached
+ // its containing block, that relative offset should be applied to the
+ // static position (before fragmentation).
+ static_position.offset +=
+ relative_offset - fixedpos_containing_block->relative_offset;
if (fixedpos_containing_block && fixedpos_containing_block->fragment) {
AddOutOfFlowFragmentainerDescendant(
{node, static_position, new_inline_container,
@@ -411,23 +432,24 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
}
}
- // If we find a multicol with OOF positioned fragmentainer descendants,
- // then that multicol is an inner multicol with pending OOFs. Those OOFs
- // will be laid out inside the inner multicol when we reach the outermost
- // fragmentation context, so we should not propagate those OOFs up the tree
- // any further.
- if (!box_fragment->HasOutOfFlowPositionedFragmentainerDescendants() ||
- box_fragment->IsFragmentationContextRoot()) {
+ if (!box_fragment->HasOutOfFlowPositionedFragmentainerDescendants())
return;
- }
const auto& out_of_flow_fragmentainer_descendants =
box_fragment->OutOfFlowPositionedFragmentainerDescendants();
for (const auto& descendant : out_of_flow_fragmentainer_descendants) {
const NGPhysicalFragment* containing_block_fragment =
descendant.containing_block.fragment.get();
- if (!containing_block_fragment)
+ if (!containing_block_fragment) {
containing_block_fragment = box_fragment;
+ } else if (box_fragment->IsFragmentationContextRoot()) {
+ // If we find a multicol with OOF positioned fragmentainer descendants,
+ // then that multicol is an inner multicol with pending OOFs. Those OOFs
+ // will be laid out inside the inner multicol when we reach the outermost
+ // fragmentation context, so we should not propagate those OOFs up the
+ // tree any further.
+ continue;
+ }
LogicalOffset containing_block_offset = converter.ToLogical(
descendant.containing_block.offset, containing_block_fragment->Size());
@@ -470,6 +492,11 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
fixedpos_containing_block->relative_offset;
}
+ LogicalOffset inline_relative_offset = converter.ToLogical(
+ descendant.inline_container.relative_offset, PhysicalSize());
+ NGInlineContainer<LogicalOffset> new_inline_container(
+ descendant.inline_container.container, inline_relative_offset);
+
// The static position should remain relative to its containing block
// fragment.
const WritingModeConverter containing_block_converter(
@@ -477,8 +504,16 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
NGLogicalStaticPosition static_position =
descendant.StaticPosition().ConvertToLogical(
containing_block_converter);
+
+ // The relative offset should be applied after fragmentation. Subtract out
+ // the accumulated relative offset from the inline container to the
+ // containing block so that it can be re-applied at the correct time.
+ if (new_inline_container.container &&
+ containing_block_fragment == box_fragment)
+ static_position.offset -= inline_relative_offset;
+
AddOutOfFlowFragmentainerDescendant(
- {descendant.Node(), static_position, descendant.inline_container,
+ {descendant.Node(), static_position, new_inline_container,
/* needs_block_offset_adjustment */ false,
NGContainingBlock<LogicalOffset>(containing_block_offset,
containing_block_rel_offset,
@@ -489,6 +524,12 @@ void NGContainerFragmentBuilder::PropagateOOFPositionedInfo(
}
}
+scoped_refptr<const NGLayoutResult> NGContainerFragmentBuilder::Abort(
+ NGLayoutResult::EStatus status) {
+ return base::AdoptRef(new NGLayoutResult(
+ NGLayoutResult::NGContainerFragmentBuilderPassKey(), status, this));
+}
+
#if DCHECK_IS_ON()
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 dbe212f5473..45e0e85ade8 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
@@ -7,6 +7,7 @@
#include "base/dcheck_is_on.h"
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h"
@@ -17,6 +18,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_early_break.h"
#include "third_party/blink/renderer/core/layout/ng/ng_floats_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_link.h"
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -126,8 +128,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
NGLogicalStaticPosition::InlineEdge =
NGLogicalStaticPosition::kInlineStart,
NGLogicalStaticPosition::BlockEdge = NGLogicalStaticPosition::kBlockStart,
- bool needs_block_offset_adjustment = true,
- const absl::optional<LogicalRect> containing_block_rect = absl::nullopt);
+ bool needs_block_offset_adjustment = true);
void AddOutOfFlowChildCandidate(
const NGLogicalOutOfFlowPositionedNode& candidate);
@@ -205,7 +206,8 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
// position OOF candidates yet, (as a containing box may be split over
// multiple lines), instead we bubble all the descendants up to the parent
// block layout algorithm, to perform the final OOF layout and positioning.
- void MoveOutOfFlowDescendantCandidatesToDescendants();
+ void MoveOutOfFlowDescendantCandidatesToDescendants(
+ LogicalOffset relative_offset);
// Propagate the OOF descendants from a fragment to the builder. Since the OOF
// descendants on the fragment are NGPhysicalOutOfFlowPositionedNodes, we
@@ -217,7 +219,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
LogicalOffset offset,
LogicalOffset relative_offset,
LogicalOffset offset_adjustment = LogicalOffset(),
- const LayoutInline* inline_container = nullptr,
+ const NGInlineContainer<LogicalOffset>* inline_container = nullptr,
LayoutUnit containing_block_adjustment = LayoutUnit(),
const NGContainingBlock<LogicalOffset>* fixedpos_containing_block =
nullptr,
@@ -255,6 +257,23 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
return is_fragmentation_context_root_;
}
+ // There may be cases where a column spanner was previously found but is no
+ // longer accessible. For example, in simplified OOF layout, we may want to
+ // recreate a spanner break for an existing fragment being relaid out, but
+ // the spanner node is no longer available. In such cases,
+ // |has_column_spanner_| may be true while |column_spanner_| is not set.
+ void SetHasColumnSpanner(bool has_column_spanner) {
+ has_column_spanner_ = has_column_spanner;
+ }
+ void SetColumnSpanner(NGBlockNode spanner) {
+ column_spanner_ = spanner;
+ SetHasColumnSpanner(!!column_spanner_);
+ }
+ bool FoundColumnSpanner() const {
+ DCHECK(has_column_spanner_ || !column_spanner_);
+ return has_column_spanner_;
+ }
+
// See NGLayoutResult::AnnotationOverflow().
void SetAnnotationOverflow(LayoutUnit overflow) {
annotation_overflow_ = overflow;
@@ -271,6 +290,8 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
const NGConstraintSpace* ConstraintSpace() const { return space_; }
+ scoped_refptr<const NGLayoutResult> Abort(NGLayoutResult::EStatus);
+
#if DCHECK_IS_ON()
String ToString() const;
#endif
@@ -294,7 +315,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
const NGPhysicalFragment& child,
LogicalOffset child_offset,
LogicalOffset relative_offset,
- const LayoutInline* inline_container = nullptr,
+ const NGInlineContainer<LogicalOffset>* inline_container = nullptr,
absl::optional<LayoutUnit> adjustment_for_oof_propagation = LayoutUnit());
void AddChildInternal(scoped_refptr<const NGPhysicalFragment>,
@@ -324,6 +345,8 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
NGBreakTokenVector child_break_tokens_;
scoped_refptr<const NGInlineBreakToken> last_inline_break_token_;
+ NGBlockNode column_spanner_ = nullptr;
+
scoped_refptr<const NGEarlyBreak> early_break_;
NGBreakAppeal break_appeal_ = kBreakAppealLastResort;
@@ -347,6 +370,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
bool has_descendant_that_depends_on_percentage_block_size_ = false;
bool has_block_fragmentation_ = false;
bool is_fragmentation_context_root_ = false;
+ bool has_column_spanner_ = false;
bool has_oof_candidate_that_needs_block_offset_adjustment_ = false;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc
new file mode 100644
index 00000000000..83ee2d959fe
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h"
+
+namespace blink {
+
+unsigned NGDisableSideEffectsScope::count_ = 0;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h
new file mode 100644
index 00000000000..c16f1b3ff20
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_DISABLE_SIDE_EFFECTS_SCOPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_DISABLE_SIDE_EFFECTS_SCOPE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+// Setup a scope where this layout is for computing purposes, and that it should
+// just return fragments without updating the |LayoutObject| tree, paint
+// properties, and other global objects. This is used e.g., when computing
+// MinMax after layout.
+class CORE_EXPORT NGDisableSideEffectsScope {
+ STACK_ALLOCATED();
+
+ public:
+ NGDisableSideEffectsScope() { ++count_; }
+ ~NGDisableSideEffectsScope() {
+ DCHECK(count_);
+ --count_;
+ }
+
+ static bool IsDisabled() { return count_; }
+
+ private:
+ static unsigned count_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_DISABLE_SIDE_EFFECTS_SCOPE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index 0c0c0dc2202..27ade09f00e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -149,7 +149,8 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
bool has_seen_all_children = false;
if (const auto* token = BreakToken()) {
const auto child_tokens = token->ChildBreakTokens();
- if (wtf_size_t break_token_count = child_tokens.size()) {
+ if (wtf_size_t break_token_count =
+ base::checked_cast<wtf_size_t>(child_tokens.size())) {
scoped_refptr<const NGBlockBreakToken> child_token =
To<NGBlockBreakToken>(child_tokens[0]);
if (child_token) {
@@ -457,7 +458,7 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForFieldsetContent(
/* is_new_fc */ true);
builder.SetCacheSlot(slot);
builder.SetAvailableSize(padding_box_size);
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
// We pass the container's PercentageResolutionSize because percentage
// padding for the fieldset content should be computed as they are in
// the container.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
index e60b23ec367..4ed59c9a20a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -802,7 +802,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentationAutoHeight) {
String dump = DumpFragmentTree(fragment.get());
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:176x500
+ offset:unplaced size:176x520
offset:13,0 size:50x500
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -814,7 +814,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentationAutoHeight) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:176x23
- offset:3,0 size:170x20
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -852,7 +851,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentation) {
String dump = DumpFragmentTree(fragment.get());
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:176x500
+ offset:unplaced size:176x520
offset:13,0 size:50x500
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -864,7 +863,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentation) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:176x23
- offset:3,0 size:170x20
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1373,10 +1371,8 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendBreakInsideAvoid) {
String dump = DumpFragmentTree(fragment.get());
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:1000x110
+ offset:unplaced size:1000x100
offset:0,0 size:20x50
- offset:0,50 size:100x60
- offset:0,0 size:10x60
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1386,9 +1382,9 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendBreakInsideAvoid) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:1000x0
- offset:0,0 size:100x0
- offset:0,0 size:100x0
+ offset:unplaced size:1000x60
+ offset:0,0 size:100x60
+ offset:0,0 size:10x60
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1483,10 +1479,8 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendBreakBeforeAvoid) {
String dump = DumpFragmentTree(fragment.get());
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:1000x125
+ offset:unplaced size:1000x100
offset:0,0 size:20x90
- offset:0,90 size:120x35
- offset:20,0 size:10x25
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1496,9 +1490,9 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendBreakBeforeAvoid) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:1000x10
- offset:0,0 size:120x10
- offset:10,0 size:100x0
+ offset:unplaced size:1000x45
+ offset:0,0 size:120x45
+ offset:20,0 size:10x25
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1710,7 +1704,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallLegendLargeBorderFragmentation) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:220x10
- offset:60,0 size:100x10
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1767,7 +1760,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallerLegendLargeBorderFragmentation) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:220x10
- offset:60,0 size:100x10
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1878,7 +1870,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallerLegendLargeBorderWithBreak) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:220x10
- offset:60,0 size:100x10
)DUMP";
EXPECT_EQ(expectation, dump);
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 fe47c293049..5e83fb5da8f 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
@@ -56,7 +56,10 @@ class CORE_EXPORT NGFragmentBuilder {
}
void SetBlockSize(LayoutUnit block_size) { size_.block_size = block_size; }
+ bool HasBlockSize() const { return size_.block_size != kIndefiniteSize; }
+
void SetIsHiddenForPaint(bool value) { is_hidden_for_paint_ = value; }
+ void SetIsOpaque() { is_opaque_ = true; }
void SetHasCollapsedBorders(bool value) { has_collapsed_borders_ = value; }
@@ -87,8 +90,9 @@ class CORE_EXPORT NGFragmentBuilder {
NGStyleVariant style_variant_;
LogicalSize size_;
LayoutObject* layout_object_ = nullptr;
- scoped_refptr<NGBreakToken> break_token_;
+ scoped_refptr<const NGBreakToken> break_token_;
bool is_hidden_for_paint_ = false;
+ bool is_opaque_ = false;
bool has_collapsed_borders_ = false;
friend class NGPhysicalFragment;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
deleted file mode 100644
index 1d73bb18ea3..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h"
-
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
-
-namespace blink {
-
-NGFragmentChildIterator::NGFragmentChildIterator(
- const NGPhysicalBoxFragment& parent,
- const NGBlockBreakToken* parent_break_token)
- : parent_fragment_(&parent),
- parent_break_token_(parent_break_token),
- is_fragmentation_context_root_(parent.IsFragmentationContextRoot()) {
- current_.link_.fragment = nullptr;
- if (parent_break_token)
- child_break_tokens_ = parent_break_token->ChildBreakTokens();
- if (parent.HasItems()) {
- current_.cursor_.emplace(parent);
- current_.block_break_token_ = parent_break_token;
- UpdateSelfFromCursor();
- } else {
- UpdateSelfFromFragment();
- }
-}
-
-NGFragmentChildIterator::NGFragmentChildIterator(
- const NGInlineCursor& parent,
- const NGBlockBreakToken* parent_break_token,
- base::span<const NGBreakToken* const> child_break_tokens)
- : parent_break_token_(parent_break_token),
- child_break_tokens_(child_break_tokens) {
- current_.block_break_token_ = parent_break_token;
- current_.link_.fragment = nullptr;
- current_.cursor_ = parent.CursorForDescendants();
- UpdateSelfFromCursor();
-}
-
-NGFragmentChildIterator NGFragmentChildIterator::Descend() const {
- if (current_.cursor_) {
- const NGFragmentItem* item = current_.cursor_->CurrentItem();
- // Descend using the cursor if the current item doesn't establish a new
- // formatting context.
- if (!item->IsFormattingContextRoot()) {
- return NGFragmentChildIterator(
- *current_.cursor_,
- current_.BlockBreakToken() ? parent_break_token_ : nullptr,
- child_break_tokens_.subspan(child_break_token_idx_));
- }
- }
- DCHECK(current_.BoxFragment());
- return NGFragmentChildIterator(*current_.BoxFragment(),
- current_.BlockBreakToken());
-}
-
-bool NGFragmentChildIterator::AdvanceChildFragment() {
- DCHECK(parent_fragment_);
- const auto children = parent_fragment_->Children();
- const NGPhysicalBoxFragment* previous_fragment =
- To<NGPhysicalBoxFragment>(current_.link_.fragment);
- DCHECK(previous_fragment);
- if (child_fragment_idx_ < children.size())
- child_fragment_idx_++;
- // There may be line box fragments among the children, and we're not
- // interested in them (lines will already have been handled by the inline
- // cursor).
- SkipToBoxFragment();
- if (child_fragment_idx_ >= children.size())
- return false;
- if (child_break_token_idx_ < child_break_tokens_.size())
- child_break_token_idx_++;
- UpdateSelfFromFragment(previous_fragment);
- return true;
-}
-
-void NGFragmentChildIterator::UpdateSelfFromFragment(
- const NGPhysicalBoxFragment* previous_fragment) {
- DCHECK(parent_fragment_);
- const auto children = parent_fragment_->Children();
- if (child_fragment_idx_ >= children.size())
- return;
- current_.link_ = children[child_fragment_idx_];
- DCHECK(current_.link_.fragment);
- SkipToBlockBreakToken();
- if (child_break_token_idx_ < child_break_tokens_.size()) {
- current_.block_break_token_ =
- To<NGBlockBreakToken>(child_break_tokens_[child_break_token_idx_]);
- // TODO(mstensho): Clean up this. What we're trying to do here is to detect
- // whether the incoming break token matches the current fragment or not.
- // Figuring out if a fragment is generated from a given node is currently
- // not possible without checking the LayoutObject associated.
- const auto* layout_object = current_.link_.fragment->GetLayoutObject();
- if (layout_object &&
- layout_object !=
- current_.block_break_token_->InputNode().GetLayoutBox()) {
- DCHECK(current_.link_.fragment->IsColumnSpanAll() ||
- // List markers are |IsMonolithic| that the flag doesn't matter.
- current_.link_.fragment->IsListMarker());
- current_.break_token_for_fragmentainer_only_ = true;
- } else {
- current_.break_token_for_fragmentainer_only_ = false;
- }
- } else if (is_fragmentation_context_root_ && previous_fragment) {
- // The outgoing break token from one fragmentainer is the incoming break
- // token to the next one. This is also true when there are column spanners
- // (and other types of non-fragmentainers) between two columns
- // (fragmentainers); the outgoing break token from the former column will be
- // ignored by any intervening spanners (and other non-fragmentainers), and
- // then fed into the first column that comes after them, as an incoming
- // break token.
- //
- // A multicol container may contain other kinds of children than
- // fragmentainers, such as a column spanner, a list item marker (if the
- // multicol container is a list item), a rendered legend (if the parent
- // fieldset also establishes a multicol container), or an out-of-flow
- // positioned fragment whose containing block is the multicol container
- // itself (in which case the OOF doesn't participate in the fragmentation
- // context established by the multicol container). We'll leave
- // |current_.block_break_token_| alone then, as it will be used as an
- // incoming break token when we get to the next column.
- if (previous_fragment->IsFragmentainerBox()) {
- current_.block_break_token_ =
- To<NGBlockBreakToken>(previous_fragment->BreakToken());
- current_.break_token_for_fragmentainer_only_ = true;
- }
- } else if (current_.link_.fragment->IsOutOfFlowPositioned() &&
- !To<NGPhysicalBoxFragment>(current_.link_.fragment)
- ->IsFirstForNode()) {
- // If an out-of-flow positioned element fragments beyond the last existing
- // fragmentainer in a nested fragmentation context, instead of creating a
- // new fragmentainer to hold it, we add it to the last existing
- // fragmentainer at the correct inline offset. Therefore, in order to find
- // the corrcet incoming break token in such cases, we must look for any
- // previous fragments inside |children| that were created by the same node.
- current_.block_break_token_ = nullptr;
- const auto* layout_object = current_.link_.fragment->GetLayoutObject();
- DCHECK(layout_object);
- for (wtf_size_t index = child_fragment_idx_; index > 0; index--) {
- const auto* child_fragment = children[index - 1].fragment;
- if (layout_object == child_fragment->GetLayoutObject()) {
- current_.block_break_token_ = To<NGBlockBreakToken>(
- To<NGPhysicalBoxFragment>(child_fragment)->BreakToken());
- current_.break_token_for_fragmentainer_only_ = false;
- break;
- }
- }
- } else {
- current_.block_break_token_ = nullptr;
- }
-}
-
-bool NGFragmentChildIterator::AdvanceWithCursor() {
- DCHECK(current_.cursor_);
- current_.cursor_->MoveToNextSkippingChildren();
- UpdateSelfFromCursor();
- if (current_.cursor_->CurrentItem())
- return true;
- // If there are more items, proceed and see if we have box fragment
- // children. There may be out-of-flow positioned child fragments.
- if (!parent_fragment_)
- return false;
- current_.cursor_.reset();
- SkipToBoxFragment();
- UpdateSelfFromFragment();
- return !IsAtEnd();
-}
-
-void NGFragmentChildIterator::UpdateSelfFromCursor() {
- DCHECK(current_.cursor_);
- // For inline items we just use the incoming break token to the containing
- // block.
- current_.block_break_token_ = parent_break_token_;
- const NGFragmentItem* item = current_.cursor_->CurrentItem();
- if (!item) {
- current_.link_.fragment = nullptr;
- return;
- }
- current_.link_ = {item->BoxFragment(), item->OffsetInContainerFragment()};
-}
-
-void NGFragmentChildIterator::SkipToBoxFragment() {
- for (const auto children = parent_fragment_->Children();
- child_fragment_idx_ < children.size(); child_fragment_idx_++) {
- if (children[child_fragment_idx_].fragment->IsBox())
- break;
- }
-}
-
-void NGFragmentChildIterator::SkipToBlockBreakToken() {
- // There may be inline break tokens here. Ignore them.
- while (child_break_token_idx_ < child_break_tokens_.size()) {
- const auto* current_break_token = DynamicTo<NGBlockBreakToken>(
- child_break_tokens_[child_break_token_idx_]);
- // Skip over any out-of-flow positioned break tokens that are the result of
- // a break before.
- if (current_break_token &&
- (!current_break_token->InputNode().IsOutOfFlowPositioned() ||
- !current_break_token->IsBreakBefore()))
- return;
- child_break_token_idx_++;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
deleted file mode 100644
index 435a0af1be8..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_CHILD_ITERATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_CHILD_ITERATOR_H_
-
-#include "base/containers/span.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_link.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
-
-namespace blink {
-
-class LayoutObject;
-class NGBlockBreakToken;
-
-// Iterator for children of a box fragment. Supports fragment items and break
-// tokens. To advance to the next sibling, call |Advance()|. To descend into
-// children of the current child, call |Descend()|.
-//
-// Using this class requires LayoutNGFragmentItem to be enabled. While fragment
-// items are in a flat list representing the contents of an inline formatting
-// context, the iterator will to a certain extent restore the object hierarchy,
-// so that we can calculate the global offset of children of a relatively
-// positioned inline correctly.
-class CORE_EXPORT NGFragmentChildIterator {
- STACK_ALLOCATED();
-
- public:
- explicit NGFragmentChildIterator(
- const NGPhysicalBoxFragment& parent,
- const NGBlockBreakToken* parent_break_token = nullptr);
-
- // Create a child iterator for the current child.
- NGFragmentChildIterator Descend() const;
-
- // Move to the next sibling. Return false if there's no next sibling. Once
- // false is returned, this object is in an unusable state, with the exception
- // that calling IsAtEnd() is allowed.
- bool Advance() {
- if (current_.cursor_)
- return AdvanceWithCursor();
- return AdvanceChildFragment();
- }
-
- bool IsAtEnd() {
- if (current_.cursor_)
- return !*current_.cursor_;
- DCHECK(parent_fragment_);
- const auto children = parent_fragment_->Children();
- return child_fragment_idx_ >= children.size();
- }
-
- class Current {
- STACK_ALLOCATED();
-
- friend class NGFragmentChildIterator;
-
- public:
- // Return the current NGLink. Note that its offset is relative to the inline
- // formatting context root, if the fragment / item participates in one.
- const NGLink& Link() const { return link_; }
-
- const NGPhysicalBoxFragment* BoxFragment() const {
- return To<NGPhysicalBoxFragment>(link_.fragment);
- }
- const NGFragmentItem* FragmentItem() const {
- if (!cursor_)
- return nullptr;
- return cursor_->CurrentItem();
- }
-
- // Get the incoming break token for the current child, i.e. the context at
- // which layout of this child's node was resumed. Note that for text and
- // non-atomic inlines this will be the incoming block break token to the
- // inline formatting context root. For monolithic content, no break token
- // will be returned (since such content isn't considered to participate in a
- // fragmentation context).
- const NGBlockBreakToken* BlockBreakToken() const {
- if (LIKELY(!block_break_token_))
- return nullptr;
- if (link_.fragment) {
- // Don't pass the break token into monolithic content.
- if (link_.fragment->IsMonolithic())
- return nullptr;
- // If the break token we've found is from a fragmentainer, it's only to
- // be used by a subsequent fragmentainer. Other fragment types (such as
- // column spanners) need to ignore it.
- if (break_token_for_fragmentainer_only_ &&
- !link_.fragment->IsFragmentainerBox())
- return nullptr;
- }
- return block_break_token_;
- }
-
- const LayoutObject* GetLayoutObject() const {
- if (const NGFragmentItem* item = FragmentItem())
- return item->GetLayoutObject();
- return BoxFragment()->GetLayoutObject();
- }
-
- private:
- NGLink link_;
- absl::optional<NGInlineCursor> cursor_;
- const NGBlockBreakToken* block_break_token_ = nullptr;
- bool break_token_for_fragmentainer_only_ = false;
- };
-
- const Current& GetCurrent() const { return current_; }
- const Current& operator*() const { return current_; }
- const Current* operator->() const { return &current_; }
-
- private:
- NGFragmentChildIterator(
- const NGInlineCursor& parent,
- const NGBlockBreakToken* parent_break_token,
- base::span<const NGBreakToken* const> child_break_tokens);
-
- bool AdvanceChildFragment();
- void UpdateSelfFromFragment(
- const NGPhysicalBoxFragment* previous_fragment = nullptr);
-
- bool AdvanceWithCursor();
- void UpdateSelfFromCursor();
- void SkipToBoxFragment();
- void SkipToBlockBreakToken();
-
- const NGPhysicalBoxFragment* parent_fragment_ = nullptr;
- const NGBlockBreakToken* parent_break_token_ = nullptr;
- Current current_;
- base::span<const NGBreakToken* const> child_break_tokens_;
- wtf_size_t child_fragment_idx_ = 0;
- wtf_size_t child_break_token_idx_ = 0;
- bool is_fragmentation_context_root_ = false;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_CHILD_ITERATOR_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator_test.cc
deleted file mode 100644
index 68de9194146..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator_test.cc
+++ /dev/null
@@ -1,806 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-
-namespace blink {
-namespace {
-
-class NGFragmentChildIteratorTest
- : public NGBaseLayoutAlgorithmTest,
- private ScopedLayoutNGBlockFragmentationForTest {
- protected:
- NGFragmentChildIteratorTest()
- : ScopedLayoutNGBlockFragmentationForTest(true) {}
-
- scoped_refptr<const NGPhysicalBoxFragment> RunBlockLayoutAlgorithm(
- Element* element) {
- NGBlockNode container(element->GetLayoutBox());
- NGConstraintSpace space = ConstructBlockLayoutTestConstraintSpace(
- {WritingMode::kHorizontalTb, TextDirection::kLtr},
- LogicalSize(LayoutUnit(1000), kIndefiniteSize));
- return NGBaseLayoutAlgorithmTest::RunBlockLayoutAlgorithm(container, space);
- }
-};
-
-TEST_F(NGFragmentChildIteratorTest, Basic) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- <div id="child1">
- <div id="grandchild"></div>
- </div>
- <div id="child2"></div>
- </div>
- )HTML");
-
- const LayoutObject* child1 = GetLayoutObjectByElementId("child1");
- const LayoutObject* child2 = GetLayoutObjectByElementId("child2");
- const LayoutObject* grandchild = GetLayoutObjectByElementId("grandchild");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
- EXPECT_FALSE(iterator1.IsAtEnd());
-
- const NGPhysicalBoxFragment* fragment = iterator1->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child1);
- EXPECT_FALSE(iterator1.IsAtEnd());
-
- NGFragmentChildIterator iterator2 = iterator1.Descend();
- EXPECT_FALSE(iterator2.IsAtEnd());
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), grandchild);
- EXPECT_FALSE(iterator2.IsAtEnd());
- EXPECT_FALSE(iterator2.Advance());
- EXPECT_TRUE(iterator2.IsAtEnd());
-
- EXPECT_TRUE(iterator1.Advance());
- fragment = iterator1->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child2);
- EXPECT_FALSE(iterator1.IsAtEnd());
-
- // #child2 has no children.
- EXPECT_TRUE(iterator1.Descend().IsAtEnd());
-
- // No more children left.
- EXPECT_FALSE(iterator1.Advance());
- EXPECT_TRUE(iterator1.IsAtEnd());
-}
-
-TEST_F(NGFragmentChildIteratorTest, BasicInline) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- xxx
- <span id="span1" style="border:solid;">
- <div id="float1" style="float:left;"></div>
- xxx
- </span>
- xxx
- </div>
- )HTML");
-
- const LayoutObject* span1 = GetLayoutObjectByElementId("span1");
- const LayoutObject* float1 = GetLayoutObjectByElementId("float1");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
-
- EXPECT_FALSE(iterator1->BoxFragment());
- const NGFragmentItem* fragment_item = iterator1->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_EQ(fragment_item->Type(), NGFragmentItem::kLine);
-
- // Descend into the line box.
- NGFragmentChildIterator iterator2 = iterator1.Descend();
- fragment_item = iterator2->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_TRUE(fragment_item->IsText());
-
- EXPECT_TRUE(iterator2.Advance());
- const NGPhysicalBoxFragment* fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), span1);
-
- // Descend into children of #span1.
- NGFragmentChildIterator iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), float1);
-
- EXPECT_TRUE(iterator3.Advance());
- fragment_item = iterator3->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_TRUE(fragment_item->IsText());
- EXPECT_FALSE(iterator3.Advance());
-
- // Continue with siblings of #span1.
- EXPECT_TRUE(iterator2.Advance());
- fragment_item = iterator2->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_TRUE(fragment_item->IsText());
-
- EXPECT_FALSE(iterator2.Advance());
- EXPECT_FALSE(iterator1.Advance());
-}
-
-TEST_F(NGFragmentChildIteratorTest, InlineBlock) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- xxx
- <span id="inlineblock">
- <div id="float1" style="float:left;"></div>
- </span>
- xxx
- </div>
- )HTML");
-
- const LayoutObject* inlineblock = GetLayoutObjectByElementId("inlineblock");
- const LayoutObject* float1 = GetLayoutObjectByElementId("float1");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
-
- EXPECT_FALSE(iterator1->BoxFragment());
- const NGFragmentItem* fragment_item = iterator1->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_EQ(fragment_item->Type(), NGFragmentItem::kLine);
-
- // Descend into the line box.
- NGFragmentChildIterator iterator2 = iterator1.Descend();
- fragment_item = iterator2->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_TRUE(fragment_item->IsText());
-
- EXPECT_TRUE(iterator2.Advance());
- const NGPhysicalBoxFragment* fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), inlineblock);
-
- // Descend into children of #inlineblock.
- NGFragmentChildIterator iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), float1);
- EXPECT_FALSE(iterator3.Advance());
-
- // Continue with siblings of #inlineblock.
- EXPECT_TRUE(iterator2.Advance());
- fragment_item = iterator2->FragmentItem();
- ASSERT_TRUE(fragment_item);
- EXPECT_TRUE(fragment_item->IsText());
-
- EXPECT_FALSE(iterator2.Advance());
- EXPECT_FALSE(iterator1.Advance());
-}
-
-TEST_F(NGFragmentChildIteratorTest, FloatsInInline) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- <span id="span1" style="border:solid;">
- <div id="float1" style="float:left;">
- <div id="child"></div>
- </div>
- </span>
- </div>
- )HTML");
-
- const LayoutObject* span1 = GetLayoutObjectByElementId("span1");
- const LayoutObject* float1 = GetLayoutObjectByElementId("float1");
- const LayoutObject* child = GetLayoutObjectByElementId("child");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
-
- const NGPhysicalBoxFragment* fragment = iterator1->BoxFragment();
- EXPECT_FALSE(fragment);
- const NGFragmentItem* item = iterator1->FragmentItem();
- ASSERT_TRUE(item);
- EXPECT_EQ(item->Type(), NGFragmentItem::kLine);
-
- // Descend into the line box.
- NGFragmentChildIterator iterator2 = iterator1.Descend();
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), span1);
-
- // Descend into children of #span1.
- NGFragmentChildIterator iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), float1);
-
- // Descend into children of #float1.
- NGFragmentChildIterator iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child);
-
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
- EXPECT_FALSE(iterator2.Advance());
- EXPECT_FALSE(iterator1.Advance());
-}
-
-TEST_F(NGFragmentChildIteratorTest, AbsposAndLine) {
- SetBodyInnerHTML(R"HTML(
- <div id="container" style="position:relative;">
- <div id="abspos" style="position:absolute;"></div>
- xxx
- </div>
- )HTML");
-
- const LayoutObject* abspos = GetLayoutObjectByElementId("abspos");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
-
- const NGPhysicalBoxFragment* fragment = iterator1->BoxFragment();
- EXPECT_FALSE(fragment);
- const NGFragmentItem* item = iterator1->FragmentItem();
- ASSERT_TRUE(item);
- EXPECT_EQ(item->Type(), NGFragmentItem::kLine);
-
- // Descend into the line box.
- NGFragmentChildIterator iterator2 = iterator1.Descend();
-
- fragment = iterator2->BoxFragment();
- EXPECT_FALSE(fragment);
- item = iterator2->FragmentItem();
- ASSERT_TRUE(item);
- EXPECT_TRUE(item->IsText());
- EXPECT_FALSE(iterator2.Advance());
-
- // The abspos is a sibling of the line box.
- EXPECT_TRUE(iterator1.Advance());
- fragment = iterator1->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), abspos);
- EXPECT_FALSE(iterator1.Advance());
-}
-
-TEST_F(NGFragmentChildIteratorTest, BasicMulticol) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- <div id="mc" style="columns:3; padding:2px; column-fill:auto; column-gap:10px; width:320px; height:100px;">
- <div id="child" style="margin-top:30px; margin-left:4px; height:200px;"></div>
- </div>
- </div>
- )HTML");
-
- const LayoutObject* mc = GetLayoutObjectByElementId("mc");
- const LayoutObject* child = GetLayoutObjectByElementId("child");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator(*container.get());
-
- const NGPhysicalBoxFragment* fragment = iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), mc);
-
- // First column.
- NGFragmentChildIterator child_iterator = iterator.Descend();
- fragment = child_iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(child_iterator->Link().offset.top, LayoutUnit(2));
- EXPECT_EQ(child_iterator->Link().offset.left, LayoutUnit(2));
- EXPECT_EQ(fragment->Size().height, LayoutUnit(100));
- EXPECT_FALSE(fragment->GetLayoutObject());
- EXPECT_FALSE(child_iterator->BlockBreakToken());
-
- NGFragmentChildIterator grandchild_iterator = child_iterator.Descend();
- fragment = grandchild_iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(grandchild_iterator->Link().offset.top, LayoutUnit(30));
- EXPECT_EQ(grandchild_iterator->Link().offset.left, LayoutUnit(4));
- EXPECT_EQ(fragment->Size().height, LayoutUnit(70));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- EXPECT_FALSE(grandchild_iterator.Advance());
- EXPECT_FALSE(grandchild_iterator->BlockBreakToken());
-
- // Second column.
- ASSERT_TRUE(child_iterator.Advance());
- fragment = child_iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(child_iterator->Link().offset.top, LayoutUnit(2));
- EXPECT_EQ(child_iterator->Link().offset.left, LayoutUnit(112));
- EXPECT_EQ(fragment->Size().height, LayoutUnit(100));
- EXPECT_FALSE(fragment->GetLayoutObject());
- const auto* break_token = child_iterator->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(100));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc);
-
- grandchild_iterator = child_iterator.Descend();
- fragment = grandchild_iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(grandchild_iterator->Link().offset.top, LayoutUnit(0));
- EXPECT_EQ(grandchild_iterator->Link().offset.left, LayoutUnit(4));
- EXPECT_EQ(fragment->Size().height, LayoutUnit(100));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- EXPECT_FALSE(grandchild_iterator.Advance());
- break_token = grandchild_iterator->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(70));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child);
-
- // Third column.
- ASSERT_TRUE(child_iterator.Advance());
- fragment = child_iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(child_iterator->Link().offset.top, LayoutUnit(2));
- EXPECT_EQ(child_iterator->Link().offset.left, LayoutUnit(222));
- EXPECT_EQ(fragment->Size().height, LayoutUnit(100));
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = child_iterator->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(200));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc);
-
- grandchild_iterator = child_iterator.Descend();
- fragment = grandchild_iterator->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(grandchild_iterator->Link().offset.top, LayoutUnit(0));
- EXPECT_EQ(grandchild_iterator->Link().offset.left, LayoutUnit(4));
- EXPECT_EQ(fragment->Size().height, LayoutUnit(30));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- EXPECT_FALSE(grandchild_iterator.Advance());
- break_token = grandchild_iterator->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(170));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child);
-
- EXPECT_FALSE(child_iterator.Advance());
- EXPECT_FALSE(iterator.Advance());
-}
-
-TEST_F(NGFragmentChildIteratorTest, ColumnSpanner) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- <div id="mc" style="columns:2;">
- <div id="child">
- <div id="grandchild1" style="height:150px;"></div>
- <div id="spanner" style="column-span:all; height:11px;"></div>
- <div id="grandchild2" style="height:66px;"></div>
- </div>
- </div>
- </div>
- )HTML");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
-
- const LayoutObject* mc = GetLayoutObjectByElementId("mc");
- const LayoutObject* child = GetLayoutObjectByElementId("child");
- const LayoutObject* spanner = GetLayoutObjectByElementId("spanner");
- const LayoutObject* grandchild1 = GetLayoutObjectByElementId("grandchild1");
- const LayoutObject* grandchild2 = GetLayoutObjectByElementId("grandchild2");
-
- const NGPhysicalBoxFragment* fragment = iterator1->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), mc);
-
- // First column before spanner.
- NGFragmentChildIterator iterator2 = iterator1.Descend();
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(fragment->Size().height, LayoutUnit(75));
- EXPECT_FALSE(fragment->GetLayoutObject());
- EXPECT_FALSE(iterator2->BlockBreakToken());
-
- // First fragment for #child.
- NGFragmentChildIterator iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(75));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- EXPECT_FALSE(iterator3->BlockBreakToken());
-
- // First fragment for #grandchild1.
- NGFragmentChildIterator iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(75));
- EXPECT_EQ(fragment->GetLayoutObject(), grandchild1);
- EXPECT_FALSE(iterator4->BlockBreakToken());
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
-
- // Second column before spanner.
- EXPECT_TRUE(iterator2.Advance());
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(fragment->Size().height, LayoutUnit(75));
- EXPECT_FALSE(fragment->GetLayoutObject());
- const auto* break_token = iterator2->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(75));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc);
-
- // Second fragment for #child.
- iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(75));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- break_token = iterator3->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(75));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child);
-
- // Second fragment for #grandchild1.
- iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(75));
- EXPECT_EQ(fragment->GetLayoutObject(), grandchild1);
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(75));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), grandchild1);
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
-
- // The spanner.
- EXPECT_TRUE(iterator2.Advance());
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(11));
- EXPECT_EQ(fragment->GetLayoutObject(), spanner);
- EXPECT_FALSE(iterator2->BlockBreakToken());
-
- // First column after spanner.
- EXPECT_TRUE(iterator2.Advance());
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(fragment->Size().height, LayoutUnit(33));
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator2->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(150));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc);
-
- // Third fragment for #child.
- iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(33));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- break_token = iterator3->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(150));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child);
-
- // First fragment for #grandchild2.
- iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(33));
- EXPECT_EQ(fragment->GetLayoutObject(), grandchild2);
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_TRUE(break_token->IsBreakBefore());
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), grandchild2);
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
-
- // Second column after spanner.
- EXPECT_TRUE(iterator2.Advance());
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_EQ(fragment->Size().height, LayoutUnit(33));
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator2->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(183));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc);
-
- // Fourth fragment for #child.
- iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(33));
- EXPECT_EQ(fragment->GetLayoutObject(), child);
- break_token = iterator3->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(183));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child);
-
- // Second fragment for #grandchild2.
- iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->Size().height, LayoutUnit(33));
- EXPECT_EQ(fragment->GetLayoutObject(), grandchild2);
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(33));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), grandchild2);
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
-
- EXPECT_FALSE(iterator2.Advance());
- EXPECT_FALSE(iterator1.Advance());
-}
-
-TEST_F(NGFragmentChildIteratorTest, NestedWithColumnSpanner) {
- SetBodyInnerHTML(R"HTML(
- <div id="container">
- <div id="mc1" style="columns:2; column-fill:auto; height:100px;">
- <div id="mc2" style="columns:2;">
- <div id="child1" style="height:150px;"></div>
- <div id="spanner1" style="column-span:all;">
- <div id="spanner1child" style="height:55px;"></div>
- </div>
- <div id="child2" style="height:50px;"></div>
- <div id="spanner2" style="column-span:all;">
- <div id="spanner2child" style="height:20px;"></div>
- </div>
- <div id="child3" style="height:20px;"></div>
- </div>
- </div>
- </div>
- )HTML");
-
- scoped_refptr<const NGPhysicalBoxFragment> container =
- RunBlockLayoutAlgorithm(GetElementById("container"));
- NGFragmentChildIterator iterator1(*container.get());
-
- const LayoutObject* mc1 = GetLayoutObjectByElementId("mc1");
- const LayoutObject* mc2 = GetLayoutObjectByElementId("mc2");
- const LayoutObject* child1 = GetLayoutObjectByElementId("child1");
- const LayoutObject* child2 = GetLayoutObjectByElementId("child2");
- const LayoutObject* child3 = GetLayoutObjectByElementId("child3");
- const LayoutObject* spanner1 = GetLayoutObjectByElementId("spanner1");
- const LayoutObject* spanner2 = GetLayoutObjectByElementId("spanner2");
- const LayoutObject* spanner1child =
- GetLayoutObjectByElementId("spanner1child");
- const LayoutObject* spanner2child =
- GetLayoutObjectByElementId("spanner2child");
-
- const NGPhysicalBoxFragment* fragment = iterator1->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), mc1);
-
- // First outer column.
- NGFragmentChildIterator iterator2 = iterator1.Descend();
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- EXPECT_FALSE(iterator2->BlockBreakToken());
-
- // First fragment for #mc2.
- NGFragmentChildIterator iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), mc2);
- EXPECT_FALSE(iterator3->BlockBreakToken());
-
- // First inner column in first outer column.
- NGFragmentChildIterator iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- EXPECT_FALSE(iterator4->BlockBreakToken());
-
- // First fragment for #child1.
- NGFragmentChildIterator iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child1);
- EXPECT_FALSE(iterator5->BlockBreakToken());
- EXPECT_FALSE(iterator5.Advance());
-
- // Second inner column in first outer column.
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- const auto* break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(75));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc2);
-
- // Second fragment for #child1.
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child1);
- break_token = iterator5->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(75));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child1);
-
- // First fragment for #spanner1 (it's split into the first and second outer
- // columns).
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), spanner1);
- EXPECT_FALSE(iterator4->BlockBreakToken());
-
- // First fragment for #spanner1child
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), spanner1child);
- EXPECT_FALSE(iterator5->BlockBreakToken());
- EXPECT_FALSE(iterator5.Advance());
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
-
- // Second outer column
- EXPECT_TRUE(iterator2.Advance());
- fragment = iterator2->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator2->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(100));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc1);
-
- // Second fragment for #mc2.
- iterator3 = iterator2.Descend();
- fragment = iterator3->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), mc2);
- break_token = iterator3->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(100));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc2);
-
- // Second fragment for #spanner1 (it's split into the first and second outer
- // columns).
- iterator4 = iterator3.Descend();
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), spanner1);
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(25));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), spanner1);
-
- // Second fragment for #spanner1child.
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), spanner1child);
- break_token = iterator5->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(25));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), spanner1child);
- EXPECT_FALSE(iterator5.Advance());
-
- // First inner column after first spanner in second outer column.
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(150));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc2);
-
- // First fragment for #child2.
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child2);
- break_token = iterator5->BlockBreakToken();
- EXPECT_TRUE(break_token);
- EXPECT_TRUE(break_token->IsBreakBefore());
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child2);
- EXPECT_FALSE(iterator5.Advance());
-
- // Second inner column after first spanner in second outer column.
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(175));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc2);
-
- // Second fragment for #child2.
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child2);
- break_token = iterator5->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(25));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child2);
- EXPECT_FALSE(iterator5.Advance());
-
- // The only fragment for #spanner2
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), spanner2);
- EXPECT_FALSE(iterator4->BlockBreakToken());
-
- // First fragment for #spanner2child
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), spanner2child);
- EXPECT_FALSE(iterator5->BlockBreakToken());
- EXPECT_FALSE(iterator5.Advance());
-
- // First inner column after second spanner in second outer column.
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(200));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc2);
-
- // First fragment for #child3.
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child3);
- break_token = iterator5->BlockBreakToken();
- EXPECT_TRUE(break_token);
- EXPECT_TRUE(break_token->IsBreakBefore());
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child3);
- EXPECT_FALSE(iterator5.Advance());
-
- // Second inner column after second spanner in second outer column.
- EXPECT_TRUE(iterator4.Advance());
- fragment = iterator4->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_TRUE(fragment->IsColumnBox());
- EXPECT_FALSE(fragment->GetLayoutObject());
- break_token = iterator4->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(210));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), mc2);
-
- // Second fragment for #child3.
- iterator5 = iterator4.Descend();
- fragment = iterator5->BoxFragment();
- ASSERT_TRUE(fragment);
- EXPECT_EQ(fragment->GetLayoutObject(), child3);
- break_token = iterator5->BlockBreakToken();
- ASSERT_TRUE(break_token);
- EXPECT_EQ(break_token->ConsumedBlockSize(), LayoutUnit(10));
- EXPECT_EQ(break_token->InputNode().GetLayoutBox(), child3);
- EXPECT_FALSE(iterator5.Advance());
- EXPECT_FALSE(iterator4.Advance());
- EXPECT_FALSE(iterator3.Advance());
- EXPECT_FALSE(iterator2.Advance());
- EXPECT_FALSE(iterator1.Advance());
-}
-
-} // anonymous namespace
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index 22093948a2b..cd3db2fcbcc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
+#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
@@ -58,19 +59,33 @@ inline int FragmentainerBreakPrecedence(EBreakBetween break_value) {
// Return layout overflow block-size that's not clipped (or simply the
// block-size if it *is* clipped).
-LayoutUnit BlockAxisLayoutOverflow(const NGPhysicalFragment& fragment,
+LayoutUnit BlockAxisLayoutOverflow(const NGLayoutResult& result,
WritingDirectionMode writing_direction) {
- const auto* box = DynamicTo<NGPhysicalBoxFragment>(fragment);
- if (box && box->HasNonVisibleOverflow()) {
- OverflowClipAxes block_axis =
- writing_direction.IsHorizontal() ? kOverflowClipY : kOverflowClipX;
- if (box->GetOverflowClipAxes() & block_axis)
- box = nullptr;
+ const NGPhysicalFragment& fragment = result.PhysicalFragment();
+ LayoutUnit block_size = NGFragment(writing_direction, fragment).BlockSize();
+ if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(fragment)) {
+ if (box->HasNonVisibleOverflow()) {
+ OverflowClipAxes block_axis =
+ writing_direction.IsHorizontal() ? kOverflowClipY : kOverflowClipX;
+ if (box->GetOverflowClipAxes() & block_axis)
+ box = nullptr;
+ }
+ if (box) {
+ WritingModeConverter converter(writing_direction, fragment.Size());
+ block_size =
+ std::max(block_size,
+ converter.ToLogical(box->LayoutOverflow()).BlockEndOffset());
+ }
+ return block_size;
}
- PhysicalRect rect = fragment.LocalRect();
- if (box)
- rect.UniteEvenIfEmpty(box->LayoutOverflow());
- return writing_direction.IsHorizontal() ? rect.Bottom() : rect.Right();
+
+ // Ruby annotations do not take up space in the line box, so we need this to
+ // make sure that we don't let them cross the fragmentation line without
+ // noticing.
+ LayoutUnit annotation_overflow = result.AnnotationOverflow();
+ if (annotation_overflow > LayoutUnit())
+ block_size += annotation_overflow;
+ return block_size;
}
} // anonymous namespace
@@ -482,6 +497,58 @@ NGBreakStatus FinishFragmentation(NGBlockNode node,
return NGBreakStatus::kContinue;
}
+NGBreakStatus FinishFragmentationForFragmentainer(
+ const NGConstraintSpace& space,
+ NGBoxFragmentBuilder* builder) {
+ DCHECK(builder->IsFragmentainerBoxType());
+ const NGBlockBreakToken* previous_break_token = builder->PreviousBreakToken();
+ LayoutUnit consumed_block_size =
+ previous_break_token ? previous_break_token->ConsumedBlockSize()
+ : LayoutUnit();
+ if (space.HasKnownFragmentainerBlockSize()) {
+ // Just copy the block-size from the constraint space. Calculating the
+ // size the regular way would cause some problems with overflow. For one,
+ // we don't want to produce a break token if there's no child content that
+ // requires it. When we lay out, we use FragmentainerCapacity(), so this
+ // is what we need to add to consumed block-size for the next break
+ // token. The fragment block-size itself will be based directly on the
+ // fragmentainer size from the constraint space, though.
+ LayoutUnit block_size = space.FragmentainerBlockSize();
+ LayoutUnit fragmentainer_capacity = FragmentainerCapacity(space);
+ builder->SetFragmentBlockSize(block_size);
+ consumed_block_size += fragmentainer_capacity;
+ builder->SetConsumedBlockSize(consumed_block_size);
+
+ // We clamp the fragmentainer block size from 0 to 1 for legacy write-back
+ // if there is content that overflows the zero-height fragmentainer.
+ // Set the consumed block size adjustment for legacy if this results
+ // in a different consumed block size than is used for NG layout.
+ LayoutUnit consumed_block_size_for_legacy =
+ previous_break_token
+ ? previous_break_token->ConsumedBlockSizeForLegacy()
+ : LayoutUnit();
+ LayoutUnit legacy_fragmentainer_block_size =
+ (builder->IntrinsicBlockSize() > LayoutUnit()) ? fragmentainer_capacity
+ : block_size;
+ LayoutUnit consumed_block_size_legacy_adjustment =
+ consumed_block_size_for_legacy + legacy_fragmentainer_block_size -
+ consumed_block_size;
+ builder->SetConsumedBlockSizeLegacyAdjustment(
+ consumed_block_size_legacy_adjustment);
+ } else {
+ // When we are in the initial column balancing pass, use the block-size
+ // calculated by the algorithm. Since any previously consumed block-size
+ // is already baked in (in order to correctly honor specified block-size
+ // (which makes sense to everyone but fragmentainers)), we need to extract
+ // it again now.
+ LayoutUnit fragments_total_block_size = builder->FragmentsTotalBlockSize();
+ builder->SetFragmentBlockSize(fragments_total_block_size -
+ consumed_block_size);
+ builder->SetConsumedBlockSize(fragments_total_block_size);
+ }
+ return NGBreakStatus::kContinue;
+}
+
NGBreakStatus BreakBeforeChildIfNeeded(const NGConstraintSpace& space,
NGLayoutInputNode child,
const NGLayoutResult& layout_result,
@@ -694,9 +761,8 @@ bool MovePastBreakpoint(const NGConstraintSpace& space,
return true;
}
} else if (refuse_break_before ||
- BlockAxisLayoutOverflow(physical_fragment,
- space.GetWritingDirection()) <=
- space_left) {
+ BlockAxisLayoutOverflow(
+ layout_result, space.GetWritingDirection()) <= space_left) {
// The child either fits, or we are not allowed to break. So we can move
// past this breakpoint.
if (child.IsBlock() && builder) {
@@ -801,7 +867,7 @@ NGConstraintSpace CreateConstraintSpaceForColumns(
parent_space, parent_space.GetWritingDirection(), /* is_new_fc */ true);
space_builder.SetAvailableSize(column_size);
space_builder.SetPercentageResolutionSize(percentage_resolution_size);
- space_builder.SetStretchInlineSizeIfAuto(true);
+ space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
space_builder.SetFragmentationType(kFragmentColumn);
space_builder.SetFragmentainerBlockSize(column_size.block_size);
space_builder.SetIsAnonymous(true);
@@ -846,4 +912,89 @@ NGConstraintSpace CreateConstraintSpaceForMulticol(
return space_builder.ToConstraintSpace();
}
+const NGBlockBreakToken* PreviousFragmentainerBreakToken(
+ const NGBoxFragmentBuilder& container_builder,
+ wtf_size_t index) {
+ const NGBlockBreakToken* previous_break_token = nullptr;
+ for (wtf_size_t i = index; i > 0; --i) {
+ auto* previous_fragment =
+ container_builder.Children()[i - 1].fragment.get();
+ if (previous_fragment->IsFragmentainerBox()) {
+ previous_break_token = To<NGBlockBreakToken>(
+ To<NGPhysicalBoxFragment>(previous_fragment)->BreakToken());
+ break;
+ }
+ }
+ return previous_break_token;
+}
+
+const NGBlockBreakToken* FindPreviousBreakToken(
+ const NGPhysicalBoxFragment& fragment) {
+ const LayoutBox* box = To<LayoutBox>(fragment.GetLayoutObject());
+ DCHECK(box);
+ DCHECK_GE(box->PhysicalFragmentCount(), 1u);
+
+ // Bail early if this is the first fragment. There'll be no previous break
+ // token then.
+ if (fragment.IsFirstForNode())
+ return nullptr;
+
+ // If this isn't the first fragment, it means that there has to be multiple
+ // fragments.
+ DCHECK_GT(box->PhysicalFragmentCount(), 1u);
+
+ const NGPhysicalBoxFragment* previous_fragment;
+ if (const auto* break_token = To<NGBlockBreakToken>(fragment.BreakToken())) {
+ // The sequence number of the outgoing break token is the same as the index
+ // of this fragment.
+ DCHECK_GE(break_token->SequenceNumber(), 1u);
+ previous_fragment =
+ box->GetPhysicalFragment(break_token->SequenceNumber() - 1);
+ } else {
+ // This is the last fragment, so its incoming break token will be the
+ // outgoing one from the penultimate fragment.
+ previous_fragment =
+ box->GetPhysicalFragment(box->PhysicalFragmentCount() - 2);
+ }
+ return To<NGBlockBreakToken>(previous_fragment->BreakToken());
+}
+
+wtf_size_t PreviousInnerFragmentainerIndex(
+ const NGPhysicalBoxFragment& fragment) {
+ // This should be a fragmentation context root, typically a multicol
+ // container.
+ DCHECK(fragment.IsFragmentationContextRoot());
+
+ const LayoutBox* box = To<LayoutBox>(fragment.GetLayoutObject());
+ DCHECK_GE(box->PhysicalFragmentCount(), 1u);
+ if (box->PhysicalFragmentCount() == 1)
+ return 0;
+
+ wtf_size_t idx = 0;
+ // Walk the list of fragments generated by the node, until we reach the
+ // specified one. Note that some fragments may not contain any fragmentainers
+ // at all, if all the space is taken up by column spanners, for instance.
+ for (const NGPhysicalBoxFragment& walker : box->PhysicalFragments()) {
+ if (&walker == &fragment)
+ return idx;
+ const auto* break_token = To<NGBlockBreakToken>(walker.BreakToken());
+
+ // Find the last fragmentainer inside this fragment.
+ const auto children = break_token->ChildBreakTokens();
+ for (scoped_refptr<const NGBreakToken> child_token :
+ base::Reversed(children)) {
+ DCHECK(child_token->IsBlockType());
+ if (child_token->InputNode() != break_token->InputNode()) {
+ // Not a fragmentainer (probably a spanner)
+ continue;
+ }
+ idx = To<NGBlockBreakToken>(child_token.get())->SequenceNumber() + 1;
+ break;
+ }
+ }
+
+ NOTREACHED();
+ return idx;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
index c6db2ec0078..4810e58a4e8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENTATION_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENTATION_UTILS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
@@ -212,6 +213,10 @@ NGBreakStatus FinishFragmentation(NGBlockNode node,
LayoutUnit space_left,
NGBoxFragmentBuilder*);
+// Special rules apply for finishing fragmentation when building fragmentainers.
+NGBreakStatus FinishFragmentationForFragmentainer(const NGConstraintSpace&,
+ NGBoxFragmentBuilder*);
+
// Insert a fragmentainer break before the child if necessary. In that case, the
// previous in-flow position will be updated, we'll return |kBrokeBefore|. If we
// don't break inside, we'll consider the appeal of doing so anyway (and store
@@ -343,6 +348,26 @@ inline LayoutUnit AdjustedMarginAfterFinalChildFragment(
return std::min(block_end_margin, space_left.ClampNegativeToZero());
}
+// Note: This should only be used for a builder that represents a
+// fragmentation context root. Returns the the break token of the
+// previous fragmentainer to the child at |index|.
+const NGBlockBreakToken* PreviousFragmentainerBreakToken(
+ const NGBoxFragmentBuilder& container_builder,
+ wtf_size_t index);
+
+// Return the break token that led to the creation of the fragment specified, or
+// nullptr if this is the first fragment. Note that this operation is O(n)
+// (number of fragments generated from the node), and should be avoided when
+// possible. This function should no longer be necessary once everything has
+// been properly converted to LayoutNG, and we have also gotten rid of the
+// fragment stitching of composited objects (will be fixed by
+// CompositeAfterPaint).
+const NGBlockBreakToken* FindPreviousBreakToken(const NGPhysicalBoxFragment&);
+
+// Return the index of the fragmentainer preceding the first fragmentainer
+// inside this fragment. Used by nested block fragmentation.
+wtf_size_t PreviousInnerFragmentainerIndex(const NGPhysicalBoxFragment&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENTATION_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
index ffe09a0d21c..6376a5fde0d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
@@ -378,26 +378,14 @@ absl::optional<PhysicalRect> NGInkOverflow::ComputeTextInkOverflow(
// so compute text decoration overflow first.
if (!style.AppliedTextDecorations().IsEmpty() && font.PrimaryFont()) {
LayoutRect decoration_rect =
- ComputeTextDecorationOverflow(text_info, style, ink_overflow);
+ ComputeTextDecorationOverflow(style, ink_overflow);
ink_overflow.Unite(decoration_rect);
}
- const WritingMode writing_mode = style.GetWritingMode();
- if (style.GetTextEmphasisMark() != TextEmphasisMark::kNone) {
- LayoutUnit emphasis_mark_height =
- LayoutUnit(font.EmphasisMarkHeight(style.TextEmphasisMarkString()));
- DCHECK_GE(emphasis_mark_height, LayoutUnit());
- if (style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver) {
- ink_overflow.ShiftYEdgeTo(
- std::min(ink_overflow.Y(), -emphasis_mark_height));
- } else {
- LayoutUnit logical_height =
- IsHorizontalWritingMode(writing_mode) ? size.height : size.width;
- ink_overflow.ShiftMaxYEdgeTo(
- std::max(ink_overflow.MaxY(), logical_height + emphasis_mark_height));
- }
- }
+ if (style.GetTextEmphasisMark() != TextEmphasisMark::kNone)
+ ink_overflow = ComputeEmphasisMarkOverflow(style, size, ink_overflow);
+ const WritingMode writing_mode = style.GetWritingMode();
if (ShadowList* text_shadow = style.TextShadow()) {
LayoutRectOutsets text_shadow_logical_outsets =
LineOrientationLayoutRectOutsets(
@@ -421,17 +409,42 @@ absl::optional<PhysicalRect> NGInkOverflow::ComputeTextInkOverflow(
return local_ink_overflow;
}
+// static
+LayoutRect NGInkOverflow::ComputeEmphasisMarkOverflow(
+ const ComputedStyle& style,
+ const PhysicalSize& size,
+ const LayoutRect& ink_overflow_in) {
+ DCHECK(style.GetTextEmphasisMark() != TextEmphasisMark::kNone);
+
+ LayoutUnit emphasis_mark_height = LayoutUnit(
+ style.GetFont().EmphasisMarkHeight(style.TextEmphasisMarkString()));
+ DCHECK_GE(emphasis_mark_height, LayoutUnit());
+
+ LayoutRect ink_overflow = ink_overflow_in;
+ if (style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver) {
+ ink_overflow.ShiftYEdgeTo(
+ std::min(ink_overflow.Y(), -emphasis_mark_height));
+ } else {
+ LayoutUnit logical_height =
+ style.IsHorizontalWritingMode() ? size.height : size.width;
+ ink_overflow.ShiftMaxYEdgeTo(
+ std::max(ink_overflow.MaxY(), logical_height + emphasis_mark_height));
+ }
+ return ink_overflow;
+}
+
+// static
LayoutRect NGInkOverflow::ComputeTextDecorationOverflow(
- const NGTextFragmentPaintInfo& text_info,
const ComputedStyle& style,
const LayoutRect& ink_overflow) {
+ DCHECK(!style.AppliedTextDecorations().IsEmpty());
// TODO(https://crbug.com/1145160): Reduce code duplication between here and
// TextPainterBase::PaintDecorations*.
// Use a zero offset because all offsets
// are applied to the ink overflow after it has been computed.
PhysicalOffset offset;
- TextDecorationInfo decoration_info(offset, offset, ink_overflow.Width(),
+ TextDecorationInfo decoration_info(offset, ink_overflow.Width(),
style.GetFontBaseline(), style,
absl::nullopt, nullptr);
NGTextDecorationOffset decoration_offset(decoration_info.Style(), style,
@@ -449,7 +462,7 @@ LayoutRect NGInkOverflow::ComputeTextDecorationOverflow(
}
FloatRect accumulated_bound;
- for (size_t applied_decoration_index = 0;
+ for (wtf_size_t applied_decoration_index = 0;
applied_decoration_index < decorations.size();
++applied_decoration_index) {
const AppliedTextDecoration& decoration =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
index ae838cd1f3e..43c091e45a9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
@@ -7,6 +7,7 @@
#include "base/dcheck_is_on.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
@@ -120,6 +121,21 @@ class CORE_EXPORT NGInkOverflow {
const ComputedStyle& style,
const PhysicalSize& size);
+ // Returns ink-overflow with emphasis mark overflow in logical direction.
+ // |size| is a size of text item, e.g. |NGFragmentItem::Size()|.
+ // Note: |style| should have emphasis mark and |ink_overflow| should be in
+ // logical direction.
+ static LayoutRect ComputeEmphasisMarkOverflow(const ComputedStyle& style,
+ const PhysicalSize& size,
+ const LayoutRect& ink_overflow);
+
+ // Returns ink-overflow with text decoration overflow in logical direction.
+ // Note: |style| should have applied text decorations and |ink_overflow|
+ // should be in logical direction.
+ static LayoutRect ComputeTextDecorationOverflow(
+ const ComputedStyle& style,
+ const LayoutRect& ink_overflow);
+
#if DCHECK_IS_ON()
struct ReadUnsetAsNoneScope {
STACK_ALLOCATED();
@@ -133,11 +149,6 @@ class CORE_EXPORT NGInkOverflow {
#endif
private:
- static LayoutRect ComputeTextDecorationOverflow(
- const NGTextFragmentPaintInfo& text_info,
- const ComputedStyle& style,
- const LayoutRect& ink_overflow);
-
PhysicalRect FromOutsets(const PhysicalSize& size) const;
void CheckType(Type type) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
index 218d0701077..9e788470696 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_ALGORITHM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_ALGORITHM_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/min_max_sizes.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
@@ -115,7 +114,7 @@ class CORE_EXPORT NGLayoutAlgorithm : public NGLayoutAlgorithmOperations {
*container_builder_.BfcBlockOffset()};
}
- NGInputNodeType Node() const { return node_; }
+ const NGInputNodeType& Node() const { return node_; }
const NGBreakTokenType* BreakToken() const { return break_token_.get(); }
@@ -167,8 +166,7 @@ class CORE_EXPORT NGLayoutAlgorithm : public NGLayoutAlgorithmOperations {
// right thing, since, as far as input is concerned, this node is meant to
// perform block fragmentation (and it may already have produced multiple
// fragment, but this one will be the last).
- NGConstraintSpace new_space =
- NGConstraintSpaceBuilder::CloneWithoutFragmentation(ConstraintSpace());
+ NGConstraintSpace new_space = ConstraintSpace().CloneWithoutFragmentation();
NGLayoutAlgorithmParams params(Node(),
container_builder_.InitialFragmentGeometry(),
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 516a42936ef..9ae18f96dd6 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
@@ -77,7 +77,7 @@ bool NGLayoutInputNode::IsSliderThumb() const {
return IsBlock() && blink::IsSliderThumb(GetDOMNode());
}
-bool NGLayoutInputNode::IsSVGText() const {
+bool NGLayoutInputNode::IsSvgText() const {
return box_ && box_->IsNGSVGText();
}
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 70a65583772..69fe110bb11 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
@@ -133,8 +133,9 @@ class CORE_EXPORT NGLayoutInputNode {
bool IsSlider() const;
// Return true if this node is for a slider thumb in <input type=range>.
bool IsSliderThumb() const;
- bool IsSVGText() const;
+ bool IsSvgText() const;
bool IsTable() const { return IsBlock() && box_->IsTable(); }
+ bool IsTextCombine() const { return box_->IsLayoutNGTextCombine(); }
bool IsNGTable() const { return IsTable() && box_->IsLayoutNGMixin(); }
bool IsTableCaption() const { return IsBlock() && box_->IsTableCaption(); }
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc
index 839aab231d9..226014eb23d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
@@ -38,7 +39,7 @@ PhysicalRect NGLayoutOverflowCalculator::RecalculateLayoutOverflowForFragment(
fragment.Padding(), fragment.Size(), writing_direction);
if (const NGFragmentItems* items = fragment.Items())
- calculator.AddItems(*items);
+ calculator.AddItems(fragment, *items);
for (const auto& child : fragment.PostLayoutChildren()) {
const auto* box_fragment =
@@ -127,24 +128,20 @@ const PhysicalRect NGLayoutOverflowCalculator::Result(
alternate_overflow.UniteEvenIfEmpty(AdjustOverflowForScrollOrigin(
converter.ToPhysical(block_end_padding_rect)));
+ if (normal_overflow == alternate_overflow)
+ return normal_overflow;
+
// We'd like everything to be |normal_overflow|, lets see what the impact
// would be.
if (node_.Style().OverflowInlineDirection() == EOverflow::kAuto ||
node_.Style().OverflowInlineDirection() == EOverflow::kScroll) {
- if (alternate_overflow.size.width != normal_overflow.size.width) {
- if (alternate_overflow.size.width != padding_rect_.size.width) {
- UseCounter::Count(
- node_.GetDocument(),
- node_.IsFlexibleBox()
- ? WebFeature::kNewLayoutOverflowDifferentAndAlreadyScrollsFlex
- : WebFeature::
- kNewLayoutOverflowDifferentAndAlreadyScrollsBlock);
- } else {
- UseCounter::Count(node_.GetDocument(),
- node_.IsFlexibleBox()
- ? WebFeature::kNewLayoutOverflowDifferentFlex
- : WebFeature::kNewLayoutOverflowDifferentBlock);
- }
+ if (alternate_overflow.size.width != padding_rect_.size.width) {
+ UseCounter::Count(
+ node_.GetDocument(),
+ WebFeature::kNewLayoutOverflowDifferentAndAlreadyScrollsBlock);
+ } else {
+ UseCounter::Count(node_.GetDocument(),
+ WebFeature::kNewLayoutOverflowDifferentBlock);
}
}
@@ -152,10 +149,17 @@ const PhysicalRect NGLayoutOverflowCalculator::Result(
}
template <typename Items>
-void NGLayoutOverflowCalculator::AddItemsInternal(const Items& items) {
+void NGLayoutOverflowCalculator::AddItemsInternal(
+ const LayoutObject* layout_object,
+ const Items& items) {
bool has_hanging = false;
PhysicalRect line_rect;
+ // |LayoutNGTextCombine| doesn't not cause layout overflow because combined
+ // text fits in 1em by using width variant font or scaling.
+ if (UNLIKELY(IsA<LayoutNGTextCombine>(layout_object)))
+ return;
+
for (const auto& item : items) {
if (const auto* line_box = item->LineBoxFragment()) {
has_hanging = line_box->HasHanging();
@@ -205,12 +209,15 @@ void NGLayoutOverflowCalculator::AddItemsInternal(const Items& items) {
}
void NGLayoutOverflowCalculator::AddItems(
+ const LayoutObject* layout_object,
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
- AddItemsInternal(items);
+ AddItemsInternal(layout_object, items);
}
-void NGLayoutOverflowCalculator::AddItems(const NGFragmentItems& items) {
- AddItemsInternal(items.Items());
+void NGLayoutOverflowCalculator::AddItems(
+ const NGPhysicalBoxFragment& box_fragment,
+ const NGFragmentItems& items) {
+ AddItemsInternal(box_fragment.GetLayoutObject(), items.Items());
}
void NGLayoutOverflowCalculator::AddTableCollapsedBorders(
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h
index 85d9066dd47..0dcac7b31d1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_OVERFLOW_CALCULATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_OVERFLOW_CALCULATOR_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
@@ -45,14 +46,15 @@ class CORE_EXPORT NGLayoutOverflowCalculator {
}
// Adds layout-overflow from fragment-items.
- void AddItems(const NGFragmentItems&);
- void AddItems(const NGFragmentItemsBuilder::ItemWithOffsetList&);
+ void AddItems(const NGPhysicalBoxFragment&, const NGFragmentItems&);
+ void AddItems(const LayoutObject*,
+ const NGFragmentItemsBuilder::ItemWithOffsetList&);
void AddTableCollapsedBorders(const NGTableBorders&);
private:
template <typename Items>
- void AddItemsInternal(const Items& items);
+ void AddItemsInternal(const LayoutObject* layout_object, const Items& items);
PhysicalRect AdjustOverflowForHanging(const PhysicalRect& line_box_rect,
PhysicalRect overflow);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator_test.cc
index ba032801629..082a3405527 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator_test.cc
@@ -9,22 +9,6 @@ namespace blink {
class NGLayoutOverflowCalculatorTest : public RenderingTest {};
TEST_F(NGLayoutOverflowCalculatorTest,
- DISABLED_NewLayoutOverflowDifferentAndAlreadyScrollsFlex) {
- if (!RuntimeEnabledFeatures::LayoutNGEnabled())
- return;
- SetBodyInnerHTML(R"HTML(
- <!DOCTYPE html>
- <div style="display: flex; width: 100px; height: 100px; padding: 10px; overflow: auto;">
- <div style="min-width: 120px; height: 10px;"></div>
- </div>
- )HTML");
- RunDocumentLifecycle();
-
- EXPECT_TRUE(GetDocument().IsUseCounted(
- WebFeature::kNewLayoutOverflowDifferentAndAlreadyScrollsFlex));
-}
-
-TEST_F(NGLayoutOverflowCalculatorTest,
NewLayoutOverflowDifferentAndAlreadyScrollsBlock) {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return;
@@ -40,22 +24,6 @@ TEST_F(NGLayoutOverflowCalculatorTest,
WebFeature::kNewLayoutOverflowDifferentAndAlreadyScrollsBlock));
}
-TEST_F(NGLayoutOverflowCalculatorTest,
- DISABLED_NewLayoutOverflowDifferentFlex) {
- if (!RuntimeEnabledFeatures::LayoutNGEnabled())
- return;
- SetBodyInnerHTML(R"HTML(
- <!DOCTYPE html>
- <div style="display: flex; width: 100px; height: 100px; padding: 10px; overflow: auto;">
- <div style="min-width: 110px; height: 10px;"></div>
- </div>
- )HTML");
- RunDocumentLifecycle();
-
- EXPECT_TRUE(
- GetDocument().IsUseCounted(WebFeature::kNewLayoutOverflowDifferentFlex));
-}
-
TEST_F(NGLayoutOverflowCalculatorTest, NewLayoutOverflowDifferentBlock) {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
index 66d8cbd03a8..0f07c375018 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
@@ -90,9 +90,6 @@ NGLayoutResult::NGLayoutResult(
rare_data->has_violating_break = builder->has_violating_break_;
- if (builder->column_spanner_)
- rare_data->column_spanner = builder->column_spanner_;
-
bitfields_.initial_break_before = static_cast<unsigned>(
builder->initial_break_before_.value_or(EBreakBetween::kAuto));
bitfields_.final_break_after =
@@ -112,16 +109,20 @@ NGLayoutResult::NGLayoutResult(
scoped_refptr<const NGPhysicalFragment> physical_fragment,
NGLineBoxFragmentBuilder* builder)
: NGLayoutResult(std::move(physical_fragment),
- static_cast<NGContainerFragmentBuilder*>(builder)) {}
+ static_cast<NGContainerFragmentBuilder*>(builder)) {
+ DCHECK_EQ(builder->bfc_block_offset_.has_value(),
+ builder->line_box_bfc_block_offset_.has_value());
+ if (builder->bfc_block_offset_ != builder->line_box_bfc_block_offset_) {
+ EnsureRareData()->line_box_bfc_block_offset =
+ builder->line_box_bfc_block_offset_;
+ }
+}
-NGLayoutResult::NGLayoutResult(NGBoxFragmentBuilderPassKey key,
+NGLayoutResult::NGLayoutResult(NGContainerFragmentBuilderPassKey key,
EStatus status,
- NGBoxFragmentBuilder* builder)
- : NGLayoutResult(/* physical_fragment */ nullptr,
- static_cast<NGContainerFragmentBuilder*>(builder)) {
+ NGContainerFragmentBuilder* builder)
+ : NGLayoutResult(/* physical_fragment */ nullptr, builder) {
bitfields_.status = status;
- if (builder->lines_until_clamp_)
- EnsureRareData()->lines_until_clamp = *builder->lines_until_clamp_;
DCHECK_NE(status, kSuccess)
<< "Use the other constructor for successful layout";
}
@@ -244,6 +245,9 @@ NGLayoutResult::NGLayoutResult(
rare_data->early_break_appeal = builder->break_appeal_;
}
+ if (builder->column_spanner_)
+ EnsureRareData()->column_spanner = builder->column_spanner_;
+
if (HasRareData()) {
rare_data_->bfc_line_offset = builder->bfc_line_offset_;
rare_data_->bfc_block_offset = builder->bfc_block_offset_;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
index 44e5afcb2bd..357d7dfd7dd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
@@ -7,6 +7,7 @@
#include "base/dcheck_is_on.h"
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/layout/ng/exclusions/ng_exclusion_space.h"
@@ -163,6 +164,29 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
return bfc_offset_.block_offset;
}
+ // The BFC block-offset where a line-box has been placed. Will be nullopt if
+ // it isn't a line-box, or an empty line-box.
+ //
+ // This can be different (but rarely) to where the |BfcBlockOffset()|
+ // resolves to, when floats are present. E.g.
+ //
+ // <div style="width: 100px; display: flow-root;">
+ // <div style="float: left; width: 200px; height: 20px;"></div>
+ // text
+ // </div>
+ //
+ // In the above example the |BfcBlockOffset()| will be at 0px, where-as the
+ // |LineBoxBfcBlockOffset()| will be at 20px.
+ absl::optional<LayoutUnit> LineBoxBfcBlockOffset() const {
+ if (!PhysicalFragment().IsLineBox())
+ return absl::nullopt;
+
+ if (HasRareData() && rare_data_->line_box_bfc_block_offset)
+ return rare_data_->line_box_bfc_block_offset;
+
+ return BfcBlockOffset();
+ }
+
const NGMarginStrut EndMarginStrut() const {
return HasRareData() ? rare_data_->end_margin_strut : NGMarginStrut();
}
@@ -351,13 +375,19 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
bool check_same_block_size = true) const;
#endif
- using NGBoxFragmentBuilderPassKey = base::PassKey<NGBoxFragmentBuilder>;
+ using NGContainerFragmentBuilderPassKey =
+ base::PassKey<NGContainerFragmentBuilder>;
// This constructor is for a non-success status.
- NGLayoutResult(NGBoxFragmentBuilderPassKey, EStatus, NGBoxFragmentBuilder*);
+ NGLayoutResult(NGContainerFragmentBuilderPassKey,
+ EStatus,
+ NGContainerFragmentBuilder*);
+
// This constructor requires a non-null fragment and sets a success status.
+ using NGBoxFragmentBuilderPassKey = base::PassKey<NGBoxFragmentBuilder>;
NGLayoutResult(NGBoxFragmentBuilderPassKey,
scoped_refptr<const NGPhysicalFragment> physical_fragment,
NGBoxFragmentBuilder*);
+
using NGLineBoxFragmentBuilderPassKey =
base::PassKey<NGLineBoxFragmentBuilder>;
// This constructor requires a non-null fragment and sets a success status.
@@ -365,7 +395,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
scoped_refptr<const NGPhysicalFragment> physical_fragment,
NGLineBoxFragmentBuilder*);
- // See https://mathml-refresh.github.io/mathml-core/#box-model
+ // See https://w3c.github.io/mathml-core/#box-model
struct MathData {
LayoutUnit italic_correction_;
};
@@ -420,6 +450,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
rare_data.tallest_unbreakable_block_size),
exclusion_space(rare_data.exclusion_space),
custom_layout_data(rare_data.custom_layout_data),
+ line_box_bfc_block_offset(rare_data.line_box_bfc_block_offset),
annotation_overflow(rare_data.annotation_overflow),
block_end_annotation_space(rare_data.block_end_annotation_space),
has_violating_break(rare_data.has_violating_break),
@@ -456,6 +487,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
NGExclusionSpace exclusion_space;
scoped_refptr<SerializedScriptValue> custom_layout_data;
+ absl::optional<LayoutUnit> line_box_bfc_block_offset;
LayoutUnit annotation_overflow;
LayoutUnit block_end_annotation_space;
bool has_violating_break = false;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
index bc35c7631b4..0f48365275f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_layout_utils.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
@@ -27,8 +28,7 @@ inline bool InlineLengthMayChange(const ComputedStyle& style,
const NGConstraintSpace& new_space,
const NGConstraintSpace& old_space,
const NGLayoutResult& layout_result) {
- DCHECK_EQ(new_space.StretchInlineSizeIfAuto(),
- old_space.StretchInlineSizeIfAuto());
+ DCHECK_EQ(new_space.InlineAutoBehavior(), old_space.InlineAutoBehavior());
bool is_unspecified =
(length.IsAuto() && type != LengthResolveType::kMinSize) ||
@@ -60,10 +60,9 @@ inline bool InlineLengthMayChange(const ComputedStyle& style,
inline bool BlockLengthMayChange(const Length& length,
const NGConstraintSpace& new_space,
const NGConstraintSpace& old_space) {
- DCHECK_EQ(new_space.StretchBlockSizeIfAuto(),
- old_space.StretchBlockSizeIfAuto());
+ DCHECK_EQ(new_space.BlockAutoBehavior(), old_space.BlockAutoBehavior());
if (length.IsFillAvailable() ||
- (length.IsAuto() && new_space.StretchBlockSizeIfAuto())) {
+ (length.IsAuto() && new_space.IsBlockAutoBehaviorStretch())) {
if (new_space.AvailableSize().block_size !=
old_space.AvailableSize().block_size)
return true;
@@ -77,13 +76,12 @@ bool BlockSizeMayChange(const NGBlockNode& node,
const NGConstraintSpace& old_space,
const NGLayoutResult& layout_result) {
DCHECK_EQ(new_space.IsFixedBlockSize(), old_space.IsFixedBlockSize());
- DCHECK_EQ(new_space.IsFixedBlockSizeIndefinite(),
- old_space.IsFixedBlockSizeIndefinite());
- DCHECK_EQ(new_space.StretchBlockSizeIfAuto(),
- old_space.StretchBlockSizeIfAuto());
+ DCHECK_EQ(new_space.IsInitialBlockSizeIndefinite(),
+ old_space.IsInitialBlockSizeIndefinite());
+ DCHECK_EQ(new_space.BlockAutoBehavior(), old_space.BlockAutoBehavior());
DCHECK_EQ(new_space.IsTableCellChild(), old_space.IsTableCellChild());
- DCHECK_EQ(new_space.IsMeasuringRestrictedBlockSizeTableCellChild(),
- old_space.IsMeasuringRestrictedBlockSizeTableCellChild());
+ DCHECK_EQ(new_space.IsRestrictedBlockSizeTableCellChild(),
+ old_space.IsRestrictedBlockSizeTableCellChild());
if (node.IsQuirkyAndFillsViewport())
return true;
@@ -121,8 +119,7 @@ bool SizeMayChange(const NGBlockNode& node,
const NGConstraintSpace& old_space,
const NGLayoutResult& layout_result) {
DCHECK_EQ(new_space.IsFixedInlineSize(), old_space.IsFixedInlineSize());
- DCHECK_EQ(new_space.StretchInlineSizeIfAuto(),
- old_space.StretchInlineSizeIfAuto());
+ DCHECK_EQ(new_space.BlockAutoBehavior(), old_space.BlockAutoBehavior());
const ComputedStyle& style = node.Style();
@@ -239,8 +236,9 @@ NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatusWithGeometry(
// within this branch (and could have re-used the result).
// TODO(ikilaptrick): This may occur for other layout modes, e.g.
// custom-layout.
- if (old_space.IsFixedBlockSize() || (old_space.StretchBlockSizeIfAuto() &&
- style.LogicalHeight().IsAuto())) {
+ if (old_space.IsFixedBlockSize() ||
+ (old_space.IsBlockAutoBehaviorStretch() &&
+ style.LogicalHeight().IsAuto())) {
if (node.IsFlexibleBox() || node.IsGrid())
intrinsic_block_size = kIndefiniteSize;
}
@@ -324,13 +322,6 @@ NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatusWithGeometry(
}
if (has_descendant_that_depends_on_percentage_block_size) {
- // %-block-size children of table-cells have different behaviour if they
- // are in the "measure" or "layout" phase.
- // Instead of trying to capture that logic here, we always miss the cache.
- if (new_space.IsTableCell() &&
- new_space.IsFixedBlockSize() != old_space.IsFixedBlockSize())
- return NGLayoutCacheStatus::kNeedsLayout;
-
// If our initial block-size is definite, we know that if we change our
// block-size we'll affect any descendant that depends on the resulting
// percentage block-size.
@@ -347,7 +338,7 @@ NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatusWithGeometry(
// depends on a percentage block-size, however it will also return true if
// the node itself depends on the %-block-size.
//
- // As we only care about the quirks-mode %-block-size behaviour we remove
+ // As we only care about the quirks-mode %-block-size behavior we remove
// this false-positive by checking if we have an initial indefinite
// block-size.
if (is_initial_block_size_indefinite &&
@@ -428,7 +419,7 @@ bool IntrinsicSizeWillChange(
const NGConstraintSpace& new_space,
absl::optional<NGFragmentGeometry>* fragment_geometry) {
const ComputedStyle& style = node.Style();
- if (new_space.StretchInlineSizeIfAuto() && !NeedMinMaxSize(style))
+ if (new_space.IsInlineAutoBehaviorStretch() && !NeedMinMaxSize(style))
return false;
if (!*fragment_geometry)
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
index a716f92018d..1b67ccdfcb4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_UTILS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
namespace blink {
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 c0665e4ca0b..889dff23179 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
@@ -6,6 +6,7 @@
#include <algorithm>
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
@@ -76,16 +77,16 @@ bool InlineLengthUnresolvable(const NGConstraintSpace& constraint_space,
bool BlockLengthUnresolvable(
const NGConstraintSpace& constraint_space,
const Length& length,
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+ const LayoutUnit* override_percentage_resolution_size) {
if (length.IsAuto() || length.IsMinContent() || length.IsMaxContent() ||
length.IsMinIntrinsic() || length.IsFitContent() || length.IsNone())
return true;
if (length.IsPercentOrCalc()) {
- LayoutUnit percentage_resolution_block_size =
- opt_percentage_resolution_block_size_for_min_max
- ? *opt_percentage_resolution_block_size_for_min_max
+ const LayoutUnit percentage_resolution_size =
+ override_percentage_resolution_size
+ ? *override_percentage_resolution_size
: constraint_space.PercentageResolutionBlockSize();
- return percentage_resolution_block_size == kIndefiniteSize;
+ return percentage_resolution_size == kIndefiniteSize;
}
if (length.IsFillAvailable())
@@ -174,7 +175,7 @@ LayoutUnit ResolveBlockLengthInternal(
const Length& length,
LayoutUnit intrinsic_size,
LayoutUnit available_block_size_adjustment,
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+ const LayoutUnit* override_percentage_resolution_size) {
DCHECK_EQ(constraint_space.GetWritingMode(), style.GetWritingMode());
switch (length.GetType()) {
@@ -192,8 +193,8 @@ LayoutUnit ResolveBlockLengthInternal(
case Length::kFixed:
case Length::kCalculated: {
const LayoutUnit percentage_resolution_size =
- opt_percentage_resolution_block_size_for_min_max
- ? *opt_percentage_resolution_block_size_for_min_max
+ override_percentage_resolution_size
+ ? *override_percentage_resolution_size
: constraint_space.PercentageResolutionBlockSize();
DCHECK(length.IsFixed() || percentage_resolution_size != kIndefiniteSize);
LayoutUnit value =
@@ -277,6 +278,7 @@ LayoutUnit BlockSizeFromAspectRatio(const NGBoxStrut& border_padding,
const LogicalSize& aspect_ratio,
EBoxSizing box_sizing,
LayoutUnit inline_size) {
+ DCHECK_GE(inline_size, border_padding.InlineSum());
if (box_sizing == EBoxSizing::kBorderBox) {
return inline_size.MulDiv(aspect_ratio.block_size,
aspect_ratio.inline_size);
@@ -369,41 +371,26 @@ MinMaxSizesResult ComputeMinAndMaxContentContributionForReplaced(
const NGBlockNode& child,
const NGConstraintSpace& space) {
const auto& child_style = child.Style();
- MinMaxSizes result;
-
- if (RuntimeEnabledFeatures::LayoutNGReplacedEnabled()) {
- const NGBoxStrut border_padding =
- ComputeBorders(space, child) + ComputePadding(space, child_style);
- result = ComputeReplacedSize(child, space, border_padding).inline_size;
-
- if (child_style.LogicalWidth().IsPercentOrCalc() ||
- child_style.LogicalMaxWidth().IsPercentOrCalc()) {
- // TODO(ikilpatrick): No browser does this today, but we'd get slightly
- // better results here if we also considered the min-block size, and
- // transferred through the aspect-ratio (if available).
- result.min_size = ResolveMinInlineLength(
- space, child_style, border_padding,
- [&](MinMaxSizesType) -> MinMaxSizesResult {
- // Behave the same as if we couldn't resolve the min-inline size.
- MinMaxSizes sizes;
- sizes = border_padding.InlineSum();
- return {sizes, /* depends_on_block_constraints */ false};
- },
- child_style.LogicalMinWidth());
- }
- } else {
- LayoutBox* box = child.GetLayoutBox();
- bool needs_size_reset = false;
- if (!box->HasOverrideContainingBlockContentLogicalHeight()) {
- box->SetOverrideContainingBlockContentLogicalHeight(
- space.ReplacedPercentageResolutionBlockSize());
- needs_size_reset = true;
- }
-
- result = box->PreferredLogicalWidths();
+ const NGBoxStrut border_padding =
+ ComputeBorders(space, child) + ComputePadding(space, child_style);
- if (needs_size_reset)
- box->ClearOverrideContainingBlockContentSize();
+ MinMaxSizes result;
+ result = ComputeReplacedSize(child, space, border_padding).inline_size;
+
+ if (child_style.LogicalWidth().IsPercentOrCalc() ||
+ child_style.LogicalMaxWidth().IsPercentOrCalc()) {
+ // TODO(ikilpatrick): No browser does this today, but we'd get slightly
+ // better results here if we also considered the min-block size, and
+ // transferred through the aspect-ratio (if available).
+ result.min_size = ResolveMinInlineLength(
+ space, child_style, border_padding,
+ [&](MinMaxSizesType) -> MinMaxSizesResult {
+ // Behave the same as if we couldn't resolve the min-inline size.
+ MinMaxSizes sizes;
+ sizes = border_padding.InlineSum();
+ return {sizes, /* depends_on_block_constraints */ false};
+ },
+ child_style.LogicalMinWidth());
}
// Replaced elements which have a percentage block-size always depend on
@@ -413,7 +400,8 @@ MinMaxSizesResult ComputeMinAndMaxContentContributionForReplaced(
child_style.LogicalHeight().IsPercentOrCalc() ||
child_style.LogicalMinHeight().IsPercentOrCalc() ||
child_style.LogicalMaxHeight().IsPercentOrCalc() ||
- (child_style.LogicalHeight().IsAuto() && space.StretchBlockSizeIfAuto());
+ (child_style.LogicalHeight().IsAuto() &&
+ space.IsBlockAutoBehaviorStretch());
return MinMaxSizesResult(result, depends_on_block_constraints);
}
@@ -494,6 +482,12 @@ LayoutUnit ComputeInlineSizeFromAspectRatio(const NGConstraintSpace& space,
const NGBoxStrut& border_padding) {
DCHECK(!style.AspectRatio().IsAuto());
+ // Even though an implicit stretch will resolve - we return an indefinite
+ // size, as we prefer the inline-axis size for this case.
+ if (style.LogicalHeight().IsAuto() &&
+ space.BlockAutoBehavior() != NGAutoBehavior::kStretchExplicit)
+ return kIndefiniteSize;
+
LayoutUnit block_size = ComputeBlockSizeForFragment(
space, style, border_padding,
/* intrinsic_size */ kIndefiniteSize, /* inline_size */ absl::nullopt);
@@ -520,19 +514,18 @@ LayoutUnit ComputeInlineSizeForFragmentInternal(
};
const ComputedStyle& style = node.Style();
+ const bool has_aspect_ratio = !style.AspectRatio().IsAuto();
Length logical_width = style.LogicalWidth();
Length min_length = style.LogicalMinWidth();
- // TODO(ikilpatrick): If we are stretching in both the inline-axis, and
- // block-axis, we shouldn't apply the aspect-ratio.
- // TODO(cbiesinger): Should the if also check !node.IsReplaced()?
LayoutUnit extent = kIndefiniteSize;
- if (!style.AspectRatio().IsAuto()) {
- if (logical_width.IsAuto() || logical_width.IsMinContent() ||
- logical_width.IsMaxContent()) {
+ if (has_aspect_ratio) {
+ if ((logical_width.IsAuto() &&
+ space.InlineAutoBehavior() != NGAutoBehavior::kStretchExplicit) ||
+ logical_width.IsMinContent() || logical_width.IsMaxContent())
extent = ComputeInlineSizeFromAspectRatio(space, style, border_padding);
- }
- if (UNLIKELY(extent != kIndefiniteSize)) {
+
+ if (extent != kIndefiniteSize) {
// This means we successfully applied aspect-ratio and now need to check
// if we need to apply the implied minimum size:
// https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
@@ -544,8 +537,10 @@ LayoutUnit ComputeInlineSizeForFragmentInternal(
if (LIKELY(extent == kIndefiniteSize)) {
if (logical_width.IsAuto()) {
- logical_width = space.StretchInlineSizeIfAuto() ? Length::FillAvailable()
- : Length::FitContent();
+ logical_width = (space.IsInlineAutoBehaviorStretch() &&
+ space.AvailableSize().inline_size != kIndefiniteSize)
+ ? Length::FillAvailable()
+ : Length::FitContent();
}
extent = ResolveMainInlineLength(space, style, border_padding,
MinMaxSizesFunc, logical_width);
@@ -587,17 +582,14 @@ MinMaxSizes ComputeMinMaxBlockSizes(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
- LayoutUnit available_block_size_adjustment,
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+ LayoutUnit available_block_size_adjustment) {
MinMaxSizes sizes = {
ResolveMinBlockLength(constraint_space, style, border_padding,
style.LogicalMinHeight(),
- available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max),
+ available_block_size_adjustment),
ResolveMaxBlockLength(constraint_space, style, border_padding,
style.LogicalMaxHeight(),
- available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max)};
+ available_block_size_adjustment)};
sizes.max_size = std::max(sizes.max_size, sizes.min_size);
return sizes;
}
@@ -652,49 +644,61 @@ LayoutUnit ComputeBlockSizeForFragmentInternal(
const NGBoxStrut& border_padding,
LayoutUnit intrinsic_size,
absl::optional<LayoutUnit> inline_size,
- LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr) {
+ LayoutUnit available_block_size_adjustment = LayoutUnit()) {
MinMaxSizes min_max = ComputeMinMaxBlockSizes(
- space, style, border_padding, available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max);
+ space, style, border_padding, available_block_size_adjustment);
- // Scrollable percentage-sized children of table cells, in the table
- // "measure" phase contribute nothing to the row height measurement.
+ // Scrollable percentage-sized children of table cells (sometimes) are sized
+ // to their min-size.
// See: https://drafts.csswg.org/css-tables-3/#row-layout
- if (space.IsMeasuringRestrictedBlockSizeTableCellChild())
+ if (space.IsRestrictedBlockSizeTableCellChild())
return min_max.min_size;
+ const bool has_aspect_ratio = !style.AspectRatio().IsAuto();
Length logical_height = style.LogicalHeight();
- if (logical_height.IsAuto()) {
- logical_height = space.StretchBlockSizeIfAuto() ? Length::FillAvailable()
- : Length::FitContent();
+
+ LayoutUnit extent = kIndefiniteSize;
+ if (has_aspect_ratio && inline_size) {
+ const bool has_explicit_stretch =
+ logical_height.IsAuto() &&
+ space.BlockAutoBehavior() == NGAutoBehavior::kStretchExplicit &&
+ space.AvailableSize().block_size != kIndefiniteSize;
+ if (BlockLengthUnresolvable(space, logical_height) &&
+ !has_explicit_stretch) {
+ extent = BlockSizeFromAspectRatio(
+ border_padding, style.LogicalAspectRatio(),
+ style.BoxSizingForAspectRatio(), *inline_size);
+ DCHECK_NE(extent, kIndefiniteSize);
+
+ // Apply the automatic minimum size for aspect ratio:
+ // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
+ // We also check for LayoutUnit::Max() because flexbox uses that as a
+ // "placeholder" to compute the flex line length while still respecting
+ // max-block-size.
+ if (style.LogicalMinHeight().IsAuto() &&
+ style.OverflowBlockDirection() == EOverflow::kVisible &&
+ intrinsic_size != kIndefiniteSize &&
+ intrinsic_size != LayoutUnit::Max())
+ min_max.min_size = intrinsic_size;
+ }
}
- // TODO(cbiesinger): Audit callers of ResolveMainBlockLength to see whether
- // they need to respect aspect ratio.
- LayoutUnit extent =
- ResolveMainBlockLength(space, style, border_padding, logical_height,
- intrinsic_size, available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max);
- if (UNLIKELY(!style.AspectRatio().IsAuto() && inline_size &&
- BlockLengthUnresolvable(
- space, logical_height,
- opt_percentage_resolution_block_size_for_min_max))) {
- extent =
- BlockSizeFromAspectRatio(border_padding, style.LogicalAspectRatio(),
- style.BoxSizingForAspectRatio(), *inline_size);
- // Apply the automatic minimum size for aspect ratio:
- // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
- // We also check for LayoutUnit::Max() because flexbox uses that as a
- // "placeholder" to compute the flex line length while still respecting
- // max-block-size.
- if (style.LogicalMinHeight().IsAuto() &&
- style.OverflowBlockDirection() == EOverflow::kVisible &&
- intrinsic_size != kIndefiniteSize &&
- intrinsic_size != LayoutUnit::Max()) {
- min_max.min_size = intrinsic_size;
+
+ if (extent == kIndefiniteSize) {
+ if (logical_height.IsAuto()) {
+ logical_height = (space.IsBlockAutoBehaviorStretch() &&
+ space.AvailableSize().block_size != kIndefiniteSize)
+ ? Length::FillAvailable()
+ : Length::FitContent();
}
- } else if (extent == kIndefiniteSize) {
+
+ // TODO(cbiesinger): Audit callers of ResolveMainBlockLength to see whether
+ // they need to respect aspect ratio.
+ extent =
+ ResolveMainBlockLength(space, style, border_padding, logical_height,
+ intrinsic_size, available_block_size_adjustment);
+ }
+
+ if (extent == kIndefiniteSize) {
DCHECK_EQ(intrinsic_size, kIndefiniteSize);
return extent;
}
@@ -743,7 +747,7 @@ LayoutUnit ComputeInitialBlockSizeForFragment(
LayoutUnit intrinsic_size,
absl::optional<LayoutUnit> inline_size,
LayoutUnit available_block_size_adjustment) {
- if (space.IsFixedBlockSizeIndefinite())
+ if (space.IsInitialBlockSizeIndefinite())
return intrinsic_size;
return ComputeBlockSizeForFragment(space, style, border_padding,
intrinsic_size, inline_size,
@@ -846,12 +850,12 @@ LogicalSize ComputeReplacedSize(const NGBlockNode& node,
// against a different size than the main size. See:
// - https://www.w3.org/TR/CSS21/visudet.html#min-max-heights
// - https://bugs.chromium.org/p/chromium/issues/detail?id=385877
- // For the history on this behaviour. Fortunately if this is the case we
- // can just use the given available size to resolve these sizes against.
+ // For the history on this behavior. Fortunately if this is the case we can
+ // just use the given available size to resolve these sizes against.
const LayoutUnit min_max_percentage_resolution_size =
node.GetDocument().InQuirksMode()
? space.AvailableSize().block_size
- : space.PercentageResolutionBlockSize();
+ : space.ReplacedPercentageResolutionBlockSize();
block_min_max_sizes = {
ResolveMinBlockLength(
@@ -867,14 +871,14 @@ LogicalSize ComputeReplacedSize(const NGBlockNode& node,
replaced_block = space.AvailableSize().block_size;
DCHECK_GE(*replaced_block, 0);
} else if (!block_length.IsAutoOrContentOrIntrinsic() ||
- space.StretchBlockSizeIfAuto()) {
+ (space.IsBlockAutoBehaviorStretch() &&
+ space.AvailableSize().block_size != kIndefiniteSize)) {
Length block_length_to_resolve = block_length;
if (block_length_to_resolve.IsAuto()) {
// TODO(dgrogan): This code block (and its corresponding inline version
// below) didn't make any tests pass when written so it may be
// unnecessary or untested. Check again when launching ReplacedNG.
- DCHECK(space.StretchBlockSizeIfAuto());
- DCHECK(space.AvailableSize().block_size != kIndefiniteSize);
+ DCHECK(space.IsBlockAutoBehaviorStretch());
block_length_to_resolve = Length::FillAvailable();
}
@@ -887,7 +891,7 @@ LogicalSize ComputeReplacedSize(const NGBlockNode& node,
/* intrinsic_size */ kIndefiniteSize,
/* available_block_size_adjustment */ LayoutUnit(),
&main_percentage_resolution_size);
- DCHECK_NE(*replaced_block, kIndefiniteSize);
+ DCHECK_GE(*replaced_block, LayoutUnit());
replaced_block =
block_min_max_sizes.ClampSizeToMinAndMax(*replaced_block);
}
@@ -925,9 +929,13 @@ LogicalSize ComputeReplacedSize(const NGBlockNode& node,
size += ComputeDefaultNaturalSize(node).inline_size;
} else {
// Stretch to the available-size if it is definite.
- size = ResolveMainInlineLength<absl::optional<MinMaxSizes>>(
- space, style, border_padding, absl::nullopt, Length::FillAvailable(),
- available_inline_size_adjustment);
+ size = ResolveMainInlineLength(
+ space, style, border_padding,
+ [](MinMaxSizesType) -> MinMaxSizesResult {
+ NOTREACHED();
+ return MinMaxSizesResult();
+ },
+ Length::FillAvailable(), available_inline_size_adjustment);
}
// If stretch-fit applies we must have an aspect-ratio.
@@ -980,11 +988,12 @@ LogicalSize ComputeReplacedSize(const NGBlockNode& node,
if (space.IsFixedInlineSize()) {
replaced_inline = space.AvailableSize().inline_size;
DCHECK_GE(*replaced_inline, 0);
- } else if (!inline_length.IsAuto() || space.StretchInlineSizeIfAuto()) {
+ } else if (!inline_length.IsAuto() ||
+ (space.IsInlineAutoBehaviorStretch() &&
+ space.AvailableSize().inline_size != kIndefiniteSize)) {
Length inline_length_to_resolve = inline_length;
if (inline_length_to_resolve.IsAuto()) {
- DCHECK(space.StretchInlineSizeIfAuto());
- DCHECK(space.AvailableSize().inline_size != kIndefiniteSize);
+ DCHECK(space.IsInlineAutoBehaviorStretch());
inline_length_to_resolve = Length::FillAvailable();
}
@@ -992,7 +1001,7 @@ LogicalSize ComputeReplacedSize(const NGBlockNode& node,
replaced_inline = ResolveMainInlineLength(
space, style, border_padding, MinMaxSizesFunc,
inline_length_to_resolve, available_inline_size_adjustment);
- DCHECK_NE(*replaced_inline, kIndefiniteSize);
+ DCHECK_GE(*replaced_inline, LayoutUnit());
replaced_inline =
inline_min_max_sizes.ClampSizeToMinAndMax(*replaced_inline);
}
@@ -1544,31 +1553,6 @@ LogicalSize AdjustChildPercentageSize(const NGConstraintSpace& space,
const NGBlockNode node,
LogicalSize child_percentage_size,
LayoutUnit parent_percentage_block_size) {
- // Flex items may have a fixed block-size, but children shouldn't resolve
- // their percentages against this.
- if (space.IsFixedBlockSizeIndefinite()) {
- DCHECK(node.IsFlexItem() || space.IsTableCell());
- child_percentage_size.block_size = kIndefiniteSize;
- return child_percentage_size;
- }
-
- bool is_table_cell_in_measure_phase =
- space.IsTableCell() && !space.IsFixedBlockSize();
- // A table-cell during the "measure" phase forces its descendants to have an
- // indefinite percentage resolution size.
- // NOTE: If the Layout and ComputeMinMaxSizes ever get merged, this can be
- // removed (as we'll need to allow for indefinite %-inline-sizes).
- if (is_table_cell_in_measure_phase) {
- // Orthogonal cells need to call layout on the cell to determine
- // size of the table. Because table's inline size is unknown, percentages
- // are resolved against 0.
- if (space.IsOrthogonalWritingModeRoot())
- child_percentage_size.block_size = LayoutUnit();
- else
- child_percentage_size.block_size = kIndefiniteSize;
- return child_percentage_size;
- }
-
// In quirks mode the percentage resolution height is passed from parent to
// child.
// https://quirks.spec.whatwg.org/#the-percentage-height-calculation-quirk
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 fceabff1719..83c95b2a247 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
@@ -58,8 +58,7 @@ CORE_EXPORT bool InlineLengthUnresolvable(const NGConstraintSpace&,
CORE_EXPORT bool BlockLengthUnresolvable(
const NGConstraintSpace&,
const Length&,
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr);
+ const LayoutUnit* override_percentage_resolution_size = nullptr);
// Resolve means translate a Length to a LayoutUnit.
// - |NGConstraintSpace| the information given by the parent, e.g. the
@@ -88,8 +87,7 @@ CORE_EXPORT LayoutUnit ResolveBlockLengthInternal(
const Length&,
LayoutUnit intrinsic_size,
LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr);
+ const LayoutUnit* override_percentage_resolution_size = nullptr);
// In this file the template parameter MinMaxSizesFunc should have the
// following form:
@@ -126,23 +124,6 @@ inline LayoutUnit ResolveMinInlineLength(
available_inline_size_adjustment);
}
-template <>
-inline LayoutUnit ResolveMinInlineLength<absl::optional<MinMaxSizes>>(
- const NGConstraintSpace& constraint_space,
- const ComputedStyle& style,
- const NGBoxStrut& border_padding,
- const absl::optional<MinMaxSizes>& min_max_sizes,
- const Length& length,
- LayoutUnit available_inline_size_adjustment) {
- if (LIKELY(length.IsAuto() ||
- InlineLengthUnresolvable(constraint_space, length)))
- return border_padding.InlineSum();
-
- return ResolveInlineLengthInternal(constraint_space, style, border_padding,
- min_max_sizes, length,
- available_inline_size_adjustment);
-}
-
// Used for resolving max inline lengths, (|ComputedStyle::MaxLogicalWidth|).
template <typename MinMaxSizesFunc>
inline LayoutUnit ResolveMaxInlineLength(
@@ -169,23 +150,6 @@ inline LayoutUnit ResolveMaxInlineLength(
available_inline_size_adjustment);
}
-template <>
-inline LayoutUnit ResolveMaxInlineLength<absl::optional<MinMaxSizes>>(
- const NGConstraintSpace& constraint_space,
- const ComputedStyle& style,
- const NGBoxStrut& border_padding,
- const absl::optional<MinMaxSizes>& min_max_sizes,
- const Length& length,
- LayoutUnit available_inline_size_adjustment) {
- if (LIKELY(length.IsNone() ||
- InlineLengthUnresolvable(constraint_space, length)))
- return LayoutUnit::Max();
-
- return ResolveInlineLengthInternal(constraint_space, style, border_padding,
- min_max_sizes, length,
- available_inline_size_adjustment);
-}
-
// Used for resolving main inline lengths, (|ComputedStyle::LogicalWidth|).
template <typename MinMaxSizesFunc>
inline LayoutUnit ResolveMainInlineLength(
@@ -209,20 +173,6 @@ inline LayoutUnit ResolveMainInlineLength(
available_inline_size_adjustment);
}
-template <>
-inline LayoutUnit ResolveMainInlineLength<absl::optional<MinMaxSizes>>(
- const NGConstraintSpace& constraint_space,
- const ComputedStyle& style,
- const NGBoxStrut& border_padding,
- const absl::optional<MinMaxSizes>& min_max_sizes,
- const Length& length,
- LayoutUnit available_inline_size_adjustment) {
- DCHECK(!length.IsAuto());
- return ResolveInlineLengthInternal(constraint_space, style, border_padding,
- min_max_sizes, length,
- available_inline_size_adjustment);
-}
-
// Used for resolving min block lengths, (|ComputedStyle::MinLogicalHeight|).
inline LayoutUnit ResolveMinBlockLength(
const NGConstraintSpace& constraint_space,
@@ -230,17 +180,14 @@ inline LayoutUnit ResolveMinBlockLength(
const NGBoxStrut& border_padding,
const Length& length,
LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr) {
- if (LIKELY(BlockLengthUnresolvable(
- constraint_space, length,
- opt_percentage_resolution_block_size_for_min_max)))
+ const LayoutUnit* override_percentage_resolution_size = nullptr) {
+ if (LIKELY(BlockLengthUnresolvable(constraint_space, length,
+ override_percentage_resolution_size)))
return border_padding.BlockSum();
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, kIndefiniteSize,
- available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max);
+ available_block_size_adjustment, override_percentage_resolution_size);
}
// Used for resolving max block lengths, (|ComputedStyle::MaxLogicalHeight|).
@@ -250,17 +197,14 @@ inline LayoutUnit ResolveMaxBlockLength(
const NGBoxStrut& border_padding,
const Length& length,
LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr) {
- if (LIKELY(BlockLengthUnresolvable(
- constraint_space, length,
- opt_percentage_resolution_block_size_for_min_max)))
+ const LayoutUnit* override_percentage_resolution_size = nullptr) {
+ if (LIKELY(BlockLengthUnresolvable(constraint_space, length,
+ override_percentage_resolution_size)))
return LayoutUnit::Max();
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, kIndefiniteSize,
- available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max);
+ available_block_size_adjustment, override_percentage_resolution_size);
}
// Used for resolving main block lengths, (|ComputedStyle::LogicalHeight|).
@@ -271,19 +215,16 @@ inline LayoutUnit ResolveMainBlockLength(
const Length& length,
LayoutUnit intrinsic_size,
LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr) {
+ const LayoutUnit* override_percentage_resolution_size = nullptr) {
DCHECK(!length.IsAuto());
if (UNLIKELY((length.IsPercentOrCalc() || length.IsFillAvailable()) &&
- BlockLengthUnresolvable(
- constraint_space, length,
- opt_percentage_resolution_block_size_for_min_max)))
+ BlockLengthUnresolvable(constraint_space, length,
+ override_percentage_resolution_size)))
return intrinsic_size;
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, intrinsic_size,
- available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max);
+ available_block_size_adjustment, override_percentage_resolution_size);
}
template <typename IntrinsicBlockSizeFunc>
@@ -293,24 +234,19 @@ inline LayoutUnit ResolveMainBlockLength(
const NGBoxStrut& border_padding,
const Length& length,
const IntrinsicBlockSizeFunc& intrinsic_block_size_func,
- LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr) {
+ LayoutUnit available_block_size_adjustment = LayoutUnit()) {
DCHECK(!length.IsAuto());
if (UNLIKELY((length.IsPercentOrCalc() || length.IsFillAvailable()) &&
- BlockLengthUnresolvable(
- constraint_space, length,
- opt_percentage_resolution_block_size_for_min_max)))
+ BlockLengthUnresolvable(constraint_space, length)))
return intrinsic_block_size_func();
LayoutUnit intrinsic_block_size = kIndefiniteSize;
if (length.IsContentOrIntrinsic())
intrinsic_block_size = intrinsic_block_size_func();
- return ResolveBlockLengthInternal(
- constraint_space, style, border_padding, length, intrinsic_block_size,
- available_block_size_adjustment,
- opt_percentage_resolution_block_size_for_min_max);
+ return ResolveBlockLengthInternal(constraint_space, style, border_padding,
+ length, intrinsic_block_size,
+ available_block_size_adjustment);
}
// For the given |child|, computes the min and max content contribution
@@ -354,9 +290,7 @@ MinMaxSizes ComputeMinMaxBlockSizes(
const NGConstraintSpace&,
const ComputedStyle&,
const NGBoxStrut& border_padding,
- LayoutUnit available_block_size_adjustment = LayoutUnit(),
- const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
- nullptr);
+ LayoutUnit available_block_size_adjustment = LayoutUnit());
MinMaxSizes ComputeTransferredMinMaxInlineSizes(
const LogicalSize& ratio,
@@ -375,13 +309,11 @@ MinMaxSizes ComputeMinMaxInlineSizesFromAspectRatio(
const NGBoxStrut& border_padding);
template <typename MinMaxSizesFunc>
-MinMaxSizes ComputeMinMaxInlineSizes(
- const NGConstraintSpace& space,
- const NGBlockNode& node,
- const NGBoxStrut& border_padding,
- const MinMaxSizesFunc& min_max_sizes_func,
- const Length* opt_min_length = nullptr,
- absl::optional<bool> is_block_size_indefinite = absl::nullopt) {
+MinMaxSizes ComputeMinMaxInlineSizes(const NGConstraintSpace& space,
+ const NGBlockNode& node,
+ const NGBoxStrut& border_padding,
+ const MinMaxSizesFunc& min_max_sizes_func,
+ const Length* opt_min_length = nullptr) {
const ComputedStyle& style = node.Style();
const Length& min_length =
opt_min_length ? *opt_min_length : style.LogicalMinWidth();
@@ -394,8 +326,7 @@ MinMaxSizes ComputeMinMaxInlineSizes(
// This implements the transferred min/max sizes per:
// https://drafts.csswg.org/css-sizing-4/#aspect-ratio-size-transfers
if (!style.AspectRatio().IsAuto() &&
- is_block_size_indefinite.value_or(
- BlockLengthUnresolvable(space, style.LogicalHeight()))) {
+ BlockLengthUnresolvable(space, style.LogicalHeight())) {
MinMaxSizes transferred_sizes =
ComputeMinMaxInlineSizesFromAspectRatio(space, style, border_padding);
sizes.min_size = std::max(
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 6fe7e5496a2..b759ca46b48 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,6 +6,7 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.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"
@@ -31,7 +32,7 @@ static NGConstraintSpace ConstructConstraintSpace(
/* is_new_fc */ false);
builder.SetAvailableSize(size);
builder.SetPercentageResolutionSize(size);
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
builder.SetIsFixedInlineSize(fixed_inline);
builder.SetIsFixedBlockSize(fixed_block);
return builder.ToConstraintSpace();
@@ -50,8 +51,12 @@ class NGLengthUtilsTest : public testing::Test {
NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
ComputePadding(constraint_space, *style_);
- return ::blink::ResolveMainInlineLength(constraint_space, *style_,
- border_padding, sizes, length);
+ return ::blink::ResolveMainInlineLength(
+ constraint_space, *style_, border_padding,
+ [&](MinMaxSizesType) -> MinMaxSizesResult {
+ return {*sizes, /* depends_on_block_constraints */ false};
+ },
+ length);
}
LayoutUnit ResolveMinInlineLength(
@@ -61,8 +66,12 @@ class NGLengthUtilsTest : public testing::Test {
NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
ComputePadding(constraint_space, *style_);
- return ::blink::ResolveMinInlineLength(constraint_space, *style_,
- border_padding, sizes, length);
+ return ::blink::ResolveMinInlineLength(
+ constraint_space, *style_, border_padding,
+ [&](MinMaxSizesType) -> MinMaxSizesResult {
+ return {*sizes, /* depends_on_block_constraints */ false};
+ },
+ length);
}
LayoutUnit ResolveMaxInlineLength(
@@ -72,8 +81,12 @@ class NGLengthUtilsTest : public testing::Test {
NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
ComputePadding(constraint_space, *style_);
- return ::blink::ResolveMaxInlineLength(constraint_space, *style_,
- border_padding, sizes, length);
+ return ::blink::ResolveMaxInlineLength(
+ constraint_space, *style_, border_padding,
+ [&](MinMaxSizesType) -> MinMaxSizesResult {
+ return {*sizes, /* depends_on_block_constraints */ false};
+ },
+ length);
}
LayoutUnit ResolveMainBlockLength(const Length& length,
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 e910be081d2..354575a8a28 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/layout/layout_flexible_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/ng/grid/ng_grid_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/layout_box_utils.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
@@ -18,12 +19,11 @@
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_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"
-#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -35,8 +35,11 @@ namespace blink {
namespace {
bool IsAnonymousContainer(const LayoutObject* layout_object) {
- return layout_object->IsAnonymousBlock() &&
- layout_object->CanContainAbsolutePositionObjects();
+ const bool result = layout_object->IsAnonymousBlock() &&
+ layout_object->CanContainAbsolutePositionObjects();
+ // There shouldn't be any anonymous container in `NGBlockInInline`.
+ DCHECK(!(RuntimeEnabledFeatures::LayoutNGBlockInInlineEnabled() && result));
+ return result;
}
// When the containing block is a split inline, Legacy and NG use different
@@ -78,15 +81,15 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
NGBoxFragmentBuilder* container_builder)
: NGOutOfFlowLayoutPart(container_node.IsAbsoluteContainer(),
container_node.IsFixedContainer(),
+ container_node.IsGrid(),
container_node.Style(),
container_space,
- container_builder) {
- can_traverse_fragments_ = container_node.CanTraversePhysicalFragments();
-}
+ container_builder) {}
NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
bool is_absolute_container,
bool is_fixed_container,
+ bool is_grid_container,
const ComputedStyle& container_style,
const NGConstraintSpace& container_space,
NGBoxFragmentBuilder* container_builder,
@@ -105,19 +108,24 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
->HasPositionedObjects())
return;
+ // Disable first tier cache for grid layouts, as grid allows for out-of-flow
+ // items to be placed in grid areas, which is complex to maintain a cache for.
+ const NGBoxStrut border_scrollbar =
+ container_builder->Borders() + container_builder->Scrollbar();
+ allow_first_tier_oof_cache_ =
+ border_scrollbar.IsEmpty() && !is_grid_container;
default_containing_block_info_for_absolute_.writing_direction =
default_writing_direction_;
default_containing_block_info_for_fixed_.writing_direction =
default_writing_direction_;
- const NGBoxStrut border_scrollbar =
- container_builder->Borders() + container_builder->Scrollbar();
- allow_first_tier_oof_cache_ = border_scrollbar.IsEmpty();
- default_containing_block_info_for_absolute_.rect.size =
- ShrinkLogicalSize(container_builder_->Size(), border_scrollbar);
- default_containing_block_info_for_fixed_.rect.size =
- initial_containing_block_fixed_size
- ? *initial_containing_block_fixed_size
- : default_containing_block_info_for_absolute_.rect.size;
+ if (container_builder_->HasBlockSize()) {
+ default_containing_block_info_for_absolute_.rect.size =
+ ShrinkLogicalSize(container_builder_->Size(), border_scrollbar);
+ default_containing_block_info_for_fixed_.rect.size =
+ initial_containing_block_fixed_size
+ ? *initial_containing_block_fixed_size
+ : default_containing_block_info_for_absolute_.rect.size;
+ }
LogicalOffset container_offset = {border_scrollbar.inline_start,
border_scrollbar.block_start};
default_containing_block_info_for_absolute_.rect.offset = container_offset;
@@ -125,25 +133,7 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
}
void NGOutOfFlowLayoutPart::Run(const LayoutBox* only_layout) {
- if (container_builder_->IsBlockFragmentationContextRoot() &&
- !has_block_fragmentation_) {
- while (container_builder_->HasOutOfFlowFragmentainerDescendants() ||
- container_builder_->HasMulticolsWithPendingOOFs()) {
- HandleMulticolsWithPendingOOFs(container_builder_);
- if (container_builder_->HasOutOfFlowFragmentainerDescendants()) {
- Vector<NGLogicalOutOfFlowPositionedNode> fragmentainer_descendants;
- container_builder_->SwapOutOfFlowFragmentainerDescendants(
- &fragmentainer_descendants);
- DCHECK(!fragmentainer_descendants.IsEmpty());
- LayoutUnit column_inline_progression = ColumnInlineProgression(
- container_builder_->ChildAvailableSize().inline_size,
- container_builder_->Style());
- LayoutFragmentainerDescendants(&fragmentainer_descendants,
- column_inline_progression);
- }
- }
- }
-
+ HandleFragmentation();
const LayoutObject* current_container = container_builder_->GetLayoutObject();
if (!container_builder_->HasOutOfFlowPositionedCandidates() &&
!To<LayoutBlock>(current_container)->HasPositionedObjects()) {
@@ -181,11 +171,11 @@ void NGOutOfFlowLayoutPart::Run(const LayoutBox* only_layout) {
if (absolute_containing_block &&
absolute_containing_block->CanContainOutOfFlowPositionedElement(
candidate.Node().Style().GetPosition())) {
- candidate.inline_container = absolute_containing_block;
+ candidate.inline_container.container = absolute_containing_block;
} else if (fixed_containing_block &&
fixed_containing_block->CanContainOutOfFlowPositionedElement(
candidate.Node().Style().GetPosition())) {
- candidate.inline_container = fixed_containing_block;
+ candidate.inline_container.container = fixed_containing_block;
}
container_builder_->AddOutOfFlowDescendant(candidate);
}
@@ -294,6 +284,30 @@ bool NGOutOfFlowLayoutPart::SweepLegacyCandidates(
return true;
}
+void NGOutOfFlowLayoutPart::HandleFragmentation() {
+ if (!container_builder_->IsBlockFragmentationContextRoot() ||
+ has_block_fragmentation_)
+ return;
+
+ while (container_builder_->HasOutOfFlowFragmentainerDescendants() ||
+ container_builder_->HasMulticolsWithPendingOOFs()) {
+ HandleMulticolsWithPendingOOFs(container_builder_);
+ if (container_builder_->HasOutOfFlowFragmentainerDescendants()) {
+ Vector<NGLogicalOutOfFlowPositionedNode> fragmentainer_descendants;
+ container_builder_->SwapOutOfFlowFragmentainerDescendants(
+ &fragmentainer_descendants);
+ DCHECK(!fragmentainer_descendants.IsEmpty());
+ LayoutUnit column_inline_progression = ColumnInlineProgression(
+ container_builder_->ChildAvailableSize().inline_size,
+ container_builder_->Style());
+ LayoutFragmentainerDescendants(&fragmentainer_descendants,
+ column_inline_progression);
+ }
+ }
+ for (auto& descendant : delayed_descendants_)
+ container_builder_->AddOutOfFlowFragmentainerDescendant(descendant);
+}
+
// Retrieve the stored ContainingBlockInfo needed for placing positioned nodes.
// When fragmenting, the ContainingBlockInfo is not stored ahead of time and
// must be generated on demand. The reason being that during fragmentation, we
@@ -305,10 +319,21 @@ bool NGOutOfFlowLayoutPart::SweepLegacyCandidates(
const NGOutOfFlowLayoutPart::ContainingBlockInfo
NGOutOfFlowLayoutPart::GetContainingBlockInfo(
const NGLogicalOutOfFlowPositionedNode& candidate) {
- if (candidate.containing_block_rect)
- return {default_writing_direction_, *candidate.containing_block_rect};
- if (candidate.inline_container) {
- const auto it = containing_blocks_map_.find(candidate.inline_container);
+ if (container_builder_->GetLayoutObject()->IsLayoutNGGrid()) {
+ absl::optional<LogicalRect> containing_block_rect =
+ NGGridLayoutAlgorithm::ComputeContainingBlockRect(
+ candidate.Node(), container_builder_->GetNGGridData(),
+ container_builder_->Style(),
+ default_writing_direction_.GetWritingMode(),
+ container_builder_->Borders(),
+ container_builder_->InitialBorderBoxSize(),
+ container_builder_->FragmentsTotalBlockSize());
+ if (containing_block_rect.has_value())
+ return {default_writing_direction_, *containing_block_rect};
+ }
+ if (candidate.inline_container.container) {
+ const auto it =
+ containing_blocks_map_.find(candidate.inline_container.container);
DCHECK(it != containing_blocks_map_.end());
return it->value;
}
@@ -358,24 +383,106 @@ NGOutOfFlowLayoutPart::GetContainingBlockInfo(
void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
const Vector<NGLogicalOutOfFlowPositionedNode>& candidates) {
- NGBoxFragmentBuilder::InlineContainingBlockMap inline_container_fragments;
+ InlineContainingBlockUtils::InlineContainingBlockMap
+ inline_container_fragments;
for (auto& candidate : candidates) {
- if (candidate.inline_container &&
- !inline_container_fragments.Contains(candidate.inline_container)) {
- NGBoxFragmentBuilder::InlineContainingBlockGeometry inline_geometry = {};
- inline_container_fragments.insert(candidate.inline_container,
+ if (candidate.inline_container.container &&
+ !inline_container_fragments.Contains(
+ candidate.inline_container.container)) {
+ InlineContainingBlockUtils::InlineContainingBlockGeometry
+ inline_geometry = {};
+ inline_container_fragments.insert(candidate.inline_container.container,
inline_geometry);
}
}
// Fetch the inline start/end fragment geometry.
- container_builder_->ComputeInlineContainerGeometry(
- &inline_container_fragments);
+ InlineContainingBlockUtils::ComputeInlineContainerGeometry(
+ &inline_container_fragments, container_builder_);
LogicalSize container_builder_size = container_builder_->Size();
PhysicalSize container_builder_physical_size =
ToPhysicalSize(container_builder_size, writing_mode_);
+ AddInlineContainingBlockInfo(
+ inline_container_fragments,
+ default_containing_block_info_for_absolute_.writing_direction,
+ container_builder_physical_size);
+}
+
+void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocksForFragmentainer(
+ const Vector<NGLogicalOutOfFlowPositionedNode>& descendants) {
+ struct InlineContainingBlockInfo {
+ InlineContainingBlockUtils::InlineContainingBlockMap map;
+ // The relative offset of the inline's containing block to the
+ // fragmentation context root.
+ LogicalOffset relative_offset;
+ // The offset of the containing block relative to the fragmentation context
+ // root (not including any relative offset).
+ LogicalOffset offset_to_fragmentation_context;
+ };
+
+ HashMap<const LayoutBox*, InlineContainingBlockInfo> inline_containg_blocks;
+
+ // Collect the inline containers by shared containing block.
+ for (auto& descendant : descendants) {
+ if (descendant.inline_container.container) {
+ DCHECK(descendant.containing_block.fragment);
+ const LayoutBox* containing_block = To<LayoutBox>(
+ descendant.containing_block.fragment->GetLayoutObject());
+
+ InlineContainingBlockUtils::InlineContainingBlockGeometry
+ inline_geometry = {};
+ inline_geometry.relative_offset =
+ descendant.inline_container.relative_offset;
+ auto it = inline_containg_blocks.find(containing_block);
+ if (it != inline_containg_blocks.end()) {
+ if (!it->value.map.Contains(descendant.inline_container.container)) {
+ it->value.map.insert(descendant.inline_container.container,
+ inline_geometry);
+ }
+ continue;
+ }
+ InlineContainingBlockUtils::InlineContainingBlockMap inline_containers;
+ inline_containers.insert(descendant.inline_container.container,
+ inline_geometry);
+ InlineContainingBlockInfo inline_info{
+ inline_containers,
+ descendant.containing_block.relative_offset,
+ descendant.containing_block.offset};
+ inline_containg_blocks.insert(containing_block, inline_info);
+ }
+ }
+
+ for (auto& inline_containg_block : inline_containg_blocks) {
+ const LayoutBox* containing_block = inline_containg_block.key;
+ InlineContainingBlockInfo& inline_info = inline_containg_block.value;
+
+ LogicalSize size(LayoutBoxUtils::InlineSize(*containing_block),
+ LayoutBoxUtils::TotalBlockSize(*containing_block));
+ PhysicalSize container_builder_physical_size =
+ ToPhysicalSize(size, containing_block->StyleRef().GetWritingMode());
+
+ // Fetch the inline start/end fragment geometry.
+ InlineContainingBlockUtils::ComputeInlineContainerGeometryForFragmentainer(
+ containing_block, container_builder_physical_size, &inline_info.map);
+
+ AddInlineContainingBlockInfo(
+ inline_info.map, containing_block->StyleRef().GetWritingDirection(),
+ container_builder_physical_size, inline_info.relative_offset,
+ inline_info.offset_to_fragmentation_context,
+ /* adjust_for_fragmentation */ true);
+ }
+}
+
+void NGOutOfFlowLayoutPart::AddInlineContainingBlockInfo(
+ const InlineContainingBlockUtils::InlineContainingBlockMap&
+ inline_container_fragments,
+ const WritingDirectionMode container_writing_direction,
+ PhysicalSize container_builder_size,
+ LogicalOffset containing_block_relative_offset,
+ LogicalOffset containing_block_offset,
+ bool adjust_for_fragmentation) {
// Transform the start/end fragments into a ContainingBlockInfo.
for (const auto& block_info : inline_container_fragments) {
DCHECK(block_info.value.has_value());
@@ -435,8 +542,6 @@ void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
const ComputedStyle* inline_cb_style = block_info.key->Style();
DCHECK(inline_cb_style);
- const auto container_writing_direction =
- default_containing_block_info_for_absolute_.writing_direction;
const auto inline_writing_direction =
inline_cb_style->GetWritingDirection();
NGBoxStrut inline_cb_borders = ComputeBordersForInline(*inline_cb_style);
@@ -450,8 +555,7 @@ void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
const PhysicalRect& start_rect =
block_info.value->start_fragment_union_rect;
LogicalOffset start_offset = start_rect.offset.ConvertToLogical(
- container_writing_direction, container_builder_physical_size,
- start_rect.size);
+ container_writing_direction, container_builder_size, start_rect.size);
// Make sure we add the inline borders, we don't need to do this in the
// inline direction if the blocks are in opposite directions.
@@ -462,8 +566,7 @@ void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
// Step 2 - determine the end_offset.
const PhysicalRect& end_rect = block_info.value->end_fragment_union_rect;
LogicalOffset end_offset = end_rect.offset.ConvertToLogical(
- container_writing_direction, container_builder_physical_size,
- end_rect.size);
+ container_writing_direction, container_builder_size, end_rect.size);
// Add in the size of the fragment to get the logical end of the fragment.
end_offset += end_rect.size.ConvertToLogical(
@@ -480,6 +583,7 @@ void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
std::max(end_offset.inline_offset, start_offset.inline_offset);
end_offset.block_offset =
std::max(end_offset.block_offset, start_offset.block_offset);
+
// Step 3 - determine the logical rectangle.
// Determine the logical size of the containing block.
@@ -489,13 +593,51 @@ void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
DCHECK_GE(inline_cb_size.inline_size, LayoutUnit());
DCHECK_GE(inline_cb_size.block_size, LayoutUnit());
- // Set the container padding-box offset.
- LogicalOffset container_offset = start_offset;
+ if (adjust_for_fragmentation) {
+ // When fragmenting, the containing block will not be associated with the
+ // current builder. Thus, we need to adjust the start offset to take the
+ // writing mode of the builder into account.
+ PhysicalSize physical_size =
+ ToPhysicalSize(inline_cb_size, writing_mode_);
+ start_offset =
+ start_offset
+ .ConvertToPhysical(container_writing_direction,
+ container_builder_size, physical_size)
+ .ConvertToLogical(default_writing_direction_,
+ container_builder_size, physical_size);
+ }
+ // Subtract out the inline relative offset, if set, so that it can be
+ // applied after fragmentation is performed on the fragmentainer
+ // descendants.
+ DCHECK((block_info.value->relative_offset == LogicalOffset() &&
+ containing_block_relative_offset == LogicalOffset() &&
+ containing_block_offset == LogicalOffset()) ||
+ container_builder_->IsBlockFragmentationContextRoot());
+ LogicalOffset container_offset =
+ start_offset - block_info.value->relative_offset;
+ LogicalOffset total_relative_offset =
+ containing_block_relative_offset + block_info.value->relative_offset;
+
+ // The offset of the container is currently relative to the containing
+ // block. Add the offset of the containng block to the fragmentation context
+ // root so that it is relative to the fragmentation context root, instead.
+ container_offset += containing_block_offset;
+
+ // If an OOF has an inline containing block, the OOF offset that is written
+ // back to legacy is relative to the containing block of the inline rather
+ // than the inline itself. |containing_block_offset| will be used when
+ // calculating this OOF offset. However, there may be some relative offset
+ // between the containing block and the inline container that should be
+ // included in the final OOF offset that is written back to legacy. Adjust
+ // for that relative offset here.
containing_blocks_map_.insert(
block_info.key,
- ContainingBlockInfo{inline_writing_direction,
- LogicalRect(container_offset, inline_cb_size)});
+ ContainingBlockInfo{
+ inline_writing_direction,
+ LogicalRect(container_offset, inline_cb_size),
+ total_relative_offset,
+ containing_block_offset - block_info.value->relative_offset});
}
}
@@ -504,22 +646,25 @@ void NGOutOfFlowLayoutPart::LayoutCandidates(
const LayoutBox* only_layout,
HashSet<const LayoutObject*>* placed_objects) {
while (candidates->size() > 0) {
- ComputeInlineContainingBlocks(*candidates);
+ if (!has_block_fragmentation_ ||
+ container_builder_->IsInitialColumnBalancingPass())
+ ComputeInlineContainingBlocks(*candidates);
for (auto& candidate : *candidates) {
LayoutBox* layout_box = candidate.box;
if (!container_builder_->IsBlockFragmentationContextRoot())
SaveStaticPositionOnPaintLayer(layout_box, candidate.static_position);
if (IsContainingBlockForCandidate(candidate) &&
(!only_layout || layout_box == only_layout)) {
- if (has_block_fragmentation_) {
+ if (layout_box != only_layout)
+ candidate.Node().InsertIntoLegacyPositionedObjects();
+ if (has_block_fragmentation_ &&
+ !container_builder_->IsInitialColumnBalancingPass()) {
container_builder_->AdjustOffsetsForFragmentainerDescendant(
candidate);
container_builder_->AdjustFixedposContainingBlockForInnerMulticols();
container_builder_->AddOutOfFlowFragmentainerDescendant(candidate);
continue;
}
- if (layout_box != only_layout)
- candidate.Node().InsertIntoLegacyPositionedObjects();
NodeInfo node_info = SetupNodeInfo(candidate);
NodeToLayout node_to_layout = {node_info,
CalculateOffset(node_info, only_layout)};
@@ -527,7 +672,11 @@ void NGOutOfFlowLayoutPart::LayoutCandidates(
LayoutOOFNode(node_to_layout, only_layout);
container_builder_->AddChild(result->PhysicalFragment(),
result->OutOfFlowPositionedOffset(),
- candidate.inline_container);
+ &candidate.inline_container);
+ if (container_builder_->IsInitialColumnBalancingPass()) {
+ container_builder_->PropagateTallestUnbreakableBlockSize(
+ result->TallestUnbreakableBlockSize());
+ }
placed_objects->insert(layout_box);
} else {
container_builder_->AddOutOfFlowDescendant(candidate);
@@ -570,13 +719,26 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
LayoutUnit column_inline_progression = kIndefiniteSize;
LogicalOffset multicol_offset = multicol_info->multicol_offset;
- NGConstraintSpace multicol_constraint_space =
+ // Create a simplified container builder for multicol children. It cannot be
+ // used to generate a fragment (since no size has been set, for one), but is
+ // suitable for holding child fragmentainers while we're cloning them.
+ NGConstraintSpace limited_multicol_constraint_space =
CreateConstraintSpaceForMulticol(multicol);
- NGFragmentGeometry fragment_geometry =
- CalculateInitialFragmentGeometry(multicol_constraint_space, multicol);
- NGBoxFragmentBuilder multicol_container_builder =
- CreateContainerBuilderForMulticol(multicol, multicol_constraint_space,
- fragment_geometry);
+ NGFragmentGeometry limited_fragment_geometry =
+ CalculateInitialFragmentGeometry(limited_multicol_constraint_space,
+ multicol);
+ NGBoxFragmentBuilder limited_multicol_container_builder =
+ CreateContainerBuilderForMulticol(multicol,
+ limited_multicol_constraint_space,
+ limited_fragment_geometry);
+ // The block size that we set on the multicol builder doesn't matter since
+ // we only care about the size of the fragmentainer children when laying out
+ // the remaining OOFs.
+ limited_multicol_container_builder.SetFragmentsTotalBlockSize(LayoutUnit());
+
+ WritingDirectionMode writing_direction =
+ multicol.Style().GetWritingDirection();
+ const NGPhysicalBoxFragment* last_fragment_with_fragmentainer = nullptr;
// Accumulate all of the pending OOF positioned nodes that are stored inside
// |multicol|.
@@ -585,7 +747,6 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
To<NGPhysicalBoxFragment>(&multicol_fragment);
const ComputedStyle& style = multicol_box_fragment->Style();
- WritingDirectionMode writing_direction = style.GetWritingDirection();
const WritingModeConverter converter(writing_direction,
multicol_box_fragment->Size());
wtf_size_t current_column_index = 0;
@@ -614,9 +775,10 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
current_column_break_token =
To<NGBlockBreakToken>(fragment->BreakToken());
current_column_index = multicol_children.size();
+ last_fragment_with_fragmentainer = multicol_box_fragment;
}
- multicol_container_builder.AddChild(
+ limited_multicol_container_builder.AddChild(
*fragment, offset, /* inline_container */ nullptr,
/* margin_strut */ nullptr, /* is_self_collapsing */ false,
/* relative_offset */ absl::nullopt,
@@ -661,6 +823,10 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
}
const NGPhysicalFragment* containing_block_fragment =
descendant.containing_block.fragment.get();
+ // If the containing block is not set, that means that the inner multicol
+ // was its containing block, and the OOF will be laid out elsewhere.
+ if (!containing_block_fragment)
+ continue;
LogicalOffset containing_block_offset =
converter.ToLogical(descendant.containing_block.offset,
containing_block_fragment->Size());
@@ -681,6 +847,11 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
fixedpos_containing_block_fragment->Size());
}
+ NGInlineContainer<LogicalOffset> inline_container(
+ descendant.inline_container.container,
+ converter.ToLogical(descendant.inline_container.relative_offset,
+ PhysicalSize()));
+
// The static position should remain relative to its containing block
// fragment.
const WritingModeConverter containing_block_converter(
@@ -692,7 +863,7 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
NGLogicalOutOfFlowPositionedNode node = {
descendant.Node(),
static_position,
- descendant.inline_container,
+ inline_container,
/* needs_block_offset_adjustment */ false,
NGContainingBlock<LogicalOffset>(containing_block_offset,
containing_block_rel_offset,
@@ -705,28 +876,104 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInMulticol(
previous_multicol_break_token = break_token;
}
DCHECK(!oof_nodes_to_layout.IsEmpty());
- DCHECK(!multicol_container_builder.HasOutOfFlowFragmentainerDescendants());
+ DCHECK(!limited_multicol_container_builder
+ .HasOutOfFlowFragmentainerDescendants());
+
+ wtf_size_t old_fragment_count =
+ limited_multicol_container_builder.Children().size();
// Layout the OOF positioned elements inside the inner multicol.
- NGOutOfFlowLayoutPart(multicol, multicol_constraint_space,
- &multicol_container_builder)
+ NGOutOfFlowLayoutPart(multicol, limited_multicol_constraint_space,
+ &limited_multicol_container_builder)
.LayoutFragmentainerDescendants(
&oof_nodes_to_layout, column_inline_progression,
multicol_info->fixedpos_containing_block.fragment.get(),
&multicol_children);
+ wtf_size_t new_fragment_count =
+ limited_multicol_container_builder.Children().size();
+
+ if (old_fragment_count != new_fragment_count) {
+ DCHECK_GT(new_fragment_count, old_fragment_count);
+ // We created additional fragmentainers to hold OOFs, and this is in a
+ // nested fragmentation context. This means that the multicol fragment has
+ // already been created, and we will therefore need to replace one of those
+ // fragments. Locate the last multicol container fragment that already has
+ // fragmentainers, and append all new fragmentainers there. Note that this
+ // means that we may end up with more inner fragmentainers than what we
+ // actually have room for (so that they'll overflow in the inline
+ // direction), because we don't attempt to put fragmentainers into
+ // additional multicol fragments in outer fragmentainers. This is an
+ // implementation limitation which we can hopefully live with.
+ DCHECK(last_fragment_with_fragmentainer);
+ LayoutBox& box = *last_fragment_with_fragmentainer->MutableOwnerLayoutBox();
+ wtf_size_t fragment_count = box.PhysicalFragmentCount();
+ DCHECK_GE(fragment_count, 1u);
+ scoped_refptr<const NGLayoutResult> old_result;
+ wtf_size_t fragment_idx = fragment_count - 1;
+ do {
+ old_result = box.GetLayoutResult(fragment_idx);
+ if (&old_result->PhysicalFragment() == last_fragment_with_fragmentainer)
+ break;
+ DCHECK_GT(fragment_idx, 0u);
+ fragment_idx--;
+ } while (true);
+
+ // We have located the right multicol fragment to replace. Re-use its old
+ // constraint space and establish a layout algorithm to regenerate the
+ // fragment.
+ const NGConstraintSpace& constraint_space =
+ old_result->GetConstraintSpaceForCaching();
+ NGFragmentGeometry fragment_geometry =
+ CalculateInitialFragmentGeometry(constraint_space, multicol);
+ NGLayoutAlgorithmParams params(multicol, fragment_geometry,
+ constraint_space);
+ NGSimplifiedLayoutAlgorithm algorithm(params, *old_result,
+ /* keep_old_size */ true);
+
+ // First copy the fragmentainers (and other child fragments) that we already
+ // had.
+ algorithm.CloneOldChildren();
+
+ WritingModeConverter converter(constraint_space.GetWritingDirection(),
+ old_result->PhysicalFragment().Size());
+ LayoutUnit additional_column_block_size;
+ // Then append the new fragmentainers.
+ for (wtf_size_t i = old_fragment_count; i < new_fragment_count; i++) {
+ NGContainerFragmentBuilder::ChildWithOffset child =
+ limited_multicol_container_builder.Children()[i];
+ algorithm.AppendNewChildFragment(*child.fragment, child.offset);
+ additional_column_block_size +=
+ converter.ToLogical(child.fragment->Size()).block_size;
+ }
+
+ // We've already written back to legacy for |multicol|, but if we added
+ // new columns to hold any OOF descendants, we need to extend the final
+ // size of the legacy flow thread to encompass those new columns.
+ multicol.MakeRoomForExtraColumns(additional_column_block_size);
+
+ // Create a new multicol container fragment and replace all references to
+ // the old one with this new one.
+ scoped_refptr<const NGLayoutResult> new_result =
+ algorithm.CreateResultAfterManualChildLayout();
+ ReplaceFragment(std::move(new_result), *last_fragment_with_fragmentainer,
+ fragment_idx);
+ }
+
// Any descendants should have been handled in
// LayoutFragmentainerDescendants(). However, if there were any candidates
// found, pass them back to |container_builder_| so they can continue
// propagating up the tree.
- DCHECK(!multicol_container_builder.HasOutOfFlowPositionedDescendants());
- DCHECK(!multicol_container_builder.HasOutOfFlowFragmentainerDescendants());
- multicol_container_builder.TransferOutOfFlowCandidates(
+ DCHECK(
+ !limited_multicol_container_builder.HasOutOfFlowPositionedDescendants());
+ DCHECK(!limited_multicol_container_builder
+ .HasOutOfFlowFragmentainerDescendants());
+ limited_multicol_container_builder.TransferOutOfFlowCandidates(
container_builder_, multicol_offset, multicol_info);
// Handle any inner multicols with OOF descendants that may have propagated up
// while laying out the direct OOF descendants of the current multicol.
- HandleMulticolsWithPendingOOFs(&multicol_container_builder);
+ HandleMulticolsWithPendingOOFs(&limited_multicol_container_builder);
}
void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
@@ -745,9 +992,26 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
Vector<Vector<NodeToLayout>> descendants_to_layout;
while (descendants->size() > 0) {
+ ComputeInlineContainingBlocksForFragmentainer(*descendants);
+
// Sort the descendants by fragmentainer index in |descendants_to_layout|.
// This will ensure that the descendants are laid out in the correct order.
for (auto& descendant : *descendants) {
+ auto* containing_block = To<LayoutBox>(
+ descendant.containing_block.fragment->GetLayoutObject());
+ DCHECK(containing_block);
+
+ // We may try to lay out an OOF once we reach a column spanner. However,
+ // if the containing block has not finished lay out, we should wait to
+ // lay out the OOF in case its position is dependent on its containing
+ // block's final size.
+ if (containing_block
+ ->GetPhysicalFragment(containing_block->PhysicalFragmentCount() -
+ 1)
+ ->BreakToken()) {
+ delayed_descendants_.push_back(descendant);
+ continue;
+ }
NodeInfo node_info = SetupNodeInfo(descendant);
NodeToLayout node_to_layout = {
node_info, CalculateOffset(node_info, /* only_layout */ nullptr)};
@@ -760,7 +1024,6 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
// and adjust the offset to be relative to that fragmentainer.
wtf_size_t start_index = 0;
ComputeStartFragmentIndexAndRelativeOffset(
- node_info.container_info,
node_info.default_writing_direction.GetWritingMode(),
*node_to_layout.offset_info.block_estimate, &start_index,
&node_to_layout.offset_info.offset);
@@ -781,19 +1044,14 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
// Skip over any column spanners.
if (!fragment || fragment->IsFragmentainerBox()) {
- const Vector<NodeToLayout>& pending_descendants =
+ Vector<NodeToLayout>& pending_descendants =
descendants_to_layout[index];
LayoutOOFsInFragmentainer(pending_descendants, index,
column_inline_progression,
&fragmented_descendants);
// Retrieve the updated or newly added fragmentainer, and add its block
- // contribution to the consumed block size. (Note: We don't add new
- // columns in a nested fragmentation context. Instead, any OOFs are
- // added to the last existing fragmentainer with an additional inline
- // offset).
- wtf_size_t used_index =
- (!fragment && multicol_children_) ? num_children - 1 : index;
- fragment = container_builder_->Children()[used_index].fragment.get();
+ // contribution to the consumed block size.
+ fragment = container_builder_->Children()[index].fragment.get();
fragmentainer_consumed_block_size_ +=
fragment->Size()
.ConvertToLogical(container_builder_->Style().GetWritingMode())
@@ -836,16 +1094,12 @@ NGOutOfFlowLayoutPart::NodeInfo NGOutOfFlowLayoutPart::SetupNodeInfo(
#endif
const ContainingBlockInfo container_info = GetContainingBlockInfo(oof_node);
- const auto default_writing_direction =
- containing_block_fragment
- ? containing_block_fragment->Style().GetWritingDirection()
- : default_writing_direction_;
const ComputedStyle& oof_style = node.Style();
const auto oof_writing_direction = oof_style.GetWritingDirection();
LogicalSize container_content_size = container_info.rect.size;
PhysicalSize container_physical_content_size = ToPhysicalSize(
- container_content_size, default_writing_direction.GetWritingMode());
+ container_content_size, default_writing_direction_.GetWritingMode());
// Adjust the |static_position| (which is currently relative to the default
// container's border-box). ng_absolute_utils expects the static position to
@@ -861,17 +1115,26 @@ NGOutOfFlowLayoutPart::NodeInfo NGOutOfFlowLayoutPart::SetupNodeInfo(
NGLogicalStaticPosition oof_static_position =
static_position
.ConvertToPhysical(
- {default_writing_direction, container_physical_content_size})
+ {default_writing_direction_, container_physical_content_size})
.ConvertToLogical(
{oof_writing_direction, container_physical_content_size});
// Need a constraint space to resolve offsets.
- NGConstraintSpaceBuilder builder(default_writing_direction.GetWritingMode(),
+ NGConstraintSpaceBuilder builder(default_writing_direction_.GetWritingMode(),
oof_writing_direction,
/* is_new_fc */ true);
builder.SetAvailableSize(container_content_size);
builder.SetPercentageResolutionSize(container_content_size);
+ if (container_builder_->IsInitialColumnBalancingPass()) {
+ // The |fragmentainer_offset_delta| will not make a difference in the
+ // initial column balancing pass.
+ SetupSpaceBuilderForFragmentation(
+ *container_builder_->ConstraintSpace(), node,
+ /* fragmentainer_offset_delta */ LayoutUnit(), &builder,
+ /* is_new_fc */ true);
+ }
+
DCHECK(!oof_node.fixedpos_containing_block.fragment ||
containing_block_fragment);
DCHECK(oof_node.fixedpos_containing_block.offset == LogicalOffset() ||
@@ -879,18 +1142,18 @@ NGOutOfFlowLayoutPart::NodeInfo NGOutOfFlowLayoutPart::SetupNodeInfo(
return NodeInfo(node, builder.ToConstraintSpace(), oof_static_position,
container_physical_content_size, container_info,
- default_writing_direction,
+ default_writing_direction_,
/* is_fragmentainer_descendant */ containing_block_fragment,
oof_node.fixedpos_containing_block,
- oof_node.inline_container);
+ oof_node.inline_container.container);
}
scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::LayoutOOFNode(
- const NodeToLayout& oof_node_to_layout,
+ NodeToLayout& oof_node_to_layout,
const LayoutBox* only_layout,
const NGConstraintSpace* fragmentainer_constraint_space) {
const NodeInfo& node_info = oof_node_to_layout.node_info;
- OffsetInfo offset_info = oof_node_to_layout.offset_info;
+ OffsetInfo& offset_info = oof_node_to_layout.offset_info;
if (offset_info.has_cached_layout_result) {
DCHECK(offset_info.initial_layout_result);
return offset_info.initial_layout_result;
@@ -1009,7 +1272,13 @@ NGOutOfFlowLayoutPart::OffsetInfo NGOutOfFlowLayoutPart::CalculateOffset(
offset_info.offset.inline_offset += inset.inline_start;
offset_info.offset.block_offset += inset.block_start;
- if (!only_layout && !can_traverse_fragments_) {
+ if (!only_layout && !container_builder_->IsBlockFragmentationContextRoot()) {
+ // OOFs contained by an inline that's been split into continuations are
+ // special, as their offset is relative to a fragment that's not the same as
+ // their containing NG fragment; take a look inside
+ // AdjustOffsetForSplitInline() for further details. This doesn't apply if
+ // block fragmentation is involved, though, since all OOFs are then child
+ // fragments of the nearest fragmentainer.
AdjustOffsetForSplitInline(node_info.node, container_builder_,
offset_info.offset);
}
@@ -1021,12 +1290,12 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
const NodeToLayout& oof_node_to_layout,
const NGConstraintSpace* fragmentainer_constraint_space) {
const NodeInfo& node_info = oof_node_to_layout.node_info;
- const OffsetInfo& offset_info = oof_node_to_layout.offset_info;
const WritingDirectionMode candidate_writing_direction =
node_info.node.Style().GetWritingDirection();
LogicalSize container_content_size_in_candidate_writing_mode =
node_info.container_physical_content_size.ConvertToLogical(
candidate_writing_direction.GetWritingMode());
+ const OffsetInfo& offset_info = oof_node_to_layout.offset_info;
LogicalOffset offset = offset_info.offset;
// Reset the |layout_result| computed earlier to allow fragmentation in the
@@ -1082,9 +1351,9 @@ bool NGOutOfFlowLayoutPart::IsContainingBlockForCandidate(
// Candidates whose containing block is inline are always positioned inside
// closest parent block flow.
- if (candidate.inline_container) {
- DCHECK(candidate.inline_container->CanContainOutOfFlowPositionedElement(
- position));
+ if (candidate.inline_container.container) {
+ DCHECK(candidate.inline_container.container
+ ->CanContainOutOfFlowPositionedElement(position));
return container_builder_->GetLayoutObject() ==
candidate.box->ContainingBlock();
}
@@ -1129,6 +1398,10 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::GenerateFragment(
SetupSpaceBuilderForFragmentation(*fragmentainer_constraint_space, node,
block_offset, &builder,
/* is_new_fc */ true);
+ } else if (container_builder_->IsInitialColumnBalancingPass()) {
+ SetupSpaceBuilderForFragmentation(*container_builder_->ConstraintSpace(),
+ node, block_offset, &builder,
+ /* is_new_fc */ true);
}
NGConstraintSpace space = builder.ToConstraintSpace();
@@ -1136,7 +1409,7 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::GenerateFragment(
}
void NGOutOfFlowLayoutPart::LayoutOOFsInFragmentainer(
- const Vector<NodeToLayout>& pending_descendants,
+ Vector<NodeToLayout>& pending_descendants,
wtf_size_t index,
LayoutUnit column_inline_progression,
Vector<NodeToLayout>* fragmented_descendants) {
@@ -1155,20 +1428,6 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInFragmentainer(
!is_new_fragment)
return;
- // If an OOF positioned element is in a nested context, and it fragments
- // beyond the last fragmentainer, we don't create a new column for it.
- // Rather, we will add it to the last existing fragmentainter at the
- // correct inline offset.
- bool create_new_fragment = is_new_fragment && !multicol_children_;
- bool add_to_last_fragment = is_new_fragment && multicol_children_;
-
- LayoutUnit additional_inline_offset;
- if (is_new_fragment) {
- wtf_size_t num_new_fragmentainers = index - num_children + 1;
- additional_inline_offset =
- column_inline_progression * num_new_fragmentainers;
- }
-
const NGConstraintSpace& space = GetFragmentainerConstraintSpace(index);
// If we are a new fragment, find a non-spanner fragmentainer as a basis.
@@ -1183,17 +1442,34 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInFragmentainer(
const auto& fragmentainer = container_builder_->Children()[index];
DCHECK(fragmentainer.fragment->IsFragmentainerBox());
const NGBlockNode& node = container_builder_->Node();
- const auto& fragment =
- To<NGPhysicalBoxFragment>(*fragmentainer.fragment.get());
+ const auto* fragment =
+ To<NGPhysicalBoxFragment>(fragmentainer.fragment.get());
+ NGFragmentGeometry fragment_geometry =
+ CalculateInitialFragmentGeometry(space, node);
+
+ // If the last existing fragmentainer does not have a break token, and we will
+ // need to add a new subsequent fragmentainer to hold an OOF, create a break
+ // token for the old fragmentainer now.
+ if (is_new_fragment && !fragment->BreakToken()) {
+ const NGBlockBreakToken* previous_break_token =
+ PreviousFragmentainerBreakToken(*container_builder_, index);
+ NGLayoutAlgorithmParams params(node, fragment_geometry, space,
+ previous_break_token,
+ /* early_break */ nullptr);
+ NGSimplifiedOOFLayoutAlgorithm algorithm(params, *fragment,
+ /* is_new_fragment */ false,
+ /* should_break_for_oof */ true);
+ ReplaceFragmentainer(index, fragmentainer.offset,
+ /* create_new_fragment */ false, &algorithm);
+ fragment = To<NGPhysicalBoxFragment>(
+ container_builder_->Children()[index].fragment.get());
+ }
+
LogicalOffset fragmentainer_offset = UpdatedFragmentainerOffset(
- fragmentainer.offset, index, column_inline_progression,
- create_new_fragment);
+ fragmentainer.offset, index, column_inline_progression, is_new_fragment);
const NGBlockBreakToken* previous_break_token =
- PreviousFragmentainerBreakToken(add_to_last_fragment ? index
- : original_index);
- NGFragmentGeometry fragment_geometry =
- CalculateInitialFragmentGeometry(space, node);
+ PreviousFragmentainerBreakToken(*container_builder_, original_index);
NGLayoutAlgorithmParams params(node, fragment_geometry, space,
previous_break_token,
/* early_break */ nullptr);
@@ -1201,34 +1477,29 @@ void NGOutOfFlowLayoutPart::LayoutOOFsInFragmentainer(
// |algorithm| corresponds to the "mutable copy" of our original
// fragmentainer. As long as this "copy" hasn't been laid out via
// NGSimplifiedOOFLayoutAlgorithm::Layout, we can append new items to it.
- NGSimplifiedOOFLayoutAlgorithm algorithm(params, fragment,
- create_new_fragment);
+ NGSimplifiedOOFLayoutAlgorithm algorithm(params, *fragment, is_new_fragment);
// Layout any OOF elements that are a continuation of layout first.
for (auto& descendant : descendants_continued) {
- AddOOFToFragmentainer(descendant, &space, additional_inline_offset,
- add_to_last_fragment, fragmentainer_offset, index,
+ AddOOFToFragmentainer(descendant, &space, fragmentainer_offset, index,
&algorithm, fragmented_descendants);
}
// Once we've laid out the OOF elements that are a continuation of layout, we
// can layout the OOF elements that start layout in the current fragmentainer.
for (auto& descendant : pending_descendants) {
- AddOOFToFragmentainer(descendant, &space, additional_inline_offset,
- add_to_last_fragment, fragmentainer_offset, index,
+ AddOOFToFragmentainer(descendant, &space, fragmentainer_offset, index,
&algorithm, fragmented_descendants);
}
// Finalize layout on the cloned fragmentainer and replace all existing
// references to the old result.
- ReplaceFragmentainer(index, fragmentainer_offset, create_new_fragment,
+ ReplaceFragmentainer(index, fragmentainer_offset, is_new_fragment,
&algorithm);
}
void NGOutOfFlowLayoutPart::AddOOFToFragmentainer(
- const NodeToLayout& descendant,
+ NodeToLayout& descendant,
const NGConstraintSpace* fragmentainer_space,
- LayoutUnit additional_inline_offset,
- bool add_to_last_fragment,
LogicalOffset fragmentainer_offset,
wtf_size_t index,
NGSimplifiedOOFLayoutAlgorithm* algorithm,
@@ -1249,14 +1520,6 @@ void NGOutOfFlowLayoutPart::AddOOFToFragmentainer(
// that all fragmentainers are stacked on top of each other.
LogicalOffset offset_adjustment = fragmentainer_offset;
- // If we are adding the result to the last fragmentainer rather than
- // creating a new fragmentainer to hold it, adjust the inline offset as if
- // we had created a new fragmentainer.
- if (add_to_last_fragment) {
- adjusted_offset.inline_offset += additional_inline_offset;
- offset_adjustment.inline_offset += additional_inline_offset;
- }
-
result->GetMutableForOutOfFlow().SetOutOfFlowPositionedOffset(
adjusted_offset, allow_first_tier_oof_cache_);
@@ -1282,7 +1545,8 @@ void NGOutOfFlowLayoutPart::AddOOFToFragmentainer(
// containing block such that the static positions are relative to the
// containing block.
DCHECK(multicol_children_);
- for (wtf_size_t i = index; i > 0u; i--) {
+ for (wtf_size_t i = std::min(index, multicol_children_->size()); i > 0u;
+ i--) {
MulticolChildInfo& column_info = (*multicol_children_)[i - 1];
if (column_info.parent_break_token) {
additional_fixedpos_offset.block_offset +=
@@ -1295,12 +1559,14 @@ void NGOutOfFlowLayoutPart::AddOOFToFragmentainer(
LayoutUnit containing_block_adjustment =
container_builder_->BlockOffsetAdjustmentForFragmentainer(
fragmentainer_consumed_block_size_);
- container_builder_->PropagateOOFPositionedInfo(
- result->PhysicalFragment(), oof_offset, relative_offset,
- offset_adjustment,
- /* inline_container */ nullptr, containing_block_adjustment,
- &descendant.node_info.fixedpos_containing_block,
- additional_fixedpos_offset);
+ if (NeedsOOFPositionedInfoPropagation(result->PhysicalFragment())) {
+ container_builder_->PropagateOOFPositionedInfo(
+ result->PhysicalFragment(), oof_offset, relative_offset,
+ offset_adjustment,
+ /* inline_container */ nullptr, containing_block_adjustment,
+ &descendant.node_info.fixedpos_containing_block,
+ additional_fixedpos_offset);
+ }
algorithm->AppendOutOfFlowResult(result);
const auto& physical_fragment =
@@ -1359,15 +1625,19 @@ void NGOutOfFlowLayoutPart::ReplaceFragmentainer(
const NGPhysicalFragment* new_fragment = &new_result->PhysicalFragment();
container_builder_->ReplaceChild(index, *new_fragment, offset);
- if (multicol_children_) {
+ if (multicol_children_ && index < multicol_children_->size()) {
// We are in a nested fragmentation context. Replace the column entry
- // and break token directly in the existing multicol fragment.;
+ // (that already existed) and break token directly in the existing
+ // multicol fragment. If there any new columns, they will be appended as
+ // part of regenerating the multicol fragment.
MulticolChildInfo& column_info = (*multicol_children_)[index];
if (auto* parent_break_token = column_info.parent_break_token) {
DCHECK_GT(parent_break_token->ChildBreakTokens().size(), 0u);
parent_break_token->GetMutableForOutOfFlow().ReplaceChildBreakToken(
new_fragment->BreakToken(),
- parent_break_token->ChildBreakTokens().size() - 1);
+ base::checked_cast<wtf_size_t>(
+ parent_break_token->ChildBreakTokens().size()) -
+ 1);
}
column_info.mutable_link->fragment->Release();
new (&column_info.mutable_link->fragment)
@@ -1437,7 +1707,7 @@ NGConstraintSpace NGOutOfFlowLayoutPart::GetFragmentainerConstraintSpace(
// If we are a new fragment and are separated from other columns by a
// spanner, compute the correct column block size to use.
- if (is_new_fragment && !multicol_children_ && index != num_children - 1 &&
+ if (is_new_fragment && index != num_children - 1 &&
original_column_block_size_ != kIndefiniteSize &&
!container_builder_->Children()[index + 1]
.fragment->IsFragmentainerBox()) {
@@ -1459,25 +1729,9 @@ NGConstraintSpace NGOutOfFlowLayoutPart::GetFragmentainerConstraintSpace(
/* balance_columns */ false);
}
-const NGBlockBreakToken* NGOutOfFlowLayoutPart::PreviousFragmentainerBreakToken(
- wtf_size_t index) const {
- const NGBlockBreakToken* previous_break_token = nullptr;
- for (wtf_size_t i = index; i > 0; --i) {
- auto* previous_fragment =
- container_builder_->Children()[i - 1].fragment.get();
- if (previous_fragment->IsFragmentainerBox()) {
- previous_break_token = To<NGBlockBreakToken>(
- To<NGPhysicalBoxFragment>(previous_fragment)->BreakToken());
- break;
- }
- }
- return previous_break_token;
-}
-
// Compute in which fragmentainer the OOF element will start its layout and
// position the offset relative to that fragmentainer.
void NGOutOfFlowLayoutPart::ComputeStartFragmentIndexAndRelativeOffset(
- const ContainingBlockInfo& container_info,
WritingMode default_writing_mode,
LayoutUnit block_estimate,
wtf_size_t* start_index,
@@ -1524,7 +1778,7 @@ void NGOutOfFlowLayoutPart::ComputeStartFragmentIndexAndRelativeOffset(
// If we are a new fragment and are separated from other columns by a
// spanner, compute the correct fragmentainer_block_size.
- if (!multicol_children_ && original_column_block_size_ != kIndefiniteSize &&
+ if (original_column_block_size_ != kIndefiniteSize &&
!container_builder_->Children()[child_index - 1]
.fragment->IsFragmentainerBox()) {
fragmentainer_block_size =
@@ -1541,6 +1795,30 @@ void NGOutOfFlowLayoutPart::ComputeStartFragmentIndexAndRelativeOffset(
additional_fragment_count * fragmentainer_block_size;
}
+void NGOutOfFlowLayoutPart::ReplaceFragment(
+ scoped_refptr<const NGLayoutResult> new_result,
+ const NGPhysicalBoxFragment& old_fragment,
+ wtf_size_t index) {
+ // Replace the LayoutBox entry.
+ LayoutBox& box = *old_fragment.MutableOwnerLayoutBox();
+ box.ReplaceLayoutResult(new_result, index);
+
+ // Replace the entry in the parent fragment.
+ const LayoutBlock& containing_block = *box.ContainingBlock();
+ for (const auto& parent_fragment : containing_block.PhysicalFragments()) {
+ for (NGLink& child_link :
+ parent_fragment.GetMutableChildrenForOutOfFlow().Children()) {
+ if (child_link.fragment == &old_fragment) {
+ child_link.fragment->Release();
+ child_link.fragment = &new_result->PhysicalFragment();
+ child_link.fragment->AddRef();
+ return;
+ }
+ }
+ }
+ NOTREACHED();
+}
+
void NGOutOfFlowLayoutPart::SaveStaticPositionOnPaintLayer(
LayoutBox* layout_box,
const NGLogicalStaticPosition& position) const {
@@ -1560,7 +1838,7 @@ NGLogicalStaticPosition NGOutOfFlowLayoutPart::ToStaticPositionForLegacy(
// Legacy expects the static position to include the block contribution from
// previous columns.
if (const auto* break_token = container_builder_->PreviousBreakToken())
- position.offset.block_offset += break_token->ConsumedBlockSize();
+ position.offset.block_offset += break_token->ConsumedBlockSizeForLegacy();
return position;
}
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 7aebd00478c..a70e5a5e9d6 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/inline_containing_block_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.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"
@@ -55,6 +56,7 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
NGOutOfFlowLayoutPart(
bool is_absolute_container,
bool is_fixed_container,
+ bool is_grid_container,
const ComputedStyle& container_style,
const NGConstraintSpace& container_space,
NGBoxFragmentBuilder* container_builder,
@@ -69,6 +71,9 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
// LayoutResult::OutOfFlowPositionedDescendants.
void Run(const LayoutBox* only_layout = nullptr);
+ // Handle the layout of any OOF elements in a fragmentation context.
+ void HandleFragmentation();
+
private:
// Information needed to position descendant within a containing block.
// Geometry expressed here is complicated:
@@ -176,8 +181,6 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
// The physical fragment of the containing block used when laying out a
// fragmentainer descendant. This is the containing block as defined by the
// spec: https://www.w3.org/TR/css-position-3/#absolute-cb.
- // TODO(almaher): Ensure that this is correct in the case of an inline
- // ancestor.
scoped_refptr<const NGPhysicalFragment> containing_block_fragment = nullptr;
};
@@ -188,6 +191,20 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
void ComputeInlineContainingBlocks(
const Vector<NGLogicalOutOfFlowPositionedNode>&);
+ void ComputeInlineContainingBlocksForFragmentainer(
+ const Vector<NGLogicalOutOfFlowPositionedNode>&);
+ // |containing_block_relative_offset| is the accumulated relative offset from
+ // the inline's containing block to the fragmentation context root.
+ // |containing_block_offset| is the offset of the inline's containing block
+ // relative to the fragmentation context root (not including any offset from
+ // relative positioning).
+ void AddInlineContainingBlockInfo(
+ const InlineContainingBlockUtils::InlineContainingBlockMap&,
+ const WritingDirectionMode container_writing_direction,
+ PhysicalSize container_builder_size,
+ LogicalOffset containing_block_relative_offset = LogicalOffset(),
+ LogicalOffset containing_block_offset = LogicalOffset(),
+ bool adjust_for_fragmentation = false);
void LayoutCandidates(Vector<NGLogicalOutOfFlowPositionedNode>* candidates,
const LayoutBox* only_layout,
@@ -210,7 +227,7 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
NodeInfo SetupNodeInfo(const NGLogicalOutOfFlowPositionedNode& oof_node);
scoped_refptr<const NGLayoutResult> LayoutOOFNode(
- const NodeToLayout& oof_node_to_layout,
+ NodeToLayout& oof_node_to_layout,
const LayoutBox* only_layout,
const NGConstraintSpace* fragmentainer_constraint_space = nullptr);
@@ -245,15 +262,12 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
// |fragmented_descendants| is also an output variable in that any OOF that
// has not finished layout in the current pass will be added back to
// |fragmented_descendants| to continue layout in the next fragmentainer.
- void LayoutOOFsInFragmentainer(
- const Vector<NodeToLayout>& pending_descendants,
- wtf_size_t index,
- LayoutUnit column_inline_progression,
- Vector<NodeToLayout>* fragmented_descendants);
- void AddOOFToFragmentainer(const NodeToLayout& descendant,
+ void LayoutOOFsInFragmentainer(Vector<NodeToLayout>& pending_descendants,
+ wtf_size_t index,
+ LayoutUnit column_inline_progression,
+ Vector<NodeToLayout>* fragmented_descendants);
+ void AddOOFToFragmentainer(NodeToLayout& descendant,
const NGConstraintSpace* fragmentainer_space,
- LayoutUnit additional_inline_offset,
- bool add_to_last_fragment,
LogicalOffset fragmentainer_offset,
wtf_size_t index,
NGSimplifiedOOFLayoutAlgorithm* algorithm,
@@ -267,15 +281,16 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
LayoutUnit column_inline_progression,
bool create_new_fragment);
NGConstraintSpace GetFragmentainerConstraintSpace(wtf_size_t index);
- const NGBlockBreakToken* PreviousFragmentainerBreakToken(
- wtf_size_t index) const;
void ComputeStartFragmentIndexAndRelativeOffset(
- const ContainingBlockInfo& container_info,
WritingMode default_writing_mode,
LayoutUnit block_estimate,
wtf_size_t* start_index,
LogicalOffset* offset) const;
+ static void ReplaceFragment(scoped_refptr<const NGLayoutResult> new_result,
+ const NGPhysicalBoxFragment& old_fragment,
+ wtf_size_t index);
+
// This saves the static-position for an OOF-positioned object into its
// paint-layer.
void SaveStaticPositionOnPaintLayer(
@@ -291,6 +306,10 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
const WritingMode writing_mode_;
const WritingDirectionMode default_writing_direction_;
+ // Out-of-flow positioned nodes that we should lay out at a later time. For
+ // example, if the containing block has not finished layout.
+ Vector<NGLogicalOutOfFlowPositionedNode> delayed_descendants_;
+
// Holds the children of an inner multicol if we are laying out OOF elements
// inside a nested fragmentation context.
Vector<MulticolChildInfo>* multicol_children_;
@@ -305,7 +324,6 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
bool is_fixed_container_ = false;
bool allow_first_tier_oof_cache_ = false;
bool has_block_fragmentation_ = false;
- bool can_traverse_fragments_ = false;
// A fixedpos containing block was found in an outer fragmentation context.
bool outer_context_has_fixedpos_container_ = false;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
index 9f05260f5ae..48e7bbcc5de 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.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_test.h"
@@ -1022,25 +1023,17 @@ TEST_F(NGOutOfFlowLayoutPartTest,
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x40
offset:0,0 size:1000x40
- offset:0,0 size:492x10
- offset:0,0 size:30x10
- offset:0,0 size:30x10
- offset:0,0 size:5x10
- offset:508,0 size:492x10
- offset:0,0 size:30x10
- offset:0,0 size:30x10
- offset:0,0 size:5x10
- offset:0,10 size:1000x0
- offset:0,10 size:1000x0
- offset:0,10 size:1000x0
- offset:0,10 size:492x30
- offset:0,0 size:5x30
- offset:508,10 size:492x30
- offset:0,0 size:5x30
- offset:1016,10 size:492x30
- offset:0,0 size:5x30
- offset:1524,10 size:492x30
- offset:0,0 size:5x10
+ offset:0,0 size:492x40
+ offset:0,0 size:30x20
+ offset:0,0 size:30x20
+ offset:0,0 size:5x40
+ offset:508,0 size:492x40
+ offset:0,0 size:5x40
+ offset:1016,0 size:492x40
+ offset:0,0 size:5x40
+ offset:0,40 size:1000x0
+ offset:0,40 size:1000x0
+ offset:0,40 size:1000x0
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1079,17 +1072,13 @@ TEST_F(NGOutOfFlowLayoutPartTest,
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x40
offset:0,0 size:1000x40
- offset:0,0 size:492x10
- offset:0,0 size:30x10
- offset:0,0 size:30x10
- offset:508,0 size:492x10
- offset:0,0 size:30x10
- offset:0,0 size:30x10
- offset:0,10 size:1000x0
- offset:0,10 size:492x30
- offset:0,5 size:5x25
- offset:508,10 size:492x30
- offset:0,0 size:5x25
+ offset:0,0 size:492x37.5
+ offset:0,0 size:30x20
+ offset:0,0 size:30x20
+ offset:0,25 size:5x12.5
+ offset:508,0 size:492x37.5
+ offset:0,0 size:5x37.5
+ offset:0,37.5 size:1000x0
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1126,20 +1115,16 @@ TEST_F(NGOutOfFlowLayoutPartTest,
String dump = DumpFragmentTree(GetElementById("container"));
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
- offset:unplaced size:1000x0
- offset:0,0 size:1000x0
- offset:0,0 size:492x0
+ offset:unplaced size:1000x2
+ offset:0,0 size:1000x2
+ offset:0,0 size:492x2
offset:0,0 size:30x0
- offset:0,0 size:5x1
- offset:0,0 size:1000x0
- offset:0,0 size:1000x0
- offset:0,0 size:1000x0
- offset:0,0 size:492x0
- offset:0,0 size:5x1
- offset:508,0 size:492x0
- offset:0,0 size:5x1
- offset:1016,0 size:492x0
- offset:0,0 size:5x1
+ offset:0,0 size:5x2
+ offset:508,0 size:492x2
+ offset:0,0 size:5x2
+ offset:0,2 size:1000x0
+ offset:0,2 size:1000x0
+ offset:0,2 size:1000x0
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1177,20 +1162,18 @@ TEST_F(NGOutOfFlowLayoutPartTest, AbsposFragWithSpannerAndNewEmptyColumns) {
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x40
offset:0,0 size:1000x40
- offset:0,0 size:492x0
- offset:0,0 size:30x0
- offset:0,0 size:1000x0
- offset:0,0 size:1000x0
- offset:0,0 size:1000x0
offset:0,0 size:492x40
+ offset:0,0 size:30x0
offset:508,0 size:492x40
- offset:0,39 size:5x1
offset:1016,0 size:492x40
offset:0,0 size:5x40
offset:1524,0 size:492x40
offset:0,0 size:5x40
offset:2032,0 size:492x40
- offset:0,0 size:5x39
+ offset:0,0 size:5x40
+ offset:0,40 size:1000x0
+ offset:0,40 size:1000x0
+ offset:0,40 size:1000x0
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1228,17 +1211,12 @@ TEST_F(NGOutOfFlowLayoutPartTest, AbsposFragmentationPctResolution) {
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x40
offset:0,0 size:1000x40
- offset:0,0 size:492x15
- offset:0,0 size:30x15
- offset:0,0 size:10x15
- offset:508,0 size:492x15
- offset:0,0 size:30x15
- offset:0,0 size:10x15
- offset:0,15 size:1000x10
- offset:0,25 size:492x15
- offset:0,0 size:5x15
- offset:508,25 size:492x15
- offset:0,0 size:5x15
+ offset:0,0 size:492x30
+ offset:0,0 size:30x30
+ offset:0,0 size:10x30
+ offset:508,0 size:492x30
+ offset:0,0 size:5x30
+ offset:0,30 size:1000x10
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1382,23 +1360,22 @@ TEST_F(NGOutOfFlowLayoutPartTest, AbsposNestedFragmentationNewColumns) {
)HTML");
String dump = DumpFragmentTree(GetElementById("container"));
+ // Note that it's not obvious that the block-size of the last inner
+ // fragmentainer (after the spanners) is correct; see crbug.com/1224337
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x100
offset:0,0 size:1000x100
offset:0,0 size:500x100
offset:0,0 size:40x40
offset:0,40 size:500x60
- offset:10,10 size:232x10
- offset:0,0 size:55x10
- offset:0,0 size:5x10
- offset:258,10 size:232x10
- offset:0,0 size:55x10
- offset:0,0 size:5x10
- offset:248,0 size:5x10
- offset:496,0 size:5x10
- offset:10,20 size:480x0
- offset:10,20 size:480x0
- offset:10,20 size:480x0
+ offset:10,10 size:232x20
+ offset:0,0 size:55x20
+ offset:0,0 size:5x20
+ offset:10,30 size:480x0
+ offset:10,30 size:480x0
+ offset:10,30 size:480x0
+ offset:10,30 size:232x40
+ offset:0,0 size:5x20
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1435,22 +1412,25 @@ TEST_F(NGOutOfFlowLayoutPartTest, AbsposNestedFragmentationNewEmptyColumns) {
)HTML");
String dump = DumpFragmentTree(GetElementById("container"));
+ // Note that it's not obvious that the block-size of the last inner
+ // fragmentainers (after the spanners) are correct; see crbug.com/1224337
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x100
offset:0,0 size:1000x100
offset:0,0 size:500x100
offset:0,0 size:40x40
- offset:0,40 size:500x40
- offset:0,0 size:242x40
- offset:0,0 size:55x40
- offset:258,0 size:242x40
- offset:0,0 size:55x40
- offset:516,0 size:5x40
- offset:774,0 size:5x40
- offset:1032,0 size:5x40
- offset:0,40 size:500x0
- offset:0,40 size:500x0
- offset:0,40 size:500x0
+ offset:0,40 size:500x60
+ offset:0,0 size:242x60
+ offset:0,0 size:55x60
+ offset:258,0 size:242x60
+ offset:0,0 size:55x20
+ offset:0,60 size:500x0
+ offset:0,60 size:500x0
+ offset:0,60 size:500x0
+ offset:0,60 size:242x60
+ offset:0,0 size:5x60
+ offset:258,60 size:242x60
+ offset:0,0 size:5x60
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -1501,5 +1481,415 @@ TEST_F(NGOutOfFlowLayoutPartTest,
)DUMP";
EXPECT_EQ(expectation, dump);
}
+
+// Tests an OOF element with an inline containing block inside a multicol
+// with a column spanner.
+TEST_F(NGOutOfFlowLayoutPartTest, AbsposFragWithInlineCBAndSpanner) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ #multicol {
+ column-count:2; column-fill:auto; column-gap:16px; height:40px;
+ }
+ .rel {
+ position: relative; width:30px;
+ }
+ .abs {
+ position:absolute; top:80px; width:5px; height:120px;
+ }
+ </style>
+ <div id="container">
+ <div id="multicol">
+ <div>
+ <span class="rel">
+ <div class="abs"></div>
+ </span>
+ </div>
+ <div style="column-span:all;"></div>
+ <div style="column-span:all;"></div>
+ <div style="column-span:all;"></div>
+ </div>
+ </div>
+ )HTML");
+ String dump = DumpFragmentTree(GetElementById("container"));
+
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x40
+ offset:0,0 size:1000x40
+ offset:0,0 size:492x40
+ offset:0,0 size:492x0
+ offset:0,0 size:0x0
+ offset:508,0 size:492x40
+ offset:1016,0 size:492x40
+ offset:0,0 size:5x40
+ offset:1524,0 size:492x40
+ offset:0,0 size:5x40
+ offset:2032,0 size:492x40
+ offset:0,0 size:5x40
+ offset:0,40 size:1000x0
+ offset:0,40 size:1000x0
+ offset:0,40 size:1000x0
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGOutOfFlowLayoutPartTest, PositionedObjectsInMulticol) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ .multicol {
+ column-count: 2; column-fill: auto; column-gap: 0px;
+ }
+ </style>
+ <div class="multicol" id="outer">
+ <div class="multicol" id="inner" style="position:relative;">
+ <div id="abs1" style="position:absolute;"></div>
+ <div id="rel" style="position:relative;">
+ <div id="abs2" style="position:absolute;"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+ Element* outer_multicol = GetDocument().getElementById("outer");
+ auto* multicol = To<LayoutBlockFlow>(outer_multicol->GetLayoutObject());
+ EXPECT_FALSE(multicol->PositionedObjects());
+
+ Element* inner_multicol = GetDocument().getElementById("inner");
+ multicol = To<LayoutBlockFlow>(inner_multicol->GetLayoutObject());
+ auto* abs = GetLayoutBoxByElementId("abs1");
+ EXPECT_TRUE(multicol->PositionedObjects()->Contains(abs));
+ EXPECT_EQ(multicol->PositionedObjects()->size(), 1u);
+
+ Element* rel_element = GetDocument().getElementById("rel");
+ auto* rel = To<LayoutBlockFlow>(rel_element->GetLayoutObject());
+ abs = GetLayoutBoxByElementId("abs2");
+ EXPECT_TRUE(rel->PositionedObjects()->Contains(abs));
+ EXPECT_EQ(rel->PositionedObjects()->size(), 1u);
+}
+
+TEST_F(NGOutOfFlowLayoutPartTest, PositionedObjectsInMulticolWithInline) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ #multicol {
+ column-count: 2; column-fill: auto; column-gap: 0px;
+ }
+ </style>
+ <div id="multicol">
+ <div id="target">
+ <span style="position: relative;">
+ <div id="abs1" style="position:absolute;"></div>
+ <div id="abs2" style="position:absolute;"></div>
+ </span>
+ </div>
+ </div>
+ )HTML");
+ Element* multicol_element = GetDocument().getElementById("multicol");
+ auto* multicol = To<LayoutBlockFlow>(multicol_element->GetLayoutObject());
+ EXPECT_FALSE(multicol->PositionedObjects());
+
+ Element* target_element = GetDocument().getElementById("target");
+ auto* target = To<LayoutBlockFlow>(target_element->GetLayoutObject());
+ auto* abs1 = GetLayoutBoxByElementId("abs1");
+ auto* abs2 = GetLayoutBoxByElementId("abs2");
+ EXPECT_TRUE(target->PositionedObjects()->Contains(abs1));
+ EXPECT_TRUE(target->PositionedObjects()->Contains(abs2));
+ EXPECT_EQ(target->PositionedObjects()->size(), 2u);
+}
+
+// Make sure the fragmentainer break tokens are correct when OOFs are added to
+// existing fragmentainers.
+TEST_F(NGOutOfFlowLayoutPartTest, FragmentainerBreakTokens) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ #multicol {
+ column-count:2; column-fill:auto; column-gap:0px;
+ height:150px; width:100px;
+ }
+ .abs {
+ position:absolute; width:50px; height:200px; top:0;
+ }
+ </style>
+ <div id="multicol">
+ <div style="position:relative;">
+ <div style="height:200px;"></div>
+ <div class="abs"></div>
+ <div style="column-span:all;"></div>
+ <div style="height:100px;"></div>
+ </div>
+ </div>
+ )HTML");
+ const LayoutBox* multicol = GetLayoutBoxByElementId("multicol");
+ ASSERT_EQ(multicol->PhysicalFragmentCount(), 1u);
+ const NGPhysicalBoxFragment* multicol_fragment =
+ multicol->GetPhysicalFragment(0);
+ const auto& children = multicol_fragment->Children();
+ ASSERT_EQ(children.size(), 5u);
+
+ const auto& column1 = To<NGPhysicalBoxFragment>(*children[0]);
+ const NGBlockBreakToken* break_token =
+ To<NGBlockBreakToken>(column1.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 0u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 100);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 2u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column2 = To<NGPhysicalBoxFragment>(*children[1]);
+ break_token = To<NGBlockBreakToken>(column2.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 1u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 200);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_TRUE(break_token->IsCausedByColumnSpanner());
+
+ const auto& spanner = To<NGPhysicalBoxFragment>(*children[2]);
+ EXPECT_TRUE(spanner.IsColumnSpanAll());
+
+ const auto& column3 = To<NGPhysicalBoxFragment>(*children[3]);
+ break_token = To<NGBlockBreakToken>(column3.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 2u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 250);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column4 = To<NGPhysicalBoxFragment>(*children[4]);
+ EXPECT_FALSE(column4.BreakToken());
+}
+
+// Make sure the fragmentainer break tokens are correct when new fragmentainers
+// are created as a result of an OOF.
+TEST_F(NGOutOfFlowLayoutPartTest, NewFragmentainerBreakTokens) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ #multicol {
+ column-count:2; column-fill:auto; column-gap:0px;
+ height:100px; width:100px;
+ }
+ .abs {
+ position:absolute; width:50px; height:200px;
+ }
+ </style>
+ <div id="multicol">
+ <div style="position:relative;">
+ <div style="height:200px;"></div>
+ <div class="abs"></div>
+ </div>
+ </div>
+ )HTML");
+ const LayoutBox* multicol = GetLayoutBoxByElementId("multicol");
+ ASSERT_EQ(multicol->PhysicalFragmentCount(), 1u);
+ const NGPhysicalBoxFragment* multicol_fragment =
+ multicol->GetPhysicalFragment(0);
+ const auto& children = multicol_fragment->Children();
+ ASSERT_EQ(children.size(), 4u);
+
+ const auto& column1 = To<NGPhysicalBoxFragment>(*children[0]);
+ const NGBlockBreakToken* break_token =
+ To<NGBlockBreakToken>(column1.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 0u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 100);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column2 = To<NGPhysicalBoxFragment>(*children[1]);
+ break_token = To<NGBlockBreakToken>(column2.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 1u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 200);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 0u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column3 = To<NGPhysicalBoxFragment>(*children[2]);
+ break_token = To<NGBlockBreakToken>(column3.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 2u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 300);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column4 = To<NGPhysicalBoxFragment>(*children[3]);
+ EXPECT_FALSE(column4.BreakToken());
+}
+
+// Make sure the fragmentainer break tokens are correct when new empty
+// fragmentainers are created as a result of an OOF.
+TEST_F(NGOutOfFlowLayoutPartTest, NewEmptyFragmentainerBreakTokens) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ #multicol {
+ column-count:2; column-fill:auto; column-gap:0px;
+ height:100px; width:100px;
+ }
+ .abs {
+ position:absolute; width:50px; height:200px; top:200px;
+ }
+ </style>
+ <div id="multicol">
+ <div style="position:relative;">
+ <div style="height:100px;"></div>
+ <div class="abs"></div>
+ </div>
+ </div>
+ )HTML");
+ const LayoutBox* multicol = GetLayoutBoxByElementId("multicol");
+ ASSERT_EQ(multicol->PhysicalFragmentCount(), 1u);
+ const NGPhysicalBoxFragment* multicol_fragment =
+ multicol->GetPhysicalFragment(0);
+ const auto& children = multicol_fragment->Children();
+ ASSERT_EQ(children.size(), 4u);
+
+ const auto& column1 = To<NGPhysicalBoxFragment>(*children[0]);
+ const NGBlockBreakToken* break_token =
+ To<NGBlockBreakToken>(column1.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 0u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 100);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 0u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column2 = To<NGPhysicalBoxFragment>(*children[1]);
+ break_token = To<NGBlockBreakToken>(column2.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 1u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 200);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 0u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column3 = To<NGPhysicalBoxFragment>(*children[2]);
+ break_token = To<NGBlockBreakToken>(column3.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 2u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 300);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column4 = To<NGPhysicalBoxFragment>(*children[3]);
+ EXPECT_FALSE(column4.BreakToken());
+}
+
+// Make sure the fragmentainer break tokens are correct when new fragmentainers
+// are created as a result of an OOF in a nested multicol.
+TEST_F(NGOutOfFlowLayoutPartTest, NewFragmentainerBreakTokensInNestedMulticol) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ .multicol {
+ column-count:2; column-fill:auto; column-gap:0px;
+ }
+ .abs {
+ position:absolute; width:50px; height:400px; top:0;
+ }
+ </style>
+ <div class="multicol" id="outer">
+ <div class="multicol" id="inner">
+ <div style="position:relative;">
+ <div style="height:200px;"></div>
+ <div class="abs"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+ const LayoutBox* multicol = GetLayoutBoxByElementId("inner");
+ ASSERT_EQ(multicol->PhysicalFragmentCount(), 1u);
+ const NGPhysicalBoxFragment* multicol_fragment =
+ multicol->GetPhysicalFragment(0);
+ const auto& children = multicol_fragment->Children();
+ ASSERT_EQ(children.size(), 4u);
+
+ const auto& column1 = To<NGPhysicalBoxFragment>(*children[0]);
+ const NGBlockBreakToken* break_token =
+ To<NGBlockBreakToken>(column1.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 0u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 100);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 2u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column2 = To<NGPhysicalBoxFragment>(*children[1]);
+ break_token = To<NGBlockBreakToken>(column2.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 1u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 200);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column3 = To<NGPhysicalBoxFragment>(*children[2]);
+ break_token = To<NGBlockBreakToken>(column3.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 2u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 300);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column4 = To<NGPhysicalBoxFragment>(*children[3]);
+ EXPECT_FALSE(column4.BreakToken());
+}
+
+// Make sure the fragmentainer break tokens are correct when a new column is
+// created before a spanner for an OOF.
+TEST_F(NGOutOfFlowLayoutPartTest, FragmentainerBreakTokenBeforeSpanner) {
+ SetBodyInnerHTML(
+ R"HTML(
+ <style>
+ #multicol {
+ column-count:2; column-fill:auto; column-gap:0px; width:100px;
+ }
+ .abs {
+ position:absolute; width:50px; height:200px; top:0;
+ }
+ </style>
+ <div id="multicol">
+ <div style="position:relative;">
+ <div style="height:100px;"></div>
+ <div class="abs"></div>
+ </div>
+ <div style="column-span:all;"></div>
+ <div style="height:100px;"></div>
+ </div>
+ )HTML");
+ const LayoutBox* multicol = GetLayoutBoxByElementId("multicol");
+ ASSERT_EQ(multicol->PhysicalFragmentCount(), 1u);
+ const NGPhysicalBoxFragment* multicol_fragment =
+ multicol->GetPhysicalFragment(0);
+ const auto& children = multicol_fragment->Children();
+ ASSERT_EQ(children.size(), 5u);
+
+ const auto& column1 = To<NGPhysicalBoxFragment>(*children[0]);
+ const NGBlockBreakToken* break_token =
+ To<NGBlockBreakToken>(column1.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 0u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 100);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 2u);
+ EXPECT_TRUE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column2 = To<NGPhysicalBoxFragment>(*children[1]);
+ break_token = To<NGBlockBreakToken>(column2.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 1u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 200);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_TRUE(break_token->IsCausedByColumnSpanner());
+
+ const auto& spanner = To<NGPhysicalBoxFragment>(*children[2]);
+ EXPECT_TRUE(spanner.IsColumnSpanAll());
+
+ const auto& column3 = To<NGPhysicalBoxFragment>(*children[3]);
+ break_token = To<NGBlockBreakToken>(column3.BreakToken());
+ EXPECT_TRUE(break_token);
+ EXPECT_EQ(break_token->SequenceNumber(), 2u);
+ EXPECT_EQ(break_token->ConsumedBlockSize(), 250);
+ EXPECT_EQ(break_token->ChildBreakTokens().size(), 1u);
+ EXPECT_FALSE(break_token->IsCausedByColumnSpanner());
+
+ const auto& column4 = To<NGPhysicalBoxFragment>(*children[4]);
+ EXPECT_FALSE(column4.BreakToken());
+}
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
index f13f588f222..aad6ba017a4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
@@ -42,6 +43,25 @@ struct NGContainingBlock {
fragment(std::move(fragment)) {}
};
+// This holds the containing block for an out-of-flow positioned element
+// if the containing block is a non-atomic inline. It is the continuation
+// root (i.e. the first LayoutInline in the continuation chain for the same
+// node) if continuations are involved.
+template <typename OffsetType>
+struct NGInlineContainer {
+ DISALLOW_NEW();
+
+ public:
+ const LayoutInline* container = nullptr;
+ // Store the relative offset so that it can be applied after fragmentation,
+ // if inside a fragmentation context.
+ OffsetType relative_offset;
+
+ NGInlineContainer() = default;
+ NGInlineContainer(const LayoutInline* container, OffsetType relative_offset)
+ : container(container), relative_offset(relative_offset) {}
+};
+
// If an out-of-flow positioned element is inside a nested fragmentation
// context, it will be laid out once it reaches the outermost fragmentation
// context root. A multicol with pending OOFs is the inner multicol information
@@ -95,21 +115,22 @@ struct CORE_EXPORT NGPhysicalOutOfFlowPositionedNode {
unsigned static_position_vertical_edge : 2;
// Whether or not this is an NGPhysicalOOFNodeForFragmentation.
unsigned is_for_fragmentation : 1;
- // Continuation root of the optional inline container.
- const LayoutInline* inline_container;
+ NGInlineContainer<PhysicalOffset> inline_container;
NGPhysicalOutOfFlowPositionedNode(
NGBlockNode node,
NGPhysicalStaticPosition static_position,
- const LayoutInline* inline_container = nullptr)
+ NGInlineContainer<PhysicalOffset> inline_container =
+ NGInlineContainer<PhysicalOffset>())
: box(node.GetLayoutBox()),
static_position(static_position.offset),
static_position_horizontal_edge(static_position.horizontal_edge),
static_position_vertical_edge(static_position.vertical_edge),
is_for_fragmentation(false),
inline_container(inline_container) {
- DCHECK(!inline_container ||
- inline_container == inline_container->ContinuationRoot());
+ DCHECK(!inline_container.container ||
+ inline_container.container ==
+ inline_container.container->ContinuationRoot());
DCHECK(node.IsBlock());
}
@@ -154,7 +175,8 @@ struct CORE_EXPORT NGPhysicalOOFNodeForFragmentation final
NGPhysicalOOFNodeForFragmentation(
NGBlockNode node,
NGPhysicalStaticPosition static_position,
- const LayoutInline* inline_container = nullptr,
+ NGInlineContainer<PhysicalOffset> inline_container =
+ NGInlineContainer<PhysicalOffset>(),
NGContainingBlock<PhysicalOffset> containing_block =
NGContainingBlock<PhysicalOffset>(),
NGContainingBlock<PhysicalOffset> fixedpos_containing_block =
@@ -180,33 +202,31 @@ struct NGLogicalOutOfFlowPositionedNode final {
public:
LayoutBox* box;
NGLogicalStaticPosition static_position;
- // Continuation root of the optional inline container.
- const LayoutInline* inline_container;
+ NGInlineContainer<LogicalOffset> inline_container;
bool needs_block_offset_adjustment;
const LayoutUnit fragmentainer_consumed_block_size;
NGContainingBlock<LogicalOffset> containing_block;
NGContainingBlock<LogicalOffset> fixedpos_containing_block;
- absl::optional<LogicalRect> containing_block_rect;
NGLogicalOutOfFlowPositionedNode(
NGBlockNode node,
NGLogicalStaticPosition static_position,
- const LayoutInline* inline_container = nullptr,
+ NGInlineContainer<LogicalOffset> inline_container =
+ NGInlineContainer<LogicalOffset>(),
bool needs_block_offset_adjustment = false,
NGContainingBlock<LogicalOffset> containing_block =
NGContainingBlock<LogicalOffset>(),
NGContainingBlock<LogicalOffset> fixedpos_containing_block =
- NGContainingBlock<LogicalOffset>(),
- const absl::optional<LogicalRect> containing_block_rect = absl::nullopt)
+ NGContainingBlock<LogicalOffset>())
: box(node.GetLayoutBox()),
static_position(static_position),
inline_container(inline_container),
needs_block_offset_adjustment(needs_block_offset_adjustment),
containing_block(containing_block),
- fixedpos_containing_block(fixedpos_containing_block),
- containing_block_rect(containing_block_rect) {
- DCHECK(!inline_container ||
- inline_container == inline_container->ContinuationRoot());
+ fixedpos_containing_block(fixedpos_containing_block) {
+ DCHECK(!inline_container.container ||
+ inline_container.container ==
+ inline_container.container->ContinuationRoot());
DCHECK(node.IsBlock());
}
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 fa7d6b8f41f..e6f4154b1c4 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
@@ -83,7 +83,7 @@ NGConstraintSpace NGPageLayoutAlgorithm::CreateConstraintSpaceForPages(
ConstraintSpace(), Style().GetWritingDirection(), /* is_new_fc */ true);
space_builder.SetAvailableSize(page_size);
space_builder.SetPercentageResolutionSize(page_size);
- space_builder.SetStretchInlineSizeIfAuto(true);
+ space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
// TODO(mstensho): Handle auto block size.
space_builder.SetFragmentationType(kFragmentPage);
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 e7246a22e2a..3852b0e6bba 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
@@ -13,12 +13,14 @@
#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/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h"
#include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
@@ -26,6 +28,10 @@
namespace blink {
+#if DCHECK_IS_ON()
+unsigned NGPhysicalBoxFragment::AllowPostLayoutScope::allow_count_ = 0;
+#endif
+
namespace {
struct SameSizeAsNGPhysicalBoxFragment : NGPhysicalFragment {
@@ -46,24 +52,16 @@ bool HasControlClip(const NGPhysicalBoxFragment& self) {
bool ShouldUsePositionForPointInBlockFlowDirection(
const LayoutObject& layout_object) {
- const LayoutBlock* const layout_block = DynamicTo<LayoutBlock>(layout_object);
- if (!layout_block)
- return false;
- if (layout_block->IsTableRow()) {
- // See editing/selection/click-before-and-after-table.html
+ const LayoutBlockFlow* const layout_block_flow =
+ DynamicTo<LayoutBlockFlow>(layout_object);
+ if (!layout_block_flow) {
+ // For <tr>, see editing/selection/click-before-and-after-table.html
return false;
}
- if (layout_block->StyleRef().SpecifiesColumns()) {
+ if (layout_block_flow->StyleRef().SpecifiesColumns()) {
// Columns are laid out in inline direction.
return false;
}
- if (layout_block->IsTable())
- return false;
- // Note: For legacy layout compatibility, we find child by using
- // |PositionForPointInBlockFlowDirection()| for flex and grid.
- // TODO(yosin): We should have specific functions for flex and grid instead
- // of using |PositionForPointInBlockFlowDirection()|,
- // e.g. "flex-direction:row" layouts children horizontally.
return true;
}
@@ -91,20 +89,27 @@ void ApplyOverflowClip(OverflowClipAxes overflow_clip_axes,
NGContainingBlock<PhysicalOffset> PhysicalContainingBlock(
NGBoxFragmentBuilder* builder,
- PhysicalSize size,
+ PhysicalSize outer_size,
+ PhysicalSize inner_size,
const NGContainingBlock<LogicalOffset>& containing_block) {
return NGContainingBlock<PhysicalOffset>(
containing_block.offset.ConvertToPhysical(
- builder->Style().GetWritingDirection(), size,
- containing_block.fragment ? containing_block.fragment->Size()
- : PhysicalSize()),
+ builder->Style().GetWritingDirection(), outer_size, inner_size),
containing_block.relative_offset.ConvertToPhysical(
- builder->Style().GetWritingDirection(), size,
- containing_block.fragment ? containing_block.fragment->Size()
- : PhysicalSize()),
+ builder->Style().GetWritingDirection(), outer_size, inner_size),
containing_block.fragment);
}
+NGContainingBlock<PhysicalOffset> PhysicalContainingBlock(
+ NGBoxFragmentBuilder* builder,
+ PhysicalSize size,
+ const NGContainingBlock<LogicalOffset>& containing_block) {
+ PhysicalSize containing_block_size =
+ containing_block.fragment ? containing_block.fragment->Size() : size;
+ return PhysicalContainingBlock(builder, size, containing_block_size,
+ containing_block);
+}
+
} // namespace
// static
@@ -148,8 +153,10 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
/* is_css_box */ builder->box_type_ != NGBoxType::kColumnBox, borders,
scrollbar, padding, physical_size, writing_direction);
- if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder())
- calculator.AddItems(items_builder->Items(physical_size));
+ if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) {
+ calculator.AddItems(builder->GetLayoutObject(),
+ items_builder->Items(physical_size));
+ }
for (auto& child : builder->children_) {
const auto* box_fragment =
@@ -273,6 +280,7 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
const_has_fragment_items_(has_fragment_items),
const_has_rare_data_(has_rare_data),
has_descendants_for_table_part_(false),
+ is_fragmentation_context_root_(builder->is_fragmentation_context_root_),
const_num_children_(builder->children_.size()) {
DCHECK(layout_object_);
DCHECK(layout_object_->IsBoxModelObject());
@@ -391,36 +399,43 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
const_has_rare_data_(other.const_has_rare_data_),
is_first_for_node_(other.is_first_for_node_),
has_descendants_for_table_part_(other.has_descendants_for_table_part_),
+ is_fragmentation_context_root_(other.is_fragmentation_context_root_),
const_num_children_(other.const_num_children_),
baseline_(other.baseline_),
last_baseline_(other.last_baseline_),
ink_overflow_(other.InkOverflowType(), other.ink_overflow_) {
// To ensure the fragment tree is consistent, use the post-layout fragment.
+#if DCHECK_IS_ON()
+ AllowPostLayoutScope allow_post_layout_scope;
+#endif
+ const LayoutBox* flow_thread = nullptr;
for (wtf_size_t i = 0; i < const_num_children_; ++i) {
children_[i].offset = other.children_[i].offset;
- scoped_refptr<const NGPhysicalFragment> post_layout =
- other.children_[i]->PostLayout();
- // While making the fragment tree consistent, we need to also clone any
- // fragmentainer fragments, as they don't necessarily have their result
- // stored on the layout-object tree.
- if (post_layout->IsFragmentainerBox()) {
- const auto& box_fragment = To<NGPhysicalBoxFragment>(*post_layout);
-
- absl::optional<PhysicalRect> recalculated_layout_overflow;
- if (recalculate_layout_overflow) {
- recalculated_layout_overflow =
- NGLayoutOverflowCalculator::RecalculateLayoutOverflowForFragment(
- box_fragment);
+ const NGPhysicalFragment* post_layout;
+ const NGPhysicalFragment& other_child_fragment = *other.children_[i];
+ if (UNLIKELY(other_child_fragment.IsColumnBox())) {
+ // To find the PostLayout fragment of a column box, copy from the
+ // FlowThread. Its |PhysicalFragments| should match the children of the
+ // multicol container fragment. |PostLayout| does not work for column
+ // boxes because a fragment can't compute its index, but we know the
+ // index. See |PostLayout| for more details.
+ if (!flow_thread) {
+ DCHECK_EQ(i, 0u);
+ flow_thread =
+ To<LayoutBox>(GetSelfOrContainerLayoutObject()->SlowFirstChild());
+ DCHECK(flow_thread);
+ DCHECK(flow_thread->IsLayoutFlowThread());
+ DCHECK_EQ(flow_thread->PhysicalFragmentCount(), const_num_children_);
}
-
- // Call the move constructor to move without |AddRef|.
- new (&children_[i].fragment) scoped_refptr<const NGPhysicalFragment>(
- NGPhysicalBoxFragment::CloneWithPostLayoutFragments(
- box_fragment, recalculated_layout_overflow));
+ post_layout = flow_thread->GetPhysicalFragment(i);
} else {
- new (&children_[i].fragment)
- scoped_refptr<const NGPhysicalFragment>(post_layout);
+ DCHECK(!flow_thread);
+ post_layout = other_child_fragment.PostLayout();
}
+
+ DCHECK(post_layout);
+ new (&children_[i].fragment)
+ scoped_refptr<const NGPhysicalFragment>(post_layout);
}
ink_overflow_type_ = other.ink_overflow_type_;
@@ -457,15 +472,30 @@ NGPhysicalBoxFragment::RareData::RareData(NGBoxFragmentBuilder* builder,
: mathml_paint_info(std::move(builder->mathml_paint_info_)) {
oof_positioned_fragmentainer_descendants.ReserveCapacity(
builder->oof_positioned_fragmentainer_descendants_.size());
- const WritingModeConverter converter(
- {builder->Style().GetWritingMode(), builder->Direction()}, size);
for (const auto& descendant :
builder->oof_positioned_fragmentainer_descendants_) {
+ WritingDirectionMode writing_direction = builder->GetWritingDirection();
+ const WritingModeConverter converter(writing_direction, size);
+ NGInlineContainer<PhysicalOffset> inline_container(
+ descendant.inline_container.container,
+ converter.ToPhysical(descendant.inline_container.relative_offset,
+ PhysicalSize()));
+
+ // The static position should remain relative to the containing block.
+ PhysicalSize containing_block_size =
+ descendant.containing_block.fragment
+ ? descendant.containing_block.fragment->Size()
+ : size;
+ const WritingModeConverter containing_block_converter(
+ writing_direction, containing_block_size);
+
oof_positioned_fragmentainer_descendants.emplace_back(
descendant.Node(),
- descendant.static_position.ConvertToPhysical(converter),
- descendant.inline_container,
- PhysicalContainingBlock(builder, size, descendant.containing_block),
+ descendant.static_position.ConvertToPhysical(
+ containing_block_converter),
+ inline_container,
+ PhysicalContainingBlock(builder, size, containing_block_size,
+ descendant.containing_block),
PhysicalContainingBlock(builder, size,
descendant.fixedpos_containing_block));
}
@@ -510,24 +540,14 @@ NGPhysicalBoxFragment::RareData::RareData(const RareData& other)
: nullptr),
table_cell_column_index(other.table_cell_column_index) {}
-scoped_refptr<const NGLayoutResult>
-NGPhysicalBoxFragment::CloneAsHiddenForPaint() const {
- const ComputedStyle& style = Style();
- NGBoxFragmentBuilder builder(GetMutableLayoutObject(), &style,
- style.GetWritingDirection());
- builder.SetBoxType(BoxType());
- NGFragmentGeometry initial_fragment_geometry{
- Size().ConvertToLogical(style.GetWritingMode())};
- builder.SetInitialFragmentGeometry(initial_fragment_geometry);
- builder.SetIsHiddenForPaint(true);
- return builder.ToBoxFragment();
-}
-
const LayoutBox* NGPhysicalBoxFragment::OwnerLayoutBox() const {
const LayoutBox* owner_box =
DynamicTo<LayoutBox>(GetSelfOrContainerLayoutObject());
DCHECK(owner_box);
if (UNLIKELY(IsColumnBox())) {
+ // Adjust the owner for column boxes. Column box fragment's |layout_object_|
+ // is its multicol container, but |LayoutFlowThread::layout_results_|
+ // has the column box fragments.
owner_box = To<LayoutBox>(owner_box->SlowFirstChild());
DCHECK(owner_box && owner_box->IsLayoutFlowThread());
}
@@ -580,6 +600,11 @@ PhysicalOffset NGPhysicalBoxFragment::OffsetFromOwnerLayoutBox() const {
}
const NGPhysicalBoxFragment* NGPhysicalBoxFragment::PostLayout() const {
+ // While side effects are disabled, new fragments are not copied to
+ // |LayoutBox|. Just return the given fragment.
+ if (NGDisableSideEffectsScope::IsDisabled())
+ return this;
+
const auto* layout_object = GetSelfOrContainerLayoutObject();
if (UNLIKELY(!layout_object)) {
NOTREACHED();
@@ -591,28 +616,51 @@ const NGPhysicalBoxFragment* NGPhysicalBoxFragment::PostLayout() const {
return this;
}
if (UNLIKELY(IsColumnBox())) {
- // Column boxes should not be a relayout boundary.
+ // For column boxes, the logic does not work because non-last column box
+ // fragments may have null |BreakToken|, and |SequenceNumber| does not match
+ // the index of |LayoutBox::PhysicalFragments|. For this reason,
+ // |CloneWithPostLayoutFragments| has special logic to handle column boxes.
+#if DCHECK_IS_ON()
+ // We can at least check whether |this| is the latest or not.
+ if (!AllowPostLayoutScope::IsAllowed())
+ DCHECK(OwnerLayoutBox());
+#endif
return this;
}
const wtf_size_t fragment_count = box->PhysicalFragmentCount();
if (UNLIKELY(fragment_count == 0)) {
- // This should not happen, but DCHECK hits. crbug.com/1107204
+#if DCHECK_IS_ON()
+ DCHECK(AllowPostLayoutScope::IsAllowed());
+#endif
return nullptr;
}
+
+ const NGPhysicalBoxFragment* post_layout = nullptr;
if (fragment_count == 1) {
- const NGPhysicalBoxFragment* post_layout = box->GetPhysicalFragment(0);
+ post_layout = box->GetPhysicalFragment(0);
DCHECK(post_layout);
- if (UNLIKELY(post_layout != this)) {
- // This can happen at the relayout boundary crbug.com/829028
- // but DCHECKing |IsRelayoutBoundary()| hits. crbug.com/1107204
- return post_layout;
+ } else if (const auto* break_token = To<NGBlockBreakToken>(BreakToken())) {
+ const unsigned index = break_token->SequenceNumber();
+ if (index < fragment_count) {
+ post_layout = box->GetPhysicalFragment(index);
+ DCHECK(post_layout);
+ DCHECK(
+ !post_layout->BreakToken() ||
+ To<NGBlockBreakToken>(post_layout->BreakToken())->SequenceNumber() ==
+ index);
}
+ } else {
+ post_layout = &box->PhysicalFragments().back();
}
- // TODO(crbug.com/829028): Block fragmentation not supported yet.
- DCHECK(box->PhysicalFragments().Contains(*this));
- return this;
+ if (post_layout == this)
+ return this;
+
+#if DCHECK_IS_ON()
+ DCHECK(AllowPostLayoutScope::IsAllowed());
+#endif
+ return post_layout;
}
PhysicalRect NGPhysicalBoxFragment::SelfInkOverflow() const {
@@ -739,7 +787,11 @@ bool NGPhysicalBoxFragment::MayIntersect(
PhysicalRect NGPhysicalBoxFragment::ScrollableOverflow(
TextHeightType height_type) const {
DCHECK(GetLayoutObject());
- DCHECK_EQ(PostLayout(), this);
+ // TODO(kojii): Scrollable overflow is computed after layout, and that the
+ // tree needs to be consistent, except for Ruby where it is computed during
+ // layout. It might be that |ComputeAnnotationOverflow| should move to layout
+ // overflow recalc, but it is to be thought out.
+ DCHECK(height_type == TextHeightType::kEmHeight || PostLayout() == this);
if (UNLIKELY(IsLayoutObjectDestroyedOrMoved())) {
NOTREACHED();
return PhysicalRect();
@@ -773,7 +825,8 @@ PhysicalRect NGPhysicalBoxFragment::ScrollableOverflow(
PhysicalRect NGPhysicalBoxFragment::ScrollableOverflowFromChildren(
TextHeightType height_type) const {
- DCHECK_EQ(PostLayout(), this);
+ // TODO(kojii): See |ScrollableOverflow|.
+ DCHECK(height_type == TextHeightType::kEmHeight || PostLayout() == this);
const NGFragmentItems* items = Items();
if (Children().empty() && !items)
return PhysicalRect();
@@ -933,10 +986,9 @@ PhysicalRect NGPhysicalBoxFragment::ScrollableOverflowFromChildren(
return context.children_overflow;
}
-LayoutSize NGPhysicalBoxFragment::PixelSnappedScrolledContentOffset() const {
+IntPoint NGPhysicalBoxFragment::PixelSnappedScrolledContentOffset() const {
DCHECK(GetLayoutObject());
- const LayoutBox* box = To<LayoutBox>(GetLayoutObject());
- return box->PixelSnappedScrolledContentOffset();
+ return To<LayoutBox>(*GetLayoutObject()).PixelSnappedScrolledContentOffset();
}
PhysicalSize NGPhysicalBoxFragment::ScrollSize() const {
@@ -1039,6 +1091,13 @@ PhysicalRect NGPhysicalBoxFragment::RecalcContentsInkOverflow() {
NGInlineCursor cursor(*this, *items);
contents_rect = NGFragmentItem::RecalcInkOverflowForCursor(&cursor);
+ // Add text decorations and emphasis mark ink over flow for combined
+ // text.
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(GetLayoutObject());
+ if (UNLIKELY(text_combine))
+ contents_rect.Unite(text_combine->RecalcContentsInkOverflow());
+
// Even if this turned out to be an inline formatting context with
// fragment items (handled above), we need to handle floating descendants.
// If a float is block-fragmented, it is resumed as a regular box fragment
@@ -1177,8 +1236,16 @@ void NGPhysicalBoxFragment::AddOutlineRects(
DCHECK(IsOutlineOwner());
// For anonymous blocks, the children add outline rects.
- if (!IsAnonymousBlock())
- outline_rects->emplace_back(additional_offset, Size().ToLayoutSize());
+ if (!IsAnonymousBlock()) {
+ if (IsSvgText()) {
+ if (const NGFragmentItems* items = Items()) {
+ outline_rects->emplace_back(PhysicalRect::EnclosingRect(
+ GetLayoutObject()->ObjectBoundingBox()));
+ }
+ } else {
+ outline_rects->emplace_back(additional_offset, Size().ToLayoutSize());
+ }
+ }
if (outline_type == NGOutlineType::kIncludeBlockVisualOverflow &&
!HasNonVisibleOverflow() && !HasControlClip(*this)) {
@@ -1240,7 +1307,7 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox(
#if DCHECK_IS_ON()
has_this_fragment = has_this_fragment || current.BoxFragment() == this;
#endif
- if (!current.Size().IsZero())
+ if (!current.Size().IsZero() && !current.GetLayoutObject()->IsSVG())
rects->push_back(current.RectInContainerFragment());
// Add descendants if any, in the container-relative coordinate.
@@ -1511,6 +1578,15 @@ NGPixelSnappedPhysicalBoxStrut NGPhysicalBoxFragment::BorderWidths() const {
}
#if DCHECK_IS_ON()
+NGPhysicalBoxFragment::AllowPostLayoutScope::AllowPostLayoutScope() {
+ ++allow_count_;
+}
+
+NGPhysicalBoxFragment::AllowPostLayoutScope::~AllowPostLayoutScope() {
+ DCHECK(allow_count_);
+ --allow_count_;
+}
+
void NGPhysicalBoxFragment::CheckSameForSimplifiedLayout(
const NGPhysicalBoxFragment& other,
bool check_same_block_size) const {
@@ -1540,6 +1616,8 @@ void NGPhysicalBoxFragment::CheckSameForSimplifiedLayout(
other.depends_on_percentage_block_size_);
DCHECK_EQ(has_descendants_for_table_part_,
other.has_descendants_for_table_part_);
+ DCHECK_EQ(is_fragmentation_context_root_,
+ other.is_fragmentation_context_root_);
DCHECK_EQ(is_fieldset_container_, other.is_fieldset_container_);
DCHECK_EQ(is_table_ng_part_, other.is_table_ng_part_);
@@ -1648,6 +1726,41 @@ void NGPhysicalBoxFragment::CheckIntegrity() const {
DCHECK(!has_list_markers);
}
}
+
+void NGPhysicalBoxFragment::AssertFragmentTreeSelf() const {
+ DCHECK(!IsInlineBox());
+ DCHECK(OwnerLayoutBox());
+ DCHECK_EQ(this, PostLayout());
+}
+
+void NGPhysicalBoxFragment::AssertFragmentTreeChildren(
+ bool allow_destroyed) const {
+ if (const NGFragmentItems* items = Items()) {
+ for (NGInlineCursor cursor(*this, *items); cursor; cursor.MoveToNext()) {
+ const NGFragmentItem& item = *cursor.Current();
+ if (item.IsLayoutObjectDestroyedOrMoved()) {
+ DCHECK(allow_destroyed);
+ DCHECK(!item.BoxFragment() ||
+ item.BoxFragment()->IsLayoutObjectDestroyedOrMoved());
+ continue;
+ }
+ if (const auto* box = item.BoxFragment()) {
+ DCHECK(!box->IsLayoutObjectDestroyedOrMoved());
+ if (!box->IsInlineBox())
+ box->AssertFragmentTreeSelf();
+ }
+ }
+ }
+
+ for (const NGLink& child : Children()) {
+ if (child->IsLayoutObjectDestroyedOrMoved()) {
+ DCHECK(allow_destroyed);
+ continue;
+ }
+ if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(child.fragment))
+ box->AssertFragmentTreeSelf();
+ }
+}
#endif
} // namespace blink
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 79d8b569812..9dc67181a41 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
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_BOX_FRAGMENT_H_
#include "base/dcheck_is_on.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/box_sides.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
@@ -57,8 +58,6 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
const PhysicalRect& layout_overflow,
bool recalculate_layout_overflow);
- scoped_refptr<const NGLayoutResult> CloneAsHiddenForPaint() const;
-
~NGPhysicalBoxFragment() {
ink_overflow_.Reset(InkOverflowType());
if (const_has_fragment_items_)
@@ -73,6 +72,20 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
}
}
+#if DCHECK_IS_ON()
+ class AllowPostLayoutScope {
+ STACK_ALLOCATED();
+
+ public:
+ AllowPostLayoutScope();
+ ~AllowPostLayoutScope();
+ static bool IsAllowed() { return allow_count_; }
+
+ private:
+ static unsigned allow_count_;
+ };
+#endif
+
const NGPhysicalBoxFragment* PostLayout() const;
// Returns the children of |this|.
@@ -164,6 +177,8 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
return *ComputeLayoutOverflowAddress();
}
+ bool HasLayoutOverflow() const { return has_layout_overflow_; }
+
const NGPhysicalBoxStrut Borders() const {
if (!has_borders_)
return NGPhysicalBoxStrut();
@@ -286,7 +301,7 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
const PhysicalOffset& location,
const NGBlockBreakToken* incoming_break_token,
OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize) const;
- LayoutSize PixelSnappedScrolledContentOffset() const;
+ IntPoint PixelSnappedScrolledContentOffset() const;
PhysicalSize ScrollSize() const;
NGInkOverflow::Type InkOverflowType() const {
@@ -368,6 +383,10 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
return has_descendants_for_table_part_;
}
+ bool IsFragmentationContextRoot() const {
+ return is_fragmentation_context_root_;
+ }
+
// Returns true if we have a descendant within this formatting context, which
// is potentially above our block-start edge.
bool MayHaveDescendantAboveBlockStart() const {
@@ -426,6 +445,8 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
#if DCHECK_IS_ON()
void InvalidateInkOverflow();
+ void AssertFragmentTreeSelf() const;
+ void AssertFragmentTreeChildren(bool allow_destroyed = false) const;
#endif
private:
@@ -547,6 +568,7 @@ class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
const unsigned const_has_rare_data_ : 1;
unsigned is_first_for_node_ : 1;
unsigned has_descendants_for_table_part_ : 1;
+ unsigned is_fragmentation_context_root_ : 1;
const wtf_size_t const_num_children_;
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 6e496b7628a..dc6a54c4f0d 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -186,4 +187,93 @@ TEST_F(NGPhysicalBoxFragmentTest, ReplacedBlock) {
EXPECT_EQ(fragment.BoxType(), NGPhysicalFragment::kBlockFlowRoot);
}
+TEST_F(NGPhysicalBoxFragmentTest, IsFragmentationContextRoot) {
+ ScopedLayoutNGBlockFragmentationForTest block_frag(true);
+ SetBodyInnerHTML(R"HTML(
+ <div id="multicol" style="columns:3;">
+ <div id="child"></div>
+ </div>
+ )HTML");
+
+ const auto& multicol = GetPhysicalBoxFragmentByElementId("multicol");
+ EXPECT_TRUE(multicol.IsFragmentationContextRoot());
+
+ // There should be one column.
+ EXPECT_EQ(multicol.Children().size(), 1u);
+ const auto& column = To<NGPhysicalBoxFragment>(*multicol.Children()[0]);
+ EXPECT_TRUE(column.IsColumnBox());
+ EXPECT_FALSE(column.IsFragmentationContextRoot());
+
+ const auto& child = GetPhysicalBoxFragmentByElementId("child");
+ EXPECT_FALSE(child.IsFragmentationContextRoot());
+}
+
+TEST_F(NGPhysicalBoxFragmentTest, IsFragmentationContextRootNested) {
+ ScopedLayoutNGBlockFragmentationForTest block_frag(true);
+ SetBodyInnerHTML(R"HTML(
+ <div id="outer" style="columns:3;">
+ <div id="foo">
+ <div id="inner" style="columns:3;">
+ <div id="bar"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ const auto& outer = GetPhysicalBoxFragmentByElementId("outer");
+ EXPECT_TRUE(outer.IsFragmentationContextRoot());
+
+ EXPECT_EQ(outer.Children().size(), 1u);
+ const auto& outer_column = To<NGPhysicalBoxFragment>(*outer.Children()[0]);
+ EXPECT_TRUE(outer_column.IsColumnBox());
+ EXPECT_FALSE(outer_column.IsFragmentationContextRoot());
+
+ const auto& foo = GetPhysicalBoxFragmentByElementId("foo");
+ EXPECT_FALSE(foo.IsFragmentationContextRoot());
+
+ const auto& inner = GetPhysicalBoxFragmentByElementId("inner");
+ EXPECT_TRUE(inner.IsFragmentationContextRoot());
+
+ EXPECT_EQ(inner.Children().size(), 1u);
+ const auto& inner_column = To<NGPhysicalBoxFragment>(*inner.Children()[0]);
+ EXPECT_TRUE(inner_column.IsColumnBox());
+ EXPECT_FALSE(inner_column.IsFragmentationContextRoot());
+
+ const auto& bar = GetPhysicalBoxFragmentByElementId("bar");
+ EXPECT_FALSE(bar.IsFragmentationContextRoot());
+}
+
+TEST_F(NGPhysicalBoxFragmentTest, IsFragmentationContextRootFieldset) {
+ ScopedLayoutNGBlockFragmentationForTest block_frag(true);
+ SetBodyInnerHTML(R"HTML(
+ <fieldset id="fieldset" style="columns:3;">
+ <legend id="legend"></legend>
+ <div id="child"></div>
+ </fieldset>
+ )HTML");
+
+ const auto& fieldset = GetPhysicalBoxFragmentByElementId("fieldset");
+ EXPECT_FALSE(fieldset.IsFragmentationContextRoot());
+
+ // There should be a legend and an anonymous fieldset wrapper fragment.
+ ASSERT_EQ(fieldset.Children().size(), 2u);
+
+ const auto& legend = To<NGPhysicalBoxFragment>(*fieldset.Children()[0]);
+ EXPECT_EQ(To<Element>(legend.GetNode())->GetIdAttribute(), "legend");
+ EXPECT_FALSE(legend.IsFragmentationContextRoot());
+
+ // The multicol container is established by the anonymous content wrapper, not
+ // the actual fieldset.
+ const auto& wrapper = To<NGPhysicalBoxFragment>(*fieldset.Children()[1]);
+ EXPECT_FALSE(wrapper.GetNode());
+ EXPECT_TRUE(wrapper.IsFragmentationContextRoot());
+
+ EXPECT_EQ(wrapper.Children().size(), 1u);
+ const auto& column = To<NGPhysicalBoxFragment>(*wrapper.Children()[0]);
+ EXPECT_TRUE(column.IsColumnBox());
+
+ const auto& child = GetPhysicalBoxFragmentByElementId("child");
+ EXPECT_FALSE(child.IsFragmentationContextRoot());
+}
+
} // namespace blink
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 001ec43b557..12bff972079 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
@@ -8,7 +8,9 @@
#include "third_party/blink/renderer/core/html/shadow/shadow_element_utils.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
@@ -94,13 +96,14 @@ class FragmentTreeDumper {
public:
FragmentTreeDumper(StringBuilder* builder,
- NGPhysicalFragment::DumpFlags flags)
- : builder_(builder), flags_(flags) {}
+ NGPhysicalFragment::DumpFlags flags,
+ const NGPhysicalFragment* target = nullptr)
+ : builder_(builder), target_fragment_(target), flags_(flags) {}
void Append(const NGPhysicalFragment* fragment,
absl::optional<PhysicalOffset> fragment_offset,
unsigned indent = 2) {
- AppendIndentation(indent);
+ AppendIndentation(indent, fragment);
bool has_content = false;
if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(fragment)) {
@@ -178,14 +181,13 @@ class FragmentTreeDumper {
builder_->Append("\n");
}
- void AppendLegacySubtree(const LayoutObject& layout_object,
- unsigned indent = 0) {
+ void AppendLegacySubtree(const LayoutObject& layout_object, unsigned indent) {
for (const LayoutObject* descendant = &layout_object; descendant;) {
- if (!descendant->IsLayoutNGObject()) {
+ if (!IsNGRootWithFragments(*descendant)) {
if (const auto* block = DynamicTo<LayoutBlock>(descendant)) {
if (const auto* positioned_descendants = block->PositionedObjects()) {
for (const auto* positioned_object : *positioned_descendants) {
- if (positioned_object->IsLayoutNGObject())
+ if (IsNGRootWithFragments(*positioned_object))
AppendNGRootInLegacySubtree(*positioned_object, indent);
else
AppendLegacySubtree(*positioned_object, indent);
@@ -203,11 +205,24 @@ class FragmentTreeDumper {
}
}
+ void AppendLegacySubtree(const LayoutObject& layout_object) {
+ AppendLegacySubtree(layout_object, 0);
+ if (target_fragment_ && !target_fragment_found_) {
+ if (flags_ & NGPhysicalFragment::DumpHeaderText) {
+ builder_->Append("(Fragment not found when searching the subtree)\n");
+ builder_->Append("(Dumping detached fragment tree now:)\n");
+ }
+ Append(target_fragment_, absl::nullopt);
+ }
+ }
+
void AppendNGRootInLegacySubtree(const LayoutObject& layout_object,
unsigned indent) {
+ DCHECK(IsNGRootWithFragments(layout_object));
if (flags_ & NGPhysicalFragment::DumpHeaderText) {
AppendIndentation(indent + 2);
- builder_->Append("(NG fragment root inside legacy subtree:)\n");
+ builder_->Append(
+ "(NG fragment root inside fragment-less or legacy subtree:)\n");
}
const LayoutBox& box_descendant = To<LayoutBox>(layout_object);
DCHECK_EQ(box_descendant.PhysicalFragmentCount(), 1u);
@@ -218,14 +233,15 @@ class FragmentTreeDumper {
void Append(NGInlineCursor* cursor, unsigned indent) {
for (; *cursor; cursor->MoveToNextSkippingChildren()) {
const NGInlineCursorPosition& current = cursor->Current();
- if (const NGPhysicalBoxFragment* box = current.BoxFragment()) {
- if (!box->IsInlineBox()) {
- Append(box, current.OffsetInContainerFragment(), indent);
- continue;
- }
+ const NGPhysicalFragment* box = current.BoxFragment();
+ if (box && !box->IsInlineBox()) {
+ Append(box, current.OffsetInContainerFragment(), indent);
+ continue;
}
- AppendIndentation(indent);
+ if (!box)
+ box = current.Item()->LineBoxFragment();
+ AppendIndentation(indent, box);
// TODO(kojii): Use the same format as layout tree dump for now. We can
// make this more similar to |AppendFragmentToString| above.
@@ -272,15 +288,39 @@ class FragmentTreeDumper {
return has_content;
}
- void AppendIndentation(unsigned indent) {
+ void AppendIndentation(unsigned indent,
+ const NGPhysicalFragment* fragment = nullptr) {
if (flags_ & NGPhysicalFragment::DumpIndentation) {
- for (unsigned i = 0; i < indent; i++)
+ unsigned start_idx = 0;
+ if (fragment && fragment == target_fragment_) {
+ builder_->Append("*");
+ start_idx = 1;
+ target_fragment_found_ = true;
+ }
+ for (unsigned i = start_idx; i < indent; i++)
builder_->Append(" ");
}
}
+ // Check if the object is an NG root ready to be traversed. If layout of the
+ // object hasn't finished yet, there'll be no fragment, and false will be
+ // returned.
+ bool IsNGRootWithFragments(const LayoutObject& object) const {
+ if (!object.IsLayoutNGObject())
+ return false;
+ const LayoutBox* box = DynamicTo<LayoutBox>(&object);
+ if (!box)
+ return false;
+ // A root should only have at most one fragment, or zero if it hasn't been
+ // laid out yet.
+ DCHECK_LE(box->PhysicalFragmentCount(), 1u);
+ return box->PhysicalFragmentCount();
+ }
+
StringBuilder* builder_;
+ const NGPhysicalFragment* target_fragment_ = nullptr;
NGPhysicalFragment::DumpFlags flags_;
+ bool target_fragment_found_ = false;
};
} // namespace
@@ -302,6 +342,7 @@ NGPhysicalFragment::NGPhysicalFragment(NGContainerFragmentBuilder* builder,
sub_type_(sub_type),
style_variant_((unsigned)builder->style_variant_),
is_hidden_for_paint_(builder->is_hidden_for_paint_),
+ is_opaque_(builder->is_opaque_),
is_fieldset_container_(false),
is_table_ng_part_(false),
is_legacy_layout_root_(false),
@@ -328,10 +369,14 @@ NGPhysicalFragment::NGPhysicalFragment(NGContainerFragmentBuilder* builder,
const WritingModeConverter converter(
{builder->Style().GetWritingMode(), builder->Direction()}, size);
for (const auto& descendant : builder->oof_positioned_descendants_) {
+ NGInlineContainer<PhysicalOffset> inline_container(
+ descendant.inline_container.container,
+ converter.ToPhysical(descendant.inline_container.relative_offset,
+ PhysicalSize()));
oof_positioned_descendants_->emplace_back(
descendant.Node(),
descendant.static_position.ConvertToPhysical(converter),
- descendant.inline_container);
+ inline_container);
}
}
}
@@ -355,6 +400,7 @@ NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other,
sub_type_(other.sub_type_),
style_variant_(other.style_variant_),
is_hidden_for_paint_(other.is_hidden_for_paint_),
+ is_opaque_(other.is_opaque_),
is_math_fraction_(other.is_math_fraction_),
is_math_operator_(other.is_math_operator_),
base_or_resolved_direction_(other.base_or_resolved_direction_),
@@ -419,7 +465,6 @@ bool NGPhysicalFragment::IsPlacedByLayoutNG() const {
}
const FragmentData* NGPhysicalFragment::GetFragmentData() const {
- DCHECK(CanTraverse());
const LayoutBox* box = DynamicTo<LayoutBox>(GetLayoutObject());
if (!box) {
DCHECK(!GetLayoutObject());
@@ -612,22 +657,24 @@ String NGPhysicalFragment::ToString() const {
String NGPhysicalFragment::DumpFragmentTree(
DumpFlags flags,
+ const NGPhysicalFragment* target,
absl::optional<PhysicalOffset> fragment_offset,
unsigned indent) const {
StringBuilder string_builder;
if (flags & DumpHeaderText)
string_builder.Append(".:: LayoutNG Physical Fragment Tree ::.\n");
- FragmentTreeDumper(&string_builder, flags)
+ FragmentTreeDumper(&string_builder, flags, target)
.Append(this, fragment_offset, indent);
return string_builder.ToString();
}
String NGPhysicalFragment::DumpFragmentTree(const LayoutObject& root,
- DumpFlags flags) {
+ DumpFlags flags,
+ const NGPhysicalFragment* target) {
if (root.IsLayoutNGObject()) {
const LayoutBox& root_box = To<LayoutBox>(root);
DCHECK_EQ(root_box.PhysicalFragmentCount(), 1u);
- return root_box.GetPhysicalFragment(0)->DumpFragmentTree(flags);
+ return root_box.GetPhysicalFragment(0)->DumpFragmentTree(flags, target);
}
StringBuilder string_builder;
if (flags & DumpHeaderText) {
@@ -636,22 +683,10 @@ String NGPhysicalFragment::DumpFragmentTree(const LayoutObject& root,
string_builder.Append(root.DebugName());
string_builder.Append(" ::.\n");
}
- FragmentTreeDumper(&string_builder, flags).AppendLegacySubtree(root);
+ FragmentTreeDumper(&string_builder, flags, target).AppendLegacySubtree(root);
return string_builder.ToString();
}
-#if DCHECK_IS_ON()
-void NGPhysicalFragment::ShowFragmentTree() const {
- DumpFlags dump_flags = DumpAll;
- LOG(INFO) << "\n" << DumpFragmentTree(dump_flags).Utf8();
-}
-
-void NGPhysicalFragment::ShowFragmentTree(const LayoutObject& root) {
- DumpFlags dump_flags = DumpAll;
- LOG(INFO) << "\n" << DumpFragmentTree(root, dump_flags).Utf8();
-}
-#endif
-
// TODO(dlibby): remove `Children` and `PostLayoutChildren` and move the
// casting and/or branching to the callers.
base::span<const NGLink> NGPhysicalFragment::Children() const {
@@ -732,34 +767,49 @@ void NGPhysicalFragment::AddOutlineRectsForCursor(
NGOutlineType outline_type,
const LayoutBoxModelObject* containing_block,
NGInlineCursor* cursor) const {
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(containing_block);
for (; *cursor; cursor->MoveToNext()) {
DCHECK(cursor->Current().Item());
const NGFragmentItem& item = *cursor->Current().Item();
if (UNLIKELY(item.IsLayoutObjectDestroyedOrMoved()))
continue;
- if (item.Type() == NGFragmentItem::kLine) {
- AddOutlineRectsForDescendant(
- {item.LineBoxFragment(), item.OffsetInContainerFragment()},
- outline_rects, additional_offset, outline_type, containing_block);
- continue;
- }
- if (item.IsText()) {
- if (outline_type == NGOutlineType::kDontIncludeBlockVisualOverflow)
- continue;
- outline_rects->push_back(
- PhysicalRect(additional_offset + item.OffsetInContainerFragment(),
- item.Size().ToLayoutSize()));
- continue;
- }
- if (item.Type() == NGFragmentItem::kBox) {
- if (const NGPhysicalBoxFragment* child_box =
- item.PostLayoutBoxFragment()) {
- DCHECK(!child_box->IsOutOfFlowPositioned());
+ switch (item.Type()) {
+ case NGFragmentItem::kLine: {
AddOutlineRectsForDescendant(
- {child_box, item.OffsetInContainerFragment()}, outline_rects,
- additional_offset, outline_type, containing_block);
+ {item.LineBoxFragment(), item.OffsetInContainerFragment()},
+ outline_rects, additional_offset, outline_type, containing_block);
+ break;
+ }
+ case NGFragmentItem::kGeneratedText:
+ case NGFragmentItem::kText: {
+ if (outline_type == NGOutlineType::kDontIncludeBlockVisualOverflow)
+ break;
+ PhysicalRect rect = item.RectInContainerFragment();
+ if (UNLIKELY(text_combine))
+ rect = text_combine->AdjustRectForBoundingBox(rect);
+ rect.Move(additional_offset);
+ outline_rects->push_back(rect);
+ break;
+ }
+ case NGFragmentItem::kSvgText: {
+ PhysicalRect rect =
+ PhysicalRect::EnclosingRect(item.ObjectBoundingBox());
+ DCHECK(!text_combine);
+ rect.Move(additional_offset);
+ outline_rects->push_back(rect);
+ break;
+ }
+ case NGFragmentItem::kBox: {
+ if (const NGPhysicalBoxFragment* child_box =
+ item.PostLayoutBoxFragment()) {
+ DCHECK(!child_box->IsOutOfFlowPositioned());
+ AddOutlineRectsForDescendant(
+ {child_box, item.OffsetInContainerFragment()}, outline_rects,
+ additional_offset, outline_type, containing_block);
+ }
+ break;
}
- continue;
}
}
}
@@ -994,3 +1044,35 @@ std::ostream& operator<<(std::ostream& out,
}
} // namespace blink
+
+#if DCHECK_IS_ON()
+
+void ShowFragmentTree(const blink::NGPhysicalFragment* fragment) {
+ if (!fragment) {
+ LOG(INFO) << "Cannot show fragment tree. Fragment is null.";
+ return;
+ }
+ blink::NGPhysicalFragment::DumpFlags dump_flags =
+ blink::NGPhysicalFragment::DumpAll;
+ LOG(INFO) << "\n" << fragment->DumpFragmentTree(dump_flags).Utf8();
+}
+
+void ShowFragmentTree(const blink::LayoutObject& root,
+ const blink::NGPhysicalFragment* target) {
+ blink::NGPhysicalFragment::DumpFlags dump_flags =
+ blink::NGPhysicalFragment::DumpAll;
+ LOG(INFO) << "\n"
+ << blink::NGPhysicalFragment::DumpFragmentTree(root, dump_flags,
+ target)
+ .Utf8();
+}
+
+void ShowEntireFragmentTree(const blink::NGPhysicalFragment* target) {
+ if (!target) {
+ LOG(INFO) << "Cannot show fragment tree. Fragment is null.";
+ return;
+ }
+ ShowFragmentTree(*target->GetSelfOrContainerLayoutObject()->View(), target);
+}
+
+#endif // DCHECK_IS_ON()
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 aa158693b6c..e6708ed1624 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
@@ -11,12 +11,14 @@
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_size.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/ng/ng_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
#include "third_party/blink/renderer/core/layout/ng/ng_link.h"
@@ -124,6 +126,10 @@ class CORE_EXPORT NGPhysicalFragment
bool IsAtomicInline() const {
return IsBox() && BoxType() == NGBoxType::kAtomicInline;
}
+ bool IsBlockInInline() const {
+ return IsBox() && BoxType() == NGBoxType::kNormalBox && GetLayoutObject() &&
+ IsA<LayoutInline>(GetLayoutObject()->Parent());
+ }
// True if this fragment is in-flow in an inline formatting context.
bool IsInline() const { return IsInlineBox() || IsAtomicInline(); }
bool IsFloating() const {
@@ -132,6 +138,9 @@ class CORE_EXPORT NGPhysicalFragment
bool IsOutOfFlowPositioned() const {
return IsBox() && BoxType() == NGBoxType::kOutOfFlowPositioned;
}
+ bool IsFixedPositioned() const {
+ return IsCSSBox() && layout_object_->IsFixedPositioned();
+ }
bool IsFloatingOrOutOfFlowPositioned() const {
return IsFloating() || IsOutOfFlowPositioned();
}
@@ -176,6 +185,8 @@ class CORE_EXPORT NGPhysicalFragment
layout_object_->IsRubyBase();
}
+ bool IsSvgText() const { return layout_object_->IsNGSVGText(); }
+
bool IsTableNGPart() const { return is_table_ng_part_; }
bool IsTableNG() const {
@@ -195,6 +206,8 @@ class CORE_EXPORT NGPhysicalFragment
!layout_object_->IsTableCellLegacy();
}
+ bool IsGridNG() const { return layout_object_->IsLayoutNGGrid(); }
+
bool IsTextControlContainer() const;
bool IsTextControlPlaceholder() const;
@@ -331,18 +344,6 @@ class CORE_EXPORT NGPhysicalFragment
return IsCSSBox() && layout_object_->ShouldClipOverflowAlongBothAxis();
}
- bool IsFragmentationContextRoot() const {
- // We have no bit that tells us whether this is a fragmentation context
- // root, so some additional checking is necessary here, to make sure that
- // we're actually establishing one. We check that we're not a custom layout
- // box, as specifying columns on such a box has no effect. Note that
- // specifying columns together with a display value of e.g. 'flex', 'grid'
- // or 'table' also has no effect, but we don't need to check for that here,
- // since such display types don't create a block flow (block container).
- return IsCSSBox() && Style().SpecifiesColumns() && IsBlockFlow() &&
- !layout_object_->IsLayoutNGCustom();
- }
-
// Return whether we can traverse this fragment and its children directly, for
// painting, hit-testing and other layout read operations. If false is
// returned, we need to traverse the layout object tree instead.
@@ -352,7 +353,14 @@ class CORE_EXPORT NGPhysicalFragment
// This fragment is hidden for paint purpose, but exists for querying layout
// information. Used for `text-overflow: ellipsis`.
- bool IsHiddenForPaint() const { return is_hidden_for_paint_; }
+ bool IsHiddenForPaint() const {
+ return is_hidden_for_paint_ || layout_object_->IsTruncated();
+ }
+
+ // This fragment is opaque for layout and paint, as if it does not exist and
+ // does not paint its backgrounds and borders, but it can have regular
+ // children and paint properties such as filters can apply.
+ bool IsOpaque() const { return is_opaque_; }
// Return true if this fragment is monolithic, as far as block fragmentation
// is concerned.
@@ -463,16 +471,22 @@ class CORE_EXPORT NGPhysicalFragment
};
typedef int DumpFlags;
+ // Dump the fragment tree, optionally mark |target| if it's found. If not
+ // found, the subtree established by |target| will be dumped as well.
String DumpFragmentTree(DumpFlags,
+ const NGPhysicalFragment* target = nullptr,
absl::optional<PhysicalOffset> = absl::nullopt,
unsigned indent = 2) const;
- static String DumpFragmentTree(const LayoutObject& root, DumpFlags);
-
-#if DCHECK_IS_ON()
- void ShowFragmentTree() const;
- static void ShowFragmentTree(const LayoutObject& root);
-#endif
+ // Dump the fragment tree, starting at |root| (searching inside legacy
+ // subtrees to find all fragments), optionally mark |target| if it's found. If
+ // not found, the subtree established by |target| will be dumped as well.
+ //
+ // Note that if we're in the middle of layout somewhere inside the subtree,
+ // behavior is undefined.
+ static String DumpFragmentTree(const LayoutObject& root,
+ DumpFlags,
+ const NGPhysicalFragment* target = nullptr);
// Same as |base::span<const NGLink>|, except that:
// * Each |NGLink| has the latest generation of post-layout. See
@@ -643,6 +657,7 @@ class CORE_EXPORT NGPhysicalFragment
const unsigned sub_type_ : 3; // NGBoxType, NGTextType, or NGLineBoxType
const unsigned style_variant_ : 2; // NGStyleVariant
const unsigned is_hidden_for_paint_ : 1;
+ unsigned is_opaque_ : 1;
unsigned is_math_fraction_ : 1;
unsigned is_math_operator_ : 1;
// base (line box) or resolve (text) direction
@@ -687,4 +702,23 @@ inline void NGPhysicalFragment::CheckType() const {}
} // namespace blink
+#if DCHECK_IS_ON()
+// Outside the blink namespace for ease of invocation from a debugger.
+
+// Output the fragment tree to the log.
+// See DumpFragmentTree().
+CORE_EXPORT void ShowFragmentTree(const blink::NGPhysicalFragment*);
+
+// Output the fragment tree(s) inside |root| to the log.
+// See DumpFragmentTree(const LayoutObject& ...).
+CORE_EXPORT void ShowFragmentTree(
+ const blink::LayoutObject& root,
+ const blink::NGPhysicalFragment* target = nullptr);
+
+// Output the fragment tree(s) from the entire document to the log.
+// See DumpFragmentTree(const LayoutObject& ...).
+CORE_EXPORT void ShowEntireFragmentTree(
+ const blink::NGPhysicalFragment* target);
+#endif // DCHECK_IS_ON()
+
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment_test.cc
index 544d2ffa3b2..89a3943ca2e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment_test.cc
@@ -6,15 +6,17 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.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 {
class NGPhysicalFragmentTest : public NGLayoutTest {
public:
- String DumpAll() const {
- return NGPhysicalFragment::DumpFragmentTree(*GetDocument().GetLayoutView(),
- NGPhysicalFragment::DumpAll);
+ String DumpAll(const NGPhysicalFragment* target = nullptr) const {
+ return NGPhysicalFragment::DumpFragmentTree(
+ *GetDocument().GetLayoutView(), NGPhysicalFragment::DumpAll, target);
}
};
@@ -25,7 +27,7 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeBasic) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x8 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x0 LayoutNGBlockFlow BODY
Box (block-flow) offset:0,0 size:784x0 LayoutNGBlockFlow DIV id='block'
@@ -42,9 +44,9 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithAbspos) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (out-of-flow-positioned block-flow)(self paint) offset:unplaced size:0x0 LayoutNGBlockFlow (positioned) DIV id='abs'
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x8 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x0 LayoutNGBlockFlow BODY
)DUMP";
@@ -62,7 +64,7 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithAbsposInRelpos) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x8 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x0 LayoutNGBlockFlow BODY
Box (block-flow)(self paint) offset:0,0 size:784x0 LayoutNGBlockFlow (relative positioned) DIV id='rel'
@@ -90,13 +92,13 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithTableWithAbspos) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x22 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x6 LayoutNGBlockFlow BODY
Box (block-flow-root legacy-layout-root)(self paint) offset:0,0 size:6x6 LayoutTable (relative positioned) TABLE
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (out-of-flow-positioned block-flow)(self paint) offset:unplaced size:0x0 LayoutNGBlockFlow (positioned) DIV id='abs'
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow) offset:unplaced size:2x2 LayoutNGTableCell TD
Box (block-flow) offset:1,1 size:0x0 LayoutNGBlockFlow DIV id='inflow'
Box (block-flow) offset:0,0 size:0x0 LayoutNGBlockFlow DIV id='inflowchild'
@@ -116,7 +118,7 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithAbsposTable) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x8 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x0 LayoutNGBlockFlow BODY
)DUMP";
@@ -138,10 +140,10 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithAbsposTableWithChild) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow) offset:unplaced size:0x0 LayoutNGTableCell (anonymous)
Box (block-flow) offset:0,0 size:0x0 LayoutNGBlockFlow DIV id='child'
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x8 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x0 LayoutNGBlockFlow BODY
)DUMP";
@@ -168,18 +170,51 @@ TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithGrid) {
String dump = DumpAll();
String expectation =
R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x16 LayoutNGBlockFlow HTML
Box (block-flow) offset:8,8 size:784x0 LayoutNGBlockFlow BODY
Box (block-flow-root legacy-layout-root) offset:0,0 size:784x0 LayoutGrid DIV id='outer-grid'
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow) offset:unplaced size:784x0 LayoutNGBlockFlow DIV id='inner-grid-item'
Box (block-flow) offset:0,0 size:784x0 LayoutNGBlockFlow DIV id='foo'
- (NG fragment root inside legacy subtree:)
+ (NG fragment root inside fragment-less or legacy subtree:)
Box (block-flow-root block-flow) offset:unplaced size:784x0 LayoutNGBlockFlow DIV id='block-container-item'
Box (block-flow) offset:0,0 size:784x0 LayoutNGBlockFlow DIV id='bar'
)DUMP";
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGPhysicalFragmentTest, DumpFragmentTreeWithTargetInsideColumn) {
+ ScopedLayoutNGBlockFragmentationForTest ng_block_frag(true);
+ SetBodyInnerHTML(R"HTML(
+ <div id="multicol" style="columns:3;">
+ <div id="child" style="height:150px;"></div>
+ </div>
+ )HTML");
+
+ const LayoutObject* child_object = GetLayoutObjectByElementId("child");
+ ASSERT_TRUE(child_object);
+ ASSERT_TRUE(child_object->IsBox());
+ const LayoutBox& box = To<LayoutBox>(*child_object);
+ ASSERT_EQ(box.PhysicalFragmentCount(), 3u);
+ const NGPhysicalBoxFragment* second_child_fragment =
+ box.GetPhysicalFragment(1);
+
+ String dump = DumpAll(second_child_fragment);
+ String expectation =
+ R"DUMP(.:: LayoutNG Physical Fragment Tree at legacy root LayoutView #document ::.
+ (NG fragment root inside fragment-less or legacy subtree:)
+ Box (block-flow-root block-flow)(self paint) offset:unplaced size:800x66 LayoutNGBlockFlow HTML
+ Box (block-flow) offset:8,8 size:784x50 LayoutNGBlockFlow BODY
+ Box (block-flow-root block-flow) offset:0,0 size:784x50 LayoutNGBlockFlow DIV id='multicol'
+ Box (column block-flow) offset:0,0 size:260.656x50
+ Box (block-flow) offset:0,0 size:260.656x50 LayoutNGBlockFlow DIV id='child'
+ Box (column block-flow) offset:261.656,0 size:260.656x50
+* Box (block-flow) offset:0,0 size:260.656x50 LayoutNGBlockFlow DIV id='child'
+ Box (column block-flow) offset:523.313,0 size:260.656x50
+ Box (block-flow) offset:0,0 size:260.656x50 LayoutNGBlockFlow DIV id='child'
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
} // namespace blink
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 26b08228d5e..23112e20509 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
@@ -142,4 +142,31 @@ LogicalOffset ComputeRelativeOffsetForInline(const NGConstraintSpace& space,
return relative_offset;
}
+LogicalOffset ComputeRelativeOffsetForOOFInInline(
+ const NGConstraintSpace& space,
+ const ComputedStyle& child_style) {
+ if (child_style.GetPosition() != EPosition::kRelative)
+ return LogicalOffset();
+
+ // The confliction resolution rules work based off the block's writing-mode
+ // and direction, not the child's container. E.g.
+ // <span style="direction: rtl;">
+ // <span style="position: relative; left: 100px; right: -50px;"></span>
+ // </span>
+ // In the above example "left" wins.
+ const WritingDirectionMode writing_direction = space.GetWritingDirection();
+ LogicalOffset relative_offset = ComputeRelativeOffset(
+ child_style, writing_direction, space.AvailableSize());
+
+ // Lines are built in a line-logical coordinate system:
+ // https://drafts.csswg.org/css-writing-modes-3/#line-directions
+ // Reverse the offset direction if we are in a RTL. We skip adjusting for
+ // flipped writing-mode when applying the relative position to an OOF
+ // positioned element.
+ if (writing_direction.IsRtl())
+ relative_offset.inline_offset = -relative_offset.inline_offset;
+
+ return relative_offset;
+}
+
} // namespace blink
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 64e93afd273..e6b1bbd6021 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
@@ -33,6 +33,10 @@ CORE_EXPORT LogicalOffset
ComputeRelativeOffsetForInline(const NGConstraintSpace& space,
const ComputedStyle& child_style);
+CORE_EXPORT LogicalOffset
+ComputeRelativeOffsetForOOFInInline(const NGConstraintSpace& space,
+ const ComputedStyle& child_style);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_RELATIVE_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
index c3b4584720b..e9c2a04b549 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
@@ -23,7 +23,8 @@ namespace blink {
NGSimplifiedLayoutAlgorithm::NGSimplifiedLayoutAlgorithm(
const NGLayoutAlgorithmParams& params,
- const NGLayoutResult& result)
+ const NGLayoutResult& result,
+ bool keep_old_size)
: NGLayoutAlgorithm(params),
previous_result_(result),
writing_direction_(Style().GetWritingDirection()) {
@@ -36,6 +37,17 @@ NGSimplifiedLayoutAlgorithm::NGSimplifiedLayoutAlgorithm(
container_builder_.SetIsNewFormattingContext(
physical_fragment.IsFormattingContextRoot());
+ container_builder_.SetIsFirstForNode(physical_fragment.IsFirstForNode());
+
+ if (physical_fragment.IsFragmentationContextRoot())
+ container_builder_.SetIsBlockFragmentationContextRoot();
+
+ if (keep_old_size) {
+ // When we're cloning a fragment to insert additional fragmentainers to hold
+ // OOFs, re-use the old break token. This may not be the last fragment.
+ container_builder_.PresetNextBreakToken(physical_fragment.BreakToken());
+ }
+
if (is_block_flow && !physical_fragment.IsFieldsetContainer()) {
container_builder_.SetIsInlineFormattingContext(
Node().IsInlineFormattingContextRoot());
@@ -133,6 +145,11 @@ NGSimplifiedLayoutAlgorithm::NGSimplifiedLayoutAlgorithm(
}
}
+ if (physical_fragment.IsGridNG()) {
+ container_builder_.TransferGridData(
+ std::make_unique<NGGridData>(*result.GridData()));
+ }
+
if (physical_fragment.IsHiddenForPaint())
container_builder_.SetIsHiddenForPaint(true);
@@ -141,25 +158,34 @@ NGSimplifiedLayoutAlgorithm::NGSimplifiedLayoutAlgorithm(
if (physical_fragment.IsTableNGPart())
container_builder_.SetIsTableNGPart();
- container_builder_.SetIntrinsicBlockSize(result.IntrinsicBlockSize());
-
- LayoutUnit new_block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), BorderPadding(), result.IntrinsicBlockSize(),
- container_builder_.InitialBorderBoxSize().inline_size);
-
- // Only block-flow is allowed to change its block-size during "simplified"
- // layout, all other layout types must remain the same size.
- if (is_block_flow) {
- container_builder_.SetFragmentBlockSize(new_block_size);
- } else {
+ if (keep_old_size) {
LayoutUnit old_block_size =
NGFragment(writing_direction_, physical_fragment).BlockSize();
+ container_builder_.SetFragmentBlockSize(old_block_size);
+ } else {
+ container_builder_.SetIntrinsicBlockSize(result.IntrinsicBlockSize());
+
+ LayoutUnit new_block_size = ComputeBlockSizeForFragment(
+ ConstraintSpace(), Style(), BorderPadding(),
+ result.IntrinsicBlockSize(),
+ container_builder_.InitialBorderBoxSize().inline_size);
+
+ // Only block-flow is allowed to change its block-size during "simplified"
+ // layout, all other layout types must remain the same size.
+ if (is_block_flow) {
+ container_builder_.SetFragmentBlockSize(new_block_size);
+ } else {
+ LayoutUnit old_block_size =
+ NGFragment(writing_direction_, physical_fragment).BlockSize();
#if DCHECK_IS_ON()
- // Tables don't respect the typical block-sizing rules.
- if (!physical_fragment.IsTableNG())
- DCHECK_EQ(old_block_size, new_block_size);
+ // Tables, sections, rows don't respect the typical block-sizing rules.
+ if (!physical_fragment.IsTableNG() &&
+ !physical_fragment.IsTableNGSection() &&
+ !physical_fragment.IsTableNGRow())
+ DCHECK_EQ(old_block_size, new_block_size);
#endif
- container_builder_.SetFragmentBlockSize(old_block_size);
+ container_builder_.SetFragmentBlockSize(old_block_size);
+ }
}
// We need the previous physical container size to calculate the position of
@@ -167,6 +193,26 @@ NGSimplifiedLayoutAlgorithm::NGSimplifiedLayoutAlgorithm(
previous_physical_container_size_ = physical_fragment.Size();
}
+void NGSimplifiedLayoutAlgorithm::CloneOldChildren() {
+ const auto& previous_fragment =
+ To<NGPhysicalBoxFragment>(previous_result_.PhysicalFragment());
+ for (const auto& child_link : previous_fragment.Children()) {
+ const auto& child_fragment = *child_link.get();
+ AddChildFragment(child_link, child_fragment);
+ }
+}
+
+void NGSimplifiedLayoutAlgorithm::AppendNewChildFragment(
+ const NGPhysicalFragment& fragment,
+ LogicalOffset offset) {
+ container_builder_.AddChild(fragment, offset);
+}
+
+scoped_refptr<const NGLayoutResult>
+NGSimplifiedLayoutAlgorithm::CreateResultAfterManualChildLayout() {
+ return container_builder_.ToBoxFragment();
+}
+
scoped_refptr<const NGLayoutResult> NGSimplifiedLayoutAlgorithm::Layout() {
// Since simplified layout's |Layout()| function deals with laying out
// children, we can early out if we are display-locked.
@@ -220,7 +266,6 @@ scoped_refptr<const NGLayoutResult> NGSimplifiedLayoutAlgorithm::Layout() {
// calculated it.
const auto* layer = child.GetLayoutBox()->Layer();
NGLogicalStaticPosition position = layer->GetStaticPosition();
-
container_builder_.AddOutOfFlowChildCandidate(
To<NGBlockNode>(child), position.offset, position.inline_edge,
position.block_edge, /* needs_block_offset_adjustment */ false);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
index e7733810a82..c2d2cd2e6d8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
@@ -40,9 +40,23 @@ class CORE_EXPORT NGSimplifiedLayoutAlgorithm
NGBlockBreakToken> {
public:
NGSimplifiedLayoutAlgorithm(const NGLayoutAlgorithmParams&,
- const NGLayoutResult&);
+ const NGLayoutResult&,
+ bool keep_old_size = false);
+ // Perform a simple copy of all children of the old fragment.
+ void CloneOldChildren();
+
+ void AppendNewChildFragment(const NGPhysicalFragment&, LogicalOffset);
+
+ // Just create a new layout result based on the current builder state. To be
+ // used after CloneOldChildren() / AppendNewChildFragment().
+ scoped_refptr<const NGLayoutResult> CreateResultAfterManualChildLayout();
+
+ // Attempt to perform simplified layout on all children and return a new
+ // result. If nullptr is returned, it means that simplified layout isn't
+ // possible.
scoped_refptr<const NGLayoutResult> Layout() override;
+
MinMaxSizesResult ComputeMinMaxSizes(
const MinMaxSizesFloatInput&) const override {
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc
index 2607bddd47f..b66f0a755c3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc
@@ -16,7 +16,8 @@ namespace blink {
NGSimplifiedOOFLayoutAlgorithm::NGSimplifiedOOFLayoutAlgorithm(
const NGLayoutAlgorithmParams& params,
const NGPhysicalBoxFragment& previous_fragment,
- bool is_new_fragment)
+ bool is_new_fragment,
+ bool should_break_for_oof)
: NGLayoutAlgorithm(params),
writing_direction_(Style().GetWritingDirection()),
incoming_break_token_(params.break_token) {
@@ -26,6 +27,31 @@ NGSimplifiedOOFLayoutAlgorithm::NGSimplifiedOOFLayoutAlgorithm(
container_builder_.SetBoxType(previous_fragment.BoxType());
container_builder_.SetFragmentBlockSize(
params.space.FragmentainerBlockSize());
+ old_fragment_break_token_ =
+ To<NGBlockBreakToken>(previous_fragment.BreakToken());
+ if (old_fragment_break_token_) {
+ bool has_column_spanner =
+ old_fragment_break_token_->IsCausedByColumnSpanner();
+ container_builder_.SetHasColumnSpanner(has_column_spanner);
+
+ // If the previous column broke for a spanner, and we are creating
+ // a new column during OOF layout, that means that the multicol hasn't
+ // finished layout yet, and we are attempting to lay out the OOF before
+ // the spanner. Make sure that the new column creates a break token in this
+ // case, even if the OOF child doesn't break. Also, copy over any child
+ // break tokens from the previous fragment to ensure that layout for those
+ // children is resumed after the spanner.
+ if (has_column_spanner && is_new_fragment) {
+ should_break_for_oof = true;
+ for (const auto* child_break_token :
+ old_fragment_break_token_->ChildBreakTokens()) {
+ if (!child_break_token->InputNode().IsOutOfFlowPositioned())
+ container_builder_.AddBreakToken(child_break_token);
+ }
+ }
+ }
+ if (should_break_for_oof)
+ container_builder_.SetDidBreakSelf();
if (incoming_break_token_)
break_token_iterator_ = incoming_break_token_->ChildBreakTokens().begin();
@@ -34,6 +60,7 @@ NGSimplifiedOOFLayoutAlgorithm::NGSimplifiedOOFLayoutAlgorithm(
if (is_new_fragment) {
child_iterator_ = children_.end();
container_builder_.SetIsFirstForNode(false);
+ old_fragment_break_token_ = nullptr;
return;
}
@@ -60,6 +87,17 @@ NGSimplifiedOOFLayoutAlgorithm::NGSimplifiedOOFLayoutAlgorithm(
}
scoped_refptr<const NGLayoutResult> NGSimplifiedOOFLayoutAlgorithm::Layout() {
+ // Any children that had previously broken due to a break before would not
+ // have been traversed via the |child_iterator_|, so their break tokens should
+ // be added before layout is completed.
+ if (old_fragment_break_token_) {
+ for (const auto* child_break_token :
+ old_fragment_break_token_->ChildBreakTokens()) {
+ if (To<NGBlockBreakToken>(child_break_token)->IsBreakBefore())
+ container_builder_.AddBreakToken(child_break_token);
+ }
+ }
+ FinishFragmentationForFragmentainer(ConstraintSpace(), &container_builder_);
return container_builder_.ToBoxFragment();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
index 7eabca6f576..cfb985d7899 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
@@ -26,7 +26,8 @@ class CORE_EXPORT NGSimplifiedOOFLayoutAlgorithm
public:
NGSimplifiedOOFLayoutAlgorithm(const NGLayoutAlgorithmParams&,
const NGPhysicalBoxFragment&,
- bool is_new_fragment);
+ bool is_new_fragment,
+ bool should_break_for_oof = false);
scoped_refptr<const NGLayoutResult> Layout() override;
MinMaxSizesResult ComputeMinMaxSizes(
@@ -47,6 +48,7 @@ class CORE_EXPORT NGSimplifiedOOFLayoutAlgorithm
base::span<const NGLink> children_;
base::span<const NGLink>::iterator child_iterator_;
const NGBlockBreakToken* incoming_break_token_;
+ const NGBlockBreakToken* old_fragment_break_token_;
base::span<const NGBreakToken* const>::iterator break_token_iterator_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.h
index ecd59629c33..b94727e18bd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_SPACE_UTILS_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc b/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
index 4a4542644d5..f223b2e3d7b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
@@ -4,10 +4,19 @@
#include "third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h"
+#include <limits>
+
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
+#include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
#include "third_party/blink/renderer/core/svg/svg_text_element.h"
namespace blink {
@@ -19,6 +28,19 @@ LayoutNGSVGText::LayoutNGSVGText(Element* element)
DCHECK(IsA<SVGTextElement>(element));
}
+void LayoutNGSVGText::StyleDidChange(StyleDifference diff,
+ const ComputedStyle* old_style) {
+ NOT_DESTROYED();
+ LayoutNGBlockFlowMixin<LayoutSVGBlock>::StyleDidChange(diff, old_style);
+ SVGResources::UpdatePaints(*GetElement(), old_style, StyleRef());
+}
+
+void LayoutNGSVGText::WillBeDestroyed() {
+ NOT_DESTROYED();
+ SVGResources::ClearPaints(*GetElement(), Style());
+ LayoutNGBlockFlowMixin<LayoutSVGBlock>::WillBeDestroyed();
+}
+
const char* LayoutNGSVGText::GetName() const {
NOT_DESTROYED();
return "LayoutNGSVGText";
@@ -64,6 +86,7 @@ void LayoutNGSVGText::SubtreeStructureChanged(
return;
SetNeedsTextMetricsUpdate();
+ LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(*this);
}
void LayoutNGSVGText::UpdateFont() {
@@ -74,6 +97,35 @@ void LayoutNGSVGText::UpdateFont() {
}
}
+void LayoutNGSVGText::Paint(const PaintInfo& paint_info) const {
+ if (paint_info.phase != PaintPhase::kForeground &&
+ paint_info.phase != PaintPhase::kForcedColorsModeBackplate &&
+ paint_info.phase != PaintPhase::kSelectionDragImage) {
+ return;
+ }
+
+ PaintInfo block_info(paint_info);
+ if (const auto* properties = FirstFragment().PaintProperties()) {
+ if (const auto* transform = properties->Transform())
+ block_info.TransformCullRect(*transform);
+ }
+ ScopedSVGTransformState transform_state(block_info, *this);
+
+ if (block_info.phase == PaintPhase::kForeground)
+ SVGModelObjectPainter::RecordHitTestData(*this, block_info);
+
+ LayoutNGBlockFlowMixin<LayoutSVGBlock>::Paint(block_info);
+
+ // Svg doesn't follow HTML PaintPhases, but is implemented with HTML classes.
+ // The nearest self-painting layer is the containing <svg> element which is
+ // painted using ReplacedPainter and ignores kDescendantOutlinesOnly.
+ // Begin a fake kOutline to paint outlines, if any.
+ if (paint_info.phase == PaintPhase::kForeground) {
+ block_info.phase = PaintPhase::kOutline;
+ LayoutNGBlockFlowMixin<LayoutSVGBlock>::Paint(block_info);
+ }
+}
+
void LayoutNGSVGText::UpdateBlockLayout(bool relayout_children) {
NOT_DESTROYED();
@@ -98,12 +150,15 @@ void LayoutNGSVGText::UpdateBlockLayout(bool relayout_children) {
needs_text_metrics_update_ = false;
}
+ FloatRect old_boundaries = ObjectBoundingBox();
+
UpdateNGBlockLayout();
needs_update_bounding_box_ = true;
- // TODO(crbug.com/1179585): Pass |bounds_changed|, and check the return value
- // of the function.
- UpdateTransformAfterLayout(true);
+ const bool bounds_changed = old_boundaries != ObjectBoundingBox();
+ // If our bounds changed, notify the parents.
+ if (UpdateTransformAfterLayout(bounds_changed) || bounds_changed)
+ SetNeedsBoundariesUpdate();
}
bool LayoutNGSVGText::IsObjectBoundingBoxValid() const {
@@ -124,7 +179,7 @@ FloatRect LayoutNGSVGText::ObjectBoundingBox() const {
if (!fragment.Items())
continue;
for (const auto& item : fragment.Items()->Items()) {
- if (item.Type() != NGFragmentItem::kSVGText)
+ if (item.Type() != NGFragmentItem::kSvgText)
continue;
// Do not use item.RectInContainerFragment() in order to avoid
// precision loss.
@@ -154,6 +209,39 @@ FloatRect LayoutNGSVGText::VisualRectInLocalSVGCoordinates() const {
return SVGLayoutSupport::ComputeVisualRectForText(*this, box);
}
+bool LayoutNGSVGText::NodeAtPoint(HitTestResult& result,
+ const HitTestLocation& hit_test_location,
+ const PhysicalOffset& accumulated_offset,
+ HitTestAction action) {
+ TransformedHitTestLocation local_location(hit_test_location,
+ LocalToSVGParentTransform());
+ return local_location &&
+ LayoutNGBlockFlowMixin<LayoutSVGBlock>::NodeAtPoint(
+ result, *local_location, accumulated_offset, action);
+}
+
+PositionWithAffinity LayoutNGSVGText::PositionForPoint(
+ const PhysicalOffset& point_in_contents) const {
+ NOT_DESTROYED();
+ FloatPoint point(point_in_contents.left, point_in_contents.top);
+ float min_distance = std::numeric_limits<float>::max();
+ const LayoutSVGInlineText* closest_inline_text = nullptr;
+ for (const LayoutObject* descendant = FirstChild(); descendant;
+ descendant = descendant->NextInPreOrder(this)) {
+ const auto* text = DynamicTo<LayoutSVGInlineText>(descendant);
+ if (!text)
+ continue;
+ float distance = descendant->ObjectBoundingBox().SquaredDistanceTo(point);
+ if (distance >= min_distance)
+ continue;
+ min_distance = distance;
+ closest_inline_text = text;
+ }
+ if (!closest_inline_text)
+ return CreatePositionWithAffinity(0);
+ return closest_inline_text->PositionForPoint(point_in_contents);
+}
+
void LayoutNGSVGText::SetNeedsPositioningValuesUpdate() {
NOT_DESTROYED();
// We resolve text layout attributes in CollectInlines().
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h
index abc5607c7ff..d02d3746882 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h
@@ -6,9 +6,14 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_LAYOUT_NG_SVG_TEXT_H_
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_block.h"
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutSVGBlock>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutSVGBlock>;
+
// The LayoutNG representation of SVG <text>.
class LayoutNGSVGText final : public LayoutNGBlockFlowMixin<LayoutSVGBlock> {
public:
@@ -32,11 +37,20 @@ class LayoutNGSVGText final : public LayoutNGBlockFlowMixin<LayoutSVGBlock> {
FloatRect ObjectBoundingBox() const override;
FloatRect StrokeBoundingBox() const override;
FloatRect VisualRectInLocalSVGCoordinates() const override;
+ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
+ void WillBeDestroyed() override;
+ bool NodeAtPoint(HitTestResult& result,
+ const HitTestLocation& hit_test_location,
+ const PhysicalOffset& accumulated_offset,
+ HitTestAction action) override;
+ PositionWithAffinity PositionForPoint(
+ const PhysicalOffset& point_in_contents) const override;
// LayoutBox override:
bool CreatesNewFormattingContext() const override;
// LayoutBlock override:
+ void Paint(const PaintInfo&) const override;
void UpdateBlockLayout(bool relayout_children) override;
void UpdateFont();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.cc b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.cc
index 5ff92409795..ada09a8f951 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.cc
@@ -9,10 +9,10 @@
namespace blink {
std::ostream& operator<<(std::ostream& ostream,
- const NGSVGCharacterData& data) {
+ const NGSvgCharacterData& data) {
if (data.HasX() || data.HasY() || data.HasDx() || data.HasDy() ||
data.HasRotate() || data.anchored_chunk) {
- ostream << "NGSVGCharacterData {";
+ ostream << "NGSvgCharacterData {";
if (data.HasX())
ostream << "x=" << data.x << " ";
if (data.HasY())
@@ -27,7 +27,7 @@ std::ostream& operator<<(std::ostream& ostream,
ostream << "anchored_chunk";
ostream << "}";
} else {
- ostream << "NGSVGCharacterData {default}";
+ ostream << "NGSvgCharacterData {default}";
}
return ostream;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h
index de13fa34beb..eef5fb2e0fe 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h
@@ -13,11 +13,11 @@ namespace blink {
// An extension of blink::SVGCharacterData for LayoutNG.
// This struct adds |anchored_chunk| data member to SVGCharacterData.
-struct NGSVGCharacterData final : public SVGCharacterData {
+struct NGSvgCharacterData final : public SVGCharacterData {
bool anchored_chunk = false;
};
-std::ostream& operator<<(std::ostream& ostream, const NGSVGCharacterData& data);
+std::ostream& operator<<(std::ostream& ostream, const NGSvgCharacterData& data);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
index 5ede83b2419..0588d59c154 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
@@ -4,84 +4,32 @@
#include "third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.h"
+#include "base/trace_event/trace_event.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/resolved_text_layout_attributes_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h"
#include "third_party/blink/renderer/core/svg/svg_animated_length.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/core/svg/svg_text_content_element.h"
namespace blink {
-namespace {
-
-// This class wraps a sparse list, |Vector<std::pair<unsigned,
-// NGSVGCharacterData>>|, so that it looks to have NGSVGCharacterData for
-// any index.
-//
-// For example, if |resolved| contains the following pairs:
-// resolved[0]: (0, NGSVGCharacterData)
-// resolved[1]: (10, NGSVGCharacterData)
-// resolved[2]: (42, NGSVGCharacterData)
-//
-// AdvanceTo(0) returns the NGSVGCharacterData at [0].
-// AdvanceTo(1 - 9) returns the default NGSVGCharacterData, which has no data.
-// AdvanceTo(10) returns the NGSVGCharacterData at [1].
-// AdvanceTo(11 - 41) returns the default NGSVGCharacterData.
-// AdvanceTo(42) returns the NGSVGCharacterData at [2].
-// AdvanceTo(43 or greater) returns the default NGSVGCharacterData.
-class ResolvedIterator final {
- public:
- explicit ResolvedIterator(
- const Vector<std::pair<unsigned, NGSVGCharacterData>>& resolved)
- : resolved_(resolved) {}
- ResolvedIterator(const ResolvedIterator&) = delete;
- ResolvedIterator& operator=(const ResolvedIterator&) = delete;
-
- const NGSVGCharacterData& AdvanceTo(unsigned addressable_index) {
- if (index_ >= resolved_.size())
- return default_data_;
- if (addressable_index < resolved_[index_].first)
- return default_data_;
- if (addressable_index == resolved_[index_].first)
- return resolved_[index_].second;
- auto* it = std::find_if(resolved_.begin() + index_, resolved_.end(),
- [addressable_index](const auto& pair) {
- return addressable_index <= pair.first;
- });
- index_ = std::distance(resolved_.begin(), it);
- return AdvanceTo(addressable_index);
- }
-
- private:
- const NGSVGCharacterData default_data_;
- const Vector<std::pair<unsigned, NGSVGCharacterData>>& resolved_;
- unsigned index_ = 0u;
-};
-
-unsigned NextCodePointOffset(StringView string, unsigned offset) {
- ++offset;
- if (offset < string.length() && U16_IS_LEAD(string[offset - 1]) &&
- U16_IS_TRAIL(string[offset]))
- ++offset;
- return offset;
-}
-
-} // anonymous namespace
-
// See https://svgwg.org/svg2-draft/text.html#TextLayoutAlgorithm
-NGSVGTextLayoutAlgorithm::NGSVGTextLayoutAlgorithm(NGInlineNode node,
+NGSvgTextLayoutAlgorithm::NGSvgTextLayoutAlgorithm(NGInlineNode node,
WritingMode writing_mode)
: inline_node_(node),
// 1.5. Let "horizontal" be a flag, true if the writing mode of ‘text’
// is horizontal, false otherwise.
horizontal_(IsHorizontalWritingMode(writing_mode)) {
- DCHECK(node.IsSVGText());
+ DCHECK(node.IsSvgText());
}
-void NGSVGTextLayoutAlgorithm::Layout(
+void NGSvgTextLayoutAlgorithm::Layout(
const String& ifc_text_content,
NGFragmentItemsBuilder::ItemWithOffsetList& items) {
+ TRACE_EVENT0("blink", "NGSvgTextLayoutAlgorithm::Layout");
// https://svgwg.org/svg2-draft/text.html#TextLayoutAlgorithm
//
// The major difference from the algorithm in the specification:
@@ -99,11 +47,12 @@ void NGSVGTextLayoutAlgorithm::Layout(
// 3. Resolve character positioning
// This was already done in PrepareLayout() step. See
- // NGSVGTextLayoutAttributesBuilder.
+ // NGSvgTextLayoutAttributesBuilder.
// Copy |rotate| and |anchored_chunk| fields.
- ResolvedIterator iterator(inline_node_.SVGCharacterDataList());
+ ResolvedTextLayoutAttributesIterator iterator(
+ inline_node_.SvgCharacterDataList());
for (wtf_size_t i = 0; i < result_.size(); ++i) {
- const NGSVGCharacterData& resolve = iterator.AdvanceTo(i);
+ const NGSvgCharacterData& resolve = iterator.AdvanceTo(i);
if (resolve.HasRotate())
result_[i].rotate = resolve.rotate;
if (resolve.anchored_chunk)
@@ -125,49 +74,10 @@ void NGSVGTextLayoutAlgorithm::Layout(
// 8. Position on path
PositionOnPath(items);
- // Write back the result to NGFragmentItems.
- for (const NGSVGPerCharacterInfo& info : result_) {
- if (info.middle)
- continue;
- NGFragmentItemsBuilder::ItemWithOffset& item = items[info.item_index];
- const auto* layout_object =
- To<LayoutSVGInlineText>(item->GetLayoutObject());
- const auto font_baseline = item->Style().GetFontBaseline();
- const auto& font_metrics =
- layout_object->ScaledFont().PrimaryFont()->GetFontMetrics();
- float x = *info.x;
- float y = *info.y;
- float width;
- float height;
- if (horizontal_) {
- y -= font_metrics.FixedAscent(font_baseline);
- width = info.inline_size;
- height = item->Size().height;
- } else {
- x -= font_metrics.FixedDescent(font_baseline);
- width = item->Size().width;
- height = info.inline_size;
- }
- FloatRect scaled_rect(x, y, width, height);
- const float scaling_factor = layout_object->ScalingFactor();
- DCHECK_NE(scaling_factor, 0.0f);
- PhysicalRect unscaled_rect(LayoutUnit(x / scaling_factor),
- LayoutUnit(y / scaling_factor),
- LayoutUnit(width / scaling_factor),
- LayoutUnit(height / scaling_factor));
- auto data = std::make_unique<NGSVGFragmentData>();
- data->shape_result = item->TextShapeResult();
- data->text_offset = item->TextOffset();
- data->rect = scaled_rect;
- data->length_adjust_scale = info.length_adjust_scale;
- data->angle = info.rotate.value_or(0.0f);
- data->baseline_shift = info.baseline_shift;
- data->in_text_path = info.in_text_path;
- item.item.ConvertToSVGText(std::move(data), unscaled_rect, info.hidden);
- }
+ WriteBackToFragmentItems(items);
}
-bool NGSVGTextLayoutAlgorithm::Setup(wtf_size_t approximate_count) {
+bool NGSvgTextLayoutAlgorithm::Setup(wtf_size_t approximate_count) {
// 1.2. Let count be the number of DOM characters within the ‘text’ element's
// subtree.
// ==> We don't use |count|. We set |addressable_count_| in the step 2.
@@ -189,7 +99,7 @@ bool NGSVGTextLayoutAlgorithm::Setup(wtf_size_t approximate_count) {
}
// This function updates |result_|.
-void NGSVGTextLayoutAlgorithm::SetFlags(
+void NGSvgTextLayoutAlgorithm::SetFlags(
const String& ifc_text_content,
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
// This function collects information per an "addressable" character in DOM
@@ -210,7 +120,7 @@ void NGSVGTextLayoutAlgorithm::SetFlags(
bool found_first_character = false;
for (wtf_size_t i : sorted_item_indexes) {
- NGSVGPerCharacterInfo info;
+ SvgPerCharacterInfo info;
info.item_index = i;
// 2.3. If the character at index i corresponds to a typographic
// character at the beginning of a line, then set the "anchored chunk"
@@ -233,7 +143,7 @@ void NGSVGTextLayoutAlgorithm::SetFlags(
logical_offset.block_offset +
font_metrics.FixedAscent(item.Style().GetFontBaseline()));
if (!horizontal_)
- offset = offset.TransposedPoint();
+ offset.Set(-offset.Y(), offset.X());
css_positions_.push_back(offset);
info.inline_size = horizontal_ ? item.Size().width : item.Size().height;
@@ -243,10 +153,10 @@ void NGSVGTextLayoutAlgorithm::SetFlags(
item.TextLength());
// 2.2. Set middle to true if the character at index i is the second or
// later character that corresponds to a typographic character.
- for (unsigned text_offset = NextCodePointOffset(item_string, 0);
+ for (unsigned text_offset = item_string.NextCodePointOffset(0);
text_offset < item_string.length();
- text_offset = NextCodePointOffset(item_string, text_offset)) {
- NGSVGPerCharacterInfo middle_info;
+ text_offset = item_string.NextCodePointOffset(text_offset)) {
+ SvgPerCharacterInfo middle_info;
middle_info.middle = true;
middle_info.item_index = info.item_index;
result_.push_back(middle_info);
@@ -256,7 +166,7 @@ void NGSVGTextLayoutAlgorithm::SetFlags(
addressable_count_ = result_.size();
}
-void NGSVGTextLayoutAlgorithm::AdjustPositionsDxDy(
+void NGSvgTextLayoutAlgorithm::AdjustPositionsDxDy(
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
// 1. Let shift be the cumulative x and y shifts due to ‘x’ and ‘y’
// attributes, initialized to (0,0).
@@ -264,9 +174,10 @@ void NGSVGTextLayoutAlgorithm::AdjustPositionsDxDy(
// attributes".
FloatPoint shift;
// 2. For each array element with index i in result:
- ResolvedIterator iterator(inline_node_.SVGCharacterDataList());
+ ResolvedTextLayoutAttributesIterator iterator(
+ inline_node_.SvgCharacterDataList());
for (wtf_size_t i = 0; i < addressable_count_; ++i) {
- const NGSVGCharacterData& resolve = iterator.AdvanceTo(i);
+ const NGSvgCharacterData& resolve = iterator.AdvanceTo(i);
// https://github.com/w3c/svgwg/issues/846
if (resolve.HasX())
shift.SetX(0.0f);
@@ -296,103 +207,13 @@ void NGSVGTextLayoutAlgorithm::AdjustPositionsDxDy(
}
}
-struct SVGTextLengthContext {
- DISALLOW_NEW();
- wtf_size_t start_index;
- const LayoutObject* layout_object;
- float text_length;
- SVGLengthAdjustType length_adjust;
-};
-
-} // namespace blink
-
-WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::SVGTextLengthContext)
-
-namespace blink {
-
-void NGSVGTextLayoutAlgorithm::ApplyTextLengthAttribute(
+void NGSvgTextLayoutAlgorithm::ApplyTextLengthAttribute(
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
- // TODO(crbug.com/1179585): Traversing LayoutObject ancestors in a layout
- // algorithm is not preferable. We should consider moving this part to
- // NGSVGTextLayoutAttributesBuilder.
-
- VectorOf<SVGTextLengthContext> context_stack;
// Start indexes of the highest textLength elements which were already
// handled by ResolveTextLength().
Vector<wtf_size_t> resolved_descendant_node_starts;
- const LayoutObject* last_parent = nullptr;
- for (wtf_size_t index = 0; index < result_.size(); ++index) {
- const LayoutObject* layout_object =
- items[result_[index].item_index]->GetLayoutObject();
- DCHECK(IsA<LayoutText>(layout_object));
- if (last_parent == layout_object->Parent())
- continue;
- last_parent = layout_object->Parent();
- auto text_length_ancestors =
- CollectTextLengthAncestors(items, index, layout_object);
-
- // Find a common part of context_stack and text_length_ancestors.
- wtf_size_t common_size = 0;
- for (const auto& ancestor : text_length_ancestors) {
- if (common_size >= context_stack.size())
- break;
- if (context_stack[common_size].layout_object != ancestor.layout_object)
- break;
- ++common_size;
- }
- // Pop uncommon part of context_stack.
- while (context_stack.size() > common_size) {
- ResolveTextLength(items, context_stack.back(), index,
- resolved_descendant_node_starts);
- context_stack.pop_back();
- }
- // Push uncommon part of text_length_ancestors.
- for (wtf_size_t p = common_size; p < text_length_ancestors.size(); ++p) {
- SVGTextLengthContext context = text_length_ancestors[p];
- context.start_index = index;
- context_stack.push_back(context);
- }
- }
- while (!context_stack.IsEmpty()) {
- ResolveTextLength(items, context_stack.back(), result_.size(),
- resolved_descendant_node_starts);
- context_stack.pop_back();
- }
-}
-
-// Collects ancestors with a valid textLength attribute up until the IFC.
-// The result is a list of pairs of scaled textLength value and LayoutObject
-// in the reversed order of distance from the specified |layout_object|.
-Vector<SVGTextLengthContext>
-NGSVGTextLayoutAlgorithm::CollectTextLengthAncestors(
- const NGFragmentItemsBuilder::ItemWithOffsetList& items,
- wtf_size_t index,
- const LayoutObject* layout_object) const {
- DCHECK(layout_object);
- VectorOf<SVGTextLengthContext> ancestors;
- do {
- layout_object = layout_object->Parent();
- if (auto* element =
- DynamicTo<SVGTextContentElement>(layout_object->GetNode())) {
- if (element->TextLengthIsSpecifiedByUser()) {
- float text_length = element->textLength()->CurrentValue()->Value(
- SVGLengthContext(element));
- // text_length is 0.0 if the textLength attribute has an invalid
- // string. Legacy SVG <text> skips textLength processing if the
- // attribute is "0" or invalid. Firefox skips textLength processing if
- // textLength value is smaller than the intrinsic width of the text.
- // This code follows the legacy behavior.
- if (text_length > 0.0f) {
- ancestors.push_back(SVGTextLengthContext{
- WTF::kNotFound, layout_object,
- text_length * ScalingFactorAt(items, index),
- element->lengthAdjust()->CurrentEnumValue()});
- }
- }
- }
- } while (layout_object != inline_node_.GetLayoutBlockFlow());
- ancestors.Reverse();
- return ancestors;
+ for (const auto& range : inline_node_.SvgTextLengthRangeList())
+ ResolveTextLength(items, range, resolved_descendant_node_starts);
}
// The implementation of step 2 of "Procedure: resolve text length"
@@ -407,12 +228,18 @@ NGSVGTextLayoutAlgorithm::CollectTextLengthAncestors(
// 1. Called for the first <tspan>.
// 2. Called for the second <tspan>.
// 3. Called for the <text>.
-void NGSVGTextLayoutAlgorithm::ResolveTextLength(
+void NGSvgTextLayoutAlgorithm::ResolveTextLength(
const NGFragmentItemsBuilder::ItemWithOffsetList& items,
- const SVGTextLengthContext& length_context,
- wtf_size_t j_plus_1,
+ const SvgTextContentRange& range,
Vector<wtf_size_t>& resolved_descendant_node_starts) {
- const wtf_size_t i = length_context.start_index;
+ const unsigned i = range.start_index;
+ const unsigned j_plus_1 = range.end_index + 1;
+ auto* element = To<SVGTextContentElement>(range.layout_object->GetNode());
+ const float text_length =
+ element->textLength()->CurrentValue()->Value(SVGLengthContext(element)) *
+ ScalingFactorAt(items, i);
+ const SVGLengthAdjustType length_adjust =
+ element->lengthAdjust()->CurrentEnumValue();
// 2.1. Let a = +Infinity and b = −Infinity.
float min_position = std::numeric_limits<float>::infinity();
@@ -420,7 +247,7 @@ void NGSVGTextLayoutAlgorithm::ResolveTextLength(
// 2.2. Let i and j be the global index of the first character and last
// characters in node, respectively.
- // ==> They are computed in ApplyTextLengthAttribute().
+ // ==> They are computed in NGTextLayoutAttributeBuilder.
// 2.3. For each index k in the range [i, j] where the "addressable" flag of
// result[k] is true:
@@ -446,19 +273,21 @@ void NGSVGTextLayoutAlgorithm::ResolveTextLength(
if (min_position == std::numeric_limits<float>::infinity())
return;
// 2.4.1. Find the distance delta = ‘textLength’ computed value − (b − a).
- const float delta =
- length_context.text_length - (max_position - min_position);
+ const float delta = text_length - (max_position - min_position);
float shift;
- if (length_context.length_adjust == kSVGLengthAdjustSpacingAndGlyphs) {
- float length_adjust_scale =
- length_context.text_length / (max_position - min_position);
+ if (length_adjust == kSVGLengthAdjustSpacingAndGlyphs) {
+ float length_adjust_scale = text_length / (max_position - min_position);
for (wtf_size_t k = i; k < j_plus_1; ++k) {
- NGSVGPerCharacterInfo& info = result_[k];
+ SvgPerCharacterInfo& info = result_[k];
+ float original_x = *info.x;
+ float original_y = *info.y;
if (horizontal_)
*info.x = min_position + (*info.x - min_position) * length_adjust_scale;
else
*info.y = min_position + (*info.y - min_position) * length_adjust_scale;
+ info.text_length_shift_x += *info.x - original_x;
+ info.text_length_shift_y += *info.y - original_y;
if (!info.middle && !info.text_length_resolved) {
info.length_adjust_scale = length_adjust_scale;
info.inline_size *= length_adjust_scale;
@@ -486,14 +315,29 @@ void NGSVGTextLayoutAlgorithm::ResolveTextLength(
// 2.4.5. Let shift = 0.
shift = 0.0f;
// 2.4.6. For each index k in the range [i,j]:
- for (wtf_size_t k = i; k < j_plus_1; ++k) {
- NGSVGPerCharacterInfo& info = result_[k];
+ // ==> This loop should run in visual order.
+ Vector<wtf_size_t> visual_indexes;
+ visual_indexes.ReserveCapacity(j_plus_1 - i);
+ for (wtf_size_t k = i; k < j_plus_1; ++k)
+ visual_indexes.push_back(k);
+ if (inline_node_.IsBidiEnabled()) {
+ std::sort(visual_indexes.begin(), visual_indexes.end(),
+ [&](wtf_size_t a, wtf_size_t b) {
+ return result_[a].item_index < result_[b].item_index;
+ });
+ }
+
+ for (wtf_size_t k : visual_indexes) {
+ SvgPerCharacterInfo& info = result_[k];
// 2.4.6.1. Add shift to the x coordinate of the position in result[k], if
// the "horizontal" flag is true, and to the y coordinate otherwise.
- if (horizontal_)
+ if (horizontal_) {
*info.x += shift;
- else
+ info.text_length_shift_x += shift;
+ } else {
*info.y += shift;
+ info.text_length_shift_y += shift;
+ }
// 2.4.6.2. If the "middle" flag for result[k] is not true and k is not a
// character in a resolved descendant node other than the first character
// then shift = shift + small-delta.
@@ -531,28 +375,47 @@ void NGSVGTextLayoutAlgorithm::ResolveTextLength(
resolved_descendant_node_starts.push_back(i);
}
-void NGSVGTextLayoutAlgorithm::AdjustPositionsXY(
+void NGSvgTextLayoutAlgorithm::AdjustPositionsXY(
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
+ // This function moves characters to
+ // <position specified by x/y attributes>
+ // + <shift specified by dx/dy attributes>
+ // + <baseline-shift done in the inline layout>
+ // css_positions_[i].Y() for horizontal_ or css_positions_[i].X() for
+ // !horizontal_ represents baseline-shift because the block offsets of the
+ // normal baseline is 0.
+
// 1. Let shift be the current adjustment due to the ‘x’ and ‘y’ attributes,
// initialized to (0,0).
FloatPoint shift;
// 2. Set index = 1.
// 3. While index < count:
// 3.5. Set index to index + 1.
- ResolvedIterator iterator(inline_node_.SVGCharacterDataList());
+ ResolvedTextLayoutAttributesIterator iterator(
+ inline_node_.SvgCharacterDataList());
for (wtf_size_t i = 0; i < result_.size(); ++i) {
const float scaling_factor = ScalingFactorAt(items, i);
- const NGSVGCharacterData& resolve = iterator.AdvanceTo(i);
+ const NGSvgCharacterData& resolve = iterator.AdvanceTo(i);
// 3.1. If resolved_x[index] is set, then let
// shift.x = resolved_x[index] − result.x[index].
// https://github.com/w3c/svgwg/issues/845
- if (resolve.HasX())
- shift.SetX(resolve.x * scaling_factor - css_positions_[i].X());
+ if (resolve.HasX()) {
+ shift.SetX(resolve.x * scaling_factor - css_positions_[i].X() -
+ result_[i].text_length_shift_x);
+ // Take into account of baseline-shift.
+ if (!horizontal_)
+ shift.SetX(shift.X() + css_positions_[i].X());
+ }
// 3.2. If resolved_y[index] is set, then let
// shift.y = resolved_y[index] − result.y[index].
// https://github.com/w3c/svgwg/issues/845
- if (resolve.HasY())
- shift.SetY(resolve.y * scaling_factor - css_positions_[i].Y());
+ if (resolve.HasY()) {
+ shift.SetY(resolve.y * scaling_factor - css_positions_[i].Y() -
+ result_[i].text_length_shift_y);
+ // Take into account of baseline-shift.
+ if (horizontal_)
+ shift.SetY(shift.Y() + css_positions_[i].Y());
+ }
// If this character is the first one in a <textPath>, reset the
// block-direction shift.
@@ -580,7 +443,7 @@ void NGSVGTextLayoutAlgorithm::AdjustPositionsXY(
}
}
-void NGSVGTextLayoutAlgorithm::ApplyAnchoring(
+void NGSvgTextLayoutAlgorithm::ApplyAnchoring(
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
DCHECK_GT(result_.size(), 0u);
DCHECK(result_[0].anchored_chunk);
@@ -593,17 +456,16 @@ void NGSVGTextLayoutAlgorithm::ApplyAnchoring(
auto* next_anchor =
std::find_if(result_.begin() + i + 1, result_.end(),
[](const auto& info) { return info.anchored_chunk; });
- wtf_size_t j = std::distance(result_.begin(), next_anchor) - 1;
+ wtf_size_t j = static_cast<wtf_size_t>(
+ std::distance(result_.begin(), next_anchor) - 1);
- const auto& text_path_ranges = inline_node_.SVGTextPathRangeList();
+ const auto& text_path_ranges = inline_node_.SvgTextPathRangeList();
const auto* text_path_iter =
std::find_if(text_path_ranges.begin(), text_path_ranges.end(),
[i](const auto& range) {
return range.start_index <= i && i <= range.end_index;
});
- bool in_text_path = false;
if (text_path_iter != text_path_ranges.end()) {
- in_text_path = true;
// Anchoring should be scoped within the <textPath>.
// Non-anchored text following <textPath> will be handled in
// PositionOnPath().
@@ -679,9 +541,9 @@ void NGSVGTextLayoutAlgorithm::ApplyAnchoring(
}
}
-void NGSVGTextLayoutAlgorithm::PositionOnPath(
+void NGSvgTextLayoutAlgorithm::PositionOnPath(
const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
- const auto& ranges = inline_node_.SVGTextPathRangeList();
+ const auto& ranges = inline_node_.SvgTextPathRangeList();
if (ranges.IsEmpty())
return;
@@ -706,8 +568,10 @@ void NGSVGTextLayoutAlgorithm::PositionOnPath(
if (range_index < ranges.size() &&
index >= ranges[range_index].start_index &&
index <= ranges[range_index].end_index) {
- if (!in_path)
- path_mapper = ranges[range_index].layout_svg_text_path->LayoutPath();
+ if (!in_path) {
+ path_mapper = To<LayoutSVGTextPath>(ranges[range_index].layout_object)
+ ->LayoutPath();
+ }
// 5.1.1. Set "in path" flag to true.
in_path = true;
info.in_text_path = true;
@@ -724,9 +588,6 @@ void NGSVGTextLayoutAlgorithm::PositionOnPath(
// 'right', then reverse path.
// ==> We don't support 'side' attribute yet.
- // 5.1.2.3. Let length be the length of path.
- const float length = path_mapper->length();
-
// 5.1.2.4. Let offset be the value of the ‘textPath’ element's
// ‘startOffset’ attribute, adjusted due to any ‘pathLength’
// attribute on the referenced element.
@@ -747,6 +608,7 @@ void NGSVGTextLayoutAlgorithm::PositionOnPath(
scaling_factor +
offset;
+ // 5.1.2.3. Let length be the length of path.
// 5.1.2.9. If path is a closed subpath depending on the values of
// text-anchor and direction of the element the character at index is
// in:
@@ -759,32 +621,9 @@ void NGSVGTextLayoutAlgorithm::PositionOnPath(
// -> (start, rtl) or (end, ltr)
// If mid−offset < −length or mid−offset > 0, set the "hidden"
// flag of result[index] to true.
- const ComputedStyle& style =
- items[result_[index].item_index]->Style();
- const bool is_ltr = style.IsLeftToRightDirection();
- const float mid_offset = mid - offset;
- switch (style.TextAnchor()) {
- default:
- NOTREACHED();
- FALLTHROUGH;
- case ETextAnchor::kStart:
- if (is_ltr) {
- info.hidden = mid_offset < 0 || mid_offset > length;
- } else {
- info.hidden = mid_offset < -length || mid_offset > 0;
- }
- break;
- case ETextAnchor::kEnd:
- if (is_ltr) {
- info.hidden = mid_offset < -length || mid_offset > 0;
- } else {
- info.hidden = mid_offset < 0 || mid_offset > length;
- }
- break;
- case ETextAnchor::kMiddle:
- info.hidden = mid_offset < -length / 2 || mid_offset > length / 2;
- break;
- }
+ //
+ // ==> Major browsers don't support the special handling for closed
+ // paths.
// 5.1.2.10. If the hidden flag is false:
if (!info.hidden) {
@@ -895,22 +734,75 @@ void NGSVGTextLayoutAlgorithm::PositionOnPath(
}
}
-float NGSVGTextLayoutAlgorithm::ScalingFactorAt(
+void NGSvgTextLayoutAlgorithm::WriteBackToFragmentItems(
+ NGFragmentItemsBuilder::ItemWithOffsetList& items) {
+ FloatRect unscaled_visual_rect;
+ for (const SvgPerCharacterInfo& info : result_) {
+ if (info.middle)
+ continue;
+ NGFragmentItemsBuilder::ItemWithOffset& item = items[info.item_index];
+ const auto* layout_object =
+ To<LayoutSVGInlineText>(item->GetLayoutObject());
+ const auto font_baseline = item->Style().GetFontBaseline();
+ const auto& font_metrics =
+ layout_object->ScaledFont().PrimaryFont()->GetFontMetrics();
+ float x = *info.x;
+ float y = *info.y;
+ float width;
+ float height;
+ if (horizontal_) {
+ y -= font_metrics.FixedAscent(font_baseline);
+ width = info.inline_size;
+ height = item->Size().height;
+ } else {
+ x -= font_metrics.FixedDescent(font_baseline);
+ width = item->Size().width;
+ height = info.inline_size;
+ }
+ FloatRect scaled_rect(x, y, width, height);
+ const float scaling_factor = layout_object->ScalingFactor();
+ DCHECK_NE(scaling_factor, 0.0f);
+ FloatRect unscaled_rect = scaled_rect;
+ unscaled_rect.Scale(1 / scaling_factor);
+ auto data = std::make_unique<NGSvgFragmentData>();
+ data->shape_result = item->TextShapeResult();
+ data->text_offset = item->TextOffset();
+ data->rect = scaled_rect;
+ data->length_adjust_scale = info.length_adjust_scale;
+ data->angle = info.rotate.value_or(0.0f);
+ data->baseline_shift = info.baseline_shift;
+ data->in_text_path = info.in_text_path;
+ item.item.ConvertToSvgText(std::move(data),
+ PhysicalRect::EnclosingRect(unscaled_rect),
+ info.hidden);
+ unscaled_visual_rect.Unite(item.item.ObjectBoundingBox());
+ }
+ if (items[0]->Type() == NGFragmentItem::kLine) {
+ items[0].item.SetSvgLineLocalRect(
+ PhysicalRect(EnclosingIntRect(unscaled_visual_rect)));
+ }
+ // |items| should not have kLine items other than the first one.
+ DCHECK_EQ(std::find_if(items.begin() + 1, items.end(),
+ [](const auto& item) {
+ return item->Type() == NGFragmentItem::kLine;
+ }),
+ items.end());
+}
+
+float NGSvgTextLayoutAlgorithm::ScalingFactorAt(
const NGFragmentItemsBuilder::ItemWithOffsetList& items,
wtf_size_t addressable_index) const {
- return To<LayoutSVGInlineText>(
- items[result_[addressable_index].item_index]->GetLayoutObject())
- ->ScalingFactor();
+ return items[result_[addressable_index].item_index]->SvgScalingFactor();
}
-bool NGSVGTextLayoutAlgorithm::IsFirstCharacterInTextPath(
+bool NGSvgTextLayoutAlgorithm::IsFirstCharacterInTextPath(
wtf_size_t index) const {
if (!result_[index].anchored_chunk)
return false;
// This implementation is O(N) where N is the number of <textPath>s in
// a <text>. If this function is a performance bottleneck, we should add
- // |first_in_text_path| flag to NGSVGCharacterData.
- const auto& text_path_ranges = inline_node_.SVGTextPathRangeList();
+ // |first_in_text_path| flag to NGSvgCharacterData.
+ const auto& text_path_ranges = inline_node_.SvgTextPathRangeList();
return std::find_if(text_path_ranges.begin(), text_path_ranges.end(),
[index](const auto& range) {
return range.start_index == index;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.h
index f4d679ff6f0..98af100f971 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.h
@@ -5,17 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_NG_SVG_TEXT_LAYOUT_ALGORITHM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_NG_SVG_TEXT_LAYOUT_ALGORITHM_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
namespace blink {
-struct SVGTextLengthContext;
+struct SvgTextContentRange;
-class NGSVGTextLayoutAlgorithm {
+class NGSvgTextLayoutAlgorithm {
STACK_ALLOCATED();
public:
- NGSVGTextLayoutAlgorithm(NGInlineNode node, WritingMode writing_mode);
+ NGSvgTextLayoutAlgorithm(NGInlineNode node, WritingMode writing_mode);
// Apply SVG specific text layout algorithm to |items|.
// Text items in |items| will be converted to kSVGText type.
@@ -31,20 +32,18 @@ class NGSVGTextLayoutAlgorithm {
const NGFragmentItemsBuilder::ItemWithOffsetList& items);
void ApplyTextLengthAttribute(
const NGFragmentItemsBuilder::ItemWithOffsetList& items);
- Vector<SVGTextLengthContext> CollectTextLengthAncestors(
- const NGFragmentItemsBuilder::ItemWithOffsetList& items,
- wtf_size_t index,
- const LayoutObject* layout_object) const;
void ResolveTextLength(
const NGFragmentItemsBuilder::ItemWithOffsetList& items,
- const SVGTextLengthContext& length_context,
- wtf_size_t j_plus_1,
+ const SvgTextContentRange& range,
Vector<wtf_size_t>& resolved_descendant_node_starts);
void AdjustPositionsXY(
const NGFragmentItemsBuilder::ItemWithOffsetList& items);
void ApplyAnchoring(const NGFragmentItemsBuilder::ItemWithOffsetList& items);
void PositionOnPath(const NGFragmentItemsBuilder::ItemWithOffsetList& items);
+ void WriteBackToFragmentItems(
+ NGFragmentItemsBuilder::ItemWithOffsetList& items);
+
float ScalingFactorAt(const NGFragmentItemsBuilder::ItemWithOffsetList& items,
wtf_size_t addressable_index) const;
bool IsFirstCharacterInTextPath(wtf_size_t index) const;
@@ -58,7 +57,7 @@ class NGSVGTextLayoutAlgorithm {
// "horizontal" flag defined in the specification.
bool horizontal_;
- struct NGSVGPerCharacterInfo {
+ struct SvgPerCharacterInfo {
absl::optional<float> x;
absl::optional<float> y;
absl::optional<float> rotate;
@@ -71,11 +70,13 @@ class NGSVGTextLayoutAlgorithm {
float baseline_shift = 0.0f;
float inline_size = 0.0f;
float length_adjust_scale = 1.0f;
+ float text_length_shift_x = 0.0f;
+ float text_length_shift_y = 0.0f;
wtf_size_t item_index = WTF::kNotFound;
};
// This data member represents "result" defined in the specification, but it
// contains only addressable characters.
- Vector<NGSVGPerCharacterInfo> result_;
+ Vector<SvgPerCharacterInfo> result_;
// This data member represents "CSS_positions" defined in the specification,
// but it contains only addressable characters.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.cc
index 6d410aaa54b..5bd2840716f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.cc
@@ -8,12 +8,26 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
+#include "third_party/blink/renderer/core/svg/svg_animated_length.h"
#include "third_party/blink/renderer/core/svg/svg_animated_length_list.h"
#include "third_party/blink/renderer/core/svg/svg_animated_number_list.h"
#include "third_party/blink/renderer/core/svg/svg_text_positioning_element.h"
namespace blink {
+struct SVGTextLengthContext {
+ DISALLOW_NEW();
+
+ const LayoutObject* layout_object;
+ unsigned start_index;
+};
+
+} // namespace blink
+
+WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::SVGTextLengthContext)
+
+namespace blink {
+
namespace {
// Iterates over x/y/dx/dy/rotate attributes on an SVGTextPositioningElement.
@@ -180,14 +194,31 @@ class LayoutAttributesStack final {
HeapVector<Member<LayoutAttributesIterator>> stack_;
};
-bool HasUpdated(const NGSVGCharacterData& data) {
+bool HasUpdated(const NGSvgCharacterData& data) {
return data.HasX() || data.HasY() || data.HasDx() || data.HasDy() ||
data.HasRotate() || data.anchored_chunk;
}
+bool HasValidTextLength(const LayoutObject& layout_object) {
+ if (auto* element =
+ DynamicTo<SVGTextContentElement>(layout_object.GetNode())) {
+ if (element->TextLengthIsSpecifiedByUser()) {
+ float text_length = element->textLength()->CurrentValue()->Value(
+ SVGLengthContext(element));
+ // text_length is 0.0 if the textLength attribute has an invalid
+ // string. Legacy SVG <text> skips textLength processing if the
+ // attribute is "0" or invalid. Firefox skips textLength processing if
+ // textLength value is smaller than the intrinsic width of the text.
+ // This code follows the legacy behavior.
+ return text_length > 0.0f;
+ }
+ }
+ return false;
+}
+
} // anonymous namespace
-NGSVGTextLayoutAttributesBuilder::NGSVGTextLayoutAttributesBuilder(
+NGSvgTextLayoutAttributesBuilder::NGSvgTextLayoutAttributesBuilder(
NGInlineNode ifc)
: block_flow_(To<LayoutBlockFlow>(ifc.GetLayoutBox())) {}
@@ -198,10 +229,11 @@ NGSVGTextLayoutAttributesBuilder::NGSVGTextLayoutAttributesBuilder(
// resolve_dy, "rotate" of result[], and "anchored chunk" of result[].
//
// [1]: https://svgwg.org/svg2-draft/text.html#TextLayoutAlgorithm
-void NGSVGTextLayoutAttributesBuilder::Build(
+void NGSvgTextLayoutAttributesBuilder::Build(
const String& ifc_text_content,
const Vector<NGInlineItem>& items) {
LayoutAttributesStack attr_stack;
+ Vector<SVGTextLengthContext> text_length_stack;
unsigned addressable_index = 0;
bool is_first_char = true;
bool in_text_path = false;
@@ -211,6 +243,10 @@ void NGSVGTextLayoutAttributesBuilder::Build(
IsHorizontalWritingMode(block_flow_->StyleRef().GetWritingMode());
attr_stack.Push(*block_flow_, in_text_path);
+ if (HasValidTextLength(*block_flow_)) {
+ text_length_stack.push_back(
+ SVGTextLengthContext{block_flow_, addressable_index});
+ }
for (const auto& item : items) {
const LayoutObject* object = item.GetLayoutObject();
@@ -224,6 +260,10 @@ void NGSVGTextLayoutAttributesBuilder::Build(
in_text_path = true;
text_path_start = addressable_index;
}
+ if (HasValidTextLength(*object)) {
+ text_length_stack.push_back(
+ SVGTextLengthContext{object, addressable_index});
+ }
} else if (item.Type() == NGInlineItem::kCloseTag) {
if (object->IsSVGTSpan()) {
@@ -235,12 +275,18 @@ void NGSVGTextLayoutAttributesBuilder::Build(
first_char_in_text_path = false;
DCHECK(text_path_start);
if (addressable_index != *text_path_start) {
- text_path_range_list_.push_back(
- SVGTextPathRange{To<LayoutSVGTextPath>(object), *text_path_start,
- addressable_index - 1});
+ text_path_range_list_.push_back(SvgTextContentRange{
+ object, *text_path_start, addressable_index - 1});
}
text_path_start.reset();
}
+ if (text_length_stack.size() > 0u &&
+ text_length_stack.back().layout_object == object) {
+ text_length_range_list_.push_back(
+ SvgTextContentRange{object, text_length_stack.back().start_index,
+ addressable_index - 1});
+ text_length_stack.pop_back();
+ }
} else if (item.Type() != NGInlineItem::kText) {
continue;
@@ -248,7 +294,7 @@ void NGSVGTextLayoutAttributesBuilder::Build(
StringView item_string(ifc_text_content, item.StartOffset(), item.Length());
for (unsigned i = 0; i < item.Length();) {
- NGSVGCharacterData data;
+ NGSvgCharacterData data;
// 2.2. Set the "anchored chunk" flag of result[index] to true.
// 1.6.1.1. If i < new_check_count, then set the "anchored chunk" flag
@@ -320,21 +366,31 @@ void NGSVGTextLayoutAttributesBuilder::Build(
resolved_.push_back(std::make_pair(addressable_index, data));
++addressable_index;
attr_stack.Advance();
- i += i + 1 < item.Length() && U16_IS_LEAD(item_string[i]) &&
- U16_IS_TRAIL(item_string[i + 1])
- ? 2
- : 1;
+ i = item_string.NextCodePointOffset(i);
}
}
+ if (text_length_stack.size() > 0u) {
+ DCHECK_EQ(text_length_stack.back().layout_object, block_flow_);
+ DCHECK_EQ(text_length_stack.back().start_index, 0u);
+ text_length_range_list_.push_back(
+ SvgTextContentRange{block_flow_, 0u, addressable_index - 1});
+ text_length_stack.pop_back();
+ }
attr_stack.Pop();
}
-Vector<std::pair<unsigned, NGSVGCharacterData>>
-NGSVGTextLayoutAttributesBuilder::CharacterDataList() {
+Vector<std::pair<unsigned, NGSvgCharacterData>>
+NGSvgTextLayoutAttributesBuilder::CharacterDataList() {
return std::move(resolved_);
}
-Vector<SVGTextPathRange> NGSVGTextLayoutAttributesBuilder::TextPathRangeList() {
+Vector<SvgTextContentRange>
+NGSvgTextLayoutAttributesBuilder::TextLengthRangeList() {
+ return std::move(text_length_range_list_);
+}
+
+Vector<SvgTextContentRange>
+NGSvgTextLayoutAttributesBuilder::TextPathRangeList() {
return std::move(text_path_range_list_);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.h
index 7c038c9450b..14f6a23fcb7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_attributes_builder.h
@@ -23,34 +23,46 @@ class NGInlineNode;
// than during the SVG text layout algorithm because we'd like to use the
// result of this class in NGInlineNode::CollectInlines().
//
+// Also, this is responsible to make lists of index ranges for <textPath> and
+// textLength.
+//
// [1] https://svgwg.org/svg2-draft/text.html#TextLayoutAlgorithm
-class NGSVGTextLayoutAttributesBuilder final {
+class NGSvgTextLayoutAttributesBuilder final {
STACK_ALLOCATED();
public:
- explicit NGSVGTextLayoutAttributesBuilder(NGInlineNode ifc);
+ explicit NGSvgTextLayoutAttributesBuilder(NGInlineNode ifc);
void Build(const String& ifc_text_content, const Vector<NGInlineItem>& items);
// This function can be called just once after Build().
- Vector<std::pair<unsigned, NGSVGCharacterData>> CharacterDataList();
+ Vector<std::pair<unsigned, NGSvgCharacterData>> CharacterDataList();
+ // This function can be called just once after Build().
+ Vector<SvgTextContentRange> TextLengthRangeList();
// This function can be called just once after Build().
- Vector<SVGTextPathRange> TextPathRangeList();
+ Vector<SvgTextContentRange> TextPathRangeList();
private:
LayoutBlockFlow* block_flow_;
// The result of Build().
// A list of a pair of addressable character index and an
- // NGSVGCharacterData. This is named 'resolved' because this is
+ // NGSvgCharacterData. This is named 'resolved' because this is
// the outcome of '3. Resolve character positioning'.
- Vector<std::pair<unsigned, NGSVGCharacterData>> resolved_;
+ Vector<std::pair<unsigned, NGSvgCharacterData>> resolved_;
+
+ // The result of Build().
+ // A list of a pair of start addressable character index and end
+ // addressable character index (inclusive) for an SVGTextContentElement
+ // with textLength.
+ // This is used in "5. Apply ‘textLength’ attribute".
+ Vector<SvgTextContentRange> text_length_range_list_;
// The result of Build().
// A list of a pair of start addressable character index and end
// addressable character index (inclusive) for a <textPath>.
// This is used in "8. Position on path".
- Vector<SVGTextPathRange> text_path_range_list_;
+ Vector<SvgTextContentRange> text_path_range_list_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.cc b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.cc
new file mode 100644
index 00000000000..acd4049d0a8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.cc
@@ -0,0 +1,342 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.h"
+
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
+
+namespace blink {
+
+namespace {
+
+unsigned CodePointLength(StringView string) {
+ unsigned count = 0;
+ for (unsigned text_offset = 0; text_offset < string.length();
+ text_offset = string.NextCodePointOffset(text_offset)) {
+ ++count;
+ }
+ return count;
+}
+
+unsigned CodePointOffsetToCodeUnitOffset(StringView string,
+ unsigned point_offset) {
+ unsigned unit_offset = 0;
+ for (unsigned point_count = 0; point_count < point_offset; ++point_count) {
+ unit_offset = string.NextCodePointOffset(unit_offset);
+ }
+ return unit_offset;
+}
+
+std::tuple<Vector<const NGFragmentItem*>, const NGFragmentItems*>
+FragmentItemsInVisualOrder(const LayoutObject& query_root) {
+ Vector<const NGFragmentItem*> item_list;
+ const NGFragmentItems* items = nullptr;
+ if (query_root.IsNGSVGText()) {
+ DCHECK_LE(To<LayoutBox>(query_root).PhysicalFragmentCount(), 1u);
+ for (const auto& fragment : To<LayoutBox>(query_root).PhysicalFragments()) {
+ if (!fragment.Items())
+ continue;
+ items = fragment.Items();
+ for (const auto& item : fragment.Items()->Items()) {
+ if (item.Type() == NGFragmentItem::kSvgText)
+ item_list.push_back(&item);
+ }
+ }
+ } else {
+ DCHECK(query_root.IsInLayoutNGInlineFormattingContext());
+ NGInlineCursor cursor;
+ cursor.MoveToIncludingCulledInline(query_root);
+ items = &cursor.Items();
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ if (item.Type() == NGFragmentItem::kSvgText) {
+ item_list.push_back(&item);
+ } else if (NGInlineCursor descendants = cursor.CursorForDescendants()) {
+ if (descendants.CurrentItem()->Type() == NGFragmentItem::kSvgText)
+ item_list.push_back(descendants.CurrentItem());
+ }
+ }
+ }
+ return std::tie(item_list, items);
+}
+
+std::tuple<Vector<const NGFragmentItem*>, const NGFragmentItems*>
+FragmentItemsInLogicalOrder(const LayoutObject& query_root) {
+ auto items_tuple = FragmentItemsInVisualOrder(query_root);
+ auto& item_list = std::get<0>(items_tuple);
+ // Sort |item_list| in the logical order.
+ std::sort(item_list.begin(), item_list.end(),
+ [](const NGFragmentItem* a, const NGFragmentItem* b) {
+ return a->StartOffset() < b->StartOffset();
+ });
+ return items_tuple;
+}
+
+// Returns a tuple of NGFragmentItem, Item text, IFC text offset for |index|,
+// and the next IFC text offset.
+std::tuple<const NGFragmentItem*, StringView, unsigned, unsigned>
+FindFragmentItemForAddressableCharacterIndex(const LayoutObject& query_root,
+ unsigned index) {
+ Vector<const NGFragmentItem*> item_list;
+ const NGFragmentItems* items;
+ std::tie(item_list, items) = FragmentItemsInLogicalOrder(query_root);
+
+ unsigned character_index = 0;
+ for (const auto* item : item_list) {
+ const StringView item_text = item->Text(*items);
+ for (unsigned i = 0; i < item_text.length();
+ i = item_text.NextCodePointOffset(i)) {
+ if (character_index == index) {
+ return {item, item_text, item->StartOffset() + i,
+ item->StartOffset() + item_text.NextCodePointOffset(i)};
+ }
+ ++character_index;
+ }
+ }
+ return {nullptr, StringView(), WTF::kNotFound, WTF::kNotFound};
+}
+
+void GetCanvasRotation(void* context,
+ unsigned,
+ Glyph,
+ FloatSize,
+ float,
+ bool,
+ CanvasRotationInVertical rotation,
+ const SimpleFontData*) {
+ auto* canvas_rotation = static_cast<CanvasRotationInVertical*>(context);
+ *canvas_rotation = rotation;
+}
+
+float InlineSize(const NGFragmentItem& item,
+ StringView item_text,
+ unsigned start_code_point_offset,
+ unsigned end_code_point_offset) {
+ unsigned start_ifc_offset =
+ item.StartOffset() +
+ CodePointOffsetToCodeUnitOffset(item_text, start_code_point_offset);
+ unsigned end_ifc_offset =
+ item.StartOffset() +
+ CodePointOffsetToCodeUnitOffset(item_text, end_code_point_offset);
+ PhysicalRect r = item.LocalRect(item_text, start_ifc_offset, end_ifc_offset);
+ return (item.IsHorizontal() ? r.Width() : r.Height()) *
+ item.SvgFragmentData()->length_adjust_scale / item.SvgScalingFactor();
+}
+
+std::tuple<const NGFragmentItem*, FloatRect> ScaledCharacterRectInContainer(
+ const LayoutObject& query_root,
+ unsigned code_point_index) {
+ const NGFragmentItem* item;
+ unsigned start_ifc_offset, end_ifc_offset;
+ StringView item_text;
+ std::tie(item, item_text, start_ifc_offset, end_ifc_offset) =
+ FindFragmentItemForAddressableCharacterIndex(query_root,
+ code_point_index);
+ DCHECK(item);
+ DCHECK_EQ(item->Type(), NGFragmentItem::kSvgText);
+ if (item->IsHiddenForPaint())
+ return {item, FloatRect()};
+ auto char_rect =
+ FloatRect(item->LocalRect(item_text, start_ifc_offset, end_ifc_offset));
+ char_rect.MoveBy(item->SvgFragmentData()->rect.Location());
+ return {item, char_rect};
+}
+
+} // namespace
+
+unsigned NGSvgTextQuery::NumberOfCharacters() const {
+ Vector<const NGFragmentItem*> item_list;
+ const NGFragmentItems* items;
+ std::tie(item_list, items) = FragmentItemsInLogicalOrder(query_root_);
+
+ unsigned addressable_character_count = 0;
+ for (const auto* item : item_list)
+ addressable_character_count += CodePointLength(item->Text(*items));
+ return addressable_character_count;
+}
+
+float NGSvgTextQuery::SubStringLength(unsigned start_index,
+ unsigned length) const {
+ Vector<const NGFragmentItem*> item_list;
+ const NGFragmentItems* items;
+ std::tie(item_list, items) = FragmentItemsInLogicalOrder(query_root_);
+
+ float total_length = 0.0f;
+ // Starting addressable character index for the current NGFragmentItem.
+ unsigned character_index = 0;
+ const unsigned end_index = start_index + length;
+ for (const auto* item : item_list) {
+ if (end_index <= character_index)
+ break;
+ StringView item_text = item->Text(*items);
+ unsigned next_character_index =
+ character_index + CodePointLength(item_text);
+ if ((character_index <= start_index &&
+ start_index < next_character_index) ||
+ (character_index < end_index && end_index <= next_character_index) ||
+ (start_index < character_index && next_character_index < end_index)) {
+ total_length += InlineSize(
+ *item, item_text,
+ start_index < character_index ? 0 : start_index - character_index,
+ std::min(end_index, next_character_index) - character_index);
+ }
+ character_index = next_character_index;
+ }
+ return total_length;
+}
+
+FloatPoint NGSvgTextQuery::StartPositionOfCharacter(unsigned index) const {
+ const NGFragmentItem* item;
+ FloatRect char_rect;
+ std::tie(item, char_rect) =
+ ScaledCharacterRectInContainer(query_root_, index);
+ DCHECK_EQ(item->Type(), NGFragmentItem::kSvgText);
+ if (item->IsHiddenForPaint())
+ return FloatPoint();
+ const auto& inline_text = *To<LayoutSVGInlineText>(item->GetLayoutObject());
+ const float ascent =
+ inline_text.ScaledFont().PrimaryFont()->GetFontMetrics().FloatAscent(
+ item->Style().GetFontBaseline());
+ const bool is_ltr = IsLtr(item->ResolvedDirection());
+ FloatPoint point;
+ if (item->IsHorizontal()) {
+ point = is_ltr ? char_rect.Location() : char_rect.MaxXMinYCorner();
+ point.Move(0.0f, ascent);
+ } else {
+ point = is_ltr ? char_rect.MaxXMinYCorner() : char_rect.MaxXMaxYCorner();
+ point.Move(-ascent, 0.0f);
+ }
+ if (item->HasSvgTransformForPaint())
+ point = item->BuildSvgTransformForPaint().MapPoint(point);
+ const float scaling_factor = inline_text.ScalingFactor();
+ point.Scale(1 / scaling_factor, 1 / scaling_factor);
+ return point;
+}
+
+FloatPoint NGSvgTextQuery::EndPositionOfCharacter(unsigned index) const {
+ const NGFragmentItem* item;
+ FloatRect char_rect;
+ std::tie(item, char_rect) =
+ ScaledCharacterRectInContainer(query_root_, index);
+ DCHECK_EQ(item->Type(), NGFragmentItem::kSvgText);
+ if (item->IsHiddenForPaint())
+ return FloatPoint();
+ const auto& inline_text = *To<LayoutSVGInlineText>(item->GetLayoutObject());
+ const float ascent =
+ inline_text.ScaledFont().PrimaryFont()->GetFontMetrics().FloatAscent(
+ item->Style().GetFontBaseline());
+ const bool is_ltr = IsLtr(item->ResolvedDirection());
+ FloatPoint point;
+ if (item->IsHorizontal()) {
+ point = is_ltr ? char_rect.MaxXMinYCorner() : char_rect.Location();
+ point.Move(0.0f, ascent);
+ } else {
+ point = is_ltr ? char_rect.MaxXMaxYCorner() : char_rect.MaxXMinYCorner();
+ point.Move(-ascent, 0.0f);
+ }
+ if (item->HasSvgTransformForPaint())
+ point = item->BuildSvgTransformForPaint().MapPoint(point);
+ const float scaling_factor = inline_text.ScalingFactor();
+ point.Scale(1 / scaling_factor, 1 / scaling_factor);
+ return point;
+}
+
+FloatRect NGSvgTextQuery::ExtentOfCharacter(unsigned index) const {
+ const NGFragmentItem* item;
+ FloatRect char_rect;
+ std::tie(item, char_rect) =
+ ScaledCharacterRectInContainer(query_root_, index);
+ DCHECK_EQ(item->Type(), NGFragmentItem::kSvgText);
+ if (item->IsHiddenForPaint())
+ return FloatRect();
+ if (item->HasSvgTransformForPaint())
+ char_rect = item->BuildSvgTransformForPaint().MapRect(char_rect);
+ char_rect.Scale(1 / item->SvgScalingFactor());
+ return char_rect;
+}
+
+float NGSvgTextQuery::RotationOfCharacter(unsigned index) const {
+ const NGFragmentItem* item;
+ unsigned start_ifc_offset, end_ifc_offset;
+ StringView item_text;
+ std::tie(item, item_text, start_ifc_offset, end_ifc_offset) =
+ FindFragmentItemForAddressableCharacterIndex(query_root_, index);
+ DCHECK(item);
+ DCHECK_EQ(item->Type(), NGFragmentItem::kSvgText);
+ if (item->IsHiddenForPaint())
+ return 0.0f;
+ float rotation = item->SvgFragmentData()->angle;
+ if (item->Style().IsHorizontalWritingMode())
+ return rotation;
+ ETextOrientation orientation = item->Style().GetTextOrientation();
+ if (orientation == ETextOrientation::kUpright)
+ return rotation;
+ if (orientation == ETextOrientation::kSideways)
+ return rotation + 90.0f;
+ DCHECK_EQ(orientation, ETextOrientation::kMixed);
+ CanvasRotationInVertical canvas_rotation;
+ // GetCanvasRotation() is called only once because a pair of
+ // start_ifc_offset and end_ifc_offset represents a single glyph.
+ item->TextShapeResult()->ForEachGlyph(0, start_ifc_offset, end_ifc_offset, 0,
+ GetCanvasRotation, &canvas_rotation);
+ if (IsCanvasRotationInVerticalUpright(canvas_rotation))
+ return rotation;
+ return rotation + 90.0f;
+}
+
+// https://svgwg.org/svg2-draft/text.html#__svg__SVGTextContentElement__getCharNumAtPosition
+int NGSvgTextQuery::CharacterNumberAtPosition(
+ const FloatPoint& position) const {
+ // The specification says we should do hit-testing in logical order.
+ // However, this does it in visual order in order to match to the legacy SVG
+ // <text> behavior.
+ Vector<const NGFragmentItem*> item_list;
+ const NGFragmentItems* items;
+ std::tie(item_list, items) = FragmentItemsInVisualOrder(query_root_);
+
+ const NGFragmentItem* hit_item = nullptr;
+ for (const auto* item : item_list) {
+ if (!item->IsHiddenForPaint() && item->Contains(position)) {
+ hit_item = item;
+ break;
+ }
+ }
+ if (!hit_item)
+ return -1;
+
+ // Count code points before |hit_item|.
+ std::sort(item_list.begin(), item_list.end(),
+ [](const NGFragmentItem* a, const NGFragmentItem* b) {
+ return a->StartOffset() < b->StartOffset();
+ });
+ unsigned addressable_character_count = 0;
+ for (const auto* item : item_list) {
+ if (item == hit_item)
+ break;
+ addressable_character_count += CodePointLength(item->Text(*items));
+ }
+
+ PhysicalOffset transformed_point =
+ hit_item->MapPointInContainer(
+ PhysicalOffset::FromFloatPointRound(position)) -
+ hit_item->OffsetInContainerFragment();
+ // NGFragmentItem::TextOffsetForPoint() is not suitable here because it
+ // returns an offset for the nearest glyph edge.
+ unsigned offset_in_item =
+ hit_item->TextShapeResult()->CreateShapeResult()->OffsetForPosition(
+ hit_item->ScaleInlineOffset(hit_item->IsHorizontal()
+ ? transformed_point.left
+ : transformed_point.top),
+ BreakGlyphs);
+ return addressable_character_count +
+ CodePointLength(StringView(hit_item->Text(*items), 0, offset_in_item));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.h
new file mode 100644
index 00000000000..24cf7755eb4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.h
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_NG_SVG_TEXT_QUERY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_NG_SVG_TEXT_QUERY_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class FloatPoint;
+class FloatRect;
+class LayoutObject;
+
+// An NG version of blink::SVGTextQuery, which is an implementation of SVG DOM
+// functions to retrieve text geometry.
+class NGSvgTextQuery {
+ STACK_ALLOCATED();
+
+ public:
+ explicit NGSvgTextQuery(LayoutObject& query_root) : query_root_(query_root) {}
+
+ unsigned NumberOfCharacters() const;
+ float SubStringLength(unsigned start_index, unsigned length) const;
+ FloatPoint StartPositionOfCharacter(unsigned index) const;
+ FloatPoint EndPositionOfCharacter(unsigned index) const;
+ FloatRect ExtentOfCharacter(unsigned index) const;
+ float RotationOfCharacter(unsigned index) const;
+ int CharacterNumberAtPosition(const FloatPoint& position) const;
+
+ private:
+ LayoutObject& query_root_;
+};
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/resolved_text_layout_attributes_iterator.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/resolved_text_layout_attributes_iterator.h
new file mode 100644
index 00000000000..c210a404b86
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/resolved_text_layout_attributes_iterator.h
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_RESOLVED_TEXT_LAYOUT_ATTRIBUTES_ITERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_RESOLVED_TEXT_LAYOUT_ATTRIBUTES_ITERATOR_H_
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+#include "third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+// This class wraps a sparse list, |Vector<std::pair<unsigned,
+// NGSvgCharacterData>>|, so that it looks to have NGSvgCharacterData for
+// any index.
+//
+// For example, if |resolved| contains the following pairs:
+// resolved[0]: (0, NGSvgCharacterData)
+// resolved[1]: (10, NGSvgCharacterData)
+// resolved[2]: (42, NGSvgCharacterData)
+//
+// AdvanceTo(0) returns the NGSvgCharacterData at [0].
+// AdvanceTo(1 - 9) returns the default NGSvgCharacterData, which has no data.
+// AdvanceTo(10) returns the NGSvgCharacterData at [1].
+// AdvanceTo(11 - 41) returns the default NGSvgCharacterData.
+// AdvanceTo(42) returns the NGSvgCharacterData at [2].
+// AdvanceTo(43 or greater) returns the default NGSvgCharacterData.
+class ResolvedTextLayoutAttributesIterator final {
+ public:
+ explicit ResolvedTextLayoutAttributesIterator(
+ const Vector<std::pair<unsigned, NGSvgCharacterData>>& resolved)
+ : resolved_(resolved) {}
+ ResolvedTextLayoutAttributesIterator(
+ const ResolvedTextLayoutAttributesIterator&) = delete;
+ ResolvedTextLayoutAttributesIterator& operator=(
+ const ResolvedTextLayoutAttributesIterator&) = delete;
+
+ const NGSvgCharacterData& AdvanceTo(unsigned addressable_index) {
+ if (index_ >= resolved_.size())
+ return default_data_;
+ if (addressable_index < resolved_[index_].first)
+ return default_data_;
+ if (addressable_index == resolved_[index_].first)
+ return resolved_[index_].second;
+ auto* it = std::find_if(resolved_.begin() + index_, resolved_.end(),
+ [addressable_index](const auto& pair) {
+ return addressable_index <= pair.first;
+ });
+ index_ = static_cast<wtf_size_t>(std::distance(resolved_.begin(), it));
+ return AdvanceTo(addressable_index);
+ }
+
+ private:
+ const NGSvgCharacterData default_data_;
+ const Vector<std::pair<unsigned, NGSvgCharacterData>>& resolved_;
+ wtf_size_t index_ = 0u;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_RESOLVED_TEXT_LAYOUT_ATTRIBUTES_ITERATOR_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h b/chromium/third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h
index 5ba58fffce5..7c63f21de9c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/svg/svg_inline_node_data.h
@@ -6,30 +6,39 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_SVG_SVG_INLINE_NODE_DATA_H_
#include "third_party/blink/renderer/core/layout/ng/svg/ng_svg_character_data.h"
-#include "third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-struct SVGTextPathRange {
+class LayoutObject;
+class LayoutText;
+
+struct SvgTextContentRange {
DISALLOW_NEW();
- const LayoutSVGTextPath* layout_svg_text_path;
+ // This must be a LayoutSVGTextPath for |SVGInlineNodeData::
+ // text_path_range_list|, and must be a LayoutObject for SVGTextContentElement
+ // for SVGInlineNodeData::text_length_range_list
+ const LayoutObject* layout_object;
unsigned start_index;
unsigned end_index;
};
} // namespace blink
-WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::SVGTextPathRange)
+WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::SvgTextContentRange)
namespace blink {
+using SvgTextChunkOffsets = HashMap<const LayoutText*, Vector<unsigned>>;
+
// SVG-specific data stored in NGInlineNodeData.
-struct SVGInlineNodeData final {
- Vector<std::pair<unsigned, NGSVGCharacterData>> character_data_list;
- Vector<SVGTextPathRange> text_path_range_list;
+struct SvgInlineNodeData final {
+ Vector<std::pair<unsigned, NGSvgCharacterData>> character_data_list;
+ Vector<SvgTextContentRange> text_length_range_list;
+ Vector<SvgTextContentRange> text_path_range_list;
+ SvgTextChunkOffsets chunk_offsets;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
index b86bbc8863d..91ec2886457 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
@@ -12,7 +12,9 @@
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_interface.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.h"
@@ -95,6 +97,8 @@ void LayoutNGTable::TableGridStructureChanged() {
NOT_DESTROYED();
// Callers must ensure table layout gets invalidated.
InvalidateCachedTableBorders();
+ if (StyleRef().BorderCollapse() == EBorderCollapse::kCollapse)
+ SetShouldDoFullPaintInvalidation(PaintInvalidationReason::kStyle);
}
bool LayoutNGTable::HasBackgroundForPaint() const {
@@ -263,13 +267,6 @@ void LayoutNGTable::AddVisualEffectOverflow() {
}
#endif
-void LayoutNGTable::Paint(const PaintInfo& paint_info) const {
- NOT_DESTROYED();
- DCHECK_EQ(PhysicalFragmentCount(), 1u);
- NGBoxFragmentPainter(*LayoutNGMixin<LayoutBlock>::GetPhysicalFragment(0))
- .Paint(paint_info);
-}
-
LayoutUnit LayoutNGTable::BorderLeft() const {
NOT_DESTROYED();
// DCHECK(cached_table_borders_.get())
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
index a6a8767c0a8..1d441e51db4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
@@ -7,8 +7,7 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.h"
@@ -32,7 +31,7 @@ class NGTableBorders;
// on LayoutObject. They are invalidated inside
// LayoutObject::SetNeeds*Layout.
-class CORE_EXPORT LayoutNGTable : public LayoutNGMixin<LayoutBlock>,
+class CORE_EXPORT LayoutNGTable : public LayoutNGBlock,
public LayoutNGTableInterface {
public:
explicit LayoutNGTable(Element*);
@@ -91,8 +90,6 @@ class CORE_EXPORT LayoutNGTable : public LayoutNGMixin<LayoutBlock>,
LayoutBox* CreateAnonymousBoxWithSameTypeAs(
const LayoutObject* parent) const override;
- void Paint(const PaintInfo&) const final;
-
LayoutUnit BorderTop() const override;
LayoutUnit BorderBottom() const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
index 7d8a907e54d..f62eaa20b0f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
@@ -14,6 +14,11 @@ namespace blink {
class LayoutNGTableInterface;
class NGPhysicalFragment;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutTableCaption>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGMixin<LayoutTableCaption>;
+
class CORE_EXPORT LayoutNGTableCaption final
: public LayoutNGBlockFlowMixin<LayoutTableCaption> {
public:
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h
index 71c8579f8d5..ccbb074a093 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h
@@ -11,6 +11,11 @@
namespace blink {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutTableCell>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGMixin<LayoutTableCell>;
+
// This is a LayoutNG variant of LayoutTableCell.
// There are 3 table cell classes in Chrome
// LayoutNGTableCell - TablesNG cell, whole table is NG.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
index edd56cef89d..b28bbad2a6b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
index 4f1f82d2ce7..96bb6968162 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
@@ -7,8 +7,9 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h"
namespace blink {
@@ -18,7 +19,7 @@ class LayoutNGTable;
// NOTE:
// Legacy table row inherits from LayoutBox, not LayoutBlock.
// Every child of LayoutNGTableRow must be LayoutNGTableCell.
-class CORE_EXPORT LayoutNGTableRow : public LayoutNGMixin<LayoutBlock>,
+class CORE_EXPORT LayoutNGTableRow : public LayoutNGBlock,
public LayoutNGTableRowInterface {
public:
explicit LayoutNGTableRow(Element*);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h
index 6e2580c57e5..014c7022040 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h
@@ -13,6 +13,7 @@ class LayoutObject;
class LayoutNGTableInterface;
class LayoutNGTableSectionInterface;
class LayoutNGTableCellInterface;
+class LayoutTableRow;
// Abstract class defining table row methods.
// Used for Legacy/NG interoperability.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
index a80d5599b7a..ed3a833e99f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
@@ -6,8 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_SECTION_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h"
namespace blink {
@@ -16,7 +15,7 @@ class LayoutNGTable;
// NOTE:
// Every child of LayoutNGTableSection must be LayoutNGTableRow.
-class CORE_EXPORT LayoutNGTableSection : public LayoutNGMixin<LayoutBlock>,
+class CORE_EXPORT LayoutNGTableSection : public LayoutNGBlock,
public LayoutNGTableSectionInterface {
public:
explicit LayoutNGTableSection(Element*);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc
index 30b2bce1965..da34d5e5b6b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc
@@ -43,73 +43,6 @@ bool IsSourceMoreSpecificThanEdge(EBorderStyle source_style,
return source_style > edge_border_style;
}
-// Side of the style the collapsed border belongs to.
-enum class LogicalEdgeSide { kInlineStart, kInlineEnd, kBlockStart, kBlockEnd };
-
-NGTableBorders::EdgeSide LogicalEdgeToPhysical(
- LogicalEdgeSide logical_side,
- WritingDirectionMode table_writing_direction) {
- // https://www.w3.org/TR/css-writing-modes-4/#logical-to-physical
- switch (logical_side) {
- case LogicalEdgeSide::kInlineStart:
- switch (table_writing_direction.GetWritingMode()) {
- case WritingMode::kHorizontalTb:
- return table_writing_direction.Direction() == TextDirection::kLtr
- ? NGTableBorders::EdgeSide::kLeft
- : NGTableBorders::EdgeSide::kRight;
- case WritingMode::kVerticalLr:
- case WritingMode::kVerticalRl:
- case WritingMode::kSidewaysRl:
- return table_writing_direction.Direction() == TextDirection::kLtr
- ? NGTableBorders::EdgeSide::kTop
- : NGTableBorders::EdgeSide::kBottom;
- case WritingMode::kSidewaysLr:
- return table_writing_direction.Direction() == TextDirection::kLtr
- ? NGTableBorders::EdgeSide::kBottom
- : NGTableBorders::EdgeSide::kTop;
- }
- case LogicalEdgeSide::kInlineEnd:
- switch (table_writing_direction.GetWritingMode()) {
- case WritingMode::kHorizontalTb:
- return table_writing_direction.Direction() == TextDirection::kLtr
- ? NGTableBorders::EdgeSide::kRight
- : NGTableBorders::EdgeSide::kLeft;
- case WritingMode::kVerticalLr:
- case WritingMode::kVerticalRl:
- case WritingMode::kSidewaysRl:
- return table_writing_direction.Direction() == TextDirection::kLtr
- ? NGTableBorders::EdgeSide::kBottom
- : NGTableBorders::EdgeSide::kTop;
- case WritingMode::kSidewaysLr:
- return table_writing_direction.Direction() == TextDirection::kLtr
- ? NGTableBorders::EdgeSide::kTop
- : NGTableBorders::EdgeSide::kBottom;
- }
- case LogicalEdgeSide::kBlockStart:
- switch (table_writing_direction.GetWritingMode()) {
- case WritingMode::kHorizontalTb:
- return NGTableBorders::EdgeSide::kTop;
- case WritingMode::kVerticalLr:
- case WritingMode::kSidewaysLr:
- return NGTableBorders::EdgeSide::kLeft;
- case WritingMode::kVerticalRl:
- case WritingMode::kSidewaysRl:
- return NGTableBorders::EdgeSide::kRight;
- }
- case LogicalEdgeSide::kBlockEnd:
- switch (table_writing_direction.GetWritingMode()) {
- case WritingMode::kHorizontalTb:
- return NGTableBorders::EdgeSide::kBottom;
- case WritingMode::kVerticalLr:
- case WritingMode::kSidewaysLr:
- return NGTableBorders::EdgeSide::kRight;
- case WritingMode::kVerticalRl:
- case WritingMode::kSidewaysRl:
- return NGTableBorders::EdgeSide::kLeft;
- }
- }
-}
-
class ColBordersMarker {
STACK_ALLOCATED();
@@ -575,22 +508,20 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row,
EnsureCellRowFits(cell_start_row + clamped_rowspan - 1);
}
}
+
+ PhysicalToLogical<EdgeSide> edge_side(table_writing_direction, EdgeSide::kTop,
+ EdgeSide::kRight, EdgeSide::kBottom,
+ EdgeSide::kLeft);
MergeRowAxisBorder(cell_start_row, cell_start_column, clamped_colspan,
- source_style, box_order,
- LogicalEdgeToPhysical(LogicalEdgeSide::kBlockStart,
- table_writing_direction));
+ source_style, box_order, edge_side.BlockStart());
MergeRowAxisBorder(cell_start_row + clamped_rowspan, cell_start_column,
clamped_colspan, source_style, box_order,
- LogicalEdgeToPhysical(LogicalEdgeSide::kBlockEnd,
- table_writing_direction));
+ edge_side.BlockEnd());
MergeColumnAxisBorder(cell_start_row, cell_start_column, clamped_rowspan,
- source_style, box_order,
- LogicalEdgeToPhysical(LogicalEdgeSide::kInlineStart,
- table_writing_direction));
+ source_style, box_order, edge_side.InlineStart());
MergeColumnAxisBorder(cell_start_row, cell_start_column + clamped_colspan,
clamped_rowspan, source_style, box_order,
- LogicalEdgeToPhysical(LogicalEdgeSide::kInlineEnd,
- table_writing_direction));
+ edge_side.InlineEnd());
if (mark_inner_borders) {
MarkInnerBordersAsDoNotFill(cell_start_row, cell_start_column,
clamped_rowspan, clamped_colspan);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h
index eb511df8368..ed5589394b4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h
@@ -7,6 +7,7 @@
#include "base/dcheck_is_on.h"
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/platform/geometry/layout_unit.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
index a08545a90ad..1468774fe8c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -5,9 +5,11 @@
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.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_out_of_flow_layout_part.h"
@@ -26,6 +28,8 @@
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_node.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
+#include "third_party/blink/renderer/core/mathml/mathml_element.h"
+#include "third_party/blink/renderer/core/mathml_names.h"
namespace blink {
@@ -58,7 +62,7 @@ void ComputeCaptionFragments(
const ComputedStyle& table_style,
const NGTableGroupedChildren& grouped_children,
const LayoutUnit table_inline_size,
- Vector<NGTableLayoutAlgorithm::CaptionResult>& captions,
+ Vector<NGTableLayoutAlgorithm::CaptionResult>* captions,
LayoutUnit& captions_block_size) {
const LogicalSize available_size = {table_inline_size, kIndefiniteSize};
for (NGBlockNode caption : grouped_children.captions) {
@@ -70,9 +74,15 @@ void ComputeCaptionFragments(
SetOrthogonalFallbackInlineSizeIfNeeded(table_style, caption, &builder);
builder.SetAvailableSize(available_size);
builder.SetPercentageResolutionSize(available_size);
- builder.SetStretchInlineSizeIfAuto(true);
+ builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchImplicit);
NGConstraintSpace caption_constraint_space = builder.ToConstraintSpace();
+ // If we are discarding the results (compute-only) and we are after layout
+ // (|!NeedsLayout|,) make sure not to update the cached layout results.
+ absl::optional<NGDisableSideEffectsScope> disable_side_effects;
+ if (!captions && !caption.GetLayoutBox()->NeedsLayout())
+ disable_side_effects.emplace();
+
scoped_refptr<const NGLayoutResult> caption_result =
caption.Layout(caption_constraint_space);
NGFragment fragment(table_constraint_space.GetWritingDirection(),
@@ -82,9 +92,11 @@ void ComputeCaptionFragments(
ResolveInlineMargins(caption_style, table_style, table_inline_size,
fragment.InlineSize(), &margins);
- captions.push_back(NGTableLayoutAlgorithm::CaptionResult{
- caption, std::move(caption_result), margins});
captions_block_size += fragment.BlockSize() + margins.BlockSum();
+ if (captions) {
+ captions->push_back(NGTableLayoutAlgorithm::CaptionResult{
+ caption, std::move(caption_result), margins});
+ }
}
}
@@ -119,7 +131,7 @@ LayoutUnit ComputeEmptyTableInlineSize(
const bool has_collapsed_borders) {
// If table has a css inline size, use that.
if (space.IsFixedInlineSize() ||
- (space.StretchInlineSizeIfAuto() &&
+ (space.IsInlineAutoBehaviorStretch() &&
table_style.LogicalWidth().IsAuto()) ||
!table_style.LogicalWidth().IsAuto() ||
!table_style.LogicalMinWidth().IsAuto()) {
@@ -437,12 +449,12 @@ LayoutUnit NGTableLayoutAlgorithm::ComputeCaptionBlockSize(
const NGTableNode& node,
const NGConstraintSpace& space,
const LayoutUnit table_inline_size) {
- Vector<NGTableLayoutAlgorithm::CaptionResult> captions;
NGTableGroupedChildren grouped_children(node);
LayoutUnit captions_block_size;
ComputeCaptionFragments(space, node.Style(), grouped_children,
- table_inline_size, captions, captions_block_size);
+ table_inline_size, /* captions */ nullptr,
+ captions_block_size);
return captions_block_size;
}
@@ -510,7 +522,7 @@ scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::Layout() {
Vector<CaptionResult> captions;
LayoutUnit captions_block_size;
ComputeCaptionFragments(ConstraintSpace(), Style(), grouped_children,
- container_builder_.InlineSize(), captions,
+ container_builder_.InlineSize(), &captions,
captions_block_size);
NGTableTypes::Rows rows;
@@ -632,7 +644,7 @@ void NGTableLayoutAlgorithm::ComputeRows(
}
LayoutUnit css_table_block_size;
- if (ConstraintSpace().IsFixedBlockSizeIndefinite() &&
+ if (ConstraintSpace().IsInitialBlockSizeIndefinite() &&
!ConstraintSpace().IsFixedBlockSize()) {
// We get here when a flexbox wants to use the table's intrinsic height as
// an input to the flex algorithm.
@@ -801,10 +813,18 @@ scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::GenerateFragment(
NGConstraintSpaceBuilder section_space_builder(
table_writing_direction.GetWritingMode(), table_writing_direction,
/* is_new_fc */ true);
- section_space_builder.SetAvailableSize(
- {section_available_inline_size, sections[section_index].block_size});
+
+ LogicalSize available_size = {section_available_inline_size,
+ kIndefiniteSize};
+
+ // Sections without rows can receive redistributed height from the table.
+ if (constraint_space_data->sections[section_index].rowspan == 0) {
+ section_space_builder.SetIsFixedBlockSize(true);
+ available_size.block_size = sections[section_index].block_size;
+ }
+
+ section_space_builder.SetAvailableSize(available_size);
section_space_builder.SetIsFixedInlineSize(true);
- section_space_builder.SetIsFixedBlockSize(true);
section_space_builder.SetPercentageResolutionSize(
{section_available_inline_size, kIndefiniteSize});
section_space_builder.SetTableSectionData(constraint_space_data,
@@ -878,6 +898,9 @@ scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::GenerateFragment(
grid_converter.ToPhysical(table_grid_rect),
border_spacing, column_block_size);
+ if (Node().GetDOMNode() &&
+ Node().GetDOMNode()->HasTagName(mathml_names::kMtableTag))
+ table_baseline = MathTableBaseline(Style(), block_offset);
if (table_baseline)
container_builder_.SetBaseline(*table_baseline);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc
index 23e0a287cf3..499b76401d3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc
@@ -13,11 +13,15 @@ namespace {
// Implements spec distribution algorithm:
// https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm
+// |treat_target_size_as_constrained| constrained target can grow fixed-width
+// columns. unconstrained target cannot grow fixed-width columns beyond
+// specified size.
Vector<LayoutUnit> DistributeInlineSizeToComputedInlineSizeAuto(
LayoutUnit target_inline_size,
LayoutUnit inline_border_spacing,
const NGTableTypes::Column* start_column,
- const NGTableTypes::Column* end_column) {
+ const NGTableTypes::Column* end_column,
+ const bool treat_target_size_as_constrained) {
unsigned all_columns_count = 0;
unsigned percent_columns_count = 0;
unsigned fixed_columns_count = 0;
@@ -263,7 +267,7 @@ Vector<LayoutUnit> DistributeInlineSizeToComputedInlineSizeAuto(
DCHECK(last_computed_size);
*last_computed_size += rounding_error_inline_size;
}
- } else if (fixed_columns_count > 0) {
+ } else if (fixed_columns_count > 0 && treat_target_size_as_constrained) {
// Grow fixed columns if available.
LayoutUnit rounding_error_inline_size = distributable_inline_size;
LayoutUnit* last_computed_size = nullptr;
@@ -304,9 +308,8 @@ Vector<LayoutUnit> DistributeInlineSizeToComputedInlineSizeAuto(
LayoutUnit* computed_size = computed_sizes.begin();
for (const NGTableTypes::Column* column = start_column;
column != end_column; ++column, ++computed_size) {
- if (column->is_mergeable)
+ if (column->is_mergeable || !column->percent)
continue;
- DCHECK(column->percent);
last_computed_size = computed_size;
LayoutUnit percent_inline_size =
column->ResolvePercentInlineSize(target_inline_size);
@@ -321,8 +324,7 @@ Vector<LayoutUnit> DistributeInlineSizeToComputedInlineSizeAuto(
rounding_error_inline_size -= delta;
*computed_size = percent_inline_size + delta;
}
- if (rounding_error_inline_size != LayoutUnit()) {
- DCHECK(last_computed_size);
+ if (rounding_error_inline_size != LayoutUnit() && last_computed_size) {
*last_computed_size += rounding_error_inline_size;
}
}
@@ -351,7 +353,6 @@ Vector<LayoutUnit> SynchronizeAssignableTableInlineSizeAndColumnsFixed(
return column.is_constrained && column.max_inline_size == LayoutUnit();
};
- float total_percent = 0.0f;
LayoutUnit total_percent_inline_size;
LayoutUnit total_auto_max_inline_size;
LayoutUnit total_fixed_inline_size;
@@ -362,7 +363,6 @@ Vector<LayoutUnit> SynchronizeAssignableTableInlineSizeAndColumnsFixed(
all_columns_count++;
if (column.percent) {
percent_columns_count++;
- total_percent += *column.percent;
total_percent_inline_size +=
column.ResolvePercentInlineSize(target_inline_size);
} else if (TreatAsFixed(column)) {
@@ -661,9 +661,9 @@ void DistributeColspanCellToColumnsAuto(
column->max_inline_size = LayoutUnit();
}
Vector<LayoutUnit> computed_sizes =
- DistributeInlineSizeToComputedInlineSizeAuto(colspan_cell_min_inline_size,
- inline_border_spacing,
- start_column, end_column);
+ DistributeInlineSizeToComputedInlineSizeAuto(
+ colspan_cell_min_inline_size, inline_border_spacing, start_column,
+ end_column, true);
LayoutUnit* computed_size = computed_sizes.begin();
for (NGTableTypes::Column* column = start_column; column != end_column;
++column, ++computed_size) {
@@ -672,12 +672,14 @@ void DistributeColspanCellToColumnsAuto(
}
computed_sizes = DistributeInlineSizeToComputedInlineSizeAuto(
colspan_cell_max_inline_size, inline_border_spacing, start_column,
- end_column);
+ end_column, /* treat_target_size_as_constrained */
+ colspan_cell.cell_inline_constraint.is_constrained);
computed_size = computed_sizes.begin();
for (NGTableTypes::Column* column = start_column; column != end_column;
++column, ++computed_size) {
column->max_inline_size =
- std::max(*column->max_inline_size, *computed_size);
+ std::max(std::max(*column->min_inline_size, *column->max_inline_size),
+ *computed_size);
}
}
@@ -730,10 +732,12 @@ void DistributeExcessBlockSizeToRows(
row->has_rowspan_start;
};
- auto IsEmptyRow = [](const NGTableTypes::Row* row) {
- return row->block_size == LayoutUnit() &&
- (!row->percent || *row->percent == 0);
- };
+ auto IsEmptyRow =
+ [&percentage_resolution_block_size](const NGTableTypes::Row* row) {
+ bool is_percent = percentage_resolution_block_size != kIndefiniteSize &&
+ row->percent && *row->percent != 0;
+ return row->block_size == LayoutUnit() && !is_percent;
+ };
unsigned percent_rows_with_deficit_count = 0;
unsigned rows_with_originating_rowspan = 0;
@@ -1042,7 +1046,7 @@ NGTableAlgorithmHelpers::SynchronizeAssignableTableInlineSizeAndColumns(
start_column + column_constraints.data.size();
return DistributeInlineSizeToComputedInlineSizeAuto(
assignable_table_inline_size, inline_border_spacing, start_column,
- end_column);
+ end_column, /* treat_target_size_as_constrained */ true);
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
index 8551bd9371f..49b1ef31923 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
@@ -197,7 +197,7 @@ NGTableTypes::Row ComputeMinimumRowBlockSize(
table_writing_direction, cell, cell_borders,
{cell_inline_size, kIndefiniteSize}, cell_percentage_inline_size,
/* alignment_baseline */ absl::nullopt, start_column,
- /* is_fixed_block_size_indefinite */ false,
+ /* is_initial_block_size_indefinite */ true,
is_table_block_size_specified,
/* is_hidden_for_paint */ false, has_collapsed_borders,
NGCacheSlot::kMeasure);
@@ -210,7 +210,6 @@ NGTableTypes::Row ComputeMinimumRowBlockSize(
LayoutUnit max_cell_block_size;
absl::optional<float> row_percent;
bool is_constrained = false;
- bool is_empty = true;
bool has_rowspan_start = false;
wtf_size_t start_cell_index = cell_block_constraints->size();
NGRowBaselineTabulator row_baseline_tabulator;
@@ -218,7 +217,6 @@ NGTableTypes::Row ComputeMinimumRowBlockSize(
// Gather block sizes of all cells.
for (NGBlockNode cell = To<NGBlockNode>(row.FirstChild()); cell;
cell = To<NGBlockNode>(cell.NextSibling())) {
- is_empty = false;
colspan_cell_tabulator->FindNextFreeColumn();
const ComputedStyle& cell_style = cell.Style();
const NGBoxStrut cell_borders = table_borders.CellBorder(
@@ -461,7 +459,7 @@ NGConstraintSpace NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
LayoutUnit percentage_inline_size,
absl::optional<LayoutUnit> alignment_baseline,
wtf_size_t column_index,
- bool is_fixed_block_size_indefinite,
+ bool is_initial_block_size_indefinite,
bool is_table_block_size_specified,
bool is_hidden_for_paint,
bool has_collapsed_borders,
@@ -482,10 +480,9 @@ NGConstraintSpace NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
builder.SetAvailableSize(cell_size);
builder.SetIsFixedInlineSize(true);
- if (cell_size.block_size != kIndefiniteSize) {
+ if (cell_size.block_size != kIndefiniteSize)
builder.SetIsFixedBlockSize(true);
- builder.SetIsFixedBlockSizeIndefinite(is_fixed_block_size_indefinite);
- }
+ builder.SetIsInitialBlockSizeIndefinite(is_initial_block_size_indefinite);
// Standard:
// https://www.w3.org/TR/css-tables-3/#computing-the-table-height "the
@@ -497,7 +494,7 @@ NGConstraintSpace NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
builder.SetTableCellAlignmentBaseline(alignment_baseline);
builder.SetTableCellColumnIndex(column_index);
builder.SetIsRestrictedBlockSizeTableCell(
- is_table_block_size_specified || !cell_style.LogicalHeight().IsAuto());
+ is_table_block_size_specified || cell_style.LogicalHeight().IsFixed());
builder.SetIsTableCellHiddenForPaint(is_hidden_for_paint);
builder.SetIsTableCellWithCollapsedBorders(has_collapsed_borders);
builder.SetHideTableCellIfEmpty(
@@ -552,7 +549,7 @@ NGTableAlgorithmUtils::ComputeColumnConstraints(
bool is_first_section = true;
wtf_size_t row_index = 0;
wtf_size_t section_index = 0;
- for (const NGBlockNode& section : grouped_children) {
+ for (NGBlockNode section : grouped_children) {
if (!section.IsEmptyTableSection()) {
ComputeSectionInlineConstraints(
section, is_fixed_layout, is_first_section, table_writing_mode,
@@ -572,7 +569,7 @@ NGTableAlgorithmUtils::ComputeColumnConstraints(
void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes(
const NGBlockNode& section,
const LayoutUnit cell_percentage_inline_size,
- const bool is_table_block_size_restricted,
+ const bool is_table_block_size_specified,
const NGTableTypes::ColumnLocations& column_locations,
const NGTableBorders& table_borders,
const LayoutUnit block_border_spacing,
@@ -594,7 +591,7 @@ void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes(
row = To<NGBlockNode>(row.NextSibling())) {
colspan_cell_tabulator.StartRow();
NGTableTypes::Row row_constraint = ComputeMinimumRowBlockSize(
- row, cell_percentage_inline_size, is_table_block_size_restricted,
+ row, cell_percentage_inline_size, is_table_block_size_specified,
column_locations, table_borders, current_row++, section_index,
/* is_section_collapsed */ section.Style().Visibility() ==
EVisibility::kCollapse,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h
index 9b13752c46c..4b91e6178b4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_NG_TABLE_LAYOUT_ALGORITHM_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_NG_TABLE_LAYOUT_ALGORITHM_UTILS_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
@@ -41,7 +42,7 @@ class NGTableAlgorithmUtils {
LayoutUnit percentage_inline_size,
absl::optional<LayoutUnit> alignment_baseline,
wtf_size_t column_index,
- bool is_fixed_block_size_indefinite,
+ bool is_initial_block_size_indefinite,
bool is_restricted_block_size_table,
bool is_hidden_for_paint,
bool has_collapsed_borders,
@@ -60,7 +61,7 @@ class NGTableAlgorithmUtils {
static void ComputeSectionMinimumRowBlockSizes(
const NGBlockNode& section,
const LayoutUnit cell_percentage_resolution_inline_size,
- const bool is_restricted_block_size_table,
+ const bool is_table_block_size_specified,
const NGTableTypes::ColumnLocations& column_locations,
const NGTableBorders& table_borders,
const LayoutUnit block_border_spacing,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc
index 15825bdae0a..eb13896a4d0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc
@@ -60,7 +60,7 @@ scoped_refptr<const NGLayoutResult> NGTableRowLayoutAlgorithm::Layout() {
// Our initial block-size is definite if this cell has a fixed block-size,
// or we have grown and the table has a specified block-size.
- bool is_fixed_block_size_definite =
+ const bool is_initial_block_size_definite =
cell_data.is_constrained ||
(cell_data.has_grown && table_data.is_table_block_size_specified);
@@ -71,7 +71,7 @@ scoped_refptr<const NGLayoutResult> NGTableRowLayoutAlgorithm::Layout() {
return NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
table_data.table_writing_direction, cell, cell_data.border_box_borders,
{cell_inline_size, cell_block_size}, container_builder_.InlineSize(),
- row_baseline, start_column, !is_fixed_block_size_definite,
+ row_baseline, start_column, !is_initial_block_size_definite,
table_data.is_table_block_size_specified, is_hidden_for_paint,
table_data.has_collapsed_borders, NGCacheSlot::kLayout);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
index 61d7a8fddc7..55dc9d646e3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
@@ -33,6 +33,8 @@ scoped_refptr<const NGLayoutResult> NGTableSectionLayoutAlgorithm::Layout() {
absl::optional<LayoutUnit> section_baseline;
+ const LogicalSize available_size = {container_builder_.InlineSize(),
+ kIndefiniteSize};
LogicalOffset offset;
bool is_first_row = true;
wtf_size_t row_index = table_data.sections[section_index].start_row_index;
@@ -44,12 +46,9 @@ scoped_refptr<const NGLayoutResult> NGTableSectionLayoutAlgorithm::Layout() {
table_data.table_writing_direction.GetWritingMode(),
table_data.table_writing_direction,
/* is_new_fc */ true);
- row_space_builder.SetAvailableSize({container_builder_.InlineSize(),
- table_data.rows[row_index].block_size});
+ row_space_builder.SetAvailableSize(available_size);
+ row_space_builder.SetPercentageResolutionSize(available_size);
row_space_builder.SetIsFixedInlineSize(true);
- row_space_builder.SetIsFixedBlockSize(true);
- row_space_builder.SetPercentageResolutionSize(
- {container_builder_.InlineSize(), kIndefiniteSize});
row_space_builder.SetTableRowData(&table_data, row_index);
NGConstraintSpace row_space = row_space_builder.ToConstraintSpace();
scoped_refptr<const NGLayoutResult> row_result = row.Layout(row_space);
@@ -66,9 +65,9 @@ scoped_refptr<const NGLayoutResult> NGTableSectionLayoutAlgorithm::Layout() {
is_first_row = false;
row_index++;
}
- if (table_data.sections[section_index].rowspan == 0) {
- // Sections without rows can get redistributed height from table.
- DCHECK(ConstraintSpace().IsFixedBlockSize());
+ if (ConstraintSpace().IsFixedBlockSize()) {
+ // A fixed block-size should only occur for a section without children.
+ DCHECK_EQ(table_data.sections[section_index].rowspan, 0u);
container_builder_.SetFragmentBlockSize(
ConstraintSpace().AvailableSize().block_size);
} else {
diff --git a/chromium/third_party/blink/renderer/core/layout/overflow_model.h b/chromium/third_party/blink/renderer/core/layout/overflow_model.h
index 0785e0ca108..6d32f8ef8d9 100644
--- a/chromium/third_party/blink/renderer/core/layout/overflow_model.h
+++ b/chromium/third_party/blink/renderer/core/layout/overflow_model.h
@@ -22,6 +22,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_OVERFLOW_MODEL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_OVERFLOW_MODEL_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
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 0494502f815..8e937cfe61c 100644
--- a/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -8,6 +8,7 @@
#include <memory>
#include "third_party/blink/renderer/core/css/css_markup.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/nth_index_cache.h"
@@ -24,6 +25,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/wtf/bloom_filter.h"
namespace blink {
@@ -326,7 +328,6 @@ ScrollAnchor::ExamineResult ScrollAnchor::Examine(
void ScrollAnchor::FindAnchor() {
TRACE_EVENT0("blink", "ScrollAnchor::findAnchor");
- SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Layout.ScrollAnchor.TimeToFindAnchor");
bool found_priority_anchor = FindAnchorInPriorityCandidates();
if (!found_priority_anchor)
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 6d916288eaf..3cb989a8f28 100644
--- a/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#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/custom_scrollbar.h"
#include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -26,6 +27,7 @@
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.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"
@@ -98,7 +100,7 @@ class ScrollbarTestingPlatformSupport : public TestingPlatformSupport {
} // namespace
-class ScrollbarsTest : public SimTest {
+class ScrollbarsTest : public PaintTestConfigurations, public SimTest {
public:
void SetUp() override {
SimTest::SetUp();
@@ -254,6 +256,8 @@ class ScrollbarsTest : public SimTest {
bool original_overlay_scrollbars_enabled_;
};
+INSTANTIATE_PAINT_TEST_SUITE_P(ScrollbarsTest);
+
class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest {
public:
void SetUp() override {
@@ -291,6 +295,8 @@ class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest {
}
};
+INSTANTIATE_PAINT_TEST_SUITE_P(ScrollbarsTestWithVirtualTimer);
+
// Try to force enable/disable overlay. Skip the test if the desired setting
// is not supported by the platform.
#define ENABLE_OVERLAY_SCROLLBARS(b) \
@@ -300,7 +306,7 @@ class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest {
return; \
} while (false)
-TEST_F(ScrollbarsTest, DocumentStyleRecalcPreservesScrollbars) {
+TEST_P(ScrollbarsTest, DocumentStyleRecalcPreservesScrollbars) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
SimRequest request("https://example.com/test.html", "text/html");
@@ -386,7 +392,7 @@ TEST(ScrollbarsTestWithOwnWebViewHelper, ScrollbarSizeForUseZoomDSF) {
// caused by trying to avoid the layout when overlays are enabled but not
// checking whether the scrollbars should be custom - which do take up layout
// space. https://crbug.com/668387.
-TEST_F(ScrollbarsTest, CustomScrollbarsCauseLayoutOnExistenceChange) {
+TEST_P(ScrollbarsTest, CustomScrollbarsCauseLayoutOnExistenceChange) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -437,13 +443,13 @@ TEST_F(ScrollbarsTest, CustomScrollbarsCauseLayoutOnExistenceChange) {
ASSERT_FALSE(layout_viewport->HorizontalScrollbar());
}
-TEST_F(ScrollbarsTest, TransparentBackgroundUsesDarkOverlayColorTheme) {
+TEST_P(ScrollbarsTest, TransparentBackgroundUsesDarkOverlayColorTheme) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
- WebView().SetBaseBackgroundColor(SK_ColorTRANSPARENT);
+ WebView().SetPageBaseBackgroundColor(SK_ColorTRANSPARENT);
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -462,7 +468,7 @@ TEST_F(ScrollbarsTest, TransparentBackgroundUsesDarkOverlayColorTheme) {
layout_viewport->GetScrollbarOverlayColorTheme());
}
-TEST_F(ScrollbarsTest, BodyBackgroundChangesOverlayColorTheme) {
+TEST_P(ScrollbarsTest, BodyBackgroundChangesOverlayColorTheme) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -491,7 +497,7 @@ TEST_F(ScrollbarsTest, BodyBackgroundChangesOverlayColorTheme) {
}
// Ensure overlay scrollbar change to display:none correctly.
-TEST_F(ScrollbarsTest, OverlayScrollbarChangeToDisplayNoneDynamically) {
+TEST_P(ScrollbarsTest, OverlayScrollbarChangeToDisplayNoneDynamically) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -560,7 +566,7 @@ TEST_F(ScrollbarsTest, OverlayScrollbarChangeToDisplayNoneDynamically) {
// Ensure that overlay scrollbars are not created, even in overflow:scroll,
// situations when there's no overflow. Specifically, after style-only changes.
-TEST_F(ScrollbarsTest, OverlayScrolblarNotCreatedInUnscrollableAxis) {
+TEST_P(ScrollbarsTest, OverlayScrolblarNotCreatedInUnscrollableAxis) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -597,7 +603,7 @@ TEST_F(ScrollbarsTest, OverlayScrolblarNotCreatedInUnscrollableAxis) {
ASSERT_FALSE(scrollable_area->HorizontalScrollbar());
}
-TEST_F(ScrollbarsTest, scrollbarIsNotHandlingTouchpadScroll) {
+TEST_P(ScrollbarsTest, scrollbarIsNotHandlingTouchpadScroll) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -637,7 +643,7 @@ TEST_F(ScrollbarsTest, scrollbarIsNotHandlingTouchpadScroll) {
scroll_begin, &should_update_capture));
}
-TEST_F(ScrollbarsTest, HidingScrollbarsOnScrollableAreaDisablesScrollbars) {
+TEST_P(ScrollbarsTest, HidingScrollbarsOnScrollableAreaDisablesScrollbars) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -708,7 +714,7 @@ TEST_F(ScrollbarsTest, HidingScrollbarsOnScrollableAreaDisablesScrollbars) {
}
// Ensure mouse cursor should be pointer when hovering over the scrollbar.
-TEST_F(ScrollbarsTest, MouseOverScrollbarInCustomCursorElement) {
+TEST_P(ScrollbarsTest, MouseOverScrollbarInCustomCursorElement) {
// Skip this test if scrollbars don't allow hit testing on the platform.
if (!WebView().GetPage()->GetScrollbarTheme().AllowsHitTest())
return;
@@ -756,7 +762,7 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarInCustomCursorElement) {
// Ensure mouse cursor should be override when hovering over the custom
// scrollbar.
-TEST_F(ScrollbarsTest, MouseOverCustomScrollbarInCustomCursorElement) {
+TEST_P(ScrollbarsTest, MouseOverCustomScrollbarInCustomCursorElement) {
// Skip this test if scrollbars don't allow hit testing on the platform.
if (!WebView().GetPage()->GetScrollbarTheme().AllowsHitTest())
return;
@@ -813,7 +819,7 @@ TEST_F(ScrollbarsTest, MouseOverCustomScrollbarInCustomCursorElement) {
// Makes sure that mouse hover over an overlay scrollbar doesn't activate
// elements below (except the Element that owns the scrollbar) unless the
// scrollbar is faded out.
-TEST_F(ScrollbarsTest, MouseOverLinkAndOverlayScrollbar) {
+TEST_P(ScrollbarsTest, MouseOverLinkAndOverlayScrollbar) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -904,7 +910,7 @@ TEST_F(ScrollbarsTest, MouseOverLinkAndOverlayScrollbar) {
// Makes sure that mouse hover over an custom scrollbar doesn't change the
// activate elements.
-TEST_F(ScrollbarsTest, MouseOverCustomScrollbar) {
+TEST_P(ScrollbarsTest, MouseOverCustomScrollbar) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -971,7 +977,7 @@ TEST_F(ScrollbarsTest, MouseOverCustomScrollbar) {
// Makes sure that mouse hover over an overlay scrollbar doesn't hover iframe
// below.
-TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
+TEST_P(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -1001,6 +1007,9 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
)HTML");
Compositor().BeginFrame();
+ frame_resource.Complete("<!DOCTYPE html>");
+ Compositor().BeginFrame();
+
// Enable the Scrollbar.
WebView()
.MainFrameImpl()
@@ -1008,9 +1017,6 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
->LayoutViewport()
->SetScrollbarsHiddenForTesting(false);
- frame_resource.Complete("<!DOCTYPE html>");
- Compositor().BeginFrame();
-
Document& document = GetDocument();
Element* iframe = document.getElementById("iframe");
DCHECK(iframe);
@@ -1061,7 +1067,7 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
// Makes sure that mouse hover over a scrollbar also hover the element owns the
// scrollbar.
-TEST_F(ScrollbarsTest, MouseOverScrollbarAndParentElement) {
+TEST_P(ScrollbarsTest, MouseOverScrollbarAndParentElement) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1148,7 +1154,7 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarAndParentElement) {
}
// Makes sure that mouse over a root scrollbar also hover the html element.
-TEST_F(ScrollbarsTest, MouseOverRootScrollbar) {
+TEST_P(ScrollbarsTest, MouseOverRootScrollbar) {
// Skip this test if scrollbars don't allow hit testing on the platform.
if (!WebView().GetPage()->GetScrollbarTheme().AllowsHitTest())
return;
@@ -1184,7 +1190,7 @@ TEST_F(ScrollbarsTest, MouseOverRootScrollbar) {
EXPECT_EQ(document.HoverElement(), document.documentElement());
}
-TEST_F(ScrollbarsTest, MouseReleaseUpdatesScrollbarHoveredPart) {
+TEST_P(ScrollbarsTest, MouseReleaseUpdatesScrollbarHoveredPart) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -1248,7 +1254,7 @@ TEST_F(ScrollbarsTest, MouseReleaseUpdatesScrollbarHoveredPart) {
EXPECT_EQ(scrollbar->HoveredPart(), ScrollbarPart::kNoPart);
}
-TEST_F(ScrollbarsTest, ContextMenuUpdatesScrollbarPressedPart) {
+TEST_P(ScrollbarsTest, ContextMenuUpdatesScrollbarPressedPart) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -1299,7 +1305,7 @@ TEST_F(ScrollbarsTest, ContextMenuUpdatesScrollbarPressedPart) {
EXPECT_EQ(scrollbar->PressedPart(), ScrollbarPart::kNoPart);
}
-TEST_F(ScrollbarsTest,
+TEST_P(ScrollbarsTest,
CustomScrollbarInOverlayScrollbarThemeWillNotCauseDCHECKFails) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
@@ -1328,7 +1334,7 @@ TEST_F(ScrollbarsTest,
// Make sure root custom scrollbar can change by Emulator but div custom
// scrollbar not.
-TEST_F(ScrollbarsTest, CustomScrollbarChangeToMobileByEmulator) {
+TEST_P(ScrollbarsTest, CustomScrollbarChangeToMobileByEmulator) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -1410,7 +1416,7 @@ TEST_F(ScrollbarsTest, CustomScrollbarChangeToMobileByEmulator) {
}
// Ensure custom scrollbar recreate when style owner change,
-TEST_F(ScrollbarsTest, CustomScrollbarWhenStyleOwnerChange) {
+TEST_P(ScrollbarsTest, CustomScrollbarWhenStyleOwnerChange) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -1466,10 +1472,10 @@ TEST_F(ScrollbarsTest, CustomScrollbarWhenStyleOwnerChange) {
// Disable on Android since VirtualTime not work for Android.
// http://crbug.com/633321
#if defined(OS_ANDROID)
-TEST_F(ScrollbarsTestWithVirtualTimer,
+TEST_P(ScrollbarsTestWithVirtualTimer,
DISABLED_TestNonCompositedOverlayScrollbarsFade) {
#else
-TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
+TEST_P(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
#endif
// This test relies on mock overlay scrollbars.
ScopedMockOverlayScrollbars mock_overlay_scrollbars(true);
@@ -1560,12 +1566,23 @@ TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(base::TimeDelta());
}
-class ScrollbarAppearanceTest
- : public ScrollbarsTest,
- public testing::WithParamInterface</*use_overlay_scrollbars=*/bool> {};
+enum { kUseOverlayScrollbars = 1 << 10 };
+
+class ScrollbarAppearanceTest : public ScrollbarsTest {
+ protected:
+ bool UsesOverlayScrollbars() const {
+ return GetParam() & kUseOverlayScrollbars;
+ }
+};
// Test both overlay and non-overlay scrollbars.
-INSTANTIATE_TEST_SUITE_P(All, ScrollbarAppearanceTest, testing::Bool());
+INSTANTIATE_TEST_SUITE_P(All,
+ ScrollbarAppearanceTest,
+ ::testing::Values(0,
+ kUseOverlayScrollbars,
+ kCompositeAfterPaint,
+ kUseOverlayScrollbars |
+ kCompositeAfterPaint));
// Make sure native scrollbar can change by Emulator.
// Disable on Android since Android always enable OverlayScrollbar.
@@ -1575,8 +1592,7 @@ TEST_P(ScrollbarAppearanceTest,
#else
TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
#endif
- bool use_overlay_scrollbar = GetParam();
- ENABLE_OVERLAY_SCROLLBARS(use_overlay_scrollbar);
+ ENABLE_OVERLAY_SCROLLBARS(UsesOverlayScrollbars());
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
@@ -1620,7 +1636,7 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
DCHECK(root_scrollable->VerticalScrollbar());
DCHECK(!root_scrollable->VerticalScrollbar()->IsCustomScrollbar());
- DCHECK_EQ(use_overlay_scrollbar,
+ DCHECK_EQ(UsesOverlayScrollbars(),
root_scrollable->VerticalScrollbar()->IsOverlayScrollbar());
DCHECK(!root_scrollable->VerticalScrollbar()->GetTheme().IsMockTheme());
@@ -1628,7 +1644,7 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
DCHECK(div_scrollable->VerticalScrollbar());
DCHECK(!div_scrollable->VerticalScrollbar()->IsCustomScrollbar());
- DCHECK_EQ(use_overlay_scrollbar,
+ DCHECK_EQ(UsesOverlayScrollbars(),
div_scrollable->VerticalScrollbar()->IsOverlayScrollbar());
DCHECK(!div_scrollable->VerticalScrollbar()->GetTheme().IsMockTheme());
@@ -1650,7 +1666,7 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
EXPECT_TRUE(root_scrollable->VerticalScrollbar());
EXPECT_FALSE(root_scrollable->VerticalScrollbar()->IsCustomScrollbar());
- DCHECK_EQ(use_overlay_scrollbar,
+ DCHECK_EQ(UsesOverlayScrollbars(),
root_scrollable->VerticalScrollbar()->IsOverlayScrollbar());
EXPECT_FALSE(root_scrollable->VerticalScrollbar()->GetTheme().IsMockTheme());
@@ -1658,7 +1674,7 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
EXPECT_TRUE(div_scrollable->VerticalScrollbar());
EXPECT_FALSE(div_scrollable->VerticalScrollbar()->IsCustomScrollbar());
- DCHECK_EQ(use_overlay_scrollbar,
+ DCHECK_EQ(UsesOverlayScrollbars(),
div_scrollable->VerticalScrollbar()->IsOverlayScrollbar());
EXPECT_FALSE(div_scrollable->VerticalScrollbar()->GetTheme().IsMockTheme());
}
@@ -1669,7 +1685,7 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
// test doesn't apply there. https://crbug.com/682209.
TEST_P(ScrollbarAppearanceTest, ThemeEngineDefinesMinimumThumbLength) {
ScopedTestingPlatformSupport<ScrollbarTestingPlatformSupport> platform;
- ENABLE_OVERLAY_SCROLLBARS(GetParam());
+ ENABLE_OVERLAY_SCROLLBARS(UsesOverlayScrollbars());
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
@@ -1695,7 +1711,7 @@ TEST_P(ScrollbarAppearanceTest, ThemeEngineDefinesMinimumThumbLength) {
// scales.
TEST_P(ScrollbarAppearanceTest, HugeScrollingThumbPosition) {
ScopedTestingPlatformSupport<ScrollbarTestingPlatformSupport> platform;
- ENABLE_OVERLAY_SCROLLBARS(GetParam());
+ ENABLE_OVERLAY_SCROLLBARS(UsesOverlayScrollbars());
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
WebView().MainFrameViewWidget()->Resize(gfx::Size(1000, 1000));
@@ -1731,7 +1747,7 @@ TEST_P(ScrollbarAppearanceTest, HugeScrollingThumbPosition) {
#endif
// A body with width just under the window width should not have scrollbars.
-TEST_F(ScrollbarsTest, WideBodyShouldNotHaveScrollbars) {
+TEST_P(ScrollbarsTest, WideBodyShouldNotHaveScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1755,7 +1771,7 @@ TEST_F(ScrollbarsTest, WideBodyShouldNotHaveScrollbars) {
}
// A body with height just under the window height should not have scrollbars.
-TEST_F(ScrollbarsTest, TallBodyShouldNotHaveScrollbars) {
+TEST_P(ScrollbarsTest, TallBodyShouldNotHaveScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1780,7 +1796,7 @@ TEST_F(ScrollbarsTest, TallBodyShouldNotHaveScrollbars) {
// A body with dimensions just barely inside the window dimensions should not
// have scrollbars.
-TEST_F(ScrollbarsTest, TallAndWideBodyShouldNotHaveScrollbars) {
+TEST_P(ScrollbarsTest, TallAndWideBodyShouldNotHaveScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1805,7 +1821,7 @@ TEST_F(ScrollbarsTest, TallAndWideBodyShouldNotHaveScrollbars) {
// A body with dimensions equal to the window dimensions should not have
// scrollbars.
-TEST_F(ScrollbarsTest, BodySizeEqualWindowSizeShouldNotHaveScrollbars) {
+TEST_P(ScrollbarsTest, BodySizeEqualWindowSizeShouldNotHaveScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1830,7 +1846,7 @@ TEST_F(ScrollbarsTest, BodySizeEqualWindowSizeShouldNotHaveScrollbars) {
// A body with percentage width extending beyond the window width should cause a
// horizontal scrollbar.
-TEST_F(ScrollbarsTest, WidePercentageBodyShouldHaveScrollbar) {
+TEST_P(ScrollbarsTest, WidePercentageBodyShouldHaveScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1856,7 +1872,7 @@ TEST_F(ScrollbarsTest, WidePercentageBodyShouldHaveScrollbar) {
// Similar to |WidePercentageBodyShouldHaveScrollbar| but with a body height
// equal to the window height.
-TEST_F(ScrollbarsTest, WidePercentageAndTallBodyShouldHaveScrollbar) {
+TEST_P(ScrollbarsTest, WidePercentageAndTallBodyShouldHaveScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1882,7 +1898,7 @@ TEST_F(ScrollbarsTest, WidePercentageAndTallBodyShouldHaveScrollbar) {
// A body with percentage height extending beyond the window height should cause
// a vertical scrollbar.
-TEST_F(ScrollbarsTest, TallPercentageBodyShouldHaveScrollbar) {
+TEST_P(ScrollbarsTest, TallPercentageBodyShouldHaveScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1908,7 +1924,7 @@ TEST_F(ScrollbarsTest, TallPercentageBodyShouldHaveScrollbar) {
// Similar to |TallPercentageBodyShouldHaveScrollbar| but with a body width
// equal to the window width.
-TEST_F(ScrollbarsTest, TallPercentageAndWideBodyShouldHaveScrollbar) {
+TEST_P(ScrollbarsTest, TallPercentageAndWideBodyShouldHaveScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1934,7 +1950,7 @@ TEST_F(ScrollbarsTest, TallPercentageAndWideBodyShouldHaveScrollbar) {
// A body with percentage dimensions extending beyond the window dimensions
// should cause scrollbars.
-TEST_F(ScrollbarsTest, TallAndWidePercentageBodyShouldHaveScrollbars) {
+TEST_P(ScrollbarsTest, TallAndWidePercentageBodyShouldHaveScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -1958,7 +1974,7 @@ TEST_F(ScrollbarsTest, TallAndWidePercentageBodyShouldHaveScrollbars) {
EXPECT_TRUE(layout_viewport->HorizontalScrollbar());
}
-TEST_F(ScrollbarsTest, MouseOverIFrameScrollbar) {
+TEST_P(ScrollbarsTest, MouseOverIFrameScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2010,7 +2026,7 @@ TEST_F(ScrollbarsTest, MouseOverIFrameScrollbar) {
EXPECT_EQ(document.HoverElement(), iframe);
}
-TEST_F(ScrollbarsTest, AutosizeTest) {
+TEST_P(ScrollbarsTest, AutosizeTest) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2078,7 +2094,7 @@ TEST_F(ScrollbarsTest, AutosizeTest) {
}
}
-TEST_F(ScrollbarsTest, AutosizeAlmostRemovableScrollbar) {
+TEST_P(ScrollbarsTest, AutosizeAlmostRemovableScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
WebView().EnableAutoResizeMode(gfx::Size(25, 25), gfx::Size(800, 600));
@@ -2114,7 +2130,7 @@ TEST_F(ScrollbarsTest, AutosizeAlmostRemovableScrollbar) {
}
}
-TEST_F(ScrollbarsTest,
+TEST_P(ScrollbarsTest,
HideTheOverlayScrollbarNotCrashAfterPLSADisposedPaintLayer) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
@@ -2159,7 +2175,7 @@ TEST_F(ScrollbarsTest,
EXPECT_FALSE(scrollable_div->ScrollbarsHiddenIfOverlay());
}
-TEST_F(ScrollbarsTest, PLSADisposeShouldClearPointerInLayers) {
+TEST_P(ScrollbarsTest, PLSADisposeShouldClearPointerInLayers) {
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
true);
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
@@ -2190,9 +2206,7 @@ TEST_F(ScrollbarsTest, PLSADisposeShouldClearPointerInLayers) {
PaintLayer* paint_layer = scrollable_div->Layer();
ASSERT_TRUE(paint_layer);
-
- cc::Layer* graphics_layer = scrollable_div->LayerForScrolling();
- ASSERT_TRUE(graphics_layer);
+ EXPECT_TRUE(scrollable_div->UsesCompositedScrolling());
div->setAttribute(html_names::kClassAttr, "hide");
document.UpdateStyleAndLayout(DocumentUpdateReason::kTest);
@@ -2200,7 +2214,7 @@ TEST_F(ScrollbarsTest, PLSADisposeShouldClearPointerInLayers) {
EXPECT_FALSE(paint_layer->GetScrollableArea());
}
-TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
+TEST_P(ScrollbarsTest, OverlayScrollbarHitTest) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -2230,6 +2244,9 @@ TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
)HTML");
Compositor().BeginFrame();
+ frame_resource.Complete("<!DOCTYPE html><body style='height: 999px'></body>");
+ Compositor().BeginFrame();
+
// Enable the main frame scrollbar.
WebView()
.MainFrameImpl()
@@ -2237,9 +2254,6 @@ TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
->LayoutViewport()
->SetScrollbarsHiddenForTesting(false);
- frame_resource.Complete("<!DOCTYPE html><body style='height: 999px'></body>");
- Compositor().BeginFrame();
-
// Enable the iframe scrollbar.
auto* iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("iframe"));
@@ -2261,7 +2275,7 @@ TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
EXPECT_FALSE(hit_test_result.GetScrollbar());
}
-TEST_F(ScrollbarsTest, AllowMiddleButtonPressOnScrollbar) {
+TEST_P(ScrollbarsTest, AllowMiddleButtonPressOnScrollbar) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2295,7 +2309,7 @@ TEST_F(ScrollbarsTest, AllowMiddleButtonPressOnScrollbar) {
}
// Ensure Scrollbar not release press by middle button down.
-TEST_F(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) {
+TEST_P(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2349,7 +2363,7 @@ TEST_F(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) {
EXPECT_EQ(scrollbar->PressedPart(), ScrollbarPart::kNoPart);
}
-TEST_F(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithMouse) {
+TEST_P(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithMouse) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2431,7 +2445,7 @@ TEST_F(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithMouse) {
WebFeature::kHorizontalScrollbarThumbScrollingWithMouse));
}
-TEST_F(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithMouse) {
+TEST_P(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithMouse) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2473,7 +2487,7 @@ TEST_F(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithMouse) {
WebFeature::kHorizontalScrollbarThumbScrollingWithMouse));
}
-TEST_F(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithTouch) {
+TEST_P(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithTouch) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2539,7 +2553,7 @@ TEST_F(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithTouch) {
WebFeature::kHorizontalScrollbarThumbScrollingWithTouch));
}
-TEST_F(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithTouch) {
+TEST_P(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithTouch) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -2585,7 +2599,7 @@ TEST_F(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithTouch) {
WebFeature::kHorizontalScrollbarThumbScrollingWithTouch));
}
-TEST_F(ScrollbarsTest, UseCounterCustomScrollbarPercentSize) {
+TEST_P(ScrollbarsTest, UseCounterCustomScrollbarPercentSize) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -2627,7 +2641,7 @@ TEST_F(ScrollbarsTest, UseCounterCustomScrollbarPercentSize) {
WebFeature::kCustomScrollbarPartPercentLength));
}
-TEST_F(ScrollbarsTest, CheckScrollCornerIfThereIsNoScrollbar) {
+TEST_P(ScrollbarsTest, CheckScrollCornerIfThereIsNoScrollbar) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -2678,7 +2692,7 @@ TEST_F(ScrollbarsTest, CheckScrollCornerIfThereIsNoScrollbar) {
EXPECT_FALSE(scrollable_container->ScrollCorner());
}
-TEST_F(ScrollbarsTest, NoNeedsBeginFrameForCustomScrollbarAfterBeginFrame) {
+TEST_P(ScrollbarsTest, NoNeedsBeginFrameForCustomScrollbarAfterBeginFrame) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -2719,7 +2733,7 @@ TEST_F(ScrollbarsTest, NoNeedsBeginFrameForCustomScrollbarAfterBeginFrame) {
EXPECT_NE(thumb_size, thumb->Size());
}
-TEST_F(ScrollbarsTest, CustomScrollbarHypotheticalThickness) {
+TEST_P(ScrollbarsTest, CustomScrollbarHypotheticalThickness) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(200, 200));
SimRequest request("https://example.com/test.html", "text/html");
@@ -2757,10 +2771,10 @@ TEST_F(ScrollbarsTest, CustomScrollbarHypotheticalThickness) {
// Disable on Android since VirtualTime not work for Android.
// http://crbug.com/633321
#if defined(OS_ANDROID)
-TEST_F(ScrollbarsTestWithVirtualTimer,
+TEST_P(ScrollbarsTestWithVirtualTimer,
DISABLED_PressScrollbarButtonOnInfiniteScrolling) {
#else
-TEST_F(ScrollbarsTestWithVirtualTimer,
+TEST_P(ScrollbarsTestWithVirtualTimer,
PressScrollbarButtonOnInfiniteScrolling) {
#endif
TimeAdvance();
@@ -2885,7 +2899,9 @@ class ScrollbarTrackMarginsTest : public ScrollbarsTest {
LayoutCustomScrollbarPart* vertical_track_ = nullptr;
};
-TEST_F(ScrollbarTrackMarginsTest,
+INSTANTIATE_PAINT_TEST_SUITE_P(ScrollbarTrackMarginsTest);
+
+TEST_P(ScrollbarTrackMarginsTest,
CustomScrollbarFractionalMarginsWillNotCauseDCHECKFailure) {
PrepareTest(R"CSS(
::-webkit-scrollbar-track {
@@ -2901,7 +2917,7 @@ TEST_F(ScrollbarTrackMarginsTest,
EXPECT_EQ(41, vertical_track_->MarginBottom());
}
-TEST_F(ScrollbarTrackMarginsTest,
+TEST_P(ScrollbarTrackMarginsTest,
CustomScrollbarScaledMarginsWillNotCauseDCHECKFailure) {
WebView().SetZoomFactorForDeviceScaleFactor(1.25f);
@@ -2935,7 +2951,6 @@ INSTANTIATE_TEST_SUITE_P(NonOverlay,
TEST_P(ScrollbarColorSchemeTest, MAYBE_ThemeEnginePaint) {
ScopedTestingPlatformSupport<ScrollbarTestingPlatformSupport> platform;
- ScopedCSSColorSchemeUARenderingForTest color_scheme_ua_scope(true);
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
SimRequest request("https://example.com/test.html", "text/html");
@@ -2979,7 +2994,7 @@ TEST_P(ScrollbarColorSchemeTest, MAYBE_ThemeEnginePaint) {
}
// Test scrollbar-gutter values with classic scrollbars and horizontal-tb text.
-TEST_F(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndClassicScrollbars) {
+TEST_P(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndClassicScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -3001,41 +3016,13 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndClassicScrollbars) {
#stable {
scrollbar-gutter: stable;
}
- #stable_both {
- scrollbar-gutter: stable both;
- }
- #always {
- scrollbar-gutter: always;
- }
- #always_both {
- scrollbar-gutter: always both;
- }
- #stable_force {
- overflow: visible;
- scrollbar-gutter: stable force;
- }
- #stable_both_force {
- overflow: hidden;
- scrollbar-gutter: stable both force;
- }
- #always_force {
- overflow: visible;
- scrollbar-gutter: always force;
- }
- #always_both_force {
- overflow: hidden;
- scrollbar-gutter: always both force;
+ #stable_both_edges {
+ scrollbar-gutter: stable both-edges;
}
</style>
<div id="auto"></div>
<div id="stable"></div>
- <div id="stable_both"></div>
- <div id="always"></div>
- <div id="always_both"></div>
- <div id="stable_force"></div>
- <div id="stable_both_force"></div>
- <div id="always_force"></div>
- <div id="always_both_force"></div>
+ <div id="stable_both_edges"></div>
)HTML");
Compositor().BeginFrame();
auto* auto_ = GetDocument().getElementById("auto");
@@ -3058,67 +3045,20 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndClassicScrollbars) {
EXPECT_EQ(box_stable_scrollbars.left, 0);
EXPECT_EQ(box_stable_scrollbars.right, 15);
- auto* stable_both = GetDocument().getElementById("stable_both");
- auto* box_stable_both = stable_both->GetLayoutBox();
- EXPECT_EQ(box_stable_both->OffsetWidth(), 100);
- EXPECT_EQ(box_stable_both->ClientWidth(), 70);
- NGPhysicalBoxStrut box_stable_both_scrollbars =
- box_stable_both->ComputeScrollbars();
- EXPECT_EQ(box_stable_both_scrollbars.top, 0);
- EXPECT_EQ(box_stable_both_scrollbars.bottom, 0);
- EXPECT_EQ(box_stable_both_scrollbars.left, 15);
- EXPECT_EQ(box_stable_both_scrollbars.right, 15);
-
- auto* always = GetDocument().getElementById("always");
- auto* box_always = always->GetLayoutBox();
- EXPECT_EQ(box_always->OffsetWidth(), 100);
- EXPECT_EQ(box_always->ClientWidth(), 85);
- NGPhysicalBoxStrut box_always_scrollbars = box_always->ComputeScrollbars();
- EXPECT_EQ(box_always_scrollbars.top, 0);
- EXPECT_EQ(box_always_scrollbars.bottom, 0);
- EXPECT_EQ(box_always_scrollbars.left, 0);
- EXPECT_EQ(box_always_scrollbars.right, 15);
-
- auto* always_both = GetDocument().getElementById("always_both");
- auto* box_always_both = always_both->GetLayoutBox();
- EXPECT_EQ(box_always_both->OffsetWidth(), 100);
- EXPECT_EQ(box_always_both->ClientWidth(), 70);
- NGPhysicalBoxStrut box_always_both_scrollbars =
- box_always_both->ComputeScrollbars();
- EXPECT_EQ(box_always_both_scrollbars.top, 0);
- EXPECT_EQ(box_always_both_scrollbars.bottom, 0);
- EXPECT_EQ(box_always_both_scrollbars.left, 15);
- EXPECT_EQ(box_always_both_scrollbars.right, 15);
-
- auto* stable_force = GetDocument().getElementById("stable_force");
- auto* box_stable_force = stable_force->GetLayoutBox();
- EXPECT_EQ(box_stable_force->OffsetWidth(), 100);
- EXPECT_EQ(box_stable_force->ClientWidth(), 85);
- EXPECT_EQ(box_stable_force->ComputeScrollbars(), box_stable_scrollbars);
-
- auto* stable_both_force = GetDocument().getElementById("stable_both_force");
- auto* box_stable_both_force = stable_both_force->GetLayoutBox();
- EXPECT_EQ(box_stable_both_force->OffsetWidth(), 100);
- EXPECT_EQ(box_stable_both_force->ClientWidth(), 70);
- EXPECT_EQ(box_stable_both_force->ComputeScrollbars(),
- box_stable_both_scrollbars);
-
- auto* always_force = GetDocument().getElementById("always_force");
- auto* box_always_force = always_force->GetLayoutBox();
- EXPECT_EQ(box_always_force->OffsetWidth(), 100);
- EXPECT_EQ(box_always_force->ClientWidth(), 85);
- EXPECT_EQ(box_always_force->ComputeScrollbars(), box_always_scrollbars);
-
- auto* always_both_force = GetDocument().getElementById("always_both_force");
- auto* box_always_both_force = always_both_force->GetLayoutBox();
- EXPECT_EQ(box_always_both_force->OffsetWidth(), 100);
- EXPECT_EQ(box_always_both_force->ClientWidth(), 70);
- EXPECT_EQ(box_always_both_force->ComputeScrollbars(),
- box_always_both_scrollbars);
+ auto* stable_both_edges = GetDocument().getElementById("stable_both_edges");
+ auto* box_stable_both_edges = stable_both_edges->GetLayoutBox();
+ EXPECT_EQ(box_stable_both_edges->OffsetWidth(), 100);
+ EXPECT_EQ(box_stable_both_edges->ClientWidth(), 70);
+ NGPhysicalBoxStrut box_stable_both_edges_scrollbars =
+ box_stable_both_edges->ComputeScrollbars();
+ EXPECT_EQ(box_stable_both_edges_scrollbars.top, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.bottom, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.left, 15);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.right, 15);
}
// Test scrollbar-gutter values with classic scrollbars and vertical-rl text.
-TEST_F(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndClassicScrollbars) {
+TEST_P(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndClassicScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -3140,41 +3080,13 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndClassicScrollbars) {
#stable {
scrollbar-gutter: stable;
}
- #stable_both {
- scrollbar-gutter: stable both;
- }
- #always {
- scrollbar-gutter: always;
- }
- #always_both {
- scrollbar-gutter: always both;
- }
- #stable_force {
- overflow: hidden;
- scrollbar-gutter: stable force;
- }
- #stable_both_force {
- overflow: visible;
- scrollbar-gutter: stable both force;
- }
- #always_force {
- overflow: hidden;
- scrollbar-gutter: always force;
- }
- #always_both_force {
- overflow: visible;
- scrollbar-gutter: always both force;
+ #stable_both_edges {
+ scrollbar-gutter: stable both-edges;
}
</style>
<div id="auto"></div>
<div id="stable"></div>
- <div id="stable_both"></div>
- <div id="always"></div>
- <div id="always_both"></div>
- <div id="stable_force"></div>
- <div id="stable_both_force"></div>
- <div id="always_force"></div>
- <div id="always_both_force"></div>
+ <div id="stable_both_edges"></div>
)HTML");
Compositor().BeginFrame();
auto* auto_ = GetDocument().getElementById("auto");
@@ -3197,67 +3109,20 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndClassicScrollbars) {
EXPECT_EQ(box_stable_scrollbars.left, 0);
EXPECT_EQ(box_stable_scrollbars.right, 0);
- auto* stable_both = GetDocument().getElementById("stable_both");
- auto* box_stable_both = stable_both->GetLayoutBox();
- EXPECT_EQ(box_stable_both->OffsetHeight(), 100);
- EXPECT_EQ(box_stable_both->ClientHeight(), 70);
- NGPhysicalBoxStrut box_stable_both_scrollbars =
- box_stable_both->ComputeScrollbars();
- EXPECT_EQ(box_stable_both_scrollbars.top, 15);
- EXPECT_EQ(box_stable_both_scrollbars.bottom, 15);
- EXPECT_EQ(box_stable_both_scrollbars.left, 0);
- EXPECT_EQ(box_stable_both_scrollbars.right, 0);
-
- auto* always = GetDocument().getElementById("always");
- auto* box_always = always->GetLayoutBox();
- EXPECT_EQ(box_always->OffsetHeight(), 100);
- EXPECT_EQ(box_always->ClientHeight(), 85);
- NGPhysicalBoxStrut box_always_scrollbars = box_always->ComputeScrollbars();
- EXPECT_EQ(box_always_scrollbars.top, 0);
- EXPECT_EQ(box_always_scrollbars.bottom, 15);
- EXPECT_EQ(box_always_scrollbars.left, 0);
- EXPECT_EQ(box_always_scrollbars.right, 0);
-
- auto* always_both = GetDocument().getElementById("always_both");
- auto* box_always_both = always_both->GetLayoutBox();
- EXPECT_EQ(box_always_both->OffsetHeight(), 100);
- EXPECT_EQ(box_always_both->ClientHeight(), 70);
- NGPhysicalBoxStrut box_always_both_scrollbars =
- box_always_both->ComputeScrollbars();
- EXPECT_EQ(box_always_both_scrollbars.top, 15);
- EXPECT_EQ(box_always_both_scrollbars.bottom, 15);
- EXPECT_EQ(box_always_both_scrollbars.left, 0);
- EXPECT_EQ(box_always_both_scrollbars.right, 0);
-
- auto* stable_force = GetDocument().getElementById("stable_force");
- auto* box_stable_force = stable_force->GetLayoutBox();
- EXPECT_EQ(box_stable_force->OffsetHeight(), 100);
- EXPECT_EQ(box_stable_force->ClientHeight(), 85);
- EXPECT_EQ(box_stable_force->ComputeScrollbars(), box_stable_scrollbars);
-
- auto* stable_both_force = GetDocument().getElementById("stable_both_force");
- auto* box_stable_both_force = stable_both_force->GetLayoutBox();
- EXPECT_EQ(box_stable_both_force->OffsetHeight(), 100);
- EXPECT_EQ(box_stable_both_force->ClientHeight(), 70);
- EXPECT_EQ(box_stable_both_force->ComputeScrollbars(),
- box_stable_both_scrollbars);
-
- auto* always_force = GetDocument().getElementById("always_force");
- auto* box_always_force = always_force->GetLayoutBox();
- EXPECT_EQ(box_always_force->OffsetHeight(), 100);
- EXPECT_EQ(box_always_force->ClientHeight(), 85);
- EXPECT_EQ(box_always_force->ComputeScrollbars(), box_always_scrollbars);
-
- auto* always_both_force = GetDocument().getElementById("always_both_force");
- auto* box_always_both_force = always_both_force->GetLayoutBox();
- EXPECT_EQ(box_always_both_force->OffsetHeight(), 100);
- EXPECT_EQ(box_always_both_force->ClientHeight(), 70);
- EXPECT_EQ(box_always_both_force->ComputeScrollbars(),
- box_always_both_scrollbars);
+ auto* stable_both_edges = GetDocument().getElementById("stable_both_edges");
+ auto* box_stable_both_edges = stable_both_edges->GetLayoutBox();
+ EXPECT_EQ(box_stable_both_edges->OffsetHeight(), 100);
+ EXPECT_EQ(box_stable_both_edges->ClientHeight(), 70);
+ NGPhysicalBoxStrut box_stable_both_edges_scrollbars =
+ box_stable_both_edges->ComputeScrollbars();
+ EXPECT_EQ(box_stable_both_edges_scrollbars.top, 15);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.bottom, 15);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.left, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.right, 0);
}
// Test scrollbar-gutter values with overlay scrollbars and horizontal-tb text.
-TEST_F(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndOverlayScrollbars) {
+TEST_P(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndOverlayScrollbars) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -3280,41 +3145,13 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndOverlayScrollbars) {
#stable {
scrollbar-gutter: stable;
}
- #stable_both {
- scrollbar-gutter: stable both;
- }
- #always {
- scrollbar-gutter: always;
- }
- #always_both {
- scrollbar-gutter: always both;
- }
- #stable_force {
- overflow: hidden;
- scrollbar-gutter: stable force;
- }
- #stable_both_force {
- overflow: visible;
- scrollbar-gutter: stable both force;
- }
- #always_force {
- overflow: hidden;
- scrollbar-gutter: always force;
- }
- #always_both_force {
- overflow: visible;
- scrollbar-gutter: always both force;
+ #stable_both_edges {
+ scrollbar-gutter: stable both-edges;
}
</style>
<div id="auto"></div>
<div id="stable"></div>
- <div id="stable_both"></div>
- <div id="always"></div>
- <div id="always_both"></div>
- <div id="stable_force"></div>
- <div id="stable_both_force"></div>
- <div id="always_force"></div>
- <div id="always_both_force"></div>
+ <div id="stable_both_edges"></div>
)HTML");
Compositor().BeginFrame();
auto* auto_ = GetDocument().getElementById("auto");
@@ -3337,73 +3174,20 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithHorizontalTextAndOverlayScrollbars) {
EXPECT_EQ(box_stable_scrollbars.left, 0);
EXPECT_EQ(box_stable_scrollbars.right, 0);
- auto* stable_both = GetDocument().getElementById("stable_both");
- auto* box_stable_both = stable_both->GetLayoutBox();
- EXPECT_EQ(box_stable_both->OffsetWidth(), 100);
- EXPECT_EQ(box_stable_both->ClientWidth(), 100);
- NGPhysicalBoxStrut box_stable_both_scrollbars =
- box_stable_both->ComputeScrollbars();
- EXPECT_EQ(box_stable_both_scrollbars.top, 0);
- EXPECT_EQ(box_stable_both_scrollbars.bottom, 0);
- EXPECT_EQ(box_stable_both_scrollbars.left, 0);
- EXPECT_EQ(box_stable_both_scrollbars.right, 0);
-
- // The size of overlay scrollbars is different between operating systems,
- // which is why we use these relative comparisons.
-
- auto* always = GetDocument().getElementById("always");
- auto* box_always = always->GetLayoutBox();
- EXPECT_EQ(box_always->OffsetWidth(), 100);
- EXPECT_LT(box_always->ClientWidth(), box_auto->ClientWidth());
- NGPhysicalBoxStrut box_always_scrollbars = box_always->ComputeScrollbars();
- EXPECT_EQ(box_always_scrollbars.top, 0);
- EXPECT_EQ(box_always_scrollbars.bottom, 0);
- EXPECT_EQ(box_always_scrollbars.left, 0);
- // scrollbar gutter
- EXPECT_GT(box_always_scrollbars.right, 0);
-
- auto* always_both = GetDocument().getElementById("always_both");
- auto* box_always_both = always_both->GetLayoutBox();
- EXPECT_EQ(box_always_both->OffsetWidth(), 100);
- EXPECT_LT(box_always_both->ClientWidth(), box_always->ClientWidth());
- NGPhysicalBoxStrut box_always_both_scrollbars =
- box_always_both->ComputeScrollbars();
- EXPECT_EQ(box_always_both_scrollbars.top, 0);
- EXPECT_EQ(box_always_both_scrollbars.bottom, 0);
- // scrollbar gutters
- EXPECT_GT(box_always_both_scrollbars.left, 0);
- EXPECT_GT(box_always_both_scrollbars.right, 0);
-
- auto* stable_force = GetDocument().getElementById("stable_force");
- auto* box_stable_force = stable_force->GetLayoutBox();
- EXPECT_EQ(box_stable_force->OffsetWidth(), 100);
- EXPECT_EQ(box_stable_force->ClientWidth(), 100);
- EXPECT_EQ(box_stable_force->ComputeScrollbars(), box_stable_scrollbars);
-
- auto* stable_both_force = GetDocument().getElementById("stable_both_force");
- auto* box_stable_both_force = stable_both_force->GetLayoutBox();
- EXPECT_EQ(box_stable_both_force->OffsetWidth(), 100);
- EXPECT_EQ(box_stable_both_force->ClientWidth(), 100);
- EXPECT_EQ(box_stable_both_force->ComputeScrollbars(),
- box_stable_both_scrollbars);
-
- auto* always_force = GetDocument().getElementById("always_force");
- auto* box_always_force = always_force->GetLayoutBox();
- EXPECT_EQ(box_always_force->OffsetWidth(), 100);
- EXPECT_LT(box_always_force->ClientWidth(), box_auto->ClientWidth());
- EXPECT_EQ(box_always_force->ComputeScrollbars(), box_always_scrollbars);
-
- auto* always_both_force = GetDocument().getElementById("always_both_force");
- auto* box_always_both_force = always_both_force->GetLayoutBox();
- EXPECT_EQ(box_always_both_force->OffsetWidth(), 100);
- EXPECT_LT(box_always_both_force->ClientWidth(),
- box_always_force->ClientWidth());
- EXPECT_EQ(box_always_both_force->ComputeScrollbars(),
- box_always_both_scrollbars);
+ auto* stable_both_edges = GetDocument().getElementById("stable_both_edges");
+ auto* box_stable_both_edges = stable_both_edges->GetLayoutBox();
+ EXPECT_EQ(box_stable_both_edges->OffsetWidth(), 100);
+ EXPECT_EQ(box_stable_both_edges->ClientWidth(), 100);
+ NGPhysicalBoxStrut box_stable_both_edges_scrollbars =
+ box_stable_both_edges->ComputeScrollbars();
+ EXPECT_EQ(box_stable_both_edges_scrollbars.top, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.bottom, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.left, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.right, 0);
}
// Test scrollbar-gutter values with overlay scrollbars and vertical-rl text.
-TEST_F(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndOverlayScrollbars) {
+TEST_P(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndOverlayScrollbars) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
ENABLE_OVERLAY_SCROLLBARS(true);
@@ -3426,41 +3210,13 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndOverlayScrollbars) {
#stable {
scrollbar-gutter: stable;
}
- #stable_both {
- scrollbar-gutter: stable both;
- }
- #always {
- scrollbar-gutter: always;
- }
- #always_both {
- scrollbar-gutter: always both;
- }
- #stable_force {
- overflow: visible;
- scrollbar-gutter: stable force;
- }
- #stable_both_force {
- overflow: hidden;
- scrollbar-gutter: stable both force;
- }
- #always_force {
- overflow: visible;
- scrollbar-gutter: always force;
- }
- #always_both_force {
- overflow: hidden;
- scrollbar-gutter: always both force;
+ #stable_both_edges {
+ scrollbar-gutter: stable both-edges;
}
</style>
<div id="auto"></div>
<div id="stable"></div>
- <div id="stable_both"></div>
- <div id="always"></div>
- <div id="always_both"></div>
- <div id="stable_force"></div>
- <div id="stable_both_force"></div>
- <div id="always_force"></div>
- <div id="always_both_force"></div>
+ <div id="stable_both_edges"></div>
)HTML");
Compositor().BeginFrame();
auto* auto_ = GetDocument().getElementById("auto");
@@ -3483,71 +3239,21 @@ TEST_F(ScrollbarsTest, ScrollbarGutterWithVerticalTextAndOverlayScrollbars) {
EXPECT_EQ(box_stable_scrollbars.left, 0);
EXPECT_EQ(box_stable_scrollbars.right, 0);
- auto* stable_both = GetDocument().getElementById("stable_both");
- auto* box_stable_both = stable_both->GetLayoutBox();
- EXPECT_EQ(box_stable_both->OffsetHeight(), 100);
- EXPECT_EQ(box_stable_both->ClientHeight(), 100);
- NGPhysicalBoxStrut box_stable_both_scrollbars =
- box_stable_both->ComputeScrollbars();
- EXPECT_EQ(box_stable_both_scrollbars.top, 0);
- EXPECT_EQ(box_stable_both_scrollbars.bottom, 0);
- EXPECT_EQ(box_stable_both_scrollbars.left, 0);
- EXPECT_EQ(box_stable_both_scrollbars.right, 0);
-
- auto* always = GetDocument().getElementById("always");
- auto* box_always = always->GetLayoutBox();
- EXPECT_EQ(box_always->OffsetHeight(), 100);
- EXPECT_LT(box_always->ClientHeight(), box_auto->ClientHeight());
- NGPhysicalBoxStrut box_always_scrollbars = box_always->ComputeScrollbars();
- EXPECT_EQ(box_always_scrollbars.top, 0);
- // scrollbar gutter
- EXPECT_GT(box_always_scrollbars.bottom, 0);
- EXPECT_EQ(box_always_scrollbars.left, 0);
- EXPECT_EQ(box_always_scrollbars.right, 0);
-
- auto* always_both = GetDocument().getElementById("always_both");
- auto* box_always_both = always_both->GetLayoutBox();
- EXPECT_EQ(box_always_both->OffsetHeight(), 100);
- EXPECT_LT(box_always_both->ClientHeight(), box_always->ClientHeight());
- NGPhysicalBoxStrut box_always_both_scrollbars =
- box_always_both->ComputeScrollbars();
- // scrollbar gutters
- EXPECT_GT(box_always_both_scrollbars.top, 0);
- EXPECT_GT(box_always_both_scrollbars.bottom, 0);
- EXPECT_EQ(box_always_both_scrollbars.left, 0);
- EXPECT_EQ(box_always_both_scrollbars.right, 0);
-
- auto* stable_force = GetDocument().getElementById("stable_force");
- auto* box_stable_force = stable_force->GetLayoutBox();
- EXPECT_EQ(box_stable_force->OffsetHeight(), 100);
- EXPECT_EQ(box_stable_force->ClientHeight(), 100);
- EXPECT_EQ(box_stable_force->ComputeScrollbars(), box_stable_scrollbars);
-
- auto* stable_both_force = GetDocument().getElementById("stable_both_force");
- auto* box_stable_both_force = stable_both_force->GetLayoutBox();
- EXPECT_EQ(box_stable_both_force->OffsetHeight(), 100);
- EXPECT_EQ(box_stable_both_force->ClientHeight(), 100);
- EXPECT_EQ(box_stable_both_force->ComputeScrollbars(),
- box_stable_both_scrollbars);
-
- // TODO this fails because overflow is "visible"
- auto* always_force = GetDocument().getElementById("always_force");
- auto* box_always_force = always_force->GetLayoutBox();
- EXPECT_EQ(box_always_force->OffsetHeight(), 100);
- EXPECT_LT(box_always_force->ClientHeight(), box_auto->ClientHeight());
- EXPECT_EQ(box_always_force->ComputeScrollbars(), box_always_scrollbars);
-
- auto* always_both_force = GetDocument().getElementById("always_both_force");
- auto* box_always_both_force = always_both_force->GetLayoutBox();
- EXPECT_EQ(box_always_both_force->OffsetHeight(), 100);
- EXPECT_LT(box_always_both_force->ClientHeight(),
- box_always_force->ClientHeight());
- EXPECT_EQ(box_always_both_force->ComputeScrollbars(),
- box_always_both_scrollbars);
+ auto* stable_both_edges = GetDocument().getElementById("stable_both_edges");
+ auto* box_stable_both_edges = stable_both_edges->GetLayoutBox();
+ EXPECT_EQ(box_stable_both_edges->OffsetHeight(), 100);
+ EXPECT_EQ(box_stable_both_edges->ClientHeight(), 100);
+ NGPhysicalBoxStrut box_stable_both_edges_scrollbars =
+ box_stable_both_edges->ComputeScrollbars();
+ EXPECT_EQ(box_stable_both_edges_scrollbars.top, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.bottom, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.left, 0);
+ EXPECT_EQ(box_stable_both_edges_scrollbars.right, 0);
}
-// Test the additional gutter created by the "both" keyword of scrollbar-gutter.
-TEST_F(ScrollbarsTest, ScrollbarGutterBothKeywordWithClassicScrollbars) {
+// Test events on the additional gutter created by the "both-edges" keyword of
+// scrollbar-gutter.
+TEST_P(ScrollbarsTest, ScrollbarGutterBothEdgesKeywordWithClassicScrollbars) {
// This test requires that scrollbars take up space.
ENABLE_OVERLAY_SCROLLBARS(false);
@@ -3561,7 +3267,7 @@ TEST_F(ScrollbarsTest, ScrollbarGutterBothKeywordWithClassicScrollbars) {
margin: 0;
}
#container {
- scrollbar-gutter: always both;
+ scrollbar-gutter: stable both-edges;
width: 200px;
height: 200px;
overflow: auto;
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 ace00d2eab0..a1ed2cc954b 100644
--- a/chromium/third_party/blink/renderer/core/layout/shapes/shape.cc
+++ b/chromium/third_party/blink/renderer/core/layout/shapes/shape.cc
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.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/graphics/paint/paint_flags.h"
@@ -276,9 +277,12 @@ static bool ExtractImageData(Image* image,
IntRect image_dest_rect(IntPoint(), image_size);
SkiaPaintCanvas canvas(surface->getCanvas());
canvas.clear(SK_ColorTRANSPARENT);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
+ draw_options.respect_image_orientation = respect_orientation;
image->Draw(&canvas, flags, FloatRect(image_dest_rect), image_source_rect,
- SkSamplingOptions(), respect_orientation,
- Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
+ draw_options, Image::kDoNotClampImageToSourceRect,
+ Image::kSyncDecode);
return true;
}
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 1f8a3f27900..e54ebef7483 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
@@ -148,21 +148,14 @@ void ShapeOutsideInfo::SetPercentageResolutionInlineSize(
static bool CheckShapeImageOrigin(Document& document,
const StyleImage& style_image) {
- if (style_image.IsGeneratedImage())
+ String failing_url;
+ if (style_image.IsAccessAllowed(failing_url))
return true;
-
- DCHECK(style_image.CachedImage());
- ImageResourceContent& image_content = *(style_image.CachedImage());
- if (image_content.IsAccessAllowed())
- return true;
-
- const KURL& url = image_content.Url();
- String url_string = url.IsNull() ? "''" : url.ElidedString();
+ String url_string = failing_url.IsNull() ? "''" : failing_url;
document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kError,
"Unsafe attempt to load URL " + url_string + "."));
-
return false;
}
@@ -196,7 +189,7 @@ std::unique_ptr<Shape> ShapeOutsideInfo::CreateShapeForImage(
LayoutObject::ShouldRespectImageOrientation(layout_box_));
const LayoutSize& image_size = RoundedLayoutSize(style_image->ImageSize(
- layout_box_->GetDocument(), layout_box_->StyleRef().EffectiveZoom(),
+ layout_box_->StyleRef().EffectiveZoom(),
FloatSize(reference_box_logical_size_), respect_orientation));
const LayoutRect& margin_rect =
@@ -252,6 +245,7 @@ const Shape& ShapeOutsideInfo::ComputedShape() const {
break;
case ShapeValue::kImage:
DCHECK(shape_value.GetImage());
+ DCHECK(shape_value.GetImage()->IsLoaded());
DCHECK(shape_value.GetImage()->CanRender());
shape_ = CreateShapeForImage(shape_value.GetImage(),
shape_image_threshold, writing_mode, margin);
@@ -391,7 +385,7 @@ bool ShapeOutsideInfo::IsEnabledFor(const LayoutBox& box) {
case ShapeValue::kImage: {
StyleImage* image = shape_value->GetImage();
DCHECK(image);
- return image->CanRender() &&
+ return image->IsLoaded() && image->CanRender() &&
CheckShapeImageOrigin(box.GetDocument(), *image);
}
case ShapeValue::kBox:
diff --git a/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h b/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h
index 9beabe702ff..56f49ef84d8 100644
--- a/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h
+++ b/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h
@@ -111,8 +111,9 @@ class ShapeOutsideInfo final {
static ShapeOutsideInfo& EnsureInfo(const LayoutBox& key) {
InfoMap& info_map = ShapeOutsideInfo::GetInfoMap();
- if (ShapeOutsideInfo* info = info_map.at(&key))
- return *info;
+ auto it = info_map.find(&key);
+ if (it != info_map.end())
+ return *it->value;
InfoMap::AddResult result =
info_map.insert(&key, base::WrapUnique(new ShapeOutsideInfo(key)));
return *result.stored_value->value;
diff --git a/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc b/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
index fafe6b6f6a7..e2ae3b7b5b5 100644
--- a/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
+++ b/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
@@ -55,6 +55,7 @@ SubtreeLayoutScope::~SubtreeLayoutScope() {
// these objects to be dirty.
if (!DisplayLockUtilities::LockedAncestorPreventingLayout(*layout_object))
layout_object->AssertLaidOut();
+ layout_object->AssertFragmentTree();
}
#endif
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container_test.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container_test.cc
index 57e3540f9dc..a625a03d0cc 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container_test.cc
@@ -117,4 +117,34 @@ TEST_F(LayoutSVGContainerTest,
EXPECT_TRUE(use->SlowFirstChild()->TransformAffectsVectorEffect());
}
+TEST_F(LayoutSVGContainerTest, PatternWithContentVisibility) {
+ SetBodyInnerHTML(R"HTML(
+ <svg viewBox="0 0 230 100" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <pattern id="pattern" viewBox="0,0,10,10" width="10%" height="10%">
+ <polygon id="polygon" points="0,0 2,5 0,10 5,8 10,10 8,5 10,0 5,2"/>
+ </pattern>
+ </defs>
+
+ <circle id="circle" cx="50" cy="50" r="50" fill="url(#pattern)"/>
+ </svg>
+ )HTML");
+
+ auto* pattern = GetDocument().getElementById("pattern");
+ auto* polygon = GetDocument().getElementById("polygon");
+
+ pattern->setAttribute("style", "contain: strict; content-visibility: hidden");
+
+ UpdateAllLifecyclePhasesForTest();
+
+ polygon->setAttribute("points", "0,0 2,5 0,10");
+
+ // This shouldn't cause a DCHECK, even though the pattern needs layout because
+ // it's under a content-visibility: hidden subtree.
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_TRUE(pattern->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(pattern->GetLayoutObject()->SelfNeedsLayout());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
index 5b61f954cd0..5ce9a312d13 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
@@ -73,17 +73,30 @@ bool LayoutSVGInline::IsObjectBoundingBoxValid() const {
return FirstLineBox();
}
+// static
+void LayoutSVGInline::ObjectBoundingBoxForCursor(NGInlineCursor& cursor,
+ FloatRect& bounds) {
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ if (item.Type() == NGFragmentItem::kSvgText) {
+ bounds.Unite(item.ObjectBoundingBox());
+ } else if (NGInlineCursor descendants = cursor.CursorForDescendants()) {
+ for (; descendants; descendants.MoveToNext()) {
+ const NGFragmentItem& descendant_item = *descendants.CurrentItem();
+ if (descendant_item.Type() == NGFragmentItem::kSvgText)
+ bounds.Unite(descendant_item.ObjectBoundingBox());
+ }
+ }
+ }
+}
+
FloatRect LayoutSVGInline::ObjectBoundingBox() const {
NOT_DESTROYED();
FloatRect bounds;
if (IsInLayoutNGInlineFormattingContext()) {
NGInlineCursor cursor;
- for (cursor.MoveToIncludingCulledInline(*this); cursor;
- cursor.MoveToNextForSameLayoutObject()) {
- const NGFragmentItem& item = *cursor.CurrentItem();
- if (item.Type() == NGFragmentItem::kSVGText)
- bounds.Unite(item.ObjectBoundingBox());
- }
+ cursor.MoveToIncludingCulledInline(*this);
+ ObjectBoundingBoxForCursor(cursor, bounds);
return bounds;
}
for (InlineFlowBox* box : *LineBoxes())
@@ -126,7 +139,7 @@ void LayoutSVGInline::AbsoluteQuads(Vector<FloatQuad>& quads,
for (cursor.MoveToIncludingCulledInline(*this); cursor;
cursor.MoveToNextForSameLayoutObject()) {
const NGFragmentItem& item = *cursor.CurrentItem();
- if (item.Type() == NGFragmentItem::kSVGText) {
+ if (item.Type() == NGFragmentItem::kSvgText) {
quads.push_back(
LocalToAbsoluteQuad(SVGLayoutSupport::ExtendTextBBoxWithStroke(
*this, item.ObjectBoundingBox()),
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
index bad248009ad..96b63313d3c 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
@@ -25,6 +25,8 @@
namespace blink {
+class NGInlineCursor;
+
class LayoutSVGInline : public LayoutInline {
public:
explicit LayoutSVGInline(Element*);
@@ -71,6 +73,9 @@ class LayoutSVGInline : public LayoutInline {
void WillBeRemovedFromTree() override;
bool IsObjectBoundingBoxValid() const;
+
+ static void ObjectBoundingBoxForCursor(NGInlineCursor& cursor,
+ FloatRect& bounds);
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc
index 2d315662935..4fa62afbac9 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc
@@ -26,9 +26,13 @@
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/font_size_functions.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.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/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h"
@@ -102,13 +106,8 @@ void LayoutSVGInlineText::StyleDidChange(StyleDifference diff,
void LayoutSVGInlineText::InvalidateSubtreeLayoutForFontUpdates() {
NOT_DESTROYED();
if (!IsFontFallbackValid()) {
- if (LayoutSVGBlock* text_or_ng_text =
- LayoutSVGText::LocateLayoutSVGTextAncestor(this)) {
- if (auto* text_layout_object = DynamicTo<LayoutSVGText>(text_or_ng_text))
- text_layout_object->SetNeedsTextMetricsUpdate();
- else
- To<LayoutNGSVGText>(text_or_ng_text)->SetNeedsTextMetricsUpdate();
- }
+ LayoutSVGText::NotifySubtreeStructureChanged(
+ this, layout_invalidation_reason::kFontsChanged);
}
LayoutText::InvalidateSubtreeLayoutForFontUpdates();
}
@@ -179,11 +178,60 @@ bool LayoutSVGInlineText::CharacterStartsNewTextChunk(int position) const {
return it->value.HasX() || it->value.HasY();
}
+FloatRect LayoutSVGInlineText::ObjectBoundingBox() const {
+ NOT_DESTROYED();
+ if (!IsInLayoutNGInlineFormattingContext())
+ return FloatLinesBoundingBox();
+
+ FloatRect bounds;
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ if (item.Type() == NGFragmentItem::kSvgText)
+ bounds.Unite(item.ObjectBoundingBox());
+ }
+ return bounds;
+}
+
PositionWithAffinity LayoutSVGInlineText::PositionForPoint(
const PhysicalOffset& point) const {
NOT_DESTROYED();
DCHECK_GE(GetDocument().Lifecycle().GetState(),
DocumentLifecycle::kPrePaintClean);
+
+ if (IsInLayoutNGInlineFormattingContext()) {
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
+ NGInlineCursor last_hit_cursor;
+ PhysicalOffset last_hit_transformed_point;
+ LayoutUnit closest_distance = LayoutUnit::Max();
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
+ PhysicalOffset transformed_point =
+ cursor.CurrentItem()->MapPointInContainer(point);
+ PhysicalRect item_rect = cursor.Current().RectInContainerFragment();
+ LayoutUnit distance;
+ if (!item_rect.Contains(transformed_point) ||
+ !cursor.PositionForPointInChild(transformed_point))
+ distance = item_rect.SquaredDistanceTo(transformed_point);
+ // Intentionally apply '<=', not '<', because we'd like to choose a later
+ // item.
+ if (distance <= closest_distance) {
+ closest_distance = distance;
+ last_hit_cursor = cursor;
+ last_hit_transformed_point = transformed_point;
+ }
+ }
+ if (last_hit_cursor) {
+ auto position_with_affinity =
+ last_hit_cursor.PositionForPointInChild(last_hit_transformed_point);
+ // Note: Due by Bidi adjustment, |position_with_affinity| isn't relative
+ // to this.
+ return AdjustForEditingBoundary(position_with_affinity);
+ }
+ return CreatePositionWithAffinity(0);
+ }
+
if (!HasInlineFragments() || !TextLength())
return CreatePositionWithAffinity(0);
@@ -461,6 +509,11 @@ void LayoutSVGInlineText::ComputeNewScaledFontForStyle(
FontDescription font_description = unscaled_font_description;
font_description.SetComputedSize(scaled_font_size);
+ const float zoom = style.EffectiveZoom();
+ font_description.SetLetterSpacing(font_description.LetterSpacing() *
+ scaling_factor / zoom);
+ font_description.SetWordSpacing(font_description.WordSpacing() *
+ scaling_factor / zoom);
scaled_font =
Font(font_description, document.GetStyleEngine().GetFontSelector());
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h
index da64906f675..f190d9cd9da 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h
@@ -70,6 +70,7 @@ class LayoutSVGInlineText final : public LayoutText {
NOT_DESTROYED();
return "LayoutSVGInlineText";
}
+ PositionWithAffinity PositionForPoint(const PhysicalOffset&) const override;
private:
void TextDidChange() override;
@@ -78,10 +79,7 @@ class LayoutSVGInlineText final : public LayoutText {
void AddMetricsFromRun(const TextRun&, bool& last_character_was_white_space);
- FloatRect ObjectBoundingBox() const override {
- NOT_DESTROYED();
- return FloatLinesBoundingBox();
- }
+ FloatRect ObjectBoundingBox() const override;
bool IsOfType(LayoutObjectType type) const override {
NOT_DESTROYED();
@@ -89,7 +87,6 @@ class LayoutSVGInlineText final : public LayoutText {
LayoutText::IsOfType(type);
}
- PositionWithAffinity PositionForPoint(const PhysicalOffset&) const override;
LayoutRect LocalCaretRect(
const InlineBox*,
int caret_offset,
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 616403176b0..b55cb3b69e3 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
@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
@@ -54,6 +55,8 @@ ClipStrategy DetermineClipStrategy(const SVGGraphicsElement& element) {
const LayoutObject* layout_object = element.GetLayoutObject();
if (!layout_object)
return ClipStrategy::kNone;
+ if (DisplayLockUtilities::LockedAncestorPreventingLayout(*layout_object))
+ return ClipStrategy::kNone;
const ComputedStyle& style = layout_object->StyleRef();
if (style.Display() == EDisplay::kNone ||
style.Visibility() != EVisibility::kVisible)
@@ -62,7 +65,7 @@ ClipStrategy DetermineClipStrategy(const SVGGraphicsElement& element) {
// Only shapes, paths and texts are allowed for clipping.
if (layout_object->IsSVGShape()) {
strategy = ClipStrategy::kPath;
- } else if (layout_object->IsSVGText()) {
+ } else if (layout_object->IsSVGText() || layout_object->IsNGSVGText()) {
// Text requires masking.
strategy = ClipStrategy::kMask;
}
@@ -74,8 +77,12 @@ ClipStrategy DetermineClipStrategy(const SVGElement& element) {
// (https://drafts.fxtf.org/css-masking/#ClipPathElement)
if (auto* svg_use_element = DynamicTo<SVGUseElement>(element)) {
const LayoutObject* use_layout_object = element.GetLayoutObject();
- if (!use_layout_object ||
- use_layout_object->StyleRef().Display() == EDisplay::kNone)
+ if (!use_layout_object)
+ return ClipStrategy::kNone;
+ if (DisplayLockUtilities::LockedAncestorPreventingLayout(
+ *use_layout_object))
+ return ClipStrategy::kNone;
+ if (use_layout_object->StyleRef().Display() == EDisplay::kNone)
return ClipStrategy::kNone;
const SVGGraphicsElement* shape_element =
svg_use_element->VisibleTargetGraphicsElementForClipping();
@@ -270,7 +277,7 @@ bool LayoutSVGResourceClipper::HitTestClipContent(
FloatRect LayoutSVGResourceClipper::ResourceBoundingBox(
const FloatRect& reference_box) {
NOT_DESTROYED();
- DCHECK(!NeedsLayout());
+ DCHECK(!SelfNeedsLayout());
if (local_clip_bounds_.IsEmpty())
CalculateLocalClipBounds();
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
index f8f04a77ec0..8d7fb110b55 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/paint/svg_object_painter.h"
@@ -64,7 +65,9 @@ sk_sp<const PaintRecord> LayoutSVGResourceMasker::CreatePaintRecord(
for (const SVGElement& child_element :
Traversal<SVGElement>::ChildrenOf(*GetElement())) {
const LayoutObject* layout_object = child_element.GetLayoutObject();
- if (!layout_object ||
+ if (!layout_object)
+ continue;
+ if (DisplayLockUtilities::LockedAncestorPreventingLayout(*layout_object) ||
layout_object->StyleRef().Display() == EDisplay::kNone)
continue;
SVGObjectPainter(*layout_object).PaintResourceSubtree(builder.Context());
@@ -90,7 +93,7 @@ FloatRect LayoutSVGResourceMasker::ResourceBoundingBox(
const FloatRect& reference_box,
float reference_box_zoom) {
NOT_DESTROYED();
- DCHECK(!NeedsLayout());
+ DCHECK(!SelfNeedsLayout());
auto* mask_element = To<SVGMaskElement>(GetElement());
DCHECK(mask_element);
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 1edd62a9f10..a14457847a4 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
@@ -24,6 +24,7 @@
#include <memory>
#include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/paint/svg_object_painter.h"
@@ -188,7 +189,7 @@ bool LayoutSVGResourcePattern::ApplyShader(
transform = *additional_transform * transform;
pattern_data->pattern->ApplyToFlags(flags,
AffineTransformToSkMatrix(transform));
- flags.setFilterQuality(kLow_SkFilterQuality);
+ flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
return true;
}
@@ -204,8 +205,20 @@ sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord(
content_transform = tile_transform;
FloatRect bounds(FloatPoint(), size);
+ PaintRecorder paint_recorder;
+ cc::PaintCanvas* canvas = paint_recorder.beginRecording(bounds);
+
+ auto* pattern_content_element = Attributes().PatternContentElement();
+ DCHECK(pattern_content_element);
+ // If the element or some of its ancestor prevents us from doing paint, we can
+ // early out. Note that any locked ancestor would prevent paint.
+ if (DisplayLockUtilities::NearestLockedInclusiveAncestor(
+ *pattern_content_element)) {
+ return paint_recorder.finishRecordingAsPicture();
+ }
+
const auto* pattern_layout_object = To<LayoutSVGResourceContainer>(
- Attributes().PatternContentElement()->GetLayoutObject());
+ pattern_content_element->GetLayoutObject());
DCHECK(pattern_layout_object);
DCHECK(!pattern_layout_object->NeedsLayout());
@@ -215,8 +228,6 @@ sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord(
for (LayoutObject* child = pattern_layout_object->FirstChild(); child;
child = child->NextSibling())
SVGObjectPainter(*child).PaintResourceSubtree(builder.Context());
- PaintRecorder paint_recorder;
- 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 a68efc24ae3..4cd9c85cd68 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
@@ -23,8 +23,10 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
+#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#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/frame/web_feature.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"
@@ -210,7 +212,7 @@ void LayoutSVGRoot::UpdateLayout() {
// StyleDidChange because descendants have not yet run StyleDidChange, so we
// don't know their compositing reasons yet. A layout is scheduled when
// |HasCompositingDescendants()| changes to ensure this is run.
- if (Layer() && RuntimeEnabledFeatures::CompositeSVGEnabled())
+ if (Layer())
Layer()->UpdateSelfPaintingLayer();
// The local-to-border-box transform is a function with the following as
@@ -464,8 +466,8 @@ PositionWithAffinity LayoutSVGRoot::PositionForPoint(
LayoutObject* layout_object = closest_descendant;
AffineTransform transform = layout_object->LocalToSVGParentTransform();
- transform.Translate(To<LayoutSVGText>(layout_object)->Location().X(),
- To<LayoutSVGText>(layout_object)->Location().Y());
+ transform.Translate(To<LayoutBox>(layout_object)->Location().X(),
+ To<LayoutBox>(layout_object)->Location().Y());
while (layout_object) {
layout_object = layout_object->Parent();
if (layout_object->IsSVGRoot())
@@ -588,8 +590,8 @@ PaintLayerType LayoutSVGRoot::LayerTypeRequired() const {
auto layer_type_required = LayoutReplaced::LayerTypeRequired();
if (layer_type_required == kNoPaintLayer) {
// Force a paint layer so,
- // 1) In CompositeSVG mode, a GraphicsLayer can be created if there are
- // directly-composited descendants.
+ // 1) A GraphicsLayer can be created if there are directly-composited
+ // descendants.
// 2) The parent layer will know if there are non-isolated descendants with
// blend mode.
layer_type_required = kForcedPaintLayer;
@@ -599,8 +601,7 @@ PaintLayerType LayoutSVGRoot::LayerTypeRequired() const {
CompositingReasons LayoutSVGRoot::AdditionalCompositingReasons() const {
NOT_DESTROYED();
- return RuntimeEnabledFeatures::CompositeSVGEnabled() &&
- !RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ return !RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
HasDescendantWithCompositingReason()
? CompositingReason::kSVGRoot
: CompositingReason::kNone;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc
index 7f40e148c84..2f2c58c4b85 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc
@@ -123,20 +123,11 @@ TEST_F(LayoutSVGRootTest, RectBasedHitTestPartialOverlap) {
EXPECT_EQ(2, count);
}
-class CompositeSVGLayoutSVGRootTest : public LayoutSVGRootTest,
- private ScopedCompositeSVGForTest {
- public:
- CompositeSVGLayoutSVGRootTest() : ScopedCompositeSVGForTest(true) {
- // The tests don't apply in CompositeAfterPaint.
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- }
-};
-
// A PaintLayer is needed for the purposes of creating a GraphicsLayer to limit
// CompositeSVG to SVG subtrees. This PaintLayer will not be needed with
// CompositeAfterPaint. If compositing is needed for descendants, the paint
// layer should be self-painting. Otherwise, it should be non-self-painting.
-TEST_F(CompositeSVGLayoutSVGRootTest, PaintLayerType) {
+TEST_F(LayoutSVGRootTest, PaintLayerType) {
SetBodyInnerHTML(R"HTML(
<svg id="root" style="width: 200px; height: 200px;">
<rect id="rect" width="100" height="100" fill="green"/>
@@ -159,7 +150,7 @@ TEST_F(CompositeSVGLayoutSVGRootTest, PaintLayerType) {
EXPECT_FALSE(root.Layer()->IsSelfPaintingLayer());
}
-TEST_F(CompositeSVGLayoutSVGRootTest, HasDescendantCompositingReasons) {
+TEST_F(LayoutSVGRootTest, HasDescendantCompositingReasons) {
SetBodyInnerHTML(R"HTML(
<svg id="root" style="width: 200px; height: 200px;">
<rect id="rect" width="100" height="100" fill="green"/>
@@ -214,7 +205,7 @@ TEST_F(CompositeSVGLayoutSVGRootTest, HasDescendantCompositingReasons) {
EXPECT_FALSE(root.HasDescendantCompositingReasons());
}
-TEST_F(CompositeSVGLayoutSVGRootTest, CompositedSVGMetric) {
+TEST_F(LayoutSVGRootTest, CompositedSVGMetric) {
SetBodyInnerHTML(R"HTML(
<style>
.anim { animation: anim 5s infinite; }
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 4e3d2e5564e..e5be30a2e23 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
@@ -45,6 +45,17 @@
namespace blink {
+namespace {
+
+void ClampBoundsToFinite(FloatRect& bounds) {
+ bounds.SetX(clampTo<float>(bounds.X()));
+ bounds.SetY(clampTo<float>(bounds.Y()));
+ bounds.SetWidth(clampTo<float>(bounds.Width()));
+ bounds.SetHeight(clampTo<float>(bounds.Height()));
+}
+
+} // namespace
+
LayoutSVGShape::LayoutSVGShape(SVGGeometryElement* node,
StrokeGeometryClass geometry_class)
: LayoutSVGModelObject(node),
@@ -121,6 +132,7 @@ void LayoutSVGShape::UpdateShapeFromElement() {
NOT_DESTROYED();
CreatePath();
fill_bounding_box_ = GetPath().TightBoundingRect();
+ ClampBoundsToFinite(fill_bounding_box_);
if (HasNonScalingStroke()) {
// NonScalingStrokeTransform may depend on LocalTransform which in turn may
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 b3153f2d551..4d352bc6c4c 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
@@ -455,7 +455,7 @@ static SearchCandidate SearchTreeForFindClosestLayoutSVGText(
// containers that could contain LayoutSVGTexts that are closer.
for (LayoutObject* child = layout_object->SlowLastChild(); child;
child = child->PreviousSibling()) {
- if (child->IsSVGText()) {
+ if (child->IsSVGText() || child->IsNGSVGText()) {
float distance = DistanceToChildLayoutObject(child, point);
if (distance >= closest_text.distance)
continue;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.h b/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
index 428e485b59f..1625ee4356f 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
@@ -121,6 +121,7 @@ class CORE_EXPORT SVGLayoutSupport {
const LayoutObject*);
static float CalculateScreenFontSizeScalingFactor(const LayoutObject*);
+ // This returns a LayoutSVGText, a LayoutNGSVGText, or nullptr.
static LayoutObject* FindClosestLayoutSVGText(const LayoutObject*,
const FloatPoint&);
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine.cc b/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine.cc
index fd49e85a8a7..46b3a2c9a78 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine.cc
@@ -415,8 +415,11 @@ void SVGTextLayoutEngine::LayoutTextOnLineOrPath(
if (!logical_text_node)
break;
+ auto it = logical_text_node->CharacterDataMap().find(
+ logical_character_offset_ + 1);
const SVGCharacterData data =
- logical_text_node->CharacterDataMap().at(logical_character_offset_ + 1);
+ it != logical_text_node->CharacterDataMap().end() ? it->value
+ : SVGCharacterData();
// TODO(fs): Use the return value to eliminate the additional
// hash-lookup below when determining if this text box should be tagged
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_baseline.h b/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_baseline.h
index 18bd1950aea..2a75582e241 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_baseline.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_baseline.h
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_spacing.h b/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_spacing.h
index b1fd92e1fea..2efc8ad04d2 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_spacing.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine_spacing.h
@@ -21,7 +21,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_TEXT_LAYOUT_ENGINE_SPACING_H_
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.cc b/chromium/third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.cc
index b73ee6edbc9..afa761ab363 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.cc
@@ -24,7 +24,12 @@ const HitTestLocation* InverseTransformLocationIfNeeded(
storage.emplace(transformed_point,
inverse.MapQuad(location.TransformedRect()));
} else {
- storage.emplace(transformed_point);
+ // Specify |bounding_box| argument even if |location| is not rect-based.
+ // Without it, HitTestLocation would have 1x1 bounding box, and it would
+ // be mapped to NxN screen pixels if scaling factor is N.
+ storage.emplace(transformed_point,
+ PhysicalRect::EnclosingRect(
+ inverse.MapRect(FloatRect(location.BoundingBox()))));
}
return &*storage;
}
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 c37fd88699b..cc89a828e62 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_autosizer.cc
+++ b/chromium/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -1266,8 +1266,6 @@ void TextAutosizer::ApplyMultiplier(LayoutObject* layout_object,
if (multiplier != 1)
page_info_.has_autosized_ = true;
-
- layout_object->ClearBaseComputedStyle();
}
bool TextAutosizer::IsWiderOrNarrowerDescendant(Cluster* cluster) {
@@ -1398,13 +1396,15 @@ bool TextAutosizer::FingerprintMapper::Remove(LayoutObject* layout_object) {
TextAutosizer::Fingerprint TextAutosizer::FingerprintMapper::Get(
const LayoutObject* layout_object) {
- return fingerprints_.at(layout_object);
+ auto it = fingerprints_.find(layout_object);
+ return it != fingerprints_.end() ? it->value : TextAutosizer::Fingerprint();
}
TextAutosizer::BlockSet*
TextAutosizer::FingerprintMapper::GetTentativeClusterRoots(
Fingerprint fingerprint) {
- return blocks_for_fingerprint_.at(fingerprint);
+ auto it = blocks_for_fingerprint_.find(fingerprint);
+ return it != blocks_for_fingerprint_.end() ? &*it->value : nullptr;
}
TextAutosizer::LayoutScope::LayoutScope(LayoutBlock* block,
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 685a96076c6..4837c41544b 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
+++ b/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
@@ -37,6 +37,7 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/text_autosizer_page_info.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/text_run_constructor.h b/chromium/third_party/blink/renderer/core/layout/text_run_constructor.h
index 5fcd51f223b..f386a3000e6 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_run_constructor.h
+++ b/chromium/third_party/blink/renderer/core/layout/text_run_constructor.h
@@ -38,8 +38,8 @@
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/text/text_run.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/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/loader/DEPS b/chromium/third_party/blink/renderer/core/loader/DEPS
index 37e638c13f9..daf3f48e4d8 100644
--- a/chromium/third_party/blink/renderer/core/loader/DEPS
+++ b/chromium/third_party/blink/renderer/core/loader/DEPS
@@ -9,4 +9,7 @@ specific_include_rules = {
"progress_tracker_test.cc" : [
"+base/run_loop.h"
],
+ "prefetched_signed_exchange_manager.cc": [
+ "+services/network/public/cpp/resource_request.h"
+ ],
}
diff --git a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h
index d59cc48ed9a..aff7e3c61ad 100644
--- a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h
+++ b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_ALTERNATE_SIGNED_EXCHANGE_RESOURCE_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_ALTERNATE_SIGNED_EXCHANGE_RESOURCE_INFO_H_
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -69,6 +68,8 @@ class CORE_EXPORT AlternateSignedExchangeResourceInfo {
header_integrity_(header_integrity),
variants_(variants),
variant_key_(variant_key) {}
+ Entry(const Entry&) = delete;
+ Entry& operator=(const Entry&) = delete;
const KURL& anchor_url() const { return anchor_url_; }
const KURL& alternative_url() const { return alternative_url_; }
const String& header_integrity() const { return header_integrity_; }
@@ -81,8 +82,6 @@ class CORE_EXPORT AlternateSignedExchangeResourceInfo {
const String header_integrity_;
const String variants_;
const String variant_key_;
-
- DISALLOW_COPY_AND_ASSIGN(Entry);
};
using EntryMap =
@@ -92,7 +91,11 @@ class CORE_EXPORT AlternateSignedExchangeResourceInfo {
const String& outer_link_header,
const String& inner_link_header);
- AlternateSignedExchangeResourceInfo(EntryMap alternative_resources);
+ explicit AlternateSignedExchangeResourceInfo(EntryMap alternative_resources);
+ AlternateSignedExchangeResourceInfo(
+ const AlternateSignedExchangeResourceInfo&) = delete;
+ AlternateSignedExchangeResourceInfo& operator=(
+ const AlternateSignedExchangeResourceInfo&) = delete;
~AlternateSignedExchangeResourceInfo() = default;
// Returns the best matching alternate resource. If the first entry which
@@ -117,8 +120,6 @@ class CORE_EXPORT AlternateSignedExchangeResourceInfo {
const Vector<String>& languages) const;
const EntryMap alternative_resources_;
-
- DISALLOW_COPY_AND_ASSIGN(AlternateSignedExchangeResourceInfo);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info_test.cc b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info_test.cc
index 454eb98e35c..2c4f2c50c1f 100644
--- a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info_test.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -17,6 +16,10 @@ class AlternateSignedExchangeResourceInfoTest
public:
AlternateSignedExchangeResourceInfoTest()
: ScopedSignedExchangeSubresourcePrefetchForTest(true) {}
+ AlternateSignedExchangeResourceInfoTest(
+ const AlternateSignedExchangeResourceInfoTest&) = delete;
+ AlternateSignedExchangeResourceInfoTest& operator=(
+ const AlternateSignedExchangeResourceInfoTest&) = delete;
~AlternateSignedExchangeResourceInfoTest() override = default;
protected:
@@ -24,9 +27,6 @@ class AlternateSignedExchangeResourceInfoTest
const AlternateSignedExchangeResourceInfo* info) {
return info->alternative_resources_;
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AlternateSignedExchangeResourceInfoTest);
};
TEST_F(AlternateSignedExchangeResourceInfoTest, Empty) {
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
index e91fee9ac51..18400e69656 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
@@ -32,11 +32,11 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_APPCACHE_APPLICATION_CACHE_HOST_H_
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
#include "third_party/blink/public/mojom/appcache/appcache_info.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/appcache/appcache_info.mojom-blink.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -57,6 +57,8 @@ class CORE_EXPORT ApplicationCacheHost
ApplicationCacheHost(
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ApplicationCacheHost(const ApplicationCacheHost&) = delete;
+ ApplicationCacheHost& operator=(const ApplicationCacheHost&) = delete;
~ApplicationCacheHost() override;
virtual void Detach();
@@ -148,8 +150,6 @@ class CORE_EXPORT ApplicationCacheHost
base::OnceClosure select_cache_for_worker_completion_callback_;
FRIEND_TEST_ALL_PREFIXES(DocumentTest, SandboxDisablesAppCache);
-
- DISALLOW_COPY_AND_ASSIGN(ApplicationCacheHost);
};
} // namespace blink
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 29b02414ef3..07ce40cf2bb 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
@@ -137,7 +137,7 @@ void BaseFetchContext::AddClientHintsIfNecessary(
// One exception, however, is that a custom UA is sometimes set without
// specifying accomponying client hints, in which case we disable sending
// them.
- if (ClientHintsPreferences::UserAgentClientHintEnabled() && ua) {
+ if (RuntimeEnabledFeatures::UserAgentClientHintEnabled() && ua) {
// ShouldSendClientHint is called to make sure UA is controlled by
// Permissions Policy.
if (ShouldSendClientHint(ClientHintsMode::kStandard, policy,
@@ -285,7 +285,7 @@ void BaseFetchContext::AddClientHintsIfNecessary(
}
// Only send User Agent hints if the info is available
- if (ClientHintsPreferences::UserAgentClientHintEnabled() && ua) {
+ if (RuntimeEnabledFeatures::UserAgentClientHintEnabled() && ua) {
if (ShouldSendClientHint(ClientHintsMode::kStandard, policy,
resource_origin, is_1p_origin,
network::mojom::blink::WebClientHintsType::kUAArch,
@@ -335,6 +335,16 @@ void BaseFetchContext::AddClientHintsIfNecessary(
network::mojom::blink::WebClientHintsType::kUAFullVersion)],
SerializeHeaderString(ua->full_version));
}
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUABitness,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUABitness)],
+ SerializeHeaderString(ua->bitness));
+ }
}
if (ShouldSendClientHint(
@@ -401,8 +411,9 @@ BaseFetchContext::CheckCSPForRequestInternal(
return absl::nullopt;
}
- if (ShouldDisableCSPCheckForSubresourceRedirectOrigin(request_context,
- redirect_status, url)) {
+ if (ShouldDisableCSPCheckForLitePageSubresourceRedirectOrigin(
+ GetResourceFetcherProperties().GetLitePageSubresourceRedirectOrigin(),
+ request_context, redirect_status, url)) {
return absl::nullopt;
}
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 333cd9c9c30..f7dcbd05c61 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
@@ -7,6 +7,7 @@
#include "net/cookies/site_for_cookies.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
+#include "services/network/public/mojom/web_client_hints_types.mojom-blink-forward.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/build.gni b/chromium/third_party/blink/renderer/core/loader/build.gni
index 8271762986b..19e80890f5b 100644
--- a/chromium/third_party/blink/renderer/core/loader/build.gni
+++ b/chromium/third_party/blink/renderer/core/loader/build.gni
@@ -3,8 +3,6 @@
# found in the LICENSE file.
blink_core_sources_loader = [
- "address_space_feature.cc",
- "address_space_feature.h",
"alternate_signed_exchange_resource_info.cc",
"alternate_signed_exchange_resource_info.h",
"appcache/application_cache.cc",
diff --git a/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc b/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc
index 801d5afb2bf..a7ddf0b7a89 100644
--- a/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc
+++ b/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/loader/cookie_jar.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -11,6 +13,18 @@
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
+namespace {
+
+void LogCookieHistogram(const char* prefix,
+ bool cookie_manager_requested,
+ base::TimeDelta elapsed) {
+ base::UmaHistogramTimes(
+ base::StrCat({prefix, cookie_manager_requested ? "ManagerRequested"
+ : "ManagerAvailable"}),
+ elapsed);
+}
+
+} // namespace
CookieJar::CookieJar(blink::Document* document)
: backend_(document->GetExecutionContext()), document_(document) {}
@@ -27,9 +41,11 @@ void CookieJar::SetCookie(const String& value) {
if (cookie_url.IsEmpty())
return;
- RequestRestrictedCookieManagerIfNeeded();
+ base::ElapsedTimer timer;
+ bool requested = RequestRestrictedCookieManagerIfNeeded();
backend_->SetCookieFromString(cookie_url, document_->SiteForCookies(),
document_->TopFrameOrigin(), value);
+ LogCookieHistogram("Blink.SetCookieTime.", requested, timer.Elapsed());
}
String CookieJar::Cookies() {
@@ -37,10 +53,12 @@ String CookieJar::Cookies() {
if (cookie_url.IsEmpty())
return String();
- RequestRestrictedCookieManagerIfNeeded();
+ base::ElapsedTimer timer;
+ bool requested = RequestRestrictedCookieManagerIfNeeded();
String value;
backend_->GetCookiesString(cookie_url, document_->SiteForCookies(),
document_->TopFrameOrigin(), &value);
+ LogCookieHistogram("Blink.CookiesTime.", requested, timer.Elapsed());
return value;
}
@@ -49,20 +67,32 @@ bool CookieJar::CookiesEnabled() {
if (cookie_url.IsEmpty())
return false;
- RequestRestrictedCookieManagerIfNeeded();
+ base::ElapsedTimer timer;
+ bool requested = RequestRestrictedCookieManagerIfNeeded();
bool cookies_enabled = false;
backend_->CookiesEnabledFor(cookie_url, document_->SiteForCookies(),
document_->TopFrameOrigin(), &cookies_enabled);
+ LogCookieHistogram("Blink.CookiesEnabledTime.", requested, timer.Elapsed());
return cookies_enabled;
}
-void CookieJar::RequestRestrictedCookieManagerIfNeeded() {
+void CookieJar::SetCookieManager(
+ mojo::PendingRemote<network::mojom::blink::RestrictedCookieManager>
+ cookie_manager) {
+ backend_.reset();
+ backend_.Bind(std::move(cookie_manager),
+ document_->GetTaskRunner(TaskType::kInternalDefault));
+}
+
+bool CookieJar::RequestRestrictedCookieManagerIfNeeded() {
if (!backend_.is_bound() || !backend_.is_connected()) {
backend_.reset();
document_->GetFrame()->GetBrowserInterfaceBroker().GetInterface(
backend_.BindNewPipeAndPassReceiver(
document_->GetTaskRunner(TaskType::kInternalDefault)));
+ return true;
}
+ return false;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/cookie_jar.h b/chromium/third_party/blink/renderer/core/loader/cookie_jar.h
index 99729ec8ac3..4d1861d9ea8 100644
--- a/chromium/third_party/blink/renderer/core/loader/cookie_jar.h
+++ b/chromium/third_party/blink/renderer/core/loader/cookie_jar.h
@@ -23,9 +23,12 @@ class CookieJar : public GarbageCollected<CookieJar> {
void SetCookie(const String& value);
String Cookies();
bool CookiesEnabled();
+ void SetCookieManager(
+ mojo::PendingRemote<network::mojom::blink::RestrictedCookieManager>
+ cookie_manager);
private:
- void RequestRestrictedCookieManagerIfNeeded();
+ bool RequestRestrictedCookieManagerIfNeeded();
HeapMojoRemote<network::mojom::blink::RestrictedCookieManager> backend_;
Member<blink::Document> document_;
diff --git a/chromium/third_party/blink/renderer/core/loader/cookie_jar_unittest.cc b/chromium/third_party/blink/renderer/core/loader/cookie_jar_unittest.cc
new file mode 100644
index 00000000000..398824ec24c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/cookie_jar_unittest.cc
@@ -0,0 +1,88 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/loader/cookie_jar.h"
+
+#include "base/test/metrics/histogram_tester.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.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+
+namespace blink {
+namespace {
+
+class CookieJarTest : public testing::Test {
+ public:
+ CookieJarTest() {
+ url_test_helpers::RegisterMockedURLLoad(
+ url_test_helpers::ToKURL("https://example.com/hello_world.html"),
+ test::CoreTestDataPath("hello_world.html"));
+ web_view_helper_.InitializeAndLoad("https://example.com/hello_world.html");
+ }
+
+ ~CookieJarTest() override {
+ url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
+ }
+
+ Document* GetDocument() {
+ return web_view_helper_.LocalMainFrame()->GetFrame()->GetDocument();
+ }
+
+ private:
+ frame_test_helpers::WebViewHelper web_view_helper_;
+};
+
+TEST_F(CookieJarTest, SetCookieHistogram) {
+ V8TestingScope scope;
+ {
+ base::HistogramTester histogram;
+ GetDocument()->setCookie("foo=bar", scope.GetExceptionState());
+ histogram.ExpectTotalCount("Blink.SetCookieTime.ManagerRequested", 1);
+ histogram.ExpectTotalCount("Blink.SetCookieTime.ManagerAvailable", 0);
+ }
+ {
+ base::HistogramTester histogram;
+ GetDocument()->setCookie("foo=bar", scope.GetExceptionState());
+ histogram.ExpectTotalCount("Blink.SetCookieTime.ManagerRequested", 0);
+ histogram.ExpectTotalCount("Blink.SetCookieTime.ManagerAvailable", 1);
+ }
+}
+
+TEST_F(CookieJarTest, CookiesHistogram) {
+ V8TestingScope scope;
+ {
+ base::HistogramTester histogram;
+ GetDocument()->cookie(scope.GetExceptionState());
+ histogram.ExpectTotalCount("Blink.CookiesTime.ManagerRequested", 1);
+ histogram.ExpectTotalCount("Blink.CookiesTime.ManagerAvailable", 0);
+ }
+ {
+ base::HistogramTester histogram;
+ GetDocument()->cookie(scope.GetExceptionState());
+ histogram.ExpectTotalCount("Blink.CookiesTime.ManagerRequested", 0);
+ histogram.ExpectTotalCount("Blink.CookiesTime.ManagerAvailable", 1);
+ }
+}
+
+TEST_F(CookieJarTest, CookiesEnabledHistogram) {
+ {
+ base::HistogramTester histogram;
+ GetDocument()->CookiesEnabled();
+ histogram.ExpectTotalCount("Blink.CookiesEnabledTime.ManagerRequested", 1);
+ histogram.ExpectTotalCount("Blink.CookiesEnabledTime.ManagerAvailable", 0);
+ }
+ {
+ base::HistogramTester histogram;
+ GetDocument()->CookiesEnabled();
+ histogram.ExpectTotalCount("Blink.CookiesEnabledTime.ManagerRequested", 0);
+ histogram.ExpectTotalCount("Blink.CookiesEnabledTime.ManagerAvailable", 1);
+ }
+}
+
+} // namespace
+} // namespace blink
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 a43e765a9fd..95c4c3e0f07 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
@@ -281,4 +281,12 @@ void DocumentLoadTiming::MarkCommitNavigationEnd() {
NotifyDocumentTimingChanged();
}
+void DocumentLoadTiming::MarkActivationStart(base::TimeTicks activation_start) {
+ activation_start_ = activation_start;
+ TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "activationtart",
+ activation_start, "frame",
+ ToTraceValue(GetFrame()));
+ NotifyDocumentTimingChanged();
+}
+
} // namespace blink
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 73c6bf156ed..3a834a5d66a 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
@@ -83,6 +83,8 @@ class CORE_EXPORT DocumentLoadTiming final {
void MarkLoadEventStart();
void MarkLoadEventEnd();
+ void MarkActivationStart(base::TimeTicks);
+
void SetCanRequestFromPreviousDocument(bool value) {
can_request_from_previous_document_ = value;
}
@@ -112,6 +114,7 @@ class CORE_EXPORT DocumentLoadTiming final {
base::TimeTicks ResponseEnd() const { return response_end_; }
base::TimeTicks LoadEventStart() const { return load_event_start_; }
base::TimeTicks LoadEventEnd() const { return load_event_end_; }
+ base::TimeTicks ActivationStart() const { return activation_start_; }
bool HasCrossOriginRedirect() const { return has_cross_origin_redirect_; }
bool CanRequestFromPreviousDocument() const {
return can_request_from_previous_document_;
@@ -152,6 +155,7 @@ class CORE_EXPORT DocumentLoadTiming final {
base::TimeTicks response_end_;
base::TimeTicks load_event_start_;
base::TimeTicks load_event_end_;
+ base::TimeTicks activation_start_;
bool has_cross_origin_redirect_;
bool can_request_from_previous_document_;
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 7c395d88dfa..5f0be38667a 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.cc
@@ -40,9 +40,12 @@
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/mojom/commit_result/commit_result.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.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_content_security_policy_struct.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/app_history/app_history.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -70,7 +73,6 @@
#include "third_party/blink/renderer/core/inspector/console_message.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/loader/address_space_feature.h"
#include "third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h"
#include "third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h"
#include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h"
@@ -82,6 +84,7 @@
#include "third_party/blink/renderer/core/loader/preload_helper.h"
#include "third_party/blink/renderer/core/loader/progress_tracker.h"
#include "third_party/blink/renderer/core/loader/subresource_filter.h"
+#include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -99,6 +102,7 @@
#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_parameters.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.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_loader_options.h"
@@ -116,6 +120,7 @@
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
@@ -227,7 +232,6 @@ struct SameSizeAsDocumentLoader
: public GarbageCollected<SameSizeAsDocumentLoader>,
public UseCounter,
public WebNavigationBodyLoader::Client {
- Vector<KURL> redirect_chain;
Member<MHTMLArchive> archive;
std::unique_ptr<WebNavigationParams> params;
std::unique_ptr<PolicyContainer> policy_container;
@@ -259,6 +263,7 @@ struct SameSizeAsDocumentLoader
bool is_error_page_for_failed_navigation;
mojo::Remote<mojom::blink::ContentSecurityNotifier> content_security_notifier;
scoped_refptr<SecurityOrigin> origin_to_commit;
+ BlinkStorageKey storage_key;
network::mojom::WebSandboxFlags sandbox_flags;
WebNavigationType navigation_type;
DocumentLoadTiming document_load_timing;
@@ -277,7 +282,7 @@ struct SameSizeAsDocumentLoader
bool in_commit_data;
scoped_refptr<SharedBuffer> data_buffer;
base::UnguessableToken devtools_navigation_token;
- WebURLLoader::DeferType defers_loading;
+ LoaderFreezeMode defers_loading;
bool last_navigation_had_transient_user_activation;
bool had_sticky_activation;
bool is_browser_initiated;
@@ -309,6 +314,8 @@ struct SameSizeAsDocumentLoader
bool is_cross_site_cross_browsing_context_group;
WebVector<WebHistoryItem> app_history_back_entries;
WebVector<WebHistoryItem> app_history_forward_entries;
+ mojo::Remote<blink::mojom::CodeCacheHost> code_cache_host;
+ HashSet<KURL> early_hints_preloaded_resources_;
};
// Asserts size of DocumentLoader, so that whenever a new attribute is added to
@@ -382,6 +389,7 @@ DocumentLoader::DocumentLoader(
origin_to_commit_(params_->origin_to_commit.IsNull()
? nullptr
: params_->origin_to_commit.Get()->IsolatedCopy()),
+ storage_key_(std::move(params_->storage_key)),
sandbox_flags_(params_->sandbox_flags),
navigation_type_(navigation_type),
document_load_timing_(*this),
@@ -396,7 +404,6 @@ DocumentLoader::DocumentLoader(
params_->had_transient_user_activation),
had_sticky_activation_(params_->is_user_activated),
is_browser_initiated_(params_->is_browser_initiated),
- is_prerendering_(params_->is_prerendering),
was_discarded_(params_->was_discarded),
loading_srcdoc_(url_.IsAboutSrcdocURL()),
loading_url_as_empty_document_(!params_->is_static_data &&
@@ -459,19 +466,11 @@ DocumentLoader::DocumentLoader(
}
}
- // The document URL needs to be added to the head of the list as that is
- // where the redirects originated. Note that this is currently broken if we
- // don't reuse the RenderFrame (e.g. cross-site navigations) - this will
- // result in an empty URL or about:blank in that case.
- // TODO(https://crbug.com/1171210): Fix this.
- if (is_client_redirect_)
- redirect_chain_.push_back(frame_->GetDocument()->Url());
-
if (was_blocked_by_document_policy_)
ReplaceWithEmptyDocument();
- if (commit_reason_ != CommitReason::kInitialization)
- redirect_chain_.push_back(url_);
+ for (const auto& resource : params_->early_hints_preloaded_resources)
+ early_hints_preloaded_resources_.insert(resource);
if (IsBackForwardLoadType(params_->frame_load_type))
DCHECK(history_item_);
@@ -493,8 +492,8 @@ DocumentLoader::CreateWebNavigationParamsToCloneDocument() {
// |replaces_current_history_item_| will be false.
// |permissions_policy_| and |document_policy_| are set in CommitNavigation(),
// with the sandbox flags set in CalculateSandboxFlags().
- // |is_client_redirect_| and |redirect_chain_| are not copied since future
- // same-document navigations will clear the redirect chain anyways.
+ // |is_client_redirect_| is not copied since future same-document navigations
+ // will reset the state anyways.
// |archive_| and other states might need to be copied, but we need to add
// fields to WebNavigationParams and create WebMHTMLArchive, etc.
// TODO(https://crbug.com/1151954): Copy |archive_| and other attributes.
@@ -511,6 +510,7 @@ DocumentLoader::CreateWebNavigationParamsToCloneDocument() {
// javascript: URL in an about:blank frame that inherited an origin will cause
// the origin to no longer be aliased).
params->origin_to_commit = window->GetSecurityOrigin();
+ params->storage_key = window->GetStorageKey();
params->sandbox_flags = sandbox_flags_;
params->origin_agent_cluster = origin_agent_cluster_;
params->grant_load_local_resources = grant_load_local_resources_;
@@ -529,7 +529,6 @@ DocumentLoader::CreateWebNavigationParamsToCloneDocument() {
params->had_transient_user_activation =
last_navigation_had_transient_user_activation_;
params->is_browser_initiated = is_browser_initiated_;
- params->is_prerendering = is_prerendering_;
params->was_discarded = was_discarded_;
params->web_bundle_physical_url = web_bundle_physical_url_;
params->web_bundle_claimed_url = web_bundle_claimed_url_;
@@ -543,6 +542,8 @@ DocumentLoader::CreateWebNavigationParamsToCloneDocument() {
CopyInitiatorOriginTrials(initiator_origin_trial_features_);
params->force_enabled_origin_trials =
CopyForceEnabledOriginTrials(force_enabled_origin_trials_);
+ for (const auto& resource : early_hints_preloaded_resources_)
+ params->early_hints_preloaded_resources.push_back(resource);
return params;
}
@@ -642,6 +643,7 @@ void DocumentLoader::DidObserveInputDelay(base::TimeDelta input_delay) {
GetLocalFrameClient().DidObserveInputDelay(input_delay);
}
}
+
void DocumentLoader::DidObserveLoadingBehavior(LoadingBehaviorFlag behavior) {
if (frame_) {
DCHECK_GE(state_, kCommitted);
@@ -666,25 +668,27 @@ WebHistoryCommitType LoadTypeToCommitType(WebFrameLoadType type) {
}
static SinglePageAppNavigationType CategorizeSinglePageAppNavigation(
- SameDocumentNavigationSource same_document_navigation_source,
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type,
WebFrameLoadType frame_load_type) {
// |SinglePageAppNavigationType| falls into this grid according to different
- // combinations of |WebFrameLoadType| and |SameDocumentNavigationSource|:
+ // combinations of |WebFrameLoadType| and |SameDocumentNavigationType|:
//
// HistoryApi Default
// kBackForward illegal otherFragmentNav
// !kBackForward sameDocBack/Forward historyPushOrReplace
- switch (same_document_navigation_source) {
- case kSameDocumentNavigationDefault:
+ switch (same_document_navigation_type) {
+ case mojom::blink::SameDocumentNavigationType::kFragment:
if (frame_load_type == WebFrameLoadType::kBackForward) {
return kSPANavTypeSameDocumentBackwardOrForward;
}
return kSPANavTypeOtherFragmentNavigation;
- case kSameDocumentNavigationHistoryApi:
- // It's illegal to have both kSameDocumentNavigationHistoryApi and
+ case mojom::blink::SameDocumentNavigationType::kHistoryApi:
+ // It's illegal to have both kHistoryApi and
// WebFrameLoadType::kBackForward.
DCHECK(frame_load_type != WebFrameLoadType::kBackForward);
return kSPANavTypeHistoryPushStateOrReplaceState;
+ case mojom::blink::SameDocumentNavigationType::kAppHistoryRespondWith:
+ return kSPANavTypeAppHistoryRespondWith;
}
NOTREACHED();
return kSPANavTypeSameDocumentBackwardOrForward;
@@ -692,27 +696,29 @@ static SinglePageAppNavigationType CategorizeSinglePageAppNavigation(
void DocumentLoader::RunURLAndHistoryUpdateSteps(
const KURL& new_url,
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type,
scoped_refptr<SerializedScriptValue> data,
WebFrameLoadType type,
mojom::blink::ScrollRestorationType scroll_restoration_type) {
+ DCHECK(!IsBackForwardLoadType(type));
// We use the security origin of this frame since callers of this method must
// already have performed same origin checks.
UpdateForSameDocumentNavigation(
- new_url, kSameDocumentNavigationHistoryApi, std::move(data),
+ new_url, same_document_navigation_type, std::move(data),
scroll_restoration_type, type, frame_->DomWindow()->GetSecurityOrigin(),
/*is_synchronously_committed=*/true);
}
void DocumentLoader::UpdateForSameDocumentNavigation(
const KURL& new_url,
- SameDocumentNavigationSource same_document_navigation_source,
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type,
scoped_refptr<SerializedScriptValue> data,
mojom::blink::ScrollRestorationType scroll_restoration_type,
WebFrameLoadType type,
const SecurityOrigin* initiator_origin,
bool is_synchronously_committed) {
SinglePageAppNavigationType single_page_app_navigation_type =
- CategorizeSinglePageAppNavigation(same_document_navigation_source, type);
+ CategorizeSinglePageAppNavigation(same_document_navigation_type, type);
UMA_HISTOGRAM_ENUMERATION(
"RendererScheduler.UpdateForSameDocumentNavigationCount",
single_page_app_navigation_type, kSPANavTypeCount);
@@ -736,18 +742,15 @@ void DocumentLoader::UpdateForSameDocumentNavigation(
original_url_ = new_url;
url_ = new_url;
replaces_current_history_item_ = type != WebFrameLoadType::kStandard;
- bool is_history_api_navigation =
- (same_document_navigation_source == kSameDocumentNavigationHistoryApi);
- if (is_history_api_navigation) {
+ bool is_history_api_or_app_history_navigation =
+ (same_document_navigation_type !=
+ mojom::blink::SameDocumentNavigationType::kFragment);
+ if (is_history_api_or_app_history_navigation) {
// See spec:
// https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
http_method_ = http_names::kGET;
http_body_ = nullptr;
}
- redirect_chain_.clear();
- if (is_client_redirect_)
- redirect_chain_.push_back(old_url);
- redirect_chain_.push_back(new_url);
last_navigation_had_trusted_initiator_ =
initiator_origin ? initiator_origin->IsSameOriginWith(
@@ -760,21 +763,22 @@ void DocumentLoader::UpdateForSameDocumentNavigation(
// that we don't unintentionally clear the token when we reach here from the
// history API.
if (type == WebFrameLoadType::kStandard ||
- same_document_navigation_source == kSameDocumentNavigationDefault) {
+ same_document_navigation_type ==
+ mojom::blink::SameDocumentNavigationType::kFragment) {
bool is_browser_initiated = !initiator_origin;
DCHECK(!(is_browser_initiated && is_synchronously_committed));
has_text_fragment_token_ =
TextFragmentAnchor::GenerateNewTokenForSameDocument(
- *this, type, same_document_navigation_source);
+ *this, type, same_document_navigation_type);
}
SetHistoryItemStateForCommit(history_item_.Get(), type,
- is_history_api_navigation
+ is_history_api_or_app_history_navigation
? HistoryNavigationType::kHistoryApi
: HistoryNavigationType::kFragment,
CommitReason::kRegular);
history_item_->SetDocumentState(frame_->GetDocument()->GetDocumentState());
- if (is_history_api_navigation) {
+ if (is_history_api_or_app_history_navigation) {
history_item_->SetStateObject(std::move(data));
history_item_->SetScrollRestorationType(scroll_restoration_type);
}
@@ -787,9 +791,12 @@ void DocumentLoader::UpdateForSameDocumentNavigation(
commit_type == kWebHistoryInertCommit,
FrameScheduler::NavigationType::kSameDocument);
+ if (auto* mf_checker = frame_->View()->GetMobileFriendlinessChecker())
+ mf_checker->EvaluateNow();
+
GetLocalFrameClient().DidFinishSameDocumentNavigation(
history_item_.Get(), commit_type, is_synchronously_committed,
- is_history_api_navigation, is_client_redirect_);
+ same_document_navigation_type, is_client_redirect_);
probe::DidNavigateWithinDocument(frame_);
if (!was_loading) {
GetLocalFrameClient().DidStopLoading();
@@ -801,6 +808,12 @@ const KURL& DocumentLoader::UrlForHistory() const {
return UnreachableURL().IsEmpty() ? Url() : UnreachableURL();
}
+void DocumentLoader::DidOpenDocumentInputStream(const KURL& url) {
+ url_ = url;
+ // Let the browser know that we have done a document.open().
+ GetLocalFrameClient().DispatchDidOpenDocumentInputStream(url_);
+}
+
void DocumentLoader::SetHistoryItemStateForCommit(
HistoryItem* old_item,
WebFrameLoadType load_type,
@@ -931,7 +944,8 @@ void DocumentLoader::BodyLoadingFinished(
probe::ToCoreProbeSink(GetFrame()), main_resource_identifier_, this,
completion_time, total_encoded_data_length, total_decoded_body_length,
should_report_corb_blocking);
- if (response_.IsHTTP() || is_error_page_for_failed_navigation_) {
+ if (response_.ShouldPopulateResourceTiming() ||
+ is_error_page_for_failed_navigation_) {
// The response is being copied here to pass the Encoded and Decoded
// sizes.
// TODO(yoav): copy the sizes info directly.
@@ -1093,7 +1107,6 @@ void DocumentLoader::HandleRedirect(
navigation_timing_info_->AddRedirect(redirect_response, url_after_redirect);
DCHECK(!GetTiming().FetchStart().is_null());
- redirect_chain_.push_back(url_after_redirect);
GetTiming().AddRedirect(url_before_redirect, url_after_redirect);
}
@@ -1261,21 +1274,6 @@ mojom::CommitResult DocumentLoader::CommitSameDocumentNavigation(
return mojom::blink::CommitResult::RestartCrossDocument;
}
- if (auto* app_history = AppHistory::appHistory(*frame_->DomWindow())) {
- UserNavigationInvolvement involvement = UserNavigationInvolvement::kNone;
- if (triggering_event_info == mojom::blink::TriggeringEventInfo::kUnknown) {
- involvement = UserNavigationInvolvement::kBrowserUI;
- } else if (triggering_event_info ==
- mojom::blink::TriggeringEventInfo::kFromTrustedEvent) {
- involvement = UserNavigationInvolvement::kActivation;
- }
- if (!app_history->DispatchNavigateEvent(url, nullptr,
- NavigateEventType::kFragment,
- frame_load_type, involvement)) {
- return mojom::blink::CommitResult::Aborted;
- }
- }
-
if (!IsBackForwardLoadType(frame_load_type)) {
// For the browser to send a same-document navigation, it will always have a
// fragment. When no fragment is present, the browser loads a new document.
@@ -1303,6 +1301,35 @@ mojom::CommitResult DocumentLoader::CommitSameDocumentNavigation(
}
}
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type =
+ mojom::blink::SameDocumentNavigationType::kFragment;
+ if (auto* app_history = AppHistory::appHistory(*frame_->DomWindow())) {
+ UserNavigationInvolvement involvement = UserNavigationInvolvement::kNone;
+ if (triggering_event_info == mojom::blink::TriggeringEventInfo::kUnknown) {
+ involvement = UserNavigationInvolvement::kBrowserUI;
+ } else if (triggering_event_info ==
+ mojom::blink::TriggeringEventInfo::kFromTrustedEvent) {
+ involvement = UserNavigationInvolvement::kActivation;
+ }
+ auto dispatch_result = app_history->DispatchNavigateEvent(
+ url, nullptr, NavigateEventType::kFragment, frame_load_type,
+ involvement, nullptr, history_item);
+ if (dispatch_result == AppHistory::DispatchResult::kAbort)
+ return mojom::blink::CommitResult::Aborted;
+ // In the kRespondWith case, if the navigation is not back-forward,
+ // DispatchNavigateEvent() will have taken care of emulating a commit and we
+ // can abort here. In the back-forward case, though, DispatchNavigateEvent()
+ // doesn't have all the state needed to correctly commit, so fall through
+ // and let the commit proceed normally, just with the
+ // mojom::blink::SameDocumentNavigationType modified.
+ if (dispatch_result == AppHistory::DispatchResult::kRespondWith) {
+ if (frame_load_type != WebFrameLoadType::kBackForward)
+ return mojom::blink::CommitResult::Aborted;
+ same_document_navigation_type =
+ mojom::blink::SameDocumentNavigationType::kAppHistoryRespondWith;
+ }
+ }
+
// If the requesting document is cross-origin, perform the navigation
// asynchronously to minimize the navigator's ability to execute timing
// attacks. If |is_synchronously_committed| is false, the navigation is
@@ -1313,17 +1340,24 @@ mojom::CommitResult DocumentLoader::CommitSameDocumentNavigation(
frame_->GetTaskRunner(TaskType::kInternalLoading)
->PostTask(
FROM_HERE,
- WTF::Bind(&DocumentLoader::CommitSameDocumentNavigationInternal,
- WrapWeakPersistent(this), url, frame_load_type,
- WrapPersistent(history_item), client_redirect_policy,
- has_transient_user_activation,
- WTF::RetainedRef(initiator_origin),
- is_synchronously_committed, triggering_event_info,
- std::move(extra_data)));
+ WTF::Bind(
+ &DocumentLoader::CommitSameDocumentNavigationInternal,
+ WrapWeakPersistent(this), url, frame_load_type,
+ WrapPersistent(history_item), same_document_navigation_type,
+ client_redirect_policy, has_transient_user_activation,
+ WTF::RetainedRef(initiator_origin), is_synchronously_committed,
+ triggering_event_info, std::move(extra_data)));
} else {
+ // Treat a navigation to the same url as replacing only if it did not
+ // originate from a cross-origin iframe. If |is_synchronously_committed| is
+ // false, the browser process already enforced this policy.
+ if (is_synchronously_committed && !IsBackForwardLoadType(frame_load_type) &&
+ history_item_ && url == history_item_->Url()) {
+ frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
+ }
CommitSameDocumentNavigationInternal(
- url, frame_load_type, history_item, client_redirect_policy,
- has_transient_user_activation, initiator_origin,
+ url, frame_load_type, history_item, same_document_navigation_type,
+ client_redirect_policy, has_transient_user_activation, initiator_origin,
is_synchronously_committed, triggering_event_info,
std::move(extra_data));
}
@@ -1334,6 +1368,7 @@ void DocumentLoader::CommitSameDocumentNavigationInternal(
const KURL& url,
WebFrameLoadType frame_load_type,
HistoryItem* history_item,
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type,
ClientRedirectPolicy client_redirect,
bool has_transient_user_activation,
const SecurityOrigin* initiator_origin,
@@ -1350,8 +1385,6 @@ void DocumentLoader::CommitSameDocumentNavigationInternal(
mojom::blink::TriggeringEventInfo::kNotFromEvent
? kWebNavigationTypeLinkClicked
: kWebNavigationTypeOther);
- if (history_item_ && url == history_item_->Url())
- frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
}
// If we have a client navigation for a different document, a fragment
@@ -1389,7 +1422,7 @@ void DocumentLoader::CommitSameDocumentNavigationInternal(
history_item_ = history_item;
if (extra_data)
GetLocalFrameClient().UpdateDocumentLoader(this, std::move(extra_data));
- UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr,
+ UpdateForSameDocumentNavigation(url, same_document_navigation_type, nullptr,
mojom::blink::ScrollRestorationType::kAuto,
frame_load_type, initiator_origin,
is_synchronously_committed);
@@ -1444,10 +1477,10 @@ void DocumentLoader::StopLoading() {
LoadFailed(ResourceError::CancelledError(Url()));
}
-void DocumentLoader::SetDefersLoading(WebURLLoader::DeferType defers) {
- defers_loading_ = defers;
+void DocumentLoader::SetDefersLoading(LoaderFreezeMode mode) {
+ freeze_mode_ = mode;
if (body_loader_)
- body_loader_->SetDefersLoading(defers);
+ body_loader_->SetDefersLoading(mode);
}
void DocumentLoader::DetachFromFrame(bool flush_microtask_queue) {
@@ -1573,14 +1606,6 @@ void DocumentLoader::StartLoadingInternal() {
HandleRedirect(redirect);
}
- if (!frame_->IsMainFrame()) {
- // We only care about detecting embedded private subresources.
- //
- // TODO(crbug.com/1129326): Revisit this when we have a coherent story for
- // top-level navigations.
- RecordAddressSpaceFeature(FetchType::kNavigation, frame_, response_);
- }
-
ApplyClientHintsConfig(params_->enabled_client_hints);
PreloadHelper::LoadLinksFromHeader(
response_.HttpHeaderField(http_names::kLink),
@@ -1608,13 +1633,13 @@ void DocumentLoader::StartLoadingInternal() {
// synchronously and parse it, and it's already loaded in a buffer usually.
// This means we should not defer, and we'll finish loading synchronously
// from StartLoadingBody().
- body_loader_->StartLoadingBody(this, false /* use_isolated_code_cache */);
+ body_loader_->StartLoadingBody(this, nullptr /*code_cache_host*/);
return;
}
InitializePrefetchedSignedExchangeManager();
- body_loader_->SetDefersLoading(defers_loading_);
+ body_loader_->SetDefersLoading(freeze_mode_);
}
void DocumentLoader::StartLoadingResponse() {
@@ -1681,7 +1706,7 @@ void DocumentLoader::StartLoadingResponse() {
if (!url_.ProtocolIsInHTTPFamily()) {
// We only support code cache for http family, and browser insists on not
// event asking for code cache with other schemes.
- body_loader_->StartLoadingBody(this, false /* use_isolated_code_cache */);
+ body_loader_->StartLoadingBody(this, nullptr /*code_cache_host*/);
return;
}
@@ -1699,7 +1724,12 @@ void DocumentLoader::StartLoadingResponse() {
MakeGarbageCollected<SourceKeyedCachedMetadataHandler>(
WTF::TextEncoding(), std::move(cached_metadata_sender));
- body_loader_->StartLoadingBody(this, use_isolated_code_cache);
+ blink::mojom::CodeCacheHost* code_cache_host = nullptr;
+ if (use_isolated_code_cache) {
+ code_cache_host = GetCodeCacheHost();
+ DCHECK(code_cache_host);
+ }
+ body_loader_->StartLoadingBody(this, code_cache_host);
}
void DocumentLoader::DidInstallNewDocument(Document* document) {
@@ -2129,6 +2159,15 @@ void DocumentLoader::InitializeWindow(Document* owner_document) {
SecurityContext& security_context = frame_->DomWindow()->GetSecurityContext();
security_context.SetSandboxFlags(sandbox_flags_);
+
+ // TODO(https://crbug.com/888079): Just use the storage key sent by the
+ // browser once the browser will be able to compute the origin in all cases.
+ frame_->DomWindow()->SetStorageKey(
+ storage_key_.GetNonce().has_value()
+ ? BlinkStorageKey::CreateWithNonce(security_origin,
+ storage_key_.GetNonce().value())
+ : BlinkStorageKey(security_origin));
+
// Conceptually, SecurityOrigin doesn't have to be initialized after sandbox
// flags are applied, but there's a UseCounter in SetSecurityOrigin() that
// wants to inspect sandbox flags.
@@ -2176,6 +2215,20 @@ void DocumentLoader::CommitNavigation() {
LocalDOMWindow* previous_window = frame_->DomWindow();
InitializeWindow(owner_document);
+ // Record if we have navigated to a non-secure page served from a IP address
+ // in the private address space.
+ //
+ // Use response_.AddressSpace() instead of frame_->DomWindow()->AddressSpace()
+ // since the latter isn't populated in unit tests.
+ if (frame_->IsMainFrame()) {
+ auto address_space = response_.AddressSpace();
+ if ((address_space == network::mojom::blink::IPAddressSpace::kPrivate ||
+ address_space == network::mojom::blink::IPAddressSpace::kLocal) &&
+ !frame_->DomWindow()->IsSecureContext()) {
+ CountUse(WebFeature::kMainFrameNonSecurePrivateAddressSpace);
+ }
+ }
+
SecurityContextInit security_init(frame_->DomWindow());
// The document constructed by XSLTProcessor and ScriptController should
@@ -2214,6 +2267,7 @@ void DocumentLoader::CommitNavigation() {
WillCommitNavigation();
+ is_prerendering_ = frame_->GetPage()->IsPrerendering();
Document* document = frame_->DomWindow()->InstallNewDocument(
DocumentInit::Create()
.WithWindow(frame_->DomWindow(), owner_document)
@@ -2425,7 +2479,7 @@ void DocumentLoader::CreateParserPostCommit() {
// Enable Auto Picture-in-Picture feature for the built-in Chrome OS Video
// Player app.
const url::Origin origin = window->GetSecurityOrigin()->ToUrlOrigin();
- if (origin.scheme() == "chrome-extension" &&
+ if (CommonSchemeRegistry::IsExtensionScheme(origin.scheme()) &&
origin.DomainIs("jcgeabjmjgoblfofpppfkcoakmfobdko") &&
origin.port() == 0) {
window->GetOriginTrialContext()->AddFeature(
@@ -2513,6 +2567,10 @@ void DocumentLoader::CountUse(mojom::WebFeature feature) {
return use_counter_.Count(feature, GetFrame());
}
+void DocumentLoader::CountDeprecation(mojom::WebFeature feature) {
+ return use_counter_.Count(feature, GetFrame());
+}
+
void DocumentLoader::RecordUseCountersForCommit() {
// Pre-commit state, count usage the use counter associated with "this"
// (provisional document loader) instead of frame_'s document loader.
@@ -2553,6 +2611,12 @@ void DocumentLoader::RecordUseCountersForCommit() {
if (client_hints_preferences_.ShouldSend(type))
hints_context.CountClientHints(type);
}
+
+ if (RuntimeEnabledFeatures::EarlyHintsPreloadForNavigationOptInEnabled(
+ frame_->DomWindow()) &&
+ !early_hints_preloaded_resources_.IsEmpty()) {
+ CountUse(WebFeature::kEarlyHintsPreload);
+ }
}
void DocumentLoader::RecordConsoleMessagesForCommit() {
@@ -2634,10 +2698,16 @@ bool DocumentLoader::ConsumeTextFragmentToken() {
return token_value;
}
-void DocumentLoader::NotifyPrerenderingDocumentActivated() {
+void DocumentLoader::NotifyPrerenderingDocumentActivated(
+ base::TimeTicks activation_start) {
DCHECK(!frame_->GetDocument()->IsPrerendering());
DCHECK(is_prerendering_);
is_prerendering_ = false;
+ GetTiming().MarkActivationStart(activation_start);
+}
+
+HashSet<KURL> DocumentLoader::GetEarlyHintsPreloadedResources() {
+ return early_hints_preloaded_resources_;
}
ContentSecurityPolicy* DocumentLoader::CreateCSP() {
@@ -2649,18 +2719,26 @@ ContentSecurityPolicy* DocumentLoader::CreateCSP() {
// Add policies from the policy container. If this is a XSLT or javascript:
// document, this will just keep the current policies. If this is a local
// scheme document, the policy container contains the right policies (as
- // inherited in the NavigationRequest in the browser). If CSP Embedded
- // Enforcement was used on this frame and the response allowed blanket
- // enforcement, the policy container includes the enforced policy. Otherwise,
- // the policy container is empty.
+ // inherited in the NavigationRequest in the browser). If this is a network
+ // scheme document, the policy container will contain the parsed CSP from the
+ // response. If CSP Embedded Enforcement was used on this frame and the
+ // response allowed blanket enforcement, the policy container includes the
+ // enforced policy.
csp->AddPolicies(
mojo::Clone(policy_container_->GetPolicies().content_security_policies));
- Vector<network::mojom::blink::ContentSecurityPolicyPtr> parsed_policies =
- ParseContentSecurityPolicyHeaders(
- ContentSecurityPolicyResponseHeaders(response_));
- policy_container_->AddContentSecurityPolicies(mojo::Clone(parsed_policies));
- csp->AddPolicies(std::move(parsed_policies));
+ // Check if the embedder wants to add any default policies, and add them.
+ WebVector<WebContentSecurityPolicyHeader> embedder_default_csp;
+ Platform::Current()->AppendContentSecurityPolicy(WebURL(Url()),
+ &embedder_default_csp);
+ for (const auto& header : embedder_default_csp) {
+ Vector<network::mojom::blink::ContentSecurityPolicyPtr>
+ parsed_embedder_policies = ParseContentSecurityPolicies(
+ header.header_value, header.type, header.source, Url());
+ policy_container_->AddContentSecurityPolicies(
+ mojo::Clone(parsed_embedder_policies));
+ csp->AddPolicies(std::move(parsed_embedder_policies));
+ }
// Retrieve CSP stored in the OriginPolicy and add them to the policy
// container.
@@ -2671,6 +2749,50 @@ ContentSecurityPolicy* DocumentLoader::CreateCSP() {
return csp;
}
+bool& GetDisableCodeCacheForTesting() {
+ static bool disable_code_cache_for_testing = false;
+ return disable_code_cache_for_testing;
+}
+
+blink::mojom::CodeCacheHost* DocumentLoader::GetCodeCacheHost() {
+ if (!code_cache_host_) {
+ if (GetDisableCodeCacheForTesting()) {
+ return nullptr;
+ }
+ // TODO(crbug.com/1083097) When NavigationThreadingOptimizations feature is
+ // enabled by default CodeCacheHost interface will be sent along with
+ // CommitNavigation message and the following code would not be required and
+ // we should just return nullptr here.
+ GetLocalFrameClient().GetBrowserInterfaceBroker().GetInterface(
+ code_cache_host_.BindNewPipeAndPassReceiver());
+ code_cache_host_.set_disconnect_handler(WTF::Bind(
+ &DocumentLoader::OnCodeCacheHostClosed, WrapWeakPersistent(this)));
+ }
+ return code_cache_host_.get();
+}
+
+void DocumentLoader::OnCodeCacheHostClosed() {
+ code_cache_host_.reset();
+}
+
+void DocumentLoader::SetCodeCacheHost(
+ mojo::PendingRemote<mojom::CodeCacheHost> code_cache_host) {
+ code_cache_host_.reset();
+ // When NavigationThreadingOptimizations feature is disabled, code_cache_host
+ // can be a nullptr. When this feature is turned off the CodeCacheHost
+ // interface is requested via BrowserBrokerInterface when required.
+ if (code_cache_host) {
+ code_cache_host_.Bind(std::move(code_cache_host));
+ code_cache_host_.set_disconnect_handler(WTF::Bind(
+ &DocumentLoader::OnCodeCacheHostClosed, WrapWeakPersistent(this)));
+ }
+}
+
+// static
+void DocumentLoader::DisableCodeCacheForTesting() {
+ GetDisableCodeCacheForTesting() = true;
+}
+
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 50cea82d626..d75ce933344 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.h
@@ -40,8 +40,10 @@
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
#include "third_party/blink/public/common/permissions_policy/document_policy.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
#include "third_party/blink/public/mojom/loader/content_security_notifier.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-blink.h"
#include "third_party/blink/public/mojom/page_state/page_state.mojom-blink.h"
#include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
@@ -68,11 +70,13 @@
#include "third_party/blink/renderer/core/permissions_policy/policy_helper.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.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/source_keyed_cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
@@ -164,6 +168,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
void RunURLAndHistoryUpdateSteps(
const KURL&,
+ mojom::blink::SameDocumentNavigationType,
scoped_refptr<SerializedScriptValue>,
WebFrameLoadType = WebFrameLoadType::kReplaceCurrentItem,
mojom::blink::ScrollRestorationType =
@@ -172,7 +177,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// |is_synchronously_committed| is described in comment for
// CommitSameDocumentNavigation.
void UpdateForSameDocumentNavigation(const KURL&,
- SameDocumentNavigationSource,
+ mojom::blink::SameDocumentNavigationType,
scoped_refptr<SerializedScriptValue>,
mojom::blink::ScrollRestorationType,
WebFrameLoadType,
@@ -231,7 +236,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
mojom::blink::TriggeringEventInfo,
std::unique_ptr<WebDocumentLoader::ExtraData>);
- void SetDefersLoading(WebURLLoader::DeferType defers);
+ void SetDefersLoading(LoaderFreezeMode);
DocumentLoadTiming& GetTiming() { return document_load_timing_; }
@@ -299,6 +304,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// UseCounter
void CountUse(mojom::WebFeature) override;
+ void CountDeprecation(mojom::WebFeature) override;
void SetApplicationCacheHostForTesting(ApplicationCacheHostForFrame* host) {
application_cache_host_ = host;
@@ -319,7 +325,8 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
return last_navigation_had_trusted_initiator_;
}
- void UpdateUrlForDocumentOpen(const KURL& url) { url_ = url; }
+ // Called when the URL needs to be updated due to a document.open() call.
+ void DidOpenDocumentInputStream(const KURL& url);
enum class HistoryNavigationType {
kDifferentDocument,
@@ -352,11 +359,17 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// Notifies that the prerendering document this loader is working for is
// activated.
- void NotifyPrerenderingDocumentActivated();
+ void NotifyPrerenderingDocumentActivated(base::TimeTicks activation_start);
- protected:
- Vector<KURL> redirect_chain_;
+ blink::mojom::CodeCacheHost* GetCodeCacheHost();
+ void OnCodeCacheHostClosed();
+ void SetCodeCacheHost(
+ mojo::PendingRemote<mojom::CodeCacheHost> code_cache_host);
+ static void DisableCodeCacheForTesting();
+
+ HashSet<KURL> GetEarlyHintsPreloadedResources();
+ protected:
// Based on its MIME type, if the main document's response corresponds to an
// MHTML archive, then every resources will be loaded from this archive.
//
@@ -399,6 +412,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
const KURL&,
WebFrameLoadType,
HistoryItem*,
+ mojom::blink::SameDocumentNavigationType,
ClientRedirectPolicy,
bool has_transient_user_activation,
const SecurityOrigin* initiator_origin,
@@ -526,6 +540,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
content_security_notifier_;
const scoped_refptr<SecurityOrigin> origin_to_commit_;
+ blink::BlinkStorageKey storage_key_;
const network::mojom::WebSandboxFlags sandbox_flags_;
WebNavigationType navigation_type_;
@@ -556,8 +571,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
scoped_refptr<SharedBuffer> data_buffer_;
const base::UnguessableToken devtools_navigation_token_;
- WebURLLoader::DeferType defers_loading_ =
- WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
// Whether the last navigation (cross-document or same-document) that
// committed in this DocumentLoader had transient activation.
@@ -574,7 +588,8 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// Whether this load request was initiated by the browser.
const bool is_browser_initiated_ = false;
- // Whether this loader is working for a prerendering document.
+ // Whether this loader committed a document in a prerendered page that has not
+ // yet been activated. This is only set after commit.
bool is_prerendering_ = false;
// If true, the navigation loading this document should allow a text fragment
@@ -630,6 +645,12 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
WebVector<WebHistoryItem> app_history_back_entries_;
WebVector<WebHistoryItem> app_history_forward_entries_;
+
+ // This is the interface that handles generated code cache
+ // requests to fetch code cache when loading resources.
+ mojo::Remote<blink::mojom::CodeCacheHost> code_cache_host_;
+
+ HashSet<KURL> early_hints_preloaded_resources_;
};
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 e91c50e541c..0d00cc87e9b 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
@@ -8,10 +8,12 @@
#include "base/auto_reset.h"
#include "base/test/scoped_feature_list.h"
+#include "base/unguessable_token.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_loader_client.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -23,6 +25,7 @@
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.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"
@@ -35,11 +38,29 @@ class DocumentLoaderTest : public testing::Test {
void SetUp() override {
web_view_helper_.Initialize();
url_test_helpers::RegisterMockedURLLoad(
+ url_test_helpers::ToKURL("http://example.com/foo.html"),
+ test::CoreTestDataPath("foo.html"));
+ url_test_helpers::RegisterMockedURLLoad(
url_test_helpers::ToKURL("https://example.com/foo.html"),
test::CoreTestDataPath("foo.html"));
url_test_helpers::RegisterMockedURLLoad(
url_test_helpers::ToKURL("https://example.com:8000/foo.html"),
test::CoreTestDataPath("foo.html"));
+ url_test_helpers::RegisterMockedURLLoad(
+ url_test_helpers::ToKURL("http://192.168.1.1/foo.html"),
+ test::CoreTestDataPath("foo.html"), WebString::FromUTF8("text/html"),
+ WebURLLoaderMockFactory::GetSingletonInstance(),
+ network::mojom::IPAddressSpace::kPrivate);
+ url_test_helpers::RegisterMockedURLLoad(
+ url_test_helpers::ToKURL("https://192.168.1.1/foo.html"),
+ test::CoreTestDataPath("foo.html"), WebString::FromUTF8("text/html"),
+ WebURLLoaderMockFactory::GetSingletonInstance(),
+ network::mojom::IPAddressSpace::kPrivate);
+ url_test_helpers::RegisterMockedURLLoad(
+ url_test_helpers::ToKURL("http://somethinglocal/foo.html"),
+ test::CoreTestDataPath("foo.html"), WebString::FromUTF8("text/html"),
+ WebURLLoaderMockFactory::GetSingletonInstance(),
+ network::mojom::IPAddressSpace::kLocal);
}
void TearDown() override {
@@ -412,6 +433,26 @@ TEST_F(DocumentLoaderTest,
EXPECT_FALSE(local_frame->GetDocument()->DeferredCompositorCommitIsAllowed());
}
+TEST_F(DocumentLoaderTest, NavigationToAboutBlank) {
+ const KURL& requestor_url =
+ KURL(NullURL(), "https://subdomain.example.com/foo.html");
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("https://example.com/foo.html");
+
+ const KURL& about_blank_url = KURL(NullURL(), "about:blank");
+ std::unique_ptr<WebNavigationParams> params =
+ std::make_unique<WebNavigationParams>();
+ params->url = about_blank_url;
+ params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
+ params->requestor_origin = WebSecurityOrigin::Create(WebURL(requestor_url));
+ LocalFrame* local_frame =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame());
+ local_frame->Loader().CommitNavigation(std::move(params), nullptr);
+
+ EXPECT_EQ(BlinkStorageKey(SecurityOrigin::Create(requestor_url)),
+ local_frame->DomWindow()->GetStorageKey());
+}
+
TEST_F(DocumentLoaderTest, SameOriginNavigation) {
const KURL& requestor_url =
KURL(NullURL(), "https://www.example.com/foo.html");
@@ -428,6 +469,8 @@ TEST_F(DocumentLoaderTest, SameOriginNavigation) {
To<LocalFrame>(web_view_impl->GetPage()->MainFrame());
local_frame->Loader().CommitNavigation(std::move(params), nullptr);
+ EXPECT_EQ(BlinkStorageKey(SecurityOrigin::Create(same_origin_url)),
+ local_frame->DomWindow()->GetStorageKey());
EXPECT_TRUE(local_frame->Loader()
.GetDocumentLoader()
->LastNavigationHadTrustedInitiator());
@@ -449,9 +492,139 @@ TEST_F(DocumentLoaderTest, CrossOriginNavigation) {
To<LocalFrame>(web_view_impl->GetPage()->MainFrame());
local_frame->Loader().CommitNavigation(std::move(params), nullptr);
+ EXPECT_EQ(BlinkStorageKey(SecurityOrigin::Create(other_origin_url)),
+ local_frame->DomWindow()->GetStorageKey());
EXPECT_FALSE(local_frame->Loader()
.GetDocumentLoader()
->LastNavigationHadTrustedInitiator());
}
+TEST_F(DocumentLoaderTest, StorageKeyFromNavigationParams) {
+ const KURL& requestor_url =
+ KURL(NullURL(), "https://www.example.com/foo.html");
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("https://example.com/foo.html");
+
+ const KURL& other_origin_url =
+ KURL(NullURL(), "https://www.another.com/bar.html");
+ std::unique_ptr<WebNavigationParams> params =
+ WebNavigationParams::CreateWithHTMLBufferForTesting(
+ SharedBuffer::Create(), other_origin_url);
+ params->requestor_origin = WebSecurityOrigin::Create(WebURL(requestor_url));
+
+ blink::StorageKey storage_key_to_commit = blink::StorageKey::CreateWithNonce(
+ url::Origin(), base::UnguessableToken::Create());
+ params->storage_key = storage_key_to_commit;
+
+ LocalFrame* local_frame =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame());
+ local_frame->Loader().CommitNavigation(std::move(params), nullptr);
+
+ EXPECT_EQ(
+ BlinkStorageKey::CreateWithNonce(SecurityOrigin::Create(other_origin_url),
+ storage_key_to_commit.nonce().value()),
+ local_frame->DomWindow()->GetStorageKey());
+}
+
+// Tests that committing a Javascript URL keeps the storage key's nonce of the
+// previous document, ensuring that
+// `DocumentLoader::CreateWebNavigationParamsToCloneDocument` works correctly
+// w.r.t. storage key.
+TEST_F(DocumentLoaderTest, JavascriptURLKeepsStorageKeyNonce) {
+ WebViewImpl* web_view_impl = web_view_helper_.Initialize();
+
+ BlinkStorageKey storage_key = BlinkStorageKey::CreateWithNonce(
+ SecurityOrigin::CreateUniqueOpaque(), base::UnguessableToken::Create());
+
+ LocalFrame* frame = To<LocalFrame>(web_view_impl->GetPage()->MainFrame());
+ frame->DomWindow()->SetStorageKey(storage_key);
+
+ frame->LoadJavaScriptURL(
+ url_test_helpers::ToKURL("javascript:'<p>hello world</p>'"));
+
+ EXPECT_EQ(storage_key.GetNonce(),
+ frame->DomWindow()->GetStorageKey().GetNonce());
+}
+
+TEST_F(DocumentLoaderTest, PublicSecureNotCounted) {
+ // Checking to make sure secure pages served in the public address space
+ // aren't counted for WebFeature::kMainFrameNonSecurePrivateAddressSpace
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("https://example.com/foo.html");
+ Document* document =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame())->GetDocument();
+ EXPECT_FALSE(document->IsUseCounted(
+ WebFeature::kMainFrameNonSecurePrivateAddressSpace));
+}
+
+TEST_F(DocumentLoaderTest, PublicNonSecureNotCounted) {
+ // Checking to make sure non-secure pages served in the public address space
+ // aren't counted for WebFeature::kMainFrameNonSecurePrivateAddressSpace
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("http://example.com/foo.html");
+ Document* document =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame())->GetDocument();
+ EXPECT_FALSE(document->IsUseCounted(
+ WebFeature::kMainFrameNonSecurePrivateAddressSpace));
+}
+
+TEST_F(DocumentLoaderTest, PrivateSecureNotCounted) {
+ // Checking to make sure secure pages served in the private address space
+ // aren't counted for WebFeature::kMainFrameNonSecurePrivateAddressSpace
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("https://192.168.1.1/foo.html");
+ Document* document =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame())->GetDocument();
+ EXPECT_FALSE(document->IsUseCounted(
+ WebFeature::kMainFrameNonSecurePrivateAddressSpace));
+}
+
+TEST_F(DocumentLoaderTest, PrivateNonSecureIsCounted) {
+ // Checking to make sure non-secure pages served in the private address space
+ // are counted for WebFeature::kMainFrameNonSecurePrivateAddressSpace
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("http://192.168.1.1/foo.html");
+ Document* document =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame())->GetDocument();
+ EXPECT_TRUE(document->IsUseCounted(
+ WebFeature::kMainFrameNonSecurePrivateAddressSpace));
+}
+
+TEST_F(DocumentLoaderTest, LocalNonSecureIsCounted) {
+ // Checking to make sure non-secure pages served in the local address space
+ // are counted for WebFeature::kMainFrameNonSecurePrivateAddressSpace
+ WebViewImpl* web_view_impl =
+ web_view_helper_.InitializeAndLoad("http://somethinglocal/foo.html");
+ Document* document =
+ To<LocalFrame>(web_view_impl->GetPage()->MainFrame())->GetDocument();
+ EXPECT_TRUE(document->IsUseCounted(
+ WebFeature::kMainFrameNonSecurePrivateAddressSpace));
+}
+
+TEST_F(DocumentLoaderSimTest, PrivateNonSecureChildFrameNotCounted) {
+ // Checking to make sure non-secure iframes served in the private address
+ // space are not counted for
+ // WebFeature::kMainFrameNonSecurePrivateAddressSpace
+ SimRequest main_resource("http://example.com", "text/html");
+ SimRequest iframe_resource("http://192.168.1.1/foo.html", "text/html");
+ LoadURL("http://example.com");
+
+ main_resource.Write(R"(
+ <iframe id='frame1'></iframe>
+ <script>
+ const iframe = document.getElementById('frame1');
+ iframe.src = 'http://192.168.1.1/foo.html'; // navigation triggered
+ </script>
+ )");
+
+ main_resource.Finish();
+ iframe_resource.Finish();
+
+ auto* child_frame = To<WebLocalFrameImpl>(MainFrame().FirstChild());
+ auto* child_document = child_frame->GetFrame()->GetDocument();
+
+ EXPECT_FALSE(child_document->IsUseCounted(
+ WebFeature::kMainFrameNonSecurePrivateAddressSpace));
+}
+
} // namespace blink
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 dee6f094e2d..4d371442f41 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -89,6 +89,12 @@ String EmptyChromeClient::AcceptLanguages() {
return String();
}
+bool EmptyChromeClient::StartDeferringCommits(LocalFrame& main_frame,
+ base::TimeDelta timeout,
+ cc::PaintHoldingReason reason) {
+ return false;
+}
+
void EmptyLocalFrameClient::BeginNavigation(
const ResourceRequest&,
mojom::RequestContextFrameType,
@@ -140,6 +146,10 @@ RemoteFrame* EmptyLocalFrameClient::AdoptPortal(HTMLPortalElement*) {
return nullptr;
}
+RemoteFrame* EmptyLocalFrameClient::CreateFencedFrame(HTMLFencedFrameElement*) {
+ return nullptr;
+}
+
WebPluginContainerImpl* EmptyLocalFrameClient::CreatePlugin(
HTMLPlugInElement&,
const KURL&,
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 f4e37cb5be1..e405538cf1f 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.h
@@ -31,16 +31,14 @@
#include <memory>
-#include "base/macros.h"
#include "cc/paint/paint_canvas.h"
+#include "cc/trees/paint_holding_reason.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/input/web_menu_source_type.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
-#include "third_party/blink/public/common/widget/screen_infos.h"
#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_spell_check_panel_host_client.h"
@@ -60,6 +58,8 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/display/screen_info.h"
+#include "ui/display/screen_infos.h"
#include "v8/include/v8.h"
/*
@@ -109,8 +109,9 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
void SetOverscrollBehavior(LocalFrame& frame,
const cc::OverscrollBehavior&) override {}
void BeginLifecycleUpdates(LocalFrame& main_frame) override {}
- void StartDeferringCommits(LocalFrame& main_frame,
- base::TimeDelta timeout) override {}
+ bool StartDeferringCommits(LocalFrame& main_frame,
+ base::TimeDelta timeout,
+ cc::PaintHoldingReason reason) override;
void StopDeferringCommits(LocalFrame& main_frame,
cc::PaintHoldingCommitTrigger) override {}
void StartDragging(LocalFrame*,
@@ -176,10 +177,10 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
float WindowToViewportScalar(LocalFrame*, const float s) const override {
return s;
}
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
return empty_screen_infos_.current();
}
- const ScreenInfos& GetScreenInfos(LocalFrame&) const override {
+ const display::ScreenInfos& GetScreenInfos(LocalFrame&) const override {
return empty_screen_infos_;
}
void ContentsSizeChanged(LocalFrame*, const IntSize&) const override {}
@@ -237,12 +238,14 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
BatterySavingsFlags savings) override {}
private:
- const ScreenInfos empty_screen_infos_{ScreenInfo()};
+ const display::ScreenInfos empty_screen_infos_{display::ScreenInfo()};
};
class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
public:
EmptyLocalFrameClient() = default;
+ EmptyLocalFrameClient(const EmptyLocalFrameClient&) = delete;
+ EmptyLocalFrameClient& operator=(const EmptyLocalFrameClient&) = delete;
~EmptyLocalFrameClient() override = default;
bool HasWebView() const override { return true; } // mainly for assertions
@@ -327,6 +330,9 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
mojo::PendingAssociatedReceiver<mojom::blink::Portal>,
mojo::PendingAssociatedRemote<mojom::blink::PortalClient>) override;
RemoteFrame* AdoptPortal(HTMLPortalElement*) override;
+
+ RemoteFrame* CreateFencedFrame(HTMLFencedFrameElement*) override;
+
WebPluginContainerImpl* CreatePlugin(HTMLPlugInElement&,
const KURL&,
const Vector<String>&,
@@ -396,8 +402,6 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
protected:
// Not owned
WebTextCheckClient* text_check_client_;
-
- DISALLOW_COPY_AND_ASSIGN(EmptyLocalFrameClient);
};
class EmptySpellCheckPanelHostClient : public WebSpellCheckPanelHostClient {
@@ -405,12 +409,14 @@ class EmptySpellCheckPanelHostClient : public WebSpellCheckPanelHostClient {
public:
EmptySpellCheckPanelHostClient() = default;
+ EmptySpellCheckPanelHostClient(const EmptySpellCheckPanelHostClient&) =
+ delete;
+ EmptySpellCheckPanelHostClient& operator=(
+ const EmptySpellCheckPanelHostClient&) = delete;
void ShowSpellingUI(bool) override {}
bool IsShowingSpellingUI() override { return false; }
void UpdateSpellingUIWithMisspelledWord(const WebString&) override {}
-
- DISALLOW_COPY_AND_ASSIGN(EmptySpellCheckPanelHostClient);
};
CORE_EXPORT ChromeClient& GetStaticEmptyChromeClientInstance();
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 adb06535236..88b44f2c1d4 100644
--- a/chromium/third_party/blink/renderer/core/loader/form_submission.h
+++ b/chromium/third_party/blink/renderer/core/loader/form_submission.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FORM_SUBMISSION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FORM_SUBMISSION_H_
-#include "base/macros.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/frame/triggering_event_info.mojom-blink-forward.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
@@ -62,6 +61,8 @@ class FormSubmission final : public GarbageCollected<FormSubmission> {
: method_(kGetMethod),
is_multi_part_form_(false),
encoding_type_("application/x-www-form-urlencoded") {}
+ Attributes(const Attributes&) = delete;
+ Attributes& operator=(const Attributes&) = delete;
SubmitMethod Method() const { return method_; }
static SubmitMethod ParseMethodType(const String&);
@@ -92,8 +93,6 @@ class FormSubmission final : public GarbageCollected<FormSubmission> {
AtomicString target_;
AtomicString encoding_type_;
String accept_charset_;
-
- DISALLOW_COPY_AND_ASSIGN(Attributes);
};
static FormSubmission* Create(HTMLFormElement*,
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc b/chromium/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc
index 2304e7d5a20..07ab5d1fd63 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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_feature.h"
@@ -33,6 +33,8 @@ static constexpr WebFeature kWebFeatureMapping[] = {
WebFeature::kClientHintsUAFullVersion,
WebFeature::kClientHintsUAPlatformVersion,
WebFeature::kClientHintsPrefersColorScheme,
+ WebFeature::kClientHintsUABitness,
+ WebFeature::kClientHintsUAReduced,
};
static_assert(static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) +
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 e1566d256a6..669f29b70d1 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
@@ -34,6 +34,7 @@
#include <memory>
#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "net/http/structured_headers.h"
@@ -57,6 +58,7 @@
#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/css/media_values.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/ad_tracker.h"
@@ -255,6 +257,8 @@ ResourceFetcher* FrameFetchContext::CreateFetcherForCommittedDocument(
fetcher->SetImagesEnabled(frame->GetSettings()->GetImagesEnabled());
fetcher->SetAutoLoadImages(
frame->GetSettings()->GetLoadsImagesAutomatically());
+ fetcher->SetEarlyHintsPreloadedResources(
+ loader.GetEarlyHintsPreloadedResources());
return fetcher;
}
@@ -472,7 +476,11 @@ void FrameFetchContext::AddClientHintsIfNecessary(
->navigator()
->SerializeLanguagesForClientHintHeader();
- prefers_color_scheme = document_->InDarkMode() ? "dark" : "light";
+ MediaValues* media_values =
+ MediaValues::CreateDynamicIfFrameExists(GetFrame());
+ bool is_dark_mode = media_values->GetPreferredColorScheme() ==
+ mojom::blink::PreferredColorScheme::kDark;
+ prefers_color_scheme = is_dark_mode ? "dark" : "light";
// TODO(crbug.com/1151050): |SerializeLanguagesForClientHintHeader| getter
// affects later calls if there is a DevTools override. The following blink
@@ -796,7 +804,16 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
const absl::optional<ResourceRequest::RedirectInfo>& redirect_info,
ReportingDisposition reporting_disposition,
const String& devtools_request_id) const {
- if (GetResourceFetcherProperties().IsDetached())
+ const char kWellKnownConversionRegistrationPath[] =
+ "/.well-known/attribution-reporting/trigger-attribution";
+ if (url.GetPath() != kWellKnownConversionRegistrationPath)
+ return false;
+
+ const bool detached = GetResourceFetcherProperties().IsDetached();
+ UMA_HISTOGRAM_BOOLEAN("Conversions.RedirectInterceptedFrameDetached",
+ detached);
+
+ if (detached)
return false;
if (!RuntimeEnabledFeatures::ConversionMeasurementEnabled(
@@ -810,13 +827,12 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
return false;
}
- const char kWellKnownConversionRegsitrationPath[] =
- "/.well-known/attribution-reporting/trigger-attribution";
- if (url.GetPath() != kWellKnownConversionRegsitrationPath)
- return false;
+ const bool feature_policy_enabled = document_->domWindow()->IsFeatureEnabled(
+ mojom::blink::PermissionsPolicyFeature::kAttributionReporting);
+ UMA_HISTOGRAM_BOOLEAN("Conversions.ConversionIgnoredByFeaturePolicy",
+ !feature_policy_enabled);
- if (!document_->domWindow()->IsFeatureEnabled(
- mojom::blink::PermissionsPolicyFeature::kAttributionReporting)) {
+ if (!feature_policy_enabled) {
AuditsIssue::ReportAttributionIssue(
document_->domWindow(),
AttributionReportingIssueType::kPermissionPolicyDisabled,
@@ -879,6 +895,7 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
conversion->reporting_origin = SecurityOrigin::Create(url);
conversion->conversion_data = 0UL;
conversion->event_source_trigger_data = 0UL;
+ conversion->dedup_key = nullptr;
const char kTriggerDataParam[] = "trigger-data";
URLSearchParams* search_params = URLSearchParams::Create(url.Query());
@@ -902,6 +919,7 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
AttributionReportingIssueType::kInvalidAttributionData, absl::nullopt,
nullptr, devtools_request_id);
}
+
// Defaulting to 0 means that it is not possible to selectively convert only
// event sources or navigation sources.
const char kEventSourceTriggerDataParam[] = "event-source-trigger-data";
@@ -914,6 +932,25 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
conversion->event_source_trigger_data = is_valid_integer ? data : 0UL;
}
+ const char kPriorityParam[] = "priority";
+ if (search_params->has(kPriorityParam)) {
+ bool is_valid_integer = false;
+ int64_t priority =
+ search_params->get(kPriorityParam).ToInt64Strict(&is_valid_integer);
+
+ // Default invalid params to 0.
+ conversion->priority = is_valid_integer ? priority : 0;
+ }
+
+ const char kDedupKeyParam[] = "dedup-key";
+ if (search_params->has(kDedupKeyParam)) {
+ bool is_valid_integer = false;
+ int64_t dedup_key =
+ search_params->get(kDedupKeyParam).ToInt64Strict(&is_valid_integer);
+ conversion->dedup_key =
+ is_valid_integer ? mojom::blink::DedupKey::New(dedup_key) : nullptr;
+ }
+
mojo::AssociatedRemote<mojom::blink::ConversionHost> conversion_host;
GetFrame()->GetRemoteNavigationAssociatedInterfaces()->GetInterface(
&conversion_host);
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 dd9ee9c01d8..65a822b4c7c 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
@@ -35,6 +35,7 @@
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/web_client_hints_types.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -44,7 +45,6 @@
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
-#include "third_party/blink/public/platform/web_client_hints_type.h"
#include "third_party/blink/public/platform/web_document_subresource_filter.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/ad_tracker.h"
@@ -541,7 +541,14 @@ TEST_F(FrameFetchContextModifyRequestTest, SendUpgradeInsecureRequestHeader) {
class FrameFetchContextHintsTest : public FrameFetchContextTest {
public:
- FrameFetchContextHintsTest() = default;
+ FrameFetchContextHintsTest() {
+ scoped_feature_list_.InitWithFeatures(
+ /*enabled_features=*/{blink::features::kUserAgentClientHint,
+ blink::features::kLangClientHintHeader,
+ blink::features::
+ kPrefersColorSchemeClientHintHeader},
+ /*disabled_features=*/{});
+ }
void SetUp() override {
// Set the document URL to a secure document.
@@ -584,6 +591,9 @@ class FrameFetchContextHintsTest : public FrameFetchContextTest {
hints_preferences, resource_width, resource_request);
return resource_request.HttpHeaderField(header_name);
}
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
};
// Verify that the client hints should be attached for subresources fetched
@@ -744,9 +754,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
// `Sec-CH-UA-*` requires opt-in.
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
- ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
@@ -760,15 +767,11 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", true, "");
- ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
@@ -776,7 +779,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
{
ClientHintsPreferences preferences;
- preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAPlatform);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
@@ -787,8 +789,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
@@ -801,15 +801,11 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
true, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
@@ -821,15 +817,11 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", true, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
@@ -870,8 +862,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHints) {
ExpectHeader("https://www.example.com/1.gif", "ect", false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-Lang", false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
@@ -892,7 +882,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHints) {
preferences.SetShouldSend(network::mojom::WebClientHintsType::kLang);
preferences.SetShouldSend(network::mojom::WebClientHintsType::kUA);
preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAArch);
- preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAPlatform);
preferences.SetShouldSend(
network::mojom::WebClientHintsType::kUAPlatformVersion);
preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAModel);
@@ -961,7 +950,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHintsPermissionsPolicy) {
preferences.SetShouldSend(network::mojom::WebClientHintsType::kLang);
preferences.SetShouldSend(network::mojom::WebClientHintsType::kUA);
preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAArch);
- preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAPlatform);
preferences.SetShouldSend(
network::mojom::WebClientHintsType::kUAPlatformVersion);
preferences.SetShouldSend(network::mojom::WebClientHintsType::kUAModel);
@@ -1048,8 +1036,6 @@ TEST_F(FrameFetchContextHintsTest, MonitorSomeHintsPermissionsPolicy) {
#endif
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-Lang", false, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Arch", false, "");
- ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Platform", false,
- "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Platform-Version",
false, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Model", false, "");
@@ -1347,6 +1333,86 @@ TEST_F(FrameFetchContextTest, SetFirstPartyCookieWhenDetached) {
net::SiteForCookies::FromUrl(document_url)));
}
+TEST_F(FrameFetchContextTest,
+ SendConversionRequestInsteadOfRedirecting_RecordsDetachedMetric) {
+ const bool kDetach = true;
+ const bool kNoDetach = false;
+
+ const char kTriggerURL[] =
+ "https://www.example.com/.well-known/attribution-reporting/"
+ "trigger-attribution";
+ const char kNoTriggerURL[] = "https://www.example.com/";
+
+ struct {
+ KURL url;
+ bool detach;
+ int expected_bucket;
+ } test_cases[] = {
+ {KURL(kNoTriggerURL), kNoDetach, 0},
+ {KURL(kTriggerURL), kNoDetach, 1},
+ {KURL(kNoTriggerURL), kDetach, 0},
+ {KURL(kTriggerURL), kDetach, 1},
+ };
+
+ for (const auto& test_case : test_cases) {
+ if (test_case.detach)
+ dummy_page_holder = nullptr;
+
+ HistogramTester histograms;
+ GetFetchContext()->SendConversionRequestInsteadOfRedirecting(
+ test_case.url, /*redirect_info=*/absl::nullopt,
+ ReportingDisposition::kReport, /*devtools_request_id=*/"");
+ histograms.ExpectUniqueSample(
+ "Conversions.RedirectInterceptedFrameDetached", test_case.detach,
+ test_case.expected_bucket);
+
+ RecreateFetchContext();
+ }
+}
+
+TEST_F(FrameFetchContextTest,
+ SendConversionRequestInsteadOfRedirecting_RecordsFeaturePolicyMetric) {
+ const bool kEnabled = true;
+ const bool kDisabled = false;
+
+ const char kTriggerURL[] =
+ "https://www.example.com/.well-known/attribution-reporting/"
+ "trigger-attribution";
+ const char kNoTriggerURL[] = "https://www.example.com/";
+
+ // The feature policy is only checked if the URL is same-origin with the
+ // previous URL.
+ const ResourceRequest::RedirectInfo redirect_info(
+ /*original_url=*/KURL(),
+ /*previous_url=*/KURL("https://www.example.com/"));
+
+ struct {
+ KURL url;
+ bool enabled;
+ int expected_bucket;
+ } test_cases[] = {
+ {KURL(kNoTriggerURL), kDisabled, 0},
+ {KURL(kTriggerURL), kDisabled, 1},
+ {KURL(kNoTriggerURL), kEnabled, 0},
+ {KURL(kTriggerURL), kEnabled, 1},
+ };
+
+ for (const auto& test_case : test_cases) {
+ RecreateFetchContext(redirect_info.previous_url,
+ /*permissions_policy_header=*/test_case.enabled
+ ? ""
+ : "attribution-reporting 'none'");
+
+ HistogramTester histograms;
+ GetFetchContext()->SendConversionRequestInsteadOfRedirecting(
+ test_case.url, redirect_info, ReportingDisposition::kReport,
+ /*devtools_request_id=*/"");
+ histograms.ExpectUniqueSample(
+ "Conversions.ConversionIgnoredByFeaturePolicy", !test_case.enabled,
+ test_case.expected_bucket);
+ }
+}
+
TEST_F(FrameFetchContextTest, TopFrameOrigin) {
const KURL document_url("https://www2.example.com/foo/bar");
RecreateFetchContext(document_url);
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 18ced3c2769..a952ede20c0 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
@@ -30,6 +30,7 @@
#include "base/stl_util.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/policy_container.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/triggering_event_info.mojom-blink.h"
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 b483cd48912..3cce358cd3c 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -243,11 +243,11 @@ LocalFrameClient* FrameLoader::Client() const {
return frame_->Client();
}
-void FrameLoader::SetDefersLoading(WebURLLoader::DeferType defers) {
+void FrameLoader::SetDefersLoading(LoaderFreezeMode mode) {
if (frame_->GetDocument())
- frame_->GetDocument()->Fetcher()->SetDefersLoading(defers);
+ frame_->GetDocument()->Fetcher()->SetDefersLoading(mode);
if (document_loader_)
- document_loader_->SetDefersLoading(defers);
+ document_loader_->SetDefersLoading(mode);
}
void FrameLoader::SaveScrollAnchor() {
@@ -450,47 +450,33 @@ void FrameLoader::DidFinishSameDocumentNavigation(
TakeObjectSnapshot();
}
-WebFrameLoadType FrameLoader::DetermineFrameLoadType(
+WebFrameLoadType FrameLoader::HandleInitialEmptyDocumentReplacementIfNeeded(
const KURL& url,
- const AtomicString& http_method,
- bool has_origin_window,
- bool is_client_reload,
- const KURL& failing_url,
WebFrameLoadType frame_load_type) {
- // TODO(dgozman): this method is rewriting the load type, which makes it hard
- // to reason about various navigations and their desired load type. We should
- // untangle it and detect the load type at the proper place. See, for example,
- // location.assign() block below.
- // Achieving that is complicated due to similar conditions in many places
- // both in the renderer and in the browser.
+ // Converts navigations from the initial empty document to do replacement if
+ // needed.
if (frame_load_type == WebFrameLoadType::kStandard ||
frame_load_type == WebFrameLoadType::kReplaceCurrentItem) {
if (frame_->Tree().Parent() &&
empty_document_status_ == EmptyDocumentStatus::kOnlyEmpty) {
+ // Subframe navigations from the initial empty document should always do
+ // replacement.
return WebFrameLoadType::kReplaceCurrentItem;
}
if (!frame_->Tree().Parent() && !Client()->BackForwardLength()) {
+ // For main frames, currently only empty-URL navigations will be converted
+ // to do replacement. Note that this will cause the navigation to be
+ // ignored in the browser side, so no NavigationEntry will be added.
+ // TODO(https://crbug.com/1215096, https://crbug.com/524208): Make the
+ // main frame case follow the behavior of subframes (always replace when
+ // navigating from the initial empty document), and that a NavigationEntry
+ // will always be created.
if (Opener() && url.IsEmpty())
return WebFrameLoadType::kReplaceCurrentItem;
return WebFrameLoadType::kStandard;
}
}
- if (frame_load_type != WebFrameLoadType::kStandard)
- return frame_load_type;
-
- if (url == document_loader_->UrlForHistory()) {
- if (http_method == http_names::kPOST)
- return WebFrameLoadType::kStandard;
- if (!has_origin_window || is_client_reload)
- return WebFrameLoadType::kReload;
- return WebFrameLoadType::kReplaceCurrentItem;
- }
-
- if (failing_url == document_loader_->UrlForHistory() &&
- document_loader_->LoadType() == WebFrameLoadType::kReload)
- return WebFrameLoadType::kReload;
-
- return WebFrameLoadType::kStandard;
+ return frame_load_type;
}
bool FrameLoader::AllowRequestForThisFrame(const FrameLoadRequest& request) {
@@ -645,10 +631,8 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
return;
}
- frame_load_type = DetermineFrameLoadType(
- resource_request.Url(), resource_request.HttpMethod(), origin_window,
- request.ClientRedirectReason() == ClientNavigationReason::kReload, KURL(),
- frame_load_type);
+ frame_load_type = HandleInitialEmptyDocumentReplacementIfNeeded(
+ resource_request.Url(), frame_load_type);
bool same_document_navigation =
request.GetNavigationPolicy() == kNavigationPolicyCurrentTab &&
@@ -668,13 +652,14 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
if (auto* app_history = AppHistory::appHistory(*frame_->DomWindow())) {
if (request.GetNavigationPolicy() == kNavigationPolicyCurrentTab) {
- if (!app_history->DispatchNavigateEvent(
+ if (app_history->DispatchNavigateEvent(
url, request.Form(), NavigateEventType::kCrossDocument,
frame_load_type,
request.GetTriggeringEventInfo() ==
mojom::blink::TriggeringEventInfo::kFromTrustedEvent
? UserNavigationInvolvement::kActivation
- : UserNavigationInvolvement::kNone)) {
+ : UserNavigationInvolvement::kNone) !=
+ AppHistory::DispatchResult::kContinue) {
return;
}
}
@@ -960,11 +945,6 @@ void FrameLoader::CommitNavigation(
if (frame_owner)
frame_owner->CancelPendingLazyLoad();
- navigation_params->frame_load_type = DetermineFrameLoadType(
- navigation_params->url, navigation_params->http_method,
- false /* has_origin_window */, false /* is_client_reload */,
- navigation_params->unreachable_url, navigation_params->frame_load_type);
-
// 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
@@ -1105,6 +1085,8 @@ void FrameLoader::StopAllLoaders(bool abort_client) {
}
frame_->GetDocument()->CancelParsing();
+ if (auto* app_history = AppHistory::appHistory(*frame_->DomWindow()))
+ app_history->InformAboutCanceledNavigation();
if (document_loader_)
document_loader_->StopLoading();
if (abort_client)
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 e8a3507a67e..0c98ff061a6 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
@@ -36,13 +36,12 @@
#include <memory>
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/page_state/page_state.mojom-blink.h"
+#include "third_party/blink/public/mojom/page_state/page_state.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
-#include "third_party/blink/public/platform/web_url_loader.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_type.h"
@@ -54,15 +53,16 @@
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/core/loader/history_item.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
class DocumentLoader;
-class LocalFrame;
+class FetchClientSettingsObject;
class Frame;
+class LocalFrame;
class LocalFrameClient;
class ProgressTracker;
class ResourceRequest;
@@ -79,6 +79,8 @@ class CORE_EXPORT FrameLoader final {
public:
explicit FrameLoader(LocalFrame*);
+ FrameLoader(const FrameLoader&) = delete;
+ FrameLoader& operator=(const FrameLoader&) = delete;
~FrameLoader();
void Init(std::unique_ptr<PolicyContainer> policy_container);
@@ -133,7 +135,7 @@ class CORE_EXPORT FrameLoader final {
DocumentLoader* GetDocumentLoader() const { return document_loader_.Get(); }
- void SetDefersLoading(WebURLLoader::DeferType defer);
+ void SetDefersLoading(LoaderFreezeMode mode);
void DidExplicitOpen();
@@ -229,12 +231,9 @@ class CORE_EXPORT FrameLoader final {
private:
bool AllowRequestForThisFrame(const FrameLoadRequest&);
- WebFrameLoadType DetermineFrameLoadType(const KURL& url,
- const AtomicString& http_method,
- bool has_origin_window,
- bool is_client_reload,
- const KURL& failing_url,
- WebFrameLoadType);
+ WebFrameLoadType HandleInitialEmptyDocumentReplacementIfNeeded(
+ const KURL& url,
+ WebFrameLoadType);
bool ShouldPerformFragmentNavigation(bool is_form_submission,
const String& http_method,
@@ -301,8 +300,6 @@ class CORE_EXPORT FrameLoader final {
// The origins for which a legacy TLS version warning has been printed. The
// size of this set is capped, after which no more warnings are printed.
HashSet<String> tls_version_warning_origins_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameLoader);
};
} // namespace blink
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 c1196989421..2d05c17d3e3 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
@@ -38,11 +38,6 @@ enum LoadStartType {
kNavigationWithinSameDocument
};
-enum SameDocumentNavigationSource {
- kSameDocumentNavigationDefault,
- kSameDocumentNavigationHistoryApi,
-};
-
enum class SavePreviousDocumentResources {
kNever,
kUntilOnDOMContentLoaded,
@@ -58,6 +53,7 @@ enum SinglePageAppNavigationType {
kSPANavTypeHistoryPushStateOrReplaceState = 0,
kSPANavTypeSameDocumentBackwardOrForward = 1,
kSPANavTypeOtherFragmentNavigation = 2,
+ kSPANavTypeAppHistoryRespondWith = 3,
kSPANavTypeCount
};
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
index 17f6344eef6..3af9c06ba35 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
@@ -84,16 +84,10 @@ bool FrameResourceFetcherProperties::IsPaused() const {
return frame->GetPage()->Paused();
}
-WebURLLoader::DeferType FrameResourceFetcherProperties::DeferType() const {
+LoaderFreezeMode FrameResourceFetcherProperties::FreezeMode() const {
LocalFrame* frame = document_->GetFrame();
DCHECK(frame);
- return frame->GetLoadDeferType();
-}
-
-bool FrameResourceFetcherProperties::IsLoadDeferred() const {
- LocalFrame* frame = document_->GetFrame();
- DCHECK(frame);
- return frame->IsLoadDeferred();
+ return frame->GetLoaderFreezeMode();
}
bool FrameResourceFetcherProperties::IsLoadComplete() const {
@@ -154,4 +148,10 @@ int FrameResourceFetcherProperties::GetOutstandingThrottledLimit() const {
return IsMainFrame() ? main_frame_limit : sub_frame_limit;
}
+scoped_refptr<SecurityOrigin>
+FrameResourceFetcherProperties::GetLitePageSubresourceRedirectOrigin() const {
+ return SecurityOrigin::CreateFromString(
+ document_->GetSettings()->GetLitePageSubresourceRedirectOrigin());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
index b16de030f4c..30c73ad606d 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
@@ -7,6 +7,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/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -35,15 +36,16 @@ class CORE_EXPORT FrameResourceFetcherProperties final
ControllerServiceWorkerMode GetControllerServiceWorkerMode() const override;
int64_t ServiceWorkerId() const override;
bool IsPaused() const override;
- WebURLLoader::DeferType DeferType() const override;
+ LoaderFreezeMode FreezeMode() const override;
bool IsDetached() const override { return false; }
- bool IsLoadDeferred() const override;
bool IsLoadComplete() const override;
bool ShouldBlockLoadingSubResource() const override;
bool IsSubframeDeprioritizationEnabled() const override;
scheduler::FrameStatus GetFrameStatus() const override;
const KURL& WebBundlePhysicalUrl() const override;
int GetOutstandingThrottledLimit() const override;
+ scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin()
+ const override;
private:
const Member<DocumentLoader> document_loader_;
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 4cd3d899c6b..25c2ef1c9d2 100644
--- a/chromium/third_party/blink/renderer/core/loader/history_item.h
+++ b/chromium/third_party/blink/renderer/core/loader/history_item.h
@@ -68,6 +68,7 @@ class CORE_EXPORT HistoryItem final : public GarbageCollected<HistoryItem> {
public:
ViewState() = default;
ViewState(const ViewState&) = default;
+ ViewState& operator=(const ViewState&) = default;
ScrollOffset visual_viewport_scroll_offset_;
ScrollOffset scroll_offset_;
diff --git a/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.cc b/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.cc
index 748af784874..973eed5f920 100644
--- a/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.cc
+++ b/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.cc
@@ -33,6 +33,8 @@
#include "third_party/blink/renderer/core/loader/http_refresh_scheduler.h"
#include <memory>
+
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/events/current_input_event.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.h b/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.h
index b92be4e00f8..ae68b7483fc 100644
--- a/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.h
+++ b/chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.h
@@ -34,7 +34,6 @@
#include <memory>
-#include "base/macros.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/document.h"
@@ -49,6 +48,8 @@ class CORE_EXPORT HttpRefreshScheduler final
: public GarbageCollected<HttpRefreshScheduler> {
public:
explicit HttpRefreshScheduler(Document*);
+ HttpRefreshScheduler(const HttpRefreshScheduler&) = delete;
+ HttpRefreshScheduler& operator=(const HttpRefreshScheduler&) = delete;
~HttpRefreshScheduler() = default;
bool IsScheduledWithin(base::TimeDelta interval) const;
@@ -81,8 +82,6 @@ class CORE_EXPORT HttpRefreshScheduler final
base::TimeTicks input_timestamp;
};
std::unique_ptr<ScheduledHttpRefresh> refresh_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpRefreshScheduler);
};
} // namespace blink
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 78f8dd959be..1afefe2f3b6 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDLENESS_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDLENESS_DETECTOR_H_
-#include "base/macros.h"
#include "base/task/sequence_manager/task_time_observer.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -29,6 +28,8 @@ class CORE_EXPORT IdlenessDetector
IdlenessDetector(
LocalFrame*,
const base::TickClock* = base::DefaultTickClock::GetInstance());
+ IdlenessDetector(const IdlenessDetector&) = delete;
+ IdlenessDetector& operator=(const IdlenessDetector&) = delete;
void Shutdown();
void WillCommitLoad();
@@ -83,8 +84,6 @@ class CORE_EXPORT IdlenessDetector
base::TimeTicks network_0_quiet_start_time_;
base::TimeTicks network_2_quiet_start_time_;
HeapTaskRunnerTimer<IdlenessDetector> network_quiet_timer_;
-
- DISALLOW_COPY_AND_ASSIGN(IdlenessDetector);
};
} // namespace blink
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 3edafd2862a..c44ab78fecd 100644
--- a/chromium/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/image_loader.cc
@@ -25,11 +25,12 @@
#include <memory>
#include <utility>
+#include "services/network/public/mojom/web_client_hints_types.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.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/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
@@ -813,6 +814,15 @@ void ImageLoader::ImageNotifyFinished(ImageResourceContent* content) {
LazyImageHelper::RecordMetricsOnLoadFinished(html_image_element);
if (content->ErrorOccurred()) {
+ // Record the image fail metric if the `html_image_element` is part of paste
+ // data.
+ if (html_image_element) {
+ const auto& document = GetElement()->GetDocument();
+ LocalFrame* frame = document.GetFrame();
+ if (frame && document.IsPageVisible())
+ frame->GetSystemClipboard()->RecordImageLoadError(
+ html_image_element->ImageSourceURL().GetString());
+ }
pending_load_event_.Cancel();
absl::optional<ResourceError> error = content->GetResourceError();
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 caf19913b46..b56f6f58386 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
@@ -12,6 +12,7 @@
#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/loader/document_loader.h"
+#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
@@ -35,6 +36,10 @@ constexpr base::TimeDelta kFirstInputDelayTraceEventThreshold =
} // namespace
+// A fix for FID computation.
+const base::Feature kFixFirstInputDelayForDesktop{
+ "FixFirstInputDelayForDesktop", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Required length of main thread and network quiet window for determining
// Time to Interactive.
constexpr auto kTimeToInteractiveWindow = base::TimeDelta::FromSeconds(5);
@@ -201,34 +206,33 @@ void InteractiveDetector::HandleForInputDelay(
base::TimeTicks event_platform_timestamp,
base::TimeTicks processing_start) {
DCHECK(event.isTrusted());
+ DCHECK(event.type() == event_type_names::kPointerdown ||
+ event.type() == event_type_names::kPointerup ||
+ event.type() == event_type_names::kMousedown ||
+ event.type() == event_type_names::kMouseup ||
+ event.type() == event_type_names::kKeydown ||
+ event.type() == event_type_names::kClick);
// This only happens sometimes on tests unrelated to InteractiveDetector. It
// is safe to ignore events that are not properly initialized.
if (event_platform_timestamp.is_null())
return;
+ if (event.type() == event_type_names::kMouseup &&
+ !base::FeatureList::IsEnabled(kFixFirstInputDelayForDesktop))
+ return;
+
+ // These variables track the values which will be reported to histograms.
+ base::TimeDelta delay;
+ base::TimeTicks event_timestamp;
+
// We can't report a pointerDown until the pointerUp, in case it turns into a
// scroll.
if (event.type() == event_type_names::kPointerdown) {
pending_pointerdown_delay_ = processing_start - event_platform_timestamp;
pending_pointerdown_timestamp_ = event_platform_timestamp;
return;
- }
-
- // We receive any event relevant for EventTiming, but we only care about
- // events relevant for FirstInputDelay.
- bool event_is_meaningful = event.type() == event_type_names::kPointerup ||
- event.type() == event_type_names::kClick ||
- event.type() == event_type_names::kKeydown ||
- event.type() == event_type_names::kMousedown;
-
- if (!event_is_meaningful)
- return;
-
- // These variables track the values which will be reported to histograms.
- base::TimeDelta delay;
- base::TimeTicks event_timestamp;
- if (event.type() == event_type_names::kPointerup) {
+ } else if (event.type() == event_type_names::kPointerup) {
// PointerUp by itself is not considered a significant input.
if (pending_pointerdown_timestamp_.is_null())
return;
@@ -240,8 +244,27 @@ void InteractiveDetector::HandleForInputDelay(
delay = pending_pointerdown_delay_;
event_timestamp = pending_pointerdown_timestamp_;
} else {
- delay = processing_start - event_platform_timestamp;
- event_timestamp = event_platform_timestamp;
+ if (base::FeatureList::IsEnabled(kFixFirstInputDelayForDesktop)) {
+ if (event.type() == event_type_names::kMousedown) {
+ pending_mousedown_delay_ = processing_start - event_platform_timestamp;
+ pending_mousedown_timestamp_ = event_platform_timestamp;
+ return;
+ } else if (event.type() == event_type_names::kMouseup) {
+ if (pending_mousedown_timestamp_.is_null())
+ return;
+ delay = pending_mousedown_delay_;
+ event_timestamp = pending_mousedown_timestamp_;
+ pending_mousedown_delay_ = base::TimeDelta();
+ pending_mousedown_timestamp_ = base::TimeTicks();
+ } else {
+ // Record delays for click, keydown.
+ delay = processing_start - event_platform_timestamp;
+ event_timestamp = event_platform_timestamp;
+ }
+ } else {
+ delay = processing_start - event_platform_timestamp;
+ event_timestamp = event_platform_timestamp;
+ }
}
pending_pointerdown_delay_ = base::TimeDelta();
pending_pointerdown_timestamp_ = base::TimeTicks();
@@ -254,22 +277,28 @@ void InteractiveDetector::HandleForInputDelay(
if (delay > kFirstInputDelayTraceEventThreshold) {
// Emit a trace event to highlight long first input delays.
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"latency", "Long First Input Delay",
- TRACE_ID_LOCAL(g_num_long_input_events), event_timestamp);
- TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
+ TRACE_ID_WITH_SCOPE("Long First Input Delay",
+ g_num_long_input_events),
+ event_timestamp);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"latency", "Long First Input Delay",
- TRACE_ID_LOCAL(g_num_long_input_events), event_timestamp + delay);
+ TRACE_ID_WITH_SCOPE("Long First Input Delay",
+ g_num_long_input_events),
+ event_timestamp + delay);
g_num_long_input_events++;
}
} else if (delay > kInputDelayTraceEventThreshold) {
// Emit a trace event to highlight long input delays from second input and
// onwards.
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
- "latency", "Long Input Delay", TRACE_ID_LOCAL(g_num_long_input_events),
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "latency", "Long Input Delay",
+ TRACE_ID_WITH_SCOPE("Long Input Delay", g_num_long_input_events),
event_timestamp);
- TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
- "latency", "Long Input Delay", TRACE_ID_LOCAL(g_num_long_input_events),
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
+ "latency", "Long Input Delay",
+ TRACE_ID_WITH_SCOPE("Long Input Delay", g_num_long_input_events),
event_timestamp + delay);
// Apply metadata on stack samples.
base::ApplyMetadataToPastSamples(
@@ -568,6 +597,10 @@ void InteractiveDetector::CheckTimeToInteractiveReached() {
void InteractiveDetector::OnTimeToInteractiveDetected() {
LongTaskDetector::Instance().UnregisterObserver(this);
network_quiet_windows_.clear();
+ LocalFrame* frame = GetSupplementable()->GetFrame();
+ DocumentLoader* loader = GetSupplementable()->Loader();
+ probe::LifecycleEvent(frame, loader, "InteractiveTime",
+ base::TimeTicks::Now().since_origin().InSecondsF());
TRACE_EVENT_MARK_WITH_TIMESTAMP2(
"loading,rail", "InteractiveTime", interactive_time_, "frame",
@@ -648,7 +681,8 @@ void InteractiveDetector::RecordInputEventTimingUKM(
{"keydown", blink::InputEventType::kKeydown},
{"pointerup", blink::InputEventType::kPointerup}};
ukm::builders::InputEvent(source_id)
- .SetEventType(static_cast<int>(event_type_to_enum.at(event_type)))
+ .SetEventType(static_cast<int>(
+ event_type_to_enum.DeprecatedAtOrEmptyValue(event_type)))
.SetInteractiveTiming_InputDelay(input_delay.InMilliseconds())
.SetInteractiveTiming_ProcessingTime(processing_time.InMilliseconds())
.SetInteractiveTiming_ProcessingFinishedToNextPaint(
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 f5abcecf3e8..e829889c9fa 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_INTERACTIVE_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_INTERACTIVE_DETECTOR_H_
-#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -30,6 +29,8 @@ class UkmRecorder;
namespace blink {
+CORE_EXPORT extern const base::Feature kFixFirstInputDelayForDesktop;
+
class Document;
class Event;
@@ -60,14 +61,14 @@ class CORE_EXPORT InteractiveDetector
class CORE_EXPORT NetworkActivityChecker {
public:
explicit NetworkActivityChecker(Document* document) : document_(document) {}
+ NetworkActivityChecker(const NetworkActivityChecker&) = delete;
+ NetworkActivityChecker& operator=(const NetworkActivityChecker&) = delete;
virtual int GetActiveConnections();
virtual ~NetworkActivityChecker() = default;
private:
WeakPersistent<Document> document_;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkActivityChecker);
};
static InteractiveDetector* From(Document&);
@@ -76,6 +77,8 @@ class CORE_EXPORT InteractiveDetector
static const char* SupplementName();
explicit InteractiveDetector(Document&, NetworkActivityChecker*);
+ InteractiveDetector(const InteractiveDetector&) = delete;
+ InteractiveDetector& operator=(const InteractiveDetector&) = delete;
~InteractiveDetector() override = default;
// Calls to base::TimeTicks::Now().since_origin().InSecondsF() is expensive,
@@ -120,7 +123,9 @@ class CORE_EXPORT InteractiveDetector
absl::optional<base::TimeDelta> GetFirstScrollDelay() const;
// Process an input event, updating first_input_delay and
- // first_input_timestamp if needed.
+ // first_input_timestamp if needed. The event types we care about are
+ // pointerdown, pointerup, mousedown, keydown, click, mouseup. And we
+ // check the event types in the caller of this function.
void HandleForInputDelay(const Event&,
base::TimeTicks event_platform_timestamp,
base::TimeTicks processing_start);
@@ -240,13 +245,13 @@ class CORE_EXPORT InteractiveDetector
// for the previous pointer down. Only non-zero if we've received a pointer
// down event, and haven't yet reported the first input delay.
base::TimeDelta pending_pointerdown_delay_;
+ base::TimeDelta pending_mousedown_delay_;
// The timestamp of a pending pointerdown event. Valid in the same cases as
// pending_pointerdown_delay_.
base::TimeTicks pending_pointerdown_timestamp_;
+ base::TimeTicks pending_mousedown_timestamp_;
ukm::UkmRecorder* ukm_recorder_;
-
- DISALLOW_COPY_AND_ASSIGN(InteractiveDetector);
};
} // namespace blink
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 62a6f5b074e..f38d5d1075a 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
@@ -5,6 +5,7 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "base/callback_helpers.h"
+#include "base/test/scoped_feature_list.h"
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -641,4 +642,104 @@ TEST_F(InteractiveDetectorTest, TotalBlockingSingleTask) {
EXPECT_EQ(GetTotalBlockingTime(), base::TimeDelta::FromMilliseconds(350));
}
+TEST_F(InteractiveDetectorTest, FirstInputDelayForClickOnMobile) {
+ auto* detector = GetDetector();
+ base::TimeTicks t0 = Now();
+ // Pointerdown
+ Event pointerdown(event_type_names::kPointerdown, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed, t0);
+ pointerdown.SetTrusted(true);
+ detector->HandleForInputDelay(pointerdown, t0,
+ t0 + base::TimeDelta::FromMilliseconds(17));
+ EXPECT_FALSE(detector->GetFirstInputDelay().has_value());
+ // Pointerup
+ Event pointerup(event_type_names::kPointerup, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed,
+ t0 + base::TimeDelta::FromMilliseconds(20));
+ pointerup.SetTrusted(true);
+ detector->HandleForInputDelay(pointerup,
+ t0 + base::TimeDelta::FromMilliseconds(20),
+ t0 + base::TimeDelta::FromMilliseconds(50));
+ EXPECT_TRUE(detector->GetFirstInputDelay().has_value());
+ EXPECT_EQ(detector->GetFirstInputDelay().value(),
+ base::TimeDelta::FromMilliseconds(17));
+}
+
+TEST_F(InteractiveDetectorTest,
+ FirstInputDelayForClickOnDesktopWithFixEnabled) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(blink::kFixFirstInputDelayForDesktop);
+ auto* detector = GetDetector();
+ base::TimeTicks t0 = Now();
+ // Pointerdown
+ Event pointerdown(event_type_names::kPointerdown, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed, t0);
+ pointerdown.SetTrusted(true);
+ detector->HandleForInputDelay(pointerdown, t0,
+ t0 + base::TimeDelta::FromMilliseconds(17));
+ EXPECT_FALSE(detector->GetFirstInputDelay().has_value());
+ // Mousedown
+ Event mousedown(event_type_names::kMousedown, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed, t0);
+ mousedown.SetTrusted(true);
+ detector->HandleForInputDelay(mousedown, t0,
+ t0 + base::TimeDelta::FromMilliseconds(13));
+ EXPECT_FALSE(detector->GetFirstInputDelay().has_value());
+ // Pointerup
+ Event pointerup(event_type_names::kPointerup, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed,
+ t0 + base::TimeDelta::FromMilliseconds(20));
+ pointerup.SetTrusted(true);
+ detector->HandleForInputDelay(pointerup,
+ t0 + base::TimeDelta::FromMilliseconds(20),
+ t0 + base::TimeDelta::FromMilliseconds(50));
+ EXPECT_TRUE(detector->GetFirstInputDelay().has_value());
+ EXPECT_EQ(detector->GetFirstInputDelay().value(),
+ base::TimeDelta::FromMilliseconds(17));
+}
+
+TEST_F(InteractiveDetectorTest,
+ FirstInputDelayForClickOnDesktopWithFixDisabled) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(blink::kFixFirstInputDelayForDesktop);
+ auto* detector = GetDetector();
+ base::TimeTicks t0 = Now();
+ // Pointerdown
+ Event pointerdown(event_type_names::kPointerdown, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed, t0);
+ pointerdown.SetTrusted(true);
+ detector->HandleForInputDelay(pointerdown, t0,
+ t0 + base::TimeDelta::FromMilliseconds(17));
+ EXPECT_FALSE(detector->GetFirstInputDelay().has_value());
+ // Mousedown
+ Event mousedown(event_type_names::kMousedown, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed, t0);
+ mousedown.SetTrusted(true);
+ detector->HandleForInputDelay(mousedown, t0,
+ t0 + base::TimeDelta::FromMilliseconds(13));
+ EXPECT_TRUE(detector->GetFirstInputDelay().has_value());
+ EXPECT_EQ(detector->GetFirstInputDelay().value(),
+ base::TimeDelta::FromMilliseconds(13));
+
+ // Pointerup
+ Event pointerup(event_type_names::kPointerup, MessageEvent::Bubbles::kYes,
+ MessageEvent::Cancelable::kYes,
+ MessageEvent::ComposedMode::kComposed,
+ t0 + base::TimeDelta::FromMilliseconds(20));
+ pointerup.SetTrusted(true);
+ detector->HandleForInputDelay(pointerup,
+ t0 + base::TimeDelta::FromMilliseconds(20),
+ t0 + base::TimeDelta::FromMilliseconds(50));
+ EXPECT_TRUE(detector->GetFirstInputDelay().has_value());
+ EXPECT_EQ(detector->GetFirstInputDelay().value(),
+ base::TimeDelta::FromMilliseconds(13));
+}
+
} // namespace blink
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 b96aa29f31e..2fce5fd95d9 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
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
index 95fd4e70338..35fc3d7aed7 100644
--- a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
+++ b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
@@ -14,9 +14,12 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url_loader_factory.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/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
@@ -137,7 +140,11 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
std::unique_ptr<WebCodeCacheLoader>
LoaderFactoryForFrame::CreateCodeCacheLoader() {
- return Platform::Current()->CreateCodeCacheLoader();
+ if (document_loader_->GetCodeCacheHost() == nullptr) {
+ return nullptr;
+ }
+ return blink::WebCodeCacheLoader::Create(
+ document_loader_->GetCodeCacheHost());
}
std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
diff --git a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_worker.cc b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_worker.cc
index a94da714c08..67fdded3aad 100644
--- a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_worker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_worker.cc
@@ -99,7 +99,12 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForWorker::CreateURLLoader(
std::unique_ptr<WebCodeCacheLoader>
LoaderFactoryForWorker::CreateCodeCacheLoader() {
- return web_context_->CreateCodeCacheLoader();
+ if (global_scope_->IsWorkerGlobalScope()) {
+ return web_context_->CreateCodeCacheLoader(
+ global_scope_->GetCodeCacheHost());
+ }
+ // TODO(mythria): Get the CodeCacheHost corresponding to worklet global scope.
+ return web_context_->CreateCodeCacheLoader(nullptr);
}
// TODO(altimin): This is used when creating a URLLoader, and
diff --git a/chromium/third_party/blink/renderer/core/loader/long_task_detector.h b/chromium/third_party/blink/renderer/core/loader/long_task_detector.h
index 5fd4bb8d2ab..92d891fd763 100644
--- a/chromium/third_party/blink/renderer/core/loader/long_task_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/long_task_detector.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_LONG_TASK_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_LONG_TASK_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"
@@ -33,6 +32,8 @@ class CORE_EXPORT LongTaskDetector final
static LongTaskDetector& Instance();
LongTaskDetector();
+ LongTaskDetector(const LongTaskDetector&) = delete;
+ LongTaskDetector& operator=(const LongTaskDetector&) = delete;
void RegisterObserver(LongTaskObserver*);
void UnregisterObserver(LongTaskObserver*);
@@ -51,8 +52,6 @@ class CORE_EXPORT LongTaskDetector final
HeapHashSet<Member<LongTaskObserver>> observers_;
HeapVector<Member<LongTaskObserver>> observers_to_be_removed_;
bool iterating_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(LongTaskDetector);
};
} // namespace blink
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 6015dd0637c..fd667ccce58 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
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MIXED_CONTENT_CHECKER_H_
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/loader/content_security_notifier.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/loader/mixed_content.mojom-blink-forward.h"
@@ -147,6 +147,9 @@ class CORE_EXPORT MixedContentChecker final {
static MixedContent::CheckModeForPlugin DecideCheckModeForPlugin(Settings*);
+ MixedContentChecker(const MixedContentChecker&) = delete;
+ MixedContentChecker& operator=(const MixedContentChecker&) = delete;
+
private:
FRIEND_TEST_ALL_PREFIXES(MixedContentCheckerTest, HandleCertificateError);
@@ -164,8 +167,6 @@ class CORE_EXPORT MixedContentChecker final {
static void Count(Frame*,
mojom::blink::RequestContextType,
const LocalFrame*);
-
- DISALLOW_COPY_AND_ASSIGN(MixedContentChecker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
index 643dcdf0296..89e3a240842 100644
--- a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
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 90675dd9c9d..73e41153e50 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
@@ -5,14 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_SCRIPT_CREATION_PARAMS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_SCRIPT_CREATION_PARAMS_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 de102865eae..ca23d99a34e 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_SCRIPT_FETCHER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_SCRIPT_FETCHER_H_
-#include "third_party/abseil-cpp/absl/types/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"
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 0328a325cea..4bb9ac940d8 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_SCRIPT_LOADER_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.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/loader/modulescript/module_script_creation_params.h"
@@ -48,6 +47,8 @@ class CORE_EXPORT ModuleScriptLoader final
const ScriptFetchOptions&,
ModuleScriptLoaderRegistry*,
ModuleScriptLoaderClient*);
+ ModuleScriptLoader(const ModuleScriptLoader&) = delete;
+ ModuleScriptLoader& operator=(const ModuleScriptLoader&) = delete;
~ModuleScriptLoader();
static void Fetch(const ModuleScriptFetchRequest&,
@@ -99,8 +100,6 @@ class CORE_EXPORT ModuleScriptLoader final
#if DCHECK_IS_ON()
KURL url_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(ModuleScriptLoader);
};
} // namespace blink
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 933391b7ea9..3943ae55eec 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
@@ -87,18 +87,6 @@ class ModuleScriptLoaderTestModulator final : public DummyModulator {
ScriptState* GetScriptState() override { return script_state_; }
- void SetModuleRequests(const Vector<String>& requests) {
- requests_.clear();
- for (const String& request : requests) {
- requests_.emplace_back(request, TextPosition::MinimumPosition(),
- Vector<ImportAssertion>());
- }
- }
- Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) override {
- return requests_;
- }
-
ModuleScriptFetcher* CreateModuleScriptFetcher(
ModuleScriptCustomFetchType custom_fetch_type,
base::PassKey<ModuleScriptLoader> pass_key) override {
@@ -117,7 +105,6 @@ class ModuleScriptLoaderTestModulator final : public DummyModulator {
private:
Member<ScriptState> script_state_;
- Vector<ModuleRequest> requests_;
};
void ModuleScriptLoaderTestModulator::Trace(Visitor* visitor) const {
@@ -128,10 +115,10 @@ void ModuleScriptLoaderTestModulator::Trace(Visitor* visitor) const {
} // namespace
class ModuleScriptLoaderTest : public PageTestBase {
- DISALLOW_COPY_AND_ASSIGN(ModuleScriptLoaderTest);
-
public:
ModuleScriptLoaderTest();
+ ModuleScriptLoaderTest(const ModuleScriptLoaderTest&) = delete;
+ ModuleScriptLoaderTest& operator=(const ModuleScriptLoaderTest&) = delete;
void SetUp() override;
void InitializeForDocument();
@@ -424,7 +411,6 @@ void ModuleScriptLoaderTest::TestInvalidSpecifier(
TestModuleScriptLoaderClient* client) {
auto* registry = MakeGarbageCollected<ModuleScriptLoaderRegistry>();
KURL url("data:text/javascript,import 'invalid';export default 'grapes';");
- GetModulator()->SetModuleRequests({"invalid"});
ModuleScriptLoader::Fetch(
ModuleScriptFetchRequest::CreateForTest(url, ModuleType::kJavaScript),
fetcher_, ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
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 024aa5cb96a..5d10d269a24 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
@@ -7,11 +7,14 @@
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/module_request.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.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/module_script.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
@@ -48,43 +51,6 @@ struct ModuleScriptFetchTarget {
} // namespace
-void ModuleTreeLinker::Fetch(
- const KURL& url,
- const ModuleType& module_type,
- ResourceFetcher* fetch_client_settings_object_fetcher,
- mojom::blink::RequestContextType context_type,
- network::mojom::RequestDestination destination,
- const ScriptFetchOptions& options,
- Modulator* modulator,
- ModuleScriptCustomFetchType custom_fetch_type,
- ModuleTreeLinkerRegistry* registry,
- ModuleTreeClient* client) {
- ModuleTreeLinker* fetcher = MakeGarbageCollected<ModuleTreeLinker>(
- fetch_client_settings_object_fetcher, context_type, destination,
- modulator, custom_fetch_type, registry, client);
- registry->AddFetcher(fetcher);
- fetcher->FetchRoot(url, module_type, options);
- DCHECK(fetcher->IsFetching());
-}
-
-void ModuleTreeLinker::FetchDescendantsForInlineScript(
- ModuleScript* module_script,
- ResourceFetcher* fetch_client_settings_object_fetcher,
- mojom::blink::RequestContextType context_type,
- network::mojom::RequestDestination destination,
- Modulator* modulator,
- ModuleScriptCustomFetchType custom_fetch_type,
- ModuleTreeLinkerRegistry* registry,
- ModuleTreeClient* client) {
- DCHECK(module_script);
- ModuleTreeLinker* fetcher = MakeGarbageCollected<ModuleTreeLinker>(
- fetch_client_settings_object_fetcher, context_type, destination,
- modulator, custom_fetch_type, registry, client);
- registry->AddFetcher(fetcher);
- fetcher->FetchRootInline(module_script);
- DCHECK(fetcher->IsFetching());
-}
-
ModuleTreeLinker::ModuleTreeLinker(
ResourceFetcher* fetch_client_settings_object_fetcher,
mojom::blink::RequestContextType context_type,
@@ -92,7 +58,8 @@ ModuleTreeLinker::ModuleTreeLinker(
Modulator* modulator,
ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeLinkerRegistry* registry,
- ModuleTreeClient* client)
+ ModuleTreeClient* client,
+ base::PassKey<ModuleTreeLinkerRegistry>)
: fetch_client_settings_object_fetcher_(
fetch_client_settings_object_fetcher),
context_type_(context_type),
@@ -175,7 +142,7 @@ void ModuleTreeLinker::AdvanceState(State new_state) {
}
#endif
- registry_->ReleaseFinishedFetcher(this);
+ registry_->ReleaseFinishedLinker(this);
// <spec label="IMSGF" step="6">When the appropriate algorithm
// asynchronously completes with final result, asynchronously complete this
@@ -188,7 +155,8 @@ void ModuleTreeLinker::AdvanceState(State new_state) {
// #fetch-a-module-worker-script-tree.
void ModuleTreeLinker::FetchRoot(const KURL& original_url,
ModuleType module_type,
- const ScriptFetchOptions& options) {
+ const ScriptFetchOptions& options,
+ base::PassKey<ModuleTreeLinkerRegistry>) {
#if DCHECK_IS_ON()
original_url_ = original_url;
module_type_ = module_type;
@@ -262,7 +230,9 @@ void ModuleTreeLinker::FetchRoot(const KURL& original_url,
// <specdef
// href="https://html.spec.whatwg.org/C/#fetch-an-inline-module-script-graph">
-void ModuleTreeLinker::FetchRootInline(ModuleScript* module_script) {
+void ModuleTreeLinker::FetchRootInline(
+ ModuleScript* module_script,
+ base::PassKey<ModuleTreeLinkerRegistry>) {
DCHECK(module_script);
#if DCHECK_IS_ON()
original_url_ = module_script->BaseURL();
@@ -369,14 +339,14 @@ void ModuleTreeLinker::NotifyModuleLoadFinished(ModuleScript* module_script) {
void ModuleTreeLinker::FetchDescendants(const ModuleScript* module_script) {
DCHECK(module_script);
- v8::Isolate* isolate = modulator_->GetScriptState()->GetIsolate();
- v8::HandleScope scope(isolate);
// [nospec] Abort the steps if the browsing context is discarded.
if (!modulator_->HasValidContext()) {
result_ = nullptr;
AdvanceState(State::kFinished);
return;
}
+ ScriptState* script_state = modulator_->GetScriptState();
+ v8::HandleScope scope(script_state->GetIsolate());
// <spec step="2">Let record be module script's record.</spec>
v8::Local<v8::Module> record = module_script->V8Module();
@@ -409,7 +379,7 @@ void ModuleTreeLinker::FetchDescendants(const ModuleScript* module_script) {
// <spec step="5">For each ModuleRequest Record requested of
// record.[[RequestedModules]],</spec>
Vector<ModuleRequest> record_requested_modules =
- modulator_->ModuleRequestsFromModuleRecord(record);
+ ModuleRecord::ModuleRequests(script_state, record);
for (const auto& requested : record_requested_modules) {
// <spec step="5.1">Let url be the result of resolving a module specifier
@@ -549,8 +519,14 @@ void ModuleTreeLinker::Instantiate() {
// <spec step="5.2">Perform record.Instantiate(). ...</spec>
AdvanceState(State::kInstantiating);
+
+ ScriptState* script_state = modulator_->GetScriptState();
+ UseCounter::Count(ExecutionContext::From(script_state),
+ WebFeature::kInstantiateModuleScript);
+
+ ScriptState::Scope scope(script_state);
ScriptValue instantiation_error =
- modulator_->InstantiateModule(record, result_->SourceURL());
+ ModuleRecord::Instantiate(script_state, record, result_->SourceURL());
// <spec step="5.2">... If this throws an exception, set result's error to
// rethrow to that exception.</spec>
@@ -606,7 +582,7 @@ ScriptValue ModuleTreeLinker::FindFirstParseError(
// <spec step="5.1">Let childSpecifiers be the value of moduleScript's
// record's [[RequestedModules]] internal slot.</spec>
Vector<ModuleRequest> child_specifiers =
- modulator_->ModuleRequestsFromModuleRecord(record);
+ ModuleRecord::ModuleRequests(modulator_->GetScriptState(), record);
for (const auto& module_request : child_specifiers) {
// <spec step="5.2">Let childURLs be the list obtained by calling resolve a
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 cbf354522ed..8a6ab5634b8 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
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_TREE_LINKER_H_
#include "base/dcheck_is_on.h"
+#include "base/types/pass_key.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -30,38 +31,6 @@ class ModuleTreeLinkerRegistry;
// by its |Context()->GetFetchClientSettingsObject()|.
class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
public:
- // https://html.spec.whatwg.org/C/#fetch-a-module-script-tree
- // https://html.spec.whatwg.org/C/#fetch-a-module-worker-script-tree
- // https://html.spec.whatwg.org/C/#fetch-an-import()-module-script-graph
- static void Fetch(const KURL& url,
- const ModuleType&,
- ResourceFetcher* fetch_client_settings_object_fetcher,
- mojom::blink::RequestContextType context_type,
- network::mojom::RequestDestination destination,
- const ScriptFetchOptions&,
- Modulator*,
- ModuleScriptCustomFetchType,
- ModuleTreeLinkerRegistry*,
- ModuleTreeClient*);
-
- // https://html.spec.whatwg.org/C/#fetch-an-inline-module-script-graph
- static void FetchDescendantsForInlineScript(
- ModuleScript*,
- ResourceFetcher* fetch_client_settings_object_fetcher,
- mojom::blink::RequestContextType context_type,
- network::mojom::RequestDestination destination,
- Modulator*,
- ModuleScriptCustomFetchType,
- ModuleTreeLinkerRegistry*,
- ModuleTreeClient*);
-
- ModuleTreeLinker(ResourceFetcher* fetch_client_settings_object_fetcher,
- mojom::blink::RequestContextType context_type,
- network::mojom::RequestDestination destination,
- Modulator*,
- ModuleScriptCustomFetchType,
- ModuleTreeLinkerRegistry*,
- ModuleTreeClient*);
~ModuleTreeLinker() override = default;
void Trace(Visitor*) const override;
@@ -70,6 +39,21 @@ class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
}
bool HasFinished() const { return state_ == State::kFinished; }
+ // Below methods are intended to be called via ModuleTreeLinkerRegistry.
+ ModuleTreeLinker(ResourceFetcher* fetch_client_settings_object_fetcher,
+ mojom::blink::RequestContextType context_type,
+ network::mojom::RequestDestination destination,
+ Modulator*,
+ ModuleScriptCustomFetchType,
+ ModuleTreeLinkerRegistry*,
+ ModuleTreeClient*,
+ base::PassKey<ModuleTreeLinkerRegistry>);
+ void FetchRoot(const KURL&,
+ ModuleType,
+ const ScriptFetchOptions&,
+ base::PassKey<ModuleTreeLinkerRegistry>);
+ void FetchRootInline(ModuleScript*, base::PassKey<ModuleTreeLinkerRegistry>);
+
private:
enum class State {
kInitial,
@@ -87,9 +71,6 @@ class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
#endif
void AdvanceState(State);
- void FetchRoot(const KURL&, ModuleType, const ScriptFetchOptions&);
- void FetchRootInline(ModuleScript*);
-
void NotifyModuleLoadFinished(ModuleScript*) override;
void FetchDescendants(const ModuleScript*);
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 86f6f3bde6b..5bc2ef08a76 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
@@ -6,25 +6,60 @@
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h"
#include "third_party/blink/renderer/platform/loader/fetch/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"
namespace blink {
+void ModuleTreeLinkerRegistry::Fetch(
+ const KURL& url,
+ const ModuleType& module_type,
+ ResourceFetcher* fetch_client_settings_object_fetcher,
+ mojom::blink::RequestContextType context_type,
+ network::mojom::RequestDestination destination,
+ const ScriptFetchOptions& options,
+ Modulator* modulator,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ ModuleTreeClient* client) {
+ ModuleTreeLinker* linker = MakeGarbageCollected<ModuleTreeLinker>(
+ fetch_client_settings_object_fetcher, context_type, destination,
+ modulator, custom_fetch_type, this, client,
+ base::PassKey<ModuleTreeLinkerRegistry>());
+ AddLinker(linker);
+ linker->FetchRoot(url, module_type, options,
+ base::PassKey<ModuleTreeLinkerRegistry>());
+ DCHECK(linker->IsFetching());
+}
+
+void ModuleTreeLinkerRegistry::FetchDescendantsForInlineScript(
+ ModuleScript* module_script,
+ ResourceFetcher* fetch_client_settings_object_fetcher,
+ mojom::blink::RequestContextType context_type,
+ network::mojom::RequestDestination destination,
+ Modulator* modulator,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ ModuleTreeClient* client) {
+ ModuleTreeLinker* linker = MakeGarbageCollected<ModuleTreeLinker>(
+ fetch_client_settings_object_fetcher, context_type, destination,
+ modulator, custom_fetch_type, this, client,
+ base::PassKey<ModuleTreeLinkerRegistry>());
+ AddLinker(linker);
+ linker->FetchRootInline(module_script,
+ base::PassKey<ModuleTreeLinkerRegistry>());
+ DCHECK(linker->IsFetching());
+}
+
void ModuleTreeLinkerRegistry::Trace(Visitor* visitor) const {
visitor->Trace(active_tree_linkers_);
}
-void ModuleTreeLinkerRegistry::AddFetcher(ModuleTreeLinker* fetcher) {
- DCHECK(!active_tree_linkers_.Contains(fetcher));
- active_tree_linkers_.insert(fetcher);
+void ModuleTreeLinkerRegistry::AddLinker(ModuleTreeLinker* linker) {
+ DCHECK(!active_tree_linkers_.Contains(linker));
+ active_tree_linkers_.insert(linker);
}
-void ModuleTreeLinkerRegistry::ReleaseFinishedFetcher(
- ModuleTreeLinker* fetcher) {
- DCHECK(fetcher->HasFinished());
+void ModuleTreeLinkerRegistry::ReleaseFinishedLinker(ModuleTreeLinker* linker) {
+ DCHECK(linker->HasFinished());
- auto it = active_tree_linkers_.find(fetcher);
+ auto it = active_tree_linkers_.find(linker);
DCHECK_NE(it, active_tree_linkers_.end());
active_tree_linkers_.erase(it);
}
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 68afcbcda9e..468b5f4a867 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,9 +5,12 @@
#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/mojom/fetch/fetch_api_request.mojom-blink-forward.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/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
@@ -19,6 +22,30 @@ class CORE_EXPORT ModuleTreeLinkerRegistry final
public NameClient {
public:
ModuleTreeLinkerRegistry() = default;
+ ~ModuleTreeLinkerRegistry() final = default;
+
+ // https://html.spec.whatwg.org/C/#fetch-a-module-script-tree
+ // https://html.spec.whatwg.org/C/#fetch-a-module-worker-script-tree
+ // https://html.spec.whatwg.org/C/#fetch-an-import()-module-script-graph
+ void Fetch(const KURL& url,
+ const ModuleType&,
+ ResourceFetcher* fetch_client_settings_object_fetcher,
+ mojom::blink::RequestContextType context_type,
+ network::mojom::RequestDestination destination,
+ const ScriptFetchOptions&,
+ Modulator*,
+ ModuleScriptCustomFetchType,
+ ModuleTreeClient*);
+
+ // https://html.spec.whatwg.org/C/#fetch-an-inline-module-script-graph
+ void FetchDescendantsForInlineScript(
+ ModuleScript*,
+ ResourceFetcher* fetch_client_settings_object_fetcher,
+ mojom::blink::RequestContextType context_type,
+ network::mojom::RequestDestination destination,
+ Modulator*,
+ ModuleScriptCustomFetchType,
+ ModuleTreeClient*);
void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override {
@@ -27,8 +54,8 @@ class CORE_EXPORT ModuleTreeLinkerRegistry final
private:
friend class ModuleTreeLinker;
- void AddFetcher(ModuleTreeLinker*);
- void ReleaseFinishedFetcher(ModuleTreeLinker*);
+ void AddLinker(ModuleTreeLinker*);
+ void ReleaseFinishedLinker(ModuleTreeLinker*);
HeapHashSet<Member<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 b0c1f9aad10..96fd3c10984 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
@@ -19,9 +19,10 @@
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h"
#include "third_party/blink/renderer/core/script/js_module_script.h"
#include "third_party/blink/renderer/core/script/modulator.h"
-#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "third_party/blink/renderer/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"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -56,196 +57,84 @@ class TestModuleTreeClient final : public ModuleTreeClient {
Member<ModuleScript> module_script_;
};
-} // namespace
-
-class ModuleTreeLinkerTestModulator final : public DummyModulator {
+class SimModuleRequest : public SimRequestBase {
public:
- explicit ModuleTreeLinkerTestModulator(ScriptState* script_state)
- : script_state_(script_state) {}
- ~ModuleTreeLinkerTestModulator() override = default;
-
- void Trace(Visitor*) const override;
-
- enum class ResolveResult { kFailure, kSuccess };
-
- // Resolve last |Modulator::FetchSingle()| call.
- ModuleScript* ResolveSingleModuleScriptFetch(
- const KURL& url,
- const Vector<String>& dependency_module_specifiers,
- bool parse_error = false) {
- ScriptState::Scope scope(script_state_);
+ explicit SimModuleRequest(KURL url)
+ : SimRequestBase(std::move(url),
+ "text/javascript",
+ /* start_immediately=*/false) {}
+ void CompleteWithImports(const Vector<String>& specifiers) {
StringBuilder source_text;
- for (const auto& specifier : dependency_module_specifiers) {
+ for (const auto& specifier : specifiers) {
source_text.Append("import '");
source_text.Append(specifier);
source_text.Append("';\n");
}
source_text.Append("export default 'grapes';");
- v8::Local<v8::Module> module_record = ModuleTestBase::CompileModule(
- script_state_->GetIsolate(), source_text.ToString(), url);
- auto* module_script =
- JSModuleScript::CreateForTest(this, module_record, url);
-
- auto result_map = module_map_.insert(url, module_script);
- EXPECT_TRUE(result_map.is_new_entry);
-
- if (parse_error) {
- v8::Local<v8::Value> error = V8ThrowException::CreateError(
- script_state_->GetIsolate(), "Parse failure.");
- module_script->SetParseErrorAndClearRecord(
- ScriptValue(script_state_->GetIsolate(), error));
- }
-
- EXPECT_TRUE(pending_clients_.Contains(url));
- pending_clients_.Take(url)->NotifyModuleLoadFinished(module_script);
-
- return module_script;
- }
-
- void ResolveDependentTreeFetch(const KURL& url, ResolveResult result) {
- ResolveSingleModuleScriptFetch(url, Vector<String>(),
- result == ResolveResult::kFailure);
- }
-
- void SetInstantiateShouldFail(bool b) { instantiate_should_fail_ = b; }
-
- bool HasInstantiated(ModuleScript* module_script) const {
- v8::Isolate* isolate = script_state_->GetIsolate();
- v8::HandleScope scope(isolate);
-
- return instantiated_records_.Contains(MakeGarbageCollected<BoxedV8Module>(
- isolate, module_script->V8Module()));
- }
-
- private:
- // Implements Modulator:
-
- 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);
- }
- void SetAcquiringImportMapsState(AcquiringImportMapsState) final {}
-
- void FetchSingle(const ModuleScriptFetchRequest& request,
- ResourceFetcher*,
- ModuleGraphLevel,
- ModuleScriptCustomFetchType,
- SingleModuleClient* client) override {
- EXPECT_FALSE(pending_clients_.Contains(request.Url()));
- pending_clients_.Set(request.Url(), client);
- }
-
- ModuleScript* GetFetchedModuleScript(const KURL& url,
- ModuleType module_type) override {
- const auto& it = module_map_.find(url);
- if (it == module_map_.end())
- return nullptr;
-
- return it->value;
+ Complete(source_text.ToString());
}
-
- ScriptValue InstantiateModule(v8::Local<v8::Module> record,
- const KURL& source_url) override {
- if (instantiate_should_fail_) {
- ScriptState::Scope scope(script_state_);
- v8::Local<v8::Value> error = V8ThrowException::CreateError(
- script_state_->GetIsolate(), "Instantiation failure.");
- return ScriptValue(script_state_->GetIsolate(), error);
- }
- instantiated_records_.insert(MakeGarbageCollected<BoxedV8Module>(
- script_state_->GetIsolate(), record));
- return ScriptValue();
- }
-
- Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module> module_record) override {
- ScriptState::Scope scope(script_state_);
- return ModuleRecord::ModuleRequests(script_state_, module_record);
- }
-
- Member<ScriptState> script_state_;
- HeapHashMap<KURL, Member<SingleModuleClient>> pending_clients_;
- HeapHashMap<KURL, Member<ModuleScript>> module_map_;
- HeapHashSet<Member<BoxedV8Module>> instantiated_records_;
- bool instantiate_should_fail_ = false;
};
-void ModuleTreeLinkerTestModulator::Trace(Visitor* visitor) const {
- visitor->Trace(script_state_);
- visitor->Trace(pending_clients_);
- visitor->Trace(module_map_);
- visitor->Trace(instantiated_records_);
- DummyModulator::Trace(visitor);
-}
-
-class ModuleTreeLinkerTest : public PageTestBase {
- DISALLOW_COPY_AND_ASSIGN(ModuleTreeLinkerTest);
+} // namespace
+class ModuleTreeLinkerTest : public SimTest {
public:
- ModuleTreeLinkerTest() = default;
- void SetUp() override;
-
- ModuleTreeLinkerTestModulator* GetModulator() { return modulator_.Get(); }
+ Modulator* GetModulator() {
+ return Modulator::From(ToScriptStateForMainWorld(MainFrame().GetFrame()));
+ }
- protected:
- Persistent<ModuleTreeLinkerTestModulator> modulator_;
+ bool HasInstantiated(ModuleScript* module_script) {
+ if (!module_script)
+ return false;
+ ScriptState::Scope script_scope(GetModulator()->GetScriptState());
+ return (module_script->V8Module()->GetStatus() ==
+ v8::Module::kInstantiated);
+ }
};
-void ModuleTreeLinkerTest::SetUp() {
- PageTestBase::SetUp(IntSize(500, 500));
- ScriptState* script_state = ToScriptStateForMainWorld(&GetFrame());
- modulator_ =
- MakeGarbageCollected<ModuleTreeLinkerTestModulator>(script_state);
-}
-
TEST_F(ModuleTreeLinkerTest, FetchTreeNoDeps) {
- auto* registry = MakeGarbageCollected<ModuleTreeLinkerRegistry>();
-
- KURL url("http://example.com/root.js");
+ SimModuleRequest sim_module(KURL("http://example.com/root.js"));
TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ GetModulator()->FetchTree(
+ sim_module.GetURL(), ModuleType::kJavaScript, GetDocument().Fetcher(),
+ mojom::blink::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, ScriptFetchOptions(),
+ ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
EXPECT_FALSE(client->GetModuleScript());
- GetModulator()->ResolveSingleModuleScriptFetch(url, {});
+ sim_module.Complete(R"(export default 'grapes';)");
+ test::RunPendingTasks();
+
EXPECT_TRUE(client->WasNotifyFinished());
- ASSERT_TRUE(client->GetModuleScript());
- EXPECT_TRUE(GetModulator()->HasInstantiated(client->GetModuleScript()));
+
+ ModuleScript* module_script = client->GetModuleScript();
+ ASSERT_TRUE(module_script);
+ EXPECT_TRUE(HasInstantiated(module_script));
}
TEST_F(ModuleTreeLinkerTest, FetchTreeInstantiationFailure) {
- GetModulator()->SetInstantiateShouldFail(true);
+ SimModuleRequest sim_module(KURL("http://example.com/root.js"));
- ModuleTreeLinkerRegistry* registry =
- MakeGarbageCollected<ModuleTreeLinkerRegistry>();
-
- KURL url("http://example.com/root.js");
TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ GetModulator()->FetchTree(
+ sim_module.GetURL(), ModuleType::kJavaScript, GetDocument().Fetcher(),
+ mojom::blink::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, ScriptFetchOptions(),
+ ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
EXPECT_FALSE(client->GetModuleScript());
- GetModulator()->ResolveSingleModuleScriptFetch(url, {});
-
- // Modulator::InstantiateModule() fails here, as
- // we SetInstantiateShouldFail(true) earlier.
+ sim_module.Complete(R"(
+ import _self_should_fail from 'http://example.com/root.js';
+ )");
+ test::RunPendingTasks();
EXPECT_TRUE(client->WasNotifyFinished());
ASSERT_TRUE(client->GetModuleScript());
@@ -255,55 +144,49 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeInstantiationFailure) {
}
TEST_F(ModuleTreeLinkerTest, FetchTreeWithSingleDependency) {
- ModuleTreeLinkerRegistry* registry =
- MakeGarbageCollected<ModuleTreeLinkerRegistry>();
+ SimModuleRequest sim_module(KURL("http://example.com/root.js"));
+ SimModuleRequest sim_module_dep(KURL("http://example.com/dep1.js"));
- KURL url("http://example.com/root.js");
TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ GetModulator()->FetchTree(
+ sim_module.GetURL(), ModuleType::kJavaScript, GetDocument().Fetcher(),
+ mojom::blink::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, ScriptFetchOptions(),
+ ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
EXPECT_FALSE(client->GetModuleScript());
- GetModulator()->ResolveSingleModuleScriptFetch(url, {"./dep1.js"});
+ sim_module.CompleteWithImports({"./dep1.js"});
+ test::RunPendingTasks();
+
EXPECT_FALSE(client->WasNotifyFinished());
- KURL url_dep1("http://example.com/dep1.js");
+ sim_module_dep.CompleteWithImports({});
+ test::RunPendingTasks();
- GetModulator()->ResolveDependentTreeFetch(
- url_dep1, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
EXPECT_TRUE(client->WasNotifyFinished());
-
- ASSERT_TRUE(client->GetModuleScript());
- EXPECT_TRUE(GetModulator()->HasInstantiated(client->GetModuleScript()));
+ ModuleScript* module_script = client->GetModuleScript();
+ ASSERT_TRUE(module_script);
+ EXPECT_TRUE(HasInstantiated(module_script));
}
TEST_F(ModuleTreeLinkerTest, FetchTreeWith3Deps) {
- ModuleTreeLinkerRegistry* registry =
- MakeGarbageCollected<ModuleTreeLinkerRegistry>();
+ SimModuleRequest sim_module(KURL("http://example.com/root.js"));
- KURL url("http://example.com/root.js");
TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ GetModulator()->FetchTree(
+ sim_module.GetURL(), ModuleType::kJavaScript, GetDocument().Fetcher(),
+ mojom::blink::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, ScriptFetchOptions(),
+ ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
EXPECT_FALSE(client->GetModuleScript());
- GetModulator()->ResolveSingleModuleScriptFetch(
- url, {"./dep1.js", "./dep2.js", "./dep3.js"});
- EXPECT_FALSE(client->WasNotifyFinished());
-
- Vector<KURL> url_deps;
+ Vector<std::unique_ptr<SimModuleRequest>> sim_module_deps;
for (int i = 1; i <= 3; ++i) {
StringBuilder url_dep_str;
url_dep_str.Append("http://example.com/dep");
@@ -311,41 +194,39 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeWith3Deps) {
url_dep_str.Append(".js");
KURL url_dep(url_dep_str.ToString());
- url_deps.push_back(url_dep);
+ sim_module_deps.push_back(std::make_unique<SimModuleRequest>(url_dep));
}
- for (const auto& url_dep : url_deps) {
+ sim_module.CompleteWithImports({"./dep1.js", "./dep2.js", "./dep3.js"});
+ test::RunPendingTasks();
+
+ for (const auto& sim_module_dep : sim_module_deps) {
EXPECT_FALSE(client->WasNotifyFinished());
- GetModulator()->ResolveDependentTreeFetch(
- url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+ sim_module_dep->CompleteWithImports({});
+ test::RunPendingTasks();
}
EXPECT_TRUE(client->WasNotifyFinished());
- ASSERT_TRUE(client->GetModuleScript());
- EXPECT_TRUE(GetModulator()->HasInstantiated(client->GetModuleScript()));
+ ModuleScript* module_script = client->GetModuleScript();
+ ASSERT_TRUE(module_script);
+ EXPECT_TRUE(HasInstantiated(module_script));
}
TEST_F(ModuleTreeLinkerTest, FetchTreeWith3Deps1Fail) {
- ModuleTreeLinkerRegistry* registry =
- MakeGarbageCollected<ModuleTreeLinkerRegistry>();
+ SimModuleRequest sim_module(KURL("http://example.com/root.js"));
- KURL url("http://example.com/root.js");
TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ GetModulator()->FetchTree(
+ sim_module.GetURL(), ModuleType::kJavaScript, GetDocument().Fetcher(),
+ mojom::blink::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, ScriptFetchOptions(),
+ ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
EXPECT_FALSE(client->GetModuleScript());
- GetModulator()->ResolveSingleModuleScriptFetch(
- url, {"./dep1.js", "./dep2.js", "./dep3.js"});
- EXPECT_FALSE(client->WasNotifyFinished());
-
- Vector<KURL> url_deps;
+ Vector<std::unique_ptr<SimModuleRequest>> sim_module_deps;
for (int i = 1; i <= 3; ++i) {
StringBuilder url_dep_str;
url_dep_str.Append("http://example.com/dep");
@@ -353,88 +234,56 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeWith3Deps1Fail) {
url_dep_str.Append(".js");
KURL url_dep(url_dep_str.ToString());
- url_deps.push_back(url_dep);
- }
-
- for (const auto& url_dep : url_deps) {
- SCOPED_TRACE(url_dep.GetString());
+ sim_module_deps.push_back(std::make_unique<SimModuleRequest>(url_dep));
}
- auto url_dep = url_deps.back();
- url_deps.pop_back();
- GetModulator()->ResolveDependentTreeFetch(
- url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
- EXPECT_FALSE(client->WasNotifyFinished());
- url_dep = url_deps.back();
- url_deps.pop_back();
- GetModulator()->ResolveDependentTreeFetch(
- url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kFailure);
-
- // TODO(kouhei): This may not hold once we implement early failure reporting.
- EXPECT_FALSE(client->WasNotifyFinished());
-
- // Check below doesn't crash.
- url_dep = url_deps.back();
- url_deps.pop_back();
- GetModulator()->ResolveDependentTreeFetch(
- url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
- EXPECT_TRUE(url_deps.IsEmpty());
-
- EXPECT_TRUE(client->WasNotifyFinished());
- ASSERT_TRUE(client->GetModuleScript());
- EXPECT_FALSE(client->GetModuleScript()->HasParseError());
- EXPECT_TRUE(client->GetModuleScript()->HasErrorToRethrow());
-}
-
-TEST_F(ModuleTreeLinkerTest, FetchDependencyTree) {
- ModuleTreeLinkerRegistry* registry =
- MakeGarbageCollected<ModuleTreeLinkerRegistry>();
+ sim_module.CompleteWithImports({"./dep1.js", "./dep2.js", "./dep3.js"});
+ test::RunPendingTasks();
- KURL url("http://example.com/depth1.js");
- TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ for (int i = 0; i < 3; ++i) {
+ const auto& sim_module_dep = sim_module_deps[i];
- EXPECT_FALSE(client->WasNotifyFinished())
- << "ModuleTreeLinker should always finish asynchronously.";
- EXPECT_FALSE(client->GetModuleScript());
-
- GetModulator()->ResolveSingleModuleScriptFetch(url, {"./depth2.js"});
-
- KURL url_dep2("http://example.com/depth2.js");
+ EXPECT_FALSE(client->WasNotifyFinished());
+ if (i == 1) {
+ // Complete the request with un-parsable JavaScript fragment.
+ sim_module_dep->Complete("%!#$@#$@#$@");
+ } else {
+ sim_module_dep->CompleteWithImports({});
+ }
- GetModulator()->ResolveDependentTreeFetch(
- url_dep2, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+ test::RunPendingTasks();
+ }
EXPECT_TRUE(client->WasNotifyFinished());
- ASSERT_TRUE(client->GetModuleScript());
- EXPECT_TRUE(GetModulator()->HasInstantiated(client->GetModuleScript()));
+ ModuleScript* module_script = client->GetModuleScript();
+ ASSERT_TRUE(module_script);
+ EXPECT_FALSE(HasInstantiated(module_script));
+ EXPECT_FALSE(module_script->HasParseError());
+ EXPECT_TRUE(module_script->HasErrorToRethrow());
}
TEST_F(ModuleTreeLinkerTest, FetchDependencyOfCyclicGraph) {
- ModuleTreeLinkerRegistry* registry =
- MakeGarbageCollected<ModuleTreeLinkerRegistry>();
+ SimModuleRequest sim_module(KURL("http://example.com/a.js"));
- KURL url("http://example.com/a.js");
TestModuleTreeClient* client = MakeGarbageCollected<TestModuleTreeClient>();
- ModuleTreeLinker::Fetch(url, ModuleType::kJavaScript, GetDocument().Fetcher(),
- mojom::blink::RequestContextType::SCRIPT,
- network::mojom::RequestDestination::kScript,
- ScriptFetchOptions(), GetModulator(),
- ModuleScriptCustomFetchType::kNone, registry, client);
+ GetModulator()->FetchTree(
+ sim_module.GetURL(), ModuleType::kJavaScript, GetDocument().Fetcher(),
+ mojom::blink::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, ScriptFetchOptions(),
+ ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
EXPECT_FALSE(client->GetModuleScript());
- GetModulator()->ResolveSingleModuleScriptFetch(url, {"./a.js"});
+ sim_module.CompleteWithImports({"./a.js"});
+ test::RunPendingTasks();
EXPECT_TRUE(client->WasNotifyFinished());
- ASSERT_TRUE(client->GetModuleScript());
- EXPECT_TRUE(GetModulator()->HasInstantiated(client->GetModuleScript()));
+ ModuleScript* module_script = client->GetModuleScript();
+ ASSERT_TRUE(module_script);
+ EXPECT_TRUE(HasInstantiated(module_script));
+ EXPECT_FALSE(module_script->HasParseError());
}
} // 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
index 5b64c070883..b9d80a978d8 100644
--- 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
@@ -5,7 +5,6 @@
#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 "third_party/abseil-cpp/absl/types/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"
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 6074b8d07d9..d171707cfcd 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
@@ -61,17 +61,10 @@ NavigationPolicy NavigationPolicyFromEventModifiers(int16_t button,
return kNavigationPolicyCurrentTab;
if (new_tab_modifier) {
- if (shift)
- return kNavigationPolicyNewForegroundTab;
- else
- return kNavigationPolicyNewBackgroundTab;
- } else {
- if (shift)
- return kNavigationPolicyNewWindow;
- else
- return kNavigationPolicyDownload;
+ return shift ? kNavigationPolicyNewForegroundTab
+ : kNavigationPolicyNewBackgroundTab;
}
- return kNavigationPolicyCurrentTab;
+ return shift ? kNavigationPolicyNewWindow : kNavigationPolicyDownload;
}
NavigationPolicy NavigationPolicyFromEventInternal(const Event* event) {
diff --git a/chromium/third_party/blink/renderer/core/loader/no_state_prefetch_client.h b/chromium/third_party/blink/renderer/core/loader/no_state_prefetch_client.h
index 10eda82ad48..2f56e90412b 100644
--- a/chromium/third_party/blink/renderer/core/loader/no_state_prefetch_client.h
+++ b/chromium/third_party/blink/renderer/core/loader/no_state_prefetch_client.h
@@ -32,7 +32,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_NO_STATE_PREFETCH_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_NO_STATE_PREFETCH_CLIENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -49,6 +48,8 @@ class CORE_EXPORT NoStatePrefetchClient
static const char kSupplementName[];
NoStatePrefetchClient(Page&, WebNoStatePrefetchClient*);
+ NoStatePrefetchClient(const NoStatePrefetchClient&) = delete;
+ NoStatePrefetchClient& operator=(const NoStatePrefetchClient&) = delete;
virtual bool IsPrefetchOnly();
@@ -56,8 +57,6 @@ class CORE_EXPORT NoStatePrefetchClient
private:
WebNoStatePrefetchClient* client_;
-
- DISALLOW_COPY_AND_ASSIGN(NoStatePrefetchClient);
};
CORE_EXPORT void ProvideNoStatePrefetchClientTo(Page&, NoStatePrefetchClient*);
diff --git a/chromium/third_party/blink/renderer/core/loader/ping_loader.cc b/chromium/third_party/blink/renderer/core/loader/ping_loader.cc
index 186a7a77e61..27650fbecf8 100644
--- a/chromium/third_party/blink/renderer/core/loader/ping_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/ping_loader.cc
@@ -294,7 +294,7 @@ void PingLoader::SendLinkAuditPing(LocalFrame* frame,
RawResource::Fetch(params, frame->DomWindow()->Fetcher(), nullptr);
}
-void PingLoader::SendViolationReport(LocalFrame* frame,
+void PingLoader::SendViolationReport(ExecutionContext* execution_context,
const KURL& report_url,
scoped_refptr<EncodedFormData> report) {
ResourceRequest request(report_url);
@@ -305,15 +305,18 @@ void PingLoader::SendViolationReport(LocalFrame* frame,
request.SetCredentialsMode(network::mojom::CredentialsMode::kSameOrigin);
request.SetRequestContext(mojom::blink::RequestContextType::CSP_REPORT);
request.SetRequestDestination(network::mojom::RequestDestination::kReport);
- request.SetRequestorOrigin(frame->DomWindow()->GetSecurityOrigin());
+ request.SetRequestorOrigin(execution_context->GetSecurityOrigin());
request.SetRedirectMode(network::mojom::RedirectMode::kError);
FetchParameters params(std::move(request),
- frame->DomWindow()->GetCurrentWorld());
+ execution_context->GetCurrentWorld());
params.MutableOptions().initiator_info.name =
fetch_initiator_type_names::kViolationreport;
- frame->Client()->DidDispatchPingLoader(report_url);
- RawResource::Fetch(params, frame->DomWindow()->Fetcher(), nullptr);
+ auto* window = DynamicTo<LocalDOMWindow>(execution_context);
+ if (window && window->GetFrame())
+ window->GetFrame()->Client()->DidDispatchPingLoader(report_url);
+
+ RawResource::Fetch(params, execution_context->Fetcher(), nullptr);
}
bool PingLoader::SendBeacon(const ScriptState& state,
diff --git a/chromium/third_party/blink/renderer/core/loader/ping_loader.h b/chromium/third_party/blink/renderer/core/loader/ping_loader.h
index 00c964b28cb..802a9705d0a 100644
--- a/chromium/third_party/blink/renderer/core/loader/ping_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/ping_loader.h
@@ -45,6 +45,7 @@ class Blob;
class DOMArrayBufferView;
class DOMArrayBuffer;
class EncodedFormData;
+class ExecutionContext;
class FormData;
class LocalFrame;
class KURL;
@@ -66,7 +67,7 @@ class CORE_EXPORT PingLoader {
static void SendLinkAuditPing(LocalFrame*,
const KURL& ping_url,
const KURL& destination_url);
- static void SendViolationReport(LocalFrame*,
+ static void SendViolationReport(ExecutionContext* execution_context,
const KURL& report_url,
scoped_refptr<EncodedFormData> report);
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 c596b10f91e..1a9dc30d5b7 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
@@ -8,6 +8,7 @@
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
@@ -157,7 +158,7 @@ TEST_F(PingLoaderTest, ViolationPriority) {
// via |PageTestBase::dummy_page_holder_|.
url_test_helpers::RegisterMockedURLLoad(
ping_url, test::CoreTestDataPath("bar.html"), "text/html");
- PingLoader::SendViolationReport(&GetFrame(), ping_url,
+ PingLoader::SendViolationReport(GetFrame().DomWindow(), ping_url,
EncodedFormData::Create());
url_test_helpers::ServeAsynchronousRequests();
const PartialResourceRequest& request = client_->PingRequest();
diff --git a/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc b/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc
index 183cea3aaf9..f5c2147bba9 100644
--- a/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc
+++ b/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
@@ -28,6 +29,7 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/link_header.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -51,7 +53,12 @@ class PrefetchedSignedExchangeManager::PrefetchedSignedExchangeLoader
request_.CopyFrom(request);
}
- ~PrefetchedSignedExchangeLoader() override {}
+ PrefetchedSignedExchangeLoader(const PrefetchedSignedExchangeLoader&) =
+ delete;
+ PrefetchedSignedExchangeLoader& operator=(
+ const PrefetchedSignedExchangeLoader&) = delete;
+
+ ~PrefetchedSignedExchangeLoader() override = default;
base::WeakPtr<PrefetchedSignedExchangeLoader> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
@@ -106,14 +113,13 @@ class PrefetchedSignedExchangeManager::PrefetchedSignedExchangeLoader
std::move(resource_load_info_notifier_wrapper),
WTF::Unretained(client)));
}
- void SetDefersLoading(DeferType value) override {
+ void Freeze(LoaderFreezeMode value) override {
if (url_loader_) {
- url_loader_->SetDefersLoading(value);
+ url_loader_->Freeze(value);
return;
}
- pending_method_calls_.push(
- WTF::Bind(&PrefetchedSignedExchangeLoader::SetDefersLoading,
- GetWeakPtr(), value));
+ pending_method_calls_.push(WTF::Bind(
+ &PrefetchedSignedExchangeLoader::Freeze, GetWeakPtr(), value));
}
void DidChangePriority(WebURLRequest::Priority new_priority,
int intra_priority_value) override {
@@ -146,8 +152,6 @@ class PrefetchedSignedExchangeManager::PrefetchedSignedExchangeLoader
std::queue<base::OnceClosure> pending_method_calls_;
base::WeakPtrFactory<PrefetchedSignedExchangeLoader> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PrefetchedSignedExchangeLoader);
};
// static
diff --git a/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h b/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h
index e476d43094f..f623309247b 100644
--- a/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h
+++ b/chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREFETCHED_SIGNED_EXCHANGE_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREFETCHED_SIGNED_EXCHANGE_MANAGER_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink-forward.h"
#include "third_party/blink/public/web/web_navigation_params.h"
@@ -45,6 +44,10 @@ class PrefetchedSignedExchangeManager final
HashMap<KURL,
std::unique_ptr<WebNavigationParams::PrefetchedSignedExchange>>
prefetched_exchanges_map);
+ PrefetchedSignedExchangeManager(const PrefetchedSignedExchangeManager&) =
+ delete;
+ PrefetchedSignedExchangeManager& operator=(
+ const PrefetchedSignedExchangeManager&) = delete;
~PrefetchedSignedExchangeManager();
void Trace(Visitor* visitor) const;
@@ -95,8 +98,6 @@ class PrefetchedSignedExchangeManager final
bool started_ = false;
WTF::Vector<base::WeakPtr<PrefetchedSignedExchangeLoader>> loaders_;
-
- DISALLOW_COPY_AND_ASSIGN(PrefetchedSignedExchangeManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/preload_helper.cc b/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
index e673079ebd4..66d7bf08efb 100644
--- a/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
+++ b/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -25,6 +25,7 @@
#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/alternate_signed_exchange_resource_info.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/link_load_parameters.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
@@ -150,6 +151,9 @@ void PreloadHelper::DnsPrefetchIfNeeded(
Document* document,
LocalFrame* frame,
LinkCaller caller) {
+ if (document && document->Loader() && document->Loader()->Archive()) {
+ return;
+ }
if (params.rel.IsDNSPrefetch()) {
UseCounter::Count(document, WebFeature::kLinkRelDnsPrefetch);
if (caller == kLinkCalledFromHeader)
@@ -182,6 +186,9 @@ void PreloadHelper::PreconnectIfNeeded(
Document* document,
LocalFrame* frame,
LinkCaller caller) {
+ if (document && document->Loader() && document->Loader()->Archive()) {
+ return;
+ }
if (params.rel.IsPreconnect() && params.href.IsValid() &&
params.href.ProtocolIsInHTTPFamily()) {
UseCounter::Count(document, WebFeature::kLinkRelPreconnect);
@@ -520,6 +527,10 @@ void PreloadHelper::ModulePreloadIfNeeded(
Resource* PreloadHelper::PrefetchIfNeeded(const LinkLoadParameters& params,
Document& document) {
+ if (document.Loader() && document.Loader()->Archive()) {
+ return nullptr;
+ }
+
if (params.rel.IsLinkPrefetch() && params.href.IsValid() &&
document.GetFrame()) {
UseCounter::Count(document, WebFeature::kLinkRelPrefetch);
diff --git a/chromium/third_party/blink/renderer/core/loader/prerender_handle.cc b/chromium/third_party/blink/renderer/core/loader/prerender_handle.cc
index 7c5bfdfc095..238db72a9fe 100644
--- a/chromium/third_party/blink/renderer/core/loader/prerender_handle.cc
+++ b/chromium/third_party/blink/renderer/core/loader/prerender_handle.cc
@@ -32,7 +32,6 @@
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/common/features.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"
@@ -64,29 +63,14 @@ PrerenderHandle* PrerenderHandle::Create(
attributes->view_size =
gfx::Size(document.GetFrame()->GetMainFrameViewportSize());
- HeapMojoRemote<mojom::blink::PrerenderProcessor> prerender_processor(context);
HeapMojoRemote<mojom::blink::NoStatePrefetchProcessor> prefetch_processor(
context);
- // Run prerendering only when kPrerender2 is enabled and the origin of the
- // prerendering URL is the same as the origin of the trigger context.
- // TODO(https://crbug.com/1176054): This is a tentative behavior. We plan to
- // support cross-origin prerendering later.
- if (features::IsPrerender2Enabled() &&
- context->GetSecurityOrigin()->IsSameOriginWith(
- SecurityOrigin::Create(url).get())) {
- context->GetBrowserInterfaceBroker().GetInterface(
- prerender_processor.BindNewPipeAndPassReceiver(
- context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
- prerender_processor->Start(std::move(attributes));
- } else {
- context->GetBrowserInterfaceBroker().GetInterface(
- prefetch_processor.BindNewPipeAndPassReceiver(
- context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
- prefetch_processor->Start(std::move(attributes));
- }
+ context->GetBrowserInterfaceBroker().GetInterface(
+ prefetch_processor.BindNewPipeAndPassReceiver(
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ prefetch_processor->Start(std::move(attributes));
return MakeGarbageCollected<PrerenderHandle>(PassKey(), context, url,
- std::move(prerender_processor),
std::move(prefetch_processor));
}
@@ -94,20 +78,14 @@ PrerenderHandle::PrerenderHandle(
PassKey pass_key,
ExecutionContext* context,
const KURL& url,
- HeapMojoRemote<mojom::blink::PrerenderProcessor> remote_prerender_processor,
HeapMojoRemote<mojom::blink::NoStatePrefetchProcessor>
remote_fetch_processor)
: url_(url),
- remote_prerender_processor_(std::move(remote_prerender_processor)),
remote_prefetch_processor_(std::move(remote_fetch_processor)) {}
PrerenderHandle::~PrerenderHandle() = default;
void PrerenderHandle::Cancel() {
- if (remote_prerender_processor_.is_bound())
- remote_prerender_processor_->Cancel();
- remote_prerender_processor_.reset();
-
if (remote_prefetch_processor_.is_bound())
remote_prefetch_processor_->Cancel();
remote_prefetch_processor_.reset();
@@ -118,7 +96,6 @@ const KURL& PrerenderHandle::Url() const {
}
void PrerenderHandle::Trace(Visitor* visitor) const {
- visitor->Trace(remote_prerender_processor_);
visitor->Trace(remote_prefetch_processor_);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/prerender_handle.h b/chromium/third_party/blink/renderer/core/loader/prerender_handle.h
index 2c0f3e50d14..2d79168f2e3 100644
--- a/chromium/third_party/blink/renderer/core/loader/prerender_handle.h
+++ b/chromium/third_party/blink/renderer/core/loader/prerender_handle.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PRERENDER_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PRERENDER_HANDLE_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/types/pass_key.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom-blink.h"
@@ -69,8 +68,9 @@ class PrerenderHandle final : public GarbageCollected<PrerenderHandle> {
PrerenderHandle(PassKey,
ExecutionContext*,
const KURL&,
- HeapMojoRemote<mojom::blink::PrerenderProcessor>,
HeapMojoRemote<mojom::blink::NoStatePrefetchProcessor>);
+ PrerenderHandle(const PrerenderHandle&) = delete;
+ PrerenderHandle& operator=(const PrerenderHandle&) = delete;
~PrerenderHandle();
// Asks the browser process to cancel the running prerender.
@@ -82,11 +82,8 @@ class PrerenderHandle final : public GarbageCollected<PrerenderHandle> {
private:
const KURL url_;
- HeapMojoRemote<mojom::blink::PrerenderProcessor> remote_prerender_processor_;
HeapMojoRemote<mojom::blink::NoStatePrefetchProcessor>
remote_prefetch_processor_;
-
- DISALLOW_COPY_AND_ASSIGN(PrerenderHandle);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/prerender_test.cc b/chromium/third_party/blink/renderer/core/loader/prerender_test.cc
index 28ff54f63f3..7716904ed70 100644
--- a/chromium/third_party/blink/renderer/core/loader/prerender_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/prerender_test.cc
@@ -33,11 +33,9 @@
#include <memory>
#include "base/memory/ptr_util.h"
-#include "base/test/scoped_feature_list.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom-blink.h"
#include "third_party/blink/public/platform/web_cache.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -68,22 +66,17 @@ class TestWebNoStatePrefetchClient : public WebNoStatePrefetchClient {
bool IsPrefetchOnly() override { return false; }
};
-class MockPrerenderProcessor : public mojom::blink::PrerenderProcessor,
- public mojom::blink::NoStatePrefetchProcessor {
+class MockNoStatePrefetchProcessor
+ : public mojom::blink::NoStatePrefetchProcessor {
public:
- explicit MockPrerenderProcessor(
- mojo::PendingReceiver<mojom::blink::PrerenderProcessor>
- pending_receiver) {
- receiver_.Bind(std::move(pending_receiver));
- }
- explicit MockPrerenderProcessor(
+ explicit MockNoStatePrefetchProcessor(
mojo::PendingReceiver<mojom::blink::NoStatePrefetchProcessor>
pending_receiver) {
receiver_for_prefetch_.Bind(std::move(pending_receiver));
}
- ~MockPrerenderProcessor() override = default;
+ ~MockNoStatePrefetchProcessor() override = default;
- // mojom::blink::PrerenderProcessor implementation
+ // mojom::blink::NoStatePrefetchProcessor implementation
void Start(mojom::blink::PrerenderAttributesPtr attributes) override {
attributes_ = std::move(attributes);
}
@@ -99,21 +92,14 @@ class MockPrerenderProcessor : public mojom::blink::PrerenderProcessor,
private:
mojom::blink::PrerenderAttributesPtr attributes_;
- mojo::Receiver<mojom::blink::PrerenderProcessor> receiver_{this};
mojo::Receiver<mojom::blink::NoStatePrefetchProcessor> receiver_for_prefetch_{
this};
size_t cancel_count_ = 0;
};
-class PrerenderTest : public testing::Test,
- public testing::WithParamInterface<bool> {
+class PrerenderTest : public testing::Test {
public:
- PrerenderTest() {
- if (GetParam())
- feature_list_.InitAndEnableFeature(blink::features::kPrerender2);
- }
-
~PrerenderTest() override {
if (web_view_helper_.GetWebView())
UnregisterMockPrerenderProcessor();
@@ -130,15 +116,9 @@ class PrerenderTest : public testing::Test,
web_view_helper_.GetWebView()->SetNoStatePrefetchClient(
&no_state_prefetch_client_);
- if (features::IsPrerender2Enabled()) {
- GetBrowserInterfaceBroker().SetBinderForTesting(
- mojom::blink::PrerenderProcessor::Name_,
- WTF::BindRepeating(&PrerenderTest::Bind, WTF::Unretained(this)));
- } else {
- GetBrowserInterfaceBroker().SetBinderForTesting(
- mojom::blink::NoStatePrefetchProcessor::Name_,
- WTF::BindRepeating(&PrerenderTest::Bind, WTF::Unretained(this)));
- }
+ GetBrowserInterfaceBroker().SetBinderForTesting(
+ mojom::blink::NoStatePrefetchProcessor::Name_,
+ WTF::BindRepeating(&PrerenderTest::Bind, WTF::Unretained(this)));
frame_test_helpers::LoadFrame(
web_view_helper_.GetWebView()->MainFrameImpl(),
@@ -146,17 +126,10 @@ class PrerenderTest : public testing::Test,
}
void Bind(mojo::ScopedMessagePipeHandle message_pipe_handle) {
- if (features::IsPrerender2Enabled()) {
- auto processor = std::make_unique<MockPrerenderProcessor>(
- mojo::PendingReceiver<mojom::blink::PrerenderProcessor>(
- std::move(message_pipe_handle)));
- processors_.push_back(std::move(processor));
- } else {
- auto processor = std::make_unique<MockPrerenderProcessor>(
- mojo::PendingReceiver<mojom::blink::NoStatePrefetchProcessor>(
- std::move(message_pipe_handle)));
- processors_.push_back(std::move(processor));
- }
+ auto processor = std::make_unique<MockNoStatePrefetchProcessor>(
+ mojo::PendingReceiver<mojom::blink::NoStatePrefetchProcessor>(
+ std::move(message_pipe_handle)));
+ processors_.push_back(std::move(processor));
}
void NavigateAway() {
@@ -181,19 +154,14 @@ class PrerenderTest : public testing::Test,
test::RunPendingTasks();
}
- std::vector<std::unique_ptr<MockPrerenderProcessor>>& processors() {
+ std::vector<std::unique_ptr<MockNoStatePrefetchProcessor>>& processors() {
return processors_;
}
private:
void UnregisterMockPrerenderProcessor() {
- if (features::IsPrerender2Enabled()) {
- GetBrowserInterfaceBroker().SetBinderForTesting(
- mojom::blink::PrerenderProcessor::Name_, {});
- } else {
- GetBrowserInterfaceBroker().SetBinderForTesting(
- mojom::blink::NoStatePrefetchProcessor::Name_, {});
- }
+ GetBrowserInterfaceBroker().SetBinderForTesting(
+ mojom::blink::NoStatePrefetchProcessor::Name_, {});
}
BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() {
@@ -202,24 +170,19 @@ class PrerenderTest : public testing::Test,
->GetBrowserInterfaceBroker();
}
- std::vector<std::unique_ptr<MockPrerenderProcessor>> processors_;
- mojo::ReceiverSet<mojom::blink::PrerenderProcessor> receiver_set_;
+ std::vector<std::unique_ptr<MockNoStatePrefetchProcessor>> processors_;
TestWebNoStatePrefetchClient no_state_prefetch_client_;
frame_test_helpers::WebViewHelper web_view_helper_;
-
- base::test::ScopedFeatureList feature_list_;
};
} // namespace
-INSTANTIATE_TEST_SUITE_P(All, PrerenderTest, testing::Bool());
-
-TEST_P(PrerenderTest, SinglePrerender) {
+TEST_F(PrerenderTest, SinglePrerender) {
Initialize("http://example.com/", "prerender/single_prerender.html");
ASSERT_EQ(processors().size(), 1u);
- MockPrerenderProcessor& processor = *processors()[0];
+ MockNoStatePrefetchProcessor& processor = *processors()[0];
EXPECT_EQ(KURL("http://example.com/prerender"), processor.Url());
EXPECT_EQ(mojom::blink::PrerenderTriggerType::kLinkRelPrerender,
@@ -228,35 +191,35 @@ TEST_P(PrerenderTest, SinglePrerender) {
EXPECT_EQ(0u, processor.CancelCount());
}
-TEST_P(PrerenderTest, CancelPrerender) {
+TEST_F(PrerenderTest, CancelPrerender) {
Initialize("http://example.com/", "prerender/single_prerender.html");
ASSERT_EQ(processors().size(), 1u);
- MockPrerenderProcessor& processor = *processors()[0];
+ MockNoStatePrefetchProcessor& processor = *processors()[0];
EXPECT_EQ(0u, processor.CancelCount());
ExecuteScript("removePrerender()");
EXPECT_EQ(1u, processor.CancelCount());
}
-TEST_P(PrerenderTest, TwoPrerenders) {
+TEST_F(PrerenderTest, TwoPrerenders) {
Initialize("http://example.com/", "prerender/multiple_prerenders.html");
ASSERT_EQ(processors().size(), 2u);
- MockPrerenderProcessor& first_processor = *processors()[0];
+ MockNoStatePrefetchProcessor& first_processor = *processors()[0];
EXPECT_EQ(KURL("http://example.com/first"), first_processor.Url());
- MockPrerenderProcessor& second_processor = *processors()[1];
+ MockNoStatePrefetchProcessor& second_processor = *processors()[1];
EXPECT_EQ(KURL("http://example.com/second"), second_processor.Url());
EXPECT_EQ(0u, first_processor.CancelCount());
EXPECT_EQ(0u, second_processor.CancelCount());
}
-TEST_P(PrerenderTest, TwoPrerendersRemovingFirstThenNavigating) {
+TEST_F(PrerenderTest, TwoPrerendersRemovingFirstThenNavigating) {
Initialize("http://example.com/", "prerender/multiple_prerenders.html");
ASSERT_EQ(processors().size(), 2u);
- MockPrerenderProcessor& first_processor = *processors()[0];
- MockPrerenderProcessor& second_processor = *processors()[1];
+ MockNoStatePrefetchProcessor& first_processor = *processors()[0];
+ MockNoStatePrefetchProcessor& second_processor = *processors()[1];
EXPECT_EQ(0u, first_processor.CancelCount());
EXPECT_EQ(0u, second_processor.CancelCount());
@@ -272,12 +235,12 @@ TEST_P(PrerenderTest, TwoPrerendersRemovingFirstThenNavigating) {
EXPECT_EQ(0u, second_processor.CancelCount());
}
-TEST_P(PrerenderTest, TwoPrerendersAddingThird) {
+TEST_F(PrerenderTest, TwoPrerendersAddingThird) {
Initialize("http://example.com/", "prerender/multiple_prerenders.html");
ASSERT_EQ(processors().size(), 2u);
- MockPrerenderProcessor& first_processor = *processors()[0];
- MockPrerenderProcessor& second_processor = *processors()[1];
+ MockNoStatePrefetchProcessor& first_processor = *processors()[0];
+ MockNoStatePrefetchProcessor& second_processor = *processors()[1];
EXPECT_EQ(0u, first_processor.CancelCount());
EXPECT_EQ(0u, second_processor.CancelCount());
@@ -285,17 +248,17 @@ TEST_P(PrerenderTest, TwoPrerendersAddingThird) {
ExecuteScript("addThirdPrerender()");
ASSERT_EQ(processors().size(), 3u);
- MockPrerenderProcessor& third_processor = *processors()[2];
+ MockNoStatePrefetchProcessor& third_processor = *processors()[2];
EXPECT_EQ(0u, first_processor.CancelCount());
EXPECT_EQ(0u, second_processor.CancelCount());
EXPECT_EQ(0u, third_processor.CancelCount());
}
-TEST_P(PrerenderTest, MutateTarget) {
+TEST_F(PrerenderTest, MutateTarget) {
Initialize("http://example.com/", "prerender/single_prerender.html");
ASSERT_EQ(processors().size(), 1u);
- MockPrerenderProcessor& processor = *processors()[0];
+ MockNoStatePrefetchProcessor& processor = *processors()[0];
EXPECT_EQ(KURL("http://example.com/prerender"), processor.Url());
@@ -306,17 +269,17 @@ TEST_P(PrerenderTest, MutateTarget) {
ExecuteScript("mutateTarget()");
ASSERT_EQ(processors().size(), 2u);
- MockPrerenderProcessor& mutated_processor = *processors()[1];
+ MockNoStatePrefetchProcessor& mutated_processor = *processors()[1];
EXPECT_EQ(KURL("http://example.com/mutated"), mutated_processor.Url());
EXPECT_EQ(1u, processor.CancelCount());
EXPECT_EQ(0u, mutated_processor.CancelCount());
}
-TEST_P(PrerenderTest, MutateRel) {
+TEST_F(PrerenderTest, MutateRel) {
Initialize("http://example.com/", "prerender/single_prerender.html");
ASSERT_EQ(processors().size(), 1u);
- MockPrerenderProcessor& processor = *processors()[0];
+ MockNoStatePrefetchProcessor& processor = *processors()[0];
EXPECT_EQ(KURL("http://example.com/prerender"), processor.Url());
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 f6f2ad943a0..751acdc0042 100644
--- a/chromium/third_party/blink/renderer/core/loader/progress_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/progress_tracker.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/loader/progress_tracker.h"
+#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -40,14 +41,10 @@
namespace blink {
-// Always start progress at initialProgressValue. This helps provide feedback as
-// soon as a load starts.
-static const double kInitialProgressValue = 0.1;
+static constexpr int kProgressItemDefaultEstimatedLength = 1024 * 1024;
-static const int kProgressItemDefaultEstimatedLength = 1024 * 1024;
-
-static const double kProgressNotificationInterval = 0.02;
-static const double kProgressNotificationTimeInterval = 0.1;
+static constexpr double kProgressNotificationInterval = 0.02;
+static constexpr double kProgressNotificationTimeInterval = 0.1;
ProgressTracker::ProgressTracker(LocalFrame* frame)
: frame_(frame),
@@ -90,7 +87,7 @@ LocalFrameClient* ProgressTracker::GetLocalFrameClient() const {
void ProgressTracker::ProgressStarted() {
Reset();
- progress_value_ = kInitialProgressValue;
+ progress_value_ = kInitialLoadProgress;
if (!frame_->IsLoading()) {
GetLocalFrameClient()->DidStartLoading();
frame_->SetIsLoading(true);
@@ -183,7 +180,7 @@ void ProgressTracker::MaybeSendProgress() {
if (!frame_->IsLoading())
return;
- progress_value_ = kInitialProgressValue + 0.1; // +0.1 for committing
+ progress_value_ = kInitialLoadProgress + 0.1; // +0.1 for committing
if (finished_parsing_)
progress_value_ += 0.1;
if (did_first_contentful_paint_)
@@ -202,7 +199,7 @@ void ProgressTracker::MaybeSendProgress() {
(double)estimated_bytes_for_pending_requests_;
progress_value_ += percent_of_bytes_received / 2;
- DCHECK_GE(progress_value_, kInitialProgressValue);
+ DCHECK_GE(progress_value_, kInitialLoadProgress);
// Always leave space at the end. This helps show the user that we're not
// done until we're done.
DCHECK_LE(progress_value_, 0.9);
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 d9e21453bad..a051999c0a1 100644
--- a/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
+++ b/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PROGRESS_TRACKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PROGRESS_TRACKER_H_
-#include "base/macros.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/heap/handle.h"
@@ -56,6 +55,8 @@ class CORE_EXPORT ProgressTracker final
: public GarbageCollected<ProgressTracker> {
public:
explicit ProgressTracker(LocalFrame*);
+ ProgressTracker(const ProgressTracker&) = delete;
+ ProgressTracker& operator=(const ProgressTracker&) = delete;
~ProgressTracker();
void Trace(Visitor*) const;
void Dispose();
@@ -97,8 +98,6 @@ class CORE_EXPORT ProgressTracker final
int64_t estimated_bytes_for_pending_requests_ = 0;
HashMap<uint64_t, ProgressItem> progress_items_;
-
- DISALLOW_COPY_AND_ASSIGN(ProgressTracker);
};
} // namespace blink
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 8c35036da16..2849ca2d5be 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
@@ -240,8 +240,8 @@ void ImageResource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
Resource::OnMemoryDump(level_of_detail, memory_dump);
const String name = GetMemoryDumpName() + "/image_content";
auto* dump = memory_dump->CreateMemoryAllocatorDump(name);
- if (content_->HasImage() && content_->GetImage()->Data())
- dump->AddScalar("size", "bytes", content_->GetImage()->Data()->size());
+ if (content_->HasImage() && content_->GetImage()->HasData())
+ dump->AddScalar("size", "bytes", content_->GetImage()->DataSize());
}
void ImageResource::Trace(Visitor* visitor) const {
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 ac259cb798a..67fec1afaa2 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
@@ -300,7 +300,7 @@ scoped_refptr<Image> ImageResourceContent::CreateImage(bool is_multipart) {
void ImageResourceContent::ClearImage() {
if (!image_)
return;
- int64_t length = image_->Data() ? image_->Data()->size() : 0;
+ int64_t length = image_->HasData() ? image_->DataSize() : 0;
v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-length);
// If our Image has an observer, it's always us so we need to clear the back
@@ -488,9 +488,9 @@ bool ImageResourceContent::IsAcceptableCompressionRatio(
double resource_length =
static_cast<double>(GetResponse().ExpectedContentLength());
- if (resource_length <= 0 && image_->Data()) {
+ if (resource_length <= 0 && image_->HasData()) {
// WPT and LayoutTests server returns -1 or 0 for the content length.
- resource_length = static_cast<double>(image_->Data()->size());
+ resource_length = static_cast<double>(image_->DataSize());
}
// Calculate the image's compression ratio (in bytes per pixel) with both 1k
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_observer.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_observer.h
index 51f9be811a7..c2e31c66d2b 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_observer.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_observer.h
@@ -23,7 +23,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_IMAGE_RESOURCE_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_IMAGE_RESOURCE_OBSERVER_H_
-#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/style/style_image.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_priority.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h
index 94ef1df10dd..9b3f7bbdc73 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h
@@ -41,7 +41,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_MULTIPART_IMAGE_RESOURCE_PARSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_MULTIPART_IMAGE_RESOURCE_PARSER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -64,6 +63,9 @@ class CORE_EXPORT MultipartImageResourceParser final
MultipartImageResourceParser(const ResourceResponse&,
const Vector<char>& boundary,
Client*);
+ MultipartImageResourceParser(const MultipartImageResourceParser&) = delete;
+ MultipartImageResourceParser& operator=(const MultipartImageResourceParser&) =
+ delete;
void AppendData(const char* bytes, wtf_size_t);
void Finish();
void Cancel() { is_cancelled_ = true; }
@@ -96,8 +98,6 @@ class CORE_EXPORT MultipartImageResourceParser final
bool is_parsing_headers_ = false;
bool saw_last_boundary_ = false;
bool is_cancelled_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MultipartImageResourceParser);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc
index d24b98530d0..bad2c4bb749 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc
@@ -8,7 +8,7 @@
#include <stdint.h>
#include <string.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -98,7 +98,7 @@ TEST(MultipartResponseTest, NoStartBoundary) {
"This is a sample response\n"
"--bound--"
"ignore junk after end token --bound\n\nTest2\n";
- parser->AppendData(kData, strlen(kData));
+ parser->AppendData(kData, static_cast<wtf_size_t>(strlen(kData)));
ASSERT_EQ(1u, client->responses_.size());
ASSERT_EQ(1u, client->data_.size());
EXPECT_EQ("This is a sample response", ToString(client->data_[0]));
@@ -124,7 +124,7 @@ TEST(MultipartResponseTest, NoEndBoundary) {
const char kData[] =
"bound\nContent-type: text/plain\n\n"
"This is a sample response\n";
- parser->AppendData(kData, strlen(kData));
+ parser->AppendData(kData, static_cast<wtf_size_t>(strlen(kData)));
ASSERT_EQ(1u, client->responses_.size());
ASSERT_EQ(1u, client->data_.size());
EXPECT_EQ("This is a sample ", ToString(client->data_[0]));
@@ -150,7 +150,7 @@ TEST(MultipartResponseTest, NoStartAndEndBoundary) {
const char kData[] =
"Content-type: text/plain\n\n"
"This is a sample response\n";
- parser->AppendData(kData, strlen(kData));
+ parser->AppendData(kData, static_cast<wtf_size_t>(strlen(kData)));
ASSERT_EQ(1u, client->responses_.size());
ASSERT_EQ(1u, client->data_.size());
EXPECT_EQ("This is a sample ", ToString(client->data_[0]));
@@ -180,7 +180,7 @@ TEST(MultipartResponseTest, MalformedBoundary) {
"This is a sample response\n"
"--bound--"
"ignore junk after end token --bound\n\nTest2\n";
- parser->AppendData(kData, strlen(kData));
+ parser->AppendData(kData, static_cast<wtf_size_t>(strlen(kData)));
ASSERT_EQ(1u, client->responses_.size());
ASSERT_EQ(1u, client->data_.size());
EXPECT_EQ("This is a sample response", ToString(client->data_[0]));
@@ -335,7 +335,7 @@ TEST(MultipartResponseTest, SmallChunk) {
"\n\n--boundContent-type: text/plain\n\n"
"--boundContent-type: text/plain\n\n"
"end--bound--";
- parser->AppendData(kData, strlen(kData));
+ parser->AppendData(kData, static_cast<wtf_size_t>(strlen(kData)));
ASSERT_EQ(4u, client->responses_.size());
ASSERT_EQ(4u, client->data_.size());
EXPECT_EQ("", ToString(client->data_[0]));
@@ -365,7 +365,7 @@ TEST(MultipartResponseTest, MultipleBoundaries) {
client);
const char kData[] = "--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--";
- parser->AppendData(kData, strlen(kData));
+ parser->AppendData(kData, static_cast<wtf_size_t>(strlen(kData)));
ASSERT_EQ(2u, client->responses_.size());
ASSERT_EQ(2u, client->data_.size());
EXPECT_EQ("", ToString(client->data_[0]));
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc
new file mode 100644
index 00000000000..4370c653ed5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc
@@ -0,0 +1,323 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this sink 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/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
+#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
+#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h"
+#include "third_party/blink/renderer/platform/testing/code_cache_loader_mock.h"
+#include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h"
+#include "third_party/blink/renderer/platform/testing/noop_web_url_loader.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
+
+namespace blink {
+namespace {
+
+class ResourceLoaderCodeCacheTest : public testing::Test {
+ protected:
+ static scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() {
+ return base::MakeRefCounted<scheduler::FakeTaskRunner>();
+ }
+
+ ResourceFetcher* MakeResourceFetcher(
+ TestResourceFetcherProperties* properties,
+ FetchContext* context,
+ ResourceFetcher::LoaderFactory* loader_factory) {
+ return MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
+ properties->MakeDetachable(), context, CreateTaskRunner(),
+ CreateTaskRunner(), loader_factory,
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
+ }
+
+ class CodeCacheTestLoaderFactory : public ResourceFetcher::LoaderFactory {
+ public:
+ explicit CodeCacheTestLoaderFactory(
+ scoped_refptr<CodeCacheLoaderMock::Controller> controller)
+ : controller_(std::move(controller)) {}
+ std::unique_ptr<WebURLLoader> CreateURLLoader(
+ const ResourceRequest& request,
+ const ResourceLoaderOptions& options,
+ scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
+ override {
+ return std::make_unique<NoopWebURLLoader>(
+ std::move(freezable_task_runner));
+ }
+ std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
+ return std::make_unique<CodeCacheLoaderMock>(controller_);
+ }
+
+ private:
+ scoped_refptr<CodeCacheLoaderMock::Controller> controller_;
+ };
+
+ void CommonSetup(const char* url_string = nullptr) {
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(
+ "codecachewithhashing");
+
+ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
+ FetchContext* context = MakeGarbageCollected<MockFetchContext>();
+ controller_ = base::MakeRefCounted<CodeCacheLoaderMock::Controller>();
+ controller_->DelayResponse();
+ auto* loader_factory =
+ MakeGarbageCollected<CodeCacheTestLoaderFactory>(controller_);
+ auto* fetcher = MakeResourceFetcher(properties, context, loader_factory);
+
+ KURL url(url_string ? url_string
+ : "codecachewithhashing://www.example.com/");
+ ResourceRequest request(url);
+ request.SetRequestContext(mojom::blink::RequestContextType::SCRIPT);
+
+ FetchParameters params = FetchParameters::CreateForTest(std::move(request));
+ resource_ = ScriptResource::Fetch(params, fetcher, nullptr,
+ ScriptResource::kNoStreaming);
+ loader_ = resource_->Loader();
+
+ response_ = ResourceResponse(url);
+ response_.SetHttpStatusCode(200);
+ }
+
+ static const size_t kSha256Bytes = 256 / 8;
+
+ std::vector<uint8_t> MakeSerializedCodeCacheData(
+ base::span<uint8_t> data,
+ absl::optional<String> source_text = {},
+ uint32_t data_type_id = 0,
+ CachedMetadataHandler::CachedMetadataType outer_type =
+ CachedMetadataHandler::kSingleEntryWithHash,
+ CachedMetadataHandler::CachedMetadataType inner_type =
+ CachedMetadataHandler::kSingleEntry) {
+ const size_t kCachedMetadataTypeSize = sizeof(uint32_t);
+ const size_t kSerializedDataSize = kCachedMetadataTypeSize + kSha256Bytes +
+ kCachedMetaDataStart + data.size();
+ std::vector<uint8_t> serialized_data(kSerializedDataSize);
+ *reinterpret_cast<uint32_t*>(&serialized_data[0]) = outer_type;
+ if (source_text.has_value()) {
+ DigestValue hash;
+ CHECK(ComputeDigest(kHashAlgorithmSha256,
+ static_cast<const char*>(source_text->Bytes()),
+ source_text->CharactersSizeInBytes(), hash));
+ CHECK_EQ(hash.size(), kSha256Bytes);
+ memcpy(&serialized_data[kCachedMetadataTypeSize], hash.data(),
+ kSha256Bytes);
+ }
+ *reinterpret_cast<uint32_t*>(
+ &serialized_data[kCachedMetadataTypeSize + kSha256Bytes]) = inner_type;
+ *reinterpret_cast<uint32_t*>(
+ &serialized_data[kCachedMetadataTypeSize + kSha256Bytes +
+ kCacheDataTypeStart]) = data_type_id;
+ memcpy(&serialized_data[kCachedMetadataTypeSize + kSha256Bytes +
+ kCachedMetaDataStart],
+ data.data(), data.size());
+ return serialized_data;
+ }
+
+ ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
+ platform_;
+
+ // State initialized by CommonSetup().
+ Persistent<ScriptResource> resource_;
+ Persistent<ResourceLoader> loader_;
+ ResourceResponse response_;
+ scoped_refptr<CodeCacheLoaderMock::Controller> controller_;
+};
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheEmptyResponseFirst) {
+ CommonSetup();
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // Nothing has changed yet because the code cache hasn't yet responded.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ // An empty code cache response means no data was found.
+ controller_->Respond(base::Time(), mojo_base::BigBuffer());
+
+ // No code cache data was present.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheEmptyResponseSecond) {
+ CommonSetup();
+
+ // An empty code cache response means no data was found.
+ controller_->Respond(base::Time(), mojo_base::BigBuffer());
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // No code cache data was present.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheFullResponseFirst) {
+ CommonSetup();
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // Nothing has changed yet because the code cache hasn't yet responded.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ controller_->Respond(
+ base::Time(),
+ mojo_base::BigBuffer(MakeSerializedCodeCacheData(cache_data)));
+
+ // Code cache data was present.
+ EXPECT_EQ(resource_->CodeCacheSize(),
+ cache_data.size() + kCachedMetaDataStart);
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheFullResponseSecond) {
+ CommonSetup();
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ controller_->Respond(
+ base::Time(),
+ mojo_base::BigBuffer(MakeSerializedCodeCacheData(cache_data)));
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // Code cache data was present.
+ EXPECT_EQ(resource_->CodeCacheSize(),
+ cache_data.size() + kCachedMetaDataStart);
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheFullHttpsScheme) {
+ CommonSetup("https://www.example.com/");
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ controller_->Respond(
+ base::Time(),
+ mojo_base::BigBuffer(MakeSerializedCodeCacheData(cache_data)));
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // Since the URL was https, and the response times were not set, the cached
+ // metadata should not be set.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheInvalidOuterType) {
+ CommonSetup();
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ controller_->Respond(
+ base::Time(),
+ mojo_base::BigBuffer(MakeSerializedCodeCacheData(
+ cache_data, {}, 0, CachedMetadataHandler::kSingleEntry)));
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // The serialized metadata was rejected due to an invalid outer type.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheInvalidInnerType) {
+ CommonSetup();
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ controller_->Respond(
+ base::Time(),
+ mojo_base::BigBuffer(MakeSerializedCodeCacheData(
+ cache_data, {}, 0, CachedMetadataHandler::kSingleEntryWithHash,
+ CachedMetadataHandler::kSourceKeyedMap)));
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // The serialized metadata was rejected due to an invalid inner type.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheHashCheckSuccess) {
+ CommonSetup();
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ String source_text("alert('hello world');");
+ controller_->Respond(
+ base::Time(), mojo_base::BigBuffer(
+ MakeSerializedCodeCacheData(cache_data, source_text)));
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // Code cache data was present.
+ EXPECT_EQ(resource_->CodeCacheSize(),
+ cache_data.size() + kCachedMetaDataStart);
+
+ // Make sure the following steps don't try to do anything too fancy.
+ resource_->CacheHandler()->DisableSendToPlatformForTesting();
+
+ // Successful check.
+ resource_->CacheHandler()->Check(nullptr, ParkableString(source_text.Impl()));
+
+ // Now the metadata can be accessed.
+ scoped_refptr<CachedMetadata> cached_metadata =
+ resource_->CacheHandler()->GetCachedMetadata(0);
+ EXPECT_EQ(cached_metadata->size(), cache_data.size());
+ EXPECT_EQ(*(cached_metadata->Data() + 2), cache_data[2]);
+
+ // But trying to load the metadata with the wrong data_type_id fails.
+ EXPECT_FALSE(resource_->CacheHandler()->GetCachedMetadata(4));
+}
+
+TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheHashCheckFailure) {
+ CommonSetup();
+
+ std::vector<uint8_t> cache_data{2, 3, 4, 5, 6};
+ String source_text("alert('hello world');");
+ controller_->Respond(
+ base::Time(), mojo_base::BigBuffer(
+ MakeSerializedCodeCacheData(cache_data, source_text)));
+
+ // Nothing has changed yet because the content response hasn't arrived yet.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+
+ loader_->DidReceiveResponse(WrappedResourceResponse(response_));
+
+ // Code cache data was present.
+ EXPECT_EQ(resource_->CodeCacheSize(),
+ cache_data.size() + kCachedMetaDataStart);
+
+ // Make sure the following steps don't try to do anything too fancy.
+ resource_->CacheHandler()->DisableSendToPlatformForTesting();
+
+ // Failed check: source text is different.
+ String source_text_2("alert('improved program');");
+ resource_->CacheHandler()->Check(nullptr,
+ ParkableString(source_text_2.Impl()));
+
+ // The metadata has been cleared.
+ EXPECT_FALSE(resource_->CodeCacheSize());
+ EXPECT_FALSE(resource_->CacheHandler()->GetCachedMetadata(0));
+}
+
+} // namespace
+} // namespace blink
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 80238ec76ed..22d6955f59d 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
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
@@ -200,10 +201,24 @@ void ScriptResource::SetSerializedCachedMetadata(mojo_base::BigBuffer data) {
}
}
+bool ScriptResource::CodeCacheHashRequired() const {
+ if (cached_metadata_handler_) {
+ bool result = cached_metadata_handler_->HashRequired();
+ if (result) {
+ DCHECK(SchemeRegistry::SchemeSupportsCodeCacheWithHashing(
+ GetResourceRequest().Url().Protocol()));
+ }
+ return result;
+ }
+ return false;
+}
+
void ScriptResource::DestroyDecodedDataIfPossible() {
if (cached_metadata_handler_) {
+ // Since we are clearing locally we don't need a CodeCacheHost interface
+ // here. It just clears the data in the cached_metadata_handler.
cached_metadata_handler_->ClearCachedMetadata(
- CachedMetadataHandler::kClearLocally);
+ /*code_cache_host*/ nullptr, CachedMetadataHandler::kClearLocally);
}
}
@@ -259,14 +274,29 @@ void ScriptResource::ResponseReceived(const ResourceResponse& response) {
}
cached_metadata_handler_ = nullptr;
- // Currently we support the metadata caching only for HTTP family.
- if (GetResourceRequest().Url().ProtocolIsInHTTPFamily() &&
- response.CurrentRequestUrl().ProtocolIsInHTTPFamily()) {
- cached_metadata_handler_ =
- MakeGarbageCollected<ScriptCachedMetadataHandler>(
- Encoding(), CachedMetadataSender::Create(
- response, mojom::blink::CodeCacheType::kJavascript,
- GetResourceRequest().RequestorOrigin()));
+ // Currently we support the metadata caching only for HTTP family and any
+ // schemes defined by SchemeRegistry as requiring a hash check.
+ bool http_family = GetResourceRequest().Url().ProtocolIsInHTTPFamily() &&
+ response.CurrentRequestUrl().ProtocolIsInHTTPFamily();
+ bool code_cache_with_hashing_supported =
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(
+ GetResourceRequest().Url().Protocol()) &&
+ GetResourceRequest().Url().ProtocolIs(
+ response.CurrentRequestUrl().Protocol());
+ bool code_cache_supported = http_family || code_cache_with_hashing_supported;
+ if (code_cache_supported) {
+ std::unique_ptr<CachedMetadataSender> sender = CachedMetadataSender::Create(
+ response, mojom::blink::CodeCacheType::kJavascript,
+ GetResourceRequest().RequestorOrigin());
+ if (code_cache_with_hashing_supported) {
+ cached_metadata_handler_ =
+ MakeGarbageCollected<ScriptCachedMetadataHandlerWithHashing>(
+ Encoding(), std::move(sender));
+ } else {
+ cached_metadata_handler_ =
+ MakeGarbageCollected<ScriptCachedMetadataHandler>(Encoding(),
+ std::move(sender));
+ }
}
} // namespace blink
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 f6c5707e3ed..afebd210d5b 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
@@ -94,6 +94,8 @@ class CORE_EXPORT ScriptResource final : public TextResource {
void SetSerializedCachedMetadata(mojo_base::BigBuffer data) override;
+ bool CodeCacheHashRequired() const override;
+
const ParkableString& SourceText();
// Get the resource's current text. This can return partial data, so should
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/script_resource_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
index 04436fcb9e6..8711d399324 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
@@ -5,8 +5,9 @@
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
namespace blink {
@@ -88,5 +89,42 @@ TEST(ScriptResourceTest, RedirectDuringRevalidation) {
EXPECT_FALSE(new_handler);
}
+TEST(ScriptResourceTest, WebUICodeCacheEnabled) {
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(
+ "codecachewithhashing");
+
+ const KURL url("codecachewithhashing://www.example.com/script.js");
+ ScriptResource* resource = ScriptResource::CreateForTest(url, UTF8Encoding());
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ resource->ResponseReceived(response);
+ constexpr char kData[5] = "abcd";
+ resource->AppendData(kData, strlen(kData));
+ resource->FinishForTest();
+
+ auto* handler = resource->CacheHandler();
+ EXPECT_TRUE(handler);
+ EXPECT_TRUE(handler->HashRequired());
+ EXPECT_EQ(UTF8Encoding().GetName(), handler->Encoding());
+
+ SchemeRegistry::RemoveURLSchemeAsCodeCacheWithHashing("codecachewithhashing");
+}
+
+TEST(ScriptResourceTest, WebUICodeCacheDisabled) {
+ const KURL url("nocodecachewithhashing://www.example.com/script.js");
+ ScriptResource* resource = ScriptResource::CreateForTest(url, UTF8Encoding());
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ resource->ResponseReceived(response);
+ constexpr char kData[5] = "abcd";
+ resource->AppendData(kData, strlen(kData));
+ resource->FinishForTest();
+
+ auto* handler = resource->CacheHandler();
+ EXPECT_FALSE(handler);
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
index f6697ac36f1..b672cebc622 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -4,15 +4,21 @@
#include "third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h"
+#include "base/stl_util.h"
#include "components/power_scheduler/power_mode_arbiter.h"
+#include "services/network/public/cpp/cors/cors_error_status.h"
+#include "services/network/public/mojom/cors.mojom-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/security/address_space_feature.h"
#include "third_party/blink/renderer/core/core_probes_inl.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/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/loader/address_space_feature.h"
#include "third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
@@ -28,6 +34,7 @@
#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"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.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/loader/fetch/resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -35,6 +42,91 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
namespace blink {
+namespace {
+
+// The list of features which should be reported as deprecated.
+constexpr WebFeature kDeprecatedAddressSpaceFeatures[] = {
+ WebFeature::kAddressSpacePublicNonSecureContextEmbeddedPrivate,
+ WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocal,
+ WebFeature::kAddressSpacePrivateNonSecureContextEmbeddedLocal,
+};
+
+// Returns whether |feature| is deprecated.
+bool IsDeprecatedAddressSpaceFeature(WebFeature feature) {
+ for (WebFeature entry : kDeprecatedAddressSpaceFeatures) {
+ if (feature == entry) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Increments the correct kAddressSpace* WebFeature UseCounter corresponding to
+// the given |client_frame| performing a subresource fetch |fetch_type| and
+// receiving the given |response|.
+//
+// Does nothing if |client_frame| is nullptr.
+void RecordAddressSpaceFeature(LocalFrame* client_frame,
+ const ResourceResponse& response) {
+ if (!client_frame) {
+ return;
+ }
+
+ LocalDOMWindow* window = client_frame->DomWindow();
+ absl::optional<WebFeature> feature =
+ AddressSpaceFeature(FetchType::kSubresource, window->AddressSpace(),
+ window->IsSecureContext(), response.AddressSpace());
+ if (!feature.has_value()) {
+ return;
+ }
+
+ // This WebFeature encompasses all private network requests.
+ UseCounter::Count(window,
+ WebFeature::kMixedContentPrivateHostnameInPublicHostname);
+
+ if (IsDeprecatedAddressSpaceFeature(*feature)) {
+ Deprecation::CountDeprecation(window, *feature);
+ } else {
+ UseCounter::Count(window, *feature);
+ }
+}
+
+// Same as above, for cases where the fetch failed.
+// Does nothing if the fetch failed due to an error other than a failed Private
+// Network Access check.
+void RecordAddressSpaceFeature(LocalFrame* client_frame,
+ const ResourceError& error) {
+ if (!client_frame) {
+ return;
+ }
+
+ absl::optional<network::CorsErrorStatus> status = error.CorsErrorStatus();
+ if (!status.has_value() ||
+ status->cors_error !=
+ network::mojom::CorsError::kInsecurePrivateNetwork) {
+ // Not the right kind of error, ignore.
+ return;
+ }
+
+ LocalDOMWindow* window = client_frame->DomWindow();
+ absl::optional<WebFeature> feature = AddressSpaceFeature(
+ FetchType::kSubresource, window->AddressSpace(),
+ window->IsSecureContext(), status->resource_address_space);
+ if (!feature.has_value()) {
+ return;
+ }
+
+ // This WebFeature encompasses all private network requests.
+ UseCounter::Count(window,
+ WebFeature::kMixedContentPrivateHostnameInPublicHostname);
+
+ // Count the feature but do not log it as a deprecation, since its use is
+ // forbidden and has resulted in the fetch failing. In other words, the
+ // document only *attempted* to use a feature that is no longer available.
+ UseCounter::Count(window, *feature);
+}
+
+} // namespace
ResourceLoadObserverForFrame::ResourceLoadObserverForFrame(
DocumentLoader& loader,
@@ -154,7 +246,7 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
return;
}
- RecordAddressSpaceFeature(FetchType::kSubresource, frame, response);
+ RecordAddressSpaceFeature(frame, response);
std::unique_ptr<AlternateSignedExchangeResourceInfo> alternate_resource_info;
@@ -268,7 +360,7 @@ void ResourceLoadObserverForFrame::DidFailLoading(
probe::DidFailLoading(GetProbe(), identifier, document_loader_, error,
frame->GetDevToolsFrameToken());
- RecordAddressSpaceFeature(FetchType::kSubresource, frame, error);
+ RecordAddressSpaceFeature(frame, error);
// Notification to FrameConsole should come AFTER InspectorInstrumentation
// call, DevTools front-end relies on this.
@@ -287,6 +379,21 @@ void ResourceLoadObserverForFrame::DidFailLoading(
document_->CheckCompleted();
}
+void ResourceLoadObserverForFrame::DidChangeRenderBlockingBehavior(
+ Resource* resource,
+ const FetchParameters& params) {
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+ "devtools.timeline", "PreloadRenderBlockingStatusChange",
+ TRACE_EVENT_SCOPE_THREAD, base::TimeTicks::Now(), "data",
+ [&](perfetto::TracedValue ctx) {
+ inspector_change_render_blocking_behavior_event::Data(
+ std::move(ctx), document_->Loader(),
+ resource->GetResourceRequest().InspectorId(),
+ resource->GetResourceRequest(),
+ params.GetResourceRequest().GetRenderBlockingBehavior());
+ });
+}
+
void ResourceLoadObserverForFrame::Trace(Visitor* visitor) const {
visitor->Trace(document_loader_);
visitor->Trace(document_);
diff --git a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
index e1f00c904ed..5ef931f758d 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
@@ -60,6 +60,8 @@ class CORE_EXPORT ResourceLoadObserverForFrame final
const ResourceError&,
int64_t encoded_data_length,
IsInternalRequest) override;
+ void DidChangeRenderBlockingBehavior(Resource* resource,
+ const FetchParameters& params) override;
void Trace(Visitor*) const override;
private:
diff --git a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
index 41307445a7c..2e4ee05b97f 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
@@ -57,6 +57,9 @@ class ResourceLoadObserverForWorker final : public ResourceLoadObserver {
const ResourceError&,
int64_t encoded_data_length,
IsInternalRequest) override;
+ void DidChangeRenderBlockingBehavior(Resource* resource,
+ const FetchParameters& params) override {
+ }
void Trace(Visitor*) const override;
private:
diff --git a/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.cc b/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.cc
index 24b05547628..92170db4e4e 100644
--- a/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.cc
+++ b/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/csp/csp_directive_list.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -29,16 +30,6 @@ bool IsSchemeHttpOrHttps(const KURL& url) {
url.Protocol() == url::kHttpScheme;
}
-// Returns the origin to use for subresource redirect from fieldtrial or the
-// default.
-scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin() {
- auto lite_page_subresource_origin = base::GetFieldTrialParamValueByFeature(
- blink::features::kSubresourceRedirect, "lite_page_subresource_origin");
- if (lite_page_subresource_origin.empty())
- return SecurityOrigin::CreateFromString("https://litepages.googlezip.net/");
- return SecurityOrigin::CreateFromString(lite_page_subresource_origin.c_str());
-}
-
// Returns whether CSP restricted subresource redirect images should be allowed
// for subresource redirect compression.
bool ShouldAllowCspRestrictedImages() {
@@ -110,11 +101,17 @@ bool ShouldEnableSubresourceRedirect(HTMLImageElement* image_element,
// Check the actual subresource redirect URL constructed from the subresource
// redirect origin is restricted by CSP.
- auto subresource_redirect_origin = GetLitePageSubresourceRedirectOrigin();
+ auto litepage_subresource_redirect_origin = SecurityOrigin::CreateFromString(
+ image_element->GetDocument()
+ .GetSettings()
+ ->GetLitePageSubresourceRedirectOrigin());
KURL subresource_redirect_url = url;
- subresource_redirect_url.SetProtocol(subresource_redirect_origin->Protocol());
- subresource_redirect_url.SetHost(subresource_redirect_origin->Host());
- subresource_redirect_url.SetPort(subresource_redirect_origin->Port());
+ subresource_redirect_url.SetProtocol(
+ litepage_subresource_redirect_origin->Protocol());
+ subresource_redirect_url.SetHost(
+ litepage_subresource_redirect_origin->Host());
+ subresource_redirect_url.SetPort(
+ litepage_subresource_redirect_origin->Port());
auto* content_security_policy =
image_element->GetExecutionContext()->GetContentSecurityPolicy();
if (content_security_policy &&
@@ -141,7 +138,8 @@ bool ShouldEnableSubresourceRedirect(HTMLImageElement* image_element,
return true;
}
-bool ShouldDisableCSPCheckForSubresourceRedirectOrigin(
+bool ShouldDisableCSPCheckForLitePageSubresourceRedirectOrigin(
+ scoped_refptr<SecurityOrigin> litepage_subresource_redirect_origin,
mojom::blink::RequestContextType request_context,
ResourceRequest::RedirectStatus redirect_status,
const KURL& url) {
@@ -156,10 +154,10 @@ bool ShouldDisableCSPCheckForSubresourceRedirectOrigin(
if (!ShouldAllowCspRestrictedImages())
return false;
- auto subresource_redirect_origin = GetLitePageSubresourceRedirectOrigin();
- DCHECK(!subresource_redirect_origin->IsOpaque());
+ if (litepage_subresource_redirect_origin->IsOpaque())
+ return false;
- return subresource_redirect_origin->IsSameOriginWith(
+ return litepage_subresource_redirect_origin->IsSameOriginWith(
SecurityOrigin::Create(url).get());
}
diff --git a/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.h b/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.h
index b8315d1779e..c27d28f119c 100644
--- a/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.h
+++ b/chromium/third_party/blink/renderer/core/loader/subresource_redirect_util.h
@@ -43,7 +43,8 @@ bool ShouldEnableSubresourceRedirect(HTMLImageElement* image_element,
// Returns whether CSP check should be disabled for this resource request for
// |url| with the given |request_context| and |redirect_status|.
-bool ShouldDisableCSPCheckForSubresourceRedirectOrigin(
+bool ShouldDisableCSPCheckForLitePageSubresourceRedirectOrigin(
+ scoped_refptr<SecurityOrigin> litepage_subresource_redirect_origin,
mojom::blink::RequestContextType request_context,
ResourceRequest::RedirectStatus redirect_status,
const KURL& url);
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 a0973dab883..8af932df025 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -42,12 +42,12 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.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/heap/heap.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/fetch/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
@@ -73,8 +73,12 @@ class DetachedClient final : public GarbageCollected<DetachedClient>,
void DidFinishLoading(uint64_t identifier) override {
self_keep_alive_.Clear();
}
- void DidFail(const ResourceError&) override { self_keep_alive_.Clear(); }
- void DidFailRedirectCheck() override { self_keep_alive_.Clear(); }
+ void DidFail(uint64_t identifier, const ResourceError&) override {
+ self_keep_alive_.Clear();
+ }
+ void DidFailRedirectCheck(uint64_t identifier) override {
+ self_keep_alive_.Clear();
+ }
void Trace(Visitor* visitor) const override {
visitor->Trace(loader_);
ThreadableLoaderClient::Trace(visitor);
@@ -103,8 +107,6 @@ ThreadableLoader::ThreadableLoader(
&ThreadableLoader::DidTimeout) {
DCHECK(client);
if (!resource_fetcher_) {
- if (auto* scope = DynamicTo<WorkerGlobalScope>(*execution_context_))
- scope->EnsureFetcher();
resource_fetcher_ = execution_context_->Fetcher();
}
}
@@ -214,9 +216,8 @@ void ThreadableLoader::Detach() {
void ThreadableLoader::SetDefersLoading(bool value) {
if (GetResource() && GetResource()->Loader()) {
- GetResource()->Loader()->SetDefersLoading(
- value ? WebURLLoader::DeferType::kDeferred
- : WebURLLoader::DeferType::kNotDeferred);
+ GetResource()->Loader()->SetDefersLoading(value ? LoaderFreezeMode::kStrict
+ : LoaderFreezeMode::kNone);
}
}
@@ -237,7 +238,8 @@ bool ThreadableLoader::RedirectReceived(
DCHECK_EQ(resource, GetResource());
checker_.RedirectReceived();
- return client_->WillFollowRedirect(new_request.Url(), redirect_response);
+ return client_->WillFollowRedirect(resource->InspectorId(), new_request.Url(),
+ redirect_response);
}
void ThreadableLoader::RedirectBlocked() {
@@ -248,7 +250,8 @@ void ThreadableLoader::RedirectBlocked() {
// unknown reason).
ThreadableLoaderClient* client = client_;
Clear();
- client->DidFailRedirectCheck();
+ uint64_t identifier = 0; // We don't have an inspector id here.
+ client->DidFailRedirectCheck(identifier);
}
void ThreadableLoader::DataSent(Resource* resource,
@@ -376,7 +379,7 @@ void ThreadableLoader::DispatchDidFail(const ResourceError& error) {
resource->SetResponseType(network::mojom::FetchResponseType::kError);
ThreadableLoaderClient* client = client_;
Clear();
- client->DidFail(error);
+ client->DidFail(resource->InspectorId(), error);
}
void ThreadableLoader::Trace(Visitor* visitor) const {
diff --git a/chromium/third_party/blink/renderer/core/loader/threadable_loader.h b/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
index 63dc34ad534..b3043bb0e8d 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
@@ -32,10 +32,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_H_
-#include "base/macros.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
-#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
@@ -95,6 +93,8 @@ class CORE_EXPORT ThreadableLoader final
ThreadableLoaderClient*,
const ResourceLoaderOptions&,
ResourceFetcher* = nullptr);
+ ThreadableLoader(const ThreadableLoader&) = delete;
+ ThreadableLoader& operator=(const ThreadableLoader&) = delete;
~ThreadableLoader() override;
// Must be called to actually begin the request.
@@ -167,8 +167,6 @@ class CORE_EXPORT ThreadableLoader final
base::TimeTicks request_started_;
RawResourceClientStateChecker checker_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadableLoader);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/threadable_loader_client.h b/chromium/third_party/blink/renderer/core/loader/threadable_loader_client.h
index 90b82b29b21..6c6b8fe0b48 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader_client.h
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader_client.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_CLIENT_H_
-#include "base/macros.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -50,7 +49,8 @@ class CORE_EXPORT ThreadableLoaderClient : public GarbageCollectedMixin {
uint64_t /*totalBytesToBeSent*/) {}
// Note that redirects for redirect modes kError and kManual are still
// notified here. A client must return false in such cases.
- virtual bool WillFollowRedirect(const KURL& new_url,
+ virtual bool WillFollowRedirect(uint64_t /*identifier*/,
+ const KURL& new_url,
const ResourceResponse&) {
return true;
}
@@ -60,8 +60,8 @@ class CORE_EXPORT ThreadableLoaderClient : public GarbageCollectedMixin {
virtual void DidReceiveData(const char*, unsigned /*dataLength*/) {}
virtual void DidReceiveCachedMetadata(mojo_base::BigBuffer) {}
virtual void DidFinishLoading(uint64_t /*identifier*/) {}
- virtual void DidFail(const ResourceError&) {}
- virtual void DidFailRedirectCheck() {}
+ virtual void DidFail(uint64_t /*identifier*/, const ResourceError&) {}
+ virtual void DidFailRedirectCheck(uint64_t /*identifier*/) {}
virtual void DidDownloadData(uint64_t /*dataLength*/) {}
// Called for requests that had DownloadToBlob set to true. Can be called with
@@ -70,12 +70,12 @@ class CORE_EXPORT ThreadableLoaderClient : public GarbageCollectedMixin {
// resource ended up being zero bytes.
virtual void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) {}
+ ThreadableLoaderClient(const ThreadableLoaderClient&) = delete;
+ ThreadableLoaderClient& operator=(const ThreadableLoaderClient&) = delete;
virtual ~ThreadableLoaderClient() = default;
protected:
ThreadableLoaderClient() = default;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadableLoaderClient);
};
} // namespace blink
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 101b5b52a95..ba3f06431ad 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
@@ -63,8 +63,8 @@ class MockThreadableLoaderClient final
MOCK_METHOD2(DidReceiveData, void(const char*, unsigned));
MOCK_METHOD1(DidReceiveCachedMetadata, void(mojo_base::BigBuffer));
MOCK_METHOD1(DidFinishLoading, void(uint64_t));
- MOCK_METHOD1(DidFail, void(const ResourceError&));
- MOCK_METHOD0(DidFailRedirectCheck, void());
+ MOCK_METHOD2(DidFail, void(uint64_t, const ResourceError&));
+ MOCK_METHOD1(DidFailRedirectCheck, void(uint64_t));
MOCK_METHOD1(DidDownloadData, void(uint64_t));
};
@@ -232,7 +232,7 @@ TEST_F(ThreadableLoaderTest, CancelAfterStart) {
EXPECT_CALL(GetCheckpoint(), Call(2))
.WillOnce(InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelLoader));
- EXPECT_CALL(*Client(), DidFail(Truly(IsCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsCancellation)));
EXPECT_CALL(GetCheckpoint(), Call(3));
StartLoader(SuccessURL());
@@ -250,7 +250,7 @@ TEST_F(ThreadableLoaderTest, CancelAndClearAfterStart) {
EXPECT_CALL(GetCheckpoint(), Call(2))
.WillOnce(
InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelAndClearLoader));
- EXPECT_CALL(*Client(), DidFail(Truly(IsCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsCancellation)));
EXPECT_CALL(GetCheckpoint(), Call(3));
StartLoader(SuccessURL());
@@ -268,7 +268,7 @@ TEST_F(ThreadableLoaderTest, CancelInDidReceiveResponse) {
EXPECT_CALL(GetCheckpoint(), Call(2));
EXPECT_CALL(*Client(), DidReceiveResponse(_, _))
.WillOnce(InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelLoader));
- EXPECT_CALL(*Client(), DidFail(Truly(IsCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsCancellation)));
StartLoader(SuccessURL());
CallCheckpoint(2);
@@ -285,7 +285,7 @@ TEST_F(ThreadableLoaderTest, CancelAndClearInDidReceiveResponse) {
EXPECT_CALL(*Client(), DidReceiveResponse(_, _))
.WillOnce(
InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelAndClearLoader));
- EXPECT_CALL(*Client(), DidFail(Truly(IsCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsCancellation)));
StartLoader(SuccessURL());
CallCheckpoint(2);
@@ -302,7 +302,7 @@ TEST_F(ThreadableLoaderTest, CancelInDidReceiveData) {
EXPECT_CALL(*Client(), DidReceiveResponse(_, _));
EXPECT_CALL(*Client(), DidReceiveData(_, _))
.WillOnce(InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelLoader));
- EXPECT_CALL(*Client(), DidFail(Truly(IsCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsCancellation)));
StartLoader(SuccessURL());
CallCheckpoint(2);
@@ -320,7 +320,7 @@ TEST_F(ThreadableLoaderTest, CancelAndClearInDidReceiveData) {
EXPECT_CALL(*Client(), DidReceiveData(_, _))
.WillOnce(
InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelAndClearLoader));
- EXPECT_CALL(*Client(), DidFail(Truly(IsCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsCancellation)));
StartLoader(SuccessURL());
CallCheckpoint(2);
@@ -384,7 +384,7 @@ TEST_F(ThreadableLoaderTest, DidFail) {
CallCheckpoint(1);
EXPECT_CALL(GetCheckpoint(), Call(2));
- EXPECT_CALL(*Client(), DidFail(Truly(IsNotCancellation)));
+ EXPECT_CALL(*Client(), DidFail(_, Truly(IsNotCancellation)));
StartLoader(ErrorURL());
CallCheckpoint(2);
@@ -398,7 +398,7 @@ TEST_F(ThreadableLoaderTest, CancelInDidFail) {
CallCheckpoint(1);
EXPECT_CALL(GetCheckpoint(), Call(2));
- EXPECT_CALL(*Client(), DidFail(_))
+ EXPECT_CALL(*Client(), DidFail(_, _))
.WillOnce(InvokeWithoutArgs(this, &ThreadableLoaderTest::CancelLoader));
StartLoader(ErrorURL());
@@ -413,7 +413,7 @@ TEST_F(ThreadableLoaderTest, ClearInDidFail) {
CallCheckpoint(1);
EXPECT_CALL(GetCheckpoint(), Call(2));
- EXPECT_CALL(*Client(), DidFail(_))
+ EXPECT_CALL(*Client(), DidFail(_, _))
.WillOnce(InvokeWithoutArgs(this, &ThreadableLoaderTest::ClearLoader));
StartLoader(ErrorURL());
diff --git a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
index cd250b8004e..243ed94e670 100644
--- a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
@@ -6,8 +6,8 @@
#include <algorithm>
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
#include "skia/ext/image_operations.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -119,7 +119,7 @@ void ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread(
}
decoded_icon_ = image_frame->Bitmap();
- if (!resize_dimensions_) {
+ if (!resize_dimensions_ || resize_dimensions_->IsEmpty()) {
notify_complete(1.0);
return;
}
@@ -138,11 +138,11 @@ void ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread(
}
int resized_width =
- base::ClampToRange(static_cast<int>(scale * decoded_icon_.width()), 1,
- resize_dimensions_->width());
+ base::clamp(static_cast<int>(scale * decoded_icon_.width()), 1,
+ resize_dimensions_->width());
int resized_height =
- base::ClampToRange(static_cast<int>(scale * decoded_icon_.height()), 1,
- resize_dimensions_->height());
+ base::clamp(static_cast<int>(scale * decoded_icon_.height()), 1,
+ resize_dimensions_->height());
// Use the RESIZE_GOOD quality allowing the implementation to pick an
// appropriate method for the resize. Can be increased to RESIZE_BETTER
@@ -166,13 +166,13 @@ void ThreadedIconLoader::OnBackgroundTaskComplete(double resize_scale) {
std::move(icon_callback_).Run(std::move(decoded_icon_), resize_scale);
}
-void ThreadedIconLoader::DidFail(const ResourceError& error) {
+void ThreadedIconLoader::DidFail(uint64_t, const ResourceError& error) {
if (stopped_)
return;
std::move(icon_callback_).Run(SkBitmap(), -1);
}
-void ThreadedIconLoader::DidFailRedirectCheck() {
+void ThreadedIconLoader::DidFailRedirectCheck(uint64_t) {
if (stopped_)
return;
std::move(icon_callback_).Run(SkBitmap(), -1);
diff --git a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h
index f82d0858fd0..c1a9bb22b21 100644
--- a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h
@@ -46,8 +46,8 @@ class CORE_EXPORT ThreadedIconLoader final
// ThreadableLoaderClient interface.
void DidReceiveData(const char* data, unsigned length) override;
void DidFinishLoading(uint64_t resource_identifier) override;
- void DidFail(const ResourceError& error) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t, const ResourceError& error) override;
+ void DidFailRedirectCheck(uint64_t) override;
void Trace(Visitor* visitor) const override;
diff --git a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc
index ad5b7c0761f..2897f0139fb 100644
--- a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc
+++ b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc
@@ -34,7 +34,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "services/network/public/cpp/request_destination.h"
#include "services/network/public/cpp/request_mode.h"
@@ -73,6 +72,9 @@ namespace {
class HTTPRequestHeaderValidator : public WebHTTPHeaderVisitor {
public:
HTTPRequestHeaderValidator() : is_safe_(true) {}
+ HTTPRequestHeaderValidator(const HTTPRequestHeaderValidator&) = delete;
+ HTTPRequestHeaderValidator& operator=(const HTTPRequestHeaderValidator&) =
+ delete;
~HTTPRequestHeaderValidator() override = default;
void VisitHeader(const WebString& name, const WebString& value) override;
@@ -80,8 +82,6 @@ class HTTPRequestHeaderValidator : public WebHTTPHeaderVisitor {
private:
bool is_safe_;
-
- DISALLOW_COPY_AND_ASSIGN(HTTPRequestHeaderValidator);
};
void HTTPRequestHeaderValidator::VisitHeader(const WebString& name,
@@ -107,6 +107,8 @@ class WebAssociatedURLLoaderImpl::ClientAdapter final
network::mojom::RequestMode,
network::mojom::CredentialsMode,
scoped_refptr<base::SingleThreadTaskRunner>);
+ ClientAdapter(const ClientAdapter&) = delete;
+ ClientAdapter& operator=(const ClientAdapter&) = delete;
// ThreadableLoaderClient
void DidSendData(uint64_t /*bytesSent*/,
@@ -115,11 +117,12 @@ class WebAssociatedURLLoaderImpl::ClientAdapter final
void DidDownloadData(uint64_t /*dataLength*/) override;
void DidReceiveData(const char*, unsigned /*dataLength*/) override;
void DidFinishLoading(uint64_t /*identifier*/) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t /*identifier*/, const ResourceError&) override;
+ void DidFailRedirectCheck(uint64_t /*identifier*/) override;
// ThreadableLoaderClient
bool WillFollowRedirect(
+ uint64_t /*identifier*/,
const KURL& /*new_url*/,
const ResourceResponse& /*redirect_response*/) override;
@@ -158,8 +161,6 @@ class WebAssociatedURLLoaderImpl::ClientAdapter final
HeapTaskRunnerTimer<ClientAdapter> error_timer_;
bool enable_error_notifications_;
bool did_fail_;
-
- DISALLOW_COPY_AND_ASSIGN(ClientAdapter);
};
WebAssociatedURLLoaderImpl::ClientAdapter::ClientAdapter(
@@ -182,6 +183,7 @@ WebAssociatedURLLoaderImpl::ClientAdapter::ClientAdapter(
}
bool WebAssociatedURLLoaderImpl::ClientAdapter::WillFollowRedirect(
+ uint64_t identifier,
const KURL& new_url,
const ResourceResponse& redirect_response) {
if (!client_)
@@ -271,6 +273,7 @@ void WebAssociatedURLLoaderImpl::ClientAdapter::DidFinishLoading(
}
void WebAssociatedURLLoaderImpl::ClientAdapter::DidFail(
+ uint64_t,
const ResourceError& error) {
if (!client_)
return;
@@ -283,8 +286,9 @@ void WebAssociatedURLLoaderImpl::ClientAdapter::DidFail(
NotifyError(&error_timer_);
}
-void WebAssociatedURLLoaderImpl::ClientAdapter::DidFailRedirectCheck() {
- DidFail(ResourceError::Failure(NullURL()));
+void WebAssociatedURLLoaderImpl::ClientAdapter::DidFailRedirectCheck(
+ uint64_t identifier) {
+ DidFail(identifier, ResourceError::Failure(NullURL()));
}
void WebAssociatedURLLoaderImpl::ClientAdapter::EnableErrorNotifications() {
@@ -444,8 +448,10 @@ void WebAssociatedURLLoaderImpl::LoadAsynchronously(
}
if (!loader_) {
- client_adapter_->DidFail(ResourceError::CancelledDueToAccessCheckError(
- request.Url(), ResourceRequestBlockedReason::kOther));
+ client_adapter_->DidFail(
+ 0 /* identifier */,
+ ResourceError::CancelledDueToAccessCheckError(
+ request.Url(), ResourceRequestBlockedReason::kOther));
}
client_adapter_->EnableErrorNotifications();
}
diff --git a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h
index 9c9ef87280d..2fda17816ac 100644
--- a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h
+++ b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_WEB_ASSOCIATED_URL_LOADER_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_WEB_ASSOCIATED_URL_LOADER_IMPL_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/web/web_associated_url_loader.h"
@@ -27,6 +26,9 @@ class CORE_EXPORT WebAssociatedURLLoaderImpl final
public:
WebAssociatedURLLoaderImpl(ExecutionContext*,
const WebAssociatedURLLoaderOptions&);
+ WebAssociatedURLLoaderImpl(const WebAssociatedURLLoaderImpl&) = delete;
+ WebAssociatedURLLoaderImpl& operator=(const WebAssociatedURLLoaderImpl&) =
+ delete;
~WebAssociatedURLLoaderImpl() override;
void LoadAsynchronously(const WebURLRequest&,
@@ -63,8 +65,6 @@ class CORE_EXPORT WebAssociatedURLLoaderImpl final
// A ExecutionContextLifecycleObserver for cancelling |loader_| when the
// context is detached.
Persistent<Observer> observer_;
-
- DISALLOW_COPY_AND_ASSIGN(WebAssociatedURLLoaderImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl_test.cc b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl_test.cc
index e2907b8427e..9525e556621 100644
--- a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl_test.cc
@@ -32,7 +32,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
index 85ddc39f30f..14accc9e27a 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
@@ -38,12 +38,8 @@ bool WorkerResourceFetcherProperties::IsPaused() const {
return global_scope_->IsContextPaused();
}
-WebURLLoader::DeferType WorkerResourceFetcherProperties::DeferType() const {
- return global_scope_->DeferType();
-}
-
-bool WorkerResourceFetcherProperties::IsLoadDeferred() const {
- return global_scope_->IsLoadDeferred();
+LoaderFreezeMode WorkerResourceFetcherProperties::FreezeMode() const {
+ return global_scope_->GetLoaderFreezeMode();
}
const KURL& WorkerResourceFetcherProperties::WebBundlePhysicalUrl() const {
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
index bfb7f57add2..5c9d9a0364f 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
@@ -42,9 +42,8 @@ class WorkerResourceFetcherProperties final : public ResourceFetcherProperties {
return -1;
}
bool IsPaused() const override;
- WebURLLoader::DeferType DeferType() const override;
+ LoaderFreezeMode FreezeMode() const override;
bool IsDetached() const override { return false; }
- bool IsLoadDeferred() const override;
bool IsLoadComplete() const override { return false; }
bool ShouldBlockLoadingSubResource() const override { return false; }
bool IsSubframeDeprioritizationEnabled() const override { return false; }
@@ -53,6 +52,10 @@ class WorkerResourceFetcherProperties final : public ResourceFetcherProperties {
}
const KURL& WebBundlePhysicalUrl() const override;
int GetOutstandingThrottledLimit() const override;
+ scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin()
+ const override {
+ return nullptr;
+ }
private:
const Member<WorkerOrWorkletGlobalScope> global_scope_;
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h b/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h
index 15363367201..569bdf97a1a 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h
+++ b/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h
@@ -37,6 +37,10 @@ class CORE_EXPORT WorkerResourceTimingNotifierImpl final
// only for MakeGarbageCollected.
explicit WorkerResourceTimingNotifierImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ WorkerResourceTimingNotifierImpl(const WorkerResourceTimingNotifierImpl&) =
+ delete;
+ WorkerResourceTimingNotifierImpl& operator=(
+ const WorkerResourceTimingNotifierImpl&) = delete;
~WorkerResourceTimingNotifierImpl() override = default;
void AddResourceTiming(
@@ -68,8 +72,6 @@ class CORE_EXPORT WorkerResourceTimingNotifierImpl final
// Used when the execution context lives on a different sequence of this
// notifier.
CrossThreadWeakPersistent<ExecutionContext> outside_execution_context_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerResourceTimingNotifierImpl);
};
// NullWorkerResourceTimingNotifier does nothing when AddResourceTiming() is
@@ -78,6 +80,10 @@ class CORE_EXPORT NullWorkerResourceTimingNotifier final
: public WorkerResourceTimingNotifier {
public:
NullWorkerResourceTimingNotifier() = default;
+ NullWorkerResourceTimingNotifier(const NullWorkerResourceTimingNotifier&) =
+ delete;
+ NullWorkerResourceTimingNotifier& operator=(
+ const NullWorkerResourceTimingNotifier&) = delete;
~NullWorkerResourceTimingNotifier() override = default;
void AddResourceTiming(
@@ -85,9 +91,6 @@ class CORE_EXPORT NullWorkerResourceTimingNotifier final
const AtomicString& initiator_type,
mojo::PendingReceiver<mojom::blink::WorkerTimingContainer>
worker_timing_receiver) override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NullWorkerResourceTimingNotifier);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_element.h
index 8d4fcf2ae26..6afe13aacc3 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_element.h
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_element.h
@@ -50,7 +50,7 @@ class CORE_EXPORT MathMLElement : public Element {
void ParseAttribute(const AttributeModificationParams&) override;
- // https://mathml-refresh.github.io/mathml-core/#dfn-boolean
+ // https://w3c.github.io/mathml-core/#dfn-boolean
absl::optional<bool> BooleanAttribute(const QualifiedName& name) const;
};
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
index 29147feba57..edbf833c31e 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h"
+#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -19,4 +21,20 @@ void MathMLFractionElement::AddMathFractionBarThicknessIfNeeded(
style.SetMathFractionBarThickness(std::move(*length_or_percentage_value));
}
+void MathMLFractionElement::ParseAttribute(
+ const AttributeModificationParams& param) {
+ if (GetLayoutObject() && GetLayoutObject()->IsMathML() &&
+ param.name == mathml_names::kLinethicknessAttr &&
+ param.new_value != param.old_value) {
+ // TODO(crbug.com/1121113): Isn't it enough to set needs style recalc and
+ // let the style system perform proper layout and paint invalidation?
+ SetNeedsStyleRecalc(
+ kLocalStyleChange,
+ StyleChangeReasonForTracing::Create(style_change_reason::kAttribute));
+ GetLayoutObject()->SetNeedsLayoutAndFullPaintInvalidation(
+ layout_invalidation_reason::kAttributeChanged);
+ }
+ MathMLElement::ParseAttribute(param);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h
index 65b250cad05..cf4ae232e50 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h
@@ -18,6 +18,9 @@ class MathMLFractionElement final : public MathMLElement {
void AddMathFractionBarThicknessIfNeeded(ComputedStyle&,
const CSSToLengthConversionData&);
+
+ private:
+ void ParseAttribute(const AttributeModificationParams&) final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.cc
index 62f3fa0723f..bc3d8c8cbf3 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.cc
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/core/mathml/mathml_operator_element.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/dom/character_data.h"
+#include "third_party/blink/renderer/core/dom/element_traversal.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/text/mathml_operator_dictionary.h"
@@ -29,12 +31,12 @@ UChar32 OperatorCodepoint(const String& text_content) {
return kNonCharacter;
UChar32 character;
- size_t offset = 0;
+ unsigned offset = 0;
U16_NEXT(text_content, offset, content_length, character);
return character;
}
-// https://mathml-refresh.github.io/mathml-core/#operator-dictionary-categories-values
+// https://w3c.github.io/mathml-core/#operator-dictionary-categories-values
// Leading and trailing spaces are respresented in math units, i.e. 1/18em.
struct MathMLOperatorDictionaryProperties {
unsigned leading_space_in_math_unit : 3;
@@ -91,14 +93,28 @@ MathMLOperatorElement::MathMLOperatorElement(Document& doc)
MathMLOperatorElement::OperatorContent
MathMLOperatorElement::ParseOperatorContent() {
MathMLOperatorElement::OperatorContent operator_content;
- if (HasOneTextChild()) {
- operator_content.characters = textContent();
- operator_content.characters.Ensure16Bit();
- operator_content.code_point =
- OperatorCodepoint(operator_content.characters);
- operator_content.is_vertical =
- Character::IsVerticalMathCharacter(operator_content.code_point);
+ // Build the text content of the <mo> element. If it contains something other
+ // than character data, exit early since no special handling is required.
+ StringBuilder text_content;
+ for (auto* child = firstChild(); child; child = child->nextSibling()) {
+ auto* character_data = DynamicTo<CharacterData>(child);
+ if (!character_data)
+ return operator_content;
+ if (child->getNodeType() == kTextNode) {
+ text_content.Append(character_data->data());
+ // TODO(crbug.com/6606): Is it worth checking the length of text_content
+ // and exiting early here? For example the MathML Operator dictionary only
+ // contains content which (as a UTF-16 string) is of length 1 or 2, and
+ // other things rely on the assumption that OperatorContent::code_point
+ // is not kNonCharacter.
+ }
}
+ // Parse the operator content.
+ operator_content.characters = text_content.ToString();
+ operator_content.characters.Ensure16Bit();
+ operator_content.code_point = OperatorCodepoint(operator_content.characters);
+ operator_content.is_vertical =
+ Character::IsVerticalMathCharacter(operator_content.code_point);
return operator_content;
}
@@ -142,9 +158,13 @@ void MathMLOperatorElement::ParseAttribute(
SetOperatorPropertyDirtyFlagIfNeeded(
param, MathMLOperatorElement::kMovableLimits, needs_layout);
} else if (param.name == mathml_names::kLspaceAttr ||
- param.name == mathml_names::kRspaceAttr) {
+ param.name == mathml_names::kRspaceAttr ||
+ param.name == mathml_names::kMinsizeAttr ||
+ param.name == mathml_names::kMaxsizeAttr) {
needs_layout = param.new_value != param.old_value;
if (needs_layout && GetLayoutObject()) {
+ // TODO(crbug.com/1121113): Isn't it enough to set needs style recalc and
+ // let the style system perform proper layout and paint invalidation?
SetNeedsStyleRecalc(
kLocalStyleChange,
StyleChangeReasonForTracing::Create(style_change_reason::kAttribute));
@@ -158,7 +178,7 @@ void MathMLOperatorElement::ParseAttribute(
MathMLElement::ParseAttribute(param);
}
-// https://mathml-refresh.github.io/mathml-core/#dfn-algorithm-for-determining-the-properties-of-an-embellished-operator
+// https://w3c.github.io/mathml-core/#dfn-algorithm-for-determining-the-properties-of-an-embellished-operator
void MathMLOperatorElement::ComputeDictionaryCategory() {
if (properties_.dictionary_category !=
MathMLOperatorDictionaryCategory::kUndefined)
@@ -170,7 +190,7 @@ void MathMLOperatorElement::ComputeDictionaryCategory() {
// We first determine the form attribute and use the default spacing and
// properties.
- // https://mathml-refresh.github.io/mathml-core/#dfn-form
+ // https://w3c.github.io/mathml-core/#dfn-form
const auto& value = FastGetAttribute(mathml_names::kFormAttr);
bool explicit_form = true;
MathMLOperatorDictionaryForm form;
@@ -183,11 +203,13 @@ void MathMLOperatorElement::ComputeDictionaryCategory() {
} else {
// TODO(crbug.com/1121113): Implement the remaining rules for determining
// form.
- // https://mathml-refresh.github.io/mathml-core/#dfn-algorithm-for-determining-the-form-of-an-embellished-operator
+ // https://w3c.github.io/mathml-core/#dfn-algorithm-for-determining-the-form-of-an-embellished-operator
explicit_form = false;
- if (!previousSibling() && nextSibling())
+ bool nextSibling = ElementTraversal::NextSibling(*this);
+ bool prevSibling = ElementTraversal::PreviousSibling(*this);
+ if (!prevSibling && nextSibling)
form = MathMLOperatorDictionaryForm::kPrefix;
- else if (previousSibling() && !nextSibling())
+ else if (prevSibling && !nextSibling)
form = MathMLOperatorDictionaryForm::kPostfix;
else
form = MathMLOperatorDictionaryForm::kInfix;
@@ -195,7 +217,7 @@ void MathMLOperatorElement::ComputeDictionaryCategory() {
// We then try and find an entry in the operator dictionary to override the
// default values.
- // https://mathml-refresh.github.io/mathml-core/#dfn-algorithm-for-determining-the-properties-of-an-embellished-operator
+ // https://w3c.github.io/mathml-core/#dfn-algorithm-for-determining-the-properties-of-an-embellished-operator
auto category = FindCategory(GetOperatorContent().characters, form);
if (category != MathMLOperatorDictionaryCategory::kNone) {
// Step 2.
@@ -226,7 +248,7 @@ void MathMLOperatorElement::ComputeOperatorProperty(OperatorPropertyFlag flag) {
DCHECK(properties_.dirty_flags & flag);
const auto& name = OperatorPropertyFlagToAttributeName(flag);
if (absl::optional<bool> value = BooleanAttribute(name)) {
- // https://mathml-refresh.github.io/mathml-core/#dfn-algorithm-for-determining-the-properties-of-an-embellished-operator
+ // https://w3c.github.io/mathml-core/#dfn-algorithm-for-determining-the-properties-of-an-embellished-operator
// Step 1.
if (*value) {
properties_.flags |= flag;
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.h
index 21a9e1db18e..535ced231e6 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.h
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_operator_element.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_OPERATOR_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_OPERATOR_ELEMENT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/mathml/mathml_element.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_padded_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_padded_element.cc
index 6f54654d635..d647e10a3e8 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_padded_element.cc
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_padded_element.cc
@@ -48,6 +48,8 @@ void MathMLPaddedElement::ParseAttribute(
const AttributeModificationParams& param) {
if (param.name == mathml_names::kLspaceAttr ||
param.name == mathml_names::kVoffsetAttr) {
+ // TODO(crbug.com/1121113): Isn't it enough to set needs style recalc and
+ // let the style system perform proper layout and paint invalidation?
SetNeedsStyleRecalc(
kLocalStyleChange,
StyleChangeReasonForTracing::Create(style_change_reason::kAttribute));
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 b/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
index 829fc38912a..0cda392e442 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
@@ -104,6 +104,10 @@
interfaceName: "MathMLRowElement",
},
{
+ name: "mtable",
+ interfaceName: "MathMLElement",
+ },
+ {
name: "mtext",
interfaceName: "MathMLElement",
},
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h
index 48570c023ca..0d379162db2 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.h b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.h
index 8c23cde13e4..499c1565f79 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.h
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MESSAGING_BLINK_CLONEABLE_MESSAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_MESSAGING_BLINK_CLONEABLE_MESSAGE_H_
-#include "base/macros.h"
#include "base/unguessable_token.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/weborigin/security_origin.h"
@@ -20,18 +20,14 @@ namespace blink {
// struct uses blink types, while the other struct uses std:: types.
struct CORE_EXPORT BlinkCloneableMessage {
BlinkCloneableMessage();
- ~BlinkCloneableMessage();
-
BlinkCloneableMessage(BlinkCloneableMessage&&);
BlinkCloneableMessage& operator=(BlinkCloneableMessage&&);
+ ~BlinkCloneableMessage();
scoped_refptr<blink::SerializedScriptValue> message;
scoped_refptr<const blink::SecurityOrigin> sender_origin;
v8_inspector::V8StackTraceId sender_stack_trace_id;
absl::optional<base::UnguessableToken> locked_agent_cluster_id;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BlinkCloneableMessage);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
index 17db6e16e25..19850144957 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
#include "mojo/public/cpp/bindings/string_traits_wtf.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink.h"
#include "third_party/blink/public/mojom/messaging/cloneable_message.mojom-shared.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
index a0d7076436d..bfbf96185be 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -9,8 +9,6 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
-#include "third_party/blink/public/web/web_dom_message_event.h"
-#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -19,107 +17,6 @@
namespace blink {
// static
-BlinkTransferableMessage BlinkTransferableMessage::FromMessageEvent(
- MessageEvent* message_event,
- absl::optional<base::UnguessableToken> cluster_id) {
- BlinkTransferableMessage result;
- SerializedScriptValue* serialized_script_value =
- message_event->DataAsSerializedScriptValue();
-
- // Message data and cluster ID (optional).
- base::span<const uint8_t> message_wire_data =
- serialized_script_value->GetWireData();
- result.message = SerializedScriptValue::Create(
- reinterpret_cast<const char*>(message_wire_data.data()),
- message_wire_data.size());
- result.locked_agent_cluster_id = cluster_id;
-
- // Ports
- Vector<MessagePortChannel> ports = message_event->ReleaseChannels();
- result.ports.AppendRange(ports.begin(), ports.end());
-
- // User activation
- UserActivation* user_activation = message_event->userActivation();
- if (user_activation) {
- result.user_activation = mojom::blink::UserActivationSnapshot::New(
- user_activation->hasBeenActive(), user_activation->isActive());
- }
-
- // Capability delegation
- result.delegate_payment_request = message_event->delegatePaymentRequest();
-
- // Blobs.
- for (const auto& blob : serialized_script_value->BlobDataHandles()) {
- result.message->BlobDataHandles().Set(
- blob.value->Uuid(),
- BlobDataHandle::Create(blob.value->Uuid(), blob.value->GetType(),
- blob.value->size(),
- blob.value->CloneBlobRemote()));
- }
-
- // Stream channels.
- for (auto& stream : serialized_script_value->GetStreams()) {
- result.message->GetStreams().push_back(std::move(stream));
- }
- // Array buffer contents array.
- auto& source_array_buffer_contents_array =
- serialized_script_value->GetArrayBufferContentsArray();
- if (!source_array_buffer_contents_array.IsEmpty()) {
- SerializedScriptValue::ArrayBufferContentsArray array_buffer_contents_array;
- array_buffer_contents_array.ReserveInitialCapacity(
- base::checked_cast<wtf_size_t>(
- source_array_buffer_contents_array.size()));
-
- for (auto& source_contents : source_array_buffer_contents_array) {
- uint8_t* allocation_start = static_cast<uint8_t*>(source_contents.Data());
- mojo_base::BigBuffer buffer(
- base::make_span(allocation_start, source_contents.DataLength()));
- ArrayBufferContents contents(buffer.size(), 1,
- ArrayBufferContents::kNotShared,
- ArrayBufferContents::kDontInitialize);
- // Check if we allocated the backing store of the ArrayBufferContents
- // correctly.
- CHECK_EQ(contents.DataLength(), buffer.size());
- memcpy(contents.Data(), buffer.data(), buffer.size());
- array_buffer_contents_array.push_back(std::move(contents));
- }
- result.message->SetArrayBufferContentsArray(
- std::move(array_buffer_contents_array));
- }
-
- // Image bitmap contents array.
- auto& source_image_bitmap_contents_array =
- serialized_script_value->GetImageBitmapContentsArray();
- if (!source_image_bitmap_contents_array.IsEmpty()) {
- SerializedScriptValue::ImageBitmapContentsArray image_bitmap_contents_array;
- image_bitmap_contents_array.ReserveInitialCapacity(
- base::checked_cast<wtf_size_t>(
- source_image_bitmap_contents_array.size()));
-
- for (auto& contents : image_bitmap_contents_array) {
- absl::optional<SkBitmap> sk_bitmap = ToSkBitmap(contents);
- if (!sk_bitmap)
- continue;
-
- const scoped_refptr<StaticBitmapImage> bitmap_contents =
- ToStaticBitmapImage(sk_bitmap.value());
- if (!bitmap_contents)
- continue;
- image_bitmap_contents_array.push_back(bitmap_contents);
- }
- result.message->SetImageBitmapContentsArray(
- std::move(image_bitmap_contents_array));
- }
-
- // File System Access transfer tokens.
- for (auto& token : serialized_script_value->FileSystemAccessTokens()) {
- result.message->FileSystemAccessTokens().push_back(std::move(token));
- }
-
- return result;
-}
-
-// static
BlinkTransferableMessage BlinkTransferableMessage::FromTransferableMessage(
TransferableMessage message) {
BlinkTransferableMessage result;
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.h b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.h
index 0fc940e2ab1..c1140c07a32 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.h
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MESSAGING_BLINK_TRANSFERABLE_MESSAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_MESSAGING_BLINK_TRANSFERABLE_MESSAGE_H_
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/messaging/transferable_message.h"
#include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom-blink.h"
@@ -17,32 +17,23 @@
namespace blink {
-class MessageEvent;
-
// This struct represents messages as they are posted over a message port. This
// type can be serialized as a blink::mojom::TransferableMessage struct.
// This is the renderer-side equivalent of blink::TransferableMessage, where
// this struct uses blink types, while the other struct uses std:: types.
struct CORE_EXPORT BlinkTransferableMessage : BlinkCloneableMessage {
- static BlinkTransferableMessage FromMessageEvent(
- MessageEvent*,
- absl::optional<base::UnguessableToken> cluster_id = absl::nullopt);
static BlinkTransferableMessage FromTransferableMessage(TransferableMessage);
BlinkTransferableMessage();
- ~BlinkTransferableMessage();
-
BlinkTransferableMessage(BlinkTransferableMessage&&);
BlinkTransferableMessage& operator=(BlinkTransferableMessage&&);
+ ~BlinkTransferableMessage();
Vector<MessagePortChannel> ports;
mojom::blink::UserActivationSnapshotPtr user_activation;
bool delegate_payment_request = false;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BlinkTransferableMessage);
};
CORE_EXPORT scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage(
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc
index 027689ecdd5..bc471d5a7d1 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc
@@ -4,15 +4,14 @@
#include "third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
@@ -55,7 +54,8 @@ TEST(BlinkTransferableMessageStructTraitsTest,
original_data[i] = static_cast<uint8_t>(i);
DOMArrayBuffer* array_buffer =
- V8ArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(v8_buffer));
+ NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ isolate, v8_buffer, scope.GetExceptionState());
Transferables transferables;
transferables.array_buffers.push_back(array_buffer);
BlinkTransferableMessage msg;
@@ -95,7 +95,8 @@ TEST(BlinkTransferableMessageStructTraitsTest,
contents[i] = static_cast<uint8_t>(i);
DOMArrayBuffer* original_array_buffer =
- V8ArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(v8_buffer));
+ NativeValueTraits<DOMArrayBuffer>::NativeValue(isolate, v8_buffer,
+ scope.GetExceptionState());
Transferables transferables;
transferables.array_buffers.push_back(original_array_buffer);
BlinkTransferableMessage msg;
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 bacf27d5792..c5714d11521 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.cc
@@ -28,8 +28,10 @@
#include <memory>
+#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+#include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink.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/serialization/post_message_helper.h"
@@ -145,7 +147,7 @@ void MessagePort::start() {
return;
started_ = true;
- connector_->ResumeIncomingMethodCallProcessing();
+ connector_->StartReceiving(task_runner_);
}
void MessagePort::close() {
@@ -168,8 +170,7 @@ void MessagePort::Entangle(MessagePortDescriptor port) {
port_ = std::move(port);
connector_ = std::make_unique<mojo::Connector>(
port_.TakeHandleToEntangle(GetExecutionContext()),
- mojo::Connector::SINGLE_THREADED_SEND, task_runner_);
- connector_->PauseIncomingMethodCallProcessing();
+ mojo::Connector::SINGLE_THREADED_SEND);
connector_->set_incoming_receiver(this);
connector_->set_connection_error_handler(
WTF::Bind(&MessagePort::close, WrapWeakPersistent(this)));
diff --git a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
index 654036bbcc4..104268abcf8 100644
--- a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
+++ b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
@@ -5,12 +5,15 @@
#include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
#include "third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom-blink.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/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/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html/html_anchor_element.h"
+#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -18,15 +21,19 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "ui/display/screen_info.h"
namespace blink {
using mojom::blink::ViewportStatus;
static constexpr int kSmallFontThreshold = 9;
-const base::Feature kBadTapTargetsRatio{"BadTapTargetsRatio",
- base::FEATURE_DISABLED_BY_DEFAULT};
static constexpr int kTimeBudgetExceeded = -2;
+// Values of maximum-scale smaller than this threshold will be considered to
+// prevent the user from scaling the page as if user-scalable=no was set.
+static constexpr double kMaximumScalePreventsZoomingThreshold = 1.2;
+
// Finding bad tap targets may takes too time for big page and should abort if
// it takes more than 5ms.
static constexpr base::TimeDelta kTimeBudgetForBadTapTarget =
@@ -36,7 +43,6 @@ MobileFriendlinessChecker::MobileFriendlinessChecker(LocalFrameView& frame_view)
: frame_view_(&frame_view),
font_size_check_enabled_(frame_view_->GetFrame().GetWidgetForLocalRoot()),
tap_target_check_enabled_(
- base::FeatureList::IsEnabled(kBadTapTargetsRatio) &&
frame_view_->GetFrame().GetWidgetForLocalRoot()),
viewport_scalar_(
font_size_check_enabled_
@@ -63,10 +69,10 @@ bool IsTimeBudgetExpired(const base::Time& from) {
// targets which are too close.
class FenwickTree {
public:
- explicit FenwickTree(size_t n) : tree(n + 1) {}
+ explicit FenwickTree(wtf_size_t n) : tree(n + 1) {}
// Returns prefix sum of the array from 0 to |index|.
- int sum(size_t index) const {
+ int sum(wtf_size_t index) const {
int sum = 0;
for (index += 1; 0 < index; index -= index & -index)
sum += tree[index];
@@ -74,7 +80,7 @@ class FenwickTree {
}
// Adds |val| at |index| of the array.
- void add(size_t index, int val) {
+ void add(wtf_size_t index, int val) {
for (index += 1; index <= tree.size() - 1; index += index & -index)
tree[index] += val;
}
@@ -92,37 +98,42 @@ class FenwickTree {
struct EdgeOrCenter {
enum Type : int { kStartEdge = 0, kCenter = 1, kEndEdge = 2 } type;
+ union PositionOrIndexUnion {
+ int position;
+ wtf_size_t index;
+ };
+
union EdgeOrCenterUnion {
// Valid iff |type| is Edge.
struct Edge {
- int left;
- int right;
+ PositionOrIndexUnion left;
+ PositionOrIndexUnion right;
} edge;
// Valid iff |type| is Center.
- int center;
+ PositionOrIndexUnion center;
} v;
static EdgeOrCenter StartEdge(int left, int right) {
EdgeOrCenter edge;
edge.type = EdgeOrCenter::kStartEdge;
- edge.v.edge.left = left;
- edge.v.edge.right = right;
+ edge.v.edge.left.position = left;
+ edge.v.edge.right.position = right;
return edge;
}
static EdgeOrCenter EndEdge(int left, int right) {
EdgeOrCenter edge;
edge.type = EdgeOrCenter::kEndEdge;
- edge.v.edge.left = left;
- edge.v.edge.right = right;
+ edge.v.edge.left.position = left;
+ edge.v.edge.right.position = right;
return edge;
}
static EdgeOrCenter Center(int center) {
EdgeOrCenter edge;
edge.type = EdgeOrCenter::kCenter;
- edge.v.center = center;
+ edge.v.center.position = center;
return edge;
}
};
@@ -143,6 +154,8 @@ bool IsTapTargetCandidate(const Node* node) {
int ExtractAndCountAllTapTargets(
LayoutObject* const root,
int finger_radius,
+ int scroll_offset,
+ int max_height,
Vector<int>& x_positions,
const base::Time& started,
Vector<std::pair<int, EdgeOrCenter>>& vertices) {
@@ -171,13 +184,17 @@ int ExtractAndCountAllTapTargets(
object = object->NextInPreOrder();
continue;
}
- const int top = rect.Y() - finger_radius;
- const int bottom = rect.MaxY() + finger_radius;
- const int left = rect.X() - finger_radius;
- const int right = rect.MaxX() + finger_radius;
- const int center = (left + right) / 2;
+ const int top = clampTo<int>(rect.Y() - finger_radius + scroll_offset);
+ const int bottom =
+ clampTo<int>(rect.MaxY() + finger_radius + scroll_offset);
+ const int left = clampTo<int>(rect.X() - finger_radius);
+ const int right = clampTo<int>(rect.MaxX() + finger_radius);
+ const int center = right / 2 + left / 2;
+ if (top > max_height) {
+ break;
+ }
vertices.emplace_back(top, EdgeOrCenter::StartEdge(left, right));
- vertices.emplace_back((top + bottom) / 2, EdgeOrCenter::Center(center));
+ vertices.emplace_back(bottom / 2 + top / 2, EdgeOrCenter::Center(center));
vertices.emplace_back(bottom, EdgeOrCenter::EndEdge(left, right));
x_positions.push_back(left);
x_positions.push_back(right);
@@ -202,21 +219,21 @@ void CompressKeyWithVector(const Vector<int>& positions,
switch (vertex.type) {
case EdgeOrCenter::kStartEdge:
case EdgeOrCenter::kEndEdge: {
- vertex.v.edge.left =
+ vertex.v.edge.left.index = static_cast<wtf_size_t>(
std::distance(positions.begin(),
std::lower_bound(positions.begin(), positions.end(),
- vertex.v.edge.left));
- vertex.v.edge.right =
+ vertex.v.edge.left.position)));
+ vertex.v.edge.right.index = static_cast<wtf_size_t>(
std::distance(positions.begin(),
std::lower_bound(positions.begin(), positions.end(),
- vertex.v.edge.right));
+ vertex.v.edge.right.position)));
break;
}
case EdgeOrCenter::kCenter: {
- vertex.v.center =
+ vertex.v.center.index = static_cast<wtf_size_t>(
std::distance(positions.begin(),
std::lower_bound(positions.begin(), positions.end(),
- vertex.v.center));
+ vertex.v.center.position)));
break;
}
}
@@ -229,7 +246,7 @@ void CompressKeyWithVector(const Vector<int>& positions,
// rightmost_position: Rightmost x position in all vertices.
// Returns bad tap targets count.
// Returns -1 if time limit exceeded.
-int CountBadTapTargets(int rightmost_position,
+int CountBadTapTargets(wtf_size_t rightmost_position,
const Vector<std::pair<int, EdgeOrCenter>>& vertices,
const base::Time& started) {
FenwickTree tree(rightmost_position);
@@ -239,20 +256,20 @@ int CountBadTapTargets(int rightmost_position,
switch (vertex.type) {
case EdgeOrCenter::kStartEdge: {
// Tap region begins.
- tree.add(vertex.v.edge.left, 1);
- tree.add(vertex.v.edge.right, -1);
+ tree.add(vertex.v.edge.left.index, 1);
+ tree.add(vertex.v.edge.right.index, -1);
break;
}
case EdgeOrCenter::kEndEdge: {
// Tap region ends.
- tree.add(vertex.v.edge.left, -1);
- tree.add(vertex.v.edge.right, 1);
+ tree.add(vertex.v.edge.left.index, -1);
+ tree.add(vertex.v.edge.right.index, 1);
break;
}
case EdgeOrCenter::kCenter: {
// Iff the center of a tap target is included other than itself, it is a
// Bad Target.
- if (tree.sum(vertex.v.center) > 1)
+ if (tree.sum(vertex.v.center.index) > 1)
bad_tap_targets++;
break;
}
@@ -279,11 +296,18 @@ void MobileFriendlinessChecker::ComputeBadTapTargetsRatio() {
Vector<std::pair<int, EdgeOrCenter>> vertices;
Vector<int> x_positions;
+ // This is like DOMWindow::scrollY() but without layout update.
+ const int scroll_y = AdjustForAbsoluteZoom::AdjustScroll(
+ frame_view_->LayoutViewport()->GetScrollOffset().Height(),
+ frame_view_->GetFrame().PageZoomFactor());
+ const int screen_height =
+ frame_view_->LayoutViewport()->GetLayoutBox()->Size().Height().ToInt();
+
// Scan full DOM tree and extract every corner and center position of tap
// targets.
- int all_tap_targets = ExtractAndCountAllTapTargets(
+ const int all_tap_targets = ExtractAndCountAllTapTargets(
frame_view_->GetFrame().GetDocument()->GetLayoutView(), finger_radius,
- x_positions, started, vertices);
+ scroll_y, screen_height, x_positions, started, vertices);
if (all_tap_targets == -1) {
mobile_friendliness_.bad_tap_targets_ratio = kTimeBudgetExceeded;
return;
@@ -316,15 +340,16 @@ void MobileFriendlinessChecker::ComputeBadTapTargetsRatio() {
if (all_tap_targets > 0) {
mobile_friendliness_.bad_tap_targets_ratio =
- bad_tap_targets * 100 / all_tap_targets;
+ bad_tap_targets * 100.0 / all_tap_targets;
} else {
mobile_friendliness_.bad_tap_targets_ratio = 0;
}
}
-void MobileFriendlinessChecker::NotifyDocumentUnload() {
+void MobileFriendlinessChecker::EvaluateNow() {
// If detached, there's no need to calculate any metrics.
- if (!frame_view_->GetChromeClient())
+ // Or if this is before FCP, there's nothing to evaluate.
+ if (!frame_view_->GetChromeClient() || !fcp_detected_)
return;
if (tap_target_check_enabled_)
@@ -333,19 +358,16 @@ void MobileFriendlinessChecker::NotifyDocumentUnload() {
if (font_size_check_enabled_)
mobile_friendliness_.small_text_ratio = text_area_sizes_.SmallTextRatio();
- // As long as evaluated as MF, TextOutsideViewportPercentage UKM must not be
- // -1 (means unknown). Even if there is no call of
- // ComputeTextContentOutsideViewport(), as far as there are FCP notification
- // and unload event, that value is not -1 anymore and to be 0.
- mobile_friendliness_.text_content_outside_viewport_percentage = std::max(
- 0, mobile_friendliness_.text_content_outside_viewport_percentage);
+ mobile_friendliness_.text_content_outside_viewport_percentage =
+ ComputeContentOutsideViewport();
- if (fcp_detected_)
- frame_view_->DidChangeMobileFriendliness(mobile_friendliness_);
+ frame_view_->DidChangeMobileFriendliness(mobile_friendliness_);
}
void MobileFriendlinessChecker::NotifyViewportUpdated(
const ViewportDescription& viewport) {
+ const double zoom = viewport.zoom_is_explicit ? viewport.zoom : 1.0;
+
switch (viewport.type) {
case ViewportDescription::Type::kUserAgentStyleSheet:
if (mobile_friendliness_.viewport_device_width ==
@@ -362,6 +384,9 @@ void MobileFriendlinessChecker::NotifyViewportUpdated(
if (viewport.max_width.IsFixed()) {
mobile_friendliness_.viewport_hardcoded_width =
viewport.max_width.GetFloatValue();
+ // Convert value from Blink space to device-independent pixels.
+ if (viewport_scalar_ != 0)
+ mobile_friendliness_.viewport_hardcoded_width /= viewport_scalar_;
}
if (viewport.zoom_is_explicit) {
mobile_friendliness_.viewport_initial_scale_x10 =
@@ -371,6 +396,10 @@ void MobileFriendlinessChecker::NotifyViewportUpdated(
mobile_friendliness_.allow_user_zoom =
viewport.user_zoom ? ViewportStatus::kYes : ViewportStatus::kNo;
}
+ if (viewport.max_zoom_is_explicit &&
+ viewport.max_zoom / zoom < kMaximumScalePreventsZoomingThreshold) {
+ mobile_friendliness_.allow_user_zoom = ViewportStatus::kNo;
+ }
break;
default:
return;
@@ -385,8 +414,6 @@ int MobileFriendlinessChecker::TextAreaWithFontSize::SmallTextRatio() const {
void MobileFriendlinessChecker::NotifyInvalidatePaint(
const LayoutObject& object) {
- ComputeTextContentOutsideViewport(object);
-
if (font_size_check_enabled_)
ComputeSmallTextRatio(object);
}
@@ -394,12 +421,19 @@ void MobileFriendlinessChecker::NotifyInvalidatePaint(
void MobileFriendlinessChecker::ComputeSmallTextRatio(
const LayoutObject& object) {
if (const auto* text = DynamicTo<LayoutText>(object)) {
- const ComputedStyle* style = text->Style();
+ const auto& style = text->StyleRef();
+
+ // Ignore elements that users cannot see.
+ if (style.Visibility() != EVisibility::kVisible)
+ return;
- if (style->Visibility() != EVisibility::kVisible)
+ // Ignore elements intended only for screen readers.
+ if (style.HasOutOfFlowPosition() && style.ClipLeft().IsZero() &&
+ style.ClipRight().IsZero() && style.ClipTop().IsZero() &&
+ style.ClipBottom().IsZero())
return;
- double actual_font_size = style->FontSize();
+ double actual_font_size = style.FontSize();
double initial_scale = frame_view_->GetPage()
->GetPageScaleConstraintsSet()
.FinalConstraints()
@@ -416,66 +450,29 @@ void MobileFriendlinessChecker::ComputeSmallTextRatio(
}
}
-constexpr int kMaxAncestorCount = 5;
-bool CheckParentHasOverflowXHidden(const LayoutObject* obj) {
- int ancestor_count = kMaxAncestorCount;
- while (obj && ancestor_count > 0) {
- const ComputedStyle* style = obj->Style();
- if (style->OverflowX() == EOverflow::kHidden)
- return true;
- obj = obj->Parent();
- --ancestor_count;
- }
- return false;
-}
-
-void MobileFriendlinessChecker::ComputeTextContentOutsideViewport(
- const LayoutObject& object) {
- if (!frame_view_->GetFrame().IsMainFrame())
- return;
-
+int MobileFriendlinessChecker::ComputeContentOutsideViewport() {
int frame_width = frame_view_->GetPage()->GetVisualViewport().Size().Width();
if (frame_width == 0) {
- return;
+ return 0;
}
- int total_text_width;
- if (const auto* text = DynamicTo<LayoutText>(object)) {
- const ComputedStyle* style = text->Style();
- if (style->Visibility() != EVisibility::kVisible ||
- style->ContentVisibility() != EContentVisibility::kVisible ||
- style->Opacity() == 0.0 || CheckParentHasOverflowXHidden(&object))
- return;
- total_text_width = text->PhysicalRightOffset().ToInt();
- } else if (const auto* image = DynamicTo<LayoutImage>(object)) {
- const ComputedStyle* style = image->Style();
- if (style->Visibility() != EVisibility::kVisible ||
- style->ContentVisibility() != EContentVisibility::kVisible ||
- style->Opacity() == 0.0 || CheckParentHasOverflowXHidden(&object))
- return;
- total_text_width = image->FrameRect().MaxX().ToInt();
- } else {
- return;
+ const auto* root_frame_viewport = frame_view_->GetRootFrameViewport();
+ if (root_frame_viewport == nullptr) {
+ return 0;
}
double initial_scale = frame_view_->GetPage()
->GetPageScaleConstraintsSet()
.FinalConstraints()
.initial_scale;
- if (initial_scale > 0)
- total_text_width *= initial_scale;
-
- int text_content_outside_viewport_percentage = 0;
- if (total_text_width > frame_width) {
- // We use ceil function here because we want to treat 100.1% as 101 which
- // requires a scroll bar.
- text_content_outside_viewport_percentage =
- std::ceil((total_text_width - frame_width) * 100.0 / frame_width);
- }
-
- mobile_friendliness_.text_content_outside_viewport_percentage =
- std::max(mobile_friendliness_.text_content_outside_viewport_percentage,
- text_content_outside_viewport_percentage);
+ int content_width =
+ root_frame_viewport->LayoutViewport().ContentsSize().Width() *
+ initial_scale;
+ int max_scroll_offset = content_width - frame_width;
+
+ // We use ceil function here because we want to treat 100.1% as 101 which
+ // requires a scroll bar.
+ return std::ceil(max_scroll_offset * 100.0 / frame_width);
}
void MobileFriendlinessChecker::Trace(Visitor* visitor) const {
diff --git a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
index 64749eeb903..5b4e6ae43ba 100644
--- a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
+++ b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
@@ -12,11 +12,11 @@
#include "third_party/blink/renderer/platform/heap/visitor.h"
namespace blink {
+
class LocalFrameView;
class LayoutObject;
-struct ViewportDescription;
-CORE_EXPORT extern const base::Feature kBadTapTargetsRatio;
+struct ViewportDescription;
// Calculates the mobile usability of current page, especially friendliness on
// smart phone devices are checked. The calculated value will be sent as a part
@@ -33,7 +33,7 @@ class CORE_EXPORT MobileFriendlinessChecker
const blink::MobileFriendliness& GetMobileFriendliness() const {
return mobile_friendliness_;
}
- void NotifyDocumentUnload();
+ void EvaluateNow();
void Trace(Visitor* visitor) const;
struct TextAreaWithFontSize {
@@ -44,7 +44,7 @@ class CORE_EXPORT MobileFriendlinessChecker
private:
void ComputeSmallTextRatio(const LayoutObject& object);
- void ComputeTextContentOutsideViewport(const LayoutObject& object);
+ int ComputeContentOutsideViewport();
void ComputeBadTapTargetsRatio();
private:
diff --git a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
index 2214455d302..e819a1ead8b 100644
--- a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
+++ b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
@@ -3,18 +3,19 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
-#include "base/test/scoped_feature_list.h"
#include "third_party/blink/public/common/mobile_metrics/mobile_friendliness.h"
#include "third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom-shared.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/mobile_metrics/mobile_metrics_test_helpers.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"
namespace blink {
+using mobile_metrics_test_helpers::MobileFriendlinessTree;
using mojom::ViewportStatus;
static constexpr char kBaseUrl[] = "http://www.test.com/";
@@ -24,68 +25,69 @@ class MobileFriendlinessCheckerTest : public testing::Test {
url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
}
- void SetUp() override {
- scoped_feature_list_.InitWithFeatures({kBadTapTargetsRatio}, {});
- }
-
static void ConfigureAndroidSettings(WebSettings* settings) {
settings->SetViewportEnabled(true);
settings->SetViewportMetaEnabled(true);
}
- MobileFriendliness CalculateMetricsForHTMLString(const std::string& html) {
- mobile_metrics_test_helpers::TestWebFrameClient web_frame_client;
- {
- // This scope is required to make sure that ~WebViewHelper() is called
- // before the return value of this function is determined. Because
- // MobileFriendlinessChecker::NotifyDocumentDestroying is called in
- // destruction sequence of WebView.
- frame_test_helpers::WebViewHelper helper;
- helper.Initialize(&web_frame_client, nullptr, ConfigureAndroidSettings);
- helper.GetWebView()->EnableAutoResizeForTesting(gfx::Size(480, 800),
- gfx::Size(480, 800));
- frame_test_helpers::LoadHTMLString(
- helper.GetWebView()->MainFrameImpl(), html,
- url_test_helpers::ToKURL("about:blank"));
- LocalFrameView& frame_view =
- *helper.GetWebView()->MainFrameImpl()->GetFrameView();
- frame_view.UpdateLifecycleToPrePaintClean(DocumentUpdateReason::kTest);
- frame_view.GetMobileFriendlinessChecker()->NotifyFirstContentfulPaint();
- }
- return web_frame_client.GetMobileFriendliness();
+ MobileFriendlinessTree CalculateMetricsForHTMLString(
+ const std::string& html,
+ float device_scale = 1.0,
+ int scroll_y_offset = 0) {
+ frame_test_helpers::WebViewHelper helper;
+ helper.Initialize(nullptr, nullptr, ConfigureAndroidSettings);
+ helper.GetWebView()->MainFrameWidget()->SetDeviceScaleFactorForTesting(
+ device_scale);
+ helper.Resize(gfx::Size(480, 800));
+ frame_test_helpers::LoadHTMLString(helper.GetWebView()->MainFrameImpl(),
+ html,
+ url_test_helpers::ToKURL("about:blank"));
+ return MobileFriendlinessTree::GetMobileFriendlinessTree(
+ helper.GetWebView()->MainFrameImpl()->GetFrameView(), scroll_y_offset);
}
- MobileFriendliness CalculateMetricsForFile(const std::string& path) {
- mobile_metrics_test_helpers::TestWebFrameClient web_frame_client;
- {
- // This scope is required to make sure that ~WebViewHelper() is called
- // before the return value of this function is determined. Because
- // MobileFriendlinessChecker::NotifyDocumentDestroying is called in
- // destruction sequence of WebView.
- frame_test_helpers::WebViewHelper helper;
- helper.Initialize(&web_frame_client, nullptr, ConfigureAndroidSettings);
- helper.GetWebView()->EnableAutoResizeForTesting(gfx::Size(480, 800),
- gfx::Size(480, 800));
- url_test_helpers::RegisterMockedURLLoadFromBase(
- WebString::FromUTF8(kBaseUrl), blink::test::CoreTestDataPath(),
- WebString::FromUTF8(path));
- frame_test_helpers::LoadFrame(helper.GetWebView()->MainFrameImpl(),
- kBaseUrl + path);
- LocalFrameView& frame_view =
- *helper.GetWebView()->MainFrameImpl()->GetFrameView();
- frame_view.UpdateLifecycleToPrePaintClean(DocumentUpdateReason::kTest);
- frame_view.GetMobileFriendlinessChecker()->NotifyFirstContentfulPaint();
- }
- return web_frame_client.GetMobileFriendliness();
+ MobileFriendlinessTree CalculateMetricsForFile(const std::string& path,
+ float device_scale = 1.0,
+ int scroll_y_offset = 0) {
+ frame_test_helpers::WebViewHelper helper;
+ helper.Initialize(nullptr, nullptr, ConfigureAndroidSettings);
+ helper.GetWebView()->MainFrameWidget()->SetDeviceScaleFactorForTesting(
+ device_scale);
+ helper.Resize(gfx::Size(480, 800));
+ url_test_helpers::RegisterMockedURLLoadFromBase(
+ WebString::FromUTF8(kBaseUrl), blink::test::CoreTestDataPath(),
+ WebString::FromUTF8(path));
+ frame_test_helpers::LoadFrame(helper.GetWebView()->MainFrameImpl(),
+ kBaseUrl + path);
+ return MobileFriendlinessTree::GetMobileFriendlinessTree(
+ helper.GetWebView()->MainFrameImpl()->GetFrameView(), scroll_y_offset);
+ }
+
+ MobileFriendliness CalculateMainFrameMetricsForHTMLString(
+ const std::string& html,
+ float device_scale = 1.0,
+ int scroll_y_offset = 0) {
+ return CalculateMetricsForHTMLString(html, device_scale, scroll_y_offset)
+ .mf;
+ }
+
+ MobileFriendliness CalculateMainFrameMetricsForFile(const std::string& path,
+ float device_scale = 1.0,
+ int scroll_y_offset = 0) {
+ return CalculateMetricsForFile(path, device_scale, scroll_y_offset).mf;
+ }
+
+ void SetUseZoomForDSF(bool use_zoom_for_dsf) {
+ platform_->SetUseZoomForDSF(use_zoom_for_dsf);
}
private:
- base::test::ScopedFeatureList scoped_feature_list_;
+ ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
};
TEST_F(MobileFriendlinessCheckerTest, NoViewportSetting) {
MobileFriendliness actual_mf =
- CalculateMetricsForHTMLString("<body>bar</body>");
+ CalculateMainFrameMetricsForHTMLString("<body>bar</body>");
EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.small_text_ratio, 100);
@@ -93,14 +95,24 @@ TEST_F(MobileFriendlinessCheckerTest, NoViewportSetting) {
TEST_F(MobileFriendlinessCheckerTest, DeviceWidth) {
MobileFriendliness actual_mf =
- CalculateMetricsForFile("viewport/viewport-1.html");
+ CalculateMainFrameMetricsForFile("viewport/viewport-1.html");
EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
}
TEST_F(MobileFriendlinessCheckerTest, HardcodedViewport) {
MobileFriendliness actual_mf =
- CalculateMetricsForFile("viewport/viewport-30.html");
+ CalculateMainFrameMetricsForFile("viewport/viewport-30.html");
+ EXPECT_EQ(actual_mf.viewport_device_width, blink::mojom::ViewportStatus::kNo);
+ EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+ EXPECT_EQ(actual_mf.viewport_hardcoded_width, 200);
+}
+
+TEST_F(MobileFriendlinessCheckerTest, HardcodedViewportWithDeviceScale3) {
+ SetUseZoomForDSF(true);
+ MobileFriendliness actual_mf =
+ CalculateMainFrameMetricsForFile("viewport/viewport-30.html",
+ /*device_scale=*/3.0);
EXPECT_EQ(actual_mf.viewport_device_width, blink::mojom::ViewportStatus::kNo);
EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.viewport_hardcoded_width, 200);
@@ -110,14 +122,42 @@ TEST_F(MobileFriendlinessCheckerTest, DeviceWidthWithInitialScale05) {
// Specifying initial-scale=0.5 is usually not the best choice for most web
// pages. But we cannot determine that such page must not be mobile friendly.
MobileFriendliness actual_mf =
- CalculateMetricsForFile("viewport/viewport-34.html");
+ CalculateMainFrameMetricsForFile("viewport/viewport-34.html");
EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.viewport_initial_scale_x10, 5);
}
+TEST_F(MobileFriendlinessCheckerTest, AllowUserScalableWithSmallMaxZoom) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+ <head>
+ <meta name="viewport" content="user-scalable=yes, maximum-scale=1.1">
+ </head>
+ )");
+ EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kNo);
+}
+
+TEST_F(MobileFriendlinessCheckerTest, AllowUserScalableWithLargeMaxZoom) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+ <head>
+ <meta name="viewport" content="user-scalable=yes, maximum-scale=2.0">
+ </head>
+ )");
+ EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+}
+
+TEST_F(MobileFriendlinessCheckerTest,
+ AllowUserScalableWithLargeMaxZoomAndLargeInitialScale) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+ <head>
+ <meta name="viewport" content="user-scalable=yes, maximum-scale=2.0, initial-scale=1.9">
+ </head>
+ )");
+ EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kNo);
+}
+
TEST_F(MobileFriendlinessCheckerTest, UserZoom) {
- MobileFriendliness actual_mf = CalculateMetricsForFile(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForFile(
"viewport-initial-scale-and-user-scalable-no.html");
EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.viewport_initial_scale_x10, 20);
@@ -127,7 +167,7 @@ TEST_F(MobileFriendlinessCheckerTest, UserZoom) {
TEST_F(MobileFriendlinessCheckerTest, NoText) {
MobileFriendliness actual_mf =
- CalculateMetricsForHTMLString(R"(<body></body>)");
+ CalculateMainFrameMetricsForHTMLString(R"(<body></body>)");
EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
EXPECT_EQ(actual_mf.small_text_ratio, 0);
@@ -135,7 +175,7 @@ TEST_F(MobileFriendlinessCheckerTest, NoText) {
}
TEST_F(MobileFriendlinessCheckerTest, NoSmallFonts) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<div style="font-size: 12px">
This is legible font size example.
</div>
@@ -146,7 +186,7 @@ TEST_F(MobileFriendlinessCheckerTest, NoSmallFonts) {
}
TEST_F(MobileFriendlinessCheckerTest, OnlySmallFonts) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<div style="font-size:7px">
Small font text.
</div>
@@ -157,7 +197,7 @@ TEST_F(MobileFriendlinessCheckerTest, OnlySmallFonts) {
}
TEST_F(MobileFriendlinessCheckerTest, MostlySmallFont) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<div style="font-size:12px">
legible text.
<div style="font-size:8px">
@@ -192,7 +232,7 @@ TEST_F(MobileFriendlinessCheckerTest, MostlySmallFont) {
}
TEST_F(MobileFriendlinessCheckerTest, MostlySmallInSpan) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<div style="font-size: 12px">
x
<span style="font-size:8px">
@@ -217,13 +257,14 @@ TEST_F(MobileFriendlinessCheckerTest, MultipleDivs) {
</div>
y
</div>
-)");
+)")
+ .mf;
EXPECT_LT(actual_mf.small_text_ratio, 100);
EXPECT_GT(actual_mf.small_text_ratio, 68);
}
TEST_F(MobileFriendlinessCheckerTest, DontCountInvisibleSmallFontArea) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body>
<div style="font-size: 12px">
@@ -241,7 +282,7 @@ TEST_F(MobileFriendlinessCheckerTest, DontCountInvisibleSmallFontArea) {
}
TEST_F(MobileFriendlinessCheckerTest, ScaleZoomedLegibleFont) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=10">
@@ -258,7 +299,7 @@ TEST_F(MobileFriendlinessCheckerTest, ScaleZoomedLegibleFont) {
}
TEST_F(MobileFriendlinessCheckerTest, ViewportZoomedOutIllegibleFont) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<head>
<meta name="viewport" content="width=480, initial-scale=0.5">
@@ -276,7 +317,7 @@ TEST_F(MobileFriendlinessCheckerTest, ViewportZoomedOutIllegibleFont) {
}
TEST_F(MobileFriendlinessCheckerTest, TooWideViewportWidthIllegibleFont) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<head>
<meta name="viewport" content="width=960">
@@ -293,7 +334,7 @@ TEST_F(MobileFriendlinessCheckerTest, TooWideViewportWidthIllegibleFont) {
}
TEST_F(MobileFriendlinessCheckerTest, CSSZoomedIllegibleFont) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body style="font-size: 12px; zoom:50%">
Illegible text in 6px.
@@ -305,8 +346,19 @@ TEST_F(MobileFriendlinessCheckerTest, CSSZoomedIllegibleFont) {
EXPECT_EQ(actual_mf.small_text_ratio, 100);
}
+TEST_F(MobileFriendlinessCheckerTest, OnlySmallFontsClipped) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+<html>
+ <body style="font-size: 6px; clip: rect(0 0 0 0); position: absolute">
+ Small font text.
+ </body>
+</html>
+)");
+ EXPECT_EQ(actual_mf.small_text_ratio, 0);
+}
+
TEST_F(MobileFriendlinessCheckerTest, TextNarrow) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body>
<pre>foo foo foo foo foo</pre>
@@ -317,37 +369,37 @@ TEST_F(MobileFriendlinessCheckerTest, TextNarrow) {
}
TEST_F(MobileFriendlinessCheckerTest, TextTooWide) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(
R"(
<html>
<body>
<pre>)" +
- std::string(10000, 'a') + R"(</pre>
+ std::string(10000, 'a') +
+ R"(</pre>
</body>
</html>
)");
EXPECT_NE(actual_mf.text_content_outside_viewport_percentage, 0);
}
-TEST_F(MobileFriendlinessCheckerTest, TextTooWideOpacityZero) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(
+TEST_F(MobileFriendlinessCheckerTest, TextTooWideAbsolutePositioning) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(
R"(
<html>
<body>
- <pre style="opacity:0">)" +
- std::string(10000, 'a') + R"(</pre>
+ <pre style="position:absolute; left:2000px">a</pre>
</body>
</html>
)");
- EXPECT_EQ(actual_mf.text_content_outside_viewport_percentage, 0);
+ EXPECT_EQ(actual_mf.text_content_outside_viewport_percentage, 317);
}
-TEST_F(MobileFriendlinessCheckerTest, TextTooWideVisibilityHidden) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(
+TEST_F(MobileFriendlinessCheckerTest, TextTooWideOverflowXHidden) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(
R"(
<html>
<body>
- <pre style="visibility:hidden">)" +
+ <pre style="overflow-x:hidden">)" +
std::string(10000, 'a') + R"(</pre>
</body>
</html>
@@ -356,12 +408,13 @@ TEST_F(MobileFriendlinessCheckerTest, TextTooWideVisibilityHidden) {
}
TEST_F(MobileFriendlinessCheckerTest, TextTooWideHidden) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(
R"(
<html>
<body>
<pre style="overflow:hidden">)" +
- std::string(10000, 'a') + R"(</pre>
+ std::string(10000, 'a') +
+ R"(</pre>
</body>
</html>
)");
@@ -369,13 +422,14 @@ TEST_F(MobileFriendlinessCheckerTest, TextTooWideHidden) {
}
TEST_F(MobileFriendlinessCheckerTest, TextTooWideHiddenInDiv) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(
R"(
<html>
<body>
<div style="overflow:hidden">
<pre>)" +
- std::string(10000, 'a') + R"(
+ std::string(10000, 'a') +
+ R"(
</pre>
</div>
</body>
@@ -385,14 +439,15 @@ TEST_F(MobileFriendlinessCheckerTest, TextTooWideHiddenInDiv) {
}
TEST_F(MobileFriendlinessCheckerTest, TextTooWideHiddenInDivDiv) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(
R"(
<html>
<body>
<div style="overflow:hidden">
<div>
<pre>)" +
- std::string(10000, 'a') + R"(
+ std::string(10000, 'a') +
+ R"(
</pre>
<div>
</div>
@@ -403,7 +458,7 @@ TEST_F(MobileFriendlinessCheckerTest, TextTooWideHiddenInDivDiv) {
}
TEST_F(MobileFriendlinessCheckerTest, ImageNarrow) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body>
<img style="width:200px; height:50px">
@@ -414,18 +469,30 @@ TEST_F(MobileFriendlinessCheckerTest, ImageNarrow) {
}
TEST_F(MobileFriendlinessCheckerTest, ImageTooWide) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body>
<img style="width:2000px; height:50px">
</body>
</html>
)");
- EXPECT_EQ(actual_mf.text_content_outside_viewport_percentage, 317);
+ EXPECT_EQ(actual_mf.text_content_outside_viewport_percentage, 319);
}
-TEST_F(MobileFriendlinessCheckerTest, ImageAbsolutePosition) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+TEST_F(MobileFriendlinessCheckerTest, ImageTooWideTwoImages) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+<html>
+ <body style="width:4000px">
+ <img style="width:2000px; height:50px">
+ <img style="width:2000px; height:50px">
+ </body>
+</html>
+)");
+ EXPECT_EQ(actual_mf.text_content_outside_viewport_percentage, 735);
+}
+
+TEST_F(MobileFriendlinessCheckerTest, ImageTooWideAbsolutePosition) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body>
<img style="width:100px; height:100px; position:absolute; left:2000px">
@@ -436,7 +503,7 @@ TEST_F(MobileFriendlinessCheckerTest, ImageAbsolutePosition) {
}
TEST_F(MobileFriendlinessCheckerTest, ImageTooWideDisplayNone) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<body>
<img style="width:2000px; height:50px; display:none">
@@ -447,7 +514,7 @@ TEST_F(MobileFriendlinessCheckerTest, ImageTooWideDisplayNone) {
}
TEST_F(MobileFriendlinessCheckerTest, ScaleTextOutsideViewport) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<html>
<head>
<meta name="viewport" content="width=480, minimum-scale=1, initial-scale=3">
@@ -470,8 +537,46 @@ TEST_F(MobileFriendlinessCheckerTest, ScaleTextOutsideViewport) {
EXPECT_GE(actual_mf.text_content_outside_viewport_percentage, 100.0);
}
+TEST_F(MobileFriendlinessCheckerTest, ScrollerOutsideViewport) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+<html>
+ <head>
+ <style>
+ div.scrollmenu {
+ background-color: #333;
+ overflow: auto;
+ white-space: nowrap;
+ }
+ div.scrollmenu a {
+ display: inline-block;
+ color: white;
+ padding: 14px;
+ }
+ </style>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0 minimum-scale=1.0">
+ </head>
+ <body style="font-size: 18px">
+ <div class="scrollmenu">
+ <a href="#1">First text</a>
+ <a href="#2">Second text</a>
+ <a href="#3">Third text</a>
+ <a href="#4">Fourth text</a>
+ <a href="#5">Fifth text</a>
+ <a href="#6">Sixth text</a>
+ <a href="#7">Seventh text</a>
+ <a href="#8">Eighth text</a>
+ <a href="#9">Ninth text</a>
+ <a href="#10">Tenth text</a>
+ </div>
+ </body>
+</html>
+)");
+ // the viewport
+ EXPECT_EQ(actual_mf.text_content_outside_viewport_percentage, 0.0);
+}
+
TEST_F(MobileFriendlinessCheckerTest, SingleTapTarget) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -485,7 +590,7 @@ TEST_F(MobileFriendlinessCheckerTest, SingleTapTarget) {
}
TEST_F(MobileFriendlinessCheckerTest, NoBadTapTarget) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -502,7 +607,7 @@ TEST_F(MobileFriendlinessCheckerTest, NoBadTapTarget) {
}
TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsVertical) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -523,7 +628,7 @@ TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsVertical) {
}
TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsVerticalSamePoint) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -549,7 +654,7 @@ TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsVerticalSamePoint) {
}
TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsHorizontal) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -570,7 +675,7 @@ TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsHorizontal) {
}
TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsHorizontalSamePoint) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -596,7 +701,7 @@ TEST_F(MobileFriendlinessCheckerTest, TooCloseTapTargetsHorizontalSamePoint) {
}
TEST_F(MobileFriendlinessCheckerTest, GridGoodTargets3X3) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -658,7 +763,7 @@ TEST_F(MobileFriendlinessCheckerTest, GridGoodTargets3X3) {
}
TEST_F(MobileFriendlinessCheckerTest, GridBadTargets3X3) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -720,7 +825,7 @@ TEST_F(MobileFriendlinessCheckerTest, GridBadTargets3X3) {
}
TEST_F(MobileFriendlinessCheckerTest, FormTapTargets) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -735,7 +840,7 @@ TEST_F(MobileFriendlinessCheckerTest, FormTapTargets) {
}
TEST_F(MobileFriendlinessCheckerTest, InvisibleTapTargetWillBeIgnored) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -752,7 +857,7 @@ TEST_F(MobileFriendlinessCheckerTest, InvisibleTapTargetWillBeIgnored) {
}
TEST_F(MobileFriendlinessCheckerTest, BadTapTargetWithPositionAbsolute) {
- MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
<head>
<meta name="viewport" content="width=480, initial-scale=1">
</head>
@@ -768,4 +873,101 @@ TEST_F(MobileFriendlinessCheckerTest, BadTapTargetWithPositionAbsolute) {
EXPECT_EQ(actual_mf.bad_tap_targets_ratio, 100);
}
+TEST_F(MobileFriendlinessCheckerTest, BadTapTargetBelowFirstOnePager) {
+ MobileFriendliness actual_mf = CalculateMainFrameMetricsForHTMLString(R"(
+ <head>
+ <meta name="viewport" content="width=480, initial-scale=1">
+ </head>
+ <body style="font-size: 18px">
+ <button style="position:absolute; width:50px; height:50px">
+ a
+ </button>
+ <button style="position:relative; width:50px; height:50px">
+ b
+ </button>
+ <!-- below area must be ignored -->
+ <div style="margin-top: 800px">
+ <a href="about:blank">
+ <div style="width: 50px;height: 50px; margin: 50px; display:inline-block">
+ have
+ </div>
+ </a>
+ <a href="about:blank">
+ <div style="width: 50px;height: 50px; margin: 50px; display:inline-block">
+ enough
+ </div>
+ </a>
+ <a href="about:blank">
+ <div style="width: 50px;height: 50px; margin: 50px; display:inline-block">
+ spans
+ </div>
+ </a>
+ </div>
+ </body>";
+ )");
+ EXPECT_EQ(actual_mf.bad_tap_targets_ratio, 100);
+}
+
+TEST_F(MobileFriendlinessCheckerTest,
+ BadTapTargetBelowFirstOnePagerWithScroll) {
+ auto eval_btt_with_scroll = [&](const int scroll_offset) {
+ return CalculateMainFrameMetricsForHTMLString(R"(
+ <head>
+ <meta name="viewport" content="width=480, initial-scale=1">
+ </head>
+ <body style="font-size: 18px">
+ <button style="position:absolute; width:50px; height:50px">
+ a
+ </button>
+ <button style="position:relative; width:50px; height:50px">
+ b
+ </button>
+ <!-- below area must be ignored -->
+ <div style="margin-top: 800px">
+ <a href="about:blank">
+ <div style="width: 50px;height: 50px; margin: 50px; display:inline-block">
+ have
+ </div>
+ </a>
+ <a href="about:blank">
+ <div style="width: 50px;height: 50px; margin: 50px; display:inline-block">
+ enough
+ </div>
+ </a>
+ <a href="about:blank">
+ <div style="width: 50px;height: 50px; margin: 50px; display:inline-block">
+ spans
+ </div>
+ </a>
+ </div>
+ </body>";
+ )",
+ 1.0 /*=device_scale*/,
+ scroll_offset)
+ .bad_tap_targets_ratio;
+ };
+
+ // BadTapTargetResult must not be affected by scrolling offset.
+ EXPECT_EQ(eval_btt_with_scroll(0), 100);
+ EXPECT_EQ(eval_btt_with_scroll(400), 100);
+ EXPECT_EQ(eval_btt_with_scroll(800), 100);
+ EXPECT_EQ(eval_btt_with_scroll(1200), 100);
+}
+
+TEST_F(MobileFriendlinessCheckerTest, IFrameTest) {
+ url_test_helpers::RegisterMockedURLLoadFromBase(
+ WebString::FromUTF8(kBaseUrl), blink::test::CoreTestDataPath(),
+ WebString::FromUTF8("visible_iframe.html"));
+ MobileFriendlinessTree actual_mf_tree =
+ CalculateMetricsForFile("single_iframe.html");
+ const MobileFriendliness& mainframe_mf = actual_mf_tree.mf;
+ EXPECT_EQ(mainframe_mf.viewport_device_width, mojom::ViewportStatus::kNo);
+ EXPECT_EQ(mainframe_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+ EXPECT_EQ(mainframe_mf.bad_tap_targets_ratio, 0);
+
+ EXPECT_EQ(actual_mf_tree.children.size(), 1u);
+ const MobileFriendliness& subframe_mf = actual_mf_tree.children[0].mf;
+ EXPECT_EQ(subframe_mf.bad_tap_targets_ratio, 0);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_metrics_test_helpers.h b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_metrics_test_helpers.h
index 1601f8bf878..e2caa6a84c0 100644
--- a/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_metrics_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/mobile_metrics/mobile_metrics_test_helpers.h
@@ -7,21 +7,41 @@
#include "third_party/blink/public/common/mobile_metrics/mobile_friendliness.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
namespace mobile_metrics_test_helpers {
-class TestWebFrameClient : public frame_test_helpers::TestWebFrameClient {
- public:
- void DidChangeMobileFriendliness(const MobileFriendliness& mf) override {
- mobile_friendliness_ = mf;
- }
- const MobileFriendliness& GetMobileFriendliness() const {
- return mobile_friendliness_;
- }
+// Collect MobileFriendliness metrics with tree structure which reflects
+// tree structure of subframe.
+struct MobileFriendlinessTree {
+ MobileFriendliness mf;
+ WTF::Vector<MobileFriendlinessTree> children;
+
+ static MobileFriendlinessTree GetMobileFriendlinessTree(LocalFrameView* view,
+ int scroll_y_offset) {
+ mobile_metrics_test_helpers::MobileFriendlinessTree result;
- private:
- MobileFriendliness mobile_friendliness_;
+ view->UpdateLifecycleToPrePaintClean(DocumentUpdateReason::kTest);
+ view->GetMobileFriendlinessChecker()->NotifyFirstContentfulPaint();
+
+ // Scroll the view to specified offset
+ view->LayoutViewport()->SetScrollOffsetUnconditionally(
+ ScrollOffset(0, scroll_y_offset));
+
+ // Do MobileFriendliness evaluation recursively.
+ view->GetMobileFriendlinessChecker()->EvaluateNow();
+ result.mf = view->GetMobileFriendlinessChecker()->GetMobileFriendliness();
+ for (Frame* child = view->GetFrame().FirstChild(); child;
+ child = child->NextSibling()) {
+ if (LocalFrame* local_frame = DynamicTo<LocalFrame>(child)) {
+ result.children.push_back(
+ GetMobileFriendlinessTree(local_frame->View(), scroll_y_offset));
+ }
+ }
+ return result;
+ }
};
} // namespace mobile_metrics_test_helpers
diff --git a/chromium/third_party/blink/renderer/core/mojo/mojo_handle.cc b/chromium/third_party/blink/renderer/core/mojo/mojo_handle.cc
index 1e57caf95d5..acb1b04ea8f 100644
--- a/chromium/third_party/blink/renderer/core/mojo/mojo_handle.cc
+++ b/chromium/third_party/blink/renderer/core/mojo/mojo_handle.cc
@@ -8,7 +8,6 @@
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/system/message_pipe.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mojo_create_shared_buffer_result.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mojo_discard_data_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mojo_duplicate_buffer_handle_options.h"
@@ -52,11 +51,7 @@ MojoWatcher* MojoHandle::watch(ScriptState* script_state,
}
MojoResult MojoHandle::writeMessage(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* buffer,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ArrayBufferOrArrayBufferView& buffer,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<MojoHandle>>& handles) {
Vector<mojo::ScopedHandle, kHandleVectorInlineCapacity> scoped_handles;
scoped_handles.ReserveCapacity(handles.size());
@@ -72,7 +67,6 @@ MojoResult MojoHandle::writeMessage(
const void* bytes = nullptr;
size_t num_bytes = 0;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (buffer->GetContentType()) {
case V8BufferSource::ContentType::kArrayBuffer: {
DOMArrayBuffer* array = buffer->GetAsArrayBuffer();
@@ -87,17 +81,6 @@ MojoResult MojoHandle::writeMessage(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (buffer.IsArrayBuffer()) {
- DOMArrayBuffer* array = buffer.GetAsArrayBuffer();
- bytes = array->Data();
- num_bytes = array->ByteLength();
- } else {
- DOMArrayBufferView* view = buffer.GetAsArrayBufferView().Get();
- bytes = view->BaseAddress();
- num_bytes = view->byteLength();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto message = mojo::Message(
base::make_span(static_cast<const uint8_t*>(bytes), num_bytes),
@@ -163,11 +146,7 @@ MojoReadMessageResult* MojoHandle::readMessage(
}
MojoWriteDataResult* MojoHandle::writeData(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* buffer,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferView& buffer,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const MojoWriteDataOptions* options_dict) {
MojoWriteDataResult* result_dict = MojoWriteDataResult::Create();
@@ -177,7 +156,6 @@ MojoWriteDataResult* MojoHandle::writeData(
const void* elements = nullptr;
base::CheckedNumeric<uint32_t> checked_num_bytes;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (buffer->GetContentType()) {
case V8BufferSource::ContentType::kArrayBuffer: {
DOMArrayBuffer* array = buffer->GetAsArrayBuffer();
@@ -192,17 +170,6 @@ MojoWriteDataResult* MojoHandle::writeData(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (buffer.IsArrayBuffer()) {
- DOMArrayBuffer* array = buffer.GetAsArrayBuffer();
- elements = array->Data();
- checked_num_bytes = array->ByteLength();
- } else {
- DOMArrayBufferView* view = buffer.GetAsArrayBufferView().Get();
- elements = view->BaseAddress();
- checked_num_bytes = view->byteLength();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
::MojoWriteDataOptions options;
options.struct_size = sizeof(options);
@@ -249,11 +216,7 @@ MojoReadDataResult* MojoHandle::discardData(
}
MojoReadDataResult* MojoHandle::readData(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* buffer,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ArrayBufferOrArrayBufferView& buffer,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const MojoReadDataOptions* options_dict) const {
MojoReadDataResult* result_dict = MojoReadDataResult::Create();
MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_NONE;
@@ -264,7 +227,6 @@ MojoReadDataResult* MojoHandle::readData(
void* elements = nullptr;
base::CheckedNumeric<uint32_t> checked_num_bytes;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (buffer->GetContentType()) {
case V8BufferSource::ContentType::kArrayBuffer: {
DOMArrayBuffer* array = buffer->GetAsArrayBuffer();
@@ -279,17 +241,6 @@ MojoReadDataResult* MojoHandle::readData(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (buffer.IsArrayBuffer()) {
- DOMArrayBuffer* array = buffer.GetAsArrayBuffer();
- elements = array->Data();
- checked_num_bytes = array->ByteLength();
- } else {
- DOMArrayBufferView* view = buffer.GetAsArrayBufferView().Get();
- elements = view->BaseAddress();
- checked_num_bytes = view->byteLength();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
::MojoReadDataOptions options;
options.struct_size = sizeof(options);
diff --git a/chromium/third_party/blink/renderer/core/mojo/mojo_handle.h b/chromium/third_party/blink/renderer/core/mojo/mojo_handle.h
index 8dd063cc6db..696fe14c4dd 100644
--- a/chromium/third_party/blink/renderer/core/mojo/mojo_handle.h
+++ b/chromium/third_party/blink/renderer/core/mojo/mojo_handle.h
@@ -12,7 +12,6 @@
namespace blink {
-class ArrayBufferOrArrayBufferView;
class MojoCreateSharedBufferResult;
class MojoDiscardDataOptions;
class MojoDuplicateBufferHandleOptions;
@@ -42,33 +41,18 @@ class CORE_EXPORT MojoHandle final : public ScriptWrappable {
V8MojoWatchCallback*);
// MessagePipe handle.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MojoResult writeMessage(const V8BufferSource* buffer,
const HeapVector<Member<MojoHandle>>& handles);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- MojoResult writeMessage(ArrayBufferOrArrayBufferView&,
- const HeapVector<Member<MojoHandle>>&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MojoReadMessageResult* readMessage(const MojoReadMessageFlags*);
// DataPipe handle.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MojoWriteDataResult* writeData(const V8BufferSource* buffer,
const MojoWriteDataOptions* options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- MojoWriteDataResult* writeData(const ArrayBufferOrArrayBufferView&,
- const MojoWriteDataOptions*);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MojoReadDataResult* queryData() const;
MojoReadDataResult* discardData(unsigned num_bytes,
const MojoDiscardDataOptions*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MojoReadDataResult* readData(const V8BufferSource* buffer,
const MojoReadDataOptions* options) const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- MojoReadDataResult* readData(ArrayBufferOrArrayBufferView&,
- const MojoReadDataOptions*) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// SharedBuffer handle.
MojoMapBufferResult* mapBuffer(unsigned offset, unsigned num_bytes);
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 c2d6d1e6143..1c180dc1186 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/metrics/histogram_functions.h"
+#include "base/numerics/safe_conversions.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
@@ -24,9 +25,11 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_resource_tracker.h"
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "third_party/blink/renderer/core/html/canvas/ukm_parameters.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
@@ -41,7 +44,6 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
@@ -72,6 +74,7 @@ OffscreenCanvas::OffscreenCanvas(ExecutionContext* context, const IntSize& size)
}
}
+ CanvasResourceTracker::For(context->GetIsolate())->Add(this, context);
UpdateMemoryUsage();
}
@@ -170,13 +173,13 @@ void OffscreenCanvas::SetSize(const IntSize& size) {
if (frame_dispatcher_)
frame_dispatcher_->Reshape(size_);
if (context_) {
- if (context_->Is3d()) {
+ if (context_->IsWebGL()) {
context_->Reshape(size_.Width(), size_.Height());
} else if (context_->IsRenderingContext2D()) {
context_->Reset();
origin_clean_ = true;
}
- context_->DidDraw();
+ context_->DidDraw(CanvasPerformanceMonitor::DrawType::kOther);
}
}
@@ -237,7 +240,8 @@ void OffscreenCanvas::RecordIdentifiabilityMetric(
scoped_refptr<Image> OffscreenCanvas::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize& size) {
+ const FloatSize& size,
+ const AlphaDisposition alpha_disposition) {
if (!context_) {
*status = kInvalidSourceImageStatus;
sk_sp<SkSurface> surface =
@@ -250,11 +254,14 @@ scoped_refptr<Image> OffscreenCanvas::GetSourceImageForCanvas(
*status = kZeroSizeCanvasSourceImageStatus;
return nullptr;
}
- scoped_refptr<Image> image = context_->GetImage();
+ scoped_refptr<StaticBitmapImage> image = context_->GetImage();
if (!image)
image = CreateTransparentImage(Size());
+
*status = image ? kNormalSourceImageStatus : kInvalidSourceImageStatus;
- return image;
+
+ // If the alpha_disposition is already correct, this is a no-op.
+ return GetImageWithAlphaDisposition(std::move(image), alpha_disposition);
}
IntSize OffscreenCanvas::BitmapSourceSize() const {
@@ -295,6 +302,15 @@ CanvasRenderingContext* OffscreenCanvas::GetCanvasRenderingContext(
return nullptr;
}
+ // TODO(crbug.com/1229274): Remove 'gpupresent' type after deprecation period.
+ if (id == "gpupresent") {
+ auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "The context type 'gpupresent' is deprecated. Use 'webgpu' instead.");
+ execution_context->AddConsoleMessage(console_message);
+ }
+
if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
if (attributes.color_space != kSRGBCanvasColorSpaceName ||
attributes.pixel_format != kUint8CanvasPixelFormatName) {
@@ -328,6 +344,8 @@ CanvasRenderingContext* OffscreenCanvas::GetCanvasRenderingContext(
recomputed_attributes.power_preference = "low-power";
context_ = factory->Create(this, recomputed_attributes);
+ if (context_)
+ context_->RecordUKMCanvasRenderingAPI();
}
return context_.Get();
@@ -392,19 +410,22 @@ CanvasResourceProvider* OffscreenCanvas::GetOrCreateResourceProvider() {
IntSize surface_size(width(), height());
const bool can_use_gpu =
SharedGpuContext::IsGpuCompositingEnabled() &&
- (Is3d() || (RuntimeEnabledFeatures::Accelerated2dCanvasEnabled() &&
- !context_->CreationAttributes().will_read_frequently));
+ (IsWebGL() || IsWebGPU() ||
+ (RuntimeEnabledFeatures::Accelerated2dCanvasEnabled() &&
+ !context_->CreationAttributes().will_read_frequently));
const bool composited_mode =
- (Is3d() ? RuntimeEnabledFeatures::WebGLImageChromiumEnabled()
- : RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled());
+ IsWebGPU() ||
+ (IsWebGL() && RuntimeEnabledFeatures::WebGLImageChromiumEnabled()) ||
+ (IsRenderingContext2D() &&
+ RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled());
uint32_t shared_image_usage_flags = gpu::SHARED_IMAGE_USAGE_DISPLAY;
- if (composited_mode)
+ if (composited_mode && HasPlaceholderCanvas())
shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
const CanvasResourceParams resource_params =
context_->CanvasRenderingContextColorParams().GetAsResourceParams();
- const SkFilterQuality filter_quality = FilterQuality();
+ const cc::PaintFlags::FilterQuality filter_quality = FilterQuality();
if (can_use_gpu) {
provider = CanvasResourceProvider::CreateSharedImageProvider(
surface_size, filter_quality, resource_params,
@@ -461,12 +482,8 @@ CanvasResourceProvider* OffscreenCanvas::GetOrCreateResourceProvider() {
return ResourceProvider();
}
-void OffscreenCanvas::DidDraw() {
- DidDraw(FloatRect(0, 0, Size().Width(), Size().Height()));
-}
-
-void OffscreenCanvas::DidDraw(const FloatRect& rect) {
- if (rect.IsEmpty())
+void OffscreenCanvas::DidDraw(const SkIRect& rect) {
+ if (rect.isEmpty())
return;
if (HasPlaceholderCanvas()) {
@@ -483,7 +500,7 @@ bool OffscreenCanvas::BeginFrame() {
}
void OffscreenCanvas::SetFilterQualityInResource(
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
if (FilterQuality() == filter_quality)
return;
@@ -528,6 +545,11 @@ UkmParameters OffscreenCanvas::GetUkmParameters() {
return {context->UkmRecorder(), context->UkmSourceID()};
}
+void OffscreenCanvas::NotifyGpuContextLost() {
+ if (context_)
+ context_->LoseContext(CanvasRenderingContext::kRealLostContext);
+}
+
FontSelector* OffscreenCanvas::GetFontSelector() {
if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
return window->document()->GetStyleEngine().GetFontSelector();
@@ -549,6 +571,10 @@ void OffscreenCanvas::UpdateMemoryUsage() {
memory_usage_ = new_memory_usage;
}
+size_t OffscreenCanvas::GetMemoryUsage() const {
+ return base::saturated_cast<size_t>(memory_usage_);
+}
+
void OffscreenCanvas::Trace(Visitor* visitor) const {
visitor->Trace(context_);
visitor->Trace(execution_context_);
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 0df00333d23..2b0ba8d9b85 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
@@ -57,7 +57,8 @@ class CORE_EXPORT OffscreenCanvas final
// CanvasResourceDispatcherClient
bool BeginFrame() override;
- void SetFilterQualityInResource(SkFilterQuality filter_quality) override;
+ void SetFilterQualityInResource(
+ cc::PaintFlags::FilterQuality filter_quality) override;
// API Methods
ImageBitmap* transferToImageBitmap(ScriptState*, ExceptionState&);
@@ -113,8 +114,8 @@ class CORE_EXPORT OffscreenCanvas final
bool PushFrameIfNeeded();
bool PushFrame(scoped_refptr<CanvasResource> frame,
const SkIRect& damage_rect) override;
- void DidDraw(const FloatRect&) override;
- void DidDraw() override;
+ void DidDraw(const SkIRect&) override;
+ using CanvasRenderingContextHost::DidDraw;
void Commit(scoped_refptr<CanvasResource> bitmap_image,
const SkIRect& damage_rect) override;
bool ShouldAccelerate2dContext() const override;
@@ -122,10 +123,11 @@ class CORE_EXPORT OffscreenCanvas final
UkmParameters GetUkmParameters() override;
// Partial CanvasResourceHost implementation
- void NotifyGpuContextLost() override {}
+ void NotifyGpuContextLost() override;
void SetNeedsCompositingUpdate() override {}
// TODO(fserb): Merge this with HTMLCanvasElement::UpdateMemoryUsage
void UpdateMemoryUsage() override;
+ size_t GetMemoryUsage() const override;
// EventTarget implementation
const AtomicString& InterfaceName() const final {
@@ -151,8 +153,10 @@ class CORE_EXPORT OffscreenCanvas final
ExceptionState&) final;
// CanvasImageSource implementation
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) final;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) final;
bool WouldTaintOrigin() const final { return !origin_clean_; }
FloatSize ElementSize(const FloatSize& default_object_size,
const RespectImageOrientationEnum) const final {
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
index 44185845421..c86d374683c 100644
--- a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -342,10 +342,7 @@ void OriginTrialContext::InitializePendingFeatures() {
// ready for script in that case, so bail out.
if (!window || !window->document())
return;
- LocalFrame* frame = window->GetFrame();
- if (!frame)
- return;
- ScriptState* script_state = ToScriptStateForMainWorld(frame);
+ ScriptState* script_state = ToScriptStateForMainWorld(window->GetFrame());
if (!script_state)
return;
if (!script_state->ContextIsValid())
@@ -369,11 +366,7 @@ bool OriginTrialContext::InstallFeature(OriginTrialFeature enabled_feature,
ScriptState* script_state) {
if (installed_features_.Contains(enabled_feature))
return false;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
InstallPropertiesPerFeature(script_state, enabled_feature);
-#else
- InstallPendingOriginTrialFeature(enabled_feature, script_state);
-#endif
installed_features_.insert(enabled_feature);
return true;
}
@@ -424,42 +417,42 @@ void OriginTrialContext::AddForceEnabledTrials(
bool OriginTrialContext::CanEnableTrialFromName(const StringView& trial_name) {
if (trial_name == "HandwritingRecognition") {
return base::FeatureList::IsEnabled(
- features::kHandwritingRecognitionWebPlatformApi) &&
- base::FeatureList::IsEnabled(
features::kHandwritingRecognitionWebPlatformApiFinch);
}
- if (trial_name == "Portals" &&
- !base::FeatureList::IsEnabled(features::kPortals)) {
- return false;
- }
- if (trial_name == "FencedFrames" &&
- !base::FeatureList::IsEnabled(features::kFencedFrames)) {
- return false;
- }
- if (trial_name == "AppCache" &&
- !base::FeatureList::IsEnabled(features::kAppCache)) {
- return false;
- }
- if (trial_name == "ComputePressure" &&
- !base::FeatureList::IsEnabled(features::kComputePressure)) {
- return false;
- }
- if (trial_name == "FledgeInterestGroupAPI" &&
- !base::FeatureList::IsEnabled(features::kFledgeInterestGroups)) {
- return false;
- }
- if (trial_name == "TrustTokens" &&
- !base::FeatureList::IsEnabled(network::features::kTrustTokens)) {
- return false;
+ if (trial_name == "Portals")
+ return base::FeatureList::IsEnabled(features::kPortals);
+
+ if (trial_name == "FencedFrames")
+ return base::FeatureList::IsEnabled(features::kFencedFrames);
+
+ if (trial_name == "AppCache")
+ return base::FeatureList::IsEnabled(features::kAppCache);
+
+ if (trial_name == "ComputePressure")
+ return base::FeatureList::IsEnabled(features::kComputePressure);
+
+ if (trial_name == "FledgeInterestGroupAPI")
+ return base::FeatureList::IsEnabled(features::kFledgeInterestGroups);
+
+ if (trial_name == "TrustTokens")
+ return base::FeatureList::IsEnabled(network::features::kTrustTokens);
+
+ if (trial_name == "InterestCohortAPI") {
+ return base::FeatureList::IsEnabled(
+ features::kInterestCohortAPIOriginTrial);
}
- if (trial_name == "InterestCohortAPI" &&
- !base::FeatureList::IsEnabled(features::kInterestCohortAPIOriginTrial)) {
- return false;
+ if (trial_name == "SpeculationRulesPrefetch") {
+ return base::FeatureList::IsEnabled(
+ features::kSpeculationRulesPrefetchProxy);
}
- if (trial_name == "SpeculationRulesPrefetch" &&
- !base::FeatureList::IsEnabled(features::kSpeculationRulesPrefetchProxy)) {
+ if (trial_name == "ConversionMeasurement" &&
+ !base::FeatureList::IsEnabled(features::kConversionMeasurement)) {
return false;
}
+
+ if (trial_name == "Prerender2")
+ return base::FeatureList::IsEnabled(features::kPrerender2);
+
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.h b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.h
index 941aa06b2bb..66de218cd26 100644
--- a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.h
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ORIGIN_TRIALS_ORIGIN_TRIAL_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ORIGIN_TRIALS_ORIGIN_TRIAL_CONTEXT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/origin_trials/trial_token.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
index cb2e5b4cdcd..db146af44c3 100644
--- a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
@@ -49,6 +49,8 @@ const char kTokenPlaceholder[] = "The token contents are not used";
class MockTokenValidator : public TrialTokenValidator {
public:
MockTokenValidator() = default;
+ MockTokenValidator(const MockTokenValidator&) = delete;
+ MockTokenValidator& operator=(const MockTokenValidator&) = delete;
~MockTokenValidator() override = default;
// blink::WebTrialTokenValidator implementation
@@ -96,8 +98,6 @@ class MockTokenValidator : public TrialTokenValidator {
bool is_third_party_;
mutable int call_count_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(MockTokenValidator);
};
} // namespace
@@ -574,7 +574,7 @@ class OriginTrialContextDevtoolsTest : public OriginTrialContextTest {
EXPECT_EQ(trial_result->value.token_results.size(),
expected_token_results.size());
- for (size_t i = 0; i < expected_token_results.size(); i++) {
+ for (wtf_size_t i = 0; i < expected_token_results.size(); i++) {
const auto& expected_token_result = expected_token_results[i];
const auto& actual_token_result = trial_result->value.token_results[i];
diff --git a/chromium/third_party/blink/renderer/core/page/DEPS b/chromium/third_party/blink/renderer/core/page/DEPS
index 1ddb8e26413..5f283142da4 100644
--- a/chromium/third_party/blink/renderer/core/page/DEPS
+++ b/chromium/third_party/blink/renderer/core/page/DEPS
@@ -10,4 +10,7 @@ specific_include_rules = {
"text_fragment_selector_generator_test\.cc": [
"+base/run_loop.h",
],
+ "context_menu_controller\.cc": [
+ "+components/shared_highlighting/core/common/shared_highlighting_features.h"
+ ]
}
diff --git a/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc b/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
index 187976f80a0..b1a7b0b9bd4 100644
--- a/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
@@ -26,7 +26,7 @@ class AutoscrollControllerTest : public SimTest {
TEST_F(AutoscrollControllerTest,
CrashWhenLayoutStopAnimationBeforeScheduleAnimation) {
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
- WebView().SetBaseBackgroundColor(SK_ColorTRANSPARENT);
+ WebView().SetPageBaseBackgroundColor(SK_ColorTRANSPARENT);
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
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 680dbc2274e..d8409b77903 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
@@ -23,7 +23,6 @@
#include <algorithm>
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_prescient_networking.h"
#include "third_party/blink/renderer/core/core_initializer.h"
@@ -42,6 +41,7 @@
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -293,7 +293,7 @@ void ChromeClient::ElementFocusedFromKeypress(LocalFrame& frame,
tooltip_text = element->DefaultToolTip();
LayoutObject* layout_object = element->GetLayoutObject();
- if (!tooltip_text.IsNull() && layout_object) {
+ if (layout_object) {
TextDirection tooltip_direction = layout_object->StyleRef().Direction();
UpdateTooltipFromKeyboard(frame, tooltip_text, tooltip_direction,
element->BoundsInViewport());
@@ -326,6 +326,16 @@ bool ChromeClient::Print(LocalFrame* frame) {
return false;
}
+ // print() returns quietly during prerendering.
+ // https://jeremyroman.github.io/alternate-loading-modes/#patch-modals
+ if (frame->GetDocument()->IsPrerendering()) {
+ frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageLevel::kError,
+ "Ignored call to 'print()' during prerendering."));
+ return false;
+ }
+
// Suspend pages in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of
// executing JavaScript.
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 ed7659e6a4b..92655e70dc2 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.h
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.h
@@ -31,8 +31,8 @@
#include "cc/input/overscroll_behavior.h"
#include "cc/paint/paint_image.h"
#include "cc/trees/paint_holding_commit_trigger.h"
+#include "cc/trees/paint_holding_reason.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
#include "third_party/blink/public/common/page/drag_operation.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy_features.h"
@@ -67,6 +67,11 @@ class Layer;
struct OverscrollBehavior;
}
+namespace display {
+struct ScreenInfo;
+struct ScreenInfos;
+} // namespace display
+
namespace ui {
class Cursor;
}
@@ -105,8 +110,6 @@ enum class FullscreenRequestType;
struct DateTimeChooserParameters;
struct FrameLoadRequest;
struct ViewportDescription;
-struct ScreenInfo;
-struct ScreenInfos;
struct WebWindowFeatures;
namespace mojom {
@@ -118,9 +121,9 @@ class TextAutosizerPageInfo;
using CompositorElementId = cc::ElementId;
class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
- DISALLOW_COPY_AND_ASSIGN(ChromeClient);
-
public:
+ ChromeClient(const ChromeClient&) = delete;
+ ChromeClient& operator=(const ChromeClient&) = delete;
virtual ~ChromeClient() = default;
virtual WebViewImpl* GetWebView() const = 0;
@@ -195,8 +198,12 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
// reference to make it clear that callers may only call this while a local
// main frame is present and the state does not persist between instances of
// local main frames.
- virtual void StartDeferringCommits(LocalFrame& main_frame,
- base::TimeDelta timeout) = 0;
+ //
+ // Returns false if commits were already deferred, indicating that the call
+ // was a no-op.
+ virtual bool StartDeferringCommits(LocalFrame& main_frame,
+ base::TimeDelta timeout,
+ cc::PaintHoldingReason reason) = 0;
virtual void StopDeferringCommits(LocalFrame& main_frame,
cc::PaintHoldingCommitTrigger) = 0;
@@ -293,8 +300,9 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
String& result);
virtual bool TabsToLinks() = 0;
- virtual const ScreenInfo& GetScreenInfo(LocalFrame& frame) const = 0;
- virtual const ScreenInfos& GetScreenInfos(LocalFrame& frame) const = 0;
+ virtual const display::ScreenInfo& GetScreenInfo(LocalFrame& frame) const = 0;
+ virtual const display::ScreenInfos& GetScreenInfos(
+ LocalFrame& frame) const = 0;
virtual void SetCursor(const ui::Cursor&, LocalFrame* local_root) = 0;
virtual void SetCursorOverridden(bool) = 0;
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc b/chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 196303d8224..fdeb0ffd7c5 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
@@ -38,6 +38,7 @@
#include "build/build_config.h"
#include "cc/animation/animation_host.h"
#include "cc/layers/picture_layer.h"
+#include "cc/trees/paint_holding_reason.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
@@ -108,6 +109,7 @@
#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/widget/frame_widget.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_concatenate.h"
@@ -255,13 +257,11 @@ Page* ChromeClientImpl::CreateWindowDelegate(
NotifyPopupOpeningObservers();
const AtomicString& frame_name =
!EqualIgnoringASCIICase(name, "_blank") ? name : g_empty_atom;
- WebViewImpl* new_view =
- static_cast<WebViewImpl*>(web_view_->Client()->CreateView(
- WebLocalFrameImpl::FromFrame(frame),
- WrappedResourceRequest(r.GetResourceRequest()), features, frame_name,
- static_cast<WebNavigationPolicy>(r.GetNavigationPolicy()),
- sandbox_flags, session_storage_namespace_id, consumed_user_gesture,
- r.Impression()));
+ WebViewImpl* new_view = To<WebViewImpl>(web_view_->Client()->CreateView(
+ WebLocalFrameImpl::FromFrame(frame),
+ WrappedResourceRequest(r.GetResourceRequest()), features, frame_name,
+ static_cast<WebNavigationPolicy>(r.GetNavigationPolicy()), sandbox_flags,
+ session_storage_namespace_id, consumed_user_gesture, r.Impression()));
if (!new_view)
return nullptr;
return new_view->GetPage();
@@ -469,11 +469,13 @@ float ChromeClientImpl::WindowToViewportScalar(LocalFrame* frame,
return frame->GetWidgetForLocalRoot()->DIPsToBlinkSpace(scalar_value);
}
-const ScreenInfo& ChromeClientImpl::GetScreenInfo(LocalFrame& frame) const {
+const display::ScreenInfo& ChromeClientImpl::GetScreenInfo(
+ LocalFrame& frame) const {
return frame.GetWidgetForLocalRoot()->GetScreenInfo();
}
-const ScreenInfos& ChromeClientImpl::GetScreenInfos(LocalFrame& frame) const {
+const display::ScreenInfos& ChromeClientImpl::GetScreenInfos(
+ LocalFrame& frame) const {
return frame.GetWidgetForLocalRoot()->GetScreenInfos();
}
@@ -585,7 +587,9 @@ void ChromeClientImpl::UpdateTooltipFromKeyboard(LocalFrame& frame,
if (!RuntimeEnabledFeatures::KeyboardAccessibleTooltipEnabled())
return;
- // TODO(bebeaudr): Add WidgetHost function and call it here.
+ WebLocalFrameImpl::FromFrame(frame)
+ ->LocalRootFrameWidget()
+ ->UpdateTooltipFromKeyboard(tooltip_text, dir, bounds);
}
void ChromeClientImpl::DispatchViewportPropertiesDidChange(
@@ -595,8 +599,8 @@ void ChromeClientImpl::DispatchViewportPropertiesDidChange(
void ChromeClientImpl::PrintDelegate(LocalFrame* frame) {
NotifyPopupOpeningObservers();
- if (web_view_->Client())
- web_view_->Client()->PrintPage(WebLocalFrameImpl::FromFrame(frame));
+ WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
+ web_frame->Client()->ScriptedPrint();
}
ColorChooser* ChromeClientImpl::OpenColorChooser(
@@ -614,6 +618,9 @@ ColorChooser* ChromeClientImpl::OpenColorChooser(
controller = MakeGarbageCollected<ColorChooserPopupUIController>(
frame, this, chooser_client);
} else {
+#if !defined(OS_ANDROID)
+ NOTREACHED() << "Page popups should be enabled on all but Android";
+#endif
controller =
MakeGarbageCollected<ColorChooserUIController>(frame, chooser_client);
}
@@ -659,13 +666,9 @@ void ChromeClientImpl::OpenFileChooser(
scoped_refptr<FileChooser> file_chooser) {
NotifyPopupOpeningObservers();
- Document* doc = frame->GetDocument();
- if (doc)
- doc->MaybeQueueSendDidEditFieldInInsecureContext();
-
static const wtf_size_t kMaximumPendingFileChooseRequests = 4;
if (file_chooser_queue_.size() > kMaximumPendingFileChooseRequests) {
- // This sanity check prevents too many file choose requests from getting
+ // This check prevents too many file choose requests from getting
// queued which could DoS the user. Getting these is most likely a
// programming error (there are many ways to DoS the user so it's not
// considered a "real" security check), either in JS requesting many file
@@ -984,12 +987,13 @@ void ChromeClientImpl::BeginLifecycleUpdates(LocalFrame& main_frame) {
web_view_->StopDeferringMainFrameUpdate();
}
-void ChromeClientImpl::StartDeferringCommits(LocalFrame& main_frame,
- base::TimeDelta timeout) {
+bool ChromeClientImpl::StartDeferringCommits(LocalFrame& main_frame,
+ base::TimeDelta timeout,
+ cc::PaintHoldingReason reason) {
DCHECK(main_frame.IsMainFrame());
- WebLocalFrameImpl::FromFrame(main_frame)
+ return WebLocalFrameImpl::FromFrame(main_frame)
->FrameWidgetImpl()
- ->StartDeferringCommits(timeout);
+ ->StartDeferringCommits(timeout, reason);
}
void ChromeClientImpl::StopDeferringCommits(
@@ -1099,7 +1103,6 @@ void ChromeClientImpl::DidChangeValueInTextField(
UseCounter::Count(doc, doc.GetExecutionContext()->IsSecureContext()
? WebFeature::kFieldEditInSecureContext
: WebFeature::kFieldEditInNonSecureContext);
- doc.MaybeQueueSendDidEditFieldInInsecureContext();
// The resource coordinator is not available in some tests.
if (auto* rc = doc.GetResourceCoordinator())
rc->SetHadFormInteraction();
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 dc404c85b2e..d7bf788ae0d 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
@@ -72,8 +72,9 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
void TakeFocus(mojom::blink::FocusType) override;
void SetKeyboardFocusURL(Element* new_focus_element) override;
void BeginLifecycleUpdates(LocalFrame& main_frame) override;
- void StartDeferringCommits(LocalFrame& main_frame,
- base::TimeDelta timeout) override;
+ bool StartDeferringCommits(LocalFrame& main_frame,
+ base::TimeDelta timeout,
+ cc::PaintHoldingReason reason) override;
void StopDeferringCommits(LocalFrame& main_frame,
cc::PaintHoldingCommitTrigger) override;
void StartDragging(LocalFrame*,
@@ -136,8 +137,8 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
IntRect ViewportToScreen(const IntRect&,
const LocalFrameView*) const override;
float WindowToViewportScalar(LocalFrame*, const float) const override;
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override;
- const ScreenInfos& GetScreenInfos(LocalFrame&) const override;
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override;
+ const display::ScreenInfos& GetScreenInfos(LocalFrame&) const override;
void OverrideVisibleRectForMainFrame(LocalFrame& frame,
IntRect* paint_rect) const override;
float InputEventsScaleForEmulation() const override;
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 717e04bf4a1..b64ba41f448 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
@@ -57,6 +57,9 @@
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
#include "third_party/blink/renderer/platform/language.h"
+// To avoid conflicts with the CreateWindow macro from the Windows SDK...
+#undef CreateWindow
+
namespace blink {
class ViewCreatingClient : public frame_test_helpers::TestWebViewClient {
@@ -178,8 +181,11 @@ class PagePopupSuppressionTest : public testing::Test {
DateTimeChooserParameters params;
params.locale = DefaultLanguage();
params.type = input_type_names::kTime;
- return !!chrome_client_impl_->OpenDateTimeChooser(
+ DateTimeChooser* chooser = chrome_client_impl_->OpenDateTimeChooser(
frame, date_time_chooser_client_, params);
+ if (chooser)
+ chooser->EndChooser();
+ return !!chooser;
}
Settings* GetSettings() {
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 ccfbb10a930..07dac876db6 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,6 +32,7 @@
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
+#include "components/shared_highlighting/core/common/shared_highlighting_features.h"
#include "services/metrics/public/cpp/ukm_entry_builder.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/common/context_menu_data/context_menu_data.h"
@@ -532,7 +533,7 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
if (IsA<HTMLVideoElement>(media_element) && media_element->HasVideo() &&
!media_element->IsFullscreen())
data.media_flags |= ContextMenuData::kMediaCanToggleControls;
- if (media_element->ShouldShowControls())
+ if (media_element->ShouldShowAllControls())
data.media_flags |= ContextMenuData::kMediaControls;
} else if (IsA<HTMLObjectElement>(*result.InnerNode()) ||
IsA<HTMLEmbedElement>(*result.InnerNode())) {
@@ -643,17 +644,18 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
<< selected_frame->Selection()
.ComputeVisibleSelectionInDOMTreeDeprecated();
if (!result.IsContentEditable()) {
- // Store text selection when it happens as it might be cleared when the
- // browser will request |TextFragmentHandler| to generate
- // selector.
UpdateTextFragmentHandler(selected_frame);
}
}
// If there is a text fragment at the same location as the click indicate that
// the context menu is being opened from an existing highlight.
- if (TextFragmentHandler::IsOverTextFragment(result)) {
- data.opened_from_highlight = true;
+ if (result.InnerNodeFrame()) {
+ result.InnerNodeFrame()->View()->UpdateLifecycleToPrePaintClean(
+ DocumentUpdateReason::kHitTest);
+ if (TextFragmentHandler::IsOverTextFragment(result)) {
+ data.opened_from_highlight = true;
+ }
}
if (result.IsContentEditable()) {
@@ -782,14 +784,16 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
void ContextMenuController::UpdateTextFragmentHandler(
LocalFrame* selected_frame) {
- if (!selected_frame->GetTextFragmentHandler())
- return;
+ if (!selected_frame->GetTextFragmentHandler()) {
+ if (!base::FeatureList::IsEnabled(
+ shared_highlighting::kSharedHighlightingAmp)) {
+ return;
+ }
+
+ selected_frame->CreateTextFragmentHandler();
+ }
- VisibleSelectionInFlatTree selection =
- selected_frame->Selection().ComputeVisibleSelectionInFlatTree();
- EphemeralRangeInFlatTree selection_range(selection.Start(), selection.End());
- selected_frame->GetTextFragmentSelectorGenerator()->UpdateSelection(
- selection_range);
+ selected_frame->GetTextFragmentHandler()->StartPreemptiveGenerationIfNeeded();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/context_menu_controller.h b/chromium/third_party/blink/renderer/core/page/context_menu_controller.h
index b12cdd50a0b..008ded230cb 100644
--- a/chromium/third_party/blink/renderer/core/page/context_menu_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/context_menu_controller.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_CONTEXT_MENU_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_CONTEXT_MENU_CONTROLLER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/input/web_menu_source_type.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom-blink.h"
@@ -49,6 +48,8 @@ class CORE_EXPORT ContextMenuController final
public mojom::blink::ContextMenuClient {
public:
explicit ContextMenuController(Page*);
+ ContextMenuController(const ContextMenuController&) = delete;
+ ContextMenuController operator=(const ContextMenuController&) = delete;
~ContextMenuController() override;
void Trace(Visitor*) const;
@@ -138,8 +139,6 @@ class CORE_EXPORT ContextMenuController final
Member<ContextMenuProvider> menu_provider_;
HitTestResult hit_test_result_;
Member<Node> image_selection_cached_result_;
-
- DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
};
} // namespace blink
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 21c38947006..ed0fcc89067 100644
--- a/chromium/third_party/blink/renderer/core/page/create_window.cc
+++ b/chromium/third_party/blink/renderer/core/page/create_window.cc
@@ -82,6 +82,11 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string,
bool ui_features_were_disabled = false;
+ // See crbug.com/1192701 for details, but we're working on changing the
+ // popup-triggering conditions for window.open. This bool represents the "new"
+ // state after this change.
+ bool is_popup_with_new_behavior = false;
+
unsigned key_begin, key_end;
unsigned value_begin, value_end;
@@ -181,6 +186,8 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string,
} else if (key_string == "width" || key_string == "innerwidth") {
window_features.width_set = true;
window_features.width = value;
+ // Width will be the only trigger for a popup.
+ is_popup_with_new_behavior = true;
} else if (key_string == "height" || key_string == "innerheight") {
window_features.height_set = true;
window_features.height = value;
@@ -217,6 +224,19 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string,
}
}
+ // Existing logic from NavigationPolicy::NavigationPolicyForCreateWindow():
+ if (dom_window && dom_window->document()) {
+ bool is_popup_with_current_behavior = !window_features.tool_bar_visible ||
+ !window_features.status_bar_visible ||
+ !window_features.scrollbars_visible ||
+ !window_features.menu_bar_visible ||
+ !window_features.resizable;
+ if (is_popup_with_current_behavior != is_popup_with_new_behavior) {
+ UseCounter::Count(dom_window->document(),
+ WebFeature::kWindowOpenNewPopupBehaviorMismatch);
+ }
+ }
+
if (window_features.noreferrer)
window_features.noopener = true;
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 2ca96374772..a017fc1fcd4 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller.cc
@@ -31,7 +31,6 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "third_party/blink/public/common/page/drag_operation.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
@@ -92,6 +91,7 @@
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
+#include "ui/display/screen_info.h"
#if defined(OS_WIN)
#include <windows.h>
@@ -1118,10 +1118,11 @@ static IntPoint DragLocationForImage(
static std::unique_ptr<DragImage> DragImageForLink(const KURL& link_url,
const String& link_text,
- float device_scale_factor) {
+ float device_scale_factor,
+ const Document* document) {
FontDescription font_description;
- LayoutTheme::GetTheme().SystemFont(blink::CSSValueID::kNone,
- font_description);
+ LayoutTheme::GetTheme().SystemFont(blink::CSSValueID::kNone, font_description,
+ document);
return DragImage::Create(link_url, link_text, font_description,
device_scale_factor);
}
@@ -1282,8 +1283,9 @@ bool DragController::StartDrag(LocalFrame* src,
DCHECK(src->GetPage());
float screen_device_scale_factor =
src->GetChromeClient().GetScreenInfo(*src).device_scale_factor;
- drag_image = DragImageForLink(link_url, hit_test_result.TextContent(),
- screen_device_scale_factor);
+ drag_image =
+ DragImageForLink(link_url, hit_test_result.TextContent(),
+ screen_device_scale_factor, src->GetDocument());
drag_location = DragLocationForLink(drag_image.get(), mouse_dragged_point,
screen_device_scale_factor,
src->GetPage()->PageScaleFactor());
diff --git a/chromium/third_party/blink/renderer/core/page/drag_controller.h b/chromium/third_party/blink/renderer/core/page/drag_controller.h
index 498edf24f21..5b3df061787 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_DRAG_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_DRAG_CONTROLLER_H_
-#include "base/macros.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/execution_context/execution_context_lifecycle_observer.h"
@@ -57,6 +56,8 @@ class CORE_EXPORT DragController final
public ExecutionContextLifecycleObserver {
public:
explicit DragController(Page*);
+ DragController(const DragController&) = delete;
+ DragController& operator=(const DragController&) = delete;
ui::mojom::blink::DragOperation DragEnteredOrUpdated(DragData*,
LocalFrame& local_root);
@@ -139,7 +140,6 @@ class CORE_EXPORT DragController final
DragDestinationAction drag_destination_action_;
bool did_initiate_drag_;
- DISALLOW_COPY_AND_ASSIGN(DragController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/drag_image.cc b/chromium/third_party/blink/renderer/core/page/drag_image.cc
index 150b1131ad3..afc6de1382a 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_image.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_image.cc
@@ -203,7 +203,8 @@ std::unique_ptr<DragImage> DragImage::Create(const KURL& url,
// TODO(fserb): are we sure this should be software?
std::unique_ptr<CanvasResourceProvider> resource_provider(
CanvasResourceProvider::CreateBitmapProvider(
- scaled_image_size, kLow_SkFilterQuality, CanvasResourceParams(),
+ scaled_image_size, cc::PaintFlags::FilterQuality::kLow,
+ CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kNo));
if (!resource_provider)
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/page/drag_image.h b/chromium/third_party/blink/renderer/core/page/drag_image.h
index 11d947d8387..a6b8cacf1a3 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_image.h
+++ b/chromium/third_party/blink/renderer/core/page/drag_image.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -62,6 +61,9 @@ class CORE_EXPORT DragImage {
const String& label,
const FontDescription& system_font,
float device_scale_factor);
+
+ DragImage(const DragImage&) = delete;
+ DragImage& operator=(const DragImage&) = delete;
~DragImage();
static FloatSize ClampedImageScale(const IntSize&,
@@ -80,8 +82,6 @@ class CORE_EXPORT DragImage {
SkBitmap bitmap_;
float resolution_scale_;
InterpolationQuality interpolation_quality_;
-
- DISALLOW_COPY_AND_ASSIGN(DragImage);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/drag_image_test.cc b/chromium/third_party/blink/renderer/core/page/drag_image_test.cc
index 22b4631e12c..d4e1f52ebae 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_image_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_image_test.cc
@@ -54,9 +54,8 @@ class TestImage : public Image {
return base::AdoptRef(new TestImage(size));
}
- IntSize Size() const override {
+ IntSize SizeWithConfig(SizeConfig) const override {
DCHECK(image_);
-
return IntSize(image_->width(), image_->height());
}
@@ -70,8 +69,7 @@ class TestImage : public Image {
const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override {
// Image pure virtual stub.
diff --git a/chromium/third_party/blink/renderer/core/page/drag_state.h b/chromium/third_party/blink/renderer/core/page/drag_state.h
index f9fc5095531..4ef9d75444f 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_state.h
+++ b/chromium/third_party/blink/renderer/core/page/drag_state.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_DRAG_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_DRAG_STATE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/page/drag_actions.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -38,6 +37,8 @@ class Node;
class DragState final : public GarbageCollected<DragState> {
public:
DragState() = default;
+ DragState(const DragState&) = delete;
+ DragState& operator=(const DragState&) = delete;
// Element that may be a drag source, for the current mouse gesture.
Member<Node> drag_src_;
@@ -49,9 +50,6 @@ class DragState final : public GarbageCollected<DragState> {
visitor->Trace(drag_src_);
visitor->Trace(drag_data_transfer_);
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DragState);
};
} // namespace blink
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 276dc7cc7b4..d0c59cc4168 100644
--- a/chromium/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/focus_controller.cc
@@ -916,7 +916,6 @@ void FocusController::FocusHasChanged() {
}
NotifyFocusChangedObservers();
- page_->GetPageScheduler()->OnFocusChanged(focused);
}
void FocusController::SetFocused(bool focused) {
diff --git a/chromium/third_party/blink/renderer/core/page/focus_controller.h b/chromium/third_party/blink/renderer/core/page/focus_controller.h
index 7f1e61819b9..02cc44098f4 100644
--- a/chromium/third_party/blink/renderer/core/page/focus_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/focus_controller.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_FOCUS_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_FOCUS_CONTROLLER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -54,6 +53,8 @@ class CORE_EXPORT FocusController final
using OwnerMap = HeapHashMap<Member<ContainerNode>, Member<Element>>;
explicit FocusController(Page*);
+ FocusController(const FocusController&) = delete;
+ FocusController& operator=(const FocusController&) = delete;
void SetFocusedFrame(Frame*, bool notify_embedder = true);
void FocusDocumentView(Frame*, bool notify_embedder = true);
@@ -129,7 +130,6 @@ class CORE_EXPORT FocusController final
bool is_changing_focused_frame_;
bool is_emulating_focus_;
HeapHashSet<WeakMember<FocusChangedObserver>> focus_changed_observers_;
- DISALLOW_COPY_AND_ASSIGN(FocusController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/frame_tree.h b/chromium/third_party/blink/renderer/core/page/frame_tree.h
index a99e25ff681..169d25680a1 100644
--- a/chromium/third_party/blink/renderer/core/page/frame_tree.h
+++ b/chromium/third_party/blink/renderer/core/page/frame_tree.h
@@ -21,7 +21,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_FRAME_TREE_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -37,6 +36,8 @@ class CORE_EXPORT FrameTree final {
public:
explicit FrameTree(Frame* this_frame);
+ FrameTree(const FrameTree&) = delete;
+ FrameTree& operator=(const FrameTree&) = delete;
~FrameTree();
const AtomicString& GetName() const;
@@ -109,8 +110,6 @@ class CORE_EXPORT FrameTree final {
// TODO(shuuran): remove this once we have gathered the data
bool cross_site_cross_browsing_context_group_set_nulled_name_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameTree);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc b/chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc
index 060d9662514..d77900d8474 100644
--- a/chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc
+++ b/chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc
@@ -20,7 +20,7 @@ void NamedPagesMapper::AddNamedPage(const AtomicString& page_name,
break;
}
- entries_.Shrink(entries_.rend() - prev_it);
+ entries_.Shrink(static_cast<wtf_size_t>(entries_.rend() - prev_it));
// Terminate the previous entry (now that we know its last page index)
// before adding the new entry.
diff --git a/chromium/third_party/blink/renderer/core/page/page.cc b/chromium/third_party/blink/renderer/core/page/page.cc
index 4ae29426622..3afca2407df 100644
--- a/chromium/third_party/blink/renderer/core/page/page.cc
+++ b/chromium/third_party/blink/renderer/core/page/page.cc
@@ -1051,10 +1051,6 @@ bool Page::LocalMainFrameNetworkIsAlmostIdle() const {
return frame->GetIdlenessDetector()->NetworkIsAlmostIdle();
}
-bool Page::IsFocused() const {
- return GetFocusController().IsFocused();
-}
-
void Page::AddAutoplayFlags(int32_t value) {
autoplay_flags_ |= value;
}
@@ -1068,7 +1064,15 @@ int32_t Page::AutoplayFlags() const {
}
void Page::SetInsidePortal(bool inside_portal) {
+ if (inside_portal_ == inside_portal)
+ return;
+
inside_portal_ = inside_portal;
+
+ if (MainFrame() && MainFrame()->IsLocalFrame() &&
+ DeprecatedLocalMainFrame()->GetDocument()) {
+ DeprecatedLocalMainFrame()->GetDocument()->ClearAXObjectCache();
+ }
}
bool Page::InsidePortal() const {
diff --git a/chromium/third_party/blink/renderer/core/page/page.h b/chromium/third_party/blink/renderer/core/page/page.h
index 9a219bef355..72e214c315a 100644
--- a/chromium/third_party/blink/renderer/core/page/page.h
+++ b/chromium/third_party/blink/renderer/core/page/page.h
@@ -26,7 +26,6 @@
#include <memory>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/types/pass_key.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/text_autosizer_page_info.mojom-blink.h"
@@ -118,6 +117,8 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
ChromeClient& chrome_client,
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
bool is_ordinary);
+ Page(const Page&) = delete;
+ Page& operator=(const Page&) = delete;
~Page() override;
void CloseSoon();
@@ -320,7 +321,6 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
bool RequestBeginMainFrameNotExpected(bool new_state) override;
void OnSetPageFrozen(bool is_frozen) override;
bool LocalMainFrameNetworkIsAlmostIdle() const override;
- bool IsFocused() const override;
void AddAutoplayFlags(int32_t flags);
void ClearAutoplayFlags();
@@ -330,6 +330,11 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
void SetInsidePortal(bool inside_portal);
bool InsidePortal() const;
+ void SetIsPrerendering(bool is_prerendering) {
+ is_prerendering_ = is_prerendering;
+ }
+ bool IsPrerendering() const { return is_prerendering_; }
+
void SetTextAutosizerPageInfo(
const mojom::blink::TextAutosizerPageInfo& page_info) {
web_text_autosizer_page_info_ = page_info;
@@ -493,11 +498,17 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
// Accessed by frames to determine whether to expose the PortalHost object.
bool inside_portal_ = false;
+ // Whether the page is being prerendered by the Prerender2
+ // feature. See content/browser/prerender/README.md.
+ //
+ // This is ordinarily initialized by WebViewImpl immediately after creating
+ // this Page. Once initialized, it can only transition from true to false on
+ // prerender activation; it does not go from false to true.
+ bool is_prerendering_ = false;
+
mojom::blink::TextAutosizerPageInfo web_text_autosizer_page_info_;
WebScopedVirtualTimePauser history_navigation_virtual_time_pauser_;
-
- DISALLOW_COPY_AND_ASSIGN(Page);
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Page>;
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 23986dde0d8..0edad1112a8 100644
--- a/chromium/third_party/blink/renderer/core/page/page_animator.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_animator.cc
@@ -59,18 +59,21 @@ void PageAnimator::ServiceScriptedAnimations(
Clock().SetAllowedToDynamicallyUpdateTime(false);
Clock().UpdateTime(monotonic_animation_start_time);
- DocumentsVector documents =
- GetAllDocuments(page_->MainFrame(), OnlyNonThrottled);
+ DocumentsVector documents = GetAllDocuments(page_->MainFrame(), AllDocuments);
for (auto& document : documents) {
- ScopedFrameBlamer frame_blamer(document->GetFrame());
- TRACE_EVENT0("blink,rail", "PageAnimator::serviceScriptedAnimations");
+ absl::optional<ScopedFrameBlamer> frame_blamer;
+ // TODO(szager): The following logic evolved piecemeal, and this conditional
+ // is suspect.
+ if (!document->View() || !document->View()->CanThrottleRendering()) {
+ frame_blamer.emplace(document->GetFrame());
+ TRACE_EVENT0("blink,rail", "PageAnimator::serviceScriptedAnimations");
+ }
if (!document->View()) {
document->GetDocumentAnimations()
.UpdateAnimationTimingForAnimationFrame();
continue;
}
- DCHECK(!document->View()->CanThrottleRendering());
document->View()->ServiceScriptedAnimations(monotonic_animation_start_time);
}
diff --git a/chromium/third_party/blink/renderer/core/page/plugin_data.cc b/chromium/third_party/blink/renderer/core/page/plugin_data.cc
index 89beb74dae8..c5f0d9c55c5 100644
--- a/chromium/third_party/blink/renderer/core/page/plugin_data.cc
+++ b/chromium/third_party/blink/renderer/core/page/plugin_data.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/page/plugin_data.h"
+#include "base/metrics/histogram_macros.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-blink.h"
@@ -39,8 +40,12 @@ void MimeClassInfo::Trace(Visitor* visitor) const {
MimeClassInfo::MimeClassInfo(const String& type,
const String& description,
- PluginInfo& plugin)
- : type_(type), description_(description), plugin_(&plugin) {}
+ PluginInfo& plugin,
+ const Vector<String> extensions)
+ : type_(type),
+ description_(description),
+ extensions_(std::move(extensions)),
+ plugin_(&plugin) {}
void PluginInfo::Trace(Visitor* visitor) const {
visitor->Trace(mimes_);
@@ -95,6 +100,7 @@ void PluginData::RefreshBrowserSidePluginCache() {
}
void PluginData::UpdatePluginList(const SecurityOrigin* main_frame_origin) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Blink.Plugin.UpdateTime");
ResetPluginData();
main_frame_origin_ = main_frame_origin;
@@ -105,14 +111,14 @@ void PluginData::UpdatePluginList(const SecurityOrigin* main_frame_origin) {
registry->GetPlugins(false, main_frame_origin_, &plugins);
for (const auto& plugin : plugins) {
auto* plugin_info = MakeGarbageCollected<PluginInfo>(
- plugin->name, FilePathToWebString(plugin->filename),
- plugin->description, plugin->background_color,
+ std::move(plugin->name), FilePathToWebString(plugin->filename),
+ std::move(plugin->description), plugin->background_color,
plugin->may_use_external_handler);
plugins_.push_back(plugin_info);
for (const auto& mime : plugin->mime_types) {
auto* mime_info = MakeGarbageCollected<MimeClassInfo>(
- mime->mime_type, mime->description, *plugin_info);
- mime_info->extensions_ = mime->file_extensions;
+ std::move(mime->mime_type), std::move(mime->description),
+ *plugin_info, std::move(mime->file_extensions));
plugin_info->AddMimeType(mime_info);
mimes_.push_back(mime_info);
}
diff --git a/chromium/third_party/blink/renderer/core/page/plugin_data.h b/chromium/third_party/blink/renderer/core/page/plugin_data.h
index 8dc24f5d25a..0d5439e9238 100644
--- a/chromium/third_party/blink/renderer/core/page/plugin_data.h
+++ b/chromium/third_party/blink/renderer/core/page/plugin_data.h
@@ -21,7 +21,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PLUGIN_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PLUGIN_DATA_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -37,7 +36,10 @@ class CORE_EXPORT MimeClassInfo final : public GarbageCollected<MimeClassInfo> {
public:
void Trace(Visitor*) const;
- MimeClassInfo(const String& type, const String& desc, PluginInfo&);
+ MimeClassInfo(const String& type,
+ const String& description,
+ PluginInfo& plugin,
+ const Vector<String> extensions);
const String& Type() const { return type_; }
const String& Description() const { return description_; }
@@ -93,6 +95,8 @@ class CORE_EXPORT PluginData final : public GarbageCollected<PluginData> {
void Trace(Visitor*) const;
PluginData() = default;
+ PluginData(const PluginData&) = delete;
+ PluginData& operator=(const PluginData&) = delete;
const HeapVector<Member<PluginInfo>>& Plugins() const { return plugins_; }
const HeapVector<Member<MimeClassInfo>>& Mimes() const { return mimes_; }
@@ -112,8 +116,6 @@ class CORE_EXPORT PluginData final : public GarbageCollected<PluginData> {
HeapVector<Member<PluginInfo>> plugins_;
HeapVector<Member<MimeClassInfo>> mimes_;
scoped_refptr<const SecurityOrigin> main_frame_origin_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginData);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h b/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h
index 8ee2203cb13..99b6cd6388f 100644
--- a/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h
+++ b/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PLUGIN_SCRIPT_FORBIDDEN_SCOPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PLUGIN_SCRIPT_FORBIDDEN_SCOPE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -43,12 +42,12 @@ class CORE_EXPORT PluginScriptForbiddenScope final {
public:
PluginScriptForbiddenScope();
+ PluginScriptForbiddenScope(const PluginScriptForbiddenScope&) = delete;
+ PluginScriptForbiddenScope& operator=(const PluginScriptForbiddenScope&) =
+ delete;
~PluginScriptForbiddenScope();
static bool IsForbidden();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PluginScriptForbiddenScope);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h b/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h
index 35cb3aa1368..f2caf84dde4 100644
--- a/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_POINTER_LOCK_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_POINTER_LOCK_CONTROLLER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/mojom/input/pointer_lock_context.mojom-blink.h"
#include "third_party/blink/public/mojom/input/pointer_lock_result.mojom-blink-forward.h"
@@ -54,6 +53,8 @@ class CORE_EXPORT PointerLockController final
: public GarbageCollected<PointerLockController> {
public:
explicit PointerLockController(Page*);
+ PointerLockController(const PointerLockController&) = delete;
+ PointerLockController& operator=(const PointerLockController&) = delete;
using ResultCallback =
base::OnceCallback<void(mojom::blink::PointerLockResult)>;
@@ -124,8 +125,6 @@ class CORE_EXPORT PointerLockController final
FloatPoint pointer_lock_screen_position_;
bool current_unadjusted_movement_setting_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(PointerLockController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/print_context.h b/chromium/third_party/blink/renderer/core/page/print_context.h
index dcb12b151ee..6922db6ea44 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context.h
+++ b/chromium/third_party/blink/renderer/core/page/print_context.h
@@ -137,14 +137,14 @@ class CORE_EXPORT ScopedPrintContext {
public:
explicit ScopedPrintContext(LocalFrame*);
+ ScopedPrintContext(const ScopedPrintContext&) = delete;
+ ScopedPrintContext& operator=(const ScopedPrintContext&) = delete;
~ScopedPrintContext();
PrintContext* operator->() const { return context_; }
private:
PrintContext* context_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedPrintContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scoped_page_pauser.h b/chromium/third_party/blink/renderer/core/page/scoped_page_pauser.h
index 5e34428fc00..9be24a4dd7c 100644
--- a/chromium/third_party/blink/renderer/core/page/scoped_page_pauser.h
+++ b/chromium/third_party/blink/renderer/core/page/scoped_page_pauser.h
@@ -20,7 +20,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCOPED_PAGE_PAUSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCOPED_PAGE_PAUSER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -34,6 +33,8 @@ class CORE_EXPORT ScopedPagePauser final {
public:
explicit ScopedPagePauser();
+ ScopedPagePauser(const ScopedPagePauser&) = delete;
+ ScopedPagePauser& operator=(const ScopedPagePauser&) = delete;
~ScopedPagePauser();
private:
@@ -43,7 +44,6 @@ class CORE_EXPORT ScopedPagePauser final {
static bool IsActive();
std::unique_ptr<ThreadScheduler::RendererPauseHandle> pause_handle_;
- DISALLOW_COPY_AND_ASSIGN(ScopedPagePauser);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
index 3c3847061a7..48f0cab609e 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
@@ -35,6 +35,8 @@ class CORE_EXPORT ElementFragmentAnchor final : public FragmentAnchor {
bool should_scroll);
ElementFragmentAnchor(Node& anchor_node, LocalFrame& frame);
+ ElementFragmentAnchor(const ElementFragmentAnchor&) = delete;
+ ElementFragmentAnchor& operator=(const ElementFragmentAnchor&) = delete;
~ElementFragmentAnchor() override = default;
// Will attempt to scroll the anchor into view.
@@ -75,8 +77,6 @@ class CORE_EXPORT ElementFragmentAnchor final : public FragmentAnchor {
// Invoke has no effect and the fragment can be disposed (unless focus is
// still needed).
bool needs_invoke_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(ElementFragmentAnchor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
index 0825e6b80be..c4ae15eebe4 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
@@ -22,6 +22,8 @@
#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/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/testing/find_cc_layer.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
@@ -35,7 +37,8 @@ namespace blink {
#define EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(actual) \
EXPECT_EQ(cc::MainThreadScrollingReason::kNotScrollingOnMain, actual)
-class MainThreadScrollingReasonsTest : public testing::Test {
+class MainThreadScrollingReasonsTest : public PaintTestConfigurations,
+ public testing::Test {
public:
MainThreadScrollingReasonsTest() : base_url_("http://www.test.com/") {
helper_.InitializeWithSettings(&ConfigureSettings);
@@ -112,9 +115,11 @@ class MainThreadScrollingReasonsTest : public testing::Test {
frame_test_helpers::WebViewHelper helper_;
};
+INSTANTIATE_PAINT_TEST_SUITE_P(MainThreadScrollingReasonsTest);
+
// More cases are tested in LocalFrameViewTest
// .RequiresMainThreadScrollingForBackgroundFixedAttachment.
-TEST_F(MainThreadScrollingReasonsTest,
+TEST_P(MainThreadScrollingReasonsTest,
BackgroundAttachmentFixedShouldTriggerMainThreadScroll) {
RegisterMockedHttpURLLoad("iframe-background-attachment-fixed.html");
RegisterMockedHttpURLLoad("iframe-background-attachment-fixed-inner.html");
@@ -122,52 +127,76 @@ TEST_F(MainThreadScrollingReasonsTest,
NavigateTo(base_url_ + "iframe-background-attachment-fixed.html");
ForceFullCompositingUpdate();
+ auto* root_layer = GetFrame()->View()->RootCcLayer();
+ auto* outer_layout_view = GetFrame()->View()->GetLayoutView();
Element* iframe = GetFrame()->GetDocument()->getElementById("iframe");
ASSERT_TRUE(iframe);
- LayoutObject* layout_object = iframe->GetLayoutObject();
- ASSERT_TRUE(layout_object);
- ASSERT_TRUE(layout_object->IsLayoutEmbeddedContent());
-
- auto* layout_embedded_content = To<LayoutEmbeddedContent>(layout_object);
- ASSERT_TRUE(layout_embedded_content);
-
- LocalFrameView* inner_frame_view =
- To<LocalFrameView>(layout_embedded_content->ChildFrameView());
+ LocalFrameView* inner_frame_view = To<LocalFrameView>(
+ To<LayoutEmbeddedContent>(iframe->GetLayoutObject())->ChildFrameView());
ASSERT_TRUE(inner_frame_view);
-
auto* inner_layout_view = inner_frame_view->GetLayoutView();
ASSERT_TRUE(inner_layout_view);
- PaintLayerCompositor* inner_compositor = inner_layout_view->Compositor();
- ASSERT_TRUE(inner_compositor->InCompositingMode());
-
- cc::Layer* cc_scroll_layer =
- inner_frame_view->LayoutViewport()->LayerForScrolling();
- ASSERT_TRUE(cc_scroll_layer);
- ASSERT_TRUE(IsScrollable(cc_scroll_layer));
+ auto* inner_scroll_node =
+ inner_layout_view->FirstFragment().PaintProperties()->Scroll();
+ ASSERT_TRUE(inner_scroll_node);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ inner_scroll_node->GetMainThreadScrollingReasons());
+ const cc::Layer* inner_scroll_layer = CcLayerByCcElementId(
+ root_layer, inner_scroll_node->GetCompositorElementId());
+ ASSERT_TRUE(inner_scroll_layer);
+ ASSERT_TRUE(IsScrollable(inner_scroll_layer));
EXPECT_MAIN_THREAD_SCROLLING_REASON(
cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
- GetMainThreadScrollingReasons(cc_scroll_layer));
+ GetMainThreadScrollingReasons(inner_scroll_layer));
+
+ // Main thread scrolling of the inner layer doesn't affect the outer layer.
+ auto* outer_scroll_node = GetFrame()
+ ->View()
+ ->GetLayoutView()
+ ->FirstFragment()
+ .PaintProperties()
+ ->Scroll();
+ ASSERT_TRUE(outer_scroll_node);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ outer_scroll_node->GetMainThreadScrollingReasons());
+ const cc::Layer* outer_scroll_layer = CcLayerByCcElementId(
+ root_layer, outer_scroll_node->GetCompositorElementId());
+ ASSERT_TRUE(outer_scroll_layer);
+ ASSERT_TRUE(IsScrollable(outer_scroll_layer));
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ GetMainThreadScrollingReasons(outer_scroll_layer));
- // Remove fixed background-attachment should make the iframe
- // scroll on cc.
- auto* iframe_doc = To<HTMLIFrameElement>(iframe)->contentDocument();
- iframe = iframe_doc->getElementById("scrollable");
- ASSERT_TRUE(iframe);
+ // Remove fixed background-attachment should make the iframe scroll on cc.
+ auto* content = inner_layout_view->GetDocument().getElementById("content");
+ ASSERT_TRUE(content);
+ content->removeAttribute("class");
- iframe->removeAttribute("class");
ForceFullCompositingUpdate();
- layout_object = iframe->GetLayoutObject();
- ASSERT_TRUE(layout_object);
+ ASSERT_EQ(inner_scroll_node,
+ inner_layout_view->FirstFragment().PaintProperties()->Scroll());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ inner_scroll_node->GetMainThreadScrollingReasons());
+ ASSERT_EQ(inner_scroll_layer,
+ CcLayerByCcElementId(root_layer,
+ inner_scroll_node->GetCompositorElementId()));
+ ASSERT_TRUE(IsScrollable(inner_scroll_layer));
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ GetMainThreadScrollingReasons(inner_scroll_layer));
- cc_scroll_layer =
- layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
- ASSERT_TRUE(cc_scroll_layer);
- ASSERT_TRUE(IsScrollable(cc_scroll_layer));
+ ASSERT_EQ(outer_scroll_node,
+ outer_layout_view->FirstFragment().PaintProperties()->Scroll());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ outer_scroll_node->GetMainThreadScrollingReasons());
+ ASSERT_EQ(outer_scroll_layer,
+ CcLayerByCcElementId(root_layer,
+ outer_scroll_node->GetCompositorElementId()));
+ ASSERT_TRUE(IsScrollable(outer_scroll_layer));
EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
- GetMainThreadScrollingReasons(cc_scroll_layer));
+ GetMainThreadScrollingReasons(outer_scroll_layer));
// Force main frame to scroll on main thread. All its descendants
// should scroll on main thread as well.
@@ -179,21 +208,37 @@ TEST_F(MainThreadScrollingReasonsTest,
ForceFullCompositingUpdate();
- layout_object = iframe->GetLayoutObject();
- ASSERT_TRUE(layout_object);
+ // Main thread scrolling of the outer layer affects the inner layer.
+ ASSERT_EQ(inner_scroll_node,
+ inner_layout_view->FirstFragment().PaintProperties()->Scroll());
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ inner_scroll_node->GetMainThreadScrollingReasons());
+ ASSERT_EQ(inner_scroll_layer,
+ CcLayerByCcElementId(root_layer,
+ inner_scroll_node->GetCompositorElementId()));
+ ASSERT_TRUE(IsScrollable(inner_scroll_layer));
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ GetMainThreadScrollingReasons(inner_scroll_layer));
- cc_scroll_layer =
- layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
- ASSERT_TRUE(cc_scroll_layer);
- ASSERT_TRUE(IsScrollable(cc_scroll_layer));
+ ASSERT_EQ(outer_scroll_node,
+ outer_layout_view->FirstFragment().PaintProperties()->Scroll());
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ outer_scroll_node->GetMainThreadScrollingReasons());
+ ASSERT_EQ(outer_scroll_layer,
+ CcLayerByCcElementId(root_layer,
+ outer_scroll_node->GetCompositorElementId()));
+ ASSERT_TRUE(IsScrollable(outer_scroll_layer));
EXPECT_MAIN_THREAD_SCROLLING_REASON(
cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
- GetMainThreadScrollingReasons(cc_scroll_layer));
+ GetMainThreadScrollingReasons(outer_scroll_layer));
}
// Upon resizing the content size, the main thread scrolling reason
// kHasBackgroundAttachmentFixedObjects should be updated on all frames
-TEST_F(MainThreadScrollingReasonsTest,
+TEST_P(MainThreadScrollingReasonsTest,
RecalculateMainThreadScrollingReasonsUponResize) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
RegisterMockedHttpURLLoad("has-non-layer-viewport-constrained-objects.html");
@@ -224,7 +269,7 @@ TEST_F(MainThreadScrollingReasonsTest,
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
}
-TEST_F(MainThreadScrollingReasonsTest, FastScrollingCanBeDisabledWithSetting) {
+TEST_P(MainThreadScrollingReasonsTest, FastScrollingCanBeDisabledWithSetting) {
GetWebView()->MainFrameViewWidget()->Resize(gfx::Size(800, 600));
LoadHTML("<div id='spacer' style='height: 1000px'></div>");
GetWebView()->GetSettings()->SetThreadedScrollingEnabled(false);
@@ -241,7 +286,7 @@ TEST_F(MainThreadScrollingReasonsTest, FastScrollingCanBeDisabledWithSetting) {
EXPECT_TRUE(GetMainThreadScrollingReasons(visual_viewport_scroll_layer));
}
-TEST_F(MainThreadScrollingReasonsTest, FastScrollingForFixedPosition) {
+TEST_P(MainThreadScrollingReasonsTest, FastScrollingForFixedPosition) {
RegisterMockedHttpURLLoad("fixed-position.html");
NavigateTo(base_url_ + "fixed-position.html");
ForceFullCompositingUpdate();
@@ -250,7 +295,7 @@ TEST_F(MainThreadScrollingReasonsTest, FastScrollingForFixedPosition) {
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
}
-TEST_F(MainThreadScrollingReasonsTest, FastScrollingForStickyPosition) {
+TEST_P(MainThreadScrollingReasonsTest, FastScrollingForStickyPosition) {
RegisterMockedHttpURLLoad("sticky-position.html");
NavigateTo(base_url_ + "sticky-position.html");
ForceFullCompositingUpdate();
@@ -259,7 +304,7 @@ TEST_F(MainThreadScrollingReasonsTest, FastScrollingForStickyPosition) {
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
}
-TEST_F(MainThreadScrollingReasonsTest, FastScrollingByDefault) {
+TEST_P(MainThreadScrollingReasonsTest, FastScrollingByDefault) {
GetWebView()->MainFrameViewWidget()->Resize(gfx::Size(800, 600));
LoadHTML("<div id='spacer' style='height: 1000px'></div>");
ForceFullCompositingUpdate();
@@ -273,31 +318,6 @@ TEST_F(MainThreadScrollingReasonsTest, FastScrollingByDefault) {
EXPECT_FALSE(GetMainThreadScrollingReasons(visual_viewport_scroll_layer));
}
-TEST_F(MainThreadScrollingReasonsTest,
- ScrollbarsForceMainThreadOrHaveCompositorScrollbarLayer) {
- RegisterMockedHttpURLLoad("trivial-scroller.html");
- NavigateTo(base_url_ + "trivial-scroller.html");
- ForceFullCompositingUpdate();
-
- Document* document = GetFrame()->GetDocument();
- Element* scrollable_element = document->getElementById("scroller");
- DCHECK(scrollable_element);
-
- LayoutObject* layout_object = scrollable_element->GetLayoutObject();
- auto* box = To<LayoutBox>(layout_object);
- ASSERT_TRUE(box->UsesCompositedScrolling());
- CompositedLayerMapping* composited_layer_mapping =
- box->Layer()->GetCompositedLayerMapping();
- GraphicsLayer* scrollbar_graphics_layer =
- composited_layer_mapping->LayerForVerticalScrollbar();
- ASSERT_TRUE(scrollbar_graphics_layer);
-
- bool has_cc_scrollbar_layer = !scrollbar_graphics_layer->DrawsContent();
- EXPECT_TRUE(
- has_cc_scrollbar_layer ||
- GetMainThreadScrollingReasons(scrollbar_graphics_layer->ContentsLayer()));
-}
-
class NonCompositedMainThreadScrollingReasonsTest
: public MainThreadScrollingReasonsTest {
static const uint32_t kLCDTextRelatedReasons =
@@ -371,61 +391,63 @@ class NonCompositedMainThreadScrollingReasonsTest
}
};
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, TransparentTest) {
+INSTANTIATE_PAINT_TEST_SUITE_P(NonCompositedMainThreadScrollingReasonsTest);
+
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, TransparentTest) {
TestNonCompositedReasons("transparent",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, TransformTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, TransformTest) {
TestNonCompositedReasons("transform",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, BackgroundNotOpaqueTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, BackgroundNotOpaqueTest) {
TestNonCompositedReasons(
"background-not-opaque",
cc::MainThreadScrollingReason::kNotOpaqueForTextAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest,
+TEST_P(NonCompositedMainThreadScrollingReasonsTest,
CantPaintScrollingBackgroundTest) {
TestNonCompositedReasons(
"cant-paint-scrolling-background",
cc::MainThreadScrollingReason::kCantPaintScrollingBackgroundAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, ClipTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, ClipTest) {
TestNonCompositedReasons("clip",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, ClipPathTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, ClipPathTest) {
TestNonCompositedReasons("clip-path",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, BoxShadowTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, BoxShadowTest) {
TestNonCompositedReasons("box-shadow",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, InsetBoxShadowTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, InsetBoxShadowTest) {
TestNonCompositedReasons(
"inset-box-shadow",
cc::MainThreadScrollingReason::kCantPaintScrollingBackgroundAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, StackingContextTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, StackingContextTest) {
TestNonCompositedReasons("non-stacking-context",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, BorderRadiusTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonsTest, BorderRadiusTest) {
TestNonCompositedReasons("border-radius",
cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest,
+TEST_P(NonCompositedMainThreadScrollingReasonsTest,
ForcedComositingWithLCDRelatedReasons) {
// 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/root_scroller_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index b9b2d608815..15c6c3b6d56 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
@@ -11,8 +11,8 @@
#include "third_party/blink/public/web/web_remote_frame.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_settings.h"
-#include "third_party/blink/renderer/bindings/core/v8/node_or_string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_node_string_trustedscript.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/dom_visual_viewport.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -218,14 +218,9 @@ TEST_F(RootScrollerTest, defaultEffectiveRootScrollerIsDocumentNode) {
// Replace the documentElement with the iframe. The effectiveRootScroller
// should remain the same.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>> nodes;
nodes.push_back(
MakeGarbageCollected<V8UnionNodeOrStringOrTrustedScript>(iframe));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<NodeOrStringOrTrustedScript> nodes;
- nodes.push_back(NodeOrStringOrTrustedScript::FromNode(iframe));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
document->documentElement()->ReplaceWith(nodes, ASSERT_NO_EXCEPTION);
UpdateAllLifecyclePhases(MainFrameView());
@@ -2854,7 +2849,7 @@ class RootScrollerHitTest : public ImplicitRootScrollerSimTest {
.GlobalRootScroller();
ScrollableArea* scrollable_area =
To<LayoutBox>(scroller->GetLayoutObject())->GetScrollableArea();
- scrollable_area->DidScroll(FloatPoint(0, 100000));
+ scrollable_area->DidCompositorScroll(FloatPoint(0, 100000));
WebView().ResizeWithBrowserControls(gfx::Size(400, 450), 50, 50, false);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h
index 0cc04b45ee8..f234b179664 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_SCROLL_CUSTOMIZATION_CALLBACKS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_SCROLL_CUSTOMIZATION_CALLBACKS_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -19,6 +18,10 @@ class CORE_EXPORT ScrollCustomizationCallbacks
: public GarbageCollected<ScrollCustomizationCallbacks> {
public:
ScrollCustomizationCallbacks() = default;
+ ScrollCustomizationCallbacks(const ScrollCustomizationCallbacks&) = delete;
+ ScrollCustomizationCallbacks& operator=(const ScrollCustomizationCallbacks&) =
+ delete;
+
void SetDistributeScroll(Node*, ScrollStateCallback*);
ScrollStateCallback* GetDistributeScroll(Node*);
void SetApplyScroll(Node*, ScrollStateCallback*);
@@ -39,8 +42,6 @@ class CORE_EXPORT ScrollCustomizationCallbacks
ScrollStateCallbackList apply_scroll_callbacks_;
ScrollStateCallbackList distribute_scroll_callbacks_;
HeapHashMap<WeakMember<Node>, bool> in_scrolling_phase_;
-
- DISALLOW_COPY_AND_ASSIGN(ScrollCustomizationCallbacks);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
index a7815a5217b..d544809d3a2 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
#include "third_party/blink/public/web/web_script_source.h"
-#include "third_party/blink/renderer/bindings/core/v8/scroll_into_view_options_or_boolean.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_to_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_boolean_scrollintoviewoptions.h"
@@ -45,14 +44,8 @@ TEST_F(ScrollIntoViewTest, InstantScroll) {
Element* content = GetDocument().getElementById("content");
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
content->scrollIntoView(
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
- content->scrollIntoView(arg);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ASSERT_EQ(Window().scrollY(), content->OffsetTop());
}
@@ -171,13 +164,8 @@ TEST_F(ScrollIntoViewTest, SmoothScroll) {
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
options->setBehavior("smooth");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Compositor().BeginFrame();
ASSERT_EQ(Window().scrollY(), 0);
@@ -215,13 +203,8 @@ TEST_F(ScrollIntoViewTest, NestedContainer) {
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
options->setBehavior("smooth");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Compositor().BeginFrame();
ASSERT_EQ(Window().scrollY(), 0);
ASSERT_EQ(container->scrollTop(), 0);
@@ -281,13 +264,8 @@ TEST_F(ScrollIntoViewTest, NewScrollIntoViewAbortsCurrentAnimation) {
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
options->setBehavior("smooth");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Compositor().BeginFrame();
ASSERT_EQ(Window().scrollY(), 0);
@@ -358,13 +336,8 @@ TEST_F(ScrollIntoViewTest, ScrollWindowAbortsCurrentAnimation) {
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
options->setBehavior("smooth");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Compositor().BeginFrame();
ASSERT_EQ(Window().scrollY(), 0);
ASSERT_EQ(container->scrollTop(), 0);
@@ -418,20 +391,13 @@ TEST_F(ScrollIntoViewTest, BlockAndInlineSettings) {
int window_width = 800;
Element* content = GetDocument().getElementById("content");
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg1, arg2, arg3, arg4;
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
ASSERT_EQ(Window().scrollY(), 0);
options->setBlock("nearest");
options->setInlinePosition("nearest");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg1 =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- arg1.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
content->scrollIntoView(arg1);
ASSERT_EQ(Window().scrollX(),
content->OffsetLeft() + content_width - window_width);
@@ -440,24 +406,16 @@ TEST_F(ScrollIntoViewTest, BlockAndInlineSettings) {
options->setBlock("start");
options->setInlinePosition("start");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg2 =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- arg2.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
content->scrollIntoView(arg2);
ASSERT_EQ(Window().scrollX(), content->OffsetLeft());
ASSERT_EQ(Window().scrollY(), content->OffsetTop());
options->setBlock("center");
options->setInlinePosition("center");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg3 =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- arg3.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
content->scrollIntoView(arg3);
ASSERT_EQ(Window().scrollX(),
content->OffsetLeft() + (content_width - window_width) / 2);
@@ -466,12 +424,8 @@ TEST_F(ScrollIntoViewTest, BlockAndInlineSettings) {
options->setBlock("end");
options->setInlinePosition("end");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg4 =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- arg4.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
content->scrollIntoView(arg4);
ASSERT_EQ(Window().scrollX(),
content->OffsetLeft() + content_width - window_width);
@@ -501,13 +455,8 @@ TEST_F(ScrollIntoViewTest, SmoothAndInstantInChain) {
Element* content = GetDocument().getElementById("content");
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Compositor().BeginFrame();
ASSERT_EQ(Window().scrollY(), 0);
ASSERT_EQ(container->scrollTop(), 0);
@@ -608,13 +557,8 @@ TEST_F(ScrollIntoViewTest, ApplyRootElementScrollBehaviorToViewport) {
Element* content = GetDocument().getElementById("content");
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Compositor().BeginFrame();
ASSERT_EQ(Window().scrollY(), 0);
@@ -829,13 +773,8 @@ TEST_F(ScrollIntoViewTest, LongDistanceSmoothScrollFinishedInThreeSeconds) {
ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
options->setBlock("start");
options->setBehavior("smooth");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* arg =
MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScrollIntoViewOptionsOrBoolean arg;
- arg.SetScrollIntoViewOptions(options);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
target->scrollIntoView(arg);
// Scrolling the window
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 ecab9a4aca1..a466b7a5117 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
@@ -90,20 +90,21 @@ ScrollingCoordinator::ScrollableAreaWithElementIdInAllLocalFrames(
return nullptr;
}
-void ScrollingCoordinator::DidScroll(
+void ScrollingCoordinator::DidCompositorScroll(
CompositorElementId element_id,
const gfx::ScrollOffset& offset,
const absl::optional<cc::TargetSnapAreaElementIds>& snap_target_ids) {
// Find the associated scrollable area using the element id and notify it of
// the compositor-side scroll. We explicitly do not check the VisualViewport
- // which handles scroll offset differently (see: VisualViewport::didScroll).
- // Remote frames will receive DidScroll callbacks from their own compositor.
+ // which handles scroll offset differently (see:
+ // VisualViewport::DidCompositorScroll). Remote frames will receive
+ // DidCompositorScroll callbacks from their own compositor.
// The ScrollableArea with matching ElementId may have been deleted and we can
- // safely ignore the DidScroll callback.
+ // safely ignore the DidCompositorScroll callback.
auto* scrollable = ScrollableAreaWithElementIdInAllLocalFrames(element_id);
if (!scrollable)
return;
- scrollable->DidScroll(FloatPoint(offset.x(), offset.y()));
+ scrollable->DidCompositorScroll(FloatPoint(offset.x(), offset.y()));
if (snap_target_ids)
scrollable->SetTargetSnapAreaElementIds(snap_target_ids.value());
}
@@ -179,7 +180,7 @@ cc::ScrollbarLayerBase* ScrollingCoordinator::GetScrollbarLayer(
ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
? horizontal_scrollbars_
: vertical_scrollbars_;
- return scrollbars.at(scrollable_area);
+ return scrollbars.DeprecatedAtOrEmptyValue(scrollable_area);
}
void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
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 cdae7058097..a8fb445489c 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
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
@@ -64,6 +63,8 @@ class CORE_EXPORT ScrollingCoordinator final
public CompositorScrollCallbacks {
public:
explicit ScrollingCoordinator(Page*);
+ ScrollingCoordinator(const ScrollingCoordinator&) = delete;
+ ScrollingCoordinator& operator=(const ScrollingCoordinator&) = delete;
~ScrollingCoordinator() override;
void Trace(Visitor*) const;
@@ -112,9 +113,10 @@ class CORE_EXPORT ScrollingCoordinator final
const CompositorElementId&);
// ScrollCallbacks implementation
- void DidScroll(CompositorElementId,
- const gfx::ScrollOffset&,
- const absl::optional<cc::TargetSnapAreaElementIds>&) override;
+ void DidCompositorScroll(
+ CompositorElementId,
+ const gfx::ScrollOffset&,
+ const absl::optional<cc::TargetSnapAreaElementIds>&) override;
void DidChangeScrollbarsHidden(CompositorElementId, bool hidden) override;
base::WeakPtr<ScrollingCoordinator> GetWeakPtr() {
@@ -149,8 +151,6 @@ class CORE_EXPORT ScrollingCoordinator final
ScrollbarMap vertical_scrollbars_;
base::WeakPtrFactory<ScrollingCoordinator> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ScrollingCoordinator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h
index a4b1b926f3d..149d332a412 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h
@@ -22,8 +22,11 @@ class CORE_EXPORT ScrollingCoordinatorContext final {
USING_FAST_MALLOC(ScrollingCoordinatorContext);
public:
- ScrollingCoordinatorContext() {}
- virtual ~ScrollingCoordinatorContext() {}
+ ScrollingCoordinatorContext() = default;
+ ScrollingCoordinatorContext(const ScrollingCoordinatorContext&) = delete;
+ ScrollingCoordinatorContext& operator=(const ScrollingCoordinatorContext&) =
+ delete;
+ virtual ~ScrollingCoordinatorContext() = default;
void SetAnimationTimeline(
std::unique_ptr<CompositorAnimationTimeline> timeline) {
@@ -39,8 +42,6 @@ class CORE_EXPORT ScrollingCoordinatorContext final {
private:
std::unique_ptr<CompositorAnimationTimeline> animation_timeline_;
cc::AnimationHost* animation_host_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(ScrollingCoordinatorContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
index 667cc41a941..c6a498fb53d 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -33,6 +33,7 @@
#include "cc/trees/sticky_position_constraint.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_cache.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_settings.h"
@@ -1319,9 +1320,9 @@ TEST_P(ScrollingTest, PluginBecomesLayoutInline) {
ForceFullCompositingUpdate();
}
-// Ensure NonFastScrollableRegions are correctly generated for both fixed and
-// in-flow plugins that need them.
-TEST_P(ScrollingTest, NonFastScrollableRegionsForPlugins) {
+// Ensure blocking wheel event regions are correctly generated for both fixed
+// and in-flow plugins that need them.
+TEST_P(ScrollingTest, WheelEventRegionsForPlugins) {
LoadHTML(R"HTML(
<style>
body {
@@ -1351,23 +1352,23 @@ TEST_P(ScrollingTest, NonFastScrollableRegionsForPlugins) {
GetFrame()->GetDocument()->getElementById("plugin"));
auto* plugin_fixed = To<HTMLObjectElement>(
GetFrame()->GetDocument()->getElementById("pluginfixed"));
- // NonFastScrollableRegions are generated for plugins that require wheel
+ // Wheel event regions are generated for plugins that require wheel
// events.
plugin->OwnedPlugin()->SetWantsWheelEvents(true);
plugin_fixed->OwnedPlugin()->SetWantsWheelEvents(true);
ForceFullCompositingUpdate();
- // The non-fixed plugin should create a non-fast scrollable region in the
+ // The non-fixed plugin should create a wheel event region in the
// scrolling contents layer of the LayoutView.
auto* viewport_non_fast_layer = MainFrameScrollingContentsLayer();
- EXPECT_EQ(viewport_non_fast_layer->non_fast_scrollable_region().bounds(),
+ EXPECT_EQ(viewport_non_fast_layer->wheel_event_region().bounds(),
gfx::Rect(0, 0, 300, 300));
- // The fixed plugin should create a non-fast scrollable region in a fixed
+ // The fixed plugin should create a wheel event region in a fixed
// cc::Layer.
auto* fixed_layer = LayerByDOMElementId("fixed");
- EXPECT_EQ(fixed_layer->non_fast_scrollable_region().bounds(),
+ EXPECT_EQ(fixed_layer->wheel_event_region().bounds(),
gfx::Rect(0, 0, 200, 200));
}
@@ -2039,7 +2040,7 @@ class UnifiedScrollingSimTest : public SimTest, public PaintTestConfigurations {
void RunIdleTasks() {
auto* scheduler =
- ThreadScheduler::Current()->GetWebMainThreadSchedulerForTest();
+ blink::scheduler::WebThreadScheduler::MainThreadScheduler();
blink::scheduler::RunIdleTasksForTesting(scheduler,
base::BindOnce([]() {}));
test::RunPendingTasks();
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 98f72b36490..4aed25c2356 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_SNAP_COORDINATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_SNAP_COORDINATOR_H_
-#include "base/macros.h"
#include "cc/input/scroll_snap_data.h"
#include "cc/input/snap_selection_strategy.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -35,6 +34,8 @@ class CORE_EXPORT SnapCoordinator final
: public GarbageCollected<SnapCoordinator> {
public:
explicit SnapCoordinator();
+ SnapCoordinator(const SnapCoordinator&) = delete;
+ SnapCoordinator& operator=(const SnapCoordinator&) = delete;
~SnapCoordinator();
void Trace(Visitor* visitor) const {}
@@ -82,8 +83,6 @@ class CORE_EXPORT SnapCoordinator final
// Used for reporting to UMA when snapping on the initial layout affects the
// initial scroll position.
bool did_first_resnap_all_containers_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(SnapCoordinator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h b/chromium/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
index a9a04127c41..b384d1a371d 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
@@ -80,6 +80,8 @@ struct StickyPositionScrollingConstraints final {
is_anchored_bottom(false) {}
StickyPositionScrollingConstraints(
const StickyPositionScrollingConstraints& other) = default;
+ StickyPositionScrollingConstraints& operator=(
+ const StickyPositionScrollingConstraints& other) = default;
// Computes the sticky offset for a given overflow clip rect.
//
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
index 44557e8731e..984f9e614ce 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
@@ -34,8 +34,8 @@ bool ParseTextDirective(const String& fragment_directive,
Vector<TextFragmentSelector>* out_selectors) {
DCHECK(out_selectors);
- size_t start_pos = 0;
- size_t end_pos = 0;
+ wtf_size_t start_pos = 0;
+ wtf_size_t end_pos = 0;
while (end_pos != kNotFound) {
if (fragment_directive.Find(kTextFragmentIdentifierPrefix, start_pos) !=
start_pos) {
@@ -117,10 +117,11 @@ bool TextFragmentAnchor::GenerateNewToken(const DocumentLoader& loader) {
bool TextFragmentAnchor::GenerateNewTokenForSameDocument(
const DocumentLoader& loader,
WebFrameLoadType load_type,
- SameDocumentNavigationSource source) {
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type) {
if ((load_type != WebFrameLoadType::kStandard &&
load_type != WebFrameLoadType::kReplaceCurrentItem) ||
- source != kSameDocumentNavigationDefault)
+ same_document_navigation_type !=
+ mojom::blink::SameDocumentNavigationType::kFragment)
return false;
// Same-document text fragment navigations are allowed only when initiated
@@ -490,7 +491,8 @@ bool TextFragmentAnchor::Dismiss() {
// fragment shown in the URL matches the state of the highlight on the page.
// This is equivalent to history.replaceState in javascript.
frame_->DomWindow()->document()->Loader()->RunURLAndHistoryUpdateSteps(
- url, /*data=*/nullptr, WebFrameLoadType::kReplaceCurrentItem,
+ url, mojom::blink::SameDocumentNavigationType::kFragment,
+ /*data=*/nullptr, WebFrameLoadType::kReplaceCurrentItem,
mojom::blink::ScrollRestorationType::kAuto);
return dismissed_;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
index c520078e49b..3d47e7b2a00 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_ANCHOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_ANCHOR_H_
+#include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-blink.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/editing/forward.h"
-#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
@@ -50,7 +50,7 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
static bool GenerateNewTokenForSameDocument(
const DocumentLoader&,
WebFrameLoadType load_type,
- SameDocumentNavigationSource source);
+ mojom::blink::SameDocumentNavigationType same_document_navigation_type);
static TextFragmentAnchor* TryCreateFragmentDirective(
const KURL& url,
@@ -61,6 +61,8 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
const Vector<TextFragmentSelector>& text_fragment_selectors,
LocalFrame& frame,
bool should_scroll);
+ TextFragmentAnchor(const TextFragmentAnchor&) = delete;
+ TextFragmentAnchor& operator=(const TextFragmentAnchor&) = delete;
~TextFragmentAnchor() override = default;
bool Invoke() override;
@@ -148,8 +150,6 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
} beforematch_state_ = kNoMatchFound;
Member<TextFragmentAnchorMetrics> metrics_;
-
- DISALLOW_COPY_AND_ASSIGN(TextFragmentAnchor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
index badf5d9a3a2..95db66cce0b 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
@@ -10,6 +10,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/scroll/scroll_enums.mojom-blink.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
@@ -37,7 +38,7 @@ class TextFragmentAnchorMetricsTest : public SimTest {
void RunAsyncMatchingTasks() {
auto* scheduler =
- ThreadScheduler::Current()->GetWebMainThreadSchedulerForTest();
+ blink::scheduler::WebThreadScheduler::MainThreadScheduler();
blink::scheduler::RunIdleTasksForTesting(scheduler,
base::BindOnce([]() {}));
RunPendingTasks();
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
index 8a13df75679..8559bef4176 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
@@ -8,8 +8,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_menu_source_type.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/public_buildflags.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_font_face_descriptors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mouse_event_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
@@ -59,7 +59,7 @@ class TextFragmentAnchorTest : public SimTest {
void RunAsyncMatchingTasks() {
auto* scheduler =
- ThreadScheduler::Current()->GetWebMainThreadSchedulerForTest();
+ blink::scheduler::WebThreadScheduler::MainThreadScheduler();
blink::scheduler::RunIdleTasksForTesting(scheduler,
base::BindOnce([]() {}));
RunPendingTasks();
@@ -94,31 +94,35 @@ class TextFragmentAnchorTest : public SimTest {
0, WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event);
+ WebView().MainFrameWidget()->ProcessInputEventSynchronouslyForTesting(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()), base::DoNothing());
}
- void SimulateTap(int x, int y) {
- WebGestureEvent event(WebInputEvent::Type::kGestureTap,
- WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
- WebGestureDevice::kTouchscreen);
- event.SetPositionInWidget(gfx::PointF(x, y));
- event.SetPositionInScreen(gfx::PointF(x, y));
+ void SimulateRightClick(int x, int y) {
+ WebMouseEvent event(WebInputEvent::Type::kMouseDown, gfx::PointF(x, y),
+ gfx::PointF(x, y), WebPointerProperties::Button::kRight,
+ 0, WebInputEvent::Modifiers::kLeftButtonDown,
+ base::TimeTicks::Now());
event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(event);
+ WebView().MainFrameWidget()->ProcessInputEventSynchronouslyForTesting(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()), base::DoNothing());
+ }
+
+ void SimulateTap(int x, int y) {
+ InjectEvent(WebInputEvent::Type::kTouchStart, x, y);
+ InjectEvent(WebInputEvent::Type::kTouchEnd, x, y);
+ InjectEvent(WebInputEvent::Type::kGestureTapDown, x, y);
+ InjectEvent(WebInputEvent::Type::kGestureTapUnconfirmed, x, y);
+ InjectEvent(WebInputEvent::Type::kGestureShowPress, x, y);
+ InjectEvent(WebInputEvent::Type::kGestureTap, x, y);
}
void LoadAhem() {
scoped_refptr<SharedBuffer> shared_buffer =
test::ReadFromFile(test::CoreTestDataPath("Ahem.ttf"));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* buffer =
MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
DOMArrayBuffer::Create(shared_buffer));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrArrayBufferOrArrayBufferView buffer =
- StringOrArrayBufferOrArrayBufferView::FromArrayBuffer(
- DOMArrayBuffer::Create(shared_buffer));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FontFace* ahem =
FontFace::Create(GetDocument().GetFrame()->DomWindow(), "Ahem", buffer,
FontFaceDescriptors::Create());
@@ -129,6 +133,41 @@ class TextFragmentAnchorTest : public SimTest {
FontFaceSetDocument::From(GetDocument())
->addForBinding(script_state, ahem, exception_state);
}
+
+ private:
+ void InjectEvent(WebInputEvent::Type type, int x, int y) {
+ if (WebInputEvent::IsGestureEventType(type)) {
+ WebGestureEvent event(type, WebInputEvent::kNoModifiers,
+ base::TimeTicks::Now(),
+ WebGestureDevice::kTouchscreen);
+ event.SetPositionInWidget(gfx::PointF(x, y));
+ event.SetPositionInScreen(gfx::PointF(x, y));
+ event.SetFrameScale(1);
+
+ WebView().MainFrameWidget()->ProcessInputEventSynchronouslyForTesting(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()), base::DoNothing());
+ } else if (WebInputEvent::IsTouchEventType(type)) {
+ WebTouchEvent event(type, WebInputEvent::kNoModifiers,
+ base::TimeTicks::Now());
+ event.SetFrameScale(1);
+
+ WebPointerProperties pointer(0, WebPointerProperties::PointerType::kTouch,
+ WebPointerProperties::Button::kNoButton,
+ gfx::PointF(x, y), gfx::PointF(x, y));
+ event.touches[0] = pointer;
+ if (type == WebInputEvent::Type::kTouchStart)
+ event.touches[0].state = WebTouchPoint::State::kStatePressed;
+ else if (type == WebInputEvent::Type::kTouchEnd)
+ event.touches[0].state = WebTouchPoint::State::kStateReleased;
+
+ WebView().MainFrameWidget()->ProcessInputEventSynchronouslyForTesting(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()), base::DoNothing());
+ WebView().MainFrameWidget()->DispatchBufferedTouchEvents();
+ } else {
+ NOTREACHED() << "Only needed to support Gesture/Touch until now. "
+ "Implement others if new modality is needed.";
+ }
+ }
};
// Basic test case, ensure we scroll the matching text into view.
@@ -2563,6 +2602,76 @@ TEST_F(TextFragmentAnchorTest,
}
#endif // BUILDFLAG(ENABLE_UNHANDLED_TAP)
+TEST_F(TextFragmentAnchorTest, TapOpeningContextMenuWithDirtyLifecycleNoCrash) {
+ ScopedTextFragmentTapOpensContextMenuForTest tap_opens_context_menu(true);
+ base::test::ScopedFeatureList feature_list_;
+ feature_list_.InitAndEnableFeature(
+ shared_highlighting::kSharedHighlightingV2);
+
+ SimRequest request(
+ "https://example.com/"
+ "test.html#:~:text=This%20is%20just%20example",
+ "text/html");
+ LoadURL(
+ "https://example.com/"
+ "test.html#:~:text=This%20is%20just%20example");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <style>
+ .content {
+ width: 1000px;
+ height: 2000px;
+ background-color: silver;
+ }
+ </style>
+ <script>
+ // Dirty lifecycle inside the click event.
+ addEventListener('click', () => {
+ document.body.style.width = '500px';
+ });
+ // This prevents calling HandleMouseReleaseEvent which has an
+ // UpdateLifecycle call inside it but it also prevents showing the
+ // context menu.
+ addEventListener('mouseup', (e) => { e.preventDefault(); });
+ </script>
+ </head>
+
+ <body>
+ This is just example text that will wrap.
+ <div class="content"></div>
+ </body>
+ </html>
+ )HTML");
+ RunAsyncMatchingTasks();
+ ContextMenuAllowedScope context_menu_allowed_scope;
+
+ Compositor().BeginFrame();
+
+ EXPECT_FALSE(GetDocument()
+ .GetPage()
+ ->GetContextMenuController()
+ .ContextMenuNodeForFrame(GetDocument().GetFrame()));
+
+ Node* first_paragraph = GetDocument().body()->firstChild();
+ const auto& start = Position(first_paragraph, 0);
+ const auto& end = Position(first_paragraph, 27);
+ ASSERT_EQ("This is just example", PlainText(EphemeralRange(start, end)));
+
+ Range* range = CreateRange(EphemeralRange(start, end));
+
+ IntPoint tap_point = range->BoundingBox().Center();
+ SimulateTap(tap_point.X(), tap_point.Y());
+
+ // Expect that we won't see the context menu because we preventDefaulted the
+ // mouseup but this test passes if it doesn't crash.
+ EXPECT_FALSE(GetDocument()
+ .GetPage()
+ ->GetContextMenuController()
+ .ContextMenuNodeForFrame(GetDocument().GetFrame()));
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.cc
index 71aad18008f..eca0dec6587 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.cc
@@ -4,15 +4,27 @@
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+#include "components/shared_highlighting/core/common/disabled_sites.h"
#include "components/shared_highlighting/core/common/shared_highlighting_features.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.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/position_with_affinity.h"
+#include "third_party/blink/renderer/core/editing/range_in_flat_tree.h"
+#include "third_party/blink/renderer/core/editing/selection_editor.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/core/page/scrolling/text_fragment_anchor.h"
+namespace {
+bool PreemptiveGenerationEnabled() {
+ return base::FeatureList::IsEnabled(
+ shared_highlighting::kPreemptiveLinkToTextGeneration);
+}
+} // namespace
+
namespace blink {
TextFragmentHandler::TextFragmentHandler(LocalFrame* main_frame)
@@ -28,17 +40,35 @@ void TextFragmentHandler::BindTextFragmentReceiver(
blink::TaskType::kInternalDefault));
}
-TextFragmentSelectorGenerator*
-TextFragmentHandler::GetTextFragmentSelectorGenerator() {
- return text_fragment_selector_generator_;
-}
-
void TextFragmentHandler::Cancel() {
- GetTextFragmentSelectorGenerator()->Cancel();
+ GetTextFragmentSelectorGenerator()->Reset();
}
void TextFragmentHandler::RequestSelector(RequestSelectorCallback callback) {
- GetTextFragmentSelectorGenerator()->RequestSelector(std::move(callback));
+ DCHECK(shared_highlighting::ShouldOfferLinkToText(
+ GetFrame()->GetDocument()->Url()));
+ DCHECK(!GetFrame()->Selection().SelectedText().IsEmpty());
+
+ if (PreemptiveGenerationEnabled()) {
+ GetTextFragmentSelectorGenerator()->RecordSelectorStateUma();
+
+ selector_requested_before_ready_ =
+ !preemptive_generation_result_.has_value();
+ response_callback_ = std::move(callback);
+
+ // If preemptive link generation is enabled, the generator would have
+ // already been invoked when the selection was updated in
+ // StartPreemptiveGenerationIfNeeded. If that generation finished simply
+ // respond with the result. Otherwise, the response callback is stored so
+ // that we reply on completion.
+ if (!selector_requested_before_ready_.value())
+ InvokeReplyCallback(preemptive_generation_result_.value());
+ } else {
+ DCHECK(!preemptive_generation_result_.has_value());
+ DCHECK(!response_callback_);
+ response_callback_ = std::move(callback);
+ StartGeneratingForCurrentSelection();
+ }
}
void TextFragmentHandler::GetExistingSelectors(
@@ -76,6 +106,12 @@ bool TextFragmentHandler::IsOverTextFragment(HitTestResult result) {
return false;
}
+ // Tree should be clean before accessing the position.
+ // |HitTestResult::GetPosition| calls |PositionForPoint()| which requires
+ // |kPrePaintClean|.
+ DCHECK_GE(result.InnerNodeFrame()->GetDocument()->Lifecycle().GetState(),
+ DocumentLifecycle::kPrePaintClean);
+
DocumentMarkerController& marker_controller =
result.InnerNodeFrame()->GetDocument()->Markers();
PositionWithAffinity pos_with_affinity = result.GetPosition();
@@ -128,19 +164,101 @@ void TextFragmentHandler::ExtractFirstFragmentRect(
PhysicalRect bounding_box(
ComputeTextRect(finder->FirstMatch()->ToEphemeralRange()));
rect_in_viewport =
- GetTextFragmentSelectorGenerator()->GetFrame()->View()->FrameToViewport(
- EnclosingIntRect(bounding_box));
+ GetFrame()->View()->FrameToViewport(EnclosingIntRect(bounding_box));
break;
}
std::move(callback).Run(gfx::Rect(rect_in_viewport));
}
+void TextFragmentHandler::DidFinishSelectorGeneration(
+ const TextFragmentSelector& selector) {
+ DCHECK(!preemptive_generation_result_.has_value());
+
+ if (response_callback_) {
+ InvokeReplyCallback(selector);
+ } else {
+ // If we don't have a callback yet, it's because we started generating
+ // preemptively. We'll store the result so that when the selector actually
+ // is requested we can simply use the stored result.
+ DCHECK(PreemptiveGenerationEnabled());
+ preemptive_generation_result_.emplace(selector);
+ }
+}
+
+void TextFragmentHandler::StartGeneratingForCurrentSelection() {
+ if (GetFrame()->Selection().SelectedText().IsEmpty())
+ return;
+
+ VisibleSelectionInFlatTree selection =
+ GetFrame()->Selection().ComputeVisibleSelectionInFlatTree();
+ EphemeralRangeInFlatTree selection_range(selection.Start(), selection.End());
+ RangeInFlatTree* current_selection_range =
+ MakeGarbageCollected<RangeInFlatTree>(selection_range.StartPosition(),
+ selection_range.EndPosition());
+ GetTextFragmentSelectorGenerator()->Generate(
+ *current_selection_range,
+ WTF::Bind(&TextFragmentHandler::DidFinishSelectorGeneration,
+ WrapWeakPersistent(this)));
+}
+
+void TextFragmentHandler::RecordPreemptiveGenerationMetrics(
+ const TextFragmentSelector& selector) {
+ DCHECK(PreemptiveGenerationEnabled());
+ DCHECK(selector_requested_before_ready_.has_value());
+
+ bool success =
+ selector.Type() != TextFragmentSelector::SelectorType::kInvalid;
+
+ std::string uma_prefix = "SharedHighlights.LinkGenerated";
+ if (selector_requested_before_ready_.value()) {
+ uma_prefix = base::StrCat({uma_prefix, ".RequestedBeforeReady"});
+ } else {
+ uma_prefix = base::StrCat({uma_prefix, ".RequestedAfterReady"});
+ }
+ base::UmaHistogramBoolean(uma_prefix, success);
+
+ if (!success) {
+ absl::optional<shared_highlighting::LinkGenerationError> optional_error =
+ GetTextFragmentSelectorGenerator()->GetError();
+ shared_highlighting::LinkGenerationError error =
+ optional_error.has_value()
+ ? optional_error.value()
+ : shared_highlighting::LinkGenerationError::kUnknown;
+ base::UmaHistogramEnumeration(
+ "SharedHighlights.LinkGenerated.Error.Requested", error);
+ }
+}
+
+void TextFragmentHandler::StartPreemptiveGenerationIfNeeded() {
+ if (PreemptiveGenerationEnabled() &&
+ shared_highlighting::ShouldOfferLinkToText(
+ GetFrame()->GetDocument()->Url())) {
+ preemptive_generation_result_.reset();
+ StartGeneratingForCurrentSelection();
+ }
+}
+
void TextFragmentHandler::Trace(Visitor* visitor) const {
visitor->Trace(text_fragment_selector_generator_);
visitor->Trace(selector_producer_);
}
+void TextFragmentHandler::DidDetachDocumentOrFrame() {
+ // Clear out any state in the generator and cancel pending tasks so they
+ // don't run after frame detachment.
+ GetTextFragmentSelectorGenerator()->Reset();
+}
+
+void TextFragmentHandler::InvokeReplyCallback(
+ const TextFragmentSelector& selector) {
+ if (PreemptiveGenerationEnabled())
+ RecordPreemptiveGenerationMetrics(selector);
+
+ DCHECK(response_callback_);
+ std::move(response_callback_).Run(selector.ToString());
+}
+
TextFragmentAnchor* TextFragmentHandler::GetTextFragmentAnchor() {
FragmentAnchor* fragmentAnchor = GetTextFragmentSelectorGenerator()
->GetFrame()
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h
index 82ec06fe54e..6a74f841826 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h
@@ -6,68 +6,99 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_HANDLER_H_
#include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink.h"
-#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
namespace blink {
class LocalFrame;
-
-// TextFragmentHandler is responsible for handling text fragment operations
-// on a LocalFrame. Generating text fragment selectors for a selection is
-// delegated to TextFragmentSelectorGenerator.
+class TextFragmentAnchor;
+
+// TextFragmentHandler is responsible for handling requests from the
+// browser-side link-to-text/shared-highlighting feature. It is responsible for
+// generating a text fragment URL based on the current selection as well as
+// collecting information about and modifying text fragments on the current
+// page. This class is registered on and owned by the frame that interacts with
+// the link-to-text/shared-highlighting feature.
class CORE_EXPORT TextFragmentHandler final
: public GarbageCollected<TextFragmentHandler>,
public blink::mojom::blink::TextFragmentReceiver {
public:
explicit TextFragmentHandler(LocalFrame* main_frame);
+ TextFragmentHandler(const TextFragmentHandler&) = delete;
+ TextFragmentHandler& operator=(const TextFragmentHandler&) = delete;
- void BindTextFragmentReceiver(
- mojo::PendingReceiver<mojom::blink::TextFragmentReceiver> producer);
+ // Determine if |result| represents a click on an existing highlight.
+ static bool IsOverTextFragment(HitTestResult result);
- // Cancel any pending selector requests.
+ // mojom::blink::TextFragmentReceiver interface
void Cancel() override;
-
- // Requests selector for current selection.
void RequestSelector(RequestSelectorCallback callback) override;
-
- // Requests selectors for all existing highlights on the page.
void GetExistingSelectors(GetExistingSelectorsCallback callback) override;
-
- // Remove all text fragments from the current frame.
void RemoveFragments() override;
-
- // Determine if |result| represents a click on an existing highlight.
- static bool IsOverTextFragment(HitTestResult result);
-
- // Retrieves the text fragments matches from the fragment directive.
void ExtractTextFragmentsMatches(
ExtractTextFragmentsMatchesCallback callback) override;
-
- // Request the bounding rectangle, relative to the viewport, of the first
- // found match. It will accept an empty rectangle if no matches are found.
void ExtractFirstFragmentRect(
ExtractFirstFragmentRectCallback callback) override;
+ // This starts the preemptive generation on the current selection if it is not
+ // empty.
+ void StartPreemptiveGenerationIfNeeded();
+
+ void BindTextFragmentReceiver(
+ mojo::PendingReceiver<mojom::blink::TextFragmentReceiver> producer);
+
void Trace(Visitor*) const;
- TextFragmentSelectorGenerator* GetTextFragmentSelectorGenerator();
+ TextFragmentSelectorGenerator* GetTextFragmentSelectorGenerator() {
+ return text_fragment_selector_generator_;
+ }
+
+ void DidDetachDocumentOrFrame();
private:
+ // The callback passed to TextFragmentSelectorGenerator that will receive the
+ // result.
+ void DidFinishSelectorGeneration(const TextFragmentSelector& selector);
+
+ // This starts running the generator over the current selection.
+ // The result will be returned by invoking DidFinishSelectorGeneration().
+ void StartGeneratingForCurrentSelection();
+
+ void RecordPreemptiveGenerationMetrics(const TextFragmentSelector& selector);
+
+ // Called to reply to the client's RequestSelector call with the result.
+ void InvokeReplyCallback(const TextFragmentSelector& selector);
+
+ TextFragmentAnchor* GetTextFragmentAnchor();
+
+ LocalFrame* GetFrame() {
+ return GetTextFragmentSelectorGenerator()->GetFrame();
+ }
+
// Class responsible for generating text fragment selectors for the current
// selection.
Member<TextFragmentSelectorGenerator> text_fragment_selector_generator_;
+ // The result of preemptively generating on selection changes will be stored
+ // in this member when completed. Used only in preemptive link generation
+ // mode.
+ absl::optional<TextFragmentSelector> preemptive_generation_result_;
+
+ // Reports whether |RequestSelector| was called before or after selector was
+ // ready. Used only in preemptive link generation mode.
+ absl::optional<bool> selector_requested_before_ready_;
+
+ // This will hold the reply callback to the RequestSelector mojo call. This
+ // will be invoked in InvokeReplyCallback to send the reply back to the
+ // browser.
+ RequestSelectorCallback response_callback_;
+
// Used for communication between |TextFragmentHandler| in renderer
// and |TextFragmentSelectorClientImpl| in browser.
HeapMojoReceiver<blink::mojom::blink::TextFragmentReceiver,
TextFragmentHandler>
selector_producer_{this, nullptr};
-
- DISALLOW_COPY_AND_ASSIGN(TextFragmentHandler);
-
- TextFragmentAnchor* GetTextFragmentAnchor();
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler_test.cc
index c46686b496e..d6b1c0a235d 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_handler_test.cc
@@ -6,18 +6,22 @@
#include <gtest/gtest.h>
+#include "base/feature_list.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/shared_highlighting/core/common/shared_highlighting_features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer_or_array_buffer_view.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_font_face_descriptors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mouse_event_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
#include "third_party/blink/renderer/core/css/css_font_face.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/html/html_frame_owner_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/platform/testing/unit_test_helpers.h"
@@ -28,21 +32,73 @@ namespace {
using test::RunPendingTasks;
-class TextFragmentHandlerTest : public SimTest {
+class TextFragmentHandlerTest : public SimTest,
+ public ::testing::WithParamInterface<bool> {
public:
void SetUp() override {
SimTest::SetUp();
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
+
+ std::vector<base::Feature> enabled;
+ std::vector<base::Feature> disabled;
+
+ enabled.push_back(shared_highlighting::kSharedHighlightingV2);
+
+ preemptive_generation_enabled_ = GetParam();
+ if (preemptive_generation_enabled_)
+ enabled.push_back(shared_highlighting::kPreemptiveLinkToTextGeneration);
+ else
+ disabled.push_back(shared_highlighting::kPreemptiveLinkToTextGeneration);
+
+ feature_list_.InitWithFeatures(enabled, disabled);
+ }
+
+ void BeginEmptyFrame() {
+ // If a test case doesn't find a match and therefore doesn't schedule the
+ // beforematch event, we should still render a second frame as if we did
+ // schedule the event to retain test coverage.
+ // When the beforematch event is not scheduled, a DCHECK will fail on
+ // BeginFrame() because no event was scheduled, so we schedule an empty task
+ // here.
+ GetDocument().EnqueueAnimationFrameTask(WTF::Bind([]() {}));
+ Compositor().BeginFrame();
}
void RunAsyncMatchingTasks() {
auto* scheduler =
- ThreadScheduler::Current()->GetWebMainThreadSchedulerForTest();
+ blink::scheduler::WebThreadScheduler::MainThreadScheduler();
blink::scheduler::RunIdleTasksForTesting(scheduler,
base::BindOnce([]() {}));
RunPendingTasks();
}
+ void SetSelection(const Position& start, const Position& end) {
+ GetDocument().GetFrame()->Selection().SetSelection(
+ SelectionInDOMTree::Builder().SetBaseAndExtent(start, end).Build(),
+ SetSelectionOptions());
+ }
+
+ String SelectThenRequestSelector(const Position& start, const Position& end) {
+ SetSelection(start, end);
+
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+
+ bool callback_called = false;
+ String selector;
+ auto lambda = [](bool& callback_called, String& selector,
+ const String& generated_selector) {
+ selector = generated_selector;
+ callback_called = true;
+ };
+ auto callback =
+ WTF::Bind(lambda, std::ref(callback_called), std::ref(selector));
+ GetTextFragmentHandler().RequestSelector(std::move(callback));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(callback_called);
+ return selector;
+ }
+
Vector<String> ExtractTextFragmentsMatches() {
bool callback_called = false;
Vector<String> target_texts;
@@ -54,10 +110,7 @@ class TextFragmentHandlerTest : public SimTest {
auto callback =
WTF::Bind(lambda, std::ref(callback_called), std::ref(target_texts));
- GetDocument()
- .GetFrame()
- ->GetTextFragmentHandler()
- ->ExtractTextFragmentsMatches(std::move(callback));
+ GetTextFragmentHandler().ExtractTextFragmentsMatches(std::move(callback));
EXPECT_TRUE(callback_called);
return target_texts;
@@ -74,10 +127,7 @@ class TextFragmentHandlerTest : public SimTest {
auto callback = WTF::Bind(lambda, std::ref(callback_called),
std::ref(text_fragment_rect));
- GetDocument()
- .GetFrame()
- ->GetTextFragmentHandler()
- ->ExtractFirstFragmentRect(std::move(callback));
+ GetTextFragmentHandler().ExtractFirstFragmentRect(std::move(callback));
EXPECT_TRUE(callback_called);
return text_fragment_rect;
@@ -86,15 +136,9 @@ class TextFragmentHandlerTest : public SimTest {
void LoadAhem() {
scoped_refptr<SharedBuffer> shared_buffer =
test::ReadFromFile(test::CoreTestDataPath("Ahem.ttf"));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* buffer =
MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
DOMArrayBuffer::Create(shared_buffer));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrArrayBufferOrArrayBufferView buffer =
- StringOrArrayBufferOrArrayBufferView::FromArrayBuffer(
- DOMArrayBuffer::Create(shared_buffer));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FontFace* ahem =
FontFace::Create(GetDocument().GetExecutionContext(), "Ahem", buffer,
FontFaceDescriptors::Create());
@@ -105,12 +149,60 @@ class TextFragmentHandlerTest : public SimTest {
FontFaceSetDocument::From(GetDocument())
->addForBinding(script_state, ahem, exception_state);
}
-};
-TEST_F(TextFragmentHandlerTest, RemoveTextFragments) {
+ void VerifyPreemptiveGenerationMetrics(bool success) {
+ if (!preemptive_generation_enabled_) {
+ histogram_tester_.ExpectTotalCount(
+ "SharedHighlights.LinkGenerated.Error.Requested", 0);
+ histogram_tester_.ExpectTotalCount(
+ "SharedHighlights.LinkGenerated.RequestedAfterReady", 0);
+ histogram_tester_.ExpectTotalCount(
+ "SharedHighlights.LinkGenerated.RequestedBeforeReady", 0);
+ } else {
+ EXPECT_EQ(
+ 1u, histogram_tester_
+ .GetAllSamples(
+ "SharedHighlights.LinkGenerated.RequestedAfterReady")
+ .size() +
+ histogram_tester_
+ .GetAllSamples(
+ "SharedHighlights.LinkGenerated.RequestedBeforeReady")
+ .size());
+
+ if (!success) {
+ histogram_tester_.ExpectTotalCount(
+ "SharedHighlights.LinkGenerated.Error.Requested", 1);
+ } else {
+ histogram_tester_.ExpectTotalCount(
+ "SharedHighlights.LinkGenerated.Error.Requested", 0);
+ }
+ }
+
+ // Check async task metrics.
+ EXPECT_LT(0u, histogram_tester_
+ .GetAllSamples("SharedHighlights.AsyncTask.Iterations")
+ .size());
+ EXPECT_LT(0u,
+ histogram_tester_
+ .GetAllSamples("SharedHighlights.AsyncTask.SearchDuration")
+ .size());
+ }
+
+ TextFragmentHandler& GetTextFragmentHandler() {
+ return *GetDocument().GetFrame()->GetTextFragmentHandler();
+ }
+
+ bool HasTextFragmentHandler(LocalFrame* frame) {
+ return frame->GetTextFragmentHandler();
+ }
+
+ protected:
+ base::HistogramTester histogram_tester_;
base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+ bool preemptive_generation_enabled_;
+};
+
+TEST_P(TextFragmentHandlerTest, RemoveTextFragments) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=test%20page&text=more%20text",
@@ -144,7 +236,7 @@ TEST_F(TextFragmentHandlerTest, RemoveTextFragments) {
EXPECT_EQ(2u, GetDocument().Markers().Markers().size());
- GetDocument().GetFrame()->GetTextFragmentHandler()->RemoveFragments();
+ GetTextFragmentHandler().RemoveFragments();
EXPECT_EQ(0u, GetDocument().Markers().Markers().size());
@@ -152,11 +244,8 @@ TEST_F(TextFragmentHandlerTest, RemoveTextFragments) {
EXPECT_FALSE(GetDocument().View()->GetFragmentAnchor());
}
-TEST_F(TextFragmentHandlerTest,
+TEST_P(TextFragmentHandlerTest,
ExtractTextFragmentWithWithMultipleTextFragments) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
SimRequest request(
"https://example.com/"
"test.html#:~:text=test%20page&text=more%20text",
@@ -195,10 +284,7 @@ TEST_F(TextFragmentHandlerTest,
EXPECT_EQ("more text", target_texts[1]);
}
-TEST_F(TextFragmentHandlerTest, ExtractTextFragmentWithNoMatch) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, ExtractTextFragmentWithNoMatch) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=not%20on%20the%20page",
@@ -234,10 +320,7 @@ TEST_F(TextFragmentHandlerTest, ExtractTextFragmentWithNoMatch) {
EXPECT_EQ(0u, target_texts.size());
}
-TEST_F(TextFragmentHandlerTest, ExtractTextFragmentWithRange) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, ExtractTextFragmentWithRange) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=This,text",
@@ -274,10 +357,7 @@ TEST_F(TextFragmentHandlerTest, ExtractTextFragmentWithRange) {
EXPECT_EQ("This is a test page, with some more text", target_texts[0]);
}
-TEST_F(TextFragmentHandlerTest, ExtractTextFragmentWithRangeAndContext) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, ExtractTextFragmentWithRangeAndContext) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=this,is&text=a-,test,page&text=with,some,-content&"
@@ -308,10 +388,7 @@ TEST_F(TextFragmentHandlerTest, ExtractTextFragmentWithRangeAndContext) {
EXPECT_EQ("nothing at", target_texts[3]);
}
-TEST_F(TextFragmentHandlerTest, ExtractFirstTextFragmentRect) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, ExtractFirstTextFragmentRect) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=This,page",
@@ -349,10 +426,7 @@ TEST_F(TextFragmentHandlerTest, ExtractFirstTextFragmentRect) {
EXPECT_EQ(expected_rect.ToString(), text_fragment_rect.ToString());
}
-TEST_F(TextFragmentHandlerTest, ExtractFirstTextFragmentRectScroll) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, ExtractFirstTextFragmentRectScroll) {
// Android settings to correctly extract the rect when the page is loaded
// zoomed in
WebView().GetPage()->GetSettings().SetViewportEnabled(true);
@@ -401,10 +475,7 @@ TEST_F(TextFragmentHandlerTest, ExtractFirstTextFragmentRectScroll) {
EXPECT_EQ(expected_rect.ToString(), text_fragment_rect.ToString());
}
-TEST_F(TextFragmentHandlerTest, ExtractFirstTextFragmentRectMultipleHighlight) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, ExtractFirstTextFragmentRectMultipleHighlight) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=test%20page&text=more%20text",
@@ -453,11 +524,8 @@ TEST_F(TextFragmentHandlerTest, ExtractFirstTextFragmentRectMultipleHighlight) {
EXPECT_EQ(expected_rect.ToString(), text_fragment_rect.ToString());
}
-TEST_F(TextFragmentHandlerTest,
+TEST_P(TextFragmentHandlerTest,
ExtractFirstTextFragmentRectMultipleHighlightWithNoFoundText) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
SimRequest request(
"https://example.com/"
"test.html#:~:text=fake&text=test%20page",
@@ -505,10 +573,7 @@ TEST_F(TextFragmentHandlerTest,
EXPECT_EQ(expected_rect.ToString(), text_fragment_rect.ToString());
}
-TEST_F(TextFragmentHandlerTest, RejectExtractFirstTextFragmentRect) {
- base::test::ScopedFeatureList feature_list_;
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kSharedHighlightingV2);
+TEST_P(TextFragmentHandlerTest, RejectExtractFirstTextFragmentRect) {
SimRequest request(
"https://example.com/"
"test.html#:~:text=not%20on%20the%20page",
@@ -546,6 +611,331 @@ TEST_F(TextFragmentHandlerTest, RejectExtractFirstTextFragmentRect) {
EXPECT_TRUE(text_fragment_rect.IsEmpty());
}
+// Checks that the selector is preemptively generated.
+TEST_P(TextFragmentHandlerTest, CheckPreemptiveGeneration) {
+ if (!preemptive_generation_enabled_)
+ return;
+
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <p id='first'>First paragraph</p>
+ )HTML");
+
+ Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
+ const auto& selected_start = Position(first_paragraph, 0);
+ const auto& selected_end = Position(first_paragraph, 5);
+ ASSERT_EQ("First", PlainText(EphemeralRange(selected_start, selected_end)));
+
+ SetSelection(selected_start, selected_end);
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+
+ base::RunLoop().RunUntilIdle();
+
+ histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated", 1);
+ histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error", 0);
+}
+
+// When URL is blocklisted, the selector shouldn't be preemptively generated.
+TEST_P(TextFragmentHandlerTest, CheckNoPreemptiveGenerationBlocklist) {
+ if (!preemptive_generation_enabled_)
+ return;
+
+ SimRequest request("https://instagram.com/test.html", "text/html");
+ LoadURL("https://instagram.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <p id='first'>First paragraph</p>
+ )HTML");
+
+ Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
+ const auto& selected_start = Position(first_paragraph, 0);
+ const auto& selected_end = Position(first_paragraph, 5);
+ ASSERT_EQ("First", PlainText(EphemeralRange(selected_start, selected_end)));
+
+ SetSelection(selected_start, selected_end);
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+
+ base::RunLoop().RunUntilIdle();
+
+ histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated", 0);
+ histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error", 0);
+}
+
+// Check that selector is not generated for editable text.
+TEST_P(TextFragmentHandlerTest, CheckNoPreemptiveGenerationEditable) {
+ if (!preemptive_generation_enabled_)
+ return;
+
+ SimRequest request("https://instagram.com/test.html", "text/html");
+ LoadURL("https://instagram.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <input type="text" id="input" value="default text in input">
+ )HTML");
+
+ Node* input_text =
+ FlatTreeTraversal::Next(*GetDocument().getElementById("input"))
+ ->firstChild();
+ const auto& selected_start = Position(input_text, 0);
+ const auto& selected_end = Position(input_text, 12);
+ ASSERT_EQ("default text",
+ PlainText(EphemeralRange(selected_start, selected_end)));
+
+ SetSelection(selected_start, selected_end);
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+
+ base::RunLoop().RunUntilIdle();
+
+ histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated", 0);
+ histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error", 0);
+}
+
+// TODO(crbug.com/1192047): Update the test to better reflect the real repro
+// steps. Test case for crash in crbug.com/1190137. When selector is requested
+// after callback is set and unused.
+TEST_P(TextFragmentHandlerTest, SecondGenerationCrash) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <p id='p'>First paragraph text</p>
+ )HTML");
+ GetDocument().UpdateStyleAndLayoutTree();
+ Node* p = GetDocument().getElementById("p");
+ const auto& start = Position(p->lastChild(), 0);
+ const auto& end = Position(p->lastChild(), 15);
+ ASSERT_EQ("First paragraph", PlainText(EphemeralRange(start, end)));
+ SetSelection(start, end);
+
+ auto callback = WTF::Bind([](const TextFragmentSelector& selector) {});
+ GetDocument()
+ .GetFrame()
+ ->GetTextFragmentHandler()
+ ->GetTextFragmentSelectorGenerator()
+ ->SetCallbackForTesting(std::move(callback));
+
+ // This shouldn't crash.
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+ base::RunLoop().RunUntilIdle();
+}
+
+// Verifies metrics for preemptive generation are correctly recorded when the
+// selector is successfully generated.
+TEST_P(TextFragmentHandlerTest, CheckMetrics_Success) {
+ base::test::ScopedFeatureList feature_list;
+ // Basic exact selector case.
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <div>Test page</div>
+ <p id='first'>First paragraph text that is longer than 20 chars</p>
+ <p id='second'>Second paragraph text</p>
+ )HTML");
+ Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
+ const auto& selected_start = Position(first_paragraph, 0);
+ const auto& selected_end = Position(first_paragraph, 28);
+ ASSERT_EQ("First paragraph text that is",
+ PlainText(EphemeralRange(selected_start, selected_end)));
+
+ String selector = SelectThenRequestSelector(selected_start, selected_end);
+ EXPECT_EQ(selector, "First%20paragraph%20text%20that%20is");
+ VerifyPreemptiveGenerationMetrics(true);
+}
+
+// Verifies metrics for preemptive generation are correctly recorded when the
+// selector request fails, in this case, because the context limit is reached.
+TEST_P(TextFragmentHandlerTest, CheckMetrics_Failure) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <div>Test page</div>
+ <p id='first'>First paragraph prefix one two three four five six seven
+ eight nine ten to not unique snippet of text followed by suffix</p>
+ <p id='second'>Second paragraph prefix one two three four five six seven
+ eight nine ten to not unique snippet of text followed by suffix</p>
+ )HTML");
+ Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
+ const auto& selected_start = Position(first_paragraph, 80);
+ const auto& selected_end = Position(first_paragraph, 106);
+ ASSERT_EQ("not unique snippet of text",
+ PlainText(EphemeralRange(selected_start, selected_end)));
+ String selector = SelectThenRequestSelector(selected_start, selected_end);
+ EXPECT_EQ(selector, "");
+ VerifyPreemptiveGenerationMetrics(false);
+}
+
+TEST_P(TextFragmentHandlerTest,
+ ShouldCreateTextFragmentHandlerAndRemoveHighlightForIframes) {
+ base::test::ScopedFeatureList feature_list_;
+ feature_list_.InitAndEnableFeature(
+ shared_highlighting::kSharedHighlightingAmp);
+ SimRequest main_request("https://example.com/test.html", "text/html");
+ SimRequest child_request("https://example.com/child.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ main_request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <iframe id="iframe" src="child.html"></iframe>
+ )HTML");
+
+ child_request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ p {
+ margin-top: 1000px;
+ }
+ </style>
+ <p>
+ test
+ </p>
+ <script>
+ window.location.hash = ':~:text=test';
+ </script>
+ )HTML");
+ RunAsyncMatchingTasks();
+
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
+ BeginEmptyFrame();
+
+ Element* iframe = GetDocument().getElementById("iframe");
+ auto* child_frame =
+ To<LocalFrame>(To<HTMLFrameOwnerElement>(iframe)->ContentFrame());
+
+ EXPECT_EQ(1u, child_frame->GetDocument()->Markers().Markers().size());
+ EXPECT_FALSE(HasTextFragmentHandler(child_frame));
+
+ child_frame->CreateTextFragmentHandler();
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+
+ mojo::Remote<mojom::blink::TextFragmentReceiver> remote;
+ EXPECT_FALSE(remote.is_bound());
+ child_frame->BindTextFragmentReceiver(remote.BindNewPipeAndPassReceiver());
+
+ EXPECT_TRUE(HasTextFragmentHandler(child_frame));
+ EXPECT_TRUE(remote.is_bound());
+ remote.get()->RemoveFragments();
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, child_frame->GetDocument()->Markers().Markers().size());
+
+ // Ensure the fragment is uninstalled
+ EXPECT_FALSE(child_frame->GetDocument()->View()->GetFragmentAnchor());
+}
+
+TEST_P(TextFragmentHandlerTest,
+ ShouldCreateTextFragmentHandlerAndRemoveHighlight) {
+ SimRequest request(
+ "https://example.com/"
+ "test.html#:~:text=test%20page&text=more%20text",
+ "text/html");
+ LoadURL(
+ "https://example.com/"
+ "test.html#:~:text=test%20page&text=more%20text");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ body {
+ height: 2200px;
+ }
+ #first {
+ position: absolute;
+ top: 1000px;
+ }
+ #second {
+ position: absolute;
+ top: 2000px;
+ }
+ </style>
+ <p id="first">This is a test page</p>
+ <p id="second">With some more text</p>
+ )HTML");
+ RunAsyncMatchingTasks();
+
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
+ Compositor().BeginFrame();
+
+ EXPECT_EQ(2u, GetDocument().Markers().Markers().size());
+ EXPECT_TRUE(HasTextFragmentHandler(GetDocument().GetFrame()));
+
+ mojo::Remote<mojom::blink::TextFragmentReceiver> remote;
+ EXPECT_FALSE(remote.is_bound());
+ GetDocument().GetFrame()->BindTextFragmentReceiver(
+ remote.BindNewPipeAndPassReceiver());
+
+ EXPECT_TRUE(HasTextFragmentHandler(GetDocument().GetFrame()));
+ EXPECT_TRUE(remote.is_bound());
+ remote.get()->RemoveFragments();
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, GetDocument().Markers().Markers().size());
+
+ // Ensure the fragment is uninstalled
+ EXPECT_FALSE(GetDocument().View()->GetFragmentAnchor());
+}
+
+TEST_P(TextFragmentHandlerTest,
+ ShouldCreateTextFragmentHandlerAndRequestSelector) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <div>Test page</div>
+ <p id='first'>First paragraph text that is longer than 20 chars</p>
+ <p id='second'>Second paragraph text</p>
+ )HTML");
+
+ Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
+ const auto& selected_start = Position(first_paragraph, 0);
+ const auto& selected_end = Position(first_paragraph, 28);
+ ASSERT_EQ("First paragraph text that is",
+ PlainText(EphemeralRange(selected_start, selected_end)));
+
+ SetSelection(selected_start, selected_end);
+
+ mojo::Remote<mojom::blink::TextFragmentReceiver> remote;
+ EXPECT_TRUE(HasTextFragmentHandler(GetDocument().GetFrame()));
+ EXPECT_FALSE(remote.is_bound());
+
+ GetTextFragmentHandler().StartPreemptiveGenerationIfNeeded();
+ GetDocument().GetFrame()->BindTextFragmentReceiver(
+ remote.BindNewPipeAndPassReceiver());
+
+ EXPECT_TRUE(HasTextFragmentHandler(GetDocument().GetFrame()));
+ EXPECT_TRUE(remote.is_bound());
+
+ bool callback_called = false;
+ String selector;
+ auto lambda = [](bool& callback_called, String& selector,
+ const String& generated_selector) {
+ selector = generated_selector;
+ callback_called = true;
+ };
+ auto callback =
+ WTF::Bind(lambda, std::ref(callback_called), std::ref(selector));
+ remote->RequestSelector(std::move(callback));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(callback_called);
+
+ EXPECT_EQ(selector, "First%20paragraph%20text%20that%20is");
+ VerifyPreemptiveGenerationMetrics(true);
+}
+
+struct PreemptiveLinkGenerationTestPassToString {
+ std::string operator()(const testing::TestParamInfo<bool> b) const {
+ return b.param ? "Preemptive" : "NonPreemptive";
+ }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+ TextFragmentHandlerTest,
+ ::testing::Bool(),
+ PreemptiveLinkGenerationTestPassToString());
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc
index 787fb1bc3b0..4c6d208aec2 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc
@@ -16,8 +16,8 @@ namespace {
// return an empty string to indicate no prefix/suffix was specified or it
// was malformed and should be ignored.
String ExtractPrefix(String* target_text) {
- size_t comma_pos = target_text->find(',');
- size_t hyphen_pos = target_text->find('-');
+ wtf_size_t comma_pos = target_text->find(',');
+ wtf_size_t hyphen_pos = target_text->find('-');
if (hyphen_pos != kNotFound && hyphen_pos == comma_pos - 1) {
String prefix = target_text->Substring(0, hyphen_pos);
@@ -28,8 +28,8 @@ String ExtractPrefix(String* target_text) {
}
String ExtractSuffix(String* target_text) {
- size_t last_comma_pos = target_text->ReverseFind(',');
- size_t last_hyphen_pos = target_text->ReverseFind('-');
+ wtf_size_t last_comma_pos = target_text->ReverseFind(',');
+ wtf_size_t last_hyphen_pos = target_text->ReverseFind('-');
if (last_hyphen_pos != kNotFound && last_hyphen_pos == last_comma_pos + 1) {
String suffix = target_text->Substring(last_hyphen_pos + 1);
@@ -49,10 +49,10 @@ TextFragmentSelector TextFragmentSelector::Create(String target_text) {
String prefix = ExtractPrefix(&target_text);
String suffix = ExtractSuffix(&target_text);
- size_t comma_pos = target_text.find(',');
+ wtf_size_t comma_pos = target_text.find(',');
// If there are more commas, this is an invalid text fragment selector.
- size_t next_comma_pos = target_text.find(',', comma_pos + 1);
+ wtf_size_t next_comma_pos = target_text.find(',', comma_pos + 1);
if (next_comma_pos != kNotFound)
return TextFragmentSelector(kInvalid);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
index 3c38e5fbcc2..3aa90bfd6fa 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
@@ -4,10 +4,9 @@
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/strcat.h"
#include "base/time/default_tick_clock.h"
-#include "components/shared_highlighting/core/common/disabled_sites.h"
#include "components/shared_highlighting/core/common/shared_highlighting_features.h"
#include "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
@@ -15,9 +14,11 @@
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/finder/find_buffer.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
+#include "third_party/blink/renderer/core/editing/range_in_flat_tree.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h"
+#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h"
#include "third_party/blink/renderer/platform/text/text_boundaries.h"
using LinkGenerationError = shared_highlighting::LinkGenerationError;
@@ -83,6 +84,23 @@ Node* NextNonEmptyVisibleTextNode(Node* start_node) {
if (!start_node)
return nullptr;
+ // Filter out nodes without layout object.
+ if (base::FeatureList::IsEnabled(
+ shared_highlighting::kSharedHighlightingLayoutObjectFix)) {
+ for (Node* node = start_node; node; node = Direction::Next(*node)) {
+ Node* next_node = Direction::GetVisibleTextNode(*node);
+ if (!next_node)
+ return nullptr;
+ if (next_node->GetLayoutObject() &&
+ !PlainText(EphemeralRange::RangeOfContents(*next_node))
+ .StripWhiteSpace()
+ .IsEmpty())
+ return next_node;
+ node = next_node;
+ }
+ return nullptr;
+ }
+
// Move forward/backward until non empty visible text node is found.
for (Node* node = start_node; node; node = Direction::Next(*node)) {
Node* next_node = Direction::GetVisibleTextNode(*node);
@@ -185,31 +203,87 @@ constexpr int kMinWordCount_ = 3;
TextFragmentSelectorGenerator::TextFragmentSelectorGenerator(
LocalFrame* main_frame)
- : selection_frame_(main_frame) {
- // Scroll-to-text doesn't support iframes.
- DCHECK(main_frame->IsMainFrame());
+ : frame_(main_frame) {
+ // Links are generally generated in the main frame except when the main frame
+ // delegates the text fragment to an iframe (e.g AMP Viewer pages).
+ if (!base::FeatureList::IsEnabled(
+ shared_highlighting::kSharedHighlightingAmp)) {
+ DCHECK(main_frame->IsMainFrame());
+ }
}
-void TextFragmentSelectorGenerator::UpdateSelection(
- const EphemeralRangeInFlatTree& selection_range) {
- selection_range_ = MakeGarbageCollected<Range>(
- selection_range.GetDocument(),
- ToPositionInDOMTree(selection_range.StartPosition()),
- ToPositionInDOMTree(selection_range.EndPosition()));
- if (base::FeatureList::IsEnabled(
- shared_highlighting::kPreemptiveLinkToTextGeneration) &&
- shared_highlighting::ShouldOfferLinkToText(
- selection_frame_->GetDocument()->Url())) {
- Reset();
- GenerateSelector();
+void TextFragmentSelectorGenerator::Generate(const RangeInFlatTree& range,
+ GenerateCallback callback) {
+ DCHECK(callback);
+ Reset();
+ range_ = MakeGarbageCollected<RangeInFlatTree>(range.StartPosition(),
+ range.EndPosition());
+ pending_generate_selector_callback_ = std::move(callback);
+
+ StartGeneration();
+}
+
+void TextFragmentSelectorGenerator::Reset() {
+ if (finder_)
+ finder_->Cancel();
+
+ generation_start_time_ = base::DefaultTickClock::GetInstance()->NowTicks();
+ state_ = kNotStarted;
+ error_.reset();
+ step_ = kExact;
+ max_available_prefix_ = "";
+ max_available_suffix_ = "";
+ max_available_range_start_ = "";
+ max_available_range_end_ = "";
+ num_context_words_ = 0;
+ num_range_words_ = 0;
+ iteration_ = 0;
+ selector_ = nullptr;
+ range_ = nullptr;
+ pending_generate_selector_callback_.Reset();
+}
+
+void TextFragmentSelectorGenerator::Trace(Visitor* visitor) const {
+ visitor->Trace(frame_);
+ visitor->Trace(range_);
+ visitor->Trace(finder_);
+}
+
+void TextFragmentSelectorGenerator::RecordSelectorStateUma() const {
+ base::UmaHistogramEnumeration("SharedHighlights.LinkGenerated.StateAtRequest",
+ state_);
+}
+
+void TextFragmentSelectorGenerator::DidFindMatch(
+ const EphemeralRangeInFlatTree& match,
+ const TextFragmentAnchorMetrics::Match match_metrics,
+ bool is_unique) {
+ if (is_unique &&
+ PlainText(match).StripWhiteSpace().length() ==
+ PlainText(range_->ToEphemeralRange()).StripWhiteSpace().length()) {
+ state_ = kSuccess;
+ ResolveSelectorState();
+ } else {
+ state_ = kNeedsNewCandidate;
+
+ // If already tried exact selector then should continue by adding context.
+ if (step_ == kExact)
+ step_ = kContext;
+ GenerateSelectorCandidate();
}
}
+void TextFragmentSelectorGenerator::NoMatchFound() {
+ state_ = kFailure;
+ error_ = LinkGenerationError::kIncorrectSelector;
+ ResolveSelectorState();
+}
+
void TextFragmentSelectorGenerator::AdjustSelection() {
- if (!selection_range_)
+ if (!range_)
return;
- EphemeralRangeInFlatTree ephemeral_range(selection_range_);
+ EphemeralRangeInFlatTree ephemeral_range = range_->ToEphemeralRange();
Node* start_container =
ephemeral_range.StartPosition().ComputeContainerNode();
Node* end_container = ephemeral_range.EndPosition().ComputeContainerNode();
@@ -274,55 +348,45 @@ void TextFragmentSelectorGenerator::AdjustSelection() {
}
if (corrected_start != start_container ||
- corrected_start_offset !=
+ static_cast<int>(corrected_start_offset) !=
ephemeral_range.StartPosition().ComputeOffsetInContainerNode() ||
corrected_end != end_container ||
- corrected_end_offset !=
+ static_cast<int>(corrected_end_offset) !=
ephemeral_range.EndPosition().ComputeOffsetInContainerNode()) {
- selection_range_ = MakeGarbageCollected<Range>(
- selection_range_->OwnerDocument(),
- Position(corrected_start, corrected_start_offset),
- Position(corrected_end, corrected_end_offset));
- }
-}
-
-void TextFragmentSelectorGenerator::Cancel() {
- Reset();
-}
-
-void TextFragmentSelectorGenerator::RequestSelector(
- RequestSelectorCallback callback) {
- DCHECK(callback);
- if (!base::FeatureList::IsEnabled(
- shared_highlighting::kPreemptiveLinkToTextGeneration)) {
- Reset();
- pending_generate_selector_callback_ = std::move(callback);
- GenerateSelector();
- } else {
- pending_generate_selector_callback_ = std::move(callback);
- DCHECK_NE(state_, kNotStarted);
- if (state_ == kFailure || state_ == kSuccess) {
- selector_requested_before_ready_ = false;
- if (state_ == kFailure) {
- NotifyClientSelectorReady(
- TextFragmentSelector(TextFragmentSelector::SelectorType::kInvalid));
- } else {
- NotifyClientSelectorReady(*selector_);
- }
+ PositionInFlatTree start(corrected_start, corrected_start_offset);
+ PositionInFlatTree end(corrected_end, corrected_end_offset);
+
+ // TODO(bokan): This can sometimes occur from a selection. Avoid crashing
+ // from this case but this can come from a seemingly correct range so we
+ // should investigate the source of the bug. https://crbug.com/1216357
+ if (start >= end) {
+ range_ = nullptr;
return;
}
- selector_requested_before_ready_ = true;
+
+ range_ = MakeGarbageCollected<RangeInFlatTree>(start, end);
}
}
-void TextFragmentSelectorGenerator::GenerateSelector() {
- DCHECK(selection_range_);
+void TextFragmentSelectorGenerator::StartGeneration() {
+ DCHECK(range_);
- selection_range_->OwnerDocument().UpdateStyleAndLayout(
+ range_->StartPosition().GetDocument()->UpdateStyleAndLayout(
DocumentUpdateReason::kFindInPage);
- // Shouldn't continue is selection is empty.
- EphemeralRangeInFlatTree ephemeral_range(selection_range_);
+ // TODO(bokan): This can sometimes occur from a selection. Avoid crashing from
+ // this case but this can come from a seemingly correct range so we should
+ // investigate the source of the bug.
+ // https://crbug.com/1216357
+ EphemeralRangeInFlatTree ephemeral_range = range_->ToEphemeralRange();
+ if (ephemeral_range.StartPosition() >= ephemeral_range.EndPosition()) {
+ state_ = kFailure;
+ error_ = LinkGenerationError::kEmptySelection;
+ ResolveSelectorState();
+ return;
+ }
+
+ // Shouldn't continue if selection is empty.
String selected_text = PlainText(ephemeral_range).StripWhiteSpace();
if (selected_text.IsEmpty()) {
state_ = kFailure;
@@ -332,9 +396,20 @@ void TextFragmentSelectorGenerator::GenerateSelector() {
}
AdjustSelection();
- UMA_HISTOGRAM_COUNTS_1000(
- "SharedHighlights.LinkGenerated.SelectionLength",
- PlainText(EphemeralRange(selection_range_)).length());
+
+ // TODO(bokan): This can sometimes occur from a selection. Avoid crashing from
+ // this case but this can come from a seemingly correct range so we should
+ // investigate the source of the bug.
+ // https://crbug.com/1216357
+ if (!range_) {
+ state_ = kFailure;
+ error_ = LinkGenerationError::kEmptySelection;
+ ResolveSelectorState();
+ return;
+ }
+
+ UMA_HISTOGRAM_COUNTS_1000("SharedHighlights.LinkGenerated.SelectionLength",
+ PlainText(range_->ToEphemeralRange()).length());
state_ = kNeedsNewCandidate;
GenerateSelectorCandidate();
}
@@ -377,79 +452,87 @@ void TextFragmentSelectorGenerator::RunTextFinder() {
iteration_++;
// |FindMatch| will call |DidFindMatch| indicating if the match was unique.
finder_ = MakeGarbageCollected<TextFragmentFinder>(
- *this, *selector_, selection_frame_->GetDocument(),
+ *this, *selector_, frame_->GetDocument(),
TextFragmentFinder::FindBufferRunnerType::kAsynchronous);
finder_->FindMatch();
}
-void TextFragmentSelectorGenerator::DidFindMatch(
- const EphemeralRangeInFlatTree& match,
- const TextFragmentAnchorMetrics::Match match_metrics,
- bool is_unique) {
- if (is_unique && PlainText(match).StripWhiteSpace().length() ==
- PlainText(EphemeralRangeInFlatTree(selection_range_))
- .StripWhiteSpace()
- .length()) {
- state_ = kSuccess;
- ResolveSelectorState();
- } else {
- state_ = kNeedsNewCandidate;
-
- // If already tried exact selector then should continue by adding context.
- if (step_ == kExact)
- step_ = kContext;
- GenerateSelectorCandidate();
- }
-}
-
-void TextFragmentSelectorGenerator::NoMatchFound() {
- state_ = kFailure;
- error_ = LinkGenerationError::kIncorrectSelector;
- ResolveSelectorState();
-}
+String TextFragmentSelectorGenerator::GetPreviousTextBlock(
+ const Position& prefix_end_position) {
+ Node* prefix_end = prefix_end_position.ComputeContainerNode();
+ unsigned prefix_end_offset =
+ prefix_end_position.ComputeOffsetInContainerNode();
-void TextFragmentSelectorGenerator::OnSelectorReady(
- const TextFragmentSelector& selector) {
- // Check that frame is not deattched and generator is still valid.
- DCHECK(selection_frame_);
+ // If given position point to the first visible text in its containiner node,
+ // use the preceding visible node for the suffix.
+ if (IsFirstVisiblePosition(prefix_end, prefix_end_offset)) {
+ prefix_end = BackwardNonEmptyVisibleTextNode(
+ FlatTreeTraversal::Previous(*prefix_end));
- RecordAllMetrics(selector);
- if (pending_generate_selector_callback_) {
- NotifyClientSelectorReady(selector);
+ if (!prefix_end)
+ return "";
+ prefix_end_offset = prefix_end->textContent().length();
}
-}
-void TextFragmentSelectorGenerator::NotifyClientSelectorReady(
- const TextFragmentSelector& selector) {
- DCHECK(pending_generate_selector_callback_);
- if (base::FeatureList::IsEnabled(
- shared_highlighting::kPreemptiveLinkToTextGeneration))
- RecordPreemptiveGenerationMetrics(selector);
- std::move(pending_generate_selector_callback_).Run(selector.ToString());
+ // The furthest node within same block without crossing block boundaries would
+ // be the prefix start.
+ Node* prefix_start = LastVisibleTextNodeWithinBlock(prefix_end);
+ if (!prefix_start)
+ return "";
+
+ auto range_start = Position(prefix_start, 0);
+ auto range_end = Position(prefix_end, prefix_end_offset);
+ // TODO(gayane): Find test case when this happens, seems related to shadow
+ // root. See crbug.com/1220830
+ if (range_start >= range_end)
+ return "";
+ return PlainText(EphemeralRange(range_start, range_end)).StripWhiteSpace();
}
-void TextFragmentSelectorGenerator::ClearSelection() {
- if (selection_range_) {
- selection_range_->Dispose();
- selection_range_ = nullptr;
+String TextFragmentSelectorGenerator::GetNextTextBlock(
+ const Position& suffix_start_position) {
+ Node* suffix_start = suffix_start_position.ComputeContainerNode();
+ unsigned suffix_start_offset =
+ suffix_start_position.ComputeOffsetInContainerNode();
+ // If given position point to the last visible text in its containiner node,
+ // use the following visible node for the suffix.
+ if (IsLastVisiblePosition(suffix_start, suffix_start_offset)) {
+ suffix_start = FirstNonEmptyVisibleTextNode(
+ FlatTreeTraversal::NextSkippingChildren(*suffix_start));
+ suffix_start_offset = 0;
}
-}
+ if (!suffix_start)
+ return "";
-void TextFragmentSelectorGenerator::Detach() {
- Reset();
- selection_frame_ = nullptr;
-}
+ // The furthest node within same block without crossing block boundaries would
+ // be the suffix end.
+ Node* suffix_end = FirstVisibleTextNodeWithinBlock(suffix_start);
+ if (!suffix_end)
+ return "";
-void TextFragmentSelectorGenerator::Trace(Visitor* visitor) const {
- visitor->Trace(selection_frame_);
- visitor->Trace(selection_range_);
- visitor->Trace(finder_);
+ auto range_start = Position(suffix_start, suffix_start_offset);
+ auto range_end = Position(suffix_end, suffix_end->textContent().length());
+
+ // TODO(gayane): Find test case when this happens, seems related to shadow
+ // root. See crbug.com/1220830
+ if (range_start >= range_end)
+ return "";
+ return PlainText(EphemeralRange(range_start, range_end)).StripWhiteSpace();
}
void TextFragmentSelectorGenerator::GenerateExactSelector() {
DCHECK_EQ(kExact, step_);
DCHECK_EQ(kNeedsNewCandidate, state_);
- EphemeralRangeInFlatTree ephemeral_range(selection_range_);
+ EphemeralRangeInFlatTree ephemeral_range = range_->ToEphemeralRange();
+
+ // TODO(bokan): Another case where the range appears to not have valid nodes.
+ // Not sure how this happens. https://crbug.com/1216773.
+ if (!ephemeral_range.StartPosition().ComputeContainerNode() ||
+ !ephemeral_range.EndPosition().ComputeContainerNode()) {
+ state_ = kFailure;
+ error_ = LinkGenerationError::kEmptySelection;
+ return;
+ }
// If not in same block, should use ranges.
if (!TextFragmentFinder::IsInSameUninterruptedBlock(
@@ -488,7 +571,7 @@ void TextFragmentSelectorGenerator::ExtendRangeSelector() {
// Initialize range start/end and word min count, if needed.
if (max_available_range_start_.IsEmpty() &&
max_available_range_end_.IsEmpty()) {
- EphemeralRangeInFlatTree ephemeral_range(selection_range_);
+ EphemeralRangeInFlatTree ephemeral_range = range_->ToEphemeralRange();
// If selection starts and ends in the same block, then split selected text
// roughly in the middle.
@@ -498,8 +581,8 @@ void TextFragmentSelectorGenerator::ExtendRangeSelector() {
selection_text.Ensure16Bit();
int selection_length = selection_text.length();
int mid_point =
- FindNextWordForward(selection_text.Characters16(), selection_length,
- selection_length / 2);
+ FindNextWordForward(selection_text.Characters16(),
+ selection_text.length(), selection_length / 2);
max_available_range_start_ = selection_text.Left(mid_point);
// If from middle till end of selection there is no word break, then we
@@ -516,9 +599,9 @@ void TextFragmentSelectorGenerator::ExtendRangeSelector() {
// If not the same node, then we use first and last block of the selection
// range.
max_available_range_start_ =
- GetNextTextBlock(selection_range_->StartPosition());
+ GetNextTextBlock(ToPositionInDOMTree(range_->StartPosition()));
max_available_range_end_ =
- GetPreviousTextBlock(selection_range_->EndPosition());
+ GetPreviousTextBlock(ToPositionInDOMTree(range_->EndPosition()));
}
// Use at least 3 words from both sides for more robust link to text.
@@ -556,8 +639,9 @@ void TextFragmentSelectorGenerator::ExtendContext() {
// Try initiating properties necessary for calculating prefix and suffix.
if (max_available_prefix_.IsEmpty() && max_available_suffix_.IsEmpty()) {
max_available_prefix_ =
- GetPreviousTextBlock(selection_range_->StartPosition());
- max_available_suffix_ = GetNextTextBlock(selection_range_->EndPosition());
+ GetPreviousTextBlock(ToPositionInDOMTree(range_->StartPosition()));
+ max_available_suffix_ =
+ GetNextTextBlock(ToPositionInDOMTree(range_->EndPosition()));
// Use at least 3 words from both sides for more robust link to text.
num_context_words_ = kMinWordCount_;
@@ -585,97 +669,14 @@ void TextFragmentSelectorGenerator::ExtendContext() {
state_ = kTestCandidate;
}
-String TextFragmentSelectorGenerator::GetPreviousTextBlock(
- const Position& prefix_end_position) {
- Node* prefix_end = prefix_end_position.ComputeContainerNode();
- unsigned prefix_end_offset =
- prefix_end_position.ComputeOffsetInContainerNode();
-
- // If given position point to the first visible text in its containiner node,
- // use the preceding visible node for the suffix.
- if (IsFirstVisiblePosition(prefix_end, prefix_end_offset)) {
- prefix_end = BackwardNonEmptyVisibleTextNode(
- FlatTreeTraversal::Previous(*prefix_end));
-
- if (!prefix_end)
- return "";
- prefix_end_offset = prefix_end->textContent().length();
- }
-
- // The furthest node within same block without crossing block boundaries would
- // be the prefix start.
- Node* prefix_start = LastVisibleTextNodeWithinBlock(prefix_end);
- if (!prefix_start)
- return "";
-
- auto range_start = Position(prefix_start, 0);
- auto range_end = Position(prefix_end, prefix_end_offset);
- // TODO(gayane): Find test case when this happens, seems related to shadow
- // root. See crbug.com/1220830
- if (range_start >= range_end)
- return "";
- return PlainText(EphemeralRange(range_start, range_end)).StripWhiteSpace();
-}
-
-String TextFragmentSelectorGenerator::GetNextTextBlock(
- const Position& suffix_start_position) {
- Node* suffix_start = suffix_start_position.ComputeContainerNode();
- unsigned suffix_start_offset =
- suffix_start_position.ComputeOffsetInContainerNode();
- // If given position point to the last visible text in its containiner node,
- // use the following visible node for the suffix.
- if (IsLastVisiblePosition(suffix_start, suffix_start_offset)) {
- suffix_start = FirstNonEmptyVisibleTextNode(
- FlatTreeTraversal::NextSkippingChildren(*suffix_start));
- suffix_start_offset = 0;
- }
- if (!suffix_start)
- return "";
-
- // The furthest node within same block without crossing block boundaries would
- // be the suffix end.
- Node* suffix_end = FirstVisibleTextNodeWithinBlock(suffix_start);
- if (!suffix_end)
- return "";
-
- auto range_start = Position(suffix_start, suffix_start_offset);
- auto range_end = Position(suffix_end, suffix_end->textContent().length());
-
- // TODO(gayane): Find test case when this happens, seems related to shadow
- // root. See crbug.com/1220830
- if (range_start >= range_end)
- return "";
- return PlainText(EphemeralRange(range_start, range_end)).StripWhiteSpace();
-}
-
-void TextFragmentSelectorGenerator::Reset() {
- if (finder_)
- finder_->Cancel();
-
- generation_start_time_ = base::DefaultTickClock::GetInstance()->NowTicks();
- state_ = kNotStarted;
- error_.reset();
- step_ = kExact;
- max_available_prefix_ = "";
- max_available_suffix_ = "";
- max_available_range_start_ = "";
- max_available_range_end_ = "";
- num_context_words_ = 0;
- num_range_words_ = 0;
- iteration_ = 0;
- selector_ = nullptr;
- selector_requested_before_ready_.reset();
- pending_generate_selector_callback_.Reset();
-}
-
void TextFragmentSelectorGenerator::RecordAllMetrics(
const TextFragmentSelector& selector) {
UMA_HISTOGRAM_BOOLEAN(
"SharedHighlights.LinkGenerated",
selector.Type() != TextFragmentSelector::SelectorType::kInvalid);
- ukm::UkmRecorder* recorder = selection_frame_->GetDocument()->UkmRecorder();
- ukm::SourceId source_id = selection_frame_->GetDocument()->UkmSourceID();
+ ukm::UkmRecorder* recorder = frame_->GetDocument()->UkmRecorder();
+ ukm::SourceId source_id = frame_->GetDocument()->UkmSourceID();
if (selector.Type() != TextFragmentSelector::SelectorType::kInvalid) {
UMA_HISTOGRAM_COUNTS_1000("SharedHighlights.LinkGenerated.ParamLength",
@@ -707,27 +708,21 @@ void TextFragmentSelectorGenerator::RecordAllMetrics(
}
}
-void TextFragmentSelectorGenerator::RecordPreemptiveGenerationMetrics(
+void TextFragmentSelectorGenerator::OnSelectorReady(
const TextFragmentSelector& selector) {
- DCHECK(selector_requested_before_ready_.has_value());
-
- bool success =
- selector.Type() != TextFragmentSelector::SelectorType::kInvalid;
+ // Check that frame is not deattched and generator is still valid.
+ DCHECK(frame_);
- std::string uma_prefix = "SharedHighlights.LinkGenerated";
- if (selector_requested_before_ready_.value()) {
- uma_prefix = base::StrCat({uma_prefix, ".RequestedBeforeReady"});
- } else {
- uma_prefix = base::StrCat({uma_prefix, ".RequestedAfterReady"});
+ RecordAllMetrics(selector);
+ if (pending_generate_selector_callback_) {
+ NotifyClientSelectorReady(selector);
}
- base::UmaHistogramBoolean(uma_prefix, success);
+}
- if (!success) {
- LinkGenerationError error =
- error_.has_value() ? error_.value() : LinkGenerationError::kUnknown;
- base::UmaHistogramEnumeration(
- "SharedHighlights.LinkGenerated.Error.Requested", error);
- }
+void TextFragmentSelectorGenerator::NotifyClientSelectorReady(
+ const TextFragmentSelector& selector) {
+ DCHECK(pending_generate_selector_callback_);
+ std::move(pending_generate_selector_callback_).Run(selector);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h
index b20e8a90dfb..2d54bc5e1b1 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h
@@ -10,52 +10,45 @@
#include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h"
-#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
namespace blink {
-using RequestSelectorCallback = base::OnceCallback<void(const WTF::String&)>;
-
class LocalFrame;
+class RangeInFlatTree;
+class TextFragmentSelector;
-// TextFragmentSelectorGenerator is responsible for generating text fragment
-// selectors for the user selected text according to spec in
+// TextFragmentSelectorGenerator is used to generate a TextFragmentSelector,
+// given a range of DOM in a document. The TextFragmentSelector provides the
+// necessary portions of a text fragment URL such that it scrolls to the given
+// range when navigated. For more details, see:
// https://github.com/WICG/scroll-to-text-fragment#proposed-solution.
-// Generated selectors would be later used to highlight the same
-// text if successfully parsed by |TextFragmentAnchor |. Generation will be
-// triggered when users request "link to text" for the selected text.
//
-// TextFragmentSelectorGenerator generates candidate selectors and tries it
-// against the page content to ensure the correct and unique match. Repeats the
-// process adding context/range to the selector as necessary until the correct
-// match is uniquely identified or no new context/range can be added.
+// TextFragmentSelectorGenerator works by starting with a candidate selector
+// and repeatedly trying it against the page content to ensure the correct and
+// unique match. While we don't have a unique match, we repeatedly adding
+// context/range to the selector until the correct match is uniquely identified
+// or no new context/range can be added.
class CORE_EXPORT TextFragmentSelectorGenerator final
: public GarbageCollected<TextFragmentSelectorGenerator>,
public TextFragmentFinder::Client {
+ using GenerateCallback =
+ base::OnceCallback<void(const TextFragmentSelector&)>;
+
public:
explicit TextFragmentSelectorGenerator(LocalFrame* main_frame);
+ TextFragmentSelectorGenerator(const TextFragmentSelectorGenerator&) = delete;
+ TextFragmentSelectorGenerator& operator=(
+ const TextFragmentSelectorGenerator&) = delete;
- // Sets the frame and range of the current selection.
- void UpdateSelection(const EphemeralRangeInFlatTree& selection_range);
-
- // Adjust the selection start/end to a valid position. That includes skipping
- // non text start/end nodes and extending selection from start and end to
- // contain full words.
- void AdjustSelection();
-
- // blink::mojom::blink::TextFragmentSelectorProducer interface
- void Cancel();
+ // Requests a TextFragmentSelector be generated for the selection of DOM
+ // specified by |range|. Will be generated asynchronously and returned by
+ // invoking |callback|.
+ void Generate(const RangeInFlatTree& range, GenerateCallback callback);
- // Requests selector for current selection.
- void RequestSelector(RequestSelectorCallback callback);
-
- // TextFragmentFinder::Client interface
- void DidFindMatch(const EphemeralRangeInFlatTree& match,
- const TextFragmentAnchorMetrics::Match match_metrics,
- bool is_unique) override;
-
- void NoMatchFound() override;
+ // Resets generator state to initial values and cancels any existing async
+ // tasks.
+ void Reset();
// Wrappers for tests.
String GetPreviousTextBlockForTesting(const Position& position) {
@@ -64,18 +57,23 @@ class CORE_EXPORT TextFragmentSelectorGenerator final
String GetNextTextBlockForTesting(const Position& position) {
return GetNextTextBlock(position);
}
- void SetCallbackForTesting(RequestSelectorCallback callback) {
+ void SetCallbackForTesting(GenerateCallback callback) {
pending_generate_selector_callback_ = std::move(callback);
}
- // Releases members if necessary.
- void ClearSelection();
+ void Trace(Visitor*) const;
- void Detach();
+ // Temporary diagnostic metric recorded to help explain discrepancies in
+ // other metrics.
+ void RecordSelectorStateUma() const;
- void Trace(Visitor*) const;
+ LocalFrame* GetFrame() { return frame_; }
- LocalFrame* GetFrame() { return selection_frame_; }
+ // If generation fails, returns the reason that generation failed. If
+ // generation hasn't finished, or was successful, returns an empty optional.
+ absl::optional<shared_highlighting::LinkGenerationError> GetError() {
+ return error_;
+ }
private:
// Used for determining the next step of selector generation.
@@ -98,11 +96,24 @@ class CORE_EXPORT TextFragmentSelectorGenerator final
kFailure,
// Selector is found. No further attempts are necessary.
- kSuccess
+ kSuccess,
+
+ kMaxValue = kSuccess
};
+ // TextFragmentFinder::Client interface
+ void DidFindMatch(const EphemeralRangeInFlatTree& match,
+ const TextFragmentAnchorMetrics::Match match_metrics,
+ bool is_unique) override;
+ void NoMatchFound() override;
+
+ // Adjust the selection start/end to a valid position. That includes skipping
+ // non text start/end nodes and extending selection from start and end to
+ // contain full words.
+ void AdjustSelection();
+
// Generates selector for current selection.
- void GenerateSelector();
+ void StartGeneration();
void GenerateSelectorCandidate();
@@ -121,30 +132,26 @@ class CORE_EXPORT TextFragmentSelectorGenerator final
void ExtendRangeSelector();
void ExtendContext();
- void Reset();
-
void RecordAllMetrics(const TextFragmentSelector& selector);
- void RecordPreemptiveGenerationMetrics(const TextFragmentSelector& selector);
// Called when selector generation is complete.
void OnSelectorReady(const TextFragmentSelector& selector);
- // Called to notify clients of the result of |GenerateSelector|.
+ // Called to notify clients of the result of |Generate|.
void NotifyClientSelectorReady(const TextFragmentSelector& selector);
- Member<LocalFrame> selection_frame_;
- Member<Range> selection_range_;
+ Member<LocalFrame> frame_;
+
+ // This is the Range for which we're generating a selector.
+ Member<RangeInFlatTree> range_;
+
std::unique_ptr<TextFragmentSelector> selector_;
- RequestSelectorCallback pending_generate_selector_callback_;
+ GenerateCallback pending_generate_selector_callback_;
GenerationStep step_ = kExact;
SelectorState state_ = kNeedsNewCandidate;
- // Used when preemptive link generation is enabled to report
- // whether |RequestSelector| was called before or after selector was ready.
- absl::optional<bool> selector_requested_before_ready_;
-
absl::optional<shared_highlighting::LinkGenerationError> error_;
// Fields used for keeping track of context.
@@ -166,8 +173,6 @@ class CORE_EXPORT TextFragmentSelectorGenerator final
base::TimeTicks generation_start_time_;
Member<TextFragmentFinder> finder_;
-
- DISALLOW_COPY_AND_ASSIGN(TextFragmentSelectorGenerator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
index 1168cb9d8e7..71e09988cd8 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/page/scrolling/text_fragment_handler.h"
#include "third_party/blink/renderer/core/testing/scoped_fake_ukm_recorder.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -33,21 +34,11 @@ const char kSuccessUkmMetric[] = "Success";
const char kErrorUkmMetric[] = "Error";
} // namespace
-class TextFragmentSelectorGeneratorTest
- : public SimTest,
- public ::testing::WithParamInterface<bool> {
+class TextFragmentSelectorGeneratorTest : public SimTest {
public:
void SetUp() override {
SimTest::SetUp();
WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
- preemptive_generation_enabled_ = GetParam();
- if (preemptive_generation_enabled_) {
- feature_list_.InitAndEnableFeature(
- shared_highlighting::kPreemptiveLinkToTextGeneration);
- } else {
- feature_list_.InitAndDisableFeature(
- shared_highlighting::kPreemptiveLinkToTextGeneration);
- }
}
void VerifySelector(Position selected_start,
@@ -95,67 +86,32 @@ class TextFragmentSelectorGeneratorTest
String GenerateSelector(Position selected_start, Position selected_end) {
generate_call_count_++;
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->UpdateSelection(ToEphemeralRangeInFlatTree(
- EphemeralRange(selected_start, selected_end)));
bool callback_called = false;
String selector;
auto lambda = [](bool& callback_called, String& selector,
- const String& generated_selector) {
- selector = generated_selector;
+ const TextFragmentSelector& generated_selector) {
+ selector = generated_selector.ToString();
callback_called = true;
};
auto callback =
WTF::Bind(lambda, std::ref(callback_called), std::ref(selector));
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->RequestSelector(std::move(callback));
+ GetTextFragmentSelectorGenerator()->Generate(
+ *MakeGarbageCollected<RangeInFlatTree>(
+ ToPositionInFlatTree(selected_start),
+ ToPositionInFlatTree(selected_end)),
+ std::move(callback));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
return selector;
}
- void VerifyPreemptiveGenerationMetrics(bool success) {
- if (!preemptive_generation_enabled_) {
- histogram_tester_.ExpectTotalCount(
- "SharedHighlights.LinkGenerated.Error.Requested", 0);
- histogram_tester_.ExpectTotalCount(
- "SharedHighlights.LinkGenerated.RequestedAfterReady", 0);
- histogram_tester_.ExpectTotalCount(
- "SharedHighlights.LinkGenerated.RequestedBeforeReady", 0);
- } else {
- EXPECT_EQ(
- 1u, histogram_tester_
- .GetAllSamples(
- "SharedHighlights.LinkGenerated.RequestedAfterReady")
- .size() +
- histogram_tester_
- .GetAllSamples(
- "SharedHighlights.LinkGenerated.RequestedBeforeReady")
- .size());
-
- if (!success) {
- histogram_tester_.ExpectTotalCount(
- "SharedHighlights.LinkGenerated.Error.Requested", 1);
- } else {
- histogram_tester_.ExpectTotalCount(
- "SharedHighlights.LinkGenerated.Error.Requested", 0);
- }
- }
-
- // Check async task metrics.
- EXPECT_LT(0u, histogram_tester_
- .GetAllSamples("SharedHighlights.AsyncTask.Iterations")
- .size());
- EXPECT_LT(0u,
- histogram_tester_
- .GetAllSamples("SharedHighlights.AsyncTask.SearchDuration")
- .size());
+ TextFragmentSelectorGenerator* GetTextFragmentSelectorGenerator() {
+ return GetDocument()
+ .GetFrame()
+ ->GetTextFragmentHandler()
+ ->GetTextFragmentSelectorGenerator();
}
protected:
@@ -166,91 +122,10 @@ class TextFragmentSelectorGeneratorTest
base::HistogramTester histogram_tester_;
ScopedFakeUkmRecorder scoped_ukm_recorder_;
int generate_call_count_ = 0;
- bool preemptive_generation_enabled_;
- base::test::ScopedFeatureList feature_list_;
};
-// Checks that the selector is preemptively generated.
-TEST_P(TextFragmentSelectorGeneratorTest, CheckPreemptiveGeneration) {
- if (!preemptive_generation_enabled_)
- return;
-
- SimRequest request("https://example.com/test.html", "text/html");
- LoadURL("https://example.com/test.html");
- request.Complete(R"HTML(
- <!DOCTYPE html>
- <p id='first'>First paragraph</p>
- )HTML");
-
- Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
- const auto& selected_start = Position(first_paragraph, 0);
- const auto& selected_end = Position(first_paragraph, 5);
- ASSERT_EQ("First", PlainText(EphemeralRange(selected_start, selected_end)));
-
- GetDocument().GetFrame()->GetTextFragmentSelectorGenerator()->UpdateSelection(
- ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end)));
- base::RunLoop().RunUntilIdle();
-
- histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated", 1);
- histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error", 0);
-}
-
-// When URL is blocklisted, the selector shouldn't be preemptively generated.
-TEST_P(TextFragmentSelectorGeneratorTest,
- CheckNoPreemptiveGenerationBlocklist) {
- if (!preemptive_generation_enabled_)
- return;
-
- SimRequest request("https://instagram.com/test.html", "text/html");
- LoadURL("https://instagram.com/test.html");
- request.Complete(R"HTML(
- <!DOCTYPE html>
- <p id='first'>First paragraph</p>
- )HTML");
-
- Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
- const auto& selected_start = Position(first_paragraph, 0);
- const auto& selected_end = Position(first_paragraph, 5);
- ASSERT_EQ("First", PlainText(EphemeralRange(selected_start, selected_end)));
-
- GetDocument().GetFrame()->GetTextFragmentSelectorGenerator()->UpdateSelection(
- ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end)));
- base::RunLoop().RunUntilIdle();
-
- histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated", 0);
- histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error", 0);
-}
-
-// Check that selector is not generated for editable text.
-TEST_P(TextFragmentSelectorGeneratorTest, CheckNoPreemptiveGenerationEditable) {
- if (!preemptive_generation_enabled_)
- return;
-
- SimRequest request("https://instagram.com/test.html", "text/html");
- LoadURL("https://instagram.com/test.html");
- request.Complete(R"HTML(
- <!DOCTYPE html>
- <input type="text" id="input" value="default text in input">
- )HTML");
-
- Node* input_text =
- FlatTreeTraversal::Next(*GetDocument().getElementById("input"))
- ->firstChild();
- const auto& selected_start = Position(input_text, 0);
- const auto& selected_end = Position(input_text, 12);
- ASSERT_EQ("default text",
- PlainText(EphemeralRange(selected_start, selected_end)));
-
- GetDocument().GetFrame()->GetTextFragmentSelectorGenerator()->UpdateSelection(
- ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end)));
- base::RunLoop().RunUntilIdle();
-
- histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated", 0);
- histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error", 0);
-}
-
// Basic exact selector case.
-TEST_P(TextFragmentSelectorGeneratorTest, EmptySelection) {
+TEST_F(TextFragmentSelectorGeneratorTest, EmptySelection) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -267,7 +142,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, EmptySelection) {
}
// Basic exact selector case.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -287,7 +162,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector) {
}
// Exact selector test where selection contains nested <i> node.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextWithNestedTextNodes) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextWithNestedTextNodes) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -308,7 +183,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextWithNestedTextNodes) {
}
// Exact selector test where selection contains multiple spaces.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextWithExtraSpace) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextWithExtraSpace) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -329,7 +204,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextWithExtraSpace) {
// Exact selector where selection is too short, in which case context is
// required.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_TooShortNeedsContext) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -351,7 +226,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// Exact selector with context test. Case when only one word for prefix and
// suffix is enough to disambiguate the selection.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_WithOneWordContext) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -373,7 +248,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// Exact selector with context test. Case when multiple words for prefix and
// suffix is necessary to disambiguate the selection.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_MultipleWordContext) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -397,7 +272,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// Exact selector with context test. Case when multiple words for prefix and
// suffix is necessary to disambiguate the selection and prefix and suffix
// contain extra space.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_MultipleWordContext_ExtraSpace) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -421,7 +296,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// Exact selector with context test. Case when available prefix for all the
// occurrences of selected text is the same. In this case suffix should be
// extended until unique selector is found.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_SamePrefix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_SamePrefix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -444,7 +319,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_SamePrefix) {
// Exact selector with context test. Case when available suffix for all the
// occurrences of selected text is the same. In this case prefix should be
// extended until unique selector is found.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_SameSuffix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_SameSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -467,7 +342,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_SameSuffix) {
// Exact selector with context test. Case when available prefix and suffix for
// all the occurrences of selected text are the same. In this case generation
// should be unsuccessful.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_SamePrefixSuffix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_SamePrefixSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -489,7 +364,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_SamePrefixSuffix) {
// Exact selector with context test. Case when available prefix and suffix for
// all the occurrences of selected text are the same for the first 10 words. In
// this case generation should be unsuccessful.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_SimilarLongPreffixSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -512,7 +387,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
}
// Exact selector with context test. Case when no prefix is available.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_NoPrefix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_NoPrefix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -531,7 +406,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_NoPrefix) {
}
// Exact selector with context test. Case when no suffix is available.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_NoSuffix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_NoSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -553,7 +428,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_NoSuffix) {
// Exact selector with context test. Case when available prefix is the
// preceding block.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_PrevNodePrefix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_PrevNodePrefix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -574,7 +449,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_PrevNodePrefix) {
// Exact selector with context test. Case when available prefix is the
// preceding block, which is a text node.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_PrevTextNodePrefix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -597,7 +472,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// Exact selector with context test. Case when available suffix is the next
// block.
-TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_NextNodeSuffix) {
+TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_NextNodeSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -619,7 +494,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, ExactTextSelector_NextNodeSuffix) {
// Exact selector with context test. Case when available suffix is the next
// block, which is a text node.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
ExactTextSelector_NexttextNodeSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -640,7 +515,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
"First%20paragraph%20with-,not%20unique%20snippet,-text");
}
-TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector) {
+TEST_F(TextFragmentSelectorGeneratorTest, RangeSelector) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -662,7 +537,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector) {
// It should be more than 300 characters selected from the same node so that
// ranges are used.
-TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector_SameNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, RangeSelector_SameNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -691,7 +566,7 @@ text text text text text text text text text and last text",
// It should be more than 300 characters selected from the same node so that
// ranges are used.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
RangeSelector_SameNode_MultipleSelections) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -741,7 +616,7 @@ text text text text text text text text text text and last text",
// When using all the selected text for the range is not enough for unique
// match, context should be added.
-TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector_RangeNotUnique) {
+TEST_F(TextFragmentSelectorGeneratorTest, RangeSelector_RangeNotUnique) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -763,7 +638,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector_RangeNotUnique) {
// When using all the selected text for the range is not enough for unique
// match, context should be added, but only prefxi and no suffix is available.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
RangeSelector_RangeNotUnique_NoSuffix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -786,7 +661,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// When no range end is available it should return empty selector.
// There is no range end available because there is no word break in the second
// half of the selection.
-TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector_NoRangeEnd) {
+TEST_F(TextFragmentSelectorGeneratorTest, RangeSelector_NoRangeEnd) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -812,7 +687,7 @@ text_text_text_text_text_text_text_text_text_and_last_text",
}
// Selection should be autocompleted to contain full words.
-TEST_P(TextFragmentSelectorGeneratorTest, WordLimit) {
+TEST_F(TextFragmentSelectorGeneratorTest, WordLimit) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -832,7 +707,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, WordLimit) {
// Selection should be autocompleted to contain full words. The autocompletion
// should work with extra spaces.
-TEST_P(TextFragmentSelectorGeneratorTest, WordLimit_ExtraSpaces) {
+TEST_F(TextFragmentSelectorGeneratorTest, WordLimit_ExtraSpaces) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -854,7 +729,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, WordLimit_ExtraSpaces) {
// When selection starts at the end of a word, selection shouldn't be
// autocompleted to contain extra words.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
WordLimit_SelectionStartsAndEndsAtWordLimit) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -874,7 +749,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
}
// Check the case when selections starts with an non text node.
-TEST_P(TextFragmentSelectorGeneratorTest, StartsWithImage) {
+TEST_F(TextFragmentSelectorGeneratorTest, StartsWithImage) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -893,7 +768,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, StartsWithImage) {
}
// Check the case when selections starts with an non text node.
-TEST_P(TextFragmentSelectorGeneratorTest, StartsWithBlockWithImage) {
+TEST_F(TextFragmentSelectorGeneratorTest, StartsWithBlockWithImage) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -915,7 +790,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, StartsWithBlockWithImage) {
// Check the case when selections starts with a node nested in "inline-block"
// node. crbug.com/1151474
-TEST_P(TextFragmentSelectorGeneratorTest, StartsWithInlineBlockChild) {
+TEST_F(TextFragmentSelectorGeneratorTest, StartsWithInlineBlockChild) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -951,7 +826,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, StartsWithInlineBlockChild) {
}
// Check the case when selections ends with an non text node.
-TEST_P(TextFragmentSelectorGeneratorTest, EndswithImage) {
+TEST_F(TextFragmentSelectorGeneratorTest, EndswithImage) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -971,7 +846,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, EndswithImage) {
}
// Check the case when selections starts at the end of the previous block.
-TEST_P(TextFragmentSelectorGeneratorTest, StartIsEndofPrevBlock) {
+TEST_F(TextFragmentSelectorGeneratorTest, StartIsEndofPrevBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -989,7 +864,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, StartIsEndofPrevBlock) {
}
// Check the case when selections starts at the end of the previous block.
-TEST_P(TextFragmentSelectorGeneratorTest, EndIsStartofNextBlock) {
+TEST_F(TextFragmentSelectorGeneratorTest, EndIsStartofNextBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1019,7 +894,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, EndIsStartofNextBlock) {
// want to ensure it correctly traverses the tree back to the previous text node
// and not to the <div>(sibling of second <p>).
// See crbug.com/1154308 for more context.
-TEST_P(TextFragmentSelectorGeneratorTest, PrevNodeIsSiblingsChild) {
+TEST_F(TextFragmentSelectorGeneratorTest, PrevNodeIsSiblingsChild) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1053,7 +928,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, PrevNodeIsSiblingsChild) {
// want to ensure it correctly traverses the tree back to the previous text by
// correctly skipping the invisible div but not skipping the second <p>.
// See crbug.com/1154308 for more context.
-TEST_P(TextFragmentSelectorGeneratorTest, PrevPrevNodeIsSiblingsChild) {
+TEST_F(TextFragmentSelectorGeneratorTest, PrevPrevNodeIsSiblingsChild) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
// HTML is intentionally not formatted. Adding new lines and indentation
@@ -1074,7 +949,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, PrevPrevNodeIsSiblingsChild) {
// Checks that for short selection that have nested block element range selector
// is used.
-TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector_SameNode_Interrupted) {
+TEST_F(TextFragmentSelectorGeneratorTest, RangeSelector_SameNode_Interrupted) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1091,7 +966,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, RangeSelector_SameNode_Interrupted) {
}
// Check min number of words is used for context if possible.
-TEST_P(TextFragmentSelectorGeneratorTest, MultiwordContext) {
+TEST_F(TextFragmentSelectorGeneratorTest, MultiwordContext) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1111,7 +986,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, MultiwordContext) {
}
// Check min number of words is used for range if possible.
-TEST_P(TextFragmentSelectorGeneratorTest, MultiWordRangeSelector) {
+TEST_F(TextFragmentSelectorGeneratorTest, MultiWordRangeSelector) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1132,7 +1007,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, MultiWordRangeSelector) {
}
// Checks the case when selection end position is a non text node.
-TEST_P(TextFragmentSelectorGeneratorTest, SelectionEndsWithNonText) {
+TEST_F(TextFragmentSelectorGeneratorTest, SelectionEndsWithNonText) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1154,7 +1029,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, SelectionEndsWithNonText) {
// Checks the case when selection end position is a non text node which doesn't
// have text child node.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
SelectionEndsWithNonTextWithNoTextChild) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1177,7 +1052,7 @@ TEST_P(TextFragmentSelectorGeneratorTest,
// Checks the case when selection end position is a non text node which doesn't
// have text child node.
-TEST_P(TextFragmentSelectorGeneratorTest, SelectionEndsWithImageDiv) {
+TEST_F(TextFragmentSelectorGeneratorTest, SelectionEndsWithImageDiv) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1199,7 +1074,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, SelectionEndsWithImageDiv) {
// Checks the case when selected range contains a range with same start and end.
// The problematic case should have both range end and suffix.
-TEST_P(TextFragmentSelectorGeneratorTest, OverlappingRange) {
+TEST_F(TextFragmentSelectorGeneratorTest, OverlappingRange) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1217,7 +1092,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, OverlappingRange) {
}
// Checks selection across table cells.
-TEST_P(TextFragmentSelectorGeneratorTest, Table) {
+TEST_F(TextFragmentSelectorGeneratorTest, Table) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1246,7 +1121,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, Table) {
}
// Checks selection across an input element.
-TEST_P(TextFragmentSelectorGeneratorTest, Input) {
+TEST_F(TextFragmentSelectorGeneratorTest, Input) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1266,7 +1141,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, Input) {
// Checks selection across a shadow tree. Input that has text value will create
// a shadow tree,
-TEST_P(TextFragmentSelectorGeneratorTest, InputSubmit) {
+TEST_F(TextFragmentSelectorGeneratorTest, InputSubmit) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1286,7 +1161,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, InputSubmit) {
// Checks selection right after a shadow tree will use the shadow tree for
// prefix. Input with text value will create a shadow tree.
-TEST_P(TextFragmentSelectorGeneratorTest, InputSubmitPrefix) {
+TEST_F(TextFragmentSelectorGeneratorTest, InputSubmitPrefix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1306,7 +1181,7 @@ TEST_P(TextFragmentSelectorGeneratorTest, InputSubmitPrefix) {
// Checks selection right after a shadow tree will use the shadow tree for
// prefix. Input with text value will create a shadow tree.
-TEST_P(TextFragmentSelectorGeneratorTest, InputSubmitOneWordPrefix) {
+TEST_F(TextFragmentSelectorGeneratorTest, InputSubmitOneWordPrefix) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1324,36 +1199,8 @@ TEST_P(TextFragmentSelectorGeneratorTest, InputSubmitOneWordPrefix) {
VerifySelector(start, end, "button-,paragraph,-text");
}
-// TODO(crbug.com/1192047): Update the test to better reflect the real repro
-// steps. Test case for crash in crbug.com/1190137. When selector is requested
-// after callback is set and unused.
-TEST_P(TextFragmentSelectorGeneratorTest, SecondGenerationCrash) {
- SimRequest request("https://example.com/test.html", "text/html");
- LoadURL("https://example.com/test.html");
- request.Complete(R"HTML(
- <!DOCTYPE html>
- <p id='p'>First paragraph text</p>
- )HTML");
- GetDocument().UpdateStyleAndLayoutTree();
- Node* p = GetDocument().getElementById("p");
- const auto& start = Position(p->lastChild(), 0);
- const auto& end = Position(p->lastChild(), 15);
- ASSERT_EQ("First paragraph", PlainText(EphemeralRange(start, end)));
-
- auto callback = WTF::Bind([](const String& generated_selector) {});
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->SetCallbackForTesting(std::move(callback));
-
- // This shouldn't crash.
- GetDocument().GetFrame()->GetTextFragmentSelectorGenerator()->UpdateSelection(
- ToEphemeralRangeInFlatTree(EphemeralRange(start, end)));
- base::RunLoop().RunUntilIdle();
-}
-
// Basic test case for |GetNextTextBlock|.
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1365,14 +1212,13 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock) {
const auto& end = Position(first_paragraph, 20);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("First paragraph", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("First paragraph",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix contains collapsible space.
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_ExtraSpace) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_ExtraSpace) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1386,15 +1232,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_ExtraSpace) {
const auto& end = Position(first_paragraph, 30);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("First paragraph", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("First paragraph",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix complete text content of the previous
// block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_PrevNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_PrevNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1408,15 +1253,13 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_PrevNode) {
ASSERT_EQ("Second", PlainText(EphemeralRange(start, end)));
EXPECT_EQ("First paragraph text",
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when there is a commented block between selection and the
// available prefix.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetPreviousTextBlock_PrevNode_WithComment) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1434,15 +1277,13 @@ TEST_P(TextFragmentSelectorGeneratorTest,
ASSERT_EQ("Second", PlainText(EphemeralRange(start, end)));
EXPECT_EQ("First paragraph text",
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix is a text node outside of selection
// block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_PrevTextNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_PrevTextNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1455,15 +1296,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_PrevTextNode) {
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("text",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix is a parent node text content outside of
// selection block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_ParentNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_ParentNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1476,14 +1316,13 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_ParentNode) {
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("nested", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("nested",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix contains non-block tag(e.g. <b>).
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_NestedTextNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_NestedTextNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1496,14 +1335,12 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_NestedTextNode) {
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
EXPECT_EQ("First bold text paragraph",
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix is collected until nested block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_NestedBlock) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_NestedBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1515,15 +1352,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock_NestedBlock) {
const auto& end = Position(first_paragraph, 15);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("paragraph", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("paragraph",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix includes non-block element but stops at
// nested block.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetPreviousTextBlock_NestedBlockInNestedText) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1536,14 +1372,13 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 15);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("bold paragraph", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("bold paragraph",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when available prefix includes invisible block.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetPreviousTextBlock_NestedInvisibleBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1556,15 +1391,14 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 10);
ASSERT_EQ("paragraph", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("First", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ EXPECT_EQ("First",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when previous node is used for available prefix when selection
// is not at index=0 but there is only space before it.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetPreviousTextBlock_SpacesBeforeSelection) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1581,15 +1415,13 @@ TEST_P(TextFragmentSelectorGeneratorTest,
ASSERT_EQ("Second", PlainText(EphemeralRange(start, end)));
EXPECT_EQ("First paragraph text",
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Check the case when previous node is used for available prefix when selection
// is not at index=0 but there is only invisible block.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetPreviousTextBlock_InvisibleBeforeSelection) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1610,16 +1442,14 @@ TEST_P(TextFragmentSelectorGeneratorTest,
ASSERT_EQ("Second", PlainText(EphemeralRange(start, end)));
EXPECT_EQ("First paragraph text",
- GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetPreviousTextBlockForTesting(start));
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
// Similar test for suffix.
// Basic test case for |GetNextTextBlock|.
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1631,14 +1461,13 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock) {
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix contains collapsible space.
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_ExtraSpace) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock_ExtraSpace) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1653,15 +1482,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_ExtraSpace) {
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix is complete text content of the next
// block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NextNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NextNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1674,15 +1502,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NextNode) {
const auto& end = Position(first_paragraph, 20);
ASSERT_EQ("First paragraph text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("Second paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "Second paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when there is a commented block between selection and the
// available suffix.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetNextTextBlock_NextNode_WithComment) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1699,15 +1526,14 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 20);
ASSERT_EQ("First paragraph text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("Second paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "Second paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix is a text node outside of selection
// block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NextTextNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NextTextNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1720,15 +1546,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NextTextNode) {
const auto& end = Position(first_paragraph, 20);
ASSERT_EQ("First paragraph text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix is a parent node text content outside of
// selection block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_ParentNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock_ParentNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1740,14 +1565,13 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_ParentNode) {
const auto& end = Position(first_paragraph, 20);
ASSERT_EQ("First paragraph text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("nested", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "nested",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix contains non-block tag(e.g. <b>).
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NestedTextNode) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NestedTextNode) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1759,14 +1583,13 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NestedTextNode) {
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("bold text paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "bold text paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix is collected until nested block.
-TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NestedBlock) {
+TEST_F(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NestedBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
@@ -1778,15 +1601,14 @@ TEST_P(TextFragmentSelectorGeneratorTest, GetNextTextBlock_NestedBlock) {
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("paragraph", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "paragraph",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix includes non-block element but stops at
// nested block.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetNextTextBlock_NestedBlockInNestedText) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1799,14 +1621,13 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("bold", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "bold",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when available suffix includes invisible block.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetNextTextBlock_NestedInvisibleBlock) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1819,15 +1640,14 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 5);
ASSERT_EQ("First", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when next node is used for available suffix when selection is
// not at last index but there is only space after it.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetNextTextBlock_SpacesAfterSelection) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1845,15 +1665,14 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 27);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("Second paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "Second paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when next node is used for available suffix when selection is
// not at last index but there is only invisible block after it.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetNextTextBlock_InvisibleAfterSelection) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1874,16 +1693,15 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 27);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("Second paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "Second paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
}
// Check the case when previous node is used for available prefix when selection
// is not at last index but there is only invisible block. Invisible block
// contains another block which also should be invisible.
-TEST_P(TextFragmentSelectorGeneratorTest,
+TEST_F(TextFragmentSelectorGeneratorTest,
GetNextTextBlock_InvisibleAfterSelection_WithNestedInvisible) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1914,56 +1732,92 @@ TEST_P(TextFragmentSelectorGeneratorTest,
const auto& end = Position(first_paragraph, 27);
ASSERT_EQ("text", PlainText(EphemeralRange(start, end)));
- EXPECT_EQ("Second paragraph text", GetDocument()
- .GetFrame()
- ->GetTextFragmentSelectorGenerator()
- ->GetNextTextBlockForTesting(end));
+ EXPECT_EQ(
+ "Second paragraph text",
+ GetTextFragmentSelectorGenerator()->GetNextTextBlockForTesting(end));
+}
+
+TEST_F(TextFragmentSelectorGeneratorTest, BeforeAndAfterAnchor) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ Foo
+ <div id="first">Hello World</div>
+ Bar
+ )HTML");
+
+ Node* node = GetDocument().getElementById("first");
+ const auto& start = Position(node, PositionAnchorType::kBeforeAnchor);
+ const auto& end = Position(node, PositionAnchorType::kAfterAnchor);
+ VerifySelectorFails(start, end, LinkGenerationError::kEmptySelection);
}
-TEST_P(TextFragmentSelectorGeneratorTest, CheckMetrics_Success) {
+// Check the case when GetPreviousTextBlock is an EOL node from Shadow Root.
+// SharedHighlightingLayoutObjectFix feature disabled does not ensures that the
+// next previous non-empty visible text has a layout object. See
+// crbug.com/1233762 for more context.
+TEST_F(TextFragmentSelectorGeneratorTest,
+ GetPreviousTextBlock_ShouldCrashWithNoLayoutObject) {
base::test::ScopedFeatureList feature_list;
- // Basic exact selector case.
+ feature_list.InitAndDisableFeature(
+ shared_highlighting::kSharedHighlightingLayoutObjectFix);
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
<!DOCTYPE html>
- <div>Test page</div>
- <p id='first'>First paragraph text that is longer than 20 chars</p>
- <p id='second'>Second paragraph text</p>
+ <div id="host1"></div>
)HTML");
- Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
- const auto& selected_start = Position(first_paragraph, 0);
- const auto& selected_end = Position(first_paragraph, 28);
- ASSERT_EQ("First paragraph text that is",
- PlainText(EphemeralRange(selected_start, selected_end)));
+ ShadowRoot& shadow1 =
+ GetDocument().getElementById("host1")->AttachShadowRootInternal(
+ ShadowRootType::kOpen);
+ shadow1.setInnerHTML(R"HTML(
+ <style>
+ :host {display: contents;}
+ </style>
+ <p>Right click the link below to experience a crash:</p>
+ <a href="/foo" id='first'>I crash</a>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhasesForTest();
- VerifySelector(selected_start, selected_end,
- "First%20paragraph%20text%20that%20is");
- VerifyPreemptiveGenerationMetrics(true);
+ EXPECT_FALSE(GetDocument().View()->NeedsLayout());
+ Node* first_paragraph = shadow1.getElementById("first")->firstChild();
+ const auto& start = Position(first_paragraph, 0);
+ EXPECT_DEATH(
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(start),
+ "");
}
-TEST_P(TextFragmentSelectorGeneratorTest, CheckMetrics_Failure) {
+// Check the case when GetPreviousTextBlock is an EOL node from Shadow Root.
+// SharedHighlightingLayoutObjectFix feature enabled ensures that the next
+// previous non-empty visible text node has a layout object. See
+// crbug.com/1233762 for more context.
+TEST_F(TextFragmentSelectorGeneratorTest,
+ GetPreviousTextBlock_ShouldSkipNodesWithNoLayoutObject) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
<!DOCTYPE html>
- <div>Test page</div>
- <p id='first'>First paragraph prefix one two three four five six seven
- eight nine ten to not unique snippet of text followed by suffix</p>
- <p id='second'>Second paragraph prefix one two three four five six seven
- eight nine ten to not unique snippet of text followed by suffix</p>
+ <div id="host1"></div>
)HTML");
- Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
- const auto& selected_start = Position(first_paragraph, 80);
- const auto& selected_end = Position(first_paragraph, 106);
- ASSERT_EQ("not unique snippet of text",
- PlainText(EphemeralRange(selected_start, selected_end)));
- VerifySelectorFails(selected_start, selected_end,
- LinkGenerationError::kContextLimitReached);
- VerifyPreemptiveGenerationMetrics(false);
+ ShadowRoot& shadow1 =
+ GetDocument().getElementById("host1")->AttachShadowRootInternal(
+ ShadowRootType::kOpen);
+ shadow1.setInnerHTML(R"HTML(
+ <style>
+ :host {display: contents;}
+ </style>
+ <p>Right click the link below to experience a crash:</p>
+ <a href="/foo" id='first'>I crash</a>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(GetDocument().View()->NeedsLayout());
+ Node* first_paragraph = shadow1.getElementById("first")->firstChild();
+ const auto& start = Position(first_paragraph, 0);
+ EXPECT_EQ("Right click the link below to experience a crash:",
+ GetTextFragmentSelectorGenerator()->GetPreviousTextBlockForTesting(
+ start));
}
-INSTANTIATE_TEST_SUITE_P(All,
- TextFragmentSelectorGeneratorTest,
- ::testing::Bool());
} // namespace blink
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 81de43b7739..a2ec423002c 100644
--- a/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -19,7 +19,6 @@
#include "third_party/blink/renderer/core/page/touch_adjustment.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -41,6 +40,7 @@
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -89,7 +89,8 @@ typedef float (*DistanceFunction)(const IntPoint&,
const IntRect&,
const SubtargetGeometry&);
-// Takes non-const Node* because isContentEditable is a non-const function.
+// Takes non-const |Node*| because |Node::WillRespondToMouseClickEvents()| is
+// non-const.
bool NodeRespondsToTapGesture(Node* node) {
if (node->WillRespondToMouseClickEvents() ||
node->WillRespondToMouseMoveEvents())
@@ -253,7 +254,7 @@ void CompileSubtargetList(const HeapVector<Member<Node>>& intersected_nodes,
visited_node = visited_node->ParentOrShadowHostNode()) {
// Check if we already have a result for a common ancestor from another
// candidate.
- responding_node = responder_map.at(visited_node);
+ responding_node = responder_map.DeprecatedAtOrEmptyValue(visited_node);
if (responding_node)
break;
visited_nodes.push_back(visited_node);
@@ -286,7 +287,8 @@ void CompileSubtargetList(const HeapVector<Member<Node>>& intersected_nodes,
// line-breaks.
for (unsigned i = 0; i < candidates.size(); i++) {
Node* candidate = candidates[i];
- // Skip nodes who's responders are ancestors of other responders. This gives
+
+ // Skip nodes whose responders are ancestors of other responders. This gives
// preference to the inner-most event-handlers. So that a link is always
// preferred even when contained in an element that monitors all
// click-events.
@@ -294,6 +296,7 @@ void CompileSubtargetList(const HeapVector<Member<Node>>& intersected_nodes,
DCHECK(responding_node);
if (ancestors_to_responders_set.Contains(responding_node))
continue;
+
// Consolidate bounds for editable content.
if (editable_ancestors.Contains(candidate))
continue;
@@ -301,7 +304,10 @@ void CompileSubtargetList(const HeapVector<Member<Node>>& intersected_nodes,
if (HasEditableStyle(*candidate)) {
Node* replacement = candidate;
Node* parent = candidate->ParentOrShadowHostNode();
- while (parent && HasEditableStyle(*parent)) {
+
+ // Ignore parents without layout objects. E.g. editable elements with
+ // display:contents. https://crbug.com/1196872
+ while (parent && HasEditableStyle(*parent) && parent->GetLayoutObject()) {
replacement = parent;
if (editable_ancestors.Contains(replacement)) {
replacement = nullptr;
diff --git a/chromium/third_party/blink/renderer/core/page/touch_adjustment_test.cc b/chromium/third_party/blink/renderer/core/page/touch_adjustment_test.cc
index 795e520ee5c..9a017795912 100644
--- a/chromium/third_party/blink/renderer/core/page/touch_adjustment_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/touch_adjustment_test.cc
@@ -5,8 +5,8 @@
#include "third_party/blink/renderer/core/page/touch_adjustment.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -20,12 +20,12 @@ class FakeChromeClient : public RenderingTestChromeClient {
screen_info_.device_scale_factor = device_scale_factor;
}
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
return screen_info_;
}
private:
- ScreenInfo screen_info_;
+ display::ScreenInfo screen_info_;
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/page/viewport_description.cc b/chromium/third_party/blink/renderer/core/page/viewport_description.cc
index 6955d535961..0ee19c1e705 100644
--- a/chromium/third_party/blink/renderer/core/page/viewport_description.cc
+++ b/chromium/third_party/blink/renderer/core/page/viewport_description.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/page/viewport_description.h"
+#include "base/metrics/histogram_macros.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"
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 8c50727249d..5c5b0f07de5 100644
--- a/chromium/third_party/blink/renderer/core/page/viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/viewport_test.cc
@@ -58,17 +58,6 @@
namespace blink {
-class DSFStateTestingPlatformSupport : public TestingPlatformSupport {
- public:
- bool IsUseZoomForDSFEnabled() override { return use_zoom_for_dsf_; }
- void SetUseZoomForDSF(bool use_zoom_for_dsf) {
- use_zoom_for_dsf_ = use_zoom_for_dsf;
- }
-
- private:
- bool use_zoom_for_dsf_ = false;
-};
-
class ViewportTest : public testing::Test {
protected:
ViewportTest()
@@ -107,7 +96,7 @@ class ViewportTest : public testing::Test {
std::string chrome_url_;
private:
- ScopedTestingPlatformSupport<DSFStateTestingPlatformSupport> platform_;
+ ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
};
static void SetViewportSettings(WebSettings* settings) {
@@ -3151,6 +3140,36 @@ TEST_F(ViewportTest, viewportUseZoomForDSF4) {
EXPECT_TRUE(page->GetViewportDescription().user_zoom);
}
+// Verifies that the value clamping from
+// https://www.w3.org/TR/css-device-adapt-1/#width-and-height-properties
+// applies to CSS pixel not physical pixel.
+TEST_F(ViewportTest, viewportUseZoomForDSF5) {
+ RegisterMockedHttpURLLoad("viewport/viewport-48.html");
+ SetUseZoomForDSF(true);
+
+ frame_test_helpers::WebViewHelper web_view_helper;
+ WebViewImpl* web_view_impl =
+ web_view_helper.InitializeWithSettings(SetViewportSettings);
+ web_view_impl->MainFrameWidget()->SetDeviceScaleFactorForTesting(4.f);
+ frame_test_helpers::LoadFrame(web_view_impl->MainFrameImpl(),
+ base_url_ + "viewport/viewport-48.html");
+
+ Page* page = web_view_helper.GetWebView()->GetPage();
+ // Initial width and height must be scaled by DSF when --use-zoom-for-dsf
+ // is enabled.
+ PageScaleConstraints constraints = RunViewportTest(page, 960, 1056);
+
+ // When --use-zoom-for-dsf is enabled,
+ // constraints layout width == 3000 * DSF = 12000 and it should not be clamped
+ // to 10000.
+ EXPECT_EQ(12000, constraints.layout_size.Width());
+ EXPECT_EQ(1056, constraints.layout_size.Height());
+ EXPECT_NEAR(1.0f, constraints.initial_scale, 0.01f);
+ EXPECT_NEAR(0.25f, constraints.minimum_scale, 0.01f);
+ EXPECT_NEAR(5.0f, constraints.maximum_scale, 0.01f);
+ EXPECT_TRUE(page->GetViewportDescription().user_zoom);
+}
+
class ViewportHistogramsTest : public SimTest {
public:
ViewportHistogramsTest() = default;
diff --git a/chromium/third_party/blink/renderer/core/paint/DEPS b/chromium/third_party/blink/renderer/core/paint/DEPS
index 00b071d198a..6fb36eba5f9 100644
--- a/chromium/third_party/blink/renderer/core/paint/DEPS
+++ b/chromium/third_party/blink/renderer/core/paint/DEPS
@@ -8,7 +8,7 @@ include_rules = [
]
specific_include_rules = {
- "(theme_painter|theme_painter_default|object_painter_base)\.cc": [
+ "(theme_painter|theme_painter_default|outline_painter)\.cc": [
"+ui/native_theme/native_theme.h",
"+ui/native_theme/native_theme_base.h",
"+ui/gfx/color_utils.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/OWNERS b/chromium/third_party/blink/renderer/core/paint/OWNERS
index 51aafa98fea..3c3161d0130 100644
--- a/chromium/third_party/blink/renderer/core/paint/OWNERS
+++ b/chromium/third_party/blink/renderer/core/paint/OWNERS
@@ -1,11 +1,7 @@
# OWNERS specializing in painting code.
-
chrishtr@chromium.org
-enne@chromium.org
fmalita@chromium.org
fs@opera.com
pdr@chromium.org
schenney@chromium.org
-senorblanco@chromium.org
-trchen@chromium.org
wangxianzhu@chromium.org
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 193ab56845d..67e8f8c2d90 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
@@ -62,7 +62,7 @@ PhysicalOffset AccumulatedScrollOffsetForFixedBackground(
block && !skip_info.AncestorSkipped();
block = block->ContainingBlock(&skip_info)) {
if (block->IsScrollContainer())
- result += PhysicalOffsetToBeNoop(block->ScrolledContentOffset());
+ result += block->ScrolledContentOffset();
if (block == container)
break;
}
@@ -355,7 +355,7 @@ PhysicalRect FixedAttachmentPositioningArea(
return rect;
// The LayoutView is the only object that can paint a fixed background into
// its scrolling contents layer, so it gets a special adjustment here.
- rect.offset = PhysicalOffsetToBeNoop(layout_view->ScrolledContentOffset());
+ rect.offset = layout_view->ScrolledContentOffset();
}
rect.Move(AccumulatedScrollOffsetForFixedBackground(obj, container));
@@ -692,8 +692,7 @@ void BackgroundImageGeometry::CalculateFillTileSize(
? snapped_positioning_area_size
: unsnapped_positioning_area_size;
PhysicalSize image_intrinsic_size = PhysicalSize::FromFloatSizeFloor(
- image->ImageSize(positioning_box_->GetDocument(),
- positioning_box_->StyleRef().EffectiveZoom(),
+ image->ImageSize(positioning_box_->StyleRef().EffectiveZoom(),
FloatSize(positioning_area_size),
LayoutObject::ShouldRespectImageOrientation(box_)));
switch (type) {
@@ -979,4 +978,14 @@ PhysicalOffset BackgroundImageGeometry::OffsetInBackground(
return element_positioning_area_offset_;
}
+PhysicalOffset BackgroundImageGeometry::ComputeDestPhase() const {
+ // Given the size that the whole image should draw at, and the input phase
+ // requested by the content, and the space between repeated tiles, compute a
+ // phase that is no more than one size + space in magnitude.
+ const PhysicalSize step_per_tile = tile_size_ + repeat_spacing_;
+ const PhysicalOffset phase = {IntMod(-phase_.left, step_per_tile.width),
+ IntMod(-phase_.top, step_per_tile.height)};
+ return snapped_dest_rect_.offset + phase;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.h b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.h
index 9f294ef3b73..52c2f4593bc 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
@@ -64,6 +64,9 @@ class BackgroundImageGeometry {
const PhysicalRect& UnsnappedDestRect() const { return unsnapped_dest_rect_; }
const PhysicalRect& SnappedDestRect() const { return snapped_dest_rect_; }
+ // Compute the phase relative to the (snapped) destination offset.
+ PhysicalOffset ComputeDestPhase() const;
+
// 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
diff --git a/chromium/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc
index d060df86a42..0b95523e435 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/paint/box_paint_invalidator.h"
+#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
namespace blink {
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 1fc8030a694..93455b24c9a 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter.cc
@@ -135,17 +135,8 @@ void BlockPainter::PaintChildren(const PaintInfo& paint_info) {
if (paint_info.DescendantPaintingBlocked())
return;
- // We may use legacy paint to paint the anonymous fieldset child. The layout
- // object for the rendered legend will be a child of that one, and has to be
- // skipped here, since it's handled by a special NG fieldset painter.
- bool may_contain_rendered_legend =
- layout_block_.IsAnonymousNGFieldsetContentWrapper();
for (LayoutBox* child = layout_block_.FirstChildBox(); child;
child = child->NextSiblingBox()) {
- if (may_contain_rendered_legend && child->IsRenderedLegend()) {
- may_contain_rendered_legend = false;
- continue;
- }
PaintChild(*child, paint_info);
}
}
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 c9906300cb6..e75ba37e2be 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
@@ -166,10 +166,10 @@ TEST_P(BlockPainterTest, BlockingWheelEventRectSubsequenceCaching) {
// Trigger a repaint with the whole stacking-context subsequence cached.
GetLayoutView().Layer()->SetNeedsRepaint();
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(1u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(1u, counter.num_cached_items);
+ EXPECT_EQ(1u, counter.num_cached_subsequences);
EXPECT_SUBSEQUENCE_FROM_CHUNK(hit_test_client,
ContentPaintChunks().begin() + 1, 1);
@@ -217,10 +217,10 @@ TEST_P(BlockPainterTest, WheelEventRectPaintCaching) {
ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(2, &hit_test_data)));
sibling_element->setAttribute(html_names::kStyleAttr, "background: green;");
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
// Only the background display item of the sibling should be invalidated.
- EXPECT_EQ(1u, counter.NumNewCachedItems());
+ EXPECT_EQ(1u, counter.num_cached_items);
EXPECT_THAT(ContentPaintChunks(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(2, &hit_test_data)));
@@ -432,10 +432,10 @@ TEST_P(BlockPainterTest, TouchActionRectSubsequenceCaching) {
// Trigger a repaint with the whole stacking-context subsequence cached.
GetLayoutView().Layer()->SetNeedsRepaint();
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(1u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(1u, counter.num_cached_items);
+ EXPECT_EQ(1u, counter.num_cached_subsequences);
EXPECT_SUBSEQUENCE_FROM_CHUNK(hit_test_client,
ContentPaintChunks().begin() + 1, 1);
@@ -480,10 +480,10 @@ TEST_P(BlockPainterTest, TouchActionRectPaintCaching) {
ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(2, &hit_test_data)));
sibling_element->setAttribute(html_names::kStyleAttr, "background: green;");
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
// Only the background display item of the sibling should be invalidated.
- EXPECT_EQ(1u, counter.NumNewCachedItems());
+ EXPECT_EQ(1u, counter.num_cached_items);
EXPECT_THAT(ContentPaintChunks(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(2, &hit_test_data)));
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 d6ca5091100..2340e9f10f4 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
@@ -6,10 +6,9 @@
#include <algorithm>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/paint/box_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/rounded_border_geometry.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -86,20 +85,6 @@ inline bool BorderStyleHasUnmatchedColorsAtCorner(EBorderStyle style,
return false;
}
-inline bool ColorsMatchAtCorner(BoxSide side,
- BoxSide adjacent_side,
- const BorderEdge edges[]) {
- if (!edges[static_cast<unsigned>(adjacent_side)].ShouldRender())
- return false;
-
- if (!edges[static_cast<unsigned>(side)].SharesColorWith(
- edges[static_cast<unsigned>(adjacent_side)]))
- return false;
-
- return !BorderStyleHasUnmatchedColorsAtCorner(
- edges[static_cast<unsigned>(side)].BorderStyle(), side, adjacent_side);
-}
-
inline bool BorderWillArcInnerEdge(const FloatSize& first_radius,
const FloatSize& second_radius) {
return !first_radius.IsZero() || !second_radius.IsZero();
@@ -140,15 +125,15 @@ inline bool BorderStylesRequireMiter(BoxSide side,
FloatRect CalculateSideRect(const FloatRoundedRect& outer_border,
const BorderEdge& edge,
- int side) {
+ BoxSide side) {
FloatRect side_rect = outer_border.Rect();
float width = edge.Width();
- if (side == static_cast<unsigned>(BoxSide::kTop))
+ if (side == BoxSide::kTop)
side_rect.SetHeight(width);
- else if (side == static_cast<unsigned>(BoxSide::kBottom))
+ else if (side == BoxSide::kBottom)
side_rect.ShiftYEdgeTo(side_rect.MaxY() - width);
- else if (side == static_cast<unsigned>(BoxSide::kLeft))
+ else if (side == BoxSide::kLeft)
side_rect.SetWidth(width);
else
side_rect.ShiftXEdgeTo(side_rect.MaxX() - width);
@@ -156,38 +141,6 @@ FloatRect CalculateSideRect(const FloatRoundedRect& outer_border,
return side_rect;
}
-FloatRect CalculateSideRectIncludingInner(const FloatRoundedRect& outer_border,
- const BorderEdge edges[],
- BoxSide side) {
- FloatRect side_rect = outer_border.Rect();
- float width;
-
- switch (side) {
- case BoxSide::kTop:
- width = side_rect.Height() -
- edges[static_cast<unsigned>(BoxSide::kBottom)].Width();
- side_rect.SetHeight(width);
- break;
- case BoxSide::kBottom:
- width = side_rect.Height() -
- edges[static_cast<unsigned>(BoxSide::kTop)].Width();
- side_rect.ShiftYEdgeTo(side_rect.MaxY() - width);
- break;
- case BoxSide::kLeft:
- width = side_rect.Width() -
- edges[static_cast<unsigned>(BoxSide::kRight)].Width();
- side_rect.SetWidth(width);
- break;
- case BoxSide::kRight:
- width = side_rect.Width() -
- edges[static_cast<unsigned>(BoxSide::kLeft)].Width();
- side_rect.ShiftXEdgeTo(side_rect.MaxX() - width);
- break;
- }
-
- return side_rect;
-}
-
FloatRoundedRect CalculateAdjustedInnerBorder(
const FloatRoundedRect& inner_border,
BoxSide side) {
@@ -276,20 +229,6 @@ FloatRoundedRect CalculateAdjustedInnerBorder(
return FloatRoundedRect(new_rect, new_radii);
}
-LayoutRectOutsets DoubleStripeInsets(const BorderEdge edges[],
- BorderEdge::DoubleBorderStripe stripe) {
- // Insets are representes as negative outsets.
- return LayoutRectOutsets(
- -edges[static_cast<unsigned>(BoxSide::kTop)].GetDoubleBorderStripeWidth(
- stripe),
- -edges[static_cast<unsigned>(BoxSide::kRight)].GetDoubleBorderStripeWidth(
- stripe),
- -edges[static_cast<unsigned>(BoxSide::kBottom)]
- .GetDoubleBorderStripeWidth(stripe),
- -edges[static_cast<unsigned>(BoxSide::kLeft)].GetDoubleBorderStripeWidth(
- stripe));
-}
-
void DrawSolidBorderRect(GraphicsContext& context,
const FloatRect& border_rect,
float border_width,
@@ -383,20 +322,25 @@ static_assert(static_cast<unsigned>(BoxSide::kLeft) == 3,
// before solid edges (inset/outset/groove/ridge/solid) to maximize overdraw
// opportunities.
const unsigned kStylePriority[] = {
- 0 /* BorderStyleNone */, 0 /* BorderStyleHidden */,
- 2 /* BorderStyleInset */, 2 /* BorderStyleGroove */,
- 2 /* BorderStyleOutset */, 2 /* BorderStyleRidge */,
- 1 /* BorderStyleDotted */, 1 /* BorderStyleDashed */,
- 3 /* BorderStyleSolid */, 1 /* BorderStyleDouble */
+ 0, // EBorderStyle::kNone
+ 0, // EBorderStyle::kHidden
+ 2, // EBorderStyle::kInset
+ 2, // EBorderStyle::kGroove
+ 2, // EBorderStyle::kOutset
+ 2, // EBorderStyle::kRidge,
+ 1, // EBorderStyle::kDotted
+ 1, // EBorderStyle::kDashed
+ 3, // EBorderStyle::kSolid
+ 1, // EBorderStyle::kDouble
};
// Given the same style, prefer drawing in non-adjacent order to minimize the
// number of sides which require miters.
const unsigned kSidePriority[] = {
- 0, /* BSTop */
- 2, /* BSRight */
- 1, /* BSBottom */
- 3, /* BSLeft */
+ 0, // BoxSide::kTop
+ 2, // BoxSide::kRight
+ 1, // BoxSide::kBottom
+ 3, // BoxSide::kLeft
};
// Edges sharing the same opacity. Stores both a side list and an edge bitfield
@@ -421,12 +365,297 @@ void ClipQuad(GraphicsContext& context,
context.ClipPath(path.detach(), antialiased ? kAntiAliased : kNotAntiAliased);
}
+void DrawDashedOrDottedBoxSide(GraphicsContext& context,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ BoxSide side,
+ Color color,
+ int thickness,
+ EBorderStyle style,
+ bool antialias) {
+ DCHECK_GT(thickness, 0);
+
+ GraphicsContextStateSaver state_saver(context);
+ context.SetShouldAntialias(antialias);
+ context.SetStrokeColor(color);
+ context.SetStrokeThickness(thickness);
+ context.SetStrokeStyle(style == EBorderStyle::kDashed ? kDashedStroke
+ : kDottedStroke);
+
+ switch (side) {
+ case BoxSide::kBottom:
+ case BoxSide::kTop: {
+ int mid_y = y1 + thickness / 2;
+ context.DrawLine(IntPoint(x1, mid_y), IntPoint(x2, mid_y));
+ break;
+ }
+ case BoxSide::kRight:
+ case BoxSide::kLeft: {
+ int mid_x = x1 + thickness / 2;
+ context.DrawLine(IntPoint(mid_x, y1), IntPoint(mid_x, y2));
+ break;
+ }
+ }
+}
+
+void DrawDoubleBoxSide(GraphicsContext& context,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ int length,
+ BoxSide side,
+ Color color,
+ float thickness,
+ int adjacent_width1,
+ int adjacent_width2,
+ bool antialias) {
+ int third_of_thickness = (thickness + 1) / 3;
+ DCHECK_GT(third_of_thickness, 0);
+
+ if (!adjacent_width1 && !adjacent_width2) {
+ StrokeStyle old_stroke_style = context.GetStrokeStyle();
+ context.SetStrokeStyle(kNoStroke);
+ context.SetFillColor(color);
+
+ bool was_antialiased = context.ShouldAntialias();
+ context.SetShouldAntialias(antialias);
+
+ switch (side) {
+ case BoxSide::kTop:
+ case BoxSide::kBottom:
+ context.DrawRect(IntRect(x1, y1, length, third_of_thickness));
+ context.DrawRect(
+ IntRect(x1, y2 - third_of_thickness, length, third_of_thickness));
+ break;
+ case BoxSide::kLeft:
+ case BoxSide::kRight:
+ context.DrawRect(IntRect(x1, y1, third_of_thickness, length));
+ context.DrawRect(
+ IntRect(x2 - third_of_thickness, y1, third_of_thickness, length));
+ break;
+ }
+
+ context.SetShouldAntialias(was_antialiased);
+ context.SetStrokeStyle(old_stroke_style);
+ return;
+ }
+
+ int adjacent1_big_third =
+ ((adjacent_width1 > 0) ? adjacent_width1 + 1 : adjacent_width1 - 1) / 3;
+ int adjacent2_big_third =
+ ((adjacent_width2 > 0) ? adjacent_width2 + 1 : adjacent_width2 - 1) / 3;
+
+ switch (side) {
+ case BoxSide::kTop:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0), y1,
+ x2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0),
+ y1 + third_of_thickness, side, color, EBorderStyle::kSolid,
+ adjacent1_big_third, adjacent2_big_third, antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max((adjacent_width1 * 2 + 1) / 3, 0),
+ y2 - third_of_thickness,
+ x2 - std::max((adjacent_width2 * 2 + 1) / 3, 0), y2, side, color,
+ EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
+ antialias);
+ break;
+ case BoxSide::kLeft:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1, y1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0),
+ x1 + third_of_thickness,
+ y2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0), side, color,
+ EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
+ antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x2 - third_of_thickness,
+ y1 + std::max((adjacent_width1 * 2 + 1) / 3, 0), x2,
+ y2 - std::max((adjacent_width2 * 2 + 1) / 3, 0), side, color,
+ EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
+ antialias);
+ break;
+ case BoxSide::kBottom:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max((adjacent_width1 * 2 + 1) / 3, 0), y1,
+ x2 - std::max((adjacent_width2 * 2 + 1) / 3, 0),
+ y1 + third_of_thickness, side, color, EBorderStyle::kSolid,
+ adjacent1_big_third, adjacent2_big_third, antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0),
+ y2 - third_of_thickness,
+ x2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0), y2, side, color,
+ EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
+ antialias);
+ break;
+ case BoxSide::kRight:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1, y1 + std::max((adjacent_width1 * 2 + 1) / 3, 0),
+ x1 + third_of_thickness,
+ y2 - std::max((adjacent_width2 * 2 + 1) / 3, 0), side, color,
+ EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
+ antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x2 - third_of_thickness,
+ y1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0), x2,
+ y2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0), side, color,
+ EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
+ antialias);
+ break;
+ default:
+ break;
+ }
+}
+
+void DrawRidgeOrGrooveBoxSide(GraphicsContext& context,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ BoxSide side,
+ Color color,
+ EBorderStyle style,
+ int adjacent_width1,
+ int adjacent_width2,
+ bool antialias) {
+ EBorderStyle s1;
+ EBorderStyle s2;
+ if (style == EBorderStyle::kGroove) {
+ s1 = EBorderStyle::kInset;
+ s2 = EBorderStyle::kOutset;
+ } else {
+ s1 = EBorderStyle::kOutset;
+ s2 = EBorderStyle::kInset;
+ }
+
+ int adjacent1_big_half =
+ ((adjacent_width1 > 0) ? adjacent_width1 + 1 : adjacent_width1 - 1) / 2;
+ int adjacent2_big_half =
+ ((adjacent_width2 > 0) ? adjacent_width2 + 1 : adjacent_width2 - 1) / 2;
+
+ switch (side) {
+ case BoxSide::kTop:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max(-adjacent_width1, 0) / 2, y1,
+ x2 - std::max(-adjacent_width2, 0) / 2, (y1 + y2 + 1) / 2, side,
+ color, s1, adjacent1_big_half, adjacent2_big_half, antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max(adjacent_width1 + 1, 0) / 2, (y1 + y2 + 1) / 2,
+ x2 - std::max(adjacent_width2 + 1, 0) / 2, y2, side, color, s2,
+ adjacent_width1 / 2, adjacent_width2 / 2, antialias);
+ break;
+ case BoxSide::kLeft:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1, y1 + std::max(-adjacent_width1, 0) / 2,
+ (x1 + x2 + 1) / 2, y2 - std::max(-adjacent_width2, 0) / 2, side,
+ color, s1, adjacent1_big_half, adjacent2_big_half, antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, (x1 + x2 + 1) / 2, y1 + std::max(adjacent_width1 + 1, 0) / 2,
+ x2, y2 - std::max(adjacent_width2 + 1, 0) / 2, side, color, s2,
+ adjacent_width1 / 2, adjacent_width2 / 2, antialias);
+ break;
+ case BoxSide::kBottom:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max(adjacent_width1, 0) / 2, y1,
+ x2 - std::max(adjacent_width2, 0) / 2, (y1 + y2 + 1) / 2, side, color,
+ s2, adjacent1_big_half, adjacent2_big_half, antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1 + std::max(-adjacent_width1 + 1, 0) / 2,
+ (y1 + y2 + 1) / 2, x2 - std::max(-adjacent_width2 + 1, 0) / 2, y2,
+ side, color, s1, adjacent_width1 / 2, adjacent_width2 / 2, antialias);
+ break;
+ case BoxSide::kRight:
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, x1, y1 + std::max(adjacent_width1, 0) / 2, (x1 + x2 + 1) / 2,
+ y2 - std::max(adjacent_width2, 0) / 2, side, color, s2,
+ adjacent1_big_half, adjacent2_big_half, antialias);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, (x1 + x2 + 1) / 2,
+ y1 + std::max(-adjacent_width1 + 1, 0) / 2, x2,
+ y2 - std::max(-adjacent_width2 + 1, 0) / 2, side, color, s1,
+ adjacent_width1 / 2, adjacent_width2 / 2, antialias);
+ break;
+ }
+}
+
+void FillQuad(GraphicsContext& context,
+ const FloatPoint quad[],
+ const Color& color,
+ bool antialias) {
+ SkPathBuilder path;
+ path.moveTo(FloatPointToSkPoint(quad[0]));
+ path.lineTo(FloatPointToSkPoint(quad[1]));
+ path.lineTo(FloatPointToSkPoint(quad[2]));
+ path.lineTo(FloatPointToSkPoint(quad[3]));
+ PaintFlags flags(context.FillFlags());
+ flags.setAntiAlias(antialias);
+ flags.setColor(color.Rgb());
+
+ context.DrawPath(path.detach(), flags);
+}
+
+void DrawSolidBoxSide(GraphicsContext& context,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ BoxSide side,
+ Color color,
+ int adjacent_width1,
+ int adjacent_width2,
+ bool antialias) {
+ DCHECK_GE(x2, x1);
+ DCHECK_GE(y2, y1);
+
+ if (!adjacent_width1 && !adjacent_width2) {
+ // Tweak antialiasing to match the behavior of fillQuad();
+ // this matters for rects in transformed contexts.
+ bool was_antialiased = context.ShouldAntialias();
+ if (antialias != was_antialiased)
+ context.SetShouldAntialias(antialias);
+ context.FillRect(IntRect(x1, y1, x2 - x1, y2 - y1), color);
+ if (antialias != was_antialiased)
+ context.SetShouldAntialias(was_antialiased);
+ return;
+ }
+
+ FloatPoint quad[4];
+ switch (side) {
+ case BoxSide::kTop:
+ quad[0] = FloatPoint(x1 + std::max(-adjacent_width1, 0), y1);
+ quad[1] = FloatPoint(x1 + std::max(adjacent_width1, 0), y2);
+ quad[2] = FloatPoint(x2 - std::max(adjacent_width2, 0), y2);
+ quad[3] = FloatPoint(x2 - std::max(-adjacent_width2, 0), y1);
+ break;
+ case BoxSide::kBottom:
+ quad[0] = FloatPoint(x1 + std::max(adjacent_width1, 0), y1);
+ quad[1] = FloatPoint(x1 + std::max(-adjacent_width1, 0), y2);
+ quad[2] = FloatPoint(x2 - std::max(-adjacent_width2, 0), y2);
+ quad[3] = FloatPoint(x2 - std::max(adjacent_width2, 0), y1);
+ break;
+ case BoxSide::kLeft:
+ quad[0] = FloatPoint(x1, y1 + std::max(-adjacent_width1, 0));
+ quad[1] = FloatPoint(x1, y2 - std::max(-adjacent_width2, 0));
+ quad[2] = FloatPoint(x2, y2 - std::max(adjacent_width2, 0));
+ quad[3] = FloatPoint(x2, y1 + std::max(adjacent_width1, 0));
+ break;
+ case BoxSide::kRight:
+ quad[0] = FloatPoint(x1, y1 + std::max(adjacent_width1, 0));
+ quad[1] = FloatPoint(x1, y2 - std::max(adjacent_width2, 0));
+ quad[2] = FloatPoint(x2, y2 - std::max(-adjacent_width2, 0));
+ quad[3] = FloatPoint(x2, y1 + std::max(-adjacent_width1, 0));
+ break;
+ }
+
+ FillQuad(context, quad, color, antialias);
+}
+
} // anonymous namespace
// Holds edges grouped by opacity and sorted in paint order.
struct BoxBorderPainter::ComplexBorderInfo {
- ComplexBorderInfo(const BoxBorderPainter& border_painter, bool anti_alias)
- : anti_alias(anti_alias) {
+ explicit ComplexBorderInfo(const BoxBorderPainter& border_painter) {
Vector<BoxSide, 4> sorted_sides;
// First, collect all visible sides.
@@ -442,10 +671,8 @@ struct BoxBorderPainter::ComplexBorderInfo {
// alpha, style, side.
std::sort(sorted_sides.begin(), sorted_sides.end(),
[&border_painter](BoxSide a, BoxSide b) -> bool {
- const BorderEdge& edge_a =
- border_painter.edges_[static_cast<unsigned>(a)];
- const BorderEdge& edge_b =
- border_painter.edges_[static_cast<unsigned>(b)];
+ const BorderEdge& edge_a = border_painter.Edge(a);
+ const BorderEdge& edge_b = border_painter.Edge(b);
const unsigned alpha_a = edge_a.color.Alpha();
const unsigned alpha_b = edge_b.color.Alpha();
@@ -475,15 +702,12 @@ struct BoxBorderPainter::ComplexBorderInfo {
// Potentially used when drawing rounded borders.
Path rounded_border_path;
- bool anti_alias;
-
private:
void BuildOpacityGroups(const BoxBorderPainter& border_painter,
const Vector<BoxSide, 4>& sorted_sides) {
unsigned current_alpha = 0;
for (BoxSide side : sorted_sides) {
- const BorderEdge& edge =
- border_painter.edges_[static_cast<unsigned>(side)];
+ const BorderEdge& edge = border_painter.Edge(side);
const unsigned edge_alpha = edge.color.Alpha();
DCHECK_GT(edge_alpha, 0u);
@@ -503,8 +727,7 @@ struct BoxBorderPainter::ComplexBorderInfo {
}
};
-void BoxBorderPainter::DrawDoubleBorder(GraphicsContext& context,
- const PhysicalRect& border_rect) const {
+void BoxBorderPainter::DrawDoubleBorder() const {
DCHECK(is_uniform_color_);
DCHECK(is_uniform_style_);
DCHECK(FirstEdge().BorderStyle() == EBorderStyle::kDouble);
@@ -516,30 +739,28 @@ void BoxBorderPainter::DrawDoubleBorder(GraphicsContext& context,
const auto force_rectangular = !outer_.IsRounded() && !inner_.IsRounded();
// outer stripe
- const LayoutRectOutsets outer_third_insets =
- DoubleStripeInsets(edges_, BorderEdge::kDoubleBorderStripeOuter);
+ const LayoutRectOutsets outer_third_outsets =
+ DoubleStripeOutsets(BorderEdge::kDoubleBorderStripeOuter);
FloatRoundedRect outer_third_rect =
- RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- style_, border_rect, outer_third_insets, sides_to_include_);
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style_, border_rect_, outer_third_outsets, sides_to_include_);
if (force_rectangular)
outer_third_rect.SetRadii(FloatRoundedRect::Radii());
- DrawBleedAdjustedDRRect(context, bleed_avoidance_, outer_, outer_third_rect,
+ DrawBleedAdjustedDRRect(context_, bleed_avoidance_, outer_, outer_third_rect,
color);
// inner stripe
- const LayoutRectOutsets inner_third_insets =
- DoubleStripeInsets(edges_, BorderEdge::kDoubleBorderStripeInner);
+ const LayoutRectOutsets inner_third_outsets =
+ DoubleStripeOutsets(BorderEdge::kDoubleBorderStripeInner);
FloatRoundedRect inner_third_rect =
- RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- style_, border_rect, inner_third_insets, sides_to_include_);
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style_, border_rect_, inner_third_outsets, sides_to_include_);
if (force_rectangular)
inner_third_rect.SetRadii(FloatRoundedRect::Radii());
- context.FillDRRect(inner_third_rect, inner_, color);
+ context_.FillDRRect(inner_third_rect, inner_, color);
}
-bool BoxBorderPainter::PaintBorderFastPath(
- GraphicsContext& context,
- const PhysicalRect& border_rect) const {
+bool BoxBorderPainter::PaintBorderFastPath() const {
if (!is_uniform_color_ || !is_uniform_style_ || !inner_.IsRenderable())
return false;
@@ -551,17 +772,17 @@ bool BoxBorderPainter::PaintBorderFastPath(
if (FirstEdge().BorderStyle() == EBorderStyle::kSolid) {
if (is_uniform_width_ && !outer_.IsRounded()) {
// 4-side, solid, uniform-width, rectangular border => one drawRect()
- DrawSolidBorderRect(context, outer_.Rect(), FirstEdge().Width(),
+ DrawSolidBorderRect(context_, outer_.Rect(), FirstEdge().Width(),
FirstEdge().color);
} else {
// 4-side, solid border => one drawDRRect()
- DrawBleedAdjustedDRRect(context, bleed_avoidance_, outer_, inner_,
+ DrawBleedAdjustedDRRect(context_, bleed_avoidance_, outer_, inner_,
FirstEdge().color);
}
} else {
// 4-side, double border => 2x drawDRRect()
DCHECK(FirstEdge().BorderStyle() == EBorderStyle::kDouble);
- DrawDoubleBorder(context, border_rect);
+ DrawDoubleBorder();
}
return true;
@@ -576,26 +797,29 @@ bool BoxBorderPainter::PaintBorderFastPath(
Path path;
path.SetWindRule(RULE_NONZERO);
- for (unsigned int i = static_cast<unsigned>(BoxSide::kTop);
- i <= static_cast<unsigned>(BoxSide::kLeft); ++i) {
- const BorderEdge& curr_edge = edges_[i];
+ for (auto side :
+ {BoxSide::kTop, BoxSide::kRight, BoxSide::kBottom, BoxSide::kLeft}) {
+ const BorderEdge& curr_edge = Edge(side);
if (curr_edge.ShouldRender())
- path.AddRect(CalculateSideRect(outer_, curr_edge, i));
+ path.AddRect(CalculateSideRect(outer_, curr_edge, side));
}
- context.SetFillColor(FirstEdge().color);
- context.FillPath(path);
+ context_.SetFillColor(FirstEdge().color);
+ context_.FillPath(path);
return true;
}
return false;
}
-BoxBorderPainter::BoxBorderPainter(const PhysicalRect& border_rect,
+BoxBorderPainter::BoxBorderPainter(GraphicsContext& context,
+ const PhysicalRect& border_rect,
const ComputedStyle& style,
BackgroundBleedAvoidance bleed_avoidance,
PhysicalBoxSides sides_to_include)
- : style_(style),
+ : context_(context),
+ border_rect_(border_rect),
+ style_(style),
bleed_avoidance_(bleed_avoidance),
sides_to_include_(sides_to_include),
visible_edge_count_(0),
@@ -622,23 +846,26 @@ BoxBorderPainter::BoxBorderPainter(const PhysicalRect& border_rect,
// can pixel snap smaller.
float max_width = outer_.Rect().Width();
float max_height = outer_.Rect().Height();
- edges_[static_cast<unsigned>(BoxSide::kTop)].ClampWidth(max_height);
- edges_[static_cast<unsigned>(BoxSide::kRight)].ClampWidth(max_width);
- edges_[static_cast<unsigned>(BoxSide::kBottom)].ClampWidth(max_height);
- edges_[static_cast<unsigned>(BoxSide::kLeft)].ClampWidth(max_width);
+ Edge(BoxSide::kTop).ClampWidth(max_height);
+ Edge(BoxSide::kRight).ClampWidth(max_width);
+ Edge(BoxSide::kBottom).ClampWidth(max_height);
+ Edge(BoxSide::kLeft).ClampWidth(max_width);
is_rounded_ = outer_.IsRounded();
}
-BoxBorderPainter::BoxBorderPainter(const ComputedStyle& style,
- const PhysicalRect& outer,
- const PhysicalRect& inner,
- const BorderEdge& uniform_edge_info)
- : style_(style),
+BoxBorderPainter::BoxBorderPainter(GraphicsContext& context,
+ const ComputedStyle& style,
+ const PhysicalRect& border_rect,
+ int inner_outset_x,
+ int inner_outset_y)
+ : context_(context),
+ border_rect_(border_rect),
+ outer_outset_x_(inner_outset_x + style.OutlineWidthInt()),
+ outer_outset_y_(inner_outset_y + style.OutlineWidthInt()),
+ style_(style),
bleed_avoidance_(kBackgroundBleedNone),
sides_to_include_(PhysicalBoxSides()),
- outer_(FloatRect(outer)),
- inner_(FloatRect(inner)),
visible_edge_count_(0),
first_visible_edge_(0),
visible_edge_set_(0),
@@ -647,10 +874,25 @@ BoxBorderPainter::BoxBorderPainter(const ComputedStyle& style,
is_uniform_color_(true),
is_rounded_(false),
has_alpha_(false) {
- for (auto& edge : edges_)
- edge = uniform_edge_info;
+ DCHECK(style.HasOutline());
+ BorderEdge edge(style.OutlineWidthInt(),
+ style.VisitedDependentColor(GetCSSPropertyOutlineColor()),
+ style.OutlineStyle());
+ for (auto& e : edges_)
+ e = edge;
ComputeBorderProperties();
+
+ outer_ = RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style, border_rect,
+ LayoutRectOutsets(outer_outset_y_, outer_outset_x_, outer_outset_y_,
+ outer_outset_x_));
+ is_rounded_ = outer_.IsRounded();
+
+ inner_ = RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style, border_rect,
+ LayoutRectOutsets(inner_outset_y, inner_outset_x, inner_outset_y,
+ inner_outset_x));
}
void BoxBorderPainter::ComputeBorderProperties() {
@@ -685,30 +927,27 @@ void BoxBorderPainter::ComputeBorderProperties() {
}
}
-void BoxBorderPainter::PaintBorder(const PaintInfo& info,
- const PhysicalRect& rect) const {
+void BoxBorderPainter::Paint() const {
if (!visible_edge_count_ || outer_.Rect().IsEmpty())
return;
- GraphicsContext& graphics_context = info.context;
-
- if (PaintBorderFastPath(graphics_context, rect))
+ if (PaintBorderFastPath())
return;
bool clip_to_outer_border = outer_.IsRounded();
- GraphicsContextStateSaver state_saver(graphics_context, clip_to_outer_border);
+ GraphicsContextStateSaver state_saver(context_, clip_to_outer_border);
if (clip_to_outer_border) {
// For BackgroundBleedClip{Only,Layer}, the outer rrect clip is already
// applied.
if (!BleedAvoidanceIsClipping(bleed_avoidance_))
- graphics_context.ClipRoundedRect(outer_);
+ context_.ClipRoundedRect(outer_);
if (inner_.IsRenderable() && !inner_.IsEmpty())
- graphics_context.ClipOutRoundedRect(inner_);
+ context_.ClipOutRoundedRect(inner_);
}
- const ComplexBorderInfo border_info(*this, true);
- PaintOpacityGroup(graphics_context, border_info, 0, 1);
+ const ComplexBorderInfo border_info(*this);
+ PaintOpacityGroup(border_info, 0, 1);
}
// In order to maximize the use of overdraw as a corner seam avoidance
@@ -721,11 +960,11 @@ void BoxBorderPainter::PaintBorder(const PaintInfo& info,
// transparency layers with adjusted/relative opacity [paintOpacityGroup]
// 4) iterate over groups (increasing opacity order), painting actual group
// contents and then ending their corresponding transparency layer
-// [paintOpacityGroup]
+// [PaintOpacityGroup]
//
// Layers are created in decreasing opacity order (top -> bottom), while actual
// border sides are drawn in increasing opacity order (bottom -> top). At each
-// level, opacity is adjusted to acount for accumulated/ancestor layer alpha.
+// level, opacity is adjusted to account for accumulated/ancestor layer alpha.
// Because opacity is applied via layers, the actual draw paint is opaque.
//
// As an example, let's consider a border with the following sides/opacities:
@@ -756,7 +995,6 @@ void BoxBorderPainter::PaintBorder(const PaintInfo& info,
// content - hence we can use overdraw to mask portions of the previous sides.
//
BorderEdgeFlags BoxBorderPainter::PaintOpacityGroup(
- GraphicsContext& context,
const ComplexBorderInfo& border_info,
unsigned index,
float effective_opacity) const {
@@ -789,7 +1027,7 @@ BorderEdgeFlags BoxBorderPainter::PaintOpacityGroup(
const float group_opacity = static_cast<float>(group.alpha) / 255;
DCHECK_LT(group_opacity, effective_opacity);
- context.BeginLayer(group_opacity / effective_opacity);
+ context_.BeginLayer(group_opacity / effective_opacity);
effective_opacity = group_opacity;
// Group opacity is applied via a layer => we draw the members using opaque
@@ -802,27 +1040,26 @@ BorderEdgeFlags BoxBorderPainter::PaintOpacityGroup(
// b) only triggers at all when mixing border sides with different opacities
// c) it allows us to express the layer nesting algorithm more naturally
BorderEdgeFlags completed_edges =
- PaintOpacityGroup(context, border_info, index + 1, effective_opacity);
+ PaintOpacityGroup(border_info, index + 1, effective_opacity);
// Paint the actual group edges with an alpha adjusted to account for
// ancenstor layers opacity.
for (BoxSide side : group.sides) {
- PaintSide(context, border_info, side, paint_alpha, completed_edges);
+ PaintSide(border_info, side, paint_alpha, completed_edges);
completed_edges |= EdgeFlagForSide(side);
}
if (needs_layer)
- context.EndLayer();
+ context_.EndLayer();
return completed_edges;
}
-void BoxBorderPainter::PaintSide(GraphicsContext& context,
- const ComplexBorderInfo& border_info,
+void BoxBorderPainter::PaintSide(const ComplexBorderInfo& border_info,
BoxSide side,
unsigned alpha,
BorderEdgeFlags completed_edges) const {
- const BorderEdge& edge = edges_[static_cast<unsigned>(side)];
+ const BorderEdge& edge = Edge(side);
DCHECK(edge.ShouldRender());
const Color color(edge.color.Red(), edge.color.Green(), edge.color.Blue(),
alpha);
@@ -843,9 +1080,8 @@ void BoxBorderPainter::PaintSide(GraphicsContext& context,
else
side_rect.SetHeight(floorf(edge.Width()));
- PaintOneBorderSide(context, side_rect, BoxSide::kTop, BoxSide::kLeft,
- BoxSide::kRight, path, border_info.anti_alias, color,
- completed_edges);
+ PaintOneBorderSide(side_rect, BoxSide::kTop, BoxSide::kLeft,
+ BoxSide::kRight, path, color, completed_edges);
break;
}
case BoxSide::kBottom: {
@@ -858,9 +1094,8 @@ void BoxBorderPainter::PaintSide(GraphicsContext& context,
else
side_rect.ShiftYEdgeTo(side_rect.MaxY() - floorf(edge.Width()));
- PaintOneBorderSide(context, side_rect, BoxSide::kBottom, BoxSide::kLeft,
- BoxSide::kRight, path, border_info.anti_alias, color,
- completed_edges);
+ PaintOneBorderSide(side_rect, BoxSide::kBottom, BoxSide::kLeft,
+ BoxSide::kRight, path, color, completed_edges);
break;
}
case BoxSide::kLeft: {
@@ -873,9 +1108,8 @@ void BoxBorderPainter::PaintSide(GraphicsContext& context,
else
side_rect.SetWidth(floorf(edge.Width()));
- PaintOneBorderSide(context, side_rect, BoxSide::kLeft, BoxSide::kTop,
- BoxSide::kBottom, path, border_info.anti_alias, color,
- completed_edges);
+ PaintOneBorderSide(side_rect, BoxSide::kLeft, BoxSide::kTop,
+ BoxSide::kBottom, path, color, completed_edges);
break;
}
case BoxSide::kRight: {
@@ -888,9 +1122,8 @@ void BoxBorderPainter::PaintSide(GraphicsContext& context,
else
side_rect.ShiftXEdgeTo(side_rect.MaxX() - floorf(edge.Width()));
- PaintOneBorderSide(context, side_rect, BoxSide::kRight, BoxSide::kTop,
- BoxSide::kBottom, path, border_info.anti_alias, color,
- completed_edges);
+ PaintOneBorderSide(side_rect, BoxSide::kRight, BoxSide::kTop,
+ BoxSide::kBottom, path, color, completed_edges);
break;
}
default:
@@ -901,10 +1134,8 @@ void BoxBorderPainter::PaintSide(GraphicsContext& context,
BoxBorderPainter::MiterType BoxBorderPainter::ComputeMiter(
BoxSide side,
BoxSide adjacent_side,
- BorderEdgeFlags completed_edges,
- bool antialias) const {
- const BorderEdge& adjacent_edge =
- edges_[static_cast<unsigned>(adjacent_side)];
+ BorderEdgeFlags completed_edges) const {
+ const BorderEdge& adjacent_edge = Edge(adjacent_side);
// No miters for missing edges.
if (!adjacent_edge.is_present)
@@ -916,15 +1147,13 @@ BoxBorderPainter::MiterType BoxBorderPainter::ComputeMiter(
// Color transitions require miters. Use miters compatible with the AA drawing
// mode to avoid introducing extra clips.
- if (!ColorsMatchAtCorner(side, adjacent_side, edges_))
- return antialias ? kSoftMiter : kHardMiter;
+ if (!ColorsMatchAtCorner(side, adjacent_side))
+ return kSoftMiter;
// Non-anti-aliased miters ensure correct same-color seaming when required by
// style.
- if (BorderStylesRequireMiter(
- side, adjacent_side,
- edges_[static_cast<unsigned>(side)].BorderStyle(),
- adjacent_edge.BorderStyle()))
+ if (BorderStylesRequireMiter(side, adjacent_side, Edge(side).BorderStyle(),
+ adjacent_edge.BorderStyle()))
return kHardMiter;
// Overdraw the adjacent edge when the colors match and we have no style
@@ -934,12 +1163,10 @@ BoxBorderPainter::MiterType BoxBorderPainter::ComputeMiter(
bool BoxBorderPainter::MitersRequireClipping(MiterType miter1,
MiterType miter2,
- EBorderStyle style,
- bool antialias) {
+ EBorderStyle style) {
// Clipping is required if any of the present miters doesn't match the current
// AA mode.
- bool should_clip = antialias ? miter1 == kHardMiter || miter2 == kHardMiter
- : miter1 == kSoftMiter || miter2 == kSoftMiter;
+ bool should_clip = miter1 == kHardMiter || miter2 == kHardMiter;
// Some styles require clipping for any type of miter.
should_clip = should_clip || ((miter1 != kNoMiter || miter2 != kNoMiter) &&
@@ -949,69 +1176,57 @@ bool BoxBorderPainter::MitersRequireClipping(MiterType miter1,
}
void BoxBorderPainter::PaintOneBorderSide(
- GraphicsContext& graphics_context,
const FloatRect& side_rect,
BoxSide side,
BoxSide adjacent_side1,
BoxSide adjacent_side2,
const Path* path,
- bool antialias,
Color color,
BorderEdgeFlags completed_edges) const {
- const BorderEdge& edge_to_render = edges_[static_cast<unsigned>(side)];
+ const BorderEdge& edge_to_render = Edge(side);
DCHECK(edge_to_render.Width());
- const BorderEdge& adjacent_edge1 =
- edges_[static_cast<unsigned>(adjacent_side1)];
- const BorderEdge& adjacent_edge2 =
- edges_[static_cast<unsigned>(adjacent_side2)];
+ const BorderEdge& adjacent_edge1 = Edge(adjacent_side1);
+ const BorderEdge& adjacent_edge2 = Edge(adjacent_side2);
if (path) {
- MiterType miter1 = ColorsMatchAtCorner(side, adjacent_side1, edges_)
- ? kHardMiter
- : kSoftMiter;
- MiterType miter2 = ColorsMatchAtCorner(side, adjacent_side2, edges_)
- ? kHardMiter
- : kSoftMiter;
-
- GraphicsContextStateSaver state_saver(graphics_context);
+ MiterType miter1 =
+ ColorsMatchAtCorner(side, adjacent_side1) ? kHardMiter : kSoftMiter;
+ MiterType miter2 =
+ ColorsMatchAtCorner(side, adjacent_side2) ? kHardMiter : kSoftMiter;
+
+ GraphicsContextStateSaver state_saver(context_);
if (inner_.IsRenderable())
- ClipBorderSidePolygon(graphics_context, side, miter1, miter2);
+ ClipBorderSidePolygon(side, miter1, miter2);
else
- ClipBorderSideForComplexInnerPath(graphics_context, side);
+ ClipBorderSideForComplexInnerPath(side);
float stroke_thickness =
std::max(std::max(edge_to_render.Width(), adjacent_edge1.Width()),
adjacent_edge2.Width());
- DrawBoxSideFromPath(graphics_context,
- PhysicalRect::EnclosingRect(outer_.Rect()), *path,
- edge_to_render.Width(), stroke_thickness, side, color,
- edge_to_render.BorderStyle());
+ DrawBoxSideFromPath(*path, edge_to_render.Width(), stroke_thickness, side,
+ color, edge_to_render.BorderStyle());
} else {
- MiterType miter1 =
- ComputeMiter(side, adjacent_side1, completed_edges, antialias);
- MiterType miter2 =
- ComputeMiter(side, adjacent_side2, completed_edges, antialias);
- bool should_clip = MitersRequireClipping(
- miter1, miter2, edge_to_render.BorderStyle(), antialias);
+ MiterType miter1 = ComputeMiter(side, adjacent_side1, completed_edges);
+ MiterType miter2 = ComputeMiter(side, adjacent_side2, completed_edges);
+ bool should_clip =
+ MitersRequireClipping(miter1, miter2, edge_to_render.BorderStyle());
- GraphicsContextStateSaver clip_state_saver(graphics_context, should_clip);
+ GraphicsContextStateSaver clip_state_saver(context_, should_clip);
if (should_clip) {
- ClipBorderSidePolygon(graphics_context, side, miter1, miter2);
-
+ ClipBorderSidePolygon(side, miter1, miter2);
// Miters are applied via clipping, no need to draw them.
miter1 = miter2 = kNoMiter;
}
- ObjectPainter::DrawLineForBoxSide(
- graphics_context, side_rect.X(), side_rect.Y(), side_rect.MaxX(),
- side_rect.MaxY(), side, color, edge_to_render.BorderStyle(),
- miter1 != kNoMiter ? floorf(adjacent_edge1.Width()) : 0,
- miter2 != kNoMiter ? floorf(adjacent_edge2.Width()) : 0, antialias);
+ DrawLineForBoxSide(context_, side_rect.X(), side_rect.Y(), side_rect.MaxX(),
+ side_rect.MaxY(), side, color,
+ edge_to_render.BorderStyle(),
+ miter1 != kNoMiter ? floorf(adjacent_edge1.Width()) : 0,
+ miter2 != kNoMiter ? floorf(adjacent_edge2.Width()) : 0,
+ /*antialias*/ true);
}
}
-void BoxBorderPainter::DrawBoxSideFromPath(GraphicsContext& graphics_context,
- const PhysicalRect& border_rect,
- const Path& border_path,
+void BoxBorderPainter::DrawBoxSideFromPath(const Path& border_path,
float border_thickness,
float stroke_thickness,
BoxSide side,
@@ -1029,22 +1244,20 @@ void BoxBorderPainter::DrawBoxSideFromPath(GraphicsContext& graphics_context,
return;
case EBorderStyle::kDotted:
case EBorderStyle::kDashed: {
- DrawDashedDottedBoxSideFromPath(graphics_context, border_rect,
- border_thickness, stroke_thickness, color,
+ DrawDashedDottedBoxSideFromPath(border_thickness, stroke_thickness, color,
border_style);
return;
}
case EBorderStyle::kDouble: {
- DrawDoubleBoxSideFromPath(graphics_context, border_rect, border_path,
- border_thickness, stroke_thickness, side,
- color);
+ DrawDoubleBoxSideFromPath(border_path, border_thickness, stroke_thickness,
+ side, color);
return;
}
case EBorderStyle::kRidge:
case EBorderStyle::kGroove: {
- DrawRidgeGrooveBoxSideFromPath(graphics_context, border_rect, border_path,
- border_thickness, stroke_thickness, side,
- color, border_style);
+ DrawRidgeGrooveBoxSideFromPath(border_path, border_thickness,
+ stroke_thickness, side, color,
+ border_style);
return;
}
case EBorderStyle::kInset:
@@ -1059,37 +1272,29 @@ void BoxBorderPainter::DrawBoxSideFromPath(GraphicsContext& graphics_context,
break;
}
- graphics_context.SetStrokeStyle(kNoStroke);
- graphics_context.SetFillColor(color);
- graphics_context.DrawRect(PixelSnappedIntRect(border_rect));
+ context_.SetStrokeStyle(kNoStroke);
+ context_.SetFillColor(color);
+ context_.DrawRect(RoundedIntRect(outer_.Rect()));
}
void BoxBorderPainter::DrawDashedDottedBoxSideFromPath(
- GraphicsContext& graphics_context,
- const PhysicalRect& border_rect,
float border_thickness,
float stroke_thickness,
Color color,
EBorderStyle border_style) const {
// Convert the path to be down the middle of the dots or dashes.
- const LayoutRectOutsets center_offsets(
- -edges_[static_cast<unsigned>(BoxSide::kTop)].UsedWidth() * 0.5,
- -edges_[static_cast<unsigned>(BoxSide::kRight)].UsedWidth() * 0.5,
- -edges_[static_cast<unsigned>(BoxSide::kBottom)].UsedWidth() * 0.5,
- -edges_[static_cast<unsigned>(BoxSide::kLeft)].UsedWidth() * 0.5);
Path centerline_path;
centerline_path.AddRoundedRect(
- RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- style_, border_rect, center_offsets, sides_to_include_));
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style_, border_rect_, CenterOutsets(), sides_to_include_));
- graphics_context.SetStrokeColor(color);
+ context_.SetStrokeColor(color);
if (!StrokeData::StrokeIsDashed(border_thickness,
border_style == EBorderStyle::kDashed
? kDashedStroke
: kDottedStroke)) {
- DrawWideDottedBoxSideFromPath(graphics_context, centerline_path,
- border_thickness);
+ DrawWideDottedBoxSideFromPath(centerline_path, border_thickness);
return;
}
@@ -1098,33 +1303,29 @@ void BoxBorderPainter::DrawDashedDottedBoxSideFromPath(
// the extra multiplier so that the clipping mask can antialias
// the edges to prevent jaggies.
const float thickness_multiplier = 2 * 1.1f;
- graphics_context.SetStrokeThickness(stroke_thickness * thickness_multiplier);
- graphics_context.SetStrokeStyle(
+ context_.SetStrokeThickness(stroke_thickness * thickness_multiplier);
+ context_.SetStrokeStyle(
border_style == EBorderStyle::kDashed ? kDashedStroke : kDottedStroke);
// TODO(schenney): stroking the border path causes issues with tight corners:
// https://bugs.chromium.org/p/chromium/issues/detail?id=344234
- graphics_context.StrokePath(centerline_path, centerline_path.length(),
- border_thickness);
+ context_.StrokePath(centerline_path, centerline_path.length(),
+ border_thickness);
}
void BoxBorderPainter::DrawWideDottedBoxSideFromPath(
- GraphicsContext& graphics_context,
const Path& border_path,
float border_thickness) const {
- graphics_context.SetStrokeThickness(border_thickness);
- graphics_context.SetStrokeStyle(kDottedStroke);
- graphics_context.SetLineCap(kRoundCap);
+ context_.SetStrokeThickness(border_thickness);
+ context_.SetStrokeStyle(kDottedStroke);
+ context_.SetLineCap(kRoundCap);
// TODO(schenney): stroking the border path causes issues with tight corners:
// https://bugs.webkit.org/show_bug.cgi?id=58711
- graphics_context.StrokePath(border_path, border_path.length(),
- border_thickness);
+ context_.StrokePath(border_path, border_path.length(), border_thickness);
}
void BoxBorderPainter::DrawDoubleBoxSideFromPath(
- GraphicsContext& graphics_context,
- const PhysicalRect& border_rect,
const Path& border_path,
float border_thickness,
float stroke_thickness,
@@ -1132,47 +1333,43 @@ void BoxBorderPainter::DrawDoubleBoxSideFromPath(
Color color) const {
// Draw inner border line
{
- GraphicsContextStateSaver state_saver(graphics_context);
- const LayoutRectOutsets inner_insets =
- DoubleStripeInsets(edges_, BorderEdge::kDoubleBorderStripeInner);
+ GraphicsContextStateSaver state_saver(context_);
+ const LayoutRectOutsets inner_outsets =
+ DoubleStripeOutsets(BorderEdge::kDoubleBorderStripeInner);
FloatRoundedRect inner_clip =
- RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- style_, border_rect, inner_insets, sides_to_include_);
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style_, border_rect_, inner_outsets, sides_to_include_);
- graphics_context.ClipRoundedRect(inner_clip);
- DrawBoxSideFromPath(graphics_context, border_rect, border_path,
- border_thickness, stroke_thickness, side, color,
- EBorderStyle::kSolid);
+ context_.ClipRoundedRect(inner_clip);
+ DrawBoxSideFromPath(border_path, border_thickness, stroke_thickness, side,
+ color, EBorderStyle::kSolid);
}
// Draw outer border line
{
- GraphicsContextStateSaver state_saver(graphics_context);
- PhysicalRect outer_rect = border_rect;
- LayoutRectOutsets outer_insets =
- DoubleStripeInsets(edges_, BorderEdge::kDoubleBorderStripeOuter);
+ GraphicsContextStateSaver state_saver(context_);
+ PhysicalRect used_border_rect = border_rect_;
+ LayoutRectOutsets outer_outsets =
+ DoubleStripeOutsets(BorderEdge::kDoubleBorderStripeOuter);
if (BleedAvoidanceIsClipping(bleed_avoidance_)) {
- outer_rect.Inflate(LayoutUnit(1));
- outer_insets.SetTop(outer_insets.Top() - 1);
- outer_insets.SetRight(outer_insets.Right() - 1);
- outer_insets.SetBottom(outer_insets.Bottom() - 1);
- outer_insets.SetLeft(outer_insets.Left() - 1);
+ used_border_rect.Inflate(LayoutUnit(1));
+ outer_outsets.SetTop(outer_outsets.Top() - 1);
+ outer_outsets.SetRight(outer_outsets.Right() - 1);
+ outer_outsets.SetBottom(outer_outsets.Bottom() - 1);
+ outer_outsets.SetLeft(outer_outsets.Left() - 1);
}
FloatRoundedRect outer_clip =
- RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- style_, outer_rect, outer_insets, sides_to_include_);
- graphics_context.ClipOutRoundedRect(outer_clip);
- DrawBoxSideFromPath(graphics_context, border_rect, border_path,
- border_thickness, stroke_thickness, side, color,
- EBorderStyle::kSolid);
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style_, used_border_rect, outer_outsets, sides_to_include_);
+ context_.ClipOutRoundedRect(outer_clip);
+ DrawBoxSideFromPath(border_path, border_thickness, stroke_thickness, side,
+ color, EBorderStyle::kSolid);
}
}
void BoxBorderPainter::DrawRidgeGrooveBoxSideFromPath(
- GraphicsContext& graphics_context,
- const PhysicalRect& border_rect,
const Path& border_path,
float border_thickness,
float stroke_thickness,
@@ -1190,43 +1387,56 @@ void BoxBorderPainter::DrawRidgeGrooveBoxSideFromPath(
}
// Paint full border
- DrawBoxSideFromPath(graphics_context, border_rect, border_path,
- border_thickness, stroke_thickness, side, color, s1);
+ DrawBoxSideFromPath(border_path, border_thickness, stroke_thickness, side,
+ color, s1);
// Paint inner only
- GraphicsContextStateSaver state_saver(graphics_context);
- int top_width = edges_[static_cast<unsigned>(BoxSide::kTop)].UsedWidth() / 2;
- int bottom_width =
- edges_[static_cast<unsigned>(BoxSide::kBottom)].UsedWidth() / 2;
- int left_width =
- edges_[static_cast<unsigned>(BoxSide::kLeft)].UsedWidth() / 2;
- int right_width =
- edges_[static_cast<unsigned>(BoxSide::kRight)].UsedWidth() / 2;
-
+ GraphicsContextStateSaver state_saver(context_);
FloatRoundedRect clip_rect =
- RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- style_, border_rect,
- LayoutRectOutsets(-top_width, -right_width, -bottom_width,
- -left_width),
- sides_to_include_);
-
- graphics_context.ClipRoundedRect(clip_rect);
- DrawBoxSideFromPath(graphics_context, border_rect, border_path,
- border_thickness, stroke_thickness, side, color, s2);
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style_, border_rect_, CenterOutsets(), sides_to_include_);
+
+ context_.ClipRoundedRect(clip_rect);
+ DrawBoxSideFromPath(border_path, border_thickness, stroke_thickness, side,
+ color, s2);
}
-void BoxBorderPainter::ClipBorderSideForComplexInnerPath(
- GraphicsContext& graphics_context,
+FloatRect BoxBorderPainter::CalculateSideRectIncludingInner(
BoxSide side) const {
- graphics_context.Clip(CalculateSideRectIncludingInner(outer_, edges_, side));
+ FloatRect side_rect = outer_.Rect();
+ float width;
+
+ switch (side) {
+ case BoxSide::kTop:
+ width = side_rect.Height() - Edge(BoxSide::kBottom).Width();
+ side_rect.SetHeight(width);
+ break;
+ case BoxSide::kBottom:
+ width = side_rect.Height() - Edge(BoxSide::kTop).Width();
+ side_rect.ShiftYEdgeTo(side_rect.MaxY() - width);
+ break;
+ case BoxSide::kLeft:
+ width = side_rect.Width() - Edge(BoxSide::kRight).Width();
+ side_rect.SetWidth(width);
+ break;
+ case BoxSide::kRight:
+ width = side_rect.Width() - Edge(BoxSide::kLeft).Width();
+ side_rect.ShiftXEdgeTo(side_rect.MaxX() - width);
+ break;
+ }
+
+ return side_rect;
+}
+
+void BoxBorderPainter::ClipBorderSideForComplexInnerPath(BoxSide side) const {
+ context_.Clip(CalculateSideRectIncludingInner(side));
FloatRoundedRect adjusted_inner_rect =
CalculateAdjustedInnerBorder(inner_, side);
if (!adjusted_inner_rect.IsEmpty())
- graphics_context.ClipOutRoundedRect(adjusted_inner_rect);
+ context_.ClipOutRoundedRect(adjusted_inner_rect);
}
-void BoxBorderPainter::ClipBorderSidePolygon(GraphicsContext& graphics_context,
- BoxSide side,
+void BoxBorderPainter::ClipBorderSidePolygon(BoxSide side,
MiterType first_miter,
MiterType second_miter) const {
DCHECK(first_miter != kNoMiter || second_miter != kNoMiter);
@@ -1446,7 +1656,7 @@ void BoxBorderPainter::ClipBorderSidePolygon(GraphicsContext& graphics_context,
}
if (first_miter == second_miter) {
- ClipQuad(graphics_context, edge_quad, first_miter == kSoftMiter);
+ ClipQuad(context_, edge_quad, first_miter == kSoftMiter);
return;
}
@@ -1466,7 +1676,7 @@ void BoxBorderPainter::ClipBorderSidePolygon(GraphicsContext& graphics_context,
clipping_quad[2] = bound_quad2;
clipping_quad[3] = edge_quad[3];
- ClipQuad(graphics_context, clipping_quad, first_miter == kSoftMiter);
+ ClipQuad(context_, clipping_quad, first_miter == kSoftMiter);
}
if (second_miter != kNoMiter) {
@@ -1479,7 +1689,105 @@ void BoxBorderPainter::ClipBorderSidePolygon(GraphicsContext& graphics_context,
clipping_quad[2] -= extension_offset;
clipping_quad[3] = edge_quad[3] - extension_offset;
- ClipQuad(graphics_context, clipping_quad, second_miter == kSoftMiter);
+ ClipQuad(context_, clipping_quad, second_miter == kSoftMiter);
+ }
+}
+
+LayoutRectOutsets BoxBorderPainter::DoubleStripeOutsets(
+ BorderEdge::DoubleBorderStripe stripe) const {
+ return LayoutRectOutsets(
+ outer_outset_y_ - Edge(BoxSide::kTop).GetDoubleBorderStripeWidth(stripe),
+ outer_outset_x_ -
+ Edge(BoxSide::kRight).GetDoubleBorderStripeWidth(stripe),
+ outer_outset_y_ -
+ Edge(BoxSide::kBottom).GetDoubleBorderStripeWidth(stripe),
+ outer_outset_x_ -
+ Edge(BoxSide::kLeft).GetDoubleBorderStripeWidth(stripe));
+}
+
+LayoutRectOutsets BoxBorderPainter::CenterOutsets() const {
+ return LayoutRectOutsets(
+ outer_outset_y_ - Edge(BoxSide::kTop).UsedWidth() * 0.5,
+ outer_outset_x_ - Edge(BoxSide::kRight).UsedWidth() * 0.5,
+ outer_outset_y_ - Edge(BoxSide::kBottom).UsedWidth() * 0.5,
+ outer_outset_x_ - Edge(BoxSide::kLeft).UsedWidth() * 0.5);
+}
+
+bool BoxBorderPainter::ColorsMatchAtCorner(BoxSide side,
+ BoxSide adjacent_side) const {
+ if (!Edge(adjacent_side).ShouldRender())
+ return false;
+
+ if (!Edge(side).SharesColorWith(Edge(adjacent_side)))
+ return false;
+
+ return !BorderStyleHasUnmatchedColorsAtCorner(Edge(side).BorderStyle(), side,
+ adjacent_side);
+}
+
+void BoxBorderPainter::DrawLineForBoxSide(GraphicsContext& context,
+ float x1,
+ float y1,
+ float x2,
+ float y2,
+ BoxSide side,
+ Color color,
+ EBorderStyle style,
+ int adjacent_width1,
+ int adjacent_width2,
+ bool antialias) {
+ float thickness;
+ float length;
+ if (side == BoxSide::kTop || side == BoxSide::kBottom) {
+ thickness = y2 - y1;
+ length = x2 - x1;
+ } else {
+ thickness = x2 - x1;
+ length = y2 - y1;
+ }
+
+ // We would like this check to be an ASSERT as we don't want to draw empty
+ // borders. However nothing guarantees that the following recursive calls to
+ // DrawLineForBoxSide() will have positive thickness and length.
+ if (length <= 0 || thickness <= 0)
+ return;
+
+ if (style == EBorderStyle::kDouble && thickness < 3)
+ style = EBorderStyle::kSolid;
+
+ switch (style) {
+ case EBorderStyle::kNone:
+ case EBorderStyle::kHidden:
+ return;
+ case EBorderStyle::kDotted:
+ case EBorderStyle::kDashed:
+ DrawDashedOrDottedBoxSide(context, x1, y1, x2, y2, side, color, thickness,
+ style, antialias);
+ break;
+ case EBorderStyle::kDouble:
+ DrawDoubleBoxSide(context, x1, y1, x2, y2, length, side, color, thickness,
+ adjacent_width1, adjacent_width2, antialias);
+ break;
+ case EBorderStyle::kRidge:
+ case EBorderStyle::kGroove:
+ DrawRidgeOrGrooveBoxSide(context, x1, y1, x2, y2, side, color, style,
+ adjacent_width1, adjacent_width2, antialias);
+ break;
+ case EBorderStyle::kInset:
+ // FIXME: Maybe we should lighten the colors on one side like Firefox.
+ // https://bugs.webkit.org/show_bug.cgi?id=58608
+ if (side == BoxSide::kTop || side == BoxSide::kLeft)
+ color = color.Dark();
+ FALLTHROUGH;
+ case EBorderStyle::kOutset:
+ if (style == EBorderStyle::kOutset &&
+ (side == BoxSide::kBottom || side == BoxSide::kRight))
+ color = color.Dark();
+ FALLTHROUGH;
+ case EBorderStyle::kSolid:
+ DrawSolidBoxSide(context, x1, y1, x2, y2, side, color, adjacent_width1,
+ adjacent_width2, antialias);
+ break;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/box_border_painter.h b/chromium/third_party/blink/renderer/core/paint/box_border_painter.h
index 42c60592d46..27fa15d11ef 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_border_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_border_painter.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/layout/background_bleed_avoidance.h"
#include "third_party/blink/renderer/core/layout/geometry/box_sides.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
@@ -15,7 +16,6 @@ namespace blink {
class ComputedStyle;
class GraphicsContext;
class Path;
-struct PaintInfo;
struct PhysicalRect;
typedef unsigned BorderEdgeFlags;
@@ -24,19 +24,68 @@ class BoxBorderPainter {
STACK_ALLOCATED();
public:
- BoxBorderPainter(const PhysicalRect& border_rect,
+ static void PaintBorder(GraphicsContext& context,
+ const PhysicalRect& border_rect,
+ const ComputedStyle& style,
+ BackgroundBleedAvoidance bleed_avoidance,
+ PhysicalBoxSides sides_to_include) {
+ BoxBorderPainter(context, border_rect, style, bleed_avoidance,
+ sides_to_include)
+ .Paint();
+ }
+
+ static void PaintSingleRectOutline(GraphicsContext& context,
+ const ComputedStyle& style,
+ const PhysicalRect& border_rect,
+ int inner_outset_x,
+ int inner_outset_y) {
+ BoxBorderPainter(context, style, border_rect, inner_outset_x,
+ inner_outset_y)
+ .Paint();
+ }
+
+ static void DrawBoxSide(GraphicsContext& context,
+ const IntRect& snapped_edge_rect,
+ BoxSide side,
+ Color color,
+ EBorderStyle style) {
+ DrawLineForBoxSide(context, snapped_edge_rect.X(), snapped_edge_rect.Y(),
+ snapped_edge_rect.MaxX(), snapped_edge_rect.MaxY(), side,
+ color, style, 0, 0, true);
+ }
+
+ // TODO(crbug.com/1201762): The float parameters are truncated to int in the
+ // function, which implicitly snaps to whole pixels perhaps unexpectedly. To
+ // avoid the problem, we should use the above function which requires the
+ // caller to snap to whole pixels explicitly.
+ static void DrawLineForBoxSide(GraphicsContext&,
+ float x1,
+ float y1,
+ float x2,
+ float y2,
+ BoxSide,
+ Color,
+ EBorderStyle,
+ int adjacent_edge_width1,
+ int adjacent_edge_width2,
+ bool antialias);
+
+ private:
+ // For PaintBorder().
+ BoxBorderPainter(GraphicsContext&,
+ const PhysicalRect& border_rect,
const ComputedStyle&,
BackgroundBleedAvoidance,
PhysicalBoxSides sides_to_include);
+ // For PaintSingleRectOutline().
+ BoxBorderPainter(GraphicsContext&,
+ const ComputedStyle&,
+ const PhysicalRect& border_rect,
+ int inner_outset_x,
+ int inner_outset_y);
- BoxBorderPainter(const ComputedStyle&,
- const PhysicalRect& outer,
- const PhysicalRect& inner,
- const BorderEdge& uniform_edge_info);
-
- void PaintBorder(const PaintInfo&, const PhysicalRect& border_rect) const;
+ void Paint() const;
- private:
struct ComplexBorderInfo;
enum MiterType {
kNoMiter,
@@ -46,82 +95,76 @@ class BoxBorderPainter {
void ComputeBorderProperties();
- BorderEdgeFlags PaintOpacityGroup(GraphicsContext&,
- const ComplexBorderInfo&,
+ BorderEdgeFlags PaintOpacityGroup(const ComplexBorderInfo&,
unsigned index,
float accumulated_opacity) const;
- void PaintSide(GraphicsContext&,
- const ComplexBorderInfo&,
+ void PaintSide(const ComplexBorderInfo&,
BoxSide,
unsigned alpha,
BorderEdgeFlags) const;
- void PaintOneBorderSide(GraphicsContext&,
- const FloatRect& side_rect,
+ void PaintOneBorderSide(const FloatRect& side_rect,
BoxSide,
BoxSide adjacent_side1,
BoxSide adjacent_side2,
const Path*,
- bool antialias,
Color,
BorderEdgeFlags) const;
- bool PaintBorderFastPath(GraphicsContext&,
- const PhysicalRect& border_rect) const;
- void DrawDoubleBorder(GraphicsContext&,
- const PhysicalRect& border_rect) const;
-
- void DrawBoxSideFromPath(GraphicsContext&,
- const PhysicalRect&,
- const Path&,
+ bool PaintBorderFastPath() const;
+ void DrawDoubleBorder() const;
+
+ void DrawBoxSideFromPath(const Path&,
float thickness,
float draw_thickness,
BoxSide,
Color,
EBorderStyle) const;
- void DrawDashedDottedBoxSideFromPath(GraphicsContext&,
- const PhysicalRect&,
- float thickness,
+ void DrawDashedDottedBoxSideFromPath(float thickness,
float draw_thickness,
Color,
EBorderStyle) const;
- void DrawWideDottedBoxSideFromPath(GraphicsContext&,
- const Path&,
- float thickness) const;
- void DrawDoubleBoxSideFromPath(GraphicsContext&,
- const PhysicalRect&,
- const Path&,
+ void DrawWideDottedBoxSideFromPath(const Path&, float thickness) const;
+ void DrawDoubleBoxSideFromPath(const Path&,
float thickness,
float draw_thickness,
BoxSide,
Color) const;
- void DrawRidgeGrooveBoxSideFromPath(GraphicsContext&,
- const PhysicalRect&,
- const Path&,
+ void DrawRidgeGrooveBoxSideFromPath(const Path&,
float thickness,
float draw_thickness,
BoxSide,
Color,
EBorderStyle) const;
- void ClipBorderSidePolygon(GraphicsContext&,
- BoxSide,
- MiterType miter1,
- MiterType miter2) const;
- void ClipBorderSideForComplexInnerPath(GraphicsContext&, BoxSide) const;
-
- MiterType ComputeMiter(BoxSide,
- BoxSide adjacent_side,
- BorderEdgeFlags,
- bool antialias) const;
+ void ClipBorderSidePolygon(BoxSide, MiterType miter1, MiterType miter2) const;
+ FloatRect CalculateSideRectIncludingInner(BoxSide) const;
+ void ClipBorderSideForComplexInnerPath(BoxSide) const;
+
+ MiterType ComputeMiter(BoxSide, BoxSide adjacent_side, BorderEdgeFlags) const;
static bool MitersRequireClipping(MiterType miter1,
MiterType miter2,
- EBorderStyle,
- bool antialias);
+ EBorderStyle);
+
+ LayoutRectOutsets DoubleStripeOutsets(
+ BorderEdge::DoubleBorderStripe stripe) const;
+ LayoutRectOutsets CenterOutsets() const;
+
+ bool ColorsMatchAtCorner(BoxSide side, BoxSide adjacent_side) const;
const BorderEdge& FirstEdge() const {
DCHECK(visible_edge_set_);
return edges_[first_visible_edge_];
}
+ BorderEdge& Edge(BoxSide side) { return edges_[static_cast<unsigned>(side)]; }
+ const BorderEdge& Edge(BoxSide side) const {
+ return edges_[static_cast<unsigned>(side)];
+ }
+
+ GraphicsContext& context_;
+
// const inputs
+ const PhysicalRect border_rect_;
+ const LayoutUnit outer_outset_x_;
+ const LayoutUnit outer_outset_y_;
const ComputedStyle& style_;
const BackgroundBleedAvoidance bleed_avoidance_;
const PhysicalBoxSides sides_to_include_;
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 958b9665987..18c9465a405 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_BOX_DECORATION_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_BOX_DECORATION_DATA_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/background_bleed_avoidance.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
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 de7526d1945..12b4e7b7ded 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
@@ -58,12 +58,13 @@ BoxModelObjectPainter::BoxModelObjectPainter(const LayoutBoxModelObject& box,
flow_box_(flow_box) {}
void BoxModelObjectPainter::PaintTextClipMask(
- GraphicsContext& context,
+ const PaintInfo& paint_info,
const IntRect& mask_rect,
const PhysicalOffset& paint_offset,
bool object_has_multiple_boxes) {
- PaintInfo paint_info(context, CullRect(mask_rect), PaintPhase::kTextClip,
- kGlobalPaintNormalPhase, 0);
+ PaintInfo mask_paint_info(paint_info.context, CullRect(mask_rect),
+ PaintPhase::kTextClip, kGlobalPaintNormalPhase, 0);
+ mask_paint_info.SetFragmentID(paint_info.FragmentID());
if (flow_box_) {
LayoutSize local_offset = ToLayoutSize(flow_box_->Location());
if (object_has_multiple_boxes &&
@@ -75,10 +76,10 @@ void BoxModelObjectPainter::PaintTextClipMask(
PhysicalOffset physical_local_offset(local_offset.Width(),
local_offset.Height());
const RootInlineBox& root = flow_box_->Root();
- flow_box_->Paint(paint_info, paint_offset - physical_local_offset,
+ flow_box_->Paint(mask_paint_info, paint_offset - physical_local_offset,
root.LineTop(), root.LineBottom());
} else if (auto* layout_block = DynamicTo<LayoutBlock>(box_model_)) {
- layout_block->PaintObject(paint_info, paint_offset);
+ layout_block->PaintObject(mask_paint_info, paint_offset);
} else {
// We should go through the above path for LayoutInlines.
DCHECK(!box_model_.IsLayoutInline());
@@ -98,7 +99,6 @@ PhysicalRect BoxModelObjectPainter::AdjustRectForScrolledContent(
if (BoxDecorationData::IsPaintingScrollingBackground(paint_info, this_box))
return rect;
- PhysicalRect scrolled_paint_rect = rect;
GraphicsContext& context = paint_info.context;
// Clip to the overflow area.
// TODO(chrishtr): this should be pixel-snapped.
@@ -106,8 +106,9 @@ PhysicalRect BoxModelObjectPainter::AdjustRectForScrolledContent(
// Adjust the paint rect to reflect a scrolled content box with borders at
// the ends.
- PhysicalOffset offset(this_box.PixelSnappedScrolledContentOffset());
- scrolled_paint_rect.Move(-offset);
+ PhysicalRect scrolled_paint_rect = rect;
+ scrolled_paint_rect.offset -=
+ PhysicalOffset(this_box.PixelSnappedScrolledContentOffset());
LayoutRectOutsets border = AdjustedBorderOutsets(info);
scrolled_paint_rect.SetWidth(border.Left() + this_box.ScrollWidth() +
border.Right());
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 03f15100911..5134ba6ecad 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
@@ -37,7 +37,7 @@ class BoxModelObjectPainter : public BoxPainterBase {
bool is_painting_scrolling_background) const override;
bool IsPaintingScrollingBackground(const PaintInfo&) const override;
- void PaintTextClipMask(GraphicsContext&,
+ void PaintTextClipMask(const PaintInfo&,
const IntRect& mask_rect,
const PhysicalOffset& paint_offset,
bool object_has_multiple_boxes) override;
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 a701c72ddc0..2f5093bf4a9 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
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/css/background_color_paint_image_generator.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -192,7 +191,7 @@ void BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
const ComputedStyle& style) {
if (!style.BoxShadow())
return;
- auto bounds = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
+ auto bounds = RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
style, inner_rect, LayoutRectOutsets());
PaintInsetBoxShadow(info, bounds, style);
}
@@ -397,39 +396,6 @@ BoxPainterBase::FillLayerInfo::FillLayerInfo(
namespace {
-// 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
-// phase that is no more than one size + space in magnitude.
-PhysicalOffset ComputePhaseForBackground(
- const BackgroundImageGeometry& geometry) {
- const PhysicalSize step_per_tile = geometry.TileSize() + geometry.SpaceSize();
- return {IntMod(-geometry.Phase().left, step_per_tile.width),
- IntMod(-geometry.Phase().top, step_per_tile.height)};
-}
-
-// 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.
-FloatRect ComputeSubsetForBackground(const PhysicalRect& phase_and_size,
- const PhysicalRect& subset,
- const FloatSize& intrinsic_size) {
- // TODO(schenney): Re-enable this after determining why it fails for
- // CAP, and maybe other cases.
- // DCHECK(phase_and_size.Contains(subset));
- const PhysicalOffset offset_in_tile = subset.offset - phase_and_size.offset;
- const FloatSize scale(phase_and_size.Width() / intrinsic_size.Width(),
- phase_and_size.Height() / intrinsic_size.Height());
- return FloatRect(
- offset_in_tile.left / scale.Width(), offset_in_tile.top / scale.Height(),
- subset.Width() / scale.Width(), subset.Height() / scale.Height());
-}
-
FloatRect SnapSourceRectIfNearIntegral(const FloatRect src_rect) {
// Round to avoid filtering pulling in neighboring pixels, for the
// common case of sprite maps, but only if we're close to an integral size.
@@ -444,11 +410,85 @@ FloatRect SnapSourceRectIfNearIntegral(const FloatRect src_rect) {
LayoutUnit::Epsilon() &&
std::abs(std::round(src_rect.MaxY()) - src_rect.MaxY()) <=
LayoutUnit::Epsilon()) {
- return FloatRect(RoundedIntRect(src_rect));
+ IntRect rounded_src_rect = RoundedIntRect(src_rect);
+ // If we have snapped the image size to 0, revert the rounding.
+ if (rounded_src_rect.IsEmpty())
+ return src_rect;
+ return FloatRect(rounded_src_rect);
}
return src_rect;
}
+absl::optional<FloatRect> OptimizeToSingleTileDraw(
+ const BackgroundImageGeometry& geometry,
+ const PhysicalRect& dest_rect,
+ Image* image,
+ RespectImageOrientationEnum respect_orientation) {
+ const PhysicalOffset dest_phase = geometry.ComputeDestPhase();
+
+ // Phase calculation uses the actual painted location, given by the
+ // border-snapped destination rect.
+ const PhysicalRect one_tile_rect(dest_phase, geometry.TileSize());
+
+ // We cannot optimize if the tile is misaligned.
+ if (!one_tile_rect.Contains(dest_rect))
+ return absl::nullopt;
+
+ const PhysicalOffset offset_in_tile =
+ geometry.SnappedDestRect().offset - dest_phase;
+ if (!image->HasIntrinsicSize()) {
+ // This is a generated image sized according to the tile size so we can use
+ // the snapped dest rect directly.
+ const PhysicalRect offset_tile(offset_in_tile,
+ geometry.SnappedDestRect().size);
+ return FloatRect(offset_tile);
+ }
+
+ // Compute the image subset, in intrinsic image coordinates, that gets mapped
+ // onto the |dest_rect|, when the whole image would be drawn with phase and
+ // size given by |one_tile_rect|. Assumes |one_tile_rect| contains
+ // |dest_rect|. The location of the requested subset should be the painting
+ // snapped location.
+ //
+ // 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.
+ //
+ // image-resolution information is baked into the given parameters, but we
+ // need oriented size.
+ const FloatSize intrinsic_tile_size = image->SizeAsFloat(respect_orientation);
+
+ // Subset computation needs the same location as was used above, but needs the
+ // unsnapped destination size to correctly calculate sprite subsets in the
+ // presence of zoom.
+ // TODO(schenney): Re-enable this after determining why it fails for
+ // CAP, and maybe other cases.
+ // DCHECK(one_tile_rect.Contains(dest_rect_for_subset));
+ const FloatSize scale(
+ geometry.TileSize().width / intrinsic_tile_size.Width(),
+ geometry.TileSize().height / intrinsic_tile_size.Height());
+ FloatRect visible_src_rect(
+ offset_in_tile.left / scale.Width(), offset_in_tile.top / scale.Height(),
+ geometry.UnsnappedDestRect().Width() / scale.Width(),
+ geometry.UnsnappedDestRect().Height() / scale.Height());
+
+ // Content providers almost always choose source pixels at integer locations,
+ // so snap to integers. This is particularly 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.
+ visible_src_rect = SnapSourceRectIfNearIntegral(visible_src_rect);
+
+ // When respecting image orientation, the drawing code expects the source
+ // rect to be in the unrotated image space, but we have computed it here in
+ // the rotated space in order to position and size the background. Undo the
+ // src rect rotation if necessary.
+ if (respect_orientation && !image->HasDefaultOrientation()) {
+ visible_src_rect = image->CorrectSrcRectForImageOrientation(
+ intrinsic_tile_size, visible_src_rect);
+ }
+ return visible_src_rect;
+}
+
// 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.
@@ -465,34 +505,6 @@ void DrawTiledBackground(GraphicsContext& context,
RespectImageOrientationEnum respect_orientation) {
DCHECK(!geometry.TileSize().IsEmpty());
- // 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(image->Size());
- // image-resolution information is baked into the given parameters, but we
- // need oriented size. That requires explicitly applying orientation here.
- if (respect_orientation &&
- image->CurrentFrameOrientation().UsesWidthAsHeight()) {
- intrinsic_tile_size = intrinsic_tile_size.TransposedSize();
- }
-
- FloatSize scale(1, 1);
- if (!image->HasIntrinsicSize() ||
- // TODO(crbug.com/1042783): This is not checking for real empty image
- // (for which we have checked and skipped the whole FillLayer), but for
- // that a subpixel image size is rounded to empty, to avoid infinite tile
- // scale that would be calculated in the |else| part.
- // We should probably support subpixel size here.
- intrinsic_tile_size.IsEmpty()) {
- intrinsic_tile_size = FloatSize(geometry.TileSize());
- } else {
- scale =
- FloatSize(geometry.TileSize().width / intrinsic_tile_size.Width(),
- geometry.TileSize().height / intrinsic_tile_size.Height());
- }
-
- const PhysicalOffset dest_phase =
- geometry.SnappedDestRect().offset + ComputePhaseForBackground(geometry);
-
// Check and see if a single draw of the image can cover the entire area we
// are supposed to tile. The dest_rect_for_subset must use the same
// location that was used in ComputePhaseForBackground and the unsnapped
@@ -500,30 +512,30 @@ void DrawTiledBackground(GraphicsContext& context,
// location in the presence of border snapping and zoom.
const PhysicalRect dest_rect_for_subset(geometry.SnappedDestRect().offset,
geometry.UnsnappedDestRect().size);
- const PhysicalRect one_tile_rect(dest_phase, geometry.TileSize());
- if (one_tile_rect.Contains(dest_rect_for_subset)) {
- FloatRect visible_src_rect = ComputeSubsetForBackground(
- one_tile_rect, dest_rect_for_subset, intrinsic_tile_size);
- visible_src_rect = SnapSourceRectIfNearIntegral(visible_src_rect);
-
- // When respecting image orientation, the drawing code expects the source
- // rect to be in the unrotated image space, but we have computed it here in
- // the rotated space in order to position and size the background. Undo the
- // src rect rotation if necessary.
- if (respect_orientation && !image->HasDefaultOrientation()) {
- visible_src_rect = image->CorrectSrcRectForImageOrientation(
- intrinsic_tile_size, visible_src_rect);
- }
-
+ if (absl::optional<FloatRect> single_tile_src = OptimizeToSingleTileDraw(
+ geometry, dest_rect_for_subset, image, respect_orientation)) {
context.DrawImage(image, Image::kSyncDecode,
- FloatRect(geometry.SnappedDestRect()), &visible_src_rect,
+ FloatRect(geometry.SnappedDestRect()), &*single_tile_src,
has_filter_property, op, respect_orientation);
return;
}
// At this point we have decided to tile the image to fill the dest rect.
+
+ // Use the intrinsic size of the image if it has one, otherwise force the
+ // generated image to be the tile size.
+ // image-resolution information is baked into the given parameters, but we
+ // need oriented size. That requires explicitly applying orientation here.
+ Image::SizeConfig size_config;
+ size_config.apply_orientation = respect_orientation;
+ const FloatSize intrinsic_tile_size =
+ image->SizeWithConfigAsFloat(size_config);
+
// Note that this tile rect uses the image's pre-scaled size.
- FloatRect tile_rect(FloatPoint(), intrinsic_tile_size);
+ ImageTilingInfo tiling_info;
+ tiling_info.image_rect.SetSize(intrinsic_tile_size);
+ tiling_info.phase = FloatPoint(geometry.ComputeDestPhase());
+ tiling_info.spacing = FloatSize(geometry.SpaceSize());
// Farther down the pipeline we will use the scaled tile size to determine
// which dimensions to clamp or repeat in. We do not want to repeat when the
@@ -535,82 +547,86 @@ void DrawTiledBackground(GraphicsContext& context,
// values in that dimension.
const PhysicalSize tile_dest_diff =
geometry.TileSize() - geometry.SnappedDestRect().size;
- if (tile_dest_diff.width.Abs() <= 0.5f) {
- scale.SetWidth(geometry.SnappedDestRect().Width() /
- intrinsic_tile_size.Width());
- }
- if (tile_dest_diff.height.Abs() <= 0.5f) {
- scale.SetHeight(geometry.SnappedDestRect().Height() /
- intrinsic_tile_size.Height());
- }
+ const LayoutUnit ref_tile_width = tile_dest_diff.width.Abs() <= 0.5f
+ ? geometry.SnappedDestRect().Width()
+ : geometry.TileSize().width;
+ const LayoutUnit ref_tile_height = tile_dest_diff.height.Abs() <= 0.5f
+ ? geometry.SnappedDestRect().Height()
+ : geometry.TileSize().height;
+ tiling_info.scale = {ref_tile_width / tiling_info.image_rect.Width(),
+ ref_tile_height / tiling_info.image_rect.Height()};
// 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.
context.DrawImageTiled(image, FloatRect(geometry.SnappedDestRect()),
- tile_rect, scale, FloatPoint(dest_phase),
- FloatSize(geometry.SpaceSize()), op,
+ tiling_info, has_filter_property, op,
respect_orientation);
}
-// Returning false meaning that we cannot paint background color with
-// BackgroundColorPaintWorklet.
-bool GetBGColorPaintWorkletParams(const BoxPainterBase::FillLayerInfo& info,
- const Document* document,
- Node* node,
- Vector<Color>* animated_colors,
- Vector<double>* offsets,
- absl::optional<double>* progress) {
- if (!info.should_paint_color_with_paint_worklet_image)
- return false;
- BackgroundColorPaintImageGenerator* generator =
- document->GetFrame()->GetBackgroundColorPaintImageGenerator();
- return generator->GetBGColorPaintWorkletParams(node, animated_colors, offsets,
- progress);
-}
-
-void FillRectWithPaintWorklet(const Document* document,
- const BoxPainterBase::FillLayerInfo& info,
- Node* node,
- const FloatRoundedRect& dest_rect,
- GraphicsContext& context,
- const Vector<Color>& animated_colors,
- const Vector<double>& offsets,
- const absl::optional<double>& progress) {
- FloatRect src_rect(FloatPoint(), dest_rect.Rect().Size());
+scoped_refptr<Image> GetBGColorPaintWorkletImage(const Document* document,
+ Node* node,
+ const FloatSize& image_size) {
+ LocalFrame* frame = document->GetFrame();
+ if (!frame)
+ return nullptr;
BackgroundColorPaintImageGenerator* generator =
- document->GetFrame()->GetBackgroundColorPaintImageGenerator();
- scoped_refptr<Image> paint_worklet_image = generator->Paint(
- src_rect.Size(), node, animated_colors, offsets, progress);
- context.DrawImageRRect(
- paint_worklet_image.get(), Image::kSyncDecode, dest_rect, src_rect,
- node && node->ComputedStyleRef().HasFilterInducingProperty(),
- SkBlendMode::kSrcOver, info.respect_image_orientation);
+ frame->GetBackgroundColorPaintImageGenerator();
+ // The generator can be null in testing environment.
+ if (!generator)
+ return nullptr;
+ Vector<Color> animated_colors;
+ Vector<double> offsets;
+ absl::optional<double> progress;
+ if (!generator->GetBGColorPaintWorkletParams(node, &animated_colors, &offsets,
+ &progress)) {
+ return nullptr;
+ }
+ return generator->Paint(image_size, node, animated_colors, offsets, progress);
}
-// Returns true if we can paint the background color with paint worklet.
+// Returns true if the background color was painted by the paint worklet.
bool PaintBGColorWithPaintWorklet(const Document* document,
const BoxPainterBase::FillLayerInfo& info,
Node* node,
const FloatRoundedRect& dest_rect,
GraphicsContext& context) {
- // TODO(xidachen): Consider merge this into GetBGColorPaintWorkletParams, so
- // that function doesn't need to return these parameters.
- Vector<Color> animated_colors;
- Vector<double> offsets;
- absl::optional<double> progress;
- if (GetBGColorPaintWorkletParams(info, document, node, &animated_colors,
- &offsets, &progress)) {
- FillRectWithPaintWorklet(document, info, node, dest_rect, context,
- animated_colors, offsets, progress);
- return true;
- }
- return false;
+ if (!info.should_paint_color_with_paint_worklet_image)
+ return false;
+ scoped_refptr<Image> paint_worklet_image =
+ GetBGColorPaintWorkletImage(document, node, dest_rect.Rect().Size());
+ if (!paint_worklet_image)
+ return false;
+ FloatRect src_rect(FloatPoint(), dest_rect.Rect().Size());
+ context.DrawImageRRect(paint_worklet_image.get(), Image::kSyncDecode,
+ dest_rect, src_rect,
+ node && node->ComputedStyleRef().DisableForceDark());
+ return true;
+}
+
+void DidDrawImage(
+ Node* node,
+ const Image& image,
+ const StyleImage& style_image,
+ const PropertyTreeStateOrAlias& current_paint_chunk_properties,
+ const FloatRect& image_rect) {
+ if (!node || !style_image.IsImageResource())
+ return;
+ const IntRect enclosing_rect = EnclosingIntRect(image_rect);
+ PaintTimingDetector::NotifyBackgroundImagePaint(
+ *node, image, To<StyleFetchedImage>(style_image),
+ current_paint_chunk_properties, enclosing_rect);
+
+ LocalDOMWindow* window = node->GetDocument().domWindow();
+ DCHECK(window);
+ ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
+ *node, To<StyleFetchedImage>(style_image), current_paint_chunk_properties,
+ enclosing_rect);
}
inline bool PaintFastBottomLayer(const Document* document,
Node* node,
- const PaintInfo& paint_info,
+ GraphicsContext& context,
const BoxPainterBase::FillLayerInfo& info,
const PhysicalRect& rect,
const FloatRoundedRect& border_rect,
@@ -630,7 +646,6 @@ inline bool PaintFastBottomLayer(const Document* document,
// 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));
@@ -638,9 +653,9 @@ inline bool PaintFastBottomLayer(const Document* document,
// 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.
- PhysicalRect image_tile;
+ FloatRect src_rect;
FloatRoundedRect image_border;
- if (info.should_paint_image) {
+ if (info.should_paint_image && image) {
// Avoid image shaders when printing (poorly supported in PDF).
if (info.is_rounded_fill && info.is_printing)
return false;
@@ -651,32 +666,32 @@ inline bool PaintFastBottomLayer(const Document* document,
? color_border
: FloatRoundedRect(FloatRect(geometry.SnappedDestRect()));
- if (!image_border.Rect().IsEmpty()) {
+ const FloatRect& image_rect = image_border.Rect();
+ if (!image_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())
+ if (geometry.TileSize().width < image_rect.Width() ||
+ geometry.TileSize().height < image_rect.Height())
return false;
- // Phase calculation uses the actual painted location, given by the
- // border-snapped destination rect.
- image_tile = PhysicalRect(geometry.SnappedDestRect().offset +
- ComputePhaseForBackground(geometry),
- geometry.TileSize());
-
// Use FastAndLossyFromFloatRect when converting the image border rect.
// At this point it should have been derived from a snapped rectangle, so
// the conversion from float should be as precise as it can be.
+ const PhysicalRect dest_rect =
+ PhysicalRect::FastAndLossyFromFloatRect(image_rect);
- // We cannot optimize if the tile is misaligned.
- if (!image_tile.Contains(
- PhysicalRect::FastAndLossyFromFloatRect(image_border.Rect())))
+ absl::optional<FloatRect> single_tile_src = OptimizeToSingleTileDraw(
+ geometry, dest_rect, image, info.respect_image_orientation);
+ if (!single_tile_src)
return false;
+ src_rect = *single_tile_src;
}
}
// 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.
+ // calls. Furthermore, if an image should be painted, |src_rect| has been
+ // updated to account for positioning and size parameters by
+ // OptimizeToSingleTileDraw() in the above code block.
absl::optional<RoundedInnerRectClipper> clipper;
if (info.is_rounded_fill && !color_border.IsRenderable()) {
// When the rrect is not renderable, we resort to clipping.
@@ -698,47 +713,9 @@ inline bool PaintFastBottomLayer(const Document* document,
}
// Paint the image if needed.
- if (!info.should_paint_image || !image || image_tile.IsEmpty())
+ if (!info.should_paint_image || src_rect.IsEmpty())
return true;
- // Generated images will be created at the desired tile size, so assume their
- // intrinsic size is the requested tile size.
- bool has_intrinsic_size = image->HasIntrinsicSize();
- const FloatSize intrinsic_tile_size =
- !has_intrinsic_size
- ? FloatSize(image_tile.size)
- : FloatSize(image->Size(info.respect_image_orientation));
-
- // 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. But if
- // this is a generated image sized according to the tile size (which is a
- // snapped value), use the snapped dest rect instead.
- const PhysicalRect dest_rect_for_subset(
- geometry.SnappedDestRect().offset,
- !has_intrinsic_size ? geometry.SnappedDestRect().size
- : 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 unrounded_subset = ComputeSubsetForBackground(
- image_tile, dest_rect_for_subset, intrinsic_tile_size);
- FloatRect src_rect = SnapSourceRectIfNearIntegral(unrounded_subset);
-
- // If we have snapped the image size to 0, revert the rounding.
- if (src_rect.IsEmpty())
- src_rect = unrounded_subset;
-
- // When respecting image orientation, the drawing code expects the source rect
- // to be in the unrotated image space, but we have computed it here in the
- // rotated space in order to position and size the background. Undo the src
- // rect rotation if necessaary.
- if (info.respect_image_orientation && !image->HasDefaultOrientation()) {
- src_rect =
- image->CorrectSrcRectForImageOrientation(intrinsic_tile_size, src_rect);
- }
-
DEVTOOLS_TIMELINE_TRACE_EVENT_WITH_CATEGORIES(
TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
inspector_paint_image_event::Data, node, *info.image,
@@ -746,24 +723,13 @@ inline bool PaintFastBottomLayer(const Document* document,
// Since there is no way for the developer to specify decode behavior, use
// kSync by default.
- context.DrawImageRRect(
- image, Image::kSyncDecode, image_border, src_rect,
- node && node->ComputedStyleRef().HasFilterInducingProperty(),
- composite_op, info.respect_image_orientation);
-
- if (node && info.image && info.image->IsImageResource()) {
- PaintTimingDetector::NotifyBackgroundImagePaint(
- *node, *image, To<StyleFetchedImage>(*info.image),
- paint_info.context.GetPaintController().CurrentPaintChunkProperties(),
- RoundedIntRect(image_border.Rect()));
-
- LocalDOMWindow* window = node->GetDocument().domWindow();
- DCHECK(window);
- ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
- *node, To<StyleFetchedImage>(*info.image),
- context.GetPaintController().CurrentPaintChunkProperties(),
- RoundedIntRect(image_border.Rect()));
- }
+ context.DrawImageRRect(image, Image::kSyncDecode, image_border, src_rect,
+ node && node->ComputedStyleRef().DisableForceDark(),
+ composite_op, info.respect_image_orientation);
+
+ DidDrawImage(node, *image, *info.image,
+ context.GetPaintController().CurrentPaintChunkProperties(),
+ image_border.Rect());
return true;
}
@@ -843,7 +809,7 @@ FloatRoundedRect RoundedBorderRectForClip(
PhysicalRect border_rect =
PhysicalRect::FastAndLossyFromFloatRect(border.Rect());
if (bg_layer.Clip() == EFillBox::kContent) {
- border = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
+ border = RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
style, border_rect, border_padding_insets, info.sides_to_include);
} else if (bg_layer.Clip() == EFillBox::kPadding) {
border = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
@@ -865,7 +831,7 @@ void PaintFillLayerBackground(const Document* document,
// TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the
// culling test by verifying whether the background image covers the entire
// painting area.
- if (info.is_bottom_layer && info.color.Alpha() && info.should_paint_color) {
+ if (info.should_paint_color) {
IntRect background_rect(PixelSnappedIntRect(scrolled_paint_rect));
// Try to paint the background with a paint worklet first in case it will be
// animated. Otherwise, paint it directly into the context.
@@ -884,23 +850,12 @@ void PaintFillLayerBackground(const Document* document,
TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
inspector_paint_image_event::Data, node, *info.image,
FloatRect(image->Rect()), FloatRect(scrolled_paint_rect));
- DrawTiledBackground(
- context, image, geometry, composite_op,
- node && node->ComputedStyleRef().HasFilterInducingProperty(),
- info.respect_image_orientation);
- if (node && info.image && info.image->IsImageResource()) {
- PaintTimingDetector::NotifyBackgroundImagePaint(
- *node, *image, To<StyleFetchedImage>(*info.image),
- context.GetPaintController().CurrentPaintChunkProperties(),
- EnclosingIntRect(geometry.SnappedDestRect()));
-
- LocalDOMWindow* window = node->GetDocument().domWindow();
- DCHECK(window);
- ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
- *node, To<StyleFetchedImage>(*info.image),
- context.GetPaintController().CurrentPaintChunkProperties(),
- EnclosingIntRect(geometry.SnappedDestRect()));
- }
+ DrawTiledBackground(context, image, geometry, composite_op,
+ node && node->ComputedStyleRef().DisableForceDark(),
+ info.respect_image_orientation);
+ DidDrawImage(node, *image, *info.image,
+ context.GetPaintController().CurrentPaintChunkProperties(),
+ FloatRect(geometry.SnappedDestRect()));
}
}
@@ -940,36 +895,37 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
const PhysicalSize& flow_box_size) {
- GraphicsContext& context = paint_info.context;
if (rect.IsEmpty())
return;
- const FillLayerInfo info =
+ const FillLayerInfo fill_layer_info =
GetFillLayerInfo(color, bg_layer, bleed_avoidance,
IsPaintingScrollingBackground(paint_info));
// If we're not actually going to paint anything, abort early.
- if (!info.should_paint_image && !info.should_paint_color)
+ if (!fill_layer_info.should_paint_image &&
+ !fill_layer_info.should_paint_color)
return;
+ GraphicsContext& context = paint_info.context;
GraphicsContextStateSaver clip_with_scrolling_state_saver(
- context, info.is_clipped_with_local_scrolling);
+ context, fill_layer_info.is_clipped_with_local_scrolling);
auto scrolled_paint_rect =
- AdjustRectForScrolledContent(paint_info, info, rect);
+ AdjustRectForScrolledContent(paint_info, fill_layer_info, rect);
const auto did_adjust_paint_rect = scrolled_paint_rect != rect;
scoped_refptr<Image> image;
SkBlendMode composite_op = SkBlendMode::kSrcOver;
absl::optional<ScopedInterpolationQuality> interpolation_quality_context;
- if (info.should_paint_image) {
+ if (fill_layer_info.should_paint_image) {
geometry.Calculate(paint_info.PaintContainer(), paint_info.phase, bg_layer,
scrolled_paint_rect);
- image = info.image->GetImage(
+ image = fill_layer_info.image->GetImage(
geometry.ImageClient(), geometry.ImageDocument(),
geometry.ImageStyle(style_), FloatSize(geometry.TileSize()));
interpolation_quality_context.emplace(context,
geometry.ImageInterpolationQuality());
- if (ShouldApplyBlendOperation(info, bg_layer)) {
+ if (ShouldApplyBlendOperation(fill_layer_info, bg_layer)) {
composite_op = WebCoreCompositeToSkiaComposite(bg_layer.Composite(),
bg_layer.GetBlendMode());
}
@@ -979,8 +935,8 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
LayoutRectOutsets padding = ComputePadding();
LayoutRectOutsets border_padding_insets = -(border + padding);
FloatRoundedRect border_rect = RoundedBorderRectForClip(
- style_, info, bg_layer, rect, object_has_multiple_boxes, flow_box_size,
- bleed_avoidance, border_padding_insets);
+ style_, fill_layer_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 with images if the dest rect has been adjusted for scrolling
@@ -989,22 +945,22 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
// if we are shrinking the background for bleed avoidance, because this
// adjusts the border rects in a way that breaks the optimization.
bool disable_fast_path =
- info.should_paint_image &&
+ fill_layer_info.should_paint_image &&
(bleed_avoidance == kBackgroundBleedShrinkBackground ||
did_adjust_paint_rect);
if (!disable_fast_path &&
- PaintFastBottomLayer(document_, node_, paint_info, info, rect,
+ PaintFastBottomLayer(document_, node_, context, fill_layer_info, rect,
border_rect, geometry, image.get(), composite_op)) {
return;
}
absl::optional<RoundedInnerRectClipper> clip_to_border;
- if (info.is_rounded_fill)
+ if (fill_layer_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,
+ PaintFillLayerTextFillBox(paint_info, fill_layer_info, image.get(),
+ composite_op, geometry, rect, scrolled_paint_rect,
object_has_multiple_boxes);
return;
}
@@ -1013,14 +969,17 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
switch (bg_layer.Clip()) {
case EFillBox::kPadding:
case EFillBox::kContent: {
- if (info.is_rounded_fill)
+ if (fill_layer_info.is_rounded_fill)
break;
// Clip to the padding or content boxes as necessary.
PhysicalRect clip_rect = scrolled_paint_rect;
- clip_rect.Contract(AdjustOutsetsForEdgeInclusion(border, info));
- if (bg_layer.Clip() == EFillBox::kContent)
- clip_rect.Contract(AdjustOutsetsForEdgeInclusion(padding, info));
+ clip_rect.Contract(
+ AdjustOutsetsForEdgeInclusion(border, fill_layer_info));
+ if (bg_layer.Clip() == EFillBox::kContent) {
+ clip_rect.Contract(
+ AdjustOutsetsForEdgeInclusion(padding, fill_layer_info));
+ }
background_clip_state_saver.Save();
context.Clip(PixelSnappedIntRect(clip_rect));
break;
@@ -1033,12 +992,13 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
break;
}
- PaintFillLayerBackground(document_, context, info, node_, image.get(),
- composite_op, geometry, scrolled_paint_rect);
+ PaintFillLayerBackground(document_, context, fill_layer_info, node_,
+ image.get(), composite_op, geometry,
+ scrolled_paint_rect);
}
void BoxPainterBase::PaintFillLayerTextFillBox(
- GraphicsContext& context,
+ const PaintInfo& paint_info,
const BoxPainterBase::FillLayerInfo& info,
Image* image,
SkBlendMode composite_op,
@@ -1051,6 +1011,8 @@ void BoxPainterBase::PaintFillLayerTextFillBox(
// rect with the border box of the background.
IntRect mask_rect = PixelSnappedIntRect(rect);
+ GraphicsContext& context = paint_info.context;
+
// We draw the background into a separate layer, to be later masked with
// yet another layer holding the text content.
GraphicsContextStateSaver background_clip_state_saver(context, false);
@@ -1067,7 +1029,7 @@ void BoxPainterBase::PaintFillLayerTextFillBox(
// they should just add their contents to the clip.
context.BeginLayer(1, SkBlendMode::kDstIn);
- PaintTextClipMask(context, mask_rect, scrolled_paint_rect.offset,
+ PaintTextClipMask(paint_info, mask_rect, scrolled_paint_rect.offset,
object_has_multiple_boxes);
context.EndLayer(); // Text mask layer.
@@ -1088,9 +1050,8 @@ void BoxPainterBase::PaintBorder(const ImageResourceObserver& obj,
return;
}
- const BoxBorderPainter border_painter(rect, style, bleed_avoidance,
- sides_to_include);
- border_painter.PaintBorder(info, rect);
+ BoxBorderPainter::PaintBorder(info.context, rect, style, bleed_avoidance,
+ sides_to_include);
}
void BoxPainterBase::PaintMaskImages(const PaintInfo& paint_info,
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 868f23d6e7a..f0cf368ecb7 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
@@ -22,7 +22,6 @@ class ComputedStyle;
class Document;
class FillLayer;
class FloatRoundedRect;
-class GraphicsContext;
class ImageResourceObserver;
class IntRect;
class LayoutBox;
@@ -145,7 +144,7 @@ class BoxPainterBase {
virtual LayoutRectOutsets ComputeBorders() const = 0;
virtual LayoutRectOutsets ComputePadding() const = 0;
LayoutRectOutsets AdjustedBorderOutsets(const FillLayerInfo&) const;
- void PaintFillLayerTextFillBox(GraphicsContext&,
+ void PaintFillLayerTextFillBox(const PaintInfo&,
const FillLayerInfo&,
Image*,
SkBlendMode composite_op,
@@ -153,7 +152,7 @@ class BoxPainterBase {
const PhysicalRect&,
const PhysicalRect& scrolled_paint_rect,
bool object_has_multiple_boxes);
- virtual void PaintTextClipMask(GraphicsContext&,
+ virtual void PaintTextClipMask(const PaintInfo&,
const IntRect& mask_rect,
const PhysicalOffset& paint_offset,
bool object_has_multiple_boxes) = 0;
diff --git a/chromium/third_party/blink/renderer/core/paint/build.gni b/chromium/third_party/blink/renderer/core/paint/build.gni
index bc9e44b569e..7812d2a77be 100644
--- a/chromium/third_party/blink/renderer/core/paint/build.gni
+++ b/chromium/third_party/blink/renderer/core/paint/build.gni
@@ -137,6 +137,8 @@ blink_core_sources_paint = [
"ng/ng_table_cell_paint_invalidator.h",
"ng/ng_table_painters.cc",
"ng/ng_table_painters.h",
+ "ng/ng_text_combine_painter.cc",
+ "ng/ng_text_combine_painter.h",
"ng/ng_text_fragment_painter.cc",
"ng/ng_text_fragment_painter.h",
"ng/ng_text_painter.cc",
@@ -150,8 +152,8 @@ blink_core_sources_paint = [
"object_paint_properties.h",
"object_painter.cc",
"object_painter.h",
- "object_painter_base.cc",
- "object_painter_base.h",
+ "outline_painter.cc",
+ "outline_painter.h",
"paint_event.h",
"paint_info.h",
"paint_invalidator.cc",
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 066bff54d9c..99d2790ba2a 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
@@ -4,6 +4,9 @@
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
+#include "third_party/blink/renderer/core/css/clip_path_paint_image_generator.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
@@ -13,6 +16,7 @@
#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/image.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"
@@ -40,10 +44,14 @@ LayoutSVGResourceClipper* ResolveElementReference(
return nullptr;
LayoutSVGResourceClipper* resource_clipper =
GetSVGResourceAsType(*client, reference_clip_path_operation);
- if (resource_clipper) {
- SECURITY_DCHECK(!resource_clipper->NeedsLayout());
- resource_clipper->ClearInvalidationMask();
- }
+ if (!resource_clipper)
+ return nullptr;
+
+ resource_clipper->ClearInvalidationMask();
+ if (DisplayLockUtilities::LockedAncestorPreventingLayout(*resource_clipper))
+ return nullptr;
+
+ SECURITY_DCHECK(!resource_clipper->SelfNeedsLayout());
return resource_clipper;
}
@@ -55,6 +63,34 @@ static bool UsesZoomedReferenceBox(const LayoutObject& clip_path_owner) {
return !clip_path_owner.IsSVGChild() || clip_path_owner.IsSVGForeignObject();
}
+static void PaintWorkletBasedClip(GraphicsContext& context,
+ const LayoutObject& clip_path_owner,
+ const FloatRect& reference_box,
+ bool uses_zoomed_reference_box) {
+ DCHECK(RuntimeEnabledFeatures::CompositeClipPathAnimationEnabled());
+ DCHECK_EQ(clip_path_owner.StyleRef().ClipPath()->GetType(),
+ ClipPathOperation::SHAPE);
+
+ float zoom = uses_zoomed_reference_box
+ ? clip_path_owner.StyleRef().EffectiveZoom()
+ : 1;
+ ClipPathPaintImageGenerator* generator =
+ clip_path_owner.GetFrame()->GetClipPathPaintImageGenerator();
+
+ scoped_refptr<Image> paint_worklet_image =
+ generator->Paint(zoom, reference_box, *clip_path_owner.GetNode());
+
+ // TODO(crbug.com/1223975): Fix bounding box. It should enclose affected area
+ // of the animation.
+ absl::optional<FloatRect> bounding_box =
+ ClipPathClipper::LocalClipPathBoundingBox(clip_path_owner);
+ DCHECK(bounding_box);
+ FloatRect src_rect(bounding_box.value());
+ context.DrawImage(paint_worklet_image.get(), Image::kSyncDecode, src_rect,
+ &src_rect, clip_path_owner.StyleRef().DisableForceDark(),
+ SkBlendMode::kSrcOver, kRespectImageOrientation);
+}
+
FloatRect ClipPathClipper::LocalReferenceBox(const LayoutObject& object) {
if (object.IsSVGChild())
return SVGResources::ReferenceBoxForEffects(object);
@@ -166,6 +202,8 @@ void ClipPathClipper::PaintClipPathAsMaskImage(
DisplayItem::kSVGClip))
return;
+ // TODO(crbug.com/1223975): Fix paint rectangle for
+ // CompositeClipPathAnimation.
DrawingRecorder recorder(
context, display_item_client, DisplayItem::kSVGClip,
EnclosingIntRect(properties->MaskClip()->UnsnappedClipRect().Rect()));
@@ -174,44 +212,57 @@ void ClipPathClipper::PaintClipPathAsMaskImage(
bool uses_zoomed_reference_box = UsesZoomedReferenceBox(layout_object);
FloatRect reference_box = LocalReferenceBox(layout_object);
- bool is_first = true;
- bool rest_of_the_chain_already_appled = false;
- const LayoutObject* current_object = &layout_object;
- while (!rest_of_the_chain_already_appled && current_object) {
- const ClipPathOperation* clip_path = current_object->StyleRef().ClipPath();
- if (!clip_path)
- break;
- // We wouldn't have reached here if the current clip-path is a shape,
- // because it would have been applied as a path-based clip already.
- LayoutSVGResourceClipper* resource_clipper = ResolveElementReference(
- *current_object, To<ReferenceClipPathOperation>(*clip_path));
- if (!resource_clipper)
- break;
-
- if (is_first)
- context.Save();
- else
- context.BeginLayer(1.f, SkBlendMode::kDstIn);
-
- if (resource_clipper->StyleRef().HasClipPath()) {
- // Try to apply nested clip-path as path-based clip.
- if (const absl::optional<Path>& path = PathBasedClipInternal(
- *resource_clipper, uses_zoomed_reference_box, reference_box)) {
- context.ClipPath(path->GetSkPath(), kAntiAliased);
- rest_of_the_chain_already_appled = true;
+ // TODO(crbug.com/1223975): Currently for CompositeClipPathAnimation feature
+ // to be activated a node must have clip-path attribute.
+ if (RuntimeEnabledFeatures::CompositeClipPathAnimationEnabled() &&
+ layout_object.StyleRef().HasCurrentClipPathAnimation() &&
+ layout_object.StyleRef().ClipPath()->GetType() ==
+ ClipPathOperation::SHAPE) {
+ if (!layout_object.GetFrame())
+ return;
+ PaintWorkletBasedClip(context, layout_object, reference_box,
+ uses_zoomed_reference_box);
+ } else {
+ bool is_first = true;
+ bool rest_of_the_chain_already_appled = false;
+ const LayoutObject* current_object = &layout_object;
+ while (!rest_of_the_chain_already_appled && current_object) {
+ const ClipPathOperation* clip_path =
+ current_object->StyleRef().ClipPath();
+ if (!clip_path)
+ break;
+ // We wouldn't have reached here if the current clip-path is a shape,
+ // because it would have been applied as a path-based clip already.
+ LayoutSVGResourceClipper* resource_clipper = ResolveElementReference(
+ *current_object, To<ReferenceClipPathOperation>(*clip_path));
+ if (!resource_clipper)
+ break;
+
+ if (is_first)
+ context.Save();
+ else
+ context.BeginLayer(1.f, SkBlendMode::kDstIn);
+
+ if (resource_clipper->StyleRef().HasClipPath()) {
+ // Try to apply nested clip-path as path-based clip.
+ if (const absl::optional<Path>& path = PathBasedClipInternal(
+ *resource_clipper, uses_zoomed_reference_box, reference_box)) {
+ context.ClipPath(path->GetSkPath(), kAntiAliased);
+ rest_of_the_chain_already_appled = true;
+ }
}
- }
- context.ConcatCTM(MaskToContentTransform(
- *resource_clipper, uses_zoomed_reference_box, reference_box));
- context.DrawRecord(resource_clipper->CreatePaintRecord());
+ context.ConcatCTM(MaskToContentTransform(
+ *resource_clipper, uses_zoomed_reference_box, reference_box));
+ context.DrawRecord(resource_clipper->CreatePaintRecord());
- if (is_first)
- context.Restore();
- else
- context.EndLayer();
+ if (is_first)
+ context.Restore();
+ else
+ context.EndLayer();
- is_first = false;
- current_object = resource_clipper;
+ is_first = false;
+ current_object = resource_clipper;
+ }
}
context.Restore();
}
@@ -219,6 +270,12 @@ void ClipPathClipper::PaintClipPathAsMaskImage(
bool ClipPathClipper::ShouldUseMaskBasedClip(const LayoutObject& object) {
if (object.IsText() || !object.StyleRef().HasClipPath())
return false;
+ // TODO(crbug.com/1223975): Currently for CompositeClipPathAnimation feature
+ // to be activated a node must have clip-path attribute.
+ if (RuntimeEnabledFeatures::CompositeClipPathAnimationEnabled() &&
+ object.StyleRef().ClipPath()->GetType() == ClipPathOperation::SHAPE &&
+ object.StyleRef().HasCurrentClipPathAnimation())
+ return true;
const auto* reference_clip =
DynamicTo<ReferenceClipPathOperation>(object.StyleRef().ClipPath());
if (!reference_clip)
@@ -232,6 +289,14 @@ bool ClipPathClipper::ShouldUseMaskBasedClip(const LayoutObject& object) {
absl::optional<Path> ClipPathClipper::PathBasedClip(
const LayoutObject& clip_path_owner) {
+ // TODO(crbug.com/1223975): Currently for CompositeClipPathAnimation feature
+ // to be activated a node must have clip-path attribute.
+ if (RuntimeEnabledFeatures::CompositeClipPathAnimationEnabled() &&
+ clip_path_owner.StyleRef().HasCurrentClipPathAnimation()) {
+ const ClipPathOperation& clip_path = *clip_path_owner.StyleRef().ClipPath();
+ if (clip_path.GetType() == ClipPathOperation::SHAPE)
+ return absl::nullopt;
+ }
return PathBasedClipInternal(clip_path_owner,
UsesZoomedReferenceBox(clip_path_owner),
LocalReferenceBox(clip_path_owner));
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 b7147fd7f3f..5d84c77416d 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
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/paint/collapsed_border_painter.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/box_border_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
@@ -362,36 +362,36 @@ void CollapsedBorderPainter::PaintCollapsedBorders(
rect.Y() - before_.outer_width,
rect.Width() + before_.begin_outset + before_.end_outset,
before_.outer_width + before_.inner_width);
- ObjectPainter::DrawBoxSide(context, edge_rect, BoxSide::kTop,
- before_.value->GetColor(),
- CollapsedBorderStyle(before_.value->Style()));
+ BoxBorderPainter::DrawBoxSide(context, edge_rect, BoxSide::kTop,
+ before_.value->GetColor(),
+ CollapsedBorderStyle(before_.value->Style()));
}
if (after_.value) {
IntRect edge_rect(rect.X() - after_.begin_outset,
rect.MaxY() - after_.inner_width,
rect.Width() + after_.begin_outset + after_.end_outset,
after_.inner_width + after_.outer_width);
- ObjectPainter::DrawBoxSide(context, edge_rect, BoxSide::kBottom,
- after_.value->GetColor(),
- CollapsedBorderStyle(after_.value->Style()));
+ BoxBorderPainter::DrawBoxSide(context, edge_rect, BoxSide::kBottom,
+ after_.value->GetColor(),
+ CollapsedBorderStyle(after_.value->Style()));
}
if (start_.value) {
IntRect edge_rect(rect.X() - start_.outer_width,
rect.Y() - start_.begin_outset,
start_.outer_width + start_.inner_width,
rect.Height() + start_.begin_outset + start_.end_outset);
- ObjectPainter::DrawBoxSide(context, edge_rect, BoxSide::kLeft,
- start_.value->GetColor(),
- CollapsedBorderStyle(start_.value->Style()));
+ BoxBorderPainter::DrawBoxSide(context, edge_rect, BoxSide::kLeft,
+ start_.value->GetColor(),
+ CollapsedBorderStyle(start_.value->Style()));
}
if (end_.value) {
IntRect edge_rect(rect.MaxX() - end_.inner_width,
rect.Y() - end_.begin_outset,
end_.inner_width + end_.outer_width,
rect.Height() + end_.begin_outset + end_.end_outset);
- ObjectPainter::DrawBoxSide(context, edge_rect, BoxSide::kRight,
- end_.value->GetColor(),
- CollapsedBorderStyle(end_.value->Style()));
+ BoxBorderPainter::DrawBoxSide(context, edge_rect, BoxSide::kRight,
+ end_.value->GetColor(),
+ CollapsedBorderStyle(end_.value->Style()));
}
}
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 68204175c25..ef97248755a 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
@@ -43,6 +43,7 @@
#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"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
@@ -143,7 +144,7 @@ static bool NeedsDecorationOutlineLayer(const PaintLayer& paint_layer,
// only 2/3 of the width is outside of the offset.
const int outline_drawn_inside =
style.OutlineStyleIsAuto()
- ? std::ceil(style.GetOutlineStrokeWidthForFocusRing() / 3.f) + 1
+ ? std::ceil(style.FocusRingInnerStrokeWidth()) + 1
: 0;
return could_obscure_decorations && style.HasOutline() &&
@@ -690,8 +691,7 @@ void CompositedLayerMapping::ComputeGraphicsLayerParentLocation(
if (compositing_container &&
compositing_container->NeedsCompositedScrolling()) {
auto& layout_box = To<LayoutBox>(compositing_container->GetLayoutObject());
- IntSize scroll_offset =
- FlooredIntSize(layout_box.PixelSnappedScrolledContentOffset());
+ IntPoint scroll_offset = layout_box.PixelSnappedScrolledContentOffset();
IntPoint scroll_origin =
compositing_container->GetScrollableArea()->ScrollOrigin();
scroll_origin.Move(-layout_box.OriginAdjustmentForScrollbars());
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 f0c7eaceb34..352db784fcb 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
@@ -1899,7 +1899,6 @@ TEST_P(CompositedLayerMappingTest,
// Unlike CompositingTest.WillChangeTransformHintInSVG, will-change hints on the
// SVG element itself should not opt into creating layers after paint.
TEST_P(CompositedLayerMappingTest, WillChangeTransformHintOnSVG) {
- ScopedCompositeSVGForTest enable_feature(true);
SetBodyInnerHTML(R"HTML(
<svg width="99" height="99" id="willChange" style="will-change: transform;">
<rect width="100%" height="100%" fill="blue"></rect>
@@ -1914,7 +1913,6 @@ TEST_P(CompositedLayerMappingTest, WillChangeTransformHintOnSVG) {
// Test that will-change changes inside SVG correctly update whether the
// graphics layer should create layers after paint.
TEST_P(CompositedLayerMappingTest, WillChangeTransformHintInSVGChanged) {
- ScopedCompositeSVGForTest enable_feature(true);
SetBodyInnerHTML(R"HTML(
<svg width="99" height="99" id="svg" style="will-change: transform;">
<rect id="rect" width="100%" height="100%" fill="blue"></rect>
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 10e6f5be696..bd35955cb37 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
@@ -198,12 +198,10 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
state, snapped_paint_offset + mask_layer->OffsetFromLayoutObject());
}
- if (RuntimeEnabledFeatures::CompositeSVGEnabled()) {
- if (object.IsSVGRoot()) {
- main_graphics_layer->SetShouldCreateLayersAfterPaint(
- To<LayoutSVGRoot>(object).HasDescendantCompositingReasons() &&
- main_graphics_layer->PaintsContentOrHitTest());
- }
+ if (object.IsSVGRoot()) {
+ main_graphics_layer->SetShouldCreateLayersAfterPaint(
+ To<LayoutSVGRoot>(object).HasDescendantCompositingReasons() &&
+ main_graphics_layer->PaintsContentOrHitTest());
}
}
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 054da3469e4..c033093e054 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
@@ -111,7 +111,7 @@ static bool ShouldPreferCompositingForLayoutView(
static CompositingReasons BackfaceInvisibility3DAncestorReason(
const PaintLayer& layer) {
- if (RuntimeEnabledFeatures::TransformInteropEnabled()) {
+ if (RuntimeEnabledFeatures::BackfaceVisibilityInteropEnabled()) {
if (auto* compositing_container = layer.CompositingContainer()) {
if (compositing_container->GetLayoutObject()
.StyleRef()
@@ -153,8 +153,7 @@ CompositingReasons CompositingReasonFinder::DirectReasonsForPaintProperties(
if (RequiresCompositingForRootScroller(*layer))
reasons |= CompositingReason::kRootScroller;
- if (RequiresCompositingForScrollDependentPosition(*layer))
- reasons |= CompositingReason::kScrollDependentPosition;
+ reasons |= CompositingReasonsForScrollDependentPosition(*layer);
if (RequiresCompositingForAffectedByOuterViewportBoundsDelta(object))
reasons |= CompositingReason::kAffectedByOuterViewportBoundsDelta;
@@ -162,6 +161,16 @@ CompositingReasons CompositingReasonFinder::DirectReasonsForPaintProperties(
if (style.HasBackdropFilter())
reasons |= CompositingReason::kBackdropFilter;
+ reasons |= BackfaceInvisibility3DAncestorReason(*layer);
+
+ if (auto* element = DynamicTo<Element>(object.GetNode())) {
+ if (element->ShouldCompositeForDocumentTransition())
+ reasons |= CompositingReason::kDocumentTransitionSharedElement;
+ }
+
+ if (object.CanHaveAdditionalCompositingReasons())
+ reasons |= object.AdditionalCompositingReasons();
+
if (auto* scrollable_area = layer->GetScrollableArea()) {
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
bool force_prefer_compositing_to_lcd_text =
@@ -181,16 +190,6 @@ CompositingReasons CompositingReasonFinder::DirectReasonsForPaintProperties(
reasons |= CompositingReason::kOverflowScrolling;
}
- reasons |= BackfaceInvisibility3DAncestorReason(*layer);
-
- if (auto* element = DynamicTo<Element>(object.GetNode())) {
- if (element->ShouldCompositeForDocumentTransition())
- reasons |= CompositingReason::kDocumentTransitionSharedElement;
- }
-
- if (object.CanHaveAdditionalCompositingReasons())
- reasons |= object.AdditionalCompositingReasons();
-
return reasons;
}
@@ -198,8 +197,6 @@ CompositingReasons
CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(
const LayoutObject& object) {
DCHECK(object.IsSVGChild());
- if (!RuntimeEnabledFeatures::CompositeSVGEnabled())
- return CompositingReason::kNone;
if (object.IsText())
return CompositingReason::kNone;
@@ -280,8 +277,7 @@ CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
}
}
- if (RequiresCompositingForScrollDependentPosition(layer))
- direct_reasons |= CompositingReason::kScrollDependentPosition;
+ direct_reasons |= CompositingReasonsForScrollDependentPosition(layer);
if (RequiresCompositingForAffectedByOuterViewportBoundsDelta(layout_object))
direct_reasons |= CompositingReason::kAffectedByOuterViewportBoundsDelta;
@@ -324,8 +320,6 @@ CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
static bool ObjectTypeSupportsCompositedTransformAnimation(
const LayoutObject& object) {
if (object.IsSVGChild()) {
- if (!RuntimeEnabledFeatures::CompositeSVGEnabled())
- return false;
// Transforms are not supported on hidden containers, inlines, or text.
return !object.IsSVGHiddenContainer() && !object.IsLayoutInline() &&
!object.IsText();
@@ -390,8 +384,10 @@ bool CompositingReasonFinder::RequiresCompositingForRootScroller(
return layer.GetLayoutObject().IsGlobalRootScroller();
}
-bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
+CompositingReasons
+CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
const PaintLayer& layer) {
+ CompositingReasons reasons = CompositingReason::kNone;
// Don't promote fixed position elements that are descendants of a non-view
// container, e.g. transformed elements. They will stay fixed wrt the
// container rather than the enclosing frame.
@@ -400,20 +396,19 @@ bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
// position elements are composited under overflow: hidden, which can still
// have smooth scroll animations.
LocalFrameView* frame_view = layer.GetLayoutObject().GetFrameView();
- return frame_view->LayoutViewport()->HasOverflow();
+ if (frame_view->LayoutViewport()->HasOverflow())
+ reasons |= CompositingReason::kFixedPosition;
}
// Don't promote sticky position elements that cannot move with scrolls.
- if (layer.SticksToScroller()) {
- // We check for |HasOverflow| instead of |ScrollsOverflow| to ensure sticky
- // position elements are composited under overflow: hidden, which can still
- // have smooth scroll animations.
- return layer.AncestorScrollContainerLayer()
- ->GetScrollableArea()
- ->HasOverflow();
- }
+ // We check for |HasOverflow| instead of |ScrollsOverflow| to ensure sticky
+ // position elements are composited under overflow: hidden, which can still
+ // have smooth scroll animations.
+ if (layer.SticksToScroller() &&
+ layer.AncestorScrollContainerLayer()->GetScrollableArea()->HasOverflow())
+ reasons |= CompositingReason::kStickyPosition;
- return false;
+ return reasons;
}
bool CompositingReasonFinder::
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 7640882046b..e865fa835aa 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
@@ -48,7 +48,8 @@ class CORE_EXPORT CompositingReasonFinder {
const LayoutObject&);
static bool RequiresCompositingForRootScroller(const PaintLayer&);
- static bool RequiresCompositingForScrollDependentPosition(const PaintLayer&);
+ static CompositingReasons CompositingReasonsForScrollDependentPosition(
+ const PaintLayer&);
static bool RequiresCompositingForAffectedByOuterViewportBoundsDelta(
const LayoutObject&);
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 67da1f6ba88..0379506f503 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
@@ -6,6 +6,7 @@
#include "base/test/scoped_feature_list.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
@@ -140,27 +141,31 @@ TEST_F(CompositingReasonFinderTest, OnlyScrollingStickyPositionPromoted) {
auto& sticky_scrolling =
*To<LayoutBoxModelObject>(GetLayoutObjectByElementId("sticky-scrolling"));
- EXPECT_TRUE(
- CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
- *sticky_scrolling.Layer()));
+ EXPECT_EQ(
+ CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+ *sticky_scrolling.Layer()),
+ CompositingReason::kStickyPosition);
auto& sticky_no_scrolling = *To<LayoutBoxModelObject>(
GetLayoutObjectByElementId("sticky-no-scrolling"));
- EXPECT_FALSE(
- CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
- *sticky_no_scrolling.Layer()));
+ EXPECT_EQ(
+ CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+ *sticky_no_scrolling.Layer()),
+ CompositingReason::kNone);
auto& overflow_hidden_scrolling = *To<LayoutBoxModelObject>(
GetLayoutObjectByElementId("overflow-hidden-scrolling"));
- EXPECT_TRUE(
- CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
- *overflow_hidden_scrolling.Layer()));
+ EXPECT_EQ(
+ CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+ *overflow_hidden_scrolling.Layer()),
+ CompositingReason::kStickyPosition);
auto& overflow_hidden_no_scrolling = *To<LayoutBoxModelObject>(
GetLayoutObjectByElementId("overflow-hidden-no-scrolling"));
- EXPECT_FALSE(
- CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
- *overflow_hidden_no_scrolling.Layer()));
+ EXPECT_EQ(
+ CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+ *overflow_hidden_no_scrolling.Layer()),
+ CompositingReason::kNone);
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
EXPECT_EQ(kPaintsIntoOwnBacking,
@@ -252,27 +257,31 @@ TEST_F(CompositingReasonFinderTest, PromoteCrossOriginIframe) {
<!DOCTYPE html>
<iframe id=iframe></iframe>
)HTML");
- UpdateAllLifecyclePhasesForTest();
HTMLFrameOwnerElement* iframe =
To<HTMLFrameOwnerElement>(GetDocument().getElementById("iframe"));
ASSERT_TRUE(iframe);
+ iframe->contentDocument()->OverrideIsInitialEmptyDocument();
+ To<LocalFrame>(iframe->ContentFrame())->View()->BeginLifecycleUpdates();
ASSERT_FALSE(iframe->ContentFrame()->IsCrossOriginToMainFrame());
+ UpdateAllLifecyclePhasesForTest();
LayoutView* iframe_layout_view =
To<LocalFrame>(iframe->ContentFrame())->ContentLayoutObject();
ASSERT_TRUE(iframe_layout_view);
PaintLayer* iframe_layer = iframe_layout_view->Layer();
ASSERT_TRUE(iframe_layer);
- EXPECT_EQ(kNotComposited, iframe_layer->DirectCompositingReasons());
+ EXPECT_EQ(CompositingReason::kNone, iframe_layer->DirectCompositingReasons());
+ EXPECT_FALSE(iframe_layer->GetScrollableArea()->NeedsCompositedScrolling());
+ EXPECT_EQ(CompositingReason::kNone,
+ CompositingReasonFinder::DirectReasonsForPaintProperties(
+ *iframe_layout_view));
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<iframe id=iframe sandbox></iframe>
)HTML");
iframe = To<HTMLFrameOwnerElement>(GetDocument().getElementById("iframe"));
- To<LocalFrame>(iframe->ContentFrame())
- ->GetDocument()
- ->OverrideIsInitialEmptyDocument();
+ iframe->contentDocument()->OverrideIsInitialEmptyDocument();
To<LocalFrame>(iframe->ContentFrame())->View()->BeginLifecycleUpdates();
UpdateAllLifecyclePhasesForTest();
iframe_layout_view =
@@ -282,11 +291,25 @@ TEST_F(CompositingReasonFinderTest, PromoteCrossOriginIframe) {
ASSERT_TRUE(iframe->ContentFrame()->IsCrossOriginToMainFrame());
EXPECT_EQ(CompositingReason::kIFrame,
iframe_layer->DirectCompositingReasons());
+ EXPECT_FALSE(iframe_layer->GetScrollableArea()->NeedsCompositedScrolling());
+ EXPECT_EQ(CompositingReason::kIFrame,
+ CompositingReasonFinder::DirectReasonsForPaintProperties(
+ *iframe_layout_view));
+
+ // Make the iframe contents scrollable.
+ iframe->contentDocument()->body()->setAttribute(html_names::kStyleAttr,
+ "height: 2000px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(iframe_layer->GetScrollableArea()->NeedsCompositedScrolling());
+ EXPECT_EQ(CompositingReason::kIFrame | CompositingReason::kOverflowScrolling,
+ CompositingReasonFinder::DirectReasonsForPaintProperties(
+ *iframe_layout_view));
}
TEST_F(CompositingReasonFinderTest,
CompositeWithBackfaceVisibilityAncestorAndPreserve3D) {
- ScopedTransformInteropForTest enabled(true);
+ ScopedTransformInteropForTest ti_enabled(true);
+ ScopedBackfaceVisibilityInteropForTest bfi_enabled(true);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -307,7 +330,8 @@ TEST_F(CompositingReasonFinderTest,
TEST_F(CompositingReasonFinderTest,
CompositeWithBackfaceVisibilityAncestorAndPreserve3DWithInterveningDiv) {
- ScopedTransformInteropForTest enabled(true);
+ ScopedTransformInteropForTest ti_enabled(true);
+ ScopedBackfaceVisibilityInteropForTest bfi_enabled(true);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -330,7 +354,8 @@ TEST_F(CompositingReasonFinderTest,
TEST_F(CompositingReasonFinderTest,
CompositeWithBackfaceVisibilityAncestorWithInterveningStackingDiv) {
- ScopedTransformInteropForTest enabled(true);
+ ScopedTransformInteropForTest ti_enabled(true);
+ ScopedBackfaceVisibilityInteropForTest bfi_enabled(true);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -358,7 +383,8 @@ TEST_F(CompositingReasonFinderTest,
TEST_F(CompositingReasonFinderTest,
CompositeWithBackfaceVisibilityAncestorAndFlattening) {
- ScopedTransformInteropForTest enabled(true);
+ ScopedTransformInteropForTest ti_enabled(true);
+ ScopedBackfaceVisibilityInteropForTest bfi_enabled(true);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -378,7 +404,8 @@ TEST_F(CompositingReasonFinderTest,
}
TEST_F(CompositingReasonFinderTest, CompositeWithBackfaceVisibility) {
- ScopedTransformInteropForTest enabled(true);
+ ScopedTransformInteropForTest ti_enabled(true);
+ ScopedBackfaceVisibilityInteropForTest bfi_enabled(true);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index 2606987c68e..c0078d40a28 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -5,6 +5,8 @@
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "cc/layers/picture_layer.h"
+#include "cc/layers/recording_source.h"
+#include "cc/layers/surface_layer.h"
#include "cc/trees/compositor_commit_data.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host.h"
@@ -25,6 +27,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/core/testing/fake_remote_frame_host.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/graphics/compositing/paint_artifact_compositor.h"
@@ -245,7 +248,6 @@ TEST_P(CompositingTest, WillChangeTransformHint) {
}
TEST_P(CompositingTest, WillChangeTransformHintInSVG) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
<!doctype html>
<style>
@@ -268,7 +270,6 @@ TEST_P(CompositingTest, WillChangeTransformHintInSVG) {
}
TEST_P(CompositingTest, Compositing3DTransformOnSVGModelObject) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
<!doctype html>
<svg width="200" height="200">
@@ -310,7 +311,6 @@ TEST_P(CompositingTest, Compositing3DTransformOnSVGModelObject) {
}
TEST_P(CompositingTest, Compositing3DTransformOnSVGBlock) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
<!doctype html>
<svg width="200" height="200">
@@ -354,7 +354,6 @@ TEST_P(CompositingTest, Compositing3DTransformOnSVGBlock) {
// Inlines do not support the transform property and should not be composited
// due to 3D transforms.
TEST_P(CompositingTest, NotCompositing3DTransformOnSVGInline) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
<!doctype html>
<svg width="200" height="200">
@@ -379,7 +378,6 @@ TEST_P(CompositingTest, NotCompositing3DTransformOnSVGInline) {
}
TEST_P(CompositingTest, PaintPropertiesWhenCompositingSVG) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
<!doctype html>
<style>
@@ -886,7 +884,6 @@ TEST_P(CompositingSimTest, DirectTransformPropertyUpdate) {
}
TEST_P(CompositingSimTest, DirectSVGTransformPropertyUpdate) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(R"HTML(
<!doctype html>
<style>
@@ -1002,11 +999,6 @@ TEST_P(CompositingSimTest, DirectTransformPropertyUpdateCausesChange) {
// so that the browser controls movement adjustments needed by bottom-fixed
// elements will work.
TEST_P(CompositingSimTest, AffectedByOuterViewportBoundsDelta) {
- // TODO(bokan): This test will have to be reevaluated for CAP. It looks like
- // the fixed layer isn't composited in CAP.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -1024,10 +1016,6 @@ TEST_P(CompositingSimTest, AffectedByOuterViewportBoundsDelta) {
auto* fixed_element = GetElementById("fixed");
auto* fixed_element_layer = CcLayerByDOMElementId("fixed");
- DCHECK_EQ(fixed_element_layer->element_id(),
- CompositorElementIdFromUniqueObjectId(
- fixed_element->GetLayoutObject()->UniqueId(),
- CompositorElementIdNamespace::kPrimary));
// Fix the DIV to the bottom of the viewport. Since the viewport height will
// expand/contract, the fixed element will need to be moved as the bounds
@@ -1108,12 +1096,6 @@ TEST_P(CompositingSimTest, DirectTransformOriginPropertyUpdate) {
// This test is similar to |LayerSubtreeTransformPropertyChanged| but for
// effect property node changes.
TEST_P(CompositingSimTest, LayerSubtreeEffectPropertyChanged) {
- // TODO(crbug.com/765003): CAP may make different layerization decisions and
- // we cannot guarantee that both divs will be composited in this test. When
- // CAP gets closer to launch, this test should be updated to pass.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -1140,16 +1122,7 @@ TEST_P(CompositingSimTest, LayerSubtreeEffectPropertyChanged) {
auto* outer_element = GetElementById("outer");
auto* outer_element_layer = CcLayerByDOMElementId("outer");
- DCHECK_EQ(outer_element_layer->element_id(),
- CompositorElementIdFromUniqueObjectId(
- outer_element->GetLayoutObject()->UniqueId(),
- CompositorElementIdNamespace::kPrimary));
- auto* inner_element = GetElementById("inner");
auto* inner_element_layer = CcLayerByDOMElementId("inner");
- DCHECK_EQ(inner_element_layer->element_id(),
- CompositorElementIdFromUniqueObjectId(
- inner_element->GetLayoutObject()->UniqueId(),
- CompositorElementIdNamespace::kPrimary));
// Initially, no layer should have |subtree_property_changed| set.
EXPECT_FALSE(outer_element_layer->subtree_property_changed());
@@ -1161,11 +1134,9 @@ TEST_P(CompositingSimTest, LayerSubtreeEffectPropertyChanged) {
// both layers.
outer_element->setAttribute(html_names::kStyleAttr, "filter: blur(20px)");
UpdateAllLifecyclePhases();
- // TODO(wangxianzhu): Probably avoid setting this flag on transform change.
EXPECT_TRUE(outer_element_layer->subtree_property_changed());
// Set by blink::PropertyTreeManager.
EXPECT_TRUE(GetEffectNode(outer_element_layer)->effect_changed);
- // TODO(wangxianzhu): Probably avoid setting this flag on transform change.
EXPECT_TRUE(inner_element_layer->subtree_property_changed());
EXPECT_FALSE(GetEffectNode(inner_element_layer)->effect_changed);
@@ -1229,12 +1200,6 @@ TEST_P(CompositingSimTest, LayerSubtreeClipPropertyChanged) {
}
TEST_P(CompositingSimTest, LayerSubtreeOverflowClipPropertyChanged) {
- // TODO(crbug.com/765003): CAP may make different layerization decisions and
- // we cannot guarantee that both divs will be composited in this test. When
- // CAP gets closer to launch, this test should be updated to pass.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -1262,12 +1227,7 @@ TEST_P(CompositingSimTest, LayerSubtreeOverflowClipPropertyChanged) {
auto* outer_element = GetElementById("outer");
auto* outer_element_layer = CcLayerByDOMElementId("outer");
- auto* inner_element = GetElementById("inner");
auto* inner_element_layer = CcLayerByDOMElementId("inner");
- DCHECK_EQ(inner_element_layer->element_id(),
- CompositorElementIdFromUniqueObjectId(
- inner_element->GetLayoutObject()->UniqueId(),
- CompositorElementIdNamespace::kPrimary));
// Initially, no layer should have |subtree_property_changed| set.
EXPECT_FALSE(outer_element_layer->subtree_property_changed());
@@ -1482,11 +1442,6 @@ TEST_P(CompositingSimTest, RootScrollingContentsSafeOpaqueBackgroundColor) {
}
TEST_P(CompositingSimTest, NonDrawableLayersIgnoredForRenderSurfaces) {
- // TODO(crbug.com/765003): CAP may make different layerization decisions. When
- // CAP gets closer to launch, this test should be updated to pass.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -1746,13 +1701,6 @@ TEST_P(CompositingTest, EffectNodesShouldHaveStableIds) {
}
TEST_P(CompositingSimTest, ImplSideScrollSkipsCommit) {
- // TODO(crbug.com/1046544): This test fails with CompositeAfterPaint because
- // PaintArtifactCompositor::Update is run for scroll offset changes. When we
- // have an early-out to avoid SetNeedsCommit for non-changing interest-rects,
- // this test will pass.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
InitializeWithHTML(R"HTML(
<div id='scroller' style='will-change: transform; overflow: scroll;
width: 100px; height: 100px'>
@@ -2006,11 +1954,10 @@ TEST_P(CompositingSimTest, MultipleChunkBackgroundColorChangeRepaintUpdate) {
EXPECT_EQ(scrolling_contents->background_color(), SK_ColorWHITE);
}
-// Similar to |BackgroundColorChangeUsesRepaintUpdate| but with CompositeSVG.
-// This test changes paint for a composited SVG element, as well as a regular
-// HTML element in the presence of composited SVG.
+// Similar to |BackgroundColorChangeUsesRepaintUpdate| but with post-paint
+// composited SVG. This test changes paint for a composited SVG element, as well
+// as a regular HTML element in the presence of composited SVG.
TEST_P(CompositingSimTest, SVGColorChangeUsesRepaintUpdate) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -2150,6 +2097,63 @@ TEST_P(CompositingSimTest, ChangingContentsOpaqueForTextRequiresFullUpdate) {
EXPECT_FALSE(CcLayerByDOMElementId("target")->contents_opaque_for_text());
}
+TEST_P(CompositingSimTest, ContentsOpaqueForTextWithSubpixelSizeSimpleBg) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <div id="target" style="will-change: transform; background: white;
+ width: 100.6px; height: 10.3px">
+ TEXT
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+ auto* cc_layer = CcLayerByDOMElementId("target");
+ // In CompositeAfterPaint, we adjust visual rect of the DrawingDisplayItem
+ // with simple painting to the bounds of the painting.
+ EXPECT_EQ(gfx::Size(101, 10), cc_layer->bounds());
+ EXPECT_TRUE(cc_layer->contents_opaque());
+ EXPECT_TRUE(cc_layer->contents_opaque_for_text());
+}
+
+TEST_P(CompositingSimTest, ContentsOpaqueForTextWithSubpixelSizeComplexBg) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <div id="target" style="will-change: transform; background: white;
+ border: 2px inset blue;
+ width: 100.6px; height: 10.3px">
+ TEXT
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+ auto* cc_layer = CcLayerByDOMElementId("target");
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_EQ(gfx::Size(105, 15), cc_layer->bounds());
+ EXPECT_FALSE(cc_layer->contents_opaque());
+ } else {
+ // Pre-CAP always pixel-snaps composited layer bounds, which might be
+ // incorrect in some corner cases where we don't pixel-snap painting.
+ EXPECT_EQ(gfx::Size(105, 14), cc_layer->bounds());
+ EXPECT_TRUE(cc_layer->contents_opaque());
+ }
+ EXPECT_TRUE(cc_layer->contents_opaque_for_text());
+}
+
+TEST_P(CompositingSimTest, ContentsOpaqueForTextWithPartialBackground) {
+ // This test works only with the new text opaque algorithm.
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <div id="target" style="will-change: transform; padding: 10px">
+ <div style="background: white">TEXT</div>
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+ auto* cc_layer = CcLayerByDOMElementId("target");
+ EXPECT_FALSE(cc_layer->contents_opaque());
+ EXPECT_TRUE(cc_layer->contents_opaque_for_text());
+}
+
TEST_P(CompositingSimTest, FullCompositingUpdateReasons) {
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
@@ -2218,9 +2222,9 @@ TEST_P(CompositingSimTest, FullCompositingUpdateReasons) {
PaintArtifactCompositor::PreviousUpdateType::kFull);
}
-// Similar to |FullCompositingUpdateReasons| but for changes in CompositeSVG.
-TEST_P(CompositingSimTest, FullCompositingUpdateReasonInCompositeSVG) {
- ScopedCompositeSVGForTest enable_feature(true);
+// Similar to |FullCompositingUpdateReasons| but for changes in post-paint
+// composited SVG.
+TEST_P(CompositingSimTest, FullCompositingUpdateReasonWithCompositedSVG) {
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -2252,7 +2256,6 @@ TEST_P(CompositingSimTest, FullCompositingUpdateReasonInCompositeSVG) {
}
TEST_P(CompositingSimTest, FullCompositingUpdateForJustCreatedChunks) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -2290,7 +2293,6 @@ TEST_P(CompositingSimTest, FullCompositingUpdateForJustCreatedChunks) {
}
TEST_P(CompositingSimTest, FullCompositingUpdateForUncachableChunks) {
- ScopedCompositeSVGForTest enable_feature(true);
InitializeWithHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -2376,4 +2378,194 @@ TEST_P(CompositingSimTest, DecompositeScrollerInHiddenIframe) {
EXPECT_FALSE(scroller->GetScrollableArea()->NeedsCompositedScrolling());
}
+TEST_P(CompositingSimTest, ForeignLayersInMovedSubsequence) {
+ SimRequest main_resource("https://origin-a.com/a.html", "text/html");
+ LoadURL("https://origin-a.com/a.html");
+ main_resource.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style> iframe { isolation: isolate; } </style>
+ <iframe sandbox src="https://origin-b.com/b.html"></iframe>
+ <div id="target" style="background: blue;">a</div>
+ )HTML");
+
+ frame_test_helpers::TestWebRemoteFrameClient remote_frame_client;
+ FakeRemoteFrameHost remote_frame_host;
+ remote_frame_host.Init(remote_frame_client.GetRemoteAssociatedInterfaces());
+ WebRemoteFrameImpl* remote_frame =
+ frame_test_helpers::CreateRemote(&remote_frame_client);
+ MainFrame().FirstChild()->Swap(remote_frame);
+
+ Compositor().BeginFrame();
+
+ auto remote_surface_layer = cc::SurfaceLayer::Create();
+ remote_frame->GetFrame()->SetCcLayerForTesting(remote_surface_layer, true);
+ Compositor().BeginFrame();
+
+ // Initially, no update is needed.
+ EXPECT_FALSE(paint_artifact_compositor()->NeedsUpdate());
+
+ // Clear the previous update to ensure we record a new one in the next update.
+ paint_artifact_compositor()->ClearPreviousUpdateForTesting();
+
+ // Modifying paint in a simple way only requires a repaint update.
+ auto* target_element = GetElementById("target");
+ target_element->setAttribute(html_names::kStyleAttr, "background: green;");
+ Compositor().BeginFrame();
+ EXPECT_EQ(paint_artifact_compositor()->PreviousUpdateForTesting(),
+ PaintArtifactCompositor::PreviousUpdateType::kRepaint);
+
+ remote_frame->Detach();
+}
+
+// While not required for correctness, it is important for performance that
+// snapped backgrounds use solid color layers which avoid tiling.
+TEST_P(CompositingSimTest, SolidColorLayersWithSnapping) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #snapDown {
+ width: 60.1px;
+ height: 100px;
+ will-change: opacity;
+ background: blue;
+ }
+ #snapUp {
+ width: 60.9px;
+ height: 100px;
+ will-change: opacity;
+ background: blue;
+ }
+ </style>
+ <div id="snapDown"></div>
+ <div id="snapUp"></div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ auto* snap_down =
+ static_cast<const cc::PictureLayer*>(CcLayerByDOMElementId("snapDown"));
+ EXPECT_TRUE(snap_down->GetRecordingSourceForTesting()->is_solid_color());
+ auto* snap_up =
+ static_cast<const cc::PictureLayer*>(CcLayerByDOMElementId("snapUp"));
+ EXPECT_TRUE(snap_up->GetRecordingSourceForTesting()->is_solid_color());
+}
+
+TEST_P(CompositingSimTest, SolidColorLayerWithSubpixelTransform) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #forceCompositing {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ will-change: transform;
+ }
+ #target {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 60.9px;
+ height: 60.1px;
+ transform: translate(0.4px, 0.6px);
+ background: blue;
+ }
+ </style>
+ <div id="forceCompositing"></div>
+ <div id="target"></div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ auto* target =
+ static_cast<const cc::PictureLayer*>(CcLayerByDOMElementId("target"));
+ EXPECT_TRUE(target->GetRecordingSourceForTesting()->is_solid_color());
+ EXPECT_NEAR(0.4, target->offset_to_transform_parent().x(), 0.001);
+ EXPECT_NEAR(0.6, target->offset_to_transform_parent().y(), 0.001);
+}
+
+// While not required for correctness, it is important for performance (e.g.,
+// the MotionMark Focus benchmark) that we do not decomposite effect nodes (see:
+// |PaintArtifactCompositor::DecompositeEffect|) when the author has specified
+// 3D transforms which are frequently used as a generic compositing trigger.
+TEST_P(CompositingSimTest, EffectCompositedWith3DTransform) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background: rebeccapurple;
+ transform: translate3d(1px, 1px, 0);
+ }
+ </style>
+ <div id="opacity" style="opacity: 0.5;"></div>
+ <div id="filter" style="filter: blur(1px);"></div>
+ )HTML");
+ Compositor().BeginFrame();
+
+ auto* opacity_effect = GetEffectNode(CcLayerByDOMElementId("opacity"));
+ EXPECT_TRUE(opacity_effect);
+ EXPECT_EQ(opacity_effect->opacity, 0.5f);
+ EXPECT_TRUE(opacity_effect->filters.IsEmpty());
+
+ auto* filter_effect = GetEffectNode(CcLayerByDOMElementId("filter"));
+ EXPECT_TRUE(filter_effect);
+ EXPECT_EQ(filter_effect->opacity, 1.f);
+ EXPECT_FALSE(filter_effect->filters.IsEmpty());
+}
+
+// The main thread will not have a chance to update the painted content of an
+// animation running on the compositor, so ensure the cc::Layer with animating
+// opacity has content when starting the animation, even if the opacity is
+// initially 0.
+TEST_P(CompositingSimTest, CompositorAnimationOfOpacityHasPaintedContent) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ @keyframes opacity {
+ 0% { opacity: 0; }
+ 99% { opacity: 0; }
+ 100% { opacity: 0.5; }
+ }
+ #animation {
+ animation-name: opacity;
+ animation-duration: 999s;
+ width: 100px;
+ height: 100px;
+ background: lightblue;
+ }
+ </style>
+ <div id="animation"></div>
+ )HTML");
+ Compositor().BeginFrame();
+ EXPECT_TRUE(CcLayerByDOMElementId("animation")->DrawsContent());
+}
+
+TEST_P(CompositingSimTest, CompositorAnimationOfNonInvertibleTransform) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ @keyframes anim {
+ 0% { transform: scale(0); }
+ 99% { transform: scale(0); }
+ 100% { transform: scale(1); }
+ }
+ #animation {
+ animation-name: anim;
+ animation-duration: 999s;
+ width: 100px;
+ height: 100px;
+ background: lightblue;
+ }
+ </style>
+ <div id="animation"></div>
+ )HTML");
+ Compositor().BeginFrame();
+ EXPECT_TRUE(CcLayerByDOMElementId("animation"));
+ EXPECT_TRUE(CcLayerByDOMElementId("animation")->DrawsContent());
+}
+
} // namespace blink
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 72c31017cc4..96f0d086e68 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
@@ -174,7 +174,7 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursive(
UpdateAssignmentsIfNeededRecursiveInternal(target_state,
compositing_reasons_stats);
UMA_HISTOGRAM_CUSTOM_COUNTS("Blink.Compositing.LayerPromotionCount.Overlap",
- compositing_reasons_stats.overlap_layers, 1, 100,
+ compositing_reasons_stats.overlap_layers, 1, 1000,
5);
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Blink.Compositing.LayerPromotionCount.ActiveAnimation",
diff --git a/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.cc b/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.cc
index bc3a8a1da42..e024453dfc3 100644
--- a/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.cc
@@ -49,34 +49,37 @@ bool SetFragmentContentsCullRect(PaintLayer& layer,
} // anonymous namespace
-CullRectUpdater::CullRectUpdater(PaintLayer& root_layer)
- : root_layer_(root_layer),
- root_state_(root_layer.GetLayoutObject()
- .FirstFragment()
- .LocalBorderBoxProperties()
- .Unalias()) {
- DCHECK(root_layer.IsRootLayer());
+void CullRectUpdater::Update() {
+ DCHECK(starting_layer_.IsRootLayer());
+ UpdateInternal(CullRect::Infinite());
+#if DCHECK_IS_ON()
+ if (VLOG_IS_ON(2)) {
+ VLOG(2) << "PaintLayer tree after cull rect update:";
+ showLayerTree(&starting_layer_);
+ }
+#endif
}
void CullRectUpdater::UpdateInternal(const CullRect& input_cull_rect) {
DCHECK(RuntimeEnabledFeatures::CullRectUpdateEnabled());
- DCHECK(root_layer_.IsRootLayer());
- if (root_layer_.GetLayoutObject().GetFrameView()->ShouldThrottleRendering())
+ const auto& object = starting_layer_.GetLayoutObject();
+ if (object.GetFrameView()->ShouldThrottleRendering())
return;
+ root_state_ =
+ object.View()->FirstFragment().LocalBorderBoxProperties().Unalias();
bool should_use_infinite =
- PaintLayerPainter(root_layer_).ShouldUseInfiniteCullRect();
- auto& fragment =
- root_layer_.GetLayoutObject().GetMutableForPainting().FirstFragment();
+ PaintLayerPainter(starting_layer_).ShouldUseInfiniteCullRect();
+ auto& fragment = object.GetMutableForPainting().FirstFragment();
SetFragmentCullRect(
- root_layer_, fragment,
+ starting_layer_, fragment,
should_use_infinite ? CullRect::Infinite() : input_cull_rect);
bool force_update_children = SetFragmentContentsCullRect(
- root_layer_, fragment,
+ starting_layer_, fragment,
should_use_infinite ? CullRect::Infinite()
: ComputeFragmentContentsCullRect(
- root_layer_, fragment, input_cull_rect));
- UpdateForDescendants(root_layer_, force_update_children);
+ starting_layer_, fragment, input_cull_rect));
+ UpdateForDescendants(starting_layer_, force_update_children);
}
void CullRectUpdater::UpdateRecursively(PaintLayer& layer,
@@ -89,13 +92,27 @@ void CullRectUpdater::UpdateRecursively(PaintLayer& layer,
// This defines the scope of force_proactive_update_ (which may be set by
// ComputeFragmentCullRect() and ComputeFragmentContentsCullRect()) to the
// subtree.
- base::AutoReset<bool> reset(&force_proactive_update_,
- force_proactive_update_);
+ base::AutoReset<bool> reset_force_update(&force_proactive_update_,
+ force_proactive_update_);
if (force_update_self || should_proactively_update ||
layer.NeedsCullRectUpdate())
force_update_children |= UpdateForSelf(layer, parent_painting_layer);
+ absl::optional<base::AutoReset<bool>> reset_subtree_is_out_of_cull_rect;
+ if (!subtree_is_out_of_cull_rect_ && layer.KnownToClipSubtree() &&
+ !layer.GetLayoutObject().FirstFragment().NextFragment()) {
+ const auto* box = layer.GetLayoutBox();
+ DCHECK(box);
+ PhysicalRect overflow_rect = box->PhysicalSelfVisualOverflowRect();
+ overflow_rect.Move(box->FirstFragment().PaintOffset());
+ if (!box->FirstFragment().GetCullRect().Intersects(
+ EnclosingIntRect(overflow_rect))) {
+ reset_subtree_is_out_of_cull_rect.emplace(&subtree_is_out_of_cull_rect_,
+ true);
+ }
+ }
+
if (force_update_children || layer.DescendantNeedsCullRectUpdate())
UpdateForDescendants(layer, force_update_children);
@@ -134,9 +151,9 @@ void CullRectUpdater::UpdateForDescendants(PaintLayer& layer,
// <div id="stacked-child" style="position: relative"></div>
// </div>
// </div>
- // If |child|'s contents cull rect changes, we need to update |stack-child|'s
- // cull rect because it's clipped by |child|. The is done in the following
- // order:
+ // If |child|'s contents cull rect changes, we need to update
+ // |stacked-child|'s cull rect because it's clipped by |child|. The is done in
+ // the following order:
// UpdateForDescendants(|layer|)
// UpdateRecursively(|child|) (in the following loop)
// |stacked-child|->SetNeedsCullRectUpdate()
@@ -171,46 +188,55 @@ bool CullRectUpdater::UpdateForSelf(PaintLayer& layer,
parent_painting_layer.GetLayoutObject().FirstFragment();
auto& first_fragment =
layer.GetLayoutObject().GetMutableForPainting().FirstFragment();
- // If both |this| and |root_layer| are fragmented and are inside the same
- // pagination container, then try to match fragments from |root_layer| to
- // |this|, so that any fragment clip for |root_layer|'s fragment matches
- // |this|'s. Note we check both ShouldFragmentCompositedBounds() and next
- // fragment here because the former may return false even if |this| is
- // fragmented, e.g. for fixed-position objects in paged media, and the next
- // fragment can be null even if the first fragment is actually in a fragmented
- // context when the current layer appears in only one of the multiple
- // fragments of the pagination container.
+ // If both |layer| and |parent_painting_layer| are fragmented and are inside
+ // the same pagination container, then try to match fragments from
+ // |parent_painting_layer| to |layer|, so that any fragment clip for
+ // |parent_painting_layer|'s fragment matches |layer|'s. Note we check both
+ // ShouldFragmentCompositedBounds() and next fragment here because the former
+ // may return false even if |layer| is fragmented, e.g. for fixed-position
+ // objects in paged media, and the next fragment can be null even if the first
+ // fragment is actually in a fragmented context when the current layer appears
+ // in only one of the multiple fragments of the pagination container.
bool is_fragmented =
layer.ShouldFragmentCompositedBounds() || first_fragment.NextFragment();
bool should_match_fragments =
is_fragmented && parent_painting_layer.EnclosingPaginationLayer() ==
layer.EnclosingPaginationLayer();
bool force_update_children = false;
+ bool should_use_infinite_cull_rect =
+ !subtree_is_out_of_cull_rect_ &&
+ PaintLayerPainter(layer).ShouldUseInfiniteCullRect();
for (auto* fragment = &first_fragment; fragment;
fragment = fragment->NextFragment()) {
- const FragmentData* parent_fragment = nullptr;
- if (should_match_fragments) {
- for (parent_fragment = &first_parent_fragment; parent_fragment;
- parent_fragment = parent_fragment->NextFragment()) {
- if (parent_fragment->LogicalTopInFlowThread() ==
- fragment->LogicalTopInFlowThread())
- break;
- }
- } else {
- parent_fragment = &first_parent_fragment;
- }
-
CullRect cull_rect;
CullRect contents_cull_rect;
- if (!parent_fragment ||
- PaintLayerPainter(layer).ShouldUseInfiniteCullRect()) {
- cull_rect = CullRect::Infinite();
- contents_cull_rect = CullRect::Infinite();
+ if (subtree_is_out_of_cull_rect_) {
+ // PaintLayerPainter may skip the subtree including this layer, so we
+ // need to SetPreviousPaintResult() here.
+ layer.SetPreviousPaintResult(kMayBeClippedByCullRect);
} else {
- cull_rect = ComputeFragmentCullRect(layer, *fragment, *parent_fragment);
- contents_cull_rect =
- ComputeFragmentContentsCullRect(layer, *fragment, cull_rect);
+ const FragmentData* parent_fragment = nullptr;
+ if (!should_use_infinite_cull_rect) {
+ if (should_match_fragments) {
+ for (parent_fragment = &first_parent_fragment; parent_fragment;
+ parent_fragment = parent_fragment->NextFragment()) {
+ if (parent_fragment->FragmentID() == fragment->FragmentID())
+ break;
+ }
+ } else {
+ parent_fragment = &first_parent_fragment;
+ }
+ }
+
+ if (should_use_infinite_cull_rect || !parent_fragment) {
+ cull_rect = CullRect::Infinite();
+ contents_cull_rect = CullRect::Infinite();
+ } else {
+ cull_rect = ComputeFragmentCullRect(layer, *fragment, *parent_fragment);
+ contents_cull_rect =
+ ComputeFragmentContentsCullRect(layer, *fragment, cull_rect);
+ }
}
SetFragmentCullRect(layer, *fragment, cull_rect);
@@ -276,32 +302,29 @@ bool CullRectUpdater::ShouldProactivelyUpdate(const PaintLayer& layer) const {
return layer.SelfOrDescendantNeedsRepaint();
}
-OverriddenCullRectScope::OverriddenCullRectScope(LocalFrameView& frame_view,
+OverriddenCullRectScope::OverriddenCullRectScope(PaintLayer& starting_layer,
const CullRect& cull_rect)
- : frame_view_(frame_view) {
+ : starting_layer_(starting_layer) {
if (!RuntimeEnabledFeatures::CullRectUpdateEnabled())
return;
- PaintLayer* root_layer = frame_view_.GetLayoutView()->Layer();
- DCHECK(root_layer);
-
- if (frame_view.GetFrame().IsLocalRoot() &&
- !root_layer->NeedsCullRectUpdate() &&
- !root_layer->DescendantNeedsCullRectUpdate() &&
+ if (starting_layer.GetLayoutObject().GetFrame()->IsLocalRoot() &&
+ !starting_layer.NeedsCullRectUpdate() &&
+ !starting_layer.DescendantNeedsCullRectUpdate() &&
cull_rect ==
- root_layer->GetLayoutObject().FirstFragment().GetCullRect()) {
- // The cull rects calculated during PrePaint are good.
+ starting_layer.GetLayoutObject().FirstFragment().GetCullRect()) {
+ // The current cull rects are good.
return;
}
updated_ = true;
- root_layer->SetNeedsCullRectUpdate();
- CullRectUpdater(*root_layer).UpdateInternal(cull_rect);
+ starting_layer.SetNeedsCullRectUpdate();
+ CullRectUpdater(starting_layer).UpdateInternal(cull_rect);
}
OverriddenCullRectScope::~OverriddenCullRectScope() {
if (RuntimeEnabledFeatures::CullRectUpdateEnabled() && updated_)
- frame_view_.GetLayoutView()->Layer()->SetNeedsCullRectUpdate();
+ starting_layer_.SetNeedsCullRectUpdate();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.h b/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.h
index 0e5d933f72a..87899064187 100644
--- a/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.h
+++ b/chromium/third_party/blink/renderer/core/paint/cull_rect_updater.h
@@ -14,7 +14,6 @@ namespace blink {
class FragmentData;
class PaintLayer;
-class LocalFrameView;
// This class is used for updating the cull rects of PaintLayer fragments (see:
// |FragmentData::cull_rect_| and |FragmentData::contents_cull_rect_|.
@@ -28,9 +27,10 @@ class CORE_EXPORT CullRectUpdater {
STACK_ALLOCATED();
public:
- explicit CullRectUpdater(PaintLayer& root_layer);
+ explicit CullRectUpdater(PaintLayer& starting_layer)
+ : starting_layer_(starting_layer) {}
- void Update() { UpdateInternal(CullRect::Infinite()); }
+ void Update();
private:
friend class OverriddenCullRectScope;
@@ -51,24 +51,27 @@ class CORE_EXPORT CullRectUpdater {
const CullRect& cull_rect);
bool ShouldProactivelyUpdate(const PaintLayer&) const;
- PaintLayer& root_layer_;
- PropertyTreeState root_state_;
+ PaintLayer& starting_layer_;
+ PropertyTreeState root_state_ = PropertyTreeState::Uninitialized();
bool force_proactive_update_ = false;
+ bool subtree_is_out_of_cull_rect_ = false;
};
// Used when painting with a custom top-level cull rect, e.g. when printing a
-// page. It temporarily overrides the cull rect on the PaintLayer of the
-// LocalFrameView and marks the PaintLayer as needing to recalculate the cull
-// rect when leaving this scope.
+// page. It temporarily overrides the cull rect on the PaintLayer (which must be
+// a stacking context) and marks the PaintLayer as needing to recalculate the
+// cull rect when leaving this scope.
+// TODO(crbug.com/1215251): Avoid repaint after the scope if the scope is used
+// to paint into a separate PaintController.
class OverriddenCullRectScope {
STACK_ALLOCATED();
public:
- OverriddenCullRectScope(LocalFrameView&, const CullRect&);
+ OverriddenCullRectScope(PaintLayer&, const CullRect&);
~OverriddenCullRectScope();
private:
- LocalFrameView& frame_view_;
+ PaintLayer& starting_layer_;
bool updated_ = false;
};
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
index 7c2ed4a4276..f7ff03b59c0 100644
--- a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/paint/document_marker_painter.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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/geometry/physical_rect.h"
@@ -56,7 +56,8 @@ sk_sp<PaintRecord> RecordMarker(Color blink_color) {
PaintRecorder recorder;
recorder.beginRecording(kMarkerWidth, kMarkerHeight);
- recorder.getRecordingCanvas()->drawPath(path.detach(), flags);
+ recorder.getRecordingCanvas()->cc::PaintCanvas::drawPath(path.detach(),
+ flags);
return recorder.finishRecordingAsPicture();
}
@@ -285,8 +286,7 @@ TextPaintStyle DocumentMarkerPainter::ComputeTextPaintStyleFrom(
if (marker.GetType() != DocumentMarker::kTextFragment) {
const Color platform_text_color =
LayoutTheme::GetTheme().PlatformTextSearchColor(
- marker.IsActiveMatch(), document.InForcedColorsMode(),
- style.UsedColorScheme());
+ marker.IsActiveMatch(), style.UsedColorScheme());
if (platform_text_color == text_color)
return {};
text_color = platform_text_color;
diff --git a/chromium/third_party/blink/renderer/core/paint/embedded_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/embedded_object_painter.cc
index bebbbd985ff..c88a78dd3f3 100644
--- a/chromium/third_party/blink/renderer/core/paint/embedded_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/embedded_object_painter.cc
@@ -25,10 +25,10 @@ static const float kReplacementTextRoundedRectOpacity = 0.20f;
static const float kReplacementTextRoundedRectRadius = 5;
static const float kReplacementTextTextOpacity = 0.55f;
-static Font ReplacementTextFont() {
+static Font ReplacementTextFont(const Document* document) {
FontDescription font_description;
LayoutTheme::GetTheme().SystemFont(CSSValueID::kWebkitSmallControl,
- font_description);
+ font_description, document);
font_description.SetWeight(BoldWeightValue());
font_description.SetComputedSize(font_description.SpecifiedSize());
Font font(font_description);
@@ -56,7 +56,7 @@ void EmbeddedObjectPainter::PaintReplaced(const PaintInfo& paint_info,
BoxDrawingRecorder recorder(context, layout_embedded_object_,
paint_info.phase, paint_offset);
- Font font = ReplacementTextFont();
+ Font font = ReplacementTextFont(&layout_embedded_object_.GetDocument());
const SimpleFontData* font_data = font.PrimaryFont();
DCHECK(font_data);
if (!font_data)
diff --git a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
index 858cddfe305..0298359969a 100644
--- a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -312,6 +312,16 @@ FilterEffect* FilterEffectBuilder::BuildFilterEffect(
convolve_matrix_operation->KernelMatrix());
break;
}
+ case FilterOperation::COMPONENT_TRANSFER: {
+ ComponentTransferFilterOperation* component_transfer_operation =
+ To<ComponentTransferFilterOperation>(filter_operation);
+ effect = MakeGarbageCollected<FEComponentTransfer>(
+ parent_filter, component_transfer_operation->RedFunc(),
+ component_transfer_operation->GreenFunc(),
+ component_transfer_operation->BlueFunc(),
+ component_transfer_operation->AlphaFunc());
+ break;
+ }
default:
break;
}
@@ -385,6 +395,7 @@ CompositorFilterOperations FilterEffectBuilder::BuildFilterOperations(
}
case FilterOperation::LUMINANCE_TO_ALPHA:
case FilterOperation::CONVOLVE_MATRIX:
+ case FilterOperation::COMPONENT_TRANSFER:
// These filter types only exist for Canvas filters.
NOTREACHED();
break;
diff --git a/chromium/third_party/blink/renderer/core/paint/find_paint_offset_needing_update.h b/chromium/third_party/blink/renderer/core/paint/find_paint_offset_needing_update.h
index 2b21d3fb3a2..e902fca391b 100644
--- a/chromium/third_party/blink/renderer/core/paint/find_paint_offset_needing_update.h
+++ b/chromium/third_party/blink/renderer/core/paint/find_paint_offset_needing_update.h
@@ -9,6 +9,7 @@
#if DCHECK_IS_ON()
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/paint/fragment_data.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
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 1737801c869..1f765b7abec 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
@@ -9,7 +9,6 @@
#if DCHECK_IS_ON()
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_property_tree_builder.h"
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 30e45501136..27c75f8989b 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
@@ -178,7 +178,6 @@ void FirstMeaningfulPaintDetector::ReportPresentationTime(
//
// TODO(crbug.com/738235): Consider not reporting any timestamp when failing
// for reasons other than kDidNotSwapSwapFails.
- paint_timing_->ReportSwapResultHistogram(result);
provisional_first_meaningful_paint_presentation_ = timestamp;
probe::PaintTiming(GetDocument(), "firstMeaningfulPaintCandidate",
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 e54f4b38b7b..641bc33c1f7 100644
--- a/chromium/third_party/blink/renderer/core/paint/fragment_data.h
+++ b/chromium/third_party/blink/renderer/core/paint/fragment_data.h
@@ -52,12 +52,32 @@ class CORE_EXPORT FragmentData {
}
void SetLayer(std::unique_ptr<PaintLayer>);
+ // A fragment ID unique within the LayoutObject. In NG block fragmentation,
+ // this is the fragmentainer index. In legacy block fragmentation, it's the
+ // flow thread block-offset.
+ wtf_size_t FragmentID() const {
+ return rare_data_ ? rare_data_->fragment_id : 0;
+ }
+ void SetFragmentID(wtf_size_t id) {
+ if (!rare_data_ && id == 0)
+ return;
+ EnsureRareData().fragment_id = id;
+ }
+
LayoutUnit LogicalTopInFlowThread() const {
- return rare_data_ ? rare_data_->logical_top_in_flow_thread : LayoutUnit();
+#if DCHECK_IS_ON()
+ DCHECK(!rare_data_ || rare_data_->has_set_flow_thread_offset_ ||
+ !rare_data_->fragment_id);
+#endif
+ return LayoutUnit::FromRawValue(static_cast<int>(FragmentID()));
}
+
void SetLogicalTopInFlowThread(LayoutUnit top) {
- if (rare_data_ || top)
- EnsureRareData().logical_top_in_flow_thread = top;
+ SetFragmentID(top.RawValue());
+#if DCHECK_IS_ON()
+ if (rare_data_)
+ rare_data_->has_set_flow_thread_offset_ = true;
+#endif
}
// The pagination offset is the additional factor to add in to map from flow
@@ -225,7 +245,7 @@ class CORE_EXPORT FragmentData {
// Fragment specific data.
PhysicalOffset legacy_pagination_offset;
- LayoutUnit logical_top_in_flow_thread;
+ wtf_size_t fragment_id = 0;
std::unique_ptr<ObjectPaintProperties> paint_properties;
std::unique_ptr<RefCountedPropertyTreeState> local_border_box_properties;
bool is_clip_path_cache_valid = false;
@@ -234,6 +254,15 @@ class CORE_EXPORT FragmentData {
CullRect cull_rect_;
CullRect contents_cull_rect_;
std::unique_ptr<FragmentData> next_fragment_;
+
+#if DCHECK_IS_ON()
+ // Legacy block fragmentation sets the flow thread offset for each
+ // FragmentData object, and this is used as its fragment_id, whereas NG
+ // block fragmentation uses the fragmentainer index instead. Here's a flag
+ // which can be used to assert that legacy code which expects flow thread
+ // offsets actually gets that.
+ bool has_set_flow_thread_offset_ = false;
+#endif
};
RareData& EnsureRareData();
diff --git a/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.cc b/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
index 6c6dbb81d23..f2c1b45dc7b 100644
--- a/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
+++ b/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
@@ -48,6 +48,9 @@ Color ForcedSystemForegroundColor(PseudoId pseudo_id,
case kPseudoIdSelection:
keyword = CSSValueID::kHighlighttext;
break;
+ case kPseudoIdHighlight:
+ keyword = CSSValueID::kHighlighttext;
+ break;
default:
NOTREACHED();
break;
@@ -66,6 +69,9 @@ Color ForcedSystemBackgroundColor(PseudoId pseudo_id,
case kPseudoIdSelection:
keyword = CSSValueID::kHighlight;
break;
+ case kPseudoIdHighlight:
+ keyword = CSSValueID::kHighlight;
+ break;
default:
NOTREACHED();
break;
@@ -89,8 +95,12 @@ Color HighlightThemeForegroundColor(const Document& document,
style.UsedColorScheme());
case kPseudoIdTargetText:
return LayoutTheme::GetTheme().PlatformTextSearchColor(
- false /* active match */, document.InForcedColorsMode(),
- style.UsedColorScheme());
+ false /* active match */, style.UsedColorScheme());
+ case kPseudoIdHighlight:
+ // TODO(ffiori): not assigning any visual effects to custom highlights by
+ // default as the spec doesn't define it. See
+ // https://github.com/w3c/csswg-drafts/issues/6375.
+ return style.VisitedDependentColor(color_property);
default:
NOTREACHED();
return Color();
@@ -112,16 +122,22 @@ Color HighlightThemeBackgroundColor(const Document& document,
return Color(shared_highlighting::kFragmentTextBackgroundColorARGB);
return LayoutTheme::GetTheme().PlatformTextSearchHighlightColor(
- false /* active match */, document.InForcedColorsMode(),
- style.UsedColorScheme());
+ false /* active match */, style.UsedColorScheme());
+ case kPseudoIdHighlight:
+ // TODO(ffiori): not assigning any visual effects to custom highlights by
+ // default as the spec doesn't define it. See
+ // https://github.com/w3c/csswg-drafts/issues/6375.
+ return style.VisitedDependentColor(GetCSSPropertyBackgroundColor());
default:
NOTREACHED();
return Color();
}
}
-scoped_refptr<const ComputedStyle> HighlightPseudoStyle(Node* node,
- PseudoId pseudo) {
+scoped_refptr<const ComputedStyle> HighlightPseudoStyle(
+ Node* node,
+ PseudoId pseudo,
+ const AtomicString& pseudo_argument) {
if (!node)
return nullptr;
@@ -155,10 +171,10 @@ scoped_refptr<const ComputedStyle> HighlightPseudoStyle(Node* node,
// cache the styles for ::selection if there are no :window-inactive
// selector, or if the page is active.
return element->UncachedStyleForPseudoElement(
- StyleRequest(pseudo, element->GetComputedStyle()));
+ StyleRequest(pseudo, element->GetComputedStyle(), pseudo_argument));
}
- return element->CachedStyleForPseudoElement(pseudo);
+ return element->CachedStyleForPseudoElement(pseudo, pseudo_argument);
}
Color HighlightColor(const Document& document,
@@ -166,7 +182,8 @@ Color HighlightColor(const Document& document,
Node* node,
PseudoId pseudo,
const CSSProperty& color_property,
- const GlobalPaintFlags global_paint_flags) {
+ const GlobalPaintFlags global_paint_flags,
+ const AtomicString& pseudo_argument = g_null_atom) {
if (pseudo == kPseudoIdSelection) {
// If the element is unselectable, or we are only painting the selection,
// don't override the foreground color with the selection foreground color.
@@ -177,7 +194,7 @@ Color HighlightColor(const Document& document,
}
scoped_refptr<const ComputedStyle> pseudo_style =
- HighlightPseudoStyle(node, pseudo);
+ HighlightPseudoStyle(node, pseudo, pseudo_argument);
mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
if (pseudo_style) {
@@ -199,7 +216,8 @@ Color HighlightPaintingUtils::HighlightBackgroundColor(
const Document& document,
const ComputedStyle& style,
Node* node,
- PseudoId pseudo) {
+ PseudoId pseudo,
+ const AtomicString& pseudo_argument) {
if (pseudo == kPseudoIdSelection) {
if (node && !NodeIsSelectable(style, node))
return Color::kTransparent;
@@ -207,7 +225,7 @@ Color HighlightPaintingUtils::HighlightBackgroundColor(
mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
if (scoped_refptr<const ComputedStyle> pseudo_style =
- HighlightPseudoStyle(node, pseudo)) {
+ HighlightPseudoStyle(node, pseudo, pseudo_argument)) {
if (!document.InForcedColorsMode() ||
pseudo_style->ForcedColorAdjust() == EForcedColorAdjust::kNone) {
Color highlight_color =
@@ -259,10 +277,11 @@ Color HighlightPaintingUtils::HighlightForegroundColor(
const ComputedStyle& style,
Node* node,
PseudoId pseudo,
- const GlobalPaintFlags global_paint_flags) {
+ const GlobalPaintFlags global_paint_flags,
+ const AtomicString& pseudo_argument) {
return HighlightColor(document, style, node, pseudo,
- GetCSSPropertyWebkitTextFillColor(),
- global_paint_flags);
+ GetCSSPropertyWebkitTextFillColor(), global_paint_flags,
+ pseudo_argument);
}
Color HighlightPaintingUtils::HighlightEmphasisMarkColor(
@@ -282,7 +301,8 @@ TextPaintStyle HighlightPaintingUtils::HighlightPaintingStyle(
Node* node,
PseudoId pseudo,
const TextPaintStyle& text_style,
- const PaintInfo& paint_info) {
+ const PaintInfo& paint_info,
+ const AtomicString& pseudo_argument) {
TextPaintStyle highlight_style = text_style;
bool uses_text_as_clip = paint_info.phase == PaintPhase::kTextClip;
const GlobalPaintFlags global_paint_flags = paint_info.GetGlobalPaintFlags();
@@ -293,13 +313,13 @@ TextPaintStyle HighlightPaintingUtils::HighlightPaintingStyle(
if (!uses_text_as_clip) {
highlight_style.fill_color = HighlightForegroundColor(
- document, style, node, pseudo, global_paint_flags);
+ document, style, node, pseudo, global_paint_flags, pseudo_argument);
highlight_style.emphasis_mark_color = HighlightEmphasisMarkColor(
document, style, node, pseudo, global_paint_flags);
}
if (scoped_refptr<const ComputedStyle> pseudo_style =
- HighlightPseudoStyle(node, pseudo)) {
+ HighlightPseudoStyle(node, pseudo, pseudo_argument)) {
highlight_style.stroke_color =
uses_text_as_clip ? Color::kBlack
: pseudo_style->VisitedDependentColor(
diff --git a/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.h b/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.h
index c29608ddc58..f1dbe602376 100644
--- a/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.h
+++ b/chromium/third_party/blink/renderer/core/paint/highlight_painting_utils.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/paint/paint_phase.h"
#include "third_party/blink/renderer/core/style/applied_text_decoration.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -28,26 +29,32 @@ class CORE_EXPORT HighlightPaintingUtils {
static absl::optional<AppliedTextDecoration> HighlightTextDecoration(
const ComputedStyle& style,
const ComputedStyle& pseudo_style);
- static Color HighlightBackgroundColor(const Document&,
- const ComputedStyle&,
- Node*,
- PseudoId);
- static Color HighlightForegroundColor(const Document&,
- const ComputedStyle&,
- Node*,
- PseudoId,
- const GlobalPaintFlags);
+ static Color HighlightBackgroundColor(
+ const Document&,
+ const ComputedStyle&,
+ Node*,
+ PseudoId,
+ const AtomicString& pseudo_argument = g_null_atom);
+ static Color HighlightForegroundColor(
+ const Document&,
+ const ComputedStyle&,
+ Node*,
+ PseudoId,
+ const GlobalPaintFlags,
+ const AtomicString& pseudo_argument = g_null_atom);
static Color HighlightEmphasisMarkColor(const Document&,
const ComputedStyle&,
Node*,
PseudoId,
const GlobalPaintFlags);
- static TextPaintStyle HighlightPaintingStyle(const Document&,
- const ComputedStyle&,
- Node*,
- PseudoId,
- const TextPaintStyle& text_style,
- const PaintInfo&);
+ static TextPaintStyle HighlightPaintingStyle(
+ const Document&,
+ const ComputedStyle&,
+ Node*,
+ PseudoId,
+ const TextPaintStyle& text_style,
+ const PaintInfo&,
+ const AtomicString& pseudo_argument = g_null_atom);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
index ba995d59323..9b3ff951616 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -3,10 +3,13 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
+#include "base/feature_list.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/blink/public/common/features.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/visual_viewport.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"
@@ -66,7 +69,9 @@ static bool LargeImageFirst(const base::WeakPtr<ImageRecord>& a,
ImagePaintTimingDetector::ImagePaintTimingDetector(
LocalFrameView* frame_view,
PaintTimingCallbackManager* callback_manager)
- : records_manager_(frame_view),
+ : uses_page_viewport_(
+ base::FeatureList::IsEnabled(features::kUsePageViewportInLCP)),
+ records_manager_(frame_view),
frame_view_(frame_view),
callback_manager_(callback_manager) {}
@@ -314,8 +319,16 @@ uint64_t ImagePaintTimingDetector::ComputeImageRectSize(
frame_view_->GetPaintTimingDetector().BlinkSpaceToDIPs(
FloatRect(image_border));
if (!viewport_size_.has_value()) {
+ // If the flag to use page viewport is enabled, we use the page viewport
+ // (aka the main frame viewport) for all frames, including iframes. This
+ // prevents us from discarding images with size equal to the size of its
+ // embedding iframe.
+ IntRect viewport_int_rect =
+ uses_page_viewport_
+ ? frame_view_->GetPage()->GetVisualViewport().VisibleContentRect()
+ : frame_view_->GetScrollableArea()->VisibleContentRect();
FloatRect viewport = frame_view_->GetPaintTimingDetector().BlinkSpaceToDIPs(
- FloatRect(frame_view_->GetScrollableArea()->VisibleContentRect()));
+ FloatRect(viewport_int_rect));
viewport_size_ = viewport.Size().Area();
}
// An SVG image size is computed with respect to the virtual viewport of the
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
index 802c124f9c2..dd7fa784da3 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -344,6 +344,8 @@ class CORE_EXPORT ImagePaintTimingDetector final
// image. This value is reset when paint is finished and is computed if unset
// when needed. 0 means that the size has not been computed.
absl::optional<uint64_t> viewport_size_;
+ // Whether the viewport size used is the page viewport.
+ bool uses_page_viewport_;
ImageRecordsManager records_manager_;
Member<LocalFrameView> frame_view_;
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
index d7f5982f4e3..b5429832e59 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -385,10 +385,10 @@ TEST_P(ImagePaintTimingDetectorTest, LargestImagePaint_TraceEvent_Candidate) {
EXPECT_TRUE(events[0]->HasArg("frame"));
EXPECT_TRUE(events[0]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId node_id;
EXPECT_TRUE(arg_dict->GetInteger("DOMNodeId", &node_id));
EXPECT_GT(node_id, 0);
@@ -455,10 +455,10 @@ TEST_P(ImagePaintTimingDetectorTest,
EXPECT_TRUE(events[0]->HasArg("frame"));
EXPECT_TRUE(events[0]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId node_id;
EXPECT_TRUE(arg_dict->GetInteger("DOMNodeId", &node_id));
EXPECT_GT(node_id, 0);
@@ -521,10 +521,10 @@ TEST_P(ImagePaintTimingDetectorTest, LargestImagePaint_TraceEvent_NoCandidate) {
EXPECT_EQ("loading", events[0]->category);
EXPECT_TRUE(events[0]->HasArg("frame"));
EXPECT_TRUE(events[0]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId candidate_index;
EXPECT_TRUE(arg_dict->GetInteger("candidateIndex", &candidate_index));
EXPECT_EQ(candidate_index, 1);
@@ -539,10 +539,10 @@ TEST_P(ImagePaintTimingDetectorTest, LargestImagePaint_TraceEvent_NoCandidate) {
// Use block to reuse the temp variable names.
{
EXPECT_TRUE(events[1]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[1]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId candidate_index;
EXPECT_TRUE(arg_dict->GetInteger("candidateIndex", &candidate_index));
EXPECT_EQ(candidate_index, 3);
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 367f07a6919..674a6801271 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_area_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_replaced.h"
@@ -21,6 +22,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
+#include "third_party/blink/renderer/core/paint/outline_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
@@ -127,11 +129,8 @@ void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info) {
PhysicalRect focus_rect = layout_image_.PhysicalContentBoxRect();
focus_rect.Move(paint_offset);
paint_info.context.Clip(PixelSnappedIntRect(focus_rect));
- paint_info.context.DrawFocusRing(
- path, area_element_style->GetOutlineStrokeWidthForFocusRing(),
- area_element_style->OutlineOffsetInt(),
- layout_image_.ResolveColor(*area_element_style,
- GetCSSPropertyOutlineColor()));
+ OutlinePainter::PaintFocusRingPath(paint_info.context, path,
+ *area_element_style);
paint_info.context.Restore();
}
@@ -254,7 +253,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
// Does not set an observer for the placeholder image, setting it to null.
scoped_refptr<PlaceholderImage> placeholder_image =
PlaceholderImage::Create(nullptr, image->Size(),
- image->Data() ? image->Data()->size() : 0);
+ image->HasData() ? image->DataSize() : 0);
placeholder_image->SetIconAndTextScaleFactor(
layout_image_.GetFrame()->PageZoomFactor());
image = std::move(placeholder_image);
@@ -263,7 +262,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
context.DrawImage(image.get(), decode_mode,
FloatRect(pixel_snapped_dest_rect), &src_rect,
- layout_image_.StyleRef().HasFilterInducingProperty(),
+ layout_image_.StyleRef().DisableForceDark(),
SkBlendMode::kSrcOver, respect_orientation);
if (ImageResourceContent* image_content = image_resource.CachedImage()) {
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 4eac70704b3..c86a356c39c 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
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_shader.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
namespace blink {
@@ -172,7 +173,12 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
inline_text_box_.LogicalHeight()));
absl::optional<SelectionBoundsRecorder> selection_recorder;
- if (have_selection && paint_info.phase == PaintPhase::kForeground &&
+ // Empty selections might be the boundary of the document selection, and thus
+ // need to get recorded.
+ const bool should_record_selection =
+ have_selection ||
+ inline_text_box_.GetLineLayoutItem().GetLayoutObject()->IsSelected();
+ if (should_record_selection && paint_info.phase == PaintPhase::kForeground &&
!is_printing) {
const FrameSelection& frame_selection =
InlineLayoutObject().GetFrame()->Selection();
@@ -183,7 +189,8 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
selection_state)) {
PhysicalRect selection_rect =
GetSelectionRect<InlineTextBoxPainter::PaintOptions::kNormal>(
- context, box_rect, style_to_use, style_to_use.GetFont());
+ context, box_rect, style_to_use, style_to_use.GetFont(), nullptr,
+ /* allow_empty_selection*/ true);
TextDirection direction = inline_text_box_.IsLeftToRightDirection()
? TextDirection::kLtr
@@ -413,10 +420,9 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
? absl::optional<AppliedTextDecoration>(
selection_style.selection_text_decoration)
: absl::nullopt;
- decoration_info.emplace(box_origin, local_origin, width,
- inline_text_box_.Root().BaselineType(),
- style_to_use, selection_text_decoration,
- decorating_box_style);
+ decoration_info.emplace(
+ local_origin, width, inline_text_box_.Root().BaselineType(),
+ style_to_use, selection_text_decoration, decorating_box_style);
TextDecorationOffset decoration_offset(decoration_info->Style(),
&inline_text_box_, decorating_box);
text_painter.PaintDecorationsExceptLineThrough(
@@ -661,6 +667,10 @@ void InlineTextBoxPainter::PaintDocumentMarkers(
styleable_marker, style, font);
}
} break;
+ case DocumentMarker::kHighlight:
+ inline_text_box_.PaintDocumentMarker(paint_info, box_origin, marker,
+ style, font, false);
+ break;
default:
// Marker is not painted, or painting code has not been added yet
break;
@@ -728,11 +738,14 @@ PhysicalRect InlineTextBoxPainter::GetSelectionRect(
const PhysicalRect& box_rect,
const ComputedStyle& style,
const Font& font,
- LayoutTextCombine* combined_text) {
+ LayoutTextCombine* combined_text,
+ bool allow_empty_selection) {
// See if we have a selection to paint at all.
int start_pos, end_pos;
inline_text_box_.SelectionStartEnd(start_pos, end_pos);
- if (start_pos >= end_pos)
+ if (start_pos > end_pos)
+ return PhysicalRect();
+ if (!allow_empty_selection && start_pos == end_pos)
return PhysicalRect();
// If the text is truncated, let the thing being painted in the truncation
@@ -833,8 +846,11 @@ PhysicalRect InlineTextBoxPainter::PaintSelection(
// If the text color ends up being the same as the selection background,
// invert the selection background.
- if (text_color == c)
+ if (text_color == c) {
+ UseCounter::Count(layout_item.GetDocument(),
+ WebFeature::kSelectionBackgroundColorInversion);
c = Color(0xff - c.Red(), 0xff - c.Green(), 0xff - c.Blue());
+ }
GraphicsContextStateSaver state_saver(context);
@@ -935,9 +951,7 @@ void InlineTextBoxPainter::PaintTextMarkerBackground(
TextRun run = inline_text_box_.ConstructTextRun(style);
Color color = LayoutTheme::GetTheme().PlatformTextSearchHighlightColor(
- marker.IsActiveMatch(),
- inline_text_box_.GetLineLayoutItem().GetDocument().InForcedColorsMode(),
- style.UsedColorScheme());
+ marker.IsActiveMatch(), style.UsedColorScheme());
GraphicsContext& context = paint_info.context;
GraphicsContextStateSaver state_saver(context);
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 42c30224e34..a9bb0b494bb 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
@@ -91,7 +91,8 @@ class InlineTextBoxPainter {
const PhysicalRect& box_rect,
const ComputedStyle&,
const Font&,
- LayoutTextCombine* = nullptr);
+ LayoutTextCombine* = nullptr,
+ bool allow_empty_selection = false);
void PaintStyleableMarkerUnderline(GraphicsContext&,
const PhysicalOffset& box_origin,
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc
index 1b505e57d1e..52c697610dd 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc
@@ -7,6 +7,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/editing/testing/selection_sample.h"
+#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
using testing::ElementsAre;
@@ -28,64 +29,4 @@ TEST_P(InlineTextBoxPainterTest, LineBreak) {
EXPECT_EQ(6u, ContentDisplayItems().size());
}
-class InlineTextBoxPainterNonNGTest : public PaintControllerPaintTest,
- public ScopedLayoutNGForTest {
- public:
- InlineTextBoxPainterNonNGTest() : ScopedLayoutNGForTest(false) {}
-};
-
-INSTANTIATE_PAINT_TEST_SUITE_P(InlineTextBoxPainterNonNGTest);
-
-TEST_P(InlineTextBoxPainterNonNGTest, RecordedSelectionAll) {
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
- SetBodyInnerHTML("<span>A<br>B<br>C</span>");
-
- GetDocument().GetFrame()->Selection().SetHandleVisibleForTesting();
- GetDocument().GetFrame()->Selection().SelectAll();
- UpdateAllLifecyclePhasesForTest();
-
- auto chunks = ContentPaintChunks();
- EXPECT_EQ(chunks.size(), 1u);
- EXPECT_TRUE(chunks.begin()->layer_selection_data->start.has_value());
- EXPECT_TRUE(chunks.begin()->layer_selection_data->end.has_value());
- PaintedSelectionBound start =
- chunks.begin()->layer_selection_data->start.value();
- EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
- EXPECT_EQ(start.edge_start, IntPoint(8, 8));
- EXPECT_EQ(start.edge_end, IntPoint(8, 9));
-
- PaintedSelectionBound end = chunks.begin()->layer_selection_data->end.value();
- EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
- EXPECT_EQ(end.edge_start, IntPoint(9, 10));
- EXPECT_EQ(end.edge_end, IntPoint(9, 11));
-}
-
-TEST_P(InlineTextBoxPainterNonNGTest, RecordedSelectionMultiline) {
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
- GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
- SelectionSample::SetSelectionText(
- GetDocument().body(),
- "<div style='white-space:pre'>f^oo\nbar\nb|az</div>"));
- GetDocument().GetFrame()->Selection().SetHandleVisibleForTesting();
- UpdateAllLifecyclePhasesForTest();
-
- auto chunks = ContentPaintChunks();
- EXPECT_EQ(chunks.size(), 1u);
- EXPECT_TRUE(chunks.begin()->layer_selection_data->start.has_value());
- EXPECT_TRUE(chunks.begin()->layer_selection_data->end.has_value());
- PaintedSelectionBound start =
- chunks.begin()->layer_selection_data->start.value();
- EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
- EXPECT_EQ(start.edge_start, IntPoint(8, 8));
- EXPECT_EQ(start.edge_end, IntPoint(8, 9));
-
- PaintedSelectionBound end = chunks.begin()->layer_selection_data->end.value();
- EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
- EXPECT_EQ(end.edge_start, IntPoint(9, 10));
- EXPECT_EQ(end.edge_end, IntPoint(9, 11));
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc b/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc
index 6841df62c20..355247b1ebe 100644
--- a/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/line_box_list_painter.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_box_model.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
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 7a381c48e5e..9b50fd32cfe 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
@@ -32,6 +32,7 @@
#include "base/memory/ptr_util.h"
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
+#include "skia/ext/skia_matrix_44.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
@@ -62,7 +63,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_f.h"
@@ -217,7 +217,9 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() {
timing_function));
auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, compositor_target_property::OPACITY, 0, 0);
+ *curve, 0, 0,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::OPACITY));
compositor_animation_->AddKeyframeModel(std::move(keyframe_model));
}
@@ -244,7 +246,7 @@ void LinkHighlightImpl::UpdateAfterPrePaint() {
return;
DCHECK(!object->GetFrameView()->ShouldThrottleRendering());
- size_t fragment_count = 0;
+ wtf_size_t fragment_count = 0;
for (const auto* fragment = &object->FirstFragment(); fragment;
fragment = fragment->NextFragment())
++fragment_count;
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 3f9b2dae2a1..34cd91faed8 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
@@ -79,7 +79,7 @@ class CORE_EXPORT LinkHighlightImpl final : public CompositorAnimationDelegate,
void Paint(GraphicsContext&);
wtf_size_t FragmentCountForTesting() const { return fragments_.size(); }
- cc::PictureLayer* LayerForTesting(size_t index) const {
+ cc::PictureLayer* LayerForTesting(wtf_size_t index) const {
return fragments_[index].Layer();
}
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 0ead31d5967..f8695af86b6 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
@@ -8,7 +8,6 @@
#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/list_marker.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/highlight_painting_utils.h"
@@ -86,8 +85,8 @@ void ListMarkerPainter::PaintSymbol(const PaintInfo& paint_info,
const ComputedStyle& style,
const LayoutRect& marker) {
DCHECK(object);
- DCHECK(style.GetListStyleType());
- DCHECK(style.GetListStyleType()->IsCounterStyle());
+ DCHECK(style.ListStyleType());
+ DCHECK(style.ListStyleType()->IsCounterStyle());
GraphicsContext& context = paint_info.context;
ScopedDarkModeElementRoleOverride list_symbol(
&context, DarkModeFilter::ElementRole::kListSymbol);
@@ -101,7 +100,7 @@ void ListMarkerPainter::PaintSymbol(const PaintInfo& paint_info,
context.SetStrokeStyle(kSolidStroke);
context.SetStrokeThickness(1.0f);
IntRect snapped_rect = PixelSnappedIntRect(marker);
- const AtomicString& type = style.GetListStyleType()->GetCounterStyleName();
+ const AtomicString& type = style.ListStyleType()->GetCounterStyleName();
if (type == "disc") {
context.FillEllipse(FloatRect(snapped_rect));
} else if (type == "circle") {
@@ -232,17 +231,9 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info) {
String prefix_str;
String suffix_str;
- if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) {
- const CounterStyle& counter_style = layout_list_marker_.GetCounterStyle();
- prefix_str = counter_style.GetPrefix();
- suffix_str = counter_style.GetSuffix();
- } else {
- UChar chars[] = {
- list_marker_text::Suffix(layout_list_marker_.StyleRef().ListStyleType(),
- layout_list_marker_.ListItem()->Value()),
- ' '};
- suffix_str = String(chars, 2);
- }
+ const CounterStyle& counter_style = layout_list_marker_.GetCounterStyle();
+ prefix_str = counter_style.GetPrefix();
+ suffix_str = counter_style.GetSuffix();
TextRun prefix_run =
ConstructTextRun(font, prefix_str, layout_list_marker_.StyleRef(),
layout_list_marker_.StyleRef().Direction());
diff --git a/chromium/third_party/blink/renderer/core/paint/multi_column_set_painter.cc b/chromium/third_party/blink/renderer/core/paint/multi_column_set_painter.cc
index cfc9b9d21c7..043e55ae4c2 100644
--- a/chromium/third_party/blink/renderer/core/paint/multi_column_set_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/multi_column_set_painter.cc
@@ -6,7 +6,7 @@
#include "third_party/blink/renderer/core/layout/layout_multi_column_set.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/box_border_painter.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/drawing_recorder.h"
@@ -64,8 +64,8 @@ void MultiColumnSetPainter::PaintColumnRules(
for (auto& bound : column_rule_bounds) {
IntRect pixel_snapped_rule_rect = PixelSnappedIntRect(bound);
- ObjectPainter::DrawBoxSide(paint_info.context, pixel_snapped_rule_rect,
- box_side, rule_color, rule_style);
+ BoxBorderPainter::DrawBoxSide(paint_info.context, pixel_snapped_rule_rect,
+ box_side, rule_color, rule_style);
}
}
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 360f0a19e45..1642dea2ade 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
#include "base/containers/adapters.h"
+#include "third_party/blink/renderer/core/css/style_engine.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/frame/local_frame.h"
@@ -14,6 +15,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
@@ -21,8 +23,10 @@
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/pointer_events_hit_rules.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
+#include "third_party/blink/renderer/core/paint/box_border_painter.h"
#include "third_party/blink/renderer/core/paint/box_decoration_data.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
@@ -31,6 +35,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_mathml_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_table_painters.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
@@ -40,6 +45,7 @@
#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/core/paint/rounded_border_geometry.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
+#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/paint/theme_painter.h"
#include "third_party/blink/renderer/core/paint/url_metadata_utils.h"
@@ -111,7 +117,21 @@ inline bool IsVisibleToHitTest(const ComputedStyle& style,
inline bool IsVisibleToHitTest(const NGFragmentItem& item,
const HitTestRequest& request) {
const ComputedStyle& style = item.Style();
- return IsVisibleToPaint(item, style) && IsVisibleToHitTest(style, request);
+ if (item.Type() != NGFragmentItem::kSvgText)
+ return IsVisibleToPaint(item, style) && IsVisibleToHitTest(style, request);
+
+ if (item.IsHiddenForPaint())
+ return false;
+ PointerEventsHitRules hit_rules(PointerEventsHitRules::SVG_TEXT_HITTESTING,
+ request, style.PointerEvents());
+ if (hit_rules.require_visible && style.Visibility() != EVisibility::kVisible)
+ return false;
+ if (hit_rules.can_hit_bounding_box ||
+ (hit_rules.can_hit_stroke &&
+ (style.HasStroke() || !hit_rules.require_stroke)) ||
+ (hit_rules.can_hit_fill && (style.HasFill() || !hit_rules.require_fill)))
+ return IsVisibleToHitTest(style, request);
+ return false;
}
inline bool IsVisibleToHitTest(const NGPhysicalFragment& fragment,
@@ -348,13 +368,13 @@ bool ShouldPaintCarets(const NGPhysicalBoxFragment& fragment) {
} // anonymous namespace
-PhysicalRect NGBoxFragmentPainter::SelfInkOverflow() const {
+PhysicalRect NGBoxFragmentPainter::InkOverflowIncludingFilters() const {
if (box_item_)
return box_item_->SelfInkOverflow();
const NGPhysicalFragment& fragment = PhysicalFragment();
DCHECK(!fragment.IsInlineBox());
return To<LayoutBox>(fragment.GetLayoutObject())
- ->PhysicalSelfVisualOverflowRect();
+ ->PhysicalVisualOverflowRectIncludingFilters();
}
void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
@@ -375,8 +395,32 @@ void NGBoxFragmentPainter::PaintInternal(const PaintInfo& paint_info) {
return;
PaintInfo& info = paint_state.MutablePaintInfo();
- PhysicalOffset paint_offset = paint_state.PaintOffset();
- PaintPhase original_phase = info.phase;
+ const PhysicalOffset paint_offset = paint_state.PaintOffset();
+ const PaintPhase original_phase = info.phase;
+
+ // For text-combine-upright:all, we need to realize canvas here for scaling
+ // to fit text content in 1em and shear for "font-style: oblique -15deg".
+ absl::optional<DrawingRecorder> recorder;
+ absl::optional<GraphicsContextStateSaver> graphics_context_state_saver;
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(box_fragment_.GetLayoutObject());
+ if (UNLIKELY(text_combine)) {
+ if (text_combine->NeedsAffineTransformInPaint()) {
+ if (original_phase == PaintPhase::kForeground)
+ PaintCaretsIfNeeded(paint_state, paint_info, paint_offset);
+ if (!paint_info.context.InDrawingRecorder()) {
+ if (DrawingRecorder::UseCachedDrawingIfPossible(
+ paint_info.context, GetDisplayItemClient(), paint_info.phase))
+ return;
+ recorder.emplace(paint_info.context, GetDisplayItemClient(),
+ paint_info.phase,
+ text_combine->VisualRectForPaint(paint_offset));
+ }
+ graphics_context_state_saver.emplace(paint_info.context);
+ paint_info.context.ConcatCTM(
+ text_combine->ComputeAffineTransformForPaint(paint_offset));
+ }
+ }
ScopedPaintTimingDetectorBlockPaintHook
scoped_paint_timing_detector_block_paint_hook;
@@ -436,22 +480,9 @@ void NGBoxFragmentPainter::PaintInternal(const PaintInfo& paint_info) {
// If the caret's node's fragment's containing block is this block, and
// the paint action is PaintPhaseForeground, then paint the caret.
- if (original_phase == PaintPhase::kForeground &&
- ShouldPaintCarets(box_fragment_)) {
- // Apply overflow clip if needed.
- // reveal-caret-of-multiline-contenteditable.html needs this.
- // TDOO(yoisn): We should share this code with |BlockPainter::Paint()|
- absl::optional<ScopedPaintChunkProperties> paint_chunk_properties;
- if (const auto* fragment = paint_state.FragmentToPaint()) {
- if (const auto* properties = fragment->PaintProperties()) {
- if (const auto* overflow_clip = properties->OverflowClip()) {
- paint_chunk_properties.emplace(
- paint_info.context.GetPaintController(), *overflow_clip,
- *box_fragment_.GetLayoutObject(), DisplayItem::kCaret);
- }
- }
- }
- PaintCarets(paint_info, paint_offset);
+ if (original_phase == PaintPhase::kForeground && LIKELY(!recorder)) {
+ DCHECK(!text_combine || !text_combine->NeedsAffineTransformInPaint());
+ PaintCaretsIfNeeded(paint_state, paint_info, paint_offset);
}
if (ShouldPaintSelfOutline(original_phase)) {
@@ -459,10 +490,28 @@ void NGBoxFragmentPainter::PaintInternal(const PaintInfo& paint_info) {
PaintObject(info, paint_offset);
}
+ if (UNLIKELY(text_combine) &&
+ NGTextCombinePainter::ShouldPaint(*text_combine)) {
+ if (recorder) {
+ // Paint text decorations and emphasis marks without scaling and share.
+ DCHECK(text_combine->NeedsAffineTransformInPaint());
+ graphics_context_state_saver->Restore();
+ } else if (!paint_info.context.InDrawingRecorder()) {
+ if (DrawingRecorder::UseCachedDrawingIfPossible(
+ paint_info.context, GetDisplayItemClient(), paint_info.phase))
+ return;
+ recorder.emplace(paint_info.context, GetDisplayItemClient(),
+ paint_info.phase,
+ text_combine->VisualRectForPaint(paint_offset));
+ }
+ NGTextCombinePainter::Paint(info, paint_offset, *text_combine);
+ }
+
// We paint scrollbars after we painted other things, so that the scrollbars
// will sit above them.
info.phase = original_phase;
if (box_fragment_.IsScrollContainer()) {
+ DCHECK(!text_combine);
ScrollableAreaPainter(*PhysicalFragment().Layer()->GetScrollableArea())
.PaintOverflowControls(info, RoundedIntPoint(paint_offset));
}
@@ -503,7 +552,7 @@ void NGBoxFragmentPainter::PaintObject(
const PaintPhase paint_phase = paint_info.phase;
const NGPhysicalBoxFragment& fragment = PhysicalFragment();
const ComputedStyle& style = fragment.Style();
- bool is_visible = IsVisibleToPaint(fragment, style);
+ const bool is_visible = IsVisibleToPaint(fragment, style);
if (ShouldPaintSelfBlockBackground(paint_phase)) {
if (is_visible) {
PaintBoxDecorationBackground(paint_info, paint_offset,
@@ -561,13 +610,6 @@ void NGBoxFragmentPainter::PaintObject(
}
} else if (!fragment.IsInlineFormattingContext()) {
PaintBlockChildren(paint_info, paint_offset);
-
- if (is_visible && paint_info.phase == PaintPhase::kForeground &&
- box_fragment_.IsTableNG()) {
- NGTablePainter(box_fragment_)
- .PaintCollapsedBorders(paint_info, paint_offset,
- VisualRect(paint_offset));
- }
}
}
@@ -581,6 +623,15 @@ void NGBoxFragmentPainter::PaintObject(
if (!is_visible)
return;
+
+ // Collapsed borders paint *after* children have painted their backgrounds.
+ if (box_fragment_.IsTableNG() &&
+ paint_phase == PaintPhase::kDescendantBlockBackgroundsOnly) {
+ NGTablePainter(box_fragment_)
+ .PaintCollapsedBorders(paint_info, paint_offset,
+ VisualRect(paint_offset));
+ }
+
if (ShouldPaintSelfOutline(paint_phase)) {
if (NGOutlineUtils::HasPaintedOutline(style, fragment.GetNode())) {
NGFragmentPainter(fragment, GetDisplayItemClient())
@@ -595,14 +646,32 @@ void NGBoxFragmentPainter::PaintObject(
}
}
-void NGBoxFragmentPainter::PaintCarets(const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- const NGPhysicalBoxFragment& fragment = PhysicalFragment();
- LocalFrame* frame = fragment.GetLayoutObject()->GetFrame();
- if (ShouldPaintCursorCaret(fragment))
+void NGBoxFragmentPainter::PaintCaretsIfNeeded(
+ const ScopedPaintState& paint_state,
+ const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
+ if (!ShouldPaintCarets(box_fragment_))
+ return;
+
+ // Apply overflow clip if needed.
+ // reveal-caret-of-multiline-contenteditable.html needs this.
+ // TDOO(yoisn): We should share this code with |BlockPainter::Paint()|
+ absl::optional<ScopedPaintChunkProperties> paint_chunk_properties;
+ if (const auto* fragment = paint_state.FragmentToPaint()) {
+ if (const auto* properties = fragment->PaintProperties()) {
+ if (const auto* overflow_clip = properties->OverflowClip()) {
+ paint_chunk_properties.emplace(
+ paint_info.context.GetPaintController(), *overflow_clip,
+ *box_fragment_.GetLayoutObject(), DisplayItem::kCaret);
+ }
+ }
+ }
+
+ LocalFrame* frame = box_fragment_.GetLayoutObject()->GetFrame();
+ if (ShouldPaintCursorCaret(box_fragment_))
frame->Selection().PaintCaret(paint_info.context, paint_offset);
- if (ShouldPaintDragCaret(fragment)) {
+ if (ShouldPaintDragCaret(box_fragment_)) {
frame->GetPage()->GetDragCaret().PaintDragCaret(frame, paint_info.context,
paint_offset);
}
@@ -652,6 +721,11 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
DCHECK(items_);
NGInlineCursor children(fragment, *items_);
+ if (fragment.IsSvgText()) {
+ ScopedSVGPaintState paint_state(*fragment.GetLayoutObject(), paint_info);
+ PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset);
+ return;
+ }
PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset);
}
@@ -659,63 +733,74 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
PhysicalOffset paint_offset) {
DCHECK(!box_fragment_.IsInlineFormattingContext());
PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
+ paint_info_for_descendants.SetIsInFragmentTraversal();
for (const NGLink& child : box_fragment_.Children()) {
const NGPhysicalFragment& child_fragment = *child;
DCHECK(child_fragment.IsBox());
if (child_fragment.HasSelfPaintingLayer() || child_fragment.IsFloating())
continue;
+ PaintBlockChild(child, paint_info, paint_info_for_descendants,
+ paint_offset);
+ }
+}
- const auto& box_child_fragment = To<NGPhysicalBoxFragment>(child_fragment);
- if (box_child_fragment.CanTraverse()) {
- if (!box_child_fragment.GetLayoutObject()) {
- // It's normally FragmentData that provides us with the paint offset.
- // FragmentData is (at least currently) associated with a LayoutObject.
- // If we have no LayoutObject, we have no FragmentData, so we need to
- // calculate the offset on our own (which is very simple, anyway).
- // Bypass Paint() and jump directly to PaintObject(), to skip the code
- // that assumes that we have a LayoutObject (and FragmentData).
- PhysicalOffset child_offset = paint_offset + child.offset;
-
- if (box_child_fragment.IsFragmentainerBox()) {
- // This is a fragmentainer, and when node inside a fragmentation
- // context paints multiple block fragments, we need to distinguish
- // between them somehow, for paint caching to work. Therefore,
- // establish a display item scope here.
- unsigned identifier =
- FragmentainerUniqueIdentifier(box_child_fragment);
- ScopedDisplayItemFragment scope(paint_info.context, identifier);
- NGBoxFragmentPainter(box_child_fragment)
- .PaintObject(paint_info, child_offset);
- continue;
- }
-
+void NGBoxFragmentPainter::PaintBlockChild(
+ const NGLink& child,
+ const PaintInfo& paint_info,
+ const PaintInfo& paint_info_for_descendants,
+ PhysicalOffset paint_offset) {
+ const NGPhysicalFragment& child_fragment = *child;
+ DCHECK(child_fragment.IsBox());
+ DCHECK(!child_fragment.HasSelfPaintingLayer());
+ DCHECK(!child_fragment.IsFloating());
+ const auto& box_child_fragment = To<NGPhysicalBoxFragment>(child_fragment);
+ if (box_child_fragment.CanTraverse()) {
+ if (!box_child_fragment.GetLayoutObject()) {
+ // It's normally FragmentData that provides us with the paint offset.
+ // FragmentData is (at least currently) associated with a LayoutObject.
+ // If we have no LayoutObject, we have no FragmentData, so we need to
+ // calculate the offset on our own (which is very simple, anyway).
+ // Bypass Paint() and jump directly to PaintObject(), to skip the code
+ // that assumes that we have a LayoutObject (and FragmentData).
+ PhysicalOffset child_offset = paint_offset + child.offset;
+
+ if (box_child_fragment.IsFragmentainerBox()) {
+ // This is a fragmentainer, and when node inside a fragmentation
+ // context paints multiple block fragments, we need to distinguish
+ // between them somehow, for paint caching to work. Therefore,
+ // establish a display item scope here.
+ unsigned identifier = FragmentainerUniqueIdentifier(box_child_fragment);
+ ScopedDisplayItemFragment scope(paint_info.context, identifier);
NGBoxFragmentPainter(box_child_fragment)
.PaintObject(paint_info, child_offset);
- continue;
+ return;
}
NGBoxFragmentPainter(box_child_fragment)
- .Paint(paint_info_for_descendants);
- continue;
+ .PaintObject(paint_info, child_offset);
+ return;
}
- // Fall back to flow-thread painting when reaching a column (the flow thread
- // is treated as a self-painting PaintLayer when fragment traversal is
- // disabled, so nothing to do here).
- if (box_child_fragment.IsColumnBox())
- continue;
+ NGBoxFragmentPainter(box_child_fragment).Paint(paint_info_for_descendants);
+ return;
+ }
- auto* layout_object = child_fragment.GetLayoutObject();
- DCHECK(layout_object);
- if (child_fragment.IsPaintedAtomically() &&
- child_fragment.IsLegacyLayoutRoot()) {
- ObjectPainter(*layout_object)
- .PaintAllPhasesAtomically(paint_info_for_descendants);
- } else {
- // TODO(ikilpatrick): Once FragmentItem ships we should call the
- // NGBoxFragmentPainter directly for NG objects.
- layout_object->Paint(paint_info_for_descendants);
- }
+ // Fall back to flow-thread painting when reaching a column (the flow thread
+ // is treated as a self-painting PaintLayer when fragment traversal is
+ // disabled, so nothing to do here).
+ if (box_child_fragment.IsColumnBox())
+ return;
+
+ auto* layout_object = child_fragment.GetLayoutObject();
+ DCHECK(layout_object);
+ if (child_fragment.IsPaintedAtomically() &&
+ child_fragment.IsLegacyLayoutRoot()) {
+ ObjectPainter(*layout_object)
+ .PaintAllPhasesAtomically(paint_info_for_descendants);
+ } else {
+ // TODO(ikilpatrick): Once FragmentItem ships we should call the
+ // NGBoxFragmentPainter directly for NG objects.
+ layout_object->Paint(paint_info_for_descendants);
}
}
@@ -1128,6 +1213,20 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRectImpl(
paint_info.context.EndLayer();
}
+void NGBoxFragmentPainter::PaintBoxDecorationBackgroundForBlockInInline(
+ NGInlineCursor* children,
+ const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
+ for (; *children; children->MoveToNext()) {
+ const NGFragmentItem* item = children->Current().Item();
+ if (item->Type() != NGFragmentItem::kBox)
+ continue;
+ const NGPhysicalBoxFragment* fragment = item->BoxFragment();
+ if (fragment && fragment->IsBlockInInline())
+ PaintBoxItem(*item, *fragment, *children, paint_info, paint_offset);
+ }
+}
+
void NGBoxFragmentPainter::PaintColumnRules(
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
@@ -1218,8 +1317,8 @@ void NGBoxFragmentPainter::PaintColumnRules(
rule.Move(paint_offset);
IntRect snapped_rule = PixelSnappedIntRect(rule);
- ObjectPainter::DrawBoxSide(paint_info.context, snapped_rule, box_side,
- rule_color, rule_style);
+ BoxBorderPainter::DrawBoxSide(paint_info.context, snapped_rule, box_side,
+ rule_color, rule_style);
recorder.UniteVisualRect(snapped_rule);
previous_column = current_column;
@@ -1312,7 +1411,7 @@ void NGBoxFragmentPainter::PaintInlineItems(const PaintInfo& paint_info,
}
switch (item->Type()) {
case NGFragmentItem::kText:
- case NGFragmentItem::kSVGText:
+ case NGFragmentItem::kSvgText:
case NGFragmentItem::kGeneratedText:
if (!item->IsHiddenForPaint())
PaintTextItem(*cursor, paint_info, paint_offset, parent_offset);
@@ -1375,8 +1474,14 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
paint_info.phase != PaintPhase::kTextClip &&
paint_info.phase != PaintPhase::kMask &&
paint_info.phase != PaintPhase::kDescendantOutlinesOnly &&
- paint_info.phase != PaintPhase::kOutline)
+ paint_info.phase != PaintPhase::kOutline) {
+ if (UNLIKELY(ShouldPaintDescendantBlockBackgrounds(paint_info.phase))) {
+ // When block-in-inline, block backgrounds need to be painted.
+ PaintBoxDecorationBackgroundForBlockInInline(children, paint_info,
+ paint_offset);
+ }
return;
+ }
// The only way an inline could paint like this is if it has a layer.
const auto* layout_object = box_fragment_.GetLayoutObject();
@@ -1556,9 +1661,19 @@ void NGBoxFragmentPainter::PaintBoxItem(
return;
}
- DCHECK(child_fragment.IsInlineBox());
- NGInlineBoxFragmentPainter(cursor, item, child_fragment)
- .Paint(paint_info, paint_offset);
+ if (child_fragment.IsInlineBox()) {
+ NGInlineBoxFragmentPainter(cursor, item, child_fragment)
+ .Paint(paint_info, paint_offset);
+ return;
+ }
+
+ // Block-in-inline
+ DCHECK(RuntimeEnabledFeatures::LayoutNGBlockInInlineEnabled());
+ DCHECK(!child_fragment.GetLayoutObject()->IsInline());
+ PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
+ paint_info_for_descendants.SetIsInFragmentTraversal();
+ PaintBlockChild({&child_fragment, item.OffsetInContainerFragment()},
+ paint_info, paint_info_for_descendants, paint_offset);
}
void NGBoxFragmentPainter::PaintBoxItem(const NGFragmentItem& item,
@@ -1616,14 +1731,15 @@ bool NGBoxFragmentPainter::ShouldPaint(
return false;
}
-void NGBoxFragmentPainter::PaintTextClipMask(GraphicsContext& context,
+void NGBoxFragmentPainter::PaintTextClipMask(const PaintInfo& paint_info,
const IntRect& mask_rect,
const PhysicalOffset& paint_offset,
bool object_has_multiple_boxes) {
- PaintInfo paint_info(context, CullRect(mask_rect), PaintPhase::kTextClip,
- kGlobalPaintNormalPhase, 0);
+ PaintInfo mask_paint_info(paint_info.context, CullRect(mask_rect),
+ PaintPhase::kTextClip, kGlobalPaintNormalPhase, 0);
+ mask_paint_info.SetFragmentID(paint_info.FragmentID());
if (!object_has_multiple_boxes) {
- PaintObject(paint_info, paint_offset);
+ PaintObject(mask_paint_info, paint_offset);
return;
}
@@ -1631,7 +1747,7 @@ void NGBoxFragmentPainter::PaintTextClipMask(GraphicsContext& context,
DCHECK(box_item_);
NGInlineBoxFragmentPainter inline_box_painter(*inline_box_cursor_,
*box_item_);
- PaintTextClipMask(paint_info,
+ PaintTextClipMask(mask_paint_info,
paint_offset - box_item_->OffsetInContainerFragment(),
&inline_box_painter);
}
@@ -1669,8 +1785,8 @@ PhysicalRect NGBoxFragmentPainter::AdjustRectForScrolledContent(
// Adjust the paint rect to reflect a scrolled content box with borders at
// the ends.
- PhysicalOffset offset(physical.PixelSnappedScrolledContentOffset());
- scrolled_paint_rect.Move(-offset);
+ scrolled_paint_rect.offset -=
+ PhysicalOffset(physical.PixelSnappedScrolledContentOffset());
LayoutRectOutsets borders = AdjustedBorderOutsets(info);
scrolled_paint_rect.size =
physical.ScrollSize() + PhysicalSize(borders.Size());
@@ -1708,10 +1824,11 @@ BoxPainterBase::FillLayerInfo NGBoxFragmentPainter::GetFillLayerInfo(
is_painting_scrolling_background);
}
+template <typename T>
bool NGBoxFragmentPainter::HitTestContext::AddNodeToResult(
Node* node,
const NGPhysicalBoxFragment* box_fragment,
- const PhysicalRect& bounds_rect,
+ const T& bounds_rect,
const PhysicalOffset& offset) const {
if (node && !result->InnerNode())
result->SetNodeAndPosition(node, box_fragment, location.Point() - offset);
@@ -1719,10 +1836,11 @@ bool NGBoxFragmentPainter::HitTestContext::AddNodeToResult(
kStopHitTesting;
}
+template <typename T>
bool NGBoxFragmentPainter::HitTestContext::AddNodeToResultWithContentOffset(
Node* node,
const NGPhysicalBoxFragment& container,
- const PhysicalRect& bounds_rect,
+ const T& bounds_rect,
PhysicalOffset offset) const {
if (container.IsScrollContainer())
offset += PhysicalOffset(container.PixelSnappedScrolledContentOffset());
@@ -1754,12 +1872,19 @@ bool NGBoxFragmentPainter::NodeAtPoint(const HitTestContext& hit_test,
physical_offset))
return false;
+ bool pointer_events_bounding_box = false;
bool hit_test_self = fragment.IsInSelfHitTestingPhase(hit_test.action);
if (hit_test_self) {
// Table row and table section are never a hit target.
+ // SVG <text> is not a hit target except if 'pointer-events: bounding-box'.
if (PhysicalFragment().IsTableNGRow() ||
- PhysicalFragment().IsTableNGSection())
+ PhysicalFragment().IsTableNGSection()) {
hit_test_self = false;
+ } else if (fragment.IsSvgText()) {
+ pointer_events_bounding_box =
+ fragment.Style().PointerEvents() == EPointerEvents::kBoundingBox;
+ hit_test_self = pointer_events_bounding_box;
+ }
}
if (hit_test_self && box_fragment_.IsScrollContainer() &&
@@ -1813,11 +1938,20 @@ bool NGBoxFragmentPainter::NodeAtPoint(const HitTestContext& hit_test,
if (hit_test_self &&
IsVisibleToHitTest(box_fragment_, hit_test.result->GetHitTestRequest())) {
PhysicalRect bounds_rect(physical_offset, size);
- if (UNLIKELY(hit_test.result->GetHitTestRequest().GetType() &
- HitTestRequest::kHitTestVisualOverflow)) {
- bounds_rect = SelfInkOverflow();
+ if (UNLIKELY(
+ hit_test.result->GetHitTestRequest().IsHitTestVisualOverflow())) {
+ // We'll include overflow from children here (in addition to self-overflow
+ // caused by filters), because we want to record a match if we hit the
+ // overflow of a child below the stop node. This matches legacy behavior
+ // in LayoutBox::NodeAtPoint(); see call to
+ // PhysicalVisualOverflowRectIncludingFilters().
+ bounds_rect = InkOverflowIncludingFilters();
bounds_rect.Move(physical_offset);
}
+ if (UNLIKELY(pointer_events_bounding_box)) {
+ bounds_rect = PhysicalRect::EnclosingRect(
+ PhysicalFragment().GetLayoutObject()->ObjectBoundingBox());
+ }
// TODO(kojii): Don't have good explanation why only inline box needs to
// snap, but matches to legacy and fixes crbug.com/976606.
if (fragment.IsInlineBox())
@@ -1891,16 +2025,27 @@ bool NGBoxFragmentPainter::HitTestTextItem(
if (!IsVisibleToHitTest(text_item, hit_test.result->GetHitTestRequest()))
return false;
- // TODO(layout-dev): Clip to line-top/bottom.
- const PhysicalOffset offset =
- hit_test.inline_root_offset + text_item.OffsetInContainerFragment();
- PhysicalRect border_rect(offset, text_item.Size());
- PhysicalRect rect(PixelSnappedIntRect(border_rect));
- if (UNLIKELY(hit_test.result->GetHitTestRequest().GetType() &
- HitTestRequest::kHitTestVisualOverflow)) {
- rect = text_item.SelfInkOverflow();
- rect.Move(border_rect.offset);
+ if (text_item.Type() == NGFragmentItem::kSvgText &&
+ text_item.HasSvgTransformForBoundingBox()) {
+ const FloatQuad quad = text_item.SvgUnscaledQuad();
+ if (!hit_test.location.Intersects(quad))
+ return false;
+ return hit_test.AddNodeToResultWithContentOffset(
+ text_item.NodeForHitTest(), cursor.ContainerFragment(), quad,
+ hit_test.inline_root_offset);
}
+
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(box_fragment_.GetLayoutObject());
+
+ // TODO(layout-dev): Clip to line-top/bottom.
+ const PhysicalRect rect =
+ UNLIKELY(text_combine)
+ ? text_combine->ComputeTextBoundsRectForHitTest(
+ text_item, hit_test.inline_root_offset)
+ : text_item.ComputeTextBoundsRectForHitTest(
+ hit_test.inline_root_offset,
+ hit_test.result->GetHitTestRequest().IsHitTestVisualOverflow());
if (!hit_test.location.Intersects(rect))
return false;
@@ -1943,6 +2088,9 @@ bool NGBoxFragmentPainter::HitTestLineBoxFragment(
bounds_rect)))
return false;
+ if (cursor.ContainerFragment().IsSvgText())
+ return false;
+
// Now hit test ourselves.
if (!hit_test.location.Intersects(bounds_rect))
return false;
@@ -2033,14 +2181,18 @@ bool NGBoxFragmentPainter::HitTestChildBoxItem(
return true;
}
+ if (cursor.ContainerFragment().IsSvgText() &&
+ item.Style().PointerEvents() != EPointerEvents::kBoundingBox)
+ return false;
+
// Now hit test ourselves.
if (hit_test.action == kHitTestForeground &&
IsVisibleToHitTest(item, hit_test.result->GetHitTestRequest())) {
const PhysicalOffset child_offset =
hit_test.inline_root_offset + item.OffsetInContainerFragment();
PhysicalRect bounds_rect(child_offset, item.Size());
- if (UNLIKELY(hit_test.result->GetHitTestRequest().GetType() &
- HitTestRequest::kHitTestVisualOverflow)) {
+ if (UNLIKELY(
+ hit_test.result->GetHitTestRequest().IsHitTestVisualOverflow())) {
bounds_rect = item.SelfInkOverflow();
bounds_rect.Move(child_offset);
}
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 1d7e9b305de..0338e7ada07 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
@@ -82,7 +82,7 @@ class CORE_EXPORT NGBoxFragmentPainter : public BoxPainterBase {
bool is_painting_scrolling_background) const override;
bool IsPaintingScrollingBackground(const PaintInfo&) const override;
- void PaintTextClipMask(GraphicsContext&,
+ void PaintTextClipMask(const PaintInfo&,
const IntRect& mask_rect,
const PhysicalOffset& paint_offset,
bool object_has_multiple_boxes) override;
@@ -115,11 +115,20 @@ class CORE_EXPORT NGBoxFragmentPainter : public BoxPainterBase {
const PhysicalRect& paint_rect,
const DisplayItemClient&);
+ void PaintBoxDecorationBackgroundForBlockInInline(
+ NGInlineCursor* children,
+ const PaintInfo&,
+ const PhysicalOffset& paint_offset);
+
void PaintColumnRules(const PaintInfo&, const PhysicalOffset& paint_offset);
void PaintInternal(const PaintInfo&);
void PaintAllPhasesAtomically(const PaintInfo&);
void PaintBlockChildren(const PaintInfo&, PhysicalOffset);
+ void PaintBlockChild(const NGLink& child,
+ const PaintInfo& paint_info,
+ const PaintInfo& paint_info_for_descendants,
+ PhysicalOffset paint_offset);
void PaintInlineItems(const PaintInfo&,
const PhysicalOffset& paint_offset,
const PhysicalOffset& parent_offset,
@@ -167,7 +176,9 @@ class CORE_EXPORT NGBoxFragmentPainter : public BoxPainterBase {
const PhysicalRect&,
const Color& background_color,
BackgroundBleedAvoidance = kBackgroundBleedNone);
- void PaintCarets(const PaintInfo&, const PhysicalOffset& paint_offset);
+ void PaintCaretsIfNeeded(const ScopedPaintState&,
+ const PaintInfo&,
+ const PhysicalOffset& paint_offset);
// This should be called in the background paint phase even if there is no
// other painted content.
@@ -193,17 +204,21 @@ class CORE_EXPORT NGBoxFragmentPainter : public BoxPainterBase {
// Add |node| to |HitTestResult|. Returns true if the hit-testing should
// stop.
+ // T is PhysicalRect or FloatQuad.
+ template <typename T>
bool AddNodeToResult(Node* node,
const NGPhysicalBoxFragment* box_fragment,
- const PhysicalRect& bounds_rect,
+ const T& bounds_rect,
const PhysicalOffset& offset) const;
// Same as |AddNodeToResult|, except that |offset| is in the content
// coordinate system rather than the container coordinate system. They
// differ when |container| is a scroll container.
+ // T is PhysicalRect or FloatQuad.
+ template <typename T>
bool AddNodeToResultWithContentOffset(
Node* node,
const NGPhysicalBoxFragment& container,
- const PhysicalRect& bounds_rect,
+ const T& bounds_rect,
PhysicalOffset offset) const;
HitTestAction action;
@@ -288,7 +303,7 @@ class CORE_EXPORT NGBoxFragmentPainter : public BoxPainterBase {
const DisplayItemClient& GetDisplayItemClient() const {
return display_item_client_;
}
- PhysicalRect SelfInkOverflow() const;
+ PhysicalRect InkOverflowIncludingFilters() const;
const NGPhysicalBoxFragment& box_fragment_;
const DisplayItemClient& display_item_client_;
@@ -315,8 +330,6 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter(
DCHECK_EQ(inline_box_cursor_->Current().Item(), box_item_);
if (box_item_)
DCHECK_EQ(box_item_->BoxFragment(), &box);
- DCHECK_EQ(box.IsInlineBox(), !!inline_box_cursor_);
- DCHECK_EQ(box.IsInlineBox(), !!box_item_);
#endif
}
@@ -336,7 +349,6 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter(
&inline_box_cursor,
&item) {
DCHECK_EQ(item.BoxFragment(), &fragment);
- DCHECK(fragment.IsInlineBox());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
index 4ad80e25d81..9d9bfd812c1 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
@@ -200,4 +200,26 @@ TEST_P(NGBoxFragmentPainterTest, SelectionTablePainting) {
auto record = builder.EndRecording();
}
+TEST_P(NGBoxFragmentPainterTest, ClippedText) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="target" style="overflow: hidden; position: relative;
+ width: 100px; height: 100px">
+ A<br>B<br>C<br>D
+ </div>
+ )HTML");
+ // Initially all the texts are painted.
+ auto num_all_display_items = ContentDisplayItems().size();
+ auto* target = GetDocument().getElementById("target");
+
+ target->SetInlineStyleProperty(CSSPropertyID::kHeight, "0px");
+ UpdateAllLifecyclePhasesForTest();
+ // None of the texts should be painted.
+ EXPECT_EQ(num_all_display_items - 4, ContentDisplayItems().size());
+
+ target->SetInlineStyleProperty(CSSPropertyID::kHeight, "1px");
+ UpdateAllLifecyclePhasesForTest();
+ // Only "A" should be painted.
+ EXPECT_EQ(num_all_display_items - 3, ContentDisplayItems().size());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc
index dd8d402df61..d8e252149e5 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h"
#include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
+#include "third_party/blink/renderer/core/paint/outline_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
@@ -35,7 +36,8 @@ void NGFragmentPainter::PaintOutline(const PaintInfo& paint_info,
visual_rect.Inflate(style_to_use.OutlineOutsetExtent());
DrawingRecorder recorder(paint_info.context, display_item_client,
paint_info.phase, visual_rect);
- PaintOutlineRects(paint_info, outline_rects, style_to_use);
+ OutlinePainter::PaintOutlineRects(paint_info.context, outline_rects,
+ style_to_use);
}
void NGFragmentPainter::AddURLRectIfNeeded(const PaintInfo& paint_info,
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h
index 679d9aad40e..b62e6145a01 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_FRAGMENT_PAINTER_H_
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
-#include "third_party/blink/renderer/core/paint/object_painter_base.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -15,8 +14,8 @@ struct PaintInfo;
struct PhysicalOffset;
// Generic fragment painter for paint logic shared between all types of
-// fragments. LayoutNG version of ObjectPainter, based on ObjectPainterBase.
-class NGFragmentPainter : public ObjectPainterBase {
+// fragments. LayoutNG version of ObjectPainter.
+class NGFragmentPainter {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc
index ac1af42b6b1..6ef75fc91e1 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc
@@ -8,9 +8,11 @@
#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/document_marker_controller.h"
+#include "third_party/blink/renderer/core/editing/markers/highlight_marker.h"
#include "third_party/blink/renderer/core/editing/markers/styleable_marker.h"
#include "third_party/blink/renderer/core/editing/markers/text_marker_base.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/highlight/highlight.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/paint/document_marker_painter.h"
@@ -18,6 +20,7 @@
#include "third_party/blink/renderer/core/paint/inline_text_box_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_text_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
namespace blink {
@@ -110,8 +113,11 @@ Color SelectionBackgroundColor(const Document& document,
// If the text color ends up being the same as the selection background,
// invert the selection background.
- if (text_color == color)
+ if (text_color == color) {
+ UseCounter::Count(node->GetDocument(),
+ WebFeature::kSelectionBackgroundColorInversion);
return Color(0xff - color.Red(), 0xff - color.Green(), 0xff - color.Blue());
+ }
return color;
}
@@ -231,15 +237,14 @@ void NGHighlightPainter::SelectionPaintState::
}
}
-NGHighlightPainter::NGHighlightPainter(
- NGTextPainter& text_painter,
- const PaintInfo& paint_info,
- const NGInlineCursor& cursor,
- const NGFragmentItem& fragment_item,
- const PhysicalOffset& box_origin,
- const ComputedStyle& style,
- absl::optional<SelectionPaintState> selection,
- bool is_printing)
+NGHighlightPainter::NGHighlightPainter(NGTextPainter& text_painter,
+ const PaintInfo& paint_info,
+ const NGInlineCursor& cursor,
+ const NGFragmentItem& fragment_item,
+ const PhysicalOffset& box_origin,
+ const ComputedStyle& style,
+ SelectionPaintState* selection,
+ bool is_printing)
: text_painter_(text_painter),
paint_info_(paint_info),
cursor_(cursor),
@@ -301,8 +306,7 @@ void NGHighlightPainter::Paint(Phase phase) {
Color color;
if (marker->GetType() == DocumentMarker::kTextMatch) {
color = LayoutTheme::GetTheme().PlatformTextSearchHighlightColor(
- text_marker.IsActiveMatch(), document.InForcedColorsMode(),
- style_.UsedColorScheme());
+ text_marker.IsActiveMatch(), style_.UsedColorScheme());
} else {
color = HighlightPaintingUtils::HighlightBackgroundColor(
document, style_, node_, kPseudoIdTargetText);
@@ -347,6 +351,49 @@ void NGHighlightPainter::Paint(Phase phase) {
}
} break;
+ case DocumentMarker::kHighlight: {
+ const auto& highlight_marker = To<HighlightMarker>(*marker);
+ const Document& document = node_->GetDocument();
+
+ // Paint background
+ if (phase == kBackground) {
+ Color background_color =
+ HighlightPaintingUtils::HighlightBackgroundColor(
+ document, style_, node_, kPseudoIdHighlight,
+ highlight_marker.GetHighlightName());
+
+ PaintRect(paint_info_.context, PhysicalOffset(box_origin_),
+ fragment_item_.LocalRect(text, paint_start_offset,
+ paint_end_offset),
+ background_color);
+ break;
+ }
+
+ DCHECK_EQ(phase, kForeground);
+ Color text_color = style_.VisitedDependentColor(GetCSSPropertyColor());
+
+ 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.color_scheme = style_.UsedColorScheme();
+ text_style.shadow = nullptr;
+
+ const TextPaintStyle final_text_style =
+ HighlightPaintingUtils::HighlightPaintingStyle(
+ document, style_, node_, kPseudoIdHighlight, text_style,
+ paint_info_, highlight_marker.GetHighlightName());
+
+ if (final_text_style.current_color == Color::kTransparent)
+ break;
+
+ text_painter_.Paint(paint_start_offset, paint_end_offset,
+ paint_end_offset - paint_start_offset,
+ final_text_style, kInvalidDOMNodeId);
+
+ } break;
+
default:
NOTREACHED();
break;
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.h
index d01ec5ff291..69185992a54 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_HIGHLIGHT_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_HIGHLIGHT_PAINTER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
@@ -98,13 +99,13 @@ class CORE_EXPORT NGHighlightPainter {
const NGFragmentItem& fragment_item,
const PhysicalOffset& box_origin,
const ComputedStyle& style,
- absl::optional<SelectionPaintState>,
+ SelectionPaintState*,
bool is_printing);
enum Phase { kBackground, kForeground };
void Paint(Phase phase);
- absl::optional<SelectionPaintState>& Selection() { return selection_; }
+ SelectionPaintState* Selection() { return selection_; }
absl::optional<AppliedTextDecoration> SelectionDecoration() {
return selection_
? selection_->GetSelectionStyle().selection_text_decoration
@@ -118,7 +119,7 @@ class CORE_EXPORT NGHighlightPainter {
const NGFragmentItem& fragment_item_;
const PhysicalOffset& box_origin_;
const ComputedStyle& style_;
- absl::optional<SelectionPaintState> selection_;
+ SelectionPaintState* selection_;
const LayoutObject* layout_object_;
Node* node_;
const DocumentMarkerVector markers_;
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
index acddffe60bd..e08bf386fb9 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
@@ -12,6 +12,7 @@
#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/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/core/style/nine_piece_image.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -50,10 +51,15 @@ void NGInlineBoxFragmentPainter::Paint(const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
ScopedDisplayItemFragment display_item_fragment(
paint_info.context, inline_box_item_.FragmentId());
+ const LayoutObject& layout_object = *inline_box_fragment_.GetLayoutObject();
+ absl::optional<ScopedSVGPaintState> svg_paint_state;
+ if (layout_object.IsSVGInline())
+ svg_paint_state.emplace(layout_object, paint_info);
const PhysicalOffset adjusted_paint_offset =
paint_offset + inline_box_item_.OffsetInContainerFragment();
- if (paint_info.phase == PaintPhase::kForeground)
+ if (paint_info.phase == PaintPhase::kForeground &&
+ !layout_object.IsSVGInline())
PaintBackgroundBorderShadow(paint_info, adjusted_paint_offset);
const bool suppress_box_decoration_background = true;
@@ -68,7 +74,8 @@ void NGInlineBoxFragmentPainterBase::PaintBackgroundBorderShadow(
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
DCHECK(paint_info.phase == PaintPhase::kForeground);
- if (inline_box_fragment_.Style().Visibility() != EVisibility::kVisible)
+ if (inline_box_fragment_.Style().Visibility() != EVisibility::kVisible ||
+ inline_box_fragment_.IsOpaque())
return;
// You can use p::first-line to specify a background. If so, the direct child
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
index 1a0fefb2448..a3a79d8f6a7 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
#include "base/dcheck_is_on.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_mathml_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_mathml_painter.cc
index d764b2f2567..fbffad0c60b 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_mathml_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_mathml_painter.cc
@@ -79,6 +79,17 @@ void NGMathMLPainter::PaintOperator(const PaintInfo& info,
auto padding = box_fragment_.Padding();
physical_offset.left += borders.left + padding.left;
physical_offset.top += borders.top + padding.top;
+
+ // TODO(http://crbug.com/1124301): NGMathOperatorLayoutAlgorithm::Layout
+ // passes the operator's inline size but this does not match the width of the
+ // box fragment, which relies on the min-max sizes instead. Shift the paint
+ // offset to work around that issue, splitting the size error symmetrically.
+ DCHECK(box_fragment_.Style().IsHorizontalWritingMode());
+ physical_offset.left +=
+ (box_fragment_.Size().width - borders.HorizontalSum() -
+ padding.HorizontalSum() - parameters.operator_inline_size) /
+ 2;
+
PaintStretchyOrLargeOperator(info, paint_offset + physical_offset);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc
index e44355ff1e8..53bca621ece 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc
@@ -13,11 +13,11 @@
#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
+#include "third_party/blink/renderer/core/paint/box_border_painter.h"
#include "third_party/blink/renderer/core/paint/box_decoration_data.h"
#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_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/paint_layer.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
@@ -53,6 +53,16 @@ class NGTableCollapsedEdge {
InitCachedProps();
}
+ NGTableCollapsedEdge(const NGTableCollapsedEdge& edge)
+ : NGTableCollapsedEdge(edge, 0) {}
+
+ NGTableCollapsedEdge& operator=(const NGTableCollapsedEdge& edge) {
+ edge_index_ = edge.edge_index_;
+ border_width_ = edge.border_width_;
+ border_style_ = edge.border_style_;
+ return *this;
+ }
+
bool Exists() const { return edge_index_ != UINT_MAX; }
bool CanPaint() const {
@@ -206,13 +216,6 @@ class NGTableCollapsedEdge {
return !(*this == rhs);
}
- NGTableCollapsedEdge& operator=(const NGTableCollapsedEdge& edge) {
- edge_index_ = edge.edge_index_;
- border_width_ = edge.border_width_;
- border_style_ = edge.border_style_;
- return *this;
- }
-
private:
void InitCachedProps() {
if (edge_index_ == UINT_MAX) {
@@ -420,7 +423,6 @@ void NGTablePainter::PaintBoxDecorationBackground(
void NGTablePainter::PaintCollapsedBorders(const PaintInfo& paint_info,
const PhysicalOffset& paint_offset,
const IntRect& visual_rect) {
- DCHECK_EQ(paint_info.phase, PaintPhase::kForeground);
const NGTableBorders* collapsed_borders = fragment_.TableCollapsedBorders();
if (!collapsed_borders)
return;
@@ -525,7 +527,7 @@ void NGTablePainter::PaintCollapsedBorders(const PaintInfo& paint_info,
} else {
box_side = edge.IsInlineAxis() ? BoxSide::kLeft : BoxSide::kTop;
}
- ObjectPainter::DrawBoxSide(
+ BoxBorderPainter::DrawBoxSide(
paint_info.context, PixelSnappedIntRect(physical_border_rect), box_side,
edge.BorderColor(), edge.BorderStyle());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc
new file mode 100644
index 00000000000..82a618e8a1e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc
@@ -0,0 +1,127 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.h"
+
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
+
+namespace blink {
+
+NGTextCombinePainter::NGTextCombinePainter(GraphicsContext& context,
+ const ComputedStyle& style,
+ const PhysicalRect& text_frame_rect)
+ : TextPainterBase(context,
+ style.GetFont(),
+ text_frame_rect.offset,
+ text_frame_rect,
+ /* horizontal */ false),
+ style_(style) {}
+
+NGTextCombinePainter::~NGTextCombinePainter() = default;
+
+void NGTextCombinePainter::Paint(const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset,
+ const LayoutNGTextCombine& text_combine) {
+ if (paint_info.phase == PaintPhase::kBlockBackground ||
+ paint_info.phase == PaintPhase::kForcedColorsModeBackplate ||
+ paint_info.phase == PaintPhase::kFloat ||
+ paint_info.phase == PaintPhase::kSelfBlockBackgroundOnly ||
+ paint_info.phase == PaintPhase::kDescendantBlockBackgroundsOnly ||
+ paint_info.phase == PaintPhase::kSelfOutlineOnly) {
+ // Note: We should not paint text decoration and emphasis markr in above
+ // paint phases. Otherwise, text decoration and emphasis mark are painted
+ // multiple time and anti-aliasing is broken.
+ // See virtual/text-antialias/emphasis-combined-text.html
+ return;
+ }
+
+ // Here |paint_info.phases| is one of following:
+ // PaintPhase::kSelectionDragImage
+ // PaintPhase::kTextClip
+ // PaintPhase::kForeground
+ // PaintPhase::kOutline
+ // These values come from |NGBoxFragmentPainter::PaintAllPhasesAtomically()|.
+
+ const ComputedStyle& style = text_combine.Parent()->StyleRef();
+ const bool has_text_decoration =
+ style.TextDecorationsInEffect() != TextDecoration::kNone;
+ const bool has_emphasis_mark =
+ style.GetTextEmphasisMark() != TextEmphasisMark::kNone;
+ DCHECK(has_text_decoration | has_emphasis_mark);
+
+ const PhysicalRect& text_frame_rect =
+ text_combine.ComputeTextFrameRect(paint_offset);
+
+ // To match the logical direction
+ GraphicsContextStateSaver state_saver(paint_info.context);
+ paint_info.context.ConcatCTM(
+ TextPainterBase::Rotation(text_frame_rect, style.GetWritingMode()));
+
+ NGTextCombinePainter text_painter(paint_info.context, style, text_frame_rect);
+ const TextPaintStyle text_style = TextPainterBase::TextPaintingStyle(
+ text_combine.GetDocument(), style, paint_info);
+
+ if (has_emphasis_mark) {
+ text_painter.PaintEmphasisMark(text_style,
+ text_combine.Parent()->StyleRef().GetFont());
+ }
+
+ if (has_text_decoration)
+ text_painter.PaintDecorations(paint_info, text_style);
+}
+
+// static
+bool NGTextCombinePainter::ShouldPaint(
+ const LayoutNGTextCombine& text_combine) {
+ const auto& style = text_combine.Parent()->StyleRef();
+ return style.TextDecorationsInEffect() != TextDecoration::kNone ||
+ style.GetTextEmphasisMark() != TextEmphasisMark::kNone;
+}
+
+void NGTextCombinePainter::ClipDecorationsStripe(float upper,
+ float stripe_width,
+ float dilation) {
+ // Nothing to do.
+}
+
+void NGTextCombinePainter::PaintDecorations(const PaintInfo& paint_info,
+ const TextPaintStyle& text_style) {
+ // Setup arguments for painting text decorations
+ const absl::optional<AppliedTextDecoration> selection_text_decoration;
+ const ComputedStyle* const decorating_box_style = nullptr;
+ TextDecorationInfo decoration_info(
+ text_frame_rect_.offset, text_frame_rect_.size.width,
+ style_.GetFontBaseline(), style_, selection_text_decoration,
+ decorating_box_style);
+
+ const NGTextDecorationOffset decoration_offset(style_, style_, nullptr);
+ const auto& applied_text_decorations = style_.AppliedTextDecorations();
+
+ // Paint text decorations except line through
+ bool has_line_through_decoration = false;
+ PaintDecorationsExceptLineThrough(decoration_offset, decoration_info,
+ paint_info, applied_text_decorations,
+ text_style, &has_line_through_decoration);
+ if (!has_line_through_decoration)
+ return;
+
+ // Paint line through
+ PaintDecorationsOnlyLineThrough(decoration_info, paint_info,
+ applied_text_decorations, text_style);
+}
+
+void NGTextCombinePainter::PaintEmphasisMark(const TextPaintStyle& text_style,
+ const Font& emphasis_mark_font) {
+ DCHECK_NE(style_.GetTextEmphasisMark(), TextEmphasisMark::kNone);
+ SetEmphasisMark(style_.TextEmphasisMarkString(),
+ style_.GetTextEmphasisPosition());
+ PaintEmphasisMarkForCombinedText(text_style, emphasis_mark_font);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.h
new file mode 100644
index 00000000000..479fae900eb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_COMBINE_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_COMBINE_PAINTER_H_
+
+#include "third_party/blink/renderer/core/paint/text_painter_base.h"
+#include "third_party/blink/renderer/platform/graphics/dom_node_id.h"
+
+namespace blink {
+
+class ComputedStyle;
+class LayoutNGTextCombine;
+
+// The painter for painting text decorations and emphasis marks for
+// LayoutNGTextCombine.
+class NGTextCombinePainter final : public TextPainterBase {
+ public:
+ NGTextCombinePainter(GraphicsContext& context,
+ const ComputedStyle& style,
+ const PhysicalRect& text_frame_rect);
+ ~NGTextCombinePainter();
+
+ static void Paint(const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset,
+ const LayoutNGTextCombine& text_combine);
+
+ static bool ShouldPaint(const LayoutNGTextCombine& text_combine);
+
+ private:
+ void ClipDecorationsStripe(float upper,
+ float stripe_width,
+ float dilation) override;
+
+ void PaintDecorations(const PaintInfo& paint_info,
+ const TextPaintStyle& text_style);
+ void PaintEmphasisMark(const TextPaintStyle& text_style,
+ const Font& emphasis_mark_font);
+
+ const ComputedStyle& style_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_COMBINE_PAINTER_H_
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 00f418a60e3..ed7e78071b1 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
@@ -13,7 +13,9 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
#include "third_party/blink/renderer/core/layout/list_marker.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -56,7 +58,7 @@ inline PhysicalRect ComputeBoxRect(const NGInlineCursor& cursor,
const PhysicalOffset& paint_offset,
const PhysicalOffset& parent_offset) {
PhysicalRect box_rect;
- if (const auto* svg_data = cursor.CurrentItem()->SVGFragmentData())
+ if (const auto* svg_data = cursor.CurrentItem()->SvgFragmentData())
box_rect = PhysicalRect::FastAndLossyFromFloatRect(svg_data->rect);
else
box_rect = cursor.CurrentItem()->RectInContainerFragment();
@@ -89,6 +91,9 @@ bool ShouldPaintEmphasisMark(const ComputedStyle& style,
const LayoutObject& layout_object) {
if (style.GetTextEmphasisMark() == TextEmphasisMark::kNone)
return false;
+ // Note: We set text-emphasis-style:none for combined text and we paint
+ // emphasis mark at left/right side of |LayoutNGTextCombine|.
+ DCHECK(!IsA<LayoutNGTextCombine>(layout_object.Parent()));
const LayoutObject* containing_block = layout_object.ContainingBlock();
if (!containing_block || !containing_block->IsRubyBase())
return true;
@@ -144,16 +149,32 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
const LayoutObject* layout_object = text_item.GetLayoutObject();
const Document& document = layout_object->GetDocument();
const bool is_printing = document.Printing();
+ // Don't paint selections when rendering a mask, clip-path (as a mask),
+ // pattern or feImage (element reference.)
+ const bool is_rendering_resource = paint_info.IsRenderingResourceSubtree();
+ const auto* const text_combine =
+ DynamicTo<LayoutNGTextCombine>(layout_object->Parent());
+#if DCHECK_IS_ON()
+ if (UNLIKELY(text_combine))
+ LayoutNGTextCombine::AssertStyleIsValid(style);
+#endif
// Determine whether or not we're selected.
- absl::optional<NGHighlightPainter::SelectionPaintState> selection;
- if (UNLIKELY(!is_printing && paint_info.phase != PaintPhase::kTextClip &&
+ NGHighlightPainter::SelectionPaintState* selection = nullptr;
+ absl::optional<NGHighlightPainter::SelectionPaintState>
+ selection_for_bounds_recording;
+ if (UNLIKELY(!is_printing && !is_rendering_resource &&
+ paint_info.phase != PaintPhase::kTextClip &&
layout_object->IsSelected())) {
const NGInlineCursor& root_inline_cursor =
InlineCursorForBlockFlow(cursor_, &inline_cursor_for_block_flow_);
- selection.emplace(root_inline_cursor);
- if (!selection->Status().HasValidRange())
- selection.reset();
+
+ // Empty selections might be the boundary of the document selection, and
+ // thus need to get recorded. We only need to paint the selection if it
+ // has a valid range.
+ selection_for_bounds_recording.emplace(root_inline_cursor);
+ if (selection_for_bounds_recording->Status().HasValidRange())
+ selection = &selection_for_bounds_recording.value();
}
if (!selection) {
// When only painting the selection drag image, don't bother to paint if
@@ -167,54 +188,64 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
}
PhysicalRect box_rect = ComputeBoxRect(cursor_, paint_offset, parent_offset_);
+ if (UNLIKELY(text_combine)) {
+ box_rect.offset.left =
+ text_combine->AdjustTextLeftForPaint(box_rect.offset.left);
+ }
+
IntRect visual_rect;
- const LayoutSVGInlineText* svg_inline_text = nullptr;
+ const auto* const svg_inline_text =
+ DynamicTo<LayoutSVGInlineText>(layout_object);
float scaling_factor = 1.0f;
- if (text_item.Type() == NGFragmentItem::kSVGText) {
- svg_inline_text = To<LayoutSVGInlineText>(layout_object);
+ if (UNLIKELY(svg_inline_text)) {
+ DCHECK_EQ(text_item.Type(), NGFragmentItem::kSvgText);
scaling_factor = svg_inline_text->ScalingFactor();
DCHECK_NE(scaling_factor, 0.0f);
visual_rect = EnclosingIntRect(
svg_inline_text->Parent()->VisualRectInLocalSVGCoordinates());
} else {
+ DCHECK_NE(text_item.Type(), NGFragmentItem::kSvgText);
PhysicalRect ink_overflow = text_item.SelfInkOverflow();
ink_overflow.Move(box_rect.offset);
visual_rect = EnclosingIntRect(ink_overflow);
}
- // The text clip phase already has a DrawingRecorder. Text clips are initiated
- // only in BoxPainterBase::PaintFillLayer, which is already within a
- // DrawingRecorder.
- absl::optional<DrawingRecorder> recorder;
- const auto& display_item_client =
- AsDisplayItemClient(cursor_, selection.has_value());
-
// Ensure the selection bounds are recorded on the paint chunk regardless of
- // whether the diplay item that contains the actual selection painting is
+ // whether the display item that contains the actual selection painting is
// reused.
absl::optional<SelectionBoundsRecorder> selection_recorder;
- if (UNLIKELY(selection && paint_info.phase == PaintPhase::kForeground &&
- !is_printing)) {
+ if (UNLIKELY(selection_for_bounds_recording &&
+ paint_info.phase == PaintPhase::kForeground && !is_printing)) {
if (SelectionBoundsRecorder::ShouldRecordSelection(
cursor_.Current().GetLayoutObject()->GetFrame()->Selection(),
- selection->State())) {
+ selection_for_bounds_recording->State())) {
PhysicalRect selection_rect =
- selection->ComputeSelectionRect(box_rect.offset);
- selection_recorder.emplace(selection->State(), selection_rect,
- paint_info.context.GetPaintController(),
- cursor_.Current().ResolvedDirection(),
- style.GetWritingMode(),
- *cursor_.Current().GetLayoutObject());
+ selection_for_bounds_recording->ComputeSelectionRect(box_rect.offset);
+ selection_recorder.emplace(
+ selection_for_bounds_recording->State(), selection_rect,
+ paint_info.context.GetPaintController(),
+ cursor_.Current().ResolvedDirection(), style.GetWritingMode(),
+ *cursor_.Current().GetLayoutObject());
}
}
+ // This is declared after selection_recorder so that this will be destructed
+ // before selection_recorder to ensure the selection is painted before
+ // selection_recorder records the selection bounds.
+ absl::optional<DrawingRecorder> recorder;
+ const auto& display_item_client =
+ AsDisplayItemClient(cursor_, selection != nullptr);
+ // Text clips are initiated only in BoxPainterBase::PaintFillLayer, which is
+ // already within a DrawingRecorder.
if (paint_info.phase != PaintPhase::kTextClip) {
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, display_item_client, paint_info.phase)) {
- return;
+ if (LIKELY(!paint_info.context.InDrawingRecorder())) {
+ if (DrawingRecorder::UseCachedDrawingIfPossible(
+ paint_info.context, display_item_client, paint_info.phase)) {
+ return;
+ }
+ recorder.emplace(paint_info.context, display_item_client,
+ paint_info.phase, visual_rect);
}
- recorder.emplace(paint_info.context, display_item_client, paint_info.phase,
- visual_rect);
}
if (UNLIKELY(text_item.IsSymbolMarker())) {
@@ -238,50 +269,62 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
// Determine text colors.
Node* node = layout_object->GetNode();
- DCHECK(!svg_inline_text ||
- (!IsA<SVGElement>(node) && IsA<SVGElement>(node->parentNode())));
TextPaintStyle text_style =
- svg_inline_text
- ? TextPainterBase::SvgTextPaintingStyle(
- document, SVGLengthContext(To<SVGElement>(node->parentNode())),
- style, paint_info)
- : TextPainterBase::TextPaintingStyle(document, style, paint_info);
- // TODO(crbug.com/1179585): Support SVG Paint Servers (e.g. Gradient, Pattern)
+ TextPainterBase::TextPaintingStyle(document, style, paint_info);
if (UNLIKELY(selection)) {
selection->ComputeSelectionStyle(document, style, node, paint_info,
text_style);
}
// Set our font.
- const Font& font =
- svg_inline_text ? svg_inline_text->ScaledFont() : style.GetFont();
+ const Font& font = UNLIKELY(svg_inline_text)
+ ? svg_inline_text->ScaledFont()
+ : UNLIKELY(text_combine)
+ ? text_combine->UsesCompressedFont()
+ ? text_combine->CompressedFont()
+ : style.GetFont()
+ : style.GetFont();
const SimpleFontData* font_data = font.PrimaryFont();
DCHECK(font_data);
const bool paint_marker_backgrounds =
paint_info.phase != PaintPhase::kSelectionDragImage &&
paint_info.phase != PaintPhase::kTextClip && !is_printing;
- absl::optional<GraphicsContextStateSaver> state_saver;
+ GraphicsContextStateSaver state_saver(context, /*save_and_restore=*/false);
absl::optional<AffineTransform> rotation;
const WritingMode writing_mode = style.GetWritingMode();
const bool is_horizontal = IsHorizontalWritingMode(writing_mode);
- int ascent = font_data ? font_data->GetFontMetrics().Ascent() : 0;
- PhysicalOffset text_origin(box_rect.offset.left,
- box_rect.offset.top + ascent);
- if (svg_inline_text && scaling_factor != 1.0f) {
- state_saver.emplace(context);
- context.Scale(1 / scaling_factor, 1 / scaling_factor);
- }
- if (text_item.HasSVGTransformForPaint()) {
- if (!state_saver)
- state_saver.emplace(context);
- context.ConcatCTM(text_item.BuildSVGTransformForPaint());
- }
+ const int ascent = font_data ? font_data->GetFontMetrics().Ascent() : 0;
+ PhysicalOffset text_origin(
+ box_rect.offset.left,
+ UNLIKELY(text_combine)
+ ? text_combine->AdjustTextTopForPaint(box_rect.offset.top)
+ : box_rect.offset.top + ascent);
+
NGTextPainter text_painter(context, font, fragment_paint_info, visual_rect,
text_origin, box_rect, is_horizontal);
- NGHighlightPainter highlight_painter(
- text_painter, paint_info, cursor_, *cursor_.CurrentItem(),
- box_rect.offset, style, std::move(selection), is_printing);
+ NGHighlightPainter highlight_painter(text_painter, paint_info, cursor_,
+ *cursor_.CurrentItem(), box_rect.offset,
+ style, selection, is_printing);
+
+ if (svg_inline_text) {
+ NGTextPainter::SvgTextPaintState& svg_state = text_painter.SetSvgState(
+ *svg_inline_text, style, paint_info.IsRenderingClipPathAsMaskImage());
+
+ if (scaling_factor != 1.0f) {
+ state_saver.SaveIfNeeded();
+ context.Scale(1 / scaling_factor, 1 / scaling_factor);
+ svg_state.EnsureShaderTransform().Scale(scaling_factor);
+ }
+ if (text_item.HasSvgTransformForPaint()) {
+ state_saver.SaveIfNeeded();
+ const auto fragment_transform = text_item.BuildSvgTransformForPaint();
+ context.ConcatCTM(fragment_transform);
+ DCHECK(fragment_transform.IsInvertible());
+ svg_state.EnsureShaderTransform().PreMultiply(
+ fragment_transform.Inverse());
+ }
+ }
// 1. Paint backgrounds for document markers that don’t participate in the CSS
// highlight overlay system, such as composition highlights. They use physical
@@ -289,21 +332,25 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
highlight_painter.Paint(NGHighlightPainter::kBackground);
if (!is_horizontal) {
- if (!state_saver)
- state_saver.emplace(context);
+ state_saver.SaveIfNeeded();
// Because we rotate the GraphicsContext to match the logical direction,
// transpose the |box_rect| to match to it.
box_rect.size = PhysicalSize(box_rect.Height(), box_rect.Width());
- rotation.emplace(TextPainterBase::Rotation(
- box_rect, writing_mode != WritingMode::kSidewaysLr
- ? TextPainterBase::kClockwise
- : TextPainterBase::kCounterclockwise));
+ rotation.emplace(TextPainterBase::Rotation(box_rect, writing_mode));
context.ConcatCTM(*rotation);
+ if (NGTextPainter::SvgTextPaintState* state = text_painter.GetSvgState()) {
+ DCHECK(rotation->IsInvertible());
+ state->EnsureShaderTransform().PreMultiply(rotation->Inverse());
+ }
}
if (UNLIKELY(highlight_painter.Selection())) {
PhysicalRect before_rotation =
highlight_painter.Selection()->ComputeSelectionRect(box_rect.offset);
+ if (scaling_factor != 1.0f) {
+ before_rotation.offset.Scale(1 / scaling_factor);
+ before_rotation.size.Scale(1 / scaling_factor);
+ }
// The selection rect is given in physical coordinates, so we need to map
// them into our now-possibly-rotated space before calling any methods
@@ -344,6 +391,7 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
&has_line_through_decoration);
text_painter.Paint(start_offset, end_offset, length, text_style, node_id);
if (has_line_through_decoration) {
+ DCHECK(!text_combine);
text_painter.PaintDecorationsOnlyLineThrough(
text_item, paint_info, style, text_style, box_rect, absl::nullopt);
}
@@ -375,6 +423,7 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
text_style, node_id);
if (has_line_through_decoration) {
+ DCHECK(!text_combine);
text_painter.PaintDecorationsOnlyLineThrough(
text_item, paint_info, style, text_style, box_rect,
highlight_painter.SelectionDecoration());
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 24047eed809..87af0ca8d3e 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
index 89650c6b601..69a63b78781 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
@@ -4,28 +4,114 @@
#include "third_party/blink/renderer/core/paint/ng/ng_text_painter.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h"
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
+#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/paint/applied_decoration_painter.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
+#include "third_party/blink/renderer/core/paint/svg_object_painter.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/shadow_list.h"
+#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.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/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
namespace blink {
namespace {
+class SelectionStyleScope {
+ STACK_ALLOCATED();
+
+ public:
+ SelectionStyleScope(LayoutObject&,
+ const ComputedStyle& style,
+ const ComputedStyle& selection_style);
+ SelectionStyleScope(const SelectionStyleScope&) = delete;
+ SelectionStyleScope& operator=(const SelectionStyleScope) = delete;
+ ~SelectionStyleScope();
+
+ private:
+ LayoutObject& layout_object_;
+ const ComputedStyle& selection_style_;
+ const bool styles_are_equal_;
+};
+
+SelectionStyleScope::SelectionStyleScope(LayoutObject& layout_object,
+ const ComputedStyle& style,
+ const ComputedStyle& selection_style)
+ : layout_object_(layout_object),
+ selection_style_(selection_style),
+ styles_are_equal_(style == selection_style) {
+ if (styles_are_equal_)
+ return;
+ DCHECK(!layout_object.IsSVGInlineText());
+ auto& element = To<SVGElement>(*layout_object_.GetNode());
+ SVGResources::UpdatePaints(element, nullptr, selection_style_);
+}
+
+SelectionStyleScope::~SelectionStyleScope() {
+ if (styles_are_equal_)
+ return;
+ auto& element = To<SVGElement>(*layout_object_.GetNode());
+ SVGResources::ClearPaints(element, &selection_style_);
+}
+
+bool SetupPaintForSvgText(const LayoutSVGInlineText& svg_inline_text,
+ const GraphicsContext& context,
+ bool is_rendering_clip_path_as_mask_image,
+ const ComputedStyle& style,
+ const AffineTransform* shader_transform,
+ LayoutSVGResourceMode resource_mode,
+ PaintFlags& flags) {
+ const LayoutObject* layout_parent = svg_inline_text.Parent();
+ if (!SVGObjectPainter(*layout_parent)
+ .PreparePaint(context, is_rendering_clip_path_as_mask_image, style,
+ resource_mode, flags, shader_transform)) {
+ return false;
+ }
+
+ flags.setAntiAlias(true);
+
+ if (style.TextShadow() &&
+ // Text shadows are disabled when printing. http://crbug.com/258321
+ !svg_inline_text.GetDocument().Printing()) {
+ flags.setLooper(TextPainterBase::CreateDrawLooper(
+ style.TextShadow(), DrawLooperBuilder::kShadowRespectsAlpha,
+ style.VisitedDependentColor(GetCSSPropertyColor()),
+ style.UsedColorScheme()));
+ }
+
+ if (resource_mode == kApplyToStrokeMode) {
+ // The stroke geometry needs be generated based on the scaled font.
+ float stroke_scale_factor =
+ style.VectorEffect() != EVectorEffect::kNonScalingStroke
+ ? svg_inline_text.ScalingFactor()
+ : 1;
+ StrokeData stroke_data;
+ SVGLayoutSupport::ApplyStrokeStyleToStrokeData(
+ stroke_data, style, *layout_parent, stroke_scale_factor);
+ if (stroke_scale_factor != 1)
+ stroke_data.SetThickness(stroke_data.Thickness() * stroke_scale_factor);
+ stroke_data.SetupPaint(&flags);
+ }
+
+ return true;
+}
+
absl::optional<TextDecorationInfo> DecorationsForLayer(
const NGFragmentItem& text_item,
const PhysicalRect& decoration_rect,
@@ -37,9 +123,9 @@ absl::optional<TextDecorationInfo> DecorationsForLayer(
text_item.IsEllipsis()) {
return absl::nullopt;
}
- return TextDecorationInfo(decoration_rect.offset, decoration_rect.offset,
- decoration_rect.Width(), style.GetFontBaseline(),
- style, selection_text_decoration, nullptr);
+ return TextDecorationInfo(decoration_rect.offset, decoration_rect.Width(),
+ style.GetFontBaseline(), style,
+ selection_text_decoration, nullptr);
}
} // namespace
@@ -87,6 +173,11 @@ void NGTextPainter::PaintSelectedText(unsigned start_offset,
// painting in most small text.
snapped_selection_rect.Inflate(1);
if (snapped_selection_rect.Contains(visual_rect_)) {
+ absl::optional<base::AutoReset<bool>> is_painting_selection_reset;
+ if (svg_text_paint_state_.has_value()) {
+ is_painting_selection_reset.emplace(
+ &svg_text_paint_state_->is_painting_selection_, true);
+ }
Paint(start_offset, end_offset, length, selection_style, node_id);
return;
}
@@ -109,6 +200,11 @@ void NGTextPainter::PaintSelectedText(unsigned start_offset,
}
// Then draw the glyphs inside the selection area, with the selection style.
{
+ absl::optional<base::AutoReset<bool>> is_painting_selection_reset;
+ if (svg_text_paint_state_.has_value()) {
+ is_painting_selection_reset.emplace(
+ &svg_text_paint_state_->is_painting_selection_, true);
+ }
GraphicsContextStateSaver state_saver(graphics_context_);
graphics_context_.Clip(float_selection_rect);
Paint(start_offset, end_offset, length, selection_style, node_id);
@@ -136,86 +232,9 @@ void NGTextPainter::PaintDecorationsExceptLineThrough(
const NGTextDecorationOffset decoration_offset(decoration_info->Style(),
text_item.Style(), nullptr);
- GraphicsContext& context = paint_info.context;
- GraphicsContextStateSaver state_saver(context);
- UpdateGraphicsContext(context, text_style, horizontal_, state_saver);
-
- if (has_combined_text_)
- context.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
-
- // text-underline-position may flip underline and overline.
- ResolvedUnderlinePosition underline_position =
- decoration_info->UnderlinePosition();
- bool flip_underline_and_overline = false;
- if (underline_position == ResolvedUnderlinePosition::kOver) {
- flip_underline_and_overline = true;
- underline_position = ResolvedUnderlinePosition::kUnder;
- }
-
- const Vector<AppliedTextDecoration>& decorations =
- style.AppliedTextDecorations();
- for (size_t applied_decoration_index = 0;
- applied_decoration_index < decorations.size();
- ++applied_decoration_index) {
- const AppliedTextDecoration& decoration =
- decorations[applied_decoration_index];
- TextDecoration lines = decoration.Lines();
- bool has_underline = EnumHasFlags(lines, TextDecoration::kUnderline);
- bool has_overline = EnumHasFlags(lines, TextDecoration::kOverline);
- if (flip_underline_and_overline)
- std::swap(has_underline, has_overline);
-
- decoration_info->SetDecorationIndex(applied_decoration_index);
-
- float resolved_thickness = decoration_info->ResolvedThickness();
- context.SetStrokeThickness(resolved_thickness);
-
- if (has_underline && decoration_info->FontData()) {
- // Don't apply text-underline-offset to overline.
- Length line_offset =
- flip_underline_and_overline ? Length() : decoration.UnderlineOffset();
-
- const int paint_underline_offset =
- decoration_offset.ComputeUnderlineOffset(
- underline_position, decoration_info->Style().ComputedFontSize(),
- decoration_info->FontData()->GetFontMetrics(), line_offset,
- resolved_thickness);
- decoration_info->SetPerLineData(
- TextDecoration::kUnderline, paint_underline_offset,
- TextDecorationInfo::DoubleOffsetFromThickness(resolved_thickness), 1);
- PaintDecorationUnderOrOverLine(context, *decoration_info,
- TextDecoration::kUnderline);
- }
-
- if (has_overline && decoration_info->FontData()) {
- // Don't apply text-underline-offset to overline.
- Length line_offset =
- flip_underline_and_overline ? decoration.UnderlineOffset() : Length();
-
- FontVerticalPositionType position =
- flip_underline_and_overline ? FontVerticalPositionType::TopOfEmHeight
- : FontVerticalPositionType::TextTop;
- const int paint_overline_offset =
- decoration_offset.ComputeUnderlineOffsetForUnder(
- line_offset, decoration_info->Style().ComputedFontSize(),
- resolved_thickness, position);
- decoration_info->SetPerLineData(
- TextDecoration::kOverline, paint_overline_offset,
- -TextDecorationInfo::DoubleOffsetFromThickness(resolved_thickness),
- 1);
- PaintDecorationUnderOrOverLine(context, *decoration_info,
- TextDecoration::kOverline);
- }
-
- // We could instead build a vector of the TextDecoration instances needing
- // line-through but this is a rare case so better to avoid vector overhead.
- *has_line_through_decoration |=
- EnumHasFlags(lines, TextDecoration::kLineThrough);
- }
-
- // Restore rotation as needed.
- if (has_combined_text_)
- context.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise));
+ TextPainterBase::PaintDecorationsExceptLineThrough(
+ decoration_offset, *decoration_info, paint_info,
+ style.AppliedTextDecorations(), text_style, has_line_through_decoration);
}
// Based on legacy TextPainter.
@@ -231,55 +250,8 @@ void NGTextPainter::PaintDecorationsOnlyLineThrough(
DCHECK(decoration_info);
- const NGTextDecorationOffset decoration_offset(decoration_info->Style(),
- text_item.Style(), nullptr);
-
- GraphicsContext& context = paint_info.context;
- GraphicsContextStateSaver state_saver(context);
- UpdateGraphicsContext(context, text_style, horizontal_, state_saver);
-
- if (has_combined_text_)
- context.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
-
- const Vector<AppliedTextDecoration>& decorations =
- style.AppliedTextDecorations();
- for (size_t applied_decoration_index = 0;
- applied_decoration_index < decorations.size();
- ++applied_decoration_index) {
- const AppliedTextDecoration& decoration =
- decorations[applied_decoration_index];
- TextDecoration lines = decoration.Lines();
- if (EnumHasFlags(lines, TextDecoration::kLineThrough)) {
- decoration_info->SetDecorationIndex(applied_decoration_index);
-
- float resolved_thickness = decoration_info->ResolvedThickness();
- context.SetStrokeThickness(resolved_thickness);
-
- // For increased line thickness, the line-through decoration needs to grow
- // in both directions from its origin, subtract half the thickness to keep
- // it centered at the same origin.
- const float line_through_offset =
- 2 * decoration_info->Baseline() / 3 - resolved_thickness / 2;
- // Floor double_offset in order to avoid double-line gap to appear
- // of different size depending on position where the double line
- // is drawn because of rounding downstream in
- // GraphicsContext::DrawLineForText.
- decoration_info->SetPerLineData(
- TextDecoration::kLineThrough, line_through_offset,
- floorf(TextDecorationInfo::DoubleOffsetFromThickness(
- resolved_thickness)),
- 0);
- AppliedDecorationPainter decoration_painter(context, *decoration_info,
- TextDecoration::kLineThrough);
- // No skip: ink for line-through,
- // compare https://github.com/w3c/csswg-drafts/issues/711
- decoration_painter.Paint();
- }
- }
-
- // Restore rotation as needed.
- if (has_combined_text_)
- context.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise));
+ TextPainterBase::PaintDecorationsOnlyLineThrough(
+ *decoration_info, paint_info, style.AppliedTextDecorations(), text_style);
}
template <NGTextPainter::PaintInternalStep step>
@@ -299,8 +271,12 @@ void NGTextPainter::PaintInternalFragment(
FloatPoint(text_origin_) + IntSize(0, emphasis_mark_offset_));
} else {
DCHECK(step == kPaintText);
- graphics_context_.DrawText(font_, fragment_paint_info_,
- FloatPoint(text_origin_), node_id);
+ if (svg_text_paint_state_.has_value()) {
+ PaintSvgTextFragment(node_id);
+ } else {
+ graphics_context_.DrawText(font_, fragment_paint_info_,
+ FloatPoint(text_origin_), node_id);
+ }
// TODO(npm): Check that there are non-whitespace characters. See
// crbug.com/788444.
graphics_context_.GetPaintController().SetTextPainted();
@@ -347,6 +323,113 @@ void NGTextPainter::ClipDecorationsStripe(float upper,
DecorationsStripeIntercepts(upper, stripe_width, dilation, text_intercepts);
}
-void NGTextPainter::PaintEmphasisMarkForCombinedText() {}
+void NGTextPainter::PaintSvgTextFragment(DOMNodeId node_id) {
+ const NGTextPainter::SvgTextPaintState& state = *svg_text_paint_state_;
+ absl::optional<SelectionStyleScope> selection_style_scope;
+ bool has_fill = state.Style().HasFill();
+ bool has_visible_stroke = state.Style().HasVisibleStroke();
+ const ComputedStyle* style_to_paint = &state.Style();
+ if (state.IsPaintingSelection()) {
+ LayoutObject* layout_parent = state.InlineText().Parent();
+ style_to_paint =
+ layout_parent->GetCachedPseudoElementStyle(kPseudoIdSelection);
+ if (style_to_paint) {
+ if (!has_fill)
+ has_fill = style_to_paint->HasFill();
+ if (!has_visible_stroke)
+ has_visible_stroke = style_to_paint->HasVisibleStroke();
+ } else {
+ style_to_paint = &state.Style();
+ }
+
+ selection_style_scope.emplace(*layout_parent, state.Style(),
+ *style_to_paint);
+ }
+
+ if (state.IsRenderingClipPathAsMaskImage()) {
+ has_fill = true;
+ has_visible_stroke = false;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ absl::optional<LayoutSVGResourceMode> resource_mode;
+
+ switch (state.Style().PaintOrderType(i)) {
+ case PT_FILL:
+ if (has_fill)
+ resource_mode = kApplyToFillMode;
+ break;
+ case PT_STROKE:
+ if (has_visible_stroke)
+ resource_mode = kApplyToStrokeMode;
+ break;
+ case PT_MARKERS:
+ // Markers don't apply to text
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ if (resource_mode) {
+ PaintFlags flags;
+ if (SetupPaintForSvgText(state.InlineText(), graphics_context_,
+ state.IsRenderingClipPathAsMaskImage(),
+ *style_to_paint, state.GetShaderTransform(),
+ *resource_mode, flags)) {
+ graphics_context_.DrawText(font_, fragment_paint_info_,
+ FloatPoint(text_origin_), flags, node_id);
+ }
+ }
+ }
+}
+
+NGTextPainter::SvgTextPaintState& NGTextPainter::SetSvgState(
+ const LayoutSVGInlineText& svg_inline_text,
+ const ComputedStyle& style,
+ bool is_rendering_clip_path_as_mask_image) {
+ return svg_text_paint_state_.emplace(svg_inline_text, style,
+ is_rendering_clip_path_as_mask_image);
+}
+
+NGTextPainter::SvgTextPaintState* NGTextPainter::GetSvgState() {
+ return base::OptionalOrNullptr(svg_text_paint_state_);
+}
+
+NGTextPainter::SvgTextPaintState::SvgTextPaintState(
+ const LayoutSVGInlineText& layout_svg_inline_text,
+ const ComputedStyle& style,
+ bool is_rendering_clip_path_as_mask_image)
+ : layout_svg_inline_text_(layout_svg_inline_text),
+ style_(style),
+ is_rendering_clip_path_as_mask_image_(
+ is_rendering_clip_path_as_mask_image) {}
+
+const LayoutSVGInlineText& NGTextPainter::SvgTextPaintState::InlineText()
+ const {
+ return layout_svg_inline_text_;
+}
+
+const ComputedStyle& NGTextPainter::SvgTextPaintState::Style() const {
+ return style_;
+}
+
+bool NGTextPainter::SvgTextPaintState::IsPaintingSelection() const {
+ return is_painting_selection_;
+}
+
+bool NGTextPainter::SvgTextPaintState::IsRenderingClipPathAsMaskImage() const {
+ return is_rendering_clip_path_as_mask_image_;
+}
+
+AffineTransform& NGTextPainter::SvgTextPaintState::EnsureShaderTransform() {
+ return shader_transform_ ? shader_transform_.value()
+ : shader_transform_.emplace();
+}
+
+const AffineTransform* NGTextPainter::SvgTextPaintState::GetShaderTransform()
+ const {
+ return base::OptionalOrNullptr(shader_transform_);
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.h
index 42e8bc6ad2a..26b4bb67899 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.h
@@ -12,6 +12,7 @@
namespace blink {
+class LayoutSVGInlineText;
class NGFragmentItem;
struct NGTextFragmentPaintInfo;
@@ -24,6 +25,29 @@ class CORE_EXPORT NGTextPainter : public TextPainterBase {
STACK_ALLOCATED();
public:
+ class SvgTextPaintState final {
+ public:
+ SvgTextPaintState(const LayoutSVGInlineText&,
+ const ComputedStyle&,
+ bool is_rendering_clip_path_as_mask_image);
+
+ const LayoutSVGInlineText& InlineText() const;
+ const ComputedStyle& Style() const;
+ bool IsPaintingSelection() const;
+ bool IsRenderingClipPathAsMaskImage() const;
+
+ AffineTransform& EnsureShaderTransform();
+ const AffineTransform* GetShaderTransform() const;
+
+ private:
+ const LayoutSVGInlineText& layout_svg_inline_text_;
+ const ComputedStyle& style_;
+ absl::optional<AffineTransform> shader_transform_;
+ bool is_painting_selection_ = false;
+ bool is_rendering_clip_path_as_mask_image_ = false;
+ friend class NGTextPainter;
+ };
+
NGTextPainter(GraphicsContext& context,
const Font& font,
const NGTextFragmentPaintInfo& fragment_paint_info,
@@ -58,7 +82,6 @@ class CORE_EXPORT NGTextPainter : public TextPainterBase {
const PhysicalRect& selection_rect,
DOMNodeId node_id);
- // Based on legacy TextPainter.
void PaintDecorationsExceptLineThrough(
const NGFragmentItem& text_item,
const PaintInfo& paint_info,
@@ -68,7 +91,6 @@ class CORE_EXPORT NGTextPainter : public TextPainterBase {
const absl::optional<AppliedTextDecoration>& selection_decoration,
bool* has_line_through_decoration);
- // Based on legacy TextPainter.
void PaintDecorationsOnlyLineThrough(
const NGFragmentItem& text_item,
const PaintInfo& paint_info,
@@ -77,6 +99,11 @@ class CORE_EXPORT NGTextPainter : public TextPainterBase {
const PhysicalRect& decoration_rect,
const absl::optional<AppliedTextDecoration>& selection_decoration);
+ SvgTextPaintState& SetSvgState(const LayoutSVGInlineText&,
+ const ComputedStyle&,
+ bool is_rendering_clip_path_as_mask_image);
+ SvgTextPaintState* GetSvgState();
+
private:
template <PaintInternalStep step>
void PaintInternalFragment(unsigned from, unsigned to, DOMNodeId node_id);
@@ -87,10 +114,11 @@ class CORE_EXPORT NGTextPainter : public TextPainterBase {
unsigned truncation_point,
DOMNodeId node_id);
- void PaintEmphasisMarkForCombinedText();
+ void PaintSvgTextFragment(DOMNodeId node_id);
NGTextFragmentPaintInfo fragment_paint_info_;
const IntRect& visual_rect_;
+ absl::optional<SvgTextPaintState> svg_text_paint_state_;
};
} // namespace blink
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 292c087dcb2..d6637d60483 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
@@ -40,9 +40,7 @@ struct TileParameters {
absl::optional<TileParameters> ComputeTileParameters(
ENinePieceImageRule tile_rule,
- float dst_pos,
float dst_extent,
- float src_pos,
float src_extent,
float in_scale_factor) {
switch (tile_rule) {
@@ -50,14 +48,13 @@ absl::optional<TileParameters> ComputeTileParameters(
float repetitions =
std::max(1.0f, roundf(dst_extent / (src_extent * in_scale_factor)));
float scale_factor = dst_extent / (src_extent * repetitions);
- return TileParameters{scale_factor, src_pos * scale_factor, 0};
+ return TileParameters{scale_factor, 0, 0};
}
case kRepeatImageRule: {
float scaled_tile_extent = src_extent * in_scale_factor;
// We want to construct the phase such that the pattern is centered (when
// stretch is not set for a particular rule).
- float phase = src_pos * in_scale_factor;
- phase -= (dst_extent - scaled_tile_extent) / 2;
+ float phase = (dst_extent - scaled_tile_extent) / 2;
return TileParameters{in_scale_factor, phase, 0};
}
case kSpaceImageRule: {
@@ -65,10 +62,10 @@ absl::optional<TileParameters> ComputeTileParameters(
CalculateSpaceNeeded(dst_extent, src_extent);
if (!spacing)
return absl::nullopt;
- return TileParameters{1, src_pos - *spacing, *spacing};
+ return TileParameters{1, *spacing, *spacing};
}
case kStretchImageRule:
- return TileParameters{in_scale_factor, src_pos * in_scale_factor, 0};
+ return TileParameters{in_scale_factor, 0, 0};
default:
NOTREACHED();
}
@@ -124,35 +121,41 @@ void PaintPieces(GraphicsContext& context,
// Since there is no way for the developer to specify decode behavior,
// use kSync by default.
context.DrawImage(image, Image::kSyncDecode, draw_info.destination,
- &draw_info.source, style.HasFilterInducingProperty());
+ &draw_info.source, style.DisableForceDark());
continue;
}
// TODO(cavalcantii): see crbug.com/662513.
absl::optional<TileParameters> h_tile = ComputeTileParameters(
- draw_info.tile_rule.horizontal, draw_info.destination.X(),
- draw_info.destination.Width(), draw_info.source.X(),
+ draw_info.tile_rule.horizontal, draw_info.destination.Width(),
draw_info.source.Width(), draw_info.tile_scale.Width());
absl::optional<TileParameters> v_tile = ComputeTileParameters(
- draw_info.tile_rule.vertical, draw_info.destination.Y(),
- draw_info.destination.Height(), draw_info.source.Y(),
+ draw_info.tile_rule.vertical, draw_info.destination.Height(),
draw_info.source.Height(), draw_info.tile_scale.Height());
if (!h_tile || !v_tile)
continue;
- FloatSize tile_scale_factor(h_tile->scale_factor, v_tile->scale_factor);
- FloatPoint tile_phase(draw_info.destination.X() - h_tile->phase,
- draw_info.destination.Y() - v_tile->phase);
- FloatSize tile_spacing(h_tile->spacing, v_tile->spacing);
-
// TODO(cavalcantii): see crbug.com/662507.
absl::optional<ScopedInterpolationQuality> interpolation_quality_override;
if (draw_info.tile_rule.horizontal == kRoundImageRule ||
draw_info.tile_rule.vertical == kRoundImageRule)
interpolation_quality_override.emplace(context, kInterpolationMedium);
- context.DrawImageTiled(image, draw_info.destination, draw_info.source,
- tile_scale_factor, tile_phase, tile_spacing);
+ ImageTilingInfo tiling_info;
+ tiling_info.image_rect = draw_info.source;
+ tiling_info.scale = FloatSize(h_tile->scale_factor, v_tile->scale_factor);
+ // The phase defines the origin of the whole image - not the image
+ // rect (see ImageTilingInfo) - so we need to adjust it to account
+ // for that.
+ FloatPoint tile_origin_in_dest_space = draw_info.source.Location();
+ tile_origin_in_dest_space.Scale(tiling_info.scale.Width(),
+ tiling_info.scale.Height());
+ tiling_info.phase =
+ draw_info.destination.Location() +
+ (FloatPoint(h_tile->phase, v_tile->phase) - tile_origin_in_dest_space);
+ tiling_info.spacing = FloatSize(h_tile->spacing, v_tile->spacing);
+
+ context.DrawImageTiled(image, draw_info.destination, tiling_info);
}
}
@@ -189,9 +192,8 @@ bool NinePieceImagePainter::Paint(GraphicsContext& graphics_context,
// image with either "native" size (raster images) or size scaled by effective
// zoom.
const FloatSize default_object_size(border_image_rect.size);
- FloatSize image_size =
- style_image->ImageSize(document, style.EffectiveZoom(),
- default_object_size, kRespectImageOrientation);
+ FloatSize image_size = style_image->ImageSize(
+ style.EffectiveZoom(), default_object_size, kRespectImageOrientation);
scoped_refptr<Image> image =
style_image->GetImage(observer, document, style, image_size);
if (!image)
@@ -201,7 +203,7 @@ bool NinePieceImagePainter::Paint(GraphicsContext& graphics_context,
// yield the size in CSS pixels. This is the unit/scale we expect the
// 'border-image-slice' values to be in.
FloatSize unzoomed_image_size = style_image->ImageSize(
- document, 1, default_object_size.ScaledBy(1 / style.EffectiveZoom()),
+ 1, default_object_size.ScaledBy(1 / style.EffectiveZoom()),
kRespectImageOrientation);
DEVTOOLS_TIMELINE_TRACE_EVENT_WITH_CATEGORIES(
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 c4afc37d1ab..bc53051bc14 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
@@ -7,7 +7,6 @@
#include "base/auto_reset.h"
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h"
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 7e0d9f6d0b1..a41e8898545 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
@@ -225,7 +225,8 @@ class CORE_EXPORT ObjectPaintProperties {
public:
#if DCHECK_IS_ON()
- // Used by FindPropertiesNeedingUpdate.h for verifying state doesn't change.
+ // Used by find_properties_needing_update.h for verifying state doesn't
+ // change.
void SetImmutable() const { is_immutable_ = true; }
bool IsImmutable() const { return is_immutable_; }
void SetMutable() const { is_immutable_ = false; }
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 a59fa4d19f7..51893f575e7 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
+#include "third_party/blink/renderer/core/paint/outline_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -50,7 +51,8 @@ void ObjectPainter::PaintOutline(const PaintInfo& paint_info,
visual_rect.Inflate(style_to_use.OutlineOutsetExtent());
DrawingRecorder recorder(paint_info.context, layout_object_, paint_info.phase,
visual_rect);
- PaintOutlineRects(paint_info, outline_rects, style_to_use);
+ OutlinePainter::PaintOutlineRects(paint_info.context, outline_rects,
+ style_to_use);
}
void ObjectPainter::PaintInlineChildrenOutlines(const PaintInfo& paint_info) {
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 25a0c8b3ccb..5d001b57a13 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_OBJECT_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_OBJECT_PAINTER_H_
-#include "third_party/blink/renderer/core/paint/object_painter_base.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -15,7 +14,7 @@ class LayoutObject;
struct PaintInfo;
struct PhysicalOffset;
-class ObjectPainter : public ObjectPainterBase {
+class ObjectPainter {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc b/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc
deleted file mode 100644
index 1029ef5e606..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc
+++ /dev/null
@@ -1,666 +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/object_painter_base.h"
-
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/core/paint/box_border_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/style/border_edge.h"
-#include "third_party/blink/renderer/core/style/computed_style.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"
-#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
-#include "ui/base/ui_base_features.h"
-#include "ui/native_theme/native_theme.h"
-
-namespace blink {
-
-namespace {
-
-struct OutlineEdgeInfo {
- int x1;
- int y1;
- int x2;
- int y2;
- BoxSide side;
-};
-
-// Adjust length of edges if needed. Returns the width of the joint.
-int AdjustJoint(int outline_width,
- OutlineEdgeInfo& edge1,
- OutlineEdgeInfo& edge2) {
- // A clockwise joint:
- // - needs no adjustment of edge length because our edges are along the
- // clockwise outer edge of the outline;
- // - needs a positive adjacent joint width (required by
- // ObjectPainterBase::DrawLineForBoxSide). A counterclockwise joint: - needs
- // to increase the edge length to include the joint; - needs a negative
- // adjacent joint width (required by ObjectPainterBase::DrawLineForBoxSide).
- switch (edge1.side) {
- case BoxSide::kTop:
- switch (edge2.side) {
- case BoxSide::kRight: // Clockwise
- return outline_width;
- case BoxSide::kLeft: // Counterclockwise
- edge1.x2 += outline_width;
- edge2.y2 += outline_width;
- return -outline_width;
- default: // Same side or no joint.
- return 0;
- }
- case BoxSide::kRight:
- switch (edge2.side) {
- case BoxSide::kBottom: // Clockwise
- return outline_width;
- case BoxSide::kTop: // Counterclockwise
- edge1.y2 += outline_width;
- edge2.x1 -= outline_width;
- return -outline_width;
- default: // Same side or no joint.
- return 0;
- }
- case BoxSide::kBottom:
- switch (edge2.side) {
- case BoxSide::kLeft: // Clockwise
- return outline_width;
- case BoxSide::kRight: // Counterclockwise
- edge1.x1 -= outline_width;
- edge2.y1 -= outline_width;
- return -outline_width;
- default: // Same side or no joint.
- return 0;
- }
- case BoxSide::kLeft:
- switch (edge2.side) {
- case BoxSide::kTop: // Clockwise
- return outline_width;
- case BoxSide::kBottom: // Counterclockwise
- edge1.y1 -= outline_width;
- edge2.x2 += outline_width;
- return -outline_width;
- default: // Same side or no joint.
- return 0;
- }
- default:
- NOTREACHED();
- return 0;
- }
-}
-
-void ApplyOutlineOffset(IntRect& rect, int offset) {
- // A negative outline-offset should not cause the rendered outline shape to
- // become smaller than twice the computed value of the outline-width, in each
- // direction separately. See: https://drafts.csswg.org/css-ui/#outline-offset
- rect.InflateX(std::max(offset, -rect.Width() / 2));
- rect.InflateY(std::max(offset, -rect.Height() / 2));
-}
-
-void PaintComplexOutline(GraphicsContext& graphics_context,
- const Vector<IntRect> rects,
- const ComputedStyle& style,
- const Color& color) {
- DCHECK(!style.OutlineStyleIsAuto());
-
- // Construct a clockwise path along the outer edge of the outline.
- SkRegion region;
- uint16_t width = style.OutlineWidthInt();
- int offset = style.OutlineOffsetInt();
- for (auto& r : rects) {
- IntRect rect = r;
- ApplyOutlineOffset(rect, offset);
- rect.Inflate(width);
- region.op(rect, SkRegion::kUnion_Op);
- }
- SkPath path;
- if (!region.getBoundaryPath(&path))
- return;
-
- Vector<OutlineEdgeInfo, 4> edges;
-
- SkPath::RawIter iter(path);
- SkPoint points[4], first_point, last_point;
- wtf_size_t count = 0;
- for (SkPath::Verb verb = iter.next(points); verb != SkPath::kDone_Verb;
- verb = iter.next(points)) {
- // Keep track of the first and last point of each contour (started with
- // kMove_Verb) so we can add the closing-line on kClose_Verb.
- if (verb == SkPath::kMove_Verb) {
- first_point = points[0];
- last_point = first_point; // this gets reset after each line, but we
- // initialize it here
- } else if (verb == SkPath::kClose_Verb) {
- // create an artificial line to close the contour
- verb = SkPath::kLine_Verb;
- points[0] = last_point;
- points[1] = first_point;
- }
- if (verb != SkPath::kLine_Verb)
- continue;
- last_point = points[1];
-
- edges.Grow(++count);
- OutlineEdgeInfo& edge = edges.back();
- edge.x1 = SkScalarTruncToInt(points[0].x());
- edge.y1 = SkScalarTruncToInt(points[0].y());
- edge.x2 = SkScalarTruncToInt(points[1].x());
- edge.y2 = SkScalarTruncToInt(points[1].y());
- if (edge.x1 == edge.x2) {
- if (edge.y1 < edge.y2) {
- edge.x1 -= width;
- edge.side = BoxSide::kRight;
- } else {
- std::swap(edge.y1, edge.y2);
- edge.x2 += width;
- edge.side = BoxSide::kLeft;
- }
- } else {
- DCHECK(edge.y1 == edge.y2);
- if (edge.x1 < edge.x2) {
- edge.y2 += width;
- edge.side = BoxSide::kTop;
- } else {
- std::swap(edge.x1, edge.x2);
- edge.y1 -= width;
- edge.side = BoxSide::kBottom;
- }
- }
- }
-
- if (!count)
- return;
-
- Color outline_color = color;
- bool use_transparency_layer = color.HasAlpha();
- if (use_transparency_layer) {
- graphics_context.BeginLayer(static_cast<float>(color.Alpha()) / 255);
- outline_color =
- Color(outline_color.Red(), outline_color.Green(), outline_color.Blue());
- }
-
- DCHECK(count >= 4 && edges.size() == count);
- int first_adjacent_width = AdjustJoint(width, edges.back(), edges.front());
-
- // The width of the angled part of starting and ending joint of the current
- // edge.
- int adjacent_width_start = first_adjacent_width;
- int adjacent_width_end;
- for (wtf_size_t i = 0; i < count; ++i) {
- OutlineEdgeInfo& edge = edges[i];
- adjacent_width_end = i == count - 1
- ? first_adjacent_width
- : AdjustJoint(width, edge, edges[i + 1]);
- int adjacent_width1 = adjacent_width_start;
- int adjacent_width2 = adjacent_width_end;
- if (edge.side == BoxSide::kLeft || edge.side == BoxSide::kBottom)
- std::swap(adjacent_width1, adjacent_width2);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, edge.x1, edge.y1, edge.x2, edge.y2, edge.side,
- outline_color, style.OutlineStyle(), adjacent_width1, adjacent_width2,
- false);
- adjacent_width_start = adjacent_width_end;
- }
-
- if (use_transparency_layer)
- graphics_context.EndLayer();
-}
-
-void PaintSingleRectangleOutline(const PaintInfo& paint_info,
- const IntRect& rect,
- const ComputedStyle& style,
- const Color& color) {
- DCHECK(!style.OutlineStyleIsAuto());
-
- IntRect offset_rect = rect;
- ApplyOutlineOffset(offset_rect, style.OutlineOffsetInt());
-
- PhysicalRect inner(offset_rect);
- PhysicalRect outer(inner);
- outer.Inflate(LayoutUnit(style.OutlineWidthInt()));
- const BorderEdge common_edge_info(style.OutlineWidthInt(), color,
- style.OutlineStyle());
- BoxBorderPainter(style, outer, inner, common_edge_info)
- .PaintBorder(paint_info, outer);
-}
-
-void FillQuad(GraphicsContext& context,
- const FloatPoint quad[],
- const Color& color,
- bool antialias) {
- SkPathBuilder path;
- path.moveTo(FloatPointToSkPoint(quad[0]));
- path.lineTo(FloatPointToSkPoint(quad[1]));
- path.lineTo(FloatPointToSkPoint(quad[2]));
- path.lineTo(FloatPointToSkPoint(quad[3]));
- PaintFlags flags(context.FillFlags());
- flags.setAntiAlias(antialias);
- flags.setColor(color.Rgb());
-
- context.DrawPath(path.detach(), flags);
-}
-
-void DrawDashedOrDottedBoxSide(GraphicsContext& graphics_context,
- int x1,
- int y1,
- int x2,
- int y2,
- BoxSide side,
- Color color,
- int thickness,
- EBorderStyle style,
- bool antialias) {
- DCHECK_GT(thickness, 0);
-
- GraphicsContextStateSaver state_saver(graphics_context);
- graphics_context.SetShouldAntialias(antialias);
- graphics_context.SetStrokeColor(color);
- graphics_context.SetStrokeThickness(thickness);
- graphics_context.SetStrokeStyle(
- style == EBorderStyle::kDashed ? kDashedStroke : kDottedStroke);
-
- switch (side) {
- case BoxSide::kBottom:
- case BoxSide::kTop: {
- int mid_y = y1 + thickness / 2;
- graphics_context.DrawLine(IntPoint(x1, mid_y), IntPoint(x2, mid_y));
- break;
- }
- case BoxSide::kRight:
- case BoxSide::kLeft: {
- int mid_x = x1 + thickness / 2;
- graphics_context.DrawLine(IntPoint(mid_x, y1), IntPoint(mid_x, y2));
- break;
- }
- }
-}
-
-void DrawDoubleBoxSide(GraphicsContext& graphics_context,
- int x1,
- int y1,
- int x2,
- int y2,
- int length,
- BoxSide side,
- Color color,
- float thickness,
- int adjacent_width1,
- int adjacent_width2,
- bool antialias) {
- int third_of_thickness = (thickness + 1) / 3;
- DCHECK_GT(third_of_thickness, 0);
-
- if (!adjacent_width1 && !adjacent_width2) {
- StrokeStyle old_stroke_style = graphics_context.GetStrokeStyle();
- graphics_context.SetStrokeStyle(kNoStroke);
- graphics_context.SetFillColor(color);
-
- bool was_antialiased = graphics_context.ShouldAntialias();
- graphics_context.SetShouldAntialias(antialias);
-
- switch (side) {
- case BoxSide::kTop:
- case BoxSide::kBottom:
- graphics_context.DrawRect(IntRect(x1, y1, length, third_of_thickness));
- graphics_context.DrawRect(
- IntRect(x1, y2 - third_of_thickness, length, third_of_thickness));
- break;
- case BoxSide::kLeft:
- case BoxSide::kRight:
- graphics_context.DrawRect(IntRect(x1, y1, third_of_thickness, length));
- graphics_context.DrawRect(
- IntRect(x2 - third_of_thickness, y1, third_of_thickness, length));
- break;
- }
-
- graphics_context.SetShouldAntialias(was_antialiased);
- graphics_context.SetStrokeStyle(old_stroke_style);
- return;
- }
-
- int adjacent1_big_third =
- ((adjacent_width1 > 0) ? adjacent_width1 + 1 : adjacent_width1 - 1) / 3;
- int adjacent2_big_third =
- ((adjacent_width2 > 0) ? adjacent_width2 + 1 : adjacent_width2 - 1) / 3;
-
- switch (side) {
- case BoxSide::kTop:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0),
- y1, x2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0),
- y1 + third_of_thickness, side, color, EBorderStyle::kSolid,
- adjacent1_big_third, adjacent2_big_third, antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max((adjacent_width1 * 2 + 1) / 3, 0),
- y2 - third_of_thickness,
- x2 - std::max((adjacent_width2 * 2 + 1) / 3, 0), y2, side, color,
- EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
- antialias);
- break;
- case BoxSide::kLeft:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1,
- y1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0),
- x1 + third_of_thickness,
- y2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0), side, color,
- EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
- antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x2 - third_of_thickness,
- y1 + std::max((adjacent_width1 * 2 + 1) / 3, 0), x2,
- y2 - std::max((adjacent_width2 * 2 + 1) / 3, 0), side, color,
- EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
- antialias);
- break;
- case BoxSide::kBottom:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max((adjacent_width1 * 2 + 1) / 3, 0), y1,
- x2 - std::max((adjacent_width2 * 2 + 1) / 3, 0),
- y1 + third_of_thickness, side, color, EBorderStyle::kSolid,
- adjacent1_big_third, adjacent2_big_third, antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0),
- y2 - third_of_thickness,
- x2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0), y2, side, color,
- EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
- antialias);
- break;
- case BoxSide::kRight:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1, y1 + std::max((adjacent_width1 * 2 + 1) / 3, 0),
- x1 + third_of_thickness,
- y2 - std::max((adjacent_width2 * 2 + 1) / 3, 0), side, color,
- EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
- antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x2 - third_of_thickness,
- y1 + std::max((-adjacent_width1 * 2 + 1) / 3, 0), x2,
- y2 - std::max((-adjacent_width2 * 2 + 1) / 3, 0), side, color,
- EBorderStyle::kSolid, adjacent1_big_third, adjacent2_big_third,
- antialias);
- break;
- default:
- break;
- }
-}
-
-void DrawRidgeOrGrooveBoxSide(GraphicsContext& graphics_context,
- int x1,
- int y1,
- int x2,
- int y2,
- BoxSide side,
- Color color,
- EBorderStyle style,
- int adjacent_width1,
- int adjacent_width2,
- bool antialias) {
- EBorderStyle s1;
- EBorderStyle s2;
- if (style == EBorderStyle::kGroove) {
- s1 = EBorderStyle::kInset;
- s2 = EBorderStyle::kOutset;
- } else {
- s1 = EBorderStyle::kOutset;
- s2 = EBorderStyle::kInset;
- }
-
- int adjacent1_big_half =
- ((adjacent_width1 > 0) ? adjacent_width1 + 1 : adjacent_width1 - 1) / 2;
- int adjacent2_big_half =
- ((adjacent_width2 > 0) ? adjacent_width2 + 1 : adjacent_width2 - 1) / 2;
-
- switch (side) {
- case BoxSide::kTop:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max(-adjacent_width1, 0) / 2, y1,
- x2 - std::max(-adjacent_width2, 0) / 2, (y1 + y2 + 1) / 2, side,
- color, s1, adjacent1_big_half, adjacent2_big_half, antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max(adjacent_width1 + 1, 0) / 2,
- (y1 + y2 + 1) / 2, x2 - std::max(adjacent_width2 + 1, 0) / 2, y2,
- side, color, s2, adjacent_width1 / 2, adjacent_width2 / 2, antialias);
- break;
- case BoxSide::kLeft:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1, y1 + std::max(-adjacent_width1, 0) / 2,
- (x1 + x2 + 1) / 2, y2 - std::max(-adjacent_width2, 0) / 2, side,
- color, s1, adjacent1_big_half, adjacent2_big_half, antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, (x1 + x2 + 1) / 2,
- y1 + std::max(adjacent_width1 + 1, 0) / 2, x2,
- y2 - std::max(adjacent_width2 + 1, 0) / 2, side, color, s2,
- adjacent_width1 / 2, adjacent_width2 / 2, antialias);
- break;
- case BoxSide::kBottom:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max(adjacent_width1, 0) / 2, y1,
- x2 - std::max(adjacent_width2, 0) / 2, (y1 + y2 + 1) / 2, side, color,
- s2, adjacent1_big_half, adjacent2_big_half, antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1 + std::max(-adjacent_width1 + 1, 0) / 2,
- (y1 + y2 + 1) / 2, x2 - std::max(-adjacent_width2 + 1, 0) / 2, y2,
- side, color, s1, adjacent_width1 / 2, adjacent_width2 / 2, antialias);
- break;
- case BoxSide::kRight:
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, x1, y1 + std::max(adjacent_width1, 0) / 2,
- (x1 + x2 + 1) / 2, y2 - std::max(adjacent_width2, 0) / 2, side, color,
- s2, adjacent1_big_half, adjacent2_big_half, antialias);
- ObjectPainterBase::DrawLineForBoxSide(
- graphics_context, (x1 + x2 + 1) / 2,
- y1 + std::max(-adjacent_width1 + 1, 0) / 2, x2,
- y2 - std::max(-adjacent_width2 + 1, 0) / 2, side, color, s1,
- adjacent_width1 / 2, adjacent_width2 / 2, antialias);
- break;
- }
-}
-
-void DrawSolidBoxSide(GraphicsContext& graphics_context,
- int x1,
- int y1,
- int x2,
- int y2,
- BoxSide side,
- Color color,
- int adjacent_width1,
- int adjacent_width2,
- bool antialias) {
- DCHECK_GE(x2, x1);
- DCHECK_GE(y2, y1);
-
- if (!adjacent_width1 && !adjacent_width2) {
- // Tweak antialiasing to match the behavior of fillQuad();
- // this matters for rects in transformed contexts.
- bool was_antialiased = graphics_context.ShouldAntialias();
- if (antialias != was_antialiased)
- graphics_context.SetShouldAntialias(antialias);
- graphics_context.FillRect(IntRect(x1, y1, x2 - x1, y2 - y1), color);
- if (antialias != was_antialiased)
- graphics_context.SetShouldAntialias(was_antialiased);
- return;
- }
-
- FloatPoint quad[4];
- switch (side) {
- case BoxSide::kTop:
- quad[0] = FloatPoint(x1 + std::max(-adjacent_width1, 0), y1);
- quad[1] = FloatPoint(x1 + std::max(adjacent_width1, 0), y2);
- quad[2] = FloatPoint(x2 - std::max(adjacent_width2, 0), y2);
- quad[3] = FloatPoint(x2 - std::max(-adjacent_width2, 0), y1);
- break;
- case BoxSide::kBottom:
- quad[0] = FloatPoint(x1 + std::max(adjacent_width1, 0), y1);
- quad[1] = FloatPoint(x1 + std::max(-adjacent_width1, 0), y2);
- quad[2] = FloatPoint(x2 - std::max(-adjacent_width2, 0), y2);
- quad[3] = FloatPoint(x2 - std::max(adjacent_width2, 0), y1);
- break;
- case BoxSide::kLeft:
- quad[0] = FloatPoint(x1, y1 + std::max(-adjacent_width1, 0));
- quad[1] = FloatPoint(x1, y2 - std::max(-adjacent_width2, 0));
- quad[2] = FloatPoint(x2, y2 - std::max(adjacent_width2, 0));
- quad[3] = FloatPoint(x2, y1 + std::max(adjacent_width1, 0));
- break;
- case BoxSide::kRight:
- quad[0] = FloatPoint(x1, y1 + std::max(adjacent_width1, 0));
- quad[1] = FloatPoint(x1, y2 - std::max(adjacent_width2, 0));
- quad[2] = FloatPoint(x2, y2 - std::max(-adjacent_width2, 0));
- quad[3] = FloatPoint(x2, y1 + std::max(-adjacent_width1, 0));
- break;
- }
-
- FillQuad(graphics_context, quad, color, antialias);
-}
-
-float GetFocusRingBorderRadius(const ComputedStyle& style) {
- // Default style is border-radius equal to outline width.
- float border_radius = style.GetOutlineStrokeWidthForFocusRing();
-
- if (::features::IsFormControlsRefreshEnabled() && !style.HasAuthorBorder() &&
- style.HasEffectiveAppearance()) {
- // For the elements that have not been styled and that have an appearance,
- // the focus ring should use the same border radius as the one used for
- // drawing the element.
- absl::optional<ui::NativeTheme::Part> part;
- switch (style.EffectiveAppearance()) {
- case kCheckboxPart:
- part = ui::NativeTheme::kCheckbox;
- break;
- case kRadioPart:
- part = ui::NativeTheme::kRadio;
- break;
- case kPushButtonPart:
- case kSquareButtonPart:
- case kButtonPart:
- part = ui::NativeTheme::kPushButton;
- break;
- case kTextFieldPart:
- case kTextAreaPart:
- case kSearchFieldPart:
- part = ui::NativeTheme::kTextField;
- break;
- default:
- break;
- }
- if (part) {
- border_radius =
- ui::NativeTheme::GetInstanceForWeb()->GetBorderRadiusForPart(
- part.value(), style.Width().GetFloatValue(),
- style.Height().GetFloatValue());
-
- // Form controls send to NativeTheme have zoom applied. But the focus ring
- // outline does not. Apply zoom to checkbox focus ring.
- return (style.EffectiveAppearance() == kCheckboxPart)
- ? border_radius * style.EffectiveZoom()
- : border_radius;
- }
- }
-
- return border_radius;
-}
-
-} // anonymous namespace
-
-void ObjectPainterBase::PaintOutlineRects(
- const PaintInfo& paint_info,
- const Vector<PhysicalRect>& outline_rects,
- const ComputedStyle& style) {
- Vector<IntRect> pixel_snapped_outline_rects;
- for (auto& r : outline_rects)
- pixel_snapped_outline_rects.push_back(PixelSnappedIntRect(r));
-
- Color color = style.VisitedDependentColor(GetCSSPropertyOutlineColor());
- if (style.OutlineStyleIsAuto()) {
- // Logic in draw focus ring is dependent on whether the border is large
- // enough to have an inset outline. Use the smallest border edge for that
- // test.
- float min_border_width =
- std::min(std::min(style.BorderTopWidth(), style.BorderBottomWidth()),
- std::min(style.BorderLeftWidth(), style.BorderRightWidth()));
- float border_radius = GetFocusRingBorderRadius(style);
- paint_info.context.DrawFocusRing(
- pixel_snapped_outline_rects, style.GetOutlineStrokeWidthForFocusRing(),
- style.OutlineOffsetInt(), border_radius, min_border_width, color,
- style.UsedColorScheme());
- return;
- }
-
- IntRect united_outline_rect = UnionRect(pixel_snapped_outline_rects);
- if (united_outline_rect == pixel_snapped_outline_rects[0]) {
- PaintSingleRectangleOutline(paint_info, united_outline_rect, style, color);
- return;
- }
- PaintComplexOutline(paint_info.context, pixel_snapped_outline_rects, style,
- color);
-}
-
-void ObjectPainterBase::DrawLineForBoxSide(GraphicsContext& graphics_context,
- float x1,
- float y1,
- float x2,
- float y2,
- BoxSide side,
- Color color,
- EBorderStyle style,
- int adjacent_width1,
- int adjacent_width2,
- bool antialias) {
- float thickness;
- float length;
- if (side == BoxSide::kTop || side == BoxSide::kBottom) {
- thickness = y2 - y1;
- length = x2 - x1;
- } else {
- thickness = x2 - x1;
- length = y2 - y1;
- }
-
- // We would like this check to be an ASSERT as we don't want to draw empty
- // borders. However nothing guarantees that the following recursive calls to
- // ObjectPainterBase::DrawLineForBoxSide will have positive thickness and
- // length.
- if (length <= 0 || thickness <= 0)
- return;
-
- if (style == EBorderStyle::kDouble && thickness < 3)
- style = EBorderStyle::kSolid;
-
- switch (style) {
- case EBorderStyle::kNone:
- case EBorderStyle::kHidden:
- return;
- case EBorderStyle::kDotted:
- case EBorderStyle::kDashed:
- DrawDashedOrDottedBoxSide(graphics_context, x1, y1, x2, y2, side, color,
- thickness, style, antialias);
- break;
- case EBorderStyle::kDouble:
- DrawDoubleBoxSide(graphics_context, x1, y1, x2, y2, length, side, color,
- thickness, adjacent_width1, adjacent_width2, antialias);
- break;
- case EBorderStyle::kRidge:
- case EBorderStyle::kGroove:
- DrawRidgeOrGrooveBoxSide(graphics_context, x1, y1, x2, y2, side, color,
- style, adjacent_width1, adjacent_width2,
- antialias);
- break;
- case EBorderStyle::kInset:
- // FIXME: Maybe we should lighten the colors on one side like Firefox.
- // https://bugs.webkit.org/show_bug.cgi?id=58608
- if (side == BoxSide::kTop || side == BoxSide::kLeft)
- color = color.Dark();
- FALLTHROUGH;
- case EBorderStyle::kOutset:
- if (style == EBorderStyle::kOutset &&
- (side == BoxSide::kBottom || side == BoxSide::kRight))
- color = color.Dark();
- FALLTHROUGH;
- case EBorderStyle::kSolid:
- DrawSolidBoxSide(graphics_context, x1, y1, x2, y2, side, color,
- adjacent_width1, adjacent_width2, antialias);
- break;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/object_painter_base.h b/chromium/third_party/blink/renderer/core/paint/object_painter_base.h
deleted file mode 100644
index 4f83f196202..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/object_painter_base.h
+++ /dev/null
@@ -1,63 +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_OBJECT_PAINTER_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_OBJECT_PAINTER_BASE_H_
-
-#include "third_party/blink/renderer/core/style/computed_style_constants.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/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class ComputedStyle;
-class GraphicsContext;
-struct PaintInfo;
-struct PhysicalRect;
-
-// Base class for object painting. Has no dependencies on the layout tree and
-// thus provides functionality and definitions that can be shared between both
-// legacy layout and LayoutNG.
-class ObjectPainterBase {
- STACK_ALLOCATED();
-
- public:
- static void DrawBoxSide(GraphicsContext& context,
- const IntRect& snapped_edge_rect,
- BoxSide side,
- Color color,
- EBorderStyle style) {
- DrawLineForBoxSide(context, snapped_edge_rect.X(), snapped_edge_rect.Y(),
- snapped_edge_rect.MaxX(), snapped_edge_rect.MaxY(), side,
- color, style, 0, 0, true);
- }
-
- // TODO(wangxianzhu): The float parameters are truncated to int in the
- // function, which implicitly snaps to whole pixels incorrectly. We should
- // always use the above function. For now the only outside caller is
- // BoxBorderPainter::PaintOneBorderSide().
- static void DrawLineForBoxSide(GraphicsContext&,
- float x1,
- float y1,
- float x2,
- float y2,
- BoxSide,
- Color,
- EBorderStyle,
- int adjacent_edge_width1,
- int adjacent_edge_width2,
- bool antialias = false);
-
- protected:
- ObjectPainterBase() = default;
- void PaintOutlineRects(const PaintInfo&,
- const Vector<PhysicalRect>&,
- const ComputedStyle&);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_OBJECT_PAINTER_BASE_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/outline_painter.cc b/chromium/third_party/blink/renderer/core/paint/outline_painter.cc
new file mode 100644
index 00000000000..bb1a6d18914
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/outline_painter.cc
@@ -0,0 +1,724 @@
+// 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/outline_painter.h"
+
+#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
+#include "third_party/blink/renderer/core/paint/box_border_painter.h"
+#include "third_party/blink/renderer/core/paint/rounded_border_geometry.h"
+#include "third_party/blink/renderer/core/style/border_edge.h"
+#include "third_party/blink/renderer/core/style/computed_style.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/graphics_context_state_saver.h"
+#include "third_party/blink/renderer/platform/graphics/path.h"
+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
+#include "ui/native_theme/native_theme.h"
+
+namespace blink {
+
+namespace {
+
+struct OutlineEdgeInfo {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ BoxSide side;
+};
+
+// Adjust length of edges if needed. Returns the width of the joint.
+int AdjustJoint(int outline_width,
+ OutlineEdgeInfo& edge1,
+ OutlineEdgeInfo& edge2) {
+ // A clockwise joint:
+ // - needs no adjustment of edge length because our edges are along the
+ // clockwise outer edge of the outline;
+ // - needs a positive adjacent joint width (required by
+ // BoxBorderPainter::DrawLineForBoxSide).
+ // A counterclockwise joint:
+ // - needs to increase the edge length to include the joint;
+ // - needs a negative adjacent joint width (required by
+ // BoxBorderPainter::DrawLineForBoxSide).
+ switch (edge1.side) {
+ case BoxSide::kTop:
+ switch (edge2.side) {
+ case BoxSide::kRight: // Clockwise
+ return outline_width;
+ case BoxSide::kLeft: // Counterclockwise
+ edge1.x2 += outline_width;
+ edge2.y2 += outline_width;
+ return -outline_width;
+ default: // Same side or no joint.
+ return 0;
+ }
+ case BoxSide::kRight:
+ switch (edge2.side) {
+ case BoxSide::kBottom: // Clockwise
+ return outline_width;
+ case BoxSide::kTop: // Counterclockwise
+ edge1.y2 += outline_width;
+ edge2.x1 -= outline_width;
+ return -outline_width;
+ default: // Same side or no joint.
+ return 0;
+ }
+ case BoxSide::kBottom:
+ switch (edge2.side) {
+ case BoxSide::kLeft: // Clockwise
+ return outline_width;
+ case BoxSide::kRight: // Counterclockwise
+ edge1.x1 -= outline_width;
+ edge2.y1 -= outline_width;
+ return -outline_width;
+ default: // Same side or no joint.
+ return 0;
+ }
+ case BoxSide::kLeft:
+ switch (edge2.side) {
+ case BoxSide::kTop: // Clockwise
+ return outline_width;
+ case BoxSide::kBottom: // Counterclockwise
+ edge1.y1 -= outline_width;
+ edge2.x2 += outline_width;
+ return -outline_width;
+ default: // Same side or no joint.
+ return 0;
+ }
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
+// A negative outline-offset should not cause the rendered outline shape to
+// become smaller than twice the computed value of the outline-width, in each
+// direction separately. See: https://drafts.csswg.org/css-ui/#outline-offset
+int AdjustedOutlineOffsetX(const IntRect& rect, int offset) {
+ return std::max(offset, -rect.Width() / 2);
+}
+int AdjustedOutlineOffsetY(const IntRect& rect, int offset) {
+ return std::max(offset, -rect.Height() / 2);
+}
+
+// Construct a clockwise path along the outer edge of the region covered by
+// |rects| expanded by |outline_offset| (which can be negative and clamped by
+// the rect size) and |additional_outset| (which should be non-negative).
+bool ComputeRightAnglePath(SkPath& path,
+ const Vector<IntRect>& rects,
+ int outline_offset,
+ int additional_outset) {
+ DCHECK_GE(additional_outset, 0);
+ SkRegion region;
+ for (auto& r : rects) {
+ IntRect rect = r;
+ rect.InflateX(AdjustedOutlineOffsetX(rect, outline_offset));
+ rect.InflateY(AdjustedOutlineOffsetY(rect, outline_offset));
+ rect.Inflate(additional_outset);
+ region.op(rect, SkRegion::kUnion_Op);
+ }
+ return region.getBoundaryPath(&path);
+}
+
+struct Line {
+ SkPoint start;
+ SkPoint end;
+};
+
+// Merge line2 into line1 if they are in the same straight line.
+bool MergeLineIfPossible(Line& line1, const Line& line2) {
+ DCHECK(line1.end == line2.start);
+ if ((line1.start.x() == line1.end.x() && line1.start.x() == line2.end.x()) ||
+ (line1.start.y() == line1.end.y() && line1.start.y() == line2.end.y())) {
+ line1.end = line2.end;
+ return true;
+ }
+ return false;
+}
+
+// Iterate a right angle |path| by running |contour_action| on each contour.
+// The path contains one or more contours each of which is like (kMove_Verb,
+// kLine_Verb, ..., kClose_Verb). Each line must be either horizontal or
+// vertical. Each pair of adjacent lines (including the last and the first)
+// should either create a right angle or be in the same straight line.
+template <typename Action>
+void IterateRightAnglePath(const SkPath& path, const Action& contour_action) {
+ SkPath::Iter iter(path, /*forceClose*/ true);
+ SkPoint points[4];
+ Vector<Line> lines;
+ for (SkPath::Verb verb = iter.next(points); verb != SkPath::kDone_Verb;
+ verb = iter.next(points)) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ DCHECK(lines.IsEmpty());
+ break;
+ case SkPath::kLine_Verb: {
+ Line new_line{points[0], points[1]};
+ if (lines.IsEmpty() || !MergeLineIfPossible(lines.back(), new_line)) {
+ lines.push_back(new_line);
+ DCHECK(lines.size() == 1 ||
+ lines.back().start == lines[lines.size() - 2].end);
+ }
+ break;
+ }
+ case SkPath::kClose_Verb: {
+ if (lines.size() >= 4u) {
+ if (MergeLineIfPossible(lines.back(), lines.front())) {
+ lines.front() = lines.back();
+ lines.pop_back();
+ }
+ DCHECK(lines.front().start == lines.back().end);
+ DCHECK_GE(lines.size(), 4u);
+ contour_action(lines);
+ }
+ lines.clear();
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+void PaintComplexRightAngleOutlineContour(GraphicsContext& context,
+ const Vector<Line>& lines,
+ const ComputedStyle& style,
+ Color color) {
+ int width = style.OutlineWidthInt();
+ Vector<OutlineEdgeInfo> edges;
+ edges.ReserveInitialCapacity(lines.size());
+ for (auto& line : lines) {
+ auto& edge = edges.emplace_back();
+ edge.x1 = SkScalarTruncToInt(line.start.x());
+ edge.y1 = SkScalarTruncToInt(line.start.y());
+ edge.x2 = SkScalarTruncToInt(line.end.x());
+ edge.y2 = SkScalarTruncToInt(line.end.y());
+ if (edge.x1 == edge.x2) {
+ if (edge.y1 < edge.y2) {
+ edge.x1 -= width;
+ edge.side = BoxSide::kRight;
+ } else {
+ std::swap(edge.y1, edge.y2);
+ edge.x2 += width;
+ edge.side = BoxSide::kLeft;
+ }
+ } else {
+ DCHECK(edge.y1 == edge.y2);
+ if (edge.x1 < edge.x2) {
+ edge.y2 += width;
+ edge.side = BoxSide::kTop;
+ } else {
+ std::swap(edge.x1, edge.x2);
+ edge.y1 -= width;
+ edge.side = BoxSide::kBottom;
+ }
+ }
+ }
+
+ int first_adjacent_width = AdjustJoint(width, edges.back(), edges.front());
+ // The width of the angled part of starting and ending joint of the current
+ // edge.
+ int adjacent_width_start = first_adjacent_width;
+ int adjacent_width_end;
+ for (wtf_size_t i = 0; i < edges.size(); ++i) {
+ OutlineEdgeInfo& edge = edges[i];
+ adjacent_width_end = i == edges.size() - 1
+ ? first_adjacent_width
+ : AdjustJoint(width, edge, edges[i + 1]);
+ int adjacent_width1 = adjacent_width_start;
+ int adjacent_width2 = adjacent_width_end;
+ if (edge.side == BoxSide::kLeft || edge.side == BoxSide::kBottom)
+ std::swap(adjacent_width1, adjacent_width2);
+ BoxBorderPainter::DrawLineForBoxSide(
+ context, edge.x1, edge.y1, edge.x2, edge.y2, edge.side, color,
+ style.OutlineStyle(), adjacent_width1, adjacent_width2,
+ /*antialias*/ false);
+ adjacent_width_start = adjacent_width_end;
+ }
+}
+
+void PaintComplexRightAngleOutline(GraphicsContext& context,
+ const Vector<IntRect>& rects,
+ const ComputedStyle& style) {
+ DCHECK(!style.OutlineStyleIsAuto());
+
+ SkPath path;
+ if (!ComputeRightAnglePath(path, rects, style.OutlineOffsetInt(),
+ style.OutlineWidthInt())) {
+ return;
+ }
+
+ Color color = style.VisitedDependentColor(GetCSSPropertyOutlineColor());
+ bool use_transparency_layer = color.HasAlpha();
+ if (use_transparency_layer) {
+ context.BeginLayer(static_cast<float>(color.Alpha()) / 255);
+ color.SetRGB(color.Red(), color.Green(), color.Blue());
+ }
+
+ IterateRightAnglePath(path, [&](const Vector<Line>& lines) {
+ PaintComplexRightAngleOutlineContour(context, lines, style, color);
+ });
+
+ if (use_transparency_layer)
+ context.EndLayer();
+}
+
+// Given 3 points defining a right angle corner, returns |p2| shifted to make
+// the containing path shrink by |inset|.
+SkPoint ShrinkCorner(const SkPoint& p1,
+ const SkPoint& p2,
+ const SkPoint& p3,
+ int inset) {
+ if (p1.x() == p2.x()) {
+ if (p1.y() < p2.y()) {
+ return p2.x() < p3.x() ? p2 + SkVector::Make(-inset, inset)
+ : p2 + SkVector::Make(-inset, -inset);
+ }
+ return p2.x() < p3.x() ? p2 + SkVector::Make(inset, inset)
+ : p2 + SkVector::Make(inset, -inset);
+ }
+ if (p1.x() < p2.x()) {
+ return p2.y() < p3.y() ? p2 + SkVector::Make(-inset, inset)
+ : p2 + SkVector::Make(inset, inset);
+ }
+ return p2.y() < p3.y() ? p2 + SkVector::Make(-inset, -inset)
+ : p2 + SkVector::Make(inset, -inset);
+}
+
+void ShrinkRightAnglePath(SkPath& path, int inset) {
+ SkPath input;
+ std::swap(input, path);
+ IterateRightAnglePath(input, [&path, inset](const Vector<Line>& lines) {
+ for (wtf_size_t i = 0; i < lines.size(); i++) {
+ const SkPoint& prev_point =
+ lines[i == 0 ? lines.size() - 1 : i - 1].start;
+ SkPoint new_point =
+ ShrinkCorner(prev_point, lines[i].start, lines[i].end, inset);
+ if (i == 0) {
+ path.moveTo(new_point);
+ } else {
+ path.lineTo(new_point);
+ }
+ }
+ path.close();
+ });
+}
+
+FloatRoundedRect::Radii ComputeCornerRadii(
+ const ComputedStyle& style,
+ const PhysicalRect& reference_border_rect,
+ float offset) {
+ return RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ style, reference_border_rect,
+ LayoutRectOutsets(offset, offset, offset, offset))
+ .GetRadii();
+}
+
+// Given 3 points defining a right angle corner, returns the corresponding
+// corner in |convex_radii| or |concave_radii|.
+FloatSize GetRadiiCorner(const FloatRoundedRect::Radii& convex_radii,
+ const FloatRoundedRect::Radii& concave_radii,
+ const SkPoint& p1,
+ const SkPoint& p2,
+ const SkPoint& p3) {
+ if (p1.x() == p2.x()) {
+ if (p1.y() == p2.y() || p2.x() == p3.x())
+ return FloatSize();
+ DCHECK_EQ(p2.y(), p3.y());
+ if (p1.y() < p2.y()) {
+ return p2.x() < p3.x() ? concave_radii.BottomLeft()
+ : convex_radii.BottomRight();
+ }
+ return p2.x() < p3.x() ? convex_radii.TopLeft() : concave_radii.TopRight();
+ }
+ DCHECK_EQ(p1.y(), p2.y());
+ if (p2.x() != p3.x() || p2.y() == p3.y())
+ return FloatSize();
+ if (p1.x() < p2.x()) {
+ return p2.y() < p3.y() ? convex_radii.TopRight()
+ : concave_radii.BottomRight();
+ }
+ return p2.y() < p3.y() ? concave_radii.TopLeft() : convex_radii.BottomLeft();
+}
+
+// Shorten |line| between rounded corners.
+void AdjustLineBetweenCorners(Line& line,
+ const FloatRoundedRect::Radii& convex_radii,
+ const FloatRoundedRect::Radii& concave_radii,
+ const SkPoint& prev_point,
+ const SkPoint& next_point) {
+ FloatSize corner1 = GetRadiiCorner(convex_radii, concave_radii, prev_point,
+ line.start, line.end);
+ FloatSize corner2 = GetRadiiCorner(convex_radii, concave_radii, line.start,
+ line.end, next_point);
+ if (line.start.x() == line.end.x()) {
+ // |line| is vertical, and adjacent lines are horizontal.
+ float height = std::abs(line.end.y() - line.start.y());
+ float corner1_height = corner1.Height();
+ float corner2_height = corner2.Height();
+ if (corner1_height + corner2_height > height) {
+ // Scale down the corner heights to make the corners fit in |height|.
+ float scale = height / (corner1_height + corner2_height);
+ corner1_height = floorf(corner1_height * scale);
+ corner2_height = floorf(corner2_height * scale);
+ }
+ if (line.start.y() < line.end.y()) {
+ line.start.offset(0, corner1_height);
+ line.end.offset(0, -corner2_height);
+ } else {
+ line.start.offset(0, -corner1_height);
+ line.end.offset(0, corner2_height);
+ }
+ } else {
+ // |line| is horizontal, and adjacent lines are vertical.
+ float width = std::abs(line.end.x() - line.start.x());
+ float corner1_width = corner1.Width();
+ float corner2_width = corner2.Width();
+ if (corner1_width + corner2_width > width) {
+ // Scale down the corner widths to make the corners fit in |width|.
+ float scale = width / (corner1_width + corner2_width);
+ corner1_width = floorf(corner1_width * scale);
+ corner2_width = floorf(corner2_width * scale);
+ }
+ if (line.start.x() < line.end.x()) {
+ line.start.offset(corner1_width, 0);
+ line.end.offset(-corner2_width, 0);
+ } else {
+ line.start.offset(-corner1_width, 0);
+ line.end.offset(corner2_width, 0);
+ }
+ }
+}
+
+// Create a rounded path from a right angle |path| by
+// - inserting arc segments for corners;
+// - adjusting length of the lines.
+void AddCornerRadiiToPath(SkPath& path,
+ const FloatRoundedRect::Radii& convex_radii,
+ const FloatRoundedRect::Radii& concave_radii) {
+ SkPath input;
+ input.swap(path);
+ IterateRightAnglePath(input, [&](const Vector<Line>& lines) {
+ auto new_lines = lines;
+ for (wtf_size_t i = 0; i < lines.size(); i++) {
+ const SkPoint& prev_point =
+ lines[i == 0 ? lines.size() - 1 : i - 1].start;
+ const SkPoint& next_point = lines[i == lines.size() - 1 ? 0 : i + 1].end;
+ AdjustLineBetweenCorners(new_lines[i], convex_radii, concave_radii,
+ prev_point, next_point);
+ }
+ // Generate the new contour into |path|.
+ DCHECK_EQ(lines.size(), new_lines.size());
+ path.moveTo(new_lines[0].start);
+ for (wtf_size_t i = 0; i < new_lines.size(); i++) {
+ const Line& line = new_lines[i];
+ if (line.end != line.start)
+ path.lineTo(line.end);
+ const Line& next_line = new_lines[i == lines.size() - 1 ? 0 : i + 1];
+ if (line.end != next_line.start) {
+ constexpr float kCornerConicWeight = 0.707106781187; // 1/sqrt(2)
+ // This produces a 90 degree arc from line.end towards lines[i].end
+ // to next_line.start.
+ path.conicTo(lines[i].end, next_line.start, kCornerConicWeight);
+ }
+ }
+ path.close();
+ });
+}
+
+class ComplexRoundedOutlinePainter {
+ public:
+ ComplexRoundedOutlinePainter(GraphicsContext& context,
+ const Vector<IntRect>& rects,
+ const PhysicalRect& reference_border_rect,
+ const ComputedStyle& style)
+ : context_(context),
+ rects_(rects),
+ reference_border_rect_(reference_border_rect),
+ style_(style),
+ outline_style_(style.OutlineStyle()),
+ offset_(style.OutlineOffsetInt()),
+ width_(style.OutlineWidthInt()),
+ color_(style.VisitedDependentColor(GetCSSPropertyOutlineColor())) {
+ DCHECK(!style.OutlineStyleIsAuto());
+ if (width_ <= 2 && outline_style_ == EBorderStyle::kDouble) {
+ outline_style_ = EBorderStyle::kSolid;
+ } else if (width_ == 1 && (outline_style_ == EBorderStyle::kRidge ||
+ outline_style_ == EBorderStyle::kGroove)) {
+ outline_style_ = EBorderStyle::kSolid;
+ Color dark = color_.Dark();
+ color_ = Color((color_.Red() + dark.Red()) / 2,
+ (color_.Green() + dark.Green()) / 2,
+ (color_.Blue() + dark.Blue()) / 2, color_.Alpha());
+ }
+ }
+
+ bool Paint() {
+ if (width_ == 0)
+ return true;
+
+ if (!ComputeRightAnglePath(right_angle_outer_path_, rects_, offset_,
+ width_)) {
+ return true;
+ }
+
+ SkPath outer_path = right_angle_outer_path_;
+ SkPath inner_path = right_angle_outer_path_;
+ ShrinkRightAnglePath(inner_path, width_);
+ auto inner_radii = ComputeRadii(0);
+ auto outer_radii = ComputeRadii(width_);
+ AddCornerRadiiToPath(outer_path, outer_radii, inner_radii);
+ AddCornerRadiiToPath(inner_path, inner_radii, outer_radii);
+
+ GraphicsContextStateSaver saver(context_);
+ context_.ClipPath(outer_path, kAntiAliased);
+ context_.ClipOut(inner_path);
+ context_.SetFillColor(color_);
+
+ switch (outline_style_) {
+ case EBorderStyle::kSolid:
+ context_.FillRect(outer_path.getBounds());
+ break;
+ case EBorderStyle::kDouble:
+ PaintDoubleOutline();
+ break;
+ case EBorderStyle::kDotted:
+ case EBorderStyle::kDashed:
+ PaintDottedOrDashedOutline();
+ break;
+ default:
+ // TODO(wangxianzhu): Draw kRidge, kGroove, kInset, kOutset by calling
+ // BoxBorderPainter::DrawBoxSideFromPath() for each segment of the path.
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ void PaintDoubleOutline() {
+ SkPath inner_third_path = right_angle_outer_path_;
+ SkPath outer_third_path = right_angle_outer_path_;
+ int stroke_width = std::round(width_ / 3.0);
+ ShrinkRightAnglePath(inner_third_path, width_ - stroke_width);
+ ShrinkRightAnglePath(outer_third_path, stroke_width);
+ auto inner_third_radii = ComputeRadii(stroke_width);
+ auto outer_third_radii = ComputeRadii(width_ - stroke_width);
+ AddCornerRadiiToPath(inner_third_path, inner_third_radii,
+ outer_third_radii);
+ AddCornerRadiiToPath(outer_third_path, outer_third_radii,
+ inner_third_radii);
+ {
+ GraphicsContextStateSaver saver(context_);
+ context_.ClipOut(outer_third_path);
+ context_.FillRect(right_angle_outer_path_.getBounds());
+ }
+ context_.FillPath(inner_third_path);
+ }
+
+ void PaintDottedOrDashedOutline() {
+ SkPath center_path = right_angle_outer_path_;
+ int center_outset = width_ / 2;
+ ShrinkRightAnglePath(center_path, width_ - center_outset);
+ auto center_radii = ComputeRadii(center_outset);
+ AddCornerRadiiToPath(center_path, center_radii, center_radii);
+ context_.SetStrokeColor(color_);
+ auto stroke_style =
+ outline_style_ == EBorderStyle::kDashed ? kDashedStroke : kDottedStroke;
+ context_.SetStrokeStyle(stroke_style);
+ if (StrokeData::StrokeIsDashed(width_, stroke_style)) {
+ // Draw wider to fill the clip area between inner_path_ and outer_path_,
+ // to get smoother edges, and even stroke thickness when the outline is
+ // thin.
+ context_.SetStrokeThickness(width_ + 2);
+ } else {
+ context_.SetStrokeThickness(width_);
+ context_.SetLineCap(kRoundCap);
+ }
+ context_.StrokePath(center_path, Path(center_path).length(), width_);
+ }
+
+ FloatRoundedRect::Radii ComputeRadii(int outset) const {
+ return ComputeCornerRadii(style_, reference_border_rect_, offset_ + outset);
+ }
+
+ GraphicsContext& context_;
+ const Vector<IntRect>& rects_;
+ const PhysicalRect& reference_border_rect_;
+ const ComputedStyle& style_;
+ EBorderStyle outline_style_;
+ int offset_;
+ int width_;
+ Color color_;
+ SkPath right_angle_outer_path_;
+};
+
+float DefaultFocusRingCornerRadius(const ComputedStyle& style) {
+ // Default style is corner radius equal to outline width.
+ return style.FocusRingStrokeWidth();
+}
+
+FloatRoundedRect::Radii GetFocusRingCornerRadii(
+ const ComputedStyle& style,
+ const PhysicalRect& reference_border_rect) {
+ if (style.HasBorderRadius() &&
+ (!style.HasEffectiveAppearance() || style.HasAuthorBorderRadius())) {
+ auto radii = ComputeCornerRadii(style, reference_border_rect,
+ style.OutlineOffsetInt());
+ radii.SetMinimumRadius(DefaultFocusRingCornerRadius(style));
+ return radii;
+ }
+
+ if (!style.HasAuthorBorder() && style.HasEffectiveAppearance()) {
+ // For the elements that have not been styled and that have an appearance,
+ // the focus ring should use the same border radius as the one used for
+ // drawing the element.
+ absl::optional<ui::NativeTheme::Part> part;
+ switch (style.EffectiveAppearance()) {
+ case kCheckboxPart:
+ part = ui::NativeTheme::kCheckbox;
+ break;
+ case kRadioPart:
+ part = ui::NativeTheme::kRadio;
+ break;
+ case kPushButtonPart:
+ case kSquareButtonPart:
+ case kButtonPart:
+ part = ui::NativeTheme::kPushButton;
+ break;
+ case kTextFieldPart:
+ case kTextAreaPart:
+ case kSearchFieldPart:
+ part = ui::NativeTheme::kTextField;
+ break;
+ default:
+ break;
+ }
+ if (part) {
+ float corner_radius =
+ ui::NativeTheme::GetInstanceForWeb()->GetBorderRadiusForPart(
+ part.value(), style.Width().GetFloatValue(),
+ style.Height().GetFloatValue());
+ corner_radius =
+ ui::NativeTheme::GetInstanceForWeb()->AdjustBorderRadiusByZoom(
+ part.value(), corner_radius, style.EffectiveZoom());
+ return FloatRoundedRect::Radii(corner_radius);
+ }
+ }
+
+ return FloatRoundedRect::Radii(DefaultFocusRingCornerRadius(style));
+}
+
+void PaintSingleFocusRing(GraphicsContext& context,
+ const Vector<IntRect>& rects,
+ float width,
+ int offset,
+ const FloatRoundedRect::Radii& corner_radii,
+ const Color& color) {
+ DCHECK(!rects.IsEmpty());
+ SkPath path;
+ if (!ComputeRightAnglePath(path, rects, offset, 0))
+ return;
+
+ SkRect rect;
+ if (path.isRect(&rect)) {
+ context.DrawFocusRingRect(FloatRoundedRect(rect, corner_radii), color,
+ width);
+ return;
+ }
+
+ absl::optional<float> corner_radius = corner_radii.UniformRadius();
+ if (corner_radius.has_value()) {
+ context.DrawFocusRingPath(path, color, width, *corner_radius);
+ return;
+ }
+
+ // Bake non-uniform radii into the path, and draw the path with 0 corner
+ // radius as the path already has rounded corners.
+ AddCornerRadiiToPath(path, corner_radii, corner_radii);
+ context.DrawFocusRingPath(path, color, width, 0);
+}
+
+void PaintFocusRing(GraphicsContext& context,
+ const Vector<IntRect>& rects,
+ const ComputedStyle& style,
+ const FloatRoundedRect::Radii& corner_radii) {
+ Color inner_color = style.VisitedDependentColor(GetCSSPropertyOutlineColor());
+#if !defined(OS_MAC)
+ if (style.DarkColorScheme())
+ inner_color = Color::kWhite;
+#endif
+
+ const float outer_ring_width = style.FocusRingOuterStrokeWidth();
+ const float inner_ring_width = style.FocusRingInnerStrokeWidth();
+ const int offset = style.FocusRingOffset();
+ Color outer_color =
+ style.DarkColorScheme() ? Color(0x10, 0x10, 0x10) : Color::kWhite;
+ PaintSingleFocusRing(context, rects, outer_ring_width,
+ offset + std::ceil(inner_ring_width), corner_radii,
+ outer_color);
+ // Draw the inner ring using |outer_ring_width| (which should be wider than
+ // the additional offset of the outer ring) over the outer ring to ensure no
+ // gaps or AA artifacts.
+ DCHECK_GE(outer_ring_width, std::ceil(inner_ring_width));
+ PaintSingleFocusRing(context, rects, outer_ring_width, offset, corner_radii,
+ inner_color);
+}
+
+} // anonymous namespace
+
+void OutlinePainter::PaintOutlineRects(
+ GraphicsContext& context,
+ const Vector<PhysicalRect>& outline_rects,
+ const ComputedStyle& style) {
+ Vector<IntRect> pixel_snapped_outline_rects;
+ for (auto& r : outline_rects) {
+ IntRect pixel_snapped_rect = PixelSnappedIntRect(r);
+ // Keep empty rect for normal outline, but not for focus rings.
+ if (!pixel_snapped_rect.IsEmpty() || !style.OutlineStyleIsAuto())
+ pixel_snapped_outline_rects.push_back(pixel_snapped_rect);
+ }
+ if (pixel_snapped_outline_rects.IsEmpty())
+ return;
+
+ if (style.OutlineStyleIsAuto()) {
+ auto corner_radii = GetFocusRingCornerRadii(style, outline_rects[0]);
+ PaintFocusRing(context, pixel_snapped_outline_rects, style, corner_radii);
+ return;
+ }
+
+ IntRect united_outline_rect = UnionRect(pixel_snapped_outline_rects);
+ if (united_outline_rect == pixel_snapped_outline_rects[0]) {
+ BoxBorderPainter::PaintSingleRectOutline(
+ context, style, outline_rects[0],
+ AdjustedOutlineOffsetX(united_outline_rect, style.OutlineOffsetInt()),
+ AdjustedOutlineOffsetY(united_outline_rect, style.OutlineOffsetInt()));
+ return;
+ }
+
+ if (style.HasBorderRadius() &&
+ ComplexRoundedOutlinePainter(context, pixel_snapped_outline_rects,
+ outline_rects[0], style)
+ .Paint()) {
+ return;
+ }
+
+ PaintComplexRightAngleOutline(context, pixel_snapped_outline_rects, style);
+}
+
+void OutlinePainter::PaintFocusRingPath(GraphicsContext& context,
+ const Path& focus_ring_path,
+ const ComputedStyle& style) {
+ // TODO(crbug/251206): Implement outline-offset and double focus rings like
+ // right angle focus rings, which requires SkPathOps to support expanding and
+ // shrinking generic paths.
+ context.DrawFocusRingPath(
+ focus_ring_path.GetSkPath(),
+ style.VisitedDependentColor(GetCSSPropertyOutlineColor()),
+ style.FocusRingStrokeWidth(), DefaultFocusRingCornerRadius(style));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/outline_painter.h b/chromium/third_party/blink/renderer/core/paint/outline_painter.h
new file mode 100644
index 00000000000..68e76bb9ac5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/outline_painter.h
@@ -0,0 +1,33 @@
+// 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_OUTLINE_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_OUTLINE_PAINTER_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class ComputedStyle;
+class GraphicsContext;
+class Path;
+struct PhysicalRect;
+
+class OutlinePainter {
+ STATIC_ONLY(OutlinePainter);
+
+ public:
+ static void PaintOutlineRects(GraphicsContext&,
+ const Vector<PhysicalRect>&,
+ const ComputedStyle&);
+
+ static void PaintFocusRingPath(GraphicsContext&,
+ const Path&,
+ const ComputedStyle&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_OUTLINE_PAINTER_H_
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 d21438ff2c5..694579235e8 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
@@ -195,7 +195,7 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelChange) {
IntRect(0, 0, 50, 100),
PaintInvalidationReason::kGeometry},
RasterInvalidationInfo{object, object->DebugName(),
- IntRect(0, 0, 101, 71),
+ IntRect(0, 0, 101, 70),
PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksRasterInvalidations(false);
@@ -208,7 +208,7 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelChange) {
IntRect(0, 0, 50, 100),
PaintInvalidationReason::kGeometry},
RasterInvalidationInfo{object, object->DebugName(),
- IntRect(0, 0, 101, 71),
+ IntRect(0, 0, 101, 70),
PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksRasterInvalidations(false);
}
@@ -230,7 +230,7 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChangeWithTransform) {
IntRect(0, 0, 100, 200),
PaintInvalidationReason::kGeometry},
RasterInvalidationInfo{object, object->DebugName(),
- IntRect(0, 0, 202, 142),
+ IntRect(0, 0, 202, 140),
PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksRasterInvalidations(false);
@@ -243,7 +243,7 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChangeWithTransform) {
IntRect(0, 0, 100, 200),
PaintInvalidationReason::kGeometry},
RasterInvalidationInfo{object, object->DebugName(),
- IntRect(0, 0, 202, 142),
+ IntRect(0, 0, 202, 140),
PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksRasterInvalidations(false);
}
@@ -269,7 +269,7 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelWithinPixelsChange) {
UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
- object, object->DebugName(), IntRect(0, 0, 50, 100),
+ object, object->DebugName(), IntRect(0, 1, 50, 99),
PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksRasterInvalidations(false);
}
@@ -951,6 +951,52 @@ TEST_P(PaintAndRasterInvalidationTest, ScrollingInvalidatesStickyOffset) {
EXPECT_EQ(PhysicalOffset(), inner->FirstFragment().PaintOffset());
}
+TEST_P(PaintAndRasterInvalidationTest, NoDamageDueToFloatingPointError) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 0;
+ height: 0;
+ will-change: transform;
+ transform-origin: top left;
+ }
+ .initial { transform: translateX(0px) scale(1.8); }
+ .updated { transform: translateX(47.22222222222222px) scale(1.8); }
+ #tile {
+ position: absolute;
+ will-change: transform;
+ transform-origin: top left;
+ transform: scale(0.55555555555556);
+ }
+ #tileInner {
+ transform-origin: top left;
+ transform: scale(1.8);
+ width: 200px;
+ height: 200px;
+ background: lightblue;
+ }
+ </style>
+ <div id="canvas" class="initial">
+ <div id="tile">
+ <div id="tileInner"></div>
+ </div>
+ </div>
+ )HTML");
+
+ GetDocument().View()->SetTracksRasterInvalidations(true);
+
+ auto* canvas = GetDocument().getElementById("canvas");
+ canvas->setAttribute(html_names::kClassAttr, "updated");
+ GetDocument().View()->SetPaintArtifactCompositorNeedsUpdate();
+
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(GetRasterInvalidationTracking(1)->HasInvalidations());
+ GetDocument().View()->SetTracksRasterInvalidations(false);
+}
+
TEST_P(PaintAndRasterInvalidationTest, ResizeElementWhichHasNonCustomResizer) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
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
index d1da3abf39a..a6d5c358146 100644
--- 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
@@ -19,7 +19,7 @@ class PaintAndRasterInvalidationTest : public PaintControllerPaintTest {
MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
protected:
- ContentLayerClientImpl* GetContentLayerClient(size_t index = 0) const {
+ ContentLayerClientImpl* GetContentLayerClient(wtf_size_t index = 0) const {
DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
const auto& clients = GetDocument()
.View()
@@ -29,7 +29,7 @@ class PaintAndRasterInvalidationTest : public PaintControllerPaintTest {
}
const RasterInvalidationTracking* GetRasterInvalidationTracking(
- size_t index = 0) const {
+ wtf_size_t index = 0) const {
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
if (auto* client = GetContentLayerClient(index))
return client->GetRasterInvalidator().GetTracking();
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 e176942d118..0c543f7cc54 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
@@ -128,10 +128,10 @@ TEST_P(PaintControllerPaintTestForCAP, FrameScrollingContents) {
<div id='div4' style='top: 9000px; left: 9000px'></div>
)HTML");
- const auto& div1 = *GetLayoutObjectByElementId("div1");
- const auto& div2 = *GetLayoutObjectByElementId("div2");
- const auto& div3 = *GetLayoutObjectByElementId("div3");
- const auto& div4 = *GetLayoutObjectByElementId("div4");
+ const auto& div1 = To<LayoutBox>(*GetLayoutObjectByElementId("div1"));
+ const auto& div2 = To<LayoutBox>(*GetLayoutObjectByElementId("div2"));
+ const auto& div3 = To<LayoutBox>(*GetLayoutObjectByElementId("div3"));
+ const auto& div4 = To<LayoutBox>(*GetLayoutObjectByElementId("div4"));
EXPECT_THAT(ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -147,8 +147,18 @@ TEST_P(PaintControllerPaintTestForCAP, FrameScrollingContents) {
PaintChunk::Id(GetLayoutView(), DisplayItem::kScrollHitTest),
GetLayoutView().FirstFragment().LocalBorderBoxProperties(),
&view_scroll_hit_test, IntRect(0, 0, 800, 600)));
- EXPECT_THAT(ContentPaintChunks(),
- ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(3, nullptr)));
+ auto contents_properties =
+ GetLayoutView().FirstFragment().ContentsProperties();
+ EXPECT_THAT(
+ ContentPaintChunks(),
+ ElementsAre(
+ VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
+ IsPaintChunk(1, 2,
+ PaintChunk::Id(*div1.Layer(), DisplayItem::kLayerChunk),
+ contents_properties),
+ IsPaintChunk(2, 3,
+ PaintChunk::Id(*div2.Layer(), DisplayItem::kLayerChunk),
+ contents_properties)));
GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(5000, 5000), mojom::blink::ScrollType::kProgrammatic);
@@ -165,8 +175,20 @@ TEST_P(PaintControllerPaintTestForCAP, FrameScrollingContents) {
PaintChunk::Id(GetLayoutView(), DisplayItem::kScrollHitTest),
GetLayoutView().FirstFragment().LocalBorderBoxProperties(),
&view_scroll_hit_test, IntRect(0, 0, 800, 600)));
- EXPECT_THAT(ContentPaintChunks(),
- ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(4, nullptr)));
+ EXPECT_THAT(
+ ContentPaintChunks(),
+ ElementsAre(
+ VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
+ // html and div1 are out of the cull rect.
+ IsPaintChunk(1, 2,
+ PaintChunk::Id(*div2.Layer(), DisplayItem::kLayerChunk),
+ contents_properties),
+ IsPaintChunk(2, 3,
+ PaintChunk::Id(*div3.Layer(), DisplayItem::kLayerChunk),
+ contents_properties),
+ IsPaintChunk(3, 4,
+ PaintChunk::Id(*div4.Layer(), DisplayItem::kLayerChunk),
+ contents_properties)));
}
TEST_P(PaintControllerPaintTestForCAP, BlockScrollingNonLayeredContents) {
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 d5ede23a64a..3471dfd69f8 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
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/editing/frame_selection.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/cull_rect_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"
@@ -49,6 +50,10 @@ class PaintControllerPaintTestBase : public RenderingTest {
void UpdateAllLifecyclePhasesExceptPaint() {
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(
DocumentUpdateReason::kTest);
+ // Run CullRectUpdater to ease testing of cull rects and repaint flags of
+ // PaintLayers on cull rect change.
+ if (RuntimeEnabledFeatures::CullRectUpdateEnabled())
+ CullRectUpdater(*GetLayoutView().Layer()).Update();
}
void PaintContents(const IntRect& interest_rect) {
@@ -111,31 +116,6 @@ class PaintControllerPaintTestBase : public RenderingTest {
return PaintChunkSubset(RootPaintController().GetPaintArtifactShared(),
begin_index, end_index);
}
-
- class CachedItemAndSubsequenceCounter {
- public:
- CachedItemAndSubsequenceCounter()
- : reset_uma_reporting_(&PaintController::disable_uma_reporting_, true) {
- Reset();
- }
- void Reset() {
- old_num_cached_items_ = PaintController::sum_num_cached_items_;
- old_num_cached_subsequences_ =
- PaintController::sum_num_cached_subsequences_;
- }
- size_t NumNewCachedItems() const {
- return PaintController::sum_num_cached_items_ - old_num_cached_items_;
- }
- size_t NumNewCachedSubsequences() const {
- return PaintController::sum_num_cached_subsequences_ -
- old_num_cached_subsequences_;
- }
-
- private:
- base::AutoReset<bool> reset_uma_reporting_;
- size_t old_num_cached_items_;
- size_t old_num_cached_subsequences_;
- };
};
class PaintControllerPaintTest : public PaintTestConfigurations,
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 37f149818af..971354f09b8 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_info.h
@@ -28,8 +28,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INFO_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
// TODO(jchaffraix): Once we unify PaintBehavior and PaintLayerFlags, we should
// move PaintLayerFlags to PaintPhase and rename it. Thus removing the need for
// this #include
@@ -59,14 +59,11 @@ struct CORE_EXPORT PaintInfo {
PaintPhase phase,
GlobalPaintFlags global_paint_flags,
PaintLayerFlags paint_flags,
- const LayoutBoxModelObject* paint_container = nullptr,
- LayoutUnit fragment_logical_top_in_flow_thread = LayoutUnit())
+ const LayoutBoxModelObject* paint_container = nullptr)
: context(context),
phase(phase),
cull_rect_(cull_rect),
paint_container_(paint_container),
- fragment_logical_top_in_flow_thread_(
- fragment_logical_top_in_flow_thread),
paint_flags_(paint_flags),
global_paint_flags_(global_paint_flags) {}
@@ -76,8 +73,7 @@ struct CORE_EXPORT PaintInfo {
phase(copy_other_fields_from.phase),
cull_rect_(copy_other_fields_from.cull_rect_),
paint_container_(copy_other_fields_from.paint_container_),
- fragment_logical_top_in_flow_thread_(
- copy_other_fields_from.fragment_logical_top_in_flow_thread_),
+ fragment_id_(copy_other_fields_from.fragment_id_),
paint_flags_(copy_other_fields_from.paint_flags_),
global_paint_flags_(copy_other_fields_from.global_paint_flags_) {
// We should never pass is_painting_scrolling_background_ other PaintInfo.
@@ -152,11 +148,16 @@ struct CORE_EXPORT PaintInfo {
// Returns the fragment of the current painting object matching the current
// layer fragment.
- const FragmentData* FragmentToPaint(const LayoutObject& object) const {
+ const FragmentData* LegacyFragmentToPaint(const LayoutObject& object) const {
+ if (fragment_id_ == WTF::kNotFound) {
+ // We haven't been set up for legacy block fragmentation, so the object
+ // better not be fragmented, then.
+ DCHECK(!object.FirstFragment().NextFragment());
+ return &object.FirstFragment();
+ }
for (const auto* fragment = &object.FirstFragment(); fragment;
fragment = fragment->NextFragment()) {
- if (fragment->LogicalTopInFlowThread() ==
- fragment_logical_top_in_flow_thread_)
+ if (fragment->FragmentID() == fragment_id_)
return fragment;
}
// No fragment of the current painting object matches the layer fragment,
@@ -164,20 +165,44 @@ struct CORE_EXPORT PaintInfo {
return nullptr;
}
- // Returns the FragmentData of the specified physical fragment. If fragment
- // traversal is supported, it will map directly to the right FragmentData.
- // Otherwise we'll fall back to matching against the current
+ const FragmentData* FragmentToPaint(const LayoutObject& object) const {
+ if (const auto* box = DynamicTo<LayoutBox>(&object)) {
+ // We're are looking up FragmentData via LayoutObject, even though the
+ // object has NG fragments. This happens with objects that don't support
+ // fragment traversal, such as replaced content. We cannot use legacy-
+ // based lookup in such cases, as we might not have set a fragment ID to
+ // match against. Since we got here, though, it has to mean that we should
+ // paint the one and only fragment.
+ if (box->PhysicalFragmentCount()) {
+ // TODO(mstensho): We should DCHECK that box->PhysicalFragmentCount() is
+ // exactly 1 here (i.e. that the object is monolithic), but we are not
+ // ready for that yet, as there's code that enters legacy paint
+ // functions when we're traversing the fragment tree. See
+ // e.g. NGBoxFragmentPainter::RecordScrollHitTestData(), and how it does
+ // the job by invoking BoxPainter, which has no concept of
+ // fragments. One of the tests that would fail with such a DCHECK here
+ // is:
+ // virtual/layout_ng_block_frag/fast/multicol/overflow-across-columns.html
+ return &box->FirstFragment();
+ }
+ }
+ return LegacyFragmentToPaint(object);
+ }
+
+ // Returns the FragmentData of the specified physical fragment. If we're
+ // performing fragment traversal, it will map directly to the right
+ // FragmentData. Otherwise we'll fall back to matching against the current
// PaintLayerFragment.
const FragmentData* FragmentToPaint(
const NGPhysicalFragment& fragment) const {
- if (fragment.CanTraverse())
+ if (fragment_id_ == WTF::kNotFound)
return fragment.GetFragmentData();
- return FragmentToPaint(*fragment.GetLayoutObject());
+ return LegacyFragmentToPaint(*fragment.GetLayoutObject());
}
- void SetFragmentLogicalTopInFlowThread(LayoutUnit fragment_logical_top) {
- fragment_logical_top_in_flow_thread_ = fragment_logical_top;
- }
+ wtf_size_t FragmentID() const { return fragment_id_; }
+ void SetFragmentID(wtf_size_t id) { fragment_id_ = id; }
+ void SetIsInFragmentTraversal() { fragment_id_ = WTF::kNotFound; }
bool IsPaintingScrollingBackground() const {
DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
@@ -206,9 +231,13 @@ struct CORE_EXPORT PaintInfo {
// The box model object that originates the current painting.
const LayoutBoxModelObject* paint_container_;
- // The logical top of the current fragment of the self-painting PaintLayer
- // which initiated the current painting, in the containing flow thread.
- LayoutUnit fragment_logical_top_in_flow_thread_;
+ // The ID of the fragment that we're currently painting.
+ //
+ // This is always used in legacy block fragmentation. In NG block
+ // fragmentation, it's only used when painting self-painting non-atomic
+ // inlines (because we currently have no way of mapping from
+ // NGPhysicalFragment to FragmentData in such cases).
+ wtf_size_t fragment_id_ = WTF::kNotFound;
PaintLayerFlags paint_flags_;
const GlobalPaintFlags global_paint_flags_;
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 ea066d96c00..648f2c0bb20 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
@@ -17,7 +18,6 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
#include "third_party/blink/renderer/core/page/link_highlight.h"
@@ -32,14 +32,12 @@
namespace blink {
void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
- PaintInvalidatorContext& context,
- bool is_ng_painting) {
+ PaintInvalidatorContext& context) {
if (object.HasLayer() &&
To<LayoutBoxModelObject>(object).HasSelfPaintingLayer()) {
context.painting_layer = To<LayoutBoxModelObject>(object).Layer();
- } else if (!is_ng_painting &&
- (object.IsColumnSpanAll() ||
- object.IsFloatingWithNonContainingBlockParent())) {
+ } else if (object.IsColumnSpanAll() ||
+ object.IsFloatingWithNonContainingBlockParent()) {
// See |LayoutObject::PaintingLayer| for the special-cases of floating under
// inline and multicolumn.
// Post LayoutNG the |LayoutObject::IsFloatingWithNonContainingBlockParent|
@@ -68,8 +66,7 @@ void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
void PaintInvalidator::UpdateDirectlyCompositedContainer(
const LayoutObject& object,
- PaintInvalidatorContext& context,
- bool is_ng_painting) {
+ PaintInvalidatorContext& context) {
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
return;
@@ -88,9 +85,8 @@ void PaintInvalidator::UpdateDirectlyCompositedContainer(
context.directly_composited_container_for_stacked_contents =
context.directly_composited_container =
&object.DirectlyCompositableContainer();
- } else if (!is_ng_painting &&
- (object.IsColumnSpanAll() ||
- object.IsFloatingWithNonContainingBlockParent())) {
+ } else if (object.IsColumnSpanAll() ||
+ object.IsFloatingWithNonContainingBlockParent()) {
// In these cases, the object may belong to an ancestor of the current
// paint invalidation container, in paint order.
// Post LayoutNG the |LayoutObject::IsFloatingWithNonContainingBlockParent|
@@ -141,11 +137,6 @@ void PaintInvalidator::UpdateDirectlyCompositedContainer(
context.subtree_flags = 0;
}
}
-
- DCHECK_EQ(context.directly_composited_container,
- object.DirectlyCompositableContainer())
- << object;
- DCHECK_EQ(context.painting_layer, object.PaintingLayer()) << object;
}
void PaintInvalidator::UpdateFromTreeBuilderContext(
@@ -227,6 +218,7 @@ void PaintInvalidator::UpdateLayoutShiftTracking(
adjusted_old_paint_offset,
tree_builder_context.translation_2d_to_layout_shift_root_delta,
tree_builder_context.current.scroll_offset_to_layout_shift_root_delta,
+ tree_builder_context.current.pending_scroll_anchor_adjustment,
new_paint_offset, logical_height);
return;
}
@@ -288,6 +280,7 @@ void PaintInvalidator::UpdateLayoutShiftTracking(
box, property_tree_state, old_rect, new_rect, adjusted_old_paint_offset,
tree_builder_context.translation_2d_to_layout_shift_root_delta,
tree_builder_context.current.scroll_offset_to_layout_shift_root_delta,
+ tree_builder_context.current.pending_scroll_anchor_adjustment,
new_paint_offset);
}
}
@@ -309,9 +302,29 @@ bool PaintInvalidator::InvalidatePaint(
object.GetMutableForPainting().EnsureIsReadyForPaintInvalidation();
- UpdatePaintingLayer(object, context, /* is_ng_painting */ !!pre_paint_info);
- UpdateDirectlyCompositedContainer(object, context,
- /* is_ng_painting */ !!pre_paint_info);
+ UpdatePaintingLayer(object, context);
+ UpdateDirectlyCompositedContainer(object, context);
+
+#if DCHECK_IS_ON()
+ // Assert that the container state in the invalidation context is consistent
+ // with what the LayoutObject tree says. We cannot do this if we're fragment-
+ // traversing an "orphaned" object (an object that has a fragment inside a
+ // fragmentainer, even though not all its ancestor objects have it; this may
+ // happen to OOFs, and also to floats, if they are inside a non-atomic
+ // inline). In such cases we'll just have to live with the inconsitency, which
+ // means that we'll lose any paint effects from such "missing" ancestors.
+ if (!pre_paint_info || !pre_paint_info->is_inside_orphaned_object) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ DCHECK_EQ(context.directly_composited_container,
+ object.DirectlyCompositableContainer())
+ << object;
+ }
+ DCHECK_EQ(context.painting_layer, object.PaintingLayer()) << object;
+ }
+#endif // DCHECK_IS_ON()
+
+ if (AXObjectCache* cache = object.GetDocument().ExistingAXObjectCache())
+ cache->InvalidateBoundingBox(&object);
if (!object.ShouldCheckForPaintInvalidation() && !context.NeedsSubtreeWalk())
return false;
@@ -337,7 +350,7 @@ bool PaintInvalidator::InvalidatePaint(
}
if (pre_paint_info) {
- FragmentData& fragment_data = pre_paint_info->fragment_data;
+ FragmentData& fragment_data = *pre_paint_info->fragment_data;
context.fragment_data = &fragment_data;
if (tree_builder_context) {
@@ -368,10 +381,6 @@ bool PaintInvalidator::InvalidatePaint(
UpdateFromTreeBuilderContext(fragment_tree_builder_context, context);
UpdateLayoutShiftTracking(object, fragment_tree_builder_context,
context);
-
- if (auto* mf_checker =
- object.GetFrameView()->GetMobileFriendlinessChecker())
- mf_checker->NotifyInvalidatePaint(object);
} else {
context.old_paint_offset = fragment_data->PaintOffset();
}
@@ -388,8 +397,12 @@ bool PaintInvalidator::InvalidatePaint(
reason == PaintInvalidationReason::kJustCreated))
pending_delayed_paint_invalidations_.push_back(&object);
- if (AXObjectCache* cache = object.GetDocument().ExistingAXObjectCache())
- cache->InvalidateBoundingBox(&object);
+ if (auto* mf_checker =
+ object.GetFrameView()->GetMobileFriendlinessChecker()) {
+ if (tree_builder_context &&
+ (!pre_paint_info || pre_paint_info->is_last_for_node))
+ mf_checker->NotifyInvalidatePaint(object);
+ }
return reason != PaintInvalidationReason::kNone;
}
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 245e629d4ec..7c6d9747747 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATOR_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/paint/paint_property_tree_builder.h"
@@ -105,11 +106,10 @@ class PaintInvalidator final {
friend struct PaintInvalidatorContext;
ALWAYS_INLINE void UpdatePaintingLayer(const LayoutObject&,
- PaintInvalidatorContext&,
- bool is_ng_painting);
- ALWAYS_INLINE void UpdateDirectlyCompositedContainer(const LayoutObject&,
- PaintInvalidatorContext&,
- bool is_ng_painting);
+ PaintInvalidatorContext&);
+ ALWAYS_INLINE void UpdateDirectlyCompositedContainer(
+ const LayoutObject&,
+ PaintInvalidatorContext&);
ALWAYS_INLINE void UpdateFromTreeBuilderContext(
const PaintPropertyTreeBuilderFragmentContext&,
PaintInvalidatorContext&);
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 4eec5f301b4..f7a02c22431 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
@@ -48,6 +48,7 @@
#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/containers/adapters.h"
+#include "build/build_config.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -85,6 +86,7 @@
#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/rounded_border_geometry.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/platform/bindings/runtime_call_stats.h"
@@ -195,7 +197,7 @@ PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
needs_cull_rect_update_(false),
forces_children_cull_rect_update_(false),
descendant_needs_cull_rect_update_(false),
- previous_paint_result_(kFullyPainted),
+ previous_paint_result_(kMayBeClippedByCullRect),
needs_paint_phase_descendant_outlines_(false),
needs_paint_phase_float_(false),
has_non_isolated_descendant_with_blend_mode_(false),
@@ -206,6 +208,7 @@ PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
self_painting_status_changed_(false),
filter_on_effect_node_dirty_(false),
backdrop_filter_on_effect_node_dirty_(false),
+ has_filter_that_moves_pixels_(false),
is_under_svg_hidden_container_(false),
descendant_has_direct_or_scrolling_compositing_reason_(false),
needs_compositing_reasons_update_(
@@ -969,10 +972,8 @@ PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor,
// inline parent to find the actual containing layer through the containing
// block chain.
// Column span need to find the containing layer through its containing block.
- // A rendered legend needs to find the containing layer through its containing
- // block to skip anonymous fieldset content box.
if ((!Parent() || Parent()->GetLayoutObject().IsLayoutBlock()) &&
- !layout_object.IsColumnSpanAll() && !layout_object.IsRenderedLegend())
+ !layout_object.IsColumnSpanAll())
return Parent();
return SlowContainingLayer(ancestor, skipped_ancestor, &layout_object);
@@ -1135,6 +1136,21 @@ PaintLayer* PaintLayer::EnclosingDirectlyCompositableLayer(
return nullptr;
}
+const PaintLayer* PaintLayer::EnclosingCompositedScrollingLayerUnderPagination(
+ IncludeSelfOrNot include_self_or_not) const {
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
+ const auto* start_layer =
+ include_self_or_not == kIncludeSelf ? this : CompositingContainer();
+ for (const auto* curr = start_layer; curr && curr->EnclosingPaginationLayer();
+ curr = curr->CompositingContainer()) {
+ if (const auto* scrollable_area = curr->GetScrollableArea()) {
+ if (scrollable_area->NeedsCompositedScrolling())
+ return curr;
+ }
+ }
+ return nullptr;
+}
+
void PaintLayer::SetNeedsCompositingInputsUpdate(bool mark_ancestor_flags) {
SetNeedsCompositingInputsUpdateInternal();
@@ -1469,8 +1485,17 @@ void PaintLayer::RemoveOnlyThisLayerAfterStyleChange(
if (!parent_)
return;
- if (old_style && GetLayoutObject().IsStacked(*old_style))
- DirtyStackingContextZOrderLists();
+ if (old_style) {
+ if (GetLayoutObject().IsStacked(*old_style))
+ DirtyStackingContextZOrderLists();
+
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ PaintLayerPainter::PaintedOutputInvisible(*old_style)) {
+ // This layer is removed because opacity becomes 1. Do the same as
+ // StyleDidChange() on change of PaintedOutputInvisible().
+ GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation();
+ }
+ }
bool did_set_paint_invalidation = false;
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
@@ -1675,10 +1700,12 @@ bool PaintLayer::RequiresScrollableArea() const {
// PaintLayerScrollableArea.
if (GetLayoutBox()->CanResize())
return true;
- // With custom scrollbars, we need a PaintLayerScrollableArea
- // so we can calculate the size of scrollbar gutters.
- if (GetLayoutObject().StyleRef().IsScrollbarGutterForce() &&
- GetLayoutObject().StyleRef().HasPseudoElementStyle(kPseudoIdScrollbar)) {
+ // With custom scrollbars unfortunately we may need a PaintLayerScrollableArea
+ // to be able to calculate the size of scrollbar gutters.
+ const ComputedStyle& style = GetLayoutObject().StyleRef();
+ if (style.IsScrollbarGutterStable() &&
+ style.OverflowBlockDirection() == EOverflow::kHidden &&
+ style.HasPseudoElementStyle(kPseudoIdScrollbar)) {
return true;
}
return false;
@@ -1711,26 +1738,18 @@ bool PaintLayer::HasOverflowControls() const {
GetLayoutObject().StyleRef().HasResize());
}
-void PaintLayer::AppendSingleFragmentIgnoringPagination(
+void PaintLayer::AppendSingleFragmentIgnoringPaginationForHitTesting(
PaintLayerFragments& fragments,
- const PaintLayer* root_layer,
- const CullRect* cull_rect,
- OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
- ShouldRespectOverflowClipType respect_overflow_clip,
- const PhysicalOffset* offset_from_root,
- const PhysicalOffset& sub_pixel_accumulation) const {
+ ShouldRespectOverflowClipType respect_overflow_clip) const {
PaintLayerFragment fragment;
- ClipRectsContext clip_rects_context(
- root_layer, &root_layer->GetLayoutObject().FirstFragment(),
- overlay_scrollbar_clip_behavior, respect_overflow_clip,
- sub_pixel_accumulation);
- Clipper(GeometryMapperOption::kUseGeometryMapper)
- .CalculateRects(clip_rects_context, &GetLayoutObject().FirstFragment(),
- cull_rect, fragment.layer_bounds,
- fragment.background_rect, fragment.foreground_rect,
- offset_from_root);
- fragment.root_fragment_data = &root_layer->GetLayoutObject().FirstFragment();
fragment.fragment_data = &GetLayoutObject().FirstFragment();
+ ClipRectsContext clip_rects_context(this, fragment.fragment_data,
+ kExcludeOverlayScrollbarSizeForHitTesting,
+ respect_overflow_clip);
+ Clipper(GeometryMapperOption::kUseGeometryMapper)
+ .CalculateRects(clip_rects_context, fragment.fragment_data, nullptr,
+ fragment.layer_bounds, fragment.background_rect,
+ fragment.foreground_rect);
if (GetLayoutObject().CanTraversePhysicalFragments()) {
// Make sure that we actually traverse the fragment tree, by providing a
// physical fragment. Otherwise we'd fall back to LayoutObject traversal.
@@ -1745,8 +1764,12 @@ bool PaintLayer::ShouldFragmentCompositedBounds(
const PaintLayer* compositing_layer) const {
if (!EnclosingPaginationLayer())
return false;
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return true;
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // We should not fragment composited scrolling layers and descendants, which
+ // is not only to render the scroller correctly, but also to prevent
+ // multiple cc::Layers with the same scrolling element id.
+ return !EnclosingCompositedScrollingLayerUnderPagination(kIncludeSelf);
+ }
if (Transform() &&
!PaintsWithDirectReasonIntoOwnBacking(kGlobalPaintNormalPhase))
return true;
@@ -1763,7 +1786,7 @@ bool PaintLayer::ShouldFragmentCompositedBounds(
void PaintLayer::CollectFragments(
PaintLayerFragments& fragments,
const PaintLayer* root_layer,
- const CullRect* cull_rect,
+ const CullRect* painting_cull_rect,
OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
ShouldRespectOverflowClipType respect_overflow_clip,
const PhysicalOffset* offset_from_root,
@@ -1794,58 +1817,63 @@ void PaintLayer::CollectFragments(
wtf_size_t physical_fragment_idx = 0u;
for (auto* fragment_data = &first_fragment_data; fragment_data;
fragment_data = fragment_data->NextFragment(), physical_fragment_idx++) {
- const FragmentData* root_fragment_data;
- if (root_layer == this) {
- root_fragment_data = fragment_data;
- } else if (should_match_fragments) {
- for (root_fragment_data = &first_root_fragment_data; root_fragment_data;
- root_fragment_data = root_fragment_data->NextFragment()) {
- if (root_fragment_data->LogicalTopInFlowThread() ==
- fragment_data->LogicalTopInFlowThread())
- break;
+ // If CullRectUpdateEnabled, skip fragment geometry logic if we are
+ // collecting fragments for painting.
+ if (!RuntimeEnabledFeatures::CullRectUpdateEnabled() ||
+ !painting_cull_rect) {
+ const FragmentData* root_fragment_data;
+ if (root_layer == this) {
+ root_fragment_data = fragment_data;
+ } else if (should_match_fragments) {
+ for (root_fragment_data = &first_root_fragment_data; root_fragment_data;
+ root_fragment_data = root_fragment_data->NextFragment()) {
+ if (root_fragment_data->FragmentID() == fragment_data->FragmentID())
+ break;
+ }
+ } else {
+ root_fragment_data = &first_root_fragment_data;
}
- } else {
- root_fragment_data = &first_root_fragment_data;
- }
- bool cant_find_fragment = !root_fragment_data;
- if (cant_find_fragment) {
- DCHECK(should_match_fragments);
- // Fall back to the first fragment, in order to have
- // PaintLayerClipper at least compute |fragment.layer_bounds|.
- root_fragment_data = &first_root_fragment_data;
- }
+ bool cant_find_fragment = !root_fragment_data;
+ if (cant_find_fragment) {
+ DCHECK(should_match_fragments);
+ // Fall back to the first fragment, in order to have
+ // PaintLayerClipper at least compute |fragment.layer_bounds|.
+ root_fragment_data = &first_root_fragment_data;
+ }
- ClipRectsContext clip_rects_context(
- root_layer, root_fragment_data, overlay_scrollbar_clip_behavior,
- respect_overflow_clip, sub_pixel_accumulation);
-
- absl::optional<CullRect> fragment_cull_rect;
- if (cull_rect) {
- // |cull_rect| is in the coordinate space of |root_layer| (i.e. the
- // space of |root_layer|'s first fragment). Map the rect to the space of
- // the current root fragment.
- auto rect = cull_rect->Rect();
- first_root_fragment_data.MapRectToFragment(*root_fragment_data, rect);
- fragment_cull_rect.emplace(rect);
- }
+ ClipRectsContext clip_rects_context(
+ root_layer, root_fragment_data, overlay_scrollbar_clip_behavior,
+ respect_overflow_clip, sub_pixel_accumulation);
+
+ absl::optional<CullRect> fragment_cull_rect;
+ if (painting_cull_rect) {
+ // |cull_rect| is in the coordinate space of |root_layer| (i.e. the
+ // space of |root_layer|'s first fragment). Map the rect to the space of
+ // the current root fragment.
+ auto rect = painting_cull_rect->Rect();
+ first_root_fragment_data.MapRectToFragment(*root_fragment_data, rect);
+ fragment_cull_rect.emplace(rect);
+ }
- Clipper(GeometryMapperOption::kUseGeometryMapper)
- .CalculateRects(
- clip_rects_context, fragment_data,
- fragment_cull_rect ? &*fragment_cull_rect : nullptr,
- fragment.layer_bounds, fragment.background_rect,
- fragment.foreground_rect,
- offset_from_root_can_be_used ? offset_from_root : nullptr);
-
- if (cant_find_fragment) {
- // If we couldn't find a matching fragment when |should_match_fragments|
- // was true, then fall back to no clip.
- fragment.background_rect.Reset();
- fragment.foreground_rect.Reset();
+ Clipper(GeometryMapperOption::kUseGeometryMapper)
+ .CalculateRects(
+ clip_rects_context, fragment_data,
+ fragment_cull_rect ? &*fragment_cull_rect : nullptr,
+ fragment.layer_bounds, fragment.background_rect,
+ fragment.foreground_rect,
+ offset_from_root_can_be_used ? offset_from_root : nullptr);
+
+ if (cant_find_fragment) {
+ // If we couldn't find a matching fragment when |should_match_fragments|
+ // was true, then fall back to no clip.
+ fragment.background_rect.Reset();
+ fragment.foreground_rect.Reset();
+ }
+
+ fragment.root_fragment_data = root_fragment_data;
}
- fragment.root_fragment_data = root_fragment_data;
fragment.fragment_data = fragment_data;
if (GetLayoutObject().CanTraversePhysicalFragments()) {
@@ -1974,6 +2002,16 @@ HitTestingTransformState PaintLayer::CreateLocalTransformState(
recursion_data.location.TransformedRect(),
FloatQuad(FloatRect(recursion_data.rect)));
+ if (container_transform_state &&
+ RuntimeEnabledFeatures::TransformInteropEnabled() &&
+ (!container_layer || &container_layer->GetLayoutObject() !=
+ GetLayoutObject().NearestAncestorForElement())) {
+ // Our parent *layer* is preserve-3d, but that preserve-3d doesn't
+ // apply to this layer because our element is not a child of our
+ // parent layer's element.
+ transform_state.Flatten();
+ }
+
PhysicalOffset offset;
if (container_transform_state)
ConvertToLayerCoords(container_layer, offset);
@@ -2203,11 +2241,9 @@ PaintLayer* PaintLayer::HitTestLayer(PaintLayer* root_layer,
if (recursion_data.intersects_location) {
layer_fragments.emplace();
if (applied_transform) {
- DCHECK(root_layer == this);
- PhysicalOffset ignored;
- AppendSingleFragmentIgnoringPagination(
- *layer_fragments, root_layer, nullptr,
- kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, &ignored);
+ DCHECK_EQ(root_layer, this);
+ AppendSingleFragmentIgnoringPaginationForHitTesting(*layer_fragments,
+ clip_behavior);
} else {
CollectFragments(*layer_fragments, root_layer, nullptr,
kExcludeOverlayScrollbarSizeForHitTesting,
@@ -2872,19 +2908,11 @@ void PaintLayer::ExpandRectForSelfPaintingDescendants(
if (!HasSelfPaintingLayerDescendant())
return;
- if (const auto* box = GetLayoutBox()) {
- // If the layer clips overflow and all descendants are contained, then no
- // need to expand for children. Not checking kIncludeAncestorClips because
- // the clip of the current layer is always applied. The doesn't check
- // whether the non-contained descendants are actual descendants of this
- // layer in paint order because it's not easy.
- if (box->ShouldClipOverflowAlongBothAxis() &&
- !HasNonContainedAbsolutePositionDescendant() &&
- !(HasFixedPositionDescendant() &&
- !box->CanContainFixedPositionObjects())) {
- return;
- }
- }
+ // If the layer is known to clip the whole subtree, then we don't need to
+ // expand for children. Not checking kIncludeAncestorClips because the clip of
+ // the current layer is always applied.
+ if (KnownToClipSubtree())
+ return;
PaintLayerPaintOrderIterator iterator(*this, kAllChildren);
while (PaintLayer* child_layer = iterator.Next()) {
@@ -2901,6 +2929,22 @@ void PaintLayer::ExpandRectForSelfPaintingDescendants(
}
}
+bool PaintLayer::KnownToClipSubtree() const {
+ if (const auto* box = GetLayoutBox()) {
+ if (!box->ShouldClipOverflowAlongBothAxis())
+ return false;
+ if (HasNonContainedAbsolutePositionDescendant())
+ return false;
+ if (HasFixedPositionDescendant() && !box->CanContainFixedPositionObjects())
+ return false;
+ // The root frame's clip is special at least in Android WebView.
+ if (is_root_layer_ && box->GetFrame()->IsLocalRoot())
+ return false;
+ return true;
+ }
+ return false;
+}
+
PhysicalRect PaintLayer::BoundingBoxForCompositing() const {
return BoundingBoxForCompositingInternal(
*this, nullptr,
@@ -3131,8 +3175,8 @@ bool PaintLayer::SupportsSubsequenceCaching() const {
if (EnclosingPaginationLayer())
return false;
- // SVG paints atomically.
- if (GetLayoutObject().IsSVGRoot())
+ // SVG root and SVG foreign object paint atomically.
+ if (GetLayoutObject().IsSVGRoot() || GetLayoutObject().IsSVGForeignObject())
return true;
// Don't create subsequence for the document element because the subsequence
@@ -3141,8 +3185,8 @@ bool PaintLayer::SupportsSubsequenceCaching() const {
if (GetLayoutObject().IsDocumentElement())
return false;
- // Create subsequence for only stacking contexts whose painting are atomic.
- return GetLayoutObject().IsStackingContext();
+ // Create subsequence for only stacked objects whose paintings are atomic.
+ return GetLayoutObject().IsStacked();
}
ScrollingCoordinator* PaintLayer::GetScrollingCoordinator() {
@@ -3157,6 +3201,7 @@ bool PaintLayer::CompositesWithTransform() const {
bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
const PhysicalRect& local_rect,
bool should_check_children) const {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
// We can't use hasVisibleContent(), because that will be true if our
// layoutObject is hidden, but some child is visible and that child doesn't
// cover the entire rect.
@@ -3201,6 +3246,7 @@ bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
const PhysicalRect& local_rect) const {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
PaintLayerPaintOrderReverseIterator reverse_iterator(*this, kAllChildren);
while (PaintLayer* child_layer = reverse_iterator.Next()) {
// Stop at composited paint boundaries and non-self-painting layers.
@@ -3228,8 +3274,7 @@ bool PaintLayer::ShouldBeSelfPaintingLayer() const {
return GetLayoutObject().LayerTypeRequired() == kNormalPaintLayer ||
(scrollable_area_ && scrollable_area_->HasOverlayOverflowControls()) ||
ScrollsOverflow() ||
- (RuntimeEnabledFeatures::CompositeSVGEnabled() &&
- GetLayoutObject().IsSVGRoot() &&
+ (GetLayoutObject().IsSVGRoot() &&
To<LayoutSVGRoot>(GetLayoutObject())
.HasDescendantCompositingReasons());
}
@@ -3420,6 +3465,8 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
UpdateScrollableArea();
+ has_filter_that_moves_pixels_ = ComputeHasFilterThatMovesPixels();
+
if (AttemptDirectCompositingUpdate(diff, old_style)) {
if (diff.HasDifference())
GetLayoutObject().SetNeedsPaintPropertyUpdate();
@@ -3483,40 +3530,39 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
UpdateBackdropFilters(old_style, new_style);
UpdateClipPath(old_style, new_style);
- if (!SelfNeedsRepaint()) {
- if (diff.ZIndexChanged()) {
- // 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.
- SetNeedsRepaint();
- } else if (old_style) {
- bool new_painted_output_invisible =
- PaintLayerPainter::PaintedOutputInvisible(new_style);
- if (PaintLayerPainter::PaintedOutputInvisible(*old_style) !=
- new_painted_output_invisible) {
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // Though CompositeAfterPaint ignores PaintedOutputInvisible during
- // paint, we still force repaint to ensure FCP/LCP will be reported.
- // See crbug.com/1184903. Only SetNeedsRepaint() won't work because
- // we won't repaint the display items which are already in the old
- // painted result. TODO(crbug.com/1104218): Optimize this.
- if (!new_painted_output_invisible)
- GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation();
- } else {
- // Change of PaintedOutputInvisible() will affect existence of paint
- // chunks, so needs repaint.
- SetNeedsRepaint();
- }
+ if (diff.ZIndexChanged()) {
+ // 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.
+ if (auto* stacking_context = AncestorStackingContext())
+ stacking_context->SetNeedsRepaint();
+ }
+
+ if (old_style) {
+ bool new_painted_output_invisible =
+ PaintLayerPainter::PaintedOutputInvisible(new_style);
+ if (PaintLayerPainter::PaintedOutputInvisible(*old_style) !=
+ new_painted_output_invisible) {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // Force repaint of the subtree for two purposes:
+ // 1. To ensure FCP/LCP will be reported. See crbug.com/1184903.
+ // 2. To update effectively_invisible flags of PaintChunks.
+ // TODO(crbug.com/1104218): Optimize this.
+ GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation();
+ } else {
+ // Change of PaintedOutputInvisible() will affect existence of paint
+ // chunks, so needs repaint.
+ SetNeedsRepaint();
}
}
}
}
-LayoutSize PaintLayer::PixelSnappedScrolledContentOffset() const {
+IntPoint PaintLayer::PixelSnappedScrolledContentOffset() const {
if (GetLayoutObject().IsScrollContainer())
return GetLayoutBox()->PixelSnappedScrolledContentOffset();
- return LayoutSize();
+ return IntPoint();
}
PaintLayerClipper PaintLayer::Clipper(
@@ -3666,7 +3712,7 @@ PhysicalRect PaintLayer::MapRectForFilter(const PhysicalRect& rect) const {
return PhysicalRect::EnclosingRect(MapRectForFilter(FloatRect(rect)));
}
-bool PaintLayer::HasFilterThatMovesPixels() const {
+bool PaintLayer::ComputeHasFilterThatMovesPixels() const {
if (!HasFilterInducingProperty())
return false;
const ComputedStyle& style = GetLayoutObject().StyleRef();
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 9ec703a5b60..92145820440 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
@@ -313,7 +313,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// testing, intersection observer). Most other cases should use the unsnapped
// offset from LayoutBox (for layout) or the source offset from the
// ScrollableArea.
- LayoutSize PixelSnappedScrolledContentOffset() const;
+ IntPoint PixelSnappedScrolledContentOffset() const;
// FIXME: size() should DCHECK(!needs_position_update_) as well, but that
// fails in some tests, for example, fast/repaint/clipped-relative.html.
@@ -408,6 +408,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
PaintLayer* EnclosingDirectlyCompositableLayer(IncludeSelfOrNot) const;
+ // For CompositeAfterPaint, but not for LayoutNGBlockFragmentation.
+ const PaintLayer* EnclosingCompositedScrollingLayerUnderPagination(
+ IncludeSelfOrNot) const;
+
// https://crbug.com/751768, this function can return nullptr sometimes.
// Always check the result before using it, don't just DCHECK.
PaintLayer* EnclosingLayerForPaintInvalidationCrossingFrameBoundaries() const;
@@ -619,6 +623,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
PhysicalOffset&);
bool PaintsWithTransparency(GlobalPaintFlags global_paint_flags) const {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
return IsTransparent() && !PaintsIntoOwnBacking(global_paint_flags);
}
@@ -681,7 +686,9 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// Calls the above, rounding outwards.
PhysicalRect MapRectForFilter(const PhysicalRect&) const;
- bool HasFilterThatMovesPixels() const;
+ bool HasFilterThatMovesPixels() const {
+ return has_filter_that_moves_pixels_;
+ }
PaintLayerResourceInfo* ResourceInfo() const {
return rare_data_ ? rare_data_->resource_info.Get() : nullptr;
@@ -990,19 +997,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void DidUpdateScrollsOverflow();
- void AppendSingleFragmentIgnoringPagination(
- PaintLayerFragments&,
- const PaintLayer* root_layer,
- const CullRect* cull_rect,
- OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize,
- ShouldRespectOverflowClipType = kRespectOverflowClip,
- const PhysicalOffset* offset_from_root = nullptr,
- const PhysicalOffset& sub_pixel_accumulation = PhysicalOffset()) const;
-
void CollectFragments(
PaintLayerFragments&,
const PaintLayer* root_layer,
- const CullRect* cull_rect,
+ const CullRect* painting_cull_rect,
OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize,
ShouldRespectOverflowClipType = kRespectOverflowClip,
const PhysicalOffset* offset_from_root = nullptr,
@@ -1162,6 +1160,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
needs_paint_offset_translation_for_compositing_ = b;
}
+ bool KnownToClipSubtree() const;
+
private:
PhysicalRect LocalBoundingBoxForCompositingOverlapTest() const;
bool PaintsWithDirectReasonIntoOwnBacking(GlobalPaintFlags) const;
@@ -1185,6 +1185,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void UpdateHasSelfPaintingLayerDescendant() const;
+ void AppendSingleFragmentIgnoringPaginationForHitTesting(
+ PaintLayerFragments&,
+ ShouldRespectOverflowClipType) const;
+
struct HitTestRecursionData {
const PhysicalRect& rect;
// Whether location.Intersects(rect) returns true.
@@ -1333,6 +1337,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
needs_reorder_overlay_overflow_controls_ = b;
}
+ bool ComputeHasFilterThatMovesPixels() const;
+
// Self-painting layer is an optimization where we avoid the heavy Layer
// painting machinery for a Layer allocated only to handle the overflow clip
// case.
@@ -1404,6 +1410,9 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
unsigned filter_on_effect_node_dirty_ : 1;
unsigned backdrop_filter_on_effect_node_dirty_ : 1;
+ // Caches |ComputeHasFilterThatMovesPixels()|, updated on style changes.
+ unsigned has_filter_that_moves_pixels_ : 1;
+
// True if the current subtree is underneath a LayoutSVGHiddenContainer
// ancestor.
unsigned is_under_svg_hidden_container_ : 1;
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 85d08c83b45..92e3f133bfe 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
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
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 680c0b5400b..707bc99c901 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
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_fragment.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_fragment.h
index 9ffa07ab179..ab911889fa2 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_fragment.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_fragment.h
@@ -81,6 +81,7 @@ struct PaintLayerFragment {
// Defines the coordinate space of the above rects:
// root_fragment_data->LocalBorderBoxProperties().Transform() +
// root_fragment_data.PaintOffset().
+ // It's for legacy cull rect calculation (pre-CompositeAfterPaint) only.
const FragmentData* root_fragment_data = nullptr;
// The corresponding FragmentData of this structure.
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 34ef71b4929..b263886d8a2 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
@@ -25,6 +25,7 @@
#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_effectively_invisible.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_hint.h"
#include "third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -59,6 +60,9 @@ bool PaintLayerPainter::PaintedOutputInvisible(const ComputedStyle& style) {
if (style.HasWillChangeOpacityHint())
return false;
+ if (style.HasCurrentOpacityAnimation())
+ return false;
+
// 0.0004f < 1/2048. With 10-bit color channels (only available on the
// newest Macs; otherwise it's 8-bit), we see that an alpha of 1/2048 or
// less leads to a color output of less than 0.5 in all channels, hence
@@ -87,17 +91,27 @@ PaintResult PaintLayerPainter::Paint(
// In CompositeAfterPaint we simplify this optimization by painting even when
// effectively invisible but skipping the painted content during layerization
// in PaintArtifactCompositor.
- if (paint_layer_.PaintsWithTransparency(
- painting_info.GetGlobalPaintFlags())) {
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
- PaintedOutputInvisible(paint_layer_.GetLayoutObject().StyleRef()))
- return kFullyPainted;
-
- paint_flags |= kPaintLayerHaveTransparency;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ paint_layer_.PaintsWithTransparency(
+ painting_info.GetGlobalPaintFlags()) &&
+ PaintedOutputInvisible(paint_layer_.GetLayoutObject().StyleRef())) {
+ return kFullyPainted;
}
- // If the transform can't be inverted, then don't paint anything.
- if (paint_layer_.PaintsWithTransform(painting_info.GetGlobalPaintFlags()) &&
+ // If the transform can't be inverted, don't paint anything. We still need
+ // to paint with CompositeAfterPaint if there are animations to ensure the
+ // animation can be setup to run on the compositor.
+ bool paint_non_invertible_transforms = false;
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ const auto* properties =
+ paint_layer_.GetLayoutObject().FirstFragment().PaintProperties();
+ if (properties && properties->Transform() &&
+ properties->Transform()->HasActiveTransformAnimation()) {
+ paint_non_invertible_transforms = true;
+ }
+ }
+ if (!paint_non_invertible_transforms &&
+ paint_layer_.PaintsWithTransform(painting_info.GetGlobalPaintFlags()) &&
!paint_layer_.RenderableTransform(painting_info.GetGlobalPaintFlags())
.IsInvertible()) {
return kFullyPainted;
@@ -211,15 +225,37 @@ bool PaintLayerPainter::ShouldUseInfiniteCullRectInternal(
if (const auto* properties =
paint_layer_.GetLayoutObject().FirstFragment().PaintProperties()) {
+ // Cull rect mapping doesn't work under perspective in some cases.
+ // See http://crbug.com/887558 for details.
if (properties->Perspective())
return true;
if (for_cull_rect_update) {
- // A CSS transform can also have perspective like
- // "transform: perspective(100px) rotateY(45deg)".
if (const auto* transform = properties->Transform()) {
+ // A CSS transform can also have perspective like
+ // "transform: perspective(100px) rotateY(45deg)". In these cases, we
+ // also want to skip cull rect mapping. See http://crbug.com/887558 for
+ // details.
if (!transform->IsIdentityOr2DTranslation() &&
- transform->Matrix().HasPerspective())
+ transform->Matrix().HasPerspective()) {
+ return true;
+ }
+
+ // Ensure content under animating transforms is not culled out, even if
+ // the initial matrix is non-invertible.
+ if (transform->HasActiveTransformAnimation() &&
+ !transform->IsIdentityOr2DTranslation() &&
+ !transform->Matrix().IsInvertible()) {
+ return true;
+ }
+
+ // As an optimization, skip cull rect updating for non-composited
+ // transforms which have already been painted. This is because the cull
+ // rect update, which needs to do complex mapping of the cull rect, can
+ // be more expensive than over-painting.
+ if (!transform->HasDirectCompositingReasons() &&
+ paint_layer_.PreviousPaintResult() == kFullyPainted) {
return true;
+ }
}
}
}
@@ -277,35 +313,7 @@ void PaintLayerPainter::AdjustForPaintProperties(
return;
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- auto& cull_rect = painting_info.cull_rect;
- // CullRect::ApplyTransforms() requires the cull rect in the source
- // transform space. Convert cull_rect from the root layer's local space.
- //
- // TODO(paint-dev): Become block fragmentation aware. Just using the first
- // fragment seems wrong.
- cull_rect.MoveBy(RoundedIntPoint(first_root_fragment.PaintOffset()));
- absl::optional<CullRect> old_cull_rect;
- if (!paint_layer_.SelfOrDescendantNeedsRepaint() &&
- !RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
- old_cull_rect = paint_layer_.PreviousCullRect();
- // Convert old_cull_rect into the layer's transform space.
- old_cull_rect->MoveBy(RoundedIntPoint(first_fragment.PaintOffset()));
- }
- if (paint_flags & kPaintLayerPaintingOverflowContents) {
- // Use PostScrollTranslation as the source transform to avoid clipping
- // of the scrolling contents in CullRect::ApplyTransforms().
- source_transform = &first_root_fragment.PostScrollTranslation();
- // Map cull_rect into scrolling contents space (i.e. source_transform).
- if (const auto* properties = first_root_fragment.PaintProperties()) {
- if (const auto* scroll_translation = properties->ScrollTranslation())
- cull_rect.Move(-scroll_translation->Translation2D());
- }
- }
- cull_rect.ApplyTransforms(source_transform->Unalias(),
- destination_transform.Unalias(), old_cull_rect);
- // Convert cull_rect from the layer's transform space to the layer's local
- // space.
- cull_rect.MoveBy(-RoundedIntPoint(first_fragment.PaintOffset()));
+ DCHECK(RuntimeEnabledFeatures::CullRectUpdateEnabled());
} else if (!painting_info.cull_rect.IsInfinite()) {
auto rect = painting_info.cull_rect.Rect();
const FragmentData& primary_stitching_fragment =
@@ -432,21 +440,6 @@ PaintResult PaintLayerPainter::PaintLayerContents(
!paint_layer_.IsUnderSVGHiddenContainer() && is_self_painting_layer &&
!is_painting_overlay_overflow_controls;
- bool should_create_subsequence =
- should_paint_content &&
- ShouldCreateSubsequence(paint_layer_, context, painting_info);
-
- absl::optional<SubsequenceRecorder> subsequence_recorder;
- if (should_create_subsequence) {
- if (!ShouldRepaintSubsequence(paint_layer_, painting_info) &&
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context,
- paint_layer_)) {
- return paint_layer_.PreviousPaintResult();
- }
- DCHECK(paint_layer_.SupportsSubsequenceCaching());
- subsequence_recorder.emplace(context, paint_layer_);
- }
-
// TODO(paint-dev): Become block fragmentation aware. Unconditionally using
// the first fragment doesn't seem right.
PhysicalOffset offset_from_root = object.FirstFragment().PaintOffset();
@@ -458,17 +451,36 @@ PaintResult PaintLayerPainter::PaintLayerContents(
if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
if (object.FirstFragment().NextFragment()) {
result = kMayBeClippedByCullRect;
- } else if (!object.FirstFragment().GetCullRect().Rect().Contains(
- visual_rect)) {
- result = kMayBeClippedByCullRect;
- } else if (const auto* box = DynamicTo<LayoutBox>(object)) {
- PhysicalRect contents_visual_rect =
- box->PhysicalContentsVisualOverflowRect();
- contents_visual_rect.Move(object.FirstFragment().PaintOffset());
- if (!PhysicalRect(object.FirstFragment().GetContentsCullRect().Rect())
- .Contains(contents_visual_rect)) {
+ } else {
+ IntRect cull_rect = object.FirstFragment().GetCullRect().Rect();
+ bool cull_rect_intersects_self = cull_rect.Intersects(visual_rect);
+ if (!cull_rect.Contains(visual_rect))
result = kMayBeClippedByCullRect;
+
+ bool cull_rect_intersects_contents = true;
+ if (const auto* box = DynamicTo<LayoutBox>(object)) {
+ PhysicalRect contents_visual_rect =
+ box->PhysicalContentsVisualOverflowRect();
+ contents_visual_rect.Move(object.FirstFragment().PaintOffset());
+ PhysicalRect contents_cull_rect(
+ object.FirstFragment().GetContentsCullRect().Rect());
+ cull_rect_intersects_contents =
+ contents_cull_rect.Intersects(contents_visual_rect);
+ if (!contents_cull_rect.Contains(contents_visual_rect))
+ result = kMayBeClippedByCullRect;
+ } else {
+ cull_rect_intersects_contents = cull_rect_intersects_self;
}
+
+ if (!cull_rect_intersects_self && !cull_rect_intersects_contents) {
+ if (!is_painting_overflow_contents &&
+ paint_layer_.KnownToClipSubtree()) {
+ paint_layer_.SetPreviousPaintResult(kMayBeClippedByCullRect);
+ return kMayBeClippedByCullRect;
+ }
+ should_paint_content = false;
+ }
+
// The above doesn't consider clips on non-self-painting contents.
// Will update in ScopedBoxContentsPaintState.
}
@@ -485,26 +497,45 @@ PaintResult PaintLayerPainter::PaintLayerContents(
if (should_paint_content || should_paint_self_outline ||
is_painting_overlay_overflow_controls) {
- // Collect the fragments. This will compute the clip rectangles and paint
- // offsets for each layer fragment.
+ // Collect the fragments. If CullRectUpdate is enabled, this will just
+ // create a light-weight adapter from FragmentData to PaintLayerFragment
+ // and we'll remove the adapter in the future. Otherwise this will compute
+ // the clip rectangles and paint offsets for each layer fragment.
paint_layer_.CollectFragments(
layer_fragments, local_painting_info.root_layer,
&local_painting_info.cull_rect, kIgnoreOverlayScrollbarSize,
respect_overflow_clip, &offset_from_root,
local_painting_info.sub_pixel_accumulation);
- // PaintLayer::CollectFragments depends on the paint dirty rect in
- // complicated ways. For now, always assume a partially painted output
- // for fragmented content.
- if (layer_fragments.size() > 1)
- result = kMayBeClippedByCullRect;
-
- if (should_paint_content) {
- should_paint_content = AtLeastOneFragmentIntersectsDamageRect(
- layer_fragments, local_painting_info, paint_flags, offset_from_root);
- if (!should_paint_content)
+ if (!RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
+ // PaintLayer::CollectFragments depends on the paint dirty rect in
+ // complicated ways. For now, always assume a partially painted output
+ // for fragmented content.
+ if (layer_fragments.size() > 1)
result = kMayBeClippedByCullRect;
+
+ if (should_paint_content) {
+ should_paint_content = AtLeastOneFragmentIntersectsDamageRect(
+ layer_fragments, local_painting_info, paint_flags,
+ offset_from_root);
+ if (!should_paint_content)
+ result = kMayBeClippedByCullRect;
+ }
+ }
+ }
+
+ bool should_create_subsequence =
+ should_paint_content &&
+ ShouldCreateSubsequence(paint_layer_, context, painting_info);
+ absl::optional<SubsequenceRecorder> subsequence_recorder;
+ if (should_create_subsequence) {
+ if (!ShouldRepaintSubsequence(paint_layer_, painting_info) &&
+ SubsequenceRecorder::UseCachedSubsequenceIfPossible(context,
+ paint_layer_)) {
+ return paint_layer_.PreviousPaintResult();
}
+ DCHECK(paint_layer_.SupportsSubsequenceCaching());
+ subsequence_recorder.emplace(context, paint_layer_);
}
bool is_painting_root_layer = (&paint_layer_) == painting_info.root_layer;
@@ -524,6 +555,11 @@ PaintResult PaintLayerPainter::PaintLayerContents(
!is_painting_overlay_overflow_controls;
bool is_video = IsA<LayoutVideo>(object);
+ absl::optional<ScopedEffectivelyInvisible> effectively_invisible;
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ PaintedOutputInvisible(object.StyleRef()))
+ effectively_invisible.emplace(context.GetPaintController());
+
absl::optional<ScopedPaintChunkHint> paint_chunk_hint;
if (should_paint_content) {
paint_chunk_hint.emplace(context.GetPaintController(),
@@ -623,6 +659,8 @@ bool PaintLayerPainter::AtLeastOneFragmentIntersectsDamageRect(
const PaintLayerPaintingInfo& local_painting_info,
PaintLayerFlags local_paint_flags,
const PhysicalOffset& offset_from_root) {
+ DCHECK(!RuntimeEnabledFeatures::CullRectUpdateEnabled());
+
if (&paint_layer_ == local_painting_info.root_layer &&
(local_paint_flags & kPaintLayerPaintingOverflowContents))
return true;
@@ -736,18 +774,19 @@ void PaintLayerPainter::PaintFragmentWithPhase(
context.GetPaintController(), chunk_properties, paint_layer_,
DisplayItem::PaintPhaseToDrawingType(phase));
- PaintInfo paint_info(
- context, cull_rect, phase, painting_info.GetGlobalPaintFlags(),
- paint_flags, &painting_info.root_layer->GetLayoutObject(),
- fragment.fragment_data ? fragment.fragment_data->LogicalTopInFlowThread()
- : LayoutUnit());
+ PaintInfo paint_info(context, cull_rect, phase,
+ painting_info.GetGlobalPaintFlags(), paint_flags,
+ &painting_info.root_layer->GetLayoutObject());
if (paint_layer_.GetLayoutObject().ChildPaintBlockedByDisplayLock())
paint_info.SetDescendantPaintingBlocked(true);
- if (fragment.physical_fragment)
+ if (fragment.physical_fragment) {
NGBoxFragmentPainter(*fragment.physical_fragment).Paint(paint_info);
- else
+ } else {
+ if (fragment.fragment_data)
+ paint_info.SetFragmentID(fragment.fragment_data->FragmentID());
paint_layer_.GetLayoutObject().Paint(paint_info);
+ }
}
static CullRect LegacyCullRect(const PaintLayerFragment& fragment,
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 27ad0e60a6e..c8e3343a6b5 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
@@ -35,7 +35,7 @@ class CORE_EXPORT PaintLayerPainter {
void Paint(GraphicsContext&,
const CullRect&,
const GlobalPaintFlags = kGlobalPaintNormalPhase,
- PaintLayerFlags = 0);
+ PaintLayerFlags = kPaintLayerNoFlag);
// Paint() assumes that the caller will clip to the bounds of the painting
// dirty if necessary.
PaintResult Paint(GraphicsContext&,
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 4fadc94b899..9728634781a 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
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/testing/find_cc_layer.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"
@@ -22,23 +23,6 @@ class PaintLayerPainterTest : public PaintControllerPaintTest {
USING_FAST_MALLOC(PaintLayerPainterTest);
public:
- void ExpectPaintedOutputInvisibleAndPaintsWithTransparency(
- const char* element_name,
- bool expected_invisible,
- bool expected_paints_with_transparency) {
- // The optimization to skip painting for effectively-invisible content is
- // limited to pre-CAP.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
- PaintLayer* target_layer = GetPaintLayerByElementId(element_name);
- bool invisible = PaintLayerPainter::PaintedOutputInvisible(
- target_layer->GetLayoutObject().StyleRef());
- EXPECT_EQ(expected_invisible, invisible);
- EXPECT_EQ(expected_paints_with_transparency,
- target_layer->PaintsWithTransparency(kGlobalPaintNormalPhase));
- }
-
PaintController& MainGraphicsLayerPaintController() {
return GetLayoutView()
.Layer()
@@ -82,8 +66,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
auto* filler2 = GetLayoutObjectByElementId("filler2");
auto* container1_layer = To<LayoutBoxModelObject>(container1)->Layer();
+ auto* content1_layer = To<LayoutBoxModelObject>(content1)->Layer();
auto* filler1_layer = To<LayoutBoxModelObject>(filler1)->Layer();
auto* container2_layer = To<LayoutBoxModelObject>(container2)->Layer();
+ auto* content2_layer = To<LayoutBoxModelObject>(content2)->Layer();
auto* filler2_layer = To<LayoutBoxModelObject>(filler2)->Layer();
auto chunk_state = GetLayoutView().FirstFragment().ContentsProperties();
@@ -106,27 +92,36 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
// Check that new paint chunks were forced for the layers.
auto chunks = ContentPaintChunks();
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*container1_layer, chunks.begin() + 1, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler1_layer, chunks.begin() + 2, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*container2_layer, chunks.begin() + 3, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler2_layer, chunks.begin() + 4, 1);
+ auto chunk_it = chunks.begin();
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*container1_layer, chunk_it + 1, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*content1_layer, chunk_it + 2, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler1_layer, chunk_it + 3, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*container2_layer, chunk_it + 4, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*content2_layer, chunk_it + 5, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler2_layer, chunk_it + 6, 1);
EXPECT_THAT(
chunks,
ElementsAre(
VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
IsPaintChunk(
- 1, 3,
+ 1, 2,
PaintChunk::Id(*container1_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 0, 200, 200)),
IsPaintChunk(
+ 2, 3, PaintChunk::Id(*content1_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(
3, 4, PaintChunk::Id(*filler1_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 200, 20, 20)),
IsPaintChunk(
- 4, 6,
+ 4, 5,
PaintChunk::Id(*container2_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 220, 200, 200)),
IsPaintChunk(
+ 5, 6, PaintChunk::Id(*content2_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 220, 100, 100)),
+ IsPaintChunk(
6, 7, PaintChunk::Id(*filler2_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 420, 20, 20))));
};
@@ -137,10 +132,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
->setAttribute(html_names::kStyleAttr,
"position: absolute; width: 100px; height: 100px; "
"background-color: green");
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(6u, counter.NumNewCachedItems());
- EXPECT_EQ(3u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(6u, counter.num_cached_items);
+ EXPECT_EQ(4u, counter.num_cached_subsequences);
// We should still have the paint chunks forced by the cached subsequences.
check_results();
@@ -181,9 +176,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
auto* filler_layer = To<LayoutBoxModelObject>(filler)->Layer();
auto chunks = ContentPaintChunks();
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 4);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 4, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1);
auto container_properties =
container->FirstFragment().LocalBorderBoxProperties();
@@ -207,6 +203,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
PaintChunk::Id(*content_layer, DisplayItem::kLayerChunk),
content_properties, nullptr, IntRect(0, 0, 200, 100)),
IsPaintChunk(
+ 1, 1,
+ PaintChunk::Id(*inner_content_layer, DisplayItem::kLayerChunk),
+ content_properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(
1, 1, PaintChunk::Id(*filler_layer, DisplayItem::kLayerChunk),
content_properties, nullptr, IntRect(0, 100, 300, 300))));
@@ -214,8 +214,12 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
->setAttribute(html_names::kStyleAttr,
"position: absolute; width: 100px; height: 100px; "
"top: 100px; background-color: green");
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(1u, counter.num_cached_items); // view background.
+ EXPECT_EQ(1u, counter.num_cached_subsequences); // filler layer.
+
EXPECT_THAT(
ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -225,6 +229,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
chunks = ContentPaintChunks();
EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5);
EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1);
EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1);
EXPECT_THAT(
@@ -250,12 +255,6 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
}
TEST_P(PaintLayerPainterTest, CachedSubsequenceOnCullRectChange) {
- // This test doesn't work in CompositeAfterPaint mode because we always paint
- // from the local root frame view, and we always expand cull rect for
- // scrolling.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='container1' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
@@ -310,15 +309,15 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnCullRectChange) {
IsSameId(&content3, kBackgroundType)));
UpdateAllLifecyclePhasesExceptPaint();
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
PaintContents(IntRect(0, 100, 300, 1000));
// Container1 becomes partly in the interest rect, but uses cached subsequence
// because it was fully painted before;
// Container2's intersection with the interest rect changes;
// Content2b is out of the interest rect and outputs nothing;
// Container3 becomes out of the interest rect and outputs nothing.
- EXPECT_EQ(5u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(5u, counter.num_cached_items);
+ EXPECT_EQ(2u, counter.num_cached_subsequences);
EXPECT_THAT(ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -356,12 +355,12 @@ TEST_P(PaintLayerPainterTest,
SetBodyInnerHTML(R"HTML(
<div id='container1' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
- <div id='content1' style='position: absolute; width: 100px;
+ <div id='content1' style='overflow: hidden; width: 100px;
height: 100px; background-color: red'></div>
</div>
<div id='container2' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
- <div id='content2' style='position: absolute; width: 100px;
+ <div id='content2' style='overflow: hidden; width: 100px;
height: 100px; background-color: green'></div>
</div>
)HTML");
@@ -390,10 +389,9 @@ TEST_P(PaintLayerPainterTest,
"position: absolute; width: 100px; height: 100px; "
"background-color: green");
UpdateAllLifecyclePhasesExceptPaint();
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
PaintContents(IntRect(0, 0, 50, 300));
- EXPECT_EQ(4u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(4u, counter.num_cached_items);
EXPECT_THAT(ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -450,10 +448,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
"display: block");
UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(target_layer->SelfNeedsRepaint());
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(2u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(2u, counter.num_cached_items);
+ EXPECT_EQ(1u, counter.num_cached_subsequences);
// |target| is still partially painted.
EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
@@ -494,8 +492,8 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
counter.Reset();
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(2u, counter.NumNewCachedItems());
- EXPECT_EQ(0u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(2u, counter.num_cached_items);
+ EXPECT_EQ(0u, counter.num_cached_subsequences);
// |target| is still partially painted.
EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
@@ -527,12 +525,13 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
div { background: blue }
</style>
<div id='container1' style='position: relative; height: 150px; z-index: 1'>
- <div id='content1a' style='position: relative; height: 100px'></div>
- <div id='content1b' style='position: relative; height: 100px'></div>
+ <div id='content1a' style='overflow: hidden; height: 100px'></div>
+ <div id='content1b' style='overflow: hidden; height: 100px'></div>
</div>
<div id='container2' style='position: relative; z-index: 1'>
- <div id='content2a' style='position: relative; height: 100px'></div>
- <div id='content2b' style='position: relative; z-index: -1; height: 100px'></div>
+ <div id='content2a' style='overflow: hidden; height: 100px'></div>
+ <div id='content2b'
+ style='position: relative; z-index: -1; height: 100px'></div>
</div>
)HTML");
@@ -559,14 +558,9 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
// Includes |container1| and |content1a|.
IsPaintChunk(
- 1, 3,
+ 1, 4,
PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 0, 800, 150)),
- // Includes |content1b| which overflows |container1|.
- IsPaintChunk(
- 3, 4,
- PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 100, 800, 100)),
+ chunk_state, nullptr, IntRect(0, 0, 800, 200)),
IsPaintChunk(
4, 5,
PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
@@ -575,10 +569,10 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
5, 6,
PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 250, 800, 100)),
- IsPaintChunk(
- 6, 7,
- PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ IsPaintChunk(6, 7,
+ PaintChunk::Id(*container2->Layer(),
+ DisplayItem::kLayerChunkForeground),
+ chunk_state, nullptr, IntRect(0, 150, 800, 100))));
}
TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
@@ -588,20 +582,18 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
<div id='container1' style='position: relative; height: 150px; z-index: 1'>
- <div id='content1a' style='position: relative; height: 100px'></div>
- <div id='content1b' style='position: relative; height: 100px'></div>
+ <div id='content1a' style='overflow: hidden; height: 100px'></div>
+ <div id='content1b' style='overflow: hidden; height: 100px'></div>
</div>
<div id='container2' style='position: relative; z-index: 1'>
- <div id='content2a' style='position: relative; height: 100px'></div>
+ <div id='content2a' style='overflow: hidden; height: 100px'></div>
<div id='content2b'
style='position: relative; z-index: -1; height: 100px'></div>
</div>
)HTML");
auto* container1 = GetLayoutBoxByElementId("container1");
- auto* content1b = GetLayoutBoxByElementId("content1b");
auto* container2 = GetLayoutBoxByElementId("container2");
- auto* content2a = GetLayoutBoxByElementId("content2a");
auto* content2b = GetLayoutBoxByElementId("content2b");
auto chunk_state = GetLayoutView().FirstFragment().ContentsProperties();
@@ -615,11 +607,7 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
IsPaintChunk(
1, 1,
PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 0, 800, 150)),
- IsPaintChunk(
- 1, 1,
- PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 100, 800, 100)),
+ chunk_state, nullptr, IntRect(0, 0, 800, 200)),
IsPaintChunk(
1, 1,
PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
@@ -628,10 +616,10 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
1, 1,
PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 250, 800, 100)),
- IsPaintChunk(
- 1, 1,
- PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ IsPaintChunk(1, 1,
+ PaintChunk::Id(*container2->Layer(),
+ DisplayItem::kLayerChunkForeground),
+ chunk_state, nullptr, IntRect(0, 150, 800, 100))));
}
TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
@@ -891,149 +879,6 @@ TEST_P(PaintLayerPainterTest, PaintPhasesUpdateOnBecomingNonSelfPainting) {
EXPECT_TRUE(html_layer.NeedsPaintPhaseDescendantOutlines());
}
-TEST_P(PaintLayerPainterTest, DontPaintWithTinyOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, true);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithTinyOpacityAndWillChangeOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001; "
- " will-change: opacity'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithTinyOpacityAndBackdropFilter) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001;"
- " backdrop-filter: blur(2px);'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest,
- DoPaintWithTinyOpacityAndBackdropFilterAndWillChangeOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001;"
- " backdrop-filter: blur(2px); will-change: opacity'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithCompositedTinyOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001;"
- " will-change: transform'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithNonTinyOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.1'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, true);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithEffectAnimationZeroOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- animation-name: example;
- animation-duration: 4s;
- }
- @keyframes example {
- from { opacity: 0.0;}
- to { opacity: 1.0;}
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithTransformAnimationZeroOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div#target {
- animation-name: example;
- animation-duration: 4s;
- opacity: 0.0;
- }
- @keyframes example {
- from { transform: translate(0px, 0px); }
- to { transform: translate(3em, 0px); }
- }
- </style>
- <div id='target'>x</div></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, false);
-}
-
-TEST_P(PaintLayerPainterTest,
- DoPaintWithTransformAnimationZeroOpacityWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div#target {
- animation-name: example;
- animation-duration: 4s;
- opacity: 0.0;
- will-change: opacity;
- }
- @keyframes example {
- from { transform: translate(0px, 0px); }
- to { transform: translate(3em, 0px); }
- }
- </style>
- <div id='target'>x</div></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- will-change: opacity;
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithZeroOpacityAndWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- opacity: 0;
- will-change: opacity;
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest,
- DoPaintWithNoContentAndZeroOpacityAndWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- opacity: 0;
- will-change: opacity;
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
using PaintLayerPainterTestCAP = PaintLayerPainterTest;
INSTANTIATE_CAP_TEST_SUITE_P(PaintLayerPainterTestCAP);
@@ -1214,6 +1059,33 @@ TEST_P(PaintLayerPainterTestCAP, ScaledAndRotatedCullRect) {
GetCullRect(*GetPaintLayerByElementId("target")).Rect());
}
+// This is a testcase for https://crbug.com/1227907 where repeated cull rect
+// updates are expensive on the motionmark microbenchmark.
+TEST_P(PaintLayerPainterTestCAP, OptimizeNonCompositedTransformUpdate) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ width: 50px;
+ height: 50px;
+ background: green;
+ transform: translate(-8px, -8px);
+ }
+ </style>
+ <div id='target'></div>
+ )HTML");
+
+ // The cull rect should be correctly calculated on first paint.
+ EXPECT_EQ(IntRect(0, 0, 800, 600),
+ GetCullRect(*GetPaintLayerByElementId("target")).Rect());
+
+ // On subsequent paints, fall back to an infinite cull rect.
+ GetDocument().getElementById("target")->setAttribute(
+ html_names::kStyleAttr, "transform: rotate(10deg);");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(CullRect::Infinite().Rect(),
+ GetCullRect(*GetPaintLayerByElementId("target")).Rect());
+}
+
TEST_P(PaintLayerPainterTestCAP, 3DRotated90DegreesCullRect) {
GetDocument().GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
SetBodyInnerHTML(R"HTML(
@@ -1381,4 +1253,138 @@ TEST_P(PaintLayerPainterTestCAP, ClippedBigLayer) {
GetCullRect(*GetPaintLayerByElementId("target")).Rect());
}
+class PaintLayerPainterPaintedOutputInvisibleTest
+ : public PaintLayerPainterTest {
+ protected:
+ void RunTest() {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <div id="target">
+ <div id="child"></div>
+ </div>
+ </div>
+ <style>
+ #parent {
+ width: 10px;
+ height: 10px;
+ will-change: transform;
+ }
+ #target {
+ width: 100px;
+ height: 100px;
+ opacity: 0.0001;
+ }
+ #child {
+ width: 200px;
+ height: 50px;
+ opacity: 0.9;
+ }
+ )HTML" + additional_style_ +
+ "</style>");
+
+ auto* parent = GetLayoutObjectByElementId("parent");
+ auto* parent_layer = To<LayoutBox>(parent)->Layer();
+ auto* target = GetLayoutObjectByElementId("target");
+ auto* target_layer = To<LayoutBox>(target)->Layer();
+ auto* child = GetLayoutObjectByElementId("child");
+ auto* child_layer = To<LayoutBox>(child)->Layer();
+
+ EXPECT_EQ(expected_invisible_,
+ PaintLayerPainter::PaintedOutputInvisible(
+ target_layer->GetLayoutObject().StyleRef()));
+
+ auto* cc_layer =
+ CcLayersByDOMElementId(GetDocument().View()->RootCcLayer(),
+ expected_composited_ ? "target" : "parent")[0];
+ ASSERT_TRUE(cc_layer);
+ EXPECT_EQ(gfx::Size(200, 100), cc_layer->bounds());
+
+ auto chunks = ContentPaintChunks();
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_THAT(
+ chunks,
+ ElementsAre(
+ VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
+ IsPaintChunk(
+ 1, 1, PaintChunk::Id(*parent_layer, DisplayItem::kLayerChunk),
+ parent->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(0, 0, 10, 10)),
+ IsPaintChunk(
+ 1, 1, PaintChunk::Id(*target_layer, DisplayItem::kLayerChunk),
+ target->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(0, 0, 100, 100)),
+ IsPaintChunk(
+ 1, 1, PaintChunk::Id(*child_layer, DisplayItem::kLayerChunk),
+ child->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(0, 0, 200, 50))));
+ EXPECT_FALSE((chunks.begin() + 1)->effectively_invisible);
+ EXPECT_EQ(expected_invisible_,
+ (chunks.begin() + 2)->effectively_invisible);
+ EXPECT_EQ(expected_invisible_,
+ (chunks.begin() + 3)->effectively_invisible);
+ } else {
+ EXPECT_EQ(expected_paints_with_transparency_,
+ target_layer->PaintsWithTransparency(kGlobalPaintNormalPhase));
+ }
+ }
+
+ String additional_style_;
+ bool expected_composited_ = false;
+ bool expected_invisible_ = true;
+ bool expected_paints_with_transparency_ = true;
+};
+
+INSTANTIATE_PAINT_TEST_SUITE_P(PaintLayerPainterPaintedOutputInvisibleTest);
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest, TinyOpacity) {
+ expected_composited_ = false;
+ expected_invisible_ = true;
+ expected_paints_with_transparency_ = true;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ TinyOpacityAndWillChangeOpacity) {
+ additional_style_ = "#target { will-change: opacity; }";
+ expected_composited_ = true;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ TinyOpacityAndBackdropFilter) {
+ additional_style_ = "#target { backdrop-filter: blur(2px); }";
+ expected_composited_ = true;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ TinyOpacityAndWillChangeTransform) {
+ additional_style_ = "#target { will-change: transform; }";
+ expected_composited_ = true;
+ expected_invisible_ = true;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest, NonTinyOpacity) {
+ additional_style_ = "#target { opacity: 0.5; }";
+ expected_composited_ = false;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = true;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ NonTinyOpacityAndWillChangeOpacity) {
+ additional_style_ = "#target { opacity: 1; will-change: opacity; }";
+ expected_composited_ = true;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
} // namespace blink
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 d5d86d38692..b0bb26c4a57 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
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
@@ -63,7 +63,6 @@ class PaintLayer;
enum PaintLayerFlag {
kPaintLayerNoFlag = 0,
- kPaintLayerHaveTransparency = 1,
kPaintLayerPaintingOverlayOverflowControls = 1 << 3,
kPaintLayerPaintingCompositingBackgroundPhase = 1 << 4,
kPaintLayerPaintingCompositingForegroundPhase = 1 << 5,
@@ -135,8 +134,6 @@ inline String PaintLayerFlagsToDebugString(PaintLayerFlags flags) {
append("kPaintLayerPaintingCompositingDecorationPhase");
}
- if (flags & kPaintLayerHaveTransparency)
- append("kPaintLayerHaveTransparency");
if (flags & kPaintLayerPaintingOverlayOverflowControls)
append("kPaintLayerPaintingOverlayOverflowControls");
if (flags & kPaintLayerPaintingCompositingScrollingPhase)
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 c838509b144..072c1af3382 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
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@gmail.com>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
@@ -76,6 +76,7 @@
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/custom_scrollbar.h"
#include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
@@ -94,6 +95,7 @@
#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/object_paint_invalidator.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/core/scroll/scroll_alignment.h"
@@ -179,8 +181,8 @@ PaintLayerScrollableArea* PaintLayerScrollableArea::FromNode(const Node& node) {
return box ? box->GetScrollableArea() : nullptr;
}
-void PaintLayerScrollableArea::DidScroll(const FloatPoint& position) {
- ScrollableArea::DidScroll(position);
+void PaintLayerScrollableArea::DidCompositorScroll(const FloatPoint& position) {
+ ScrollableArea::DidCompositorScroll(position);
// This should be alive if it receives composited scroll callbacks.
CHECK(!HasBeenDisposed());
}
@@ -646,16 +648,30 @@ void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange() {
bool background_paint_in_scrolling_contents =
background_paint_location & kBackgroundPaintInScrollingContents;
- // Both local attachment background painted in graphics layer and normal
- // attachment background painted in scrolling contents require paint
- // invalidation. Fixed attachment background has been dealt with in
+ // Invalidate background on scroll if needed.
+ // Fixed attachment background has been dealt with in
// frame_view->InvalidateBackgroundAttachmentFixedDescendantsOnScroll().
- auto background_layers = box->StyleRef().BackgroundLayers();
- if ((background_layers.AnyLayerHasLocalAttachmentImage() &&
- background_paint_in_graphics_layer) ||
- (background_layers.AnyLayerHasDefaultAttachmentImage() &&
- background_paint_in_scrolling_contents))
+ const auto& background_layers = box->StyleRef().BackgroundLayers();
+ if (background_layers.AnyLayerHasLocalAttachmentImage() &&
+ background_paint_in_graphics_layer) {
+ // Local-attachment background image scrolls, so needs invalidation if it
+ // paints in non-scrolling space.
box->SetBackgroundNeedsFullPaintInvalidation();
+ } else if (background_layers.AnyLayerHasDefaultAttachmentImage() &&
+ background_paint_in_scrolling_contents) {
+ // Normal attachment background image doesn't scroll, so needs
+ // invalidation if it paints in scrolling contents.
+ box->SetBackgroundNeedsFullPaintInvalidation();
+ } else if (background_layers.AnyLayerHasLocalAttachment() &&
+ background_layers.AnyLayerUsesContentBox() &&
+ background_paint_in_graphics_layer &&
+ (box->PaddingLeft() || box->PaddingTop() ||
+ box->PaddingRight() || box->PaddingBottom())) {
+ // Local attachment content box background needs invalidation if there is
+ // padding because the content area can change on scroll (e.g. the top
+ // padding can disappear when the box scrolls to the bottom).
+ box->SetBackgroundNeedsFullPaintInvalidation();
+ }
}
// If any scrolling content might have been clipped by a cull rect, then
@@ -2669,6 +2685,12 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrollingInternal(
return needs_composited_scrolling;
}
+bool PaintLayerScrollableArea::UsesCompositedScrolling() const {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return GetLayoutBox()->UsesCompositedScrolling();
+ return ScrollableArea::UsesCompositedScrolling();
+}
+
void PaintLayerScrollableArea::UpdateNeedsCompositedScrolling(
bool force_prefer_compositing_to_lcd_text) {
bool new_needs_composited_scrolling =
@@ -2785,9 +2807,7 @@ Scrollbar* PaintLayerScrollableArea::ScrollbarManager::CreateScrollbar(
ScrollableArea(), orientation, To<Element>(style_source.GetNode()));
} else {
Element* style_source_element = nullptr;
- if (::features::IsFormControlsRefreshEnabled()) {
- style_source_element = DynamicTo<Element>(style_source.GetNode());
- }
+ style_source_element = DynamicTo<Element>(style_source.GetNode());
scrollbar = MakeGarbageCollected<Scrollbar>(ScrollableArea(), orientation,
style_source_element);
}
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 81e80996e04..d794536ad08 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
@@ -5,7 +5,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
@@ -278,7 +278,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
// only a helper.
cc::Layer* LayerForScrolling() const override;
- void DidScroll(const FloatPoint&) override;
+ void DidCompositorScroll(const FloatPoint&) override;
// GraphicsLayers for the scrolling components.
// Any function can return nullptr if they are not accelerated.
@@ -459,6 +459,11 @@ class CORE_EXPORT PaintLayerScrollableArea final
// Rectangle encompassing the scroll corner and resizer rect.
IntRect ScrollCornerAndResizerRect() const;
+ // The difference between this function and NeedsCompositedScrolling() is
+ // that this function returns the composited scrolling status based on paint
+ // properties which are updated based on the latter.
+ bool UsesCompositedScrolling() const override;
+
void UpdateNeedsCompositedScrolling(
bool force_prefer_compositing_to_lcd_text);
bool NeedsCompositedScrolling() const { return needs_composited_scrolling_; }
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 78187982a9d..bac1b5d58ad 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "build/build_config.h"
+#include "cc/layers/picture_layer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
@@ -17,6 +18,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
using testing::_;
@@ -921,7 +923,7 @@ TEST_P(PaintLayerScrollableAreaTest,
}
TEST_P(PaintLayerScrollableAreaTest,
- ScrollWithFixedDoesNotNeedCompositingInputsUpdate) {
+ ScrollWithFixedDoesNotNeedCompositingUpdate) {
SetBodyInnerHTML(R"HTML(
<style>
* {
@@ -951,6 +953,9 @@ TEST_P(PaintLayerScrollableAreaTest,
scrollable_area->SetScrollOffset(ScrollOffset(0, 1),
mojom::blink::ScrollType::kProgrammatic);
EXPECT_FALSE(scrollable_area->Layer()->NeedsCompositingInputsUpdate());
+ UpdateAllLifecyclePhasesExceptPaint();
+ EXPECT_FALSE(
+ GetDocument().View()->GetPaintArtifactCompositor()->NeedsUpdate());
UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
}
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 30ab95fbbb3..5ae07789067 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
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
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 ff04f7c7ae9..9544b3f6374 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
@@ -6,7 +6,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
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 5bf75df25e1..398368e4ff3 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
@@ -212,7 +212,7 @@ TEST_P(PaintLayerTest, CompositedScrollingNoNeedsRepaint) {
EXPECT_EQ(PhysicalOffset(0, 0),
content_layer->LocationWithoutPositionOffset());
EXPECT_EQ(
- LayoutSize(1000, 1000),
+ IntPoint(1000, 1000),
content_layer->ContainingLayer()->PixelSnappedScrolledContentOffset());
EXPECT_FALSE(content_layer->SelfNeedsRepaint());
EXPECT_FALSE(scroll_layer->SelfNeedsRepaint());
@@ -249,7 +249,7 @@ TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) {
EXPECT_EQ(PhysicalOffset(0, 0),
content_layer->LocationWithoutPositionOffset());
EXPECT_EQ(
- LayoutSize(1000, 1000),
+ IntPoint(1000, 1000),
content_layer->ContainingLayer()->PixelSnappedScrolledContentOffset());
if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
@@ -1074,44 +1074,35 @@ TEST_P(PaintLayerTest, SubsequenceCachingStackedLayers) {
PaintLayer* grandchild1 = GetPaintLayerByElementId("grandchild1");
PaintLayer* grandchild2 = GetPaintLayerByElementId("grandchild2");
- EXPECT_FALSE(parent->SupportsSubsequenceCaching());
- EXPECT_FALSE(child1->SupportsSubsequenceCaching());
- EXPECT_TRUE(child2->SupportsSubsequenceCaching());
- EXPECT_FALSE(grandchild1->SupportsSubsequenceCaching());
- EXPECT_FALSE(grandchild2->SupportsSubsequenceCaching());
-
- GetDocument()
- .getElementById("grandchild1")
- ->setAttribute(html_names::kStyleAttr, "isolation: isolate");
- UpdateAllLifecyclePhasesForTest();
-
- EXPECT_FALSE(parent->SupportsSubsequenceCaching());
- EXPECT_FALSE(child1->SupportsSubsequenceCaching());
+ EXPECT_TRUE(parent->SupportsSubsequenceCaching());
+ EXPECT_TRUE(child1->SupportsSubsequenceCaching());
EXPECT_TRUE(child2->SupportsSubsequenceCaching());
EXPECT_TRUE(grandchild1->SupportsSubsequenceCaching());
- EXPECT_FALSE(grandchild2->SupportsSubsequenceCaching());
+ EXPECT_TRUE(grandchild2->SupportsSubsequenceCaching());
}
-TEST_P(PaintLayerTest, SubsequenceCachingSVGRoot) {
+TEST_P(PaintLayerTest, SubsequenceCachingSVG) {
SetBodyInnerHTML(R"HTML(
- <div id='parent' style='position: relative'>
- <svg id='svgroot' style='position: relative'></svg>
- </div>
+ <svg id='svgroot'>
+ <foreignObject id='foreignObject'/>
+ </svg>
)HTML");
PaintLayer* svgroot = GetPaintLayerByElementId("svgroot");
+ PaintLayer* foreign_object = GetPaintLayerByElementId("foreignObject");
EXPECT_TRUE(svgroot->SupportsSubsequenceCaching());
+ EXPECT_TRUE(foreign_object->SupportsSubsequenceCaching());
}
TEST_P(PaintLayerTest, SubsequenceCachingMuticol) {
SetBodyInnerHTML(R"HTML(
<div style='columns: 2'>
- <svg id='svgroot' style='position: relative'></svg>
+ <div id='target' style='position: relative'></div>
</div>
)HTML");
- PaintLayer* svgroot = GetPaintLayerByElementId("svgroot");
- EXPECT_FALSE(svgroot->SupportsSubsequenceCaching());
+ PaintLayer* target = GetPaintLayerByElementId("target");
+ EXPECT_FALSE(target->SupportsSubsequenceCaching());
}
TEST_P(PaintLayerTest, NegativeZIndexChangeToPositive) {
@@ -1635,7 +1626,7 @@ TEST_P(PaintLayerTest, FloatLayerUnderInlineLayerScrolled) {
EXPECT_EQ(PhysicalOffset(0, 0), span->LocationWithoutPositionOffset());
EXPECT_EQ(PhysicalOffset(0, 0),
span->GetLayoutObject().OffsetForInFlowPosition());
- EXPECT_EQ(LayoutSize(0, 400),
+ EXPECT_EQ(IntPoint(0, 400),
span->ContainingLayer()->PixelSnappedScrolledContentOffset());
EXPECT_EQ(PhysicalOffset(150, 150),
floating->LocationWithoutPositionOffset());
@@ -1649,12 +1640,12 @@ TEST_P(PaintLayerTest, FloatLayerUnderInlineLayerScrolled) {
EXPECT_EQ(PhysicalOffset(0, 0), span->LocationWithoutPositionOffset());
EXPECT_EQ(PhysicalOffset(100, 100),
span->GetLayoutObject().OffsetForInFlowPosition());
- EXPECT_EQ(LayoutSize(0, 400),
+ EXPECT_EQ(IntPoint(0, 400),
span->ContainingLayer()->PixelSnappedScrolledContentOffset());
EXPECT_EQ(PhysicalOffset(0, 0), floating->LocationWithoutPositionOffset());
EXPECT_EQ(PhysicalOffset(50, 50),
floating->GetLayoutObject().OffsetForInFlowPosition());
- EXPECT_EQ(LayoutSize(0, 400),
+ EXPECT_EQ(IntPoint(0, 400),
floating->ContainingLayer()->PixelSnappedScrolledContentOffset());
EXPECT_EQ(PhysicalOffset(-50, -50),
floating->VisualOffsetFromAncestor(span));
@@ -1963,7 +1954,7 @@ TEST_P(PaintLayerTest, ColumnSpanLayerUnderExtraLayerScrolled) {
EXPECT_EQ(PhysicalOffset(50, 50),
spanner->GetLayoutObject().OffsetForInFlowPosition());
- EXPECT_EQ(LayoutSize(200, 0),
+ EXPECT_EQ(IntPoint(200, 0),
spanner->ContainingLayer()->PixelSnappedScrolledContentOffset());
EXPECT_EQ(PhysicalOffset(0, 0), extra_layer->LocationWithoutPositionOffset());
EXPECT_EQ(PhysicalOffset(100, 100),
@@ -2518,6 +2509,10 @@ TEST_P(PaintLayerTest, HitTestOverlayResizer) {
}
TEST_P(PaintLayerTest, BackgroundIsKnownToBeOpaqueInRectChildren) {
+ // This test doesn't apply in CompositeAfterPaint.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
SetBodyInnerHTML(R"HTML(
<style>
div {
@@ -2772,8 +2767,6 @@ TEST_P(PaintLayerTest, HasNonEmptyChildLayoutObjectsZeroSizeOverflowVisible) {
EXPECT_TRUE(layer->HasNonEmptyChildLayoutObjects());
}
-enum { kCompositingOptimizations = 1 << 0 };
-
class PaintLayerOverlapTest : public RenderingTest {
public:
PaintLayerOverlapTest()
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 0d45e6fcda3..fb7fcfa2e15 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
@@ -28,7 +28,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
@@ -111,6 +111,7 @@ PaintPropertyTreeBuilderContext::PaintPropertyTreeBuilderContext()
was_main_thread_scrolling(false) {}
PaintPropertyChangeType VisualViewportPaintPropertyTreeBuilder::Update(
+ LocalFrameView& main_frame_view,
VisualViewport& visual_viewport,
PaintPropertyTreeBuilderContext& full_context) {
if (full_context.fragments.IsEmpty())
@@ -121,6 +122,11 @@ PaintPropertyChangeType VisualViewportPaintPropertyTreeBuilder::Update(
auto property_changed =
visual_viewport.UpdatePaintPropertyNodesIfNeeded(context);
+ if (const EffectPaintPropertyNode* overscroll_elasticity_effect_node =
+ visual_viewport.GetOverscrollElasticityEffectNode()) {
+ context.current_effect = overscroll_elasticity_effect_node;
+ }
+
context.current.transform = visual_viewport.GetScrollTranslationNode();
context.absolute_position.transform =
visual_viewport.GetScrollTranslationNode();
@@ -135,6 +141,10 @@ PaintPropertyChangeType VisualViewportPaintPropertyTreeBuilder::Update(
// removed). Not a big deal for performance because this is rare.
full_context.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationPiercing;
+ // The main frame's paint chunks (e.g. scrollbars) may reference paint
+ // properties of the visual viewport.
+ if (auto* layout_view = main_frame_view.GetLayoutView())
+ layout_view->Layer()->SetNeedsRepaint();
}
#if DCHECK_IS_ON()
@@ -250,6 +260,38 @@ class FragmentPaintPropertyTreeBuilder {
bool IsInNGFragmentTraversal() const { return pre_paint_info_; }
+ void SwitchToOOFContext(
+ PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext&
+ oof_context) const {
+ context_.current = oof_context;
+
+ // If we're not block-fragmented, or if we're traversing the fragment tree
+ // to an orphaned object, simply setting a new context is all we have to do.
+ if (!oof_context.is_in_block_fragmentation ||
+ (pre_paint_info_ && pre_paint_info_->is_inside_orphaned_object))
+ return;
+
+ // Inside NG block fragmentation we have to perform an offset adjustment.
+ // An OOF fragment that is contained by something inside a fragmentainer
+ // will be a direct child of the fragmentainer, rather than a child of its
+ // actual containing block. We therefore need to adjust the offset to make
+ // us relative to the fragmentainer before applying the offset of the OOF.
+ PhysicalOffset delta =
+ oof_context.paint_offset - context_.fragmentainer_paint_offset;
+ // So, we did store |fragmentainer_paint_offset| when entering the
+ // fragmentainer, but the offset may have been reset by
+ // UpdateForPaintOffsetTranslation() since we entered it, which we'll need
+ // to compensate for now.
+ delta += context_.adjustment_for_oof_in_fragmentainer;
+ context_.current.paint_offset -= delta;
+ }
+
+ void ResetPaintOffset(PhysicalOffset new_offset = PhysicalOffset()) {
+ context_.adjustment_for_oof_in_fragmentainer +=
+ context_.current.paint_offset - new_offset;
+ context_.current.paint_offset = new_offset;
+ }
+
void OnUpdate(PaintPropertyChangeType change) {
property_changed_ = std::max(property_changed_, change);
}
@@ -499,7 +541,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
// compositing code.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
NeedsIsolationNodes(object_)) {
- context_.current.paint_offset = PhysicalOffset();
+ ResetPaintOffset();
context_.current.directly_composited_container_paint_offset_subpixel_delta =
PhysicalOffset();
return;
@@ -514,9 +556,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
PhysicalOffset subpixel_accumulation;
if (RequiresFragmentStitching()) {
const LayoutBox& box = To<LayoutBox>(object_);
- const NGFragmentChildIterator& iterator = pre_paint_info_->iterator;
- const NGPhysicalBoxFragment& fragment = *iterator->BoxFragment();
- const NGBlockBreakToken* incoming_break_token = iterator->BlockBreakToken();
+ const NGPhysicalBoxFragment& fragment = pre_paint_info_->box_fragment;
// Calculate this fragment's rectangle relatively to the enclosing stitched
// layout object, with help from the break token.
@@ -528,7 +568,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
WritingModeConverter converter(box.StyleRef().GetWritingDirection(),
PhysicalSize(box.Size()));
LogicalOffset logical_offset;
- if (incoming_break_token)
+ if (const NGBlockBreakToken* incoming_break_token =
+ FindPreviousBreakToken(fragment))
logical_offset.block_offset = incoming_break_token->ConsumedBlockSize();
LogicalRect logical_rect(logical_offset,
converter.ToLogical(fragment.Size()));
@@ -540,7 +581,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
// offset in order to get to the right offset for each fragment.
new_paint_offset = converter.ToPhysical(logical_rect).offset;
- if (&pre_paint_info_->fragment_data == &object_.FirstFragment()) {
+ if (pre_paint_info_->fragment_data == &object_.FirstFragment()) {
// Make the translation relatively to the top/left corner of the box. In
// vertical-rl writing mode, the first fragment is not the leftmost one.
PhysicalOffset topleft = context_.current.paint_offset - new_paint_offset;
@@ -571,7 +612,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
// If the object has a non-translation transform, discard the fractional
// paint offset which can't be transformed by the transform.
if (!CanPropagateSubpixelAccumulation()) {
- context_.current.paint_offset = new_paint_offset;
+ ResetPaintOffset(new_paint_offset);
context_.current
.directly_composited_container_paint_offset_subpixel_delta =
PhysicalOffset();
@@ -579,7 +620,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
}
}
- context_.current.paint_offset = new_paint_offset + subpixel_accumulation;
+ ResetPaintOffset(new_paint_offset + subpixel_accumulation);
bool can_be_directly_composited =
RuntimeEnabledFeatures::CompositeAfterPaintEnabled()
@@ -616,6 +657,14 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
state.direct_compositing_reasons =
full_context_.direct_compositing_reasons &
CompositingReason::kDirectReasonsForPaintOffsetTranslationProperty;
+ if (state.direct_compositing_reasons & CompositingReason::kFixedPosition &&
+ object_.View()->FirstFragment().PaintProperties()->Scroll()) {
+ state.scroll_translation_for_fixed = object_.View()
+ ->FirstFragment()
+ .PaintProperties()
+ ->ScrollTranslation();
+ }
+
if (IsA<LayoutView>(object_)) {
DCHECK(object_.GetFrame());
state.flags.is_frame_paint_offset_translation = true;
@@ -761,7 +810,7 @@ static CompositingReasons CompositingReasonsForTransformProperty() {
reasons |= CompositingReason::kWillChangeFilter;
reasons |= CompositingReason::kWillChangeBackdropFilter;
- if (RuntimeEnabledFeatures::TransformInteropEnabled())
+ if (RuntimeEnabledFeatures::BackfaceVisibilityInteropEnabled())
reasons |= CompositingReason::kBackfaceInvisibility3DAncestor;
return reasons;
@@ -842,19 +891,16 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransformForSVGChild(
// TODO(pdr): There is additional logic in
// FragmentPaintPropertyTreeBuilder::UpdateTransform that likely needs to
- // be included here, such as setting animation_is_axis_aligned, which
- // may be the only important difference remaining.
- if (RuntimeEnabledFeatures::CompositeSVGEnabled()) {
- state.direct_compositing_reasons =
- direct_compositing_reasons &
- CompositingReasonsForTransformProperty();
- state.flags.flattens_inherited_transform =
- context_.current.should_flatten_inherited_transform;
- state.rendering_context_id = context_.current.rendering_context_id;
- state.flags.is_for_svg_child = true;
- state.compositor_element_id = GetCompositorElementId(
- CompositorElementIdNamespace::kPrimaryTransform);
- }
+ // be included here, such as setting animation_is_axis_aligned, which may
+ // be the only important difference remaining.
+ state.direct_compositing_reasons =
+ direct_compositing_reasons & CompositingReasonsForTransformProperty();
+ state.flags.flattens_inherited_transform =
+ context_.current.should_flatten_inherited_transform;
+ state.rendering_context_id = context_.current.rendering_context_id;
+ state.flags.is_for_svg_child = true;
+ state.compositor_element_id = GetCompositorElementId(
+ CompositorElementIdNamespace::kPrimaryTransform);
TransformPaintPropertyNode::AnimationState animation_state;
animation_state.is_running_animation_on_compositor =
@@ -900,8 +946,11 @@ static FloatPoint3D TransformOrigin(const ComputedStyle& style,
style.TransformOriginZ());
}
-static bool NeedsTransform(const LayoutObject& object,
- CompositingReasons direct_compositing_reasons) {
+} // namespace
+
+bool PaintPropertyTreeBuilder::NeedsTransform(
+ const LayoutObject& object,
+ CompositingReasons direct_compositing_reasons) {
if (object.IsText())
return false;
@@ -920,6 +969,8 @@ static bool NeedsTransform(const LayoutObject& object,
return false;
}
+namespace {
+
static bool UpdateBoxSizeAndCheckActiveAnimationAxisAlignment(
const LayoutBox& object,
CompositingReasons compositing_reasons) {
@@ -949,7 +1000,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
// direct compositing reason. The latter is required because this is the
// only way to represent compositing both an element and its stacking
// descendants.
- if (NeedsTransform(object_, full_context_.direct_compositing_reasons)) {
+ if (PaintPropertyTreeBuilder::NeedsTransform(
+ object_, full_context_.direct_compositing_reasons)) {
TransformPaintPropertyNode::State state;
if (object_.IsBox()) {
@@ -957,10 +1009,11 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
// Each individual fragment should have its own transform origin, based
// on the fragment size. We'll do that, unless the fragments aren't to
// be stitched together.
- PhysicalSize size(
- !pre_paint_info_ || RequiresFragmentStitching()
- ? PhysicalSize(box.Size())
- : pre_paint_info_->iterator->BoxFragment()->Size());
+ PhysicalSize size;
+ if (!pre_paint_info_ || RequiresFragmentStitching())
+ size = PhysicalSize(box.Size());
+ else
+ size = pre_paint_info_->box_fragment.Size();
TransformationMatrix matrix;
style.ApplyTransform(
matrix, size.ToLayoutSize(), ComputedStyle::kExcludeTransformOrigin,
@@ -1068,7 +1121,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
transform->Translation2D();
}
} else if (RuntimeEnabledFeatures::TransformInteropEnabled() &&
- !object_.IsAnonymous()) {
+ object_.IsForElement()) {
// With kTransformInterop enabled, 3D rendering contexts follow the
// DOM ancestor chain, so flattening should apply regardless of
// presence of transform.
@@ -1084,9 +1137,10 @@ static bool MayNeedClipPathClip(const LayoutObject& object) {
(object.HasLayer() || object.IsSVGChild());
}
-static bool NeedsClipPathClip(const LayoutObject& object) {
+static bool NeedsClipPathClip(const LayoutObject& object,
+ const FragmentData& fragment_data) {
// We should have already updated the clip path cache when this is called.
- if (object.FirstFragment().ClipPathPath()) {
+ if (fragment_data.ClipPathPath()) {
DCHECK(MayNeedClipPathClip(object));
return true;
}
@@ -1285,6 +1339,17 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
full_context_.direct_compositing_reasons &
CompositingReasonsForEffectProperty();
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // If an effect node exists, add an additional direct compositing reason
+ // for 3d transforms to ensure it is composited.
+ CompositingReasons additional_transform_compositing_trigger =
+ CompositingReason::k3DTransform |
+ CompositingReason::kTrivial3DTransform;
+ state.direct_compositing_reasons |=
+ (full_context_.direct_compositing_reasons &
+ additional_transform_compositing_trigger);
+ }
+
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
state.direct_compositing_reasons |=
full_context_.direct_compositing_reasons &
@@ -1534,6 +1599,18 @@ void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
state.direct_compositing_reasons =
full_context_.direct_compositing_reasons &
CompositingReasonsForFilterProperty();
+
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // If an effect node exists, add an additional direct compositing reason
+ // for 3d transforms to ensure it is composited.
+ CompositingReasons additional_transform_compositing_trigger =
+ CompositingReason::k3DTransform |
+ CompositingReason::kTrivial3DTransform;
+ state.direct_compositing_reasons |=
+ (full_context_.direct_compositing_reasons &
+ additional_transform_compositing_trigger);
+ }
+
state.compositor_element_id =
GetCompositorElementId(CompositorElementIdNamespace::kEffectFilter);
@@ -1623,7 +1700,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateCssClip() {
void FragmentPaintPropertyTreeBuilder::UpdateClipPathClip() {
if (NeedsPaintPropertyUpdate()) {
- if (!NeedsClipPathClip(object_)) {
+ if (!NeedsClipPathClip(object_, fragment_data_)) {
OnClearClip(properties_->ClearClipPathClip());
} else {
ClipPaintPropertyNode::State state(
@@ -1831,13 +1908,14 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowClip() {
LayoutReplaced::PreSnappedRectForPersistentSizing(content_rect);
}
// LayoutReplaced clips the foreground by rounded content box.
- auto clip_rect = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
- replaced.StyleRef(), content_rect,
- LayoutRectOutsets(
- -(replaced.PaddingTop() + replaced.BorderTop()),
- -(replaced.PaddingRight() + replaced.BorderRight()),
- -(replaced.PaddingBottom() + replaced.BorderBottom()),
- -(replaced.PaddingLeft() + replaced.BorderLeft())));
+ auto clip_rect =
+ RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
+ replaced.StyleRef(), content_rect,
+ LayoutRectOutsets(
+ -(replaced.PaddingTop() + replaced.BorderTop()),
+ -(replaced.PaddingRight() + replaced.BorderRight()),
+ -(replaced.PaddingBottom() + replaced.BorderBottom()),
+ -(replaced.PaddingLeft() + replaced.BorderLeft())));
state.SetClipRect(clip_rect, clip_rect);
if (replaced.IsLayoutEmbeddedContent()) {
// Embedded objects are always sized to fit the content rect, but they
@@ -1852,9 +1930,9 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowClip() {
} else if (object_.IsBox()) {
PhysicalRect clip_rect;
if (pre_paint_info_) {
- const NGFragmentChildIterator& iterator = pre_paint_info_->iterator;
- clip_rect = iterator->BoxFragment()->OverflowClipRect(
- context_.current.paint_offset, iterator->BlockBreakToken());
+ clip_rect = pre_paint_info_->box_fragment.OverflowClipRect(
+ context_.current.paint_offset,
+ FindPreviousBreakToken(pre_paint_info_->box_fragment));
} else {
clip_rect = To<LayoutBox>(object_).OverflowClipRect(
context_.current.paint_offset);
@@ -1909,7 +1987,7 @@ void FragmentPaintPropertyTreeBuilder::UpdatePerspective() {
// most transform nodes do.
TransformPaintPropertyNode::State state{
TransformPaintPropertyNode::TransformAndOrigin(
- TransformationMatrix().ApplyPerspective(style.Perspective()),
+ TransformationMatrix().ApplyPerspective(style.UsedPerspective()),
PerspectiveOrigin(To<LayoutBox>(object_)) +
FloatSize(context_.current.paint_offset))};
state.flags.flattens_inherited_transform =
@@ -2117,6 +2195,11 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
FloatPoint scroll_position = FloatPoint(box.ScrollOrigin()) +
box.GetScrollableArea()->GetScrollOffset();
TransformPaintPropertyNode::State state{-ToFloatSize(scroll_position)};
+ if (!box.GetScrollableArea()->PendingScrollAnchorAdjustment().IsZero()) {
+ context_.current.pending_scroll_anchor_adjustment +=
+ box.GetScrollableArea()->PendingScrollAnchorAdjustment();
+ box.GetScrollableArea()->ClearPendingScrollAnchorAdjustment();
+ }
state.flags.flattens_inherited_transform =
context_.current.should_flatten_inherited_transform;
state.rendering_context_id = context_.current.rendering_context_id;
@@ -2166,11 +2249,20 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
scroll_translation->Translation2D() != old_scroll_offset) {
- // Scrolling can change overlap relationship.
+ // Scrolling can change overlap relationship for sticky positioned or
+ // elements fixed to an overflow: hidden view that programmatically
+ // scrolls via script. In this case the fixed transform doesn't have
+ // enough information to perform the expansion - there is no scroll node
+ // to describe the bounds of the scrollable content.
auto* frame_view = object_.GetFrameView();
- if (frame_view->HasViewportConstrainedObjects()) {
- // TODO(crbug.com/1099379): Implement better fixed/sticky overlap
- // testing.
+ if (frame_view->HasStickyViewportConstrainedObject()) {
+ // TODO(crbug.com/1117658): Implement better sticky overlap testing.
+ frame_view->SetPaintArtifactCompositorNeedsUpdate();
+ } else if (frame_view->HasViewportConstrainedObjects() &&
+ !frame_view->GetLayoutView()
+ ->FirstFragment()
+ .PaintProperties()
+ ->Scroll()) {
frame_view->SetPaintArtifactCompositorNeedsUpdate();
} else if (!object_.IsStackingContext() &&
// TODO(wangxianzhu): for accuracy, this should be something
@@ -2422,15 +2514,6 @@ static PhysicalOffset PaintOffsetInPaginationContainer(
}
void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
- if (IsInNGFragmentTraversal()) {
- // Text and non-atomic inlines are special, in that they share one
- // FragmentData per fragmentainer, so their paint offset is kept at their
- // container. For all other objects, include the offset now.
- if (object_.IsBox())
- context_.current.paint_offset += pre_paint_info_->iterator->Link().offset;
- return;
- }
-
// Paint offsets for fragmented content are computed from scratch.
const auto* enclosing_pagination_layer =
full_context_.painting_layer->EnclosingPaginationLayer();
@@ -2485,14 +2568,17 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
return;
}
- if (object_.IsFloating() && !object_.IsInLayoutNGInlineFormattingContext())
- context_.current.paint_offset = context_.paint_offset_for_float;
+ if (!pre_paint_info_) {
+ if (object_.IsFloating() && !object_.IsInLayoutNGInlineFormattingContext())
+ context_.current.paint_offset = context_.paint_offset_for_float;
- // Multicolumn spanners are painted starting at the multicolumn container (but
- // still inherit properties in layout-tree order) so reset the paint offset.
- if (object_.IsColumnSpanAll()) {
- context_.current.paint_offset =
- object_.Container()->FirstFragment().PaintOffset();
+ // Multicolumn spanners are painted starting at the multicolumn container
+ // (but still inherit properties in layout-tree order) so reset the paint
+ // offset.
+ if (object_.IsColumnSpanAll()) {
+ context_.current.paint_offset =
+ object_.Container()->FirstFragment().PaintOffset();
+ }
}
if (object_.IsBoxModelObject()) {
@@ -2505,8 +2591,12 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
box_model_object.OffsetForInFlowPosition();
break;
case EPosition::kAbsolute: {
- DCHECK_EQ(full_context_.container_for_absolute_position,
- box_model_object.Container());
+#if DCHECK_IS_ON()
+ if (!pre_paint_info_ || !pre_paint_info_->is_inside_orphaned_object) {
+ DCHECK_EQ(full_context_.container_for_absolute_position,
+ box_model_object.Container());
+ }
+#endif
if (RuntimeEnabledFeatures::TransformInteropEnabled()) {
// FIXME(dbaron): When the TransformInteropEnabled flag is removed
// because it's always enabled, we should move these variables from
@@ -2517,7 +2607,7 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
context_.absolute_position.rendering_context_id =
context_.current.rendering_context_id;
}
- context_.current = context_.absolute_position;
+ SwitchToOOFContext(context_.absolute_position);
// Absolutely positioned content in an inline should be positioned
// relative to the inline.
@@ -2534,8 +2624,12 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
case EPosition::kSticky:
break;
case EPosition::kFixed: {
- DCHECK_EQ(full_context_.container_for_fixed_position,
- box_model_object.Container());
+#if DCHECK_IS_ON()
+ if (!pre_paint_info_ || !pre_paint_info_->is_inside_orphaned_object) {
+ DCHECK_EQ(full_context_.container_for_fixed_position,
+ box_model_object.Container());
+ }
+#endif
if (RuntimeEnabledFeatures::TransformInteropEnabled()) {
// FIXME(dbaron): When the TransformInteropEnabled flag is removed
// because it's always enabled, we should move these variables from
@@ -2546,7 +2640,7 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
context_.fixed_position.rendering_context_id =
context_.current.rendering_context_id;
}
- context_.current = context_.fixed_position;
+ SwitchToOOFContext(context_.fixed_position);
// Fixed-position elements that are fixed to the viewport have a
// transform above the scroll of the LayoutView. Child content is
// relative to that transform, and hence the fixed-position element.
@@ -2568,21 +2662,32 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
}
}
- if (object_.IsBox()) {
- // TODO(pdr): Several calls in this function walk back up the tree to
- // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*).
- // The containing block and other containers can be stored on
- // PaintPropertyTreeBuilderFragmentContext instead of recomputing them.
- context_.current.paint_offset += To<LayoutBox>(object_).PhysicalLocation();
+ if (const auto* box = DynamicTo<LayoutBox>(&object_)) {
+ if (pre_paint_info_) {
+ context_.current.paint_offset += pre_paint_info_->paint_offset;
- // This is a weird quirk that table cells paint as children of table rows,
- // but their location have the row's location baked-in.
- // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
- if (object_.IsTableCellLegacy()) {
- LayoutObject* parent_row = object_.Parent();
- DCHECK(parent_row && parent_row->IsTableRow());
- context_.current.paint_offset -=
- To<LayoutBox>(parent_row)->PhysicalLocation();
+ // Determine whether we're inside block fragmentation or not. OOF
+ // descendants need special treatment inside block fragmentation.
+ context_.current.is_in_block_fragmentation =
+ pre_paint_info_->fragmentainer_idx != WTF::kNotFound &&
+ box->GetNGPaginationBreakability() != LayoutBox::kForbidBreaks;
+ } else {
+ // TODO(pdr): Several calls in this function walk back up the tree to
+ // calculate containers (e.g., physicalLocation,
+ // offsetForInFlowPosition*). The containing block and other containers
+ // can be stored on PaintPropertyTreeBuilderFragmentContext instead of
+ // recomputing them.
+ context_.current.paint_offset += box->PhysicalLocation();
+
+ // This is a weird quirk that table cells paint as children of table rows,
+ // but their location have the row's location baked-in.
+ // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
+ if (object_.IsTableCellLegacy()) {
+ LayoutObject* parent_row = object_.Parent();
+ DCHECK(parent_row && parent_row->IsTableRow());
+ context_.current.paint_offset -=
+ To<LayoutBox>(parent_row)->PhysicalLocation();
+ }
}
}
@@ -2742,8 +2847,11 @@ static bool IsLayoutShiftRoot(const LayoutObject& object,
void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
#if DCHECK_IS_ON()
- FindPaintOffsetNeedingUpdateScope check_paint_offset(
- object_, fragment_data_, full_context_.is_actually_needed);
+ absl::optional<FindPaintOffsetNeedingUpdateScope> check_paint_offset;
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ check_paint_offset.emplace(object_, fragment_data_,
+ full_context_.is_actually_needed);
+ }
#endif
// This is not in FindObjectPropertiesNeedingUpdateScope because paint offset
@@ -2757,8 +2865,12 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
if (properties_) {
{
#if DCHECK_IS_ON()
- FindPropertiesNeedingUpdateScope check_fragment_clip(
- object_, fragment_data_, full_context_.force_subtree_update_reasons);
+ absl::optional<FindPropertiesNeedingUpdateScope> check_fragment_clip;
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ bool force_subtree_update = full_context_.force_subtree_update_reasons;
+ check_fragment_clip.emplace(object_, fragment_data_,
+ force_subtree_update);
+ }
#endif
UpdateFragmentClip();
}
@@ -2768,8 +2880,12 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
}
#if DCHECK_IS_ON()
- FindPropertiesNeedingUpdateScope check_paint_properties(
- object_, fragment_data_, full_context_.force_subtree_update_reasons);
+ absl::optional<FindPropertiesNeedingUpdateScope> check_paint_properties;
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ bool force_subtree_update = full_context_.force_subtree_update_reasons;
+ check_paint_properties.emplace(object_, fragment_data_,
+ force_subtree_update);
+ }
#endif
if (properties_) {
@@ -2781,7 +2897,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
UpdateFilter();
UpdateOverflowControlsClip();
} else if (RuntimeEnabledFeatures::TransformInteropEnabled() &&
- !object_.IsAnonymous()) {
+ object_.IsForElement()) {
// With kTransformInterop enabled, 3D rendering contexts follow the
// DOM ancestor chain, so flattening should apply regardless of
// presence of transform.
@@ -2806,13 +2922,19 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
void FragmentPaintPropertyTreeBuilder::UpdateForChildren() {
#if DCHECK_IS_ON()
- // Paint offset should not change during this function.
+ // Will be used though a reference by check_paint_offset, so it's declared
+ // here to out-live check_paint_offset. It's false because paint offset
+ // should not change during this function.
const bool needs_paint_offset_update = false;
- FindPaintOffsetNeedingUpdateScope check_paint_offset(
- object_, fragment_data_, needs_paint_offset_update);
-
- FindPropertiesNeedingUpdateScope check_paint_properties(
- object_, fragment_data_, full_context_.force_subtree_update_reasons);
+ absl::optional<FindPaintOffsetNeedingUpdateScope> check_paint_offset;
+ absl::optional<FindPropertiesNeedingUpdateScope> check_paint_properties;
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ check_paint_offset.emplace(object_, fragment_data_,
+ needs_paint_offset_update);
+ bool force_subtree_update = full_context_.force_subtree_update_reasons;
+ check_paint_properties.emplace(object_, fragment_data_,
+ force_subtree_update);
+ }
#endif
if (properties_) {
@@ -2838,8 +2960,10 @@ void FragmentPaintPropertyTreeBuilder::UpdateForChildren() {
context_.translation_2d_to_layout_shift_root_delta = FloatSize();
// Don't reset scroll_offset_to_layout_shift_root_delta if this object has
// scroll translation because we need to propagate the delta to descendants.
- if (!properties_ || !properties_->ScrollTranslation())
+ if (!properties_ || !properties_->ScrollTranslation()) {
context_.current.scroll_offset_to_layout_shift_root_delta = FloatSize();
+ context_.current.pending_scroll_anchor_adjustment = FloatSize();
+ }
}
#if DCHECK_IS_ON()
@@ -2910,7 +3034,7 @@ void PaintPropertyTreeBuilder::InitFragmentPaintPropertiesForNG(
context_.fragments.push_back(PaintPropertyTreeBuilderFragmentContext());
else
context_.fragments.resize(1);
- InitFragmentPaintProperties(pre_paint_info_->fragment_data,
+ InitFragmentPaintProperties(*pre_paint_info_->fragment_data,
needs_paint_properties, context_.fragments[0]);
}
@@ -2931,12 +3055,15 @@ void PaintPropertyTreeBuilder::InitSingleFragmentFromParent(
// Column-span:all skips pagination container in the tree hierarchy, so it
// should also skip any fragment clip created by the skipped pagination
- // container. We also need to skip fragment clip if the object is a paint
- // invalidation container which doesn't allow fragmentation.
- bool skip_fragment_clip_for_composited_layer =
- !RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
- object_.CanBeCompositedForDirectReasons() &&
- To<LayoutBoxModelObject>(object_).Layer()->EnclosingPaginationLayer();
+ // container. We also need to skip fragment clip if the layer doesn't allow
+ // fragmentation.
+ bool skip_fragment_clip_for_composited_layer = false;
+ if (object_.HasLayer()) {
+ const auto* layer = To<LayoutBoxModelObject>(object_).Layer();
+ skip_fragment_clip_for_composited_layer =
+ layer->EnclosingPaginationLayer() &&
+ !layer->ShouldFragmentCompositedBounds();
+ }
if (!skip_fragment_clip_for_composited_layer && !object_.IsColumnSpanAll())
return;
@@ -2979,8 +3106,6 @@ void PaintPropertyTreeBuilder::InitSingleFragmentFromParent(
void PaintPropertyTreeBuilder::UpdateCompositedLayerPaginationOffset() {
DCHECK(!IsInNGFragmentTraversal());
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
const auto* enclosing_pagination_layer =
context_.painting_layer->EnclosingPaginationLayer();
@@ -2994,13 +3119,28 @@ void PaintPropertyTreeBuilder::UpdateCompositedLayerPaginationOffset() {
DCHECK(!context_.painting_layer->ShouldFragmentCompositedBounds());
FragmentData& first_fragment =
object_.GetMutableForPainting().FirstFragment();
- bool can_be_directly_composited = object_.CanBeCompositedForDirectReasons();
- const auto* parent_directly_composited_layer =
- context_.painting_layer->EnclosingDirectlyCompositableLayer(
- can_be_directly_composited ? kExcludeSelf : kIncludeSelf);
- if (can_be_directly_composited &&
- (!parent_directly_composited_layer ||
- !parent_directly_composited_layer->EnclosingPaginationLayer())) {
+ bool may_use_self_pagination_offset = false;
+ const PaintLayer* parent_pagination_offset_layer = nullptr;
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ parent_pagination_offset_layer =
+ context_.painting_layer
+ ->EnclosingCompositedScrollingLayerUnderPagination(kIncludeSelf);
+ if (parent_pagination_offset_layer->GetLayoutObject() == object_) {
+ may_use_self_pagination_offset = true;
+ parent_pagination_offset_layer =
+ parent_pagination_offset_layer
+ ->EnclosingCompositedScrollingLayerUnderPagination(kExcludeSelf);
+ }
+ } else {
+ may_use_self_pagination_offset = object_.CanBeCompositedForDirectReasons();
+ parent_pagination_offset_layer =
+ context_.painting_layer->EnclosingDirectlyCompositableLayer(
+ may_use_self_pagination_offset ? kExcludeSelf : kIncludeSelf);
+ }
+
+ if (may_use_self_pagination_offset &&
+ (!parent_pagination_offset_layer ||
+ !parent_pagination_offset_layer->EnclosingPaginationLayer())) {
// |object_| establishes the top level composited layer under the
// pagination layer.
FragmentainerIterator iterator(
@@ -3013,10 +3153,10 @@ void PaintPropertyTreeBuilder::UpdateCompositedLayerPaginationOffset() {
first_fragment.SetLogicalTopInFlowThread(
iterator.FragmentainerLogicalTopInFlowThread());
}
- } else if (parent_directly_composited_layer) {
+ } else if (parent_pagination_offset_layer) {
// All objects under the composited layer use the same pagination offset.
const auto& fragment =
- parent_directly_composited_layer->GetLayoutObject().FirstFragment();
+ parent_pagination_offset_layer->GetLayoutObject().FirstFragment();
first_fragment.SetLegacyPaginationOffset(fragment.LegacyPaginationOffset());
first_fragment.SetLogicalTopInFlowThread(fragment.LogicalTopInFlowThread());
}
@@ -3762,7 +3902,7 @@ PaintPropertyChangeType PaintPropertyTreeBuilder::UpdateForSelf() {
DCHECK_EQ(context_.fragments.size(), 1u);
FragmentPaintPropertyTreeBuilder builder(object_, pre_paint_info_, context_,
context_.fragments[0],
- pre_paint_info_->fragment_data);
+ *pre_paint_info_->fragment_data);
builder.UpdateForSelf();
property_changed = std::max(property_changed, builder.PropertyChanged());
} else {
@@ -3813,7 +3953,7 @@ PaintPropertyChangeType PaintPropertyTreeBuilder::UpdateForChildren() {
FragmentData* fragment_data;
if (pre_paint_info_) {
DCHECK_EQ(context_.fragments.size(), 1u);
- fragment_data = &pre_paint_info_->fragment_data;
+ fragment_data = pre_paint_info_->fragment_data;
DCHECK(fragment_data);
} else {
fragment_data = &object_.GetMutableForPainting().FirstFragment();
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 a8d5224beb2..9ef282663dd 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
@@ -21,7 +21,7 @@ class FragmentData;
class LayoutObject;
class LayoutNGTableSectionInterface;
class LocalFrameView;
-class NGFragmentChildIterator;
+class NGPhysicalBoxFragment;
class PaintLayer;
class VisualViewport;
@@ -96,6 +96,8 @@ struct PaintPropertyTreeBuilderFragmentContext {
// object has changed.
bool layout_shift_root_changed = false;
+ bool is_in_block_fragmentation = false;
+
// Rendering context for 3D sorting. See
// TransformPaintPropertyNode::renderingContextId.
unsigned rendering_context_id = 0;
@@ -110,6 +112,8 @@ struct PaintPropertyTreeBuilderFragmentContext {
// reference a scroll offset transform, scroll nodes should be updated if
// the transform tree changes.
const ScrollPaintPropertyNode* scroll = nullptr;
+
+ FloatSize pending_scroll_anchor_adjustment;
};
ContainingBlockContext current;
@@ -121,8 +125,6 @@ struct PaintPropertyTreeBuilderFragmentContext {
// containing block of corresponding positioned descendants. Overflow clips
// are also inherited by containing block tree instead of DOM tree, thus they
// are included in the additional context too.
- //
- // Note that these contexts are not used in LayoutNGFragmentTraversal.
ContainingBlockContext absolute_position;
ContainingBlockContext fixed_position;
@@ -154,6 +156,13 @@ struct PaintPropertyTreeBuilderFragmentContext {
PhysicalOffset old_paint_offset;
+ // Paint offset at the current innermost fragmentainer.
+ PhysicalOffset fragmentainer_paint_offset;
+
+ // Amount of adjustment done by UpdateForPaintOffsetTranslation() since we
+ // entered the innermost fragmentainer.
+ PhysicalOffset adjustment_for_oof_in_fragmentainer;
+
// An additional offset that applies to the current fragment, but is detected
// *before* the ContainingBlockContext is updated for it. Once the
// ContainingBlockContext is set, this value should be added to
@@ -175,7 +184,6 @@ struct PaintPropertyTreeBuilderContext final {
Vector<PaintPropertyTreeBuilderFragmentContext, 1> fragments;
- // TODO(mstensho): Stop using these in LayoutNGFragmentTraversal.
const LayoutObject* container_for_absolute_position = nullptr;
const LayoutObject* container_for_fixed_position = nullptr;
@@ -252,7 +260,8 @@ class VisualViewportPaintPropertyTreeBuilder {
// Update the paint properties for the visual viewport and ensure the context
// is up to date. Returns the maximum paint property change type for any of
// the viewport nodes.
- static PaintPropertyChangeType Update(VisualViewport&,
+ static PaintPropertyChangeType Update(LocalFrameView& main_frame_view,
+ VisualViewport&,
PaintPropertyTreeBuilderContext&);
};
@@ -260,12 +269,41 @@ struct NGPrePaintInfo {
STACK_ALLOCATED();
public:
- NGPrePaintInfo(const NGFragmentChildIterator& iterator,
- FragmentData& fragment_data)
- : iterator(iterator), fragment_data(fragment_data) {}
-
- const NGFragmentChildIterator& iterator;
- FragmentData& fragment_data;
+ NGPrePaintInfo(const NGPhysicalBoxFragment& box_fragment,
+ PhysicalOffset paint_offset,
+ wtf_size_t fragmentainer_idx,
+ bool is_first_for_node,
+ bool is_last_for_node,
+ bool is_inside_orphaned_object,
+ bool is_inside_fragment_child)
+ : box_fragment(box_fragment),
+ paint_offset(paint_offset),
+ fragmentainer_idx(fragmentainer_idx),
+ is_first_for_node(is_first_for_node),
+ is_last_for_node(is_last_for_node),
+ is_inside_orphaned_object(is_inside_orphaned_object),
+ is_inside_fragment_child(is_inside_fragment_child) {}
+
+ // The fragment for the LayoutObject currently being processed, or, in the
+ // case of text and non-atomic inlines: the fragment of the containing block.
+ const NGPhysicalBoxFragment& box_fragment;
+
+ FragmentData* fragment_data = nullptr;
+ PhysicalOffset paint_offset;
+ wtf_size_t fragmentainer_idx;
+ bool is_first_for_node;
+ bool is_last_for_node;
+
+ // True if we're fragment-traversing an object (OOF or float) directly,
+ // instead of walking the layout object tree. In this case, the property /
+ // invalidation context chains will be missing ancestors between the
+ // fragmentainer and the OOF / float.
+ bool is_inside_orphaned_object;
+
+ // True if |box_fragment| is the containing block of the LayoutObject
+ // currently being processed. Otherwise, |box_fragment| is a fragment for the
+ // LayoutObject itself.
+ bool is_inside_fragment_child;
};
// Creates paint property tree nodes for non-local effects in the layout tree.
@@ -295,6 +333,9 @@ class PaintPropertyTreeBuilder {
// Returns whether any paint property of the object has changed.
PaintPropertyChangeType UpdateForChildren();
+ static bool NeedsTransform(const LayoutObject& object,
+ CompositingReasons direct_compositing_reasons);
+
private:
ALWAYS_INLINE void InitFragmentPaintProperties(
FragmentData&,
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 f8028de1716..0c159000b5b 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
@@ -125,7 +125,13 @@ void PaintPropertyTreeBuilderTest::SetUp() {
#define CHECK_EXACT_VISUAL_RECT(expected, source_object, ancestor) \
CHECK_VISUAL_RECT(expected, source_object, ancestor, 0)
-INSTANTIATE_PAINT_TEST_SUITE_P(PaintPropertyTreeBuilderTest);
+INSTANTIATE_TEST_SUITE_P(All,
+ PaintPropertyTreeBuilderTest,
+ ::testing::Values(0,
+ kCompositeAfterPaint,
+ kUnderInvalidationChecking,
+ kCompositeAfterPaint |
+ kUnderInvalidationChecking));
TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
LoadTestData("fixed-position.html");
@@ -833,8 +839,9 @@ TEST_P(PaintPropertyTreeBuilderTest, WillChangeContents) {
TEST_P(PaintPropertyTreeBuilderTest,
BackfaceVisibilityWithPseudoStacking3DChildren) {
- ScopedTransformInteropForTest enabled(true);
- // TODO(chrishtr): implement for CAP. This entails computing
+ ScopedTransformInteropForTest ti_enabled(true);
+ ScopedBackfaceVisibilityInteropForTest bfi_enabled(true);
+ // TODO(chrishtr, dbaron): implement for CAP. This entails computing
// has_backface_invisible_ancestor_in_same_3d_context in the pre-paint tree
// walk.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
@@ -4318,6 +4325,12 @@ TEST_P(PaintPropertyTreeBuilderTest, SpanFragmentsLimitedToSize) {
TEST_P(PaintPropertyTreeBuilderTest,
PaintOffsetUnderMulticolumnScrollFixedPos) {
+ // Raster under-invalidation will fail to allocate bitmap when checking a huge
+ // layer created without LayoutNGBlockFragmentation.
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
+ !RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled())
+ return;
+
SetBodyInnerHTML(R"HTML(
<div id=fixed style='position: fixed; columns: 2'>
<div style='width: 50px; height: 20px; background: lightblue'></div>
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 f3b66da3b0a..0570c2d62e1 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
@@ -113,7 +113,9 @@ class PropertyTreePrinterTraits<EffectPaintPropertyNodeOrAlias> {
public:
static void AddVisualViewportProperties(
const VisualViewport& visual_viewport,
- PropertyTreePrinter<EffectPaintPropertyNodeOrAlias>& printer) {}
+ PropertyTreePrinter<EffectPaintPropertyNodeOrAlias>& printer) {
+ printer.AddNode(visual_viewport.GetOverscrollElasticityEffectNode());
+ }
static void AddObjectPaintProperties(
const ObjectPaintProperties& properties,
@@ -165,6 +167,10 @@ namespace paint_property_tree_printer {
void UpdateDebugNames(const VisualViewport& viewport) {
if (auto* device_emulation_node = viewport.GetDeviceEmulationTransformNode())
device_emulation_node->SetDebugName("Device Emulation Node");
+ if (auto* overscroll_effect_node =
+ viewport.GetOverscrollElasticityEffectNode()) {
+ overscroll_effect_node->SetDebugName("Overscroll Elasticity Effect Node");
+ }
if (auto* overscroll_node = viewport.GetOverscrollElasticityTransformNode())
overscroll_node->SetDebugName("Overscroll Elasticity Node");
viewport.GetPageScaleNode()->SetDebugName("VisualViewport Scale Node");
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 279953b0614..b989f2f8287 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
@@ -18,7 +18,13 @@ namespace blink {
// Tests covering incremental updates of paint property trees.
class PaintPropertyTreeUpdateTest : public PaintPropertyTreeBuilderTest {};
-INSTANTIATE_PAINT_TEST_SUITE_P(PaintPropertyTreeUpdateTest);
+INSTANTIATE_TEST_SUITE_P(All,
+ PaintPropertyTreeUpdateTest,
+ ::testing::Values(0,
+ kCompositeAfterPaint,
+ kUnderInvalidationChecking,
+ kCompositeAfterPaint |
+ kUnderInvalidationChecking));
TEST_P(PaintPropertyTreeUpdateTest,
ThreadedScrollingDisabledMainThreadScrollReason) {
@@ -826,7 +832,7 @@ TEST_P(PaintPropertyTreeUpdateTest,
SetBodyInnerHTML(R"HTML(
<style>
::-webkit-scrollbar {width: 20px; height: 20px}
- body {height: 10000px; width: 10000px; margin: 0;}
+ body {height: 2000px; width: 2000px; margin: 0;}
</style>
)HTML");
@@ -840,7 +846,7 @@ TEST_P(PaintPropertyTreeUpdateTest,
TEST_P(PaintPropertyTreeUpdateTest, ViewportAddRemoveDeviceEmulationNode) {
SetBodyInnerHTML(
- "<style>body {height: 10000px; width: 10000px; margin: 0;}</style>");
+ "<style>body {height: 2000px; width: 2000px; margin: 0;}</style>");
auto& visual_viewport = GetDocument().GetPage()->GetVisualViewport();
EXPECT_FALSE(visual_viewport.GetDeviceEmulationTransformNode());
@@ -858,8 +864,10 @@ TEST_P(PaintPropertyTreeUpdateTest, ViewportAddRemoveDeviceEmulationNode) {
EXPECT_EQ(&TransformPaintPropertyNode::Root(),
&scrollbar_layer->GetPropertyTreeState().Transform());
} else {
- // TODO(wangxianzhu): Test for CompositeAfterPaint.
- EXPECT_FALSE(scrollbar_layer);
+ auto& chunk = *(ContentPaintChunks().begin() + 1);
+ EXPECT_EQ(DisplayItem::kScrollbarHorizontal, chunk.id.type);
+ EXPECT_EQ(&TransformPaintPropertyNode::Root(),
+ &chunk.properties.Transform());
}
// These emulate WebViewImpl::SetDeviceEmulationTransform().
@@ -874,8 +882,10 @@ TEST_P(PaintPropertyTreeUpdateTest, ViewportAddRemoveDeviceEmulationNode) {
EXPECT_EQ(visual_viewport.GetDeviceEmulationTransformNode(),
&scrollbar_layer->GetPropertyTreeState().Transform());
} else {
- // TODO(wangxianzhu): Test for CompositeAfterPaint.
- EXPECT_FALSE(scrollbar_layer);
+ auto& chunk = *(ContentPaintChunks().begin() + 1);
+ EXPECT_EQ(DisplayItem::kScrollbarHorizontal, chunk.id.type);
+ EXPECT_EQ(visual_viewport.GetDeviceEmulationTransformNode(),
+ &chunk.properties.Transform());
}
// These emulate WebViewImpl::SetDeviceEmulationTransform().
@@ -889,8 +899,10 @@ TEST_P(PaintPropertyTreeUpdateTest, ViewportAddRemoveDeviceEmulationNode) {
EXPECT_EQ(&TransformPaintPropertyNode::Root(),
&scrollbar_layer->GetPropertyTreeState().Transform());
} else {
- // TODO(wangxianzhu): Test for CompositeAfterPaint.
- EXPECT_FALSE(scrollbar_layer);
+ auto& chunk = *(ContentPaintChunks().begin() + 1);
+ EXPECT_EQ(DisplayItem::kScrollbarHorizontal, chunk.id.type);
+ EXPECT_EQ(&TransformPaintPropertyNode::Root(),
+ &chunk.properties.Transform());
}
}
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 5b92ab258b1..44da167084b 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
+#include "third_party/blink/renderer/platform/graphics/paint/ignore_paint_timing_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
@@ -49,7 +50,7 @@ class RecodingTimeAfterBackForwardCacheRestoreFrameCallback
public:
RecodingTimeAfterBackForwardCacheRestoreFrameCallback(
PaintTiming* paint_timing,
- size_t record_index)
+ wtf_size_t record_index)
: paint_timing_(paint_timing), record_index_(record_index) {}
~RecodingTimeAfterBackForwardCacheRestoreFrameCallback() override = default;
@@ -81,7 +82,7 @@ class RecodingTimeAfterBackForwardCacheRestoreFrameCallback
private:
Member<PaintTiming> paint_timing_;
- const size_t record_index_;
+ const wtf_size_t record_index_;
size_t count_ = 0;
};
@@ -104,6 +105,7 @@ void PaintTiming::MarkFirstPaint() {
// markFirstPaint().
if (!first_paint_.is_null())
return;
+ DCHECK_EQ(IgnorePaintTimingScope::IgnoreDepth(), 0);
SetFirstPaint(clock_->NowTicks());
}
@@ -114,12 +116,15 @@ void PaintTiming::MarkFirstContentfulPaint() {
// markFirstContentfulPaint().
if (!first_contentful_paint_.is_null())
return;
+ if (IgnorePaintTimingScope::IgnoreDepth() > 0)
+ return;
SetFirstContentfulPaint(clock_->NowTicks());
}
void PaintTiming::MarkFirstImagePaint() {
if (!first_image_paint_.is_null())
return;
+ DCHECK_EQ(IgnorePaintTimingScope::IgnoreDepth(), 0);
first_image_paint_ = clock_->NowTicks();
SetFirstContentfulPaint(first_image_paint_);
RegisterNotifyPresentationTime(PaintEvent::kFirstImagePaint);
@@ -176,6 +181,8 @@ void PaintTiming::SetFirstMeaningfulPaint(
void PaintTiming::NotifyPaint(bool is_first_paint,
bool text_painted,
bool image_painted) {
+ if (IgnorePaintTimingScope::IgnoreDepth() > 0)
+ return;
if (is_first_paint)
MarkFirstPaint();
if (text_painted)
@@ -223,13 +230,7 @@ void PaintTiming::SetFirstPaint(base::TimeTicks stamp) {
if (!first_paint_.is_null())
return;
- LocalFrame* frame = GetFrame();
- if (frame && frame->GetDocument()) {
- Document* document = frame->GetDocument();
- document->MarkFirstPaint();
- if (frame->IsMainFrame())
- document->Fetcher()->MarkFirstPaint();
- }
+ DCHECK_EQ(IgnorePaintTimingScope::IgnoreDepth(), 0);
first_paint_ = stamp;
RegisterNotifyPresentationTime(PaintEvent::kFirstPaint);
@@ -238,6 +239,7 @@ void PaintTiming::SetFirstPaint(base::TimeTicks stamp) {
void PaintTiming::SetFirstContentfulPaint(base::TimeTicks stamp) {
if (!first_contentful_paint_.is_null())
return;
+ DCHECK_EQ(IgnorePaintTimingScope::IgnoreDepth(), 0);
SetFirstPaint(stamp);
first_contentful_paint_ = stamp;
RegisterNotifyPresentationTime(PaintEvent::kFirstContentfulPaint);
@@ -248,9 +250,6 @@ void PaintTiming::SetFirstContentfulPaint(base::TimeTicks stamp) {
return;
frame->View()->OnFirstContentfulPaint();
- if (frame->GetDocument() && frame->GetDocument()->Fetcher())
- frame->GetDocument()->Fetcher()->MarkFirstContentfulPaint();
-
if (frame->GetFrameScheduler())
frame->GetFrameScheduler()->OnFirstContentfulPaintInMainFrame();
@@ -266,7 +265,7 @@ void PaintTiming::RegisterNotifyPresentationTime(PaintEvent event) {
void PaintTiming::
RegisterNotifyFirstPaintAfterBackForwardCacheRestorePresentationTime(
- size_t index) {
+ wtf_size_t index) {
RegisterNotifyPresentationTime(CrossThreadBindOnce(
&PaintTiming::
ReportFirstPaintAfterBackForwardCacheRestorePresentationTime,
@@ -299,7 +298,6 @@ void PaintTiming::ReportPresentationTime(PaintEvent event,
//
// TODO(crbug.com/738235): Consider not reporting any timestamp when failing
// for reasons other than kDidNotSwapSwapFails.
- ReportSwapResultHistogram(result);
switch (event) {
case PaintEvent::kFirstPaint:
SetFirstPaintPresentation(timestamp);
@@ -319,11 +317,10 @@ void PaintTiming::ReportPresentationTime(PaintEvent event,
}
void PaintTiming::ReportFirstPaintAfterBackForwardCacheRestorePresentationTime(
- size_t index,
+ wtf_size_t index,
WebSwapResult result,
base::TimeTicks timestamp) {
DCHECK(IsMainThread());
- ReportSwapResultHistogram(result);
SetFirstPaintAfterBackForwardCacheRestorePresentation(timestamp, index);
}
@@ -382,7 +379,7 @@ void PaintTiming::SetFirstImagePaintPresentation(base::TimeTicks stamp) {
void PaintTiming::SetFirstPaintAfterBackForwardCacheRestorePresentation(
base::TimeTicks stamp,
- size_t index) {
+ wtf_size_t index) {
// The elements are allocated when the page is restored from the cache.
DCHECK_GE(first_paints_after_back_forward_cache_restore_presentation_.size(),
index);
@@ -393,7 +390,7 @@ void PaintTiming::SetFirstPaintAfterBackForwardCacheRestorePresentation(
}
void PaintTiming::SetRequestAnimationFrameAfterBackForwardCacheRestore(
- size_t index,
+ wtf_size_t index,
size_t count) {
auto now = clock_->NowTicks();
@@ -407,15 +404,10 @@ void PaintTiming::SetRequestAnimationFrameAfterBackForwardCacheRestore(
current_rafs[count] = now;
}
-void PaintTiming::ReportSwapResultHistogram(WebSwapResult result) {
- UMA_HISTOGRAM_ENUMERATION("PageLoad.Internal.Renderer.PaintTiming.SwapResult",
- result);
-}
-
void PaintTiming::OnRestoredFromBackForwardCache() {
// Allocate the last element with 0, which indicates that the first paint
// after this navigation doesn't happen yet.
- size_t index =
+ wtf_size_t index =
first_paints_after_back_forward_cache_restore_presentation_.size();
DCHECK_EQ(index,
request_animation_frames_after_back_forward_cache_restore_.size());
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing.h b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
index d0dbdf06ace..7a44f1d77ca 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
@@ -146,12 +146,10 @@ class CORE_EXPORT PaintTiming final : public GarbageCollected<PaintTiming>,
WebSwapResult,
base::TimeTicks timestamp);
void ReportFirstPaintAfterBackForwardCacheRestorePresentationTime(
- size_t index,
+ wtf_size_t index,
WebSwapResult,
base::TimeTicks timestamp);
- void ReportSwapResultHistogram(WebSwapResult);
-
// The caller owns the |clock| which must outlive the PaintTiming.
void SetTickClockForTesting(const base::TickClock* clock);
@@ -191,13 +189,13 @@ class CORE_EXPORT PaintTiming final : public GarbageCollected<PaintTiming>,
// index to avoid confusing the data from different navigations.
void SetFirstPaintAfterBackForwardCacheRestorePresentation(
base::TimeTicks stamp,
- size_t index);
- void SetRequestAnimationFrameAfterBackForwardCacheRestore(size_t index,
+ wtf_size_t index);
+ void SetRequestAnimationFrameAfterBackForwardCacheRestore(wtf_size_t index,
size_t count);
void RegisterNotifyPresentationTime(PaintEvent);
void RegisterNotifyFirstPaintAfterBackForwardCacheRestorePresentationTime(
- size_t index);
+ wtf_size_t index);
base::TimeTicks FirstPaintRendered() const { return first_paint_; }
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
index 85e53c825b4..9a795855075 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/html_element.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/layout/layout_view.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
index 0c8698caf2d..9b8bd4c7c66 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/graphics/paint/ignore_paint_timing_scope.h"
#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
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 08626f312fb..9806adced82 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/pre_paint_tree_walk.h"
#include "base/auto_reset.h"
+#include "base/stl_util.h"
#include "cc/base/features.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
@@ -15,20 +16,19 @@
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
-#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
-#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
+#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#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/cull_rect_updater.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_property_tree_printer.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
@@ -36,114 +36,6 @@
namespace blink {
-namespace {
-
-// Locate or/and set up the current FragmentData object. This may involve
-// creating it, or resetting an existing one. If |allow_reset| is set, we're
-// allowed to clear old FragmentData objects.
-NGPrePaintInfo SetupFragmentData(const NGFragmentChildIterator& iterator,
- bool allow_reset) {
- // TODO(crbug.com/1043787): What's here is mostly gross, and we need to come
- // up with something better. The way FragmentData works (and is stored)
- // vs. the way NGPhysicalFragment works is less than ideal.
- //
- // There's essentially a 1:1 correspondence between a block-level
- // NGPhysicalBoxFragment and FragmentData, but there's no direct link between
- // them, so we have to do some work. In the future we might want to make
- // FragmentData part of NGPhysicalBoxFragment objects, to simplify this, and
- // to get rid of O(n^2) performance complexity (where n is the number of
- // fragments generated by a node). Note that this performance complexity also
- // exists in the legacy engine.
- //
- // For inline-level nodes, it gets a bit more complicated. There's one
- // FragmentData object per fragmentainer said node occurs in. The offset and
- // invalidation rectangle in each FragmentData will be a union of all the
- // fragments generated by the node (one per line box, typically) in that
- // fragmentainer. This also matches how we do it in legacy layout. It's
- // considered too expensive to have one FragmentData object per line for each
- // text node or non-atomic inline.
- DCHECK(iterator->GetLayoutObject());
- const LayoutObject& object = *iterator->GetLayoutObject();
- FragmentData* fragment_data = &object.GetMutableForPainting().FirstFragment();
- const auto* incoming_break_token = iterator->BlockBreakToken();
- const NGPhysicalBoxFragment* box_fragment = iterator->BoxFragment();
-
- // The need for paint properties is the same across all fragments, so if the
- // first FragmentData needs it, so do all the others.
- bool needs_paint_properties = fragment_data->PaintProperties();
-
- if (const NGFragmentItem* fragment_item = iterator->FragmentItem()) {
- // We're in an inline formatting context. The consumed block-size stored in
- // the incoming break token will be stored in FragmentData objects to
- // identify each portion for a given fragmentainer.
- LayoutUnit consumed_block_size;
- if (incoming_break_token)
- consumed_block_size = incoming_break_token->ConsumedBlockSize();
- if (fragment_item->IsFirstForNode()) {
- // This is the first fragment generated for the node (i.e. we're on the
- // first line and first fragmentainer (column) that this node occurs
- // in). Now is our chance to reset everything (the number or size of
- // fragments may have changed since last time). All the other fragments
- // will be visited in due course.
- if (allow_reset && !object.IsBox()) {
- // For text and non-atomic inlines, we now remove additional
- // FragmentData objects, and reset the visual rect. The visual rect will
- // be set and expanded, as we visit each individual fragment.
- fragment_data->ClearNextFragment();
- }
- fragment_data->SetLogicalTopInFlowThread(consumed_block_size);
- } else {
- // This is not the first fragment. Now see if we can find a FragmentData
- // with the right consumed block-size (or flow thread logical top). If
- // not, we'll have to create one now.
- while (consumed_block_size > fragment_data->LogicalTopInFlowThread()) {
- FragmentData* next_fragment_data = fragment_data->NextFragment();
- if (!next_fragment_data) {
- fragment_data = &fragment_data->EnsureNextFragment();
- fragment_data->SetLogicalTopInFlowThread(consumed_block_size);
- break;
- }
- fragment_data = next_fragment_data;
- }
- DCHECK_EQ(fragment_data->LogicalTopInFlowThread(), consumed_block_size);
- }
- } else {
- // The fragment is block-level.
- if (IsResumingLayout(incoming_break_token)) {
- // This isn't the first fragment for the node. We now need to walk past
- // all preceding fragments to figure out which FragmentData to return (or
- // create, if it doesn't already exist).
- const auto& layout_box = To<LayoutBox>(object);
- for (wtf_size_t idx = 0;; idx++) {
- DCHECK_LT(idx, layout_box.PhysicalFragmentCount());
- if (layout_box.GetPhysicalFragment(idx) == box_fragment)
- break;
- FragmentData* next = fragment_data->NextFragment();
- if (!next) {
- DCHECK_EQ(layout_box.GetPhysicalFragment(idx + 1), box_fragment);
- fragment_data = &fragment_data->EnsureNextFragment();
- break;
- }
- fragment_data = next;
- }
- fragment_data->SetLogicalTopInFlowThread(
- incoming_break_token->ConsumedBlockSize());
- }
- if (!box_fragment->BreakToken()) {
- // We have reached the end. There may be more data entries that were
- // needed in the previous layout, but not any more. Clear them.
- fragment_data->ClearNextFragment();
- }
- }
-
- if (needs_paint_properties)
- fragment_data->EnsurePaintProperties();
-
- return NGPrePaintInfo(iterator, *fragment_data);
-}
-
-} // anonymous namespace
-
static void SetNeedsCompositingLayerPropertyUpdate(const LayoutObject& object) {
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
return;
@@ -192,7 +84,7 @@ void PrePaintTreeWalk::WalkTree(LocalFrameView& root_frame_view) {
if (root_frame_view.GetFrame().IsMainFrame()) {
auto property_changed = VisualViewportPaintPropertyTreeBuilder::Update(
- root_frame_view.GetPage()->GetVisualViewport(),
+ root_frame_view, root_frame_view.GetPage()->GetVisualViewport(),
*context.tree_builder_context);
if (property_changed >
@@ -206,14 +98,10 @@ void PrePaintTreeWalk::WalkTree(LocalFrameView& root_frame_view) {
Walk(root_frame_view, context);
paint_invalidator_.ProcessPendingDelayedPaintInvalidations();
- if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
- if (auto* layout_view = root_frame_view.GetLayoutView())
- CullRectUpdater(*layout_view->Layer()).Update();
- }
-
#if DCHECK_IS_ON()
if (needs_tree_builder_context_update) {
- if (VLOG_IS_ON(2) && root_frame_view.GetLayoutView()) {
+ if (!RuntimeEnabledFeatures::CullRectUpdateEnabled() && VLOG_IS_ON(2) &&
+ root_frame_view.GetLayoutView()) {
VLOG(2) << "PrePaintTreeWalk::Walk(root_frame_view=" << &root_frame_view
<< ")\nPaintLayer tree:";
showLayerTree(root_frame_view.GetLayoutView()->Layer());
@@ -257,6 +145,12 @@ void PrePaintTreeWalk::Walk(LocalFrameView& frame_view,
PrePaintTreeWalkContext context(parent_context,
needs_tree_builder_context_update);
+ // Block fragmentation doesn't cross frame boundaries.
+ context.current_fragmentainer = {};
+ context.absolute_positioned_container = {};
+ context.fixed_positioned_container = {};
+ context.oof_container_candidate_fragment = nullptr;
+
// ancestor_scroll_container_paint_layer does not cross frame boundaries.
context.ancestor_scroll_container_paint_layer = nullptr;
if (context.tree_builder_context) {
@@ -273,14 +167,14 @@ void PrePaintTreeWalk::Walk(LocalFrameView& frame_view,
<< ")\nLayout tree:";
showLayoutTree(view);
VLOG(3) << "Fragment tree:";
- NGPhysicalFragment::ShowFragmentTree(*view);
+ ShowFragmentTree(*view);
}
#endif
is_wheel_event_regions_enabled_ =
base::FeatureList::IsEnabled(::features::kWheelEventRegions);
- Walk(*view, context, /* iterator */ nullptr);
+ Walk(*view, context, /* pre_paint_info */ nullptr);
#if DCHECK_IS_ON()
view->AssertSubtreeClearedPaintInvalidationFlags();
#endif
@@ -428,8 +322,14 @@ bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate(
}
return frame_view.GetLayoutView() &&
- (ObjectRequiresTreeBuilderContext(*frame_view.GetLayoutView()) ||
- ContextRequiresChildTreeBuilderContext(context));
+ NeedsTreeBuilderContextUpdate(*frame_view.GetLayoutView(), context);
+}
+
+bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate(
+ const LayoutObject& object,
+ const PrePaintTreeWalkContext& parent_context) {
+ return ContextRequiresChildTreeBuilderContext(parent_context) ||
+ ObjectRequiresTreeBuilderContext(object);
}
bool PrePaintTreeWalk::ObjectRequiresPrePaint(const LayoutObject& object) {
@@ -548,18 +448,108 @@ void PrePaintTreeWalk::UpdatePaintInvalidationContainer(
}
}
+NGPrePaintInfo PrePaintTreeWalk::CreatePrePaintInfo(
+ const NGLink& child,
+ const PrePaintTreeWalkContext& context) {
+ const auto& fragment = *To<NGPhysicalBoxFragment>(child.fragment);
+ return NGPrePaintInfo(fragment, child.offset,
+ context.current_fragmentainer.fragmentainer_idx,
+ fragment.IsFirstForNode(), !fragment.BreakToken(),
+ context.is_inside_orphaned_object,
+ /* is_inside_fragment_child */ false);
+}
+
+FragmentData* PrePaintTreeWalk::GetOrCreateFragmentData(
+ const LayoutObject& object,
+ const PrePaintTreeWalkContext& context,
+ const NGPrePaintInfo& pre_paint_info) {
+ // If |allow_update| is set, we're allowed to add, remove and modify
+ // FragmentData objects. Otherwise they will be left alone.
+ bool allow_update = context.NeedsTreeBuilderContext();
+
+ FragmentData* fragment_data = &object.GetMutableForPainting().FirstFragment();
+
+ // The need for paint properties is the same across all fragments, so if the
+ // first FragmentData needs it, so do all the others.
+ bool needs_paint_properties = fragment_data->PaintProperties();
+
+ wtf_size_t fragment_id = pre_paint_info.fragmentainer_idx;
+ // TODO(mstensho): For now we need to treat unfragmented as ID 0. It doesn't
+ // really matter for LayoutNG, but legacy
+ // PaintPropertyTreeBuilder::ContextForFragment() may take a walk up the tree
+ // and end up querying this (LayoutNG) object, and
+ // FragmentData::LogicalTopInFlowThread() will DCHECK that the value is 0
+ // unless it has been explicitly set by legacy code (which won't happen, since
+ // it's an NG object).
+ if (fragment_id == WTF::kNotFound)
+ fragment_id = 0;
+
+ if (pre_paint_info.is_first_for_node) {
+ if (allow_update)
+ fragment_data->ClearNextFragment();
+ else
+ DCHECK_EQ(fragment_data->FragmentID(), fragment_id);
+ } else {
+ FragmentData* last_fragment = nullptr;
+ do {
+ if (fragment_data->FragmentID() >= fragment_id)
+ break;
+ last_fragment = fragment_data;
+ fragment_data = fragment_data->NextFragment();
+ } while (fragment_data);
+ if (fragment_data) {
+ if (pre_paint_info.is_last_for_node) {
+ // We have reached the end. There may be more data entries that were
+ // needed in the previous layout, but not any more. Clear them.
+ if (allow_update)
+ fragment_data->ClearNextFragment();
+ else
+ DCHECK(!fragment_data->NextFragment());
+ } else if (fragment_data->FragmentID() != fragment_id) {
+ // There are entries for fragmentainers after this one, but none for
+ // this one. Remove the fragment tail.
+ DCHECK(allow_update);
+ DCHECK_GT(fragment_data->FragmentID(), fragment_id);
+ fragment_data->ClearNextFragment();
+ }
+ } else {
+ DCHECK(allow_update);
+ fragment_data = &last_fragment->EnsureNextFragment();
+ }
+ }
+
+ if (allow_update) {
+ fragment_data->SetFragmentID(fragment_id);
+
+ if (needs_paint_properties)
+ fragment_data->EnsurePaintProperties();
+ } else {
+ DCHECK_EQ(fragment_data->FragmentID(), fragment_id);
+ DCHECK(!needs_paint_properties || fragment_data->PaintProperties());
+ }
+
+ return fragment_data;
+}
+
void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
PrePaintTreeWalkContext& context,
- const NGFragmentChildIterator* iterator) {
+ NGPrePaintInfo* pre_paint_info) {
PaintInvalidatorContext& paint_invalidator_context =
context.paint_invalidator_context;
- absl::optional<NGPrePaintInfo> pre_paint_info_storage;
- NGPrePaintInfo* pre_paint_info = nullptr;
- if (iterator) {
- bool allow_reset = context.NeedsTreeBuilderContext();
- pre_paint_info_storage.emplace(SetupFragmentData(*iterator, allow_reset));
- pre_paint_info = &pre_paint_info_storage.value();
+ if (pre_paint_info) {
+ DCHECK(!pre_paint_info->fragment_data);
+ // Find, update or create a FragmentData object to match the current block
+ // fragment.
+ //
+ // TODO(mstensho): If this is collapsed text or a culled inline, we might
+ // not have any work to do (we could just return early here), as there'll be
+ // no need for paint property updates or invalidation. However, this is a
+ // bit tricky to determine, because of things like LinkHighlight, which
+ // might set paint properties on a culled inline.
+ pre_paint_info->fragment_data =
+ GetOrCreateFragmentData(object, context, *pre_paint_info);
+ DCHECK(pre_paint_info->fragment_data);
}
// This must happen before updatePropertiesForSelf, because the latter reads
@@ -677,6 +667,70 @@ void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
}
}
+bool PrePaintTreeWalk::CollectMissableChildren(
+ PrePaintTreeWalkContext& context,
+ const NGPhysicalBoxFragment& parent) {
+ bool has_missable_children = false;
+ for (const NGLink& child : parent.Children()) {
+ if ((child->IsOutOfFlowPositioned() &&
+ (context.current_fragmentainer.fragment ||
+ child->IsFixedPositioned())) ||
+ (child->IsFloating() && parent.IsInlineFormattingContext() &&
+ context.current_fragmentainer.fragment)) {
+ // We'll add resumed floats (or floats that couldn't fit a fragment in the
+ // fragmentainer where it was discovered) that have escaped their inline
+ // formatting context.
+ //
+ // We'll also add all out-of-flow positioned fragments inside a
+ // fragmentation context. If a fragment is fixed-positioned, we even need
+ // to add those that aren't inside a fragmentation context, because they
+ // may have an ancestor LayoutObject inside one, and one of those
+ // ancestors may be out-of-flow positioned, which may be missed, in which
+ // case we'll miss this fixed-positioned one as well (since we don't enter
+ // descendant OOFs when walking missed children) (example: fixedpos inside
+ // missed abspos in relpos in multicol).
+ pending_missables_.insert(child.fragment);
+ has_missable_children = true;
+ }
+ }
+ return has_missable_children;
+}
+
+void PrePaintTreeWalk::WalkMissedChildren(const NGPhysicalBoxFragment& fragment,
+ PrePaintTreeWalkContext& context) {
+ if (pending_missables_.IsEmpty())
+ return;
+
+ for (const NGLink& child : fragment.Children()) {
+ if (!child->IsOutOfFlowPositioned() && !child->IsFloating())
+ continue;
+ if (!pending_missables_.Contains(child.fragment))
+ continue;
+ const LayoutObject& descendant_object = *child->GetLayoutObject();
+ PrePaintTreeWalkContext descendant_context(
+ context, NeedsTreeBuilderContextUpdate(descendant_object, context));
+ if (child->IsOutOfFlowPositioned() &&
+ descendant_context.tree_builder_context) {
+ PaintPropertyTreeBuilderFragmentContext& fragment_context =
+ descendant_context.tree_builder_context->fragments[0];
+ // Reset the relevant OOF context to this fragmentainer, since this is its
+ // containing block, as far as the NG fragment structure is concerned.
+ // Note that when walking a missed child OOF fragment, we'll also
+ // forcefully miss any OOF descendant nodes, which is why we only set the
+ // context for the OOF type we're dealing with here.
+ if (child->IsFixedPositioned())
+ fragment_context.fixed_position = fragment_context.current;
+ else
+ fragment_context.absolute_position = fragment_context.current;
+ }
+ descendant_context.is_inside_orphaned_object = true;
+
+ NGPrePaintInfo pre_paint_info =
+ CreatePrePaintInfo(child, descendant_context);
+ Walk(descendant_object, descendant_context, &pre_paint_info);
+ }
+}
+
LocalFrameView* FindWebViewPluginContentFrameView(
const LayoutEmbeddedContent& embedded_content) {
for (Frame* frame = embedded_content.GetFrame()->Tree().FirstChild(); frame;
@@ -688,248 +742,454 @@ LocalFrameView* FindWebViewPluginContentFrameView(
return nullptr;
}
-void PrePaintTreeWalk::WalkNGChildren(const LayoutObject* parent,
- PrePaintTreeWalkContext& parent_context,
- NGFragmentChildIterator* iterator) {
+void PrePaintTreeWalk::WalkFragmentationContextRootChildren(
+ const LayoutObject& object,
+ const NGPhysicalBoxFragment& fragment,
+ PrePaintTreeWalkContext& context) {
+ // The actual children are inside the flow thread child of |object|.
+ const auto* flow_thread =
+ To<LayoutBlockFlow>(&object)->MultiColumnFlowThread();
+ const LayoutObject& actual_parent = flow_thread ? *flow_thread : object;
+
FragmentData* fragmentainer_fragment_data = nullptr;
#if DCHECK_IS_ON()
const LayoutObject* fragmentainer_owner_box = nullptr;
#endif
- for (; !iterator->IsAtEnd(); iterator->Advance()) {
- const LayoutObject* object = (*iterator)->GetLayoutObject();
- if (const auto* fragment_item = (*iterator)->FragmentItem()) {
- // Line boxes are not interesting. They have no paint effects. Descend
- // directly into children.
- if (fragment_item->Type() == NGFragmentItem::kLine) {
- WalkChildren(/* parent */ nullptr, parent_context, iterator);
- continue;
- }
- } else if (!object) {
- const NGPhysicalBoxFragment* box_fragment = (*iterator)->BoxFragment();
- if (UNLIKELY(box_fragment->IsLayoutObjectDestroyedOrMoved()))
- continue;
- // Check |box_fragment| and the |LayoutBox| that produced it are in sync.
- // |OwnerLayoutBox()| has a few DCHECKs for this purpose.
- DCHECK(box_fragment->OwnerLayoutBox());
+ DCHECK(fragment.IsFragmentationContextRoot());
- // A fragmentainer doesn't paint anything itself. Just include its offset
- // and descend into children.
- DCHECK((*iterator)->BoxFragment()->IsFragmentainerBox());
- if (UNLIKELY(!parent_context.tree_builder_context)) {
- WalkChildren(/* parent */ nullptr, parent_context, iterator);
+ const auto outer_fragmentainer = context.current_fragmentainer;
+ absl::optional<wtf_size_t> inner_fragmentainer_idx;
+
+ for (NGLink child : fragment.Children()) {
+ const auto* box_fragment = To<NGPhysicalBoxFragment>(child.fragment);
+ if (UNLIKELY(box_fragment->IsLayoutObjectDestroyedOrMoved()))
+ continue;
+
+ if (box_fragment->GetLayoutObject()) {
+ // OOFs contained by a multicol container will be visited during object
+ // tree traversal.
+ if (box_fragment->IsOutOfFlowPositioned())
continue;
- }
- PaintPropertyTreeBuilderContext& tree_builder_context =
- *parent_context.tree_builder_context;
- PaintPropertyTreeBuilderFragmentContext& context =
- tree_builder_context.fragments[0];
- PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext*
- containing_block_context = &context.current;
- const PhysicalOffset offset = (*iterator)->Link().offset;
- containing_block_context->paint_offset += offset;
- const PhysicalOffset paint_offset =
- containing_block_context->paint_offset;
-
- // Create corresponding |FragmentData|. Hit-testing needs
- // |FragmentData.PaintOffset|.
- if (fragmentainer_fragment_data) {
- DCHECK(!box_fragment->IsFirstForNode());
+ // We'll walk all other non-fragmentainer children directly now, entering
+ // them from the fragment tree, rather than from the LayoutObject tree.
+ // One consequence of this is that paint effects on any ancestors between
+ // a column spanner and its multicol container will not be applied on the
+ // spanner. This is fixable, but it would require non-trivial amounts of
+ // special-code for such a special case. If anyone complains, we can
+ // revisit this decision.
+ if (box_fragment->IsColumnSpanAll())
+ context.current_fragmentainer = outer_fragmentainer;
+
+ NGPrePaintInfo pre_paint_info = CreatePrePaintInfo(child, context);
+ Walk(*box_fragment->GetLayoutObject(), context, &pre_paint_info);
+ continue;
+ }
+
+ // Check |box_fragment| and the |LayoutBox| that produced it are in sync.
+ // |OwnerLayoutBox()| has a few DCHECKs for this purpose.
+ DCHECK(box_fragment->OwnerLayoutBox());
+
+ // A fragmentainer doesn't paint anything itself. Just include its offset
+ // and descend into children.
+ DCHECK(box_fragment->IsFragmentainerBox());
+
+ // Always keep track of the current innermost fragmentainer we're handling,
+ // as they may serve as containing blocks for OOF descendants.
+ context.current_fragmentainer.fragment = box_fragment;
+
+ // Set up |inner_fragmentainer_idx| lazily, as it's O(n) (n == number of
+ // multicol container fragments).
+ if (!inner_fragmentainer_idx)
+ inner_fragmentainer_idx = PreviousInnerFragmentainerIndex(fragment);
+ context.current_fragmentainer.fragmentainer_idx = *inner_fragmentainer_idx;
+
+ if (UNLIKELY(!context.tree_builder_context)) {
+ WalkChildren(actual_parent, box_fragment, context);
+ continue;
+ }
+
+ PaintPropertyTreeBuilderContext& tree_builder_context =
+ *context.tree_builder_context;
+ PaintPropertyTreeBuilderFragmentContext& fragment_context =
+ tree_builder_context.fragments[0];
+ PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext*
+ containing_block_context = &fragment_context.current;
+ containing_block_context->paint_offset += child.offset;
+
+ const PhysicalOffset paint_offset = containing_block_context->paint_offset;
+ // Keep track of the paint offset at the fragmentainer, and also reset the
+ // offset adjustment tracker. This is needed when entering OOF
+ // descendants. OOFs have the nearest fragmentainer as their containing
+ // block, so when entering them during LayoutObject tree traversal, we have
+ // to compensate for this.
+ fragment_context.fragmentainer_paint_offset = paint_offset;
+ fragment_context.adjustment_for_oof_in_fragmentainer = PhysicalOffset();
+
+ // Create corresponding |FragmentData|. Hit-testing needs
+ // |FragmentData.PaintOffset|.
+ if (fragmentainer_fragment_data) {
+ DCHECK(!box_fragment->IsFirstForNode());
#if DCHECK_IS_ON()
- DCHECK_EQ(fragmentainer_owner_box, box_fragment->OwnerLayoutBox());
+ DCHECK_EQ(fragmentainer_owner_box, box_fragment->OwnerLayoutBox());
#endif
- fragmentainer_fragment_data =
- &fragmentainer_fragment_data->EnsureNextFragment();
- } else {
- const LayoutBox* owner_box = box_fragment->OwnerLayoutBox();
+ fragmentainer_fragment_data =
+ &fragmentainer_fragment_data->EnsureNextFragment();
+ } else {
+ const LayoutBox* owner_box = box_fragment->OwnerLayoutBox();
#if DCHECK_IS_ON()
- DCHECK(!fragmentainer_owner_box);
- fragmentainer_owner_box = owner_box;
+ DCHECK(!fragmentainer_owner_box);
+ fragmentainer_owner_box = owner_box;
#endif
+ fragmentainer_fragment_data =
+ &owner_box->GetMutableForPainting().FirstFragment();
+ if (box_fragment->IsFirstForNode()) {
+ fragmentainer_fragment_data->ClearNextFragment();
+ } else {
+ // |box_fragment| is nested in another fragmentainer, and that it is
+ // the first one in this loop, but not the first one for the
+ // |LayoutObject|. Append a new |FragmentData| to the last one.
fragmentainer_fragment_data =
- &owner_box->GetMutableForPainting().FirstFragment();
- if (box_fragment->IsFirstForNode()) {
- fragmentainer_fragment_data->ClearNextFragment();
- } else {
- // |box_fragment| is nested in another fragmentainer, and that it is
- // the first one in this loop, but not the first one for the
- // |LayoutObject|. Append a new |FragmentData| to the last one.
- fragmentainer_fragment_data =
- &fragmentainer_fragment_data->LastFragment().EnsureNextFragment();
- }
+ &fragmentainer_fragment_data->LastFragment().EnsureNextFragment();
}
- fragmentainer_fragment_data->SetPaintOffset(paint_offset);
-
- WalkChildren(/* parent */ nullptr, parent_context, iterator);
- containing_block_context->paint_offset -= offset;
- continue;
}
- Walk(*object, parent_context, iterator);
+ fragmentainer_fragment_data->SetPaintOffset(paint_offset);
+
+ WalkChildren(actual_parent, box_fragment, context);
+
+ containing_block_context->paint_offset -= child.offset;
+ (*inner_fragmentainer_idx)++;
}
- const LayoutBlockFlow* parent_block = DynamicTo<LayoutBlockFlow>(parent);
- if (!parent_block || !parent_block->MultiColumnFlowThread())
+ if (!flow_thread)
return;
// Multicol containers only contain special legacy children invisible to
// LayoutNG, so we need to clean them manually.
- for (const LayoutObject* child = parent->SlowFirstChild(); child;
+ if (fragment.BreakToken())
+ return; // Wait until we've reached the end.
+ for (const LayoutObject* child = object.SlowFirstChild(); child;
child = child->NextSibling()) {
DCHECK(child->IsLayoutFlowThread() || child->IsLayoutMultiColumnSet() ||
child->IsLayoutMultiColumnSpannerPlaceholder());
child->GetMutableForPainting().ClearPaintFlags();
}
-}
-void PrePaintTreeWalk::WalkLegacyChildren(const LayoutObject& object,
- PrePaintTreeWalkContext& context) {
- if (const auto* layout_box = DynamicTo<LayoutBox>(&object)) {
- if (layout_box->CanTraversePhysicalFragments()) {
- // Enter NG child fragment traversal. We'll stay in this mode for all
- // descendants that support fragment traversal. We'll re-enter
- // LayoutObject traversal for descendants that don't support it. This only
- // works correctly if we're not block-fragmented, though, so DCHECK for
- // that.
- DCHECK_EQ(layout_box->PhysicalFragmentCount(), 1u);
- const NGPhysicalBoxFragment& fragment =
- To<NGPhysicalBoxFragment>(*layout_box->GetPhysicalFragment(0));
- DCHECK(!fragment.BreakToken());
- NGFragmentChildIterator child_iterator(fragment);
- WalkNGChildren(&object, context, &child_iterator);
- return;
+ // If we missed any nested fixpos elements during fragment traversal, that
+ // means that their containing block lives outside the fragmentation context
+ // root. Walk these missed fixepos elements now.
+ if (!pending_fixedpos_missables_.IsEmpty()) {
+ for (const auto* fixedpos : pending_fixedpos_missables_) {
+ DCHECK(!walked_fixedpos_.Contains(fixedpos));
+ Walk(*fixedpos, context, /* pre_paint_info */ nullptr);
}
}
+}
- if (UNLIKELY(object.IsFieldsetIncludingNG())) {
- // Handle the rendered legend of the fieldset right away. It may not be a
- // direct child in the layout object tree (there may be an anonymous
- // fieldset content wrapper in-between, and even a flow thread), but it is
- // to be treated as such (similarly to out-of-flow positioned elements in a
- // way).
- if (const LayoutBox* legend =
- LayoutFieldset::FindInFlowLegend(To<LayoutBlock>(object)))
- Walk(*legend, context, /* iterator */ nullptr);
- }
+void PrePaintTreeWalk::WalkLayoutObjectChildren(
+ const LayoutObject& parent_object,
+ const NGPhysicalBoxFragment* parent_fragment,
+ PrePaintTreeWalkContext& context) {
+ absl::optional<NGInlineCursor> inline_cursor;
+ for (const LayoutObject* child = parent_object.SlowFirstChild(); child;
+ // Stay on the |child| while iterating fragments of |child|.
+ child = inline_cursor ? child : child->NextSibling()) {
+ if (!parent_fragment) {
+ // If we haven't found a fragment tree to accompany us in our walk,
+ // perform a pure LayoutObject tree walk. This is needed for legacy block
+ // fragmentation, and it also works fine if there's no block fragmentation
+ // involved at all (in such cases we can either to do this, or perform the
+ // NGPhysicalBoxFragment-accompanied walk that we do further down).
+
+ if (child->IsLayoutMultiColumnSpannerPlaceholder()) {
+ child->GetMutableForPainting().ClearPaintFlags();
+ continue;
+ }
- for (const LayoutObject* child = object.SlowFirstChild(); child;
- child = child->NextSibling()) {
- if (child->IsLayoutMultiColumnSpannerPlaceholder()) {
- child->GetMutableForPainting().ClearPaintFlags();
+ Walk(*child, context, /* pre_paint_info */ nullptr);
continue;
}
- // Skip out-of-flow positioned children lest they be walked twice. If |this|
- // is an NG object, but it still walks its children the legacy way (this may
- // happen to table-cells; see LayoutObject::CanTraversePhysicalFragments()),
- // we're either going to handle it in the code below after the loop - if
- // |this| is actually the containing block. Otherwise it will be handled by
- // some ancestor - either in the same code below (if it's a legacy-walking
- // object) or via regular child fragment traversal. If we walk it here as
- // well, we'd end up walking it twice. This is both bad for performance, and
- // also correctness, as fragment items are sensitive to how they're walked
- // (see SetupFragmentData()).
- if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled() &&
- child->IsOutOfFlowPositioned() && object.IsLayoutNGObject()))
- continue;
- // The rendered legend was handled above, before processing the children of
- // the fieldset. So skip it when found during normal child traversal.
- if (UNLIKELY(child->IsRenderedLegend()))
+ // If we're in the middle of walking a missed OOF, don't enter nested OOFs
+ // (but miss those as well, and handle them via fragment traversal).
+ if (context.is_inside_orphaned_object && child->IsOutOfFlowPositioned()) {
+ if (child->IsFixedPositioned() && !walked_fixedpos_.Contains(child))
+ pending_fixedpos_missables_.insert(child);
continue;
+ }
- Walk(*child, context, /* iterator */ nullptr);
- }
+ // Perform an NGPhysicalBoxFragment-accompanied walk of the child
+ // LayoutObject tree.
+ //
+ // We'll map each child LayoutObject to a corresponding
+ // NGPhysicalBoxFragment. For text and non-atomic inlines this will be the
+ // fragment of their containing block, while for all other objects, it will
+ // be a fragment generated by the object itself. Even when we have LayoutNG
+ // fragments, we'll try to do the pre-paint walk it in LayoutObject tree
+ // order. This will ensure that paint properties are applied correctly (the
+ // LayoutNG fragment tree follows the containing block structure closely,
+ // but for paint effects, it's actually the LayoutObject / DOM tree
+ // structure that matters, e.g. when there's a relpos with a child with
+ // opacity, which has an absolutely positioned child, the absolutely
+ // positioned child should be affected by opacity, even if the object that
+ // establishes the opacity layer isn't in the containing block
+ // chain). Furthermore, culled inlines have no fragments, but they still
+ // need to be visited, since the invalidation code marks them for pre-paint.
+ const NGPhysicalBoxFragment* box_fragment = nullptr;
+ wtf_size_t fragmentainer_idx =
+ context.current_fragmentainer.fragmentainer_idx;
+ PhysicalOffset paint_offset;
+ const auto* child_box = DynamicTo<LayoutBox>(child);
+ bool is_first_for_node = true;
+ bool is_last_for_node = true;
+ bool is_inside_fragment_child = false;
+
+ if (!inline_cursor && parent_fragment->HasItems() &&
+ child->HasInlineFragments()) {
+ // Limit the search to descendants of |parent_fragment|.
+ inline_cursor.emplace(*parent_fragment);
+ inline_cursor->MoveTo(*child);
+ // Searching fragments of |child| may not find any because they may be in
+ // other fragmentainers than |parent_fragment|.
+ }
+ if (inline_cursor) {
+ for (; inline_cursor->Current();
+ inline_cursor->MoveToNextForSameLayoutObject()) {
+ // Check if the search is limited to descendants of |parent_fragment|.
+ DCHECK_EQ(&inline_cursor->ContainerFragment(), parent_fragment);
+ const NGFragmentItem& item = *inline_cursor->Current().Item();
+ DCHECK_EQ(item.GetLayoutObject(), child);
+
+ is_last_for_node = item.IsLastForNode();
+ if (box_fragment) {
+ if (is_last_for_node)
+ break;
+ continue;
+ }
- if (!RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled())
- return;
+ paint_offset = item.OffsetInContainerFragment();
+ is_first_for_node = item.IsFirstForNode();
- const LayoutBlock* block = DynamicTo<LayoutBlock>(&object);
- if (!block)
- return;
- const auto* positioned_objects = block->PositionedObjects();
- if (!positioned_objects)
- return;
+ if (item.BoxFragment() && !item.BoxFragment()->IsInlineBox()) {
+ box_fragment = item.BoxFragment();
+ is_last_for_node = !box_fragment->BreakToken();
+ break;
+ } else {
+ // Inlines will pass their containing block fragment (and its incoming
+ // break token).
+ box_fragment = parent_fragment;
+ is_inside_fragment_child = true;
+ }
- // If we have performed NG fragment traversal in any part of the subtree, we
- // may have missed certain out-of-flow positioned objects. LayoutNG fragments
- // are always children of their containing block, while the structure of the
- // LayoutObject tree corresponds more closely to that of the DOM tree.
- //
- // Example: if we assume that flexbox isn't natively supported in LayoutNG:
- //
- // <div id="flex" style="display:flex; position:relative;">
- // <div id="flexitem">
- // <div id="abs" style="position:absolute;"></div>
- // <div id="regular"></div>
- //
- // If we let |object| be #flex, it will be handled by legacy LayoutObject
- // traversal, while #flexitem, on the other hand, can traverse its NG child
- // fragments. However, #regular will be the only child fragment of #flexitem,
- // since the containing block for #abs is #flex. So we'd miss it, unless we
- // walk it now.
- for (const LayoutBox* box : *positioned_objects) {
- // It's important that objects that have already been walked be left alone.
- // Otherwise, we might calculate the wrong offsets (and overwrite the
- // correct ones) in case of out-of-flow positioned objects whose containing
- // block is a relatively positioned non-atomic inline (such objects will
- // already have been properly walked, since we don't switch engines within
- // an inline formatting context). Put differently, the code here will only
- // do the right thing if |object| is truly the containing block of the
- // positioned objects in its list (which isn't the case if the containing
- // block is a non-atomic inline).
- if (!ObjectRequiresPrePaint(*box) &&
- !ObjectRequiresTreeBuilderContext(*box))
- continue;
- DCHECK_EQ(box->Container(), &object);
- Walk(*box, context, /* iterator */ nullptr);
+ if (is_last_for_node)
+ break;
+
+ // Keep looking for the end. We need to know whether this is the last
+ // time we're going to visit this object.
+ }
+ if (is_last_for_node || !inline_cursor->Current()) {
+ // If all fragments are done, move to the next sibling of |child|.
+ inline_cursor.reset();
+ } else {
+ inline_cursor->MoveToNextForSameLayoutObject();
+ }
+ if (!box_fragment)
+ continue;
+ } else if (child->IsInline() && !child_box) {
+ // Deal with inline-level objects not searched for above.
+ //
+ // Needed for fragment-less objects that have children. This is the case
+ // for culled inlines. We're going to have to enter them for every
+ // fragment in the parent.
+ //
+ // The child is inline-level even if the parent fragment doesn't establish
+ // an inline formatting context. This may happen if there's only collapsed
+ // text, or if we had to insert a break in a block before we got to any
+ // inline content. Make sure that we visit such objects once.
+
+ // Inlines will pass their containing block fragment (and its incoming
+ // break token).
+ box_fragment = parent_fragment;
+ is_inside_fragment_child = true;
+
+ is_first_for_node = parent_fragment->IsFirstForNode();
+ is_last_for_node = !parent_fragment->BreakToken();
+ } else if (child_box && child_box->PhysicalFragmentCount()) {
+ // Figure out which fragment the child may be found inside. The fragment
+ // tree follows the structure of containing blocks closely, while here
+ // we're walking the LayoutObject tree (which follows the structure of the
+ // flat DOM tree, more or less). This means that for out-of-flow
+ // positioned objects, the fragment of the parent LayoutObject might not
+ // be the right place to search.
+ const NGPhysicalBoxFragment* search_fragment = parent_fragment;
+ if (child_box->IsOutOfFlowPositioned()) {
+ if (child_box->IsFixedPositioned()) {
+ search_fragment = context.fixed_positioned_container.fragment;
+ fragmentainer_idx =
+ context.fixed_positioned_container.fragmentainer_idx;
+ } else {
+ search_fragment = context.absolute_positioned_container.fragment;
+ fragmentainer_idx =
+ context.absolute_positioned_container.fragmentainer_idx;
+ }
+ if (!search_fragment) {
+ // Only walk unfragmented legacy-contained OOFs once.
+ if (!parent_fragment->IsFirstForNode())
+ continue;
+ }
+ }
+
+ if (search_fragment) {
+ // See if we can find a fragment for the child.
+ for (NGLink link : search_fragment->Children()) {
+ if (link->GetLayoutObject() != child)
+ continue;
+ // We found it!
+ box_fragment = To<NGPhysicalBoxFragment>(link.get());
+ paint_offset = link.offset;
+ is_first_for_node = box_fragment->IsFirstForNode();
+ is_last_for_node = !box_fragment->BreakToken();
+ break;
+ }
+ // If we didn't find a fragment for the child, it means that the child
+ // doesn't occur inside the fragmentainer that we're currently handling.
+ if (!box_fragment)
+ continue;
+ }
+ }
+
+ if (box_fragment) {
+ NGPrePaintInfo pre_paint_info(
+ *box_fragment, paint_offset, fragmentainer_idx, is_first_for_node,
+ is_last_for_node, context.is_inside_orphaned_object,
+ is_inside_fragment_child);
+ Walk(*child, context, &pre_paint_info);
+ } else {
+ Walk(*child, context, /* pre_paint_info */ nullptr);
+ }
}
}
-void PrePaintTreeWalk::WalkChildren(const LayoutObject* object,
+void PrePaintTreeWalk::WalkChildren(const LayoutObject& object,
+ const NGPhysicalBoxFragment* fragment,
PrePaintTreeWalkContext& context,
- const NGFragmentChildIterator* iterator) {
- DCHECK(iterator || object);
+ bool is_inside_fragment_child) {
+ const LayoutBox* box = DynamicTo<LayoutBox>(&object);
+ if (box) {
+ if (fragment) {
+ if (!box->IsLayoutFlowThread() && (!box->CanTraversePhysicalFragments() ||
+ !box->PhysicalFragmentCount())) {
+ // Leave LayoutNGBoxFragment-accompanied child LayoutObject traversal,
+ // since this object doesn't support that (or has no fragments (happens
+ // for table columns)). We need to switch back to legacy LayoutObject
+ // traversal for its children. We're then also assuming that we're
+ // either not block-fragmenting, or that this is monolithic content. We
+ // may re-enter LayoutNGBoxFragment-accompanied traversal if we get to a
+ // descendant that supports that.
+ DCHECK(
+ !box->FlowThreadContainingBlock() ||
+ (box->GetNGPaginationBreakability() == LayoutBox::kForbidBreaks));
+
+ fragment = nullptr;
+ context.oof_container_candidate_fragment = nullptr;
+ }
+ } else if (box->PhysicalFragmentCount()) {
+ // Enter LayoutNGBoxFragment-accompanied child LayoutObject traversal if
+ // we're at an NG fragmentation context root. While we in theory *could*
+ // enter this mode for any object that has a traversable fragment, without
+ // affecting correctness, we're better off with plain LayoutObject
+ // traversal when possible, as fragment-accompanied traversal has O(n^2)
+ // performance complexity (where n is the number of siblings).
+ //
+ // We'll stay in this mode for all descendants that support fragment
+ // traversal. We'll re-enter legacy traversal for descendants that don't
+ // support it. This only works correctly as long as there's no block
+ // fragmentation in the ancestry, though, so DCHECK for that.
+ DCHECK_EQ(box->PhysicalFragmentCount(), 1u);
+ const auto* first_fragment =
+ To<NGPhysicalBoxFragment>(box->GetPhysicalFragment(0));
+ DCHECK(!first_fragment->BreakToken());
+ if (first_fragment->IsFragmentationContextRoot() &&
+ box->CanTraversePhysicalFragments())
+ fragment = first_fragment;
+ }
- if (!iterator) {
- // We're not doing LayoutNG fragment traversal of this object.
- WalkLegacyChildren(*object, context);
- return;
+ // Inline-contained OOFs are placed in the containing block of the
+ // containing inline in NG, not an anonymous block that's part of a
+ // continuation, if any. We need to know where these might be stored, so
+ // that we eventually search the right ancestor fragment for them.
+ if (fragment && !box->IsAnonymousBlock())
+ context.oof_container_candidate_fragment = fragment;
}
- // If we are performing LayoutNG fragment traversal, but this object doesn't
- // support that, we need to switch back to legacy LayoutObject traversal for
- // its children. We're then also assuming that we're either not
- // block-fragmenting, or that this is monolithic content. We may re-enter
- // LayoutNG fragment traversal if we get to a descendant that supports that.
- if (object && !object->CanTraversePhysicalFragments()) {
- DCHECK(!object->FlowThreadContainingBlock() ||
- (object->IsBox() &&
- To<LayoutBox>(object)->GetNGPaginationBreakability() ==
- LayoutBox::kForbidBreaks));
- WalkLegacyChildren(*object, context);
- return;
+ // Keep track of fragments that act as containers for OOFs, so that we can
+ // search their children when looking for an OOF further down in the tree.
+ if (object.CanContainAbsolutePositionObjects()) {
+ if (context.current_fragmentainer.fragment && box &&
+ box->GetNGPaginationBreakability() == LayoutBox::kForbidBreaks) {
+ // If we're in a fragmentation context, the parent fragment of OOFs is the
+ // fragmentainer, unless the object is monolithic, in which case nothing
+ // inside the object participates in the current block fragmentation
+ // context. This means that this object (and not the nearest
+ // fragmentainer) acts as a containing block for OOF descendants,
+ context.current_fragmentainer = {};
+ }
+ // The OOF containing block structure is special under block fragmentation:
+ // A fragmentable OOF is always a direct child of a fragmentainer.
+ const auto* container_fragment = context.current_fragmentainer.fragment;
+ if (!container_fragment)
+ container_fragment = context.oof_container_candidate_fragment;
+ context.absolute_positioned_container = {
+ container_fragment, context.current_fragmentainer.fragmentainer_idx};
+ if (object.CanContainFixedPositionObjects()) {
+ context.fixed_positioned_container = {
+ container_fragment, context.current_fragmentainer.fragmentainer_idx};
+ }
}
- // Traverse child NG fragments.
- NGFragmentChildIterator child_iterator(iterator->Descend());
- WalkNGChildren(object, context, &child_iterator);
+ if (fragment) {
+ bool has_missable_children = false;
+ // If we are at a block fragment, collect any missable children.
+ DCHECK(!is_inside_fragment_child || !object.IsBox());
+ if (!is_inside_fragment_child)
+ has_missable_children = CollectMissableChildren(context, *fragment);
+
+ // We'll always walk the LayoutObject tree when possible, but if this is a
+ // fragmentation context root (such as a multicol container), we need to
+ // enter each fragmentainer child and then walk all the LayoutObject
+ // children.
+ if (fragment->IsFragmentationContextRoot())
+ WalkFragmentationContextRootChildren(object, *fragment, context);
+ else
+ WalkLayoutObjectChildren(object, fragment, context);
+
+ if (has_missable_children)
+ WalkMissedChildren(*fragment, context);
+ } else {
+ WalkLayoutObjectChildren(object, fragment, context);
+ }
}
void PrePaintTreeWalk::Walk(const LayoutObject& object,
const PrePaintTreeWalkContext& parent_context,
- const NGFragmentChildIterator* iterator) {
+ NGPrePaintInfo* pre_paint_info) {
const NGPhysicalBoxFragment* physical_fragment = nullptr;
- bool is_last_fragment = true;
- if (iterator) {
- physical_fragment = (*iterator)->BoxFragment();
- if (const auto* fragment_item = (*iterator)->FragmentItem())
- is_last_fragment = fragment_item->IsLastForNode();
- else if (physical_fragment)
- is_last_fragment = !physical_fragment->BreakToken();
+ bool is_inside_fragment_child = false;
+ if (pre_paint_info) {
+ physical_fragment = &pre_paint_info->box_fragment;
+ if (physical_fragment && (physical_fragment->IsOutOfFlowPositioned() ||
+ physical_fragment->IsFloating())) {
+ pending_missables_.erase(physical_fragment);
+ if (object.IsFixedPositioned()) {
+ pending_fixedpos_missables_.erase(&object);
+ walked_fixedpos_.insert(&object);
+ }
+ }
+ is_inside_fragment_child = pre_paint_info->is_inside_fragment_child;
}
bool needs_tree_builder_context_update =
- ContextRequiresChildTreeBuilderContext(parent_context) ||
- ObjectRequiresTreeBuilderContext(object);
+ NeedsTreeBuilderContextUpdate(object, parent_context);
#if DCHECK_IS_ON()
CheckTreeBuilderContextState(object, parent_context);
@@ -951,7 +1211,7 @@ void PrePaintTreeWalk::Walk(const LayoutObject& object,
context.tree_builder_context->clip_changed = false;
}
- WalkInternal(object, context, iterator);
+ WalkInternal(object, context, pre_paint_info);
bool child_walk_blocked = object.ChildPrePaintBlockedByDisplayLock();
// If we need a subtree walk due to context flags, we need to store that
@@ -971,7 +1231,7 @@ void PrePaintTreeWalk::Walk(const LayoutObject& object,
}
if (!child_walk_blocked) {
- WalkChildren(&object, context, iterator);
+ WalkChildren(object, physical_fragment, context, is_inside_fragment_child);
if (const auto* layout_embedded_content =
DynamicTo<LayoutEmbeddedContent>(object)) {
@@ -1000,7 +1260,7 @@ void PrePaintTreeWalk::Walk(const LayoutObject& object,
}
}
}
- if (is_last_fragment)
+ if (!pre_paint_info || pre_paint_info->is_last_for_node)
object.GetMutableForPainting().ClearPaintFlags();
}
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 42ae9c2d19d..7971ae5340a 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
@@ -6,15 +6,19 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PRE_PAINT_TREE_WALK_H_
#include "base/dcheck_is_on.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_property_tree_builder.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
class LayoutObject;
class LocalFrameView;
-class NGFragmentChildIterator;
+struct NGLink;
+class NGPhysicalBoxFragment;
+class NGPhysicalFragment;
// This class walks the whole layout tree, beginning from the root
// LocalFrameView, across frame boundaries. Helper classes are called for each
@@ -30,56 +34,24 @@ class CORE_EXPORT PrePaintTreeWalk final {
static bool ObjectRequiresPrePaint(const LayoutObject&);
static bool ObjectRequiresTreeBuilderContext(const LayoutObject&);
- struct PrePaintTreeWalkContext {
- STACK_ALLOCATED();
+ struct ContainingFragment {
+ const NGPhysicalBoxFragment* fragment = nullptr;
+ wtf_size_t fragmentainer_idx = WTF::kNotFound;
+ };
- public:
- PrePaintTreeWalkContext() {
- tree_builder_context.emplace();
- }
- PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parent_context,
- bool needs_tree_builder_context)
- : paint_invalidator_context(parent_context.paint_invalidator_context),
- ancestor_scroll_container_paint_layer(
- parent_context.ancestor_scroll_container_paint_layer),
- inside_blocking_touch_event_handler(
- parent_context.inside_blocking_touch_event_handler),
- effective_allowed_touch_action_changed(
- parent_context.effective_allowed_touch_action_changed),
- inside_blocking_wheel_event_handler(
- parent_context.inside_blocking_wheel_event_handler),
- blocking_wheel_event_handler_changed(
- parent_context.blocking_wheel_event_handler_changed),
- clip_changed(parent_context.clip_changed),
- paint_invalidation_container(
- parent_context.paint_invalidation_container),
- paint_invalidation_container_for_stacked_contents(
- parent_context
- .paint_invalidation_container_for_stacked_contents) {
- if (needs_tree_builder_context || DCHECK_IS_ON()) {
- DCHECK(parent_context.tree_builder_context);
- tree_builder_context.emplace(*parent_context.tree_builder_context);
- }
-#if DCHECK_IS_ON()
- if (needs_tree_builder_context)
- DCHECK(parent_context.tree_builder_context->is_actually_needed);
- tree_builder_context->is_actually_needed = needs_tree_builder_context;
-#endif
- }
+ // This provides a default base copy constructor for PrePaintTreeWalkContext.
+ // It contains all fields except for tree_builder_context which needs special
+ // treatment in the copy constructor.
+ struct PrePaintTreeWalkContextBase {
+ STACK_ALLOCATED();
- absl::optional<PaintPropertyTreeBuilderContext> tree_builder_context;
+ protected:
+ PrePaintTreeWalkContextBase() = default;
+ PrePaintTreeWalkContextBase(const PrePaintTreeWalkContextBase&) = default;
+ public:
PaintInvalidatorContext paint_invalidator_context;
- bool NeedsTreeBuilderContext() const {
-#if DCHECK_IS_ON()
- DCHECK(tree_builder_context);
- return tree_builder_context->is_actually_needed;
-#else
- return tree_builder_context.has_value();
-#endif
- }
-
// The ancestor in the PaintLayer tree which is a scroll container. Note
// that it is tree ancestor, not containing block or stacking ancestor.
PaintLayer* ancestor_scroll_container_paint_layer = nullptr;
@@ -104,9 +76,60 @@ class CORE_EXPORT PrePaintTreeWalk final {
// enabled.
bool clip_changed = false;
+ // True if we're fragment-traversing an object whose fragment wasn't found
+ // and walked when walking the layout object tree. This may happen for
+ // out-of-flow positioned and floated fragments inside block fragmentation,
+ // when an ancestor object doesn't have a fragment representation in a
+ // fragmentainer even if the OOF / float is there.
+ bool is_inside_orphaned_object = false;
+
const LayoutBoxModelObject* paint_invalidation_container = nullptr;
const LayoutBoxModelObject*
paint_invalidation_container_for_stacked_contents = nullptr;
+
+ ContainingFragment current_fragmentainer;
+ ContainingFragment absolute_positioned_container;
+ ContainingFragment fixed_positioned_container;
+
+ // When walking down the tree and discovering containers for OOFs, not every
+ // such container has the fragment actually containing OOF descendants; they
+ // may instead be inside a fragment generated by a parent (this happens for
+ // inline continuations, for instance). So keep track of the innermost valid
+ // container fragment for OOFs, and set
+ // absolute_positioned_container_fragment and
+ // fixed_positioned_container_fragment to this one as appropriate.
+ const NGPhysicalBoxFragment* oof_container_candidate_fragment = nullptr;
+ };
+
+ struct PrePaintTreeWalkContext : public PrePaintTreeWalkContextBase {
+ PrePaintTreeWalkContext() { tree_builder_context.emplace(); }
+ PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parent_context,
+ bool needs_tree_builder_context)
+ : PrePaintTreeWalkContextBase(parent_context) {
+ if (needs_tree_builder_context || DCHECK_IS_ON()) {
+ DCHECK(parent_context.tree_builder_context);
+ tree_builder_context.emplace(*parent_context.tree_builder_context);
+ }
+#if DCHECK_IS_ON()
+ if (needs_tree_builder_context)
+ DCHECK(parent_context.tree_builder_context->is_actually_needed);
+ tree_builder_context->is_actually_needed = needs_tree_builder_context;
+#endif
+ }
+
+ PrePaintTreeWalkContext(const PrePaintTreeWalkContext&) = delete;
+ PrePaintTreeWalkContext& operator=(const PrePaintTreeWalkContext&) = delete;
+
+ bool NeedsTreeBuilderContext() const {
+#if DCHECK_IS_ON()
+ DCHECK(tree_builder_context);
+ return tree_builder_context->is_actually_needed;
+#else
+ return tree_builder_context.has_value();
+#endif
+ }
+
+ absl::optional<PaintPropertyTreeBuilderContext> tree_builder_context;
};
static bool ContextRequiresChildPrePaint(const PrePaintTreeWalkContext&);
@@ -118,6 +141,19 @@ class CORE_EXPORT PrePaintTreeWalk final {
const PrePaintTreeWalkContext&);
#endif
+ // Upon entering a child LayoutObject, create an NGPrePaintInfo, and populate
+ // everything except its FragmentData. We need to get a bit further inside the
+ // child (WalkInternal()) before we can set up FragmentData (if we get there
+ // at all).
+ NGPrePaintInfo CreatePrePaintInfo(const NGLink& child,
+ const PrePaintTreeWalkContext& context);
+
+ // Locate and/or set up a FragmentData object for the current object /
+ // physical fragment.
+ FragmentData* GetOrCreateFragmentData(const LayoutObject&,
+ const PrePaintTreeWalkContext&,
+ const NGPrePaintInfo&);
+
void Walk(LocalFrameView&, const PrePaintTreeWalkContext& parent_context);
// This is to minimize stack frame usage during recursion. Modern compilers
@@ -127,20 +163,44 @@ class CORE_EXPORT PrePaintTreeWalk final {
// See https://crbug.com/781301 .
NOINLINE void WalkInternal(const LayoutObject&,
PrePaintTreeWalkContext&,
- const NGFragmentChildIterator*);
- void WalkNGChildren(const LayoutObject* parent,
- PrePaintTreeWalkContext& parent_context,
- NGFragmentChildIterator*);
- void WalkLegacyChildren(const LayoutObject&, PrePaintTreeWalkContext&);
- void WalkChildren(const LayoutObject*,
+ NGPrePaintInfo*);
+
+ // Add any "missable" children to a list. Missable children are children that
+ // we might not find during LayoutObject traversal. This happens when an
+ // ancestor LayoutObject (of the missable child) has no fragment inside a
+ // given fragmentainer, e.g. when there's an OOF fragment, but its containing
+ // block has no fragment inside that fragmentainer. Later, during the child
+ // walk, when a missable child is actually walked, it's removed from the
+ // list.
+ //
+ // Returns true if there are any missable children inside the fragment, false
+ // otherwise.
+ bool CollectMissableChildren(PrePaintTreeWalkContext&,
+ const NGPhysicalBoxFragment&);
+
+ // Walk any missed children (i.e. those collected by CollectMissableChildren()
+ // and not walked by Walk()) after child object traversal.
+ void WalkMissedChildren(const NGPhysicalBoxFragment&,
+ PrePaintTreeWalkContext&);
+
+ void WalkFragmentationContextRootChildren(const LayoutObject&,
+ const NGPhysicalBoxFragment&,
+ PrePaintTreeWalkContext&);
+ void WalkLayoutObjectChildren(const LayoutObject&,
+ const NGPhysicalBoxFragment*,
+ PrePaintTreeWalkContext&);
+ void WalkChildren(const LayoutObject&,
+ const NGPhysicalBoxFragment*,
PrePaintTreeWalkContext&,
- const NGFragmentChildIterator*);
+ bool is_inside_fragment_child = false);
void Walk(const LayoutObject&,
const PrePaintTreeWalkContext& parent_context,
- const NGFragmentChildIterator*);
+ NGPrePaintInfo*);
bool NeedsTreeBuilderContextUpdate(const LocalFrameView&,
const PrePaintTreeWalkContext&);
+ bool NeedsTreeBuilderContextUpdate(const LayoutObject&,
+ const PrePaintTreeWalkContext&);
void UpdateAuxiliaryObjectProperties(const LayoutObject&,
PrePaintTreeWalkContext&);
// Updates |LayoutObject::InsideBlockingTouchEventHandler|. Also ensures
@@ -163,6 +223,21 @@ class CORE_EXPORT PrePaintTreeWalk final {
PaintInvalidator paint_invalidator_;
+ // List of fragments that may be missed during LayoutObject walking. See
+ // CollectMissableChildren() and WalkMissedChildren().
+ HashSet<const NGPhysicalFragment*> pending_missables_;
+
+ // List of fixedpos objects that may be missed during fragment traversal. This
+ // can happen if a fixedpos is nested in another OOF inside a multicol, and
+ // the OOF parent is a pending missable (see |pending_missables_|). If that
+ // fixedpos' containing block is located outside of the multicol, we can would
+ // miss it during normal fragment traversal.
+ HashSet<const LayoutObject*> pending_fixedpos_missables_;
+
+ // List of fixedpos objects that have already been walked. This helps to avoid
+ // re-walking any fixedpos objects handled by |pending_fixedpos_missables_|.
+ HashSet<const LayoutObject*> walked_fixedpos_;
+
// TODO(https://crbug.com/841364): Remove is_wheel_event_regions_enabled
// argument once kWheelEventRegions feature flag is removed.
bool is_wheel_event_regions_enabled_ = false;
diff --git a/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.cc b/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.cc
index 32d127242e4..db66edbb0ef 100644
--- a/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.cc
@@ -112,39 +112,46 @@ FloatRoundedRect RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
int bottom_width =
sides_to_include.bottom ? style.BorderBottomWidth().Floor() : 0;
- return PixelSnappedRoundedInnerBorder(
+ return PixelSnappedRoundedBorderWithOutsets(
style, border_rect,
LayoutRectOutsets(-top_width, -right_width, -bottom_width, -left_width),
sides_to_include);
}
-FloatRoundedRect RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
+FloatRoundedRect RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets(
const ComputedStyle& style,
const PhysicalRect& border_rect,
- const LayoutRectOutsets& insets,
+ const LayoutRectOutsets& outsets,
PhysicalBoxSides sides_to_include) {
- PhysicalRect inner_rect = border_rect;
- inner_rect.Expand(insets);
- inner_rect.size.ClampNegativeToZero();
+ PhysicalRect rect_with_outsets = border_rect;
+ rect_with_outsets.Expand(outsets);
+ rect_with_outsets.size.ClampNegativeToZero();
// The standard LayoutRect::PixelSnappedIntRect() method will not
// let small sizes snap to zero, but that has the side effect here of
// preventing an inner border for a very thin element from snapping to
// zero size as occurs when a unit width border is applied to a sub-pixel
// sized element. So round without forcing non-near-zero sizes to one.
- FloatRoundedRect rounded_rect(IntRect(
- RoundedIntPoint(inner_rect.offset),
- IntSize(
- SnapSizeToPixelAllowingZero(inner_rect.Width(), inner_rect.X()),
- SnapSizeToPixelAllowingZero(inner_rect.Height(), inner_rect.Y()))));
+ FloatRoundedRect rounded_rect(
+ IntRect(RoundedIntPoint(rect_with_outsets.offset),
+ IntSize(SnapSizeToPixelAllowingZero(rect_with_outsets.Width(),
+ rect_with_outsets.X()),
+ SnapSizeToPixelAllowingZero(rect_with_outsets.Height(),
+ rect_with_outsets.Y()))));
if (style.HasBorderRadius()) {
FloatRoundedRect::Radii radii =
PixelSnappedRoundedBorder(style, border_rect, sides_to_include)
.GetRadii();
- // Insets use negative values.
- radii.Shrink(-insets.Top().ToFloat(), -insets.Bottom().ToFloat(),
- -insets.Left().ToFloat(), -insets.Right().ToFloat());
+ if (outsets.Top() <= 0 && outsets.Bottom() <= 0 && outsets.Left() <= 0 &&
+ outsets.Right() <= 0) {
+ radii.Shrink(-outsets.Top().ToFloat(), -outsets.Bottom().ToFloat(),
+ -outsets.Left().ToFloat(), -outsets.Right().ToFloat());
+ } else {
+ // radii.Expand() will DCHECK if all values are >= 0.
+ radii.Expand(outsets.Top().ToFloat(), outsets.Bottom().ToFloat(),
+ outsets.Left().ToFloat(), outsets.Right().ToFloat());
+ }
ExcludeSides(sides_to_include, &radii);
rounded_rect.SetRadii(radii);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.h b/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.h
index 4881daeb366..5e9c4dfed5e 100644
--- a/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.h
+++ b/chromium/third_party/blink/renderer/core/paint/rounded_border_geometry.h
@@ -36,10 +36,12 @@ class CORE_EXPORT RoundedBorderGeometry {
const PhysicalRect& border_rect,
PhysicalBoxSides edges_to_include = PhysicalBoxSides());
- static FloatRoundedRect PixelSnappedRoundedInnerBorder(
+ // Values in |outsets| must be either all >= 0 to expand from |border_rect|,
+ // or all <= 0 to shrink from |border_rect|.
+ static FloatRoundedRect PixelSnappedRoundedBorderWithOutsets(
const ComputedStyle&,
const PhysicalRect& border_rect,
- const LayoutRectOutsets& insets,
+ const LayoutRectOutsets& outsets_from_border,
PhysicalBoxSides edges_to_include = PhysicalBoxSides());
};
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc
index 3e302b138f0..db29fae1c85 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc
@@ -55,25 +55,25 @@ void ScopedBoxContentsPaintState::AdjustForBoxContents(const LayoutBox& box) {
fragment_to_paint_->ContentsProperties(), box,
input_paint_info_.DisplayItemTypeForClipping());
- // Then adjust paint offset and cull rect for scroll translation.
const auto* properties = fragment_to_paint_->PaintProperties();
- if (!properties)
- return;
- const auto* scroll_translation = properties->ScrollTranslation();
- if (!scroll_translation)
- return;
+ const auto* scroll_translation =
+ properties ? properties->ScrollTranslation() : nullptr;
// See comments for ScrollTranslation in object_paint_properties.h
// for the reason of adding ScrollOrigin(). The paint offset will
// be used only for the scrolling contents that are not painted through
// descendant objects' Paint() method, e.g. inline boxes.
- paint_offset_ += PhysicalOffset(box.ScrollOrigin());
+ if (scroll_translation)
+ paint_offset_ += PhysicalOffset(box.ScrollOrigin());
if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) {
+ // We calculated cull rects for PaintLayers only.
+ if (!box.HasLayer())
+ return;
adjusted_paint_info_.emplace(input_paint_info_);
adjusted_paint_info_->SetCullRect(
fragment_to_paint_->GetContentsCullRect());
- if (box.HasLayer() && box.Layer()->PreviousPaintResult() == kFullyPainted) {
+ if (box.Layer()->PreviousPaintResult() == kFullyPainted) {
PhysicalRect contents_visual_rect =
box.PhysicalContentsVisualOverflowRect();
contents_visual_rect.Move(fragment_to_paint_->PaintOffset());
@@ -94,8 +94,10 @@ void ScopedBoxContentsPaintState::AdjustForBoxContents(const LayoutBox& box) {
if (IsA<LayoutView>(box) && input_paint_info_.GetCullRect().IsInfinite())
return;
- adjusted_paint_info_.emplace(input_paint_info_);
- adjusted_paint_info_->TransformCullRect(*scroll_translation);
+ if (scroll_translation) {
+ adjusted_paint_info_.emplace(input_paint_info_);
+ adjusted_paint_info_->TransformCullRect(*scroll_translation);
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h
index e2a0f807a38..8a1d5f85777 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_PAINT_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_PAINT_STATE_H_
+#include "third_party/abseil-cpp/absl/types/optional.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/paint/paint_info.h"
@@ -45,7 +46,9 @@ class ScopedPaintState {
return;
}
const auto* properties = fragment_to_paint_->PaintProperties();
- if (properties && properties->PaintOffsetTranslation()) {
+ if (!properties)
+ return;
+ if (properties->PaintOffsetTranslation()) {
AdjustForPaintOffsetTranslation(object,
*properties->PaintOffsetTranslation());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h
index 750aed68085..6cc9ccc4014 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h
@@ -26,6 +26,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_SVG_PAINT_STATE_H_
#include "base/dcheck_is_on.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/scoped_paint_chunk_properties.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 e6fc87badf9..089a702ffac 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -225,6 +226,20 @@ void ScrollableAreaPainter::PaintScrollbar(GraphicsContext& context,
if (!cull_rect.Intersects(visual_rect))
return;
+ const auto* properties =
+ GetScrollableArea().GetLayoutBox()->FirstFragment().PaintProperties();
+ DCHECK(properties);
+ auto type = scrollbar.Orientation() == kHorizontalScrollbar
+ ? DisplayItem::kScrollbarHorizontal
+ : DisplayItem::kScrollbarVertical;
+ absl::optional<ScopedPaintChunkProperties> chunk_properties;
+ if (const auto* effect = scrollbar.Orientation() == kHorizontalScrollbar
+ ? properties->HorizontalScrollbarEffect()
+ : properties->VerticalScrollbarEffect()) {
+ chunk_properties.emplace(context.GetPaintController(), *effect, scrollbar,
+ type);
+ }
+
if (scrollbar.IsCustomScrollbar()) {
scrollbar.Paint(context, paint_offset);
@@ -240,19 +255,12 @@ void ScrollableAreaPainter::PaintScrollbar(GraphicsContext& context,
return;
}
- auto type = scrollbar.Orientation() == kHorizontalScrollbar
- ? DisplayItem::kScrollbarHorizontal
- : DisplayItem::kScrollbarVertical;
if (context.GetPaintController().UseCachedItemIfPossible(scrollbar, type))
return;
const TransformPaintPropertyNode* scroll_translation = nullptr;
- if (scrollable_area_->ShouldDirectlyCompositeScrollbar(scrollbar)) {
- auto* properties =
- GetScrollableArea().GetLayoutBox()->FirstFragment().PaintProperties();
- DCHECK(properties);
+ if (scrollable_area_->ShouldDirectlyCompositeScrollbar(scrollbar))
scroll_translation = properties->ScrollTranslation();
- }
auto delegate = base::MakeRefCounted<ScrollbarLayerDelegate>(
scrollbar, context.DeviceScaleFactor());
ScrollbarDisplayItem::Record(context, scrollbar, type, delegate, visual_rect,
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter_test.cc
new file mode 100644
index 00000000000..c438826ab37
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter_test.cc
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
+
+using testing::_;
+using testing::ElementsAre;
+
+namespace blink {
+
+using ScrollableAreaPainterTest = PaintControllerPaintTest;
+
+INSTANTIATE_CAP_TEST_SUITE_P(ScrollableAreaPainterTest);
+
+TEST_P(ScrollableAreaPainterTest, OverlayScrollbars) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="target" style="overflow: scroll; width: 50px; height: 50px">
+ <div style="width: 200px; height: 200px"></div>
+ </div>
+ )HTML");
+
+ ASSERT_TRUE(
+ GetDocument().GetPage()->GetScrollbarTheme().UsesOverlayScrollbars());
+ const auto* target = To<LayoutBox>(GetLayoutObjectByElementId("target"));
+ const auto* properties =
+ GetLayoutObjectByElementId("target")->FirstFragment().PaintProperties();
+ ASSERT_TRUE(properties);
+ ASSERT_TRUE(properties->HorizontalScrollbarEffect());
+ ASSERT_TRUE(properties->VerticalScrollbarEffect());
+
+ PaintChunk::Id horizontal_id(
+ *target->GetScrollableArea()->HorizontalScrollbar(),
+ DisplayItem::kScrollbarHorizontal);
+ auto horizontal_state = target->FirstFragment().LocalBorderBoxProperties();
+ horizontal_state.SetEffect(*properties->HorizontalScrollbarEffect());
+
+ PaintChunk::Id vertical_id(*target->GetScrollableArea()->VerticalScrollbar(),
+ DisplayItem::kScrollbarVertical);
+ auto vertical_state = target->FirstFragment().LocalBorderBoxProperties();
+ vertical_state.SetEffect(*properties->VerticalScrollbarEffect());
+
+ EXPECT_THAT(ContentPaintChunks(),
+ ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, _, _, _,
+ IsPaintChunk(1, 2, horizontal_id, horizontal_state),
+ IsPaintChunk(2, 3, vertical_id, vertical_state)));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc b/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc
index 58c5409858b..f9266ca880b 100644
--- a/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc
@@ -3,12 +3,15 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/selection_bounds_recorder.h"
+
#include "third_party/blink/renderer/core/editing/frame_selection.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/layout/api/selection_state.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.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/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
namespace blink {
@@ -164,6 +167,16 @@ bool SelectionBoundsRecorder::ShouldRecordSelection(
if (!frame_selection.IsHandleVisible() || frame_selection.IsHidden())
return false;
+ // If the currently focused frame is not the one in which selection
+ // lives, don't paint the selection bounds. Note this is subtly different
+ // from whether the frame has focus (i.e. `FrameSelection::SelectionHasFocus`)
+ // which is false if the hosting window is not focused.
+ LocalFrame* local_frame = frame_selection.GetFrame();
+ LocalFrame* focused_frame =
+ local_frame->GetPage()->GetFocusController().FocusedFrame();
+ if (local_frame != focused_frame)
+ return false;
+
if (state == SelectionState::kInside || state == SelectionState::kNone)
return false;
@@ -189,7 +202,7 @@ bool SelectionBoundsRecorder::IsVisible(const LayoutObject& rect_layout_object,
return true;
const PhysicalOffset sample_point = GetSamplePointForVisibility(
- edge_start, edge_end, rect_layout_object.View()->ZoomFactor());
+ edge_start, edge_end, rect_layout_object.GetFrame()->PageZoomFactor());
auto* const text_control_object = To<LayoutBox>(layout_object);
const PhysicalOffset position_in_input =
diff --git a/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc b/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc
new file mode 100644
index 00000000000..2f14c05d1d6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc
@@ -0,0 +1,206 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/editing/testing/selection_sample.h"
+#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
+
+using testing::ElementsAre;
+
+namespace blink {
+
+class SelectionBoundsRecorderTest : public PaintControllerPaintTestBase,
+ public testing::WithParamInterface<bool>,
+ public ScopedLayoutNGForTest,
+ public ScopedCompositeAfterPaintForTest {
+ public:
+ SelectionBoundsRecorderTest()
+ : ScopedLayoutNGForTest(GetParam()),
+ ScopedCompositeAfterPaintForTest(true) {}
+};
+
+struct SelectionBoundsRecorderTestPassToString {
+ std::string operator()(const testing::TestParamInfo<bool> b) const {
+ return b.param ? "LayoutNG" : "LegacyLayout";
+ }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+ SelectionBoundsRecorderTest,
+ ::testing::Bool(),
+ SelectionBoundsRecorderTestPassToString());
+
+TEST_P(SelectionBoundsRecorderTest, SelectAll) {
+ SetBodyInnerHTML("<span>A<br>B<br>C</span>");
+
+ LocalFrame* local_frame = GetDocument().GetFrame();
+ local_frame->Selection().SetHandleVisibleForTesting();
+ local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame);
+ local_frame->Selection().SelectAll();
+ UpdateAllLifecyclePhasesForTest();
+
+ auto chunks = ContentPaintChunks();
+ EXPECT_EQ(chunks.size(), 1u);
+ EXPECT_TRUE(chunks.begin()->layer_selection_data->start.has_value());
+ EXPECT_TRUE(chunks.begin()->layer_selection_data->end.has_value());
+ PaintedSelectionBound start =
+ chunks.begin()->layer_selection_data->start.value();
+ EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
+ EXPECT_EQ(start.edge_start, IntPoint(8, 8));
+ EXPECT_EQ(start.edge_end, IntPoint(8, 9));
+
+ PaintedSelectionBound end = chunks.begin()->layer_selection_data->end.value();
+ EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
+ EXPECT_EQ(end.edge_start, IntPoint(9, 10));
+ EXPECT_EQ(end.edge_end, IntPoint(9, 11));
+}
+
+TEST_P(SelectionBoundsRecorderTest, SelectMultiline) {
+ LocalFrame* local_frame = GetDocument().GetFrame();
+ local_frame->Selection().SetSelectionAndEndTyping(
+ SelectionSample::SetSelectionText(
+ GetDocument().body(),
+ "<div style='white-space:pre'>f^oo\nbar\nb|az</div>"));
+ local_frame->Selection().SetHandleVisibleForTesting();
+ local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame);
+ UpdateAllLifecyclePhasesForTest();
+
+ auto chunks = ContentPaintChunks();
+ EXPECT_EQ(chunks.size(), 1u);
+ EXPECT_TRUE(chunks.begin()->layer_selection_data->start.has_value());
+ EXPECT_TRUE(chunks.begin()->layer_selection_data->end.has_value());
+ PaintedSelectionBound start =
+ chunks.begin()->layer_selection_data->start.value();
+ EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
+ EXPECT_EQ(start.edge_start, IntPoint(8, 8));
+ EXPECT_EQ(start.edge_end, IntPoint(8, 9));
+
+ PaintedSelectionBound end = chunks.begin()->layer_selection_data->end.value();
+ EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
+ EXPECT_EQ(end.edge_start, IntPoint(9, 10));
+ EXPECT_EQ(end.edge_end, IntPoint(9, 11));
+}
+
+TEST_P(SelectionBoundsRecorderTest, SelectMultilineEmptyStartEnd) {
+ LocalFrame* local_frame = GetDocument().GetFrame();
+ LoadAhem(*local_frame);
+ local_frame->Selection().SetSelectionAndEndTyping(
+ SelectionSample::SetSelectionText(GetDocument().body(),
+ R"HTML(
+ <style>
+ body { margin: 0; }
+ * { font: 10px/1 Ahem; }
+ </style>
+ <div>foo^<br>bar<br>|baz</div>
+ )HTML"));
+ local_frame->Selection().SetHandleVisibleForTesting();
+ local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame);
+ UpdateAllLifecyclePhasesForTest();
+
+ auto chunks = ContentPaintChunks();
+ EXPECT_EQ(chunks.size(), 1u);
+ EXPECT_TRUE(chunks.begin()->layer_selection_data->start.has_value());
+ EXPECT_TRUE(chunks.begin()->layer_selection_data->end.has_value());
+ PaintedSelectionBound start =
+ chunks.begin()->layer_selection_data->start.value();
+ EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
+ EXPECT_EQ(start.edge_start, IntPoint(30, 0));
+ EXPECT_EQ(start.edge_end, IntPoint(30, 10));
+
+ PaintedSelectionBound end = chunks.begin()->layer_selection_data->end.value();
+ EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
+ EXPECT_EQ(end.edge_start, IntPoint(0, 20));
+ EXPECT_EQ(end.edge_end, IntPoint(0, 30));
+}
+
+TEST_P(SelectionBoundsRecorderTest, InvalidationForEmptyBounds) {
+ LocalFrame* local_frame = GetDocument().GetFrame();
+ LoadAhem(*local_frame);
+
+ // Set a selection that has empty start and end in separate paint chunks.
+ // We'll move these empty endpoints into the middle div and make sure
+ // everything is invalidated/re-painted/recorded correctly.
+ local_frame->Selection().SetSelectionAndEndTyping(
+ SelectionSample::SetSelectionText(GetDocument().body(),
+ R"HTML(
+ <style>
+ body { margin: 0; }
+ div { will-change: transform; }
+ * { font: 10px/1 Ahem; }
+ </style>
+ <div>foo^</div><div id=target>bar</div><div>|baz</div>
+ )HTML"));
+ local_frame->Selection().SetHandleVisibleForTesting();
+ local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame);
+ UpdateAllLifecyclePhasesForTest();
+
+ auto chunks = ContentPaintChunks();
+ EXPECT_EQ(chunks.size(), 4u);
+
+ PaintChunkSubset::Iterator chunk_iterator = chunks.begin();
+ // Skip the root chunk to get to the first div.
+ ++chunk_iterator;
+ EXPECT_TRUE(chunk_iterator->layer_selection_data->start.has_value());
+ PaintedSelectionBound start =
+ chunk_iterator->layer_selection_data->start.value();
+ EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
+ EXPECT_EQ(start.edge_start, IntPoint(30, 0));
+ EXPECT_EQ(start.edge_end, IntPoint(30, 10));
+
+ // Skip the middle div as well to get to the third div where the end of the
+ // selection is.
+ ++chunk_iterator;
+ ++chunk_iterator;
+
+ EXPECT_TRUE(chunk_iterator->layer_selection_data->end.has_value());
+ PaintedSelectionBound end = chunk_iterator->layer_selection_data->end.value();
+ EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
+ // Coordinates are chunk-relative, so they should start at 0 y coordinate.
+ EXPECT_EQ(end.edge_start, IntPoint(0, 0));
+ EXPECT_EQ(end.edge_end, IntPoint(0, 10));
+
+ // Move the selection around the start and end of the second div.
+ local_frame->Selection().SetSelectionAndEndTyping(
+ SelectionInDOMTree::Builder()
+ .Collapse(Position(GetElementById("target")->firstChild(), 0))
+ .Extend(Position(GetElementById("target")->firstChild(), 3))
+ .Build());
+
+ // Ensure the handle will be visible for the next paint (previous call to
+ // SetSelectionAndEndTyping will clear the bit).
+ local_frame->Selection().SetHandleVisibleForTesting();
+
+ UpdateAllLifecyclePhasesForTest();
+
+ chunks = ContentPaintChunks();
+ chunk_iterator = chunks.begin();
+ EXPECT_EQ(chunks.size(), 4u);
+
+ // Skip the root chunk to get to the first div, which should no longer have
+ // a recorded value.
+ ++chunk_iterator;
+ EXPECT_FALSE(chunk_iterator->layer_selection_data);
+
+ // Validate start/end in second div.
+ ++chunk_iterator;
+ EXPECT_TRUE(chunk_iterator->layer_selection_data->start.has_value());
+ EXPECT_TRUE(chunk_iterator->layer_selection_data->end.has_value());
+ start = chunk_iterator->layer_selection_data->start.value();
+ EXPECT_EQ(start.type, gfx::SelectionBound::LEFT);
+ EXPECT_EQ(start.edge_start, IntPoint(0, 0));
+ EXPECT_EQ(start.edge_end, IntPoint(0, 10));
+
+ end = chunk_iterator->layer_selection_data->end.value();
+ EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT);
+ EXPECT_EQ(end.edge_start, IntPoint(30, 0));
+ EXPECT_EQ(end.edge_end, IntPoint(30, 10));
+
+ // Third div's chunk should no longer have an end value.
+ ++chunk_iterator;
+ EXPECT_FALSE(chunk_iterator->layer_selection_data);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_container_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/svg_container_painter_test.cc
index 80d94a1b198..fbe8b7ad23e 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_container_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_container_painter_test.cc
@@ -23,7 +23,6 @@ using SVGContainerPainterTest = PaintControllerPaintTest;
INSTANTIATE_PAINT_TEST_SUITE_P(SVGContainerPainterTest);
TEST_P(SVGContainerPainterTest, FilterPaintProperties) {
- ScopedCompositeSVGForTest enable_feature(true);
SetBodyInnerHTML(R"HTML(
<style>
#container, #before, #after { will-change: transform; }
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 0f1f5c9970d..944feb5e496 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
@@ -87,10 +87,9 @@ void SVGImagePainter::PaintForeground(const PaintInfo& paint_info) {
layout_svg_image_.StyleRef().GetInterpolationQuality());
Image::ImageDecodingMode decode_mode =
image_element->GetDecodingModeForPainting(image->paint_image_id());
- paint_info.context.DrawImage(
- image.get(), decode_mode, dest_rect, &src_rect,
- layout_svg_image_.StyleRef().HasFilterInducingProperty(),
- SkBlendMode::kSrcOver, respect_orientation);
+ paint_info.context.DrawImage(image.get(), decode_mode, dest_rect, &src_rect,
+ layout_svg_image_.StyleRef().DisableForceDark(),
+ SkBlendMode::kSrcOver, respect_orientation);
ImageResourceContent* image_content = image_resource.CachedImage();
if (image_content->IsLoaded()) {
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
index 430e7873c4c..c4ec5e29300 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h"
#include <memory>
+
+#include "base/stl_util.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
@@ -379,9 +381,12 @@ void SVGInlineTextBoxPainter::PaintDecoration(const PaintInfo& paint_info,
if (decoration_style.HasFill()) {
PaintFlags fill_flags;
if (!SVGObjectPainter(*decoration_layout_object)
- .PreparePaint(paint_info, decoration_style, kApplyToFillMode,
- fill_flags))
+ .PreparePaint(paint_info.context,
+ paint_info.IsRenderingClipPathAsMaskImage(),
+ decoration_style, kApplyToFillMode,
+ fill_flags)) {
break;
+ }
fill_flags.setAntiAlias(true);
paint_info.context.DrawPath(path.GetSkPath(), fill_flags);
}
@@ -390,9 +395,12 @@ void SVGInlineTextBoxPainter::PaintDecoration(const PaintInfo& paint_info,
if (decoration_style.HasVisibleStroke()) {
PaintFlags stroke_flags;
if (!SVGObjectPainter(*decoration_layout_object)
- .PreparePaint(paint_info, decoration_style,
- kApplyToStrokeMode, stroke_flags))
+ .PreparePaint(paint_info.context,
+ paint_info.IsRenderingClipPathAsMaskImage(),
+ decoration_style, kApplyToStrokeMode,
+ stroke_flags)) {
break;
+ }
stroke_flags.setAntiAlias(true);
float stroke_scale_factor = decoration_style.VectorEffect() ==
EVectorEffect::kNonScalingStroke
@@ -441,9 +449,13 @@ bool SVGInlineTextBoxPainter::SetupTextPaint(
}
if (!SVGObjectPainter(ParentInlineLayoutObject())
- .PreparePaint(paint_info, style, resource_mode, flags,
- base::OptionalOrNullptr(paint_server_transform)))
+ .PreparePaint(paint_info.context,
+ paint_info.IsRenderingClipPathAsMaskImage(), style,
+ resource_mode, flags,
+ base::OptionalOrNullptr(paint_server_transform))) {
return false;
+ }
+
flags.setAntiAlias(true);
if (style.TextShadow() &&
@@ -677,11 +689,7 @@ void SVGInlineTextBoxPainter::PaintTextMarkerForeground(
return;
Color text_color = LayoutTheme::GetTheme().PlatformTextSearchColor(
- marker.IsActiveMatch(),
- svg_inline_text_box_.GetLineLayoutItem()
- .GetDocument()
- .InForcedColorsMode(),
- style.UsedColorScheme());
+ marker.IsActiveMatch(), style.UsedColorScheme());
PaintFlags fill_flags;
fill_flags.setColor(text_color.Rgb());
@@ -724,11 +732,7 @@ void SVGInlineTextBoxPainter::PaintTextMarkerBackground(
return;
Color color = LayoutTheme::GetTheme().PlatformTextSearchHighlightColor(
- marker.IsActiveMatch(),
- svg_inline_text_box_.GetLineLayoutItem()
- .GetDocument()
- .InForcedColorsMode(),
- style.UsedColorScheme());
+ marker.IsActiveMatch(), style.UsedColorScheme());
for (const SVGTextFragmentWithRange& text_match_info : text_match_info_list) {
const SVGTextFragment& fragment = text_match_info.fragment;
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 6870ae22f33..865ffad3cdc 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_INLINE_TEXT_BOX_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_INLINE_TEXT_BOX_PAINTER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/paint/svg_object_painter.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
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 72f23f43e38..893109d449b 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/svg_mask_painter.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
@@ -46,7 +47,9 @@ void SVGMaskPainter::Paint(GraphicsContext& context,
auto* masker = GetSVGResourceAsType<LayoutSVGResourceMasker>(
*client, style.MaskerResource());
DCHECK(masker);
- SECURITY_DCHECK(!masker->NeedsLayout());
+ if (DisplayLockUtilities::LockedAncestorPreventingLayout(*masker))
+ return;
+ SECURITY_DCHECK(!masker->SelfNeedsLayout());
masker->ClearInvalidationMask();
FloatRect reference_box = SVGResources::ReferenceBoxForEffects(layout_object);
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_object_painter.cc
index acd0c2d1623..f675b25f63d 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_object_painter.cc
@@ -14,7 +14,8 @@ namespace blink {
namespace {
-void CopyStateFromGraphicsContext(GraphicsContext& context, PaintFlags& flags) {
+void CopyStateFromGraphicsContext(const GraphicsContext& context,
+ PaintFlags& flags) {
// TODO(fs): The color filter can be set when generating a picture for a mask
// due to color-interpolation. We could also just apply the
// color-interpolation property from the the shape itself (which could mean
@@ -31,7 +32,7 @@ void CopyStateFromGraphicsContext(GraphicsContext& context, PaintFlags& flags) {
} // namespace
void SVGObjectPainter::PaintResourceSubtree(GraphicsContext& context) {
- DCHECK(!layout_object_.NeedsLayout());
+ DCHECK(!layout_object_.SelfNeedsLayout());
PaintInfo info(context, CullRect::Infinite(), PaintPhase::kForeground,
kGlobalPaintNormalPhase | kGlobalPaintFlattenCompositingLayers,
@@ -57,12 +58,13 @@ bool SVGObjectPainter::ApplyPaintResource(
}
bool SVGObjectPainter::PreparePaint(
- const PaintInfo& paint_info,
+ const GraphicsContext& context,
+ bool is_rendering_clip_path_as_mask_image,
const ComputedStyle& style,
LayoutSVGResourceMode resource_mode,
PaintFlags& flags,
const AffineTransform* additional_paint_server_transform) {
- if (paint_info.IsRenderingClipPathAsMaskImage()) {
+ if (is_rendering_clip_path_as_mask_image) {
if (resource_mode == kApplyToStrokeMode)
return false;
flags.setColor(SK_ColorBLACK);
@@ -78,7 +80,7 @@ bool SVGObjectPainter::PreparePaint(
if (paint.HasUrl()) {
if (ApplyPaintResource(paint, additional_paint_server_transform, flags)) {
flags.setColor(ScaleAlpha(SK_ColorBLACK, alpha));
- CopyStateFromGraphicsContext(paint_info.context, flags);
+ CopyStateFromGraphicsContext(context, flags);
return true;
}
}
@@ -88,7 +90,7 @@ bool SVGObjectPainter::PreparePaint(
const Color color = style.VisitedDependentColor(property);
flags.setColor(ScaleAlpha(color.Rgb(), alpha));
flags.setShader(nullptr);
- CopyStateFromGraphicsContext(paint_info.context, flags);
+ CopyStateFromGraphicsContext(context, flags);
return true;
}
return false;
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_object_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_object_painter.h
index 2be9fa3f5c2..a45b590e5be 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_object_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_object_painter.h
@@ -11,7 +11,6 @@
namespace blink {
-struct PaintInfo;
class AffineTransform;
class ComputedStyle;
class GraphicsContext;
@@ -34,7 +33,8 @@ class SVGObjectPainter {
// object. Returns true if successful, and the caller can continue to paint
// using |paint_flags|.
bool PreparePaint(
- const PaintInfo&,
+ const GraphicsContext& context,
+ bool is_rendering_clip_path_as_mask_image,
const ComputedStyle&,
LayoutSVGResourceMode,
PaintFlags& paint_flags,
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 fc56de03b3d..252cb9ae20d 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/svg_shape_painter.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_shape.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
@@ -74,9 +75,11 @@ void SVGShapePainter::Paint(const PaintInfo& paint_info) {
case PT_FILL: {
PaintFlags fill_flags;
if (!SVGObjectPainter(layout_svg_shape_)
- .PreparePaint(paint_info, style, kApplyToFillMode,
- fill_flags))
+ .PreparePaint(paint_info.context,
+ paint_info.IsRenderingClipPathAsMaskImage(),
+ style, kApplyToFillMode, fill_flags)) {
break;
+ }
fill_flags.setAntiAlias(should_anti_alias);
FillShape(paint_info.context, fill_flags,
FillRuleFromStyle(paint_info, style));
@@ -99,9 +102,12 @@ void SVGShapePainter::Paint(const PaintInfo& paint_info) {
PaintFlags stroke_flags;
if (!SVGObjectPainter(layout_svg_shape_)
.PreparePaint(
- paint_info, style, kApplyToStrokeMode, stroke_flags,
- base::OptionalOrNullptr(non_scaling_transform)))
+ paint_info.context,
+ paint_info.IsRenderingClipPathAsMaskImage(), style,
+ kApplyToStrokeMode, stroke_flags,
+ base::OptionalOrNullptr(non_scaling_transform))) {
break;
+ }
stroke_flags.setAntiAlias(should_anti_alias);
StrokeData stroke_data;
diff --git a/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
index fb7125dee16..00889fb2825 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
@@ -10,6 +10,7 @@
#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/paint/box_paint_invalidator.h"
+#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
namespace blink {
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 9c099775574..886e3ccdf21 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
@@ -48,8 +48,7 @@ void TableSectionPainter::Paint(const PaintInfo& paint_info) {
for (const auto* fragment = &layout_table_section_.FirstFragment(); fragment;
fragment = fragment->NextFragment()) {
PaintInfo fragment_paint_info = paint_info;
- fragment_paint_info.SetFragmentLogicalTopInFlowThread(
- fragment->LogicalTopInFlowThread());
+ fragment_paint_info.SetFragmentID(fragment->FragmentID());
ScopedDisplayItemFragment scoped_display_item_fragment(
fragment_paint_info.context, fragment_index++);
PaintSection(fragment_paint_info);
@@ -106,11 +105,13 @@ void TableSectionPainter::PaintCollapsedBorders(const PaintInfo& paint_info) {
return;
}
+ unsigned fragment_index = 0;
for (const auto* fragment = &layout_table_section_.FirstFragment(); fragment;
fragment = fragment->NextFragment()) {
PaintInfo fragment_paint_info = paint_info;
- fragment_paint_info.SetFragmentLogicalTopInFlowThread(
- fragment->LogicalTopInFlowThread());
+ fragment_paint_info.SetFragmentID(fragment->FragmentID());
+ ScopedDisplayItemFragment scoped_display_item_fragment(
+ fragment_paint_info.context, fragment_index++);
PaintCollapsedSectionBorders(fragment_paint_info);
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/text_decoration_info.cc b/chromium/third_party/blink/renderer/core/paint/text_decoration_info.cc
index 3409e759e1b..31983132cb7 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_decoration_info.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_decoration_info.cc
@@ -28,7 +28,7 @@ static ResolvedUnderlinePosition ResolveUnderlinePosition(
if (style.TextUnderlinePosition() & kTextUnderlinePositionFromFont)
return ResolvedUnderlinePosition::kNearAlphabeticBaselineFromFont;
return ResolvedUnderlinePosition::kNearAlphabeticBaselineAuto;
- case kIdeographicBaseline:
+ case kCentralBaseline: {
// Compute language-appropriate default underline position.
// https://drafts.csswg.org/css-text-decor-3/#default-stylesheet
UScriptCode script = style.GetFontDescription().GetScript();
@@ -42,6 +42,10 @@ static ResolvedUnderlinePosition ResolveUnderlinePosition(
return ResolvedUnderlinePosition::kOver;
}
return ResolvedUnderlinePosition::kUnder;
+ }
+ default:
+ NOTREACHED();
+ break;
}
NOTREACHED();
return ResolvedUnderlinePosition::kNearAlphabeticBaselineAuto;
@@ -154,7 +158,6 @@ static int TextDecorationToLineDataIndex(TextDecoration line) {
} // anonymous namespace
TextDecorationInfo::TextDecorationInfo(
- const PhysicalOffset& box_origin,
PhysicalOffset local_origin,
LayoutUnit width,
FontBaseline baseline_type,
diff --git a/chromium/third_party/blink/renderer/core/paint/text_decoration_info.h b/chromium/third_party/blink/renderer/core/paint/text_decoration_info.h
index 1973942f40b..be9d2e63831 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_decoration_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_decoration_info.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_DECORATION_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_DECORATION_INFO_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/paint/text_paint_style.h"
@@ -37,7 +38,6 @@ class CORE_EXPORT TextDecorationInfo {
public:
TextDecorationInfo(
- const PhysicalOffset& box_origin,
PhysicalOffset local_origin,
LayoutUnit width,
FontBaseline baseline_type,
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_style.h b/chromium/third_party/blink/renderer/core/paint/text_paint_style.h
index 427f81b1f55..33fb74c26af 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_style.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_style.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_PAINT_STYLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_PAINT_STYLE_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/frame/color_scheme.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/style/applied_text_decoration.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
index 63fc7b0ed8b..14a8233ba68 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
@@ -85,7 +85,8 @@ class TextPaintTimingDetectorTest : public testing::Test {
wtf_size_t CountRankingSetSize() {
DCHECK(GetTextPaintTimingDetector());
- return GetLargestTextPaintManager()->size_ordered_set_.size();
+ return static_cast<wtf_size_t>(
+ GetLargestTextPaintManager()->size_ordered_set_.size());
}
wtf_size_t CountInvisibleTexts() {
@@ -326,10 +327,10 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_TraceEvent_Candidate) {
EXPECT_TRUE(events[0]->HasArg("frame"));
EXPECT_TRUE(events[0]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId node_id;
EXPECT_TRUE(arg_dict->GetInteger("DOMNodeId", &node_id));
EXPECT_GT(node_id, 0);
@@ -395,10 +396,10 @@ TEST_F(TextPaintTimingDetectorTest,
EXPECT_TRUE(events[0]->HasArg("frame"));
EXPECT_TRUE(events[0]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId node_id;
EXPECT_TRUE(arg_dict->GetInteger("DOMNodeId", &node_id));
EXPECT_GT(node_id, 0);
@@ -463,10 +464,10 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_TraceEvent_NoCandidate) {
EXPECT_TRUE(events[0]->HasArg("frame"));
EXPECT_TRUE(events[0]->HasArg("data"));
- std::unique_ptr<base::Value> arg;
+ base::Value arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
+ EXPECT_TRUE(arg.GetAsDictionary(&arg_dict));
DOMNodeId candidate_index;
EXPECT_TRUE(arg_dict->GetInteger("candidateIndex", &candidate_index));
EXPECT_EQ(candidate_index, 2);
diff --git a/chromium/third_party/blink/renderer/core/paint/text_painter.cc b/chromium/third_party/blink/renderer/core/paint/text_painter.cc
index f8379c71dd4..77e220b71b1 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_painter.cc
@@ -44,12 +44,15 @@ void TextPainter::Paint(unsigned start_offset,
}
if (!emphasis_mark_.IsEmpty()) {
- if (text_style.emphasis_mark_color != text_style.fill_color)
- graphics_context_.SetFillColor(text_style.emphasis_mark_color);
-
if (combined_text_) {
- PaintEmphasisMarkForCombinedText();
+ graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
+ PaintEmphasisMarkForCombinedText(text_style,
+ combined_text_->OriginalFont());
+ graphics_context_.ConcatCTM(
+ Rotation(text_frame_rect_, kCounterclockwise));
} else {
+ if (text_style.emphasis_mark_color != text_style.fill_color)
+ graphics_context_.SetFillColor(text_style.emphasis_mark_color);
PaintInternal<kPaintEmphasisMark>(start_offset, end_offset, length,
node_id);
}
@@ -67,7 +70,7 @@ void TextPainter::PaintDecorationsExceptLineThrough(
GraphicsContextStateSaver state_saver(context);
UpdateGraphicsContext(context, text_style, horizontal_, state_saver);
- if (has_combined_text_)
+ if (combined_text_)
context.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
// text-underline-position may flip underline and overline.
@@ -79,7 +82,7 @@ void TextPainter::PaintDecorationsExceptLineThrough(
underline_position = ResolvedUnderlinePosition::kUnder;
}
- for (size_t applied_decoration_index = 0;
+ for (wtf_size_t applied_decoration_index = 0;
applied_decoration_index < decorations.size();
++applied_decoration_index) {
const AppliedTextDecoration& decoration =
@@ -139,7 +142,7 @@ void TextPainter::PaintDecorationsExceptLineThrough(
}
// Restore rotation as needed.
- if (has_combined_text_)
+ if (combined_text_)
context.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise));
}
@@ -152,10 +155,10 @@ void TextPainter::PaintDecorationsOnlyLineThrough(
GraphicsContextStateSaver state_saver(context);
UpdateGraphicsContext(context, text_style, horizontal_, state_saver);
- if (has_combined_text_)
+ if (combined_text_)
context.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
- for (size_t applied_decoration_index = 0;
+ for (wtf_size_t applied_decoration_index = 0;
applied_decoration_index < decorations.size();
++applied_decoration_index) {
const AppliedTextDecoration& decoration =
@@ -190,7 +193,7 @@ void TextPainter::PaintDecorationsOnlyLineThrough(
}
// Restore rotation as needed.
- if (has_combined_text_)
+ if (combined_text_)
context.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise));
}
@@ -253,24 +256,4 @@ void TextPainter::ClipDecorationsStripe(float upper,
DecorationsStripeIntercepts(upper, stripe_width, dilation, text_intercepts);
}
-void TextPainter::PaintEmphasisMarkForCombinedText() {
- const SimpleFontData* font_data = font_.PrimaryFont();
- DCHECK(font_data);
- if (!font_data)
- return;
-
- DCHECK(combined_text_);
- TextRun placeholder_text_run(&kIdeographicFullStopCharacter, 1);
- FloatPoint emphasis_mark_text_origin(
- text_frame_rect_.X().ToFloat(), text_frame_rect_.Y().ToFloat() +
- font_data->GetFontMetrics().Ascent() +
- emphasis_mark_offset_);
- TextRunPaintInfo text_run_paint_info(placeholder_text_run);
- graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
- graphics_context_.DrawEmphasisMarks(combined_text_->OriginalFont(),
- text_run_paint_info, emphasis_mark_,
- emphasis_mark_text_origin);
- graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise));
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/text_painter.h b/chromium/third_party/blink/renderer/core/paint/text_painter.h
index 423743444e0..232c67d496b 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_painter.h
@@ -32,13 +32,11 @@ class CORE_EXPORT TextPainter : public TextPainterBase {
text_origin,
text_frame_rect,
horizontal),
- run_(run),
- combined_text_(nullptr) {}
+ run_(run) {}
~TextPainter() = default;
void SetCombinedText(LayoutTextCombine* combined_text) {
combined_text_ = combined_text;
- has_combined_text_ = combined_text_ ? true : false;
}
void ClipDecorationsStripe(float upper,
@@ -74,10 +72,8 @@ class CORE_EXPORT TextPainter : public TextPainterBase {
unsigned truncation_point,
DOMNodeId node_id);
- void PaintEmphasisMarkForCombinedText();
-
const TextRun& run_;
- LayoutTextCombine* combined_text_;
+ LayoutTextCombine* combined_text_ = nullptr;
};
} // namespace blink
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 74463be4405..18107374fc3 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
@@ -13,8 +13,8 @@
#include "third_party/blink/renderer/core/paint/text_decoration_info.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/shadow_list.h"
-#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
@@ -42,10 +42,7 @@ TextPainterBase::TextPainterBase(GraphicsContext& context,
font_(font),
text_origin_(text_origin),
text_frame_rect_(text_frame_rect),
- horizontal_(horizontal),
- has_combined_text_(false),
- emphasis_mark_offset_(0),
- ellipsis_offset_(0) {}
+ horizontal_(horizontal) {}
TextPainterBase::~TextPainterBase() = default;
@@ -74,34 +71,6 @@ void TextPainterBase::SetEmphasisMark(const AtomicString& emphasis_mark,
}
// static
-void TextPainterBase::AdjustTextStyleForClip(TextPaintStyle& text_style) {
- // When we use the text as a clip, we only care about the alpha, thus we
- // make all the colors black.
- text_style.current_color = Color::kBlack;
- text_style.fill_color = Color::kBlack;
- text_style.stroke_color = Color::kBlack;
- text_style.emphasis_mark_color = Color::kBlack;
- text_style.shadow = nullptr;
-}
-
-// static
-void TextPainterBase::AdjustTextStyleForPrint(const Document& document,
- const ComputedStyle& style,
- TextPaintStyle& text_style) {
- // Adjust text color when printing with a white background.
- bool force_background_to_white =
- BoxPainterBase::ShouldForceWhiteBackgroundForPrintEconomy(document,
- style);
- if (force_background_to_white) {
- text_style.fill_color = TextColorForWhiteBackground(text_style.fill_color);
- text_style.stroke_color =
- TextColorForWhiteBackground(text_style.stroke_color);
- text_style.emphasis_mark_color =
- TextColorForWhiteBackground(text_style.emphasis_mark_color);
- }
-}
-
-// static
void TextPainterBase::UpdateGraphicsContext(
GraphicsContext& context,
const TextPaintStyle& text_style,
@@ -188,7 +157,13 @@ TextPaintStyle TextPainterBase::TextPaintingStyle(const Document& document,
text_style.color_scheme = style.UsedColorScheme();
if (paint_info.phase == PaintPhase::kTextClip) {
- AdjustTextStyleForClip(text_style);
+ // When we use the text as a clip, we only care about the alpha, thus we
+ // make all the colors black.
+ text_style.current_color = Color::kBlack;
+ text_style.fill_color = Color::kBlack;
+ text_style.stroke_color = Color::kBlack;
+ text_style.emphasis_mark_color = Color::kBlack;
+ text_style.shadow = nullptr;
} else {
text_style.current_color =
style.VisitedDependentColor(GetCSSPropertyColor());
@@ -200,54 +175,18 @@ TextPaintStyle TextPainterBase::TextPaintingStyle(const Document& document,
style.VisitedDependentColor(GetCSSPropertyWebkitTextEmphasisColor());
text_style.shadow = style.TextShadow();
- AdjustTextStyleForPrint(document, style, text_style);
- }
-
- return text_style;
-}
-
-// static
-TextPaintStyle TextPainterBase::SvgTextPaintingStyle(
- const Document& document,
- const SVGLengthContext& length_context,
- const ComputedStyle& style,
- const PaintInfo& paint_info) {
- TextPaintStyle text_style;
- text_style.stroke_width =
- style.HasStroke() ? length_context.ValueForLength(style.StrokeWidth())
- : 0;
- text_style.color_scheme = style.UsedColorScheme();
-
- if (paint_info.phase == PaintPhase::kTextClip) {
- AdjustTextStyleForClip(text_style);
- } else {
- text_style.current_color =
- style.VisitedDependentColor(GetCSSPropertyColor());
-
- const SVGPaint fill_paint = style.FillPaint();
- if (fill_paint.IsNone()) {
- text_style.fill_color = Color::kTransparent;
- } else if (fill_paint.HasColor()) {
- const Color color = style.VisitedDependentColor(GetCSSPropertyFill());
- const float alpha = style.FillOpacity();
- text_style.fill_color = ScaleAlpha(color.Rgb(), alpha);
- } else {
- text_style.fill_color = Color::kBlack;
+ // Adjust text color when printing with a white background.
+ bool force_background_to_white =
+ BoxPainterBase::ShouldForceWhiteBackgroundForPrintEconomy(document,
+ style);
+ if (force_background_to_white) {
+ text_style.fill_color =
+ TextColorForWhiteBackground(text_style.fill_color);
+ text_style.stroke_color =
+ TextColorForWhiteBackground(text_style.stroke_color);
+ text_style.emphasis_mark_color =
+ TextColorForWhiteBackground(text_style.emphasis_mark_color);
}
-
- if (style.StrokePaint().HasColor()) {
- const Color color = style.VisitedDependentColor(GetCSSPropertyStroke());
- const float alpha = style.StrokeOpacity();
- text_style.stroke_color = ScaleAlpha(color.Rgb(), alpha);
- } else {
- text_style.stroke_color = Color::kTransparent;
- }
-
- text_style.emphasis_mark_color =
- style.VisitedDependentColor(GetCSSPropertyWebkitTextEmphasisColor());
- text_style.shadow = style.TextShadow();
-
- AdjustTextStyleForPrint(document, style, text_style);
}
return text_style;
@@ -289,6 +228,130 @@ void TextPainterBase::DecorationsStripeIntercepts(
}
}
+void TextPainterBase::PaintDecorationsExceptLineThrough(
+ const TextDecorationOffsetBase& decoration_offset,
+ TextDecorationInfo& decoration_info,
+ const PaintInfo& paint_info,
+ const Vector<AppliedTextDecoration>& decorations,
+ const TextPaintStyle& text_style,
+ bool* has_line_through_decoration) {
+ GraphicsContext& context = paint_info.context;
+ GraphicsContextStateSaver state_saver(context);
+ UpdateGraphicsContext(context, text_style, horizontal_, state_saver);
+
+ // text-underline-position may flip underline and overline.
+ ResolvedUnderlinePosition underline_position =
+ decoration_info.UnderlinePosition();
+ bool flip_underline_and_overline = false;
+ if (underline_position == ResolvedUnderlinePosition::kOver) {
+ flip_underline_and_overline = true;
+ underline_position = ResolvedUnderlinePosition::kUnder;
+ }
+
+ for (wtf_size_t applied_decoration_index = 0;
+ applied_decoration_index < decorations.size();
+ ++applied_decoration_index) {
+ const AppliedTextDecoration& decoration =
+ decorations[applied_decoration_index];
+ TextDecoration lines = decoration.Lines();
+ bool has_underline = EnumHasFlags(lines, TextDecoration::kUnderline);
+ bool has_overline = EnumHasFlags(lines, TextDecoration::kOverline);
+ if (flip_underline_and_overline)
+ std::swap(has_underline, has_overline);
+
+ decoration_info.SetDecorationIndex(applied_decoration_index);
+
+ float resolved_thickness = decoration_info.ResolvedThickness();
+ context.SetStrokeThickness(resolved_thickness);
+
+ if (has_underline && decoration_info.FontData()) {
+ // Don't apply text-underline-offset to overline.
+ Length line_offset =
+ flip_underline_and_overline ? Length() : decoration.UnderlineOffset();
+
+ const int paint_underline_offset =
+ decoration_offset.ComputeUnderlineOffset(
+ underline_position, decoration_info.Style().ComputedFontSize(),
+ decoration_info.FontData()->GetFontMetrics(), line_offset,
+ resolved_thickness);
+ decoration_info.SetPerLineData(
+ TextDecoration::kUnderline, paint_underline_offset,
+ TextDecorationInfo::DoubleOffsetFromThickness(resolved_thickness), 1);
+ PaintDecorationUnderOrOverLine(context, decoration_info,
+ TextDecoration::kUnderline);
+ }
+
+ if (has_overline && decoration_info.FontData()) {
+ // Don't apply text-underline-offset to overline.
+ Length line_offset =
+ flip_underline_and_overline ? decoration.UnderlineOffset() : Length();
+
+ FontVerticalPositionType position =
+ flip_underline_and_overline ? FontVerticalPositionType::TopOfEmHeight
+ : FontVerticalPositionType::TextTop;
+ const int paint_overline_offset =
+ decoration_offset.ComputeUnderlineOffsetForUnder(
+ line_offset, decoration_info.Style().ComputedFontSize(),
+ resolved_thickness, position);
+ decoration_info.SetPerLineData(
+ TextDecoration::kOverline, paint_overline_offset,
+ -TextDecorationInfo::DoubleOffsetFromThickness(resolved_thickness),
+ 1);
+ PaintDecorationUnderOrOverLine(context, decoration_info,
+ TextDecoration::kOverline);
+ }
+
+ // We could instead build a vector of the TextDecoration instances needing
+ // line-through but this is a rare case so better to avoid vector overhead.
+ *has_line_through_decoration |=
+ EnumHasFlags(lines, TextDecoration::kLineThrough);
+ }
+}
+
+void TextPainterBase::PaintDecorationsOnlyLineThrough(
+ TextDecorationInfo& decoration_info,
+ const PaintInfo& paint_info,
+ const Vector<AppliedTextDecoration>& decorations,
+ const TextPaintStyle& text_style) {
+ GraphicsContext& context = paint_info.context;
+ GraphicsContextStateSaver state_saver(context);
+ UpdateGraphicsContext(context, text_style, horizontal_, state_saver);
+
+ for (wtf_size_t applied_decoration_index = 0;
+ applied_decoration_index < decorations.size();
+ ++applied_decoration_index) {
+ const AppliedTextDecoration& decoration =
+ decorations[applied_decoration_index];
+ TextDecoration lines = decoration.Lines();
+ if (EnumHasFlags(lines, TextDecoration::kLineThrough)) {
+ decoration_info.SetDecorationIndex(applied_decoration_index);
+
+ float resolved_thickness = decoration_info.ResolvedThickness();
+ context.SetStrokeThickness(resolved_thickness);
+
+ // For increased line thickness, the line-through decoration needs to grow
+ // in both directions from its origin, subtract half the thickness to keep
+ // it centered at the same origin.
+ const float line_through_offset =
+ 2 * decoration_info.Baseline() / 3 - resolved_thickness / 2;
+ // Floor double_offset in order to avoid double-line gap to appear
+ // of different size depending on position where the double line
+ // is drawn because of rounding downstream in
+ // GraphicsContext::DrawLineForText.
+ decoration_info.SetPerLineData(
+ TextDecoration::kLineThrough, line_through_offset,
+ floorf(TextDecorationInfo::DoubleOffsetFromThickness(
+ resolved_thickness)),
+ 0);
+ AppliedDecorationPainter decoration_painter(context, decoration_info,
+ TextDecoration::kLineThrough);
+ // No skip: ink for line-through,
+ // compare https://github.com/w3c/csswg-drafts/issues/711
+ decoration_painter.Paint();
+ }
+ }
+}
+
void TextPainterBase::PaintDecorationUnderOrOverLine(
GraphicsContext& context,
TextDecorationInfo& decoration_info,
@@ -308,4 +371,30 @@ void TextPainterBase::PaintDecorationUnderOrOverLine(
decoration_painter.Paint();
}
+void TextPainterBase::PaintEmphasisMarkForCombinedText(
+ const TextPaintStyle& text_style,
+ const Font& emphasis_mark_font) {
+ DCHECK(emphasis_mark_font.GetFontDescription().IsVerticalBaseline());
+ DCHECK(emphasis_mark_);
+ const SimpleFontData* const font_data = font_.PrimaryFont();
+ DCHECK(font_data);
+ if (!font_data)
+ return;
+
+ if (text_style.emphasis_mark_color != text_style.fill_color) {
+ // See virtual/text-antialias/emphasis-combined-text.html
+ graphics_context_.SetFillColor(text_style.emphasis_mark_color);
+ }
+
+ const auto font_ascent = font_data->GetFontMetrics().Ascent();
+ const TextRun placeholder_text_run(&kIdeographicFullStopCharacter, 1);
+ const FloatPoint emphasis_mark_text_origin(
+ text_frame_rect_.X().ToFloat(),
+ text_frame_rect_.Y().ToFloat() + font_ascent + emphasis_mark_offset_);
+ const TextRunPaintInfo text_run_paint_info(placeholder_text_run);
+ graphics_context_.DrawEmphasisMarks(emphasis_mark_font, text_run_paint_info,
+ emphasis_mark_,
+ emphasis_mark_text_origin);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/text_painter_base.h b/chromium/third_party/blink/renderer/core/paint/text_painter_base.h
index 35271337b3f..bba7e4bb175 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_painter_base.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_painter_base.h
@@ -25,7 +25,7 @@ class Document;
class GraphicsContext;
class GraphicsContextStateSaver;
class Node;
-class SVGLengthContext;
+class TextDecorationOffsetBase;
struct PaintInfo;
// Base class for text painting. Has no dependencies on the layout tree and thus
@@ -71,10 +71,6 @@ class CORE_EXPORT TextPainterBase {
static TextPaintStyle TextPaintingStyle(const Document&,
const ComputedStyle&,
const PaintInfo&);
- static TextPaintStyle SvgTextPaintingStyle(const Document&,
- const SVGLengthContext&,
- const ComputedStyle&,
- const PaintInfo&);
static TextPaintStyle SelectionPaintingStyle(
const Document&,
const ComputedStyle&,
@@ -85,12 +81,9 @@ class CORE_EXPORT TextPainterBase {
enum RotationDirection { kCounterclockwise, kClockwise };
static AffineTransform Rotation(const PhysicalRect& box_rect,
RotationDirection);
+ static AffineTransform Rotation(const PhysicalRect& box_rect, WritingMode);
protected:
- static void AdjustTextStyleForClip(TextPaintStyle&);
- static void AdjustTextStyleForPrint(const Document&,
- const ComputedStyle&,
- TextPaintStyle&);
void UpdateGraphicsContext(const TextPaintStyle& style,
GraphicsContextStateSaver& saver) {
UpdateGraphicsContext(graphics_context_, style, horizontal_, saver);
@@ -101,17 +94,42 @@ class CORE_EXPORT TextPainterBase {
float dilation,
const Vector<Font::TextIntercept>& text_intercepts);
+ // We have two functions to paint text decoations, because we should paint
+ // text and decorations in following order:
+ // 1. Paint text decorations except line through
+ // 2. Paint text
+ // 3. Paint line throguh
+ void PaintDecorationsExceptLineThrough(const TextDecorationOffsetBase&,
+ TextDecorationInfo&,
+ const PaintInfo&,
+ const Vector<AppliedTextDecoration>&,
+ const TextPaintStyle& text_style,
+ bool* has_line_through_decoration);
+ void PaintDecorationsOnlyLineThrough(TextDecorationInfo&,
+ const PaintInfo&,
+ const Vector<AppliedTextDecoration>&,
+ const TextPaintStyle&);
+
+ // Paints emphasis mark as for ideographic full stop character. Callers of
+ // this function should rotate canvas to paint emphasis mark at left/right
+ // side instead of top/bottom side.
+ // |emphasis_mark_font| is used for painting emphasis mark because |font_|
+ // may be compressed font (width variants).
+ // TODO(yosin): Once legacy inline layout gone, we should move this function
+ // to |NGTextCombinePainter|.
+ void PaintEmphasisMarkForCombinedText(const TextPaintStyle& text_style,
+ const Font& emphasis_mark_font);
+
enum PaintInternalStep { kPaintText, kPaintEmphasisMark };
GraphicsContext& graphics_context_;
const Font& font_;
- PhysicalOffset text_origin_;
- PhysicalRect text_frame_rect_;
- bool horizontal_;
- bool has_combined_text_;
+ const PhysicalOffset text_origin_;
+ const PhysicalRect text_frame_rect_;
AtomicString emphasis_mark_;
- int emphasis_mark_offset_;
- int ellipsis_offset_;
+ int emphasis_mark_offset_ = 0;
+ int ellipsis_offset_ = 0;
+ const bool horizontal_;
};
inline AffineTransform TextPainterBase::Rotation(
@@ -139,6 +157,13 @@ inline AffineTransform TextPainterBase::Rotation(
box_rect.X() + box_rect.Bottom());
}
+inline AffineTransform TextPainterBase::Rotation(const PhysicalRect& box_rect,
+ WritingMode writing_mode) {
+ return Rotation(box_rect, writing_mode != WritingMode::kSidewaysLr
+ ? TextPainterBase::kClockwise
+ : TextPainterBase::kCounterclockwise);
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_PAINTER_BASE_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter.cc b/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
index f228a00a533..9ef1c2346e8 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
@@ -23,6 +23,7 @@
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.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/forms/html_data_list_element.h"
#include "third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h"
@@ -171,15 +172,9 @@ bool ThemePainter::Paint(const LayoutObject& o,
case kMenulistButtonPart:
return true;
case kTextFieldPart:
- if (!features::IsFormControlsRefreshEnabled()) {
- return true;
- }
CountAppearanceTextFieldPart(element);
return PaintTextField(element, style, paint_info, r);
case kTextAreaPart:
- if (!features::IsFormControlsRefreshEnabled()) {
- return true;
- }
COUNT_APPEARANCE(doc, TextArea);
return PaintTextArea(element, style, paint_info, r);
case kSearchFieldPart: {
@@ -211,17 +206,8 @@ bool ThemePainter::PaintBorderOnly(const Node* node,
// Call the appropriate paint method based off the appearance value.
switch (style.EffectiveAppearance()) {
case kTextFieldPart:
- if (features::IsFormControlsRefreshEnabled()) {
- return false;
- }
- CountAppearanceTextFieldPart(element);
- return PaintTextField(element, style, paint_info, r);
case kTextAreaPart:
- if (features::IsFormControlsRefreshEnabled()) {
- return false;
- }
- COUNT_APPEARANCE(element.GetDocument(), TextArea);
- return PaintTextArea(element, style, paint_info, r);
+ return false;
case kMenulistButtonPart:
case kSearchFieldPart:
case kListboxPart:
@@ -249,8 +235,6 @@ bool ThemePainter::PaintBorderOnly(const Node* node,
// appearance values.
return false;
}
-
- return false;
}
bool ThemePainter::PaintDecorations(const Node* node,
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 8832e863a1a..ed10b07cd5d 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
@@ -27,6 +27,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/public/resources/grit/blink_image_resources.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/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/slider_thumb_element.h"
@@ -187,10 +188,14 @@ bool ThemePainterDefault::PaintCheckbox(const Element& element,
GraphicsContextStateSaver state_saver(paint_info.context, false);
IntRect unzoomed_rect =
ApplyZoomToRect(rect, paint_info, state_saver, zoom_level);
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartCheckbox, GetWebThemeState(element),
- gfx::Rect(unzoomed_rect), &extra_params, style.UsedColorScheme(),
+ gfx::Rect(unzoomed_rect), &extra_params, color_scheme,
GetAccentColor(style));
return false;
}
@@ -209,13 +214,15 @@ bool ThemePainterDefault::PaintRadio(const Element& element,
extra_params.button.zoom = zoom_level;
GraphicsContextStateSaver state_saver(paint_info.context, false);
IntRect unzoomed_rect =
- features::IsFormControlsRefreshEnabled()
- ? ApplyZoomToRect(rect, paint_info, state_saver, zoom_level)
- : rect;
+ ApplyZoomToRect(rect, paint_info, state_saver, zoom_level);
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartRadio, GetWebThemeState(element),
- gfx::Rect(unzoomed_rect), &extra_params, style.UsedColorScheme(),
+ gfx::Rect(unzoomed_rect), &extra_params, color_scheme,
GetAccentColor(style));
return false;
}
@@ -235,10 +242,14 @@ bool ThemePainterDefault::PaintButton(const Element& element,
extra_params.button.background_color =
style.VisitedDependentColor(GetCSSPropertyBackgroundColor()).Rgb();
}
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
+
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartButton, GetWebThemeState(element),
- gfx::Rect(rect), &extra_params, style.UsedColorScheme(),
- GetAccentColor(style));
+ gfx::Rect(rect), &extra_params, color_scheme, GetAccentColor(style));
return false;
}
@@ -251,15 +262,6 @@ bool ThemePainterDefault::PaintTextField(const Element& element,
if (style.HasBorderRadius() || style.HasBackgroundImage())
return true;
- // Don't use the theme painter if dark mode is enabled. It has a separate
- // graphics pipeline that doesn't go through GraphicsContext and so does not
- // currently know how to handle Dark Mode, causing elements to be rendered
- // incorrectly (e.g. https://crbug.com/937872).
- // TODO(gilmanmh): Implement a more permanent solution that allows use of
- // native dark themes.
- if (paint_info.context.IsDarkModeEnabled())
- return true;
-
ControlPart part = style.EffectiveAppearance();
WebThemeEngine::ExtraParams extra_params;
@@ -276,10 +278,14 @@ bool ThemePainterDefault::PaintTextField(const Element& element,
extra_params.text_field.auto_complete_active =
DynamicTo<HTMLFormControlElement>(element)->IsAutofilled();
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
+
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartTextField, GetWebThemeState(element),
- gfx::Rect(rect), &extra_params, style.UsedColorScheme(),
- GetAccentColor(style));
+ gfx::Rect(rect), &extra_params, color_scheme, GetAccentColor(style));
return false;
}
@@ -312,10 +318,14 @@ bool ThemePainterDefault::PaintMenuList(const Element& element,
SetupMenuListArrow(document, style, rect, extra_params);
cc::PaintCanvas* canvas = i.context.Canvas();
+ bool enable_force_dark =
+ i.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
+
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartMenuList, GetWebThemeState(element),
- gfx::Rect(rect), &extra_params, style.UsedColorScheme(),
- GetAccentColor(style));
+ gfx::Rect(rect), &extra_params, color_scheme, GetAccentColor(style));
return false;
}
@@ -332,10 +342,14 @@ bool ThemePainterDefault::PaintMenuListButton(const Element& element,
SetupMenuListArrow(document, style, rect, extra_params);
cc::PaintCanvas* canvas = paint_info.context.Canvas();
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
+
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartMenuList, GetWebThemeState(element),
- gfx::Rect(rect), &extra_params, style.UsedColorScheme(),
- GetAccentColor(style));
+ gfx::Rect(rect), &extra_params, color_scheme, GetAccentColor(style));
return false;
}
@@ -353,8 +367,7 @@ void ThemePainterDefault::SetupMenuListArrow(
theme_.ClampedMenuListArrowPaddingSize(document.GetFrame(), style);
float arrow_scale_factor = arrow_box_width / theme_.MenuListArrowWidthInDIP();
// TODO(tkent): This should be 7.0 to match scroll bar buttons.
- float arrow_size = (features::IsFormControlsRefreshEnabled() ? 8.0 : 6.0) *
- arrow_scale_factor;
+ float arrow_size = 8.0 * arrow_scale_factor;
// Put the arrow at the center of paddingForArrow area.
// |arrowX| is the left position for Aura theme engine.
extra_params.menu_list.arrow_x =
@@ -362,6 +375,8 @@ void ThemePainterDefault::SetupMenuListArrow(
? left + (arrow_box_width - arrow_size) / 2
: right - (arrow_box_width + arrow_size) / 2;
extra_params.menu_list.arrow_size = arrow_size;
+ // TODO: (https://crbug.com/1227305)This color still does not support forced
+ // dark mode
extra_params.menu_list.arrow_color =
style.VisitedDependentColor(GetCSSPropertyColor()).Rgb();
}
@@ -383,14 +398,6 @@ bool ThemePainterDefault::PaintSliderTrack(const Element& element,
extra_params.slider.zoom = zoom_level;
GraphicsContextStateSaver state_saver(i.context, false);
IntRect unzoomed_rect = rect;
- if (zoom_level != 1 && !features::IsFormControlsRefreshEnabled()) {
- state_saver.Save();
- unzoomed_rect.SetWidth(unzoomed_rect.Width() / zoom_level);
- unzoomed_rect.SetHeight(unzoomed_rect.Height() / zoom_level);
- i.context.Translate(unzoomed_rect.X(), unzoomed_rect.Y());
- i.context.Scale(zoom_level, zoom_level);
- i.context.Translate(-unzoomed_rect.X(), -unzoomed_rect.Y());
- }
auto* input = DynamicTo<HTMLInputElement>(element);
extra_params.slider.thumb_x = 0;
@@ -405,29 +412,22 @@ bool ThemePainterDefault::PaintSliderTrack(const Element& element,
LayoutBox* input_box = input->GetLayoutBox();
if (thumb) {
IntRect thumb_rect = PixelSnappedIntRect(thumb->FrameRect());
- if (features::IsFormControlsRefreshEnabled()) {
- extra_params.slider.thumb_x = thumb_rect.X() +
- input_box->PaddingLeft().ToInt() +
- input_box->BorderLeft().ToInt();
- extra_params.slider.thumb_y = thumb_rect.Y() +
- input_box->PaddingTop().ToInt() +
- input_box->BorderTop().ToInt();
- } else {
- extra_params.slider.thumb_x =
- (thumb_rect.X() + input_box->PaddingLeft().ToInt() +
- input_box->BorderLeft().ToInt()) /
- zoom_level;
- extra_params.slider.thumb_y =
- (thumb_rect.Y() + input_box->PaddingTop().ToInt() +
- input_box->BorderTop().ToInt()) /
- zoom_level;
- }
+ extra_params.slider.thumb_x = thumb_rect.X() +
+ input_box->PaddingLeft().ToInt() +
+ input_box->BorderLeft().ToInt();
+ extra_params.slider.thumb_y = thumb_rect.Y() +
+ input_box->PaddingTop().ToInt() +
+ input_box->BorderTop().ToInt();
}
}
+ bool enable_force_dark =
+ i.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = o.StyleRef().UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartSliderTrack, GetWebThemeState(element),
- gfx::Rect(unzoomed_rect), &extra_params, o.StyleRef().UsedColorScheme(),
+ gfx::Rect(unzoomed_rect), &extra_params, color_scheme,
GetAccentColor(style));
return false;
}
@@ -446,14 +446,6 @@ bool ThemePainterDefault::PaintSliderThumb(const Element& element,
extra_params.slider.zoom = zoom_level;
GraphicsContextStateSaver state_saver(paint_info.context, false);
IntRect unzoomed_rect = rect;
- if (zoom_level != 1 && !features::IsFormControlsRefreshEnabled()) {
- state_saver.Save();
- unzoomed_rect.SetWidth(unzoomed_rect.Width() / zoom_level);
- unzoomed_rect.SetHeight(unzoomed_rect.Height() / zoom_level);
- paint_info.context.Translate(unzoomed_rect.X(), unzoomed_rect.Y());
- paint_info.context.Scale(zoom_level, zoom_level);
- paint_info.context.Translate(-unzoomed_rect.X(), -unzoomed_rect.Y());
- }
// The element passed in is inside the user agent shadowdom of the input
// element, so we have to access the parent input element in order to get the
@@ -464,11 +456,14 @@ bool ThemePainterDefault::PaintSliderThumb(const Element& element,
// SliderThumbElement
absl::optional<SkColor> accent_color =
GetAccentColor(*slider_element->HostInput()->EnsureComputedStyle());
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartSliderThumb, GetWebThemeState(element),
- gfx::Rect(unzoomed_rect), &extra_params, style.UsedColorScheme(),
- accent_color);
+ gfx::Rect(unzoomed_rect), &extra_params, color_scheme, accent_color);
return false;
}
@@ -491,11 +486,14 @@ bool ThemePainterDefault::PaintInnerSpinButton(const Element& element,
extra_params.inner_spin.spin_up = spin_up;
extra_params.inner_spin.read_only = read_only;
+ bool enable_force_dark =
+ paint_info.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartInnerSpinButton, GetWebThemeState(element),
- gfx::Rect(rect), &extra_params, style.UsedColorScheme(),
- GetAccentColor(style));
+ gfx::Rect(rect), &extra_params, color_scheme, GetAccentColor(style));
return false;
}
@@ -520,10 +518,14 @@ bool ThemePainterDefault::PaintProgressBar(const Element& element,
DirectionFlippingScope scope(o, i, rect);
cc::PaintCanvas* canvas = i.context.Canvas();
+ bool enable_force_dark =
+ i.context.IsDarkModeEnabled() && !style.DisableForceDark();
+ mojom::blink::ColorScheme color_scheme = o.StyleRef().UsedColorScheme();
+ AdjustColorScheme(color_scheme, enable_force_dark);
+
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartProgressBar, GetWebThemeState(element),
- gfx::Rect(rect), &extra_params, o.StyleRef().UsedColorScheme(),
- GetAccentColor(style));
+ gfx::Rect(rect), &extra_params, color_scheme, GetAccentColor(style));
return false;
}
@@ -641,4 +643,11 @@ IntRect ThemePainterDefault::ApplyZoomToRect(
return unzoomed_rect;
}
+void ThemePainterDefault::AdjustColorScheme(mojom::ColorScheme& color_scheme,
+ bool enable_force_dark) {
+ if (color_scheme == mojom::blink::ColorScheme::kLight && enable_force_dark) {
+ color_scheme = mojom::blink::ColorScheme::kDark;
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter_default.h b/chromium/third_party/blink/renderer/core/paint/theme_painter_default.h
index 965c7a92b87..377fd89e263 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter_default.h
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter_default.h
@@ -111,6 +111,8 @@ class ThemePainterDefault final : public ThemePainter {
GraphicsContextStateSaver&,
float zoom_level);
+ void AdjustColorScheme(mojom::ColorScheme&, bool);
+
// ThemePaintDefault is a part object of m_theme.
LayoutThemeDefault& theme_;
};
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_fuzzer.cc b/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_fuzzer.cc
index b79de5b49b6..8d051a7ff2a 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_fuzzer.cc
@@ -15,6 +15,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
blink::BlinkFuzzerTestSupport();
blink::PolicyParserMessageBuffer logger;
- blink::DocumentPolicyParser::Parse(WTF::String(data, size), logger);
+ blink::DocumentPolicyParser::Parse(
+ WTF::String(data, static_cast<wtf_size_t>(size)), logger);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser.h b/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser.h
index ae6c428dff0..7ae86c5dc78 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser.h
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PERMISSIONS_POLICY_DOCUMENT_POLICY_PARSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PERMISSIONS_POLICY_DOCUMENT_POLICY_PARSER_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/permissions_policy/document_policy.h"
#include "third_party/blink/public/common/permissions_policy/document_policy_features.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser_test.cc b/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser_test.cc
index 6a9e70e7667..ceb621ce577 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/document_policy_parser_test.cc
@@ -476,7 +476,7 @@ TEST_P(DocumentPolicyParserTest, ParseResultShouldMatch) {
ASSERT_EQ(actual_messages.size(), expected_messages.size())
<< "message count should match";
- for (size_t i = 0; i < expected_messages.size(); ++i) {
+ for (wtf_size_t i = 0; i < expected_messages.size(); ++i) {
const auto& actual_message = actual_messages[i];
const MessageForTest& expected_message = expected_messages[i];
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/feature_policy_fuzzer.cc b/chromium/third_party/blink/renderer/core/permissions_policy/feature_policy_fuzzer.cc
index f3185965923..d7398dba0cc 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/feature_policy_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/feature_policy_fuzzer.cc
@@ -21,6 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
scoped_refptr<const blink::SecurityOrigin> origin =
blink::SecurityOrigin::CreateFromString("https://example.com/");
blink::PermissionsPolicyParser::ParseHeader(
- WTF::String(data, size), g_empty_string, origin.get(), logger, logger);
+ WTF::String(data, static_cast<wtf_size_t>(size)), g_empty_string,
+ origin.get(), logger, logger);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h b/chromium/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h
index 77e0b1f930a..080e98a021b 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h
@@ -20,6 +20,9 @@ class LayoutAnimationsPolicy {
DISALLOW_NEW();
public:
+ LayoutAnimationsPolicy(const LayoutAnimationsPolicy&) = delete;
+ LayoutAnimationsPolicy& operator=(const LayoutAnimationsPolicy&) = delete;
+
// Returns a set of the CSS properties which are affected by the permissions
// policy 'layout-animations'.
static const HashSet<const CSSProperty*>& AffectedCSSProperties();
@@ -34,8 +37,6 @@ class LayoutAnimationsPolicy {
private:
LayoutAnimationsPolicy();
-
- DISALLOW_COPY_AND_ASSIGN(LayoutAnimationsPolicy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_attr_fuzzer.cc b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_attr_fuzzer.cc
index ff08d3e28a5..74347b9e417 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_attr_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_attr_fuzzer.cc
@@ -23,6 +23,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
scoped_refptr<const blink::SecurityOrigin> child_origin =
blink::SecurityOrigin::CreateFromString("https://example.net/");
blink::PermissionsPolicyParser::ParseAttribute(
- WTF::String(data, size), parent_origin.get(), child_origin.get(), logger);
+ WTF::String(data, static_cast<wtf_size_t>(size)), parent_origin.get(),
+ child_origin.get(), logger);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
index 66327a81dca..52554decdff 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
@@ -28,6 +28,27 @@
feature_default: {
default: "EnableForSelf",
valid_values: ["EnableForAll", "EnableForSelf"]
+ },
+
+ // "default_value_behind_flag" specifies default_value override values
+ // based on different runtime flags set.
+ //
+ // When multiple flags are set, default_value correspond to the first
+ // flag in the list will be used, e.g.
+ // default_value_behind_flag: [
+ // ["A", "EnableForSelf"],
+ // ["B", "EnableForAll"],
+ // ]
+ // "EnableForSelf" will be used as default value when both flag A and B are set.
+ //
+ // Note: the runtime flags here refer to features defined in
+ // "third_party/blink/public/common/features.h", instead of those defined in
+ // "runtime_enabled_features.json5" because the latter is only available
+ // on renderer side, while default_value is needed from browser side as
+ // well.
+ default_value_behind_flag: {
+ default: [],
+ valid_type: "list",
}
},
@@ -96,9 +117,17 @@
depends_on: ["FeaturePolicyForClientHints"],
},
{
+ name: "ClientHintUABitness",
+ permissions_policy_name: "ch-ua-bitness",
+ depends_on: ["FeaturePolicyForClientHints"],
+ },
+ {
name: "ClientHintUAPlatform",
permissions_policy_name: "ch-ua-platform",
depends_on: ["FeaturePolicyForClientHints"],
+ default_value_behind_flag: [
+ ["UACHPlatformEnabledByDefault", "EnableForAll"],
+ ],
},
{
name: "ClientHintUAModel",
@@ -122,6 +151,11 @@
depends_on: ["FeaturePolicyForClientHints"],
},
{
+ name: "ClientHintUAReduced",
+ permissions_policy_name: "ch-ua-reduced",
+ depends_on: ["FeaturePolicyForClientHints"],
+ },
+ {
name: "ClientHintViewportWidth",
permissions_policy_name: "ch-viewport-width",
depends_on: ["FeaturePolicyForClientHints"],
@@ -157,7 +191,6 @@
{
name: "DisplayCapture",
permissions_policy_name: "display-capture",
- depends_on: ["GetCurrentBrowsingContextMedia"],
},
{
name: "DocumentDomain",
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_fuzzer.cc b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_fuzzer.cc
index 1a3c3eeb491..8bb1c9ccefb 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_fuzzer.cc
@@ -21,6 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
scoped_refptr<const blink::SecurityOrigin> origin =
blink::SecurityOrigin::CreateFromString("https://example.com/");
blink::PermissionsPolicyParser::ParseHeader(
- g_empty_string, WTF::String(data, size), origin.get(), logger, logger);
+ g_empty_string, WTF::String(data, static_cast<unsigned>(size)),
+ origin.get(), logger, logger);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.cc b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.cc
index 51900f5ab1c..e30b29029ba 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.cc
@@ -11,6 +11,7 @@
#include "net/http/structured_headers.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
@@ -18,6 +19,7 @@
#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/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "url/origin.h"
@@ -48,7 +50,7 @@ class ParsedFeaturePolicies final
1) {}
bool Observed(mojom::blink::PermissionsPolicyFeature feature) {
- size_t feature_index = static_cast<size_t>(feature);
+ wtf_size_t feature_index = static_cast<wtf_size_t>(feature);
if (policies_[feature_index])
return true;
policies_[feature_index] = true;
@@ -131,6 +133,7 @@ class ParsingContext {
ParsedAllowlist ParseAllowlist(const Vector<String>& origin_strings);
void ReportFeatureUsage(mojom::blink::PermissionsPolicyFeature feature);
+ void ReportFeatureUsageLegacy(mojom::blink::PermissionsPolicyFeature feature);
// This function should be called after Allowlist Histograms related flags
// have been captured.
@@ -147,6 +150,9 @@ class ParsingContext {
scoped_refptr<const SecurityOrigin> self_origin_;
scoped_refptr<const SecurityOrigin> src_origin_;
const FeatureNameMap& feature_names_;
+ // `execution_context_` is used for reporting various WebFeatures
+ // during the parsing process.
+ // `execution_context_` should only be `nullptr` in tests.
ExecutionContext* execution_context_;
// Flags for the types of items which can be used in allowlists.
@@ -171,7 +177,9 @@ bool FeatureObserver::FeatureObserved(
}
}
-void ParsingContext::ReportFeatureUsage(
+// TODO: Remove this function once we verified the new histogram counts
+// are consistent with old ones.
+void ParsingContext::ReportFeatureUsageLegacy(
mojom::blink::PermissionsPolicyFeature feature) {
if (src_origin_) {
if (!execution_context_ ||
@@ -184,6 +192,20 @@ void ParsingContext::ReportFeatureUsage(
}
}
+void ParsingContext::ReportFeatureUsage(
+ mojom::blink::PermissionsPolicyFeature feature) {
+ if (!execution_context_ || !execution_context_->IsWindow())
+ return;
+
+ LocalDOMWindow* local_dom_window = To<LocalDOMWindow>(execution_context_);
+
+ auto usage_type =
+ src_origin_ ? UseCounterImpl::PermissionsPolicyUsageType::kIframeAttribute
+ : UseCounterImpl::PermissionsPolicyUsageType::kHeader;
+
+ local_dom_window->CountPermissionsPolicyUsage(feature, usage_type);
+}
+
void ParsingContext::RecordAllowlistTypeUsage(size_t origin_count) {
// Record the type of allowlist used.
if (origin_count == 0) {
@@ -391,6 +413,7 @@ ParsedPermissionsPolicy ParsingContext::ParseIR(
ParseFeature(declaration_node);
if (parsed_feature) {
ReportFeatureUsage(parsed_feature->feature);
+ ReportFeatureUsageLegacy(parsed_feature->feature);
parsed_policy.push_back(*parsed_feature);
}
}
@@ -562,18 +585,30 @@ ParsedPermissionsPolicy PermissionsPolicyParser::ParseHeader(
observer.FeatureObserved(policy_declaration.feature);
DCHECK(!feature_observed);
}
+
+ std::vector<std::string> overlap_features;
+
for (const auto& policy_declaration : feature_policy) {
if (!observer.FeatureObserved(policy_declaration.feature)) {
permissions_policy.push_back(policy_declaration);
} else {
- feature_policy_logger.Warn(String::Format(
- "Feature %s has been specified in both Feature-Policy and "
- "Permissions-Policy header. Value defined in Permissions-Policy "
- "header will be used.",
- GetNameForFeature(policy_declaration.feature).Ascii().c_str()));
+ overlap_features.push_back(
+ GetNameForFeature(policy_declaration.feature).Ascii().c_str());
}
}
+ if (!overlap_features.empty()) {
+ std::ostringstream features_stream;
+ std::copy(overlap_features.begin(), overlap_features.end() - 1,
+ std::ostream_iterator<std::string>(features_stream, ", "));
+ features_stream << overlap_features.back();
+
+ feature_policy_logger.Warn(String::Format(
+ "Some features are specified in both Feature-Policy and "
+ "Permissions-Policy header: %s. Values defined in Permissions-Policy "
+ "header will be used.",
+ features_stream.str().c_str()));
+ }
return permissions_policy;
}
diff --git a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
index 5f66b9a56da..617dbe839a0 100644
--- a/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
+++ b/chromium/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
@@ -200,7 +200,7 @@ class PermissionsPolicyParserParsingTest
const Vector<PolicyParserMessageBuffer::Message>& actual,
const std::vector<String> expected) {
ASSERT_EQ(actual.size(), expected.size());
- for (size_t i = 0; i < actual.size(); ++i) {
+ for (wtf_size_t i = 0; i < actual.size(); ++i) {
EXPECT_EQ(actual[i].content, expected[i]);
}
}
@@ -644,6 +644,45 @@ TEST_F(PermissionsPolicyParserParsingTest,
}
TEST_F(PermissionsPolicyParserParsingTest,
+ OverlapDeclarationSingleWarningMessage) {
+ PolicyParserMessageBuffer feature_policy_logger("");
+ PolicyParserMessageBuffer permissions_policy_logger("");
+
+ CheckParsedPolicy(
+ PermissionsPolicyParser::ParseHeader(
+ "geolocation 'self', fullscreen 'self'" /* feature_policy_header */
+ ,
+ "geolocation=*, fullscreen=*" /* permissions_policy_header */
+ ,
+ origin_a_.get(), feature_policy_logger, permissions_policy_logger,
+ nullptr /* context */
+ ),
+ {
+ {
+ mojom::blink::PermissionsPolicyFeature::kGeolocation,
+ /* matches_all_origins */ true,
+ /* matches_opaque_src */ true,
+ {},
+ },
+ {
+ mojom::blink::PermissionsPolicyFeature::kFullscreen,
+ /* matches_all_origins */ true,
+ /* matches_opaque_src */ true,
+ {},
+ },
+ });
+
+ CheckConsoleMessage(feature_policy_logger.GetMessages(),
+ {
+ "Some features are specified in both Feature-Policy "
+ "and Permissions-Policy header: geolocation, "
+ "fullscreen. Values defined in "
+ "Permissions-Policy header will be used.",
+ });
+ CheckConsoleMessage(permissions_policy_logger.GetMessages(), {});
+}
+
+TEST_F(PermissionsPolicyParserParsingTest,
FeaturePolicyHeaderPermissionsPolicyHeaderCoExistSeparateLogger) {
PolicyParserMessageBuffer feature_policy_logger("Feature Policy: ");
PolicyParserMessageBuffer permissions_policy_logger("Permissions Policy: ");
@@ -674,8 +713,8 @@ TEST_F(PermissionsPolicyParserParsingTest,
feature_policy_logger.GetMessages(),
{
"Feature Policy: Unrecognized feature: 'worse-feature'.",
- "Feature Policy: Feature geolocation has been specified in both "
- "Feature-Policy and Permissions-Policy header. Value defined in "
+ "Feature Policy: Some features are specified in both Feature-Policy "
+ "and Permissions-Policy header: geolocation. Values defined in "
"Permissions-Policy header will be used.",
});
CheckConsoleMessage(
@@ -1300,13 +1339,16 @@ TEST_F(FeaturePolicyMutationTest, TestAllowNewFeatureUnconditionally) {
}
class PermissionsPolicyViolationHistogramTest : public testing::Test {
+ public:
+ PermissionsPolicyViolationHistogramTest(
+ const PermissionsPolicyViolationHistogramTest&) = delete;
+ PermissionsPolicyViolationHistogramTest& operator=(
+ const PermissionsPolicyViolationHistogramTest&) = delete;
+
protected:
PermissionsPolicyViolationHistogramTest() = default;
~PermissionsPolicyViolationHistogramTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PermissionsPolicyViolationHistogramTest);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/probe/BUILD.gn b/chromium/third_party/blink/renderer/core/probe/BUILD.gn
index 6944d32431b..0eb50432907 100644
--- a/chromium/third_party/blink/renderer/core/probe/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/probe/BUILD.gn
@@ -48,7 +48,7 @@ blink_core_sources("probe") {
deps = [
":instrumentation_probes",
"//skia",
- "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
+ "//third_party/blink/renderer/bindings/core/v8:generated",
"//third_party/blink/renderer/core:all_generators",
"//third_party/blink/renderer/platform:make_platform_generated",
"//third_party/blink/renderer/platform/wtf",
diff --git a/chromium/third_party/blink/renderer/core/probe/OWNERS b/chromium/third_party/blink/renderer/core/probe/OWNERS
index a5b1e783065..3e398966f97 100644
--- a/chromium/third_party/blink/renderer/core/probe/OWNERS
+++ b/chromium/third_party/blink/renderer/core/probe/OWNERS
@@ -1,2 +1 @@
-alph@chromium.org
caseq@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/probe/core_probes.json5 b/chromium/third_party/blink/renderer/core/probe/core_probes.json5
index 30d507253f4..2f98fd616d7 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.json5
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.json5
@@ -88,6 +88,7 @@
InspectorDOMDebuggerAgent: {
probes: [
"BreakableLocation",
+ "CharacterDataModified",
"DidCreateCanvasContext",
"DidFireWebGLError",
"DidFireWebGLErrorOrWarning",
@@ -99,7 +100,6 @@
"UserCallback",
"WillInsertDOMNode",
"WillModifyDOMAttr",
- "WillRemoveDOMNode",
"WillSendXMLHttpOrFetchNetworkRequest",
"DidCreateAudioContext",
"DidCloseAudioContext",
@@ -151,7 +151,6 @@
"DidChangeResourcePriority",
"DidCloseWebSocket",
"DidCommitLoad",
- "DidCreateWebSocket",
"DidFailLoading",
"DidFinishLoading",
"DidFinishXHR",
@@ -176,6 +175,7 @@
"WebTransportCreated",
"WebTransportConnectionEstablished",
"WebTransportClosed",
+ "WillCreateWebSocket",
"WillDispatchEventSourceEvent",
"WillLoadXHR",
"WillSendEventSourceRequest",
diff --git a/chromium/third_party/blink/renderer/core/probe/core_probes.pidl b/chromium/third_party/blink/renderer/core/probe/core_probes.pidl
index c2cf11a618a..21d03f34580 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.pidl
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -126,7 +126,7 @@ interface CoreProbes {
void FrameRequestedNavigation(LocalFrame*, Frame* target_frame, const KURL& url, ClientNavigationReason reason, NavigationPolicy policy);
void FrameScheduledNavigation([Keep] LocalFrame*, const KURL& url, base::TimeDelta delay, ClientNavigationReason reason);
void FrameClearedScheduledNavigation([Keep] LocalFrame*);
- void DidCreateWebSocket([Keep] ExecutionContext*, uint64_t identifier, const KURL& request_url, const String& protocol);
+ void WillCreateWebSocket([Keep] ExecutionContext*, uint64_t identifier, const KURL& request_url, const String& protocol, absl::optional<base::UnguessableToken>* devtools_token);
void WillSendWebSocketHandshakeRequest([Keep] ExecutionContext*, uint64_t identifier, network::mojom::blink::WebSocketHandshakeRequest* request);
void DidReceiveWebSocketHandshakeResponse([Keep] ExecutionContext*, uint64_t identifier, network::mojom::blink::WebSocketHandshakeRequest* request, network::mojom::blink::WebSocketHandshakeResponse* response);
void DidCloseWebSocket([Keep] ExecutionContext*, uint64_t identifier);
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 4b4d3ffafab..b0555c36a56 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
@@ -196,7 +196,7 @@ void ResizeObserver::ClearObservations() {
}
bool ResizeObserver::HasPendingActivity() const {
- return !observations_.IsEmpty();
+ return !active_observations_.IsEmpty();
}
void ResizeObserver::Trace(Visitor* visitor) const {
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 765f5068f00..e028a79735d 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
@@ -76,9 +76,7 @@ class CORE_EXPORT ResizeObserver final
const Member<V8ResizeObserverCallback> callback_;
const Member<Delegate> delegate_;
- // List of Elements we are observing. These Elements make the ResizeObserver
- // and most-importantly |callback_| alive. If |observations_| is empty, no one
- // is performing wrapper-tracing and |callback_| might already be gone.
+ // List of Elements we are observing
ObservationList observations_;
// List of elements that have changes
HeapVector<Member<ResizeObservation>> active_observations_;
diff --git a/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc b/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
index 27fa2a8550a..348c2bd35df 100644
--- a/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
+++ b/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
@@ -38,6 +38,7 @@
#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/graphics/compositing/paint_artifact_compositor.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
#include "third_party/blink/renderer/platform/testing/find_cc_layer.h"
@@ -1169,6 +1170,11 @@ TEST_P(FrameThrottlingTest, ThrottleInnerCompositedLayer) {
EXPECT_TRUE(frame_element->contentDocument()->View()->CanThrottleRendering());
// The inner div should still be composited.
EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "div").size());
+ // The owner document may included stale painted output for the iframe in its
+ // cache; make sure it gets invalidated.
+ EXPECT_FALSE(To<LayoutBoxModelObject>(frame_element->GetLayoutObject())
+ ->Layer()
+ ->IsValid());
// If painting of the iframe is throttled, we should only receive drawing
// commands for the main frame.
@@ -1187,14 +1193,8 @@ TEST_P(FrameThrottlingTest, ThrottleInnerCompositedLayer) {
// And a throttled full lifecycle update.
UpdateAllLifecyclePhases();
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // Leave the composited layer of the inner div as-is because we don't
- // repaint it.
- EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "div").size());
- } else {
- // The inner div is no longer composited.
- EXPECT_EQ(0u, CcLayersByDOMElementId(root_layer, "div").size());
- }
+ // The inner div is no longer composited.
+ EXPECT_EQ(0u, CcLayersByDOMElementId(root_layer, "div").size());
auto commands_throttled1 = CompositeFrame();
EXPECT_LT(commands_throttled1.DrawCount(), full_draw_count);
@@ -1204,6 +1204,9 @@ TEST_P(FrameThrottlingTest, ThrottleInnerCompositedLayer) {
CompositeFrame();
EXPECT_FALSE(
frame_element->contentDocument()->View()->CanThrottleRendering());
+ EXPECT_FALSE(To<LayoutBoxModelObject>(frame_element->GetLayoutObject())
+ ->Layer()
+ ->IsValid());
auto commands_not_throttled1 = CompositeFrame();
// The inner div is still not composited.
EXPECT_EQ(0u, CcLayersByDOMElementId(root_layer, "div").size());
@@ -1786,6 +1789,60 @@ TEST_P(FrameThrottlingTest, LifecycleThrottledFrameNeedsRepaint) {
GetDocument().GetLayoutView()->Layer()->SelfOrDescendantNeedsRepaint());
}
+namespace {
+
+class TestEventListener : public NativeEventListener {
+ public:
+ TestEventListener() = default;
+ void Invoke(ExecutionContext*, Event*) final { count_++; }
+ int GetCallCount() const { return count_; }
+
+ private:
+ int count_ = 0;
+};
+
+} // namespace
+
+TEST_P(FrameThrottlingTest, ThrottledIframeGetsResizeEvents) {
+ ScopedThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframesForTest
+ scoped_flag_override(true);
+ WebView().GetSettings()->SetJavaScriptEnabled(true);
+
+ // Set up child-iframe that can be throttled and make sure it still gets a
+ // resize event when it loads.
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest frame_resource("https://sub.example.com/iframe.html", "text/html");
+ LoadURL("https://example.com/");
+
+ // The frame is initially throttled.
+ main_resource.Complete(R"HTML(
+ <iframe id="frame" src="https://sub.example.com/iframe.html"
+ style="margin-top: 2000px"></iframe>
+ )HTML");
+ frame_resource.Complete(R"HTML(
+ Hello, world!
+ )HTML");
+
+ // Load and verify throttling.
+ auto* frame_element =
+ To<HTMLIFrameElement>(GetDocument().getElementById("frame"));
+ auto* listener = MakeGarbageCollected<TestEventListener>();
+ frame_element->contentWindow()->addEventListener("resize", listener);
+ EXPECT_EQ(listener->GetCallCount(), 0);
+ CompositeFrame();
+ EXPECT_TRUE(frame_element->contentDocument()->View()->CanThrottleRendering());
+ EXPECT_EQ(listener->GetCallCount(), 1);
+
+ // Composite a second frame to pick up the resize.
+ frame_element->SetInlineStyleProperty(CSSPropertyID::kWidth, "200px");
+ // This should trigger resize event without clearing NeedsBeginMainFrame().
+ GetDocument().View()->UpdateAllLifecyclePhasesForTest();
+ CompositeFrame();
+ EXPECT_EQ(listener->GetCallCount(), 2);
+
+ frame_element->contentWindow()->removeEventListener("resize", listener);
+}
+
TEST_P(FrameThrottlingTest, AncestorTouchActionAndWheelEventHandlers) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(::features::kWheelEventRegions);
diff --git a/chromium/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc b/chromium/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc
index c3fe4067960..a56367ac424 100644
--- a/chromium/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc
+++ b/chromium/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc
@@ -145,84 +145,6 @@ TEST_F(SchedulingAffectingFeaturesTest, CacheControl_Navigation) {
testing::UnorderedElementsAre());
}
-TEST_F(SchedulingAffectingFeaturesTest, EventListener_PageShow) {
- SimRequest main_resource("https://foo.com/", "text/html");
- LoadURL("https://foo.com/");
- main_resource.Complete(
- "<script>"
- " window.addEventListener(\"pageshow\", () => {}); "
- "</script>");
-
- EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
- testing::UnorderedElementsAre(
- SchedulingPolicy::Feature::kPageShowEventListener));
-}
-
-TEST_F(SchedulingAffectingFeaturesTest, EventListener_PageHide) {
- SimRequest main_resource("https://foo.com/", "text/html");
- LoadURL("https://foo.com/");
- main_resource.Complete(
- "<script>"
- " window.addEventListener(\"pagehide\", () => {}); "
- "</script>");
-
- EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
- testing::UnorderedElementsAre(
- SchedulingPolicy::Feature::kPageHideEventListener));
-}
-
-TEST_F(SchedulingAffectingFeaturesTest, EventListener_BeforeUnload) {
- SimRequest main_resource("https://foo.com/", "text/html");
- LoadURL("https://foo.com/");
- main_resource.Complete(
- "<script>"
- " window.addEventListener(\"beforeunload\", () => {}); "
- "</script>");
-
- EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
- testing::UnorderedElementsAre(
- SchedulingPolicy::Feature::kBeforeUnloadEventListener));
-}
-
-TEST_F(SchedulingAffectingFeaturesTest, EventListener_Unload) {
- SimRequest main_resource("https://foo.com/", "text/html");
- LoadURL("https://foo.com/");
- main_resource.Complete(
- "<script>"
- " window.addEventListener(\"unload\", () => {}); "
- "</script>");
-
- EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
- testing::UnorderedElementsAre(
- SchedulingPolicy::Feature::kUnloadEventListener));
-}
-
-TEST_F(SchedulingAffectingFeaturesTest, EventListener_Freeze) {
- SimRequest main_resource("https://foo.com/", "text/html");
- LoadURL("https://foo.com/");
- main_resource.Complete(
- "<script>"
- " window.addEventListener(\"freeze\", () => {}); "
- "</script>");
-
- EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
- testing::UnorderedElementsAre(
- SchedulingPolicy::Feature::kFreezeEventListener));
-}
-
-TEST_F(SchedulingAffectingFeaturesTest, EventListener_Resume) {
- SimRequest main_resource("https://foo.com/", "text/html");
- LoadURL("https://foo.com/");
- main_resource.Complete(
- "<script>"
- " window.addEventListener(\"resume\", () => {}); "
- "</script>");
-
- EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
- testing::UnorderedElementsAre(
- SchedulingPolicy::Feature::kResumeEventListener));
-}
-
TEST_F(SchedulingAffectingFeaturesTest, Plugins) {
class PluginCreatingWebFrameClient
: public frame_test_helpers::TestWebFrameClient {
diff --git a/chromium/third_party/blink/renderer/core/script/OWNERS b/chromium/third_party/blink/renderer/core/script/OWNERS
index ec3c853c9fc..a6bb5f0c23e 100644
--- a/chromium/third_party/blink/renderer/core/script/OWNERS
+++ b/chromium/third_party/blink/renderer/core/script/OWNERS
@@ -1,4 +1,3 @@
dom@chromium.org
hiroshige@chromium.org
-jbroman@chromium.org
kouhei@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/script/build.gni b/chromium/third_party/blink/renderer/core/script/build.gni
index 78e233b14d0..e45ee3c3539 100644
--- a/chromium/third_party/blink/renderer/core/script/build.gni
+++ b/chromium/third_party/blink/renderer/core/script/build.gni
@@ -23,6 +23,8 @@ blink_core_sources_script = [
"ignore_destructive_write_count_incrementer.h",
"import_map.cc",
"import_map.h",
+ "import_map_error.cc",
+ "import_map_error.h",
"js_module_script.cc",
"js_module_script.h",
"modulator.cc",
diff --git a/chromium/third_party/blink/renderer/core/script/classic_script.cc b/chromium/third_party/blink/renderer/core/script/classic_script.cc
index 702f35b4f10..53b3243ee85 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/classic_script.cc
@@ -63,11 +63,14 @@ v8::Local<v8::Value> ClassicScript::RunScriptInIsolatedWorldAndReturnValue(
// Unlike other methods, RunScriptInIsolatedWorldAndReturnValue()'s
// default policy is kExecuteScriptWhenScriptsDisabled, to keep existing
// behavior.
+ ScriptState* script_state = nullptr;
+ if (window->GetFrame()) {
+ script_state = ToScriptState(window->GetFrame(),
+ *DOMWrapperWorld::EnsureIsolatedWorld(
+ ToIsolate(window->GetFrame()), world_id));
+ }
ScriptEvaluationResult result = RunScriptOnScriptStateAndReturnValue(
- ToScriptState(window->GetFrame(),
- *DOMWrapperWorld::EnsureIsolatedWorld(
- ToIsolate(window->GetFrame()), world_id)),
- ExecuteScriptPolicy::kExecuteScriptWhenScriptsDisabled);
+ script_state, ExecuteScriptPolicy::kExecuteScriptWhenScriptsDisabled);
if (result.GetResultType() == ScriptEvaluationResult::ResultType::kSuccess)
return result.GetSuccessValue();
diff --git a/chromium/third_party/blink/renderer/core/script/detect_javascript_frameworks.cc b/chromium/third_party/blink/renderer/core/script/detect_javascript_frameworks.cc
index 0bc25d99c5b..208a0d4f361 100644
--- a/chromium/third_party/blink/renderer/core/script/detect_javascript_frameworks.cc
+++ b/chromium/third_party/blink/renderer/core/script/detect_javascript_frameworks.cc
@@ -4,30 +4,41 @@
#include "third_party/blink/renderer/core/script/detect_javascript_frameworks.h"
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.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/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "v8/include/v8.h"
namespace blink {
namespace {
+constexpr char kGatsbyId[] = "___gatsby";
+constexpr char kNextjsId[] = "__next";
+constexpr char kNextjsData[] = "__NEXT_DATA__";
+constexpr char kNuxtjsData[] = "__NUXT__";
+constexpr char kSapperData[] = "__SAPPER__";
+constexpr char kVuepressData[] = "__VUEPRESS__";
+
bool IsFrameworkVariableUsed(v8::Local<v8::Context> context,
const String& framework_variable_name) {
v8::Isolate* isolate = context->GetIsolate();
- v8::HandleScope handle_scope(isolate);
-
v8::Local<v8::Object> global = context->Global();
v8::TryCatch try_catch(isolate);
-
bool has_property;
bool succeeded =
global
->HasRealNamedProperty(
context, V8AtomicString(isolate, framework_variable_name))
.To(&has_property);
-
DCHECK(succeeded && !try_catch.HasCaught());
return has_property;
}
@@ -39,14 +50,167 @@ bool IsFrameworkIDUsed(Document& document, const AtomicString& framework_id) {
return false;
}
+void CheckForGatsby(Document& document, v8::Local<v8::Context> context) {
+ if (IsFrameworkIDUsed(document, kGatsbyId)) {
+ document.Loader()->DidObserveLoadingBehavior(
+ kLoadingBehaviorGatsbyFrameworkUsed);
+ }
+}
+
void CheckForNextJS(Document& document, v8::Local<v8::Context> context) {
- if (IsFrameworkIDUsed(document, "__next") &&
- IsFrameworkVariableUsed(context, "__NEXT_DATA__")) {
+ if (IsFrameworkIDUsed(document, kNextjsId) &&
+ IsFrameworkVariableUsed(context, kNextjsData)) {
document.Loader()->DidObserveLoadingBehavior(
LoadingBehaviorFlag::kLoadingBehaviorNextJSFrameworkUsed);
}
}
+void CheckForNuxtJS(Document& document, v8::Local<v8::Context> context) {
+ if (IsFrameworkVariableUsed(context, kNuxtjsData)) {
+ document.Loader()->DidObserveLoadingBehavior(
+ kLoadingBehaviorNuxtJSFrameworkUsed);
+ }
+}
+
+void CheckForSapper(Document& document, v8::Local<v8::Context> context) {
+ if (IsFrameworkVariableUsed(context, kSapperData)) {
+ document.Loader()->DidObserveLoadingBehavior(
+ kLoadingBehaviorSapperFrameworkUsed);
+ }
+}
+
+void CheckForVuePress(Document& document, v8::Local<v8::Context> context) {
+ if (IsFrameworkVariableUsed(context, kVuepressData)) {
+ document.Loader()->DidObserveLoadingBehavior(
+ kLoadingBehaviorVuePressFrameworkUsed);
+ }
+}
+
+inline void CheckIdMatches(Document& document,
+ int& loading_behavior_flag,
+ bool& has_nextjs_id) {
+ DEFINE_STATIC_LOCAL(AtomicString, kReactId, ("react-root"));
+ if (IsFrameworkIDUsed(document, kGatsbyId))
+ loading_behavior_flag |= kLoadingBehaviorGatsbyFrameworkUsed;
+ if (IsFrameworkIDUsed(document, kNextjsId))
+ has_nextjs_id = true;
+ if (IsFrameworkIDUsed(document, kReactId))
+ loading_behavior_flag |= kLoadingBehaviorReactFrameworkUsed;
+}
+
+inline void CheckAttributeMatches(const Element& element,
+ int& loading_behavior_flag) {
+ DEFINE_STATIC_LOCAL(QualifiedName, ng_version,
+ (g_null_atom, "ng-version", g_null_atom));
+ DEFINE_STATIC_LOCAL(QualifiedName, data_reactroot,
+ (g_null_atom, "data-reactroot", g_null_atom));
+ static constexpr char kSvelte[] = "svelte-";
+ if (element.FastHasAttribute(ng_version))
+ loading_behavior_flag |= kLoadingBehaviorAngularFrameworkUsed;
+ if (element.FastHasAttribute(data_reactroot))
+ loading_behavior_flag |= kLoadingBehaviorReactFrameworkUsed;
+ if (element.GetClassAttribute().StartsWith(kSvelte))
+ loading_behavior_flag |= kLoadingBehaviorSvelteFrameworkUsed;
+}
+
+inline void CheckPropertyMatches(Element& element,
+ DOMDataStore& dom_data_store,
+ v8::Local<v8::Context> context,
+ v8::Isolate* isolate,
+ int& loading_behavior_flag) {
+ v8::Local<v8::Object> v8_element = dom_data_store.Get(&element, isolate);
+ if (v8_element.IsEmpty())
+ return;
+ v8::Local<v8::Array> property_names;
+ if (!v8_element->GetOwnPropertyNames(context).ToLocal(&property_names))
+ return;
+
+ DEFINE_STATIC_LOCAL(AtomicString, vue_string, ("__vue__"));
+ DEFINE_STATIC_LOCAL(AtomicString, vue_app_string, ("__vue_app__"));
+ DEFINE_STATIC_LOCAL(AtomicString, k_string, ("__k"));
+ DEFINE_STATIC_LOCAL(AtomicString, reactRootContainer_string,
+ ("_reactRootContainer"));
+ DEFINE_STATIC_LOCAL(AtomicString, reactListening_string, ("_reactListening"));
+ DEFINE_STATIC_LOCAL(AtomicString, reactFiber_string, ("__reactFiber"));
+ for (uint32_t i = 0; i < property_names->Length(); ++i) {
+ v8::Local<v8::Value> key;
+ if (!property_names->Get(context, i).ToLocal(&key) || !key->IsString()) {
+ continue;
+ }
+ AtomicString key_value = ToCoreAtomicString(key.As<v8::String>());
+ if (key_value == vue_string || key_value == vue_app_string) {
+ loading_behavior_flag |= kLoadingBehaviorVueFrameworkUsed;
+ } else if (key_value == k_string) {
+ loading_behavior_flag |= kLoadingBehaviorPreactFrameworkUsed;
+ } else if (key_value == reactRootContainer_string) {
+ loading_behavior_flag |= kLoadingBehaviorReactFrameworkUsed;
+ } else if (key_value.StartsWith(reactListening_string) ||
+ key_value.StartsWith(reactFiber_string)) {
+ loading_behavior_flag |= kLoadingBehaviorReactFrameworkUsed;
+ }
+ }
+}
+
+inline void CheckGlobalPropertyMatches(v8::Local<v8::Context> context,
+ v8::Isolate* isolate,
+ int& loading_behavior_flag,
+ bool& has_nextjs_id) {
+ static constexpr char kVueData[] = "Vue";
+ static constexpr char kReactData[] = "React";
+ if (has_nextjs_id && IsFrameworkVariableUsed(context, kNextjsData))
+ loading_behavior_flag |= kLoadingBehaviorNextJSFrameworkUsed;
+ if (IsFrameworkVariableUsed(context, kNuxtjsData))
+ loading_behavior_flag |= kLoadingBehaviorNuxtJSFrameworkUsed;
+ if (IsFrameworkVariableUsed(context, kSapperData))
+ loading_behavior_flag |= kLoadingBehaviorSapperFrameworkUsed;
+ if (IsFrameworkVariableUsed(context, kVuepressData))
+ loading_behavior_flag |= kLoadingBehaviorVuePressFrameworkUsed;
+ if (IsFrameworkVariableUsed(context, kVueData))
+ loading_behavior_flag |= kLoadingBehaviorVueFrameworkUsed;
+ // TODO(npm): Add check for window.React.Component, not just window.React.
+ if (IsFrameworkVariableUsed(context, kReactData))
+ loading_behavior_flag |= kLoadingBehaviorReactFrameworkUsed;
+}
+
+void DidObserveLoadingBehaviors(Document& document, int loading_behavior_flag) {
+ // TODO(npm): ideally we'd be able to surface multiple loading behaviors to
+ // the document loader at once.
+ static constexpr LoadingBehaviorFlag flags[] = {
+ kLoadingBehaviorAngularFrameworkUsed, kLoadingBehaviorGatsbyFrameworkUsed,
+ kLoadingBehaviorNextJSFrameworkUsed, kLoadingBehaviorNextJSFrameworkUsed,
+ kLoadingBehaviorNuxtJSFrameworkUsed, kLoadingBehaviorPreactFrameworkUsed,
+ kLoadingBehaviorReactFrameworkUsed, kLoadingBehaviorSapperFrameworkUsed,
+ kLoadingBehaviorSvelteFrameworkUsed, kLoadingBehaviorVueFrameworkUsed,
+ kLoadingBehaviorVuePressFrameworkUsed};
+ for (LoadingBehaviorFlag flag : flags) {
+ if (loading_behavior_flag & flag) {
+ document.Loader()->DidObserveLoadingBehavior(flag);
+ }
+ }
+}
+
+void TraverseTreeForFrameworks(Document& document,
+ v8::Local<v8::Context> context) {
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::TryCatch try_catch(isolate);
+ int loading_behavior_flag = kLoadingBehaviorNone;
+ bool has_nextjs_id = false;
+ if (!document.documentElement())
+ return;
+ DOMDataStore& dom_data_store = DOMWrapperWorld::MainWorld().DomDataStore();
+ for (Element& element :
+ ElementTraversal::InclusiveDescendantsOf(*document.documentElement())) {
+ CheckAttributeMatches(element, loading_behavior_flag);
+ CheckPropertyMatches(element, dom_data_store, context, isolate,
+ loading_behavior_flag);
+ }
+ CheckIdMatches(document, loading_behavior_flag, has_nextjs_id);
+ CheckGlobalPropertyMatches(context, isolate, loading_behavior_flag,
+ has_nextjs_id);
+ DCHECK(!try_catch.HasCaught());
+ DidObserveLoadingBehaviors(document, loading_behavior_flag);
+}
+
} // namespace
void DetectJavascriptFrameworksOnLoad(Document& document) {
@@ -72,7 +236,15 @@ void DetectJavascriptFrameworksOnLoad(Document& document) {
ScriptState::Scope scope(script_state);
v8::Local<v8::Context> context = script_state->GetContext();
- CheckForNextJS(document, context);
+ if (base::FeatureList::IsEnabled(features::kReportAllJavascriptFrameworks)) {
+ TraverseTreeForFrameworks(document, context);
+ } else {
+ CheckForGatsby(document, context);
+ CheckForNextJS(document, context);
+ CheckForNuxtJS(document, context);
+ CheckForSapper(document, context);
+ CheckForVuePress(document, context);
+ }
}
} // namespace blink
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 a02c2198a09..2089cb1a945 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
@@ -260,7 +260,6 @@ void DynamicModuleResolver::Trace(Visitor* visitor) const {
// href="https://html.spec.whatwg.org/C/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)">
void DynamicModuleResolver::ResolveDynamically(
const ModuleRequest& module_request,
- const KURL& referrer_resource_url,
const ReferrerScriptInfo& referrer_info,
ScriptPromiseResolver* promise_resolver) {
DCHECK(modulator_->GetScriptState()->GetIsolate()->InContext())
@@ -273,11 +272,6 @@ void DynamicModuleResolver::ResolveDynamically(
// <spec step="4.3">Set base URL to referencing script's base URL.</spec>
KURL base_url = referrer_info.BaseURL();
if (base_url.IsNull()) {
- // ReferrerScriptInfo::BaseURL returns null if it should defer to referrer
- // resource url.
- base_url = referrer_resource_url;
- }
- if (base_url.IsNull()) {
// The case where "referencing script" doesn't exist.
//
// <spec step="1">Let settings object be the current settings object.</spec>
@@ -340,29 +334,6 @@ void DynamicModuleResolver::ResolveDynamically(
return;
}
- switch (referrer_info.GetBaseUrlSource()) {
- case ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSSameOrigin:
- if (!modulator_
- ->ResolveModuleSpecifier(module_request.specifier, BlankURL())
- .IsValid()) {
- UseCounter::Count(
- ExecutionContext::From(modulator_->GetScriptState()),
- WebFeature::kDynamicImportModuleScriptRelativeClassicSameOrigin);
- }
- break;
- case ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSCrossOrigin:
- if (!modulator_
- ->ResolveModuleSpecifier(module_request.specifier, BlankURL())
- .IsValid()) {
- UseCounter::Count(
- ExecutionContext::From(modulator_->GetScriptState()),
- WebFeature::kDynamicImportModuleScriptRelativeClassicCrossOrigin);
- }
- break;
- case ReferrerScriptInfo::BaseUrlSource::kOther:
- break;
- }
-
// <spec step="4.4">Set fetch options to the descendant script fetch options
// for referencing script's fetch options.</spec>
//
@@ -397,8 +368,6 @@ void DynamicModuleResolver::ResolveDynamically(
// highly discouraged since it breaks layering. Rewrite this.
auto* execution_context =
ExecutionContext::From(modulator_->GetScriptState());
- if (auto* scope = DynamicTo<WorkerGlobalScope>(*execution_context))
- scope->EnsureFetcher();
modulator_->FetchTree(url, module_type, execution_context->Fetcher(),
mojom::blink::RequestContextType::SCRIPT,
network::mojom::RequestDestination::kScript, options,
diff --git a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h
index 1c8bd2cccc6..0a1c646de0c 100644
--- a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h
+++ b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h
@@ -32,7 +32,6 @@ class CORE_EXPORT DynamicModuleResolver final
// Implements "HostImportModuleDynamically" semantics.
// Should be called w/ a valid V8 context.
void ResolveDynamically(const ModuleRequest& module_request,
- const KURL& referrer_resource_url,
const ReferrerScriptInfo& referrer_info,
ScriptPromiseResolver*);
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 ffd4f6ca9b8..ad590e0e3a6 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
@@ -39,6 +39,9 @@ const KURL TestDependencyURL() {
const KURL TestDependencyURLJSON() {
return KURL(kTestDependencyURLJSON);
}
+ReferrerScriptInfo TestReferrerScriptInfo() {
+ return ReferrerScriptInfo(TestReferrerURL(), ScriptFetchOptions());
+}
class DynamicModuleResolverTestModulator final : public DummyModulator {
public:
@@ -241,14 +244,14 @@ TEST_P(DynamicModuleResolverTest, ResolveSuccess) {
ModuleRequest module_request("./dependency.js",
TextPosition::MinimumPosition(),
Vector<ImportAssertion>());
- resolver->ResolveDynamically(module_request, TestReferrerURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, TestReferrerScriptInfo(),
+ promise_resolver);
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_FALSE(capture->WasCalled());
v8::Local<v8::Module> record = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const foo = 'hello';", TestReferrerURL());
+ scope.GetScriptState(), "export const foo = 'hello';", TestReferrerURL());
ModuleScript* module_script =
JSModuleScript::CreateForTest(modulator, record, TestDependencyURL());
EXPECT_TRUE(ModuleRecord::Instantiate(scope.GetScriptState(), record,
@@ -277,8 +280,8 @@ TEST_P(DynamicModuleResolverTest, ResolveJSONModuleSuccess) {
ImportAssertion("type", "json", TextPosition::MinimumPosition())};
ModuleRequest module_request(
"./dependency.json", TextPosition::MinimumPosition(), import_assertions);
- resolver->ResolveDynamically(module_request, TestReferrerURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, TestReferrerScriptInfo(),
+ promise_resolver);
// Instantiating and evaluating a JSON module requires a lot of
// machinery not currently available in this unit test suite. For
@@ -308,8 +311,8 @@ TEST_P(DynamicModuleResolverTest, ResolveSpecifierFailure) {
ModuleRequest module_request("invalid-specifier",
TextPosition::MinimumPosition(),
Vector<ImportAssertion>());
- resolver->ResolveDynamically(module_request, TestReferrerURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, TestReferrerScriptInfo(),
+ promise_resolver);
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_TRUE(capture->WasCalled());
@@ -338,8 +341,8 @@ TEST_P(DynamicModuleResolverTest, ResolveModuleTypeFailure) {
ImportAssertion("type", "notARealType", TextPosition::MinimumPosition())};
ModuleRequest module_request(
"./dependency.js", TextPosition::MinimumPosition(), import_assertions);
- resolver->ResolveDynamically(module_request, TestReferrerURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, TestReferrerScriptInfo(),
+ promise_resolver);
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_TRUE(capture->WasCalled());
@@ -367,8 +370,8 @@ TEST_P(DynamicModuleResolverTest, FetchFailure) {
ModuleRequest module_request("./dependency.js",
TextPosition::MinimumPosition(),
Vector<ImportAssertion>());
- resolver->ResolveDynamically(module_request, TestReferrerURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, TestReferrerScriptInfo(),
+ promise_resolver);
EXPECT_FALSE(capture->WasCalled());
@@ -400,13 +403,13 @@ TEST_P(DynamicModuleResolverTest, ExceptionThrown) {
ModuleRequest module_request("./dependency.js",
TextPosition::MinimumPosition(),
Vector<ImportAssertion>());
- resolver->ResolveDynamically(module_request, TestReferrerURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, TestReferrerScriptInfo(),
+ promise_resolver);
EXPECT_FALSE(capture->WasCalled());
v8::Local<v8::Module> record = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "throw Error('bar')", TestReferrerURL());
+ scope.GetScriptState(), "throw Error('bar')", TestReferrerURL());
ModuleScript* module_script =
JSModuleScript::CreateForTest(modulator, record, TestDependencyURL());
EXPECT_TRUE(ModuleRecord::Instantiate(scope.GetScriptState(), record,
@@ -442,14 +445,15 @@ TEST_P(DynamicModuleResolverTest, ResolveWithNullReferrerScriptSuccess) {
ModuleRequest module_request("./dependency.js",
TextPosition::MinimumPosition(),
Vector<ImportAssertion>());
- resolver->ResolveDynamically(module_request, /* null referrer */ KURL(),
- ReferrerScriptInfo(), promise_resolver);
+ resolver->ResolveDynamically(module_request, ReferrerScriptInfo(),
+ promise_resolver);
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_FALSE(capture->WasCalled());
v8::Local<v8::Module> record = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const foo = 'hello';", TestDependencyURL());
+ scope.GetScriptState(), "export const foo = 'hello';",
+ TestDependencyURL());
ModuleScript* module_script =
JSModuleScript::CreateForTest(modulator, record, TestDependencyURL());
EXPECT_TRUE(ModuleRecord::Instantiate(scope.GetScriptState(), record,
@@ -474,15 +478,13 @@ TEST_P(DynamicModuleResolverTest, ResolveWithReferrerScriptInfoBaseURL) {
auto* promise_resolver =
MakeGarbageCollected<ScriptPromiseResolver>(scope.GetScriptState());
auto* resolver = MakeGarbageCollected<DynamicModuleResolver>(modulator);
- KURL wrong_base_url("https://example.com/wrong/bar.js");
KURL correct_base_url("https://example.com/correct/baz.js");
ModuleRequest module_request("./dependency.js",
TextPosition::MinimumPosition(),
Vector<ImportAssertion>());
resolver->ResolveDynamically(
- module_request, wrong_base_url,
- ReferrerScriptInfo(correct_base_url, ScriptFetchOptions(),
- ReferrerScriptInfo::BaseUrlSource::kOther),
+ module_request,
+ ReferrerScriptInfo(correct_base_url, ScriptFetchOptions()),
promise_resolver);
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
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 4e118ab3021..577533743c4 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
@@ -611,6 +611,7 @@ void HTMLParserScriptRunner::ProcessScriptElementInternal(
}
void HTMLParserScriptRunner::Trace(Visitor* visitor) const {
+ visitor->Trace(reentry_permit_);
visitor->Trace(document_);
visitor->Trace(host_);
visitor->Trace(parser_blocking_script_);
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 1e9df70be4c..785ef3ec8b7 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
@@ -135,7 +135,7 @@ class HTMLParserScriptRunner final
PendingScript* TryTakeReadyScriptWaitingForParsing(
HeapDeque<Member<PendingScript>>* waiting_scripts);
- scoped_refptr<HTMLParserReentryPermit> reentry_permit_;
+ Member<HTMLParserReentryPermit> reentry_permit_;
Member<Document> document_;
Member<HTMLParserScriptRunnerHost> host_;
diff --git a/chromium/third_party/blink/renderer/core/script/import_map.cc b/chromium/third_party/blink/renderer/core/script/import_map.cc
index c63c448c06b..235ad39741b 100644
--- a/chromium/third_party/blink/renderer/core/script/import_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/import_map.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/script/import_map_error.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/parsed_specifier.h"
#include "third_party/blink/renderer/platform/json/json_parser.h"
@@ -131,11 +132,10 @@ KURL NormalizeValue(const String& key,
// Parse |text| as an import map. Errors (e.g. json parsing error, invalid
// keys/values, etc.) are basically ignored, except that they are reported to
// the console |logger|.
-ImportMap* ImportMap::Parse(const Modulator& modulator,
- const String& input,
+ImportMap* ImportMap::Parse(const String& input,
const KURL& base_url,
ConsoleLogger& logger,
- ScriptValue* error_to_rethrow) {
+ absl::optional<ImportMapError>* error_to_rethrow) {
DCHECK(error_to_rethrow);
// <spec step="1">Let parsed be the result of parsing JSON into Infra values
@@ -144,7 +144,8 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
if (!parsed) {
*error_to_rethrow =
- modulator.CreateSyntaxError("Failed to parse import map: invalid JSON");
+ ImportMapError(ImportMapError::Type::kSyntaxError,
+ "Failed to parse import map: invalid JSON");
return MakeGarbageCollected<ImportMap>();
}
@@ -153,7 +154,8 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
std::unique_ptr<JSONObject> parsed_map = JSONObject::From(std::move(parsed));
if (!parsed_map) {
*error_to_rethrow =
- modulator.CreateTypeError("Failed to parse import map: not an object");
+ ImportMapError(ImportMapError::Type::kTypeError,
+ "Failed to parse import map: not an object");
return MakeGarbageCollected<ImportMap>();
}
@@ -167,9 +169,10 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
// object.</spec>
JSONObject* imports = parsed_map->GetJSONObject("imports");
if (!imports) {
- *error_to_rethrow = modulator.CreateTypeError(
- "Failed to parse import map: \"imports\" "
- "top-level key must be a JSON object.");
+ *error_to_rethrow =
+ ImportMapError(ImportMapError::Type::kTypeError,
+ "Failed to parse import map: \"imports\" "
+ "top-level key must be a JSON object.");
return MakeGarbageCollected<ImportMap>();
}
@@ -189,9 +192,10 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
// indicating that the "scopes" top-level key must be a JSON object.</spec>
JSONObject* scopes = parsed_map->GetJSONObject("scopes");
if (!scopes) {
- *error_to_rethrow = modulator.CreateTypeError(
- "Failed to parse import map: \"scopes\" "
- "top-level key must be a JSON object.");
+ *error_to_rethrow =
+ ImportMapError(ImportMapError::Type::kTypeError,
+ "Failed to parse import map: \"scopes\" "
+ "top-level key must be a JSON object.");
return MakeGarbageCollected<ImportMap>();
}
@@ -216,10 +220,11 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
// potentialSpecifierMap is not a map, then throw a TypeError indicating
// that the value of the scope with prefix scopePrefix must be a JSON
// object.</spec>
- *error_to_rethrow = modulator.CreateTypeError(
+ *error_to_rethrow = ImportMapError(
+ ImportMapError::Type::kTypeError,
"Failed to parse import map: the value of the scope with prefix "
"\"" +
- entry.first + "\" must be a JSON object.");
+ entry.first + "\" must be a JSON object.");
return MakeGarbageCollected<ImportMap>();
}
diff --git a/chromium/third_party/blink/renderer/core/script/import_map.h b/chromium/third_party/blink/renderer/core/script/import_map.h
index 36535ecf1c8..bfad802538b 100644
--- a/chromium/third_party/blink/renderer/core/script/import_map.h
+++ b/chromium/third_party/blink/renderer/core/script/import_map.h
@@ -5,8 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IMPORT_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IMPORT_MAP_H_
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/import_map_error.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"
@@ -15,21 +16,19 @@
namespace blink {
class ConsoleLogger;
+class ImportMapError;
class JSONObject;
-class Modulator;
class ParsedSpecifier;
-class ScriptValue;
// Import maps.
// https://wicg.github.io/import-maps/
// https://github.com/WICG/import-maps/blob/master/spec.md
class CORE_EXPORT ImportMap final : public GarbageCollected<ImportMap> {
public:
- static ImportMap* Parse(const Modulator&,
- const String& text,
+ static ImportMap* Parse(const String& text,
const KURL& base_url,
ConsoleLogger& logger,
- ScriptValue* error_to_rethrow);
+ absl::optional<ImportMapError>* error_to_rethrow);
// <spec href="https://wicg.github.io/import-maps/#specifier-map">A specifier
// map is an ordered map from strings to resolution results.</spec>
diff --git a/chromium/third_party/blink/renderer/core/script/import_map_error.cc b/chromium/third_party/blink/renderer/core/script/import_map_error.cc
new file mode 100644
index 00000000000..3abf70ef1b9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/import_map_error.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/script/import_map_error.h"
+#include "third_party/blink/renderer/core/script/pending_import_map.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+
+namespace blink {
+
+v8::Local<v8::Value> ImportMapError::ToV8(ScriptState* script_state) {
+ v8::Isolate* isolate = script_state->GetIsolate();
+ switch (type_) {
+ case ImportMapError::Type::kTypeError:
+ return V8ThrowException::CreateTypeError(isolate, message_);
+ case ImportMapError::Type::kSyntaxError:
+ return V8ThrowException::CreateSyntaxError(isolate, message_);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/import_map_error.h b/chromium/third_party/blink/renderer/core/script/import_map_error.h
new file mode 100644
index 00000000000..3866984b335
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/import_map_error.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IMPORT_MAP_ERROR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IMPORT_MAP_ERROR_H_
+
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class ScriptState;
+
+// ImportMapError carries around the data needed to instantiate a V8 error.
+// ImportMapError enables us to decouple ImportMap implementation with V8.
+class ImportMapError final {
+ public:
+ enum class Type {
+ kTypeError,
+ kSyntaxError,
+ };
+
+ ImportMapError(Type type, String message)
+ : type_(type), message_(std::move(message)) {
+ DCHECK(!message_.IsEmpty());
+ }
+
+ ImportMapError(ImportMapError&&) = default;
+ ImportMapError& operator=(ImportMapError&&) = default;
+
+ ~ImportMapError() = default;
+
+ v8::Local<v8::Value> ToV8(ScriptState* script_state);
+
+ private:
+ Type type_;
+ String message_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IMPORT_MAP_ERROR_H_
diff --git a/chromium/third_party/blink/renderer/core/script/js_module_script.cc b/chromium/third_party/blink/renderer/core/script/js_module_script.cc
index ecd5ee7e7eb..7dd7a80eb1c 100644
--- a/chromium/third_party/blink/renderer/core/script/js_module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/js_module_script.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/script/js_module_script.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
@@ -47,7 +48,7 @@ JSModuleScript* JSModuleScript::Create(
ModuleRecordProduceCacheData* produce_cache_data = nullptr;
v8::Local<v8::Module> result = ModuleRecord::Compile(
- isolate, params, options, start_position, exception_state,
+ script_state, params, options, start_position, exception_state,
modulator->GetV8CacheOptions(), &produce_cache_data);
// CreateInternal processes Steps 4 and 8-10.
@@ -76,7 +77,7 @@ JSModuleScript* JSModuleScript::Create(
// <spec step="9">For each string requested of
// result.[[RequestedModules]]:</spec>
for (const auto& requested :
- modulator->ModuleRequestsFromModuleRecord(result)) {
+ ModuleRecord::ModuleRequests(script_state, result)) {
// <spec step="9.1">Let url be the result of resolving a module specifier
// given script's base URL and requested.</spec>
//
@@ -177,8 +178,11 @@ void JSModuleScript::ProduceCache() {
v8::Isolate* isolate = script_state->GetIsolate();
ScriptState::Scope scope(script_state);
- V8CodeCache::ProduceCache(isolate, produce_cache_data_, source_text_length_,
- SourceURL(), StartPosition());
+ ExecutionContext* execution_context =
+ ExecutionContext::From(isolate->GetCurrentContext());
+ V8CodeCache::ProduceCache(
+ isolate, ExecutionContext::GetCodeCacheHostFromContext(execution_context),
+ produce_cache_data_, source_text_length_, SourceURL(), StartPosition());
produce_cache_data_ = nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h b/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
index f545c451586..2e2f544bf12 100644
--- a/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
+++ b/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MOCK_SCRIPT_ELEMENT_BASE_H_
#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
@@ -50,6 +49,7 @@ class MockScriptElementBase : public GarbageCollected<MockScriptElementBase>,
MOCK_CONST_METHOD0(GetDocument, Document&());
MOCK_CONST_METHOD0(GetExecutionContext, ExecutionContext*());
MOCK_METHOD0(AsV8HTMLOrSVGScriptElement, V8HTMLOrSVGScriptElement*());
+ MOCK_METHOD0(GetDOMNodeId, DOMNodeId());
MOCK_METHOD1(SetScriptElementForBinding,
void(HTMLScriptElementOrSVGScriptElement&));
MOCK_CONST_METHOD0(Loader, ScriptLoader*());
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.h b/chromium/third_party/blink/renderer/core/script/modulator.h
index 531ffc241ba..2030ad3a10e 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator.h
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/import_map_error.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"
@@ -37,7 +38,6 @@ class ResourceFetcher;
class ModuleRecordResolver;
class ScriptPromiseResolver;
class ScriptState;
-class ScriptValue;
enum class ModuleType;
// A SingleModuleClient is notified when single module script node (node as in a
@@ -47,7 +47,7 @@ class CORE_EXPORT SingleModuleClient
: public GarbageCollected<SingleModuleClient>,
public NameClient {
public:
- virtual ~SingleModuleClient() = default;
+ ~SingleModuleClient() override = default;
virtual void Trace(Visitor* visitor) const {}
const char* NameInHeapSnapshot() const override {
return "SingleModuleClient";
@@ -61,7 +61,7 @@ class CORE_EXPORT SingleModuleClient
class CORE_EXPORT ModuleTreeClient : public GarbageCollected<ModuleTreeClient>,
public NameClient {
public:
- virtual ~ModuleTreeClient() = default;
+ ~ModuleTreeClient() override = default;
virtual void Trace(Visitor* visitor) const {}
const char* NameInHeapSnapshot() const override { return "ModuleTreeClient"; }
@@ -103,7 +103,7 @@ class CORE_EXPORT Modulator : public GarbageCollected<Modulator>,
public NameClient {
public:
static Modulator* From(ScriptState*);
- virtual ~Modulator();
+ ~Modulator() override;
static void SetModulator(ScriptState*, Modulator*);
static void ClearModulator(ScriptState*);
@@ -122,8 +122,6 @@ class CORE_EXPORT Modulator : public GarbageCollected<Modulator>,
// "scripting is disabled for settings's responsible browsing context"
virtual bool IsScriptingDisabled() const = 0;
- virtual bool ImportMapsEnabled() const = 0;
-
// https://html.spec.whatwg.org/C/#fetch-a-module-script-tree
// https://html.spec.whatwg.org/C/#fetch-a-module-worker-script-tree
// Note that |this| is the "module map settings object" and
@@ -176,18 +174,15 @@ class CORE_EXPORT Modulator : public GarbageCollected<Modulator>,
// https://tc39.github.io/proposal-dynamic-import/#sec-hostimportmoduledynamically
virtual void ResolveDynamically(const ModuleRequest& module_request,
- const KURL&,
const ReferrerScriptInfo&,
ScriptPromiseResolver*) = 0;
- virtual ScriptValue CreateTypeError(const String& message) const = 0;
- virtual ScriptValue CreateSyntaxError(const String& message) const = 0;
-
// Import maps. https://github.com/WICG/import-maps
// https://wicg.github.io/import-maps/#register-an-import-map
- virtual void RegisterImportMap(const ImportMap*,
- ScriptValue error_to_rethrow) = 0;
+ virtual void RegisterImportMap(
+ const ImportMap*,
+ absl::optional<ImportMapError> error_to_rethrow) = 0;
virtual const ImportMap* GetImportMapForTest() const = 0;
// https://wicg.github.io/import-maps/#document-acquiring-import-maps
@@ -210,11 +205,6 @@ class CORE_EXPORT Modulator : public GarbageCollected<Modulator>,
virtual bool HasValidContext() = 0;
- virtual ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) = 0;
-
- virtual Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) = 0;
-
virtual ModuleType ModuleTypeFromRequest(
const ModuleRequest& module_request) const = 0;
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 78a982a8004..aa90e7ff1a9 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
@@ -54,10 +54,6 @@ bool ModulatorImplBase::IsScriptingDisabled() const {
return !GetExecutionContext()->CanExecuteScripts(kAboutToExecuteScript);
}
-bool ModulatorImplBase::ImportMapsEnabled() const {
- return RuntimeEnabledFeatures::ImportMapsEnabled(GetExecutionContext());
-}
-
mojom::blink::V8CacheOptions ModulatorImplBase::GetV8CacheOptions() const {
return GetExecutionContext()->GetV8CacheOptions();
}
@@ -75,10 +71,9 @@ void ModulatorImplBase::FetchTree(
const ScriptFetchOptions& options,
ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeClient* client) {
- ModuleTreeLinker::Fetch(url, module_type,
- fetch_client_settings_object_fetcher, context_type,
- destination, options, this, custom_fetch_type,
- tree_linker_registry_, client);
+ tree_linker_registry_->Fetch(
+ url, module_type, fetch_client_settings_object_fetcher, context_type,
+ destination, options, this, custom_fetch_type, client);
}
void ModulatorImplBase::FetchDescendantsForInlineScript(
@@ -87,10 +82,9 @@ void ModulatorImplBase::FetchDescendantsForInlineScript(
mojom::blink::RequestContextType context_type,
network::mojom::RequestDestination destination,
ModuleTreeClient* client) {
- ModuleTreeLinker::FetchDescendantsForInlineScript(
+ tree_linker_registry_->FetchDescendantsForInlineScript(
module_script, fetch_client_settings_object_fetcher, context_type,
- destination, this, ModuleScriptCustomFetchType::kNone,
- tree_linker_registry_, client);
+ destination, this, ModuleScriptCustomFetchType::kNone, client);
}
void ModulatorImplBase::FetchSingle(
@@ -174,36 +168,21 @@ KURL ModulatorImplBase::ResolveModuleSpecifier(const String& specifier,
}
}
-ScriptValue ModulatorImplBase::CreateTypeError(const String& message) const {
- ScriptState::Scope scope(script_state_);
- ScriptValue error(
- script_state_->GetIsolate(),
- V8ThrowException::CreateTypeError(script_state_->GetIsolate(), message));
- return error;
-}
-
-ScriptValue ModulatorImplBase::CreateSyntaxError(const String& message) const {
- ScriptState::Scope scope(script_state_);
- ScriptValue error(script_state_->GetIsolate(),
- V8ThrowException::CreateSyntaxError(
- script_state_->GetIsolate(), message));
- return error;
-}
-
// <specdef href="https://wicg.github.io/import-maps/#register-an-import-map">
-void ModulatorImplBase::RegisterImportMap(const ImportMap* import_map,
- ScriptValue error_to_rethrow) {
+void ModulatorImplBase::RegisterImportMap(
+ const ImportMap* import_map,
+ absl::optional<ImportMapError> error_to_rethrow) {
DCHECK(import_map);
- DCHECK(ImportMapsEnabled());
// <spec step="7">If import map parse result’s error to rethrow is not null,
// then:</spec>
- if (!error_to_rethrow.IsEmpty()) {
+ if (error_to_rethrow.has_value()) {
// <spec step="7.1">Report the exception given import map parse result’s
// error to rethrow. ...</spec>
if (!IsScriptingDisabled()) {
ScriptState::Scope scope(script_state_);
- ModuleRecord::ReportException(script_state_, error_to_rethrow.V8Value());
+ ModuleRecord::ReportException(script_state_,
+ error_to_rethrow->ToV8(script_state_));
}
// <spec step="7.2">Return.</spec>
@@ -228,7 +207,6 @@ bool ModulatorImplBase::HasValidContext() {
void ModulatorImplBase::ResolveDynamically(
const ModuleRequest& module_request,
- const KURL& referrer_url,
const ReferrerScriptInfo& referrer_info,
ScriptPromiseResolver* resolver) {
String reason;
@@ -239,8 +217,8 @@ void ModulatorImplBase::ResolveDynamically(
}
UseCounter::Count(GetExecutionContext(),
WebFeature::kDynamicImportModuleScript);
- dynamic_module_resolver_->ResolveDynamically(module_request, referrer_url,
- referrer_info, resolver);
+ dynamic_module_resolver_->ResolveDynamically(module_request, referrer_info,
+ resolver);
}
// <specdef href="https://html.spec.whatwg.org/C/#hostgetimportmetaproperties">
@@ -260,22 +238,6 @@ ModuleImportMeta ModulatorImplBase::HostGetImportMetaProperties(
return ModuleImportMeta(url_string);
}
-ScriptValue ModulatorImplBase::InstantiateModule(
- v8::Local<v8::Module> module_record,
- const KURL& source_url) {
- UseCounter::Count(GetExecutionContext(),
- WebFeature::kInstantiateModuleScript);
-
- ScriptState::Scope scope(script_state_);
- return ModuleRecord::Instantiate(script_state_, module_record, source_url);
-}
-
-Vector<ModuleRequest> ModulatorImplBase::ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module> module_record) {
- ScriptState::Scope scope(script_state_);
- return ModuleRecord::ModuleRequests(script_state_, module_record);
-}
-
ModuleType ModulatorImplBase::ModuleTypeFromRequest(
const ModuleRequest& module_request) const {
String module_type_string = module_request.GetModuleTypeString();
@@ -328,7 +290,7 @@ void ModulatorImplBase::ProduceCacheModuleTree(
module_script->ProduceCache();
Vector<ModuleRequest> child_specifiers =
- ModuleRequestsFromModuleRecord(record);
+ ModuleRecord::ModuleRequests(GetScriptState(), record);
for (const auto& module_request : child_specifiers) {
KURL child_url =
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 e4bee0e15f2..a6f5cf7de85 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
@@ -6,8 +6,10 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULATOR_IMPL_BASE_H_
#include "base/single_thread_task_runner.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
+#include "third_party/blink/renderer/core/script/import_map_error.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/v8_per_isolate_data.h"
@@ -42,8 +44,6 @@ class ModulatorImplBase : public Modulator {
bool IsScriptingDisabled() const override;
- bool ImportMapsEnabled() const override;
-
mojom::blink::V8CacheOptions GetV8CacheOptions() const final;
ModuleRecordResolver* GetModuleRecordResolver() override {
@@ -78,14 +78,12 @@ class ModulatorImplBase : public Modulator {
const KURL& base_url,
String* failure_reason) final;
void ResolveDynamically(const ModuleRequest& module_request,
- const KURL&,
const ReferrerScriptInfo&,
ScriptPromiseResolver*) override;
const ImportMap* GetImportMapForTest() const final { return import_map_; }
- ScriptValue CreateTypeError(const String& message) const override;
- ScriptValue CreateSyntaxError(const String& message) const override;
- void RegisterImportMap(const ImportMap*, ScriptValue error_to_rethrow) final;
+ void RegisterImportMap(const ImportMap*,
+ absl::optional<ImportMapError> error_to_rethrow) final;
AcquiringImportMapsState GetAcquiringImportMapsState() const final {
return acquiring_import_maps_;
}
@@ -94,9 +92,6 @@ class ModulatorImplBase : public Modulator {
}
ModuleImportMeta HostGetImportMetaProperties(
v8::Local<v8::Module>) const override;
- ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) override;
- Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) override;
ModuleType ModuleTypeFromRequest(
const ModuleRequest& module_request) const override;
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 545f61e128b..a0cd1fb9e83 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map.h
+++ b/chromium/third_party/blink/renderer/core/script/module_map.h
@@ -34,6 +34,7 @@ class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap>,
ModuleMap(const ModuleMap&) = delete;
ModuleMap& operator=(const ModuleMap&) = delete;
explicit ModuleMap(Modulator*);
+ ~ModuleMap() override = default;
void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override { return "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 73d231332ed..8d3659ab9d5 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
@@ -138,11 +138,6 @@ class ModuleMapTestModulator final : public DummyModulator {
return MakeGarbageCollected<TestModuleScriptFetcher>(this, pass_key);
}
- Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) override {
- return Vector<ModuleRequest>();
- }
-
base::SingleThreadTaskRunner* TaskRunner() override {
return Thread::Current()->GetTaskRunner().get();
}
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
index 750507954c7..b383fe3a6ef 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
@@ -78,7 +78,8 @@ ModuleScript* CreateReferrerModuleScript(Modulator* modulator,
V8TestingScope& scope) {
KURL js_url("https://example.com/referrer.js");
v8::Local<v8::Module> referrer_record = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "import './target.js'; export const a = 42;", js_url);
+ scope.GetScriptState(), "import './target.js'; export const a = 42;",
+ js_url);
KURL referrer_url("https://example.com/referrer.js");
auto* referrer_module_script =
JSModuleScript::CreateForTest(modulator, referrer_record, referrer_url);
@@ -90,7 +91,7 @@ ModuleScript* CreateTargetModuleScript(Modulator* modulator,
bool has_parse_error = false) {
KURL js_url("https://example.com/target.js");
v8::Local<v8::Module> record = ModuleTestBase::CompileModule(
- scope.GetIsolate(), "export const pi = 3.14;", js_url);
+ scope.GetScriptState(), "export const pi = 3.14;", js_url);
KURL url("https://example.com/target.js");
auto* module_script = JSModuleScript::CreateForTest(modulator, record, url);
if (has_parse_error) {
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 53848c41eef..ee769fa1be5 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script.cc
@@ -100,7 +100,7 @@ KURL ModuleScript::ResolveModuleSpecifier(const String& module_request,
void ModuleScript::Trace(Visitor* visitor) const {
visitor->Trace(settings_object_);
- visitor->Trace(record_.UnsafeCast<v8::Value>());
+ visitor->Trace(record_);
visitor->Trace(parse_error_);
visitor->Trace(error_to_rethrow_);
Script::Trace(visitor);
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 79199c59bbf..24d1d0777eb 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.h
+++ b/chromium/third_party/blink/renderer/core/script/module_script.h
@@ -16,7 +16,7 @@
#include "third_party/blink/renderer/platform/bindings/parkable_string.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/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.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"
@@ -87,9 +87,6 @@ class CORE_EXPORT ModuleScript : public Script {
Member<Modulator> settings_object_;
// https://html.spec.whatwg.org/C/#concept-script-record
- // TODO(keishi): Visitor only defines a trace method for v8::Value so this
- // needs to be cast.
- GC_PLUGIN_IGNORE("757708")
TraceWrapperV8Reference<v8::Module> record_;
// https://html.spec.whatwg.org/C/#concept-script-parse-error
diff --git a/chromium/third_party/blink/renderer/core/script/module_script_test.cc b/chromium/third_party/blink/renderer/core/script/module_script_test.cc
index 69ac13344dc..dccb2193de0 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script_test.cc
@@ -19,9 +19,9 @@
#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
using ::testing::_;
@@ -32,15 +32,10 @@ namespace {
class ModuleScriptTestModulator final : public DummyModulator {
public:
- ModuleScriptTestModulator(ScriptState* script_state)
+ explicit ModuleScriptTestModulator(ScriptState* script_state)
: script_state_(script_state) {}
~ModuleScriptTestModulator() override = default;
- Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) override {
- return Vector<ModuleRequest>();
- }
-
void Trace(Visitor* visitor) const override {
visitor->Trace(script_state_);
DummyModulator::Trace(visitor);
@@ -56,7 +51,8 @@ class MockCachedMetadataSender : public CachedMetadataSender {
public:
MockCachedMetadataSender() = default;
- MOCK_METHOD2(Send, void(const uint8_t*, size_t));
+ MOCK_METHOD3(Send,
+ void(blink::mojom::CodeCacheHost*, const uint8_t*, size_t));
bool IsServedFromCacheStorage() override { return false; }
};
@@ -66,7 +62,7 @@ static const int kScriptRepeatLength = 500;
class ModuleScriptTest : public ::testing::Test, public ParametrizedModuleTest {
protected:
- static String LargeSourceText() {
+ static String LargeSourceText(const char* suffix = nullptr) {
StringBuilder builder;
// Returns a sufficiently long script that is eligible for V8 code cache.
builder.Append(String("window.foo = "));
@@ -74,6 +70,8 @@ class ModuleScriptTest : public ::testing::Test, public ParametrizedModuleTest {
builder.Append(String("1 + "));
}
builder.Append(String("0;"));
+ if (suffix)
+ builder.Append(String(suffix));
return builder.ToString();
}
@@ -184,7 +182,7 @@ TEST_P(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kSetTimeStamp,
GetProduceCacheOptions(module_script));
- EXPECT_CALL(*sender_ptr, Send(_, _));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
break;
case 1:
@@ -194,7 +192,7 @@ TEST_P(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kProduceCodeCache,
GetProduceCacheOptions(module_script));
- EXPECT_CALL(*sender_ptr, Send(_, _));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
break;
case 2:
@@ -239,7 +237,7 @@ TEST_P(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
// As code cache is mismatched and rejected by V8, the CachedMetadata are
// cleared and notified to Platform.
- EXPECT_CALL(*sender_ptr, Send(_, _));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
EXPECT_CALL(checkpoint, Call(4));
// In actual cases CachedMetadataHandler and its code cache data are passed
@@ -308,7 +306,7 @@ TEST_P(ModuleScriptTest, V8CodeCacheWithDiscarding) {
EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kSetTimeStamp,
GetProduceCacheOptions(module_script));
- EXPECT_CALL(*sender_ptr, Send(_, _));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
break;
case 1:
@@ -318,7 +316,7 @@ TEST_P(ModuleScriptTest, V8CodeCacheWithDiscarding) {
EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kProduceCodeCache,
GetProduceCacheOptions(module_script));
- EXPECT_CALL(*sender_ptr, Send(_, _));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
break;
case 2:
@@ -408,6 +406,175 @@ TEST_P(ModuleScriptTest, ValueWrapperSyntheticModuleScript) {
ASSERT_FALSE(module_script->V8Module().IsEmpty());
}
+TEST_P(ModuleScriptTest, V8CodeCacheWithHashChecking) {
+ // The order of steps below is chosen so that only the last step's behavior
+ // differs based on this flag. The important tests that verify rejection of
+ // cache data on content mismatches occur before that point.
+ feature_list_.InitAndDisableFeature(
+ blink::features::kDiscardCodeCacheAfterFirstUse);
+
+ using Checkpoint = testing::StrictMock<testing::MockFunction<void(int)>>;
+
+ V8TestingScope scope;
+ Modulator* modulator =
+ MakeGarbageCollected<ModuleScriptTestModulator>(scope.GetScriptState());
+ Modulator::SetModulator(scope.GetScriptState(), modulator);
+
+ auto sender = std::make_unique<MockCachedMetadataSender>();
+ MockCachedMetadataSender* sender_ptr = sender.get();
+ ScriptCachedMetadataHandlerWithHashing* cache_handler =
+ MakeGarbageCollected<ScriptCachedMetadataHandlerWithHashing>(
+ UTF8Encoding(), std::move(sender));
+ const uint32_t kTimeStampTag = V8CodeCache::TagForTimeStamp(cache_handler);
+ const uint32_t kCodeTag = V8CodeCache::TagForCodeCache(cache_handler);
+
+ // Six loads:
+ // 0: cold, should produce timestamp
+ // 1: source text changed, should produce timestamp
+ // 2: warm, should produce code cache
+ // 3: source text changed again, should produce timestamp
+ // 4: warm, should produce code cache
+ // 5: hot, should consume code cache
+ for (int nth_load = 0; nth_load < 6; ++nth_load) {
+ // Running the module script immediately clears the code cache contents if
+ // it detects a hash mismatch. Thus, some checks must occur before it is
+ // called.
+ switch (nth_load) {
+ case 1:
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+
+ case 3:
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+ }
+
+ // Compile a module script.
+ String source =
+ LargeSourceText((nth_load == 1 || nth_load == 2) ? " " : nullptr);
+ cache_handler->ResetForTesting();
+ JSModuleScript* module_script =
+ CreateJSModuleScript(modulator, source, cache_handler);
+ ASSERT_TRUE(module_script);
+
+ // Check that the module script is instantiated/evaluated correctly.
+ ASSERT_TRUE(ModuleRecord::Instantiate(scope.GetScriptState(),
+ module_script->V8Module(),
+ module_script->SourceURL())
+ .IsEmpty());
+ ASSERT_EQ(module_script->RunScriptAndReturnValue().GetResultType(),
+ ScriptEvaluationResult::ResultType::kSuccess);
+ TestFoo(scope);
+
+ Checkpoint checkpoint;
+ ::testing::InSequence s;
+
+ switch (nth_load) {
+ case 0:
+ // For the first time, the cache handler doesn't contain any data, and
+ // we'll set timestamp in ProduceCache() below.
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kSetTimeStamp,
+ GetProduceCacheOptions(module_script));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+
+ case 1:
+ // For the second time, the timestamp has been cleared and will be
+ // replaced by another timestamp because the content didn't match.
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kSetTimeStamp,
+ GetProduceCacheOptions(module_script));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+
+ case 2:
+ // For the third time, as timestamp is already set, we'll produce code
+ // cache in ProduceCache() below.
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kProduceCodeCache,
+ GetProduceCacheOptions(module_script));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+
+ case 3:
+ // For the fourth time, the code cache has been cleared and will get
+ // replaced with a timestamp in ProduceCache() due to a content
+ // mismatch.
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kSetTimeStamp,
+ GetProduceCacheOptions(module_script));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+
+ case 4:
+ // For the fifth time, as timestamp is already set, we'll produce code
+ // cache in ProduceCache() below.
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kProduceCodeCache,
+ GetProduceCacheOptions(module_script));
+ EXPECT_CALL(*sender_ptr, Send(_, _, _));
+ break;
+
+ case 5:
+ // For the sixth time, the code cache is already there and we've
+ // consumed the code cache and won't do anything in ProduceCache().
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kCodeTag));
+ EXPECT_EQ(V8CodeCache::ProduceCacheOptions::kNoProduceCache,
+ GetProduceCacheOptions(module_script));
+ break;
+ }
+
+ EXPECT_CALL(checkpoint, Call(3));
+
+ module_script->ProduceCache();
+
+ checkpoint.Call(3);
+
+ switch (nth_load) {
+ case 0:
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ break;
+
+ case 1:
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ break;
+
+ case 2:
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kCodeTag));
+ break;
+
+ case 3:
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
+ break;
+
+ case 4:
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kCodeTag));
+ break;
+
+ case 5:
+ EXPECT_FALSE(cache_handler->GetCachedMetadata(kTimeStampTag));
+ EXPECT_TRUE(cache_handler->GetCachedMetadata(kCodeTag));
+ break;
+ }
+ }
+}
+
// Instantiate tests once with TLA and once without:
INSTANTIATE_TEST_SUITE_P(ModuleScriptTestGroup,
ModuleScriptTest,
diff --git a/chromium/third_party/blink/renderer/core/script/parsed_specifier.h b/chromium/third_party/blink/renderer/core/script/parsed_specifier.h
index c95e30f8f05..ec06378b86a 100644
--- a/chromium/third_party/blink/renderer/core/script/parsed_specifier.h
+++ b/chromium/third_party/blink/renderer/core/script/parsed_specifier.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PARSED_SPECIFIER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PARSED_SPECIFIER_H_
-#include "base/macros.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/script/pending_import_map.cc b/chromium/third_party/blink/renderer/core/script/pending_import_map.cc
index 2242897135c..ce7d5349af3 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_import_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/pending_import_map.cc
@@ -18,35 +18,27 @@ PendingImportMap* PendingImportMap::CreateInline(ScriptElementBase& element,
const String& import_map_text,
const KURL& base_url) {
ExecutionContext* context = element.GetExecutionContext();
- ScriptState* script_state =
- ToScriptStateForMainWorld(To<LocalDOMWindow>(context)->GetFrame());
- Modulator* modulator = Modulator::From(script_state);
- ScriptValue error_to_rethrow;
- ImportMap* import_map = ImportMap::Parse(
- *modulator, import_map_text, base_url, *context, &error_to_rethrow);
+ absl::optional<ImportMapError> error_to_rethrow;
+ ImportMap* import_map =
+ ImportMap::Parse(import_map_text, base_url, *context, &error_to_rethrow);
return MakeGarbageCollected<PendingImportMap>(
- script_state, element, import_map, error_to_rethrow, *context);
+ element, import_map, std::move(error_to_rethrow), *context);
}
-PendingImportMap::PendingImportMap(ScriptState* script_state,
- ScriptElementBase& element,
- ImportMap* import_map,
- ScriptValue error_to_rethrow,
- const ExecutionContext& original_context)
+PendingImportMap::PendingImportMap(
+ ScriptElementBase& element,
+ ImportMap* import_map,
+ absl::optional<ImportMapError> error_to_rethrow,
+ const ExecutionContext& original_context)
: element_(&element),
import_map_(import_map),
- original_execution_context_(&original_context) {
- if (!error_to_rethrow.IsEmpty()) {
- ScriptState::Scope scope(script_state);
- error_to_rethrow_.Set(script_state->GetIsolate(),
- error_to_rethrow.V8Value());
- }
-}
+ error_to_rethrow_(std::move(error_to_rethrow)),
+ original_execution_context_(&original_context) {}
// <specdef href="https://wicg.github.io/import-maps/#register-an-import-map">
// This is parallel to PendingScript::ExecuteScriptBlock().
-void PendingImportMap::RegisterImportMap() const {
+void PendingImportMap::RegisterImportMap() {
// <spec step="1">If element’s the script’s result is null, then fire an event
// named error at element, and return.</spec>
if (!import_map_) {
@@ -76,20 +68,14 @@ void PendingImportMap::RegisterImportMap() const {
return;
// Steps 7 and 8.
- LocalFrame* frame = To<LocalDOMWindow>(context)->GetFrame();
- if (!frame)
+ Modulator* modulator = Modulator::From(
+ ToScriptStateForMainWorld(To<LocalDOMWindow>(context)->GetFrame()));
+ if (!modulator)
return;
- Modulator* modulator = Modulator::From(ToScriptStateForMainWorld(frame));
-
ScriptState* script_state = modulator->GetScriptState();
ScriptState::Scope scope(script_state);
- ScriptValue error;
- if (!error_to_rethrow_.IsEmpty()) {
- error = ScriptValue(script_state->GetIsolate(),
- error_to_rethrow_.Get(script_state));
- }
- modulator->RegisterImportMap(import_map_, error);
+ modulator->RegisterImportMap(import_map_, std::move(error_to_rethrow_));
// <spec step="9">If element is from an external file, then fire an event
// named load at element.</spec>
@@ -100,7 +86,6 @@ void PendingImportMap::RegisterImportMap() const {
void PendingImportMap::Trace(Visitor* visitor) const {
visitor->Trace(element_);
visitor->Trace(import_map_);
- visitor->Trace(error_to_rethrow_);
visitor->Trace(original_execution_context_);
}
diff --git a/chromium/third_party/blink/renderer/core/script/pending_import_map.h b/chromium/third_party/blink/renderer/core/script/pending_import_map.h
index 96e10c8e6c8..2bc92bca957 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_import_map.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_import_map.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/import_map_error.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/wtf/text/wtf_string.h"
@@ -18,7 +19,6 @@ class ExecutionContext;
class ImportMap;
class KURL;
class ScriptElementBase;
-class ScriptValue;
// PendingImportMap serves as a container for an import map after "prepare a
// script" until it is registered. PendingImportMap is similar to PendingScript.
@@ -40,15 +40,16 @@ class CORE_EXPORT PendingImportMap final
const String& import_map_text,
const KURL& base_url);
- PendingImportMap(ScriptState* script_state,
- ScriptElementBase&,
+ PendingImportMap(ScriptElementBase&,
ImportMap*,
- ScriptValue error_to_rethrow,
+ absl::optional<ImportMapError> error_to_rethrow,
const ExecutionContext& original_context);
PendingImportMap(const PendingImportMap&) = delete;
PendingImportMap& operator=(const PendingImportMap&) = delete;
- void RegisterImportMap() const;
+ // Registers import map to the |element_|`s context. Should be called only
+ // once. |this| is invalidated after calling.
+ void RegisterImportMap();
virtual void Trace(Visitor* visitor) const;
@@ -59,8 +60,7 @@ class CORE_EXPORT PendingImportMap final
Member<ImportMap> import_map_;
// https://wicg.github.io/import-maps/#import-map-parse-result-error-to-rethrow
- // The error is TypeError if the string is non-null, or null otherwise.
- WorldSafeV8Reference<v8::Value> error_to_rethrow_;
+ absl::optional<ImportMapError> error_to_rethrow_;
// https://wicg.github.io/import-maps/#import-map-parse-result-settings-object
// The context at the time when PrepareScript() is executed.
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 6b9c8021605..bf726d53368 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.h
@@ -66,7 +66,7 @@ class CORE_EXPORT PendingScript : public GarbageCollected<PendingScript>,
public:
PendingScript(const PendingScript&) = delete;
PendingScript& operator=(const PendingScript&) = delete;
- virtual ~PendingScript();
+ ~PendingScript() override;
TextPosition StartingPosition() const { return starting_position_; }
void MarkParserBlockingLoadStartTime();
diff --git a/chromium/third_party/blink/renderer/core/script/script_element_base.h b/chromium/third_party/blink/renderer/core/script/script_element_base.h
index 3c7ce524d3a..e6b6a334837 100644
--- a/chromium/third_party/blink/renderer/core/script/script_element_base.h
+++ b/chromium/third_party/blink/renderer/core/script/script_element_base.h
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#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/dom/dom_node_ids.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -93,12 +94,8 @@ class CORE_EXPORT ScriptElementBase : public GarbageCollectedMixin {
virtual Document& GetDocument() const = 0;
virtual ExecutionContext* GetExecutionContext() const = 0;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual V8HTMLOrSVGScriptElement* AsV8HTMLOrSVGScriptElement() = 0;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void SetScriptElementForBinding(
- HTMLScriptElementOrSVGScriptElement&) = 0;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ virtual DOMNodeId GetDOMNodeId() = 0;
virtual void DispatchLoadEvent() = 0;
virtual void DispatchErrorEvent() = 0;
diff --git a/chromium/third_party/blink/renderer/core/script/script_loader.cc b/chromium/third_party/blink/renderer/core/script/script_loader.cc
index 0761d94c0e7..4187de06190 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.cc
@@ -82,9 +82,7 @@ namespace blink {
ScriptLoader::ScriptLoader(ScriptElementBase* element,
const CreateElementFlags flags)
- : element_(element),
- will_be_parser_executed_(false),
- will_execute_when_document_finished_parsing_(false) {
+ : element_(element) {
// <spec href="https://html.spec.whatwg.org/C/#already-started">... The
// cloning steps for script elements must set the "already started" flag on
// the copy if it is set on the element being cloned.</spec>
@@ -193,21 +191,6 @@ enum class ShouldFireErrorEvent {
kShouldFire,
};
-bool IsImportMapEnabled(LocalDOMWindow* context_window) {
- // When window/modulator is null, `true` is returned here, because
- // PrepareScript() should fail at "scripting is disabled" checks, not here.
-
- if (!context_window)
- return true;
-
- Modulator* modulator =
- Modulator::From(ToScriptStateForMainWorld(context_window->GetFrame()));
- if (!modulator)
- return true;
-
- return modulator->ImportMapsEnabled();
-}
-
} // namespace
// <specdef href="https://html.spec.whatwg.org/C/#prepare-a-script">
@@ -270,7 +253,7 @@ network::mojom::CredentialsMode ScriptLoader::ModuleScriptCredentialsMode(
return network::mojom::CredentialsMode::kOmit;
}
-// https://github.com/w3c/webappsec-permissions-policy/issues/135
+// https://github.com/WICG/document-policy/issues/2
bool ShouldBlockSyncScriptForDocumentPolicy(
const ScriptElementBase* element,
ScriptLoader::ScriptTypeAtPrepare script_type,
@@ -350,11 +333,6 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
case ScriptTypeAtPrepare::kInvalid:
return false;
- case ScriptTypeAtPrepare::kImportMap:
- if (!IsImportMapEnabled(context_window))
- return false;
- break;
-
case ScriptTypeAtPrepare::kSpeculationRules:
if (!RuntimeEnabledFeatures::SpeculationRulesEnabled(context_window))
return false;
@@ -362,6 +340,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
case ScriptTypeAtPrepare::kClassic:
case ScriptTypeAtPrepare::kModule:
+ case ScriptTypeAtPrepare::kImportMap:
break;
}
@@ -428,7 +407,6 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
if (!IsScriptForEventSupported())
return false;
- // This Document Policy is still in the process of being added to the spec.
if (ShouldBlockSyncScriptForDocumentPolicy(element_.Get(), GetScriptType(),
parser_inserted_)) {
element_document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
@@ -733,10 +711,20 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// If the script’s result is not null, append it to the element’s node
// document's list of speculation rule sets.
DCHECK(RuntimeEnabledFeatures::SpeculationRulesEnabled(context_window));
- if (auto* rule_set =
- SpeculationRuleSet::ParseInline(source_text, base_url)) {
+ String parse_error;
+ if (auto* rule_set = SpeculationRuleSet::ParseInline(
+ source_text, base_url, &parse_error)) {
DocumentSpeculationRules::From(element_document).AddRuleSet(rule_set);
}
+ if (!parse_error.IsNull()) {
+ auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+ mojom::ConsoleMessageSource::kOther,
+ mojom::ConsoleMessageLevel::kWarning,
+ "While parsing speculation rules: " + parse_error);
+ console_message->SetNodes(element_document.GetFrame(),
+ {element_->GetDOMNodeId()});
+ element_document.AddConsoleMessage(console_message);
+ }
return false;
}
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 1492f45d8c2..c104624ffa5 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.h
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.h
@@ -192,9 +192,9 @@ class CORE_EXPORT ScriptLoader final : public GarbageCollected<ScriptLoader>,
bool is_external_script_ = false;
// Same as "The parser will handle executing the script."
- bool will_be_parser_executed_;
+ bool will_be_parser_executed_ = false;
- bool will_execute_when_document_finished_parsing_;
+ bool will_execute_when_document_finished_parsing_ = false;
// A PendingScript is first created in PrepareScript() and stored in
// |prepared_pending_script_|.
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 6e9899be562..6888dc11774 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.cc
@@ -46,11 +46,9 @@
namespace blink {
ScriptRunner::ScriptRunner(Document* document)
- : ExecutionContextLifecycleStateObserver(document->GetExecutionContext()),
- document_(document),
+ : document_(document),
task_runner_(document->GetTaskRunner(TaskType::kNetworking)) {
DCHECK(document);
- UpdateStateIfNeeded();
}
void ScriptRunner::QueueScriptForExecution(PendingScript* pending_script) {
@@ -78,28 +76,6 @@ void ScriptRunner::PostTask(const base::Location& web_trace_location) {
WTF::Bind(&ScriptRunner::ExecuteTask, WrapWeakPersistent(this)));
}
-void ScriptRunner::ContextLifecycleStateChanged(
- mojom::FrameLifecycleState state) {
- if (!IsExecutionSuspended())
- PostTasksForReadyScripts(FROM_HERE);
-}
-
-bool ScriptRunner::IsExecutionSuspended() {
- return !GetExecutionContext() || GetExecutionContext()->IsContextPaused();
-}
-
-void ScriptRunner::PostTasksForReadyScripts(
- const base::Location& web_trace_location) {
- DCHECK(!IsExecutionSuspended());
-
- for (size_t i = 0; i < async_scripts_to_execute_soon_.size(); ++i) {
- PostTask(web_trace_location);
- }
- for (size_t i = 0; i < in_order_scripts_to_execute_soon_.size(); ++i) {
- PostTask(web_trace_location);
- }
-}
-
void ScriptRunner::ScheduleReadyInOrderScripts() {
while (!pending_in_order_scripts_.IsEmpty() &&
pending_in_order_scripts_.front()
@@ -110,85 +86,6 @@ void ScriptRunner::ScheduleReadyInOrderScripts() {
}
}
-void ScriptRunner::DelayAsyncScript(PendingScript* pending_script) {
- DCHECK(!delay_async_script_milestone_reached_ ||
- async_script_execution_paused_);
- SECURITY_CHECK(pending_async_scripts_.Contains(pending_script));
- pending_async_scripts_.erase(pending_script);
-
- // When the ScriptRunner is notified via
- // |NotifyDelayedAsyncScriptsMilestoneReached()|, the scripts in
- // |pending_delayed_async_scripts_| will be scheduled for execution.
- pending_delayed_async_scripts_.push_back(pending_script);
-}
-
-void ScriptRunner::ScheduleDelayedAsyncScripts() {
- DCHECK(delay_async_script_milestone_reached_ ||
- !async_script_execution_paused_);
- while (!pending_delayed_async_scripts_.IsEmpty()) {
- PendingScript* pending_script = pending_delayed_async_scripts_.TakeFirst();
- DCHECK_EQ(pending_script->GetSchedulingType(),
- ScriptSchedulingType::kAsync);
-
- async_scripts_to_execute_soon_.push_back(pending_script);
- PostTask(FROM_HERE);
- }
-}
-
-void ScriptRunner::NotifyDelayedAsyncScriptsMilestoneReached() {
- delay_async_script_milestone_reached_ = true;
- ScheduleDelayedAsyncScripts();
-}
-
-bool ScriptRunner::CanDelayAsyncScripts() {
- if (delay_async_script_milestone_reached_)
- return false;
-
- // We first check to see if the base::Feature is enabled, before the
- // RuntimeEnabledFeatures. This is because the RuntimeEnabledFeatures simply
- // exist for testing, so if they are enabled *and* the base::Feature is
- // enabled, we should log UKM via DocumentLoader::DidObserveLoadingBehavior,
- // which is associated with the experiment running the base::Feature flag.
- static bool feature_enabled =
- base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution);
- bool optimization_guide_hints_unknown =
- !document_->GetFrame() ||
- !document_->GetFrame()->GetOptimizationGuideHints() ||
- !document_->GetFrame()
- ->GetOptimizationGuideHints()
- ->delay_async_script_execution_hints ||
- document_->GetFrame()
- ->GetOptimizationGuideHints()
- ->delay_async_script_execution_hints->delay_type ==
- mojom::blink::DelayAsyncScriptExecutionDelayType::kUnknown;
- if (feature_enabled) {
- if (document_->Parsing() && document_->Loader()) {
- document_->Loader()->DidObserveLoadingBehavior(
- kLoadingBehaviorAsyncScriptReadyBeforeDocumentFinishedParsing);
- }
-
- // If the base::Feature is enabled, we always want to delay async scripts,
- // unless we delegate to the OptimizationGuide, but the hints aren't
- // available.
- if (features::kDelayAsyncScriptExecutionDelayParam.Get() !=
- features::DelayAsyncScriptDelayType::kUseOptimizationGuide ||
- !optimization_guide_hints_unknown) {
- return true;
- }
- }
-
- // Delay milestone has not been reached yet. We have to check the feature flag
- // configuration to see if we are able to delay async scripts or not:
- if (RuntimeEnabledFeatures::
- DelayAsyncScriptExecutionUntilFinishedParsingEnabled() ||
- RuntimeEnabledFeatures::
- DelayAsyncScriptExecutionUntilFirstPaintOrFinishedParsingEnabled()) {
- return true;
- }
-
- return false;
-}
-
void ScriptRunner::NotifyScriptReady(PendingScript* pending_script) {
SECURITY_CHECK(pending_script);
@@ -200,12 +97,6 @@ void ScriptRunner::NotifyScriptReady(PendingScript* pending_script) {
// to detach).
SECURITY_CHECK(pending_async_scripts_.Contains(pending_script));
- if ((pending_script->IsEligibleForDelay() && CanDelayAsyncScripts()) ||
- async_script_execution_paused_) {
- DelayAsyncScript(pending_script);
- return;
- }
-
pending_async_scripts_.erase(pending_script);
async_scripts_to_execute_soon_.push_back(pending_script);
@@ -298,8 +189,7 @@ bool ScriptRunner::ExecuteInOrderTask() {
bool ScriptRunner::ExecuteAsyncTask() {
TRACE_EVENT0("blink", "ScriptRunner::ExecuteAsyncTask");
- if (async_script_execution_paused_ ||
- async_scripts_to_execute_soon_.IsEmpty())
+ if (async_scripts_to_execute_soon_.IsEmpty())
return false;
// Remove the async script loader from the ready-to-exec set and execute.
@@ -315,14 +205,13 @@ bool ScriptRunner::ExecuteAsyncTask() {
}
void ScriptRunner::ExecuteTask() {
+ DCHECK(!document_->domWindow() || !document_->domWindow()->IsContextPaused());
+
// This method is triggered by ScriptRunner::PostTask, and runs directly from
// the scheduler. So, the call stack is safe to reenter.
scheduler::CooperativeSchedulingManager::AllowedStackScope
allowed_stack_scope(scheduler::CooperativeSchedulingManager::Instance());
- if (IsExecutionSuspended())
- return;
-
if (ExecuteAsyncTask())
return;
@@ -330,30 +219,10 @@ void ScriptRunner::ExecuteTask() {
return;
}
-void ScriptRunner::PauseAsyncScriptExecution() {
- if (async_script_execution_paused_)
- return;
- TRACE_EVENT0("blink", "ScriptRunner::PauseAsyncScriptExecution");
- async_script_execution_paused_ = true;
-}
-
-void ScriptRunner::ResumeAsyncScriptExecution() {
- if (!async_script_execution_paused_)
- return;
- TRACE_EVENT0("blink", "ScriptRunner::ResumeAsyncScriptExecution");
- async_script_execution_paused_ = false;
- for (wtf_size_t i = 0; i < async_scripts_to_execute_soon_.size(); i++) {
- PostTask(FROM_HERE);
- }
- ScheduleDelayedAsyncScripts();
-}
-
void ScriptRunner::Trace(Visitor* visitor) const {
- ExecutionContextLifecycleStateObserver::Trace(visitor);
visitor->Trace(document_);
visitor->Trace(pending_in_order_scripts_);
visitor->Trace(pending_async_scripts_);
- visitor->Trace(pending_delayed_async_scripts_);
visitor->Trace(async_scripts_to_execute_soon_);
visitor->Trace(in_order_scripts_to_execute_soon_);
}
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 3aa1adffc85..509fa7d370e 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.h
@@ -43,10 +43,10 @@ class ScriptLoader;
class CORE_EXPORT ScriptRunner final
: public GarbageCollected<ScriptRunner>,
- public ExecutionContextLifecycleStateObserver,
public NameClient {
public:
explicit ScriptRunner(Document*);
+ ~ScriptRunner() override = default;
ScriptRunner(const ScriptRunner&) = delete;
ScriptRunner& operator=(const ScriptRunner&) = delete;
@@ -56,9 +56,6 @@ class CORE_EXPORT ScriptRunner final
!pending_async_scripts_.IsEmpty();
}
void NotifyScriptReady(PendingScript*);
- void NotifyDelayedAsyncScriptsMilestoneReached();
- void ContextLifecycleStateChanged(mojom::FrameLifecycleState) final;
- void ContextDestroyed() final {}
static void MovePendingScript(Document&, Document&, ScriptLoader*);
@@ -66,32 +63,17 @@ class CORE_EXPORT ScriptRunner final
task_runner_ = task_runner;
}
- void Trace(Visitor*) const override;
+ void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override { return "ScriptRunner"; }
- // HTML parser can defer async scripts until after it's processed sequential
- // sync <script> tags.
- void PauseAsyncScriptExecution();
- void ResumeAsyncScriptExecution();
- bool AsyncScriptExecutionPaused() const {
- return async_script_execution_paused_;
- }
-
private:
class Task;
void MovePendingScript(ScriptRunner*, PendingScript*);
bool RemovePendingInOrderScript(PendingScript*);
void ScheduleReadyInOrderScripts();
- void ScheduleDelayedAsyncScripts();
-
- // Used to delay async scripts. These scripts are delayed until
- // |NotifyDelayedAsyncScriptsMilestoneReached()| is called.
- bool CanDelayAsyncScripts();
- void DelayAsyncScript(PendingScript*);
void PostTask(const base::Location&);
- void PostTasksForReadyScripts(const base::Location&);
// Execute the first task in in_order_scripts_to_execute_soon_.
// Returns true if task was run, and false otherwise.
@@ -103,13 +85,10 @@ class CORE_EXPORT ScriptRunner final
void ExecuteTask();
- bool IsExecutionSuspended();
-
Member<Document> document_;
HeapDeque<Member<PendingScript>> pending_in_order_scripts_;
HeapHashSet<Member<PendingScript>> pending_async_scripts_;
- HeapDeque<Member<PendingScript>> pending_delayed_async_scripts_;
// http://www.whatwg.org/specs/web-apps/current-work/#set-of-scripts-that-will-execute-as-soon-as-possible
HeapDeque<Member<PendingScript>> async_scripts_to_execute_soon_;
@@ -118,15 +97,6 @@ class CORE_EXPORT ScriptRunner final
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
int number_of_in_order_scripts_with_pending_notification_ = 0;
-
- // Scripts in |pending_delayed_async_scripts_| are delayed until the
- // |NotifyDelayedAsyncScriptsMilestoneReached()| is called. After this point,
- // the ScriptRunner no longer delays async scripts. This bool is used to
- // ensure we don't continue delaying async scripts after this point. See the
- // design doc:
- // https://docs.google.com/document/u/1/d/1G-IUrT4enARZlsIrFQ4d4cRVe9MRTJASfWwolV09JZE/edit.
- bool delay_async_script_milestone_reached_ = false;
- bool async_script_execution_paused_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/script_runner_test.cc b/chromium/third_party/blink/renderer/core/script/script_runner_test.cc
index 6f7cf8e9cb8..bd3e081efc3 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -7,6 +7,7 @@
#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/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/script/mock_script_element_base.h"
#include "third_party/blink/renderer/core/script/pending_script.h"
#include "third_party/blink/renderer/core/script/script.h"
@@ -104,13 +105,6 @@ class ScriptRunnerTest : public testing::Test {
script_runner_->QueueScriptForExecution(pending_script);
}
- void PauseAsyncScriptExecution() {
- script_runner_->PauseAsyncScriptExecution();
- }
- void ResumeAsyncScriptExecution() {
- script_runner_->ResumeAsyncScriptExecution();
- }
-
std::unique_ptr<DummyPageHolder> page_holder_;
Persistent<Document> document_;
Persistent<ScriptRunner> script_runner_;
@@ -198,57 +192,17 @@ TEST_F(ScriptRunnerTest, QueueMixedScripts) {
EXPECT_CALL(*pending_script5, ExecuteScriptBlock(_))
.WillOnce(InvokeWithoutArgs([this] { order_.push_back(5); }));
+ platform_->RunSingleTask();
+ document_->domWindow()->SetLifecycleState(
+ mojom::FrameLifecycleState::kPaused);
+ document_->domWindow()->SetLifecycleState(
+ mojom::FrameLifecycleState::kRunning);
platform_->RunUntilIdle();
// Async tasks are expected to run first.
EXPECT_THAT(order_, ElementsAre(4, 5, 1, 2, 3));
}
-TEST_F(ScriptRunnerTest, QueueMixedScriptWithAsyncDelay) {
- // PauseAsyncScriptExecution/ResumeAsyncScriptExecution are designed so that
- // the parser can guarantee async scripts don't run between adjacent <script>
- // tags.
- auto* pending_script1 = MockPendingScript::CreateInOrder(document_);
- auto* pending_script2 = MockPendingScript::CreateInOrder(document_);
- auto* pending_script3 = MockPendingScript::CreateInOrder(document_);
- auto* pending_script4 = MockPendingScript::CreateAsync(document_);
- auto* pending_script5 = MockPendingScript::CreateAsync(document_);
-
- QueueScriptForExecution(pending_script1);
- QueueScriptForExecution(pending_script2);
- QueueScriptForExecution(pending_script3);
- QueueScriptForExecution(pending_script4);
- QueueScriptForExecution(pending_script5);
-
- EXPECT_CALL(*pending_script1, ExecuteScriptBlock(_))
- .WillOnce(InvokeWithoutArgs([this] { order_.push_back(1); }));
- EXPECT_CALL(*pending_script2, ExecuteScriptBlock(_))
- .WillOnce(InvokeWithoutArgs([this] { order_.push_back(2); }));
- EXPECT_CALL(*pending_script3, ExecuteScriptBlock(_))
- .WillOnce(InvokeWithoutArgs([this] { order_.push_back(3); }));
- EXPECT_CALL(*pending_script4, ExecuteScriptBlock(_))
- .WillOnce(InvokeWithoutArgs([this] { order_.push_back(4); }));
- EXPECT_CALL(*pending_script5, ExecuteScriptBlock(_))
- .WillOnce(InvokeWithoutArgs([this] { order_.push_back(5); }));
-
- NotifyScriptReady(pending_script1);
- NotifyScriptReady(pending_script2);
-
- platform_->RunUntilIdle();
- EXPECT_THAT(order_, ElementsAre(1, 2));
- PauseAsyncScriptExecution();
-
- NotifyScriptReady(pending_script3);
- NotifyScriptReady(pending_script4);
- NotifyScriptReady(pending_script5);
-
- platform_->RunUntilIdle();
- EXPECT_THAT(order_, ElementsAre(1, 2, 3));
- ResumeAsyncScriptExecution();
- platform_->RunUntilIdle();
- EXPECT_THAT(order_, ElementsAre(1, 2, 3, 4, 5));
-}
-
TEST_F(ScriptRunnerTest, QueueReentrantScript_Async) {
auto* pending_script1 = MockPendingScript::CreateAsync(document_);
auto* pending_script2 = MockPendingScript::CreateAsync(document_);
@@ -382,10 +336,9 @@ TEST_F(ScriptRunnerTest, ResumeAndSuspend_InOrder) {
NotifyScriptReady(pending_script2);
NotifyScriptReady(pending_script3);
- platform_->RunSingleTask();
- script_runner_->ContextLifecycleStateChanged(
+ document_->domWindow()->SetLifecycleState(
mojom::FrameLifecycleState::kPaused);
- script_runner_->ContextLifecycleStateChanged(
+ document_->domWindow()->SetLifecycleState(
mojom::FrameLifecycleState::kRunning);
platform_->RunUntilIdle();
@@ -413,10 +366,9 @@ TEST_F(ScriptRunnerTest, ResumeAndSuspend_Async) {
EXPECT_CALL(*pending_script3, ExecuteScriptBlock(_))
.WillOnce(InvokeWithoutArgs([this] { order_.push_back(3); }));
- platform_->RunSingleTask();
- script_runner_->ContextLifecycleStateChanged(
+ document_->domWindow()->SetLifecycleState(
mojom::FrameLifecycleState::kPaused);
- script_runner_->ContextLifecycleStateChanged(
+ document_->domWindow()->SetLifecycleState(
mojom::FrameLifecycleState::kRunning);
platform_->RunUntilIdle();
diff --git a/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
index 0f6797af904..80d602d75c0 100644
--- a/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -47,8 +47,13 @@ ValueWrapperSyntheticModuleScript::CreateCSSWrapperSyntheticModuleScript(
ScriptFetchOptions(), error);
}
CSSStyleSheetInit* init = CSSStyleSheetInit::Create();
- CSSStyleSheet* style_sheet =
- CSSStyleSheet::Create(*context_window->document(), init, exception_state);
+ // The base URL used to construct the CSSStyleSheet is also used for
+ // DevTools as the CSS source URL. This is fine since these two values
+ // are always the same for CSS module scripts.
+ DCHECK_EQ(params.BaseURL(), params.SourceURL());
+ CSSStyleSheet* style_sheet = CSSStyleSheet::Create(
+ *context_window->document(), params.BaseURL(), init, exception_state);
+ style_sheet->SetIsForCSSModuleScript();
if (exception_state.HadException()) {
v8::Local<v8::Value> error = exception_state.GetException();
exception_state.ClearException();
diff --git a/chromium/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.cc b/chromium/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.cc
index 0f4f67818d1..49019fbdde4 100644
--- a/chromium/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.cc
@@ -144,7 +144,9 @@ void ProgrammaticScrollAnimator::UpdateCompositorAnimations() {
if (!scrollable_area_->ShouldScrollOnMainThread() &&
!is_sequenced_scroll_) {
auto animation = std::make_unique<CompositorKeyframeModel>(
- *animation_curve_, compositor_target_property::SCROLL_OFFSET, 0, 0);
+ *animation_curve_, 0, 0,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::SCROLL_OFFSET));
if (AddAnimation(std::move(animation))) {
sent_to_compositor = true;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.cc b/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.cc
index 976c9048fab..2965075cb11 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.cc
@@ -5,7 +5,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.h b/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.h
index 5ebc15d47da..dcfa5305a2b 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_alignment.h
@@ -5,7 +5,7 @@
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
+ * David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc b/chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc
index 655be0c8c28..890e011a692 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc
@@ -276,7 +276,9 @@ bool ScrollAnimator::SendAnimationToCompositor() {
return false;
auto animation = std::make_unique<CompositorKeyframeModel>(
- *animation_curve_, compositor_target_property::SCROLL_OFFSET, 0, 0);
+ *animation_curve_, 0, 0,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::SCROLL_OFFSET));
// Being here means that either there is an animation that needs
// to be sent to the compositor, or an animation that needs to
// be updated (a new scroll event before the previous animation
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc
index 1f340cfa64e..7abea57ae26 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -53,6 +53,8 @@
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
+#include "third_party/blink/renderer/platform/graphics/color.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/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -110,9 +112,6 @@ ScrollableArea::ScrollableArea(
uses_composited_scrolling_(false),
compositor_task_runner_(std::move(compositor_task_runner)) {
DCHECK(compositor_task_runner_);
-#if defined(OS_MAC)
- scrollbar_animator_ = MacScrollbarAnimator::Create(this);
-#endif
}
ScrollableArea::~ScrollableArea() = default;
@@ -126,8 +125,8 @@ void ScrollableArea::Dispose() {
}
void ScrollableArea::ClearScrollableArea() {
- if (scrollbar_animator_)
- scrollbar_animator_->Dispose();
+ if (mac_scrollbar_animator_)
+ mac_scrollbar_animator_->Dispose();
scroll_animator_.Clear();
programmatic_scroll_animator_.Clear();
if (fade_overlay_scrollbars_timer_)
@@ -135,7 +134,13 @@ void ScrollableArea::ClearScrollableArea() {
}
MacScrollbarAnimator* ScrollableArea::GetMacScrollbarAnimator() const {
- return scrollbar_animator_;
+#if defined(OS_MAC)
+ if (!mac_scrollbar_animator_) {
+ mac_scrollbar_animator_ =
+ MacScrollbarAnimator::Create(const_cast<ScrollableArea*>(this));
+ }
+#endif
+ return mac_scrollbar_animator_;
}
ScrollAnimatorBase& ScrollableArea::GetScrollAnimator() const {
@@ -251,6 +256,14 @@ ScrollResult ScrollableArea::UserScroll(ScrollGranularity granularity,
return result;
}
+ScrollOffset ScrollableArea::PendingScrollAnchorAdjustment() const {
+ return pending_scroll_anchor_adjustment_;
+}
+
+void ScrollableArea::ClearPendingScrollAnchorAdjustment() {
+ pending_scroll_anchor_adjustment_ = ScrollOffset();
+}
+
void ScrollableArea::SetScrollOffset(const ScrollOffset& offset,
mojom::blink::ScrollType scroll_type,
mojom::blink::ScrollBehavior behavior,
@@ -267,8 +280,10 @@ void ScrollableArea::SetScrollOffset(const ScrollOffset& offset,
}
}
+ ScrollOffset previous_offset = GetScrollOffset();
+
ScrollOffset clamped_offset = ClampScrollOffset(offset);
- if (clamped_offset == GetScrollOffset()) {
+ if (clamped_offset == previous_offset) {
return;
}
@@ -293,6 +308,8 @@ void ScrollableArea::SetScrollOffset(const ScrollOffset& offset,
case mojom::blink::ScrollType::kAnchoring:
GetScrollAnimator().AdjustAnimationAndSetScrollOffset(clamped_offset,
scroll_type);
+
+ pending_scroll_anchor_adjustment_ += clamped_offset - previous_offset;
break;
case mojom::blink::ScrollType::kProgrammatic:
ProgrammaticScrollHelper(clamped_offset, behavior, false,
@@ -475,23 +492,23 @@ void ScrollableArea::RunScrollCompleteCallbacks() {
}
void ScrollableArea::ContentAreaWillPaint() const {
- if (GetMacScrollbarAnimator())
- GetMacScrollbarAnimator()->ContentAreaWillPaint();
+ if (mac_scrollbar_animator_)
+ mac_scrollbar_animator_->ContentAreaWillPaint();
}
void ScrollableArea::MouseEnteredContentArea() const {
- if (GetMacScrollbarAnimator())
- GetMacScrollbarAnimator()->MouseEnteredContentArea();
+ if (mac_scrollbar_animator_)
+ mac_scrollbar_animator_->MouseEnteredContentArea();
}
void ScrollableArea::MouseExitedContentArea() const {
- if (GetMacScrollbarAnimator())
- GetMacScrollbarAnimator()->MouseExitedContentArea();
+ if (mac_scrollbar_animator_)
+ mac_scrollbar_animator_->MouseExitedContentArea();
}
void ScrollableArea::MouseMovedInContentArea() const {
- if (GetMacScrollbarAnimator())
- GetMacScrollbarAnimator()->MouseMovedInContentArea();
+ if (mac_scrollbar_animator_)
+ mac_scrollbar_animator_->MouseMovedInContentArea();
}
void ScrollableArea::MouseEnteredScrollbar(Scrollbar& scrollbar) {
@@ -544,17 +561,17 @@ void ScrollableArea::DidAddScrollbar(Scrollbar& scrollbar,
void ScrollableArea::WillRemoveScrollbar(Scrollbar& scrollbar,
ScrollbarOrientation orientation) {
- if (GetMacScrollbarAnimator()) {
+ if (mac_scrollbar_animator_) {
if (orientation == kVerticalScrollbar)
- GetMacScrollbarAnimator()->WillRemoveVerticalScrollbar(scrollbar);
+ mac_scrollbar_animator_->WillRemoveVerticalScrollbar(scrollbar);
else
- GetMacScrollbarAnimator()->WillRemoveHorizontalScrollbar(scrollbar);
+ mac_scrollbar_animator_->WillRemoveHorizontalScrollbar(scrollbar);
}
}
void ScrollableArea::ContentsResized() {
- if (GetMacScrollbarAnimator())
- GetMacScrollbarAnimator()->ContentsResized();
+ if (mac_scrollbar_animator_)
+ mac_scrollbar_animator_->ContentsResized();
}
void ScrollableArea::InvalidateScrollTimeline() {
@@ -588,7 +605,7 @@ void ScrollableArea::SetScrollbarOverlayColorTheme(
}
void ScrollableArea::RecalculateScrollbarOverlayColorTheme(
- Color background_color) {
+ const Color& background_color) {
ScrollbarOverlayColorTheme old_overlay_theme =
GetScrollbarOverlayColorTheme();
ScrollbarOverlayColorTheme overlay_theme = kScrollbarOverlayColorThemeDark;
@@ -753,7 +770,7 @@ void ScrollableArea::ShowNonMacOverlayScrollbars() {
// Don't do this for composited scrollbars. These scrollbars are handled
// by separate code in cc::ScrollbarAnimationController.
- if (LayerForVerticalScrollbar() || LayerForHorizontalScrollbar())
+ if (UsesCompositedScrolling())
return;
SetScrollbarsHiddenIfOverlay(false);
@@ -881,7 +898,7 @@ IntSize ScrollableArea::ExcludeScrollbars(const IntSize& size) const {
std::max(0, size.Height() - HorizontalScrollbarHeight()));
}
-void ScrollableArea::DidScroll(const FloatPoint& position) {
+void ScrollableArea::DidCompositorScroll(const FloatPoint& position) {
ScrollOffset new_offset(ScrollPositionToOffset(position));
SetScrollOffset(new_offset, mojom::blink::ScrollType::kCompositor);
}
@@ -994,7 +1011,7 @@ bool ScrollableArea::PerformSnapping(
void ScrollableArea::Trace(Visitor* visitor) const {
visitor->Trace(scroll_animator_);
- visitor->Trace(scrollbar_animator_);
+ visitor->Trace(mac_scrollbar_animator_);
visitor->Trace(programmatic_scroll_animator_);
visitor->Trace(fade_overlay_scrollbars_timer_);
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
index 2aed8c54470..d17a5784322 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
@@ -35,7 +35,6 @@
#include "third_party/blink/renderer/core/loader/history_item.h"
#include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.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/graphics/overlay_scrollbar_clip_behavior.h"
#include "third_party/blink/renderer/platform/heap/disallow_new_wrapper.h"
@@ -56,16 +55,17 @@ class Layer;
namespace blink {
class ChromeClient;
+class Color;
class CompositorAnimationTimeline;
class Document;
class LayoutBox;
class LayoutObject;
class LocalFrame;
+class MacScrollbarAnimator;
class Node;
class PaintLayer;
class ProgrammaticScrollAnimator;
class ScrollAnchor;
-class MacScrollbarAnimator;
class ScrollAnimatorBase;
struct SerializedAnchor;
class SmoothScrollSequencer;
@@ -221,12 +221,14 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
// overflow:overlay might be deprecated soon.
bool HasOverlayScrollbars() const;
void SetScrollbarOverlayColorTheme(ScrollbarOverlayColorTheme);
- void RecalculateScrollbarOverlayColorTheme(Color);
+ void RecalculateScrollbarOverlayColorTheme(const Color& background_color);
ScrollbarOverlayColorTheme GetScrollbarOverlayColorTheme() const {
return static_cast<ScrollbarOverlayColorTheme>(
scrollbar_overlay_color_theme_);
}
+ // This getter will create a MacScrollAnimator if it doesn't already exist,
+ // only on MacOS.
MacScrollbarAnimator* GetMacScrollbarAnimator() const;
// This getter will create a ScrollAnimatorBase if it doesn't already exist.
@@ -393,8 +395,12 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual void RegisterForAnimation() {}
virtual void DeregisterForAnimation() {}
- bool UsesCompositedScrolling() const { return uses_composited_scrolling_; }
+ virtual bool UsesCompositedScrolling() const {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
+ return uses_composited_scrolling_;
+ }
void SetUsesCompositedScrolling(bool uses_composited_scrolling) {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
uses_composited_scrolling_ = uses_composited_scrolling;
}
virtual bool ShouldScrollOnMainThread() const { return false; }
@@ -520,7 +526,7 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
const = 0;
// Callback for compositor-side scrolling.
- virtual void DidScroll(const FloatPoint&);
+ virtual void DidCompositorScroll(const FloatPoint& position);
virtual void ScrollbarFrameRectChanged() {}
@@ -547,6 +553,9 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
// box. GetLayoutBox()->GetNode() doesn't work in this case.
Node* EventTargetNode() const;
+ ScrollOffset PendingScrollAnchorAdjustment() const;
+ void ClearPendingScrollAnchorAdjustment();
+
scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner();
protected:
@@ -630,7 +639,7 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
// using AppKit-specific code (Cocoa APIs). It requires input from
// ScrollableArea about changes on scrollbars. For other platforms, painting
// is done by blink, and this member will be a nullptr.
- mutable Member<MacScrollbarAnimator> scrollbar_animator_;
+ mutable Member<MacScrollbarAnimator> mac_scrollbar_animator_;
mutable Member<ScrollAnimatorBase> scroll_animator_;
mutable Member<ProgrammaticScrollAnimator> programmatic_scroll_animator_;
@@ -640,6 +649,8 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
Vector<ScrollCallback> pending_scroll_complete_callbacks_;
+ ScrollOffset pending_scroll_anchor_adjustment_;
+
unsigned scrollbar_overlay_color_theme_ : 2;
unsigned horizontal_scrollbar_needs_paint_invalidation_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollable_area_test.cc b/chromium/third_party/blink/renderer/core/scroll/scrollable_area_test.cc
index 8cfee5100d3..7d06943c47a 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollable_area_test.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollable_area_test.cc
@@ -285,7 +285,7 @@ TEST_F(ScrollableAreaTest, ScrollableAreaDidScroll) {
MockScrollableArea* scrollable_area =
MockScrollableArea::Create(ScrollOffset(100, 100));
- scrollable_area->DidScroll(FloatPoint(40, 51));
+ scrollable_area->DidCompositorScroll(FloatPoint(40, 51));
EXPECT_EQ(40, scrollable_area->ScrollOffsetInt().Width());
EXPECT_EQ(51, scrollable_area->ScrollOffsetInt().Height());
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
index ee48f97526d..ef7d3896ee9 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
@@ -130,6 +130,7 @@ int Scrollbar::Maximum() const {
void Scrollbar::OffsetDidChange(mojom::blink::ScrollType scroll_type) {
DCHECK(scrollable_area_);
+ pending_injected_delta_ = ScrollOffset();
float position = ScrollableAreaCurrentPos();
if (position == current_pos_)
@@ -377,7 +378,6 @@ bool Scrollbar::GestureEvent(const WebGestureEvent& evt,
NOTREACHED();
return true;
}
- break;
case WebInputEvent::Type::kGestureScrollUpdate:
switch (evt.SourceDevice()) {
case WebGestureDevice::kSyntheticAutoscroll:
@@ -402,7 +402,6 @@ bool Scrollbar::GestureEvent(const WebGestureEvent& evt,
NOTREACHED();
return true;
}
- break;
case WebInputEvent::Type::kGestureScrollEnd:
// If we see a GSE targeted at the scrollbar, clear the state that
// says we injected GestureScrollBegin, since we no longer need to inject
@@ -608,7 +607,8 @@ void Scrollbar::InjectGestureScrollUpdateForThumbMove(
// Convert the target offset to the delta that will be injected as part of a
// GestureScrollUpdate event.
ScrollOffset current_offset =
- scrollable_area_->GetScrollAnimator().CurrentOffset();
+ scrollable_area_->GetScrollAnimator().CurrentOffset() +
+ pending_injected_delta_;
float desired_x = orientation_ == kHorizontalScrollbar
? single_axis_target_offset
: current_offset.Width();
@@ -659,6 +659,7 @@ void Scrollbar::InjectScrollGesture(WebInputEvent::Type gesture_type,
granularity);
}
+ pending_injected_delta_ += delta;
scrollable_area_->InjectGestureScrollEvent(WebGestureDevice::kScrollbar,
delta, granularity, gesture_type);
@@ -815,16 +816,14 @@ float Scrollbar::ScaleFromDIP() const {
}
float Scrollbar::EffectiveZoom() const {
- if (::features::IsFormControlsRefreshEnabled() && style_source_ &&
- style_source_->GetLayoutObject()) {
+ if (style_source_ && style_source_->GetLayoutObject()) {
return style_source_->GetLayoutObject()->Style()->EffectiveZoom();
}
return 1.0;
}
bool Scrollbar::ContainerIsRightToLeft() const {
- if (::features::IsFormControlsRefreshEnabled() && style_source_ &&
- style_source_->GetLayoutObject()) {
+ if (style_source_ && style_source_->GetLayoutObject()) {
TextDirection dir = style_source_->GetLayoutObject()->Style()->Direction();
return IsRtl(dir);
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
index a0eb0e9b164..dfe6b50cd26 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
@@ -263,6 +263,13 @@ class CORE_EXPORT Scrollbar : public GarbageCollected<Scrollbar>,
IntRect frame_rect_;
Member<Element> style_source_;
+
+ // Tracks scroll delta that has been injected into the compositor thread as a
+ // GestureScrollUpdate but hasn't yet updated the scroll position on main.
+ // Scrollbar::MouseMoved needs this to calculate deltas during thumb drags.
+ // In particular we often process two mousemoves in the same frame thanks to
+ // MouseEventManager::RecomputeMouseHoverState sending fake ones.
+ ScrollOffset pending_injected_delta_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
index 05b828f260f..9c483985984 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
@@ -224,8 +224,8 @@ void ScrollbarThemeMac::SetNewPainterForScrollbar(
ScrollbarPainter ScrollbarThemeMac::PainterForScrollbar(
const Scrollbar& scrollbar) const {
- return
- [GetScrollbarPainterMap().at(const_cast<Scrollbar*>(&scrollbar)) painter];
+ return [GetScrollbarPainterMap().DeprecatedAtOrEmptyValue(
+ const_cast<Scrollbar*>(&scrollbar)) painter];
}
WebThemeEngine::ExtraParams GetPaintParams(const Scrollbar& scrollbar,
@@ -258,6 +258,7 @@ WebThemeEngine::ExtraParams GetPaintParams(const Scrollbar& scrollbar,
params.scrollbar_extra.is_hovering =
scrollbar.HoveredPart() != ScrollbarPart::kNoPart;
+ params.scrollbar_extra.scale_from_dip = scrollbar.ScaleFromDIP();
return params;
}
@@ -355,7 +356,8 @@ void ScrollbarThemeMac::PaintThumbInternal(GraphicsContext& context,
// and because the ScrollAnimator doesn't animate correctly without them.
{
base::scoped_nsobject<BlinkScrollbarObserver> observer(
- GetScrollbarPainterMap().at(const_cast<Scrollbar*>(&scrollbar)),
+ GetScrollbarPainterMap().DeprecatedAtOrEmptyValue(
+ const_cast<Scrollbar*>(&scrollbar)),
base::scoped_policy::RETAIN);
ScrollbarPainter scrollbar_painter = [observer painter];
[scrollbar_painter setEnabled:scrollbar.Enabled()];
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mobile.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mobile.cc
index 37aa2e5d2f5..7532efef804 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mobile.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mobile.cc
@@ -16,7 +16,7 @@ namespace blink {
static const WebThemeEngine::ScrollbarStyle& ScrollbarStyle() {
static bool initialized = false;
DEFINE_STATIC_LOCAL(WebThemeEngine::ScrollbarStyle, style,
- (WebThemeEngine::ScrollbarStyle{3, 4, 0x80808080}));
+ (WebThemeEngine::ScrollbarStyle{3, 4, 3, 4, 0x80808080}));
if (!initialized) {
// During device emulation, the chrome WebThemeEngine implementation may not
// be the mobile theme which can provide the overlay scrollbar styles.
diff --git a/chromium/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/chromium/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
index dfb390ead69..99b87ddc13d 100644
--- a/chromium/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
+++ b/chromium/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -3,9 +3,12 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h"
+
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/features.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/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -73,24 +76,28 @@ void DocumentSpeculationRules::UpdateSpeculationCandidates() {
if (!host)
return;
+ auto* execution_context = GetSupplementable()->GetExecutionContext();
+ network::mojom::ReferrerPolicy referrer_policy =
+ execution_context->GetReferrerPolicy();
+ String outgoing_referrer = execution_context->OutgoingReferrer();
+
Vector<mojom::blink::SpeculationCandidatePtr> candidates;
- auto push_candidates = [&candidates](
+ auto push_candidates = [&candidates, &referrer_policy, &outgoing_referrer](
mojom::blink::SpeculationAction action,
const HeapVector<Member<SpeculationRule>>& rules) {
for (SpeculationRule* rule : rules) {
- mojom::blink::SpeculationCandidate candidate;
- candidate.action = action;
- candidate.requires_anonymous_client_ip_when_cross_origin =
- rule->requires_anonymous_client_ip_when_cross_origin();
for (const KURL& url : rule->urls()) {
- candidate.url = url;
- candidates.push_back(
- mojom::blink::SpeculationCandidate::New(candidate));
+ Referrer referrer = SecurityPolicy::GenerateReferrer(
+ referrer_policy, url, outgoing_referrer);
+ auto referrer_ptr = mojom::blink::Referrer::New(
+ KURL(referrer.referrer), referrer.referrer_policy);
+ candidates.push_back(mojom::blink::SpeculationCandidate::New(
+ url, action, std::move(referrer_ptr),
+ rule->requires_anonymous_client_ip_when_cross_origin()));
}
}
};
- auto* execution_context = GetSupplementable()->GetExecutionContext();
for (SpeculationRuleSet* rule_set : rule_sets_) {
// If kSpeculationRulesPrefetchProxy is enabled, collect all prefetch
// speculation rules.
@@ -107,6 +114,15 @@ void DocumentSpeculationRules::UpdateSpeculationCandidates() {
if (RuntimeEnabledFeatures::Prerender2Enabled(execution_context)) {
push_candidates(mojom::blink::SpeculationAction::kPrerender,
rule_set->prerender_rules());
+
+ // Set the flag to evict the cached data of Session Storage when the
+ // document is frozen or unload to avoid reusing old data in the cache
+ // after the session storage has been modified by another renderer
+ // process. See crbug.com/1215680 for more details.
+ LocalFrame* frame = GetSupplementable()->GetFrame();
+ if (frame->IsMainFrame()) {
+ frame->SetEvictCachedSessionStorageOnFreezeOrUnload();
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
index ed9199451dc..cf12a455854 100644
--- a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
+++ b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
@@ -86,16 +86,24 @@ SpeculationRule* ParseSpeculationRule(JSONObject* input, const KURL& base_url) {
// static
SpeculationRuleSet* SpeculationRuleSet::ParseInline(const String& source_text,
- const KURL& base_url) {
+ const KURL& base_url,
+ String* out_error) {
// https://jeremyroman.github.io/alternate-loading-modes/#parse-speculation-rules
// Let parsed be the result of parsing a JSON string to an Infra value given
// input.
- auto parsed = JSONObject::From(ParseJSON(source_text));
+ JSONParseError parse_error;
+ auto parsed = JSONObject::From(ParseJSON(source_text, &parse_error));
// If parsed is not a map, then return null.
- if (!parsed)
+ if (!parsed) {
+ if (out_error) {
+ *out_error = parse_error.type != JSONParseErrorType::kNoError
+ ? parse_error.message
+ : "Parsed JSON must be an object.";
+ }
return nullptr;
+ }
// Let result be an empty speculation rule set.
SpeculationRuleSet* result = MakeGarbageCollected<SpeculationRuleSet>();
diff --git a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
index 0ae337a3e82..9f55df9617f 100644
--- a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
+++ b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
@@ -24,8 +24,12 @@ class SpeculationRule;
class CORE_EXPORT SpeculationRuleSet final
: public GarbageCollected<SpeculationRuleSet> {
public:
+ // If provided, |out_error| may be populated with an error/warning message.
+ // A warning may be present even if parsing succeeds, to indicate a case that,
+ // though valid, is likely to be an error.
static SpeculationRuleSet* ParseInline(const String& source_text,
- const KURL& base_url);
+ const KURL& base_url,
+ String* out_error = nullptr);
const HeapVector<Member<SpeculationRule>>& prefetch_rules() const {
return prefetch_rules_;
diff --git a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
index f389759fe09..07dd6c8086e 100644
--- a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
+++ b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h"
#include "base/bind.h"
+#include "base/ranges/algorithm.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -18,6 +19,7 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
+#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.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"
@@ -187,9 +189,19 @@ TEST_F(SpeculationRuleSetTest, RequiresAnonymousClientIPWhenCrossOrigin) {
}
TEST_F(SpeculationRuleSetTest, RejectsInvalidJSON) {
- auto* rule_set =
- SpeculationRuleSet::ParseInline("[invalid]", KURL("https://example.com"));
+ String parse_error;
+ auto* rule_set = SpeculationRuleSet::ParseInline(
+ "[invalid]", KURL("https://example.com"), &parse_error);
+ EXPECT_FALSE(rule_set);
+ EXPECT_TRUE(parse_error.Contains("Syntax error"));
+}
+
+TEST_F(SpeculationRuleSetTest, RejectsNonObject) {
+ String parse_error;
+ auto* rule_set = SpeculationRuleSet::ParseInline(
+ "42", KURL("https://example.com"), &parse_error);
EXPECT_FALSE(rule_set);
+ EXPECT_TRUE(parse_error.Contains("must be an object"));
}
TEST_F(SpeculationRuleSetTest, IgnoresUnknownOrDifferentlyTypedTopLevelKeys) {
@@ -228,7 +240,8 @@ TEST_F(SpeculationRuleSetTest, DropUnrecognizedRules) {
// This includes totally invalid ones and ones with unacceptable schemes.
R"({"source": "list",
"urls": [
- "valid.html", "mailto:alice@example.com", "http://@:"
+ "valid.html", "mailto:alice@example.com", "http://@:",
+ "blob:https://bar"
]
}]})",
KURL("https://example.com/"));
@@ -449,5 +462,41 @@ TEST_F(SpeculationRuleSetTest, UseCounter) {
page_holder.GetDocument().IsUseCounted(WebFeature::kSpeculationRules));
}
+class ConsoleCapturingChromeClient : public EmptyChromeClient {
+ public:
+ void AddMessageToConsole(LocalFrame*,
+ mojom::ConsoleMessageSource,
+ mojom::ConsoleMessageLevel,
+ const String& message,
+ unsigned line_number,
+ const String& source_id,
+ const String& stack_trace) override {
+ messages_.push_back(message);
+ }
+
+ const Vector<String>& ConsoleMessages() const { return messages_; }
+
+ private:
+ Vector<String> messages_;
+};
+
+// Tests that parse errors are logged to the console.
+TEST_F(SpeculationRuleSetTest, ConsoleWarning) {
+ auto* chrome_client = MakeGarbageCollected<ConsoleCapturingChromeClient>();
+ DummyPageHolder page_holder(/*initial_view_size=*/{}, chrome_client);
+ page_holder.GetFrame().GetSettings()->SetScriptEnabled(true);
+
+ Document& document = page_holder.GetDocument();
+ HTMLScriptElement* script =
+ MakeGarbageCollected<HTMLScriptElement>(document, CreateElementFlags());
+ script->setAttribute(html_names::kTypeAttr, "speculationrules");
+ script->setText("[invalid]");
+ document.head()->appendChild(script);
+
+ EXPECT_TRUE(base::ranges::any_of(
+ chrome_client->ConsoleMessages(),
+ [](const String& message) { return message.Contains("Syntax error"); }));
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rules_origin_trial_test.cc b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rules_origin_trial_test.cc
index 3344a4cbfe1..731658a9366 100644
--- a/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rules_origin_trial_test.cc
+++ b/chromium/third_party/blink/renderer/core/speculation_rules/speculation_rules_origin_trial_test.cc
@@ -4,12 +4,11 @@
#include <vector>
#include "base/bind.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
-#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_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/settings.h"
@@ -24,12 +23,6 @@
namespace blink {
namespace {
-constexpr char 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,
-};
-
// Generated by:
// tools/origin_trials/generate_token.py --version 3 --expire-days 3650 \
// https://speculationrules.test SpeculationRulesPrefetch
@@ -58,22 +51,6 @@ constexpr char kSimplePrefetchProxyRuleSet[] =
}]
})";
-class ScopedOriginTrialPolicy : public OriginTrialPolicy {
- public:
- ScopedOriginTrialPolicy() {
- TrialTokenValidator::SetOriginTrialPolicyGetter(WTF::BindRepeating(
- [](OriginTrialPolicy* self) { return self; }, base::Unretained(this)));
- }
- ~ScopedOriginTrialPolicy() override {
- TrialTokenValidator::ResetOriginTrialPolicyGetter();
- }
- bool IsOriginTrialsSupported() const override { return true; }
- std::vector<base::StringPiece> GetPublicKeys() const override {
- return {{kOriginTrialPublicKey, base::size(kOriginTrialPublicKey)}};
- }
- bool IsOriginSecure(const GURL& url) const override { return true; }
-};
-
// Similar to SpeculationRuleSettest.PropagatesToDocument.
::testing::AssertionResult DocumentAcceptsRuleSet(const char* trial_token,
const char* json) {
@@ -116,7 +93,7 @@ TEST(SpeculationRulesOriginTrialTest, RequiresBaseFeature) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndDisableFeature(
features::kSpeculationRulesPrefetchProxy);
- ScopedOriginTrialPolicy using_test_keys;
+ ScopedTestOriginTrialPolicy using_test_keys;
EXPECT_FALSE(DocumentAcceptsRuleSet(kSpeculationRulesPrefetchToken,
kSimplePrefetchProxyRuleSet));
@@ -127,7 +104,7 @@ TEST(SpeculationRulesOriginTrialTest, RequiresValidToken) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kSpeculationRulesPrefetchProxy);
- ScopedOriginTrialPolicy using_test_keys;
+ ScopedTestOriginTrialPolicy using_test_keys;
EXPECT_FALSE(
DocumentAcceptsRuleSet("invalid token", kSimplePrefetchProxyRuleSet));
@@ -138,7 +115,7 @@ TEST(SpeculationRulesOriginTrialTest, BaseFeatureAndValidTokenSuffice) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kSpeculationRulesPrefetchProxy);
- ScopedOriginTrialPolicy using_test_keys;
+ ScopedTestOriginTrialPolicy using_test_keys;
EXPECT_TRUE(DocumentAcceptsRuleSet(kSpeculationRulesPrefetchToken,
kSimplePrefetchProxyRuleSet));
diff --git a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h
index 692b138f2ee..4dfd5b240f2 100644
--- a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h
+++ b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h
@@ -168,6 +168,8 @@ class StrategyUnpacker final {
// arbitrary user code. The object cannot be used if
// exception_state.HadException() is true.
StrategyUnpacker(ScriptState*, ScriptValue strategy, ExceptionState&);
+ StrategyUnpacker(const StrategyUnpacker&) = delete;
+ StrategyUnpacker& operator=(const StrategyUnpacker&) = delete;
~StrategyUnpacker() = default;
// Performs MakeSizeAlgorithmFromSizeFunction on |size_|. Because this method
@@ -186,8 +188,6 @@ class StrategyUnpacker final {
private:
v8::Local<v8::Value> size_;
v8::Local<v8::Value> high_water_mark_;
-
- DISALLOW_COPY_AND_ASSIGN(StrategyUnpacker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc b/chromium/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc
index f8798d71f5b..25abbf5c7e8 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc
@@ -6,7 +6,7 @@
#include "base/numerics/checked_math.h"
#include "base/numerics/clamped_math.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source_cancel_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source_pull_callback.h"
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
index 127ac6e59cf..922fab98f91 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -4,9 +4,8 @@
#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
-#include "third_party/blink/renderer/bindings/core/v8/readable_stream_default_reader_or_readable_stream_byob_reader.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_abort_signal.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
@@ -96,6 +95,8 @@ class ReadableStream::PipeToEngine final
public:
PipeToEngine(ScriptState* script_state, PipeOptions* pipe_options)
: script_state_(script_state), pipe_options_(pipe_options) {}
+ PipeToEngine(const PipeToEngine&) = delete;
+ PipeToEngine& operator=(const PipeToEngine&) = delete;
// This is the main entrypoint for ReadableStreamPipeTo().
ScriptPromise Start(ReadableStream* readable, WritableStream* destination) {
@@ -702,13 +703,13 @@ class ReadableStream::PipeToEngine final
TraceWrapperV8Reference<v8::Value> shutdown_error_;
bool is_shutting_down_ = false;
bool is_reading_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(PipeToEngine);
};
class ReadableStream::TeeEngine final : public GarbageCollected<TeeEngine> {
public:
TeeEngine() = default;
+ TeeEngine(const TeeEngine&) = delete;
+ TeeEngine& operator=(const TeeEngine&) = delete;
// Create the streams and start copying data.
void Start(ScriptState*, ReadableStream*, ExceptionState&);
@@ -746,8 +747,6 @@ class ReadableStream::TeeEngine final : public GarbageCollected<TeeEngine> {
TraceWrapperV8Reference<v8::Value> reason_[2];
Member<ReadableStream> branch_[2];
Member<ReadableStreamDefaultController> controller_[2];
-
- DISALLOW_COPY_AND_ASSIGN(TeeEngine);
};
class ReadableStream::TeeEngine::PullAlgorithm final : public StreamAlgorithm {
@@ -1115,32 +1114,44 @@ ReadableStream* ReadableStream::CreateWithCountQueueingStrategy(
AllowPerChunkTransferring allow_per_chunk_transferring,
std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer) {
auto* isolate = script_state->GetIsolate();
-
- auto strategy = CreateTrivialQueuingStrategy(isolate, high_water_mark);
-
ExceptionState exception_state(isolate, ExceptionState::kConstructionContext,
"ReadableStream");
v8::MicrotasksScope microtasks_scope(
isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
- v8::Local<v8::Value> underlying_source_v8 =
- ToV8(underlying_source, script_state);
-
auto* stream = MakeGarbageCollected<ReadableStream>();
- stream->InitInternal(script_state, ScriptValue(isolate, underlying_source_v8),
- strategy, true, exception_state);
-
+ stream->InitWithCountQueueingStrategy(
+ script_state, underlying_source, high_water_mark,
+ allow_per_chunk_transferring, std::move(optimizer), exception_state);
if (exception_state.HadException()) {
exception_state.ClearException();
DLOG(WARNING)
<< "Ignoring an exception in CreateWithCountQueuingStrategy().";
}
-
- stream->allow_per_chunk_transferring_ = allow_per_chunk_transferring;
- stream->transferring_optimizer_ = std::move(optimizer);
return stream;
}
+void ReadableStream::InitWithCountQueueingStrategy(
+ ScriptState* script_state,
+ UnderlyingSourceBase* underlying_source,
+ size_t high_water_mark,
+ AllowPerChunkTransferring allow_per_chunk_transferring,
+ std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer,
+ ExceptionState& exception_state) {
+ auto* isolate = script_state->GetIsolate();
+
+ auto strategy = CreateTrivialQueuingStrategy(isolate, high_water_mark);
+
+ v8::Local<v8::Value> underlying_source_v8 =
+ ToV8(underlying_source, script_state);
+
+ InitInternal(script_state, ScriptValue(isolate, underlying_source_v8),
+ strategy, true, exception_state);
+
+ allow_per_chunk_transferring_ = allow_per_chunk_transferring;
+ transferring_optimizer_ = std::move(optimizer);
+}
+
ReadableStream* ReadableStream::Create(ScriptState* script_state,
StreamStartAlgorithm* start_algorithm,
StreamAlgorithm* pull_algorithm,
@@ -1216,7 +1227,6 @@ ScriptPromise ReadableStream::cancel(ScriptState* script_state,
return ScriptPromise(script_state, result);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8ReadableStreamReader* ReadableStream::getReader(
ScriptState* script_state,
ExceptionState& exception_state) {
@@ -1229,20 +1239,7 @@ V8ReadableStreamReader* ReadableStream::getReader(
return nullptr;
return MakeGarbageCollected<V8ReadableStreamReader>(reader);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ReadableStream::getReader(
- ScriptState* script_state,
- ReadableStreamDefaultReaderOrReadableStreamBYOBReader& return_value,
- ExceptionState& exception_state) {
- // https://streams.spec.whatwg.org/#rs-get-reader
- // 1. If options["mode"] does not exist, return ?
- // AcquireReadableStreamDefaultReader(this).
- return_value.SetReadableStreamDefaultReader(
- AcquireDefaultReader(script_state, this, true, exception_state));
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8ReadableStreamReader* ReadableStream::getReader(
ScriptState* script_state,
const ReadableStreamGetReaderOptions* options,
@@ -1263,40 +1260,14 @@ V8ReadableStreamReader* ReadableStream::getReader(
return getReader(script_state, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ReadableStream::getReader(
- ScriptState* script_state,
- ReadableStreamGetReaderOptions* options,
- ReadableStreamDefaultReaderOrReadableStreamBYOBReader& return_value,
- ExceptionState& exception_state) {
- // https://streams.spec.whatwg.org/#rs-get-reader
- if (options->hasMode()) {
- DCHECK_EQ(options->mode(), "byob");
-
- UseCounter::Count(ExecutionContext::From(script_state),
- WebFeature::kReadableStreamBYOBReader);
-
- return_value.SetReadableStreamBYOBReader(
- AcquireBYOBReader(script_state, this, exception_state));
- } else {
- getReader(script_state, return_value, exception_state);
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ReadableStreamDefaultReader* ReadableStream::GetDefaultReaderForTesting(
ScriptState* script_state,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* result = getReader(script_state, exception_state);
if (!result)
return nullptr;
return result->GetAsReadableStreamDefaultReader();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ReadableStreamDefaultReaderOrReadableStreamBYOBReader return_value;
- getReader(script_state, return_value, exception_state);
- return return_value.GetAsReadableStreamDefaultReader();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
ReadableStream* ReadableStream::pipeThrough(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream.h b/chromium/third_party/blink/renderer/core/streams/readable_stream.h
index 687a618f03d..136f600fa6c 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/streams/readable_stream_byob_reader.h"
@@ -28,7 +27,6 @@ class MessagePort;
class ReadableByteStreamController;
class ReadableStreamController;
class ReadableStreamDefaultController;
-class ReadableStreamDefaultReaderOrReadableStreamBYOBReader;
class ReadableStreamGetReaderOptions;
class ReadableStreamTransferringOptimizer;
class ReadableWritablePair;
@@ -117,6 +115,16 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
~ReadableStream() override;
+ // See CreateWithCountQueueingStrategy() comment above for how to use
+ // `allow_per_chunk_transferring`.
+ void InitWithCountQueueingStrategy(
+ ScriptState*,
+ UnderlyingSourceBase*,
+ size_t high_water_mark,
+ AllowPerChunkTransferring allow_per_chunk_transferring,
+ std::unique_ptr<ReadableStreamTransferringOptimizer>,
+ ExceptionState&);
+
// https://streams.spec.whatwg.org/#rs-constructor
bool locked() const;
@@ -125,29 +133,14 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
// https://streams.spec.whatwg.org/#rs-cancel
ScriptPromise cancel(ScriptState*, ScriptValue reason, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8ReadableStreamReader* getReader(ScriptState* script_state,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void getReader(
- ScriptState*,
- ReadableStreamDefaultReaderOrReadableStreamBYOBReader& return_value,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// https://streams.spec.whatwg.org/#rs-get-reader
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8ReadableStreamReader* getReader(
ScriptState* script_state,
const ReadableStreamGetReaderOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void getReader(
- ScriptState*,
- ReadableStreamGetReaderOptions* options,
- ReadableStreamDefaultReaderOrReadableStreamBYOBReader& return_value,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ReadableStreamDefaultReader* GetDefaultReaderForTesting(ScriptState*,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_generic_reader.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_generic_reader.cc
index 7168d98f410..131320c2292 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_generic_reader.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_generic_reader.cc
@@ -70,6 +70,7 @@ void ReadableStreamGenericReader::GenericRelease(
// 3. If reader.[[ownerReadableStream]].[[state]] is "readable", reject
// reader.[[closedPromise]] with a TypeError exception.
if (reader->owner_readable_stream_->state_ == ReadableStream::kReadable) {
+ reader->closed_promise_->MarkAsSilent(isolate);
reader->closed_promise_->Reject(
script_state,
v8::Exception::TypeError(V8String(
@@ -79,7 +80,7 @@ void ReadableStreamGenericReader::GenericRelease(
} else {
// 4. Otherwise, set reader.[[closedPromise]] to a promise rejected with a
// TypeError exception.
- reader->closed_promise_ = StreamPromiseResolver::CreateRejected(
+ reader->closed_promise_ = StreamPromiseResolver::CreateRejectedAndSilent(
script_state, v8::Exception::TypeError(V8String(
isolate,
"This readable stream reader has been released and "
@@ -152,7 +153,7 @@ void ReadableStreamGenericReader::GenericInitialize(
// b. Set reader.[[closedPromise]] to a promise rejected with stream.
// [[storedError]].
- reader->closed_promise_ = StreamPromiseResolver::CreateRejected(
+ reader->closed_promise_ = StreamPromiseResolver::CreateRejectedAndSilent(
script_state, stream->GetStoredError(isolate));
// c. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
index e03a6143541..04478de51e6 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -6,7 +6,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/readable_stream_default_reader_or_readable_stream_byob_reader.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"
@@ -251,18 +250,11 @@ TEST_F(ReadableStreamTest, GetBYOBReader) {
auto* options = ReadableStreamGetReaderOptions::Create();
options->setMode("byob");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ReadableStreamBYOBReader* reader = nullptr;
if (const auto* result =
stream->getReader(script_state, options, ASSERT_NO_EXCEPTION)) {
reader = result->GetAsReadableStreamBYOBReader();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ReadableStreamDefaultReaderOrReadableStreamBYOBReader return_value;
- stream->getReader(script_state, options, return_value, ASSERT_NO_EXCEPTION);
- ReadableStreamBYOBReader* reader =
- return_value.GetAsReadableStreamBYOBReader();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ASSERT_TRUE(reader);
EXPECT_TRUE(stream->locked());
diff --git a/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.cc b/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.cc
index a6784644f21..c7c2120f145 100644
--- a/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.cc
@@ -32,6 +32,15 @@ StreamPromiseResolver* StreamPromiseResolver::CreateRejected(
return promise;
}
+StreamPromiseResolver* StreamPromiseResolver::CreateRejectedAndSilent(
+ ScriptState* script_state,
+ v8::Local<v8::Value> reason) {
+ auto* promise = MakeGarbageCollected<StreamPromiseResolver>(script_state);
+ promise->MarkAsSilent(script_state->GetIsolate());
+ promise->Reject(script_state, reason);
+ return promise;
+}
+
StreamPromiseResolver::StreamPromiseResolver(ScriptState* script_state) {
v8::Local<v8::Promise::Resolver> resolver;
if (v8::Promise::Resolver::New(script_state->GetContext())
@@ -103,6 +112,14 @@ void StreamPromiseResolver::MarkAsHandled(v8::Isolate* isolate) {
promise->MarkAsHandled();
}
+void StreamPromiseResolver::MarkAsSilent(v8::Isolate* isolate) {
+ v8::Local<v8::Promise> promise = V8Promise(isolate);
+ if (promise.IsEmpty()) {
+ return;
+ }
+ promise->MarkAsSilent();
+}
+
v8::Promise::PromiseState StreamPromiseResolver::State(
v8::Isolate* isolate) const {
v8::Local<v8::Promise> promise = V8Promise(isolate);
diff --git a/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.h b/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.h
index 13723308f85..f6fb50a70f4 100644
--- a/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.h
+++ b/chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.h
@@ -46,6 +46,12 @@ class CORE_EXPORT StreamPromiseResolver final
static StreamPromiseResolver* CreateRejected(ScriptState*,
v8::Local<v8::Value> reason);
+ // Similar to CreateRejected but marks the promise as silent before rejecting.
+ // https://crbug.com/1132506
+ static StreamPromiseResolver* CreateRejectedAndSilent(
+ ScriptState*,
+ v8::Local<v8::Value> reason);
+
// Creates an initialised promise.
explicit StreamPromiseResolver(ScriptState*);
@@ -70,6 +76,10 @@ class CORE_EXPORT StreamPromiseResolver final
// an unhandled rejection.
void MarkAsHandled(v8::Isolate*);
+ // Marks the promise as silent so that it doesn't pause the debugger when it
+ // rejects.
+ void MarkAsSilent(v8::Isolate*);
+
// Returns the state of the promise, one of pending, fulfilled or rejected.
v8::Promise::PromiseState State(v8::Isolate*) const;
diff --git a/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc b/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
index 643e1028c2a..7455c7b49bd 100644
--- a/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -7,8 +7,7 @@
#include "third_party/blink/renderer/core/streams/transferable_streams.h"
-#include "base/stl_util.h"
-#include "third_party/blink/renderer/bindings/core/v8/readable_stream_default_reader_or_readable_stream_byob_reader.h"
+#include "base/cxx17_backports.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/bindings/core/v8/v8_dom_exception.h"
diff --git a/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc b/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc
index a8b6a8b7f50..4c6656f3f8d 100644
--- a/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc
@@ -6,7 +6,6 @@
#include "base/types/strong_alias.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/readable_stream_default_reader_or_readable_stream_byob_reader.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"
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_transformer.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_transformer.h
index 530b2c9ee07..f5aa8a4f5c4 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_transformer.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_transformer.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_TRANSFORMER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_TRANSFORMER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -27,6 +26,9 @@ class CORE_EXPORT TransformStreamTransformer
: public GarbageCollected<TransformStreamTransformer> {
public:
TransformStreamTransformer() = default;
+ TransformStreamTransformer(const TransformStreamTransformer&) = delete;
+ TransformStreamTransformer& operator=(const TransformStreamTransformer&) =
+ delete;
virtual ~TransformStreamTransformer() = default;
virtual ScriptPromise Transform(v8::Local<v8::Value> chunk,
@@ -39,9 +41,6 @@ class CORE_EXPORT TransformStreamTransformer
virtual ScriptState* GetScriptState() = 0;
virtual void Trace(Visitor*) const {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TransformStreamTransformer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
index e47f01b3514..e635e5094bb 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -45,6 +45,8 @@ class WritableStream::PendingAbortRequest final
: promise_(promise),
reason_(isolate, reason),
was_already_erroring_(was_already_erroring) {}
+ PendingAbortRequest(const PendingAbortRequest&) = delete;
+ PendingAbortRequest& operator=(const PendingAbortRequest&) = delete;
StreamPromiseResolver* GetPromise() { return promise_; }
v8::Local<v8::Value> Reason(v8::Isolate* isolate) {
@@ -62,8 +64,6 @@ class WritableStream::PendingAbortRequest final
Member<StreamPromiseResolver> promise_;
TraceWrapperV8Reference<v8::Value> reason_;
const bool was_already_erroring_;
-
- DISALLOW_COPY_AND_ASSIGN(PendingAbortRequest);
};
WritableStream* WritableStream::Create(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream.h b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
index 0022a256b85..e10cdd66c97 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "third_party/abseil-cpp/absl/types/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"
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
index c7bc87aca5d..c1a73e1a996 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// This is only used when the new C++ implementation is enabled.
-
// https://streams.spec.whatwg.org/#ws-default-controller-class-definition
+[
+ Exposed=(Window,Worker,Worklet)
+]
interface WritableStreamDefaultController {
[CallWith=ScriptState] void error(optional any e);
};
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc
index 10bf54a2bc6..8888b9036a1 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc
@@ -92,7 +92,7 @@ WritableStreamDefaultWriter::WritableStreamDefaultWriter(
case WritableStream::kErroring: {
// a. Set this.[[readyPromise]] to a promise rejected with
// stream.[[storedError]].
- ready_promise_ = StreamPromiseResolver::CreateRejected(
+ ready_promise_ = StreamPromiseResolver::CreateRejectedAndSilent(
script_state, stream->GetStoredError(isolate));
// b. Set this.[[readyPromise]].[[PromiseIsHandled]] to true.
@@ -127,16 +127,16 @@ WritableStreamDefaultWriter::WritableStreamDefaultWriter(
// c. Set this.[[readyPromise]] to a promise rejected with
// storedError.
- ready_promise_ =
- StreamPromiseResolver::CreateRejected(script_state, stored_error);
+ ready_promise_ = StreamPromiseResolver::CreateRejectedAndSilent(
+ script_state, stored_error);
// d. Set this.[[readyPromise]].[[PromiseIsHandled]] to true.
ready_promise_->MarkAsHandled(isolate);
// e. Set this.[[closedPromise]] to a promise rejected with
// storedError.
- closed_promise_ =
- StreamPromiseResolver::CreateRejected(script_state, stored_error);
+ closed_promise_ = StreamPromiseResolver::CreateRejectedAndSilent(
+ script_state, stored_error);
// f. Set this.[[closedPromise]].[[PromiseIsHandled]] to true.
closed_promise_->MarkAsHandled(isolate);
@@ -284,12 +284,13 @@ void WritableStreamDefaultWriter::EnsureReadyPromiseRejected(
// 1. If writer.[[readyPromise]].[[PromiseState]] is "pending", reject
// writer.[[readyPromise]] with error.
if (!writer->ready_promise_->IsSettled()) {
+ writer->ready_promise_->MarkAsSilent(isolate);
writer->ready_promise_->Reject(script_state, error);
} else {
// 2. Otherwise, set writer.[[readyPromise]] to a promise rejected with
// error.
writer->ready_promise_ =
- StreamPromiseResolver::CreateRejected(script_state, error);
+ StreamPromiseResolver::CreateRejectedAndSilent(script_state, error);
}
// 3. Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
@@ -517,12 +518,13 @@ void WritableStreamDefaultWriter::EnsureClosedPromiseRejected(
// 1. If writer.[[closedPromise]].[[PromiseState]] is "pending", reject
// writer.[[closedPromise]] with error.
if (!writer->closed_promise_->IsSettled()) {
+ writer->closed_promise_->MarkAsSilent(isolate);
writer->closed_promise_->Reject(script_state, error);
} else {
// 2. Otherwise, set writer.[[closedPromise]] to a promise rejected with
// error.
writer->closed_promise_ =
- StreamPromiseResolver::CreateRejected(script_state, error);
+ StreamPromiseResolver::CreateRejectedAndSilent(script_state, error);
}
// 3. Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
diff --git a/chromium/third_party/blink/renderer/core/style/OWNERS b/chromium/third_party/blink/renderer/core/style/OWNERS
index 7c1cab453b7..ec2b6419752 100644
--- a/chromium/third_party/blink/renderer/core/style/OWNERS
+++ b/chromium/third_party/blink/renderer/core/style/OWNERS
@@ -1,4 +1,3 @@
-alancutter@chromium.org
andruud@chromium.org
ericwilligers@chromium.org
futhark@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/style/basic_shapes.h b/chromium/third_party/blink/renderer/core/style/basic_shapes.h
index 932a64a8b65..e423999631b 100644
--- a/chromium/third_party/blink/renderer/core/style/basic_shapes.h
+++ b/chromium/third_party/blink/renderer/core/style/basic_shapes.h
@@ -89,10 +89,9 @@ class BasicShapeCenterCoordinate {
? length
: length.SubtractFromOneHundredPercent()) {}
- BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate& other)
- : direction_(other.GetDirection()),
- length_(other.length()),
- computed_length_(other.computed_length_) {}
+ BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate&) = default;
+ BasicShapeCenterCoordinate& operator=(const BasicShapeCenterCoordinate&) =
+ default;
bool operator==(const BasicShapeCenterCoordinate& other) const {
return direction_ == other.direction_ && length_ == other.length_ &&
@@ -117,8 +116,8 @@ class BasicShapeRadius {
BasicShapeRadius() : type_(kClosestSide) {}
explicit BasicShapeRadius(const Length& v) : value_(v), type_(kValue) {}
explicit BasicShapeRadius(RadiusType t) : type_(t) {}
- BasicShapeRadius(const BasicShapeRadius& other)
- : value_(other.Value()), type_(other.GetType()) {}
+ BasicShapeRadius(const BasicShapeRadius&) = default;
+ BasicShapeRadius& operator=(const BasicShapeRadius&) = default;
bool operator==(const BasicShapeRadius& other) const {
return type_ == other.type_ && value_ == other.value_;
}
diff --git a/chromium/third_party/blink/renderer/core/style/build.gni b/chromium/third_party/blink/renderer/core/style/build.gni
index 3f955ff42c4..c8cf135c142 100644
--- a/chromium/third_party/blink/renderer/core/style/build.gni
+++ b/chromium/third_party/blink/renderer/core/style/build.gni
@@ -60,8 +60,12 @@ blink_core_sources_style = [
"shape_clip_path_operation.h",
"shape_value.h",
"style_aspect_ratio.h",
+ "style_base_data.h",
+ "style_base_data.cc",
"style_cached_data.h",
"style_content_alignment_data.h",
+ "style_crossfade_image.cc",
+ "style_crossfade_image.h",
"style_difference.cc",
"style_difference.h",
"style_fetched_image.cc",
@@ -90,6 +94,8 @@ blink_core_sources_style = [
"style_ray.h",
"style_reflection.h",
"style_self_alignment_data.h",
+ "style_svg_resource.cc",
+ "style_svg_resource.h",
"style_variables.cc",
"style_variables.h",
"svg_dash_array.cc",
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 52b16de6bb7..f240ccd0dcf 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.cc
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.cc
@@ -27,9 +27,9 @@
#include <memory>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/clamped_math.h"
-#include "base/numerics/ranges.h"
#include "build/build_config.h"
#include "cc/input/overscroll_behavior.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
@@ -37,11 +37,14 @@
#include "third_party/blink/renderer/core/css/css_paint_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_property_equality.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/properties/longhand.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.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/html/html_progress_element.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h"
@@ -99,11 +102,13 @@ ASSERT_SIZE(BorderValue, SameSizeAsBorderValue);
struct SameSizeAsComputedStyleBase {
SameSizeAsComputedStyleBase() {
base::debug::Alias(&data_refs);
+ base::debug::Alias(&pointers);
base::debug::Alias(&bitfields);
}
private:
- void* data_refs[9];
+ void* data_refs[8];
+ void* pointers[1];
unsigned bitfields[5];
};
@@ -150,6 +155,25 @@ scoped_refptr<ComputedStyle> ComputedStyle::CreateInitialStyleSingleton() {
return base::MakeRefCounted<ComputedStyle>(PassKey());
}
+Vector<AtomicString>* ComputedStyle::GetVariableNamesCache() const {
+ if (cached_data_)
+ return cached_data_->variable_names_.get();
+ return nullptr;
+}
+
+Vector<AtomicString>& ComputedStyle::EnsureVariableNamesCache() const {
+ if (!cached_data_ || !cached_data_->variable_names_) {
+ EnsureCachedData().variable_names_ =
+ std::make_unique<Vector<AtomicString>>();
+ }
+ return *cached_data_->variable_names_;
+}
+
+void ComputedStyle::ClearVariableNamesCache() const {
+ if (cached_data_)
+ cached_data_->variable_names_.reset();
+}
+
scoped_refptr<ComputedStyle> ComputedStyle::Clone(const ComputedStyle& other) {
return base::AdoptRef(new ComputedStyle(PassKey(), other));
}
@@ -188,6 +212,25 @@ static bool PseudoElementStylesEqual(const ComputedStyle& old_style,
return true;
}
+static bool DiffAffectsContainerQueries(const ComputedStyle& old_style,
+ const ComputedStyle& new_style) {
+ if (!old_style.IsContainerForContainerQueries() &&
+ !new_style.IsContainerForContainerQueries()) {
+ return false;
+ }
+ if ((old_style.ContainerName() != new_style.ContainerName()) ||
+ (old_style.ContainerType() != new_style.ContainerType())) {
+ return true;
+ }
+ if (new_style.Display() != old_style.Display()) {
+ if (new_style.Display() == EDisplay::kNone ||
+ new_style.Display() == EDisplay::kContents) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool ComputedStyle::NeedsReattachLayoutTree(const Element& element,
const ComputedStyle* old_style,
const ComputedStyle* new_style) {
@@ -223,9 +266,27 @@ bool ComputedStyle::NeedsReattachLayoutTree(const Element& element,
// based on appearance.
return true;
}
+
+ // LayoutObject tree structure for <legend> depends on whether it's a
+ // rendered legend or not.
+ if (UNLIKELY(IsA<HTMLLegendElement>(element) &&
+ (old_style->IsFloating() != new_style->IsFloating() ||
+ old_style->HasOutOfFlowPosition() !=
+ new_style->HasOutOfFlowPosition())))
+ return true;
+
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return false;
+ // We use LayoutNGTextCombine only for vertical writing mode.
+ if (RuntimeEnabledFeatures::LayoutNGTextCombineEnabled() &&
+ new_style->HasTextCombine() &&
+ old_style->IsHorizontalWritingMode() !=
+ new_style->IsHorizontalWritingMode()) {
+ DCHECK_EQ(old_style->HasTextCombine(), new_style->HasTextCombine());
+ return true;
+ }
+
// LayoutNG needs an anonymous inline wrapper if ::first-line is applied.
// Also see |LayoutBlockFlow::NeedsAnonymousInlineWrapper()|.
if (new_style->HasPseudoElementStyle(kPseudoIdFirstLine) &&
@@ -271,7 +332,10 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle(
DCHECK_NE(&old_style, &new_style);
if (old_style.Display() != new_style.Display() &&
old_style.BlockifiesChildren() != new_style.BlockifiesChildren())
- return Difference::kDisplayAffectingDescendantStyles;
+ return Difference::kDescendantAffecting;
+ // TODO(crbug.com/1213888): Only recalc affected descendants.
+ if (DiffAffectsContainerQueries(old_style, new_style))
+ return Difference::kDescendantAffecting;
if (!old_style.NonIndependentInheritedEqual(new_style))
return Difference::kInherited;
if (old_style.JustifyItems() != new_style.JustifyItems())
@@ -308,8 +372,11 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle(
void ComputedStyle::PropagateIndependentInheritedProperties(
const ComputedStyle& parent_style) {
ComputedStyleBase::PropagateIndependentInheritedProperties(parent_style);
- if (!HasVariableReference() && !HasVariableDeclaration())
- InheritCustomPropertiesFrom(parent_style);
+ if (!HasVariableReference() && !HasVariableDeclaration() &&
+ (InheritedVariables() != parent_style.InheritedVariables())) {
+ MutableInheritedVariablesInternal() =
+ parent_style.InheritedVariablesInternal();
+ }
}
StyleSelfAlignmentData ResolvedSelfAlignment(
@@ -529,6 +596,18 @@ void ComputedStyle::ClearCachedPseudoElementStyles() const {
cached_data_->pseudo_element_styles_->clear();
}
+const ComputedStyle* ComputedStyle::GetBaseComputedStyle() const {
+ if (auto* base_data = BaseData().get())
+ return base_data->GetBaseComputedStyle();
+ return nullptr;
+}
+
+const CSSBitset* ComputedStyle::GetBaseImportantSet() const {
+ if (auto* base_data = BaseData().get())
+ return base_data->GetBaseImportantSet();
+ return nullptr;
+}
+
bool ComputedStyle::InheritedEqual(const ComputedStyle& other) const {
return IndependentInheritedEqual(other) &&
NonIndependentInheritedEqual(other);
@@ -1008,14 +1087,11 @@ void ComputedStyle::ClearCursorList() {
static bool HasPropertyThatCreatesStackingContext(
const Vector<CSSPropertyID>& properties) {
for (CSSPropertyID property : properties) {
- switch (property) {
+ switch (ResolveCSSPropertyID(property)) {
case CSSPropertyID::kOpacity:
case CSSPropertyID::kTransform:
- case CSSPropertyID::kAliasWebkitTransform:
case CSSPropertyID::kTransformStyle:
- case CSSPropertyID::kAliasWebkitTransformStyle:
case CSSPropertyID::kPerspective:
- case CSSPropertyID::kAliasWebkitPerspective:
case CSSPropertyID::kTranslate:
case CSSPropertyID::kRotate:
case CSSPropertyID::kScale:
@@ -1024,10 +1100,8 @@ static bool HasPropertyThatCreatesStackingContext(
case CSSPropertyID::kWebkitMask:
case CSSPropertyID::kWebkitMaskBoxImage:
case CSSPropertyID::kClipPath:
- case CSSPropertyID::kAliasWebkitClipPath:
case CSSPropertyID::kWebkitBoxReflect:
case CSSPropertyID::kFilter:
- case CSSPropertyID::kAliasWebkitFilter:
case CSSPropertyID::kBackdropFilter:
case CSSPropertyID::kZIndex:
case CSSPropertyID::kPosition:
@@ -1082,15 +1156,15 @@ void ComputedStyle::SetContent(ContentData* content_data) {
}
static bool IsWillChangeTransformHintProperty(CSSPropertyID property) {
- switch (property) {
+ switch (ResolveCSSPropertyID(property)) {
case CSSPropertyID::kTransform:
- case CSSPropertyID::kAliasWebkitTransform:
case CSSPropertyID::kPerspective:
case CSSPropertyID::kTranslate:
case CSSPropertyID::kScale:
case CSSPropertyID::kRotate:
case CSSPropertyID::kOffsetPath:
case CSSPropertyID::kOffsetPosition:
+ case CSSPropertyID::kTransformStyle:
return true;
default:
break;
@@ -1101,10 +1175,9 @@ static bool IsWillChangeTransformHintProperty(CSSPropertyID property) {
static bool IsWillChangeCompositingHintProperty(CSSPropertyID property) {
if (IsWillChangeTransformHintProperty(property))
return true;
- switch (property) {
+ switch (ResolveCSSPropertyID(property)) {
case CSSPropertyID::kOpacity:
case CSSPropertyID::kFilter:
- case CSSPropertyID::kAliasWebkitFilter:
case CSSPropertyID::kBackdropFilter:
case CSSPropertyID::kTop:
case CSSPropertyID::kLeft:
@@ -1342,7 +1415,7 @@ bool ComputedStyle::SetEffectiveZoom(float f) {
// real cost to our understanding of the zooms in use.
base::UmaHistogramSparse(
"Blink.EffectiveZoom",
- base::ClampToRange<float>(clamped_effective_zoom * 100, 0, 400));
+ base::clamp<float>(clamped_effective_zoom * 100, 0, 400));
return true;
}
@@ -1368,8 +1441,11 @@ CounterDirectiveMap& ComputedStyle::AccessCounterDirectives() {
const CounterDirectives ComputedStyle::GetCounterDirectives(
const AtomicString& identifier) const {
- if (const CounterDirectiveMap* directives = GetCounterDirectives())
- return directives->at(identifier);
+ if (GetCounterDirectives()) {
+ auto it = GetCounterDirectives()->find(identifier);
+ if (it != GetCounterDirectives()->end())
+ return it->value;
+ }
return CounterDirectives();
}
@@ -1665,13 +1741,41 @@ CSSTransitionData& ComputedStyle::AccessTransitions() {
}
FontBaseline ComputedStyle::GetFontBaseline() const {
- // TODO(kojii): Incorporate 'dominant-baseline' when we support it.
- // https://www.w3.org/TR/css-inline-3/#dominant-baseline-property
+ // CssDominantBaseline() always returns kAuto for non-SVG elements,
+ // and never returns kUseScript, kNoChange, and kResetSize.
+ // See StyleAdjuster::AdjustComputedStyle().
+ switch (CssDominantBaseline()) {
+ case EDominantBaseline::kAuto:
+ break;
+ case EDominantBaseline::kMiddle:
+ return kXMiddleBaseline;
+ case EDominantBaseline::kAlphabetic:
+ return kAlphabeticBaseline;
+ case EDominantBaseline::kHanging:
+ return kHangingBaseline;
+ case EDominantBaseline::kCentral:
+ return kCentralBaseline;
+ case EDominantBaseline::kTextBeforeEdge:
+ return kTextOverBaseline;
+ case EDominantBaseline::kTextAfterEdge:
+ return kTextUnderBaseline;
+ case EDominantBaseline::kIdeographic:
+ return kIdeographicUnderBaseline;
+ case EDominantBaseline::kMathematical:
+ return kMathBaseline;
+
+ case EDominantBaseline::kUseScript:
+ case EDominantBaseline::kNoChange:
+ case EDominantBaseline::kResetSize:
+ NOTREACHED();
+ break;
+ }
// Vertical flow (except 'text-orientation: sideways') uses ideographic
- // baseline. https://drafts.csswg.org/css-writing-modes-3/#intro-baselines
+ // central baseline.
+ // https://drafts.csswg.org/css-writing-modes-3/#text-baselines
return !GetFontDescription().IsVerticalAnyUpright() ? kAlphabeticBaseline
- : kIdeographicBaseline;
+ : kCentralBaseline;
}
FontHeight ComputedStyle::GetFontHeight(FontBaseline baseline) const {
@@ -1782,7 +1886,18 @@ bool ComputedStyle::HasVariables() const {
HasInitialVariables(InitialDataInternal().get());
}
-HashSet<AtomicString> ComputedStyle::GetVariableNames() const {
+wtf_size_t ComputedStyle::GetVariableNamesCount() const {
+ if (!HasVariables())
+ return 0;
+ return GetVariableNames().size();
+}
+
+const Vector<AtomicString>& ComputedStyle::GetVariableNames() const {
+ if (auto* cache = GetVariableNamesCache())
+ return *cache;
+
+ Vector<AtomicString>& cache = EnsureVariableNamesCache();
+
HashSet<AtomicString> names;
if (auto* initial_data = InitialDataInternal().get())
initial_data->CollectVariableNames(names);
@@ -1790,18 +1905,22 @@ HashSet<AtomicString> ComputedStyle::GetVariableNames() const {
inherited_variables->CollectNames(names);
if (auto* non_inherited_variables = NonInheritedVariables())
non_inherited_variables->CollectNames(names);
- return names;
+ CopyToVector(names, cache);
+
+ return cache;
}
-StyleInheritedVariables* ComputedStyle::InheritedVariables() const {
+const StyleInheritedVariables* ComputedStyle::InheritedVariables() const {
return InheritedVariablesInternal().get();
}
-StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const {
+const StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const {
return NonInheritedVariablesInternal().get();
}
StyleInheritedVariables& ComputedStyle::MutableInheritedVariables() {
+ ClearVariableNamesCache();
+
scoped_refptr<StyleInheritedVariables>& variables =
MutableInheritedVariablesInternal();
if (!variables)
@@ -1812,6 +1931,8 @@ StyleInheritedVariables& ComputedStyle::MutableInheritedVariables() {
}
StyleNonInheritedVariables& ComputedStyle::MutableNonInheritedVariables() {
+ ClearVariableNamesCache();
+
std::unique_ptr<StyleNonInheritedVariables>& variables =
MutableNonInheritedVariablesInternal();
if (!variables)
@@ -1820,6 +1941,8 @@ StyleNonInheritedVariables& ComputedStyle::MutableNonInheritedVariables() {
}
void ComputedStyle::SetInitialData(scoped_refptr<StyleInitialData> data) {
+ ClearVariableNamesCache();
+
MutableInitialDataInternal() = std::move(data);
}
@@ -1971,12 +2094,20 @@ LayoutUnit ComputedStyle::ComputedLineHeightAsFixed(const Font& font) const {
if (lh.IsNegative() && font.PrimaryFont())
return font.PrimaryFont()->GetFontMetrics().FixedLineSpacing();
- if (lh.IsPercentOrCalc()) {
- return LayoutUnit(
- MinimumValueForLength(lh, ComputedFontSizeAsFixed(font)).ToInt());
- }
+ if (RuntimeEnabledFeatures::FractionalLineHeightEnabled()) {
+ if (lh.IsPercentOrCalc()) {
+ return MinimumValueForLength(lh, ComputedFontSizeAsFixed(font));
+ }
- return LayoutUnit(floorf(lh.Value()));
+ return LayoutUnit::FromFloatFloor(lh.Value());
+ } else {
+ if (lh.IsPercentOrCalc()) {
+ return LayoutUnit(
+ MinimumValueForLength(lh, ComputedFontSizeAsFixed(font)).ToInt());
+ }
+
+ return LayoutUnit(floorf(lh.Value()));
+ }
}
LayoutUnit ComputedStyle::ComputedLineHeightAsFixed() const {
@@ -1996,6 +2127,9 @@ void ComputedStyle::SetLetterSpacing(float letter_spacing) {
}
void ComputedStyle::SetTextAutosizingMultiplier(float multiplier) {
+ if (TextAutosizingMultiplier() == multiplier)
+ return;
+
SetTextAutosizingMultiplierInternal(multiplier);
float size = SpecifiedFontSize();
@@ -2215,24 +2349,41 @@ int ComputedStyle::OutlineOutsetExtent() const {
if (!HasOutline())
return 0;
if (OutlineStyleIsAuto()) {
- return GraphicsContext::FocusRingOutsetExtent(
- OutlineOffsetInt(), std::ceil(GetOutlineStrokeWidthForFocusRing()));
+ // Unlike normal outlines (whole width is outside of the offset), focus
+ // rings are drawn with only part of it outside of the offset.
+ return FocusRingOffset() + std::ceil(FocusRingStrokeWidth() / 3.f) * 2;
}
return base::ClampAdd(OutlineWidthInt(), OutlineOffsetInt()).Max(0);
}
-float ComputedStyle::GetOutlineStrokeWidthForFocusRing() const {
- if (::features::IsFormControlsRefreshEnabled() && OutlineStyleIsAuto()) {
- return std::max(EffectiveZoom(), 3.f);
- }
+float ComputedStyle::FocusRingOuterStrokeWidth() const {
+ // The focus ring is made of two rings which have a 2:1 ratio.
+ return FocusRingStrokeWidth() / 3.f * 2;
+}
+
+float ComputedStyle::FocusRingInnerStrokeWidth() const {
+ return FocusRingStrokeWidth() / 3.f;
+}
-#if defined(OS_MAC)
- return OutlineWidthInt();
-#else
- // Draw an outline with thickness in proportion to the zoom level, but never
+float ComputedStyle::FocusRingStrokeWidth() const {
+ DCHECK(OutlineStyleIsAuto());
+ // Draw focus ring with thickness in proportion to the zoom level, but never
// so narrow that it becomes invisible.
- return std::max(EffectiveZoom(), 1.f);
-#endif
+ return std::max(EffectiveZoom(), 3.f);
+}
+
+int ComputedStyle::FocusRingOffset() const {
+ DCHECK(OutlineStyleIsAuto());
+ // How much space the focus ring would like to take from the actual border.
+ constexpr float kMaxInsideBorderWidth = 1;
+ int offset = OutlineOffsetInt();
+ // Focus ring is dependent on whether the border is large enough to have an
+ // inset outline. Use the smallest border edge for that test.
+ float min_border_width = std::min({BorderTopWidth(), BorderBottomWidth(),
+ BorderLeftWidth(), BorderRightWidth()});
+ if (min_border_width >= kMaxInsideBorderWidth)
+ offset -= kMaxInsideBorderWidth;
+ return offset;
}
bool ComputedStyle::StrokeDashArrayDataEquivalent(
@@ -2411,27 +2562,15 @@ void ComputedStyle::ClearBackgroundImage() {
curr_child->ClearImage();
}
-ListStyleTypeData* ComputedStyle::GetListStyleType() const {
- return ListStyleTypeInternal();
-}
-
-EListStyleType ComputedStyle::ListStyleType() const {
- if (!GetListStyleType())
- return EListStyleType::kNone;
- if (GetListStyleType()->IsString())
- return EListStyleType::kString;
- return GetListStyleType()->ToDeprecatedListStyleTypeEnum();
-}
-
const AtomicString& ComputedStyle::ListStyleStringValue() const {
- if (!GetListStyleType() || !GetListStyleType()->IsString())
+ if (!ListStyleType() || !ListStyleType()->IsString())
return g_null_atom;
- return GetListStyleType()->GetStringValue();
+ return ListStyleType()->GetStringValue();
}
absl::optional<Color> ComputedStyle::AccentColorResolved() const {
const StyleAutoColor& auto_color = AccentColor();
- if (auto_color.IsAutoColor() || ShouldForceColor(auto_color))
+ if (auto_color.IsAutoColor())
return absl::nullopt;
return auto_color.Resolve(GetCurrentColor(), UsedColorScheme());
}
@@ -2475,6 +2614,27 @@ EPaintOrderType ComputedStyle::PaintOrderType(unsigned index) const {
return static_cast<EPaintOrderType>(pt);
}
+bool ComputedStyle::ShouldApplyAnyContainment(const Element& element) const {
+ DCHECK(IsA<HTMLBodyElement>(element) || IsA<HTMLHtmlElement>(element))
+ << "Since elements can override the computed display for which box type "
+ "to create, this method is not generally correct. Use "
+ "LayoutObject::ShouldApplyAnyContainment if possible.";
+ if (ContainsStyle())
+ return true;
+ if (!element.LayoutObjectIsNeeded(*this))
+ return false;
+ if (Display() == EDisplay::kInline)
+ return false;
+ if ((ContainsInlineSize() || ContainsBlockSize()) &&
+ (!IsDisplayTableType() || Display() == EDisplay::kTableCaption)) {
+ return true;
+ }
+ return (ContainsLayout() || ContainsPaint()) &&
+ (!IsDisplayTableType() || IsDisplayTableBox() ||
+ Display() == EDisplay::kTableCell ||
+ Display() == EDisplay::kTableCaption);
+}
+
STATIC_ASSERT_ENUM(cc::OverscrollBehavior::Type::kAuto,
EOverscrollBehavior::kAuto);
STATIC_ASSERT_ENUM(cc::OverscrollBehavior::Type::kContain,
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 d868f42a7a2..9dc5a3aef30 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.h
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.h
@@ -26,10 +26,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_COMPUTED_STYLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_COMPUTED_STYLE_H_
+#include <algorithm>
#include <memory>
#include "base/types/pass_key.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/style_auto_color.h"
#include "third_party/blink/renderer/core/css/style_color.h"
@@ -282,6 +284,10 @@ class ComputedStyle : public ComputedStyleBase,
PseudoElementStyleCache* GetPseudoElementStyleCache() const;
PseudoElementStyleCache& EnsurePseudoElementStyleCache() const;
+ Vector<AtomicString>* GetVariableNamesCache() const;
+ Vector<AtomicString>& EnsureVariableNamesCache() const;
+ void ClearVariableNamesCache() const;
+
private:
// TODO(sashab): Move these private members to the bottom of ComputedStyle.
ALWAYS_INLINE ComputedStyle();
@@ -323,11 +329,17 @@ class ComputedStyle : public ComputedStyleBase,
// Inherited properties are different which means we need to recalc style
// for children.
kInherited,
+ // Properties which can affect descendants changed. This can happen the
+ // following ways:
+ //
// Display type changes for flex/grid/custom layout affects computed style
// adjustments for descendants. For instance flex/grid items are blockified
// at computed style time and such items can be arbitrarily deep down the
// flat tree in the presence of display:contents.
- kDisplayAffectingDescendantStyles,
+ //
+ // The container-name property affects which container is queried by
+ // rules matching descedant elements.
+ kDescendantAffecting,
};
CORE_EXPORT static Difference ComputeDifference(
const ComputedStyle* old_style,
@@ -385,6 +397,22 @@ class ComputedStyle : public ComputedStyleBase,
scoped_refptr<const ComputedStyle>) const;
void ClearCachedPseudoElementStyles() const;
+ // If this ComputedStyle is affected by animation/transitions, then the
+ // unanimated "base" style can be retrieved with this function.
+ //
+ // If this function returns nullptr, then this ComputedStyle is not
+ // affected by animations, and *is* the base style.
+ CORE_EXPORT const ComputedStyle* GetBaseComputedStyle() const;
+
+ // Indicates which properties are !important in the base style.
+ CORE_EXPORT const CSSBitset* GetBaseImportantSet() const;
+
+ CORE_EXPORT const ComputedStyle* GetBaseComputedStyleOrThis() const {
+ if (auto* base = GetBaseComputedStyle())
+ return base;
+ return this;
+ }
+
/**
* ComputedStyle properties
*
@@ -838,14 +866,8 @@ class ComputedStyle : public ComputedStyleBase,
inline bool IsScrollbarGutterStable() const {
return ScrollbarGutter() & kScrollbarGutterStable;
}
- inline bool IsScrollbarGutterAlways() const {
- return ScrollbarGutter() & kScrollbarGutterAlways;
- }
- inline bool IsScrollbarGutterBoth() const {
- return ScrollbarGutter() & kScrollbarGutterBoth;
- }
- inline bool IsScrollbarGutterForce() const {
- return ScrollbarGutter() & kScrollbarGutterForce;
+ inline bool IsScrollbarGutterBothEdges() const {
+ return ScrollbarGutter() & kScrollbarGutterBothEdges;
}
// ignore non-standard ::-webkit-scrollbar when standard properties are in use
@@ -957,16 +979,9 @@ class ComputedStyle : public ComputedStyleBase,
void SetListStyleImage(StyleImage*);
// list-style-type
- // TODO(crbug.com/687225): These functions are deprecated. Callers should be
- // migrated to GetListStyleType().
- CORE_EXPORT EListStyleType ListStyleType() const;
const AtomicString& ListStyleStringValue() const;
- // TODO(crbug.com/687225): Get rid of the deprecated functions above so that
- // the getter can also be auto-generated.
- CORE_EXPORT ListStyleTypeData* GetListStyleType() const;
bool ListStyleTypeDataEquivalent(const ComputedStyle& other) const {
- return DataEquivalent(ListStyleTypeInternal(),
- other.ListStyleTypeInternal());
+ return DataEquivalent(ListStyleType(), other.ListStyleType());
}
// quotes
@@ -1162,9 +1177,10 @@ class ComputedStyle : public ComputedStyleBase,
// Variables.
bool HasVariables() const;
- CORE_EXPORT HashSet<AtomicString> GetVariableNames() const;
- CORE_EXPORT StyleInheritedVariables* InheritedVariables() const;
- CORE_EXPORT StyleNonInheritedVariables* NonInheritedVariables() const;
+ CORE_EXPORT wtf_size_t GetVariableNamesCount() const;
+ CORE_EXPORT const Vector<AtomicString>& GetVariableNames() const;
+ CORE_EXPORT const StyleInheritedVariables* InheritedVariables() const;
+ CORE_EXPORT const StyleNonInheritedVariables* NonInheritedVariables() const;
CORE_EXPORT void SetVariableData(const AtomicString&,
scoped_refptr<CSSVariableData>,
@@ -1416,7 +1432,8 @@ class ComputedStyle : public ComputedStyleBase,
// Will-change utility functions.
bool HasWillChangeCompositingHint() const;
bool HasWillChangeOpacityHint() const {
- return WillChangeProperties().Contains(CSSPropertyID::kOpacity);
+ return WillChangeProperties().Contains(CSSPropertyID::kOpacity) ||
+ WillChangeProperties().Contains(CSSPropertyID::kAliasWebkitOpacity);
}
bool HasWillChangeTransformHint() const;
bool HasWillChangeFilterHint() const {
@@ -1919,7 +1936,12 @@ class ComputedStyle : public ComputedStyleBase,
}
// Perspective utility functions.
- bool HasPerspective() const { return Perspective() > 0; }
+ bool HasPerspective() const { return Perspective() >= 0; }
+
+ float UsedPerspective() const {
+ DCHECK(HasPerspective());
+ return std::max(1.0f, Perspective());
+ }
// Outline utility functions.
// HasOutline is insufficient to determine whether Node has an outline.
@@ -1928,7 +1950,10 @@ class ComputedStyle : public ComputedStyleBase,
return OutlineWidth() > 0 && OutlineStyle() > EBorderStyle::kHidden;
}
CORE_EXPORT int OutlineOutsetExtent() const;
- CORE_EXPORT float GetOutlineStrokeWidthForFocusRing() const;
+ CORE_EXPORT float FocusRingOuterStrokeWidth() const;
+ CORE_EXPORT float FocusRingInnerStrokeWidth() const;
+ CORE_EXPORT float FocusRingStrokeWidth() const;
+ CORE_EXPORT int FocusRingOffset() const;
bool HasOutlineWithCurrentColor() const {
return HasOutline() && OutlineColor().IsCurrentColor();
}
@@ -2034,14 +2059,47 @@ class ComputedStyle : public ComputedStyleBase,
}
// Contain utility functions.
- bool ContainsPaint() const { return Contain() & kContainsPaint; }
- bool ContainsStyle() const { return Contain() & kContainsStyle; }
- bool ContainsLayout() const { return Contain() & kContainsLayout; }
+ //
+ // Containment can be enabled from a variety of sources, not just the
+ // 'contain' property itself. The return values represent whether or not
+ // we should enable containment of a given type, taking those different
+ // sources into account.
+ //
+ // Note that even with a return value of |true|, containment may still not
+ // be applied if the layout object is ineligible for the given containment
+ // type. See |LayoutObject::IsEligibleForSizeContainment| and similar
+ // functions.
+
+ bool ContainsPaint() const {
+ return (Contain() & kContainsPaint) || !IsContentVisibilityVisible();
+ }
+ bool ContainsStyle() const {
+ return (Contain() & kContainsStyle) || IsInlineOrBlockSizeContainer() ||
+ !IsContentVisibilityVisible();
+ }
+ bool ContainsLayout() const {
+ return (Contain() & kContainsLayout) || IsInlineOrBlockSizeContainer() ||
+ !IsContentVisibilityVisible();
+ }
bool ContainsSize() const {
- return (Contain() & kContainsSize) == kContainsSize;
+ return ((Contain() & kContainsSize) == kContainsSize) ||
+ IsInlineAndBlockSizeContainer() || SkipsContents();
+ }
+ bool ContainsInlineSize() const {
+ return (Contain() & kContainsInlineSize) || IsInlineSizeContainer() ||
+ SkipsContents();
+ }
+ bool ContainsBlockSize() const {
+ return (Contain() & kContainsBlockSize) || IsBlockSizeContainer() ||
+ SkipsContents();
+ }
+ CORE_EXPORT bool ShouldApplyAnyContainment(const Element& element) const;
+
+ bool IsContainerForContainerQueries() const {
+ return (StyleType() == kPseudoIdNone) &&
+ (ContainsStyle() && ContainsLayout() &&
+ (ContainsInlineSize() || ContainsBlockSize()));
}
- bool ContainsInlineSize() const { return Contain() & kContainsInlineSize; }
- bool ContainsBlockSize() const { return Contain() & kContainsBlockSize; }
// Display utility functions.
bool IsDisplayReplacedType() const {
@@ -2602,9 +2660,7 @@ class ComputedStyle : public ComputedStyleBase,
}
mojom::blink::ColorScheme UsedColorScheme() const {
- return RuntimeEnabledFeatures::CSSColorSchemeUARenderingEnabled()
- ? ComputedColorScheme()
- : mojom::blink::ColorScheme::kLight;
+ return ComputedColorScheme();
}
mojom::blink::ColorScheme UsedColorSchemeForInitialColors() const {
@@ -2638,11 +2694,33 @@ class ComputedStyle : public ComputedStyleBase,
return EBoxSizing::kContentBox;
}
+ bool DisableForceDark() const {
+ return ColorSchemeOnly() || HasFilterInducingProperty();
+ }
+
private:
EClear Clear() const { return ClearInternal(); }
EFloat Floating() const { return FloatingInternal(); }
EResize Resize() const { return ResizeInternal(); }
+ bool IsInlineSizeContainer() const {
+ return ContainerType() & kContainerTypeInlineSize;
+ }
+ bool IsBlockSizeContainer() const {
+ return ContainerType() & kContainerTypeBlockSize;
+ }
+ bool IsInlineOrBlockSizeContainer() const {
+ return ContainerType() &
+ (kContainerTypeInlineSize | kContainerTypeBlockSize);
+ }
+ bool IsInlineAndBlockSizeContainer() const {
+ const unsigned both = (kContainerTypeInlineSize | kContainerTypeBlockSize);
+ return (ContainerType() & both) == both;
+ }
+ bool IsContentVisibilityVisible() const {
+ return ContentVisibility() == EContentVisibility::kVisible;
+ }
+
void SetInternalVisitedColor(const StyleColor& v) {
SetInternalVisitedColorInternal(v);
}
@@ -3001,6 +3079,8 @@ class ComputedStyle : public ComputedStyleBase,
FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, InitialVariableNames);
FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest,
InitialAndInheritedAndNonInheritedVariableNames);
+ FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest,
+ GetVariableNamesWithInitialData_Invalidation);
FRIEND_TEST_ALL_PREFIXES(StyleCascadeTest, ForcedVisitedBackgroundColor);
FRIEND_TEST_ALL_PREFIXES(
ComputedStyleTest,
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 02ca08c83b3..a4bcb72707d 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
@@ -194,8 +194,9 @@ enum Containment {
kContainsBlockSize = 0x8,
kContainsInlineSize = 0x10,
kContainsSize = kContainsBlockSize | kContainsInlineSize,
- kContainsStrict = kContainsLayout | kContainsPaint | kContainsSize,
- kContainsContent = kContainsLayout | kContainsPaint,
+ kContainsStrict =
+ kContainsStyle | kContainsLayout | kContainsPaint | kContainsSize,
+ kContainsContent = kContainsStyle | kContainsLayout | kContainsPaint,
};
inline Containment operator|(Containment a, Containment b) {
return Containment(int(a) | int(b));
@@ -204,6 +205,19 @@ inline Containment& operator|=(Containment& a, Containment b) {
return a = a | b;
}
+static const size_t kContainerTypeBits = 2;
+enum EContainerType {
+ kContainerTypeNone = 0x0,
+ kContainerTypeInlineSize = 0x1,
+ kContainerTypeBlockSize = 0x2,
+};
+inline EContainerType operator|(EContainerType a, EContainerType b) {
+ return EContainerType(int(a) | int(b));
+}
+inline EContainerType& operator|=(EContainerType& a, EContainerType b) {
+ return a = a | b;
+}
+
static const size_t kTextUnderlinePositionBits = 4;
enum TextUnderlinePosition {
kTextUnderlinePositionAuto = 0x0,
@@ -288,13 +302,11 @@ enum class LineLogicalSide {
kUnder,
};
-constexpr size_t kScrollbarGutterBits = 4;
+constexpr size_t kScrollbarGutterBits = 2;
enum ScrollbarGutter {
kScrollbarGutterAuto = 0x0,
kScrollbarGutterStable = 0x1,
- kScrollbarGutterAlways = 0x2,
- kScrollbarGutterBoth = 0x4,
- kScrollbarGutterForce = 0x8
+ kScrollbarGutterBothEdges = 0x2,
};
inline ScrollbarGutter operator|(ScrollbarGutter a, ScrollbarGutter b) {
return ScrollbarGutter(int(a) | int(b));
@@ -303,77 +315,6 @@ inline ScrollbarGutter& operator|=(ScrollbarGutter& a, ScrollbarGutter b) {
return a = a | b;
}
-// https://drafts.csswg.org/css-counter-styles-3/#predefined-counters
-enum class EListStyleType : unsigned {
- // https://drafts.csswg.org/css-counter-styles-3/#simple-symbolic
- kDisc,
- kCircle,
- kSquare,
- kDisclosureOpen,
- kDisclosureClosed,
-
- // https://drafts.csswg.org/css-counter-styles-3/#simple-numeric
- kDecimal,
- kDecimalLeadingZero,
- kArabicIndic,
- kBengali,
- kCambodian,
- kKhmer,
- kDevanagari,
- kGujarati,
- kGurmukhi,
- kKannada,
- kLao,
- kMalayalam,
- kMongolian,
- kMyanmar,
- kOriya,
- kPersian,
- kUrdu,
- kTelugu,
- kTibetan,
- kThai,
- kLowerRoman,
- kUpperRoman,
-
- // https://drafts.csswg.org/css-counter-styles-3/#simple-alphabetic
- kLowerGreek,
- kLowerAlpha,
- kLowerLatin,
- kUpperAlpha,
- kUpperLatin,
-
- // https://drafts.csswg.org/css-counter-styles-3/#simple-fixed
- kCjkEarthlyBranch,
- kCjkHeavenlyStem,
-
- kEthiopicHalehame,
- kEthiopicHalehameAm,
- kEthiopicHalehameTiEr,
- kEthiopicHalehameTiEt,
- kHangul,
- kHangulConsonant,
- kKoreanHangulFormal,
- kKoreanHanjaFormal,
- kKoreanHanjaInformal,
- kHebrew,
- kArmenian,
- kLowerArmenian,
- kUpperArmenian,
- kGeorgian,
- kCjkIdeographic,
- kSimpChineseFormal,
- kSimpChineseInformal,
- kTradChineseFormal,
- kTradChineseInformal,
- kHiragana,
- kKatakana,
- kHiraganaIroha,
- kKatakanaIroha,
- kNone,
- kString,
-};
-
enum class EBaselineShiftType : unsigned { kLength, kSub, kSuper };
enum EPaintOrderType {
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index 9bee04427d9..04526c193d3 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -104,7 +104,8 @@
"column-rule-width", "column-rule-color", "-internal-visited-column-rule-color",
"column-count", "HasAutoColumnCount", "HasAutoColumnWidth", "column-fill", "column-span",
"cx", "cy", "d", "rx", "ry", "x", "y", "r", "alignment-baseline", "vector-effect",
- "BaselineShiftType", "baseline-shift", "dominant-baseline", "text-anchor",
+ "BaselineShiftType", "baseline-shift", "dominant-baseline",
+ "CssDominantBaseline", "text-anchor",
"stroke-width", "stroke-miterlimit", "stroke-linecap", "stroke-linejoin",
"marker-end", "marker-mid", "marker-start", "scrollbar-width"],
methods_to_diff: [
@@ -230,9 +231,9 @@
fields_to_diff: ["width", "min-width", "max-width", "height", "min-height",
"max-height", "VerticalAlignLength", "box-sizing", "align-content",
"align-items", "align-self", "justify-content", "justify-items",
- "justify-self", "contain", "contain-intrinsic-size", "aspect-ratio",
- "overflow-clip-margin", "-internal-align-self-block", "orphans",
- "widows"],
+ "justify-self", "contain", "contain-intrinsic-size", "container-type",
+ "content-visibility", "aspect-ratio", "overflow-clip-margin",
+ "-internal-align-self-block", "orphans", "widows"],
methods_to_diff: [
{
method: "VerticalAlign()",
@@ -242,6 +243,10 @@
method: "GetPosition()",
field_dependencies: ["position"]
},
+ {
+ method: "SkipsContents()",
+ field_dependencies: ["content-visibility"]
+ },
]
},
{
@@ -280,8 +285,8 @@
field_dependencies: ["color-scheme"]
},
{
- method: "AccentColor()",
- field_dependencies: ["accent-color"]
+ method: "AccentColorResolved()",
+ field_dependencies: ["accent-color", "color"]
}
],
predicates_to_test: [
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
index f87b481e4ed..7cb6d890c1f 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
+++ b/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -88,6 +88,7 @@
{
name: "InForcedColorsMode",
field_template: "primitive",
+ field_group: "inherited",
default_value: "false",
type_name: "bool",
inherited: true,
@@ -214,6 +215,12 @@
default_value: "false",
custom_compare: true,
},
+ {
+ name: "HasContainerRelativeUnits",
+ field_template: "monotonic_flag",
+ default_value: "false",
+ custom_compare: true,
+ },
// True if this ComputedStyle is the result of CustomStyleForLayoutObject()
// that uses font metrics in its calculation.
{
@@ -493,7 +500,7 @@
include_paths: ["third_party/blink/renderer/core/style/style_inherited_variables.h"],
default_value: "nullptr",
wrapper_pointer_name: "scoped_refptr",
- field_group: "InheritedVariables",
+ field_group: "inherited",
computed_style_custom_functions: ["getter", "setter"],
},
{
@@ -645,6 +652,13 @@
default_value: "false",
},
{
+ name: "HasCurrentClipPathAnimation",
+ field_template: "primitive",
+ type_name: "bool",
+ field_group: "*",
+ default_value: "false",
+ },
+ {
name: "CompositablePaintAnimationChanged",
field_template: "primitive",
type_name: "bool",
@@ -727,6 +741,11 @@
default_value: "false",
},
{
+ name: "HasAuthorBorderRadius",
+ field_template: "monotonic_flag",
+ default_value: "false",
+ },
+ {
name: "WillChangeProperties",
field_template: "external",
type_name: "Vector<CSSPropertyID>",
@@ -753,7 +772,7 @@
name: "HasAutoColumnWidth",
field_template: "primitive",
type_name: "bool",
- field_group: "*->multi-col",
+ field_group: "*",
default_value: "true",
computed_style_custom_functions: ["setter"],
},
@@ -761,7 +780,7 @@
name: "HasAutoColumnCount",
field_template: "primitive",
type_name: "bool",
- field_group: "*->multi-col",
+ field_group: "*",
default_value: "true",
computed_style_custom_functions: ["setter"],
},
@@ -856,46 +875,46 @@
{
name: "NamedGridAreaRowCount",
field_template: "primitive",
- type_name: "size_t",
+ type_name: "wtf_size_t",
field_group: "*->grid",
default_value: "0",
},
{
name: "NamedGridAreaColumnCount",
field_template: "primitive",
- type_name: "size_t",
+ type_name: "wtf_size_t",
field_group: "*->grid",
default_value: "0",
},
{
name: "GridAutoRepeatColumns",
field_template: "external",
- type_name: "Vector<GridTrackSize>",
+ type_name: "Vector<GridTrackSize, 1>",
field_group: "*->grid",
- default_value: "Vector<GridTrackSize>()",
+ default_value: "Vector<GridTrackSize, 1>()",
include_paths: ["third_party/blink/renderer/platform/wtf/vector.h",
"third_party/blink/renderer/core/style/grid_track_size.h"],
},
{
name: "GridAutoRepeatRows",
field_template: "external",
- type_name: "Vector<GridTrackSize>",
+ type_name: "Vector<GridTrackSize, 1>",
field_group: "*->grid",
- default_value: "Vector<GridTrackSize>()",
+ default_value: "Vector<GridTrackSize, 1>()",
include_paths: ["third_party/blink/renderer/platform/wtf/vector.h",
"third_party/blink/renderer/core/style/grid_track_size.h"],
},
{
name: "GridAutoRepeatColumnsInsertionPoint",
field_template: "primitive",
- type_name: "size_t",
+ type_name: "wtf_size_t",
field_group: "*->grid",
default_value: "0",
},
{
name: "GridAutoRepeatRowsInsertionPoint",
field_template: "primitive",
- type_name: "size_t",
+ type_name: "wtf_size_t",
field_group: "*->grid",
default_value: "0",
},
@@ -927,12 +946,14 @@
{
name: "MayHaveMargin",
field_template: "monotonic_flag",
+ field_group: "surround",
default_value: "false",
custom_compare: true,
},
{
name: "MayHavePadding",
field_template: "monotonic_flag",
+ field_group: "surround",
default_value: "false",
custom_compare: true,
},
@@ -945,6 +966,14 @@
inherited: true,
},
{
+ name: "ColorSchemeOnly",
+ field_template: "primitive",
+ type_name: "bool",
+ default_value: "false",
+ custom_compare: true,
+ inherited: true,
+ },
+ {
name: "IsInBlockifyingDisplay",
field_template: "monotonic_flag",
default_value: "false",
@@ -993,7 +1022,7 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathBaseline",
},
{
@@ -1002,7 +1031,7 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathFractionBarThickness",
},
{
@@ -1011,7 +1040,7 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathLSpace",
},
{
@@ -1020,7 +1049,7 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathRSpace",
},
{
@@ -1029,7 +1058,7 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathPaddedVOffset",
},
{
@@ -1038,17 +1067,16 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathPaddedDepth",
},
-
{
name: "MathMinSize",
field_template: "external",
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathMinSize",
},
{
@@ -1057,7 +1085,7 @@
default_value: "Length()",
include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
type_name: "Length",
- field_group: "*",
+ field_group: "*->math",
getter: "GetMathMaxSize",
},
{
@@ -1077,11 +1105,42 @@
default_value: "EBaselineShiftType::kLength",
},
{
+ // Represents 'dominant-baseline' defined in the css-inline specification,
+ // not in SVG 1.1 specification.
+ // This doesn't have 'use-script', 'no-change', and 'reset-size'.
+ // For now ComputedStyle for non-SVG elemnts always have the initial value
+ // in order to disable the feature.
+ name: "CssDominantBaseline",
+ field_group: "svg",
+ field_template: "primitive",
+ field_size: 4,
+ type_name: "EDominantBaseline",
+ default_value: "EDominantBaseline::kAuto",
+ inherited: true,
+ },
+ {
name: "DependsOnContainerQueries",
field_template: "primitive",
type_name: "bool",
field_group: "*",
default_value: "false",
},
+ {
+ name: "BaseData",
+ inherited: false,
+ field_template: "external",
+ type_name: "StyleBaseData",
+ include_paths: ["third_party/blink/renderer/core/style/style_base_data.h"],
+ default_value: "nullptr",
+ wrapper_pointer_name: "scoped_refptr",
+ custom_compare: true,
+ custom_copy: true,
+ },
+ {
+ // https://drafts.csswg.org/css-contain-2/#skips-its-contents
+ name: "SkipsContents",
+ field_template: "monotonic_flag",
+ default_value: "false",
+ },
],
}
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 fb60bb01ab3..03ebee2c352 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
@@ -22,7 +22,10 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/html/html_body_element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.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"
@@ -91,30 +94,13 @@ TEST_F(ComputedStyleTest, ClipPathEqual) {
TEST_F(ComputedStyleTest, FocusRingWidth) {
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
- if (::features::IsFormControlsRefreshEnabled()) {
- style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
- EXPECT_EQ(3, style->GetOutlineStrokeWidthForFocusRing());
- style->SetEffectiveZoom(3.5);
- style->SetOutlineWidth(4);
- EXPECT_EQ(3.5, style->GetOutlineStrokeWidthForFocusRing());
- } else {
- style->SetEffectiveZoom(3.5);
- style->SetOutlineStyle(EBorderStyle::kSolid);
-#if defined(OS_MAC)
- EXPECT_EQ(3, style->GetOutlineStrokeWidthForFocusRing());
-#else
- style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
- static uint16_t outline_width = 4;
- style->SetOutlineWidth(outline_width);
-
- double expected_width = 3.5;
- EXPECT_EQ(expected_width, style->GetOutlineStrokeWidthForFocusRing());
-
- expected_width = 1.0;
- style->SetEffectiveZoom(0.5);
- EXPECT_EQ(expected_width, style->GetOutlineStrokeWidthForFocusRing());
-#endif
- }
+ style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
+ EXPECT_EQ(3, style->FocusRingStrokeWidth());
+ EXPECT_EQ(2, style->FocusRingOuterStrokeWidth());
+ EXPECT_EQ(1, style->FocusRingInnerStrokeWidth());
+ style->SetEffectiveZoom(3.5);
+ style->SetOutlineWidth(4);
+ EXPECT_EQ(3.5, style->FocusRingStrokeWidth());
}
TEST_F(ComputedStyleTest, FocusRingOutset) {
@@ -122,15 +108,7 @@ TEST_F(ComputedStyleTest, FocusRingOutset) {
style->SetOutlineStyle(EBorderStyle::kSolid);
style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
style->SetEffectiveZoom(4.75);
- if (::features::IsFormControlsRefreshEnabled()) {
- EXPECT_EQ(4, style->OutlineOutsetExtent());
- } else {
-#if defined(OS_MAC)
- EXPECT_EQ(4, style->OutlineOutsetExtent());
-#else
- EXPECT_EQ(3, style->OutlineOutsetExtent());
-#endif
- }
+ EXPECT_EQ(4, style->OutlineOutsetExtent());
}
TEST_F(ComputedStyleTest, SVGStackingContext) {
@@ -679,8 +657,6 @@ TEST_F(ComputedStyleTest, CustomPropertiesInheritance_StyleRecalc) {
}
TEST_F(ComputedStyleTest, ApplyColorSchemeLightOnDark) {
- ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
-
std::unique_ptr<DummyPageHolder> dummy_page_holder =
std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
Document& document = dummy_page_holder->GetDocument();
@@ -691,7 +667,7 @@ TEST_F(ComputedStyleTest, ApplyColorSchemeLightOnDark) {
color_scheme_helper.SetPreferredColorScheme(
mojom::blink::PreferredColorScheme::kDark);
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
state.SetStyle(style);
@@ -714,8 +690,6 @@ TEST_F(ComputedStyleTest, ApplyColorSchemeLightOnDark) {
TEST_F(ComputedStyleTest, ApplyInternalLightDarkColor) {
using css_test_helpers::ParseDeclarationBlock;
- ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
-
std::unique_ptr<DummyPageHolder> dummy_page_holder =
std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
Document& document = dummy_page_holder->GetDocument();
@@ -726,7 +700,7 @@ TEST_F(ComputedStyleTest, ApplyInternalLightDarkColor) {
color_scheme_helper.SetPreferredColorScheme(
mojom::blink::PreferredColorScheme::kDark);
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
state.SetStyle(style);
@@ -758,8 +732,6 @@ TEST_F(ComputedStyleTest, ApplyInternalLightDarkColor) {
TEST_F(ComputedStyleTest, ApplyInternalLightDarkBackgroundImage) {
using css_test_helpers::ParseDeclarationBlock;
- ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
-
std::unique_ptr<DummyPageHolder> dummy_page_holder =
std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
Document& document = dummy_page_holder->GetDocument();
@@ -770,7 +742,7 @@ TEST_F(ComputedStyleTest, ApplyInternalLightDarkBackgroundImage) {
color_scheme_helper.SetPreferredColorScheme(
mojom::blink::PreferredColorScheme::kDark);
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
state.SetStyle(style);
@@ -809,7 +781,7 @@ TEST_F(ComputedStyleTest, StrokeWidthZoomAndCalc) {
document.GetStyleResolver().InitialStyleForElement();
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
style->SetEffectiveZoom(1.5);
@@ -924,6 +896,67 @@ TEST_F(ComputedStyleTest, InitialAndInheritedAndNonInheritedVariableNames) {
EXPECT_TRUE(style->GetVariableNames().Contains("--e"));
}
+TEST_F(ComputedStyleTest, GetVariableNamesCount_Invalidation) {
+ scoped_refptr<ComputedStyle> style = CreateComputedStyle();
+
+ EXPECT_EQ(style->GetVariableNamesCount(), 0u);
+
+ auto data = css_test_helpers::CreateVariableData("foo");
+ style->SetVariableData("--x", data, false);
+ EXPECT_EQ(style->GetVariableNamesCount(), 1u);
+
+ style->SetVariableData("--y", data, false);
+ EXPECT_EQ(style->GetVariableNamesCount(), 2u);
+
+ style->SetVariableData("--z", data, true);
+ EXPECT_EQ(style->GetVariableNamesCount(), 3u);
+}
+
+TEST_F(ComputedStyleTest, GetVariableNames_Invalidation) {
+ scoped_refptr<ComputedStyle> style = CreateComputedStyle();
+
+ auto data = css_test_helpers::CreateVariableData("foo");
+ style->SetVariableData("--x", data, false);
+ EXPECT_EQ(style->GetVariableNames().size(), 1u);
+ EXPECT_TRUE(style->GetVariableNames().Contains("--x"));
+
+ style->SetVariableData("--y", data, false);
+ EXPECT_EQ(style->GetVariableNames().size(), 2u);
+ EXPECT_TRUE(style->GetVariableNames().Contains("--x"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--y"));
+
+ style->SetVariableData("--z", data, true);
+ EXPECT_EQ(style->GetVariableNames().size(), 3u);
+ EXPECT_TRUE(style->GetVariableNames().Contains("--x"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--y"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--z"));
+}
+
+TEST_F(ComputedStyleTest, GetVariableNamesWithInitialData_Invalidation) {
+ using css_test_helpers::CreateLengthRegistration;
+
+ scoped_refptr<ComputedStyle> style = CreateComputedStyle();
+
+ {
+ PropertyRegistry* registry = MakeGarbageCollected<PropertyRegistry>();
+ registry->RegisterProperty("--x", *CreateLengthRegistration("--x", 1));
+ style->SetInitialData(StyleInitialData::Create(*registry));
+ }
+ EXPECT_EQ(style->GetVariableNames().size(), 1u);
+ EXPECT_TRUE(style->GetVariableNames().Contains("--x"));
+
+ // Not set StyleInitialData to something else.
+ {
+ PropertyRegistry* registry = MakeGarbageCollected<PropertyRegistry>();
+ registry->RegisterProperty("--y", *CreateLengthRegistration("--y", 2));
+ registry->RegisterProperty("--z", *CreateLengthRegistration("--z", 3));
+ style->SetInitialData(StyleInitialData::Create(*registry));
+ }
+ EXPECT_EQ(style->GetVariableNames().size(), 2u);
+ EXPECT_TRUE(style->GetVariableNames().Contains("--y"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--z"));
+}
+
TEST_F(ComputedStyleTest, BorderWidthZoom) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
@@ -932,7 +965,7 @@ TEST_F(ComputedStyleTest, BorderWidthZoom) {
document.GetStyleResolver().InitialStyleForElement();
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
style->SetEffectiveZoom(2);
@@ -980,7 +1013,7 @@ TEST_F(ComputedStyleTest,
document.GetStyleResolver().InitialStyleForElement();
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
@@ -1020,7 +1053,7 @@ TEST_F(ComputedStyleTest, TextDecorationNotEqualRequiresRecomputeInkOverflow) {
document.GetStyleResolver().InitialStyleForElement();
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
@@ -1128,7 +1161,7 @@ TEST_F(ComputedStyleTest, ApplyInitialAnimationNameAndTransitionProperty) {
document.GetStyleResolver().InitialStyleForElement();
StyleResolverState state(document, *document.documentElement(),
- StyleRequest(initial.get()));
+ StyleRecalcContext(), StyleRequest(initial.get()));
scoped_refptr<ComputedStyle> style = CreateComputedStyle();
state.SetStyle(style);
@@ -1186,6 +1219,81 @@ TEST_F(ComputedStyleTest, SvgMiscStyleShouldCompareValue) {
TEST_STYLE_VALUE_NO_DIFF(BaselineShift);
}
+TEST_F(ComputedStyleTest, ShouldApplyAnyContainment) {
+ std::unique_ptr<DummyPageHolder> dummy_page_holder =
+ std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
+ Document& document = dummy_page_holder->GetDocument();
+
+ auto* html = document.documentElement();
+ auto* body = document.body();
+ ASSERT_TRUE(html);
+ ASSERT_TRUE(body);
+
+ auto display_types = {CSSValueID::kInline,
+ CSSValueID::kBlock,
+ CSSValueID::kListItem,
+ CSSValueID::kInlineBlock,
+ CSSValueID::kTable,
+ CSSValueID::kInlineTable,
+ CSSValueID::kTableRowGroup,
+ CSSValueID::kTableHeaderGroup,
+ CSSValueID::kTableFooterGroup,
+ CSSValueID::kTableRow,
+ CSSValueID::kTableColumnGroup,
+ CSSValueID::kTableColumn,
+ CSSValueID::kTableCell,
+ CSSValueID::kTableCaption,
+ CSSValueID::kWebkitBox,
+ CSSValueID::kWebkitInlineBox,
+ CSSValueID::kFlex,
+ CSSValueID::kInlineFlex,
+ CSSValueID::kGrid,
+ CSSValueID::kInlineGrid,
+ CSSValueID::kContents,
+ CSSValueID::kFlowRoot,
+ CSSValueID::kNone,
+ CSSValueID::kMath};
+
+ for (auto contain :
+ {CSSValueID::kNone, CSSValueID::kLayout, CSSValueID::kPaint,
+ CSSValueID::kSize, CSSValueID::kStyle}) {
+ html->SetInlineStyleProperty(CSSPropertyID::kContain,
+ getValueName(contain));
+ body->SetInlineStyleProperty(CSSPropertyID::kContain,
+ getValueName(contain));
+ for (auto html_display : display_types) {
+ html->SetInlineStyleProperty(CSSPropertyID::kDisplay, html_display);
+ for (auto body_display : display_types) {
+ body->SetInlineStyleProperty(CSSPropertyID::kDisplay, body_display);
+ document.View()->UpdateAllLifecyclePhasesForTest();
+
+ if (!html->GetLayoutObject()) {
+ EXPECT_TRUE(!html->GetComputedStyle());
+ continue;
+ }
+ EXPECT_EQ(html->GetLayoutObject()->ShouldApplyAnyContainment(),
+ html->GetLayoutObject()->StyleRef().ShouldApplyAnyContainment(
+ *html))
+ << "html contain:" << getValueName(contain)
+ << " display:" << getValueName(html_display);
+ if (!body->GetLayoutObject()) {
+ if (const auto* body_style = body->GetComputedStyle()) {
+ EXPECT_EQ(body_style->Display(), EDisplay::kContents);
+ EXPECT_EQ(body_style->ShouldApplyAnyContainment(*body),
+ contain == CSSValueID::kStyle);
+ }
+ continue;
+ }
+ EXPECT_EQ(body->GetLayoutObject()->ShouldApplyAnyContainment(),
+ body->GetLayoutObject()->StyleRef().ShouldApplyAnyContainment(
+ *body))
+ << "body contain:" << getValueName(contain)
+ << " display:" << getValueName(body_display);
+ }
+ }
+ }
+}
+
#if DCHECK_IS_ON()
TEST_F(ComputedStyleTest, DebugDiffFields) {
diff --git a/chromium/third_party/blink/renderer/core/style/content_data.cc b/chromium/third_party/blink/renderer/core/style/content_data.cc
index ee3a7101731..bdd71fa978e 100644
--- a/chromium/third_party/blink/renderer/core/style/content_data.cc
+++ b/chromium/third_party/blink/renderer/core/style/content_data.cc
@@ -25,10 +25,10 @@
#include <memory>
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
-#include "third_party/blink/renderer/core/layout/layout_counter.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_image_resource.h"
#include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_quote.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -97,8 +97,9 @@ LayoutObject* AltTextContentData::CreateLayoutObject(
LayoutObject* CounterContentData::CreateLayoutObject(
PseudoElement& pseudo,
const ComputedStyle& pseudo_style,
- LegacyLayout) const {
- LayoutObject* layout_object = new LayoutCounter(pseudo, *this);
+ LegacyLayout legacy) const {
+ LayoutObject* layout_object =
+ LayoutObjectFactory::CreateCounter(pseudo, *this, legacy);
layout_object->SetPseudoElementStyle(&pseudo_style);
return layout_object;
}
@@ -111,8 +112,10 @@ void CounterContentData::Trace(Visitor* visitor) const {
LayoutObject* QuoteContentData::CreateLayoutObject(
PseudoElement& pseudo,
const ComputedStyle& pseudo_style,
- LegacyLayout) const {
+ LegacyLayout legacy) const {
LayoutObject* layout_object = new LayoutQuote(pseudo, quote_);
+ if (legacy == LegacyLayout::kForce)
+ layout_object->SetForceLegacyLayout();
layout_object->SetPseudoElementStyle(&pseudo_style);
return layout_object;
}
diff --git a/chromium/third_party/blink/renderer/core/style/content_data.h b/chromium/third_party/blink/renderer/core/style/content_data.h
index c5aebe2ee67..34f747ffb75 100644
--- a/chromium/third_party/blink/renderer/core/style/content_data.h
+++ b/chromium/third_party/blink/renderer/core/style/content_data.h
@@ -209,8 +209,6 @@ class CounterContentData final : public ContentData {
const AtomicString& Separator() const { return separator_; }
const TreeScope* GetTreeScope() const { return tree_scope_; }
- EListStyleType ToDeprecatedListStyleTypeEnum() const;
-
void Trace(Visitor*) const override;
private:
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 a8c40abff33..7097e9966cd 100644
--- a/chromium/third_party/blink/renderer/core/style/fill_layer.cc
+++ b/chromium/third_party/blink/renderer/core/style/fill_layer.cc
@@ -21,7 +21,8 @@
#include "third_party/blink/renderer/core/style/fill_layer.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/css/css_value.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/platform/wtf/size_assertions.h"
@@ -80,7 +81,7 @@ FillLayer::FillLayer(EFillLayerType type, bool use_initial_values)
any_layer_uses_content_box_(false),
any_layer_has_image_(false),
any_layer_has_url_image_(false),
- any_layer_has_local_attachment_image_(false),
+ any_layer_has_local_attachment_(false),
any_layer_has_fixed_attachment_image_(false),
any_layer_has_default_attachment_image_(false),
cached_properties_computed_(false) {}
@@ -118,7 +119,7 @@ FillLayer::FillLayer(const FillLayer& o)
any_layer_uses_content_box_(false),
any_layer_has_image_(false),
any_layer_has_url_image_(false),
- any_layer_has_local_attachment_image_(false),
+ any_layer_has_local_attachment_(false),
any_layer_has_fixed_attachment_image_(false),
any_layer_has_default_attachment_image_(false),
cached_properties_computed_(false) {}
@@ -350,8 +351,7 @@ void FillLayer::ComputeCachedProperties() const {
any_layer_has_image_ = !!GetImage();
any_layer_has_url_image_ =
any_layer_has_image_ && GetImage()->CssValue()->MayContainUrl();
- any_layer_has_local_attachment_image_ =
- any_layer_has_image_ && Attachment() == EFillAttachment::kLocal;
+ any_layer_has_local_attachment_ = Attachment() == EFillAttachment::kLocal;
any_layer_has_fixed_attachment_image_ =
any_layer_has_image_ && Attachment() == EFillAttachment::kFixed;
any_layer_has_default_attachment_image_ =
@@ -365,8 +365,7 @@ void FillLayer::ComputeCachedProperties() const {
any_layer_uses_content_box_ |= next_->any_layer_uses_content_box_;
any_layer_has_image_ |= next_->any_layer_has_image_;
any_layer_has_url_image_ |= next_->any_layer_has_url_image_;
- any_layer_has_local_attachment_image_ |=
- next_->any_layer_has_local_attachment_image_;
+ any_layer_has_local_attachment_ |= next_->any_layer_has_local_attachment_;
any_layer_has_fixed_attachment_image_ |=
next_->any_layer_has_fixed_attachment_image_;
any_layer_has_default_attachment_image_ |=
@@ -396,7 +395,7 @@ bool FillLayer::ImageIsOpaque(const Document& document,
// checking for IsEmpty.
return image_->KnownToBeOpaque(document, style) &&
!image_
- ->ImageSize(document, style.EffectiveZoom(), FloatSize(),
+ ->ImageSize(style.EffectiveZoom(), FloatSize(),
kRespectImageOrientation)
.IsEmpty();
}
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 216cb691b6d..2c0c24f42f8 100644
--- a/chromium/third_party/blink/renderer/core/style/fill_layer.h
+++ b/chromium/third_party/blink/renderer/core/style/fill_layer.h
@@ -235,9 +235,14 @@ class CORE_EXPORT FillLayer {
ComputeCachedPropertiesIfNeeded();
return any_layer_has_url_image_;
}
+ bool AnyLayerHasLocalAttachment() const {
+ ComputeCachedPropertiesIfNeeded();
+ return any_layer_has_local_attachment_;
+ }
bool AnyLayerHasLocalAttachmentImage() const {
ComputeCachedPropertiesIfNeeded();
- return any_layer_has_local_attachment_image_;
+ // Note that this can have false-positive in rare cases.
+ return any_layer_has_local_attachment_ && any_layer_has_image_;
}
bool AnyLayerHasFixedAttachmentImage() const {
ComputeCachedPropertiesIfNeeded();
@@ -343,8 +348,8 @@ class CORE_EXPORT FillLayer {
mutable unsigned any_layer_has_image_ : 1;
// True if any of this of subsequent layers has a url() image.
mutable unsigned any_layer_has_url_image_ : 1;
- // True if any of this or subsequent layers has local attachment image.
- mutable unsigned any_layer_has_local_attachment_image_ : 1;
+ // True if any of this or subsequent layers has local attachment.
+ mutable unsigned any_layer_has_local_attachment_ : 1;
// True if any of this or subsequent layers has fixed attachment image.
mutable unsigned any_layer_has_fixed_attachment_image_ : 1;
// True if any of this or subsequent layers has default attachment image.
diff --git a/chromium/third_party/blink/renderer/core/style/filter_operation.cc b/chromium/third_party/blink/renderer/core/style/filter_operation.cc
index e8d60dd3f54..1b39279caee 100644
--- a/chromium/third_party/blink/renderer/core/style/filter_operation.cc
+++ b/chromium/third_party/blink/renderer/core/style/filter_operation.cc
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/style/filter_operation.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h"
-#include "third_party/blink/renderer/platform/animation/animation_utilities.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h"
diff --git a/chromium/third_party/blink/renderer/core/style/filter_operation.h b/chromium/third_party/blink/renderer/core/style/filter_operation.h
index afda061dbc1..68c606e9c6b 100644
--- a/chromium/third_party/blink/renderer/core/style/filter_operation.h
+++ b/chromium/third_party/blink/renderer/core/style/filter_operation.h
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/platform/geometry/length.h"
#include "third_party/blink/renderer/platform/graphics/box_reflection.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -62,6 +63,7 @@ class CORE_EXPORT FilterOperation : public GarbageCollected<FilterOperation> {
DROP_SHADOW,
BOX_REFLECT,
COLOR_MATRIX,
+ COMPONENT_TRANSFER,
CONVOLVE_MATRIX,
NONE
};
@@ -82,6 +84,7 @@ class CORE_EXPORT FilterOperation : public GarbageCollected<FilterOperation> {
case COLOR_MATRIX:
return true;
case REFERENCE:
+ case COMPONENT_TRANSFER:
case CONVOLVE_MATRIX:
case BOX_REFLECT:
return false;
@@ -403,6 +406,47 @@ struct DowncastTraits<ConvolveMatrixFilterOperation> {
}
};
+class CORE_EXPORT ComponentTransferFilterOperation : public FilterOperation {
+ public:
+ ComponentTransferFilterOperation(const ComponentTransferFunction& red_func,
+ const ComponentTransferFunction& green_func,
+ const ComponentTransferFunction& blue_func,
+ const ComponentTransferFunction& alpha_func)
+ : FilterOperation(COMPONENT_TRANSFER),
+ red_func_(red_func),
+ green_func_(green_func),
+ blue_func_(blue_func),
+ alpha_func_(alpha_func) {}
+
+ ComponentTransferFunction RedFunc() const { return red_func_; }
+ ComponentTransferFunction GreenFunc() const { return green_func_; }
+ ComponentTransferFunction BlueFunc() const { return blue_func_; }
+ ComponentTransferFunction AlphaFunc() const { return alpha_func_; }
+
+ private:
+ bool operator==(const FilterOperation& o) const override {
+ if (!IsSameType(o))
+ return false;
+ const ComponentTransferFilterOperation* other =
+ static_cast<const ComponentTransferFilterOperation*>(&o);
+ return (
+ red_func_ == other->red_func_ && green_func_ == other->green_func_ &&
+ blue_func_ == other->blue_func_ && alpha_func_ == other->alpha_func_);
+ }
+
+ ComponentTransferFunction red_func_;
+ ComponentTransferFunction green_func_;
+ ComponentTransferFunction blue_func_;
+ ComponentTransferFunction alpha_func_;
+};
+
+template <>
+struct DowncastTraits<ComponentTransferFilterOperation> {
+ static bool AllowFrom(const FilterOperation& op) {
+ return op.GetType() == FilterOperation::COMPONENT_TRANSFER;
+ }
+};
+
#undef DEFINE_FILTER_OPERATION_TYPE_CASTS
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/grid_area.h b/chromium/third_party/blink/renderer/core/style/grid_area.h
index ef4704fbb41..0b4bf121ea2 100644
--- a/chromium/third_party/blink/renderer/core/style/grid_area.h
+++ b/chromium/third_party/blink/renderer/core/style/grid_area.h
@@ -59,12 +59,14 @@ struct GridSpan {
return GridSpan(start_line, end_line, kUntranslatedDefinite);
}
- static GridSpan TranslatedDefiniteGridSpan(size_t start_line,
- size_t end_line) {
+ static GridSpan TranslatedDefiniteGridSpan(wtf_size_t start_line,
+ wtf_size_t end_line) {
return GridSpan(start_line, end_line, kTranslatedDefinite);
}
- static GridSpan IndefiniteGridSpan() { return GridSpan(0, 1, kIndefinite); }
+ static GridSpan IndefiniteGridSpan(wtf_size_t span_size = 1) {
+ return GridSpan(wtf_size_t{0}, span_size, kIndefinite);
+ }
bool operator==(const GridSpan& o) const {
return type_ == o.type_ && start_line_ == o.start_line_ &&
@@ -82,12 +84,19 @@ struct GridSpan {
return *this < o || *this == o;
}
- size_t IntegerSpan() const {
+ wtf_size_t IntegerSpan() const {
DCHECK(IsTranslatedDefinite());
DCHECK_GT(end_line_, start_line_);
return end_line_ - start_line_;
}
+ wtf_size_t IndefiniteSpanSize() const {
+ DCHECK(IsIndefinite());
+ DCHECK_EQ(start_line_, 0);
+ DCHECK_GT(end_line_, 0);
+ return end_line_;
+ }
+
int UntranslatedStartLine() const {
DCHECK_EQ(type_, kUntranslatedDefinite);
return start_line_;
@@ -98,28 +107,28 @@ struct GridSpan {
return end_line_;
}
- size_t StartLine() const {
+ wtf_size_t StartLine() const {
DCHECK(IsTranslatedDefinite());
DCHECK_GE(start_line_, 0);
return start_line_;
}
- size_t EndLine() const {
+ wtf_size_t EndLine() const {
DCHECK(IsTranslatedDefinite());
DCHECK_GT(end_line_, 0);
return end_line_;
}
struct GridSpanIterator {
- GridSpanIterator(size_t v) : value(v) {}
+ GridSpanIterator(wtf_size_t v) : value(v) {}
- size_t operator*() const { return value; }
- size_t operator++() { return value++; }
+ wtf_size_t operator*() const { return value; }
+ wtf_size_t operator++() { return value++; }
bool operator!=(GridSpanIterator other) const {
return value != other.value;
}
- size_t value;
+ wtf_size_t value;
};
GridSpanIterator begin() const {
@@ -136,7 +145,7 @@ struct GridSpan {
bool IsTranslatedDefinite() const { return type_ == kTranslatedDefinite; }
bool IsIndefinite() const { return type_ == kIndefinite; }
- void Translate(size_t offset) {
+ void Translate(wtf_size_t offset) {
DCHECK_EQ(type_, kUntranslatedDefinite);
type_ = kTranslatedDefinite;
diff --git a/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.cc b/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.cc
index 41ada541a31..fb92a2d9d37 100644
--- a/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.cc
@@ -27,8 +27,8 @@ NamedLineCollection::NamedLineCollection(
const ComputedStyle& grid_container_style,
const String& named_line,
GridTrackSizingDirection direction,
- size_t last_line,
- size_t auto_repeat_tracks_count)
+ wtf_size_t last_line,
+ wtf_size_t auto_repeat_tracks_count)
: last_line_(last_line),
auto_repeat_total_tracks_(auto_repeat_tracks_count) {
bool is_row_axis = direction == kForColumns;
@@ -76,20 +76,20 @@ bool NamedLineCollection::HasNamedLines() {
return HasExplicitNamedLines() || implicit_named_lines_indexes_;
}
-bool NamedLineCollection::Contains(size_t line) {
+bool NamedLineCollection::Contains(wtf_size_t line) {
CHECK(HasNamedLines());
if (line > last_line_)
return false;
- auto find = [](const Vector<size_t>* indexes, size_t line) {
+ auto find = [](const Vector<wtf_size_t>* indexes, wtf_size_t line) {
return indexes && indexes->Find(line) != kNotFound;
};
if (find(implicit_named_lines_indexes_, line))
return true;
- if (auto_repeat_track_list_length_ == 0LU || line < insertion_point_)
+ if (auto_repeat_track_list_length_ == 0 || line < insertion_point_)
return find(named_lines_indexes_, line);
DCHECK(auto_repeat_total_tracks_);
@@ -108,7 +108,7 @@ bool NamedLineCollection::Contains(size_t line) {
find(named_lines_indexes_, insertion_point_ + 1);
}
- size_t auto_repeat_index_in_first_repetition =
+ wtf_size_t auto_repeat_index_in_first_repetition =
(line - insertion_point_) % auto_repeat_track_list_length_;
if (!auto_repeat_index_in_first_repetition &&
find(auto_repeat_named_lines_indexes_, auto_repeat_track_list_length_))
@@ -117,10 +117,10 @@ bool NamedLineCollection::Contains(size_t line) {
auto_repeat_index_in_first_repetition);
}
-size_t NamedLineCollection::FirstExplicitPosition() {
+wtf_size_t NamedLineCollection::FirstExplicitPosition() {
DCHECK(HasExplicitNamedLines());
- size_t first_line = 0;
+ wtf_size_t first_line = 0;
// If there is no auto repeat(), there must be some named line outside, return
// the 1st one. Also return it if it precedes the auto-repeat().
@@ -137,10 +137,10 @@ size_t NamedLineCollection::FirstExplicitPosition() {
return named_lines_indexes_->at(first_line) + auto_repeat_total_tracks_ - 1;
}
-size_t NamedLineCollection::FirstPosition() {
+wtf_size_t NamedLineCollection::FirstPosition() {
CHECK(HasNamedLines());
- size_t first_line = 0;
+ wtf_size_t first_line = 0;
if (!implicit_named_lines_indexes_)
return FirstExplicitPosition();
@@ -188,16 +188,17 @@ static void InitialAndFinalPositionsFromStyle(
initial_position.SetSpanPosition(1, g_null_atom);
}
-static size_t LookAheadForNamedGridLine(int start,
- size_t number_of_lines,
- size_t grid_last_line,
- NamedLineCollection& lines_collection) {
+static wtf_size_t LookAheadForNamedGridLine(
+ int start,
+ wtf_size_t number_of_lines,
+ wtf_size_t grid_last_line,
+ NamedLineCollection& lines_collection) {
DCHECK(number_of_lines);
// Only implicit lines on the search direction are assumed to have the given
// name, so we can start to look from first line.
// See: https://drafts.csswg.org/css-grid/#grid-placement-span-int
- size_t end = std::max(start, 0);
+ wtf_size_t end = std::max(start, 0);
if (!lines_collection.HasNamedLines()) {
end = std::max(end, grid_last_line + 1);
@@ -214,7 +215,7 @@ static size_t LookAheadForNamedGridLine(int start,
}
static int LookBackForNamedGridLine(int end,
- size_t number_of_lines,
+ wtf_size_t number_of_lines,
int grid_last_line,
NamedLineCollection& lines_collection) {
DCHECK(number_of_lines);
@@ -257,10 +258,10 @@ static GridSpan DefiniteGridSpanWithNamedSpanAgainstOpposite(
return GridSpan::UntranslatedDefiniteGridSpan(start, end);
}
-size_t GridPositionsResolver::ExplicitGridColumnCount(
+wtf_size_t GridPositionsResolver::ExplicitGridColumnCount(
const ComputedStyle& grid_container_style,
- size_t auto_repeat_tracks_count) {
- return std::min<size_t>(
+ wtf_size_t auto_repeat_tracks_count) {
+ return std::min<wtf_size_t>(
std::max(
grid_container_style.GridTemplateColumns().LegacyTrackList().size() +
auto_repeat_tracks_count,
@@ -268,10 +269,10 @@ size_t GridPositionsResolver::ExplicitGridColumnCount(
kGridMaxTracks);
}
-size_t GridPositionsResolver::ExplicitGridRowCount(
+wtf_size_t GridPositionsResolver::ExplicitGridRowCount(
const ComputedStyle& grid_container_style,
- size_t auto_repeat_tracks_count) {
- return std::min<size_t>(
+ wtf_size_t auto_repeat_tracks_count) {
+ return std::min<wtf_size_t>(
std::max(
grid_container_style.GridTemplateRows().LegacyTrackList().size() +
auto_repeat_tracks_count,
@@ -279,9 +280,10 @@ size_t GridPositionsResolver::ExplicitGridRowCount(
kGridMaxTracks);
}
-static size_t ExplicitGridSizeForSide(const ComputedStyle& grid_container_style,
- GridPositionSide side,
- size_t auto_repeat_tracks_count) {
+static wtf_size_t ExplicitGridSizeForSide(
+ const ComputedStyle& grid_container_style,
+ GridPositionSide side,
+ wtf_size_t auto_repeat_tracks_count) {
return (side == kColumnStartSide || side == kColumnEndSide)
? GridPositionsResolver::ExplicitGridColumnCount(
grid_container_style, auto_repeat_tracks_count)
@@ -293,7 +295,7 @@ static GridSpan ResolveNamedGridLinePositionAgainstOppositePosition(
const ComputedStyle& grid_container_style,
int opposite_line,
const GridPosition& position,
- size_t auto_repeat_tracks_count,
+ wtf_size_t auto_repeat_tracks_count,
GridPositionSide side) {
DCHECK(position.IsSpan());
DCHECK(!position.NamedGridLine().IsNull());
@@ -301,8 +303,8 @@ static GridSpan ResolveNamedGridLinePositionAgainstOppositePosition(
// been handled during parsing.
DCHECK_GT(position.SpanPosition(), 0);
- size_t last_line = ExplicitGridSizeForSide(grid_container_style, side,
- auto_repeat_tracks_count);
+ wtf_size_t last_line = ExplicitGridSizeForSide(grid_container_style, side,
+ auto_repeat_tracks_count);
NamedLineCollection lines_collection(
grid_container_style, position.NamedGridLine(), DirectionFromSide(side),
last_line, auto_repeat_tracks_count);
@@ -314,7 +316,7 @@ static GridSpan DefiniteGridSpanWithSpanAgainstOpposite(
int opposite_line,
const GridPosition& position,
GridPositionSide side) {
- size_t position_offset = position.SpanPosition();
+ wtf_size_t position_offset = position.SpanPosition();
if (side == kColumnStartSide || side == kRowStartSide)
return GridSpan::UntranslatedDefiniteGridSpan(
opposite_line - position_offset, opposite_line);
@@ -328,7 +330,7 @@ static GridSpan ResolveGridPositionAgainstOppositePosition(
int opposite_line,
const GridPosition& position,
GridPositionSide side,
- size_t auto_repeat_tracks_count) {
+ wtf_size_t auto_repeat_tracks_count) {
if (position.IsAuto()) {
if (side == kColumnStartSide || side == kRowStartSide)
return GridSpan::UntranslatedDefiniteGridSpan(opposite_line - 1,
@@ -351,37 +353,40 @@ static GridSpan ResolveGridPositionAgainstOppositePosition(
return DefiniteGridSpanWithSpanAgainstOpposite(opposite_line, position, side);
}
-size_t GridPositionsResolver::SpanSizeForAutoPlacedItem(
- const ComputedStyle& grid_item_style,
- GridTrackSizingDirection direction) {
- GridPosition initial_position, final_position;
- InitialAndFinalPositionsFromStyle(grid_item_style, direction,
- initial_position, final_position);
-
+static wtf_size_t SpanSizeFromPositions(const GridPosition& initial_position,
+ const GridPosition& final_position) {
// This method will only be used when both positions need to be resolved
// against the opposite one.
- DCHECK(initial_position.ShouldBeResolvedAgainstOppositePosition());
- DCHECK(final_position.ShouldBeResolvedAgainstOppositePosition());
+ DCHECK(initial_position.ShouldBeResolvedAgainstOppositePosition() &&
+ final_position.ShouldBeResolvedAgainstOppositePosition());
if (initial_position.IsAuto() && final_position.IsAuto())
return 1;
- GridPosition position =
+ const GridPosition& span_position =
initial_position.IsSpan() ? initial_position : final_position;
- DCHECK(position.IsSpan());
- DCHECK(position.SpanPosition());
- return position.SpanPosition();
+ DCHECK(span_position.IsSpan() && span_position.SpanPosition());
+ return span_position.SpanPosition();
+}
+
+wtf_size_t GridPositionsResolver::SpanSizeForAutoPlacedItem(
+ const ComputedStyle& grid_item_style,
+ GridTrackSizingDirection direction) {
+ GridPosition initial_position, final_position;
+ InitialAndFinalPositionsFromStyle(grid_item_style, direction,
+ initial_position, final_position);
+ return SpanSizeFromPositions(initial_position, final_position);
}
static int ResolveNamedGridLinePositionFromStyle(
const ComputedStyle& grid_container_style,
const GridPosition& position,
GridPositionSide side,
- size_t auto_repeat_tracks_count) {
+ wtf_size_t auto_repeat_tracks_count) {
DCHECK(!position.NamedGridLine().IsNull());
- size_t last_line = ExplicitGridSizeForSide(grid_container_style, side,
- auto_repeat_tracks_count);
+ wtf_size_t last_line = ExplicitGridSizeForSide(grid_container_style, side,
+ auto_repeat_tracks_count);
NamedLineCollection lines_collection(
grid_container_style, position.NamedGridLine(), DirectionFromSide(side),
last_line, auto_repeat_tracks_count);
@@ -398,7 +403,7 @@ static int ResolveGridPositionFromStyle(
const ComputedStyle& grid_container_style,
const GridPosition& position,
GridPositionSide side,
- size_t auto_repeat_tracks_count) {
+ wtf_size_t auto_repeat_tracks_count) {
switch (position.GetType()) {
case kExplicitPosition: {
DCHECK(position.IntegerPosition());
@@ -411,9 +416,9 @@ static int ResolveGridPositionFromStyle(
if (position.IsPositive())
return position.IntegerPosition() - 1;
- size_t resolved_position = abs(position.IntegerPosition()) - 1;
- size_t end_of_track = ExplicitGridSizeForSide(grid_container_style, side,
- auto_repeat_tracks_count);
+ wtf_size_t resolved_position = abs(position.IntegerPosition()) - 1;
+ wtf_size_t end_of_track = ExplicitGridSizeForSide(
+ grid_container_style, side, auto_repeat_tracks_count);
return end_of_track - resolved_position;
}
@@ -425,8 +430,8 @@ static int ResolveGridPositionFromStyle(
String named_grid_line = position.NamedGridLine();
DCHECK(!position.NamedGridLine().IsNull());
- size_t last_line = ExplicitGridSizeForSide(grid_container_style, side,
- auto_repeat_tracks_count);
+ wtf_size_t last_line = ExplicitGridSizeForSide(grid_container_style, side,
+ auto_repeat_tracks_count);
NamedLineCollection implicit_lines(
grid_container_style,
ImplicitNamedGridLineForSide(named_grid_line, side),
@@ -461,7 +466,7 @@ GridSpan GridPositionsResolver::ResolveGridPositionsFromStyle(
const ComputedStyle& grid_container_style,
const ComputedStyle& grid_item_style,
GridTrackSizingDirection direction,
- size_t auto_repeat_tracks_count) {
+ wtf_size_t auto_repeat_tracks_count) {
GridPosition initial_position, final_position;
InitialAndFinalPositionsFromStyle(grid_item_style, direction,
initial_position, final_position);
@@ -473,7 +478,8 @@ GridSpan GridPositionsResolver::ResolveGridPositionsFromStyle(
final_position.ShouldBeResolvedAgainstOppositePosition()) {
// We can't get our grid positions without running the auto placement
// algorithm.
- return GridSpan::IndefiniteGridSpan();
+ return GridSpan::IndefiniteGridSpan(
+ SpanSizeFromPositions(initial_position, final_position));
}
if (initial_position.ShouldBeResolvedAgainstOppositePosition()) {
diff --git a/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.h b/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.h
index 13bc3650050..54a6ffddca2 100644
--- a/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.h
+++ b/chromium/third_party/blink/renderer/core/style/grid_positions_resolver.h
@@ -28,25 +28,25 @@ class NamedLineCollection {
NamedLineCollection(const ComputedStyle&,
const String& named_line,
GridTrackSizingDirection,
- size_t last_line,
- size_t auto_repeat_tracks_count);
+ wtf_size_t last_line,
+ wtf_size_t auto_repeat_tracks_count);
bool HasNamedLines();
- size_t FirstPosition();
+ wtf_size_t FirstPosition();
- bool Contains(size_t line);
+ bool Contains(wtf_size_t line);
private:
bool HasExplicitNamedLines();
- size_t FirstExplicitPosition();
- const Vector<size_t>* named_lines_indexes_ = nullptr;
- const Vector<size_t>* auto_repeat_named_lines_indexes_ = nullptr;
- const Vector<size_t>* implicit_named_lines_indexes_ = nullptr;
+ wtf_size_t FirstExplicitPosition();
+ const Vector<wtf_size_t>* named_lines_indexes_ = nullptr;
+ const Vector<wtf_size_t>* auto_repeat_named_lines_indexes_ = nullptr;
+ const Vector<wtf_size_t>* implicit_named_lines_indexes_ = nullptr;
- size_t insertion_point_;
- size_t last_line_;
- size_t auto_repeat_total_tracks_;
- size_t auto_repeat_track_list_length_;
+ wtf_size_t insertion_point_;
+ wtf_size_t last_line_;
+ wtf_size_t auto_repeat_total_tracks_;
+ wtf_size_t auto_repeat_track_list_length_;
NamedLineCollection(const NamedLineCollection&) = delete;
NamedLineCollection& operator=(const NamedLineCollection&) = delete;
@@ -58,21 +58,22 @@ class GridPositionsResolver {
DISALLOW_NEW();
public:
- static size_t ExplicitGridColumnCount(const ComputedStyle&,
- size_t auto_repeat_columns_count);
- static size_t ExplicitGridRowCount(const ComputedStyle&,
- size_t auto_repeat_rows_count);
+ static wtf_size_t ExplicitGridColumnCount(
+ const ComputedStyle&,
+ wtf_size_t auto_repeat_columns_count);
+ static wtf_size_t ExplicitGridRowCount(const ComputedStyle&,
+ wtf_size_t auto_repeat_rows_count);
static GridPositionSide InitialPositionSide(GridTrackSizingDirection);
static GridPositionSide FinalPositionSide(GridTrackSizingDirection);
- static size_t SpanSizeForAutoPlacedItem(const ComputedStyle&,
- GridTrackSizingDirection);
+ static wtf_size_t SpanSizeForAutoPlacedItem(const ComputedStyle&,
+ GridTrackSizingDirection);
static GridSpan ResolveGridPositionsFromStyle(
const ComputedStyle&,
const ComputedStyle&,
GridTrackSizingDirection,
- size_t auto_repeat_tracks_count);
+ wtf_size_t auto_repeat_tracks_count);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/grid_track_list.cc b/chromium/third_party/blink/renderer/core/style/grid_track_list.cc
index 98b48db09ae..afe94e93c88 100644
--- a/chromium/third_party/blink/renderer/core/style/grid_track_list.cc
+++ b/chromium/third_party/blink/renderer/core/style/grid_track_list.cc
@@ -87,7 +87,7 @@ wtf_size_t NGGridTrackList::AutoRepeatSize() const {
}
bool NGGridTrackList::AddRepeater(
- const Vector<GridTrackSize>& repeater_track_sizes,
+ const Vector<GridTrackSize, 1>& repeater_track_sizes,
wtf_size_t repeat_count) {
return AddRepeater(repeater_track_sizes,
NGGridTrackRepeater::RepeatType::kNoAutoRepeat,
@@ -95,13 +95,13 @@ bool NGGridTrackList::AddRepeater(
}
bool NGGridTrackList::AddAutoRepeater(
- const Vector<GridTrackSize>& repeater_track_sizes,
+ const Vector<GridTrackSize, 1>& repeater_track_sizes,
NGGridTrackRepeater::RepeatType repeat_type) {
return AddRepeater(repeater_track_sizes, repeat_type, 1u);
}
bool NGGridTrackList::AddRepeater(
- const Vector<GridTrackSize>& repeater_track_sizes,
+ const Vector<GridTrackSize, 1>& repeater_track_sizes,
NGGridTrackRepeater::RepeatType repeat_type,
wtf_size_t repeat_count) {
if (repeat_count == 0u || repeater_track_sizes.IsEmpty())
@@ -176,45 +176,34 @@ GridTrackList::GridTrackList(const GridTrackList& other) {
AssignFrom(other);
}
-GridTrackList::GridTrackList() {
- if (RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
- ng_track_list_ = std::make_unique<NGGridTrackList>();
- }
-}
-
GridTrackList::GridTrackList(const GridTrackSize& default_track_size) {
- if (RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
- ng_track_list_ = std::make_unique<NGGridTrackList>();
- ng_track_list_->AddRepeater({default_track_size}, 1);
- }
+ if (RuntimeEnabledFeatures::LayoutNGGridEnabled())
+ ng_track_list_.AddRepeater({default_track_size}, 1);
+
legacy_track_list_.push_back(default_track_size);
}
-GridTrackList::GridTrackList(Vector<GridTrackSize>& legacy_tracks)
+GridTrackList::GridTrackList(Vector<GridTrackSize, 1>& legacy_tracks)
: legacy_track_list_(std::move(legacy_tracks)) {
- if (RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
- ng_track_list_ = std::make_unique<NGGridTrackList>();
- ng_track_list_->AddRepeater(legacy_track_list_, 1);
- }
+ if (RuntimeEnabledFeatures::LayoutNGGridEnabled())
+ ng_track_list_.AddRepeater(legacy_track_list_, 1);
}
-Vector<GridTrackSize>& GridTrackList::LegacyTrackList() {
+Vector<GridTrackSize, 1>& GridTrackList::LegacyTrackList() {
return legacy_track_list_;
}
-const Vector<GridTrackSize>& GridTrackList::LegacyTrackList() const {
+const Vector<GridTrackSize, 1>& GridTrackList::LegacyTrackList() const {
return legacy_track_list_;
}
NGGridTrackList& GridTrackList::NGTrackList() {
DCHECK(RuntimeEnabledFeatures::LayoutNGGridEnabled());
- DCHECK(ng_track_list_);
- return *ng_track_list_;
+ return ng_track_list_;
}
const NGGridTrackList& GridTrackList::NGTrackList() const {
DCHECK(RuntimeEnabledFeatures::LayoutNGGridEnabled());
- DCHECK(ng_track_list_);
- return *ng_track_list_;
+ return ng_track_list_;
}
void GridTrackList::operator=(const GridTrackList& other) {
@@ -222,9 +211,9 @@ void GridTrackList::operator=(const GridTrackList& other) {
}
bool GridTrackList::operator==(const GridTrackList& other) const {
- if (RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
- return *ng_track_list_ == *other.ng_track_list_;
- }
+ if (RuntimeEnabledFeatures::LayoutNGGridEnabled())
+ return ng_track_list_ == other.ng_track_list_;
+
return LegacyTrackList() == other.LegacyTrackList();
}
@@ -233,10 +222,9 @@ bool GridTrackList::operator!=(const GridTrackList& other) const {
}
void GridTrackList::AssignFrom(const GridTrackList& other) {
- if (RuntimeEnabledFeatures::LayoutNGGridEnabled()) {
- DCHECK(other.ng_track_list_);
- ng_track_list_ = std::make_unique<NGGridTrackList>(*other.ng_track_list_);
- }
+ if (RuntimeEnabledFeatures::LayoutNGGridEnabled())
+ ng_track_list_ = other.ng_track_list_;
+
legacy_track_list_ = other.legacy_track_list_;
}
diff --git a/chromium/third_party/blink/renderer/core/style/grid_track_list.h b/chromium/third_party/blink/renderer/core/style/grid_track_list.h
index e2620d6204c..3366a022cb3 100644
--- a/chromium/third_party/blink/renderer/core/style/grid_track_list.h
+++ b/chromium/third_party/blink/renderer/core/style/grid_track_list.h
@@ -64,10 +64,10 @@ class CORE_EXPORT NGGridTrackList {
wtf_size_t AutoRepeatSize() const;
// Adds a non-auto repeater.
- bool AddRepeater(const Vector<GridTrackSize>& repeater_track_sizes,
+ bool AddRepeater(const Vector<GridTrackSize, 1>& repeater_track_sizes,
wtf_size_t repeat_count);
// Adds an auto repeater.
- bool AddAutoRepeater(const Vector<GridTrackSize>& repeater_track_sizes,
+ bool AddAutoRepeater(const Vector<GridTrackSize, 1>& repeater_track_sizes,
NGGridTrackRepeater::RepeatType repeat_type);
// Returns true if this list contains an auto repeater.
bool HasAutoRepeater() const;
@@ -81,17 +81,17 @@ class CORE_EXPORT NGGridTrackList {
bool operator==(const NGGridTrackList& o) const;
private:
- bool AddRepeater(const Vector<GridTrackSize>& repeater_track_sizes,
+ bool AddRepeater(const Vector<GridTrackSize, 1>& repeater_track_sizes,
NGGridTrackRepeater::RepeatType repeat_type,
wtf_size_t repeat_count);
// Returns the amount of tracks available before overflow.
wtf_size_t AvailableTrackCount() const;
- Vector<NGGridTrackRepeater> repeaters_;
+ Vector<NGGridTrackRepeater, 1> repeaters_;
// Stores the track sizes of every repeater added to this list; tracks from
// the same repeater group are stored consecutively.
- Vector<GridTrackSize> repeater_track_sizes_;
+ Vector<GridTrackSize, 1> repeater_track_sizes_;
// The index of the automatic repeater, if there is one; |kInvalidRangeIndex|
// otherwise.
@@ -107,14 +107,14 @@ class GridTrackList {
DISALLOW_NEW();
public:
- GridTrackList();
+ GridTrackList() = default;
GridTrackList(const GridTrackList& other);
explicit GridTrackList(const GridTrackSize& default_track_size);
- explicit GridTrackList(Vector<GridTrackSize>& legacy_tracks);
+ explicit GridTrackList(Vector<GridTrackSize, 1>& legacy_tracks);
- Vector<GridTrackSize>& LegacyTrackList();
- const Vector<GridTrackSize>& LegacyTrackList() const;
+ Vector<GridTrackSize, 1>& LegacyTrackList();
+ const Vector<GridTrackSize, 1>& LegacyTrackList() const;
NGGridTrackList& NGTrackList();
const NGGridTrackList& NGTrackList() const;
@@ -125,8 +125,8 @@ class GridTrackList {
private:
void AssignFrom(const GridTrackList& other);
- Vector<GridTrackSize> legacy_track_list_;
- std::unique_ptr<NGGridTrackList> ng_track_list_;
+ Vector<GridTrackSize, 1> legacy_track_list_;
+ NGGridTrackList ng_track_list_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/list_style_type_data.cc b/chromium/third_party/blink/renderer/core/style/list_style_type_data.cc
index 4af9f60f5cf..0771d0e2114 100644
--- a/chromium/third_party/blink/renderer/core/style/list_style_type_data.cc
+++ b/chromium/third_party/blink/renderer/core/style/list_style_type_data.cc
@@ -9,42 +9,12 @@
#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/tree_scope.h"
-#include "third_party/blink/renderer/core/style/content_data.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
-namespace {
-
-using PredefinedCounterStyleNameMap = HashMap<AtomicString, EListStyleType>;
-
-PredefinedCounterStyleNameMap BuildPredefinedCounterStyleNameMap() {
- PredefinedCounterStyleNameMap map;
- for (unsigned i = 0; i < static_cast<unsigned>(EListStyleType::kString);
- ++i) {
- EListStyleType list_style_type = static_cast<EListStyleType>(i);
- CSSValueID css_value_id = PlatformEnumToCSSValueID(list_style_type);
- AtomicString value_name(getValueName(css_value_id));
- map.Set(value_name, list_style_type);
- }
- return map;
-}
-
-EListStyleType CounterStyleNameToDeprecatedEnum(const AtomicString& name) {
- DEFINE_STATIC_LOCAL(PredefinedCounterStyleNameMap,
- predefined_counter_style_name_map,
- (BuildPredefinedCounterStyleNameMap()));
- auto iterator = predefined_counter_style_name_map.find(name);
- if (iterator != predefined_counter_style_name_map.end())
- return iterator->value;
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
- return EListStyleType::kDecimal;
-}
-
-} // namespace
-
void ListStyleTypeData::Trace(Visitor* visitor) const {
visitor->Trace(tree_scope_);
visitor->Trace(counter_style_);
@@ -63,23 +33,7 @@ ListStyleTypeData* ListStyleTypeData::CreateCounterStyle(
tree_scope);
}
-EListStyleType ListStyleTypeData::ToDeprecatedListStyleTypeEnum() const {
- if (IsString())
- return EListStyleType::kString;
- return CounterStyleNameToDeprecatedEnum(GetCounterStyleName());
-}
-
-// TODO(crbug.com/687225): We temporarily put this function here to share the
-// common logic. Clean it up when @counter-style is shipped.
-EListStyleType CounterContentData::ToDeprecatedListStyleTypeEnum() const {
- if (ListStyle() == "none")
- return EListStyleType::kNone;
- return CounterStyleNameToDeprecatedEnum(ListStyle());
-}
-
bool ListStyleTypeData::IsCounterStyleReferenceValid(Document& document) const {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
-
if (!IsCounterStyle()) {
DCHECK(!counter_style_);
return true;
@@ -98,7 +52,6 @@ bool ListStyleTypeData::IsCounterStyleReferenceValid(Document& document) const {
const CounterStyle& ListStyleTypeData::GetCounterStyle(
Document& document) const {
- DCHECK(RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled());
DCHECK(IsCounterStyle());
if (!IsCounterStyleReferenceValid(document)) {
counter_style_ = document.GetStyleEngine().FindCounterStyleAcrossScopes(
diff --git a/chromium/third_party/blink/renderer/core/style/list_style_type_data.h b/chromium/third_party/blink/renderer/core/style/list_style_type_data.h
index 8b79e26d5a0..a17722c01e3 100644
--- a/chromium/third_party/blink/renderer/core/style/list_style_type_data.h
+++ b/chromium/third_party/blink/renderer/core/style/list_style_type_data.h
@@ -61,8 +61,6 @@ class ListStyleTypeData final : public GarbageCollected<ListStyleTypeData> {
bool IsCounterStyleReferenceValid(Document&) const;
const CounterStyle& GetCounterStyle(Document&) const;
- EListStyleType ToDeprecatedListStyleTypeEnum() const;
-
private:
Type type_;
AtomicString name_or_string_value_;
diff --git a/chromium/third_party/blink/renderer/core/style/named_grid_lines_map.h b/chromium/third_party/blink/renderer/core/style/named_grid_lines_map.h
index 55f5866757f..daa76199494 100644
--- a/chromium/third_party/blink/renderer/core/style/named_grid_lines_map.h
+++ b/chromium/third_party/blink/renderer/core/style/named_grid_lines_map.h
@@ -11,7 +11,7 @@
namespace blink {
-using NamedGridLinesMap = HashMap<String, Vector<size_t>>;
+using NamedGridLinesMap = HashMap<String, Vector<wtf_size_t>>;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/quotes_data.cc b/chromium/third_party/blink/renderer/core/style/quotes_data.cc
index c6bf42ef006..4e39eb02139 100644
--- a/chromium/third_party/blink/renderer/core/style/quotes_data.cc
+++ b/chromium/third_party/blink/renderer/core/style/quotes_data.cc
@@ -28,8 +28,8 @@ scoped_refptr<QuotesData> QuotesData::Create(UChar open1,
UChar open2,
UChar close2) {
scoped_refptr<QuotesData> data = QuotesData::Create();
- data->AddPair(std::make_pair(String(&open1, 1), String(&close1, 1)));
- data->AddPair(std::make_pair(String(&open2, 1), String(&close2, 1)));
+ data->AddPair(std::make_pair(String(&open1, 1u), String(&close1, 1u)));
+ data->AddPair(std::make_pair(String(&open2, 1u), String(&close2, 1u)));
return data;
}
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 a879045866a..a97e281a16d 100644
--- a/chromium/third_party/blink/renderer/core/style/shadow_data.cc
+++ b/chromium/third_party/blink/renderer/core/style/shadow_data.cc
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/core/style/shadow_data.h"
-#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"
diff --git a/chromium/third_party/blink/renderer/core/style/style_base_data.cc b/chromium/third_party/blink/renderer/core/style/style_base_data.cc
new file mode 100644
index 00000000000..476b3a43bce
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/style_base_data.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/style/style_base_data.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+
+namespace blink {
+
+StyleBaseData::StyleBaseData(scoped_refptr<const ComputedStyle> style,
+ std::unique_ptr<CSSBitset> set)
+ : computed_style_(style), important_set_(std::move(set)) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_base_data.h b/chromium/third_party/blink/renderer/core/style/style_base_data.h
new file mode 100644
index 00000000000..eb547b198ff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/style_base_data.h
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_BASE_DATA_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_BASE_DATA_H_
+
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+
+namespace blink {
+
+class ComputedStyle;
+
+class CORE_EXPORT StyleBaseData : public RefCounted<StyleBaseData> {
+ USING_FAST_MALLOC(StyleBaseData);
+
+ public:
+ static scoped_refptr<StyleBaseData> Create(
+ scoped_refptr<const ComputedStyle> style,
+ std::unique_ptr<CSSBitset> important_set) {
+ return base::AdoptRef(new StyleBaseData(style, std::move(important_set)));
+ }
+
+ const ComputedStyle* GetBaseComputedStyle() const {
+ return computed_style_.get();
+ }
+ const CSSBitset* GetBaseImportantSet() const { return important_set_.get(); }
+
+ private:
+ StyleBaseData(scoped_refptr<const ComputedStyle>, std::unique_ptr<CSSBitset>);
+
+ scoped_refptr<const ComputedStyle> computed_style_;
+
+ // Keeps track of the !important declarations used to build the base
+ // computed style. These declarations must not be overwritten by animation
+ // effects, hence we have to disable the base computed style optimization when
+ // !important declarations conflict with active animations.
+ //
+ // If there were no !important declarations in the base style, this field
+ // will be nullptr.
+ //
+ // TODO(andruud): We should be able to simply skip applying the animation
+ // for properties in this set instead of disabling the optimization.
+ // However, we currently need the cascade to handle the case where
+ // an !important declaration appears in a :visited selector.
+ // See https://crbug.com/1062217.
+ std::unique_ptr<CSSBitset> important_set_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_BASE_DATA_H_
diff --git a/chromium/third_party/blink/renderer/core/style/style_cached_data.h b/chromium/third_party/blink/renderer/core/style/style_cached_data.h
index 0dc05bd839b..a0fcdba8452 100644
--- a/chromium/third_party/blink/renderer/core/style/style_cached_data.h
+++ b/chromium/third_party/blink/renderer/core/style/style_cached_data.h
@@ -7,6 +7,8 @@
#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/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -37,6 +39,9 @@ class CORE_EXPORT StyleCachedData final {
// getComputedStyle(div, "::before").color // still green.
// </script>
std::unique_ptr<PseudoElementStyleCache> pseudo_element_styles_;
+
+ // Stores the names of of all custom properties on a given ComputedStyle.
+ std::unique_ptr<Vector<AtomicString>> variable_names_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_crossfade_image.cc b/chromium/third_party/blink/renderer/core/style/style_crossfade_image.cc
new file mode 100644
index 00000000000..e625580325a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/style_crossfade_image.cc
@@ -0,0 +1,157 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/style/style_crossfade_image.h"
+
+#include "third_party/blink/renderer/core/css/css_crossfade_value.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/graphics/crossfade_generated_image.h"
+
+namespace blink {
+
+StyleCrossfadeImage::StyleCrossfadeImage(cssvalue::CSSCrossfadeValue& value,
+ StyleImage* from_image,
+ StyleImage* to_image)
+ : original_value_(value), from_image_(from_image), to_image_(to_image) {
+ is_crossfade_ = true;
+}
+
+StyleCrossfadeImage::~StyleCrossfadeImage() = default;
+
+bool StyleCrossfadeImage::IsEqual(const StyleImage& other) const {
+ if (!other.IsCrossfadeImage())
+ return false;
+ return original_value_ == To<StyleCrossfadeImage>(other).original_value_;
+}
+
+CSSValue* StyleCrossfadeImage::CssValue() const {
+ return original_value_;
+}
+
+CSSValue* StyleCrossfadeImage::ComputedCSSValue(
+ const ComputedStyle& style,
+ bool allow_visited_style) const {
+ // If either of the images are null (meaning that they are 'none'), then use
+ // the original value.
+ CSSValue* from_value =
+ from_image_ ? from_image_->ComputedCSSValue(style, allow_visited_style)
+ : &original_value_->From();
+ CSSValue* to_value =
+ to_image_ ? to_image_->ComputedCSSValue(style, allow_visited_style)
+ : &original_value_->To();
+ return MakeGarbageCollected<cssvalue::CSSCrossfadeValue>(
+ from_value, to_value, &original_value_->Percentage());
+}
+
+bool StyleCrossfadeImage::CanRender() const {
+ return (!from_image_ || from_image_->CanRender()) &&
+ (!to_image_ || to_image_->CanRender());
+}
+
+bool StyleCrossfadeImage::IsLoaded() const {
+ return (!from_image_ || from_image_->IsLoaded()) &&
+ (!to_image_ || to_image_->IsLoaded());
+}
+
+bool StyleCrossfadeImage::ErrorOccurred() const {
+ return (from_image_ && from_image_->ErrorOccurred()) ||
+ (to_image_ && to_image_->ErrorOccurred());
+}
+
+bool StyleCrossfadeImage::IsAccessAllowed(String& failing_url) const {
+ return (!from_image_ || from_image_->IsAccessAllowed(failing_url)) &&
+ (!to_image_ || to_image_->IsAccessAllowed(failing_url));
+}
+
+FloatSize StyleCrossfadeImage::ImageSize(float multiplier,
+ const FloatSize& default_object_size,
+ RespectImageOrientationEnum) const {
+ if (!from_image_ || !to_image_)
+ return FloatSize();
+
+ // TODO(fs): Consider |respect_orientation|?
+ FloatSize from_image_size = from_image_->ImageSize(
+ multiplier, default_object_size, kRespectImageOrientation);
+ FloatSize to_image_size = to_image_->ImageSize(
+ multiplier, default_object_size, kRespectImageOrientation);
+
+ // Rounding issues can cause transitions between images of equal size to
+ // return a different fixed size; avoid performing the interpolation if the
+ // images are the same size.
+ if (from_image_size == to_image_size)
+ return from_image_size;
+
+ float percentage = original_value_->Percentage().GetFloatValue();
+ float inverse_percentage = 1 - percentage;
+ return FloatSize(from_image_size.Width() * inverse_percentage +
+ to_image_size.Width() * percentage,
+ from_image_size.Height() * inverse_percentage +
+ to_image_size.Height() * percentage);
+}
+
+bool StyleCrossfadeImage::HasIntrinsicSize() const {
+ return (from_image_ && from_image_->HasIntrinsicSize()) ||
+ (to_image_ && to_image_->HasIntrinsicSize());
+}
+
+void StyleCrossfadeImage::AddClient(ImageResourceObserver* observer) {
+ const bool had_clients = original_value_->HasClients();
+ original_value_->AddClient(observer);
+ if (had_clients)
+ return;
+ ImageResourceObserver* proxy_observer = original_value_->GetObserverProxy();
+ if (from_image_)
+ from_image_->AddClient(proxy_observer);
+ if (to_image_)
+ to_image_->AddClient(proxy_observer);
+}
+
+void StyleCrossfadeImage::RemoveClient(ImageResourceObserver* observer) {
+ original_value_->RemoveClient(observer);
+ if (original_value_->HasClients())
+ return;
+ ImageResourceObserver* proxy_observer = original_value_->GetObserverProxy();
+ if (from_image_)
+ from_image_->RemoveClient(proxy_observer);
+ if (to_image_)
+ to_image_->RemoveClient(proxy_observer);
+}
+
+scoped_refptr<Image> StyleCrossfadeImage::GetImage(
+ const ImageResourceObserver& observer,
+ const Document& document,
+ const ComputedStyle& style,
+ const FloatSize& target_size) const {
+ if (target_size.IsEmpty())
+ return nullptr;
+ if (!from_image_ || !to_image_)
+ return Image::NullImage();
+ const FloatSize resolved_size =
+ ImageSize(style.EffectiveZoom(), target_size, kRespectImageOrientation);
+ const ImageResourceObserver* proxy_observer =
+ original_value_->GetObserverProxy();
+ return CrossfadeGeneratedImage::Create(
+ from_image_->GetImage(*proxy_observer, document, style, target_size),
+ to_image_->GetImage(*proxy_observer, document, style, target_size),
+ original_value_->Percentage().GetFloatValue(), resolved_size);
+}
+
+WrappedImagePtr StyleCrossfadeImage::Data() const {
+ return original_value_.Get();
+}
+
+bool StyleCrossfadeImage::KnownToBeOpaque(const Document& document,
+ const ComputedStyle& style) const {
+ return from_image_ && from_image_->KnownToBeOpaque(document, style) &&
+ to_image_ && to_image_->KnownToBeOpaque(document, style);
+}
+
+void StyleCrossfadeImage::Trace(Visitor* visitor) const {
+ visitor->Trace(original_value_);
+ visitor->Trace(from_image_);
+ visitor->Trace(to_image_);
+ StyleImage::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_crossfade_image.h b/chromium/third_party/blink/renderer/core/style/style_crossfade_image.h
new file mode 100644
index 00000000000..dad4122f036
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/style_crossfade_image.h
@@ -0,0 +1,70 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_CROSSFADE_IMAGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_CROSSFADE_IMAGE_H_
+
+#include "third_party/blink/renderer/core/style/style_image.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+namespace cssvalue {
+class CSSCrossfadeValue;
+}
+
+// This class represents a <cross-fade()> <image> function.
+class StyleCrossfadeImage final : public StyleImage {
+ public:
+ StyleCrossfadeImage(cssvalue::CSSCrossfadeValue&,
+ StyleImage* from_image,
+ StyleImage* to_image);
+ ~StyleCrossfadeImage() override;
+
+ CSSValue* CssValue() const override;
+ CSSValue* ComputedCSSValue(const ComputedStyle&,
+ bool allow_visited_style) const override;
+
+ bool CanRender() const override;
+ bool IsLoaded() const override;
+ bool ErrorOccurred() const override;
+ bool IsAccessAllowed(String&) const override;
+
+ FloatSize ImageSize(float multiplier,
+ const FloatSize& default_object_size,
+ RespectImageOrientationEnum) const override;
+
+ bool HasIntrinsicSize() const override;
+
+ void AddClient(ImageResourceObserver*) override;
+ void RemoveClient(ImageResourceObserver*) override;
+
+ scoped_refptr<Image> GetImage(const ImageResourceObserver&,
+ const Document&,
+ const ComputedStyle&,
+ const FloatSize& target_size) const override;
+
+ WrappedImagePtr Data() const override;
+ bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
+
+ void Trace(Visitor*) const override;
+
+ private:
+ bool IsEqual(const StyleImage&) const override;
+
+ Member<cssvalue::CSSCrossfadeValue> original_value_;
+ Member<StyleImage> from_image_;
+ Member<StyleImage> to_image_;
+};
+
+template <>
+struct DowncastTraits<StyleCrossfadeImage> {
+ static bool AllowFrom(const StyleImage& style_image) {
+ return style_image.IsCrossfadeImage();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_CROSSFADE_IMAGE_H_
diff --git a/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc b/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc
index cc194f2142a..11268a3daee 100644
--- a/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -107,8 +107,15 @@ bool StyleFetchedImage::ErrorOccurred() const {
return image_->ErrorOccurred();
}
+bool StyleFetchedImage::IsAccessAllowed(String& failing_url) const {
+ DCHECK(image_->IsLoaded());
+ if (image_->IsAccessAllowed())
+ return true;
+ failing_url = image_->Url().ElidedString();
+ return false;
+}
+
FloatSize StyleFetchedImage::ImageSize(
- const Document&,
float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum respect_orientation) const {
diff --git a/chromium/third_party/blink/renderer/core/style/style_fetched_image.h b/chromium/third_party/blink/renderer/core/style/style_fetched_image.h
index 843c35c61a1..f77edd61425 100644
--- a/chromium/third_party/blink/renderer/core/style/style_fetched_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_fetched_image.h
@@ -57,8 +57,9 @@ class StyleFetchedImage final : public StyleImage,
bool CanRender() const override;
bool IsLoaded() const override;
bool ErrorOccurred() const override;
- FloatSize ImageSize(const Document&,
- float multiplier,
+ bool IsAccessAllowed(String&) const override;
+
+ FloatSize ImageSize(float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum) const override;
bool HasIntrinsicSize() const override;
diff --git a/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.cc b/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.cc
index 0fe22a09cd9..c3790b9b34b 100644
--- a/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.cc
@@ -93,8 +93,15 @@ bool StyleFetchedImageSet::ErrorOccurred() const {
return best_fit_image_->ErrorOccurred();
}
+bool StyleFetchedImageSet::IsAccessAllowed(String& failing_url) const {
+ DCHECK(best_fit_image_->IsLoaded());
+ if (best_fit_image_->IsAccessAllowed())
+ return true;
+ failing_url = best_fit_image_->Url().ElidedString();
+ return false;
+}
+
FloatSize StyleFetchedImageSet::ImageSize(
- const Document&,
float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum respect_orientation) const {
diff --git a/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.h b/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.h
index 5eb6f5f943e..61c9c08bc05 100644
--- a/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.h
+++ b/chromium/third_party/blink/renderer/core/style/style_fetched_image_set.h
@@ -65,8 +65,9 @@ class StyleFetchedImageSet final : public StyleImage,
bool CanRender() const override;
bool IsLoaded() const override;
bool ErrorOccurred() const override;
- FloatSize ImageSize(const Document&,
- float multiplier,
+ bool IsAccessAllowed(String&) const override;
+
+ FloatSize ImageSize(float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum) const override;
bool HasIntrinsicSize() const override;
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 349a0aaa43a..c409c5c54b5 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
@@ -23,7 +23,9 @@
#include "third_party/blink/renderer/core/style/style_generated_image.h"
+#include "third_party/blink/renderer/core/css/css_gradient_value.h"
#include "third_party/blink/renderer/core/css/css_image_generator_value.h"
+#include "third_party/blink/renderer/core/css/css_paint_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"
@@ -31,8 +33,7 @@
namespace blink {
StyleGeneratedImage::StyleGeneratedImage(const CSSImageGeneratorValue& value)
- : image_generator_value_(const_cast<CSSImageGeneratorValue*>(&value)),
- fixed_size_(image_generator_value_->IsFixedSize()) {
+ : image_generator_value_(const_cast<CSSImageGeneratorValue*>(&value)) {
is_generated_image_ = true;
if (value.IsPaintValue())
is_paint_image_ = true;
@@ -52,21 +53,17 @@ CSSValue* StyleGeneratedImage::CssValue() const {
CSSValue* StyleGeneratedImage::ComputedCSSValue(
const ComputedStyle& style,
bool allow_visited_style) const {
- return image_generator_value_->ComputedCSSValue(style, allow_visited_style);
+ if (auto* image_gradient_value =
+ DynamicTo<cssvalue::CSSGradientValue>(image_generator_value_.Get())) {
+ return image_gradient_value->ComputedCSSValue(style, allow_visited_style);
+ }
+ DCHECK(IsA<CSSPaintValue>(image_generator_value_.Get()));
+ return image_generator_value_;
}
-FloatSize StyleGeneratedImage::ImageSize(const Document& document,
- float multiplier,
+FloatSize StyleGeneratedImage::ImageSize(float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum) const {
- if (fixed_size_) {
- FloatSize unzoomed_default_object_size = default_object_size;
- unzoomed_default_object_size.Scale(1 / multiplier);
- return ApplyZoom(FloatSize(image_generator_value_->FixedSize(
- document, unzoomed_default_object_size)),
- multiplier);
- }
-
return default_object_size;
}
diff --git a/chromium/third_party/blink/renderer/core/style/style_generated_image.h b/chromium/third_party/blink/renderer/core/style/style_generated_image.h
index a1ec410ea3c..b1e8080cec1 100644
--- a/chromium/third_party/blink/renderer/core/style/style_generated_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_generated_image.h
@@ -35,8 +35,8 @@ class CSSImageGeneratorValue;
class Document;
class ImageResourceObserver;
-// This class represents a generated <image> such as a gradient, cross-fade or
-// paint(...) function.
+// This class represents a generated <image> such as a gradient or paint(...)
+// function. Use only for images that have no intrinsic dimensions.
class CORE_EXPORT StyleGeneratedImage final : public StyleImage {
public:
explicit StyleGeneratedImage(const CSSImageGeneratorValue&);
@@ -47,11 +47,12 @@ class CORE_EXPORT StyleGeneratedImage final : public StyleImage {
CSSValue* ComputedCSSValue(const ComputedStyle&,
bool allow_visited_style) const override;
- FloatSize ImageSize(const Document&,
- float multiplier,
+ bool IsAccessAllowed(String&) const override { return true; }
+
+ FloatSize ImageSize(float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum) const override;
- bool HasIntrinsicSize() const override { return fixed_size_; }
+ bool HasIntrinsicSize() const override { return false; }
void AddClient(ImageResourceObserver*) override;
void RemoveClient(ImageResourceObserver*) override;
// The |target_size| is the desired image size
@@ -72,7 +73,6 @@ class CORE_EXPORT StyleGeneratedImage final : public StyleImage {
// TODO(sashab): Replace this with <const CSSImageGeneratorValue> once
// Member<> supports const types.
Member<CSSImageGeneratorValue> image_generator_value_;
- const bool fixed_size_;
};
template <>
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 353307a6883..d161f6b25a6 100644
--- a/chromium/third_party/blink/renderer/core/style/style_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_image.h
@@ -72,6 +72,11 @@ class CORE_EXPORT StyleImage : public GarbageCollected<StyleImage> {
// Any underlying resources this <image> references failed to load.
virtual bool ErrorOccurred() const { return false; }
+ // Is the <image> considered same-origin? Can only be called if IsLoaded()
+ // returns true. |failing_url| is set to the (potentially formatted) URL of
+ // the first non-same-origin <image>.
+ virtual bool IsAccessAllowed(String& failing_url) const = 0;
+
// Determine the concrete object size of this <image>, scaled by multiplier,
// using the specified default object size. Return value as a FloatSize
// because we want integer sizes to remain integers when zoomed and then
@@ -89,8 +94,7 @@ class CORE_EXPORT StyleImage : public GarbageCollected<StyleImage> {
//
// The size will respect the image orientation if requested and if the image
// supports it.
- virtual FloatSize ImageSize(const Document&,
- float multiplier,
+ virtual FloatSize ImageSize(float multiplier,
const FloatSize& default_object_size,
RespectImageOrientationEnum) const = 0;
@@ -147,6 +151,7 @@ class CORE_EXPORT StyleImage : public GarbageCollected<StyleImage> {
return is_image_resource_set_;
}
ALWAYS_INLINE bool IsPaintImage() const { return is_paint_image_; }
+ ALWAYS_INLINE bool IsCrossfadeImage() const { return is_crossfade_; }
bool IsLazyloadPossiblyDeferred() const {
return is_lazyload_possibly_deferred_;
@@ -160,12 +165,14 @@ class CORE_EXPORT StyleImage : public GarbageCollected<StyleImage> {
is_pending_image_(false),
is_generated_image_(false),
is_image_resource_set_(false),
+ is_crossfade_(false),
is_paint_image_(false),
is_lazyload_possibly_deferred_(false) {}
bool is_image_resource_ : 1;
bool is_pending_image_ : 1;
bool is_generated_image_ : 1;
bool is_image_resource_set_ : 1;
+ bool is_crossfade_ : 1;
bool is_paint_image_ : 1;
bool is_lazyload_possibly_deferred_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/style/style_pending_image.cc b/chromium/third_party/blink/renderer/core/style/style_pending_image.cc
index f793daca994..eb1be629218 100644
--- a/chromium/third_party/blink/renderer/core/style/style_pending_image.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_pending_image.cc
@@ -4,27 +4,69 @@
#include "third_party/blink/renderer/core/style/style_pending_image.h"
+#include "third_party/blink/renderer/core/css/css_crossfade_value.h"
+#include "third_party/blink/renderer/core/css/css_gradient_value.h"
+#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_image_generator_value.h"
#include "third_party/blink/renderer/core/css/css_image_set_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
+#include "third_party/blink/renderer/core/css/css_paint_value.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
-CSSValue* StylePendingImage::ComputedCSSValue(const ComputedStyle& style,
- bool allow_visited_style) const {
- DCHECK(style.IsEnsuredInDisplayNone() ||
- style.Display() == EDisplay::kContents);
+namespace {
+
+class ComputedCSSValueBuilder {
+ STACK_ALLOCATED();
+
+ public:
+ ComputedCSSValueBuilder(const ComputedStyle& style, bool allow_visited_style)
+ : style_(style), allow_visited_style_(allow_visited_style) {}
+
+ CSSValue* Build(CSSValue* value) const;
+
+ private:
+ CSSValue* CrossfadeArgument(CSSValue*) const;
+
+ const ComputedStyle& style_;
+ const bool allow_visited_style_;
+};
- CSSValue* value = CssValue();
+CSSValue* ComputedCSSValueBuilder::CrossfadeArgument(CSSValue* value) const {
+ if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ DCHECK_EQ(identifier_value->GetValueID(), CSSValueID::kNone);
+ return value;
+ }
+ return Build(value);
+}
+
+CSSValue* ComputedCSSValueBuilder::Build(CSSValue* value) const {
if (auto* image_value = DynamicTo<CSSImageValue>(value))
return image_value->ValueWithURLMadeAbsolute();
if (auto* image_set_value = DynamicTo<CSSImageSetValue>(value))
return image_set_value->ValueWithURLsMadeAbsolute();
- if (auto* image_generator_value = DynamicTo<CSSImageGeneratorValue>(value))
- return image_generator_value->ComputedCSSValue(style, allow_visited_style);
+ if (auto* image_crossfade = DynamicTo<cssvalue::CSSCrossfadeValue>(value)) {
+ return MakeGarbageCollected<cssvalue::CSSCrossfadeValue>(
+ CrossfadeArgument(&image_crossfade->From()),
+ CrossfadeArgument(&image_crossfade->To()),
+ &image_crossfade->Percentage());
+ }
+ if (IsA<CSSPaintValue>(value))
+ return value;
+ if (auto* image_gradient_value = DynamicTo<cssvalue::CSSGradientValue>(value))
+ return image_gradient_value->ComputedCSSValue(style_, allow_visited_style_);
NOTREACHED();
return value;
}
+} // namespace
+
+CSSValue* StylePendingImage::ComputedCSSValue(const ComputedStyle& style,
+ bool allow_visited_style) const {
+ DCHECK(style.IsEnsuredInDisplayNone() ||
+ style.Display() == EDisplay::kContents);
+ return ComputedCSSValueBuilder(style, allow_visited_style).Build(CssValue());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_pending_image.h b/chromium/third_party/blink/renderer/core/style/style_pending_image.h
index 6acdd067db8..e4247434f7e 100644
--- a/chromium/third_party/blink/renderer/core/style/style_pending_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_pending_image.h
@@ -54,8 +54,8 @@ class StylePendingImage final : public StyleImage {
CSSValue* ComputedCSSValue(const ComputedStyle& style,
bool allow_visited_style) const override;
- FloatSize ImageSize(const Document&,
- float,
+ bool IsAccessAllowed(String&) const override { return true; }
+ FloatSize ImageSize(float,
const FloatSize&,
RespectImageOrientationEnum) const override {
return FloatSize();
diff --git a/chromium/third_party/blink/renderer/core/style/style_svg_resource.cc b/chromium/third_party/blink/renderer/core/style/style_svg_resource.cc
new file mode 100644
index 00000000000..55ea5c449d1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/style_svg_resource.cc
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/style/style_svg_resource.h"
+
+#include "third_party/blink/renderer/core/svg/svg_resource.h"
+
+namespace blink {
+
+StyleSVGResource::StyleSVGResource(SVGResource* resource,
+ const AtomicString& url)
+ : resource_(resource), url_(url) {}
+
+StyleSVGResource::~StyleSVGResource() = default;
+
+void StyleSVGResource::AddClient(SVGResourceClient& client) {
+ if (resource_)
+ resource_->AddClient(client);
+}
+
+void StyleSVGResource::RemoveClient(SVGResourceClient& client) {
+ if (resource_)
+ resource_->RemoveClient(client);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_svg_resource.h b/chromium/third_party/blink/renderer/core/style/style_svg_resource.h
index ec1a91f5d28..18eab559f57 100644
--- a/chromium/third_party/blink/renderer/core/style/style_svg_resource.h
+++ b/chromium/third_party/blink/renderer/core/style/style_svg_resource.h
@@ -6,13 +6,16 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_SVG_RESOURCE_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/svg/svg_resource.h"
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
+class SVGResource;
+class SVGResourceClient;
+
class StyleSVGResource : public RefCounted<StyleSVGResource> {
USING_FAST_MALLOC(StyleSVGResource);
@@ -21,26 +24,20 @@ class StyleSVGResource : public RefCounted<StyleSVGResource> {
const AtomicString& url) {
return base::AdoptRef(new StyleSVGResource(resource, url));
}
+ CORE_EXPORT ~StyleSVGResource();
bool operator==(const StyleSVGResource& other) const {
return resource_.Get() == other.resource_.Get();
}
- void AddClient(SVGResourceClient& client) {
- if (resource_)
- resource_->AddClient(client);
- }
- void RemoveClient(SVGResourceClient& client) {
- if (resource_)
- resource_->RemoveClient(client);
- }
+ void AddClient(SVGResourceClient& client);
+ void RemoveClient(SVGResourceClient& client);
SVGResource* Resource() const { return resource_; }
const AtomicString& Url() const { return url_; }
private:
- StyleSVGResource(SVGResource* resource, const AtomicString& url)
- : resource_(resource), url_(url) {}
+ StyleSVGResource(SVGResource* resource, const AtomicString& url);
Persistent<SVGResource> resource_;
const AtomicString url_;
diff --git a/chromium/third_party/blink/renderer/core/style/style_variables.cc b/chromium/third_party/blink/renderer/core/style/style_variables.cc
index 149278211a1..87a6fc7c931 100644
--- a/chromium/third_party/blink/renderer/core/style/style_variables.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_variables.cc
@@ -37,6 +37,12 @@ StyleVariables::StyleVariables(const StyleVariables& other)
: data_(other.data_),
values_(MakeGarbageCollected<ValueMap>(*other.values_)) {}
+StyleVariables& StyleVariables::operator=(const StyleVariables& other) {
+ data_ = other.data_;
+ values_ = MakeGarbageCollected<ValueMap>(*other.values_);
+ return *this;
+}
+
bool StyleVariables::operator==(const StyleVariables& other) const {
if (data_.size() != other.data_.size())
return false;
diff --git a/chromium/third_party/blink/renderer/core/style/style_variables.h b/chromium/third_party/blink/renderer/core/style/style_variables.h
index 9100c460751..4640aa7ff08 100644
--- a/chromium/third_party/blink/renderer/core/style/style_variables.h
+++ b/chromium/third_party/blink/renderer/core/style/style_variables.h
@@ -47,6 +47,7 @@ class CORE_EXPORT StyleVariables {
StyleVariables();
StyleVariables(const StyleVariables&);
+ StyleVariables& operator=(const StyleVariables&);
bool operator==(const StyleVariables& other) const;
bool operator!=(const StyleVariables& other) const {
diff --git a/chromium/third_party/blink/renderer/core/style/style_variables_test.cc b/chromium/third_party/blink/renderer/core/style/style_variables_test.cc
index 4d62b457fe7..dd519c27743 100644
--- a/chromium/third_party/blink/renderer/core/style/style_variables_test.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_variables_test.cc
@@ -36,6 +36,44 @@ TEST_F(StyleVariablesTest, Copy) {
EXPECT_EQ(vars1, vars2);
}
+TEST_F(StyleVariablesTest, Assignment) {
+ auto foo_data = css_test_helpers::CreateVariableData("foo");
+ const CSSValue* foo_value = css_test_helpers::CreateCustomIdent("foo");
+
+ StyleVariables vars1;
+ vars1.SetData("--x", foo_data);
+ vars1.SetValue("--x", foo_value);
+ EXPECT_EQ(foo_data, vars1.GetData("--x").value_or(nullptr));
+ EXPECT_EQ(foo_value, vars1.GetValue("--x").value_or(nullptr));
+
+ StyleVariables vars2;
+ EXPECT_FALSE(vars2.GetData("--x").has_value());
+ EXPECT_FALSE(vars2.GetValue("--x").has_value());
+
+ vars2.SetData("--y", foo_data);
+ vars2.SetValue("--y", foo_value);
+ EXPECT_EQ(foo_data, vars2.GetData("--y").value_or(nullptr));
+ EXPECT_EQ(foo_value, vars2.GetValue("--y").value_or(nullptr));
+
+ vars2 = vars1;
+ EXPECT_TRUE(vars2.GetData("--x").has_value());
+ EXPECT_TRUE(vars2.GetValue("--x").has_value());
+ EXPECT_FALSE(vars2.GetData("--y").has_value());
+ EXPECT_FALSE(vars2.GetValue("--y").has_value());
+ EXPECT_EQ(vars1, vars2);
+
+ vars2.SetData("--z", foo_data);
+ vars2.SetValue("--z", foo_value);
+ EXPECT_EQ(foo_data, vars2.GetData("--z").value_or(nullptr));
+ EXPECT_EQ(foo_value, vars2.GetValue("--z").value_or(nullptr));
+
+ // Should not affect vars1:
+ EXPECT_FALSE(vars1.GetData("--y").has_value());
+ EXPECT_FALSE(vars1.GetValue("--y").has_value());
+ EXPECT_FALSE(vars1.GetData("--z").has_value());
+ EXPECT_FALSE(vars1.GetValue("--z").has_value());
+}
+
TEST_F(StyleVariablesTest, GetNames) {
StyleVariables vars;
vars.SetData("--x", css_test_helpers::CreateVariableData("foo"));
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/priority_queue.h b/chromium/third_party/blink/renderer/core/svg/animation/priority_queue.h
index 86030bc43e8..fe60c684753 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/priority_queue.h
+++ b/chromium/third_party/blink/renderer/core/svg/animation/priority_queue.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_PRIORITY_QUEUE_H_
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/heap/member.h"
@@ -30,6 +29,8 @@ class PriorityQueue {
using const_iterator = typename StorageType::const_iterator;
PriorityQueue() = default;
+ PriorityQueue(const PriorityQueue&) = delete;
+ PriorityQueue& operator=(const PriorityQueue&) = delete;
bool Contains(ElementType* element) const {
return element->PriorityQueueHandle() != kNotFound;
@@ -79,8 +80,6 @@ class PriorityQueue {
}
StorageType heap_;
-
- DISALLOW_COPY_AND_ASSIGN(PriorityQueue);
};
template <typename PriorityType, typename ElementType>
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.h b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.h
index badbc1371d2..9c37ebfa602 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.h
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.h
@@ -28,7 +28,7 @@
#include "base/dcheck_is_on.h"
#include "base/time/time.h"
-#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/svg/animation/priority_queue.h"
#include "third_party/blink/renderer/core/svg/animation/smil_time.h"
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
index 8a6f6139e34..64624d674ca 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -85,7 +85,9 @@ void SMILInstanceTimeList::InsertSortedAndUnique(SMILTime time,
if (position->Origin() == origin)
return;
}
- instance_times_.insert(position - instance_times_.begin(), time_with_origin);
+ instance_times_.insert(
+ static_cast<wtf_size_t>(position - instance_times_.begin()),
+ time_with_origin);
AddOrigin(origin);
}
@@ -97,7 +99,8 @@ void SMILInstanceTimeList::RemoveWithOrigin(SMILTimeOrigin origin) {
[origin](const SMILTimeWithOrigin& instance_time) {
return instance_time.Origin() == origin;
});
- instance_times_.Shrink(tail - instance_times_.begin());
+ instance_times_.Shrink(
+ static_cast<wtf_size_t>(tail - instance_times_.begin()));
ClearOrigin(origin);
}
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 c685e0b5575..7d5fadd5c74 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
@@ -208,7 +208,7 @@ sk_sp<PaintFilter> FEImage::CreateImageFilter() {
if (crop_rect != dst_rect)
src_rect = blink::MapRect(crop_rect, dst_rect, src_rect);
return sk_make_sp<ImagePaintFilter>(std::move(image), src_rect, crop_rect,
- kHigh_SkFilterQuality);
+ cc::PaintFlags::FilterQuality::kHigh);
}
// "A href reference that is an empty image (zero width or zero height),
// that fails to download, is non-existent, or that cannot be displayed
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc b/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc
index bea7d731a63..c042969d4d3 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc
@@ -196,6 +196,7 @@ void SVGFilterBuilder::BuildGraph(Filter* filter,
}
void SVGFilterBuilder::Add(const AtomicString& id, FilterEffect* effect) {
+ DCHECK(effect);
if (id.IsEmpty()) {
last_effect_ = effect;
return;
@@ -210,16 +211,20 @@ void SVGFilterBuilder::Add(const AtomicString& id, FilterEffect* effect) {
FilterEffect* SVGFilterBuilder::GetEffectById(const AtomicString& id) const {
if (!id.IsEmpty()) {
- if (FilterEffect* builtin_effect = builtin_effects_.at(id))
- return builtin_effect;
+ auto builtin_it = builtin_effects_.find(id);
+ if (builtin_it != builtin_effects_.end())
+ return builtin_it->value;
- if (FilterEffect* named_effect = named_effects_.at(id))
- return named_effect;
+ auto named_it = named_effects_.find(id);
+ if (named_it != named_effects_.end())
+ return named_it->value;
}
if (last_effect_)
return last_effect_;
+ // Fallback to the 'SourceGraphic' input. We add it in the constructor so it will always be
+ // present.
return builtin_effects_.at(FilterInputKeywords::GetSourceGraphic());
}
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 c085d714c5f..93d12ad82f5 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
@@ -119,7 +119,7 @@ class FailingLoader final : public WebURLLoader {
WebURLLoaderClient* client) override {
NOTREACHED();
}
- void SetDefersLoading(DeferType) override {}
+ void Freeze(LoaderFreezeMode) override {}
void DidChangePriority(WebURLRequest::Priority, int) override {}
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
override {
@@ -284,7 +284,7 @@ bool SVGImage::CurrentFrameHasSingleSecurityOrigin() const {
return true;
}
-IntSize SVGImage::Size() const {
+IntSize SVGImage::SizeWithConfig(SizeConfig) const {
return RoundedIntSize(intrinsic_size_);
}
@@ -369,11 +369,13 @@ FloatSize SVGImage::ConcreteObjectSize(
SVGImage::DrawInfo::DrawInfo(const FloatSize& container_size,
float zoom,
- const KURL& url)
+ const KURL& url,
+ bool is_dark_mode_enabled)
: container_size_(container_size),
- rounded_container_size_(RoundedLayoutSize(container_size)),
+ rounded_container_size_(RoundedIntSize(container_size)),
zoom_(zoom),
- url_(url) {}
+ url_(url),
+ is_dark_mode_enabled_(is_dark_mode_enabled) {}
FloatSize SVGImage::DrawInfo::CalculateResidualScale() const {
return FloatSize(rounded_container_size_.Width() / container_size_.Width(),
@@ -397,7 +399,7 @@ void SVGImage::DrawForContainer(const DrawInfo& draw_info,
}
PaintImage SVGImage::PaintImageForCurrentFrame() {
- const DrawInfo draw_info(FloatSize(intrinsic_size_), 1, NullURL());
+ const DrawInfo draw_info(FloatSize(intrinsic_size_), 1, NullURL(), false);
auto builder = CreatePaintImageBuilder();
PopulatePaintRecordForCurrentFrameForContainer(draw_info, builder);
return builder.TakePaintImage();
@@ -405,23 +407,20 @@ PaintImage SVGImage::PaintImageForCurrentFrame() {
void SVGImage::DrawPatternForContainer(const DrawInfo& draw_info,
GraphicsContext& context,
- const FloatRect& src_rect,
- const FloatSize& tile_scale,
- const FloatPoint& phase,
- SkBlendMode composite_op,
+ const cc::PaintFlags& base_flags,
const FloatRect& dst_rect,
- const FloatSize& repeat_spacing) {
+ const ImageTilingInfo& tiling_info) {
// Tile adjusted for scaling/stretch.
- FloatRect tile(src_rect);
- tile.Scale(tile_scale.Width(), tile_scale.Height());
+ FloatRect tile(tiling_info.image_rect);
+ tile.Scale(tiling_info.scale.Width(), tiling_info.scale.Height());
// Expand the tile to account for repeat spacing.
FloatRect spaced_tile(tile);
- spaced_tile.Expand(FloatSize(repeat_spacing));
+ spaced_tile.Expand(tiling_info.spacing);
SkMatrix pattern_transform;
- pattern_transform.setTranslate(phase.X() + spaced_tile.X(),
- phase.Y() + spaced_tile.Y());
+ pattern_transform.setTranslate(tiling_info.phase.X() + spaced_tile.X(),
+ tiling_info.phase.Y() + spaced_tile.Y());
PaintRecordBuilder builder(context);
{
@@ -429,24 +428,25 @@ void SVGImage::DrawPatternForContainer(const DrawInfo& draw_info,
DisplayItem::Type::kSVGImage);
// When generating an expanded tile, make sure we don't draw into the
// spacing area.
- if (tile != spaced_tile)
+ if (!tiling_info.spacing.IsZero())
builder.Context().Clip(tile);
DrawForContainer(draw_info, builder.Context().Canvas(), PaintFlags(), tile,
- src_rect);
+ tiling_info.image_rect);
}
- PaintFlags flags;
- flags.setShader(PaintShader::MakePaintRecord(
+ sk_sp<PaintShader> tile_shader = PaintShader::MakePaintRecord(
builder.EndRecording(), spaced_tile, SkTileMode::kRepeat,
- SkTileMode::kRepeat, &pattern_transform));
+ SkTileMode::kRepeat, &pattern_transform);
+
// 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.
- if (!flags.HasShader())
- flags.setColor(SK_ColorTRANSPARENT);
+ PaintFlags flags = base_flags;
+ flags.setColor(tile_shader ? SK_ColorBLACK : SK_ColorTRANSPARENT);
+ flags.setShader(std::move(tile_shader));
+ // Reset filter quality.
+ flags.setFilterQuality(cc::PaintFlags::FilterQuality::kNone);
- flags.setBlendMode(composite_op);
- flags.setColorFilter(sk_ref_sp(context.GetColorFilter()));
context.DrawRect(dst_rect, flags);
StartAnimation();
@@ -491,7 +491,7 @@ bool SVGImage::ApplyShaderInternal(const DrawInfo& draw_info,
}
bool SVGImage::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) {
- const DrawInfo draw_info(FloatSize(intrinsic_size_), 1, NullURL());
+ const DrawInfo draw_info(FloatSize(intrinsic_size_), 1, NullURL(), false);
return ApplyShaderInternal(draw_info, flags, local_matrix);
}
@@ -511,11 +511,11 @@ void SVGImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) {
- const DrawInfo draw_info(FloatSize(intrinsic_size_), 1, NullURL());
+ const DrawInfo draw_info(FloatSize(intrinsic_size_), 1, NullURL(),
+ draw_options.apply_dark_mode);
DrawInternal(draw_info, canvas, flags, dst_rect, src_rect);
}
@@ -527,11 +527,10 @@ sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(
// re-laying out the image.
ImageObserverDisabler disable_image_observer(this);
- const LayoutSize layout_container_size = draw_info.RoundedContainerSize();
if (LayoutSVGRoot* layout_root = LayoutRoot())
- layout_root->SetContainerSize(layout_container_size);
+ layout_root->SetContainerSize(RoundedLayoutSize(draw_info.ContainerSize()));
LocalFrameView* view = GetFrame()->View();
- const IntSize rounded_container_size = RoundedIntSize(layout_container_size);
+ const IntSize rounded_container_size = draw_info.RoundedContainerSize();
view->Resize(rounded_container_size);
page_->GetVisualViewport().SetSize(rounded_container_size);
@@ -547,6 +546,7 @@ sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(
FlushPendingTimelineRewind();
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ page_->GetSettings().SetForceDarkModeEnabled(draw_info.IsDarkModeEnabled());
view->UpdateAllLifecyclePhases(DocumentUpdateReason::kSVGImage);
return view->GetPaintRecord();
}
@@ -557,7 +557,9 @@ sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(
return nullptr;
view->UpdateAllLifecyclePhasesExceptPaint(DocumentUpdateReason::kSVGImage);
+ PaintController::CycleScope cycle_scope(*paint_controller_);
PaintRecordBuilder builder(*paint_controller_);
+ builder.Context().SetDarkModeEnabled(draw_info.IsDarkModeEnabled());
view->PaintOutsideOfLifecycle(builder.Context(), kGlobalPaintNormalPhase);
return builder.EndRecording();
}
@@ -701,7 +703,7 @@ void SVGImage::ServiceAnimations(
// directly without worrying about including PaintArtifactCompositor's
// analysis of whether animations should be composited.
frame->GetDocument()->GetDocumentAnimations().UpdateAnimations(
- DocumentLifecycle::kLayoutClean, nullptr);
+ DocumentLifecycle::kLayoutClean, nullptr, false);
}
void SVGImage::AdvanceAnimationForTesting() {
@@ -773,7 +775,7 @@ Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
TRACE_EVENT0("blink", "SVGImage::dataChanged");
// Don't do anything if is an empty image.
- if (!Data()->size())
+ if (!DataSize())
return kSizeAvailable;
if (!all_data_received)
@@ -854,12 +856,15 @@ Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
// SVG Images are transparent.
frame->View()->SetBaseBackgroundColor(Color::kTransparent);
- page_ = page;
-
TRACE_EVENT0("blink", "SVGImage::dataChanged::load");
frame->ForceSynchronousDocumentInstall("image/svg+xml", Data());
+ // Set up our Page reference after installing our document. This avoids
+ // tripping on a non-existing (null) Document if a GC is triggered during the
+ // set up and ends up collecting the last owner/observer of this image.
+ page_ = page;
+
// Intrinsic sizing relies on computed style (e.g. font-size and
// writing-mode).
frame->GetDocument()->UpdateStyleAndLayoutTree();
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 58096e62477..101e2cf1abd 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
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_GRAPHICS_SVG_IMAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_GRAPHICS_SVG_IMAGE_H_
-#include "base/macros.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
@@ -73,7 +72,7 @@ class CORE_EXPORT SVGImage final : public Image {
static bool IsInSVGImage(const Node*);
bool IsSVGImage() const override { return true; }
- IntSize Size() const override;
+ IntSize SizeWithConfig(SizeConfig) const override;
void CheckLoaded() const;
bool CurrentFrameHasSingleSecurityOrigin() const override;
@@ -142,29 +141,33 @@ class CORE_EXPORT SVGImage final : public Image {
STACK_ALLOCATED();
public:
- DrawInfo(const FloatSize& container_size, float zoom, const KURL& url);
+ DrawInfo(const FloatSize& container_size,
+ float zoom,
+ const KURL& url,
+ bool is_dark_mode_enabled);
FloatSize CalculateResidualScale() const;
float Zoom() const { return zoom_; }
const FloatSize& ContainerSize() const { return container_size_; }
- const LayoutSize& RoundedContainerSize() const {
+ const IntSize& RoundedContainerSize() const {
return rounded_container_size_;
}
const KURL& Url() const { return url_; }
+ bool IsDarkModeEnabled() const { return is_dark_mode_enabled_; }
private:
const FloatSize container_size_;
- const LayoutSize rounded_container_size_;
+ const IntSize rounded_container_size_;
const float zoom_;
const KURL& url_;
+ const bool is_dark_mode_enabled_;
};
void Draw(cc::PaintCanvas*,
const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
void DrawForContainer(const DrawInfo&,
@@ -174,12 +177,9 @@ class CORE_EXPORT SVGImage final : public Image {
const FloatRect& src_rect);
void DrawPatternForContainer(const DrawInfo&,
GraphicsContext&,
- const FloatRect& src_rect,
- const FloatSize& tile_scale,
- const FloatPoint& phase,
- SkBlendMode composite_op,
+ const cc::PaintFlags&,
const FloatRect& dst_rect,
- const FloatSize& repeat_spacing);
+ const ImageTilingInfo&);
void PopulatePaintRecordForCurrentFrameForContainer(const DrawInfo&,
PaintImageBuilder&);
@@ -258,11 +258,13 @@ class ImageObserverDisabler {
image_->SetImageObserverDisabled(true);
}
+ ImageObserverDisabler(const ImageObserverDisabler&) = delete;
+ ImageObserverDisabler& operator=(const ImageObserverDisabler&) = delete;
+
~ImageObserverDisabler() { image_->SetImageObserverDisabled(false); }
private:
Image* image_;
- DISALLOW_COPY_AND_ASSIGN(ImageObserverDisabler);
};
} // namespace blink
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 9814e891f26..0567b0d5f6b 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
@@ -18,16 +18,15 @@
*/
#include "third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
namespace blink {
-IntSize SVGImageForContainer::Size() const {
- // The image orientation is irrelevant because there is not concept of
- // orientation for SVG images.
- return RoundedIntSize(SizeAsFloat(kRespectImageOrientation));
+IntSize SVGImageForContainer::SizeWithConfig(SizeConfig config) const {
+ return RoundedIntSize(SizeWithConfigAsFloat(config));
}
-FloatSize SVGImageForContainer::SizeAsFloat(RespectImageOrientationEnum) const {
+FloatSize SVGImageForContainer::SizeWithConfigAsFloat(SizeConfig) const {
return container_size_.ScaledBy(zoom_);
}
@@ -35,35 +34,33 @@ void SVGImageForContainer::Draw(cc::PaintCanvas* canvas,
const cc::PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) {
- const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_);
+ const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_,
+ draw_options.apply_dark_mode);
image_->DrawForContainer(draw_info, canvas, flags, dst_rect, src_rect);
}
void SVGImageForContainer::DrawPattern(GraphicsContext& context,
- const FloatRect& src_rect,
- const FloatSize& scale,
- const FloatPoint& phase,
- SkBlendMode op,
+ const cc::PaintFlags& flags,
const FloatRect& dst_rect,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum) {
- const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_);
- image_->DrawPatternForContainer(draw_info, context, src_rect, scale, phase,
- op, dst_rect, repeat_spacing);
+ const ImageTilingInfo& tiling_info,
+ const ImageDrawOptions& draw_options) {
+ const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_,
+ draw_options.apply_dark_mode);
+ image_->DrawPatternForContainer(draw_info, context, flags, dst_rect,
+ tiling_info);
}
bool SVGImageForContainer::ApplyShader(cc::PaintFlags& flags,
const SkMatrix& local_matrix) {
- const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_);
+ const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_, false);
return image_->ApplyShaderForContainer(draw_info, flags, local_matrix);
}
PaintImage SVGImageForContainer::PaintImageForCurrentFrame() {
- const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_);
+ const SVGImage::DrawInfo draw_info(container_size_, zoom_, url_, false);
auto builder = CreatePaintImageBuilder();
image_->PopulatePaintRecordForCurrentFrameForContainer(draw_info, builder);
return builder.TakePaintImage();
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 a69c1243035..aeb02525f9a 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
@@ -69,8 +69,8 @@ class CORE_EXPORT SVGImageForContainer final : public Image {
image, container_size_without_zoom, zoom, url));
}
- IntSize Size() const override;
- FloatSize SizeAsFloat(RespectImageOrientationEnum) const override;
+ IntSize SizeWithConfig(SizeConfig) const override;
+ FloatSize SizeWithConfigAsFloat(SizeConfig) const override;
bool HasIntrinsicSize() const override { return image_->HasIntrinsicSize(); }
@@ -80,25 +80,23 @@ class CORE_EXPORT SVGImageForContainer final : public Image {
const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
// FIXME: Implement this to be less conservative.
bool CurrentFrameKnownToBeOpaque() override { return false; }
+ bool IsSVGImageForContainer() const override { return true; }
+
PaintImage PaintImageForCurrentFrame() override;
protected:
void DrawPattern(GraphicsContext&,
- const FloatRect&,
- const FloatSize&,
- const FloatPoint&,
- SkBlendMode,
- const FloatRect&,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum) override;
+ const cc::PaintFlags&,
+ const FloatRect& dest_rect,
+ const ImageTilingInfo&,
+ const ImageDrawOptions& draw_options) override;
private:
SVGImageForContainer(SVGImage* image,
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 3cd32995018..b4f9cd0fe22 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
@@ -60,9 +60,10 @@ class SVGImageTest : public testing::Test, private ScopedMockOverlayScrollbars {
SkiaPaintCanvas canvas(null_canvas.get());
PaintFlags flags;
FloatRect dummy_rect(0, 0, 100, 100);
- image->Draw(&canvas, flags, dummy_rect, dummy_rect, SkSamplingOptions(),
- kRespectImageOrientation, Image::kDoNotClampImageToSourceRect,
- Image::kSyncDecode);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
+ image->Draw(&canvas, flags, dummy_rect, dummy_rect, draw_options,
+ Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
}
private:
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 56847e9e1f0..cc5a5b836a3 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
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_PROPERTIES_SVG_ANIMATED_PROPERTY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_PROPERTIES_SVG_ANIMATED_PROPERTY_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/svg/properties/svg_property_info.h"
@@ -47,6 +46,8 @@ class SVGElement;
class SVGAnimatedPropertyBase : public GarbageCollectedMixin {
public:
+ SVGAnimatedPropertyBase(const SVGAnimatedPropertyBase&) = delete;
+ SVGAnimatedPropertyBase& operator=(const SVGAnimatedPropertyBase&) = delete;
virtual ~SVGAnimatedPropertyBase();
virtual const SVGPropertyBase& BaseValueBase() const = 0;
@@ -108,7 +109,6 @@ class SVGAnimatedPropertyBase : public GarbageCollectedMixin {
unsigned base_value_needs_synchronization_ : 1;
Member<SVGElement> context_element_;
const QualifiedName& attribute_name_;
- DISALLOW_COPY_AND_ASSIGN(SVGAnimatedPropertyBase);
};
template <typename Property>
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_angle.cc b/chromium/third_party/blink/renderer/core/svg/svg_angle.cc
index d4711f30bd0..51bd3a912ab 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_angle.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_angle.cc
@@ -187,7 +187,7 @@ String SVGAngle::ValueAsString() const {
}
StringBuilder builder;
builder.AppendNumber(value_in_specified_units_);
- builder.Append(unit_string, strlen(unit_string));
+ builder.Append(unit_string, static_cast<unsigned>(strlen(unit_string)));
return builder.ToString();
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
index bb52b24eef1..e5a0ecfbc2f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
@@ -254,8 +254,7 @@ float SVGAnimateMotionElement::CalculateDistance(const String& from_string,
return -1;
if (!ParsePoint(to_string, to))
return -1;
- FloatSize diff = to - from;
- return sqrtf(diff.Width() * diff.Width() + diff.Height() * diff.Height());
+ return (to - from).DiagonalLength();
}
void SVGAnimateMotionElement::UpdateAnimationMode() {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_href.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_href.cc
index e194e73dd20..3b6b1644463 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_href.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_href.cc
@@ -14,8 +14,6 @@
namespace blink {
-class StringOrTrustedScriptURL;
-
void SVGAnimatedHref::Trace(Visitor* visitor) const {
visitor->Trace(xlink_href_);
SVGAnimatedString::Trace(visitor);
@@ -45,8 +43,6 @@ const SVGString* SVGAnimatedHref::CurrentValue() const {
return BackingString()->SVGAnimatedString::CurrentValue();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionStringOrTrustedScriptURL* SVGAnimatedHref::baseVal() {
UseCounter::Count(ContextElement()->GetDocument(),
WebFeature::kSVGHrefBaseVal);
@@ -60,24 +56,6 @@ void SVGAnimatedHref::setBaseVal(const V8UnionStringOrTrustedScriptURL* value,
BackingString()->SVGAnimatedString::setBaseVal(value, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void SVGAnimatedHref::baseVal(
- StringOrTrustedScriptURL& string_or_trusted_script_url) {
- UseCounter::Count(ContextElement()->GetDocument(),
- WebFeature::kSVGHrefBaseVal);
- BackingString()->SVGAnimatedString::baseVal(string_or_trusted_script_url);
-}
-
-void SVGAnimatedHref::setBaseVal(const StringOrTrustedScriptURL& value,
- ExceptionState& exception_state) {
- UseCounter::Count(ContextElement()->GetDocument(),
- WebFeature::kSVGHrefBaseVal);
- return BackingString()->SVGAnimatedString::setBaseVal(value, exception_state);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
String SVGAnimatedHref::animVal() {
UseCounter::Count(ContextElement()->GetDocument(),
WebFeature::kSVGHrefAnimVal);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_href.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_href.h
index 3f53e465d1e..a8987320398 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_href.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_href.h
@@ -9,8 +9,6 @@
namespace blink {
-class StringOrTrustedScriptURL;
-
// This is an "access wrapper" for the 'href' attribute. The object
// itself holds the value for 'href' in the null/default NS and wraps
// one for 'href' in the XLink NS. Both objects are added to an
@@ -26,14 +24,9 @@ class SVGAnimatedHref final : public SVGAnimatedString {
SVGString* CurrentValue();
const SVGString* CurrentValue() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionStringOrTrustedScriptURL* baseVal() override;
void setBaseVal(const V8UnionStringOrTrustedScriptURL* value,
ExceptionState& exception_state) override;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void baseVal(StringOrTrustedScriptURL&) override;
- void setBaseVal(const StringOrTrustedScriptURL&, ExceptionState&) override;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String animVal() override;
bool IsSpecified() const {
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 e52ad811f33..e3450e19cd6 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
@@ -57,6 +57,16 @@ class SVGAnimatedLength : public ScriptWrappable,
SVGParsingError AttributeChanged(const String&) override;
+ // TODO(fs): This doesn't handle calc expressions. For that, we'd probably
+ // need to rewrap the CSSMathExpressionNode with a kValueRangeNonNegative
+ // range specification.
+ const CSSValue* NonNegativeCssValue() const {
+ if (CurrentValue()->IsNegativeNumericLiteral()) {
+ return nullptr;
+ }
+ return &CurrentValue()->AsCSSPrimitiveValue();
+ }
+
const CSSValue& CssValue() const {
return CurrentValue()->AsCSSPrimitiveValue();
}
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 b3b1e5f88d0..0b69f3a4cec 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
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/svg/svg_animated_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script_url.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedscripturl.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
@@ -12,8 +11,6 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionStringOrTrustedScriptURL* SVGAnimatedString::baseVal() {
return MakeGarbageCollected<V8UnionStringOrTrustedScriptURL>(
SVGAnimatedProperty<SVGString>::baseVal());
@@ -42,36 +39,6 @@ void SVGAnimatedString::setBaseVal(const V8UnionStringOrTrustedScriptURL* value,
SVGAnimatedProperty<SVGString>::setBaseVal(string, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void SVGAnimatedString::setBaseVal(
- const StringOrTrustedScriptURL& string_or_trusted_script_url,
- ExceptionState& exception_state) {
- String value;
- // See:
- // https://w3c.github.io/webappsec-trusted-types/dist/spec/#integration-with-svg
- if (string_or_trusted_script_url.IsTrustedScriptURL()) {
- value = string_or_trusted_script_url.GetAsTrustedScriptURL()->toString();
- } else {
- value = string_or_trusted_script_url.GetAsString();
- if (ContextElement()->IsScriptElement()) {
- value = TrustedTypesCheckForScriptURL(
- value, ContextElement()->GetExecutionContext(), exception_state);
- if (exception_state.HadException())
- return;
- }
- }
- SVGAnimatedProperty<SVGString>::setBaseVal(value, exception_state);
-}
-
-void SVGAnimatedString::baseVal(
- StringOrTrustedScriptURL& string_or_trusted_script_url) {
- string_or_trusted_script_url.SetString(
- SVGAnimatedProperty<SVGString>::baseVal());
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
String SVGAnimatedString::animVal() {
return SVGAnimatedProperty<SVGString>::animVal();
}
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 c7a85cccbd7..be7ed2e8a84 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
@@ -38,7 +38,6 @@
namespace blink {
-class StringOrTrustedScriptURL;
class V8UnionStringOrTrustedScriptURL;
class SVGAnimatedString : public ScriptWrappable,
@@ -52,14 +51,9 @@ class SVGAnimatedString : public ScriptWrappable,
attribute_name,
MakeGarbageCollected<SVGString>()) {}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual V8UnionStringOrTrustedScriptURL* baseVal();
virtual void setBaseVal(const V8UnionStringOrTrustedScriptURL* value,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void setBaseVal(const StringOrTrustedScriptURL&, ExceptionState&);
- virtual void baseVal(StringOrTrustedScriptURL&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual String animVal();
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 8f5c52b6c3d..a1038570ad7 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
@@ -384,9 +384,8 @@ void SVGAnimationElement::CalculateKeyTimesForCalcModePaced() {
total_distance += distance;
calculated_key_times.push_back(distance);
}
- if (!total_distance) {
+ if (!std::isfinite(total_distance) || !total_distance)
return;
- }
// Normalize.
for (unsigned n = 1; n < calculated_key_times.size() - 1; ++n) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_document_extensions.h b/chromium/third_party/blink/renderer/core/svg/svg_document_extensions.h
index 004ee2b2e62..d8f3c50ca98 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_document_extensions.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_document_extensions.h
@@ -22,7 +22,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_DOCUMENT_EXTENSIONS_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -40,6 +39,8 @@ class CORE_EXPORT SVGDocumentExtensions final
: public GarbageCollected<SVGDocumentExtensions> {
public:
explicit SVGDocumentExtensions(Document*);
+ SVGDocumentExtensions(const SVGDocumentExtensions&) = delete;
+ SVGDocumentExtensions& operator=(const SVGDocumentExtensions&) = delete;
~SVGDocumentExtensions();
void AddTimeContainer(SVGSVGElement*);
@@ -85,7 +86,6 @@ class CORE_EXPORT SVGDocumentExtensions final
#if DCHECK_IS_ON()
bool in_relative_length_svg_roots_invalidation_ = false;
#endif
- DISALLOW_COPY_AND_ASSIGN(SVGDocumentExtensions);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_element.cc
index 7a89f8ab06f..532d9118d6d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element.cc
@@ -25,7 +25,7 @@
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "base/auto_reset.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/effect_stack.h"
@@ -460,7 +460,10 @@ CSSPropertyID SVGElement::CssPropertyIdForSVGAttributeName(
}
}
- return property_name_to_id_map->at(attr_name.LocalName().Impl());
+ auto it = property_name_to_id_map->find(attr_name.LocalName().Impl());
+ if (it == property_name_to_id_map->end())
+ return CSSPropertyID::kInvalid;
+ return it->value;
}
void SVGElement::UpdateRelativeLengthsInformation(
@@ -746,7 +749,10 @@ AnimatedPropertyType SVGElement::AnimatedPropertyTypeForCSSAttribute(
for (size_t i = 0; i < base::size(attr_to_types); i++)
css_property_map.Set(attr_to_types[i].attr, attr_to_types[i].prop_type);
}
- return css_property_map.at(attribute_name);
+ auto it = css_property_map.find(attribute_name);
+ if (it == css_property_map.end())
+ return kAnimatedUnknown;
+ return it->value;
}
void SVGElement::AddToPropertyMap(SVGAnimatedPropertyBase* property) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_element.h b/chromium/third_party/blink/renderer/core/svg/svg_element.h
index 2171cb9aed5..dfc9919e22a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element.h
@@ -23,7 +23,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_ELEMENT_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.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/dom/events/simulated_click_options.h"
@@ -201,11 +200,12 @@ class CORE_EXPORT SVGElement : public Element {
public:
InvalidationGuard(SVGElement* element) : element_(element) {}
+ InvalidationGuard(const InvalidationGuard&) = delete;
+ InvalidationGuard& operator=(const InvalidationGuard&) = delete;
~InvalidationGuard() { element_->InvalidateInstances(); }
private:
SVGElement* element_;
- DISALLOW_COPY_AND_ASSIGN(InvalidationGuard);
};
class InstanceUpdateBlocker {
@@ -213,11 +213,12 @@ class CORE_EXPORT SVGElement : public Element {
public:
InstanceUpdateBlocker(SVGElement* target_element);
+ InstanceUpdateBlocker(const InstanceUpdateBlocker&) = delete;
+ InstanceUpdateBlocker& operator=(const InstanceUpdateBlocker&) = delete;
~InstanceUpdateBlocker();
private:
SVGElement* target_element_;
- DISALLOW_COPY_AND_ASSIGN(InstanceUpdateBlocker);
};
void InvalidateInstances();
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h b/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h
index d48de268676..f06f79e9637 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h
@@ -20,7 +20,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_ELEMENT_RARE_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_ELEMENT_RARE_DATA_H_
-#include "base/macros.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/heap/handle.h"
@@ -39,6 +38,8 @@ class SVGElementRareData final : public GarbageCollected<SVGElementRareData> {
instances_updates_blocked_(false),
needs_override_computed_style_update_(false),
web_animated_attributes_dirty_(false) {}
+ SVGElementRareData(const SVGElementRareData&) = delete;
+ SVGElementRareData& operator=(const SVGElementRareData&) = delete;
SVGElementSet& OutgoingReferences() { return outgoing_references_; }
const SVGElementSet& OutgoingReferences() const {
@@ -116,7 +117,6 @@ class SVGElementRareData final : public GarbageCollected<SVGElementRareData> {
scoped_refptr<ComputedStyle> override_computed_style_;
// Used by <animateMotion>
AffineTransform animate_motion_transform_;
- DISALLOW_COPY_AND_ASSIGN(SVGElementRareData);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_enumeration_map.h b/chromium/third_party/blink/renderer/core/svg/svg_enumeration_map.h
index 9bc228a8e48..5a427240a53 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_enumeration_map.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_enumeration_map.h
@@ -7,6 +7,7 @@
#include "base/check.h"
#include "base/check_op.h"
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
@@ -20,7 +21,7 @@ namespace blink {
// |max_exposed_value| should be set to the last old value. From this also
// follow that the new values should sort last - after the |max_exposed_value|.
// (This is currently always the case in the spec too.)
-class SVGEnumerationMap {
+class CORE_EXPORT SVGEnumerationMap {
public:
struct Entry {
const uint16_t value;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc
index 993e66996f8..12d4fed52ee 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc
@@ -37,7 +37,8 @@
namespace blink {
template <>
-const SVGEnumerationMap& GetEnumerationMap<FEConvolveMatrix::EdgeModeType>() {
+CORE_EXPORT const SVGEnumerationMap&
+GetEnumerationMap<FEConvolveMatrix::EdgeModeType>() {
static const SVGEnumerationMap::Entry enum_items[] = {
{FEConvolveMatrix::EDGEMODE_DUPLICATE, "duplicate"},
{FEConvolveMatrix::EDGEMODE_WRAP, "wrap"},
@@ -179,8 +180,8 @@ float SVGFEConvolveMatrixElement::ComputeDivisor() const {
return divisor_->CurrentValue()->Value();
float divisor_value = 0;
SVGNumberList* kernel_matrix = kernel_matrix_->CurrentValue();
- size_t kernel_matrix_size = kernel_matrix->length();
- for (size_t i = 0; i < kernel_matrix_size; ++i)
+ uint32_t kernel_matrix_size = kernel_matrix->length();
+ for (uint32_t i = 0; i < kernel_matrix_size; ++i)
divisor_value += kernel_matrix->at(i)->Value();
return divisor_value ? divisor_value : 1;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_length_context.cc b/chromium/third_party/blink/renderer/core/svg/svg_length_context.cc
index b4d12cdf9e9..3b7f1bf40de 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_length_context.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_length_context.cc
@@ -484,8 +484,10 @@ float SVGLengthContext::ResolveValue(const CSSPrimitiveValue& primitive_value,
if (!root_style)
return 0;
+ // TOOD(crbug.com/1223030): Handle container relative units.
CSSToLengthConversionData conversion_data = CSSToLengthConversionData(
- style, root_style, context_->GetDocument().GetLayoutView(), 1.0f);
+ style, root_style, context_->GetDocument().GetLayoutView(),
+ /* nearest_container */ nullptr, 1.0f);
Length length = primitive_value.ConvertToLength(conversion_data);
return ValueForLength(length, 1.0f, mode);
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_blender.cc b/chromium/third_party/blink/renderer/core/svg/svg_path_blender.cc
index feeb3608ae4..26da2851da8 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_blender.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_blender.cc
@@ -22,7 +22,7 @@
#include "third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h"
#include "third_party/blink/renderer/core/svg/svg_path_consumer.h"
#include "third_party/blink/renderer/core/svg/svg_path_data.h"
-#include "third_party/blink/renderer/platform/animation/animation_utilities.h"
+#include "third_party/blink/renderer/platform/geometry/blend.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_blender.h b/chromium/third_party/blink/renderer/core/svg/svg_path_blender.h
index 62e0f0defdc..7f18acbda82 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_blender.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_blender.h
@@ -20,7 +20,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_BLENDER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_BLENDER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -35,6 +34,8 @@ class SVGPathBlender final {
SVGPathBlender(SVGPathByteStreamSource* from_source,
SVGPathByteStreamSource* to_source,
SVGPathConsumer*);
+ SVGPathBlender(const SVGPathBlender&) = delete;
+ SVGPathBlender& operator=(const SVGPathBlender&) = delete;
bool AddAnimatedPath(unsigned repeat_count);
bool BlendAnimatedPath(float);
@@ -46,7 +47,6 @@ class SVGPathBlender final {
SVGPathByteStreamSource* from_source_;
SVGPathByteStreamSource* to_source_;
SVGPathConsumer* consumer_;
- DISALLOW_COPY_AND_ASSIGN(SVGPathBlender);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h b/chromium/third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h
index 3f79ca5a3cf..211fe17d9a8 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h
@@ -20,7 +20,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_BYTE_STREAM_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_BYTE_STREAM_SOURCE_H_
-#include "base/macros.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/core/svg/svg_path_byte_stream.h"
#include "third_party/blink/renderer/core/svg/svg_path_data.h"
@@ -34,6 +33,8 @@ class SVGPathByteStreamSource {
public:
explicit SVGPathByteStreamSource(const SVGPathByteStream& stream)
: stream_current_(stream.begin()), stream_end_(stream.end()) {}
+ SVGPathByteStreamSource(const SVGPathByteStreamSource&) = delete;
+ SVGPathByteStreamSource& operator=(const SVGPathByteStreamSource&) = delete;
bool HasMoreData() const { return stream_current_ < stream_end_; }
PathSegmentData ParseSegment();
@@ -63,7 +64,6 @@ class SVGPathByteStreamSource {
SVGPathByteStream::DataIterator stream_current_;
SVGPathByteStream::DataIterator stream_end_;
- DISALLOW_COPY_AND_ASSIGN(SVGPathByteStreamSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_consumer.h b/chromium/third_party/blink/renderer/core/svg/svg_path_consumer.h
index 4d1f6cef8be..1decb5b0a66 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_consumer.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_consumer.h
@@ -24,7 +24,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_CONSUMER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_CONSUMER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -37,12 +36,11 @@ class CORE_EXPORT SVGPathConsumer {
public:
SVGPathConsumer() = default;
+ SVGPathConsumer(const SVGPathConsumer&) = delete;
+ SVGPathConsumer& operator=(const SVGPathConsumer&) = delete;
virtual ~SVGPathConsumer() = default;
virtual void EmitSegment(const PathSegmentData&) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SVGPathConsumer);
};
} // namespace blink
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 2d7aa59da7f..2d0f08f8c3a 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
@@ -81,6 +81,7 @@ SVGPointTearOff* SVGPathElement::getPointAtLength(
GetDocument().UpdateStyleAndLayoutForNode(this,
DocumentUpdateReason::kJavaScript);
+ EnsureComputedStyle();
const SVGPathByteStream& byte_stream = PathByteStream();
if (byte_stream.IsEmpty()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_string_source.h b/chromium/third_party/blink/renderer/core/svg/svg_path_string_source.h
index 7b9cc28f994..5ff24a73fa0 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_string_source.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_string_source.h
@@ -21,7 +21,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_STRING_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_PATH_STRING_SOURCE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/svg/svg_parsing_error.h"
#include "third_party/blink/renderer/core/svg/svg_path_data.h"
@@ -34,6 +33,8 @@ class CORE_EXPORT SVGPathStringSource {
public:
explicit SVGPathStringSource(StringView);
+ SVGPathStringSource(const SVGPathStringSource&) = delete;
+ SVGPathStringSource& operator=(const SVGPathStringSource&) = delete;
bool HasMoreData() const {
if (is_8bit_source_)
@@ -64,8 +65,6 @@ class CORE_EXPORT SVGPathStringSource {
SVGPathSegType previous_command_;
SVGParsingError error_;
StringView source_;
-
- DISALLOW_COPY_AND_ASSIGN(SVGPathStringSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_resource.h b/chromium/third_party/blink/renderer/core/svg/svg_resource.h
index 7f591d7ce8c..4b897df206f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_resource.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_resource.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_RESOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_RESOURCE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -62,6 +61,8 @@ class TreeScope;
//
class SVGResource : public GarbageCollected<SVGResource> {
public:
+ SVGResource(const SVGResource&) = delete;
+ SVGResource& operator=(const SVGResource&) = delete;
virtual ~SVGResource();
virtual void Load(Document&) {}
@@ -103,9 +104,6 @@ class SVGResource : public GarbageCollected<SVGResource> {
CycleState cached_cycle_check = kNeedCheck;
};
mutable HeapHashMap<Member<SVGResourceClient>, ClientEntry> clients_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SVGResource);
};
// Local resource reference (see SVGResource.)
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 e47f4d0dcd1..c0f0688986d 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
@@ -20,7 +20,6 @@
#include "third_party/blink/renderer/core/svg/svg_script_element.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/js_event_handler_for_content_attribute.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlscriptelement_svgscriptelement.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
@@ -194,19 +193,15 @@ const AttrNameToTrustedType& SVGScriptElement::GetCheckedAttributeTypes()
return attribute_map;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8HTMLOrSVGScriptElement* SVGScriptElement::AsV8HTMLOrSVGScriptElement() {
if (IsInShadowTree())
return nullptr;
return MakeGarbageCollected<V8HTMLOrSVGScriptElement>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void SVGScriptElement::SetScriptElementForBinding(
- HTMLScriptElementOrSVGScriptElement& element) {
- if (!IsInShadowTree())
- element.SetSVGScriptElement(this);
+
+DOMNodeId SVGScriptElement::GetDOMNodeId() {
+ return DOMNodeIds::IdForNode(this);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void SVGScriptElement::Trace(Visitor* visitor) const {
visitor->Trace(loader_);
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 d57d9928691..5c1727f5b16 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
@@ -52,12 +52,8 @@ class SVGScriptElement final : public SVGElement,
const AttrNameToTrustedType& GetCheckedAttributeTypes() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8HTMLOrSVGScriptElement* AsV8HTMLOrSVGScriptElement() override;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetScriptElementForBinding(
- HTMLScriptElementOrSVGScriptElement&) override;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ DOMNodeId GetDOMNodeId() override;
void Trace(Visitor*) const 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 a2ea0cd2f48..53bc49ce7bb 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
@@ -36,6 +36,7 @@
#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_object.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
@@ -220,12 +221,19 @@ void SVGSVGElement::CollectStyleForPresentationAttribute(
y_->CssValue());
} else if (IsOutermostSVGSVGElement() &&
(property == width_ || property == height_)) {
+ // SVG allows negative numbers for these attributes but CSS doesn't allow
+ // negative <length> values for the corresponding CSS properties. So remove
+ // negative values here.
if (property == width_) {
- AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
- width_->CssValue());
+ if (const CSSValue* width = width_->NonNegativeCssValue()) {
+ AddPropertyToPresentationAttributeStyle(
+ style, property->CssPropertyId(), *width);
+ }
} else if (property == height_) {
- AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
- height_->CssValue());
+ if (const CSSValue* height = height_->NonNegativeCssValue()) {
+ AddPropertyToPresentationAttributeStyle(
+ style, property->CssPropertyId(), *height);
+ }
}
} else {
SVGGraphicsElement::CollectStyleForPresentationAttribute(name, value,
@@ -468,7 +476,7 @@ AffineTransform SVGSVGElement::LocalCoordinateSpaceTransform(
TransformationMatrix matrix;
// Adjust for the zoom level factored into CSS coordinates (WK bug
// #96361).
- matrix.Scale(1.0 / layout_object->StyleRef().EffectiveZoom());
+ matrix.Scale(1.0 / layout_object->View()->StyleRef().EffectiveZoom());
// Apply transforms from our ancestor coordinate space, including any
// non-SVG ancestor transforms.
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 c50de2b8681..64d3e14cc5d 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
@@ -26,6 +26,9 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.h"
+#include "third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_query.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/svg_text_query.h"
#include "third_party/blink/renderer/core/svg/svg_animated_length.h"
#include "third_party/blink/renderer/core/svg/svg_enumeration_map.h"
@@ -40,6 +43,15 @@
namespace blink {
+namespace {
+
+bool IsNGTextOrInline(const LayoutObject* object) {
+ return object && (object->IsNGSVGText() ||
+ object->IsInLayoutNGInlineFormattingContext());
+}
+
+} // namespace
+
template <>
const SVGEnumerationMap& GetEnumerationMap<SVGLengthAdjustType>() {
static const SVGEnumerationMap::Entry enum_items[] = {
@@ -95,13 +107,21 @@ void SVGTextContentElement::Trace(Visitor* visitor) const {
unsigned SVGTextContentElement::getNumberOfChars() {
GetDocument().UpdateStyleAndLayoutForNode(this,
DocumentUpdateReason::kJavaScript);
- return SVGTextQuery(GetLayoutObject()).NumberOfCharacters();
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object))
+ return NGSvgTextQuery(*layout_object).NumberOfCharacters();
+ return SVGTextQuery(layout_object).NumberOfCharacters();
}
float SVGTextContentElement::getComputedTextLength() {
GetDocument().UpdateStyleAndLayoutForNode(this,
DocumentUpdateReason::kJavaScript);
- return SVGTextQuery(GetLayoutObject()).TextLength();
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object)) {
+ NGSvgTextQuery query(*layout_object);
+ return query.SubStringLength(0, query.NumberOfCharacters());
+ }
+ return SVGTextQuery(layout_object).TextLength();
}
float SVGTextContentElement::getSubStringLength(
@@ -123,7 +143,10 @@ float SVGTextContentElement::getSubStringLength(
if (nchars > number_of_chars - charnum)
nchars = number_of_chars - charnum;
- return SVGTextQuery(GetLayoutObject()).SubStringLength(charnum, nchars);
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object))
+ return NGSvgTextQuery(*layout_object).SubStringLength(charnum, nchars);
+ return SVGTextQuery(layout_object).SubStringLength(charnum, nchars);
}
SVGPointTearOff* SVGTextContentElement::getStartPositionOfChar(
@@ -140,8 +163,13 @@ SVGPointTearOff* SVGTextContentElement::getStartPositionOfChar(
return nullptr;
}
- FloatPoint point =
- SVGTextQuery(GetLayoutObject()).StartPositionOfCharacter(charnum);
+ FloatPoint point;
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object)) {
+ point = NGSvgTextQuery(*layout_object).StartPositionOfCharacter(charnum);
+ } else {
+ point = SVGTextQuery(layout_object).StartPositionOfCharacter(charnum);
+ }
return SVGPointTearOff::CreateDetached(point);
}
@@ -159,8 +187,13 @@ SVGPointTearOff* SVGTextContentElement::getEndPositionOfChar(
return nullptr;
}
- FloatPoint point =
- SVGTextQuery(GetLayoutObject()).EndPositionOfCharacter(charnum);
+ FloatPoint point;
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object)) {
+ point = NGSvgTextQuery(*layout_object).EndPositionOfCharacter(charnum);
+ } else {
+ point = SVGTextQuery(layout_object).EndPositionOfCharacter(charnum);
+ }
return SVGPointTearOff::CreateDetached(point);
}
@@ -178,7 +211,13 @@ SVGRectTearOff* SVGTextContentElement::getExtentOfChar(
return nullptr;
}
- FloatRect rect = SVGTextQuery(GetLayoutObject()).ExtentOfCharacter(charnum);
+ FloatRect rect;
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object)) {
+ rect = NGSvgTextQuery(*layout_object).ExtentOfCharacter(charnum);
+ } else {
+ rect = SVGTextQuery(layout_object).ExtentOfCharacter(charnum);
+ }
return SVGRectTearOff::CreateDetached(rect);
}
@@ -196,7 +235,10 @@ float SVGTextContentElement::getRotationOfChar(
return 0.0f;
}
- return SVGTextQuery(GetLayoutObject()).RotationOfCharacter(charnum);
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object))
+ return NGSvgTextQuery(*layout_object).RotationOfCharacter(charnum);
+ return SVGTextQuery(layout_object).RotationOfCharacter(charnum);
}
int SVGTextContentElement::getCharNumAtPosition(
@@ -204,7 +246,12 @@ int SVGTextContentElement::getCharNumAtPosition(
ExceptionState& exception_state) {
GetDocument().UpdateStyleAndLayoutForNode(this,
DocumentUpdateReason::kJavaScript);
- return SVGTextQuery(GetLayoutObject())
+ auto* layout_object = GetLayoutObject();
+ if (IsNGTextOrInline(layout_object)) {
+ return NGSvgTextQuery(*layout_object)
+ .CharacterNumberAtPosition(point->Target()->Value());
+ }
+ return SVGTextQuery(layout_object)
.CharacterNumberAtPosition(point->Target()->Value());
}
@@ -268,8 +315,12 @@ void SVGTextContentElement::SvgAttributeChanged(
attr_name == xml_names::kSpaceAttr) {
SVGElement::InvalidationGuard invalidation_guard(this);
- if (LayoutObject* layout_object = GetLayoutObject())
+ if (LayoutObject* layout_object = GetLayoutObject()) {
+ if (auto* ng_text = DynamicTo<LayoutNGSVGText>(
+ LayoutSVGText::LocateLayoutSVGTextAncestor(layout_object)))
+ ng_text->SetNeedsPositioningValuesUpdate();
MarkForLayoutAndParentResourceInvalidation(*layout_object);
+ }
return;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_transform.cc b/chromium/third_party/blink/renderer/core/svg/svg_transform.cc
index f89dadb83ee..edaaed45f98 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_transform.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_transform.cc
@@ -20,7 +20,7 @@
#include "third_party/blink/renderer/core/svg/svg_transform.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/geometry/float_size.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/core/svg/svg_transform_list.cc b/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc
index 5e60c4ee7f7..722176b90e5 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc
@@ -23,7 +23,7 @@
#include "third_party/blink/renderer/core/svg/svg_transform_list.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc
index 5feb50931ff..547131c295f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc
@@ -27,7 +27,10 @@ LocalSVGResource* SVGTreeScopeResources::ExistingResourceForId(
const AtomicString& id) const {
if (id.IsEmpty())
return nullptr;
- return resources_.at(id);
+ auto it = resources_.find(id);
+ if (it == resources_.end())
+ return nullptr;
+ return it->value;
}
void SVGTreeScopeResources::ProcessCustomWeakness(const LivenessBroker& info) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h
index 2267e752687..568b448fd5d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h
@@ -22,6 +22,8 @@ class SVGTreeScopeResources final
: public GarbageCollected<SVGTreeScopeResources> {
public:
explicit SVGTreeScopeResources(TreeScope*);
+ SVGTreeScopeResources(const SVGTreeScopeResources&) = delete;
+ SVGTreeScopeResources& operator=(const SVGTreeScopeResources&) = delete;
LocalSVGResource* ResourceForId(const AtomicString& id);
LocalSVGResource* ExistingResourceForId(const AtomicString& id) const;
@@ -33,8 +35,6 @@ class SVGTreeScopeResources final
HeapHashMap<AtomicString, WeakMember<LocalSVGResource>> resources_;
Member<TreeScope> tree_scope_;
-
- DISALLOW_COPY_AND_ASSIGN(SVGTreeScopeResources);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc
index 3f15628f159..f21eead32fd 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc
@@ -88,7 +88,7 @@ SVGUseElement::SVGUseElement(Document& document)
AddToPropertyMap(width_);
AddToPropertyMap(height_);
- AttachShadowRootInternal(ShadowRootType::kClosed);
+ CreateUserAgentShadowRoot();
}
SVGUseElement::~SVGUseElement() = default;
@@ -411,7 +411,8 @@ static void MoveChildrenToReplacementElement(ContainerNode& source_root,
}
SVGElement* SVGUseElement::CreateInstanceTree(SVGElement& target_root) const {
- SVGElement* instance_root = &To<SVGElement>(target_root.CloneWithChildren());
+ SVGElement* instance_root =
+ &To<SVGElement>(target_root.CloneWithChildren(CloneChildrenFlag::kClone));
if (IsA<SVGSymbolElement>(target_root)) {
// Spec: The referenced 'symbol' and its contents are deep-cloned into
// the generated tree, with the exception that the 'symbol' is replaced
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_use_element.h b/chromium/third_party/blink/renderer/core/svg/svg_use_element.h
index 383b1abf5b8..19013ee0029 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_use_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_use_element.h
@@ -92,8 +92,8 @@ class SVGUseElement final : public SVGGraphicsElement,
bool SelfHasRelativeLengths() const override;
ShadowRoot& UseShadowRoot() const {
- CHECK(ClosedShadowRoot());
- return *ClosedShadowRoot();
+ CHECK(UserAgentShadowRoot());
+ return *UserAgentShadowRoot();
}
Element* ResolveTargetElement();
diff --git a/chromium/third_party/blink/renderer/core/testing/data/iframe-background-attachment-fixed-inner.html b/chromium/third_party/blink/renderer/core/testing/data/iframe-background-attachment-fixed-inner.html
index 5dc4b2dd376..8ff944913f1 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/iframe-background-attachment-fixed-inner.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/iframe-background-attachment-fixed-inner.html
@@ -6,4 +6,4 @@
}
</style>
-<div id="scrollable" style="will-change:transform; height: 2000px;" class="background-attachment-fixed" />
+<div id="content" style="will-change:transform; height: 2000px;" class="background-attachment-fixed" />
diff --git a/chromium/third_party/blink/renderer/core/testing/data/trivial-scroller.html b/chromium/third_party/blink/renderer/core/testing/data/trivial-scroller.html
deleted file mode 100644
index 7bf668ee23f..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/trivial-scroller.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-#scroller {
- width: 100px;
- height: 100px;
- overflow: scroll;
- will-change: transform;
-}
-.scrolled {
- background: blue;
- width: 50px;
- height: 180px;
-}
-</style>
-<div id="scroller">
- <div class="scrolled"></div>
-</div>
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 9c3684b94ce..c5f953ba1c8 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
@@ -4,264 +4,167 @@
#include "third_party/blink/renderer/core/testing/dictionary_test.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_iterator.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_internal_dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_internal_dictionary_derived.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_internal_dictionary_derived_derived.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
-DictionaryTest::DictionaryTest() : required_boolean_member_(false) {}
+DictionaryTest::DictionaryTest() = default;
DictionaryTest::~DictionaryTest() = default;
-void DictionaryTest::set(const InternalDictionary* testing_dictionary) {
- Reset();
- if (testing_dictionary->hasLongMember())
- long_member_ = testing_dictionary->longMember();
- if (testing_dictionary->hasLongMemberWithClamp())
- long_member_with_clamp_ = testing_dictionary->longMemberWithClamp();
- if (testing_dictionary->hasLongMemberWithEnforceRange()) {
- long_member_with_enforce_range_ =
- testing_dictionary->longMemberWithEnforceRange();
+#define SAVE_DICT_MEMBER(camel, capital) \
+ if (input_dictionary->has##capital()) { \
+ dictionary_->set##capital(input_dictionary->camel()); \
+ } else { \
}
- long_member_with_default_ = testing_dictionary->longMemberWithDefault();
- if (testing_dictionary->hasLongOrNullMember())
- long_or_null_member_ = testing_dictionary->longOrNullMember();
- if (testing_dictionary->hasLongOrNullMemberWithDefault()) {
- long_or_null_member_with_default_ =
- testing_dictionary->longOrNullMemberWithDefault();
- }
- if (testing_dictionary->hasBooleanMember())
- boolean_member_ = testing_dictionary->booleanMember();
- if (testing_dictionary->hasDoubleMember())
- double_member_ = testing_dictionary->doubleMember();
- if (testing_dictionary->hasUnrestrictedDoubleMember()) {
- unrestricted_double_member_ =
- testing_dictionary->unrestrictedDoubleMember();
- }
- if (testing_dictionary->hasStringMember())
- string_member_ = testing_dictionary->stringMember();
- string_member_with_default_ = testing_dictionary->stringMemberWithDefault();
- if (testing_dictionary->hasByteStringMember())
- byte_string_member_ = testing_dictionary->byteStringMember();
- if (testing_dictionary->hasUsvStringMember())
- usv_string_member_ = testing_dictionary->usvStringMember();
- if (testing_dictionary->hasStringSequenceMember())
- string_sequence_member_ = testing_dictionary->stringSequenceMember();
- string_sequence_member_with_default_ =
- testing_dictionary->stringSequenceMemberWithDefault();
- if (testing_dictionary->hasStringSequenceOrNullMember()) {
- string_sequence_or_null_member_ =
- testing_dictionary->stringSequenceOrNullMember();
- }
- if (testing_dictionary->hasEnumMember())
- enum_member_ = testing_dictionary->enumMember();
- enum_member_with_default_ = testing_dictionary->enumMemberWithDefault();
- if (testing_dictionary->hasEnumOrNullMember())
- enum_or_null_member_ = testing_dictionary->enumOrNullMember();
- if (testing_dictionary->hasElementMember())
- element_member_ = testing_dictionary->elementMember();
- if (testing_dictionary->hasElementOrNullMember()) {
- element_or_null_member_ = testing_dictionary->elementOrNullMember();
- has_element_or_null_member_ = true;
- }
- if (testing_dictionary->hasObjectMember())
- object_member_ = testing_dictionary->objectMember();
- object_or_null_member_with_default_ =
- testing_dictionary->objectOrNullMemberWithDefault();
- if (testing_dictionary->hasDoubleOrStringMember())
- double_or_string_member_ = testing_dictionary->doubleOrStringMember();
- if (testing_dictionary->hasDoubleOrStringSequenceMember()) {
- double_or_string_sequence_or_null_member_ =
- MakeGarbageCollected<HeapVector<DoubleOrString>>();
- *double_or_string_sequence_or_null_member_ =
- testing_dictionary->doubleOrStringSequenceMember();
- }
- // eventTargetOrNullMember has a default null value.
- event_target_or_null_member_ = testing_dictionary->eventTargetOrNullMember();
- if (testing_dictionary->hasInternalEnumOrInternalEnumSequenceMember()) {
- internal_enum_or_internal_enum_sequence_ =
- testing_dictionary->internalEnumOrInternalEnumSequenceMember();
- }
- if (testing_dictionary->hasAnyMember())
- any_member_ = testing_dictionary->anyMember();
- if (testing_dictionary->hasCallbackFunctionMember())
- callback_function_member_ = testing_dictionary->callbackFunctionMember();
+
+void DictionaryTest::set(v8::Isolate* isolate,
+ const InternalDictionary* input_dictionary) {
+ dictionary_ = InternalDictionaryDerivedDerived::Create(isolate);
+
+ SAVE_DICT_MEMBER(longMember, LongMember);
+ SAVE_DICT_MEMBER(longMemberWithClamp, LongMemberWithClamp);
+ SAVE_DICT_MEMBER(longMemberWithEnforceRange, LongMemberWithEnforceRange);
+ SAVE_DICT_MEMBER(longMemberWithDefault, LongMemberWithDefault);
+ SAVE_DICT_MEMBER(longOrNullMember, LongOrNullMember);
+ SAVE_DICT_MEMBER(longOrNullMemberWithDefault, LongOrNullMemberWithDefault);
+ SAVE_DICT_MEMBER(booleanMember, BooleanMember);
+ SAVE_DICT_MEMBER(doubleMember, DoubleMember);
+ SAVE_DICT_MEMBER(unrestrictedDoubleMember, UnrestrictedDoubleMember);
+ SAVE_DICT_MEMBER(stringMember, StringMember);
+ SAVE_DICT_MEMBER(stringMemberWithDefault, StringMemberWithDefault);
+ SAVE_DICT_MEMBER(byteStringMember, ByteStringMember);
+ SAVE_DICT_MEMBER(usvStringMember, UsvStringMember);
+ SAVE_DICT_MEMBER(stringSequenceMember, StringSequenceMember);
+ SAVE_DICT_MEMBER(stringSequenceMemberWithDefault,
+ StringSequenceMemberWithDefault);
+ SAVE_DICT_MEMBER(stringSequenceOrNullMember, StringSequenceOrNullMember);
+ SAVE_DICT_MEMBER(enumMember, EnumMember);
+ SAVE_DICT_MEMBER(enumMemberWithDefault, EnumMemberWithDefault);
+ SAVE_DICT_MEMBER(enumOrNullMember, EnumOrNullMember);
+ SAVE_DICT_MEMBER(elementMember, ElementMember);
+ SAVE_DICT_MEMBER(elementOrNullMember, ElementOrNullMember);
+ SAVE_DICT_MEMBER(objectMember, ObjectMember);
+ SAVE_DICT_MEMBER(objectOrNullMemberWithDefault,
+ ObjectOrNullMemberWithDefault);
+ SAVE_DICT_MEMBER(doubleOrStringMember, DoubleOrStringMember);
+ SAVE_DICT_MEMBER(doubleOrStringSequenceMember, DoubleOrStringSequenceMember);
+ SAVE_DICT_MEMBER(eventTargetOrNullMember, EventTargetOrNullMember);
+ SAVE_DICT_MEMBER(internalEnumOrInternalEnumSequenceMember,
+ InternalEnumOrInternalEnumSequenceMember);
+ SAVE_DICT_MEMBER(anyMember, AnyMember);
+ SAVE_DICT_MEMBER(callbackFunctionMember, CallbackFunctionMember);
}
InternalDictionary* DictionaryTest::get(v8::Isolate* isolate) {
- InternalDictionary* result = InternalDictionary::Create(isolate);
- GetInternals(result);
- return result;
+ InternalDictionary* dictionary = InternalDictionary::Create(isolate);
+ RestoreInternalDictionary(dictionary);
+ return dictionary;
}
-void DictionaryTest::setDerived(const InternalDictionaryDerived* derived) {
- DCHECK(derived->hasRequiredBooleanMember());
- set(derived);
- if (derived->hasDerivedStringMember())
- derived_string_member_ = derived->derivedStringMember();
- derived_string_member_with_default_ =
- derived->derivedStringMemberWithDefault();
- required_boolean_member_ = derived->requiredBooleanMember();
+void DictionaryTest::setDerived(
+ v8::Isolate* isolate,
+ const InternalDictionaryDerived* input_dictionary) {
+ set(isolate, input_dictionary);
+
+ SAVE_DICT_MEMBER(derivedStringMember, DerivedStringMember);
+ SAVE_DICT_MEMBER(derivedStringMemberWithDefault,
+ DerivedStringMemberWithDefault);
+ SAVE_DICT_MEMBER(requiredBooleanMember, RequiredBooleanMember);
}
InternalDictionaryDerived* DictionaryTest::getDerived(v8::Isolate* isolate) {
- InternalDictionaryDerived* result =
+ InternalDictionaryDerived* dictionary =
InternalDictionaryDerived::Create(isolate);
- GetDerivedInternals(result);
- return result;
+ RestoreInternalDictionaryDerived(dictionary);
+ return dictionary;
}
void DictionaryTest::setDerivedDerived(
- const InternalDictionaryDerivedDerived* derived) {
- setDerived(derived);
- if (derived->hasDerivedDerivedStringMember())
- derived_derived_string_member_ = derived->derivedDerivedStringMember();
+ v8::Isolate* isolate,
+ const InternalDictionaryDerivedDerived* input_dictionary) {
+ setDerived(isolate, input_dictionary);
+
+ SAVE_DICT_MEMBER(derivedDerivedStringMember, DerivedDerivedStringMember);
}
InternalDictionaryDerivedDerived* DictionaryTest::getDerivedDerived(
v8::Isolate* isolate) {
- InternalDictionaryDerivedDerived* result =
+ InternalDictionaryDerivedDerived* dictionary =
InternalDictionaryDerivedDerived::Create(isolate);
- GetDerivedDerivedInternals(result);
- return result;
+ RestoreInternalDictionaryDerivedDerived(dictionary);
+ return dictionary;
}
-void DictionaryTest::Reset() {
- long_member_ = absl::nullopt;
- long_member_with_clamp_ = absl::nullopt;
- long_member_with_enforce_range_ = absl::nullopt;
- long_member_with_default_ = -1; // This value should not be returned.
- long_or_null_member_ = absl::nullopt;
- long_or_null_member_with_default_ = absl::nullopt;
- boolean_member_ = absl::nullopt;
- double_member_ = absl::nullopt;
- unrestricted_double_member_ = absl::nullopt;
- string_member_ = absl::nullopt;
- string_member_with_default_ = String("Should not be returned");
- byte_string_member_ = absl::nullopt;
- usv_string_member_ = absl::nullopt;
- string_sequence_member_ = absl::nullopt;
- string_sequence_member_with_default_.Fill("Should not be returned", 1);
- string_sequence_or_null_member_ = absl::nullopt;
- enum_member_ = absl::nullopt;
- enum_member_with_default_ = String();
- enum_or_null_member_ = absl::nullopt;
- element_member_ = nullptr;
- element_or_null_member_.Clear();
- has_element_or_null_member_ = false;
- object_member_ = ScriptValue();
- object_or_null_member_with_default_ = ScriptValue();
- double_or_string_member_ = DoubleOrString();
- double_or_string_sequence_or_null_member_ = nullptr;
- event_target_or_null_member_ = nullptr;
- derived_string_member_ = absl::nullopt;
- derived_string_member_with_default_ = String();
- derived_derived_string_member_ = absl::nullopt;
- required_boolean_member_ = false;
- dictionary_member_properties_ = absl::nullopt;
- internal_enum_or_internal_enum_sequence_ =
- InternalEnumOrInternalEnumSequence();
- any_member_ = ScriptValue();
- callback_function_member_ = nullptr;
-}
+#undef SAVE_DICT_MEMBER
-void DictionaryTest::GetInternals(InternalDictionary* dict) {
- DCHECK(dict);
+void DictionaryTest::Trace(Visitor* visitor) const {
+ ScriptWrappable::Trace(visitor);
+ visitor->Trace(dictionary_);
+}
- if (long_member_)
- dict->setLongMember(long_member_.value());
- if (long_member_with_clamp_)
- dict->setLongMemberWithClamp(long_member_with_clamp_.value());
- if (long_member_with_enforce_range_) {
- dict->setLongMemberWithEnforceRange(
- long_member_with_enforce_range_.value());
- }
- dict->setLongMemberWithDefault(long_member_with_default_);
- if (long_or_null_member_)
- dict->setLongOrNullMember(long_or_null_member_.value());
- if (long_or_null_member_with_default_) {
- dict->setLongOrNullMemberWithDefault(
- long_or_null_member_with_default_.value());
- }
- if (boolean_member_)
- dict->setBooleanMember(boolean_member_.value());
- if (double_member_)
- dict->setDoubleMember(double_member_.value());
- if (unrestricted_double_member_)
- dict->setUnrestrictedDoubleMember(unrestricted_double_member_.value());
- if (string_member_)
- dict->setStringMember(string_member_.value());
- dict->setStringMemberWithDefault(string_member_with_default_);
- if (byte_string_member_)
- dict->setByteStringMember(byte_string_member_.value());
- if (usv_string_member_)
- dict->setUsvStringMember(usv_string_member_.value());
- if (string_sequence_member_)
- dict->setStringSequenceMember(string_sequence_member_.value());
- dict->setStringSequenceMemberWithDefault(
- string_sequence_member_with_default_);
- if (string_sequence_or_null_member_) {
- dict->setStringSequenceOrNullMember(
- string_sequence_or_null_member_.value());
+#define RESTORE_DICT_MEMBER(camel, capital) \
+ if (dictionary_->has##capital()) { \
+ output_dictionary->set##capital(dictionary_->camel()); \
+ } else { \
}
- if (enum_member_)
- dict->setEnumMember(enum_member_.value());
- dict->setEnumMemberWithDefault(enum_member_with_default_);
- if (enum_or_null_member_)
- dict->setEnumOrNullMember(enum_or_null_member_.value());
- if (element_member_)
- dict->setElementMember(element_member_);
- if (has_element_or_null_member_)
- dict->setElementOrNullMember(element_or_null_member_);
- dict->setObjectMember(object_member_);
- dict->setObjectOrNullMemberWithDefault(object_or_null_member_with_default_);
- if (!double_or_string_member_.IsNull())
- dict->setDoubleOrStringMember(double_or_string_member_);
- if (double_or_string_sequence_or_null_member_) {
- dict->setDoubleOrStringSequenceMember(
- *double_or_string_sequence_or_null_member_);
- }
- dict->setEventTargetOrNullMember(event_target_or_null_member_);
- dict->setInternalEnumOrInternalEnumSequenceMember(
- internal_enum_or_internal_enum_sequence_);
- dict->setAnyMember(any_member_);
- if (callback_function_member_)
- dict->setCallbackFunctionMember(callback_function_member_);
+
+void DictionaryTest::RestoreInternalDictionary(
+ InternalDictionary* output_dictionary) {
+ RESTORE_DICT_MEMBER(longMember, LongMember);
+ RESTORE_DICT_MEMBER(longMemberWithClamp, LongMemberWithClamp);
+ RESTORE_DICT_MEMBER(longMemberWithEnforceRange, LongMemberWithEnforceRange);
+ RESTORE_DICT_MEMBER(longMemberWithDefault, LongMemberWithDefault);
+ RESTORE_DICT_MEMBER(longOrNullMember, LongOrNullMember);
+ RESTORE_DICT_MEMBER(longOrNullMemberWithDefault, LongOrNullMemberWithDefault);
+ RESTORE_DICT_MEMBER(booleanMember, BooleanMember);
+ RESTORE_DICT_MEMBER(doubleMember, DoubleMember);
+ RESTORE_DICT_MEMBER(unrestrictedDoubleMember, UnrestrictedDoubleMember);
+ RESTORE_DICT_MEMBER(stringMember, StringMember);
+ RESTORE_DICT_MEMBER(stringMemberWithDefault, StringMemberWithDefault);
+ RESTORE_DICT_MEMBER(byteStringMember, ByteStringMember);
+ RESTORE_DICT_MEMBER(usvStringMember, UsvStringMember);
+ RESTORE_DICT_MEMBER(stringSequenceMember, StringSequenceMember);
+ RESTORE_DICT_MEMBER(stringSequenceMemberWithDefault,
+ StringSequenceMemberWithDefault);
+ RESTORE_DICT_MEMBER(stringSequenceOrNullMember, StringSequenceOrNullMember);
+ RESTORE_DICT_MEMBER(enumMember, EnumMember);
+ RESTORE_DICT_MEMBER(enumMemberWithDefault, EnumMemberWithDefault);
+ RESTORE_DICT_MEMBER(enumOrNullMember, EnumOrNullMember);
+ RESTORE_DICT_MEMBER(elementMember, ElementMember);
+ RESTORE_DICT_MEMBER(elementOrNullMember, ElementOrNullMember);
+ RESTORE_DICT_MEMBER(objectMember, ObjectMember);
+ RESTORE_DICT_MEMBER(objectOrNullMemberWithDefault,
+ ObjectOrNullMemberWithDefault);
+ RESTORE_DICT_MEMBER(doubleOrStringMember, DoubleOrStringMember);
+ RESTORE_DICT_MEMBER(doubleOrStringSequenceMember,
+ DoubleOrStringSequenceMember);
+ RESTORE_DICT_MEMBER(eventTargetOrNullMember, EventTargetOrNullMember);
+ RESTORE_DICT_MEMBER(internalEnumOrInternalEnumSequenceMember,
+ InternalEnumOrInternalEnumSequenceMember);
+ RESTORE_DICT_MEMBER(anyMember, AnyMember);
+ RESTORE_DICT_MEMBER(callbackFunctionMember, CallbackFunctionMember);
}
-void DictionaryTest::GetDerivedInternals(InternalDictionaryDerived* dict) {
- GetInternals(dict);
+void DictionaryTest::RestoreInternalDictionaryDerived(
+ InternalDictionaryDerived* output_dictionary) {
+ RestoreInternalDictionary(output_dictionary);
- if (derived_string_member_)
- dict->setDerivedStringMember(derived_string_member_.value());
- dict->setDerivedStringMemberWithDefault(derived_string_member_with_default_);
- dict->setRequiredBooleanMember(required_boolean_member_);
+ RESTORE_DICT_MEMBER(derivedStringMember, DerivedStringMember);
+ RESTORE_DICT_MEMBER(derivedStringMemberWithDefault,
+ DerivedStringMemberWithDefault);
+ RESTORE_DICT_MEMBER(requiredBooleanMember, RequiredBooleanMember);
}
-void DictionaryTest::GetDerivedDerivedInternals(
- InternalDictionaryDerivedDerived* dict) {
- GetDerivedInternals(dict);
+void DictionaryTest::RestoreInternalDictionaryDerivedDerived(
+ InternalDictionaryDerivedDerived* output_dictionary) {
+ RestoreInternalDictionaryDerived(output_dictionary);
- if (derived_derived_string_member_)
- dict->setDerivedDerivedStringMember(derived_derived_string_member_.value());
+ RESTORE_DICT_MEMBER(derivedDerivedStringMember, DerivedDerivedStringMember);
}
-void DictionaryTest::Trace(Visitor* visitor) const {
- visitor->Trace(element_member_);
- visitor->Trace(element_or_null_member_);
- visitor->Trace(object_member_);
- visitor->Trace(object_or_null_member_with_default_);
- visitor->Trace(double_or_string_sequence_or_null_member_);
- visitor->Trace(event_target_or_null_member_);
- visitor->Trace(any_member_);
- visitor->Trace(callback_function_member_);
- ScriptWrappable::Trace(visitor);
-}
+#undef RESTORE_DICT_MEMBER
} // namespace blink
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 f2d1ac9e169..12b59455b9f 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
@@ -5,17 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_DICTIONARY_TEST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_DICTIONARY_TEST_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/internal_enum_or_internal_enum_sequence.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_internal_enum.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_test_callback.h"
-#include "third_party/blink/renderer/core/dom/element.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/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
namespace blink {
@@ -31,74 +21,31 @@ class DictionaryTest : public ScriptWrappable {
DictionaryTest();
~DictionaryTest() override;
- // Stores all members into corresponding fields
- void set(const InternalDictionary*);
- // Sets each member of the given TestDictionary from fields
+ // Saves the given InternalDictionary in this object.
+ void set(v8::Isolate* isolate, const InternalDictionary* input_dictionary);
+ // Returns an InternalDictionary with filled with the saved dictionary
+ // members.
InternalDictionary* get(v8::Isolate* isolate);
- void setDerived(const InternalDictionaryDerived*);
+ void setDerived(v8::Isolate* isolate,
+ const InternalDictionaryDerived* input_dictionary);
InternalDictionaryDerived* getDerived(v8::Isolate* isolate);
- void setDerivedDerived(const InternalDictionaryDerivedDerived*);
+ void setDerivedDerived(
+ v8::Isolate* isolate,
+ const InternalDictionaryDerivedDerived* input_dictionary);
InternalDictionaryDerivedDerived* getDerivedDerived(v8::Isolate* isolate);
void Trace(Visitor*) const override;
private:
- void Reset();
+ void RestoreInternalDictionary(InternalDictionary* output_dictionary);
+ void RestoreInternalDictionaryDerived(
+ InternalDictionaryDerived* output_dictionary);
+ void RestoreInternalDictionaryDerivedDerived(
+ InternalDictionaryDerivedDerived* output_dictionary);
- void GetInternals(InternalDictionary*);
- void GetDerivedInternals(InternalDictionaryDerived*);
- void GetDerivedDerivedInternals(InternalDictionaryDerivedDerived*);
-
- // The reason to use absl::optional<T> is convenience; we use
- // absl::optional<T> here to record whether the member field is set or not.
- // Some members are not wrapped with optional because:
- // - |longMemberWithDefault| has a non-null default value
- // - String and PtrTypes can express whether they are null
- // - absl::optional does not work with GarbageCollected types when used on
- // heap.
- absl::optional<int> long_member_;
- absl::optional<int> long_member_with_clamp_;
- absl::optional<int> long_member_with_enforce_range_;
- int long_member_with_default_;
- absl::optional<int> long_or_null_member_;
- absl::optional<int> long_or_null_member_with_default_;
- absl::optional<bool> boolean_member_;
- absl::optional<double> double_member_;
- absl::optional<double> unrestricted_double_member_;
- absl::optional<String> string_member_;
- String string_member_with_default_;
- absl::optional<String> byte_string_member_;
- absl::optional<String> usv_string_member_;
- absl::optional<Vector<String>> string_sequence_member_;
- Vector<String> string_sequence_member_with_default_;
- absl::optional<Vector<String>> string_sequence_or_null_member_;
- absl::optional<String> enum_member_;
- String enum_member_with_default_;
-#ifdef USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY
- // The outer optional<> represents if the member is missing, and the inner
- // optional<> represents if the member is a null value.
- absl::optional<absl::optional<V8InternalEnum>> enum_or_null_member_;
-#else
- absl::optional<String> enum_or_null_member_;
-#endif
- Member<Element> element_member_;
- Member<Element> element_or_null_member_;
- bool has_element_or_null_member_ = false;
- ScriptValue object_member_;
- ScriptValue object_or_null_member_with_default_;
- DoubleOrString double_or_string_member_;
- Member<HeapVector<DoubleOrString>> double_or_string_sequence_or_null_member_;
- Member<EventTarget> event_target_or_null_member_;
- absl::optional<String> derived_string_member_;
- String derived_string_member_with_default_;
- absl::optional<String> derived_derived_string_member_;
- bool required_boolean_member_;
- absl::optional<HashMap<String, String>> dictionary_member_properties_;
- InternalEnumOrInternalEnumSequence internal_enum_or_internal_enum_sequence_;
- ScriptValue any_member_;
- Member<V8TestCallback> callback_function_member_;
+ Member<InternalDictionaryDerivedDerived> dictionary_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl b/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl
index 24efc582987..8fdcae60a51 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl
@@ -3,12 +3,12 @@
// found in the LICENSE file.
interface DictionaryTest {
- void set(optional InternalDictionary testingDictionary = {});
+ [CallWith=Isolate] void set(optional InternalDictionary testingDictionary = {});
[CallWith=Isolate] InternalDictionary get();
- void setDerived(InternalDictionaryDerived derived);
+ [CallWith=Isolate] void setDerived(InternalDictionaryDerived derived);
[CallWith=Isolate] InternalDictionaryDerived getDerived();
- void setDerivedDerived(InternalDictionaryDerivedDerived derived);
+ [CallWith=Isolate] void setDerivedDerived(InternalDictionaryDerivedDerived derived);
[CallWith=Isolate] InternalDictionaryDerivedDerived getDerivedDerived();
};
diff --git a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
index de225c91f58..91e2d574c60 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
+#include "third_party/blink/renderer/core/script/import_map_error.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
namespace blink {
@@ -61,10 +62,6 @@ bool DummyModulator::IsScriptingDisabled() const {
return false;
}
-bool DummyModulator::ImportMapsEnabled() const {
- return false;
-}
-
ModuleRecordResolver* DummyModulator::GetModuleRecordResolver() {
return resolver_.Get();
}
@@ -119,23 +116,14 @@ bool DummyModulator::HasValidContext() {
}
void DummyModulator::ResolveDynamically(const ModuleRequest& module_request,
- const KURL&,
const ReferrerScriptInfo&,
ScriptPromiseResolver*) {
NOTREACHED();
}
-ScriptValue DummyModulator::CreateTypeError(const String& message) const {
- NOTREACHED();
- return ScriptValue();
-}
-ScriptValue DummyModulator::CreateSyntaxError(const String& message) const {
- NOTREACHED();
- return ScriptValue();
-}
-
-void DummyModulator::RegisterImportMap(const ImportMap*,
- ScriptValue error_to_rethrow) {
+void DummyModulator::RegisterImportMap(
+ const ImportMap*,
+ absl::optional<ImportMapError> error_to_rethrow) {
NOTREACHED();
}
@@ -160,18 +148,6 @@ ModuleImportMeta DummyModulator::HostGetImportMetaProperties(
return ModuleImportMeta(String());
}
-ScriptValue DummyModulator::InstantiateModule(v8::Local<v8::Module>,
- const KURL&) {
- NOTREACHED();
- return ScriptValue();
-}
-
-Vector<ModuleRequest> DummyModulator::ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) {
- NOTREACHED();
- return Vector<ModuleRequest>();
-}
-
ModuleType DummyModulator::ModuleTypeFromRequest(
const ModuleRequest& module_request) const {
String module_type_string = module_request.GetModuleTypeString();
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 13a7f2ae8fb..325a665f11a 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -9,6 +9,7 @@
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/module_request.h"
+#include "third_party/blink/renderer/core/script/import_map_error.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -24,10 +25,10 @@ class ModuleRecordResolver;
// implementation. Unit tests can implement a subset of Modulator interface
// which is exercised from unit-under-test.
class DummyModulator : public Modulator {
- DISALLOW_COPY_AND_ASSIGN(DummyModulator);
-
public:
DummyModulator();
+ DummyModulator(const DummyModulator&) = delete;
+ DummyModulator& operator=(const DummyModulator&) = delete;
~DummyModulator() override;
void Trace(Visitor*) const override;
@@ -37,8 +38,6 @@ class DummyModulator : public Modulator {
mojom::blink::V8CacheOptions GetV8CacheOptions() const override;
bool IsScriptingDisabled() const override;
- bool ImportMapsEnabled() const override;
-
void FetchTree(const KURL&,
ModuleType,
ResourceFetcher*,
@@ -62,21 +61,16 @@ class DummyModulator : public Modulator {
KURL ResolveModuleSpecifier(const String&, const KURL&, String*) override;
bool HasValidContext() override;
void ResolveDynamically(const ModuleRequest& module_request,
- const KURL&,
const ReferrerScriptInfo&,
ScriptPromiseResolver*) override;
- ScriptValue CreateTypeError(const String& message) const override;
- ScriptValue CreateSyntaxError(const String& message) const override;
- void RegisterImportMap(const ImportMap*,
- ScriptValue error_to_rethrow) override;
+ void RegisterImportMap(
+ const ImportMap*,
+ absl::optional<ImportMapError> error_to_rethrow) override;
AcquiringImportMapsState GetAcquiringImportMapsState() const override;
void SetAcquiringImportMapsState(AcquiringImportMapsState) override;
ModuleImportMeta HostGetImportMetaProperties(
v8::Local<v8::Module>) const override;
const ImportMap* GetImportMapForTest() const override;
- ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) override;
- Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
- v8::Local<v8::Module>) override;
ModuleType ModuleTypeFromRequest(
const ModuleRequest& module_request) const override;
ModuleScriptFetcher* CreateModuleScriptFetcher(
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 435f56f980a..7c4a25e3148 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
@@ -83,6 +83,9 @@ DummyPageHolder::DummyPageHolder(
if (setting_overrider)
std::move(setting_overrider).Run(settings);
+ // DummyPageHolder doesn't provide a browser interface, so code caches cannot
+ // be fetched. If testing for code caches provide a mock code cache host.
+ DocumentLoader::DisableCodeCacheForTesting();
local_frame_client_ = local_frame_client;
if (!local_frame_client_)
local_frame_client_ = MakeGarbageCollected<DummyLocalFrameClient>();
diff --git a/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.h b/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.h
index 10d66647642..c237b6902a2 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.h
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.h
@@ -35,7 +35,6 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -76,6 +75,8 @@ class DummyPageHolder {
base::OnceCallback<void(Settings&)> setting_overrider =
base::NullCallback(),
const base::TickClock* clock = base::DefaultTickClock::GetInstance());
+ DummyPageHolder(const DummyPageHolder&) = delete;
+ DummyPageHolder& operator=(const DummyPageHolder&) = delete;
~DummyPageHolder();
Page& GetPage() const;
@@ -100,7 +101,6 @@ class DummyPageHolder {
Persistent<LocalFrameClient> local_frame_client_;
std::unique_ptr<scheduler::WebAgentGroupScheduler> agent_group_scheduler_;
- DISALLOW_COPY_AND_ASSIGN(DummyPageHolder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
index 70d0a8e83a8..31f80c24aa3 100644
--- a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
+++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/core/testing/fake_local_frame_host.h"
#include "skia/public/mojom/skcolor.mojom-blink.h"
+#include "third_party/blink/public/mojom/choosers/popup_menu.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink.h"
@@ -200,9 +202,10 @@ void FakeLocalFrameHost::DidChangeFrameOwnerProperties(
void FakeLocalFrameHost::DidChangeOpener(
const absl::optional<LocalFrameToken>& opener_frame) {}
-void FakeLocalFrameHost::DidChangeCSPAttribute(
+void FakeLocalFrameHost::DidChangeIframeAttributes(
const blink::FrameToken& child_frame_token,
- network::mojom::blink::ContentSecurityPolicyPtr) {}
+ network::mojom::blink::ContentSecurityPolicyPtr,
+ bool anonymous) {}
void FakeLocalFrameHost::DidChangeFramePolicy(
const blink::FrameToken& child_frame_token,
@@ -229,7 +232,8 @@ void FakeLocalFrameHost::DidAddMessageToConsole(
void FakeLocalFrameHost::FrameSizeChanged(const gfx::Size& frame_size) {}
-void FakeLocalFrameHost::DidActivateForPrerendering() {}
+void FakeLocalFrameHost::DidUpdatePreferredColorScheme(
+ blink::mojom::PreferredColorScheme preferred_color_scheme) {}
void FakeLocalFrameHost::BindFrameHostReceiver(
mojo::ScopedInterfaceEndpointHandle handle) {
diff --git a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
index 674aa1836e9..2ec80b20adc 100644
--- a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
+++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -73,6 +73,8 @@ class FakeLocalFrameHost : public mojom::blink::LocalFrameHost {
void DidFinishLoad(const KURL& validated_url) override;
void DispatchLoad() override;
void GoToEntryAtOffset(int32_t offset, bool has_user_gesture) override;
+ void NavigateToAppHistoryKey(const WTF::String& key,
+ bool has_user_gesture) override {}
void UpdateTitle(const WTF::String& title,
base::i18n::TextDirection title_direction) override;
void UpdateUserActivationState(
@@ -134,9 +136,10 @@ class FakeLocalFrameHost : public mojom::blink::LocalFrameHost {
mojom::blink::FrameOwnerPropertiesPtr frame_owner_properties) override;
void DidChangeOpener(
const absl::optional<LocalFrameToken>& opener_frame) override;
- void DidChangeCSPAttribute(const blink::FrameToken& child_frame_token,
- network::mojom::blink::ContentSecurityPolicyPtr
- parsed_csp_attribute) override;
+ void DidChangeIframeAttributes(
+ const blink::FrameToken& child_frame_token,
+ network::mojom::blink::ContentSecurityPolicyPtr parsed_csp_attribute,
+ bool anonymous) override;
void DidChangeFramePolicy(const blink::FrameToken& child_frame_token,
const FramePolicy& frame_policy) override;
void CapturePaintPreviewOfSubframe(
@@ -155,7 +158,8 @@ class FakeLocalFrameHost : public mojom::blink::LocalFrameHost {
const WTF::String& source_id,
const WTF::String& untrusted_stack_trace) override;
void FrameSizeChanged(const gfx::Size& frame_size) override;
- void DidActivateForPrerendering() override;
+ void DidUpdatePreferredColorScheme(
+ blink::mojom::PreferredColorScheme preferred_color_scheme) override;
private:
void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/chromium/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc b/chromium/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc
index b82cfa5729f..f9f79bd44c3 100644
--- a/chromium/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc
+++ b/chromium/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/testing/fake_remote_frame_host.h"
+#include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-blink.h"
+
namespace blink {
void FakeRemoteFrameHost::Init(blink::AssociatedInterfaceProvider* provider) {
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.cc b/chromium/third_party/blink/renderer/core/testing/internals.cc
index a7fbd640859..c855514e9ac 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.cc
+++ b/chromium/third_party/blink/renderer/core/testing/internals.cc
@@ -30,7 +30,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/process/process_handle.h"
#include "cc/layers/picture_layer.h"
#include "cc/trees/layer_tree_host.h"
@@ -123,6 +122,7 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/loader/history_item.h"
+#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -196,6 +196,7 @@
#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
+#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
#include "ui/base/ui_base_features.h"
@@ -215,6 +216,9 @@ class UseCounterImplObserverImpl final : public UseCounterImpl::Observer {
UseCounterImplObserverImpl(ScriptPromiseResolver* resolver,
WebFeature feature)
: resolver_(resolver), feature_(feature) {}
+ UseCounterImplObserverImpl(const UseCounterImplObserverImpl&) = delete;
+ UseCounterImplObserverImpl& operator=(const UseCounterImplObserverImpl&) =
+ delete;
bool OnCountFeature(WebFeature feature) final {
if (feature_ != feature)
@@ -231,7 +235,6 @@ class UseCounterImplObserverImpl final : public UseCounterImpl::Observer {
private:
Member<ScriptPromiseResolver> resolver_;
WebFeature feature_;
- DISALLOW_COPY_AND_ASSIGN(UseCounterImplObserverImpl);
};
class TestReadableStreamSource : public UnderlyingSourceBase {
@@ -711,10 +714,6 @@ unsigned Internals::workerThreadCount() const {
return WorkerThread::WorkerThreadCount();
}
-bool Internals::isFormControlsRefreshEnabled() const {
- return ::features::IsFormControlsRefreshEnabled();
-}
-
GCObservation* Internals::observeGC(ScriptValue script_value) {
v8::Local<v8::Value> observed_value = script_value.V8Value();
DCHECK(!observed_value.IsEmpty());
@@ -756,6 +755,18 @@ unsigned Internals::needsLayoutCount(ExceptionState& exception_state) const {
return needs_layout_objects;
}
+unsigned Internals::layoutCountForTesting(
+ ExceptionState& exception_state) const {
+ LocalFrame* context_frame = GetFrame();
+ if (!context_frame) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+ "No context frame is available.");
+ return 0;
+ }
+
+ return context_frame->View()->LayoutCountForTesting();
+}
+
unsigned Internals::hitTestCount(Document* doc,
ExceptionState& exception_state) const {
if (!doc) {
@@ -2216,7 +2227,7 @@ HitTestLayerRectList* Internals::touchEventTargetLayerRects(
IntSize(layer->bounds()));
Vector<IntRect> layer_hit_test_rects;
- for (const auto& hit_test_rect : touch_action_region.GetAllRegions())
+ for (auto hit_test_rect : touch_action_region.GetAllRegions())
layer_hit_test_rects.push_back(IntRect(hit_test_rect));
MergeRects(layer_hit_test_rects);
@@ -2358,8 +2369,7 @@ bool Internals::canHyphenate(const AtomicString& locale) {
}
void Internals::setMockHyphenation(const AtomicString& locale) {
- LayoutLocale::SetHyphenationForTesting(locale,
- base::AdoptRef(new MockHyphenation));
+ LayoutLocale::SetHyphenationForTesting(locale, MockHyphenation::Create());
}
unsigned Internals::numberOfLiveNodes() const {
@@ -2521,7 +2531,7 @@ DOMRectList* Internals::nonFastScrollableRects(
Vector<IntRect> layer_non_fast_scrollable_rects;
for (auto* layer : *layer_tree_host) {
const cc::Region& non_fast_region = layer->non_fast_scrollable_region();
- for (const gfx::Rect& non_fast_rect : non_fast_region) {
+ for (gfx::Rect non_fast_rect : non_fast_region) {
gfx::RectF layer_rect(non_fast_rect);
// Map |layer_rect| into screen space.
@@ -2774,6 +2784,9 @@ void Internals::setMediaControlsTestMode(HTMLMediaElement* media_element,
void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(
const String& scheme) {
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(scheme);
}
@@ -2787,12 +2800,18 @@ void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(
else if (policy_area == "style")
policy_areas_enum |= SchemeRegistry::kPolicyAreaStyle;
}
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
scheme, static_cast<SchemeRegistry::PolicyAreas>(policy_areas_enum));
}
void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(
const String& scheme) {
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RemoveURLSchemeRegisteredAsBypassingContentSecurityPolicy(
scheme);
}
@@ -3467,6 +3486,18 @@ void Internals::forceLoseCanvasContext(HTMLCanvasElement* canvas,
CanvasContextCreationAttributesCore attr;
CanvasRenderingContext* context =
canvas->GetCanvasRenderingContext(context_type, attr);
+ if (!context)
+ return;
+ context->LoseContext(CanvasRenderingContext::kSyntheticLostContext);
+}
+
+void Internals::forceLoseCanvasContext(OffscreenCanvas* offscreencanvas,
+ const String& context_type) {
+ CanvasContextCreationAttributesCore attr;
+ CanvasRenderingContext* context = offscreencanvas->GetCanvasRenderingContext(
+ document_->GetExecutionContext(), context_type, attr);
+ if (!context)
+ return;
context->LoseContext(CanvasRenderingContext::kSyntheticLostContext);
}
@@ -3829,10 +3860,12 @@ void Internals::setIsAdSubframe(HTMLIFrameElement* iframe,
}
LocalFrame* parent_frame = iframe->GetDocument().GetFrame();
LocalFrame* child_frame = To<LocalFrame>(iframe->ContentFrame());
- bool parent_is_ad = parent_frame && parent_frame->IsAdSubframe();
- child_frame->SetIsAdSubframe(parent_is_ad
- ? blink::mojom::AdFrameType::kChildAd
- : blink::mojom::AdFrameType::kRootAd);
+ blink::FrameAdEvidence ad_evidence(parent_frame &&
+ parent_frame->IsAdSubframe());
+ ad_evidence.set_created_by_ad_script(
+ mojom::FrameCreationStackEvidence::kCreatedByAdScript);
+ ad_evidence.set_is_complete();
+ child_frame->SetAdEvidence(ad_evidence);
}
ReadableStream* Internals::createReadableStream(
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.h b/chromium/third_party/blink/renderer/core/testing/internals.h
index 73adfc28945..d89952b7cca 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.h
+++ b/chromium/third_party/blink/renderer/core/testing/internals.h
@@ -72,6 +72,7 @@ class LocalFrame;
class Location;
class Node;
class OriginTrialsTest;
+class OffscreenCanvas;
class Page;
class Range;
class ReadableStream;
@@ -153,6 +154,7 @@ class Internals final : public ScriptWrappable {
unsigned updateStyleAndReturnAffectedElementCount(ExceptionState&) const;
unsigned needsLayoutCount(ExceptionState&) const;
+ unsigned layoutCountForTesting(ExceptionState&) const;
unsigned hitTestCount(Document*, ExceptionState&) const;
unsigned hitTestCacheHits(Document*, ExceptionState&) const;
Element* elementFromPoint(Document*,
@@ -333,8 +335,6 @@ class Internals final : public ScriptWrappable {
InternalRuntimeFlags* runtimeFlags() const;
unsigned workerThreadCount() const;
- bool isFormControlsRefreshEnabled() const;
-
String resolveModuleSpecifier(const String& specifier,
const String& base_url_string,
Document*,
@@ -508,6 +508,9 @@ class Internals final : public ScriptWrappable {
void forceLoseCanvasContext(HTMLCanvasElement* canvas,
const String& context_type);
+ void forceLoseCanvasContext(OffscreenCanvas* offscreencanvas,
+ const String& context_type);
+
void setScrollChain(ScrollState*,
const HeapVector<Member<Element>>& elements,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.idl b/chromium/third_party/blink/renderer/core/testing/internals.idl
index 9cc0ff70934..2885edbd854 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.idl
+++ b/chromium/third_party/blink/renderer/core/testing/internals.idl
@@ -63,6 +63,7 @@
[RaisesException] unsigned short compareTreeScopePosition(Node treeScope1, Node treeScope2);
[RaisesException] unsigned long updateStyleAndReturnAffectedElementCount();
[RaisesException] unsigned long needsLayoutCount();
+ [RaisesException] unsigned long layoutCountForTesting();
[RaisesException] unsigned long hitTestCount(Document document);
[RaisesException] unsigned long hitTestCacheHits(Document document);
[RaisesException] Element? elementFromPoint(Document document, double x, double y, boolean ignoreClipping, boolean allowChildFrameContent);
@@ -185,7 +186,6 @@
readonly attribute InternalSettings settings;
readonly attribute InternalRuntimeFlags runtimeFlags;
readonly attribute unsigned long workerThreadCount;
- readonly attribute boolean isFormControlsRefreshEnabled;
// Flag for layerTreeAsText. The value must be kept in sync with the value
// of LayerTreeFlags in layers_as_json.h.
@@ -321,6 +321,7 @@
boolean isInCanvasFontCache(Document document, DOMString fontString);
unsigned long canvasFontCacheMaxFonts();
void forceLoseCanvasContext(HTMLCanvasElement canvas, DOMString contextType);
+ void forceLoseCanvasContext(OffscreenCanvas offscreencanvas, DOMString context_type);
DictionaryTest dictionaryTest();
RecordTest recordTest();
diff --git a/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.cc b/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.cc
new file mode 100644
index 00000000000..ce466599c28
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.cc
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/testing/internals_delete_all_cookies.h"
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/cookie_manager/cookie_manager_automation.mojom-blink.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/frame/local_dom_window.h"
+
+namespace blink {
+
+// static
+ScriptPromise InternalsDeleteAllCookies::deleteAllCookies(
+ ScriptState* script_state,
+ Internals&) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ mojo::Remote<test::mojom::blink::CookieManagerAutomation> cookie_manager;
+ window->GetBrowserInterfaceBroker().GetInterface(
+ cookie_manager.BindNewPipeAndPassReceiver());
+ DCHECK(cookie_manager.is_bound());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+ // Get the interface so `cookie_manager` can be moved below.
+ test::mojom::blink::CookieManagerAutomation* raw_cookie_manager =
+ cookie_manager.get();
+ raw_cookie_manager->DeleteAllCookies(WTF::Bind(
+ [](ScriptPromiseResolver* resolver,
+ mojo::Remote<test::mojom::blink::CookieManagerAutomation>) {
+ resolver->Resolve();
+ },
+ WrapPersistent(resolver),
+ // Keep `cookie_manager` alive to wait for callback.
+ std::move(cookie_manager)));
+ return promise;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.h b/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.h
new file mode 100644
index 00000000000..98ae7133361
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNALS_DELETE_ALL_COOKIES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNALS_DELETE_ALL_COOKIES_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class Internals;
+class ScriptPromise;
+class ScriptState;
+
+class InternalsDeleteAllCookies {
+ STATIC_ONLY(InternalsDeleteAllCookies);
+
+ public:
+ static ScriptPromise deleteAllCookies(ScriptState* script_state,
+ Internals& internals);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNALS_DELETE_ALL_COOKIES_H_
diff --git a/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.idl b/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.idl
new file mode 100644
index 00000000000..2c31d11edcd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/internals_delete_all_cookies.idl
@@ -0,0 +1,9 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+ ImplementedAs=InternalsDeleteAllCookies
+] partial interface Internals {
+ [CallWith=ScriptState] Promise<void> deleteAllCookies();
+};
diff --git a/chromium/third_party/blink/renderer/core/testing/intersection_observer_test_helper.h b/chromium/third_party/blink/renderer/core/testing/intersection_observer_test_helper.h
index 785bb0fa0cf..0b2bacec926 100644
--- a/chromium/third_party/blink/renderer/core/testing/intersection_observer_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/testing/intersection_observer_test_helper.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERSECTION_OBSERVER_TEST_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERSECTION_OBSERVER_TEST_HELPER_H_
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
@@ -12,13 +14,16 @@ namespace blink {
class TestIntersectionObserverDelegate : public IntersectionObserverDelegate {
public:
- explicit TestIntersectionObserverDelegate(Document& document)
- : document_(document), call_count_(0) {}
+ explicit TestIntersectionObserverDelegate(
+ Document& document,
+ LocalFrameUkmAggregator::MetricId metric_id =
+ LocalFrameUkmAggregator::kJavascriptIntersectionObserver)
+ : document_(document), metric_id_(metric_id), call_count_(0) {}
// TODO(szager): Add tests for the synchronous delivery code path. There is
// already some indirect coverage by unit tests exercising features that rely
// on it, but we should have some direct coverage in here.
LocalFrameUkmAggregator::MetricId GetUkmMetricId() const override {
- return LocalFrameUkmAggregator::kJavascriptIntersectionObserver;
+ return metric_id_;
}
IntersectionObserver::DeliveryBehavior GetDeliveryBehavior() const override {
return IntersectionObserver::kPostTaskToDeliver;
@@ -53,6 +58,7 @@ class TestIntersectionObserverDelegate : public IntersectionObserverDelegate {
private:
Member<Document> document_;
+ LocalFrameUkmAggregator::MetricId metric_id_;
HeapVector<Member<IntersectionObserverEntry>> entries_;
int call_count_;
};
diff --git a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc
index adf990e8d7f..a90377ece22 100644
--- a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc
+++ b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc
@@ -6,6 +6,11 @@
#include "base/containers/contains.h"
#include "build/build_config.h"
+#include "mojo/public/cpp/base/big_buffer.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
+#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
+#include "third_party/skia/include/core/SkBitmap.h"
namespace blink {
@@ -23,6 +28,7 @@ void MockClipboardHost::Reset() {
html_text_ = g_empty_string;
svg_text_ = g_empty_string;
url_ = KURL();
+ png_.clear();
image_.reset();
custom_data_.clear();
write_smart_paste_ = false;
@@ -45,7 +51,7 @@ void MockClipboardHost::ReadAvailableTypes(
types.push_back("text/html");
if (!svg_text_.IsEmpty())
types.push_back("image/svg+xml");
- if (!image_.isNull())
+ if (!png_.IsEmpty() || !image_.isNull())
types.push_back("image/png");
for (auto& it : custom_data_) {
CHECK(!base::Contains(types, it.key));
@@ -99,6 +105,11 @@ void MockClipboardHost::ReadRtf(mojom::ClipboardBuffer clipboard_buffer,
std::move(callback).Run(g_empty_string);
}
+void MockClipboardHost::ReadPng(mojom::ClipboardBuffer clipboard_buffer,
+ ReadPngCallback callback) {
+ std::move(callback).Run(mojo_base::BigBuffer(png_));
+}
+
void MockClipboardHost::ReadImage(mojom::ClipboardBuffer clipboard_buffer,
ReadImageCallback callback) {
std::move(callback).Run(image_);
@@ -154,14 +165,56 @@ void MockClipboardHost::WriteBookmark(const String& url, const String& title) {}
void MockClipboardHost::WriteImage(const SkBitmap& bitmap) {
if (needs_reset_)
Reset();
+ // TODO(crbug.com/1223254): Consider removing `image_` in favor of `png_`.
+ // For now, write to each.
image_ = bitmap;
+
+ SkPixmap pixmap;
+ bitmap.peekPixels(&pixmap);
+ // Set encoding options to favor speed over size.
+ SkPngEncoder::Options options;
+ options.fZLibLevel = 1;
+ options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
+
+ ImageEncoder::Encode(&png_, pixmap, options);
}
void MockClipboardHost::CommitWrite() {
- ++sequence_number_;
+ sequence_number_ = ClipboardSequenceNumberToken();
needs_reset_ = true;
}
+void MockClipboardHost::ReadAvailableCustomAndStandardFormats(
+ ReadAvailableCustomAndStandardFormatsCallback callback) {
+ Vector<String> format_names;
+ for (const auto& item : unsanitized_custom_data_map_)
+ format_names.emplace_back(item.key);
+ std::move(callback).Run(format_names);
+}
+
+void MockClipboardHost::ReadUnsanitizedCustomFormat(
+ const String& format,
+ ReadUnsanitizedCustomFormatCallback callback) {
+ const auto it = unsanitized_custom_data_map_.find(format);
+ if (it == unsanitized_custom_data_map_.end())
+ return;
+
+ mojo_base::BigBuffer buffer =
+ mojo_base::BigBuffer(base::make_span(it->value.data(), it->value.size()));
+ std::move(callback).Run(std::move(buffer));
+}
+
+void MockClipboardHost::WriteUnsanitizedCustomFormat(
+ const String& format,
+ mojo_base::BigBuffer data) {
+ if (needs_reset_)
+ Reset();
+ // Simulate the underlying platform copying this data.
+ Vector<uint8_t> data_copy(base::saturated_cast<wtf_size_t>(data.size()),
+ *data.data());
+ unsanitized_custom_data_map_.Set(format, data_copy);
+}
+
#if defined(OS_MAC)
void MockClipboardHost::WriteStringToFindPboard(const String& text) {}
#endif
diff --git a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h
index 97a724b95fe..8957dbae807 100644
--- a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h
+++ b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h
@@ -8,6 +8,7 @@
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom-blink.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -16,6 +17,8 @@ namespace blink {
class MockClipboardHost : public mojom::blink::ClipboardHost {
public:
MockClipboardHost();
+ MockClipboardHost(const MockClipboardHost&) = delete;
+ MockClipboardHost& operator=(const MockClipboardHost&) = delete;
~MockClipboardHost() override;
void Bind(mojo::PendingReceiver<mojom::blink::ClipboardHost> receiver);
@@ -39,6 +42,8 @@ class MockClipboardHost : public mojom::blink::ClipboardHost {
ReadSvgCallback callback) override;
void ReadRtf(mojom::ClipboardBuffer clipboard_buffer,
ReadRtfCallback callback) override;
+ void ReadPng(mojom::ClipboardBuffer clipboard_buffer,
+ ReadPngCallback callback) override;
void ReadImage(mojom::ClipboardBuffer clipboard_buffer,
ReadImageCallback callback) override;
void ReadFiles(mojom::ClipboardBuffer clipboard_buffer,
@@ -54,22 +59,30 @@ class MockClipboardHost : public mojom::blink::ClipboardHost {
void WriteBookmark(const String& url, const String& title) override;
void WriteImage(const SkBitmap& bitmap) override;
void CommitWrite() override;
+ void ReadAvailableCustomAndStandardFormats(
+ ReadAvailableCustomAndStandardFormatsCallback callback) override;
+ void ReadUnsanitizedCustomFormat(
+ const String& format,
+ ReadUnsanitizedCustomFormatCallback callback) override;
+ void WriteUnsanitizedCustomFormat(const String& format,
+ mojo_base::BigBuffer data) override;
#if defined(OS_MAC)
void WriteStringToFindPboard(const String& text) override;
#endif
mojo::ReceiverSet<mojom::blink::ClipboardHost> receivers_;
- uint64_t sequence_number_ = 0;
+ ClipboardSequenceNumberToken sequence_number_;
String plain_text_ = g_empty_string;
String html_text_ = g_empty_string;
String svg_text_ = g_empty_string;
KURL url_;
+ Vector<uint8_t> png_;
+ // TODO(asully): Remove `image_` once ReadImage() path is removed.
SkBitmap image_;
HashMap<String, String> custom_data_;
bool write_smart_paste_ = false;
bool needs_reset_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MockClipboardHost);
+ HashMap<String, Vector<uint8_t>> unsanitized_custom_data_map_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/mock_hyphenation.h b/chromium/third_party/blink/renderer/core/testing/mock_hyphenation.h
index 04d6b768508..7cef7fbd66f 100644
--- a/chromium/third_party/blink/renderer/core/testing/mock_hyphenation.h
+++ b/chromium/third_party/blink/renderer/core/testing/mock_hyphenation.h
@@ -13,6 +13,10 @@ class MockHyphenation : public Hyphenation {
public:
wtf_size_t LastHyphenLocation(const StringView&,
wtf_size_t before_index) const override;
+
+ static scoped_refptr<MockHyphenation> Create() {
+ return base::AdoptRef(new MockHyphenation);
+ }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/module_test_base.cc b/chromium/third_party/blink/renderer/core/testing/module_test_base.cc
index 13b07bf4f11..73ffae7b10b 100644
--- a/chromium/third_party/blink/renderer/core/testing/module_test_base.cc
+++ b/chromium/third_party/blink/renderer/core/testing/module_test_base.cc
@@ -15,15 +15,15 @@
namespace blink {
v8::Local<v8::Module> ModuleTestBase::CompileModule(
- v8::Isolate* isolate,
+ ScriptState* script_state,
const char* source,
const KURL& url,
ExceptionState& exception_state) {
- return CompileModule(isolate, String(source), url, exception_state);
+ return CompileModule(script_state, String(source), url, exception_state);
}
v8::Local<v8::Module> ModuleTestBase::CompileModule(
- v8::Isolate* isolate,
+ ScriptState* script_state,
String source,
const KURL& url,
ExceptionState& exception_state) {
@@ -31,7 +31,7 @@ v8::Local<v8::Module> ModuleTestBase::CompileModule(
/*source_url=*/url, /*base_url=*/url,
ScriptSourceLocationType::kExternalFile, ModuleType::kJavaScript,
ParkableString(source.Impl()), nullptr);
- return ModuleRecord::Compile(isolate, params, ScriptFetchOptions(),
+ return ModuleRecord::Compile(script_state, params, ScriptFetchOptions(),
TextPosition::MinimumPosition(),
exception_state);
}
diff --git a/chromium/third_party/blink/renderer/core/testing/module_test_base.h b/chromium/third_party/blink/renderer/core/testing/module_test_base.h
index 91b017ea9fd..d67e4330713 100644
--- a/chromium/third_party/blink/renderer/core/testing/module_test_base.h
+++ b/chromium/third_party/blink/renderer/core/testing/module_test_base.h
@@ -18,12 +18,12 @@ namespace blink {
class ModuleTestBase {
public:
static v8::Local<v8::Module> CompileModule(
- v8::Isolate*,
+ ScriptState*,
const char*,
const KURL&,
ExceptionState& state = DummyExceptionStateForTesting().ReturnThis());
static v8::Local<v8::Module> CompileModule(
- v8::Isolate*,
+ ScriptState*,
String,
const KURL&,
ExceptionState& state = DummyExceptionStateForTesting().ReturnThis());
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 7eb63bcc02b..fedd1ca6d50 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
@@ -22,7 +22,7 @@ NullExecutionContext::NullExecutionContext()
: ExecutionContext(
v8::Isolate::GetCurrent(),
MakeGarbageCollected<Agent>(v8::Isolate::GetCurrent(),
- base::UnguessableToken::Null())),
+ base::UnguessableToken::Create())),
scheduler_(scheduler::CreateDummyFrameScheduler()) {}
NullExecutionContext::~NullExecutionContext() {}
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 b9e8f84420b..4b6c28b2015 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
@@ -47,13 +47,14 @@ class NullExecutionContext : public GarbageCollected<NullExecutionContext>,
void SetUpSecurityContextForTesting();
- ResourceFetcher* Fetcher() const override { return nullptr; }
+ ResourceFetcher* Fetcher() override { return nullptr; }
bool CrossOriginIsolatedCapability() const override { return false; }
bool DirectSocketCapability() const override { return false; }
FrameOrWorkerScheduler* GetScheduler() override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
void CountUse(mojom::WebFeature) override {}
+ void CountDeprecation(mojom::WebFeature) override {}
const BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() const override;
diff --git a/chromium/third_party/blink/renderer/core/testing/origin_trials_test_global.h b/chromium/third_party/blink/renderer/core/testing/origin_trials_test_global.h
new file mode 100644
index 00000000000..2cbb03c34a5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/origin_trials_test_global.h
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ORIGIN_TRIALS_TEST_GLOBAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ORIGIN_TRIALS_TEST_GLOBAL_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class LocalDOMWindow;
+
+// This is used for testing that the Window interface can be extended with
+// origin trial-enabled IDL members at run-time.
+class OriginTrialsTestGlobal final {
+ STATIC_ONLY(OriginTrialsTestGlobal);
+
+ public:
+ static bool testOriginTrialGlobalAttribute(LocalDOMWindow&) { return true; }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ORIGIN_TRIALS_TEST_GLOBAL_H_
diff --git a/chromium/third_party/blink/renderer/core/testing/origin_trials_test_window.idl b/chromium/third_party/blink/renderer/core/testing/origin_trials_test_window.idl
new file mode 100644
index 00000000000..1c4adb6065b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/origin_trials_test_window.idl
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+ ImplementedAs=OriginTrialsTestGlobal,
+ RuntimeEnabled=OriginTrialsSampleAPI
+] partial interface Window {
+ readonly attribute boolean testOriginTrialGlobalAttribute;
+};
diff --git a/chromium/third_party/blink/renderer/core/testing/page_test_base.cc b/chromium/third_party/blink/renderer/core/testing/page_test_base.cc
index 97f9ac0af53..64ebb69e5f2 100644
--- a/chromium/third_party/blink/renderer/core/testing/page_test_base.cc
+++ b/chromium/third_party/blink/renderer/core/testing/page_test_base.cc
@@ -10,7 +10,6 @@
#include "base/test/bind.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.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_font_face_descriptors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
@@ -52,8 +51,13 @@ void ToSimpleLayoutTree(std::ostream& ostream,
ostream << *node;
else
ostream << "(anonymous)";
- if (auto* layout_text_fragment = DynamicTo<LayoutTextFragment>(layout_object))
+ if (auto* layout_text_fragment =
+ DynamicTo<LayoutTextFragment>(layout_object)) {
ostream << " (" << layout_text_fragment->GetText() << ")";
+ } else if (auto* layout_text = DynamicTo<LayoutText>(layout_object)) {
+ if (!layout_object.GetNode())
+ ostream << " " << layout_text->GetText();
+ }
ostream << std::endl;
for (auto* child = layout_object.SlowFirstChild(); child;
child = child->NextSibling()) {
@@ -190,15 +194,9 @@ void PageTestBase::LoadAhem(LocalFrame& frame) {
Document& document = *frame.DomWindow()->document();
scoped_refptr<SharedBuffer> shared_buffer =
test::ReadFromFile(test::CoreTestDataPath("Ahem.ttf"));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* buffer =
MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
DOMArrayBuffer::Create(shared_buffer));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrArrayBufferOrArrayBufferView buffer =
- StringOrArrayBufferOrArrayBufferView::FromArrayBuffer(
- DOMArrayBuffer::Create(shared_buffer));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FontFace* ahem = FontFace::Create(frame.DomWindow(), "Ahem", buffer,
FontFaceDescriptors::Create());
diff --git a/chromium/third_party/blink/renderer/core/testing/record_test.cc b/chromium/third_party/blink/renderer/core/testing/record_test.cc
index 0172179ed1c..99403eef111 100644
--- a/chromium/third_party/blink/renderer/core/testing/record_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/record_test.cc
@@ -73,17 +73,10 @@ RecordTest::returnStringByteStringSequenceRecord() {
return record;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool RecordTest::unionReceivedARecord(
const V8UnionBooleanOrByteStringByteStringRecord* arg) {
return arg->IsByteStringByteStringRecord();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool RecordTest::unionReceivedARecord(
- const BooleanOrByteStringByteStringRecord& arg) {
- return arg.IsByteStringByteStringRecord();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void RecordTest::Trace(Visitor* visitor) const {
visitor->Trace(string_element_record_);
diff --git a/chromium/third_party/blink/renderer/core/testing/record_test.h b/chromium/third_party/blink/renderer/core/testing/record_test.h
index 83d7cc07fdb..458b9e3570f 100644
--- a/chromium/third_party/blink/renderer/core/testing/record_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/record_test.h
@@ -6,9 +6,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_RECORD_TEST_H_
#include <utility>
+
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/boolean_or_byte_string_byte_string_record.h"
-#include "third_party/blink/renderer/bindings/core/v8/float_or_string_element_record.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -51,19 +50,11 @@ class RecordTest final : public ScriptWrappable {
Vector<std::pair<String, Vector<String>>>
returnStringByteStringSequenceRecord();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool unionReceivedARecord(
const V8UnionBooleanOrByteStringByteStringRecord* arg);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool unionReceivedARecord(const BooleanOrByteStringByteStringRecord& arg);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setFloatOrStringElementRecord(const V8UnionFloatOrStringElementRecord*) {
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setFloatOrStringElementRecord(const FloatOrStringElementRecord&) {}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
diff --git a/chromium/third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h b/chromium/third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h
index 44bbb12eea5..2e0fb7c1ad0 100644
--- a/chromium/third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h
+++ b/chromium/third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h
@@ -68,7 +68,8 @@ class ScopedMockOverlayScrollbars {
// platform independent.
if (use_mock_overlay_scrollbars_)
return true;
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || \
+ BUILDFLAG(IS_CHROMEOS_LACROS)
// Non-overlay scrollbar is not supported on Android and ChromeOS.
return false;
#else
diff --git a/chromium/third_party/blink/renderer/core/testing/sequence_test.cc b/chromium/third_party/blink/renderer/core/testing/sequence_test.cc
index d274a7495cf..77367671689 100644
--- a/chromium/third_party/blink/renderer/core/testing/sequence_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sequence_test.cc
@@ -45,16 +45,10 @@ void SequenceTest::setElementSequence(const HeapVector<Member<Element>>& arg) {
element_sequence_ = arg;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool SequenceTest::unionReceivedSequence(
const V8UnionDoubleOrDoubleSequence* arg) {
return arg->IsDoubleSequence();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool SequenceTest::unionReceivedSequence(const DoubleOrDoubleSequence& arg) {
- return arg.IsDoubleSequence();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void SequenceTest::Trace(Visitor* visitor) const {
visitor->Trace(element_sequence_);
diff --git a/chromium/third_party/blink/renderer/core/testing/sequence_test.h b/chromium/third_party/blink/renderer/core/testing/sequence_test.h
index b90c964018d..e5f476e4860 100644
--- a/chromium/third_party/blink/renderer/core/testing/sequence_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/sequence_test.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_SEQUENCE_TEST_H_
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_double_sequence.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_food_enum.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -37,11 +36,7 @@ class SequenceTest final : public ScriptWrappable {
HeapVector<Member<Element>> getElementSequence() const;
void setElementSequence(const HeapVector<Member<Element>>& arg);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool unionReceivedSequence(const V8UnionDoubleOrDoubleSequence* arg);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool unionReceivedSequence(const DoubleOrDoubleSequence& arg);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
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 20fa6d18e4d..2346cc3665a 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
@@ -12,13 +12,13 @@
namespace blink {
-SimRequestBase::SimRequestBase(String url,
+SimRequestBase::SimRequestBase(KURL url,
String mime_type,
bool start_immediately,
Params params)
- : url_(url),
+ : url_(std::move(url)),
redirect_url_(params.redirect_url),
- mime_type_(mime_type),
+ mime_type_(std::move(mime_type)),
referrer_(params.referrer),
start_immediately_(start_immediately),
started_(false),
@@ -82,7 +82,7 @@ void SimRequestBase::WriteInternal(base::span<const char> data) {
if (navigation_body_loader_)
navigation_body_loader_->Write(data.data(), data.size());
else
- client_->DidReceiveData(data.data(), data.size());
+ client_->DidReceiveData(data.data(), base::checked_cast<int>(data.size()));
}
void SimRequestBase::Finish(bool body_loader_finished) {
@@ -138,15 +138,29 @@ void SimRequestBase::ServePending() {
SimNetwork::Current().ServePendingRequests();
}
+SimRequest::SimRequest(KURL url, String mime_type, Params params)
+ : SimRequestBase(std::move(url),
+ std::move(mime_type),
+ /* start_immediately=*/true,
+ params) {}
+
SimRequest::SimRequest(String url, String mime_type, Params params)
- : SimRequestBase(url, mime_type, true /* start_immediately */, params) {}
+ : SimRequest(KURL(url), std::move(mime_type), params) {}
SimRequest::~SimRequest() = default;
+SimSubresourceRequest::SimSubresourceRequest(KURL url,
+ String mime_type,
+ Params params)
+ : SimRequestBase(std::move(url),
+ std::move(mime_type),
+ /* start_immediately=*/false,
+ params) {}
+
SimSubresourceRequest::SimSubresourceRequest(String url,
String mime_type,
Params params)
- : SimRequestBase(url, mime_type, false /* start_immediately */, params) {}
+ : SimSubresourceRequest(KURL(url), std::move(mime_type), params) {}
SimSubresourceRequest::~SimSubresourceRequest() = default;
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_request.h b/chromium/third_party/blink/renderer/core/testing/sim/sim_request.h
index 2c75ac91041..7de708ade4f 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_request.h
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_request.h
@@ -56,8 +56,10 @@ class SimRequestBase {
void Complete(const String& data = String());
void Complete(const Vector<char>& data);
+ const KURL& GetURL() const { return url_; }
+
protected:
- SimRequestBase(String url,
+ SimRequestBase(KURL url,
String mime_type,
bool start_immediately,
Params params = Params());
@@ -79,11 +81,11 @@ class SimRequestBase {
void DidFail(const WebURLError&);
void UsedForNavigation(StaticDataNavigationBodyLoader*);
- KURL url_;
+ const KURL url_;
String redirect_url_;
String mime_type_;
String referrer_;
- bool start_immediately_;
+ const bool start_immediately_;
bool started_;
WebURLResponse response_;
absl::optional<WebURLError> error_;
@@ -100,6 +102,7 @@ class SimRequestBase {
// TODO(dgozman): rename this to SimNavigationRequest or something.
class SimRequest final : public SimRequestBase {
public:
+ SimRequest(KURL url, String mime_type, Params params = Params());
SimRequest(String url, String mime_type, Params params = Params());
~SimRequest();
};
@@ -108,6 +111,7 @@ class SimRequest final : public SimRequestBase {
// delayed load of subresources.
class SimSubresourceRequest final : public SimRequestBase {
public:
+ SimSubresourceRequest(KURL url, String mime_type, Params params = Params());
SimSubresourceRequest(String url, String mime_type, Params params = Params());
~SimSubresourceRequest();
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 8654d3ee26f..91cc2530859 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
@@ -50,6 +50,10 @@ void SimTest::SetUp() {
web_view_helper_ =
std::make_unique<frame_test_helpers::WebViewHelper>(base::BindRepeating(
&SimTest::CreateTestWebFrameWidget, base::Unretained(this)));
+ // These tests don't simulate a browser interface and hence fetching code
+ // caching doesn't work in these tests. Currently tests that use this testing
+ // set up don't test / need code caches. Disable code caches for these tests.
+ DocumentLoader::DisableCodeCacheForTesting();
web_view_helper_->Initialize(web_frame_client_.get(), web_view_client_.get());
compositor_->SetWebView(WebView(), *web_view_client_);
diff --git a/chromium/third_party/blink/renderer/core/testing/static_selection.h b/chromium/third_party/blink/renderer/core/testing/static_selection.h
index 6c4b3cba9a2..9aeb123dc72 100644
--- a/chromium/third_party/blink/renderer/core/testing/static_selection.h
+++ b/chromium/third_party/blink/renderer/core/testing/static_selection.h
@@ -22,6 +22,8 @@ class StaticSelection final : public ScriptWrappable {
explicit StaticSelection(const SelectionInFlatTree&);
explicit StaticSelection(const SelectionInDOMTree&);
+ StaticSelection(const StaticSelection&) = delete;
+ StaticSelection& operator=(const StaticSelection&) = delete;
Node* anchorNode() const { return anchor_node_; }
unsigned anchorOffset() const { return anchor_offset_; }
@@ -36,8 +38,6 @@ class StaticSelection final : public ScriptWrappable {
const unsigned anchor_offset_;
const Member<Node> focus_node_;
const unsigned focus_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(StaticSelection);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/union_types_test.cc b/chromium/third_party/blink/renderer/core/testing/union_types_test.cc
index 487e7f26fdc..9d76b0d47a2 100644
--- a/chromium/third_party/blink/renderer/core/testing/union_types_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/union_types_test.cc
@@ -12,7 +12,6 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionDoubleOrStringOrStringSequence*
UnionTypesTest::doubleOrStringOrStringSequenceAttribute() const {
switch (attribute_type_) {
@@ -156,141 +155,5 @@ String UnionTypesTest::doubleOrStringOrStringSequenceArg(
NOTREACHED();
return String();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void UnionTypesTest::doubleOrStringOrStringSequenceAttribute(
- DoubleOrStringOrStringSequence& double_or_string_or_string_sequence) {
- switch (attribute_type_) {
- case kSpecificTypeNone:
- // Default value is zero (of double).
- double_or_string_or_string_sequence.SetDouble(0);
- break;
- case kSpecificTypeDouble:
- double_or_string_or_string_sequence.SetDouble(attribute_double_);
- break;
- case kSpecificTypeString:
- double_or_string_or_string_sequence.SetString(attribute_string_);
- break;
- case kSpecificTypeStringSequence:
- double_or_string_or_string_sequence.SetStringSequence(
- attribute_string_sequence_);
- break;
- default:
- NOTREACHED();
- }
-}
-
-void UnionTypesTest::setDoubleOrStringOrStringSequenceAttribute(
- const DoubleOrStringOrStringSequence& double_or_string_or_string_sequence) {
- if (double_or_string_or_string_sequence.IsDouble()) {
- attribute_double_ = double_or_string_or_string_sequence.GetAsDouble();
- attribute_type_ = kSpecificTypeDouble;
- } else if (double_or_string_or_string_sequence.IsString()) {
- attribute_string_ = double_or_string_or_string_sequence.GetAsString();
- attribute_type_ = kSpecificTypeString;
- } else if (double_or_string_or_string_sequence.IsStringSequence()) {
- attribute_string_sequence_ =
- double_or_string_or_string_sequence.GetAsStringSequence();
- attribute_type_ = kSpecificTypeStringSequence;
- } else {
- NOTREACHED();
- }
-}
-
-String UnionTypesTest::doubleOrStringArg(DoubleOrString& double_or_string) {
- if (double_or_string.IsNull())
- return "null is passed";
- if (double_or_string.IsDouble()) {
- return "double is passed: " +
- String::NumberToStringECMAScript(double_or_string.GetAsDouble());
- }
- if (double_or_string.IsString())
- return "string is passed: " + double_or_string.GetAsString();
- NOTREACHED();
- return String();
-}
-
-String UnionTypesTest::doubleOrInternalEnumArg(
- DoubleOrInternalEnum& double_or_internal_enum) {
- if (double_or_internal_enum.IsDouble()) {
- return "double is passed: " + String::NumberToStringECMAScript(
- double_or_internal_enum.GetAsDouble());
- }
- if (double_or_internal_enum.IsInternalEnum()) {
- return "InternalEnum is passed: " +
- double_or_internal_enum.GetAsInternalEnum();
- }
- NOTREACHED();
- return String();
-}
-
-String UnionTypesTest::doubleOrStringSequenceArg(
- HeapVector<DoubleOrString>& sequence) {
- if (!sequence.size())
- return "";
-
- StringBuilder builder;
- for (DoubleOrString& double_or_string : sequence) {
- DCHECK(!double_or_string.IsNull());
- if (double_or_string.IsDouble()) {
- builder.Append("double: ");
- builder.Append(
- String::NumberToStringECMAScript(double_or_string.GetAsDouble()));
- } else if (double_or_string.IsString()) {
- builder.Append("string: ");
- builder.Append(double_or_string.GetAsString());
- } else {
- NOTREACHED();
- }
- builder.Append(", ");
- }
- return builder.Substring(0, builder.length() - 2);
-}
-
-String UnionTypesTest::nodeListOrElementArg(
- NodeListOrElement& node_list_or_element) {
- DCHECK(!node_list_or_element.IsNull());
- return nodeListOrElementOrNullArg(node_list_or_element);
-}
-
-String UnionTypesTest::nodeListOrElementOrNullArg(
- NodeListOrElement& node_list_or_element_or_null) {
- if (node_list_or_element_or_null.IsNull())
- return "null or undefined is passed";
- if (node_list_or_element_or_null.IsNodeList())
- return "nodelist is passed";
- if (node_list_or_element_or_null.IsElement())
- return "element is passed";
- NOTREACHED();
- return String();
-}
-
-String UnionTypesTest::doubleOrStringOrStringSequenceArg(
- const DoubleOrStringOrStringSequence& double_or_string_or_string_sequence) {
- if (double_or_string_or_string_sequence.IsNull())
- return "null";
-
- if (double_or_string_or_string_sequence.IsDouble()) {
- return "double: " + String::NumberToStringECMAScript(
- double_or_string_or_string_sequence.GetAsDouble());
- }
-
- if (double_or_string_or_string_sequence.IsString())
- return "string: " + double_or_string_or_string_sequence.GetAsString();
-
- DCHECK(double_or_string_or_string_sequence.IsStringSequence());
- const Vector<String>& sequence =
- double_or_string_or_string_sequence.GetAsStringSequence();
- if (!sequence.size())
- return "sequence: []";
- StringBuilder builder;
- builder.Append("sequence: [");
- for (const String& item : sequence) {
- DCHECK(!item.IsNull());
- builder.Append(item);
- builder.Append(", ");
- }
- return builder.Substring(0, builder.length() - 2) + "]";
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/union_types_test.h b/chromium/third_party/blink/renderer/core/testing/union_types_test.h
index fa98653ff79..dcd53f5aadd 100644
--- a/chromium/third_party/blink/renderer/core/testing/union_types_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/union_types_test.h
@@ -5,10 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_UNION_TYPES_TEST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_UNION_TYPES_TEST_H_
-#include "third_party/blink/renderer/bindings/core/v8/double_or_internal_enum.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_string_or_string_sequence.h"
-#include "third_party/blink/renderer/bindings/core/v8/node_list_or_element.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -25,7 +22,6 @@ class UnionTypesTest final : public ScriptWrappable {
UnionTypesTest() = default;
~UnionTypesTest() override = default;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionDoubleOrStringOrStringSequence*
doubleOrStringOrStringSequenceAttribute() const;
void setDoubleOrStringOrStringSequenceAttribute(
@@ -41,27 +37,9 @@ class UnionTypesTest final : public ScriptWrappable {
String doubleOrStringOrStringSequenceArg(
const V8UnionDoubleOrStringOrStringSequence* arg);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void doubleOrStringOrStringSequenceAttribute(DoubleOrStringOrStringSequence&);
- void setDoubleOrStringOrStringSequenceAttribute(
- const DoubleOrStringOrStringSequence&);
-
- String doubleOrStringArg(DoubleOrString&);
- String doubleOrInternalEnumArg(DoubleOrInternalEnum&);
- String doubleOrStringSequenceArg(HeapVector<DoubleOrString>&);
-
- String nodeListOrElementArg(NodeListOrElement&);
- String nodeListOrElementOrNullArg(NodeListOrElement&);
-
- String doubleOrStringOrStringSequenceArg(
- const DoubleOrStringOrStringSequence&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
enum AttributeSpecificType {
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- kSpecificTypeNone,
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
kSpecificTypeDouble,
kSpecificTypeString,
kSpecificTypeStringSequence,
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 f2f6cb7be2b..2fd934c1ca9 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
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/testing/v8/web_core_test_support.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_origin_trials_test.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"
@@ -35,7 +34,6 @@
#include "third_party/blink/renderer/core/testing/internals.h"
#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"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -45,11 +43,6 @@ namespace web_core_test_support {
namespace {
-InstallOriginTrialFeaturesFunction
- s_original_install_origin_trial_features_function = nullptr;
-InstallPendingOriginTrialFeatureFunction
- s_original_install_pending_origin_trial_feature_function = nullptr;
-
v8::Local<v8::Value> CreateInternalsObject(v8::Local<v8::Context> context) {
ScriptState* script_state = ScriptState::From(context);
v8::Local<v8::Object> global = script_state->GetContext()->Global();
@@ -68,8 +61,6 @@ v8::Local<v8::Value> CreateInternalsObject(v8::Local<v8::Context> context) {
} // namespace
void InjectInternalsObject(v8::Local<v8::Context> context) {
- RegisterInstallOriginTrialFeaturesForTesting();
-
ScriptState* script_state = ScriptState::From(context);
ScriptState::Scope scope(script_state);
v8::Local<v8::Object> global = script_state->GetContext()->Global();
@@ -84,52 +75,6 @@ void InjectInternalsObject(v8::Local<v8::Context> context) {
.ToChecked();
}
-void InstallOriginTrialFeaturesForTesting(
- const WrapperTypeInfo* type,
- const ScriptState* script_state,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object) {
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
- (*s_original_install_origin_trial_features_function)(
- type, script_state, prototype_object, interface_object);
-
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
-
- if (type == V8OriginTrialsTest::GetWrapperTypeInfo()) {
- if (RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabled(
- execution_context)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPI(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- if (RuntimeEnabledFeatures::OriginTrialsSampleAPIDeprecationEnabled(
- execution_context)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPIDeprecation(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- if (RuntimeEnabledFeatures::OriginTrialsSampleAPIImpliedEnabled(
- execution_context)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPIImplied(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- if (RuntimeEnabledFeatures::OriginTrialsSampleAPINavigationEnabled(
- execution_context)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPINavigation(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- if (RuntimeEnabledFeatures::OriginTrialsSampleAPIThirdPartyEnabled(
- execution_context)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPIThirdParty(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- }
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-}
-
void ResetInternalsObject(v8::Local<v8::Context> context) {
// This can happen if JavaScript is disabled in the main frame.
if (context.IsEmpty())
@@ -148,89 +93,6 @@ void ResetInternalsObject(v8::Local<v8::Context> context) {
InternalSettings::From(*page)->ResetToConsistentState();
}
-void InstallPendingOriginTrialFeatureForTesting(
- OriginTrialFeature feature,
- const ScriptState* script_state) {
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
- (*s_original_install_pending_origin_trial_feature_function)(feature,
- script_state);
- v8::Local<v8::Object> prototype_object;
- v8::Local<v8::Function> interface_object;
- switch (feature) {
- case OriginTrialFeature::kOriginTrialsSampleAPI: {
- if (script_state->PerContextData()
- ->GetExistingConstructorAndPrototypeForType(
- V8OriginTrialsTest::GetWrapperTypeInfo(), &prototype_object,
- &interface_object)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPI(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- break;
- }
- case OriginTrialFeature::kOriginTrialsSampleAPIDeprecation: {
- if (script_state->PerContextData()
- ->GetExistingConstructorAndPrototypeForType(
- V8OriginTrialsTest::GetWrapperTypeInfo(), &prototype_object,
- &interface_object)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPIDeprecation(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- break;
- }
- case OriginTrialFeature::kOriginTrialsSampleAPIImplied: {
- if (script_state->PerContextData()
- ->GetExistingConstructorAndPrototypeForType(
- V8OriginTrialsTest::GetWrapperTypeInfo(), &prototype_object,
- &interface_object)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPIImplied(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- break;
- }
- case OriginTrialFeature::kOriginTrialsSampleAPINavigation: {
- if (script_state->PerContextData()
- ->GetExistingConstructorAndPrototypeForType(
- V8OriginTrialsTest::GetWrapperTypeInfo(), &prototype_object,
- &interface_object)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPINavigation(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- break;
- }
- case OriginTrialFeature::kOriginTrialsSampleAPIThirdParty: {
- if (script_state->PerContextData()
- ->GetExistingConstructorAndPrototypeForType(
- V8OriginTrialsTest::GetWrapperTypeInfo(), &prototype_object,
- &interface_object)) {
- V8OriginTrialsTest::InstallOriginTrialsSampleAPIThirdParty(
- script_state->GetIsolate(), script_state->World(),
- v8::Local<v8::Object>(), prototype_object, interface_object);
- }
- break;
- }
- default:
- break;
- }
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-}
-
-void RegisterInstallOriginTrialFeaturesForTesting() {
- if (!s_original_install_origin_trial_features_function) {
- s_original_install_origin_trial_features_function =
- SetInstallOriginTrialFeaturesFunction(
- InstallOriginTrialFeaturesForTesting);
- }
- if (!s_original_install_pending_origin_trial_feature_function) {
- s_original_install_pending_origin_trial_feature_function =
- SetInstallPendingOriginTrialFeatureFunction(
- &InstallPendingOriginTrialFeatureForTesting);
- }
-}
-
} // namespace web_core_test_support
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.h b/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.h
index b276e00ee20..2667e7554f5 100644
--- a/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.h
+++ b/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.h
@@ -34,7 +34,6 @@ namespace web_core_test_support {
void InjectInternalsObject(v8::Local<v8::Context>);
void ResetInternalsObject(v8::Local<v8::Context>);
-void RegisterInstallOriginTrialFeaturesForTesting();
} // namespace web_core_test_support
diff --git a/chromium/third_party/blink/renderer/core/timing/background_tracing_helper.cc b/chromium/third_party/blink/renderer/core/timing/background_tracing_helper.cc
index 0202a46217c..319f6562b67 100644
--- a/chromium/third_party/blink/renderer/core/timing/background_tracing_helper.cc
+++ b/chromium/third_party/blink/renderer/core/timing/background_tracing_helper.cc
@@ -4,9 +4,9 @@
#include "third_party/blink/renderer/core/timing/background_tracing_helper.h"
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/hash/md5.h"
-#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "base/trace_event/typed_macros.h"
#include "third_party/blink/public/common/features.h"
@@ -173,17 +173,26 @@ void BackgroundTracingHelper::MaybeEmitBackgroundTracingPerformanceMarkEvent(
if (!mark_hashes_->Contains(mark_hash))
return;
- // Emit the trace event. We emit hashes and strings to facilitate local trace
+ // Emit the trace events. We emit hashes and strings to facilitate local trace
// consumption. However, the strings will be stripped and only the hashes
// shipped externally.
- TRACE_EVENT("blink", "performance.mark", [&](perfetto::EventContext ctx) {
+
+ auto event_lambda = [&](perfetto::EventContext ctx) {
auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
auto* data = event->set_chrome_hashed_performance_mark();
data->set_site_hash(site_hash_);
data->set_site(site_.Ascii());
data->set_mark_hash(mark_hash);
data->set_mark(mark_name_ascii);
- });
+ };
+
+ // For additional context, also emit a paired event marking *when* the
+ // performance.mark was actually created.
+ TRACE_EVENT_INSTANT("blink", "performance.mark.created", event_lambda);
+
+ // Emit an event with the actual timestamp associated with the mark.
+ TRACE_EVENT_INSTANT("blink", "performance.mark", mark.UnsafeTimeForTraces(),
+ event_lambda);
// If this is a slow-reports trigger then fire it.
if (MarkNameIsTrigger(mark_name)) {
diff --git a/chromium/third_party/blink/renderer/core/timing/build.gni b/chromium/third_party/blink/renderer/core/timing/build.gni
index c12d93beb64..c39d5d343c2 100644
--- a/chromium/third_party/blink/renderer/core/timing/build.gni
+++ b/chromium/third_party/blink/renderer/core/timing/build.gni
@@ -39,6 +39,8 @@ blink_core_sources_timing = [
"performance_navigation.h",
"performance_navigation_timing.cc",
"performance_navigation_timing.h",
+ "performance_navigation_timing_activation_start.cc",
+ "performance_navigation_timing_activation_start.h",
"performance_observer.cc",
"performance_observer.h",
"performance_observer_entry_list.cc",
@@ -59,6 +61,8 @@ blink_core_sources_timing = [
"profiler_group.h",
"background_tracing_helper.cc",
"background_tracing_helper.h",
+ "responsiveness_metrics.cc",
+ "responsiveness_metrics.h",
"task_attribution_timing.cc",
"task_attribution_timing.h",
"time_clamper.cc",
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 26be96f656c..bcb8383b6f6 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_DOM_WINDOW_PERFORMANCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_DOM_WINDOW_PERFORMANCE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -25,6 +24,8 @@ class CORE_EXPORT DOMWindowPerformance final
static WindowPerformance* performance(LocalDOMWindow&);
explicit DOMWindowPerformance(LocalDOMWindow&);
+ DOMWindowPerformance(const DOMWindowPerformance&) = delete;
+ DOMWindowPerformance& operator=(const DOMWindowPerformance&) = delete;
void Trace(Visitor*) const override;
@@ -32,7 +33,6 @@ class CORE_EXPORT DOMWindowPerformance final
WindowPerformance* performance();
Member<WindowPerformance> performance_;
- DISALLOW_COPY_AND_ASSIGN(DOMWindowPerformance);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/event_counts.idl b/chromium/third_party/blink/renderer/core/timing/event_counts.idl
index a78ac1fdc8a..9da127ce83c 100644
--- a/chromium/third_party/blink/renderer/core/timing/event_counts.idl
+++ b/chromium/third_party/blink/renderer/core/timing/event_counts.idl
@@ -1,4 +1,4 @@
-[Exposed=Window, RuntimeEnabled=EventTiming]
+[Exposed=Window]
interface EventCounts {
readonly maplike<DOMString, unsigned long long>;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/event_timing.cc b/chromium/third_party/blink/renderer/core/timing/event_timing.cc
index 4f57dcb2401..95143ba9c06 100644
--- a/chromium/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/event_timing.cc
@@ -14,7 +14,6 @@
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
namespace {
@@ -30,17 +29,14 @@ bool ShouldLogEvent(const Event& event) {
event.type() == event_type_names::kPointerup ||
event.type() == event_type_names::kClick ||
event.type() == event_type_names::kKeydown ||
- event.type() == event_type_names::kMousedown;
+ event.type() == event_type_names::kMousedown ||
+ event.type() == event_type_names::kMouseup;
}
bool ShouldReportForEventTiming(WindowPerformance* performance) {
if (!performance->FirstInputDetected())
return true;
- if (!RuntimeEnabledFeatures::EventTimingEnabled(
- performance->GetExecutionContext()))
- return false;
-
return (!performance->IsEventTimingBufferFull() ||
performance->HasObserverFor(PerformanceEntry::kEvent));
}
@@ -48,13 +44,31 @@ bool ShouldReportForEventTiming(WindowPerformance* performance) {
} // namespace
EventTiming::EventTiming(base::TimeTicks processing_start,
- base::TimeTicks event_timestamp,
WindowPerformance* performance,
- bool should_log_event)
+ const Event& event)
: processing_start_(processing_start),
- event_timestamp_(event_timestamp),
performance_(performance),
- should_log_event_(should_log_event) {}
+ event_(&event) {
+ performance_->SetCurrentEventTimingEvent(&event);
+}
+
+// static
+void EventTiming::HandleInputDelay(LocalDOMWindow* window, const Event& event) {
+ auto* pointer_event = DynamicTo<PointerEvent>(&event);
+ base::TimeTicks event_timestamp =
+ pointer_event ? pointer_event->OldestPlatformTimeStamp()
+ : event.PlatformTimeStamp();
+
+ base::TimeTicks processing_start = Now();
+ if (ShouldLogEvent(event) && event.isTrusted()) {
+ InteractiveDetector* interactive_detector =
+ InteractiveDetector::From(*window->document());
+ if (interactive_detector) {
+ interactive_detector->HandleForInputDelay(event, event_timestamp,
+ processing_start);
+ }
+ }
+}
// static
bool EventTiming::IsEventTypeForEventTiming(const Event& event) {
@@ -80,7 +94,16 @@ bool EventTiming::IsEventTypeForEventTiming(const Event& event) {
std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
const Event& event) {
auto* performance = DOMWindowPerformance::performance(*window);
- if (!performance || !IsEventTypeForEventTiming(event))
+ if (!performance || !event.isTrusted() ||
+ (!IsEventTypeForEventTiming(event) &&
+ event.type() != event_type_names::kPointermove))
+ return nullptr;
+
+ // Most events track their performance in EventDispatcher::Dispatch but
+ // some event types which can be filtered are tracked at the point
+ // where they may be filtered. This condition check ensures we don't create
+ // two EventTiming objects for the same Event.
+ if (performance->GetCurrentEventTimingEvent() == &event)
return nullptr;
bool should_report_for_event_timing = ShouldReportForEventTiming(performance);
@@ -89,39 +112,38 @@ std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
if (!should_report_for_event_timing && !should_log_event)
return nullptr;
- auto* pointer_event = DynamicTo<PointerEvent>(&event);
- base::TimeTicks event_timestamp =
- pointer_event ? pointer_event->OldestPlatformTimeStamp()
- : event.PlatformTimeStamp();
-
base::TimeTicks processing_start = Now();
-
- if (should_log_event) {
- InteractiveDetector* interactive_detector =
- InteractiveDetector::From(*window->document());
- if (interactive_detector) {
- interactive_detector->HandleForInputDelay(event, event_timestamp,
- processing_start);
- }
- }
-
return should_report_for_event_timing
- ? std::make_unique<EventTiming>(processing_start, event_timestamp,
- performance, should_log_event)
+ ? std::make_unique<EventTiming>(processing_start, performance,
+ event)
: nullptr;
}
-void EventTiming::DidDispatchEvent(const Event& event, Document& document) {
- Node* target = event.target() ? event.target()->ToNode() : nullptr;
- base::TimeTicks processing_end = Now();
- performance_->RegisterEventTiming(event.type(), event_timestamp_,
- processing_start_, processing_end,
- event.cancelable(), target);
-}
-
// static
void EventTiming::SetTickClockForTesting(const base::TickClock* clock) {
g_clock_for_testing = clock;
}
+EventTiming::~EventTiming() {
+ absl::optional<int> key_code = absl::nullopt;
+ if (event_->IsKeyboardEvent())
+ key_code = DynamicTo<KeyboardEvent>(event_.Get())->keyCode();
+
+ absl::optional<PointerId> pointer_id = absl::nullopt;
+ const PointerEvent* pointer_event = DynamicTo<PointerEvent>(event_.Get());
+ if (pointer_event)
+ pointer_id = pointer_event->pointerId();
+
+ base::TimeTicks event_timestamp =
+ pointer_event ? pointer_event->OldestPlatformTimeStamp()
+ : event_->PlatformTimeStamp();
+
+ // Register Event Timing for the event.
+ performance_->RegisterEventTiming(
+ event_->type(), event_timestamp, processing_start_, Now(),
+ event_->cancelable(),
+ event_->target() ? event_->target()->ToNode() : nullptr, key_code,
+ pointer_id);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/event_timing.h b/chromium/third_party/blink/renderer/core/timing/event_timing.h
index aa83fd3097c..59a8627d92f 100644
--- a/chromium/third_party/blink/renderer/core/timing/event_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/event_timing.h
@@ -26,16 +26,19 @@ class CORE_EXPORT EventTiming final {
// Processes an event that will be dispatched. Notifies the
// InteractiveDetector if it needs to be logged into input delay histograms.
// Returns an object only if the event is relevant for the EventTiming API.
+ // This object should be constructed before the event is dispatched and
+ // destructed after dispatch so that we can calculate the input delay and
+ // other latency values correctly.
static std::unique_ptr<EventTiming> Create(LocalDOMWindow*, const Event&);
explicit EventTiming(base::TimeTicks processing_start,
- base::TimeTicks event_timestamp,
WindowPerformance* performance,
- bool should_log);
-
- // Notifies the Performance object that the event has been dispatched.
- void DidDispatchEvent(const Event&, Document& document);
+ const Event& event);
+ ~EventTiming();
+ EventTiming(const EventTiming&) = delete;
+ EventTiming& operator=(const EventTiming&) = delete;
+ static void HandleInputDelay(LocalDOMWindow* window, const Event& event);
// The caller owns the |clock| which must outlive the EventTiming.
static void SetTickClockForTesting(const base::TickClock* clock);
@@ -50,9 +53,7 @@ class CORE_EXPORT EventTiming final {
Persistent<WindowPerformance> performance_;
- bool should_log_event_;
-
- DISALLOW_COPY_AND_ASSIGN(EventTiming);
+ Persistent<const Event> event_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc
index 66a0568caf0..79ce17f9aaa 100644
--- a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc
+++ b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc
@@ -11,7 +11,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_attribution.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_attribution_container.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_breakdown_entry.h"
@@ -46,6 +46,7 @@ namespace {
// String constants used for building the result.
constexpr const char* kCrossOriginUrl = "cross-origin-url";
+constexpr const char* kMemoryTypeCanvas = "Canvas";
constexpr const char* kMemoryTypeDom = "DOM";
constexpr const char* kMemoryTypeJavaScript = "JavaScript";
constexpr const char* kMemoryTypeShared = "Shared";
@@ -184,7 +185,6 @@ ScriptPromise MeasureMemoryController::StartMeasurement(
return ScriptPromise(script_state, promise_resolver->GetPromise());
}
-
namespace {
// Satisfies the requirements of UniformRandomBitGenerator from C++ standard.
@@ -237,11 +237,13 @@ MemoryAttribution* ConvertAttribution(
result->setUrl(kCrossOriginUrl);
}
result->setScope(ConvertScope(attribution->scope));
- result->setContainer(ConvertContainer(attribution));
+ if (auto* container = ConvertContainer(attribution)) {
+ result->setContainer(container);
+ }
return result;
}
-MemoryBreakdownEntry* ConvertBreakdown(
+MemoryBreakdownEntry* ConvertJavaScriptBreakdown(
const WebMemoryBreakdownEntryPtr& breakdown_entry) {
auto* result = MemoryBreakdownEntry::Create();
DCHECK(breakdown_entry->memory);
@@ -255,6 +257,20 @@ MemoryBreakdownEntry* ConvertBreakdown(
return result;
}
+MemoryBreakdownEntry* ConvertCanvasBreakdown(
+ const WebMemoryBreakdownEntryPtr& breakdown_entry) {
+ auto* result = MemoryBreakdownEntry::Create();
+ DCHECK(breakdown_entry->canvas_memory);
+ result->setBytes(breakdown_entry->canvas_memory->bytes);
+ HeapVector<Member<MemoryAttribution>> attribution;
+ for (const auto& entry : breakdown_entry->attribution) {
+ attribution.push_back(ConvertAttribution(entry));
+ }
+ result->setAttribution(attribution);
+ result->setTypes({WTF::AtomicString(kMemoryTypeCanvas)});
+ return result;
+}
+
MemoryBreakdownEntry* CreateUnattributedBreakdown(
const WebMemoryUsagePtr& memory,
const WTF::String& memory_type) {
@@ -280,8 +296,13 @@ MemoryMeasurement* ConvertResult(const WebMemoryMeasurementPtr& measurement) {
HeapVector<Member<MemoryBreakdownEntry>> breakdown;
for (const auto& entry : measurement->breakdown) {
// Skip breakdowns that didn't get a measurement.
- if (entry->memory)
- breakdown.push_back(ConvertBreakdown(entry));
+ if (entry->memory) {
+ breakdown.push_back(ConvertJavaScriptBreakdown(entry));
+ }
+ // Skip breakdowns that didn't get a measurement.
+ if (entry->canvas_memory) {
+ breakdown.push_back(ConvertCanvasBreakdown(entry));
+ }
}
// Add breakdowns for memory that isn't attributed to an execution context.
breakdown.push_back(CreateUnattributedBreakdown(measurement->shared_memory,
@@ -369,14 +390,16 @@ void MeasureMemoryController::MeasurementComplete(
}
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::Context> context = context_.NewLocal(isolate_);
+ ScriptState* script_state = ScriptState::From(context);
v8::Context::Scope context_scope(context);
v8::MicrotasksScope microtasks_scope(
isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
- auto* result = ConvertResult(measurement);
+ MemoryMeasurement* result = ConvertResult(measurement);
v8::Local<v8::Promise::Resolver> promise_resolver =
promise_resolver_.NewLocal(isolate_);
- promise_resolver->Resolve(context, ToV8(result, promise_resolver, isolate_))
- .ToChecked();
+ v8::MaybeLocal<v8::Value> v8_result =
+ ToV8Traits<MemoryMeasurement>::ToV8(script_state, result);
+ promise_resolver->Resolve(context, v8_result.ToLocalChecked()).ToChecked();
promise_resolver_.Clear();
RecordWebMemoryUkm(context, measurement);
}
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 9f8a31e1883..99df56a0dd5 100644
--- a/chromium/third_party/blink/renderer/core/timing/memory_info.cc
+++ b/chromium/third_party/blink/renderer/core/timing/memory_info.cc
@@ -32,7 +32,6 @@
#include <limits>
-#include "base/macros.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -63,6 +62,8 @@ class HeapSizeCache {
public:
HeapSizeCache() : clock_(base::DefaultTickClock::GetInstance()) {}
+ HeapSizeCache(const HeapSizeCache&) = delete;
+ HeapSizeCache& operator=(const HeapSizeCache&) = delete;
void GetCachedHeapSize(HeapInfo& info, MemoryInfo::Precision precision) {
MaybeUpdate(precision);
@@ -109,7 +110,6 @@ class HeapSizeCache {
const base::TickClock* clock_;
HeapInfo info_;
- DISALLOW_COPY_AND_ASSIGN(HeapSizeCache);
};
// We quantize the sizes to make it more difficult for an attacker to see
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.cc b/chromium/third_party/blink/renderer/core/timing/performance.cc
index cc63f8a3bae..a262da3c512 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance.cc
@@ -43,7 +43,6 @@
#include "third_party/blink/public/platform/platform.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/string_or_performance_measure_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_mark_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_measure_options.h"
@@ -83,7 +82,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.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/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "v8/include/v8-metrics.h"
@@ -92,6 +90,10 @@ namespace blink {
namespace {
+// LongTask API can be a source of many events. Filter on Performance object
+// level before reporting to UKM to smooth out recorded events over all pages.
+constexpr size_t kLongTaskUkmSampleInterval = 100;
+
const SecurityOrigin* GetSecurityOrigin(ExecutionContext* context) {
if (context)
return context->GetSecurityOrigin();
@@ -129,32 +131,6 @@ void RecordLongTaskUkm(ExecutionContext* execution_context,
.Record(execution_context->UkmRecorder());
}
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-V8UnionPerformanceMeasureOptionsOrString*
-StringOrPerformanceMeasureOptionsToNewV8Union(
- const StringOrPerformanceMeasureOptions& value) {
- if (value.IsString()) {
- return MakeGarbageCollected<V8UnionPerformanceMeasureOptionsOrString>(
- value.GetAsString());
- }
- if (value.IsPerformanceMeasureOptions()) {
- return MakeGarbageCollected<V8UnionPerformanceMeasureOptionsOrString>(
- value.GetAsPerformanceMeasureOptions());
- }
- return nullptr;
-}
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-// TODO(crbug.com/1181288): Remove the old IDL union version.
-V8UnionDoubleOrString* StringOrDoubleToV8UnionDoubleOrString(
- const StringOrDouble& value) {
- if (value.IsString())
- return MakeGarbageCollected<V8UnionDoubleOrString>(value.GetAsString());
- if (value.IsDouble())
- return MakeGarbageCollected<V8UnionDoubleOrString>(value.GetAsDouble());
- return nullptr;
-}
-
} // namespace
using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>;
@@ -704,7 +680,6 @@ void Performance::AddElementTimingBuffer(PerformanceElementTiming& entry) {
}
void Performance::AddEventTimingBuffer(PerformanceEventTiming& entry) {
- DCHECK(RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext()));
if (!IsEventTimingBufferFull()) {
event_timing_buffer_.push_back(&entry);
}
@@ -772,9 +747,12 @@ void Performance::AddLongTaskTiming(base::TimeTicks start_time,
} else {
UseCounter::Count(execution_context, WebFeature::kLongTaskBufferFull);
}
- RecordLongTaskUkm(execution_context,
- base::TimeDelta::FromMillisecondsD(dom_high_res_start_time),
- end_time - start_time);
+ if ((++long_task_counter_ % kLongTaskUkmSampleInterval) == 0) {
+ RecordLongTaskUkm(
+ execution_context,
+ base::TimeDelta::FromMillisecondsD(dom_high_res_start_time),
+ end_time - start_time);
+ }
NotifyObserversOfEntry(*entry);
}
@@ -788,12 +766,12 @@ PerformanceMark* Performance::mark(ScriptState* script_state,
const AtomicString& mark_name,
PerformanceMarkOptions* mark_options,
ExceptionState& exception_state) {
- DEFINE_STATIC_LOCAL(const AtomicString, mark_fully_loaded,
- ("mark_fully_loaded"));
- DEFINE_STATIC_LOCAL(const AtomicString, mark_fully_visible,
- ("mark_fully_visible"));
- DEFINE_STATIC_LOCAL(const AtomicString, mark_interactive,
- ("mark_interactive"));
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(const AtomicString, mark_fully_loaded,
+ ("mark_fully_loaded"));
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(const AtomicString, mark_fully_visible,
+ ("mark_fully_visible"));
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(const AtomicString, mark_interactive,
+ ("mark_interactive"));
if (mark_options &&
(mark_options->hasStartTime() || mark_options->hasDetail())) {
UseCounter::Count(GetExecutionContext(), WebFeature::kUserTimingL3);
@@ -850,7 +828,6 @@ PerformanceMeasure* Performance::measure(ScriptState* script_state,
exception_state);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
PerformanceMeasure* Performance::measure(
ScriptState* script_state,
const AtomicString& measure_name,
@@ -859,20 +836,7 @@ PerformanceMeasure* Performance::measure(
return MeasureInternal(script_state, measure_name, start_or_options,
absl::nullopt, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-PerformanceMeasure* Performance::measure(
- ScriptState* script_state,
- const AtomicString& measure_name,
- const StringOrPerformanceMeasureOptions& start_or_options,
- ExceptionState& exception_state) {
- return MeasureInternal(
- script_state, measure_name,
- StringOrPerformanceMeasureOptionsToNewV8Union(start_or_options),
- absl::nullopt, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
PerformanceMeasure* Performance::measure(
ScriptState* script_state,
const AtomicString& measure_name,
@@ -882,19 +846,6 @@ PerformanceMeasure* Performance::measure(
return MeasureInternal(script_state, measure_name, start_or_options,
absl::optional<String>(end), exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-PerformanceMeasure* Performance::measure(
- ScriptState* script_state,
- const AtomicString& measure_name,
- const StringOrPerformanceMeasureOptions& start_or_options,
- const String& end,
- ExceptionState& exception_state) {
- return MeasureInternal(
- script_state, measure_name,
- StringOrPerformanceMeasureOptionsToNewV8Union(start_or_options),
- absl::optional<String>(end), exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// |MeasureInternal| exists to unify the arguments from different
// `performance.measure()` overloads into a consistent form, then delegate to
@@ -947,18 +898,12 @@ PerformanceMeasure* Performance::MeasureInternal(
return nullptr;
}
- V8UnionDoubleOrString* start = nullptr;
- if (options->hasStart()) {
- start = StringOrDoubleToV8UnionDoubleOrString(options->start());
- }
+ V8UnionDoubleOrString* start = options->getStartOr(nullptr);
absl::optional<double> duration;
if (options->hasDuration()) {
duration = options->duration();
}
- V8UnionDoubleOrString* end = nullptr;
- if (options->hasEnd()) {
- end = StringOrDoubleToV8UnionDoubleOrString(options->end());
- }
+ V8UnionDoubleOrString* end = options->getEndOr(nullptr);
return MeasureWithDetail(
script_state, measure_name, start, duration, end,
@@ -1004,34 +949,6 @@ void Performance::clearMeasures(const AtomicString& measure_name) {
GetUserTiming().ClearMeasures(measure_name);
}
-ScriptPromise Performance::profile(ScriptState* script_state,
- const ProfilerInitOptions* options,
- ExceptionState& exception_state) {
- auto* execution_context = ExecutionContext::From(script_state);
- DCHECK(execution_context);
- DCHECK(
- RuntimeEnabledFeatures::ExperimentalJSProfilerEnabled(execution_context));
-
- bool can_profile = false;
- if (LocalDOMWindow* window = LocalDOMWindow::From(script_state)) {
- can_profile = ProfilerGroup::CanProfile(window, &exception_state,
- ReportOptions::kReportOnFailure);
- }
-
- if (!can_profile)
- return ScriptPromise();
-
- auto* profiler_group = ProfilerGroup::From(script_state->GetIsolate());
- DCHECK(profiler_group);
-
- auto* profiler = profiler_group->CreateProfiler(
- script_state, *options, time_origin_, exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
-
- return ScriptPromise::Cast(script_state, ToV8(profiler, script_state));
-}
-
void Performance::RegisterPerformanceObserver(PerformanceObserver& observer) {
observer_filter_options_ |= observer.FilterOptions();
observers_.insert(&observer);
@@ -1051,8 +968,6 @@ void Performance::UpdatePerformanceObserverFilterOptions() {
}
void Performance::NotifyObserversOfEntry(PerformanceEntry& entry) const {
- DCHECK(entry.EntryTypeEnum() != PerformanceEntry::kEvent ||
- RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext()));
bool observer_found = false;
for (auto& observer : observers_) {
if (observer->FilterOptions() & entry.EntryTypeEnum() &&
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.h b/chromium/third_party/blink/renderer/core/timing/performance.h
index a3c9924825b..32c9894e3d8 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance.h
@@ -34,7 +34,6 @@
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_double.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/core/dom/events/event_target.h"
@@ -73,14 +72,12 @@ class PerformanceMeasure;
class PerformanceNavigation;
class PerformanceObserver;
class PerformanceTiming;
-class ProfilerInitOptions;
class ResourceResponse;
class ResourceTimingInfo;
class ScriptPromise;
class ScriptState;
class ScriptValue;
class SecurityOrigin;
-class StringOrPerformanceMeasureOptions;
class UserTiming;
class V8ObjectBuilder;
class V8UnionDoubleOrString;
@@ -145,9 +142,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
DOMHighResTimeStamp timeOrigin() const;
// Internal getter method for the time origin value.
- double GetTimeOrigin() const {
- return time_origin_.since_origin().InSecondsF();
- }
+ base::TimeTicks GetTimeOriginInternal() const { return time_origin_; }
PerformanceEntryVector getEntries();
// Get BufferedEntriesByType will return all entries in the buffer regardless
@@ -268,43 +263,22 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
const AtomicString& measure_name,
ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
PerformanceMeasure* measure(
ScriptState* script_state,
const AtomicString& measure_name,
const V8UnionPerformanceMeasureOptionsOrString* start_or_options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- PerformanceMeasure* measure(
- ScriptState*,
- const AtomicString& measure_name,
- const StringOrPerformanceMeasureOptions& start_or_options,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
PerformanceMeasure* measure(
ScriptState* script_state,
const AtomicString& measure_name,
const V8UnionPerformanceMeasureOptionsOrString* start_or_options,
const String& end,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- PerformanceMeasure* measure(
- ScriptState*,
- const AtomicString& measure_name,
- const StringOrPerformanceMeasureOptions& start_or_options,
- const String& end,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void clearMeasures(const AtomicString& measure_name);
void clearMeasures() { return clearMeasures(AtomicString()); }
- ScriptPromise profile(ScriptState*,
- const ProfilerInitOptions*,
- ExceptionState&);
-
void UnregisterPerformanceObserver(PerformanceObserver&);
void RegisterPerformanceObserver(PerformanceObserver&);
void UpdatePerformanceObserverFilterOptions();
@@ -431,6 +405,9 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
// See crbug.com/1181774.
Member<BackgroundTracingHelper> background_tracing_helper_;
+
+ // Running counter for LongTask observations.
+ size_t long_task_counter_ = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.idl b/chromium/third_party/blink/renderer/core/timing/performance.idl
index 7088dff953c..c5d098ae474 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance.idl
@@ -71,12 +71,8 @@ interface Performance : EventTarget {
// a dedicated worker is included in the result of the API call in Window.
[MeasureAs=MeasureMemory, Exposed=(Window,ServiceWorker,SharedWorker), CallWith=ScriptState, RuntimeEnabled=MeasureMemory, RaisesException, CrossOriginIsolated] Promise<MemoryMeasurement> measureUserAgentSpecificMemory();
- // JS Self-Profiling API
- // https://github.com/WICG/js-self-profiling/
- [MeasureAs=JSSelfProfiling, CallWith=ScriptState, RuntimeEnabled=ExperimentalJSProfiler, RaisesException] Promise<Profiler> profile(ProfilerInitOptions options);
-
// Event Timing
- [Exposed=Window, SameObject, SaveSameObject, RuntimeEnabled=EventTiming] readonly attribute EventCounts eventCounts;
+ [Exposed=Window, SameObject, SaveSameObject] readonly attribute EventCounts eventCounts;
[CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl
index 17b3db120b1..68cef848abc 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl
@@ -8,7 +8,7 @@ interface PerformanceEventTiming : PerformanceEntry {
readonly attribute DOMHighResTimeStamp processingStart;
readonly attribute DOMHighResTimeStamp processingEnd;
readonly attribute boolean cancelable;
- [RuntimeEnabled=EventTiming] readonly attribute Node? target;
+ readonly attribute Node? target;
[CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
};
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 487e2f98a69..30ec9b574f0 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -58,8 +58,8 @@ PerformanceMark* PerformanceMark::Create(ScriptState* script_state,
// GetTimeOrigin() returns seconds from the monotonic clock's origin..
// Trace events timestamps accept seconds (as a double) based on
// CurrentTime::monotonicallyIncreasingTime().
- unsafe_start_for_traces = trace_event::ToTraceTimestamp(
- performance->GetTimeOrigin() + start / 1000.0);
+ unsafe_start_for_traces = performance->GetTimeOriginInternal() +
+ base::TimeDelta::FromMillisecondsD(start);
} else {
start = performance->now();
unsafe_start_for_traces = base::TimeTicks::Now();
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 fa42819274c..67ee52f97be 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
@@ -13,7 +13,9 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/performance_entry_names.h"
#include "third_party/blink/renderer/core/timing/performance.h"
+#include "third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.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/weborigin/kurl.h"
namespace blink {
@@ -318,5 +320,12 @@ void PerformanceNavigationTiming::BuildJSONValue(
builder.AddNumber("loadEventEnd", loadEventEnd());
builder.AddString("type", type());
builder.AddNumber("redirectCount", redirectCount());
+
+ if (RuntimeEnabledFeatures::Prerender2Enabled(
+ ExecutionContext::From(builder.GetScriptState()))) {
+ builder.AddNumber(
+ "activationStart",
+ PerformanceNavigationTimingActivationStart::activationStart(*this));
+ }
}
} // namespace blink
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 1c5f76ef0b1..ca71acbeef2 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
@@ -69,6 +69,8 @@ class CORE_EXPORT PerformanceNavigationTiming final
void BuildJSONValue(V8ObjectBuilder&) const override;
private:
+ friend class PerformanceNavigationTimingActivationStart;
+
static AtomicString GetNavigationType(WebNavigationType, const Document*);
const DocumentTiming* GetDocumentTiming() const;
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc
new file mode 100644
index 00000000000..504088e7d71
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h"
+
+#include "third_party/blink/renderer/core/loader/document_load_timing.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
+
+namespace blink {
+
+// static
+DOMHighResTimeStamp PerformanceNavigationTimingActivationStart::activationStart(
+ const PerformanceNavigationTiming& performance_navigation_timing) {
+ DocumentLoadTiming* timing =
+ performance_navigation_timing.GetDocumentLoadTiming();
+ if (!timing)
+ return 0.0;
+ return Performance::MonotonicTimeToDOMHighResTimeStamp(
+ performance_navigation_timing.TimeOrigin(), timing->ActivationStart(),
+ false /* allow_negative_value */,
+ performance_navigation_timing.CrossOriginIsolatedCapability());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h
new file mode 100644
index 00000000000..c42f599967c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_ACTIVATION_START_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_ACTIVATION_START_H_
+
+#include "third_party/blink/renderer/core/timing/performance_navigation_timing.h"
+
+namespace blink {
+
+class PerformanceNavigationTimingActivationStart final {
+ public:
+ static DOMHighResTimeStamp activationStart(
+ const PerformanceNavigationTiming& performance_navigation_timing);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_ACTIVATION_START_H_
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl
new file mode 100644
index 00000000000..62f799de902
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://jeremyroman.github.io/alternate-loading-modes/#performance-navigation-timing-extension
+[
+ ImplementedAs=PerformanceNavigationTimingActivationStart,
+ RuntimeEnabled=Prerender2
+] partial interface PerformanceNavigationTiming {
+ readonly attribute DOMHighResTimeStamp activationStart;
+}; \ No newline at end of file
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 60a2ac86d78..bbff4d6bd3c 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
@@ -59,8 +59,7 @@ Vector<AtomicString> PerformanceObserver::supportedEntryTypes(
auto* execution_context = ExecutionContext::From(script_state);
if (execution_context->IsWindow()) {
supportedEntryTypes.push_back(performance_entry_names::kElement);
- if (RuntimeEnabledFeatures::EventTimingEnabled(execution_context))
- supportedEntryTypes.push_back(performance_entry_names::kEvent);
+ supportedEntryTypes.push_back(performance_entry_names::kEvent);
supportedEntryTypes.push_back(performance_entry_names::kFirstInput);
supportedEntryTypes.push_back(
performance_entry_names::kLargestContentfulPaint);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl b/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl
index f4169cd8cfa..ee124eae41a 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl
@@ -8,5 +8,5 @@ dictionary PerformanceObserverInit {
sequence<DOMString> entryTypes;
DOMString type;
boolean buffered = false;
- [RuntimeEnabled=EventTiming] DOMHighResTimeStamp durationThreshold;
+ DOMHighResTimeStamp durationThreshold;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_test.cc b/chromium/third_party/blink/renderer/core/timing/performance_test.cc
index 6555f4e7b06..09efdb6cc7c 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_test.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_test.cc
@@ -7,8 +7,6 @@
#include "base/test/metrics/histogram_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_double.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_performance_measure_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_observer_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_observer_init.h"
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 78383485335..7a3716503a7 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
@@ -63,7 +63,8 @@ static uint64_t ToIntegerMilliseconds(base::TimeDelta duration,
PerformanceTiming::PerformanceTiming(ExecutionContext* context)
: ExecutionContextClient(context) {
- cross_origin_isolated_capability_ = context->CrossOriginIsolatedCapability();
+ cross_origin_isolated_capability_ =
+ context && context->CrossOriginIsolatedCapability();
}
uint64_t PerformanceTiming::navigationStart() const {
@@ -354,12 +355,12 @@ PerformanceTiming::BackForwardCacheRestore() const {
WTF::Vector<BackForwardCacheRestoreTiming> restore_timings(
navigation_starts.size());
- for (size_t i = 0; i < restore_timings.size(); i++) {
+ for (wtf_size_t i = 0; i < restore_timings.size(); i++) {
restore_timings[i].navigation_start =
MonotonicTimeToIntegerMilliseconds(navigation_starts[i]);
restore_timings[i].first_paint =
MonotonicTimeToIntegerMilliseconds(first_paints[i]);
- for (size_t j = 0; j < request_animation_frames[i].size(); j++) {
+ for (wtf_size_t j = 0; j < request_animation_frames[i].size(); j++) {
restore_timings[i].request_animation_frames[j] =
MonotonicTimeToIntegerMilliseconds(request_animation_frames[i][j]);
}
@@ -639,6 +640,19 @@ absl::optional<base::TimeTicks> PerformanceTiming::LastPortalActivatedPaint()
return timing->LastPortalActivatedPaint();
}
+absl::optional<base::TimeDelta> PerformanceTiming::PrerenderActivationStart()
+ const {
+ DocumentLoadTiming* timing = GetDocumentLoadTiming();
+ if (!timing)
+ return absl::nullopt;
+
+ base::TimeTicks activation_start = timing->ActivationStart();
+ if (activation_start.is_null())
+ return absl::nullopt;
+
+ return timing->MonotonicTimeToZeroBasedDocumentTime(activation_start);
+}
+
absl::optional<base::TimeTicks> PerformanceTiming::UnloadStart() const {
DocumentLoadTiming* timing = GetDocumentLoadTiming();
if (!timing)
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 484844bc784..a5c7172ae0a 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_timing.h
@@ -196,6 +196,8 @@ class CORE_EXPORT PerformanceTiming final : public ScriptWrappable,
// The time of the first paint after a portal activation.
absl::optional<base::TimeTicks> LastPortalActivatedPaint() const;
+ // The start time of the prerender activation navigation.
+ absl::optional<base::TimeDelta> PrerenderActivationStart() const;
typedef uint64_t (PerformanceTiming::*PerformanceTimingGetter)() const;
using NameToAttributeMap = HashMap<AtomicString, PerformanceTimingGetter>;
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 2bf5070bc21..887e3330450 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
@@ -109,7 +109,8 @@ double UserTiming::FindExistingMarkStartTime(const AtomicString& mark_name,
}
PerformanceTiming::PerformanceTimingGetter timing_function =
- PerformanceTiming::GetAttributeMapping().at(mark_name);
+ PerformanceTiming::GetAttributeMapping().DeprecatedAtOrEmptyValue(
+ mark_name);
if (!timing_function) {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
@@ -176,15 +177,8 @@ base::TimeTicks UserTiming::GetPerformanceMarkUnsafeTimeForTraces(
return mark->UnsafeTimeForTraces();
}
}
-
- // User timing events are stored as integer milliseconds from the start of
- // navigation.
- // GetTimeOrigin() returns seconds from the monotonic clock's origin..
- // Trace events timestamps accept seconds (as a double) based on
- // CurrentTime::monotonicallyIncreasingTime().
- double start_time_in_seconds = start_time / 1000.0;
- return trace_event::ToTraceTimestamp(performance_->GetTimeOrigin() +
- start_time_in_seconds);
+ return performance_->GetTimeOriginInternal() +
+ base::TimeDelta::FromMillisecondsD(start_time);
}
PerformanceMeasure* UserTiming::Measure(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h
index c4a983f6e2c..2ed451c7f3a 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_USER_TIMING_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_USER_TIMING_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/core/timing/performance_timing.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler.cc b/chromium/third_party/blink/renderer/core/timing/profiler.cc
index a48c173fa73..0bee7aedb0b 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler.cc
+++ b/chromium/third_party/blink/renderer/core/timing/profiler.cc
@@ -6,15 +6,52 @@
#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_dom_window.h"
+#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/profiler_group.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
namespace blink {
+Profiler* Profiler::Create(ScriptState* script_state,
+ const ProfilerInitOptions* options,
+ ExceptionState& exception_state) {
+ auto* execution_context = ExecutionContext::From(script_state);
+ DCHECK(execution_context);
+ DCHECK(
+ RuntimeEnabledFeatures::ExperimentalJSProfilerEnabled(execution_context));
+
+ Performance* performance = nullptr;
+ bool can_profile = false;
+ if (LocalDOMWindow* window = LocalDOMWindow::From(script_state)) {
+ can_profile = ProfilerGroup::CanProfile(window, &exception_state,
+ ReportOptions::kReportOnFailure);
+ performance = DOMWindowPerformance::performance(*window);
+ }
+
+ if (!can_profile) {
+ DCHECK(exception_state.HadException());
+ return nullptr;
+ }
+
+ DCHECK(performance);
+
+ auto* profiler_group = ProfilerGroup::From(script_state->GetIsolate());
+ DCHECK(profiler_group);
+
+ auto* profiler = profiler_group->CreateProfiler(
+ script_state, *options, performance->GetTimeOriginInternal(),
+ exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+
+ return profiler;
+}
+
void Profiler::Trace(Visitor* visitor) const {
visitor->Trace(profiler_group_);
visitor->Trace(script_state_);
- ScriptWrappable::Trace(visitor);
+ EventTargetWithInlineData::Trace(visitor);
}
void Profiler::DisposeAsync() {
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler.h b/chromium/third_party/blink/renderer/core/timing/profiler.h
index b5e9074a052..da8590ca532 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler.h
+++ b/chromium/third_party/blink/renderer/core/timing/profiler.h
@@ -19,7 +19,9 @@
namespace blink {
+class ExceptionState;
class ScriptState;
+class ProfilerInitOptions;
// A web-exposed JS sampling profiler created via blink::ProfilerGroup,
// wrapping a handle to v8::CpuProfiler. Records samples periodically from the
@@ -44,6 +46,10 @@ class CORE_EXPORT Profiler final : public EventTargetWithInlineData {
~Profiler() override = default;
+ static Profiler* Create(ScriptState*,
+ const ProfilerInitOptions*,
+ ExceptionState&);
+
void Trace(Visitor* visitor) const override;
void DisposeAsync();
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler.idl b/chromium/third_party/blink/renderer/core/timing/profiler.idl
index 4ffdc531ad7..649f08798aa 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler.idl
+++ b/chromium/third_party/blink/renderer/core/timing/profiler.idl
@@ -3,9 +3,11 @@
// found in the LICENSE file.
// https://wicg.github.io/js-self-profiling/#the-profiler-interface
-[Exposed=(Window,Worker), RuntimeEnabled=ExperimentalJSProfiler]
+[Exposed=Window, RuntimeEnabled=ExperimentalJSProfiler]
interface Profiler : EventTarget {
readonly attribute DOMHighResTimeStamp sampleInterval;
readonly attribute boolean stopped;
+
+ [MeasureAs=JSSelfProfiling, CallWith=ScriptState, RaisesException] constructor(ProfilerInitOptions options);
[CallWith=ScriptState] Promise<ProfilerTrace> stop();
};
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler_group.cc b/chromium/third_party/blink/renderer/core/timing/profiler_group.cc
index d404c852317..090068ee1dc 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler_group.cc
+++ b/chromium/third_party/blink/renderer/core/timing/profiler_group.cc
@@ -80,18 +80,6 @@ bool ProfilerGroup::CanProfile(LocalDOMWindow* local_window,
return false;
}
- // Bypass COOP/COEP checks when the |--disable-web-security| flag is present.
- auto* local_frame = local_window->GetFrame();
- DCHECK(local_frame);
- if (local_frame->GetSettings()->GetWebSecurityEnabled() &&
- !local_window->CrossOriginIsolatedCapability()) {
- if (exception_state) {
- exception_state->ThrowSecurityError(
- "performance.profile() requires COOP+COEP (web.dev/coop-coep)");
- }
- return false;
- }
-
return true;
}
@@ -182,9 +170,7 @@ Profiler* ProfilerGroup::CreateProfiler(ScriptState* script_state,
String profiler_id = NextProfilerId();
v8::CpuProfilingOptions options(
- v8::kLeafNodeLineNumbers,
- init_options.hasMaxBufferSize() ? init_options.maxBufferSize()
- : v8::CpuProfilingOptions::kNoSampleLimit,
+ v8::kLeafNodeLineNumbers, init_options.maxBufferSize(),
static_cast<int>(sample_interval_us), script_state->GetContext());
v8::CpuProfilingStatus status = cpu_profiler_->StartProfiling(
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler_group.h b/chromium/third_party/blink/renderer/core/timing/profiler_group.h
index 5b91224cc64..d673d0d6ec6 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler_group.h
+++ b/chromium/third_party/blink/renderer/core/timing/profiler_group.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PROFILER_GROUP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PROFILER_GROUP_H_
-#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
@@ -47,6 +46,8 @@ class CORE_EXPORT ProfilerGroup
static base::TimeDelta GetBaseSampleInterval();
ProfilerGroup(v8::Isolate* isolate);
+ ProfilerGroup(const ProfilerGroup&) = delete;
+ ProfilerGroup& operator=(const ProfilerGroup&) = delete;
~ProfilerGroup() override;
Profiler* CreateProfiler(ScriptState* script_state,
@@ -93,8 +94,6 @@ class CORE_EXPORT ProfilerGroup
// A set of observers, one for each ExecutionContext that has profiling
// enabled.
HeapHashSet<Member<ProfilingContextObserver>> context_observers_;
-
- DISALLOW_COPY_AND_ASSIGN(ProfilerGroup);
};
class DiscardedSamplesDelegate : public v8::DiscardedSamplesDelegate {
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler_init_options.idl b/chromium/third_party/blink/renderer/core/timing/profiler_init_options.idl
index a9f2ab00498..e904e48c9b9 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler_init_options.idl
+++ b/chromium/third_party/blink/renderer/core/timing/profiler_init_options.idl
@@ -5,5 +5,5 @@
// https://wicg.github.io/js-self-profiling/#dom-profilerinitoptions
dictionary ProfilerInitOptions {
required DOMHighResTimeStamp sampleInterval;
- unsigned long maxBufferSize;
+ required unsigned long maxBufferSize;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.cc b/chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.cc
new file mode 100644
index 00000000000..7b638a1650d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.cc
@@ -0,0 +1,204 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/timing/responsiveness_metrics.h"
+
+#include "base/rand_util.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+
+namespace blink {
+
+namespace {
+// Minimum potentially generated value for UKM sampling.
+constexpr int kMinValueForSampling = 1;
+// Maximum potentially generated value for UKM sampling.
+constexpr int kMaxValueForSampling = 100;
+// UKM sampling rate. The sampling strategy is 1/N.
+constexpr int kUkmSamplingRate = 10;
+
+base::TimeDelta MaxEventDuration(
+ WTF::Vector<ResponsivenessMetrics::EventTimestamps> timestamps) {
+ base::TimeDelta max_duration =
+ timestamps[0].end_time - timestamps[0].start_time;
+ for (WTF::wtf_size_t i = 1; i < timestamps.size(); ++i) {
+ max_duration = std::max(max_duration,
+ timestamps[i].end_time - timestamps[i].start_time);
+ }
+ return max_duration;
+}
+
+base::TimeDelta TotalEventDuration(
+ // timestamps is sorted by the start_time of EventTimestamps.
+ WTF::Vector<ResponsivenessMetrics::EventTimestamps> timestamps) {
+ // TODO(crbug.com/1229668): Once the event timestamp bug is fixed, add a
+ // DCHECK(IsSorted) here.
+ base::TimeDelta total_duration =
+ timestamps[0].end_time - timestamps[0].start_time;
+ base::TimeTicks current_end_time = timestamps[0].end_time;
+ for (WTF::wtf_size_t i = 1; i < timestamps.size(); ++i) {
+ total_duration += timestamps[i].end_time - timestamps[i].start_time;
+ if (timestamps[i].start_time < current_end_time) {
+ total_duration -= std::min(current_end_time, timestamps[i].end_time) -
+ timestamps[i].start_time;
+ }
+ current_end_time = std::max(current_end_time, timestamps[i].end_time);
+ }
+ return total_duration;
+}
+} // namespace
+
+ResponsivenessMetrics::ResponsivenessMetrics() = default;
+ResponsivenessMetrics::~ResponsivenessMetrics() = default;
+
+void ResponsivenessMetrics::RecordUserInteractionUKM(
+ LocalDOMWindow* window,
+ UserInteractionType interaction_type,
+ base::TimeDelta max_event_duration,
+ base::TimeDelta total_event_duration) {
+ if (!window)
+ return;
+
+ ukm::UkmRecorder* ukm_recorder = window->UkmRecorder();
+ ukm::SourceId source_id = window->UkmSourceID();
+ if (source_id != ukm::kInvalidSourceId &&
+ (!sampling_ || base::RandInt(kMinValueForSampling,
+ kMaxValueForSampling) <= kUkmSamplingRate)) {
+ ukm::builders::Responsiveness_UserInteraction(source_id)
+ .SetInteractionType(static_cast<int>(interaction_type))
+ .SetMaxEventDuration(max_event_duration.InMilliseconds())
+ .SetTotalEventDuration(total_event_duration.InMilliseconds())
+ .Record(ukm_recorder);
+ }
+}
+
+void ResponsivenessMetrics::NotifyPotentialDrag() {
+ is_drag_ = pending_pointer_down_timestamps_.has_value() &&
+ !pending_pointer_up_timestamps_.has_value();
+}
+
+void ResponsivenessMetrics::RecordPerInteractionLatency(
+ LocalDOMWindow* window,
+ const AtomicString& event_type,
+ absl::optional<int> key_code,
+ absl::optional<PointerId> pointer_id,
+ EventTimestamps event_timestamps) {
+ // Keyboard interactions.
+ if (key_code.has_value()) {
+ RecordKeyboardInteractions(window, event_type, key_code.value(),
+ event_timestamps);
+ }
+ // Tap(Click) or Drag.
+ if (pointer_id.has_value()) {
+ RecordTapOrClickOrDrag(window, event_type, event_timestamps);
+ }
+}
+
+void ResponsivenessMetrics::FlushPendingInteraction(LocalDOMWindow* window) {
+ // For tap delay, the click can be dropped. We will measure the latency
+ // without any click data.
+ if (pending_pointer_down_timestamps_.has_value() &&
+ pending_pointer_up_timestamps_.has_value()) {
+ WTF::Vector<EventTimestamps> timestamps;
+ // Insertion order matters for latency computation.
+ timestamps.push_back(pending_pointer_down_timestamps_.value());
+ timestamps.push_back(pending_pointer_up_timestamps_.value());
+ RecordUserInteractionUKM(window,
+ is_drag_ ? UserInteractionType::kDrag
+ : UserInteractionType::kTapOrClick,
+ MaxEventDuration(timestamps),
+ TotalEventDuration(timestamps));
+ }
+ ResetPendingPointers();
+}
+
+void ResponsivenessMetrics::ResetPendingPointers() {
+ is_drag_ = false;
+ pending_pointer_down_timestamps_.reset();
+ pending_pointer_up_timestamps_.reset();
+}
+
+// For multi-finger touch, we record the innermost pair of pointerdown and
+// pointerup.
+// TODO(hbsong): Record one interaction per pointer id.
+void ResponsivenessMetrics::RecordTapOrClickOrDrag(
+ LocalDOMWindow* window,
+ const AtomicString& event_type,
+ EventTimestamps event_timestamps) {
+ if (event_type == event_type_names::kPointercancel) {
+ pending_pointer_down_timestamps_.reset();
+ } else if (event_type == event_type_names::kPointerdown) {
+ FlushPendingInteraction(window);
+ pending_pointer_down_timestamps_ = event_timestamps;
+ } else if (event_type == event_type_names::kPointerup &&
+ pending_pointer_down_timestamps_.has_value() &&
+ !pending_pointer_up_timestamps_.has_value()) {
+ pending_pointer_up_timestamps_ = event_timestamps;
+ } else if (event_type == event_type_names::kClick) {
+ WTF::Vector<EventTimestamps> timestamps;
+ // Insertion order matters for latency computation.
+ if (pending_pointer_down_timestamps_.has_value()) {
+ timestamps.push_back(pending_pointer_down_timestamps_.value());
+ }
+ if (pending_pointer_up_timestamps_.has_value()) {
+ timestamps.push_back(pending_pointer_up_timestamps_.value());
+ }
+ timestamps.push_back(event_timestamps);
+ RecordUserInteractionUKM(window,
+ is_drag_ ? UserInteractionType::kDrag
+ : UserInteractionType::kTapOrClick,
+ MaxEventDuration(timestamps),
+ TotalEventDuration(timestamps));
+ ResetPendingPointers();
+ }
+}
+
+void ResponsivenessMetrics::RecordKeyboardInteractions(
+ LocalDOMWindow* window,
+ const AtomicString& event_type,
+ int key_code,
+ EventTimestamps event_timestamps) {
+ if (event_type == event_type_names::kKeydown) {
+ if (key_down_timestamps_map_.find(key_code) !=
+ key_down_timestamps_map_.end()) {
+ // Found a previous key_down with the same keycode, which means a key is
+ // being held down. We regard the duration of the keydown as an
+ // interaction level latency.
+ EventTimestamps key_down_timestamps =
+ key_down_timestamps_map_.at(key_code);
+ base::TimeDelta event_duration =
+ key_down_timestamps.end_time - key_down_timestamps.start_time;
+ RecordUserInteractionUKM(window, UserInteractionType::kKeyboard,
+ event_duration, event_duration);
+ }
+ key_down_timestamps_map_[key_code] = event_timestamps;
+ } else if (event_type == event_type_names::kKeyup) {
+ if (key_down_timestamps_map_.find(key_code) !=
+ key_down_timestamps_map_.end()) {
+ // Found a previous key_down with the same keycode as keyup.
+ // We calculate the interaction latency based on the durations of keydown
+ // and keyup.
+ EventTimestamps key_down_timestamps =
+ key_down_timestamps_map_.at(key_code);
+ WTF::Vector<EventTimestamps> timestamps;
+ // Insertion order matters for latency computation.
+ timestamps.push_back(key_down_timestamps);
+ timestamps.push_back(event_timestamps);
+ RecordUserInteractionUKM(window, UserInteractionType::kKeyboard,
+ MaxEventDuration(timestamps),
+ TotalEventDuration(timestamps));
+ // Remove the stale keydown.
+ key_down_timestamps_map_.erase(key_code);
+ } else {
+ // Can't find a corresponding keydown. We regard the duration of the keyup
+ // as an interaction latency.
+ base::TimeDelta event_duration =
+ event_timestamps.end_time - event_timestamps.start_time;
+ RecordUserInteractionUKM(window, UserInteractionType::kKeyboard,
+ event_duration, event_duration);
+ }
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.h b/chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.h
new file mode 100644
index 00000000000..0f18ada4f98
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/responsiveness_metrics.h
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_RESPONSIVENESS_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_RESPONSIVENESS_METRICS_H_
+
+#include <unordered_map>
+
+#include "third_party/blink/renderer/core/events/pointer_event.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+
+namespace blink {
+
+// Enum class for user interaction types. It's used in UKM and should not be
+// changed.
+enum class UserInteractionType { kKeyboard = 0, kTapOrClick = 1, kDrag = 2 };
+
+class ResponsivenessMetrics {
+ public:
+ ResponsivenessMetrics();
+ ~ResponsivenessMetrics();
+
+ // Timestamps for input events.
+ struct EventTimestamps {
+ // The event creation time.
+ base::TimeTicks start_time;
+ // The time when the first display update caused by the input event was
+ // performed.
+ base::TimeTicks end_time;
+ };
+
+ // Track ongoing user interactions and calculate the latency when an
+ // interaction is completed. The latency data for each interaction will be
+ // recored in UKM.
+ void RecordPerInteractionLatency(LocalDOMWindow* window,
+ const AtomicString& event_type,
+ absl::optional<int> key_code,
+ absl::optional<PointerId> pointer_id,
+ EventTimestamps event_timestamps);
+
+ // Stop UKM sampling for testing.
+ void StopUkmSamplingForTesting() { sampling_ = false; }
+
+ // The use might be dragging. The function will be called whenever we have a
+ // pointermove.
+ void NotifyPotentialDrag();
+
+ private:
+ // Record UKM for user interaction latencies.
+ void RecordUserInteractionUKM(LocalDOMWindow* window,
+ UserInteractionType interaction_type,
+ base::TimeDelta max_event_duration,
+ base::TimeDelta total_devent_duration);
+
+ void RecordKeyboardInteractions(LocalDOMWindow* window,
+ const AtomicString& event_type,
+ int key_code,
+ EventTimestamps event_timestamps);
+
+ // Might not be accurate for multi-fingers touch.
+ void RecordTapOrClickOrDrag(LocalDOMWindow* window,
+ const AtomicString& event_type,
+ EventTimestamps event_timestamps);
+ // Flush the latency data for pending tap or drag.
+ void FlushPendingInteraction(LocalDOMWindow* window);
+
+ // Reset the latency data for pointer events.
+ void ResetPendingPointers();
+
+ // Variables for per-interaction latencies.
+ std::unordered_map<int, EventTimestamps> key_down_timestamps_map_;
+
+ absl::optional<EventTimestamps> pending_pointer_up_timestamps_;
+ absl::optional<EventTimestamps> pending_pointer_down_timestamps_;
+ bool is_drag_ = false;
+
+ // Whether to perform UKM sampling.
+ bool sampling_ = true;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_RESPONSIVENESS_METRICS_H_
diff --git a/chromium/third_party/blink/renderer/core/timing/time_clamper.h b/chromium/third_party/blink/renderer/core/timing/time_clamper.h
index 7504ab11664..05908af8f07 100644
--- a/chromium/third_party/blink/renderer/core/timing/time_clamper.h
+++ b/chromium/third_party/blink/renderer/core/timing/time_clamper.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_TIME_CLAMPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_TIME_CLAMPER_H_
-#include "base/macros.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -22,6 +22,8 @@ class CORE_EXPORT TimeClamper {
static constexpr int kFineResolutionMicroseconds = 5;
TimeClamper();
+ TimeClamper(const TimeClamper&) = delete;
+ TimeClamper& operator=(const TimeClamper&) = delete;
// Deterministically clamp the time value |time_microseconds| to a fixed
// interval to prevent timing attacks. See
@@ -41,8 +43,6 @@ class CORE_EXPORT TimeClamper {
static inline uint64_t MurmurHash3(uint64_t value);
uint64_t secret_;
-
- DISALLOW_COPY_AND_ASSIGN(TimeClamper);
};
} // namespace blink
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 eddf6d27a08..4c1a84ecf36 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.cc
@@ -41,6 +41,8 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
+#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
@@ -56,6 +58,7 @@
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
#include "third_party/blink/renderer/core/timing/performance_observer.h"
#include "third_party/blink/renderer/core/timing/performance_timing.h"
+#include "third_party/blink/renderer/core/timing/responsiveness_metrics.h"
#include "third_party/blink/renderer/core/timing/visibility_state_entry.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -94,6 +97,8 @@ AtomicString GetFrameOwnerType(HTMLFrameOwnerElement* frame_owner) {
return "frame";
case mojom::blink::FrameOwnerElementType::kPortal:
return "portal";
+ case mojom::blink::FrameOwnerElementType::kFencedframe:
+ return "fencedframe";
}
NOTREACHED();
return "";
@@ -169,6 +174,10 @@ WindowPerformance::WindowPerformance(LocalDOMWindow* window)
}
}
+void WindowPerformance::EventData::Trace(Visitor* visitor) const {
+ visitor->Trace(event_timing_);
+}
+
WindowPerformance::~WindowPerformance() = default;
ExecutionContext* WindowPerformance::GetExecutionContext() const {
@@ -237,11 +246,12 @@ void WindowPerformance::BuildJSONValue(V8ObjectBuilder& builder) const {
}
void WindowPerformance::Trace(Visitor* visitor) const {
- visitor->Trace(event_timings_);
+ visitor->Trace(events_data_);
visitor->Trace(first_pointer_down_event_timing_);
visitor->Trace(event_counts_);
visitor->Trace(navigation_);
visitor->Trace(timing_);
+ visitor->Trace(current_event_);
Performance::Trace(visitor);
PerformanceMonitor::Client::Trace(visitor);
ExecutionContextClient::Trace(visitor);
@@ -342,43 +352,35 @@ void WindowPerformance::ReportLongTask(base::TimeTicks start_time,
}
}
-void WindowPerformance::RegisterEventTiming(const AtomicString& event_type,
- base::TimeTicks start_time,
- base::TimeTicks processing_start,
- base::TimeTicks processing_end,
- bool cancelable,
- Node* target) {
+void WindowPerformance::RegisterEventTiming(
+ const AtomicString& event_type,
+ base::TimeTicks start_time,
+ base::TimeTicks processing_start,
+ base::TimeTicks processing_end,
+ bool cancelable,
+ Node* target,
+ absl::optional<int> key_code,
+ absl::optional<PointerId> pointer_id) {
// |start_time| could be null in some tests that inject input.
DCHECK(!processing_start.is_null());
DCHECK(!processing_end.is_null());
DCHECK_GE(processing_end, processing_start);
if (!DomWindow())
return;
-
- // Count non-pointerevent Events. Avoid double counting pointerevents
- // because we count them in pointer_event_manager.cc. Note click, auxclick and
- // contextmenu are PointerEvent but the dispatch process of them are different
- // from other PointerEvent.
- if (event_type != event_type_names::kPointerover &&
- event_type != event_type_names::kPointerenter &&
- event_type != event_type_names::kPointerdown &&
- event_type != event_type_names::kPointerup &&
- event_type != event_type_names::kPointercancel &&
- event_type != event_type_names::kPointerout &&
- event_type != event_type_names::kPointerleave &&
- event_type != event_type_names::kGotpointercapture &&
- event_type != event_type_names::kLostpointercapture) {
- eventCounts()->Add(event_type);
+ if (event_type == event_type_names::kPointermove) {
+ NotifyPotentialDrag();
+ SetCurrentEventTimingEvent(nullptr);
+ return;
}
-
+ eventCounts()->Add(event_type);
PerformanceEventTiming* entry = PerformanceEventTiming::Create(
event_type, MonotonicTimeToDOMHighResTimeStamp(start_time),
MonotonicTimeToDOMHighResTimeStamp(processing_start),
MonotonicTimeToDOMHighResTimeStamp(processing_end), cancelable, target);
// Add |entry| to the end of the queue along with the frame index at which is
// is being queued to know when to queue a presentation promise for it.
- event_timings_.push_back(entry);
- event_frames_.push_back(frame_index_);
+ events_data_.push_back(
+ EventData::Create(entry, frame_index_, start_time, key_code, pointer_id));
bool should_queue_presentation_promise = false;
// If there are no pending presentation promises, we should queue one. This
// ensures that |event_timings_| are processed even if the Blink lifecycle
@@ -400,37 +402,43 @@ void WindowPerformance::RegisterEventTiming(const AtomicString& event_type,
last_registered_frame_index_ = frame_index_;
++pending_presentation_promise_count_;
}
+ SetCurrentEventTimingEvent(nullptr);
}
-void WindowPerformance::ReportEventTimings(uint64_t frame_index,
- WebSwapResult result,
- base::TimeTicks timestamp) {
+void WindowPerformance::ReportEventTimings(
+ uint64_t frame_index,
+ WebSwapResult result,
+ base::TimeTicks presentation_timestamp) {
DCHECK(pending_presentation_promise_count_);
--pending_presentation_promise_count_;
- // |event_timings_| and |event_frames_| should always have the same size.
- DCHECK(event_timings_.size() == event_frames_.size());
- if (event_timings_.IsEmpty())
+ if (events_data_.IsEmpty())
return;
if (!DomWindow())
return;
InteractiveDetector* interactive_detector =
InteractiveDetector::From(*(DomWindow()->document()));
- bool event_timing_enabled =
- RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext());
- DOMHighResTimeStamp end_time = MonotonicTimeToDOMHighResTimeStamp(timestamp);
- while (!event_timings_.IsEmpty()) {
- PerformanceEventTiming* entry = event_timings_.front();
- uint64_t entry_frame_index = event_frames_.front();
+ DOMHighResTimeStamp end_time =
+ MonotonicTimeToDOMHighResTimeStamp(presentation_timestamp);
+ while (!events_data_.IsEmpty()) {
+ auto event_data = events_data_.front();
+ PerformanceEventTiming* entry = event_data->GetEventTiming();
+ uint64_t entry_frame_index = event_data->GetFrameIndex();
+ base::TimeTicks event_timestamp = event_data->GetEventTimestamp();
+ absl::optional<int> key_code = event_data->GetKeyCode();
+ absl::optional<PointerId> pointer_id = event_data->GetPointerId();
// If the entry was queued at a frame index that is larger than
// |frame_index|, then we've reached the end of the entries that we can
// process during this callback.
if (entry_frame_index > frame_index)
break;
- event_timings_.pop_front();
- event_frames_.pop_front();
+ events_data_.pop_front();
+ ResponsivenessMetrics::EventTimestamps event_timestamps = {
+ event_timestamp, presentation_timestamp};
+ responsiveness_metrics_.RecordPerInteractionLatency(
+ DomWindow(), entry->name(), key_code, pointer_id, event_timestamps);
int duration_in_ms = std::round((end_time - entry->startTime()) / 8) * 8;
base::TimeDelta input_delay = base::TimeDelta::FromMillisecondsD(
entry->processingStart() - entry->startTime());
@@ -473,8 +481,6 @@ void WindowPerformance::ReportEventTimings(uint64_t frame_index,
PerformanceEventTiming::CreateFirstInputTiming(entry));
}
}
- if (!event_timing_enabled)
- continue;
if (HasObserverFor(PerformanceEntry::kEvent)) {
UseCounter::Count(GetExecutionContext(),
@@ -555,7 +561,6 @@ void WindowPerformance::PageVisibilityChanged() {
}
EventCounts* WindowPerformance::eventCounts() {
- DCHECK(RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext()));
if (!event_counts_)
event_counts_ = MakeGarbageCollected<EventCounts>();
return event_counts_;
@@ -584,4 +589,8 @@ void WindowPerformance::OnPaintFinished() {
++frame_index_;
}
+void WindowPerformance::NotifyPotentialDrag() {
+ responsiveness_metrics_.NotifyPotentialDrag();
+}
+
} // namespace blink
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 44bac04a32c..93d1f69191d 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.h
@@ -35,14 +35,17 @@
#include "base/rand_util.h"
#include "third_party/blink/public/web/web_swap_result.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/core/timing/event_counts.h"
+#include "third_party/blink/renderer/core/timing/event_timing.h"
#include "third_party/blink/renderer/core/timing/memory_info.h"
#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/core/timing/performance_navigation.h"
#include "third_party/blink/renderer/core/timing/performance_timing.h"
+#include "third_party/blink/renderer/core/timing/responsiveness_metrics.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
namespace blink {
@@ -55,6 +58,52 @@ class CORE_EXPORT WindowPerformance final : public Performance,
public PageVisibilityObserver {
friend class WindowPerformanceTest;
+ class EventData : public GarbageCollected<EventData> {
+ public:
+ EventData(PerformanceEventTiming* event_timing,
+ uint64_t frame,
+ base::TimeTicks event_timestamp,
+ absl::optional<int> key_code,
+ absl::optional<PointerId> pointer_id)
+ : event_timing_(event_timing),
+ frame_(frame),
+ event_timestamp_(event_timestamp),
+ key_code_(key_code),
+ pointer_id_(pointer_id) {}
+
+ static EventData* Create(PerformanceEventTiming* event_timing,
+ uint64_t frame,
+ base::TimeTicks event_timestamp,
+ absl::optional<int> key_code,
+ absl::optional<PointerId> pointer_id) {
+ return MakeGarbageCollected<EventData>(
+ event_timing, frame, event_timestamp, key_code, pointer_id);
+ }
+ ~EventData() = default;
+ void Trace(Visitor*) const;
+ PerformanceEventTiming* GetEventTiming() { return event_timing_; }
+ uint64_t GetFrameIndex() { return frame_; }
+ base::TimeTicks GetEventTimestamp() { return event_timestamp_; }
+ absl::optional<int> GetKeyCode() { return key_code_; }
+ absl::optional<PointerId> GetPointerId() { return pointer_id_; }
+
+ private:
+ // Event PerformanceEventTiming entry that has not been sent to observers
+ // yet: the event dispatch has been completed but the presentation promise
+ // used to determine |duration| has not yet been resolved.
+ Member<PerformanceEventTiming> event_timing_;
+ // Frame index in which the entry in |event_timing_| were added.
+ uint64_t frame_;
+ // The event creation timestamp.
+ base::TimeTicks event_timestamp_;
+ // Keycode for the event. If the event is not a keyboard event, the keycode
+ // wouldn't be set.
+ absl::optional<int> key_code_;
+ // PointerId for the event. If the event is not a pointer event, the
+ // PointerId wouldn't be set.
+ absl::optional<PointerId> pointer_id_;
+ };
+
public:
explicit WindowPerformance(LocalDOMWindow*);
~WindowPerformance() override;
@@ -78,7 +127,9 @@ class CORE_EXPORT WindowPerformance final : public Performance,
base::TimeTicks processing_start,
base::TimeTicks processing_end,
bool cancelable,
- Node*);
+ Node*,
+ absl::optional<int> key_code,
+ absl::optional<PointerId> pointer_id);
void OnPaintFinished();
@@ -107,6 +158,17 @@ class CORE_EXPORT WindowPerformance final : public Performance,
void Trace(Visitor*) const override;
+ ResponsivenessMetrics& GetResponsivenessMetrics() {
+ return responsiveness_metrics_;
+ }
+
+ void NotifyPotentialDrag();
+
+ void SetCurrentEventTimingEvent(const Event* event) {
+ current_event_ = event;
+ }
+ const Event* GetCurrentEventTimingEvent() { return current_event_; }
+
private:
PerformanceNavigationTiming* CreateNavigationTimingInstance() override;
@@ -123,11 +185,12 @@ class CORE_EXPORT WindowPerformance final : public Performance,
void BuildJSONValue(V8ObjectBuilder&) const override;
- // Method called once presentation promise is resolved. It will add all event
- // timings that have not been added since the last presentation promise.
+ // Method called once presentation promise for a frame is resolved. It will
+ // add all event timings that have not been added since the last presentation
+ // promise.
void ReportEventTimings(uint64_t frame_index,
WebSwapResult result,
- base::TimeTicks timestamp);
+ base::TimeTicks presentation_timestamp);
void DispatchFirstInputTiming(PerformanceEventTiming* entry);
@@ -138,19 +201,10 @@ class CORE_EXPORT WindowPerformance final : public Performance,
uint64_t last_registered_frame_index_ = 0;
// Number of pending presentation promises.
uint16_t pending_presentation_promise_count_ = 0;
- // PerformanceEventTiming entries that have not been sent to observers yet:
- // the event dispatch has been completed but the presentation promise used to
- // determine |duration| has not yet been resolved. It is handled as a queue:
- // FIFO.
- HeapDeque<Member<PerformanceEventTiming>> event_timings_;
- // Entries corresponding to frame indices in which the entries in
- // |event_timings_| were added. This could be combined with |event_timings_|
- // into a single deque, but PerformanceEventTiming is GarbageCollected so it
- // would need to be a HeapDeque. HeapDeque does not allow std::pair as its
- // type, so we would have to add a new wrapper GarbageCollected class that
- // contains the PerformanceEventTiming object as well as the frame index. This
- // is more work than having two separate deques.
- Deque<uint64_t> event_frames_;
+ // Store all event timing and latency related data, including
+ // PerformanceEventTiming, frame_index, keycode and pointerId. We use the data
+ // to calculate events latencies.
+ HeapDeque<Member<EventData>> events_data_;
Member<PerformanceEventTiming> first_pointer_down_event_timing_;
Member<EventCounts> event_counts_;
mutable Member<PerformanceNavigation> navigation_;
@@ -158,6 +212,11 @@ class CORE_EXPORT WindowPerformance final : public Performance,
absl::optional<base::TimeDelta> pending_pointer_down_input_delay_;
absl::optional<base::TimeDelta> pending_pointer_down_processing_time_;
absl::optional<base::TimeDelta> pending_pointer_down_time_to_next_paint_;
+
+ // Calculate responsiveness metrics and record UKM for them.
+ ResponsivenessMetrics responsiveness_metrics_;
+ // The event we are currently processing.
+ WeakMember<const Event> current_event_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/window_performance.idl b/chromium/third_party/blink/renderer/core/timing/window_performance.idl
index b55f5b40642..efebb32ca90 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.idl
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.idl
@@ -9,5 +9,5 @@
[
ImplementedAs=DOMWindowPerformance
] partial interface Window {
- [Affects=Nothing, Replaceable] readonly attribute Performance performance;
+ [Replaceable] readonly attribute Performance performance;
};
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 62ca695d3b7..37336dd18f1 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
@@ -5,8 +5,8 @@
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "base/test/test_mock_time_task_runner.h"
+#include "services/metrics/public/cpp/ukm_builders.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/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_init.h"
@@ -18,18 +18,25 @@
#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/testing/mock_policy_container_host.h"
+#include "third_party/blink/renderer/core/testing/scoped_fake_ukm_recorder.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/unit_test_helpers.h"
namespace blink {
+using test::RunPendingTasks;
+
namespace {
base::TimeTicks GetTimeOrigin() {
return base::TimeTicks() + base::TimeDelta::FromSeconds(500);
}
+base::TimeTicks GetTimeStamp(int64_t time) {
+ return GetTimeOrigin() + base::TimeDelta::FromMilliseconds(time);
+}
+
} // namespace
class WindowPerformanceTest : public testing::Test {
@@ -90,16 +97,23 @@ class WindowPerformanceTest : public testing::Test {
performance_->SetClocksForTesting(test_task_runner_->GetMockClock(),
test_task_runner_->GetMockTickClock());
performance_->time_origin_ = GetTimeOrigin();
+ // Stop UKM sampling for testing.
+ performance_->GetResponsivenessMetrics().StopUkmSamplingForTesting();
}
ScriptState* GetScriptState() const {
return ToScriptStateForMainWorld(page_holder_->GetDocument().GetFrame());
}
+ ukm::TestUkmRecorder* GetUkmRecorder() {
+ return scoped_fake_ukm_recorder_.recorder();
+ }
+
uint64_t frame_counter = 1;
Persistent<WindowPerformance> performance_;
std::unique_ptr<DummyPageHolder> page_holder_;
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
+ ScopedFakeUkmRecorder scoped_fake_ukm_recorder_;
};
TEST_F(WindowPerformanceTest, LongTaskObserverInstrumentation) {
@@ -237,7 +251,6 @@ TEST_F(WindowPerformanceTest, EnsureEntryListOrder) {
}
TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
- ScopedEventTimingForTest event_timing(true);
EXPECT_TRUE(page_holder_->GetFrame().Loader().GetDocumentLoader());
base::TimeTicks start_time =
@@ -247,7 +260,7 @@ TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
base::TimeTicks processing_end =
GetTimeOrigin() + base::TimeDelta::FromSecondsD(3.8);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
base::TimeTicks swap_time =
GetTimeOrigin() + base::TimeDelta::FromSecondsD(6.0);
SimulateSwapPromise(swap_time);
@@ -259,7 +272,7 @@ TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
->GetTiming()
.MarkLoadEventStart();
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, true, nullptr);
+ processing_end, true, nullptr, 4, 4);
SimulateSwapPromise(swap_time);
EXPECT_EQ(2u, performance_->getBufferedEntriesByType("event").size());
@@ -267,13 +280,12 @@ TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
GetFrame()->DetachDocument();
EXPECT_FALSE(page_holder_->GetFrame().Loader().GetDocumentLoader());
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
SimulateSwapPromise(swap_time);
EXPECT_EQ(3u, performance_->getBufferedEntriesByType("event").size());
}
TEST_F(WindowPerformanceTest, Expose100MsEvents) {
- ScopedEventTimingForTest event_timing(true);
base::TimeTicks start_time =
GetTimeOrigin() + base::TimeDelta::FromSeconds(1);
base::TimeTicks processing_start =
@@ -281,12 +293,12 @@ TEST_F(WindowPerformanceTest, Expose100MsEvents) {
base::TimeTicks processing_end =
processing_start + base::TimeDelta::FromMilliseconds(10);
performance_->RegisterEventTiming("mousedown", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
base::TimeTicks start_time2 =
start_time + base::TimeDelta::FromMicroseconds(200);
performance_->RegisterEventTiming("click", start_time2, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
// The swap time is 100.1 ms after |start_time| but only 99.9 ms after
// |start_time2|.
@@ -300,8 +312,6 @@ TEST_F(WindowPerformanceTest, Expose100MsEvents) {
}
TEST_F(WindowPerformanceTest, EventTimingDuration) {
- ScopedEventTimingForTest event_timing(true);
-
base::TimeTicks start_time =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1000);
base::TimeTicks processing_start =
@@ -309,24 +319,24 @@ TEST_F(WindowPerformanceTest, EventTimingDuration) {
base::TimeTicks processing_end =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1002);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
base::TimeTicks short_swap_time =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1003);
SimulateSwapPromise(short_swap_time);
EXPECT_EQ(0u, performance_->getBufferedEntriesByType("event").size());
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, true, nullptr);
+ processing_end, true, nullptr, 4, 4);
base::TimeTicks long_swap_time =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2000);
SimulateSwapPromise(long_swap_time);
EXPECT_EQ(1u, performance_->getBufferedEntriesByType("event").size());
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, true, nullptr);
+ processing_end, true, nullptr, 4, 4);
SimulateSwapPromise(short_swap_time);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
SimulateSwapPromise(long_swap_time);
EXPECT_EQ(2u, performance_->getBufferedEntriesByType("event").size());
}
@@ -334,8 +344,6 @@ TEST_F(WindowPerformanceTest, EventTimingDuration) {
// Test the case where multiple events are registered and then their swap
// promise is resolved.
TEST_F(WindowPerformanceTest, MultipleEventsThenSwap) {
- ScopedEventTimingForTest event_timing(true);
-
size_t num_events = 10;
for (size_t i = 0; i < num_events; ++i) {
base::TimeTicks start_time =
@@ -345,7 +353,7 @@ TEST_F(WindowPerformanceTest, MultipleEventsThenSwap) {
base::TimeTicks processing_end =
start_time + base::TimeDelta::FromMilliseconds(200);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
EXPECT_EQ(0u, performance_->getBufferedEntriesByType("event").size());
}
base::TimeTicks swap_time =
@@ -367,7 +375,8 @@ TEST_F(WindowPerformanceTest, FirstInput) {
performance_->RegisterEventTiming(
input.event_type, GetTimeOrigin(),
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1),
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr);
+ GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr,
+ 4, 4);
SimulateSwapPromise(GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3));
PerformanceEntryVector firstInputs =
performance_->getEntriesByType("first-input");
@@ -385,7 +394,8 @@ TEST_F(WindowPerformanceTest, FirstInputAfterIgnored) {
performance_->RegisterEventTiming(
event, GetTimeOrigin(),
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1),
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr);
+ GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr,
+ 4, 4);
SimulateSwapPromise(GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3));
}
ASSERT_EQ(1u, performance_->getEntriesByType("first-input").size());
@@ -395,19 +405,16 @@ TEST_F(WindowPerformanceTest, FirstInputAfterIgnored) {
// Test that pointerdown followed by pointerup works as a 'firstInput'.
TEST_F(WindowPerformanceTest, FirstPointerUp) {
- base::TimeTicks start_time = GetTimeOrigin();
- base::TimeTicks processing_start =
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1);
- base::TimeTicks processing_end =
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2);
- base::TimeTicks swap_time =
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3);
+ base::TimeTicks start_time = GetTimeStamp(0);
+ base::TimeTicks processing_start = GetTimeStamp(1);
+ base::TimeTicks processing_end = GetTimeStamp(2);
+ base::TimeTicks swap_time = GetTimeStamp(3);
performance_->RegisterEventTiming("pointerdown", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
SimulateSwapPromise(swap_time);
EXPECT_EQ(0u, performance_->getEntriesByType("first-input").size());
performance_->RegisterEventTiming("pointerup", start_time, processing_start,
- processing_end, false, nullptr);
+ processing_end, false, nullptr, 4, 4);
SimulateSwapPromise(swap_time);
EXPECT_EQ(1u, performance_->getEntriesByType("first-input").size());
// The name of the entry should be "pointerdown".
@@ -415,4 +422,446 @@ TEST_F(WindowPerformanceTest, FirstPointerUp) {
1u, performance_->getEntriesByName("pointerdown", "first-input").size());
}
+TEST_F(WindowPerformanceTest, OneKeyboardInteraction) {
+ base::TimeTicks keydown_timestamp = GetTimeStamp(0);
+ // Keydown
+ base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+ base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+ base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = absl::nullopt;
+ absl::optional<int> key_code = 2;
+ performance_->RegisterEventTiming(
+ "keydown", keydown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+ // Keyup
+ base::TimeTicks keyup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+ base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+ base::TimeTicks swap_time_keyup = GetTimeStamp(10);
+ performance_->RegisterEventTiming(
+ "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+ false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keyup);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ auto merged_entries = GetUkmRecorder()->GetMergedEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(1u, merged_entries.size());
+ for (const auto& kv : merged_entries) {
+ const ukm::mojom::UkmEntry* ukm_entry = kv.second.get();
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+ 7);
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+ 10);
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 0);
+ }
+}
+
+TEST_F(WindowPerformanceTest, HoldingDownAKey) {
+ auto entries = GetUkmRecorder()->GetEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(0u, entries.size());
+ base::TimeTicks keydown_timestamp = GetTimeOrigin();
+ base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+ base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+ base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = absl::nullopt;
+ absl::optional<int> key_code = 2;
+ performance_->RegisterEventTiming(
+ "keydown", keydown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+
+ // Second Keydown
+ keydown_timestamp = GetTimeStamp(1);
+ processing_start_keydown = GetTimeStamp(2);
+ processing_end_keydown = GetTimeStamp(3);
+ swap_time_keydown = GetTimeStamp(7);
+ performance_->RegisterEventTiming(
+ "keydown", keydown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+
+ // Third Keydown
+ keydown_timestamp = GetTimeStamp(2);
+ processing_start_keydown = GetTimeStamp(3);
+ processing_end_keydown = GetTimeStamp(5);
+ swap_time_keydown = GetTimeStamp(9);
+ performance_->RegisterEventTiming(
+ "keydown", keydown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+
+ // Keyup
+ base::TimeTicks keyup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+ base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+ base::TimeTicks swap_time_keyup = GetTimeStamp(13);
+ performance_->RegisterEventTiming(
+ "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+ false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keyup);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ entries = GetUkmRecorder()->GetEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(3u, entries.size());
+ std::vector<std::pair<int, int>> expected_durations;
+ expected_durations.emplace_back(std::make_pair(5, 5));
+ expected_durations.emplace_back(std::make_pair(6, 6));
+ expected_durations.emplace_back(std::make_pair(10, 11));
+ for (std::size_t i = 0; i < entries.size(); ++i) {
+ auto* entry = entries[i];
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+ expected_durations[i].first);
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+ expected_durations[i].second);
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 0);
+ }
+}
+
+TEST_F(WindowPerformanceTest, PressMultipleKeys) {
+ auto entries = GetUkmRecorder()->GetEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(0u, entries.size());
+ // Press the first key.
+ base::TimeTicks keydown_timestamp = GetTimeOrigin();
+ base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+ base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+ base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = absl::nullopt;
+ absl::optional<int> first_key_code = 2;
+ performance_->RegisterEventTiming(
+ "keydown", keydown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, first_key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+
+ // Press the second key.
+ processing_start_keydown = GetTimeStamp(2);
+ processing_end_keydown = GetTimeStamp(3);
+ swap_time_keydown = GetTimeStamp(7);
+ absl::optional<int> second_key_code = 4;
+ performance_->RegisterEventTiming(
+ "keydown", keydown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, second_key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+
+ // Release the first key.
+ base::TimeTicks keyup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+ base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+ base::TimeTicks swap_time_keyup = GetTimeStamp(13);
+ performance_->RegisterEventTiming(
+ "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+ false, nullptr, first_key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keyup);
+
+ // Release the second key.
+ keyup_timestamp = GetTimeStamp(5);
+ processing_start_keyup = GetTimeStamp(5);
+ processing_end_keyup = GetTimeStamp(6);
+ swap_time_keyup = GetTimeStamp(20);
+ performance_->RegisterEventTiming(
+ "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+ false, nullptr, second_key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keyup);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ entries = GetUkmRecorder()->GetEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(2u, entries.size());
+ std::vector<std::pair<int, int>> expected_durations;
+ expected_durations.emplace_back(std::make_pair(10, 13));
+ expected_durations.emplace_back(std::make_pair(15, 20));
+ for (std::size_t i = 0; i < entries.size(); ++i) {
+ auto* entry = entries[i];
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+ expected_durations[i].first);
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+ expected_durations[i].second);
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 0);
+ }
+}
+
+TEST_F(WindowPerformanceTest, TapOrClick) {
+ // Pointerdown
+ base::TimeTicks pointerdwon_timestamp = GetTimeOrigin();
+ base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+ base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+ base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = 4;
+ absl::optional<int> key_code = absl::nullopt;
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdwon_timestamp, processing_start_pointerdown,
+ processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_pointerdown);
+ // Pointerup
+ base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_pointerup = GetTimeStamp(5);
+ base::TimeTicks processing_end_pointerup = GetTimeStamp(6);
+ base::TimeTicks swap_time_pointerup = GetTimeStamp(10);
+ performance_->RegisterEventTiming(
+ "pointerup", pointerup_timestamp, processing_start_pointerup,
+ processing_end_pointerup, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_pointerup);
+ // Click
+ base::TimeTicks click_timestamp = GetTimeStamp(13);
+ base::TimeTicks processing_start_click = GetTimeStamp(15);
+ base::TimeTicks processing_end_click = GetTimeStamp(16);
+ base::TimeTicks swap_time_click = GetTimeStamp(20);
+ performance_->RegisterEventTiming(
+ "click", click_timestamp, processing_start_click, processing_end_click,
+ false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_click);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+ GetUkmRecorder()->GetMergedEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(1u, merged_entries.size());
+ for (const auto& kv : merged_entries) {
+ const ukm::mojom::UkmEntry* ukm_entry = kv.second.get();
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+ 7);
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+ 17);
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 1);
+ }
+}
+
+TEST_F(WindowPerformanceTest, Drag) {
+ // Pointerdown
+ base::TimeTicks pointerdwon_timestamp = GetTimeOrigin();
+ base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+ base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+ base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = 4;
+ absl::optional<int> key_code = absl::nullopt;
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdwon_timestamp, processing_start_pointerdown,
+ processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_pointerdown);
+ // Notify drag.
+ performance_->NotifyPotentialDrag();
+ // Pointerup
+ base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_pointerup = GetTimeStamp(5);
+ base::TimeTicks processing_end_pointerup = GetTimeStamp(6);
+ base::TimeTicks swap_time_pointerup = GetTimeStamp(10);
+ performance_->RegisterEventTiming(
+ "pointerup", pointerup_timestamp, processing_start_pointerup,
+ processing_end_pointerup, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_pointerup);
+ // Click
+ base::TimeTicks click_timestamp = GetTimeStamp(13);
+ base::TimeTicks processing_start_click = GetTimeStamp(15);
+ base::TimeTicks processing_end_click = GetTimeStamp(16);
+ base::TimeTicks swap_time_click = GetTimeStamp(20);
+ performance_->RegisterEventTiming(
+ "click", click_timestamp, processing_start_click, processing_end_click,
+ false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_click);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+ GetUkmRecorder()->GetMergedEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(1u, merged_entries.size());
+ for (const auto& kv : merged_entries) {
+ const ukm::mojom::UkmEntry* ukm_entry = kv.second.get();
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+ 7);
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+ 17);
+ GetUkmRecorder()->ExpectEntryMetric(
+ ukm_entry,
+ ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 2);
+ }
+}
+
+TEST_F(WindowPerformanceTest, Scroll) {
+ // Pointerdown
+ base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
+ base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+ base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+ base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = 5;
+ absl::optional<int> key_code = absl::nullopt;
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdown_timestamp, processing_start_keydown,
+ processing_end_keydown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keydown);
+ // Pointercancel
+ base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+ base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+ base::TimeTicks swap_time_keyup = GetTimeStamp(10);
+ performance_->RegisterEventTiming(
+ "pointercancel", pointerup_timestamp, processing_start_keyup,
+ processing_end_keyup, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_keyup);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+ GetUkmRecorder()->GetMergedEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(0u, merged_entries.size());
+}
+
+TEST_F(WindowPerformanceTest, TouchesWithoutClick) {
+ base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
+ // First Pointerdown
+ base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+ base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+ base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id = 4;
+ absl::optional<int> key_code = absl::nullopt;
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+ processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_pointerdown);
+
+ // Second Pointerdown
+ pointerdown_timestamp = GetTimeStamp(6);
+ processing_start_pointerdown = GetTimeStamp(7);
+ processing_end_pointerdown = GetTimeStamp(8);
+ swap_time_pointerdown = GetTimeStamp(15);
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+ processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+ SimulateSwapPromise(swap_time_pointerdown);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+ GetUkmRecorder()->GetMergedEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(0u, merged_entries.size());
+}
+
+// For multi-touch, we only record the innermost pair of pointerdown and
+// pointerup.
+// TODO(hbsong): Record each touch by pointer_id separately.
+TEST_F(WindowPerformanceTest, MultiTouch) {
+ // First Pointerdown
+ base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
+ base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+ base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+ base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+ absl::optional<PointerId> pointer_id_1 = 4;
+ absl::optional<int> key_code = absl::nullopt;
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+ processing_end_pointerdown, false, nullptr, key_code, pointer_id_1);
+ SimulateSwapPromise(swap_time_pointerdown);
+ // Second Pointerdown
+ pointerdown_timestamp = GetTimeOrigin();
+ processing_start_pointerdown = GetTimeStamp(1);
+ processing_end_pointerdown = GetTimeStamp(2);
+ swap_time_pointerdown = GetTimeStamp(6);
+ absl::optional<PointerId> pointer_id_2 = 6;
+ performance_->RegisterEventTiming(
+ "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+ processing_end_pointerdown, false, nullptr, key_code, pointer_id_2);
+ SimulateSwapPromise(swap_time_pointerdown);
+
+ // First Pointerup
+ base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+ base::TimeTicks processing_start_pointerup = GetTimeStamp(5);
+ base::TimeTicks processing_end_pointerup = GetTimeStamp(6);
+ base::TimeTicks swap_time_pointerup = GetTimeStamp(9);
+ performance_->RegisterEventTiming(
+ "pointerup", pointerup_timestamp, processing_start_pointerup,
+ processing_end_pointerup, false, nullptr, key_code, pointer_id_2);
+ SimulateSwapPromise(swap_time_pointerup);
+
+ // Second Pointerup
+ pointerup_timestamp = GetTimeStamp(5);
+ processing_start_pointerup = GetTimeStamp(6);
+ processing_end_pointerup = GetTimeStamp(7);
+ swap_time_pointerup = GetTimeStamp(13);
+ performance_->RegisterEventTiming(
+ "pointerup", pointerup_timestamp, processing_start_pointerup,
+ processing_end_pointerup, false, nullptr, key_code, pointer_id_1);
+ SimulateSwapPromise(swap_time_pointerup);
+
+ // Click
+ base::TimeTicks click_timestamp = GetTimeStamp(13);
+ base::TimeTicks processing_start_click = GetTimeStamp(15);
+ base::TimeTicks processing_end_click = GetTimeStamp(16);
+ base::TimeTicks swap_time_click = GetTimeStamp(20);
+ performance_->RegisterEventTiming(
+ "click", click_timestamp, processing_start_click, processing_end_click,
+ false, nullptr, key_code, pointer_id_2);
+ SimulateSwapPromise(swap_time_click);
+
+ // Flush UKM logging mojo request.
+ RunPendingTasks();
+
+ // Check UKM recording.
+ auto entries = GetUkmRecorder()->GetEntriesByName(
+ ukm::builders::Responsiveness_UserInteraction::kEntryName);
+ EXPECT_EQ(1u, entries.size());
+ auto* entry = entries[0];
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName, 7);
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+ 16);
+ GetUkmRecorder()->ExpectEntryMetric(
+ entry,
+ ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 1);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
index 828b9bed25c..f4c09237a4f 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
@@ -7,7 +7,7 @@
typedef [StringContext=TrustedHTML] DOMString HTMLString;
[
- Exposed=Window,
+ Exposed=(Window, Worker),
RuntimeEnabled=TrustedDOMTypes
] interface TrustedHTML {
stringifier;
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl
index fc0390f325d..eb7fc3cfa67 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl
@@ -8,7 +8,7 @@ typedef [StringContext=TrustedScript] DOMString ScriptString;
[
IsCodeLike,
- Exposed=Window,
+ Exposed=(Window, Worker),
RuntimeEnabled=TrustedDOMTypes
] interface TrustedScript {
stringifier;
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
index b5b9cc1e33a..9484dfc747d 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
@@ -7,7 +7,7 @@
typedef [StringContext=TrustedScriptURL] USVString ScriptURLString;
[
- Exposed=Window,
+ Exposed=(Window, Worker),
RuntimeEnabled=TrustedDOMTypes
] interface TrustedScriptURL {
stringifier;
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl
index 22b48f331ba..b75b982f41e 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl
@@ -7,7 +7,7 @@
typedef (DOMString or TrustedHTML or TrustedScript or TrustedScriptURL) TrustedString;
[
- Exposed=Window,
+ Exposed=(Window, Worker),
RuntimeEnabled=TrustedDOMTypes
] interface TrustedTypePolicy {
readonly attribute DOMString name;
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
index 638295dcea5..ad23721bd7b 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
@@ -104,7 +104,7 @@ TrustedTypePolicy* TrustedTypePolicyFactory::createPolicy(
}
TrustedTypePolicy* TrustedTypePolicyFactory::defaultPolicy() const {
- return policy_map_.at("default");
+ return policy_map_.DeprecatedAtOrEmptyValue("default");
}
TrustedTypePolicyFactory::TrustedTypePolicyFactory(ExecutionContext* context)
@@ -288,7 +288,7 @@ ScriptValue TrustedTypePolicyFactory::getTypeMapping(ScriptState* script_state,
// {tagname: { ["attributes"|"properties"]: { attribute: type }}}
if (!ns.IsEmpty())
- return ScriptValue();
+ return ScriptValue::CreateNull(script_state->GetIsolate());
v8::HandleScope handle_scope(script_state->GetIsolate());
v8::Local<v8::Object> top = v8::Object::New(script_state->GetIsolate());
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
index 3d5b850ac13..e3810ce6b49 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -4,13 +4,11 @@
#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
+#include "base/unguessable_token.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_treat_null_as_empty_string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedhtml_trustedscript_trustedscripturl.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedscript.h"
@@ -18,6 +16,8 @@
#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/console_message.h"
+#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
+#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
@@ -113,10 +113,10 @@ const char* GetMessage(TrustedTypeViolationKind kind) {
return "";
}
-String GetSamplePrefix(const ExceptionState& exception_state,
+String GetSamplePrefix(const ExceptionContext& exception_context,
const String& value) {
- const char* interface_name = exception_state.InterfaceName();
- const char* property_name = exception_state.PropertyName();
+ const char* interface_name = exception_context.GetClassName();
+ const char* property_name = exception_context.GetPropertyName();
// We have two sample formats, one for eval and one for assignment.
// If we don't have the required values being passed in, just leave the
@@ -156,13 +156,13 @@ const char* GetElementName(const ScriptElementBase::Type type) {
HeapVector<ScriptValue> GetDefaultCallbackArgs(
v8::Isolate* isolate,
const char* type,
- const ExceptionState& exception_state,
+ const ExceptionContext& exception_context,
const String& value = g_empty_string) {
ScriptState* script_state = ScriptState::Current(isolate);
HeapVector<ScriptValue> args;
args.push_back(ScriptValue::From(script_state, type));
- args.push_back(
- ScriptValue::From(script_state, GetSamplePrefix(exception_state, value)));
+ args.push_back(ScriptValue::From(script_state,
+ GetSamplePrefix(exception_context, value)));
return args;
}
@@ -186,14 +186,20 @@ bool TrustedTypeFail(TrustedTypeViolationKind kind,
if (execution_context->GetTrustedTypes())
execution_context->GetTrustedTypes()->CountTrustedTypeAssignmentError();
- String prefix = GetSamplePrefix(exception_state, value);
+ String prefix = GetSamplePrefix(exception_state.GetContext(), value);
+ // This issue_id is used to generate a link in the DevTools front-end from
+ // the JavaScript TypeError to the inspector issue which is reported by
+ // ContentSecurityPolicy::ReportViolation via the call to
+ // AllowTrustedTypeAssignmentFailure below.
+ base::UnguessableToken issue_id = base::UnguessableToken::Create();
bool allow =
execution_context->GetContentSecurityPolicy()
->AllowTrustedTypeAssignmentFailure(
GetMessage(kind),
- prefix == "Function" ? value.Substring(strlen(kAnonymousPrefix))
+ prefix == "Function" ? value.Substring(static_cast<wtf_size_t>(
+ strlen(kAnonymousPrefix)))
: value,
- prefix);
+ prefix, issue_id);
// TODO(1087743): Add a console message for Trusted Type-related Function
// constructor failures, to warn the developer of the outstanding issues
@@ -217,6 +223,15 @@ bool TrustedTypeFail(TrustedTypeViolationKind kind,
if (!allow) {
exception_state.ThrowTypeError(GetMessage(kind));
+ v8::Local<v8::Value> exception = exception_state.GetException();
+ if (!exception.IsEmpty()) {
+ v8::Isolate* isolate = execution_context->GetIsolate();
+ ThreadDebugger* debugger = ThreadDebugger::From(isolate);
+ debugger->GetV8Inspector()->associateExceptionData(
+ v8::Local<v8::Context>(), exception,
+ V8AtomicString(isolate, "issueId"),
+ V8String(isolate, IdentifiersFactory::IdFromToken(issue_id)));
+ }
}
return !allow;
}
@@ -280,7 +295,7 @@ String GetStringFromScriptHelper(
TrustedScript* result = default_policy->CreateScript(
context->GetIsolate(), script,
GetDefaultCallbackArgs(context->GetIsolate(), "TrustedScript",
- exception_state, script),
+ exception_state.GetContext(), script),
exception_state);
if (exception_state.HadException()) {
exception_state.ClearException();
@@ -336,7 +351,7 @@ String TrustedTypesCheckForHTML(String html,
TrustedHTML* result = default_policy->CreateHTML(
execution_context->GetIsolate(), html,
GetDefaultCallbackArgs(execution_context->GetIsolate(), "TrustedHTML",
- exception_state),
+ exception_state.GetContext()),
exception_state);
if (exception_state.HadException()) {
return g_empty_string;
@@ -385,7 +400,7 @@ String TrustedTypesCheckForScript(String script,
TrustedScript* result = default_policy->CreateScript(
execution_context->GetIsolate(), script,
GetDefaultCallbackArgs(execution_context->GetIsolate(), "TrustedScript",
- exception_state, script),
+ exception_state.GetContext(), script),
exception_state);
DCHECK_EQ(!result, exception_state.HadException());
if (exception_state.HadException()) {
@@ -437,7 +452,7 @@ String TrustedTypesCheckForScriptURL(String script_url,
TrustedScriptURL* result = default_policy->CreateScriptURL(
execution_context->GetIsolate(), script_url,
GetDefaultCallbackArgs(execution_context->GetIsolate(),
- "TrustedScriptURL", exception_state),
+ "TrustedScriptURL", exception_state.GetContext()),
exception_state);
if (exception_state.HadException()) {
@@ -456,7 +471,6 @@ String TrustedTypesCheckForScriptURL(String script_url,
return result->toString();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String TrustedTypesCheckFor(SpecificTrustedType type,
const V8TrustedString* trusted,
const ExecutionContext* execution_context,
@@ -491,40 +505,6 @@ String TrustedTypesCheckFor(SpecificTrustedType type,
return TrustedTypesCheckFor(type, std::move(value), execution_context,
exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-String TrustedTypesCheckFor(
- SpecificTrustedType type,
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& trusted,
- const ExecutionContext* execution_context,
- ExceptionState& exception_state) {
- // Whatever happens below, we will need the string value:
- String value;
- if (trusted.IsTrustedHTML()) {
- value = trusted.GetAsTrustedHTML()->toString();
- } else if (trusted.IsTrustedScript()) {
- value = trusted.GetAsTrustedScript()->toString();
- } else if (trusted.IsTrustedScriptURL()) {
- value = trusted.GetAsTrustedScriptURL()->toString();
- } else if (trusted.IsString()) {
- value = trusted.GetAsString();
- } // else: trusted.IsNull(). But we don't have anything to do in that case.
-
- // The check passes if we have the proper trusted type:
- if (type == SpecificTrustedType::kNone ||
- (trusted.IsTrustedHTML() && type == SpecificTrustedType::kHTML) ||
- (trusted.IsTrustedScript() && type == SpecificTrustedType::kScript) ||
- (trusted.IsTrustedScriptURL() &&
- type == SpecificTrustedType::kScriptURL)) {
- return value;
- }
-
- // In all other cases: run the full check against the string value.
- return TrustedTypesCheckFor(type, std::move(value), execution_context,
- exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String TrustedTypesCheckForScript(const V8UnionStringOrTrustedScript* value,
const ExecutionContext* execution_context,
@@ -578,49 +558,6 @@ String TrustedTypesCheckForScript(
return String();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-String TrustedTypesCheckForScript(const StringOrTrustedScript& trusted,
- const ExecutionContext* execution_context,
- ExceptionState& exception_state) {
- // To remain compatible with legacy behaviour, HTMLElement uses extended IDL
- // attributes to allow for nullable union of (DOMString or TrustedScript).
- // Thus, this method is required to handle the case where
- // string_or_trusted_script.IsNull(), unlike the various similar methods in
- // this file.
- if (trusted.IsTrustedScript()) {
- return trusted.GetAsTrustedScript()->toString();
- }
- if (trusted.IsNull()) {
- return TrustedTypesCheckForScript(g_empty_string, execution_context,
- exception_state);
- }
- return TrustedTypesCheckForScript(trusted.GetAsString(), execution_context,
- exception_state);
-}
-
-String TrustedTypesCheckForScript(
- const StringTreatNullAsEmptyStringOrTrustedScript& trusted,
- const ExecutionContext* execution_context,
- ExceptionState& exception_state) {
- // To remain compatible with legacy behaviour, HTMLElement uses extended IDL
- // attributes to allow for nullable union of (DOMString or TrustedScript).
- // Thus, this method is required to handle the case where
- // string_or_trusted_script.IsNull(), unlike the various similar methods in
- // this file.
- if (trusted.IsTrustedScript()) {
- return trusted.GetAsTrustedScript()->toString();
- }
- if (trusted.IsNull()) {
- return TrustedTypesCheckForScript(g_empty_string, execution_context,
- exception_state);
- }
- return TrustedTypesCheckForScript(trusted.GetAsString(), execution_context,
- exception_state);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
String TrustedTypesCheckFor(SpecificTrustedType type,
String trusted,
const ExecutionContext* execution_context,
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
index 9082c3824ce..e11c834c297 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
@@ -14,9 +14,6 @@ namespace blink {
class ExceptionState;
class ExecutionContext;
-class StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL;
-class StringOrTrustedScript;
-class StringTreatNullAsEmptyStringOrTrustedScript;
class V8UnionStringOrTrustedScript;
class V8UnionStringTreatNullAsEmptyStringOrTrustedScript;
@@ -29,20 +26,11 @@ enum class SpecificTrustedType {
// Perform Trusted Type checks, with the IDL union types as input. All of these
// will call String& versions below to do the heavy lifting.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CORE_EXPORT String
TrustedTypesCheckFor(SpecificTrustedType type,
const V8TrustedString* trusted,
const ExecutionContext* execution_context,
ExceptionState& exception_state) WARN_UNUSED_RESULT;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CORE_EXPORT String TrustedTypesCheckFor(
- SpecificTrustedType,
- const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&,
- const ExecutionContext*,
- ExceptionState&) WARN_UNUSED_RESULT;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CORE_EXPORT String
TrustedTypesCheckForScript(const V8UnionStringOrTrustedScript* value,
const ExecutionContext* execution_context,
@@ -51,16 +39,6 @@ CORE_EXPORT String TrustedTypesCheckForScript(
const V8UnionStringTreatNullAsEmptyStringOrTrustedScript* value,
const ExecutionContext* execution_context,
ExceptionState& exception_state) WARN_UNUSED_RESULT;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CORE_EXPORT String TrustedTypesCheckForScript(const StringOrTrustedScript&,
- const ExecutionContext*,
- ExceptionState&)
- WARN_UNUSED_RESULT;
-CORE_EXPORT String
-TrustedTypesCheckForScript(const StringTreatNullAsEmptyStringOrTrustedScript&,
- const ExecutionContext*,
- ExceptionState&) WARN_UNUSED_RESULT;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Perform Trusted Type checks, for a dynamically or statically determined
// type.
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
index 86bfe28f970..fe479556522 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
@@ -6,8 +6,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedscript.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -86,11 +84,7 @@ void TrustedTypesCheckForScriptURLThrows(const String& string) {
}
void TrustedTypesCheckForScriptWorks(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionStringOrTrustedScript* string_or_trusted_script,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrTrustedScript& string_or_trusted_script,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String expected) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
LocalDOMWindow* window = dummy_page_holder->GetFrame().DomWindow();
@@ -109,13 +103,8 @@ TEST(TrustedTypesUtilTest, TrustedTypesCheckForHTML_String) {
// TrustedTypesCheckForScript tests
TEST(TrustedTypesUtilTest, TrustedTypesCheckForScript_TrustedScript) {
auto* script = MakeGarbageCollected<TrustedScript>("A string");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* trusted_value =
MakeGarbageCollected<V8UnionStringOrTrustedScript>(script);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrTrustedScript trusted_value =
- StringOrTrustedScript::FromTrustedScript(script);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
TrustedTypesCheckForScriptWorks(trusted_value, "A string");
}
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/BUILD.gn b/chromium/third_party/blink/renderer/core/typed_arrays/BUILD.gn
deleted file mode 100644
index 19e064c3efe..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/BUILD.gn
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/blink/renderer/core/core.gni")
-
-blink_core_sources("typed_arrays") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
- sources = [
- "array_buffer/array_buffer_contents.cc",
- "array_buffer/array_buffer_contents.h",
- "array_buffer_view_helpers.h",
- "dom_array_buffer.cc",
- "dom_array_buffer.h",
- "dom_array_buffer_base.h",
- "dom_array_buffer_view.h",
- "dom_array_piece.cc",
- "dom_array_piece.h",
- "dom_data_view.cc",
- "dom_data_view.h",
- "dom_shared_array_buffer.cc",
- "dom_shared_array_buffer.h",
- "dom_typed_array.cc",
- "dom_typed_array.h",
- "flexible_array_buffer_view.h",
- "typed_flexible_array_buffer_view.h",
- ]
-
- deps = [ "//third_party/blink/renderer/core:core_generated" ]
-
- allow_circular_includes_from =
- [ "//third_party/blink/renderer/core:core_generated" ]
-}
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer.idl b/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer.idl
deleted file mode 100644
index b31110f8376..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer.idl
+++ /dev/null
@@ -1,12 +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.
-
-// http://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer-constructor
-
-[
- ImplementedAs=DOMArrayBuffer,
- LegacyNoInterfaceObject
-] interface ArrayBuffer {
- readonly attribute unsigned long byteLength;
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h b/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
index fcf19e66856..03fcc368bcc 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
@@ -28,7 +28,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_ARRAY_BUFFER_ARRAY_BUFFER_CONTENTS_H_
#include "base/allocator/partition_allocator/page_allocator.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer_view.idl b/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer_view.idl
deleted file mode 100644
index 3f5267fb8bb..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer_view.idl
+++ /dev/null
@@ -1,14 +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://www.khronos.org/registry/typedarray/specs/latest/#ARRAYBUFFERVIEW
-
-[
- ImplementedAs=DOMArrayBufferView,
- LegacyNoInterfaceObject
-] interface ArrayBufferView {
- readonly attribute ArrayBuffer buffer;
- readonly attribute unsigned long byteOffset;
- readonly attribute unsigned long byteLength;
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/big_int_64_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/big_int_64_array.idl
deleted file mode 100644
index 36902494608..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/big_int_64_array.idl
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMBigInt64Array,
- LegacyNoInterfaceObject
-] interface BigInt64Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/big_uint_64_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/big_uint_64_array.idl
deleted file mode 100644
index 4cefca30379..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/big_uint_64_array.idl
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMBigUint64Array,
- LegacyNoInterfaceObject
-] interface BigUint64Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/build.gni b/chromium/third_party/blink/renderer/core/typed_arrays/build.gni
new file mode 100644
index 00000000000..39ef7d77fe0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/build.gni
@@ -0,0 +1,24 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+blink_core_sources_typed_arrays = [
+ "array_buffer/array_buffer_contents.cc",
+ "array_buffer/array_buffer_contents.h",
+ "array_buffer_view_helpers.h",
+ "dom_array_buffer.cc",
+ "dom_array_buffer.h",
+ "dom_array_buffer_base.h",
+ "dom_array_buffer_view.cc",
+ "dom_array_buffer_view.h",
+ "dom_array_piece.cc",
+ "dom_array_piece.h",
+ "dom_data_view.cc",
+ "dom_data_view.h",
+ "dom_shared_array_buffer.cc",
+ "dom_shared_array_buffer.h",
+ "dom_typed_array.cc",
+ "dom_typed_array.h",
+ "flexible_array_buffer_view.h",
+ "typed_flexible_array_buffer_view.h",
+]
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/data_view.idl b/chromium/third_party/blink/renderer/core/typed_arrays/data_view.idl
deleted file mode 100644
index 8723dc10d55..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/data_view.idl
+++ /dev/null
@@ -1,31 +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 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.
- */
-
-// https://www.khronos.org/registry/typedarray/specs/latest/#DATAVIEW
-
-[
- ImplementedAs=DOMDataView
-] interface DataView : ArrayBufferView {
-};
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 ea420e7e8f7..9306dff11cd 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
@@ -10,10 +10,38 @@
#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/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
+// Construction of WrapperTypeInfo may require non-trivial initialization due
+// to cross-component address resolution in order to load the pointer to the
+// parent interface's WrapperTypeInfo. We ignore this issue because the issue
+// happens only on component builds and the official release builds
+// (statically-linked builds) are never affected by this issue.
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+#endif
+
+const WrapperTypeInfo DOMArrayBuffer::wrapper_type_info_body_{
+ gin::kEmbedderBlink,
+ nullptr,
+ nullptr,
+ "ArrayBuffer",
+ nullptr,
+ WrapperTypeInfo::kWrapperTypeObjectPrototype,
+ WrapperTypeInfo::kObjectClassId,
+ WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
+ WrapperTypeInfo::kIdlBufferSourceType,
+};
+
+const WrapperTypeInfo& DOMArrayBuffer::wrapper_type_info_ =
+ DOMArrayBuffer::wrapper_type_info_body_;
+
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
static void AccumulateArrayBuffersForAllWorlds(
v8::Isolate* isolate,
DOMArrayBuffer* object,
@@ -158,4 +186,5 @@ DOMArrayBuffer* DOMArrayBuffer::Slice(size_t begin, size_t end) const {
size_t size = begin <= end ? end - begin : 0;
return Create(static_cast<const char*>(Data()) + begin, size);
}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
index 940b3d50c17..88a8256db16 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
@@ -16,6 +16,7 @@ namespace blink {
class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase {
DEFINE_WRAPPERTYPEINFO();
+ static const WrapperTypeInfo wrapper_type_info_body_;
public:
static DOMArrayBuffer* Create(ArrayBufferContents contents) {
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.cc b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.cc
new file mode 100644
index 00000000000..8c5b63fb6cf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.cc
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
+
+namespace blink {
+
+// Construction of WrapperTypeInfo may require non-trivial initialization due
+// to cross-component address resolution in order to load the pointer to the
+// parent interface's WrapperTypeInfo. We ignore this issue because the issue
+// happens only on component builds and the official release builds
+// (statically-linked builds) are never affected by this issue.
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+#endif
+
+const WrapperTypeInfo DOMArrayBufferView::wrapper_type_info_body_{
+ gin::kEmbedderBlink,
+ nullptr,
+ nullptr,
+ "ArrayBufferView",
+ nullptr,
+ WrapperTypeInfo::kWrapperTypeObjectPrototype,
+ WrapperTypeInfo::kObjectClassId,
+ WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
+ WrapperTypeInfo::kIdlBufferSourceType,
+};
+
+const WrapperTypeInfo& DOMArrayBufferView::wrapper_type_info_ =
+ DOMArrayBufferView::wrapper_type_info_body_;
+
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h
index 9388089b0ae..eaaef1d907c 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h
@@ -14,6 +14,7 @@ namespace blink {
class CORE_EXPORT DOMArrayBufferView : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
+ static const WrapperTypeInfo wrapper_type_info_body_;
public:
enum ViewType {
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.cc b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.cc
index 1fac3b137f8..0c374d1d2de 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.cc
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
namespace blink {
@@ -21,7 +20,6 @@ DOMArrayPiece::DOMArrayPiece(DOMArrayBufferView* buffer) {
InitWithArrayBufferView(buffer);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DOMArrayPiece::DOMArrayPiece(
const V8UnionArrayBufferOrArrayBufferView* array_buffer_or_view) {
DCHECK(array_buffer_or_view);
@@ -39,20 +37,6 @@ DOMArrayPiece::DOMArrayPiece(
NOTREACHED();
InitNull();
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-// TODO(crbug.com/1181288): Remove the old IDL union version.
-DOMArrayPiece::DOMArrayPiece(
- const ArrayBufferOrArrayBufferView& array_buffer_or_view) {
- if (array_buffer_or_view.IsArrayBuffer()) {
- DOMArrayBuffer* array_buffer = array_buffer_or_view.GetAsArrayBuffer();
- InitWithArrayBuffer(array_buffer);
- } else if (array_buffer_or_view.IsArrayBufferView()) {
- DOMArrayBufferView* array_buffer_view =
- array_buffer_or_view.GetAsArrayBufferView().Get();
- InitWithArrayBufferView(array_buffer_view);
- }
-}
bool DOMArrayPiece::IsNull() const {
return is_null_;
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.h b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.h
index 1b4250013d1..b3afee67352 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_piece.h
@@ -10,7 +10,6 @@
namespace blink {
-class ArrayBufferOrArrayBufferView;
class DOMArrayBufferView;
class V8UnionArrayBufferOrArrayBufferView;
@@ -28,14 +27,13 @@ class CORE_EXPORT DOMArrayPiece {
public:
DOMArrayPiece();
+ // NOLINTNEXTLINE(google-explicit-constructor)
DOMArrayPiece(DOMArrayBuffer* buffer);
+ // NOLINTNEXTLINE(google-explicit-constructor)
DOMArrayPiece(DOMArrayBufferView* view);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ // NOLINTNEXTLINE(google-explicit-constructor)
DOMArrayPiece(
const V8UnionArrayBufferOrArrayBufferView* array_buffer_or_view);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- // TODO(crbug.com/1181288): Remove the old IDL union version.
- DOMArrayPiece(const ArrayBufferOrArrayBufferView&);
bool operator==(const DOMArrayBuffer& other) const {
return ByteLength() == other.ByteLength() &&
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 e22d375713f..692b9074d81 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
@@ -6,11 +6,39 @@
#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
namespace blink {
+// Construction of WrapperTypeInfo may require non-trivial initialization due
+// to cross-component address resolution in order to load the pointer to the
+// parent interface's WrapperTypeInfo. We ignore this issue because the issue
+// happens only on component builds and the official release builds
+// (statically-linked builds) are never affected by this issue.
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+#endif
+
+const WrapperTypeInfo DOMDataView::wrapper_type_info_body_{
+ gin::kEmbedderBlink,
+ nullptr,
+ nullptr,
+ "DataView",
+ nullptr,
+ WrapperTypeInfo::kWrapperTypeObjectPrototype,
+ WrapperTypeInfo::kObjectClassId,
+ WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
+ WrapperTypeInfo::kIdlBufferSourceType,
+};
+
+const WrapperTypeInfo& DOMDataView::wrapper_type_info_ =
+ DOMDataView::wrapper_type_info_body_;
+
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
DOMDataView* DOMDataView::Create(DOMArrayBufferBase* buffer,
size_t byte_offset,
size_t byte_length) {
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.h b/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.h
index e44260fbebc..bb70da7b7a3 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.h
@@ -12,6 +12,7 @@ namespace blink {
class CORE_EXPORT DOMDataView final : public DOMArrayBufferView {
DEFINE_WRAPPERTYPEINFO();
+ static const WrapperTypeInfo wrapper_type_info_body_;
public:
typedef char ValueType;
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.cc b/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.cc
index fa660a2ac90..244d557622b 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.cc
@@ -8,6 +8,35 @@
namespace blink {
+// Construction of WrapperTypeInfo may require non-trivial initialization due
+// to cross-component address resolution in order to load the pointer to the
+// parent interface's WrapperTypeInfo. We ignore this issue because the issue
+// happens only on component builds and the official release builds
+// (statically-linked builds) are never affected by this issue.
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+#endif
+
+const WrapperTypeInfo DOMSharedArrayBuffer::wrapper_type_info_body_{
+ gin::kEmbedderBlink,
+ nullptr,
+ nullptr,
+ "SharedArrayBuffer",
+ nullptr,
+ WrapperTypeInfo::kWrapperTypeObjectPrototype,
+ WrapperTypeInfo::kObjectClassId,
+ WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
+ WrapperTypeInfo::kIdlBufferSourceType,
+};
+
+const WrapperTypeInfo& DOMSharedArrayBuffer::wrapper_type_info_ =
+ DOMSharedArrayBuffer::wrapper_type_info_body_;
+
+#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
v8::MaybeLocal<v8::Value> DOMSharedArrayBuffer::Wrap(
ScriptState* script_state) {
DCHECK(!DOMDataStore::ContainsWrapper(this, script_state->GetIsolate()));
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h b/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h
index 7c26fda73bd..7a39c9a1dd4 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h
@@ -14,6 +14,7 @@ namespace blink {
class CORE_EXPORT DOMSharedArrayBuffer final : public DOMArrayBufferBase {
DEFINE_WRAPPERTYPEINFO();
+ static const WrapperTypeInfo wrapper_type_info_body_;
public:
static DOMSharedArrayBuffer* Create(ArrayBufferContents contents) {
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.cc b/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.cc
index ac23996a992..abe04a2c466 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.cc
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.cc
@@ -5,18 +5,6 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_big_int_64_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_big_uint_64_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_float32_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_float64_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_int16_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_int32_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_int8_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint16_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint32_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_clamped_array.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
namespace blink {
@@ -51,47 +39,46 @@ v8::MaybeLocal<v8::Value> DOMTypedArray<T, V8TypedArray, clamped>::Wrap(
wrapper);
}
-// TODO(tasak): The following traits should be auto-generated by binding
-// script and should be placed in bindings/core/v8/V8*Array.h.
-template <typename ArrayType>
-struct DOMTypedArrayTraits {};
+#define DOMTYPEDARRAY_FOREACH_VIEW_TYPE(V) \
+ V(int8_t, Int8, false) \
+ V(int16_t, Int16, false) \
+ V(int32_t, Int32, false) \
+ V(uint8_t, Uint8, false) \
+ V(uint8_t, Uint8Clamped, true) \
+ V(uint16_t, Uint16, false) \
+ V(uint32_t, Uint32, false) \
+ V(float, Float32, false) \
+ V(double, Float64, false) \
+ V(int64_t, BigInt64, false) \
+ V(uint64_t, BigUint64, false)
-#define DEFINE_DOMTYPEDARRAY_TRAITS(ArrayType, V8BindingType) \
- template <> \
- struct DOMTypedArrayTraits<ArrayType> { \
- typedef V8BindingType Type; \
- }
-
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMInt8Array, V8Int8Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMInt16Array, V8Int16Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMInt32Array, V8Int32Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMUint8Array, V8Uint8Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMUint8ClampedArray, V8Uint8ClampedArray);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMUint16Array, V8Uint16Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMUint32Array, V8Uint32Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMBigInt64Array, V8BigInt64Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMBigUint64Array, V8BigUint64Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMFloat32Array, V8Float32Array);
-DEFINE_DOMTYPEDARRAY_TRAITS(DOMFloat64Array, V8Float64Array);
+#define DOMTYPEDARRAY_DEFINE_WRAPPERTYPEINFO(val_t, Type, clamped) \
+ template <> \
+ const WrapperTypeInfo \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>::wrapper_type_info_body_{ \
+ gin::kEmbedderBlink, \
+ nullptr, \
+ nullptr, \
+ #Type "Array", \
+ nullptr, \
+ WrapperTypeInfo::kWrapperTypeObjectPrototype, \
+ WrapperTypeInfo::kObjectClassId, \
+ WrapperTypeInfo::kNotInheritFromActiveScriptWrappable, \
+ WrapperTypeInfo::kIdlBufferSourceType, \
+ }; \
+ template <> \
+ const WrapperTypeInfo& DOMTypedArray<val_t, v8::Type##Array, \
+ clamped>::wrapper_type_info_ = \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>::wrapper_type_info_body_;
+DOMTYPEDARRAY_FOREACH_VIEW_TYPE(DOMTYPEDARRAY_DEFINE_WRAPPERTYPEINFO)
+#undef DOMTYPEDARRAY_DEFINE_WRAPPERTYPEINFO
-template <typename T, typename V8TypedArray, bool clamped>
-const WrapperTypeInfo*
-DOMTypedArray<T, V8TypedArray, clamped>::GetWrapperTypeInfo() const {
- return DOMTypedArrayTraits<
- DOMTypedArray<T, V8TypedArray, clamped>>::Type::GetWrapperTypeInfo();
-}
+#define DOMTYPEDARRAY_EXPLICITLY_INSTANTIATE(val_t, Type, clamped) \
+ template class CORE_TEMPLATE_EXPORT \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>;
+DOMTYPEDARRAY_FOREACH_VIEW_TYPE(DOMTYPEDARRAY_EXPLICITLY_INSTANTIATE)
+#undef DOMTYPEDARRAY_EXPLICITLY_INSTANTIATE
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<int8_t, v8::Int8Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<int16_t, v8::Int16Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<int32_t, v8::Int32Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<uint8_t, v8::Uint8Array>;
-template class CORE_TEMPLATE_EXPORT
- DOMTypedArray<uint8_t, v8::Uint8ClampedArray, /*clamped=*/true>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<uint16_t, v8::Uint16Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<uint32_t, v8::Uint32Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<int64_t, v8::BigInt64Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<uint64_t, v8::BigUint64Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<float, v8::Float32Array>;
-template class CORE_TEMPLATE_EXPORT DOMTypedArray<double, v8::Float64Array>;
+#undef DOMTYPEDARRAY_FOREACH_VIEW_TYPE
} // namespace blink
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 bf59ee58ede..126aad413f4 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
@@ -7,42 +7,23 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "v8/include/v8.h"
namespace blink {
-namespace {
-// Helper to verify that a given sub-range of an ArrayBuffer is within range.
-template <typename T>
-bool VerifySubRange(const DOMArrayBufferBase* buffer,
- size_t byte_offset,
- size_t num_elements) {
- if (!buffer)
- return false;
- if (sizeof(T) > 1 && byte_offset % sizeof(T))
- return false;
- if (byte_offset > buffer->ByteLength())
- return false;
- size_t remaining_elements = (buffer->ByteLength() - byte_offset) / sizeof(T);
- if (num_elements > remaining_elements)
- return false;
- return true;
-}
-} // namespace
-
template <typename T, typename V8TypedArray, bool clamped = false>
class DOMTypedArray final : public DOMArrayBufferView {
typedef DOMTypedArray<T, V8TypedArray, clamped> ThisType;
- DECLARE_WRAPPERTYPEINFO();
+ DEFINE_WRAPPERTYPEINFO();
+ static const WrapperTypeInfo wrapper_type_info_body_;
public:
typedef T ValueType;
+
static ThisType* Create(DOMArrayBufferBase* buffer,
size_t byte_offset,
size_t length) {
- CHECK(VerifySubRange<ValueType>(buffer, byte_offset, length));
+ CHECK(VerifySubRange(buffer, byte_offset, length));
return MakeGarbageCollected<ThisType>(buffer, byte_offset, length);
}
@@ -99,75 +80,71 @@ class DOMTypedArray final : public DOMArrayBufferView {
v8::MaybeLocal<v8::Value> Wrap(ScriptState*) override;
private:
+ // Helper to verify that a given sub-range of an ArrayBuffer is within range.
+ static bool VerifySubRange(const DOMArrayBufferBase* buffer,
+ size_t byte_offset,
+ size_t num_elements) {
+ if (!buffer)
+ return false;
+ if (sizeof(T) > 1 && byte_offset % sizeof(T))
+ return false;
+ if (byte_offset > buffer->ByteLength())
+ return false;
+ size_t remaining_elements =
+ (buffer->ByteLength() - byte_offset) / sizeof(T);
+ if (num_elements > remaining_elements)
+ return false;
+ return true;
+ }
+
// It may be stale after Detach. Use length() instead.
size_t raw_length_;
};
-#define FOREACH_VIEW_TYPE(V) \
- V(int8_t, v8::Int8Array, kTypeInt8) \
- V(int16_t, v8::Int16Array, kTypeInt16) \
- V(int32_t, v8::Int32Array, kTypeInt32) \
- V(uint8_t, v8::Uint8Array, kTypeUint8) \
- V(uint16_t, v8::Uint16Array, kTypeUint16) \
- V(uint32_t, v8::Uint32Array, kTypeUint32) \
- V(float, v8::Float32Array, kTypeFloat32) \
- V(double, v8::Float64Array, kTypeFloat64) \
- V(int64_t, v8::BigInt64Array, kTypeBigInt64) \
- V(uint64_t, v8::BigUint64Array, kTypeBigUint64)
-
-#define GET_TYPE(c_type, v8_type, view_type) \
- template <> \
- inline DOMArrayBufferView::ViewType \
- DOMTypedArray<c_type, v8_type, false>::GetType() const { \
- return DOMArrayBufferView::view_type; \
+#define DOMTYPEDARRAY_FOREACH_VIEW_TYPE(V) \
+ V(int8_t, Int8, false) \
+ V(int16_t, Int16, false) \
+ V(int32_t, Int32, false) \
+ V(uint8_t, Uint8, false) \
+ V(uint8_t, Uint8Clamped, true) \
+ V(uint16_t, Uint16, false) \
+ V(uint32_t, Uint32, false) \
+ V(float, Float32, false) \
+ V(double, Float64, false) \
+ V(int64_t, BigInt64, false) \
+ V(uint64_t, BigUint64, false)
+
+#define DOMTYPEDARRAY_DECLARE_WRAPPERTYPEINFO(val_t, Type, clamped) \
+ template <> \
+ const WrapperTypeInfo \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>::wrapper_type_info_body_; \
+ template <> \
+ const WrapperTypeInfo& \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>::wrapper_type_info_;
+DOMTYPEDARRAY_FOREACH_VIEW_TYPE(DOMTYPEDARRAY_DECLARE_WRAPPERTYPEINFO)
+#undef DOMTYPEDARRAY_DECLARE_WRAPPERTYPEINFO
+
+#define DOMTYPEDARRAY_DEFINE_GETTYPE(val_t, Type, clamped) \
+ template <> \
+ inline DOMArrayBufferView::ViewType \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>::GetType() const { \
+ return DOMArrayBufferView::kType##Type; \
}
+DOMTYPEDARRAY_FOREACH_VIEW_TYPE(DOMTYPEDARRAY_DEFINE_GETTYPE)
+#undef DOMTYPEDARRAY_DEFINE_GETTYPE
+
+#define DOMTYPEDARRAY_DECLARE_EXTERN_TEMPLATE(val_t, Type, clamped) \
+ extern template class CORE_EXTERN_TEMPLATE_EXPORT \
+ DOMTypedArray<val_t, v8::Type##Array, clamped>;
+DOMTYPEDARRAY_FOREACH_VIEW_TYPE(DOMTYPEDARRAY_DECLARE_EXTERN_TEMPLATE)
+#undef DOMTYPEDARRAY_DECLARE_EXTERN_TEMPLATE
+
+#define DOMTYPEDARRAY_DEFINE_TYPEDEFNAME(val_t, Type, clamped) \
+ using DOM##Type##Array = DOMTypedArray<val_t, v8::Type##Array, clamped>;
+DOMTYPEDARRAY_FOREACH_VIEW_TYPE(DOMTYPEDARRAY_DEFINE_TYPEDEFNAME)
+#undef DOMTYPEDARRAY_DEFINE_TYPEDEFNAME
-FOREACH_VIEW_TYPE(GET_TYPE)
-
-#undef GET_TYPE
-#undef FOREACH_VIEW_TYPE
-
-template <>
-inline DOMArrayBufferView::ViewType
-DOMTypedArray<uint8_t, v8::Uint8ClampedArray, true>::GetType() const {
- return DOMArrayBufferView::kTypeUint8Clamped;
-}
-
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<int8_t, v8::Int8Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<int16_t, v8::Int16Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<int32_t, v8::Int32Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<uint8_t, v8::Uint8Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<uint8_t, v8::Uint8ClampedArray, /*clamped=*/true>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<uint16_t, v8::Uint16Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<uint32_t, v8::Uint32Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<int64_t, v8::BigInt64Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<uint64_t, v8::BigUint64Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<float, v8::Float32Array>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
- DOMTypedArray<double, v8::Float64Array>;
-
-typedef DOMTypedArray<int8_t, v8::Int8Array> DOMInt8Array;
-typedef DOMTypedArray<int16_t, v8::Int16Array> DOMInt16Array;
-typedef DOMTypedArray<int32_t, v8::Int32Array> DOMInt32Array;
-typedef DOMTypedArray<uint8_t, v8::Uint8Array> DOMUint8Array;
-typedef DOMTypedArray<uint8_t, v8::Uint8ClampedArray, /*clamped=*/true>
- DOMUint8ClampedArray;
-typedef DOMTypedArray<uint16_t, v8::Uint16Array> DOMUint16Array;
-typedef DOMTypedArray<uint32_t, v8::Uint32Array> DOMUint32Array;
-typedef DOMTypedArray<int64_t, v8::BigInt64Array> DOMBigInt64Array;
-typedef DOMTypedArray<uint64_t, v8::BigUint64Array> DOMBigUint64Array;
-typedef DOMTypedArray<float, v8::Float32Array> DOMFloat32Array;
-typedef DOMTypedArray<double, v8::Float64Array> DOMFloat64Array;
+#undef DOMTYPEDARRAY_FOREACH_VIEW_TYPE
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h b/chromium/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h
index 62c4e334d04..4927e44a18f 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h
@@ -5,8 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_FLEXIBLE_ARRAY_BUFFER_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_FLEXIBLE_ARRAY_BUFFER_VIEW_H_
-#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -46,7 +45,11 @@ class CORE_EXPORT FlexibleArrayBufferView {
small_data_ = small_buffer_;
small_length_ = size;
} else {
- full_ = V8ArrayBufferView::ToImpl(array_buffer_view);
+ NonThrowableExceptionState exception_state;
+ full_ = NativeValueTraits<MaybeShared<DOMArrayBufferView>>::NativeValue(
+ array_buffer_view->GetIsolate(), array_buffer_view,
+ exception_state)
+ .Get();
}
}
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/float32_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/float32_array.idl
deleted file mode 100644
index f178206cf17..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/float32_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMFloat32Array,
- LegacyNoInterfaceObject
-] interface Float32Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/float64_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/float64_array.idl
deleted file mode 100644
index 7dc131e8c96..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/float64_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMFloat64Array,
- LegacyNoInterfaceObject
-] interface Float64Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/int16_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/int16_array.idl
deleted file mode 100644
index 86f4deb79c5..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/int16_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMInt16Array,
- LegacyNoInterfaceObject
-] interface Int16Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/int32_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/int32_array.idl
deleted file mode 100644
index 15c9a31b246..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/int32_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMInt32Array,
- LegacyNoInterfaceObject
-] interface Int32Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/int8_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/int8_array.idl
deleted file mode 100644
index 5c4fee87727..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/int8_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMInt8Array,
- LegacyNoInterfaceObject
-] interface Int8Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/shared_array_buffer.idl b/chromium/third_party/blink/renderer/core/typed_arrays/shared_array_buffer.idl
deleted file mode 100644
index 52b32ebbd26..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/shared_array_buffer.idl
+++ /dev/null
@@ -1,12 +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.
-
-// Draft spec: https://github.com/lars-t-hansen/ecmascript_sharedmem
-[
- ImplementedAs=DOMSharedArrayBuffer,
- LegacyNoInterfaceObject,
- RuntimeEnabled=SharedArrayBuffer
-] interface SharedArrayBuffer {
- readonly attribute unsigned long byteLength;
-};
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 5eac3e79085..fd4e39e792a 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_TYPED_FLEXIBLE_ARRAY_BUFFER_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_TYPED_FLEXIBLE_ARRAY_BUFFER_VIEW_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/uint16_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/uint16_array.idl
deleted file mode 100644
index 89e3858a352..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/uint16_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMUint16Array,
- LegacyNoInterfaceObject
-] interface Uint16Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/uint32_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/uint32_array.idl
deleted file mode 100644
index c41c7da32c8..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/uint32_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMUint32Array,
- LegacyNoInterfaceObject
-] interface Uint32Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/uint8_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/uint8_array.idl
deleted file mode 100644
index 06adfb7e641..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/uint8_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMUint8Array,
- LegacyNoInterfaceObject
-] interface Uint8Array : ArrayBufferView {
-};
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/uint8_clamped_array.idl b/chromium/third_party/blink/renderer/core/typed_arrays/uint8_clamped_array.idl
deleted file mode 100644
index a413c840445..00000000000
--- a/chromium/third_party/blink/renderer/core/typed_arrays/uint8_clamped_array.idl
+++ /dev/null
@@ -1,11 +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://www.khronos.org/registry/typedarray/specs/latest/#TYPEDARRAYS
-
-[
- ImplementedAs=DOMUint8ClampedArray,
- LegacyNoInterfaceObject
-] interface Uint8ClampedArray : ArrayBufferView {
-};
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 336b3af30c9..2f0488283d7 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url.cc
+++ b/chromium/third_party/blink/renderer/core/url/dom_url.cc
@@ -35,15 +35,30 @@
namespace blink {
-DOMURL::DOMURL(const String& url,
- const KURL& base,
- ExceptionState& exception_state) {
- if (!base.IsValid()) {
+// static
+DOMURL* DOMURL::Create(const String& url, ExceptionState& exception_state) {
+ return MakeGarbageCollected<DOMURL>(PassKey(), url, NullURL(),
+ exception_state);
+}
+
+// static
+DOMURL* DOMURL::Create(const String& url,
+ const String& base,
+ ExceptionState& exception_state) {
+ KURL base_url(base);
+ if (!base_url.IsValid()) {
exception_state.ThrowTypeError("Invalid base URL");
- return;
+ return nullptr;
}
+ return MakeGarbageCollected<DOMURL>(PassKey(), url, base_url,
+ exception_state);
+}
- url_ = KURL(base, url);
+DOMURL::DOMURL(PassKey,
+ const String& url,
+ const KURL& base,
+ ExceptionState& exception_state)
+ : url_(base, url) {
if (!url_.IsValid())
exception_state.ThrowTypeError("Invalid URL");
}
@@ -55,15 +70,13 @@ void DOMURL::Trace(Visitor* visitor) const {
ScriptWrappable::Trace(visitor);
}
-void DOMURL::SetInput(const String& value) {
- KURL url(BlankURL(), value);
- if (url.IsValid()) {
- url_ = url;
- input_ = String();
- } else {
- url_ = KURL();
- input_ = value;
+void DOMURL::setHref(const String& value, ExceptionState& exception_state) {
+ KURL url(value);
+ if (!url.IsValid()) {
+ exception_state.ThrowTypeError("Invalid URL");
+ return;
}
+ url_ = url;
Update();
}
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 adb7f8c47f5..19e01e984b3 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url.h
+++ b/chromium/third_party/blink/renderer/core/url/dom_url.h
@@ -27,6 +27,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_URL_DOM_URL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_URL_DOM_URL_H_
+#include "base/types/pass_key.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/url/dom_url_utils.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -45,18 +46,14 @@ class CORE_EXPORT DOMURL final : public ScriptWrappable, public DOMURLUtils {
DEFINE_WRAPPERTYPEINFO();
public:
- static DOMURL* Create(const String& url, ExceptionState& exception_state) {
- return MakeGarbageCollected<DOMURL>(url, BlankURL(), exception_state);
- }
+ using PassKey = base::PassKey<DOMURL>;
+ static DOMURL* Create(const String& url, ExceptionState& exception_state);
static DOMURL* Create(const String& url,
const String& base,
- ExceptionState& exception_state) {
- return MakeGarbageCollected<DOMURL>(url, KURL(NullURL(), base),
- exception_state);
- }
+ ExceptionState& exception_state);
- DOMURL(const String& url, const KURL& base, ExceptionState&);
+ DOMURL(PassKey, const String& url, const KURL& base, ExceptionState&);
~DOMURL() override;
static String CreatePublicURL(ExecutionContext*, URLRegistrable*);
@@ -64,9 +61,13 @@ class CORE_EXPORT DOMURL final : public ScriptWrappable, public DOMURLUtils {
KURL Url() const override { return url_; }
void SetURL(const KURL& url) override { url_ = url; }
- String Input() const override { return input_; }
- void SetInput(const String&) override;
+ String Input() const override {
+ // Url() can never be null, so Input() is never called.
+ NOTREACHED();
+ return String();
+ }
+ void setHref(const String&, ExceptionState& exception_state);
void setSearch(const String&) override;
URLSearchParams* searchParams();
@@ -82,7 +83,6 @@ class CORE_EXPORT DOMURL final : public ScriptWrappable, public DOMURLUtils {
void UpdateSearchParams(const String&);
KURL url_;
- String input_;
WeakMember<URLSearchParams> search_params_;
};
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 694b3411648..32b8aae6b0b 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
@@ -33,10 +33,6 @@ namespace blink {
DOMURLUtils::~DOMURLUtils() = default;
-void DOMURLUtils::setHref(const String& value) {
- SetInput(value);
-}
-
void DOMURLUtils::setProtocol(const String& value) {
KURL kurl = Url();
if (kurl.IsNull())
@@ -50,7 +46,8 @@ void DOMURLUtils::setUsername(const String& value) {
if (kurl.IsNull())
return;
kurl.SetUser(value);
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setPassword(const String& value) {
@@ -58,7 +55,8 @@ void DOMURLUtils::setPassword(const String& value) {
if (kurl.IsNull())
return;
kurl.SetPass(value);
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setHost(const String& value) {
@@ -70,27 +68,21 @@ void DOMURLUtils::setHost(const String& value) {
return;
kurl.SetHostAndPort(value);
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setHostname(const String& value) {
- KURL kurl = Url();
- if (!kurl.CanSetHostOrPort())
+ if (value.IsEmpty())
return;
- // Before setting new value:
- // Remove all leading U+002F SOLIDUS ("/") characters.
- unsigned i = 0;
- unsigned host_length = value.length();
- while (value[i] == '/')
- i++;
-
- if (i == host_length)
+ KURL kurl = Url();
+ if (!kurl.CanSetHostOrPort())
return;
- kurl.SetHost(value.Substring(i));
-
- SetURL(kurl);
+ kurl.SetHost(value);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setPort(const String& value) {
@@ -101,7 +93,8 @@ void DOMURLUtils::setPort(const String& value) {
kurl.SetPort(value);
else
kurl.RemovePort();
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setPathname(const String& value) {
@@ -109,7 +102,8 @@ void DOMURLUtils::setPathname(const String& value) {
if (!kurl.CanSetPathname())
return;
kurl.SetPath(value);
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setSearch(const String& value) {
@@ -130,7 +124,8 @@ void DOMURLUtils::SetSearchInternal(const String& value) {
else
kurl.SetQuery(value);
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
void DOMURLUtils::setHash(const String& value) {
@@ -149,7 +144,8 @@ void DOMURLUtils::setHash(const String& value) {
kurl.SetFragmentIdentifier(value);
}
- SetURL(kurl);
+ if (kurl.IsValid())
+ SetURL(kurl);
}
} // namespace blink
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..ef0ccfa7039 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
@@ -38,11 +38,8 @@ class KURL;
class CORE_EXPORT DOMURLUtils : public DOMURLUtilsReadOnly {
public:
virtual void SetURL(const KURL&) = 0;
- virtual void SetInput(const String&) = 0;
~DOMURLUtils() override;
- void setHref(const String&);
-
void setProtocol(const String&);
void setUsername(const String&);
void setPassword(const String&);
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..03355d84b79 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
@@ -36,10 +36,11 @@ namespace blink {
class CORE_EXPORT DOMURLUtilsReadOnly {
public:
virtual KURL Url() const = 0;
- virtual String Input() const = 0;
virtual ~DOMURLUtilsReadOnly() = default;
+ // href() returns Url() if it is non-null, or Input() otherwise.
String href();
+ virtual String Input() const = 0;
static String origin(const KURL&);
String origin() { return origin(Url()); }
diff --git a/chromium/third_party/blink/renderer/core/url/url.idl b/chromium/third_party/blink/renderer/core/url/url.idl
index 71451416ee1..7dcabc73cd2 100644
--- a/chromium/third_party/blink/renderer/core/url/url.idl
+++ b/chromium/third_party/blink/renderer/core/url/url.idl
@@ -32,9 +32,9 @@
LegacyWindowAlias=webkitURL
] interface URL {
[RaisesException] constructor(USVString url, optional USVString base);
- stringifier attribute USVString href;
- readonly attribute USVString origin;
+ [RaisesException=Setter] stringifier attribute USVString href;
+ readonly attribute USVString origin;
attribute USVString protocol;
attribute USVString username;
attribute USVString password;
@@ -43,7 +43,7 @@
attribute USVString port;
attribute USVString pathname;
attribute USVString search;
- readonly attribute URLSearchParams searchParams;
+ [SameObject] readonly attribute URLSearchParams searchParams;
attribute USVString hash;
USVString toJSON();
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 bb45d24aef0..e3a1c16177d 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
@@ -44,7 +44,7 @@ class URLSearchParamsIterationSource final
private:
Member<URLSearchParams> params_;
- size_t current_;
+ wtf_size_t current_;
};
bool CompareParams(const std::pair<String, String>& a,
@@ -54,7 +54,6 @@ bool CompareParams(const std::pair<String, String>& a,
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
URLSearchParams* URLSearchParams::Create(const URLSearchParamsInit* init,
ExceptionState& exception_state) {
DCHECK(init);
@@ -75,28 +74,6 @@ URLSearchParams* URLSearchParams::Create(const URLSearchParamsInit* init,
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-URLSearchParams* URLSearchParams::Create(const URLSearchParamsInit& init,
- ExceptionState& exception_state) {
- if (init.IsUSVString()) {
- const String& query_string = init.GetAsUSVString();
- if (query_string.StartsWith('?'))
- return MakeGarbageCollected<URLSearchParams>(query_string.Substring(1));
- return MakeGarbageCollected<URLSearchParams>(query_string);
- }
- if (init.IsUSVStringUSVStringRecord()) {
- return URLSearchParams::Create(init.GetAsUSVStringUSVStringRecord(),
- exception_state);
- }
- if (init.IsUSVStringSequenceSequence()) {
- return URLSearchParams::Create(init.GetAsUSVStringSequenceSequence(),
- exception_state);
- }
-
- DCHECK(init.IsNull());
- return MakeGarbageCollected<URLSearchParams>(String());
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
URLSearchParams* URLSearchParams::Create(const Vector<Vector<String>>& init,
ExceptionState& exception_state) {
@@ -166,15 +143,15 @@ static String DecodeString(String input) {
void URLSearchParams::SetInputWithoutUpdate(const String& query_string) {
params_.clear();
- size_t start = 0;
- size_t query_string_length = query_string.length();
+ wtf_size_t start = 0;
+ wtf_size_t query_string_length = query_string.length();
while (start < query_string_length) {
- size_t name_start = start;
- size_t name_value_end = query_string.find('&', start);
+ wtf_size_t name_start = start;
+ wtf_size_t name_value_end = query_string.find('&', start);
if (name_value_end == kNotFound)
name_value_end = query_string_length;
if (name_value_end > start) {
- size_t end_of_name = query_string.find('=', start);
+ wtf_size_t end_of_name = query_string.find('=', start);
if (end_of_name == kNotFound || end_of_name > name_value_end)
end_of_name = name_value_end;
String name = DecodeString(
@@ -208,7 +185,7 @@ void URLSearchParams::append(const String& name, const String& value) {
}
void URLSearchParams::deleteAllWithName(const String& name) {
- for (size_t i = 0; i < params_.size();) {
+ for (wtf_size_t i = 0; i < params_.size();) {
if (params_[i].first == name)
params_.EraseAt(i);
else
@@ -244,7 +221,7 @@ bool URLSearchParams::has(const String& name) const {
void URLSearchParams::set(const String& name, const String& value) {
bool found_match = false;
- for (size_t i = 0; i < params_.size();) {
+ for (wtf_size_t i = 0; i < params_.size();) {
// If there are any name-value whose name is 'name', set
// the value of the first such name-value pair to 'value'
// and remove the others.
diff --git a/chromium/third_party/blink/renderer/core/url/url_search_params.h b/chromium/third_party/blink/renderer/core/url/url_search_params.h
index 7a12e95feec..402b8b9cd19 100644
--- a/chromium/third_party/blink/renderer/core/url/url_search_params.h
+++ b/chromium/third_party/blink/renderer/core/url/url_search_params.h
@@ -10,7 +10,6 @@
#include "base/dcheck_is_on.h"
#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/bindings/core/v8/iterable.h"
-#include "third_party/blink/renderer/bindings/core/v8/usv_string_sequence_sequence_or_usv_string_usv_string_record_or_usv_string.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/network/encoded_form_data.h"
@@ -23,25 +22,16 @@ class DOMURL;
class ExceptionState;
class V8UnionUSVStringOrUSVStringSequenceSequenceOrUSVStringUSVStringRecord;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
using URLSearchParamsInit =
V8UnionUSVStringOrUSVStringSequenceSequenceOrUSVStringUSVStringRecord;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-typedef USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString
- URLSearchParamsInit;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
class CORE_EXPORT URLSearchParams final : public ScriptWrappable,
public PairIterable<String, String> {
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static URLSearchParams* Create(const URLSearchParamsInit* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static URLSearchParams* Create(const URLSearchParamsInit&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static URLSearchParams* Create(const Vector<std::pair<String, String>>&,
ExceptionState&);
static URLSearchParams* Create(const Vector<Vector<String>>&,
diff --git a/chromium/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h b/chromium/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h
index ba740c8ccb1..7a4621a7255 100644
--- a/chromium/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h
+++ b/chromium/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h
@@ -8,7 +8,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "third_party/blink/public/test/frame_widget_test_helper.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/cross_thread_global_scope_creation_params_copier.cc b/chromium/third_party/blink/renderer/core/workers/cross_thread_global_scope_creation_params_copier.cc
index e97ac0282b2..2e4a7292572 100644
--- a/chromium/third_party/blink/renderer/core/workers/cross_thread_global_scope_creation_params_copier.cc
+++ b/chromium/third_party/blink/renderer/core/workers/cross_thread_global_scope_creation_params_copier.cc
@@ -55,8 +55,8 @@ network::mojom::blink::CSPSourceListPtr CSPSourceListIsolatedCopy(
std::move(sources), CrossThreadCopier<Vector<String>>::Copy(in->nonces),
std::move(hashes), in->allow_self, in->allow_star,
in->allow_response_redirects, in->allow_inline, in->allow_eval,
- in->allow_wasm_eval, in->allow_dynamic, in->allow_unsafe_hashes,
- in->report_sample);
+ in->allow_wasm_eval, in->allow_wasm_unsafe_eval, in->allow_dynamic,
+ in->allow_unsafe_hashes, in->report_sample);
}
HashMap<network::mojom::blink::CSPDirectiveName,
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 7f4cf6368c8..0b96946ad42 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -102,12 +102,6 @@ DedicatedWorker::DedicatedWorker(ExecutionContext* context,
DCHECK(script_request_url_.IsValid());
DCHECK(context_proxy_);
- // For nested workers, ensure the inside ResourceFetcher because it may not
- // have been used yet.
- // For documents, the ResourceFetcher is always already valid.
- if (auto* scope = DynamicTo<WorkerGlobalScope>(*context))
- scope->EnsureFetcher();
-
outside_fetch_client_settings_object_ =
MakeGarbageCollected<FetchClientSettingsObjectSnapshot>(
context->Fetcher()->GetProperties().GetFetchClientSettingsObject());
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 574a098a2f5..f8c48793269 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_MESSAGING_PROXY_H_
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
#include "third_party/blink/public/common/tokens/tokens.h"
@@ -34,6 +33,9 @@ class CORE_EXPORT DedicatedWorkerMessagingProxy
: public ThreadedMessagingProxyBase {
public:
DedicatedWorkerMessagingProxy(ExecutionContext*, DedicatedWorker*);
+ DedicatedWorkerMessagingProxy(const DedicatedWorkerMessagingProxy&) = delete;
+ DedicatedWorkerMessagingProxy& operator=(
+ const DedicatedWorkerMessagingProxy&) = delete;
~DedicatedWorkerMessagingProxy() override;
// These methods should only be used on the parent context thread.
@@ -105,8 +107,6 @@ class CORE_EXPORT DedicatedWorkerMessagingProxy
// Passed to DedicatedWorkerThread on worker thread creation.
mojo::PendingRemote<mojom::blink::DedicatedWorkerHost>
pending_dedicated_worker_host_;
-
- DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerMessagingProxy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
index f8e4eaf01c6..2bafa0832e3 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_OBJECT_PROXY_H_
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -59,6 +58,9 @@ class CORE_EXPORT DedicatedWorkerObjectProxy : public ThreadedObjectProxyBase {
DedicatedWorkerObjectProxy(DedicatedWorkerMessagingProxy*,
ParentExecutionContextTaskRunners*,
const DedicatedWorkerToken&);
+ DedicatedWorkerObjectProxy(const DedicatedWorkerObjectProxy&) = delete;
+ DedicatedWorkerObjectProxy& operator=(const DedicatedWorkerObjectProxy&) =
+ delete;
~DedicatedWorkerObjectProxy() override;
void PostMessageToWorkerObject(BlinkTransferableMessage);
@@ -89,8 +91,6 @@ class CORE_EXPORT DedicatedWorkerObjectProxy : public ThreadedObjectProxyBase {
// the tasks.
CrossThreadWeakPersistent<DedicatedWorkerMessagingProxy>
messaging_proxy_weak_ptr_;
-
- DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerObjectProxy);
};
} // namespace blink
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 018cacdad11..478ad29a8f1 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_GLOBAL_SCOPE_CREATION_PARAMS_H_
#include <memory>
-#include "base/macros.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
@@ -72,6 +71,9 @@ struct CORE_EXPORT GlobalScopeCreationParams final {
absl::nullopt,
bool parent_cross_origin_isolated_capability = false,
bool parent_direct_socket_capability = false);
+ GlobalScopeCreationParams(const GlobalScopeCreationParams&) = delete;
+ GlobalScopeCreationParams& operator=(const GlobalScopeCreationParams&) =
+ delete;
~GlobalScopeCreationParams() = default;
@@ -186,8 +188,6 @@ struct CORE_EXPORT GlobalScopeCreationParams final {
//
// TODO(mkwst): We need a specification for this capability.
const bool parent_direct_socket_capability;
-
- DISALLOW_COPY_AND_ASSIGN(GlobalScopeCreationParams);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.h b/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.h
index 44a5b2b859f..1c373ad7c67 100644
--- a/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.h
+++ b/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_INSTALLED_SCRIPTS_MANAGER_H_
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
@@ -33,6 +32,8 @@ class InstalledScriptsManager {
String source_text,
std::unique_ptr<Vector<uint8_t>> meta_data,
std::unique_ptr<CrossThreadHTTPHeaderMapData>);
+ ScriptData(const ScriptData&) = delete;
+ ScriptData& operator=(const ScriptData&) = delete;
ScriptData(ScriptData&& other) = default;
ScriptData& operator=(ScriptData&& other) = default;
@@ -56,8 +57,6 @@ class InstalledScriptsManager {
std::unique_ptr<Vector<uint8_t>> meta_data_;
HTTPHeaderMap headers_;
network::mojom::IPAddressSpace response_address_space_;
-
- DISALLOW_COPY_AND_ASSIGN(ScriptData);
};
// Used on the main or worker thread. Returns true if the script has been
diff --git a/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h b/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h
index 97fa92c16f6..7eff879b7e6 100644
--- a/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h
+++ b/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_PARENT_EXECUTION_CONTEXT_TASK_RUNNERS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_PARENT_EXECUTION_CONTEXT_TASK_RUNNERS_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_annotations.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -37,6 +36,11 @@ class CORE_EXPORT ParentExecutionContextTaskRunners final
// particular context.
explicit ParentExecutionContextTaskRunners(ExecutionContext*);
+ ParentExecutionContextTaskRunners(const ParentExecutionContextTaskRunners&) =
+ delete;
+ ParentExecutionContextTaskRunners& operator=(
+ const ParentExecutionContextTaskRunners&) = delete;
+
// Might return nullptr for unsupported task types. This can be called from
// any threads.
scoped_refptr<base::SingleThreadTaskRunner> Get(TaskType)
@@ -54,8 +58,6 @@ class CORE_EXPORT ParentExecutionContextTaskRunners final
Mutex mutex_;
TaskRunnerHashMap task_runners_ GUARDED_BY(mutex_);
-
- DISALLOW_COPY_AND_ASSIGN(ParentExecutionContextTaskRunners);
};
} // namespace blink
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 1270587e605..5709ae5e2de 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
@@ -75,11 +75,7 @@ SharedWorker::SharedWorker(ExecutionContext* context)
SharedWorker* SharedWorker::Create(
ExecutionContext* context,
const String& url,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionStringOrWorkerOptions* name_or_options,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrWorkerOptions& name_or_options,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
DCHECK(IsMainThread());
@@ -116,7 +112,6 @@ SharedWorker* SharedWorker::Create(
}
auto options = mojom::blink::WorkerOptions::New();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (name_or_options->GetContentType()) {
case V8UnionStringOrWorkerOptions::ContentType::kString:
options->name = name_or_options->GetAsString();
@@ -135,24 +130,6 @@ SharedWorker* SharedWorker::Create(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (name_or_options.IsString()) {
- options->name = name_or_options.GetAsString();
- } else if (name_or_options.IsWorkerOptions()) {
- WorkerOptions* worker_options = name_or_options.GetAsWorkerOptions();
- options->name = worker_options->name();
- absl::optional<mojom::blink::ScriptType> type_result =
- Script::ParseScriptType(worker_options->type());
- DCHECK(type_result);
- options->type = type_result.value();
- absl::optional<network::mojom::CredentialsMode> credentials_result =
- Request::ParseCredentialsMode(worker_options->credentials());
- DCHECK(credentials_result);
- options->credentials = credentials_result.value();
- } else {
- NOTREACHED();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(!options->name.IsNull());
if (options->type == mojom::blink::ScriptType::kClassic)
UseCounter::Count(window, WebFeature::kClassicSharedWorker);
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker.h b/chromium/third_party/blink/renderer/core/workers/shared_worker.h
index 319ca5e3192..2198b064417 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.h
@@ -33,7 +33,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_H_
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_worker_options.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/workers/abstract_worker.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -52,18 +51,11 @@ class CORE_EXPORT SharedWorker final
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static SharedWorker* Create(
ExecutionContext* context,
const String& url,
const V8UnionStringOrWorkerOptions* name_or_options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static SharedWorker* Create(ExecutionContext*,
- const String& url,
- const StringOrWorkerOptions&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
explicit SharedWorker(ExecutionContext*);
~SharedWorker() override;
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
index 433e7cae722..da73e6b924a 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_CLIENT_HOLDER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_CLIENT_HOLDER_H_
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
@@ -68,6 +67,8 @@ class CORE_EXPORT SharedWorkerClientHolder final
static SharedWorkerClientHolder* From(LocalDOMWindow&);
explicit SharedWorkerClientHolder(LocalDOMWindow&);
+ SharedWorkerClientHolder(const SharedWorkerClientHolder&) = delete;
+ SharedWorkerClientHolder& operator=(const SharedWorkerClientHolder&) = delete;
virtual ~SharedWorkerClientHolder() = default;
// Establishes a connection with SharedWorkerHost in the browser process.
@@ -85,8 +86,6 @@ class CORE_EXPORT SharedWorkerClientHolder final
HeapMojoUniqueReceiverSet<mojom::blink::SharedWorkerClient> client_receivers_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedWorkerClientHolder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
index c4ee20bec35..6811b34a498 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_REPORTING_PROXY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_REPORTING_PROXY_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -23,6 +22,9 @@ class SharedWorkerReportingProxy final
public:
SharedWorkerReportingProxy(WebSharedWorkerImpl*,
ParentExecutionContextTaskRunners*);
+ SharedWorkerReportingProxy(const SharedWorkerReportingProxy&) = delete;
+ SharedWorkerReportingProxy& operator=(const SharedWorkerReportingProxy&) =
+ delete;
~SharedWorkerReportingProxy() override;
// WorkerReportingProxy methods:
@@ -49,7 +51,6 @@ class SharedWorkerReportingProxy final
Member<ParentExecutionContextTaskRunners>
parent_execution_context_task_runners_;
- DISALLOW_COPY_AND_ASSIGN(SharedWorkerReportingProxy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h b/chromium/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
index 6d462da9b88..a53ed42a9f9 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_OBJECT_PROXY_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_OBJECT_PROXY_BASE_H_
-#include "base/macros.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/messaging/message_port.h"
@@ -24,6 +23,8 @@ class ThreadedMessagingProxyBase;
class CORE_EXPORT ThreadedObjectProxyBase : public WorkerReportingProxy {
USING_FAST_MALLOC(ThreadedObjectProxyBase);
public:
+ ThreadedObjectProxyBase(const ThreadedObjectProxyBase&) = delete;
+ ThreadedObjectProxyBase& operator=(const ThreadedObjectProxyBase&) = delete;
~ThreadedObjectProxyBase() override = default;
void ReportPendingActivity(bool has_pending_activity);
@@ -48,7 +49,6 @@ class CORE_EXPORT ThreadedObjectProxyBase : public WorkerReportingProxy {
// thread.
CrossThreadPersistent<ParentExecutionContextTaskRunners>
parent_execution_context_task_runners_;
- DISALLOW_COPY_AND_ASSIGN(ThreadedObjectProxyBase);
};
} // namespace blink
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 6d492a79052..00c0f0ae215 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_WORKLET_OBJECT_PROXY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_WORKLET_OBJECT_PROXY_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -34,6 +33,10 @@ class CORE_EXPORT ThreadedWorkletObjectProxy : public ThreadedObjectProxyBase {
static std::unique_ptr<ThreadedWorkletObjectProxy> Create(
ThreadedWorkletMessagingProxy*,
ParentExecutionContextTaskRunners*);
+
+ ThreadedWorkletObjectProxy(const ThreadedWorkletObjectProxy&) = delete;
+ ThreadedWorkletObjectProxy& operator=(const ThreadedWorkletObjectProxy&) =
+ delete;
~ThreadedWorkletObjectProxy() override;
void FetchAndInvokeScript(
@@ -59,7 +62,6 @@ class CORE_EXPORT ThreadedWorkletObjectProxy : public ThreadedObjectProxyBase {
// the tasks.
CrossThreadWeakPersistent<ThreadedWorkletMessagingProxy>
messaging_proxy_weak_ptr_;
- DISALLOW_COPY_AND_ASSIGN(ThreadedWorkletObjectProxy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h b/chromium/third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h
index 4f968d360cd..63f87461648 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h
@@ -42,6 +42,13 @@ struct CrossThreadCopier<absl::optional<blink::WorkerBackingThreadStartupData>>
: public CrossThreadCopierPassThrough<
absl::optional<blink::WorkerBackingThreadStartupData>> {};
+// This allows to pass WorkerBackingThreadStartupData across threads by
+// PostTask().
+template <>
+struct CrossThreadCopier<blink::WorkerBackingThreadStartupData>
+ : public CrossThreadCopierPassThrough<
+ blink::WorkerBackingThreadStartupData> {};
+
} // namespace WTF
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_BACKING_THREAD_STARTUP_DATA_H_
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 405467d3a4d..457a6d8393c 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
@@ -282,13 +282,13 @@ void WorkerClassicScriptLoader::DidFinishLoading(uint64_t identifier) {
NotifyFinished();
}
-void WorkerClassicScriptLoader::DidFail(const ResourceError& error) {
+void WorkerClassicScriptLoader::DidFail(uint64_t, const ResourceError& error) {
need_to_cancel_ = false;
canceled_ = error.IsCancellation();
NotifyError();
}
-void WorkerClassicScriptLoader::DidFailRedirectCheck() {
+void WorkerClassicScriptLoader::DidFailRedirectCheck(uint64_t) {
// When didFailRedirectCheck() is called, the ResourceLoader for the script
// is not canceled yet. So we don't reset |m_needToCancel| here.
NotifyError();
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.h b/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
index 7688023e180..4976d8e21b3 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
@@ -137,8 +137,8 @@ class CORE_EXPORT WorkerClassicScriptLoader final
void DidReceiveData(const char* data, unsigned data_length) override;
void DidReceiveCachedMetadata(mojo_base::BigBuffer) override;
void DidFinishLoading(uint64_t identifier) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t, const ResourceError&) override;
+ void DidFailRedirectCheck(uint64_t) override;
// WorkerMainScriptLoaderClient
// These will be called for dedicated workers (when PlzDedicatedWorker is
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_clients.h b/chromium/third_party/blink/renderer/core/workers/worker_clients.h
index d63263be48f..067dad342a7 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_clients.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_clients.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_CLIENTS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_CLIENTS_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -46,13 +45,12 @@ class CORE_EXPORT WorkerClients final : public GarbageCollected<WorkerClients>,
public Supplementable<WorkerClients> {
public:
WorkerClients() = default;
+ WorkerClients(const WorkerClients&) = delete;
+ WorkerClients& operator=(const WorkerClients&) = delete;
void Trace(Visitor* visitor) const override {
Supplementable<WorkerClients>::Trace(visitor);
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WorkerClients);
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<WorkerClients>;
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 e7e50c92e79..dc90346d413 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
@@ -68,6 +68,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_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/fonts/font_matching_metrics.h"
@@ -371,7 +372,6 @@ bool WorkerGlobalScope::FetchClassicImportedScript(
ExecutionContext* execution_context = GetExecutionContext();
WorkerClassicScriptLoader* classic_script_loader =
MakeGarbageCollected<WorkerClassicScriptLoader>();
- EnsureFetcher();
classic_script_loader->LoadSynchronously(
*execution_context, Fetcher(), script_url,
mojom::blink::RequestContextType::SCRIPT,
@@ -694,4 +694,17 @@ FontMatchingMetrics* WorkerGlobalScope::GetFontMatchingMetrics() {
return font_matching_metrics_.get();
}
+blink::mojom::CodeCacheHost* WorkerGlobalScope::GetCodeCacheHost() {
+ if (!code_cache_host_) {
+ // We may not have a valid browser interface in tests. For ex:
+ // FakeWorkerGlobalScope doesn't provide a valid interface. These tests
+ // don't rely on code caching so it's safe to return nullptr here.
+ if (!GetBrowserInterfaceBroker().is_bound())
+ return nullptr;
+ GetBrowserInterfaceBroker().GetInterface(
+ code_cache_host_.BindNewPipeAndPassReceiver());
+ }
+ return code_cache_host_.get();
+}
+
} // 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 0a35a746215..f01316ae1a9 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
@@ -33,6 +33,7 @@
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/loader/worker_main_script_load_parameters.h"
#include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -45,7 +46,7 @@
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.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"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -74,6 +75,10 @@ class CORE_EXPORT WorkerGlobalScope
~WorkerGlobalScope() override;
// Returns null if caching is not supported.
+ // TODO(crbug/964467): Currently workers do fetch cached code but they don't
+ // use it because we don't create a CachedMetadtaHandler. Only service workers
+ // override this method and provide a valid handler. We need to implement it
+ // for Dedicated / Shared workers too so we can benefit from code caches.
virtual SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler(
const KURL& script_url,
std::unique_ptr<Vector<uint8_t>> meta_data) {
@@ -86,6 +91,7 @@ class CORE_EXPORT WorkerGlobalScope
WorkerThread* GetThread() const final { return thread_; }
const base::UnguessableToken& GetDevToolsToken() const override;
bool IsInitialized() const final { return !url_.IsNull(); }
+ blink::mojom::CodeCacheHost* GetCodeCacheHost() override;
void ExceptionUnhandled(int exception_id);
@@ -325,6 +331,10 @@ class CORE_EXPORT WorkerGlobalScope
std::unique_ptr<WorkerMainScriptLoadParameters>
worker_main_script_load_params_for_modules_;
+ // This is the interface that handles generated code cache
+ // requests both to fetch code cache when loading resources.
+ mojo::Remote<blink::mojom::CodeCacheHost> code_cache_host_;
+
const ukm::SourceId ukm_source_id_;
};
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 8e9ef781d7f..bdf693dda08 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_navigator.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_navigator.cc
@@ -45,8 +45,7 @@ String WorkerNavigator::GetAcceptLanguages() {
WorkerOrWorkletGlobalScope* global_scope =
To<WorkerOrWorkletGlobalScope>(GetExecutionContext());
auto* web_worker_fetch_context =
- static_cast<WorkerFetchContext*>(
- (&global_scope->EnsureFetcher()->Context()))
+ static_cast<WorkerFetchContext*>((&global_scope->Fetcher()->Context()))
->GetWebWorkerFetchContext();
return web_worker_fetch_context->GetAcceptLanguages();
}
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 3816f71ffad..d076eb34c13 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
+#include <utility>
+
#include "base/threading/thread_checker.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/features.h"
@@ -11,7 +13,9 @@
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/content_security_notifier.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/public/platform/web_content_security_policy_struct.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.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"
@@ -38,6 +42,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
+#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -247,6 +252,10 @@ void WorkerOrWorkletGlobalScope::CountUse(WebFeature feature) {
ReportingProxy().CountFeature(feature);
}
+void WorkerOrWorkletGlobalScope::CountDeprecation(WebFeature feature) {
+ Deprecation::CountDeprecation(this, feature);
+}
+
ResourceLoadScheduler::ThrottleOptionOverride
WorkerOrWorkletGlobalScope::GetThrottleOptionOverride() const {
return ResourceLoadScheduler::ThrottleOptionOverride::kNone;
@@ -277,11 +286,12 @@ void WorkerOrWorkletGlobalScope::InitializeWebFetchContextIfNeeded() {
}
}
-ResourceFetcher* WorkerOrWorkletGlobalScope::EnsureFetcher() {
+ResourceFetcher* WorkerOrWorkletGlobalScope::Fetcher() {
DCHECK(IsContextThread());
// Worklets don't support subresource fetch.
DCHECK(IsWorkerGlobalScope());
+ // Check if the fetcher has already been initialized, otherwise initialize it.
if (inside_settings_resource_fetcher_)
return inside_settings_resource_fetcher_;
@@ -355,19 +365,11 @@ ResourceFetcher* WorkerOrWorkletGlobalScope::CreateFetcherInternal(
nullptr /* back_forward_cache_loader_helper */));
}
if (IsContextPaused())
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
resource_fetchers_.insert(fetcher);
return fetcher;
}
-ResourceFetcher* WorkerOrWorkletGlobalScope::Fetcher() const {
- DCHECK(IsContextThread());
- // Worklets don't support subresource fetch.
- DCHECK(IsWorkerGlobalScope());
- DCHECK(inside_settings_resource_fetcher_);
- return inside_settings_resource_fetcher_;
-}
-
ResourceFetcher* WorkerOrWorkletGlobalScope::CreateOutsideSettingsFetcher(
const FetchClientSettingsObject& outside_settings_object,
WorkerResourceTimingNotifier& outside_resource_timing_notifier) {
@@ -448,6 +450,16 @@ void WorkerOrWorkletGlobalScope::InitContentSecurityPolicyFromVector(
auto* csp = MakeGarbageCollected<ContentSecurityPolicy>();
csp->SetSupportsWasmEval(SchemeRegistry::SchemeSupportsWasmEvalCSP(
GetSecurityOrigin()->Protocol()));
+
+ // Check if the embedder wants to add any default policies, and add them.
+ WebVector<WebContentSecurityPolicyHeader> embedder_default_csp;
+ Platform::Current()->AppendContentSecurityPolicy(WebURL(Url()),
+ &embedder_default_csp);
+ for (const auto& header : embedder_default_csp) {
+ csp->AddPolicies(ParseContentSecurityPolicies(
+ header.header_value, header.type, header.source, Url()));
+ }
+
SetContentSecurityPolicy(csp);
}
GetContentSecurityPolicy()->AddPolicies(std::move(policies));
@@ -509,9 +521,9 @@ void WorkerOrWorkletGlobalScope::FetchModuleScript(
}
void WorkerOrWorkletGlobalScope::SetDefersLoadingForResourceFetchers(
- WebURLLoader::DeferType defers) {
+ LoaderFreezeMode mode) {
for (ResourceFetcher* resource_fetcher : resource_fetchers_)
- resource_fetcher->SetDefersLoading(defers);
+ resource_fetcher->SetDefersLoading(mode);
}
int WorkerOrWorkletGlobalScope::GetOutstandingThrottledLimit() const {
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 2490a1f5c54..a7e2f9da312 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
@@ -10,6 +10,7 @@
#include "base/unguessable_token.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-forward.h"
#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -89,6 +90,7 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
// UseCounter
void CountUse(WebFeature feature) final;
+ void CountDeprecation(WebFeature feature) final;
// May return nullptr if this global scope is not threaded (i.e.,
// WorkletGlobalScope for the main thread) or after Dispose() is called.
@@ -107,8 +109,7 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
// Returns the resource fetcher for subresources (a.k.a. inside settings
// resource fetcher). See core/workers/README.md for details.
- ResourceFetcher* Fetcher() const override;
- ResourceFetcher* EnsureFetcher();
+ ResourceFetcher* Fetcher() override;
// ResourceFetcher for off-the-main-thread worker top-level script fetching,
// corresponding to "outside" fetch client's settings object.
@@ -151,7 +152,7 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
void SetSandboxFlags(network::mojom::blink::WebSandboxFlags mask);
- void SetDefersLoadingForResourceFetchers(WebURLLoader::DeferType defers);
+ void SetDefersLoadingForResourceFetchers(LoaderFreezeMode);
virtual int GetOutstandingThrottledLimit() const;
@@ -159,6 +160,12 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
// PlzServiceWorker ship.
virtual bool IsInitialized() const = 0;
+ // TODO(crbug/964467): Currently all workers fetch cached code but only
+ // services workers use them. Dedicated / Shared workers don't use the cached
+ // code since we don't create a CachedMetadataHandler. We need to fix this by
+ // creating a cached metadta handler for all workers.
+ virtual blink::mojom::CodeCacheHost* GetCodeCacheHost() { return nullptr; }
+
Deprecation& GetDeprecation() { return deprecation_; }
protected:
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 f32e4fc35c6..c694aa7cab1 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -76,18 +76,6 @@ namespace {
constexpr base::TimeDelta kForcibleTerminationDelay =
base::TimeDelta::FromSeconds(2);
-void TerminateThreadsInSet(HashSet<WorkerThread*> threads) {
- for (WorkerThread* thread : threads)
- thread->TerminateForTesting();
-
- for (WorkerThread* thread : threads)
- thread->WaitForShutdownForTesting();
-
- // Destruct base::Thread and join the underlying system threads.
- for (WorkerThread* thread : threads)
- thread->ClearWorkerBackingThread();
-}
-
} // namespace
Mutex& WorkerThread::ThreadSetMutex() {
@@ -115,6 +103,9 @@ class WorkerThread::RefCountedWaitableEvent
return base::AdoptRef<RefCountedWaitableEvent>(new RefCountedWaitableEvent);
}
+ RefCountedWaitableEvent(const RefCountedWaitableEvent&) = delete;
+ RefCountedWaitableEvent& operator=(const RefCountedWaitableEvent&) = delete;
+
void Wait() { event_.Wait(); }
void Signal() { event_.Signal(); }
@@ -122,8 +113,6 @@ class WorkerThread::RefCountedWaitableEvent
RefCountedWaitableEvent() = default;
base::WaitableEvent event_;
-
- DISALLOW_COPY_AND_ASSIGN(RefCountedWaitableEvent);
};
// A class that is passed into V8 Interrupt and via a PostTask. Once both have
@@ -134,6 +123,8 @@ class WorkerThread::InterruptData {
public:
InterruptData(WorkerThread* worker_thread, mojom::FrameLifecycleState state)
: worker_thread_(worker_thread), state_(state) {}
+ InterruptData(const InterruptData&) = delete;
+ InterruptData& operator=(const InterruptData&) = delete;
bool ShouldRemoveFromList() { return seen_interrupt_ && seen_post_task_; }
void MarkPostTaskCalled() { seen_post_task_ = true; }
@@ -147,8 +138,6 @@ class WorkerThread::InterruptData {
mojom::FrameLifecycleState state_;
bool seen_interrupt_ = false;
bool seen_post_task_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(InterruptData);
};
WorkerThread::~WorkerThread() {
@@ -304,15 +293,6 @@ void WorkerThread::TerminateForTesting() {
EnsureScriptExecutionTerminates(ExitCode::kSyncForciblyTerminated);
}
-void WorkerThread::TerminateAllWorkersForTesting() {
- DCHECK(IsMainThread());
-
- // Keep this lock to prevent WorkerThread instances from being destroyed.
- MutexLocker lock(ThreadSetMutex());
- TerminateThreadsInSet(InitializingWorkerThreads());
- TerminateThreadsInSet(WorkerThreads());
-}
-
void WorkerThread::WillProcessTask(const base::PendingTask& pending_task,
bool was_blocked_or_low_priority) {
DCHECK(IsCurrentThread());
@@ -863,8 +843,7 @@ void WorkerThread::PauseOrFreezeOnWorkerThread(
state == mojom::FrameLifecycleState::kPaused);
pause_or_freeze_count_++;
GlobalScope()->SetLifecycleState(state);
- GlobalScope()->SetDefersLoadingForResourceFetchers(
- WebURLLoader::DeferType::kDeferred);
+ GlobalScope()->SetDefersLoadingForResourceFetchers(LoaderFreezeMode::kStrict);
// If already paused return early.
if (pause_or_freeze_count_ > 1)
@@ -883,8 +862,7 @@ void WorkerThread::PauseOrFreezeOnWorkerThread(
&nested_runner_, nested_runner.get());
nested_runner->Run();
}
- GlobalScope()->SetDefersLoadingForResourceFetchers(
- WebURLLoader::DeferType::kNotDeferred);
+ GlobalScope()->SetDefersLoadingForResourceFetchers(LoaderFreezeMode::kNone);
GlobalScope()->SetLifecycleState(mojom::FrameLifecycleState::kRunning);
}
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 8d00f8a5ea5..f4859641923 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.h
@@ -152,14 +152,6 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
// is quickly terminated. Called on the main thread.
virtual void TerminateForTesting();
- // Called on the main thread for the leak detector. Forcibly terminates the
- // script execution and waits by *blocking* the calling thread until the
- // workers are shut down. Please be careful when using this function, because
- // after the synchronous termination any V8 APIs may suddenly start to return
- // empty handles and it may cause crashes.
- // WARNING: This is not safe if a nested worker is running.
- static void TerminateAllWorkersForTesting();
-
// Thread::TaskObserver.
void WillProcessTask(const base::PendingTask&, bool) override;
void DidProcessTask(const base::PendingTask&) override;
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 0924cdd270b..f574dec932f 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.h b/chromium/third_party/blink/renderer/core/workers/worklet.h
index f648cde210d..52e26f056b7 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_H_
-#include "base/macros.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/execution_context/execution_context_lifecycle_observer.h"
@@ -29,6 +28,8 @@ class CORE_EXPORT Worklet : public ScriptWrappable,
USING_PRE_FINALIZER(Worklet, Dispose);
public:
+ Worklet(const Worklet&) = delete;
+ Worklet& operator=(const Worklet&) = delete;
~Worklet() override;
void Dispose();
@@ -94,8 +95,6 @@ class CORE_EXPORT Worklet : public ScriptWrappable,
// Keeps track of pending tasks from addModule() call.
HeapHashSet<Member<WorkletPendingTasks>> pending_tasks_set_;
-
- DISALLOW_COPY_AND_ASSIGN(Worklet);
};
} // 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 207ffffb9d7..26dcc2abd05 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_MODULE_RESPONSES_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_MODULE_RESPONSES_MAP_H_
+#include "third_party/abseil-cpp/absl/types/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/modulescript/module_script_fetcher.h"
diff --git a/chromium/third_party/blink/renderer/core/xml/document_xslt.h b/chromium/third_party/blink/renderer/core/xml/document_xslt.h
index 86de7a3fa95..ea34ef49c7b 100644
--- a/chromium/third_party/blink/renderer/core/xml/document_xslt.h
+++ b/chromium/third_party/blink/renderer/core/xml/document_xslt.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XML_DOCUMENT_XSLT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_DOCUMENT_XSLT_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -34,10 +33,9 @@ class DocumentXSLT final : public GarbageCollected<DocumentXSLT>,
static bool HasTransformSourceDocument(Document&);
explicit DocumentXSLT(Document&);
+ DocumentXSLT(const DocumentXSLT&) = delete;
+ DocumentXSLT& operator=(const DocumentXSLT&) = delete;
void Trace(Visitor*) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DocumentXSLT);
};
} // namespace blink
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 bdeea6241c2..a6d21c40db0 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
@@ -37,7 +37,7 @@
#include <memory>
#include "base/auto_reset.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/cdata_section.h"
#include "third_party/blink/renderer/core/dom/comment.h"
@@ -707,8 +707,8 @@ scoped_refptr<XMLParserContext> XMLParserContext::CreateMemoryParser(
InitializeLibXMLIfNecessary();
// appendFragmentSource() checks that the length doesn't overflow an int.
- xmlParserCtxtPtr parser =
- xmlCreateMemoryParserCtxt(chunk.c_str(), chunk.length());
+ xmlParserCtxtPtr parser = xmlCreateMemoryParserCtxt(
+ chunk.c_str(), base::checked_cast<int>(chunk.length()));
if (!parser)
return nullptr;
@@ -981,10 +981,15 @@ void XMLDocumentParser::StartElementNs(const AtomicString& local_name,
AtomicString adjusted_uri = uri;
if (parsing_fragment_ && adjusted_uri.IsNull()) {
- if (!prefix.IsNull())
- adjusted_uri = prefix_to_namespace_map_.at(prefix);
- else
+ if (!prefix.IsNull()) {
+ // TODO(https://crbug.com/1239288) Assign `default_namespace_uri_` to
+ // `adjusted_uri` when `prefix` is not found.
+ auto it = prefix_to_namespace_map_.find(prefix);
+ if (it != prefix_to_namespace_map_.end())
+ adjusted_uri = it->value;
+ } else {
adjusted_uri = default_namespace_uri_;
+ }
}
bool is_first_element = !saw_first_element_;
diff --git a/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser_scope.h b/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser_scope.h
index 8f5f07f0184..37cd36ecba4 100644
--- a/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser_scope.h
+++ b/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser_scope.h
@@ -27,7 +27,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_PARSER_XML_DOCUMENT_PARSER_SCOPE_H_
#include <libxml/xmlerror.h>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -43,6 +42,8 @@ class XMLDocumentParserScope {
xmlGenericErrorFunc,
xmlStructuredErrorFunc = nullptr,
void* error_context = nullptr);
+ XMLDocumentParserScope(const XMLDocumentParserScope&) = delete;
+ XMLDocumentParserScope& operator=(const XMLDocumentParserScope&) = delete;
~XMLDocumentParserScope();
static Document* current_document_;
@@ -53,7 +54,6 @@ class XMLDocumentParserScope {
xmlGenericErrorFunc old_generic_error_func_;
xmlStructuredErrorFunc old_structured_error_func_;
void* old_error_context_;
- DISALLOW_COPY_AND_ASSIGN(XMLDocumentParserScope);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_expression_node.h b/chromium/third_party/blink/renderer/core/xml/xpath_expression_node.h
index 6c24488c625..7de84ba9748 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_expression_node.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_expression_node.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_EXPRESSION_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_EXPRESSION_NODE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/xml/xpath_value.h"
@@ -64,6 +63,8 @@ class CORE_EXPORT ParseNode : public GarbageCollected<ParseNode> {
class CORE_EXPORT Expression : public ParseNode {
public:
Expression();
+ Expression(const Expression&) = delete;
+ Expression& operator=(const Expression&) = delete;
~Expression() override;
void Trace(Visitor*) const override;
@@ -107,7 +108,6 @@ class CORE_EXPORT Expression : public ParseNode {
bool is_context_node_sensitive_;
bool is_context_position_sensitive_;
bool is_context_size_sensitive_;
- DISALLOW_COPY_AND_ASSIGN(Expression);
};
} // namespace xpath
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_functions.cc b/chromium/third_party/blink/renderer/core/xml/xpath_functions.cc
index 671000a1ab4..e0a5df4fe64 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_functions.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_functions.cc
@@ -27,7 +27,7 @@
#include "third_party/blink/renderer/core/xml/xpath_functions.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
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 39fe46eee6b..e55143bcfdc 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_parser.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_parser.cc
@@ -36,6 +36,7 @@
#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"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
namespace xpath {
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_parser.h b/chromium/third_party/blink/renderer/core/xml/xpath_parser.h
index e0b28f3e684..75caf3d89a5 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_parser.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_parser.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_PARSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_PARSER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/xml/xpath_predicate.h"
#include "third_party/blink/renderer/core/xml/xpath_step.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -65,6 +64,8 @@ class Parser {
public:
Parser();
+ Parser(const Parser&) = delete;
+ Parser& operator=(const Parser&) = delete;
~Parser();
XPathNSResolver* Resolver() const { return resolver_; }
@@ -109,8 +110,6 @@ class Parser {
String data_;
int last_token_type_;
XPathNSResolver* resolver_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(Parser);
};
} // namespace xpath
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_predicate.h b/chromium/third_party/blink/renderer/core/xml/xpath_predicate.h
index f6b47e8bf4e..694b1f97e14 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_predicate.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_predicate.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_PREDICATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_PREDICATE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/xml/xpath_expression_node.h"
#include "third_party/blink/renderer/core/xml/xpath_value.h"
@@ -120,6 +119,8 @@ class Union final : public Expression {
class Predicate final : public GarbageCollected<Predicate> {
public:
explicit Predicate(Expression*);
+ Predicate(const Predicate&) = delete;
+ Predicate& operator=(const Predicate&) = delete;
void Trace(Visitor*) const;
bool Evaluate(EvaluationContext&) const;
@@ -133,7 +134,6 @@ class Predicate final : public GarbageCollected<Predicate> {
private:
Member<Expression> expr_;
- DISALLOW_COPY_AND_ASSIGN(Predicate);
};
} // namespace xpath
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_step.h b/chromium/third_party/blink/renderer/core/xml/xpath_step.h
index 5d03a5437bf..16adbf24251 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_step.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_step.h
@@ -27,7 +27,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_STEP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_STEP_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/core/xml/xpath_expression_node.h"
#include "third_party/blink/renderer/core/xml/xpath_node_set.h"
@@ -109,6 +108,8 @@ class Step final : public ParseNode {
Step(Axis, const NodeTest&);
Step(Axis, const NodeTest&, HeapVector<Member<Predicate>>&);
+ Step(const Step&) = delete;
+ Step& operator=(const Step&) = delete;
~Step() override;
void Trace(Visitor*) const override;
@@ -131,7 +132,6 @@ class Step final : public ParseNode {
Axis axis_;
Member<NodeTest> node_test_;
HeapVector<Member<Predicate>> predicates_;
- DISALLOW_COPY_AND_ASSIGN(Step);
};
bool OptimizeStepPair(Step*, Step*);
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_util.h b/chromium/third_party/blink/renderer/core/xml/xpath_util.h
index 2013cc4ec82..1f553af0eee 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_util.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_util.h
@@ -28,7 +28,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_UTIL_H_
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
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 c7ac76374c3..417376ac26c 100644
--- a/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
@@ -164,7 +164,10 @@ String XSLTProcessor::getParameter(const String& /*namespaceURI*/,
const String& local_name) const {
// FIXME: namespace support?
// should make a QualifiedName here but we'd have to expose the impl
- return parameters_.at(local_name);
+ auto it = parameters_.find(local_name);
+ if (it == parameters_.end())
+ return String();
+ return it->value;
}
void XSLTProcessor::removeParameter(const String& /*namespaceURI*/,
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 65b143d03cf..16d87904ad7 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
@@ -37,8 +37,6 @@
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.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_usv_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/document_or_xml_http_request_body_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_document_formdata_urlsearchparams_usvstring.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
@@ -95,6 +93,7 @@
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -135,7 +134,7 @@ void FindCharsetInMediaType(const String& media_type,
unsigned& charset_len) {
charset_len = 0;
- size_t pos = charset_pos;
+ unsigned pos = charset_pos;
unsigned length = media_type.length();
while (pos < length) {
@@ -325,6 +324,15 @@ v8::Local<v8::String> XMLHttpRequest::responseText(
v8::Local<v8::String> XMLHttpRequest::ResponseJSONSource() {
DCHECK_EQ(response_type_code_, kResponseTypeJSON);
+ const auto& head = response_body_head_;
+ if (state_ == kDone && !error_ && head.size() >= 2) {
+ if ((head[0] == 0xfe && head[1] == 0xff) ||
+ (head[0] == 0xff && head[1] == 0xfe)) {
+ Deprecation::CountDeprecation(GetExecutionContext(),
+ WebFeature::kXHRJSONEncodingDetection);
+ }
+ }
+
if (error_ || state_ != kDone)
return v8::Local<v8::String>();
return response_text_.V8Value(isolate_);
@@ -763,7 +771,6 @@ bool XMLHttpRequest::InitSend(ExceptionState& exception_state) {
return true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void XMLHttpRequest::send(const V8UnionDocumentOrXMLHttpRequestBodyInit* body,
ExceptionState& exception_state) {
probe::WillSendXMLHttpOrFetchNetworkRequest(GetExecutionContext(), Url());
@@ -790,56 +797,11 @@ void XMLHttpRequest::send(const V8UnionDocumentOrXMLHttpRequestBodyInit* body,
NOTREACHED();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void XMLHttpRequest::send(
- const DocumentOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString&
- body,
- ExceptionState& exception_state) {
- probe::WillSendXMLHttpOrFetchNetworkRequest(GetExecutionContext(), Url());
-
- if (body.IsNull()) {
- send(String(), exception_state);
- return;
- }
-
- if (body.IsDocument()) {
- send(body.GetAsDocument(), exception_state);
- return;
- }
-
- if (body.IsBlob()) {
- send(body.GetAsBlob(), exception_state);
- return;
- }
-
- if (body.IsArrayBuffer()) {
- send(body.GetAsArrayBuffer(), exception_state);
- return;
- }
-
- if (body.IsArrayBufferView()) {
- send(body.GetAsArrayBufferView().Get(), exception_state);
- return;
- }
-
- if (body.IsFormData()) {
- send(body.GetAsFormData(), exception_state);
- return;
- }
-
- if (body.IsURLSearchParams()) {
- send(body.GetAsURLSearchParams(), exception_state);
- return;
- }
-
- DCHECK(body.IsUSVString());
- send(body.GetAsUSVString(), exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool XMLHttpRequest::AreMethodAndURLValidForSend() {
return method_ != http_names::kGET && method_ != http_names::kHEAD &&
- url_.ProtocolIsInHTTPFamily();
+ SchemeRegistry::ShouldTreatURLSchemeAsSupportingFetchAPI(
+ url_.Protocol());
}
void XMLHttpRequest::send(Document* document, ExceptionState& exception_state) {
@@ -982,7 +944,8 @@ void XMLHttpRequest::SendBytesData(const void* data,
scoped_refptr<EncodedFormData> http_body;
if (AreMethodAndURLValidForSend()) {
- http_body = EncodedFormData::Create(data, length);
+ http_body =
+ EncodedFormData::Create(data, base::checked_cast<wtf_size_t>(length));
}
CreateRequest(std::move(http_body), exception_state);
@@ -1692,7 +1655,7 @@ String XMLHttpRequest::statusText() const {
return String();
}
-void XMLHttpRequest::DidFail(const ResourceError& error) {
+void XMLHttpRequest::DidFail(uint64_t, const ResourceError& error) {
DVLOG(1) << this << " didFail()";
ScopedEventDispatchProtect protect(&event_dispatch_recursion_level_);
@@ -1725,7 +1688,7 @@ void XMLHttpRequest::DidFail(const ResourceError& error) {
HandleNetworkError();
}
-void XMLHttpRequest::DidFailRedirectCheck() {
+void XMLHttpRequest::DidFailRedirectCheck(uint64_t) {
DVLOG(1) << this << " didFailRedirectCheck()";
ScopedEventDispatchProtect protect(&event_dispatch_recursion_level_);
@@ -1769,13 +1732,6 @@ void XMLHttpRequest::DidFinishLoadingInternal() {
if (decoder_) {
auto text = decoder_->Flush();
- if (response_type_code_ == kResponseTypeJSON) {
- // See https://crbug.com/1189627: We want to deprecate the BOM sniffing.
- if (decoder_->Encoding() != UTF8Encoding()) {
- GetExecutionContext()->CountUse(WebFeature::kXHRJSONEncodingDetection);
- }
- }
-
if (!text.IsEmpty() && !response_text_overflow_) {
response_text_.Concat(isolate_, text);
response_text_overflow_ = response_text_.IsEmpty();
@@ -1897,11 +1853,9 @@ void XMLHttpRequest::ParseDocumentChunk(const char* data, unsigned len) {
}
std::unique_ptr<TextResourceDecoder> XMLHttpRequest::CreateDecoder() const {
- const TextResourceDecoderOptions decoder_options_for_utf8_plain_text(
- TextResourceDecoderOptions::kPlainTextContent, UTF8Encoding());
if (response_type_code_ == kResponseTypeJSON) {
- return std::make_unique<TextResourceDecoder>(
- decoder_options_for_utf8_plain_text);
+ return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
+ TextResourceDecoderOptions::CreateUTF8Decode()));
}
WTF::TextEncoding final_response_charset = FinalResponseCharset();
@@ -1925,8 +1879,9 @@ std::unique_ptr<TextResourceDecoder> XMLHttpRequest::CreateDecoder() const {
return std::make_unique<TextResourceDecoder>(decoder_options_for_xml);
FALLTHROUGH;
case kResponseTypeText:
- return std::make_unique<TextResourceDecoder>(
- decoder_options_for_utf8_plain_text);
+ return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
+ TextResourceDecoderOptions::kPlainTextContent, UTF8Encoding()));
+
case kResponseTypeDocument:
if (ResponseIsHTML()) {
return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
@@ -1961,6 +1916,13 @@ void XMLHttpRequest::DidReceiveData(const char* data, unsigned len) {
if (!len)
return;
+ // Store the first few bytes of the response body so that we can check the BOM
+ // later.
+ for (wtf_size_t i = 0;
+ i < len && response_body_head_.size() < kResponseBodyHeadSize; ++i) {
+ response_body_head_.push_back(static_cast<uint8_t>(data[i]));
+ }
+
if (response_type_code_ == kResponseTypeDocument && ResponseIsHTML()) {
ParseDocumentChunk(data, len);
} else if (response_type_code_ == kResponseTypeDefault ||
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 2fc148e35e9..7e6ec5ad584 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
@@ -55,8 +55,6 @@
namespace blink {
-class
- DocumentOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString;
class Blob;
class BlobDataHandle;
class DOMArrayBuffer;
@@ -135,14 +133,8 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
const KURL&,
bool async,
ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void send(const V8UnionDocumentOrXMLHttpRequestBodyInit* body,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void send(
- const DocumentOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void abort();
void Dispose();
void setRequestHeader(const AtomicString& name,
@@ -196,8 +188,8 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
void DidDownloadData(uint64_t data_length) override;
void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) override;
void DidFinishLoading(uint64_t identifier) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t, const ResourceError&) override;
+ void DidFailRedirectCheck(uint64_t) override;
// BlobLoader notifications.
void DidFinishLoadingInternal();
@@ -323,9 +315,13 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
std::unique_ptr<TextResourceDecoder> decoder_;
+ // TODO(crbug.com/1226775): Remove these on M96.
+ static constexpr size_t kResponseBodyHeadSize = 2;
+ Vector<uint8_t, kResponseBodyHeadSize> response_body_head_;
+
// Avoid using a flat WTF::String here and rather use a traced v8::String
// which internally builds a string rope.
- GC_PLUGIN_IGNORE("crbug.com/841830") TraceWrapperV8String response_text_;
+ TraceWrapperV8String response_text_;
Member<Document> response_document_;
Member<DocumentParser> response_document_parser_;
diff --git a/chromium/third_party/blink/renderer/extensions/DIR_METADATA b/chromium/third_party/blink/renderer/extensions/DIR_METADATA
new file mode 100644
index 00000000000..90b2e9cf1bc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "Blink>Internals>Modularization"
+}
+
+team_email: "platform-architecture-dev@chromium.org"
diff --git a/chromium/third_party/blink/renderer/extensions/OWNERS b/chromium/third_party/blink/renderer/extensions/OWNERS
new file mode 100644
index 00000000000..95fdefa552d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/OWNERS
@@ -0,0 +1,2 @@
+chrishtr@chromium.org
+haraken@chromium.org
diff --git a/chromium/third_party/blink/renderer/extensions/README.md b/chromium/third_party/blink/renderer/extensions/README.md
new file mode 100644
index 00000000000..90bff3eb41a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/README.md
@@ -0,0 +1,11 @@
+# The `extensions/` directory
+
+The `extensions/` directory contains embedder-specific, not-web-exposed APIs (e.g., not-web-exposed APIs for Chromium OS etc).
+The directory is useful to implement embedder-specific, not-web-exposed APIs
+using Blink technologies for web-exposed APIs like WebIDL, V8 bindings and Oilpan.
+
+Remember that you should not implement any web-exposed APIs in `extensions/`. Web-exposed APIs should go through the standardization process and be implemented in `core/` or `modules/`. Also, per [the Chromium contributor guideline](https://chromium.googlesource.com/chromium/src/+/main/docs/contributing.md#code-guidelines), code that is not used by Chromium should not be added to `extensions/`.
+
+In terms of dependencies, `extensions/` can depend on `modules/`, `core/` and `platform/`, but not vice versa.
+
+The `extensions/` directory contains sub-directories for individual embedders (e.g., `extensions/chromeos/`). Each sub-directory is linked into the Blink link unit only when the embedder is built.
diff --git a/chromium/third_party/blink/renderer/extensions/chromeos/BUILD.gn b/chromium/third_party/blink/renderer/extensions/chromeos/BUILD.gn
new file mode 100644
index 00000000000..97509efc78c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/chromeos/BUILD.gn
@@ -0,0 +1,49 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/bindings/bindings.gni")
+import("//third_party/blink/renderer/build/scripts/scripts.gni")
+import("//third_party/blink/renderer/config.gni")
+import("//third_party/blink/renderer/extensions/extensions.gni")
+
+assert(use_blink_extensions_chromeos)
+
+visibility = [ "//third_party/blink/renderer/extensions/*" ]
+
+config("extensions_chromeos_implementation") {
+ visibility += [ "//third_party/blink/renderer/bindings/extensions/*" ]
+ defines = [ "BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION=1" ]
+}
+
+component("chromeos") {
+ output_name = "blink_extensions_chromeos"
+
+ visibility = [] # Allow re-assignment of list.
+ visibility = [ "//third_party/blink/*" ]
+
+ sources = [
+ "chromeos.cc",
+ "chromeos.h",
+ "extensions_chromeos_export.h",
+ ]
+
+ # This sets the default list of configs when the blink_modules_sources target
+ # is defined. The default_compiler_configs comes from BUILDCONFIG.gn and
+ # is the list normally applied to static libraries and source sets.
+ configs += [
+ ":extensions_chromeos_implementation",
+
+ "//third_party/blink/renderer:config",
+ "//third_party/blink/renderer:non_test_config",
+ "//third_party/blink/renderer:inside_blink",
+ ]
+
+ deps = [
+ "//third_party/blink/renderer/core",
+ "//third_party/blink/renderer/modules",
+ ]
+
+ public_deps =
+ [ "//third_party/blink/renderer/bindings/extensions/v8:v8_chromeos" ]
+}
diff --git a/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.cc b/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.cc
new file mode 100644
index 00000000000..124bf54c022
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.cc
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/extensions/chromeos/chromeos.h"
+
+namespace blink {
+
+bool ChromeOS::myEmbedderFunction(bool testArg) {
+ return !testArg;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.h b/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.h
new file mode 100644
index 00000000000..048c94b7999
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.h
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_CHROMEOS_H_
+#define THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_CHROMEOS_H_
+
+#include "third_party/blink/renderer/extensions/chromeos/extensions_chromeos_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class EXTENSIONS_CHROMEOS_EXPORT ChromeOS : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static bool myEmbedderFunction(bool testArg);
+
+ private:
+ ChromeOS() = default;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_CHROMEOS_H_
diff --git a/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.idl b/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.idl
new file mode 100644
index 00000000000..ff6855d62b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/chromeos/chromeos.idl
@@ -0,0 +1,7 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace ChromeOS {
+ boolean myEmbedderFunction(boolean testArg);
+};
diff --git a/chromium/third_party/blink/renderer/extensions/chromeos/extensions_chromeos_export.h b/chromium/third_party/blink/renderer/extensions/chromeos/extensions_chromeos_export.h
new file mode 100644
index 00000000000..e3e02c42030
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/chromeos/extensions_chromeos_export.h
@@ -0,0 +1,68 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This header defines macros to export component's symbols.
+// See "platform/PlatformExport.h" for details.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_EXTENSIONS_CHROMEOS_EXPORT_H_
+#define THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_EXTENSIONS_CHROMEOS_EXPORT_H_
+
+#include "build/build_config.h"
+
+//
+// BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION
+//
+#if !defined(BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION)
+#define BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION 0
+#endif
+
+//
+// EXTENSIONS_CHROMEOS_EXPORT
+//
+#if !defined(COMPONENT_BUILD)
+#define EXTENSIONS_CHROMEOS_EXPORT // No need of export
+#else
+
+#if defined(COMPILER_MSVC)
+#if BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION
+#define EXTENSIONS_CHROMEOS_EXPORT __declspec(dllexport)
+#else
+#define EXTENSIONS_CHROMEOS_EXPORT __declspec(dllimport)
+#endif
+#endif // defined(COMPILER_MSVC)
+
+#if defined(COMPILER_GCC)
+#if BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION
+#define EXTENSIONS_CHROMEOS_EXPORT __attribute__((visibility("default")))
+#else
+#define EXTENSIONS_CHROMEOS_EXPORT
+#endif
+#endif // defined(COMPILER_GCC)
+
+#endif // !defined(COMPONENT_BUILD)
+
+//
+// EXTENSIONS_CHROMEOS_EXTERN_TEMPLATE_EXPORT
+// EXTENSIONS_CHROMEOS_TEMPLATE_EXPORT
+//
+#if BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION
+
+#if defined(COMPILER_MSVC)
+#define EXTENSIONS_CHROMEOS_EXTERN_TEMPLATE_EXPORT
+#define EXTENSIONS_CHROMEOS_TEMPLATE_EXPORT EXTENSIONS_CHROMEOS_EXPORT
+#endif
+
+#if defined(COMPILER_GCC)
+#define EXTENSIONS_CHROMEOS_EXTERN_TEMPLATE_EXPORT EXTENSIONS_CHROMEOS_EXPORT
+#define EXTENSIONS_CHROMEOS_TEMPLATE_EXPORT
+#endif
+
+#else // BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION
+
+#define EXTENSIONS_CHROMEOS_EXTERN_TEMPLATE_EXPORT EXTENSIONS_CHROMEOS_EXPORT
+#define EXTENSIONS_CHROMEOS_TEMPLATE_EXPORT
+
+#endif // BLINK_EXTENSIONS_CHROMEOS_IMPLEMENTATION
+
+#endif // THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_EXTENSIONS_CHROMEOS_EXPORT_H_
diff --git a/chromium/third_party/blink/renderer/extensions/extensions.gni b/chromium/third_party/blink/renderer/extensions/extensions.gni
new file mode 100644
index 00000000000..69b0dcafb79
--- /dev/null
+++ b/chromium/third_party/blink/renderer/extensions/extensions.gni
@@ -0,0 +1,57 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/config.gni")
+blink_extensions_output_dir =
+ "$root_gen_dir/third_party/blink/renderer/extensions"
+
+# Defines a part of blink extensions_chromeos. This is either a source set or a
+# static library with defaults for commonly-used values.
+#
+# deps
+# Default deps are automatically appended to any specified on the caller.
+#
+# visibility
+# Normal meaning if defined. If undefined, defaults to everything in
+# extensions.
+template("blink_extensions_chromeos_sources") {
+ assert(use_blink_extensions_chromeos)
+
+ if (is_component_build) {
+ target_type = "source_set"
+ } else {
+ target_type = "static_library"
+ }
+
+ target(target_type, target_name) {
+ # The visibility will get overridden by forward_variables_from below if the
+ # invoker defined it.
+ visibility = [ "//third_party/blink/renderer/extensions/*" ]
+
+ deps = [
+ "//third_party/blink/renderer/core",
+ "//third_party/blink/renderer/modules",
+ ]
+ if (defined(invoker.deps)) {
+ deps += invoker.deps
+ }
+
+ # Take everything else not handled above from the invoker.
+ forward_variables_from(invoker, "*", [ "deps" ])
+ }
+}
+set_defaults("blink_extensions_chromeos_sources") {
+ # This sets the default list of configs when the blink_extensions_chromeos_sources
+ # target is defined. The default_compiler_configs comes from BUILDCONFIG.gn
+ # and is the list normally applied to static libraries and source sets.
+ configs = default_compiler_configs
+ configs -= [ "//build/config/compiler:default_symbols" ]
+ configs += blink_symbols_config
+ configs += [
+ "//third_party/blink/renderer:config",
+ "//third_party/blink/renderer:non_test_config",
+ "//third_party/blink/renderer:inside_blink",
+ ]
+ configs += [ "//third_party/blink/renderer/extensions/chromeos:extensions_chromeos_implementation" ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/BUILD.gn b/chromium/third_party/blink/renderer/modules/BUILD.gn
index 1b9f3c7206e..9ba7c0ba632 100644
--- a/chromium/third_party/blink/renderer/modules/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/BUILD.gn
@@ -5,11 +5,9 @@
import("//build/config/chromecast_build.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/blink/renderer/bindings/bindings.gni")
-import("//third_party/blink/renderer/bindings/modules/v8/generated.gni")
-import("//third_party/blink/renderer/bindings/modules/v8/v8.gni")
+import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
import("//third_party/blink/renderer/build/scripts/scripts.gni")
import("//third_party/blink/renderer/modules/modules.gni")
-import("//third_party/blink/renderer/modules/modules_idl_files.gni")
import("//third_party/webrtc/webrtc.gni")
if (is_android) {
@@ -22,18 +20,6 @@ config("modules_implementation") {
defines = [ "BLINK_MODULES_IMPLEMENTATION=1" ]
}
-make_names("indexed_db_names") {
- in_files = [ "indexeddb/indexed_db_names.json5" ]
- output_dir = blink_modules_output_dir
- deps = [] # Don't use default deps (otherwise it will be circular).
-}
-
-make_names("media_capabilities_names") {
- in_files = [ "media_capabilities/media_capabilities_names.json5" ]
- output_dir = blink_modules_output_dir
- deps = [] # Don't use default deps (otherwise it will be circular).
-}
-
component("modules") {
output_name = "blink_modules"
@@ -49,24 +35,11 @@ component("modules") {
"modules_initializer.h",
]
- # Compile sources generated by make_names script.
- sources += get_target_outputs(":indexed_db_names")
- sources += get_target_outputs(":media_capabilities_names")
-
- sources += bindings_modules_v8_files
-
- if (!use_blink_v8_binding_new_idl_interface) {
- sources += rebase_path(
- [ bindings_generated_v8_context_snapshot_external_references_file ],
- ".",
- "//")
- }
+ sources += blink_modules_sources_bindings
configs += [
":modules_implementation",
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- "//build/config/compiler:no_size_t_to_int_warning",
"//third_party/blink/renderer:config",
"//third_party/blink/renderer:non_test_config",
"//third_party/blink/renderer:inside_blink",
@@ -75,6 +48,7 @@ component("modules") {
]
sub_modules = [
+ ":modules_generated",
"//third_party/blink/renderer/bindings/modules/v8",
"//third_party/blink/renderer/modules/accessibility",
"//third_party/blink/renderer/modules/ad_auction",
@@ -104,6 +78,7 @@ component("modules") {
"//third_party/blink/renderer/modules/compression",
"//third_party/blink/renderer/modules/delegated_ink",
"//third_party/blink/renderer/modules/device_orientation",
+ "//third_party/blink/renderer/modules/device_posture",
"//third_party/blink/renderer/modules/document_metadata",
"//third_party/blink/renderer/modules/donottrack",
"//third_party/blink/renderer/modules/encoding",
@@ -160,9 +135,11 @@ component("modules") {
"//third_party/blink/renderer/modules/sensor",
"//third_party/blink/renderer/modules/service_worker",
"//third_party/blink/renderer/modules/shapedetection",
+ "//third_party/blink/renderer/modules/shared_storage",
"//third_party/blink/renderer/modules/speech",
"//third_party/blink/renderer/modules/srcobject",
"//third_party/blink/renderer/modules/storage",
+ "//third_party/blink/renderer/modules/subapps",
"//third_party/blink/renderer/modules/url_pattern",
"//third_party/blink/renderer/modules/vibration",
"//third_party/blink/renderer/modules/video_rvfc",
@@ -194,14 +171,9 @@ component("modules") {
}
deps = [
- ":indexed_db_names",
":make_modules_generated",
- ":media_capabilities_names",
"//jingle:webrtc_glue",
"//net:net",
- "//third_party/blink/renderer/bindings/modules:generated",
- "//third_party/blink/renderer/bindings/modules/v8:bindings_modules_impl",
- "//third_party/blink/renderer/bindings/modules/v8:bindings_modules_origin_trial_features",
"//third_party/blink/renderer/bindings/modules/v8:generated",
"//third_party/blink/renderer/core",
"//third_party/icu",
@@ -279,13 +251,155 @@ source_set("modules_testing") {
group("make_modules_generated") {
public_deps = [
- ":indexed_db_names",
- ":media_capabilities_names",
- "//third_party/blink/renderer/bindings/modules:bindings_modules_generated",
+ ":make_modules_generated_event_factory",
+ ":make_modules_generated_event_names",
+ ":make_modules_generated_event_target_names",
+ ":make_modules_generated_indexed_db_names",
+ ":make_modules_generated_media_capabilities_names",
+ "//components/payments/mojom:mojom_blink_headers",
+ "//components/schema_org/common:mojom_blink_headers",
+ "//components/services/filesystem/public/mojom:mojom_blink_headers",
+ "//device/bluetooth/public/mojom:mojom_blink_headers",
+ "//device/gamepad/public/mojom:mojom_blink_headers",
+ "//device/vr/public/mojom:vr_service_blink_headers",
+ "//media/capture/mojom:image_capture_blink_headers",
+ "//media/midi:mojo_blink_headers",
+ "//services/device/public/mojom:generic_sensor_headers",
+ "//services/device/public/mojom:mojom_blink_headers",
+ "//services/device/public/mojom:usb_blink_headers",
+ "//services/shape_detection/public/mojom:mojom_blink_headers",
+ "//third_party/blink/public/mojom:mojom_modules_blink_headers",
"//third_party/blink/renderer/bindings/modules/v8:generated",
"//third_party/blink/renderer/core:core_event_interfaces",
"//third_party/blink/renderer/modules/mediarecorder:buildflags",
+ "//ui/accessibility:ax_enums_mojo_blink_headers",
+ "//ui/display/mojom:mojom_blink_headers",
]
+ if (is_fuchsia) {
+ public_deps += [ "//media/fuchsia/mojom:mojom_blink_headers" ]
+ }
+}
+
+# generate_event_interfaces ----------------------------------------------------
+
+generate_event_interfaces("modules_event_interfaces") {
+ sources = [
+ "app_banner/before_install_prompt_event.idl",
+ "background_fetch/background_fetch_event.idl",
+ "background_fetch/background_fetch_update_ui_event.idl",
+ "background_sync/periodic_sync_event.idl",
+ "background_sync/sync_event.idl",
+ "content_index/content_index_event.idl",
+ "cookie_store/cookie_change_event.idl",
+ "cookie_store/extendable_cookie_change_event.idl",
+ "device_orientation/device_motion_event.idl",
+ "device_orientation/device_orientation_event.idl",
+ "encryptedmedia/media_encrypted_event.idl",
+ "encryptedmedia/media_key_message_event.idl",
+ "gamepad/gamepad_axis_event.idl",
+ "gamepad/gamepad_button_event.idl",
+ "gamepad/gamepad_event.idl",
+ "hid/hid_connection_event.idl",
+ "hid/hid_input_report_event.idl",
+ "indexeddb/idb_version_change_event.idl",
+ "mediarecorder/blob_event.idl",
+ "mediastream/capture_handle_change_event.idl",
+ "mediastream/capture_handle_change_event_init.idl",
+ "mediastream/media_stream_event.idl",
+ "mediastream/media_stream_track_event.idl",
+ "nfc/ndef_reading_event.idl",
+ "notifications/notification_event.idl",
+ "payments/abort_payment_event.idl",
+ "payments/can_make_payment_event.idl",
+ "payments/merchant_validation_event.idl",
+ "payments/payment_method_change_event.idl",
+ "payments/payment_request_details_update.idl",
+ "payments/payment_request_event.idl",
+ "payments/payment_request_update_event.idl",
+ "peerconnection/rtc_data_channel_event.idl",
+ "peerconnection/rtc_dtmf_tone_change_event.idl",
+ "peerconnection/rtc_peer_connection_ice_error_event.idl",
+ "peerconnection/rtc_peer_connection_ice_event.idl",
+ "picture_in_picture/picture_in_picture_event.idl",
+ "presentation/presentation_connection_available_event.idl",
+ "presentation/presentation_connection_close_event.idl",
+ "push_messaging/push_event.idl",
+ "scheduler/task_priority_change_event.idl",
+ "sensor/sensor_error_event.idl",
+ "service_worker/extendable_event.idl",
+ "service_worker/extendable_message_event.idl",
+ "service_worker/fetch_event.idl",
+ "service_worker/install_event.idl",
+ "speech/speech_recognition_error_event.idl",
+ "speech/speech_recognition_event.idl",
+ "speech/speech_synthesis_error_event.idl",
+ "speech/speech_synthesis_event.idl",
+ "storage/storage_event.idl",
+ "webaudio/audio_processing_event.idl",
+ "webaudio/offline_audio_completion_event.idl",
+ "webgl/webgl_context_event.idl",
+ "webmidi/midi_connection_event.idl",
+ "webmidi/midi_message_event.idl",
+ "websockets/close_event.idl",
+ "xr/xr_input_source_event.idl",
+ "xr/xr_input_sources_change_event.idl",
+ "xr/xr_reference_space_event.idl",
+ "xr/xr_session_event.idl",
+ ]
+
+ output_file = "modules/event_interface_modules_names.json5"
+ suffix = "Modules"
+}
+
+# make_event_factory -----------------------------------------------------------
+
+make_event_factory("make_modules_generated_event_factory") {
+ in_files = [ "$blink_modules_output_dir/event_interface_modules_names.json5" ]
+ outputs = [ "$blink_modules_output_dir/event_modules_factory.cc" ]
+ deps = make_core_generated_deps + [ ":modules_event_interfaces" ]
+}
+
+# make_names -------------------------------------------------------------------
+
+make_names("make_modules_generated_event_names") {
+ in_files = [ "$blink_modules_output_dir/event_interface_modules_names.json5" ]
+ output_dir = blink_modules_output_dir
+ deps = make_core_generated_deps + [ ":modules_event_interfaces" ]
+}
+
+make_names("make_modules_generated_event_target_names") {
+ in_files = [ "event_target_modules_names.json5" ]
+ output_dir = blink_modules_output_dir
+}
+
+make_names("make_modules_generated_indexed_db_names") {
+ in_files = [ "indexeddb/indexed_db_names.json5" ]
+ output_dir = blink_modules_output_dir
+ deps = [] # Don't use default deps (otherwise it will be circular).
+}
+
+make_names("make_modules_generated_media_capabilities_names") {
+ in_files = [ "media_capabilities/media_capabilities_names.json5" ]
+ output_dir = blink_modules_output_dir
+ deps = [] # Don't use default deps (otherwise it will be circular).
+}
+
+blink_modules_sources("modules_generated") {
+ # Targets from above that generate outputs that need to be compiled.
+ # All sources declared as outputs from these targets will be compiled
+ # into one target.
+ targets_generating_sources = [
+ ":make_modules_generated_event_factory",
+ ":make_modules_generated_event_names",
+ ":make_modules_generated_event_target_names",
+ ":make_modules_generated_indexed_db_names",
+ ":make_modules_generated_media_capabilities_names",
+ ]
+
+ sources = []
+ foreach(current, targets_generating_sources) {
+ sources += get_target_outputs(current)
+ }
}
source_set("unit_tests") {
@@ -319,8 +433,8 @@ source_set("unit_tests") {
"content_index/content_description_type_converter_test.cc",
"credentialmanager/credentials_container_test.cc",
"credentialmanager/password_credential_test.cc",
- "csspaint/background_color_paint_worklet_test.cc",
"csspaint/document_paint_definition_test.cc",
+ "csspaint/nativepaint/background_color_paint_definition_test.cc",
"csspaint/paint_rendering_context_2d_test.cc",
"csspaint/paint_worklet_global_scope_test.cc",
"csspaint/paint_worklet_proxy_client_test.cc",
@@ -337,7 +451,6 @@ source_set("unit_tests") {
"manifest/image_resource_type_converters_test.cc",
"manifest/manifest_manager_unittest.cc",
"manifest/manifest_parser_unittest.cc",
- "manifest/manifest_type_converters_unittest.cc",
"media/audio/audio_renderer_mixer_manager_test.cc",
"media/audio/audio_renderer_sink_cache_test.cc",
"media/audio/mojo_audio_input_ipc_test.cc",
@@ -473,6 +586,7 @@ source_set("unit_tests") {
"webaudio/dynamics_compressor_node_test.cc",
"webaudio/script_processor_node_test.cc",
"webaudio/stereo_panner_node_test.cc",
+ "webdatabase/dom_window_web_database_test.cc",
"webdatabase/quota_tracker_test.cc",
"webshare/navigator_share_test.cc",
"websockets/dom_websocket_test.cc",
@@ -529,6 +643,7 @@ source_set("unit_tests") {
"//third_party/blink/renderer/core",
"//third_party/blink/renderer/core:testing",
"//third_party/blink/renderer/core:unit_test_support",
+ "//third_party/blink/renderer/modules/ad_auction:unit_tests",
"//third_party/blink/renderer/modules/breakout_box:unit_tests",
"//third_party/blink/renderer/modules/file_system_access:unit_tests",
"//third_party/blink/renderer/modules/gamepad:unit_tests",
diff --git a/chromium/third_party/blink/renderer/modules/DEPS b/chromium/third_party/blink/renderer/modules/DEPS
index 1779202d873..dc9a6516157 100644
--- a/chromium/third_party/blink/renderer/modules/DEPS
+++ b/chromium/third_party/blink/renderer/modules/DEPS
@@ -20,6 +20,10 @@ include_rules = [
"!third_party/blink/renderer/core/frame/web_local_frame_impl.h",
"!third_party/blink/renderer/core/frame/web_remote_frame_impl.h",
"+third_party/blink/renderer/modules",
+ "+ui/accessibility/ax_mode.h",
+ "+ui/display/screen_info.h",
+ "+ui/display/screen_infos.h",
+ "+ui/display/mojom",
"+ui/gfx/geometry",
"-web",
]
@@ -47,4 +51,8 @@ specific_include_rules = {
"web_ax_object.cc": [
"+ui/accessibility/ax_action_data.h",
],
+
+ "tcp_writable_stream_wrapper.h": [
+ "+base/allocator/partition_allocator/partition_root.h",
+ ]
}
diff --git a/chromium/third_party/blink/renderer/modules/OWNERS b/chromium/third_party/blink/renderer/modules/OWNERS
index 5c0579dd8c2..4e16111583b 100644
--- a/chromium/third_party/blink/renderer/modules/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/OWNERS
@@ -6,5 +6,4 @@ mkwst@chromium.org
# Reviewers for inspector-related code:
dgozman@chromium.org
-pfeldman@chromium.org
caseq@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/OWNERS b/chromium/third_party/blink/renderer/modules/accessibility/OWNERS
index 31035ef506e..72e48cc8d01 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/accessibility/OWNERS
@@ -1,4 +1,6 @@
aboxhall@chromium.org
aleventhal@chromium.org
+dlibby@microsoft.com
dmazzoni@chromium.org
+kschmi@microsoft.com
nektar@chromium.org
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 8ba9a008a97..5db8c559772 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
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
namespace test {
@@ -36,7 +37,7 @@ TEST_F(AccessibilityObjectModelTest, DOMElementsHaveAnAccessibleNode) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<button id=button>Click me</button>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* button = GetDocument().getElementById("button");
EXPECT_NE(nullptr, button->accessibleNode());
@@ -52,7 +53,7 @@ TEST_F(AccessibilityObjectModelTest, SetAccessibleNodeRole) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<button id=button>Click me</button>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* cache = AXObjectCache();
ASSERT_NE(nullptr, cache);
@@ -78,7 +79,7 @@ TEST_F(AccessibilityObjectModelTest, AOMDoesNotReflectARIA) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<input id=textbox>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
// Set ARIA attributes.
auto* textbox = GetDocument().getElementById("textbox");
@@ -107,7 +108,7 @@ TEST_F(AccessibilityObjectModelTest, AOMPropertiesCanBeCleared) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<input type=button id=button>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
// Set ARIA attributes.
auto* button = GetDocument().getElementById("button");
@@ -159,7 +160,7 @@ TEST_F(AccessibilityObjectModelTest, RangeProperties) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<div role=slider id=slider>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* slider = GetDocument().getElementById("slider");
ASSERT_NE(nullptr, slider);
@@ -185,7 +186,7 @@ TEST_F(AccessibilityObjectModelTest, Level) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<div role=heading id=heading>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* heading = GetDocument().getElementById("heading");
ASSERT_NE(nullptr, heading);
@@ -202,7 +203,7 @@ TEST_F(AccessibilityObjectModelTest, ListItem) {
LoadURL("https://example.com/");
main_resource.Complete(
"<div role=list><div role=listitem id=listitem></div></div>");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* listitem = GetDocument().getElementById("listitem");
ASSERT_NE(nullptr, listitem);
@@ -227,7 +228,7 @@ TEST_F(AccessibilityObjectModelTest, Grid) {
</div>
</div>
)HTML");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* grid = GetDocument().getElementById("grid");
ASSERT_NE(nullptr, grid);
@@ -274,6 +275,7 @@ TEST_F(AccessibilityObjectModelTest, SparseAttributes) {
aria-virtualcontent=block-end
aria-activedescendant=active
aria-details=details
+ aria-invalid=true
aria-errormessage=error>
<div id=active role=option></div>
<div id=active2 role=gridcell></div>
@@ -282,7 +284,7 @@ TEST_F(AccessibilityObjectModelTest, SparseAttributes) {
<div id=error role=article>Error</div>
<div id=error2 role=banner>Error 2</div>
)HTML");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* target = GetDocument().getElementById("target");
auto* cache = AXObjectCache();
@@ -361,7 +363,7 @@ TEST_F(AccessibilityObjectModelTest, LabeledBy) {
<label id=l2>Label 2</label>
<label id=l3>Label 3</label>
)HTML");
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
auto* target = GetDocument().getElementById("target");
auto* l1 = GetDocument().getElementById("l1");
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 9ee0a87f11a..e9d67000f15 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
@@ -28,13 +28,13 @@
#include "third_party/blink/renderer/modules/accessibility/ax_image_map_link.h"
+#include "skia/ext/skia_matrix_44.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/core/html/html_image_element.h"
#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
namespace blink {
@@ -102,7 +102,7 @@ KURL AXImageMapLink::Url() const {
void AXImageMapLink::GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children) const {
*out_container = nullptr;
out_bounds_in_container = FloatRect();
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.h
index c325cc031d4..c43de037e76 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.h
@@ -67,7 +67,7 @@ class AXImageMapLink final : public AXNodeObject {
static AXObject* GetAXObjectForImageMap(AXObjectCacheImpl& cache, Node* area);
void GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children = nullptr) const override;
private:
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 f6f95831d8f..8e975798425 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
@@ -56,7 +56,7 @@ AXInlineTextBox::AXInlineTextBox(
void AXInlineTextBox::GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children) const {
*out_container = nullptr;
out_bounds_in_container = FloatRect();
@@ -98,7 +98,7 @@ void AXInlineTextBox::TextCharacterOffsets(Vector<int>& offsets) const {
Vector<float> widths;
inline_text_box_->CharacterWidths(widths);
- DCHECK_EQ(int{widths.size()}, TextLength());
+ DCHECK_EQ(static_cast<int>(widths.size()), TextLength());
offsets.resize(TextLength());
float width_so_far = 0;
@@ -131,8 +131,8 @@ int AXInlineTextBox::TextOffsetInFormattingContext(int offset) const {
return 0;
// Retrieve the text offset from the start of the layout block flow ancestor.
- return int{inline_text_box_->TextOffsetInFormattingContext(
- static_cast<unsigned int>(offset))};
+ return static_cast<int>(inline_text_box_->TextOffsetInFormattingContext(
+ static_cast<unsigned int>(offset)));
}
int AXInlineTextBox::TextOffsetInContainer(int offset) const {
@@ -389,7 +389,7 @@ bool AXInlineTextBox::IsLineBreakingObject() const {
int AXInlineTextBox::TextLength() const {
if (IsDetached())
return 0;
- return int{inline_text_box_->Len()};
+ return static_cast<int>(inline_text_box_->Len());
}
void AXInlineTextBox::ClearChildren() const {
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h
index 98d17ed1906..d940404b0cc 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h
@@ -56,7 +56,7 @@ class AXInlineTextBox final : public AXObject {
int TextOffsetInContainer(int offset) const override;
void GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children = nullptr) const override;
ax::mojom::blink::WritingDirection GetTextDirection() const override;
Node* GetNode() const override;
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 454c0502df3..e0b80ecad0a 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
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/events/event_util.h"
#include "third_party/blink/renderer/core/frame/frame_owner.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -216,14 +217,19 @@ ax::mojom::blink::Role AXLayoutObject::RoleFromLayoutObjectOrNode() const {
// the screen reader determine what to do for CSS tables. If this line
// is reached, then it is not an HTML table, and therefore will only be
// considered a data table if ARIA markup indicates it is a table.
- if (layout_object_->IsTable() && node)
- return ax::mojom::blink::Role::kLayoutTable;
- if (layout_object_->IsTableSection())
- return DetermineTableSectionRole();
- if (layout_object_->IsTableRow() && node)
- return DetermineTableRowRole();
- if (layout_object_->IsTableCell() && node)
- return DetermineTableCellRole();
+ // Additionally, as pseudo elements don't have any structure it doesn't make
+ // sense to report their table-related layout roles that could be set via the
+ // display property.
+ if (node && !node->IsPseudoElement()) {
+ if (layout_object_->IsTable())
+ return ax::mojom::blink::Role::kLayoutTable;
+ if (layout_object_->IsTableSection())
+ return DetermineTableSectionRole();
+ if (layout_object_->IsTableRow())
+ return DetermineTableRowRole();
+ if (layout_object_->IsTableCell())
+ return DetermineTableCellRole();
+ }
if (IsImageOrAltText(layout_object_, node)) {
if (IsA<HTMLInputElement>(node))
@@ -309,31 +315,6 @@ static bool IsLinkable(const AXObject& object) {
object.GetLayoutObject()->IsText();
}
-bool AXLayoutObject::IsLineBreakingObject() const {
- if (IsDetached())
- return false;
-
- // Presentational objects should not contribute any of their remove semantic
- // meaning to the accessibility tree, including to its text representation.
- if (IsPresentational())
- return false;
-
- // Without this condition, LayoutNG reports list markers as line breaking
- // objects (legacy layout does not).
- if (RoleValue() == ax::mojom::blink::Role::kListMarker)
- return false;
-
- const LayoutObject* layout_object = GetLayoutObject();
- if (layout_object->IsBR() || layout_object->IsLayoutBlock() ||
- layout_object->IsTableSection() || layout_object->IsAnonymousBlock() ||
- (layout_object->IsLayoutBlockFlow() &&
- layout_object->StyleRef().IsDisplayBlockContainer())) {
- return true;
- }
-
- return AXNodeObject::IsLineBreakingObject();
-}
-
bool AXLayoutObject::IsLinked() const {
if (!IsLinkable(*this))
return false;
@@ -406,9 +387,17 @@ AXObjectInclusion AXLayoutObject::DefaultObjectInclusion(
static bool HasLineBox(const LayoutBlockFlow& block_flow) {
if (!block_flow.IsLayoutNGMixin())
return block_flow.FirstLineBox();
- if (block_flow.HasNGInlineNodeData())
- return !block_flow.GetNGInlineNodeData()->IsEmptyInline();
+
// TODO(layout-dev): We should call this function after layout completion.
+ NGInlineCursor cursor(block_flow);
+ if (!cursor.HasRoot())
+ return false;
+
+ for (cursor.MoveToFirstLine(); cursor; cursor.MoveToNextLine()) {
+ if (!cursor.CurrentItem()->IsEmptyLineBox())
+ return true;
+ }
+
return false;
}
@@ -469,6 +458,26 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
if (semantic_inclusion == kIgnoreObject)
return true;
+ // Inner editor element of editable area with empty text provides bounds
+ // used to compute the character extent for index 0. This is the same as
+ // what the caret's bounds would be if the editable area is focused.
+ if (node) {
+ const TextControlElement* text_control = EnclosingTextControl(node);
+ if (text_control) {
+ // Keep only the inner editor element and it's children.
+ // If inline textboxes are being loaded, then the inline textbox for the
+ // text wil be included by AXNodeObject::AddInlineTextboxChildren().
+ // By only keeping the inner editor and its text, it makes finding the
+ // inner editor simpler on the browser side.
+ // See BrowserAccessibility::GetTextFieldInnerEditorElement().
+ // TODO(accessibility) In the future, we may want to keep all descendants
+ // of the inner text element -- right now we only include one internally
+ // used container, it's text, and possibly the text's inlinext text box.
+ return text_control->InnerEditorElement() != node &&
+ text_control->InnerEditorElement() != NodeTraversal::Parent(*node);
+ }
+ }
+
// 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())
@@ -485,15 +494,6 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
// Make sure renderers with layers stay in the tree.
if (GetLayoutObject() && GetLayoutObject()->HasLayer() && node &&
node->hasChildren()) {
- if (IsPlaceholder()) {
- // Placeholder is already exposed via AX attributes, do not expose as
- // child of text input. Therefore, if there is a child of a text input,
- // it will contain the value.
- if (ignored_reasons)
- ignored_reasons->push_back(IgnoredReason(kAXPresentational));
- return true;
- }
-
return false;
}
@@ -571,15 +571,6 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
return false;
}
- // Inner editor element of editable area with empty text provides bounds
- // used to compute the character extent for index 0. This is the same as
- // what the caret's bounds would be if the editable area is focused.
- if (node) {
- const TextControlElement* text_control = EnclosingTextControl(node);
- if (text_control && text_control->InnerEditorElement() == node)
- return false;
- }
-
// Ignore layout objects that are block flows with inline children. These
// are usually dummy layout objects that pad out the tree, but there are
// some exceptions below.
@@ -639,7 +630,7 @@ ax::mojom::blink::ListStyle AXLayoutObject::GetListStyle() const {
return ax::mojom::blink::ListStyle::kNone;
case ListMarker::ListStyleCategory::kSymbol: {
const AtomicString& counter_style_name =
- computed_style->GetListStyleType()->GetCounterStyleName();
+ computed_style->ListStyleType()->GetCounterStyleName();
if (counter_style_name == "disc")
return ax::mojom::blink::ListStyle::kDisc;
if (counter_style_name == "circle")
@@ -650,14 +641,13 @@ ax::mojom::blink::ListStyle AXLayoutObject::GetListStyle() const {
}
case ListMarker::ListStyleCategory::kLanguage: {
const AtomicString& counter_style_name =
- computed_style->GetListStyleType()->GetCounterStyleName();
+ computed_style->ListStyleType()->GetCounterStyleName();
if (counter_style_name == "decimal")
return ax::mojom::blink::ListStyle::kNumeric;
if (counter_style_name == "decimal-leading-zero") {
// 'decimal-leading-zero' may be overridden by custom counter styles. We
// return kNumeric only when we are using the predefined counter style.
- if (!RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled() ||
- ListMarker::GetCounterStyle(*GetDocument(), *computed_style)
+ if (ListMarker::GetCounterStyle(*GetDocument(), *computed_style)
.IsPredefined())
return ax::mojom::blink::ListStyle::kNumeric;
}
@@ -755,6 +745,7 @@ static AXObject* NextOnLineInternalNG(const AXObject& ax_object) {
cursor.MoveToNextInlineLeafOnLine();
if (cursor) {
LayoutObject* runner_layout_object = cursor.CurrentMutableLayoutObject();
+ DCHECK(runner_layout_object);
AXObject* result =
ax_object.AXObjectCache().GetOrCreate(runner_layout_object);
result = GetDeepestAXChildInLayoutTree(result, true);
@@ -779,16 +770,15 @@ static AXObject* NextOnLineInternalNG(const AXObject& ax_object) {
if (!ax_result)
return nullptr;
-#if DCHECK_IS_ON()
- if (!ax_object.AXObjectCache().IsAriaOwned(&ax_object)) {
- DCHECK_NE(ax_result->ParentObject(), &ax_object)
- << "NextOnLine() must not point to a child of the current object. "
- "Because inline objects without try to return a result from their "
- "parents, using a descendant can cause a previous position to be "
- "reused, which appears as a loop in the nextOnLine data, and "
- "can cause an infinite loop in consumers of the nextOnLine data";
+ if (!ax_object.AXObjectCache().IsAriaOwned(&ax_object) &&
+ ax_result->ParentObject() == &ax_object) {
+ // NextOnLine() must not point to a child of the current object.
+ // Because inline objects try to return a result from their
+ // parents, using a descendant can cause a previous position to be
+ // reused, which appears as a loop in the nextOnLine data, and
+ // can cause an infinite loop in consumers of the nextOnLine data.
+ return nullptr;
}
-#endif
return ax_result;
}
@@ -803,6 +793,8 @@ AXObject* AXLayoutObject::NextOnLine() const {
return nullptr;
}
+ DCHECK(GetLayoutObject());
+
if (GetLayoutObject()->IsBoxListMarkerIncludingNG()) {
// A list marker should be followed by a list item on the same line.
// Note that pseudo content is always included in the tree, so
@@ -904,6 +896,7 @@ static AXObject* PreviousOnLineInlineNG(const AXObject& ax_object) {
cursor.MoveToPreviousInlineLeafOnLine();
if (cursor) {
LayoutObject* runner_layout_object = cursor.CurrentMutableLayoutObject();
+ DCHECK(runner_layout_object);
AXObject* result =
ax_object.AXObjectCache().GetOrCreate(runner_layout_object);
result = GetDeepestAXChildInLayoutTree(result, false);
@@ -929,16 +922,15 @@ static AXObject* PreviousOnLineInlineNG(const AXObject& ax_object) {
if (!ax_result)
return nullptr;
-#if DCHECK_IS_ON()
- if (!ax_object.AXObjectCache().IsAriaOwned(&ax_object)) {
- DCHECK_NE(ax_result->ParentObject(), &ax_object)
- << "PreviousOnLine() must not point to a child of the current object. "
- "Because inline objects without try to return a result from their "
- "parents, using a descendant can cause a previous position to be "
- "reused, which appears as a loop in the previousOnLine data, and "
- "can cause an infinite loop in consumers of the previousOnLine data";
+ if (!ax_object.AXObjectCache().IsAriaOwned(&ax_object) &&
+ ax_result->ParentObject() == &ax_object) {
+ // PreviousOnLine() must not point to a child of the current object.
+ // Because inline objects without try to return a result from their
+ // parents, using a descendant can cause a previous position to be
+ // reused, which appears as a loop in the previousOnLine data, and
+ // can cause an infinite loop in consumers of the previousOnLine data.
+ return nullptr;
}
-#endif
return ax_result;
}
@@ -953,6 +945,8 @@ AXObject* AXLayoutObject::PreviousOnLine() const {
return nullptr;
}
+ DCHECK(GetLayoutObject());
+
AXObject* previous_sibling = AccessibilityIsIncludedInTree()
? PreviousSiblingIncludingIgnored()
: nullptr;
@@ -1020,12 +1014,13 @@ AXObject* AXLayoutObject::PreviousOnLine() const {
// Properties of interactive elements.
//
-String AXLayoutObject::TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::blink::NameFrom& name_from,
- AXRelatedObjectVector* related_objects,
- NameSources* name_sources) const {
+String AXLayoutObject::TextAlternative(
+ bool recursive,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::blink::NameFrom& name_from,
+ AXRelatedObjectVector* related_objects,
+ NameSources* name_sources) const {
if (layout_object_) {
absl::optional<String> text_alternative = GetCSSAltText(GetNode());
bool found_text_alternative = false;
@@ -1083,9 +1078,9 @@ String AXLayoutObject::TextAlternative(bool recursive,
}
}
- return AXNodeObject::TextAlternative(recursive, in_aria_labelled_by_traversal,
- visited, name_from, related_objects,
- name_sources);
+ return AXNodeObject::TextAlternative(
+ recursive, aria_label_or_description_root, visited, name_from,
+ related_objects, name_sources);
}
//
@@ -1172,49 +1167,6 @@ Document* AXLayoutObject::GetDocument() const {
return &GetLayoutObject()->GetDocument();
}
-Element* AXLayoutObject::AnchorElement() const {
- if (!layout_object_)
- return nullptr;
-
- AXObjectCacheImpl& cache = AXObjectCache();
- LayoutObject* curr_layout_object;
-
- // Search up the layout tree for a LayoutObject with a DOM node. Defer to an
- // earlier continuation, though.
- for (curr_layout_object = layout_object_;
- curr_layout_object && !curr_layout_object->GetNode();
- curr_layout_object = curr_layout_object->Parent()) {
- auto* curr_block_flow = DynamicTo<LayoutBlockFlow>(curr_layout_object);
- if (!curr_block_flow || !curr_block_flow->IsAnonymousBlock())
- continue;
-
- if (LayoutObject* continuation = curr_block_flow->Continuation())
- return cache.GetOrCreate(continuation)->AnchorElement();
- }
- // bail if none found
- if (!curr_layout_object)
- return nullptr;
-
- // Search up the DOM tree for an anchor element.
- // NOTE: this assumes that any non-image with an anchor is an
- // HTMLAnchorElement
- Node* node = curr_layout_object->GetNode();
- if (!node)
- return nullptr;
- for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*node)) {
- if (IsA<HTMLAnchorElement>(runner))
- return To<Element>(&runner);
-
- if (LayoutObject* layout_object = runner.GetLayoutObject()) {
- AXObject* ax_object = cache.GetOrCreate(layout_object);
- if (ax_object && ax_object->IsAnchor())
- return To<Element>(&runner);
- }
- }
-
- return nullptr;
-}
-
void AXLayoutObject::HandleAutofillStateChanged(WebAXAutofillState state) {
// Autofill state is stored in AXObjectCache.
AXObjectCache().SetAutofillState(AXObjectID(), state);
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 9b376d41ccf..abb2b8d0fe3 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
@@ -37,7 +37,6 @@
namespace blink {
class AXObjectCacheImpl;
-class Element;
class HTMLAreaElement;
class IntPoint;
class Node;
@@ -57,7 +56,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
// DOM and layout tree access.
Document* GetDocument() const override;
- Element* AnchorElement() const override;
protected:
LayoutObject* layout_object_;
@@ -70,7 +68,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
bool IsAXLayoutObject() const final;
// Check object role or purpose.
- bool IsLineBreakingObject() const override;
bool IsLinked() const override;
bool IsOffScreen() const override;
bool IsVisited() const override;
@@ -91,7 +88,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
// AX name calc.
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::blink::NameFrom&,
AXRelatedObjectVector*,
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object_test.cc
index ef26ab34184..73ae0bd0ec8 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object_test.cc
@@ -167,25 +167,7 @@ TEST_F(AXLayoutObjectTest, AccessibilityHitTestShadowDOM) {
}
// https://crbug.com/1167596
-TEST_F(AXLayoutObjectTest, GetListStyleDecimalLeadingZero) {
- ScopedCSSAtRuleCounterStyleForTest scope(false);
-
- using ListStyle = ax::mojom::blink::ListStyle;
-
- SetBodyInnerHTML(R"HTML(
- <ul>
- <li id="target" style="list-style-type: decimal-leading-zero"></li>
- </ul>
- )HTML");
-
- EXPECT_EQ(ListStyle::kNumeric,
- GetAXObjectByElementId("target")->GetListStyle());
-}
-
-// https://crbug.com/1167596
TEST_F(AXLayoutObjectTest, GetListStyleDecimalLeadingZeroAsCustomCounterStyle) {
- ScopedCSSAtRuleCounterStyleForTest scope(true);
-
using ListStyle = ax::mojom::blink::ListStyle;
SetBodyInnerHTML(R"HTML(
@@ -199,8 +181,6 @@ TEST_F(AXLayoutObjectTest, GetListStyleDecimalLeadingZeroAsCustomCounterStyle) {
}
// https://crbug.com/1167596
TEST_F(AXLayoutObjectTest, GetListStyleOverriddenDecimalLeadingZero) {
- ScopedCSSAtRuleCounterStyleForTest scope(true);
-
using ListStyle = ax::mojom::blink::ListStyle;
SetBodyInnerHTML(R"HTML(
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 d2924bba469..9b40a67809b 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
@@ -74,12 +74,13 @@ bool AXListBoxOption::ComputeAccessibilityIsIgnored(
return false;
}
-String AXListBoxOption::TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::NameFrom& name_from,
- AXRelatedObjectVector* related_objects,
- NameSources* name_sources) const {
+String AXListBoxOption::TextAlternative(
+ bool recursive,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::NameFrom& name_from,
+ AXRelatedObjectVector* related_objects,
+ NameSources* name_sources) const {
// If nameSources is non-null, relatedObjects is used in filling it in, so it
// must be non-null as well.
if (name_sources)
@@ -90,7 +91,7 @@ String AXListBoxOption::TextAlternative(bool recursive,
bool found_text_alternative = false;
String text_alternative = AriaTextAlternative(
- recursive, in_aria_labelled_by_traversal, visited, name_from,
+ recursive, aria_label_or_description_root, visited, name_from,
related_objects, name_sources, &found_text_alternative);
if (found_text_alternative && !name_sources)
return text_alternative;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.h
index e4bb885433f..345992a5b82 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.h
@@ -50,7 +50,7 @@ class AXListBoxOption final : public AXLayoutObject {
bool OnNativeSetSelectedAction(bool) override;
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom&,
AXRelatedObjectVector*,
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.cc
index a339d726a08..4715a48eb4f 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.cc
@@ -27,7 +27,7 @@ AccessibilityMediaElement::AccessibilityMediaElement(
String AccessibilityMediaElement::TextAlternative(
bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom& name_from,
AXRelatedObjectVector* related_objects,
@@ -41,7 +41,7 @@ String AccessibilityMediaElement::TextAlternative(
return element->GetLocale().QueryString(IDS_MEDIA_PLAYBACK_ERROR);
}
return AXLayoutObject::TextAlternative(
- recursive, in_aria_labelled_by_traversal, visited, name_from,
+ recursive, aria_label_or_description_root, visited, name_from,
related_objects, name_sources);
}
@@ -61,24 +61,6 @@ AXRestriction AccessibilityMediaElement::Restriction() const {
return AXNodeObject::Restriction();
}
-bool AccessibilityMediaElement::HasControls() const {
- if (IsDetached())
- return false;
- if (!IsA<HTMLMediaElement>(GetNode()) || !GetNode()->isConnected()) {
- NOTREACHED() << "Accessible media element not ready: " << GetNode()
- << " isConnected? " << GetNode()->isConnected();
- return false;
- }
- return To<HTMLMediaElement>(GetNode())->ShouldShowControls();
-}
-
-bool AccessibilityMediaElement::HasEmptySource() const {
- if (IsDetached())
- return false;
- return To<HTMLMediaElement>(GetNode())->getNetworkState() ==
- HTMLMediaElement::kNetworkEmpty;
-}
-
bool AccessibilityMediaElement::IsUnplayable() const {
if (IsDetached())
return true;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.h
index 7676bee42cc..e58ceb9e25e 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.h
@@ -22,7 +22,7 @@ class AccessibilityMediaElement : public AXLayoutObject {
// AXLayoutObject overrides.
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom&,
AXRelatedObjectVector*,
@@ -34,8 +34,6 @@ class AccessibilityMediaElement : public AXLayoutObject {
AXRestriction Restriction() const override;
protected:
- bool HasControls() const;
- bool HasEmptySource() const;
bool IsUnplayable() const;
DISALLOW_COPY_AND_ASSIGN(AccessibilityMediaElement);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
index 8dddcb56c54..2888a418d10 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
@@ -51,6 +51,10 @@ bool AXMenuList::OnNativeClickAction() {
select->HidePopup();
else
select->ShowPopup();
+
+ // Send notification that action has been handled.
+ AXObjectCache().HandleClicked(GetNode());
+
return true;
}
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 bcd8b2447dd..36544df0553 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
@@ -25,13 +25,13 @@
#include "third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h"
+#include "skia/ext/skia_matrix_44.h"
#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/dom/events/simulated_click_options.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"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
namespace blink {
@@ -143,10 +143,11 @@ bool AXMenuListOption::ComputeAccessibilityIsIgnored(
return AccessibilityIsIgnoredByDefault(ignored_reasons);
}
-void AXMenuListOption::GetRelativeBounds(AXObject** out_container,
- FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
- bool* clips_children) const {
+void AXMenuListOption::GetRelativeBounds(
+ AXObject** out_container,
+ FloatRect& out_bounds_in_container,
+ skia::Matrix44& out_container_transform,
+ bool* clips_children) const {
DCHECK(!IsDetached());
*out_container = nullptr;
out_bounds_in_container = FloatRect();
@@ -174,12 +175,13 @@ void AXMenuListOption::GetRelativeBounds(AXObject** out_container,
}
}
-String AXMenuListOption::TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::NameFrom& name_from,
- AXRelatedObjectVector* related_objects,
- NameSources* name_sources) const {
+String AXMenuListOption::TextAlternative(
+ bool recursive,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::NameFrom& name_from,
+ AXRelatedObjectVector* related_objects,
+ NameSources* name_sources) const {
// If nameSources is non-null, relatedObjects is used in filling it in, so it
// must be non-null as well.
if (name_sources)
@@ -190,7 +192,7 @@ String AXMenuListOption::TextAlternative(bool recursive,
bool found_text_alternative = false;
String text_alternative = AriaTextAlternative(
- recursive, in_aria_labelled_by_traversal, visited, name_from,
+ recursive, aria_label_or_description_root, visited, name_from,
related_objects, name_sources, &found_text_alternative);
if (found_text_alternative && !name_sources)
return text_alternative;
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 74d30ee4f5d..36235604545 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
@@ -58,10 +58,10 @@ class AXMenuListOption final : public AXNodeObject {
void GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children = nullptr) const override;
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom&,
AXRelatedObjectVector*,
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 10cd1b53341..cc959dde006 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
@@ -152,14 +152,14 @@ void AXMenuListPopup::DidUpdateActiveOption(int option_index,
if (old_index != option_index && old_index >= 0 &&
old_index < static_cast<int>(children_.size())) {
AXObject* previous_child = children_[old_index].Get();
- cache.MarkAXObjectDirtyWithCleanLayout(previous_child, false);
+ cache.MarkAXObjectDirtyWithCleanLayout(previous_child);
}
if (option_index >= 0 && option_index < static_cast<int>(children_.size())) {
AXObject* child = children_[option_index].Get();
cache.PostNotification(this, ax::mojom::Event::kChildrenChanged);
cache.PostNotification(this, ax::mojom::Event::kActiveDescendantChanged);
- cache.MarkAXObjectDirtyWithCleanLayout(child, false);
+ cache.MarkAXObjectDirtyWithCleanLayout(child);
}
}
@@ -169,7 +169,7 @@ void AXMenuListPopup::DidHide() {
cache.PostNotification(this, ax::mojom::Event::kHide);
if (descendant) {
cache.PostNotification(this, ax::mojom::Event::kChildrenChanged);
- cache.MarkAXObjectDirtyWithCleanLayout(descendant, false);
+ cache.MarkAXObjectDirtyWithCleanLayout(descendant);
}
}
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 4455cbe96ab..04d036b75a4 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,11 +30,13 @@
#include <math.h>
#include <memory>
+#include <queue>
#include <algorithm>
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
#include "third_party/blink/renderer/core/aom/accessible_node.h"
@@ -48,6 +50,7 @@
#include "third_party/blink/renderer/core/dom/qualified_name.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/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/events/event_util.h"
@@ -92,7 +95,6 @@
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_file_upload_control.h"
-#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_table.h"
@@ -105,6 +107,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/core/svg/svg_title_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_layout_object.h"
@@ -120,19 +123,54 @@
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "ui/accessibility/ax_common.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace {
-blink::HTMLMapElement* GetMapForImage(blink::LayoutObject* layout_object) {
- blink::LayoutImage* layout_image =
- blink::DynamicTo<blink::LayoutImage>(layout_object);
- if (!layout_image)
- return nullptr;
+// It is not easily possible to find out if an element is the target of an
+// in-page link.
+// As a workaround, we consider the following to be potential targets:
+// - <a name>
+// - <foo id> -- an element with an id that is not SVG, a <label> or <optgroup>.
+// <label> does not make much sense as an in-page link target.
+// Exposing <optgroup> is redundant, as the group is already exposed via a
+// child in its shadow DOM, which contains the accessible name.
+// #document -- this is always a potential link target via <a name="#">.
+// This is a compromise that does not include too many elements, and
+// has minimal impact on tests.
+bool IsPotentialInPageLinkTarget(blink::Node& node) {
+ auto* element = blink::DynamicTo<blink::Element>(&node);
+ if (!element) {
+ // The document itself is a potential link target, e.g. via <a name="#">.
+ return blink::IsA<blink::Document>(node);
+ }
+
+ // We exclude elements that are in the shadow DOM. They cannot be linked by a
+ // document fragment from the main page:as they have their own id namespace.
+ if (element->ContainingShadowRoot())
+ return false;
+
+ // SVG elements are unlikely link targets, and we want to avoid creating
+ // a lot of noise in the AX tree or breaking tests unnecessarily.
+ if (element->IsSVGElement())
+ return false;
+
+ // <a name>
+ if (auto* anchor = blink::DynamicTo<blink::HTMLAnchorElement>(element)) {
+ if (anchor->HasName())
+ return true;
+ }
- return layout_image->ImageMap();
+ // <foo id> not in an <optgroup> or <label>.
+ if (element->HasID() && !blink::IsA<blink::HTMLLabelElement>(element) &&
+ !blink::IsA<blink::HTMLOptGroupElement>(element)) {
+ return true;
+ }
+
+ return false;
}
bool IsNeutralWithinTable(blink::AXObject* obj) {
@@ -165,8 +203,6 @@ blink::AXObject* GetDOMTableAXAncestor(blink::Node* node,
if (ax_object && !IsNeutralWithinTable(ax_object))
return ax_object;
}
-
- return nullptr;
}
enum class AXAction {
@@ -224,6 +260,32 @@ TextDecorationStyleToAXTextDecorationStyle(
return ax::mojom::blink::TextDecorationStyle::kNone;
}
+String GetTitle(blink::Element* element) {
+ if (!element)
+ return String();
+
+ if (blink::SVGElement* svg_element =
+ blink::DynamicTo<blink::SVGElement>(element)) {
+ // Don't use title() in SVG, as it calls innerText() which updates layout.
+ // Unfortunately, this must duplicate some logic from SVGElement::title().
+ if (svg_element->InUseShadowTree()) {
+ String title = GetTitle(svg_element->OwnerShadowHost());
+ if (!title.IsEmpty())
+ return title;
+ }
+ // If we aren't an instance in a <use> or the <use> title was not found,
+ // then find the first <title> child of this element. If a title child was
+ // found, return the text contents.
+ if (auto* title_element =
+ blink::Traversal<blink::SVGTitleElement>::FirstChild(*element)) {
+ return title_element->GetInnerTextWithoutUpdate();
+ }
+ return String();
+ }
+
+ return element->title();
+}
+
} // namespace
namespace blink {
@@ -346,6 +408,21 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
return kDefaultBehavior;
}
+ // Avoid double speech. The ruby text describes pronunciation of the ruby
+ // base, and generally produces redundant screen reader output. Expose it only
+ // as a description on the <ruby> element so that screen reader users can
+ // toggle it on/off as with other descriptions/annotations.
+ if (RoleValue() == ax::mojom::blink::Role::kRubyAnnotation ||
+ (RoleValue() == ax::mojom::blink::Role::kStaticText && ParentObject() &&
+ ParentObject()->RoleValue() ==
+ ax::mojom::blink::Role::kRubyAnnotation)) {
+ return kIgnoreObject;
+ }
+
+ Element* element = GetElement();
+ if (!element)
+ return kDefaultBehavior;
+
if (IsTableLikeRole() || IsTableRowLikeRole() || IsTableCellLikeRole())
return kIncludeObject;
@@ -353,7 +430,7 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
if (!IsA<HTMLBodyElement>(node) && CanSetFocusAttribute())
return kIncludeObject;
- if (IsLink() || IsInPageLinkTarget())
+ if (IsLink())
return kIncludeObject;
// A click handler might be placed on an otherwise ignored non-empty block
@@ -363,7 +440,7 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
if (IsClickable())
return kIncludeObject;
- if (IsHeading() || IsLandmarkRelated())
+ if (IsHeading())
return kIncludeObject;
// Header and footer tags may also be exposed as landmark roles but not
@@ -381,6 +458,7 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
return kIncludeObject;
// Anything with CSS alt should be included.
+ // Descendants are pruned: IsRelevantPseudoElementDescendant() returns false.
// Note: this is duplicated from AXLayoutObject because CSS alt text may apply
// to both Elements and pseudo-elements.
absl::optional<String> alt_text = GetCSSAltText(GetNode());
@@ -401,24 +479,54 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
static const HashSet<ax::mojom::blink::Role> always_included_computed_roles =
{
ax::mojom::blink::Role::kAbbr,
+ ax::mojom::blink::Role::kApplication,
+ ax::mojom::blink::Role::kArticle,
+ ax::mojom::blink::Role::kBanner,
ax::mojom::blink::Role::kBlockquote,
+ ax::mojom::blink::Role::kComplementary,
ax::mojom::blink::Role::kContentDeletion,
+ ax::mojom::blink::Role::kContentInfo,
ax::mojom::blink::Role::kContentInsertion,
- ax::mojom::blink::Role::kDetails,
ax::mojom::blink::Role::kDescriptionList,
ax::mojom::blink::Role::kDescriptionListDetail,
ax::mojom::blink::Role::kDescriptionListTerm,
+ ax::mojom::blink::Role::kDetails,
ax::mojom::blink::Role::kDialog,
+ ax::mojom::blink::Role::kDocAcknowledgments,
+ ax::mojom::blink::Role::kDocAfterword,
+ ax::mojom::blink::Role::kDocAppendix,
+ ax::mojom::blink::Role::kDocBibliography,
+ ax::mojom::blink::Role::kDocChapter,
+ ax::mojom::blink::Role::kDocConclusion,
+ ax::mojom::blink::Role::kDocCredits,
+ ax::mojom::blink::Role::kDocEndnotes,
+ ax::mojom::blink::Role::kDocEpilogue,
+ ax::mojom::blink::Role::kDocErrata,
+ ax::mojom::blink::Role::kDocForeword,
+ ax::mojom::blink::Role::kDocGlossary,
+ ax::mojom::blink::Role::kDocIntroduction,
+ ax::mojom::blink::Role::kDocPart,
+ ax::mojom::blink::Role::kDocPreface,
+ ax::mojom::blink::Role::kDocPrologue,
+ ax::mojom::blink::Role::kDocToc,
ax::mojom::blink::Role::kFigcaption,
ax::mojom::blink::Role::kFigure,
+ ax::mojom::blink::Role::kFooter,
+ ax::mojom::blink::Role::kForm,
+ ax::mojom::blink::Role::kHeader,
ax::mojom::blink::Role::kList,
ax::mojom::blink::Role::kListItem,
+ ax::mojom::blink::Role::kMain,
ax::mojom::blink::Role::kMark,
ax::mojom::blink::Role::kMath,
ax::mojom::blink::Role::kMeter,
+ ax::mojom::blink::Role::kNavigation,
ax::mojom::blink::Role::kPluginObject,
ax::mojom::blink::Role::kProgressIndicator,
+ ax::mojom::blink::Role::kRegion,
ax::mojom::blink::Role::kRuby,
+ ax::mojom::blink::Role::kSearch,
+ ax::mojom::blink::Role::kSection,
ax::mojom::blink::Role::kSplitter,
ax::mojom::blink::Role::kTime,
};
@@ -427,17 +535,6 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
always_included_computed_roles.end())
return kIncludeObject;
- // Avoid double speech. The ruby text describes pronunciation of the ruby
- // base, and generally produces redundant screen reader output. Expose it only
- // as a description on the <ruby> element so that screen reader users can
- // toggle it on/off as with other descriptions/annotations.
- if (RoleValue() == ax::mojom::blink::Role::kRubyAnnotation ||
- (RoleValue() == ax::mojom::blink::Role::kStaticText && ParentObject() &&
- ParentObject()->RoleValue() ==
- ax::mojom::blink::Role::kRubyAnnotation)) {
- return kIgnoreObject;
- }
-
// 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
@@ -457,6 +554,10 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
return kIgnoreObject;
}
+ // Process potential in-page link targets
+ if (IsPotentialInPageLinkTarget(*element))
+ return kIncludeObject;
+
// <span> tags are inline tags and not meant to convey information if they
// have no other ARIA information on them. If we don't ignore them, they may
// emit signals expected to come from their parent.
@@ -482,7 +583,14 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
return kDefaultBehavior;
}
+// static
absl::optional<String> AXNodeObject::GetCSSAltText(const Node* node) {
+ // CSS alt text rules allow text to be assigned to ::before/::after content.
+ // For example, the following CSS assigns "bullet" text to bullet.png:
+ // .something::before {
+ // content: url(bullet.png) / "bullet";
+ // }
+
if (!node || !node->GetComputedStyle() ||
node->GetComputedStyle()->ContentBehavesAsNormal()) {
return absl::nullopt;
@@ -535,7 +643,8 @@ bool AXNodeObject::ComputeAccessibilityIsIgnored(
DCHECK(!GetLayoutObject());
if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*GetNode())) {
- if (DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+ if (IsAriaHidden() ||
+ DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
*GetNode(), DisplayLockActivationReason::kAccessibility)) {
if (ignored_reasons)
ignored_reasons->push_back(IgnoredReason(kAXNotRendered));
@@ -718,18 +827,17 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
return RoleFromLayoutObjectOrNode();
}
- if (GetCSSAltText(GetNode())) {
+ if (GetNode()->IsPseudoElement() && GetCSSAltText(GetNode())) {
const ComputedStyle* style = GetNode()->GetComputedStyle();
ContentData* content_data = style->GetContentData();
-
// We just check the first item of the content list to determine the
// appropriate role, should only ever be image or text.
- // TODO(accessibility) Should it still be possible to use an ARIA role here?
// TODO(accessibility) Is it possible to use CSS alt text on an HTML tag
// with strong semantics? If so, why are we overriding the role here?
// We only need to ensure the accessible name gets the CSS alt text.
- // Note: by doing this, we are often hiding a child image, because
- // CanHaveChildren() returns false for an image.
+ // Note: by doing this, we are often hiding child pseudo element content
+ // because IsRelevantPseudoElementDescendant() returns false when an
+ // ancestor has CSS alt text.
if (content_data->IsImage())
return ax::mojom::blink::Role::kImage;
@@ -742,23 +850,17 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (IsA<HTMLImageElement>(GetNode()))
return ax::mojom::blink::Role::kImage;
- // <a href> or <svg:a xlink:href>
- if (GetNode()->IsLink()) {
- // |HTMLAnchorElement| sets isLink only when it has kHrefAttr.
- return ax::mojom::blink::Role::kLink;
+ // <a> or <svg:a>.
+ if (IsA<HTMLAnchorElement>(GetNode()) || IsA<SVGAElement>(GetNode())) {
+ // Assume that an anchor element is a Role::kLink if it has an href or a
+ // click event listener.
+ if (GetNode()->IsLink() || IsClickable())
+ return ax::mojom::blink::Role::kLink;
+ return ax::mojom::blink::Role::kGenericContainer;
}
- if (IsA<HTMLPortalElement>(*GetNode())) {
+ if (IsA<HTMLPortalElement>(*GetNode()))
return ax::mojom::blink::Role::kPortal;
- }
-
- if (IsA<HTMLAnchorElement>(*GetNode())) {
- // We assume that an anchor element is LinkRole if it has event listeners
- // even though it doesn't have kHrefAttr.
- if (IsClickable())
- return ax::mojom::blink::Role::kLink;
- return ax::mojom::blink::Role::kAnchor;
- }
if (IsA<HTMLButtonElement>(*GetNode()))
return ButtonRoleType();
@@ -1178,28 +1280,57 @@ bool AXNodeObject::IsInputImage() const {
return false;
}
-// It is not easily possible to find out if an element is the target of an
-// in-page link.
-// As a workaround, we check if the element is a sectioning element with an ID,
-// or an anchor with a name.
-bool AXNodeObject::IsInPageLinkTarget() const {
- auto* element = DynamicTo<Element>(node_.Get());
- if (!element)
+bool AXNodeObject::IsLineBreakingObject() const {
+ // According to Blink Editing, objects without an associated DOM node such as
+ // pseudo-elements and list bullets, are never considered as paragraph
+ // boundaries.
+ if (IsDetached() || !GetNode())
return false;
- // We exclude elements that are in the shadow DOM.
- if (element->ContainingShadowRoot())
+
+ // Presentational objects should not contribute any of their semantic meaning
+ // to the accessibility tree, including to its text representation.
+ if (IsPresentational())
return false;
- if (auto* anchor = DynamicTo<HTMLAnchorElement>(element)) {
- return anchor->HasName() || anchor->HasID();
- }
+ // `IsEnclosingBlock` includes all elements with display block, inline block,
+ // table related, flex, grid, list item, flow-root, webkit-box, and display
+ // contents. This is the same function used by Blink > Editing for determining
+ // paragraph boundaries, i.e. line breaking objects.
+ if (IsEnclosingBlock(GetNode()))
+ return true;
- if (element->HasID() &&
- (IsLandmarkRelated() || IsA<HTMLSpanElement>(element) ||
- IsA<HTMLDivElement>(element))) {
+ // Not all <br> elements have an associated layout object. They might be
+ // "visibility: hidden" or within a display locked region. We need to check
+ // their DOM node first.
+ if (IsA<HTMLBRElement>(GetNode()))
return true;
+
+ const LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object)
+ return AXObject::IsLineBreakingObject();
+
+ if (layout_object->IsBR())
+ return true;
+
+ // LayoutText objects could include a paragraph break in their text. This can
+ // only occur if line breaks are preserved and a newline character is present
+ // in their collapsed text. Text collapsing removes all whitespace found in
+ // the HTML file, but a special style rule could be used to preserve line
+ // breaks.
+ //
+ // The best example is the <pre> element:
+ // <pre>Line 1
+ // Line 2</pre>
+ if (const LayoutText* layout_text = DynamicTo<LayoutText>(layout_object)) {
+ const ComputedStyle& style = layout_object->StyleRef();
+ if (layout_text->HasNonCollapsedText() && style.PreserveNewline() &&
+ layout_text->PlainText().find('\n') != WTF::kNotFound) {
+ return true;
+ }
}
- return false;
+
+ // Rely on the ARIA role to figure out if this object is line breaking.
+ return AXObject::IsLineBreakingObject();
}
bool AXNodeObject::IsLoaded() const {
@@ -1330,7 +1461,7 @@ AccessibilitySelectedState AXNodeObject::IsSelected() const {
// is marked as required or implied for this element in the ARIA specs.
// If this object can't follow the focus, then we can't say that it's selected
// nor that it's not.
- if (!SelectionShouldFollowFocus())
+ if (!ui::IsSelectRequiredOrImplicit(RoleValue()))
return kSelectedStateUndefined;
// Selection follows focus, but ONLY in single selection containers, and only
@@ -1338,21 +1469,43 @@ AccessibilitySelectedState AXNodeObject::IsSelected() const {
return IsSelectedFromFocus() ? kSelectedStateTrue : kSelectedStateFalse;
}
+bool AXNodeObject::IsSelectedFromFocusSupported() const {
+ // The selection should only follow the focus when the aria-selected attribute
+ // is marked as required or implied for this element in the ARIA specs.
+ // If this object can't follow the focus, then we can't say that it's selected
+ // nor that it's not.
+ // TODO(crbug.com/1143483): Consider allowing more roles.
+ if (!ui::IsSelectRequiredOrImplicit(RoleValue()))
+ return false;
+
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-selected
+ // Any explicit assignment of aria-selected takes precedence over the implicit
+ // selection based on focus.
+ bool is_selected;
+ if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kSelected, is_selected))
+ return false;
+
+ // Selection follows focus only when in a single selection container.
+ const AXObject* container = ContainerWidget();
+ if (!container || container->IsMultiSelectable())
+ return false;
+
+ // TODO(crbug.com/1143451): https://www.w3.org/TR/wai-aria-1.1/#aria-selected
+ // If any DOM element in the widget is explicitly marked as selected, the user
+ // agent MUST NOT convey implicit selection for the widget.
+ return true;
+}
+
// In single selection containers, selection follows focus unless aria_selected
// is set to false. This is only valid for a subset of elements.
bool AXNodeObject::IsSelectedFromFocus() const {
- if (!SelectionShouldFollowFocus())
+ if (!IsSelectedFromFocusSupported())
return false;
// A tab item can also be selected if it is associated to a focused tabpanel
// via the aria-labelledby attribute.
if (IsTabItem() && IsTabItemSelected())
- return kSelectedStateTrue;
-
- // If not a single selection container, selection does not follow focus.
- AXObject* container = ContainerWidget();
- if (!container || container->IsMultiSelectable())
- return false;
+ return true;
// If this object is not accessibility focused, then it is not selected from
// focus.
@@ -1361,25 +1514,7 @@ bool AXNodeObject::IsSelectedFromFocus() const {
(!focused_object || focused_object->ActiveDescendant() != this))
return false;
- // In single selection container and accessibility focused => true if
- // aria-selected wasn't used as an override.
- bool is_selected;
- return !HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kSelected,
- is_selected);
-}
-
-// Returns true if the node's aria-selected attribute should be set to true
-// when the node is focused. This is true for only a subset of roles.
-bool AXNodeObject::SelectionShouldFollowFocus() const {
- switch (RoleValue()) {
- case ax::mojom::blink::Role::kListBoxOption:
- case ax::mojom::blink::Role::kMenuListOption:
- case ax::mojom::blink::Role::kTab:
- return true;
- default:
- break;
- }
- return false;
+ return true;
}
bool AXNodeObject::IsTabItemSelected() const {
@@ -1629,8 +1764,6 @@ unsigned AXNodeObject::HierarchicalLevel() const {
default:
return 0;
}
-
- return 0;
}
String AXNodeObject::AutoComplete() const {
@@ -1722,7 +1855,7 @@ void AXNodeObject::SerializeMarkerAttributes(ui::AXNodeData* node_data) const {
}
AXObject* AXNodeObject::InPageLinkTarget() const {
- if (!IsAnchor() || !GetDocument())
+ if (!IsLink() || !GetDocument())
return AXObject::InPageLinkTarget();
const Element* anchor = AnchorElement();
@@ -1742,11 +1875,23 @@ AXObject* AXNodeObject::InPageLinkTarget() const {
String fragment = link_url.FragmentIdentifier();
TreeScope& tree_scope = anchor->GetTreeScope();
Node* target = tree_scope.FindAnchor(fragment);
- if (!target)
+ AXObject* ax_target = AXObjectCache().GetOrCreate(target);
+ if (!ax_target || !IsPotentialInPageLinkTarget(*ax_target->GetNode()))
return AXObject::InPageLinkTarget();
- // If the target is not in the accessibility tree, get the first unignored
- // sibling.
- return AXObjectCache().FirstAccessibleObjectFromNode(target);
+
+#if DCHECK_IS_ON()
+ // Link targets always have an element, unless it is the document itself,
+ // e.g. via <a href="#">.
+ DCHECK(ax_target->IsWebArea() || ax_target->GetElement())
+ << "The link target is expected to be a document or an element: "
+ << ax_target->ToString(true, true) << "\n* URL fragment = " << fragment;
+#endif
+
+ // Usually won't be ignored, but could be e.g. if aria-hidden.
+ if (ax_target->AccessibilityIsIgnored())
+ return nullptr;
+
+ return ax_target;
}
AccessibilityOrientation AXNodeObject::Orientation() const {
@@ -1871,7 +2016,36 @@ ax::mojom::blink::WritingDirection AXNodeObject::GetTextDirection() const {
return AXNodeObject::GetTextDirection();
}
+ax::mojom::blink::TextPosition AXNodeObject::GetTextPositionFromAria() const {
+ // Check for role="subscript" or role="superscript" on the element, or if
+ // static text, on the containing element.
+ AXObject* obj = nullptr;
+ if (RoleValue() == ax::mojom::blink::Role::kStaticText)
+ obj = ParentObject();
+ else if (RoleValue() == ax::mojom::blink::Role::kGenericContainer)
+ obj = const_cast<AXNodeObject*>(this); // May have role=sub/superscript.
+
+ if (obj) {
+ const AtomicString& aria_role =
+ obj->GetAOMPropertyOrARIAAttribute(AOMStringProperty::kRole);
+ if (aria_role == "subscript")
+ return ax::mojom::blink::TextPosition::kSubscript;
+ if (aria_role == "superscript")
+ return ax::mojom::blink::TextPosition::kSuperscript;
+ }
+
+ return ax::mojom::blink::TextPosition::kNone;
+}
+
ax::mojom::blink::TextPosition AXNodeObject::GetTextPosition() const {
+ if (GetNode()) {
+ // role="subscript" and role="superscript" don't use an internal role, they
+ // just return a TextPosition here.
+ const auto& text_position = GetTextPositionFromAria();
+ if (text_position != ax::mojom::blink::TextPosition::kNone)
+ return text_position;
+ }
+
if (!GetLayoutObject())
return AXObject::GetTextPosition();
@@ -2325,8 +2499,10 @@ bool AXNodeObject::MaxValueForRange(float* out_value) const {
}
// In ARIA 1.1, default value of scrollbar, separator and slider
- // for aria-valuemax were changed to 100.
+ // for aria-valuemax were changed to 100. This change was made for
+ // progressbar in ARIA 1.2.
switch (AriaRoleAttribute()) {
+ case ax::mojom::blink::Role::kProgressIndicator:
case ax::mojom::blink::Role::kScrollBar:
case ax::mojom::blink::Role::kSplitter:
case ax::mojom::blink::Role::kSlider: {
@@ -2358,8 +2534,10 @@ bool AXNodeObject::MinValueForRange(float* out_value) const {
}
// In ARIA 1.1, default value of scrollbar, separator and slider
- // for aria-valuemin were changed to 0.
+ // for aria-valuemin were changed to 0. This change was made for
+ // progressbar in ARIA 1.2.
switch (AriaRoleAttribute()) {
+ case ax::mojom::blink::Role::kProgressIndicator:
case ax::mojom::blink::Role::kScrollBar:
case ax::mojom::blink::Role::kSplitter:
case ax::mojom::blink::Role::kSlider: {
@@ -2404,18 +2582,8 @@ bool AXNodeObject::StepValueForRange(float* out_value) const {
}
KURL AXNodeObject::Url() const {
- if (IsAnchor()) {
- const Element* anchor = AnchorElement();
-
- if (const auto* html_anchor = DynamicTo<HTMLAnchorElement>(anchor)) {
- return html_anchor->Href();
- }
-
- // Some non-HTML elements, most notably SVG <a> elements, can act as
- // links/anchors.
- if (anchor)
- return anchor->HrefURL();
- }
+ if (IsLink()) // <area>, <link>, <html:a> or <svg:a>
+ return GetElement()->HrefURL();
if (IsWebArea() && GetDocument())
return GetDocument()->Url();
@@ -2482,7 +2650,7 @@ String AXNodeObject::GetValueForControl() const {
// We don't retrieve the element's value attribute on purpose. The value
// attribute might be sanitized and might be different from what is actually
// displayed inside the <select> element on screen.
- return select_element->InnerElement().innerText();
+ return select_element->InnerElement().GetInnerTextWithoutUpdate();
}
if (IsAtomicTextField()) {
@@ -2712,8 +2880,10 @@ bool AXNodeObject::HasContentEditableAttributeSet() const {
if (!html_element)
return false;
- String normalized_value = html_element->contentEditable();
- return normalized_value == "true" || normalized_value == "plaintext-only";
+ ContentEditableType normalized_value =
+ html_element->contentEditableNormalized();
+ return normalized_value == ContentEditableType::kContentEditable ||
+ normalized_value == ContentEditableType::kPlaintextOnly;
}
// Returns the nearest block-level LayoutBlockFlow ancestor
@@ -2802,12 +2972,13 @@ String AXNodeObject::GetName(ax::mojom::blink::NameFrom& name_from,
return name;
}
-String AXNodeObject::TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::blink::NameFrom& name_from,
- AXRelatedObjectVector* related_objects,
- NameSources* name_sources) const {
+String AXNodeObject::TextAlternative(
+ bool recursive,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::blink::NameFrom& name_from,
+ AXRelatedObjectVector* related_objects,
+ NameSources* name_sources) const {
// If nameSources is non-null, relatedObjects is used in filling it in, so it
// must be non-null as well.
if (name_sources)
@@ -2848,7 +3019,7 @@ String AXNodeObject::TextAlternative(bool recursive,
// Step 2C from: http://www.w3.org/TR/accname-aam-1.1 -- aria-label.
String text_alternative = AriaTextAlternative(
- recursive, in_aria_labelled_by_traversal, visited, name_from,
+ recursive, aria_label_or_description_root, visited, name_from,
related_objects, name_sources, &found_text_alternative);
if (found_text_alternative && !name_sources)
return text_alternative;
@@ -2864,7 +3035,7 @@ String AXNodeObject::TextAlternative(bool recursive,
return text_alternative;
// Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1 -- from content.
- if (in_aria_labelled_by_traversal || SupportsNameFromContents(recursive)) {
+ if (aria_label_or_description_root || SupportsNameFromContents(recursive)) {
Node* node = GetNode();
if (!IsA<HTMLSelectElement>(node)) { // Avoid option descendant text
name_from = ax::mojom::blink::NameFrom::kContents;
@@ -2891,7 +3062,7 @@ String AXNodeObject::TextAlternative(bool recursive,
}
}
- // Step 2H from: http://www.w3.org/TR/accname-aam-1.1
+ // Step 2I from: http://www.w3.org/TR/accname-aam-1.1
name_from = ax::mojom::blink::NameFrom::kTitle;
if (name_sources) {
name_sources->push_back(NameSource(found_text_alternative, kTitleAttr));
@@ -2981,7 +3152,7 @@ static bool ShouldInsertSpaceBetweenObjectsIfNeeded(
String AXNodeObject::TextFromDescendants(AXObjectSet& visited,
bool recursive) const {
if (!CanHaveChildren())
- return recursive ? String() : GetElement()->innerText();
+ return recursive ? String() : GetElement()->GetInnerTextWithoutUpdate();
StringBuilder accumulated_text;
AXObject* previous = nullptr;
@@ -2991,10 +3162,9 @@ String AXNodeObject::TextFromDescendants(AXObjectSet& visited,
AXObjectVector children;
HeapVector<Member<AXObject>> owned_children;
- AXObjectCache().GetAriaOwnedChildren(this, owned_children);
+ AXObjectCache().ValidatedAriaOwnedChildren(this, owned_children);
// TODO(aleventhal) Why isn't this just using cached children?
- AXNodeObject* parent = const_cast<AXNodeObject*>(this);
for (Node* child = LayoutTreeBuilderTraversal::FirstChild(*node_); child;
child = LayoutTreeBuilderTraversal::NextSibling(*child)) {
auto* child_text_node = DynamicTo<Text>(child);
@@ -3003,7 +3173,7 @@ String AXNodeObject::TextFromDescendants(AXObjectSet& visited,
// skip over empty text nodes
continue;
}
- AXObject* child_obj = AXObjectCache().GetOrCreate(child, parent);
+ AXObject* child_obj = AXObjectCache().GetOrCreate(child);
if (child_obj && !AXObjectCache().IsAriaOwned(child_obj))
children.push_back(child_obj);
}
@@ -3016,7 +3186,7 @@ String AXNodeObject::TextFromDescendants(AXObjectSet& visited,
break; // Need to add 1 because the root naming node is in the list.
// Don't recurse into children that are explicitly hidden.
- // Note that we don't call IsInertOrAriaHidden because that would return
+ // Note that we don't call IsInert()/IsAriaHidden because they would return
// true if any ancestor is hidden, but we need to be able to compute the
// accessible name of object inside hidden subtrees (for example, if
// aria-labelledby points to an object that's hidden).
@@ -3032,7 +3202,7 @@ String AXNodeObject::TextFromDescendants(AXObjectSet& visited,
result = child->TextFromDescendants(visited, true);
} else {
result =
- RecursiveTextAlternative(*child, false, visited, child_name_from);
+ RecursiveTextAlternative(*child, nullptr, visited, child_name_from);
}
if (!result.IsEmpty() && previous && accumulated_text.length() &&
@@ -3127,7 +3297,7 @@ bool AXNodeObject::IsRedundantLabel(HTMLLabelElement* label) {
void AXNodeObject::GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children) const {
if (GetLayoutObject()) {
AXObject::GetRelativeBounds(out_container, out_bounds_in_container,
@@ -3337,39 +3507,42 @@ int AXNodeObject::TextOffsetInFormattingContext(int offset) const {
inline_offset_mapping->GetMappingUnitsForLayoutObject(*layout_obj);
if (mapping_units.empty())
return AXObject::TextOffsetInFormattingContext(offset);
- return int{mapping_units.front().TextContentStart()} + offset;
+ return static_cast<int>(mapping_units.front().TextContentStart()) + offset;
}
//
// Inline text boxes.
//
-void AXNodeObject::LoadInlineTextBoxesRecursive() {
- if (ui::CanHaveInlineTextBoxChildren(RoleValue())) {
- if (children_.IsEmpty()) {
- // We only need to add inline textbox children if they aren't present.
- // Although some platforms (e.g. Android), load inline text boxes
- // on subtrees that may later be stale, once they are stale, the old
- // inline text boxes are cleared because SetNeedsToUpdateChildren()
- // calls ClearChildren().
- AddInlineTextBoxChildren(/*force*/ true);
- children_dirty_ = false; // Avoid adding these children twice.
+void AXNodeObject::LoadInlineTextBoxes() {
+ std::queue<AXID> work_queue;
+ work_queue.push(AXObjectID());
+
+ while (!work_queue.empty()) {
+ AXObject* work_obj = AXObjectCache().ObjectFromAXID(work_queue.front());
+ work_queue.pop();
+ if (!work_obj || !work_obj->AccessibilityIsIncludedInTree())
+ continue;
+
+ if (ui::CanHaveInlineTextBoxChildren(work_obj->RoleValue())) {
+ if (work_obj->CachedChildrenIncludingIgnored().IsEmpty()) {
+ // We only need to add inline textbox children if they aren't present.
+ // Although some platforms (e.g. Android), load inline text boxes
+ // on subtrees that may later be stale, once they are stale, the old
+ // inline text boxes are cleared because SetNeedsToUpdateChildren()
+ // calls ClearChildren().
+ work_obj->ForceAddInlineTextBoxChildren();
+ }
+ } else {
+ for (const auto& child : work_obj->ChildrenIncludingIgnored())
+ work_queue.push(child->AXObjectID());
}
- return;
}
+}
- for (const auto& child : ChildrenIncludingIgnored()) {
- // TODO(https://crbug.com/1200244) Downgrade these to DCHECKs.
- CHECK(child) << "Child has been destroyed before attempted use, parent is: "
- << ToString(true, true);
- CHECK(!child->IsDetached())
- << "Child has been detached before attempted use, parent is: "
- << ToString(true, true);
- CHECK(!IsDetached()) << "Parent was detached while attempting to load "
- "child text boxes, parent is: "
- << ToString(true, true);
- child->LoadInlineTextBoxesRecursive();
- }
+void AXNodeObject::ForceAddInlineTextBoxChildren() {
+ AddInlineTextBoxChildren(true /*force*/);
+ children_dirty_ = false; // Avoid adding these children twice.
}
void AXNodeObject::AddInlineTextBoxChildren(bool force) {
@@ -3425,7 +3598,7 @@ void AXNodeObject::AddValidationMessageChild() {
}
void AXNodeObject::AddImageMapChildren() {
- HTMLMapElement* map = GetMapForImage(GetLayoutObject());
+ HTMLMapElement* map = GetMapForImage(GetNode());
if (!map)
return;
@@ -3450,16 +3623,6 @@ void AXNodeObject::AddImageMapChildren() {
// Get the primary image, which is the first image using this map.
HTMLImageElement* primary_image_element = map->ImageElement();
- DCHECK(primary_image_element);
-#if DCHECK_IS_ON()
- // Prove that this is the same as getting the first image using this map.
- String usemap_selector = "img[usemap=\"";
- usemap_selector = usemap_selector + usemap + "\"]";
- Element* first_image_with_this_usemap =
- GetDocument()->QuerySelector(AtomicString(usemap_selector));
- DCHECK(primary_image_element) << "No match for " << usemap_selector;
- DCHECK_EQ(primary_image_element, first_image_with_this_usemap);
-#endif
// Is this the primary image for this map?
if (primary_image_element != curr_image_element) {
@@ -3469,7 +3632,7 @@ void AXNodeObject::AddImageMapChildren() {
AXObjectCache().GetOrCreate(primary_image_element);
if (ax_primary_image &&
ax_primary_image->ChildCountIncludingIgnored() == 0 &&
- Traversal<HTMLAreaElement>::FirstWithin(*map)) {
+ NodeTraversal::FirstChild(*map)) {
// The primary image still needs to add the area children, and there's at
// least one to add.
AXObjectCache().ChildrenChanged(primary_image_element);
@@ -3478,28 +3641,24 @@ void AXNodeObject::AddImageMapChildren() {
}
// Yes, this is the primary image.
- HTMLAreaElement* first_area = Traversal<HTMLAreaElement>::FirstWithin(*map);
- if (first_area) {
- // If the <area> children were part of a different parent, notify that
- // parent that its children have changed.
- if (AXObject* ax_preexisting = AXObjectCache().Get(first_area)) {
- if (AXObject* ax_previous_parent = ax_preexisting->CachedParentObject()) {
- if (ax_previous_parent != this) {
- DCHECK(ax_previous_parent->GetNode());
- AXObjectCache().ChildrenChangedWithCleanLayout(
- ax_previous_parent->GetNode(), ax_previous_parent);
- ax_previous_parent->ClearChildren();
- }
- }
- }
- // Add the area children to |this|.
- for (HTMLAreaElement& area :
- Traversal<HTMLAreaElement>::DescendantsOf(*map)) {
- // Add an <area> element for this child if it has a link and is visible.
- AddChildAndCheckIncluded(AXObjectCache().GetOrCreate(&area, this));
+ // If the children were part of a different parent, notify that parent that
+ // its children have changed.
+ if (AXObject* ax_previous_parent = AXObjectCache().GetAXImageForMap(*map)) {
+ if (ax_previous_parent != this) {
+ DCHECK(ax_previous_parent->GetNode());
+ AXObjectCache().ChildrenChangedWithCleanLayout(
+ ax_previous_parent->GetNode(), ax_previous_parent);
+ ax_previous_parent->ClearChildren();
}
}
+
+ // Add the children to |this|.
+ Node* child = LayoutTreeBuilderTraversal::FirstChild(*map);
+ while (child) {
+ AddChildAndCheckIncluded(AXObjectCache().GetOrCreate(child, this));
+ child = LayoutTreeBuilderTraversal::NextSibling(*child);
+ }
}
void AXNodeObject::AddPopupChildren() {
@@ -3598,7 +3757,7 @@ void AXNodeObject::AddAccessibleNodeChildren() {
void AXNodeObject::AddOwnedChildren() {
AXObjectVector owned_children;
- AXObjectCache().GetAriaOwnedChildren(this, owned_children);
+ AXObjectCache().ValidatedAriaOwnedChildren(this, owned_children);
DCHECK(owned_children.size() == 0 || AXRelationCache::IsValidOwner(this))
<< "This object is not allowed to use aria-owns, but it is.\n"
@@ -3741,17 +3900,17 @@ void AXNodeObject::CheckValidChild(AXObject* child) {
Node* child_node = child->GetNode();
- // An HTML image can only have area children.
- DCHECK(!IsA<HTMLImageElement>(GetNode()) || IsA<HTMLAreaElement>(child_node))
- << "Image elements can only have area children, but this one has:\n"
- << child->ToString(true, true);
-
// <area> children should only be added via AddImageMapChildren(), as the
- // children of an <image usemap>, and never alone or as children of a <map>.
- DCHECK(IsA<HTMLImageElement>(GetNode()) || !IsA<HTMLAreaElement>(child_node))
- << "Area elements can only be added by image parents: "
- << child->ToString(true, true) << " had a parent of "
- << ToString(true, true);
+ // descendants of an <image usemap> -- never alone or as children of a <map>.
+ if (IsA<HTMLAreaElement>(child_node)) {
+ AXObject* ancestor = this;
+ while (ancestor && !IsA<HTMLImageElement>(ancestor->GetNode()))
+ ancestor = ancestor->CachedParentObject();
+ DCHECK(ancestor && IsA<HTMLImageElement>(ancestor->GetNode()))
+ << "Area elements can only be added by image parents: "
+ << child->ToString(true, true) << " had a parent of "
+ << ToString(true, true);
+ }
// An option or popup for a <select size=1> must only be added via an
// overridden AddChildren() on AXMenuList/AXMenuListPopup.
@@ -3840,10 +3999,15 @@ void AXNodeObject::InsertChild(AXObject* child,
int new_index = index;
for (wtf_size_t i = 0; i < length; ++i) {
if (children[i]->IsDetached()) {
- CHECK(false) << "Cannot add a detached child: "
- << "\n* Child: " << children[i]->ToString(true, true)
- << "\n* Parent: " << child->ToString(true, true)
- << "\n* Grandparent: " << ToString(true, true);
+ // TODO(accessibility) Restore to CHECK().
+#if defined(AX_FAIL_FAST_BUILD)
+ SANITIZER_NOTREACHED()
+ << "Cannot add a detached child: "
+ << "\n* Child: " << children[i]->ToString(true, true)
+ << "\n* Parent: " << child->ToString(true, true)
+ << "\n* Grandparent: " << ToString(true, true);
+#endif
+ continue;
}
// If the child was owned, it will be added elsewhere as a direct
// child of the object owning it.
@@ -3903,9 +4067,6 @@ bool AXNodeObject::CanHaveChildren() const {
// Note: these can have AXInlineTextBox children, but when adding them, we
// also check AXObjectCache().InlineTextBoxAccessibilityEnabled().
return true;
- case ax::mojom::blink::Role::kImage:
- // Can turn into an image map if gains children later.
- return GetNode() && GetNode()->IsLink();
default:
break;
}
@@ -3916,44 +4077,10 @@ bool AXNodeObject::CanHaveChildren() const {
if (blink::EnclosingTextControl(GetNode()))
return true;
- switch (AriaRoleAttribute()) {
- case ax::mojom::blink::Role::kImage:
- return false;
- case ax::mojom::blink::Role::kCheckBox:
- case ax::mojom::blink::Role::kListBoxOption:
- case ax::mojom::blink::Role::kMath: // role="math" is flat, unlike <math>
- case ax::mojom::blink::Role::kMenuListOption:
- case ax::mojom::blink::Role::kMenuItem:
- case ax::mojom::blink::Role::kMenuItemCheckBox:
- case ax::mojom::blink::Role::kMenuItemRadio:
- case ax::mojom::blink::Role::kPopUpButton:
- case ax::mojom::blink::Role::kProgressIndicator:
- case ax::mojom::blink::Role::kRadioButton:
- case ax::mojom::blink::Role::kScrollBar:
- case ax::mojom::blink::Role::kSlider:
- case ax::mojom::blink::Role::kSplitter:
- case ax::mojom::blink::Role::kSwitch:
- case ax::mojom::blink::Role::kTab:
- case ax::mojom::blink::Role::kToggleButton: {
- // These roles have ChildrenPresentational: true in the ARIA spec.
- // We used to remove/prune all descendants of them, but that removed
- // useful content if the author didn't follow the spec perfectly, for
- // example if they wanted a complex radio button with a textfield child.
- // We are now only pruning these if there is a single text child,
- // otherwise the subtree is exposed. The ChildrenPresentational rule
- // is thus useful for authoring/verification tools but does not break
- // complex widget implementations.
- // Similarly, when content is inside a contenteditable, it does not make
- // sense to hide it, since the user can interact with it.
- // TODO(accessibility) Does it make sense to hide any of this content even
- // in non-editable content?
- Element* element = GetElement();
- return element &&
- (HasEditableStyle(*element) || !element->HasOneTextChild());
- }
- default:
- break;
- }
+ // ARIA roles with childrenPresentational:true in the ARIA spec expose
+ // their contents to the browser side, allowing platforms to decide whether
+ // to make them a leaf, ensuring that focusable content cannot be hidden,
+ // and improving stability in Blink.
return true;
}
@@ -3987,6 +4114,8 @@ Element* AXNodeObject::ActionElement() const {
return element;
Element* anchor = AnchorElement();
+ if (anchor && !anchor->IsLiveLink())
+ anchor = nullptr; // Non-interactive link target like <a name>.
Element* click_element = MouseButtonListener();
if (!anchor || (click_element && click_element->IsDescendantOf(anchor)))
return click_element;
@@ -3994,24 +4123,16 @@ Element* AXNodeObject::ActionElement() const {
}
Element* AXNodeObject::AnchorElement() const {
- Node* node = GetNode();
- if (!node)
- return nullptr;
-
- AXObjectCacheImpl& cache = AXObjectCache();
-
- // search up the DOM tree for an anchor element
- // NOTE: this assumes that any non-image with an anchor is an
- // HTMLAnchorElement
- for (; node; node = node->parentNode()) {
- if (IsA<HTMLAnchorElement>(*node))
- return To<Element>(node);
-
- if (LayoutObject* layout_object = node->GetLayoutObject()) {
- AXObject* ax_object = cache.GetOrCreate(layout_object);
- if (ax_object && ax_object->IsAnchor())
- return To<Element>(node);
+ // Search up the DOM tree for an anchor. This can be anything that has the
+ // linked state, such as an HTMLAnchorElement or role=link/doc-backlink.
+ const AXObject* current = this;
+ while (current) {
+ if (current->IsLink()) {
+ DCHECK(current->GetElement())
+ << "An AXObject* that is a link should always have an element.";
+ return current->GetElement();
}
+ current = current->ParentObject();
}
return nullptr;
@@ -4359,11 +4480,14 @@ void AXNodeObject::HandleActiveDescendantChanged() {
// Mark this node dirty. AXEventGenerator will automatically infer
// that the active descendant changed.
- AXObjectCache().MarkAXObjectDirtyWithCleanLayout(this, false);
+ AXObjectCache().MarkAXObjectDirtyWithCleanLayout(this);
}
}
AXObject* AXNodeObject::ErrorMessage() const {
+ if (GetInvalidState() == ax::mojom::blink::InvalidState::kFalse)
+ return nullptr;
+
// Check for aria-errormessage.
Element* existing_error_message =
GetAOMPropertyOrARIAAttribute(AOMRelationProperty::kErrorMessage);
@@ -4675,7 +4799,7 @@ String AXNodeObject::NativeTextAlternative(
AXObject* figcaption_ax_object = AXObjectCache().GetOrCreate(figcaption);
if (figcaption_ax_object) {
text_alternative =
- RecursiveTextAlternative(*figcaption_ax_object, false, visited);
+ RecursiveTextAlternative(*figcaption_ax_object, nullptr, visited);
if (related_objects) {
local_related_objects.push_back(
@@ -4738,7 +4862,7 @@ String AXNodeObject::NativeTextAlternative(
AXObject* caption_ax_object = AXObjectCache().GetOrCreate(caption);
if (caption_ax_object) {
text_alternative =
- RecursiveTextAlternative(*caption_ax_object, false, visited);
+ RecursiveTextAlternative(*caption_ax_object, nullptr, visited);
if (related_objects) {
local_related_objects.push_back(
MakeGarbageCollected<NameSourceRelatedObject>(caption_ax_object,
@@ -4797,7 +4921,7 @@ String AXNodeObject::NativeTextAlternative(
AXObject* title_ax_object = AXObjectCache().GetOrCreate(title);
if (title_ax_object && !visited.Contains(title_ax_object)) {
text_alternative =
- RecursiveTextAlternative(*title_ax_object, false, visited);
+ RecursiveTextAlternative(*title_ax_object, nullptr, visited);
if (related_objects) {
local_related_objects.push_back(
MakeGarbageCollected<NameSourceRelatedObject>(title_ax_object,
@@ -4832,7 +4956,7 @@ String AXNodeObject::NativeTextAlternative(
// Avoid an infinite loop
if (legend_ax_object && !visited.Contains(legend_ax_object)) {
text_alternative =
- RecursiveTextAlternative(*legend_ax_object, false, visited);
+ RecursiveTextAlternative(*legend_ax_object, nullptr, visited);
if (related_objects) {
local_related_objects.push_back(
@@ -5077,7 +5201,7 @@ String AXNodeObject::Description(
if (ruby_annotation_ax_object) {
AXObjectSet visited;
description =
- RecursiveTextAlternative(*ruby_annotation_ax_object, true, visited);
+ RecursiveTextAlternative(*ruby_annotation_ax_object, this, visited);
if (related_objects) {
related_objects->push_back(
MakeGarbageCollected<NameSourceRelatedObject>(
@@ -5110,7 +5234,7 @@ String AXNodeObject::Description(
if (caption_ax_object) {
AXObjectSet visited;
description =
- RecursiveTextAlternative(*caption_ax_object, false, visited);
+ RecursiveTextAlternative(*caption_ax_object, nullptr, visited);
if (related_objects) {
related_objects->push_back(
MakeGarbageCollected<NameSourceRelatedObject>(caption_ax_object,
@@ -5214,15 +5338,9 @@ String AXNodeObject::Placeholder(ax::mojom::blink::NameFrom name_from) const {
String AXNodeObject::Title(ax::mojom::blink::NameFrom name_from) const {
if (name_from == ax::mojom::blink::NameFrom::kTitle)
- return String();
+ return String(); // Already exposed the title in the name field.
- if (const auto* element = GetElement()) {
- String title = element->title();
- if (!title.IsEmpty())
- return title;
- }
-
- return String();
+ return GetTitle(GetElement());
}
String AXNodeObject::PlaceholderFromNativeAttribute() const {
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 48ef377b405..d77e10c00de 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
@@ -47,6 +47,9 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
public:
AXNodeObject(Node*, AXObjectCacheImpl&);
~AXNodeObject() override;
+
+ static absl::optional<String> GetCSSAltText(const Node*);
+
void Trace(Visitor*) const override;
protected:
@@ -61,7 +64,6 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
// The ARIA role, not taking the native role into account.
ax::mojom::blink::Role aria_role_;
- static absl::optional<String> GetCSSAltText(const Node*);
AXObjectInclusion ShouldIncludeBasedOnSemantics(
IgnoredReasons* = nullptr) const;
bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
@@ -96,7 +98,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
bool IsHovered() const final;
bool IsImageButton() const;
bool IsInputImage() const final;
- bool IsInPageLinkTarget() const override;
+ bool IsLineBreakingObject() const override;
bool IsLoaded() const override;
bool IsMultiSelectable() const override;
bool IsNativeImage() const final;
@@ -114,6 +116,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
AccessibilityGrabbedState IsGrabbed() const override;
AccessibilityExpanded IsExpanded() const override;
AccessibilitySelectedState IsSelected() const override;
+ bool IsSelectedFromFocusSupported() const override;
bool IsSelectedFromFocus() const override;
bool IsRequired() const final;
bool IsControl() const override;
@@ -192,7 +195,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
String GetName(ax::mojom::blink::NameFrom&,
AXObjectVector* name_objects) const override;
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::blink::NameFrom&,
AXRelatedObjectVector*,
@@ -210,7 +213,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
// Location
void GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children = nullptr) const override;
void AddChildren() override;
@@ -266,7 +269,8 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
HeapVector<Member<AXObject>>& owned_children) const;
// Inline text boxes.
- void LoadInlineTextBoxesRecursive() override;
+ void LoadInlineTextBoxes() override;
+ void ForceAddInlineTextBoxChildren() override;
//
// Layout object specific methods.
@@ -291,7 +295,6 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
String PlaceholderFromNativeAttribute() const;
String GetValueContributionToName() const;
bool UseNameFromSelectedOption() const;
- bool SelectionShouldFollowFocus() const;
virtual bool IsTabItemSelected() const;
void AddChildrenImpl();
@@ -312,6 +315,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
void CheckValidChild(AXObject* child);
#endif
+ ax::mojom::blink::TextPosition GetTextPositionFromAria() const;
ax::mojom::blink::Dropeffect ParseDropeffect(String& dropeffect) const;
static bool IsNameFromLabelElement(HTMLElement* control);
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 fa0a78a291f..ff515b92081 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -32,7 +32,9 @@
#include <ostream>
#include "base/strings/string_util.h"
#include "build/build_config.h"
+#include "skia/ext/skia_matrix_44.h"
#include "third_party/blink/public/common/input/web_menu_source_type.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
@@ -56,6 +58,8 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#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_map_element.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
@@ -64,12 +68,14 @@
#include "third_party/blink/renderer/core/html/html_table_row_element.h"
#include "third_party/blink/renderer/core/html/html_table_section_element.h"
#include "third_party/blink/renderer/core/html/html_title_element.h"
+#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/input_type_names.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/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
@@ -94,7 +100,6 @@
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_common.h"
#include "ui/accessibility/ax_node_data.h"
@@ -203,8 +208,19 @@ Node* GetParentNodeForComputeParent(Node* node) {
// Whenever null is returned from this function, then a parent cannot be
// computed, and when a parent is not provided or computed, the accessible
// object will not be created.
- // TODO(aleventhal) Remove this method / inline, if proven to be this simple.
- return LayoutTreeBuilderTraversal::Parent(*node);
+ Node* parent = LayoutTreeBuilderTraversal::Parent(*node);
+ HTMLMapElement* map_element = DynamicTo<HTMLMapElement>(parent);
+ if (!map_element)
+ return parent;
+
+ // For a <map>, return the <img> associated with it. This is necessary because
+ // the AX tree is flat, adding image map children as children of the <img>,
+ // whereas in the DOM they are actually children of the <map>.
+ // Therefore, if a node is a DOM child of a map, its AX parent is the image.
+ // This code double checks that the image actually uses the map.
+ HTMLImageElement* image_element = map_element->ImageElement();
+ return AXObject::GetMapForImage(image_element) == map_element ? image_element
+ : nullptr;
}
#if DCHECK_IS_ON()
@@ -288,6 +304,7 @@ const RoleEntry kAriaRoles[] = {
{"doc-afterword", ax::mojom::blink::Role::kDocAfterword},
{"doc-appendix", ax::mojom::blink::Role::kDocAppendix},
{"doc-backlink", ax::mojom::blink::Role::kDocBackLink},
+ // Deprecated in DPUB-ARIA 1.1. Use a listitem inside of a doc-bibliography.
{"doc-biblioentry", ax::mojom::blink::Role::kDocBiblioEntry},
{"doc-bibliography", ax::mojom::blink::Role::kDocBibliography},
{"doc-biblioref", ax::mojom::blink::Role::kDocBiblioRef},
@@ -298,6 +315,7 @@ const RoleEntry kAriaRoles[] = {
{"doc-credit", ax::mojom::blink::Role::kDocCredit},
{"doc-credits", ax::mojom::blink::Role::kDocCredits},
{"doc-dedication", ax::mojom::blink::Role::kDocDedication},
+ // Deprecated in DPUB-ARIA 1.1. Use a listitem inside of a doc-endnotes.
{"doc-endnote", ax::mojom::blink::Role::kDocEndnote},
{"doc-endnotes", ax::mojom::blink::Role::kDocEndnotes},
{"doc-epigraph", ax::mojom::blink::Role::kDocEpigraph},
@@ -474,7 +492,6 @@ int32_t ToAXMarkerType(DocumentMarker::MarkerType marker_type) {
}
// static
-bool AXObject::is_loading_inline_boxes_ = false;
unsigned AXObject::number_of_live_ax_objects_ = 0;
AXObject::AXObject(AXObjectCacheImpl& ax_object_cache)
@@ -485,7 +502,8 @@ AXObject::AXObject(AXObjectCacheImpl& ax_object_cache)
last_modification_count_(-1),
cached_is_ignored_(false),
cached_is_ignored_but_included_in_tree_(false),
- cached_is_inert_or_aria_hidden_(false),
+ cached_is_inert_(false),
+ cached_is_aria_hidden_(false),
cached_is_descendant_of_disabled_node_(false),
cached_live_region_root_(nullptr),
cached_aria_column_index_(0),
@@ -568,11 +586,6 @@ void AXObject::Detach() {
SANITIZER_CHECK(!is_adding_children_) << ToString(true, true);
#endif
- CHECK(!is_loading_inline_boxes_)
- << "Should not be attempting to detach object while in the middle of "
- "recursively loading inline text boxes: "
- << ToString(true, true);
-
// Clear any children and call DetachFromParent() on them so that
// no children are left with dangling pointers to their parent.
ClearChildren();
@@ -638,8 +651,14 @@ void AXObject::SetParent(AXObject* new_parent) const {
}
bool AXObject::IsMissingParent() const {
- if (!parent_)
- return !IsRoot();
+ if (!parent_) {
+ // Do not attempt to repair the ParentObject() of a validation message
+ // object, because hidden ones are purposely kept around without being in
+ // the tree, and without a parent, for potential later reuse.
+ // TODO(accessibility) This is ugly. Consider destroying validation message
+ // objects between uses instead. See GetOrCreateValidationMessageObject().
+ return !IsRoot() && !IsValidationMessage();
+ }
if (parent_->IsDetached())
return true;
@@ -664,25 +683,30 @@ AXObject* AXObject::ComputeParent() const {
#if defined(AX_FAIL_FAST_BUILD)
SANITIZER_CHECK(!IsDetached());
- SANITIZER_CHECK(!IsVirtualObject())
- << "A virtual object must have a parent, and cannot exist without one. "
- "The parent is set when the object is constructed.";
SANITIZER_CHECK(!IsMockObject())
<< "A mock object must have a parent, and cannot exist without one. "
"The parent is set when the object is constructed.";
- SANITIZER_CHECK(GetNode() || GetLayoutObject())
+ SANITIZER_CHECK(GetNode() || GetLayoutObject() || IsVirtualObject())
<< "Can't compute parent on AXObjects without a backing Node "
- "or LayoutObject. Objects without those must set the "
+ "LayoutObject, "
+ " or AccessibleNode. Objects without those must set the "
"parent in Init(), |this| = "
<< RoleValue();
#endif
- AXObject* ax_parent =
- AXObjectCache().IsAriaOwned(this)
- ? AXObjectCache().GetAriaOwnedParent(this)
- : ComputeNonARIAParent(AXObjectCache(), GetNode(), GetLayoutObject());
+ AXObject* ax_parent = nullptr;
+ if (AXObjectCache().IsAriaOwned(this)) {
+ ax_parent = AXObjectCache().ValidatedAriaOwner(this);
+ } else if (IsVirtualObject()) {
+ ax_parent =
+ ComputeAccessibleNodeParent(AXObjectCache(), *GetAccessibleNode());
+ }
+ if (!ax_parent) {
+ ax_parent =
+ ComputeNonARIAParent(AXObjectCache(), GetNode(), GetLayoutObject());
+ }
CHECK(!ax_parent || !ax_parent->IsDetached())
<< "Computed parent should never be detached:"
@@ -707,17 +731,68 @@ bool AXObject::CanComputeAsNaturalParent(Node* node) {
if (IsA<HTMLBRElement>(node))
return false;
- // Image map parent-child relationships (from image to area) must be retrieved
- // manually via AXImageMapLink::GetAXObjectForImageMap().
- if (IsA<HTMLMapElement>(node) || IsA<HTMLAreaElement>(node) ||
- IsA<HTMLImageElement>(node)) {
+ // Image map parent-child relationships work as follows:
+ // - The image is the parent
+ // - The DOM children of the ssociated <map> are the children
+ // This is accomplished by having GetParentNodeForComputeParent() return the
+ // <img> instead of the <map> for the map's children.
+ if (IsA<HTMLMapElement>(node))
return false;
- }
return true;
}
// static
+AXObject* AXObject::ComputeAccessibleNodeParent(
+ AXObjectCacheImpl& cache,
+ AccessibleNode& accessible_node) {
+ if (AccessibleNode* parent_accessible_node = accessible_node.GetParent()) {
+ if (AXObject* parent = cache.Get(parent_accessible_node))
+ return parent;
+
+ // If |accessible_node|'s parent is attached to a DOM element, we return the
+ // AXObject of the DOM element as the parent AXObject of |accessible_node|,
+ // since the accessible node directly attached to an element should not have
+ // its own AXObject.
+ if (Element* element = parent_accessible_node->element())
+ return cache.GetOrCreate(element);
+
+ // Compute grandparent first, since constructing parent AXObject for
+ // |accessible_node| requires grandparent to be provided.
+ AXObject* grandparent_object =
+ AXObject::ComputeAccessibleNodeParent(cache, *parent_accessible_node);
+
+ if (grandparent_object)
+ return cache.GetOrCreate(parent_accessible_node, grandparent_object);
+ }
+
+ return nullptr;
+}
+
+// static
+HTMLMapElement* AXObject::GetMapForImage(Node* image) {
+ if (!IsA<HTMLImageElement>(image))
+ return nullptr;
+
+ LayoutImage* layout_image = DynamicTo<LayoutImage>(image->GetLayoutObject());
+ if (!layout_image)
+ return nullptr;
+
+ HTMLMapElement* map_element = layout_image->ImageMap();
+ if (!map_element)
+ return nullptr;
+
+ // Don't allow images that are actually children of a map, as this could lead
+ // to an infinite loop, where the descendant image points to the ancestor map,
+ // yet the descendant image is being returned here as an ancestor.
+ if (Traversal<HTMLMapElement>::FirstAncestor(*image))
+ return nullptr;
+
+ // The image has an associated <map> and does not have a <map> ancestor.
+ return map_element;
+}
+
+// static
AXObject* AXObject::ComputeNonARIAParent(AXObjectCacheImpl& cache,
Node* current_node,
LayoutObject* current_layout_obj) {
@@ -770,14 +845,6 @@ AXObject* AXObject::ComputeNonARIAParent(AXObjectCacheImpl& cache,
}
}
- // For <area>, return the image it is a child link of.
- if (IsA<HTMLAreaElement>(current_node)) {
- if (AXObject* ax_image =
- AXImageMapLink::GetAXObjectForImageMap(cache, current_node)) {
- return ax_image;
- }
- }
-
Node* parent_node = GetParentNodeForComputeParent(current_node);
if (!parent_node) {
// This occurs when a DOM child isn't visited by LayoutTreeBuilderTraversal,
@@ -1001,17 +1068,26 @@ void AXObject::Serialize(ui::AXNodeData* node_data,
node_data->AddState(ax::mojom::blink::State::kInvisible);
if (is_visible || is_focusable) {
+ // If the author applied the ARIA "textbox" role on something that is not
+ // (currently) editable, this may be read-only rich-text object. Or it
+ // might just be bad authoring. Either way, we want to expose its
+ // descendants, especially the interactive ones which might gain focus.
+ bool is_non_atomic_textfield_root = IsARIATextField();
+
// Preserve continuity in subtrees of richly editable content by including
// richlyEditable state even if ignored.
if (IsEditable()) {
node_data->AddState(ax::mojom::blink::State::kEditable);
- if (IsEditableRoot()) {
- node_data->AddBoolAttribute(
- ax::mojom::blink::BoolAttribute::kContentEditableRoot, true);
- }
+ if (!is_non_atomic_textfield_root)
+ is_non_atomic_textfield_root = IsEditableRoot();
+
if (IsRichlyEditable())
node_data->AddState(ax::mojom::blink::State::kRichlyEditable);
}
+ if (is_non_atomic_textfield_root) {
+ node_data->AddBoolAttribute(
+ ax::mojom::blink::BoolAttribute::kNonAtomicTextFieldRoot, true);
+ }
}
if (accessibility_mode.has_mode(ui::AXMode::kHTML))
@@ -1306,6 +1382,20 @@ void AXObject::SerializeScrollAttributes(ui::AXNodeData* node_data) {
max_scroll_offset.y());
}
+const AtomicString& AXObject::GetRoleAttributeStringForObjectAttribute() {
+ // All ARIA roles are exposed in xml-roles.
+ if (const AtomicString& role_str =
+ GetAOMPropertyOrARIAAttribute(AOMStringProperty::kRole)) {
+ return role_str;
+ }
+
+ // Landmarks are the only native roles exposed in xml-roles, matching Firefox.
+ if (ui::IsLandmark(RoleValue()))
+ return ARIARoleName(RoleValue());
+
+ return g_null_atom;
+}
+
void AXObject::SerializeElementAttributes(ui::AXNodeData* node_data) {
Element* element = GetElement();
if (!element)
@@ -1317,18 +1407,13 @@ void AXObject::SerializeElementAttributes(ui::AXNodeData* node_data) {
class_name.Utf8());
}
- // ARIA role.
- if (const AtomicString& aria_role =
- GetAOMPropertyOrARIAAttribute(AOMStringProperty::kRole)) {
+ // Expose StringAttribute::kRole, which is used for the xml-roles object
+ // attribute. Prefer the raw ARIA role attribute value, otherwise, the ARIA
+ // equivalent role is used, if it is a role that is exposed in xml-roles.
+ const AtomicString& role_str = GetRoleAttributeStringForObjectAttribute();
+ if (role_str) {
TruncateAndAddStringAttribute(
- node_data, ax::mojom::blink::StringAttribute::kRole, aria_role.Utf8());
- } else {
- const AtomicString& role_str = GetEquivalentAriaRoleName(RoleValue());
- if (role_str != g_null_atom) {
- TruncateAndAddStringAttribute(node_data,
- ax::mojom::blink::StringAttribute::kRole,
- role_str.Ascii());
- }
+ node_data, ax::mojom::blink::StringAttribute::kRole, role_str.Utf8());
}
}
@@ -1479,10 +1564,11 @@ void AXObject::SerializeSparseAttributes(ui::AXNodeData* node_data) {
HashSet<QualifiedName> set_attributes;
for (const Attribute& attr : attributes) {
set_attributes.insert(attr.GetName());
- AXSparseSetterFunc callback = setter_map.at(attr.GetName());
-
- if (callback)
- callback.Run(this, node_data, attr.Value());
+ AXSparseSetterFunc callback;
+ auto it = setter_map.find(attr.GetName());
+ if (it == setter_map.end())
+ continue;
+ it->value.Run(this, node_data, attr.Value());
}
if (!element->DidAttachInternals())
@@ -1490,13 +1576,10 @@ void AXObject::SerializeSparseAttributes(ui::AXNodeData* node_data) {
const auto& internals_attributes =
element->EnsureElementInternals().GetAttributes();
for (const QualifiedName& attr : internals_attributes.Keys()) {
- if (set_attributes.Contains(attr))
+ auto it = setter_map.find(attr);
+ if (set_attributes.Contains(attr) || it == setter_map.end())
continue;
-
- AXSparseSetterFunc callback = setter_map.at(attr);
-
- if (callback)
- callback.Run(this, node_data, internals_attributes.at(attr));
+ it->value.Run(this, node_data, internals_attributes.at(attr));
}
}
@@ -1619,10 +1702,6 @@ ax::mojom::blink::Role AXObject::RoleValue() const {
return role_;
}
-bool AXObject::IsAnchor() const {
- return IsLink() && !IsNativeImage();
-}
-
bool AXObject::IsARIATextField() const {
if (IsAtomicTextField())
return false; // Native role supercedes the ARIA one.
@@ -1675,10 +1754,6 @@ bool AXObject::IsLink() const {
return ui::IsLink(RoleValue());
}
-bool AXObject::IsInPageLinkTarget() const {
- return false;
-}
-
bool AXObject::IsImageMapLink() const {
return false;
}
@@ -1774,44 +1849,6 @@ bool AXObject::IsNativeCheckboxInMixedState(const Node* node) {
return input->ShouldAppearIndeterminate();
}
-bool AXObject::IsLandmarkRelated() const {
- switch (RoleValue()) {
- case ax::mojom::blink::Role::kApplication:
- case ax::mojom::blink::Role::kArticle:
- case ax::mojom::blink::Role::kBanner:
- case ax::mojom::blink::Role::kComplementary:
- case ax::mojom::blink::Role::kContentInfo:
- case ax::mojom::blink::Role::kDocAcknowledgments:
- case ax::mojom::blink::Role::kDocAfterword:
- case ax::mojom::blink::Role::kDocAppendix:
- case ax::mojom::blink::Role::kDocBibliography:
- case ax::mojom::blink::Role::kDocChapter:
- case ax::mojom::blink::Role::kDocConclusion:
- case ax::mojom::blink::Role::kDocCredits:
- case ax::mojom::blink::Role::kDocEndnotes:
- case ax::mojom::blink::Role::kDocEpilogue:
- case ax::mojom::blink::Role::kDocErrata:
- case ax::mojom::blink::Role::kDocForeword:
- case ax::mojom::blink::Role::kDocGlossary:
- case ax::mojom::blink::Role::kDocIntroduction:
- case ax::mojom::blink::Role::kDocPart:
- case ax::mojom::blink::Role::kDocPreface:
- case ax::mojom::blink::Role::kDocPrologue:
- case ax::mojom::blink::Role::kDocToc:
- case ax::mojom::blink::Role::kFooter:
- case ax::mojom::blink::Role::kForm:
- case ax::mojom::blink::Role::kHeader:
- case ax::mojom::blink::Role::kMain:
- case ax::mojom::blink::Role::kNavigation:
- case ax::mojom::blink::Role::kRegion:
- case ax::mojom::blink::Role::kSearch:
- case ax::mojom::blink::Role::kSection:
- return true;
- default:
- return false;
- }
-}
-
bool AXObject::IsMenuRelated() const {
return ui::IsMenuRelated(RoleValue());
}
@@ -1926,7 +1963,11 @@ bool AXObject::IsHovered() const {
}
bool AXObject::IsLineBreakingObject() const {
- return false;
+ // Not all AXObjects have an associated node or layout object. They could be
+ // virtual accessibility nodes, for example.
+ //
+ // We assume that most images on the Web are inline.
+ return !IsImage() && ui::IsStructure(RoleValue());
}
bool AXObject::IsLinked() const {
@@ -1953,6 +1994,10 @@ AccessibilitySelectedState AXObject::IsSelected() const {
return kSelectedStateUndefined;
}
+bool AXObject::IsSelectedFromFocusSupported() const {
+ return false;
+}
+
bool AXObject::IsSelectedFromFocus() const {
return false;
}
@@ -2023,31 +2068,20 @@ void AXObject::UpdateCachedAttributeValuesIfNeeded(
// the entire subtree needs to recompute descendants.
// In addition, the below computations for is_ignored_but_included_in_tree is
// dependent on having the correct new cached value.
- bool is_inert_or_aria_hidden = ComputeIsInertOrAriaHidden();
- if (cached_is_inert_or_aria_hidden_ != is_inert_or_aria_hidden) {
+ bool is_inert = ComputeIsInert();
+ bool is_aria_hidden = ComputeIsAriaHidden();
+ if (cached_is_inert_ != is_inert ||
+ cached_is_aria_hidden_ != is_aria_hidden) {
// Update children if not already dirty (e.g. during Init() time.
SetNeedsToUpdateChildren();
- cached_is_inert_or_aria_hidden_ = is_inert_or_aria_hidden;
+ cached_is_inert_ = is_inert;
+ cached_is_aria_hidden_ = is_aria_hidden;
}
- cached_is_descendant_of_disabled_node_ = !!DisabledAncestor();
+ cached_is_descendant_of_disabled_node_ = ComputeIsDescendantOfDisabledNode();
bool is_ignored = ComputeAccessibilityIsIgnored();
bool is_ignored_but_included_in_tree =
is_ignored && ComputeAccessibilityIsIgnoredButIncludedInTree();
-#if DCHECK_IS_ON()
- // Ensure that display-locked text is pruned from the tree. This means that
- // they will be missed in the virtual buffer; therefore, it may be a rule
- // subject to change. Note that changing the rule would potentially cause a
- // lot of display-locked whitespace to be exposed.
- if (is_ignored && RoleValue() == ax::mojom::blink::Role::kStaticText &&
- GetNode() &&
- DisplayLockUtilities::NearestLockedExclusiveAncestor(*GetNode())) {
- DCHECK(!cached_is_ignored_but_included_in_tree_)
- << "Display locked text should not be included in the tree (subject to "
- "future rule change): "
- << ToString(true, true);
- }
-#endif
bool included_in_tree_changed = false;
// If the child's "included in tree" state changes, we will be notifying the
@@ -2122,30 +2156,31 @@ bool AXObject::AccessibilityIsIgnoredByDefault(
AXObjectInclusion AXObject::DefaultObjectInclusion(
IgnoredReasons* ignored_reasons) const {
- if (IsInertOrAriaHidden()) {
+ if (IsAriaHidden()) {
// Keep focusable elements that are aria-hidden in tree, so that they can
// still fire events such as focus and value changes.
if (!CanSetFocusAttribute()) {
if (ignored_reasons)
- ComputeIsInertOrAriaHidden(ignored_reasons);
+ ComputeIsAriaHidden(ignored_reasons);
return kIgnoreObject;
}
}
+ if (IsInert()) {
+ if (ignored_reasons)
+ ComputeIsInert(ignored_reasons);
+ return kIgnoreObject;
+ }
+
return kDefaultBehavior;
}
-bool AXObject::IsInertOrAriaHidden() const {
+bool AXObject::IsInert() const {
UpdateCachedAttributeValuesIfNeeded();
- return cached_is_inert_or_aria_hidden_;
+ return cached_is_inert_;
}
-bool AXObject::IsAriaHidden() const {
- return IsInertOrAriaHidden() && AriaHiddenRoot();
-}
-
-bool AXObject::ComputeIsInertOrAriaHidden(
- IgnoredReasons* ignored_reasons) const {
+bool AXObject::ComputeIsInert(IgnoredReasons* ignored_reasons) const {
if (GetNode()) {
if (GetNode()->IsInert()) {
if (ignored_reasons) {
@@ -2174,13 +2209,21 @@ bool AXObject::ComputeIsInertOrAriaHidden(
}
} else {
AXObject* parent = ParentObject();
- if (parent && parent->IsInertOrAriaHidden()) {
+ if (parent && parent->IsInert()) {
if (ignored_reasons)
- parent->ComputeIsInertOrAriaHidden(ignored_reasons);
+ parent->ComputeIsInert(ignored_reasons);
return true;
}
}
+ return false;
+}
+
+bool AXObject::IsAriaHidden() const {
+ UpdateCachedAttributeValuesIfNeeded();
+ return cached_is_aria_hidden_;
+}
+bool AXObject::ComputeIsAriaHidden(IgnoredReasons* ignored_reasons) const {
const AXObject* hidden_root = AriaHiddenRoot();
if (hidden_root) {
if (ignored_reasons) {
@@ -2235,7 +2278,9 @@ bool AXObject::IsBlockedByAriaModalDialog(
}
bool AXObject::IsVisible() const {
- return !IsInertOrAriaHidden() && !IsHiddenViaStyle();
+ // TODO(accessibility) Consider exposing inert objects as visible, since they
+ // are visible. It should be fine, since the objexcts are ignored.
+ return !IsAriaHidden() && !IsInert() && !IsHiddenViaStyle();
}
const AXObject* AXObject::AriaHiddenRoot() const {
@@ -2356,18 +2401,18 @@ bool AXObject::IsDescendantOfDisabledNode() const {
return cached_is_descendant_of_disabled_node_;
}
-const AXObject* AXObject::DisabledAncestor() const {
+bool AXObject::ComputeIsDescendantOfDisabledNode() const {
+ if (IsA<Document>(GetNode()))
+ return false;
+
bool disabled = false;
- if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kDisabled, disabled)) {
- if (disabled)
- return this;
- return nullptr;
- }
+ if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kDisabled, disabled))
+ return disabled;
if (AXObject* parent = ParentObject())
- return parent->DisabledAncestor();
+ return parent->IsDescendantOfDisabledNode();
- return nullptr;
+ return false;
}
bool AXObject::ComputeAccessibilityIsIgnoredButIncludedInTree() const {
@@ -2430,10 +2475,27 @@ bool AXObject::ComputeAccessibilityIsIgnoredButIncludedInTree() const {
// Custom elements and their children are included in the tree.
// <slot>s and their children are included in the tree.
- // This checks to see if this a child one of those.
+ // Also children of <label> elements, for accname calculation purposes.
+ // This checks to see whether this is a child of one of those.
if (Node* parent_node = LayoutTreeBuilderTraversal::Parent(*node)) {
if (parent_node->IsCustomElement() || IsA<HTMLSlotElement>(parent_node))
return true;
+ // <span>s are ignored because they are considered uninteresting. Do not add
+ // them back inside labels.
+ if (IsA<HTMLLabelElement>(parent_node) && !IsA<HTMLSpanElement>(node))
+ return true;
+ // Simplify AXNodeObject::AddImageMapChildren() -- it will only need to deal
+ // with included children.
+ if (IsA<HTMLMapElement>(parent_node))
+ return true;
+ }
+
+ // The ignored state of media controls can change without a layout update.
+ // Keep them in the tree at all times so that the serializer isn't
+ // accidentally working with unincluded nodes, which is not allowed.
+ if (node->IsInUserAgentShadowRoot() &&
+ IsA<HTMLMediaElement>(node->OwnerShadowHost())) {
+ return true;
}
Element* element = GetElement();
@@ -2494,6 +2556,16 @@ bool AXObject::ComputeAccessibilityIsIgnoredButIncludedInTree() const {
if (IsLineBreakingObject())
return true;
+ // Ruby annotations (i.e. <rt> elements) need to be included because they are
+ // used for calculating an accessible description for the ruby. We explicitly
+ // exclude from the tree any <rp> elements, even though they also have the
+ // kRubyAnnotation role, because such elements provide fallback content for
+ // browsers that do not support ruby. Hence, their contents should not be
+ // included in the accessible description, unless another condition in this
+ // method decides to keep them in the tree for some reason.
+ if (element->HasTagName(html_names::kRtTag))
+ return true;
+
// Preserve SVG grouping elements.
if (IsA<SVGGElement>(element))
return true;
@@ -2817,7 +2889,7 @@ bool AXObject::IsSubWidget() const {
case ax::mojom::blink::Role::kColumnHeader:
case ax::mojom::blink::Role::kRowHeader:
case ax::mojom::blink::Role::kColumn:
- case ax::mojom::blink::Role::kRow:
+ case ax::mojom::blink::Role::kRow: {
// If it has an explicit ARIA role, it's a subwidget.
//
// Reasoning:
@@ -2836,13 +2908,14 @@ bool AXObject::IsSubWidget() const {
// Otherwise it's only a subwidget if it's in a grid or treegrid,
// not in a table.
- return std::any_of(
+ AncestorsIterator ancestor = std::find_if(
UnignoredAncestorsBegin(), UnignoredAncestorsEnd(),
- [](const AXObject& ancestor) {
- return ancestor.RoleValue() == ax::mojom::blink::Role::kGrid ||
- ancestor.RoleValue() == ax::mojom::blink::Role::kTreeGrid;
- });
-
+ [](const AXObject& ancestor) { return ancestor.IsTableLikeRole(); });
+ return ancestor.current_ &&
+ (ancestor.current_->RoleValue() == ax::mojom::blink::Role::kGrid ||
+ ancestor.current_->RoleValue() ==
+ ax::mojom::blink::Role::kTreeGrid);
+ }
case ax::mojom::blink::Role::kListBoxOption:
case ax::mojom::blink::Role::kMenuListOption:
case ax::mojom::blink::Role::kTab:
@@ -2854,6 +2927,13 @@ bool AXObject::IsSubWidget() const {
}
bool AXObject::SupportsARIASetSizeAndPosInSet() const {
+ if (RoleValue() == ax::mojom::blink::Role::kRow) {
+ AncestorsIterator ancestor = std::find_if(
+ UnignoredAncestorsBegin(), UnignoredAncestorsEnd(),
+ [](const AXObject& ancestor) { return ancestor.IsTableLikeRole(); });
+ return ancestor.current_ &&
+ ancestor.current_->RoleValue() == ax::mojom::blink::Role::kTreeGrid;
+ }
return ui::IsSetLike(RoleValue()) || ui::IsItemLike(RoleValue());
}
@@ -2884,7 +2964,7 @@ String AXObject::GetName(ax::mojom::blink::NameFrom& name_from,
// Initialize |name_from|, as TextAlternative() might never set it in some
// cases.
name_from = ax::mojom::blink::NameFrom::kNone;
- String text = TextAlternative(false, false, visited, name_from,
+ String text = TextAlternative(false, nullptr, visited, name_from,
&related_objects, nullptr);
ax::mojom::blink::Role role = RoleValue();
@@ -2906,29 +2986,30 @@ String AXObject::GetName(NameSources* name_sources) const {
AXObjectSet visited;
ax::mojom::blink::NameFrom tmp_name_from;
AXRelatedObjectVector tmp_related_objects;
- String text = TextAlternative(false, false, visited, tmp_name_from,
+ String text = TextAlternative(false, nullptr, visited, tmp_name_from,
&tmp_related_objects, name_sources);
text = text.SimplifyWhiteSpace(IsHTMLSpace<UChar>);
return text;
}
-String AXObject::RecursiveTextAlternative(const AXObject& ax_obj,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited) {
+String AXObject::RecursiveTextAlternative(
+ const AXObject& ax_obj,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited) {
ax::mojom::blink::NameFrom tmp_name_from;
- return RecursiveTextAlternative(ax_obj, in_aria_labelled_by_traversal,
+ return RecursiveTextAlternative(ax_obj, aria_label_or_description_root,
visited, tmp_name_from);
}
String AXObject::RecursiveTextAlternative(
const AXObject& ax_obj,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::blink::NameFrom& name_from) {
- if (visited.Contains(&ax_obj) && !in_aria_labelled_by_traversal)
+ if (visited.Contains(&ax_obj) && !aria_label_or_description_root)
return String();
- return ax_obj.TextAlternative(true, in_aria_labelled_by_traversal, visited,
+ return ax_obj.TextAlternative(true, aria_label_or_description_root, visited,
name_from, nullptr, nullptr);
}
@@ -2937,6 +3018,7 @@ bool AXObject::ComputeIsHiddenViaStyle() const {
if (!node)
return false;
+ // content-visibility:hidden or content-visibility: auto.
if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*node)) {
// Ensure contents of head, style and script are never exposed.
// Note: an AXObject is created for <title> to gather the document's name.
@@ -2948,6 +3030,8 @@ bool AXObject::ComputeIsHiddenViaStyle() const {
DCHECK(!Traversal<HTMLScriptElement>::FirstAncestorOrSelf(*node)) << node;
// content-visibility: hidden subtrees are always hidden.
+ // content-visibility: auto subtrees are treated as visible, as we must
+ // make a guess since computed style is not available.
return DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
*node, DisplayLockActivationReason::kAccessibility);
}
@@ -3010,20 +3094,21 @@ bool AXObject::IsHiddenForTextAlternativeCalculation() const {
(!ParentObject() || !ParentObject()->IsHiddenViaStyle());
}
-String AXObject::AriaTextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::blink::NameFrom& name_from,
- AXRelatedObjectVector* related_objects,
- NameSources* name_sources,
- bool* found_text_alternative) const {
+String AXObject::AriaTextAlternative(
+ bool recursive,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::blink::NameFrom& name_from,
+ AXRelatedObjectVector* related_objects,
+ NameSources* name_sources,
+ bool* found_text_alternative) const {
String text_alternative;
bool already_visited = visited.Contains(this);
visited.insert(this);
// Step 2A from: http://www.w3.org/TR/accname-aam-1.1
// If you change this logic, update AXNodeObject::nameFromLabelElement, too.
- if (!in_aria_labelled_by_traversal &&
+ if (!aria_label_or_description_root &&
IsHiddenForTextAlternativeCalculation()) {
*found_text_alternative = true;
return String();
@@ -3031,7 +3116,7 @@ String AXObject::AriaTextAlternative(bool recursive,
// Step 2B from: http://www.w3.org/TR/accname-aam-1.1
// If you change this logic, update AXNodeObject::nameFromLabelElement, too.
- if (!in_aria_labelled_by_traversal && !already_visited) {
+ if (!aria_label_or_description_root && !already_visited) {
name_from = ax::mojom::blink::NameFrom::kRelatedElement;
// Check ARIA attributes.
@@ -3124,9 +3209,11 @@ String AXObject::TextFromElements(
AXObject* ax_element = AXObjectCache().GetOrCreate(element);
if (ax_element) {
found_valid_element = true;
-
- String result = RecursiveTextAlternative(
- *ax_element, in_aria_labelledby_traversal, visited);
+ AXObject* aria_labelled_by_node = nullptr;
+ if (in_aria_labelledby_traversal)
+ aria_labelled_by_node = ax_element;
+ String result =
+ RecursiveTextAlternative(*ax_element, aria_labelled_by_node, visited);
visited.insert(ax_element);
local_related_objects.push_back(
MakeGarbageCollected<NameSourceRelatedObject>(ax_element, result));
@@ -3171,12 +3258,12 @@ bool AXObject::ElementsFromAttribute(Element* from,
// element references set via the IDL, or computed from the content attribute.
TokenVectorFromAttribute(from, ids, attribute);
- absl::optional<HeapVector<Member<Element>>> attr_associated_elements =
+ HeapVector<Member<Element>>* attr_associated_elements =
from->GetElementArrayAttribute(attribute);
if (!attr_associated_elements)
return false;
- for (const auto& element : attr_associated_elements.value())
+ for (const auto& element : *attr_associated_elements)
elements.push_back(element);
return elements.size();
@@ -3246,12 +3333,9 @@ AccessibilityOrientation AXObject::Orientation() const {
return kAccessibilityOrientationUndefined;
}
-void AXObject::LoadInlineTextBoxes() {
- base::AutoReset<bool> reentrancy_protector(&is_loading_inline_boxes_, true);
- LoadInlineTextBoxesRecursive();
-}
+void AXObject::LoadInlineTextBoxes() {}
-void AXObject::LoadInlineTextBoxesRecursive() {}
+void AXObject::ForceAddInlineTextBoxChildren() {}
AXObject* AXObject::NextOnLine() const {
return nullptr;
@@ -3378,6 +3462,7 @@ bool AXObject::SupportsARIAExpanded() const {
case ax::mojom::blink::Role::kSwitch:
case ax::mojom::blink::Role::kTab:
case ax::mojom::blink::Role::kTextFieldWithComboBox:
+ case ax::mojom::blink::Role::kToggleButton:
case ax::mojom::blink::Role::kTreeItem:
return true;
case ax::mojom::blink::Role::kCell:
@@ -3610,6 +3695,30 @@ ax::mojom::blink::Role AXObject::DetermineAriaRoleAttribute() const {
role = ax::mojom::blink::Role::kComboBoxMenuButton;
}
+ // DPUB ARIA 1.1 deprecated doc-biblioentry and doc-endnote, but it's still
+ // possible to create these internal roles / platform mappings with a listitem
+ // (native or ARIA) inside of a doc-bibliography or doc-endnotes section.
+ if (role == ax::mojom::blink::Role::kListItem ||
+ NativeRoleIgnoringAria() == ax::mojom::blink::Role::kListItem) {
+ AXObject* ancestor = ParentObjectUnignored();
+ if (ancestor && ancestor->RoleValue() == ax::mojom::blink::Role::kList) {
+ // Go up to the root, or next list, checking to see if the list item is
+ // inside an endnote or bibliography section. If it is, remap the role.
+ // The remapping does not occur for list items multiple levels deep.
+ while (true) {
+ ancestor = ancestor->ParentObjectUnignored();
+ if (!ancestor)
+ break;
+ ax::mojom::blink::Role ancestor_role = ancestor->RoleValue();
+ if (ancestor_role == ax::mojom::blink::Role::kList)
+ break;
+ if (ancestor_role == ax::mojom::blink::Role::kDocBibliography)
+ return ax::mojom::blink::Role::kDocBiblioEntry;
+ if (ancestor_role == ax::mojom::blink::Role::kDocEndnotes)
+ return ax::mojom::blink::Role::kDocEndnote;
+ }
+ }
+ }
return role;
}
@@ -3744,12 +3853,8 @@ AXObject::AncestorsIterator AXObject::UnignoredAncestorsEnd() const {
return AXObject::AncestorsIterator();
}
-AXObject::InOrderTraversalIterator AXObject::GetInOrderTraversalIterator() {
- return InOrderTraversalIterator(*this);
-}
-
int AXObject::ChildCountIncludingIgnored() const {
- return int{ChildrenIncludingIgnored().size()};
+ return static_cast<int>(ChildrenIncludingIgnored().size());
}
AXObject* AXObject::ChildAtIncludingIgnored(int index) const {
@@ -3982,12 +4087,12 @@ AXObject* AXObject::PreviousInPostOrderIncludingIgnored(
}
int AXObject::UnignoredChildCount() const {
- return int{UnignoredChildren().size()};
+ return static_cast<int>(UnignoredChildren().size());
}
AXObject* AXObject::UnignoredChildAt(int index) const {
const AXObjectVector unignored_children = UnignoredChildren();
- if (index < 0 || index >= int{unignored_children.size()})
+ if (index < 0 || index >= static_cast<int>(unignored_children.size()))
return nullptr;
return unignored_children[index];
}
@@ -4101,12 +4206,8 @@ AXObject* AXObject::ParentObject() const {
// detached, but the children still exist. One example of this is when
// a <select size="1"> changes to <select size="2">, where the
// Role::kMenuListPopup is detached.
- if (IsMissingParent()) {
- DCHECK(!IsVirtualObject())
- << "A virtual object must have a parent, and cannot exist without one. "
- "The parent is set when the object is constructed.";
+ if (IsMissingParent())
RepairMissingParent();
- }
return parent_;
}
@@ -4196,6 +4297,8 @@ void AXObject::UpdateChildrenIfNecessary() {
}
#endif
+ UpdateCachedAttributeValuesIfNeeded();
+
AddChildren();
}
@@ -4236,10 +4339,6 @@ void AXObject::ClearChildren() const {
<< ToString(true, true);
#endif
- CHECK(!is_loading_inline_boxes_) << "Should not attempt to clear children "
- "while loading inline text boxes: "
- << ToString(true, true);
-
for (const auto& child : children_) {
// Check parent first, as the child might be several levels down if there
// are unincluded nodes in between, in which case the cached parent will
@@ -4252,7 +4351,8 @@ void AXObject::ClearChildren() const {
children_.clear();
- if (!GetNode())
+ Node* node = GetNode();
+ if (!node)
return;
if (GetDocument()->IsFlatTreeTraversalForbidden()) {
@@ -4278,14 +4378,17 @@ void AXObject::ClearChildren() const {
// TODO(crbug.com/1209216): Figure out why removing this causes a
// use-after-poison and possibly replace it with a better check.
- HTMLSlotElement* slot = DynamicTo<HTMLSlotElement>(GetNode());
+ HTMLSlotElement* slot = DynamicTo<HTMLSlotElement>(node);
if (slot && slot->SupportsAssignment())
return;
+ if (Node* map = GetMapForImage(node))
+ node = map;
+
// Detach children that were not cleared from first loop.
// These must have been an unincluded node who's parent is this,
// although it may now be included since the children were last updated.
- for (Node* child_node = LayoutTreeBuilderTraversal::FirstChild(*GetNode());
+ for (Node* child_node = LayoutTreeBuilderTraversal::FirstChild(*node);
child_node;
child_node = LayoutTreeBuilderTraversal::NextSibling(*child_node)) {
// Get the child object that should be detached from this parent.
@@ -4558,14 +4661,14 @@ int AXObject::AriaRowCount() const {
if (!HasAOMPropertyOrARIAAttribute(AOMIntProperty::kRowCount, row_count))
return 0;
- if (row_count > int{RowCount()})
+ 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)
+ if (row_count == static_cast<int>(RowCount()) || row_count != -1)
return 0;
// In the spec, -1 explicitly means an unknown number of rows.
@@ -4661,7 +4764,7 @@ int AXObject::GetDOMNodeId() const {
void AXObject::GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children) const {
*out_container = nullptr;
out_bounds_in_container = FloatRect();
@@ -4800,7 +4903,7 @@ FloatRect AXObject::LocalBoundingBoxRectForAccessibility() {
LayoutRect AXObject::GetBoundsInFrameCoordinates() const {
AXObject* container = nullptr;
FloatRect bounds;
- SkMatrix44 transform;
+ skia::Matrix44 transform;
GetRelativeBounds(&container, bounds, transform);
FloatRect computed_bounds(0, 0, bounds.Width(), bounds.Height());
while (container && container != this) {
@@ -4846,7 +4949,6 @@ bool AXObject::PerformAction(const ui::AXActionData& action_data) {
return true;
case ax::mojom::blink::Action::kSetSequentialFocusNavigationStartingPoint:
return RequestSetSequentialFocusNavigationStartingPointAction();
- break;
case ax::mojom::blink::Action::kSetValue:
return RequestSetValueAction(
WTF::String::FromUTF8(action_data.value.c_str()));
@@ -4875,6 +4977,10 @@ bool AXObject::PerformAction(const ui::AXActionData& action_data) {
case ax::mojom::blink::Action::kSetSelection:
case ax::mojom::blink::Action::kShowTooltip:
case ax::mojom::blink::Action::kSignalEndOfTest:
+ case ax::mojom::blink::Action::kResumeMedia:
+ case ax::mojom::blink::Action::kStartDuckingMedia:
+ case ax::mojom::blink::Action::kStopDuckingMedia:
+ case ax::mojom::blink::Action::kSuspendMedia:
return false;
}
}
@@ -5180,9 +5286,9 @@ ax::mojom::blink::Role AXObject::AriaRoleStringToRoleEnum(const String& value) {
value.Split(' ', role_vector);
ax::mojom::blink::Role role = ax::mojom::blink::Role::kUnknown;
for (const auto& child : role_vector) {
- role = role_map->at(child);
- if (role != ax::mojom::blink::Role::kUnknown)
- return role;
+ auto it = role_map->find(child);
+ if (it != role_map->end())
+ return it->value;
}
return role;
@@ -5195,7 +5301,6 @@ bool AXObject::SupportsNameFromContents(bool recursive) const {
switch (RoleValue()) {
// ----- NameFrom: contents -------------------------
// Get their own name from contents, or contribute to ancestors
- case ax::mojom::blink::Role::kAnchor:
case ax::mojom::blink::Role::kButton:
case ax::mojom::blink::Role::kCell:
case ax::mojom::blink::Role::kCheckBox:
@@ -5464,12 +5569,13 @@ bool AXObject::SupportsARIAReadOnly() const {
if (ui::IsCellOrTableHeader(RoleValue())) {
// For cells and row/column headers, readonly is supported within a grid.
- return std::any_of(
+ AncestorsIterator ancestor = std::find_if(
UnignoredAncestorsBegin(), UnignoredAncestorsEnd(),
- [](const AXObject& ancestor) {
- return ancestor.RoleValue() == ax::mojom::blink::Role::kGrid ||
- ancestor.RoleValue() == ax::mojom::blink::Role::kTreeGrid;
- });
+ [](const AXObject& ancestor) { return ancestor.IsTableLikeRole(); });
+ return ancestor.current_ &&
+ (ancestor.current_->RoleValue() == ax::mojom::blink::Role::kGrid ||
+ ancestor.current_->RoleValue() ==
+ ax::mojom::blink::Role::kTreeGrid);
}
return false;
@@ -5496,32 +5602,6 @@ const AtomicString& AXObject::ARIARoleName(ax::mojom::blink::Role role) {
return aria_role_name_vector->at(static_cast<wtf_size_t>(role));
}
-// static
-const AtomicString& AXObject::GetEquivalentAriaRoleName(
- const ax::mojom::blink::Role role) {
- // TODO(accessibilty) Why are some roles listed here and not others?
- switch (role) {
- case ax::mojom::blink::Role::kArticle:
- case ax::mojom::blink::Role::kBanner:
- case ax::mojom::blink::Role::kButton:
- case ax::mojom::blink::Role::kComplementary:
- case ax::mojom::blink::Role::kFigure:
- case ax::mojom::blink::Role::kFooter:
- case ax::mojom::blink::Role::kHeader:
- case ax::mojom::blink::Role::kHeading:
- case ax::mojom::blink::Role::kImage:
- case ax::mojom::blink::Role::kMain:
- case ax::mojom::blink::Role::kNavigation:
- case ax::mojom::blink::Role::kRadioButton:
- case ax::mojom::blink::Role::kRegion:
- case ax::mojom::blink::Role::kSlider:
- case ax::mojom::blink::Role::kTime:
- return ARIARoleName(role);
- default:
- return g_null_atom;
- }
-}
-
const String AXObject::InternalRoleName(ax::mojom::blink::Role role) {
std::ostringstream role_name;
role_name << role;
@@ -5656,15 +5736,15 @@ String AXObject::ToString(bool verbose, bool cached_values_only) const {
}
}
if (cached_values_only) {
- if (cached_is_inert_or_aria_hidden_ && GetNode() && !GetNode()->IsInert())
+ if (cached_is_aria_hidden_)
string_builder = string_builder + " ariaHidden";
- } else {
- if (const AXObject* aria_hidden_root = AriaHiddenRoot()) {
- string_builder = string_builder + " ariaHiddenRoot";
- if (aria_hidden_root != this) {
- string_builder =
- string_builder + GetNodeString(aria_hidden_root->GetNode());
- }
+ } else if (IsAriaHidden()) {
+ const AXObject* aria_hidden_root = AriaHiddenRoot();
+ DCHECK(aria_hidden_root);
+ string_builder = string_builder + " ariaHiddenRoot";
+ if (aria_hidden_root != this) {
+ string_builder =
+ string_builder + GetNodeString(aria_hidden_root->GetNode());
}
}
if (cached_values_only ? cached_is_hidden_via_style : IsHiddenViaStyle())
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 7de1c54b612..b8e672e2c56 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -56,7 +56,9 @@
#include "ui/accessibility/ax_enums.mojom-blink.h"
#include "ui/accessibility/ax_mode.h"
-class SkMatrix44;
+namespace skia {
+class Matrix44;
+}
namespace ui {
struct AXActionData;
@@ -174,98 +176,6 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
public:
typedef HeapVector<Member<AXObject>> AXObjectVector;
- // Iterator for doing an in-order traversal of the accessibility tree.
- //
- // Includes objects that are ignored but included in the accessibility tree in
- // the traversal.
- class MODULES_EXPORT InOrderTraversalIterator final
- : public GarbageCollected<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_->NextInPreOrderIncludingIgnored()
- : nullptr;
- return *this;
- }
-
- InOrderTraversalIterator operator++(int) {
- InOrderTraversalIterator ret = *this;
- ++*this;
- return ret;
- }
-
- InOrderTraversalIterator& operator--() {
- current_ = previous_;
- previous_ = (current_ && !current_->IsDetached())
- ? current_->PreviousInPreOrderIncludingIgnored()
- : 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(Visitor* visitor) const {
- 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.
@@ -438,7 +348,6 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Check object role or purpose.
ax::mojom::blink::Role RoleValue() const;
- bool IsAnchor() const;
// Returns true if this object is an ARIA text field, i.e. it is neither an
// <input> nor a <textarea>, but it has an ARIA role of textbox, searchbox or
@@ -454,9 +363,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
bool IsHeading() const;
bool IsImage() const;
virtual bool IsInputImage() const;
- bool IsLandmarkRelated() const;
bool IsLink() const;
- virtual bool IsInPageLinkTarget() const;
bool IsMenu() const;
bool IsMenuRelated() const;
bool IsMeter() const;
@@ -513,7 +420,11 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// aria-grabbed is deprecated in WAI-ARIA 1.1.
virtual AccessibilityGrabbedState IsGrabbed() const;
virtual bool IsHovered() const;
+
+ // Returns true if this object starts a new paragraph in the accessibility
+ // tree's text representation.
virtual bool IsLineBreakingObject() const;
+
virtual bool IsLinked() const;
virtual bool IsLoaded() const;
virtual bool IsModal() const;
@@ -521,6 +432,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
virtual bool IsOffScreen() const;
virtual bool IsRequired() const;
virtual AccessibilitySelectedState IsSelected() const;
+ virtual bool IsSelectedFromFocusSupported() const;
// Is the object selected because selection is following focus?
virtual bool IsSelectedFromFocus() const;
virtual bool IsSelectedOptionActive() const;
@@ -554,16 +466,17 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
bool AccessibilityIsIgnoredByDefault(IgnoredReasons* = nullptr) const;
virtual AXObjectInclusion DefaultObjectInclusion(
IgnoredReasons* = nullptr) const;
- bool IsInertOrAriaHidden() const;
+ bool IsInert() const;
bool IsAriaHidden() const;
const AXObject* AriaHiddenRoot() const;
- bool ComputeIsInertOrAriaHidden(IgnoredReasons* = nullptr) const;
+ bool ComputeIsInert(IgnoredReasons* = nullptr) const;
+ bool ComputeIsAriaHidden(IgnoredReasons* = nullptr) const;
bool IsBlockedByAriaModalDialog(IgnoredReasons* = nullptr) const;
bool IsDescendantOfDisabledNode() const;
bool ComputeAccessibilityIsIgnoredButIncludedInTree() const;
const AXObject* GetAtomicTextFieldAncestor(int max_levels_to_check = 3) const;
const AXObject* DatetimeAncestor(int max_levels_to_check = 3) const;
- const AXObject* DisabledAncestor() const;
+ bool ComputeIsDescendantOfDisabledNode() const;
bool LastKnownIsIgnoredValue() const;
bool LastKnownIsIgnoredButIncludedInTreeValue() const;
bool LastKnownIsIncludedInTreeValue() const;
@@ -622,7 +535,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Internal functions used by name and description, above.
typedef HeapHashSet<Member<const AXObject>> AXObjectSet;
virtual String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::blink::NameFrom& name_from,
AXRelatedObjectVector* related_objects,
@@ -675,6 +588,10 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
virtual String ImageDataUrl(const IntSize& max_size) const {
return g_null_atom;
}
+ // If this element points to another element in the same page, e.g.
+ // <a href="#foo">, this will return the AXObject for the target.
+ // The object returned should be unignored. If necessary, it will return
+ // a descendant of the actual target.
virtual AXObject* InPageLinkTarget() const { return nullptr; }
virtual AccessibilityOrientation Orientation() const;
virtual ax::mojom::blink::ListStyle GetListStyle() const {
@@ -710,8 +627,8 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Load inline text boxes for just this node, even if
// settings->inlineTextBoxAccessibilityEnabled() is false.
- void LoadInlineTextBoxes();
- virtual void LoadInlineTextBoxesRecursive();
+ virtual void LoadInlineTextBoxes();
+ virtual void ForceAddInlineTextBoxChildren();
// Walk the AXObjects on the same line.
virtual AXObject* NextOnLine() const;
@@ -903,7 +820,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// set |clips_children| to true.
virtual void GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children = nullptr) const;
FloatRect LocalBoundingBoxRectForAccessibility();
@@ -945,12 +862,6 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
AncestorsIterator UnignoredAncestorsBegin() const;
AncestorsIterator UnignoredAncestorsEnd() const;
- // Iterator for doing an in-order traversal of the accessibility tree.
- //
- // Includes nodes that are accessibility ignored but "included in tree" in the
- // traversal.
- InOrderTraversalIterator GetInOrderTraversalIterator();
-
// Returns the number of children, including children that are included in the
// accessibility tree but are accessibility ignored.
//
@@ -1133,6 +1044,9 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// used, only allows <option>/AXMenuListOption children.
static bool CanComputeAsNaturalParent(Node*);
+ // For a given image, return a <map> that's actually used for it.
+ static HTMLMapElement* GetMapForImage(Node* image);
+
// Compute the AXObject parent for the given node or layout_object.
// The layout object is only necessary if the node is null, which is the case
// only for pseudo elements. ** Does not take aria-owns into account. **
@@ -1140,6 +1054,11 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
Node* node,
LayoutObject* layout_object = nullptr);
+ // Compute parent for an AccessibleNode, which is not backed up a DOM node
+ // or layout object.
+ static AXObject* ComputeAccessibleNodeParent(AXObjectCacheImpl& cache,
+ AccessibleNode& accessible_node);
+
// Returns true if |parent_| is null and not at the root.
bool IsMissingParent() const;
@@ -1330,10 +1249,6 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Return the equivalent ARIA name for an enumerated role, or g_null_atom.
static const AtomicString& ARIARoleName(ax::mojom::blink::Role);
- // For a native role get the equivalent ARIA role for use in the xml-roles
- // object attribute.
- static const AtomicString& GetEquivalentAriaRoleName(ax::mojom::blink::Role);
-
// Return the equivalent internal role name as a string.
static const String InternalRoleName(ax::mojom::blink::Role);
@@ -1363,6 +1278,10 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// What should the role be assuming an ARIA role is not present?
virtual ax::mojom::blink::Role NativeRoleIgnoringAria() const = 0;
+ // Get the role to be used in StringAttribute::kRole, which is used in the
+ // xml-roles object attribute.
+ const AtomicString& GetRoleAttributeStringForObjectAttribute();
+
// Returns a string representation of this object.
// |cached_values_only| avoids recomputing cached values, and thus can be
// used during UpdateCachedValuesIfNecessary() without causing recursion.
@@ -1386,21 +1305,23 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Used only inside textAlternative():
static String CollapseWhitespace(const String&);
- static String RecursiveTextAlternative(const AXObject&,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited);
- static String RecursiveTextAlternative(const AXObject&,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::blink::NameFrom& name_from);
+ static String RecursiveTextAlternative(
+ const AXObject&,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited);
+ static String RecursiveTextAlternative(
+ const AXObject&,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::blink::NameFrom& name_from);
String AriaTextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::blink::NameFrom&,
AXRelatedObjectVector*,
NameSources*,
bool* found_text_alternative) const;
- String TextFromElements(bool in_aria_labelled_by_traversal,
+ String TextFromElements(bool in_aria_labelledby_traversal,
AXObjectSet& visited,
HeapVector<Member<Element>>& elements,
AXRelatedObjectVector* related_objects) const;
@@ -1462,7 +1383,8 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// AXObjectCacheImpl::ModificationCount().
mutable bool cached_is_ignored_ : 1;
mutable bool cached_is_ignored_but_included_in_tree_ : 1;
- mutable bool cached_is_inert_or_aria_hidden_ : 1;
+ mutable bool cached_is_inert_ : 1;
+ mutable bool cached_is_aria_hidden_ : 1;
mutable bool cached_is_hidden_via_style : 1;
mutable bool cached_is_descendant_of_disabled_node_ : 1;
mutable Member<AXObject> cached_live_region_root_;
@@ -1505,8 +1427,6 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
const std::string& value,
uint32_t max_len = kMaxStringAttributeLength) const;
- static bool is_loading_inline_boxes_;
-
static unsigned number_of_live_ax_objects_;
DISALLOW_COPY_AND_ASSIGN(AXObject);
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 0c7b9b8d088..9041a61ddfb 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
@@ -300,6 +300,12 @@ bool IsTextRelevantForAccessibility(const LayoutText& layout_text) {
bool IsShadowContentRelevantForAccessibility(const Node* node) {
DCHECK(node->ContainingShadowRoot());
+ // Native <img> create extra child nodes to hold alt text.
+ if (node->IsInUserAgentShadowRoot() &&
+ IsA<HTMLImageElement>(node->OwnerShadowHost())) {
+ return false;
+ }
+
// Don't use non-<option> descendants of an AXMenuList.
// If the UseAXMenuList flag is on, we use a specialized class AXMenuList
// for handling the user-agent shadow DOM exposed by a <select> element.
@@ -327,7 +333,7 @@ bool IsShadowContentRelevantForAccessibility(const Node* node) {
// Outside of AXMenuList descendants, all other non-slot user agent shadow
// nodes are relevant.
const HTMLSlotElement* slot_element = DynamicTo<HTMLSlotElement>(node);
- if (!slot_element)
+ if (!slot_element || !slot_element->SupportsAssignment())
return true;
// Slots are relevant if they have content.
@@ -387,7 +393,7 @@ bool IsLayoutObjectRelevantForAccessibility(const LayoutObject& layout_object) {
// An HTML <title> does not require an AXObject: the document's name is
// retrieved directly via the inner text.
if (IsA<HTMLTitleElement>(node))
- return node->IsSVGElement();
+ return false;
return true;
}
@@ -454,9 +460,8 @@ bool IsNodeRelevantForAccessibility(const Node* node,
if (!node->IsElementNode())
return false; // Only documents, elements and text nodes get ax objects.
- if (IsA<HTMLAreaElement>(node) &&
- !Traversal<HTMLMapElement>::FirstAncestor(*node)) {
- return false; // <area> without ancestor <map> is not relevant.
+ if (IsA<HTMLAreaElement>(node) && !IsA<HTMLMapElement>(node->parentNode())) {
+ return false; // <area> without parent <map> is not relevant.
}
if (IsA<HTMLMapElement>(node))
@@ -482,7 +487,7 @@ bool IsNodeRelevantForAccessibility(const Node* node,
// An HTML <title> does not require an AXObject: the document's name is
// retrieved directly via the inner text.
if (IsA<HTMLTitleElement>(node))
- return node->IsSVGElement();
+ return false;
// The node is either hidden or display locked:
// Do not consider <head>/<style>/<script> relevant in these cases.
@@ -549,7 +554,6 @@ AXObjectCacheImpl::AXObjectCacheImpl(Document& document,
permission_observer_receiver_(this, document.GetExecutionContext()) {
if (document_->LoadEventFinished())
AddPermissionStatusListener();
- documents_.insert(&document);
use_ax_menu_list_ = GetSettings()->GetUseAXMenuList();
}
@@ -578,20 +582,6 @@ AXObject* AXObjectCacheImpl::Root() {
return GetOrCreate(document_);
}
-void AXObjectCacheImpl::InitializePopup(Document* document) {
- if (!document || documents_.Contains(document) || !document->View())
- return;
-
- documents_.insert(document);
-}
-
-void AXObjectCacheImpl::DisposePopup(Document* document) {
- if (!documents_.Contains(document) || !document->View())
- return;
-
- documents_.erase(document);
-}
-
Node* AXObjectCacheImpl::FocusedElement() {
Node* focused_node = document_->FocusedElement();
if (!focused_node)
@@ -651,7 +641,8 @@ AXObject* AXObjectCacheImpl::Get(const LayoutObject* layout_object) {
if (!layout_object)
return nullptr;
- AXID ax_id = layout_object_mapping_.at(layout_object);
+ auto it_id = layout_object_mapping_.find(layout_object);
+ AXID ax_id = it_id != layout_object_mapping_.end() ? it_id->value : 0;
DCHECK(!HashTraits<AXID>::IsDeletedValue(ax_id));
Node* node = layout_object->GetNode();
@@ -667,7 +658,7 @@ AXObject* AXObjectCacheImpl::Get(const LayoutObject* layout_object) {
// layout object and replace it with an AXNodeObject created from the node
// instead. Do this later at a safe time.
if (node) {
- Invalidate(ax_id);
+ Invalidate(node->GetDocument(), ax_id);
} else {
// Happens if pseudo content no longer relevant.
Remove(const_cast<LayoutObject*>(layout_object));
@@ -675,7 +666,8 @@ AXObject* AXObjectCacheImpl::Get(const LayoutObject* layout_object) {
}
}
- AXObject* result = objects_.at(ax_id);
+ auto it_result = objects_.find(ax_id);
+ AXObject* result = it_result != objects_.end() ? it_result->value : nullptr;
#if DCHECK_IS_ON()
DCHECK(result) << "Had AXID for Node but no entry in objects_";
DCHECK(result->IsAXNodeObject());
@@ -687,16 +679,53 @@ AXObject* AXObjectCacheImpl::Get(const LayoutObject* layout_object) {
return result;
}
+AXObject* AXObjectCacheImpl::GetWithoutInvalidation(const Node* node) {
+ if (!node)
+ return nullptr;
+
+ LayoutObject* layout_object = node->GetLayoutObject();
+
+ AXID layout_id = 0;
+ if (layout_object) {
+ auto it = layout_object_mapping_.find(layout_object);
+ if (it != layout_object_mapping_.end())
+ layout_id = it->value;
+ }
+ DCHECK(!HashTraits<AXID>::IsDeletedValue(layout_id));
+ if (layout_id) {
+ auto it = objects_.find(layout_id);
+ if (it != objects_.end())
+ return it->value;
+ return nullptr;
+ }
+
+ auto it_node = node_object_mapping_.find(node);
+ AXID node_id = it_node != node_object_mapping_.end() ? it_node->value : 0;
+ DCHECK(!HashTraits<AXID>::IsDeletedValue(node_id));
+ if (node_id) {
+ auto it = objects_.find(node_id);
+ if (it != objects_.end())
+ return it->value;
+ }
+ return nullptr;
+}
+
AXObject* AXObjectCacheImpl::Get(const Node* node) {
if (!node)
return nullptr;
LayoutObject* layout_object = node->GetLayoutObject();
- AXID layout_id = layout_object ? layout_object_mapping_.at(layout_object) : 0;
+ AXID layout_id = 0;
+ if (layout_object) {
+ auto it = layout_object_mapping_.find(layout_object);
+ if (it != layout_object_mapping_.end())
+ layout_id = it->value;
+ }
DCHECK(!HashTraits<AXID>::IsDeletedValue(layout_id));
- AXID node_id = node_object_mapping_.at(node);
+ auto it_node = node_object_mapping_.find(node);
+ AXID node_id = it_node != node_object_mapping_.end() ? it_node->value : 0;
DCHECK(!HashTraits<AXID>::IsDeletedValue(node_id));
if (!layout_id && !node_id)
@@ -714,16 +743,16 @@ AXObject* AXObjectCacheImpl::Get(const Node* node) {
// if it already is whitespace and the text around it changes to makes it
// redundant whitespace. In this case, Invalidate(), which will remove
// objects that are no longer relevant.
- Invalidate(layout_id);
+ Invalidate(node->GetDocument(), layout_id);
} else {
// Layout object is irrelevant, but node object can still be relevant.
if (!node_id) {
DCHECK(layout_id); // One of of node_id, layout_id is non-zero.
- Invalidate(layout_id);
- return nullptr;
+ Invalidate(layout_object->GetDocument(), layout_id);
+ } else {
+ layout_object = nullptr;
+ layout_id = 0;
}
- layout_object = nullptr;
- layout_id = 0;
}
}
@@ -731,7 +760,7 @@ AXObject* AXObjectCacheImpl::Get(const Node* node) {
// Change from AXLayoutObject -> AXNodeObject.
// The node is in a display locked subtree, but we've previously put it in
// the cache with its layout object.
- Invalidate(layout_id);
+ Invalidate(layout_object->GetDocument(), layout_id);
} else if (layout_object && node_id && !layout_id && !IsDisplayLocked(node)) {
// Change from AXNodeObject -> AXLayoutObject.
// Has a layout object but no layout_id, meaning that when the AXObject was
@@ -739,11 +768,12 @@ AXObject* AXObjectCacheImpl::Get(const Node* node) {
// This can happen if an AXNodeObject is created for a node that's not laid
// out, but later something changes and it gets a layoutObject (like if it's
// reparented). It's also possible the layout object changed.
- Invalidate(node_id);
+ Invalidate(layout_object->GetDocument(), node_id);
}
if (layout_id) {
- AXObject* result = objects_.at(layout_id);
+ auto it = objects_.find(layout_id);
+ AXObject* result = it != objects_.end() ? it->value : nullptr;
#if DCHECK_IS_ON()
DCHECK(result) << "Had AXID for LayoutObject but no entry in objects_";
DCHECK(result->IsAXLayoutObject());
@@ -757,7 +787,8 @@ AXObject* AXObjectCacheImpl::Get(const Node* node) {
DCHECK(node_id);
- AXObject* result = objects_.at(node_id);
+ auto it_result = objects_.find(node_id);
+ AXObject* result = it_result != objects_.end() ? it_result->value : nullptr;
#if DCHECK_IS_ON()
DCHECK(result) << "Had AXID for Node but no entry in objects_";
DCHECK(result->IsAXNodeObject());
@@ -773,12 +804,15 @@ AXObject* AXObjectCacheImpl::Get(AbstractInlineTextBox* inline_text_box) {
if (!inline_text_box)
return nullptr;
- AXID ax_id = inline_text_box_object_mapping_.at(inline_text_box);
+ auto it_ax = inline_text_box_object_mapping_.find(inline_text_box);
+ AXID ax_id =
+ it_ax != inline_text_box_object_mapping_.end() ? it_ax->value : 0;
DCHECK(!HashTraits<AXID>::IsDeletedValue(ax_id));
if (!ax_id)
return nullptr;
- AXObject* result = objects_.at(ax_id);
+ auto it_result = objects_.find(ax_id);
+ AXObject* result = it_result != objects_.end() ? it_result->value : nullptr;
#if DCHECK_IS_ON()
DCHECK(result) << "Had AXID for inline text box but no entry in objects_";
DCHECK(result->IsAXInlineTextBox());
@@ -790,9 +824,9 @@ AXObject* AXObjectCacheImpl::Get(AbstractInlineTextBox* inline_text_box) {
return result;
}
-void AXObjectCacheImpl::Invalidate(AXID ax_id) {
- if (invalidated_ids_.insert(ax_id).is_new_entry)
- ScheduleVisualUpdate();
+void AXObjectCacheImpl::Invalidate(Document& document, AXID ax_id) {
+ if (GetInvalidatedIds(document).insert(ax_id).is_new_entry)
+ ScheduleVisualUpdate(document);
}
AXID AXObjectCacheImpl::GetAXID(Node* node) {
@@ -813,12 +847,14 @@ AXObject* AXObjectCacheImpl::Get(AccessibleNode* accessible_node) {
if (!accessible_node)
return nullptr;
- AXID ax_id = accessible_node_mapping_.at(accessible_node);
+ auto it_ax = accessible_node_mapping_.find(accessible_node);
+ AXID ax_id = it_ax != accessible_node_mapping_.end() ? it_ax->value : 0;
DCHECK(!HashTraits<AXID>::IsDeletedValue(ax_id));
if (!ax_id)
return nullptr;
- AXObject* result = objects_.at(ax_id);
+ auto it_result = objects_.find(ax_id);
+ AXObject* result = it_result != objects_.end() ? it_result->value : nullptr;
#if DCHECK_IS_ON()
DCHECK(result) << "Had AXID for accessible_node but no entry in objects_";
DCHECK(result->IsVirtualObject());
@@ -831,11 +867,23 @@ AXObject* AXObjectCacheImpl::Get(AccessibleNode* accessible_node) {
}
AXObject* AXObjectCacheImpl::GetAXImageForMap(HTMLMapElement& map) {
- HTMLElement* first_area = Traversal<HTMLAreaElement>::FirstWithin(map);
- AXObject* ax_child_area = Get(first_area);
- if (!ax_child_area)
- return nullptr;
- return ax_child_area->CachedParentObject();
+ // Find first child node of <map> that has an AXObject and return it's
+ // parent, which should be a native image.
+ Node* child = LayoutTreeBuilderTraversal::FirstChild(map);
+ while (child) {
+ if (AXObject* ax_child = Get(child)) {
+ if (AXObject* ax_image = ax_child->CachedParentObject()) {
+ DCHECK(!ax_image->IsDetached());
+ DCHECK(IsA<HTMLImageElement>(ax_image->GetNode()))
+ << "Expected image AX parent of <map>'s DOM child, got: "
+ << ax_image->GetNode() << "\n* Map's DOM child was: " << child
+ << "\n* ax_image: " << ax_image->ToString(true, true);
+ return ax_image;
+ }
+ }
+ child = LayoutTreeBuilderTraversal::NextSibling(*child);
+ }
+ return nullptr;
}
AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
@@ -947,8 +995,12 @@ bool AXObjectCacheImpl::IsRelevantPseudoElementDescendant(
ancestor = ancestor->Parent();
if (!ancestor)
return false;
- if (ancestor->IsPseudoElement())
+ if (ancestor->IsPseudoElement()) {
+ // When an ancestor is exposed using CSS alt text, descendants are pruned.
+ if (AXNodeObject::GetCSSAltText(ancestor->GetNode()))
+ return false;
return IsRelevantPseudoElement(*ancestor->GetNode());
+ }
if (!ancestor->IsAnonymous())
return false;
}
@@ -1080,20 +1132,19 @@ AXObject* AXObjectCacheImpl::CreateAndInit(Node* node,
// One of the above calls could have already created the planned object via a
// recursive call to GetOrCreate(). If so, just return that object.
- if (node_object_mapping_.at(node))
+ if (node_object_mapping_.Contains(node))
return Get(node);
AXObject* new_obj = CreateFromNode(node);
// Will crash later if we have two objects for the same node.
- DCHECK(!node_object_mapping_.at(node))
+ DCHECK(!node_object_mapping_.Contains(node))
<< "Already have an AXObject for " << node;
const AXID ax_id = AssociateAXID(new_obj, use_axid);
DCHECK(!HashTraits<AXID>::IsDeletedValue(ax_id));
node_object_mapping_.Set(node, ax_id);
new_obj->Init(parent);
- MaybeNewRelationTarget(*node, new_obj);
return new_obj;
}
@@ -1194,7 +1245,7 @@ AXObject* AXObjectCacheImpl::CreateAndInit(LayoutObject* layout_object,
// Example: parent calls Init() => ComputeAccessibilityIsIgnored() =>
// CanSetFocusAttribute() => CanBeActiveDescendant() =>
// IsARIAControlledByTextboxWithActiveDescendant() => GetOrCreate().
- if (layout_object_mapping_.at(layout_object)) {
+ if (layout_object_mapping_.Contains(layout_object)) {
AXObject* result = Get(layout_object);
DCHECK(result) << "Missing cached AXObject for " << layout_object;
return result;
@@ -1205,14 +1256,12 @@ AXObject* AXObjectCacheImpl::CreateAndInit(LayoutObject* layout_object,
DCHECK(new_obj) << "Could not create AXObject for " << layout_object;
// Will crash later if we have two objects for the same layoutObject.
- DCHECK(!layout_object_mapping_.at(layout_object))
+ DCHECK(!layout_object_mapping_.Contains(layout_object))
<< "Already have an AXObject for " << layout_object;
const AXID axid = AssociateAXID(new_obj, use_axid);
layout_object_mapping_.Set(layout_object, axid);
new_obj->Init(parent);
- if (node) // There may not be a node, e.g. for an anonymous block.
- MaybeNewRelationTarget(*node, new_obj);
return new_obj;
}
@@ -1331,7 +1380,8 @@ void AXObjectCacheImpl::Remove(AXID ax_id) {
return;
// First, fetch object to operate some cleanup functions on it.
- AXObject* obj = objects_.at(ax_id);
+ auto it = objects_.find(ax_id);
+ AXObject* obj = it != objects_.end() ? it->value : nullptr;
if (!obj)
return;
@@ -1349,48 +1399,77 @@ void AXObjectCacheImpl::Remove(AXID ax_id) {
DCHECK_GE(objects_.size(), ids_in_use_.size());
}
+// This is safe to call even if there isn't a current mapping.
void AXObjectCacheImpl::Remove(AccessibleNode* accessible_node) {
if (!accessible_node)
return;
- AXID ax_id = accessible_node_mapping_.at(accessible_node);
- accessible_node_mapping_.erase(accessible_node);
+ auto iter = accessible_node_mapping_.find(accessible_node);
+ if (iter == accessible_node_mapping_.end())
+ return;
+
+ AXID ax_id = iter->value;
+ accessible_node_mapping_.erase(iter);
Remove(ax_id);
}
+// This is safe to call even if there isn't a current mapping.
bool AXObjectCacheImpl::Remove(LayoutObject* layout_object) {
if (!layout_object)
return false;
- AXID ax_id = layout_object_mapping_.at(layout_object);
- if (!ax_id)
+ auto iter = layout_object_mapping_.find(layout_object);
+ if (iter == layout_object_mapping_.end())
return false;
- layout_object_mapping_.erase(layout_object);
+ AXID ax_id = iter->value;
+ DCHECK(ax_id);
+
+ layout_object_mapping_.erase(iter);
Remove(ax_id);
return true;
}
+// This is safe to call even if there isn't a current mapping.
void AXObjectCacheImpl::Remove(Node* node) {
if (!node)
return;
- // This is all safe even if we didn't have a mapping.
- AXID ax_id = node_object_mapping_.at(node);
- node_object_mapping_.erase(node);
+ LayoutObject* layout_object = node->GetLayoutObject();
- if (!Remove(node->GetLayoutObject()))
+ // A layout object will be used whenever it is available and relevant. It's
+ // the preferred backing object, rather than the DOM node.
+ if (Remove(node->GetLayoutObject())) {
+ DCHECK_EQ(node_object_mapping_.find(node), node_object_mapping_.end())
+ << "AXObject cannot be backed by both a layout object and node.";
+ return;
+ }
+
+ auto iter = node_object_mapping_.find(node);
+ if (iter != node_object_mapping_.end()) {
+ DCHECK(!layout_object || layout_object_mapping_.find(layout_object) ==
+ layout_object_mapping_.end())
+ << "AXObject cannot be backed by both a layout object and node.";
+ AXID ax_id = iter->value;
+ DCHECK(ax_id);
+ node_object_mapping_.erase(iter);
Remove(ax_id);
+ }
}
+// This is safe to call even if there isn't a current mapping.
void AXObjectCacheImpl::Remove(AbstractInlineTextBox* inline_text_box) {
if (!inline_text_box)
return;
- AXID ax_id = inline_text_box_object_mapping_.at(inline_text_box);
- inline_text_box_object_mapping_.erase(inline_text_box);
+ auto iter = inline_text_box_object_mapping_.find(inline_text_box);
+ if (iter == inline_text_box_object_mapping_.end())
+ return;
+
+ AXID ax_id = iter->value;
+ inline_text_box_object_mapping_.erase(iter);
Remove(ax_id);
}
@@ -1461,21 +1540,11 @@ 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::UpdateNumTreeUpdatesQueuedBeforeLayoutHistogram() {
UMA_HISTOGRAM_COUNTS_100000(
"Blink.Accessibility.NumTreeUpdatesQueuedBeforeLayout",
- tree_update_callback_queue_.size());
+ tree_update_callback_queue_main_.size() +
+ tree_update_callback_queue_popup_.size());
}
void AXObjectCacheImpl::InvalidateBoundingBoxForFixedOrStickyPosition() {
@@ -1501,11 +1570,14 @@ void AXObjectCacheImpl::DeferTreeUpdateInternal(base::OnceClosure callback,
if (!tree_update_document || !IsActive(*tree_update_document))
return;
- if (tree_update_callback_queue_.size() >= max_pending_updates_) {
+ TreeUpdateCallbackQueue& queue =
+ GetTreeUpdateCallbackQueue(*tree_update_document);
+
+ if (queue.size() >= max_pending_updates_) {
UpdateNumTreeUpdatesQueuedBeforeLayoutHistogram();
tree_updates_paused_ = true;
- tree_update_callback_queue_.clear();
+ queue.clear();
return;
}
@@ -1526,13 +1598,13 @@ void AXObjectCacheImpl::DeferTreeUpdateInternal(base::OnceClosure callback,
// << "\n* Lifecycle: " << tree_update_document->Lifecycle().ToString();
#endif
- tree_update_callback_queue_.push_back(MakeGarbageCollected<TreeUpdateParams>(
+ queue.push_back(MakeGarbageCollected<TreeUpdateParams>(
obj->GetNode(), obj->AXObjectID(), ComputeEventFrom(),
active_event_from_action_, ActiveEventIntents(), std::move(callback)));
// These events are fired during DocumentLifecycle::kInAccessibility,
// ensure there is a document lifecycle update scheduled.
- ScheduleVisualUpdate();
+ ScheduleVisualUpdate(*tree_update_document);
}
void AXObjectCacheImpl::DeferTreeUpdateInternal(base::OnceClosure callback,
@@ -1548,11 +1620,14 @@ void AXObjectCacheImpl::DeferTreeUpdateInternal(base::OnceClosure callback,
if (!IsActive(tree_update_document))
return;
- if (tree_update_callback_queue_.size() >= max_pending_updates_) {
+ TreeUpdateCallbackQueue& queue =
+ GetTreeUpdateCallbackQueue(tree_update_document);
+
+ if (queue.size() >= max_pending_updates_) {
UpdateNumTreeUpdatesQueuedBeforeLayoutHistogram();
tree_updates_paused_ = true;
- tree_update_callback_queue_.clear();
+ queue.clear();
return;
}
@@ -1568,13 +1643,13 @@ void AXObjectCacheImpl::DeferTreeUpdateInternal(base::OnceClosure callback,
<< "\n* Lifecycle: " << tree_update_document.Lifecycle().ToString();
#endif
- tree_update_callback_queue_.push_back(MakeGarbageCollected<TreeUpdateParams>(
+ queue.push_back(MakeGarbageCollected<TreeUpdateParams>(
node, 0, ComputeEventFrom(), active_event_from_action_,
ActiveEventIntents(), std::move(callback)));
// These events are fired during DocumentLifecycle::kInAccessibility,
// ensure there is a document lifecycle update scheduled.
- ScheduleVisualUpdate();
+ ScheduleVisualUpdate(tree_update_document);
}
void AXObjectCacheImpl::DeferTreeUpdate(
@@ -1684,7 +1759,7 @@ void AXObjectCacheImpl::StyleChangedWithCleanLayout(Node* node) {
if (parent && ui::IsContainerWithSelectableChildren(parent->RoleValue()))
return;
- MarkAXObjectDirtyWithCleanLayout(obj, false);
+ MarkAXObjectDirtyWithCleanLayout(obj);
}
void AXObjectCacheImpl::TextChanged(Node* node) {
@@ -1749,7 +1824,7 @@ void AXObjectCacheImpl::TextChangedWithCleanLayout(
}
}
- MarkAXObjectDirtyWithCleanLayout(obj, /*subtree=*/false);
+ MarkAXObjectDirtyWithCleanLayout(obj);
}
if (optional_node_for_relation_update)
@@ -1761,7 +1836,7 @@ void AXObjectCacheImpl::TextChangedWithCleanLayout(Node* node) {
return;
DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node));
- TextChangedWithCleanLayout(node, Get(node));
+ TextChangedWithCleanLayout(node, GetOrCreate(node));
}
void AXObjectCacheImpl::FocusableChangedWithCleanLayout(Element* element) {
@@ -1783,7 +1858,7 @@ void AXObjectCacheImpl::FocusableChangedWithCleanLayout(Element* element) {
}
// Refresh the focusable state and State::kIgnored on the exposed object.
- MarkAXObjectDirtyWithCleanLayout(obj, false);
+ MarkAXObjectDirtyWithCleanLayout(obj);
}
void AXObjectCacheImpl::DocumentTitleChanged() {
@@ -1801,41 +1876,6 @@ void AXObjectCacheImpl::UpdateCacheAfterNodeIsAttached(Node* node) {
&AXObjectCacheImpl::UpdateCacheAfterNodeIsAttachedWithCleanLayout, node);
}
-bool AXObjectCacheImpl::IsStillInTree(AXObject* obj) {
- // Return an AXObject for the node if the AXObject is still in the tree.
- // If there is a viable included parent, that means it's still in the tree.
- // Otherwise, repair missing parent, or prune the object if no viable parent
- // can be found. For example, through CSS changes, an ancestor became an
- // image, which is always a leaf; therefore, no descendants are "in the tree".
-
- if (!obj)
- return false;
-
- if (obj->IsMissingParent()) {
- // Parent is missing. Attempt to repair it with a viable recomputed parent.
- AXObject* ax_parent = obj->ComputeParent();
- if (!IsStillInTree(ax_parent)) {
- // Parent is unrepairable, meaning that this AXObject can no longer be
- // attached to the tree and is no longer viable. Prune it now.
- Remove(obj);
- return false;
- }
- obj->SetParent(ax_parent);
- return true;
- }
-
- if (!obj->LastKnownIsIncludedInTreeValue()) {
- // Current object was not included in the tree, therefore, recursively
- // keep checking up a level until a viable included parent is found.
- if (!IsStillInTree(obj->CachedParentObject())) {
- Remove(obj);
- return false;
- }
- }
-
- return true;
-}
-
void AXObjectCacheImpl::UpdateCacheAfterNodeIsAttachedWithCleanLayout(
Node* node) {
if (!node || !node->isConnected())
@@ -1965,6 +2005,17 @@ AXObject* AXObjectCacheImpl::InvalidateChildren(AXObject* obj) {
return ancestor;
}
+void AXObjectCacheImpl::SlotAssignmentWillChange(Node* node) {
+ // Use GetWithoutInvalidation(), because right before slot assignment is a
+ // dangerous time to test whether the slot must be invalidated, because
+ // this currently requires looking at the <slot> children in
+ // IsShadowContentRelevantForAccessibility(), resulting in an infinite loop
+ // as looking at the children causes slot assignment to be recalculated.
+ // TODO(accessibility) In the future this may be simplified.
+ // See crbug.com/1219311.
+ ChildrenChanged(GetWithoutInvalidation(node));
+}
+
void AXObjectCacheImpl::ChildrenChanged(Node* node) {
ChildrenChanged(Get(node));
}
@@ -2024,10 +2075,16 @@ void AXObjectCacheImpl::ChildrenChangedWithCleanLayout(Node* node) {
return;
LayoutObject* layout_object = node->GetLayoutObject();
- AXID layout_id = layout_object ? layout_object_mapping_.at(layout_object) : 0;
+ AXID layout_id = 0;
+ if (layout_object) {
+ auto it = layout_object_mapping_.find(layout_object);
+ if (it != layout_object_mapping_.end())
+ layout_id = it->value;
+ }
DCHECK(!HashTraits<AXID>::IsDeletedValue(layout_id));
- AXID node_id = node_object_mapping_.at(node);
+ auto it = node_object_mapping_.find(node);
+ AXID node_id = it != node_object_mapping_.end() ? it->value : 0;
DCHECK(!HashTraits<AXID>::IsDeletedValue(node_id));
DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node));
@@ -2048,7 +2105,7 @@ void AXObjectCacheImpl::ChildrenChangedWithCleanLayout(Node* optional_node,
#if DCHECK_IS_ON()
if (obj && optional_node) {
DCHECK_EQ(obj->GetNode(), optional_node);
- DCHECK_EQ(obj, Get(optional_node));
+ DCHECK_EQ(obj, GetWithoutInvalidation(optional_node));
}
Document* document = obj ? obj->GetDocument() : &optional_node->GetDocument();
DCHECK(document);
@@ -2057,9 +2114,12 @@ void AXObjectCacheImpl::ChildrenChangedWithCleanLayout(Node* optional_node,
#endif // DCHECK_IS_ON()
if (obj) {
- if (!IsStillInTree(obj))
- return; // Object is no longer in tree, and therefore not viable.
obj->ChildrenChangedWithCleanLayout();
+ // TODO(accessibility) Only needed for <select> size changes.
+ // This can turn into a DCHECK if the shadow DOM is used for <select>
+ // elements instead of AXMenuList* and AXListBox* classes.
+ if (obj->IsDetached())
+ return;
}
if (optional_node)
@@ -2075,6 +2135,14 @@ void AXObjectCacheImpl::ProcessDeferredAccessibilityEvents(Document& document) {
return;
}
+ if (!IsDirty())
+ return;
+
+ DCHECK(GetDocument().IsAccessibilityEnabled())
+ << "ProcessDeferredAccessibilityEvents should not perform work when "
+ "accessibility is not enabled."
+ << "\n* IsPopup? " << IsPopup(document);
+
SCOPED_UMA_HISTOGRAM_TIMER(
"Accessibility.Performance.ProcessDeferredAccessibilityEvents");
@@ -2109,7 +2177,7 @@ void AXObjectCacheImpl::ProcessDeferredAccessibilityEvents(Document& document) {
DCHECK_LE(++loop_counter, 100) << "Probable infinite loop detected.";
#endif
} while (!nodes_with_pending_children_changed_.IsEmpty() ||
- !invalidated_ids_.IsEmpty());
+ !GetInvalidatedIds(document).IsEmpty());
// Send events to RenderAccessibilityImpl, which serializes them and then
// sends the serialized events and dirty objects to the browser process.
@@ -2119,21 +2187,66 @@ void AXObjectCacheImpl::ProcessDeferredAccessibilityEvents(Document& document) {
bool AXObjectCacheImpl::IsDirty() const {
if (tree_updates_paused_)
return false;
- return tree_update_callback_queue_.size() || notifications_to_post_.size() ||
- invalidated_ids_.size();
+ return !tree_update_callback_queue_main_.IsEmpty() ||
+ !tree_update_callback_queue_popup_.IsEmpty() ||
+ !notifications_to_post_main_.IsEmpty() ||
+ !notifications_to_post_popup_.IsEmpty() ||
+ !invalidated_ids_main_.IsEmpty() ||
+ !invalidated_ids_popup_.IsEmpty() || relation_cache_->IsDirty();
}
void AXObjectCacheImpl::EmbeddingTokenChanged(HTMLFrameOwnerElement* element) {
if (!element)
return;
- MarkElementDirty(element, false);
+ MarkElementDirty(element);
}
-void AXObjectCacheImpl::ProcessInvalidatedObjects(Document& document) {
- HashSet<AXID> wrong_document_invalidated_ids;
- HashSet<AXID> old_invalidated_ids;
+bool AXObjectCacheImpl::IsPopup(Document& document) const {
+ // There are 1-2 documents per AXObjectCache: the main document and
+ // sometimes a popup document.
+ int is_popup = document != GetDocument();
+#if DCHECK_IS_ON()
+ if (is_popup) {
+ // Verify that the popup document's owner is the main document.
+ LocalFrame* frame = document.GetFrame();
+ DCHECK(frame);
+ Element* popup_owner = frame->PagePopupOwner();
+ DCHECK(popup_owner);
+ DCHECK_EQ(popup_owner->GetDocument(), GetDocument())
+ << "The popup document's owner should be in the main document.";
+ Page* main_page = GetDocument().GetPage();
+ DCHECK(main_page);
+ // TODO(accessibility) Verify that the main document's popup is |document|.
+ // PagePopupController* popup_controller =
+ // PagePopupController::From(*main_page);
+ // DCHECK(popup_controller);
+ // AXObject* popup_root_ax_object = popup_controller->RootAXObject();
+ // DCHECK(popup_root_ax_object);
+ // DCHECK_EQ(popup_root_ax_object->GetDocument(), &document)
+ // << "There can be only one active popup document.";
+ }
+#endif
+ return is_popup;
+}
+
+HashSet<AXID>& AXObjectCacheImpl::GetInvalidatedIds(Document& document) {
+ return IsPopup(document) ? invalidated_ids_popup_ : invalidated_ids_main_;
+}
+
+AXObjectCacheImpl::TreeUpdateCallbackQueue&
+AXObjectCacheImpl::GetTreeUpdateCallbackQueue(Document& document) {
+ return IsPopup(document) ? tree_update_callback_queue_popup_
+ : tree_update_callback_queue_main_;
+}
+HeapVector<Member<AXObjectCacheImpl::AXEventParams>>&
+AXObjectCacheImpl::GetNotificationsToPost(Document& document) {
+ return IsPopup(document) ? notifications_to_post_popup_
+ : notifications_to_post_main_;
+}
+
+void AXObjectCacheImpl::ProcessInvalidatedObjects(Document& document) {
// Create a new object with the same AXID as the old one.
// Currently only supported for objects with a backing node.
// Returns the new object.
@@ -2149,7 +2262,7 @@ void AXObjectCacheImpl::ProcessInvalidatedObjects(Document& document) {
if (current->GetLayoutObject()) {
layout_object_mapping_.erase(current->GetLayoutObject());
} else if (node->GetLayoutObject()) {
- DCHECK(!layout_object_mapping_.at(node->GetLayoutObject()))
+ DCHECK(!layout_object_mapping_.Contains(node->GetLayoutObject()))
<< node << " " << node->GetLayoutObject();
}
@@ -2180,77 +2293,66 @@ void AXObjectCacheImpl::ProcessInvalidatedObjects(Document& document) {
return new_object;
};
- while (!invalidated_ids_.IsEmpty()) {
- // ChildrenChanged() calls from below work may invalidate more objects. This
- // outer loop ensures all newly invalid objects are caught and refreshed
- // before the function returns.
- old_invalidated_ids.swap(invalidated_ids_);
- for (AXID ax_id : old_invalidated_ids) {
- AXObject* object = ObjectFromAXID(ax_id);
- if (!object || object->IsDetached())
- continue;
- if (object->GetDocument() != &document) {
- // Wrong document -- this AXObjectCache processes the current popup
- // document too. Keep the ID around until its document is processed.
- DCHECK(!HashTraits<AXID>::IsDeletedValue(ax_id));
- wrong_document_invalidated_ids.insert(ax_id);
- continue;
- }
+ // ChildrenChanged() calls from below work may invalidate more objects.
+ // Thereore, work from a separate list of ids, allowing new invalidated_ids.
+ HashSet<AXID> old_invalidated_ids;
+ old_invalidated_ids.swap(GetInvalidatedIds(document));
+ for (AXID ax_id : old_invalidated_ids) {
+ AXObject* object = ObjectFromAXID(ax_id);
+ if (!object || object->IsDetached())
+ continue;
+ DCHECK_EQ(object->GetDocument(), &document);
#if defined(AX_FAIL_FAST_BUILD)
- bool did_use_layout_object_traversal =
- object->ShouldUseLayoutObjectTraversalForChildren();
+ bool did_use_layout_object_traversal =
+ object->ShouldUseLayoutObjectTraversalForChildren();
#endif
- // Invalidate children on the first available non-detached parent that is
- // included in the tree. Sometimes a cached parent is detached because
- // an object was detached in the middle of the tree, and cached parents
- // are not corrected until the call to UpdateChildrenIfNecessary() below.
- AXObject* parent = object;
- while (true) {
- AXObject* candidate_parent = parent->CachedParentObject();
- if (!candidate_parent || candidate_parent->IsDetached()) {
- // The cached parent pointed to a detached AXObject. Compute a new
- // candidate parent and repair the cached parent now, so that
- // refreshing and initializing the new object can occur (a parent is
- // required).
- candidate_parent = parent->ComputeParent();
- if (candidate_parent)
- parent->SetParent(candidate_parent);
- }
+ // Invalidate children on the first available non-detached parent that is
+ // included in the tree. Sometimes a cached parent is detached because
+ // an object was detached in the middle of the tree, and cached parents
+ // are not corrected until the call to UpdateChildrenIfNecessary() below.
+ AXObject* parent = object;
+ while (true) {
+ AXObject* candidate_parent = parent->CachedParentObject();
+ if (!candidate_parent || candidate_parent->IsDetached()) {
+ // The cached parent pointed to a detached AXObject. Compute a new
+ // candidate parent and repair the cached parent now, so that
+ // refreshing and initializing the new object can occur (a parent is
+ // required).
+ candidate_parent = parent->ComputeParent();
+ if (candidate_parent)
+ parent->SetParent(candidate_parent);
+ }
- parent = candidate_parent;
- if (!parent)
- break; // No higher candidate parent found, will invalidate |parent|.
+ parent = candidate_parent;
+ if (!parent)
+ break; // No higher candidate parent found, will invalidate |parent|.
- // Queue up a ChildrenChanged() call for this parent.
- if (parent->LastKnownIsIncludedInTreeValue())
- break; // Stop here (otherwise continue to higher ancestor).
- }
+ // Queue up a ChildrenChanged() call for this parent.
+ if (parent->LastKnownIsIncludedInTreeValue())
+ break; // Stop here (otherwise continue to higher ancestor).
+ }
- if (!parent) {
- // If no parent is possible, prune from the tree.
- Remove(object);
- continue;
- }
+ if (!parent) {
+ // If no parent is possible, prune from the tree.
+ Remove(object);
+ continue;
+ }
- AXObject* new_object = refresh(object);
- MarkAXObjectDirtyWithCleanLayout(new_object, false);
+ AXObject* new_object = refresh(object);
+ MarkAXObjectDirtyWithCleanLayout(new_object);
#if defined(AX_FAIL_FAST_BUILD)
- SANITIZER_CHECK(!new_object ||
- new_object->ShouldUseLayoutObjectTraversalForChildren() ==
- did_use_layout_object_traversal)
- << "This should no longer be possible, an object only uses layout "
- "object traversal if it is part of a pseudo element subtree, "
- "and that never changes: "
- << new_object->ToString(true, true);
+ SANITIZER_CHECK(!new_object ||
+ new_object->ShouldUseLayoutObjectTraversalForChildren() ==
+ did_use_layout_object_traversal)
+ << "This should no longer be possible, an object only uses layout "
+ "object traversal if it is part of a pseudo element subtree, "
+ "and that never changes: "
+ << new_object->ToString(true, true);
#endif
- }
- old_invalidated_ids.clear();
}
- // Invalidate these objects when their document is clean.
- invalidated_ids_.swap(wrong_document_invalidated_ids);
}
void AXObjectCacheImpl::ProcessCleanLayoutCallbacks(Document& document) {
@@ -2265,7 +2367,7 @@ void AXObjectCacheImpl::ProcessCleanLayoutCallbacks(Document& document) {
UpdateNumTreeUpdatesQueuedBeforeLayoutHistogram();
TreeUpdateCallbackQueue old_tree_update_callback_queue;
- tree_update_callback_queue_.swap(old_tree_update_callback_queue);
+ GetTreeUpdateCallbackQueue(document).swap(old_tree_update_callback_queue);
nodes_with_pending_children_changed_.clear();
for (auto& tree_update : old_tree_update_callback_queue) {
@@ -2286,8 +2388,9 @@ void AXObjectCacheImpl::ProcessCleanLayoutCallbacks(Document& document) {
DCHECK(!obj->IsDetached());
if (node) {
DCHECK_EQ(node, obj->GetNode());
- DCHECK_EQ(Get(node), obj);
+ DCHECK_EQ(GetWithoutInvalidation(node), obj);
}
+ DCHECK_EQ(obj->GetDocument(), document);
}
}
#endif
@@ -2298,11 +2401,9 @@ void AXObjectCacheImpl::ProcessCleanLayoutCallbacks(Document& document) {
// main document.
Document& tree_update_document = node ? node->GetDocument() : GetDocument();
if (document != tree_update_document) {
- tree_update_callback_queue_.push_back(
- MakeGarbageCollected<TreeUpdateParams>(
- node, axid, tree_update->event_from,
- tree_update->event_from_action, tree_update->event_intents,
- std::move(callback)));
+ // Document does not match one of the supported documents for this
+ // AXObjectCacheImpl. This can happen if a node is adopted by another
+ // document. In this case, we throw the callback on the floor.
continue;
}
@@ -2314,7 +2415,7 @@ void AXObjectCacheImpl::ProcessCleanLayoutCallbacks(Document& document) {
void AXObjectCacheImpl::PostNotifications(Document& document) {
HeapVector<Member<AXEventParams>> old_notifications_to_post;
- notifications_to_post_.swap(old_notifications_to_post);
+ GetNotificationsToPost(document).swap(old_notifications_to_post);
for (auto& params : old_notifications_to_post) {
AXObject* obj = params->target;
@@ -2324,16 +2425,13 @@ void AXObjectCacheImpl::PostNotifications(Document& document) {
if (obj->IsDetached())
continue;
+ DCHECK_EQ(obj->GetDocument(), &document)
+ << "Wrong document in PostNotifications";
+
ax::mojom::blink::Event event_type = params->event_type;
ax::mojom::blink::EventFrom event_from = params->event_from;
ax::mojom::blink::Action event_from_action = params->event_from_action;
const BlinkAXEventIntentsSet& event_intents = params->event_intents;
- if (obj->GetDocument() != &document) {
- notifications_to_post_.push_back(MakeGarbageCollected<AXEventParams>(
- obj, event_type, event_from, event_from_action, event_intents));
- continue;
- }
-
FireAXEventImmediately(obj, event_type, event_from, event_from_action,
event_intents);
}
@@ -2368,44 +2466,47 @@ void AXObjectCacheImpl::PostNotification(AXObject* object,
modification_count_++;
+ Document& document = *object->GetDocument();
+
// It's possible for FireAXEventImmediately to post another notification.
// If we're still in the accessibility document lifecycle, fire these events
// immediately rather than deferring them.
- if (object->GetDocument()->Lifecycle().GetState() ==
- DocumentLifecycle::kInAccessibility) {
+ if (document.Lifecycle().GetState() == DocumentLifecycle::kInAccessibility) {
FireAXEventImmediately(object, event_type, ComputeEventFrom(),
active_event_from_action_, ActiveEventIntents());
return;
}
- notifications_to_post_.push_back(MakeGarbageCollected<AXEventParams>(
- object, event_type, ComputeEventFrom(), active_event_from_action_,
- ActiveEventIntents()));
+ GetNotificationsToPost(document).push_back(
+ MakeGarbageCollected<AXEventParams>(
+ object, event_type, ComputeEventFrom(), active_event_from_action_,
+ ActiveEventIntents()));
// These events are fired during DocumentLifecycle::kInAccessibility,
// ensure there is a visual update scheduled.
- ScheduleVisualUpdate();
+ ScheduleVisualUpdate(document);
}
-void AXObjectCacheImpl::ScheduleVisualUpdate() {
+void AXObjectCacheImpl::ScheduleVisualUpdate(Document& document) {
// Scheduling visual updates before the document is finished loading can
- // interfere with event ordering.
- if (!GetDocument().IsLoadCompleted())
+ // interfere with event ordering. In any case, at least one visual update will
+ // occur between now and when the document load is complete.
+ if (!document.IsLoadCompleted())
return;
// If there was a document change that doesn't trigger a lifecycle update on
// its own, (e.g. because it doesn't make layout dirty), make sure we run
// lifecycle phases to update the computed accessibility tree.
- LocalFrameView* frame_view = GetDocument().View();
- Page* page = GetDocument().GetPage();
+ LocalFrameView* frame_view = document.View();
+ Page* page = document.GetPage();
if (!frame_view || !page)
return;
if (!frame_view->CanThrottleRendering() &&
- (!GetDocument().GetPage()->Animator().IsServicingAnimations() ||
- GetDocument().Lifecycle().GetState() >=
+ (!document.GetPage()->Animator().IsServicingAnimations() ||
+ document.Lifecycle().GetState() >=
DocumentLifecycle::kInAccessibility)) {
- page->Animator().ScheduleVisualUpdate(GetDocument().GetFrame());
+ page->Animator().ScheduleVisualUpdate(document.GetFrame());
}
}
@@ -2469,16 +2570,16 @@ bool AXObjectCacheImpl::IsAriaOwned(const AXObject* object) const {
return relation_cache_->IsAriaOwned(object);
}
-AXObject* AXObjectCacheImpl::GetAriaOwnedParent(const AXObject* object) const {
- return relation_cache_->GetAriaOwnedParent(object);
+AXObject* AXObjectCacheImpl::ValidatedAriaOwner(const AXObject* object) const {
+ return relation_cache_->ValidatedAriaOwner(object);
}
-void AXObjectCacheImpl::GetAriaOwnedChildren(
+void AXObjectCacheImpl::ValidatedAriaOwnedChildren(
const AXObject* owner,
HeapVector<Member<AXObject>>& owned_children) {
DCHECK(GetDocument().Lifecycle().GetState() >=
DocumentLifecycle::kLayoutClean);
- relation_cache_->GetAriaOwnedChildren(owner, owned_children);
+ relation_cache_->ValidatedAriaOwnedChildren(owner, owned_children);
}
bool AXObjectCacheImpl::MayHaveHTMLLabel(const HTMLElement& elem) {
@@ -2532,7 +2633,7 @@ void AXObjectCacheImpl::LocationChanged(const LayoutObject* layout_object) {
void AXObjectCacheImpl::ImageLoaded(const LayoutObject* layout_object) {
AXObject* obj = Get(layout_object);
- MarkAXObjectDirty(obj, false);
+ MarkAXObjectDirty(obj);
}
void AXObjectCacheImpl::HandleClicked(Node* node) {
@@ -2575,7 +2676,7 @@ void AXObjectCacheImpl::HandleAriaSelectedChangedWithCleanLayout(Node* node) {
AXObject* listbox = obj->ParentObjectUnignored();
if (listbox && listbox->RoleValue() == ax::mojom::Role::kListBox) {
// Ensure listbox options are in sync as selection status may have changed
- MarkAXObjectDirty(listbox, true);
+ MarkAXSubtreeDirty(listbox);
PostNotification(listbox, ax::mojom::Event::kSelectedChildrenChanged);
}
}
@@ -2591,6 +2692,11 @@ void AXObjectCacheImpl::HandleNodeLostFocusWithCleanLayout(Node* node) {
"AXObjectCacheImpl::HandleNodeLostFocusWithCleanLayout", "id",
obj->AXObjectID());
PostNotification(obj, ax::mojom::Event::kBlur);
+
+ if (AXObject* active_descendant = obj->ActiveDescendant()) {
+ if (active_descendant->IsSelectedFromFocusSupported())
+ HandleAriaSelectedChangedWithCleanLayout(active_descendant->GetNode());
+ }
}
void AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout(Node* node) {
@@ -2614,6 +2720,11 @@ void AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout(Node* node) {
"AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout", "id",
obj->AXObjectID());
PostNotification(obj, ax::mojom::Event::kFocus);
+
+ if (AXObject* active_descendant = obj->ActiveDescendant()) {
+ if (active_descendant->IsSelectedFromFocusSupported())
+ HandleAriaSelectedChangedWithCleanLayout(active_descendant->GetNode());
+ }
}
// This might be the new target of a relation. Handle all possible cases.
@@ -2671,7 +2782,7 @@ void AXObjectCacheImpl::SectionOrRegionRoleMaybeChanged(Element* element) {
if (ax_object->RoleValue() == ax_object->DetermineAccessibilityRole())
return;
- Invalidate(ax_object->AXObjectID());
+ Invalidate(element->GetDocument(), ax_object->AXObjectID());
}
// Be as safe as possible about changes that could alter the accessibility role,
@@ -2728,9 +2839,7 @@ void AXObjectCacheImpl::HandleAriaHiddenChangedWithCleanLayout(Node* node) {
if (parent) {
// If the parent is inert or aria-hidden, then the subtree will be
// ignored and changing aria-hidden will have no effect.
- // |IsInertOrAriaHidden| returns true if the element or one of its
- // ancestors is either inert or within an aria-hidden subtree.
- if (parent->IsInertOrAriaHidden())
+ if (parent->IsInert() || parent->IsAriaHidden())
return;
// If the parent is 'display: none', then the subtree will be ignored and
// changing aria-hidden will have no effect.
@@ -2758,7 +2867,7 @@ void AXObjectCacheImpl::HandleAriaHiddenChangedWithCleanLayout(Node* node) {
// Invalidate the subtree because aria-hidden affects the
// accessibility ignored state for the entire subtree.
- MarkAXObjectDirtyWithCleanLayout(obj, /*subtree=*/true);
+ MarkAXSubtreeDirtyWithCleanLayout(obj);
ChildrenChangedWithCleanLayout(obj->CachedParentObject());
}
@@ -2799,18 +2908,20 @@ void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout(
FocusableChangedWithCleanLayout(element);
} else if (attr_name == html_names::kDisabledAttr ||
attr_name == html_names::kReadonlyAttr) {
- MarkElementDirtyWithCleanLayout(element, false);
+ MarkElementDirtyWithCleanLayout(element);
} else if (attr_name == html_names::kValueAttr) {
HandleValueChanged(element);
} else if (attr_name == html_names::kMinAttr ||
attr_name == html_names::kMaxAttr) {
- MarkElementDirtyWithCleanLayout(element, false);
+ MarkElementDirtyWithCleanLayout(element);
} else if (attr_name == html_names::kStepAttr) {
- MarkElementDirtyWithCleanLayout(element, false);
+ MarkElementDirtyWithCleanLayout(element);
} else if (attr_name == html_names::kUsemapAttr) {
HandleUseMapAttributeChangedWithCleanLayout(element);
} else if (attr_name == html_names::kNameAttr) {
HandleNameAttributeChangedWithCleanLayout(element);
+ } else if (attr_name == html_names::kControlsAttr) {
+ ChildrenChangedWithCleanLayout(element);
}
if (!attr_name.LocalName().StartsWith("aria-"))
@@ -2840,9 +2951,9 @@ void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout(
} else if (attr_name == html_names::kAriaHiddenAttr) {
HandleAriaHiddenChangedWithCleanLayout(element);
} else if (attr_name == html_names::kAriaInvalidAttr) {
- MarkElementDirtyWithCleanLayout(element, false);
+ MarkElementDirtyWithCleanLayout(element);
} else if (attr_name == html_names::kAriaErrormessageAttr) {
- MarkElementDirtyWithCleanLayout(element, false);
+ MarkElementDirtyWithCleanLayout(element);
} else if (attr_name == html_names::kAriaOwnsAttr) {
if (AXObject* obj = GetOrCreate(element))
relation_cache_->UpdateAriaOwnsWithCleanLayout(obj);
@@ -2936,6 +3047,7 @@ AXObject* AXObjectCacheImpl::ValidationMessageObjectIfInvalid(
// children, and the root doesn't already have this child.
ChildrenChanged(document_);
}
+ DCHECK_EQ(message->CachedParentObject(), Root());
return message;
}
}
@@ -2944,11 +3056,17 @@ AXObject* AXObjectCacheImpl::ValidationMessageObjectIfInvalid(
}
// No focused, invalid form control.
- RemoveValidationMessageObject();
+ if (validation_message_axid_) {
+ DeferTreeUpdate(
+ &AXObjectCacheImpl::RemoveValidationMessageObjectWithCleanLayout,
+ document_);
+ }
return nullptr;
}
-void AXObjectCacheImpl::RemoveValidationMessageObject() {
+void AXObjectCacheImpl::RemoveValidationMessageObjectWithCleanLayout(
+ Node* document) {
+ DCHECK_EQ(document, document_);
if (validation_message_axid_) {
// Remove when it becomes hidden, so that a new object is created the next
// time the message becomes visible. It's not possible to reuse the same
@@ -2984,14 +3102,12 @@ void AXObjectCacheImpl::HandleValidationMessageVisibilityChangedWithCleanLayout(
AXObject* message_ax_object = ValidationMessageObjectIfInvalid(
/* Fire children changed on root if it gains message child */ true);
- if (message_ax_object) {
- MarkAXObjectDirtyWithCleanLayout(message_ax_object,
- false); // May be invisible now.
- }
+ if (message_ax_object) // May be invisible now.
+ MarkAXObjectDirtyWithCleanLayout(message_ax_object);
// If the form control is invalid, it will now have an error message relation
// to the message container.
- MarkElementDirtyWithCleanLayout(form_control, false);
+ MarkElementDirtyWithCleanLayout(form_control);
}
void AXObjectCacheImpl::HandleEventListenerAdded(
@@ -3028,7 +3144,7 @@ void AXObjectCacheImpl::HandleEventSubscriptionChanged(
// If the |event_type| may affect the ignored state of |node|, which means
// that the parent's children may have changed.
modification_count_++;
- MarkElementDirty(&node, /*subtree=*/false);
+ MarkElementDirty(&node);
}
void AXObjectCacheImpl::LabelChangedWithCleanLayout(Element* element) {
@@ -3040,7 +3156,8 @@ void AXObjectCacheImpl::InlineTextBoxesUpdated(LayoutObject* layout_object) {
if (!InlineTextBoxAccessibilityEnabled())
return;
- AXID ax_id = layout_object_mapping_.at(layout_object);
+ auto it = layout_object_mapping_.find(layout_object);
+ AXID ax_id = it != layout_object_mapping_.end() ? it->value : 0;
DCHECK(!HashTraits<AXID>::IsDeletedValue(ax_id));
// Only update if the accessibility object already exists and it's
@@ -3086,27 +3203,6 @@ const Element* AXObjectCacheImpl::RootAXEditableElement(const Node* node) {
return result;
}
-AXObject* AXObjectCacheImpl::FirstAccessibleObjectFromNode(const Node* node) {
- if (!node)
- return nullptr;
-
- AXObject* accessible_object = GetOrCreate(node->GetLayoutObject());
- while (accessible_object &&
- !accessible_object->AccessibilityIsIncludedInTree()) {
- node = NodeTraversal::Next(*node);
-
- while (node && !node->GetLayoutObject())
- node = NodeTraversal::NextSkippingChildren(*node);
-
- if (!node)
- return nullptr;
-
- accessible_object = GetOrCreate(node->GetLayoutObject());
- }
-
- return accessible_object;
-}
-
bool AXObjectCacheImpl::NodeIsTextControl(const Node* node) {
if (!node)
return false;
@@ -3132,10 +3228,9 @@ void AXObjectCacheImpl::PostPlatformNotification(
ax::mojom::blink::EventFrom event_from,
ax::mojom::blink::Action event_from_action,
const BlinkAXEventIntentsSet& event_intents) {
- if (!document_ || !document_->View() ||
- !document_->View()->GetFrame().GetPage()) {
+ obj = GetSerializationTarget(obj);
+ if (!obj)
return;
- }
WebLocalFrameImpl* web_frame =
WebLocalFrameImpl::FromFrame(document_->AXObjectCacheOwner().GetFrame());
@@ -3155,65 +3250,87 @@ void AXObjectCacheImpl::PostPlatformNotification(
}
}
-void AXObjectCacheImpl::MarkAXObjectDirtyHelper(
- AXObject* obj,
- bool subtree,
- ax::mojom::blink::Action event_from_action) {
- if (!obj || obj->IsDetached() || !obj->GetDocument() ||
- !obj->GetDocument()->View() ||
- !obj->GetDocument()->View()->GetFrame().GetPage()) {
+void AXObjectCacheImpl::MarkAXObjectDirtyWithCleanLayoutHelper(AXObject* obj,
+ bool subtree) {
+ obj = GetSerializationTarget(obj);
+ if (!obj)
return;
- }
WebLocalFrameImpl* webframe = WebLocalFrameImpl::FromFrame(
obj->GetDocument()->AXObjectCacheOwner().GetFrame());
- if (webframe && webframe->Client()) {
- webframe->Client()->MarkWebAXObjectDirty(WebAXObject(obj), subtree,
- event_from_action);
- }
+ if (webframe && webframe->Client())
+ webframe->Client()->MarkWebAXObjectDirty(WebAXObject(obj), subtree);
+ obj->UpdateCachedAttributeValuesIfNeeded(true);
}
-void AXObjectCacheImpl::MarkAXObjectDirtyWithCleanLayout(
- AXObject* obj,
- bool subtree,
- ax::mojom::blink::Action event_from_action) {
- if (!obj)
- return;
- MarkAXObjectDirtyHelper(obj, subtree, event_from_action);
- UpdateCachedAttributeValuesWithCleanLayout(obj->GetNode(), obj);
+void AXObjectCacheImpl::MarkAXObjectDirtyWithCleanLayout(AXObject* obj) {
+ MarkAXObjectDirtyWithCleanLayoutHelper(obj, false);
}
-void AXObjectCacheImpl::UpdateCachedAttributeValuesWithCleanLayout(
- Node* node,
- AXObject* obj) {
- if (obj)
- obj->UpdateCachedAttributeValuesIfNeeded(true);
+void AXObjectCacheImpl::MarkAXSubtreeDirtyWithCleanLayout(AXObject* obj) {
+ MarkAXObjectDirtyWithCleanLayoutHelper(obj, true);
}
-void AXObjectCacheImpl::MarkAXObjectDirty(
- AXObject* obj,
- bool subtree,
- ax::mojom::blink::Action event_from_action) {
+void AXObjectCacheImpl::MarkAXObjectDirty(AXObject* obj) {
if (!obj)
return;
- MarkAXObjectDirtyHelper(obj, subtree, event_from_action);
- if (obj->GetNode()) {
- DeferTreeUpdate(
- &AXObjectCacheImpl::UpdateCachedAttributeValuesWithCleanLayout, obj);
- }
+ base::OnceClosure callback =
+ WTF::Bind(&AXObjectCacheImpl::MarkAXObjectDirtyWithCleanLayout,
+ WrapWeakPersistent(this), WrapWeakPersistent(obj));
+ DeferTreeUpdateInternal(std::move(callback), obj);
+}
+
+void AXObjectCacheImpl::MarkAXSubtreeDirty(AXObject* obj) {
+ if (!obj)
+ return;
+ base::OnceClosure callback =
+ WTF::Bind(&AXObjectCacheImpl::MarkAXSubtreeDirtyWithCleanLayout,
+ WrapWeakPersistent(this), WrapWeakPersistent(obj));
+ DeferTreeUpdateInternal(std::move(callback), obj);
}
-void AXObjectCacheImpl::MarkElementDirty(const Node* element, bool subtree) {
- // Warning, if no AXObject exists for element, nothing is marked dirty,
- // including descendant objects when subtree == true.
- MarkAXObjectDirty(Get(element), subtree);
+void AXObjectCacheImpl::MarkElementDirty(const Node* element) {
+ // Warning, if no AXObject exists for element, nothing is marked dirty.
+ MarkAXObjectDirty(Get(element));
}
-void AXObjectCacheImpl::MarkElementDirtyWithCleanLayout(const Node* element,
- bool subtree) {
- // Warning, if no AXObject exists for element, nothing is marked dirty,
- // including descendant objects when subtree == true.
- MarkAXObjectDirtyWithCleanLayout(Get(element), subtree);
+void AXObjectCacheImpl::MarkElementDirtyWithCleanLayout(const Node* element) {
+ // Warning, if no AXObject exists for element, nothing is marked dirty.
+ MarkAXObjectDirtyWithCleanLayout(Get(element));
+}
+
+AXObject* AXObjectCacheImpl::GetSerializationTarget(AXObject* obj) {
+ if (!obj || obj->IsDetached() || !obj->GetDocument() ||
+ !obj->GetDocument()->View() ||
+ !obj->GetDocument()->View()->GetFrame().GetPage()) {
+ return nullptr;
+ }
+
+ // Ensure still in tree.
+ if (obj->IsMissingParent()) {
+ // TODO(accessibility) Only needed because of <select> size changes.
+ // This should become a DCHECK(!obj->IsMissingParent()) once the shadow DOM
+ // is used for <select> elements instead of AXMenuList* and AXListBox*
+ // classes.
+ if (!RestoreParentOrPrune(obj))
+ return nullptr;
+ }
+
+ // Return included in tree object.
+ if (obj->LastKnownIsIncludedInTreeValue())
+ return obj;
+
+ return obj->ParentObjectIncludedInTree();
+}
+
+AXObject* AXObjectCacheImpl::RestoreParentOrPrune(AXObject* child) {
+ AXObject* parent = child->ComputeParent();
+ if (parent)
+ child->SetParent(parent);
+ else // If no parent is possible, the child is no longer part of the tree.
+ Remove(child);
+
+ return parent;
}
void AXObjectCacheImpl::HandleFocusedUIElementChanged(
@@ -3221,14 +3338,22 @@ void AXObjectCacheImpl::HandleFocusedUIElementChanged(
Element* new_focused_element) {
TRACE_EVENT0("accessibility",
"AXObjectCacheImpl::HandleFocusedUIElementChanged");
-#if DCHECK_IS_ON()
- // The focus can be in a different document when a popup is open.
Document& focused_doc =
new_focused_element ? new_focused_element->GetDocument() : *document_;
+
+#if DCHECK_IS_ON()
+ // The focus can be in a different document when a popup is open.
SCOPED_DISALLOW_LIFECYCLE_TRANSITION(focused_doc);
#endif // DCHECK_IS_ON()
- RemoveValidationMessageObject();
+ if (focused_doc.GetPage() && focused_doc.GetPage()->InsidePortal())
+ return; // Elements inside a portal are not considered focusable.
+
+ if (validation_message_axid_) {
+ DeferTreeUpdate(
+ &AXObjectCacheImpl::RemoveValidationMessageObjectWithCleanLayout,
+ document_);
+ }
if (!new_focused_element) {
// When focus is cleared, implicitly focus the document by sending a blur.
@@ -3265,7 +3390,7 @@ void AXObjectCacheImpl::UpdateActiveAriaModalDialog(Node* node) {
active_aria_modal_dialog_ = new_active_aria_modal;
modification_count_++;
- MarkAXObjectDirty(Root(), true);
+ MarkAXSubtreeDirty(Root());
}
AXObject* AXObjectCacheImpl::AncestorAriaModalDialog(Node* node) {
@@ -3375,7 +3500,7 @@ void AXObjectCacheImpl::HandleValueChanged(Node* node) {
void AXObjectCacheImpl::HandleUpdateActiveMenuOption(Node* menu_list) {
if (!use_ax_menu_list_) {
- MarkElementDirty(menu_list, false);
+ MarkElementDirty(menu_list);
return;
}
@@ -3400,7 +3525,7 @@ void AXObjectCacheImpl::DidShowMenuListPopup(LayoutObject* menu_list) {
void AXObjectCacheImpl::DidShowMenuListPopupWithCleanLayout(Node* menu_list) {
if (!use_ax_menu_list_) {
- MarkAXObjectDirtyWithCleanLayout(Get(menu_list), false);
+ MarkAXObjectDirtyWithCleanLayout(Get(menu_list));
return;
}
@@ -3419,7 +3544,7 @@ void AXObjectCacheImpl::DidHideMenuListPopup(LayoutObject* menu_list) {
void AXObjectCacheImpl::DidHideMenuListPopupWithCleanLayout(Node* menu_list) {
if (!use_ax_menu_list_) {
- MarkAXObjectDirtyWithCleanLayout(Get(menu_list), false);
+ MarkAXObjectDirtyWithCleanLayout(Get(menu_list));
return;
}
@@ -3477,7 +3602,7 @@ void AXObjectCacheImpl::HandleScrolledToAnchor(const Node* anchor_node) {
}
void AXObjectCacheImpl::HandleFrameRectsChanged(Document& document) {
- MarkAXObjectDirty(Get(&document), false);
+ MarkElementDirty(&document);
}
void AXObjectCacheImpl::InvalidateBoundingBox(
@@ -3491,7 +3616,7 @@ void AXObjectCacheImpl::HandleScrollPositionChanged(
SCOPED_DISALLOW_LIFECYCLE_TRANSITION(*frame_view->GetFrame().GetDocument());
InvalidateBoundingBoxForFixedOrStickyPosition();
- MarkElementDirty(document_, false);
+ MarkElementDirty(document_);
DeferTreeUpdate(&AXObjectCacheImpl::EnsurePostNotification, document_,
ax::mojom::blink::Event::kLayoutComplete);
}
@@ -3502,7 +3627,7 @@ void AXObjectCacheImpl::HandleScrollPositionChanged(
InvalidateBoundingBoxForFixedOrStickyPosition();
Node* node = GetClosestNodeForLayoutObject(layout_object);
if (node) {
- MarkElementDirty(node, false);
+ MarkElementDirty(node);
DeferTreeUpdate(&AXObjectCacheImpl::EnsurePostNotification, node,
ax::mojom::blink::Event::kLayoutComplete);
}
@@ -3625,11 +3750,12 @@ void AXObjectCacheImpl::Trace(Visitor* visitor) const {
visitor->Trace(active_aria_modal_dialog_);
visitor->Trace(objects_);
- visitor->Trace(notifications_to_post_);
+ visitor->Trace(notifications_to_post_main_);
+ visitor->Trace(notifications_to_post_popup_);
visitor->Trace(permission_service_);
visitor->Trace(permission_observer_receiver_);
- visitor->Trace(documents_);
- visitor->Trace(tree_update_callback_queue_);
+ visitor->Trace(tree_update_callback_queue_main_);
+ visitor->Trace(tree_update_callback_queue_popup_);
visitor->Trace(nodes_with_pending_children_changed_);
AXObjectCache::Trace(visitor);
}
@@ -3658,7 +3784,7 @@ void AXObjectCacheImpl::SetAutofillState(AXID id, WebAXAutofillState state) {
WebAXAutofillState previous_state = GetAutofillState(id);
if (state != previous_state) {
autofill_state_map_.Set(id, state);
- MarkAXObjectDirty(ObjectFromAXID(id), false);
+ MarkAXObjectDirty(ObjectFromAXID(id));
}
}
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 8db06a4ca38..a9d1384ff6a 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
@@ -72,7 +72,7 @@ class MODULES_EXPORT AXObjectCacheImpl
~AXObjectCacheImpl() override;
void Trace(Visitor*) const override;
- Document& GetDocument() { return *document_; }
+ Document& GetDocument() const { return *document_; }
AXObject* FocusedObject();
const ui::AXMode& GetAXMode() override;
@@ -84,17 +84,10 @@ class MODULES_EXPORT AXObjectCacheImpl
void Thaw() override { is_frozen_ = false; }
bool IsFrozen() { return is_frozen_; }
- // Register/remove popups
- void InitializePopup(Document* document) override;
- void DisposePopup(Document* document) override;
-
//
// Iterators.
//
- AXObject::InOrderTraversalIterator InOrderTraversalBegin();
- AXObject::InOrderTraversalIterator InOrderTraversalEnd();
-
void SelectionChanged(Node*) override;
void UpdateReverseRelations(const AXObject* relation_source,
const Vector<String>& target_ids);
@@ -103,6 +96,7 @@ class MODULES_EXPORT AXObjectCacheImpl
void ChildrenChanged(Node*) override;
void ChildrenChanged(const LayoutObject*) override;
void ChildrenChanged(AccessibleNode*) override;
+ void SlotAssignmentWillChange(Node*) override;
void CheckedStateChanged(Node*) override;
void ListboxOptionStateChanged(HTMLOptionElement*) override;
void ListboxSelectedChildrenChanged(HTMLSelectElement*) override;
@@ -116,7 +110,6 @@ class MODULES_EXPORT AXObjectCacheImpl
void Remove(Node*) override;
void Remove(AbstractInlineTextBox*) override;
void Remove(AXObject*); // Calls more specific Remove methods as necessary.
-
// For any ancestor that could contain the passed-in AXObject* in their cached
// children, clear their children and set needs to update children on them.
// In addition, ChildrenChanged() on an included ancestor that might contain
@@ -171,6 +164,7 @@ class MODULES_EXPORT AXObjectCacheImpl
void InlineTextBoxesUpdated(LayoutObject*) override;
void ProcessDeferredAccessibilityEvents(Document&) override;
+ // Is there work to be done when layout becomes clean?
bool IsDirty() const override;
// Called when a HTMLFrameOwnerElement (such as an iframe element) changes the
@@ -196,7 +190,10 @@ class MODULES_EXPORT AXObjectCacheImpl
void OnTouchAccessibilityHover(const IntPoint&) override;
- AXObject* ObjectFromAXID(AXID id) const { return objects_.at(id); }
+ AXObject* ObjectFromAXID(AXID id) const {
+ auto it = objects_.find(id);
+ return it != objects_.end() ? it->value : nullptr;
+ }
AXObject* Root();
// Used for objects without backing DOM nodes, layout objects, etc.
@@ -225,15 +222,24 @@ class MODULES_EXPORT AXObjectCacheImpl
AXObject* Get(const Node*);
AXObject* Get(const LayoutObject*);
+ // Get an AXObject* without any potential side effects, such as queuing up an
+ // invalidation for objects that need to be removed or replaced.
+ AXObject* GetWithoutInvalidation(const Node* node);
+
// Return true if the object is still part of the tree, meaning that ancestors
// exist or can be repaired all the way to the root.
bool IsStillInTree(AXObject*);
- AXObject* FirstAccessibleObjectFromNode(const Node*);
-
void ChildrenChangedWithCleanLayout(Node* optional_node_for_relation_update,
AXObject*);
+ void MarkAXObjectDirtyWithCleanLayout(AXObject*);
+ void MarkAXSubtreeDirtyWithCleanLayout(AXObject*);
+
+ // Set the parent of |child|. If no parent is possible, this means the child
+ // can no longer be in the AXTree, so remove the child.
+ AXObject* RestoreParentOrPrune(AXObject* child);
+
// When an object is created or its id changes, this must be called so that
// the relation cache is updated.
void MaybeNewRelationTarget(Node& node, AXObject* obj);
@@ -265,6 +271,7 @@ class MODULES_EXPORT AXObjectCacheImpl
// Counts the number of times the document has been modified. Some attribute
// values are cached as long as the modification count hasn't changed.
int ModificationCount() const { return modification_count_; }
+ void IncrementModificationCount() { ++modification_count_; }
void PostNotification(const LayoutObject*, ax::mojom::blink::Event);
// Creates object if necessary.
@@ -273,11 +280,6 @@ class MODULES_EXPORT AXObjectCacheImpl
// TODO(accessibility) Find out if we can merge with EnsurePostNotification().
void PostNotification(Node*, ax::mojom::blink::Event);
void PostNotification(AXObject*, ax::mojom::blink::Event);
- void MarkAXObjectDirtyWithCleanLayout(
- AXObject*,
- bool subtree,
- ax::mojom::blink::Action event_from_action =
- ax::mojom::blink::Action::kNone);
//
// Aria-owns support.
@@ -287,13 +289,16 @@ class MODULES_EXPORT AXObjectCacheImpl
// aria-owns.
bool IsAriaOwned(const AXObject*) const;
- // Returns the parent of the given object due to aria-owns.
- AXObject* GetAriaOwnedParent(const AXObject*) const;
+ // Returns the parent of the given object due to aria-owns, if valid.
+ AXObject* ValidatedAriaOwner(const AXObject*) const;
// Given an object that has an aria-owns attribute, return the validated
// set of aria-owned children.
- void GetAriaOwnedChildren(const AXObject* owner,
- HeapVector<Member<AXObject>>& owned_children);
+ void ValidatedAriaOwnedChildren(const AXObject* owner,
+ HeapVector<Member<AXObject>>& owned_children);
+
+ // Given a <map> element, get the image currently associated with it, if any.
+ AXObject* GetAXImageForMap(HTMLMapElement& map);
// Adds |object| to |fixed_or_sticky_node_ids_| if it has a fixed or sticky
// position.
@@ -375,16 +380,13 @@ class MODULES_EXPORT AXObjectCacheImpl
// Will result in a new object with the same AXID, and will also call
// ChildrenChanged() on the parent of invalidated objects. Automatically
// de-dupes extra object refreshes and ChildrenChanged() calls.
- void Invalidate(AXID);
+ void Invalidate(Document&, AXID);
AXObject* CreateFromRenderer(LayoutObject*);
AXObject* CreateFromNode(Node*);
AXObject* CreateFromInlineTextBox(AbstractInlineTextBox*);
void Remove(AXID);
- // Given a <map> element, get the image currently associated with it, if any.
- AXObject* GetAXImageForMap(HTMLMapElement& map);
-
private:
struct AXEventParams final : public GarbageCollected<AXEventParams> {
AXEventParams(AXObject* target,
@@ -434,20 +436,22 @@ class MODULES_EXPORT AXObjectCacheImpl
void Trace(Visitor* visitor) const { visitor->Trace(node); }
};
+ typedef HeapVector<Member<TreeUpdateParams>> TreeUpdateCallbackQueue;
ax::mojom::blink::EventFrom ComputeEventFrom();
- void UpdateCachedAttributeValuesWithCleanLayout(Node* node, AXObject* obj);
- void MarkAXObjectDirtyHelper(AXObject* obj,
- bool subtree,
- ax::mojom::blink::Action event_from_action);
- void MarkAXObjectDirty(AXObject*,
- bool subtree,
- ax::mojom::blink::Action event_from_action =
- ax::mojom::blink::Action::kNone);
- void MarkElementDirty(const Node*, bool subtree);
- void MarkAXSubtreeDirtyWithCleanLayout(AXObject*);
- void MarkElementDirtyWithCleanLayout(const Node*, bool subtree);
+ void MarkAXObjectDirtyWithCleanLayoutHelper(AXObject* obj, bool subtree);
+ void MarkAXObjectDirty(AXObject*);
+ void MarkAXSubtreeDirty(AXObject*);
+ void MarkElementDirty(const Node*);
+ void MarkElementDirtyWithCleanLayout(const Node*);
+
+ // Given an object to mark dirty or fire an event on, return an object
+ // included in the tree that can be used with the serializer, or null if there
+ // is no relevant object to use. Objects that are not included in the tree,
+ // and have no ancestor object included in the tree, are pruned from the tree,
+ // in which case there is nothing to be serialized.
+ AXObject* GetSerializationTarget(AXObject* obj);
// Helper that clears children up to the first included ancestor and returns
// the ancestor if a children changed notification should be fired on it.
@@ -484,7 +488,8 @@ class MODULES_EXPORT AXObjectCacheImpl
bool has_been_disposed_ = false;
#endif
- HeapVector<Member<AXEventParams>> notifications_to_post_;
+ HeapVector<Member<AXEventParams>> notifications_to_post_main_;
+ HeapVector<Member<AXEventParams>> notifications_to_post_popup_;
// Call the queued callback methods that do processing which must occur when
// layout is clean. These callbacks are stored in tree_update_callback_queue_,
@@ -534,7 +539,7 @@ class MODULES_EXPORT AXObjectCacheImpl
// Object for HTML validation alerts. Created at most once per object cache.
AXObject* GetOrCreateValidationMessageObject();
- void RemoveValidationMessageObject();
+ void RemoveValidationMessageObjectWithCleanLayout(Node* document);
// Enqueue a callback to the given method to be run after layout is
// complete.
@@ -584,7 +589,7 @@ class MODULES_EXPORT AXObjectCacheImpl
// setting enabled, or where there is no active ancestral aria-modal dialog.
AXObject* AncestorAriaModalDialog(Node* node);
- void ScheduleVisualUpdate();
+ void ScheduleVisualUpdate(Document& document);
void FireTreeUpdatedEventImmediately(
Document& document,
ax::mojom::blink::EventFrom event_from,
@@ -609,6 +614,20 @@ class MODULES_EXPORT AXObjectCacheImpl
// GetAllObjectsWithChangedBounds.
void InvalidateBoundingBoxForFixedOrStickyPosition();
+ // Return true if this is the popup document. There can only be one popup
+ // document at a time. If it is not the popup document, it's the main
+ // document stored in |document_|.
+ bool IsPopup(Document& document) const;
+
+ // Get the invalidated objects for the passed-in document.
+ HashSet<AXID>& GetInvalidatedIds(Document& document);
+
+ // Get the queued tree update callbacks for the passed-in document
+ TreeUpdateCallbackQueue& GetTreeUpdateCallbackQueue(Document& document);
+
+ // Get the event notifications to post for the passed-in document.
+ HeapVector<Member<AXEventParams>>& GetNotificationsToPost(Document& document);
+
// Whether the user has granted permission for the user to install event
// listeners for accessibility events using the AOM.
mojom::PermissionStatus accessibility_event_permission_;
@@ -618,12 +637,10 @@ class MODULES_EXPORT AXObjectCacheImpl
HeapMojoReceiver<mojom::blink::PermissionObserver, AXObjectCacheImpl>
permission_observer_receiver_;
- // The main document, plus any page popups.
- HeapHashSet<WeakMember<Document>> documents_;
-
// Queued callbacks.
- typedef HeapVector<Member<TreeUpdateParams>> TreeUpdateCallbackQueue;
- TreeUpdateCallbackQueue tree_update_callback_queue_;
+ TreeUpdateCallbackQueue tree_update_callback_queue_main_;
+ TreeUpdateCallbackQueue tree_update_callback_queue_popup_;
+
HeapHashSet<WeakMember<Node>> nodes_with_pending_children_changed_;
// If tree_update_callback_queue_ gets improbably large, stop
@@ -657,7 +674,8 @@ class MODULES_EXPORT AXObjectCacheImpl
bool is_frozen_ = false; // Used with Freeze(), Thaw() and IsFrozen() above.
// Set of ID's of current AXObjects that need to be destroyed and recreated.
- HashSet<AXID> invalidated_ids_;
+ HashSet<AXID> invalidated_ids_main_;
+ HashSet<AXID> invalidated_ids_popup_;
// If false, exposes the internal accessibility tree of a select pop-up
// instead.
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 191831a1f97..cb044ec0a29 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
@@ -6,14 +6,21 @@
#include <memory>
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
namespace test {
+using testing::Each;
+using testing::Property;
+using testing::SafeMatcherCast;
+
TEST_F(AccessibilityTest, IsDescendantOf) {
SetBodyInnerHTML(R"HTML(<button id="button">button</button>)HTML");
@@ -677,7 +684,7 @@ TEST_F(AccessibilityTest, AXObjectComparisonOperators) {
TEST_F(AccessibilityTest, AXObjectUnignoredAncestorsIterator) {
SetBodyInnerHTML(
- R"HTML(<p id="paragraph"><b id="bold"><br id="br"></b></p>)HTML");
+ R"HTML(<p id="paragraph"><b role="none" id="bold"><br id="br"></b></p>)HTML");
AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -697,31 +704,6 @@ TEST_F(AccessibilityTest, AXObjectUnignoredAncestorsIterator) {
EXPECT_EQ(br->UnignoredAncestorsEnd(), ++iter);
}
-TEST_F(AccessibilityTest, AXObjectInOrderTraversalIterator) {
- SetBodyInnerHTML(R"HTML(<input type="checkbox" id="checkbox">)HTML");
-
- AXObject* root = GetAXRootObject();
- ASSERT_NE(nullptr, root);
- AXObject* body = GetAXBodyObject();
- ASSERT_NE(nullptr, root);
- AXObject* checkbox = GetAXObjectByElementId("checkbox");
- ASSERT_NE(nullptr, checkbox);
-
- AXObject::InOrderTraversalIterator iter = body->GetInOrderTraversalIterator();
- EXPECT_EQ(*body, *iter);
- EXPECT_NE(GetAXObjectCache().InOrderTraversalEnd(), iter);
- EXPECT_EQ(*checkbox, *++iter);
- EXPECT_EQ(ax::mojom::Role::kCheckBox, iter->RoleValue());
- EXPECT_EQ(*checkbox, *iter++);
- EXPECT_EQ(GetAXObjectCache().InOrderTraversalEnd(), iter);
- EXPECT_EQ(*checkbox, *--iter);
- EXPECT_EQ(*checkbox, *iter--);
- --iter; // Skip the BODY element.
- --iter; // Skip the HTML element.
- EXPECT_EQ(ax::mojom::Role::kRootWebArea, iter->RoleValue());
- EXPECT_EQ(GetAXObjectCache().InOrderTraversalBegin(), iter);
-}
-
TEST_F(AccessibilityTest, AxNodeObjectContainsHtmlAnchorElementUrl) {
SetBodyInnerHTML(R"HTML(<a id="anchor" href="http://test.com">link</a>)HTML");
@@ -864,65 +846,227 @@ TEST_P(ParameterizedAccessibilityTest, NextOnLine) {
EXPECT_EQ("b", next->GetNode()->textContent());
}
-TEST_F(AccessibilityTest, AxObjectPreservedWhitespaceIsLineBreakingObjects) {
+TEST_F(AccessibilityTest, TableRowAndCellIsLineBreakingObject) {
SetBodyInnerHTML(R"HTML(
- <span style="white-space: pre-line" id="preserved">
- First Paragraph
- Second Paragraph
- Third Paragraph
- </span>)HTML");
+ <table id="table">
+ <caption>Caption</caption>
+ <tr id="row">
+ <td id="cell">Cell</td>
+ </tr>
+ </table>
+ )HTML");
- const AXObject* root = GetAXRootObject();
- ASSERT_NE(nullptr, root);
+ const AXObject* table = GetAXObjectByElementId("table");
+ ASSERT_NE(nullptr, table);
+ ASSERT_EQ(ax::mojom::Role::kTable, table->RoleValue());
+ EXPECT_TRUE(table->IsLineBreakingObject());
+
+ const AXObject* row = GetAXObjectByElementId("row");
+ ASSERT_NE(nullptr, row);
+ ASSERT_EQ(ax::mojom::Role::kRow, row->RoleValue());
+ EXPECT_TRUE(row->IsLineBreakingObject());
+
+ const AXObject* cell = GetAXObjectByElementId("cell");
+ ASSERT_NE(nullptr, cell);
+ ASSERT_EQ(ax::mojom::Role::kCell, cell->RoleValue());
+ EXPECT_TRUE(cell->IsLineBreakingObject());
+}
+
+TEST_F(AccessibilityTest,
+ PreservedWhitespaceWithInitialLineBreakIsLineBreakingObject) {
+ SetBodyInnerHTML(R"HTML(
+ <span style="white-space: pre-line" id="preserved">
+ First Paragraph
+ Second Paragraph
+ Third Paragraph
+ </span>)HTML");
const AXObject* preserved_span = GetAXObjectByElementId("preserved");
ASSERT_NE(nullptr, preserved_span);
ASSERT_EQ(ax::mojom::Role::kGenericContainer, preserved_span->RoleValue());
- ASSERT_EQ(1, preserved_span->ChildCountIncludingIgnored());
+ ASSERT_EQ(1, preserved_span->UnignoredChildCount());
EXPECT_FALSE(preserved_span->IsLineBreakingObject());
AXObject* preserved_text = preserved_span->FirstChildIncludingIgnored();
ASSERT_NE(nullptr, preserved_text);
ASSERT_EQ(ax::mojom::Role::kStaticText, preserved_text->RoleValue());
- EXPECT_FALSE(preserved_text->IsLineBreakingObject());
+ EXPECT_TRUE(preserved_text->IsLineBreakingObject())
+ << "This text node starts with a line break character, so it should be a "
+ "paragraph boundary.";
- // Expect 7 kInlineTextBox children
- // 3 lines of text, and 4 newlines
+ // Expect 7 kInlineTextBox children.
+ // 3 lines of text, and 4 newlines including one a the start of the text.
preserved_text->LoadInlineTextBoxes();
- ASSERT_EQ(7, preserved_text->ChildCountIncludingIgnored());
- bool all_children_are_inline_text_boxes = true;
- for (const AXObject* child : preserved_text->ChildrenIncludingIgnored()) {
- if (child->RoleValue() != ax::mojom::Role::kInlineTextBox) {
- all_children_are_inline_text_boxes = false;
- break;
- }
- }
- ASSERT_TRUE(all_children_are_inline_text_boxes);
-
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(0)->ComputedName(), "\n");
- EXPECT_TRUE(
- preserved_text->ChildAtIncludingIgnored(0)->IsLineBreakingObject());
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(1)->ComputedName(),
+ ASSERT_EQ(7, preserved_text->UnignoredChildCount());
+ ASSERT_THAT(preserved_text->UnignoredChildren(),
+ Each(SafeMatcherCast<AXObject*>(
+ Property("AXObject::RoleValue()", &AXObject::RoleValue,
+ ax::mojom::Role::kInlineTextBox))));
+
+ ASSERT_EQ(preserved_text->UnignoredChildAt(0)->ComputedName(), "\n");
+ EXPECT_TRUE(preserved_text->UnignoredChildAt(0)->IsLineBreakingObject());
+ ASSERT_EQ(preserved_text->UnignoredChildAt(1)->ComputedName(),
"First Paragraph");
- EXPECT_FALSE(
- preserved_text->ChildAtIncludingIgnored(1)->IsLineBreakingObject());
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(2)->ComputedName(), "\n");
- EXPECT_TRUE(
- preserved_text->ChildAtIncludingIgnored(2)->IsLineBreakingObject());
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(3)->ComputedName(),
+ EXPECT_FALSE(preserved_text->UnignoredChildAt(1)->IsLineBreakingObject());
+ ASSERT_EQ(preserved_text->UnignoredChildAt(2)->ComputedName(), "\n");
+ EXPECT_TRUE(preserved_text->UnignoredChildAt(2)->IsLineBreakingObject());
+ ASSERT_EQ(preserved_text->UnignoredChildAt(3)->ComputedName(),
"Second Paragraph");
- EXPECT_FALSE(
- preserved_text->ChildAtIncludingIgnored(3)->IsLineBreakingObject());
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(4)->ComputedName(), "\n");
- EXPECT_TRUE(
- preserved_text->ChildAtIncludingIgnored(4)->IsLineBreakingObject());
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(5)->ComputedName(),
+ EXPECT_FALSE(preserved_text->UnignoredChildAt(3)->IsLineBreakingObject());
+ ASSERT_EQ(preserved_text->UnignoredChildAt(4)->ComputedName(), "\n");
+ EXPECT_TRUE(preserved_text->UnignoredChildAt(4)->IsLineBreakingObject());
+ ASSERT_EQ(preserved_text->UnignoredChildAt(5)->ComputedName(),
"Third Paragraph");
- EXPECT_FALSE(
- preserved_text->ChildAtIncludingIgnored(5)->IsLineBreakingObject());
- ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(6)->ComputedName(), "\n");
- EXPECT_TRUE(
- preserved_text->ChildAtIncludingIgnored(6)->IsLineBreakingObject());
+ EXPECT_FALSE(preserved_text->UnignoredChildAt(5)->IsLineBreakingObject());
+ ASSERT_EQ(preserved_text->UnignoredChildAt(6)->ComputedName(), "\n");
+ EXPECT_TRUE(preserved_text->UnignoredChildAt(6)->IsLineBreakingObject());
+}
+
+TEST_F(AccessibilityTest, DivWithFirstLetterIsLineBreakingObject) {
+ SetBodyInnerHTML(R"HTML(
+ <style>div::first-letter { color: "red"; }</style>
+ <div id="firstLetter">First letter</div>)HTML");
+
+ const AXObject* div = GetAXObjectByElementId("firstLetter");
+ ASSERT_NE(nullptr, div);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, div->RoleValue());
+ ASSERT_EQ(1, div->UnignoredChildCount());
+ EXPECT_TRUE(div->IsLineBreakingObject());
+
+ AXObject* div_text = div->FirstChildIncludingIgnored();
+ ASSERT_NE(nullptr, div_text);
+ ASSERT_EQ(ax::mojom::Role::kStaticText, div_text->RoleValue());
+ EXPECT_FALSE(div_text->IsLineBreakingObject());
+
+ div_text->LoadInlineTextBoxes();
+ ASSERT_EQ(1, div_text->UnignoredChildCount());
+ ASSERT_EQ(ax::mojom::Role::kInlineTextBox,
+ div_text->UnignoredChildAt(0)->RoleValue());
+ ASSERT_EQ(div_text->UnignoredChildAt(0)->ComputedName(), "First letter");
+ EXPECT_FALSE(div_text->UnignoredChildAt(0)->IsLineBreakingObject());
+}
+
+TEST_F(AccessibilityTest, SlotIsLineBreakingObject) {
+ // Even though a <span>, <b> and <i> element are not line-breaking, a
+ // paragraph element in the shadow DOM should be.
+ const char* body_content = R"HTML(
+ <span id="host">
+ <b slot="slot1" id="slot1">slot1</b>
+ <i slot="slot2" id="slot2">slot2</i>
+ </span>)HTML";
+ const char* shadow_content = R"HTML(
+ <p><slot name="slot1"></slot></p>
+ <p><slot name="slot2"></slot></p>
+ )HTML";
+ SetBodyContent(body_content);
+ ShadowRoot& shadow_root =
+ GetElementById("host")->AttachShadowRootInternal(ShadowRootType::kOpen);
+ shadow_root.setInnerHTML(String::FromUTF8(shadow_content),
+ ASSERT_NO_EXCEPTION);
+ UpdateAllLifecyclePhasesForTest();
+
+ const AXObject* host = GetAXObjectByElementId("host");
+ ASSERT_NE(nullptr, host);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, host->RoleValue());
+ EXPECT_FALSE(host->IsLineBreakingObject());
+ EXPECT_TRUE(host->ParentObjectUnignored()->IsLineBreakingObject());
+
+ const AXObject* slot1 = GetAXObjectByElementId("slot1");
+ ASSERT_NE(nullptr, slot1);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, slot1->RoleValue());
+ EXPECT_FALSE(slot1->IsLineBreakingObject());
+ EXPECT_TRUE(slot1->ParentObjectUnignored()->IsLineBreakingObject());
+
+ const AXObject* slot2 = GetAXObjectByElementId("slot2");
+ ASSERT_NE(nullptr, slot2);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, slot2->RoleValue());
+ EXPECT_FALSE(slot2->IsLineBreakingObject());
+ EXPECT_TRUE(slot2->ParentObjectUnignored()->IsLineBreakingObject());
+}
+
+TEST_F(AccessibilityTest, LineBreakInDisplayLockedIsLineBreakingObject) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="spacer"
+ style="height: 30000px; contain-intrinsic-size: 1px 30000px;"></div>
+ <p id="lockedContainer" style="content-visibility: auto">
+ Line 1
+ <br id="br" style="content-visibility: hidden">
+ Line 2
+ </p>
+ )HTML");
+
+ const AXObject* paragraph = GetAXObjectByElementId("lockedContainer");
+ ASSERT_NE(nullptr, paragraph);
+ ASSERT_EQ(ax::mojom::Role::kParagraph, paragraph->RoleValue());
+ ASSERT_EQ(3, paragraph->UnignoredChildCount());
+ ASSERT_EQ(paragraph->GetNode(),
+ DisplayLockUtilities::NearestLockedInclusiveAncestor(
+ *paragraph->GetNode()))
+ << "The <p> element should be display locked.";
+ EXPECT_TRUE(paragraph->IsLineBreakingObject());
+
+ const AXObject* br = GetAXObjectByElementId("br");
+ ASSERT_NE(nullptr, br);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, br->RoleValue())
+ << "The <br> child should be display locked and thus have a generic "
+ "role.";
+ ASSERT_EQ(
+ paragraph->GetNode(),
+ DisplayLockUtilities::NearestLockedInclusiveAncestor(*br->GetNode()))
+ << "The <br> child should be display locked.";
+ EXPECT_TRUE(br->IsLineBreakingObject());
+}
+
+TEST_P(ParameterizedAccessibilityTest, ListMarkerIsNotLineBreakingObject) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ul li::marker {
+ content: "X";
+ }
+ </style>
+ <ul id="unorderedList">
+ <li id="unorderedListItem">.....
+ Unordered item 1
+ </li>
+ </ul>
+ <ol id="orderedList">
+ <li id="orderedListItem">
+ Ordered item 1
+ </li>
+ </ol>
+ )HTML");
+
+ const AXObject* unordered_list = GetAXObjectByElementId("unorderedList");
+ ASSERT_NE(nullptr, unordered_list);
+ ASSERT_EQ(ax::mojom::Role::kList, unordered_list->RoleValue());
+ EXPECT_TRUE(unordered_list->IsLineBreakingObject());
+
+ const AXObject* unordered_list_item =
+ GetAXObjectByElementId("unorderedListItem");
+ ASSERT_NE(nullptr, unordered_list_item);
+ ASSERT_EQ(ax::mojom::Role::kListItem, unordered_list_item->RoleValue());
+ EXPECT_TRUE(unordered_list_item->IsLineBreakingObject());
+
+ const AXObject* unordered_list_marker =
+ unordered_list_item->UnignoredChildAt(0);
+ ASSERT_NE(nullptr, unordered_list_marker);
+ ASSERT_EQ(ax::mojom::Role::kListMarker, unordered_list_marker->RoleValue());
+ EXPECT_FALSE(unordered_list_marker->IsLineBreakingObject());
+
+ const AXObject* ordered_list = GetAXObjectByElementId("orderedList");
+ ASSERT_NE(nullptr, ordered_list);
+ ASSERT_EQ(ax::mojom::Role::kList, ordered_list->RoleValue());
+ EXPECT_TRUE(ordered_list->IsLineBreakingObject());
+
+ const AXObject* ordered_list_item = GetAXObjectByElementId("orderedListItem");
+ ASSERT_NE(nullptr, ordered_list_item);
+ ASSERT_EQ(ax::mojom::Role::kListItem, ordered_list_item->RoleValue());
+ EXPECT_TRUE(ordered_list_item->IsLineBreakingObject());
+
+ const AXObject* ordered_list_marker = ordered_list_item->UnignoredChildAt(0);
+ ASSERT_NE(nullptr, ordered_list_marker);
+ ASSERT_EQ(ax::mojom::Role::kListMarker, ordered_list_marker->RoleValue());
+ EXPECT_FALSE(ordered_list_marker->IsLineBreakingObject());
}
TEST_F(AccessibilityTest, CheckNoDuplicateChildren) {
@@ -954,7 +1098,7 @@ TEST_F(AccessibilityTest, InitRelationCacheLabelFor) {
// Now recreate an AXContext, simulating what happens if accessibility
// is enabled after the document is loaded.
- ax_context_ = std::make_unique<AXContext>(GetDocument());
+ ax_context_ = std::make_unique<AXContext>(GetDocument(), ui::kAXModeComplete);
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -980,7 +1124,7 @@ TEST_F(AccessibilityTest, InitRelationCacheAriaOwns) {
// Now recreate an AXContext, simulating what happens if accessibility
// is enabled after the document is loaded.
- ax_context_ = std::make_unique<AXContext>(GetDocument());
+ ax_context_ = std::make_unique<AXContext>(GetDocument(), ui::kAXModeComplete);
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -1002,5 +1146,52 @@ TEST_F(AccessibilityTest, InitRelationCacheAriaOwns) {
EXPECT_EQ(li->ParentObjectUnignored(), ul);
}
+TEST_F(AccessibilityTest, IsSelectedFromFocusSupported) {
+ SetBodyInnerHTML(R"HTML(
+ <input role="combobox" type="search" aria-expanded="true"
+ aria-haspopup="true" aria-autocomplete="list1" aria-owns="list1">
+ <ul id="list1" role="listbox">
+ <li id="option1" role="option" tabindex="-1">Apple</li>
+ </ul>
+ <input role="combobox" type="search" aria-expanded="true"
+ aria-haspopup="true" aria-autocomplete="list2" aria-owns="list2">
+ <ul id="list2" role="listbox">
+ <li id="option2" role="row" tabindex="-1">Apple</li>
+ </ul>
+ <input role="combobox" type="search" aria-expanded="true"
+ aria-haspopup="true" aria-autocomplete="list3" aria-owns="list3">
+ <ul id="list3" role="listbox">
+ <li id="option3" role="option" tabindex="-1"
+ aria-selected="false">Apple</li>
+ </ul>
+ <input role="combobox" type="search" aria-expanded="true"
+ aria-haspopup="true" aria-autocomplete="list4" aria-owns="list4">
+ <ul id="list4" role="listbox">
+ <li id="option4" role="option" tabindex="-1"
+ aria-selected="true">Apple</li>
+ <li id="option5" role="option" tabindex="-1">Orange</li>
+ </ul>
+ )HTML");
+
+ const AXObject* option1 = GetAXObjectByElementId("option1");
+ ASSERT_NE(option1, nullptr);
+ const AXObject* option2 = GetAXObjectByElementId("option2");
+ ASSERT_NE(option2, nullptr);
+ const AXObject* option3 = GetAXObjectByElementId("option3");
+ ASSERT_NE(option3, nullptr);
+ const AXObject* option4 = GetAXObjectByElementId("option4");
+ ASSERT_NE(option4, nullptr);
+ const AXObject* option5 = GetAXObjectByElementId("option5");
+ ASSERT_NE(option5, nullptr);
+
+ EXPECT_TRUE(option1->IsSelectedFromFocusSupported());
+ EXPECT_FALSE(option2->IsSelectedFromFocusSupported());
+ EXPECT_FALSE(option3->IsSelectedFromFocusSupported());
+ EXPECT_FALSE(option4->IsSelectedFromFocusSupported());
+ // TODO(crbug.com/1143451): #option5 should not support selection from focus
+ // because #option4 is explicitly selected.
+ EXPECT_TRUE(option5->IsSelectedFromFocusSupported());
+}
+
} // namespace test
} // 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 6f89a2c4936..31166460b8a 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
@@ -266,9 +266,10 @@ const AXPosition AXPosition::FromPosition(
// same formatting context.
int container_offset = container->TextOffsetInFormattingContext(0);
int text_offset =
- int{container_offset_mapping
+ static_cast<int>(
+ container_offset_mapping
->GetTextContentOffset(parent_anchored_position)
- .value_or(static_cast<unsigned int>(container_offset))} -
+ .value_or(static_cast<unsigned int>(container_offset))) -
container_offset;
DCHECK_GE(text_offset, 0);
ax_position.text_offset_or_child_index_ = text_offset;
@@ -463,8 +464,8 @@ int AXPosition::MaxTextOffset() const {
container_offset_mapping->GetMappingUnitsForNode(*container_node);
if (mapping_units.empty())
return container_object_->ComputedName().length();
- return int{mapping_units.back().TextContentEnd() -
- mapping_units.front().TextContentStart()};
+ return static_cast<int>(mapping_units.back().TextContentEnd() -
+ mapping_units.front().TextContentStart());
}
TextAffinity AXPosition::Affinity() const {
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 dfb9e2abc37..6a08fa0af6a 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
@@ -8,6 +8,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/editing/position.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/html/html_element.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
@@ -678,6 +679,69 @@ TEST_F(AccessibilityTest, PositionInHTMLLabel) {
Label text.
</label>
<p id="paragraph">Intervening paragraph.</p>
+ <input id="input">
+ )HTML");
+
+ const Node* label = GetElementById("label");
+ ASSERT_NE(nullptr, label);
+ const Node* label_text = label->firstChild();
+ ASSERT_NE(nullptr, label_text);
+ ASSERT_TRUE(label_text->IsTextNode());
+ const Node* paragraph = GetElementById("paragraph");
+ ASSERT_NE(nullptr, paragraph);
+
+ const AXObject* ax_body = GetAXBodyObject();
+ ASSERT_NE(nullptr, ax_body);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_body->RoleValue());
+
+ const AXObject* ax_label = GetAXObjectByElementId("label");
+ ASSERT_NE(nullptr, ax_label);
+ ASSERT_FALSE(ax_label->AccessibilityIsIgnored());
+ const AXObject* ax_label_text = ax_label->FirstChildIncludingIgnored();
+ ASSERT_NE(nullptr, ax_label_text);
+ ASSERT_EQ(ax::mojom::Role::kStaticText, ax_label_text->RoleValue());
+ const AXObject* ax_paragraph = GetAXObjectByElementId("paragraph");
+ ASSERT_NE(nullptr, ax_paragraph);
+ ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue());
+
+ const auto position_before_label = Position::BeforeNode(*label);
+ const auto ax_position_before_label =
+ AXPosition::FromPosition(position_before_label, TextAffinity::kDownstream,
+ AXPositionAdjustmentBehavior::kMoveLeft);
+ EXPECT_FALSE(ax_position_before_label.IsTextPosition());
+ EXPECT_EQ(ax_body, ax_position_before_label.ContainerObject());
+ EXPECT_EQ(0, ax_position_before_label.ChildIndex());
+ EXPECT_EQ(ax_label, ax_position_before_label.ChildAfterTreePosition());
+
+ const auto position_before_text = Position::BeforeNode(*label_text);
+ const auto position_in_text = Position::FirstPositionInNode(*label_text);
+ const auto position_after_label = Position::AfterNode(*label);
+ for (const auto& position :
+ {position_before_text, position_in_text, position_after_label}) {
+ const auto ax_position =
+ AXPosition::FromPosition(position, TextAffinity::kDownstream,
+ AXPositionAdjustmentBehavior::kMoveLeft);
+ EXPECT_TRUE(ax_position.IsTextPosition());
+ EXPECT_EQ(ax_label_text, ax_position.ContainerObject());
+ EXPECT_EQ(nullptr, ax_position.ChildAfterTreePosition());
+ }
+ const auto position_before_paragraph = Position::BeforeNode(*paragraph);
+ const auto ax_position_before_paragraph = AXPosition::FromPosition(
+ position_before_paragraph, TextAffinity::kDownstream,
+ AXPositionAdjustmentBehavior::kMoveLeft);
+ EXPECT_FALSE(ax_position_before_paragraph.IsTextPosition());
+ EXPECT_EQ(ax_body, ax_position_before_paragraph.ContainerObject());
+ EXPECT_EQ(1, ax_position_before_paragraph.ChildIndex());
+ EXPECT_EQ(ax_paragraph,
+ ax_position_before_paragraph.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, PositionInHTMLLabelIgnored) {
+ SetBodyInnerHTML(R"HTML(
+ <label id="label" for="input">
+ Label text.
+ </label>
+ <p id="paragraph">Intervening paragraph.</p>
<input id="input" type="checkbox" checked>
)HTML");
@@ -697,15 +761,25 @@ TEST_F(AccessibilityTest, PositionInHTMLLabel) {
const AXObject* ax_label = GetAXObjectByElementId("label");
ASSERT_NE(nullptr, ax_label);
ASSERT_TRUE(ax_label->AccessibilityIsIgnored());
+ const AXObject* ax_label_text = ax_label->FirstChildIncludingIgnored();
+ ASSERT_NE(nullptr, ax_label_text);
+ ASSERT_TRUE(ax_label_text->AccessibilityIsIgnored());
+ ASSERT_EQ(ax::mojom::Role::kStaticText, ax_label_text->RoleValue());
const AXObject* ax_paragraph = GetAXObjectByElementId("paragraph");
ASSERT_NE(nullptr, ax_paragraph);
ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue());
- // All of the following DOM positions should be ignored in the accessibility
- // tree.
+ // A position anchored before a text node is explicitly moved to before the
+ // first character of the text object.
const auto position_before = Position::BeforeNode(*label);
const auto position_before_text = Position::BeforeNode(*label_text);
+
const auto position_in_text = Position::FirstPositionInNode(*label_text);
+
+ // This position points to the empty text node between the label and the
+ // paragraph. That's invalid so it's moved the closest node to the left
+ // (because we used AXPositionAdjustmentBehavior::kMoveLeft), landing in the
+ // last character of the label text.
const auto position_after = Position::AfterNode(*label);
for (const auto& position : {position_before, position_before_text,
@@ -713,16 +787,26 @@ TEST_F(AccessibilityTest, PositionInHTMLLabel) {
const auto ax_position =
AXPosition::FromPosition(position, TextAffinity::kDownstream,
AXPositionAdjustmentBehavior::kMoveLeft);
- EXPECT_FALSE(ax_position.IsTextPosition());
- EXPECT_EQ(ax_body, ax_position.ContainerObject());
- EXPECT_EQ(0, ax_position.ChildIndex());
- EXPECT_EQ(ax_paragraph, ax_position.ChildAfterTreePosition());
+ EXPECT_TRUE(ax_position.IsTextPosition());
+ EXPECT_EQ(ax_label_text, ax_position.ContainerObject());
+ EXPECT_EQ(nullptr, ax_position.ChildAfterTreePosition());
const auto position_from_ax = ax_position.ToPositionWithAffinity();
- EXPECT_EQ(GetDocument().body(), position_from_ax.AnchorNode());
- EXPECT_EQ(3, position_from_ax.GetPosition().OffsetInContainerNode());
- EXPECT_EQ(paragraph,
+ EXPECT_EQ(label_text, position_from_ax.AnchorNode());
+ EXPECT_EQ(nullptr,
position_from_ax.GetPosition().ComputeNodeAfterPosition());
+
+ if (position == position_after) {
+ // this position excludes whitespace
+ EXPECT_EQ(11, ax_position.TextOffset());
+ // this position includes the whitespace before "Label text."
+ EXPECT_EQ(20, position_from_ax.GetPosition().OffsetInContainerNode());
+ } else {
+ // this position excludes whitespace
+ EXPECT_EQ(0, ax_position.TextOffset());
+ // this position includes the whitespace before "Label text."
+ EXPECT_EQ(9, position_from_ax.GetPosition().OffsetInContainerNode());
+ }
}
}
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 15c8d1950af..a3e6114cfed 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
@@ -56,6 +56,10 @@ void AXRelationCache::ProcessUpdatesWithCleanLayout() {
owner_ids_to_update_.clear();
}
+bool AXRelationCache::IsDirty() const {
+ return !initialized_ || !owner_ids_to_update_.IsEmpty();
+}
+
bool AXRelationCache::IsAriaOwned(const AXObject* child) const {
if (!child)
return false;
@@ -74,6 +78,14 @@ AXObject* AXRelationCache::GetAriaOwnedParent(const AXObject* child) const {
return ObjectFromAXID(iter->value);
}
+AXObject* AXRelationCache::ValidatedAriaOwner(const AXObject* child) {
+ AXObject* owner = GetAriaOwnedParent(child);
+ if (!owner || IsValidOwnsRelation(owner, const_cast<AXObject*>(child)))
+ return owner;
+ RemoveOwnedRelation(child->AXObjectID());
+ return nullptr;
+}
+
// Update reverse relation map, where relation_source is related to target_ids.
// TODO Support when HasExplicitlySetAttrAssociatedElement() == true.
void AXRelationCache::UpdateReverseRelations(const AXObject* relation_source,
@@ -88,12 +100,29 @@ void AXRelationCache::UpdateReverseRelations(const AXObject* relation_source,
}
}
+// ContainsCycle() should:
+// * Return true when a cycle is an authoring error, but not an error in Blink.
+// * CHECK(false) when Blink should have caught this error earlier ... we should
+// have never gotten into this state.
+//
+// For example, if a web page specifies that grandchild owns it's grandparent,
+// what should happen is the ContainsCycle will start at the grandchild and go
+// up, finding that it's grandparent is already in the ancestor chain, and
+// return false, thus disallowing the relation. However, if on the way to the
+// root, it discovers that any other two objects are repeated in the ancestor
+// chain, this is unexpected, and results in the CHECK(false) condition.
static bool ContainsCycle(AXObject* owner, AXObject* child) {
+ HashSet<AXID> visited;
// Walk up the parents of the owner object, make sure that this child
// doesn't appear there, as that would create a cycle.
- for (AXObject* parent = owner; parent; parent = parent->ParentObject()) {
- if (parent == child)
+ for (AXObject* ancestor = owner; ancestor;
+ ancestor = ancestor->CachedParentObject()) {
+ if (ancestor == child)
return true;
+ CHECK(visited.insert(ancestor->AXObjectID()).is_new_entry)
+ << "Cycle in unexpected place:\n"
+ << "* Owner = " << owner->ToString(true, true)
+ << "* Child = " << child->ToString(true, true);
}
return false;
}
@@ -116,6 +145,7 @@ bool AXRelationCache::IsValidOwnsRelation(AXObject* owner,
return true;
}
+// static
bool AXRelationCache::IsValidOwner(AXObject* owner) {
if (!owner->GetNode()) {
NOTREACHED() << "Cannot use aria-owns without a node on both ends";
@@ -146,6 +176,7 @@ bool AXRelationCache::IsValidOwner(AXObject* owner) {
return true;
}
+// static
bool AXRelationCache::IsValidOwnedChild(AXObject* child) {
if (!child)
return false;
@@ -162,8 +193,11 @@ bool AXRelationCache::IsValidOwnedChild(AXObject* child) {
}
void AXRelationCache::UnmapOwnedChildren(const AXObject* owner,
- const Vector<AXID> child_ids) {
- for (AXID removed_child_id : child_ids) {
+ const Vector<AXID>& removed_child_ids,
+ const Vector<AXID>& newly_owned_ids) {
+ DCHECK(owner);
+ DCHECK(!owner->IsDetached());
+ for (AXID removed_child_id : removed_child_ids) {
// Find the AXObject for the child that this owner no longer owns.
AXObject* removed_child = ObjectFromAXID(removed_child_id);
@@ -182,20 +216,30 @@ void AXRelationCache::UnmapOwnedChildren(const AXObject* owner,
// parent and calling childrenChanged on its real parent.
removed_child->DetachFromParent();
// Recompute the real parent and cache it.
- AXObject* real_parent = removed_child->ParentObject();
- SANITIZER_CHECK(real_parent) << "No parent to restore for object with "
- "unmapped aria-owns, child is: "
- << removed_child->ToString(true, true);
- if (real_parent)
- ChildrenChanged(real_parent);
+ // Don't do this if it's also in the newly owned ids, as it's about to
+ // get a new parent, and we want to avoid accidentally pruning it.
+ if (!newly_owned_ids.Contains(removed_child_id)) {
+ if (AXObject* real_parent =
+ object_cache_->RestoreParentOrPrune(removed_child)) {
+ ChildrenChanged(real_parent);
+ }
+ // Now that the child is not owned, it's "included in tree" state must
+ // be recomputed because while owned children are always included in the
+ // tree, unowned children may not be included.
+ removed_child->UpdateCachedAttributeValuesIfNeeded(false);
+ }
}
}
}
void AXRelationCache::MapOwnedChildren(const AXObject* owner,
- const Vector<AXID> child_ids) {
+ const Vector<AXID>& child_ids) {
+ DCHECK(owner);
+ DCHECK(!owner->IsDetached());
for (AXID added_child_id : child_ids) {
AXObject* added_child = ObjectFromAXID(added_child_id);
+ DCHECK(added_child);
+ DCHECK(!added_child->IsDetached());
// Add this child to the mapping from child to owner.
aria_owned_child_to_owner_mapping_.Set(added_child_id, owner->AXObjectID());
@@ -209,6 +253,9 @@ void AXRelationCache::MapOwnedChildren(const AXObject* owner,
if (original_parent)
ChildrenChanged(original_parent);
}
+ // Now that the child is owned, it's "included in tree" state must be
+ // recomputed because owned children are always included in the tree.
+ added_child->UpdateCachedAttributeValuesIfNeeded(false);
}
}
@@ -229,13 +276,14 @@ void AXRelationCache::UpdateAriaOwnsFromAttrAssociatedElementsWithCleanLayout(
// TODO(meredithl): Determine how to update reverse relations for elements
// without an id.
- if (element->GetIdAttribute())
- owned_id_vector.push_back(element->GetIdAttribute());
if (IsValidOwnsRelation(const_cast<AXObject*>(owner), child)) {
+ if (element->GetIdAttribute())
+ owned_id_vector.push_back(element->GetIdAttribute());
validated_owned_children_result.push_back(child);
} else if (child) {
// Invalid owns relation: repair the parent that was set above.
- child->SetParent(child->ComputeParent());
+ object_cache_->RestoreParentOrPrune(child);
+ DCHECK_NE(child->CachedParentObject(), owner);
}
}
@@ -247,7 +295,7 @@ void AXRelationCache::UpdateAriaOwnsFromAttrAssociatedElementsWithCleanLayout(
owner, validated_owned_children_result, force);
}
-void AXRelationCache::GetAriaOwnedChildren(
+void AXRelationCache::ValidatedAriaOwnedChildren(
const AXObject* owner,
HeapVector<Member<AXObject>>& validated_owned_children_result) {
if (!aria_owner_to_children_mapping_.Contains(owner->AXObjectID()))
@@ -256,9 +304,14 @@ void AXRelationCache::GetAriaOwnedChildren(
aria_owner_to_children_mapping_.at(owner->AXObjectID());
for (AXID child_id : current_child_axids) {
AXObject* child = ObjectFromAXID(child_id);
- if (child) {
+ if (!child) {
+ RemoveOwnedRelation(child_id);
+ } else if (ValidatedAriaOwner(child) == owner) {
validated_owned_children_result.push_back(child);
- DCHECK(IsAriaOwned(child)) << "Owned child not in owned child map";
+ DCHECK(IsAriaOwned(child))
+ << "Owned child not in owned child map:"
+ << "\n* Owner = " << owner->ToString(true, true)
+ << "\n* Child = " << child->ToString(true, true);
}
}
}
@@ -292,8 +345,7 @@ void AXRelationCache::UpdateAriaOwnsWithCleanLayout(AXObject* owner,
} else if (element && element->HasExplicitlySetAttrAssociatedElements(
html_names::kAriaOwnsAttr)) {
UpdateAriaOwnsFromAttrAssociatedElementsWithCleanLayout(
- owner,
- element->GetElementArrayAttribute(html_names::kAriaOwnsAttr).value(),
+ owner, *element->GetElementArrayAttribute(html_names::kAriaOwnsAttr),
owned_children, force);
} else {
// Figure out the ids that actually correspond to children that exist
@@ -318,7 +370,8 @@ void AXRelationCache::UpdateAriaOwnsWithCleanLayout(AXObject* owner,
owned_children.push_back(child);
} else if (child) {
// Invalid owns relation: repair the parent that was set above.
- child->SetParent(child->ComputeParent());
+ object_cache_->RestoreParentOrPrune(child);
+ DCHECK_NE(child->CachedParentObject(), owner);
}
}
}
@@ -342,27 +395,36 @@ void AXRelationCache::UpdateAriaOwnerToChildrenMappingWithCleanLayout(
// Compare this to the current list of owned children, and exit early if
// there are no changes.
- Vector<AXID> current_child_axids =
- aria_owner_to_children_mapping_.at(owner->AXObjectID());
+ Vector<AXID> previously_owned_child_ids;
+ auto it = aria_owner_to_children_mapping_.find(owner->AXObjectID());
+ if (it != aria_owner_to_children_mapping_.end()) {
+ previously_owned_child_ids = it->value;
+ }
// Only force the refresh if there was or will be owned children; otherwise,
// there is nothing to refresh even for a new AXObject replacing an old owner.
- if (current_child_axids == validated_owned_child_axids &&
- (!force || current_child_axids.IsEmpty())) {
+ if (previously_owned_child_ids == validated_owned_child_axids &&
+ (!force || previously_owned_child_ids.IsEmpty())) {
return;
}
+ // Incrementing the modification count ensures that cached "included in tree"
+ // state is recomputed on objects with changed ownership -- owned children
+ // must always be included in the tree.
+ object_cache_->IncrementModificationCount();
+
// The list of owned children has changed. Even if they were just reordered,
// to be safe and handle all cases we remove all of the current owned
// children and add the new list of owned children.
- UnmapOwnedChildren(owner, current_child_axids);
+ UnmapOwnedChildren(owner, previously_owned_child_ids,
+ validated_owned_child_axids);
MapOwnedChildren(owner, validated_owned_child_axids);
#if DCHECK_IS_ON()
// Owned children must be in tree to avoid serialization issues.
for (AXObject* child : validated_owned_children_result) {
DCHECK(IsAriaOwned(child));
- DCHECK(child->AccessibilityIsIncludedInTree())
+ DCHECK(child->ComputeAccessibilityIsIgnoredButIncludedInTree())
<< "Owned child not in tree: " << child->ToString(true, false)
<< "\nRecompute included in tree: "
<< child->ComputeAccessibilityIsIgnoredButIncludedInTree();
@@ -414,7 +476,9 @@ void AXRelationCache::UpdateRelatedTree(Node* node, AXObject* obj) {
HeapVector<Member<AXObject>> related_sources;
#if DCHECK_IS_ON()
DCHECK(node);
- AXObject* obj_for_node = Get(node);
+ if (obj)
+ DCHECK(!obj->IsDetached());
+ AXObject* obj_for_node = object_cache_->GetWithoutInvalidation(node);
DCHECK(!obj || obj_for_node == obj)
<< "Object and node did not match:"
<< "\n* node = " << node << "\n* obj = " << obj->ToString(true, true)
@@ -424,9 +488,9 @@ void AXRelationCache::UpdateRelatedTree(Node* node, AXObject* obj) {
AXObject* related_target = obj ? obj : Get(node);
// If it's already owned, schedule an update on the owner.
if (related_target && IsAriaOwned(related_target)) {
- AXObject* owned_parent = GetAriaOwnedParent(related_target);
- DCHECK(owned_parent);
- owner_ids_to_update_.insert(owned_parent->AXObjectID());
+ AXObject* owned_parent = ValidatedAriaOwner(related_target);
+ if (owned_parent)
+ owner_ids_to_update_.insert(owned_parent->AXObjectID());
}
// Ensure children are updated if there is a change.
@@ -452,18 +516,18 @@ void AXRelationCache::UpdateRelatedText(Node* node) {
HeapVector<Member<AXObject>> related_sources;
GetReverseRelated(current_node, related_sources);
for (AXObject* related : related_sources) {
- if (related) {
- object_cache_->MarkAXObjectDirtyWithCleanLayout(related,
- /*subtree=*/false);
- }
+ if (related && related->AccessibilityIsIncludedInTree())
+ object_cache_->MarkAXObjectDirtyWithCleanLayout(related);
}
// Ancestors that may derive their accessible name from descendant content
// should also handle text changed events when descendant content changes.
if (current_node != node) {
AXObject* obj = Get(current_node);
- if (obj && obj->SupportsNameFromContents(/*recursive=*/false))
- object_cache_->MarkAXObjectDirtyWithCleanLayout(obj, /*subtree=*/false);
+ if (obj && obj->AccessibilityIsIncludedInTree() &&
+ obj->SupportsNameFromContents(/*recursive=*/false)) {
+ object_cache_->MarkAXObjectDirtyWithCleanLayout(obj);
+ }
}
// Forward relation via <label for="[id]">.
@@ -487,6 +551,11 @@ void AXRelationCache::RemoveAXID(AXID obj_id) {
}
// Another id owned |obj_id|:
+ RemoveOwnedRelation(obj_id);
+}
+
+void AXRelationCache::RemoveOwnedRelation(AXID obj_id) {
+ // Another id owned |obj_id|.
if (aria_owned_child_to_owner_mapping_.Contains(obj_id)) {
// Previous owner no longer relevant to this child.
// Also, remove |obj_id| from previous owner's owned child list:
@@ -523,9 +592,9 @@ void AXRelationCache::LabelChanged(Node* node) {
To<HTMLElement>(node)->FastGetAttribute(html_names::kForAttr);
if (!id.IsEmpty()) {
all_previously_seen_label_target_ids_.insert(id);
- if (auto* control = To<HTMLLabelElement>(node)->control()) {
- if (AXObject* obj = Get(control))
- object_cache_->MarkAXObjectDirtyWithCleanLayout(obj, /*subtree=*/false);
+ if (AXObject* obj = Get(To<HTMLLabelElement>(node)->control())) {
+ if (obj->AccessibilityIsIncludedInTree())
+ object_cache_->MarkAXObjectDirtyWithCleanLayout(obj);
}
}
}
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 4240ead9f65..5d7bb0107a3 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
@@ -31,12 +31,15 @@ class AXRelationCache {
bool IsAriaOwned(AXID) const;
bool IsAriaOwned(const AXObject*) const;
- // Returns the parent of the given object due to aria-owns.
- AXObject* GetAriaOwnedParent(const AXObject*) const;
+ // Returns the parent of the given object due to aria-owns, if valid,
+ // otherwise, removes the child from maps indicating that it is owned.
+ AXObject* ValidatedAriaOwner(const AXObject*);
// Returns the validated owned children of this element with aria-owns.
- void GetAriaOwnedChildren(const AXObject* owner,
- HeapVector<Member<AXObject>>& owned_children);
+ // Any children that are no longer valid are removed from maps indicating they
+ // are owned.
+ void ValidatedAriaOwnedChildren(const AXObject* owner,
+ HeapVector<Member<AXObject>>& owned_children);
// Return true if any label ever pointed to the element via the for attribute.
bool MayHaveHTMLLabelViaForAttribute(const HTMLElement&);
@@ -52,6 +55,10 @@ class AXRelationCache {
// Remove given AXID from cache.
void RemoveAXID(AXID);
+ // The child cannot be owned, either because the child was removed or the
+ // relation was invalid, so remove from all relevant mappings.
+ void RemoveOwnedRelation(AXID);
+
// Update map of ids to related objects.
// If one or more ids aren't found, they're added to a lookup table so that if
// an element with that id appears later, it can be added when you call
@@ -84,10 +91,16 @@ class AXRelationCache {
// owned ids have not changed, e.g. when an object has been refreshed.
void UpdateAriaOwnsWithCleanLayout(AXObject* owner, bool force = false);
+ // Is there work to be done when layout becomes clean?
+ bool IsDirty() const;
+
static bool IsValidOwner(AXObject* owner);
static bool IsValidOwnedChild(AXObject* child);
private:
+ // Returns the parent of the given object due to aria-owns.
+ AXObject* GetAriaOwnedParent(const AXObject*) const;
+
// Given an object that has explicitly set elements for aria-owns, update the
// internal state to reflect the new set of children owned by this object.
// Note that |owned_children| will be the AXObjects corresponding to the
@@ -104,8 +117,11 @@ class AXRelationCache {
void UpdateRelatedText(Node*);
bool IsValidOwnsRelation(AXObject* owner, AXObject* child) const;
- void UnmapOwnedChildren(const AXObject* owner, Vector<AXID>);
- void MapOwnedChildren(const AXObject* owner, Vector<AXID>);
+ void UnmapOwnedChildren(const AXObject* owner,
+ const Vector<AXID>& removed_child_ids,
+ const Vector<AXID>& newly_owned_ids);
+
+ void MapOwnedChildren(const AXObject* owner, const Vector<AXID>&);
void GetReverseRelated(Node*, HeapVector<Member<AXObject>>& sources);
// Updates |aria_owner_to_children_mapping_| after calling UpdateAriaOwns for
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 2b0c51e6fd7..986aee88789 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
@@ -158,13 +158,13 @@ AXSelection AXSelection::FromCurrentSelection(
const bool is_backward = (text_control.selectionDirection() == "backward");
const auto ax_base = AXPosition::CreatePositionInTextObject(
*ax_text_control,
- (is_backward ? int{text_control.selectionEnd()}
- : int{text_control.selectionStart()}),
+ static_cast<int>(is_backward ? text_control.selectionEnd()
+ : text_control.selectionStart()),
base_affinity);
const auto ax_extent = AXPosition::CreatePositionInTextObject(
*ax_text_control,
- (is_backward ? int{text_control.selectionStart()}
- : int{text_control.selectionEnd()}),
+ static_cast<int>(is_backward ? text_control.selectionStart()
+ : text_control.selectionEnd()),
extent_affinity);
if (!ax_base.IsValid() || !ax_extent.IsValid())
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 06f217eee8f..f9fb65a522b 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
@@ -865,7 +865,7 @@ TEST_F(AccessibilitySelectionTest,
ASSERT_TRUE(ax_selection.Extent().IsTextPosition());
EXPECT_EQ(ax_static_text, ax_selection.Extent().ContainerObject());
EXPECT_EQ(ax_static_text->ComputedName().length(),
- unsigned{ax_selection.Extent().TextOffset()});
+ static_cast<unsigned>(ax_selection.Extent().TextOffset()));
}
TEST_F(AccessibilitySelectionTest,
@@ -1187,8 +1187,8 @@ TEST_F(AccessibilitySelectionTest, SelectEachConsecutiveCharacterInTextField) {
testing::Message message;
message << "While selecting forward character "
- << char{text_control.InnerEditorValue()[i]} << " at position " << i
- << " in text field.";
+ << static_cast<char>(text_control.InnerEditorValue()[i])
+ << " at position " << i << " in text field.";
SCOPED_TRACE(message);
EXPECT_TRUE(ax_selection.Select());
@@ -1206,8 +1206,8 @@ TEST_F(AccessibilitySelectionTest, SelectEachConsecutiveCharacterInTextField) {
testing::Message message;
message << "While selecting backward character "
- << char{text_control.InnerEditorValue()[i]} << " at position " << i
- << " in text field.";
+ << static_cast<char>(text_control.InnerEditorValue()[i])
+ << " at position " << i << " in text field.";
SCOPED_TRACE(message);
EXPECT_TRUE(ax_selection.Select());
@@ -1263,8 +1263,8 @@ TEST_F(AccessibilitySelectionTest,
testing::Message message;
message << "While selecting forward character "
- << char{text_control.InnerEditorValue()[i]} << " at position " << i
- << " in text field.";
+ << static_cast<char>(text_control.InnerEditorValue()[i])
+ << " at position " << i << " in text field.";
SCOPED_TRACE(message);
EXPECT_TRUE(ax_selection.Select());
@@ -1282,8 +1282,8 @@ TEST_F(AccessibilitySelectionTest,
testing::Message message;
message << "While selecting backward character "
- << char{text_control.InnerEditorValue()[i]} << " at position " << i
- << " in text field.";
+ << static_cast<char>(text_control.InnerEditorValue()[i])
+ << " at position " << i << " in text field.";
SCOPED_TRACE(message);
EXPECT_TRUE(ax_selection.Select());
@@ -1510,8 +1510,8 @@ TEST_F(AccessibilitySelectionTest, SelectEachConsecutiveCharacterInTextarea) {
testing::Message message;
message << "While selecting forward character "
- << char{text_control.value()[i]} << " at position " << i
- << " in textarea.";
+ << static_cast<char>(text_control.value()[i]) << " at position "
+ << i << " in textarea.";
SCOPED_TRACE(message);
EXPECT_TRUE(ax_selection.Select());
@@ -1530,8 +1530,8 @@ TEST_F(AccessibilitySelectionTest, SelectEachConsecutiveCharacterInTextarea) {
testing::Message message;
message << "While selecting backward character "
- << char{text_control.value()[i]} << " at position " << i
- << " in textarea.";
+ << static_cast<char>(text_control.value()[i]) << " at position "
+ << i << " in textarea.";
SCOPED_TRACE(message);
EXPECT_TRUE(ax_selection.Select());
@@ -1651,13 +1651,13 @@ TEST_F(AccessibilitySelectionTest,
EXPECT_TRUE(ax_selection.Base().IsTextPosition());
EXPECT_EQ(ax_text, ax_selection.Base().ContainerObject());
EXPECT_LE(15, ax_selection.Base().TextOffset());
- EXPECT_GT(int{ax_text->ComputedName().length()},
+ EXPECT_GT(static_cast<int>(ax_text->ComputedName().length()),
ax_selection.Base().TextOffset());
EXPECT_EQ(TextAffinity::kUpstream, ax_selection.Base().Affinity());
EXPECT_TRUE(ax_selection.Extent().IsTextPosition());
EXPECT_EQ(ax_text, ax_selection.Extent().ContainerObject());
EXPECT_LE(15, ax_selection.Extent().TextOffset());
- EXPECT_GT(int{ax_text->ComputedName().length()},
+ EXPECT_GT(static_cast<int>(ax_text->ComputedName().length()),
ax_selection.Extent().TextOffset());
EXPECT_EQ(TextAffinity::kUpstream, ax_selection.Extent().Affinity());
}
@@ -1712,8 +1712,10 @@ TEST_F(AccessibilitySelectionTest,
// The discrepancy between DOM and AX text offsets is due to the fact that
// there is some white space in the DOM that is compressed in the
// accessibility tree.
- EXPECT_EQ(int{i + 9}, dom_selection.Base().OffsetInContainerNode());
- EXPECT_EQ(int{i + 10}, dom_selection.Extent().OffsetInContainerNode());
+ EXPECT_EQ(static_cast<int>(i + 9),
+ dom_selection.Base().OffsetInContainerNode());
+ EXPECT_EQ(static_cast<int>(i + 10),
+ dom_selection.Extent().OffsetInContainerNode());
}
for (unsigned int i = computed_name.length(); i > 0; --i) {
@@ -1738,8 +1740,10 @@ TEST_F(AccessibilitySelectionTest,
// The discrepancy between DOM and AX text offsets is due to the fact that
// there is some white space in the DOM that is compressed in the
// accessibility tree.
- EXPECT_EQ(int{i + 9}, dom_selection.Base().OffsetInContainerNode());
- EXPECT_EQ(int{i + 8}, dom_selection.Extent().OffsetInContainerNode());
+ EXPECT_EQ(static_cast<int>(i + 9),
+ dom_selection.Base().OffsetInContainerNode());
+ EXPECT_EQ(static_cast<int>(i + 8),
+ dom_selection.Extent().OffsetInContainerNode());
}
}
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc
index bd83a723f96..b8aed3a3966 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc
@@ -87,7 +87,7 @@ bool AXSlider::OnNativeSetValueAction(const String& value) {
return false;
// Ensure the AX node is updated.
- AXObjectCache().MarkAXObjectDirtyWithCleanLayout(this, false);
+ AXObjectCache().MarkAXObjectDirtyWithCleanLayout(this);
return true;
}
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
index af587c98697..f1616cc046b 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
@@ -3,8 +3,10 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h"
+
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -70,6 +72,10 @@ void SetObjectAttribute(ax::mojom::blink::IntAttribute attribute,
!ax_target->IsVisible()) {
return;
}
+ if (attribute == ax::mojom::blink::IntAttribute::kErrormessageId &&
+ object->GetInvalidState() == ax::mojom::blink::InvalidState::kFalse) {
+ return;
+ }
node_data->AddIntAttribute(attribute, ax_target->AXObjectID());
}
@@ -82,13 +88,13 @@ void SetIntListAttribute(ax::mojom::blink::IntListAttribute attribute,
Element* element = object->GetElement();
if (!element)
return;
- absl::optional<HeapVector<Member<Element>>> attr_associated_elements =
+ HeapVector<Member<Element>>* attr_associated_elements =
element->GetElementArrayAttribute(qualified_name);
- if (!attr_associated_elements || attr_associated_elements.value().IsEmpty())
+ if (!attr_associated_elements || attr_associated_elements->IsEmpty())
return;
std::vector<int32_t> ax_ids;
- for (const auto& associated_element : attr_associated_elements.value()) {
+ for (const auto& associated_element : *attr_associated_elements) {
AXObject* ax_element =
object->AXObjectCache().GetOrCreate(associated_element);
if (!ax_element)
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc
index e57ff990934..e0e9fcf5404 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc
@@ -4,12 +4,12 @@
#include "third_party/blink/renderer/modules/accessibility/ax_validation_message.h"
+#include "skia/ext/skia_matrix_44.h"
#include "third_party/blink/renderer/core/html/forms/listed_element.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/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
namespace blink {
@@ -25,10 +25,11 @@ bool AXValidationMessage::ComputeAccessibilityIsIgnored(
// TODO(accessibility) Currently we return the bounds of the focused form
// control. If this becomes an issue, return the bounds of the alert itself.
-void AXValidationMessage::GetRelativeBounds(AXObject** out_container,
- FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
- bool* clips_children) const {
+void AXValidationMessage::GetRelativeBounds(
+ AXObject** out_container,
+ FloatRect& out_bounds_in_container,
+ skia::Matrix44& out_container_transform,
+ bool* clips_children) const {
DCHECK(out_container);
*out_container = nullptr;
out_bounds_in_container = FloatRect();
@@ -57,7 +58,10 @@ bool AXValidationMessage::IsOffScreen() const {
}
bool AXValidationMessage::IsVisible() const {
- return RelatedFormControlIfVisible();
+ bool is_visible = RelatedFormControlIfVisible();
+ DCHECK(!is_visible || CachedParentObject() == AXObjectCache().Root())
+ << "A visible validation message's parent must be the root object'.";
+ return is_visible;
}
const AtomicString& AXValidationMessage::LiveRegionStatus() const {
@@ -99,7 +103,7 @@ ListedElement* AXValidationMessage::RelatedFormControlIfVisible() const {
String AXValidationMessage::TextAlternative(
bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom& name_from,
AXRelatedObjectVector* related_objects,
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.h
index 1ac7447753d..f0b2007989f 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_validation_message.h
@@ -30,7 +30,7 @@ class AXValidationMessage final : public AXMockObject {
bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
void GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
- SkMatrix44& out_container_transform,
+ skia::Matrix44& out_container_transform,
bool* clips_children) const override;
const AtomicString& LiveRegionStatus() const override;
const AtomicString& LiveRegionRelevant() const override;
@@ -38,7 +38,7 @@ class AXValidationMessage final : public AXMockObject {
bool IsValidationMessage() const override { return true; }
bool IsVisible() const override;
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom&,
AXRelatedObjectVector*,
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 1de1df6b6b6..a1e46c9f2a7 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
@@ -85,17 +85,18 @@ AccessibleNode* AXVirtualObject::GetAccessibleNode() const {
return accessible_node_;
}
-String AXVirtualObject::TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
- AXObjectSet& visited,
- ax::mojom::NameFrom& name_from,
- AXRelatedObjectVector* related_objects,
- NameSources* name_sources) const {
+String AXVirtualObject::TextAlternative(
+ bool recursive,
+ const AXObject* aria_label_or_description_root,
+ AXObjectSet& visited,
+ ax::mojom::NameFrom& name_from,
+ AXRelatedObjectVector* related_objects,
+ NameSources* name_sources) const {
if (!accessible_node_)
return String();
bool found_text_alternative = false;
- return AriaTextAlternative(recursive, in_aria_labelled_by_traversal, visited,
+ return AriaTextAlternative(recursive, aria_label_or_description_root, visited,
name_from, related_objects, name_sources,
&found_text_alternative);
}
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 3a914ef8e0f..12b4ec789da 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
@@ -30,7 +30,7 @@ class MODULES_EXPORT AXVirtualObject : public AXObject {
bool& result) const override;
AccessibleNode* GetAccessibleNode() const override;
String TextAlternative(bool recursive,
- bool in_aria_labelled_by_traversal,
+ const AXObject* aria_label_or_description_root,
AXObjectSet& visited,
ax::mojom::NameFrom&,
AXRelatedObjectVector*,
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/idls.gni b/chromium/third_party/blink/renderer/modules/accessibility/idls.gni
deleted file mode 100644
index 34bfc1ef92e..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_testing_dependency_idl_files = [ "testing/internals_accessibility.idl" ]
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 4e1c4987559..ee82ead02a5 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
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
@@ -547,7 +548,10 @@ Response InspectorAccessibilityAgent::getPartialAXTree(
LocalFrame* local_frame = document.GetFrame();
if (!local_frame)
return Response::ServerError("Frame is detached.");
- AXContext ax_context(document);
+
+ RetainAXContextForDocument(&document);
+
+ AXContext ax_context(document, ui::kAXModeComplete);
auto& cache = To<AXObjectCacheImpl>(ax_context.GetAXObjectCache());
AXObject* inspected_ax_object = cache.GetOrCreate(dom_node);
@@ -737,12 +741,28 @@ std::unique_ptr<AXNode> InspectorAccessibilityAgent::BuildProtocolAXObject(
return node_object;
}
+LocalFrame* InspectorAccessibilityAgent::FrameFromIdOrRoot(
+ const protocol::Maybe<String>& frame_id) {
+ if (frame_id.isJust()) {
+ return IdentifiersFactory::FrameById(inspected_frames_,
+ frame_id.fromJust());
+ }
+ return inspected_frames_->Root();
+}
+
Response InspectorAccessibilityAgent::getFullAXTree(
protocol::Maybe<int> max_depth,
+ Maybe<String> frame_id,
std::unique_ptr<protocol::Array<AXNode>>* nodes) {
- Document* document = inspected_frames_->Root()->GetDocument();
+ LocalFrame* frame = FrameFromIdOrRoot(frame_id);
+ if (!frame) {
+ return Response::InvalidParams(
+ "Frame with the given frameId is not found.");
+ }
+
+ Document* document = frame->GetDocument();
if (!document)
- return Response::ServerError("No document.");
+ return Response::InternalError();
if (document->View()->NeedsLayout() || document->NeedsLayoutTreeUpdate())
document->UpdateStyleAndLayout(DocumentUpdateReason::kInspector);
@@ -757,7 +777,8 @@ InspectorAccessibilityAgent::WalkAXNodesToDepth(Document* document,
std::unique_ptr<protocol::Array<AXNode>> nodes =
std::make_unique<protocol::Array<protocol::Accessibility::AXNode>>();
- AXContext ax_context(*document);
+ RetainAXContextForDocument(document);
+ AXContext ax_context(*document, ui::kAXModeComplete);
auto& cache = To<AXObjectCacheImpl>(ax_context.GetAXObjectCache());
Deque<std::pair<AXID, int>> id_depths;
@@ -789,27 +810,32 @@ InspectorAccessibilityAgent::WalkAXNodesToDepth(Document* document,
protocol::Response InspectorAccessibilityAgent::getChildAXNodes(
const String& in_id,
+ Maybe<String> frame_id,
std::unique_ptr<protocol::Array<protocol::Accessibility::AXNode>>*
out_nodes) {
if (!enabled_.Get())
return Response::ServerError("Accessibility has not been enabled.");
- // FIXME(aboxhall): specify a document to this and getRootAXNode()
- Document* document = inspected_frames_->Root()->GetDocument();
+ LocalFrame* frame = FrameFromIdOrRoot(frame_id);
+ if (!frame) {
+ return Response::InvalidParams(
+ "Frame with the given frameId is not found.");
+ }
+
+ Document* document = frame->GetDocument();
if (!document)
- return Response::ServerError("No document.");
+ return Response::InternalError();
if (document->View()->NeedsLayout() || document->NeedsLayoutTreeUpdate())
document->UpdateStyleAndLayout(DocumentUpdateReason::kInspector);
- // Since we called enable(), this should exist.
- AXObjectCacheImpl* cache =
- To<AXObjectCacheImpl>(document->ExistingAXObjectCache());
- if (!cache)
- return Response::ServerError("No AXObjectCache.");
+ RetainAXContextForDocument(document);
+ AXContext ax_context(*document, ui::kAXModeComplete);
+
+ auto& cache = To<AXObjectCacheImpl>(ax_context.GetAXObjectCache());
AXID ax_id = in_id.ToUInt();
- AXObject* ax_object = cache->ObjectFromAXID(ax_id);
+ AXObject* ax_object = cache.ObjectFromAXID(ax_id);
if (!ax_object)
return Response::InvalidParams("Invalid ID");
@@ -820,7 +846,7 @@ protocol::Response InspectorAccessibilityAgent::getChildAXNodes(
const AXObject::AXObjectVector& children = ax_object->UnignoredChildren();
for (auto& child_ax_object : children) {
std::unique_ptr<AXNode> child_node = BuildProtocolAXObject(
- *child_ax_object, nullptr, false, *out_nodes, *cache);
+ *child_ax_object, nullptr, false, *out_nodes, cache);
auto grandchild_ids = std::make_unique<protocol::Array<AXNodeId>>();
const AXObject::AXObjectVector& grandchildren =
child_ax_object->UnignoredChildren();
@@ -956,39 +982,52 @@ Response InspectorAccessibilityAgent::queryAXTree(
object_id, root_dom_node);
if (!response.IsSuccess())
return response;
+
+ // Shadow roots are missing from a11y tree.
+ // We start searching the host element instead as a11y tree does not
+ // care about shadow roots.
+ if (root_dom_node->IsShadowRoot()) {
+ root_dom_node = root_dom_node->OwnerShadowHost();
+ }
+ if (!root_dom_node)
+ return Response::InvalidParams("Root DOM node could not be found");
Document& document = root_dom_node->GetDocument();
document.UpdateStyleAndLayout(DocumentUpdateReason::kInspector);
DocumentLifecycle::DisallowTransitionScope disallow_transition(
document.Lifecycle());
- AXContext ax_context(document);
+
+ RetainAXContextForDocument(&document);
+ AXContext ax_context(document, ui::kAXModeComplete);
*nodes = std::make_unique<protocol::Array<protocol::Accessibility::AXNode>>();
auto& cache = To<AXObjectCacheImpl>(ax_context.GetAXObjectCache());
AXObject* root_ax_node = cache.GetOrCreate(root_dom_node);
- auto sought_role = ax::mojom::blink::Role::kUnknown;
- if (role.isJust())
- sought_role = AXObject::AriaRoleStringToRoleEnum(role.fromJust());
const String sought_name = accessible_name.fromMaybe("");
HeapVector<Member<AXObject>> reachable;
- reachable.push_back(root_ax_node);
+ if (root_ax_node)
+ reachable.push_back(root_ax_node);
while (!reachable.IsEmpty()) {
AXObject* ax_object = reachable.back();
reachable.pop_back();
- const AXObject::AXObjectVector& children = ax_object->UnignoredChildren();
+ const AXObject::AXObjectVector& children =
+ ax_object->ChildrenIncludingIgnored();
reachable.AppendRange(children.rbegin(), children.rend());
// if querying by name: skip if name of current object does not match.
if (accessible_name.isJust() && sought_name != ax_object->ComputedName())
continue;
+
// if querying by role: skip if role of current object does not match.
- if (role.isJust() && sought_role != ax_object->RoleValue())
+ if (role.isJust() &&
+ role.fromJust() != AXObject::RoleName(ax_object->RoleValue())) {
continue;
- // both name and role are OK, so we can add current object to the result.
+ }
+ // both name and role are OK, so we can add current object to the result.
if (ax_object->AccessibilityIsIgnored()) {
Node* dom_node = ax_object->GetNode();
std::unique_ptr<AXNode> protocol_node =
@@ -1013,7 +1052,6 @@ void InspectorAccessibilityAgent::EnableAndReset() {
HeapHashSet<Member<InspectorAccessibilityAgent>>>());
}
EnabledAgents().find(frame)->value->insert(this);
- CreateAXContext();
}
protocol::Response InspectorAccessibilityAgent::enable() {
@@ -1026,7 +1064,7 @@ protocol::Response InspectorAccessibilityAgent::disable() {
if (!enabled_.Get())
return Response::Success();
enabled_.Set(false);
- context_ = nullptr;
+ document_to_context_map_.clear();
LocalFrame* frame = inspected_frames_->Root();
DCHECK(EnabledAgents().Contains(frame));
auto it = EnabledAgents().find(frame);
@@ -1045,18 +1083,24 @@ void InspectorAccessibilityAgent::ProvideTo(LocalFrame* frame) {
if (!EnabledAgents().Contains(frame))
return;
for (InspectorAccessibilityAgent* agent : *EnabledAgents().find(frame)->value)
- agent->CreateAXContext();
+ agent->RetainAXContextForDocument(frame->GetDocument());
}
-void InspectorAccessibilityAgent::CreateAXContext() {
- Document* document = inspected_frames_->Root()->GetDocument();
- if (document)
- context_ = std::make_unique<AXContext>(*document);
+void InspectorAccessibilityAgent::RetainAXContextForDocument(
+ Document* document) {
+ if (!enabled_.Get()) {
+ return;
+ }
+ if (!document_to_context_map_.Contains(document)) {
+ document_to_context_map_.insert(
+ document, std::make_unique<AXContext>(*document, ui::kAXModeComplete));
+ }
}
void InspectorAccessibilityAgent::Trace(Visitor* visitor) const {
visitor->Trace(inspected_frames_);
visitor->Trace(dom_agent_);
+ visitor->Trace(document_to_context_map_);
InspectorBaseAgent::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h b/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h
index cce276c7f8d..7ead61ab0fd 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h
@@ -28,7 +28,6 @@ class MODULES_EXPORT InspectorAccessibilityAgent
InspectorAccessibilityAgent(InspectedFrames*, InspectorDOMAgent*);
static void ProvideTo(LocalFrame* frame);
- void CreateAXContext();
// Base agent methods.
void Trace(Visitor*) const override;
@@ -46,10 +45,12 @@ class MODULES_EXPORT InspectorAccessibilityAgent
override;
protocol::Response getFullAXTree(
protocol::Maybe<int> max_depth,
+ protocol::Maybe<String> frame_id,
std::unique_ptr<protocol::Array<protocol::Accessibility::AXNode>>*)
override;
protocol::Response getChildAXNodes(
const String& in_id,
+ protocol::Maybe<String> frame_id,
std::unique_ptr<protocol::Array<protocol::Accessibility::AXNode>>*
out_nodes) override;
protocol::Response queryAXTree(
@@ -116,11 +117,16 @@ class MODULES_EXPORT InspectorAccessibilityAgent
std::unique_ptr<protocol::Array<AXNodeId>>& child_ids,
std::unique_ptr<protocol::Array<AXNode>>& nodes,
AXObjectCacheImpl&) const;
+ LocalFrame* FrameFromIdOrRoot(const protocol::Maybe<String>& frame_id);
+ void RetainAXContextForDocument(Document* document);
Member<InspectedFrames> inspected_frames_;
Member<InspectorDOMAgent> dom_agent_;
InspectorAgentState::Boolean enabled_;
- std::unique_ptr<AXContext> context_;
+
+ // The agent needs to keep AXContext because it enables caching of a11y nodes.
+ HeapHashMap<WeakMember<Document>, std::unique_ptr<AXContext>>
+ document_to_context_map_;
DISALLOW_COPY_AND_ASSIGN(InspectorAccessibilityAgent);
};
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
index d85702c5a8f..402e1a0d8c9 100644
--- 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
@@ -235,7 +235,7 @@ class AXSelectionDeserializer final {
return ax_selections;
}
- for (size_t i = 0; i < foci_->size(); ++i) {
+ for (wtf_size_t i = 0; i < foci_->size(); ++i) {
DCHECK(anchors_->at(i).first);
const Position base(*anchors_->at(i).first, anchors_->at(i).second);
const auto ax_base = AXPosition::FromPosition(base);
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 b8ca5fe7c65..7256c49760e 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
@@ -19,7 +20,7 @@ AccessibilityTest::AccessibilityTest(LocalFrameClient* local_frame_client)
void AccessibilityTest::SetUp() {
RenderingTest::SetUp();
- ax_context_ = std::make_unique<AXContext>(GetDocument());
+ ax_context_ = std::make_unique<AXContext>(GetDocument(), ui::kAXModeComplete);
}
AXObjectCacheImpl& AccessibilityTest::GetAXObjectCache() const {
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/BUILD.gn b/chromium/third_party/blink/renderer/modules/ad_auction/BUILD.gn
index 820b2f7e2c9..22f7b5cbfa4 100644
--- a/chromium/third_party/blink/renderer/modules/ad_auction/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/BUILD.gn
@@ -8,5 +8,21 @@ blink_modules_sources("ad_auction") {
sources = [
"navigator_auction.cc",
"navigator_auction.h",
+ "validate_blink_interest_group.cc",
+ "validate_blink_interest_group.h",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "validate_blink_interest_group_test.cc" ]
+
+ deps = [
+ "//base",
+ "//testing/gtest:gtest",
+ "//third_party/blink/public:test_headers",
+ "//third_party/blink/public/common:headers",
+ "//third_party/blink/renderer/modules:modules",
+ "//url",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/DEPS b/chromium/third_party/blink/renderer/modules/ad_auction/DEPS
new file mode 100644
index 00000000000..f6bde18f96f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/DEPS
@@ -0,0 +1,11 @@
+include_rules = [
+ "+url/url_constants.h",
+]
+
+specific_include_rules = {
+ "validate_blink_interest_group_test.cc": [
+ "+base",
+ "+url/gurl.h",
+ "+url/origin.h",
+ ],
+}
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/DIR_METADATA b/chromium/third_party/blink/renderer/modules/ad_auction/DIR_METADATA
new file mode 100644
index 00000000000..5313345b4ca
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>InterestGroups"
+}
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/idls.gni b/chromium/third_party/blink/renderer/modules/ad_auction/idls.gni
deleted file mode 100644
index 3ed27eec0c2..00000000000
--- a/chromium/third_party/blink/renderer/modules/ad_auction/idls.gni
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "navigator_auction.idl" ]
-
-modules_dictionary_idl_files = [
- "auction_ad_config.idl",
- "auction_ad_interest_group.idl",
- "auction_ad.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc b/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
index 0fba4da4ea8..956a70bb352 100644
--- a/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
@@ -4,11 +4,16 @@
#include "third_party/blink/renderer/modules/ad_auction/navigator_auction.h"
+#include <utility>
+
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_usvstring_usvstringsequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_auction_ad.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_auction_ad_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_auction_ad_interest_group.h"
+#include "third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin_hash.h"
@@ -90,7 +95,8 @@ scoped_refptr<const SecurityOrigin> ParseOrigin(const String& origin_string) {
// joinAdInterestGroup() copy functions.
-bool CopyOwnerFromIdlToMojo(ExceptionState& exception_state,
+bool CopyOwnerFromIdlToMojo(const ExecutionContext& execution_context,
+ ExceptionState& exception_state,
const AuctionAdInterestGroup& input,
mojom::blink::InterestGroup& output) {
scoped_refptr<const SecurityOrigin> owner = ParseOrigin(input.owner());
@@ -101,6 +107,16 @@ bool CopyOwnerFromIdlToMojo(ExceptionState& exception_state,
input.owner().Utf8().c_str(), input.name().Utf8().c_str()));
return false;
}
+
+ if (!execution_context.GetSecurityOrigin()->IsSameOriginWith(owner.get())) {
+ exception_state.ThrowTypeError(String::Format(
+ "owner '%s' for AuctionAdInterestGroup with name '%s' match frame "
+ "origin '%s'.",
+ input.owner().Utf8().c_str(), input.name().Utf8().c_str(),
+ owner->ToString().Utf8().c_str()));
+ return false;
+ }
+
output.owner = std::move(owner);
return true;
}
@@ -256,31 +272,37 @@ bool CopyInterestGroupBuyersFromIdlToMojo(
if (!input.hasInterestGroupBuyers())
return true;
output.interest_group_buyers = mojom::blink::InterestGroupBuyers::New();
- if (input.interestGroupBuyers().IsUSVString()) {
- String maybe_wildcard = input.interestGroupBuyers().GetAsUSVString();
- if (maybe_wildcard != "*") {
- exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
- input, "interestGroupBuyers", maybe_wildcard,
- "must be \"*\" (wildcard) or a list of buyer https origin strings."));
- return false;
- }
- output.interest_group_buyers->set_all_buyers(
- mojom::blink::AllBuyers::New());
- } else {
- DCHECK(input.interestGroupBuyers().IsUSVStringSequence());
- Vector<scoped_refptr<const SecurityOrigin>> buyers;
- for (const auto& buyer_str :
- input.interestGroupBuyers().GetAsUSVStringSequence()) {
- scoped_refptr<const SecurityOrigin> buyer = ParseOrigin(buyer_str);
- if (!buyer) {
+ switch (input.interestGroupBuyers()->GetContentType()) {
+ case V8UnionUSVStringOrUSVStringSequence::ContentType::kUSVString: {
+ const String& maybe_wildcard =
+ input.interestGroupBuyers()->GetAsUSVString();
+ if (maybe_wildcard != "*") {
exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
- input, "interestGroupBuyers buyer", buyer_str,
- "must be a valid https origin."));
+ input, "interestGroupBuyers", maybe_wildcard,
+ "must be \"*\" (wildcard) or a list of buyer https origin "
+ "strings."));
return false;
}
- buyers.push_back(buyer);
+ output.interest_group_buyers->set_all_buyers(
+ mojom::blink::AllBuyers::New());
+ break;
+ }
+ case V8UnionUSVStringOrUSVStringSequence::ContentType::kUSVStringSequence: {
+ Vector<scoped_refptr<const SecurityOrigin>> buyers;
+ for (const auto& buyer_str :
+ input.interestGroupBuyers()->GetAsUSVStringSequence()) {
+ scoped_refptr<const SecurityOrigin> buyer = ParseOrigin(buyer_str);
+ if (!buyer) {
+ exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
+ input, "interestGroupBuyers buyer", buyer_str,
+ "must be a valid https origin."));
+ return false;
+ }
+ buyers.push_back(buyer);
+ }
+ output.interest_group_buyers->set_buyers(std::move(buyers));
+ break;
}
- output.interest_group_buyers->set_buyers(std::move(buyers));
}
return true;
@@ -384,26 +406,42 @@ void NavigatorAuction::joinAdInterestGroup(ScriptState* script_state,
auto mojo_group = mojom::blink::InterestGroup::New();
mojo_group->expiry =
base::Time::Now() + base::TimeDelta::FromSecondsD(duration_seconds);
- if (!CopyOwnerFromIdlToMojo(exception_state, *group, *mojo_group))
+ if (!CopyOwnerFromIdlToMojo(*context, exception_state, *group, *mojo_group))
return;
mojo_group->name = group->name();
if (!CopyBiddingLogicUrlFromIdlToMojo(*context, exception_state, *group,
- *mojo_group))
+ *mojo_group)) {
return;
+ }
if (!CopyDailyUpdateUrlFromIdlToMojo(*context, exception_state, *group,
- *mojo_group))
+ *mojo_group)) {
return;
+ }
if (!CopyTrustedBiddingSignalsUrlFromIdlToMojo(*context, exception_state,
- *group, *mojo_group))
+ *group, *mojo_group)) {
return;
+ }
if (!CopyTrustedBiddingSignalsKeysFromIdlToMojo(*group, *mojo_group))
return;
if (!CopyUserBiddingSignalsFromIdlToMojo(*script_state, exception_state,
- *group, *mojo_group))
+ *group, *mojo_group)) {
return;
+ }
if (!CopyAdsFromIdlToMojo(*context, *script_state, exception_state, *group,
- *mojo_group))
+ *mojo_group)) {
return;
+ }
+
+ String error_field_name;
+ String error_field_value;
+ String error;
+ if (!ValidateBlinkInterestGroup(
+ *mojo_group, error_field_name, error_field_value, error)) {
+ exception_state.ThrowTypeError(ErrorInvalidInterestGroup(
+ *group, error_field_name, error_field_value, error));
+ return;
+ }
+
interest_group_store_->JoinInterestGroup(std::move(mojo_group));
}
@@ -441,6 +479,17 @@ void NavigatorAuction::leaveAdInterestGroup(ScriptState* script_state,
.leaveAdInterestGroup(script_state, group, exception_state);
}
+void NavigatorAuction::updateAdInterestGroups() {
+ interest_group_store_->UpdateAdInterestGroups();
+}
+
+/* static */
+void NavigatorAuction::updateAdInterestGroups(ScriptState* script_state,
+ Navigator& navigator) {
+ return From(ExecutionContext::From(script_state), navigator)
+ .updateAdInterestGroups();
+}
+
ScriptPromise NavigatorAuction::runAdAuction(ScriptState* script_state,
const AuctionAdConfig* config,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.h b/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.h
index f58a2070d3f..ee8d74ddb6e 100644
--- a/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.h
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.h
@@ -47,6 +47,8 @@ class MODULES_EXPORT NavigatorAuction final
Navigator&,
const AuctionAdInterestGroup*,
ExceptionState&);
+ void updateAdInterestGroups();
+ static void updateAdInterestGroups(ScriptState*, Navigator&);
ScriptPromise runAdAuction(ScriptState*,
const AuctionAdConfig*,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl b/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
index 44f95cbb45e..4d7941c6242 100644
--- a/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
@@ -16,6 +16,9 @@
[CallWith=ScriptState, Measure, RaisesException]
void leaveAdInterestGroup(AuctionAdInterestGroup group);
+ [CallWith=ScriptState, Measure]
+ void updateAdInterestGroups();
+
[CallWith=ScriptState, Measure, RaisesException]
Promise<USVString?> runAdAuction(AuctionAdConfig config);
};
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc b/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc
new file mode 100644
index 00000000000..6ff2dbe16d3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc
@@ -0,0 +1,104 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h"
+
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-blink.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 "third_party/blink/renderer/platform/wtf/vector.h"
+#include "url/url_constants.h"
+
+namespace blink {
+
+namespace {
+
+// Check if `url` can be used as an interest group's ad render URL. Ad URLs can
+// be cross origin, unlike other interest group URLs, but are still restricted
+// to HTTPS with no embedded credentials.
+bool IsUrlAllowedForRenderUrls(const KURL& url) {
+ if (!url.IsValid() || !url.ProtocolIs(url::kHttpsScheme))
+ return false;
+
+ return url.User().IsEmpty() && url.Pass().IsEmpty();
+}
+
+// Check if `url` can be used with the specified interest group for any of
+// script URL, update URL, or realtime data URL. Ad render URLs should be
+// checked with IsUrlAllowedForRenderUrls(), which doesn't have the same-origin
+// check, and allows references.
+bool IsUrlAllowed(const KURL& url, const mojom::blink::InterestGroup& group) {
+ if (!group.owner->IsSameOriginWith(SecurityOrigin::Create(url).get()))
+ return false;
+
+ return IsUrlAllowedForRenderUrls(url) && !url.HasFragmentIdentifier();
+}
+
+} // namespace
+
+// The logic in this method must be kept in sync with InterestGroup::IsValid()
+// in blink/common/interest_group/.
+bool ValidateBlinkInterestGroup(const mojom::blink::InterestGroup& group,
+ String& error_field_name,
+ String& error_field_value,
+ String& error) {
+ if (group.owner->Protocol() != url::kHttpsScheme) {
+ error_field_name = String::FromUTF8("owner");
+ error_field_value = group.owner->ToString();
+ error = String::FromUTF8("owner origin must be HTTPS.");
+ return false;
+ }
+
+ if (group.bidding_url && !IsUrlAllowed(*group.bidding_url, group)) {
+ error_field_name = String::FromUTF8("biddingUrl");
+ error_field_value = group.bidding_url->GetString();
+ error = String::FromUTF8(
+ "biddingUrl must have the same origin as the InterestGroup owner "
+ "and have no fragment identifier or embedded credentials.");
+ return false;
+ }
+
+ if (group.update_url && !IsUrlAllowed(*group.update_url, group)) {
+ error_field_name = String::FromUTF8("updateUrl");
+ error_field_value = group.update_url->GetString();
+ error = String::FromUTF8(
+ "updateUrl must have the same origin as the InterestGroup owner "
+ "and have no fragment identifier or embedded credentials.");
+ return false;
+ }
+
+ if (group.trusted_bidding_signals_url) {
+ // In addition to passing the same checks used on the other URLs,
+ // `trusted_bidding_signals_url` must not have a query string, since the
+ // query parameter needs to be set as part of running an auction.
+ if (!IsUrlAllowed(*group.trusted_bidding_signals_url, group) ||
+ !group.trusted_bidding_signals_url->Query().IsEmpty()) {
+ error_field_name = String::FromUTF8("trustedBiddingSignalsUrl");
+ error_field_value = group.trusted_bidding_signals_url->GetString();
+ error = String::FromUTF8(
+ "trustedBiddingSignalsUrl must have the same origin as the "
+ "InterestGroup owner and have no query string, fragment identifier "
+ "or embedded credentials.");
+ return false;
+ }
+ }
+
+ if (group.ads) {
+ for (WTF::wtf_size_t i = 0; i < group.ads.value().size(); ++i) {
+ const KURL& render_url = group.ads.value()[i]->render_url;
+ if (!IsUrlAllowedForRenderUrls(render_url)) {
+ error_field_name = String::Format("ad[%u].renderUrl", i);
+ error_field_value = render_url.GetString();
+ error = String::FromUTF8(
+ "renderUrls must be HTTPS and have no embedded credentials.");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h b/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h
new file mode 100644
index 00000000000..932c18715d8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_AD_AUCTION_VALIDATE_BLINK_INTEREST_GROUP_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_AD_AUCTION_VALIDATE_BLINK_INTEREST_GROUP_H_
+
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-blink-forward.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// Checks that the specified mojom::blink::InterestGroup is valid. Invalid
+// interest groups contain auction or update URLs cross-origin to the owner, or
+// URLs that contain disallowed components (e.g., user/pass). When it returns
+// false, writes information about the error to `error_field_name`,
+// `error_field_value`, and `error`.
+//
+// Checks all provided URLs. Does no validation of expiration time. Does no
+// validation of values expected to be in JSON, since ValidateInterestGroup()
+// does not validate JSON. Must be kept in sync with ValidateInterestGroup(),
+// which performs the exact same logic, except on mojom::InterestGroups, and is
+// used to validate InterestGroups received from a less trusted renderer
+// process.
+MODULES_EXPORT bool ValidateBlinkInterestGroup(
+ const mojom::blink::InterestGroup& group,
+ String& error_field_name,
+ String& error_field_value,
+ String& error);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_AD_AUCTION_VALIDATE_BLINK_INTEREST_GROUP_H_
diff --git a/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc b/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc
new file mode 100644
index 00000000000..ce14a446729
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc
@@ -0,0 +1,392 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/string_piece.h"
+#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
+#include "mojo/public/cpp/bindings/message.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/interest_group/interest_group.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-blink.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.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"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace blink {
+
+namespace {
+
+constexpr char kOriginString[] = "https://origin.test/";
+constexpr char kNameString[] = "name";
+
+} // namespace
+
+// Test fixture for testing both ValidateBlinkInterestGroup() and
+// ValidateInterestGroup(), and making sure they behave the same.
+class ValidateBlinkInterestGroupTest : public testing::Test {
+ public:
+ // Check that `blink_interest_group` is valid, if added from its owner origin.
+ void ExpectInterestGroupIsValid(
+ const mojom::blink::InterestGroupPtr& blink_interest_group) {
+ String error_field_name;
+ String error_field_value;
+ String error;
+ EXPECT_TRUE(ValidateBlinkInterestGroup(
+ *blink_interest_group, error_field_name, error_field_value, error));
+ EXPECT_TRUE(error_field_name.IsNull());
+ EXPECT_TRUE(error_field_value.IsNull());
+ EXPECT_TRUE(error.IsNull());
+
+ EXPECT_TRUE(CanSerializeAndDeserialize(blink_interest_group));
+ }
+
+ // Check that `blink_interest_group` is valid, if added from `blink_origin`,
+ // and returns the provided error values.
+ void ExpectInterestGroupIsNotValid(
+ const mojom::blink::InterestGroupPtr& blink_interest_group,
+ const std::string& expected_error_field_name,
+ const std::string& expected_error_field_value,
+ const std::string& expected_error) {
+ String error_field_name;
+ String error_field_value;
+ String error;
+ EXPECT_FALSE(ValidateBlinkInterestGroup(
+ *blink_interest_group, error_field_name, error_field_value, error));
+ EXPECT_EQ(String::FromUTF8(expected_error_field_name), error_field_name);
+ EXPECT_EQ(String::FromUTF8(expected_error_field_value), error_field_value);
+ EXPECT_EQ(String::FromUTF8(expected_error), error);
+
+ EXPECT_FALSE(CanSerializeAndDeserialize(blink_interest_group));
+ }
+
+ // Tries to Converts a mojom::blink::InterestGroupPtr to a
+ // blink::InterestGroup by using Mojo to serialize and deserialize it. Returns
+ // true on success, false on failure. Failure indicates the traits conversion
+ // logic refused to serialize the InterestGroup, since it was invalid. Based
+ // off of mojo::test::SerializeAndDeserialize(), which can't convert between
+ // blink and non-blink types.
+ bool CanSerializeAndDeserialize(
+ const mojom::blink::InterestGroupPtr& blink_interest_group) {
+ mojo::Message message =
+ mojom::blink::InterestGroup::SerializeAsMessage(&blink_interest_group);
+ mojo::ScopedMessageHandle handle = message.TakeMojoMessage();
+ message = mojo::Message::CreateFromMessageHandle(&handle);
+ DCHECK(!message.IsNull());
+
+ auto interest_group = std::make_unique<blink::InterestGroup>();
+ return mojom::InterestGroup::DeserializeFromMessage(std::move(message),
+ interest_group.get());
+ }
+
+ // Creates and returns a minimally populated mojom::blink::InterestGroup.
+ mojom::blink::InterestGroupPtr CreateMinimalInterestGroup() {
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ mojom::blink::InterestGroup::New();
+ blink_interest_group->owner = kOrigin;
+ blink_interest_group->name = kName;
+ return blink_interest_group;
+ }
+
+ // Creates an interest group with all fields populated with valid values.
+ mojom::blink::InterestGroupPtr CreateFullyPopulatedInterestGroup() {
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateMinimalInterestGroup();
+
+ // Url that's allowed in every field. Populate all portions of the URL that
+ // are allowed in most places.
+ const KURL kAllowedUrl =
+ KURL(String::FromUTF8("https://origin.test/foo?bar"));
+ blink_interest_group->bidding_url = kAllowedUrl;
+ blink_interest_group->update_url = kAllowedUrl;
+
+ // `trusted_bidding_signals_url` doesn't allow query strings, unlike the
+ // above ones.
+ blink_interest_group->trusted_bidding_signals_url =
+ KURL(String::FromUTF8("https://origin.test/foo"));
+
+ blink_interest_group->trusted_bidding_signals_keys.emplace();
+ blink_interest_group->trusted_bidding_signals_keys->push_back(
+ String::FromUTF8("1"));
+ blink_interest_group->trusted_bidding_signals_keys->push_back(
+ String::FromUTF8("2"));
+ blink_interest_group->user_bidding_signals =
+ String::FromUTF8("\"This field isn't actually validated\"");
+
+ // Add two ads. Use different URLs, with references.
+ blink_interest_group->ads.emplace();
+ auto mojo_ad1 = mojom::blink::InterestGroupAd::New();
+ mojo_ad1->render_url =
+ KURL(String::FromUTF8("https://origin.test/foo?bar#baz"));
+ mojo_ad1->metadata =
+ String::FromUTF8("\"This field isn't actually validated\"");
+ blink_interest_group->ads->push_back(std::move(mojo_ad1));
+ auto mojo_ad2 = mojom::blink::InterestGroupAd::New();
+ mojo_ad2->render_url =
+ KURL(String::FromUTF8("https://origin.test/foo?bar#baz2"));
+ blink_interest_group->ads->push_back(std::move(mojo_ad2));
+
+ return blink_interest_group;
+ }
+
+ protected:
+ // SecurityOrigin used as the owner in most tests.
+ const scoped_refptr<const SecurityOrigin> kOrigin =
+ SecurityOrigin::CreateFromString(String::FromUTF8(kOriginString));
+
+ const String kName = String::FromUTF8(kNameString);
+};
+
+// Test behavior with an InterestGroup with as few fields populated as allowed.
+TEST_F(ValidateBlinkInterestGroupTest, MinimallyPopulated) {
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateMinimalInterestGroup();
+ ExpectInterestGroupIsValid(blink_interest_group);
+}
+
+// Test behavior with an InterestGroup with all fields populated with valid
+// values.
+TEST_F(ValidateBlinkInterestGroupTest, FullyPopulated) {
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateFullyPopulatedInterestGroup();
+ ExpectInterestGroupIsValid(blink_interest_group);
+}
+
+// Make sure that non-HTTPS origins are rejected, both as the frame origin, and
+// as the owner. HTTPS frame origins with non-HTTPS owners are currently
+// rejected due to origin mismatch, but once sites can add users to 3P interest
+// groups, they should still be rejected for being non-HTTPS.
+TEST_F(ValidateBlinkInterestGroupTest, NonHttpsOriginRejected) {
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateMinimalInterestGroup();
+ blink_interest_group->owner =
+ SecurityOrigin::CreateFromString(String::FromUTF8("http://origin.test/"));
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group, "owner" /* expected_error_field_name */,
+ "http://origin.test" /* expected_error_field_value */,
+ "owner origin must be HTTPS." /* expected_error */);
+
+ blink_interest_group->owner =
+ SecurityOrigin::CreateFromString(String::FromUTF8("data:,foo"));
+ // Data URLs have opaque origins, which are mapped to the string "null".
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group, "owner" /* expected_error_field_name */,
+ "null" /* expected_error_field_value */,
+ "owner origin must be HTTPS." /* expected_error */);
+}
+
+// Check that `bidding_url`, `update_url`, and `trusted_bidding_signals_url`
+// must be same-origin and HTTPS.
+//
+// Ad URLs do not have to be same origin, so they're checked in a different
+// test.
+TEST_F(ValidateBlinkInterestGroupTest, RejectedUrls) {
+ // Strings when each field has a bad URL, copied from cc file.
+ const char kBadBiddingUrlError[] =
+ "biddingUrl must have the same origin as the InterestGroup owner "
+ "and have no fragment identifier or embedded credentials.";
+ const char kBadUpdateUrlError[] =
+ "updateUrl must have the same origin as the InterestGroup owner "
+ "and have no fragment identifier or embedded credentials.";
+ const char kBadTrustedBiddingSignalsUrlError[] =
+ "trustedBiddingSignalsUrl must have the same origin as the "
+ "InterestGroup owner and have no query string, fragment identifier "
+ "or embedded credentials.";
+
+ // Nested URL schemes, like filesystem URLs, are the only cases where a URL
+ // being same origin with an HTTPS origin does not imply the URL itself is
+ // also HTTPS.
+ const KURL kFileSystemUrl =
+ KURL(String::FromUTF8("filesystem:https://origin.test/foo"));
+ EXPECT_TRUE(
+ kOrigin->IsSameOriginWith(SecurityOrigin::Create(kFileSystemUrl).get()));
+
+ const KURL kRejectedUrls[] = {
+ // HTTP URLs is rejected: it's both the wrong scheme, and cross-origin.
+ KURL(String::FromUTF8("filesystem:http://origin.test/foo")),
+ // Cross origin HTTPS URLs are rejected.
+ KURL(String::FromUTF8("https://origin2.test/foo")),
+ // URL with different ports are cross-origin.
+ KURL(String::FromUTF8("https://origin.test:1234/")),
+ // URLs with opaque origins are cross-origin.
+ KURL(String::FromUTF8("data://text/html,payload")),
+ // Unknown scheme.
+ KURL(String::FromUTF8("unknown-scheme://foo/")),
+
+ // filesystem URLs are rejected, even if they're same-origin with the page
+ // origin.
+ kFileSystemUrl,
+
+ // URLs with user/ports are rejected.
+ KURL(String::FromUTF8("https://user:pass@origin.test/")),
+ // References also aren't allowed, as they aren't sent over HTTP.
+ KURL(String::FromUTF8("https://origin.test/#foopy")),
+
+ // Invalid URLs.
+ KURL(String::FromUTF8("")),
+ KURL(String::FromUTF8("invalid url")),
+ KURL(String::FromUTF8("https://!@#$%^&*()/")),
+ KURL(String::FromUTF8("https://[1::::::2]/")),
+ KURL(String::FromUTF8("https://origin.test/%00")),
+ };
+
+ for (const KURL& rejected_url : kRejectedUrls) {
+ SCOPED_TRACE(rejected_url.GetString());
+
+ // Test `bidding_url`.
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateMinimalInterestGroup();
+ blink_interest_group->bidding_url = rejected_url;
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group, "biddingUrl" /* expected_error_field_name */,
+ rejected_url.GetString().Utf8() /* expected_error_field_value */,
+ kBadBiddingUrlError /* expected_error */);
+
+ // Test `update_url`.
+ blink_interest_group = CreateMinimalInterestGroup();
+ blink_interest_group->update_url = rejected_url;
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group, "updateUrl" /* expected_error_field_name */,
+ rejected_url.GetString().Utf8() /* expected_error_field_value */,
+ // expected_error
+ kBadUpdateUrlError /* expected_error */);
+
+ // Test `trusted_bidding_signals_url`.
+ blink_interest_group = CreateMinimalInterestGroup();
+ blink_interest_group->trusted_bidding_signals_url = rejected_url;
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group,
+ "trustedBiddingSignalsUrl" /* expected_error_field_name */,
+ rejected_url.GetString().Utf8() /* expected_error_field_value */,
+ kBadTrustedBiddingSignalsUrlError /* expected_error */);
+ }
+
+ // `trusted_bidding_signals_url` also can't include query strings.
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateMinimalInterestGroup();
+ KURL rejected_url = KURL(String::FromUTF8("https://origin.test/?query"));
+ blink_interest_group->trusted_bidding_signals_url = rejected_url;
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group,
+ "trustedBiddingSignalsUrl" /* expected_error_field_name */,
+ rejected_url.GetString().Utf8() /* expected_error_field_value */,
+ kBadTrustedBiddingSignalsUrlError /* expected_error */);
+}
+
+// Tests valid and invalid ad render URLs.
+TEST_F(ValidateBlinkInterestGroupTest, AdRenderUrlValidation) {
+ const char kBadAdUrlError[] =
+ "renderUrls must be HTTPS and have no embedded credentials.";
+
+ const struct {
+ bool expect_allowed;
+ const char* url;
+ } kTestCases[] = {
+ // Same origin URLs are allowed.
+ {true, "https://origin.test/foo?bar"},
+
+ // Cross origin URLs are allowed, as long as they're HTTPS.
+ {true, "https://b.test/"},
+ {true, "https://a.test:1234/"},
+
+ // URLs with the wrong scheme are rejected.
+ {false, "http://a.test/"},
+ {false, "data://text/html,payload"},
+ {false, "filesystem:https://a.test/foo"},
+
+ // URLs with user/ports are rejected.
+ {false, "https://user:pass@a.test/"},
+
+ // References are allowed for ads, though not other requests, since they
+ // only have an effect when loading a page in a renderer.
+ {true, "https://a.test/#foopy"},
+ };
+
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(test_case.url);
+
+ KURL test_case_url = KURL(String::FromUTF8(test_case.url));
+
+ // Add an InterestGroup with the test cases's URL as the only ad's URL.
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ CreateMinimalInterestGroup();
+ blink_interest_group->ads.emplace();
+ blink_interest_group->ads->emplace_back(mojom::blink::InterestGroupAd::New(
+ test_case_url, String() /* metadata */));
+ if (test_case.expect_allowed) {
+ ExpectInterestGroupIsValid(blink_interest_group);
+ } else {
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group,
+ "ad[0].renderUrl" /* expected_error_field_name */,
+ test_case_url.GetString().Utf8() /* expected_error_field_value */,
+ kBadAdUrlError /* expected_error */);
+ }
+
+ // Add an InterestGroup with the test cases's URL as the second ad's URL.
+ blink_interest_group = CreateMinimalInterestGroup();
+ blink_interest_group->ads.emplace();
+ blink_interest_group->ads->emplace_back(mojom::blink::InterestGroupAd::New(
+ KURL(String::FromUTF8("https://origin.test/")),
+ String() /* metadata */));
+ blink_interest_group->ads->emplace_back(mojom::blink::InterestGroupAd::New(
+ test_case_url, String() /* metadata */));
+ if (test_case.expect_allowed) {
+ ExpectInterestGroupIsValid(blink_interest_group);
+ } else {
+ ExpectInterestGroupIsNotValid(
+ blink_interest_group,
+ "ad[1].renderUrl" /* expected_error_field_name */,
+ test_case_url.GetString().Utf8() /* expected_error_field_value */,
+ kBadAdUrlError /* expected_error */);
+ }
+ }
+}
+
+// Mojo rejects malformed URLs when converting mojom::blink::InterestGroup to
+// blink::InterestGroup. Since the rejection happens internally in Mojo,
+// typemapping code that invokes blink::InterestGroup::IsValid() isn't run, so
+// adding a AdRenderUrlValidation testcase to verify malformed URLs wouldn't
+// exercise blink::InterestGroup::IsValid(). Since blink::InterestGroup users
+// can call IsValid() directly (i.e when not using Mojo), we need a test that
+// also calls IsValid() directly.
+TEST_F(ValidateBlinkInterestGroupTest, MalformedUrl) {
+ constexpr char kMalformedUrl[] = "https://invalid^";
+
+ // First, check against mojom::blink::InterestGroup.
+ constexpr char kBadAdUrlError[] =
+ "renderUrls must be HTTPS and have no embedded credentials.";
+ mojom::blink::InterestGroupPtr blink_interest_group =
+ mojom::blink::InterestGroup::New();
+ blink_interest_group->owner = kOrigin;
+ blink_interest_group->name = kName;
+ blink_interest_group->ads.emplace();
+ blink_interest_group->ads->emplace_back(mojom::blink::InterestGroupAd::New(
+ KURL(kMalformedUrl), String() /* metadata */));
+ String error_field_name;
+ String error_field_value;
+ String error;
+ EXPECT_FALSE(ValidateBlinkInterestGroup(
+ *blink_interest_group, error_field_name, error_field_value, error));
+ EXPECT_EQ(error_field_name, String::FromUTF8("ad[0].renderUrl"));
+ // The invalid ^ gets escaped.
+ EXPECT_EQ(error_field_value, String::FromUTF8("https://invalid%5E/"));
+ EXPECT_EQ(error, String::FromUTF8(kBadAdUrlError));
+
+ // Now, test against blink::InterestGroup.
+ blink::InterestGroup interest_group;
+ interest_group.owner = url::Origin::Create(GURL(kOriginString));
+ interest_group.name = kNameString;
+ interest_group.ads.emplace();
+ interest_group.ads->emplace_back(
+ blink::InterestGroup::Ad(GURL(kMalformedUrl), /*metadata=*/""));
+ EXPECT_FALSE(interest_group.IsValid());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/OWNERS b/chromium/third_party/blink/renderer/modules/animationworklet/OWNERS
index 759412f561f..e16b20d59cd 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/OWNERS
@@ -2,5 +2,4 @@ flackr@chromium.org
majidvp@chromium.org
# for Worker related changes
-kinuko@chromium.org
nhiroki@chromium.org
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 261f03fb663..cf406eed568 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
@@ -72,10 +72,11 @@ Animator* AnimationWorkletGlobalScope::CreateAnimatorFor(
WorkletAnimationOptions options,
scoped_refptr<SerializedScriptValue> serialized_state,
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings) {
- DCHECK(!animators_.at(animation_id));
- Animator* animator =
- CreateInstance(name, options, serialized_state, local_times, timings);
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings) {
+ DCHECK(!animators_.Contains(animation_id));
+ Animator* animator = CreateInstance(name, options, serialized_state,
+ local_times, timings, normalized_timings);
if (!animator)
return nullptr;
animators_.Set(animation_id, animator);
@@ -107,17 +108,20 @@ void AnimationWorkletGlobalScope::UpdateAnimatorsList(
}
// Down casting to blink type
- Vector<Timing> timings = (static_cast<WorkletAnimationEffectTimings*>(
- animation.effect_timings.get()))
- ->GetTimings()
- ->data;
+ WorkletAnimationEffectTimings* effect_timings =
+ (static_cast<WorkletAnimationEffectTimings*>(
+ animation.effect_timings.get()));
+ Vector<Timing> timings = effect_timings->GetTimings()->data;
DCHECK_GE(timings.size(), 1u);
+ Vector<Timing::NormalizedTiming> normalized_timings =
+ effect_timings->GetNormalizedTimings()->data;
+ DCHECK_GE(normalized_timings.size(), 1u);
Vector<absl::optional<base::TimeDelta>> local_times(
static_cast<int>(timings.size()), absl::nullopt);
CreateAnimatorFor(id, name, options, nullptr /* serialized_state */,
- local_times, timings);
+ local_times, timings, normalized_timings);
}
}
@@ -132,12 +136,15 @@ void AnimationWorkletGlobalScope::UpdateAnimators(
ScriptState::Scope scope(script_state);
for (const auto& animation : input.added_and_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.
// This can only happen if constructing an animator instance has failed
// e.g., the constructor throws an exception.
- if (!animator || !predicate(animator))
+ auto it = animators_.find(animation.worklet_animation_id.animation_id);
+ if (it == animators_.end())
+ continue;
+
+ Animator* animator = it->value;
+ if (!predicate(animator))
continue;
UpdateAnimation(isolate, animator, animation.worklet_animation_id,
@@ -145,10 +152,13 @@ void AnimationWorkletGlobalScope::UpdateAnimators(
}
for (const auto& animation : 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 || !predicate(animator))
+ auto it = animators_.find(animation.worklet_animation_id.animation_id);
+ if (it == animators_.end())
+ continue;
+
+ Animator* animator = it->value;
+ if (!predicate(animator))
continue;
UpdateAnimation(isolate, animator, animation.worklet_animation_id,
@@ -232,7 +242,8 @@ Animator* AnimationWorkletGlobalScope::CreateInstance(
WorkletAnimationOptions options,
scoped_refptr<SerializedScriptValue> serialized_state,
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings) {
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings) {
DCHECK(IsContextThread());
AnimatorDefinition* definition = animator_definitions_.at(name);
if (!definition)
@@ -263,7 +274,7 @@ Animator* AnimationWorkletGlobalScope::CreateInstance(
return MakeGarbageCollected<Animator>(isolate, definition, instance.V8Value(),
name, std::move(options), local_times,
- timings);
+ timings, normalized_timings);
}
bool AnimationWorkletGlobalScope::IsAnimatorStateful(int animation_id) {
@@ -320,14 +331,18 @@ void AnimationWorkletGlobalScope::MigrateAnimatorsTo(
animator->GetLocalTimes(local_times);
target_global_scope->CreateAnimatorFor(
animation_id, animator->name(), animator->options(), serialized_state,
- std::move(local_times), animator->GetTimings());
+ std::move(local_times), animator->GetTimings(),
+ animator->GetNormalizedTimings());
}
animators_.clear();
}
AnimatorDefinition* AnimationWorkletGlobalScope::FindDefinitionForTest(
const String& name) {
- return animator_definitions_.at(name);
+ auto it = animator_definitions_.find(name);
+ if (it != animator_definitions_.end())
+ return it->value;
+ return nullptr;
}
} // namespace blink
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 8465670d41b..dfa168fed12 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
@@ -78,14 +78,16 @@ class MODULES_EXPORT AnimationWorkletGlobalScope : public WorkletGlobalScope {
WorkletAnimationOptions options,
scoped_refptr<SerializedScriptValue> serialized_state,
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings);
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings);
Animator* CreateAnimatorFor(
int animation_id,
const String& name,
WorkletAnimationOptions options,
scoped_refptr<SerializedScriptValue> serialized_state,
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings);
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings);
typedef HeapHashMap<String, Member<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 757a1c4718c..f9012b312d3 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
@@ -62,7 +62,11 @@ std::unique_ptr<AnimationWorkletOutput> ProxyClientMutate(
std::unique_ptr<WorkletAnimationEffectTimings> CreateEffectTimings() {
auto timings = base::MakeRefCounted<base::RefCountedData<Vector<Timing>>>();
timings->data.push_back(Timing());
- return std::make_unique<WorkletAnimationEffectTimings>(std::move(timings));
+ auto normalized_timings = base::MakeRefCounted<
+ base::RefCountedData<Vector<Timing::NormalizedTiming>>>();
+ normalized_timings->data.push_back(Timing::NormalizedTiming());
+ return std::make_unique<WorkletAnimationEffectTimings>(
+ std::move(timings), std::move(normalized_timings));
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc
index 0aa9947c542..ca81f237b02 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc
@@ -148,7 +148,11 @@ class AnimationWorkletProxyClientTest : public RenderingTest {
std::unique_ptr<WorkletAnimationEffectTimings> CreateEffectTimings() {
auto timings = base::MakeRefCounted<base::RefCountedData<Vector<Timing>>>();
timings->data.push_back(Timing());
- return std::make_unique<WorkletAnimationEffectTimings>(std::move(timings));
+ auto normalized_timings = base::MakeRefCounted<
+ base::RefCountedData<Vector<Timing::NormalizedTiming>>>();
+ normalized_timings->data.push_back(Timing::NormalizedTiming());
+ return std::make_unique<WorkletAnimationEffectTimings>(
+ std::move(timings), std::move(normalized_timings));
}
void RunMigrateAnimatorsBetweenGlobalScopesOnWorklet(
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc
index 5425194c65b..5da41684192 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc
@@ -4,13 +4,12 @@
#include "third_party/blink/renderer/modules/animationworklet/animator.h"
-#include "base/stl_util.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_animate_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_state_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_workletanimationeffect_workletgroupeffect.h"
-#include "third_party/blink/renderer/bindings/modules/v8/worklet_animation_effect_or_worklet_group_effect.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/bindings/v8_binding.h"
#include "v8/include/v8.h"
namespace blink {
@@ -21,13 +20,16 @@ Animator::Animator(v8::Isolate* isolate,
const String& name,
WorkletAnimationOptions options,
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings)
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings)
: definition_(definition),
instance_(isolate, instance),
name_(name),
options_(options),
group_effect_(
- MakeGarbageCollected<WorkletGroupEffect>(local_times, timings)) {
+ MakeGarbageCollected<WorkletGroupEffect>(local_times,
+ timings,
+ normalized_timings)) {
DCHECK_GE(local_times.size(), 1u);
}
@@ -49,7 +51,6 @@ bool Animator::Animate(
if (IsUndefinedOrNull(instance))
return false;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionWorkletAnimationEffectOrWorkletGroupEffect* effect = nullptr;
if (group_effect_->getChildren().size() == 1) {
effect =
@@ -60,14 +61,6 @@ bool Animator::Animate(
MakeGarbageCollected<V8UnionWorkletAnimationEffectOrWorkletGroupEffect>(
group_effect_);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WorkletAnimationEffectOrWorkletGroupEffect effect;
- if (group_effect_->getChildren().size() == 1) {
- effect.SetWorkletAnimationEffect(group_effect_->getChildren()[0]);
- } else {
- effect.SetWorkletGroupEffect(group_effect_);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
@@ -90,6 +83,16 @@ Vector<Timing> Animator::GetTimings() const {
return timings;
}
+Vector<Timing::NormalizedTiming> Animator::GetNormalizedTimings() const {
+ Vector<Timing::NormalizedTiming> normalized_timings;
+ normalized_timings.ReserveInitialCapacity(
+ group_effect_->getChildren().size());
+ for (const auto& effect : group_effect_->getChildren()) {
+ normalized_timings.push_back(effect->NormalizedTiming());
+ }
+ return normalized_timings;
+}
+
bool Animator::IsStateful() const {
return definition_->IsStateful();
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator.h b/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
index 33aa2d330f4..009a64194ae 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
@@ -31,8 +31,9 @@ class Animator final : public GarbageCollected<Animator>, public NameClient {
const String& name,
WorkletAnimationOptions options,
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings);
- ~Animator();
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings);
+ ~Animator() final;
void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override { return "Animator"; }
@@ -57,6 +58,7 @@ class Animator final : public GarbageCollected<Animator>, public NameClient {
}
Vector<Timing> GetTimings() const;
+ Vector<Timing::NormalizedTiming> GetNormalizedTimings() const;
bool IsStateful() const;
const String& name() const { return name_; }
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 c7b6efd9b1f..c4c6a9d9894 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
@@ -27,6 +27,7 @@ class MODULES_EXPORT AnimatorDefinition final
explicit AnimatorDefinition(V8AnimatorConstructor* constructor,
V8AnimateCallback* animate,
V8StateCallback* state);
+ ~AnimatorDefinition() override = default;
virtual void Trace(Visitor* visitor) const;
const char* NameInHeapSnapshot() const override {
return "AnimatorDefinition";
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/idls.gni b/chromium/third_party/blink/renderer/modules/animationworklet/idls.gni
deleted file mode 100644
index ea4eccf0cb6..00000000000
--- a/chromium/third_party/blink/renderer/modules/animationworklet/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "animation_worklet_global_scope.idl",
- "worklet_animation_effect.idl",
- "worklet_animation.idl",
- "worklet_group_effect.idl",
-]
-
-modules_dependency_idl_files = [ "css_animation_worklet.idl" ]
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 15704d032f1..5ca152215d6 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -6,12 +6,10 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_animationeffect_animationeffectsequence.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_documenttimeline_scrolltimeline.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
-#include "third_party/blink/renderer/bindings/modules/v8/animation_effect_or_animation_effect_sequence.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
@@ -37,20 +35,13 @@ namespace blink {
namespace {
bool ConvertAnimationEffects(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionAnimationEffectOrAnimationEffectSequence* effects,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AnimationEffectOrAnimationEffectSequence& effects,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<KeyframeEffect>>& keyframe_effects,
String& error_string) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(effects);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(keyframe_effects.IsEmpty());
// Currently we only support KeyframeEffect.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (effects->GetContentType()) {
case V8UnionAnimationEffectOrAnimationEffectSequence::ContentType::
kAnimationEffect: {
@@ -80,29 +71,6 @@ bool ConvertAnimationEffects(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (effects.IsAnimationEffect()) {
- auto* const effect = effects.GetAsAnimationEffect();
- auto* key_frame = DynamicTo<KeyframeEffect>(effect);
- if (!key_frame) {
- error_string = "Effect must be a KeyframeEffect object";
- return false;
- }
- keyframe_effects.push_back(key_frame);
- } else {
- const HeapVector<Member<AnimationEffect>>& effect_sequence =
- effects.GetAsAnimationEffectSequence();
- keyframe_effects.ReserveInitialCapacity(effect_sequence.size());
- for (const auto& effect : effect_sequence) {
- auto* key_frame = DynamicTo<KeyframeEffect>(*effect);
- if (!key_frame) {
- error_string = "Effects must all be KeyframeEffect objects";
- return false;
- }
- keyframe_effects.push_back(key_frame);
- }
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (keyframe_effects.IsEmpty()) {
error_string = "Effects array must be non-empty";
@@ -133,7 +101,6 @@ bool IsActive(const Animation::AnimationPlayState& state) {
}
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool ValidateTimeline(const V8UnionDocumentTimelineOrScrollTimeline* timeline,
String& error_string) {
if (!timeline)
@@ -148,22 +115,7 @@ bool ValidateTimeline(const V8UnionDocumentTimelineOrScrollTimeline* timeline,
}
return true;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool ValidateTimeline(const DocumentTimelineOrScrollTimeline& timeline,
- String& error_string) {
- if (timeline.IsScrollTimeline()) {
- DoubleOrScrollTimelineAutoKeyword time_range;
- timeline.GetAsScrollTimeline()->timeRange(time_range);
- if (time_range.IsScrollTimelineAutoKeyword()) {
- error_string = "ScrollTimeline timeRange must have non-auto value";
- return false;
- }
- }
- return true;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AnimationTimeline* ConvertAnimationTimeline(
const Document& document,
const V8UnionDocumentTimelineOrScrollTimeline* timeline) {
@@ -179,19 +131,6 @@ AnimationTimeline* ConvertAnimationTimeline(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-AnimationTimeline* ConvertAnimationTimeline(
- const Document& document,
- const DocumentTimelineOrScrollTimeline& timeline) {
- if (timeline.IsScrollTimeline())
- return timeline.GetAsScrollTimeline();
-
- if (timeline.IsDocumentTimeline())
- return timeline.GetAsDocumentTimeline();
-
- return &document.Timeline();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool CheckElementComposited(const Node& target) {
return target.GetLayoutObject() &&
@@ -256,9 +195,9 @@ absl::optional<base::TimeDelta> CalculateStartTime(
return base::TimeDelta::FromMillisecondsD(timeline_current_time_ms.value()) -
(current_time / playback_rate);
}
+
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WorkletAnimation* WorkletAnimation::Create(
ScriptState* script_state,
const String& animator_name,
@@ -267,19 +206,7 @@ WorkletAnimation* WorkletAnimation::Create(
return Create(script_state, animator_name, effects, nullptr, ScriptValue(),
exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WorkletAnimation* WorkletAnimation::Create(
- ScriptState* script_state,
- String animator_name,
- const AnimationEffectOrAnimationEffectSequence& effects,
- ExceptionState& exception_state) {
- return Create(script_state, animator_name, effects,
- DocumentTimelineOrScrollTimeline(), ScriptValue(),
- exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WorkletAnimation* WorkletAnimation::Create(
ScriptState* script_state,
const String& animator_name,
@@ -289,29 +216,12 @@ WorkletAnimation* WorkletAnimation::Create(
return Create(script_state, animator_name, effects, timeline, ScriptValue(),
exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WorkletAnimation* WorkletAnimation::Create(
- ScriptState* script_state,
- String animator_name,
- const AnimationEffectOrAnimationEffectSequence& effects,
- DocumentTimelineOrScrollTimeline timeline,
- ExceptionState& exception_state) {
- return Create(script_state, animator_name, effects, timeline, ScriptValue(),
- exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WorkletAnimation* WorkletAnimation::Create(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& animator_name,
const V8UnionAnimationEffectOrAnimationEffectSequence* effects,
const V8UnionDocumentTimelineOrScrollTimeline* timeline,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- String animator_name,
- const AnimationEffectOrAnimationEffectSequence& effects,
- DocumentTimelineOrScrollTimeline timeline,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ScriptValue& options,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
@@ -389,14 +299,20 @@ WorkletAnimation::WorkletAnimation(
auto timings = base::MakeRefCounted<base::RefCountedData<Vector<Timing>>>();
timings->data.ReserveInitialCapacity(effects_.size());
+ auto normalized_timings = base::MakeRefCounted<
+ base::RefCountedData<Vector<Timing::NormalizedTiming>>>();
+ normalized_timings->data.ReserveInitialCapacity(effects_.size());
+
DCHECK_GE(effects_.size(), 1u);
for (auto& effect : effects_) {
AnimationEffect* target_effect = effect;
target_effect->Attach(this);
local_times_.push_back(absl::nullopt);
timings->data.push_back(target_effect->SpecifiedTiming());
+ normalized_timings->data.push_back(target_effect->NormalizedTiming());
}
- effect_timings_ = std::make_unique<WorkletAnimationEffectTimings>(timings);
+ effect_timings_ = std::make_unique<WorkletAnimationEffectTimings>(
+ timings, normalized_timings);
if (timeline_->IsScrollTimeline())
To<ScrollTimeline>(*timeline_).WorkletAnimationAttached();
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 316e4dab887..a1be789b410 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
#include "third_party/abseil-cpp/absl/types/optional.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"
@@ -21,7 +20,6 @@
namespace blink {
-class AnimationEffectOrAnimationEffectSequence;
class ScriptValue;
class SerializedScriptValue;
class V8UnionAnimationEffectOrAnimationEffectSequence;
@@ -46,7 +44,6 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
USING_PRE_FINALIZER(WorkletAnimation, Dispose);
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static WorkletAnimation* Create(
ScriptState* script_state,
const String& animator_name,
@@ -65,26 +62,6 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
const V8UnionDocumentTimelineOrScrollTimeline* timeline,
const ScriptValue& options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- 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,
- const ScriptValue& options,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WorkletAnimation(WorkletAnimationId id,
const String& animator_name,
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
index 5f4275c9fbe..14c0a7cc9d3 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
@@ -10,9 +10,11 @@ namespace blink {
WorkletAnimationEffect::WorkletAnimationEffect(
absl::optional<base::TimeDelta> local_time,
- const Timing& specified_timing)
+ const Timing& specified_timing,
+ const Timing::NormalizedTiming& normalized_timing)
: local_time_(local_time),
specified_timing_(specified_timing),
+ normalized_timing_(normalized_timing),
calculated_() {
specified_timing_.AssertValid();
}
@@ -36,11 +38,11 @@ ComputedEffectTiming* WorkletAnimationEffect::getComputedTiming() const {
local_time = AnimationTimeDelta(local_time_.value());
}
calculated_ = specified_timing_.CalculateTimings(
- local_time, absl::nullopt, Timing::AnimationDirection::kForwards, false,
- playback_rate);
+ local_time, absl::nullopt, normalized_timing_,
+ Timing::AnimationDirection::kForwards, false, playback_rate);
}
- return specified_timing_.getComputedTiming(calculated_,
+ return specified_timing_.getComputedTiming(calculated_, normalized_timing_,
/*is_keyframe_effect*/ false);
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.h b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.h
index 944b7edb28e..268d48fca62 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_EFFECT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_EFFECT_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -19,15 +20,20 @@ class MODULES_EXPORT WorkletAnimationEffect : public ScriptWrappable {
public:
WorkletAnimationEffect(absl::optional<base::TimeDelta> local_time,
- const Timing& timing);
+ const Timing& timing,
+ const Timing::NormalizedTiming& normalized_timing);
// Because getTiming needs to be used below, SpecifiedTiming will be used to
// return the specified Timing object given at initialization
const Timing& SpecifiedTiming() { return specified_timing_; }
+ const Timing::NormalizedTiming& NormalizedTiming() {
+ return normalized_timing_;
+ }
// This function is named getTiming() as opposed to getEffectTiming() because
// that is how it is defined in worklet_animation_effect.idl
EffectTiming* getTiming() const;
+
ComputedEffectTiming* getComputedTiming() const;
absl::optional<double> localTime() const;
@@ -42,6 +48,7 @@ class MODULES_EXPORT WorkletAnimationEffect : public ScriptWrappable {
// above function call getTiming() which returns a pointer to an EffectTiming
// object, as is defined in worklet_animation_effect.idl.
const Timing specified_timing_;
+ const Timing::NormalizedTiming normalized_timing_;
mutable Timing::CalculatedTiming calculated_;
// last_update_time_ has type base::TimeDelta to match the type of local_time_
// since it is a cached value of local_time_
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.cc b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.cc
index 852ec236eed..72ef0155194 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.cc
@@ -7,12 +7,15 @@
namespace blink {
WorkletAnimationEffectTimings::WorkletAnimationEffectTimings(
- scoped_refptr<base::RefCountedData<Vector<Timing>>> timings)
- : timings_(timings) {}
+ scoped_refptr<base::RefCountedData<Vector<Timing>>> timings,
+ scoped_refptr<base::RefCountedData<Vector<Timing::NormalizedTiming>>>
+ normalized_timings)
+ : timings_(timings), normalized_timings_(normalized_timings) {}
std::unique_ptr<cc::AnimationEffectTimings>
WorkletAnimationEffectTimings::Clone() const {
- return std::make_unique<WorkletAnimationEffectTimings>(timings_);
+ return std::make_unique<WorkletAnimationEffectTimings>(timings_,
+ normalized_timings_);
}
WorkletAnimationEffectTimings::~WorkletAnimationEffectTimings() {}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h
index c71c4d6415c..d253fda9b31 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h
@@ -15,7 +15,8 @@ class MODULES_EXPORT WorkletAnimationEffectTimings final
: public cc::AnimationEffectTimings {
public:
explicit WorkletAnimationEffectTimings(
- scoped_refptr<base::RefCountedData<Vector<Timing>>>);
+ scoped_refptr<base::RefCountedData<Vector<Timing>>>,
+ scoped_refptr<base::RefCountedData<Vector<Timing::NormalizedTiming>>>);
std::unique_ptr<cc::AnimationEffectTimings> Clone() const override;
@@ -24,9 +25,15 @@ class MODULES_EXPORT WorkletAnimationEffectTimings final
const scoped_refptr<base::RefCountedData<Vector<Timing>>>& GetTimings() {
return timings_;
}
+ const scoped_refptr<base::RefCountedData<Vector<Timing::NormalizedTiming>>>&
+ GetNormalizedTimings() {
+ return normalized_timings_;
+ }
private:
scoped_refptr<base::RefCountedData<Vector<Timing>>> timings_;
+ scoped_refptr<base::RefCountedData<Vector<Timing::NormalizedTiming>>>
+ normalized_timings_;
};
} // namespace blink
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 e396e8327ad..15e5a516234 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
@@ -10,18 +10,18 @@
#include "base/time/time_delta_from_string.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_animationeffect_animationeffectsequence.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_documenttimeline_scrolltimeline.h"
-#include "third_party/blink/renderer/bindings/modules/v8/animation_effect_or_animation_effect_sequence.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.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/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/document.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"
@@ -68,7 +68,6 @@ WorkletAnimation* CreateWorkletAnimation(
Element* element,
const String& animator_name,
ScrollTimeline* scroll_timeline = nullptr) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* effects =
MakeGarbageCollected<V8UnionAnimationEffectOrAnimationEffectSequence>(
CreateKeyframeEffect(element));
@@ -77,14 +76,6 @@ WorkletAnimation* CreateWorkletAnimation(
timeline = MakeGarbageCollected<V8UnionDocumentTimelineOrScrollTimeline>(
scroll_timeline);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- AnimationEffectOrAnimationEffectSequence effects;
- AnimationEffect* effect = CreateKeyframeEffect(element);
- effects.SetAnimationEffect(effect);
- DocumentTimelineOrScrollTimeline timeline;
- if (scroll_timeline)
- timeline.SetScrollTimeline(scroll_timeline);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptValue options;
ScriptState::Scope scope(script_state);
@@ -212,8 +203,8 @@ TEST_F(WorkletAnimationTest,
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -329,8 +320,8 @@ TEST_F(WorkletAnimationTest, ScrollTimelineSetPlaybackRate) {
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -383,8 +374,8 @@ TEST_F(WorkletAnimationTest, ScrollTimelineSetPlaybackRateWhilePlaying) {
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
ScrollTimeline* scroll_timeline =
@@ -432,8 +423,8 @@ TEST_F(WorkletAnimationTest, ScrollTimelineNewlyActive) {
Element* scroller_element = GetElementById("scroller");
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(scroller_element);
ScrollTimeline* scroll_timeline =
@@ -489,8 +480,8 @@ TEST_F(WorkletAnimationTest, ScrollTimelineNewlyInactive) {
Element* scroller_element = GetElementById("scroller");
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ auto* time_range =
+ MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(100);
options->setTimeRange(time_range);
options->setScrollSource(scroller_element);
ScrollTimeline* scroll_timeline =
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.cc b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.cc
index 968a35cf328..f7a82660a39 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.cc
@@ -8,14 +8,16 @@ namespace blink {
WorkletGroupEffect::WorkletGroupEffect(
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings) {
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings) {
DCHECK_GE(local_times.size(), 1u);
DCHECK_EQ(local_times.size(), timings.size());
+ DCHECK_EQ(local_times.size(), normalized_timings.size());
effects_.ReserveInitialCapacity(timings.size());
for (int i = 0; i < static_cast<int>(local_times.size()); i++) {
effects_.push_back(MakeGarbageCollected<WorkletAnimationEffect>(
- local_times[i], timings[i]));
+ local_times[i], timings[i], normalized_timings[i]));
}
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.h b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.h
index a0c8fa2e19d..8cf1289d49d 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_group_effect.h
@@ -19,7 +19,8 @@ class MODULES_EXPORT WorkletGroupEffect : public ScriptWrappable {
public:
explicit WorkletGroupEffect(
const Vector<absl::optional<base::TimeDelta>>& local_times,
- const Vector<Timing>& timings);
+ const Vector<Timing>& timings,
+ const Vector<Timing::NormalizedTiming>& normalized_timings);
const HeapVector<Member<WorkletAnimationEffect>>& getChildren() {
return effects_;
}
diff --git a/chromium/third_party/blink/renderer/modules/app_banner/idls.gni b/chromium/third_party/blink/renderer/modules/app_banner/idls.gni
deleted file mode 100644
index e89d9712f90..00000000000
--- a/chromium/third_party/blink/renderer/modules/app_banner/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "before_install_prompt_event.idl" ]
-
-modules_dictionary_idl_files = [
- "app_banner_prompt_result.idl",
- "before_install_prompt_event_init.idl",
-]
-
-modules_dependency_idl_files = [ "window_installation.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/audio_output_devices/idls.gni b/chromium/third_party/blink/renderer/modules/audio_output_devices/idls.gni
deleted file mode 100644
index 4af27b2c208..00000000000
--- a/chromium/third_party/blink/renderer/modules/audio_output_devices/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "html_media_element_audio_output_device.idl" ]
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 ee5afec0bde..f246ea9ddaf 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
@@ -9,10 +9,9 @@
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.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/core/v8/v8_union_request_requestorusvstringsequence_usvstring.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/bindings/core/v8/v8_union_request_usvstring.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_background_fetch_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_resource.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -51,11 +50,6 @@ namespace {
const char kEmptyRequestSequenceErrorMessage[] =
"At least one request must be given.";
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// Message for the TypeError thrown when a null request is seen.
-const char kNullRequestErrorMessage[] = "Requests must not be null.";
-#endif // !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
ScriptPromise RejectWithTypeError(ScriptState* script_state,
const KURL& request_url,
const String& reason,
@@ -164,11 +158,7 @@ BackgroundFetchManager::BackgroundFetchManager(
ScriptPromise BackgroundFetchManager::fetch(
ScriptState* script_state,
const String& id,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionRequestInfoOrRequestOrUSVStringSequence* requests,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestOrUSVStringOrRequestOrUSVStringSequence& requests,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const BackgroundFetchOptions* options,
ExceptionState& exception_state) {
if (!registration_->active()) {
@@ -387,7 +377,6 @@ ScriptPromise BackgroundFetchManager::get(ScriptState* script_state,
return promise;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
Vector<mojom::blink::FetchAPIRequestPtr>
BackgroundFetchManager::CreateFetchAPIRequestVector(
@@ -463,83 +452,6 @@ BackgroundFetchManager::CreateFetchAPIRequestVector(
return fetch_api_requests;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-Vector<mojom::blink::FetchAPIRequestPtr>
-BackgroundFetchManager::CreateFetchAPIRequestVector(
- ScriptState* script_state,
- const RequestOrUSVStringOrRequestOrUSVStringSequence& requests,
- ExceptionState& exception_state,
- bool* has_requests_with_body) {
- DCHECK(has_requests_with_body);
-
- Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests;
- *has_requests_with_body = false;
-
- if (requests.IsRequestOrUSVStringSequence()) {
- HeapVector<RequestOrUSVString> request_vector =
- requests.GetAsRequestOrUSVStringSequence();
-
- // Throw a TypeError when the developer has passed an empty sequence.
- if (!request_vector.size()) {
- exception_state.ThrowTypeError(kEmptyRequestSequenceErrorMessage);
- return Vector<mojom::blink::FetchAPIRequestPtr>();
- }
-
- fetch_api_requests.resize(request_vector.size());
-
- for (wtf_size_t i = 0; i < request_vector.size(); ++i) {
- const RequestOrUSVString& request_or_url = request_vector[i];
-
- Request* request = nullptr;
- if (request_or_url.IsRequest()) {
- request = request_or_url.GetAsRequest();
- } else if (request_or_url.IsUSVString()) {
- request = Request::Create(script_state, request_or_url.GetAsUSVString(),
- exception_state);
- if (exception_state.HadException())
- return Vector<mojom::blink::FetchAPIRequestPtr>();
- } else {
- exception_state.ThrowTypeError(kNullRequestErrorMessage);
- return Vector<mojom::blink::FetchAPIRequestPtr>();
- }
-
- DCHECK(request);
- *has_requests_with_body |= request->HasBody();
- fetch_api_requests[i] = request->CreateFetchAPIRequest();
- fetch_api_requests[i]->blob = ExtractBlobHandle(request, exception_state);
- if (exception_state.HadException())
- return Vector<mojom::blink::FetchAPIRequestPtr>();
- }
- } else if (requests.IsRequest()) {
- auto* request = requests.GetAsRequest();
- DCHECK(request);
-
- *has_requests_with_body = request->HasBody();
- fetch_api_requests.resize(1);
- fetch_api_requests[0] = request->CreateFetchAPIRequest();
- fetch_api_requests[0]->blob =
- ExtractBlobHandle(requests.GetAsRequest(), exception_state);
- if (exception_state.HadException())
- return Vector<mojom::blink::FetchAPIRequestPtr>();
- } else if (requests.IsUSVString()) {
- Request* request = Request::Create(script_state, requests.GetAsUSVString(),
- exception_state);
- if (exception_state.HadException())
- return Vector<mojom::blink::FetchAPIRequestPtr>();
-
- DCHECK(request);
- *has_requests_with_body = request->HasBody();
- fetch_api_requests.resize(1);
- fetch_api_requests[0] = request->CreateFetchAPIRequest();
- } else {
- exception_state.ThrowTypeError(kNullRequestErrorMessage);
- return Vector<mojom::blink::FetchAPIRequestPtr>();
- }
-
- return fetch_api_requests;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void BackgroundFetchManager::DidGetRegistration(
ScriptPromiseResolver* resolver,
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h
index abe70781d6d..330468c4d36 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h
@@ -24,7 +24,6 @@ class BackgroundFetchIconLoader;
class BackgroundFetchOptions;
class BackgroundFetchRegistration;
class ExceptionState;
-class RequestOrUSVStringOrRequestOrUSVStringSequence;
class ScriptPromiseResolver;
class ScriptState;
class ServiceWorkerRegistration;
@@ -44,11 +43,7 @@ class MODULES_EXPORT BackgroundFetchManager final
ScriptPromise fetch(
ScriptState* script_state,
const String& id,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionRequestInfoOrRequestOrUSVStringSequence* requests,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestOrUSVStringOrRequestOrUSVStringSequence& requests,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const BackgroundFetchOptions* options,
ExceptionState& exception_state);
ScriptPromise get(ScriptState* script_state,
@@ -69,11 +64,7 @@ class MODULES_EXPORT BackgroundFetchManager final
// |has_requests_with_body| will be set if any of the |requests| has a body.
static Vector<mojom::blink::FetchAPIRequestPtr> CreateFetchAPIRequestVector(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionRequestInfoOrRequestOrUSVStringSequence* requests,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestOrUSVStringOrRequestOrUSVStringSequence& requests,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state,
bool* has_requests_with_body);
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 a0daf6ce000..5b5757a212d 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,12 +5,11 @@
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h"
#include "testing/gtest/include/gtest/gtest.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/core/v8/v8_request_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_request_requestorusvstringsequence_usvstring.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/bindings/core/v8/v8_union_request_usvstring.h"
#include "third_party/blink/renderer/core/fetch/request.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -25,11 +24,7 @@ class BackgroundFetchManagerTest : public testing::Test {
// declarations necessary in the BackgroundFetchManager.
Vector<mojom::blink::FetchAPIRequestPtr> CreateFetchAPIRequestVector(
V8TestingScope& scope,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionRequestInfoOrRequestOrUSVStringSequence* requests
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestOrUSVStringOrRequestOrUSVStringSequence& requests
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
bool has_requests_with_body;
return BackgroundFetchManager::CreateFetchAPIRequestVector(
@@ -38,41 +33,14 @@ class BackgroundFetchManagerTest : public testing::Test {
}
};
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#define MAYBE_NullValue DISABLED_NullValue
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#define MAYBE_NullValue NullValue
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-TEST_F(BackgroundFetchManagerTest, MAYBE_NullValue) {
- V8TestingScope scope;
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- V8UnionRequestInfoOrRequestOrUSVStringSequence* requests = nullptr;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVStringOrRequestOrUSVStringSequence requests;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
- CreateFetchAPIRequestVector(scope, requests);
- ASSERT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(scope.GetExceptionState().CodeAs<ESErrorType>(),
- ESErrorType::kTypeError);
-}
-
TEST_F(BackgroundFetchManagerTest, SingleUSVString) {
V8TestingScope scope;
KURL image_url("https://www.example.com/my_image.png");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* requests =
MakeGarbageCollected<V8UnionRequestInfoOrRequestOrUSVStringSequence>(
image_url.GetString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVStringOrRequestOrUSVStringSequence requests =
- RequestOrUSVStringOrRequestOrUSVStringSequence::FromUSVString(
- image_url.GetString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
CreateFetchAPIRequestVector(scope, requests);
@@ -96,14 +64,9 @@ TEST_F(BackgroundFetchManagerTest, SingleRequest) {
ASSERT_FALSE(scope.GetExceptionState().HadException());
ASSERT_TRUE(request);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* requests =
MakeGarbageCollected<V8UnionRequestInfoOrRequestOrUSVStringSequence>(
request);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVStringOrRequestOrUSVStringSequence requests =
- RequestOrUSVStringOrRequestOrUSVStringSequence::FromRequest(request);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
CreateFetchAPIRequestVector(scope, requests);
@@ -121,17 +84,10 @@ TEST_F(BackgroundFetchManagerTest, Sequence) {
KURL icon_url("https://www.example.com/my_icon.jpg");
KURL cat_video_url("https://www.example.com/my_cat_video.avi");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* image_request =
MakeGarbageCollected<V8UnionRequestOrUSVString>(image_url.GetString());
auto* icon_request =
MakeGarbageCollected<V8UnionRequestOrUSVString>(icon_url.GetString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVString image_request =
- RequestOrUSVString::FromUSVString(image_url.GetString());
- RequestOrUSVString icon_request =
- RequestOrUSVString::FromUSVString(icon_url.GetString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
RequestInit* request_init = RequestInit::Create();
request_init->setMethod("DELETE");
@@ -141,32 +97,17 @@ TEST_F(BackgroundFetchManagerTest, Sequence) {
ASSERT_FALSE(scope.GetExceptionState().HadException());
ASSERT_TRUE(request);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* cat_video_request =
MakeGarbageCollected<V8UnionRequestOrUSVString>(request);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVString cat_video_request =
- RequestOrUSVString::FromRequest(request);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionRequestOrUSVString>> request_sequence;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<RequestOrUSVString> request_sequence;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
request_sequence.push_back(image_request);
request_sequence.push_back(icon_request);
request_sequence.push_back(cat_video_request);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* requests =
MakeGarbageCollected<V8UnionRequestInfoOrRequestOrUSVStringSequence>(
request_sequence);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVStringOrRequestOrUSVStringSequence requests =
- RequestOrUSVStringOrRequestOrUSVStringSequence::
- FromRequestOrUSVStringSequence(request_sequence);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
CreateFetchAPIRequestVector(scope, requests);
@@ -186,63 +127,10 @@ TEST_F(BackgroundFetchManagerTest, Sequence) {
TEST_F(BackgroundFetchManagerTest, SequenceEmpty) {
V8TestingScope scope;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<Member<V8UnionRequestOrUSVString>> request_sequence;
- auto* requests =
- MakeGarbageCollected<V8UnionRequestInfoOrRequestOrUSVStringSequence>(
- request_sequence);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<RequestOrUSVString> request_sequence;
- RequestOrUSVStringOrRequestOrUSVStringSequence requests =
- RequestOrUSVStringOrRequestOrUSVStringSequence::
- FromRequestOrUSVStringSequence(request_sequence);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
- CreateFetchAPIRequestVector(scope, requests);
- ASSERT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(scope.GetExceptionState().CodeAs<ESErrorType>(),
- ESErrorType::kTypeError);
-}
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#define MAYBE_SequenceWithNullValue DISABLED_SequenceWithNullValue
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#define MAYBE_SequenceWithNullValue SequenceWithNullValue
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-TEST_F(BackgroundFetchManagerTest, MAYBE_SequenceWithNullValue) {
- V8TestingScope scope;
-
- KURL image_url("https://www.example.com/my_image.png");
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- auto* image_request =
- MakeGarbageCollected<V8UnionRequestOrUSVString>(image_url.GetString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVString null_request;
- RequestOrUSVString image_request =
- RequestOrUSVString::FromUSVString(image_url.GetString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionRequestOrUSVString>> request_sequence;
- request_sequence.push_back(image_request);
- request_sequence.push_back(nullptr);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<RequestOrUSVString> request_sequence;
- request_sequence.push_back(image_request);
- request_sequence.push_back(null_request);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* requests =
MakeGarbageCollected<V8UnionRequestInfoOrRequestOrUSVStringSequence>(
request_sequence);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVStringOrRequestOrUSVStringSequence requests =
- RequestOrUSVStringOrRequestOrUSVStringSequence::
- FromRequestOrUSVStringSequence(request_sequence);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
CreateFetchAPIRequestVector(scope, requests);
@@ -271,35 +159,18 @@ TEST_F(BackgroundFetchManagerTest, BlobsExtracted) {
ASSERT_TRUE(image_request->HasBody());
// Create second request without a body.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* icon_request =
MakeGarbageCollected<V8UnionRequestOrUSVString>(icon_url.GetString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVString icon_request =
- RequestOrUSVString::FromUSVString(icon_url.GetString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Create a request sequence with both requests.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionRequestOrUSVString>> request_sequence;
request_sequence.push_back(
MakeGarbageCollected<V8UnionRequestOrUSVString>(image_request));
request_sequence.push_back(icon_request);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<RequestOrUSVString> request_sequence;
- request_sequence.push_back(RequestOrUSVString::FromRequest(image_request));
- request_sequence.push_back(icon_request);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* requests =
MakeGarbageCollected<V8UnionRequestInfoOrRequestOrUSVStringSequence>(
request_sequence);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestOrUSVStringOrRequestOrUSVStringSequence requests =
- RequestOrUSVStringOrRequestOrUSVStringSequence::
- FromRequestOrUSVStringSequence(request_sequence);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Extract the blobs.
Vector<mojom::blink::FetchAPIRequestPtr> fetch_api_requests =
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 1f13a4316d6..7f04b14ca1d 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
@@ -148,69 +148,37 @@ ScriptPromise BackgroundFetchRegistration::abort(ScriptState* script_state) {
ScriptPromise BackgroundFetchRegistration::match(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* request,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestOrUSVString& request,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const CacheQueryOptions* options,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return MatchImpl(script_state, request,
mojom::blink::CacheQueryOptions::From(options),
exception_state,
/* match_all = */ false);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return MatchImpl(
- script_state, absl::make_optional<RequestOrUSVString>(request),
- mojom::blink::CacheQueryOptions::From(options), exception_state,
- /* match_all = */ false);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
ScriptPromise BackgroundFetchRegistration::matchAll(
ScriptState* script_state,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return MatchImpl(script_state, /* request = */ nullptr,
/* cache_query_options = */ nullptr, exception_state,
/* match_all = */ true);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return MatchImpl(script_state, /* request = */ absl::nullopt,
- /* cache_query_options = */ nullptr, exception_state,
- /* match_all = */ true);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
ScriptPromise BackgroundFetchRegistration::matchAll(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* request,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestOrUSVString& request,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const CacheQueryOptions* options,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return MatchImpl(script_state, request,
mojom::blink::CacheQueryOptions::From(options),
exception_state,
/* match_all = */ true);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return MatchImpl(
- script_state, absl::make_optional<RequestOrUSVString>(request),
- mojom::blink::CacheQueryOptions::From(options), exception_state,
- /* match_all = */ true);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
ScriptPromise BackgroundFetchRegistration::MatchImpl(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* request,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- absl::optional<RequestOrUSVString> request,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
mojom::blink::CacheQueryOptionsPtr cache_query_options,
ExceptionState& exception_state,
bool match_all) {
@@ -233,7 +201,6 @@ ScriptPromise BackgroundFetchRegistration::MatchImpl(
// Convert |request| to mojom::blink::FetchAPIRequestPtr.
mojom::blink::FetchAPIRequestPtr request_to_match;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (request) {
switch (request->GetContentType()) {
case V8RequestInfo::ContentType::kRequest:
@@ -249,19 +216,6 @@ ScriptPromise BackgroundFetchRegistration::MatchImpl(
}
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (request.has_value()) {
- if (request->IsRequest()) {
- request_to_match = request->GetAsRequest()->CreateFetchAPIRequest();
- } else {
- Request* new_request = Request::Create(
- script_state, request->GetAsUSVString(), exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- request_to_match = new_request->CreateFetchAPIRequest();
- }
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(registration_);
DCHECK(registration_service_);
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h
index fe2f538d296..7ddd0366f09 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h
@@ -26,7 +26,6 @@ class ExceptionState;
class ScriptPromiseResolver;
class ScriptState;
class ServiceWorkerRegistration;
-class RequestOrUSVString;
// Represents an individual Background Fetch registration. Gives developers
// access to its properties, options, and enables them to abort the fetch.
@@ -60,30 +59,16 @@ class BackgroundFetchRegistration final
// Web Exposed attribute defined in the IDL file. Corresponds to the
// |developer_id| used elsewhere in the codebase.
String id() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise match(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise match(ScriptState* script_state,
- const RequestOrUSVString& request,
- const CacheQueryOptions* options,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise matchAll(ScriptState* scrip_state,
ExceptionState& exception_state);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise matchAll(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise matchAll(ScriptState* script_state,
- const RequestOrUSVString& request,
- const CacheQueryOptions* options,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
uint64_t uploadTotal() const;
uint64_t uploaded() const;
@@ -115,21 +100,12 @@ class BackgroundFetchRegistration final
private:
void DidAbort(ScriptPromiseResolver* resolver,
mojom::blink::BackgroundFetchError error);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise MatchImpl(
ScriptState* script_state,
const V8RequestInfo* request,
mojom::blink::CacheQueryOptionsPtr cache_query_options,
ExceptionState& exception_state,
bool match_all);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise MatchImpl(
- ScriptState* script_state,
- absl::optional<RequestOrUSVString> request,
- mojom::blink::CacheQueryOptionsPtr cache_query_options,
- ExceptionState& exception_state,
- bool match_all);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void DidGetMatchingRequests(
ScriptPromiseResolver* resolver,
bool return_all,
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/idls.gni b/chromium/third_party/blink/renderer/modules/background_fetch/idls.gni
deleted file mode 100644
index 959d9ff3aaa..00000000000
--- a/chromium/third_party/blink/renderer/modules/background_fetch/idls.gni
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "background_fetch_event.idl",
- "background_fetch_manager.idl",
- "background_fetch_record.idl",
- "background_fetch_registration.idl",
- "background_fetch_update_ui_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "background_fetch_event_init.idl",
- "background_fetch_options.idl",
- "background_fetch_ui_options.idl",
-]
-
-modules_dependency_idl_files = [
- "service_worker_global_scope_background_fetch.idl",
- "service_worker_registration_background_fetch.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/idls.gni b/chromium/third_party/blink/renderer/modules/background_sync/idls.gni
deleted file mode 100644
index a42a23a6f52..00000000000
--- a/chromium/third_party/blink/renderer/modules/background_sync/idls.gni
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "sync_event.idl",
- "periodic_sync_event.idl",
- "periodic_sync_manager.idl",
- "sync_manager.idl",
-]
-
-modules_dictionary_idl_files = [
- "background_sync_options.idl",
- "sync_event_init.idl",
- "periodic_sync_event_init.idl",
-]
-
-modules_dependency_idl_files = [
- "service_worker_global_scope_sync.idl",
- "service_worker_registration_sync.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/badging/idls.gni b/chromium/third_party/blink/renderer/modules/badging/idls.gni
deleted file mode 100644
index 7e5cf65e37b..00000000000
--- a/chromium/third_party/blink/renderer/modules/badging/idls.gni
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [
- "navigator_badge.idl",
- "worker_navigator_badge.idl",
-]
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 27ebe5280cf..ff9a33d51dc 100644
--- a/chromium/third_party/blink/renderer/modules/battery/battery_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/battery/battery_manager.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/modules/battery/battery_dispatcher.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/battery/idls.gni b/chromium/third_party/blink/renderer/modules/battery/idls.gni
deleted file mode 100644
index 25d6ec90ecb..00000000000
--- a/chromium/third_party/blink/renderer/modules/battery/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "battery_manager.idl" ]
-
-modules_dependency_idl_files = [ "navigator_battery.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/beacon/idls.gni b/chromium/third_party/blink/renderer/modules/beacon/idls.gni
deleted file mode 100644
index 03172bb3a1a..00000000000
--- a/chromium/third_party/blink/renderer/modules/beacon/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "navigator_beacon.idl" ]
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 f28cb0f18a2..f2e4e2351bd 100644
--- a/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc
+++ b/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/beacon/navigator_beacon.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_formdata_readablestream_urlsearchparams_usvstring.h"
-#include "third_party/blink/renderer/bindings/modules/v8/readable_stream_or_xml_http_request_body_init.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -61,7 +60,6 @@ bool NavigatorBeacon::CanSendBeacon(ExecutionContext* context,
return GetSupplementable()->DomWindow();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool NavigatorBeacon::sendBeacon(
ScriptState* script_state,
Navigator& navigator,
@@ -71,20 +69,7 @@ bool NavigatorBeacon::sendBeacon(
return NavigatorBeacon::From(navigator).SendBeaconImpl(
script_state, url_string, data, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool NavigatorBeacon::sendBeacon(
- ScriptState* script_state,
- Navigator& navigator,
- const String& urlstring,
- const ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString&
- data,
- ExceptionState& exception_state) {
- return NavigatorBeacon::From(navigator).SendBeaconImpl(
- script_state, urlstring, data, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool NavigatorBeacon::SendBeaconImpl(
ScriptState* script_state,
const String& url_string,
@@ -173,78 +158,5 @@ bool NavigatorBeacon::SendBeaconImpl(
return allowed;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool NavigatorBeacon::SendBeaconImpl(
- ScriptState* script_state,
- const String& urlstring,
- const ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString&
- data,
- ExceptionState& exception_state) {
- ExecutionContext* context = ExecutionContext::From(script_state);
- KURL url = context->CompleteURL(urlstring);
- if (!CanSendBeacon(context, url, exception_state)) {
- // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done.
- VLOG(1) << "Cannot send a beacon to " << url.ElidedString()
- << ", initiator = " << context->Url();
- return false;
- }
-
- // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done.
- VLOG(1) << "Send a beacon to " << url.ElidedString()
- << ", initiator = " << context->Url();
- bool allowed;
-
- LocalFrame* frame = GetSupplementable()->DomWindow()->GetFrame();
- if (data.IsArrayBuffer()) {
- auto* data_buffer = data.GetAsArrayBuffer();
- if (!base::CheckedNumeric<wtf_size_t>(data_buffer->ByteLength())
- .IsValid()) {
- // At the moment the PingLoader::SendBeacon implementation cannot deal
- // with huge ArrayBuffers.
- exception_state.ThrowRangeError(
- "The data provided to sendBeacon() exceeds the maximally possible "
- "length, which is 4294967295.");
- return false;
- }
- allowed = PingLoader::SendBeacon(*script_state, frame, url, data_buffer);
- } else if (data.IsArrayBufferView()) {
- auto* data_view = data.GetAsArrayBufferView().Get();
- if (!base::CheckedNumeric<wtf_size_t>(data_view->byteLength()).IsValid()) {
- // At the moment the PingLoader::SendBeacon implementation cannot deal
- // with huge ArrayBuffers.
- exception_state.ThrowRangeError(
- "The data provided to sendBeacon() exceeds the maximally possible "
- "length, which is 4294967295.");
- return false;
- }
- allowed = PingLoader::SendBeacon(*script_state, frame, url, data_view);
- } else if (data.IsBlob()) {
- Blob* blob = data.GetAsBlob();
- allowed = PingLoader::SendBeacon(*script_state, frame, url, blob);
- } else if (data.IsUSVString()) {
- allowed = PingLoader::SendBeacon(*script_state, frame, url,
- data.GetAsUSVString());
- } else if (data.IsFormData()) {
- allowed =
- PingLoader::SendBeacon(*script_state, frame, url, data.GetAsFormData());
- } else if (data.IsURLSearchParams()) {
- allowed = PingLoader::SendBeacon(*script_state, frame, url,
- data.GetAsURLSearchParams());
- } else if (data.IsReadableStream()) {
- exception_state.ThrowTypeError(
- "sendBeacon cannot have a ReadableStream body.");
- return false;
- } else {
- allowed = PingLoader::SendBeacon(*script_state, frame, url, String());
- }
-
- if (!allowed) {
- UseCounter::Count(context, WebFeature::kSendBeaconQuotaExceeded);
- return false;
- }
-
- return true;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h b/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h
index 600e4b77e14..06302d57bbd 100644
--- a/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h
+++ b/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h
@@ -15,8 +15,6 @@ namespace blink {
class ScriptState;
class ExceptionState;
class KURL;
-class
- ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString;
class NavigatorBeacon final : public GarbageCollected<NavigatorBeacon>,
public Supplement<Navigator> {
@@ -28,37 +26,20 @@ class NavigatorBeacon final : public GarbageCollected<NavigatorBeacon>,
explicit NavigatorBeacon(Navigator&);
virtual ~NavigatorBeacon();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static bool sendBeacon(
ScriptState* script_state,
Navigator& navigator,
const String& url_string,
const V8UnionReadableStreamOrXMLHttpRequestBodyInit* data,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static bool sendBeacon(
- ScriptState*,
- Navigator&,
- const String&,
- const ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
private:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool SendBeaconImpl(ScriptState* script_state,
const String& url_string,
const V8UnionReadableStreamOrXMLHttpRequestBodyInit* data,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool SendBeaconImpl(
- ScriptState*,
- const String&,
- const ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool CanSendBeacon(ExecutionContext*, const KURL&, ExceptionState&);
};
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
index dc23f839b41..5baf452155a 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_device.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
@@ -56,25 +57,6 @@ const char kInactiveDocumentError[] = "Document not active";
const char kHandleGestureForPermissionRequest[] =
"Must be handling a user gesture to show a permission request.";
-namespace {
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// TODO(crbug.com/1181288): Remove the old IDL union version.
-V8BluetoothServiceUUID* ToV8BluetoothServiceUUID(
- const StringOrUnsignedLong& uuid) {
- if (uuid.IsString()) {
- return MakeGarbageCollected<V8BluetoothServiceUUID>(uuid.GetAsString());
- } else if (uuid.IsUnsignedLong()) {
- return MakeGarbageCollected<V8BluetoothServiceUUID>(
- uuid.GetAsUnsignedLong());
- }
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-} // namespace
-
// Remind developers when they are using Web Bluetooth on unsupported platforms.
// TODO(https://crbug.com/570344): Remove this method when all platforms are
// supported.
@@ -108,14 +90,9 @@ static void CanonicalizeFilter(
return;
}
canonicalized_filter->services.emplace();
- for (const StringOrUnsignedLong& service : filter->services()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const String& validated_service = BluetoothUUID::getService(
- ToV8BluetoothServiceUUID(service), exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ for (const V8UnionStringOrUnsignedLong* service : filter->services()) {
const String& validated_service =
BluetoothUUID::getService(service, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException())
return;
canonicalized_filter->services->push_back(validated_service);
@@ -153,8 +130,14 @@ static void CanonicalizeFilter(
}
canonicalized_filter->manufacturer_data.emplace();
for (const auto& manufacturer_data : filter->manufacturerData()) {
- DOMArrayPiece mask_buffer = manufacturer_data->mask();
- DOMArrayPiece data_prefix_buffer = manufacturer_data->dataPrefix();
+ DOMArrayPiece mask_buffer = manufacturer_data->hasMask()
+ ? DOMArrayPiece(manufacturer_data->mask())
+ : DOMArrayPiece();
+ DOMArrayPiece data_prefix_buffer =
+ manufacturer_data->hasDataPrefix()
+ ? DOMArrayPiece(manufacturer_data->dataPrefix())
+ : DOMArrayPiece();
+
if (manufacturer_data->hasMask()) {
if (mask_buffer.IsDetached()) {
exception_state.ThrowDOMException(
@@ -254,15 +237,10 @@ static void ConvertRequestDeviceOptions(
}
if (options->hasOptionalServices()) {
- for (const StringOrUnsignedLong& optional_service :
+ for (const V8UnionStringOrUnsignedLong* optional_service :
options->optionalServices()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const String& validated_optional_service = BluetoothUUID::getService(
- ToV8BluetoothServiceUUID(optional_service), exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& validated_optional_service =
BluetoothUUID::getService(optional_service, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException())
return;
result->optional_services.push_back(validated_optional_service);
@@ -579,14 +557,16 @@ Bluetooth::~Bluetooth() = default;
BluetoothDevice* Bluetooth::GetBluetoothDeviceRepresentingDevice(
mojom::blink::WebBluetoothDevicePtr device_ptr,
ExecutionContext* context) {
- String& id = device_ptr->id;
- BluetoothDevice* device = device_instance_map_.at(id);
- if (!device) {
- device = MakeGarbageCollected<BluetoothDevice>(context,
- std::move(device_ptr), this);
- auto result = device_instance_map_.insert(id, device);
- DCHECK(result.is_new_entry);
+ auto it = device_instance_map_.find(device_ptr->id);
+ if (it != device_instance_map_.end()) {
+ return it->value;
}
+
+ String id = device_ptr->id;
+ BluetoothDevice* device = MakeGarbageCollected<BluetoothDevice>(
+ context, std::move(device_ptr), this);
+ auto result = device_instance_map_.insert(id, device);
+ DCHECK(result.is_new_entry);
return device;
}
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.cc
index 74a957892a3..4220a602b33 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unsignedlong.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_unsigned_long.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_bluetooth_advertising_event_init.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/event_type_names.h"
@@ -21,27 +20,14 @@ BluetoothAdvertisingEvent::BluetoothAdvertisingEvent(
: Event(event_type, initializer),
device_(initializer->device()),
name_(initializer->name()),
-#if !defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- uuids_(initializer->uuids()),
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
appearance_(initializer->hasAppearance() ? initializer->appearance() : 0),
txPower_(initializer->hasTxPower() ? initializer->txPower() : 0),
rssi_(initializer->hasRssi() ? initializer->rssi() : 0),
manufacturer_data_map_(initializer->manufacturerData()),
service_data_map_(initializer->serviceData()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- for (const auto& uuid : initializer->uuids()) {
- if (uuid.IsString()) {
- uuids_.push_back(
- MakeGarbageCollected<V8UnionUUIDOrUnsignedLong>(uuid.GetAsString()));
- } else if (uuid.IsUnsignedLong()) {
- uuids_.push_back(MakeGarbageCollected<V8UnionUUIDOrUnsignedLong>(
- uuid.GetAsUnsignedLong()));
- } else {
- NOTREACHED();
- }
+ if (initializer->hasUuids()) {
+ uuids_ = initializer->uuids();
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
BluetoothAdvertisingEvent::BluetoothAdvertisingEvent(
@@ -59,13 +45,7 @@ BluetoothAdvertisingEvent::BluetoothAdvertisingEvent(
service_data_map_(MakeGarbageCollected<BluetoothServiceDataMap>(
advertising_event->service_data)) {
for (const String& uuid : advertising_event->uuids) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
uuids_.push_back(MakeGarbageCollected<V8UnionUUIDOrUnsignedLong>(uuid));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrUnsignedLong value;
- value.SetString(uuid);
- uuids_.push_back(value);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
} // namespace blink
@@ -91,17 +71,10 @@ const String& BluetoothAdvertisingEvent::name() const {
return name_;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionUUIDOrUnsignedLong>>&
BluetoothAdvertisingEvent::uuids() const {
return uuids_;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-const HeapVector<StringOrUnsignedLong>& BluetoothAdvertisingEvent::uuids()
- const {
- return uuids_;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
BluetoothManufacturerDataMap* BluetoothAdvertisingEvent::manufacturerData()
const {
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
index b8b8d27c7d3..e8ebf2638e8 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
@@ -15,7 +15,6 @@ class BluetoothDevice;
class BluetoothAdvertisingEventInit;
class BluetoothManufacturerDataMap;
class BluetoothServiceDataMap;
-class StringOrUnsignedLong;
class BluetoothAdvertisingEvent final : public Event {
DEFINE_WRAPPERTYPEINFO();
@@ -37,11 +36,7 @@ class BluetoothAdvertisingEvent final : public Event {
BluetoothDevice* device() const;
const String& name() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const HeapVector<Member<V8UnionUUIDOrUnsignedLong>>& uuids() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<StringOrUnsignedLong>& uuids() const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<uint16_t> appearance() const { return appearance_; }
absl::optional<int8_t> txPower() const { return txPower_; }
absl::optional<int8_t> rssi() const { return rssi_; }
@@ -51,11 +46,7 @@ class BluetoothAdvertisingEvent final : public Event {
private:
Member<BluetoothDevice> device_;
String name_;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8UnionUUIDOrUnsignedLong>> uuids_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<StringOrUnsignedLong> uuids_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<uint16_t> appearance_;
absl::optional<int8_t> txPower_;
absl::optional<int8_t> rssi_;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc
index 195ecbfdb1a..de06c805625 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h
index 13f23762ab0..138886746f1 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h
@@ -7,6 +7,7 @@
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink-forward.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/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
index 84df2a30670..0c09f3a9d2d 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unsignedlong.h"
namespace blink {
@@ -30,11 +31,10 @@ BluetoothLEScan::BluetoothLEScan(
filter_init->setNamePrefix(filter->name_prefix);
if (filter->services && filter->services.has_value()) {
- HeapVector<blink::StringOrUnsignedLong> services;
+ HeapVector<Member<V8UnionStringOrUnsignedLong>> services;
for (const auto& uuid : filter->services.value()) {
- blink::StringOrUnsignedLong uuid_string;
- uuid_string.SetString(uuid);
- services.push_back(uuid_string);
+ services.push_back(
+ MakeGarbageCollected<V8UnionStringOrUnsignedLong>(uuid));
}
filter_init->setServices(services);
}
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 b840ee7c1d8..ed10319c624 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
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.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/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -51,7 +52,16 @@ void BluetoothRemoteGATTCharacteristic::RemoteCharacteristicValueChanged(
if (!GetGatt()->connected())
return;
SetValue(BluetoothRemoteGATTUtils::ConvertWTFVectorToDataView(value));
- DispatchEvent(*Event::Create(event_type_names::kCharacteristicvaluechanged));
+ if (notification_registration_in_progress()) {
+ // Save event and value to be dispatched after notification is registered.
+ deferred_value_change_data_.push_back(
+ MakeGarbageCollected<DeferredValueChange>(
+ Event::Create(event_type_names::kCharacteristicvaluechanged),
+ value_, /*promise=*/nullptr));
+ } else {
+ DispatchEvent(
+ *Event::Create(event_type_names::kCharacteristicvaluechanged));
+ }
}
const WTF::AtomicString& BluetoothRemoteGATTCharacteristic::InterfaceName()
@@ -98,9 +108,17 @@ void BluetoothRemoteGATTCharacteristic::ReadValueCallback(
DOMDataView* dom_data_view =
BluetoothRemoteGATTUtils::ConvertWTFVectorToDataView(value.value());
SetValue(dom_data_view);
- DispatchEvent(
- *Event::Create(event_type_names::kCharacteristicvaluechanged));
- resolver->Resolve(dom_data_view);
+ if (notification_registration_in_progress()) {
+ // Save event to be dispatched after notification is registered.
+ deferred_value_change_data_.push_back(
+ MakeGarbageCollected<DeferredValueChange>(
+ Event::Create(event_type_names::kCharacteristicvaluechanged),
+ dom_data_view, resolver));
+ } else {
+ DispatchEvent(
+ *Event::Create(event_type_names::kCharacteristicvaluechanged));
+ resolver->Resolve(dom_data_view);
+ }
} else {
resolver->Reject(BluetoothError::CreateDOMException(result));
}
@@ -252,7 +270,12 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::writeValueWithoutResponse(
void BluetoothRemoteGATTCharacteristic::NotificationsCallback(
ScriptPromiseResolver* resolver,
+ bool started,
mojom::blink::WebBluetoothResult result) {
+ if (started) {
+ DCHECK_NE(num_in_flight_notification_registrations_, 0U);
+ num_in_flight_notification_registrations_--;
+ }
if (!resolver->GetExecutionContext() ||
resolver->GetExecutionContext()->IsContextDestroyed())
return;
@@ -269,6 +292,25 @@ void BluetoothRemoteGATTCharacteristic::NotificationsCallback(
} else {
resolver->Reject(BluetoothError::CreateDOMException(result));
}
+
+ if (started && !notification_registration_in_progress() &&
+ !deferred_value_change_data_.IsEmpty()) {
+ // Ensure promises are resolved before dispatching events allows them
+ // to add listeners.
+ blink::Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate());
+ // Dispatch deferred characteristicvaluechanged events created during the
+ // registration of notifications.
+ auto deferred_value_change_data = std::move(deferred_value_change_data_);
+ deferred_value_change_data_.clear();
+ for (const auto& value_changed_data : deferred_value_change_data) {
+ auto prior_value = value_;
+ value_ = value_changed_data->dom_data_view;
+ DispatchEvent(*value_changed_data->event);
+ if (value_changed_data->resolver)
+ value_changed_data->resolver->Resolve(value_);
+ value_ = prior_value;
+ }
+ }
}
ScriptPromise BluetoothRemoteGATTCharacteristic::startNotifications(
@@ -303,10 +345,12 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::startNotifications(
client.InitWithNewEndpointAndPassReceiver(),
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI));
+ num_in_flight_notification_registrations_++;
service->RemoteCharacteristicStartNotifications(
characteristic_->instance_id, std::move(client),
WTF::Bind(&BluetoothRemoteGATTCharacteristic::NotificationsCallback,
- WrapPersistent(this), WrapPersistent(resolver)));
+ WrapPersistent(this), WrapPersistent(resolver),
+ /*starting=*/true));
return promise;
}
@@ -340,17 +384,13 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::stopNotifications(
characteristic_->instance_id,
WTF::Bind(&BluetoothRemoteGATTCharacteristic::NotificationsCallback,
WrapPersistent(this), WrapPersistent(resolver),
- mojom::blink::WebBluetoothResult::SUCCESS));
+ /*starting=*/false, mojom::blink::WebBluetoothResult::SUCCESS));
return promise;
}
ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptor(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothDescriptorUUID* descriptor_uuid,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& descriptor_uuid,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
String descriptor =
BluetoothUUID::getDescriptor(descriptor_uuid, exception_state);
@@ -372,11 +412,7 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors(
ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothDescriptorUUID* descriptor_uuid,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& descriptor_uuid,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
String descriptor =
BluetoothUUID::getDescriptor(descriptor_uuid, exception_state);
@@ -490,8 +526,18 @@ void BluetoothRemoteGATTCharacteristic::Trace(Visitor* visitor) const {
visitor->Trace(value_);
visitor->Trace(device_);
visitor->Trace(receivers_);
+ visitor->Trace(deferred_value_change_data_);
+
EventTargetWithInlineData::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
}
+void BluetoothRemoteGATTCharacteristic::DeferredValueChange::Trace(
+ Visitor* visitor) const {
+ visitor->Trace(event);
+ visitor->Trace(dom_data_view);
+ if (resolver)
+ visitor->Trace(resolver);
+}
+
} // namespace blink
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 80343010290..571e6c868c5 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
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_set.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -75,19 +76,11 @@ class BluetoothRemoteGATTCharacteristic final
BluetoothCharacteristicProperties* properties() { return properties_; }
DOMDataView* value() const { return value_; }
ScriptPromise getDescriptor(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothDescriptorUUID* descriptor_uuid,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& descriptor_uuid,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state);
ScriptPromise getDescriptors(ScriptState*, ExceptionState&);
ScriptPromise getDescriptors(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothDescriptorUUID* descriptor_uuid,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& descriptor_uuid,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state);
ScriptPromise readValue(ScriptState*, ExceptionState&);
ScriptPromise writeValue(ScriptState*, const DOMArrayPiece&, ExceptionState&);
@@ -111,6 +104,20 @@ class BluetoothRemoteGATTCharacteristic final
private:
friend class BluetoothRemoteGATTDescriptor;
+ struct DeferredValueChange : public GarbageCollected<DeferredValueChange> {
+ DeferredValueChange(Member<Event> event,
+ Member<DOMDataView> dom_data_view,
+ Member<ScriptPromiseResolver> resolver)
+ : event(event), dom_data_view(dom_data_view), resolver(resolver) {}
+
+ // GarbageCollectedMixin:
+ void Trace(Visitor*) const;
+
+ Member<Event> event; // Event to dispatch before resolving promise.
+ Member<DOMDataView> dom_data_view;
+ Member<ScriptPromiseResolver> resolver; // Possibly null.
+ };
+
BluetoothRemoteGATTServer* GetGatt() { return service_->device()->gatt(); }
void ReadValueCallback(ScriptPromiseResolver*,
@@ -119,7 +126,12 @@ class BluetoothRemoteGATTCharacteristic final
void WriteValueCallback(ScriptPromiseResolver*,
const Vector<uint8_t>& value,
mojom::blink::WebBluetoothResult);
+
+ // Callback for startNotifictions/stopNotifications.
+ // |started| is true if called as a result of startNotifictions() and
+ // false if called as a result of stopNotifications().
void NotificationsCallback(ScriptPromiseResolver*,
+ bool started,
mojom::blink::WebBluetoothResult);
ScriptPromise WriteCharacteristicValue(ScriptState*,
@@ -143,6 +155,11 @@ class BluetoothRemoteGATTCharacteristic final
String CreateInvalidCharacteristicErrorMessage();
+ // Still waiting for acknowledgement from device of request for notifications?
+ bool notification_registration_in_progress() const {
+ return num_in_flight_notification_registrations_ > 0;
+ }
+
mojom::blink::WebBluetoothRemoteGATTCharacteristicPtr characteristic_;
Member<BluetoothRemoteGATTService> service_;
Member<BluetoothCharacteristicProperties> properties_;
@@ -151,6 +168,12 @@ class BluetoothRemoteGATTCharacteristic final
HeapMojoAssociatedReceiverSet<mojom::blink::WebBluetoothCharacteristicClient,
BluetoothRemoteGATTCharacteristic>
receivers_;
+
+ uint32_t num_in_flight_notification_registrations_ = 0;
+
+ // Queue of characteristicvaluechanged events created if a value changes
+ // while startNotificications() is in the process of registering a listener.
+ HeapVector<Member<DeferredValueChange>> deferred_value_change_data_;
};
} // namespace blink
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 6d31006f8f3..31ceddb6aad 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
@@ -167,11 +167,7 @@ void BluetoothRemoteGATTServer::GetPrimaryServicesCallback(
ScriptPromise BluetoothRemoteGATTServer::getPrimaryService(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothServiceUUID* service,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& service,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
String service_uuid = BluetoothUUID::getService(service, exception_state);
if (exception_state.HadException())
@@ -184,11 +180,7 @@ ScriptPromise BluetoothRemoteGATTServer::getPrimaryService(
ScriptPromise BluetoothRemoteGATTServer::getPrimaryServices(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothServiceUUID* service,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& service,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
String service_uuid = BluetoothUUID::getService(service, exception_state);
if (exception_state.HadException())
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
index a6ae87b6a19..0a11474a077 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_unsigned_long.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_device.h"
@@ -69,21 +68,12 @@ class BluetoothRemoteGATTServer
bool connected() { return connected_; }
ScriptPromise connect(ScriptState*);
void disconnect(ScriptState*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise getPrimaryService(ScriptState* script_state,
const V8BluetoothServiceUUID* service,
ExceptionState& exception_state);
ScriptPromise getPrimaryServices(ScriptState* script_state,
const V8BluetoothServiceUUID* service,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise getPrimaryService(ScriptState*,
- const StringOrUnsignedLong& service,
- ExceptionState&);
- ScriptPromise getPrimaryServices(ScriptState*,
- const StringOrUnsignedLong& service,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise getPrimaryServices(ScriptState*, ExceptionState&);
private:
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 aed33a90c2f..1da3898ac5b 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
@@ -90,11 +90,7 @@ void BluetoothRemoteGATTService::GetCharacteristicsCallback(
ScriptPromise BluetoothRemoteGATTService::getCharacteristic(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothCharacteristicUUID* characteristic,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& characteristic,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
String characteristic_uuid =
BluetoothUUID::getCharacteristic(characteristic, exception_state);
@@ -108,11 +104,7 @@ ScriptPromise BluetoothRemoteGATTService::getCharacteristic(
ScriptPromise BluetoothRemoteGATTService::getCharacteristics(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothCharacteristicUUID* characteristic,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrUnsignedLong& characteristic,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
String characteristic_uuid =
BluetoothUUID::getCharacteristic(characteristic, exception_state);
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h
index e10fcaa2dfa..4f7daa8ee39 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_H_
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink-forward.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_unsigned_long.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_device.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -44,7 +43,6 @@ class BluetoothRemoteGATTService final : public ScriptWrappable {
String uuid() { return service_->uuid; }
bool isPrimary() { return is_primary_; }
BluetoothDevice* device() { return device_; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise getCharacteristic(
ScriptState* script_state,
const V8BluetoothCharacteristicUUID* characteristic,
@@ -53,14 +51,6 @@ class BluetoothRemoteGATTService final : public ScriptWrappable {
ScriptState* script_state,
const V8BluetoothCharacteristicUUID* characteristic,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise getCharacteristic(ScriptState*,
- const StringOrUnsignedLong& characteristic,
- ExceptionState&);
- ScriptPromise getCharacteristics(ScriptState*,
- const StringOrUnsignedLong& characteristic,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise getCharacteristics(ScriptState*, ExceptionState&);
private:
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_service_data_map.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_service_data_map.h
index 990d153d5a8..0fdc736da6c 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_service_data_map.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_service_data_map.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_SERVICE_DATA_MAP_H_
#include "third_party/blink/renderer/bindings/core/v8/maplike.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_unsigned_long.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
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 d3f4f27b318..41338b060f0 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
@@ -8,6 +8,7 @@
#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_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/uuid.h"
@@ -318,16 +319,9 @@ NameToAssignedNumberMap* GetAssignedNumberForDescriptorNameMap() {
}
String GetUUIDForGATTAttribute(GATTAttribute attribute,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8UnionStringOrUnsignedLong* name_arg,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrUnsignedLong name,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8UnionStringOrUnsignedLong* name,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DCHECK(name_arg);
- const V8UnionStringOrUnsignedLong& name = *name_arg;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ DCHECK(name);
// Implementation of BluetoothUUID.getService, BluetoothUUID.getCharacteristic
// and BluetoothUUID.getDescriptor algorithms:
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getservice
@@ -336,10 +330,10 @@ String GetUUIDForGATTAttribute(GATTAttribute attribute,
// If name is an unsigned long, return BluetoothUUID.cannonicalUUI(name) and
// abort this steps.
- if (name.IsUnsignedLong())
- return BluetoothUUID::canonicalUUID(name.GetAsUnsignedLong());
+ if (name->IsUnsignedLong())
+ return BluetoothUUID::canonicalUUID(name->GetAsUnsignedLong());
- String name_str = name.GetAsString();
+ const String& name_str = name->GetAsString();
// If name is a valid UUID, return name and abort these steps.
if (WTF::IsValidUUID(name_str))
@@ -403,11 +397,7 @@ String GetUUIDForGATTAttribute(GATTAttribute attribute,
// static
String BluetoothUUID::getService(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothServiceUUID* name,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrUnsignedLong name,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return GetUUIDForGATTAttribute(GATTAttribute::kService, name,
exception_state);
@@ -415,11 +405,7 @@ String BluetoothUUID::getService(
// static
String BluetoothUUID::getCharacteristic(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothCharacteristicUUID* name,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrUnsignedLong name,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return GetUUIDForGATTAttribute(GATTAttribute::kCharacteristic, name,
exception_state);
@@ -427,11 +413,7 @@ String BluetoothUUID::getCharacteristic(
// static
String BluetoothUUID::getDescriptor(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BluetoothDescriptorUUID* name,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrUnsignedLong name,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
return GetUUIDForGATTAttribute(GATTAttribute::kDescriptor, name,
exception_state);
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h
index 0fd2d1bea43..863a98d6203 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_UUID_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_UUID_H_
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_unsigned_long.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -21,18 +20,12 @@ class BluetoothUUID final : public ScriptWrappable {
public:
// IDL exposed interface:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static String getService(const V8BluetoothServiceUUID* name,
ExceptionState& exception_state);
static String getCharacteristic(const V8BluetoothCharacteristicUUID* name,
ExceptionState& exception_state);
static String getDescriptor(const V8BluetoothDescriptorUUID* name,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static String getService(StringOrUnsignedLong name, ExceptionState&);
- static String getCharacteristic(StringOrUnsignedLong name, ExceptionState&);
- static String getDescriptor(StringOrUnsignedLong name, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static String canonicalUUID(unsigned alias);
};
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/idls.gni b/chromium/third_party/blink/renderer/modules/bluetooth/idls.gni
deleted file mode 100644
index 30ee0005670..00000000000
--- a/chromium/third_party/blink/renderer/modules/bluetooth/idls.gni
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "bluetooth.idl",
- "bluetooth_advertising_event.idl",
- "bluetooth_characteristic_properties.idl",
- "bluetooth_device.idl",
- "bluetooth_le_scan.idl",
- "bluetooth_manufacturer_data_map.idl",
- "bluetooth_remote_gatt_characteristic.idl",
- "bluetooth_remote_gatt_descriptor.idl",
- "bluetooth_remote_gatt_server.idl",
- "bluetooth_remote_gatt_service.idl",
- "bluetooth_service_data_map.idl",
- "bluetooth_uuid.idl",
-]
-
-modules_dictionary_idl_files = [
- "bluetooth_advertising_event_init.idl",
- "bluetooth_data_filter_init.idl",
- "bluetooth_le_scan_filter_init.idl",
- "bluetooth_le_scan_options.idl",
- "bluetooth_manufacturer_data_filter_init.idl",
- "request_device_options.idl",
- "watch_advertisements_options.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_bluetooth.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/testing/clusterfuzz/PRESUBMIT.py b/chromium/third_party/blink/renderer/modules/bluetooth/testing/clusterfuzz/PRESUBMIT.py
index 9c3f101ac51..8b5b6a4360c 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/testing/clusterfuzz/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/testing/clusterfuzz/PRESUBMIT.py
@@ -3,6 +3,8 @@
# found in the LICENSE file.
"""Script that runs tests before uploading a patch."""
+USE_PYTHON3 = True
+
def _RunTests(input_api, output_api):
"""Runs all test files in the directory."""
@@ -11,7 +13,7 @@ def _RunTests(input_api, output_api):
test_cmd = input_api.Command(
name=cmd_name, cmd=cmd, kwargs={}, message=output_api.PresubmitError)
if input_api.verbose:
- print 'Running ' + cmd_name
+ print('Running ' + cmd_name)
return input_api.RunTests([test_cmd])
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/BUILD.gn b/chromium/third_party/blink/renderer/modules/breakout_box/BUILD.gn
index 497fde09b7c..f622158f20c 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/BUILD.gn
@@ -31,10 +31,6 @@ blink_modules_sources("breakout_box") {
"pushable_media_stream_video_source.h",
"transferred_frame_queue_underlying_source.cc",
"transferred_frame_queue_underlying_source.h",
- "video_track_signal_underlying_sink.cc",
- "video_track_signal_underlying_sink.h",
- "video_track_signal_underlying_source.cc",
- "video_track_signal_underlying_source.h",
]
deps = [
"//third_party/blink/renderer/modules/mediastream:mediastream",
@@ -56,8 +52,6 @@ source_set("unit_tests") {
"pushable_media_stream_video_source_test.cc",
"stream_test_utils.cc",
"stream_test_utils.h",
- "video_track_signal_underlying_sink_test.cc",
- "video_track_signal_underlying_source_test.cc",
]
deps = [
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/DEPS b/chromium/third_party/blink/renderer/modules/breakout_box/DEPS
index 2549b0a9ca0..3642fd0ee13 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/DEPS
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+base/bind_post_task.h",
"+media/base",
+ "+media/capture/video",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/breakout_box",
"+third_party/blink/renderer/modules/mediastream",
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue.h b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue.h
index f5c2b2307b0..fd646927884 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue.h
@@ -20,22 +20,48 @@ class FrameQueue
explicit FrameQueue(wtf_size_t max_size)
: max_size_(std::max(1u, max_size)) {}
- void Push(NativeFrameType frame) {
+ Mutex& GetMutex() { return lock_; }
+
+ absl::optional<NativeFrameType> Push(NativeFrameType frame) {
MutexLocker locker_(lock_);
+ return PushLocked(std::move(frame));
+ }
+
+ absl::optional<NativeFrameType> PushLocked(NativeFrameType frame) {
+ lock_.AssertAcquired();
+ absl::optional<NativeFrameType> ret;
if (queue_.size() == max_size_)
- queue_.pop_front();
+ ret = queue_.TakeFirst();
queue_.push_back(std::move(frame));
+ return ret;
}
absl::optional<NativeFrameType> Pop() {
MutexLocker locker_(lock_);
+ return PopLocked();
+ }
+
+ absl::optional<NativeFrameType> PopLocked() {
+ lock_.AssertAcquired();
if (queue_.empty())
return absl::nullopt;
return queue_.TakeFirst();
}
+ absl::optional<NativeFrameType> PeekLocked() {
+ lock_.AssertAcquired();
+ if (queue_.empty())
+ return absl::nullopt;
+ return queue_.front();
+ }
+
bool IsEmpty() {
MutexLocker locker_(lock_);
+ return IsEmptyLocked();
+ }
+
+ bool IsEmptyLocked() {
+ lock_.AssertAcquired();
return queue_.empty();
}
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_test.cc
index 6a44cd892b7..8564b34c3dc 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_test.cc
@@ -34,6 +34,25 @@ TEST_F(FrameQueueTest, PushPopMatches) {
}
}
+TEST_F(FrameQueueTest, PushReturnsReplacedElement) {
+ const int kMaxSize = 2;
+ scoped_refptr<FrameQueue<int>> queue =
+ base::MakeRefCounted<FrameQueue<int>>(kMaxSize);
+ absl::optional<int> replaced = queue->Push(1);
+ EXPECT_FALSE(replaced.has_value());
+
+ replaced = queue->Push(2);
+ EXPECT_FALSE(replaced.has_value());
+
+ replaced = queue->Push(3);
+ EXPECT_TRUE(replaced.has_value());
+ EXPECT_EQ(replaced.value(), 1);
+
+ replaced = queue->Push(4);
+ EXPECT_TRUE(replaced.has_value());
+ EXPECT_EQ(replaced.value(), 2);
+}
+
TEST_F(FrameQueueTest, EmptyQueueReturnsNullopt) {
scoped_refptr<FrameQueue<int>> queue =
base::MakeRefCounted<FrameQueue<int>>(5);
@@ -141,4 +160,41 @@ TEST_F(FrameQueueTest, PushValuesInOrderOnSeparateThread) {
EXPECT_LE(num_read, kMaxSize);
}
+TEST_F(FrameQueueTest, LockedOperations) {
+ const int kMaxSize = 1;
+ scoped_refptr<FrameQueue<int>> queue =
+ base::MakeRefCounted<FrameQueue<int>>(kMaxSize);
+ MutexLocker locker(queue->GetMutex());
+ EXPECT_TRUE(queue->IsEmptyLocked());
+
+ absl::optional<int> peeked = queue->PeekLocked();
+ EXPECT_FALSE(peeked.has_value());
+
+ absl::optional<int> popped = queue->PushLocked(1);
+ EXPECT_FALSE(popped.has_value());
+ EXPECT_FALSE(queue->IsEmptyLocked());
+
+ peeked = queue->PeekLocked();
+ EXPECT_TRUE(peeked.has_value());
+ EXPECT_EQ(peeked.value(), 1);
+ EXPECT_FALSE(queue->IsEmptyLocked());
+
+ popped = queue->PushLocked(2);
+ EXPECT_TRUE(popped.has_value());
+ EXPECT_EQ(popped.value(), 1);
+
+ peeked = queue->PeekLocked();
+ EXPECT_TRUE(peeked.has_value());
+ EXPECT_EQ(peeked.value(), 2);
+ EXPECT_FALSE(queue->IsEmptyLocked());
+
+ popped = queue->PopLocked();
+ EXPECT_TRUE(popped.has_value());
+ EXPECT_EQ(popped.value(), 2);
+ EXPECT_TRUE(queue->IsEmptyLocked());
+
+ peeked = queue->PeekLocked();
+ EXPECT_FALSE(peeked.has_value());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
index 09bb43158a4..4dbe4fb1d73 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.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/scheduler/public/post_cross_thread_task.h"
@@ -19,15 +20,43 @@
namespace blink {
+namespace {
+
+int GetFrameId(const scoped_refptr<media::VideoFrame>& video_frame) {
+ return video_frame->unique_id();
+}
+
+int GetFrameId(const scoped_refptr<media::AudioBuffer>&) {
+ NOTREACHED();
+ return -1;
+}
+
+} // namespace
+
template <typename NativeFrameType>
FrameQueueUnderlyingSource<NativeFrameType>::FrameQueueUnderlyingSource(
ScriptState* script_state,
- wtf_size_t max_queue_size)
+ wtf_size_t max_queue_size,
+ std::string device_id,
+ wtf_size_t frame_pool_size)
: UnderlyingSourceBase(script_state),
realm_task_runner_(ExecutionContext::From(script_state)
->GetTaskRunner(TaskType::kInternalMediaRealTime)),
frame_queue_handle_(
- base::MakeRefCounted<FrameQueue<NativeFrameType>>(max_queue_size)) {}
+ base::MakeRefCounted<FrameQueue<NativeFrameType>>(max_queue_size)),
+ device_id_(std::move(device_id)),
+ frame_pool_size_(frame_pool_size) {
+ DCHECK(device_id_.empty() || frame_pool_size_ > 0);
+}
+
+template <typename NativeFrameType>
+FrameQueueUnderlyingSource<NativeFrameType>::FrameQueueUnderlyingSource(
+ ScriptState* script_state,
+ wtf_size_t max_queue_size)
+ : FrameQueueUnderlyingSource(script_state,
+ max_queue_size,
+ std::string(),
+ /*frame_pool_size=*/0) {}
template <typename NativeFrameType>
FrameQueueUnderlyingSource<NativeFrameType>::FrameQueueUnderlyingSource(
@@ -36,29 +65,35 @@ FrameQueueUnderlyingSource<NativeFrameType>::FrameQueueUnderlyingSource(
: UnderlyingSourceBase(script_state),
realm_task_runner_(ExecutionContext::From(script_state)
->GetTaskRunner(TaskType::kInternalMediaRealTime)),
- frame_queue_handle_(other_source->frame_queue_handle_.Queue()) {}
+ frame_queue_handle_(other_source->frame_queue_handle_.Queue()),
+ device_id_(other_source->device_id_),
+ frame_pool_size_(other_source->frame_pool_size_) {
+ DCHECK(device_id_.empty() || frame_pool_size_ > 0);
+}
template <typename NativeFrameType>
ScriptPromise FrameQueueUnderlyingSource<NativeFrameType>::pull(
ScriptState* script_state) {
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
+ {
+ MutexLocker locker(mutex_);
+ num_pending_pulls_++;
+ }
auto frame_queue = frame_queue_handle_.Queue();
if (!frame_queue)
return ScriptPromise::CastUndefined(script_state);
- if (frame_queue->IsEmpty()) {
- MutexLocker locker(mutex_);
- is_pending_pull_ = true;
- return ScriptPromise::CastUndefined(script_state);
+
+ if (!frame_queue->IsEmpty()) {
+ // Enqueuing the frame in the stream controller synchronously can lead to a
+ // state where the JS code issuing and handling the read requests keeps
+ // executing and prevents other tasks from executing. To avoid this, enqueue
+ // the frame on another task. See https://crbug.com/1216445#c1
+ realm_task_runner_->PostTask(
+ FROM_HERE,
+ WTF::Bind(&FrameQueueUnderlyingSource<
+ NativeFrameType>::MaybeSendFrameFromQueueToStream,
+ WrapPersistent(this)));
}
- // Enqueuing the frame in the stream controller synchronously can lead to a
- // state where the JS code issuing and handling the read requests keeps
- // executing and prevents other tasks from executing. To avoid this, enqueue
- // the frame on another task. See https://crbug.com/1216445#c1
- realm_task_runner_->PostTask(
- FROM_HERE,
- WTF::Bind(&FrameQueueUnderlyingSource<
- NativeFrameType>::MaybeSendFrameFromQueueToStream,
- WrapPersistent(this)));
return ScriptPromise::CastUndefined(script_state);
}
@@ -66,20 +101,19 @@ template <typename NativeFrameType>
ScriptPromise FrameQueueUnderlyingSource<NativeFrameType>::Start(
ScriptState* script_state) {
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
- if (!StartFrameDelivery()) {
- // There is only one way in which this can fail for now. Perhaps
- // implementations should return their own failure messages.
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(
- "Invalid track",
- DOMException::GetErrorName(DOMExceptionCode::kInvalidStateError)));
- }
- if (is_pending_close_) {
- realm_task_runner_->PostTask(
- FROM_HERE,
- WTF::Bind(&FrameQueueUnderlyingSource<NativeFrameType>::Close,
- WrapWeakPersistent(this)));
+ if (is_closed_) {
+ // This was intended to be closed before Start() was called.
+ CloseController();
+ } else {
+ if (!StartFrameDelivery()) {
+ // There is only one way in which this can fail for now. Perhaps
+ // implementations should return their own failure messages.
+ return ScriptPromise::RejectWithDOMException(
+ script_state,
+ DOMException::Create("Invalid track",
+ DOMException::GetErrorName(
+ DOMExceptionCode::kInvalidStateError)));
+ }
}
return ScriptPromise::CastUndefined(script_state);
@@ -97,14 +131,14 @@ ScriptPromise FrameQueueUnderlyingSource<NativeFrameType>::Cancel(
template <typename NativeFrameType>
bool FrameQueueUnderlyingSource<NativeFrameType>::HasPendingActivity() const {
MutexLocker locker(mutex_);
- return is_pending_pull_ && Controller();
+ return (num_pending_pulls_ > 0) && Controller();
}
template <typename NativeFrameType>
void FrameQueueUnderlyingSource<NativeFrameType>::ContextDestroyed() {
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
+ Close();
UnderlyingSourceBase::ContextDestroyed();
- frame_queue_handle_.Invalidate();
}
template <typename NativeFrameType>
@@ -119,28 +153,37 @@ void FrameQueueUnderlyingSource<NativeFrameType>::Close() {
if (is_closed_)
return;
- // The source has not started. Postpone close until it starts.
- if (!Controller()) {
- is_pending_close_ = true;
- return;
- }
-
- StopFrameDelivery();
- CloseController();
- frame_queue_handle_.Invalidate();
is_closed_ = true;
+ if (Controller()) {
+ StopFrameDelivery();
+ CloseController();
+ }
+ bool should_clear_queue = true;
{
MutexLocker locker(mutex_);
- is_pending_pull_ = false;
+ num_pending_pulls_ = 0;
if (transferred_source_) {
PostCrossThreadTask(
*transferred_source_->GetRealmRunner(), FROM_HERE,
CrossThreadBindOnce(
&FrameQueueUnderlyingSource<NativeFrameType>::Close,
WrapCrossThreadWeakPersistent(transferred_source_.Get())));
+ // The queue will be cleared by |transferred_source_|.
+ should_clear_queue = false;
}
transferred_source_.Clear();
}
+ auto frame_queue = frame_queue_handle_.Queue();
+ if (frame_queue && should_clear_queue && MustUseMonitor()) {
+ while (!frame_queue->IsEmpty()) {
+ absl::optional<NativeFrameType> popped_frame = frame_queue->Pop();
+ MutexLocker monitor_locker(GetMonitorMutex());
+ MonitorPopFrameLocked(popped_frame.value());
+ }
+ }
+ // Invalidating will clear the queue in the non-monitoring case if there is
+ // no transferred source.
+ frame_queue_handle_.Invalidate();
}
template <typename NativeFrameType>
@@ -153,14 +196,44 @@ void FrameQueueUnderlyingSource<NativeFrameType>::QueueFrame(
transferred_source_->QueueFrame(std::move(media_frame));
return;
}
- should_send_frame_to_stream = is_pending_pull_;
+ should_send_frame_to_stream = num_pending_pulls_ > 0;
}
auto frame_queue = frame_queue_handle_.Queue();
if (!frame_queue)
return;
- frame_queue->Push(std::move(media_frame));
+ if (MustUseMonitor()) {
+ MutexLocker queue_locker(frame_queue->GetMutex());
+ MutexLocker monitor_locker(GetMonitorMutex());
+ absl::optional<NativeFrameType> oldest_frame = frame_queue->PeekLocked();
+ NewFrameAction action = AnalyzeNewFrameLocked(media_frame, oldest_frame);
+ switch (action) {
+ case NewFrameAction::kPush: {
+ MonitorPushFrameLocked(media_frame);
+ absl::optional<NativeFrameType> replaced_frame =
+ frame_queue->PushLocked(std::move(media_frame));
+ if (replaced_frame.has_value())
+ MonitorPopFrameLocked(replaced_frame.value());
+ break;
+ }
+ case NewFrameAction::kReplace:
+ MonitorPushFrameLocked(media_frame);
+ if (oldest_frame.has_value())
+ MonitorPopFrameLocked(oldest_frame.value());
+ // Explicitly pop the old frame and push the new one since the
+ // |frame_pool_size_| limit has been reached and it may be smaller
+ // than the maximum size of |frame_queue|.
+ frame_queue->PopLocked();
+ frame_queue->PushLocked(std::move(media_frame));
+ break;
+ case NewFrameAction::kDrop:
+ // Drop |media_frame| by retuning without doing anything with it.
+ return;
+ }
+ } else {
+ frame_queue->Push(std::move(media_frame));
+ }
if (should_send_frame_to_stream) {
PostCrossThreadTask(
*realm_task_runner_, FROM_HERE,
@@ -178,10 +251,10 @@ void FrameQueueUnderlyingSource<NativeFrameType>::Trace(
}
template <typename NativeFrameType>
-bool FrameQueueUnderlyingSource<NativeFrameType>::IsPendingPullForTesting()
+int FrameQueueUnderlyingSource<NativeFrameType>::NumPendingPullsForTesting()
const {
MutexLocker locker(mutex_);
- return is_pending_pull_;
+ return num_pending_pulls_;
}
template <typename NativeFrameType>
@@ -217,24 +290,110 @@ void FrameQueueUnderlyingSource<
if (!frame_queue)
return;
- absl::optional<NativeFrameType> media_frame = frame_queue->Pop();
- if (!media_frame.has_value())
- return;
-
- Controller()->Enqueue(MakeBlinkFrame(std::move(media_frame.value())));
{
MutexLocker locker(mutex_);
- is_pending_pull_ = false;
+ if (num_pending_pulls_ == 0)
+ return;
+ }
+ while (true) {
+ absl::optional<NativeFrameType> media_frame = frame_queue->Pop();
+ if (!media_frame.has_value())
+ return;
+
+ int frame_id = MustUseMonitor() ? GetFrameId(media_frame.value()) : -1;
+ Controller()->Enqueue(MakeBlinkFrame(std::move(media_frame.value())));
+ // Update the monitor after creating the Blink VideoFrame to avoid
+ // temporarily removing the frame from the monitor.
+ MaybeMonitorPopFrameId(frame_id);
+ {
+ MutexLocker locker(mutex_);
+ if (--num_pending_pulls_ == 0)
+ return;
+ }
}
}
+template <typename NativeFrameType>
+bool FrameQueueUnderlyingSource<NativeFrameType>::MustUseMonitor() const {
+ return !device_id_.empty();
+}
+
+template <typename NativeFrameType>
+Mutex& FrameQueueUnderlyingSource<NativeFrameType>::GetMonitorMutex() {
+ DCHECK(MustUseMonitor());
+ return VideoFrameMonitor::Instance().GetMutex();
+}
+
+template <typename NativeFrameType>
+void FrameQueueUnderlyingSource<NativeFrameType>::MaybeMonitorPopFrameId(
+ int frame_id) {
+ if (!MustUseMonitor())
+ return;
+ VideoFrameMonitor::Instance().OnCloseFrame(device_id_, frame_id);
+}
+
+template <typename NativeFrameType>
+void FrameQueueUnderlyingSource<NativeFrameType>::MonitorPopFrameLocked(
+ const NativeFrameType& media_frame) {
+ DCHECK(MustUseMonitor());
+ int frame_id = GetFrameId(media_frame);
+ VideoFrameMonitor::Instance().OnCloseFrameLocked(device_id_, frame_id);
+}
+
+template <typename NativeFrameType>
+void FrameQueueUnderlyingSource<NativeFrameType>::MonitorPushFrameLocked(
+ const NativeFrameType& media_frame) {
+ DCHECK(MustUseMonitor());
+ int frame_id = GetFrameId(media_frame);
+ VideoFrameMonitor::Instance().OnOpenFrameLocked(device_id_, frame_id);
+}
+
+template <typename NativeFrameType>
+typename FrameQueueUnderlyingSource<NativeFrameType>::NewFrameAction
+FrameQueueUnderlyingSource<NativeFrameType>::AnalyzeNewFrameLocked(
+ const NativeFrameType& new_frame,
+ const absl::optional<NativeFrameType>& oldest_frame) {
+ DCHECK(MustUseMonitor());
+ absl::optional<int> oldest_frame_id;
+ if (oldest_frame.has_value())
+ oldest_frame_id = GetFrameId(oldest_frame.value());
+
+ VideoFrameMonitor& monitor = VideoFrameMonitor::Instance();
+ wtf_size_t num_total_frames = monitor.NumFramesLocked(device_id_);
+ if (num_total_frames < frame_pool_size_) {
+ // The limit is not reached yet.
+ return NewFrameAction::kPush;
+ }
+
+ int new_frame_id = GetFrameId(new_frame);
+ if (monitor.NumRefsLocked(device_id_, new_frame_id) > 0) {
+ // The new frame is already in another queue or exposed to JS, so adding
+ // it to the queue would not count against the limit.
+ return NewFrameAction::kPush;
+ }
+
+ if (!oldest_frame_id.has_value()) {
+ // The limit has been reached and there is nothing that can be replaced.
+ return NewFrameAction::kDrop;
+ }
+
+ if (monitor.NumRefsLocked(device_id_, oldest_frame_id.value()) == 1) {
+ // The frame pool size limit has been reached. However, we can safely
+ // replace the oldest frame in our queue, since it is not referenced
+ // elsewhere.
+ return NewFrameAction::kReplace;
+ }
+
+ return NewFrameAction::kDrop;
+}
+
template <>
ScriptWrappable*
FrameQueueUnderlyingSource<scoped_refptr<media::VideoFrame>>::MakeBlinkFrame(
scoped_refptr<media::VideoFrame> media_frame) {
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
return MakeGarbageCollected<VideoFrame>(std::move(media_frame),
- GetExecutionContext());
+ GetExecutionContext(), device_id_);
}
template <>
@@ -245,6 +404,12 @@ FrameQueueUnderlyingSource<scoped_refptr<media::AudioBuffer>>::MakeBlinkFrame(
return MakeGarbageCollected<AudioData>(std::move(media_frame));
}
+template <>
+bool FrameQueueUnderlyingSource<
+ scoped_refptr<media::AudioBuffer>>::MustUseMonitor() const {
+ return false;
+}
+
template class MODULES_TEMPLATE_EXPORT
FrameQueueUnderlyingSource<scoped_refptr<media::AudioBuffer>>;
template class MODULES_TEMPLATE_EXPORT
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
index 55fe4787a8f..a5d529a4231 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
@@ -24,7 +24,12 @@ class FrameQueueUnderlyingSource
using TransferFramesCB = CrossThreadFunction<void(NativeFrameType)>;
// Initializes a new FrameQueueUnderlyingSource with a new internal circular
- // queue that can hold up to |queue_size| elements.
+ // queue that can hold up to |queue_size| elements. If a nonempty |device_id|
+ // is given, it will be used as a key to monitor open frames.
+ FrameQueueUnderlyingSource(ScriptState*,
+ wtf_size_t queue_size,
+ std::string device_id,
+ wtf_size_t frame_pool_size);
FrameQueueUnderlyingSource(ScriptState*, wtf_size_t queue_size);
~FrameQueueUnderlyingSource() override = default;
@@ -49,10 +54,7 @@ class FrameQueueUnderlyingSource
// Must be called on |realm_task_runner_|.
void Close();
- bool IsClosed() {
- DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
- return is_closed_;
- }
+ bool IsClosed() { return is_closed_; }
// Start or stop the delivery of frames via QueueFrame().
// Must be called on |realm_task_runner_|.
@@ -62,7 +64,7 @@ class FrameQueueUnderlyingSource
// Delivers a new frame to this source.
void QueueFrame(NativeFrameType);
- bool IsPendingPullForTesting() const;
+ int NumPendingPullsForTesting() const;
double DesiredSizeForTesting() const;
void Trace(Visitor*) const override;
@@ -84,6 +86,9 @@ class FrameQueueUnderlyingSource
void TransferSource(
FrameQueueUnderlyingSource<NativeFrameType>* transferred_source);
+ protected:
+ bool MustUseMonitor() const;
+
private:
// Must be called on |realm_task_runner_|.
void CloseController();
@@ -92,12 +97,22 @@ class FrameQueueUnderlyingSource
// into the the stream's controller. Must be called on |realm_task_runner|.
void MaybeSendFrameFromQueueToStream();
+ Mutex& GetMonitorMutex();
+
+ void MaybeMonitorPopFrameId(int frame_id);
+ void MonitorPopFrameLocked(const NativeFrameType& media_frame);
+ void MonitorPushFrameLocked(const NativeFrameType& media_frame);
+
+ enum class NewFrameAction { kPush, kReplace, kDrop };
+ NewFrameAction AnalyzeNewFrameLocked(
+ const NativeFrameType& media_frame,
+ const absl::optional<NativeFrameType>& old_frame);
+
// Creates a JS frame (VideoFrame or AudioData) backed by |media_frame|.
// Must be called on |realm_task_runner_|.
ScriptWrappable* MakeBlinkFrame(NativeFrameType media_frame);
bool is_closed_ = false;
- bool is_pending_close_ = false;
// Main task runner for the window or worker context this source runs on.
const scoped_refptr<base::SequencedTaskRunner> realm_task_runner_;
@@ -115,7 +130,14 @@ class FrameQueueUnderlyingSource
// transferred stream.
CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
transferred_source_ GUARDED_BY(mutex_);
- bool is_pending_pull_ GUARDED_BY(mutex_) = false;
+ int num_pending_pulls_ GUARDED_BY(mutex_) = 0;
+ // When nonempty, |device_id_| is used to monitor all frames queued by this
+ // source or exposed to JS via the stream connected to this source.
+ // Frame monitoring applies only to video. Audio is never monitored.
+ const std::string device_id_;
+ // Maximum number of distinct frames allowed to be used by this source.
+ // This limit applies only when |device_id_| is nonempty.
+ const wtf_size_t frame_pool_size_ = 0;
};
template <>
@@ -126,6 +148,10 @@ template <>
ScriptWrappable* FrameQueueUnderlyingSource<scoped_refptr<media::AudioBuffer>>::
MakeBlinkFrame(scoped_refptr<media::AudioBuffer>);
+template <>
+bool FrameQueueUnderlyingSource<
+ scoped_refptr<media::AudioBuffer>>::MustUseMonitor() const;
+
extern template class MODULES_EXTERN_TEMPLATE_EXPORT
FrameQueueUnderlyingSource<scoped_refptr<media::VideoFrame>>;
extern template class MODULES_EXTERN_TEMPLATE_EXPORT
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.cc
index 902236bad96..35a778c6ec4 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.cc
@@ -18,19 +18,29 @@
namespace blink {
namespace {
-class PlaceholderTransferringOptimizer
- : public WritableStreamTransferringOptimizer {
+
+class TransferringOptimizer : public WritableStreamTransferringOptimizer {
+ public:
+ explicit TransferringOptimizer(
+ scoped_refptr<PushableMediaStreamAudioSource::Broker> source_broker)
+ : source_broker_(std::move(source_broker)) {}
UnderlyingSinkBase* PerformInProcessOptimization(
ScriptState* script_state) override {
RecordBreakoutBoxUsage(BreakoutBoxUsage::kWritableAudioWorker);
- return nullptr;
+ return MakeGarbageCollected<MediaStreamAudioTrackUnderlyingSink>(
+ source_broker_);
}
+
+ private:
+ const scoped_refptr<PushableMediaStreamAudioSource::Broker> source_broker_;
};
+
} // namespace
MediaStreamAudioTrackUnderlyingSink::MediaStreamAudioTrackUnderlyingSink(
- PushableMediaStreamAudioSource* source)
- : source_(source->GetWeakPtr()) {
+ scoped_refptr<PushableMediaStreamAudioSource::Broker> source_broker)
+ : source_broker_(std::move(source_broker)) {
+ DCHECK(source_broker_);
RecordBreakoutBoxUsage(BreakoutBoxUsage::kWritableAudio);
}
@@ -38,6 +48,9 @@ ScriptPromise MediaStreamAudioTrackUnderlyingSink::start(
ScriptState* script_state,
WritableStreamDefaultController* controller,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ source_broker_->OnClientStarted();
+ is_connected_ = true;
return ScriptPromise::CastUndefined(script_state);
}
@@ -46,6 +59,7 @@ ScriptPromise MediaStreamAudioTrackUnderlyingSink::write(
ScriptValue chunk,
WritableStreamDefaultController* controller,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
AudioData* audio_data = V8AudioData::ToImplWithTypeCheck(
script_state->GetIsolate(), chunk.V8Value());
if (!audio_data) {
@@ -58,15 +72,13 @@ ScriptPromise MediaStreamAudioTrackUnderlyingSink::write(
return ScriptPromise();
}
- PushableMediaStreamAudioSource* pushable_source =
- static_cast<PushableMediaStreamAudioSource*>(source_.get());
- if (!pushable_source || !pushable_source->running()) {
+ if (!source_broker_->IsRunning()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Stream closed");
return ScriptPromise();
}
- pushable_source->PushAudioData(audio_data->data());
+ source_broker_->PushAudioData(audio_data->data());
audio_data->close();
return ScriptPromise::CastUndefined(script_state);
@@ -76,22 +88,32 @@ ScriptPromise MediaStreamAudioTrackUnderlyingSink::abort(
ScriptState* script_state,
ScriptValue reason,
ExceptionState& exception_state) {
- if (source_)
- source_->StopSource();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ Disconnect();
return ScriptPromise::CastUndefined(script_state);
}
ScriptPromise MediaStreamAudioTrackUnderlyingSink::close(
ScriptState* script_state,
ExceptionState& exception_state) {
- if (source_)
- source_->StopSource();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ Disconnect();
return ScriptPromise::CastUndefined(script_state);
}
std::unique_ptr<WritableStreamTransferringOptimizer>
MediaStreamAudioTrackUnderlyingSink::GetTransferringOptimizer() {
- return std::make_unique<PlaceholderTransferringOptimizer>();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return std::make_unique<TransferringOptimizer>(source_broker_);
+}
+
+void MediaStreamAudioTrackUnderlyingSink::Disconnect() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!is_connected_)
+ return;
+
+ source_broker_->OnClientStopped();
+ is_connected_ = false;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.h b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.h
index 4411d65b57b..297249e5801 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.h
@@ -6,13 +6,12 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_MEDIA_STREAM_AUDIO_TRACK_UNDERLYING_SINK_H_
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
+#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
namespace blink {
-class MediaStreamAudioSource;
-class PushableMediaStreamAudioSource;
class WritableStreamTransferringOptimizer;
class MODULES_EXPORT MediaStreamAudioTrackUnderlyingSink
@@ -20,7 +19,7 @@ class MODULES_EXPORT MediaStreamAudioTrackUnderlyingSink
public:
// |source| must outlive this MediaStreamAudioTrackUnderlyingSink.
explicit MediaStreamAudioTrackUnderlyingSink(
- PushableMediaStreamAudioSource* source);
+ scoped_refptr<PushableMediaStreamAudioSource::Broker> source_broker);
// UnderlyingSinkBase overrides.
ScriptPromise start(ScriptState* script_state,
@@ -40,7 +39,10 @@ class MODULES_EXPORT MediaStreamAudioTrackUnderlyingSink
GetTransferringOptimizer();
private:
- base::WeakPtr<MediaStreamAudioSource> source_;
+ void Disconnect();
+ const scoped_refptr<PushableMediaStreamAudioSource::Broker> source_broker_;
+ bool is_connected_ = false;
+ SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc
index 37cb8bbfa07..309fcc224a7 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc
@@ -51,7 +51,7 @@ class MediaStreamAudioTrackUnderlyingSinkTest : public testing::Test {
MediaStreamAudioTrackUnderlyingSink* CreateUnderlyingSink(
ScriptState* script_state) {
return MakeGarbageCollected<MediaStreamAudioTrackUnderlyingSink>(
- pushable_audio_source_);
+ pushable_audio_source_->GetBroker());
}
void CreateTrackAndConnectToSource() {
@@ -110,13 +110,13 @@ TEST_F(MediaStreamAudioTrackUnderlyingSinkTest,
AudioData* audio_data = nullptr;
auto audio_data_chunk = CreateAudioData(script_state, &audio_data);
EXPECT_NE(audio_data, nullptr);
- EXPECT_NE(audio_data->buffer(), nullptr);
+ EXPECT_NE(audio_data->data(), nullptr);
ScriptPromiseTester write_tester(
script_state,
writer->write(script_state, audio_data_chunk, exception_state));
// |audio_data| should be invalidated after sending it to the sink.
write_tester.WaitUntilSettled();
- EXPECT_EQ(audio_data->buffer(), nullptr);
+ EXPECT_EQ(audio_data->data(), nullptr);
write_loop.Run();
writer->releaseLock(script_state);
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
index 218df8dc44f..16b6313aa82 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
@@ -6,23 +6,14 @@
#include "media/base/audio_buffer.h"
#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
+#include "third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h"
#include "third_party/blink/renderer/modules/breakout_box/metrics.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
-namespace {
-class PlaceholderTransferringOptimizer
- : public ReadableStreamTransferringOptimizer {
- UnderlyingSourceBase* PerformInProcessOptimization(
- ScriptState* script_state) override {
- RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableAudioWorker);
- return nullptr;
- }
-};
-} // namespace
-
MediaStreamAudioTrackUnderlyingSource::MediaStreamAudioTrackUnderlyingSource(
ScriptState* script_state,
MediaStreamComponent* track,
@@ -41,7 +32,11 @@ bool MediaStreamAudioTrackUnderlyingSource::StartFrameDelivery() {
if (!audio_track)
return false;
+ if (added_to_track_)
+ return true;
+
WebMediaStreamAudioSink::AddToAudioTrack(this, WebMediaStreamTrack(track_));
+ added_to_track_ = true;
return true;
}
@@ -52,7 +47,7 @@ void MediaStreamAudioTrackUnderlyingSource::DisconnectFromTrack() {
WebMediaStreamAudioSink::RemoveFromAudioTrack(this,
WebMediaStreamTrack(track_));
-
+ added_to_track_ = false;
track_.Clear();
}
@@ -92,7 +87,20 @@ void MediaStreamAudioTrackUnderlyingSource::OnSetFormat(
std::unique_ptr<ReadableStreamTransferringOptimizer>
MediaStreamAudioTrackUnderlyingSource::GetTransferringOptimizer() {
- return std::make_unique<PlaceholderTransferringOptimizer>();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return std::make_unique<AudioDataQueueTransferOptimizer>(
+ this, GetRealmRunner(), MaxQueueSize(),
+ CrossThreadBindOnce(
+ &MediaStreamAudioTrackUnderlyingSource::OnSourceTransferStarted,
+ WrapCrossThreadWeakPersistent(this)));
+}
+
+void MediaStreamAudioTrackUnderlyingSource::OnSourceTransferStarted(
+ scoped_refptr<base::SequencedTaskRunner> transferred_runner,
+ TransferredAudioDataQueueUnderlyingSource* source) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ TransferSource(source);
+ RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableAudioWorker);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
index fb6ebe5d558..c0d8bcf69a1 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
@@ -9,6 +9,7 @@
#include "media/base/audio_parameters.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h"
#include "third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h"
+#include "third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
@@ -52,12 +53,16 @@ class MODULES_EXPORT MediaStreamAudioTrackUnderlyingSource
void StopFrameDelivery() override;
void DisconnectFromTrack();
+ void OnSourceTransferStarted(
+ scoped_refptr<base::SequencedTaskRunner> transferred_runner,
+ TransferredAudioDataQueueUnderlyingSource* source);
// Only used to prevent the gargabe collector from reclaiming the media
// stream track processor that created |this|.
const Member<ScriptWrappable> media_stream_track_processor_;
Member<MediaStreamComponent> track_;
+ bool added_to_track_ = false;
media::AudioParameters audio_parameters_;
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source_test.cc
index 470cd05a175..e987ab0e083 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source_test.cc
@@ -183,9 +183,9 @@ TEST_F(MediaStreamAudioTrackUnderlyingSourceTest,
// Pulling causes a pending pull since there are no frames available for
// reading.
- EXPECT_FALSE(source->IsPendingPullForTesting());
+ EXPECT_EQ(source->NumPendingPullsForTesting(), 0);
source->pull(script_state);
- EXPECT_TRUE(source->IsPendingPullForTesting());
+ EXPECT_EQ(source->NumPendingPullsForTesting(), 1);
source->Close();
WebMediaStreamAudioSink::RemoveFromAudioTrack(
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.cc
index b18c345dfd0..44030469910 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.cc
@@ -8,14 +8,12 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_generator_init.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
#include "third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h"
#include "third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink.h"
#include "third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.h"
#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h"
#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h"
-#include "third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_utils.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -28,18 +26,6 @@
namespace blink {
-namespace {
-
-const wtf_size_t kDefaultMaxSignalBufferSize = 20u;
-
-class NullUnderlyingSource : public UnderlyingSourceBase {
- public:
- explicit NullUnderlyingSource(ScriptState* script_state)
- : UnderlyingSourceBase(script_state) {}
-};
-
-} // namespace
-
MediaStreamTrackGenerator* MediaStreamTrackGenerator::Create(
ScriptState* script_state,
const String& kind,
@@ -62,8 +48,7 @@ MediaStreamTrackGenerator* MediaStreamTrackGenerator::Create(
return MakeGarbageCollected<MediaStreamTrackGenerator>(
script_state, type,
- /*track_id=*/WTF::CreateCanonicalUUIDString(), nullptr,
- kDefaultMaxSignalBufferSize);
+ /*track_id=*/WTF::CreateCanonicalUUIDString());
}
MediaStreamTrackGenerator* MediaStreamTrackGenerator::Create(
@@ -81,11 +66,6 @@ MediaStreamTrackGenerator* MediaStreamTrackGenerator::Create(
return nullptr;
}
- if (init->hasSignalTarget() && init->signalTarget()->kind() != init->kind()) {
- exception_state.ThrowTypeError("kind and signalTarget.kind() do not match");
- return nullptr;
- }
-
MediaStreamSource::StreamType type;
if (init->kind() == "video") {
type = MediaStreamSource::kTypeVideo;
@@ -96,32 +76,24 @@ MediaStreamTrackGenerator* MediaStreamTrackGenerator::Create(
return nullptr;
}
- wtf_size_t max_signal_buffer_size = kDefaultMaxSignalBufferSize;
- if (init->hasMaxSignalBufferSize())
- max_signal_buffer_size = init->maxSignalBufferSize();
-
return MakeGarbageCollected<MediaStreamTrackGenerator>(
script_state, type,
- /*track_id=*/WTF::CreateCanonicalUUIDString(), init->signalTarget(),
- max_signal_buffer_size);
+ /*track_id=*/WTF::CreateCanonicalUUIDString());
}
MediaStreamTrackGenerator::MediaStreamTrackGenerator(
ScriptState* script_state,
MediaStreamSource::StreamType type,
- const String& track_id,
- MediaStreamTrack* signal_target,
- wtf_size_t max_signal_buffer_size)
+ const String& track_id)
: MediaStreamTrack(
ExecutionContext::From(script_state),
MakeGarbageCollected<MediaStreamComponent>(
MakeGarbageCollected<MediaStreamSource>(track_id,
type,
track_id,
- /*remote=*/false))),
- max_signal_buffer_size_(max_signal_buffer_size) {
+ /*remote=*/false))) {
if (type == MediaStreamSource::kTypeVideo) {
- CreateVideoOutputPlatformTrack(signal_target);
+ CreateVideoOutputPlatformTrack();
} else {
DCHECK_EQ(type, MediaStreamSource::kTypeAudio);
CreateAudioOutputPlatformTrack();
@@ -142,39 +114,19 @@ WritableStream* MediaStreamTrackGenerator::writable(ScriptState* script_state) {
return writable_;
}
-ReadableStream* MediaStreamTrackGenerator::readableControl(
- ScriptState* script_state) {
- if (readable_control_)
- return readable_control_;
-
- if (kind() == "video")
- CreateVideoControlStream(script_state);
- else if (kind() == "audio")
- CreateAudioControlStream(script_state);
-
- return readable_control_;
-}
-
PushableMediaStreamVideoSource* MediaStreamTrackGenerator::PushableVideoSource()
const {
DCHECK_EQ(Component()->Source()->GetType(), MediaStreamSource::kTypeVideo);
return static_cast<PushableMediaStreamVideoSource*>(
+ GetExecutionContext()->GetTaskRunner(TaskType::kInternalMediaRealTime),
MediaStreamVideoSource::GetVideoSource(Component()->Source()));
}
-void MediaStreamTrackGenerator::CreateVideoOutputPlatformTrack(
- MediaStreamTrack* signal_target) {
- base::WeakPtr<MediaStreamVideoSource> signal_target_upstream_source;
- if (signal_target) {
- MediaStreamVideoSource* upstream_source =
- MediaStreamVideoSource::GetVideoSource(
- signal_target->Component()->Source());
- signal_target_upstream_source = upstream_source->GetWeakPtr();
- }
-
+void MediaStreamTrackGenerator::CreateVideoOutputPlatformTrack() {
std::unique_ptr<PushableMediaStreamVideoSource> platform_source =
std::make_unique<PushableMediaStreamVideoSource>(
- signal_target_upstream_source);
+ GetExecutionContext()->GetTaskRunner(
+ TaskType::kInternalMediaRealTime));
PushableMediaStreamVideoSource* platform_source_ptr = platform_source.get();
Component()->Source()->SetPlatformSource(std::move(platform_source));
std::unique_ptr<MediaStreamVideoTrack> platform_track =
@@ -218,42 +170,17 @@ void MediaStreamTrackGenerator::CreateAudioStream(ScriptState* script_state) {
static_cast<PushableMediaStreamAudioSource*>(
Component()->Source()->GetPlatformSource());
audio_underlying_sink_ =
- MakeGarbageCollected<MediaStreamAudioTrackUnderlyingSink>(source);
+ MakeGarbageCollected<MediaStreamAudioTrackUnderlyingSink>(
+ source->GetBroker());
writable_ = WritableStream::CreateWithCountQueueingStrategy(
script_state, audio_underlying_sink_, /*high_water_mark=*/1,
audio_underlying_sink_->GetTransferringOptimizer());
}
-void MediaStreamTrackGenerator::CreateVideoControlStream(
- ScriptState* script_state) {
- DCHECK(!readable_control_);
- // TODO(crbug.com/1142955): Make the queue size configurable from the
- // constructor.
- control_underlying_source_ =
- MakeGarbageCollected<VideoTrackSignalUnderlyingSource>(
- script_state, this, max_signal_buffer_size_);
- readable_control_ = ReadableStream::CreateWithCountQueueingStrategy(
- script_state, control_underlying_source_, /*high_water_mark=*/0);
-}
-
-void MediaStreamTrackGenerator::CreateAudioControlStream(
- ScriptState* script_state) {
- DCHECK(!readable_control_);
- // Since no signals have been defined for audio, use a null source that
- // does nothing, so that a valid stream can be returned for audio
- // MediaStreamTrackGenerators.
- control_underlying_source_ =
- MakeGarbageCollected<NullUnderlyingSource>(script_state);
- readable_control_ = ReadableStream::CreateWithCountQueueingStrategy(
- script_state, control_underlying_source_, /*high_water_mark=*/0);
-}
-
void MediaStreamTrackGenerator::Trace(Visitor* visitor) const {
visitor->Trace(video_underlying_sink_);
visitor->Trace(audio_underlying_sink_);
visitor->Trace(writable_);
- visitor->Trace(control_underlying_source_);
- visitor->Trace(readable_control_);
MediaStreamTrack::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h
index cf18289fd7d..6cf6009a24f 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h
@@ -15,9 +15,7 @@ class MediaStreamAudioTrackUnderlyingSink;
class MediaStreamTrackGeneratorInit;
class MediaStreamVideoTrackUnderlyingSink;
class PushableMediaStreamVideoSource;
-class ReadableStream;
class ScriptState;
-class UnderlyingSourceBase;
class WritableStream;
class MODULES_EXPORT MediaStreamTrackGenerator : public MediaStreamTrack {
@@ -32,15 +30,12 @@ class MODULES_EXPORT MediaStreamTrackGenerator : public MediaStreamTrack {
ExceptionState&);
MediaStreamTrackGenerator(ScriptState*,
MediaStreamSource::StreamType,
- const String& track_id,
- MediaStreamTrack* signal_target,
- wtf_size_t max_signal_buffer_size);
+ const String& track_id);
MediaStreamTrackGenerator(const MediaStreamTrackGenerator&) = delete;
MediaStreamTrackGenerator& operator=(const MediaStreamTrackGenerator&) =
delete;
WritableStream* writable(ScriptState* script_state);
- ReadableStream* readableControl(ScriptState* script_state);
PushableMediaStreamVideoSource* PushableVideoSource() const;
@@ -50,18 +45,12 @@ class MODULES_EXPORT MediaStreamTrackGenerator : public MediaStreamTrack {
void CreateAudioOutputPlatformTrack();
void CreateAudioStream(ScriptState* script_state);
- void CreateVideoOutputPlatformTrack(MediaStreamTrack* signal_target);
+ void CreateVideoOutputPlatformTrack();
void CreateVideoStream(ScriptState* script_state);
- void CreateAudioControlStream(ScriptState* script_state);
- void CreateVideoControlStream(ScriptState* script_state);
-
Member<MediaStreamAudioTrackUnderlyingSink> audio_underlying_sink_;
Member<MediaStreamVideoTrackUnderlyingSink> video_underlying_sink_;
Member<WritableStream> writable_;
- Member<UnderlyingSourceBase> control_underlying_source_;
- Member<ReadableStream> readable_control_;
- const wtf_size_t max_signal_buffer_size_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.idl b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.idl
index 7cdd15d9c41..25946bb92a5 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.idl
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.idl
@@ -16,7 +16,4 @@ interface MediaStreamTrackGenerator : MediaStreamTrack {
// This streams takes VideoFrame or AudioData objects.
[CallWith=ScriptState] readonly attribute WritableStream writable;
-
- // This stream returns MediaStreamTrackSignal objects.
- [CallWith=ScriptState] readonly attribute ReadableStream readableControl;
};
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator_test.cc
index 2eefac01cf2..bc0ded42fb5 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_generator_test.cc
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_generator_init.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
@@ -165,33 +164,6 @@ TEST_F(MediaStreamTrackGeneratorTest, AudioDataAreWritten) {
histogram_tester.ExpectTotalCount("Media.BreakoutBox.Usage", 1);
}
-TEST_F(MediaStreamTrackGeneratorTest, SignalsAreRead) {
- base::HistogramTester histogram_tester;
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- MediaStreamTrackGenerator* generator = MediaStreamTrackGenerator::Create(
- script_state, "video", ASSERT_NO_EXCEPTION);
-
- auto* video_source = generator->PushableVideoSource();
- auto* video_track = MediaStreamVideoTrack::From(generator->Component());
-
- auto* reader =
- generator->readableControl(script_state)
- ->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
- video_source->RequestRefreshFrame();
- auto* signal = ReadObjectFromStream<MediaStreamTrackSignal>(v8_scope, reader);
- EXPECT_EQ(signal->signalType(), "request-frame");
-
- const double min_frame_rate = 3.5;
- video_track->SetMinimumFrameRate(min_frame_rate);
- signal = ReadObjectFromStream<MediaStreamTrackSignal>(v8_scope, reader);
- EXPECT_EQ(signal->signalType(), "set-min-frame-rate");
- EXPECT_TRUE(signal->hasFrameRate());
- EXPECT_EQ(signal->frameRate(), min_frame_rate);
- histogram_tester.ExpectUniqueSample(
- "Media.BreakoutBox.Usage", BreakoutBoxUsage::kReadableControlVideo, 1);
- histogram_tester.ExpectTotalCount("Media.BreakoutBox.Usage", 1);
-}
TEST_F(MediaStreamTrackGeneratorTest, FramesDoNotFlowOnStoppedGenerator) {
V8TestingScope v8_scope;
@@ -317,53 +289,4 @@ TEST_F(MediaStreamTrackGeneratorTest, CloneStopSource) {
EXPECT_TRUE(clone->Ended());
}
-TEST_F(MediaStreamTrackGeneratorTest, SignalsFlowFromGeneratorToProcessor) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- auto* generator = MediaStreamTrackGenerator::Create(script_state, "video",
- ASSERT_NO_EXCEPTION);
-
- // Create a processor connected to a mock source.
- auto* mock_video_source = CreateMockVideoSource();
- auto* processor = MediaStreamTrackProcessor::Create(
- script_state,
- CreateVideoMediaStreamTrack(v8_scope.GetExecutionContext(),
- mock_video_source),
- ASSERT_NO_EXCEPTION);
- mock_video_source->StartMockedSource();
-
- // Connect the generator to the processor.
- generator->readableControl(script_state)
- ->pipeTo(script_state, processor->writableControl(script_state),
- ASSERT_NO_EXCEPTION);
-
- // Push a signal to the generator and verify that it makes it to the mock
- // source backing the processor at the end of the chain.
- base::RunLoop loop;
- EXPECT_CALL(*mock_video_source, OnRequestRefreshFrame())
- .WillOnce(base::test::RunOnceClosure(loop.QuitClosure()));
- generator->PushableVideoSource()->RequestRefreshFrame();
- loop.Run();
-}
-
-TEST_F(MediaStreamTrackGeneratorTest, ImplicitSignalsAreForwarded) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
-
- MockMediaStreamVideoSource* mock_source = CreateMockVideoSource();
- MediaStreamTrack* signal_target =
- CreateVideoMediaStreamTrack(v8_scope.GetExecutionContext(), mock_source);
- mock_source->StartMockedSource();
-
- auto* init = MediaStreamTrackGeneratorInit::Create();
- init->setKind("video");
- init->setSignalTarget(signal_target);
- auto* generator = MediaStreamTrackGenerator::Create(script_state, init,
- ASSERT_NO_EXCEPTION);
- // Send a signal to the generator. It should be forwarded to the source of the
- // |signal_target| track.
- EXPECT_CALL(*mock_source, OnRequestRefreshFrame());
- generator->PushableVideoSource()->RequestRefreshFrame();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.cc
index cc6e85c9cc2..267be57cedd 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.cc
@@ -8,10 +8,8 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_processor_init.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/core/streams/writable_stream.h"
#include "third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h"
#include "third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h"
-#include "third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_utils.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
@@ -22,38 +20,6 @@
namespace blink {
-namespace {
-
-// Trivial sink for audio control signals.
-class NullUnderlyingSink : public UnderlyingSinkBase {
- public:
- // UnderlyingSinkBase overrides.
- ScriptPromise start(ScriptState* script_state,
- WritableStreamDefaultController* controller,
- ExceptionState& exception_state) override {
- return ScriptPromise::CastUndefined(script_state);
- }
-
- ScriptPromise write(ScriptState* script_state,
- ScriptValue chunk,
- WritableStreamDefaultController* controller,
- ExceptionState& exception_state) override {
- exception_state.ThrowTypeError("Invalid audio signal");
- return ScriptPromise();
- }
- ScriptPromise abort(ScriptState* script_state,
- ScriptValue reason,
- ExceptionState& exception_state) override {
- return ScriptPromise::CastUndefined(script_state);
- }
- ScriptPromise close(ScriptState* script_state,
- ExceptionState& exception_state) override {
- return ScriptPromise::CastUndefined(script_state);
- }
-};
-
-} // namespace
-
// A MediaStreamTrack Observer which closes the provided
// UnderlyingSource whenever the provided track is ended.
class MediaStreamTrackProcessor::UnderlyingSourceCloser
@@ -108,20 +74,6 @@ ReadableStream* MediaStreamTrackProcessor::readable(ScriptState* script_state) {
return source_stream_;
}
-WritableStream* MediaStreamTrackProcessor::writableControl(
- ScriptState* script_state) {
- if (control_stream_)
- return control_stream_;
-
- if (input_track_->Component()->Source()->GetType() ==
- MediaStreamSource::kTypeVideo) {
- CreateVideoControlStream(script_state);
- } else {
- CreateAudioControlStream(script_state);
- }
- return control_stream_;
-}
-
void MediaStreamTrackProcessor::CreateVideoSourceStream(
ScriptState* script_state) {
DCHECK(!source_stream_);
@@ -146,23 +98,6 @@ void MediaStreamTrackProcessor::CreateAudioSourceStream(
audio_underlying_source_->GetTransferringOptimizer());
}
-void MediaStreamTrackProcessor::CreateVideoControlStream(
- ScriptState* script_state) {
- DCHECK(!control_stream_);
- signal_underlying_sink_ =
- MakeGarbageCollected<VideoTrackSignalUnderlyingSink>(input_track_);
- control_stream_ = WritableStream::CreateWithCountQueueingStrategy(
- script_state, signal_underlying_sink_, /*high_water_mark=*/1u);
-}
-
-void MediaStreamTrackProcessor::CreateAudioControlStream(
- ScriptState* script_state) {
- DCHECK(!control_stream_);
- signal_underlying_sink_ = MakeGarbageCollected<NullUnderlyingSink>();
- control_stream_ = WritableStream::CreateWithCountQueueingStrategy(
- script_state, signal_underlying_sink_, /*high_water_mark=*/1u);
-}
-
MediaStreamTrackProcessor* MediaStreamTrackProcessor::Create(
ScriptState* script_state,
MediaStreamTrack* track,
@@ -230,9 +165,7 @@ void MediaStreamTrackProcessor::Trace(Visitor* visitor) const {
visitor->Trace(input_track_);
visitor->Trace(audio_underlying_source_);
visitor->Trace(video_underlying_source_);
- visitor->Trace(signal_underlying_sink_);
visitor->Trace(source_stream_);
- visitor->Trace(control_stream_);
visitor->Trace(source_closer_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.h b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.h
index 6564031b25f..76e3f5938f5 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.h
@@ -20,8 +20,6 @@ class MediaStreamTrack;
class MediaStreamTrackProcessorInit;
class ReadableStream;
class ScriptState;
-class UnderlyingSinkBase;
-class WritableStream;
class MODULES_EXPORT MediaStreamTrackProcessor : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -46,7 +44,6 @@ class MODULES_EXPORT MediaStreamTrackProcessor : public ScriptWrappable {
// MediaStreamTrackProcessor interface
ReadableStream* readable(ScriptState* script_state);
- WritableStream* writableControl(ScriptState* script_state);
// Closes |audio_underlying_source_| and |video_underlying_source_| if they
// exist.
@@ -59,17 +56,13 @@ class MODULES_EXPORT MediaStreamTrackProcessor : public ScriptWrappable {
private:
void CreateVideoSourceStream(ScriptState* script_state);
void CreateAudioSourceStream(ScriptState* script_state);
- void CreateVideoControlStream(ScriptState* script_state);
- void CreateAudioControlStream(ScriptState* script_state);
class UnderlyingSourceCloser;
Member<MediaStreamTrack> input_track_;
Member<MediaStreamVideoTrackUnderlyingSource> video_underlying_source_;
Member<MediaStreamAudioTrackUnderlyingSource> audio_underlying_source_;
- Member<UnderlyingSinkBase> signal_underlying_sink_;
Member<ReadableStream> source_stream_;
- Member<WritableStream> control_stream_;
Member<UnderlyingSourceCloser> source_closer_;
uint16_t buffer_size_;
};
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.idl b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.idl
index a9e7997dd3a..34a6850d372 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.idl
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor.idl
@@ -16,7 +16,4 @@ interface MediaStreamTrackProcessor {
// This stream returns VideoFrame or AudioFrame objects.
[CallWith=ScriptState] readonly attribute ReadableStream readable;
-
- // This stream accepts MediaStreamTrackSignal objects
- [CallWith=ScriptState] readonly attribute WritableStream writableControl;
};
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor_test.cc
index 701e159f906..6218b8dd719 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_processor_test.cc
@@ -7,15 +7,16 @@
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/metrics/histogram_tester.h"
+#include "build/build_config.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_generator_init.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
@@ -45,13 +46,14 @@ namespace {
std::unique_ptr<PushableMediaStreamAudioSource> CreatePushableAudioSource() {
// Use the IO thread for testing purposes.
return std::make_unique<PushableMediaStreamAudioSource>(
- Thread::MainThread()->GetTaskRunner(),
+ scheduler::GetSingleThreadTaskRunnerForTesting(),
Platform::Current()->GetIOTaskRunner());
}
PushableMediaStreamVideoSource* CreatePushableVideoSource() {
PushableMediaStreamVideoSource* pushable_video_source =
- new PushableMediaStreamVideoSource();
+ new PushableMediaStreamVideoSource(
+ scheduler::GetSingleThreadTaskRunnerForTesting());
MediaStreamSource* media_stream_source =
MakeGarbageCollected<MediaStreamSource>(
"source_id", MediaStreamSource::kTypeVideo, "source_name",
@@ -80,32 +82,6 @@ MediaStreamTrack* CreateAudioMediaStreamTrack(
return MakeGarbageCollected<MediaStreamTrack>(context, component);
}
-ScriptValue CreateRequestFrameChunk(ScriptState* script_state) {
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType("request-frame");
- return ScriptValue(script_state->GetIsolate(),
- ToV8(signal, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
-}
-
-ScriptValue CreateSetMinFrameRateChunk(ScriptState* script_state,
- double frame_rate) {
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType("set-min-frame-rate");
- signal->setFrameRate(frame_rate);
- return ScriptValue(script_state->GetIsolate(),
- ToV8(signal, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
-}
-
-ScriptValue CreateInvalidSignalChunk(ScriptState* script_state) {
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType("set-min-frame-rate");
- return ScriptValue(script_state->GetIsolate(),
- ToV8(signal, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
-}
-
} // namespace
class MediaStreamTrackProcessorTest : public testing::Test {
@@ -223,84 +199,6 @@ TEST_F(MediaStreamTrackProcessorTest, AudioDataAreExposed) {
histogram_tester.ExpectTotalCount("Media.BreakoutBox.Usage", 1);
}
-TEST_F(MediaStreamTrackProcessorTest, VideoControlSignalsAreForwarded) {
- base::HistogramTester histogram_tester;
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- ExceptionState& exception_state = v8_scope.GetExceptionState();
- MockMediaStreamVideoSource* mock_video_source = CreateMockVideoSource();
- MediaStreamTrackProcessor* track_processor =
- MediaStreamTrackProcessor::Create(
- script_state,
- CreateVideoMediaStreamTrack(v8_scope.GetExecutionContext(),
- mock_video_source),
- exception_state);
- EXPECT_FALSE(exception_state.HadException());
- EXPECT_EQ(
- track_processor->InputTrack()->Component()->Source()->GetPlatformSource(),
- mock_video_source);
- mock_video_source->StartMockedSource();
-
- EXPECT_CALL(*mock_video_source, OnRequestRefreshFrame());
- auto* writer = track_processor->writableControl(script_state)
- ->getWriter(script_state, exception_state);
- ScriptPromiseTester request_frame_tester(
- script_state,
- writer->write(script_state, CreateRequestFrameChunk(script_state),
- exception_state));
- request_frame_tester.WaitUntilSettled();
- EXPECT_TRUE(request_frame_tester.IsFulfilled());
- EXPECT_FALSE(exception_state.HadException());
-
- MediaStreamVideoTrack* platform_track =
- MediaStreamVideoTrack::From(track_processor->InputTrack()->Component());
- EXPECT_FALSE(platform_track->min_frame_rate().has_value());
- const double min_frame_rate = 15.0;
- ScriptPromiseTester set_min_frame_rate_tester(
- script_state,
- writer->write(script_state,
- CreateSetMinFrameRateChunk(script_state, min_frame_rate),
- exception_state));
- set_min_frame_rate_tester.WaitUntilSettled();
- EXPECT_TRUE(set_min_frame_rate_tester.IsFulfilled());
- EXPECT_FALSE(exception_state.HadException());
- EXPECT_TRUE(platform_track->min_frame_rate().has_value());
- EXPECT_EQ(platform_track->min_frame_rate().value(), min_frame_rate);
-
- ScriptPromiseTester invalid_signal_tester(
- script_state,
- writer->write(script_state, CreateInvalidSignalChunk(script_state),
- exception_state));
- invalid_signal_tester.WaitUntilSettled();
- EXPECT_TRUE(invalid_signal_tester.IsRejected());
- histogram_tester.ExpectUniqueSample(
- "Media.BreakoutBox.Usage", BreakoutBoxUsage::kWritableControlVideo, 1);
- histogram_tester.ExpectTotalCount("Media.BreakoutBox.Usage", 1);
-}
-
-TEST_F(MediaStreamTrackProcessorTest, AudioControlSignalsAreRejected) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- ExceptionState& exception_state = v8_scope.GetExceptionState();
- MediaStreamTrackProcessor* track_processor =
- MediaStreamTrackProcessor::Create(
- script_state,
- CreateAudioMediaStreamTrack(v8_scope.GetExecutionContext(),
- std::make_unique<MediaStreamAudioSource>(
- Thread::MainThread()->GetTaskRunner(),
- /*is_local=*/true)),
- exception_state);
-
- auto* writer = track_processor->writableControl(script_state)
- ->getWriter(script_state, exception_state);
- ScriptPromiseTester tester(
- script_state,
- writer->write(script_state, CreateRequestFrameChunk(script_state),
- exception_state));
- tester.WaitUntilSettled();
- EXPECT_TRUE(tester.IsRejected());
-}
-
TEST_F(MediaStreamTrackProcessorTest, CanceledReadableDisconnects) {
V8TestingScope v8_scope;
ScriptState* script_state = v8_scope.GetScriptState();
@@ -446,7 +344,15 @@ TEST_F(MediaStreamTrackProcessorTest, VideoCloseOnTrackEnd) {
EXPECT_TRUE(readable->IsClosed());
}
-TEST_F(MediaStreamTrackProcessorTest, VideoNoCloseOnTrackDisable) {
+#if defined(OS_FUCHSIA)
+// TODO(https://crbug.com/1234343): Test seems flaky on Fuchsia, enable once
+// flakiness has been investigated.
+#define MAYBE_VideoNoCloseOnTrackDisable DISABLED_VideoNoCloseOnTrackDisable
+#else
+#define MAYBE_VideoNoCloseOnTrackDisable VideoNoCloseOnTrackDisable
+#endif
+
+TEST_F(MediaStreamTrackProcessorTest, MAYBE_VideoNoCloseOnTrackDisable) {
V8TestingScope v8_scope;
ScriptState* script_state = v8_scope.GetScriptState();
ExceptionState& exception_state = v8_scope.GetExceptionState();
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_signal.idl b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_signal.idl
deleted file mode 100644
index 905c908b840..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_track_signal.idl
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://w3c.github.io/mediacapture-insertable-streams/#dictdef-mediastreamtracksignal
-
-enum MediaStreamTrackSignalType {
- "request-frame",
- "set-min-frame-rate"
-};
-
-dictionary MediaStreamTrackSignal {
- required MediaStreamTrackSignalType signalType;
- double frameRate;
-};
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink_test.cc
index ba5c39510fb..e0a87fa5f95 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink_test.cc
@@ -7,6 +7,7 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -28,7 +29,8 @@ namespace blink {
class MediaStreamVideoTrackUnderlyingSinkTest : public testing::Test {
public:
MediaStreamVideoTrackUnderlyingSinkTest() {
- pushable_video_source_ = new PushableMediaStreamVideoSource();
+ pushable_video_source_ = new PushableMediaStreamVideoSource(
+ scheduler::GetSingleThreadTaskRunnerForTesting());
media_stream_source_ = MakeGarbageCollected<MediaStreamSource>(
"dummy_source_id", MediaStreamSource::kTypeVideo, "dummy_source_name",
/*remote=*/false);
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
index b6d76784fe6..ca8fa89ce5b 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h"
+#include "base/feature_list.h"
+#include "media/capture/video/video_capture_buffer_pool_util.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/modules/breakout_box/frame_queue_transferring_optimizer.h"
@@ -13,16 +15,38 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/webrtc/api/frame_transformer_interface.h"
namespace blink {
+namespace {
+constexpr char kScreenPrefix[] = "screen:";
+constexpr char kWindowPrefix[] = "window:";
+
+bool IsScreenOrWindowCapture(const std::string& device_id) {
+ return base::StartsWith(device_id, kScreenPrefix,
+ base::CompareCase::SENSITIVE) ||
+ base::StartsWith(device_id, kWindowPrefix,
+ base::CompareCase::SENSITIVE);
+}
+} // namespace
+
+const base::Feature kBreakoutBoxFrameLimiter{"BreakoutBoxFrameLimiter",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+const int MediaStreamVideoTrackUnderlyingSource::kMaxMonitoredFrameCount = 20;
+const int MediaStreamVideoTrackUnderlyingSource::kMinMonitoredFrameCount = 2;
+
MediaStreamVideoTrackUnderlyingSource::MediaStreamVideoTrackUnderlyingSource(
ScriptState* script_state,
MediaStreamComponent* track,
ScriptWrappable* media_stream_track_processor,
wtf_size_t max_queue_size)
- : FrameQueueUnderlyingSource(script_state, max_queue_size),
+ : FrameQueueUnderlyingSource(
+ script_state,
+ max_queue_size,
+ GetDeviceIdForMonitoring(
+ track->Source()->GetPlatformSource()->device()),
+ GetFramePoolSize(track->Source()->GetPlatformSource()->device())),
media_stream_track_processor_(media_stream_track_processor),
track_(track) {
DCHECK(track_);
@@ -90,4 +114,51 @@ void MediaStreamVideoTrackUnderlyingSource::StopFrameDelivery() {
DisconnectFromTrack();
}
+// static
+std::string MediaStreamVideoTrackUnderlyingSource::GetDeviceIdForMonitoring(
+ const MediaStreamDevice& device) {
+ if (!base::FeatureList::IsEnabled(kBreakoutBoxFrameLimiter))
+ return std::string();
+
+ switch (device.type) {
+ case mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
+ return device.id;
+ case mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE:
+ case mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE:
+ if (IsScreenOrWindowCapture(device.id))
+ return device.id;
+ FALLTHROUGH;
+ default:
+ return std::string();
+ }
+}
+
+// static
+wtf_size_t MediaStreamVideoTrackUnderlyingSource::GetFramePoolSize(
+ const MediaStreamDevice& device) {
+ switch (device.type) {
+ case mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
+ return static_cast<wtf_size_t>(std::min(
+ MediaStreamVideoTrackUnderlyingSource::kMaxMonitoredFrameCount,
+ std::max(
+ MediaStreamVideoTrackUnderlyingSource::kMinMonitoredFrameCount,
+ std::max(media::kVideoCaptureDefaultMaxBufferPoolSize / 2,
+ media::DeviceVideoCaptureMaxBufferPoolSize() / 3))));
+ case mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE:
+ case mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE:
+ if (IsScreenOrWindowCapture(device.id)) {
+ return static_cast<wtf_size_t>(std::min(
+ MediaStreamVideoTrackUnderlyingSource::kMaxMonitoredFrameCount,
+ std::max(
+ MediaStreamVideoTrackUnderlyingSource::kMinMonitoredFrameCount,
+ media::kVideoCaptureDefaultMaxBufferPoolSize / 2)));
+ }
+ FALLTHROUGH;
+ default:
+ // There will be no monitoring and no frame pool size. Return 0 to signal
+ // that the returned value will not be used.
+ return 0u;
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
index ddb1f8dc62a..64e067c8b2d 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
@@ -16,6 +16,7 @@
namespace blink {
class MediaStreamComponent;
+struct MediaStreamDevice;
class MODULES_EXPORT MediaStreamVideoTrackUnderlyingSource
: public VideoFrameQueueUnderlyingSource,
@@ -23,6 +24,8 @@ class MODULES_EXPORT MediaStreamVideoTrackUnderlyingSource
public:
using CrossThreadFrameQueueSource =
CrossThreadPersistent<TransferredVideoFrameQueueUnderlyingSource>;
+ static const int kMaxMonitoredFrameCount;
+ static const int kMinMonitoredFrameCount;
explicit MediaStreamVideoTrackUnderlyingSource(
ScriptState*,
@@ -42,7 +45,14 @@ class MODULES_EXPORT MediaStreamVideoTrackUnderlyingSource
GetStreamTransferOptimizer();
private:
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamVideoTrackUnderlyingSourceTest,
+ DeviceIdAndMaxFrameCountForMonitoring);
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamVideoTrackUnderlyingSourceTest,
+ FrameLimiter);
+
scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner();
+ static std::string GetDeviceIdForMonitoring(const MediaStreamDevice& device);
+ static wtf_size_t GetFramePoolSize(const MediaStreamDevice& device);
// FrameQueueUnderlyingSource implementation.
bool StartFrameDelivery() override;
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc
index a809f87af53..307359f7821 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc
@@ -6,8 +6,11 @@
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
+#include "media/capture/video/video_capture_buffer_pool_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -20,6 +23,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
@@ -36,7 +40,8 @@ class MediaStreamVideoTrackUnderlyingSourceTest : public testing::Test {
MediaStreamSource::kTypeVideo,
"dummy_source_name",
false /* remote */)),
- pushable_video_source_(new PushableMediaStreamVideoSource()) {
+ pushable_video_source_(new PushableMediaStreamVideoSource(
+ scheduler::GetSingleThreadTaskRunnerForTesting())) {
media_stream_source_->SetPlatformSource(
base::WrapUnique(pushable_video_source_));
}
@@ -78,6 +83,22 @@ class MediaStreamVideoTrackUnderlyingSourceTest : public testing::Test {
platform_->RunUntilIdle();
}
+ static PushableMediaStreamVideoSource* CreateDevicePushableSource(
+ const std::string& device_id) {
+ auto* media_stream_source = MakeGarbageCollected<MediaStreamSource>(
+ "dummy_source_id", MediaStreamSource::kTypeVideo, "dummy_source_name",
+ false /* remote */);
+ auto* pushable_video_source = new PushableMediaStreamVideoSource(
+ scheduler::GetSingleThreadTaskRunnerForTesting());
+ MediaStreamDevice device(mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE,
+ device_id, "My window device");
+ pushable_video_source->SetDevice(device);
+ media_stream_source->SetPlatformSource(
+ base::WrapUnique(pushable_video_source));
+
+ return pushable_video_source;
+ }
+
ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
const Persistent<MediaStreamSource> media_stream_source_;
PushableMediaStreamVideoSource* const pushable_video_source_;
@@ -177,9 +198,9 @@ TEST_F(MediaStreamVideoTrackUnderlyingSourceTest,
// Pulling causes a pending pull since there are no frames available for
// reading.
- EXPECT_FALSE(source->IsPendingPullForTesting());
+ EXPECT_EQ(source->NumPendingPullsForTesting(), 0);
source->pull(script_state);
- EXPECT_TRUE(source->IsPendingPullForTesting());
+ EXPECT_EQ(source->NumPendingPullsForTesting(), 1);
source->Close();
track->stopTrack(v8_scope.GetExecutionContext());
@@ -211,4 +232,307 @@ TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, PlatformSourceAliveAfterGC) {
blink::WebHeap::CollectAllGarbageForTesting();
}
+TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, CloseOnContextDestroyed) {
+ MediaStreamVideoTrackUnderlyingSource* source = nullptr;
+ {
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = CreateTrack(v8_scope.GetExecutionContext());
+ source = CreateSource(script_state, track, 0u);
+ EXPECT_FALSE(source->IsClosed());
+ // Create a stream so that |source| starts.
+ auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+ v8_scope.GetScriptState(), source, 0);
+ EXPECT_FALSE(source->IsClosed());
+ EXPECT_FALSE(stream->IsClosed());
+ }
+ EXPECT_TRUE(source->IsClosed());
+}
+
+TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, CloseBeforeStart) {
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = CreateTrack(v8_scope.GetExecutionContext());
+ auto* source = CreateSource(script_state, track, 0u);
+ EXPECT_FALSE(source->IsClosed());
+ source->Close();
+ EXPECT_TRUE(source->IsClosed());
+ // Create a stream so that the start method of |source| runs.
+ auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+ v8_scope.GetScriptState(), source, 0);
+ EXPECT_TRUE(source->IsClosed());
+ EXPECT_TRUE(stream->IsClosed());
+}
+
+TEST_F(MediaStreamVideoTrackUnderlyingSourceTest,
+ DeviceIdAndMaxFrameCountForMonitoring) {
+ using M = MediaStreamVideoTrackUnderlyingSource;
+ const std::string window_id = "window:a-window";
+ const std::string screen_id = "screen:a-screen";
+ const std::string tab_id = "web-contents-media-stream://5:1";
+ const std::string camera_id = "my-camera";
+ const std::string mic_id = "my-mic";
+
+ MediaStreamDevice device;
+ device.type = mojom::MediaStreamType::NO_SERVICE;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+
+ device.id = mic_id;
+ device.type = mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+
+ device.id = tab_id;
+ device.type = mojom::MediaStreamType::GUM_TAB_AUDIO_CAPTURE;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+ device.type = mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+
+ device.type = mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE;
+ device.id = screen_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+ device.id = window_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+
+ device.type = mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE;
+ device.id = screen_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+ device.id = window_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+ device.id = tab_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+
+ device.type = mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE_THIS_TAB;
+ device.id = tab_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+
+ // Camera capture is subject to monitoring.
+ device.type = mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE;
+ device.id = camera_id;
+ EXPECT_FALSE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device),
+ static_cast<size_t>(
+ std::max(media::kVideoCaptureDefaultMaxBufferPoolSize / 2,
+ media::DeviceVideoCaptureMaxBufferPoolSize() / 3)));
+
+ // Screen and Window capture with the desktop capture extension API are
+ // subject to monitoring.
+ device.type = mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE;
+ device.id = screen_id;
+ EXPECT_FALSE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(
+ M::GetFramePoolSize(device),
+ static_cast<size_t>(media::kVideoCaptureDefaultMaxBufferPoolSize / 2));
+ device.id = window_id;
+ EXPECT_FALSE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(
+ M::GetFramePoolSize(device),
+ static_cast<size_t>(media::kVideoCaptureDefaultMaxBufferPoolSize / 2));
+
+ // Screen and Window capture with getDisplayMedia are subject to monitoring,
+ // but not tab capture.
+ device.type = mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE;
+ device.id = screen_id;
+ EXPECT_FALSE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(
+ M::GetFramePoolSize(device),
+ static_cast<size_t>(media::kVideoCaptureDefaultMaxBufferPoolSize / 2));
+ device.id = window_id;
+ EXPECT_FALSE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(
+ M::GetFramePoolSize(device),
+ static_cast<size_t>(media::kVideoCaptureDefaultMaxBufferPoolSize / 2));
+ device.id = tab_id;
+ EXPECT_TRUE(M::GetDeviceIdForMonitoring(device).empty());
+ EXPECT_EQ(M::GetFramePoolSize(device), 0u);
+}
+
+TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, FrameLimiter) {
+ const std::string device_id = "window:my-window";
+ auto* pushable_video_source = CreateDevicePushableSource(device_id);
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = MakeGarbageCollected<MediaStreamTrack>(
+ v8_scope.GetExecutionContext(),
+ MediaStreamVideoTrack::CreateVideoTrack(
+ pushable_video_source,
+ MediaStreamVideoSource::ConstraintsOnceCallback(),
+ /*enabled=*/true));
+ // Use a large buffer so that the effective buffer size is guaranteed to be
+ // the one set by frame monitoring.
+ auto* source = CreateSource(
+ script_state, track,
+ MediaStreamVideoTrackUnderlyingSource::kMaxMonitoredFrameCount);
+ const wtf_size_t max_frame_count =
+ MediaStreamVideoTrackUnderlyingSource::GetFramePoolSize(
+ pushable_video_source->device());
+
+ // This test assumes that |max_frame_count| is 2, for simplicity.
+ ASSERT_EQ(max_frame_count, 2u);
+
+ VideoFrameMonitor& monitor = VideoFrameMonitor::Instance();
+ auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+ v8_scope.GetScriptState(), source, 0);
+
+ // Add a sink to the track to make it possible to wait until a pushed frame
+ // is delivered to sinks, including |source|, which is a sink of the track.
+ MockMediaStreamVideoSink mock_sink;
+ mock_sink.ConnectToTrack(WebMediaStreamTrack(source->Track()));
+ auto push_frame_sync = [&](scoped_refptr<media::VideoFrame> video_frame) {
+ base::RunLoop sink_loop;
+ EXPECT_CALL(mock_sink, OnVideoFrame(_))
+ .WillOnce(base::test::RunOnceClosure(sink_loop.QuitClosure()));
+ pushable_video_source->PushFrame(std::move(video_frame),
+ base::TimeTicks::Now());
+ sink_loop.Run();
+ };
+
+ Vector<scoped_refptr<media::VideoFrame>> frames;
+ auto create_video_frame = [&]() {
+ auto frame = media::VideoFrame::CreateBlackFrame(gfx::Size(10, 10));
+ frames.push_back(frame);
+ return frame;
+ };
+ auto get_frame_id = [&](int idx) { return frames[idx]->unique_id(); };
+
+ EXPECT_TRUE(monitor.IsEmpty());
+ // These frames are queued, pending to be read.
+ for (size_t i = 0; i < max_frame_count; ++i) {
+ auto video_frame = create_video_frame();
+ int frame_id = video_frame->unique_id();
+ push_frame_sync(std::move(video_frame));
+ EXPECT_EQ(monitor.NumFrames(device_id), i + 1);
+ EXPECT_EQ(monitor.NumRefs(device_id, frame_id), 1);
+ }
+ {
+ // Push another video frame with the limit reached.
+ auto video_frame = create_video_frame();
+ int frame_id = video_frame->unique_id();
+ push_frame_sync(std::move(video_frame));
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, frame_id), 1);
+
+ // The oldest frame should have been removed from the queue.
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(0)), 0);
+ }
+
+ auto* reader = stream->GetDefaultReaderForTesting(
+ script_state, v8_scope.GetExceptionState());
+ VideoFrame* video_frame1 = ReadObjectFromStream<VideoFrame>(v8_scope, reader);
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(1)), 1);
+
+ VideoFrame* clone_frame1 = video_frame1->clone(v8_scope.GetExceptionState());
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(1)), 2);
+
+ VideoFrame* video_frame2 = ReadObjectFromStream<VideoFrame>(v8_scope, reader);
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(2)), 1);
+
+ // A new frame arrives, but the limit has been reached and there is nothing
+ // that can be replaced.
+ {
+ auto video_frame = create_video_frame();
+ int frame_id = video_frame->unique_id();
+ push_frame_sync(std::move(video_frame));
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, frame_id), 0);
+ }
+
+ // One of the JS VideoFrames backed by frames[1] is closed.
+ clone_frame1->close();
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(1)), 1);
+
+ // A new source connected to the same device is created and started in another
+ // execution context.
+ auto* pushable_video_source2 = CreateDevicePushableSource(device_id);
+ V8TestingScope v8_scope2;
+ ScriptState* script_state2 = v8_scope2.GetScriptState();
+ auto* track2 = MakeGarbageCollected<MediaStreamTrack>(
+ v8_scope2.GetExecutionContext(),
+ MediaStreamVideoTrack::CreateVideoTrack(
+ pushable_video_source2,
+ MediaStreamVideoSource::ConstraintsOnceCallback(),
+ /*enabled=*/true));
+ auto* source2 = CreateSource(
+ script_state2, track2,
+ MediaStreamVideoTrackUnderlyingSource::kMaxMonitoredFrameCount);
+ ReadableStream::CreateWithCountQueueingStrategy(script_state2, source2, 0);
+
+ MockMediaStreamVideoSink mock_sink2;
+ mock_sink2.ConnectToTrack(WebMediaStreamTrack(source2->Track()));
+ auto push_frame_sync2 = [&](scoped_refptr<media::VideoFrame> video_frame) {
+ base::RunLoop sink_loop;
+ EXPECT_CALL(mock_sink2, OnVideoFrame(_))
+ .WillOnce(base::test::RunOnceClosure(sink_loop.QuitClosure()));
+ pushable_video_source2->PushFrame(std::move(video_frame),
+ base::TimeTicks::Now());
+ sink_loop.Run();
+ };
+
+ // The system delivers the last two created frames to the new source.
+ {
+ int idx = frames.size() - 2;
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_GT(monitor.NumRefs(device_id, get_frame_id(idx)), 0);
+ int num_refs = monitor.NumRefs(device_id, get_frame_id(idx));
+ // The limit has been reached, but this frame is already monitored,
+ // so it is queued.
+ push_frame_sync2(frames[idx]);
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(idx)), num_refs + 1);
+ }
+ {
+ int idx = frames.size() - 1;
+ // The limit has been reached, and this frame was dropped by the other
+ // source, so it is dropped by this one too.
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(idx)), 0);
+ push_frame_sync2(frames[idx]);
+ EXPECT_EQ(monitor.NumFrames(device_id), max_frame_count);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(idx)), 0);
+ }
+
+ // The first context closes its source, but its VideoFrame objects are still
+ // open.
+ source->Close();
+
+ // At this point, the only monitored frames are frames[1] and frames[2], both
+ // open in context 1. frames[2] is also queued in context 2.
+ EXPECT_EQ(monitor.NumFrames(device_id), 2u);
+
+ // video_frame1 is the only reference to frames[1].
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(1)), 1);
+
+ // video_frame2 is frames[2] and is open in context 1 and queued in context 2.
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(2)), 2);
+
+ // Context 1 closes its video_frame1.
+ video_frame1->close();
+ EXPECT_EQ(monitor.NumFrames(device_id), 1u);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(1)), 0);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(2)), 2);
+
+ // Context 1 closes its video_frame2, after which the only monitored frame is
+ // the one queued by source 2.
+ video_frame2->close();
+ EXPECT_EQ(monitor.NumFrames(device_id), 1u);
+ EXPECT_EQ(monitor.NumRefs(device_id, get_frame_id(2)), 1);
+
+ // Context 2 closes its source, which should clear everything in the monitor.
+ source2->Close();
+ EXPECT_TRUE(monitor.IsEmpty());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.cc b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.cc
index e31591b2d78..24c4a7ae409 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.cc
@@ -10,17 +10,57 @@
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
-PushableMediaStreamAudioSource::LivenessBroker::LivenessBroker(
+
+PushableMediaStreamAudioSource::Broker::Broker(
PushableMediaStreamAudioSource* source)
- : source_(source) {}
+ : source_(source), main_task_runner_(source->GetTaskRunner()) {
+ DCHECK(main_task_runner_);
+}
-void PushableMediaStreamAudioSource::LivenessBroker::
- OnSourceDestroyedOrStopped() {
+void PushableMediaStreamAudioSource::Broker::OnClientStarted() {
WTF::MutexLocker locker(mutex_);
- source_ = nullptr;
+ DCHECK_GE(num_clients_, 0);
+ ++num_clients_;
+}
+
+void PushableMediaStreamAudioSource::Broker::OnClientStopped() {
+ bool should_stop = false;
+ {
+ WTF::MutexLocker locker(mutex_);
+ should_stop = --num_clients_ == 0;
+ DCHECK_GE(num_clients_, 0);
+ }
+ if (should_stop)
+ StopSource();
+}
+
+bool PushableMediaStreamAudioSource::Broker::IsRunning() {
+ WTF::MutexLocker locker(mutex_);
+ return is_running_;
+}
+
+void PushableMediaStreamAudioSource::Broker::PushAudioData(
+ scoped_refptr<media::AudioBuffer> data) {
+ WTF::MutexLocker locker(mutex_);
+ if (!source_)
+ return;
+
+ source_->PushAudioData(std::move(data));
+}
+
+void PushableMediaStreamAudioSource::Broker::StopSource() {
+ if (main_task_runner_->RunsTasksInCurrentSequence()) {
+ StopSourceOnMain();
+ } else {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(
+ &PushableMediaStreamAudioSource::Broker::StopSourceOnMain,
+ WrapRefCounted(this)));
+ }
}
-void PushableMediaStreamAudioSource::LivenessBroker::PushAudioData(
+void PushableMediaStreamAudioSource::Broker::DeliverData(
scoped_refptr<media::AudioBuffer> data) {
WTF::MutexLocker locker(mutex_);
if (!source_)
@@ -29,17 +69,39 @@ void PushableMediaStreamAudioSource::LivenessBroker::PushAudioData(
source_->DeliverData(std::move(data));
}
+void PushableMediaStreamAudioSource::Broker::OnSourceStarted() {
+ DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+ if (!source_)
+ return;
+
+ WTF::MutexLocker locker(mutex_);
+ is_running_ = true;
+}
+
+void PushableMediaStreamAudioSource::Broker::OnSourceDestroyedOrStopped() {
+ DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+ WTF::MutexLocker locker(mutex_);
+ source_ = nullptr;
+ is_running_ = false;
+}
+
+void PushableMediaStreamAudioSource::Broker::StopSourceOnMain() {
+ DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+ if (!source_)
+ return;
+
+ source_->StopSource();
+}
+
PushableMediaStreamAudioSource::PushableMediaStreamAudioSource(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SequencedTaskRunner> audio_task_runner)
: MediaStreamAudioSource(std::move(main_task_runner), /* is_local */ true),
audio_task_runner_(std::move(audio_task_runner)),
- liveness_broker_(
- base::MakeRefCounted<PushableMediaStreamAudioSource::LivenessBroker>(
- this)) {}
+ broker_(AdoptRef(new Broker(this))) {}
PushableMediaStreamAudioSource::~PushableMediaStreamAudioSource() {
- liveness_broker_->OnSourceDestroyedOrStopped();
+ broker_->OnSourceDestroyedOrStopped();
}
void PushableMediaStreamAudioSource::PushAudioData(
@@ -53,9 +115,8 @@ void PushableMediaStreamAudioSource::PushAudioData(
PostCrossThreadTask(
*audio_task_runner_, FROM_HERE,
- CrossThreadBindOnce(
- &PushableMediaStreamAudioSource::LivenessBroker::PushAudioData,
- liveness_broker_, std::move(data)));
+ CrossThreadBindOnce(&PushableMediaStreamAudioSource::Broker::DeliverData,
+ broker_, std::move(data)));
}
void PushableMediaStreamAudioSource::DeliverData(
@@ -91,14 +152,13 @@ void PushableMediaStreamAudioSource::DeliverData(
bool PushableMediaStreamAudioSource::EnsureSourceIsStarted() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- is_running_ = true;
+ broker_->OnSourceStarted();
return true;
}
void PushableMediaStreamAudioSource::EnsureSourceIsStopped() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- liveness_broker_->OnSourceDestroyedOrStopped();
- is_running_ = false;
+ broker_->OnSourceDestroyedOrStopped();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h
index 0e3ce960677..039f332a760 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source.h
@@ -18,6 +18,61 @@ namespace blink {
class MODULES_EXPORT PushableMediaStreamAudioSource
: public MediaStreamAudioSource {
public:
+ // Helper class that facilitates interacting with a
+ // PushableMediaStreamAudioSource from multiple threads. This also includes
+ // safely posting tasks to/from outside the main thread.
+ // The public methods of this class can be called on any thread.
+ class MODULES_EXPORT Broker : public WTF::ThreadSafeRefCounted<Broker> {
+ public:
+ Broker(const Broker&) = delete;
+ Broker& operator=(const Broker&) = delete;
+
+ // Increases the count of connected clients.
+ void OnClientStarted();
+ // Decreases the count of connected clients. If the count reaches zero,
+ // StopSource() is called.
+ // OnClientStarted() should not be called after the number of clients
+ // reaches zero and StopSource() has been been called. It would have
+ // no effect.
+ // In practice, the clients are WritableStream underlying sources that
+ // use the same PushableMediaStreamAudioSource, such as the sources for
+ // the transferred version of a stream (for example, in a Worker) and the
+ // corresponding original stream (for example, in the Window scope).
+ // During a transfer, a new client is created in the new realm, then the
+ // old client disconnects.
+ void OnClientStopped();
+ bool IsRunning();
+ void PushAudioData(scoped_refptr<media::AudioBuffer> data);
+ void StopSource();
+
+ private:
+ friend class PushableMediaStreamAudioSource;
+
+ explicit Broker(PushableMediaStreamAudioSource* source);
+
+ // Must be called on the audio task runner of |source_|.
+ void DeliverData(scoped_refptr<media::AudioBuffer> data);
+
+ // These functions must be called on |main_task_runner_|.
+ void OnSourceStarted();
+ void OnSourceDestroyedOrStopped();
+ void StopSourceOnMain();
+
+ WTF::Mutex mutex_;
+ // Source can only change its value on |main_task_runner_|. We use |mutex_|
+ // to guard it for value changes and for reads outside |main_task_runner_|.
+ // It is not necessary to guard it with |mutex_| to read its value on
+ // |main_task_runner_|. This helps avoid deadlocks in
+ // Stop()/OnSourceDestroyedOrStopped() interactions.
+ PushableMediaStreamAudioSource* source_;
+ // The same apples to |is_running_|, but since it does not have complex
+ // interactions with owners, like |source_| does, we always guard it for
+ // simplicity.
+ bool is_running_ GUARDED_BY(mutex_) = false;
+ int num_clients_ GUARDED_BY(mutex_) = 0;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ };
+
PushableMediaStreamAudioSource(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SequencedTaskRunner> audio_task_runner);
@@ -28,26 +83,12 @@ class MODULES_EXPORT PushableMediaStreamAudioSource
// |audio_task_runner_|
void PushAudioData(scoped_refptr<media::AudioBuffer> data);
- bool running() const {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- return is_running_;
- }
+ // These functions can be called on any thread.
+ bool IsRunning() const { return broker_->IsRunning(); }
+ scoped_refptr<Broker> GetBroker() const { return broker_; }
private:
- // Helper class that facilitates the jump to |audio_task_runner_|, by
- // outliving the given |source| if there is a pending task.
- class LivenessBroker : public WTF::ThreadSafeRefCounted<LivenessBroker> {
- public:
- explicit LivenessBroker(PushableMediaStreamAudioSource* source);
-
- void OnSourceDestroyedOrStopped();
- void PushAudioData(scoped_refptr<media::AudioBuffer> data);
-
- private:
- WTF::Mutex mutex_;
- PushableMediaStreamAudioSource* source_ GUARDED_BY(mutex_);
- };
-
+ friend class Broker;
// Actually push data to the audio tracks. Only called on
// |audio_task_runner_|.
void DeliverData(scoped_refptr<media::AudioBuffer> data);
@@ -56,14 +97,12 @@ class MODULES_EXPORT PushableMediaStreamAudioSource
bool EnsureSourceIsStarted() final;
void EnsureSourceIsStopped() final;
- bool is_running_ = false;
-
int last_channels_ = 0;
int last_frames_ = 0;
int last_sample_rate_ = 0;
- scoped_refptr<base::SequencedTaskRunner> audio_task_runner_;
- scoped_refptr<LivenessBroker> liveness_broker_;
+ const scoped_refptr<base::SequencedTaskRunner> audio_task_runner_;
+ const scoped_refptr<Broker> broker_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source_test.cc
index 61212ef8a91..4f11b4b0514 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_audio_source_test.cc
@@ -208,18 +208,18 @@ class PushableMediaStreamAudioSourceTest : public testing::Test {
TEST_F(PushableMediaStreamAudioSourceTest, ConnectAndStop) {
EXPECT_EQ(MediaStreamSource::kReadyStateLive,
stream_source_->GetReadyState());
- EXPECT_FALSE(pushable_audio_source_->running());
+ EXPECT_FALSE(pushable_audio_source_->IsRunning());
EXPECT_TRUE(ConnectSourceToTrack());
EXPECT_EQ(MediaStreamSource::kReadyStateLive,
stream_source_->GetReadyState());
- EXPECT_TRUE(pushable_audio_source_->running());
+ EXPECT_TRUE(pushable_audio_source_->IsRunning());
// If the pushable source stops, the MediaStreamSource should stop.
pushable_audio_source_->StopSource();
EXPECT_EQ(MediaStreamSource::kReadyStateEnded,
stream_source_->GetReadyState());
- EXPECT_FALSE(pushable_audio_source_->running());
+ EXPECT_FALSE(pushable_audio_source_->IsRunning());
}
TEST_F(PushableMediaStreamAudioSourceTest, FramesPropagateToSink) {
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
index 67d5bf19ec7..5fd07df24e2 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
@@ -5,9 +5,7 @@
#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -15,7 +13,7 @@ namespace blink {
PushableMediaStreamVideoSource::Broker::Broker(
PushableMediaStreamVideoSource* source)
: source_(source),
- main_task_runner_(Thread::MainThread()->GetTaskRunner()),
+ main_task_runner_(source->GetTaskRunner()),
io_task_runner_(source->io_task_runner()) {
DCHECK(main_task_runner_);
DCHECK(io_task_runner_);
@@ -105,12 +103,10 @@ void PushableMediaStreamVideoSource::Broker::StopSourceOnMain() {
source_->StopSource();
}
-PushableMediaStreamVideoSource::PushableMediaStreamVideoSource()
- : broker_(AdoptRef(new Broker(this))) {}
-
PushableMediaStreamVideoSource::PushableMediaStreamVideoSource(
- const base::WeakPtr<MediaStreamVideoSource>& upstream_source)
- : upstream_source_(upstream_source), broker_(AdoptRef(new Broker(this))) {}
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+ : MediaStreamVideoSource(std::move(main_task_runner)),
+ broker_(AdoptRef(new Broker(this))) {}
PushableMediaStreamVideoSource::~PushableMediaStreamVideoSource() {
broker_->OnSourceDestroyedOrStopped();
@@ -122,51 +118,17 @@ void PushableMediaStreamVideoSource::PushFrame(
broker_->PushFrame(std::move(video_frame), estimated_capture_time);
}
-void PushableMediaStreamVideoSource::RequestRefreshFrame() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (upstream_source_)
- upstream_source_->RequestRefreshFrame();
- if (signal_observer_)
- signal_observer_->RequestFrame();
-}
-
-void PushableMediaStreamVideoSource::OnFrameDropped(
- media::VideoCaptureFrameDropReason reason) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (upstream_source_)
- upstream_source_->OnFrameDropped(reason);
-}
-
-VideoCaptureFeedbackCB PushableMediaStreamVideoSource::GetFeedbackCallback()
- const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (upstream_source_) {
- return WTF::BindRepeating(
- [](const base::WeakPtr<MediaStreamVideoSource>& source,
- const media::VideoCaptureFeedback& feedback) {
- if (!source)
- return;
-
- PushableMediaStreamVideoSource* pushable_source =
- static_cast<PushableMediaStreamVideoSource*>(source.get());
- pushable_source->GetInternalFeedbackCallback().Run(feedback);
- },
- GetWeakPtr());
- }
- return VideoCaptureFeedbackCB();
-}
-
void PushableMediaStreamVideoSource::StartSourceImpl(
VideoCaptureDeliverFrameCB frame_callback,
EncodedVideoFrameCB encoded_frame_callback) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DCHECK(frame_callback);
broker_->OnSourceStarted(std::move(frame_callback));
OnStartDone(mojom::blink::MediaStreamRequestResult::OK);
}
void PushableMediaStreamVideoSource::StopSourceImpl() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
broker_->OnSourceDestroyedOrStopped();
}
@@ -175,19 +137,4 @@ PushableMediaStreamVideoSource::GetWeakPtr() const {
return weak_factory_.GetWeakPtr();
}
-VideoCaptureFeedbackCB
-PushableMediaStreamVideoSource::GetInternalFeedbackCallback() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (!upstream_source_)
- return VideoCaptureFeedbackCB();
-
- return upstream_source_->GetFeedbackCallback();
-}
-
-void PushableMediaStreamVideoSource::SetSignalObserver(
- MediaStreamVideoTrackSignalObserver* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- signal_observer_ = observer;
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
index 32f4a93ca78..c2e98357953 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
@@ -8,11 +8,10 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
namespace blink {
-class MediaStreamVideoTrackSignalObserver;
-
// Simplifies the creation of video tracks. Just do this:
// auto source = std::make_unique<PushableMediaStreamVideoSource>();
// auto* track = CreateVideoTrackFromSource(script_state, source);
@@ -67,9 +66,8 @@ class MODULES_EXPORT PushableMediaStreamVideoSource
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
};
- PushableMediaStreamVideoSource();
explicit PushableMediaStreamVideoSource(
- const base::WeakPtr<MediaStreamVideoSource>& upstream_source);
+ scoped_refptr<base::SingleThreadTaskRunner>);
~PushableMediaStreamVideoSource() override;
// See the definition of VideoCaptureDeliverFrameCB in
@@ -85,22 +83,13 @@ class MODULES_EXPORT PushableMediaStreamVideoSource
scoped_refptr<Broker> GetBroker() const { return broker_; }
// MediaStreamVideoSource
- void RequestRefreshFrame() override;
- void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
- VideoCaptureFeedbackCB GetFeedbackCallback() const override;
void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
EncodedVideoFrameCB encoded_frame_callback) override;
void StopSourceImpl() override;
base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() const override;
- VideoCaptureFeedbackCB GetInternalFeedbackCallback() const;
- void SetSignalObserver(MediaStreamVideoTrackSignalObserver*);
-
private:
- base::WeakPtr<MediaStreamVideoSource> upstream_source_;
- WeakPersistent<MediaStreamVideoTrackSignalObserver> signal_observer_;
scoped_refptr<Broker> broker_;
- THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<MediaStreamVideoSource> weak_factory_{this};
};
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source_test.cc
index 4c09f80f012..e008e97358b 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source_test.cc
@@ -8,6 +8,7 @@
#include "media/base/bind_to_current_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
@@ -76,19 +77,13 @@ WebMediaStreamTrack StartVideoSource(MediaStreamVideoSource* video_source) {
/*enabled=*/true);
}
-MediaStreamSource* CreateAndStartMediaStreamSource(
- MediaStreamVideoSource* video_source) {
- MediaStreamSource* source = CreateConnectedMediaStreamSource(video_source);
- StartVideoSource(video_source);
- return source;
-}
-
} // namespace
class PushableMediaStreamVideoSourceTest : public testing::Test {
public:
PushableMediaStreamVideoSourceTest() {
- pushable_video_source_ = new PushableMediaStreamVideoSource();
+ pushable_video_source_ = new PushableMediaStreamVideoSource(
+ scheduler::GetSingleThreadTaskRunnerForTesting());
stream_source_ = CreateConnectedMediaStreamSource(pushable_video_source_);
}
@@ -150,25 +145,4 @@ TEST_F(PushableMediaStreamVideoSourceTest, FramesPropagateToSink) {
EXPECT_EQ(natural_size.height(), 50);
}
-TEST_F(PushableMediaStreamVideoSourceTest, ForwardToUpstream) {
- MockMediaStreamVideoSource* mock_source = new MockMediaStreamVideoSource();
- PushableMediaStreamVideoSource* pushable_video_source =
- new PushableMediaStreamVideoSource(mock_source->GetWeakPtr());
- CreateAndStartMediaStreamSource(mock_source);
- CreateAndStartMediaStreamSource(pushable_video_source);
-
- EXPECT_CALL(*mock_source, OnRequestRefreshFrame());
- pushable_video_source->RequestRefreshFrame();
-
- EXPECT_CALL(*mock_source,
- OnFrameDropped(media::VideoCaptureFrameDropReason::
- kResolutionAdapterFrameIsNotValid));
- pushable_video_source->OnFrameDropped(
- media::VideoCaptureFrameDropReason::kResolutionAdapterFrameIsNotValid);
-
- EXPECT_CALL(*mock_source, OnFrameFeedback(media::VideoCaptureFeedback()));
- pushable_video_source->GetFeedbackCallback().Run(
- media::VideoCaptureFeedback());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.cc b/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.cc
deleted file mode 100644
index c645f040d1e..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h"
-
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
-#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal_type.h"
-#include "third_party/blink/renderer/modules/breakout_box/metrics.h"
-#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
-
-namespace blink {
-
-VideoTrackSignalUnderlyingSink::VideoTrackSignalUnderlyingSink(
- MediaStreamTrack* track) {
- if (!MediaStreamVideoTrack::From(track->Component()))
- return;
- track_ = track;
- MediaStreamVideoSource* video_source =
- MediaStreamVideoSource::GetVideoSource(track->Component()->Source());
- if (video_source)
- source_ = video_source->GetWeakPtr();
-
- RecordBreakoutBoxUsage(BreakoutBoxUsage::kWritableControlVideo);
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSink::start(
- ScriptState* script_state,
- WritableStreamDefaultController* controller,
- ExceptionState& exception_state) {
- return ScriptPromise::CastUndefined(script_state);
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSink::write(
- ScriptState* script_state,
- ScriptValue chunk,
- WritableStreamDefaultController* controller,
- ExceptionState& exception_state) {
- MediaStreamTrackSignal* signal =
- NativeValueTraits<MediaStreamTrackSignal>::NativeValue(
- script_state->GetIsolate(), chunk.V8Value(), exception_state);
- if (!signal) {
- exception_state.ThrowTypeError("Null signal.");
- return ScriptPromise();
- }
-
- if (!track_ || track_->Ended()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "No live track");
- return ScriptPromise();
- }
-
- if (signal->signalType() == "request-frame") {
- if (!source_ || !source_->IsRunning()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "No active source");
- return ScriptPromise();
- }
- source_->RequestRefreshFrame();
- return ScriptPromise::CastUndefined(script_state);
- } else if (signal->signalType() == "set-min-frame-rate") {
- if (!signal->hasFrameRate()) {
- exception_state.ThrowTypeError(
- "A non-negative frameRate is required for set-min-frame-rate.");
- return ScriptPromise();
- }
- if (auto* video_track = MediaStreamVideoTrack::From(track_->Component())) {
- video_track->SetMinimumFrameRate(signal->frameRate());
- return ScriptPromise::CastUndefined(script_state);
- } else {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "No active track");
- return ScriptPromise();
- }
- }
-
- exception_state.ThrowTypeError("Invalid signal.");
- return ScriptPromise();
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSink::abort(
- ScriptState* script_state,
- ScriptValue reason,
- ExceptionState& exception_state) {
- track_.Clear();
- source_.reset();
- return ScriptPromise::CastUndefined(script_state);
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSink::close(
- ScriptState* script_state,
- ExceptionState& exception_state) {
- track_.Clear();
- source_.reset();
- return ScriptPromise::CastUndefined(script_state);
-}
-
-void VideoTrackSignalUnderlyingSink::Trace(Visitor* visitor) const {
- visitor->Trace(track_);
- UnderlyingSinkBase::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h b/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h
deleted file mode 100644
index 0dcc6baf3b7..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_VIDEO_TRACK_SIGNAL_UNDERLYING_SINK_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_VIDEO_TRACK_SIGNAL_UNDERLYING_SINK_H_
-
-#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class MediaStreamTrack;
-class MediaStreamVideoSource;
-
-class MODULES_EXPORT VideoTrackSignalUnderlyingSink
- : public UnderlyingSinkBase {
- public:
- // |source| must outlive this MediaStreamVideoTrackUnderlyingSink.
- explicit VideoTrackSignalUnderlyingSink(MediaStreamTrack* track);
-
- // UnderlyingSinkBase overrides.
- ScriptPromise start(ScriptState* script_state,
- WritableStreamDefaultController* controller,
- ExceptionState& exception_state) override;
- ScriptPromise write(ScriptState* script_state,
- ScriptValue chunk,
- WritableStreamDefaultController* controller,
- ExceptionState& exception_state) override;
- ScriptPromise abort(ScriptState* script_state,
- ScriptValue reason,
- ExceptionState& exception_state) override;
- ScriptPromise close(ScriptState* script_state,
- ExceptionState& exception_state) override;
- void Trace(Visitor* visitor) const override;
-
- private:
- WeakMember<MediaStreamTrack> track_;
- base::WeakPtr<MediaStreamVideoSource> source_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_VIDEO_TRACK_SIGNAL_UNDERLYING_SINK_H_
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink_test.cc
deleted file mode 100644
index d43376fec7a..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink_test.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_sink.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/web/web_heap.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.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/modules/v8/v8_media_stream_track_signal.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal_type.h"
-#include "third_party/blink/renderer/core/streams/writable_stream.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
-#include "third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h"
-#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
-#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
-#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
-
-using testing::_;
-
-namespace blink {
-
-class VideoTrackSignalUnderlyingSinkTest : public testing::Test {
- public:
- VideoTrackSignalUnderlyingSinkTest() {
- mock_video_source_ = new MockMediaStreamVideoSource();
- media_stream_source_ = MakeGarbageCollected<MediaStreamSource>(
- "dummy_source_id", MediaStreamSource::kTypeVideo, "dummy_source_name",
- /*remote=*/false);
- media_stream_source_->SetPlatformSource(
- base::WrapUnique(mock_video_source_));
- web_track_ = MediaStreamVideoTrack::CreateVideoTrack(
- mock_video_source_, MediaStreamVideoSource::ConstraintsOnceCallback(),
- true);
- mock_video_source_->StartMockedSource();
- }
-
- ~VideoTrackSignalUnderlyingSinkTest() override {
- platform_->RunUntilIdle();
- mock_video_source_->StopSource();
- base::RunLoop run_loop;
- platform_->GetIOTaskRunner()->PostTask(FROM_HERE, run_loop.QuitClosure());
- run_loop.Run();
- WebHeap::CollectAllGarbageForTesting();
- }
-
- MediaStreamTrack* CreateTrack(ExecutionContext* context) const {
- return MakeGarbageCollected<MediaStreamTrack>(context, web_track_);
- }
- VideoTrackSignalUnderlyingSink* CreateUnderlyingSink(
- MediaStreamTrack* track) {
- return MakeGarbageCollected<VideoTrackSignalUnderlyingSink>(track);
- }
-
- ScriptValue CreateSignalChunk(
- ScriptState* script_state,
- const V8MediaStreamTrackSignalType& signal_type) {
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType(signal_type);
- return ScriptValue(script_state->GetIsolate(),
- ToV8(signal, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
- }
-
- ScriptValue CreateRequestFrameChunk(ScriptState* script_state) {
- return CreateSignalChunk(
- script_state, V8MediaStreamTrackSignalType(
- V8MediaStreamTrackSignalType::Enum::kRequestFrame));
- }
-
- ScriptValue CreateSetMinFrameRateChunk(
- ScriptState* script_state,
- const absl::optional<double>& frame_rate = 10.0) {
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType("set-min-frame-rate");
- if (frame_rate)
- signal->setFrameRate(*frame_rate);
- return ScriptValue(script_state->GetIsolate(),
- ToV8(signal, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
- }
-
- protected:
- Persistent<MediaStreamSource> media_stream_source_;
- WebMediaStreamTrack web_track_;
- MockMediaStreamVideoSource* mock_video_source_;
- ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
-};
-
-TEST_F(VideoTrackSignalUnderlyingSinkTest,
- WriteRequestFrameToStreamForwardsToVideoSource) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- auto* track = CreateTrack(v8_scope.GetExecutionContext());
- auto* underlying_sink = CreateUnderlyingSink(track);
- auto* writable_stream = WritableStream::CreateWithCountQueueingStrategy(
- script_state, underlying_sink, 1u);
-
- NonThrowableExceptionState exception_state;
- auto* writer = writable_stream->getWriter(script_state, exception_state);
-
- auto request_frame_chunk = CreateRequestFrameChunk(script_state);
- EXPECT_CALL(*mock_video_source_, OnRequestRefreshFrame());
- ScriptPromiseTester write_tester(
- script_state,
- writer->write(script_state, request_frame_chunk, exception_state));
- write_tester.WaitUntilSettled();
-
- const double frame_rate = 14.8;
- auto set_min_frame_rate_chunk =
- CreateSetMinFrameRateChunk(script_state, frame_rate);
- MediaStreamVideoTrack* video_track =
- MediaStreamVideoTrack::From(track->Component());
- EXPECT_FALSE(video_track->min_frame_rate().has_value());
- ScriptPromiseTester write_tester2(
- script_state,
- writer->write(script_state, set_min_frame_rate_chunk, exception_state));
- write_tester2.WaitUntilSettled();
- EXPECT_TRUE(video_track->min_frame_rate().has_value());
- EXPECT_EQ(video_track->min_frame_rate().value(), frame_rate);
-
- writer->releaseLock(script_state);
- ScriptPromiseTester close_tester(
- script_state, writable_stream->close(script_state, exception_state));
- close_tester.WaitUntilSettled();
-
- MediaStreamTrack* clone = track->clone(script_state);
- track->stopTrack(v8_scope.GetExecutionContext());
-
- // Writing to the sink after the track closes should fail, even if the source
- // is active.
- EXPECT_TRUE(mock_video_source_->IsRunning());
- DummyExceptionStateForTesting dummy_exception_state;
- underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
- nullptr, dummy_exception_state);
- EXPECT_TRUE(dummy_exception_state.HadException());
- EXPECT_EQ(dummy_exception_state.Code(),
- static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
-
- clone->stopTrack(v8_scope.GetExecutionContext());
- EXPECT_FALSE(mock_video_source_->IsRunning());
- // Writing to the sink after the source closes should fail.
- dummy_exception_state.ClearException();
- underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
- nullptr, dummy_exception_state);
- EXPECT_TRUE(dummy_exception_state.HadException());
- EXPECT_EQ(dummy_exception_state.Code(),
- static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
-}
-
-TEST_F(VideoTrackSignalUnderlyingSinkTest, WriteInvalidDataFails) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- auto* track = CreateTrack(v8_scope.GetExecutionContext());
- auto* underlying_sink = CreateUnderlyingSink(track);
-
- MediaStreamVideoTrack* video_track =
- MediaStreamVideoTrack::From(track->Component());
- EXPECT_FALSE(video_track->min_frame_rate().has_value());
-
- DummyExceptionStateForTesting exception_state;
- auto set_min_frame_rate_chunk =
- CreateSetMinFrameRateChunk(script_state, absl::nullopt);
- underlying_sink->write(script_state, set_min_frame_rate_chunk, nullptr,
- exception_state);
- EXPECT_TRUE(exception_state.HadException());
- EXPECT_FALSE(video_track->min_frame_rate().has_value());
-
- exception_state.ClearException();
- EXPECT_FALSE(exception_state.HadException());
-
- // Writing null fails
- exception_state.ClearException();
- EXPECT_FALSE(exception_state.HadException());
- underlying_sink->write(script_state,
- ScriptValue::CreateNull(v8_scope.GetIsolate()),
- nullptr, exception_state);
- EXPECT_TRUE(exception_state.HadException());
-
- // Writing an intenger fails
- exception_state.ClearException();
- EXPECT_FALSE(exception_state.HadException());
- underlying_sink->write(script_state, ScriptValue::From(script_state, 5),
- nullptr, exception_state);
- EXPECT_TRUE(exception_state.HadException());
-
- track->stopTrack(v8_scope.GetExecutionContext());
-}
-
-TEST_F(VideoTrackSignalUnderlyingSinkTest, WriteToClosedSinkFails) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- auto* track = CreateTrack(v8_scope.GetExecutionContext());
- auto* underlying_sink = CreateUnderlyingSink(track);
-
- auto* writable_stream = WritableStream::CreateWithCountQueueingStrategy(
- script_state, underlying_sink, 1u);
-
- NonThrowableExceptionState exception_state;
- ScriptPromiseTester abort_tester(
- script_state, writable_stream->close(script_state, exception_state));
- abort_tester.WaitUntilSettled();
-
- // Writing to the sink after the stream closes should fail.
- DummyExceptionStateForTesting dummy_exception_state;
- underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
- nullptr, dummy_exception_state);
- EXPECT_TRUE(dummy_exception_state.HadException());
- EXPECT_EQ(dummy_exception_state.Code(),
- static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
-
- track->stopTrack(v8_scope.GetExecutionContext());
-}
-
-TEST_F(VideoTrackSignalUnderlyingSinkTest, WriteToAbortedSinkFails) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- auto* track = CreateTrack(v8_scope.GetExecutionContext());
- auto* underlying_sink = CreateUnderlyingSink(track);
-
- auto* writable_stream = WritableStream::CreateWithCountQueueingStrategy(
- script_state, underlying_sink, 1u);
-
- NonThrowableExceptionState exception_state;
- ScriptPromiseTester abort_tester(
- script_state, writable_stream->abort(script_state, exception_state));
- abort_tester.WaitUntilSettled();
-
- // Writing to the sink after the stream aborts should fail.
- DummyExceptionStateForTesting dummy_exception_state;
- underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
- nullptr, dummy_exception_state);
- EXPECT_TRUE(dummy_exception_state.HadException());
- EXPECT_EQ(dummy_exception_state.Code(),
- static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
-
- track->stopTrack(v8_scope.GetExecutionContext());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.cc b/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.cc
deleted file mode 100644
index eb7ed2693c5..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.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/streams/readable_stream_default_controller_with_script_scope.h"
-#include "third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h"
-#include "third_party/blink/renderer/modules/breakout_box/metrics.h"
-#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
-#include "third_party/blink/renderer/modules/webcodecs/video_frame.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/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/webrtc/api/frame_transformer_interface.h"
-
-namespace blink {
-
-VideoTrackSignalUnderlyingSource::VideoTrackSignalUnderlyingSource(
- ScriptState* script_state,
- MediaStreamTrackGenerator* generator,
- wtf_size_t max_queue_size)
- : UnderlyingSourceBase(script_state),
- main_task_runner_(ExecutionContext::From(script_state)
- ->GetTaskRunner(TaskType::kInternalMediaRealTime)),
- generator_(generator),
- max_queue_size_(std::max(1u, max_queue_size)) {
- DCHECK(generator_);
- RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableControlVideo);
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSource::pull(
- ScriptState* script_state) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- if (!queue_.empty()) {
- PullFromQueue();
- } else {
- is_pending_pull_ = true;
- }
-
- DCHECK_LT(queue_.size(), max_queue_size_);
- return ScriptPromise::CastUndefined(script_state);
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSource::Start(
- ScriptState* script_state) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- auto* video_track = MediaStreamVideoTrack::From(generator_->Component());
- if (!video_track) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(
- "No input track",
- DOMException::GetErrorName(DOMExceptionCode::kInvalidStateError)));
- }
- video_track->SetSignalObserver(this);
-
- auto* video_source = generator_->PushableVideoSource();
- video_source->SetSignalObserver(this);
- return ScriptPromise::CastUndefined(script_state);
-}
-
-ScriptPromise VideoTrackSignalUnderlyingSource::Cancel(
- ScriptState* script_state,
- ScriptValue reason) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- Stop();
- return ScriptPromise::CastUndefined(script_state);
-}
-
-void VideoTrackSignalUnderlyingSource::Trace(Visitor* visitor) const {
- visitor->Trace(generator_);
- visitor->Trace(queue_);
- UnderlyingSourceBase::Trace(visitor);
-}
-
-double VideoTrackSignalUnderlyingSource::DesiredSizeForTesting() const {
- return Controller()->DesiredSize();
-}
-
-void VideoTrackSignalUnderlyingSource::ContextDestroyed() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- UnderlyingSourceBase::ContextDestroyed();
- Stop();
-}
-
-void VideoTrackSignalUnderlyingSource::Close() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- Stop();
- if (Controller())
- Controller()->Close();
-}
-
-void VideoTrackSignalUnderlyingSource::SetMinimumFrameRate(double frame_rate) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType("set-min-frame-rate");
- signal->setFrameRate(frame_rate);
- ProcessNewSignal(signal);
-}
-
-void VideoTrackSignalUnderlyingSource::RequestFrame() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
- signal->setSignalType("request-frame");
- ProcessNewSignal(signal);
-}
-
-void VideoTrackSignalUnderlyingSource::ProcessNewSignal(
- MediaStreamTrackSignal* signal) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DCHECK_LE(queue_.size(), max_queue_size_);
- if (!is_active_)
- return;
-
- // If the |queue_| is empty and the consumer has signaled a pull, bypass
- // |queue_| and send the frame directly to the stream controller.
- if (queue_.empty() && is_pending_pull_) {
- SendSignalToStream(signal);
- return;
- }
-
- if (queue_.size() == max_queue_size_)
- queue_.pop_front();
-
- queue_.push_back(signal);
- if (is_pending_pull_) {
- PullFromQueue();
- }
-}
-
-void VideoTrackSignalUnderlyingSource::PullFromQueue() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DCHECK(!queue_.empty());
- DCHECK(is_active_);
- SendSignalToStream(std::move(queue_.front()));
- queue_.pop_front();
-}
-
-void VideoTrackSignalUnderlyingSource::SendSignalToStream(
- MediaStreamTrackSignal* signal) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DCHECK(signal);
- DCHECK(is_active_);
- if (!Controller())
- return;
-
- Controller()->Enqueue(signal);
- is_pending_pull_ = false;
-}
-
-void VideoTrackSignalUnderlyingSource::Stop() {
- is_active_ = false;
- queue_.clear();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h b/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h
deleted file mode 100644
index 56423bd0dc6..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_VIDEO_TRACK_SIGNAL_UNDERLYING_SOURCE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_VIDEO_TRACK_SIGNAL_UNDERLYING_SOURCE_H_
-
-#include "base/threading/thread_checker.h"
-#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/deque.h"
-
-namespace blink {
-
-class MediaStreamTrackSignal;
-class MediaStreamTrackGenerator;
-
-// This class serves as the source for the control signals sent to
-// a MediaStreamTrackGenerator and exposed on its readableControl field.
-// This class maintains an internal circular queue to store unconsumed
-// signals. If the queue becomes full and new signals are produced,
-// older signals are dropped to accommodate the new signals.
-class MODULES_EXPORT VideoTrackSignalUnderlyingSource
- : public UnderlyingSourceBase,
- public MediaStreamVideoTrackSignalObserver {
- public:
- explicit VideoTrackSignalUnderlyingSource(ScriptState*,
- MediaStreamTrackGenerator*,
- wtf_size_t queue_size);
- VideoTrackSignalUnderlyingSource(const VideoTrackSignalUnderlyingSource&) =
- delete;
- VideoTrackSignalUnderlyingSource& operator=(
- const VideoTrackSignalUnderlyingSource&) = delete;
-
- // UnderlyingSourceBase
- ScriptPromise pull(ScriptState*) override;
- ScriptPromise Start(ScriptState*) override;
- ScriptPromise Cancel(ScriptState*, ScriptValue reason) override;
-
- // ExecutionLifecycleObserver
- void ContextDestroyed() override;
-
- MediaStreamTrackGenerator* Generator() const { return generator_.Get(); }
- wtf_size_t MaxQueueSize() const { return max_queue_size_; }
-
- bool IsPendingPullForTesting() const { return is_pending_pull_; }
- const HeapDeque<Member<MediaStreamTrackSignal>>& QueueForTesting() const {
- return queue_;
- }
- double DesiredSizeForTesting() const;
-
- void Close();
- void Trace(Visitor*) const override;
-
- private:
- // MediaStreamVideoTrackSignalObserver
- void SetMinimumFrameRate(double) override;
- void RequestFrame() override;
-
- void ProcessNewSignal(MediaStreamTrackSignal*);
- void SendSignalToStream(MediaStreamTrackSignal*);
- void PullFromQueue();
- void Stop();
-
- const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
- Member<MediaStreamTrackGenerator> generator_;
-
- // An internal deque prior to the stream controller's queue. It acts as a ring
- // buffer and allows dropping old signals instead of new ones in case signals
- // accumulate due to slow consumption.
- HeapDeque<Member<MediaStreamTrackSignal>> queue_;
- const wtf_size_t max_queue_size_;
- bool is_pending_pull_ = false;
- bool is_active_ = true;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_VIDEO_TRACK_SIGNAL_UNDERLYING_SOURCE_H_
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source_test.cc b/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source_test.cc
deleted file mode 100644
index 40158fb618f..00000000000
--- a/chromium/third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source_test.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/breakout_box/video_track_signal_underlying_source.h"
-
-#include "base/run_loop.h"
-#include "base/test/gmock_callback_support.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h"
-#include "third_party/blink/public/web/web_heap.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
-#include "third_party/blink/renderer/modules/breakout_box/media_stream_track_generator.h"
-#include "third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h"
-#include "third_party/blink/renderer/modules/breakout_box/stream_test_utils.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
-#include "third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
-
-using testing::_;
-
-namespace blink {
-
-class VideoTrackSignalUnderlyingSourceTest : public testing::Test {
- public:
- ~VideoTrackSignalUnderlyingSourceTest() override {
- platform_->RunUntilIdle();
- WebHeap::CollectAllGarbageForTesting();
- }
-
- MediaStreamTrackGenerator* CreateGenerator(ScriptState* script_state) {
- return MakeGarbageCollected<MediaStreamTrackGenerator>(
- script_state, MediaStreamSource::kTypeVideo, "test-generator",
- /*signal_target=*/nullptr, /*max_signal_buffer_size=*/10u);
- }
-
- VideoTrackSignalUnderlyingSource* CreateSource(
- ScriptState* script_state,
- MediaStreamTrackGenerator* generator,
- wtf_size_t max_buffer_size) {
- return MakeGarbageCollected<VideoTrackSignalUnderlyingSource>(
- script_state, generator, max_buffer_size);
- }
-
- VideoTrackSignalUnderlyingSource* CreateSource(
- ScriptState* script_state,
- MediaStreamTrackGenerator* generator) {
- return CreateSource(script_state, generator, 1u);
- }
-
- protected:
- ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
-};
-
-TEST_F(VideoTrackSignalUnderlyingSourceTest, SignalsAreExposed) {
- V8TestingScope v8_scope;
- auto* script_state = v8_scope.GetScriptState();
- auto* generator = CreateGenerator(script_state);
- auto* video_track = MediaStreamVideoTrack::From(generator->Component());
- auto* video_source = generator->PushableVideoSource();
- auto* source = CreateSource(script_state, generator);
- auto* stream =
- ReadableStream::CreateWithCountQueueingStrategy(script_state, source, 0);
- auto* reader =
- stream->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
-
- video_source->RequestRefreshFrame();
- auto* signal = ReadObjectFromStream<MediaStreamTrackSignal>(v8_scope, reader);
- EXPECT_EQ(signal->signalType(), "request-frame");
-
- const double min_frame_rate = 3.5;
- video_track->SetMinimumFrameRate(min_frame_rate);
- signal = ReadObjectFromStream<MediaStreamTrackSignal>(v8_scope, reader);
- EXPECT_EQ(signal->signalType(), "set-min-frame-rate");
- EXPECT_TRUE(signal->hasFrameRate());
- EXPECT_EQ(signal->frameRate(), min_frame_rate);
-
- source->Close();
-}
-
-TEST_F(VideoTrackSignalUnderlyingSourceTest, CancelStreamDisconnectsFromTrack) {
- V8TestingScope v8_scope;
- auto* script_state = v8_scope.GetScriptState();
- auto* generator = CreateGenerator(script_state);
- auto* source = CreateSource(script_state, generator);
- ReadableStream::CreateWithCountQueueingStrategy(script_state, source, 0);
- auto& queue = source->QueueForTesting();
-
- generator->PushableVideoSource()->RequestRefreshFrame();
- EXPECT_EQ(queue.size(), 1u);
-
- source->Cancel(script_state, ScriptValue());
- EXPECT_EQ(queue.size(), 0u);
-
- generator->PushableVideoSource()->RequestRefreshFrame();
- EXPECT_EQ(queue.size(), 0u);
-
- source->Close();
-}
-
-TEST_F(VideoTrackSignalUnderlyingSourceTest, DropOldSignalsWhenQueueIsFull) {
- V8TestingScope v8_scope;
- auto* script_state = v8_scope.GetScriptState();
- auto* generator = CreateGenerator(script_state);
- auto* video_track = MediaStreamVideoTrack::From(generator->Component());
- const wtf_size_t buffer_size = 3;
- auto* source = CreateSource(script_state, generator, buffer_size);
- EXPECT_EQ(source->MaxQueueSize(), buffer_size);
- ReadableStream::CreateWithCountQueueingStrategy(script_state, source, 0);
-
- const auto& queue = source->QueueForTesting();
- for (wtf_size_t i = 0; i < buffer_size; ++i) {
- EXPECT_EQ(queue.size(), i);
- video_track->SetMinimumFrameRate(i);
- EXPECT_EQ(queue.back()->frameRate(), i);
- EXPECT_EQ(queue.front()->frameRate(), 0.0);
- }
-
- // Push another signal while the queue is full.
- EXPECT_EQ(queue.size(), buffer_size);
- video_track->SetMinimumFrameRate(buffer_size);
-
- // Since the queue was full, the oldest signal from the queue should have been
- // dropped.
- EXPECT_EQ(queue.size(), buffer_size);
- EXPECT_EQ(queue.back()->frameRate(), buffer_size);
- EXPECT_EQ(queue.front()->frameRate(), 1.0);
-
- // Pulling with signals in the queue should move the oldest signal in the
- // queue to the stream's controller.
- EXPECT_EQ(source->DesiredSizeForTesting(), 0);
- EXPECT_FALSE(source->IsPendingPullForTesting());
- source->pull(script_state);
- EXPECT_EQ(source->DesiredSizeForTesting(), -1);
- EXPECT_FALSE(source->IsPendingPullForTesting());
- EXPECT_EQ(queue.size(), buffer_size - 1);
- EXPECT_EQ(queue.front()->frameRate(), 2);
-
- source->Close();
- EXPECT_EQ(queue.size(), 0u);
-}
-
-TEST_F(VideoTrackSignalUnderlyingSourceTest,
- BypassQueueAfterPullWithEmptyBuffer) {
- V8TestingScope v8_scope;
- auto* script_state = v8_scope.GetScriptState();
- auto* generator = CreateGenerator(script_state);
- auto* source = CreateSource(script_state, generator);
- ReadableStream::CreateWithCountQueueingStrategy(script_state, source, 0);
-
- // At first, the queue is empty and the desired size is empty as well.
- EXPECT_TRUE(source->QueueForTesting().empty());
- EXPECT_EQ(source->DesiredSizeForTesting(), 0);
- EXPECT_FALSE(source->IsPendingPullForTesting());
-
- source->pull(script_state);
- EXPECT_TRUE(source->QueueForTesting().empty());
- EXPECT_EQ(source->DesiredSizeForTesting(), 0);
- EXPECT_TRUE(source->IsPendingPullForTesting());
-
- generator->PushableVideoSource()->RequestRefreshFrame();
- // Since a pull was pending, the signal is put directly in the stream
- // controller, bypassing the source queue.
- EXPECT_TRUE(source->QueueForTesting().empty());
- EXPECT_EQ(source->DesiredSizeForTesting(), -1);
- EXPECT_FALSE(source->IsPendingPullForTesting());
-
- source->Close();
-}
-
-TEST_F(VideoTrackSignalUnderlyingSourceTest, QueueSizeCannotBeZero) {
- V8TestingScope v8_scope;
- auto* script_state = v8_scope.GetScriptState();
- auto* generator = CreateGenerator(script_state);
- auto* source = CreateSource(script_state, generator, /*max_buffer_size=*/0u);
-
- // Queue size is always at least 1, even if 0 is requested.
- EXPECT_EQ(source->MaxQueueSize(), 1u);
- source->Close();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/broadcastchannel/idls.gni b/chromium/third_party/blink/renderer/modules/broadcastchannel/idls.gni
deleted file mode 100644
index 687c09309a7..00000000000
--- a/chromium/third_party/blink/renderer/modules/broadcastchannel/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "broadcast_channel.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/buckets/idls.gni b/chromium/third_party/blink/renderer/modules/buckets/idls.gni
deleted file mode 100644
index c3d1f981411..00000000000
--- a/chromium/third_party/blink/renderer/modules/buckets/idls.gni
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "storage_bucket_manager.idl",
- "storage_bucket.idl",
-]
-
-modules_dictionary_idl_files = [ "storage_bucket_options.idl" ]
-
-modules_dependency_idl_files = [
- "navigator_storage_buckets.idl",
- "worker_navigator_storage_buckets.idl",
-]
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 2d275e2a3a4..c76c7677a17 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -183,15 +183,13 @@ class Cache::BarrierCallbackForPutResponse final
Cache* cache,
const String& method_name,
const HeapVector<Member<Request>>& request_list,
- const ExceptionState& exception_state,
+ const ExceptionContext& exception_context,
int64_t trace_id)
: resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)),
cache_(cache),
method_name_(method_name),
request_list_(request_list),
- context_type_(exception_state.Context()),
- property_name_(exception_state.PropertyName()),
- interface_name_(exception_state.InterfaceName()),
+ exception_context_(exception_context),
trace_id_(trace_id),
response_list_(request_list_.size()),
blob_list_(request_list_.size()) {
@@ -224,8 +222,8 @@ class Cache::BarrierCallbackForPutResponse final
if (num_complete_ == request_list_.size()) {
ScriptState* script_state = resolver_->GetScriptState();
- ExceptionState exception_state(script_state->GetIsolate(), context_type_,
- property_name_, interface_name_);
+ ExceptionState exception_state(script_state->GetIsolate(),
+ exception_context_);
cache_->PutImpl(resolver_, method_name_, request_list_, response_list_,
blob_list_, exception_state, trace_id_);
blob_list_.clear();
@@ -288,9 +286,7 @@ class Cache::BarrierCallbackForPutResponse final
Member<Cache> cache_;
const String method_name_;
const HeapVector<Member<Request>> request_list_;
- ExceptionState::ContextType context_type_;
- const char* property_name_;
- const char* interface_name_;
+ const ExceptionContext exception_context_;
const int64_t trace_id_;
HeapVector<Member<Response>> response_list_;
WTF::Vector<scoped_refptr<BlobDataHandle>> blob_list_;
@@ -557,32 +553,30 @@ class Cache::FetchHandler final : public ScriptFunction {
ScriptState* script_state,
ResponseBodyLoader* response_loader,
BarrierCallbackForPutResponse* barrier_callback,
- const ExceptionState& exception_state) {
+ const ExceptionContext& exception_context) {
FetchHandler* self = MakeGarbageCollected<FetchHandler>(
- script_state, response_loader, barrier_callback, exception_state);
+ script_state, response_loader, barrier_callback, exception_context);
return self->BindToV8Function();
}
static v8::Local<v8::Function> CreateForReject(
ScriptState* script_state,
BarrierCallbackForPutResponse* barrier_callback,
- const ExceptionState& exception_state) {
+ const ExceptionContext& exception_context) {
FetchHandler* self = MakeGarbageCollected<FetchHandler>(
script_state, /*response_loader=*/nullptr, barrier_callback,
- exception_state);
+ exception_context);
return self->BindToV8Function();
}
FetchHandler(ScriptState* script_state,
ResponseBodyLoader* response_loader,
BarrierCallbackForPutResponse* barrier_callback,
- const ExceptionState& exception_state)
+ const ExceptionContext& exception_context)
: ScriptFunction(script_state),
response_loader_(response_loader),
barrier_callback_(barrier_callback),
- context_type_(exception_state.Context()),
- property_name_(exception_state.PropertyName()),
- interface_name_(exception_state.InterfaceName()) {}
+ exception_context_(exception_context) {}
ScriptValue Call(ScriptValue value) override {
// We always resolve undefined from this promise handler since the
@@ -599,8 +593,7 @@ class Cache::FetchHandler final : public ScriptFunction {
}
ExceptionState exception_state(GetScriptState()->GetIsolate(),
- context_type_, property_name_,
- interface_name_);
+ exception_context_);
// Resolve handler, so try to process a Response.
Response* response = NativeValueTraits<Response>::NativeValue(
@@ -622,9 +615,7 @@ class Cache::FetchHandler final : public ScriptFunction {
private:
Member<ResponseBodyLoader> response_loader_;
Member<BarrierCallbackForPutResponse> barrier_callback_;
- ExceptionState::ContextType context_type_;
- const char* property_name_;
- const char* interface_name_;
+ const ExceptionContext exception_context_;
};
class Cache::CodeCacheHandleCallbackForPut final
@@ -743,7 +734,6 @@ class Cache::CodeCacheHandleCallbackForPut final
mojom::blink::FetchAPIResponsePtr fetch_api_response_;
};
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::match(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
@@ -763,64 +753,32 @@ ScriptPromise Cache::match(ScriptState* script_state,
}
return MatchImpl(script_state, request_object, options);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::match(ScriptState* script_state,
- const RequestInfo& request,
- const CacheQueryOptions* options,
- ExceptionState& exception_state) {
- DCHECK(!request.IsNull());
- if (request.IsRequest())
- return MatchImpl(script_state, request.GetAsRequest(), options);
- Request* new_request =
- Request::Create(script_state, request.GetAsUSVString(), exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- return MatchImpl(script_state, new_request, options);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::matchAll(ScriptState* script_state,
- ExceptionState& exception_state) {
+ScriptPromise Cache::matchAll(ScriptState* script_state, ExceptionState&) {
return MatchAllImpl(script_state, nullptr, CacheQueryOptions::Create());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::matchAll(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state) {
- DCHECK(request);
Request* request_object = nullptr;
- switch (request->GetContentType()) {
- case V8RequestInfo::ContentType::kRequest:
- request_object = request->GetAsRequest();
- break;
- case V8RequestInfo::ContentType::kUSVString:
- request_object = Request::Create(script_state, request->GetAsUSVString(),
- exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- break;
+ if (request) {
+ switch (request->GetContentType()) {
+ case V8RequestInfo::ContentType::kRequest:
+ request_object = request->GetAsRequest();
+ break;
+ case V8RequestInfo::ContentType::kUSVString:
+ request_object = Request::Create(
+ script_state, request->GetAsUSVString(), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
+ break;
+ }
}
return MatchAllImpl(script_state, request_object, options);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::matchAll(ScriptState* script_state,
- const RequestInfo& request,
- const CacheQueryOptions* options,
- ExceptionState& exception_state) {
- DCHECK(!request.IsNull());
- if (request.IsRequest())
- return MatchAllImpl(script_state, request.GetAsRequest(), options);
- Request* new_request =
- Request::Create(script_state, request.GetAsUSVString(), exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- return MatchAllImpl(script_state, new_request, options);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::add(ScriptState* script_state,
const V8RequestInfo* request,
ExceptionState& exception_state) {
@@ -839,26 +797,7 @@ ScriptPromise Cache::add(ScriptState* script_state,
}
return AddAllImpl(script_state, "Cache.add()", requests, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::add(ScriptState* script_state,
- const RequestInfo& request,
- ExceptionState& exception_state) {
- DCHECK(!request.IsNull());
- HeapVector<Member<Request>> requests;
- if (request.IsRequest()) {
- requests.push_back(request.GetAsRequest());
- } else {
- requests.push_back(Request::Create(script_state, request.GetAsUSVString(),
- exception_state));
- if (exception_state.HadException())
- return ScriptPromise();
- }
-
- return AddAllImpl(script_state, "Cache.add()", requests, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::addAll(ScriptState* script_state,
const HeapVector<Member<V8RequestInfo>>& requests,
ExceptionState& exception_state) {
@@ -879,27 +818,7 @@ ScriptPromise Cache::addAll(ScriptState* script_state,
return AddAllImpl(script_state, "Cache.addAll()", request_objects,
exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::addAll(ScriptState* script_state,
- const HeapVector<RequestInfo>& raw_requests,
- ExceptionState& exception_state) {
- HeapVector<Member<Request>> requests;
- for (RequestInfo request : raw_requests) {
- if (request.IsRequest()) {
- requests.push_back(request.GetAsRequest());
- } else {
- requests.push_back(Request::Create(script_state, request.GetAsUSVString(),
- exception_state));
- if (exception_state.HadException())
- return ScriptPromise();
- }
- }
-
- return AddAllImpl(script_state, "Cache.addAll()", requests, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::Delete(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
@@ -919,39 +838,15 @@ ScriptPromise Cache::Delete(ScriptState* script_state,
}
return DeleteImpl(script_state, request_object, options);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::Delete(ScriptState* script_state,
- const RequestInfo& request,
- const CacheQueryOptions* options,
- ExceptionState& exception_state) {
- DCHECK(!request.IsNull());
- if (request.IsRequest())
- return DeleteImpl(script_state, request.GetAsRequest(), options);
- Request* new_request =
- Request::Create(script_state, request.GetAsUSVString(), exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- return DeleteImpl(script_state, new_request, options);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::put(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* request_info,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestInfo& request_info,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Response* response,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(request_info);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DCHECK(!request_info.IsNull());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
int64_t trace_id = blink::cache_storage::CreateTraceId();
TRACE_EVENT_WITH_FLOW0("CacheStorage", "Cache::put",
TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_OUT);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Request* request = nullptr;
switch (request_info->GetContentType()) {
case V8RequestInfo::ContentType::kRequest:
@@ -964,15 +859,6 @@ ScriptPromise Cache::put(ScriptState* script_state,
return ScriptPromise();
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Request* request =
- request_info.IsRequest()
- ? request_info.GetAsRequest()
- : Request::Create(script_state, request_info.GetAsUSVString(),
- exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ValidateRequestForPut(request, exception_state);
if (exception_state.HadException())
@@ -980,7 +866,8 @@ ScriptPromise Cache::put(ScriptState* script_state,
auto* barrier_callback = MakeGarbageCollected<BarrierCallbackForPutResponse>(
script_state, this, "Cache.put()",
- HeapVector<Member<Request>>(1, request), exception_state, trace_id);
+ HeapVector<Member<Request>>(1, request), exception_state.GetContext(),
+ trace_id);
// We must get the promise before any rejections can happen during loading.
ScriptPromise promise = barrier_callback->Promise();
@@ -997,41 +884,26 @@ ScriptPromise Cache::keys(ScriptState* script_state, ExceptionState&) {
return KeysImpl(script_state, nullptr, CacheQueryOptions::Create());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise Cache::keys(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state) {
- DCHECK(request);
Request* request_object = nullptr;
- switch (request->GetContentType()) {
- case V8RequestInfo::ContentType::kRequest:
- request_object = request->GetAsRequest();
- break;
- case V8RequestInfo::ContentType::kUSVString:
- request_object = Request::Create(script_state, request->GetAsUSVString(),
- exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- break;
+ if (request) {
+ switch (request->GetContentType()) {
+ case V8RequestInfo::ContentType::kRequest:
+ request_object = request->GetAsRequest();
+ break;
+ case V8RequestInfo::ContentType::kUSVString:
+ request_object = Request::Create(
+ script_state, request->GetAsUSVString(), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
+ break;
+ }
}
return KeysImpl(script_state, request_object, options);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise Cache::keys(ScriptState* script_state,
- const RequestInfo& request,
- const CacheQueryOptions* options,
- ExceptionState& exception_state) {
- DCHECK(!request.IsNull());
- if (request.IsRequest())
- return KeysImpl(script_state, request.GetAsRequest(), options);
- Request* new_request =
- Request::Create(script_state, request.GetAsUSVString(), exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- return KeysImpl(script_state, new_request, options);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Cache::Cache(GlobalFetch::ScopedFetcher* fetcher,
CacheStorageBlobClientList* blob_client_list,
@@ -1232,7 +1104,8 @@ ScriptPromise Cache::AddAllImpl(ScriptState* script_state,
}
auto* barrier_callback = MakeGarbageCollected<BarrierCallbackForPutResponse>(
- script_state, this, method_name, request_list, exception_state, trace_id);
+ script_state, this, method_name, request_list,
+ exception_state.GetContext(), trace_id);
// We must get the promise before any rejections can happen during loading.
ScriptPromise promise = barrier_callback->Promise();
@@ -1244,12 +1117,7 @@ ScriptPromise Cache::AddAllImpl(ScriptState* script_state,
if (barrier_callback->Signal())
request_list[i]->signal()->Follow(barrier_callback->Signal());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RequestInfo* info = MakeGarbageCollected<V8RequestInfo>(request_list[i]);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RequestInfo info;
- info.SetRequest(request_list[i]);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* response_loader = MakeGarbageCollected<ResponseBodyLoader>(
script_state, barrier_callback, i, /*require_ok_response=*/true,
@@ -1257,9 +1125,10 @@ ScriptPromise Cache::AddAllImpl(ScriptState* script_state,
scoped_fetcher_
->Fetch(script_state, info, RequestInit::Create(), exception_state)
.Then(FetchHandler::CreateForResolve(script_state, response_loader,
- barrier_callback, exception_state),
+ barrier_callback,
+ exception_state.GetContext()),
FetchHandler::CreateForReject(script_state, barrier_callback,
- exception_state));
+ exception_state.GetContext()));
}
return promise;
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 7bec6588d2d..e1d8de221b7 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
@@ -47,8 +47,6 @@ class Request;
class ScriptPromiseResolver;
class ScriptState;
-typedef RequestOrUSVString RequestInfo;
-
class MODULES_EXPORT Cache : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -59,30 +57,15 @@ class MODULES_EXPORT Cache : public ScriptWrappable {
scoped_refptr<base::SingleThreadTaskRunner>);
// From Cache.idl:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise match(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise match(ScriptState*,
- const RequestInfo&,
- const CacheQueryOptions*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise matchAll(ScriptState*, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise matchAll(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise matchAll(ScriptState*,
- const RequestInfo&,
- const CacheQueryOptions*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise add(ScriptState* script_state,
const V8RequestInfo* request,
ExceptionState& exception_state);
@@ -97,32 +80,11 @@ class MODULES_EXPORT Cache : public ScriptWrappable {
const V8RequestInfo* request,
Response* response,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise add(ScriptState*, const RequestInfo&, ExceptionState&);
- ScriptPromise addAll(ScriptState*,
- const HeapVector<RequestInfo>&,
- ExceptionState&);
- ScriptPromise Delete(ScriptState*,
- const RequestInfo&,
- const CacheQueryOptions*,
- ExceptionState&);
- ScriptPromise put(ScriptState*,
- const RequestInfo&,
- Response*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise keys(ScriptState*, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise keys(ScriptState* script_state,
const V8RequestInfo* request,
const CacheQueryOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise keys(ScriptState*,
- const RequestInfo&,
- const CacheQueryOptions*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
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 ba19d0c43ca..dbab1eee114 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
@@ -331,7 +331,6 @@ ScriptPromise CacheStorage::keys(ScriptState* script_state) {
return promise;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise CacheStorage::match(ScriptState* script_state,
const V8RequestInfo* request,
const MultiCacheQueryOptions* options,
@@ -351,22 +350,6 @@ ScriptPromise CacheStorage::match(ScriptState* script_state,
}
return MatchImpl(script_state, request_object, options);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-ScriptPromise CacheStorage::match(ScriptState* script_state,
- const RequestInfo& request,
- const MultiCacheQueryOptions* options,
- ExceptionState& exception_state) {
- DCHECK(!request.IsNull());
-
- if (request.IsRequest())
- return MatchImpl(script_state, request.GetAsRequest(), options);
- Request* new_request =
- Request::Create(script_state, request.GetAsUSVString(), exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- return MatchImpl(script_state, new_request, options);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise CacheStorage::MatchImpl(ScriptState* script_state,
const Request* request,
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.h b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.h
index 7a87771faa4..5a4e7632ad8 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.h
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.h
@@ -38,17 +38,10 @@ class CacheStorage final : public ScriptWrappable,
ScriptPromise has(ScriptState*, const String& cache_name);
ScriptPromise Delete(ScriptState*, const String& cache_name);
ScriptPromise keys(ScriptState*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise match(ScriptState* script_state,
const V8RequestInfo* request,
const MultiCacheQueryOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise match(ScriptState*,
- const RequestInfo&,
- const MultiCacheQueryOptions*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool HasPendingActivity() const override;
void Trace(Visitor*) const override;
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 f2282be9225..01f88a19484 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
@@ -61,16 +61,11 @@ class ScopedFetcherForTests final
ScopedFetcherForTests() = default;
ScriptPromise Fetch(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8RequestInfo* request_info,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const RequestInfo& request_info,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const RequestInit*,
ExceptionState& exception_state) override {
++fetch_count_;
if (expected_url_) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (request_info->GetContentType()) {
case V8RequestInfo::ContentType::kRequest:
EXPECT_EQ(*expected_url_, request_info->GetAsRequest()->url());
@@ -79,12 +74,6 @@ class ScopedFetcherForTests final
EXPECT_EQ(*expected_url_, request_info->GetAsUSVString());
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (request_info.IsRequest())
- EXPECT_EQ(*expected_url_, request_info.GetAsRequest()->url());
- else
- EXPECT_EQ(*expected_url_, request_info.GetAsUSVString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
if (response_) {
@@ -389,7 +378,6 @@ class CacheStorageTest : public PageTestBase {
receiver_;
};
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RequestInfo* RequestToRequestInfo(Request* value) {
return MakeGarbageCollected<V8RequestInfo>(value);
}
@@ -397,19 +385,6 @@ V8RequestInfo* RequestToRequestInfo(Request* value) {
V8RequestInfo* StringToRequestInfo(const String& value) {
return MakeGarbageCollected<V8RequestInfo>(value);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-RequestInfo StringToRequestInfo(const String& value) {
- RequestInfo info;
- info.SetUSVString(value);
- return info;
-}
-
-RequestInfo RequestToRequestInfo(Request* value) {
- RequestInfo info;
- info.SetRequest(value);
- return info;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
TEST_F(CacheStorageTest, Basics) {
ScriptState::Scope scope(GetScriptState());
@@ -845,11 +820,7 @@ TEST_F(CacheStorageTest, AddAllAbortOne) {
Response* response = Response::error(GetScriptState());
fetcher->SetResponse(response);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8RequestInfo>> info_list;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<RequestInfo> info_list;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
info_list.push_back(RequestToRequestInfo(request));
ScriptPromise promise =
@@ -878,11 +849,7 @@ TEST_F(CacheStorageTest, AddAllAbortMany) {
Response* response = Response::error(GetScriptState());
fetcher->SetResponse(response);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8RequestInfo>> info_list;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<RequestInfo> info_list;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
info_list.push_back(RequestToRequestInfo(request));
info_list.push_back(RequestToRequestInfo(request));
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/idls.gni b/chromium/third_party/blink/renderer/modules/cache_storage/idls.gni
deleted file mode 100644
index dd0d4b1633e..00000000000
--- a/chromium/third_party/blink/renderer/modules/cache_storage/idls.gni
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "cache.idl",
- "cache_storage.idl",
-]
-
-modules_dictionary_idl_files = [
- "cache_query_options.idl",
- "multi_cache_query_options.idl",
-]
-
-modules_dependency_idl_files = [
- "window_cache_storage.idl",
- "worker_cache_storage.idl",
-]
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 608ef20b8f8..ca8b83bfe38 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
@@ -7,8 +7,10 @@
#include <algorithm>
#include <memory>
#include <utility>
+
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
+#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
diff --git a/chromium/third_party/blink/renderer/modules/canvas/BUILD.gn b/chromium/third_party/blink/renderer/modules/canvas/BUILD.gn
index 4c7dfb33a46..807fd66a232 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/canvas/BUILD.gn
@@ -37,6 +37,7 @@ blink_modules_sources("canvas") {
"canvas2d/hit_region.h",
"canvas2d/identifiability_study_helper.cc",
"canvas2d/identifiability_study_helper.h",
+ "canvas2d/path_2d.cc",
"canvas2d/path_2d.h",
"htmlcanvas/canvas_context_creation_attributes_helpers.cc",
"htmlcanvas/canvas_context_creation_attributes_helpers.h",
@@ -48,7 +49,6 @@ blink_modules_sources("canvas") {
"imagebitmap/image_bitmap_rendering_context.h",
"imagebitmap/image_bitmap_rendering_context_base.cc",
"imagebitmap/image_bitmap_rendering_context_base.h",
- "imagebitmap/image_bitmap_source_union.h",
"offscreencanvas/offscreen_canvas_module.cc",
"offscreencanvas/offscreen_canvas_module.h",
"offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc",
diff --git a/chromium/third_party/blink/renderer/modules/canvas/OWNERS b/chromium/third_party/blink/renderer/modules/canvas/OWNERS
index 492fe3802c9..6d502dc544e 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/canvas/OWNERS
@@ -5,5 +5,3 @@ junov@chromium.org
yiyix@chromium.org
# canvas, imagebitmap
senorblanco@chromium.org
-# lowLatency
-mcasas@chromium.org
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 aa17d476ab0..af78cfec2d6 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
@@ -12,10 +12,13 @@
#include "base/metrics/histogram_functions.h"
#include "base/numerics/checked_math.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_canvasfilter_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_csscolorvalue_canvasgradient_canvaspattern_string.h"
#include "third_party/blink/renderer/core/css/cssom/css_color_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/canvas/text_metrics.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.h"
@@ -23,9 +26,11 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#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/heap/heap.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
namespace blink {
@@ -62,8 +67,28 @@ const char BaseRenderingContext2D::kOptimizeLegibilityRendering[] =
const char BaseRenderingContext2D::kGeometricPrecisionRendering[] =
"geometricprecision";
+// After context lost, it waits |kTryRestoreContextInterval| before start the
+// restore the context. This wait needs to be long enough to avoid spamming the
+// GPU process with retry attempts and short enough to provide decent UX. It's
+// currently set to 500ms.
+const base::TimeDelta kTryRestoreContextInterval =
+ base::TimeDelta::FromMilliseconds(500);
+
BaseRenderingContext2D::BaseRenderingContext2D()
- : clip_antialiasing_(kNotAntiAliased), origin_tainted_by_content_(false) {
+ : dispatch_context_lost_event_timer_(
+ Thread::Current()->GetTaskRunner(),
+ this,
+ &BaseRenderingContext2D::DispatchContextLostEvent),
+ dispatch_context_restored_event_timer_(
+ Thread::Current()->GetTaskRunner(),
+ this,
+ &BaseRenderingContext2D::DispatchContextRestoredEvent),
+ try_restore_context_event_timer_(
+ Thread::Current()->GetTaskRunner(),
+ this,
+ &BaseRenderingContext2D::TryRestoreContextEvent),
+ clip_antialiasing_(kNotAntiAliased),
+ origin_tainted_by_content_(false) {
state_stack_.push_back(MakeGarbageCollected<CanvasRenderingContext2DState>());
}
@@ -72,6 +97,9 @@ BaseRenderingContext2D::~BaseRenderingContext2D() = default;
void BaseRenderingContext2D::save() {
if (isContextLost())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSave);
+ }
ValidateStateStack();
@@ -83,7 +111,8 @@ void BaseRenderingContext2D::save() {
cc::PaintCanvas* canvas = GetOrCreatePaintCanvas();
state_stack_.push_back(MakeGarbageCollected<CanvasRenderingContext2DState>(
- GetState(), CanvasRenderingContext2DState::kDontCopyClipList));
+ GetState(), CanvasRenderingContext2DState::kDontCopyClipList,
+ CanvasRenderingContext2DState::SaveType::kSaveRestore));
if (canvas)
canvas->save();
@@ -95,25 +124,147 @@ void BaseRenderingContext2D::restore() {
if (isContextLost())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kRestore);
+ }
ValidateStateStack();
- DCHECK_GE(state_stack_.size(), 1u);
+ DCHECK_GT(state_stack_.size(), static_cast<WTF::wtf_size_t>(layer_count_));
if (state_stack_.size() <= 1)
return;
+
+ // Verify that the top of the stack was pushed with Save.
+ if (RuntimeEnabledFeatures::Canvas2dLayersEnabled() &&
+ state_stack_.back()->GetSaveType() !=
+ CanvasRenderingContext2DState::SaveType::kSaveRestore) {
+ return;
+ }
+
+ // Verify that the current state's transform is invertible.
+ if (IsTransformInvertible())
+ path_.Transform(GetState().GetTransform());
+
+ PopAndRestore();
+}
+
+void BaseRenderingContext2D::beginLayer() {
+ if (isContextLost())
+ return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
+
+ ValidateStateStack();
+
+ DCHECK_GE(state_stack_.size(), 1u);
+
+ // GetOrCreatePaintCanvas() can call RestoreMatrixClipStack which syncs
+ // canvas to state_stack_. Get the canvas before adjusting state_stack_ to
+ // ensure canvas is synced prior to adjusting state_stack_.
+ cc::PaintCanvas* canvas = GetOrCreatePaintCanvas();
+
+ state_stack_.push_back(MakeGarbageCollected<CanvasRenderingContext2DState>(
+ GetState(), CanvasRenderingContext2DState::kDontCopyClipList,
+ CanvasRenderingContext2DState::SaveType::kBeginEndLayer));
+ layer_count_++;
+
+ PaintFlags flags;
+ GetState().FillStyle()->ApplyToFlags(flags);
+ flags.setColor(GetState().FillStyle()->PaintColor());
+ flags.setBlendMode(GetState().GlobalComposite());
+ flags.setImageFilter(StateGetFilter());
+ // TODO(crbug.com/1235854): Add shadows to flags.
+
+ if (canvas) {
+ if (StateGetFilter() && globalAlpha() != 1) {
+ // We have to save the filter before alpha.
+ GetState().setRestoreToCount(canvas->getSaveCount());
+ canvas->saveLayer(nullptr, &flags);
+
+ // Push to state stack to keep stack size up to date.
+ state_stack_.push_back(
+ MakeGarbageCollected<CanvasRenderingContext2DState>(
+ GetState(), CanvasRenderingContext2DState::kDontCopyClipList,
+ CanvasRenderingContext2DState::SaveType::kBeginEndLayer));
+
+ PaintFlags second_layer_flags;
+ GetState().FillStyle()->ApplyToFlags(second_layer_flags);
+ second_layer_flags.setColor(GetState().FillStyle()->PaintColor());
+ second_layer_flags.setAlpha(globalAlpha() * 255);
+ canvas->saveLayer(nullptr, &second_layer_flags);
+ } else {
+ GetState().setRestoreToCount(absl::nullopt);
+ flags.setAlpha(globalAlpha() * 255);
+ canvas->saveLayer(nullptr, &flags);
+ }
+ }
+
+ ValidateStateStack();
+
+ // Reset compositing attributes.
+ setGlobalAlpha(1.0);
+ setGlobalCompositeOperation("source-over");
+ V8UnionCanvasFilterOrString* filter =
+ MakeGarbageCollected<V8UnionCanvasFilterOrString>("none");
+ setFilter(GetCanvasRenderingContextHost()->GetTopExecutionContext(), filter);
+}
+
+void BaseRenderingContext2D::endLayer() {
+ if (isContextLost())
+ return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
+
+ ValidateStateStack();
+
+ DCHECK_GT(state_stack_.size(), static_cast<WTF::wtf_size_t>(layer_count_));
+ if (state_stack_.size() <= 1 || layer_count_ <= 0)
+ return;
+
// Verify that the current state's transform is invertible.
- if (GetState().IsTransformInvertible())
+ if (IsTransformInvertible())
path_.Transform(GetState().GetTransform());
+ // All saves performed since the last beginLayer are no-ops.
+ while (state_stack_.back()->GetSaveType() ==
+ CanvasRenderingContext2DState::SaveType::kSaveRestore) {
+ PopAndRestore();
+ }
+
+ DCHECK(state_stack_.back()->GetSaveType() ==
+ CanvasRenderingContext2DState::SaveType::kBeginEndLayer);
+ PopAndRestore();
+ layer_count_--;
+}
+
+void BaseRenderingContext2D::PopAndRestore() {
+ if (state_stack_.size() <= 1) {
+ NOTREACHED();
+ return;
+ }
+
state_stack_.pop_back();
state_stack_.back()->ClearResolvedFilter();
- if (GetState().IsTransformInvertible())
+ SetIsTransformInvertible(GetState().IsTransformInvertible());
+ if (IsTransformInvertible())
path_.Transform(GetState().GetTransform().Inverse());
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
- if (c)
- c->restore();
+ if (c) {
+ const absl::optional<int> restore_to_count =
+ state_stack_.back()->getRestoreToCount();
+ if (restore_to_count.has_value()) {
+ c->restoreToCount(restore_to_count.value());
+ int pops = state_stack_.size() - restore_to_count.value() + 1;
+ for (int i = 0; i < pops; i++) {
+ state_stack_.pop_back();
+ state_stack_.back()->ClearResolvedFilter();
+ }
+ } else {
+ c->restore();
+ }
+ }
ValidateStateStack();
}
@@ -147,10 +298,14 @@ void BaseRenderingContext2D::UnwindStateStack() {
}
void BaseRenderingContext2D::reset() {
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kReset);
+ }
ValidateStateStack();
UnwindStateStack();
state_stack_.resize(1);
state_stack_.front() = MakeGarbageCollected<CanvasRenderingContext2DState>();
+ SetIsTransformInvertible(true);
path_.Clear();
if (cc::PaintCanvas* c = GetPaintCanvas()) {
// The canvas should always have an initial/unbalanced save frame, which
@@ -172,7 +327,6 @@ void BaseRenderingContext2D::reset() {
origin_tainted_by_content_ = false;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString*
ConvertCanvasStyleToUnionType(CanvasStyle* style) {
if (CanvasGradient* gradient = style->GetCanvasGradient()) {
@@ -187,24 +341,8 @@ ConvertCanvasStyleToUnionType(CanvasStyle* style) {
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>(
style->GetColorAsString());
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-static inline void ConvertCanvasStyleToUnionType(
- CanvasStyle* style,
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& return_value) {
- if (CanvasGradient* gradient = style->GetCanvasGradient()) {
- return_value.SetCanvasGradient(gradient);
- return;
- }
- if (CanvasPattern* pattern = style->GetCanvasPattern()) {
- return_value.SetCanvasPattern(pattern);
- return;
- }
- return_value.SetString(style->GetColorAsString());
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void BaseRenderingContext2D::IdentifiabilityMaybeUpdateForStyleUnion(
+void BaseRenderingContext2D::IdentifiabilityUpdateForStyleUnion(
const V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* style) {
switch (style->GetContentType()) {
case V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString::
@@ -212,36 +350,24 @@ void BaseRenderingContext2D::IdentifiabilityMaybeUpdateForStyleUnion(
break;
case V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString::
ContentType::kCanvasGradient:
- identifiability_study_helper_.MaybeUpdateBuilder(
+ identifiability_study_helper_.UpdateBuilder(
style->GetAsCanvasGradient()->GetIdentifiableToken());
break;
case V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString::
ContentType::kCanvasPattern:
- identifiability_study_helper_.MaybeUpdateBuilder(
+ identifiability_study_helper_.UpdateBuilder(
style->GetAsCanvasPattern()->GetIdentifiableToken());
break;
case V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString::
ContentType::kString:
- identifiability_study_helper_.MaybeUpdateBuilder(
+ identifiability_study_helper_.UpdateBuilder(
IdentifiabilityBenignStringToken(style->GetAsString()));
break;
+ default:
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void BaseRenderingContext2D::IdentifiabilityMaybeUpdateForStyleUnion(
- const StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& style) {
- if (style.IsString()) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- IdentifiabilityBenignStringToken(style.GetAsString()));
- } else if (style.IsCanvasPattern()) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- style.GetAsCanvasPattern()->GetIdentifiableToken());
- } else if (style.IsCanvasGradient()) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- style.GetAsCanvasGradient()->GetIdentifiableToken());
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
RespectImageOrientationEnum
BaseRenderingContext2D::RespectImageOrientationInternal(
@@ -252,8 +378,6 @@ BaseRenderingContext2D::RespectImageOrientationInternal(
return RespectImageOrientation();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString*
BaseRenderingContext2D::strokeStyle() const {
return ConvertCanvasStyleToUnionType(GetState().StrokeStyle());
@@ -263,8 +387,10 @@ void BaseRenderingContext2D::setStrokeStyle(
const V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* style) {
DCHECK(style);
- identifiability_study_helper_.MaybeUpdateBuilder(CanvasOps::kSetStrokeStyle);
- IdentifiabilityMaybeUpdateForStyleUnion(style);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetStrokeStyle);
+ IdentifiabilityUpdateForStyleUnion(style);
+ }
String color_string;
CanvasStyle* canvas_style = nullptr;
@@ -312,62 +438,6 @@ void BaseRenderingContext2D::setStrokeStyle(
GetState().ClearResolvedFilter();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void BaseRenderingContext2D::strokeStyle(
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& return_value) const {
- ConvertCanvasStyleToUnionType(GetState().StrokeStyle(), return_value);
-}
-
-void BaseRenderingContext2D::setStrokeStyle(
- const StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& style) {
- DCHECK(!style.IsNull());
- identifiability_study_helper_.MaybeUpdateBuilder(CanvasOps::kSetStrokeStyle);
- IdentifiabilityMaybeUpdateForStyleUnion(style);
-
- String color_string;
- CanvasStyle* canvas_style = nullptr;
- if (style.IsString()) {
- color_string = style.GetAsString();
- if (color_string == GetState().UnparsedStrokeColor())
- return;
- Color parsed_color = 0;
- if (!ParseColorOrCurrentColor(parsed_color, color_string))
- return;
- if (GetState().StrokeStyle()->IsEquivalentRGBA(parsed_color.Rgb())) {
- GetState().SetUnparsedStrokeColor(color_string);
- return;
- }
- canvas_style = MakeGarbageCollected<CanvasStyle>(parsed_color.Rgb());
- } else if (style.IsCanvasGradient()) {
- canvas_style =
- MakeGarbageCollected<CanvasStyle>(style.GetAsCanvasGradient());
- } else if (style.IsCanvasPattern()) {
- CanvasPattern* canvas_pattern = style.GetAsCanvasPattern();
-
- if (!origin_tainted_by_content_ && !canvas_pattern->OriginClean())
- SetOriginTaintedByContent();
-
- canvas_style = MakeGarbageCollected<CanvasStyle>(canvas_pattern);
- } else if (style.IsCSSColorValue()) {
- if (!RuntimeEnabledFeatures::NewCanvas2DAPIEnabled())
- return;
- CSSColorValue* css_color = style.GetAsCSSColorValue();
- canvas_style =
- MakeGarbageCollected<CanvasStyle>(css_color->ToColor().Rgb());
- }
-
- DCHECK(canvas_style);
-
- GetState().SetStrokeStyle(canvas_style);
- GetState().SetUnparsedStrokeColor(color_string);
- GetState().ClearResolvedFilter();
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString*
BaseRenderingContext2D::fillStyle() const {
return ConvertCanvasStyleToUnionType(GetState().FillStyle());
@@ -378,8 +448,10 @@ void BaseRenderingContext2D::setFillStyle(
DCHECK(style);
ValidateStateStack();
- identifiability_study_helper_.MaybeUpdateBuilder(CanvasOps::kSetFillStyle);
- IdentifiabilityMaybeUpdateForStyleUnion(style);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetFillStyle);
+ IdentifiabilityUpdateForStyleUnion(style);
+ }
String color_string;
CanvasStyle* canvas_style = nullptr;
@@ -427,60 +499,6 @@ void BaseRenderingContext2D::setFillStyle(
GetState().ClearResolvedFilter();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void BaseRenderingContext2D::fillStyle(
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& return_value) const {
- ConvertCanvasStyleToUnionType(GetState().FillStyle(), return_value);
-}
-
-void BaseRenderingContext2D::setFillStyle(
- const StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& style) {
- DCHECK(!style.IsNull());
- ValidateStateStack();
- identifiability_study_helper_.MaybeUpdateBuilder(CanvasOps::kSetFillStyle);
- IdentifiabilityMaybeUpdateForStyleUnion(style);
-
- String color_string;
- CanvasStyle* canvas_style = nullptr;
- if (style.IsString()) {
- color_string = style.GetAsString();
- if (color_string == GetState().UnparsedFillColor())
- return;
- Color parsed_color = 0;
- if (!ParseColorOrCurrentColor(parsed_color, color_string))
- return;
- if (GetState().FillStyle()->IsEquivalentRGBA(parsed_color.Rgb())) {
- GetState().SetUnparsedFillColor(color_string);
- return;
- }
- canvas_style = MakeGarbageCollected<CanvasStyle>(parsed_color.Rgb());
- } else if (style.IsCanvasGradient()) {
- canvas_style =
- MakeGarbageCollected<CanvasStyle>(style.GetAsCanvasGradient());
- } else if (style.IsCanvasPattern()) {
- CanvasPattern* canvas_pattern = style.GetAsCanvasPattern();
-
- if (!origin_tainted_by_content_ && !canvas_pattern->OriginClean()) {
- SetOriginTaintedByContent();
- }
- canvas_style = MakeGarbageCollected<CanvasStyle>(canvas_pattern);
- } else if (style.IsCSSColorValue()) {
- if (!RuntimeEnabledFeatures::NewCanvas2DAPIEnabled())
- return;
- CSSColorValue* css_color = style.GetAsCSSColorValue();
- canvas_style =
- MakeGarbageCollected<CanvasStyle>(css_color->ToColor().Rgb());
- }
-
- DCHECK(canvas_style);
- GetState().SetFillStyle(canvas_style);
- GetState().SetUnparsedFillColor(color_string);
- GetState().ClearResolvedFilter();
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
double BaseRenderingContext2D::lineWidth() const {
return GetState().LineWidth();
}
@@ -490,6 +508,10 @@ void BaseRenderingContext2D::setLineWidth(double width) {
return;
if (GetState().LineWidth() == width)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetLineWidth,
+ width);
+ }
GetState().SetLineWidth(clampTo<float>(width));
}
@@ -503,6 +525,9 @@ void BaseRenderingContext2D::setLineCap(const String& s) {
return;
if (GetState().GetLineCap() == cap)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetLineCap, cap);
+ }
GetState().SetLineCap(cap);
}
@@ -516,6 +541,9 @@ void BaseRenderingContext2D::setLineJoin(const String& s) {
return;
if (GetState().GetLineJoin() == join)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetLineJoin, join);
+ }
GetState().SetLineJoin(join);
}
@@ -528,6 +556,10 @@ void BaseRenderingContext2D::setMiterLimit(double limit) {
return;
if (GetState().MiterLimit() == limit)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetMiterLimit,
+ limit);
+ }
GetState().SetMiterLimit(clampTo<float>(limit));
}
@@ -540,6 +572,10 @@ void BaseRenderingContext2D::setShadowOffsetX(double x) {
return;
if (GetState().ShadowOffset().Width() == x)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetShadowOffsetX,
+ x);
+ }
GetState().SetShadowOffsetX(clampTo<float>(x));
}
@@ -552,6 +588,10 @@ void BaseRenderingContext2D::setShadowOffsetY(double y) {
return;
if (GetState().ShadowOffset().Height() == y)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetShadowOffsetY,
+ y);
+ }
GetState().SetShadowOffsetY(clampTo<float>(y));
}
@@ -564,6 +604,10 @@ void BaseRenderingContext2D::setShadowBlur(double blur) {
return;
if (GetState().ShadowBlur() == blur)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetShadowBlur,
+ blur);
+ }
GetState().SetShadowBlur(clampTo<float>(blur));
}
@@ -577,6 +621,10 @@ void BaseRenderingContext2D::setShadowColor(const String& color_string) {
return;
if (GetState().ShadowColor() == color)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetShadowColor,
+ color.Rgb());
+ }
GetState().SetShadowColor(color.Rgb());
}
@@ -592,6 +640,10 @@ static bool LineDashSequenceIsValid(const Vector<double>& dash) {
void BaseRenderingContext2D::setLineDash(const Vector<double>& dash) {
if (!LineDashSequenceIsValid(dash))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetLineDash,
+ base::make_span(dash));
+ }
GetState().SetLineDash(dash);
}
@@ -602,6 +654,10 @@ double BaseRenderingContext2D::lineDashOffset() const {
void BaseRenderingContext2D::setLineDashOffset(double offset) {
if (!std::isfinite(offset) || GetState().LineDashOffset() == offset)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetLineDashOffset,
+ offset);
+ }
GetState().SetLineDashOffset(clampTo<float>(offset));
}
@@ -614,6 +670,10 @@ void BaseRenderingContext2D::setGlobalAlpha(double alpha) {
return;
if (GetState().GlobalAlpha() == alpha)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kSetGlobalAlpha,
+ alpha);
+ }
GetState().SetGlobalAlpha(alpha);
}
@@ -632,11 +692,13 @@ void BaseRenderingContext2D::setGlobalCompositeOperation(
SkBlendMode sk_blend_mode = WebCoreCompositeToSkiaComposite(op, blend_mode);
if (GetState().GlobalComposite() == sk_blend_mode)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetGlobalCompositeOpertion, sk_blend_mode);
+ }
GetState().SetGlobalComposite(sk_blend_mode);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
const V8UnionCanvasFilterOrString* BaseRenderingContext2D::filter() const {
if (CanvasFilter* filter = GetState().GetCanvasFilter()) {
return MakeGarbageCollected<V8UnionCanvasFilterOrString>(filter);
@@ -656,10 +718,17 @@ void BaseRenderingContext2D::setFilter(
if (RuntimeEnabledFeatures::NewCanvas2DAPIEnabled()) {
GetState().SetCanvasFilter(input->GetAsCanvasFilter());
SnapshotStateForFilter();
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
}
break;
case V8UnionCanvasFilterOrString::ContentType::kString: {
const String& filter_string = input->GetAsString();
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetFilter,
+ IdentifiabilitySensitiveStringToken(filter_string));
+ }
if (!GetState().GetCanvasFilter() &&
filter_string == GetState().UnparsedCSSFilter()) {
return;
@@ -678,45 +747,6 @@ void BaseRenderingContext2D::setFilter(
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void BaseRenderingContext2D::filter(StringOrCanvasFilter& filter) const {
- if (GetState().GetCanvasFilter())
- filter.SetCanvasFilter(GetState().GetCanvasFilter());
- else
- filter.SetString(GetState().UnparsedCSSFilter());
-}
-
-void BaseRenderingContext2D::setFilter(
- const ExecutionContext* execution_context,
- StringOrCanvasFilter input) {
- if (input.IsString()) {
- String filter_string = input.GetAsString();
-
- if (!GetState().GetCanvasFilter() &&
- filter_string == GetState().UnparsedCSSFilter())
- return;
-
- const CSSValue* css_value = CSSParser::ParseSingleValue(
- CSSPropertyID::kFilter, filter_string,
- MakeGarbageCollected<CSSParserContext>(
- kHTMLStandardMode, execution_context->GetSecureContextMode()));
-
- if (!css_value || css_value->IsCSSWideKeyword())
- return;
-
- GetState().SetUnparsedCSSFilter(filter_string);
- GetState().SetCSSFilter(css_value);
- SnapshotStateForFilter();
- } else if (input.IsCanvasFilter() &&
- RuntimeEnabledFeatures::NewCanvas2DAPIEnabled()) {
- GetState().SetCanvasFilter(input.GetAsCanvasFilter());
- SnapshotStateForFilter();
- }
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void BaseRenderingContext2D::scale(double sx, double sy) {
// TODO(crbug.com/1140535): Investigate the performance impact of simply
// calling the 3d version of this function
@@ -726,6 +756,9 @@ void BaseRenderingContext2D::scale(double sx, double sy) {
if (!std::isfinite(sx) || !std::isfinite(sy))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kScale, sx, sy);
+ }
TransformationMatrix new_transform = GetState().GetTransform();
float fsx = clampTo<float>(sx);
@@ -734,8 +767,8 @@ void BaseRenderingContext2D::scale(double sx, double sy) {
if (GetState().GetTransform() == new_transform)
return;
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->scale(fsx, fsy);
@@ -758,8 +791,8 @@ void BaseRenderingContext2D::scale(double sx, double sy, double sz) {
if (GetState().GetTransform() == new_transform)
return;
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
// SkCanvas has no 3d scale method for now
@@ -776,14 +809,18 @@ void BaseRenderingContext2D::rotate(double angle_in_radians) {
if (!std::isfinite(angle_in_radians))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kRotate,
+ angle_in_radians);
+ }
TransformationMatrix new_transform = GetState().GetTransform();
new_transform.Rotate(rad2deg(angle_in_radians));
if (GetState().GetTransform() == new_transform)
return;
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->rotate(clampTo<float>(angle_in_radians * (180.0 / kPiFloat)));
path_.Transform(AffineTransform().RotateRadians(-angle_in_radians));
@@ -797,6 +834,8 @@ void BaseRenderingContext2D::rotate3d(double rx, double ry, double rz) {
if (!std::isfinite(rx) || !std::isfinite(ry) || !std::isfinite(rz))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
TransformationMatrix rotation_matrix =
TransformationMatrix().Rotate3d(rad2deg(rx), rad2deg(ry), rad2deg(rz));
@@ -808,8 +847,8 @@ void BaseRenderingContext2D::rotate3d(double rx, double ry, double rz) {
return;
// Must call setTransform to set the IsTransformInvertible flag.
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->concat(TransformationMatrix::ToSkM44(rotation_matrix));
@@ -827,6 +866,8 @@ void BaseRenderingContext2D::rotateAxis(double axisX,
if (!std::isfinite(axisX) || !std::isfinite(axisY) || !std::isfinite(axisZ) ||
!std::isfinite(angle_in_radians))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
TransformationMatrix rotation_matrix = TransformationMatrix().Rotate3d(
axisX, axisY, axisZ, rad2deg(angle_in_radians));
@@ -838,8 +879,8 @@ void BaseRenderingContext2D::rotateAxis(double axisX,
return;
// Must call setTransform to set the IsTransformInvertible flag.
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->concat(TransformationMatrix::ToSkM44(rotation_matrix));
@@ -853,11 +894,14 @@ void BaseRenderingContext2D::translate(double tx, double ty) {
if (!c)
return;
- if (!GetState().IsTransformInvertible())
+ if (!IsTransformInvertible())
return;
if (!std::isfinite(tx) || !std::isfinite(ty))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kTranslate, tx, ty);
+ }
TransformationMatrix new_transform = GetState().GetTransform();
// clamp to float to avoid float cast overflow when used as SkScalar
@@ -867,8 +911,8 @@ void BaseRenderingContext2D::translate(double tx, double ty) {
if (GetState().GetTransform() == new_transform)
return;
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->translate(ftx, fty);
@@ -898,8 +942,8 @@ void BaseRenderingContext2D::translate(double tx, double ty, double tz) {
return;
// We need to call SetTransform() to set the IsTransformInvertible flag.
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->concat(TransformationMatrix::ToSkM44(translation_matrix));
@@ -913,6 +957,8 @@ void BaseRenderingContext2D::perspective(double length) {
if (length == 0 || !std::isfinite(length))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
float flength = clampTo<float>(length);
@@ -926,8 +972,8 @@ void BaseRenderingContext2D::perspective(double length) {
return;
// We need to call SetTransform() to set the IsTransformInvertible flag.
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->concat(TransformationMatrix::ToSkM44(perspective_matrix));
@@ -961,6 +1007,8 @@ void BaseRenderingContext2D::transform(double m11,
!std::isfinite(m41) || !std::isfinite(m42) || !std::isfinite(m43) ||
!std::isfinite(m44))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
// clamp to float to avoid float cast overflow when used as SkScalar
float fm11 = clampTo<float>(m11);
@@ -990,8 +1038,8 @@ void BaseRenderingContext2D::transform(double m11,
return;
// Must call setTransform to set the IsTransformInvertible flag.
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->concat(TransformationMatrix::ToSkM44(transform));
@@ -1022,14 +1070,18 @@ void BaseRenderingContext2D::transform(double m11,
float fm22 = clampTo<float>(m22);
float fdx = clampTo<float>(dx);
float fdy = clampTo<float>(dy);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kTransform, fm11,
+ fm12, fm21, fm22, fdx, fdy);
+ }
TransformationMatrix transform(fm11, fm12, fm21, fm22, fdx, fdy);
TransformationMatrix new_transform = GetState().GetTransform() * transform;
if (GetState().GetTransform() == new_transform)
return;
- GetState().SetTransform(new_transform);
- if (!GetState().IsTransformInvertible())
+ SetTransform(new_transform);
+ if (!IsTransformInvertible())
return;
c->concat(TransformationMatrix::ToSkM44(transform));
@@ -1040,9 +1092,12 @@ void BaseRenderingContext2D::resetTransform() {
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
if (!c)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kResetTransform);
+ }
TransformationMatrix ctm = GetState().GetTransform();
- bool invertible_ctm = GetState().IsTransformInvertible();
+ bool invertible_ctm = IsTransformInvertible();
// It is possible that CTM is identity while CTM is not invertible.
// When CTM becomes non-invertible, realizeSaves() can make CTM identity.
if (ctm.IsIdentity() && invertible_ctm)
@@ -1050,6 +1105,7 @@ void BaseRenderingContext2D::resetTransform() {
// resetTransform() resolves the non-invertible CTM state.
GetState().ResetTransform();
+ SetIsTransformInvertible(true);
// Set the SkCanvas' matrix to identity.
c->setMatrix(SkM44());
@@ -1146,22 +1202,22 @@ DOMMatrix* BaseRenderingContext2D::getTransform() {
return m;
}
-void BaseRenderingContext2D::beginPath() {
- path_.Clear();
+TransformationMatrix BaseRenderingContext2D::GetTransform() const {
+ return GetState().GetTransform();
}
-bool BaseRenderingContext2D::IsFullCanvasCompositeMode(SkBlendMode op) {
- // See 4.8.11.1.3 Compositing
- // CompositeSourceAtop and CompositeDestinationOut are not listed here as the
- // platforms already implement the specification's behavior.
- return op == SkBlendMode::kSrcIn || op == SkBlendMode::kSrcOut ||
- op == SkBlendMode::kDstIn || op == SkBlendMode::kDstATop;
+void BaseRenderingContext2D::beginPath() {
+ path_.Clear();
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kBeginPath);
+ }
}
void BaseRenderingContext2D::DrawPathInternal(
const Path& path,
CanvasRenderingContext2DState::PaintType paint_type,
- SkPathFillType fill_type) {
+ SkPathFillType fill_type,
+ UsePaintCache use_paint_cache) {
if (path.IsEmpty())
return;
@@ -1178,14 +1234,16 @@ void BaseRenderingContext2D::DrawPathInternal(
if (!GetOrCreatePaintCanvas())
return;
- Draw([sk_path](cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
- { c->drawPath(sk_path, *flags); },
+ Draw([sk_path, use_paint_cache](cc::PaintCanvas* c,
+ const PaintFlags* flags) // draw lambda
+ { c->drawPath(sk_path, *flags, use_paint_cache); },
[](const SkIRect& rect) // overdraw test lambda
{ return false; },
bounds, paint_type,
GetState().HasPattern(paint_type)
? CanvasRenderingContext2DState::kNonOpaqueImage
- : CanvasRenderingContext2DState::kNoImage);
+ : CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kPath);
}
static SkPathFillType ParseWinding(const String& winding_rule_string) {
@@ -1199,24 +1257,42 @@ static SkPathFillType ParseWinding(const String& winding_rule_string) {
}
void BaseRenderingContext2D::fill(const String& winding_rule_string) {
+ const SkPathFillType winding_rule = ParseWinding(winding_rule_string);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kFill, winding_rule);
+ }
DrawPathInternal(path_, CanvasRenderingContext2DState::kFillPaintType,
- ParseWinding(winding_rule_string));
+ winding_rule, UsePaintCache::kDisabled);
}
void BaseRenderingContext2D::fill(Path2D* dom_path,
const String& winding_rule_string) {
+ const SkPathFillType winding_rule = ParseWinding(winding_rule_string);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kFill__Path, dom_path->GetIdentifiableToken(), winding_rule);
+ }
DrawPathInternal(dom_path->GetPath(),
- CanvasRenderingContext2DState::kFillPaintType,
- ParseWinding(winding_rule_string));
+ CanvasRenderingContext2DState::kFillPaintType, winding_rule,
+ UsePaintCache::kEnabled);
}
void BaseRenderingContext2D::stroke() {
- DrawPathInternal(path_, CanvasRenderingContext2DState::kStrokePaintType);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kStroke);
+ }
+ DrawPathInternal(path_, CanvasRenderingContext2DState::kStrokePaintType,
+ SkPathFillType::kWinding, UsePaintCache::kDisabled);
}
void BaseRenderingContext2D::stroke(Path2D* dom_path) {
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kStroke__Path, dom_path->GetIdentifiableToken());
+ }
DrawPathInternal(dom_path->GetPath(),
- CanvasRenderingContext2DState::kStrokePaintType);
+ CanvasRenderingContext2DState::kStrokePaintType,
+ SkPathFillType::kWinding, UsePaintCache::kEnabled);
}
void BaseRenderingContext2D::fillRect(double x,
@@ -1228,6 +1304,10 @@ void BaseRenderingContext2D::fillRect(double x,
if (!GetOrCreatePaintCanvas())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kFillRect, x, y,
+ width, height);
+ }
// clamp to float to avoid float cast overflow when used as SkScalar
AdjustRectForCanvas(x, y, width, height);
@@ -1260,7 +1340,8 @@ void BaseRenderingContext2D::fillRect(double x,
rect, CanvasRenderingContext2DState::kFillPaintType,
GetState().HasPattern(CanvasRenderingContext2DState::kFillPaintType)
? CanvasRenderingContext2DState::kNonOpaqueImage
- : CanvasRenderingContext2DState::kNoImage);
+ : CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kRectangle);
}
static void StrokeRectOnCanvas(const FloatRect& rect,
@@ -1288,6 +1369,10 @@ void BaseRenderingContext2D::strokeRect(double x,
if (!GetOrCreatePaintCanvas())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kStrokeRect, x, y,
+ width, height);
+ }
// clamp to float to avoid float cast overflow when used as SkScalar
AdjustRectForCanvas(x, y, width, height);
@@ -1311,33 +1396,46 @@ void BaseRenderingContext2D::strokeRect(double x,
bounds, CanvasRenderingContext2DState::kStrokePaintType,
GetState().HasPattern(CanvasRenderingContext2DState::kStrokePaintType)
? CanvasRenderingContext2DState::kNonOpaqueImage
- : CanvasRenderingContext2DState::kNoImage);
+ : CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kRectangle);
}
void BaseRenderingContext2D::ClipInternal(const Path& path,
- const String& winding_rule_string) {
+ const String& winding_rule_string,
+ UsePaintCache use_paint_cache) {
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
if (!c) {
return;
}
- if (!GetState().IsTransformInvertible()) {
+ if (!IsTransformInvertible()) {
return;
}
SkPath sk_path = path.GetSkPath();
sk_path.setFillType(ParseWinding(winding_rule_string));
GetState().ClipPath(sk_path, clip_antialiasing_);
- c->clipPath(sk_path, SkClipOp::kIntersect,
- clip_antialiasing_ == kAntiAliased);
+ c->clipPath(sk_path, SkClipOp::kIntersect, clip_antialiasing_ == kAntiAliased,
+ use_paint_cache);
}
void BaseRenderingContext2D::clip(const String& winding_rule_string) {
- ClipInternal(path_, winding_rule_string);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kClip,
+ IdentifiabilitySensitiveStringToken(winding_rule_string));
+ }
+ ClipInternal(path_, winding_rule_string, UsePaintCache::kDisabled);
}
void BaseRenderingContext2D::clip(Path2D* dom_path,
const String& winding_rule_string) {
- ClipInternal(dom_path->GetPath(), winding_rule_string);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kClip__Path, dom_path->GetIdentifiableToken(),
+ IdentifiabilitySensitiveStringToken(winding_rule_string));
+ }
+ ClipInternal(dom_path->GetPath(), winding_rule_string,
+ UsePaintCache::kEnabled);
}
bool BaseRenderingContext2D::isPointInPath(const double x,
@@ -1361,7 +1459,7 @@ bool BaseRenderingContext2D::IsPointInPathInternal(
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
if (!c)
return false;
- if (!GetState().IsTransformInvertible())
+ if (!IsTransformInvertible())
return false;
if (!std::isfinite(x) || !std::isfinite(y))
@@ -1390,7 +1488,7 @@ bool BaseRenderingContext2D::IsPointInStrokeInternal(const Path& path,
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
if (!c)
return false;
- if (!GetState().IsTransformInvertible())
+ if (!IsTransformInvertible())
return false;
if (!std::isfinite(x) || !std::isfinite(y))
@@ -1421,12 +1519,16 @@ void BaseRenderingContext2D::clearRect(double x,
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
if (!c)
return;
- if (!GetState().IsTransformInvertible())
+ if (!IsTransformInvertible())
return;
SkIRect clip_bounds;
if (!c->getDeviceClipBounds(&clip_bounds))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kClearRect, x, y,
+ width, height);
+ }
PaintFlags clear_flags;
clear_flags.setBlendMode(SkBlendMode::kClear);
@@ -1443,14 +1545,15 @@ void BaseRenderingContext2D::clearRect(double x,
if (RectContainsTransformedRect(rect, clip_bounds)) {
CheckOverdraw(rect, &clear_flags, CanvasRenderingContext2DState::kNoImage,
kClipFill);
- c = GetPaintCanvas(); // Check overdraw may have swapped the PaintCanvas
- c->drawRect(rect, clear_flags);
- DidDraw(clip_bounds);
+ GetPaintCanvasForDraw(clip_bounds,
+ CanvasPerformanceMonitor::DrawType::kOther)
+ ->drawRect(rect, clear_flags);
} else {
SkIRect dirty_rect;
if (ComputeDirtyRect(rect, clip_bounds, &dirty_rect)) {
- c->drawRect(rect, clear_flags);
- DidDraw(dirty_rect);
+ GetPaintCanvasForDraw(clip_bounds,
+ CanvasPerformanceMonitor::DrawType::kOther)
+ ->drawRect(rect, clear_flags);
}
}
}
@@ -1485,12 +1588,7 @@ static inline void ClipRectsToImageRect(const FloatRect& image_rect,
}
void BaseRenderingContext2D::drawImage(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CanvasImageSource* image_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CanvasImageSourceUnion&
- image_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
double x,
double y,
ExceptionState& exception_state) {
@@ -1511,12 +1609,7 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
}
void BaseRenderingContext2D::drawImage(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CanvasImageSource* image_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CanvasImageSourceUnion&
- image_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
double x,
double y,
double width,
@@ -1535,12 +1628,7 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
}
void BaseRenderingContext2D::drawImage(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CanvasImageSource* image_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CanvasImageSourceUnion&
- image_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
double sx,
double sy,
double sw,
@@ -1589,6 +1677,41 @@ bool BaseRenderingContext2D::ShouldDrawImageAntialiased(
dest_rect.Height() * fabs(height_expansion) < 1;
}
+void BaseRenderingContext2D::DispatchContextLostEvent(TimerBase*) {
+ if (GetCanvasRenderingContextHost() &&
+ RuntimeEnabledFeatures::NewCanvas2DAPIEnabled()) {
+ Event* event = Event::CreateCancelable(event_type_names::kContextlost);
+ GetCanvasRenderingContextHost()->HostDispatchEvent(event);
+
+ UseCounter::Count(GetCanvasRenderingContextHost()->GetTopExecutionContext(),
+ WebFeature::kCanvasRenderingContext2DContextLostEvent);
+ if (event->defaultPrevented()) {
+ context_restorable_ = false;
+ }
+ }
+
+ if (context_restorable_ &&
+ (context_lost_mode_ == CanvasRenderingContext::kRealLostContext ||
+ context_lost_mode_ == CanvasRenderingContext::kSyntheticLostContext)) {
+ try_restore_context_attempt_count_ = 0;
+ try_restore_context_event_timer_.StartOneShot(kTryRestoreContextInterval,
+ FROM_HERE);
+ }
+}
+
+void BaseRenderingContext2D::DispatchContextRestoredEvent(TimerBase*) {
+ DCHECK(context_lost_mode_ != CanvasRenderingContext::kNotLostContext);
+ reset();
+ context_lost_mode_ = CanvasRenderingContext::kNotLostContext;
+ if (RuntimeEnabledFeatures::NewCanvas2DAPIEnabled()) {
+ Event* event(Event::Create(event_type_names::kContextrestored));
+ GetCanvasRenderingContextHost()->HostDispatchEvent(event);
+ UseCounter::Count(
+ GetCanvasRenderingContextHost()->GetTopExecutionContext(),
+ WebFeature::kCanvasRenderingContext2DContextRestoredEvent);
+ }
+}
+
void BaseRenderingContext2D::DrawImageInternal(
cc::PaintCanvas* c,
CanvasImageSource* image_source,
@@ -1646,9 +1769,11 @@ void BaseRenderingContext2D::DrawImageInternal(
image->SizeAsFloat(kRespectImageOrientation), src_rect);
}
image_flags.setAntiAlias(ShouldDrawImageAntialiased(dst_rect));
- image->Draw(c, image_flags, dst_rect, corrected_src_rect, sampling,
- respect_orientation, Image::kDoNotClampImageToSourceRect,
- Image::kSyncDecode);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = sampling;
+ draw_options.respect_image_orientation = respect_orientation;
+ image->Draw(c, image_flags, dst_rect, corrected_src_rect, draw_options,
+ Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
} else {
c->save();
c->clipRect(dst_rect);
@@ -1732,6 +1857,12 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
if (src_rect.IsEmpty())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kDrawImage, fsx, fsy, fsw, fsh, fdx, fdy, fdw, fdh,
+ image ? image->width() : 0, image ? image->height() : 0);
+ identifiability_study_helper_.set_encountered_partially_digested_image();
+ }
ValidateStateStack();
@@ -1748,16 +1879,17 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
{
SkSamplingOptions sampling =
PaintFlags::FilterQualityToSkSamplingOptions(
- flags ? flags->getFilterQuality() : kNone_SkFilterQuality);
+ flags ? flags->getFilterQuality()
+ : cc::PaintFlags::FilterQuality::kNone);
DrawImageInternal(c, image_source, image.get(), src_rect, dst_rect,
sampling, flags);
},
[this, &dst_rect](const SkIRect& clip_bounds) // overdraw test lambda
{ return RectContainsTransformedRect(dst_rect, clip_bounds); },
dst_rect, CanvasRenderingContext2DState::kImagePaintType,
- image_source->IsOpaque()
- ? CanvasRenderingContext2DState::kOpaqueImage
- : CanvasRenderingContext2DState::kNonOpaqueImage);
+ image_source->IsOpaque() ? CanvasRenderingContext2DState::kOpaqueImage
+ : CanvasRenderingContext2DState::kNonOpaqueImage,
+ CanvasPerformanceMonitor::DrawType::kImage);
ValidateStateStack();
bool source_is_canvas = false;
@@ -1779,12 +1911,14 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
image_source_name = "SVG";
} else if (image_source->IsVideoElement()) {
image_source_name = "Video";
+ } else if (image_source->IsVideoFrame()) {
+ image_source_name = "VideoFrame";
} else { // Unknown source.
image_source_name = "Unknown";
}
std::string duration_histogram_name =
- "Blink.Canvas.DrawImage.Duration." + image_source_name;
+ "Blink.Canvas.DrawImage.Duration2." + image_source_name;
std::string size_histogram_name =
"Blink.Canvas.DrawImage.SqrtNumberOfPixels." + image_source_name;
@@ -1800,9 +1934,7 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
- // TODO(crbug.com/983261) Change this to use UmaHistogramMicrosecondsTimes.
- base::UmaHistogramMicrosecondsTimesUnderTenMilliseconds(
- duration_histogram_name, elapsed);
+ base::UmaHistogramMicrosecondsTimes(duration_histogram_name, elapsed);
float sqrt_pixels_float =
std::sqrt(dst_rect.Width()) * std::sqrt(dst_rect.Height());
@@ -1851,6 +1983,8 @@ CanvasGradient* BaseRenderingContext2D::createLinearGradient(double x0,
auto* gradient = MakeGarbageCollected<CanvasGradient>(FloatPoint(fx0, fy0),
FloatPoint(fx1, fy1));
+ gradient->SetExecutionContext(
+ identifiability_study_helper_.execution_context());
return gradient;
}
@@ -1884,6 +2018,8 @@ CanvasGradient* BaseRenderingContext2D::createRadialGradient(
auto* gradient = MakeGarbageCollected<CanvasGradient>(
FloatPoint(fx0, fy0), fr0, FloatPoint(fx1, fy1), fr1);
+ gradient->SetExecutionContext(
+ identifiability_study_helper_.execution_context());
return gradient;
}
@@ -1893,6 +2029,8 @@ CanvasGradient* BaseRenderingContext2D::createConicGradient(double startAngle,
if (!std::isfinite(startAngle) || !std::isfinite(centerX) ||
!std::isfinite(centerY))
return nullptr;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
// clamp to float to avoid float cast overflow
float a = clampTo<float>(startAngle);
@@ -1904,10 +2042,11 @@ CanvasGradient* BaseRenderingContext2D::createConicGradient(double startAngle,
a = rad2deg(a) + 90;
auto* gradient = MakeGarbageCollected<CanvasGradient>(a, FloatPoint(x, y));
+ gradient->SetExecutionContext(
+ identifiability_study_helper_.execution_context());
return gradient;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CanvasPattern* BaseRenderingContext2D::createPattern(
ScriptState* script_state,
const V8CanvasImageSource* image_source,
@@ -1922,22 +2061,6 @@ CanvasPattern* BaseRenderingContext2D::createPattern(
return createPattern(script_state, image_source_internal, repetition_type,
exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CanvasPattern* BaseRenderingContext2D::createPattern(
- ScriptState* script_state,
- const CanvasImageSourceUnion& image_source,
- const String& repetition_type,
- ExceptionState& exception_state) {
- CanvasImageSource* image_source_internal =
- ToCanvasImageSource(image_source, exception_state);
- if (!image_source_internal) {
- return nullptr;
- }
-
- return createPattern(script_state, image_source_internal, repetition_type,
- exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CanvasPattern* BaseRenderingContext2D::createPattern(
ScriptState* script_state,
@@ -1992,43 +2115,22 @@ CanvasPattern* BaseRenderingContext2D::createPattern(
bool origin_clean = !WouldTaintOrigin(image_source);
- return MakeGarbageCollected<CanvasPattern>(std::move(image_for_rendering),
- repeat_mode, origin_clean);
+ auto* pattern = MakeGarbageCollected<CanvasPattern>(
+ std::move(image_for_rendering), repeat_mode, origin_clean);
+ pattern->SetExecutionContext(
+ identifiability_study_helper_.execution_context());
+ return pattern;
}
bool BaseRenderingContext2D::ComputeDirtyRect(const FloatRect& local_rect,
SkIRect* dirty_rect) {
SkIRect clip_bounds;
- if (!GetOrCreatePaintCanvas() ||
- !GetPaintCanvas()->getDeviceClipBounds(&clip_bounds))
+ cc::PaintCanvas* paint_canvas = GetOrCreatePaintCanvas();
+ if (!paint_canvas || !paint_canvas->getDeviceClipBounds(&clip_bounds))
return false;
return ComputeDirtyRect(local_rect, clip_bounds, dirty_rect);
}
-bool BaseRenderingContext2D::ComputeDirtyRect(
- const FloatRect& local_rect,
- const SkIRect& transformed_clip_bounds,
- SkIRect* dirty_rect) {
- FloatRect canvas_rect = GetState().GetTransform().MapRect(local_rect);
-
- if (AlphaChannel(GetState().ShadowColor())) {
- FloatRect shadow_rect(canvas_rect);
- shadow_rect.Move(GetState().ShadowOffset());
- shadow_rect.Inflate(clampTo<float>(GetState().ShadowBlur()));
- canvas_rect.Unite(shadow_rect);
- }
-
- SkIRect canvas_i_rect;
- static_cast<SkRect>(canvas_rect).roundOut(&canvas_i_rect);
- if (!canvas_i_rect.intersect(transformed_clip_bounds))
- return false;
-
- if (dirty_rect)
- *dirty_rect = canvas_i_rect;
-
- return true;
-}
-
ImageData* BaseRenderingContext2D::createImageData(
ImageData* image_data,
ExceptionState& exception_state) const {
@@ -2042,6 +2144,18 @@ ImageData* BaseRenderingContext2D::createImageData(
ImageData* BaseRenderingContext2D::createImageData(
int sw,
int sh,
+ ExceptionState& exception_state) const {
+ ImageData::ValidateAndCreateParams params;
+ params.context_2d_error_mode = true;
+ params.default_color_space = GetCanvas2DColorParams().ColorSpace();
+ return ImageData::ValidateAndCreate(std::abs(sw), std::abs(sh), absl::nullopt,
+ /*settings=*/nullptr, params,
+ exception_state);
+}
+
+ImageData* BaseRenderingContext2D::createImageData(
+ int sw,
+ int sh,
ImageDataSettings* image_data_settings,
ExceptionState& exception_state) const {
ImageData::ValidateAndCreateParams params;
@@ -2057,6 +2171,16 @@ ImageData* BaseRenderingContext2D::getImageData(
int sy,
int sw,
int sh,
+ ExceptionState& exception_state) {
+ return getImageDataInternal(sx, sy, sw, sh, /*image_data_settings=*/nullptr,
+ exception_state);
+}
+
+ImageData* BaseRenderingContext2D::getImageData(
+ int sx,
+ int sy,
+ int sw,
+ int sh,
ImageDataSettings* image_data_settings,
ExceptionState& exception_state) {
return getImageDataInternal(sx, sy, sw, sh, image_data_settings,
@@ -2241,6 +2365,14 @@ void BaseRenderingContext2D::putImageData(ImageData* data,
if (!hasResourceProvider)
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kPutImageData, data->width(), data->height(),
+ data->GetCanvasColorSpace(), data->GetImageDataStorageFormat(), dx, dy,
+ dirty_x, dirty_y, dirty_width, dirty_height);
+ identifiability_study_helper_.set_encountered_partially_digested_image();
+ }
+
if (dirty_width < 0) {
if (dirty_x < 0) {
dirty_x = dirty_width = 0;
@@ -2327,7 +2459,8 @@ void BaseRenderingContext2D::putImageData(ImageData* data,
}
}
- DidDraw(dest_rect);
+ GetPaintCanvasForDraw(dest_rect,
+ CanvasPerformanceMonitor::DrawType::kImageData);
}
void BaseRenderingContext2D::PutByteArray(const SkPixmap& source,
@@ -2384,6 +2517,10 @@ bool BaseRenderingContext2D::imageSmoothingEnabled() const {
void BaseRenderingContext2D::setImageSmoothingEnabled(bool enabled) {
if (enabled == GetState().ImageSmoothingEnabled())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetImageSmoothingEnabled, enabled);
+ }
GetState().SetImageSmoothingEnabled(enabled);
}
@@ -2396,6 +2533,11 @@ void BaseRenderingContext2D::setImageSmoothingQuality(const String& quality) {
if (quality == GetState().ImageSmoothingQuality())
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetImageSmoothingQuality,
+ IdentifiabilitySensitiveStringToken(quality));
+ }
GetState().SetImageSmoothingQuality(quality);
}
@@ -2463,16 +2605,16 @@ void BaseRenderingContext2D::CheckOverdraw(
WillOverwriteCanvas();
}
-double BaseRenderingContext2D::textLetterSpacing() const {
- return GetState().GetTextLetterSpacing();
+double BaseRenderingContext2D::letterSpacing() const {
+ return GetState().GetLetterSpacing();
}
-double BaseRenderingContext2D::textWordSpacing() const {
- return GetState().GetTextWordSpacing();
+double BaseRenderingContext2D::wordSpacing() const {
+ return GetState().GetWordSpacing();
}
String BaseRenderingContext2D::textRendering() const {
- return ToString(GetState().GetTextRendering());
+ return ToStringForIdl(GetState().GetTextRendering());
}
float BaseRenderingContext2D::GetFontBaseline(
@@ -2485,8 +2627,10 @@ String BaseRenderingContext2D::textAlign() const {
}
void BaseRenderingContext2D::setTextAlign(const String& s) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kSetTextAlign, IdentifiabilityBenignStringToken(s));
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetTextAlign, IdentifiabilityBenignStringToken(s));
+ }
TextAlign align;
if (!ParseTextAlign(s, align))
return;
@@ -2500,8 +2644,10 @@ String BaseRenderingContext2D::textBaseline() const {
}
void BaseRenderingContext2D::setTextBaseline(const String& s) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kSetTextBaseline, IdentifiabilityBenignStringToken(s));
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetTextBaseline, IdentifiabilityBenignStringToken(s));
+ }
TextBaseline baseline;
if (!ParseTextBaseline(s, baseline))
return;
@@ -2511,19 +2657,23 @@ void BaseRenderingContext2D::setTextBaseline(const String& s) {
}
String BaseRenderingContext2D::fontKerning() const {
- return FontDescription::ToString(GetState().GetFontKerning());
+ return FontDescription::ToString(GetState().GetFontKerning()).LowerASCII();
}
String BaseRenderingContext2D::fontStretch() const {
- return FontDescription::ToString(GetState().GetFontStretch());
+ return FontDescription::ToString(GetState().GetFontStretch()).LowerASCII();
}
String BaseRenderingContext2D::fontVariantCaps() const {
- return FontDescription::ToString(GetState().GetFontVariantCaps());
+ return FontDescription::ToStringForIdl(GetState().GetFontVariantCaps());
}
void BaseRenderingContext2D::Trace(Visitor* visitor) const {
visitor->Trace(state_stack_);
+ visitor->Trace(dispatch_context_lost_event_timer_);
+ visitor->Trace(dispatch_context_restored_event_timer_);
+ visitor->Trace(try_restore_context_event_timer_);
+ CanvasPath::Trace(visitor);
}
BaseRenderingContext2D::UsageCounters::UsageCounters()
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 f2d9413a80d..b3226c81992 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
@@ -7,11 +7,9 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/modules/v8/canvas_image_source.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_canvas_filter.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_canvas_gradient_or_canvas_pattern_or_css_color_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h"
@@ -30,33 +28,21 @@ class Image;
class Path2D;
class V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString;
class V8UnionCanvasFilterOrString;
+using cc::UsePaintCache;
-class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
- public CanvasPath {
+class MODULES_EXPORT BaseRenderingContext2D : public CanvasPath {
public:
~BaseRenderingContext2D() override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* strokeStyle()
const;
void setStrokeStyle(
const V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* style);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void strokeStyle(StringOrCanvasGradientOrCanvasPatternOrCSSColorValue&) const;
- void setStrokeStyle(
- const StringOrCanvasGradientOrCanvasPatternOrCSSColorValue&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* fillStyle()
const;
void setFillStyle(
const V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* style);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void fillStyle(StringOrCanvasGradientOrCanvasPatternOrCSSColorValue&) const;
- void setFillStyle(
- const StringOrCanvasGradientOrCanvasPatternOrCSSColorValue&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
double lineWidth() const;
void setLineWidth(double);
@@ -94,17 +80,16 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
String globalCompositeOperation() const;
void setGlobalCompositeOperation(const String&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionCanvasFilterOrString* filter() const;
void setFilter(const ExecutionContext* execution_context,
const V8UnionCanvasFilterOrString* input);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void filter(StringOrCanvasFilter&) const;
- void setFilter(const ExecutionContext*, StringOrCanvasFilter input);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void save();
void restore();
+ // Push state on state stack and creates bitmap for subsequent draw ops.
+ void beginLayer();
+ // Pop state stack if top state was pushed by beginLayer, restore state and draw the bitmap.
+ void endLayer();
void reset();
void scale(double sx, double sy);
@@ -189,7 +174,6 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
void fillRect(double x, double y, double width, double height);
void strokeRect(double x, double y, double width, double height);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void drawImage(ScriptState* script_state,
const V8CanvasImageSource* image_source,
double x,
@@ -213,31 +197,6 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
double dw,
double dh,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void drawImage(ScriptState*,
- const CanvasImageSourceUnion&,
- double x,
- double y,
- ExceptionState&);
- void drawImage(ScriptState*,
- const CanvasImageSourceUnion&,
- double x,
- double y,
- double width,
- double height,
- ExceptionState&);
- void drawImage(ScriptState*,
- const CanvasImageSourceUnion&,
- double sx,
- double sy,
- double sw,
- double sh,
- double dx,
- double dy,
- double dw,
- double dh,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void drawImage(ScriptState*,
CanvasImageSource*,
double sx,
@@ -264,23 +223,17 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
CanvasGradient* createConicGradient(double startAngle,
double centerX,
double centerY);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CanvasPattern* createPattern(ScriptState* script_state,
const V8CanvasImageSource* image_source,
const String& repetition_type,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasPattern* createPattern(ScriptState*,
- const CanvasImageSourceUnion&,
- const String& repetition_type,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CanvasPattern* createPattern(ScriptState*,
CanvasImageSource*,
const String& repetition_type,
ExceptionState&);
ImageData* createImageData(ImageData*, ExceptionState&) const;
+ ImageData* createImageData(int sw, int sh, ExceptionState&) const;
ImageData* createImageData(int sw,
int sh,
ImageDataSettings*,
@@ -288,6 +241,7 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
// For deferred canvases this will have the side effect of drawing recorded
// commands in order to finalize the frame
+ ImageData* getImageData(int sx, int sy, int sw, int sh, ExceptionState&);
ImageData* getImageData(int sx,
int sy,
int sw,
@@ -336,15 +290,21 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
virtual cc::PaintCanvas* GetOrCreatePaintCanvas() = 0;
virtual cc::PaintCanvas* GetPaintCanvas() const = 0;
+ virtual cc::PaintCanvas* GetPaintCanvasForDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType) = 0;
- virtual void DidDraw(const SkIRect& dirty_rect) = 0;
-
- virtual bool StateHasFilter() = 0;
virtual sk_sp<PaintFilter> StateGetFilter() = 0;
virtual void SnapshotStateForFilter() = 0;
+ virtual CanvasRenderingContextHost* GetCanvasRenderingContextHost() {
+ return nullptr;
+ }
+
void ValidateStateStack() const {
+#if DCHECK_IS_ON()
ValidateStateStackWithCanvas(GetPaintCanvas());
+#endif
}
virtual void ValidateStateStackWithCanvas(const cc::PaintCanvas*) const = 0;
@@ -367,8 +327,8 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
String textBaseline() const;
void setTextBaseline(const String&);
- double textLetterSpacing() const;
- double textWordSpacing() const;
+ double letterSpacing() const;
+ double wordSpacing() const;
String textRendering() const;
String fontKerning() const;
@@ -430,6 +390,12 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
};
const UsageCounters& GetUsage();
+ HeapTaskRunnerTimer<BaseRenderingContext2D>
+ dispatch_context_lost_event_timer_;
+ HeapTaskRunnerTimer<BaseRenderingContext2D>
+ dispatch_context_restored_event_timer_;
+ HeapTaskRunnerTimer<BaseRenderingContext2D> try_restore_context_event_timer_;
+ unsigned try_restore_context_attempt_count_ = 0;
protected:
BaseRenderingContext2D();
@@ -448,7 +414,8 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
const DrawCoversClipBoundsFunc&,
const SkRect& bounds,
CanvasRenderingContext2DState::PaintType,
- CanvasRenderingContext2DState::ImageType);
+ CanvasRenderingContext2DState::ImageType,
+ CanvasPerformanceMonitor::DrawType);
void InflateStrokeRect(FloatRect&) const;
@@ -482,11 +449,16 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
DrawType);
HeapVector<Member<CanvasRenderingContext2DState>> state_stack_;
+ // Counts how many states have been pushed with BeginLayer.
+ int layer_count_ = 0;
AntiAliasingMode clip_antialiasing_;
virtual void FinalizeFrame() {}
float GetFontBaseline(const SimpleFontData&) const;
+ virtual void DispatchContextLostEvent(TimerBase*);
+ virtual void DispatchContextRestoredEvent(TimerBase*);
+ virtual void TryRestoreContextEvent(TimerBase*) {}
static const char kDefaultFont[];
static const char kInheritDirectionString[];
@@ -522,17 +494,30 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
virtual bool IsPaint2D() const { return false; }
virtual void WillOverwriteCanvas() = 0;
- IdentifiabilityStudyHelper identifiability_study_helper_;
+ bool context_restorable_{true};
+ CanvasRenderingContext::LostContextMode context_lost_mode_{
+ CanvasRenderingContext::kNotLostContext};
private:
+ // Pops from the top of the state stack, inverts transform, restores the
+ // PaintCanvas, and validates the state stack. Helper for Restore and
+ // EndLayer.
+ void PopAndRestore();
+
bool ShouldDrawImageAntialiased(const FloatRect& dest_rect) const;
+ void SetTransform(const TransformationMatrix&);
+
+ TransformationMatrix GetTransform() const override;
+
+ bool StateHasFilter();
+
// When the canvas is stroked or filled with a pattern, which is assumed to
// have a transparent background, the shadow needs to be applied with
// DropShadowPaintFilter for kNonOpaqueImageType
// Used in Draw and CompositedDraw to avoid the shadow offset being modified
// by the transformation matrix
- bool ShouldUseDropShadowPaintFilter(
+ ALWAYS_INLINE bool ShouldUseDropShadowPaintFilter(
CanvasRenderingContext2DState::PaintType paint_type,
CanvasRenderingContext2DState::ImageType image_type) const {
return (paint_type == CanvasRenderingContext2DState::kFillPaintType ||
@@ -546,11 +531,13 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
const SkRect& bounds,
CanvasRenderingContext2DState::PaintType,
CanvasRenderingContext2DState::ImageType,
- const SkIRect& clip_bounds);
+ const SkIRect& clip_bounds,
+ CanvasPerformanceMonitor::DrawType);
void DrawPathInternal(const Path&,
CanvasRenderingContext2DState::PaintType,
- SkPathFillType = SkPathFillType::kWinding);
+ SkPathFillType,
+ UsePaintCache);
void DrawImageInternal(cc::PaintCanvas*,
CanvasImageSource*,
Image*,
@@ -558,7 +545,9 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
const FloatRect& dst_rect,
const SkSamplingOptions&,
const PaintFlags*);
- void ClipInternal(const Path&, const String& winding_rule_string);
+ void ClipInternal(const Path&,
+ const String& winding_rule_string,
+ UsePaintCache);
bool IsPointInPathInternal(const Path&,
const double x,
@@ -599,13 +588,10 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
float height,
base::TimeTicks start_time);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void IdentifiabilityMaybeUpdateForStyleUnion(
+ // Only call if identifiability_study_helper_.ShouldUpdateBuilder() returns
+ // true.
+ void IdentifiabilityUpdateForStyleUnion(
const V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString* style);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void IdentifiabilityMaybeUpdateForStyleUnion(
- const StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& style);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
RespectImageOrientationEnum RespectImageOrientationInternal(
CanvasImageSource*);
@@ -622,29 +608,29 @@ void BaseRenderingContext2D::DrawInternal(
const SkRect& bounds,
CanvasRenderingContext2DState::PaintType paint_type,
CanvasRenderingContext2DState::ImageType image_type,
- const SkIRect& clip_bounds) {
- if (IsFullCanvasCompositeMode(GetState().GlobalComposite()) ||
- StateHasFilter() ||
- (GetState().ShouldDrawShadows() &&
+ const SkIRect& clip_bounds,
+ CanvasPerformanceMonitor::DrawType draw_type) {
+ const CanvasRenderingContext2DState& state = GetState();
+ SkBlendMode global_composite = state.GlobalComposite();
+ if (IsFullCanvasCompositeMode(global_composite) || StateHasFilter() ||
+ (state.ShouldDrawShadows() &&
ShouldUseDropShadowPaintFilter(paint_type, image_type))) {
- CompositedDraw(draw_func, GetPaintCanvas(), paint_type, image_type);
- DidDraw(clip_bounds);
- } else if (GetState().GlobalComposite() == SkBlendMode::kSrc) {
+ CompositedDraw(draw_func, GetPaintCanvasForDraw(clip_bounds, draw_type),
+ paint_type, image_type);
+ } else if (global_composite == SkBlendMode::kSrc) {
ClearCanvas(); // takes care of checkOverdraw()
const PaintFlags* flags =
- GetState().GetFlags(paint_type, kDrawForegroundOnly, image_type);
- draw_func(GetPaintCanvas(), flags);
- DidDraw(clip_bounds);
+ state.GetFlags(paint_type, kDrawForegroundOnly, image_type);
+ draw_func(GetPaintCanvasForDraw(clip_bounds, draw_type), flags);
} else {
SkIRect dirty_rect;
if (ComputeDirtyRect(bounds, clip_bounds, &dirty_rect)) {
const PaintFlags* flags =
- GetState().GetFlags(paint_type, kDrawShadowAndForeground, image_type);
+ state.GetFlags(paint_type, kDrawShadowAndForeground, image_type);
if (paint_type != CanvasRenderingContext2DState::kStrokePaintType &&
draw_covers_clip_bounds(clip_bounds))
CheckOverdraw(bounds, flags, image_type, kClipFill);
- draw_func(GetPaintCanvas(), flags);
- DidDraw(dirty_rect);
+ draw_func(GetPaintCanvasForDraw(dirty_rect, draw_type), flags);
}
}
}
@@ -655,8 +641,9 @@ void BaseRenderingContext2D::Draw(
const DrawCoversClipBoundsFunc& draw_covers_clip_bounds,
const SkRect& bounds,
CanvasRenderingContext2DState::PaintType paint_type,
- CanvasRenderingContext2DState::ImageType image_type) {
- if (!GetState().IsTransformInvertible())
+ CanvasRenderingContext2DState::ImageType image_type,
+ CanvasPerformanceMonitor::DrawType draw_type) {
+ if (!IsTransformInvertible())
return;
SkIRect clip_bounds;
@@ -670,10 +657,10 @@ void BaseRenderingContext2D::Draw(
&BaseRenderingContext2D::DrawInternal<DrawFunc,
DrawCoversClipBoundsFunc>,
WrapPersistent(this), draw_func, draw_covers_clip_bounds, bounds,
- paint_type, image_type, clip_bounds));
+ paint_type, image_type, clip_bounds, draw_type));
} else {
DrawInternal(draw_func, draw_covers_clip_bounds, bounds, paint_type,
- image_type, clip_bounds);
+ image_type, clip_bounds, draw_type);
}
}
@@ -684,24 +671,24 @@ void BaseRenderingContext2D::CompositedDraw(
CanvasRenderingContext2DState::PaintType paint_type,
CanvasRenderingContext2DState::ImageType image_type) {
sk_sp<PaintFilter> canvas_filter = StateGetFilter();
- DCHECK(IsFullCanvasCompositeMode(GetState().GlobalComposite()) ||
- canvas_filter ||
- (GetState().ShouldDrawShadows() &&
+ const CanvasRenderingContext2DState& state = GetState();
+ DCHECK(IsFullCanvasCompositeMode(state.GlobalComposite()) || canvas_filter ||
+ (state.ShouldDrawShadows() &&
ShouldUseDropShadowPaintFilter(paint_type, image_type)));
SkM44 ctm = c->getLocalToDevice();
c->setMatrix(SkM44());
PaintFlags composite_flags;
- composite_flags.setBlendMode(GetState().GlobalComposite());
- if (GetState().ShouldDrawShadows()) {
+ composite_flags.setBlendMode(state.GlobalComposite());
+ if (state.ShouldDrawShadows()) {
// unroll into two independently composited passes if drawing shadows
PaintFlags shadow_flags =
- *GetState().GetFlags(paint_type, kDrawShadowOnly, image_type);
+ *state.GetFlags(paint_type, kDrawShadowOnly, image_type);
int save_count = c->getSaveCount();
c->save();
if (canvas_filter ||
ShouldUseDropShadowPaintFilter(paint_type, image_type)) {
PaintFlags foreground_flags =
- *GetState().GetFlags(paint_type, kDrawForegroundOnly, image_type);
+ *state.GetFlags(paint_type, kDrawForegroundOnly, image_type);
shadow_flags.setImageFilter(sk_make_sp<ComposePaintFilter>(
sk_make_sp<ComposePaintFilter>(foreground_flags.getImageFilter(),
shadow_flags.getImageFilter()),
@@ -712,7 +699,7 @@ void BaseRenderingContext2D::CompositedDraw(
c->setMatrix(ctm);
draw_func(c, &foreground_flags);
} else {
- DCHECK(IsFullCanvasCompositeMode(GetState().GlobalComposite()));
+ DCHECK(IsFullCanvasCompositeMode(state.GlobalComposite()));
c->saveLayer(nullptr, &composite_flags);
shadow_flags.setBlendMode(SkBlendMode::kSrcOver);
c->setMatrix(ctm);
@@ -724,7 +711,7 @@ void BaseRenderingContext2D::CompositedDraw(
composite_flags.setImageFilter(std::move(canvas_filter));
c->saveLayer(nullptr, &composite_flags);
PaintFlags foreground_flags =
- *GetState().GetFlags(paint_type, kDrawForegroundOnly, image_type);
+ *state.GetFlags(paint_type, kDrawForegroundOnly, image_type);
foreground_flags.setBlendMode(SkBlendMode::kSrcOver);
c->setMatrix(ctm);
draw_func(c, &foreground_flags);
@@ -757,6 +744,53 @@ void BaseRenderingContext2D::AdjustRectForCanvas(T& x,
}
}
+ALWAYS_INLINE void BaseRenderingContext2D::SetTransform(
+ const TransformationMatrix& matrix) {
+ GetState().SetTransform(matrix);
+ SetIsTransformInvertible(matrix.IsInvertible());
+}
+
+ALWAYS_INLINE bool BaseRenderingContext2D::IsFullCanvasCompositeMode(
+ SkBlendMode op) {
+ // See 4.8.11.1.3 Compositing
+ // CompositeSourceAtop and CompositeDestinationOut are not listed here as the
+ // platforms already implement the specification's behavior.
+ return op == SkBlendMode::kSrcIn || op == SkBlendMode::kSrcOut ||
+ op == SkBlendMode::kDstIn || op == SkBlendMode::kDstATop;
+}
+
+ALWAYS_INLINE bool BaseRenderingContext2D::StateHasFilter() {
+ const CanvasRenderingContext2DState& state = GetState();
+ if (UNLIKELY(state.IsFilterUnresolved())) {
+ DCHECK(!IsInFastMode()); // Should de-opt before reaching this point.
+ return !!StateGetFilter();
+ }
+ // The fast path avoids the virtual call overhead of StateGetFilter
+ return state.IsFilterResolved();
+}
+
+ALWAYS_INLINE bool BaseRenderingContext2D::ComputeDirtyRect(
+ const FloatRect& local_rect,
+ const SkIRect& transformed_clip_bounds,
+ SkIRect* dirty_rect) {
+ DCHECK(dirty_rect);
+ const CanvasRenderingContext2DState& state = GetState();
+ FloatRect canvas_rect = state.GetTransform().MapRect(local_rect);
+
+ if (UNLIKELY(AlphaChannel(state.ShadowColor()))) {
+ FloatRect shadow_rect(canvas_rect);
+ shadow_rect.Move(state.ShadowOffset());
+ shadow_rect.Inflate(clampTo<float>(state.ShadowBlur()));
+ canvas_rect.Unite(shadow_rect);
+ }
+
+ static_cast<SkRect>(canvas_rect).roundOut(dirty_rect);
+ if (UNLIKELY(!dirty_rect->intersect(transformed_clip_bounds)))
+ return false;
+
+ return true;
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_BASE_RENDERING_CONTEXT_2D_H_
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.cc
index c12f0233915..f9edd3c11b1 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.cc
@@ -14,16 +14,10 @@ CanvasFilter::CanvasFilter(FilterOperations filter_operations)
: filter_operations_(filter_operations) {}
CanvasFilter* CanvasFilter::Create(
- ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionCanvasFilterDictionaryOrCanvasFilterDictionaryArray* init,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasFilterDictionaryOrCanvasFilterDictionaryArray& init,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
HeapVector<Member<CanvasFilterDictionary>> filter_array;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (init->GetContentType()) {
case V8UnionCanvasFilterDictionaryOrCanvasFilterDictionaryArray::
ContentType::kCanvasFilterDictionary:
@@ -34,16 +28,10 @@ CanvasFilter* CanvasFilter::Create(
filter_array = init->GetAsCanvasFilterDictionaryArray();
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (init.IsCanvasFilterDictionary())
- filter_array.push_back(init.GetAsCanvasFilterDictionary());
- else
- filter_array = init.GetAsCanvasFilterDictionaryArray();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FilterOperations filter_operations =
- CanvasFilterOperationResolver::CreateFilterOperations(
- script_state, filter_array, exception_state);
+ CanvasFilterOperationResolver::CreateFilterOperations(filter_array,
+ exception_state);
return MakeGarbageCollected<CanvasFilter>(filter_operations);
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.h
index 3e269f20e80..b9b538d9111 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_FILTER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_FILTER_H_
-#include "third_party/blink/renderer/bindings/modules/v8/canvas_filter_dictionary_or_canvas_filter_dictionary_array.h"
#include "third_party/blink/renderer/core/style/filter_operations.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -22,17 +21,9 @@ class MODULES_EXPORT CanvasFilter final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static CanvasFilter* Create(
- ScriptState* script_state,
const V8UnionCanvasFilterDictionaryOrCanvasFilterDictionaryArray* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static CanvasFilter* Create(
- ScriptState*,
- CanvasFilterDictionaryOrCanvasFilterDictionaryArray&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
explicit CanvasFilter(FilterOperations filter_operations);
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.idl b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.idl
index 85f51bcf8bd..f843fe422a0 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter.idl
@@ -6,6 +6,6 @@
Exposed=(Window,Worker), RuntimeEnabled=NewCanvas2DAPI
] interface CanvasFilter {
- [CallWith=(ScriptState), RaisesException] constructor((CanvasFilterDictionary or FrozenArray<CanvasFilterDictionary>) init);
+ [RaisesException] constructor((CanvasFilterDictionary or FrozenArray<CanvasFilterDictionary>) init);
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_dictionary.idl b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_dictionary.idl
index 6421cc3300b..e37fa2d98f6 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_dictionary.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_dictionary.idl
@@ -7,4 +7,5 @@ dictionary CanvasFilterDictionary {
object blur;
object colorMatrix;
object convolveMatrix;
+ object componentTransfer;
};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.cc
index f51498f1640..bc55c50c042 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.cc
@@ -3,283 +3,198 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
+#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
+#include "third_party/blink/renderer/core/svg/svg_enumeration_map.h"
+#include "third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.h"
namespace blink {
namespace {
-double GetDoubleOr(double default_value,
- v8::Local<v8::Object> v8_object,
- WTF::String key,
- ScriptState* script_state) {
- v8::Local<v8::Value> v8_value;
- if (!v8_object
- ->Get(script_state->GetContext(),
- V8String(script_state->GetIsolate(), key))
- .ToLocal(&v8_value) ||
- !v8_value->IsNumber()) {
- return default_value;
- }
-
- double result = v8_value.As<v8::Number>()->Value();
- if (!std::isfinite(result))
- return default_value;
- return result;
-}
-
-bool GetBooleanOr(bool default_value,
- v8::Local<v8::Object> v8_object,
- WTF::String key,
- ScriptState* script_state) {
- v8::Local<v8::Value> v8_value;
- if (!v8_object
- ->Get(script_state->GetContext(),
- V8String(script_state->GetIsolate(), key))
- .ToLocal(&v8_value) ||
- !v8_value->IsBoolean()) {
- return default_value;
- }
-
- return v8_value.As<v8::Boolean>()->Value();
-}
-
-String GetStringValue(v8::Local<v8::Object> v8_object,
- WTF::String key,
- ScriptState* script_state) {
- v8::Local<v8::Value> v8_type;
- if (!v8_object
- ->Get(script_state->GetContext(),
- V8String(script_state->GetIsolate(), "type"))
- .ToLocal(&v8_type))
- return String();
- return ToCoreStringWithUndefinedOrNullCheck(v8_type);
-}
-
-BlurFilterOperation* ResolveBlur(v8::Local<v8::Object> v8_filter_obj,
- ScriptState* script_state,
+BlurFilterOperation* ResolveBlur(const Dictionary& blur_dict,
ExceptionState& exception_state) {
- Length std_deviation = Length::Fixed(0);
- v8::Local<v8::Value> v8_std_deviation;
- if (v8_filter_obj
- ->Get(script_state->GetContext(),
- V8String(script_state->GetIsolate(), "stdDeviation"))
- .ToLocal(&v8_std_deviation)) {
- if (v8_std_deviation->IsNumber()) {
- std_deviation = Length::Fixed(v8_std_deviation.As<v8::Number>()->Value());
- } else if (v8_std_deviation->IsUndefined()) {
- exception_state.ThrowTypeError(
- "Failed to construct blur filter, 'stdDeviation' required.");
- return nullptr;
- } else {
- exception_state.ThrowTypeError(
- "Failed to construct blur filter, 'stdDeviation' must be a number.");
- return nullptr;
- }
- } else {
+ absl::optional<double> std_deviation =
+ blur_dict.Get<IDLDouble>("stdDeviation", exception_state);
+ if (!std_deviation) {
exception_state.ThrowTypeError(
- "Failed to construct blur filter, 'stdDeviation' required.");
+ "Failed to construct blur filter, 'stdDeviation' required and must be "
+ "a number.");
return nullptr;
}
- return MakeGarbageCollected<BlurFilterOperation>(std_deviation);
+ return MakeGarbageCollected<BlurFilterOperation>(
+ Length::Fixed(*std_deviation));
}
ColorMatrixFilterOperation* ResolveColorMatrix(
- v8::Local<v8::Object> v8_filter_obj,
- ScriptState* script_state,
+ const Dictionary& dict,
ExceptionState& exception_state) {
- v8::Local<v8::Value> v8_value;
- v8::Local<v8::Array> v8_array;
- if (v8_filter_obj
- ->Get(script_state->GetContext(),
- V8String(script_state->GetIsolate(), "values"))
- .ToLocal(&v8_value)) {
- if (!v8_value->IsArray()) {
- exception_state.ThrowTypeError(
- "Failed to construct color matrix filter, 'values' must be an array "
- "of 20 numbers.");
- return nullptr;
- }
- v8_array = v8_value.As<v8::Array>();
- }
+ absl::optional<Vector<float>> values =
+ dict.Get<IDLSequence<IDLFloat>>("values", exception_state);
- // Color matrices are 4x5, so the input must be of length 20.
- // https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feColorMatrix
- const int length = 20;
- if (v8_array->Length() != length) {
+ if (!values) {
exception_state.ThrowTypeError(
- "Failed to construct color matrix filter, 'values' array must have 20 "
- "numbers.");
+ "Failed to construct color matrix filter, 'values' array required.");
return nullptr;
}
- Vector<float> values;
- values.ReserveInitialCapacity(length);
- for (uint32_t i = 0; i < length; ++i) {
- if (!v8_array->Get(script_state->GetContext(), i).ToLocal(&v8_value) ||
- !v8_value->IsNumber()) {
- exception_state.ThrowTypeError(
- "Failed to construct color matrix filter, 'values' array must be "
- "numbers.");
- return nullptr;
- }
- const float value = v8_value.As<v8::Number>()->Value();
- if (!std::isfinite(value)) {
- exception_state.ThrowTypeError(
- "Failed to construct color matrix filter, 'values' array must have "
- "finite values.");
- return nullptr;
- }
- values.push_back(value);
+ if (values->size() != 20) {
+ exception_state.ThrowTypeError(
+ "Failed to construct color matrix filter, 'values' must be an array "
+ "of 20 numbers.");
+ return nullptr;
}
return MakeGarbageCollected<ColorMatrixFilterOperation>(
- values, FilterOperation::COLOR_MATRIX);
+ *values, FilterOperation::COLOR_MATRIX);
}
struct KernelMatrix {
Vector<float> values;
- int width = 0;
- int height = 0;
+ uint32_t width;
+ uint32_t height;
};
// For resolving feConvolveMatrix type filters
-KernelMatrix* GetKernelMatrix(v8::Local<v8::Object> v8_filter_obj,
- ScriptState* script_state,
- ExceptionState& exception_state) {
- v8::Local<v8::Value> v8_value;
- v8::Local<v8::Array> v8_kernel_matrix;
- if (v8_filter_obj
- ->Get(script_state->GetContext(),
- V8String(script_state->GetIsolate(), "kernelMatrix"))
- .ToLocal(&v8_value)) {
- if (!v8_value->IsArray()) {
- exception_state.ThrowTypeError(
- "Failed to construct convolve matrix filter. 'kernelMatrix' must be "
- "an array of arrays representing an n by m matrix.");
- return nullptr;
- }
- v8_kernel_matrix = v8_value.As<v8::Array>();
- }
-
- KernelMatrix* kernel_matrix = new KernelMatrix();
- kernel_matrix->height = v8_kernel_matrix->Length();
- v8::Local<v8::Array> v8_kernel_matrix_row;
- if (!v8_kernel_matrix->Get(script_state->GetContext(), 0)
- .ToLocal(&v8_value) ||
- !v8_value->IsArray()) {
+absl::optional<KernelMatrix> GetKernelMatrix(const Dictionary& dict,
+ ExceptionState& exception_state) {
+ absl::optional<Vector<Vector<float>>> km_input =
+ dict.Get<IDLSequence<IDLSequence<IDLFloat>>>("kernelMatrix",
+ exception_state);
+ if (!km_input || km_input->size() == 0) {
exception_state.ThrowTypeError(
"Failed to construct convolve matrix filter. 'kernelMatrix' must be an "
- "array of arrays representing an n by m matrix.");
- return nullptr;
+ "array of arrays of numbers representing an n by m matrix.");
+ return absl::nullopt;
}
- v8_kernel_matrix_row = v8_value.As<v8::Array>();
- kernel_matrix->width = v8_kernel_matrix_row->Length();
- kernel_matrix->values.ReserveInitialCapacity(kernel_matrix->width *
- kernel_matrix->height);
+ KernelMatrix result;
+ result.height = km_input->size();
+ result.width = km_input.value()[0].size();
- for (int y = 0; y < kernel_matrix->height; ++y) {
- if (!v8_kernel_matrix->Get(script_state->GetContext(), y)
- .ToLocal(&v8_value) ||
- !v8_value->IsArray()) {
- exception_state.ThrowTypeError(
- "Failed to construct convolve matrix filter. 'kernelMatrix' must be "
- "an array of arrays representing an n by m matrix.");
- return nullptr;
- }
- v8_kernel_matrix_row = v8_value.As<v8::Array>();
- if (int(v8_kernel_matrix_row->Length()) != kernel_matrix->width) {
+ for (uint32_t y = 0; y < result.height; ++y) {
+ if (km_input.value()[y].size() != result.width) {
exception_state.ThrowTypeError(
"Failed to construct convolve matrix filter. All rows of the "
"'kernelMatrix' must be the same length.");
- return nullptr;
+ return absl::nullopt;
}
- for (int x = 0; x < kernel_matrix->width; ++x) {
- if (!v8_kernel_matrix_row->Get(script_state->GetContext(), x)
- .ToLocal(&v8_value) ||
- !v8_value->IsNumber()) {
- exception_state.ThrowTypeError(
- "Failed to construct convolve matrix filter. All 'kernelMatrix' "
- "values must be numbers.");
- return nullptr;
- }
- const float value = v8_value.As<v8::Number>()->Value();
- if (!std::isfinite(value)) {
- exception_state.ThrowTypeError(
- "Failed to construct convolve matrix filter, 'kernel_matrix' must "
- "have finite values.");
- return kernel_matrix;
- }
- kernel_matrix->values.push_back(value);
- }
+ result.values.AppendVector(km_input.value()[y]);
}
- return kernel_matrix;
+ return absl::optional<KernelMatrix>(result);
}
ConvolveMatrixFilterOperation* ResolveConvolveMatrix(
- v8::Local<v8::Object> v8_filter_obj,
- ScriptState* script_state,
+ const Dictionary& dict,
ExceptionState& exception_state) {
- KernelMatrix* kernel_matrix =
- GetKernelMatrix(v8_filter_obj, script_state, exception_state);
+ absl::optional<KernelMatrix> kernel_matrix =
+ GetKernelMatrix(dict, exception_state);
if (!kernel_matrix)
return nullptr;
IntSize kernel_size(kernel_matrix->width, kernel_matrix->height);
- double divisor = GetDoubleOr(1, v8_filter_obj, "divisor", script_state);
- double bias = GetDoubleOr(0, v8_filter_obj, "bias", script_state);
+ double divisor = dict.Get<IDLDouble>("divisor", exception_state).value_or(1);
+ double bias = dict.Get<IDLDouble>("bias", exception_state).value_or(0);
IntPoint target_offset =
- IntPoint(int(GetDoubleOr(kernel_matrix->width / 2, v8_filter_obj,
- "targetX", script_state)),
- int(GetDoubleOr(kernel_matrix->height / 2, v8_filter_obj,
- "targetY", script_state)));
- FEConvolveMatrix::EdgeModeType edge_mode =
- FEConvolveMatrix::EDGEMODE_DUPLICATE;
+ IntPoint(dict.Get<IDLShort>("targetX", exception_state)
+ .value_or(kernel_matrix->width / 2),
+ dict.Get<IDLShort>("targetY", exception_state)
+ .value_or(kernel_matrix->height / 2));
+
String edge_mode_string =
- GetStringValue(v8_filter_obj, "edgeMode", script_state);
- if (edge_mode_string == "wrap")
- edge_mode = FEConvolveMatrix::EDGEMODE_WRAP;
- if (edge_mode_string == "none")
- edge_mode = FEConvolveMatrix::EDGEMODE_NONE;
+ dict.Get<IDLString>("edgeMode", exception_state).value_or("duplicate");
+ FEConvolveMatrix::EdgeModeType edge_mode =
+ static_cast<FEConvolveMatrix::EdgeModeType>(
+ GetEnumerationMap<FEConvolveMatrix::EdgeModeType>().ValueFromName(
+ edge_mode_string));
+
bool preserve_alpha =
- GetBooleanOr(false, v8_filter_obj, "preserve_alpha", script_state);
+ dict.Get<IDLBoolean>("preserveAlpha", exception_state).value_or(false);
return MakeGarbageCollected<ConvolveMatrixFilterOperation>(
kernel_size, divisor, bias, target_offset, edge_mode, preserve_alpha,
kernel_matrix->values);
}
+
+ComponentTransferFunction GetComponentTransferFunction(
+ const StringView& key,
+ const Dictionary& filter,
+ ExceptionState& exception_state) {
+ Dictionary transfer_dict;
+ filter.Get(key, transfer_dict);
+
+ ComponentTransferFunction result;
+ result.slope =
+ transfer_dict.Get<IDLDouble>("slope", exception_state).value_or(1);
+ result.intercept =
+ transfer_dict.Get<IDLDouble>("intercept", exception_state).value_or(0);
+ result.amplitude =
+ transfer_dict.Get<IDLDouble>("amplitude", exception_state).value_or(1);
+ result.exponent =
+ transfer_dict.Get<IDLDouble>("exponent", exception_state).value_or(1);
+ result.offset =
+ transfer_dict.Get<IDLDouble>("offset", exception_state).value_or(0);
+
+ absl::optional<Vector<float>> table_values =
+ transfer_dict.Get<IDLSequence<IDLFloat>>("tableValues", exception_state);
+ if (table_values)
+ result.table_values.AppendVector(table_values.value());
+
+ String type = transfer_dict.Get<IDLString>("type", exception_state)
+ .value_or("identity");
+ if (type == "identity")
+ result.type = FECOMPONENTTRANSFER_TYPE_IDENTITY;
+ else if (type == "linear")
+ result.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
+ else if (type == "gamma")
+ result.type = FECOMPONENTTRANSFER_TYPE_GAMMA;
+ else if (type == "table")
+ result.type = FECOMPONENTTRANSFER_TYPE_TABLE;
+ else if (type == "discrete")
+ result.type = FECOMPONENTTRANSFER_TYPE_DISCRETE;
+
+ return result;
+}
+
+ComponentTransferFilterOperation* ResolveComponentTransfer(
+ const Dictionary& dict,
+ ExceptionState& exception_state) {
+ return MakeGarbageCollected<ComponentTransferFilterOperation>(
+ GetComponentTransferFunction("funcR", dict, exception_state),
+ GetComponentTransferFunction("funcG", dict, exception_state),
+ GetComponentTransferFunction("funcB", dict, exception_state),
+ GetComponentTransferFunction("funcA", dict, exception_state));
+}
} // namespace
FilterOperations CanvasFilterOperationResolver::CreateFilterOperations(
- ScriptState* script_state,
HeapVector<Member<CanvasFilterDictionary>> filters,
ExceptionState& exception_state) {
FilterOperations operations;
- v8::Local<v8::Context> context = script_state->GetContext();
for (auto filter : filters) {
- v8::Local<v8::Object> v8_object;
- if (filter->hasBlur() &&
- filter->blur().V8Value()->ToObject(context).ToLocal(&v8_object)) {
+ if (filter->hasBlur()) {
if (auto* blur_operation =
- ResolveBlur(v8_object, script_state, exception_state)) {
+ ResolveBlur(Dictionary(filter->blur()), exception_state)) {
operations.Operations().push_back(blur_operation);
}
}
- if (filter->hasColorMatrix() &&
- filter->colorMatrix().V8Value()->ToObject(context).ToLocal(
- &v8_object)) {
- String type = GetStringValue(v8_object, "type", script_state);
+ if (filter->hasColorMatrix()) {
+ Dictionary colormatrix_dict(filter->colorMatrix());
+ String type = colormatrix_dict.Get<IDLString>("type", exception_state)
+ .value_or("matrix");
if (type == "hueRotate") {
- double amount = GetDoubleOr(0, v8_object, "values", script_state);
+ double amount =
+ colormatrix_dict.Get<IDLDouble>("values", exception_state)
+ .value_or(0);
operations.Operations().push_back(
MakeGarbageCollected<BasicColorMatrixFilterOperation>(
amount, FilterOperation::HUE_ROTATE));
} else if (type == "saturate") {
- double amount = GetDoubleOr(0, v8_object, "values", script_state);
+ double amount =
+ colormatrix_dict.Get<IDLDouble>("values", exception_state)
+ .value_or(0);
operations.Operations().push_back(
MakeGarbageCollected<BasicColorMatrixFilterOperation>(
amount, FilterOperation::SATURATE));
@@ -287,19 +202,23 @@ FilterOperations CanvasFilterOperationResolver::CreateFilterOperations(
operations.Operations().push_back(
MakeGarbageCollected<BasicColorMatrixFilterOperation>(
0, FilterOperation::LUMINANCE_TO_ALPHA));
- } else if (auto* color_matrix_operation = ResolveColorMatrix(
- v8_object, script_state, exception_state)) {
+ } else if (auto* color_matrix_operation =
+ ResolveColorMatrix(colormatrix_dict, exception_state)) {
operations.Operations().push_back(color_matrix_operation);
}
}
- if (filter->hasConvolveMatrix() &&
- filter->convolveMatrix().V8Value()->ToObject(context).ToLocal(
- &v8_object)) {
- if (auto* convolve_operation =
- ResolveConvolveMatrix(v8_object, script_state, exception_state)) {
+ if (filter->hasConvolveMatrix()) {
+ if (auto* convolve_operation = ResolveConvolveMatrix(
+ Dictionary(filter->convolveMatrix()), exception_state)) {
operations.Operations().push_back(convolve_operation);
}
}
+ if (filter->hasComponentTransfer()) {
+ if (auto* component_transfer_operation = ResolveComponentTransfer(
+ Dictionary(filter->componentTransfer()), exception_state)) {
+ operations.Operations().push_back(component_transfer_operation);
+ }
+ }
}
return operations;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.h
index bdb0e8539ec..463f28872ac 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_filter_operation_resolver.h
@@ -27,7 +27,6 @@ class MODULES_EXPORT CanvasFilterOperationResolver {
public:
static FilterOperations CreateFilterOperations(
- ScriptState*,
HeapVector<Member<CanvasFilterDictionary>>,
ExceptionState&);
};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_formatted_text.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_formatted_text.cc
index 34ce2d74512..ee834bd45d6 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_formatted_text.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_formatted_text.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_formatted_text.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h"
@@ -146,9 +147,6 @@ sk_sp<PaintRecord> CanvasFormattedText::PaintFormattedText(
LayoutBlockFlow* block = GetLayoutBlock(document, font);
NGBlockNode block_node(block);
NGInlineNode node(block);
- // Call IsEmptyInline to force prepare layout.
- if (node.IsEmptyInline())
- return nullptr;
// TODO(sushraja) Once we add support for writing mode on the canvas formatted
// text, fix this to be not hardcoded horizontal top to bottom.
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 7510eb5b568..bf61fdafed4 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
@@ -39,8 +39,10 @@ CanvasGradient::CanvasGradient(const FloatPoint& p0, const FloatPoint& p1)
kSpreadMethodPad,
Gradient::ColorInterpolation::kUnpremultiplied,
Gradient::DegenerateHandling::kDisallow)) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kCreateLinearGradient, p0.X(), p0.Y(), p1.X(), p1.Y());
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kCreateLinearGradient, p0.X(), p0.Y(), p1.X(), p1.Y());
+ }
}
CanvasGradient::CanvasGradient(const FloatPoint& p0,
@@ -56,8 +58,11 @@ CanvasGradient::CanvasGradient(const FloatPoint& p0,
kSpreadMethodPad,
Gradient::ColorInterpolation::kUnpremultiplied,
Gradient::DegenerateHandling::kDisallow)) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kCreateRadialGradient, p0.X(), p0.Y(), r0, p1.X(), p1.Y(), r1);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kCreateRadialGradient, p0.X(), p0.Y(), r0, p1.X(), p1.Y(),
+ r1);
+ }
}
// CanvasRenderingContext2D.createConicGradient only takes one angle argument
@@ -90,8 +95,10 @@ void CanvasGradient::addColorStop(double value,
"') could not be parsed as a color.");
return;
}
- identifiability_study_helper_.MaybeUpdateBuilder(CanvasOps::kAddColorStop,
- value, color.Rgb());
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kAddColorStop, value,
+ color.Rgb());
+ }
gradient_->AddColorStop(value, color);
}
@@ -100,4 +107,13 @@ IdentifiableToken CanvasGradient::GetIdentifiableToken() const {
return identifiability_study_helper_.GetToken();
}
+void CanvasGradient::SetExecutionContext(ExecutionContext* context) {
+ identifiability_study_helper_.SetExecutionContext(context);
+}
+
+void CanvasGradient::Trace(Visitor* visitor) const {
+ visitor->Trace(identifiability_study_helper_);
+ ScriptWrappable::Trace(visitor);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h
index 6da67968611..7d8c53ba56b 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h
@@ -58,6 +58,11 @@ class MODULES_EXPORT CanvasGradient final : public ScriptWrappable {
IdentifiableToken GetIdentifiableToken() const;
+ // Sets on internal IdentifiabilityStudyHelper.
+ void SetExecutionContext(ExecutionContext*);
+
+ void Trace(Visitor* visitor) const override;
+
private:
scoped_refptr<Gradient> gradient_;
IdentifiabilityStudyHelper identifiability_study_helper_;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.cc
index 12b4b15a440..b82b385c41c 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.cc
@@ -16,7 +16,6 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CanvasImageSource* ToCanvasImageSource(const V8CanvasImageSource* value,
ExceptionState& exception_state) {
DCHECK(value);
@@ -78,70 +77,5 @@ CanvasImageSource* ToCanvasImageSource(const V8CanvasImageSource* value,
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-CanvasImageSource* ToCanvasImageSource(const CanvasImageSourceUnion& value,
- ExceptionState& exception_state) {
- if (value.IsCSSImageValue())
- return value.GetAsCSSImageValue();
- if (value.IsHTMLImageElement())
- return value.GetAsHTMLImageElement();
- if (value.IsHTMLVideoElement()) {
- HTMLVideoElement* video = value.GetAsHTMLVideoElement();
- video->VideoWillBeDrawnToCanvas();
- return video;
- }
- if (value.IsSVGImageElement())
- return value.GetAsSVGImageElement();
- if (value.IsHTMLCanvasElement()) {
- if (static_cast<HTMLCanvasElement*>(value.GetAsHTMLCanvasElement())
- ->Size()
- .IsEmpty()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "The image argument is a canvas element with a width "
- "or height of 0.");
- return nullptr;
- }
- return value.GetAsHTMLCanvasElement();
- }
- if (value.IsImageBitmap()) {
- if (static_cast<ImageBitmap*>(value.GetAsImageBitmap())->IsNeutered()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The image source is detached");
- return nullptr;
- }
- return value.GetAsImageBitmap();
- }
- if (value.IsOffscreenCanvas()) {
- if (static_cast<OffscreenCanvas*>(value.GetAsOffscreenCanvas())
- ->IsNeutered()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The image source is detached");
- return nullptr;
- }
- if (static_cast<OffscreenCanvas*>(value.GetAsOffscreenCanvas())
- ->Size()
- .IsEmpty()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "The image argument is an OffscreenCanvas element "
- "with a width or height of 0.");
- return nullptr;
- }
- return value.GetAsOffscreenCanvas();
- }
- if (value.IsVideoFrame()) {
- auto* video_frame = static_cast<VideoFrame*>(value.GetAsVideoFrame());
- if (!video_frame->frame()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The VideoFrame has been closed");
- return nullptr;
- }
- return video_frame;
- }
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h
index ddc55b3ed8c..27a6ee53216 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h
@@ -5,27 +5,17 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_IMAGE_SOURCE_UTIL_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_IMAGE_SOURCE_UTIL_H_
-#include "third_party/blink/renderer/bindings/modules/v8/canvas_image_source.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
class CanvasImageSource;
+class ExceptionState;
-using CanvasImageSourceUnion =
- CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvasOrVideoFrame;
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MODULES_EXPORT CanvasImageSource* ToCanvasImageSource(
const V8CanvasImageSource* value,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-MODULES_EXPORT CanvasImageSource* ToCanvasImageSource(
- const CanvasImageSourceUnion& value,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
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 4c470190457..91a3900be2b 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
@@ -36,8 +36,9 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h"
#include "base/numerics/safe_conversions.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_dompoint_unrestricteddouble.h"
-#include "third_party/blink/renderer/core/geometry/dom_point.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_dom_point_init.h"
+#include "third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.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"
@@ -49,17 +50,24 @@ namespace blink {
// DoublePoint & DoubleRect instead of FloatPoint & FloatRect.
void CanvasPath::closePath() {
- if (path_.IsEmpty())
+ if (UNLIKELY(path_.IsEmpty()))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kClosePath);
+ }
path_.CloseSubpath();
}
void CanvasPath::moveTo(double double_x, double double_y) {
float x = base::saturated_cast<float>(double_x);
float y = base::saturated_cast<float>(double_y);
- if (!std::isfinite(x) || !std::isfinite(y))
+ if (UNLIKELY(!std::isfinite(x) || !std::isfinite(y)))
return;
- if (!IsTransformInvertible()) {
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kMoveTo, double_x,
+ double_y);
+ }
+ if (UNLIKELY(!IsTransformInvertible())) {
path_.MoveTo(GetTransform().MapPoint(FloatPoint(x, y)));
return;
}
@@ -69,15 +77,19 @@ void CanvasPath::moveTo(double double_x, double double_y) {
void CanvasPath::lineTo(double double_x, double double_y) {
float x = base::saturated_cast<float>(double_x);
float y = base::saturated_cast<float>(double_y);
- if (!std::isfinite(x) || !std::isfinite(y))
+ if (UNLIKELY(!std::isfinite(x) || !std::isfinite(y)))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kLineTo, double_x,
+ double_y);
+ }
FloatPoint p1 = FloatPoint(x, y);
- if (!IsTransformInvertible()) {
+ if (UNLIKELY(!IsTransformInvertible())) {
p1 = GetTransform().MapPoint(p1);
}
- if (!path_.HasCurrentPoint())
+ if (UNLIKELY(!path_.HasCurrentPoint()))
path_.MoveTo(p1);
path_.AddLineTo(p1);
@@ -92,18 +104,23 @@ void CanvasPath::quadraticCurveTo(double double_cpx,
float x = base::saturated_cast<float>(double_x);
float y = base::saturated_cast<float>(double_y);
- if (!std::isfinite(cpx) || !std::isfinite(cpy) || !std::isfinite(x) ||
- !std::isfinite(y))
+ if (UNLIKELY(!std::isfinite(cpx) || !std::isfinite(cpy) ||
+ !std::isfinite(x) || !std::isfinite(y)))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kQuadradicCurveTo,
+ double_cpx, double_cpy,
+ double_x, double_y);
+ }
FloatPoint p1 = FloatPoint(x, y);
FloatPoint cp = FloatPoint(cpx, cpy);
- if (!IsTransformInvertible()) {
+ if (UNLIKELY(!IsTransformInvertible())) {
p1 = GetTransform().MapPoint(p1);
cp = GetTransform().MapPoint(cp);
}
- if (!path_.HasCurrentPoint())
+ if (UNLIKELY(!path_.HasCurrentPoint()))
path_.MoveTo(FloatPoint(cpx, cpy));
path_.AddQuadCurveTo(cp, p1);
@@ -121,20 +138,26 @@ void CanvasPath::bezierCurveTo(double double_cp1x,
float cp2y = base::saturated_cast<float>(double_cp2y);
float x = base::saturated_cast<float>(double_x);
float y = base::saturated_cast<float>(double_y);
- if (!std::isfinite(cp1x) || !std::isfinite(cp1y) || !std::isfinite(cp2x) ||
- !std::isfinite(cp2y) || !std::isfinite(x) || !std::isfinite(y))
+ if (UNLIKELY(!std::isfinite(cp1x) || !std::isfinite(cp1y) ||
+ !std::isfinite(cp2x) || !std::isfinite(cp2y) ||
+ !std::isfinite(x) || !std::isfinite(y)))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kBezierCurveTo, double_cp1x, double_cp1y, double_cp2x,
+ double_cp2y, double_x, double_y);
+ }
FloatPoint p1 = FloatPoint(x, y);
FloatPoint cp1 = FloatPoint(cp1x, cp1y);
FloatPoint cp2 = FloatPoint(cp2x, cp2y);
- if (!IsTransformInvertible()) {
+ if (UNLIKELY(!IsTransformInvertible())) {
p1 = GetTransform().MapPoint(p1);
cp1 = GetTransform().MapPoint(cp1);
cp2 = GetTransform().MapPoint(cp2);
}
- if (!path_.HasCurrentPoint())
+ if (UNLIKELY(!path_.HasCurrentPoint()))
path_.MoveTo(FloatPoint(cp1x, cp1y));
path_.AddBezierCurveTo(cp1, cp2, p1);
@@ -151,28 +174,33 @@ void CanvasPath::arcTo(double double_x1,
float x2 = base::saturated_cast<float>(double_x2);
float y2 = base::saturated_cast<float>(double_y2);
float r = base::saturated_cast<float>(double_r);
- if (!std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(x2) ||
- !std::isfinite(y2) || !std::isfinite(r))
+ if (UNLIKELY(!std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(x2) ||
+ !std::isfinite(y2) || !std::isfinite(r)))
return;
- if (r < 0) {
+ if (UNLIKELY(r < 0)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kIndexSizeError,
"The radius provided (" + String::Number(r) + ") is negative.");
return;
}
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kArcTo, double_x1,
+ double_y1, double_x2, double_y2,
+ double_r);
+ }
FloatPoint p1 = FloatPoint(x1, y1);
FloatPoint p2 = FloatPoint(x2, y2);
- if (!IsTransformInvertible()) {
+ if (UNLIKELY(!IsTransformInvertible())) {
p1 = GetTransform().MapPoint(p1);
p2 = GetTransform().MapPoint(p2);
}
- if (!path_.HasCurrentPoint())
+ if (UNLIKELY(!path_.HasCurrentPoint()))
path_.MoveTo(p1);
- else if (p1 == path_.CurrentPoint() || p1 == p2 || !r)
+ else if (UNLIKELY(p1 == path_.CurrentPoint() || p1 == p2 || !r))
lineTo(x1, y1);
else
path_.AddArcTo(p1, p2, r);
@@ -310,7 +338,7 @@ void DegenerateEllipse(CanvasPath* path,
// arc.
LineToFloatPoint(path, center + rotation_matrix.MapPoint(GetPointOnEllipse(
radius_x, radius_y, start_angle)));
- if ((!radius_x && !radius_y) || start_angle == end_angle)
+ if (UNLIKELY((!radius_x && !radius_y) || start_angle == end_angle))
return;
if (!anticlockwise) {
@@ -351,21 +379,27 @@ void CanvasPath::arc(double double_x,
float radius = base::saturated_cast<float>(double_radius);
float start_angle = base::saturated_cast<float>(double_start_angle);
float end_angle = base::saturated_cast<float>(double_end_angle);
- if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) ||
- !std::isfinite(start_angle) || !std::isfinite(end_angle))
+ if (UNLIKELY(!std::isfinite(x) || !std::isfinite(y) ||
+ !std::isfinite(radius) || !std::isfinite(start_angle) ||
+ !std::isfinite(end_angle)))
return;
- if (radius < 0) {
+ if (UNLIKELY(radius < 0)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kIndexSizeError,
"The radius provided (" + String::Number(radius) + ") is negative.");
return;
}
- if (!IsTransformInvertible())
+ if (UNLIKELY(!IsTransformInvertible()))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kArc, double_x, double_y, double_radius, double_start_angle,
+ double_end_angle, anticlockwise);
+ }
- if (!radius || start_angle == end_angle) {
+ if (UNLIKELY(!radius || start_angle == end_angle)) {
// The arc is empty but we still need to draw the connecting line.
lineTo(x + radius * cosf(start_angle), y + radius * sinf(start_angle));
return;
@@ -392,19 +426,20 @@ void CanvasPath::ellipse(double double_x,
float rotation = base::saturated_cast<float>(double_rotation);
float start_angle = base::saturated_cast<float>(double_start_angle);
float end_angle = base::saturated_cast<float>(double_end_angle);
- if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius_x) ||
- !std::isfinite(radius_y) || !std::isfinite(rotation) ||
- !std::isfinite(start_angle) || !std::isfinite(end_angle))
+ if (UNLIKELY(!std::isfinite(x) || !std::isfinite(y) ||
+ !std::isfinite(radius_x) || !std::isfinite(radius_y) ||
+ !std::isfinite(rotation) || !std::isfinite(start_angle) ||
+ !std::isfinite(end_angle)))
return;
- if (radius_x < 0) {
+ if (UNLIKELY(radius_x < 0)) {
exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
"The major-axis radius provided (" +
String::Number(radius_x) +
") is negative.");
return;
}
- if (radius_y < 0) {
+ if (UNLIKELY(radius_y < 0)) {
exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
"The minor-axis radius provided (" +
String::Number(radius_y) +
@@ -412,13 +447,19 @@ void CanvasPath::ellipse(double double_x,
return;
}
- if (!IsTransformInvertible())
+ if (UNLIKELY(!IsTransformInvertible()))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kEllipse, double_x, double_y, double_radius_x,
+ double_radius_y, double_rotation, double_start_angle, double_end_angle,
+ anticlockwise);
+ }
CanonicalizeAngle(&start_angle, &end_angle);
float adjusted_end_angle =
AdjustEndAngle(start_angle, end_angle, anticlockwise);
- if (!radius_x || !radius_y || start_angle == adjusted_end_angle) {
+ if (UNLIKELY(!radius_x || !radius_y || start_angle == adjusted_end_angle)) {
// The ellipse is empty but we still need to draw the connecting line to
// start point.
DegenerateEllipse(this, x, y, radius_x, radius_y, rotation, start_angle,
@@ -438,12 +479,16 @@ void CanvasPath::rect(double double_x,
float y = base::saturated_cast<float>(double_y);
float width = base::saturated_cast<float>(double_width);
float height = base::saturated_cast<float>(double_height);
- if (!IsTransformInvertible())
+ if (UNLIKELY(!IsTransformInvertible()))
return;
- if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) ||
- !std::isfinite(height))
+ if (UNLIKELY(!std::isfinite(x) || !std::isfinite(y) ||
+ !std::isfinite(width) || !std::isfinite(height)))
return;
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kRect, double_x, double_y, double_width, double_height);
+ }
path_.AddRect(FloatRect(x, y, width, height));
}
@@ -453,101 +498,64 @@ void CanvasPath::roundRect(
double double_y,
double double_width,
double double_height,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<Member<V8UnionDOMPointOrUnrestrictedDouble>>& radii,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const HeapVector<UnrestrictedDoubleOrDOMPoint, 0> radii,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const HeapVector<Member<V8UnionDOMPointInitOrUnrestrictedDouble>>& radii,
ExceptionState& exception_state) {
const int num_radii = radii.size();
- if (num_radii < 1 || num_radii > 4) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
+ if (UNLIKELY(num_radii < 1 || num_radii > 4)) {
+ exception_state.ThrowRangeError(
String::Number(num_radii) +
- " radii provided. Between one and four radii are necessary.");
+ " radii provided. Between one and four radii are necessary.");
}
float x = base::saturated_cast<float>(double_x);
float y = base::saturated_cast<float>(double_y);
float width = base::saturated_cast<float>(double_width);
float height = base::saturated_cast<float>(double_height);
- if (!IsTransformInvertible())
+ if (UNLIKELY(!IsTransformInvertible()))
return;
- if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) ||
- !std::isfinite(height))
+ if (UNLIKELY(!std::isfinite(x) || !std::isfinite(y) ||
+ !std::isfinite(width) || !std::isfinite(height)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
FloatSize r[num_radii];
for (int i = 0; i < num_radii; ++i) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (radii[i]->GetContentType()) {
- case V8UnionDOMPointOrUnrestrictedDouble::ContentType::kDOMPoint: {
- DOMPoint* p = radii[i]->GetAsDOMPoint();
+ case V8UnionDOMPointInitOrUnrestrictedDouble::ContentType::
+ kDOMPointInit: {
+ DOMPointInit* p = radii[i]->GetAsDOMPointInit();
float r_x = base::saturated_cast<float>(p->x());
float r_y = base::saturated_cast<float>(p->y());
if (UNLIKELY(!std::isfinite(r_x)) || UNLIKELY(!std::isfinite(r_y)))
return;
if (UNLIKELY(r_x < 0.0f)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
+ exception_state.ThrowRangeError(
"X-radius value " + String::Number(r_x) + " is negative.");
}
if (UNLIKELY(r_y < 0.0f)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
+ exception_state.ThrowRangeError(
"Y-radius value " + String::Number(r_y) + " is negative.");
}
r[i] = FloatSize(base::saturated_cast<float>(p->x()),
base::saturated_cast<float>(p->y()));
break;
}
- case V8UnionDOMPointOrUnrestrictedDouble::ContentType::
+ case V8UnionDOMPointInitOrUnrestrictedDouble::ContentType::
kUnrestrictedDouble: {
float a =
base::saturated_cast<float>(radii[i]->GetAsUnrestrictedDouble());
if (UNLIKELY(!std::isfinite(a)))
return;
if (UNLIKELY(a < 0.0f)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
- "Radius value " + String::Number(a) + " is negative.");
+ exception_state.ThrowRangeError("Radius value " + String::Number(a) +
+ " is negative.");
}
r[i] = FloatSize(a, a);
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (radii[i].IsUnrestrictedDouble()) {
- float a = base::saturated_cast<float>(radii[i].GetAsUnrestrictedDouble());
- if (UNLIKELY(!std::isfinite(a)))
- return;
- if (UNLIKELY(a < 0.0f)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
- "Radius value " + String::Number(a) + " is negative.");
- }
- r[i] = FloatSize(a, a);
- } else { // This radius is a DOMPoint
- DOMPoint* p = radii[i].GetAsDOMPoint();
- float r_x = base::saturated_cast<float>(p->x());
- float r_y = base::saturated_cast<float>(p->y());
- if (UNLIKELY(!std::isfinite(r_x)) || UNLIKELY(!std::isfinite(r_y)))
- return;
- if (UNLIKELY(r_x < 0.0f)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
- "X-radius value " + String::Number(r_x) + " is negative.");
- }
- if (UNLIKELY(r_y < 0.0f)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kIndexSizeError,
- "Y-radius value " + String::Number(r_y) + " is negative.");
- }
- r[i] = FloatSize(base::saturated_cast<float>(p->x()),
- base::saturated_cast<float>(p->y()));
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
if (UNLIKELY(width == 0) || UNLIKELY(height == 0)) {
@@ -612,4 +620,7 @@ void CanvasPath::roundRect(
path_.MoveTo(FloatPoint(x, y));
}
+void CanvasPath::Trace(Visitor* visitor) const {
+ visitor->Trace(identifiability_study_helper_);
+}
} // namespace blink
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 954e99e601b..cf9d2e68038 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
@@ -30,19 +30,21 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_PATH_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_PATH_H_
-#include "third_party/blink/renderer/bindings/modules/v8/unrestricted_double_or_dom_point.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_dompointinit_unrestricteddouble.h"
+#include "third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/no_alloc_direct_call_host.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
class ExceptionState;
-class V8UnionDOMPointOrUnrestrictedDouble;
-class MODULES_EXPORT CanvasPath : public NoAllocDirectCallHost {
+class MODULES_EXPORT CanvasPath : public GarbageCollectedMixin,
+ public NoAllocDirectCallHost {
DISALLOW_NEW();
public:
@@ -87,35 +89,55 @@ class MODULES_EXPORT CanvasPath : public NoAllocDirectCallHost {
double double_y,
double double_width,
double double_height);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void roundRect(
double double_x,
double double_y,
double double_width,
double double_height,
- const HeapVector<Member<V8UnionDOMPointOrUnrestrictedDouble>>& radii,
+ const HeapVector<Member<V8UnionDOMPointInitOrUnrestrictedDouble>>& radii,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void roundRect(double double_x,
- double double_y,
- double double_width,
- double double_height,
- const HeapVector<UnrestrictedDoubleOrDOMPoint, 0> radii,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- virtual bool IsTransformInvertible() const { return true; }
+
+ bool IsTransformInvertible() const;
+
virtual TransformationMatrix GetTransform() const {
// This will be the identity matrix
return TransformationMatrix();
}
+ IdentifiableToken GetIdentifiableToken() const {
+ return identifiability_study_helper_.GetToken();
+ }
+
+ void Trace(Visitor*) const override;
+
protected:
CanvasPath() { path_.SetIsVolatile(true); }
- CanvasPath(const Path& path) : path_(path) { path_.SetIsVolatile(true); }
+ explicit CanvasPath(const Path& path) : path_(path) {
+ path_.SetIsVolatile(true);
+ }
+ ALWAYS_INLINE void SetIsTransformInvertible(bool val) {
+ is_transform_invertible_ = val;
+ }
Path path_;
+
+ // This mirrors state that is stored in CanvasRenderingContext2DState. We
+ // replicate it here so that IsTransformInvertible() can be a non-virtual
+ // inline-able call. We do not replicate the whole CTM. Therefore
+ // GetTransform() remains virtual, which is okay because it is only called in
+ // code paths that handle non-invertible transforms.
+ bool is_transform_invertible_ = true;
+
+ IdentifiabilityStudyHelper identifiability_study_helper_;
};
+ALWAYS_INLINE bool CanvasPath::IsTransformInvertible() const {
+ // Verify that the cached is_transform_invertible_ remains in sync with the
+ // ground truth state.
+ DCHECK(is_transform_invertible_ == GetTransform().IsInvertible());
+
+ return is_transform_invertible_;
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_PATH_H_
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl
index 004eeb27cbb..96d27a9c7ed 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl
@@ -13,7 +13,7 @@ interface mixin CanvasPath {
[NoAllocDirectCall] void bezierCurveTo(unrestricted double cp1x, unrestricted double cp1y, unrestricted double cp2x, unrestricted double cp2y, unrestricted double x, unrestricted double y);
[NoAllocDirectCall, RaisesException] void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radius);
[NoAllocDirectCall] void rect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
- [RuntimeEnabled=NewCanvas2DAPI, RaisesException] void roundRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h, sequence<(unrestricted double or DOMPoint)> radii);
+ [RuntimeEnabled=NewCanvas2DAPI, RaisesException] void roundRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h, sequence<(unrestricted double or DOMPointInit)> radii);
[NoAllocDirectCall, RaisesException] void arc(unrestricted double x, unrestricted double y, unrestricted double radius, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false);
[NoAllocDirectCall, RaisesException] void ellipse(unrestricted double x, unrestricted double y, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false);
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 6b1438626fd..c06e40dd527 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
@@ -58,9 +58,11 @@ CanvasPattern::CanvasPattern(scoped_refptr<Image> image,
bool origin_clean)
: pattern_(Pattern::CreateImagePattern(std::move(image), repeat)),
origin_clean_(origin_clean) {
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kCreatePattern, image ? image->width() : 0,
- image ? image->height() : 0, repeat);
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kCreatePattern, image ? image->width() : 0,
+ image ? image->height() : 0, repeat);
+ }
}
void CanvasPattern::setTransform(DOMMatrix2DInit* transform,
@@ -71,8 +73,10 @@ void CanvasPattern::setTransform(DOMMatrix2DInit* transform,
if (!m) {
return;
}
- identifiability_study_helper_.MaybeUpdateBuilder(
- m->m11(), m->m12(), m->m21(), m->m22(), m->m41(), m->m42());
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(m->m11(), m->m12(), m->m21(),
+ m->m22(), m->m41(), m->m42());
+ }
pattern_transform_ = m->GetAffineTransform();
}
@@ -81,4 +85,13 @@ IdentifiableToken CanvasPattern::GetIdentifiableToken() const {
return identifiability_study_helper_.GetToken();
}
+void CanvasPattern::SetExecutionContext(ExecutionContext* context) {
+ identifiability_study_helper_.SetExecutionContext(context);
+}
+
+void CanvasPattern::Trace(Visitor* visitor) const {
+ visitor->Trace(identifiability_study_helper_);
+ ScriptWrappable::Trace(visitor);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h
index 6bd134ac011..0e347ce1cfb 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h
@@ -56,6 +56,11 @@ class CanvasPattern final : public ScriptWrappable {
IdentifiableToken GetIdentifiableToken() const;
+ // Sets on internal IdentifiabilityStudyHelper.
+ void SetExecutionContext(ExecutionContext*);
+
+ void Trace(Visitor* visitor) const override;
+
private:
scoped_refptr<Pattern> pattern_;
AffineTransform pattern_transform_;
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 78fe811af2a..fa3db49fabc 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
@@ -40,7 +40,6 @@
#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/modules/v8/rendering_context.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
@@ -80,8 +79,9 @@
namespace blink {
-static const base::TimeDelta kTryRestoreContextInterval =
- base::TimeDelta::FromMilliseconds(500);
+// Try to restore context 4 times in the event that the context is lost. If the
+// context is unable to be restored after 4 attempts, we discard the backing
+// storage of the context and allocate a new one.
static const unsigned kMaxTryRestoreContextAttempts = 4;
// Drawing methods need to use this instead of SkAutoCanvasRestore in case
@@ -121,34 +121,19 @@ CanvasRenderingContext* CanvasRenderingContext2D::Factory::Create(
MakeGarbageCollected<CanvasRenderingContext2D>(
static_cast<HTMLCanvasElement*>(host), attrs);
DCHECK(rendering_context);
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::k2D);
return rendering_context;
}
CanvasRenderingContext2D::CanvasRenderingContext2D(
HTMLCanvasElement* canvas,
const CanvasContextCreationAttributesCore& attrs)
- : CanvasRenderingContext(canvas, attrs),
- context_lost_mode_(kNotLostContext),
- context_restorable_(true),
- try_restore_context_attempt_count_(0),
- dispatch_context_lost_event_timer_(
- canvas->GetDocument().GetTaskRunner(TaskType::kMiscPlatformAPI),
- this,
- &CanvasRenderingContext2D::DispatchContextLostEvent),
- dispatch_context_restored_event_timer_(
- canvas->GetDocument().GetTaskRunner(TaskType::kMiscPlatformAPI),
- this,
- &CanvasRenderingContext2D::DispatchContextRestoredEvent),
- try_restore_context_event_timer_(
- canvas->GetDocument().GetTaskRunner(TaskType::kMiscPlatformAPI),
- this,
- &CanvasRenderingContext2D::TryRestoreContextEvent),
+ : CanvasRenderingContext(canvas, attrs, CanvasRenderingAPI::k2D),
should_prune_local_font_cache_(false),
random_generator_((uint32_t)base::RandUint64()),
bernoulli_distribution_(kRasterMetricProbability),
color_params_(attrs.color_space, attrs.pixel_format, attrs.alpha) {
+ identifiability_study_helper_.SetExecutionContext(
+ canvas->GetTopExecutionContext());
if (canvas->GetDocument().GetSettings() &&
canvas->GetDocument().GetSettings()->GetAntialiasedClips2dCanvasEnabled())
clip_antialiasing_ = kAntiAliased;
@@ -156,21 +141,10 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(
ValidateStateStack();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* CanvasRenderingContext2D::AsV8RenderingContext() {
return MakeGarbageCollected<V8RenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void CanvasRenderingContext2D::SetCanvasGetContextResult(
- RenderingContext& result) {
- result.SetCanvasRenderingContext2D(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
CanvasRenderingContext2D::~CanvasRenderingContext2D() = default;
void CanvasRenderingContext2D::ValidateStateStackWithCanvas(
@@ -220,6 +194,14 @@ bool CanvasRenderingContext2D::isContextLost() const {
return context_lost_mode_ != kNotLostContext;
}
+void CanvasRenderingContext2D::SendContextLostEventIfNeeded() {
+ if (!needs_context_lost_event_)
+ return;
+
+ needs_context_lost_event_ = false;
+ dispatch_context_lost_event_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
+}
+
void CanvasRenderingContext2D::LoseContext(LostContextMode lost_mode) {
if (context_lost_mode_ != kNotLostContext)
return;
@@ -227,7 +209,13 @@ void CanvasRenderingContext2D::LoseContext(LostContextMode lost_mode) {
if (context_lost_mode_ == kSyntheticLostContext && Host()) {
Host()->DiscardResourceProvider();
}
- dispatch_context_lost_event_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
+
+ if (canvas() && canvas()->IsVisible()) {
+ dispatch_context_lost_event_timer_.StartOneShot(base::TimeDelta(),
+ FROM_HERE);
+ } else {
+ needs_context_lost_event_ = true;
+ }
}
void CanvasRenderingContext2D::DidSetSurfaceSize() {
@@ -251,32 +239,12 @@ void CanvasRenderingContext2D::DidSetSurfaceSize() {
void CanvasRenderingContext2D::Trace(Visitor* visitor) const {
visitor->Trace(hit_region_manager_);
- visitor->Trace(dispatch_context_lost_event_timer_);
- visitor->Trace(dispatch_context_restored_event_timer_);
- visitor->Trace(try_restore_context_event_timer_);
visitor->Trace(filter_operations_);
CanvasRenderingContext::Trace(visitor);
BaseRenderingContext2D::Trace(visitor);
SVGResourceClient::Trace(visitor);
}
-void CanvasRenderingContext2D::DispatchContextLostEvent(TimerBase*) {
- if (canvas() && RuntimeEnabledFeatures::NewCanvas2DAPIEnabled()) {
- Event* event = Event::CreateCancelable(event_type_names::kContextlost);
- canvas()->DispatchEvent(*event);
- if (event->defaultPrevented()) {
- context_restorable_ = false;
- }
- }
-
- if (context_restorable_ && (context_lost_mode_ == kRealLostContext ||
- context_lost_mode_ == kSyntheticLostContext)) {
- try_restore_context_attempt_count_ = 0;
- try_restore_context_event_timer_.StartRepeating(kTryRestoreContextInterval,
- FROM_HERE);
- }
-}
-
void CanvasRenderingContext2D::TryRestoreContextEvent(TimerBase* timer) {
if (context_lost_mode_ == kNotLostContext) {
// Canvas was already restored (possibly thanks to a resize), so stop
@@ -303,8 +271,12 @@ void CanvasRenderingContext2D::TryRestoreContextEvent(TimerBase* timer) {
DispatchContextRestoredEvent(nullptr);
}
- if (++try_restore_context_attempt_count_ > kMaxTryRestoreContextAttempts) {
- // final attempt: allocate a brand new image buffer instead of restoring
+ // If it fails to restore the context, TryRestoreContextEvent again.
+ if (++try_restore_context_attempt_count_ < kMaxTryRestoreContextAttempts) {
+ TryRestoreContextEvent(nullptr);
+ } else {
+ // After 4 tries, we start the final attempt, allocate a brand new image
+ // buffer instead of restoring
Host()->DiscardResourceProvider();
try_restore_context_event_timer_.Stop();
if (CanCreateCanvas2dResourceProvider())
@@ -312,17 +284,6 @@ void CanvasRenderingContext2D::TryRestoreContextEvent(TimerBase* timer) {
}
}
-void CanvasRenderingContext2D::DispatchContextRestoredEvent(TimerBase*) {
- if (context_lost_mode_ == kNotLostContext)
- return;
- Reset();
- context_lost_mode_ = kNotLostContext;
- if (RuntimeEnabledFeatures::NewCanvas2DAPIEnabled()) {
- Event* event(Event::Create(event_type_names::kContextrestored));
- canvas()->DispatchEvent(*event);
- }
-}
-
void CanvasRenderingContext2D::WillDrawImage(CanvasImageSource* source) const {
canvas()->WillDrawImageTo2DContext(source);
}
@@ -369,7 +330,7 @@ void CanvasRenderingContext2D::scrollPathIntoView(Path2D* path2d) {
}
void CanvasRenderingContext2D::ScrollPathIntoViewInternal(const Path& path) {
- if (!GetState().IsTransformInvertible() || path.IsEmpty())
+ if (!IsTransformInvertible() || path.IsEmpty())
return;
canvas()->GetDocument().UpdateStyleAndLayout(
@@ -445,17 +406,6 @@ void CanvasRenderingContext2D::clearRect(double x,
}
}
-void CanvasRenderingContext2D::DidDraw(const SkIRect& dirty_rect) {
- if (dirty_rect.isEmpty())
- return;
-
- CanvasRenderingContext::DidDraw(dirty_rect);
-}
-
-bool CanvasRenderingContext2D::StateHasFilter() {
- return GetState().HasFilter(canvas(), canvas()->Size(), this);
-}
-
sk_sp<PaintFilter> CanvasRenderingContext2D::StateGetFilter() {
return GetState().GetFilter(canvas(), canvas()->Size(), this);
}
@@ -470,19 +420,30 @@ void CanvasRenderingContext2D::SnapshotStateForFilter() {
}
cc::PaintCanvas* CanvasRenderingContext2D::GetOrCreatePaintCanvas() {
- if (isContextLost())
+ if (UNLIKELY(isContextLost()))
return nullptr;
- if (canvas()->GetOrCreateCanvas2DLayerBridge())
+ if (LIKELY(canvas()->GetOrCreateCanvas2DLayerBridge()))
return canvas()->GetCanvas2DLayerBridge()->GetPaintCanvas();
return nullptr;
}
cc::PaintCanvas* CanvasRenderingContext2D::GetPaintCanvas() const {
- if (isContextLost() || !canvas()->GetCanvas2DLayerBridge())
+ if (UNLIKELY(isContextLost() || !canvas() ||
+ !canvas()->GetCanvas2DLayerBridge() ||
+ !canvas()->GetCanvas2DLayerBridge()->ResourceProvider()))
return nullptr;
- if (canvas() && canvas()->GetCanvas2DLayerBridge()->ResourceProvider())
- return canvas()->GetCanvas2DLayerBridge()->GetPaintCanvas();
- return nullptr;
+ return canvas()->GetCanvas2DLayerBridge()->GetPaintCanvas();
+}
+
+cc::PaintCanvas* CanvasRenderingContext2D::GetPaintCanvasForDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType draw_type) {
+ if (UNLIKELY(isContextLost() || !canvas() ||
+ !canvas()->GetCanvas2DLayerBridge() ||
+ !canvas()->GetCanvas2DLayerBridge()->ResourceProvider()))
+ return nullptr;
+ CanvasRenderingContext::DidDraw(dirty_rect, draw_type);
+ return canvas()->GetCanvas2DLayerBridge()->GetPaintCanvas();
}
String CanvasRenderingContext2D::font() const {
@@ -529,8 +490,10 @@ void CanvasRenderingContext2D::setFont(const String& new_font) {
// documents.
if (!canvas()->GetDocument().GetFrame())
return;
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kSetFont, IdentifiabilityBenignStringToken(new_font));
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetFont, IdentifiabilityBenignStringToken(new_font));
+ }
base::TimeTicks start_time = base::TimeTicks::Now();
canvas()->GetDocument().UpdateStyleAndLayoutTreeForNode(canvas());
@@ -610,8 +573,7 @@ void CanvasRenderingContext2D::setFont(const String& new_font) {
GetState().SetUnparsedFont(new_font_safe_copy);
if (bernoulli_distribution_(random_generator_)) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
- base::UmaHistogramMicrosecondsTimesUnderTenMilliseconds(
- "Canvas.TextMetrics.SetFont", elapsed);
+ base::UmaHistogramMicrosecondsTimes("Canvas.TextMetrics.SetFont2", elapsed);
}
}
@@ -715,6 +677,11 @@ void CanvasRenderingContext2D::FinalizeFrame() {
canvas()->GetCanvas2DLayerBridge()->FinalizeFrame();
}
+CanvasRenderingContextHost*
+CanvasRenderingContext2D::GetCanvasRenderingContextHost() {
+ return Host();
+}
+
bool CanvasRenderingContext2D::ParseColorOrCurrentColor(
Color& color,
const String& color_string) const {
@@ -810,32 +777,36 @@ void CanvasRenderingContext2D::setDirection(const String& direction_string) {
GetState().SetDirection(direction);
}
-void CanvasRenderingContext2D::setTextLetterSpacing(
- const double letter_spacing) {
+void CanvasRenderingContext2D::setLetterSpacing(const double letter_spacing) {
if (UNLIKELY(!std::isfinite(letter_spacing)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
float letter_spacing_float = clampTo<float>(letter_spacing);
- GetState().SetTextLetterSpacing(letter_spacing_float,
- Host()->GetFontSelector());
+ GetState().SetLetterSpacing(letter_spacing_float, Host()->GetFontSelector());
}
-void CanvasRenderingContext2D::setTextWordSpacing(const double word_spacing) {
+void CanvasRenderingContext2D::setWordSpacing(const double word_spacing) {
if (UNLIKELY(!std::isfinite(word_spacing)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
float word_spacing_float = clampTo<float>(word_spacing);
- GetState().SetTextWordSpacing(word_spacing_float, Host()->GetFontSelector());
+ GetState().SetWordSpacing(word_spacing_float, Host()->GetFontSelector());
}
void CanvasRenderingContext2D::setTextRendering(
const String& text_rendering_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -861,6 +832,8 @@ void CanvasRenderingContext2D::setTextRendering(
void CanvasRenderingContext2D::setFontKerning(
const String& font_kerning_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
FontDescription::Kerning kerning;
@@ -881,6 +854,8 @@ void CanvasRenderingContext2D::setFontKerning(
}
void CanvasRenderingContext2D::setFontStretch(const String& font_stretch) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -915,6 +890,8 @@ void CanvasRenderingContext2D::setFontStretch(const String& font_stretch) {
void CanvasRenderingContext2D::setFontVariantCaps(
const String& font_variant_caps_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
FontDescription::FontVariantCaps variant_caps;
@@ -995,6 +972,8 @@ void CanvasRenderingContext2D::fillFormattedText(
double wrap_width) {
if (!formatted_text)
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -1007,7 +986,8 @@ void CanvasRenderingContext2D::fillFormattedText(
{ c->drawPicture(recording); },
[](const SkIRect& rect) { return false; }, bounds,
CanvasRenderingContext2DState::PaintType::kFillPaintType,
- CanvasRenderingContext2DState::kNoImage);
+ CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kText);
}
void CanvasRenderingContext2D::DrawTextInternal(
@@ -1035,13 +1015,15 @@ void CanvasRenderingContext2D::DrawTextInternal(
if (max_width && (!std::isfinite(*max_width) || *max_width <= 0))
return;
- identifiability_study_helper_.MaybeUpdateBuilder(
- paint_type == CanvasRenderingContext2DState::kFillPaintType
- ? CanvasOps::kFillText
- : CanvasOps::kStrokeText,
- IdentifiabilitySensitiveStringToken(text), x, y,
- max_width ? *max_width : -1);
- identifiability_study_helper_.set_encountered_sensitive_ops();
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ paint_type == CanvasRenderingContext2DState::kFillPaintType
+ ? CanvasOps::kFillText
+ : CanvasOps::kStrokeText,
+ IdentifiabilitySensitiveStringToken(text), x, y,
+ max_width ? *max_width : -1);
+ identifiability_study_helper_.set_encountered_sensitive_ops();
+ }
const Font& font = AccessFont();
const SimpleFontData* font_data = font.PrimaryFont();
@@ -1120,7 +1102,8 @@ void CanvasRenderingContext2D::DrawTextInternal(
},
[](const SkIRect& rect) // overdraw test lambda
{ return false; },
- bounds, paint_type, CanvasRenderingContext2DState::kNoImage);
+ bounds, paint_type, CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kText);
}
const Font& CanvasRenderingContext2D::AccessFont() {
@@ -1142,14 +1125,6 @@ void CanvasRenderingContext2D::SetIsBeingDisplayed(bool displayed) {
canvas()->GetCanvas2DLayerBridge()->SetIsBeingDisplayed(displayed);
}
-bool CanvasRenderingContext2D::IsTransformInvertible() const {
- return GetState().IsTransformInvertible();
-}
-
-TransformationMatrix CanvasRenderingContext2D::GetTransform() const {
- return GetState().GetTransform();
-}
-
cc::Layer* CanvasRenderingContext2D::CcLayer() const {
return IsPaintable() ? canvas()->GetCanvas2DLayerBridge()->Layer() : nullptr;
}
@@ -1159,10 +1134,10 @@ CanvasRenderingContext2D::getContextAttributes() const {
CanvasRenderingContext2DSettings* settings =
CanvasRenderingContext2DSettings::Create();
settings->setAlpha(CreationAttributes().alpha);
- settings->setColorSpace(GetCanvas2DColorParams().GetColorSpaceAsString());
- if (RuntimeEnabledFeatures::CanvasColorManagementEnabled()) {
+ if (RuntimeEnabledFeatures::CanvasColorManagementEnabled())
+ settings->setColorSpace(GetCanvas2DColorParams().GetColorSpaceAsString());
+ if (RuntimeEnabledFeatures::CanvasColorManagementV2Enabled())
settings->setPixelFormat(GetCanvas2DColorParams().GetPixelFormatAsString());
- }
settings->setDesynchronized(Host()->LowLatencyEnabled());
if (RuntimeEnabledFeatures::NewCanvas2DAPIEnabled())
settings->setWillReadFrequently(CreationAttributes().will_read_frequently);
@@ -1175,11 +1150,14 @@ void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) {
void CanvasRenderingContext2D::drawFocusIfNeeded(Path2D* path2d,
Element* element) {
- DrawFocusIfNeededInternal(path2d->GetPath(), element);
+ DrawFocusIfNeededInternal(path2d->GetPath(), element,
+ path2d->GetIdentifiableToken());
}
-void CanvasRenderingContext2D::DrawFocusIfNeededInternal(const Path& path,
- Element* element) {
+void CanvasRenderingContext2D::DrawFocusIfNeededInternal(
+ const Path& path,
+ Element* element,
+ IdentifiableToken path_token) {
if (!FocusRingCallIsValid(path, element))
return;
@@ -1187,6 +1165,10 @@ void CanvasRenderingContext2D::DrawFocusIfNeededInternal(const Path& path,
// element->focused(), because element->focused() isn't updated until after
// focus events fire.
if (element->GetDocument().FocusedElement() == element) {
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kDrawFocusIfNeeded,
+ path_token);
+ }
ScrollPathIntoViewInternal(path);
DrawFocusRing(path, element);
}
@@ -1198,7 +1180,7 @@ void CanvasRenderingContext2D::DrawFocusIfNeededInternal(const Path& path,
bool CanvasRenderingContext2D::FocusRingCallIsValid(const Path& path,
Element* element) {
DCHECK(element);
- if (!GetState().IsTransformInvertible())
+ if (!IsTransformInvertible())
return false;
if (path.IsEmpty())
return false;
@@ -1232,7 +1214,7 @@ void CanvasRenderingContext2D::DrawFocusRing(const Path& path,
if (!ComputeDirtyRect(path.StrokeBoundingRect(stroke_data), &dirty_rect))
return;
- DidDraw(dirty_rect);
+ DidDraw(dirty_rect, CanvasPerformanceMonitor::DrawType::kPath);
}
void CanvasRenderingContext2D::UpdateElementAccessibility(const Path& path,
@@ -1281,7 +1263,7 @@ void CanvasRenderingContext2D::addHitRegion(const HitRegionOptions* options,
cc::PaintCanvas* c = GetOrCreatePaintCanvas();
- if (hit_region_path.IsEmpty() || !c || !GetState().IsTransformInvertible() ||
+ if (hit_region_path.IsEmpty() || !c || !IsTransformInvertible() ||
c->isClipEmpty()) {
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 40abded75ff..cdbb963303a 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
@@ -69,9 +69,6 @@ class HitTestCanvasResult;
class Path2D;
class TextMetrics;
-using CanvasImageSourceUnion =
- CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvasOrVideoFrame;
-
class MODULES_EXPORT CanvasRenderingContext2D final
: public CanvasRenderingContext,
public BaseRenderingContext2D,
@@ -104,11 +101,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
DCHECK(!Host() || !Host()->IsOffscreenCanvas());
return static_cast<HTMLCanvasElement*>(Host());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* AsV8RenderingContext() final;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetCanvasGetContextResult(RenderingContext&) final;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool isContextLost() const override;
@@ -131,8 +124,8 @@ class MODULES_EXPORT CanvasRenderingContext2D final
String direction() const;
void setDirection(const String&);
- void setTextLetterSpacing(const double letter_spacing);
- void setTextWordSpacing(const double word_spacing);
+ void setLetterSpacing(const double letter_spacing);
+ void setWordSpacing(const double word_spacing);
void setTextRendering(const String&);
void setFontKerning(const String&);
@@ -200,11 +193,12 @@ class MODULES_EXPORT CanvasRenderingContext2D final
cc::PaintCanvas* GetOrCreatePaintCanvas() final;
cc::PaintCanvas* GetPaintCanvas() const final;
+ cc::PaintCanvas* GetPaintCanvasForDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType) final;
- void DidDraw(const SkIRect& dirty_rect) final;
scoped_refptr<StaticBitmapImage> GetImage() final;
- bool StateHasFilter() final;
sk_sp<PaintFilter> StateGetFilter() final;
void SnapshotStateForFilter() final;
@@ -212,6 +206,8 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void FinalizeFrame() override;
+ CanvasRenderingContextHost* GetCanvasRenderingContextHost() override;
+
bool IsPaintable() const final {
return canvas() && canvas()->GetCanvas2DLayerBridge();
}
@@ -243,6 +239,12 @@ class MODULES_EXPORT CanvasRenderingContext2D final
return identifiability_study_helper_.encountered_sensitive_ops();
}
+ void SendContextLostEventIfNeeded() override;
+
+ bool IdentifiabilityEncounteredPartiallyDigestedImage() const override {
+ return identifiability_study_helper_.encountered_partially_digested_image();
+ }
+
protected:
// This reports CanvasColorParams to the CanvasRenderingContext interface.
CanvasColorParams CanvasRenderingContextColorParams() const override {
@@ -258,14 +260,11 @@ class MODULES_EXPORT CanvasRenderingContext2D final
int x,
int y) override;
void WillOverwriteCanvas() override;
+ void TryRestoreContextEvent(TimerBase*) override;
private:
friend class CanvasRenderingContext2DAutoRestoreSkCanvas;
- void DispatchContextLostEvent(TimerBase*);
- void DispatchContextRestoredEvent(TimerBase*);
- void TryRestoreContextEvent(TimerBase*);
-
void PruneLocalFontCache(size_t target_size);
void ScrollPathIntoViewInternal(const Path&);
@@ -278,7 +277,10 @@ class MODULES_EXPORT CanvasRenderingContext2D final
const Font& AccessFont();
- void DrawFocusIfNeededInternal(const Path&, Element*);
+ void DrawFocusIfNeededInternal(
+ const Path&,
+ Element*,
+ IdentifiableToken path_hash = IdentifiableToken());
bool FocusRingCallIsValid(const Path&, Element*);
void DrawFocusRing(const Path&, Element*);
void UpdateElementAccessibility(const Path&, Element*);
@@ -287,7 +289,6 @@ class MODULES_EXPORT CanvasRenderingContext2D final
return CanvasRenderingContext::kContext2D;
}
- bool IsRenderingContext2D() const override { return true; }
bool IsComposited() const override;
bool IsAccelerated() const override;
bool IsOriginTopLeft() const override;
@@ -299,22 +300,10 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void SetIsBeingDisplayed(bool) override;
void Stop() final;
- bool IsTransformInvertible() const override;
- TransformationMatrix GetTransform() const override;
-
cc::Layer* CcLayer() const override;
bool IsCanvas2DBufferValid() const override;
Member<HitRegionManager> hit_region_manager_;
- LostContextMode context_lost_mode_;
- bool context_restorable_;
- unsigned try_restore_context_attempt_count_;
- HeapTaskRunnerTimer<CanvasRenderingContext2D>
- dispatch_context_lost_event_timer_;
- HeapTaskRunnerTimer<CanvasRenderingContext2D>
- dispatch_context_restored_event_timer_;
- HeapTaskRunnerTimer<CanvasRenderingContext2D>
- try_restore_context_event_timer_;
FilterOperations filter_operations_;
HashMap<String, FontDescription> fonts_resolved_using_current_style_;
@@ -325,6 +314,10 @@ class MODULES_EXPORT CanvasRenderingContext2D final
std::mt19937 random_generator_;
std::bernoulli_distribution bernoulli_distribution_;
CanvasColorParams color_params_;
+
+ // For privacy reasons we need to delay contextLost events until the page is
+ // visible. In order to do this we will hold on to a bool here
+ bool needs_context_lost_event_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl
index 8e2b35d1ab1..2ca0843d1a2 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl
@@ -45,14 +45,19 @@ typedef (CSSImageValue or
enum CanvasFillRule { "nonzero", "evenodd" };
enum ImageSmoothingQuality {"low", "medium", "high"};
-[Exposed=Window]
+[
+ ActiveScriptWrappable,
+ Exposed=Window
+]
interface CanvasRenderingContext2D {
// back-reference to the canvas
readonly attribute HTMLCanvasElement canvas;
// state
void save(); // push state on state stack
- [NoAllocDirectCall] void restore(); // pop state stack and restore state
+ [NoAllocDirectCall] void restore(); // pop state stack if top state was pushed by save, and restore state
+ [RuntimeEnabled=Canvas2dLayers] void beginLayer(); // push state on state stack and creates bitmap for subsequent draw ops
+ [RuntimeEnabled=Canvas2dLayers] void endLayer(); // pop state stack if top state was pushed by beginLayer, restore state and draw the bitmap
// Clear the canvas and reset the path
[RuntimeEnabled=NewCanvas2DAPI] void reset();
@@ -143,8 +148,10 @@ interface CanvasRenderingContext2D {
// pixel manipulation
[RaisesException] ImageData createImageData(ImageData imagedata);
- [RaisesException] ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh, optional ImageDataSettings imageDataSettings = {});
- [RaisesException] ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh, optional ImageDataSettings imageDataSettings = {});
+ [RaisesException] ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh);
+ [RaisesException, RuntimeEnabled=CanvasColorManagement] ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh, ImageDataSettings imageDataSettings);
+ [RaisesException] ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh);
+ [RaisesException, RuntimeEnabled=CanvasColorManagement] ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh, ImageDataSettings imageDataSettings);
[RaisesException] void putImageData(ImageData imagedata, [EnforceRange] long dx, [EnforceRange] long dy);
[RaisesException] void putImageData(ImageData imagedata, [EnforceRange] long dx, [EnforceRange] long dy, [EnforceRange] long dirtyX, [EnforceRange] long dirtyY, [EnforceRange] long dirtyWidth, [EnforceRange] long dirtyHeight);
@@ -174,9 +181,9 @@ interface CanvasRenderingContext2D {
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString fontKerning; // "auto", "normal", "none" (default: "auto")
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString fontStretch; // "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "normal", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" (default: normal)
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString fontVariantCaps; // "normal", "small-caps", "all-small-caps", "petite-caps", "all-petite-caps", "unicase", "titling-caps" (default: "normal")
- [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double textLetterSpacing; // length in pixel (default: 0)
+ [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double letterSpacing; // length in pixel (default: 0)
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString textRendering; // "auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision" (default: auto)
- [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double textWordSpacing; // length in pixel (default: 0)
+ [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double wordSpacing; // length in pixel (default: 0)
};
CanvasRenderingContext2D includes CanvasPath;
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 74548784ac4..4f08b2afde3 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
@@ -11,9 +11,9 @@
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_float32array_uint16array_uint8clampedarray.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_canvas_gradient_or_canvas_pattern_or_css_color_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_hit_region_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_csscolorvalue_canvasgradient_canvaspattern_string.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_cssimagevalue_htmlcanvaselement_htmlimageelement_htmlvideoelement_imagebitmap_offscreencanvas_svgimageelement_videoframe.h"
#include "third_party/blink/renderer/core/accessibility/ax_context.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context.h"
+#include "ui/accessibility/ax_mode.h"
using testing::Mock;
@@ -75,6 +76,7 @@ void CanvasRenderingContext2DAPITest::SetUp() {
}
void CanvasRenderingContext2DAPITest::TearDown() {
+ PageTestBase::TearDown();
CanvasRenderingContext::GetCanvasPerformanceMonitor().ResetForTesting();
}
@@ -145,7 +147,6 @@ TEST_F(CanvasRenderingContext2DAPITest, SetShadowColor_Clamping) {
String TrySettingStrokeStyle(CanvasRenderingContext2D* ctx,
const String& value) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ctx->setStrokeStyle(
MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>("#666"));
@@ -155,20 +156,9 @@ String TrySettingStrokeStyle(CanvasRenderingContext2D* ctx,
auto* style = ctx->strokeStyle();
EXPECT_TRUE(style->IsString());
return style->GetAsString();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue arg1, arg2, arg3;
- arg1.SetString("#666");
- ctx->setStrokeStyle(arg1);
- arg2.SetString(value);
- ctx->setStrokeStyle(arg2);
- ctx->strokeStyle(arg3);
- EXPECT_TRUE(arg3.IsString());
- return arg3.GetAsString();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
String TrySettingFillStyle(CanvasRenderingContext2D* ctx, const String& value) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ctx->setFillStyle(
MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>("#666"));
@@ -178,16 +168,6 @@ String TrySettingFillStyle(CanvasRenderingContext2D* ctx, const String& value) {
auto* style = ctx->fillStyle();
EXPECT_TRUE(style->IsString());
return style->GetAsString();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue arg1, arg2, arg3;
- arg1.SetString("#666");
- ctx->setFillStyle(arg1);
- arg2.SetString(value);
- ctx->setFillStyle(arg2);
- ctx->fillStyle(arg3);
- EXPECT_TRUE(arg3.IsString());
- return arg3.GetAsString();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
String TrySettingShadowColor(CanvasRenderingContext2D* ctx,
@@ -223,29 +203,15 @@ TEST_F(CanvasRenderingContext2DAPITest, DefaultAttributeValues) {
CreateContext(kNonOpaque);
{
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* style = Context2D()->strokeStyle();
EXPECT_TRUE(style->IsString());
EXPECT_EQ(String("#000000"), style->GetAsString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue value;
- Context2D()->strokeStyle(value);
- EXPECT_TRUE(value.IsString());
- EXPECT_EQ(String("#000000"), value.GetAsString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
{
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* style = Context2D()->fillStyle();
EXPECT_TRUE(style->IsString());
EXPECT_EQ(String("#000000"), style->GetAsString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue value;
- Context2D()->fillStyle(value);
- EXPECT_TRUE(value.IsString());
- EXPECT_EQ(String("#000000"), value.GetAsString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
EXPECT_EQ(String("rgba(0, 0, 0, 0)"), Context2D()->shadowColor());
@@ -281,21 +247,12 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
EXPECT_EQ(100, image_data->width());
EXPECT_EQ(50, image_data->height());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
for (size_t i = 0; i < image_data->data()->GetAsUint8ClampedArray()->length();
++i) {
image_data->data()->GetAsUint8ClampedArray()->Data()[i] = 255;
}
EXPECT_EQ(255, image_data->data()->GetAsUint8ClampedArray()->Data()[32]);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- for (size_t i = 0; i < image_data->data().GetAsUint8ClampedArray()->length();
- ++i) {
- image_data->data().GetAsUint8ClampedArray()->Data()[i] = 255;
- }
-
- EXPECT_EQ(255, image_data->data().GetAsUint8ClampedArray()->Data()[32]);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// createImageData(imageData) should create a new ImageData of the same size
// as 'imageData' but filled with transparent black
@@ -305,13 +262,8 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
EXPECT_FALSE(exception_state.HadException());
EXPECT_EQ(100, same_size_image_data->width());
EXPECT_EQ(50, same_size_image_data->height());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ(0,
same_size_image_data->data()->GetAsUint8ClampedArray()->Data()[32]);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- EXPECT_EQ(0,
- same_size_image_data->data().GetAsUint8ClampedArray()->Data()[32]);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// createImageData(width, height) takes the absolute magnitude of the size
// arguments
@@ -329,17 +281,10 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
Context2D()->createImageData(-10, -20, settings, exception_state);
EXPECT_FALSE(exception_state.HadException());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
EXPECT_EQ(800u, imgdata1->data()->GetAsUint8ClampedArray()->length());
EXPECT_EQ(800u, imgdata2->data()->GetAsUint8ClampedArray()->length());
EXPECT_EQ(800u, imgdata3->data()->GetAsUint8ClampedArray()->length());
EXPECT_EQ(800u, imgdata4->data()->GetAsUint8ClampedArray()->length());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- EXPECT_EQ(800u, imgdata1->data().GetAsUint8ClampedArray()->length());
- EXPECT_EQ(800u, imgdata2->data().GetAsUint8ClampedArray()->length());
- EXPECT_EQ(800u, imgdata3->data().GetAsUint8ClampedArray()->length());
- EXPECT_EQ(800u, imgdata4->data().GetAsUint8ClampedArray()->length());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
TEST_F(CanvasRenderingContext2DAPITest, CreateImageDataTooBig) {
@@ -402,7 +347,7 @@ void ResetCanvasForAccessibilityRectTest(Document& document) {
TEST_F(CanvasRenderingContext2DAPITest, AccessibilityRectTestForAddHitRegion) {
ResetCanvasForAccessibilityRectTest(GetDocument());
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
Element* button_element = GetDocument().getElementById("button");
auto* canvas = To<HTMLCanvasElement>(GetDocument().getElementById("canvas"));
@@ -431,7 +376,7 @@ TEST_F(CanvasRenderingContext2DAPITest, AccessibilityRectTestForAddHitRegion) {
TEST_F(CanvasRenderingContext2DAPITest,
AccessibilityRectTestForDrawFocusIfNeeded) {
ResetCanvasForAccessibilityRectTest(GetDocument());
- AXContext ax_context(GetDocument());
+ AXContext ax_context(GetDocument(), ui::kAXModeComplete);
Element* button_element = GetDocument().getElementById("button");
auto* canvas = To<HTMLCanvasElement>(GetDocument().getElementById("canvas"));
@@ -459,7 +404,8 @@ TEST_F(CanvasRenderingContext2DAPITest,
// participation.
class ActiveSettingsProvider : public IdentifiabilityStudySettingsProvider {
public:
- bool IsActive() const override { return true; }
+ explicit ActiveSettingsProvider(bool enabled) : enabled_(enabled) {}
+ bool IsActive() const override { return enabled_; }
bool IsAnyTypeOrSurfaceBlocked() const override { return false; }
bool IsSurfaceAllowed(IdentifiableSurface surface) const override {
return true;
@@ -467,17 +413,18 @@ class ActiveSettingsProvider : public IdentifiabilityStudySettingsProvider {
bool IsTypeAllowed(IdentifiableSurface::Type type) const override {
return true;
}
- int SampleRate(IdentifiableSurface surface) const override { return 1; }
- int SampleRate(IdentifiableSurface::Type type) const override { return 1; }
+
+ private:
+ const bool enabled_ = true;
};
// An RAII class that opts into study participation using
// ActiveSettingsProvider.
class StudyParticipationRaii {
public:
- StudyParticipationRaii() {
+ explicit StudyParticipationRaii(bool enabled = true) {
IdentifiabilityStudySettings::SetGlobalProvider(
- std::make_unique<ActiveSettingsProvider>());
+ std::make_unique<ActiveSettingsProvider>(enabled));
}
~StudyParticipationRaii() {
IdentifiabilityStudySettings::ResetStateForTesting();
@@ -506,6 +453,7 @@ TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyMaxOperations) {
EXPECT_TRUE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_Font) {
@@ -513,11 +461,27 @@ TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_Font) {
CreateContext(kNonOpaque);
Context2D()->setFont("Arial");
- EXPECT_EQ(INT64_C(4260982106376580867),
+ EXPECT_EQ(INT64_C(-7111871220951205888),
+ Context2D()->IdentifiableTextToken().ToUkmMetricValue());
+
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
+}
+
+TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDisabled) {
+ StudyParticipationRaii study_participation_raii(/*enabled=*/false);
+ constexpr int64_t kTokenBuilderInitialDigest = INT64_C(6544625333304541877);
+
+ CreateContext(kNonOpaque);
+
+ Context2D()->setFont("Arial");
+ EXPECT_EQ(kTokenBuilderInitialDigest,
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_StrokeText) {
@@ -525,11 +489,12 @@ TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_StrokeText) {
CreateContext(kNonOpaque);
Context2D()->strokeText("Sensitive message", 1.0, 1.0);
- EXPECT_EQ(INT64_C(-2943272460643878232),
+ EXPECT_EQ(INT64_C(2232415440872807707),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_TRUE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_FillText) {
@@ -537,11 +502,12 @@ TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_FillText) {
CreateContext(kNonOpaque);
Context2D()->fillText("Sensitive message", 1.0, 1.0);
- EXPECT_EQ(INT64_C(8733208206881150098),
+ EXPECT_EQ(INT64_C(6317349156921019980),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_TRUE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_TextAlign) {
@@ -549,11 +515,12 @@ TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_TextAlign) {
CreateContext(kNonOpaque);
Context2D()->setTextAlign("center");
- EXPECT_EQ(INT64_C(-4778938416456134710),
+ EXPECT_EQ(INT64_C(-1799394612814265049),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest,
@@ -562,11 +529,12 @@ TEST_F(CanvasRenderingContext2DAPITest,
CreateContext(kNonOpaque);
Context2D()->setTextBaseline("top");
- EXPECT_EQ(INT64_C(-3065573128425485855),
+ EXPECT_EQ(INT64_C(-7620161594820691651),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest,
@@ -574,38 +542,30 @@ TEST_F(CanvasRenderingContext2DAPITest,
StudyParticipationRaii study_participation_raii;
CreateContext(kNonOpaque);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* style = MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>("blue");
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue style;
- style.SetString("blue");
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Context2D()->setStrokeStyle(style);
- EXPECT_EQ(INT64_C(2059186787917525779),
+ EXPECT_EQ(INT64_C(-1964835352532316734),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_FillStyle) {
StudyParticipationRaii study_participation_raii;
CreateContext(kNonOpaque);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* style = MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>("blue");
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue style;
- style.SetString("blue");
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Context2D()->setFillStyle(style);
- EXPECT_EQ(INT64_C(-6322980727372024031),
+ EXPECT_EQ(INT64_C(-4860826471555317536),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_Combo) {
@@ -613,25 +573,57 @@ TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_Combo) {
CreateContext(kNonOpaque);
Context2D()->fillText("Sensitive message", 1.0, 1.0);
- EXPECT_EQ(INT64_C(8733208206881150098),
+ EXPECT_EQ(INT64_C(6317349156921019980),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
Context2D()->setFont("Helvetica");
Context2D()->setTextBaseline("bottom");
Context2D()->setTextAlign("right");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* style = MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>("red");
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue style;
- style.SetString("red");
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Context2D()->setFillStyle(style);
Context2D()->fillText("Bye", 4.0, 3.0);
- EXPECT_EQ(INT64_C(2368400155273386771),
+ EXPECT_EQ(INT64_C(5574475585707445774),
Context2D()->IdentifiableTextToken().ToUkmMetricValue());
EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
EXPECT_TRUE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
+}
+
+TEST_F(CanvasRenderingContext2DAPITest,
+ IdentifiabilityStudyDigest_putImageData) {
+ StudyParticipationRaii study_participation_raii;
+ CreateContext(kNonOpaque);
+ NonThrowableExceptionState exception_state;
+
+ ImageData* image_data =
+ Context2D()->createImageData(/*sw=*/1, /*sh=*/1, exception_state);
+ EXPECT_FALSE(exception_state.HadException());
+ Context2D()->putImageData(image_data, /*dx=*/1, /*dy=*/1, exception_state);
+ EXPECT_EQ(INT64_C(2821795876044191773),
+ Context2D()->IdentifiableTextToken().ToUkmMetricValue());
+
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_TRUE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
+}
+
+TEST_F(CanvasRenderingContext2DAPITest, IdentifiabilityStudyDigest_drawImage) {
+ StudyParticipationRaii study_participation_raii;
+ CreateContext(kNonOpaque);
+ NonThrowableExceptionState exception_state;
+
+ // We can use our own canvas as the image source!
+ auto* image_source =
+ MakeGarbageCollected<V8CanvasImageSource>(&CanvasElement());
+ Context2D()->drawImage(/*script_state=*/nullptr, image_source, /*x=*/1,
+ /*y=*/1, exception_state);
+ EXPECT_EQ(INT64_C(-4851825694092845811),
+ Context2D()->IdentifiableTextToken().ToUkmMetricValue());
+
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSkippedOps());
+ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredSensitiveOps());
+ EXPECT_TRUE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_settings.idl b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_settings.idl
index 2d6a9799955..03fa6d678fb 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_settings.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_settings.idl
@@ -6,8 +6,8 @@
dictionary CanvasRenderingContext2DSettings {
boolean alpha = true;
boolean desynchronized = false;
- PredefinedColorSpace colorSpace = "srgb";
- [RuntimeEnabled=CanvasColorManagement] CanvasPixelFormat pixelFormat = "uint8";
+ [RuntimeEnabled=CanvasColorManagement] PredefinedColorSpace colorSpace = "srgb";
+ [RuntimeEnabled=CanvasColorManagementV2] CanvasPixelFormat pixelFormat = "uint8";
[RuntimeEnabled=NewCanvas2DAPI] boolean willReadFrequently = false;
};
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 a86ef1faaf3..4d4fb443500 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
@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/style_builder.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
-#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/css/scoped_css_value.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
@@ -54,7 +53,7 @@ CanvasRenderingContext2DState::CanvasRenderingContext2DState()
fill_style_dirty_(true),
stroke_style_dirty_(true),
line_dash_dirty_(false),
- image_smoothing_quality_(kLow_SkFilterQuality) {
+ image_smoothing_quality_(cc::PaintFlags::FilterQuality::kLow) {
fill_flags_.setStyle(PaintFlags::kFill_Style);
fill_flags_.setAntiAlias(true);
image_flags_.setStyle(PaintFlags::kFill_Style);
@@ -70,7 +69,8 @@ CanvasRenderingContext2DState::CanvasRenderingContext2DState()
CanvasRenderingContext2DState::CanvasRenderingContext2DState(
const CanvasRenderingContext2DState& other,
- ClipListCopyMode mode)
+ ClipListCopyMode mode,
+ SaveType save_type)
: unparsed_stroke_color_(other.unparsed_stroke_color_),
unparsed_fill_color_(other.unparsed_fill_color_),
stroke_style_(other.stroke_style_),
@@ -117,7 +117,8 @@ CanvasRenderingContext2DState::CanvasRenderingContext2DState(
stroke_style_dirty_(other.stroke_style_dirty_),
line_dash_dirty_(other.line_dash_dirty_),
image_smoothing_enabled_(other.image_smoothing_enabled_),
- image_smoothing_quality_(other.image_smoothing_quality_) {
+ image_smoothing_quality_(other.image_smoothing_quality_),
+ save_type_(save_type) {
if (mode == kCopyClipList) {
clip_list_ = other.clip_list_;
}
@@ -415,45 +416,33 @@ sk_sp<PaintFilter> CanvasRenderingContext2DState::GetFilter(
if (canvas_filter_) {
operations = canvas_filter_->Operations();
} else {
- // StyleResolverState cannot be used in frame-less documents.
- if (!style_resolution_host->GetDocument().GetFrame())
+ Document& document = style_resolution_host->GetDocument();
+
+ // StyleResolver cannot be used in frame-less documents.
+ if (!document.GetFrame())
return nullptr;
// Update the filter value to the proper base URL if needed.
if (css_filter_value_->MayContainUrl()) {
- style_resolution_host->GetDocument().UpdateStyleAndLayout(
- DocumentUpdateReason::kCanvas);
- css_filter_value_->ReResolveUrl(style_resolution_host->GetDocument());
+ document.UpdateStyleAndLayout(DocumentUpdateReason::kCanvas);
+ css_filter_value_->ReResolveUrl(document);
}
- scoped_refptr<ComputedStyle> filter_style =
- style_resolution_host->GetDocument()
- .GetStyleResolver()
- .CreateComputedStyle();
+ const Font* font = &font_for_filter_;
+
// Must set font in case the filter uses any font-relative units (em, ex)
// If font_for_filter_ was never set (ie frame-less documents) use base font
- if (LIKELY(font_for_filter_.GetFontSelector())) {
- filter_style->SetFont(font_for_filter_);
- } else {
- const ComputedStyle* computed_style =
- style_resolution_host->GetDocument().GetComputedStyle();
- if (computed_style) {
- filter_style->SetFont(computed_style->GetFont());
+ if (UNLIKELY(!font_for_filter_.GetFontSelector())) {
+ if (const ComputedStyle* computed_style = document.GetComputedStyle()) {
+ font = &computed_style->GetFont();
} else {
return nullptr;
}
}
- StyleResolverState resolver_state(style_resolution_host->GetDocument(),
- *style_resolution_host,
- StyleRequest(filter_style.get()));
- resolver_state.SetStyle(filter_style);
-
- StyleBuilder::ApplyProperty(
- GetCSSPropertyFilter(), resolver_state,
- ScopedCSSValue(*css_filter_value_,
- &style_resolution_host->GetDocument()));
- resolver_state.LoadPendingResources();
-
- operations = filter_style->Filter();
+
+ DCHECK(font);
+
+ operations = document.GetStyleResolver().ComputeFilterOperations(
+ style_resolution_host, *font, *css_filter_value_);
}
// We can't reuse m_fillFlags and m_strokeFlags for the filter, since these
@@ -488,23 +477,6 @@ sk_sp<PaintFilter> CanvasRenderingContext2DState::GetFilter(
return resolved_filter_;
}
-bool CanvasRenderingContext2DState::HasFilterForOffscreenCanvas(
- IntSize canvas_size,
- BaseRenderingContext2D* context) {
- // Checking for a non-null m_filterValue isn't sufficient, since this value
- // might refer to a non-existent filter.
- return !!GetFilterForOffscreenCanvas(canvas_size, context);
-}
-
-bool CanvasRenderingContext2DState::HasFilter(
- Element* style_resolution_host,
- IntSize canvas_size,
- CanvasRenderingContext2D* context) {
- // Checking for a non-null m_filterValue isn't sufficient, since this value
- // might refer to a non-existent filter.
- return !!GetFilter(style_resolution_host, canvas_size, context);
-}
-
void CanvasRenderingContext2DState::ClearResolvedFilter() {
resolved_filter_.reset();
filter_state_ = (canvas_filter_ || css_filter_value_)
@@ -633,11 +605,11 @@ bool CanvasRenderingContext2DState::ImageSmoothingEnabled() const {
void CanvasRenderingContext2DState::SetImageSmoothingQuality(
const String& quality_string) {
if (quality_string == "low") {
- image_smoothing_quality_ = kLow_SkFilterQuality;
+ image_smoothing_quality_ = cc::PaintFlags::FilterQuality::kLow;
} else if (quality_string == "medium") {
- image_smoothing_quality_ = kMedium_SkFilterQuality;
+ image_smoothing_quality_ = cc::PaintFlags::FilterQuality::kMedium;
} else if (quality_string == "high") {
- image_smoothing_quality_ = kHigh_SkFilterQuality;
+ image_smoothing_quality_ = cc::PaintFlags::FilterQuality::kHigh;
} else {
return;
}
@@ -646,11 +618,11 @@ void CanvasRenderingContext2DState::SetImageSmoothingQuality(
String CanvasRenderingContext2DState::ImageSmoothingQuality() const {
switch (image_smoothing_quality_) {
- case kLow_SkFilterQuality:
+ case cc::PaintFlags::FilterQuality::kLow:
return "low";
- case kMedium_SkFilterQuality:
+ case cc::PaintFlags::FilterQuality::kMedium:
return "medium";
- case kHigh_SkFilterQuality:
+ case cc::PaintFlags::FilterQuality::kHigh:
return "high";
default:
NOTREACHED();
@@ -660,24 +632,19 @@ String CanvasRenderingContext2DState::ImageSmoothingQuality() const {
void CanvasRenderingContext2DState::UpdateFilterQuality() const {
if (!image_smoothing_enabled_) {
- UpdateFilterQualityWithSkFilterQuality(kNone_SkFilterQuality);
+ UpdateFilterQuality(cc::PaintFlags::FilterQuality::kNone);
} else {
- UpdateFilterQualityWithSkFilterQuality(image_smoothing_quality_);
+ UpdateFilterQuality(image_smoothing_quality_);
}
}
-void CanvasRenderingContext2DState::UpdateFilterQualityWithSkFilterQuality(
- const SkFilterQuality& filter_quality) const {
+void CanvasRenderingContext2DState::UpdateFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) const {
stroke_flags_.setFilterQuality(filter_quality);
fill_flags_.setFilterQuality(filter_quality);
image_flags_.setFilterQuality(filter_quality);
}
-bool CanvasRenderingContext2DState::ShouldDrawShadows() const {
- return AlphaChannel(shadow_color_) &&
- (shadow_blur_ || !shadow_offset_.IsZero());
-}
-
const PaintFlags* CanvasRenderingContext2DState::GetFlags(
PaintType paint_type,
ShadowMode shadow_mode,
@@ -750,9 +717,8 @@ bool CanvasRenderingContext2DState::PatternIsAccelerated(
return Style(paint_type)->GetCanvasPattern()->GetPattern()->IsTextureBacked();
}
-void CanvasRenderingContext2DState::SetTextLetterSpacing(
- float letter_spacing,
- FontSelector* selector) {
+void CanvasRenderingContext2DState::SetLetterSpacing(float letter_spacing,
+ FontSelector* selector) {
DCHECK(realized_font_);
FontDescription font_description(GetFontDescription());
font_description.SetLetterSpacing(letter_spacing);
@@ -760,8 +726,8 @@ void CanvasRenderingContext2DState::SetTextLetterSpacing(
SetFont(font_description, selector);
}
-void CanvasRenderingContext2DState::SetTextWordSpacing(float word_spacing,
- FontSelector* selector) {
+void CanvasRenderingContext2DState::SetWordSpacing(float word_spacing,
+ FontSelector* selector) {
DCHECK(realized_font_);
FontDescription font_description(GetFontDescription());
font_description.SetWordSpacing(word_spacing);
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 993b494f32e..7c12c4069d4 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
@@ -6,9 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_RENDERING_CONTEXT_2D_STATE_H_
#include "base/macros.h"
+#include "cc/paint/paint_flags.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_selector_client.h"
+#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_filter.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -36,10 +38,15 @@ class CanvasRenderingContext2DState final
public FontSelectorClient {
public:
enum ClipListCopyMode { kCopyClipList, kDontCopyClipList };
+ // SaveType indicates whether the state was pushed to the state stack by Save
+ // or by BeginLayer. The first state on the state stack, which is created in
+ // the canvas constructor and not by Save or BeginLayer, has SaveType kInitial.
+ enum class SaveType { kSaveRestore, kBeginEndLayer, kInitial };
CanvasRenderingContext2DState();
CanvasRenderingContext2DState(const CanvasRenderingContext2DState&,
- ClipListCopyMode);
+ ClipListCopyMode,
+ SaveType);
~CanvasRenderingContext2DState() override;
void Trace(Visitor*) const override;
@@ -99,12 +106,12 @@ class CanvasRenderingContext2DState final
CanvasRenderingContext2D*);
sk_sp<PaintFilter> GetFilterForOffscreenCanvas(IntSize canvas_size,
BaseRenderingContext2D*);
- bool HasFilterForOffscreenCanvas(IntSize canvas_size,
- BaseRenderingContext2D*);
- bool HasFilter(Element*, IntSize canvas_size, CanvasRenderingContext2D*);
ALWAYS_INLINE bool IsFilterUnresolved() const {
return filter_state_ == FilterState::kUnresolved;
}
+ ALWAYS_INLINE bool IsFilterResolved() const {
+ return filter_state_ == FilterState::kResolved;
+ }
void ClearResolvedFilter();
void ValidateFilterState() const;
@@ -137,11 +144,11 @@ class CanvasRenderingContext2DState final
void SetTextBaseline(TextBaseline baseline) { text_baseline_ = baseline; }
TextBaseline GetTextBaseline() const { return text_baseline_; }
- void SetTextLetterSpacing(float letter_space, FontSelector* selector);
- float GetTextLetterSpacing() const { return letter_spacing_; }
+ void SetLetterSpacing(float letter_space, FontSelector* selector);
+ float GetLetterSpacing() const { return letter_spacing_; }
- void SetTextWordSpacing(float word_space, FontSelector* selector);
- float GetTextWordSpacing() const { return word_spacing_; }
+ void SetWordSpacing(float word_space, FontSelector* selector);
+ float GetWordSpacing() const { return word_spacing_; }
void SetTextRendering(TextRenderingMode text_rendering,
FontSelector* selector);
@@ -223,12 +230,20 @@ class CanvasRenderingContext2DState final
// Opaque.
const PaintFlags* GetFlags(PaintType, ShadowMode, ImageType = kNoImage) const;
+ SaveType GetSaveType() const { return save_type_; }
+
+ void setRestoreToCount(absl::optional<int> count) {
+ restore_to_count_ = count;
+ }
+
+ absl::optional<int> getRestoreToCount() { return restore_to_count_; }
+
private:
void UpdateLineDash() const;
void UpdateStrokeStyle() const;
void UpdateFillStyle() const;
void UpdateFilterQuality() const;
- void UpdateFilterQualityWithSkFilterQuality(const SkFilterQuality&) const;
+ void UpdateFilterQuality(cc::PaintFlags::FilterQuality) const;
void ShadowParameterChanged();
sk_sp<SkDrawLooper>& EmptyDrawLooper() const;
sk_sp<SkDrawLooper>& ShadowOnlyDrawLooper() const;
@@ -296,13 +311,24 @@ class CanvasRenderingContext2DState final
mutable bool line_dash_dirty_ : 1;
bool image_smoothing_enabled_;
- SkFilterQuality image_smoothing_quality_;
+ cc::PaintFlags::FilterQuality image_smoothing_quality_;
ClipList clip_list_;
+ const SaveType save_type_ = SaveType::kInitial;
+
DISALLOW_COPY_AND_ASSIGN(CanvasRenderingContext2DState);
+
+ // Some endlayer calls need to restore to a specific save count.
+ // If no such restore is needed, restore_to_count_ is set to nullopt.
+ absl::optional<int> restore_to_count_ = absl::nullopt;
};
+ALWAYS_INLINE bool CanvasRenderingContext2DState::ShouldDrawShadows() const {
+ return AlphaChannel(shadow_color_) &&
+ (shadow_blur_ || !shadow_offset_.IsZero());
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CANVAS_RENDERING_CONTEXT_2D_STATE_H_
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 0df3d223687..67bfce918ea 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
@@ -18,7 +18,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_float32array_uint16array_uint8clampedarray.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_canvas_gradient_or_canvas_pattern_or_css_color_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_csscolorvalue_canvasgradient_canvaspattern_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_cssimagevalue_htmlcanvaselement_htmlimageelement_htmlvideoelement_imagebitmap_offscreencanvas_svgimageelement_videoframe.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -69,7 +68,8 @@ class FakeImageSource : public CanvasImageSource {
FakeImageSource(IntSize, BitmapOpacity);
scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) override;
+ const FloatSize&,
+ const AlphaDisposition) override;
bool WouldTaintOrigin() const override { return false; }
FloatSize ElementSize(const FloatSize&,
@@ -98,7 +98,11 @@ FakeImageSource::FakeImageSource(IntSize size, BitmapOpacity opacity)
scoped_refptr<Image> FakeImageSource::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize&) {
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) {
+ // Only cover premultiply alpha cases.
+ DCHECK_EQ(alpha_disposition, kPremultiplyAlpha);
+
if (status)
*status = kNormalSourceImageStatus;
return image_;
@@ -175,15 +179,10 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
visitor->Trace(alpha_gradient_);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>
opaque_gradient_;
Member<V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>
alpha_gradient_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue opaque_gradient_;
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue alpha_gradient_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
// TODO(Oilpan): avoid tedious part-object wrapper by supporting on-heap
@@ -198,7 +197,6 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
FakeImageSource alpha_bitmap_;
scoped_refptr<viz::TestContextProvider> test_context_provider_;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>&
OpaqueGradient() {
return wrap_gradients_->opaque_gradient_;
@@ -207,14 +205,6 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
AlphaGradient() {
return wrap_gradients_->alpha_gradient_;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& OpaqueGradient() {
- return wrap_gradients_->opaque_gradient_;
- }
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue& AlphaGradient() {
- return wrap_gradients_->alpha_gradient_;
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
CanvasRenderingContext2DTest::CanvasRenderingContext2DTest()
@@ -264,13 +254,9 @@ void CanvasRenderingContext2DTest::SetUp() {
EXPECT_FALSE(exception_state.HadException());
opaque_gradient->addColorStop(1, String("blue"), exception_state);
EXPECT_FALSE(exception_state.HadException());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
OpaqueGradient() = MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>(
opaque_gradient);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- OpaqueGradient().SetCanvasGradient(opaque_gradient);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* alpha_gradient =
MakeGarbageCollected<CanvasGradient>(FloatPoint(0, 0), FloatPoint(10, 0));
@@ -279,14 +265,9 @@ void CanvasRenderingContext2DTest::SetUp() {
alpha_gradient->addColorStop(1, String("rgba(0, 0, 255, 0.5)"),
exception_state);
EXPECT_FALSE(exception_state.HadException());
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue wrapped_alpha_gradient;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
AlphaGradient() = MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>(
alpha_gradient);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- AlphaGradient().SetCanvasGradient(alpha_gradient);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
global_memory_cache_ =
ReplaceMemoryCacheForTesting(MakeGarbageCollected<MemoryCache>(
@@ -352,7 +333,7 @@ class FakeCanvasResourceProvider : public CanvasResourceProvider {
RasterModeHint hint)
: CanvasResourceProvider(CanvasResourceProvider::kBitmap,
size,
- kLow_SkFilterQuality,
+ cc::PaintFlags::FilterQuality::kLow,
params,
/*is_origin_top_left=*/false,
nullptr,
@@ -636,13 +617,8 @@ TEST_F(CanvasRenderingContext2DTest, ImageResourceLifetime) {
CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(
canvas->GetCanvasRenderingContext("2d", attributes));
DummyExceptionStateForTesting exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* image_source =
MakeGarbageCollected<V8CanvasImageSource>(image_bitmap_derived);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasImageSourceUnion image_source;
- image_source.SetImageBitmap(image_bitmap_derived);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
context->drawImage(GetScriptState(), image_source, 0, 0, exception_state);
}
@@ -822,25 +798,14 @@ static void TestDrawSingleHighBitDepthPNGOnCanvas(
context->clearRect(0, 0, 2, 2);
NonThrowableExceptionState exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* image_union = MakeGarbageCollected<V8CanvasImageSource>(image_element);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasImageSourceUnion image_union;
- image_union.SetHTMLImageElement(image_element);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
context->drawImage(script_state, image_union, 0, 0, exception_state);
ImageData* image_data =
context->getImageData(0, 0, 2, 2, color_setting, exception_state);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageDataArray* data_array = image_data->data();
ASSERT_TRUE(data_array->IsFloat32Array());
DOMArrayBufferView* buffer_view = data_array->GetAsFloat32Array().Get();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ImageDataArray data_array = image_data->data();
- ASSERT_TRUE(data_array.IsFloat32Array());
- DOMArrayBufferView* buffer_view = data_array.GetAsFloat32Array().Get();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ASSERT_EQ(16u, buffer_view->byteLength() / buffer_view->TypeSize());
float* actual_pixels = static_cast<float*>(buffer_view->BaseAddress());
@@ -996,7 +961,7 @@ void TestPutImageDataOnCanvasWithColorSpaceSettings(
EXPECT_EQ(data_length, data_f32->length());
ImageData* image_data = nullptr;
- int num_pixels = data_length / 4;
+ size_t num_pixels = data_length / 4;
// At most four bytes are needed for Float32 output per color component.
std::unique_ptr<uint8_t[]> pixels_converted_manually(
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 7f382a00769..c9d6b59aa7a 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
@@ -39,6 +39,8 @@ SkPath ClipList::IntersectPathWithClip(const SkPath& path) const {
ClipList::ClipOp::ClipOp() : anti_aliasing_mode_(kAntiAliased) {}
-ClipList::ClipOp::ClipOp(const ClipOp& other) = default;
+ClipList::ClipOp::ClipOp(const ClipOp&) = default;
+
+ClipList::ClipOp& ClipList::ClipOp::operator=(const ClipOp&) = default;
} // namespace blink
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 630cf97871c..343157b2049 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
@@ -36,6 +36,7 @@ class ClipList {
ClipOp();
ClipOp(const ClipOp&);
+ ClipOp& operator=(const ClipOp&);
};
// Number of clip ops that can be stored in a ClipList without resorting to
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 a9b0a45c73e..c67cb995acb 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
@@ -90,13 +90,15 @@ void HitRegionManager::RemoveAllHitRegions() {
}
HitRegion* HitRegionManager::GetHitRegionById(const String& id) const {
- return hit_region_id_map_.at(id);
+ // TODO(https://crbug.com/1236734) Refactor call to deprecated method.
+ return hit_region_id_map_.DeprecatedAtOrEmptyValue(id);
}
HitRegion* HitRegionManager::GetHitRegionByControl(
const Element* control) const {
+ // TODO(https://crbug.com/1236734) Refactor call to deprecated method.
if (control)
- return hit_region_control_map_.at(control);
+ return hit_region_control_map_.DeprecatedAtOrEmptyValue(control);
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.cc
index 480d3eb6c4b..75a930592c0 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.cc
@@ -11,4 +11,8 @@ namespace blink {
// IdentifiabilityStudyHelper::ScopedMaxOperationsSetter.
/*static*/ int IdentifiabilityStudyHelper::max_operations_ = 1 << 20;
+void IdentifiabilityStudyHelper::Trace(Visitor* visitor) const {
+ visitor->Trace(execution_context_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.h
index c45827a2850..ca03d57c795 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.h
@@ -10,6 +10,7 @@
#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
@@ -28,18 +29,66 @@ namespace blink {
// **Don't renumber after the privacy budget study has started to ensure
// consistency.**
enum class CanvasOps {
+ // CanvasPath operations.
+ kClosePath = 0,
+ kMoveTo,
+ kLineTo,
+ kQuadradicCurveTo,
+ kBezierCurveTo,
+ kArcTo,
+ kArc,
+ kEllipse,
+ kRect,
+ // Path2D operations.
+ kAddPath,
// BaseRenderingContext2D methods.
kSetStrokeStyle,
kSetFillStyle,
+ kSetLineWidth,
+ kSetLineCap,
+ kSetLineJoin,
+ kSetMiterLimit,
+ kSetLineDash,
+ kSetLineDashOffset,
+ kSetShadowOffsetX,
+ kSetShadowOffsetY,
+ kSetShadowBlur,
+ kSetShadowColor,
+ kSetGlobalAlpha,
+ kSetGlobalCompositeOpertion,
+ kSetFilter,
+ kSave,
+ kRestore,
+ kScale,
+ kRotate,
+ kTranslate,
+ kTransform,
+ kResetTransform,
+ kBeginPath,
+ kFill,
+ kFill__Path,
+ kStroke,
+ kStroke__Path,
+ kClip,
+ kClip__Path,
+ kClearRect,
+ kFillRect,
+ kStrokeRect,
+ kDrawImage,
kCreateLinearGradient,
kCreateRadialGradient,
kCreatePattern,
+ kPutImageData,
+ kSetImageSmoothingEnabled,
+ kSetImageSmoothingQuality,
kSetTextAlign,
kSetTextBaseline,
+ kReset,
// CanvasRenderingContext2D / OffscreenCanvasRenderingContext2D methods.
kSetFont,
kFillText,
kStrokeText,
+ kDrawFocusIfNeeded, // CanvasRenderingContext2D only.
// CanvasGradient methods.
kAddColorStop,
};
@@ -47,30 +96,62 @@ enum class CanvasOps {
// A helper class to simplify maintaining the current text digest for the canvas
// context. An operation count is also maintained to limit the performance
// impact of the study.
-class IdentifiabilityStudyHelper {
+class IdentifiabilityStudyHelper final {
+ DISALLOW_NEW();
+
public:
- template <typename... Ts>
- void MaybeUpdateBuilder(Ts... tokens) {
- if (!IdentifiabilityStudySettings::Get()->IsTypeAllowed(
- blink::IdentifiableSurface::Type::kCanvasReadback)) {
- return;
- }
- if (operation_count_ >= max_operations_) {
+ // UpdateBuilder() should be called iff ShouldUpdateBuilder() is true, to
+ // avoid unnecessary copies of parameters and hashing when GetToken() won't be
+ // called.
+ bool ShouldUpdateBuilder() {
+ if (!is_canvas_type_allowed_)
+ return false;
+ if (!execution_context_ ||
+ execution_context_->IsInRequestAnimationFrame() ||
+ operation_count_ >= max_operations_) {
encountered_skipped_ops_ = true;
- return;
+ return false;
}
+ return true;
+ }
+
+ // Do *not* call this method if ShouldUpdateBuilder() is false -- updates
+ // the internal digest based on the series of digestable parameters.
+ template <typename... Ts>
+ void UpdateBuilder(Ts... tokens) {
AddTokens(tokens...);
operation_count_++;
}
+ // Returns an IdentifiableToken representing the internal computed digest.
IdentifiableToken GetToken() const { return builder_.GetToken(); }
- bool encountered_skipped_ops() const { return encountered_skipped_ops_; }
+ bool encountered_skipped_ops() const WARN_UNUSED_RESULT {
+ return encountered_skipped_ops_;
+ }
+
+ bool encountered_sensitive_ops() const WARN_UNUSED_RESULT {
+ return encountered_sensitive_ops_;
+ }
+
+ bool encountered_partially_digested_image() const WARN_UNUSED_RESULT {
+ return encountered_partially_digested_image_;
+ }
- bool encountered_sensitive_ops() const { return encountered_sensitive_ops_; }
+ void set_encountered_skipped_ops() { encountered_skipped_ops_ = true; }
void set_encountered_sensitive_ops() { encountered_sensitive_ops_ = true; }
+ void set_encountered_partially_digested_image() {
+ encountered_partially_digested_image_ = true;
+ }
+
+ void SetExecutionContext(ExecutionContext* context) {
+ execution_context_ = context;
+ }
+
+ ExecutionContext* execution_context() const { return execution_context_; }
+
// For testing, allows scoped changing the max number of operations for all
// IdentifiabilityStudyHelper instances.
class ScopedMaxOperationsSetter {
@@ -87,6 +168,8 @@ class IdentifiabilityStudyHelper {
const int old_max_operations_;
};
+ void Trace(Visitor* visitor) const;
+
private:
// Note that primitives are implicitly converted to IdentifiableTokens
template <typename... Ts>
@@ -96,6 +179,12 @@ class IdentifiabilityStudyHelper {
}
void AddTokens() {}
+ const bool is_canvas_type_allowed_ =
+ IdentifiabilityStudySettings::Get()->IsTypeAllowed(
+ blink::IdentifiableSurface::Type::kCanvasReadback);
+
+ Member<ExecutionContext> execution_context_;
+
static MODULES_EXPORT int max_operations_;
IdentifiableTokenBuilder builder_;
@@ -109,6 +198,11 @@ class IdentifiabilityStudyHelper {
//
// This must be set manually by calling set_encountered_sensitive_ops().
bool encountered_sensitive_ops_ = false;
+
+ // If true, at least one op was partially-digested -- for instance, images
+ // drawn to the canvas have their width, height, etc. digested, but not the
+ // image contents, for performance and complexity reasons.
+ bool encountered_partially_digested_image_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.cc
new file mode 100644
index 00000000000..42065a43350
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.cc
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h"
+
+namespace blink {
+
+void Path2D::Trace(Visitor* visitor) const {
+ visitor->Trace(identifiability_study_helper_);
+ ScriptWrappable::Trace(visitor);
+ CanvasPath::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h
index 84895074ec3..aa38648fa85 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h
@@ -29,12 +29,13 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_PATH_2D_H_
#include "base/macros.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_2d_init.h"
-#include "third_party/blink/renderer/bindings/modules/v8/path_2d_or_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_path2d_string.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
#include "third_party/blink/renderer/core/svg/svg_path_utilities.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h"
+#include "third_party/blink/renderer/modules/canvas/canvas2d/identifiability_study_helper.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"
@@ -47,32 +48,23 @@ class MODULES_EXPORT Path2D final : public ScriptWrappable, public CanvasPath {
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Path2D* Create(const V8UnionPath2DOrString* path) {
+ static Path2D* Create(ExecutionContext* context,
+ const V8UnionPath2DOrString* path) {
DCHECK(path);
switch (path->GetContentType()) {
case V8UnionPath2DOrString::ContentType::kPath2D:
- return MakeGarbageCollected<Path2D>(path->GetAsPath2D());
+ return MakeGarbageCollected<Path2D>(context, path->GetAsPath2D());
case V8UnionPath2DOrString::ContentType::kString:
- return MakeGarbageCollected<Path2D>(path->GetAsString());
+ return MakeGarbageCollected<Path2D>(context, path->GetAsString());
}
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Path2D* Create(Path2DOrString pathorstring) {
- DCHECK(!pathorstring.IsNull());
- if (pathorstring.IsPath2D())
- return MakeGarbageCollected<Path2D>(pathorstring.GetAsPath2D());
- if (pathorstring.IsString())
- return MakeGarbageCollected<Path2D>(pathorstring.GetAsString());
- NOTREACHED();
- return nullptr;
+ static Path2D* Create(ExecutionContext* context) {
+ return MakeGarbageCollected<Path2D>(context);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static Path2D* Create() { return MakeGarbageCollected<Path2D>(); }
- static Path2D* Create(const Path& path) {
- return MakeGarbageCollected<Path2D>(path);
+ static Path2D* Create(ExecutionContext* context, const Path& path) {
+ return MakeGarbageCollected<Path2D>(context, path);
}
const Path& GetPath() const { return path_; }
@@ -88,12 +80,26 @@ class MODULES_EXPORT Path2D final : public ScriptWrappable, public CanvasPath {
!std::isfinite(matrix->m42()))
return;
path_.AddPath(path->GetPath(), matrix->GetAffineTransform());
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(CanvasOps::kAddPath,
+ path->GetIdentifiableToken());
+ }
}
- Path2D() : CanvasPath() {}
- Path2D(const Path& path) : CanvasPath(path) {}
- Path2D(Path2D* path) : CanvasPath(path->GetPath()) {}
- Path2D(const String& path_data) : CanvasPath() {
+ void Trace(Visitor*) const override;
+
+ explicit Path2D(ExecutionContext* context) {
+ identifiability_study_helper_.SetExecutionContext(context);
+ }
+ Path2D(ExecutionContext* context, const Path& path) : CanvasPath(path) {
+ identifiability_study_helper_.SetExecutionContext(context);
+ }
+ Path2D(ExecutionContext* context, Path2D* path)
+ : CanvasPath(path->GetPath()) {
+ identifiability_study_helper_.SetExecutionContext(context);
+ }
+ Path2D(ExecutionContext* context, const String& path_data) {
+ identifiability_study_helper_.SetExecutionContext(context);
BuildPathFromString(path_data, path_);
}
~Path2D() override = default;
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 c9049fc14f0..d9d38f3b0fc 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
@@ -31,7 +31,7 @@
[
Exposed=(PaintWorklet,Window,Worker)
] interface Path2D {
- constructor(optional (Path2D or DOMString) path);
+ [CallWith=ExecutionContext] constructor(optional (Path2D or DOMString) path);
[RaisesException] void addPath(Path2D path, optional DOMMatrix2DInit transform = {});
};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_module.idl b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_module.idl
index b46db2305fa..6b080a57df7 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_module.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_module.idl
@@ -38,8 +38,8 @@ dictionary CanvasContextCreationAttributesModule {
// Canvas 2D attributes
boolean alpha = true; // Also used for WebGL.
- PredefinedColorSpace colorSpace = "srgb";
- [RuntimeEnabled=CanvasColorManagement] CanvasPixelFormat pixelFormat = "uint8";
+ [RuntimeEnabled=CanvasColorManagement] PredefinedColorSpace colorSpace = "srgb";
+ [RuntimeEnabled=CanvasColorManagementV2] CanvasPixelFormat pixelFormat = "uint8";
[RuntimeEnabled=NewCanvas2DAPI] boolean willReadFrequently = false;
// WebGL attributes
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 a1757aa0fd0..2854b3c6446 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
@@ -13,7 +13,6 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* HTMLCanvasElementModule::getContext(
HTMLCanvasElement& canvas,
const String& context_id,
@@ -40,34 +39,6 @@ V8RenderingContext* HTMLCanvasElementModule::getContext(
return nullptr;
return context->AsV8RenderingContext();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void HTMLCanvasElementModule::getContext(
- HTMLCanvasElement& canvas,
- const String& type,
- const CanvasContextCreationAttributesModule* attributes,
- RenderingContext& result,
- ExceptionState& exception_state) {
- if (canvas.SurfaceLayerBridge() && !canvas.LowLatencyEnabled()) {
- // The existence of canvas surfaceLayerBridge indicates that
- // HTMLCanvasElement.transferControlToOffscreen() has been called.
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot get context from a canvas that "
- "has transferred its control to "
- "offscreen.");
- return;
- }
-
- CanvasContextCreationAttributesCore canvas_context_creation_attributes;
- if (!ToCanvasContextCreationAttributes(
- attributes, canvas_context_creation_attributes, exception_state)) {
- return;
- }
- CanvasRenderingContext* context = canvas.GetCanvasRenderingContext(
- type, canvas_context_creation_attributes);
- if (context)
- context->SetCanvasGetContextResult(result);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
OffscreenCanvas* HTMLCanvasElementModule::transferControlToOffscreen(
ExecutionContext* execution_context,
@@ -114,4 +85,5 @@ OffscreenCanvas* HTMLCanvasElementModule::TransferControlToOffscreenInternal(
}
return offscreen_canvas;
}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h
index f094cc06235..b3ffb691f8f 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h
@@ -6,13 +6,15 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_HTMLCANVAS_HTML_CANVAS_ELEMENT_MODULE_H_
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
-#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
class CanvasContextCreationAttributesModule;
+class ExceptionState;
+class ExecutionContext;
class HTMLCanvasElement;
class OffscreenCanvas;
@@ -22,19 +24,11 @@ class MODULES_EXPORT HTMLCanvasElementModule {
friend class HTMLCanvasElementModuleTest;
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static V8RenderingContext* getContext(
HTMLCanvasElement& canvas,
const String& context_id,
const CanvasContextCreationAttributesModule* attributes,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static void getContext(HTMLCanvasElement&,
- const String&,
- const CanvasContextCreationAttributesModule*,
- RenderingContext&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static OffscreenCanvas* transferControlToOffscreen(ExecutionContext*,
HTMLCanvasElement&,
ExceptionState&);
@@ -44,6 +38,7 @@ class MODULES_EXPORT HTMLCanvasElementModule {
HTMLCanvasElement&,
ExceptionState&);
};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_HTMLCANVAS_HTML_CANVAS_ELEMENT_MODULE_H_
diff --git a/chromium/third_party/blink/renderer/modules/canvas/idls.gni b/chromium/third_party/blink/renderer/modules/canvas/idls.gni
deleted file mode 100644
index 5ee0dba4608..00000000000
--- a/chromium/third_party/blink/renderer/modules/canvas/idls.gni
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/blink/renderer/config.gni")
-
-modules_idl_files = [
- "canvas2d/canvas_filter.idl",
- "canvas2d/canvas_formatted_text.idl",
- "canvas2d/canvas_formatted_text_run.idl",
- "canvas2d/canvas_gradient.idl",
- "canvas2d/canvas_pattern.idl",
- "canvas2d/canvas_rendering_context_2d.idl",
- "canvas2d/path_2d.idl",
- "imagebitmap/image_bitmap_rendering_context.idl",
- "offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl",
-]
-
-modules_dictionary_idl_files = [
- "canvas2d/canvas_filter_dictionary.idl",
- "canvas2d/canvas_rendering_context_2d_settings.idl",
- "canvas2d/hit_region_options.idl",
- "htmlcanvas/canvas_context_creation_attributes_module.idl",
-]
-
-modules_dependency_idl_files = [
- "canvas2d/canvas_path.idl",
- "htmlcanvas/html_canvas_element_module.idl",
- "imagebitmap/window_create_image_bitmap.idl",
- "imagebitmap/worker_create_image_bitmap.idl",
- "offscreencanvas/offscreen_canvas_module.idl",
-]
-
-modules_testing_dependency_idl_files =
- [ "canvas2d/testing/internals_canvas_rendering_context_2d.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.cc b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.cc
index 8f42c005e87..a62c7bf2271 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.cc
@@ -80,7 +80,6 @@ enum CreateImageBitmapSource {
} // namespace
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
inline ImageBitmapSource* ToImageBitmapSourceInternal(
const V8ImageBitmapSource* value,
const ImageBitmapOptions* options,
@@ -129,60 +128,6 @@ inline ImageBitmapSource* ToImageBitmapSourceInternal(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-static inline ImageBitmapSource* ToImageBitmapSourceInternal(
- const ImageBitmapSourceUnion& value,
- const ImageBitmapOptions* options,
- bool has_crop_rect) {
- if (value.IsHTMLVideoElement()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceHTMLVideoElement);
- return value.GetAsHTMLVideoElement();
- }
- if (value.IsHTMLImageElement()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceHTMLImageElement);
- return value.GetAsHTMLImageElement();
- }
- if (value.IsSVGImageElement()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceSVGImageElement);
- return value.GetAsSVGImageElement();
- }
- if (value.IsHTMLCanvasElement()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceHTMLCanvasElement);
- return value.GetAsHTMLCanvasElement();
- }
- if (value.IsBlob()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceBlob);
- return value.GetAsBlob();
- }
- if (value.IsImageData()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceImageData);
- return value.GetAsImageData();
- }
- if (value.IsImageBitmap()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceImageBitmap);
- return value.GetAsImageBitmap();
- }
- if (value.IsOffscreenCanvas()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceOffscreenCanvas);
- return value.GetAsOffscreenCanvas();
- }
- if (value.IsVideoFrame()) {
- UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.CreateImageBitmapSource",
- kCreateImageBitmapSourceVideoFrame);
- return value.GetAsVideoFrame();
- }
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise ImageBitmapFactories::CreateImageBitmapFromBlob(
ScriptState* script_state,
@@ -200,11 +145,7 @@ ScriptPromise ImageBitmapFactories::CreateImageBitmapFromBlob(
ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource* bitmap_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& bitmap_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
WebFeature feature = WebFeature::kCreateImageBitmap;
@@ -219,11 +160,7 @@ ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource* bitmap_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& bitmap_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
int sx,
int sy,
int sw,
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h
index 593be689e4a..3b94d2e0796 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h
@@ -37,14 +37,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/bindings/core/v8/v8_image_bitmap_options.h"
-#include "third_party/blink/renderer/bindings/modules/v8/image_bitmap_source.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_source_union.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_state.h"
@@ -71,19 +69,11 @@ class MODULES_EXPORT ImageBitmapFactories final
ImageBitmapFactories();
static ScriptPromise CreateImageBitmap(ScriptState*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ImageBitmapOptions*,
ExceptionState&);
static ScriptPromise CreateImageBitmap(ScriptState*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
int sx,
int sy,
int sw,
@@ -100,11 +90,7 @@ class MODULES_EXPORT ImageBitmapFactories final
static ScriptPromise createImageBitmap(
ScriptState* script_state,
LocalDOMWindow&,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource* bitmap_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& bitmap_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
return CreateImageBitmap(script_state, bitmap_source, options,
@@ -113,11 +99,7 @@ class MODULES_EXPORT ImageBitmapFactories final
static ScriptPromise createImageBitmap(
ScriptState* script_state,
LocalDOMWindow&,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource* bitmap_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& bitmap_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
int sx,
int sy,
int sw,
@@ -132,11 +114,7 @@ class MODULES_EXPORT ImageBitmapFactories final
static ScriptPromise createImageBitmap(
ScriptState* script_state,
WorkerGlobalScope&,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource* bitmap_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& bitmap_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
return CreateImageBitmap(script_state, bitmap_source, options,
@@ -145,11 +123,7 @@ class MODULES_EXPORT ImageBitmapFactories final
static ScriptPromise createImageBitmap(
ScriptState* script_state,
WorkerGlobalScope&,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8ImageBitmapSource* bitmap_source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& bitmap_source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
int sx,
int sy,
int sw,
@@ -160,7 +134,7 @@ class MODULES_EXPORT ImageBitmapFactories final
options, exception_state);
}
- virtual ~ImageBitmapFactories() = default;
+ ~ImageBitmapFactories() override = default;
void Trace(Visitor*) const override;
const char* NameInHeapSnapshot() const override {
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 86abf5bf444..fdc329d73a7 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
@@ -6,8 +6,6 @@
#include <utility>
-#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/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
@@ -23,8 +21,6 @@ ImageBitmapRenderingContext::ImageBitmapRenderingContext(
ImageBitmapRenderingContext::~ImageBitmapRenderingContext() = default;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* ImageBitmapRenderingContext::AsV8RenderingContext() {
return MakeGarbageCollected<V8RenderingContext>(this);
}
@@ -34,19 +30,6 @@ ImageBitmapRenderingContext::AsV8OffscreenRenderingContext() {
return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void ImageBitmapRenderingContext::SetCanvasGetContextResult(
- RenderingContext& result) {
- result.SetImageBitmapRenderingContext(this);
-}
-void ImageBitmapRenderingContext::SetOffscreenCanvasGetContextResult(
- OffscreenRenderingContext& result) {
- result.SetImageBitmapRenderingContext(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void ImageBitmapRenderingContext::transferFromImageBitmap(
ImageBitmap* image_bitmap,
ExceptionState& exception_state) {
@@ -79,8 +62,6 @@ CanvasRenderingContext* ImageBitmapRenderingContext::Factory::Create(
CanvasRenderingContext* rendering_context =
MakeGarbageCollected<ImageBitmapRenderingContext>(host, attrs);
DCHECK(rendering_context);
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::kBitmaprenderer);
return rendering_context;
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h
index 6e54e50b239..fe82b05e5bb 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h
@@ -50,13 +50,8 @@ class MODULES_EXPORT ImageBitmapRenderingContext final
}
ImageBitmap* TransferToImageBitmap(ScriptState*) override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* AsV8RenderingContext() final;
V8OffscreenRenderingContext* AsV8OffscreenRenderingContext() final;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetCanvasGetContextResult(RenderingContext&) final;
- void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) final;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
~ImageBitmapRenderingContext() override;
};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.idl b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.idl
index 0e7ad6f20c2..a36e36a1453 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.idl
@@ -5,6 +5,7 @@
// https://html.spec.whatwg.org/C/#the-imagebitmap-rendering-context
[
+ ActiveScriptWrappable,
Exposed=(Window,Worker)
] interface ImageBitmapRenderingContext {
// back-reference to the canvas
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
index fad044cf917..a3db1e96175 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
@@ -5,8 +5,6 @@
#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.h"
-#include "third_party/blink/renderer/bindings/modules/v8/html_canvas_element_or_offscreen_canvas.h"
-#include "third_party/blink/renderer/bindings/modules/v8/rendering_context.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
@@ -21,13 +19,12 @@ namespace blink {
ImageBitmapRenderingContextBase::ImageBitmapRenderingContextBase(
CanvasRenderingContextHost* host,
const CanvasContextCreationAttributesCore& attrs)
- : CanvasRenderingContext(host, attrs),
+ : CanvasRenderingContext(host, attrs, CanvasRenderingAPI::kBitmaprenderer),
image_layer_bridge_(MakeGarbageCollected<ImageLayerBridge>(
attrs.alpha ? kNonOpaque : kOpaque)) {}
ImageBitmapRenderingContextBase::~ImageBitmapRenderingContextBase() = default;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionHTMLCanvasElementOrOffscreenCanvas*
ImageBitmapRenderingContextBase::getHTMLOrOffscreenCanvas() const {
if (Host()->IsOffscreenCanvas()) {
@@ -37,16 +34,6 @@ ImageBitmapRenderingContextBase::getHTMLOrOffscreenCanvas() const {
return MakeGarbageCollected<V8UnionHTMLCanvasElementOrOffscreenCanvas>(
static_cast<HTMLCanvasElement*>(Host()));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void ImageBitmapRenderingContextBase::getHTMLOrOffscreenCanvas(
- HTMLCanvasElementOrOffscreenCanvas& result) const {
- if (Host()->IsOffscreenCanvas()) {
- result.SetOffscreenCanvas(static_cast<OffscreenCanvas*>(Host()));
- } else {
- result.SetHTMLCanvasElement(static_cast<HTMLCanvasElement*>(Host()));
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void ImageBitmapRenderingContextBase::Stop() {
image_layer_bridge_->Dispose();
@@ -75,7 +62,7 @@ void ImageBitmapRenderingContextBase::SetImage(ImageBitmap* image_bitmap) {
else
ResetInternalBitmapToBlackTransparent(Host()->width(), Host()->height());
- DidDraw();
+ DidDraw(CanvasPerformanceMonitor::DrawType::kOther);
if (image_bitmap)
image_bitmap->close();
@@ -133,6 +120,9 @@ bool ImageBitmapRenderingContextBase::PushFrame() {
return false;
scoped_refptr<StaticBitmapImage> image = image_layer_bridge_->GetImage();
+ if (!image) {
+ return false;
+ }
cc::PaintFlags paint_flags;
paint_flags.setBlendMode(SkBlendMode::kSrc);
Host()->ResourceProvider()->Canvas()->drawImage(
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
index 591bd77ed31..514ddfa2fc0 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
@@ -17,7 +17,6 @@ class Layer;
namespace blink {
-class HTMLCanvasElementOrOffscreenCanvas;
class ImageBitmap;
class ImageLayerBridge;
class V8UnionHTMLCanvasElementOrOffscreenCanvas;
@@ -39,11 +38,7 @@ class MODULES_EXPORT ImageBitmapRenderingContextBase
}
bool CanCreateCanvas2dResourceProvider() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionHTMLCanvasElementOrOffscreenCanvas* getHTMLOrOffscreenCanvas() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void getHTMLOrOffscreenCanvas(HTMLCanvasElementOrOffscreenCanvas&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void SetIsInHiddenPage(bool) override {}
void SetIsBeingDisplayed(bool) override {}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_source_union.h b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_source_union.h
deleted file mode 100644
index 7f2c0f047d2..00000000000
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_source_union.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_IMAGEBITMAP_IMAGE_BITMAP_SOURCE_UNION_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_IMAGEBITMAP_IMAGE_BITMAP_SOURCE_UNION_H_
-
-#include "third_party/blink/renderer/bindings/modules/v8/image_bitmap_source.h"
-
-namespace blink {
-
-using ImageBitmapSourceUnion =
- HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvasOrVideoFrame;
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_IMAGEBITMAP_IMAGE_BITMAP_SOURCE_UNION_H_
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 df92f8e2c2f..ef3e28e973d 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
@@ -12,7 +12,6 @@
namespace blink {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8OffscreenRenderingContext* OffscreenCanvasModule::getContext(
ExecutionContext* execution_context,
OffscreenCanvas& offscreen_canvas,
@@ -38,32 +37,5 @@ V8OffscreenRenderingContext* OffscreenCanvasModule::getContext(
return nullptr;
return context->AsV8OffscreenRenderingContext();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void OffscreenCanvasModule::getContext(
- ExecutionContext* execution_context,
- OffscreenCanvas& offscreen_canvas,
- const String& id,
- const CanvasContextCreationAttributesModule* attributes,
- OffscreenRenderingContext& result,
- ExceptionState& exception_state) {
- if (offscreen_canvas.IsNeutered()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "OffscreenCanvas object is detached");
- return;
- }
- CanvasContextCreationAttributesCore canvas_context_creation_attributes;
- if (!ToCanvasContextCreationAttributes(
- attributes, canvas_context_creation_attributes, exception_state)) {
- return;
- }
-
- // OffscreenCanvas cannot be transferred after getContext, so this execution
- // context will always be the right one from here on.
- CanvasRenderingContext* context = offscreen_canvas.GetCanvasRenderingContext(
- execution_context, id, canvas_context_creation_attributes);
- if (context)
- context->SetOffscreenCanvasGetContextResult(result);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
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 0639ae4f416..7f25144b86c 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
@@ -21,21 +21,12 @@ class MODULES_EXPORT OffscreenCanvasModule {
STATIC_ONLY(OffscreenCanvasModule);
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static V8OffscreenRenderingContext* getContext(
ExecutionContext* execution_context,
OffscreenCanvas& offscreen_canvas,
const String& context_id,
const CanvasContextCreationAttributesModule* attributes,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static void getContext(ExecutionContext*,
- OffscreenCanvas&,
- const String&,
- const CanvasContextCreationAttributesModule*,
- OffscreenRenderingContext&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
} // namespace blink
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 cf134948a03..7912837be53 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
@@ -9,7 +9,7 @@ typedef (OffscreenCanvasRenderingContext2D or
WebGL2RenderingContext or
ImageBitmapRenderingContext or
GPUCanvasContext) OffscreenRenderingContext;
-enum OffscreenRenderingContextType { "2d", "webgl", "webgl2", "bitmaprenderer", "gpupresent" };
+enum OffscreenRenderingContextType { "2d", "webgl", "webgl2", "bitmaprenderer", "gpupresent", "webgpu" };
[
ImplementedAs=OffscreenCanvasModule
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 92ffb0ee1e4..b2869c35d9f 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
@@ -149,7 +149,7 @@ TEST_P(OffscreenCanvasTest, CompositorFrameOpacity) {
const auto canvas_resource = CanvasResourceSharedBitmap::Create(
offscreen_canvas().Size(), CanvasResourceParams(), nullptr /* provider */,
- kLow_SkFilterQuality);
+ cc::PaintFlags::FilterQuality::kLow);
EXPECT_TRUE(!!canvas_resource);
EXPECT_CALL(mock_embedded_frame_sink_provider.mock_compositor_frame_sink(),
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 05291896076..2af7de9bf05 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
@@ -5,8 +5,8 @@
#include "third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h"
#include "base/metrics/histogram_functions.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/bindings/modules/v8/offscreen_rendering_context.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
@@ -34,6 +34,8 @@ namespace {
const size_t kHardMaxCachedFonts = 250;
const size_t kMaxCachedFonts = 25;
const float kUMASampleProbability = 0.01;
+// Max delay to fire context lost for context in iframes.
+static const unsigned kMaxIframeContextLoseDelay = 100;
class OffscreenFontCache {
public:
@@ -84,8 +86,6 @@ CanvasRenderingContext* OffscreenCanvasRenderingContext2D::Factory::Create(
MakeGarbageCollected<OffscreenCanvasRenderingContext2D>(
static_cast<OffscreenCanvas*>(host), attrs);
DCHECK(rendering_context);
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::k2D);
return rendering_context;
}
@@ -95,15 +95,17 @@ OffscreenCanvasRenderingContext2D::~OffscreenCanvasRenderingContext2D() =
OffscreenCanvasRenderingContext2D::OffscreenCanvasRenderingContext2D(
OffscreenCanvas* canvas,
const CanvasContextCreationAttributesCore& attrs)
- : CanvasRenderingContext(canvas, attrs),
- random_generator_((uint32_t)base::RandUint64()),
+ : CanvasRenderingContext(canvas, attrs, CanvasRenderingAPI::k2D),
+ random_generator_(static_cast<uint32_t>(base::RandUint64())),
bernoulli_distribution_(kUMASampleProbability),
color_params_(attrs.color_space, attrs.pixel_format, attrs.alpha) {
+ identifiability_study_helper_.SetExecutionContext(
+ canvas->GetTopExecutionContext());
is_valid_size_ = IsValidImageSize(Host()->Size());
// Clear the background transparent or opaque.
if (IsCanvas2DBufferValid())
- DidDraw();
+ DidDraw(CanvasPerformanceMonitor::DrawType::kOther);
ExecutionContext* execution_context = canvas->GetTopExecutionContext();
if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
@@ -190,11 +192,15 @@ CanvasResourceProvider*
OffscreenCanvasRenderingContext2D::GetCanvasResourceProvider() const {
return Host()->ResourceProvider();
}
+
void OffscreenCanvasRenderingContext2D::Reset() {
Host()->DiscardResourceProvider();
BaseRenderingContext2D::reset();
// Because the host may have changed to a zero size
is_valid_size_ = IsValidImageSize(Host()->Size());
+ // We must resize the damage rect to avoid a potentially larger damage than
+ // actual canvas size. See: crbug.com/1227165
+ dirty_rect_for_commit_ = SkIRect::MakeWH(Width(), Height());
}
scoped_refptr<CanvasResource>
@@ -222,6 +228,11 @@ bool OffscreenCanvasRenderingContext2D::PushFrame() {
return ret;
}
+CanvasRenderingContextHost*
+OffscreenCanvasRenderingContext2D::GetCanvasRenderingContextHost() {
+ return Host();
+}
+
ImageBitmap* OffscreenCanvasRenderingContext2D::TransferToImageBitmap(
ScriptState* script_state) {
WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmap2D;
@@ -252,8 +263,6 @@ scoped_refptr<StaticBitmapImage> OffscreenCanvasRenderingContext2D::GetImage() {
return image;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* OffscreenCanvasRenderingContext2D::AsV8RenderingContext() {
return nullptr;
}
@@ -263,15 +272,6 @@ OffscreenCanvasRenderingContext2D::AsV8OffscreenRenderingContext() {
return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void OffscreenCanvasRenderingContext2D::SetOffscreenCanvasGetContextResult(
- OffscreenRenderingContext& result) {
- result.SetOffscreenCanvasRenderingContext2D(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
bool OffscreenCanvasRenderingContext2D::ParseColorOrCurrentColor(
Color& color,
const String& color_string) const {
@@ -290,22 +290,17 @@ cc::PaintCanvas* OffscreenCanvasRenderingContext2D::GetPaintCanvas() const {
return GetCanvasResourceProvider()->Canvas();
}
-void OffscreenCanvasRenderingContext2D::DidDraw() {
- dirty_rect_for_commit_.setWH(Width(), Height());
- Host()->DidDraw();
- if (GetCanvasResourceProvider() && GetCanvasResourceProvider()->needs_flush())
- FinalizeFrame();
-}
-
-void OffscreenCanvasRenderingContext2D::DidDraw(const SkIRect& dirty_rect) {
+cc::PaintCanvas* OffscreenCanvasRenderingContext2D::GetPaintCanvasForDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType draw_type) {
+ if (!is_valid_size_ || !GetCanvasResourceProvider())
+ return nullptr;
dirty_rect_for_commit_.join(dirty_rect);
- Host()->DidDraw(SkRect::Make(dirty_rect_for_commit_));
+ GetCanvasPerformanceMonitor().DidDraw(draw_type);
+ Host()->DidDraw(dirty_rect_for_commit_);
if (GetCanvasResourceProvider() && GetCanvasResourceProvider()->needs_flush())
FinalizeFrame();
-}
-
-bool OffscreenCanvasRenderingContext2D::StateHasFilter() {
- return GetState().HasFilterForOffscreenCanvas(Host()->Size(), this);
+ return GetCanvasResourceProvider()->Canvas();
}
sk_sp<PaintFilter> OffscreenCanvasRenderingContext2D::StateGetFilter() {
@@ -327,7 +322,19 @@ void OffscreenCanvasRenderingContext2D::ValidateStateStackWithCanvas(
}
bool OffscreenCanvasRenderingContext2D::isContextLost() const {
- return false;
+ return context_lost_mode_ != kNotLostContext;
+}
+
+void OffscreenCanvasRenderingContext2D::LoseContext(LostContextMode lost_mode) {
+ if (context_lost_mode_ != kNotLostContext)
+ return;
+ context_lost_mode_ = lost_mode;
+ if (context_lost_mode_ == kSyntheticLostContext && Host()) {
+ Host()->DiscardResourceProvider();
+ }
+ uint32_t delay = base::RandInt(1, kMaxIframeContextLoseDelay);
+ dispatch_context_lost_event_timer_.StartOneShot(
+ base::TimeDelta::FromMilliseconds(delay), FROM_HERE);
}
bool OffscreenCanvasRenderingContext2D::IsPaintable() const {
@@ -399,8 +406,10 @@ String OffscreenCanvasRenderingContext2D::font() const {
void OffscreenCanvasRenderingContext2D::setFont(const String& new_font) {
if (GetState().HasRealizedFont() && new_font == GetState().UnparsedFont())
return;
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kSetFont, IdentifiabilityBenignStringToken(new_font));
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetFont, IdentifiabilityBenignStringToken(new_font));
+ }
base::TimeTicks start_time = base::TimeTicks::Now();
OffscreenFontCache& font_cache = GetOffscreenFontCache();
@@ -410,21 +419,10 @@ void OffscreenCanvasRenderingContext2D::setFont(const String& new_font) {
GetState().SetFont(*cached_font, Host()->GetFontSelector());
} else {
auto* style =
- MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);
+ CSSParser::ParseFont(new_font, Host()->GetTopExecutionContext());
if (!style)
return;
- CSSParser::ParseValue(style, CSSPropertyID::kFont, new_font, true,
- Host()->GetTopExecutionContext());
-
- // According to
- // http://lists.w3.org/Archives/Public/public-html/2009Jul/0947.html,
- // the "inherit", "initial" and "unset" values must be ignored.
- const CSSValue* font_value =
- style->GetPropertyCSSValue(CSSPropertyID::kFontSize);
- if (!font_value || font_value->IsCSSWideKeyword())
- return;
-
FontDescription desc =
FontStyleResolver::ComputeFont(*style, Host()->GetFontSelector());
@@ -434,8 +432,8 @@ void OffscreenCanvasRenderingContext2D::setFont(const String& new_font) {
GetState().SetUnparsedFont(new_font);
if (bernoulli_distribution_(random_generator_)) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
- base::UmaHistogramMicrosecondsTimesUnderTenMilliseconds(
- "OffscreenCanvas.TextMetrics.SetFont", elapsed);
+ base::UmaHistogramMicrosecondsTimes("OffscreenCanvas.TextMetrics.SetFont2",
+ elapsed);
}
}
@@ -458,33 +456,38 @@ String OffscreenCanvasRenderingContext2D::direction() const {
? kRtlDirectionString
: kLtrDirectionString;
}
-void OffscreenCanvasRenderingContext2D::setTextLetterSpacing(
+void OffscreenCanvasRenderingContext2D::setLetterSpacing(
const double letter_spacing) {
if (UNLIKELY(!std::isfinite(letter_spacing)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
float letter_spacing_float = clampTo<float>(letter_spacing);
- GetState().SetTextLetterSpacing(letter_spacing_float,
- Host()->GetFontSelector());
+ GetState().SetLetterSpacing(letter_spacing_float, Host()->GetFontSelector());
}
-void OffscreenCanvasRenderingContext2D::setTextWordSpacing(
+void OffscreenCanvasRenderingContext2D::setWordSpacing(
const double word_spacing) {
if (UNLIKELY(!std::isfinite(word_spacing)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
float word_spacing_float = clampTo<float>(word_spacing);
- GetState().SetTextWordSpacing(word_spacing_float, Host()->GetFontSelector());
+ GetState().SetWordSpacing(word_spacing_float, Host()->GetFontSelector());
}
void OffscreenCanvasRenderingContext2D::setTextRendering(
const String& text_rendering_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -526,6 +529,8 @@ void OffscreenCanvasRenderingContext2D::setDirection(
void OffscreenCanvasRenderingContext2D::setFontKerning(
const String& font_kerning_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
FontDescription::Kerning kerning;
@@ -547,6 +552,8 @@ void OffscreenCanvasRenderingContext2D::setFontKerning(
void OffscreenCanvasRenderingContext2D::setFontStretch(
const String& font_stretch) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -581,6 +588,8 @@ void OffscreenCanvasRenderingContext2D::setFontStretch(
void OffscreenCanvasRenderingContext2D::setFontVariantCaps(
const String& font_variant_caps_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
FontDescription::FontVariantCaps variant_caps;
@@ -651,13 +660,15 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
if (max_width && (!std::isfinite(*max_width) || *max_width <= 0))
return;
- identifiability_study_helper_.MaybeUpdateBuilder(
- paint_type == CanvasRenderingContext2DState::kFillPaintType
- ? CanvasOps::kFillText
- : CanvasOps::kStrokeText,
- IdentifiabilitySensitiveStringToken(text), x, y,
- max_width ? *max_width : -1);
- identifiability_study_helper_.set_encountered_sensitive_ops();
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ paint_type == CanvasRenderingContext2DState::kFillPaintType
+ ? CanvasOps::kFillText
+ : CanvasOps::kStrokeText,
+ IdentifiabilitySensitiveStringToken(text), x, y,
+ max_width ? *max_width : -1);
+ identifiability_study_helper_.set_encountered_sensitive_ops();
+ }
const Font& font = AccessFont();
const SimpleFontData* font_data = font.PrimaryFont();
@@ -728,7 +739,8 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
},
[](const SkIRect& rect) // overdraw test lambda
{ return false; },
- bounds, paint_type, CanvasRenderingContext2DState::kNoImage);
+ bounds, paint_type, CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kText);
// |paint_canvas| maybe rese during Draw. If that happens,
// GetOrCreatePaintCanvas will create a new |paint_canvas| and return a new
@@ -762,4 +774,40 @@ bool OffscreenCanvasRenderingContext2D::IsCanvas2DBufferValid() const {
return false;
}
+void OffscreenCanvasRenderingContext2D::TryRestoreContextEvent(
+ TimerBase* timer) {
+ if (context_lost_mode_ == kNotLostContext) {
+ // Canvas was already restored (possibly thanks to a resize), so stop
+ // trying.
+ try_restore_context_event_timer_.Stop();
+ return;
+ }
+
+ DCHECK(context_lost_mode_ != kWebGLLoseContextLostContext);
+
+ // If lost mode is |kSyntheticLostContext| and |context_restorable_| is set to
+ // true, it means context is forced to be lost for testing purpose. Restore
+ // the context.
+ if (context_lost_mode_ == kSyntheticLostContext) {
+ try_restore_context_event_timer_.Stop();
+ Host()->GetOrCreateCanvasResourceProvider(RasterModeHint::kPreferGPU);
+ DispatchContextRestoredEvent(nullptr);
+
+ // If lost mode is |kRealLostContext|, it means the context was not lost due
+ // to surface failure but rather due to a an eviction, which means image
+ // buffer exists.
+ } else if (context_lost_mode_ == kRealLostContext &&
+ GetOrCreatePaintCanvas()) {
+ try_restore_context_event_timer_.Stop();
+ DispatchContextRestoredEvent(nullptr);
+ }
+
+ // It gets here if lost mode is |kRealLostContext| and it fails to create a
+ // new PaintCanvas. Discard the old resource and allocating a new one here.
+ Host()->DiscardResourceProvider();
+ try_restore_context_event_timer_.Stop();
+ if (GetOrCreatePaintCanvas())
+ DispatchContextRestoredEvent(nullptr);
+}
+
} // namespace blink
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 5a0a91fecbb..4d7270f0f86 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
@@ -56,16 +56,10 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
// CanvasRenderingContext implementation
~OffscreenCanvasRenderingContext2D() override;
ContextType GetContextType() const override { return kContext2D; }
- bool IsRenderingContext2D() const override { return true; }
bool IsComposited() const override { return false; }
bool IsAccelerated() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* AsV8RenderingContext() final;
V8OffscreenRenderingContext* AsV8OffscreenRenderingContext() final;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetCanvasGetContextResult(RenderingContext&) final {}
- void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) final;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void SetIsInHiddenPage(bool) final { NOTREACHED(); }
void SetIsBeingDisplayed(bool) final { NOTREACHED(); }
void Stop() final { NOTREACHED(); }
@@ -77,6 +71,12 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
void RestoreCanvasMatrixClipStack(cc::PaintCanvas* c) const override {
RestoreMatrixClipStack(c);
}
+ // CanvasRenderingContext - ActiveScriptWrappable
+ // This method will avoid this class to be garbage collected, as soon as
+ // HasPendingActivity returns true.
+ bool HasPendingActivity() const final {
+ return !dirty_rect_for_commit_.isEmpty();
+ }
String font() const;
void setFont(const String&) override;
@@ -84,8 +84,8 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
String direction() const;
void setDirection(const String&);
- void setTextLetterSpacing(const double letter_spacing);
- void setTextWordSpacing(const double word_spacing);
+ void setLetterSpacing(const double letter_spacing);
+ void setWordSpacing(const double word_spacing);
void setTextRendering(const String&);
void setFontKerning(const String&);
void setFontStretch(const String&);
@@ -118,11 +118,10 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
cc::PaintCanvas* GetOrCreatePaintCanvas() final;
cc::PaintCanvas* GetPaintCanvas() const final;
+ cc::PaintCanvas* GetPaintCanvasForDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType) final;
- void DidDraw() final;
- void DidDraw(const SkIRect& dirty_rect) final;
-
- bool StateHasFilter() final;
sk_sp<PaintFilter> StateGetFilter() final;
void SnapshotStateForFilter() final;
@@ -133,6 +132,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
return CreationAttributes().desynchronized;
}
bool isContextLost() const override;
+ void LoseContext(LostContextMode) override;
ImageBitmap* TransferToImageBitmap(ScriptState*) final;
@@ -140,6 +140,8 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
bool PushFrame() override;
+ CanvasRenderingContextHost* GetCanvasRenderingContextHost() override;
+
IdentifiableToken IdentifiableTextToken() const override {
return identifiability_study_helper_.GetToken();
}
@@ -152,6 +154,10 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
return identifiability_study_helper_.encountered_sensitive_ops();
}
+ bool IdentifiabilityEncounteredPartiallyDigestedImage() const override {
+ return identifiability_study_helper_.encountered_partially_digested_image();
+ }
+
protected:
// This reports CanvasColorParams to the CanvasRenderingContext interface.
CanvasColorParams CanvasRenderingContextColorParams() const override {
@@ -167,6 +173,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
int x,
int y) override;
void WillOverwriteCanvas() override;
+ void TryRestoreContextEvent(TimerBase*) override;
private:
void FinalizeFrame() final;
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 9783aef36a0..3c8b3134706 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
@@ -5,6 +5,7 @@
// https://html.spec.whatwg.org/C/#the-offscreen-2d-rendering-context
[
+ ActiveScriptWrappable,
Exposed=(Window,Worker)
] interface OffscreenCanvasRenderingContext2D {
// back-reference to the canvas
@@ -14,9 +15,12 @@
// state
void save(); // push state on state stack
- [NoAllocDirectCall] void restore(); // pop state stack and restore state
+ [NoAllocDirectCall] void restore(); // pop state stack if top state was pushed by save, and restore state
+ [RuntimeEnabled=Canvas2dLayers] void beginLayer(); // push state on state stack and creates bitmap for subsequent draw ops
+ [RuntimeEnabled=Canvas2dLayers] void endLayer(); // pop state stack if top state was pushed by beginLayer, restore state and draw the bitmap
// Clear the canvas and reset the path
[RuntimeEnabled=NewCanvas2DAPI] void reset();
+ [RuntimeEnabled=NewCanvas2DAPI] boolean isContextLost();
// transformations (default transform is the identity matrix)
void scale(unrestricted double x, unrestricted double y);
@@ -92,10 +96,12 @@
// pixel manipulation
[RaisesException] ImageData createImageData(ImageData imagedata);
- [RaisesException] ImageData createImageData(long sw, long sh, optional ImageDataSettings imageDataSettings = {});
- [HighEntropy, MeasureAs=OffscreenCanvasGetImageData, RaisesException] ImageData getImageData(long sx, long sy, long sw, long sh, optional ImageDataSettings imageDataSettings = {});
- [RaisesException] void putImageData(ImageData imagedata, long dx, long dy);
- [RaisesException] void putImageData(ImageData imagedata, long dx, long dy, long dirtyX, long dirtyY, long dirtyWidth, long dirtyHeight);
+ [RaisesException] ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh);
+ [RaisesException, RuntimeEnabled=CanvasColorManagement] ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh, ImageDataSettings imageDataSettings);
+ [HighEntropy, MeasureAs=OffscreenCanvasGetImageData, RaisesException] ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh);
+ [HighEntropy, MeasureAs=OffscreenCanvasGetImageData, RaisesException, RuntimeEnabled=CanvasColorManagement] ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh, ImageDataSettings imageDataSettings);
+ [RaisesException] void putImageData(ImageData imagedata, [EnforceRange] long dx, [EnforceRange] long dy);
+ [RaisesException] void putImageData(ImageData imagedata, [EnforceRange] long dx, [EnforceRange] long dy, [EnforceRange] long dirtyX, [EnforceRange] long dirtyY, [EnforceRange] long dirtyWidth, [EnforceRange] long dirtyHeight);
// Line caps/joins
attribute unrestricted double lineWidth; // (default 1)
@@ -116,9 +122,9 @@
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString fontKerning; // "auto", "normal", "none" (default: "auto")
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString fontStretch; // "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "normal", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" (default: normal)
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString fontVariantCaps; // "normal", "small-caps", "all-small-caps", "petite-caps", "all-petite-caps", "unicase", "titling-caps" (default: "normal")
- [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double textLetterSpacing; // length in pixel (default: 0)
+ [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double letterSpacing; // length in pixel (default: 0)
[RuntimeEnabled=NewCanvas2DAPI] attribute DOMString textRendering; // "auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision" (default: auto)
- [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double textWordSpacing; // length in pixel (default: 0)
+ [RuntimeEnabled=NewCanvas2DAPI] attribute unrestricted double wordSpacing; // length in pixel (default: 0)
};
OffscreenCanvasRenderingContext2D includes CanvasPath;
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/OWNERS b/chromium/third_party/blink/renderer/modules/clipboard/OWNERS
index a9eeb38c1f2..123405e4ac6 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/clipboard/OWNERS
@@ -1,8 +1,6 @@
# Primary:
-huangdarwin@chromium.org
+mek@chromium.org
# Secondary:
garykac@chromium.org
-mek@chromium.org
pwnall@chromium.org
-jsbell@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard.idl b/chromium/third_party/blink/renderer/modules/clipboard/clipboard.idl
index 6ba3ccc290c..01d0dac998d 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard.idl
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard.idl
@@ -14,7 +14,7 @@
[MeasureAs=AsyncClipboardAPIRead,
CallWith=ScriptState,
- RuntimeEnabled=RawClipboard
+ RuntimeEnabled=ClipboardCustomFormats
] Promise<sequence<ClipboardItem>> read(ClipboardItemOptions options);
[MeasureAs=AsyncClipboardAPIReadText,
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.cc b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.cc
index ee00cb385f2..b8b218a0dc3 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.cc
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.cc
@@ -31,10 +31,13 @@ ClipboardItem* ClipboardItem::Create(
ClipboardItem::ClipboardItem(
const HeapVector<std::pair<String, Member<Blob>>>& items,
const ClipboardItemOptions* options)
- : items_(items),
- is_raw_(base::FeatureList::IsEnabled(features::kRawClipboard) &&
- options->raw()) {
+ : items_(items) {
DCHECK(items_.size());
+ if (options->hasUnsanitized()) {
+ for (const auto& unsanitized_item : options->unsanitized()) {
+ custom_format_items_.push_back(unsanitized_item);
+ }
+ }
}
Vector<String> ClipboardItem::types() const {
@@ -46,10 +49,6 @@ Vector<String> ClipboardItem::types() const {
return types;
}
-bool ClipboardItem::raw() const {
- return is_raw_;
-}
-
ScriptPromise ClipboardItem::getType(ScriptState* script_state,
const String& type) const {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.h b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.h
index a497ee5f863..81757201183 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.h
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.h
@@ -28,18 +28,20 @@ class ClipboardItem final : public ScriptWrappable {
const HeapVector<std::pair<String, Member<Blob>>>& items,
const ClipboardItemOptions* options);
Vector<String> types() const;
- bool raw() const;
ScriptPromise getType(ScriptState* script_state, const String& type) const;
const HeapVector<std::pair<String, Member<Blob>>>& GetItems() const {
return items_;
}
+ // Returns the custom formats passed to direct option.
+ const Vector<String>& CustomFormats() const { return custom_format_items_; }
+
void Trace(Visitor*) const override;
private:
HeapVector<std::pair<String, Member<Blob>>> items_;
- const bool is_raw_;
+ Vector<String> custom_format_items_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.idl b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.idl
index 1024f684599..ac3eefa6db6 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.idl
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item.idl
@@ -5,15 +5,13 @@
// https://w3c.github.io/clipboard-apis/#clipboard-interface
[
+ SecureContext,
Exposed=Window
] interface ClipboardItem {
[RaisesException] constructor(record<DOMString, Blob> items,
optional ClipboardItemOptions options = {});
readonly attribute FrozenArray<DOMString> types;
- [RuntimeEnabled=RawClipboard]
- readonly attribute boolean raw;
-
[
CallWith=ScriptState
] Promise<Blob> getType(DOMString type);
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item_options.idl b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item_options.idl
index eefa3ed4c54..c1e12134f66 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item_options.idl
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_item_options.idl
@@ -5,5 +5,5 @@
// https://w3c.github.io/clipboard-apis/#clipboard-interface
dictionary ClipboardItemOptions {
- boolean raw = false;
+ [RuntimeEnabled=ClipboardCustomFormats] sequence<DOMString> unsanitized;
}; \ No newline at end of file
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 3dabb82f769..631100bf570 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -16,7 +16,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_clipboard_item_options.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
-#include "third_party/blink/renderer/core/clipboard/raw_system_clipboard.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/dom/dom_exception.h"
@@ -133,10 +132,7 @@ void ClipboardPromise::WriteNextRepresentation() {
// This is in the start flow so that a |clipboard_item_data_| with 0 items
// will still commit gracefully.
if (clipboard_representation_index_ == clipboard_item_data_.size()) {
- if (is_raw_)
- local_frame->GetRawSystemClipboard()->CommitWrite();
- else
- local_frame->GetSystemClipboard()->CommitWrite();
+ local_frame->GetSystemClipboard()->CommitWrite();
script_promise_resolver_->Resolve();
return;
}
@@ -148,14 +144,8 @@ void ClipboardPromise::WriteNextRepresentation() {
clipboard_item_data_[clipboard_representation_index_].second;
DCHECK(!clipboard_writer_);
- if (is_raw_) {
- clipboard_writer_ = ClipboardWriter::Create(
- local_frame->GetRawSystemClipboard(), type, this);
- } else {
- clipboard_writer_ =
- ClipboardWriter::Create(local_frame->GetSystemClipboard(), type, this);
- }
-
+ clipboard_writer_ =
+ ClipboardWriter::Create(local_frame->GetSystemClipboard(), type, this);
clipboard_writer_->WriteToSystem(blob);
}
@@ -171,10 +161,13 @@ void ClipboardPromise::RejectFromReadOrDecodeFailure() {
void ClipboardPromise::HandleRead(ClipboardItemOptions* options) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (base::FeatureList::IsEnabled(features::kRawClipboard) && options &&
- options->hasRaw())
- is_raw_ = options->raw();
- RequestPermission(mojom::blink::PermissionName::CLIPBOARD_READ, is_raw_,
+ if (options->hasUnsanitized()) {
+ for (const auto& unsanitized_item : options->unsanitized()) {
+ custom_format_items_.push_back(unsanitized_item);
+ }
+ }
+ RequestPermission(mojom::blink::PermissionName::CLIPBOARD_READ,
+ !custom_format_items_.IsEmpty(),
WTF::Bind(&ClipboardPromise::HandleReadWithPermission,
WrapPersistent(this)));
}
@@ -208,11 +201,12 @@ void ClipboardPromise::HandleWrite(
// For now, we only process the first ClipboardItem.
ClipboardItem* clipboard_item = (*clipboard_items)[0];
clipboard_item_data_ = clipboard_item->GetItems();
- is_raw_ = clipboard_item->raw();
-
- DCHECK(base::FeatureList::IsEnabled(features::kRawClipboard) || !is_raw_);
+ custom_format_items_ = clipboard_item->CustomFormats();
+ DCHECK(base::FeatureList::IsEnabled(features::kClipboardCustomFormats) ||
+ custom_format_items_.IsEmpty());
- RequestPermission(mojom::blink::PermissionName::CLIPBOARD_WRITE, is_raw_,
+ RequestPermission(mojom::blink::PermissionName::CLIPBOARD_WRITE,
+ !custom_format_items_.IsEmpty(),
WTF::Bind(&ClipboardPromise::HandleWriteWithPermission,
WrapPersistent(this)));
}
@@ -235,13 +229,6 @@ void ClipboardPromise::HandleReadWithPermission(PermissionStatus status) {
return;
}
- if (is_raw_) {
- RawSystemClipboard* raw_system_clipboard =
- GetLocalFrame()->GetRawSystemClipboard();
- raw_system_clipboard->ReadAvailableFormatNames(WTF::Bind(
- &ClipboardPromise::OnReadAvailableFormatNames, WrapPersistent(this)));
- return;
- }
SystemClipboard* system_clipboard = GetLocalFrame()->GetSystemClipboard();
Vector<String> available_types = system_clipboard->ReadAvailableTypes();
OnReadAvailableFormatNames(available_types);
@@ -258,7 +245,7 @@ void ClipboardPromise::ResolveRead() {
}
ClipboardItemOptions* options = ClipboardItemOptions::Create();
- options->setRaw(is_raw_);
+ options->setUnsanitized(custom_format_items_);
HeapVector<Member<ClipboardItem>> clipboard_items = {
MakeGarbageCollected<ClipboardItem>(clipboard_item_data_, options)};
@@ -273,7 +260,8 @@ void ClipboardPromise::OnReadAvailableFormatNames(
clipboard_item_data_.ReserveInitialCapacity(format_names.size());
for (const String& format_name : format_names) {
- if (ClipboardWriter::IsValidType(format_name, is_raw_)) {
+ if (ClipboardWriter::IsValidType(format_name,
+ /*is_custom_format_type=*/false)) {
clipboard_item_data_.emplace_back(format_name,
/* Placeholder value. */ nullptr);
}
@@ -292,12 +280,6 @@ void ClipboardPromise::ReadNextRepresentation() {
String format_name =
clipboard_item_data_[clipboard_representation_index_].first;
- if (is_raw_) {
- GetLocalFrame()->GetRawSystemClipboard()->Read(
- format_name,
- WTF::Bind(&ClipboardPromise::OnRawRead, WrapPersistent(this)));
- return;
- }
ClipboardReader* clipboard_reader = ClipboardReader::Create(
GetLocalFrame()->GetSystemClipboard(), format_name, this);
@@ -308,26 +290,6 @@ void ClipboardPromise::ReadNextRepresentation() {
clipboard_reader->Read();
}
-void ClipboardPromise::OnRawRead(mojo_base::BigBuffer data) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!GetExecutionContext())
- return;
- String format_name =
- clipboard_item_data_[clipboard_representation_index_].first;
- Blob* blob = Blob::Create(reinterpret_cast<const uint8_t*>(data.data()),
- data.size(), format_name);
- if (!blob) {
- script_promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kDataError,
- "Failed to read or decode clipboard data for type " +
- clipboard_item_data_[clipboard_representation_index_].first + "."));
- return;
- }
- clipboard_item_data_[clipboard_representation_index_].second = blob;
- ++clipboard_representation_index_;
- ReadNextRepresentation();
-}
-
void ClipboardPromise::OnRead(Blob* blob) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
clipboard_item_data_[clipboard_representation_index_].second = blob;
@@ -364,16 +326,16 @@ void ClipboardPromise::HandleWriteWithPermission(PermissionStatus status) {
for (const auto& type_and_blob : clipboard_item_data_) {
String type = type_and_blob.first;
String type_with_args = type_and_blob.second->type();
- if (!ClipboardWriter::IsValidType(type, is_raw_)) {
+ bool is_valid_custom_format = base::Contains(custom_format_items_, type);
+ if (!ClipboardWriter::IsValidType(type, is_valid_custom_format)) {
script_promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotAllowedError,
"Type " + type + " not supported on write."));
return;
}
- // For normal (not-raw) write, blobs may have a full MIME type with args
+ // For normal (not-custom) write, blobs may have a full MIME type with args
// (ex. 'text/plain;charset=utf-8'), whereas the type must not have args
// (ex. 'text/plain' only), so ensure that Blob->type is contained in type.
- // For raw clipboard, Blobs convert their type to lowercase.
if (!type_with_args.Contains(type.LowerASCII())) {
script_promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotAllowedError,
@@ -455,10 +417,11 @@ void ClipboardPromise::RequestPermission(
return;
}
- if (is_raw_ && !LocalFrame::HasTransientUserActivation(GetLocalFrame())) {
+ if (!custom_format_items_.IsEmpty() &&
+ !LocalFrame::HasTransientUserActivation(GetLocalFrame())) {
script_promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError,
- "Must be handling a user gesture to use raw clipboard"));
+ "Must be handling a user gesture to use custom clipboard"));
return;
}
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 5805b43dd7d..c2f0cbd0f31 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -18,10 +18,6 @@
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
-namespace mojo_base {
-class BigBuffer;
-}
-
namespace blink {
class ClipboardWriter;
@@ -78,7 +74,6 @@ class ClipboardPromise final : public GarbageCollected<ClipboardPromise>,
void OnReadAvailableFormatNames(const Vector<String>& format_names);
void ReadNextRepresentation();
- void OnRawRead(mojo_base::BigBuffer data);
void ResolveRead();
// Checks for permissions (interacting with PermissionService).
@@ -104,9 +99,10 @@ class ClipboardPromise final : public GarbageCollected<ClipboardPromise>,
// Only for use in writeText().
String plain_text_;
HeapVector<std::pair<String, Member<Blob>>> clipboard_item_data_;
- bool is_raw_; // Corresponds to allowWithoutSanitization in ClipboardItem.
// Index of clipboard representation currently being processed.
wtf_size_t clipboard_representation_index_;
+ // Stores all the custom formats defined in `ClipboardItemOptions`.
+ Vector<String> custom_format_items_;
// Because v8 is thread-hostile, ensures that all interactions with
// ScriptState and ScriptPromiseResolver occur on the main thread.
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
index 50fda32311e..850c1ac036d 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/editing/serializers/serialization.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/web_feature.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/modules/clipboard/clipboard_promise.h"
#include "third_party/blink/renderer/modules/clipboard/clipboard_writer.h"
@@ -25,6 +26,37 @@ namespace blink {
namespace { // anonymous namespace for ClipboardReader's derived classes.
+// Reads a PNG from the System Clipboard as a Blob with image/png content.
+// Since the data returned from ReadPng() is already in the desired format, no
+// encoding is required and the blob is created directly from Read().
+class ClipboardPngReader final : public ClipboardReader {
+ public:
+ explicit ClipboardPngReader(SystemClipboard* system_clipboard,
+ ClipboardPromise* promise)
+ : ClipboardReader(system_clipboard, promise) {}
+ ~ClipboardPngReader() override = default;
+
+ ClipboardPngReader(const ClipboardPngReader&) = delete;
+ ClipboardPngReader& operator=(const ClipboardPngReader&) = delete;
+
+ void Read() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ mojo_base::BigBuffer data =
+ system_clipboard()->ReadPng(mojom::blink::ClipboardBuffer::kStandard);
+
+ Blob* blob = nullptr;
+ if (data.size()) {
+ blob = Blob::Create(data.data(), data.size(), kMimeTypeImagePng);
+ }
+ promise_->OnRead(blob);
+ }
+
+ private:
+ void NextRead(Vector<uint8_t> utf8_bytes) override { NOTREACHED(); }
+};
+
+// TODO(crbug.com/1223849): Replace this class with `ClipboardPngReader` logic
+// and remove `ClipboardPngReader` once `ReadImage()` path is removed.
// Reads an image from the System Clipboard as a Blob with image/png content.
class ClipboardImageReader final : public ClipboardReader {
public:
@@ -305,10 +337,19 @@ class ClipboardSvgReader final : public ClipboardReader {
ClipboardReader* ClipboardReader::Create(SystemClipboard* system_clipboard,
const String& mime_type,
ClipboardPromise* promise) {
- DCHECK(ClipboardWriter::IsValidType(mime_type, /*is_raw=*/false));
- if (mime_type == kMimeTypeImagePng)
- return MakeGarbageCollected<ClipboardImageReader>(system_clipboard,
+ DCHECK(
+ ClipboardWriter::IsValidType(mime_type, /*is_custom_format_type=*/false));
+ if (mime_type == kMimeTypeImagePng) {
+ // TODO(crbug.com/1223849): Use `ClipboardPngReader` once `ReadImage()` path
+ // is removed.
+ if (RuntimeEnabledFeatures::ClipboardReadPngEnabled()) {
+ return MakeGarbageCollected<ClipboardPngReader>(system_clipboard,
promise);
+ } else {
+ return MakeGarbageCollected<ClipboardImageReader>(system_clipboard,
+ promise);
+ }
+ }
if (mime_type == kMimeTypeTextPlain)
return MakeGarbageCollected<ClipboardTextReader>(system_clipboard, promise);
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc
index 48469de5608..7fb38eafa71 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc
@@ -6,15 +6,14 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom-blink.h"
-#include "third_party/blink/public/mojom/clipboard/raw_clipboard.mojom-blink.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
-#include "third_party/blink/renderer/core/clipboard/raw_system_clipboard.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -216,48 +215,6 @@ class ClipboardSvgWriter final : public ClipboardWriter {
}
};
-// Writes a Blob with arbitrary, unsanitized content to the System Clipboard.
-class ClipboardRawDataWriter final : public ClipboardWriter {
- public:
- ClipboardRawDataWriter(RawSystemClipboard* raw_system_clipboard,
- ClipboardPromise* promise,
- String mime_type)
- : ClipboardWriter(raw_system_clipboard, promise), mime_type_(mime_type) {}
- ~ClipboardRawDataWriter() override = default;
-
- private:
- void StartWrite(
- DOMArrayBuffer* raw_data,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // Raw Data is written directly, and doesn't require decoding.
- Write(raw_data);
- }
-
- void Write(DOMArrayBuffer* raw_data) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- if (raw_data->ByteLength() >=
- mojom::blink::RawClipboardHost::kMaxDataSize) {
- promise_->RejectFromReadOrDecodeFailure();
- return;
- }
-
- uint8_t* raw_data_pointer = static_cast<uint8_t*>(raw_data->Data());
- mojo_base::BigBuffer buffer(std::vector<uint8_t>(
- raw_data_pointer, raw_data_pointer + raw_data->ByteLength()));
-
- if (!promise_->GetLocalFrame())
- return;
- raw_system_clipboard()->Write(mime_type_, std::move(buffer));
-
- promise_->CompleteWriteRepresentation();
- }
-
- String mime_type_;
-};
-
} // anonymous namespace
// ClipboardWriter functions.
@@ -266,7 +223,8 @@ class ClipboardRawDataWriter final : public ClipboardWriter {
ClipboardWriter* ClipboardWriter::Create(SystemClipboard* system_clipboard,
const String& mime_type,
ClipboardPromise* promise) {
- DCHECK(ClipboardWriter::IsValidType(mime_type, /*is_raw=*/false));
+ DCHECK(
+ ClipboardWriter::IsValidType(mime_type, /*is_custom_format_type=*/false));
if (mime_type == kMimeTypeImagePng) {
return MakeGarbageCollected<ClipboardImageWriter>(system_clipboard,
promise);
@@ -286,27 +244,7 @@ ClipboardWriter* ClipboardWriter::Create(SystemClipboard* system_clipboard,
return nullptr;
}
-// static
-ClipboardWriter* ClipboardWriter::Create(
- RawSystemClipboard* raw_system_clipboard,
- const String& mime_type,
- ClipboardPromise* promise) {
- DCHECK(base::FeatureList::IsEnabled(features::kRawClipboard));
- DCHECK(ClipboardWriter::IsValidType(mime_type, /*is_raw=*/true));
- return MakeGarbageCollected<ClipboardRawDataWriter>(raw_system_clipboard,
- promise, mime_type);
-}
-
-ClipboardWriter::ClipboardWriter(SystemClipboard* system_clipboard,
- ClipboardPromise* promise)
- : ClipboardWriter(system_clipboard, nullptr, promise) {}
-
-ClipboardWriter::ClipboardWriter(RawSystemClipboard* raw_system_clipboard,
- ClipboardPromise* promise)
- : ClipboardWriter(nullptr, raw_system_clipboard, promise) {}
-
ClipboardWriter::ClipboardWriter(SystemClipboard* system_clipboard,
- RawSystemClipboard* raw_system_clipboard,
ClipboardPromise* promise)
: promise_(promise),
clipboard_task_runner_(promise->GetExecutionContext()->GetTaskRunner(
@@ -314,7 +252,6 @@ ClipboardWriter::ClipboardWriter(SystemClipboard* system_clipboard,
file_reading_task_runner_(promise->GetExecutionContext()->GetTaskRunner(
TaskType::kFileReading)),
system_clipboard_(system_clipboard),
- raw_system_clipboard_(raw_system_clipboard),
self_keep_alive_(PERSISTENT_FROM_HERE, this) {}
ClipboardWriter::~ClipboardWriter() {
@@ -322,9 +259,10 @@ ClipboardWriter::~ClipboardWriter() {
}
// static
-bool ClipboardWriter::IsValidType(const String& type, bool is_raw) {
- if (is_raw)
- return type.length() < mojom::blink::RawClipboardHost::kMaxFormatSize;
+bool ClipboardWriter::IsValidType(const String& type,
+ bool is_custom_format_type) {
+ if (is_custom_format_type)
+ return type.length() < mojom::blink::ClipboardHost::kMaxFormatSize;
if (type == kMimeTypeImageSvg)
return RuntimeEnabledFeatures::ClipboardSvgEnabled();
@@ -368,7 +306,6 @@ void ClipboardWriter::DidFail(FileErrorCode error_code) {
void ClipboardWriter::Trace(Visitor* visitor) const {
visitor->Trace(promise_);
visitor->Trace(system_clipboard_);
- visitor->Trace(raw_system_clipboard_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.h b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.h
index 442a3c5fb9f..4d3822a2a2c 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.h
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_writer.h
@@ -17,7 +17,6 @@ namespace blink {
class FileReaderLoader;
class SystemClipboard;
-class RawSystemClipboard;
// Interface for writing an individual Clipboard API format as a Blob to the
// System Clipboard, safely and asynchronously.
@@ -59,11 +58,7 @@ class ClipboardWriter : public GarbageCollected<ClipboardWriter>,
static ClipboardWriter* Create(SystemClipboard* system_clipboard,
const String& mime_type,
ClipboardPromise* promise);
- // For writing unsanitized types.
- // IsValidType() must return true on types passed into `mime_type`.
- static ClipboardWriter* Create(RawSystemClipboard* raw_system_clipboard,
- const String& mime_type,
- ClipboardPromise* promise);
+
~ClipboardWriter() override;
// Returns whether ClipboardWriter has implemented support for this type.
@@ -74,7 +69,7 @@ class ClipboardWriter : public GarbageCollected<ClipboardWriter>,
// IsValidType() is used for both ClipboardWriter and ClipboardReader, as read
// and write currently support the same types. If this changes in the future,
// please create separate IsValidType functions.
- static bool IsValidType(const String& mime_type, bool is_raw);
+ static bool IsValidType(const String& mime_type, bool is_custom_format_type);
// Begins the sequence of writing the Blob to the system clipbaord.
void WriteToSystem(Blob* blob);
@@ -88,8 +83,6 @@ class ClipboardWriter : public GarbageCollected<ClipboardWriter>,
protected:
ClipboardWriter(SystemClipboard* system_clipboard, ClipboardPromise* promise);
- ClipboardWriter(RawSystemClipboard* raw_system_clipboard,
- ClipboardPromise* promise);
// Decodes and writes `raw_data`. Decoding is done off the main thread
// whenever possible, by calling DecodeOnBackgroundThread.
@@ -97,18 +90,13 @@ class ClipboardWriter : public GarbageCollected<ClipboardWriter>,
DOMArrayBuffer* raw_data,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) = 0;
- // SystemClipboard and RawSystemClipboard are bound to LocalFrame, so the
- // bound LocalFrame must still be valid by the time they're used.
+ // SystemClipboard is bound to LocalFrame, so the bound LocalFrame must still
+ // be valid by the time it's used.
SystemClipboard* system_clipboard() {
DCHECK(promise_->GetLocalFrame());
return system_clipboard_;
}
- RawSystemClipboard* raw_system_clipboard() {
- DCHECK(promise_->GetLocalFrame());
- return raw_system_clipboard_;
- }
-
// This ClipboardPromise owns this ClipboardWriter. Subclasses use `promise_`
// to report success or failure, or to obtain the execution context.
Member<ClipboardPromise> promise_;
@@ -118,9 +106,6 @@ class ClipboardWriter : public GarbageCollected<ClipboardWriter>,
SEQUENCE_CHECKER(sequence_checker_);
private:
- ClipboardWriter(SystemClipboard* system_clipboard,
- RawSystemClipboard* raw_system_clipboard,
- ClipboardPromise* promise);
// TaskRunner for interacting with the system clipboard.
const scoped_refptr<base::SingleThreadTaskRunner> clipboard_task_runner_;
// TaskRunner for reading files.
@@ -129,8 +114,6 @@ class ClipboardWriter : public GarbageCollected<ClipboardWriter>,
std::unique_ptr<FileReaderLoader> file_reader_;
// Access to the global sanitized system clipboard.
Member<SystemClipboard> system_clipboard_;
- // Access to the global unsanitized system clipboard.
- Member<RawSystemClipboard> raw_system_clipboard_;
// Oilpan: ClipboardWriter must remain alive until Member<T>::Clear() is
// called, to keep the FileReaderLoader alive and avoid unexpected UaPs.
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/idls.gni b/chromium/third_party/blink/renderer/modules/clipboard/idls.gni
deleted file mode 100644
index 433867112b5..00000000000
--- a/chromium/third_party/blink/renderer/modules/clipboard/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "clipboard.idl",
- "clipboard_item.idl",
-]
-
-modules_dictionary_idl_files = [ "clipboard_item_options.idl" ]
-
-modules_dependency_idl_files = [ "navigator_clipboard.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc
index 5c4601dc816..1c17bd584bb 100644
--- a/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc
+++ b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc
@@ -4,17 +4,18 @@
#include "third_party/blink/renderer/modules/compression/deflate_transformer.h"
-#include <string.h>
#include <algorithm>
+#include <cstring>
#include <limits>
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.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_uint8_array.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/compression/compression_format.h"
#include "third_party/blink/renderer/modules/compression/zlib_partition_alloc.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -56,38 +57,19 @@ ScriptPromise DeflateTransformer::Transform(
v8::Local<v8::Value> chunk,
TransformStreamDefaultController* controller,
ExceptionState& exception_state) {
- ArrayBufferOrArrayBufferView buffer_source;
- V8ArrayBufferOrArrayBufferView::ToImpl(
- script_state_->GetIsolate(), chunk, buffer_source,
- UnionTypeConversionMode::kNotNullable, exception_state);
- if (exception_state.HadException()) {
+ auto* buffer_source = V8BufferSource::Create(script_state_->GetIsolate(),
+ chunk, exception_state);
+ if (exception_state.HadException())
return ScriptPromise();
- }
- if (buffer_source.IsArrayBufferView()) {
- const auto* view = buffer_source.GetAsArrayBufferView().Get();
- const uint8_t* start = static_cast<const uint8_t*>(view->BaseAddress());
- size_t length = view->byteLength();
- if (length > std::numeric_limits<wtf_size_t>::max()) {
- exception_state.ThrowRangeError(
- "Buffer size exceeds maximum heap object size.");
- return ScriptPromise();
- }
- Deflate(start, static_cast<wtf_size_t>(length), IsFinished(false),
- controller, exception_state);
- return ScriptPromise::CastUndefined(script_state_);
- }
- DCHECK(buffer_source.IsArrayBuffer());
- const auto* array_buffer = buffer_source.GetAsArrayBuffer();
- const uint8_t* start = static_cast<const uint8_t*>(array_buffer->Data());
- size_t length = array_buffer->ByteLength();
- if (length > std::numeric_limits<wtf_size_t>::max()) {
+ DOMArrayPiece array_piece(buffer_source);
+ if (array_piece.ByteLength() > std::numeric_limits<wtf_size_t>::max()) {
exception_state.ThrowRangeError(
"Buffer size exceeds maximum heap object size.");
return ScriptPromise();
}
- Deflate(start, static_cast<wtf_size_t>(length), IsFinished(false), controller,
- exception_state);
-
+ Deflate(array_piece.Bytes(),
+ static_cast<wtf_size_t>(array_piece.ByteLength()), IsFinished(false),
+ controller, exception_state);
return ScriptPromise::CastUndefined(script_state_);
}
diff --git a/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h
index 16d70ae5bf6..26d40a2ee06 100644
--- a/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h
+++ b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_
#include "base/types/strong_alias.h"
-
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/modules/compression/idls.gni b/chromium/third_party/blink/renderer/modules/compression/idls.gni
deleted file mode 100644
index d986709dc5d..00000000000
--- a/chromium/third_party/blink/renderer/modules/compression/idls.gni
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "compression_stream.idl",
- "decompression_stream.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc
index b052abe307b..f4ba1bcb17f 100644
--- a/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc
+++ b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc
@@ -4,17 +4,18 @@
#include "third_party/blink/renderer/modules/compression/inflate_transformer.h"
-#include <string.h>
#include <algorithm>
+#include <cstring>
#include <limits>
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.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_uint8_array.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/compression/compression_format.h"
#include "third_party/blink/renderer/modules/compression/zlib_partition_alloc.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -54,39 +55,19 @@ ScriptPromise InflateTransformer::Transform(
v8::Local<v8::Value> chunk,
TransformStreamDefaultController* controller,
ExceptionState& exception_state) {
- // TODO(canonmukai): Support SharedArrayBuffer.
- ArrayBufferOrArrayBufferView buffer_source;
- V8ArrayBufferOrArrayBufferView::ToImpl(
- script_state_->GetIsolate(), chunk, buffer_source,
- UnionTypeConversionMode::kNotNullable, exception_state);
- if (exception_state.HadException()) {
+ auto* buffer_source = V8BufferSource::Create(script_state_->GetIsolate(),
+ chunk, exception_state);
+ if (exception_state.HadException())
return ScriptPromise();
- }
- if (buffer_source.IsArrayBufferView()) {
- const auto* view = buffer_source.GetAsArrayBufferView().Get();
- const uint8_t* start = static_cast<const uint8_t*>(view->BaseAddress());
- size_t length = view->byteLength();
- if (length > std::numeric_limits<wtf_size_t>::max()) {
- exception_state.ThrowRangeError(
- "Buffer size exceeds maximum heap object size.");
- return ScriptPromise();
- }
- Inflate(start, static_cast<wtf_size_t>(length), IsFinished(false),
- controller, exception_state);
- return ScriptPromise::CastUndefined(script_state_);
- }
- DCHECK(buffer_source.IsArrayBuffer());
- const auto* array_buffer = buffer_source.GetAsArrayBuffer();
- const uint8_t* start = static_cast<const uint8_t*>(array_buffer->Data());
- size_t length = array_buffer->ByteLength();
- if (length > std::numeric_limits<wtf_size_t>::max()) {
+ DOMArrayPiece array_piece(buffer_source);
+ if (array_piece.ByteLength() > std::numeric_limits<wtf_size_t>::max()) {
exception_state.ThrowRangeError(
"Buffer size exceeds maximum heap object size.");
return ScriptPromise();
}
- Inflate(start, static_cast<wtf_size_t>(length), IsFinished(false), controller,
- exception_state);
-
+ Inflate(array_piece.Bytes(),
+ static_cast<wtf_size_t>(array_piece.ByteLength()), IsFinished(false),
+ controller, exception_state);
return ScriptPromise::CastUndefined(script_state_);
}
diff --git a/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h
index ac01659f96d..b602cdc8132 100644
--- a/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h
+++ b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_INFLATE_TRANSFORMER_H_
#include "base/types/strong_alias.h"
-
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/modules/compute_pressure/compute_pressure_observer.cc b/chromium/third_party/blink/renderer/modules/compute_pressure/compute_pressure_observer.cc
index e9feea6b771..324a6d32505 100644
--- a/chromium/third_party/blink/renderer/modules/compute_pressure/compute_pressure_observer.cc
+++ b/chromium/third_party/blink/renderer/modules/compute_pressure/compute_pressure_observer.cc
@@ -9,10 +9,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/bindings/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_compute_pressure_observer_options.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_compute_pressure_observer_update.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/compute_pressure/compute_pressure_observer_options.h"
-#include "third_party/blink/renderer/modules/compute_pressure/compute_pressure_observer_update.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/heap/heap.h"
@@ -160,12 +160,12 @@ void ComputePressureObserver::stop(ScriptState* script_state) {
}
void ComputePressureObserver::Trace(blink::Visitor* visitor) const {
- ScriptWrappable::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
visitor->Trace(observer_callback_);
visitor->Trace(normalized_options_);
visitor->Trace(compute_pressure_host_);
visitor->Trace(receiver_);
+ ScriptWrappable::Trace(visitor);
+ ExecutionContextLifecycleStateObserver::Trace(visitor);
}
void ComputePressureObserver::OnUpdate(
diff --git a/chromium/third_party/blink/renderer/modules/compute_pressure/idls.gni b/chromium/third_party/blink/renderer/modules/compute_pressure/idls.gni
deleted file mode 100644
index c5401c5a781..00000000000
--- a/chromium/third_party/blink/renderer/modules/compute_pressure/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "compute_pressure_observer.idl" ]
-
-modules_callback_function_idl_files = [ "compute_pressure_update_callback.idl" ]
-
-modules_dictionary_idl_files = [
- "compute_pressure_observer_update.idl",
- "compute_pressure_observer_options.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc
index a70f0beed0c..a94d1e2737f 100644
--- a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/contacts_picker/contacts_manager.h"
-#include "base/stl_util.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_contact_info.h"
diff --git a/chromium/third_party/blink/renderer/modules/contacts_picker/idls.gni b/chromium/third_party/blink/renderer/modules/contacts_picker/idls.gni
deleted file mode 100644
index af35464b6be..00000000000
--- a/chromium/third_party/blink/renderer/modules/contacts_picker/idls.gni
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "contact_address.idl",
- "contacts_manager.idl",
-]
-
-modules_dictionary_idl_files = [
- "contact_info.idl",
- "contacts_select_options.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_contacts.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/content_index/idls.gni b/chromium/third_party/blink/renderer/modules/content_index/idls.gni
deleted file mode 100644
index ecd395aa12d..00000000000
--- a/chromium/third_party/blink/renderer/modules/content_index/idls.gni
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "content_index.idl",
- "content_index_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "content_description.idl",
- "content_icon_definition.idl",
- "content_index_event_init.idl",
-]
-
-modules_dependency_idl_files = [
- "service_worker_global_scope_content_index.idl",
- "service_worker_registration_content_index.idl",
-]
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 ccb4af1fea2..7b909911867 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
@@ -109,8 +109,7 @@ CookieListItem* CookieChangeEvent::ToCookieListItem(
if (!is_deleted) {
list_item->setValue(String::FromUTF8(canonical_cookie.Value()));
if (canonical_cookie.ExpiryDate().is_null()) {
- // TODO(crbug.com/1070871): Use absl::nullopt instead.
- list_item->setExpiresToNull();
+ list_item->setExpires(absl::nullopt);
} else {
list_item->setExpires(ConvertSecondsToDOMTimeStamp(
canonical_cookie.ExpiryDate().ToDoubleT()));
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 73c8f6578d7..9e42692ca0d 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
@@ -12,6 +12,7 @@
#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
#include "third_party/abseil-cpp/absl/types/optional.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_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_cookie_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_cookie_list_item.h"
@@ -151,11 +152,13 @@ std::unique_ptr<net::CanonicalCookie> ToCanonicalCookie(
}
// TODO(crbug.com/1144187): Add support for SameParty attribute.
+ // TODO(crbug.com/1225444): Add support for Partitioned attrbute.
return net::CanonicalCookie::CreateSanitizedCookie(
cookie_url, name.Utf8(), value.Utf8(), domain.Utf8(), path.Utf8(),
base::Time() /*creation*/, expires, base::Time() /*last_access*/,
true /*secure*/, false /*http_only*/, same_site,
- net::CookiePriority::COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ net::CookiePriority::COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/);
}
const KURL DefaultCookieURL(ExecutionContext* execution_context) {
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/idls.gni b/chromium/third_party/blink/renderer/modules/cookie_store/idls.gni
deleted file mode 100644
index 16de1d6cb2e..00000000000
--- a/chromium/third_party/blink/renderer/modules/cookie_store/idls.gni
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "cookie_change_event.idl",
- "cookie_store.idl",
- "cookie_store_manager.idl",
- "extendable_cookie_change_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "cookie_change_event_init.idl",
- "cookie_init.idl",
- "cookie_list_item.idl",
- "cookie_store_delete_options.idl",
- "cookie_store_get_options.idl",
- "extendable_cookie_change_event_init.idl",
-]
-
-modules_dependency_idl_files = [
- "service_worker_global_scope_cookie_store.idl",
- "service_worker_registration_cookies.idl",
- "window_cookie_store.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/OWNERS b/chromium/third_party/blink/renderer/modules/credentialmanager/OWNERS
index d19e950583f..b52f3066146 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/OWNERS
@@ -1,4 +1,3 @@
-mkwst@chromium.org
vasilii@chromium.org
file://device/fido/OWNERS
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 1e6318a7f37..534c35da4cb 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
@@ -32,4 +32,10 @@ dictionary AuthenticationExtensionsClientInputs {
// https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html#sctn-credBlob-extension
BufferSource credBlob;
boolean getCredBlob;
+
+ // Legacy compatibility extension for U2F migration https://groups.google.com/a/chromium.org/g/blink-dev/c/xHC3AtU_65A.
+ boolean googleLegacyAppidSupport;
+
+ // https://github.com/w3c/secure-payment-confirmation
+ [RuntimeEnabled=SecurePaymentConfirmation] AuthenticationExtensionsPaymentInputs payment;
};
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_payment_inputs.idl b/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_payment_inputs.idl
new file mode 100644
index 00000000000..c6580f199cd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_payment_inputs.idl
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/secure-payment-confirmation/#dom-authenticationextensionsclientinputs-payment
+
+dictionary AuthenticationExtensionsPaymentInputs {
+ boolean isPayment;
+};
+
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.cc
index d5f410d6f60..afed7aada87 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.cc
@@ -4,7 +4,30 @@
#include "third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h"
+#include <utility>
+
namespace blink {
+namespace {
+
+DOMArrayBuffer* VectorToDOMArrayBuffer(const Vector<uint8_t> buffer) {
+ return DOMArrayBuffer::Create(static_cast<const void*>(buffer.data()),
+ buffer.size());
+}
+
+} // namespace
+
+AuthenticatorAssertionResponse::AuthenticatorAssertionResponse(
+ const Vector<uint8_t> client_data_json,
+ const Vector<uint8_t> authenticator_data,
+ const Vector<uint8_t> signature,
+ const absl::optional<Vector<uint8_t>> optional_user_handle)
+ : AuthenticatorAssertionResponse(
+ VectorToDOMArrayBuffer(client_data_json),
+ VectorToDOMArrayBuffer(authenticator_data),
+ VectorToDOMArrayBuffer(signature),
+ optional_user_handle && optional_user_handle->size() > 0
+ ? VectorToDOMArrayBuffer(std::move(*optional_user_handle))
+ : nullptr) {}
AuthenticatorAssertionResponse::AuthenticatorAssertionResponse(
DOMArrayBuffer* client_data_json,
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h b/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h
index 897395989ab..ab33675cd52 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h
@@ -5,10 +5,14 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_AUTHENTICATOR_ASSERTION_RESPONSE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_AUTHENTICATOR_ASSERTION_RESPONSE_H_
+#include <stdint.h>
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/credentialmanager/authenticator_response.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/wtf/vector.h"
namespace blink {
@@ -17,10 +21,20 @@ class MODULES_EXPORT AuthenticatorAssertionResponse final
DEFINE_WRAPPERTYPEINFO();
public:
- explicit AuthenticatorAssertionResponse(DOMArrayBuffer* client_data_json,
- DOMArrayBuffer* authenticator_data,
- DOMArrayBuffer* signature,
- DOMArrayBuffer* user_handle);
+ // It is recommended to use std::move() for the Vector parameters into this
+ // constructor to avoid copying potentially large chunks of memory. Note this
+ // constructor will std::move() the Vector from `optional_user_handle`, if
+ // present.
+ AuthenticatorAssertionResponse(
+ const Vector<uint8_t> client_data_json,
+ const Vector<uint8_t> authenticator_data,
+ const Vector<uint8_t> signature,
+ const absl::optional<Vector<uint8_t>> optional_user_handle);
+
+ AuthenticatorAssertionResponse(DOMArrayBuffer* client_data_json,
+ DOMArrayBuffer* authenticator_data,
+ DOMArrayBuffer* signature,
+ DOMArrayBuffer* user_handle);
~AuthenticatorAssertionResponse() override;
DOMArrayBuffer* authenticatorData() const {
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 287e63bbc91..e1419515525 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
@@ -10,9 +10,11 @@
#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_inputs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_inputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_payment_inputs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authenticator_selection_criteria.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_cable_authentication_data.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_cable_registration_data.h"
@@ -22,6 +24,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_request_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_rp_entity.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_user_entity.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/credentialmanager/credential.h"
#include "third_party/blink/renderer/modules/credentialmanager/federated_credential.h"
#include "third_party/blink/renderer/modules/credentialmanager/password_credential.h"
@@ -170,6 +173,10 @@ TypeConverter<CredentialManagerError, AuthenticatorStatus>::Convert(
case blink::mojom::blink::AuthenticatorStatus::
INVALID_ALLOW_CREDENTIALS_FOR_LARGE_BLOB:
return CredentialManagerError::INVALID_ALLOW_CREDENTIALS_FOR_LARGE_BLOB;
+ case blink::mojom::blink::AuthenticatorStatus::
+ FAILED_TO_SAVE_CREDENTIAL_ID_FOR_PAYMENT_EXTENSION:
+ return CredentialManagerError::
+ FAILED_TO_SAVE_CREDENTIAL_ID_FOR_PAYMENT_EXTENSION;
case blink::mojom::blink::AuthenticatorStatus::SUCCESS:
NOTREACHED();
break;
@@ -180,38 +187,33 @@ TypeConverter<CredentialManagerError, AuthenticatorStatus>::Convert(
}
// static helper method.
-Vector<uint8_t> ConvertFixedSizeArray(
- const blink::ArrayBufferOrArrayBufferView& buffer,
- unsigned length) {
- if (buffer.IsArrayBuffer() &&
- (buffer.GetAsArrayBuffer()->ByteLength() != length)) {
- return Vector<uint8_t>();
- }
-
- if (buffer.IsArrayBufferView() &&
- buffer.GetAsArrayBufferView()->byteLength() != length) {
- return Vector<uint8_t>();
- }
+Vector<uint8_t> ConvertFixedSizeArray(const blink::V8BufferSource* buffer,
+ unsigned length) {
+ if (blink::DOMArrayPiece(buffer).ByteLength() != length)
+ return {};
return ConvertTo<Vector<uint8_t>>(buffer);
}
// static
Vector<uint8_t>
-TypeConverter<Vector<uint8_t>, blink::ArrayBufferOrArrayBufferView>::Convert(
- const blink::ArrayBufferOrArrayBufferView& buffer) {
- DCHECK(!buffer.IsNull());
+TypeConverter<Vector<uint8_t>, blink::V8UnionArrayBufferOrArrayBufferView*>::
+ Convert(const blink::V8UnionArrayBufferOrArrayBufferView* buffer) {
+ DCHECK(buffer);
Vector<uint8_t> vector;
- if (buffer.IsArrayBuffer()) {
- vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
- base::checked_cast<wtf_size_t>(
- buffer.GetAsArrayBuffer()->ByteLength()));
- } else {
- DCHECK(buffer.IsArrayBufferView());
- vector.Append(
- static_cast<uint8_t*>(buffer.GetAsArrayBufferView()->BaseAddress()),
- base::checked_cast<wtf_size_t>(
- buffer.GetAsArrayBufferView()->byteLength()));
+ switch (buffer->GetContentType()) {
+ case blink::V8UnionArrayBufferOrArrayBufferView::ContentType::kArrayBuffer:
+ vector.Append(static_cast<uint8_t*>(buffer->GetAsArrayBuffer()->Data()),
+ base::checked_cast<wtf_size_t>(
+ buffer->GetAsArrayBuffer()->ByteLength()));
+ break;
+ case blink::V8UnionArrayBufferOrArrayBufferView::ContentType::
+ kArrayBufferView:
+ vector.Append(
+ static_cast<uint8_t*>(buffer->GetAsArrayBufferView()->BaseAddress()),
+ base::checked_cast<wtf_size_t>(
+ buffer->GetAsArrayBufferView()->byteLength()));
+ break;
}
return vector;
}
@@ -584,6 +586,14 @@ TypeConverter<PublicKeyCredentialCreationOptionsPtr,
mojo_options->cred_blob =
ConvertTo<Vector<uint8_t>>(extensions->credBlob());
}
+ if (extensions->hasGoogleLegacyAppidSupport()) {
+ mojo_options->google_legacy_app_id_support =
+ extensions->googleLegacyAppidSupport();
+ }
+ if (extensions->hasPayment() && extensions->payment()->hasIsPayment() &&
+ extensions->payment()->isPayment()) {
+ mojo_options->is_payment_credential_creation = true;
+ }
}
return mojo_options;
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 fe48abdfa4d..f8090fcb190 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
@@ -14,7 +14,6 @@
namespace blink {
class AuthenticatorSelectionCriteria;
-class ArrayBufferOrArrayBufferView;
class CableAuthenticationData;
class CableRegistrationData;
class Credential;
@@ -25,6 +24,7 @@ class PublicKeyCredentialRequestOptions;
class PublicKeyCredentialRpEntity;
class PublicKeyCredentialUserEntity;
class UserVerificationRequirement;
+class V8UnionArrayBufferOrArrayBufferView;
} // namespace blink
namespace mojo {
@@ -53,8 +53,10 @@ struct TypeConverter<blink::mojom::blink::CredentialManagerError,
};
template <>
-struct TypeConverter<Vector<uint8_t>, blink::ArrayBufferOrArrayBufferView> {
- static Vector<uint8_t> Convert(const blink::ArrayBufferOrArrayBufferView&);
+struct TypeConverter<Vector<uint8_t>,
+ blink::V8UnionArrayBufferOrArrayBufferView*> {
+ static Vector<uint8_t> Convert(
+ const blink::V8UnionArrayBufferOrArrayBufferView*);
};
template <>
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 53b140b50ed..e1f614b6303 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -20,10 +20,12 @@
#include "third_party/blink/public/mojom/sms/webotp_service.mojom-blink.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_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_inputs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_outputs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_inputs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_outputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_payment_inputs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_authenticator_selection_criteria.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_credential_creation_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_credential_properties_output.h"
@@ -37,6 +39,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_request_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_rp_entity.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_user_entity.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_htmlformelement_passwordcredentialdata.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -293,20 +296,21 @@ bool IsIconURLNullOrSecure(const KURL& url) {
// Checks if the size of the supplied ArrayBuffer or ArrayBufferView is at most
// the maximum size allowed.
bool IsArrayBufferOrViewBelowSizeLimit(
- ArrayBufferOrArrayBufferView buffer_or_view) {
- if (buffer_or_view.IsNull())
+ const V8UnionArrayBufferOrArrayBufferView* buffer_or_view) {
+ if (!buffer_or_view)
return true;
-
- if (buffer_or_view.IsArrayBuffer()) {
- return base::CheckedNumeric<wtf_size_t>(
- buffer_or_view.GetAsArrayBuffer()->ByteLength())
- .IsValid();
+ switch (buffer_or_view->GetContentType()) {
+ case V8UnionArrayBufferOrArrayBufferView::ContentType::kArrayBuffer:
+ return base::CheckedNumeric<wtf_size_t>(
+ buffer_or_view->GetAsArrayBuffer()->ByteLength())
+ .IsValid();
+ case V8UnionArrayBufferOrArrayBufferView::ContentType::kArrayBufferView:
+ return base::CheckedNumeric<wtf_size_t>(
+ buffer_or_view->GetAsArrayBufferView()->byteLength())
+ .IsValid();
}
-
- DCHECK(buffer_or_view.IsArrayBufferView());
- return base::CheckedNumeric<wtf_size_t>(
- buffer_or_view.GetAsArrayBufferView()->byteLength())
- .IsValid();
+ NOTREACHED();
+ return false;
}
DOMException* CredentialManagerErrorToDOMException(
@@ -419,6 +423,12 @@ DOMException* CredentialManagerErrorToDOMException(
DOMExceptionCode::kNotReadableError,
"An unknown error occurred while talking "
"to the credential manager.");
+ case CredentialManagerError::
+ FAILED_TO_SAVE_CREDENTIAL_ID_FOR_PAYMENT_EXTENSION:
+ return MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotReadableError,
+ "Failed to save the credential identifier for the 'payment' "
+ "extension.");
case CredentialManagerError::SUCCESS:
NOTREACHED();
break;
@@ -567,6 +577,48 @@ void OnMakePublicKeyCredentialComplete(
credential->info->id, raw_id, authenticator_response, extension_outputs));
}
+void OnSaveCredentialIdForPaymentExtension(
+ std::unique_ptr<ScopedPromiseResolver> scoped_resolver,
+ MakeCredentialAuthenticatorResponsePtr credential,
+ PaymentCredentialStorageStatus storage_status) {
+ auto status = AuthenticatorStatus::SUCCESS;
+ if (storage_status != PaymentCredentialStorageStatus::SUCCESS) {
+ status =
+ AuthenticatorStatus::FAILED_TO_SAVE_CREDENTIAL_ID_FOR_PAYMENT_EXTENSION;
+ credential = nullptr;
+ }
+ OnMakePublicKeyCredentialComplete(std::move(scoped_resolver), status,
+ std::move(credential));
+}
+
+void OnMakePublicKeyCredentialWithPaymentExtensionComplete(
+ std::unique_ptr<ScopedPromiseResolver> scoped_resolver,
+ const String& rp_id_for_payment_extension,
+ AuthenticatorStatus status,
+ MakeCredentialAuthenticatorResponsePtr credential) {
+ auto* resolver = scoped_resolver->Release();
+ const auto required_origin_type = RequiredOriginType::kSecure;
+
+ AssertSecurityRequirementsBeforeResponse(resolver, required_origin_type);
+ if (status != AuthenticatorStatus::SUCCESS) {
+ DCHECK(!credential);
+ resolver->Reject(CredentialManagerErrorToDOMException(
+ mojo::ConvertTo<CredentialManagerError>(status)));
+ return;
+ }
+
+ Vector<uint8_t> credential_id = credential->info->raw_id;
+ auto* payment_credential_remote =
+ CredentialManagerProxy::From(resolver->GetScriptState())
+ ->PaymentCredential();
+ payment_credential_remote->StorePaymentCredentialAndHideUserPrompt(
+ PaymentCredentialInstrument::New(/*display_name=*/"", /*icon=*/KURL()),
+ std::move(credential_id), rp_id_for_payment_extension,
+ WTF::Bind(&OnSaveCredentialIdForPaymentExtension,
+ std::make_unique<ScopedPromiseResolver>(resolver),
+ std::move(credential)));
+}
+
void OnGetAssertionComplete(
std::unique_ptr<ScopedPromiseResolver> scoped_resolver,
AuthenticatorStatus status,
@@ -582,23 +634,11 @@ void OnGetAssertionComplete(
UseCounter::Count(
resolver->GetExecutionContext(),
WebFeature::kCredentialManagerGetPublicKeyCredentialSuccess);
- DOMArrayBuffer* client_data_buffer =
- VectorToDOMArrayBuffer(std::move(credential->info->client_data_json));
- DOMArrayBuffer* raw_id =
- VectorToDOMArrayBuffer(std::move(credential->info->raw_id));
-
- DOMArrayBuffer* authenticator_buffer =
- VectorToDOMArrayBuffer(std::move(credential->info->authenticator_data));
- DOMArrayBuffer* signature_buffer =
- VectorToDOMArrayBuffer(std::move(credential->signature));
- DOMArrayBuffer* user_handle =
- (credential->user_handle && credential->user_handle->size() > 0)
- ? VectorToDOMArrayBuffer(std::move(*credential->user_handle))
- : nullptr;
auto* authenticator_response =
MakeGarbageCollected<AuthenticatorAssertionResponse>(
- client_data_buffer, authenticator_buffer, signature_buffer,
- user_handle);
+ std::move(credential->info->client_data_json),
+ std::move(credential->info->authenticator_data),
+ std::move(credential->signature), credential->user_handle);
AuthenticationExtensionsClientOutputs* extension_outputs =
AuthenticationExtensionsClientOutputs::Create();
if (credential->echo_appid_extension) {
@@ -635,8 +675,9 @@ void OnGetAssertionComplete(
}
}
resolver->Resolve(MakeGarbageCollected<PublicKeyCredential>(
- credential->info->id, raw_id, authenticator_response,
- extension_outputs));
+ credential->info->id,
+ VectorToDOMArrayBuffer(std::move(credential->info->raw_id)),
+ authenticator_response, extension_outputs));
return;
}
DCHECK(!credential);
@@ -647,7 +688,7 @@ void OnGetAssertionComplete(
void OnSmsReceive(ScriptPromiseResolver* resolver,
base::TimeTicks start_time,
mojom::blink::SmsStatus status,
- const WTF::String& otp) {
+ const String& otp) {
AssertSecurityRequirementsBeforeResponse(
resolver, resolver->GetExecutionContext()->IsFeatureEnabled(
mojom::blink::PermissionsPolicyFeature::kOTPCredentials)
@@ -715,7 +756,7 @@ void OnPaymentCredentialCreationComplete(
client_data_buffer, attestation_buffer, credential->transports,
authenticator_data, public_key_der, credential->public_key_algo);
- resolver->Resolve(MakeGarbageCollected<PaymentCredential>(
+ resolver->Resolve(MakeGarbageCollected<PublicKeyCredential>(
credential->info->id, raw_id, authenticator_response,
AuthenticationExtensionsClientOutputs::Create()));
}
@@ -789,15 +830,17 @@ void DidDownloadPaymentCredentialIconAndShowUserPrompt(
WrapPersistent(options)));
}
-void CreatePublicKeyCredentialForPaymentCredential(
+void OnIsUserVerifyingPlatformAuthenticatorAvailableForPaymentCredentialCreate(
const PaymentCredentialCreationOptions* options,
- ScriptPromiseResolver* resolver) {
+ std::unique_ptr<ScopedPromiseResolver> scoped_resolver,
+ bool is_available) {
// TODO(kenrb): Much of this could eventually be deduplicated with the
// PublicKeyCredential handling code in CredentialsContainer::create(), but
// it is preferable to keep these separate during the experimentation stage
// for SecurePaymentConfirmation because this is subject to a lot of change
// and possibly removal.
+ auto* resolver = scoped_resolver->Release();
if (!options->rp() || !options->rp()->hasId() || !options->instrument() ||
!options->instrument()->displayName() || !options->instrument()->icon()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -821,6 +864,14 @@ void CreatePublicKeyCredentialForPaymentCredential(
if (!RuntimeEnabledFeatures::SecurePaymentConfirmationDebugEnabled()) {
// PaymentCredentials is only supported with user-verifying authenticators.
+ if (!is_available) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotAllowedError,
+ "A user verifying platform authenticator is required for payments.",
+ "NotAllowedError"));
+ return;
+ }
+
auto selection_criteria =
mojom::blink::AuthenticatorSelectionCriteria::New();
selection_criteria->authenticator_attachment =
@@ -910,17 +961,106 @@ void CreatePublicKeyCredentialForPaymentCredential(
mojo_options->is_payment_credential_creation = true;
- // Download instrument icon and prompt the user before creating the
- // credential.
- auto* payment_credential_remote =
- CredentialManagerProxy::From(resolver->GetScriptState())
- ->PaymentCredential();
- payment_credential_remote->DownloadIconAndShowUserPrompt(
- PaymentCredentialInstrument::New(options->instrument()->displayName(),
- KURL(options->instrument()->icon())),
- WTF::Bind(&DidDownloadPaymentCredentialIconAndShowUserPrompt,
- std::make_unique<ScopedPromiseResolver>(resolver),
- std::move(mojo_options), WrapPersistent(options)));
+ // SecurePaymentConfirmationAPIV3 skips downloading instrument icon and
+ // showing user prompt.
+ if (RuntimeEnabledFeatures::SecurePaymentConfirmationAPIV3Enabled()) {
+ auto* authenticator =
+ CredentialManagerProxy::From(resolver->GetScriptState())
+ ->Authenticator();
+ authenticator->MakeCredential(
+ std::move(mojo_options),
+ WTF::Bind(&OnMakePublicKeyCredentialForPaymentComplete,
+ std::make_unique<ScopedPromiseResolver>(resolver),
+ WrapPersistent(options)));
+ } else {
+ // Download instrument icon and prompt the user before creating the
+ // credential.
+ auto* payment_credential_remote =
+ CredentialManagerProxy::From(resolver->GetScriptState())
+ ->PaymentCredential();
+ payment_credential_remote->DownloadIconAndShowUserPrompt(
+ PaymentCredentialInstrument::New(options->instrument()->displayName(),
+ KURL(options->instrument()->icon())),
+ WTF::Bind(&DidDownloadPaymentCredentialIconAndShowUserPrompt,
+ std::make_unique<ScopedPromiseResolver>(resolver),
+ std::move(mojo_options), WrapPersistent(options)));
+ }
+}
+
+void CreatePublicKeyCredentialForPaymentCredential(
+ const PaymentCredentialCreationOptions* options,
+ ScriptPromiseResolver* resolver) {
+ auto* authenticator =
+ CredentialManagerProxy::From(resolver->GetScriptState())->Authenticator();
+ authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(WTF::Bind(
+ &OnIsUserVerifyingPlatformAuthenticatorAvailableForPaymentCredentialCreate,
+ WrapPersistent(options),
+ std::make_unique<ScopedPromiseResolver>(resolver)));
+}
+
+// Validates the "payment" extension for public key credential creation. The
+// function rejects the promise before returning in this case.
+bool IsPaymentExtensionValid(const CredentialCreationOptions* options,
+ ScriptPromiseResolver* resolver) {
+ const auto* payment = options->publicKey()->extensions()->payment();
+ if (!payment->hasIsPayment() || !payment->isPayment())
+ return true;
+
+ const auto* context = resolver->GetExecutionContext();
+ DCHECK(RuntimeEnabledFeatures::SecurePaymentConfirmationEnabled(context));
+
+ if (!context->IsFeatureEnabled(
+ mojom::blink::PermissionsPolicyFeature::kPayment)) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "The 'payment' feature is not enabled in this document. Permissions "
+ "Policy may be used to delegate Web Payment capabilities to "
+ "cross-origin child frames."));
+ return false;
+ }
+
+ if (RuntimeEnabledFeatures::SecurePaymentConfirmationDebugEnabled())
+ return true;
+
+ if (!options->publicKey()->hasAuthenticatorSelection()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "A user verifying platform authenticator with resident key support is "
+ "required for 'payment' extension."));
+ return false;
+ }
+
+ const auto* authenticator = options->publicKey()->authenticatorSelection();
+ if (!authenticator->hasUserVerification() ||
+ authenticator->userVerification() != "required") {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "User verification is required for 'payment' extension."));
+ return false;
+ }
+
+ if ((!authenticator->hasResidentKey() &&
+ !authenticator->hasRequireResidentKey()) ||
+ (authenticator->hasResidentKey() &&
+ authenticator->residentKey() != "required") ||
+ (!authenticator->hasResidentKey() &&
+ authenticator->hasRequireResidentKey() &&
+ !authenticator->requireResidentKey())) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "A resident key is required for 'payment' extension."));
+ return false;
+ }
+
+ if (!authenticator->hasAuthenticatorAttachment() ||
+ authenticator->authenticatorAttachment() != "platform") {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "A platform authenticator is required for 'payment' extension."));
+ return false;
+ }
+
+ return true;
}
} // namespace
@@ -1022,6 +1162,20 @@ ScriptPromise CredentialsContainer::get(
return promise;
}
}
+ if (options->publicKey()->extensions()->hasGoogleLegacyAppidSupport()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "The 'googleLegacyAppidSupport' extension is only valid when "
+ "creating a credential"));
+ return promise;
+ }
+ if (options->publicKey()->extensions()->hasPayment()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "The 'payment' extension is only valid when creating a "
+ "credential"));
+ return promise;
+ }
}
if (!options->publicKey()->hasUserVerification()) {
@@ -1215,12 +1369,13 @@ ScriptPromise CredentialsContainer::create(
if (options->hasPassword()) {
resolver->Resolve(
- options->password().IsPasswordCredentialData()
+ options->password()->IsPasswordCredentialData()
? PasswordCredential::Create(
- options->password().GetAsPasswordCredentialData(),
+ options->password()->GetAsPasswordCredentialData(),
exception_state)
: PasswordCredential::Create(
- options->password().GetAsHTMLFormElement(), exception_state));
+ options->password()->GetAsHTMLFormElement(),
+ exception_state));
return promise;
}
if (options->hasFederated()) {
@@ -1323,6 +1478,24 @@ ScriptPromise CredentialsContainer::create(
return promise;
}
}
+ if (options->publicKey()->extensions()->hasGoogleLegacyAppidSupport()) {
+ const auto& rp_id =
+ options->publicKey()->rp()->id()
+ ? options->publicKey()->rp()->id()
+ : resolver->GetExecutionContext()->GetSecurityOrigin()->Domain();
+ if (rp_id != "google.com") {
+ resolver->DomWindow()->AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "The 'googleLegacyAppidSupport' extension is ignored for "
+ "requests with an 'rp.id' not equal to 'google.com'"));
+ }
+ }
+ if (options->publicKey()->extensions()->hasPayment() &&
+ !IsPaymentExtensionValid(options, resolver)) {
+ return promise;
+ }
}
if (options->hasSignal()) {
@@ -1361,6 +1534,7 @@ ScriptPromise CredentialsContainer::create(
"Ignoring unknown publicKey.authenticatorSelection.residentKey "
"value"));
}
+
auto mojo_options =
MojoPublicKeyCredentialCreationOptions::From(*options->publicKey());
if (!mojo_options) {
@@ -1398,10 +1572,19 @@ ScriptPromise CredentialsContainer::create(
auto* authenticator =
CredentialManagerProxy::From(script_state)->Authenticator();
- authenticator->MakeCredential(
- std::move(mojo_options),
- WTF::Bind(&OnMakePublicKeyCredentialComplete,
- std::make_unique<ScopedPromiseResolver>(resolver)));
+ if (mojo_options->is_payment_credential_creation) {
+ String rp_id_for_payment_extension = mojo_options->relying_party->id;
+ authenticator->MakeCredential(
+ std::move(mojo_options),
+ WTF::Bind(&OnMakePublicKeyCredentialWithPaymentExtensionComplete,
+ std::make_unique<ScopedPromiseResolver>(resolver),
+ rp_id_for_payment_extension));
+ } else {
+ authenticator->MakeCredential(
+ std::move(mojo_options),
+ WTF::Bind(&OnMakePublicKeyCredentialComplete,
+ std::make_unique<ScopedPromiseResolver>(resolver)));
+ }
}
return promise;
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 0463d18e65d..7b2b6340f88 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
@@ -16,6 +16,7 @@
#include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-blink.h"
#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/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_credential_creation_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_credential_request_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_creation_options.h"
@@ -249,8 +250,8 @@ TEST(CredentialsContainerTest,
auto* user_options = PublicKeyCredentialUserEntity::Create();
int dummy_buffer_source = 1;
- auto dummy_buffer =
- ArrayBufferOrArrayBufferView::FromArrayBuffer(DOMArrayBuffer::Create(
+ auto* dummy_buffer =
+ MakeGarbageCollected<V8BufferSource>(DOMArrayBuffer::Create(
&dummy_buffer_source, sizeof(dummy_buffer_source)));
user_options->setId(dummy_buffer);
user_options->setIcon("invalid URL");
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/idls.gni b/chromium/third_party/blink/renderer/modules/credentialmanager/idls.gni
deleted file mode 100644
index 8feeabfc6c4..00000000000
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/idls.gni
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "authenticator_assertion_response.idl",
- "authenticator_attestation_response.idl",
- "authenticator_response.idl",
- "credential.idl",
- "credentials_container.idl",
- "federated_credential.idl",
- "otp_credential.idl",
- "password_credential.idl",
- "payment_credential.idl",
- "public_key_credential.idl",
-]
-
-modules_dictionary_idl_files = [
- "authentication_extensions_client_inputs.idl",
- "authentication_extensions_client_outputs.idl",
- "authentication_extensions_large_blob_inputs.idl",
- "authentication_extensions_large_blob_outputs.idl",
- "authenticator_selection_criteria.idl",
- "cable_authentication_data.idl",
- "cable_registration_data.idl",
- "collected_client_data.idl",
- "credential_creation_options.idl",
- "credential_data.idl",
- "credential_request_options.idl",
- "credential_properties_output.idl",
- "federated_credential_init.idl",
- "federated_credential_request_options.idl",
- "otp_credential_request_options.idl",
- "password_credential_data.idl",
- "payment_credential_creation_options.idl",
- "payment_credential_instrument.idl",
- "public_key_credential_creation_options.idl",
- "public_key_credential_descriptor.idl",
- "public_key_credential_entity.idl",
- "public_key_credential_parameters.idl",
- "public_key_credential_request_options.idl",
- "public_key_credential_rp_entity.idl",
- "public_key_credential_user_entity.idl",
-]
-
-modules_dependency_idl_files = [
- "credential_user_data.idl",
- "navigator_credentials.idl",
-]
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 0cbe27f1601..d4521ac6951 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
@@ -65,19 +65,11 @@ PasswordCredential* PasswordCredential::Create(
// https://html.spec.whatwg.org/C/#constructing-the-form-data-set
DCHECK(!submittable_element->GetName().IsEmpty());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8FormDataEntryValue* value =
form_data->get(submittable_element->GetName());
if (!value || !value->IsUSVString())
continue;
const String& usv_string_value = value->GetAsUSVString();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- FileOrUSVString value;
- form_data->get(submittable_element->GetName(), value);
- if (!value.IsUSVString())
- continue;
- const String& usv_string_value = value.GetAsUSVString();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Vector<String> autofill_tokens;
submittable_element->ToHTMLElement()
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto.cc b/chromium/third_party/blink/renderer/modules/crypto/crypto.cc
index e192f0cd0bf..544390dd7f1 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto.cc
@@ -45,7 +45,9 @@ bool IsIntegerArray(NotShared<DOMArrayBufferView> array) {
type == DOMArrayBufferView::kTypeInt16 ||
type == DOMArrayBufferView::kTypeUint16 ||
type == DOMArrayBufferView::kTypeInt32 ||
- type == DOMArrayBufferView::kTypeUint32;
+ type == DOMArrayBufferView::kTypeUint32 ||
+ type == DOMArrayBufferView::kTypeBigInt64 ||
+ type == DOMArrayBufferView::kTypeBigUint64;
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto.h b/chromium/third_party/blink/renderer/modules/crypto/crypto.h
index d86528aa4c0..5d2ab8c0b6a 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto.h
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto.h
@@ -29,6 +29,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CRYPTO_CRYPTO_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CRYPTO_CRYPTO_H_
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/modules/crypto/subtle_crypto.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/modules/crypto/crypto_key.cc b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
index b6ff20c8b9f..373ffb3bfd9 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
@@ -30,12 +30,12 @@
#include "third_party/blink/renderer/modules/crypto/crypto_key.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#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/v8_object_builder.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.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/to_v8.h"
#include "third_party/blink/renderer/platform/crypto_result.h"
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto_key.h b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.h
index 8b6d3156f5d..13eb7309631 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto_key.h
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CRYPTO_CRYPTO_KEY_H_
#include "third_party/blink/public/platform/web_crypto_key.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/modules/crypto/normalize_algorithm.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.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 35cd210a771..263214567dd 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
@@ -34,7 +34,6 @@
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.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"
#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/bindings/modules/v8/v8_crypto_key.h"
diff --git a/chromium/third_party/blink/renderer/modules/crypto/idls.gni b/chromium/third_party/blink/renderer/modules/crypto/idls.gni
deleted file mode 100644
index 3e3e2433ea8..00000000000
--- a/chromium/third_party/blink/renderer/modules/crypto/idls.gni
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "crypto.idl",
- "crypto_key.idl",
- "subtle_crypto.idl",
-]
-
-modules_dictionary_idl_files = [
- "json_web_key.idl",
- "rsa_other_primes_info.idl",
-]
-
-modules_dependency_idl_files = [
- "window_crypto.idl",
- "worker_global_scope_crypto.idl",
-]
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 dfb08da5a57..c666a6968bf 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
@@ -33,14 +33,11 @@
#include <algorithm>
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/char_traits.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.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_union_object_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
@@ -300,14 +297,23 @@ bool GetOptionalBufferSource(const Dictionary& raw,
has_property = true;
if (v8_value->IsArrayBufferView()) {
- bytes = CopyBytes(
- V8ArrayBufferView::ToImpl(v8::Local<v8::Object>::Cast(v8_value)));
+ DOMArrayBufferView* array_buffer_view =
+ NativeValueTraits<NotShared<DOMArrayBufferView>>::NativeValue(
+ raw.GetIsolate(), v8_value, exception_state)
+ .Get();
+ if (exception_state.HadException())
+ return false;
+ bytes = CopyBytes(array_buffer_view);
return true;
}
if (v8_value->IsArrayBuffer()) {
- bytes =
- CopyBytes(V8ArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(v8_value)));
+ DOMArrayBuffer* array_buffer =
+ NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ raw.GetIsolate(), v8_value, exception_state);
+ if (exception_state.HadException())
+ return false;
+ bytes = CopyBytes(array_buffer);
return true;
}
@@ -497,7 +503,6 @@ bool GetOptionalUint8(const Dictionary& raw,
return true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8AlgorithmIdentifier* GetAlgorithmIdentifier(v8::Isolate* isolate,
const Dictionary& raw,
const char* property_name,
@@ -524,36 +529,6 @@ V8AlgorithmIdentifier* GetAlgorithmIdentifier(v8::Isolate* isolate,
return MakeGarbageCollected<V8AlgorithmIdentifier>(algorithm_name);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-bool GetAlgorithmIdentifier(v8::Isolate* isolate,
- const Dictionary& raw,
- const char* property_name,
- AlgorithmIdentifier& value,
- const ErrorContext& context,
- ExceptionState& exception_state) {
- // FIXME: This is not correct: http://crbug.com/438060
- // (1) It may retrieve the property twice from the dictionary, whereas it
- // should be reading the v8 value once to avoid issues with getters.
- // (2) The value is stringified (whereas the spec says it should be an
- // instance of DOMString).
- Dictionary dictionary;
- if (raw.Get(property_name, dictionary) && dictionary.IsObject()) {
- value.SetObject(ScriptValue(isolate, dictionary.V8Value()));
- return true;
- }
-
- String algorithm_name;
- if (!DictionaryHelper::Get(raw, property_name, algorithm_name)) {
- SetTypeError(context.ToString(property_name,
- "Missing or not an AlgorithmIdentifier"),
- exception_state);
- return false;
- }
-
- value.SetString(algorithm_name);
- return true;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Defined by the WebCrypto spec as:
//
@@ -590,11 +565,7 @@ bool ParseAesKeyGenParams(const Dictionary& raw,
}
bool ParseAlgorithmIdentifier(v8::Isolate*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8AlgorithmIdentifier&,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebCryptoOperation,
WebCryptoAlgorithm&,
ErrorContext,
@@ -605,7 +576,6 @@ bool ParseHash(v8::Isolate* isolate,
WebCryptoAlgorithm& hash,
ErrorContext context,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8AlgorithmIdentifier* raw_hash =
GetAlgorithmIdentifier(isolate, raw, "hash", context, exception_state);
if (!raw_hash) {
@@ -616,16 +586,6 @@ bool ParseHash(v8::Isolate* isolate,
context.Add("hash");
return ParseAlgorithmIdentifier(isolate, *raw_hash, kWebCryptoOperationDigest,
hash, context, exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- AlgorithmIdentifier raw_hash;
- if (!GetAlgorithmIdentifier(isolate, raw, "hash", raw_hash, context,
- exception_state))
- return false;
-
- context.Add("hash");
- return ParseAlgorithmIdentifier(isolate, raw_hash, kWebCryptoOperationDigest,
- hash, context, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
// Defined by the WebCrypto spec as:
@@ -1217,11 +1177,7 @@ bool ParseAlgorithmDictionary(v8::Isolate* isolate,
}
bool ParseAlgorithmIdentifier(v8::Isolate* isolate,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8AlgorithmIdentifier& raw,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier& raw,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebCryptoOperation op,
WebCryptoAlgorithm& algorithm,
ErrorContext context,
@@ -1254,22 +1210,13 @@ bool ParseAlgorithmIdentifier(v8::Isolate* isolate,
} // namespace
bool NormalizeAlgorithm(v8::Isolate* isolate,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8AlgorithmIdentifier* raw,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier& raw,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebCryptoOperation op,
WebCryptoAlgorithm& algorithm,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(raw);
return ParseAlgorithmIdentifier(isolate, *raw, op, algorithm, ErrorContext(),
exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return ParseAlgorithmIdentifier(isolate, raw, op, algorithm, ErrorContext(),
- exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.h b/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.h
index f515fd2773b..59c3a548434 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.h
+++ b/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.h
@@ -34,16 +34,13 @@
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/modules/v8/object_or_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "v8/include/v8.h"
namespace blink {
-using AlgorithmIdentifier = ObjectOrString;
+class ExceptionState;
// Converts a javascript AlgorithmIdentifier to a WebCryptoAlgorithm object.
//
@@ -59,11 +56,7 @@ using AlgorithmIdentifier = ObjectOrString;
// https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
MODULES_EXPORT WARN_UNUSED_RESULT bool NormalizeAlgorithm(
v8::Isolate*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8AlgorithmIdentifier*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebCryptoOperation,
WebCryptoAlgorithm&,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.cc b/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.cc
index 143d906d74a..a99fe63a763 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.cc
@@ -31,14 +31,13 @@
#include "third_party/blink/renderer/modules/crypto/subtle_crypto.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.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_crypto.h"
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/modules/v8/array_buffer_or_array_buffer_view_or_json_web_key.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_json_web_key.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_arraybuffer_arraybufferview_jsonwebkey.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
@@ -115,19 +114,11 @@ static bool ParseJsonWebKey(const JsonWebKey& key,
SubtleCrypto::SubtleCrypto() = default;
ScriptPromise SubtleCrypto::encrypt(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
CryptoKey* key,
const V8BufferSource* raw_data,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- CryptoKey* key,
- const BufferSource& raw_data,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-encrypt
@@ -169,19 +160,11 @@ ScriptPromise SubtleCrypto::encrypt(
}
ScriptPromise SubtleCrypto::decrypt(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
CryptoKey* key,
const V8BufferSource* raw_data,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- CryptoKey* key,
- const BufferSource& raw_data,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-decrypt
@@ -223,19 +206,11 @@ ScriptPromise SubtleCrypto::decrypt(
}
ScriptPromise SubtleCrypto::sign(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
CryptoKey* key,
const V8BufferSource* raw_data,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- CryptoKey* key,
- const BufferSource& raw_data,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-sign
@@ -277,21 +252,12 @@ ScriptPromise SubtleCrypto::sign(
}
ScriptPromise SubtleCrypto::verifySignature(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
CryptoKey* key,
const V8BufferSource* raw_signature,
const V8BufferSource* raw_data,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- CryptoKey* key,
- const BufferSource& raw_signature,
- const BufferSource& raw_data,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-verify
@@ -337,17 +303,10 @@ ScriptPromise SubtleCrypto::verifySignature(
}
ScriptPromise SubtleCrypto::digest(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
const V8BufferSource* raw_data,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- const BufferSource& raw_data,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-digest
@@ -377,19 +336,11 @@ ScriptPromise SubtleCrypto::digest(
}
ScriptPromise SubtleCrypto::generateKey(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
bool extractable,
const Vector<String>& raw_key_usages,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- bool extractable,
- const Vector<String>& raw_key_usages,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-generateKey
@@ -426,7 +377,6 @@ ScriptPromise SubtleCrypto::generateKey(
}
ScriptPromise SubtleCrypto::importKey(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const String& raw_format,
const V8UnionBufferSourceOrJsonWebKey* raw_key_data,
@@ -434,15 +384,6 @@ ScriptPromise SubtleCrypto::importKey(
bool extractable,
const Vector<String>& raw_key_usages,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const String& raw_format,
- const ArrayBufferOrArrayBufferViewOrJsonWebKey& raw_key_data,
- const AlgorithmIdentifier& raw_algorithm,
- bool extractable,
- const Vector<String>& raw_key_usages,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-importKey
@@ -473,7 +414,6 @@ ScriptPromise SubtleCrypto::importKey(
case kWebCryptoKeyFormatRaw:
case kWebCryptoKeyFormatPkcs8:
case kWebCryptoKeyFormatSpki:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (raw_key_data->GetContentType()) {
case V8UnionBufferSourceOrJsonWebKey::ContentType::kArrayBuffer:
key_data = CopyBytes(raw_key_data->GetAsArrayBuffer());
@@ -487,18 +427,6 @@ ScriptPromise SubtleCrypto::importKey(
"Key data must be a BufferSource for non-JWK formats");
return promise;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (raw_key_data.IsArrayBuffer()) {
- key_data = CopyBytes(raw_key_data.GetAsArrayBuffer());
- } else if (raw_key_data.IsArrayBufferView()) {
- key_data = CopyBytes(raw_key_data.GetAsArrayBufferView().Get());
- } else {
- result->CompleteWithError(
- kWebCryptoErrorTypeType,
- "Key data must be a BufferSource for non-JWK formats");
- return promise;
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
break;
// 14.3.9.2: If format is equal to the string "jwk":
//
@@ -508,7 +436,6 @@ ScriptPromise SubtleCrypto::importKey(
// (2) Let keyData be the keyData parameter passed to the importKey
// method.
case kWebCryptoKeyFormatJwk:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!raw_key_data->IsJsonWebKey()) {
result->CompleteWithError(kWebCryptoErrorTypeType,
"Key data must be an object for JWK import");
@@ -516,16 +443,6 @@ ScriptPromise SubtleCrypto::importKey(
}
if (!ParseJsonWebKey(*raw_key_data->GetAsJsonWebKey(), key_data, result))
return promise;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (raw_key_data.IsJsonWebKey()) {
- if (!ParseJsonWebKey(*raw_key_data.GetAsJsonWebKey(), key_data, result))
- return promise;
- } else {
- result->CompleteWithError(kWebCryptoErrorTypeType,
- "Key data must be an object for JWK import");
- return promise;
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
break;
}
@@ -584,11 +501,7 @@ ScriptPromise SubtleCrypto::wrapKey(
const String& raw_format,
CryptoKey* key,
CryptoKey* wrapping_key,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8AlgorithmIdentifier* raw_wrap_algorithm,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier& raw_wrap_algorithm,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-wrapKey
@@ -648,7 +561,6 @@ ScriptPromise SubtleCrypto::wrapKey(
}
ScriptPromise SubtleCrypto::unwrapKey(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const String& raw_format,
const V8BufferSource* raw_wrapped_key,
@@ -658,17 +570,6 @@ ScriptPromise SubtleCrypto::unwrapKey(
bool extractable,
const Vector<String>& raw_key_usages,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const String& raw_format,
- const BufferSource& raw_wrapped_key,
- CryptoKey* unwrapping_key,
- const AlgorithmIdentifier& raw_unwrap_algorithm,
- const AlgorithmIdentifier& raw_unwrapped_key_algorithm,
- bool extractable,
- const Vector<String>& raw_key_usages,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-unwrapKey
@@ -743,11 +644,7 @@ ScriptPromise SubtleCrypto::unwrapKey(
ScriptPromise SubtleCrypto::deriveBits(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8AlgorithmIdentifier* raw_algorithm,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier& raw_algorithm,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
CryptoKey* base_key,
unsigned length_bits,
ExceptionState& exception_state) {
@@ -788,7 +685,6 @@ ScriptPromise SubtleCrypto::deriveBits(
}
ScriptPromise SubtleCrypto::deriveKey(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptState* script_state,
const V8AlgorithmIdentifier* raw_algorithm,
CryptoKey* base_key,
@@ -796,15 +692,6 @@ ScriptPromise SubtleCrypto::deriveKey(
bool extractable,
const Vector<String>& raw_key_usages,
ExceptionState& exception_state
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptState* script_state,
- const AlgorithmIdentifier& raw_algorithm,
- CryptoKey* base_key,
- const AlgorithmIdentifier& raw_derived_key_type,
- bool extractable,
- const Vector<String>& raw_key_usages,
- ExceptionState& exception_state
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
// Method described by:
// https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-deriveKey
diff --git a/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.h b/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.h
index 922b4ff9dda..9219c0b6ba6 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.h
+++ b/chromium/third_party/blink/renderer/modules/crypto/subtle_crypto.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CRYPTO_SUBTLE_CRYPTO_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CRYPTO_SUBTLE_CRYPTO_H_
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
@@ -42,99 +41,47 @@
namespace blink {
-class ArrayBufferOrArrayBufferViewOrJsonWebKey;
class CryptoKey;
-using BufferSource = ArrayBufferOrArrayBufferView;
-
class SubtleCrypto final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
SubtleCrypto();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise encrypt(ScriptState*,
const V8AlgorithmIdentifier*,
CryptoKey*,
const V8BufferSource*,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise encrypt(ScriptState*,
- const AlgorithmIdentifier&,
- CryptoKey*,
- const BufferSource&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise decrypt(ScriptState*,
const V8AlgorithmIdentifier*,
CryptoKey*,
const V8BufferSource*,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise decrypt(ScriptState*,
- const AlgorithmIdentifier&,
- CryptoKey*,
- const BufferSource&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise sign(ScriptState*,
const V8AlgorithmIdentifier*,
CryptoKey*,
const V8BufferSource*,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise sign(ScriptState*,
- const AlgorithmIdentifier&,
- CryptoKey*,
- const BufferSource&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// Note that this is not named "verify" because when compiling on Mac that
// expands to a macro and breaks.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise verifySignature(ScriptState*,
const V8AlgorithmIdentifier*,
CryptoKey*,
const V8BufferSource* signature,
const V8BufferSource* data,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise verifySignature(ScriptState*,
- const AlgorithmIdentifier&,
- CryptoKey*,
- const BufferSource& signature,
- const BufferSource& data,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise digest(ScriptState*,
const V8AlgorithmIdentifier*,
const V8BufferSource* data,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise digest(ScriptState*,
- const AlgorithmIdentifier&,
- const BufferSource& data,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise generateKey(ScriptState*,
const V8AlgorithmIdentifier*,
bool extractable,
const Vector<String>& key_usages,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise generateKey(ScriptState*,
- const AlgorithmIdentifier&,
- bool extractable,
- const Vector<String>& key_usages,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise importKey(ScriptState*,
const String&,
const V8UnionBufferSourceOrJsonWebKey*,
@@ -142,33 +89,14 @@ class SubtleCrypto final : public ScriptWrappable {
bool extractable,
const Vector<String>& key_usages,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise importKey(ScriptState*,
- const String&,
- const ArrayBufferOrArrayBufferViewOrJsonWebKey&,
- const AlgorithmIdentifier&,
- bool extractable,
- const Vector<String>& key_usages,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise exportKey(ScriptState*, const String&, CryptoKey*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise wrapKey(ScriptState*,
const String&,
CryptoKey*,
CryptoKey*,
const V8AlgorithmIdentifier*,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise wrapKey(ScriptState*,
- const String&,
- CryptoKey*,
- CryptoKey*,
- const AlgorithmIdentifier&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise unwrapKey(ScriptState*,
const String&,
const V8BufferSource*,
@@ -178,32 +106,12 @@ class SubtleCrypto final : public ScriptWrappable {
bool,
const Vector<String>&,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise unwrapKey(ScriptState*,
- const String&,
- const BufferSource&,
- CryptoKey*,
- const AlgorithmIdentifier&,
- const AlgorithmIdentifier&,
- bool,
- const Vector<String>&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise deriveBits(ScriptState*,
const V8AlgorithmIdentifier*,
CryptoKey*,
unsigned,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise deriveBits(ScriptState*,
- const AlgorithmIdentifier&,
- CryptoKey*,
- unsigned,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise deriveKey(ScriptState*,
const V8AlgorithmIdentifier*,
CryptoKey*,
@@ -211,15 +119,6 @@ class SubtleCrypto final : public ScriptWrappable {
bool extractable,
const Vector<String>&,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise deriveKey(ScriptState*,
- const AlgorithmIdentifier&,
- CryptoKey*,
- const AlgorithmIdentifier&,
- bool extractable,
- const Vector<String>&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn b/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn
index 48cd55d5699..d372e6484ef 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn
@@ -6,10 +6,6 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("csspaint") {
sources = [
- "background_color_paint_image_generator_impl.cc",
- "background_color_paint_image_generator_impl.h",
- "background_color_paint_worklet.cc",
- "background_color_paint_worklet.h",
"css_paint_definition.cc",
"css_paint_definition.h",
"css_paint_image_generator_impl.cc",
@@ -18,9 +14,16 @@ blink_modules_sources("csspaint") {
"css_paint_worklet.h",
"document_paint_definition.cc",
"document_paint_definition.h",
- "native_paint_worklet.cc",
- "native_paint_worklet.h",
- "native_paint_worklet_proxy_client.h",
+ "nativepaint/background_color_paint_definition.cc",
+ "nativepaint/background_color_paint_definition.h",
+ "nativepaint/background_color_paint_image_generator_impl.cc",
+ "nativepaint/background_color_paint_image_generator_impl.h",
+ "nativepaint/clip_path_paint_definition.cc",
+ "nativepaint/clip_path_paint_definition.h",
+ "nativepaint/clip_path_paint_image_generator_impl.cc",
+ "nativepaint/clip_path_paint_image_generator_impl.h",
+ "nativepaint/native_paint_definition.h",
+ "paint_definition.h",
"paint_rendering_context_2d.cc",
"paint_rendering_context_2d.h",
"paint_size.h",
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/OWNERS b/chromium/third_party/blink/renderer/modules/csspaint/OWNERS
index cffe5fc12a3..eb3a0a7688c 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/csspaint/OWNERS
@@ -1,3 +1,2 @@
flackr@chromium.org
-ikilpatrick@chromium.org
xidachen@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/README.md b/chromium/third_party/blink/renderer/modules/csspaint/README.md
index 26a07ad805c..41982460bfc 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/README.md
+++ b/chromium/third_party/blink/renderer/modules/csspaint/README.md
@@ -11,11 +11,12 @@ of this feature, as well as [Samples](https://github.com/GoogleChromeLabs/houdin
## Workflow
Historically the CSS Paint API (PaintWorklet) implementation ran on the main
-thread, but is currently being optimized to run on the compositor thread. We
-will use an example to show the workflow of both cases.
+thread. It has been optimized to run on the compositor thread. We will use an
+example to show the workflow of both cases.
Here is a simple example of using PaintWorklet to draw something on the screen.
+``` html
<style>
#demo {
background-image: paint(foo);
@@ -23,7 +24,7 @@ Here is a simple example of using PaintWorklet to draw something on the screen.
height: 200px;
}
</style>
-<script>
+<script id="code" type="text/worklet">
registerPaint('foo', class {
paint(ctx, size) {
ctx.fillStyle = 'green';
@@ -31,21 +32,48 @@ registerPaint('foo', class {
}
});
</script>
+<script>
+var code = document.getElementById('code').textContent;
+var blob = new Blob([code], {type : 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob));
+</script>
+```
In our implementation, there is one [PaintWorklet](paint_worklet.h) instance
-created from the frame. There are two
-[PaintWorkletGlobalScope](paint_worklet_global_scope.h) created to enforce
-stateless. The number of global scopes can be arbitrary, and our implementation
-chose two.
+created from the frame.
+
+### Main thread workflow
+
+Let's start with the two web-exposed APIs and dive into the main thread
+workflow. Specifically the two APIs are `addModule` and `registerPaint`.
+
+When `addModule` is executed, `Worklet::addModule` is called. There are two
+[PaintWorkletGlobalScope](paint_worklet_global_scope.h) created, and the
+[PaintWorkletGlobalScopeProxy](paint_worklet_global_scope_proxy.h) serves as the
+proxy when other classes need to communicate with PaintWorkletGlobalScope. We
+create two PaintWorkletGlobalScope to enforce stateless. The number of global
+scopes can be arbitrary as long as it is >= 2, and we chose two in our
+implementation.
-During `PaintWorkletGlobalScope#registerPaint`, the Javascript inside the paint
+`registerPaint` is executed on each PaintWorkletGlobalScope. When the
+`PaintWorkletGlobalScope::registerPaint` is called, it creates a
+[CSSPaintDefinition](css_paint_definition.h) and PaintWorkletGlobalScope owns
+it. Besides that, it creates
+[DocumentPaintDefinition](document_paint_definition.h) which is owned by
+PaintWorklet. It then registers the CSSPaintDefinition to the
+DocumentPaintDefinition.
+
+Below is a diagram that shows what happens when `addModule` and `registerPaint`
+are called:
+
+![addModule and registerPaint call](images/addModule_registerPaint.png)
+
+During `PaintWorkletGlobalScope::registerPaint`, the Javascript inside the paint
function is turned into a V8 paint callback. We randomly choose one of the two
global scopes to execute the callback. The execution of the callback
produces a PaintRecord, which contains a set of skia draw commands. The V8 paint
callback is executed on a shared V8 isolate.
-### Main thread workflow
-
During the main thread paint, the `PaintWorklet::Paint` is called, which
executes the V8 paint callback synchronously. A PaintRecord is produced and
passed to the compositor thread to raster.
@@ -53,6 +81,10 @@ passed to the compositor thread to raster.
When animation is involved, the main thread animation system updates the value
of the animated properties, which are used by the `PaintWorklet::Paint`.
+Below is a diagram that shows what happens when `PaintWorklet::Paint` is called.
+
+![PaintWorklet::Paint](images/PaintWorklet_Paint.png)
+
### Off main thread workflow
Let's see how it works without animations.
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h b/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h
deleted file mode 100644
index 9473ebe65ed..00000000000
--- a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_BACKGROUND_COLOR_PAINT_WORKLET_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_BACKGROUND_COLOR_PAINT_WORKLET_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
-#include "third_party/blink/renderer/modules/csspaint/native_paint_worklet.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/geometry/float_size.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-namespace blink {
-
-class Image;
-class LocalFrame;
-class Node;
-
-class MODULES_EXPORT BackgroundColorPaintWorklet : public NativePaintWorklet {
- DISALLOW_COPY_AND_ASSIGN(BackgroundColorPaintWorklet);
-
- public:
- static BackgroundColorPaintWorklet* Create(LocalFrame&);
-
- explicit BackgroundColorPaintWorklet(LocalFrame&);
- ~BackgroundColorPaintWorklet() final;
-
- // The |container_size| is without subpixel snapping.
- scoped_refptr<Image> Paint(const FloatSize& container_size,
- const Node*,
- const Vector<Color>& animated_colors,
- const Vector<double>& offsets,
- const absl::optional<double>& progress);
-
- // Get the animated colors and offsets from the animation keyframes. Moreover,
- // we obtain the progress of the animation from the main thread, such that if
- // the animation failed to run on the compositor thread, we can still paint
- // the element off the main thread with that progress + the keyframes.
- // Returning false meaning that we cannot paint background color with
- // BackgroundColorPaintWorklet.
- // A side effect of this is that it will ensure a unique_id exists.
- static bool GetBGColorPaintWorkletParams(Node* node,
- Vector<Color>* animated_colors,
- Vector<double>* offsets,
- absl::optional<double>* progress);
-
- // Shared code that is being called in multiple places.
- static Animation* GetAnimationIfCompositable(const Element* element);
-
- // For testing purpose only.
- static sk_sp<cc::PaintRecord> ProxyClientPaintForTest(
- const Vector<Color>& animated_colors,
- const Vector<double>& offsets,
- const CompositorPaintWorkletJob::AnimatedPropertyValues&
- animated_property_values);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_BACKGROUND_COLOR_PAINT_WORKLET_H_
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 2b801859836..d7e5c26fca7 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
@@ -10,14 +10,17 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_no_argument_constructor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_paint_callback.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_color_value.h"
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h"
#include "third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h"
#include "third_party/blink/renderer/modules/csspaint/paint_size.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/graphics/paint_generated_image.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -53,6 +56,32 @@ CSSPaintDefinition::CSSPaintDefinition(
CSSPaintDefinition::~CSSPaintDefinition() = default;
+// PaintDefinition override
+sk_sp<PaintRecord> CSSPaintDefinition::Paint(
+ const CompositorPaintWorkletInput* compositor_input,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&
+ animated_property_values) {
+ const CSSPaintWorkletInput* input =
+ To<CSSPaintWorkletInput>(compositor_input);
+ PaintWorkletStylePropertyMap* style_map =
+ MakeGarbageCollected<PaintWorkletStylePropertyMap>(input->StyleMapData());
+ CSSStyleValueVector paint_arguments;
+ for (const auto& style_value : input->ParsedInputArguments()) {
+ paint_arguments.push_back(style_value->ToCSSStyleValue());
+ }
+
+ ApplyAnimatedPropertyOverrides(style_map, animated_property_values);
+
+ sk_sp<PaintRecord> result =
+ Paint(FloatSize(input->GetSize()), input->EffectiveZoom(), style_map,
+ &paint_arguments, input->DeviceScaleFactor());
+
+ // Return empty record if paint fails.
+ if (!result)
+ result = sk_make_sp<PaintRecord>();
+ return result;
+}
+
sk_sp<PaintRecord> CSSPaintDefinition::Paint(
const FloatSize& container_size,
float zoom,
@@ -95,6 +124,44 @@ sk_sp<PaintRecord> CSSPaintDefinition::Paint(
return rendering_context->GetRecord();
}
+void CSSPaintDefinition::ApplyAnimatedPropertyOverrides(
+ PaintWorkletStylePropertyMap* style_map,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&
+ animated_property_values) {
+ for (const auto& property_value : animated_property_values) {
+ DCHECK(property_value.second.has_value());
+ String property_name(
+ property_value.first.custom_property_name.value().c_str());
+ DCHECK(style_map->StyleMapData().Contains(property_name));
+ CrossThreadStyleValue* old_value =
+ style_map->StyleMapData().at(property_name);
+ switch (old_value->GetType()) {
+ case CrossThreadStyleValue::StyleValueType::kUnitType: {
+ DCHECK(property_value.second.float_value);
+ std::unique_ptr<CrossThreadUnitValue> new_value =
+ std::make_unique<CrossThreadUnitValue>(
+ property_value.second.float_value.value(),
+ DynamicTo<CrossThreadUnitValue>(old_value)->GetUnitType());
+ style_map->StyleMapData().Set(property_name, std::move(new_value));
+ break;
+ }
+ case CrossThreadStyleValue::StyleValueType::kColorType: {
+ DCHECK(property_value.second.color_value);
+ SkColor sk_color = property_value.second.color_value.value();
+ Color color(MakeRGBA(SkColorGetR(sk_color), SkColorGetG(sk_color),
+ SkColorGetB(sk_color), SkColorGetA(sk_color)));
+ std::unique_ptr<CrossThreadColorValue> new_value =
+ std::make_unique<CrossThreadColorValue>(color);
+ style_map->StyleMapData().Set(property_name, std::move(new_value));
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
void CSSPaintDefinition::MaybeCreatePaintInstance() {
if (did_call_constructor_)
return;
@@ -115,6 +182,7 @@ void CSSPaintDefinition::Trace(Visitor* visitor) const {
visitor->Trace(instance_);
visitor->Trace(context_settings_);
visitor->Trace(script_state_);
+ PaintDefinition::Trace(visitor);
}
} // 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 bf10dc8e1fd..ccc5ba1537d 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
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_definition.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"
@@ -21,6 +22,7 @@
namespace blink {
+class PaintWorkletStylePropertyMap;
class ScriptState;
class StylePropertyMapReadOnly;
class V8NoArgumentConstructor;
@@ -31,7 +33,8 @@ class V8PaintCallback;
// types as well.
class MODULES_EXPORT CSSPaintDefinition final
: public GarbageCollected<CSSPaintDefinition>,
- public NameClient {
+ public NameClient,
+ public PaintDefinition {
public:
CSSPaintDefinition(
ScriptState*,
@@ -41,7 +44,12 @@ class MODULES_EXPORT CSSPaintDefinition final
const Vector<AtomicString>& custom_invalidation_properties,
const Vector<CSSSyntaxDefinition>& input_argument_types,
const PaintRenderingContext2DSettings*);
- virtual ~CSSPaintDefinition();
+ ~CSSPaintDefinition() override;
+
+ // PaintDefinition override
+ sk_sp<PaintRecord> Paint(
+ const CompositorPaintWorkletInput*,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&) override;
// Invokes the javascript 'paint' callback on an instance of the javascript
// class. The size given will be the size of the PaintRenderingContext2D
@@ -72,13 +80,17 @@ class MODULES_EXPORT CSSPaintDefinition final
ScriptState* GetScriptState() const { return script_state_; }
- virtual void Trace(Visitor* visitor) const;
+ void Trace(Visitor* visitor) const override;
const char* NameInHeapSnapshot() const override {
return "CSSPaintDefinition";
}
private:
void MaybeCreatePaintInstance();
+ void ApplyAnimatedPropertyOverrides(
+ PaintWorkletStylePropertyMap* style_map,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&
+ animated_property_values);
Member<ScriptState> script_state_;
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc
index e7764e28d41..2e960873f54 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc
@@ -61,7 +61,8 @@ scoped_refptr<Image> CSSPaintImageGeneratorImpl::Paint(
}
bool CSSPaintImageGeneratorImpl::HasDocumentDefinition() const {
- return paint_worklet_->GetDocumentDefinitionMap().at(name_);
+ return paint_worklet_->GetDocumentDefinitionMap().DeprecatedAtOrEmptyValue(
+ name_);
}
bool CSSPaintImageGeneratorImpl::GetValidDocumentDefinition(
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition_test.cc
index 99c36c8958f..5249c810748 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition_test.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition_test.cc
@@ -30,7 +30,7 @@ TEST(DocumentPaintDefinitionTest, NativeInvalidationProperties) {
custom_invalidation_properties,
input_argument_types, true);
EXPECT_EQ(document_definition.NativeInvalidationProperties().size(), 3u);
- for (size_t i = 0; i < 3; i++) {
+ for (wtf_size_t i = 0; i < 3; i++) {
EXPECT_EQ(native_invalidation_properties[i],
document_definition.NativeInvalidationProperties()[i]);
}
@@ -48,7 +48,7 @@ TEST(DocumentPaintDefinitionTest, CustomInvalidationProperties) {
custom_invalidation_properties,
input_argument_types, true);
EXPECT_EQ(document_definition.CustomInvalidationProperties().size(), 2u);
- for (size_t i = 0; i < 2; i++) {
+ for (wtf_size_t i = 0; i < 2; i++) {
EXPECT_EQ(custom_invalidation_properties[i],
document_definition.CustomInvalidationProperties()[i]);
}
@@ -82,7 +82,7 @@ TEST(DocumentPaintDefinitionTest, InputArgumentTypes) {
input_argument_types, true);
EXPECT_EQ(document_definition.InputArgumentTypes().size(), 2u);
- for (size_t i = 0; i < 2; i++) {
+ for (wtf_size_t i = 0; i < 2; i++) {
EXPECT_EQ(input_argument_types[i],
document_definition.InputArgumentTypes()[i]);
}
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/idls.gni b/chromium/third_party/blink/renderer/modules/csspaint/idls.gni
deleted file mode 100644
index 2395e7fef58..00000000000
--- a/chromium/third_party/blink/renderer/modules/csspaint/idls.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "paint_rendering_context_2d.idl",
- "paint_size.idl",
- "paint_worklet_global_scope.idl",
-]
-
-modules_dictionary_idl_files = [ "paint_rendering_context_2d_settings.idl" ]
-
-modules_dependency_idl_files = [ "css_paint_worklet.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png b/chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png
new file mode 100644
index 00000000000..1dc7fb43558
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png
Binary files differ
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot b/chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot
new file mode 100644
index 00000000000..e44bbcabdb4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot
@@ -0,0 +1,7 @@
+// dot -Tpng third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot > third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png
+// When making modifications run the above command to regenerate the diagram
+
+digraph {
+ label = "Workflow of main thread paint worklet";
+ "CSSPaintImageGeneratorImpl\::Paint" -> "PaintWorklet\::Paint" -> FindAvaiableGlobalScope -> FindDefinition -> "CSSPaintDefinition\::Paint";
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png b/chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png
new file mode 100644
index 00000000000..d1a483674ad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png
Binary files differ
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot b/chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot
new file mode 100644
index 00000000000..05cbf8159de
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot
@@ -0,0 +1,9 @@
+// dot -Tpng third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot > third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png
+// When making modifications run the above command to regenerate the diagram
+
+digraph {
+ label = "Workflow of addModule and registerPaint";
+ addModule -> CreateGlobalScope;
+ registerPaint -> "Create CSSPaintDefinition";
+ registerPaint -> RegisterCSSPaintDefinition -> "Create DocumentPaintDefinition";
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc b/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
deleted file mode 100644
index a9b42d21c15..00000000000
--- a/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/csspaint/native_paint_worklet.h"
-
-#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/modules/csspaint/native_paint_worklet_proxy_client.h"
-#include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
-#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-
-namespace blink {
-
-NativePaintWorklet::NativePaintWorklet(LocalFrame& local_root)
- : worklet_id_(PaintWorkletIdGenerator::NextId()) {
- DCHECK(local_root.IsLocalRoot());
- paint_dispatcher_ =
- WebLocalFrameImpl::FromFrame(local_root)
- ->FrameWidgetImpl()
- ->EnsureCompositorPaintDispatcher(&compositor_host_queue_);
- DCHECK(IsMainThread());
- ThreadCreationParams params(ThreadType::kDedicatedWorkerThread);
- // TODO(crbug.com/1143407): We don't need this thread if we can make the
- // compositor thread support GC.
- worker_thread_ = Thread::CreateThread(params.SetSupportsGC(true));
-}
-
-void NativePaintWorklet::RegisterProxyClient(
- NativePaintWorkletProxyClient* client) {
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- worker_thread_->GetTaskRunner();
- // At this moment, we are in the paint phase which is before commit, we queue
- // a task to the compositor thread to register the |paint_dispatcher_|. When
- // compositor schedules the actual paint job (PaintWorkletPainter::Paint),
- // which is after commit, the |paint_dispatcher_| should have been registerted
- // and ready to use.
- PostCrossThreadTask(
- *compositor_host_queue_, FROM_HERE,
- CrossThreadBindOnce(
- &PaintWorkletPaintDispatcher::RegisterPaintWorkletPainter,
- paint_dispatcher_, WrapCrossThreadPersistent(client), task_runner));
-}
-
-void NativePaintWorklet::UnregisterProxyClient() {
- PostCrossThreadTask(
- *compositor_host_queue_, FROM_HERE,
- CrossThreadBindOnce(
- &PaintWorkletPaintDispatcher::UnregisterPaintWorkletPainter,
- paint_dispatcher_, worklet_id_));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h b/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h
deleted file mode 100644
index 501803f0a6e..00000000000
--- a/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/geometry/float_size.h"
-#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-namespace blink {
-
-class LocalFrame;
-class NativePaintWorkletProxyClient;
-class PaintWorkletPaintDispatcher;
-class SingleThreadTaskRunner;
-class Thread;
-
-// NativePaintWorklet contains the shared information by all kinds of native
-// paint worklet. We allow the instance creation of its subclasses, but not this
-// class. Each subclass would have its own implementation of the Paint function.
-// For example, the BackgroundColorPaintWorklet takes a SkColor in its Paint
-// function.
-class MODULES_EXPORT NativePaintWorklet
- : public GarbageCollected<NativePaintWorklet> {
- DISALLOW_COPY_AND_ASSIGN(NativePaintWorklet);
-
- public:
- virtual ~NativePaintWorklet() = default;
-
- int WorkletId() const { return worklet_id_; }
-
- // Register the NativePaintWorkletProxyClient to the compositor thread that
- // will hold a cross thread persistent pointer to it. This should be called
- // during the construction of native paint worklets, to ensure that the proxy
- // client is ready on the compositor thread when dispatching a paint job.
- void RegisterProxyClient(NativePaintWorkletProxyClient*);
-
- // Unregister the painter to ensure that there is no memory leakage on the
- // compositor thread.
- void UnregisterProxyClient();
-
- virtual void Trace(Visitor*) const {}
-
- protected:
- explicit NativePaintWorklet(LocalFrame& local_root);
-
- int worklet_id_;
- base::WeakPtr<PaintWorkletPaintDispatcher> paint_dispatcher_;
- scoped_refptr<base::SingleThreadTaskRunner> compositor_host_queue_;
- // The worker thread that does the paint work.
- std::unique_ptr<Thread> worker_thread_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet_proxy_client.h b/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet_proxy_client.h
deleted file mode 100644
index 81b51abec98..00000000000
--- a/chromium/third_party/blink/renderer/modules/csspaint/native_paint_worklet_proxy_client.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_PROXY_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_PROXY_CLIENT_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/graphics/paint_worklet_painter.h"
-
-namespace blink {
-
-// This class contains the shared bits for all kinds of
-// NativePaintWorkletProxyClient. Instance creation of this class is not
-// allowed, but its subclasses are allowed. Each subclass should have its own
-// implementation of the Paint function from the PaintWorkletPainter.
-class MODULES_EXPORT NativePaintWorkletProxyClient
- : public GarbageCollected<NativePaintWorkletProxyClient>,
- public PaintWorkletPainter {
- DISALLOW_COPY_AND_ASSIGN(NativePaintWorkletProxyClient);
-
- public:
- ~NativePaintWorkletProxyClient() override = default;
-
- // PaintWorkletPainter implementation.
- int GetWorkletId() const override { return worklet_id_; }
-
- protected:
- explicit NativePaintWorkletProxyClient(int worklet_id)
- : worklet_id_(worklet_id) {}
-
- private:
- const int worklet_id_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_PROXY_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.cc
index 66716f32d51..202be16a0c7 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.cc
@@ -1,8 +1,8 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
#include "third_party/blink/renderer/core/animation/compositor_animations.h"
@@ -12,19 +12,28 @@
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h"
#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h"
+#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h"
+#include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.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/modules/csspaint/native_paint_worklet_proxy_client.h"
+#include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h"
#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
namespace {
-const float kProgressBoundsTolerance = 0.000001f;
-
// This class includes information that is required by the compositor thread
// when painting background color.
class BackgroundColorPaintWorkletInput : public PaintWorkletInput {
@@ -47,6 +56,10 @@ class BackgroundColorPaintWorkletInput : public PaintWorkletInput {
const Vector<double>& Offsets() const { return offsets_; }
const absl::optional<double>& MainThreadProgress() const { return progress_; }
+ PaintWorkletInputType GetType() const override {
+ return PaintWorkletInputType::kBackgroundColor;
+ }
+
private:
// TODO(xidachen): wrap these 3 into a structure.
// animated_colors_: The colors extracted from animated keyframes.
@@ -57,91 +70,6 @@ class BackgroundColorPaintWorkletInput : public PaintWorkletInput {
absl::optional<double> progress_;
};
-class BackgroundColorPaintWorkletProxyClient
- : public NativePaintWorkletProxyClient {
- DISALLOW_COPY_AND_ASSIGN(BackgroundColorPaintWorkletProxyClient);
-
- public:
- static BackgroundColorPaintWorkletProxyClient* Create(int worklet_id) {
- return MakeGarbageCollected<BackgroundColorPaintWorkletProxyClient>(
- worklet_id);
- }
-
- explicit BackgroundColorPaintWorkletProxyClient(int worklet_id)
- : NativePaintWorkletProxyClient(worklet_id) {}
- ~BackgroundColorPaintWorkletProxyClient() override = default;
-
- // PaintWorkletPainter implementation.
- sk_sp<PaintRecord> Paint(
- const CompositorPaintWorkletInput* compositor_input,
- const CompositorPaintWorkletJob::AnimatedPropertyValues&
- animated_property_values) override {
- const BackgroundColorPaintWorkletInput* input =
- static_cast<const BackgroundColorPaintWorkletInput*>(compositor_input);
- FloatSize container_size = input->ContainerSize();
- Vector<Color> animated_colors = input->AnimatedColors();
- Vector<double> offsets = input->Offsets();
- DCHECK_GT(animated_colors.size(), 1u);
- DCHECK_EQ(animated_colors.size(), offsets.size());
-
- // TODO(crbug.com/1188760): We should handle the case when it is null, and
- // paint the original background-color retrieved from its style.
- float progress = input->MainThreadProgress().has_value()
- ? input->MainThreadProgress().value()
- : 0;
- // This would mean that the animation started on compositor, so we override
- // the progress that we obtained from the main thread.
- if (!animated_property_values.empty()) {
- DCHECK_EQ(animated_property_values.size(), 1u);
- const auto& entry = animated_property_values.begin();
- progress = entry->second.float_value.value();
- }
-
- // Get the start and end color based on the progress and offsets.
- unsigned result_index = offsets.size() - 1;
- // The progress of the animation might outside of [0, 1] by
- // kProgressBoundsTolerance.
- if (progress <= 0) {
- result_index = 0;
- DCHECK_GE(progress, -kProgressBoundsTolerance);
- } else if (progress > 0 && progress < 1) {
- for (unsigned i = 0; i < offsets.size() - 1; i++) {
- if (progress <= offsets[i + 1]) {
- result_index = i;
- break;
- }
- }
- }
- if (result_index == offsets.size() - 1) {
- DCHECK_LE(std::fabs(progress - 1), kProgressBoundsTolerance);
- result_index = offsets.size() - 2;
- }
- // Because the progress is a global one, we need to adjust it with offsets.
- float adjusted_progress =
- (progress - offsets[result_index]) /
- (offsets[result_index + 1] - offsets[result_index]);
- std::unique_ptr<InterpolableValue> from =
- CSSColorInterpolationType::CreateInterpolableColor(
- animated_colors[result_index]);
- std::unique_ptr<InterpolableValue> to =
- CSSColorInterpolationType::CreateInterpolableColor(
- animated_colors[result_index + 1]);
- std::unique_ptr<InterpolableValue> result =
- CSSColorInterpolationType::CreateInterpolableColor(
- animated_colors[result_index + 1]);
- from->Interpolate(*to, adjusted_progress, *result);
- Color rgba = CSSColorInterpolationType::GetRGBA(*(result.get()));
- SkColor current_color = static_cast<SkColor>(rgba);
-
- PaintRenderingContext2DSettings* context_settings =
- PaintRenderingContext2DSettings::Create();
- auto* rendering_context = MakeGarbageCollected<PaintRenderingContext2D>(
- RoundedIntSize(container_size), context_settings, 1, 1);
- rendering_context->GetPaintCanvas()->drawColor(current_color);
- return rendering_context->GetRecord();
- }
-};
-
// TODO(crbug.com/1163949): Support animation keyframes without 0% or 100%.
// Returns false if we cannot successfully get the animated color.
void GetColorsFromKeyframe(const PropertySpecificKeyframe* frame,
@@ -223,7 +151,20 @@ bool GetBGColorPaintWorkletParamsInternal(
} // namespace
-Animation* BackgroundColorPaintWorklet::GetAnimationIfCompositable(
+template <>
+struct DowncastTraits<BackgroundColorPaintWorkletInput> {
+ static bool AllowFrom(const cc::PaintWorkletInput& worklet_input) {
+ auto* input = DynamicTo<PaintWorkletInput>(worklet_input);
+ return input && AllowFrom(*input);
+ }
+
+ static bool AllowFrom(const PaintWorkletInput& worklet_input) {
+ return worklet_input.GetType() ==
+ PaintWorkletInput::PaintWorkletInputType::kBackgroundColor;
+ }
+};
+
+Animation* BackgroundColorPaintDefinition::GetAnimationIfCompositable(
const Element* element) {
if (!element->GetElementAnimations())
return nullptr;
@@ -262,22 +203,119 @@ Animation* BackgroundColorPaintWorklet::GetAnimationIfCompositable(
}
// static
-BackgroundColorPaintWorklet* BackgroundColorPaintWorklet::Create(
+BackgroundColorPaintDefinition* BackgroundColorPaintDefinition::Create(
+ LocalFrame& local_root) {
+ if (!WebLocalFrameImpl::FromFrame(local_root))
+ return nullptr;
+ return MakeGarbageCollected<BackgroundColorPaintDefinition>(local_root);
+}
+
+BackgroundColorPaintDefinition::BackgroundColorPaintDefinition(
+ LocalFrame& local_root)
+ : worklet_id_(PaintWorkletIdGenerator::NextId()) {
+ DCHECK(local_root.IsLocalRoot());
+ DCHECK(IsMainThread());
+ ExecutionContext* context = local_root.DomWindow();
+ FrameOrWorkerScheduler* scheduler =
+ context ? context->GetScheduler() : nullptr;
+ // TODO(crbug.com/1143407): We don't need this thread if we can make the
+ // compositor thread support GC.
+ ThreadCreationParams params(ThreadType::kAnimationAndPaintWorkletThread);
+ worker_backing_thread_ = std::make_unique<WorkerBackingThread>(
+ params.SetFrameOrWorkerScheduler(scheduler));
+ auto startup_data = WorkerBackingThreadStartupData::CreateDefault();
+ PostCrossThreadTask(
+ *worker_backing_thread_->BackingThread().GetTaskRunner(), FROM_HERE,
+ CrossThreadBindOnce(&WorkerBackingThread::InitializeOnBackingThread,
+ CrossThreadUnretained(worker_backing_thread_.get()),
+ startup_data));
+ RegisterProxyClient(local_root);
+}
+
+void BackgroundColorPaintDefinition::RegisterProxyClient(
LocalFrame& local_root) {
- return MakeGarbageCollected<BackgroundColorPaintWorklet>(local_root);
+ proxy_client_ =
+ PaintWorkletProxyClient::Create(local_root.DomWindow(), worklet_id_);
+ proxy_client_->RegisterForNativePaintWorklet(
+ worker_backing_thread_.get(), this,
+ PaintWorkletInput::PaintWorkletInputType::kBackgroundColor);
}
-BackgroundColorPaintWorklet::BackgroundColorPaintWorklet(LocalFrame& local_root)
- : NativePaintWorklet(local_root) {
- // This is called only once per document.
- BackgroundColorPaintWorkletProxyClient* client =
- BackgroundColorPaintWorkletProxyClient::Create(worklet_id_);
- RegisterProxyClient(client);
+void BackgroundColorPaintDefinition::UnregisterProxyClient() {
+ proxy_client_->UnregisterForNativePaintWorklet();
}
-BackgroundColorPaintWorklet::~BackgroundColorPaintWorklet() = default;
+sk_sp<PaintRecord> BackgroundColorPaintDefinition::Paint(
+ const CompositorPaintWorkletInput* compositor_input,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&
+ animated_property_values) {
+ const BackgroundColorPaintWorkletInput* input =
+ static_cast<const BackgroundColorPaintWorkletInput*>(compositor_input);
+ FloatSize container_size = input->ContainerSize();
+ Vector<Color> animated_colors = input->AnimatedColors();
+ Vector<double> offsets = input->Offsets();
+ DCHECK_GT(animated_colors.size(), 1u);
+ DCHECK_EQ(animated_colors.size(), offsets.size());
+
+ // TODO(crbug.com/1188760): We should handle the case when it is null, and
+ // paint the original background-color retrieved from its style.
+ float progress = input->MainThreadProgress().has_value()
+ ? input->MainThreadProgress().value()
+ : 0;
+ // This would mean that the animation started on compositor, so we override
+ // the progress that we obtained from the main thread.
+ if (!animated_property_values.empty()) {
+ DCHECK_EQ(animated_property_values.size(), 1u);
+ const auto& entry = animated_property_values.begin();
+ progress = entry->second.float_value.value();
+ }
-scoped_refptr<Image> BackgroundColorPaintWorklet::Paint(
+ // Get the start and end color based on the progress and offsets.
+ unsigned result_index = offsets.size() - 1;
+ if (progress <= 0) {
+ result_index = 0;
+ } else if (progress > 0 && progress < 1) {
+ for (unsigned i = 0; i < offsets.size() - 1; i++) {
+ if (progress <= offsets[i + 1]) {
+ result_index = i;
+ break;
+ }
+ }
+ }
+ if (result_index == offsets.size() - 1) {
+ result_index = offsets.size() - 2;
+ }
+ // Because the progress is a global one, we need to adjust it with offsets.
+ float adjusted_progress = (progress - offsets[result_index]) /
+ (offsets[result_index + 1] - offsets[result_index]);
+ std::unique_ptr<InterpolableValue> from =
+ CSSColorInterpolationType::CreateInterpolableColor(
+ animated_colors[result_index]);
+ std::unique_ptr<InterpolableValue> to =
+ CSSColorInterpolationType::CreateInterpolableColor(
+ animated_colors[result_index + 1]);
+ std::unique_ptr<InterpolableValue> result =
+ CSSColorInterpolationType::CreateInterpolableColor(
+ animated_colors[result_index + 1]);
+ from->Interpolate(*to, adjusted_progress, *result);
+ Color rgba = CSSColorInterpolationType::GetRGBA(*(result.get()));
+ SkColor current_color = static_cast<SkColor>(rgba);
+
+ // When render this element, we always do pixel snapping to its nearest pixel,
+ // therefore we use rounded |container_size| to create the rendering context.
+ IntSize rounded_size = RoundedIntSize(container_size);
+ if (!context_ || context_->Width() != rounded_size.Width() ||
+ context_->Height() != rounded_size.Height()) {
+ PaintRenderingContext2DSettings* context_settings =
+ PaintRenderingContext2DSettings::Create();
+ context_ = MakeGarbageCollected<PaintRenderingContext2D>(
+ rounded_size, context_settings, 1, 1);
+ }
+ context_->GetDrawingPaintCanvas()->drawColor(current_color);
+ return context_->GetRecord();
+}
+
+scoped_refptr<Image> BackgroundColorPaintDefinition::Paint(
const FloatSize& container_size,
const Node* node,
const Vector<Color>& animated_colors,
@@ -298,7 +336,7 @@ scoped_refptr<Image> BackgroundColorPaintWorklet::Paint(
return PaintWorkletDeferredImage::Create(std::move(input), container_size);
}
-bool BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+bool BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
Node* node,
Vector<Color>* animated_colors,
Vector<double>* offsets,
@@ -312,7 +350,7 @@ bool BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
progress, compositable_animation);
}
-sk_sp<PaintRecord> BackgroundColorPaintWorklet::ProxyClientPaintForTest(
+sk_sp<PaintRecord> BackgroundColorPaintDefinition::PaintForTest(
const Vector<Color>& animated_colors,
const Vector<double>& offsets,
const CompositorPaintWorkletJob::AnimatedPropertyValues&
@@ -324,9 +362,12 @@ sk_sp<PaintRecord> BackgroundColorPaintWorklet::ProxyClientPaintForTest(
base::MakeRefCounted<BackgroundColorPaintWorkletInput>(
container_size, 1u, animated_colors, offsets, progress,
property_keys);
- BackgroundColorPaintWorkletProxyClient* client =
- BackgroundColorPaintWorkletProxyClient::Create(1u);
- return client->Paint(input.get(), animated_property_values);
+ return Paint(input.get(), animated_property_values);
+}
+
+void BackgroundColorPaintDefinition::Trace(Visitor* visitor) const {
+ visitor->Trace(proxy_client_);
+ NativePaintDefinition::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h
new file mode 100644
index 00000000000..2f56afc3f45
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_BACKGROUND_COLOR_PAINT_DEFINITION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_BACKGROUND_COLOR_PAINT_DEFINITION_H_
+
+#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
+#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/blink/renderer/platform/graphics/color.h"
+
+namespace blink {
+
+class Image;
+class LocalFrame;
+class Node;
+class PaintWorkletProxyClient;
+
+class MODULES_EXPORT BackgroundColorPaintDefinition final
+ : public GarbageCollected<BackgroundColorPaintDefinition>,
+ public NativePaintDefinition {
+ public:
+ static BackgroundColorPaintDefinition* Create(LocalFrame&);
+ explicit BackgroundColorPaintDefinition(LocalFrame&);
+ ~BackgroundColorPaintDefinition() final = default;
+ BackgroundColorPaintDefinition(const BackgroundColorPaintDefinition&) =
+ delete;
+ BackgroundColorPaintDefinition& operator=(
+ const BackgroundColorPaintDefinition&) = delete;
+
+ // PaintDefinition override
+ sk_sp<PaintRecord> Paint(
+ const CompositorPaintWorkletInput*,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&) override;
+
+ // The |container_size| is without subpixel snapping.
+ scoped_refptr<Image> Paint(const FloatSize& container_size,
+ const Node*,
+ const Vector<Color>& animated_colors,
+ const Vector<double>& offsets,
+ const absl::optional<double>& progress);
+
+ // Get the animated colors and offsets from the animation keyframes. Moreover,
+ // we obtain the progress of the animation from the main thread, such that if
+ // the animation failed to run on the compositor thread, we can still paint
+ // the element off the main thread with that progress + the keyframes.
+ // Returning false meaning that we cannot paint background color with
+ // BackgroundColorPaintWorklet.
+ // A side effect of this is that it will ensure a unique_id exists.
+ static bool GetBGColorPaintWorkletParams(Node* node,
+ Vector<Color>* animated_colors,
+ Vector<double>* offsets,
+ absl::optional<double>* progress);
+
+ // Shared code that is being called in multiple places.
+ static Animation* GetAnimationIfCompositable(const Element* element);
+
+ // Unregister the painter to ensure that there is no memory leakage on the
+ // compositor thread.
+ void UnregisterProxyClient();
+
+ void Trace(Visitor* visitor) const override;
+
+ // Constructor for testing purpose only.
+ BackgroundColorPaintDefinition() = default;
+ sk_sp<PaintRecord> PaintForTest(
+ const Vector<Color>& animated_colors,
+ const Vector<double>& offsets,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&
+ animated_property_values);
+
+ private:
+ // Register the PaintWorkletProxyClient to the compositor thread that
+ // will hold a cross thread persistent pointer to it. This should be called
+ // during the construction of native paint worklets, to ensure that the proxy
+ // client is ready on the compositor thread when dispatching a paint job.
+ void RegisterProxyClient(LocalFrame&);
+
+ int worklet_id_;
+ // The worker thread that does the paint work.
+ std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
+ Member<PaintWorkletProxyClient> proxy_client_;
+
+ // The instance of BackgroundColorPaintDefinition is created on the main
+ // thread, which means |context_| is initialized on the main thread's heap.
+ // However, |context_| is used on a worker backing thread, and that's why it
+ // needs to be CrossThreadPersistent.
+ // The |context_| can live as long as BackgroundColorPaintDefinition.
+ CrossThreadPersistent<PaintRenderingContext2D> context_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_BACKGROUND_COLOR_PAINT_DEFINITION_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition_test.cc
index 51c80cfb45f..c8c33a88357 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition_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/modules/csspaint/background_color_paint_worklet.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
@@ -23,11 +23,23 @@
namespace blink {
-using BackgroundColorPaintWorkletTest = PageTestBase;
+namespace {
+
+void RunPaintForTest(
+ const Vector<Color>& animated_colors,
+ const Vector<double>& offsets,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues& property_values) {
+ BackgroundColorPaintDefinition* definition =
+ MakeGarbageCollected<BackgroundColorPaintDefinition>();
+ definition->PaintForTest(animated_colors, offsets, property_values);
+}
+} // namespace
+
+using BackgroundColorPaintDefinitionTest = PageTestBase;
// Test the case where there is a background-color animation with two simple
// keyframes that will not fall back to main.
-TEST_F(BackgroundColorPaintWorkletTest, SimpleBGColorAnimationNotFallback) {
+TEST_F(BackgroundColorPaintDefinitionTest, SimpleBGColorAnimationNotFallback) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
<div id ="target" style="width: 100px; height: 100px">
@@ -69,12 +81,12 @@ TEST_F(BackgroundColorPaintWorkletTest, SimpleBGColorAnimationNotFallback) {
Vector<Color> animated_colors;
Vector<double> offsets;
absl::optional<double> progress;
- EXPECT_TRUE(BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+ EXPECT_TRUE(BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
element, &animated_colors, &offsets, &progress));
}
// Test the case when there is no animation attached to the element.
-TEST_F(BackgroundColorPaintWorkletTest, FallbackToMainNoAnimation) {
+TEST_F(BackgroundColorPaintDefinitionTest, FallbackToMainNoAnimation) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
<div id ="target" style="width: 100px; height: 100px">
@@ -85,14 +97,14 @@ TEST_F(BackgroundColorPaintWorkletTest, FallbackToMainNoAnimation) {
Vector<Color> animated_colors;
Vector<double> offsets;
absl::optional<double> progress;
- EXPECT_FALSE(BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+ EXPECT_FALSE(BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
element, &animated_colors, &offsets, &progress));
}
// Test that when an element has other animations but no background color
// animation, then we fall back to the main thread. Also testing that calling
-// BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams do not crash.
-TEST_F(BackgroundColorPaintWorkletTest, NoBGColorAnimationFallback) {
+// BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams do not crash.
+TEST_F(BackgroundColorPaintDefinitionTest, NoBGColorAnimationFallback) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
<div id ="target" style="width: 100px; height: 100px">
@@ -134,14 +146,14 @@ TEST_F(BackgroundColorPaintWorkletTest, NoBGColorAnimationFallback) {
Vector<Color> animated_colors;
Vector<double> offsets;
absl::optional<double> progress;
- EXPECT_FALSE(BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+ EXPECT_FALSE(BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
element, &animated_colors, &offsets, &progress));
EXPECT_TRUE(animated_colors.IsEmpty());
EXPECT_TRUE(offsets.IsEmpty());
}
// Test the case where the composite mode is not replace.
-TEST_F(BackgroundColorPaintWorkletTest, FallbackToMainCompositeAccumulate) {
+TEST_F(BackgroundColorPaintDefinitionTest, FallbackToMainCompositeAccumulate) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
<div id ="target" style="width: 100px; height: 100px">
@@ -183,11 +195,11 @@ TEST_F(BackgroundColorPaintWorkletTest, FallbackToMainCompositeAccumulate) {
Vector<Color> animated_colors;
Vector<double> offsets;
absl::optional<double> progress;
- EXPECT_FALSE(BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+ EXPECT_FALSE(BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
element, &animated_colors, &offsets, &progress));
}
-TEST_F(BackgroundColorPaintWorkletTest, MultipleAnimationsFallback) {
+TEST_F(BackgroundColorPaintDefinitionTest, MultipleAnimationsFallback) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
<div id ="target" style="width: 100px; height: 100px">
@@ -241,14 +253,14 @@ TEST_F(BackgroundColorPaintWorkletTest, MultipleAnimationsFallback) {
Vector<Color> animated_colors;
Vector<double> offsets;
absl::optional<double> progress;
- EXPECT_FALSE(BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+ EXPECT_FALSE(BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
element, &animated_colors, &offsets, &progress));
}
// Test that style->CompositablePaintAnimationChanged() should be true in the
// case where we initially have one background-color animation, and then changed
// to have two background-color animation on the element.
-TEST_F(BackgroundColorPaintWorkletTest,
+TEST_F(BackgroundColorPaintDefinitionTest,
TriggerRepaintCompositedToNonComposited) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
@@ -322,7 +334,7 @@ TEST_F(BackgroundColorPaintWorkletTest,
// Test that style->CompositablePaintAnimationChanged() should be true in the
// case where we initially have one background-color animation, and then we
// changed one of the animation's keyframes.
-TEST_F(BackgroundColorPaintWorkletTest, TriggerRepaintChangedKeyframe) {
+TEST_F(BackgroundColorPaintDefinitionTest, TriggerRepaintChangedKeyframe) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
SetBodyInnerHTML(R"HTML(
<div id ="target" style="width: 100px; height: 100px">
@@ -389,18 +401,19 @@ TEST_F(BackgroundColorPaintWorkletTest, TriggerRepaintChangedKeyframe) {
// Test that calling BackgroundColorPaintWorkletProxyClient::Paint won't crash
// when the animated property value is empty.
-TEST_F(BackgroundColorPaintWorkletTest, ProxyClientPaintWithNoPropertyValue) {
+TEST_F(BackgroundColorPaintDefinitionTest,
+ ProxyClientPaintWithNoPropertyValue) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
Vector<Color> animated_colors = {Color(0, 255, 0), Color(255, 0, 0)};
Vector<double> offsets = {0, 1};
CompositorPaintWorkletJob::AnimatedPropertyValues property_values;
- BackgroundColorPaintWorklet::ProxyClientPaintForTest(animated_colors, offsets,
- property_values);
+ RunPaintForTest(animated_colors, offsets, property_values);
}
// Test that BackgroundColorPaintWorkletProxyClient::Paint won't crash if the
// progress of the animation is a negative number.
-TEST_F(BackgroundColorPaintWorkletTest, ProxyClientPaintWithNegativeProgress) {
+TEST_F(BackgroundColorPaintDefinitionTest,
+ ProxyClientPaintWithNegativeProgress) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
Vector<Color> animated_colors = {Color(0, 255, 0), Color(255, 0, 0)};
Vector<double> offsets = {0, 1};
@@ -410,13 +423,12 @@ TEST_F(BackgroundColorPaintWorkletTest, ProxyClientPaintWithNegativeProgress) {
CompositorElementId(1u));
CompositorPaintWorkletInput::PropertyValue property_value(-0.0f);
property_values.insert(std::make_pair(property_key, property_value));
- BackgroundColorPaintWorklet::ProxyClientPaintForTest(animated_colors, offsets,
- property_values);
+ RunPaintForTest(animated_colors, offsets, property_values);
}
// Test that BackgroundColorPaintWorkletProxyClient::Paint won't crash if the
// progress of the animation is > 1.
-TEST_F(BackgroundColorPaintWorkletTest,
+TEST_F(BackgroundColorPaintDefinitionTest,
ProxyClientPaintWithLargerThanOneProgress) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
Vector<Color> animated_colors = {Color(0, 255, 0), Color(255, 0, 0)};
@@ -428,13 +440,13 @@ TEST_F(BackgroundColorPaintWorkletTest,
float progress = 1 + std::numeric_limits<float>::epsilon();
CompositorPaintWorkletInput::PropertyValue property_value(progress);
property_values.insert(std::make_pair(property_key, property_value));
- BackgroundColorPaintWorklet::ProxyClientPaintForTest(animated_colors, offsets,
- property_values);
+ RunPaintForTest(animated_colors, offsets, property_values);
}
// Test that BackgroundColorPaintWorkletProxyClient::Paint won't crash when the
// largest offset is not exactly one.
-TEST_F(BackgroundColorPaintWorkletTest, ProxyClientPaintWithCloseToOneOffset) {
+TEST_F(BackgroundColorPaintDefinitionTest,
+ ProxyClientPaintWithCloseToOneOffset) {
ScopedCompositeBGColorAnimationForTest composite_bgcolor_animation(true);
Vector<Color> animated_colors = {Color(0, 255, 0), Color(0, 255, 255),
Color(255, 0, 0)};
@@ -446,8 +458,7 @@ TEST_F(BackgroundColorPaintWorkletTest, ProxyClientPaintWithCloseToOneOffset) {
float progress = 1 - std::numeric_limits<float>::epsilon();
CompositorPaintWorkletInput::PropertyValue property_value(progress);
property_values.insert(std::make_pair(property_key, property_value));
- BackgroundColorPaintWorklet::ProxyClientPaintForTest(animated_colors, offsets,
- property_values);
+ RunPaintForTest(animated_colors, offsets, property_values);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.cc b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.cc
index 7cacf060f1c..c7a759daa8b 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.cc
@@ -2,29 +2,30 @@
// Use 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/csspaint/background_color_paint_image_generator_impl.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.h"
-#include "third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
namespace blink {
BackgroundColorPaintImageGenerator*
BackgroundColorPaintImageGeneratorImpl::Create(LocalFrame& local_root) {
- BackgroundColorPaintWorklet* background_color_paint_worklet =
- BackgroundColorPaintWorklet::Create(local_root);
+ BackgroundColorPaintDefinition* background_color_paint_definition =
+ BackgroundColorPaintDefinition::Create(local_root);
+ if (!background_color_paint_definition)
+ return nullptr;
- DCHECK(background_color_paint_worklet);
BackgroundColorPaintImageGeneratorImpl* generator =
MakeGarbageCollected<BackgroundColorPaintImageGeneratorImpl>(
- background_color_paint_worklet);
+ background_color_paint_definition);
return generator;
}
BackgroundColorPaintImageGeneratorImpl::BackgroundColorPaintImageGeneratorImpl(
- BackgroundColorPaintWorklet* background_color_paint_worklet)
- : background_color_paint_worklet_(background_color_paint_worklet) {}
+ BackgroundColorPaintDefinition* background_color_paint_definition)
+ : background_color_paint_definition_(background_color_paint_definition) {}
scoped_refptr<Image> BackgroundColorPaintImageGeneratorImpl::Paint(
const FloatSize& container_size,
@@ -32,7 +33,7 @@ scoped_refptr<Image> BackgroundColorPaintImageGeneratorImpl::Paint(
const Vector<Color>& animated_colors,
const Vector<double>& offsets,
const absl::optional<double>& progress) {
- return background_color_paint_worklet_->Paint(
+ return background_color_paint_definition_->Paint(
container_size, node, animated_colors, offsets, progress);
}
@@ -41,21 +42,21 @@ bool BackgroundColorPaintImageGeneratorImpl::GetBGColorPaintWorkletParams(
Vector<Color>* animated_colors,
Vector<double>* offsets,
absl::optional<double>* progress) {
- return BackgroundColorPaintWorklet::GetBGColorPaintWorkletParams(
+ return BackgroundColorPaintDefinition::GetBGColorPaintWorkletParams(
node, animated_colors, offsets, progress);
}
Animation* BackgroundColorPaintImageGeneratorImpl::GetAnimationIfCompositable(
const Element* element) {
- return BackgroundColorPaintWorklet::GetAnimationIfCompositable(element);
+ return BackgroundColorPaintDefinition::GetAnimationIfCompositable(element);
}
void BackgroundColorPaintImageGeneratorImpl::Shutdown() {
- background_color_paint_worklet_->UnregisterProxyClient();
+ background_color_paint_definition_->UnregisterProxyClient();
}
void BackgroundColorPaintImageGeneratorImpl::Trace(Visitor* visitor) const {
- visitor->Trace(background_color_paint_worklet_);
+ visitor->Trace(background_color_paint_definition_);
BackgroundColorPaintImageGenerator::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.h b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.h
index e9fd99fc939..51f653b8590 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_IMPL_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_IMPL_H_
#include "third_party/blink/renderer/core/css/background_color_paint_image_generator.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -13,14 +13,15 @@
namespace blink {
class Image;
-class BackgroundColorPaintWorklet;
+class BackgroundColorPaintDefinition;
class MODULES_EXPORT BackgroundColorPaintImageGeneratorImpl final
: public BackgroundColorPaintImageGenerator {
public:
static BackgroundColorPaintImageGenerator* Create(LocalFrame&);
- explicit BackgroundColorPaintImageGeneratorImpl(BackgroundColorPaintWorklet*);
+ explicit BackgroundColorPaintImageGeneratorImpl(
+ BackgroundColorPaintDefinition*);
~BackgroundColorPaintImageGeneratorImpl() override = default;
// The |container_size| is without subpixel snapping.
@@ -42,9 +43,9 @@ class MODULES_EXPORT BackgroundColorPaintImageGeneratorImpl final
void Trace(Visitor*) const override;
private:
- Member<BackgroundColorPaintWorklet> background_color_paint_worklet_;
+ Member<BackgroundColorPaintDefinition> background_color_paint_definition_;
};
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_IMPL_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_BACKGROUND_COLOR_PAINT_IMAGE_GENERATOR_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.cc b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.cc
new file mode 100644
index 00000000000..70cd2aeab93
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.cc
@@ -0,0 +1,224 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.h"
+
+#include "third_party/blink/renderer/core/animation/element_animations.h"
+#include "third_party/blink/renderer/core/css/basic_shape_functions.h"
+#include "third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h"
+#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.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/style/shape_clip_path_operation.h"
+#include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
+#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
+#include "third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+
+namespace blink {
+
+namespace {
+
+// This class includes information that is required by the compositor thread
+// when painting clip path.
+class ClipPathPaintWorkletInput : public PaintWorkletInput {
+ public:
+ ClipPathPaintWorkletInput(
+ const FloatRect& container_rect,
+ int worklet_id,
+ float zoom,
+ const Vector<scoped_refptr<ShapeClipPathOperation>>& animated_shapes,
+ cc::PaintWorkletInput::PropertyKeys property_keys)
+ : PaintWorkletInput(container_rect.Size(),
+ worklet_id,
+ std::move(property_keys)),
+ zoom_(zoom),
+ animated_shapes_(animated_shapes) {}
+
+ ~ClipPathPaintWorkletInput() override = default;
+ const Vector<scoped_refptr<ShapeClipPathOperation>>& AnimatedShapes() const {
+ return animated_shapes_;
+ }
+ float Zoom() const { return zoom_; }
+
+ PaintWorkletInputType GetType() const override {
+ return PaintWorkletInputType::kClipPath;
+ }
+
+ private:
+ float zoom_;
+ // TODO(crbug.com/1223975): This structure should support values for
+ // StylePath.
+ Vector<scoped_refptr<ShapeClipPathOperation>> animated_shapes_;
+};
+
+void GetAnimatedShapesFromKeyframes(
+ const PropertySpecificKeyframe* frame,
+ Vector<scoped_refptr<ShapeClipPathOperation>>* animated_shapes,
+ const Element* element) {
+ DCHECK(frame->IsCSSPropertySpecificKeyframe());
+ const CSSValue* value =
+ static_cast<const CSSPropertySpecificKeyframe*>(frame)->Value();
+ const CSSPropertyName property_name =
+ CSSPropertyName(CSSPropertyID::kClipPath);
+ const CSSValue* computed_value = StyleResolver::ComputeValue(
+ const_cast<Element*>(element), property_name, *value);
+
+ StyleResolverState state(element->GetDocument(),
+ *const_cast<Element*>(element));
+ scoped_refptr<ShapeClipPathOperation> basic_shape =
+ ShapeClipPathOperation::Create(
+ BasicShapeForValue(state, *computed_value));
+
+ animated_shapes->push_back(basic_shape);
+}
+} // namespace
+
+template <>
+struct DowncastTraits<ClipPathPaintWorkletInput> {
+ static bool AllowFrom(const cc::PaintWorkletInput& worklet_input) {
+ auto* input = DynamicTo<PaintWorkletInput>(worklet_input);
+ return input && AllowFrom(*input);
+ }
+
+ static bool AllowFrom(const PaintWorkletInput& worklet_input) {
+ return worklet_input.GetType() ==
+ PaintWorkletInput::PaintWorkletInputType::kClipPath;
+ }
+};
+
+// static
+ClipPathPaintDefinition* ClipPathPaintDefinition::Create(
+ LocalFrame& local_root) {
+ return MakeGarbageCollected<ClipPathPaintDefinition>(PassKey(), local_root);
+}
+
+ClipPathPaintDefinition::ClipPathPaintDefinition(PassKey pass_key,
+ LocalFrame& local_root)
+ : worklet_id_(PaintWorkletIdGenerator::NextId()) {
+ DCHECK(local_root.IsLocalRoot());
+ DCHECK(IsMainThread());
+ ExecutionContext* context = local_root.DomWindow();
+ FrameOrWorkerScheduler* scheduler =
+ context ? context->GetScheduler() : nullptr;
+ // TODO(crbug.com/1143407): We don't need this thread if we can make the
+ // compositor thread support GC.
+ ThreadCreationParams params(ThreadType::kAnimationAndPaintWorkletThread);
+ worker_backing_thread_ = std::make_unique<WorkerBackingThread>(
+ params.SetFrameOrWorkerScheduler(scheduler));
+ auto startup_data = WorkerBackingThreadStartupData::CreateDefault();
+ PostCrossThreadTask(
+ *worker_backing_thread_->BackingThread().GetTaskRunner(), FROM_HERE,
+ CrossThreadBindOnce(&WorkerBackingThread::InitializeOnBackingThread,
+ CrossThreadUnretained(worker_backing_thread_.get()),
+ startup_data));
+ RegisterProxyClient(local_root);
+}
+
+void ClipPathPaintDefinition::RegisterProxyClient(LocalFrame& local_root) {
+ proxy_client_ =
+ PaintWorkletProxyClient::Create(local_root.DomWindow(), worklet_id_);
+ proxy_client_->RegisterForNativePaintWorklet(
+ worker_backing_thread_.get(), this,
+ PaintWorkletInput::PaintWorkletInputType::kClipPath);
+}
+
+void ClipPathPaintDefinition::UnregisterProxyClient() {
+ proxy_client_->UnregisterForNativePaintWorklet();
+}
+
+sk_sp<PaintRecord> ClipPathPaintDefinition::Paint(
+ const CompositorPaintWorkletInput* compositor_input,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&
+ animated_property_values) {
+ const ClipPathPaintWorkletInput* input =
+ To<ClipPathPaintWorkletInput>(compositor_input);
+ FloatSize container_size = input->ContainerSize();
+
+ Vector<scoped_refptr<ShapeClipPathOperation>> animated_shapes =
+ input->AnimatedShapes();
+ DCHECK_GT(animated_shapes.size(), 1u);
+
+ DCHECK_EQ(animated_property_values.size(), 1u);
+ const auto& entry = animated_property_values.begin();
+ float progress = entry->second.float_value.value();
+ // TODO(crbug.com/1223975): implement interpolation here, instead of hard
+ // coding.
+ scoped_refptr<ShapeClipPathOperation> current_shape =
+ progress < 0.5 ? animated_shapes[0] : animated_shapes[1];
+ Path path = current_shape->GetPath(
+ FloatRect(FloatPoint(0.0, 0.0), container_size), input->Zoom());
+ PaintRenderingContext2DSettings* context_settings =
+ PaintRenderingContext2DSettings::Create();
+ auto* rendering_context = MakeGarbageCollected<PaintRenderingContext2D>(
+ RoundedIntSize(container_size), context_settings, 1, 1);
+
+ PaintFlags flags;
+ flags.setAntiAlias(true);
+ rendering_context->GetPaintCanvas()->drawPath(path.GetSkPath(), flags);
+
+ return rendering_context->GetRecord();
+}
+
+scoped_refptr<Image> ClipPathPaintDefinition::Paint(
+ float zoom,
+ const FloatRect& reference_box,
+ const Node& node) {
+ DCHECK(node.IsElementNode());
+ const Element* element = static_cast<Element*>(const_cast<Node*>(&node));
+ ElementAnimations* element_animations = element->GetElementAnimations();
+
+ Vector<scoped_refptr<ShapeClipPathOperation>> animated_shapes;
+ // TODO(crbug.com/1223975): implement main-thread fall back logic for
+ // animations that we cannot handle.
+ for (const auto& animation : element_animations->Animations()) {
+ const AnimationEffect* effect = animation.key->effect();
+ if (!effect->IsKeyframeEffect())
+ continue;
+ const KeyframeEffectModelBase* model =
+ static_cast<const KeyframeEffect*>(effect)->Model();
+ // TODO(crbug.com/1223975): handle transition keyframes here.
+ if (!model->IsStringKeyframeEffectModel())
+ continue;
+ const PropertySpecificKeyframeVector* frames =
+ model->GetPropertySpecificKeyframes(
+ PropertyHandle(GetCSSPropertyClipPath()));
+ DCHECK_GE(frames->size(), 2u);
+ // TODO(crbug.com/1223975): right now we keep the first and last keyframe
+ // values only, we need to keep all keyframe values.
+ GetAnimatedShapesFromKeyframes(frames->front(), &animated_shapes, element);
+ GetAnimatedShapesFromKeyframes(frames->back(), &animated_shapes, element);
+ }
+
+ node.GetLayoutObject()->GetMutableForPainting().EnsureId();
+ CompositorElementId element_id = CompositorElementIdFromUniqueObjectId(
+ node.GetLayoutObject()->UniqueId(),
+ CompositorAnimations::CompositorElementNamespaceForProperty(
+ CSSPropertyID::kClipPath));
+ CompositorPaintWorkletInput::PropertyKeys input_property_keys;
+ input_property_keys.emplace_back(
+ CompositorPaintWorkletInput::NativePropertyType::kClipPath, element_id);
+ scoped_refptr<ClipPathPaintWorkletInput> input =
+ base::MakeRefCounted<ClipPathPaintWorkletInput>(
+ reference_box, worklet_id_, zoom, animated_shapes,
+ std::move(input_property_keys));
+
+ return PaintWorkletDeferredImage::Create(std::move(input),
+ reference_box.Size());
+}
+
+void ClipPathPaintDefinition::Trace(Visitor* visitor) const {
+ visitor->Trace(proxy_client_);
+ NativePaintDefinition::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.h
new file mode 100644
index 00000000000..b93267fea83
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_CLIP_PATH_PAINT_DEFINITION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_CLIP_PATH_PAINT_DEFINITION_H_
+
+#include "base/types/pass_key.h"
+#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+class FloatRect;
+class Image;
+class LocalFrame;
+class Node;
+class PaintWorkletProxyClient;
+
+class MODULES_EXPORT ClipPathPaintDefinition final
+ : public GarbageCollected<ClipPathPaintDefinition>,
+ public NativePaintDefinition {
+ public:
+ static ClipPathPaintDefinition* Create(LocalFrame& local_root);
+
+ using PassKey = base::PassKey<ClipPathPaintDefinition>;
+ explicit ClipPathPaintDefinition(PassKey, LocalFrame& local_root);
+ ~ClipPathPaintDefinition() final = default;
+ ClipPathPaintDefinition(const ClipPathPaintDefinition&) = delete;
+ ClipPathPaintDefinition& operator=(const ClipPathPaintDefinition&) = delete;
+
+ // PaintDefinition override
+ sk_sp<PaintRecord> Paint(
+ const CompositorPaintWorkletInput*,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&) override;
+
+ scoped_refptr<Image> Paint(float zoom,
+ const FloatRect& reference_box,
+ const Node&);
+
+ // Unregister the painter to ensure that there is no memory leakage on the
+ // compositor thread.
+ void UnregisterProxyClient();
+
+ void Trace(Visitor* visitor) const override;
+
+ private:
+ // Register the PaintWorkletProxyClient to the compositor thread that
+ // will hold a cross thread persistent pointer to it. This should be called
+ // during the construction of native paint worklets, to ensure that the proxy
+ // client is ready on the compositor thread when dispatching a paint job.
+ void RegisterProxyClient(LocalFrame&);
+
+ int worklet_id_;
+ // The worker thread that does the paint work.
+ std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
+ Member<PaintWorkletProxyClient> proxy_client_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_CLIP_PATH_PAINT_DEFINITION_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.cc b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.cc
new file mode 100644
index 00000000000..823eb6613c8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.cc
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.h"
+
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_definition.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
+
+namespace blink {
+
+ClipPathPaintImageGenerator* ClipPathPaintImageGeneratorImpl::Create(
+ LocalFrame& local_root) {
+ ClipPathPaintDefinition* clip_path_paint_definition =
+ ClipPathPaintDefinition::Create(local_root);
+
+ DCHECK(clip_path_paint_definition);
+ ClipPathPaintImageGeneratorImpl* generator =
+ MakeGarbageCollected<ClipPathPaintImageGeneratorImpl>(
+ clip_path_paint_definition);
+
+ return generator;
+}
+
+ClipPathPaintImageGeneratorImpl::ClipPathPaintImageGeneratorImpl(
+ ClipPathPaintDefinition* clip_path_paint_definition)
+ : clip_path_paint_definition_(clip_path_paint_definition) {}
+
+scoped_refptr<Image> ClipPathPaintImageGeneratorImpl::Paint(
+ float zoom,
+ const FloatRect& reference_box,
+ const Node& node) {
+ return clip_path_paint_definition_->Paint(zoom, reference_box, node);
+}
+
+void ClipPathPaintImageGeneratorImpl::Shutdown() {
+ clip_path_paint_definition_->UnregisterProxyClient();
+}
+
+void ClipPathPaintImageGeneratorImpl::Trace(Visitor* visitor) const {
+ visitor->Trace(clip_path_paint_definition_);
+ ClipPathPaintImageGenerator::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.h b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.h
new file mode 100644
index 00000000000..c3eee477e7d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_CLIP_PATH_PAINT_IMAGE_GENERATOR_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_CLIP_PATH_PAINT_IMAGE_GENERATOR_IMPL_H_
+
+#include "third_party/blink/renderer/core/css/clip_path_paint_image_generator.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+
+namespace blink {
+
+class Image;
+class ClipPathPaintDefinition;
+
+class MODULES_EXPORT ClipPathPaintImageGeneratorImpl final
+ : public ClipPathPaintImageGenerator {
+ public:
+ static ClipPathPaintImageGenerator* Create(LocalFrame&);
+
+ explicit ClipPathPaintImageGeneratorImpl(ClipPathPaintDefinition*);
+ ~ClipPathPaintImageGeneratorImpl() override = default;
+
+ scoped_refptr<Image> Paint(float zoom,
+ const FloatRect& reference_box,
+ const Node&) final;
+
+ void Shutdown() final;
+
+ void Trace(Visitor*) const override;
+
+ private:
+ Member<ClipPathPaintDefinition> clip_path_paint_definition_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_CLIP_PATH_PAINT_IMAGE_GENERATOR_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h
new file mode 100644
index 00000000000..6591c5c85d7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_NATIVE_PAINT_DEFINITION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_NATIVE_PAINT_DEFINITION_H_
+
+#include "third_party/blink/renderer/modules/csspaint/paint_definition.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class MODULES_EXPORT NativePaintDefinition : public PaintDefinition {
+ public:
+ ~NativePaintDefinition() override = default;
+ void Trace(Visitor* visitor) const override {
+ PaintDefinition::Trace(visitor);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_NATIVE_PAINT_DEFINITION_H_
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_definition.h
new file mode 100644
index 00000000000..5c434e2c44f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_definition.h
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_DEFINITION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_DEFINITION_H_
+
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
+#include "third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class MODULES_EXPORT PaintDefinition : public GarbageCollectedMixin {
+ public:
+ virtual ~PaintDefinition() = default;
+
+ virtual sk_sp<PaintRecord> Paint(
+ const CompositorPaintWorkletInput*,
+ const CompositorPaintWorkletJob::AnimatedPropertyValues&) = 0;
+
+ void Trace(Visitor* visitor) const override {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_DEFINITION_H_
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 c1380630be3..c5c04cd6239 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
@@ -41,10 +41,6 @@ void PaintRenderingContext2D::InitializePaintRecorder() {
did_record_draw_commands_in_paint_recorder_ = false;
}
-void PaintRenderingContext2D::DidDraw(const SkIRect&) {
- did_record_draw_commands_in_paint_recorder_ = true;
-}
-
int PaintRenderingContext2D::Width() const {
return container_size_.Width();
}
@@ -98,6 +94,19 @@ cc::PaintCanvas* PaintRenderingContext2D::GetPaintCanvas() const {
return paint_recorder_->getRecordingCanvas();
}
+cc::PaintCanvas* PaintRenderingContext2D::GetDrawingPaintCanvas() {
+ DCHECK(paint_recorder_);
+ DCHECK(paint_recorder_->getRecordingCanvas());
+ did_record_draw_commands_in_paint_recorder_ = true;
+ return paint_recorder_->getRecordingCanvas();
+}
+
+cc::PaintCanvas* PaintRenderingContext2D::GetPaintCanvasForDraw(
+ const SkIRect&,
+ CanvasPerformanceMonitor::DrawType) {
+ return GetDrawingPaintCanvas();
+}
+
void PaintRenderingContext2D::ValidateStateStackWithCanvas(
const cc::PaintCanvas* canvas) const {
#if DCHECK_IS_ON()
@@ -108,11 +117,6 @@ void PaintRenderingContext2D::ValidateStateStackWithCanvas(
#endif
}
-bool PaintRenderingContext2D::StateHasFilter() {
- return GetState().HasFilterForOffscreenCanvas(IntSize(Width(), Height()),
- this);
-}
-
sk_sp<PaintFilter> PaintRenderingContext2D::StateGetFilter() {
return GetState().GetFilterForOffscreenCanvas(IntSize(Width(), Height()),
this);
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 cd568e8ea0a..45fac5431e3 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
@@ -55,8 +55,9 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable,
cc::PaintCanvas* GetOrCreatePaintCanvas() final { return GetPaintCanvas(); }
cc::PaintCanvas* GetPaintCanvas() const final;
-
- void DidDraw(const SkIRect&) final;
+ cc::PaintCanvas* GetPaintCanvasForDraw(
+ const SkIRect&,
+ CanvasPerformanceMonitor::DrawType) final;
double shadowOffsetX() const final;
void setShadowOffsetX(double) final;
@@ -67,7 +68,6 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable,
double shadowBlur() const final;
void setShadowBlur(double) final;
- bool StateHasFilter() final;
sk_sp<PaintFilter> StateGetFilter() final;
void SnapshotStateForFilter() final {}
@@ -92,6 +92,7 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable,
void resetTransform() final;
sk_sp<PaintRecord> GetRecord();
+ cc::PaintCanvas* GetDrawingPaintCanvas();
protected:
CanvasColorParams GetCanvas2DColorParams() const override;
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 114ed2167a7..8726ee6f54b 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
@@ -9,7 +9,9 @@
] interface PaintRenderingContext2D {
// state
void save(); // push state on state stack
- void restore(); // pop state stack and restore state
+ void restore(); // pop state stack if top state was pushed by save, and restore state
+ [RuntimeEnabled=Canvas2dLayers] void beginLayer(); // push state on state stack and creates bitmap for subsequent draw ops
+ [RuntimeEnabled=Canvas2dLayers] void endLayer(); // pop state stack if top state was pushed by beginLayer, restore state and draw the bitmap
// transformations (default transform is the identity matrix)
void scale(unrestricted double x, unrestricted double y);
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
index 05812dc797e..dc6542553ae 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_canvas_gradient_or_canvas_pattern_or_css_color_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_csscolorvalue_canvasgradient_canvaspattern_string.h"
namespace blink {
@@ -18,7 +17,6 @@ static const float kZoom = 1.0;
void TrySettingStrokeStyle(PaintRenderingContext2D* ctx,
const String& expected,
const String& value) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ctx->setStrokeStyle(
MakeGarbageCollected<
V8UnionCSSColorValueOrCanvasGradientOrCanvasPatternOrString>("red"));
@@ -28,15 +26,6 @@ void TrySettingStrokeStyle(PaintRenderingContext2D* ctx,
auto* result = ctx->strokeStyle();
ASSERT_TRUE(result);
EXPECT_EQ(expected, result->GetAsString());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrCanvasGradientOrCanvasPatternOrCSSColorValue result, arg, dummy;
- dummy.SetString("red");
- arg.SetString(value);
- ctx->setStrokeStyle(dummy);
- ctx->setStrokeStyle(arg);
- ctx->strokeStyle(result);
- EXPECT_EQ(expected, result.GetAsString());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
TEST(PaintRenderingContext2DTest, testParseColorOrCurrentColor) {
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 a0d4e00f229..154d66bc6e0 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
@@ -236,7 +236,7 @@ void PaintWorkletGlobalScope::registerPaint(const ScriptState* script_state,
CSSPaintDefinition* PaintWorkletGlobalScope::FindDefinition(
const String& name) {
- return paint_definitions_.at(name);
+ return paint_definitions_.DeprecatedAtOrEmptyValue(name);
}
double PaintWorkletGlobalScope::devicePixelRatio() const {
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc
index 8bf6336a270..5ee216ff8b7 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc
@@ -10,7 +10,7 @@ namespace blink {
void PaintWorkletPendingGeneratorRegistry::NotifyGeneratorReady(
const String& name) {
- GeneratorHashSet* set = pending_generators_.at(name);
+ GeneratorHashSet* set = pending_generators_.DeprecatedAtOrEmptyValue(name);
if (set) {
for (const auto& generator : *set) {
if (generator)
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
index b742b961c38..d919877b0c7 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
@@ -15,12 +15,15 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -169,6 +172,14 @@ sk_sp<PaintRecord> PaintWorkletProxyClient::Paint(
const CompositorPaintWorkletInput* compositor_input,
const CompositorPaintWorkletJob::AnimatedPropertyValues&
animated_property_values) {
+ const PaintWorkletInput* worklet_input =
+ To<PaintWorkletInput>(compositor_input);
+ PaintDefinition* definition;
+ if (worklet_input->GetType() !=
+ PaintWorkletInput::PaintWorkletInputType::kCSS) {
+ definition = native_definitions_.at(worklet_input->GetType());
+ return definition->Paint(compositor_input, animated_property_values);
+ }
// TODO: Can this happen? We don't register till all are here.
if (global_scopes_.IsEmpty())
return sk_make_sp<PaintRecord>();
@@ -187,71 +198,39 @@ sk_sp<PaintRecord> PaintWorkletProxyClient::Paint(
0, (PaintWorklet::kNumGlobalScopesPerThread)-1)];
const CSSPaintWorkletInput* input =
- static_cast<const CSSPaintWorkletInput*>(compositor_input);
- CSSPaintDefinition* definition =
- global_scope->FindDefinition(input->NameCopy());
- PaintWorkletStylePropertyMap* style_map =
- MakeGarbageCollected<PaintWorkletStylePropertyMap>(input->StyleMapData());
-
- CSSStyleValueVector paint_arguments;
- for (const auto& style_value : input->ParsedInputArguments()) {
- paint_arguments.push_back(style_value->ToCSSStyleValue());
- }
-
- ApplyAnimatedPropertyOverrides(style_map, animated_property_values);
-
+ To<CSSPaintWorkletInput>(compositor_input);
device_pixel_ratio_ = input->DeviceScaleFactor() * input->EffectiveZoom();
+ definition = global_scope->FindDefinition(input->NameCopy());
+ return definition->Paint(compositor_input, animated_property_values);
+}
- sk_sp<PaintRecord> result = definition->Paint(
- FloatSize(input->GetSize()), input->EffectiveZoom(), style_map,
- &paint_arguments, input->DeviceScaleFactor());
-
- // CSSPaintDefinition::Paint returns nullptr if it fails, but for
- // OffThread-PaintWorklet we prefer to insert empty PaintRecords into the
- // cache. Do the conversion here.
- // TODO(smcgruer): Once OffThread-PaintWorklet launches, we can make
- // CSSPaintDefinition::Paint return empty PaintRecords.
- if (!result)
- result = sk_make_sp<PaintRecord>();
- return result;
+void PaintWorkletProxyClient::RegisterForNativePaintWorklet(
+ WorkerBackingThread* thread,
+ NativePaintDefinition* definition,
+ PaintWorkletInput::PaintWorkletInputType type) {
+ DCHECK(!native_definitions_.Contains(type));
+ native_definitions_.insert(type, definition);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ thread->BackingThread().GetTaskRunner();
+ // At this moment, we are in the paint phase which is before commit, we queue
+ // a task to the compositor thread to register the |paint_dispatcher_|. When
+ // compositor schedules the actual paint job (PaintWorkletPainter::Paint),
+ // which is after commit, the |paint_dispatcher_| should have been registerted
+ // and ready to use.
+ PostCrossThreadTask(
+ *compositor_host_queue_, FROM_HERE,
+ CrossThreadBindOnce(
+ &PaintWorkletPaintDispatcher::RegisterPaintWorkletPainter,
+ paint_dispatcher_, WrapCrossThreadPersistent(this), task_runner));
}
-void PaintWorkletProxyClient::ApplyAnimatedPropertyOverrides(
- PaintWorkletStylePropertyMap* style_map,
- const CompositorPaintWorkletJob::AnimatedPropertyValues&
- animated_property_values) {
- for (const auto& property_value : animated_property_values) {
- DCHECK(property_value.second.has_value());
- String property_name(
- property_value.first.custom_property_name.value().c_str());
- DCHECK(style_map->StyleMapData().Contains(property_name));
- CrossThreadStyleValue* old_value =
- style_map->StyleMapData().at(property_name);
- switch (old_value->GetType()) {
- case CrossThreadStyleValue::StyleValueType::kUnitType: {
- DCHECK(property_value.second.float_value);
- std::unique_ptr<CrossThreadUnitValue> new_value =
- std::make_unique<CrossThreadUnitValue>(
- property_value.second.float_value.value(),
- DynamicTo<CrossThreadUnitValue>(old_value)->GetUnitType());
- style_map->StyleMapData().Set(property_name, std::move(new_value));
- break;
- }
- case CrossThreadStyleValue::StyleValueType::kColorType: {
- DCHECK(property_value.second.color_value);
- SkColor sk_color = property_value.second.color_value.value();
- Color color(MakeRGBA(SkColorGetR(sk_color), SkColorGetG(sk_color),
- SkColorGetB(sk_color), SkColorGetA(sk_color)));
- std::unique_ptr<CrossThreadColorValue> new_value =
- std::make_unique<CrossThreadColorValue>(color);
- style_map->StyleMapData().Set(property_name, std::move(new_value));
- break;
- }
- default:
- NOTREACHED();
- break;
- }
- }
+void PaintWorkletProxyClient::UnregisterForNativePaintWorklet() {
+ PostCrossThreadTask(
+ *compositor_host_queue_, FROM_HERE,
+ CrossThreadBindOnce(
+ &PaintWorkletPaintDispatcher::UnregisterPaintWorkletPainter,
+ paint_dispatcher_, worklet_id_));
+ paint_dispatcher_ = nullptr;
}
void ProvidePaintWorkletProxyClientTo(WorkerClients* clients,
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
index d0a106fcad8..a9479ee30b2 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
@@ -7,8 +7,9 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h"
+#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
@@ -20,6 +21,7 @@ namespace blink {
class DocumentPaintDefinition;
class PaintWorklet;
class WorkletGlobalScope;
+class WorkerBackingThread;
// Mediates between the (multiple) PaintWorkletGlobalScopes on the worklet
// thread and the (single) PaintWorkletPaintDispatcher on the non-worklet
@@ -95,17 +97,18 @@ class MODULES_EXPORT PaintWorkletProxyClient
double DevicePixelRatio() const { return device_pixel_ratio_; }
+ void RegisterForNativePaintWorklet(
+ WorkerBackingThread* thread,
+ NativePaintDefinition* definition,
+ PaintWorkletInput::PaintWorkletInputType type);
+ void UnregisterForNativePaintWorklet();
+
private:
friend class PaintWorkletGlobalScopeTest;
friend class PaintWorkletProxyClientTest;
FRIEND_TEST_ALL_PREFIXES(PaintWorkletProxyClientTest,
PaintWorkletProxyClientConstruction);
- void ApplyAnimatedPropertyOverrides(
- PaintWorkletStylePropertyMap* style_map,
- const CompositorPaintWorkletJob::AnimatedPropertyValues&
- animated_property_values);
-
// Store the device pixel ratio here so it can be used off main thread
double device_pixel_ratio_;
@@ -150,6 +153,10 @@ class MODULES_EXPORT PaintWorkletProxyClient
// handle to the PaintWorklet called via a stored task runner.
scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
CrossThreadWeakPersistent<PaintWorklet> paint_worklet_;
+
+ HashMap<PaintWorkletInput::PaintWorkletInputType,
+ CrossThreadPersistent<NativePaintDefinition>>
+ native_definitions_;
};
void MODULES_EXPORT ProvidePaintWorkletProxyClientTo(WorkerClients*,
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc
index d1e4d1be7b4..c1a9d85ca80 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc
@@ -89,13 +89,13 @@ class PaintWorkletProxyClientTest : public RenderingTest {
// create multiple WorkerThread for this. Note that the underlying thread
// may be shared even though they are unique WorkerThread instances!
Vector<std::unique_ptr<WorkerThread>> worklet_threads;
- for (size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; i++) {
+ for (wtf_size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; i++) {
worklet_threads.push_back(CreateThreadAndProvidePaintWorkletProxyClient(
&GetDocument(), reporting_proxy_.get(), proxy_client_));
}
// Add the global scopes. This must happen on the worklet thread.
- for (size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; i++) {
+ for (wtf_size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; i++) {
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*worklet_threads[i]->GetTaskRunner(TaskType::kInternalTest),
@@ -121,7 +121,7 @@ class PaintWorkletProxyClientTest : public RenderingTest {
waitable_event.Wait();
// And finally clean up.
- for (size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; i++) {
+ for (wtf_size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; i++) {
worklet_threads[i]->Terminate();
worklet_threads[i]->WaitForShutdownForTesting();
}
@@ -356,7 +356,7 @@ void RunAllDefinitionsMustBeRegisteredBeforePostingTestOnWorklet(
// end up posting a task to the PaintWorklet.
const Vector<CrossThreadPersistent<PaintWorkletGlobalScope>>& global_scopes =
proxy_client->GetGlobalScopesForTesting();
- for (size_t i = 0; i < global_scopes.size() - 1; i++) {
+ for (wtf_size_t i = 0; i < global_scopes.size() - 1; i++) {
ClassicScript::CreateUnspecifiedScript(
ScriptSourceCode("registerPaint('foo', class { paint() { } });"))
->RunScriptOnWorkerOrWorklet(*global_scopes[i]);
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 5de58c9c20c..c8e5230e0f8 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
@@ -252,7 +252,7 @@ TEST_P(MainOrOffThreadPaintWorkletTest, ConsistentGlobalScopeOnMainThread) {
EXPECT_CALL(*observer, PaintImageGeneratorReady).Times(0);
Vector<Persistent<PaintWorkletGlobalScope>> global_scopes;
- for (size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; ++i) {
+ for (wtf_size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; ++i) {
paint_worklet_to_test->AddGlobalScopeForTesting();
global_scopes.push_back(
PaintWorkletGlobalScopeProxy::From(
@@ -360,7 +360,7 @@ TEST_F(PaintWorkletTest, ConsistentGlobalScopeCrossThread) {
EXPECT_CALL(*observer, PaintImageGeneratorReady).Times(0);
Vector<Persistent<PaintWorkletGlobalScope>> global_scopes;
- for (size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; ++i) {
+ for (wtf_size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; ++i) {
paint_worklet_to_test->AddGlobalScopeForTesting();
global_scopes.push_back(
PaintWorkletGlobalScopeProxy::From(
@@ -517,7 +517,7 @@ TEST_F(PaintWorkletTest, GeneratorNotifiedAfterAllRegistrations) {
EXPECT_CALL(*observer, PaintImageGeneratorReady).Times(0);
Vector<Persistent<PaintWorkletGlobalScope>> global_scopes;
- for (size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; ++i) {
+ for (wtf_size_t i = 0; i < PaintWorklet::kNumGlobalScopesPerThread; ++i) {
paint_worklet_to_test->AddGlobalScopeForTesting();
global_scopes.push_back(
PaintWorkletGlobalScopeProxy::From(
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc
index 1ebbd115762..32ff8b786be 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ink_trail_style.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/events/pointer_event.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/geometry/dom_rect.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/chrome_client.h"
@@ -21,60 +21,46 @@
namespace blink {
-DelegatedInkTrailPresenter* DelegatedInkTrailPresenter::CreatePresenter(
- Element* element,
- LocalFrame* frame) {
- DCHECK(!element || element->GetDocument() == frame->GetDocument());
-
- return MakeGarbageCollected<DelegatedInkTrailPresenter>(element, frame);
-}
-
DelegatedInkTrailPresenter::DelegatedInkTrailPresenter(Element* element,
LocalFrame* frame)
- : presentation_area_(element), local_frame_(frame) {}
-
-void ThrowException(v8::Isolate* isolate,
- ExceptionCode code,
- const String& error_message) {
- ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
- "DelegatedInkTrailPresenter",
- "updateInkTrailStatePoint");
- exception_state.ThrowException(code, error_message);
+ : presentation_area_(element), local_frame_(frame) {
+ DCHECK(!presentation_area_ ||
+ presentation_area_->GetDocument() == local_frame_->GetDocument());
}
void DelegatedInkTrailPresenter::updateInkTrailStartPoint(
ScriptState* state,
PointerEvent* evt,
- InkTrailStyle* style) {
+ InkTrailStyle* style,
+ ExceptionState& exception_state) {
DCHECK(RuntimeEnabledFeatures::DelegatedInkTrailsEnabled());
if (!state->ContextIsValid()) {
- ThrowException(state->GetIsolate(),
- ToExceptionCode(DOMExceptionCode::kInvalidStateError),
- "The object is no longer associated with a window.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "The object is no longer associated with a window.");
return;
}
if (!evt->isTrusted()) {
- ThrowException(state->GetIsolate(),
- ToExceptionCode(DOMExceptionCode::kNotAllowedError),
- "Only trusted pointerevents are accepted.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotAllowedError,
+ "Only trusted pointerevents are accepted.");
return;
}
// If diameter is less than or equal to 0, then nothing is going to be
// displayed anyway, so just bail early and save the effort.
- if (style->diameter() <= 0) {
- ThrowException(state->GetIsolate(),
- ToExceptionCode(DOMExceptionCode::kNotSupportedError),
- "Delegated ink trail diameter must be greater than 0.");
+ if (!(style->diameter() > 0)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Delegated ink trail diameter must be greater than 0.");
return;
}
Color color;
if (!CSSParser::ParseColor(color, style->color(), true /*strict*/)) {
- ThrowException(state->GetIsolate(),
- ToExceptionCode(ESErrorType::kTypeError), "Unknown color.");
+ exception_state.ThrowTypeError("Unknown color.");
return;
}
@@ -86,8 +72,7 @@ void DelegatedInkTrailPresenter::updateInkTrailStartPoint(
physical_point.Scale(effective_zoom);
physical_point = layout_view->LocalToAbsolutePoint(
physical_point, kTraverseDocumentBoundaries);
- gfx::PointF point(physical_point.left.ToFloat(),
- physical_point.top.ToFloat());
+ gfx::PointF point = FloatPoint(physical_point);
LayoutBox* layout_box = nullptr;
if (presentation_area_) {
@@ -128,10 +113,7 @@ void DelegatedInkTrailPresenter::updateInkTrailStartPoint(
border_box_rect_absolute.Intersect(PhysicalRect(
local_frame_->GetPage()->GetVisualViewport().VisibleContentRect()));
- gfx::RectF area(border_box_rect_absolute.X().ToFloat(),
- border_box_rect_absolute.Y().ToFloat(),
- border_box_rect_absolute.Width().ToFloat(),
- border_box_rect_absolute.Height().ToFloat());
+ gfx::RectF area = FloatRect(border_box_rect_absolute);
// This is used to know if the user starts inking with the pointer down or
// not, so that we can stop drawing delegated ink trails as quickly as
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h
index 439a57f82f7..5e7fe2b7a00 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h
@@ -11,6 +11,7 @@
namespace blink {
class Element;
+class ExceptionState;
class InkTrailStyle;
class LocalFrame;
class PointerEvent;
@@ -28,12 +29,12 @@ class MODULES_EXPORT DelegatedInkTrailPresenter : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- static DelegatedInkTrailPresenter* CreatePresenter(Element* element,
- LocalFrame* frame);
DelegatedInkTrailPresenter(Element* element, LocalFrame* frame);
+
void updateInkTrailStartPoint(ScriptState* state,
PointerEvent* evt,
- InkTrailStyle* style);
+ InkTrailStyle* style,
+ ExceptionState& exception_state);
uint32_t expectedImprovement() const { return expected_improvement_; }
Element* presentationArea() const { return presentation_area_; }
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.idl b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.idl
index d0f2b650826..1aa54b7a129 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.idl
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.idl
@@ -8,8 +8,8 @@
RuntimeEnabled=DelegatedInkTrails,
Exposed=Window
] interface DelegatedInkTrailPresenter {
- [CallWith=ScriptState] void updateInkTrailStartPoint(PointerEvent evt, InkTrailStyle style);
+ [CallWith=ScriptState, RaisesException] void updateInkTrailStartPoint(PointerEvent evt, InkTrailStyle style);
readonly attribute Element? presentationArea;
readonly attribute unsigned long expectedImprovement;
-}; \ No newline at end of file
+};
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc
index 1e7c3d51dba..7a065afb1d2 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc
@@ -63,7 +63,7 @@ class TestDelegatedInkMetadata {
DelegatedInkTrailPresenter* CreatePresenter(Element* element,
LocalFrame* frame) {
- return DelegatedInkTrailPresenter::CreatePresenter(element, frame);
+ return MakeGarbageCollected<DelegatedInkTrailPresenter>(element, frame);
}
} // namespace
@@ -172,10 +172,11 @@ TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport,
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorBLUE);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(100, 100);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(GetDocument().GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ true), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ true), &style, exception_state);
expected_metadata.SetHovering(true);
expected_metadata.SetPoint(pt);
@@ -233,10 +234,11 @@ TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport,
expected_metadata.SetDiameter(style.diameter() * kZoom);
expected_metadata.SetColor(SK_ColorMAGENTA);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(87, 113);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(GetDocument().GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ true), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ true), &style, exception_state);
expected_metadata.SetHovering(true);
pt.Scale(kZoom);
expected_metadata.SetPoint(pt);
@@ -298,10 +300,11 @@ TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, CanvasNotAtOrigin) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorRED);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(380, 175);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(GetDocument().GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ false), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ false), &style, exception_state);
expected_metadata.SetHovering(false);
expected_metadata.SetPoint(pt);
@@ -397,10 +400,11 @@ TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, CanvasInIFrame) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorCYAN);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(380, 375);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ false), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ false), &style, exception_state);
expected_metadata.SetHovering(false);
expected_metadata.SetPoint(
gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset));
@@ -524,10 +528,11 @@ TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, NestedIframe) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorYELLOW);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(350, 375);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ true), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ true), &style, exception_state);
expected_metadata.SetHovering(true);
expected_metadata.SetPoint(gfx::PointF(pt.x() + kInnerIframeLeftOffset,
pt.y() + kInnerIframeTopOffset));
@@ -608,10 +613,11 @@ TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport,
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorWHITE);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(380, 375);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ true), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ true), &style, exception_state);
expected_metadata.SetHovering(true);
expected_metadata.SetPoint(
gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset));
@@ -643,10 +649,11 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, PresentationAreaNotProvided) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorYELLOW);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(70, 109);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(GetDocument().GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ false), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ false), &style, exception_state);
expected_metadata.SetHovering(false);
expected_metadata.SetPoint(pt);
@@ -728,10 +735,11 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasExtendsOutsideOfIframe) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorGREEN);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(102, 67);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ false), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ false), &style, exception_state);
expected_metadata.SetHovering(false);
expected_metadata.SetPoint(
gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset));
@@ -819,10 +827,11 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasLeftAndAboveIframeBoundaries) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorGREEN);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(102, 67);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ true), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ true), &style, exception_state);
expected_metadata.SetHovering(true);
expected_metadata.SetPoint(
gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset));
@@ -941,10 +950,11 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, OuterIframeClipsInnerIframe) {
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorRED);
+ DummyExceptionStateForTesting exception_state;
gfx::PointF pt(357, 401);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
- CreatePointerMoveEvent(pt, /*hovering*/ false), &style);
+ CreatePointerMoveEvent(pt, /*hovering*/ false), &style, exception_state);
expected_metadata.SetHovering(false);
expected_metadata.SetPoint(gfx::PointF(pt.x() + kInnerIframeLeftOffset,
pt.y() + kInnerIframeTopOffset));
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/idls.gni b/chromium/third_party/blink/renderer/modules/delegated_ink/idls.gni
deleted file mode 100644
index 0fe1fd3db0e..00000000000
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "delegated_ink_trail_presenter.idl",
- "ink.idl",
-]
-
-modules_dictionary_idl_files = [ "ink_trail_style.idl" ]
-
-modules_dependency_idl_files = [ "navigator_ink.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/ink.cc b/chromium/third_party/blink/renderer/modules/delegated_ink/ink.cc
index 53f7515bc48..bf7b099d270 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/ink.cc
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/ink.cc
@@ -5,8 +5,10 @@
#include "third_party/blink/renderer/modules/delegated_ink/ink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_ink_presenter_param.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/modules/delegated_ink/delegated_ink_trail_presenter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -26,32 +28,22 @@ Ink* Ink::ink(Navigator& navigator) {
Ink::Ink(Navigator& navigator) : Supplement<Navigator>(navigator) {}
ScriptPromise Ink::requestPresenter(ScriptState* state,
- String type,
- Element* presentationArea) {
+ InkPresenterParam* presenter_param,
+ ExceptionState& exception_state) {
DCHECK(RuntimeEnabledFeatures::DelegatedInkTrailsEnabled());
- DCHECK_EQ(type, "delegated-ink-trail");
-
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(state);
- ScriptPromise promise = resolver->Promise();
if (!state->ContextIsValid()) {
- resolver->Reject(V8ThrowException::CreateError(
- state->GetIsolate(),
- "The object is no longer associated with a window."));
- return promise;
- }
-
- if (type != "delegated-ink-trail") {
- resolver->Reject(V8ThrowException::CreateTypeError(
- state->GetIsolate(), "Unknown type requested."));
- return promise;
+ exception_state.ThrowException(
+ ToExceptionCode(ESErrorType::kError),
+ "The object is no longer associated with a window.");
+ return ScriptPromise();
}
- DelegatedInkTrailPresenter* trail_presenter =
- DelegatedInkTrailPresenter::CreatePresenter(
- presentationArea, GetSupplementable()->DomWindow()->GetFrame());
-
- resolver->Resolve(trail_presenter);
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(state);
+ ScriptPromise promise = resolver->Promise();
+ resolver->Resolve(MakeGarbageCollected<DelegatedInkTrailPresenter>(
+ presenter_param->presentationArea(),
+ GetSupplementable()->DomWindow()->GetFrame()));
return promise;
}
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/ink.h b/chromium/third_party/blink/renderer/modules/delegated_ink/ink.h
index 169cb34a5b4..bdca0b6194a 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/ink.h
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/ink.h
@@ -5,14 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DELEGATED_INK_INK_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DELEGATED_INK_INK_H_
-#include "third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/supplementable.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
-class Element;
+class ExceptionState;
+class InkPresenterParam;
class Navigator;
class ScriptPromise;
class ScriptState;
@@ -26,8 +25,8 @@ class Ink : public ScriptWrappable, public Supplement<Navigator> {
explicit Ink(Navigator&);
ScriptPromise requestPresenter(ScriptState* state,
- String type,
- Element* presentationArea = nullptr);
+ InkPresenterParam* presenter_param,
+ ExceptionState& exception_state);
void Trace(blink::Visitor*) const override;
};
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/ink.idl b/chromium/third_party/blink/renderer/modules/delegated_ink/ink.idl
index 54fe51f24a7..d85a93b4739 100644
--- a/chromium/third_party/blink/renderer/modules/delegated_ink/ink.idl
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/ink.idl
@@ -4,13 +4,9 @@
// https://github.com/WICG/ink-enhancement
-enum PresenterType {
- "delegated-ink-trail"
-};
-
[
RuntimeEnabled=DelegatedInkTrails,
Exposed=Window
] interface Ink {
- [CallWith=ScriptState] Promise<DelegatedInkTrailPresenter> requestPresenter(PresenterType type, optional Element? presentationArea = null);
-}; \ No newline at end of file
+ [CallWith=ScriptState, RaisesException] Promise<DelegatedInkTrailPresenter> requestPresenter(optional InkPresenterParam param = {});
+};
diff --git a/chromium/third_party/blink/renderer/modules/delegated_ink/ink_presenter_param.idl b/chromium/third_party/blink/renderer/modules/delegated_ink/ink_presenter_param.idl
new file mode 100644
index 00000000000..9d9231221d8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/delegated_ink/ink_presenter_param.idl
@@ -0,0 +1,9 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://wicg.github.io/ink-enhancement/
+
+dictionary InkPresenterParam {
+ Element? presentationArea = null;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/OWNERS b/chromium/third_party/blink/renderer/modules/device_orientation/OWNERS
index 72fc2caf38b..ff41043f529 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/OWNERS
@@ -1,2 +1 @@
reillyg@chromium.org
-timvolodine@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration.h
index 759fa1a8d64..2571d4b105f 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_ACCELERATION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_ACCELERATION_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_rotation_rate.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_rotation_rate.h
index c1562720547..ad15969d9bc 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_rotation_rate.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_rotation_rate.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_ROTATION_RATE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_ROTATION_RATE_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/idls.gni b/chromium/third_party/blink/renderer/modules/device_orientation/idls.gni
deleted file mode 100644
index 10da5c80d8a..00000000000
--- a/chromium/third_party/blink/renderer/modules/device_orientation/idls.gni
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "device_motion_event.idl",
- "device_motion_event_acceleration.idl",
- "device_motion_event_rotation_rate.idl",
- "device_orientation_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "device_motion_event_acceleration_init.idl",
- "device_motion_event_init.idl",
- "device_motion_event_rotation_rate_init.idl",
- "device_orientation_event_init.idl",
-]
-
-modules_dependency_idl_files = [
- "window_device_motion.idl",
- "window_device_orientation.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/BUILD.gn b/chromium/third_party/blink/renderer/modules/device_posture/BUILD.gn
new file mode 100644
index 00000000000..24991284506
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2021 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("device_posture") {
+ sources = [
+ "device_posture.cc",
+ "device_posture.h",
+ "navigator_device_posture.cc",
+ "navigator_device_posture.h",
+ ]
+
+ deps = [ "//services/device/public/mojom" ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/DEPS b/chromium/third_party/blink/renderer/modules/device_posture/DEPS
new file mode 100644
index 00000000000..abe9bf40b1a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "+services/device/public/mojom",
+ "-third_party/blink/renderer/modules",
+ "+third_party/blink/renderer/modules/device_posture",
+ "+third_party/blink/renderer/modules/event_target_modules.h",
+ "+third_party/blink/renderer/modules/modules_export.h",
+]
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/DIR_METADATA b/chromium/third_party/blink/renderer/modules/device_posture/DIR_METADATA
new file mode 100644
index 00000000000..7db743ccc5c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>FoldableAPIs"
+}
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/README.md b/chromium/third_party/blink/renderer/modules/device_posture/README.md
new file mode 100644
index 00000000000..0dd8aa0e1a0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/README.md
@@ -0,0 +1,5 @@
+# DevicePosture
+
+This directory contains the implementation of [the DevicePosture API](https://w3c.github.io/device-posture/).
+
+[Device Posture Mojo interface]: ../../../../../services/device/public/mojom/device_posture_provider.mojom
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/device_posture.cc b/chromium/third_party/blink/renderer/modules/device_posture/device_posture.cc
new file mode 100644
index 00000000000..ef4777e9a1c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/device_posture.cc
@@ -0,0 +1,96 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/device_posture/device_posture.h"
+
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/event_target_modules.h"
+
+namespace blink {
+
+namespace {
+
+String PostureToString(device::mojom::blink::DevicePostureType posture) {
+ switch (posture) {
+ case device::mojom::blink::DevicePostureType::kContinuous:
+ return "continuous";
+ case device::mojom::blink::DevicePostureType::kFolded:
+ return "folded";
+ case device::mojom::blink::DevicePostureType::kFoldedOver:
+ return "folded-over";
+ }
+}
+
+} // namespace
+
+DevicePosture::DevicePosture(LocalDOMWindow* window)
+ : ExecutionContextClient(window),
+ service_(GetExecutionContext()),
+ receiver_(this, GetExecutionContext()) {}
+
+DevicePosture::~DevicePosture() = default;
+
+String DevicePosture::type() {
+ EnsureServiceConnection();
+ return PostureToString(posture_);
+}
+
+void DevicePosture::OnPostureChanged(
+ device::mojom::blink::DevicePostureType posture) {
+ if (posture_ == posture)
+ return;
+
+ posture_ = posture;
+ DispatchEvent(*Event::CreateBubble(event_type_names::kChange));
+}
+
+void DevicePosture::EnsureServiceConnection() {
+ auto* context = GetExecutionContext();
+ if (!context)
+ return;
+
+ if (service_.is_bound())
+ return;
+
+ auto task_runner =
+ GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
+ GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(task_runner));
+
+ service_->AddListenerAndGetCurrentPosture(
+ receiver_.BindNewPipeAndPassRemote(task_runner),
+ WTF::Bind(&DevicePosture::OnPostureChanged, WrapPersistent(this)));
+}
+
+void DevicePosture::AddedEventListener(const AtomicString& event_type,
+ RegisteredEventListener& listener) {
+ EventTargetWithInlineData::AddedEventListener(event_type, listener);
+
+ if (event_type != event_type_names::kChange)
+ return;
+
+ ExecutionContext* context = GetExecutionContext();
+ if (!context)
+ return;
+
+ EnsureServiceConnection();
+}
+
+ExecutionContext* DevicePosture::GetExecutionContext() const {
+ return ExecutionContextClient::GetExecutionContext();
+}
+
+const AtomicString& DevicePosture::InterfaceName() const {
+ return event_target_names::kDevicePosture;
+}
+
+void DevicePosture::Trace(blink::Visitor* visitor) const {
+ visitor->Trace(service_);
+ visitor->Trace(receiver_);
+ EventTargetWithInlineData::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/device_posture.h b/chromium/third_party/blink/renderer/modules/device_posture/device_posture.h
new file mode 100644
index 00000000000..a7f37ade1ed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/device_posture.h
@@ -0,0 +1,60 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_POSTURE_DEVICE_POSTURE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_POSTURE_DEVICE_POSTURE_H_
+
+#include "services/device/public/mojom/device_posture_provider.mojom-blink.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.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/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+class LocalDOMWindow;
+
+class MODULES_EXPORT DevicePosture
+ : public EventTargetWithInlineData,
+ public ExecutionContextClient,
+ public device::mojom::blink::DevicePostureProviderClient {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit DevicePosture(LocalDOMWindow*);
+ ~DevicePosture() override;
+
+ // Web-exposed interfaces
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(change, kChange)
+ String type();
+
+ // EventTarget overrides.
+ ExecutionContext* GetExecutionContext() const override;
+ const AtomicString& InterfaceName() const override;
+
+ void Trace(blink::Visitor*) const override;
+
+ private:
+ // DevicePostureServiceClient
+ void OnPostureChanged(
+ device::mojom::blink::DevicePostureType posture) override;
+ void AddedEventListener(const AtomicString& event_type,
+ RegisteredEventListener&) override;
+ void OnServiceConnectionError();
+ void EnsureServiceConnection();
+
+ device::mojom::blink::DevicePostureType posture_ =
+ device::mojom::blink::DevicePostureType::kContinuous;
+ HeapMojoRemote<device::mojom::blink::DevicePostureProvider> service_;
+ HeapMojoReceiver<device::mojom::blink::DevicePostureProviderClient,
+ DevicePosture>
+ receiver_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_POSTURE_DEVICE_POSTURE_H_
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/device_posture.idl b/chromium/third_party/blink/renderer/modules/device_posture/device_posture.idl
new file mode 100644
index 00000000000..e89b0644b75
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/device_posture.idl
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+enum DevicePostureType {
+ "continuous",
+ "folded",
+ "folded-over"
+};
+
+[Exposed=Window, RuntimeEnabled=DevicePosture, SecureContext]
+interface DevicePosture : EventTarget {
+ readonly attribute DevicePostureType type;
+ attribute EventHandler onchange;
+};
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.cc b/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.cc
new file mode 100644
index 00000000000..9c32eecd4cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.cc
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/device_posture/navigator_device_posture.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/modules/device_posture/device_posture.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+// static
+const char NavigatorDevicePosture::kSupplementName[] = "NavigatorDevicePosture";
+
+// static
+DevicePosture* NavigatorDevicePosture::devicePosture(Navigator& navigator) {
+ DCHECK(RuntimeEnabledFeatures::DevicePostureEnabled());
+
+ NavigatorDevicePosture* supplement =
+ Supplement<Navigator>::From<NavigatorDevicePosture>(navigator);
+ if (!supplement) {
+ supplement = MakeGarbageCollected<NavigatorDevicePosture>(navigator);
+ ProvideTo(navigator, supplement);
+ }
+ return supplement->posture_;
+}
+
+NavigatorDevicePosture::NavigatorDevicePosture(Navigator& navigator)
+ : Supplement<Navigator>(navigator),
+ posture_(MakeGarbageCollected<DevicePosture>(
+ GetSupplementable()->DomWindow())) {}
+
+void NavigatorDevicePosture::Trace(Visitor* visitor) const {
+ visitor->Trace(posture_);
+ Supplement<Navigator>::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.h b/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.h
new file mode 100644
index 00000000000..af6d00ad981
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.h
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_POSTURE_NAVIGATOR_DEVICE_POSTURE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_POSTURE_NAVIGATOR_DEVICE_POSTURE_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 DevicePosture;
+
+class NavigatorDevicePosture final
+ : public GarbageCollected<NavigatorDevicePosture>,
+ public Supplement<Navigator> {
+ public:
+ static const char kSupplementName[];
+ static DevicePosture* devicePosture(Navigator&);
+
+ explicit NavigatorDevicePosture(Navigator&);
+
+ void Trace(Visitor*) const override;
+
+ private:
+ Member<DevicePosture> posture_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_POSTURE_NAVIGATOR_DEVICE_POSTURE_H_
diff --git a/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.idl b/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.idl
new file mode 100644
index 00000000000..c6e0f224e5a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_posture/navigator_device_posture.idl
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+ SecureContext,
+ Exposed=(Window),
+ SameObject,
+ RuntimeEnabled=DevicePosture,
+ ImplementedAs=NavigatorDevicePosture
+] partial interface Navigator {
+ readonly attribute DevicePosture devicePosture;
+};
diff --git a/chromium/third_party/blink/renderer/modules/direct_sockets/idls.gni b/chromium/third_party/blink/renderer/modules/direct_sockets/idls.gni
deleted file mode 100644
index 16e849f17a5..00000000000
--- a/chromium/third_party/blink/renderer/modules/direct_sockets/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "tcp_socket.idl",
- "udp_socket.idl",
-]
-
-modules_dictionary_idl_files = [ "socket_options.idl" ]
-
-modules_dependency_idl_files = [ "navigator_socket.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc b/chromium/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc
index e24baab288b..7a6ec2e7cdd 100644
--- a/chromium/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc
+++ b/chromium/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc
@@ -5,10 +5,12 @@
#include "third_party/blink/renderer/modules/direct_sockets/navigator_socket.h"
#include "base/macros.h"
+#include "net/base/net_errors.h"
#include "services/network/public/mojom/tcp_socket.mojom-blink.h"
#include "services/network/public/mojom/udp_socket.mojom-blink.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.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/bindings/modules/v8/v8_socket_options.h"
diff --git a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc
index 242ab35a767..545960f5f6e 100644
--- a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc
+++ b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
diff --git a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc
index d9568fca5f2..68cbef3f257 100644
--- a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc
@@ -5,10 +5,10 @@
#include "third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h"
#include "base/test/mock_callback.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -71,12 +71,13 @@ class StreamCreator {
void ClosePipe() { data_pipe_producer_.reset(); }
// Copies the contents of a v8::Value containing a Uint8Array to a Vector.
- static Vector<uint8_t> ToVector(const V8TestingScope& scope,
+ static Vector<uint8_t> ToVector(V8TestingScope& scope,
v8::Local<v8::Value> v8value) {
Vector<uint8_t> ret;
- DOMUint8Array* value =
- V8Uint8Array::ToImplWithTypeCheck(scope.GetIsolate(), v8value);
+ NotShared<DOMUint8Array> value =
+ NativeValueTraits<NotShared<DOMUint8Array>>::NativeValue(
+ scope.GetIsolate(), v8value, scope.GetExceptionState());
if (!value) {
ADD_FAILURE() << "chunk is not an Uint8Array";
return ret;
@@ -94,8 +95,7 @@ class StreamCreator {
// Performs a single read from |reader|, converting the output to the
// Iterator type. Assumes that the readable stream is not errored.
// static Iterator Read(const V8TestingScope& scope,
- Iterator Read(const V8TestingScope& scope,
- ReadableStreamDefaultReader* reader) {
+ Iterator Read(V8TestingScope& scope, ReadableStreamDefaultReader* reader) {
auto* script_state = scope.GetScriptState();
ScriptPromise read_promise =
reader->read(script_state, ASSERT_NO_EXCEPTION);
@@ -105,7 +105,7 @@ class StreamCreator {
return IteratorFromReadResult(scope, tester.Value().V8Value());
}
- static Iterator IteratorFromReadResult(const V8TestingScope& scope,
+ static Iterator IteratorFromReadResult(V8TestingScope& scope,
v8::Local<v8::Value> result) {
CHECK(result->IsObject());
Iterator ret;
diff --git a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc
index afcc7df9918..5bbcd123a09 100644
--- a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc
+++ b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc
@@ -4,11 +4,13 @@
#include "third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.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"
@@ -204,32 +206,15 @@ ScriptPromise TCPWritableStreamWrapper::SinkWrite(
return ScriptPromise();
}
- auto* isolate = script_state->GetIsolate();
-
- ArrayBufferOrArrayBufferView buffer_source;
- V8ArrayBufferOrArrayBufferView::ToImpl(
- isolate, chunk.V8Value(), buffer_source,
- UnionTypeConversionMode::kNotNullable, exception_state);
+ auto* buffer_source = V8BufferSource::Create(
+ script_state_->GetIsolate(), chunk.V8Value(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
+ DCHECK(buffer_source);
- DCHECK(!buffer_source.IsNull());
-
- // |data| will not be valid when this function returns.
- base::span<const uint8_t> data;
- if (buffer_source.IsArrayBuffer()) {
- const auto* array_buffer = buffer_source.GetAsArrayBuffer();
- data = base::make_span(static_cast<const uint8_t*>(array_buffer->Data()),
- array_buffer->ByteLength());
- } else {
- DCHECK(buffer_source.IsArrayBufferView());
- const auto* array_buffer_view = buffer_source.GetAsArrayBufferView().Get();
- data = base::make_span(
- static_cast<const uint8_t*>(array_buffer_view->BaseAddress()),
- array_buffer_view->byteLength());
- }
-
- return WriteOrCacheData(script_state, data);
+ DOMArrayPiece array_piece(buffer_source);
+ return WriteOrCacheData(script_state,
+ {array_piece.Bytes(), array_piece.ByteLength()});
}
// Attempt to write |data|. Cache anything that could not be written
diff --git a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h
index 483505e8f39..e918fabda4a 100644
--- a/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h
+++ b/chromium/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DIRECT_SOCKETS_TCP_WRITABLE_STREAM_WRAPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DIRECT_SOCKETS_TCP_WRITABLE_STREAM_WRAPPER_H_
+#include "base/allocator/partition_allocator/partition_root.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/modules/document_metadata/OWNERS b/chromium/third_party/blink/renderer/modules/document_metadata/OWNERS
deleted file mode 100644
index c48e48ef750..00000000000
--- a/chromium/third_party/blink/renderer/modules/document_metadata/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-steimel@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/donottrack/idls.gni b/chromium/third_party/blink/renderer/modules/donottrack/idls.gni
deleted file mode 100644
index 5687a466323..00000000000
--- a/chromium/third_party/blink/renderer/modules/donottrack/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "navigator_do_not_track.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/encoding/OWNERS b/chromium/third_party/blink/renderer/modules/encoding/OWNERS
index 0c07f679ffb..b47ce3e9b87 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/encoding/OWNERS
@@ -1,3 +1,2 @@
jsbell@chromium.org
ricea@chromium.org
-kbr@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/encoding/encoding.h b/chromium/third_party/blink/renderer/modules/encoding/encoding.h
index 0c9b0efc28e..209f5d64188 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/encoding.h
+++ b/chromium/third_party/blink/renderer/modules/encoding/encoding.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ENCODING_ENCODING_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ENCODING_ENCODING_H_
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/encoding/idls.gni b/chromium/third_party/blink/renderer/modules/encoding/idls.gni
deleted file mode 100644
index a6ce5aa1743..00000000000
--- a/chromium/third_party/blink/renderer/modules/encoding/idls.gni
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "text_decoder.idl",
- "text_decoder_stream.idl",
- "text_encoder.idl",
- "text_encoder_stream.idl",
-]
-
-modules_dictionary_idl_files = [
- "text_decode_options.idl",
- "text_decoder_options.idl",
- "text_encoder_encode_into_result.idl",
-]
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 0da435edaab..4e31b723b8c 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc
+++ b/chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc
@@ -78,7 +78,6 @@ String TextDecoder::encoding() const {
return name;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String TextDecoder::decode(const V8BufferSource* input,
const TextDecodeOptions* options,
ExceptionState& exception_state) {
@@ -108,32 +107,6 @@ String TextDecoder::decode(const V8BufferSource* input,
return decode(static_cast<const char*>(start), static_cast<uint32_t>(length),
options, exception_state);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-String TextDecoder::decode(const BufferSource& input,
- const TextDecodeOptions* options,
- ExceptionState& exception_state) {
- DCHECK(options);
- // In case of `input` == IDL "missing" special value, default to (nullptr, 0).
- void* start = nullptr;
- size_t length = 0;
- if (input.IsArrayBufferView()) {
- start = input.GetAsArrayBufferView()->BaseAddress();
- length = input.GetAsArrayBufferView()->byteLength();
- } else if (input.IsArrayBuffer()) {
- start = input.GetAsArrayBuffer()->Data();
- length = input.GetAsArrayBuffer()->ByteLength();
- }
-
- if (length > std::numeric_limits<uint32_t>::max()) {
- exception_state.ThrowRangeError(
- "Buffer size exceeds maximum heap object size.");
- return String();
- }
-
- return decode(static_cast<const char*>(start), static_cast<uint32_t>(length),
- options, exception_state);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String TextDecoder::decode(const char* start,
uint32_t length,
diff --git a/chromium/third_party/blink/renderer/modules/encoding/text_decoder.h b/chromium/third_party/blink/renderer/modules/encoding/text_decoder.h
index 0bc718ded32..96d6cefc1a4 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/text_decoder.h
+++ b/chromium/third_party/blink/renderer/modules/encoding/text_decoder.h
@@ -33,7 +33,6 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_text_decode_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_text_decoder_options.h"
@@ -47,8 +46,6 @@ namespace blink {
class ExceptionState;
-typedef ArrayBufferOrArrayBufferView BufferSource;
-
class TextDecoder final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -64,13 +61,9 @@ class TextDecoder final : public ScriptWrappable {
String encoding() const;
bool fatal() const { return fatal_; }
bool ignoreBOM() const { return ignore_bom_; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String decode(const V8BufferSource* input,
const TextDecodeOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- String decode(const BufferSource&, const TextDecodeOptions*, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String decode(ExceptionState&);
private:
diff --git a/chromium/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc b/chromium/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc
index b8bddfc1524..b02958e6c89 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc
@@ -7,12 +7,14 @@
#include <memory>
#include <utility>
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.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_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_text_decoder_options.h"
#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/modules/encoding/encoding.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
@@ -42,42 +44,23 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer {
ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultController* controller,
ExceptionState& exception_state) override {
- ArrayBufferOrArrayBufferView bufferSource;
- V8ArrayBufferOrArrayBufferView::ToImpl(
- script_state_->GetIsolate(), chunk, bufferSource,
- UnionTypeConversionMode::kNotNullable, exception_state);
+ auto* buffer_source = V8BufferSource::Create(script_state_->GetIsolate(),
+ chunk, exception_state);
if (exception_state.HadException())
return ScriptPromise();
// This implements the "get a copy of the bytes held by the buffer source"
// algorithm (https://heycam.github.io/webidl/#dfn-get-buffer-source-copy).
- if (bufferSource.IsArrayBufferView()) {
- const auto* view = bufferSource.GetAsArrayBufferView().Get();
- const char* start = static_cast<const char*>(view->BaseAddress());
- size_t length = view->byteLength();
- if (length > std::numeric_limits<uint32_t>::max()) {
- exception_state.ThrowRangeError(
- "Buffer size exceeds maximum heap object size.");
- return ScriptPromise();
- }
- DecodeAndEnqueue(start, static_cast<uint32_t>(length),
- WTF::FlushBehavior::kDoNotFlush, controller,
- exception_state);
- return ScriptPromise::CastUndefined(script_state_);
- }
- DCHECK(bufferSource.IsArrayBuffer());
- const auto* array_buffer = bufferSource.GetAsArrayBuffer();
- const char* start = static_cast<const char*>(array_buffer->Data());
- size_t length = array_buffer->ByteLength();
- if (length > std::numeric_limits<uint32_t>::max()) {
+ DOMArrayPiece array_piece(buffer_source);
+ if (array_piece.ByteLength() > std::numeric_limits<uint32_t>::max()) {
exception_state.ThrowRangeError(
"Buffer size exceeds maximum heap object size.");
return ScriptPromise();
}
- DecodeAndEnqueue(start, static_cast<uint32_t>(length),
+ DecodeAndEnqueue(static_cast<char*>(array_piece.Data()),
+ static_cast<uint32_t>(array_piece.ByteLength()),
WTF::FlushBehavior::kDoNotFlush, controller,
exception_state);
-
return ScriptPromise::CastUndefined(script_state_);
}
diff --git a/chromium/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc b/chromium/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc
index da6a889469f..d7efa9db3a2 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc
@@ -10,7 +10,7 @@
#include <memory>
#include <utility>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
@@ -101,10 +101,7 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer {
}
private:
- static std::string ReplacementCharacterInUtf8() {
- constexpr char kRawBytes[] = {0xEF, 0xBF, 0xBD};
- return std::string(kRawBytes, sizeof(kRawBytes));
- }
+ static std::string ReplacementCharacterInUtf8() { return "\ufffd"; }
static DOMUint8Array* CreateDOMUint8ArrayFromTwoStdStringsConcatenated(
const std::string& string1,
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/DEPS b/chromium/third_party/blink/renderer/modules/encryptedmedia/DEPS
index 85333ee093c..8673eb6b8ce 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/DEPS
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"-third_party/blink/renderer/modules",
+ "+media/base/content_decryption_module.h",
"+media/base/eme_constants.h",
"+services/metrics/public/cpp/ukm_builders.h",
"+services/metrics/public/cpp/ukm_recorder.h",
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/idls.gni b/chromium/third_party/blink/renderer/modules/encryptedmedia/idls.gni
deleted file mode 100644
index fa457ba6dec..00000000000
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/idls.gni
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "media_encrypted_event.idl",
- "media_key_message_event.idl",
- "media_key_session.idl",
- "media_key_status_map.idl",
- "media_key_system_access.idl",
- "media_keys.idl",
-]
-
-modules_dictionary_idl_files = [
- "media_encrypted_event_init.idl",
- "media_key_message_event_init.idl",
- "media_key_system_configuration.idl",
- "media_key_system_media_capability.idl",
- "media_keys_policy.idl",
-]
-
-modules_dependency_idl_files = [
- "html_media_element_encrypted_media.idl",
- "media_keys_get_status_for_policy.idl",
- "navigator_request_media_key_system_access.idl",
-]
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 89cb7a68fc7..e7cdac56962 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
@@ -28,6 +28,7 @@
#include <cmath>
#include <limits>
+#include "media/base/content_decryption_module.h"
#include "media/base/eme_constants.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_content_decryption_module.h"
@@ -55,6 +56,7 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.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/timer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
@@ -107,6 +109,22 @@ static bool IsPersistentSessionType(WebEncryptedMediaSessionType session_type) {
return false;
}
+V8MediaKeySessionClosedReason::Enum ConvertSessionClosedReason(
+ media::CdmSessionClosedReason reason) {
+ switch (reason) {
+ case media::CdmSessionClosedReason::kInternalError:
+ return V8MediaKeySessionClosedReason::Enum::kInternalError;
+ case media::CdmSessionClosedReason::kClose:
+ return V8MediaKeySessionClosedReason::Enum::kClosedByApplication;
+ case media::CdmSessionClosedReason::kReleaseAcknowledged:
+ return V8MediaKeySessionClosedReason::Enum::kReleaseAcknowledged;
+ case media::CdmSessionClosedReason::kHardwareContextReset:
+ return V8MediaKeySessionClosedReason::Enum::kHardwareContextReset;
+ case media::CdmSessionClosedReason::kResourceEvicted:
+ return V8MediaKeySessionClosedReason::Enum::kResourceEvicted;
+ }
+}
+
static ScriptPromise CreateRejectedPromiseNotCallable(
ExceptionState& exception_state) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
@@ -846,7 +864,7 @@ void MediaKeySession::ActionTimerFired(TimerBase*) {
}
// Queue a task to fire a simple event named keymessage at the new object.
-void MediaKeySession::OnSessionMessage(MessageType message_type,
+void MediaKeySession::OnSessionMessage(media::CdmMessageType message_type,
const unsigned char* message,
size_t message_length) {
DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";
@@ -864,20 +882,16 @@ void MediaKeySession::OnSessionMessage(MessageType message_type,
MediaKeyMessageEventInit* init = MediaKeyMessageEventInit::Create();
switch (message_type) {
- case WebContentDecryptionModuleSession::Client::MessageType::
- kLicenseRequest:
+ case media::CdmMessageType::LICENSE_REQUEST:
init->setMessageType("license-request");
break;
- case WebContentDecryptionModuleSession::Client::MessageType::
- kLicenseRenewal:
+ case media::CdmMessageType::LICENSE_RENEWAL:
init->setMessageType("license-renewal");
break;
- case WebContentDecryptionModuleSession::Client::MessageType::
- kLicenseRelease:
+ case media::CdmMessageType::LICENSE_RELEASE:
init->setMessageType("license-release");
break;
- case WebContentDecryptionModuleSession::Client::MessageType::
- kIndividualizationRequest:
+ case media::CdmMessageType::INDIVIDUALIZATION_REQUEST:
init->setMessageType("individualization-request");
break;
}
@@ -890,7 +904,7 @@ void MediaKeySession::OnSessionMessage(MessageType message_type,
async_event_queue_->EnqueueEvent(FROM_HERE, *event);
}
-void MediaKeySession::OnSessionClosed() {
+void MediaKeySession::OnSessionClosed(media::CdmSessionClosedReason reason) {
// Note that this is the event from the CDM when this session is actually
// closed. The CDM can close a session at any time. Normally it would happen
// as the result of a close() call, but also happens when update() has been
@@ -916,7 +930,12 @@ void MediaKeySession::OnSessionClosed() {
OnSessionExpirationUpdate(std::numeric_limits<double>::quiet_NaN());
// 7. Resolve promise.
- closed_promise_->ResolveWithUndefined();
+ if (RuntimeEnabledFeatures::EncryptedMediaSessionClosedReasonEnabled()) {
+ closed_promise_->Resolve(
+ V8MediaKeySessionClosedReason(ConvertSessionClosedReason(reason)));
+ } else {
+ closed_promise_->ResolveWithUndefined();
+ }
// Stop the CDM from firing any more events for this session.
session_.reset();
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 192e4d43e4e..2dfa7d8347c 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
@@ -27,10 +27,13 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ENCRYPTEDMEDIA_MEDIA_KEY_SESSION_H_
#include <memory>
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_content_decryption_module_session.h"
#include "third_party/blink/public/platform/web_encrypted_media_types.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_media_key_session_closed_reason.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.h"
@@ -40,6 +43,7 @@
namespace media {
enum class EmeInitDataType;
+enum class CdmSessionClosedReason;
}
namespace blink {
@@ -130,10 +134,10 @@ class MediaKeySession final
void RemoveTask(ContentDecryptionModuleResult*);
// WebContentDecryptionModuleSession::Client
- void OnSessionMessage(MessageType,
+ void OnSessionMessage(media::CdmMessageType message_type,
const unsigned char* message,
size_t message_length) override;
- void OnSessionClosed() override;
+ void OnSessionClosed(media::CdmSessionClosedReason reason) override;
void OnSessionExpirationUpdate(double updated_expiry_time_in_ms) override;
void OnSessionKeysChange(const WebVector<WebEncryptedMediaKeyInformation>&,
bool has_additional_usable_key) override;
@@ -156,7 +160,10 @@ class MediaKeySession final
bool is_closing_or_closed_;
// Keep track of the closed promise.
- typedef ScriptPromiseProperty<ToV8UndefinedGenerator, Member<DOMException>>
+ // absl::optional<> is needed because V8MediaKeySessionClosedReason's default
+ // constructor is private.
+ typedef ScriptPromiseProperty<absl::optional<V8MediaKeySessionClosedReason>,
+ Member<DOMException>>
ClosedPromise;
Member<ClosedPromise> closed_promise_;
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.idl b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.idl
index 58481d00b49..adc751e92bb 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.idl
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.idl
@@ -25,6 +25,14 @@
// https://w3c.github.io/encrypted-media/#mediakeysession-interface
+enum MediaKeySessionClosedReason {
+ "internal-error",
+ "closed-by-application",
+ "release-acknowledged",
+ "hardware-context-reset",
+ "resource-evicted"
+};
+
[
Exposed=Window,
ActiveScriptWrappable,
@@ -33,7 +41,10 @@
// session properties
readonly attribute DOMString sessionId;
readonly attribute unrestricted double expiration;
- [CallWith=ScriptState] readonly attribute Promise<void> closed;
+ // When runtime feature EncryptedMediaSessionClosedReason is enabled, the
+ // promise is resolved with "MediaKeySessionClosedReason". Otherwise, it's
+ // resolved with "undefined".
+ [CallWith=ScriptState] readonly attribute Promise<MediaKeySessionClosedReason> closed;
readonly attribute MediaKeyStatusMap keyStatuses;
attribute EventHandler onkeystatuseschange;
attribute EventHandler onmessage;
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
index c982d02e9e4..cd284235e72 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
@@ -8,7 +8,6 @@
#include <limits>
#include "third_party/blink/public/platform/web_data.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
@@ -66,21 +65,13 @@ class MediaKeyStatusMap::MapEntry final
// Represents an Iterator that loops through the set of MapEntrys.
class MapIterationSource final
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
: public PairIterable<Member<V8BufferSource>, String>::IterationSource
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- : public PairIterable<ArrayBufferOrArrayBufferView, String>::IterationSource
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
{
public:
MapIterationSource(MediaKeyStatusMap* map) : map_(map), current_(0) {}
bool Next(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<V8BufferSource>& key,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ArrayBufferOrArrayBufferView& key,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String& value,
ExceptionState&) override {
// This simply advances an index and returns the next value if any,
@@ -89,24 +80,15 @@ class MapIterationSource final
return false;
const auto& entry = map_->at(current_++);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
key = MakeGarbageCollected<V8BufferSource>(entry.KeyId());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- key.SetArrayBuffer(entry.KeyId());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
value = entry.Status();
return true;
}
void Trace(Visitor* visitor) const override {
visitor->Trace(map_);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
PairIterable<Member<V8BufferSource>, String>::IterationSource::Trace(
visitor);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- PairIterable<ArrayBufferOrArrayBufferView, String>::IterationSource::Trace(
- visitor);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
private:
@@ -148,22 +130,14 @@ uint32_t MediaKeyStatusMap::IndexOf(const DOMArrayPiece& key) const {
}
bool MediaKeyStatusMap::has(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* key_id
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferView& key_id
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
uint32_t index = IndexOf(key_id);
return index < entries_.size();
}
ScriptValue MediaKeyStatusMap::get(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* key_id
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferView& key_id
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
uint32_t index = IndexOf(key_id);
if (index >= entries_.size()) {
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.h b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.h
index 6210c87d423..c9e152b795b 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.h
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.h
@@ -23,11 +23,7 @@ class WebData;
// if the event loop runs.
class MediaKeyStatusMap final
: public ScriptWrappable,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
public PairIterable<Member<V8BufferSource>, String>
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- public PairIterable<ArrayBufferOrArrayBufferView, String>
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
{
DEFINE_WRAPPERTYPEINFO();
@@ -49,13 +45,8 @@ class MediaKeyStatusMap final
// IDL attributes / methods
uint32_t size() const { return entries_.size(); }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool has(const V8BufferSource* key_id);
ScriptValue get(ScriptState*, const V8BufferSource* key_id);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool has(const ArrayBufferOrArrayBufferView& key_id);
- ScriptValue get(ScriptState*, const ArrayBufferOrArrayBufferView& key_id);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
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 f475a843f5b..5d8c31f2a71 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
@@ -7,5 +7,5 @@
dictionary MediaKeySystemMediaCapability {
DOMString contentType = "";
DOMString robustness = "";
- [RuntimeEnabled=EncryptedMediaEncryptionSchemeQuery] DOMString? encryptionScheme = null;
+ DOMString? encryptionScheme = null;
};
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 7d8a05e21a8..d4d4e1ed3f2 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
@@ -17,6 +17,7 @@
"DelegatedInkTrail",
"EyeDropper",
"NavigatorManagedData",
+ "DevicePosture",
"MediaKeySession",
"FileWriter",
"GPUDevice",
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 053b53d35a9..74b72feac22 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc
@@ -87,13 +87,6 @@ EventSource* EventSource::Create(ExecutionContext* context,
? WebFeature::kEventSourceDocument
: WebFeature::kEventSourceWorker);
- if (url.IsEmpty()) {
- exception_state.ThrowDOMException(
- 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(
@@ -298,7 +291,7 @@ void EventSource::DidFinishLoading(uint64_t) {
NetworkRequestEnded();
}
-void EventSource::DidFail(const ResourceError& error) {
+void EventSource::DidFail(uint64_t, const ResourceError& error) {
DCHECK(loader_);
if (error.IsCancellation() && state_ == kClosed) {
NetworkRequestEnded();
@@ -321,7 +314,7 @@ void EventSource::DidFail(const ResourceError& error) {
NetworkRequestEnded();
}
-void EventSource::DidFailRedirectCheck() {
+void EventSource::DidFailRedirectCheck(uint64_t) {
DCHECK(loader_);
AbortConnectionAttempt();
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 fa820adae4f..4512214e1e6 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source.h
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source.h
@@ -104,8 +104,8 @@ class MODULES_EXPORT EventSource final
void DidReceiveResponse(uint64_t, const ResourceResponse&) override;
void DidReceiveData(const char*, unsigned) override;
void DidFinishLoading(uint64_t) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t, const ResourceError&) override;
+ void DidFailRedirectCheck(uint64_t) override;
void OnMessageEvent(const AtomicString& event,
const String& data,
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 420f0fb6db1..6ffdc8f93a9 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
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/eventsource/event_source_parser.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/modules/eventsource/event_source.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
diff --git a/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser_test.cc b/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser_test.cc
index d0bb1165806..65583b5570e 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser_test.cc
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser_test.cc
@@ -378,7 +378,7 @@ TEST(EventSourceParserStoppingTest, StopWhileParsing) {
client->SetParser(parser);
const char kInput[] = "data:hello\nid:99\n\nid:44\ndata:bye\n\n";
- parser->AddBytes(kInput, strlen(kInput));
+ parser->AddBytes(kInput, static_cast<uint32_t>(strlen(kInput)));
const auto& events = client->Events();
diff --git a/chromium/third_party/blink/renderer/modules/eventsource/idls.gni b/chromium/third_party/blink/renderer/modules/eventsource/idls.gni
deleted file mode 100644
index e50a5c4b1ce..00000000000
--- a/chromium/third_party/blink/renderer/modules/eventsource/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "event_source.idl" ]
-
-modules_dictionary_idl_files = [ "event_source_init.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_ax_context.cc b/chromium/third_party/blink/renderer/modules/exported/web_ax_context.cc
index 5553fb8bb94..3a0ff3f670f 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_ax_context.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_ax_context.cc
@@ -9,11 +9,12 @@
#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/modules/accessibility/ax_object_cache_impl.h"
+#include "ui/accessibility/ax_mode.h"
namespace blink {
-WebAXContext::WebAXContext(WebDocument root_document)
- : private_(new AXContext(*root_document.Unwrap<Document>())) {}
+WebAXContext::WebAXContext(WebDocument root_document, const ui::AXMode& mode)
+ : private_(new AXContext(*root_document.Unwrap<Document>(), mode)) {}
WebAXContext::~WebAXContext() {}
@@ -31,4 +32,8 @@ WebAXObject WebAXContext::Root() const {
static_cast<AXObjectCacheImpl*>(&private_->GetAXObjectCache())->Root());
}
+const ui::AXMode& WebAXContext::GetAXMode() const {
+ return private_->GetAXMode();
+}
+
} // namespace blink
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 6a7e722d407..6805777bbe3 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
@@ -30,6 +30,7 @@
#include "third_party/blink/public/web/web_ax_object.h"
+#include "skia/ext/skia_matrix_44.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/web_document.h"
@@ -57,7 +58,6 @@
#include "third_party/blink/renderer/modules/accessibility/ax_range.h"
#include "third_party/blink/renderer/modules/accessibility/ax_selection.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/accessibility/ax_action_data.h"
namespace blink {
@@ -228,7 +228,8 @@ WebAXObject WebAXObject::ChildAt(unsigned index) const {
if (IsDetached())
return WebAXObject();
- return WebAXObject(private_->ChildAtIncludingIgnored(int{index}));
+ return WebAXObject(
+ private_->ChildAtIncludingIgnored(static_cast<int>(index)));
}
WebAXObject WebAXObject::ParentObject() const {
@@ -246,13 +247,6 @@ void WebAXObject::Serialize(ui::AXNodeData* node_data,
private_->Serialize(node_data, accessibility_mode);
}
-bool WebAXObject::IsAnchor() const {
- if (IsDetached())
- return false;
-
- return private_->IsAnchor();
-}
-
WebString WebAXObject::AutoComplete() const {
if (IsDetached())
return WebString();
@@ -944,6 +938,11 @@ bool WebAXObject::AccessibilityIsIncludedInTree() const {
if (IsDetached())
return false;
+ DCHECK_GE(private_->GetDocument()->Lifecycle().GetState(),
+ DocumentLifecycle::kLayoutClean)
+ << "Document lifecycle must be at LayoutClean or later, was "
+ << private_->GetDocument()->Lifecycle().GetState();
+
return private_->AccessibilityIsIncludedInTree();
}
@@ -1180,7 +1179,7 @@ void WebAXObject::Dropeffects(
void WebAXObject::GetRelativeBounds(WebAXObject& offset_container,
gfx::RectF& bounds_in_container,
- SkMatrix44& container_transform,
+ skia::Matrix44& container_transform,
bool* clips_children) const {
if (IsDetached())
return;
@@ -1279,6 +1278,9 @@ bool WebAXObject::CanCallAOMEventListenersForTesting() const {
}
WebString WebAXObject::ToString(bool verbose) const {
+ if (private_.IsNull())
+ return WebString("[Null]");
+
return private_->ToString(verbose);
}
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 920066789d1..7387827088d 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
@@ -50,14 +50,9 @@ WebCryptoAlgorithm NormalizeCryptoAlgorithm(
ExceptionState exception_state(isolate, ExceptionState::kQueryContext,
"WebCryptoAlgorithm", "NormalizeAlgorithm");
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8AlgorithmIdentifier* algorithm_identifier =
MakeGarbageCollected<V8AlgorithmIdentifier>(
ScriptValue(isolate, algorithm_object));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- AlgorithmIdentifier algorithm_identifier;
- algorithm_identifier.SetObject(ScriptValue(isolate, algorithm_object));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebCryptoAlgorithm algorithm;
if (!NormalizeAlgorithm(isolate, algorithm_identifier, operation, algorithm,
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_testing_support.cc b/chromium/third_party/blink/renderer/modules/exported/web_testing_support.cc
index b553315feef..d6e9383d072 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_testing_support.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_testing_support.cc
@@ -25,29 +25,23 @@
#include "third_party/blink/public/web/web_testing_support.h"
+#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
+#include "third_party/blink/renderer/bindings/modules/v8/init_idl_interfaces_for_testing.h"
+#include "third_party/blink/renderer/bindings/modules/v8/properties_per_feature_installer_for_testing.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h"
#include "third_party/blink/renderer/core/testing/v8/web_core_test_support.h"
+#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "v8/include/v8.h"
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-#include "third_party/blink/renderer/bindings/modules/v8/init_idl_interfaces_for_testing.h"
-#include "third_party/blink/renderer/bindings/modules/v8/properties_per_feature_installer_for_testing.h"
-#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
-#else
-#include "third_party/blink/renderer/bindings/modules/v8/v8_internals_partial.h"
-#endif
-
namespace blink {
namespace {
RuntimeEnabledFeatures::Backup* g_features_backup = nullptr;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-
InstallPropertiesPerFeatureFuncType
g_original_install_properties_per_feature_func;
@@ -67,11 +61,9 @@ bool EnsureV8BindingsForTestingInternal() {
void EnsureV8BindingsForTesting() {
static bool unused = EnsureV8BindingsForTestingInternal();
- ALLOW_UNUSED_LOCAL(unused);
+ ignore_result(unused);
}
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
} // namespace
WebTestingSupport::WebScopedMockScrollbars::WebScopedMockScrollbars()
@@ -90,21 +82,13 @@ void WebTestingSupport::ResetRuntimeFeatures() {
}
void WebTestingSupport::InjectInternalsObject(WebLocalFrame* frame) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
EnsureV8BindingsForTesting();
-#else
- V8InternalsPartial::Initialize();
-#endif
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
web_core_test_support::InjectInternalsObject(frame->MainWorldScriptContext());
}
void WebTestingSupport::InjectInternalsObject(v8::Local<v8::Context> context) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
EnsureV8BindingsForTesting();
-#else
- V8InternalsPartial::Initialize();
-#endif
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
web_core_test_support::InjectInternalsObject(context);
}
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/BUILD.gn b/chromium/third_party/blink/renderer/modules/eyedropper/BUILD.gn
index 9d70bb3d6ae..eb5b2c6b22d 100644
--- a/chromium/third_party/blink/renderer/modules/eyedropper/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/eyedropper/BUILD.gn
@@ -6,8 +6,6 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("eyedropper") {
sources = [
- "color_select_event.cc",
- "color_select_event.h",
"eye_dropper.cc",
"eye_dropper.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.cc b/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.cc
deleted file mode 100644
index 1e704812b09..00000000000
--- a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/eyedropper/color_select_event.h"
-
-#include "third_party/blink/renderer/bindings/modules/v8/v8_color_select_event_init.h"
-
-namespace blink {
-
-ColorSelectEvent::ColorSelectEvent(const AtomicString& type,
- const ColorSelectEventInit* initializer,
- base::TimeTicks platform_time_stamp,
- SyntheticEventType synthetic_event_type,
- WebMenuSourceType menu_source_type)
- : PointerEvent(type,
- initializer,
- platform_time_stamp,
- synthetic_event_type,
- menu_source_type),
- value_(initializer->value()) {}
-
-ColorSelectEvent* ColorSelectEvent::Create(
- const AtomicString& type,
- const ColorSelectEventInit* initializer,
- base::TimeTicks platform_time_stamp,
- SyntheticEventType synthetic_event_type,
- WebMenuSourceType menu_source_type) {
- return MakeGarbageCollected<ColorSelectEvent>(
- type, initializer, platform_time_stamp, synthetic_event_type,
- menu_source_type);
-}
-
-String ColorSelectEvent::value() const {
- return value_;
-}
-
-void ColorSelectEvent::Trace(Visitor* visitor) const {
- PointerEvent::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.h b/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.h
deleted file mode 100644
index 3b09874450a..00000000000
--- a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_EYEDROPPER_COLOR_SELECT_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_EYEDROPPER_COLOR_SELECT_EVENT_H_
-
-#include "third_party/blink/renderer/bindings/modules/v8/v8_color_select_event_init.h"
-#include "third_party/blink/renderer/core/events/pointer_event.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-
-namespace blink {
-
-class ColorSelectEvent final : public PointerEvent {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- explicit ColorSelectEvent(const AtomicString& type,
- const ColorSelectEventInit* initializer,
- base::TimeTicks platform_time_stamp,
- SyntheticEventType synthetic_event_type,
- WebMenuSourceType menu_source_type);
-
- static ColorSelectEvent* Create(
- const AtomicString& type,
- const ColorSelectEventInit* initializer,
- base::TimeTicks platform_time_stamp = base::TimeTicks::Now(),
- SyntheticEventType synthetic_event_type = kRealOrIndistinguishable,
- WebMenuSourceType menu_source_type = kMenuSourceNone);
-
- String value() const;
-
- void Trace(Visitor*) const override;
-
- private:
- String value_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_EYEDROPPER_COLOR_SELECT_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.idl b/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.idl
deleted file mode 100644
index 97b2bfb845c..00000000000
--- a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/EyeDropper/explainer.md
-
-[Exposed=Window, RuntimeEnabled=EyeDropperAPI]
-interface ColorSelectEvent : PointerEvent {
- constructor(DOMString type, optional ColorSelectEventInit eventInitDict = {});
-
- readonly attribute DOMString value;
-};
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event_init.idl b/chromium/third_party/blink/renderer/modules/eyedropper/color_selection_result.idl
index 0285a737641..57061060dae 100644
--- a/chromium/third_party/blink/renderer/modules/eyedropper/color_select_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/eyedropper/color_selection_result.idl
@@ -4,6 +4,6 @@
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/EyeDropper/explainer.md
-dictionary ColorSelectEventInit : PointerEventInit {
- DOMString value = "";
+dictionary ColorSelectionResult {
+ DOMString sRGBHex;
};
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc b/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc
index 615ae23a1b2..95dac2eb66b 100644
--- a/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc
+++ b/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc
@@ -4,45 +4,100 @@
#include "third_party/blink/renderer/modules/eyedropper/eye_dropper.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/public/common/browser_interface_broker_proxy.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/modules/v8/v8_color_selection_result.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-EyeDropper::EyeDropper(ScriptState* script_state)
- : ExecutionContextClient(ExecutionContext::From(script_state)),
- opened_(false) {}
+EyeDropper::EyeDropper(ExecutionContext* context)
+ : eye_dropper_chooser_(context) {}
-EyeDropper* EyeDropper::Create(ScriptState* script_state) {
- return MakeGarbageCollected<EyeDropper>(script_state);
+EyeDropper* EyeDropper::Create(ExecutionContext* context) {
+ return MakeGarbageCollected<EyeDropper>(context);
}
-ExecutionContext* EyeDropper::GetExecutionContext() const {
- return ExecutionContextClient::GetExecutionContext();
-}
+ScriptPromise EyeDropper::open(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ DCHECK(RuntimeEnabledFeatures::EyeDropperAPIEnabled());
-const AtomicString& EyeDropper::InterfaceName() const {
- return event_target_names::kEyeDropper;
-}
+ if (!script_state->ContextIsValid()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "The object is no longer associated with a window.");
+ return ScriptPromise();
+ }
+
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (!LocalFrame::HasTransientUserActivation(window->GetFrame())) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotAllowedError,
+ "EyeDropper::open() requires user gesture.");
+ return ScriptPromise();
+ }
+
+ if (eye_dropper_chooser_.is_bound()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "EyeDropper is already open.");
+ return ScriptPromise();
+ }
-EyeDropper::~EyeDropper() = default;
+ auto* resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver_->Promise();
-bool EyeDropper::opened() const {
- return opened_;
+ auto* frame = window->GetFrame();
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ eye_dropper_chooser_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kUserInteraction)));
+ eye_dropper_chooser_.set_disconnect_handler(
+ WTF::Bind(&EyeDropper::EndChooser, WrapWeakPersistent(this)));
+ eye_dropper_chooser_->Choose(WTF::Bind(&EyeDropper::EyeDropperResponseHandler,
+ WrapPersistent(this),
+ WrapPersistent(resolver_)));
+
+ return promise;
}
-ScriptPromise EyeDropper::open() {
- // TODO(iopopesc): Add support for open.
- return ScriptPromise();
+void EyeDropper::EyeDropperResponseHandler(ScriptPromiseResolver* resolver,
+ bool success,
+ uint32_t color) {
+ eye_dropper_chooser_.reset();
+
+ if (!resolver->GetExecutionContext() ||
+ resolver->GetExecutionContext()->IsContextDestroyed()) {
+ return;
+ }
+
+ if (success) {
+ ColorSelectionResult* result = ColorSelectionResult::Create();
+ result->setSRGBHex(Color(color).Serialized());
+ resolver->Resolve(result);
+ } else {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kAbortError, "The user canceled the selection."));
+ }
}
-void EyeDropper::close() {
- // TODO(iopopesc): Add support for close.
+void EyeDropper::EndChooser() {
+ eye_dropper_chooser_.reset();
+ if (resolver_) {
+ resolver_->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kOperationError, "EyeDropper is not available."));
+ resolver_ = nullptr;
+ }
}
void EyeDropper::Trace(Visitor* visitor) const {
- EventTargetWithInlineData::Trace(visitor);
- ExecutionContextClient::Trace(visitor);
+ visitor->Trace(eye_dropper_chooser_);
+ visitor->Trace(resolver_);
+ ScriptWrappable::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.h b/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.h
index e131a0b217b..3c44cb33b83 100644
--- a/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.h
+++ b/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.h
@@ -6,52 +6,45 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_EYEDROPPER_EYE_DROPPER_H_
#include "base/macros.h"
+#include "third_party/blink/public/mojom/choosers/color_chooser.mojom-blink.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/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
namespace blink {
+class ExceptionState;
+class ScriptPromise;
+class ScriptPromiseResolver;
+
// The EyeDropper API enables developers to use a browser-supplied eyedropper
// in their web applications. This feature is still
// under development, and is not part of the standard. It can be enabled
// by passing --enable-blink-features=EyeDropperAPI. See
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/EyeDropper/explainer.md
// for more details.
-class EyeDropper final : public EventTargetWithInlineData,
- public ExecutionContextClient {
+class EyeDropper final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- explicit EyeDropper(ScriptState*);
- static EyeDropper* Create(ScriptState*);
+ explicit EyeDropper(ExecutionContext*);
+ static EyeDropper* Create(ExecutionContext*);
EyeDropper(const EyeDropper&) = delete;
EyeDropper& operator=(const EyeDropper&) = delete;
- ~EyeDropper() override;
-
- // EventTarget:
- ExecutionContext* GetExecutionContext() const override;
- const AtomicString& InterfaceName() const override;
-
- // Opens the eyedropper and replaces the cursor with a browser-defined preview
- // and sets opened boolean to true.
- ScriptPromise open();
+ ~EyeDropper() override = default;
- // Exits the eyedropper mode and the cursor returns to its regular
- // functionality. Sets opened boolean to false.
- void close();
-
- // States if the eyedropper is opened and in use.
- bool opened() const;
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(colorselect, kColorselect)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(close, kClose)
+ // Opens the eyedropper and replaces the cursor with a browser-defined
+ // preview.
+ ScriptPromise open(ScriptState*, ExceptionState&);
void Trace(Visitor*) const override;
private:
- bool opened_;
+ void EyeDropperResponseHandler(ScriptPromiseResolver*, bool, uint32_t);
+ void EndChooser();
+
+ HeapMojoRemote<mojom::blink::EyeDropperChooser> eye_dropper_chooser_;
+ Member<ScriptPromiseResolver> resolver_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.idl b/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.idl
index 75278162d47..c6ce2db4100 100644
--- a/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.idl
+++ b/chromium/third_party/blink/renderer/modules/eyedropper/eye_dropper.idl
@@ -5,15 +5,8 @@
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/EyeDropper/explainer.md
[Exposed=Window, RuntimeEnabled=EyeDropperAPI]
-interface EyeDropper : EventTarget {
- [CallWith=ScriptState] constructor();
+interface EyeDropper {
+ [CallWith=ExecutionContext] constructor();
- Promise<void> open();
- void close();
-
- readonly attribute boolean opened;
-
- // Event handler attributes
- attribute EventHandler oncolorselect;
- attribute EventHandler onclose;
+ [CallWith=ScriptState, RaisesException] Promise<ColorSelectionResult> open();
};
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/BUILD.gn b/chromium/third_party/blink/renderer/modules/file_system_access/BUILD.gn
index 6727d5dd0cd..d416279d596 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/BUILD.gn
@@ -10,6 +10,11 @@ blink_modules_sources("file_system_access") {
"data_transfer_item_file_system_access.h",
"file_system_access_error.cc",
"file_system_access_error.h",
+ "file_system_access_file_delegate.h",
+ "file_system_access_incognito_file_delegate.cc",
+ "file_system_access_incognito_file_delegate.h",
+ "file_system_access_regular_file_delegate.cc",
+ "file_system_access_regular_file_delegate.h",
"file_system_directory_handle.cc",
"file_system_directory_handle.h",
"file_system_directory_iterator.cc",
@@ -18,6 +23,8 @@ blink_modules_sources("file_system_access") {
"file_system_file_handle.h",
"file_system_handle.cc",
"file_system_handle.h",
+ "file_system_sync_access_handle.cc",
+ "file_system_sync_access_handle.h",
"file_system_underlying_sink.cc",
"file_system_underlying_sink.h",
"file_system_writable_file_stream.cc",
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/DEPS b/chromium/third_party/blink/renderer/modules/file_system_access/DEPS
index 70275dcd3a7..56acc02764b 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/DEPS
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/DEPS
@@ -1,5 +1,7 @@
include_rules = [
"+base/files/file.h",
+ "+base/files/file_error_or.h",
+ "+base/mac/mac_util.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/event_target_modules.h",
"+third_party/blink/renderer/modules/modules_export.h",
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl b/chromium/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl
index 4409b4b652b..8bafbee254b 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl
@@ -6,4 +6,5 @@
dictionary DirectoryPickerOptions {
DOMString id;
(WellKnownDirectory or FileSystemHandle) startIn;
+ [RuntimeEnabled=FileSystemAccessAPIExperimental] FileSystemPermissionMode mode = "read";
};
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h
new file mode 100644
index 00000000000..bd2c7429acc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h
@@ -0,0 +1,75 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_FILE_DELEGATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_FILE_DELEGATE_H_
+
+#include "base/files/file.h"
+#include "base/files/file_error_or.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+// File object providing a common interface for file operations for an
+// AccessHandle. These methods closely map to base::File equivalents. The
+// implementation of the FileDelegate will depend on whether the renderer is in
+// incognito. All methods are synchronous.
+// A FileDelegate may get accessed by multiple threads, even though the caller
+// has to make sure that there is no concurrent access. This means that at any
+// point in time there is exactly one thread that may access the FileDelegate.
+class FileSystemAccessFileDelegate
+ : public GarbageCollected<FileSystemAccessFileDelegate> {
+ public:
+ virtual ~FileSystemAccessFileDelegate() = default;
+
+ static FileSystemAccessFileDelegate* Create(ExecutionContext* context,
+ base::File backing_file);
+ static FileSystemAccessFileDelegate* CreateForIncognito(
+ ExecutionContext* context,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessFileDelegateHost>
+ incognito_file_remote);
+
+ // Reads the given number of bytes (or until EOF is reached) into the span
+ // starting with the given offset. Returns the number of bytes read, or a file
+ // error on failure.
+ virtual base::FileErrorOr<int> Read(int64_t offset,
+ base::span<uint8_t> data) = 0;
+
+ // Writes the span into the file at the given offset, overwriting any data
+ // that was previously there. Returns the number of bytes written, or a file
+ // error on failure.
+ virtual base::FileErrorOr<int> Write(int64_t offset,
+ const base::span<uint8_t> data) = 0;
+
+ // Asynchronously get the size of the file. Returns the current size of this
+ // file, or a file error on failure.
+ virtual void GetLength(
+ base::OnceCallback<void(base::FileErrorOr<int64_t>)> callback) = 0;
+
+ // Asynchronously truncates the file to the given length. If |length| is
+ // greater than the current size of the file, the file is extended with zeros.
+ // If the file doesn't exist, |false| is returned.
+ virtual void SetLength(int64_t length,
+ base::OnceCallback<void(bool)> callback) = 0;
+
+ // Asynchronously instructs the filesystem to flush the file to disk.
+ virtual void Flush(base::OnceCallback<void(bool)> callback) = 0;
+
+ // Asynchronously close the file. Destroying this object will close the file
+ // automatically.
+ virtual void Close(base::OnceClosure callback) = 0;
+
+ // Returns |true| if the file handle wrapped by this object is valid.
+ virtual bool IsValid() const = 0;
+
+ // GarbageCollected
+ virtual void Trace(Visitor* visitor) const {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_FILE_DELEGATE_H_
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc
new file mode 100644
index 00000000000..ca6869bc5af
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc
@@ -0,0 +1,202 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h"
+
+#include "base/callback_helpers.h"
+#include "base/files/file.h"
+#include "base/files/file_error_or.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/notreached.h"
+#include "base/task/thread_pool.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/system/string_data_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/modules/file_system_access/file_system_access_file_delegate.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace blink {
+
+namespace {
+
+// Creates a mojo data pipe, where the capacity of the data pipe is derived from
+// the provided `data_size`. Returns false if creating the data pipe failed.
+bool CreateDataPipeForSize(uint64_t data_size,
+ mojo::ScopedDataPipeProducerHandle& producer,
+ mojo::ScopedDataPipeConsumerHandle& consumer) {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = BlobUtils::GetDataPipeCapacity(data_size);
+
+ MojoResult rv = CreateDataPipe(&options, producer, consumer);
+ if (rv != MOJO_RESULT_OK) {
+ return false;
+ }
+ return true;
+}
+
+void WriteDataToProducer(
+ mojo::ScopedDataPipeProducerHandle producer_handle,
+ scoped_refptr<base::RefCountedData<Vector<uint8_t>>> data) {
+ DCHECK(!IsMainThread())
+ << "WriteDataToProducer must not be called on the main thread";
+
+ auto data_source = std::make_unique<mojo::StringDataSource>(
+ base::span<const char>(reinterpret_cast<const char*>(data->data.data()),
+ data->data.size()),
+ mojo::StringDataSource::AsyncWritingMode::
+ STRING_STAYS_VALID_UNTIL_COMPLETION);
+
+ auto producer =
+ std::make_unique<mojo::DataPipeProducer>(std::move(producer_handle));
+ mojo::DataPipeProducer* producer_raw = producer.get();
+ // Bind the producer and data to the callback to ensure they stay alive for
+ // the duration of the write.
+ producer_raw->Write(
+ std::move(data_source),
+ WTF::Bind(base::DoNothing::Once<
+ std::unique_ptr<mojo::DataPipeProducer>,
+ scoped_refptr<base::RefCountedData<Vector<uint8_t>>>,
+ MojoResult>(),
+ std::move(producer), std::move(data)));
+}
+
+} // namespace
+
+FileSystemAccessFileDelegate* FileSystemAccessFileDelegate::CreateForIncognito(
+ ExecutionContext* context,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessFileDelegateHost>
+ incognito_file_remote) {
+ return MakeGarbageCollected<FileSystemAccessIncognitoFileDelegate>(
+ context, std::move(incognito_file_remote),
+ base::PassKey<FileSystemAccessFileDelegate>());
+}
+
+FileSystemAccessIncognitoFileDelegate::FileSystemAccessIncognitoFileDelegate(
+ ExecutionContext* context,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessFileDelegateHost>
+ incognito_file_remote,
+ base::PassKey<FileSystemAccessFileDelegate>)
+ : mojo_ptr_(context),
+ task_runner_(context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {
+ mojo_ptr_.Bind(std::move(incognito_file_remote), task_runner_);
+ DCHECK(mojo_ptr_.is_bound());
+}
+
+void FileSystemAccessIncognitoFileDelegate::Trace(Visitor* visitor) const {
+ visitor->Trace(mojo_ptr_);
+ FileSystemAccessFileDelegate::Trace(visitor);
+}
+
+base::FileErrorOr<int> FileSystemAccessIncognitoFileDelegate::Read(
+ int64_t offset,
+ base::span<uint8_t> data) {
+ base::File::Error file_error;
+ int bytes_read;
+ absl::optional<mojo_base::BigBuffer> buffer;
+ mojo_ptr_->Read(offset, data.size(), &buffer, &file_error, &bytes_read);
+
+ CHECK_EQ(buffer.has_value(), file_error == base::File::FILE_OK);
+
+ if (buffer.has_value()) {
+ CHECK_LE(static_cast<uint64_t>(bytes_read), data.size());
+ CHECK_LE(buffer->size(), data.size());
+
+ memcpy(data.data(), buffer->data(), buffer->size());
+ } else {
+ CHECK_EQ(bytes_read, 0);
+ }
+
+ return file_error == base::File::Error::FILE_OK ? bytes_read : file_error;
+}
+
+base::FileErrorOr<int> FileSystemAccessIncognitoFileDelegate::Write(
+ int64_t offset,
+ const base::span<uint8_t> data) {
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ if (!CreateDataPipeForSize(data.size(), producer_handle, consumer_handle)) {
+ return base::File::Error::FILE_ERROR_FAILED;
+ }
+
+ auto ref_counted_data =
+ base::MakeRefCounted<base::RefCountedData<Vector<uint8_t>>>();
+ ref_counted_data->data.Append(data.data(),
+ static_cast<wtf_size_t>(data.size()));
+
+ // Write the data to the data pipe on another thread. This is safe to run in
+ // parallel to the `Write()` call, since the browser can read from the pipe as
+ // data is written. The `Write()` call won't complete until the mojo datapipe
+ // has closed, so we must write to the data pipe on anther thread to be able
+ // to close the pipe when all data has been written.
+ scoped_refptr<base::SequencedTaskRunner> task_runner =
+ base::ThreadPool::CreateSequencedTaskRunner({});
+ PostCrossThreadTask(
+ *task_runner, FROM_HERE,
+ CrossThreadBindOnce(&WriteDataToProducer, std::move(producer_handle),
+ ref_counted_data));
+
+ base::File::Error file_error;
+ int bytes_written;
+ mojo_ptr_->Write(offset, std::move(consumer_handle), &file_error,
+ &bytes_written);
+
+ return file_error == base::File::Error::FILE_OK ? bytes_written : file_error;
+}
+
+void FileSystemAccessIncognitoFileDelegate::GetLength(
+ base::OnceCallback<void(base::FileErrorOr<int64_t>)> callback) {
+ mojo_ptr_->GetLength(WTF::Bind(
+ [](base::OnceCallback<void(base::FileErrorOr<int64_t>)> callback,
+ base::File::Error file_error, uint64_t length) {
+ std::move(callback).Run(
+ file_error == base::File::Error::FILE_OK ? length : file_error);
+ },
+ std::move(callback)));
+}
+
+void FileSystemAccessIncognitoFileDelegate::SetLength(
+ int64_t length,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ if (length < 0) {
+ // This method is expected to finish asynchronously, so post a task to the
+ // current sequence to return the error.
+ task_runner_->PostTask(
+ FROM_HERE, WTF::Bind(std::move(callback),
+ base::File::Error::FILE_ERROR_INVALID_OPERATION));
+ return;
+ }
+
+ mojo_ptr_->SetLength(length, WTF::Bind(std::move(callback)));
+}
+
+void FileSystemAccessIncognitoFileDelegate::Flush(
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ // Flush is a no-op for in-memory file systems. Even if the file delegate is
+ // used for other FS types, writes through the FileSystemOperationRunner are
+ // automatically flushed. If this proves to be too slow, we can consider
+ // changing the FileSystemAccessFileDelegateHostImpl to write with a
+ // FileStreamWriter and only flushing when this method is called.
+ task_runner_->PostTask(FROM_HERE,
+ WTF::Bind(std::move(callback), /*success=*/true));
+}
+
+void FileSystemAccessIncognitoFileDelegate::Close(base::OnceClosure callback) {
+ mojo_ptr_.reset();
+
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ task_runner_->PostTask(FROM_HERE, std::move(callback));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h
new file mode 100644
index 00000000000..a7d308399ab
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_INCOGNITO_FILE_DELEGATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_INCOGNITO_FILE_DELEGATE_H_
+
+#include "base/files/file.h"
+#include "base/files/file_error_or.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_delegate_host.mojom-blink.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+
+namespace blink {
+
+// Incognito implementation of the FileSystemAccessFileDelegate. All file
+// operations are routed to the browser to be written to in-memory files.
+class FileSystemAccessIncognitoFileDelegate final
+ : public FileSystemAccessFileDelegate {
+ public:
+ // Instances should only be constructed via
+ // `FileSystemAccessFileDelegate::CreateForIncognito()`
+ explicit FileSystemAccessIncognitoFileDelegate(
+ ExecutionContext* context,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessFileDelegateHost>
+ incognito_file_remote,
+ base::PassKey<FileSystemAccessFileDelegate>);
+
+ FileSystemAccessIncognitoFileDelegate(
+ const FileSystemAccessIncognitoFileDelegate&) = delete;
+ FileSystemAccessIncognitoFileDelegate& operator=(
+ const FileSystemAccessIncognitoFileDelegate&) = delete;
+
+ base::FileErrorOr<int> Read(int64_t offset,
+ base::span<uint8_t> data) override;
+ base::FileErrorOr<int> Write(int64_t offset,
+ const base::span<uint8_t> data) override;
+
+ void GetLength(
+ base::OnceCallback<void(base::FileErrorOr<int64_t>)> callback) override;
+ void SetLength(int64_t length, base::OnceCallback<void(bool)>) override;
+
+ void Flush(base::OnceCallback<void(bool)> callback) override;
+ void Close(base::OnceClosure callback) override;
+
+ bool IsValid() const override { return mojo_ptr_.is_bound(); }
+
+ void Trace(Visitor*) const override;
+
+ private:
+ // Used to route file operations to the browser.
+ HeapMojoRemote<mojom::blink::FileSystemAccessFileDelegateHost> mojo_ptr_;
+
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_INCOGNITO_FILE_DELEGATE_H_
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc
new file mode 100644
index 00000000000..603061545c5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc
@@ -0,0 +1,208 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h"
+
+#include "base/files/file_error_or.h"
+#include "base/memory/scoped_refptr.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+#if defined(OS_MAC)
+#include "base/mac/mac_util.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#endif
+
+namespace blink {
+
+FileSystemAccessFileDelegate* FileSystemAccessFileDelegate::Create(
+ ExecutionContext* context,
+ base::File backing_file) {
+ return MakeGarbageCollected<FileSystemAccessRegularFileDelegate>(
+ context, std::move(backing_file),
+ base::PassKey<FileSystemAccessFileDelegate>());
+}
+
+FileSystemAccessRegularFileDelegate::FileSystemAccessRegularFileDelegate(
+ ExecutionContext* context,
+ base::File backing_file,
+ base::PassKey<FileSystemAccessFileDelegate>)
+ :
+#if defined(OS_MAC)
+ context_(context),
+ file_utilities_host_(context),
+#endif // defined(OS_MAC)
+ backing_file_(std::move(backing_file)),
+ task_runner_(context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {
+}
+
+base::FileErrorOr<int> FileSystemAccessRegularFileDelegate::Read(
+ int64_t offset,
+ base::span<uint8_t> data) {
+ int size = base::checked_cast<int>(data.size());
+ int result =
+ backing_file_.Read(offset, reinterpret_cast<char*>(data.data()), size);
+ if (result >= 0) {
+ return result;
+ }
+ return base::File::GetLastFileError();
+}
+
+base::FileErrorOr<int> FileSystemAccessRegularFileDelegate::Write(
+ int64_t offset,
+ const base::span<uint8_t> data) {
+ int size = base::checked_cast<int>(data.size());
+ int result =
+ backing_file_.Write(offset, reinterpret_cast<char*>(data.data()), size);
+ if (size == result) {
+ return result;
+ }
+ return base::File::GetLastFileError();
+}
+
+void FileSystemAccessRegularFileDelegate::GetLength(
+ base::OnceCallback<void(base::FileErrorOr<int64_t>)> callback) {
+ auto wrapped_callback =
+ CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)>(
+ std::move(callback));
+
+ // Get file length on a worker thread and reply back to this sequence.
+ worker_pool::PostTask(
+ FROM_HERE, {base::MayBlock()},
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoGetLength,
+ WrapCrossThreadPersistent(this),
+ std::move(wrapped_callback), task_runner_));
+}
+
+// static
+void FileSystemAccessRegularFileDelegate::DoGetLength(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ WTF::CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)>
+ wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ int64_t length = delegate->backing_file_.GetLength();
+
+ // If the length is negative, the file operation failed. Get the last error
+ // now before another file operation might run.
+ base::FileErrorOr<int64_t> result =
+ length >= 0 ? length : base::File::GetLastFileError();
+
+ PostCrossThreadTask(
+ *task_runner, FROM_HERE,
+ CrossThreadBindOnce(std::move(wrapped_callback), std::move(result)));
+}
+
+void FileSystemAccessRegularFileDelegate::SetLength(
+ int64_t length,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ if (length < 0) {
+ // This method is expected to finish asynchronously, so post a task to the
+ // current sequence to return the error.
+ task_runner_->PostTask(
+ FROM_HERE, WTF::Bind(std::move(callback),
+ base::File::Error::FILE_ERROR_INVALID_OPERATION));
+ return;
+ }
+
+#if defined(OS_MAC)
+ // On macOS < 10.15, a sandboxing limitation causes failures in ftruncate()
+ // syscalls issued from renderers. For this reason, base::File::SetLength()
+ // fails in the renderer. We work around this problem by calling ftruncate()
+ // in the browser process. See https://crbug.com/1084565.
+ if (!base::mac::IsAtLeastOS10_15()) {
+ if (!file_utilities_host_.is_bound()) {
+ context_->GetBrowserInterfaceBroker().GetInterface(
+ file_utilities_host_.BindNewPipeAndPassReceiver(task_runner_));
+ }
+ file_utilities_host_->SetLength(
+ std::move(backing_file_), length,
+ WTF::Bind(&FileSystemAccessRegularFileDelegate::DidSetLengthMac,
+ WrapPersistent(this), std::move(callback)));
+ return;
+ }
+#endif // defined(OS_MAC)
+
+ auto wrapped_callback =
+ CrossThreadOnceFunction<void(bool)>(std::move(callback));
+
+ // Truncate file on a worker thread and reply back to this sequence.
+ worker_pool::PostTask(
+ FROM_HERE, {base::MayBlock()},
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoSetLength,
+ WrapCrossThreadPersistent(this),
+ std::move(wrapped_callback), task_runner_, length));
+}
+
+// static
+void FileSystemAccessRegularFileDelegate::DoSetLength(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceFunction<void(bool)> wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ int64_t length) {
+ bool result = delegate->backing_file_.SetLength(length);
+ PostCrossThreadTask(
+ *task_runner, FROM_HERE,
+ CrossThreadBindOnce(std::move(wrapped_callback), std::move(result)));
+}
+
+#if defined(OS_MAC)
+void FileSystemAccessRegularFileDelegate::DidSetLengthMac(
+ base::OnceCallback<void(bool)> callback,
+ base::File file,
+ bool result) {
+ backing_file_ = std::move(file);
+ std::move(callback).Run(result);
+}
+
+#endif // defined(OS_MAC)
+void FileSystemAccessRegularFileDelegate::Flush(
+ base::OnceCallback<void(bool)> callback) {
+ auto wrapped_callback =
+ CrossThreadOnceFunction<void(bool)>(std::move(callback));
+
+ // Flush file on a worker thread and reply back to this sequence.
+ worker_pool::PostTask(
+ FROM_HERE, {base::MayBlock()},
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoFlush,
+ WrapCrossThreadPersistent(this),
+ std::move(wrapped_callback), task_runner_));
+}
+
+// static
+void FileSystemAccessRegularFileDelegate::DoFlush(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceFunction<void(bool)> wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ bool result = delegate->backing_file_.Flush();
+ PostCrossThreadTask(*task_runner, FROM_HERE,
+ CrossThreadBindOnce(std::move(wrapped_callback), result));
+}
+
+void FileSystemAccessRegularFileDelegate::Close(base::OnceClosure callback) {
+ auto wrapped_callback = CrossThreadOnceClosure(std::move(callback));
+
+ // Close file on a worker thread and reply back to this sequence.
+ worker_pool::PostTask(
+ FROM_HERE, {base::MayBlock()},
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoClose,
+ WrapCrossThreadPersistent(this),
+ std::move(wrapped_callback), task_runner_));
+}
+
+// static
+void FileSystemAccessRegularFileDelegate::DoClose(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceClosure wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ delegate->backing_file_.Close();
+ PostCrossThreadTask(*task_runner, FROM_HERE, std::move(wrapped_callback));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h
new file mode 100644
index 00000000000..914abe691a9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h
@@ -0,0 +1,105 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_REGULAR_FILE_DELEGATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_REGULAR_FILE_DELEGATE_H_
+
+#include "base/files/file.h"
+#include "base/files/file_error_or.h"
+#include "base/types/pass_key.h"
+#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+#if defined(OS_MAC)
+#include "third_party/blink/public/mojom/file/file_utilities.mojom-blink.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#endif // defined(OS_MAC)
+
+namespace blink {
+
+// Non-incognito implementation of the FileSystemAccessFileDelegate. This class
+// is a thin wrapper around an OS-level file descriptor.
+class FileSystemAccessRegularFileDelegate final
+ : public FileSystemAccessFileDelegate {
+ public:
+ // Instances should only be constructed via
+ // `FileSystemAccessFileDelegate::Create()`
+ explicit FileSystemAccessRegularFileDelegate(
+ ExecutionContext* context,
+ base::File backing_file,
+ base::PassKey<FileSystemAccessFileDelegate>);
+
+ FileSystemAccessRegularFileDelegate(
+ const FileSystemAccessRegularFileDelegate&) = delete;
+ FileSystemAccessRegularFileDelegate& operator=(
+ const FileSystemAccessRegularFileDelegate&) = delete;
+
+ void Trace(Visitor* visitor) const override {
+ FileSystemAccessFileDelegate::Trace(visitor);
+#if defined(OS_MAC)
+ visitor->Trace(context_);
+ visitor->Trace(file_utilities_host_);
+#endif // defined(OS_MAC)
+ }
+
+ base::FileErrorOr<int> Read(int64_t offset,
+ base::span<uint8_t> data) override;
+ base::FileErrorOr<int> Write(int64_t offset,
+ const base::span<uint8_t> data) override;
+
+ void GetLength(
+ base::OnceCallback<void(base::FileErrorOr<int64_t>)> callback) override;
+ void SetLength(int64_t length,
+ base::OnceCallback<void(bool)> callback) override;
+
+ void Flush(base::OnceCallback<void(bool)> callback) override;
+ void Close(base::OnceClosure callback) override;
+
+ bool IsValid() const override { return backing_file_.IsValid(); }
+
+ private:
+ static void DoGetLength(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)>
+ wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner);
+ static void DoSetLength(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceFunction<void(bool)> wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ int64_t length);
+ static void DoFlush(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceFunction<void(bool)> wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+ static void DoClose(
+ CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
+ CrossThreadOnceClosure wrapped_callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+#if defined(OS_MAC)
+ void DidSetLengthMac(base::OnceCallback<void(bool)> callback,
+ base::File file,
+ bool result);
+
+ // We need the FileUtilitiesHost only on Mac, where we have to execute
+ // base::File::SetLength on the browser process, see crbug.com/1084565.
+ // We need the context_ to create the instance of FileUtilitiesHost lazily.
+ Member<ExecutionContext> context_;
+ HeapMojoRemote<mojom::blink::FileUtilitiesHost> file_utilities_host_;
+#endif // defined(OS_MAC)
+
+ // The file on disk backing the parent FileSystemFileHandle.
+ base::File backing_file_;
+
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_REGULAR_FILE_DELEGATE_H_
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc
index 176cfff3102..1788cadaf06 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc
@@ -241,6 +241,19 @@ void FileSystemDirectoryHandle::RequestPermissionImpl(
mojo_ptr_->RequestPermission(writable, std::move(callback));
}
+void FileSystemDirectoryHandle::RemoveImpl(
+ const FileSystemRemoveOptions* options,
+ base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr)> callback) {
+ if (!mojo_ptr_.is_bound()) {
+ std::move(callback).Run(mojom::blink::FileSystemAccessError::New(
+ mojom::blink::FileSystemAccessStatus::kInvalidState,
+ base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"));
+ return;
+ }
+
+ mojo_ptr_->Remove(options->recursive(), std::move(callback));
+}
+
void FileSystemDirectoryHandle::IsSameEntryImpl(
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)>
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h
index 0ade0d772fe..99a5b3e9770 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h
@@ -62,6 +62,10 @@ class FileSystemDirectoryHandle final : public FileSystemHandle {
bool writable,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr,
mojom::blink::PermissionStatus)>) override;
+ void RemoveImpl(
+ const FileSystemRemoveOptions* options,
+ base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr)>)
+ override;
// IsSameEntry for directories is implemented in terms of resolve, as resolve
// also can be used to figure out if two directories are the same entry.
void IsSameEntryImpl(
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc
index 0308f9053c2..81fffc24659 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink.h"
@@ -13,6 +14,8 @@
#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/file_system_access/file_system_access_error.h"
+#include "third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h"
+#include "third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.h"
#include "third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
@@ -20,6 +23,7 @@
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
+
using mojom::blink::FileSystemAccessErrorPtr;
FileSystemFileHandle::FileSystemFileHandle(
@@ -93,6 +97,60 @@ ScriptPromise FileSystemFileHandle::getFile(ScriptState* script_state,
return result;
}
+ScriptPromise FileSystemFileHandle::createSyncAccessHandle(
+ ScriptState* script_state,
+ ExceptionState& exception_state) {
+ // TODO(fivedots): Check if storage access is allowed.
+ if (!mojo_ptr_.is_bound()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "");
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise result = resolver->Promise();
+
+ mojo_ptr_->OpenAccessHandle(WTF::Bind(
+ [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result,
+ mojom::blink::FileSystemAccessAccessHandleFilePtr file,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessAccessHandleHost>
+ access_handle_remote) {
+ if (result->status != mojom::blink::FileSystemAccessStatus::kOk) {
+ file_system_access_error::Reject(resolver, *result);
+ return;
+ }
+ DCHECK(!file.is_null());
+ DCHECK(access_handle_remote.is_valid());
+
+ ExecutionContext* context = resolver->GetExecutionContext();
+ if (!context)
+ return;
+
+ FileSystemAccessFileDelegate* file_delegate = nullptr;
+ if (file->is_regular_file()) {
+ file_delegate = FileSystemAccessFileDelegate::Create(
+ context, std::move(file->get_regular_file()));
+ } else if (file->is_incognito_file_delegate()) {
+ file_delegate = FileSystemAccessFileDelegate::CreateForIncognito(
+ context, std::move(file->get_incognito_file_delegate()));
+ }
+
+ if (!file_delegate || !file_delegate->IsValid()) {
+ file_system_access_error::Reject(
+ resolver,
+ *mojom::blink::FileSystemAccessError::New(
+ mojom::blink::FileSystemAccessStatus::kFileError,
+ base::File::Error::FILE_ERROR_FAILED, "File not valid"));
+ return;
+ }
+ resolver->Resolve(MakeGarbageCollected<FileSystemSyncAccessHandle>(
+ context, std::move(file_delegate),
+ std::move(access_handle_remote)));
+ },
+ WrapPersistent(resolver)));
+
+ return result;
+}
+
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>
FileSystemFileHandle::Transfer() {
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> result;
@@ -132,6 +190,19 @@ void FileSystemFileHandle::RequestPermissionImpl(
mojo_ptr_->RequestPermission(writable, std::move(callback));
}
+void FileSystemFileHandle::RemoveImpl(
+ const FileSystemRemoveOptions* options,
+ base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr)> callback) {
+ if (!mojo_ptr_.is_bound()) {
+ std::move(callback).Run(mojom::blink::FileSystemAccessError::New(
+ mojom::blink::FileSystemAccessStatus::kInvalidState,
+ base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"));
+ return;
+ }
+
+ mojo_ptr_->Remove(std::move(callback));
+}
+
void FileSystemFileHandle::IsSameEntryImpl(
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)>
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h
index 1c46d619a0f..6748ba35497 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h
@@ -29,6 +29,10 @@ class FileSystemFileHandle final : public FileSystemHandle {
ExceptionState&);
ScriptPromise getFile(ScriptState*, ExceptionState&);
+ // TODO(fivedots): Define if this method should be generally exposed or only
+ // on files backed by the Origin Private File System.
+ ScriptPromise createSyncAccessHandle(ScriptState*, ExceptionState&);
+
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> Transfer()
override;
@@ -46,6 +50,10 @@ class FileSystemFileHandle final : public FileSystemHandle {
bool writable,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr,
mojom::blink::PermissionStatus)>) override;
+ void RemoveImpl(
+ const FileSystemRemoveOptions* options,
+ base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr)>)
+ override;
void IsSameEntryImpl(
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)>)
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl
index f8c4cf50bdc..297de85ee3f 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl
@@ -13,4 +13,11 @@
Promise<FileSystemWritableFileStream> createWritable(optional FileSystemCreateWritableOptions options = {});
[CallWith=ScriptState, RaisesException] Promise<File> getFile();
+
+ [
+ CallWith=ScriptState,
+ RaisesException,
+ Exposed=DedicatedWorker,
+ RuntimeEnabled=FileSystemAccessAccessHandle
+ ] Promise<FileSystemSyncAccessHandle> createSyncAccessHandle();
};
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc
index 6ad38845f22..bb4f3ab03dc 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc
@@ -91,6 +91,22 @@ ScriptPromise FileSystemHandle::requestPermission(
return result;
}
+ScriptPromise FileSystemHandle::remove(ScriptState* script_state,
+ const FileSystemRemoveOptions* options) {
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise result = resolver->Promise();
+
+ RemoveImpl(
+ options,
+ WTF::Bind(
+ [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result) {
+ file_system_access_error::ResolveOrReject(resolver, *result);
+ },
+ WrapPersistent(resolver)));
+
+ return result;
+}
+
ScriptPromise FileSystemHandle::isSameEntry(ScriptState* script_state,
FileSystemHandle* other) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.h
index 8ef5fe4ca0e..58290704ba6 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.h
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.h
@@ -20,6 +20,7 @@
namespace blink {
class ExecutionContext;
class FileSystemHandlePermissionDescriptor;
+class FileSystemRemoveOptions;
class FileSystemHandle : public ScriptWrappable, public ExecutionContextClient {
DEFINE_WRAPPERTYPEINFO();
@@ -40,6 +41,8 @@ class FileSystemHandle : public ScriptWrappable, public ExecutionContextClient {
ScriptPromise requestPermission(ScriptState*,
const FileSystemHandlePermissionDescriptor*);
+ ScriptPromise remove(ScriptState*, const FileSystemRemoveOptions* options);
+
ScriptPromise isSameEntry(ScriptState*, FileSystemHandle* other);
// Grab a handle to a transfer token. This may return an invalid PendingRemote
@@ -57,6 +60,9 @@ class FileSystemHandle : public ScriptWrappable, public ExecutionContextClient {
bool writable,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr,
mojom::blink::PermissionStatus)>) = 0;
+ virtual void RemoveImpl(
+ const FileSystemRemoveOptions* options,
+ base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr)>) = 0;
virtual void IsSameEntryImpl(
mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other,
base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr,
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl
index bff43870a46..3d67f1c2c55 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl
@@ -27,6 +27,11 @@ enum FileSystemHandleKind {
[CallWith=ScriptState] Promise<PermissionState> requestPermission(
optional FileSystemHandlePermissionDescriptor descriptor = {});
+ [
+ CallWith=ScriptState,
+ RuntimeEnabled=FileSystemAccessAPIExperimental
+ ] Promise<void> remove(optional FileSystemRemoveOptions options = {});
+
[CallWith=ScriptState, Measure]
Promise<boolean> isSameEntry(FileSystemHandle other);
};
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_read_write_options.idl b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_read_write_options.idl
new file mode 100644
index 00000000000..28bc992f791
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_read_write_options.idl
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(fivedots): Replace link with explainer, once it lands.
+// https://docs.google.com/document/d/1g7ZCqZ5NdiU7oqyCpsc2iZ7rRAY1ZXO-9VoG4LfP7fM
+
+dictionary FileSystemReadWriteOptions {
+ unsigned long long at;
+};
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.cc
new file mode 100644
index 00000000000..0ca78782923
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.cc
@@ -0,0 +1,325 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.h"
+
+#include "base/files/file_error_or.h"
+#include "build/build_config.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/modules/file_system_access/file_system_access_file_delegate.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+
+namespace blink {
+
+FileSystemSyncAccessHandle::FileSystemSyncAccessHandle(
+ ExecutionContext* context,
+ FileSystemAccessFileDelegate* file_delegate,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessAccessHandleHost>
+ access_handle_remote)
+ : file_delegate_(file_delegate),
+ access_handle_remote_(context),
+ resolver_task_runner_(
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {
+ access_handle_remote_.Bind(
+ std::move(access_handle_remote),
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI));
+ DCHECK(access_handle_remote_.is_bound());
+}
+
+void FileSystemSyncAccessHandle::Trace(Visitor* visitor) const {
+ ScriptWrappable::Trace(visitor);
+ visitor->Trace(file_delegate_);
+ visitor->Trace(access_handle_remote_);
+ visitor->Trace(queued_close_resolver_);
+}
+
+ScriptPromise FileSystemSyncAccessHandle::close(ScriptState* script_state) {
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ auto promise = resolver->Promise();
+
+ if (is_closed_ || !access_handle_remote_.is_bound()) {
+ // close() is idempotent.
+ resolver->Resolve();
+ return promise;
+ }
+
+ is_closed_ = true;
+
+ DCHECK(!queued_close_resolver_) << "Close logic kicked off twice";
+ queued_close_resolver_ = resolver;
+
+ if (!io_pending_) {
+ // Pretend that a close() promise was queued behind an I/O operation, and
+ // the operation just finished. This is less logic than handling the
+ // non-queued case separately.
+ DispatchQueuedClose();
+ }
+
+ return promise;
+}
+
+void FileSystemSyncAccessHandle::DispatchQueuedClose() {
+ DCHECK(!io_pending_)
+ << "Dispatching close() concurrently with other I/O operations is racy";
+
+ if (!queued_close_resolver_)
+ return;
+
+ DCHECK(is_closed_) << "close() resolver queued without setting closed_";
+ ScriptPromiseResolver* resolver = queued_close_resolver_;
+ queued_close_resolver_ = nullptr;
+
+ // Access file delegate directly rather than through accessor method, which
+ // checks `io_pending_`.
+ DCHECK(file_delegate_->IsValid())
+ << "file I/O operation queued after file closed";
+
+ file_delegate_->Close(WTF::Bind(
+ [](ScriptPromiseResolver* resolver,
+ FileSystemSyncAccessHandle* access_handle) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ access_handle->access_handle_remote_->Close(WTF::Bind(
+ [](ScriptPromiseResolver* resolver) { resolver->Resolve(); },
+ WrapPersistent(resolver)));
+ },
+ WrapPersistent(resolver), WrapPersistent(this)));
+}
+
+ScriptPromise FileSystemSyncAccessHandle::flush(
+ ScriptState* script_state,
+ ExceptionState& exception_state) {
+ if (is_closed_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The file was already closed");
+ return ScriptPromise();
+ }
+
+ if (!EnterOperation()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Another I/O operation is in progress on the same file");
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise result = resolver->Promise();
+
+ DCHECK(file_delegate()->IsValid())
+ << "file I/O operation queued after file closed";
+
+ file_delegate()->Flush(WTF::Bind(WTF::Bind(
+ [](ScriptPromiseResolver* resolver,
+ FileSystemSyncAccessHandle* access_handle, bool success) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ access_handle->ExitOperation();
+ if (!success) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kInvalidStateError,
+ "flush failed"));
+ return;
+ }
+ resolver->Resolve();
+ },
+ WrapPersistent(resolver), WrapPersistent(this))));
+
+ return result;
+}
+
+ScriptPromise FileSystemSyncAccessHandle::getSize(
+ ScriptState* script_state,
+ ExceptionState& exception_state) {
+ if (is_closed_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The file was already closed");
+ return ScriptPromise();
+ }
+
+ if (!EnterOperation()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Another I/O operation is in progress on the same file");
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise result = resolver->Promise();
+
+ DCHECK(file_delegate()->IsValid())
+ << "file I/O operation queued after file closed";
+
+ file_delegate()->GetLength(WTF::Bind(
+ [](ScriptPromiseResolver* resolver,
+ FileSystemSyncAccessHandle* access_handle,
+ base::FileErrorOr<int64_t> error_or_length) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ access_handle->ExitOperation();
+ if (error_or_length.is_error()) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kInvalidStateError,
+ "getSize failed"));
+ return;
+ }
+ resolver->Resolve(error_or_length.value());
+ },
+ WrapPersistent(resolver), WrapPersistent(this)));
+
+ return result;
+}
+
+ScriptPromise FileSystemSyncAccessHandle::truncate(
+ ScriptState* script_state,
+ uint64_t size,
+ ExceptionState& exception_state) {
+ if (is_closed_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The file was already closed");
+ return ScriptPromise();
+ }
+
+ if (!EnterOperation()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Another I/O operation is in progress on the same file");
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise result = resolver->Promise();
+
+ DCHECK(file_delegate()->IsValid())
+ << "file I/O operation queued after file closed";
+
+ file_delegate()->SetLength(
+ base::checked_cast<int64_t>(size),
+ WTF::Bind(
+ [](ScriptPromiseResolver* resolver,
+ FileSystemSyncAccessHandle* access_handle, bool success) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ access_handle->ExitOperation();
+ if (!success) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(),
+ DOMExceptionCode::kInvalidStateError, "truncate failed"));
+ return;
+ }
+ resolver->Resolve(success);
+ },
+ WrapPersistent(resolver), WrapPersistent(this)));
+
+ return result;
+}
+
+uint64_t FileSystemSyncAccessHandle::read(
+ MaybeShared<DOMArrayBufferView> buffer,
+ FileSystemReadWriteOptions* options,
+ ExceptionState& exception_state) {
+ OperationScope scope(this);
+ if (!scope.entered_operation()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "There is a pending operation on the access handle");
+ return 0;
+ }
+
+ if (!file_delegate()->IsValid() || is_closed_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The access handle was already closed");
+ return 0;
+ }
+
+ size_t read_size = buffer->byteLength();
+ uint8_t* read_data = static_cast<uint8_t*>(buffer->BaseAddressMaybeShared());
+ uint64_t file_offset = options->at();
+ if (!base::CheckedNumeric<int64_t>(file_offset).IsValid()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Cannot read at given offset");
+ return 0;
+ }
+
+ base::FileErrorOr<int> result =
+ file_delegate()->Read(file_offset, {read_data, read_size});
+
+ if (result.is_error()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Failed to read the content");
+ return 0;
+ }
+ return base::as_unsigned(result.value());
+}
+
+uint64_t FileSystemSyncAccessHandle::write(
+ MaybeShared<DOMArrayBufferView> buffer,
+ FileSystemReadWriteOptions* options,
+ ExceptionState& exception_state) {
+ OperationScope scope(this);
+ if (!scope.entered_operation()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "There is a pending operation on the access handle");
+ return 0;
+ }
+
+ if (!file_delegate()->IsValid() || is_closed_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The access handle was already closed");
+ return 0;
+ }
+
+ uint64_t file_offset = options->at();
+ if (!base::CheckedNumeric<int64_t>(file_offset).IsValid()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Cannot write at given offset");
+ return 0;
+ }
+
+ size_t write_size = buffer->byteLength();
+ if (!base::CheckedNumeric<int>(write_size).IsValid()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Cannot write more than 2GB");
+ }
+
+ uint8_t* write_data = static_cast<uint8_t*>(buffer->BaseAddressMaybeShared());
+
+ int64_t write_end_offset;
+ if (!base::CheckAdd(file_offset, write_size)
+ .AssignIfValid(&write_end_offset)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "No capacity available for this operation");
+ return 0;
+ }
+ DCHECK_GE(write_end_offset, 0);
+
+ base::FileErrorOr<int> result =
+ file_delegate()->Write(file_offset, {write_data, write_size});
+ if (result.is_error()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Failed to write to the access handle");
+ return 0;
+ }
+
+ return base::as_unsigned(result.value());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.h
new file mode 100644
index 00000000000..46b6a4ca2db
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.h
@@ -0,0 +1,138 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_SYNC_ACCESS_HANDLE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_SYNC_ACCESS_HANDLE_H_
+
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_access_handle_host.mojom-blink.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.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/modules/v8/v8_file_system_read_write_options.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
+#include "third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+
+namespace blink {
+
+class ScriptPromiseResolver;
+
+class FileSystemSyncAccessHandle final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit FileSystemSyncAccessHandle(
+ ExecutionContext* context,
+ FileSystemAccessFileDelegate* file_delegate,
+ mojo::PendingRemote<mojom::blink::FileSystemAccessAccessHandleHost>
+ access_handle_host);
+
+ FileSystemSyncAccessHandle(const FileSystemSyncAccessHandle&) = delete;
+ FileSystemSyncAccessHandle& operator=(const FileSystemSyncAccessHandle&) =
+ delete;
+
+ // GarbageCollected
+ void Trace(Visitor* visitor) const override;
+
+ ScriptPromise close(ScriptState*);
+
+ ScriptPromise flush(ScriptState*, ExceptionState&);
+
+ ScriptPromise getSize(ScriptState*, ExceptionState&);
+
+ ScriptPromise truncate(ScriptState*, uint64_t size, ExceptionState&);
+
+ uint64_t read(MaybeShared<DOMArrayBufferView> buffer,
+ FileSystemReadWriteOptions* options,
+ ExceptionState&);
+
+ uint64_t write(MaybeShared<DOMArrayBufferView> buffer,
+ FileSystemReadWriteOptions* options,
+ ExceptionState&);
+
+ private:
+ void DispatchQueuedClose();
+
+ bool EnterOperation() {
+ if (io_pending_)
+ return false;
+ io_pending_ = true;
+ return true;
+ }
+
+ void ExitOperation() {
+ DCHECK(io_pending_);
+ io_pending_ = false;
+ DispatchQueuedClose();
+ }
+ FileSystemAccessFileDelegate* file_delegate() {
+ DCHECK(io_pending_);
+ return file_delegate_.Get();
+ }
+
+ // The {OperationScope} is used to call {EnterOperation()} and
+ // {ExitOperation()} in the synchronous functions {read} and {write}.
+ // {OperationScope} calls {ExitOperation()} automatically in its destructor.
+ class OperationScope {
+ STACK_ALLOCATED();
+
+ public:
+ explicit OperationScope(FileSystemSyncAccessHandle* handle)
+ : handle_(handle) {
+ entered_operation_ = handle_->EnterOperation();
+ }
+
+ ~OperationScope() {
+ if (entered_operation_) {
+ handle_->ExitOperation();
+ }
+ }
+
+ bool entered_operation() const { return entered_operation_; }
+
+ private:
+ FileSystemSyncAccessHandle* handle_;
+ bool entered_operation_;
+ };
+
+ // Interface that provides file-like access to the backing storage.
+ // The file delegate should only be accessed through the {file_delegate()}
+ // getter.
+ Member<FileSystemAccessFileDelegate> file_delegate_;
+
+ // Mojo pipe that holds the renderer's write lock on the file.
+ HeapMojoRemote<mojom::blink::FileSystemAccessAccessHandleHost>
+ access_handle_remote_;
+
+ // True when an I/O operation other than close is underway.
+ //
+ // Set to {true} whenever an async operation is started, and back to {false}
+ // when the operation resolves its promise.
+ // All I/O operations throw an exception if they get called when
+ // {io_pending_} is true, except for close(). This ensures that at most one
+ // I/O operation is underway at any given time. When close() is called when
+ // {io_pending_} is true, then the close() operation gets queued right after
+ // the pending I/O operation.
+ // {io_pending_} should only be set with the {EnterOperation()} and
+ // {ExitOperation()} functions.
+ bool io_pending_ = false;
+
+ bool is_closed_ = false;
+
+ // Non-null when a close() I/O is queued behind another I/O operation.
+ //
+ // Set when close() is called while another I/O operation is underway. Cleared
+ // when the queued close() operation is queued.
+ Member<ScriptPromiseResolver> queued_close_resolver_;
+
+ // Schedules resolving Promises with file I/O results.
+ const scoped_refptr<base::SequencedTaskRunner> resolver_task_runner_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_SYNC_ACCESS_HANDLE_H_
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.idl b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.idl
new file mode 100644
index 00000000000..acfe7347257
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_sync_access_handle.idl
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(fivedots): Replace link with explainer, once it lands.
+// https://docs.google.com/document/d/1g7ZCqZ5NdiU7oqyCpsc2iZ7rRAY1ZXO-9VoG4LfP7fM
+
+[
+ Exposed=DedicatedWorker,
+ RuntimeEnabled=FileSystemAccessAccessHandle,
+ SecureContext
+] interface FileSystemSyncAccessHandle {
+ [CallWith=ScriptState] Promise<void> close();
+
+[
+ CallWith=ScriptState, RaisesException
+] Promise<void> flush();
+
+[
+ CallWith=ScriptState, RaisesException
+] Promise<unsigned long long> getSize();
+
+[
+ CallWith = ScriptState, RaisesException
+] Promise<void> truncate([EnforceRange] unsigned long long size);
+
+[
+ RaisesException
+] unsigned long long read([AllowShared] ArrayBufferView buffer,
+ FileSystemReadWriteOptions options);
+[
+ RaisesException
+] unsigned long long write([AllowShared] ArrayBufferView buffer,
+ FileSystemReadWriteOptions options);
+};
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc
index ad275e1ad80..32d35a81d8f 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc
@@ -8,11 +8,13 @@
#include "net/base/net_errors.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.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/native_value_traits_impl.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/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_blob_usvstring.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_arraybuffer_arraybufferview_blob_usvstring_writeparams.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_write_params.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
@@ -45,34 +47,20 @@ ScriptPromise FileSystemUnderlyingSink::write(
ScriptValue chunk,
WritableStreamDefaultController* controller,
ExceptionState& exception_state) {
- v8::Local<v8::Value> value = chunk.V8Value();
-
- ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams input;
- V8ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams::ToImpl(
- script_state->GetIsolate(), value, input,
- UnionTypeConversionMode::kNotNullable, exception_state);
+ auto* input = NativeValueTraits<
+ V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams>::
+ NativeValue(script_state->GetIsolate(), chunk.V8Value(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
- if (input.IsNull()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot provide null object");
- return ScriptPromise();
- }
-
- if (input.IsWriteParams()) {
- return HandleParams(script_state, std::move(*input.GetAsWriteParams()),
+ if (input->IsWriteParams()) {
+ return HandleParams(script_state, *input->GetAsWriteParams(),
exception_state);
}
- ArrayBufferOrArrayBufferViewOrBlobOrUSVString write_data;
- V8ArrayBufferOrArrayBufferViewOrBlobOrUSVString::ToImpl(
- script_state->GetIsolate(), value, write_data,
- UnionTypeConversionMode::kNotNullable, exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
- return WriteData(script_state, offset_, std::move(write_data),
- exception_state);
+ auto* write_data =
+ input->GetAsV8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString();
+ return WriteData(script_state, offset_, write_data, exception_state);
}
ScriptPromise FileSystemUnderlyingSink::close(ScriptState* script_state,
@@ -332,9 +320,9 @@ bool CreateDataPipe(uint64_t data_size,
ScriptPromise FileSystemUnderlyingSink::WriteData(
ScriptState* script_state,
uint64_t position,
- const ArrayBufferOrArrayBufferViewOrBlobOrUSVString& data,
+ const V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString* data,
ExceptionState& exception_state) {
- DCHECK(!data.IsNull());
+ DCHECK(data);
if (!writer_remote_.is_bound() || pending_operation_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
@@ -343,31 +331,44 @@ ScriptPromise FileSystemUnderlyingSink::WriteData(
}
std::unique_ptr<mojo::DataPipeProducer::DataSource> data_source;
- if (data.IsArrayBuffer()) {
- DOMArrayBuffer* array_buffer = data.GetAsArrayBuffer();
- data_source = std::make_unique<mojo::StringDataSource>(
- base::span<const char>(static_cast<const char*>(array_buffer->Data()),
- array_buffer->ByteLength()),
- mojo::StringDataSource::AsyncWritingMode::
- STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION);
- } else if (data.IsArrayBufferView()) {
- DOMArrayBufferView* array_buffer_view = data.GetAsArrayBufferView().Get();
- data_source = std::make_unique<mojo::StringDataSource>(
- base::span<const char>(
- static_cast<const char*>(array_buffer_view->BaseAddress()),
- array_buffer_view->byteLength()),
- mojo::StringDataSource::AsyncWritingMode::
- STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION);
- } else if (data.IsUSVString()) {
- data_source = std::make_unique<mojo::StringDataSource>(
- StringUTF8Adaptor(data.GetAsUSVString()).AsStringPiece(),
- mojo::StringDataSource::AsyncWritingMode::
- STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION);
+ switch (data->GetContentType()) {
+ case V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString::ContentType::
+ kArrayBuffer: {
+ DOMArrayBuffer* array_buffer = data->GetAsArrayBuffer();
+ data_source = std::make_unique<mojo::StringDataSource>(
+ base::span<const char>(static_cast<const char*>(array_buffer->Data()),
+ array_buffer->ByteLength()),
+ mojo::StringDataSource::AsyncWritingMode::
+ STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION);
+ break;
+ }
+ case V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString::ContentType::
+ kArrayBufferView: {
+ DOMArrayBufferView* array_buffer_view =
+ data->GetAsArrayBufferView().Get();
+ data_source = std::make_unique<mojo::StringDataSource>(
+ base::span<const char>(
+ static_cast<const char*>(array_buffer_view->BaseAddress()),
+ array_buffer_view->byteLength()),
+ mojo::StringDataSource::AsyncWritingMode::
+ STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION);
+ break;
+ }
+ case V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString::ContentType::
+ kBlob:
+ break;
+ case V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString::ContentType::
+ kUSVString:
+ data_source = std::make_unique<mojo::StringDataSource>(
+ StringUTF8Adaptor(data->GetAsUSVString()).AsStringPiece(),
+ mojo::StringDataSource::AsyncWritingMode::
+ STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION);
+ break;
}
- DCHECK(data_source || data.IsBlob());
+ DCHECK(data_source || data->IsBlob());
uint64_t data_size =
- data_source ? data_source->GetLength() : data.GetAsBlob()->size();
+ data_source ? data_source->GetLength() : data->GetAsBlob()->size();
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
@@ -377,14 +378,14 @@ ScriptPromise FileSystemUnderlyingSink::WriteData(
}
WriterHelper* helper;
- if (data.IsBlob()) {
+ if (data->IsBlob()) {
mojo::PendingRemote<mojom::blink::BlobReaderClient> reader_client;
helper =
new BlobWriterHelper(reader_client.InitWithNewPipeAndPassReceiver(),
WTF::Bind(&FileSystemUnderlyingSink::WriteComplete,
WrapPersistent(this)));
- data.GetAsBlob()->GetBlobDataHandle()->ReadAll(std::move(producer_handle),
- std::move(reader_client));
+ data->GetAsBlob()->GetBlobDataHandle()->ReadAll(std::move(producer_handle),
+ std::move(reader_client));
} else {
auto producer =
std::make_unique<mojo::DataPipeProducer>(std::move(producer_handle));
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h
index 87d7eca9405..d93bdf15571 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_UNDERLYING_SINK_H_
#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.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/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -16,6 +15,7 @@ namespace blink {
class ExceptionState;
class ScriptPromiseResolver;
+class V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString;
class WriteParams;
class FileSystemUnderlyingSink final : public UnderlyingSinkBase {
@@ -44,7 +44,7 @@ class FileSystemUnderlyingSink final : public UnderlyingSinkBase {
ScriptPromise WriteData(
ScriptState*,
uint64_t position,
- const ArrayBufferOrArrayBufferViewOrBlobOrUSVString& data,
+ const V8UnionArrayBufferOrArrayBufferViewOrBlobOrUSVString* data,
ExceptionState&);
ScriptPromise Truncate(ScriptState*, uint64_t size, ExceptionState&);
ScriptPromise Seek(ScriptState*, uint64_t offset, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc
index b747270da51..b34a8dedcf3 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.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/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_queuing_strategy_init.h"
@@ -58,18 +57,13 @@ FileSystemWritableFileStream* FileSystemWritableFileStream::Create(
ScriptPromise FileSystemWritableFileStream::write(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionBlobOrBufferSourceOrUSVStringOrWriteParams* data,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams& data,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
WritableStreamDefaultWriter* writer =
WritableStream::AcquireDefaultWriter(script_state, this, exception_state);
if (exception_state.HadException())
return ScriptPromise();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
v8::Local<v8::Value> v8_data;
{
v8::TryCatch v8_try_block(script_state->GetIsolate());
@@ -83,10 +77,6 @@ ScriptPromise FileSystemWritableFileStream::write(
ScriptPromise promise = writer->write(
script_state, ScriptValue(script_state->GetIsolate(), v8_data),
exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise promise = writer->write(
- script_state, ScriptValue::From(script_state, data), exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WritableStreamDefaultWriter::Release(script_state, writer);
return promise;
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h
index aa2b85e0ac6..81598a289ef 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h
@@ -8,7 +8,6 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/modules/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string_or_write_params.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
@@ -31,17 +30,10 @@ class FileSystemWritableFileStream final : public WritableStream {
void Trace(Visitor* visitor) const override;
// IDL defined functions specific to FileSystemWritableFileStream.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise write(
ScriptState*,
const V8UnionBlobOrBufferSourceOrUSVStringOrWriteParams* data,
ExceptionState&);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise write(
- ScriptState*,
- const ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams& data,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise truncate(ScriptState*, uint64_t size, ExceptionState&);
ScriptPromise seek(ScriptState*, uint64_t offset, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc b/chromium/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc
index d3a3bf23c25..961d7cc1766 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc
@@ -11,16 +11,18 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-shared.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_union_usvstring_usvstringsequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_directory_picker_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_picker_accept_type.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_open_file_picker_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_save_file_picker_options.h"
-#include "third_party/blink/renderer/bindings/modules/v8/well_known_directory_or_file_system_handle.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_filesystemhandle_wellknowndirectory.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
@@ -138,15 +140,21 @@ Vector<mojom::blink::ChooseFileSystemEntryAcceptsOptionPtr> ConvertAccepts(
}
mimeTypes.push_back(type);
- if (a.second.IsUSVString()) {
- if (!AddExtension(a.second.GetAsUSVString(), extensions,
- exception_state))
- return {};
- } else {
- for (const auto& extension : a.second.GetAsUSVStringSequence()) {
- if (!AddExtension(extension, extensions, exception_state))
+ switch (a.second->GetContentType()) {
+ case V8UnionUSVStringOrUSVStringSequence::ContentType::kUSVString:
+ if (!AddExtension(a.second->GetAsUSVString(), extensions,
+ exception_state)) {
return {};
- }
+ }
+ break;
+ case V8UnionUSVStringOrUSVStringSequence::ContentType::
+ kUSVStringSequence:
+ for (const auto& extension : a.second->GetAsUSVStringSequence()) {
+ if (!AddExtension(extension, extensions, exception_state)) {
+ return {};
+ }
+ }
+ break;
}
}
result.emplace_back(
@@ -309,13 +317,17 @@ ScriptPromise GlobalFileSystemAccess::showOpenFilePicker(
mojom::blink::WellKnownDirectory::kDefault;
mojo::PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken> token;
if (options->hasStartIn()) {
- auto& start_in = options->startIn();
- if (start_in.IsWellKnownDirectory()) {
- well_known_starting_directory =
- ConvertWellKnownDirectory(start_in.GetAsWellKnownDirectory());
- }
- if (start_in.IsFileSystemHandle()) {
- token = start_in.GetAsFileSystemHandle()->Transfer();
+ const auto* start_in = options->startIn();
+ switch (start_in->GetContentType()) {
+ case V8UnionFileSystemHandleOrWellKnownDirectory::ContentType::
+ kFileSystemHandle:
+ token = start_in->GetAsFileSystemHandle()->Transfer();
+ break;
+ case V8UnionFileSystemHandleOrWellKnownDirectory::ContentType::
+ kWellKnownDirectory:
+ well_known_starting_directory =
+ ConvertWellKnownDirectory(start_in->GetAsWellKnownDirectory());
+ break;
}
}
@@ -368,13 +380,17 @@ ScriptPromise GlobalFileSystemAccess::showSaveFilePicker(
mojom::blink::WellKnownDirectory::kDefault;
mojo::PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken> token;
if (options->hasStartIn()) {
- auto& start_in = options->startIn();
- if (start_in.IsWellKnownDirectory()) {
- well_known_starting_directory =
- ConvertWellKnownDirectory(start_in.GetAsWellKnownDirectory());
- }
- if (start_in.IsFileSystemHandle()) {
- token = start_in.GetAsFileSystemHandle()->Transfer();
+ const auto* start_in = options->startIn();
+ switch (start_in->GetContentType()) {
+ case V8UnionFileSystemHandleOrWellKnownDirectory::ContentType::
+ kFileSystemHandle:
+ token = start_in->GetAsFileSystemHandle()->Transfer();
+ break;
+ case V8UnionFileSystemHandleOrWellKnownDirectory::ContentType::
+ kWellKnownDirectory:
+ well_known_starting_directory =
+ ConvertWellKnownDirectory(start_in->GetAsWellKnownDirectory());
+ break;
}
}
@@ -417,13 +433,17 @@ ScriptPromise GlobalFileSystemAccess::showDirectoryPicker(
mojom::blink::WellKnownDirectory::kDefault;
mojo::PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken> token;
if (options->hasStartIn()) {
- auto& start_in = options->startIn();
- if (start_in.IsWellKnownDirectory()) {
- well_known_starting_directory =
- ConvertWellKnownDirectory(start_in.GetAsWellKnownDirectory());
- }
- if (start_in.IsFileSystemHandle()) {
- token = start_in.GetAsFileSystemHandle()->Transfer();
+ const auto* start_in = options->startIn();
+ switch (start_in->GetContentType()) {
+ case V8UnionFileSystemHandleOrWellKnownDirectory::ContentType::
+ kFileSystemHandle:
+ token = start_in->GetAsFileSystemHandle()->Transfer();
+ break;
+ case V8UnionFileSystemHandleOrWellKnownDirectory::ContentType::
+ kWellKnownDirectory:
+ well_known_starting_directory =
+ ConvertWellKnownDirectory(start_in->GetAsWellKnownDirectory());
+ break;
}
}
@@ -431,7 +451,9 @@ ScriptPromise GlobalFileSystemAccess::showDirectoryPicker(
if (exception_state.HadException())
return ScriptPromise();
- auto directory_picker_options = mojom::blink::DirectoryPickerOptions::New();
+ bool request_writable = options->mode() == "readwrite";
+ auto directory_picker_options =
+ mojom::blink::DirectoryPickerOptions::New(request_writable);
return ShowFilePickerImpl(
script_state, window,
mojom::blink::FilePickerOptions::NewDirectoryPickerOptions(
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/idls.gni b/chromium/third_party/blink/renderer/modules/file_system_access/idls.gni
deleted file mode 100644
index 2d4f3232423..00000000000
--- a/chromium/third_party/blink/renderer/modules/file_system_access/idls.gni
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "file_system_directory_iterator.idl",
- "file_system_directory_handle.idl",
- "file_system_file_handle.idl",
- "file_system_handle.idl",
- "file_system_writable_file_stream.idl",
-]
-
-modules_dictionary_idl_files = [
- "directory_picker_options.idl",
- "file_picker_accept_type.idl",
- "file_picker_options.idl",
- "file_system_create_writable_options.idl",
- "file_system_get_directory_options.idl",
- "file_system_get_file_options.idl",
- "file_system_handle_permission_descriptor.idl",
- "file_system_remove_options.idl",
- "open_file_picker_options.idl",
- "save_file_picker_options.idl",
- "write_params.idl",
-]
-
-modules_dependency_idl_files = [
- "data_transfer_item_file_system_access.idl",
- "storage_manager_file_system_access.idl",
- "window_file_system_access.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc b/chromium/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc
index c21b28d29ed..0ab45a57dfd 100644
--- a/chromium/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc
+++ b/chromium/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc
@@ -10,6 +10,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/DEPS b/chromium/third_party/blink/renderer/modules/filesystem/DEPS
index 0baabac330a..637bee5701f 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/DEPS
+++ b/chromium/third_party/blink/renderer/modules/filesystem/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+base/files/file.h",
+ "+components/services/filesystem/public/mojom/types.mojom-blink.h",
"+services/metrics/public/cpp",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/event_target_modules.h",
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/OWNERS b/chromium/third_party/blink/renderer/modules/filesystem/OWNERS
index b39c0796866..c441c168337 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/filesystem/OWNERS
@@ -1,5 +1,3 @@
mek@chromium.org
jsbell@chromium.org
-kinuko@chromium.org
pwnall@chromium.org
-nhiroki@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc b/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc
index 3fad596fd2f..3f6ed5d23b8 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "build/build_config.h"
+#include "components/services/filesystem/public/mojom/types.mojom-blink.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/idls.gni b/chromium/third_party/blink/renderer/modules/filesystem/idls.gni
deleted file mode 100644
index 80a222d8908..00000000000
--- a/chromium/third_party/blink/renderer/modules/filesystem/idls.gni
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "directory_entry.idl",
- "directory_entry_sync.idl",
- "directory_reader.idl",
- "directory_reader_sync.idl",
- "dom_file_system.idl",
- "dom_file_system_sync.idl",
- "entries_callback.idl",
- "entry.idl",
- "entry_callback.idl",
- "entry_sync.idl",
- "error_callback.idl",
- "file_callback.idl",
- "file_entry.idl",
- "file_entry_sync.idl",
- "file_system_callback.idl",
- "file_writer.idl",
- "file_writer_callback.idl",
- "file_writer_sync.idl",
- "metadata.idl",
- "metadata_callback.idl",
-]
-
-modules_dictionary_idl_files = [ "file_system_flags.idl" ]
-
-modules_dependency_idl_files = [
- "data_transfer_item_file_system.idl",
- "dedicated_worker_global_scope_file_system.idl",
- "dev_tools_host_file_system.idl",
- "html_input_element_file_system.idl",
- "shared_worker_global_scope_file_system.idl",
- "window_file_system.idl",
-]
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 ca23699b21e..c25ebcd3f27 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
@@ -59,6 +59,7 @@ class LocalFileSystem final : public GarbageCollected<LocalFileSystem>,
static const char kSupplementName[];
explicit LocalFileSystem(ExecutionContext&);
+ ~LocalFileSystem() final = default;
void ResolveURL(const KURL&,
std::unique_ptr<ResolveURICallbacks>,
diff --git a/chromium/third_party/blink/renderer/modules/font_access/font_manager.cc b/chromium/third_party/blink/renderer/modules/font_access/font_manager.cc
index 81bdcd1f39c..98a6086f891 100644
--- a/chromium/third_party/blink/renderer/modules/font_access/font_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/font_access/font_manager.cc
@@ -61,7 +61,7 @@ ScriptPromise FontManager::query(ScriptState* script_state,
void FontManager::Trace(blink::Visitor* visitor) const {
ScriptWrappable::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
+ ExecutionContextLifecycleObserver::Trace(visitor);
}
void FontManager::DidShowFontChooser(
diff --git a/chromium/third_party/blink/renderer/modules/font_access/idls.gni b/chromium/third_party/blink/renderer/modules/font_access/idls.gni
deleted file mode 100644
index 83654aa295b..00000000000
--- a/chromium/third_party/blink/renderer/modules/font_access/idls.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "font_metadata.idl",
- "font_table_map.idl",
- "font_manager.idl",
-]
-
-modules_dictionary_idl_files = [ "query_options.idl" ]
-
-modules_dependency_idl_files = [ "navigator_fonts.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/font_access/navigator_fonts.cc b/chromium/third_party/blink/renderer/modules/font_access/navigator_fonts.cc
index 0d5e82cd912..bd566af08fc 100644
--- a/chromium/third_party/blink/renderer/modules/font_access/navigator_fonts.cc
+++ b/chromium/third_party/blink/renderer/modules/font_access/navigator_fonts.cc
@@ -36,6 +36,7 @@ class NavigatorFontsImpl final : public GarbageCollected<NavigatorFontsImpl<T>>,
}
explicit NavigatorFontsImpl(T& navigator) : Supplement<T>(navigator) {}
+ ~NavigatorFontsImpl() final = default;
FontManager* GetFontManager(ExecutionContext* context) const {
if (!font_manager_) {
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/OWNERS b/chromium/third_party/blink/renderer/modules/gamepad/OWNERS
index a53699ce8a8..1aef6446885 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/gamepad/OWNERS
@@ -1,3 +1,2 @@
-b.kelemen@samsung.com
bajones@chromium.org
mattreynolds@chromium.org
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
index 71c7448c33a..674d74037ec 100644
--- 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
@@ -151,11 +151,9 @@ void GamepadSharedMemoryReader::GamepadDisconnected(
listener_->DidDisconnectGamepad(index, gamepad);
}
-void GamepadSharedMemoryReader::GamepadButtonOrAxisChanged(
- uint32_t index,
- const device::Gamepad& gamepad) {
- if (listener_)
- listener_->ButtonOrAxisDidChange(index, gamepad);
+void GamepadSharedMemoryReader::GamepadChanged(
+ device::mojom::blink::GamepadChangesPtr change) {
+ // TODO(crbug.com/856290): use these calls to Generate Button Event.
}
} // 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
index fd836d83b64..e15e41339ae 100644
--- 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
@@ -54,8 +54,7 @@ class GamepadSharedMemoryReader
const device::Gamepad& gamepad) override;
void GamepadDisconnected(uint32_t index,
const device::Gamepad& gamepad) override;
- void GamepadButtonOrAxisChanged(uint32_t index,
- const device::Gamepad& gamepad) override;
+ void GamepadChanged(device::mojom::blink::GamepadChangesPtr changes) override;
base::ReadOnlySharedMemoryRegion renderer_shared_buffer_region_;
base::ReadOnlySharedMemoryMapping renderer_shared_buffer_mapping_;
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/idls.gni b/chromium/third_party/blink/renderer/modules/gamepad/idls.gni
deleted file mode 100644
index 9e7a155f720..00000000000
--- a/chromium/third_party/blink/renderer/modules/gamepad/idls.gni
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "gamepad.idl",
- "gamepad_axis_event.idl",
- "gamepad_button.idl",
- "gamepad_button_event.idl",
- "gamepad_event.idl",
- "gamepad_haptic_actuator.idl",
- "gamepad_list.idl",
-]
-
-modules_dictionary_idl_files = [
- "gamepad_axis_event_init.idl",
- "gamepad_button_event_init.idl",
- "gamepad_effect_parameters.idl",
- "gamepad_event_init.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_gamepad.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/OWNERS b/chromium/third_party/blink/renderer/modules/geolocation/OWNERS
index 1ebe75b6510..7959d9d5701 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/geolocation/OWNERS
@@ -1,4 +1 @@
mattreynolds@chromium.org
-
-# Original (legacy) owner.
-mcasas@chromium.org
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 2ea6c284a2b..767413467c4 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
@@ -26,7 +26,7 @@ class GeoNotifier final : public GarbageCollected<GeoNotifier>,
V8PositionCallback*,
V8PositionErrorCallback*,
const PositionOptions*);
- ~GeoNotifier() = default;
+ ~GeoNotifier() override = default;
void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override { return "GeoNotifier"; }
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h
index f4a7537751c..c750a93e1b3 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_COORDINATES_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_COORDINATES_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/event_modules.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/modules/geolocation/geolocation_watchers.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
index 602564837df..b1edaf5545a 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
@@ -16,6 +16,7 @@ class GeolocationWatchers final : public GarbageCollected<GeolocationWatchers>,
public NameClient {
public:
GeolocationWatchers() = default;
+ ~GeolocationWatchers() override = default;
void Trace(Visitor*) const;
const char* NameInHeapSnapshot() const override {
return "GeolocationWatchers";
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/idls.gni b/chromium/third_party/blink/renderer/modules/geolocation/idls.gni
deleted file mode 100644
index f3a1927d3c6..00000000000
--- a/chromium/third_party/blink/renderer/modules/geolocation/idls.gni
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "geolocation.idl",
- "geolocation_coordinates.idl",
- "geolocation_position.idl",
- "geolocation_position_error.idl",
-]
-
-modules_dictionary_idl_files = [ "position_options.idl" ]
-
-modules_dependency_idl_files = [ "navigator_geolocation.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/handwriting/handwriting_hints.idl b/chromium/third_party/blink/renderer/modules/handwriting/handwriting_hints.idl
index 20ba6faa5c0..5ca898a4d97 100644
--- a/chromium/third_party/blink/renderer/modules/handwriting/handwriting_hints.idl
+++ b/chromium/third_party/blink/renderer/modules/handwriting/handwriting_hints.idl
@@ -7,6 +7,6 @@
dictionary HandwritingHints {
DOMString recognitionType = "text";
DOMString inputType = "mouse";
- DOMString textContext = "";
+ DOMString textContext;
unsigned long alternatives = 3;
};
diff --git a/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters.cc b/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters.cc
index 7e66b26da71..ca079412aac 100644
--- a/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters.cc
+++ b/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters.cc
@@ -68,7 +68,9 @@ TypeConverter<HandwritingHintsPtr, blink::HandwritingHints*>::Convert(
auto output = handwriting::mojom::blink::HandwritingHints::New();
output->recognition_type = input->recognitionType();
output->input_type = input->inputType();
- output->text_context = input->textContext();
+ if (input->hasTextContext()) {
+ output->text_context = input->textContext();
+ }
output->alternatives = input->alternatives();
return output;
}
diff --git a/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc b/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc
index 489f9613329..cbe9084da6e 100644
--- a/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc
@@ -94,10 +94,24 @@ TEST(HandwritingTypeConvertersTest, IdlHandwritingHintsToMojo) {
ASSERT_FALSE(mojo_hints.is_null());
EXPECT_EQ(mojo_hints->recognition_type, "recognition type");
EXPECT_EQ(mojo_hints->input_type, "input type");
+ ASSERT_FALSE(mojo_hints->text_context.IsNull());
EXPECT_EQ(mojo_hints->text_context, "text context");
EXPECT_EQ(mojo_hints->alternatives, 10u);
}
+// Tests whether the default values of `HandwritingHints` can be correctly
+// converted, especially for `textContext` which is not-set by default.
+TEST(HandwritingTypeConvertersTest, IdlHandwritingHintsToDefaultValue) {
+ auto* idl_hints = blink::HandwritingHints::Create();
+
+ auto mojo_hints = mojo::ConvertTo<HandwritingHintsPtr>(idl_hints);
+ ASSERT_FALSE(mojo_hints.is_null());
+ EXPECT_EQ(mojo_hints->recognition_type, "text");
+ EXPECT_EQ(mojo_hints->input_type, "mouse");
+ EXPECT_TRUE(mojo_hints->text_context.IsNull());
+ EXPECT_EQ(mojo_hints->alternatives, 3u);
+}
+
TEST(HandwritingTypeConvertersTest, IdlHandwritingFeatureQueryToMojo) {
V8TestingScope v8_testing_scope;
auto* idl_query = blink::HandwritingFeatureQuery::Create();
diff --git a/chromium/third_party/blink/renderer/modules/handwriting/idls.gni b/chromium/third_party/blink/renderer/modules/handwriting/idls.gni
deleted file mode 100644
index c41de06552b..00000000000
--- a/chromium/third_party/blink/renderer/modules/handwriting/idls.gni
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "handwriting_drawing.idl",
- "handwriting_recognizer.idl",
- "handwriting_stroke.idl",
-]
-
-modules_dictionary_idl_files = [
- "handwriting_feature_query.idl",
- "handwriting_feature_query_result.idl",
- "handwriting_hints.idl",
- "handwriting_model_constraint.idl",
- "handwriting_point.idl",
- "handwriting_prediction.idl",
- "handwriting_drawing_segment.idl",
- "handwriting_segment.idl",
-]
-
-modules_dependency_idl_files =
- [ "navigator_handwriting_recognition_service.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid.cc b/chromium/third_party/blink/renderer/modules/hid/hid.cc
index f5a0c1714b2..5ce8014faae 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid.cc
@@ -153,15 +153,15 @@ void HID::DeviceRemoved(device::mojom::blink::HidDeviceInfoPtr device_info) {
}
void HID::DeviceChanged(device::mojom::blink::HidDeviceInfoPtr device_info) {
- auto* device = device_cache_.at(device_info->guid);
- if (!device) {
- // If the GUID is not in the |device_cache_| then this is the first time we
- // have been notified for this device.
- DeviceAdded(std::move(device_info));
+ auto it = device_cache_.find(device_info->guid);
+ if (it != device_cache_.end()) {
+ it->value->UpdateDeviceInfo(std::move(device_info));
return;
}
- device->UpdateDeviceInfo(std::move(device_info));
+ // If the GUID is not in the |device_cache_| then this is the first time we
+ // have been notified for this device.
+ DeviceAdded(std::move(device_info));
}
ScriptPromise HID::getDevices(ScriptState* script_state,
@@ -244,13 +244,15 @@ void HID::Connect(
}
HIDDevice* HID::GetOrCreateDevice(device::mojom::blink::HidDeviceInfoPtr info) {
- const String guid = info->guid;
- HIDDevice* device = device_cache_.at(guid);
- if (!device) {
- device = MakeGarbageCollected<HIDDevice>(this, std::move(info),
- GetExecutionContext());
- device_cache_.insert(guid, device);
+ auto it = device_cache_.find(info->guid);
+ if (it != device_cache_.end()) {
+ return it->value;
}
+
+ const String guid = info->guid;
+ HIDDevice* device = MakeGarbageCollected<HIDDevice>(this, std::move(info),
+ GetExecutionContext());
+ device_cache_.insert(guid, device);
return device;
}
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_device.cc b/chromium/third_party/blink/renderer/modules/hid/hid_device.cc
index b10e14ebf2f..de68f8116bf 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_device.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_device.cc
@@ -35,7 +35,6 @@ const char kUnexpectedClose[] = "The device was closed unexpectedly.";
const char kArrayBufferTooBig[] =
"The provided ArrayBuffer exceeds the maximum allowed size.";
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Vector<uint8_t> ConvertBufferSource(const V8BufferSource* buffer) {
DCHECK(buffer);
Vector<uint8_t> vector;
@@ -54,24 +53,6 @@ Vector<uint8_t> ConvertBufferSource(const V8BufferSource* buffer) {
}
return vector;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-Vector<uint8_t> ConvertBufferSource(
- const ArrayBufferOrArrayBufferView& buffer) {
- DCHECK(!buffer.IsNull());
- Vector<uint8_t> vector;
- if (buffer.IsArrayBuffer()) {
- vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
- base::checked_cast<wtf_size_t>(
- buffer.GetAsArrayBuffer()->ByteLength()));
- } else {
- vector.Append(
- static_cast<uint8_t*>(buffer.GetAsArrayBufferView()->BaseAddress()),
- base::checked_cast<wtf_size_t>(
- buffer.GetAsArrayBufferView()->byteLength()));
- }
- return vector;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool IsProtected(
const device::mojom::blink::HidUsageAndPage& hid_usage_and_page) {
@@ -164,7 +145,7 @@ int8_t UnitFactorExponentToInt(uint8_t unit_factor_exponent) {
DCHECK_LE(unit_factor_exponent, 0x0f);
// Values from 0x08 to 0x0f encode negative exponents.
if (unit_factor_exponent > 0x08)
- return int8_t{unit_factor_exponent} - 16;
+ return static_cast<int8_t>(unit_factor_exponent) - 16;
return unit_factor_exponent;
}
@@ -321,11 +302,7 @@ ScriptPromise HIDDevice::close(ScriptState* script_state) {
ScriptPromise HIDDevice::sendReport(ScriptState* script_state,
uint8_t report_id,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* data
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferView& data
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
ScriptPromiseResolver* resolver =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -339,15 +316,9 @@ ScriptPromise HIDDevice::sendReport(ScriptState* script_state,
return promise;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
size_t data_size = data->IsArrayBuffer()
? data->GetAsArrayBuffer()->ByteLength()
: data->GetAsArrayBufferView()->byteLength();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- size_t data_size = data.IsArrayBuffer()
- ? data.GetAsArrayBuffer()->ByteLength()
- : data.GetAsArrayBufferView()->byteLength();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!base::CheckedNumeric<wtf_size_t>(data_size).IsValid()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -364,12 +335,7 @@ ScriptPromise HIDDevice::sendReport(ScriptState* script_state,
ScriptPromise HIDDevice::sendFeatureReport(ScriptState* script_state,
uint8_t report_id,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8BufferSource* data
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferView&
- data
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
ScriptPromiseResolver* resolver =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -383,15 +349,9 @@ ScriptPromise HIDDevice::sendFeatureReport(ScriptState* script_state,
return promise;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
size_t data_size = data->IsArrayBuffer()
? data->GetAsArrayBuffer()->ByteLength()
: data->GetAsArrayBufferView()->byteLength();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- size_t data_size = data.IsArrayBuffer()
- ? data.GetAsArrayBuffer()->ByteLength()
- : data.GetAsArrayBufferView()->byteLength();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!base::CheckedNumeric<wtf_size_t>(data_size).IsValid()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_device.h b/chromium/third_party/blink/renderer/modules/hid/hid_device.h
index 6a4d6cf1e32..4f2d526fae1 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_device.h
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_device.h
@@ -9,7 +9,6 @@
#include "services/device/public/mojom/hid.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/hid/hid.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_hid_report_item.h"
@@ -63,21 +62,12 @@ class MODULES_EXPORT HIDDevice
ScriptPromise open(ScriptState*);
ScriptPromise close(ScriptState*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise sendReport(ScriptState*,
uint8_t report_id,
const V8BufferSource* data);
ScriptPromise sendFeatureReport(ScriptState*,
uint8_t report_id,
const V8BufferSource* data);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise sendReport(ScriptState*,
- uint8_t report_id,
- const ArrayBufferOrArrayBufferView& data);
- ScriptPromise sendFeatureReport(ScriptState*,
- uint8_t report_id,
- const ArrayBufferOrArrayBufferView& data);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise receiveFeatureReport(ScriptState*, uint8_t report_id);
// ExecutionContextLifecycleObserver:
diff --git a/chromium/third_party/blink/renderer/modules/hid/idls.gni b/chromium/third_party/blink/renderer/modules/hid/idls.gni
deleted file mode 100644
index 0ef4e76abcf..00000000000
--- a/chromium/third_party/blink/renderer/modules/hid/idls.gni
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "hid.idl",
- "hid_connection_event.idl",
- "hid_device.idl",
- "hid_input_report_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "hid_collection_info.idl",
- "hid_connection_event_init.idl",
- "hid_device_filter.idl",
- "hid_device_request_options.idl",
- "hid_report_info.idl",
- "hid_report_item.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_hid.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/idle/idls.gni b/chromium/third_party/blink/renderer/modules/idle/idls.gni
deleted file mode 100644
index 05f75736eb9..00000000000
--- a/chromium/third_party/blink/renderer/modules/idle/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "idle_detector.idl" ]
-
-modules_dictionary_idl_files = [ "idle_options.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/BUILD.gn b/chromium/third_party/blink/renderer/modules/imagecapture/BUILD.gn
index deb9de1f70b..d4d54672e0d 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/BUILD.gn
@@ -14,9 +14,12 @@ blink_modules_sources("imagecapture") {
deps = [
"//media",
- "//media/capture/mojom:image_capture_blink",
- "//skia",
"//third_party/blink/renderer/modules/permissions:permissions",
"//third_party/libyuv",
]
+
+ public_deps = [
+ "//media/capture/mojom:image_capture_blink",
+ "//skia",
+ ]
}
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/OWNERS b/chromium/third_party/blink/renderer/modules/imagecapture/OWNERS
index 52977106453..94a0ef8908d 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/OWNERS
@@ -1,5 +1,2 @@
reillyg@chromium.org
rijubrata.bhaumik@intel.com
-
-# Original (legacy) owner.
-mcasas@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/idls.gni b/chromium/third_party/blink/renderer/modules/imagecapture/idls.gni
deleted file mode 100644
index 88a06a76f37..00000000000
--- a/chromium/third_party/blink/renderer/modules/imagecapture/idls.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "image_capture.idl" ]
-
-modules_dictionary_idl_files = [
- "constrain_point_2d_parameters.idl",
- "media_settings_range.idl",
- "photo_capabilities.idl",
- "photo_settings.idl",
- "point_2d.idl",
-]
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 da85cd3ec4c..955950aeb11 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -20,6 +20,12 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_capabilities.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_photo_capabilities.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_point_2d.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_constrainbooleanparameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_constraindoublerange_double.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindomstringparameters_string_stringsequence.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindoublerange_double.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constrainpoint2dparameters_point2dsequence.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -91,7 +97,6 @@ WebString ToString(MeteringMode value) {
}
}
-#ifdef USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY
V8FillLightMode ToV8FillLightMode(FillLightMode value) {
switch (value) {
case FillLightMode::OFF:
@@ -102,18 +107,6 @@ V8FillLightMode ToV8FillLightMode(FillLightMode value) {
return V8FillLightMode(V8FillLightMode::Enum::kFlash);
}
}
-#else
-String ToV8FillLightMode(FillLightMode value) {
- switch (value) {
- case FillLightMode::OFF:
- return String::FromUTF8("off");
- case FillLightMode::AUTO:
- return String::FromUTF8("auto");
- case FillLightMode::FLASH:
- return String::FromUTF8("flash");
- }
-}
-#endif
WebString ToString(RedEyeReduction value) {
switch (value) {
@@ -501,11 +494,12 @@ void ImageCapture::SetMediaTrackConstraints(
// TODO(mcasas): support other Mode types beyond simple string i.e. the
// equivalents of "sequence<DOMString>"" or "ConstrainDOMStringParameters".
- settings->has_white_balance_mode = constraints->hasWhiteBalanceMode() &&
- constraints->whiteBalanceMode().IsString();
+ settings->has_white_balance_mode =
+ constraints->hasWhiteBalanceMode() &&
+ constraints->whiteBalanceMode()->IsString();
if (settings->has_white_balance_mode) {
const auto white_balance_mode =
- constraints->whiteBalanceMode().GetAsString();
+ constraints->whiteBalanceMode()->GetAsString();
if (capabilities_->whiteBalanceMode().Find(white_balance_mode) ==
kNotFound) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -517,9 +511,9 @@ void ImageCapture::SetMediaTrackConstraints(
settings->white_balance_mode = ParseMeteringMode(white_balance_mode);
}
settings->has_exposure_mode =
- constraints->hasExposureMode() && constraints->exposureMode().IsString();
+ constraints->hasExposureMode() && constraints->exposureMode()->IsString();
if (settings->has_exposure_mode) {
- const auto exposure_mode = constraints->exposureMode().GetAsString();
+ const auto exposure_mode = constraints->exposureMode()->GetAsString();
if (capabilities_->exposureMode().Find(exposure_mode) == kNotFound) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, "Unsupported exposureMode."));
@@ -530,9 +524,9 @@ void ImageCapture::SetMediaTrackConstraints(
}
settings->has_focus_mode =
- constraints->hasFocusMode() && constraints->focusMode().IsString();
+ constraints->hasFocusMode() && constraints->focusMode()->IsString();
if (settings->has_focus_mode) {
- const auto focus_mode = constraints->focusMode().GetAsString();
+ const auto focus_mode = constraints->focusMode()->GetAsString();
if (capabilities_->focusMode().Find(focus_mode) == kNotFound) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, "Unsupported focusMode."));
@@ -544,9 +538,11 @@ void ImageCapture::SetMediaTrackConstraints(
// TODO(mcasas): support ConstrainPoint2DParameters.
if (constraints->hasPointsOfInterest() &&
- constraints->pointsOfInterest().IsPoint2DSequence()) {
+ constraints->pointsOfInterest()->IsPoint2DSequence()
+ ) {
for (const auto& point :
- constraints->pointsOfInterest().GetAsPoint2DSequence()) {
+ constraints->pointsOfInterest()->GetAsPoint2DSequence()
+ ) {
auto mojo_point = media::mojom::blink::Point2D::New();
mojo_point->x = point->x();
mojo_point->y = point->y();
@@ -558,10 +554,10 @@ void ImageCapture::SetMediaTrackConstraints(
// TODO(mcasas): support ConstrainDoubleRange where applicable.
settings->has_exposure_compensation =
constraints->hasExposureCompensation() &&
- constraints->exposureCompensation().IsDouble();
+ constraints->exposureCompensation()->IsDouble();
if (settings->has_exposure_compensation) {
const auto exposure_compensation =
- constraints->exposureCompensation().GetAsDouble();
+ constraints->exposureCompensation()->GetAsDouble();
if (exposure_compensation < capabilities_->exposureCompensation()->min() ||
exposure_compensation > capabilities_->exposureCompensation()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -575,9 +571,9 @@ void ImageCapture::SetMediaTrackConstraints(
}
settings->has_exposure_time =
- constraints->hasExposureTime() && constraints->exposureTime().IsDouble();
+ constraints->hasExposureTime() && constraints->exposureTime()->IsDouble();
if (settings->has_exposure_time) {
- const auto exposure_time = constraints->exposureTime().GetAsDouble();
+ const auto exposure_time = constraints->exposureTime()->GetAsDouble();
if (exposure_time < capabilities_->exposureTime()->min() ||
exposure_time > capabilities_->exposureTime()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -589,10 +585,10 @@ void ImageCapture::SetMediaTrackConstraints(
settings->exposure_time = exposure_time;
}
settings->has_color_temperature = constraints->hasColorTemperature() &&
- constraints->colorTemperature().IsDouble();
+ constraints->colorTemperature()->IsDouble();
if (settings->has_color_temperature) {
const auto color_temperature =
- constraints->colorTemperature().GetAsDouble();
+ constraints->colorTemperature()->GetAsDouble();
if (color_temperature < capabilities_->colorTemperature()->min() ||
color_temperature > capabilities_->colorTemperature()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -603,9 +599,9 @@ void ImageCapture::SetMediaTrackConstraints(
temp_constraints->setColorTemperature(constraints->colorTemperature());
settings->color_temperature = color_temperature;
}
- settings->has_iso = constraints->hasIso() && constraints->iso().IsDouble();
+ settings->has_iso = constraints->hasIso() && constraints->iso()->IsDouble();
if (settings->has_iso) {
- const auto iso = constraints->iso().GetAsDouble();
+ const auto iso = constraints->iso()->GetAsDouble();
if (iso < capabilities_->iso()->min() ||
iso > capabilities_->iso()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -617,9 +613,9 @@ void ImageCapture::SetMediaTrackConstraints(
}
settings->has_brightness =
- constraints->hasBrightness() && constraints->brightness().IsDouble();
+ constraints->hasBrightness() && constraints->brightness()->IsDouble();
if (settings->has_brightness) {
- const auto brightness = constraints->brightness().GetAsDouble();
+ const auto brightness = constraints->brightness()->GetAsDouble();
if (brightness < capabilities_->brightness()->min() ||
brightness > capabilities_->brightness()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -631,9 +627,9 @@ void ImageCapture::SetMediaTrackConstraints(
settings->brightness = brightness;
}
settings->has_contrast =
- constraints->hasContrast() && constraints->contrast().IsDouble();
+ constraints->hasContrast() && constraints->contrast()->IsDouble();
if (settings->has_contrast) {
- const auto contrast = constraints->contrast().GetAsDouble();
+ const auto contrast = constraints->contrast()->GetAsDouble();
if (contrast < capabilities_->contrast()->min() ||
contrast > capabilities_->contrast()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -645,9 +641,9 @@ void ImageCapture::SetMediaTrackConstraints(
settings->contrast = contrast;
}
settings->has_saturation =
- constraints->hasSaturation() && constraints->saturation().IsDouble();
+ constraints->hasSaturation() && constraints->saturation()->IsDouble();
if (settings->has_saturation) {
- const auto saturation = constraints->saturation().GetAsDouble();
+ const auto saturation = constraints->saturation()->GetAsDouble();
if (saturation < capabilities_->saturation()->min() ||
saturation > capabilities_->saturation()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -659,9 +655,9 @@ void ImageCapture::SetMediaTrackConstraints(
settings->saturation = saturation;
}
settings->has_sharpness =
- constraints->hasSharpness() && constraints->sharpness().IsDouble();
+ constraints->hasSharpness() && constraints->sharpness()->IsDouble();
if (settings->has_sharpness) {
- const auto sharpness = constraints->sharpness().GetAsDouble();
+ const auto sharpness = constraints->sharpness()->GetAsDouble();
if (sharpness < capabilities_->sharpness()->min() ||
sharpness > capabilities_->sharpness()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -674,9 +670,9 @@ void ImageCapture::SetMediaTrackConstraints(
}
settings->has_focus_distance = constraints->hasFocusDistance() &&
- constraints->focusDistance().IsDouble();
+ constraints->focusDistance()->IsDouble();
if (settings->has_focus_distance) {
- const auto focus_distance = constraints->focusDistance().GetAsDouble();
+ const auto focus_distance = constraints->focusDistance()->GetAsDouble();
if (focus_distance < capabilities_->focusDistance()->min() ||
focus_distance > capabilities_->focusDistance()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -688,14 +684,14 @@ void ImageCapture::SetMediaTrackConstraints(
settings->focus_distance = focus_distance;
}
- settings->has_pan = constraints->hasPan() && constraints->pan().IsDouble();
+ settings->has_pan = constraints->hasPan() && constraints->pan()->IsDouble();
if (settings->has_pan) {
if (!IsPageVisible()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError, "the page is not visible"));
return;
}
- const auto pan = constraints->pan().GetAsDouble();
+ const auto pan = constraints->pan()->GetAsDouble();
if (pan < capabilities_->pan()->min() ||
pan > capabilities_->pan()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -706,14 +702,15 @@ void ImageCapture::SetMediaTrackConstraints(
settings->pan = pan;
}
- settings->has_tilt = constraints->hasTilt() && constraints->tilt().IsDouble();
+ settings->has_tilt =
+ constraints->hasTilt() && constraints->tilt()->IsDouble();
if (settings->has_tilt) {
if (!IsPageVisible()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError, "the page is not visible"));
return;
}
- const auto tilt = constraints->tilt().GetAsDouble();
+ const auto tilt = constraints->tilt()->GetAsDouble();
if (tilt < capabilities_->tilt()->min() ||
tilt > capabilities_->tilt()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -724,14 +721,15 @@ void ImageCapture::SetMediaTrackConstraints(
settings->tilt = tilt;
}
- settings->has_zoom = constraints->hasZoom() && constraints->zoom().IsDouble();
+ settings->has_zoom =
+ constraints->hasZoom() && constraints->zoom()->IsDouble();
if (settings->has_zoom) {
if (!IsPageVisible()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError, "the page is not visible"));
return;
}
- const auto zoom = constraints->zoom().GetAsDouble();
+ const auto zoom = constraints->zoom()->GetAsDouble();
if (zoom < capabilities_->zoom()->min() ||
zoom > capabilities_->zoom()->max()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -744,9 +742,9 @@ void ImageCapture::SetMediaTrackConstraints(
// TODO(mcasas): support ConstrainBooleanParameters where applicable.
settings->has_torch =
- constraints->hasTorch() && constraints->torch().IsBoolean();
+ constraints->hasTorch() && constraints->torch()->IsBoolean();
if (settings->has_torch) {
- const auto torch = constraints->torch().GetAsBoolean();
+ const auto torch = constraints->torch()->GetAsBoolean();
if (torch && !capabilities_->torch()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, "torch not supported"));
@@ -992,11 +990,7 @@ void ImageCapture::OnMojoGetPhotoState(
ToMediaSettingsRange(*photo_state->width));
}
-#ifdef USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY
WTF::Vector<V8FillLightMode> fill_light_mode;
-#else
- WTF::Vector<WTF::String> fill_light_mode;
-#endif
for (const auto& mode : photo_state->fill_light_mode) {
fill_light_mode.push_back(ToV8FillLightMode(mode));
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/BUILD.gn b/chromium/third_party/blink/renderer/modules/indexeddb/BUILD.gn
index 765d73523ad..0db8a3b585c 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/BUILD.gn
@@ -61,15 +61,12 @@ blink_modules_sources("indexeddb") {
"web_idb_callbacks.h",
"web_idb_callbacks_impl.cc",
"web_idb_callbacks_impl.h",
+ "web_idb_cursor.cc",
"web_idb_cursor.h",
- "web_idb_cursor_impl.cc",
- "web_idb_cursor_impl.h",
+ "web_idb_database.cc",
"web_idb_database.h",
- "web_idb_database_impl.cc",
- "web_idb_database_impl.h",
+ "web_idb_transaction.cc",
"web_idb_transaction.h",
- "web_idb_transaction_impl.cc",
- "web_idb_transaction_impl.h",
]
public_deps = [ "//third_party/blink/public/mojom:mojom_modules_blink" ]
@@ -86,14 +83,14 @@ source_set("unit_tests") {
"idb_transaction_test.cc",
"idb_value_wrapping_test.cc",
"indexed_db_blink_mojom_traits_test.cc",
+ "mock_idb_database.cc",
+ "mock_idb_database.h",
+ "mock_idb_transaction.cc",
+ "mock_idb_transaction.h",
"mock_web_idb_callbacks.cc",
"mock_web_idb_callbacks.h",
- "mock_web_idb_database.cc",
- "mock_web_idb_database.h",
- "mock_web_idb_transaction.cc",
- "mock_web_idb_transaction.h",
- "web_idb_cursor_impl_unittest.cc",
- "web_idb_transaction_impl_unittest.cc",
+ "web_idb_cursor_unittest.cc",
+ "web_idb_transaction_unittest.cc",
]
configs += [
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 260ba9509fd..ec22ad6b32b 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
@@ -53,11 +53,7 @@ namespace blink {
IDBCursor::IDBCursor(std::unique_ptr<WebIDBCursor> backend,
mojom::IDBCursorDirection direction,
IDBRequest* request,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source* source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const Source& source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction* transaction)
: backend_(std::move(backend)),
request_(request),
@@ -66,11 +62,7 @@ IDBCursor::IDBCursor(std::unique_ptr<WebIDBCursor> backend,
transaction_(transaction) {
DCHECK(backend_);
DCHECK(request_);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(source_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DCHECK(!source_.IsNull());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(transaction_);
}
@@ -134,11 +126,7 @@ IDBRequest* IDBCursor::update(ScriptState* script_state,
IDBObjectStore* object_store = EffectiveObjectStore();
return object_store->DoPut(script_state, mojom::IDBPutMode::CursorUpdate,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MakeGarbageCollected<IDBRequest::Source>(this),
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBRequest::Source::FromIDBCursor(this),
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
value, IdbPrimaryKey(), exception_state);
}
@@ -171,7 +159,7 @@ void IDBCursor::advance(unsigned count, ExceptionState& exception_state) {
request_->SetPendingCursor(this);
request_->AssignNewMetrics(std::move(metrics));
got_value_ = false;
- backend_->Advance(count, request_->CreateWebCallbacks().release());
+ backend_->Advance(count, request_->CreateWebCallbacks());
}
void IDBCursor::Continue(ScriptState* script_state,
@@ -233,11 +221,7 @@ void IDBCursor::continuePrimaryKey(ScriptState* script_state,
}
if (
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
!source_->IsIDBIndex()
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- !source_.IsIDBIndex()
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The cursor's source is not an index.");
@@ -334,7 +318,7 @@ void IDBCursor::Continue(std::unique_ptr<IDBKey> key,
request_->AssignNewMetrics(std::move(metrics));
got_value_ = false;
backend_->CursorContinue(key.get(), primary_key.get(),
- request_->CreateWebCallbacks().release());
+ request_->CreateWebCallbacks());
}
IDBRequest* IDBCursor::Delete(ScriptState* script_state,
@@ -439,15 +423,9 @@ ScriptValue IDBCursor::value(ScriptState* script_state) {
return script_value;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const IDBCursor::Source* IDBCursor::source() const {
return source_;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void IDBCursor::source(Source& source) const {
- source = source_;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void IDBCursor::SetValueReady(std::unique_ptr<IDBKey> key,
std::unique_ptr<IDBKey> primary_key,
@@ -496,7 +474,6 @@ const IDBKey* IDBCursor::IdbPrimaryKey() const {
}
IDBObjectStore* IDBCursor::EffectiveObjectStore() const {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (source_->GetContentType()) {
case Source::ContentType::kIDBIndex:
return source_->GetAsIDBIndex()->objectStore();
@@ -505,15 +482,9 @@ IDBObjectStore* IDBCursor::EffectiveObjectStore() const {
}
NOTREACHED();
return nullptr;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (source_.IsIDBObjectStore())
- return source_.GetAsIDBObjectStore();
- return source_.GetAsIDBIndex()->objectStore();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
bool IDBCursor::IsDeleted() const {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (source_->GetContentType()) {
case Source::ContentType::kIDBIndex:
return source_->GetAsIDBIndex()->IsDeleted();
@@ -522,11 +493,6 @@ bool IDBCursor::IsDeleted() const {
}
NOTREACHED();
return false;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (source_.IsIDBObjectStore())
- return source_.GetAsIDBObjectStore()->IsDeleted();
- return source_.GetAsIDBIndex()->IsDeleted();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
mojom::IDBCursorDirection IDBCursor::StringToDirection(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
index f6a8a5a473e..ef69700f7c5 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
@@ -32,7 +32,6 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
@@ -51,27 +50,15 @@ class IDBCursor : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
using Source = V8UnionIDBIndexOrIDBObjectStore;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- using Source = IDBObjectStoreOrIDBIndex;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static mojom::IDBCursorDirection StringToDirection(const String& mode_string);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBCursor(std::unique_ptr<WebIDBCursor> backend,
mojom::blink::IDBCursorDirection direction,
IDBRequest* request,
const Source* source,
IDBTransaction* transaction);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBCursor(std::unique_ptr<WebIDBCursor>,
- mojom::IDBCursorDirection,
- IDBRequest*,
- const Source&,
- IDBTransaction*);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
~IDBCursor() override;
void Trace(Visitor*) const override;
@@ -88,11 +75,7 @@ class IDBCursor : public ScriptWrappable {
ScriptValue primaryKey(ScriptState*);
ScriptValue value(ScriptState*);
IDBRequest* request() { return request_.Get(); }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source* source() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void source(Source&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBRequest* update(ScriptState*, const ScriptValue&, ExceptionState&);
void advance(unsigned, ExceptionState&);
@@ -127,11 +110,7 @@ class IDBCursor : public ScriptWrappable {
std::unique_ptr<WebIDBCursor> backend_;
Member<IDBRequest> request_;
const mojom::IDBCursorDirection direction_;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<const Source> source_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Source source_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<IDBTransaction> transaction_;
bool got_value_ = false;
bool key_dirty_ = true;
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc
index 1e8aab7deb2..c0f72be787e 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc
@@ -35,11 +35,7 @@ namespace blink {
IDBCursorWithValue::IDBCursorWithValue(std::unique_ptr<WebIDBCursor> backend,
mojom::IDBCursorDirection direction,
IDBRequest* request,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source* source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const Source& source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction* transaction)
: IDBCursor(std::move(backend), direction, request, source, transaction) {
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
index e41f92cc033..ce92735ab82 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_CURSOR_WITH_VALUE_H_
#include <memory>
+
#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
@@ -45,11 +46,7 @@ class IDBCursorWithValue final : public IDBCursor {
IDBCursorWithValue(std::unique_ptr<WebIDBCursor>,
mojom::IDBCursorDirection,
IDBRequest*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const Source&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction*);
~IDBCursorWithValue() override;
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 eb5fc821197..c0777365878 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -47,7 +47,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_version_change_event.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.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/heap/heap.h"
@@ -331,11 +331,7 @@ void IDBDatabase::deleteObjectStore(const String& name,
IDBTransaction* IDBDatabase::transaction(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionStringOrStringSequence* store_names,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrStringSequence& store_names,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& mode,
ExceptionState& exception_state) {
return transaction(script_state, store_names, mode, nullptr, exception_state);
@@ -343,18 +339,13 @@ IDBTransaction* IDBDatabase::transaction(
IDBTransaction* IDBDatabase::transaction(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionStringOrStringSequence* store_names,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrStringSequence& store_names,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& mode_string,
const IDBTransactionOptions* options,
ExceptionState& exception_state) {
IDB_TRACE("IDBDatabase::transaction");
HashSet<String> scope;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(store_names);
switch (store_names->GetContentType()) {
case V8UnionStringOrStringSequence::ContentType::kString:
@@ -365,16 +356,6 @@ IDBTransaction* IDBDatabase::transaction(
scope.insert(name);
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (store_names.IsString()) {
- scope.insert(store_names.GetAsString());
- } else if (store_names.IsStringSequence()) {
- for (const String& name : store_names.GetAsStringSequence())
- scope.insert(name);
- } else {
- NOTREACHED();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (version_change_transaction_) {
exception_state.ThrowDOMException(
@@ -424,7 +405,7 @@ IDBTransaction* IDBDatabase::transaction(
// TODO(cmp): Delete |transaction_id| once all users are removed.
int64_t transaction_id = NextTransactionId();
- auto transaction_backend = std::make_unique<WebIDBTransactionImpl>(
+ auto transaction_backend = std::make_unique<WebIDBTransaction>(
ExecutionContext::From(script_state)
->GetTaskRunner(TaskType::kDatabaseAccess),
transaction_id);
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 bbdf8fa2482..18291ea5645 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
@@ -32,7 +32,6 @@
#include "third_party/blink/public/mojom/feature_observer/feature_observer.mojom-blink.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_string_sequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_object_store_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_transaction_options.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
@@ -97,7 +96,6 @@ class MODULES_EXPORT IDBDatabase final
return createObjectStore(name, IDBKeyPath(options->keyPath()),
options->autoIncrement(), exception_state);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction* transaction(ScriptState* script_state,
const V8UnionStringOrStringSequence* store_names,
const String& mode,
@@ -107,17 +105,6 @@ class MODULES_EXPORT IDBDatabase final
const String& mode,
const IDBTransactionOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBTransaction* transaction(ScriptState*,
- const StringOrStringSequence& store_names,
- const String& mode,
- ExceptionState&);
- IDBTransaction* transaction(ScriptState*,
- const StringOrStringSequence& store_names,
- const String& mode,
- const IDBTransactionOptions* options,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void deleteObjectStore(const String& name, ExceptionState&);
void close();
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 1745aa381cf..30c03dd4f29 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -56,7 +56,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.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/heap/persistent.h"
@@ -94,7 +94,7 @@ class WebIDBGetDBNamesCallbacksImpl : public WebIDBCallbacks {
"databases() promise could be resolved"));
}
- void SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
+ void SetState(base::WeakPtr<WebIDBCursor> cursor,
int64_t transaction_id) override {}
void Error(mojom::blink::IDBException code, const String& message) override {
@@ -346,7 +346,7 @@ IDBOpenDBRequest* IDBFactory::OpenInternal(ScriptState* script_state,
auto& factory = GetFactory(ExecutionContext::From(script_state));
- auto transaction_backend = std::make_unique<WebIDBTransactionImpl>(
+ auto transaction_backend = std::make_unique<WebIDBTransaction>(
ExecutionContext::From(script_state)
->GetTaskRunner(TaskType::kDatabaseAccess),
transaction_id);
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 7ea637a656d..59ac7c7bbae 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc
@@ -30,7 +30,6 @@
#include <utility>
#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/execution_context/execution_context.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.cc
index 20664f17ab7..a0faca9baa1 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.cc
@@ -115,7 +115,6 @@ IDBKeyPath::IDBKeyPath(const Vector<class String>& array)
#endif
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBKeyPath::IDBKeyPath(const V8UnionStringOrStringSequence* key_path) {
if (!key_path) {
type_ = mojom::IDBKeyPathType::Null;
@@ -138,25 +137,6 @@ IDBKeyPath::IDBKeyPath(const V8UnionStringOrStringSequence* key_path) {
break;
}
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-IDBKeyPath::IDBKeyPath(const StringOrStringSequence& key_path) {
- if (key_path.IsNull()) {
- type_ = mojom::IDBKeyPathType::Null;
- } else if (key_path.IsString()) {
- type_ = mojom::IDBKeyPathType::String;
- string_ = key_path.GetAsString();
- DCHECK(!string_.IsNull());
- } else {
- DCHECK(key_path.IsStringSequence());
- type_ = mojom::IDBKeyPathType::Array;
- array_ = key_path.GetAsStringSequence();
-#if DCHECK_IS_ON()
- for (const auto& element : array_)
- DCHECK(!element.IsNull());
-#endif
- }
-}
bool IDBKeyPath::IsValid() const {
switch (type_) {
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.h
index f003d977a90..e67bd887d91 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.h
@@ -27,7 +27,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_KEY_PATH_H_
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-shared.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_string_sequence.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -53,11 +52,7 @@ class MODULES_EXPORT IDBKeyPath {
IDBKeyPath() : type_(mojom::IDBKeyPathType::Null) {}
explicit IDBKeyPath(const String&);
explicit IDBKeyPath(const Vector<String>& array);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
explicit IDBKeyPath(const V8UnionStringOrStringSequence* key_path);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- // TODO(crbug.com/1181288): Remove the old IDL union version.
- explicit IDBKeyPath(const StringOrStringSequence& key_path);
mojom::IDBKeyPathType GetType() const { return type_; }
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 60dca5a2858..bd7211a211d 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
@@ -401,12 +401,8 @@ IDBRequest* IDBObjectStore::DoPutAll(ScriptState* script_state,
keys.push_back(std::move(key_ptr));
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const IDBRequest::Source* source =
MakeGarbageCollected<IDBRequest::Source>(this);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBRequest::Source source = IDBRequest::Source::FromIDBObjectStore(this);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBRequest::AsyncTraceState metrics("IDBObjectStore::putAll");
if (IsDeleted()) {
@@ -603,21 +599,13 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
return DoPut(script_state, put_mode,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MakeGarbageCollected<IDBRequest::Source>(this),
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBRequest::Source::FromIDBObjectStore(this),
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
value, key.get(), exception_state);
}
IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
mojom::IDBPutMode put_mode,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const IDBRequest::Source* source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const IDBRequest::Source& source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ScriptValue& value,
const IDBKey* key,
ExceptionState& exception_state) {
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 2424b6f9ddc..d9fb2dbef8f 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
@@ -121,11 +121,7 @@ class MODULES_EXPORT IDBObjectStore final : public ScriptWrappable {
IDBIndex* createIndex(ScriptState* script_state,
const String& name,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionStringOrStringSequence* key_path,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrStringSequence& key_path,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const IDBIndexParameters* options,
ExceptionState& exception_state) {
return createIndex(script_state, name, IDBKeyPath(key_path), options,
@@ -139,11 +135,7 @@ class MODULES_EXPORT IDBObjectStore final : public ScriptWrappable {
// Exposed for the use of IDBCursor::update().
IDBRequest* DoPut(ScriptState*,
mojom::IDBPutMode,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const IDBRequest::Source*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const IDBRequest::Source&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const ScriptValue&,
const IDBKey*,
ExceptionState&);
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 10daa7e41ec..5fd65b64b46 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
@@ -30,7 +30,6 @@
#include "base/metrics/histogram_macros.h"
#include "third_party/abseil-cpp/absl/types/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/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
@@ -50,11 +49,7 @@ IDBOpenDBRequest::IDBOpenDBRequest(
IDBRequest::AsyncTraceState metrics,
mojo::PendingRemote<mojom::blink::ObservedFeature> connection_lifetime)
: IDBRequest(script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
nullptr,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBRequest::Source(),
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
nullptr,
std::move(metrics)),
callbacks_receiver_(std::move(callbacks_receiver)),
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 1d5a248efc7..bfc070aa6bd 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -34,7 +34,6 @@
#include "third_party/blink/public/platform/web_blob_info.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/bindings/modules/v8/v8_union_idbcursor_idbindex_idbobjectstore.h"
@@ -100,50 +99,31 @@ IDBRequest* IDBRequest::Create(ScriptState* script_state,
IDBIndex* source,
IDBTransaction* transaction,
IDBRequest::AsyncTraceState metrics) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return Create(script_state,
source ? MakeGarbageCollected<Source>(source) : nullptr,
transaction, std::move(metrics));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return IDBRequest::Create(script_state, Source::FromIDBIndex(source),
- transaction, std::move(metrics));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
IDBRequest* IDBRequest::Create(ScriptState* script_state,
IDBObjectStore* source,
IDBTransaction* transaction,
IDBRequest::AsyncTraceState metrics) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return Create(script_state,
source ? MakeGarbageCollected<Source>(source) : nullptr,
transaction, std::move(metrics));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return IDBRequest::Create(script_state, Source::FromIDBObjectStore(source),
- transaction, std::move(metrics));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
IDBRequest* IDBRequest::Create(ScriptState* script_state,
IDBCursor* source,
IDBTransaction* transaction,
IDBRequest::AsyncTraceState metrics) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return Create(script_state,
source ? MakeGarbageCollected<Source>(source) : nullptr,
transaction, std::move(metrics));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return IDBRequest::Create(script_state, Source::FromIDBCursor(source),
- transaction, std::move(metrics));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
IDBRequest* IDBRequest::Create(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source* source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const Source& source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction* transaction,
IDBRequest::AsyncTraceState metrics) {
IDBRequest* request = MakeGarbageCollected<IDBRequest>(
@@ -156,11 +136,7 @@ IDBRequest* IDBRequest::Create(ScriptState* script_state,
}
IDBRequest::IDBRequest(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source* source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const Source& source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction* transaction,
AsyncTraceState metrics)
: ExecutionContextLifecycleObserver(ExecutionContext::From(script_state)),
@@ -223,21 +199,11 @@ DOMException* IDBRequest::error(ExceptionState& exception_state) const {
return error_;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const IDBRequest::Source* IDBRequest::source(ScriptState* script_state) const {
if (!GetExecutionContext())
return nullptr;
return source_;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void IDBRequest::source(ScriptState* script_state,
- IDBObjectStoreOrIDBIndexOrIDBCursor& source) const {
- if (!GetExecutionContext()) {
- source = Source();
- }
- source = source_;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& IDBRequest::readyState() const {
DCHECK(ready_state_ == PENDING || ready_state_ == DONE);
@@ -487,7 +453,6 @@ void IDBRequest::EnqueueResponse(std::unique_ptr<WebIDBCursor> backend,
DCHECK(!pending_cursor_);
IDBCursor* cursor = nullptr;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBCursor::Source* source = nullptr;
DCHECK(source_);
@@ -504,17 +469,6 @@ void IDBRequest::EnqueueResponse(std::unique_ptr<WebIDBCursor> backend,
break;
}
DCHECK(source);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBObjectStoreOrIDBIndex source;
-
- if (source_.IsIDBObjectStore()) {
- source =
- IDBCursor::Source::FromIDBObjectStore(source_.GetAsIDBObjectStore());
- } else if (source_.IsIDBIndex()) {
- source = IDBCursor::Source::FromIDBIndex(source_.GetAsIDBIndex());
- }
- DCHECK(!source.IsNull());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (cursor_type_) {
case indexed_db::kCursorKeyOnly:
@@ -568,7 +522,6 @@ void IDBRequest::EnqueueResponse(Vector<std::unique_ptr<IDBValue>> values) {
}
#if DCHECK_IS_ON()
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static IDBObjectStore* EffectiveObjectStore(const IDBRequest::Source* source) {
DCHECK(source);
switch (source->GetContentType()) {
@@ -583,17 +536,6 @@ static IDBObjectStore* EffectiveObjectStore(const IDBRequest::Source* source) {
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-static IDBObjectStore* EffectiveObjectStore(const IDBRequest::Source& source) {
- if (source.IsIDBObjectStore())
- return source.GetAsIDBObjectStore();
- if (source.IsIDBIndex())
- return source.GetAsIDBIndex()->objectStore();
-
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
#endif // DCHECK_IS_ON()
void IDBRequest::EnqueueResponse(std::unique_ptr<IDBValue> value) {
@@ -682,13 +624,8 @@ void IDBRequest::ContextDestroyed() {
transaction_->UnregisterRequest(this);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (source_ && source_->IsIDBCursor())
source_->GetAsIDBCursor()->ContextWillBeDestroyed();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (source_.IsIDBCursor())
- source_.GetAsIDBCursor()->ContextWillBeDestroyed();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (result_)
result_->ContextWillBeDestroyed();
if (pending_cursor_)
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 bed4528e9ab..2c2e4f02589 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
@@ -39,8 +39,6 @@
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index.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_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"
@@ -71,11 +69,8 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
DEFINE_WRAPPERTYPEINFO();
public:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
using Source = V8UnionIDBCursorOrIDBIndexOrIDBObjectStore;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- using Source = IDBObjectStoreOrIDBIndexOrIDBCursor;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+
// Container for async tracing state.
//
// The documentation for TRACE_EVENT_NESTABLE_ASYNC_{BEGIN,END} suggests
@@ -181,22 +176,14 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
IDBTransaction* source,
AsyncTraceState);
static IDBRequest* Create(ScriptState*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const Source&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction*,
AsyncTraceState);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBRequest(ScriptState* script_state,
const Source* source,
IDBTransaction* transaction,
AsyncTraceState metrics);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- IDBRequest(ScriptState*, const Source&, IDBTransaction*, AsyncTraceState);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
~IDBRequest() override;
void Trace(Visitor*) const override;
@@ -204,11 +191,7 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
v8::Isolate* GetIsolate() const { return isolate_; }
ScriptValue result(ScriptState*, ExceptionState&);
DOMException* error(ExceptionState&) const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const Source* source(ScriptState* script_state) const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void source(ScriptState*, Source&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransaction* transaction() const { return transaction_.Get(); }
bool isResultDirty() const { return result_dirty_; }
@@ -408,11 +391,7 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
void ClearPutOperationBlobs() { transit_blob_handles_.clear(); }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<const Source> source_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- Source source_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<IDBAny> result_;
Member<DOMException> error_;
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 cce79bf10b7..9533afb16d1 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
@@ -54,9 +54,11 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
#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/mock_web_idb_database.h"
-#include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h"
+#include "third_party/blink/renderer/modules/indexeddb/mock_idb_database.h"
+#include "third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
@@ -178,14 +180,22 @@ class IDBRequestTest : public testing::Test {
url_loader_mock_factory_->UnregisterAllURLsAndClearMemoryCache();
}
- void BuildTransaction(
- V8TestingScope& scope,
- std::unique_ptr<MockWebIDBDatabase> database_backend,
- std::unique_ptr<MockWebIDBTransaction> transaction_backend) {
+ void BuildTransaction(V8TestingScope& scope,
+ MockIDBDatabase& mock_database,
+ MockIDBTransaction& mock_transaction) {
+ auto database_backend = std::make_unique<WebIDBDatabase>(
+ mock_database.BindNewEndpointAndPassDedicatedRemote(),
+ /*task_runner=*/nullptr);
db_ = MakeGarbageCollected<IDBDatabase>(
scope.GetExecutionContext(), std::move(database_backend),
mojo::NullAssociatedReceiver(), mojo::NullRemote());
+ auto transaction_backend = std::make_unique<WebIDBTransaction>(
+ /*task_runner=*/nullptr, kTransactionId);
+ auto transaction_receiver = transaction_backend->CreateReceiver();
+ transaction_receiver.EnableUnassociatedUsage();
+ mock_transaction.Bind(std::move(transaction_receiver));
+
HashSet<String> transaction_scope = {"store"};
transaction_ = IDBTransaction::CreateNonVersionChange(
scope.GetScriptState(), std::move(transaction_backend), kTransactionId,
@@ -208,6 +218,8 @@ class IDBRequestTest : public testing::Test {
static constexpr int64_t kStoreId = 5678;
};
+const int64_t IDBRequestTest::kTransactionId;
+
void EnsureIDBCallbacksDontThrow(IDBRequest* request,
ExceptionState& exception_state) {
ASSERT_TRUE(request->transaction());
@@ -230,15 +242,11 @@ void EnsureIDBCallbacksDontThrow(IDBRequest* request,
TEST_F(IDBRequestTest, EventsAfterEarlyDeathStop) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*transaction_backend, Commit(0)).Times(1);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ EXPECT_CALL(transaction_backend, Commit(0)).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
ASSERT_TRUE(!scope.GetExceptionState().HadException());
ASSERT_TRUE(transaction_);
@@ -253,19 +261,17 @@ TEST_F(IDBRequestTest, EventsAfterEarlyDeathStop) {
scope.GetExecutionContext()->NotifyContextDestroyed();
EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
+ transaction_->transaction_backend()->FlushForTesting();
+ database_backend.Flush();
}
TEST_F(IDBRequestTest, EventsAfterDoneStop) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*transaction_backend, Commit(0)).Times(1);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ EXPECT_CALL(transaction_backend, Commit(0)).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
ASSERT_TRUE(!scope.GetExceptionState().HadException());
ASSERT_TRUE(transaction_);
@@ -279,19 +285,17 @@ TEST_F(IDBRequestTest, EventsAfterDoneStop) {
scope.GetExecutionContext()->NotifyContextDestroyed();
EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
+ transaction_->transaction_backend()->FlushForTesting();
+ database_backend.Flush();
}
TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithQueuedResult) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*transaction_backend, Commit(0)).Times(1);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ EXPECT_CALL(transaction_backend, Commit(0)).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
ASSERT_TRUE(!scope.GetExceptionState().HadException());
ASSERT_TRUE(transaction_);
@@ -308,6 +312,8 @@ TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithQueuedResult) {
EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
url_loader_mock_factory_->ServeAsynchronousRequests();
EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
+ transaction_->transaction_backend()->FlushForTesting();
+ database_backend.Flush();
}
// This test is flaky on Marshmallow 64 bit Tester because the test is
@@ -322,15 +328,11 @@ TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithQueuedResult) {
TEST_F(IDBRequestTest, MAYBE_EventsAfterEarlyDeathStopWithTwoQueuedResults) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*transaction_backend, Commit(0)).Times(1);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ EXPECT_CALL(transaction_backend, Commit(0)).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
ASSERT_TRUE(!scope.GetExceptionState().HadException());
ASSERT_TRUE(transaction_);
@@ -355,6 +357,8 @@ TEST_F(IDBRequestTest, MAYBE_EventsAfterEarlyDeathStopWithTwoQueuedResults) {
url_loader_mock_factory_->ServeAsynchronousRequests();
EnsureIDBCallbacksDontThrow(request1, scope.GetExceptionState());
EnsureIDBCallbacksDontThrow(request2, scope.GetExceptionState());
+ transaction_->transaction_backend()->FlushForTesting();
+ database_backend.Flush();
}
// This test is flaky on Marshmallow 64 bit Tester because the test is
@@ -391,21 +395,21 @@ TEST_F(IDBRequestTest, MAYBE_AbortErrorAfterAbort) {
TEST_F(IDBRequestTest, ConnectionsAfterStopping) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
const int64_t kVersion = 1;
const int64_t kOldVersion = 0;
const IDBDatabaseMetadata metadata;
{
+ MockIDBDatabase mock_database;
mojo::AssociatedRemote<mojom::blink::IDBDatabase> remote;
- std::unique_ptr<BackendDatabaseWithMockedClose> mock_database =
- std::make_unique<BackendDatabaseWithMockedClose>(
- remote.BindNewEndpointAndPassDedicatedReceiver());
- EXPECT_CALL(*mock_database, Close()).Times(1);
-
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
+ mock_database.Bind(remote.BindNewEndpointAndPassDedicatedReceiver());
+ EXPECT_CALL(mock_database, Close()).Times(1);
+
+ auto transaction_backend = std::make_unique<WebIDBTransaction>(
+ /*task_runner=*/nullptr, kTransactionId);
+ auto transaction_receiver = transaction_backend->CreateReceiver();
+ transaction_receiver.EnableUnassociatedUsage();
+
auto* request = MakeGarbageCollected<IDBOpenDBRequest>(
scope.GetScriptState(), mojo::NullAssociatedReceiver(),
std::move(transaction_backend), kTransactionId, kVersion,
@@ -420,15 +424,16 @@ TEST_F(IDBRequestTest, ConnectionsAfterStopping) {
}
{
+ MockIDBDatabase mock_database;
mojo::AssociatedRemote<mojom::blink::IDBDatabase> remote;
- std::unique_ptr<BackendDatabaseWithMockedClose> mock_database =
- std::make_unique<BackendDatabaseWithMockedClose>(
- remote.BindNewEndpointAndPassDedicatedReceiver());
- EXPECT_CALL(*mock_database, Close()).Times(1);
-
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
+ mock_database.Bind(remote.BindNewEndpointAndPassDedicatedReceiver());
+ EXPECT_CALL(mock_database, Close()).Times(1);
+
+ auto transaction_backend = std::make_unique<WebIDBTransaction>(
+ /*task_runner=*/nullptr, kTransactionId);
+ auto transaction_receiver = transaction_backend->CreateReceiver();
+ transaction_receiver.EnableUnassociatedUsage();
+
auto* request = MakeGarbageCollected<IDBOpenDBRequest>(
scope.GetScriptState(), mojo::NullAssociatedReceiver(),
std::move(transaction_backend), kTransactionId, kVersion,
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 9b09859b09e..f85a5e3d287 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
@@ -51,8 +51,11 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_test_helper.h"
#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/mock_web_idb_database.h"
-#include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h"
+#include "third_party/blink/renderer/modules/indexeddb/mock_idb_database.h"
+#include "third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
@@ -80,14 +83,22 @@ class IDBTransactionTest : public testing::Test,
url_loader_mock_factory_->UnregisterAllURLsAndClearMemoryCache();
}
- void BuildTransaction(
- V8TestingScope& scope,
- std::unique_ptr<MockWebIDBDatabase> database_backend,
- std::unique_ptr<MockWebIDBTransaction> transaction_backend) {
+ void BuildTransaction(V8TestingScope& scope,
+ MockIDBDatabase& mock_database,
+ MockIDBTransaction& mock_transaction) {
+ auto database_backend = std::make_unique<WebIDBDatabase>(
+ mock_database.BindNewEndpointAndPassDedicatedRemote(),
+ /*task_runner=*/nullptr);
db_ = MakeGarbageCollected<IDBDatabase>(
scope.GetExecutionContext(), std::move(database_backend),
mojo::NullAssociatedReceiver(), mojo::NullRemote());
+ auto transaction_backend = std::make_unique<WebIDBTransaction>(
+ /*task_runner=*/nullptr, kTransactionId);
+ auto transaction_receiver = transaction_backend->CreateReceiver();
+ transaction_receiver.EnableUnassociatedUsage();
+ mock_transaction.Bind(std::move(transaction_receiver));
+
HashSet<String> transaction_scope = {"store"};
transaction_ = IDBTransaction::CreateNonVersionChange(
scope.GetScriptState(), std::move(transaction_backend), kTransactionId,
@@ -110,16 +121,14 @@ class IDBTransactionTest : public testing::Test,
static constexpr int64_t kStoreId = 5678;
};
+const int64_t IDBTransactionTest::kTransactionId;
+
TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
@@ -143,8 +152,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) {
scope.GetExecutionContext()->NotifyContextDestroyed();
transaction_->OnAbort(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError, "Aborted"));
+ transaction_->transaction_backend()->FlushForTesting();
transaction_.Clear();
store_.Clear();
+ database_backend.Flush();
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_EQ(0U, live_transactions->size());
@@ -152,14 +163,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) {
TEST_F(IDBTransactionTest, ContextDestroyedAfterDone) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
@@ -185,8 +192,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedAfterDone) {
scope.GetExecutionContext()->NotifyContextDestroyed();
transaction_->OnAbort(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError, "Aborted"));
+ transaction_->transaction_backend()->FlushForTesting();
transaction_.Clear();
store_.Clear();
+ database_backend.Flush();
// The request completed, so it has enqueued a success event. Discard the
// event, so that the transaction can go away.
@@ -198,14 +207,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedAfterDone) {
TEST_F(IDBTransactionTest, ContextDestroyedWithQueuedResult) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
@@ -230,8 +235,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedWithQueuedResult) {
scope.GetExecutionContext()->NotifyContextDestroyed();
transaction_->OnAbort(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError, "Aborted"));
+ transaction_->transaction_backend()->FlushForTesting();
transaction_.Clear();
store_.Clear();
+ database_backend.Flush();
url_loader_mock_factory_->ServeAsynchronousRequests();
@@ -241,14 +248,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedWithQueuedResult) {
TEST_F(IDBTransactionTest, ContextDestroyedWithTwoQueuedResults) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
@@ -278,8 +281,10 @@ TEST_F(IDBTransactionTest, ContextDestroyedWithTwoQueuedResults) {
scope.GetExecutionContext()->NotifyContextDestroyed();
transaction_->OnAbort(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError, "Aborted"));
+ transaction_->transaction_backend()->FlushForTesting();
transaction_.Clear();
store_.Clear();
+ database_backend.Flush();
url_loader_mock_factory_->ServeAsynchronousRequests();
@@ -290,64 +295,65 @@ TEST_F(IDBTransactionTest, ContextDestroyedWithTwoQueuedResults) {
TEST_F(IDBTransactionTest, DocumentShutdownWithQueuedAndBlockedResults) {
// This test covers the conditions of https://crbug.com/733642
- V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
-
- Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
- MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
- live_transactions->insert(transaction_);
-
- ThreadState::Current()->CollectAllGarbageForTesting();
- EXPECT_EQ(1U, live_transactions->size());
-
- Persistent<IDBRequest> request1 =
- IDBRequest::Create(scope.GetScriptState(), store_.Get(),
- transaction_.Get(), IDBRequest::AsyncTraceState());
- Persistent<IDBRequest> request2 =
- IDBRequest::Create(scope.GetScriptState(), store_.Get(),
- transaction_.Get(), IDBRequest::AsyncTraceState());
- DeactivateNewTransactions(scope.GetIsolate());
-
- request1->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true));
- request2->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), false));
-
- request1.Clear(); // The transaction is holding onto the requests.
- request2.Clear();
- ThreadState::Current()->CollectAllGarbageForTesting();
- EXPECT_EQ(1U, live_transactions->size());
-
- // 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(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kAbortError, "Aborted"));
- transaction_.Clear();
- store_.Clear();
-
- url_loader_mock_factory_->ServeAsynchronousRequests();
-
- ThreadState::Current()->CollectAllGarbageForTesting();
- EXPECT_EQ(0U, live_transactions->size());
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ {
+ // The database isn't actually closed until `scope` is destroyed, so create
+ // this object in a nested scope to allow mock expectations to be verified.
+ V8TestingScope scope;
+
+ BuildTransaction(scope, database_backend, transaction_backend);
+
+ Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
+ MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
+ live_transactions->insert(transaction_);
+
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_EQ(1U, live_transactions->size());
+
+ Persistent<IDBRequest> request1 =
+ IDBRequest::Create(scope.GetScriptState(), store_.Get(),
+ transaction_.Get(), IDBRequest::AsyncTraceState());
+ Persistent<IDBRequest> request2 =
+ IDBRequest::Create(scope.GetScriptState(), store_.Get(),
+ transaction_.Get(), IDBRequest::AsyncTraceState());
+ DeactivateNewTransactions(scope.GetIsolate());
+
+ request1->HandleResponse(
+ CreateIDBValueForTesting(scope.GetIsolate(), true));
+ request2->HandleResponse(
+ CreateIDBValueForTesting(scope.GetIsolate(), false));
+
+ request1.Clear(); // The transaction is holding onto the requests.
+ request2.Clear();
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_EQ(1U, live_transactions->size());
+
+ // 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(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kAbortError, "Aborted"));
+ transaction_->transaction_backend()->FlushForTesting();
+ transaction_.Clear();
+ store_.Clear();
+
+ url_loader_mock_factory_->ServeAsynchronousRequests();
+
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_EQ(0U, live_transactions->size());
+ }
+ database_backend.Flush();
}
TEST_F(IDBTransactionTest, TransactionFinish) {
V8TestingScope scope;
- const int64_t kTransactionId = 1234;
- auto database_backend = std::make_unique<MockWebIDBDatabase>();
- auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
- scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess),
- kTransactionId);
- EXPECT_CALL(*transaction_backend, Commit(0)).Times(1);
- EXPECT_CALL(*database_backend, Close()).Times(1);
- BuildTransaction(scope, std::move(database_backend),
- std::move(transaction_backend));
+ MockIDBDatabase database_backend;
+ MockIDBTransaction transaction_backend;
+ EXPECT_CALL(transaction_backend, Commit(0)).Times(1);
+ EXPECT_CALL(database_backend, Close()).Times(1);
+ BuildTransaction(scope, database_backend, transaction_backend);
Persistent<HeapHashSet<WeakMember<IDBTransaction>>> live_transactions =
MakeGarbageCollected<HeapHashSet<WeakMember<IDBTransaction>>>();
@@ -361,6 +367,7 @@ TEST_F(IDBTransactionTest, TransactionFinish) {
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_EQ(1U, live_transactions->size());
+ transaction_->transaction_backend()->FlushForTesting();
transaction_.Clear();
store_.Clear();
@@ -376,6 +383,8 @@ TEST_F(IDBTransactionTest, TransactionFinish) {
db_->Abort(kTransactionId, mojom::blink::IDBException::kAbortError,
"Aborted");
+ database_backend.Flush();
+
// OnAbort() should have cleared the transaction's reference to the database.
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_EQ(0U, live_transactions->size());
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_value.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_value.h
index b118a34515a..85d80b37636 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_value.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_value.h
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
+#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idls.gni b/chromium/third_party/blink/renderer/modules/indexeddb/idls.gni
deleted file mode 100644
index 543974793d5..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idls.gni
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "idb_cursor.idl",
- "idb_cursor_with_value.idl",
- "idb_database.idl",
- "idb_factory.idl",
- "idb_index.idl",
- "idb_key_range.idl",
- "idb_object_store.idl",
- "idb_open_db_request.idl",
- "idb_request.idl",
- "idb_transaction.idl",
- "idb_version_change_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "idb_database_info.idl",
- "idb_index_parameters.idl",
- "idb_object_store_parameters.idl",
- "idb_transaction_options.idl",
- "idb_version_change_event_init.idl",
-]
-
-modules_dependency_idl_files = [
- "window_indexed_database.idl",
- "worker_global_scope_indexed_database.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
index 914f88cf89a..7291b8de00e 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/stl_util.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc
index 3654f6d7534..49ac8379d67 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc
@@ -25,7 +25,7 @@ namespace blink {
TEST(IDBMojomTraitsTest, IDBKeyBinary) {
// Generate test data.
std::mt19937 rng(5);
- size_t test_data_size = 10000;
+ wtf_size_t test_data_size = 10000;
Vector<char> test_data(test_data_size);
std::generate(test_data.begin(), test_data.end(), rng);
scoped_refptr<SharedBuffer> input_data =
@@ -56,7 +56,7 @@ TEST(IDBMojomTraitsTest, IDBKeyBinary) {
TEST(IDBMojomTraitsTest, IDBValue) {
// Generate test data.
std::mt19937 rng(5);
- size_t test_data_size = 10000;
+ wtf_size_t test_data_size = 10000;
Vector<char> test_data(test_data_size);
std::generate(test_data.begin(), test_data.end(), rng);
scoped_refptr<SharedBuffer> input_data =
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc
index 194addf8106..c750bbb46c3 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
namespace blink {
// static
@@ -20,14 +20,14 @@ IndexedDBDispatcher* IndexedDBDispatcher::GetInstanceForCurrentThread() {
IndexedDBDispatcher::IndexedDBDispatcher() = default;
// static
-void IndexedDBDispatcher::RegisterCursor(WebIDBCursorImpl* cursor) {
+void IndexedDBDispatcher::RegisterCursor(WebIDBCursor* cursor) {
IndexedDBDispatcher* this_ptr = GetInstanceForCurrentThread();
DCHECK(!this_ptr->cursors_.Contains(cursor));
this_ptr->cursors_.insert(cursor);
}
// static
-void IndexedDBDispatcher::UnregisterCursor(WebIDBCursorImpl* cursor) {
+void IndexedDBDispatcher::UnregisterCursor(WebIDBCursor* cursor) {
IndexedDBDispatcher* this_ptr = GetInstanceForCurrentThread();
DCHECK(this_ptr->cursors_.Contains(cursor));
this_ptr->cursors_.erase(cursor);
@@ -36,9 +36,9 @@ void IndexedDBDispatcher::UnregisterCursor(WebIDBCursorImpl* cursor) {
// static
void IndexedDBDispatcher::ResetCursorPrefetchCaches(
int64_t transaction_id,
- WebIDBCursorImpl* except_cursor) {
+ WebIDBCursor* except_cursor) {
IndexedDBDispatcher* this_ptr = GetInstanceForCurrentThread();
- for (WebIDBCursorImpl* cursor : this_ptr->cursors_) {
+ for (WebIDBCursor* cursor : this_ptr->cursors_) {
if (cursor != except_cursor && cursor->transaction_id() == transaction_id)
cursor->ResetPrefetchCache();
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h
index a3aa852ca70..7dd6ded0981 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h
@@ -17,7 +17,7 @@
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
namespace blink {
-class WebIDBCursorImpl;
+class WebIDBCursor;
// Handle the indexed db related communication for this context thread - the
// main thread and each worker thread have their own copies.
@@ -25,18 +25,18 @@ class MODULES_EXPORT IndexedDBDispatcher {
DISALLOW_NEW();
public:
- static void RegisterCursor(WebIDBCursorImpl* cursor);
- static void UnregisterCursor(WebIDBCursorImpl* cursor);
+ static void RegisterCursor(WebIDBCursor* cursor);
+ static void UnregisterCursor(WebIDBCursor* cursor);
// Reset cursor prefetch caches for all cursors except |except_cursor|.
// In most callers, |except_cursor| is passed as nullptr, causing all cursors
- // to have their prefetch cache to be reset. In 2 WebIDBCursorImpl callers,
+ // to have their prefetch cache to be reset. In 2 WebIDBCursor callers,
// specifically from |Advance| and |CursorContinue|, these want to reset all
// cursor prefetch caches except the cursor the calls are running from. They
// get that behavior by passing |this| to |ResetCursorPrefetchCaches| which
// skips calling |ResetPrefetchCache| on them.
static void ResetCursorPrefetchCaches(int64_t transaction_id,
- WebIDBCursorImpl* except_cursor);
+ WebIDBCursor* except_cursor);
private:
friend class WTF::ThreadSpecific<IndexedDBDispatcher>;
@@ -45,10 +45,7 @@ class MODULES_EXPORT IndexedDBDispatcher {
IndexedDBDispatcher();
- FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
-
- WTF::HashSet<WebIDBCursorImpl*> cursors_;
+ WTF::HashSet<WebIDBCursor*> cursors_;
};
} // namespace blink
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 4a2e9c49dc8..a79a3e30417 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
@@ -332,13 +332,8 @@ IDBTransaction* TransactionForDatabase(
const String& object_store_name,
const String& mode = indexed_db_names::kReadonly) {
DummyExceptionStateForTesting exception_state;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionStringOrStringSequence* scope =
MakeGarbageCollected<V8UnionStringOrStringSequence>(object_store_name);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrStringSequence scope;
- scope.SetString(object_store_name);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
IDBTransactionOptions options;
options.setDurability("relaxed");
IDBTransaction* idb_transaction = idb_database->transaction(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.cc b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.cc
new file mode 100644
index 00000000000..64a855025b8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.cc
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/indexeddb/mock_idb_database.h"
+
+namespace blink {
+
+void MockIDBDatabase::Bind(
+ mojo::PendingAssociatedReceiver<mojom::blink::IDBDatabase> receiver) {
+ receiver_.Bind(std::move(receiver));
+}
+
+mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase>
+MockIDBDatabase::BindNewEndpointAndPassDedicatedRemote() {
+ return receiver_.BindNewEndpointAndPassDedicatedRemote();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.h b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.h
new file mode 100644
index 00000000000..86a35fedaf8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_database.h
@@ -0,0 +1,143 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_IDB_DATABASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_IDB_DATABASE_H_
+
+#include <gmock/gmock.h>
+#include <memory>
+
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+
+namespace blink {
+
+class MockIDBDatabase : public testing::StrictMock<mojom::blink::IDBDatabase> {
+ public:
+ MOCK_METHOD(void,
+ RenameObjectStore,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ const String& new_name),
+ (override));
+ MOCK_METHOD(
+ void,
+ CreateTransaction,
+ (mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction> receiver,
+ int64_t id,
+ const Vector<int64_t>& scope,
+ mojom::blink::IDBTransactionMode,
+ mojom::blink::IDBTransactionDurability),
+ (override));
+ MOCK_METHOD(void, Close, (), (override));
+ MOCK_METHOD(void, VersionChangeIgnored, (), (override));
+ MOCK_METHOD(void, Abort, (int64_t transaction_id), (override));
+ MOCK_METHOD(void,
+ CreateIndex,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const String& name,
+ const IDBKeyPath&,
+ bool unique,
+ bool multi_entry),
+ (override));
+ MOCK_METHOD(void,
+ DeleteIndex,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id),
+ (override));
+ MOCK_METHOD(void,
+ RenameIndex,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const String& new_name),
+ (override));
+ MOCK_METHOD(void,
+ Get,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ mojom::blink::IDBKeyRangePtr,
+ bool key_only,
+ GetCallback),
+ (override));
+ MOCK_METHOD(void,
+ GetAll,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ mojom::blink::IDBKeyRangePtr,
+ bool key_only,
+ int64_t max_count,
+ GetAllCallback),
+ (override));
+ MOCK_METHOD(void,
+ SetIndexKeys,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ std::unique_ptr<IDBKey> primary_key,
+ Vector<IDBIndexKeys>),
+ (override));
+ MOCK_METHOD(void,
+ SetIndexesReady,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ const Vector<int64_t>& index_ids),
+ (override));
+ MOCK_METHOD(void,
+ OpenCursor,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ mojom::blink::IDBKeyRangePtr,
+ mojom::blink::IDBCursorDirection,
+ bool key_only,
+ mojom::blink::IDBTaskType,
+ OpenCursorCallback),
+ (override));
+ MOCK_METHOD(void,
+ Count,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ mojom::blink::IDBKeyRangePtr,
+ mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks>),
+ (override));
+ MOCK_METHOD(void,
+ DeleteRange,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ mojom::blink::IDBKeyRangePtr,
+ mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks>),
+ (override));
+ MOCK_METHOD(void,
+ GetKeyGeneratorCurrentNumber,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks>),
+ (override));
+ MOCK_METHOD(void,
+ Clear,
+ (int64_t transaction_id,
+ int64_t object_store_id,
+ mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks>),
+ (override));
+
+ void Bind(mojo::PendingAssociatedReceiver<mojom::blink::IDBDatabase>);
+ mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase>
+ BindNewEndpointAndPassDedicatedRemote();
+
+ void Flush() { receiver_.FlushForTesting(); }
+
+ private:
+ mojo::AssociatedReceiver<mojom::blink::IDBDatabase> receiver_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_IDB_DATABASE_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.cc b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.cc
new file mode 100644
index 00000000000..ab12df3acec
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h"
+
+namespace blink {
+
+void MockIDBTransaction::Bind(
+ mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction> receiver) {
+ receiver_.Bind(std::move(receiver));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h
new file mode 100644
index 00000000000..dc744f53e7d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/mock_idb_transaction.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_IDB_TRANSACTION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_IDB_TRANSACTION_H_
+
+#include <gmock/gmock.h>
+#include <memory>
+
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+
+namespace blink {
+
+class MockIDBTransaction
+ : public testing::StrictMock<mojom::blink::IDBTransaction> {
+ public:
+ MOCK_METHOD(void,
+ CreateObjectStore,
+ (int64_t object_store_id,
+ const String& name,
+ const IDBKeyPath&,
+ bool auto_increment),
+ (override));
+ MOCK_METHOD(void, DeleteObjectStore, (int64_t object_store_id), (override));
+ MOCK_METHOD(void,
+ Put,
+ (int64_t object_store_id,
+ std::unique_ptr<IDBValue> value,
+ std::unique_ptr<IDBKey> key,
+ mojom::blink::IDBPutMode,
+ Vector<IDBIndexKeys>,
+ PutCallback callback),
+ (override));
+ MOCK_METHOD(void,
+ PutAll,
+ (int64_t object_store_id,
+ Vector<mojom::blink::IDBPutParamsPtr> puts,
+ PutAllCallback callback),
+ (override));
+ MOCK_METHOD(void, Commit, (int64_t num_errors_handled), (override));
+
+ void Bind(mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>);
+
+ private:
+ mojo::AssociatedReceiver<mojom::blink::IDBTransaction> receiver_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_TRANSACTION_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc
index 5a55873f07f..587b2b80e94 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc
@@ -13,7 +13,7 @@ MockWebIDBCallbacks::MockWebIDBCallbacks() {}
MockWebIDBCallbacks::~MockWebIDBCallbacks() {}
-void MockWebIDBCallbacks::SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
+void MockWebIDBCallbacks::SetState(base::WeakPtr<WebIDBCursor> cursor,
int64_t transaction_id) {}
void MockWebIDBCallbacks::SuccessCursorContinue(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h
index 0bde99343e5..d638cd66d28 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h
@@ -29,7 +29,7 @@ class MockWebIDBCallbacks : public WebIDBCallbacks {
MockWebIDBCallbacks(const MockWebIDBCallbacks&) = delete;
MockWebIDBCallbacks& operator=(const MockWebIDBCallbacks&) = delete;
- void SetState(base::WeakPtr<WebIDBCursorImpl>, int64_t) override;
+ void SetState(base::WeakPtr<WebIDBCursor>, int64_t) override;
MOCK_METHOD2(Error, void(mojom::blink::IDBException, const String&));
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc
deleted file mode 100644
index bf95b302a1b..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc
+++ /dev/null
@@ -1,17 +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/indexeddb/mock_web_idb_database.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-
-namespace blink {
-
-MockWebIDBDatabase::MockWebIDBDatabase() = default;
-
-MockWebIDBDatabase::~MockWebIDBDatabase() = default;
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
deleted file mode 100644
index 59a6da0c16c..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
+++ /dev/null
@@ -1,115 +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_INDEXEDDB_MOCK_WEB_IDB_DATABASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_DATABASE_H_
-
-#include <gmock/gmock.h>
-#include <memory>
-#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
-
-namespace blink {
-
-class MockWebIDBDatabase : public testing::StrictMock<WebIDBDatabase> {
- public:
- MockWebIDBDatabase();
- ~MockWebIDBDatabase() override;
-
- MOCK_METHOD3(RenameObjectStore,
- void(int64_t transaction_id,
- int64_t object_store_id,
- const String& new_name));
- MOCK_METHOD5(CreateTransaction,
- void(mojo::PendingAssociatedReceiver<
- mojom::blink::IDBTransaction> receiver,
- int64_t id,
- const Vector<int64_t>& scope,
- mojom::IDBTransactionMode,
- mojom::IDBTransactionDurability));
- MOCK_METHOD0(Close, void());
- MOCK_METHOD0(VersionChangeIgnored, void());
- MOCK_METHOD1(Abort, void(int64_t transaction_id));
- MOCK_METHOD7(CreateIndex,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& name,
- const IDBKeyPath&,
- bool unique,
- bool multi_entry));
- MOCK_METHOD3(DeleteIndex,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id));
- MOCK_METHOD4(RenameIndex,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& new_name));
- MOCK_METHOD6(Get,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- bool key_only,
- WebIDBCallbacks*));
- MOCK_METHOD7(GetAll,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- int64_t max_count,
- bool key_only,
- WebIDBCallbacks*));
-
- MOCK_METHOD4(SetIndexKeys,
- void(int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IDBKey> primary_key,
- Vector<IDBIndexKeys>));
- MOCK_METHOD3(SetIndexesReady,
- void(int64_t transaction_id,
- int64_t object_store_id,
- const Vector<int64_t>& index_ids));
- MOCK_METHOD8(OpenCursor,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- mojom::IDBCursorDirection,
- bool key_only,
- mojom::IDBTaskType,
- WebIDBCallbacks*));
- MOCK_METHOD5(Count,
- void(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- WebIDBCallbacks*));
- MOCK_METHOD4(Delete,
- void(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKey* primary_key,
- WebIDBCallbacks*));
- MOCK_METHOD4(DeleteRange,
- void(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKeyRange*,
- WebIDBCallbacks*));
- MOCK_METHOD3(GetKeyGeneratorCurrentNumber,
- void(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks*));
- MOCK_METHOD3(Clear,
- void(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks*));
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_DATABASE_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.cc b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.cc
deleted file mode 100644
index ac5695900ce..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.cc
+++ /dev/null
@@ -1,28 +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/indexeddb/mock_web_idb_transaction.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-
-namespace blink {
-
-MockWebIDBTransaction::MockWebIDBTransaction(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- int64_t transaction_id) {}
-
-MockWebIDBTransaction::MockWebIDBTransaction() = default;
-
-MockWebIDBTransaction::~MockWebIDBTransaction() = default;
-
-mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
-MockWebIDBTransaction::CreateReceiver() {
- return mojo::NullAssociatedReceiver();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h b/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h
deleted file mode 100644
index 0227f879cb3..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_TRANSACTION_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_TRANSACTION_H_
-
-#include <gmock/gmock.h>
-#include <memory>
-
-#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h"
-
-namespace blink {
-
-class MockWebIDBTransaction : public testing::StrictMock<WebIDBTransaction> {
- public:
- MockWebIDBTransaction(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- int64_t transaction_id);
- MockWebIDBTransaction();
- ~MockWebIDBTransaction() override;
-
- MOCK_METHOD4(CreateObjectStore,
- void(int64_t object_store_id,
- const String& name,
- const IDBKeyPath&,
- bool auto_increment));
- MOCK_METHOD1(DeleteObjectStore, void(int64_t object_store_id));
- MOCK_METHOD6(Put,
- void(int64_t object_store_id,
- std::unique_ptr<IDBValue> value,
- std::unique_ptr<IDBKey> primary_key,
- mojom::IDBPutMode,
- std::unique_ptr<WebIDBCallbacks>,
- Vector<IDBIndexKeys>));
- MOCK_METHOD3(PutAll,
- void(int64_t object_store_id,
- Vector<mojom::blink::IDBPutParamsPtr> puts,
- std::unique_ptr<WebIDBCallbacks> callbacks));
- MOCK_METHOD1(Commit, void(int64_t num_errors_handled));
-
- mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction> CreateReceiver()
- override;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_TRANSACTION_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h
index 7a5e337d458..6d686394f19 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h
@@ -30,12 +30,13 @@
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
-class WebIDBCursorImpl;
+class WebIDBCursor;
class WebIDBCallbacks : public mojom::blink::IDBCallbacks {
public:
@@ -44,7 +45,7 @@ class WebIDBCallbacks : public mojom::blink::IDBCallbacks {
Vector<std::unique_ptr<IDBKey>> primary_keys,
Vector<std::unique_ptr<IDBValue>> values) = 0;
virtual void DetachRequestFromCallback() = 0;
- virtual void SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
+ virtual void SetState(base::WeakPtr<WebIDBCursor> cursor,
int64_t transaction_id) = 0;
virtual void SuccessCursor(
mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> cursor_info,
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 baa5240facc..5059b620027 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
@@ -43,9 +43,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -83,7 +81,7 @@ void WebIDBCallbacksImpl::DetachRequestFromCallback() {
request_.Clear();
}
-void WebIDBCallbacksImpl::SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
+void WebIDBCallbacksImpl::SetState(base::WeakPtr<WebIDBCursor> cursor,
int64_t transaction_id) {
cursor_ = cursor;
transaction_id_ = transaction_id;
@@ -125,7 +123,7 @@ void WebIDBCallbacksImpl::SuccessCursor(
if (!request_)
return;
- std::unique_ptr<WebIDBCursorImpl> cursor = std::make_unique<WebIDBCursorImpl>(
+ std::unique_ptr<WebIDBCursor> cursor = std::make_unique<WebIDBCursor>(
std::move(cursor_info), transaction_id_, task_runner_);
std::unique_ptr<IDBValue> value;
if (optional_value.has_value()) {
@@ -162,8 +160,8 @@ void WebIDBCallbacksImpl::SuccessDatabase(
const IDBDatabaseMetadata& metadata) {
std::unique_ptr<WebIDBDatabase> db;
if (pending_database.is_valid()) {
- db = std::make_unique<WebIDBDatabaseImpl>(std::move(pending_database),
- task_runner_);
+ db = std::make_unique<WebIDBDatabase>(std::move(pending_database),
+ task_runner_);
}
if (request_) {
probe::AsyncTask async_task(request_->GetExecutionContext(),
@@ -306,8 +304,8 @@ void WebIDBCallbacksImpl::UpgradeNeeded(
const IDBDatabaseMetadata& metadata) {
std::unique_ptr<WebIDBDatabase> db;
if (pending_database.is_valid()) {
- db = std::make_unique<WebIDBDatabaseImpl>(std::move(pending_database),
- task_runner_);
+ db = std::make_unique<WebIDBDatabase>(std::move(pending_database),
+ task_runner_);
}
if (request_) {
probe::AsyncTask async_task(request_->GetExecutionContext(),
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
index 563c04c6f56..b7c651b3100 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
@@ -44,7 +44,7 @@ namespace blink {
class IDBKey;
class IDBRequest;
class IDBValue;
-class WebIDBCursorImpl;
+class WebIDBCursor;
struct IDBDatabaseMetadata;
class WebIDBCallbacksImpl final : public WebIDBCallbacks {
@@ -59,7 +59,7 @@ class WebIDBCallbacksImpl final : public WebIDBCallbacks {
explicit WebIDBCallbacksImpl(IDBRequest*);
~WebIDBCallbacksImpl() override;
- void SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
+ void SetState(base::WeakPtr<WebIDBCursor> cursor,
int64_t transaction_id) override;
// Pointers transfer ownership.
@@ -105,7 +105,7 @@ class WebIDBCallbacksImpl final : public WebIDBCallbacks {
void DetachCallbackFromRequest();
Persistent<IDBRequest> request_;
- base::WeakPtr<WebIDBCursorImpl> cursor_;
+ base::WeakPtr<WebIDBCursor> cursor_;
int64_t transaction_id_;
probe::AsyncTaskId async_task_id_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.cc
index d186af62566..4c8bebcfd2d 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.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/modules/indexeddb/web_idb_cursor_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
#include <stddef.h>
#include <utility>
@@ -16,7 +16,7 @@
namespace blink {
-WebIDBCursorImpl::WebIDBCursorImpl(
+WebIDBCursor::WebIDBCursor(
mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> cursor_info,
int64_t transaction_id,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
@@ -30,7 +30,7 @@ WebIDBCursorImpl::WebIDBCursorImpl(
IndexedDBDispatcher::RegisterCursor(this);
}
-WebIDBCursorImpl::~WebIDBCursorImpl() {
+WebIDBCursor::~WebIDBCursor() {
// It's not possible for there to be pending callbacks that address this
// object since inside WebKit, they hold a reference to the object which owns
// this object. But, if that ever changed, then we'd need to invalidate
@@ -38,8 +38,8 @@ WebIDBCursorImpl::~WebIDBCursorImpl() {
IndexedDBDispatcher::UnregisterCursor(this);
}
-void WebIDBCursorImpl::Advance(uint32_t count, WebIDBCallbacks* callbacks_ptr) {
- std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+void WebIDBCursor::Advance(uint32_t count,
+ std::unique_ptr<WebIDBCallbacks> callbacks) {
if (count <= prefetch_keys_.size()) {
CachedAdvance(count, callbacks.get());
return;
@@ -50,14 +50,13 @@ void WebIDBCursorImpl::Advance(uint32_t count, WebIDBCallbacks* callbacks_ptr) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, this);
callbacks->SetState(weak_factory_.GetWeakPtr(), transaction_id_);
- cursor_->Advance(count,
- WTF::Bind(&WebIDBCursorImpl::AdvanceCallback,
- WTF::Unretained(this), std::move(callbacks)));
+ cursor_->Advance(
+ count, WTF::Bind(&WebIDBCursor::AdvanceCallback, WTF::Unretained(this),
+ std::move(callbacks)));
}
-void WebIDBCursorImpl::AdvanceCallback(
- std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBCursorResultPtr result) {
+void WebIDBCursor::AdvanceCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBCursorResultPtr result) {
if (result->is_error_result()) {
callbacks->Error(result->get_error_result()->error_code,
std::move(result->get_error_result()->error_message));
@@ -70,7 +69,7 @@ void WebIDBCursorImpl::AdvanceCallback(
callbacks.reset();
return;
} else if (result->is_empty()) {
- callbacks->Error(blink::mojom::IDBException::kUnknownError,
+ callbacks->Error(mojom::blink::IDBException::kUnknownError,
"Invalid response");
callbacks.reset();
return;
@@ -79,7 +78,7 @@ void WebIDBCursorImpl::AdvanceCallback(
if (result->get_values()->keys.size() != 1u ||
result->get_values()->primary_keys.size() != 1u ||
result->get_values()->values.size() != 1u) {
- callbacks->Error(blink::mojom::IDBException::kUnknownError,
+ callbacks->Error(mojom::blink::IDBException::kUnknownError,
"Invalid response");
callbacks.reset();
return;
@@ -92,14 +91,13 @@ void WebIDBCursorImpl::AdvanceCallback(
callbacks.reset();
}
-void WebIDBCursorImpl::CursorContinue(const IDBKey* key,
- const IDBKey* primary_key,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBCursor::CursorContinue(const IDBKey* key,
+ const IDBKey* primary_key,
+ std::unique_ptr<WebIDBCallbacks> callbacks) {
DCHECK(key && primary_key);
- std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
- if (key->GetType() == mojom::IDBKeyType::None &&
- primary_key->GetType() == mojom::IDBKeyType::None) {
+ if (key->GetType() == mojom::blink::IDBKeyType::None &&
+ primary_key->GetType() == mojom::blink::IDBKeyType::None) {
// No key(s), so this would qualify for a prefetch.
++continue_count_;
@@ -115,7 +113,7 @@ void WebIDBCursorImpl::CursorContinue(const IDBKey* key,
callbacks->SetState(weak_factory_.GetWeakPtr(), transaction_id_);
cursor_->Prefetch(prefetch_amount_,
- WTF::Bind(&WebIDBCursorImpl::PrefetchCallback,
+ WTF::Bind(&WebIDBCursor::PrefetchCallback,
WTF::Unretained(this), std::move(callbacks)));
// Increase prefetch_amount_ exponentially.
@@ -135,11 +133,11 @@ void WebIDBCursorImpl::CursorContinue(const IDBKey* key,
callbacks->SetState(weak_factory_.GetWeakPtr(), transaction_id_);
cursor_->CursorContinue(
IDBKey::Clone(key), IDBKey::Clone(primary_key),
- WTF::Bind(&WebIDBCursorImpl::CursorContinueCallback,
- WTF::Unretained(this), std::move(callbacks)));
+ WTF::Bind(&WebIDBCursor::CursorContinueCallback, WTF::Unretained(this),
+ std::move(callbacks)));
}
-void WebIDBCursorImpl::CursorContinueCallback(
+void WebIDBCursor::CursorContinueCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
mojom::blink::IDBCursorResultPtr result) {
if (result->is_error_result()) {
@@ -154,7 +152,7 @@ void WebIDBCursorImpl::CursorContinueCallback(
callbacks.reset();
return;
} else if (result->is_empty()) {
- callbacks->Error(blink::mojom::IDBException::kUnknownError,
+ callbacks->Error(mojom::blink::IDBException::kUnknownError,
"Invalid response");
callbacks.reset();
return;
@@ -163,7 +161,7 @@ void WebIDBCursorImpl::CursorContinueCallback(
if (result->get_values()->keys.size() != 1u ||
result->get_values()->primary_keys.size() != 1u ||
result->get_values()->values.size() != 1u) {
- callbacks->Error(blink::mojom::IDBException::kUnknownError,
+ callbacks->Error(mojom::blink::IDBException::kUnknownError,
"Invalid response");
callbacks.reset();
return;
@@ -176,9 +174,8 @@ void WebIDBCursorImpl::CursorContinueCallback(
callbacks.reset();
}
-void WebIDBCursorImpl::PrefetchCallback(
- std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBCursorResultPtr result) {
+void WebIDBCursor::PrefetchCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBCursorResultPtr result) {
if (result->is_error_result()) {
callbacks->Error(result->get_error_result()->error_code,
std::move(result->get_error_result()->error_message));
@@ -191,7 +188,7 @@ void WebIDBCursorImpl::PrefetchCallback(
callbacks.reset();
return;
} else if (result->is_empty()) {
- callbacks->Error(blink::mojom::IDBException::kUnknownError,
+ callbacks->Error(mojom::blink::IDBException::kUnknownError,
"Invalid response");
callbacks.reset();
return;
@@ -201,7 +198,7 @@ void WebIDBCursorImpl::PrefetchCallback(
result->get_values()->primary_keys.size() ||
result->get_values()->keys.size() !=
result->get_values()->values.size()) {
- callbacks->Error(blink::mojom::IDBException::kUnknownError,
+ callbacks->Error(mojom::blink::IDBException::kUnknownError,
"Invalid response");
callbacks.reset();
return;
@@ -214,7 +211,7 @@ void WebIDBCursorImpl::PrefetchCallback(
callbacks.reset();
}
-void WebIDBCursorImpl::PostSuccessHandlerCallback() {
+void WebIDBCursor::PostSuccessHandlerCallback() {
pending_onsuccess_callbacks_--;
// If the onsuccess callback called continue()/advance() on the cursor
@@ -227,10 +224,9 @@ void WebIDBCursorImpl::PostSuccessHandlerCallback() {
ResetPrefetchCache();
}
-void WebIDBCursorImpl::SetPrefetchData(
- Vector<std::unique_ptr<IDBKey>> keys,
- Vector<std::unique_ptr<IDBKey>> primary_keys,
- Vector<std::unique_ptr<IDBValue>> values) {
+void WebIDBCursor::SetPrefetchData(Vector<std::unique_ptr<IDBKey>> keys,
+ Vector<std::unique_ptr<IDBKey>> primary_keys,
+ Vector<std::unique_ptr<IDBValue>> values) {
// Keys and values are stored in reverse order so that a cache'd continue can
// pop a value off of the back and prevent new memory allocations.
prefetch_keys_.AppendRange(std::make_move_iterator(keys.rbegin()),
@@ -245,8 +241,7 @@ void WebIDBCursorImpl::SetPrefetchData(
pending_onsuccess_callbacks_ = 0;
}
-void WebIDBCursorImpl::CachedAdvance(uint32_t count,
- WebIDBCallbacks* callbacks) {
+void WebIDBCursor::CachedAdvance(uint32_t count, WebIDBCallbacks* callbacks) {
DCHECK_GE(prefetch_keys_.size(), count);
DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
@@ -262,7 +257,7 @@ void WebIDBCursorImpl::CachedAdvance(uint32_t count,
CachedContinue(callbacks);
}
-void WebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
+void WebIDBCursor::CachedContinue(WebIDBCallbacks* callbacks) {
DCHECK_GT(prefetch_keys_.size(), 0ul);
DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
@@ -293,7 +288,7 @@ void WebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
std::move(value));
}
-void WebIDBCursorImpl::ResetPrefetchCache() {
+void WebIDBCursor::ResetPrefetchCache() {
continue_count_ = 0;
prefetch_amount_ = kMinPrefetchAmount;
@@ -314,7 +309,7 @@ void WebIDBCursorImpl::ResetPrefetchCache() {
}
mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks>
-WebIDBCursorImpl::GetCallbacksProxy(
+WebIDBCursor::GetCallbacksProxy(
std::unique_ptr<WebIDBCallbacks> callbacks_impl) {
mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks> pending_callbacks;
mojo::MakeSelfOwnedAssociatedReceiver(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h
index 786a51f18d5..eed6b61d259 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h
@@ -1,43 +1,38 @@
-/*
- * 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 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 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_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
-#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/gtest_prod_util.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+#include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
-class MODULES_EXPORT WebIDBCursor {
+class MODULES_EXPORT WebIDBCursor final {
public:
- virtual ~WebIDBCursor() = default;
+ WebIDBCursor(mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> cursor,
+ int64_t transaction_id,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~WebIDBCursor();
+
+ // Disallow copy and assign.
+ WebIDBCursor(const WebIDBCursor&) = delete;
+ WebIDBCursor& operator=(const WebIDBCursor&) = delete;
// Used to implement IDBCursor.advance().
- virtual void Advance(uint32_t count, WebIDBCallbacks*) = 0;
+ void Advance(uint32_t count, std::unique_ptr<WebIDBCallbacks> callback);
// Used to implement IDBCursor.continue() and IDBCursor.continuePrimaryKey().
//
@@ -47,18 +42,72 @@ class MODULES_EXPORT WebIDBCursor {
//
// The keys pointed to by IDBKey* are only guaranteed to be alive for
// the duration of the call.
- virtual void CursorContinue(const IDBKey*,
- const IDBKey* primary_key,
- WebIDBCallbacks*) = 0;
+ void CursorContinue(const IDBKey* key,
+ const IDBKey* primary_key,
+ std::unique_ptr<WebIDBCallbacks> callback);
+ void CursorContinueCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBCursorResultPtr result);
+
+ void PrefetchCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBCursorResultPtr result);
// Called after a cursor request's success handler is executed.
//
// This is only used by the cursor prefetching logic, and does not result in
// an IPC.
- virtual void PostSuccessHandlerCallback() = 0;
+ void PostSuccessHandlerCallback();
+
+ void SetPrefetchData(Vector<std::unique_ptr<IDBKey>> keys,
+ Vector<std::unique_ptr<IDBKey>> primary_keys,
+ Vector<std::unique_ptr<IDBValue>> values);
+
+ void CachedAdvance(uint32_t count, WebIDBCallbacks* callbacks);
+ void CachedContinue(WebIDBCallbacks* callbacks);
+
+ void ResetPrefetchCache();
+
+ int64_t transaction_id() const { return transaction_id_; }
+
+ private:
+ void AdvanceCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBCursorResultPtr result);
+ mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks> GetCallbacksProxy(
+ std::unique_ptr<WebIDBCallbacks> callbacks);
+
+ FRIEND_TEST_ALL_PREFIXES(WebIDBCursorTest, AdvancePrefetchTest);
+ FRIEND_TEST_ALL_PREFIXES(WebIDBCursorTest, PrefetchReset);
+ FRIEND_TEST_ALL_PREFIXES(WebIDBCursorTest, PrefetchTest);
+
+ static constexpr int kPrefetchContinueThreshold = 2;
+ static constexpr int kMinPrefetchAmount = 5;
+ static constexpr int kMaxPrefetchAmount = 100;
+
+ int64_t transaction_id_;
+
+ mojo::AssociatedRemote<mojom::blink::IDBCursor> cursor_;
+
+ // Prefetch cache. Keys and values are stored in reverse order so that a
+ // cache'd continue can pop a value off of the back and prevent new memory
+ // allocations.
+ Vector<std::unique_ptr<IDBKey>> prefetch_keys_;
+ Vector<std::unique_ptr<IDBKey>> prefetch_primary_keys_;
+ Vector<std::unique_ptr<IDBValue>> prefetch_values_;
+
+ // Number of continue calls that would qualify for a pre-fetch.
+ int continue_count_;
+
+ // Number of items used from the last prefetch.
+ int used_prefetches_;
+
+ // Number of onsuccess handlers we are waiting for.
+ int pending_onsuccess_callbacks_;
+
+ // Number of items to request in next prefetch.
+ int prefetch_amount_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- protected:
- WebIDBCursor() = default;
+ base::WeakPtrFactory<WebIDBCursor> weak_factory_{this};
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
deleted file mode 100644
index 9b127da6efc..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
+++ /dev/null
@@ -1,105 +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_MODULES_INDEXEDDB_WEB_IDB_CURSOR_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_IMPL_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/gtest_prod_util.h"
-#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "mojo/public/cpp/bindings/pending_associated_remote.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class MODULES_EXPORT WebIDBCursorImpl : public WebIDBCursor {
- public:
- WebIDBCursorImpl(
- mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> cursor,
- int64_t transaction_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~WebIDBCursorImpl() override;
-
- // Disallow copy and assign.
- WebIDBCursorImpl(const WebIDBCursorImpl&) = delete;
- WebIDBCursorImpl& operator=(const WebIDBCursorImpl&) = delete;
-
- void Advance(uint32_t count, WebIDBCallbacks* callback) override;
-
- void CursorContinue(const IDBKey* key,
- const IDBKey* primary_key,
- WebIDBCallbacks* callback) override;
- void CursorContinueCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBCursorResultPtr result);
- void PrefetchCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBCursorResultPtr result);
-
- void PostSuccessHandlerCallback() override;
-
- void SetPrefetchData(Vector<std::unique_ptr<IDBKey>> keys,
- Vector<std::unique_ptr<IDBKey>> primary_keys,
- Vector<std::unique_ptr<IDBValue>> values);
-
- void CachedAdvance(uint32_t count, WebIDBCallbacks* callbacks);
- void CachedContinue(WebIDBCallbacks* callbacks);
-
- // This method is virtual so it can be overridden in unit tests.
- virtual void ResetPrefetchCache();
-
- int64_t transaction_id() const { return transaction_id_; }
-
- private:
- void AdvanceCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBCursorResultPtr result);
- mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks> GetCallbacksProxy(
- std::unique_ptr<WebIDBCallbacks> callbacks);
-
- FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
- FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, AdvancePrefetchTest);
- FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchReset);
- FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
-
- static constexpr int kPrefetchContinueThreshold = 2;
- static constexpr int kMinPrefetchAmount = 5;
- static constexpr int kMaxPrefetchAmount = 100;
-
- int64_t transaction_id_;
-
- mojo::AssociatedRemote<mojom::blink::IDBCursor> cursor_;
-
- // Prefetch cache. Keys and values are stored in reverse order so that a
- // cache'd continue can pop a value off of the back and prevent new memory
- // allocations.
- Vector<std::unique_ptr<IDBKey>> prefetch_keys_;
- Vector<std::unique_ptr<IDBKey>> prefetch_primary_keys_;
- Vector<std::unique_ptr<IDBValue>> prefetch_values_;
-
- // Number of continue calls that would qualify for a pre-fetch.
- int continue_count_;
-
- // Number of items used from the last prefetch.
- int used_prefetches_;
-
- // Number of onsuccess handlers we are waiting for.
- int pending_onsuccess_callbacks_;
-
- // Number of items to request in next prefetch.
- int prefetch_amount_;
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- base::WeakPtrFactory<WebIDBCursorImpl> weak_factory_{this};
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_unittest.cc
index 05cdaeb6307..02294a2b754 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_unittest.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/modules/indexeddb/web_idb_cursor_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
#include <stddef.h>
#include <stdint.h>
@@ -91,7 +91,7 @@ class MockContinueCallbacks : public testing::StrictMock<MockWebIDBCallbacks> {
Vector<WebBlobInfo>* blobs = nullptr)
: key_(key), blobs_(blobs) {}
- void SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
+ void SetState(base::WeakPtr<WebIDBCursor> cursor,
int64_t transaction_id) override {}
void SuccessValue(mojom::blink::IDBReturnValuePtr return_value) override {}
@@ -112,35 +112,35 @@ class MockContinueCallbacks : public testing::StrictMock<MockWebIDBCallbacks> {
} // namespace
-class WebIDBCursorImplTest : public testing::Test {
+class WebIDBCursorTest : public testing::Test {
public:
- WebIDBCursorImplTest() : null_key_(IDBKey::CreateNone()) {
+ WebIDBCursorTest() : null_key_(IDBKey::CreateNone()) {
mojo::AssociatedRemote<mojom::blink::IDBCursor> remote;
mock_cursor_ = std::make_unique<MockCursorImpl>(
remote.BindNewEndpointAndPassDedicatedReceiver());
- cursor_ = std::make_unique<WebIDBCursorImpl>(
+ cursor_ = std::make_unique<WebIDBCursor>(
remote.Unbind(), 1,
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
}
// Disallow copy and assign.
- WebIDBCursorImplTest(const WebIDBCursorImplTest&) = delete;
- WebIDBCursorImplTest& operator=(const WebIDBCursorImplTest&) = delete;
+ WebIDBCursorTest(const WebIDBCursorTest&) = delete;
+ WebIDBCursorTest& operator=(const WebIDBCursorTest&) = delete;
protected:
ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
std::unique_ptr<IDBKey> null_key_;
- std::unique_ptr<WebIDBCursorImpl> cursor_;
+ std::unique_ptr<WebIDBCursor> cursor_;
std::unique_ptr<MockCursorImpl> mock_cursor_;
};
-TEST_F(WebIDBCursorImplTest, PrefetchTest) {
+TEST_F(WebIDBCursorTest, PrefetchTest) {
// Call continue() until prefetching should kick in.
int continue_calls = 0;
EXPECT_EQ(mock_cursor_->continue_calls(), 0);
- for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
+ for (int i = 0; i < WebIDBCursor::kPrefetchContinueThreshold; ++i) {
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks());
+ std::make_unique<MockContinueCallbacks>());
platform_->RunUntilIdle();
EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(0, mock_cursor_->prefetch_calls());
@@ -155,7 +155,7 @@ TEST_F(WebIDBCursorImplTest, PrefetchTest) {
for (int repetitions = 0; repetitions < kPrefetchRepetitions; ++repetitions) {
// Initiate the prefetch
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks());
+ std::make_unique<MockContinueCallbacks>());
platform_->RunUntilIdle();
EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls());
@@ -197,8 +197,9 @@ TEST_F(WebIDBCursorImplTest, PrefetchTest) {
for (int i = 0; i < prefetch_count; ++i) {
std::unique_ptr<IDBKey> key;
Vector<WebBlobInfo> blobs;
- cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks(&key, &blobs));
+ cursor_->CursorContinue(
+ null_key_.get(), null_key_.get(),
+ std::make_unique<MockContinueCallbacks>(&key, &blobs));
platform_->RunUntilIdle();
EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls());
@@ -214,23 +215,23 @@ TEST_F(WebIDBCursorImplTest, PrefetchTest) {
EXPECT_TRUE(mock_cursor_->destroyed());
}
-TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
+TEST_F(WebIDBCursorTest, AdvancePrefetchTest) {
// Call continue() until prefetching should kick in.
EXPECT_EQ(0, mock_cursor_->continue_calls());
- for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
+ for (int i = 0; i < WebIDBCursor::kPrefetchContinueThreshold; ++i) {
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks());
+ std::make_unique<MockContinueCallbacks>());
}
platform_->RunUntilIdle();
EXPECT_EQ(0, mock_cursor_->prefetch_calls());
// Initiate the prefetch
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks());
+ std::make_unique<MockContinueCallbacks>());
platform_->RunUntilIdle();
EXPECT_EQ(1, mock_cursor_->prefetch_calls());
- EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
+ EXPECT_EQ(static_cast<int>(WebIDBCursor::kPrefetchContinueThreshold),
mock_cursor_->continue_calls());
EXPECT_EQ(0, mock_cursor_->advance_calls());
@@ -271,35 +272,35 @@ TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
// IDBCursor.continue()
std::unique_ptr<IDBKey> key;
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks(&key));
+ std::make_unique<MockContinueCallbacks>(&key));
platform_->RunUntilIdle();
EXPECT_EQ(0, key->Number());
// IDBCursor.advance(1)
- cursor_->Advance(1, new MockContinueCallbacks(&key));
+ cursor_->Advance(1, std::make_unique<MockContinueCallbacks>(&key));
platform_->RunUntilIdle();
EXPECT_EQ(1, key->Number());
// IDBCursor.continue()
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks(&key));
+ std::make_unique<MockContinueCallbacks>(&key));
platform_->RunUntilIdle();
EXPECT_EQ(2, key->Number());
// IDBCursor.advance(2)
- cursor_->Advance(2, new MockContinueCallbacks(&key));
+ cursor_->Advance(2, std::make_unique<MockContinueCallbacks>(&key));
platform_->RunUntilIdle();
EXPECT_EQ(4, key->Number());
EXPECT_EQ(0, mock_cursor_->advance_calls());
// IDBCursor.advance(lots) - beyond the fetched amount
- cursor_->Advance(WebIDBCursorImpl::kMaxPrefetchAmount,
- new MockContinueCallbacks(&key));
+ cursor_->Advance(WebIDBCursor::kMaxPrefetchAmount,
+ std::make_unique<MockContinueCallbacks>(&key));
platform_->RunUntilIdle();
EXPECT_EQ(1, mock_cursor_->advance_calls());
EXPECT_EQ(1, mock_cursor_->prefetch_calls());
- EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
+ EXPECT_EQ(static_cast<int>(WebIDBCursor::kPrefetchContinueThreshold),
mock_cursor_->continue_calls());
cursor_.reset();
@@ -307,13 +308,13 @@ TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
EXPECT_TRUE(mock_cursor_->destroyed());
}
-TEST_F(WebIDBCursorImplTest, PrefetchReset) {
+TEST_F(WebIDBCursorTest, PrefetchReset) {
// Call continue() until prefetching should kick in.
int continue_calls = 0;
EXPECT_EQ(mock_cursor_->continue_calls(), 0);
- for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
+ for (int i = 0; i < WebIDBCursor::kPrefetchContinueThreshold; ++i) {
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks());
+ std::make_unique<MockContinueCallbacks>());
platform_->RunUntilIdle();
EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(0, mock_cursor_->prefetch_calls());
@@ -321,7 +322,7 @@ TEST_F(WebIDBCursorImplTest, PrefetchReset) {
// Initiate the prefetch
cursor_->CursorContinue(null_key_.get(), null_key_.get(),
- new MockContinueCallbacks());
+ std::make_unique<MockContinueCallbacks>());
platform_->RunUntilIdle();
EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(1, mock_cursor_->prefetch_calls());
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.cc
index d0e7e4a768c..8383e755289 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.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/modules/indexeddb/web_idb_database_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
#include <utility>
@@ -20,46 +20,46 @@
namespace blink {
-WebIDBDatabaseImpl::WebIDBDatabaseImpl(
+WebIDBDatabase::WebIDBDatabase(
mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase> pending_database,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(std::move(task_runner)) {
database_.Bind(std::move(pending_database), task_runner_);
}
-WebIDBDatabaseImpl::~WebIDBDatabaseImpl() = default;
+WebIDBDatabase::~WebIDBDatabase() = default;
-void WebIDBDatabaseImpl::RenameObjectStore(int64_t transaction_id,
- int64_t object_store_id,
- const String& new_name) {
+void WebIDBDatabase::RenameObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const String& new_name) {
database_->RenameObjectStore(transaction_id, object_store_id, new_name);
}
-void WebIDBDatabaseImpl::CreateTransaction(
+void WebIDBDatabase::CreateTransaction(
mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
transaction_receiver,
int64_t transaction_id,
const Vector<int64_t>& object_store_ids,
- mojom::IDBTransactionMode mode,
- mojom::IDBTransactionDurability durability) {
+ mojom::blink::IDBTransactionMode mode,
+ mojom::blink::IDBTransactionDurability durability) {
database_->CreateTransaction(std::move(transaction_receiver), transaction_id,
object_store_ids, mode, durability);
}
-void WebIDBDatabaseImpl::Close() {
+void WebIDBDatabase::Close() {
database_->Close();
}
-void WebIDBDatabaseImpl::VersionChangeIgnored() {
+void WebIDBDatabase::VersionChangeIgnored() {
database_->VersionChangeIgnored();
}
-void WebIDBDatabaseImpl::Get(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange* key_range,
- bool key_only,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBDatabase::Get(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange* key_range,
+ bool key_only,
+ WebIDBCallbacks* callbacks_ptr) {
std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
@@ -68,13 +68,12 @@ void WebIDBDatabaseImpl::Get(int64_t transaction_id,
callbacks->SetState(nullptr, transaction_id);
database_->Get(transaction_id, object_store_id, index_id,
std::move(key_range_ptr), key_only,
- WTF::Bind(&WebIDBDatabaseImpl::GetCallback,
- WTF::Unretained(this), std::move(callbacks)));
+ WTF::Bind(&WebIDBDatabase::GetCallback, WTF::Unretained(this),
+ std::move(callbacks)));
}
-void WebIDBDatabaseImpl::GetCallback(
- std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBDatabaseGetResultPtr result) {
+void WebIDBDatabase::GetCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBDatabaseGetResultPtr result) {
if (result->is_error_result()) {
callbacks->Error(result->get_error_result()->error_code,
std::move(result->get_error_result()->error_message));
@@ -101,13 +100,13 @@ void WebIDBDatabaseImpl::GetCallback(
}
}
-void WebIDBDatabaseImpl::GetAll(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange* key_range,
- int64_t max_count,
- bool key_only,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBDatabase::GetAll(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange* key_range,
+ int64_t max_count,
+ bool key_only,
+ WebIDBCallbacks* callbacks_ptr) {
std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
@@ -117,40 +116,40 @@ void WebIDBDatabaseImpl::GetAll(int64_t transaction_id,
database_->GetAll(
transaction_id, object_store_id, index_id, std::move(key_range_ptr),
key_only, max_count,
- WTF::Bind(&WebIDBDatabaseImpl::GetAllCallback, WTF::Unretained(this),
+ WTF::Bind(&WebIDBDatabase::GetAllCallback, WTF::Unretained(this),
std::move(callbacks), key_only));
}
-void WebIDBDatabaseImpl::GetAllCallback(
+void WebIDBDatabase::GetAllCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
bool key_only,
mojo::PendingReceiver<mojom::blink::IDBDatabaseGetAllResultSink> receiver) {
callbacks->ReceiveGetAllResults(key_only, std::move(receiver));
}
-void WebIDBDatabaseImpl::SetIndexKeys(int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IDBKey> primary_key,
- Vector<IDBIndexKeys> index_keys) {
+void WebIDBDatabase::SetIndexKeys(int64_t transaction_id,
+ int64_t object_store_id,
+ std::unique_ptr<IDBKey> primary_key,
+ Vector<IDBIndexKeys> index_keys) {
database_->SetIndexKeys(transaction_id, object_store_id,
std::move(primary_key), std::move(index_keys));
}
-void WebIDBDatabaseImpl::SetIndexesReady(int64_t transaction_id,
- int64_t object_store_id,
- const Vector<int64_t>& index_ids) {
+void WebIDBDatabase::SetIndexesReady(int64_t transaction_id,
+ int64_t object_store_id,
+ const Vector<int64_t>& index_ids) {
database_->SetIndexesReady(transaction_id, object_store_id,
std::move(index_ids));
}
-void WebIDBDatabaseImpl::OpenCursor(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange* key_range,
- mojom::IDBCursorDirection direction,
- bool key_only,
- mojom::IDBTaskType task_type,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBDatabase::OpenCursor(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange* key_range,
+ mojom::blink::IDBCursorDirection direction,
+ bool key_only,
+ mojom::blink::IDBTaskType task_type,
+ WebIDBCallbacks* callbacks_ptr) {
std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
@@ -160,11 +159,11 @@ void WebIDBDatabaseImpl::OpenCursor(int64_t transaction_id,
database_->OpenCursor(transaction_id, object_store_id, index_id,
std::move(key_range_ptr), direction, key_only,
task_type,
- WTF::Bind(&WebIDBDatabaseImpl::OpenCursorCallback,
+ WTF::Bind(&WebIDBDatabase::OpenCursorCallback,
WTF::Unretained(this), std::move(callbacks)));
}
-void WebIDBDatabaseImpl::OpenCursorCallback(
+void WebIDBDatabase::OpenCursorCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
mojom::blink::IDBDatabaseOpenCursorResultPtr result) {
if (result->is_error_result()) {
@@ -189,11 +188,11 @@ void WebIDBDatabaseImpl::OpenCursorCallback(
callbacks.reset();
}
-void WebIDBDatabaseImpl::Count(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange* key_range,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabase::Count(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange* key_range,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
mojom::blink::IDBKeyRangePtr key_range_ptr =
@@ -204,10 +203,10 @@ void WebIDBDatabaseImpl::Count(int64_t transaction_id,
GetCallbacksProxy(base::WrapUnique(callbacks)));
}
-void WebIDBDatabaseImpl::Delete(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKey* primary_key,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabase::Delete(int64_t transaction_id,
+ int64_t object_store_id,
+ const IDBKey* primary_key,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
mojom::blink::IDBKeyRangePtr key_range_ptr =
@@ -218,10 +217,10 @@ void WebIDBDatabaseImpl::Delete(int64_t transaction_id,
GetCallbacksProxy(base::WrapUnique(callbacks)));
}
-void WebIDBDatabaseImpl::DeleteRange(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKeyRange* key_range,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabase::DeleteRange(int64_t transaction_id,
+ int64_t object_store_id,
+ const IDBKeyRange* key_range,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
mojom::blink::IDBKeyRangePtr key_range_ptr =
@@ -232,19 +231,18 @@ void WebIDBDatabaseImpl::DeleteRange(int64_t transaction_id,
GetCallbacksProxy(base::WrapUnique(callbacks)));
}
-void WebIDBDatabaseImpl::GetKeyGeneratorCurrentNumber(
- int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabase::GetKeyGeneratorCurrentNumber(int64_t transaction_id,
+ int64_t object_store_id,
+ WebIDBCallbacks* callbacks) {
callbacks->SetState(nullptr, transaction_id);
database_->GetKeyGeneratorCurrentNumber(
transaction_id, object_store_id,
GetCallbacksProxy(base::WrapUnique(callbacks)));
}
-void WebIDBDatabaseImpl::Clear(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabase::Clear(int64_t transaction_id,
+ int64_t object_store_id,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
callbacks->SetState(nullptr, transaction_id);
@@ -252,37 +250,37 @@ void WebIDBDatabaseImpl::Clear(int64_t transaction_id,
GetCallbacksProxy(base::WrapUnique(callbacks)));
}
-void WebIDBDatabaseImpl::CreateIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& name,
- const IDBKeyPath& key_path,
- bool unique,
- bool multi_entry) {
+void WebIDBDatabase::CreateIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const String& name,
+ const IDBKeyPath& key_path,
+ bool unique,
+ bool multi_entry) {
database_->CreateIndex(transaction_id, object_store_id, index_id, name,
key_path, unique, multi_entry);
}
-void WebIDBDatabaseImpl::DeleteIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id) {
+void WebIDBDatabase::DeleteIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id) {
database_->DeleteIndex(transaction_id, object_store_id, index_id);
}
-void WebIDBDatabaseImpl::RenameIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& new_name) {
+void WebIDBDatabase::RenameIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const String& new_name) {
DCHECK(!new_name.IsNull());
database_->RenameIndex(transaction_id, object_store_id, index_id, new_name);
}
-void WebIDBDatabaseImpl::Abort(int64_t transaction_id) {
+void WebIDBDatabase::Abort(int64_t transaction_id) {
database_->Abort(transaction_id);
}
mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks>
-WebIDBDatabaseImpl::GetCallbacksProxy(
+WebIDBDatabase::GetCallbacksProxy(
std::unique_ptr<WebIDBCallbacks> callbacks_impl) {
mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks> pending_callbacks;
mojo::MakeSelfOwnedAssociatedReceiver(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.h
index f2b4872ff11..fd6bf1a30f5 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.h
@@ -1,132 +1,123 @@
-/*
- * 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 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 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_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
-#include <bitset>
+#include <stdint.h>
#include <memory>
+#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-
-class IDBKeyRange;
class WebIDBCallbacks;
-class MODULES_EXPORT WebIDBDatabase {
+class MODULES_EXPORT WebIDBDatabase final {
public:
- virtual ~WebIDBDatabase() = default;
-
- virtual void RenameObjectStore(int64_t transaction_id,
- int64_t object_store_id,
- const String& name) = 0;
- virtual void CreateTransaction(
- mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
- transaction_receiver,
- int64_t id,
- const Vector<int64_t>& scope,
- mojom::IDBTransactionMode,
- mojom::IDBTransactionDurability) = 0;
- virtual void Close() = 0;
- virtual void VersionChangeIgnored() = 0;
+ WebIDBDatabase(
+ mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase> pending_database,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~WebIDBDatabase();
- virtual void Abort(int64_t transaction_id) = 0;
+ static const int64_t kMinimumIndexId = 30;
- virtual void CreateIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& name,
- const IDBKeyPath&,
- bool unique,
- bool multi_entry) = 0;
- virtual void DeleteIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id) = 0;
- virtual void RenameIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& new_name) = 0;
+ void RenameObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const String& new_name);
+ void CreateTransaction(mojo::PendingAssociatedReceiver<
+ mojom::blink::IDBTransaction> transaction_receiver,
+ int64_t transaction_id,
+ const Vector<int64_t>& scope,
+ mojom::blink::IDBTransactionMode mode,
+ mojom::blink::IDBTransactionDurability durability);
- static const int64_t kMinimumIndexId = 30;
+ void Close();
+ void VersionChangeIgnored();
- virtual void Get(int64_t transaction_id,
+ void Get(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange*,
+ bool key_only,
+ WebIDBCallbacks*);
+ void GetCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBDatabaseGetResultPtr result);
+ void GetAll(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange*,
+ int64_t max_count,
+ bool key_only,
+ WebIDBCallbacks*);
+ void GetAllCallback(
+ std::unique_ptr<WebIDBCallbacks> callbacks,
+ bool key_only,
+ mojo::PendingReceiver<mojom::blink::IDBDatabaseGetAllResultSink>
+ receiver);
+ void SetIndexKeys(int64_t transaction_id,
+ int64_t object_store_id,
+ std::unique_ptr<IDBKey> primary_key,
+ Vector<IDBIndexKeys>);
+ void SetIndexesReady(int64_t transaction_id,
+ int64_t object_store_id,
+ const Vector<int64_t>& index_ids);
+ void OpenCursor(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange*,
+ mojom::blink::IDBCursorDirection direction,
+ bool key_only,
+ mojom::blink::IDBTaskType,
+ WebIDBCallbacks*);
+ void OpenCursorCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBDatabaseOpenCursorResultPtr result);
+ void Count(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IDBKeyRange*,
+ WebIDBCallbacks*);
+ void Delete(int64_t transaction_id,
+ int64_t object_store_id,
+ const IDBKey* primary_key,
+ WebIDBCallbacks*);
+ void DeleteRange(int64_t transaction_id,
int64_t object_store_id,
- int64_t index_id,
const IDBKeyRange*,
- bool key_only,
- WebIDBCallbacks*) = 0;
- virtual void GetAll(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- int64_t max_count,
- bool key_only,
- WebIDBCallbacks*) = 0;
- virtual void SetIndexKeys(int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IDBKey> primary_key,
- Vector<IDBIndexKeys>) = 0;
- virtual void SetIndexesReady(int64_t transaction_id,
- int64_t object_store_id,
- const Vector<int64_t>& index_ids) = 0;
- virtual void OpenCursor(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- mojom::IDBCursorDirection,
- bool key_only,
- mojom::IDBTaskType,
- WebIDBCallbacks*) = 0;
- virtual void Count(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- WebIDBCallbacks*) = 0;
- virtual void Delete(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKey* primary_key,
- WebIDBCallbacks*) = 0;
- virtual void DeleteRange(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKeyRange*,
- WebIDBCallbacks*) = 0;
- virtual void GetKeyGeneratorCurrentNumber(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks*) = 0;
- virtual void Clear(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks*) = 0;
+ WebIDBCallbacks*);
+ void GetKeyGeneratorCurrentNumber(int64_t transaction_id,
+ int64_t object_store_id,
+ WebIDBCallbacks*);
+ void Clear(int64_t transaction_id, int64_t object_store_id, WebIDBCallbacks*);
+ void CreateIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const String& name,
+ const IDBKeyPath&,
+ bool unique,
+ bool multi_entry);
+ void DeleteIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id);
+ void RenameIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const String& new_name);
+ void Abort(int64_t transaction_id);
+
+ private:
+ mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks> GetCallbacksProxy(
+ std::unique_ptr<WebIDBCallbacks> callbacks);
- protected:
- WebIDBDatabase() = default;
+ mojo::AssociatedRemote<mojom::blink::IDBDatabase> database_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h
deleted file mode 100644
index a0c1c0af3f0..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h
+++ /dev/null
@@ -1,127 +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_MODULES_INDEXEDDB_WEB_IDB_DATABASE_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_IMPL_H_
-
-#include <stdint.h>
-#include <memory>
-
-#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "mojo/public/cpp/bindings/pending_associated_remote.h"
-#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-class WebIDBCallbacks;
-
-class MODULES_EXPORT WebIDBDatabaseImpl : public WebIDBDatabase {
- public:
- WebIDBDatabaseImpl(
- mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase> pending_database,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~WebIDBDatabaseImpl() override;
-
- // WebIDBDatabase
- void RenameObjectStore(int64_t transaction_id,
- int64_t object_store_id,
- const String& new_name) override;
- void CreateTransaction(mojo::PendingAssociatedReceiver<
- mojom::blink::IDBTransaction> transaction_receiver,
- int64_t transaction_id,
- const Vector<int64_t>& scope,
- mojom::IDBTransactionMode mode,
- mojom::IDBTransactionDurability durability) override;
-
- void Close() override;
- void VersionChangeIgnored() override;
-
- void Get(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- bool key_only,
- WebIDBCallbacks*) override;
- void GetCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBDatabaseGetResultPtr result);
- void GetAll(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- int64_t max_count,
- bool key_only,
- WebIDBCallbacks*) override;
- void GetAllCallback(
- std::unique_ptr<WebIDBCallbacks> callbacks,
- bool key_only,
- mojo::PendingReceiver<mojom::blink::IDBDatabaseGetAllResultSink>
- receiver);
- void SetIndexKeys(int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IDBKey> primary_key,
- Vector<IDBIndexKeys>) override;
- void SetIndexesReady(int64_t transaction_id,
- int64_t object_store_id,
- const Vector<int64_t>& index_ids) override;
- void OpenCursor(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- mojom::IDBCursorDirection direction,
- bool key_only,
- mojom::IDBTaskType,
- WebIDBCallbacks*) override;
- void OpenCursorCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBDatabaseOpenCursorResultPtr result);
- void Count(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IDBKeyRange*,
- WebIDBCallbacks*) override;
- void Delete(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKey* primary_key,
- WebIDBCallbacks*) override;
- void DeleteRange(int64_t transaction_id,
- int64_t object_store_id,
- const IDBKeyRange*,
- WebIDBCallbacks*) override;
- void GetKeyGeneratorCurrentNumber(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks*) override;
- void Clear(int64_t transaction_id,
- int64_t object_store_id,
- WebIDBCallbacks*) override;
- void CreateIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& name,
- const IDBKeyPath&,
- bool unique,
- bool multi_entry) override;
- void DeleteIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id) override;
- void RenameIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const String& new_name) override;
- void Abort(int64_t transaction_id) override;
-
- private:
- mojo::PendingAssociatedRemote<mojom::blink::IDBCallbacks> GetCallbacksProxy(
- std::unique_ptr<WebIDBCallbacks> callbacks);
-
- mojo::AssociatedRemote<mojom::blink::IDBDatabase> database_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.cc
index 5bf11c6d3a4..7aaf5b56114 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.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/modules/indexeddb/web_idb_transaction_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h"
#include <cstddef>
#include <memory>
@@ -21,36 +21,36 @@
namespace blink {
-WebIDBTransactionImpl::WebIDBTransactionImpl(
+WebIDBTransaction::WebIDBTransaction(
scoped_refptr<base::SequencedTaskRunner> task_runner,
int64_t transaction_id)
: task_runner_(task_runner), transaction_id_(transaction_id) {}
-WebIDBTransactionImpl::~WebIDBTransactionImpl() = default;
+WebIDBTransaction::~WebIDBTransaction() = default;
mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
-WebIDBTransactionImpl::CreateReceiver() {
+WebIDBTransaction::CreateReceiver() {
return transaction_.BindNewEndpointAndPassReceiver(task_runner_);
}
-void WebIDBTransactionImpl::CreateObjectStore(int64_t object_store_id,
- const String& name,
- const IDBKeyPath& key_path,
- bool auto_increment) {
+void WebIDBTransaction::CreateObjectStore(int64_t object_store_id,
+ const String& name,
+ const IDBKeyPath& key_path,
+ bool auto_increment) {
transaction_->CreateObjectStore(object_store_id, name, key_path,
auto_increment);
}
-void WebIDBTransactionImpl::DeleteObjectStore(int64_t object_store_id) {
+void WebIDBTransaction::DeleteObjectStore(int64_t object_store_id) {
transaction_->DeleteObjectStore(object_store_id);
}
-void WebIDBTransactionImpl::Put(int64_t object_store_id,
- std::unique_ptr<IDBValue> value,
- std::unique_ptr<IDBKey> primary_key,
- mojom::IDBPutMode put_mode,
- std::unique_ptr<WebIDBCallbacks> callbacks,
- Vector<IDBIndexKeys> index_keys) {
+void WebIDBTransaction::Put(int64_t object_store_id,
+ std::unique_ptr<IDBValue> value,
+ std::unique_ptr<IDBKey> primary_key,
+ mojom::blink::IDBPutMode put_mode,
+ std::unique_ptr<WebIDBCallbacks> callbacks,
+ Vector<IDBIndexKeys> index_keys) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, nullptr);
size_t index_keys_size = 0;
@@ -77,11 +77,11 @@ void WebIDBTransactionImpl::Put(int64_t object_store_id,
callbacks->SetState(nullptr, transaction_id_);
transaction_->Put(object_store_id, std::move(value), std::move(primary_key),
put_mode, std::move(index_keys),
- WTF::Bind(&WebIDBTransactionImpl::PutCallback,
+ WTF::Bind(&WebIDBTransaction::PutCallback,
WTF::Unretained(this), std::move(callbacks)));
}
-void WebIDBTransactionImpl::PutCallback(
+void WebIDBTransaction::PutCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
mojom::blink::IDBTransactionPutResultPtr result) {
if (result->is_error_result()) {
@@ -98,9 +98,9 @@ void WebIDBTransactionImpl::PutCallback(
}
}
-void WebIDBTransactionImpl::PutAll(int64_t object_store_id,
- Vector<mojom::blink::IDBPutParamsPtr> puts,
- std::unique_ptr<WebIDBCallbacks> callbacks) {
+void WebIDBTransaction::PutAll(int64_t object_store_id,
+ Vector<mojom::blink::IDBPutParamsPtr> puts,
+ std::unique_ptr<WebIDBCallbacks> callbacks) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, nullptr);
base::CheckedNumeric<size_t> index_keys_size = 0;
for (auto& put : puts) {
@@ -130,11 +130,11 @@ void WebIDBTransactionImpl::PutAll(int64_t object_store_id,
callbacks->SetState(nullptr, transaction_id_);
transaction_->PutAll(object_store_id, std::move(puts),
- WTF::Bind(&WebIDBTransactionImpl::PutAllCallback,
+ WTF::Bind(&WebIDBTransaction::PutAllCallback,
WTF::Unretained(this), std::move(callbacks)));
}
-void WebIDBTransactionImpl::PutAllCallback(
+void WebIDBTransaction::PutAllCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
mojom::blink::IDBTransactionPutAllResultPtr result) {
if (result->is_error_result()) {
@@ -151,8 +151,12 @@ void WebIDBTransactionImpl::PutAllCallback(
}
}
-void WebIDBTransactionImpl::Commit(int64_t num_errors_handled) {
+void WebIDBTransaction::Commit(int64_t num_errors_handled) {
transaction_->Commit(num_errors_handled);
}
+void WebIDBTransaction::FlushForTesting() {
+ transaction_.FlushForTesting();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h
index 0e0120e8961..91dd2694094 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h
@@ -1,67 +1,68 @@
-/*
- * Copyright (C) 2019 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_TRANSACTION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_TRANSACTION_H_
+#include <stdint.h>
#include <memory>
+#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
-class IDBKeyPath;
-
-class MODULES_EXPORT WebIDBTransaction {
+class MODULES_EXPORT WebIDBTransaction final {
public:
- virtual ~WebIDBTransaction() = default;
+ WebIDBTransaction(scoped_refptr<base::SequencedTaskRunner> task_runner,
+ int64_t transaction_id);
+ ~WebIDBTransaction();
+
+ void CreateObjectStore(int64_t objectstore_id,
+ const String& name,
+ const IDBKeyPath&,
+ bool auto_increment);
+ void DeleteObjectStore(int64_t object_store_id);
+ void Put(int64_t object_store_id,
+ std::unique_ptr<IDBValue> value,
+ std::unique_ptr<IDBKey> primary_key,
+ mojom::blink::IDBPutMode,
+ std::unique_ptr<WebIDBCallbacks> callbacks,
+ Vector<IDBIndexKeys>);
+ void PutAll(int64_t object_store_id,
+ Vector<mojom::blink::IDBPutParamsPtr> puts,
+ std::unique_ptr<WebIDBCallbacks> callbacks);
+ void PutCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBTransactionPutResultPtr result);
+ void PutAllCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+ mojom::blink::IDBTransactionPutAllResultPtr result);
+ void Commit(int64_t num_errors_handled);
+
+ mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
+ CreateReceiver();
+
+ void FlushForTesting();
- virtual void CreateObjectStore(int64_t object_store_id,
- const String& name,
- const IDBKeyPath&,
- bool auto_increment) = 0;
- virtual void DeleteObjectStore(int64_t object_store_id) = 0;
- virtual void Put(int64_t object_store_id,
- std::unique_ptr<IDBValue> value,
- std::unique_ptr<IDBKey> primary_key,
- mojom::IDBPutMode,
- std::unique_ptr<WebIDBCallbacks>,
- Vector<IDBIndexKeys>) = 0;
- virtual void PutAll(int64_t object_store_id,
- Vector<mojom::blink::IDBPutParamsPtr> puts,
- std::unique_ptr<WebIDBCallbacks> callbacks) = 0;
- virtual void Commit(int64_t num_errors_handled) = 0;
+ private:
+ FRIEND_TEST_ALL_PREFIXES(WebIDBTransactionTest, ValueSizeTest);
+ FRIEND_TEST_ALL_PREFIXES(WebIDBTransactionTest, KeyAndValueSizeTest);
- virtual mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
- CreateReceiver() = 0;
+ // Maximum size (in bytes) of value/key pair allowed for put requests. Any
+ // requests larger than this size will be rejected.
+ // Used by unit tests to exercise behavior without allocating huge chunks
+ // of memory.
+ size_t max_put_value_size_ =
+ mojom::blink::kIDBMaxMessageSize - mojom::blink::kIDBMaxMessageOverhead;
- protected:
- WebIDBTransaction() = default;
+ mojo::AssociatedRemote<mojom::blink::IDBTransaction> transaction_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ int64_t transaction_id_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h
deleted file mode 100644
index 49b9f043d7e..00000000000
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_TRANSACTION_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_TRANSACTION_IMPL_H_
-
-#include <stdint.h>
-#include <memory>
-
-#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class MODULES_EXPORT WebIDBTransactionImpl : public WebIDBTransaction {
- public:
- WebIDBTransactionImpl(scoped_refptr<base::SequencedTaskRunner> task_runner,
- int64_t transaction_id);
- ~WebIDBTransactionImpl() override;
-
- // WebIDBTransaction
- void CreateObjectStore(int64_t objectstore_id,
- const String& name,
- const IDBKeyPath&,
- bool auto_increment) override;
- void DeleteObjectStore(int64_t object_store_id) override;
- void Put(int64_t object_store_id,
- std::unique_ptr<IDBValue> value,
- std::unique_ptr<IDBKey> primary_key,
- mojom::IDBPutMode,
- std::unique_ptr<WebIDBCallbacks> callbacks,
- Vector<IDBIndexKeys>) override;
- void PutAll(int64_t object_store_id,
- Vector<mojom::blink::IDBPutParamsPtr> puts,
- std::unique_ptr<WebIDBCallbacks> callbacks) override;
- void PutCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBTransactionPutResultPtr result);
- void PutAllCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
- mojom::blink::IDBTransactionPutAllResultPtr result);
- void Commit(int64_t num_errors_handled) override;
-
- mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction> CreateReceiver()
- override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(WebIDBTransactionImplTest, ValueSizeTest);
- FRIEND_TEST_ALL_PREFIXES(WebIDBTransactionImplTest, KeyAndValueSizeTest);
-
- // Maximum size (in bytes) of value/key pair allowed for put requests. Any
- // requests larger than this size will be rejected.
- // Used by unit tests to exercise behavior without allocating huge chunks
- // of memory.
- size_t max_put_value_size_ =
- mojom::blink::kIDBMaxMessageSize - mojom::blink::kIDBMaxMessageOverhead;
-
- mojo::AssociatedRemote<mojom::blink::IDBTransaction> transaction_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- int64_t transaction_id_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_TRANSACTION_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl_unittest.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_unittest.cc
index d2e44d9ad74..3ef75f65688 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction_unittest.cc
@@ -15,7 +15,7 @@
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
#include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h"
+#include "third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h"
using testing::_;
using testing::Invoke;
@@ -24,9 +24,9 @@ using testing::WithArgs;
namespace blink {
-class WebIDBTransactionImplTest : public testing::Test {};
+class WebIDBTransactionTest : public testing::Test {};
-TEST_F(WebIDBTransactionImplTest, ValueSizeTest) {
+TEST_F(WebIDBTransactionTest, ValueSizeTest) {
// For testing use a much smaller maximum size to prevent allocating >100 MB
// of memory, which crashes on memory-constrained systems.
const size_t kMaxValueSizeForTesting = 10 * 1024 * 1024; // 10 MB
@@ -46,15 +46,15 @@ TEST_F(WebIDBTransactionImplTest, ValueSizeTest) {
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_CALL(*callbacks, Error(_, _)).Times(1);
- WebIDBTransactionImpl transaction_impl(
+ WebIDBTransaction transaction(
blink::scheduler::GetSingleThreadTaskRunnerForTesting(), transaction_id);
- transaction_impl.max_put_value_size_ = kMaxValueSizeForTesting;
- transaction_impl.Put(object_store_id, std::move(value), std::move(key),
- mojom::IDBPutMode::AddOrUpdate, std::move(callbacks),
- Vector<IDBIndexKeys>());
+ transaction.max_put_value_size_ = kMaxValueSizeForTesting;
+ transaction.Put(object_store_id, std::move(value), std::move(key),
+ mojom::IDBPutMode::AddOrUpdate, std::move(callbacks),
+ Vector<IDBIndexKeys>());
}
-TEST_F(WebIDBTransactionImplTest, KeyAndValueSizeTest) {
+TEST_F(WebIDBTransactionTest, KeyAndValueSizeTest) {
// For testing use a much smaller maximum size to prevent allocating >100 MB
// of memory, which crashes on memory-constrained systems.
const size_t kMaxValueSizeForTesting = 10 * 1024 * 1024; // 10 MB
@@ -89,12 +89,12 @@ TEST_F(WebIDBTransactionImplTest, KeyAndValueSizeTest) {
ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_CALL(*callbacks, Error(_, _)).Times(1);
- WebIDBTransactionImpl transaction_impl(
+ WebIDBTransaction transaction(
blink::scheduler::GetSingleThreadTaskRunnerForTesting(), transaction_id);
- transaction_impl.max_put_value_size_ = kMaxValueSizeForTesting;
- transaction_impl.Put(object_store_id, std::move(value), std::move(key),
- mojom::IDBPutMode::AddOrUpdate, std::move(callbacks),
- Vector<IDBIndexKeys>());
+ transaction.max_put_value_size_ = kMaxValueSizeForTesting;
+ transaction.Put(object_store_id, std::move(value), std::move(key),
+ mojom::IDBPutMode::AddOrUpdate, std::move(callbacks),
+ Vector<IDBIndexKeys>());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/idls.gni b/chromium/third_party/blink/renderer/modules/installedapp/idls.gni
deleted file mode 100644
index 4e38e2b809b..00000000000
--- a/chromium/third_party/blink/renderer/modules/installedapp/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "navigator_installed_app.idl" ]
-
-modules_dictionary_idl_files = [ "related_application.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc b/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc
index cc979093e31..0e37d959238 100644
--- a/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc
@@ -8,7 +8,6 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/installedapp/related_application.mojom-blink.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/idls.gni b/chromium/third_party/blink/renderer/modules/keyboard/idls.gni
deleted file mode 100644
index 3c1e3e9d96e..00000000000
--- a/chromium/third_party/blink/renderer/modules/keyboard/idls.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "keyboard.idl",
- "keyboard_layout_map.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_keyboard.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/launch/idls.gni b/chromium/third_party/blink/renderer/modules/launch/idls.gni
deleted file mode 100644
index 0719af46060..00000000000
--- a/chromium/third_party/blink/renderer/modules/launch/idls.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "launch_params.idl",
- "launch_queue.idl",
-]
-
-modules_dependency_idl_files = [ "dom_window_launch_queue.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/launch/launch_queue.cc b/chromium/third_party/blink/renderer/modules/launch/launch_queue.cc
index 328e00c2f0d..4267e8c44bc 100644
--- a/chromium/third_party/blink/renderer/modules/launch/launch_queue.cc
+++ b/chromium/third_party/blink/renderer/modules/launch/launch_queue.cc
@@ -19,7 +19,7 @@ void LaunchQueue::Enqueue(LaunchParams* params) {
return;
}
- consumer_->Invoke(nullptr, params).Check();
+ consumer_->InvokeAndReportException(nullptr, params);
}
void LaunchQueue::setConsumer(V8LaunchConsumer* consumer) {
@@ -33,7 +33,7 @@ void LaunchQueue::setConsumer(V8LaunchConsumer* consumer) {
LaunchParams* params = unconsumed_launch_params_.at(0);
unconsumed_launch_params_.EraseAt(0);
- consumer_->Invoke(nullptr, params).Check();
+ consumer_->InvokeAndReportException(nullptr, params);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/launch/launch_queue.idl b/chromium/third_party/blink/renderer/modules/launch/launch_queue.idl
index f2210dae046..b78153df1cf 100644
--- a/chromium/third_party/blink/renderer/modules/launch/launch_queue.idl
+++ b/chromium/third_party/blink/renderer/modules/launch/launch_queue.idl
@@ -12,4 +12,4 @@
void setConsumer(LaunchConsumer consumer);
};
-callback LaunchConsumer = any (LaunchParams params);
+callback LaunchConsumer = void(LaunchParams params);
diff --git a/chromium/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc b/chromium/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc
index 372b3f1d76e..ce889b5df19 100644
--- a/chromium/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/modules/launch/dom_window_launch_queue.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
diff --git a/chromium/third_party/blink/renderer/modules/lock_screen/idls.gni b/chromium/third_party/blink/renderer/modules/lock_screen/idls.gni
deleted file mode 100644
index b9929ad6e2a..00000000000
--- a/chromium/third_party/blink/renderer/modules/lock_screen/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "lock_screen_data.idl" ]
-
-modules_dependency_idl_files = [ "dom_window_lock_screen.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/locks/idls.gni b/chromium/third_party/blink/renderer/modules/locks/idls.gni
deleted file mode 100644
index 7c94c5f9329..00000000000
--- a/chromium/third_party/blink/renderer/modules/locks/idls.gni
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "lock.idl",
- "lock_manager.idl",
-]
-
-modules_dictionary_idl_files = [
- "lock_info.idl",
- "lock_manager_snapshot.idl",
- "lock_options.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_locks.idl",
- "worker_navigator_locks.idl",
-]
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 9918fa33248..9cf7e30b391 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
@@ -9,7 +9,6 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/feature_observer/feature_observer.mojom-blink.h"
#include "third_party/blink/public/mojom/locks/lock_manager.mojom-blink-forward.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_string_sequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_lock_options.h"
#include "third_party/blink/renderer/modules/locks/lock.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/managed_device/idls.gni b/chromium/third_party/blink/renderer/modules/managed_device/idls.gni
deleted file mode 100644
index e07cab68f44..00000000000
--- a/chromium/third_party/blink/renderer/modules/managed_device/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "navigator_managed_data.idl" ]
-
-modules_dependency_idl_files = [ "navigator_managed.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed.idl b/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed.idl
index f2e424bf646..0be789c684d 100644
--- a/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed.idl
+++ b/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed.idl
@@ -4,7 +4,6 @@
//
[
ImplementedAs=NavigatorManagedData,
- RuntimeEnabled=ManagedInterface,
SecureContext
] partial interface Navigator {
[SameObject]
diff --git a/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc b/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc
index 605456ccb86..2df64ff2c51 100644
--- a/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc
+++ b/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc
@@ -123,6 +123,9 @@ ScriptPromise NavigatorManagedData::getManagedConfiguration(
pending_promises_.insert(resolver);
ScriptPromise promise = resolver->Promise();
+ if (!GetExecutionContext()) {
+ return promise;
+ }
GetManagedConfigurationService()->GetManagedConfiguration(
keys, WTF::Bind(&NavigatorManagedData::OnConfigurationReceived,
WrapWeakPersistent(this), WrapPersistent(resolver)));
@@ -134,6 +137,9 @@ ScriptPromise NavigatorManagedData::getDirectoryId(ScriptState* script_state) {
pending_promises_.insert(resolver);
ScriptPromise promise = resolver->Promise();
+ if (!GetExecutionContext()) {
+ return promise;
+ }
GetService()->GetDirectoryId(WTF::Bind(
&NavigatorManagedData::OnAttributeReceived, WrapWeakPersistent(this),
WrapPersistent(script_state), WrapPersistent(resolver)));
@@ -145,6 +151,9 @@ ScriptPromise NavigatorManagedData::getHostname(ScriptState* script_state) {
pending_promises_.insert(resolver);
ScriptPromise promise = resolver->Promise();
+ if (!GetExecutionContext()) {
+ return promise;
+ }
GetService()->GetHostname(WTF::Bind(
&NavigatorManagedData::OnAttributeReceived, WrapWeakPersistent(this),
WrapPersistent(script_state), WrapPersistent(resolver)));
@@ -156,6 +165,9 @@ ScriptPromise NavigatorManagedData::getSerialNumber(ScriptState* script_state) {
pending_promises_.insert(resolver);
ScriptPromise promise = resolver->Promise();
+ if (!GetExecutionContext()) {
+ return promise;
+ }
GetService()->GetSerialNumber(WTF::Bind(
&NavigatorManagedData::OnAttributeReceived, WrapWeakPersistent(this),
WrapPersistent(script_state), WrapPersistent(resolver)));
@@ -168,6 +180,9 @@ ScriptPromise NavigatorManagedData::getAnnotatedAssetId(
pending_promises_.insert(resolver);
ScriptPromise promise = resolver->Promise();
+ if (!GetExecutionContext()) {
+ return promise;
+ }
GetService()->GetAnnotatedAssetId(WTF::Bind(
&NavigatorManagedData::OnAttributeReceived, WrapWeakPersistent(this),
WrapPersistent(script_state), WrapPersistent(resolver)));
@@ -180,6 +195,9 @@ ScriptPromise NavigatorManagedData::getAnnotatedLocation(
pending_promises_.insert(resolver);
ScriptPromise promise = resolver->Promise();
+ if (!GetExecutionContext()) {
+ return promise;
+ }
GetService()->GetAnnotatedLocation(WTF::Bind(
&NavigatorManagedData::OnAttributeReceived, WrapWeakPersistent(this),
WrapPersistent(script_state), WrapPersistent(resolver)));
@@ -236,6 +254,10 @@ void NavigatorManagedData::OnConfigurationChanged() {
void NavigatorManagedData::AddedEventListener(
const AtomicString& event_type,
RegisteredEventListener& registered_listener) {
+ if (!GetExecutionContext()) {
+ return;
+ }
+
EventTargetWithInlineData::AddedEventListener(event_type,
registered_listener);
if (event_type == event_type_names::kManagedconfigurationchange) {
diff --git a/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.idl b/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.idl
index e62fb699114..aa3d1533268 100644
--- a/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.idl
+++ b/chromium/third_party/blink/renderer/modules/managed_device/navigator_managed_data.idl
@@ -5,7 +5,6 @@
[
ActiveScriptWrappable,
Exposed=Window,
- RuntimeEnabled=ManagedInterface,
SecureContext
] interface NavigatorManagedData : EventTarget {
// Managed Configuration API.
diff --git a/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn b/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn
index 357b88ec72c..1ada0e3eb08 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn
@@ -16,8 +16,6 @@ blink_modules_sources("manifest") {
"manifest_manager.h",
"manifest_parser.cc",
"manifest_parser.h",
- "manifest_type_converters.cc",
- "manifest_type_converters.h",
"manifest_uma_util.cc",
"manifest_uma_util.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/manifest/DIR_METADATA b/chromium/third_party/blink/renderer/modules/manifest/DIR_METADATA
new file mode 100644
index 00000000000..0ff3ed55bf6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Blink>AppManifest"
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/OWNERS b/chromium/third_party/blink/renderer/modules/manifest/OWNERS
index ea6a1d81eee..edf88ff9994 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/manifest/OWNERS
@@ -6,5 +6,3 @@ msw@chromium.org
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
-
-# Component: Blink>AppManifest
diff --git a/chromium/third_party/blink/renderer/modules/manifest/idls.gni b/chromium/third_party/blink/renderer/modules/manifest/idls.gni
deleted file mode 100644
index 21793946376..00000000000
--- a/chromium/third_party/blink/renderer/modules/manifest/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dictionary_idl_files = [ "image_resource.idl" ]
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
index 20c7b45cf2f..ba7ed28cfa1 100644
--- 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
@@ -5,6 +5,7 @@
#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 "mojo/public/cpp/bindings/type_converter.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.cc
index 9e887a4504c..7916b8d98fc 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.cc
@@ -60,10 +60,7 @@ void ManifestChangeNotifier::ReportManifestChange() {
EnsureManifestChangeObserver();
DCHECK(manifest_change_observer_.is_bound());
- if (manifest_url.IsNull())
- manifest_change_observer_->ManifestUrlChanged(absl::nullopt);
- else
- manifest_change_observer_->ManifestUrlChanged(manifest_url);
+ manifest_change_observer_->ManifestUrlChanged(manifest_url);
}
void ManifestChangeNotifier::EnsureManifestChangeObserver() {
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc
index e53002d8903..52923b35b94 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc
@@ -78,7 +78,7 @@ void ManifestFetcher::DidFinishLoading(uint64_t) {
data_.Clear();
}
-void ManifestFetcher::DidFail(const ResourceError& error) {
+void ManifestFetcher::DidFail(uint64_t, const ResourceError& error) {
if (!callback_)
return;
@@ -87,8 +87,8 @@ void ManifestFetcher::DidFail(const ResourceError& error) {
std::move(callback_).Run(response_, String());
}
-void ManifestFetcher::DidFailRedirectCheck() {
- DidFail(ResourceError::Failure(NullURL()));
+void ManifestFetcher::DidFailRedirectCheck(uint64_t identifier) {
+ DidFail(identifier, ResourceError::Failure(NullURL()));
}
void ManifestFetcher::Trace(Visitor* visitor) const {
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h b/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h
index f576fad06e9..d18e2dcd351 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h
@@ -48,8 +48,8 @@ class ManifestFetcher final : public GarbageCollected<ManifestFetcher>,
void DidReceiveResponse(uint64_t, const ResourceResponse&) override;
void DidReceiveData(const char*, unsigned) override;
void DidFinishLoading(uint64_t) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
+ void DidFail(uint64_t, const ResourceError&) override;
+ void DidFailRedirectCheck(uint64_t) override;
void Trace(Visitor* visitor) const override;
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc
index 2d080a6255f..91f16fa9dcd 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc
@@ -19,7 +19,6 @@
#include "third_party/blink/renderer/modules/manifest/manifest_change_notifier.h"
#include "third_party/blink/renderer/modules/manifest/manifest_fetcher.h"
#include "third_party/blink/renderer/modules/manifest/manifest_parser.h"
-#include "third_party/blink/renderer/modules/manifest/manifest_type_converters.h"
#include "third_party/blink/renderer/modules/manifest/manifest_uma_util.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -96,7 +95,7 @@ void ManifestManager::RequestManifestForTesting(
[](WebManifestManager::Callback callback, const KURL& manifest_url,
const mojom::blink::ManifestPtr& manifest,
const mojom::blink::ManifestDebugInfo* debug_info) {
- std::move(callback).Run(manifest_url, manifest.To<Manifest>());
+ std::move(callback).Run(manifest_url);
},
std::move(callback)));
}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h b/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h
index b6931bdd2ca..b1e52ab3b27 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h
@@ -8,7 +8,6 @@
#include "base/callback.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom-blink.h"
#include "third_party/blink/public/web/web_manifest_manager.h"
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc
index 902d334daaf..e2f7f8e33ed 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -124,6 +124,7 @@ void ManifestParser::Parse() {
manifest_->short_name = ParseShortName(root_object.get());
manifest_->description = ParseDescription(root_object.get());
manifest_->start_url = ParseStartURL(root_object.get());
+ manifest_->id = ParseId(root_object.get(), manifest_->start_url);
manifest_->scope = ParseScope(root_object.get(), manifest_->start_url);
manifest_->display = ParseDisplay(root_object.get());
manifest_->display_override = ParseDisplayOverride(root_object.get());
@@ -158,6 +159,13 @@ void ManifestParser::Parse() {
manifest_->shortcuts = ParseShortcuts(root_object.get());
manifest_->capture_links = ParseCaptureLinks(root_object.get());
+ if (base::FeatureList::IsEnabled(
+ blink::features::kWebAppEnableIsolatedStorage)) {
+ manifest_->isolated_storage = ParseIsolatedStorage(root_object.get());
+ }
+
+ manifest_->launch_handler = ParseLaunchHandler(root_object.get());
+
ManifestUmaUtil::ParseSucceeded(manifest_);
}
@@ -301,6 +309,50 @@ KURL ManifestParser::ParseURL(const JSONObject* object,
return KURL();
}
+template <typename Enum>
+Enum ManifestParser::ParseFirstValidEnum(const JSONObject* object,
+ const String& key,
+ Enum (*parse_enum)(const std::string&),
+ Enum invalid_value) {
+ const JSONValue* value = object->Get(key);
+ if (!value)
+ return invalid_value;
+
+ String string_value;
+ if (value->AsString(&string_value)) {
+ Enum enum_value = parse_enum(string_value.Utf8());
+ if (enum_value == invalid_value) {
+ AddErrorInfo(key + " value '" + string_value +
+ "' ignored, unknown value.");
+ }
+ return enum_value;
+ }
+
+ const JSONArray* list = JSONArray::Cast(value);
+ if (!list) {
+ AddErrorInfo("property '" + key +
+ "' ignored, type string or array of strings expected.");
+ return invalid_value;
+ }
+
+ for (wtf_size_t i = 0; i < list->size(); ++i) {
+ const JSONValue* item = list->at(i);
+ if (!item->AsString(&string_value)) {
+ AddErrorInfo(key + " value '" + item->ToJSONString() +
+ "' ignored, string expected.");
+ continue;
+ }
+
+ Enum enum_value = parse_enum(string_value.Utf8());
+ if (enum_value != invalid_value)
+ return enum_value;
+
+ AddErrorInfo(key + " value '" + string_value + "' ignored, unknown value.");
+ }
+
+ return invalid_value;
+}
+
String ManifestParser::ParseName(const JSONObject* object) {
absl::optional<String> name = ParseString(object, "name", Trim);
if (name.has_value()) {
@@ -326,6 +378,37 @@ String ManifestParser::ParseDescription(const JSONObject* object) {
return description.has_value() ? *description : String();
}
+String ManifestParser::ParseId(const JSONObject* object,
+ const KURL& start_url) {
+ if (!base::FeatureList::IsEnabled(blink::features::kWebAppEnableManifestId)) {
+ ManifestUmaUtil::ParseIdResult(
+ ManifestUmaUtil::ParseIdResultType::kFeatureDisabled);
+ return String();
+ }
+
+ if (!start_url.IsValid()) {
+ ManifestUmaUtil::ParseIdResult(
+ ManifestUmaUtil::ParseIdResultType::kInvalidStartUrl);
+ return String();
+ }
+ KURL start_url_origin = KURL(SecurityOrigin::Create(start_url)->ToString());
+
+ KURL id = ParseURL(object, "id", start_url_origin,
+ ParseURLRestrictions::kSameOriginOnly);
+ if (id.IsValid()) {
+ ManifestUmaUtil::ParseIdResult(
+ ManifestUmaUtil::ParseIdResultType::kSucceed);
+ } else {
+ // If id is not specified, sets to start_url
+ ManifestUmaUtil::ParseIdResult(
+ ManifestUmaUtil::ParseIdResultType::kDefaultToStartUrl);
+ id = start_url;
+ }
+ // TODO(https://crbug.com/1231765): rename the field to relative_id to reflect
+ // the actual value.
+ return id.GetString().Substring(id.PathStart() + 1);
+}
+
KURL ManifestParser::ParseStartURL(const JSONObject* object) {
return ParseURL(object, "start_url", manifest_url_,
ParseURLRestrictions::kSameOriginOnly);
@@ -409,6 +492,11 @@ Vector<mojom::blink::DisplayMode> ManifestParser::ParseDisplayOverride(
display_enum = mojom::blink::DisplayMode::kUndefined;
}
+ if (!RuntimeEnabledFeatures::WebAppTabStripEnabled(feature_context_) &&
+ display_enum == mojom::blink::DisplayMode::kTabbed) {
+ display_enum = mojom::blink::DisplayMode::kUndefined;
+ }
+
if (display_enum != mojom::blink::DisplayMode::kUndefined)
display_override.push_back(display_enum);
}
@@ -874,17 +962,17 @@ ManifestParser::ParseShareTarget(const JSONObject* object) {
Vector<mojom::blink::ManifestFileHandlerPtr> ManifestParser::ParseFileHandlers(
const JSONObject* object) {
- Vector<mojom::blink::ManifestFileHandlerPtr> result;
if (!object->Get("file_handlers"))
- return result;
+ return {};
JSONArray* entry_array = object->GetArray("file_handlers");
if (!entry_array) {
AddErrorInfo("property 'file_handlers' ignored, type array expected.");
- return result;
+ return {};
}
+ Vector<mojom::blink::ManifestFileHandlerPtr> result;
for (wtf_size_t i = 0; i < entry_array->size(); ++i) {
JSONObject* json_entry = JSONObject::Cast(entry_array->at(i));
if (!json_entry) {
@@ -915,6 +1003,12 @@ ManifestParser::ParseFileHandler(const JSONObject* file_handler) {
}
entry->name = ParseString(file_handler, "name", Trim).value_or("");
+ const bool feature_enabled =
+ base::FeatureList::IsEnabled(blink::features::kFileHandlingIcons) ||
+ RuntimeEnabledFeatures::FileHandlingIconsEnabled(feature_context_);
+ if (feature_enabled) {
+ entry->icons = ParseIcons(file_handler);
+ }
entry->accept = ParseFileHandlerAccept(file_handler->GetJSONObject("accept"));
if (entry->accept.IsEmpty()) {
@@ -1087,7 +1181,7 @@ ManifestParser::ParseProtocolHandler(const JSONObject* object) {
Vector<mojom::blink::ManifestUrlHandlerPtr> ManifestParser::ParseUrlHandlers(
const JSONObject* from) {
Vector<mojom::blink::ManifestUrlHandlerPtr> url_handlers;
- bool feature_enabled =
+ const bool feature_enabled =
base::FeatureList::IsEnabled(blink::features::kWebAppEnableUrlHandlers) ||
RuntimeEnabledFeatures::WebAppUrlHandlingEnabled(feature_context_);
if (!feature_enabled || !from->Get("url_handlers")) {
@@ -1126,7 +1220,8 @@ Vector<mojom::blink::ManifestUrlHandlerPtr> ManifestParser::ParseUrlHandlers(
absl::optional<mojom::blink::ManifestUrlHandlerPtr>
ManifestParser::ParseUrlHandler(const JSONObject* object) {
DCHECK(
- base::FeatureList::IsEnabled(blink::features::kWebAppEnableUrlHandlers));
+ base::FeatureList::IsEnabled(blink::features::kWebAppEnableUrlHandlers) ||
+ RuntimeEnabledFeatures::WebAppUrlHandlingEnabled(feature_context_));
if (!object->Get("origin")) {
AddErrorInfo(
"url_handlers entry ignored, required property 'origin' is missing.");
@@ -1324,53 +1419,56 @@ String ManifestParser::ParseGCMSenderID(const JSONObject* object) {
mojom::blink::CaptureLinks ManifestParser::ParseCaptureLinks(
const JSONObject* object) {
- // Parse if either the command line flag is passed (for about:flags) or the
- // runtime enabled feature is turned on (for origin trial).
- if (!base::FeatureList::IsEnabled(features::kWebAppEnableLinkCapturing) &&
- !RuntimeEnabledFeatures::WebAppLinkCapturingEnabled(feature_context_)) {
+ if (!RuntimeEnabledFeatures::WebAppLinkCapturingEnabled(feature_context_))
return mojom::blink::CaptureLinks::kUndefined;
- }
- String capture_links_string;
- if (object->GetString("capture_links", &capture_links_string)) {
- mojom::blink::CaptureLinks capture_links =
- CaptureLinksFromString(capture_links_string.Utf8());
- if (capture_links == mojom::blink::CaptureLinks::kUndefined) {
- AddErrorInfo("capture_links value '" + capture_links_string +
- "' ignored, unknown value.");
- }
- return capture_links;
+ return ParseFirstValidEnum<mojom::blink::CaptureLinks>(
+ object, "capture_links", &CaptureLinksFromString,
+ /*invalid_value=*/mojom::blink::CaptureLinks::kUndefined);
+}
+
+bool ManifestParser::ParseIsolatedStorage(const JSONObject* object) {
+ bool is_storage_isolated = ParseBoolean(object, "isolated_storage", false);
+ if (is_storage_isolated && manifest_->scope.GetPath() != "/") {
+ AddErrorInfo("Isolated storage is only supported with a scope of \"/\".");
+ return false;
}
+ return is_storage_isolated;
+}
- if (JSONArray* list = object->GetArray("capture_links")) {
- for (wtf_size_t i = 0; i < list->size(); ++i) {
- const JSONValue* item = list->at(i);
- if (!item->AsString(&capture_links_string)) {
- AddErrorInfo("capture_links value '" + item->ToJSONString() +
- "' ignored, string expected.");
- continue;
- }
+mojom::blink::ManifestLaunchHandlerPtr ManifestParser::ParseLaunchHandler(
+ const JSONObject* object) {
+ using RouteTo = mojom::blink::ManifestLaunchHandler::RouteTo;
+ using NavigateExistingClient =
+ mojom::blink::ManifestLaunchHandler::NavigateExistingClient;
- mojom::blink::CaptureLinks capture_links =
- CaptureLinksFromString(capture_links_string.Utf8());
- if (capture_links != mojom::blink::CaptureLinks::kUndefined)
- return capture_links;
+ if (!RuntimeEnabledFeatures::WebAppLaunchHandlerEnabled(feature_context_))
+ return nullptr;
- AddErrorInfo("capture_links value '" + capture_links_string +
- "' ignored, unknown value.");
- }
- return mojom::blink::CaptureLinks::kUndefined;
- }
+ const JSONValue* launch_handler_value = object->Get("launch_handler");
+ if (!launch_handler_value)
+ return nullptr;
- if (object->Get("capture_links")) {
- // There was something defined that wasn't handled already, it must be the
- // wrong type.
- AddErrorInfo(
- "property 'capture_links' ignored, type string or array of strings "
- "expected.");
+ const JSONObject* launch_handler_object =
+ JSONObject::Cast(launch_handler_value);
+ if (!launch_handler_object) {
+ AddErrorInfo("launch_handler value ignored, object expected.");
+ return nullptr;
}
- return mojom::blink::CaptureLinks::kUndefined;
+ RouteTo route_to = ParseFirstValidEnum<absl::optional<RouteTo>>(
+ launch_handler_object, "route_to", &RouteToFromString,
+ /*invalid_value=*/absl::nullopt)
+ .value_or(RouteTo::kAuto);
+
+ NavigateExistingClient navigate_existing_client =
+ ParseFirstValidEnum<absl::optional<NavigateExistingClient>>(
+ launch_handler_object, "navigate_existing_client",
+ &NavigateExistingClientFromString, /*invalid_value=*/absl::nullopt)
+ .value_or(NavigateExistingClient::kAlways);
+
+ return mojom::blink::ManifestLaunchHandler::New(route_to,
+ navigate_existing_client);
}
void ManifestParser::AddErrorInfo(const String& error_msg,
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h
index 8ddb9047b86..e6d107129d2 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
@@ -105,6 +104,20 @@ class MODULES_EXPORT ManifestParser {
const KURL& base_url,
ParseURLRestrictions origin_restriction);
+ // Helper function to parse "enum" fields that accept a single value or a
+ // list of values to allow sites to be backwards compatible with browsers that
+ // don't support the latest spec.
+ // Example:
+ // - Spec specifies valid field values are A, B and C.
+ // - Browser supports only A and B.
+ // - Site specifies "field": ["C", "B"].
+ // - Browser will fail to parse C and fallback to B.
+ template <typename Enum>
+ Enum ParseFirstValidEnum(const JSONObject* object,
+ const String& key,
+ Enum (*parse_enum)(const std::string&),
+ Enum invalid_value);
+
// Parses the 'name' field of the manifest, as defined in:
// https://w3c.github.io/manifest/#dfn-steps-for-processing-the-name-member
// Returns the parsed string if any, a null string if the parsing failed.
@@ -120,6 +133,9 @@ class MODULES_EXPORT ManifestParser {
// Returns the parsed string if any, a null string if the parsing failed.
String ParseDescription(const JSONObject* object);
+ // Parses the 'id' field of the manifest.
+ String ParseId(const JSONObject* object, const KURL& start_url);
+
// Parses the 'scope' field of the manifest, as defined in:
// https://w3c.github.io/manifest/#scope-member. Returns the parsed KURL if
// any, or start URL (falling back to document URL) without filename, path,
@@ -400,6 +416,18 @@ class MODULES_EXPORT ManifestParser {
// https://github.com/WICG/sw-launch/blob/master/declarative_link_capturing.md#proposal
mojom::blink::CaptureLinks ParseCaptureLinks(const JSONObject* object);
+ // Parses the 'isolated_storage' field of the manifest.
+ // This marks whether the application should be loaded in a dedicated storage
+ // partition.
+ // Returns true iff the field could be parsed as the boolean true.
+ bool ParseIsolatedStorage(const JSONObject* object);
+
+ // Parses the 'launch_handler' field of the manifest as defined in:
+ // https://github.com/WICG/sw-launch/blob/main/launch_handler.md
+ // Returns default values if parsing fails.
+ mojom::blink::ManifestLaunchHandlerPtr ParseLaunchHandler(
+ const JSONObject* object);
+
void AddErrorInfo(const String& error_msg,
bool critical = false,
int error_line = 0,
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
index 7efa0007a5c..49b9cdfe40e 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -68,7 +68,7 @@ class ManifestParserTest : public testing::Test {
TEST_F(ManifestParserTest, CrashTest) {
// Passing temporary variables should not crash.
- const String json = "{\"start_url\": \"/\"}";
+ const String json = R"({"start_url": "/"})";
KURL url("http://example.com");
ManifestParser parser(json, url, url, /*feature_context=*/nullptr);
@@ -114,12 +114,28 @@ TEST_F(ManifestParserTest, ValidNoContentParses) {
ASSERT_TRUE(manifest->shortcuts.IsEmpty());
}
+TEST_F(ManifestParserTest, UnrecognizedFieldsIgnored) {
+ auto& manifest = ParseManifest(
+ R"({
+ "unrecognizable_manifest_field": ["foo"],
+ "name": "bar"
+ })");
+
+ // Unrecognized Manifest fields are not a parsing error.
+ EXPECT_EQ(0u, GetErrorCount());
+
+ // Check that subsequent fields parsed.
+ ASSERT_FALSE(IsManifestEmpty(manifest));
+ ASSERT_EQ(manifest->name, "bar");
+ ASSERT_EQ(DefaultDocumentUrl().BaseAsString(), manifest->scope.GetString());
+}
+
TEST_F(ManifestParserTest, MultipleErrorsReporting) {
auto& manifest = ParseManifest(
- "{ \"name\": 42, \"short_name\": 4,"
- "\"orientation\": {}, \"display\": \"foo\","
- "\"start_url\": null, \"icons\": {}, \"theme_color\": 42,"
- "\"background_color\": 42, \"shortcuts\": {} }");
+ R"({ "name": 42, "short_name": 4, "id": 12,
+ "orientation": {}, "display": "foo",
+ "start_url": null, "icons": {}, "theme_color": 42,
+ "background_color": 42, "shortcuts": {} })");
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(9u, GetErrorCount());
@@ -142,7 +158,7 @@ TEST_F(ManifestParserTest, MultipleErrorsReporting) {
TEST_F(ManifestParserTest, NameParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"name\": \"foo\" }");
+ auto& manifest = ParseManifest(R"({ "name": "foo" })");
ASSERT_EQ(manifest->name, "foo");
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -150,14 +166,14 @@ TEST_F(ManifestParserTest, NameParseRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"name\": \" foo \" }");
+ auto& manifest = ParseManifest(R"({ "name": " foo " })");
ASSERT_EQ(manifest->name, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"name\": {} }");
+ auto& manifest = ParseManifest(R"({ "name": {} })");
ASSERT_TRUE(manifest->name.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' ignored, type string expected.", errors()[0]);
@@ -165,7 +181,7 @@ TEST_F(ManifestParserTest, NameParseRules) {
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"name\": 42 }");
+ auto& manifest = ParseManifest(R"({ "name": 42 })");
ASSERT_TRUE(manifest->name.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' ignored, type string expected.", errors()[0]);
@@ -219,7 +235,7 @@ TEST_F(ManifestParserTest, DescriptionParseRules) {
TEST_F(ManifestParserTest, ShortNameParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"short_name\": \"foo\" }");
+ auto& manifest = ParseManifest(R"({ "short_name": "foo" })");
ASSERT_EQ(manifest->short_name, "foo");
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -227,14 +243,14 @@ TEST_F(ManifestParserTest, ShortNameParseRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"short_name\": \" foo \" }");
+ auto& manifest = ParseManifest(R"({ "short_name": " foo " })");
ASSERT_EQ(manifest->short_name, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"short_name\": {} }");
+ auto& manifest = ParseManifest(R"({ "short_name": {} })");
ASSERT_TRUE(manifest->short_name.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'short_name' ignored, type string expected.",
@@ -243,7 +259,7 @@ TEST_F(ManifestParserTest, ShortNameParseRules) {
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"short_name\": 42 }");
+ auto& manifest = ParseManifest(R"({ "short_name": 42 })");
ASSERT_TRUE(manifest->short_name.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'short_name' ignored, type string expected.",
@@ -259,10 +275,78 @@ TEST_F(ManifestParserTest, ShortNameParseRules) {
}
}
+TEST_F(ManifestParserTest, IdParseRules) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(blink::features::kWebAppEnableManifestId);
+ // Empty manifest.
+ {
+ auto& manifest = ParseManifest("{ }");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ(String(), manifest->id);
+ }
+ // Does not contain id field.
+ {
+ auto& manifest = ParseManifest(R"({"start_url": "/start?query=a" })");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("start?query=a", manifest->id);
+ }
+ // Invalid type.
+ {
+ auto& manifest =
+ ParseManifest("{\"start_url\": \"/start?query=a\", \"id\": 1}");
+ ASSERT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("start?query=a", manifest->id);
+ }
+ // Empty string.
+ {
+ auto& manifest =
+ ParseManifest(R"({ "start_url": "/start?query=a", "id": "" })");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("", manifest->id);
+ }
+ // Full url.
+ {
+ auto& manifest = ParseManifest(
+ "{ \"start_url\": \"/start?query=a\", \"id\": \"http://foo.com/foo\" "
+ "}");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("foo", manifest->id);
+ }
+ // Full url with different origin.
+ {
+ auto& manifest = ParseManifest(
+ "{ \"start_url\": \"/start?query=a\", \"id\": "
+ "\"http://another.com/foo\" }");
+ ASSERT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("start?query=a", manifest->id);
+ }
+ // Relative path
+ {
+ auto& manifest =
+ ParseManifest("{ \"start_url\": \"/start?query=a\", \"id\": \".\" }");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("", manifest->id);
+ }
+ // Absolute path
+ {
+ auto& manifest =
+ ParseManifest("{ \"start_url\": \"/start?query=a\", \"id\": \"/\" }");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("", manifest->id);
+ }
+ // Smoke test.
+ {
+ auto& manifest =
+ ParseManifest(R"({ "start_url": "/start?query=a", "id": "foo" })");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("foo", manifest->id);
+ }
+}
+
TEST_F(ManifestParserTest, StartURLParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"start_url\": \"land.html\" }");
+ auto& manifest = ParseManifest(R"({ "start_url": "land.html" })");
ASSERT_EQ(manifest->start_url, KURL(DefaultDocumentUrl(), "land.html"));
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -270,15 +354,16 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Whitespaces.
{
- auto& manifest = ParseManifest("{ \"start_url\": \" land.html \" }");
+ auto& manifest = ParseManifest(R"({ "start_url": " land.html " })");
ASSERT_EQ(manifest->start_url, KURL(DefaultDocumentUrl(), "land.html"));
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if property isn't a string.
{
- auto& manifest = ParseManifest("{ \"start_url\": {} }");
+ auto& manifest = ParseManifest(R"({ "start_url": {} })");
ASSERT_TRUE(manifest->start_url.IsEmpty());
+ ASSERT_EQ(String(), manifest->id);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'start_url' ignored, type string expected.",
errors()[0]);
@@ -286,7 +371,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Don't parse if property isn't a string.
{
- auto& manifest = ParseManifest("{ \"start_url\": 42 }");
+ auto& manifest = ParseManifest(R"({ "start_url": 42 })");
ASSERT_TRUE(manifest->start_url.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'start_url' ignored, type string expected.",
@@ -296,7 +381,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Don't parse if property isn't a valid URL.
{
auto& manifest =
- ParseManifest("{ \"start_url\": \"http://www.google.ca:a\" }");
+ ParseManifest(R"({ "start_url": "http://www.google.ca:a" })");
ASSERT_TRUE(manifest->start_url.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'start_url' ignored, URL is invalid.", errors()[0]);
@@ -305,7 +390,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Absolute start_url, same origin with document.
{
auto& manifest =
- ParseManifestWithURLs("{ \"start_url\": \"http://foo.com/land.html\" }",
+ ParseManifestWithURLs(R"({ "start_url": "http://foo.com/land.html" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->start_url.GetString(), "http://foo.com/land.html");
@@ -315,7 +400,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Absolute start_url, cross origin with document.
{
auto& manifest =
- ParseManifestWithURLs("{ \"start_url\": \"http://bar.com/land.html\" }",
+ ParseManifestWithURLs(R"({ "start_url": "http://bar.com/land.html" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_TRUE(manifest->start_url.IsEmpty());
@@ -329,7 +414,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Resolving has to happen based on the manifest_url.
{
auto& manifest =
- ParseManifestWithURLs("{ \"start_url\": \"land.html\" }",
+ ParseManifestWithURLs(R"({ "start_url": "land.html" })",
KURL("http://foo.com/landing/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->start_url.GetString(),
@@ -342,7 +427,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Smoke test.
{
auto& manifest = ParseManifest(
- "{ \"scope\": \"land\", \"start_url\": \"land/landing.html\" }");
+ R"({ "scope": "land", "start_url": "land/landing.html" })");
ASSERT_EQ(manifest->scope, KURL(DefaultDocumentUrl(), "land"));
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -351,14 +436,14 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Whitespaces.
{
auto& manifest = ParseManifest(
- "{ \"scope\": \" land \", \"start_url\": \"land/landing.html\" }");
+ R"({ "scope": " land ", "start_url": "land/landing.html" })");
ASSERT_EQ(manifest->scope, KURL(DefaultDocumentUrl(), "land"));
EXPECT_EQ(0u, GetErrorCount());
}
// Return the default value if the property isn't a string.
{
- auto& manifest = ParseManifest("{ \"scope\": {} }");
+ auto& manifest = ParseManifest(R"({ "scope": {} })");
ASSERT_EQ(manifest->scope.GetString(), DefaultDocumentUrl().BaseAsString());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
@@ -367,8 +452,8 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Return the default value if property isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"scope\": 42, "
- "\"start_url\": \"http://foo.com/land/landing.html\" }");
+ R"({ "scope": 42,
+ "start_url": "http://foo.com/land/landing.html" })");
ASSERT_EQ(manifest->scope, KURL(DefaultDocumentUrl(), "land/"));
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
@@ -377,8 +462,8 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Absolute scope, start URL is in scope.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://foo.com/land/landing.html\" }",
+ R"({ "scope": "http://foo.com/land",
+ "start_url": "http://foo.com/land/landing.html" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->scope.GetString(), "http://foo.com/land");
@@ -388,8 +473,8 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Absolute scope, start URL is not in scope.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://foo.com/index.html\" }",
+ R"({ "scope": "http://foo.com/land",
+ "start_url": "http://foo.com/index.html" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->scope.GetString(), DefaultDocumentUrl().BaseAsString());
@@ -403,8 +488,8 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Absolute scope, start URL has different origin than scope URL.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://bar.com/land/landing.html\" }",
+ R"({ "scope": "http://foo.com/land",
+ "start_url": "http://bar.com/land/landing.html" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->scope.GetString(), DefaultDocumentUrl().BaseAsString());
@@ -422,8 +507,8 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
{
KURL document_url("http://bar.com/index.html");
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://foo.com/land/landing.html\" }",
+ R"({ "scope": "http://foo.com/land",
+ "start_url": "http://foo.com/land/landing.html" })",
KURL("http://foo.com/manifest.json"), document_url);
ASSERT_EQ(manifest->scope.GetString(), document_url.BaseAsString());
ASSERT_EQ(2u, GetErrorCount());
@@ -439,7 +524,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// No start URL. Document URL is in a subdirectory of scope.
{
auto& manifest =
- ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
+ ParseManifestWithURLs(R"({ "scope": "http://foo.com/land" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/land/site/index.html"));
ASSERT_EQ(manifest->scope.GetString(), "http://foo.com/land");
@@ -450,7 +535,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
{
KURL document_url("http://foo.com/index.html");
auto& manifest =
- ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
+ ParseManifestWithURLs(R"({ "scope": "http://foo.com/land" })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->scope.GetString(), document_url.BaseAsString());
@@ -464,7 +549,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Resolving has to happen based on the manifest_url.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"treasure\" }", KURL("http://foo.com/map/manifest.json"),
+ R"({ "scope": "treasure" })", KURL("http://foo.com/map/manifest.json"),
KURL("http://foo.com/map/treasure/island/index.html"));
ASSERT_EQ(manifest->scope.GetString(), "http://foo.com/map/treasure");
EXPECT_EQ(0u, GetErrorCount());
@@ -473,7 +558,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Scope is parent directory.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"..\" }", KURL("http://foo.com/map/manifest.json"),
+ R"({ "scope": ".." })", KURL("http://foo.com/map/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->scope.GetString(), "http://foo.com/");
EXPECT_EQ(0u, GetErrorCount());
@@ -482,7 +567,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Scope tries to go up past domain.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"../..\" }", KURL("http://foo.com/map/manifest.json"),
+ R"({ "scope": "../.." })", KURL("http://foo.com/map/manifest.json"),
KURL("http://foo.com/index.html"));
ASSERT_EQ(manifest->scope.GetString(), "http://foo.com/");
EXPECT_EQ(0u, GetErrorCount());
@@ -490,14 +575,14 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Scope defaults to start_url with the filename, query, and fragment removed.
{
- auto& manifest = ParseManifest("{ \"start_url\": \"land/landing.html\" }");
+ auto& manifest = ParseManifest(R"({ "start_url": "land/landing.html" })");
ASSERT_EQ(manifest->scope, KURL(DefaultDocumentUrl(), "land/"));
EXPECT_EQ(0u, GetErrorCount());
}
{
auto& manifest =
- ParseManifest("{ \"start_url\": \"land/land/landing.html\" }");
+ ParseManifest(R"({ "start_url": "land/land/landing.html" })");
ASSERT_EQ(manifest->scope, KURL(DefaultDocumentUrl(), "land/land/"));
EXPECT_EQ(0u, GetErrorCount());
}
@@ -513,7 +598,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
TEST_F(ManifestParserTest, DisplayParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"display\": \"browser\" }");
+ auto& manifest = ParseManifest(R"({ "display": "browser" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -521,14 +606,14 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"display\": \" browser \" }");
+ auto& manifest = ParseManifest(R"({ "display": " browser " })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"display\": {} }");
+ auto& manifest = ParseManifest(R"({ "display": {} })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -539,7 +624,7 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"display\": 42 }");
+ auto& manifest = ParseManifest(R"({ "display": 42 })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -550,7 +635,7 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Parse fails if string isn't known.
{
- auto& manifest = ParseManifest("{ \"display\": \"browser_something\" }");
+ auto& manifest = ParseManifest(R"({ "display": "browser_something" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("unknown 'display' value ignored.", errors()[0]);
@@ -558,43 +643,44 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Accept 'fullscreen'.
{
- auto& manifest = ParseManifest("{ \"display\": \"fullscreen\" }");
+ auto& manifest = ParseManifest(R"({ "display": "fullscreen" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kFullscreen);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'standalone'.
{
- auto& manifest = ParseManifest("{ \"display\": \"standalone\" }");
+ auto& manifest = ParseManifest(R"({ "display": "standalone" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kStandalone);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'minimal-ui'.
{
- auto& manifest = ParseManifest("{ \"display\": \"minimal-ui\" }");
+ auto& manifest = ParseManifest(R"({ "display": "minimal-ui" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kMinimalUi);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'browser'.
{
- auto& manifest = ParseManifest("{ \"display\": \"browser\" }");
+ auto& manifest = ParseManifest(R"({ "display": "browser" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
// Case insensitive.
{
- auto& manifest = ParseManifest("{ \"display\": \"BROWSER\" }");
+ auto& manifest = ParseManifest(R"({ "display": "BROWSER" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
// Parsing fails for 'window-controls-overlay' when WCO flag is disabled.
{
+ ScopedWebAppWindowControlsOverlayForTest window_controls_overlay(false);
auto& manifest =
- ParseManifest("{ \"display\": \"window-controls-overlay\" }");
+ ParseManifest(R"({ "display": "window-controls-overlay" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("inapplicable 'display' value ignored.", errors()[0]);
@@ -604,7 +690,25 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
{
ScopedWebAppWindowControlsOverlayForTest window_controls_overlay(true);
auto& manifest =
- ParseManifest("{ \"display\": \"window-controls-overlay\" }");
+ ParseManifest(R"({ "display": "window-controls-overlay" })");
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("inapplicable 'display' value ignored.", errors()[0]);
+ }
+
+ // Parsing fails for 'tabbed' when flag is disabled.
+ {
+ ScopedWebAppTabStripForTest tabbed(false);
+ auto& manifest = ParseManifest(R"({ "display": "tabbed" })");
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("inapplicable 'display' value ignored.", errors()[0]);
+ }
+
+ // Parsing fails for 'tabbed' when flag is enabled.
+ {
+ ScopedWebAppTabStripForTest tabbed(true);
+ auto& manifest = ParseManifest(R"({ "display": "tabbed" })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("inapplicable 'display' value ignored.", errors()[0]);
@@ -615,14 +719,14 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Smoke test: if no display_override, no value.
{
- auto& manifest = ParseManifest("{ \"display_override\": [] }");
+ auto& manifest = ParseManifest(R"({ "display_override": [] })");
EXPECT_TRUE(manifest->display_override.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Smoke test: if not array, value will be ignored
{
- auto& manifest = ParseManifest("{ \"display_override\": 23 }");
+ auto& manifest = ParseManifest(R"({ "display_override": 23 })");
EXPECT_TRUE(manifest->display_override.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'display_override' ignored, type array expected.",
@@ -631,21 +735,21 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Smoke test: if array value is not a string, it will be ignored
{
- auto& manifest = ParseManifest("{ \"display_override\": [ 23 ] }");
+ auto& manifest = ParseManifest(R"({ "display_override": [ 23 ] })");
EXPECT_TRUE(manifest->display_override.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Smoke test: if array value is not not recognized, it will be ignored
{
- auto& manifest = ParseManifest("{ \"display_override\": [ \"test\" ] }");
+ auto& manifest = ParseManifest(R"({ "display_override": [ "test" ] })");
EXPECT_TRUE(manifest->display_override.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Case insensitive
{
- auto& manifest = ParseManifest("{ \"display_override\": [ \"BROWSER\" ] }");
+ auto& manifest = ParseManifest(R"({ "display_override": [ "BROWSER" ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kBrowser);
@@ -656,7 +760,7 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Trim whitespace
{
auto& manifest =
- ParseManifest("{ \"display_override\": [ \" browser \" ] }");
+ ParseManifest(R"({ "display_override": [ " browser " ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kBrowser);
@@ -666,7 +770,7 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Accept 'browser'
{
- auto& manifest = ParseManifest("{ \"display_override\": [ \"browser\" ] }");
+ auto& manifest = ParseManifest(R"({ "display_override": [ "browser" ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kBrowser);
@@ -676,8 +780,8 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Accept 'browser', 'minimal-ui'
{
- auto& manifest = ParseManifest(
- "{ \"display_override\": [ \"browser\", \"minimal-ui\" ] }");
+ auto& manifest =
+ ParseManifest(R"({ "display_override": [ "browser", "minimal-ui" ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kBrowser);
@@ -691,8 +795,8 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Accept 'browser', 'minimal-ui'
{
auto& manifest = ParseManifest(
- "{ \"display_override\": [ 3, \"browser\", \"invalid-display\", "
- "\"minimal-ui\" ] }");
+ R"({ "display_override": [ 3, "browser", "invalid-display",
+ "minimal-ui" ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kBrowser);
@@ -707,8 +811,8 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Accept 'browser', 'minimal-ui', 'standalone'
{
auto& manifest = ParseManifest(
- "{ \"display\": \"standalone\", \"display_override\": [ \"browser\", "
- "\"minimal-ui\", \"standalone\" ] }");
+ R"({ "display": "standalone", "display_override": [ "browser",
+ "minimal-ui", "standalone" ] })");
EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kStandalone);
EXPECT_EQ(0u, GetErrorCount());
EXPECT_FALSE(manifest->display_override.IsEmpty());
@@ -724,9 +828,9 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// validate duplicate entries.
// Accept 'browser', 'minimal-ui', 'browser'
{
- auto& manifest = ParseManifest(
- "{ \"display_override\": [ \"browser\", \"minimal-ui\", "
- "\"browser\" ] }");
+ auto& manifest =
+ ParseManifest(R"({ "display_override": [ "browser", "minimal-ui",
+ "browser" ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kBrowser);
@@ -740,8 +844,9 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
// Reject 'window-controls-overlay' when WCO flag is disabled.
{
+ ScopedWebAppWindowControlsOverlayForTest window_controls_overlay(false);
auto& manifest = ParseManifest(
- "{ \"display_override\": [ \"window-controls-overlay\" ] }");
+ R"({ "display_override": [ "window-controls-overlay" ] })");
EXPECT_TRUE(manifest->display_override.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
@@ -750,19 +855,38 @@ TEST_F(ManifestParserTest, DisplayOverrideParseRules) {
{
ScopedWebAppWindowControlsOverlayForTest window_controls_overlay(true);
auto& manifest = ParseManifest(
- "{ \"display_override\": [ \"window-controls-overlay\" ] }");
+ R"({ "display_override": [ "window-controls-overlay" ] })");
EXPECT_FALSE(manifest->display_override.IsEmpty());
EXPECT_EQ(manifest->display_override[0],
blink::mojom::DisplayMode::kWindowControlsOverlay);
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
}
+
+ // Ignore 'tabbed' when flag is disabled.
+ {
+ ScopedWebAppTabStripForTest tabbed(false);
+ auto& manifest = ParseManifest(R"({ "display_override": [ "tabbed" ] })");
+ EXPECT_TRUE(manifest->display_override.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Accept 'tabbed' when flag is enabled.
+ {
+ ScopedWebAppTabStripForTest tabbed(true);
+ auto& manifest = ParseManifest(R"({ "display_override": [ "tabbed" ] })");
+ EXPECT_FALSE(manifest->display_override.IsEmpty());
+ EXPECT_EQ(manifest->display_override[0],
+ blink::mojom::DisplayMode::kTabbed);
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_EQ(0u, GetErrorCount());
+ }
}
TEST_F(ManifestParserTest, OrientationParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "natural" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::NATURAL);
EXPECT_FALSE(IsManifestEmpty(manifest));
@@ -771,7 +895,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "natural" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::NATURAL);
EXPECT_EQ(0u, GetErrorCount());
@@ -779,7 +903,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"orientation\": {} }");
+ auto& manifest = ParseManifest(R"({ "orientation": {} })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::DEFAULT);
EXPECT_EQ(1u, GetErrorCount());
@@ -789,7 +913,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Don't parse if name isn't a string.
{
- auto& manifest = ParseManifest("{ \"orientation\": 42 }");
+ auto& manifest = ParseManifest(R"({ "orientation": 42 })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::DEFAULT);
EXPECT_EQ(1u, GetErrorCount());
@@ -799,7 +923,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Parse fails if string isn't known.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"naturalish\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "naturalish" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::DEFAULT);
EXPECT_EQ(1u, GetErrorCount());
@@ -808,7 +932,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'any'.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"any\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "any" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::ANY);
EXPECT_EQ(0u, GetErrorCount());
@@ -816,7 +940,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'natural'.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "natural" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::NATURAL);
EXPECT_EQ(0u, GetErrorCount());
@@ -824,7 +948,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'landscape'.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"landscape\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "landscape" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::LANDSCAPE);
EXPECT_EQ(0u, GetErrorCount());
@@ -832,8 +956,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'landscape-primary'.
{
- auto& manifest =
- ParseManifest("{ \"orientation\": \"landscape-primary\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "landscape-primary" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::LANDSCAPE_PRIMARY);
EXPECT_EQ(0u, GetErrorCount());
@@ -842,7 +965,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'landscape-secondary'.
{
auto& manifest =
- ParseManifest("{ \"orientation\": \"landscape-secondary\" }");
+ ParseManifest(R"({ "orientation": "landscape-secondary" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::LANDSCAPE_SECONDARY);
EXPECT_EQ(0u, GetErrorCount());
@@ -850,7 +973,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'portrait'.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"portrait\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "portrait" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::PORTRAIT);
EXPECT_EQ(0u, GetErrorCount());
@@ -858,7 +981,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'portrait-primary'.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"portrait-primary\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "portrait-primary" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::PORTRAIT_PRIMARY);
EXPECT_EQ(0u, GetErrorCount());
@@ -867,7 +990,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Accept 'portrait-secondary'.
{
auto& manifest =
- ParseManifest("{ \"orientation\": \"portrait-secondary\" }");
+ ParseManifest(R"({ "orientation": "portrait-secondary" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::PORTRAIT_SECONDARY);
EXPECT_EQ(0u, GetErrorCount());
@@ -875,7 +998,7 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
// Case insensitive.
{
- auto& manifest = ParseManifest("{ \"orientation\": \"LANDSCAPE\" }");
+ auto& manifest = ParseManifest(R"({ "orientation": "LANDSCAPE" })");
EXPECT_EQ(manifest->orientation,
device::mojom::ScreenOrientationLockType::LANDSCAPE);
EXPECT_EQ(0u, GetErrorCount());
@@ -885,28 +1008,28 @@ TEST_F(ManifestParserTest, OrientationParseRules) {
TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: if no icon, no value.
{
- auto& manifest = ParseManifest("{ \"icons\": [] }");
+ auto& manifest = ParseManifest(R"({ "icons": [] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Smoke test: if empty icon, no value.
{
- auto& manifest = ParseManifest("{ \"icons\": [ {} ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {} ] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Smoke test: icon with invalid src, no value.
{
- auto& manifest = ParseManifest("{ \"icons\": [ { \"icons\": [] } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ { "icons": [] } ] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Smoke test: if icon with empty src, it will be present in the list.
{
- auto& manifest = ParseManifest("{ \"icons\": [ { \"src\": \"\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ { "src": "" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -918,7 +1041,7 @@ TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: if one icons with valid src, it will be present in the list.
{
- auto& manifest = ParseManifest("{ \"icons\": [{ \"src\": \"foo.jpg\" }] }");
+ auto& manifest = ParseManifest(R"({ "icons": [{ "src": "foo.jpg" }] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -981,8 +1104,7 @@ TEST_F(ManifestParserTest, ScreenshotsParseRules) {
TEST_F(ManifestParserTest, IconSrcParseRules) {
// Smoke test.
{
- auto& manifest =
- ParseManifest("{ \"icons\": [ {\"src\": \"foo.png\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "foo.png" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->src, KURL(DefaultDocumentUrl(), "foo.png"));
EXPECT_EQ(0u, GetErrorCount());
@@ -991,7 +1113,7 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Whitespaces.
{
auto& manifest =
- ParseManifest("{ \"icons\": [ {\"src\": \" foo.png \" } ] }");
+ ParseManifest(R"({ "icons": [ {"src": " foo.png " } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->src, KURL(DefaultDocumentUrl(), "foo.png"));
EXPECT_EQ(0u, GetErrorCount());
@@ -999,7 +1121,7 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Don't parse if property isn't a string.
{
- auto& manifest = ParseManifest("{ \"icons\": [ {\"src\": {} } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": {} } ] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'src' ignored, type string expected.", errors()[0]);
@@ -1007,7 +1129,7 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Don't parse if property isn't a string.
{
- auto& manifest = ParseManifest("{ \"icons\": [ {\"src\": 42 } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": 42 } ] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'src' ignored, type string expected.", errors()[0]);
@@ -1016,7 +1138,7 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Resolving has to happen based on the document_url.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"icons\": [ {\"src\": \"icons/foo.png\" } ] }",
+ R"({ "icons": [ {"src": "icons/foo.png" } ] })",
KURL("http://foo.com/landing/index.html"), DefaultManifestUrl());
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->src.GetString(),
@@ -1029,7 +1151,7 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
// Smoke test.
{
auto& manifest =
- ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": \"foo\" } ] }");
+ ParseManifest(R"({ "icons": [ {"src": "", "type": "foo" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->type, "foo");
EXPECT_EQ(0u, GetErrorCount());
@@ -1037,9 +1159,8 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- " \"type\": \" foo \" } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "icons": [ {"src": "", "type": " foo " } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->type, "foo");
EXPECT_EQ(0u, GetErrorCount());
@@ -1048,7 +1169,7 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
// Don't parse if property isn't a string.
{
auto& manifest =
- ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": {} } ] }");
+ ParseManifest(R"({ "icons": [ {"src": "", "type": {} } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_TRUE(manifest->icons[0]->type.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
@@ -1058,7 +1179,7 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
// Don't parse if property isn't a string.
{
auto& manifest =
- ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": 42 } ] }");
+ ParseManifest(R"({ "icons": [ {"src": "", "type": 42 } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_TRUE(manifest->icons[0]->type.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
@@ -1069,9 +1190,8 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
TEST_F(ManifestParserTest, IconSizesParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"42x42\" } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "icons": [ {"src": "", "sizes": "42x42" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -1079,9 +1199,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \" 42x42 \" } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "icons": [ {"src": "", "sizes": " 42x42 " } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -1089,9 +1208,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Ignore sizes if property isn't a string.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": {} } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "icons": [ {"src": "", "sizes": {} } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -1100,9 +1218,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Ignore sizes if property isn't a string.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": 42 } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "icons": [ {"src": "", "sizes": 42 } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -1112,8 +1229,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Smoke test: value correctly parsed.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"42x42 48x48\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "42x42 48x48" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1125,8 +1241,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// <WIDTH>'x'<HEIGHT> and <WIDTH>'X'<HEIGHT> are equivalent.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"42X42 48X48\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "42X42 48X48" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1138,8 +1253,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Twice the same value is parsed twice.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"42X42 42x42\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "42X42 42x42" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1151,8 +1265,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Width or height can't start with 0.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"004X007 042x00\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "004X007 042x00" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -1162,8 +1275,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Width and height MUST contain digits.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"e4X1.0 55ax1e10\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "e4X1.0 55ax1e10" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -1173,8 +1285,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// 'any' is correctly parsed and transformed to gfx::Size(0,0).
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"any AnY ANY aNy\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "any AnY ANY aNy" } ] })");
gfx::Size any = gfx::Size(0, 0);
EXPECT_FALSE(manifest->icons.IsEmpty());
@@ -1190,8 +1301,7 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Some invalid width/height combinations.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"sizes\": \"x 40xx 1x2x3 x42 42xx42\" } ] }");
+ R"({ "icons": [ {"src": "", "sizes": "x 40xx 1x2x3 x42 42xx42" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -1210,9 +1320,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \"any\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": "any" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->purpose.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -1220,9 +1329,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Trim leading and trailing whitespaces.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \" any \" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": " any " } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
EXPECT_EQ(manifest->icons[0]->purpose.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -1230,7 +1338,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// 'any' is added when property isn't present.
{
- auto& manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1243,9 +1351,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// 'any' is added with error message when property isn't a string (is a
// number).
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": 42 } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": 42 } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1259,9 +1366,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// 'any' is added with error message when property isn't a string (is a
// dictionary).
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": {} } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": {} } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1274,9 +1380,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Smoke test: values correctly parsed.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \"Any Monochrome Maskable\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": "Any Monochrome Maskable" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1292,9 +1397,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Trim whitespaces between values.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \" Any Monochrome \" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": " Any Monochrome " } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1308,9 +1412,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Twice the same value is parsed twice.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \"monochrome monochrome\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": "monochrome monochrome" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1324,9 +1427,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Invalid icon purpose is ignored.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \"monochrome fizzbuzz\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": "monochrome fizzbuzz" } ] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1339,9 +1441,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// If developer-supplied purpose is invalid, entire icon is removed.
{
- auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\","
- "\"purpose\": \"fizzbuzz\" } ] }");
+ auto& manifest = ParseManifest(R"({ "icons": [ {"src": "",
+ "purpose": "fizzbuzz" } ] })");
ASSERT_TRUE(manifest->icons.IsEmpty());
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ(kPurposeInvalidValueError, errors()[0]);
@@ -1350,8 +1451,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Two icons, one with an invalid purpose and the other normal.
{
auto& manifest = ParseManifest(
- "{ \"icons\": [ {\"src\": \"\", \"purpose\": \"fizzbuzz\" }, "
- " {\"src\": \"\" }] }");
+ R"({ "icons": [ {"src": "", "purpose": "fizzbuzz" },
+ {"src": "" }] })");
EXPECT_FALSE(manifest->icons.IsEmpty());
auto& icons = manifest->icons;
@@ -1367,14 +1468,14 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
TEST_F(ManifestParserTest, ShortcutsParseRules) {
// Smoke test: if no shortcut, no value.
{
- auto& manifest = ParseManifest("{ \"shortcuts\": [] }");
+ auto& manifest = ParseManifest(R"({ "shortcuts": [] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Smoke test: if empty shortcut, no value.
{
- auto& manifest = ParseManifest("{ \"shortcuts\": [ {} ] }");
+ auto& manifest = ParseManifest(R"({ "shortcuts": [ {} ] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'url' of 'shortcut' not present.", errors()[0]);
@@ -1384,7 +1485,7 @@ TEST_F(ManifestParserTest, ShortcutsParseRules) {
// the list.
{
auto& manifest =
- ParseManifest("{ \"shortcuts\": [ { \"shortcuts\": [] } ] }");
+ ParseManifest(R"({ "shortcuts": [ { "shortcuts": [] } ] })");
EXPECT_TRUE(manifest->icons.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'url' of 'shortcut' not present.", errors()[0]);
@@ -1392,7 +1493,7 @@ TEST_F(ManifestParserTest, ShortcutsParseRules) {
// Smoke test: shortcut with no name, it will not be present in the list.
{
- auto& manifest = ParseManifest("{ \"shortcuts\": [ { \"url\": \"\" } ] }");
+ auto& manifest = ParseManifest(R"({ "shortcuts": [ { "url": "" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' of 'shortcut' not present.", errors()[0]);
@@ -1400,7 +1501,7 @@ TEST_F(ManifestParserTest, ShortcutsParseRules) {
// Smoke test: shortcut with no url, it will not be present in the list.
{
- auto& manifest = ParseManifest("{ \"shortcuts\": [ { \"name\": \"\" } ] }");
+ auto& manifest = ParseManifest(R"({ "shortcuts": [ { "name": "" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'url' of 'shortcut' not present.", errors()[0]);
@@ -1409,8 +1510,8 @@ TEST_F(ManifestParserTest, ShortcutsParseRules) {
// Smoke test: shortcut with empty name, and empty src, will not be present in
// the list.
{
- auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ { \"name\": \"\", \"url\": \"\" } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "shortcuts": [ { "name": "", "url": "" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' of 'shortcut' is an empty string.", errors()[0]);
@@ -1420,8 +1521,8 @@ TEST_F(ManifestParserTest, ShortcutsParseRules) {
// in the list.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [{ \"name\": \"New Post\", \"url\": \"compose\" }] "
- "}");
+ R"({ "shortcuts": [{ "name": "New Post", "url": "compose" }]
+ })");
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
auto& shortcuts = manifest->shortcuts;
@@ -1437,8 +1538,8 @@ TEST_F(ManifestParserTest, ShortcutNameParseRules) {
// Smoke test.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"foo\", \"url\": \"NameParseTest\" } ] "
- "}");
+ R"({ "shortcuts": [ {"name": "foo", "url": "NameParseTest" } ]
+ })");
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(manifest->shortcuts[0]->name, "foo");
EXPECT_EQ(0u, GetErrorCount());
@@ -1447,8 +1548,8 @@ TEST_F(ManifestParserTest, ShortcutNameParseRules) {
// Trim whitespaces.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \" foo \", \"url\": \"NameParseTest\" "
- "} ] }");
+ R"({ "shortcuts": [ {"name": " foo ", "url": "NameParseTest"
+ } ] })");
ASSERT_EQ(manifest->shortcuts[0]->name, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
@@ -1456,7 +1557,7 @@ TEST_F(ManifestParserTest, ShortcutNameParseRules) {
// Don't parse if shortcut->name isn't present.
{
auto& manifest =
- ParseManifest("{ \"shortcuts\": [ {\"url\": \"NameParseTest\" } ] }");
+ ParseManifest(R"({ "shortcuts": [ {"url": "NameParseTest" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' of 'shortcut' not present.", errors()[0]);
@@ -1465,7 +1566,7 @@ TEST_F(ManifestParserTest, ShortcutNameParseRules) {
// Don't parse if shortcut->name isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": {}, \"url\": \"NameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": {}, "url": "NameParseTest" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' of 'shortcut' ignored, type string expected.",
@@ -1475,7 +1576,7 @@ TEST_F(ManifestParserTest, ShortcutNameParseRules) {
// Don't parse if shortcut->name isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": 42, \"url\": \"NameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": 42, "url": "NameParseTest" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' of 'shortcut' ignored, type string expected.",
@@ -1485,7 +1586,7 @@ TEST_F(ManifestParserTest, ShortcutNameParseRules) {
// Don't parse if shortcut->name is an empty string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"\", \"url\": \"NameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": "", "url": "NameParseTest" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' of 'shortcut' is an empty string.", errors()[0]);
@@ -1496,8 +1597,8 @@ TEST_F(ManifestParserTest, ShortcutShortNameParseRules) {
// Smoke test.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"ShortNameParseTest\", \"short_name\": "
- "\"foo\", \"url\": \"ShortNameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": "ShortNameParseTest", "short_name":
+ "foo", "url": "ShortNameParseTest" } ] })");
ASSERT_EQ(manifest->shortcuts[0]->short_name, "foo");
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -1505,9 +1606,9 @@ TEST_F(ManifestParserTest, ShortcutShortNameParseRules) {
// Shortcut member is parsed when no short_name is present
{
- auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"ShortNameParseTest\", \"url\": "
- "\"ShortNameParseTest\" } ] }");
+ auto& manifest =
+ ParseManifest(R"({ "shortcuts": [ {"name": "ShortNameParseTest", "url":
+ "ShortNameParseTest" } ] })");
ASSERT_TRUE(manifest->shortcuts[0]->short_name.IsNull());
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -1516,8 +1617,8 @@ TEST_F(ManifestParserTest, ShortcutShortNameParseRules) {
// Trim whitespaces.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"ShortNameParseTest\", \"short_name\": "
- "\" foo \", \"url\": \"ShortNameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": "ShortNameParseTest", "short_name":
+ " foo ", "url": "ShortNameParseTest" } ] })");
ASSERT_EQ(manifest->shortcuts[0]->short_name, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
@@ -1525,8 +1626,8 @@ TEST_F(ManifestParserTest, ShortcutShortNameParseRules) {
// Don't parse short_name if it isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"ShortNameParseTest\", \"short_name\": "
- "{}, \"url\": \"ShortNameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": "ShortNameParseTest", "short_name":
+ {}, "url": "ShortNameParseTest" } ] })");
ASSERT_TRUE(manifest->shortcuts[0]->short_name.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -1537,8 +1638,8 @@ TEST_F(ManifestParserTest, ShortcutShortNameParseRules) {
// Don't parse short_name if it isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"ShortNameParseTest\", \"short_name\": "
- "42, \"url\": \"ShortNameParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": "ShortNameParseTest", "short_name":
+ 42, "url": "ShortNameParseTest" } ] })");
ASSERT_TRUE(manifest->shortcuts[0]->short_name.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -1551,9 +1652,11 @@ TEST_F(ManifestParserTest, ShortcutDescriptionParseRules) {
// Smoke test.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"DescriptionParseTest\", "
- "\"description\": "
- "\"foo\", \"url\": \"DescriptionParseTest\" } ] }");
+ R"({ "shortcuts": [ {
+ "name": "DescriptionParseTest",
+ "description": "foo",
+ "url": "DescriptionParseTest" } ]
+ })");
ASSERT_EQ(manifest->shortcuts[0]->description, "foo");
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -1562,8 +1665,8 @@ TEST_F(ManifestParserTest, ShortcutDescriptionParseRules) {
// Shortcut member is parsed when no description is present
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"DescriptionParseTest\", \"url\": "
- "\"DescriptionParseTest\" } ] }");
+ R"({ "shortcuts": [ {"name": "DescriptionParseTest", "url":
+ "DescriptionParseTest" } ] })");
ASSERT_TRUE(manifest->shortcuts[0]->description.IsNull());
ASSERT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -1572,9 +1675,11 @@ TEST_F(ManifestParserTest, ShortcutDescriptionParseRules) {
// Trim whitespaces.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"DescriptionParseTest\", "
- "\"description\": "
- "\" foo \", \"url\": \"DescriptionParseTest\" } ] }");
+ R"({ "shortcuts": [ {
+ "name": "DescriptionParseTest",
+ "description": " foo ",
+ "url": "DescriptionParseTest" } ]
+ })");
ASSERT_EQ(manifest->shortcuts[0]->description, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
@@ -1582,9 +1687,11 @@ TEST_F(ManifestParserTest, ShortcutDescriptionParseRules) {
// Don't parse description if it isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"DescriptionParseTest\", "
- "\"description\": "
- "{}, \"url\": \"DescriptionParseTest\" } ] }");
+ R"({ "shortcuts": [ {
+ "name": "DescriptionParseTest",
+ "description": {},
+ "url": "DescriptionParseTest" } ]
+ })");
ASSERT_TRUE(manifest->shortcuts[0]->description.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -1595,9 +1702,11 @@ TEST_F(ManifestParserTest, ShortcutDescriptionParseRules) {
// Don't parse description if it isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"DescriptionParseTest\", "
- "\"description\": "
- "42, \"url\": \"DescriptionParseTest\" } ] }");
+ R"({ "shortcuts": [ {
+ "name": "DescriptionParseTest",
+ "description": 42,
+ "url": "DescriptionParseTest" } ]
+ })");
ASSERT_TRUE(manifest->shortcuts[0]->description.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -1610,8 +1719,8 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Smoke test.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"UrlParseTest\", \"url\": \"foo\" } ] "
- "}");
+ R"({ "shortcuts": [ {"name": "UrlParseTest", "url": "foo" } ]
+ })");
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(manifest->shortcuts[0]->url, KURL(DefaultDocumentUrl(), "foo"));
EXPECT_EQ(0u, GetErrorCount());
@@ -1619,7 +1728,7 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Smoke test. Don't parse (with an error) when url is not present.
{
- auto& manifest = ParseManifest("{ \"shortcuts\": [ { \"name\": \"\" } ] }");
+ auto& manifest = ParseManifest(R"({ "shortcuts": [ { "name": "" } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'url' of 'shortcut' not present.", errors()[0]);
@@ -1628,8 +1737,7 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Whitespaces.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"UrlParseTest\", \"url\": \" foo "
- "\" } ] }");
+ R"({ "shortcuts": [ {"name": "UrlParseTest", "url": " foo " } ] })");
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(manifest->shortcuts[0]->url, KURL(DefaultDocumentUrl(), "foo"));
EXPECT_EQ(0u, GetErrorCount());
@@ -1638,7 +1746,7 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Don't parse if url isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"UrlParseTest\", \"url\": {} } ] }");
+ R"({ "shortcuts": [ {"name": "UrlParseTest", "url": {} } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(2u, GetErrorCount());
EXPECT_EQ("property 'url' ignored, type string expected.", errors()[0]);
@@ -1648,7 +1756,7 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Don't parse if url isn't a string.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"UrlParseTest\", \"url\": 42 } ] }");
+ R"({ "shortcuts": [ {"name": "UrlParseTest", "url": 42 } ] })");
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(2u, GetErrorCount());
EXPECT_EQ("property 'url' ignored, type string expected.", errors()[0]);
@@ -1658,8 +1766,8 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Resolving has to happen based on the manifest_url.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"shortcuts\": [ {\"name\": \"UrlParseTest\", \"url\": \"foo\" } ] "
- "}",
+ R"({ "shortcuts": [ {"name": "UrlParseTest", "url": "foo" } ]
+ })",
KURL("http://foo.com/landing/manifest.json"), DefaultDocumentUrl());
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(manifest->shortcuts[0]->url.GetString(),
@@ -1670,9 +1778,9 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// Shortcut url should have same origin as the document url.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"shortcuts\": [ {\"name\": \"UrlParseTest\", \"url\": "
- "\"http://bar.com/landing\" } ] "
- "}",
+ R"({ "shortcuts": [ {"name": "UrlParseTest", "url":
+ "http://bar.com/landing" } ]
+ })",
KURL("http://foo.com/landing/manifest.json"), DefaultDocumentUrl());
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
EXPECT_EQ(2u, GetErrorCount());
@@ -1686,8 +1794,8 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// The shortcut_url will be http://foo.com/shortcut which is in not in scope.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"http://foo.com/landing\", \"shortcuts\": [ {\"name\": "
- "\"UrlParseTest\", \"url\": \"shortcut\" } ] }",
+ R"({ "scope": "http://foo.com/landing", "shortcuts": [ {"name":
+ "UrlParseTest", "url": "shortcut" } ] })",
KURL("http://foo.com/manifest.json"),
KURL("http://foo.com/landing/index.html"));
EXPECT_TRUE(manifest->shortcuts.IsEmpty());
@@ -1703,9 +1811,9 @@ TEST_F(ManifestParserTest, ShortcutUrlParseRules) {
// The shortcut_url will be http://foo.com/land/shortcut which is in scope.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"scope\": \"http://foo.com/land\", \"start_url\": "
- "\"http://foo.com/land/landing.html\", \"shortcuts\": [ {\"name\": "
- "\"UrlParseTest\", \"url\": \"shortcut\" } ] }",
+ R"({ "scope": "http://foo.com/land", "start_url":
+ "http://foo.com/land/landing.html", "shortcuts": [ {"name":
+ "UrlParseTest", "url": "shortcut" } ] })",
KURL("http://foo.com/land/manifest.json"),
KURL("http://foo.com/index.html"));
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
@@ -1720,8 +1828,8 @@ TEST_F(ManifestParserTest, ShortcutIconsParseRules) {
// Smoke test: if no icons, shortcut->icons has no value.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"IconParseTest\", \"url\": \"foo\", "
- "\"icons\": [] } ] }");
+ R"({ "shortcuts": [ {"name": "IconParseTest", "url": "foo",
+ "icons": [] } ] })");
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_TRUE(manifest->shortcuts[0]->icons.IsEmpty());
@@ -1731,8 +1839,8 @@ TEST_F(ManifestParserTest, ShortcutIconsParseRules) {
// Smoke test: if empty icon, shortcut->icons has no value.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"IconParseTest\", \"url\": \"foo\", "
- "\"icons\": [{}] } ] }");
+ R"({ "shortcuts": [ {"name": "IconParseTest", "url": "foo",
+ "icons": [{}] } ] })");
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_TRUE(manifest->shortcuts[0]->icons.IsEmpty());
@@ -1742,8 +1850,8 @@ TEST_F(ManifestParserTest, ShortcutIconsParseRules) {
// Smoke test: icon with invalid src, shortcut->icons has no value.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"IconParseTest\", \"url\": \"foo\", "
- "\"icons\": [{ \"icons\": [] }] } ] }");
+ R"({ "shortcuts": [ {"name": "IconParseTest", "url": "foo",
+ "icons": [{ "icons": [] }] } ] })");
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_TRUE(manifest->shortcuts[0]->icons.IsEmpty());
@@ -1753,8 +1861,8 @@ TEST_F(ManifestParserTest, ShortcutIconsParseRules) {
// Smoke test: if icon with empty src, it will be present in shortcut->icons.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"IconParseTest\", \"url\": \"foo\", "
- "\"icons\": [ { \"src\": \"\" } ] } ] }");
+ R"({ "shortcuts": [ {"name": "IconParseTest", "url": "foo",
+ "icons": [ { "src": "" } ] } ] })");
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_FALSE(manifest->shortcuts[0]->icons.IsEmpty());
@@ -1769,8 +1877,8 @@ TEST_F(ManifestParserTest, ShortcutIconsParseRules) {
// shortcut->icons.
{
auto& manifest = ParseManifest(
- "{ \"shortcuts\": [ {\"name\": \"IconParseTest\", \"url\": \"foo\", "
- "\"icons\": [ { \"src\": \"foo.jpg\" } ] } ] }");
+ R"({ "shortcuts": [ {"name": "IconParseTest", "url": "foo",
+ "icons": [ { "src": "foo.jpg" } ] } ] })");
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_FALSE(manifest->shortcuts.IsEmpty());
EXPECT_FALSE(manifest->shortcuts[0]->icons.IsEmpty());
@@ -1779,9 +1887,27 @@ TEST_F(ManifestParserTest, ShortcutIconsParseRules) {
EXPECT_EQ(icons[0]->src.GetString(), "http://foo.com/foo.jpg");
EXPECT_EQ(0u, GetErrorCount());
}
+
+ // Smoke test: if >1 icon with valid src, it will be present in
+ // shortcut->icons.
+ {
+ auto& manifest = ParseManifest(
+ R"({ "shortcuts": [ {"name": "IconParseTest", "url": "foo",
+ "icons": [ {"src": "foo.jpg"}, {"src": "bar.jpg"} ] } ] })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->shortcuts.IsEmpty());
+ EXPECT_FALSE(manifest->shortcuts[0]->icons.IsEmpty());
+ auto& icons = manifest->shortcuts[0]->icons;
+ EXPECT_EQ(icons.size(), 2u);
+ EXPECT_EQ(icons[0]->src.GetString(), "http://foo.com/foo.jpg");
+ EXPECT_EQ(icons[1]->src.GetString(), "http://foo.com/bar.jpg");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
}
TEST_F(ManifestParserTest, FileHandlerParseRules) {
+ base::test::ScopedFeatureList feature_list(
+ blink::features::kFileHandlingIcons);
// Does not contain file_handlers field.
{
auto& manifest = ParseManifest("{ }");
@@ -1791,7 +1917,7 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// file_handlers is not an array.
{
- auto& manifest = ParseManifest("{ \"file_handlers\": { } }");
+ auto& manifest = ParseManifest(R"({ "file_handlers": { } })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'file_handlers' ignored, type array expected.",
errors()[0]);
@@ -1800,19 +1926,18 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Contains file_handlers field but no file handlers.
{
- auto& manifest = ParseManifest("{ \"file_handlers\": [ ] }");
+ auto& manifest = ParseManifest(R"({ "file_handlers": [ ] })");
ASSERT_EQ(0u, GetErrorCount());
EXPECT_EQ(0u, manifest->file_handlers.size());
}
- // Entries must be objects
+ // Entries must be objects.
{
- auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " \"hello world\""
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "file_handlers": [
+ "hello world"
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("FileHandler ignored, type object expected.", errors()[0]);
EXPECT_EQ(0u, manifest->file_handlers.size());
@@ -1821,18 +1946,19 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry without an action is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"accept\": {"
- " \"image/png\": ["
- " \".png\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "accept": {
+ "image/png": [
+ ".png"
+ ]
+ }
+ }
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("FileHandler ignored. Property 'action' is invalid.",
errors()[0]);
@@ -1842,19 +1968,20 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry with an action on a different origin is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"https://example.com/files\","
- " \"accept\": {"
- " \"image/png\": ["
- " \".png\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "https://example.com/files",
+ "accept": {
+ "image/png": [
+ ".png"
+ ]
+ }
+ }
+ ]
+ })");
ASSERT_EQ(2u, GetErrorCount());
EXPECT_EQ(
"property 'action' ignored, should be within scope of the manifest.",
@@ -1867,21 +1994,22 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry with an action outside of the manifest scope is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"start_url\": \"/app/\","
- " \"scope\": \"/app/\","
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": ["
- " \".png\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "start_url": "/app/",
+ "scope": "/app/",
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": [
+ ".png"
+ ]
+ }
+ }
+ ]
+ })");
ASSERT_EQ(2u, GetErrorCount());
EXPECT_EQ(
"property 'action' ignored, should be within scope of the manifest.",
@@ -1894,18 +2022,39 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry without a name is valid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": ["
- " \".png\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": [
+ ".png"
+ ]
+ }
+ }
+ ]
+ })");
+ ASSERT_EQ(0u, GetErrorCount());
+ EXPECT_EQ(1u, manifest->file_handlers.size());
+ }
+
+ // Entry without an icon is valid.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "action": "/files",
+ "accept": {
+ "image/png": [
+ ".png"
+ ]
+ }
+ }
+ ]
+ })");
ASSERT_EQ(0u, GetErrorCount());
EXPECT_EQ(1u, manifest->file_handlers.size());
}
@@ -1913,14 +2062,15 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry without an accept is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\""
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files"
+ }
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("FileHandler ignored. Property 'accept' is invalid.",
errors()[0]);
@@ -1930,15 +2080,16 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry where accept is not an object is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": \"image/png\""
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": "image/png"
+ }
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("FileHandler ignored. Property 'accept' is invalid.",
errors()[0]);
@@ -1948,17 +2099,18 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry where accept extensions are not an array or string is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": {}"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": {}
+ }
+ }
+ ]
+ })");
ASSERT_EQ(2u, GetErrorCount());
EXPECT_EQ(
"property 'accept' type ignored. File extensions must be type array or "
@@ -1972,19 +2124,20 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry where accept extensions are not an array or string is invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": ["
- " {}"
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": [
+ {}
+ ]
+ }
+ }
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'accept' file extension ignored, type string expected.",
errors()[0]);
@@ -1994,23 +2147,26 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Entry with an empty list of extensions is valid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": []"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": []
+ }
+ }
+ ]
+ })");
auto& file_handlers = manifest->file_handlers;
ASSERT_EQ(0u, GetErrorCount());
ASSERT_EQ(1u, file_handlers.size());
EXPECT_EQ("name", file_handlers[0]->name);
+ EXPECT_EQ("http://foo.com/foo.jpg",
+ file_handlers[0]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/files"), file_handlers[0]->action);
ASSERT_TRUE(file_handlers[0]->accept.Contains("image/png"));
EXPECT_EQ(0u, file_handlers[0]->accept.find("image/png")->value.size());
@@ -2019,19 +2175,20 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Extensions that do not start with a '.' are invalid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": ["
- " \"png\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": [
+ "png"
+ ]
+ }
+ }
+ ]
+ })");
auto& file_handlers = manifest->file_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2041,6 +2198,8 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
ASSERT_EQ(1u, file_handlers.size());
EXPECT_EQ("name", file_handlers[0]->name);
+ EXPECT_EQ("http://foo.com/foo.jpg",
+ file_handlers[0]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/files"), file_handlers[0]->action);
ASSERT_TRUE(file_handlers[0]->accept.Contains("image/png"));
EXPECT_EQ(0u, file_handlers[0]->accept.find("image/png")->value.size());
@@ -2049,23 +2208,26 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Extensions specified as a single string is valid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": \".png\""
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
auto& file_handlers = manifest->file_handlers;
ASSERT_EQ(0u, GetErrorCount());
ASSERT_EQ(1u, file_handlers.size());
EXPECT_EQ("name", file_handlers[0]->name);
+ EXPECT_EQ("http://foo.com/foo.jpg",
+ file_handlers[0]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/files"), file_handlers[0]->action);
ASSERT_TRUE(file_handlers[0]->accept.Contains("image/png"));
ASSERT_EQ(1u, file_handlers[0]->accept.find("image/png")->value.size());
@@ -2075,26 +2237,29 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// An array of extensions is valid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/jpg\": ["
- " \".jpg\","
- " \".jpeg\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "name",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/jpg": [
+ ".jpg",
+ ".jpeg"
+ ]
+ }
+ }
+ ]
+ })");
auto& file_handlers = manifest->file_handlers;
ASSERT_EQ(0u, GetErrorCount());
ASSERT_EQ(1u, file_handlers.size());
EXPECT_EQ("name", file_handlers[0]->name);
+ EXPECT_EQ("http://foo.com/foo.jpg",
+ file_handlers[0]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/files"), file_handlers[0]->action);
ASSERT_TRUE(file_handlers[0]->accept.Contains("image/jpg"));
ASSERT_EQ(2u, file_handlers[0]->accept.find("image/jpg")->value.size());
@@ -2105,27 +2270,30 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// Multiple mime types are valid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"Image\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": \".png\","
- " \"image/jpg\": ["
- " \".jpg\","
- " \".jpeg\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "Image",
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png",
+ "image/jpg": [
+ ".jpg",
+ ".jpeg"
+ ]
+ }
+ }
+ ]
+ })");
auto& file_handlers = manifest->file_handlers;
ASSERT_EQ(0u, GetErrorCount());
ASSERT_EQ(1u, file_handlers.size());
EXPECT_EQ("Image", file_handlers[0]->name);
+ EXPECT_EQ("http://foo.com/foo.jpg",
+ file_handlers[0]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/files"), file_handlers[0]->action);
ASSERT_TRUE(file_handlers[0]->accept.Contains("image/jpg"));
@@ -2141,33 +2309,37 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
// file_handlers with multiple entries is valid.
{
auto& manifest = ParseManifest(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"Graph\","
- " \"action\": \"/graph\","
- " \"accept\": {"
- " \"text/svg+xml\": ["
- " \".svg\","
- " \".graph\""
- " ]"
- " }"
- " },"
- " {"
- " \"name\": \"Raw\","
- " \"action\": \"/raw\","
- " \"accept\": {"
- " \"text/csv\": \".csv\""
- " }"
- " }"
- " ]"
- "}");
+ R"({
+ "file_handlers": [
+ {
+ "name": "Graph",
+ "icons": [{ "src": "graph.jpg" }],
+ "action": "/graph",
+ "accept": {
+ "text/svg+xml": [
+ ".svg",
+ ".graph"
+ ]
+ }
+ },
+ {
+ "name": "Raw",
+ "icons": [{ "src": "raw.jpg" }],
+ "action": "/raw",
+ "accept": {
+ "text/csv": ".csv"
+ }
+ }
+ ]
+ })");
auto& file_handlers = manifest->file_handlers;
ASSERT_EQ(0u, GetErrorCount());
ASSERT_EQ(2u, file_handlers.size());
EXPECT_EQ("Graph", file_handlers[0]->name);
+ EXPECT_EQ("http://foo.com/graph.jpg",
+ file_handlers[0]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/graph"), file_handlers[0]->action);
ASSERT_TRUE(file_handlers[0]->accept.Contains("text/svg+xml"));
ASSERT_EQ(2u, file_handlers[0]->accept.find("text/svg+xml")->value.size());
@@ -2176,6 +2348,8 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
file_handlers[0]->accept.find("text/svg+xml")->value[1]);
EXPECT_EQ("Raw", file_handlers[1]->name);
+ EXPECT_EQ("http://foo.com/raw.jpg",
+ file_handlers[1]->icons[0]->src.GetString());
EXPECT_EQ(KURL("http://foo.com/raw"), file_handlers[1]->action);
ASSERT_TRUE(file_handlers[1]->accept.Contains("text/csv"));
ASSERT_EQ(1u, file_handlers[1]->accept.find("text/csv")->value.size());
@@ -2183,6 +2357,142 @@ TEST_F(ManifestParserTest, FileHandlerParseRules) {
}
}
+TEST_F(ManifestParserTest, FileHandlerIconsParseRules) {
+ // Smoke test: if no icons, file_handler->icon has no value.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "icons": [],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->file_handlers.IsEmpty());
+ EXPECT_TRUE(manifest->file_handlers[0]->icons.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Smoke test: if empty icon, file_handler->icons has no value.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "icons": [{}],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->file_handlers.IsEmpty());
+ EXPECT_TRUE(manifest->file_handlers[0]->icons.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Smoke test: icon with invalid src, file_handler->icons has no value.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "icons": [{ "icons": [] }],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->file_handlers.IsEmpty());
+ EXPECT_TRUE(manifest->file_handlers[0]->icons.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Smoke test: if icon with empty src, it will be present in
+ // file_handler->icons.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "icons": [{ "src": "" }],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->file_handlers.IsEmpty());
+ EXPECT_FALSE(manifest->file_handlers[0]->icons.IsEmpty());
+
+ auto& icons = manifest->file_handlers[0]->icons;
+ EXPECT_EQ(icons.size(), 1u);
+ EXPECT_EQ(icons[0]->src.GetString(), "http://foo.com/manifest.json");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Smoke test: if one icon with valid src, it will be present in
+ // file_handler->icons.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "icons": [{ "src": "foo.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->file_handlers.IsEmpty());
+ EXPECT_FALSE(manifest->file_handlers[0]->icons.IsEmpty());
+ auto& icons = manifest->file_handlers[0]->icons;
+ EXPECT_EQ(icons.size(), 1u);
+ EXPECT_EQ(icons[0]->src.GetString(), "http://foo.com/foo.jpg");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Smoke test: if >1 icon with valid src, it will be present in
+ // file_handler->icons.
+ {
+ auto& manifest = ParseManifest(
+ R"({
+ "file_handlers": [
+ {
+ "icons": [{ "src": "foo.jpg" }, { "src": "bar.jpg" }],
+ "action": "/files",
+ "accept": {
+ "image/png": ".png"
+ }
+ }
+ ]
+ })");
+ EXPECT_FALSE(IsManifestEmpty(manifest));
+ EXPECT_FALSE(manifest->file_handlers.IsEmpty());
+ EXPECT_FALSE(manifest->file_handlers[0]->icons.IsEmpty());
+ auto& icons = manifest->file_handlers[0]->icons;
+ EXPECT_EQ(icons.size(), 2u);
+ EXPECT_EQ(icons[0]->src.GetString(), "http://foo.com/foo.jpg");
+ EXPECT_EQ(icons[1]->src.GetString(), "http://foo.com/bar.jpg");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+}
+
TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// Does not contain protocol_handlers field.
{
@@ -2193,7 +2503,7 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// protocol_handlers is not an array.
{
- auto& manifest = ParseManifest("{ \"protocol_handlers\": { } }");
+ auto& manifest = ParseManifest(R"({ "protocol_handlers": { } })");
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'protocol_handlers' ignored, type array expected.",
errors()[0]);
@@ -2202,19 +2512,18 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// Contains protocol_handlers field but no protocol handlers.
{
- auto& manifest = ParseManifest("{ \"protocol_handlers\": [ ] }");
+ auto& manifest = ParseManifest(R"({ "protocol_handlers": [ ] })");
ASSERT_EQ(0u, GetErrorCount());
EXPECT_EQ(0u, manifest->protocol_handlers.size());
}
// Entries must be objects
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " \"hello world\""
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ "hello world"
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("protocol_handlers entry ignored, type object expected.",
errors()[0]);
@@ -2223,15 +2532,14 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// A valid protocol handler.
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"web+github\","
- " \"url\": \"http://foo.com/?profile=%s\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ {
+ "protocol": "web+github",
+ "url": "http://foo.com/?profile=%s"
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2243,15 +2551,14 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// An invalid protocol handler with the URL not being from the same origin.
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"web+github\","
- " \"url\": \"http://bar.com/?profile=%s\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ {
+ "protocol": "web+github",
+ "url": "http://bar.com/?profile=%s"
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(2u, GetErrorCount());
@@ -2266,16 +2573,16 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// An invalid protocol handler with the URL not being within manifest scope.
{
auto& manifest = ParseManifest(
- "{"
- " \"start_url\": \"/app/\","
- " \"scope\": \"/app/\","
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"web+github\","
- " \"url\": \"/?profile=%s\""
- " }"
- " ]"
- "}");
+ R"({
+ "start_url": "/app/",
+ "scope": "/app/",
+ "protocol_handlers": [
+ {
+ "protocol": "web+github",
+ "url": "/?profile=%s"
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(2u, GetErrorCount());
@@ -2289,14 +2596,13 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// An invalid protocol handler with no value for protocol.
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"url\": \"http://foo.com/?profile=%s\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ {
+ "url": "http://foo.com/?profile=%s"
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2309,14 +2615,13 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// An invalid protocol handler with no url.
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"web+github\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ {
+ "protocol": "web+github"
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2328,15 +2633,14 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// An invalid protocol handler with a url that doesn't contain the %s token.
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"web+github\","
- " \"url\": \"http://foo.com/?profile=\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ {
+ "protocol": "web+github",
+ "url": "http://foo.com/?profile="
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(2u, GetErrorCount());
@@ -2351,15 +2655,14 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// An invalid protocol handler with a non-allowed protocol.
{
- auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"github\","
- " \"url\": \"http://foo.com/?profile=\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "protocol_handlers": [
+ {
+ "protocol": "github",
+ "url": "http://foo.com/?profile="
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(2u, GetErrorCount());
@@ -2377,22 +2680,22 @@ TEST_F(ManifestParserTest, ProtocolHandlerParseRules) {
// Multiple valid protocol handlers
{
auto& manifest = ParseManifest(
- "{"
- " \"protocol_handlers\": ["
- " {"
- " \"protocol\": \"web+github\","
- " \"url\": \"http://foo.com/?profile=%s\""
- " },"
- " {"
- " \"protocol\": \"web+test\","
- " \"url\": \"http://foo.com/?test=%s\""
- " },"
- " {"
- " \"protocol\": \"web+relative\","
- " \"url\": \"relativeURL=%s\""
- " }"
- " ]"
- "}");
+ R"({
+ "protocol_handlers": [
+ {
+ "protocol": "web+github",
+ "url": "http://foo.com/?profile=%s"
+ },
+ {
+ "protocol": "web+test",
+ "url": "http://foo.com/?test=%s"
+ },
+ {
+ "protocol": "web+relative",
+ "url": "relativeURL=%s"
+ }
+ ]
+ })");
auto& protocol_handlers = manifest->protocol_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2420,7 +2723,7 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// 'url_handlers' is not an array.
{
- auto& manifest = ParseManifest("{ \"url_handlers\": { } }");
+ auto& manifest = ParseManifest(R"({ "url_handlers": { } })");
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'url_handlers' ignored, type array expected.",
errors()[0]);
@@ -2429,19 +2732,18 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Contains 'url_handlers' field but no URL handler entries.
{
- auto& manifest = ParseManifest("{ \"url_handlers\": [ ] }");
+ auto& manifest = ParseManifest(R"({ "url_handlers": [ ] })");
ASSERT_EQ(0u, GetErrorCount());
EXPECT_EQ(0u, manifest->url_handlers.size());
}
// 'url_handlers' array entries must be objects.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " \"foo.com\""
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ "foo.com"
+ ]
+ })");
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("url_handlers entry ignored, type object expected.", errors()[0]);
EXPECT_EQ(0u, manifest->url_handlers.size());
@@ -2449,14 +2751,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// A valid url handler.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://foo.com\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://foo.com"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2467,14 +2768,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Scheme must be https.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"http://foo.com\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "http://foo.com"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2487,14 +2787,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Origin must be valid.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https:///////\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https:///////"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2506,17 +2805,16 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse multiple valid handlers.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://foo.com\""
- " },"
- " {"
- " \"origin\": \"https://bar.com\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://foo.com"
+ },
+ {
+ "origin": "https://bar.com"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2529,17 +2827,16 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse both valid and invalid handlers.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://foo.com\""
- " },"
- " {"
- " \"origin\": \"about:\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://foo.com"
+ },
+ {
+ "origin": "about:"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2553,14 +2850,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse invalid handler where the origin is a TLD.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://co.uk\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://co.uk"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2573,14 +2869,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse origin with wildcard.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*.foo.com\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*.foo.com"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2592,14 +2887,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse invalid origin wildcard format.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*foo.com\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*foo.com"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2611,14 +2905,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse origin where the host is just the wildcard prefix.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*.\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*."
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2631,14 +2924,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse invalid origin where wildcard is used with a TLD.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*.com\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*.com"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2651,14 +2943,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse invalid origin where wildcard is used with an unknown TLD.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*.foo\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*.foo"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2671,14 +2962,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse invalid origin where wildcard is used with a multipart TLD.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*.co.uk\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*.co.uk"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2691,14 +2981,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse valid origin with private registry.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://*.glitch.me\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://*.glitch.me"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2710,14 +2999,13 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
// Parse valid IP address as origin.
{
- auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://192.168.0.1:8888\""
- " }"
- " ]"
- "}");
+ auto& manifest = ParseManifest(R"({
+ "url_handlers": [
+ {
+ "origin": "https://192.168.0.1:8888"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(0u, GetErrorCount());
@@ -2728,47 +3016,47 @@ TEST_F(ManifestParserTest, UrlHandlerParseRules) {
ASSERT_FALSE(url_handlers[0]->has_origin_wildcard);
}
- // Validate only the first 10 handlers are parsed.
+ // Validate only the first 10 handlers are parsed. The following manifest
+ // specifies 11 handlers, so the last one should not be in the result.
{
auto& manifest = ParseManifest(
- "{"
- " \"url_handlers\": ["
- " {"
- " \"origin\": \"https://192.168.0.1:8001\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8002\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8003\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8004\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8005\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8006\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8007\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8008\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8009\""
- " },"
- " {"
- " \"origin\": \"https://192.168.0.1:8010\""
- " },"
- // 10 handlers above, this one should not be in the result.
- " {"
- " \"origin\": \"https://192.168.0.1:8011\""
- " }"
- " ]"
- "}");
+ R"({
+ "url_handlers": [
+ {
+ "origin": "https://192.168.0.1:8001"
+ },
+ {
+ "origin": "https://192.168.0.1:8002"
+ },
+ {
+ "origin": "https://192.168.0.1:8003"
+ },
+ {
+ "origin": "https://192.168.0.1:8004"
+ },
+ {
+ "origin": "https://192.168.0.1:8005"
+ },
+ {
+ "origin": "https://192.168.0.1:8006"
+ },
+ {
+ "origin": "https://192.168.0.1:8007"
+ },
+ {
+ "origin": "https://192.168.0.1:8008"
+ },
+ {
+ "origin": "https://192.168.0.1:8009"
+ },
+ {
+ "origin": "https://192.168.0.1:8010"
+ },
+ {
+ "origin": "https://192.168.0.1:8011"
+ }
+ ]
+ })");
auto& url_handlers = manifest->url_handlers;
ASSERT_EQ(1u, GetErrorCount());
@@ -2901,7 +3189,7 @@ TEST_F(ManifestParserTest, NoteTakingParseRules) {
TEST_F(ManifestParserTest, ShareTargetParseRules) {
// Contains share_target field but no keys.
{
- auto& manifest = ParseManifest("{ \"share_target\": {} }");
+ auto& manifest = ParseManifest(R"({ "share_target": {} })");
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
@@ -2910,8 +3198,7 @@ TEST_F(ManifestParserTest, ShareTargetParseRules) {
// Contains share_target field but no params key.
{
- auto& manifest =
- ParseManifest("{ \"share_target\": { \"action\": \"\" } }");
+ auto& manifest = ParseManifest(R"({ "share_target": { "action": "" } })");
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(3u, GetErrorCount());
EXPECT_EQ(
@@ -2931,7 +3218,7 @@ TEST_F(ManifestParserTest, ShareTargetParseRules) {
// Contains share_target field but no action key.
{
- auto& manifest = ParseManifest("{ \"share_target\": { \"params\": {} } }");
+ auto& manifest = ParseManifest(R"({ "share_target": { "params": {} } })");
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
@@ -2941,7 +3228,7 @@ TEST_F(ManifestParserTest, ShareTargetParseRules) {
// Key in share_target that isn't valid.
{
auto& manifest = ParseManifest(
- "{ \"share_target\": {\"incorrect_key\": \"some_value\" } }");
+ R"({ "share_target": {"incorrect_key": "some_value" } })");
ASSERT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
@@ -2956,8 +3243,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Contains share_target, but action is empty.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", \"params\": {} } }",
- manifest_url, document_url);
+ R"({ "share_target": { "action": "", "params": {} } })", manifest_url,
+ document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action, manifest_url);
EXPECT_TRUE(manifest->share_target->params->text.IsNull());
@@ -2979,8 +3266,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Parse but throw an error if url_template property isn't a string.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", \"params\": {} } }",
- manifest_url, document_url);
+ R"({ "share_target": { "action": "", "params": {} } })", manifest_url,
+ document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action, manifest_url);
EXPECT_TRUE(manifest->share_target->params->text.IsNull());
@@ -3002,8 +3289,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if action property isn't a string.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": {}, \"params\": {} } }",
- manifest_url, document_url);
+ R"({ "share_target": { "action": {}, "params": {} } })", manifest_url,
+ document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(2u, GetErrorCount());
EXPECT_EQ("property 'action' ignored, type string expected.", errors()[0]);
@@ -3014,8 +3301,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if action property isn't a string.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": 42, \"params\": {} } }",
- manifest_url, document_url);
+ R"({ "share_target": { "action": 42, "params": {} } })", manifest_url,
+ document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(2u, GetErrorCount());
EXPECT_EQ("property 'action' ignored, type string expected.", errors()[0]);
@@ -3026,8 +3313,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if params property isn't a dict.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", \"params\": \"\" } }",
- manifest_url, document_url);
+ R"({ "share_target": { "action": "", "params": "" } })", manifest_url,
+ document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(3u, GetErrorCount());
EXPECT_EQ(
@@ -3048,8 +3335,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if params property isn't a dict.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", \"params\": 42 } }",
- manifest_url, document_url);
+ R"({ "share_target": { "action": "", "params": 42 } })", manifest_url,
+ document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(3u, GetErrorCount());
EXPECT_EQ(
@@ -3070,8 +3357,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Ignore params keys with invalid types.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", \"params\": { \"text\": 42 }"
- " } }",
+ R"({ "share_target": { "action": "", "params": { "text": 42 }
+ } })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action, manifest_url);
@@ -3095,8 +3382,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Ignore params keys with invalid types.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", "
- "\"params\": { \"title\": 42 } } }",
+ R"({ "share_target": { "action": "",
+ "params": { "title": 42 } } })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action, manifest_url);
@@ -3120,8 +3407,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if params property has keys with invalid types.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"\", \"params\": { \"url\": {}, "
- "\"text\": \"hi\" } } }",
+ R"({ "share_target": { "action": "", "params": { "url": {},
+ "text": "hi" } } })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action, manifest_url);
@@ -3145,8 +3432,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if action property isn't a valid URL.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com:a\", \"params\": "
- "{} } }",
+ R"({ "share_target": { "action": "https://foo.com:a", "params":
+ {} } })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(2u, GetErrorCount());
@@ -3159,8 +3446,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// manifest.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo2.com/\", "
- "\"params\": {} } }",
+ R"({ "share_target": { "action": "https://foo2.com/",
+ "params": {} } })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(2u, GetErrorCount());
@@ -3176,10 +3463,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Fail parsing if action is not within scope of the manifest.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"start_url\": \"/app/\","
- " \"scope\": \"/app/\","
- " \"share_target\": { \"action\": \"/\", "
- "\"params\": {} } }",
+ R"({ "start_url": "/app/",
+ "scope": "/app/",
+ "share_target": { "action": "/",
+ "params": {} } })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(2u, GetErrorCount());
@@ -3195,7 +3482,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Smoke test: Contains share_target and action, and action is valid.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": {\"action\": \"share/\", \"params\": {} } }",
+ R"({ "share_target": {"action": "share/", "params": {} } })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action.GetString(),
@@ -3220,8 +3507,8 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// is populated.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": {\"action\": \"share/\", \"params\": { \"text\": "
- "\"foo\", \"title\": \"bar\", \"url\": \"baz\" } } }",
+ R"({ "share_target": {"action": "share/", "params": { "text":
+ "foo", "title": "bar", "url": "baz" } } })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action.GetString(),
@@ -3246,10 +3533,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// action, and action is valid, params is populated.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"url_template\": "
- "\"foo.com/share?title={title}\", "
- "\"action\": \"share/\", \"params\": { \"text\": "
- "\"foo\", \"title\": \"bar\", \"url\": \"baz\" } } }",
+ R"({ "share_target": { "url_template":
+ "foo.com/share?title={title}",
+ "action": "share/", "params": { "text":
+ "foo", "title": "bar", "url": "baz" } } })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action.GetString(),
@@ -3274,9 +3561,9 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// valid and is absolute.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
ASSERT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->action.GetString(), "https://foo.com/#");
@@ -3299,10 +3586,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Return undefined if method or enctype is not string.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "10, \"enctype\": 10, \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ 10, "enctype": 10, "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3315,11 +3602,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Valid method and enctype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"GET\", \"enctype\": \"application/x-www-form-urlencoded\", "
- "\"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "GET", "enctype": "application/x-www-form-urlencoded",
+ "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->method,
@@ -3332,9 +3619,9 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// enctype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->method,
@@ -3346,10 +3633,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Invalid method values, return undefined.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"\", \"enctype\": \"application/x-www-form-urlencoded\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "", "enctype": "application/x-www-form-urlencoded", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3363,10 +3650,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// "application/x-www-form-urlencoded".
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"GET\", \"enctype\": \"RANDOM\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "GET", "enctype": "RANDOM", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3380,10 +3667,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// "application/x-www-form-urlencoded" or "multipart/form-data".
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"random\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "random", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3396,11 +3683,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Valid enctype for when method is "POST".
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"application/x-www-form-urlencoded\", "
- "\"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"( { "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "application/x-www-form-urlencoded",
+ "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->method,
@@ -3413,10 +3700,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Valid enctype for when method is "POST".
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->method,
@@ -3429,10 +3716,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Ascii in-sensitive.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"PosT\", \"enctype\": \"mUltIparT/Form-dAta\", \"params\": "
- "{ \"title\": \"mytitle\" } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "PosT", "enctype": "mUltIparT/Form-dAta", "params":
+ { "title": "mytitle" } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->method,
@@ -3445,10 +3732,10 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// No files is okay.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [] } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_EQ(manifest->share_target->method,
@@ -3462,11 +3749,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// GET method, for example, will cause an error in this case.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"GET\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"text/plain\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "GET", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": ["text/plain"]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3480,12 +3767,12 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Enctype other than multipart/form-data will cause an error.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"application/x-www-form-urlencoded\", "
- "\"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"text/plain\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "application/x-www-form-urlencoded",
+ "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": ["text/plain"]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3497,11 +3784,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// This case is valid.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"text/plain\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": ["text/plain"]}] } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_TRUE(manifest->share_target->params->files.has_value());
@@ -3512,11 +3799,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Invalid mimetype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": [""]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3526,11 +3813,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Invalid mimetype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"helloworld\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": ["helloworld"]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3540,11 +3827,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Invalid mimetype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"^$/@$\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": ["^$/@$"]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3554,11 +3841,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Invalid mimetype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\"/\"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": ["/"]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3568,11 +3855,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Invalid mimetype.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": [\" \"]}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": [" "]}] } }
+ })",
manifest_url, document_url);
EXPECT_FALSE(manifest->share_target.get());
EXPECT_EQ(1u, GetErrorCount());
@@ -3582,11 +3869,11 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Accept field is empty.
{
auto& manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"method\": "
- "\"POST\", \"enctype\": \"multipart/form-data\", \"params\": "
- "{ \"title\": \"mytitle\", \"files\": [{ \"name\": \"name\", "
- "\"accept\": []}] } } "
- "}",
+ R"({ "share_target": { "action": "https://foo.com/#", "method":
+ "POST", "enctype": "multipart/form-data", "params":
+ { "title": "mytitle", "files": [{ "name": "name",
+ "accept": []}] } }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
EXPECT_FALSE(manifest->share_target->params->files.has_value());
@@ -3596,20 +3883,20 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Accept sequence contains non-string elements.
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": [{"
- " \"name\": \"name\","
- " \"accept\": [\"image/png\", 42]"
- " }]"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": [{
+ "name": "name",
+ "accept": ["image/png", 42]
+ }]
+ }
+ }
+ })",
manifest_url, document_url);
auto* share_target = manifest->share_target.get();
EXPECT_TRUE(share_target);
@@ -3631,20 +3918,20 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Accept is just a single string.
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": [{"
- " \"name\": \"name\","
- " \"accept\": \"image/png\""
- " }]"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": [{
+ "name": "name",
+ "accept": "image/png"
+ }]
+ }
+ }
+ })",
manifest_url, document_url);
auto* share_target = manifest->share_target.get();
EXPECT_TRUE(share_target);
@@ -3663,20 +3950,20 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Accept is neither a string nor an array of strings.
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": [{"
- " \"name\": \"name\","
- " \"accept\": true"
- " }]"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": [{
+ "name": "name",
+ "accept": true
+ }]
+ }
+ }
+ })",
manifest_url, document_url);
auto* share_target = manifest->share_target.get();
EXPECT_TRUE(share_target);
@@ -3690,20 +3977,20 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Files is just a single FileFilter (not an array).
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": {"
- " \"name\": \"name\","
- " \"accept\": \"image/png\""
- " }"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": {
+ "name": "name",
+ "accept": "image/png"
+ }
+ }
+ }
+ })",
manifest_url, document_url);
EXPECT_TRUE(manifest->share_target.get());
@@ -3723,17 +4010,17 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Files is neither array nor FileFilter.
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": 3"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": 3
+ }
+ }
+ })",
manifest_url, document_url);
auto* share_target = manifest->share_target.get();
EXPECT_TRUE(share_target);
@@ -3747,23 +4034,23 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Files contains a non-dictionary entry.
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": ["
- " {"
- " \"name\": \"name\","
- " \"accept\": \"image/png\""
- " },"
- " 3"
- " ]"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": [
+ {
+ "name": "name",
+ "accept": "image/png"
+ },
+ 3
+ ]
+ }
+ }
+ })",
manifest_url, document_url);
auto* share_target = manifest->share_target.get();
EXPECT_TRUE(share_target);
@@ -3785,23 +4072,23 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Files contains empty file.
{
auto& manifest = ParseManifestWithURLs(
- "{"
- " \"share_target\": {"
- " \"action\": \"https://foo.com/#\","
- " \"method\": \"POST\","
- " \"enctype\": \"multipart/form-data\","
- " \"params\": {"
- " \"title\": \"mytitle\","
- " \"files\": ["
- " {"
- " \"name\": \"name\","
- " \"accept\": \"image/png\""
- " },"
- " {}"
- " ]"
- " }"
- " }"
- "}",
+ R"({
+ "share_target": {
+ "action": "https://foo.com/#",
+ "method": "POST",
+ "enctype": "multipart/form-data",
+ "params": {
+ "title": "mytitle",
+ "files": [
+ {
+ "name": "name",
+ "accept": "image/png"
+ },
+ {}
+ ]
+ }
+ }
+ })",
manifest_url, document_url);
auto* share_target = manifest->share_target.get();
EXPECT_TRUE(share_target);
@@ -3823,14 +4110,14 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If no application, empty list.
{
- auto& manifest = ParseManifest("{ \"related_applications\": []}");
+ auto& manifest = ParseManifest(R"({ "related_applications": []})");
EXPECT_TRUE(manifest->related_applications.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// If empty application, empty list.
{
- auto& manifest = ParseManifest("{ \"related_applications\": [{}]}");
+ auto& manifest = ParseManifest(R"({ "related_applications": [{}]})");
EXPECT_TRUE(manifest->related_applications.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("'platform' is a required field, related application ignored.",
@@ -3840,7 +4127,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If invalid platform, application is ignored.
{
auto& manifest =
- ParseManifest("{ \"related_applications\": [{\"platform\": 123}]}");
+ ParseManifest(R"({ "related_applications": [{"platform": 123}]})");
EXPECT_TRUE(manifest->related_applications.IsEmpty());
EXPECT_EQ(2u, GetErrorCount());
EXPECT_EQ("property 'platform' ignored, type string expected.",
@@ -3854,7 +4141,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If missing platform, application is ignored.
{
auto& manifest =
- ParseManifest("{ \"related_applications\": [{\"id\": \"foo\"}]}");
+ ParseManifest(R"({ "related_applications": [{"id": "foo"}]})");
EXPECT_TRUE(manifest->related_applications.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("'platform' is a required field, related application ignored.",
@@ -3863,8 +4150,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If missing id and url, application is ignored.
{
- auto& manifest = ParseManifest(
- "{ \"related_applications\": [{\"platform\": \"play\"}]}");
+ auto& manifest =
+ ParseManifest(R"({ "related_applications": [{"platform": "play"}]})");
EXPECT_TRUE(manifest->related_applications.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("one of 'url' or 'id' is required, related application ignored.",
@@ -3873,9 +4160,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Valid application, with url.
{
- auto& manifest = ParseManifest(
- "{ \"related_applications\": ["
- "{\"platform\": \"play\", \"url\": \"http://www.foo.com\"}]}");
+ auto& manifest = ParseManifest(R"({ "related_applications": [
+ {"platform": "play", "url": "http://www.foo.com"}]})");
auto& related_applications = manifest->related_applications;
EXPECT_EQ(related_applications.size(), 1u);
EXPECT_EQ(related_applications[0]->platform, "play");
@@ -3887,9 +4173,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Application with an invalid url.
{
- auto& manifest = ParseManifest(
- "{ \"related_applications\": ["
- "{\"platform\": \"play\", \"url\": \"http://www.foo.com:co&uk\"}]}");
+ auto& manifest = ParseManifest(R"({ "related_applications": [
+ {"platform": "play", "url": "http://www.foo.com:co&uk"}]})");
EXPECT_TRUE(manifest->related_applications.IsEmpty());
EXPECT_EQ(2u, GetErrorCount());
EXPECT_EQ("property 'url' ignored, URL is invalid.", errors()[0]);
@@ -3899,9 +4184,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Valid application, with id.
{
- auto& manifest = ParseManifest(
- "{ \"related_applications\": ["
- "{\"platform\": \"itunes\", \"id\": \"foo\"}]}");
+ auto& manifest = ParseManifest(R"({ "related_applications": [
+ {"platform": "itunes", "id": "foo"}]})");
auto& related_applications = manifest->related_applications;
EXPECT_EQ(related_applications.size(), 1u);
EXPECT_EQ(related_applications[0]->platform, "itunes");
@@ -3913,9 +4197,9 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// All valid applications are in list.
{
auto& manifest = ParseManifest(
- "{ \"related_applications\": ["
- "{\"platform\": \"play\", \"id\": \"foo\"},"
- "{\"platform\": \"itunes\", \"id\": \"bar\"}]}");
+ R"({ "related_applications": [
+ {"platform": "play", "id": "foo"},
+ {"platform": "itunes", "id": "bar"}]})");
auto& related_applications = manifest->related_applications;
EXPECT_EQ(related_applications.size(), 2u);
EXPECT_EQ(related_applications[0]->platform, "play");
@@ -3930,10 +4214,10 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// be in the list.
{
auto& manifest = ParseManifest(
- "{ \"related_applications\": ["
- "{\"platform\": \"itunes\"},"
- "{\"platform\": \"play\", \"id\": \"foo\"},"
- "{}]}");
+ R"({ "related_applications": [
+ {"platform": "itunes"},
+ {"platform": "play", "id": "foo"},
+ {}]})");
auto& related_applications = manifest->related_applications;
EXPECT_EQ(related_applications.size(), 1u);
EXPECT_EQ(related_applications[0]->platform, "play");
@@ -3950,14 +4234,15 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"prefer_related_applications\": true }");
+ auto& manifest =
+ ParseManifest(R"({ "prefer_related_applications": true })");
EXPECT_TRUE(manifest->prefer_related_applications);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if the property isn't a boolean.
{
- auto& manifest = ParseManifest("{ \"prefer_related_applications\": {} }");
+ auto& manifest = ParseManifest(R"({ "prefer_related_applications": {} })");
EXPECT_FALSE(manifest->prefer_related_applications);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -3967,7 +4252,7 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
}
{
auto& manifest =
- ParseManifest("{ \"prefer_related_applications\": \"true\" }");
+ ParseManifest(R"({ "prefer_related_applications": "true" })");
EXPECT_FALSE(manifest->prefer_related_applications);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -3976,7 +4261,7 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
errors()[0]);
}
{
- auto& manifest = ParseManifest("{ \"prefer_related_applications\": 1 }");
+ auto& manifest = ParseManifest(R"({ "prefer_related_applications": 1 })");
EXPECT_FALSE(manifest->prefer_related_applications);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -3988,7 +4273,7 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
// "False" should set the boolean false without throwing errors.
{
auto& manifest =
- ParseManifest("{ \"prefer_related_applications\": false }");
+ ParseManifest(R"({ "prefer_related_applications": false })");
EXPECT_FALSE(manifest->prefer_related_applications);
EXPECT_EQ(0u, GetErrorCount());
}
@@ -3997,7 +4282,7 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"#FF0000\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "#FF0000" })");
EXPECT_TRUE(manifest->has_theme_color);
EXPECT_EQ(manifest->theme_color, 0xFFFF0000u);
EXPECT_FALSE(IsManifestEmpty(manifest));
@@ -4006,7 +4291,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \" blue \" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": " blue " })");
EXPECT_TRUE(manifest->has_theme_color);
EXPECT_EQ(manifest->theme_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
@@ -4014,7 +4299,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"theme_color\": {} }");
+ auto& manifest = ParseManifest(R"({ "theme_color": {} })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
@@ -4023,7 +4308,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"theme_color\": false }");
+ auto& manifest = ParseManifest(R"({ "theme_color": false })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
@@ -4032,7 +4317,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"theme_color\": null }");
+ auto& manifest = ParseManifest(R"({ "theme_color": null })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
@@ -4041,7 +4326,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"theme_color\": [] }");
+ auto& manifest = ParseManifest(R"({ "theme_color": [] })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
@@ -4050,7 +4335,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"theme_color\": 42 }");
+ auto& manifest = ParseManifest(R"({ "theme_color": 42 })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
@@ -4059,7 +4344,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if string is not in a known format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"foo(bar)\" }");
+ auto& manifest = ParseManifest(R"~({ "theme_color": "foo(bar)" })~");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4070,7 +4355,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if string is not in a known format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"bleu\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "bleu" })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, 'bleu' is not a valid color.",
@@ -4079,7 +4364,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if string is not in a known format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"FF00FF\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "FF00FF" })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4090,7 +4375,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if multiple values for theme_color are given.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"#ABC #DEF\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "#ABC #DEF" })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4101,7 +4386,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if multiple values for theme_color are given.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"#AABBCC #DDEEFF\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "#AABBCC #DDEEFF" })");
EXPECT_FALSE(manifest->has_theme_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4112,51 +4397,50 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Accept CSS color keyword format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"blue\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "blue" })");
EXPECT_EQ(manifest->theme_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS color keyword format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"chartreuse\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "chartreuse" })");
EXPECT_EQ(manifest->theme_color, 0xFF7FFF00u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"#FFF\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "#FFF" })");
EXPECT_EQ(manifest->theme_color, 0xFFFFFFFFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"#ABC\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "#ABC" })");
EXPECT_EQ(manifest->theme_color, 0xFFAABBCCu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RRGGBB format.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"#FF0000\" }");
+ auto& manifest = ParseManifest(R"({ "theme_color": "#FF0000" })");
EXPECT_EQ(manifest->theme_color, 0xFFFF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept translucent colors.
{
- auto& manifest = ParseManifest(
- "{ \"theme_color\": \"rgba(255,0,0,"
- "0.4)\" }");
+ auto& manifest =
+ ParseManifest(R"~({ "theme_color": "rgba(255,0,0,0.4)" })~");
EXPECT_EQ(manifest->theme_color, 0x66FF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept transparent colors.
{
- auto& manifest = ParseManifest("{ \"theme_color\": \"rgba(0,0,0,0)\" }");
+ auto& manifest = ParseManifest(R"~({ "theme_color": "rgba(0,0,0,0)" })~");
EXPECT_EQ(manifest->theme_color, 0x00000000u);
EXPECT_EQ(0u, GetErrorCount());
}
@@ -4165,7 +4449,7 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"#FF0000\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "#FF0000" })");
EXPECT_EQ(manifest->background_color, 0xFFFF0000u);
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
@@ -4173,14 +4457,14 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"background_color\": \" blue \" }");
+ auto& manifest = ParseManifest(R"({ "background_color": " blue " })");
EXPECT_EQ(manifest->background_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if background_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"background_color\": {} }");
+ auto& manifest = ParseManifest(R"({ "background_color": {} })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
@@ -4189,7 +4473,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"background_color\": false }");
+ auto& manifest = ParseManifest(R"({ "background_color": false })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
@@ -4198,7 +4482,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"background_color\": null }");
+ auto& manifest = ParseManifest(R"({ "background_color": null })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
@@ -4207,7 +4491,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"background_color\": [] }");
+ auto& manifest = ParseManifest(R"({ "background_color": [] })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
@@ -4216,7 +4500,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- auto& manifest = ParseManifest("{ \"background_color\": 42 }");
+ auto& manifest = ParseManifest(R"({ "background_color": 42 })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
@@ -4225,7 +4509,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if string is not in a known format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"foo(bar)\" }");
+ auto& manifest = ParseManifest(R"~({ "background_color": "foo(bar)" })~");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4236,7 +4520,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if string is not in a known format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"bleu\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "bleu" })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4247,7 +4531,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if string is not in a known format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"FF00FF\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "FF00FF" })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4258,7 +4542,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if multiple values for background_color are given.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"#ABC #DEF\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "#ABC #DEF" })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4270,7 +4554,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if multiple values for background_color are given.
{
auto& manifest =
- ParseManifest("{ \"background_color\": \"#AABBCC #DDEEFF\" }");
+ ParseManifest(R"({ "background_color": "#AABBCC #DDEEFF" })");
EXPECT_FALSE(manifest->has_background_color);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -4281,53 +4565,51 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Accept CSS color keyword format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"blue\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "blue" })");
EXPECT_EQ(manifest->background_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS color keyword format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"chartreuse\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "chartreuse" })");
EXPECT_EQ(manifest->background_color, 0xFF7FFF00u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"#FFF\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "#FFF" })");
EXPECT_EQ(manifest->background_color, 0xFFFFFFFFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"#ABC\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "#ABC" })");
EXPECT_EQ(manifest->background_color, 0xFFAABBCCu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RRGGBB format.
{
- auto& manifest = ParseManifest("{ \"background_color\": \"#FF0000\" }");
+ auto& manifest = ParseManifest(R"({ "background_color": "#FF0000" })");
EXPECT_EQ(manifest->background_color, 0xFFFF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept translucent colors.
{
- auto& manifest = ParseManifest(
- "{ \"background_color\": \"rgba(255,0,0,"
- "0.4)\" }");
+ auto& manifest =
+ ParseManifest(R"~({ "background_color": "rgba(255,0,0,0.4)" })~");
EXPECT_EQ(manifest->background_color, 0x66FF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept transparent colors.
{
- auto& manifest = ParseManifest(
- "{ \"background_color\": \"rgba(0,0,0,"
- "0)\" }");
+ auto& manifest =
+ ParseManifest(R"~({ "background_color": "rgba(0,0,0,0)" })~");
EXPECT_EQ(manifest->background_color, 0x00000000u);
EXPECT_EQ(0u, GetErrorCount());
}
@@ -4336,28 +4618,28 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
TEST_F(ManifestParserTest, GCMSenderIDParseRules) {
// Smoke test.
{
- auto& manifest = ParseManifest("{ \"gcm_sender_id\": \"foo\" }");
+ auto& manifest = ParseManifest(R"({ "gcm_sender_id": "foo" })");
EXPECT_EQ(manifest->gcm_sender_id, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
// Trim whitespaces.
{
- auto& manifest = ParseManifest("{ \"gcm_sender_id\": \" foo \" }");
+ auto& manifest = ParseManifest(R"({ "gcm_sender_id": " foo " })");
EXPECT_EQ(manifest->gcm_sender_id, "foo");
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if the property isn't a string.
{
- auto& manifest = ParseManifest("{ \"gcm_sender_id\": {} }");
+ auto& manifest = ParseManifest(R"({ "gcm_sender_id": {} })");
EXPECT_TRUE(manifest->gcm_sender_id.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'gcm_sender_id' ignored, type string expected.",
errors()[0]);
}
{
- auto& manifest = ParseManifest("{ \"gcm_sender_id\": 42 }");
+ auto& manifest = ParseManifest(R"({ "gcm_sender_id": 42 })");
EXPECT_TRUE(manifest->gcm_sender_id.IsNull());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'gcm_sender_id' ignored, type string expected.",
@@ -4365,119 +4647,299 @@ TEST_F(ManifestParserTest, GCMSenderIDParseRules) {
}
}
-TEST_F(ManifestParserTest, CaptureLinksParseRules) {
+TEST_F(ManifestParserTest, StorageIsolationDisabled) {
// Feature not enabled, should not be parsed.
{
- auto& manifest = ParseManifest(R"({ "capture_links": "none" })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
+ auto& manifest = ParseManifest(R"({ "isolated_storage": true })");
+ EXPECT_EQ(manifest->isolated_storage, false);
EXPECT_EQ(0u, GetErrorCount());
}
}
-class ManifestCaptureLinksParserTest : public ManifestParserTest {
- public:
- ManifestCaptureLinksParserTest() {
- scoped_feature_list_.InitAndEnableFeature(
- features::kWebAppEnableLinkCapturing);
- }
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(ManifestCaptureLinksParserTest, CaptureLinksParseRules) {
- // Smoke test.
- {
- auto& manifest = ParseManifest(R"({ "capture_links": "none" })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kNone);
- EXPECT_EQ(0u, GetErrorCount());
- }
- {
- auto& manifest = ParseManifest(R"({ "capture_links": ["new-client"] })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kNewClient);
- EXPECT_EQ(0u, GetErrorCount());
- }
-
- // Empty array is fine.
+TEST_F(ManifestParserTest, StorageIsolationEnabled) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ blink::features::kWebAppEnableIsolatedStorage);
{
- auto& manifest = ParseManifest(R"({ "capture_links": [] })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
+ auto& manifest = ParseManifest(R"({ "isolated_storage": true })");
+ EXPECT_EQ(manifest->isolated_storage, true);
EXPECT_EQ(0u, GetErrorCount());
}
+}
- // Unknown single string.
+TEST_F(ManifestParserTest, StorageIsolationBadScope) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ blink::features::kWebAppEnableIsolatedStorage);
{
- auto& manifest = ParseManifest(R"({ "capture_links": "unknown" })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
+ auto& manifest = ParseManifest(
+ R"({ "isolated_storage": true,
+ "scope": "/invalid",
+ "start_url": "/invalid/index.html" })");
+ EXPECT_EQ(manifest->isolated_storage, false);
EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ("capture_links value 'unknown' ignored, unknown value.",
+ EXPECT_EQ("Isolated storage is only supported with a scope of \"/\".",
errors()[0]);
}
+}
- // First known value in array is used.
+TEST_F(ManifestParserTest, CaptureLinksParseRules) {
{
- auto& manifest = ParseManifest(
- R"({ "capture_links": ["none", "existing-client-navigate"] })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kNone);
+ ScopedWebAppLinkCapturingForTest feature(false);
+
+ // Feature not enabled, should not be parsed.
+ auto& manifest = ParseManifest(R"({ "capture_links": "none" })");
+ EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
EXPECT_EQ(0u, GetErrorCount());
}
+
{
- auto& manifest = ParseManifest(R"({
- "capture_links": [
- "unknown",
- "existing-client-navigate",
- "also-unknown",
- "none"
- ]
- })");
- EXPECT_EQ(manifest->capture_links,
- mojom::blink::CaptureLinks::kExistingClientNavigate);
- EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ("capture_links value 'unknown' ignored, unknown value.",
- errors()[0]);
+ ScopedWebAppLinkCapturingForTest feature(true);
+ // Smoke test.
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": "none" })");
+ EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kNone);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": ["new-client"] })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kNewClient);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Empty array is fine.
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": [] })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kUndefined);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Unknown single string.
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": "unknown" })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kUndefined);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("capture_links value 'unknown' ignored, unknown value.",
+ errors()[0]);
+ }
+
+ // First known value in array is used.
+ {
+ auto& manifest = ParseManifest(
+ R"({ "capture_links": ["none", "existing-client-navigate"] })");
+ EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kNone);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+ {
+ auto& manifest = ParseManifest(R"({
+ "capture_links": [
+ "unknown",
+ "existing-client-navigate",
+ "also-unknown",
+ "none"
+ ]
+ })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kExistingClientNavigate);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("capture_links value 'unknown' ignored, unknown value.",
+ errors()[0]);
+ }
+ {
+ auto& manifest = ParseManifest(R"({
+ "capture_links": [
+ 1234,
+ "new-client",
+ null,
+ "none"
+ ]
+ })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kNewClient);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("capture_links value '1234' ignored, string expected.",
+ errors()[0]);
+ }
+
+ // Don't parse if the property isn't a string or array of strings.
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": null })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kUndefined);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ(
+ "property 'capture_links' ignored, type string or array of strings "
+ "expected.",
+ errors()[0]);
+ }
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": 1234 })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kUndefined);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ(
+ "property 'capture_links' ignored, type string or array of strings "
+ "expected.",
+ errors()[0]);
+ }
+ {
+ auto& manifest = ParseManifest(R"({ "capture_links": [12, 34] })");
+ EXPECT_EQ(manifest->capture_links,
+ mojom::blink::CaptureLinks::kUndefined);
+ EXPECT_EQ(2u, GetErrorCount());
+ EXPECT_EQ("capture_links value '12' ignored, string expected.",
+ errors()[0]);
+ EXPECT_EQ("capture_links value '34' ignored, string expected.",
+ errors()[1]);
+ }
}
+}
+
+TEST_F(ManifestParserTest, LaunchHandlerParseRules) {
+ using RouteTo = mojom::blink::ManifestLaunchHandler::RouteTo;
+ using NavigateExistingClient =
+ mojom::blink::ManifestLaunchHandler::NavigateExistingClient;
+
{
+ ScopedWebAppLaunchHandlerForTest feature(false);
+
+ // Feature not enabled, should not be parsed.
auto& manifest = ParseManifest(R"({
- "capture_links": [
- 1234,
- "new-client",
- null,
- "none"
- ]
+ "launch_handler": {
+ "route_to": "existing-client",
+ "navigate_existing_client": "never"
+ }
})");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kNewClient);
- EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ("capture_links value '1234' ignored, string expected.",
- errors()[0]);
- }
-
- // Don't parse if the property isn't a string or array of strings.
- {
- auto& manifest = ParseManifest(R"({ "capture_links": null })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
- EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ(
- "property 'capture_links' ignored, type string or array of strings "
- "expected.",
- errors()[0]);
- }
- {
- auto& manifest = ParseManifest(R"({ "capture_links": 1234 })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
- EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ(
- "property 'capture_links' ignored, type string or array of strings "
- "expected.",
- errors()[0]);
- }
- {
- auto& manifest = ParseManifest(R"({ "capture_links": [12, 34] })");
- EXPECT_EQ(manifest->capture_links, mojom::blink::CaptureLinks::kUndefined);
- EXPECT_EQ(2u, GetErrorCount());
- EXPECT_EQ("capture_links value '12' ignored, string expected.",
- errors()[0]);
- EXPECT_EQ("capture_links value '34' ignored, string expected.",
- errors()[1]);
+ EXPECT_FALSE(manifest->launch_handler);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ {
+ ScopedWebAppLaunchHandlerForTest feature(true);
+ // Smoke test.
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {
+ "route_to": "existing-client",
+ "navigate_existing_client": "never"
+ }
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kExistingClient);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kNever);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {
+ "route_to": "new-client",
+ "navigate_existing_client": "always"
+ }
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kNewClient);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kAlways);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Empty object is fine.
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {}
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kAuto);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kAlways);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Empty array is fine.
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {
+ "route_to": [],
+ "navigate_existing_client": []
+ }
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kAuto);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kAlways);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Unknown single string.
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {
+ "route_to": "space",
+ "navigate_existing_client": "sometimes"
+ }
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kAuto);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kAlways);
+ EXPECT_EQ(2u, GetErrorCount());
+ EXPECT_EQ("route_to value 'space' ignored, unknown value.", errors()[0]);
+ EXPECT_EQ(
+ "navigate_existing_client value 'sometimes' ignored, unknown value.",
+ errors()[1]);
+ }
+
+ // First known value in array is used.
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {
+ "route_to": ["existing-client", "new-client"],
+ "navigate_existing_client": ["never", "always"]
+ }
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kExistingClient);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kNever);
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": {
+ "route_to": [null, "space", "existing-client", "auto"],
+ "navigate_existing_client": [1234, "sometimes", "never", "always"]
+ }
+ })");
+ EXPECT_EQ(manifest->launch_handler->route_to, RouteTo::kExistingClient);
+ EXPECT_EQ(manifest->launch_handler->navigate_existing_client,
+ NavigateExistingClient::kNever);
+ EXPECT_EQ(4u, GetErrorCount());
+ EXPECT_EQ("route_to value 'null' ignored, string expected.", errors()[0]);
+ EXPECT_EQ("route_to value 'space' ignored, unknown value.", errors()[1]);
+ EXPECT_EQ(
+ "navigate_existing_client value '1234' ignored, string expected.",
+ errors()[2]);
+ EXPECT_EQ(
+ "navigate_existing_client value 'sometimes' ignored, unknown value.",
+ errors()[3]);
+ }
+
+ // Don't parse if the property isn't an object.
+ {
+ auto& manifest = ParseManifest(R"({ "launch_handler": null })");
+ EXPECT_FALSE(manifest->launch_handler);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("launch_handler value ignored, object expected.", errors()[0]);
+ }
+ {
+ auto& manifest = ParseManifest(R"({
+ "launch_handler": [{
+ "route_to": "new-client",
+ "navigate_existing_client": "never"
+ }]
+ })");
+ EXPECT_FALSE(manifest->launch_handler);
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("launch_handler value ignored, object expected.", errors()[0]);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc
deleted file mode 100644
index 5cfd6936243..00000000000
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/manifest/manifest_type_converters.h"
-
-#include <utility>
-
-#include "third_party/blink/public/common/manifest/manifest.h"
-#include "third_party/blink/public/common/manifest/manifest_mojom_traits.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace mojo {
-
-blink::Manifest
-TypeConverter<blink::Manifest, blink::mojom::blink::ManifestPtr>::Convert(
- const blink::mojom::blink::ManifestPtr& input) {
- blink::Manifest output;
- if (input.is_null())
- return output;
-
- if (!input->name.IsEmpty())
- output.name = blink::WebString(input->name).Utf16();
-
- if (!input->short_name.IsEmpty())
- output.short_name = blink::WebString(input->short_name).Utf16();
-
- if (!input->start_url.IsEmpty())
- output.start_url = input->start_url;
-
- output.display = input->display;
- output.orientation = input->orientation;
-
- for (auto& icon : input->icons)
- output.icons.push_back(icon.To<blink::Manifest::ImageResource>());
-
- for (auto& shortcut : input->shortcuts)
- output.shortcuts.push_back(shortcut.To<blink::Manifest::ShortcutItem>());
-
- if (!input->share_target.is_null()) {
- output.share_target =
- input->share_target.To<blink::Manifest::ShareTarget>();
- }
-
- for (auto& entry : input->file_handlers) {
- output.file_handlers.push_back(entry.To<blink::Manifest::FileHandler>());
- }
-
- for (auto& uri_protocol : input->protocol_handlers) {
- output.protocol_handlers.push_back(
- uri_protocol.To<blink::Manifest::ProtocolHandler>());
- }
-
- for (auto& url_handler : input->url_handlers) {
- output.url_handlers.push_back(
- url_handler.To<blink::Manifest::UrlHandler>());
- }
-
- output.note_taking = input->note_taking.To<blink::Manifest::NoteTaking>();
-
- for (auto& related_application : input->related_applications) {
- output.related_applications.push_back(
- related_application.To<blink::Manifest::RelatedApplication>());
- }
-
- output.prefer_related_applications = input->prefer_related_applications;
-
- if (input->has_theme_color)
- output.theme_color = input->theme_color;
-
- if (input->has_background_color)
- output.background_color = input->background_color;
-
- if (!input->gcm_sender_id.IsEmpty()) {
- output.gcm_sender_id = blink::WebString(input->gcm_sender_id).Utf16();
- }
-
- if (!input->scope.IsEmpty())
- output.scope = input->scope;
-
- output.capture_links = input->capture_links;
-
- return output;
-}
-
-blink::Manifest::ImageResource
-TypeConverter<blink::Manifest::ImageResource,
- blink::mojom::blink::ManifestImageResourcePtr>::
- Convert(const blink::mojom::blink::ManifestImageResourcePtr& input) {
- blink::Manifest::ImageResource output;
- if (input.is_null())
- return output;
-
- output.src = input->src;
- output.type = blink::WebString(input->type).Utf16();
-
- for (auto& size : input->sizes)
- output.sizes.push_back(gfx::Size(size));
-
- for (auto purpose : input->purpose)
- output.purpose.push_back(purpose);
-
- return output;
-}
-
-blink::Manifest::ShortcutItem
-TypeConverter<blink::Manifest::ShortcutItem,
- blink::mojom::blink::ManifestShortcutItemPtr>::
- Convert(const blink::mojom::blink::ManifestShortcutItemPtr& input) {
- blink::Manifest::ShortcutItem output;
- if (input.is_null())
- return output;
-
- output.name = blink::WebString(input->name).Utf16();
-
- if (!input->short_name.IsEmpty()) {
- output.short_name = blink::WebString(input->short_name).Utf16();
- }
-
- if (!input->description.IsEmpty()) {
- output.description = blink::WebString(input->description).Utf16();
- }
-
- output.url = input->url;
-
- for (auto& icon : input->icons)
- output.icons.push_back(icon.To<::blink::Manifest::ImageResource>());
-
- return output;
-}
-
-blink::Manifest::ShareTarget
-TypeConverter<blink::Manifest::ShareTarget,
- blink::mojom::blink::ManifestShareTargetPtr>::
- Convert(const blink::mojom::blink::ManifestShareTargetPtr& input) {
- blink::Manifest::ShareTarget output;
- if (input.is_null())
- return output;
-
- output.action = input->action;
- output.method = input->method;
- output.enctype = input->enctype;
-
- output.params = input->params.To<::blink::Manifest::ShareTargetParams>();
-
- return output;
-}
-
-blink::Manifest::ShareTargetParams
-TypeConverter<blink::Manifest::ShareTargetParams,
- blink::mojom::blink::ManifestShareTargetParamsPtr>::
- Convert(const blink::mojom::blink::ManifestShareTargetParamsPtr& input) {
- blink::Manifest::ShareTargetParams output;
- if (input.is_null())
- return output;
-
- if (!input->title.IsEmpty()) {
- output.title = blink::WebString(input->title).Utf16();
- }
-
- if (!input->text.IsEmpty())
- output.text = blink::WebString(input->text).Utf16();
-
- if (!input->url.IsEmpty())
- output.url = blink::WebString(input->url).Utf16();
-
- if (input->files.has_value()) {
- for (auto& file : *input->files)
- output.files.push_back(file.To<::blink::Manifest::FileFilter>());
- }
-
- return output;
-}
-
-blink::Manifest::FileFilter
-TypeConverter<blink::Manifest::FileFilter,
- blink::mojom::blink::ManifestFileFilterPtr>::
- Convert(const blink::mojom::blink::ManifestFileFilterPtr& input) {
- blink::Manifest::FileFilter output;
- if (input.is_null())
- return output;
-
- output.name = blink::WebString(input->name).Utf16();
-
- for (auto& accept : input->accept)
- output.accept.push_back(blink::WebString(accept).Utf16());
-
- return output;
-}
-
-blink::Manifest::FileHandler
-TypeConverter<blink::Manifest::FileHandler,
- blink::mojom::blink::ManifestFileHandlerPtr>::
- Convert(const blink::mojom::blink::ManifestFileHandlerPtr& input) {
- blink::Manifest::FileHandler output;
- if (input.is_null())
- return output;
-
- output.name = blink::WebString(input->name).Utf16();
- output.action = input->action;
- for (const auto& it : input->accept) {
- auto& extensions = output.accept[blink::WebString(it.key).Utf16()];
- for (const auto& extension : it.value)
- extensions.push_back(blink::WebString(extension).Utf16());
- }
-
- return output;
-}
-
-blink::Manifest::ProtocolHandler
-TypeConverter<blink::Manifest::ProtocolHandler,
- blink::mojom::blink::ManifestProtocolHandlerPtr>::
- Convert(const blink::mojom::blink::ManifestProtocolHandlerPtr& input) {
- blink::Manifest::ProtocolHandler output;
- if (input.is_null())
- return output;
- output.protocol = blink::WebString(input->protocol).Utf16();
- output.url = input->url;
- return output;
-}
-
-blink::Manifest::UrlHandler
-TypeConverter<blink::Manifest::UrlHandler,
- blink::mojom::blink::ManifestUrlHandlerPtr>::
- Convert(const blink::mojom::blink::ManifestUrlHandlerPtr& input) {
- blink::Manifest::UrlHandler output;
- if (input.is_null())
- return output;
-
- if (!output.origin.opaque()) {
- output.origin = input->origin->ToUrlOrigin();
- output.has_origin_wildcard = input->has_origin_wildcard;
- }
-
- return output;
-}
-
-blink::Manifest::NoteTaking
-TypeConverter<blink::Manifest::NoteTaking,
- blink::mojom::blink::ManifestNoteTakingPtr>::
- Convert(const blink::mojom::blink::ManifestNoteTakingPtr& input) {
- blink::Manifest::NoteTaking output;
- if (input.is_null())
- return output;
-
- if (!input->new_note_url.IsEmpty())
- output.new_note_url = input->new_note_url;
-
- return output;
-}
-
-blink::Manifest::RelatedApplication
-TypeConverter<blink::Manifest::RelatedApplication,
- blink::mojom::blink::ManifestRelatedApplicationPtr>::
- Convert(const blink::mojom::blink::ManifestRelatedApplicationPtr& input) {
- blink::Manifest::RelatedApplication output;
- if (input.is_null())
- return output;
-
- if (!input->platform.IsEmpty()) {
- output.platform = blink::WebString(input->platform).Utf16();
- }
-
- if (input->url.has_value())
- output.url = *input->url;
-
- if (!input->id.IsEmpty())
- output.id = blink::WebString(input->id).Utf16();
-
- return output;
-}
-
-} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h b/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h
deleted file mode 100644
index 4cb7cb0b845..00000000000
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_MANIFEST_TYPE_CONVERTERS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_MANIFEST_TYPE_CONVERTERS_H_
-
-#include "third_party/blink/public/common/manifest/manifest.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink-forward.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-struct Manifest;
-}
-
-namespace mojo {
-
-// TODO(crbug.com/704441): These converters are temporary to help the manifest
-// migration until content::PushMessagingClient is moved to blink.
-
-template <>
-struct MODULES_EXPORT
- TypeConverter<blink::Manifest, blink::mojom::blink::ManifestPtr> {
- static blink::Manifest Convert(const blink::mojom::blink::ManifestPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::ImageResource,
- blink::mojom::blink::ManifestImageResourcePtr> {
- static blink::Manifest::ImageResource Convert(
- const blink::mojom::blink::ManifestImageResourcePtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::ShortcutItem,
- blink::mojom::blink::ManifestShortcutItemPtr> {
- static blink::Manifest::ShortcutItem Convert(
- const blink::mojom::blink::ManifestShortcutItemPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::ShareTarget,
- blink::mojom::blink::ManifestShareTargetPtr> {
- static blink::Manifest::ShareTarget Convert(
- const blink::mojom::blink::ManifestShareTargetPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::ShareTargetParams,
- blink::mojom::blink::ManifestShareTargetParamsPtr> {
- static blink::Manifest::ShareTargetParams Convert(
- const blink::mojom::blink::ManifestShareTargetParamsPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::FileFilter,
- blink::mojom::blink::ManifestFileFilterPtr> {
- static blink::Manifest::FileFilter Convert(
- const blink::mojom::blink::ManifestFileFilterPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::FileHandler,
- blink::mojom::blink::ManifestFileHandlerPtr> {
- static blink::Manifest::FileHandler Convert(
- const blink::mojom::blink::ManifestFileHandlerPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::ProtocolHandler,
- blink::mojom::blink::ManifestProtocolHandlerPtr> {
- static blink::Manifest::ProtocolHandler Convert(
- const blink::mojom::blink::ManifestProtocolHandlerPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::UrlHandler,
- blink::mojom::blink::ManifestUrlHandlerPtr> {
- static blink::Manifest::UrlHandler Convert(
- const blink::mojom::blink::ManifestUrlHandlerPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::NoteTaking,
- blink::mojom::blink::ManifestNoteTakingPtr> {
- static blink::Manifest::NoteTaking Convert(
- const blink::mojom::blink::ManifestNoteTakingPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::Manifest::RelatedApplication,
- blink::mojom::blink::ManifestRelatedApplicationPtr> {
- static blink::Manifest::RelatedApplication Convert(
- const blink::mojom::blink::ManifestRelatedApplicationPtr& input);
-};
-
-} // namespace mojo
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_MANIFEST_TYPE_CONVERTERS_H_
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters_unittest.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters_unittest.cc
deleted file mode 100644
index 8ffdf17d31c..00000000000
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters_unittest.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/manifest/manifest_type_converters.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "mojo/public/cpp/bindings/type_converter.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
-#include "third_party/blink/renderer/modules/manifest/manifest_parser.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
-
-namespace blink {
-
-class ManifestTypeConvertersTest : public testing::Test {
- protected:
- ManifestTypeConvertersTest() {}
- ~ManifestTypeConvertersTest() override {}
-
- mojom::blink::ManifestPtr Load(const String& json) {
- KURL url("http://example.com");
- ManifestParser parser(json, url, url, /*feature_context=*/nullptr);
- parser.Parse();
-
- Vector<mojom::blink::ManifestErrorPtr> errors;
- parser.TakeErrors(&errors);
-
- EXPECT_EQ(0u, errors.size());
- EXPECT_FALSE(parser.failed());
-
- return parser.manifest().Clone();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ManifestTypeConvertersTest);
-};
-
-TEST_F(ManifestTypeConvertersTest, NoFileHandlerDoesNotConvert) {
- const String json = "{\"start_url\": \"/\"}";
- const mojom::blink::ManifestPtr& mojo_manifest = Load(json);
-
- auto manifest = mojo_manifest.To<blink::Manifest>();
- EXPECT_EQ(0u, manifest.file_handlers.size());
-}
-
-TEST_F(ManifestTypeConvertersTest, BasicFileHandlerIsCorrectlyConverted) {
- const mojom::blink::ManifestPtr& mojo_manifest = Load(
- "{"
- " \"file_handlers\": ["
- " {"
- " \"name\": \"name\","
- " \"action\": \"/files\","
- " \"accept\": {"
- " \"image/png\": ["
- " \".png\""
- " ]"
- " }"
- " }"
- " ]"
- "}");
-
- auto manifest = mojo_manifest.To<blink::Manifest>();
- ASSERT_EQ(manifest.file_handlers.size(), 1u);
- EXPECT_EQ(manifest.file_handlers[0].action, "http://example.com/files");
- EXPECT_TRUE(base::EqualsASCII(manifest.file_handlers[0].name, "name"));
- ASSERT_EQ(manifest.file_handlers[0].accept.size(), 1u);
-
- std::u16string mime = u"image/png";
- ASSERT_EQ(manifest.file_handlers[0].accept.count(mime), 1u);
- EXPECT_EQ(manifest.file_handlers[0].accept[mime].size(), 1u);
- EXPECT_TRUE(
- base::EqualsASCII(manifest.file_handlers[0].accept[mime][0], ".png"));
-}
-
-TEST_F(ManifestTypeConvertersTest, NoShortcutsDoesNotConvert) {
- const String json = "{\"start_url\": \"/\"}";
- const mojom::blink::ManifestPtr& mojo_manifest = Load(json);
-
- auto manifest = mojo_manifest.To<blink::Manifest>();
- EXPECT_TRUE(manifest.shortcuts.empty());
-}
-
-TEST_F(ManifestTypeConvertersTest, BasicShortcutIsCorrectlyConverted) {
- const mojom::blink::ManifestPtr& mojo_manifest = Load(
- "{"
- " \"shortcuts\": ["
- " {"
- " \"name\": \"name\", "
- " \"short_name\": \"short_name\","
- " \"url\": \"url\", "
- " \"icons\": ["
- " {"
- " \"src\": \"image.jpg\""
- " }"
- " ] "
- " }"
- " ] "
- "}");
-
- auto manifest = mojo_manifest.To<blink::Manifest>();
- ASSERT_FALSE(manifest.shortcuts.empty());
-
- ASSERT_EQ(manifest.shortcuts.size(), 1u);
- EXPECT_TRUE(base::EqualsASCII(manifest.shortcuts[0].name, "name"));
- EXPECT_EQ(manifest.shortcuts[0].short_name, u"short_name");
- EXPECT_EQ(manifest.shortcuts[0].url.spec(), "http://example.com/url");
-
- ASSERT_EQ(manifest.shortcuts[0].icons.size(), 1u);
- ASSERT_EQ(manifest.shortcuts[0].icons[0].src.spec(),
- "http://example.com/image.jpg");
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.cc
index 9c8e5a8026a..5713a45bfd7 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/manifest/manifest_uma_util.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
namespace blink {
@@ -12,6 +13,7 @@ namespace {
static const char kUMANameParseSuccess[] = "Manifest.ParseSuccess";
static const char kUMANameFetchResult[] = "Manifest.FetchResult";
+static const char kUMAIdParseResult[] = "Manifest.ParseIdResult";
// Enum for UMA purposes, make sure you update histograms.xml if you add new
// result types. Never delete or reorder an entry; only add new entries
@@ -66,6 +68,10 @@ void ManifestUmaUtil::ParseFailed() {
UMA_HISTOGRAM_BOOLEAN(kUMANameParseSuccess, false);
}
+void ManifestUmaUtil::ParseIdResult(ParseIdResultType result) {
+ base::UmaHistogramEnumeration(kUMAIdParseResult, result);
+}
+
void ManifestUmaUtil::FetchSucceeded() {
UMA_HISTOGRAM_ENUMERATION(kUMANameFetchResult, MANIFEST_FETCH_SUCCESS,
MANIFEST_FETCH_RESULT_TYPE_COUNT);
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.h b/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.h
index 6d1052dd1f0..3c1bf2d69cb 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.h
@@ -17,6 +17,16 @@ class ManifestUmaUtil {
FETCH_UNSPECIFIED_REASON
};
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class ParseIdResultType {
+ kSucceed = 0,
+ kDefaultToStartUrl = 1,
+ kInvalidStartUrl = 2,
+ kFeatureDisabled = 3,
+ kMaxValue = kFeatureDisabled,
+ };
+
// Record that the Manifest was successfully parsed. If it is an empty
// Manifest, it will recorded as so and nothing will happen. Otherwise, the
// presence of each properties will be recorded.
@@ -31,6 +41,9 @@ class ManifestUmaUtil {
// Record that the Manifest fetching failed and takes the |reason| why it
// failed.
static void FetchFailed(FetchFailureReason reason);
+
+ // Record the result of parsing manifest id.
+ static void ParseIdResult(ParseIdResultType result);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_mixer_manager_test.cc b/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_mixer_manager_test.cc
index 4d13e66b6b1..aeca5c9f383 100644
--- a/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_mixer_manager_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_mixer_manager_test.cc
@@ -110,7 +110,7 @@ class AudioRendererMixerManagerTest : public testing::Test {
}
// Number of instantiated mixers.
- int mixer_count() { return manager_->mixers_.size(); }
+ size_t mixer_count() { return manager_->mixers_.size(); }
protected:
scoped_refptr<media::MockAudioRendererSink> GetSink(
@@ -154,7 +154,7 @@ class AudioRendererMixerManagerTest : public testing::Test {
// respect to the explicit ref counting done.
TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) {
// There should be no mixers outstanding to start with.
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params1(media::AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -163,17 +163,17 @@ TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) {
GetMixer(kFrameToken, params1, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
// The same parameters should return the same mixer1.
EXPECT_EQ(mixer1,
GetMixer(kFrameToken, params1, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kExistingSink));
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
// Return the extra mixer we just acquired.
ReturnMixer(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
media::AudioParameters params2(AudioParameters::AUDIO_PCM_LINEAR,
kAnotherChannelLayout, kSampleRate * 2,
@@ -182,22 +182,22 @@ TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) {
GetMixer(kFrameToken, params2, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer2);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
// Different parameters should result in a different mixer1.
EXPECT_NE(mixer1, mixer2);
// Return both outstanding mixers.
ReturnMixer(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify GetMixer() correctly deduplicates mixer with irrelevant AudioParameter
// differences.
TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -205,7 +205,7 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
GetMixer(kFrameToken, params1, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
// Different sample rates, formats, bit depths, and buffer sizes should not
// result in a different mixer.
@@ -216,9 +216,9 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
GetMixer(kFrameToken, params2, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kExistingSink);
EXPECT_EQ(mixer1, mixer2);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
// Modify some parameters that do matter: channel layout
media::AudioParameters params3(AudioParameters::AUDIO_PCM_LOW_LATENCY,
@@ -229,13 +229,13 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
GetMixer(kFrameToken, params3, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
EXPECT_NE(mixer1, mixer3);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
ReturnMixer(mixer3);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
// Return final mixer.
ReturnMixer(mixer1);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify CreateInput() provides AudioRendererMixerInput with the appropriate
@@ -247,14 +247,14 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
kChannelLayout, kSampleRate, kBufferSize);
// Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::FakeAudioRenderCallback callback(0, kSampleRate);
mock_sink_ = CreateNormalSink();
EXPECT_CALL(*mock_sink_, Start()).Times(1);
auto input =
CreateInputHelper(kFrameToken, base::UnguessableToken(), kDefaultDeviceId,
AudioLatency::LATENCY_PLAYBACK, params, &callback);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::FakeAudioRenderCallback another_callback(1, kSampleRate);
EXPECT_FALSE(!!mock_sink_);
@@ -263,22 +263,22 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
auto another_input = CreateInputHelper(
kAnotherFrameToken, base::UnguessableToken(), kDefaultDeviceId,
AudioLatency::LATENCY_PLAYBACK, params, &another_callback);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
// Implicitly test that AudioRendererMixerInput was provided with the expected
// callbacks needed to acquire an AudioRendererMixer and return it.
input->Start();
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
another_input->Start();
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
// Destroying the inputs should destroy the mixers.
input->Stop();
input = nullptr;
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
another_input->Stop();
another_input = nullptr;
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify CreateInput() provided with session id creates AudioRendererMixerInput
@@ -291,68 +291,68 @@ TEST_F(AudioRendererMixerManagerTest, DISABLED_CreateInputWithSessionId) {
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
media::FakeAudioRenderCallback callback(0, kSampleRate);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
// Empty device id, zero session id;
auto input_to_default_device = CreateInputHelper(
kFrameToken, base::UnguessableToken(), // session_id
std::string(), AudioLatency::LATENCY_PLAYBACK, params, &callback);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
// Specific device id, zero session id;
auto input_to_another_device = CreateInputHelper(
kFrameToken, base::UnguessableToken(), // session_id
kMatchedDeviceId, AudioLatency::LATENCY_PLAYBACK, params, &callback);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
// Specific device id, non-zero session id (to be ignored);
auto input_to_matched_device = CreateInputHelper(
kFrameToken,
base::UnguessableToken::Create(), // session id
kAnotherDeviceId, AudioLatency::LATENCY_PLAYBACK, params, &callback);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
// Empty device id, non-zero session id;
auto input_to_matched_device_with_session_id = CreateInputHelper(
kFrameToken,
base::UnguessableToken::Create(), // session id
std::string(), AudioLatency::LATENCY_PLAYBACK, params, &callback);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
// Implicitly test that AudioRendererMixerInput was provided with the expected
// callbacks needed to acquire an AudioRendererMixer and return it.
input_to_default_device->Start();
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
input_to_another_device->Start();
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
input_to_matched_device->Start();
- EXPECT_EQ(3, mixer_count());
+ EXPECT_EQ(3u, mixer_count());
// Should go to the same device as the input above.
input_to_matched_device_with_session_id->Start();
- EXPECT_EQ(3, mixer_count());
+ EXPECT_EQ(3u, mixer_count());
// Destroying the inputs should destroy the mixers.
input_to_default_device->Stop();
input_to_default_device = nullptr;
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
input_to_another_device->Stop();
input_to_another_device = nullptr;
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
input_to_matched_device->Stop();
input_to_matched_device = nullptr;
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
input_to_matched_device_with_session_id->Stop();
input_to_matched_device_with_session_id = nullptr;
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify GetMixer() correctly creates different mixers with the same
// parameters, but different device ID.
TEST_F(AudioRendererMixerManagerTest, MixerDevices) {
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -360,25 +360,25 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) {
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kAnotherDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer2);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
EXPECT_NE(mixer1, mixer2);
ReturnMixer(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify GetMixer() correctly deduplicate mixers with the same
// parameters and default device ID, even if one is "" and one is "default".
TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentDefaultDeviceIDs) {
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -386,25 +386,25 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentDefaultDeviceIDs) {
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
std::string(), SinkUseState::kExistingSink);
ASSERT_TRUE(mixer2);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
EXPECT_EQ(mixer1, mixer2);
ReturnMixer(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify that GetMixer() correctly returns a null mixer and an appropriate
// status code when a nonexistent device is requested.
TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) {
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -416,13 +416,13 @@ TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) {
EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
device_info.device_status());
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify GetMixer() correctly deduplicate mixers basing on latency
// requirements.
TEST_F(AudioRendererMixerManagerTest, LatencyMixing) {
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -430,58 +430,58 @@ TEST_F(AudioRendererMixerManagerTest, LatencyMixing) {
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kExistingSink);
ASSERT_TRUE(mixer2);
EXPECT_EQ(mixer1, mixer2); // Same latency => same mixer.
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
media::AudioRendererMixer* mixer3 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_RTC, kDefaultDeviceId,
SinkUseState::kNewSink);
ASSERT_TRUE(mixer3);
EXPECT_NE(mixer1, mixer3);
- EXPECT_EQ(2, mixer_count()); // Another latency => another mixer.
+ EXPECT_EQ(2u, mixer_count()); // Another latency => another mixer.
media::AudioRendererMixer* mixer4 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_RTC, kDefaultDeviceId,
SinkUseState::kExistingSink);
EXPECT_EQ(mixer3, mixer4);
- EXPECT_EQ(2, mixer_count()); // Same latency => same mixer.
+ EXPECT_EQ(2u, mixer_count()); // Same latency => same mixer.
media::AudioRendererMixer* mixer5 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_INTERACTIVE,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer5);
- EXPECT_EQ(3, mixer_count()); // Another latency => another mixer.
+ EXPECT_EQ(3u, mixer_count()); // Another latency => another mixer.
media::AudioRendererMixer* mixer6 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_INTERACTIVE,
kDefaultDeviceId, SinkUseState::kExistingSink);
EXPECT_EQ(mixer5, mixer6);
- EXPECT_EQ(3, mixer_count()); // Same latency => same mixer.
+ EXPECT_EQ(3u, mixer_count()); // Same latency => same mixer.
ReturnMixer(mixer1);
- EXPECT_EQ(3, mixer_count());
+ EXPECT_EQ(3u, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
ReturnMixer(mixer3);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
ReturnMixer(mixer4);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer5);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer6);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify GetMixer() correctly deduplicate mixers basing on the effects
// requirements.
TEST_F(AudioRendererMixerManagerTest, EffectsMixing) {
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBufferSize);
@@ -490,14 +490,14 @@ TEST_F(AudioRendererMixerManagerTest, EffectsMixing) {
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kExistingSink);
ASSERT_TRUE(mixer2);
EXPECT_EQ(mixer1, mixer2); // Same effects => same mixer.
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
params.set_effects(2);
media::AudioRendererMixer* mixer3 =
@@ -505,39 +505,39 @@ TEST_F(AudioRendererMixerManagerTest, EffectsMixing) {
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer3);
EXPECT_NE(mixer1, mixer3);
- EXPECT_EQ(2, mixer_count()); // Another effects => another mixer.
+ EXPECT_EQ(2u, mixer_count()); // Another effects => another mixer.
media::AudioRendererMixer* mixer4 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kExistingSink);
EXPECT_EQ(mixer3, mixer4);
- EXPECT_EQ(2, mixer_count()); // Same effects => same mixer.
+ EXPECT_EQ(2u, mixer_count()); // Same effects => same mixer.
params.set_effects(3);
media::AudioRendererMixer* mixer5 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kNewSink);
ASSERT_TRUE(mixer5);
- EXPECT_EQ(3, mixer_count()); // Another effects => another mixer.
+ EXPECT_EQ(3u, mixer_count()); // Another effects => another mixer.
media::AudioRendererMixer* mixer6 =
GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
kDefaultDeviceId, SinkUseState::kExistingSink);
EXPECT_EQ(mixer5, mixer6);
- EXPECT_EQ(3, mixer_count()); // Same effects => same mixer.
+ EXPECT_EQ(3u, mixer_count()); // Same effects => same mixer.
ReturnMixer(mixer1);
- EXPECT_EQ(3, mixer_count());
+ EXPECT_EQ(3u, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
ReturnMixer(mixer3);
- EXPECT_EQ(2, mixer_count());
+ EXPECT_EQ(2u, mixer_count());
ReturnMixer(mixer4);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer5);
- EXPECT_EQ(1, mixer_count());
+ EXPECT_EQ(1u, mixer_count());
ReturnMixer(mixer6);
- EXPECT_EQ(0, mixer_count());
+ EXPECT_EQ(0u, mixer_count());
}
// Verify output bufer size of the mixer is correctly adjusted for Playback
diff --git a/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache.cc b/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache.cc
index a29c0fe37ec..1e7371a1423 100644
--- a/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache.cc
+++ b/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache.cc
@@ -8,10 +8,10 @@
#include <memory>
#include <utility>
+#include "base/containers/cxx20_erase.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/trace_event.h"
#include "media/audio/audio_device_description.h"
diff --git a/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache_test.cc b/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache_test.cc
index 522049e0264..cdbe7d02467 100644
--- a/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media/audio/audio_renderer_sink_cache_test.cc
@@ -54,7 +54,7 @@ class AudioRendererSinkCacheTest : public testing::Test {
}
protected:
- int sink_count() {
+ size_t sink_count() {
DCHECK(task_runner_->BelongsToCurrentThread());
return cache_->GetCacheSizeForTesting();
}
@@ -108,19 +108,19 @@ class AudioRendererSinkCacheTest : public testing::Test {
// Verify that normal get/release sink sequence works.
TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
// Verify that a new sink is successfully created.
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
scoped_refptr<media::AudioRendererSink> sink =
cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
ExpectNotToStop(sink.get()); // Cache should not stop sinks marked as used.
EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Verify that another sink with the same key is successfully created
scoped_refptr<media::AudioRendererSink> another_sink =
cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
ExpectNotToStop(another_sink.get());
EXPECT_EQ(kDefaultDeviceId, another_sink->GetOutputDeviceInfo().device_id());
- EXPECT_EQ(2, sink_count());
+ EXPECT_EQ(2u, sink_count());
EXPECT_NE(sink, another_sink);
// Verify that another sink with a different kay is successfully created.
@@ -129,13 +129,13 @@ TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
ExpectNotToStop(yet_another_sink.get());
EXPECT_EQ(kAnotherDeviceId,
yet_another_sink->GetOutputDeviceInfo().device_id());
- EXPECT_EQ(3, sink_count());
+ EXPECT_EQ(3u, sink_count());
EXPECT_NE(sink, yet_another_sink);
EXPECT_NE(another_sink, yet_another_sink);
// Verify that the first sink is successfully deleted.
cache_->ReleaseSink(sink.get());
- EXPECT_EQ(2, sink_count());
+ EXPECT_EQ(2u, sink_count());
sink = nullptr;
// Make sure we deleted the right sink, and the memory for the rest is not
@@ -146,77 +146,77 @@ TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
// Verify that the second sink is successfully deleted.
cache_->ReleaseSink(another_sink.get());
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
EXPECT_EQ(kAnotherDeviceId,
yet_another_sink->GetOutputDeviceInfo().device_id());
cache_->ReleaseSink(yet_another_sink.get());
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
}
// Verify that the sink created with GetSinkInfo() is reused when possible.
TEST_F(AudioRendererSinkCacheTest, GetDeviceInfo) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// The info on the same device is requested, so no new sink is created.
media::OutputDeviceInfo one_more_device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
// Aquire the sink that was created on GetSinkInfo().
scoped_refptr<media::AudioRendererSink> sink =
cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
EXPECT_EQ(device_info.device_id(), sink->GetOutputDeviceInfo().device_id());
// Now the sink is in used, but we can still get the device info out of it, no
// new sink is created.
one_more_device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
// Request sink for the same device. The first sink is in use, so a new one
// should be created.
scoped_refptr<media::AudioRendererSink> another_sink =
cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
- EXPECT_EQ(2, sink_count());
+ EXPECT_EQ(2u, sink_count());
EXPECT_EQ(device_info.device_id(),
another_sink->GetOutputDeviceInfo().device_id());
}
// Verify that the sink created with GetSinkInfo() is deleted if unused.
TEST_F(AudioRendererSinkCacheTest, GarbageCollection) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
media::OutputDeviceInfo another_device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kAnotherDeviceId);
- EXPECT_EQ(2, sink_count());
+ EXPECT_EQ(2u, sink_count());
// Wait for garbage collection. Doesn't actually sleep, just advances the mock
// clock.
task_runner_->FastForwardBy(kDeleteTimeout);
// All the sinks should be garbage-collected by now.
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
}
// Verify that the sink created with GetSinkInfo() is not deleted if used within
// the timeout.
TEST_F(AudioRendererSinkCacheTest, NoGarbageCollectionForUsedSink) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Wait less than garbage collection timeout.
base::TimeDelta wait_a_bit =
@@ -224,31 +224,31 @@ TEST_F(AudioRendererSinkCacheTest, NoGarbageCollectionForUsedSink) {
task_runner_->FastForwardBy(wait_a_bit);
// Sink is not deleted yet.
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Request it:
scoped_refptr<media::AudioRendererSink> sink =
cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Wait more to hit garbage collection timeout.
task_runner_->FastForwardBy(kDeleteTimeout);
// The sink is still in place.
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
}
// Verify that the sink created with GetSinkInfo() is not cached if it is
// unhealthy.
TEST_F(AudioRendererSinkCacheTest, UnhealthySinkIsNotCached) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kUnhealthyDeviceId);
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
scoped_refptr<media::AudioRendererSink> sink =
cache_->GetSink(kFrameToken, kUnhealthyDeviceId).get();
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
}
// Verify that a sink created with GetSinkInfo() is stopped even if it's
@@ -310,39 +310,39 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkUsingSessionIdIsStopped) {
// Verify that cache works fine if a sink scheduled for deletion is acquired and
// released before deletion timeout elapses.
TEST_F(AudioRendererSinkCacheTest, ReleaseSinkBeforeScheduledDeletion) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
base::Thread thread("timeout_thread");
thread.Start();
media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
- EXPECT_EQ(1, sink_count()); // This sink is scheduled for deletion now.
+ EXPECT_EQ(1u, sink_count()); // This sink is scheduled for deletion now.
// Request it:
scoped_refptr<media::AudioRendererSink> sink =
cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
ExpectNotToStop(sink.get());
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Release it:
cache_->ReleaseSink(sink.get());
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
media::OutputDeviceInfo another_device_info = cache_->GetSinkInfo(
kFrameToken, base::UnguessableToken(), kAnotherDeviceId);
- EXPECT_EQ(1, sink_count()); // This sink is scheduled for deletion now.
+ EXPECT_EQ(1u, sink_count()); // This sink is scheduled for deletion now.
task_runner_->FastForwardBy(kDeleteTimeout);
// Nothing crashed and the second sink deleted on schedule.
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
}
// Check that a sink created on one thread in response to GetSinkInfo can be
// used on another thread.
TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
base::Thread thread1("thread1");
thread1.Start();
@@ -357,7 +357,7 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
base::Unretained(cache_.get()), kFrameToken,
base::UnguessableToken(), kDefaultDeviceId));
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Request the sink on the second thread.
media::AudioRendererSink* sink;
@@ -368,7 +368,7 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
kDefaultDeviceId, &sink));
EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Request device information on the first thread again.
PostAndWaitUntilDone(
@@ -376,7 +376,7 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
base::BindOnce(base::IgnoreResult(&AudioRendererSinkCache::GetSinkInfo),
base::Unretained(cache_.get()), kFrameToken,
base::UnguessableToken(), kDefaultDeviceId));
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
// Release the sink on the second thread.
PostAndWaitUntilDone(
@@ -384,37 +384,37 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
base::BindOnce(&AudioRendererSinkCache::ReleaseSink,
base::Unretained(cache_.get()), base::RetainedRef(sink)));
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
}
TEST_F(AudioRendererSinkCacheTest, StopsAndDropsSinks) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
scoped_refptr<media::AudioRendererSink> sink1 =
cache_->GetSink(kFrameToken, "device1").get();
scoped_refptr<media::AudioRendererSink> sink2 =
cache_->GetSink(kFrameToken, "device2").get();
- EXPECT_EQ(2, sink_count());
+ EXPECT_EQ(2u, sink_count());
EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink1.get()), Stop());
EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink2.get()), Stop());
DropSinksForFrame(kFrameToken);
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
}
TEST_F(AudioRendererSinkCacheTest, StopsAndDropsCorrectSinks) {
- EXPECT_EQ(0, sink_count());
+ EXPECT_EQ(0u, sink_count());
scoped_refptr<media::AudioRendererSink> sink1 =
cache_->GetSink(kFrameToken, "device1").get();
scoped_refptr<media::AudioRendererSink> another_sink =
cache_->GetSink(LocalFrameToken(), "device1").get();
scoped_refptr<media::AudioRendererSink> sink2 =
cache_->GetSink(kFrameToken, "device2").get();
- EXPECT_EQ(3, sink_count());
+ EXPECT_EQ(3u, sink_count());
EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink1.get()), Stop());
EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink2.get()), Stop());
DropSinksForFrame(kFrameToken);
- EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(1u, sink_count());
EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(another_sink.get()),
Stop());
}
diff --git a/chromium/third_party/blink/renderer/modules/media/audio/web_audio_output_ipc_factory_test.cc b/chromium/third_party/blink/renderer/modules/media/audio/web_audio_output_ipc_factory_test.cc
index 66884afcd9e..23cd4366c5d 100644
--- a/chromium/third_party/blink/renderer/modules/media/audio/web_audio_output_ipc_factory_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media/audio/web_audio_output_ipc_factory_test.cc
@@ -179,7 +179,7 @@ TEST_F(WebAudioOutputIPCFactoryTest, SeveralFactories) {
WebAudioOutputIPCFactory ipc_factory(io_thread->task_runner());
- for (size_t i = 0; i < n_factories; i++) {
+ for (int i = 0; i < n_factories; i++) {
ipc_factory.RegisterRemoteFactory(TokenFromInt(kRenderFrameId + i),
&interface_broker);
}
@@ -207,7 +207,7 @@ TEST_F(WebAudioOutputIPCFactoryTest, SeveralFactories) {
ipc_factory.CreateAudioOutputIPC(TokenFromInt(kRenderFrameId + 2))));
run_loop2.Run();
- for (size_t i = 0; i < n_factories; i++) {
+ for (int i = 0; i < n_factories; i++) {
if (i == 1)
continue;
ipc_factory.MaybeDeregisterRemoteFactory(TokenFromInt(i));
diff --git a/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util.cc b/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util.cc
index 9618f34a260..c50f885d93a 100644
--- a/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util.cc
+++ b/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util.cc
@@ -12,9 +12,12 @@
#include "base/metrics/histogram_macros.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/media_log.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_media_player_encrypted_media_client.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace {
@@ -67,9 +70,10 @@ media::mojom::MediaURLScheme GetMediaURLScheme(const WebURL& url) {
return media::mojom::MediaURLScheme::kContentId;
// Some internals pages and extension pages play media.
- if (url.ProtocolIs("chrome"))
+ KURL kurl(url);
+ if (SchemeRegistry::IsWebUIScheme(kurl.Protocol()))
return media::mojom::MediaURLScheme::kChrome;
- if (url.ProtocolIs("chrome-extension"))
+ if (CommonSchemeRegistry::IsExtensionScheme(kurl.Protocol().Ascii()))
return media::mojom::MediaURLScheme::kChromeExtension;
return media::mojom::MediaURLScheme::kUnknown;
@@ -106,6 +110,7 @@ WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
case media::PIPELINE_ERROR_DECODE:
case media::PIPELINE_ERROR_ABORT:
case media::PIPELINE_ERROR_INVALID_STATE:
+ case media::PIPELINE_ERROR_HARDWARE_CONTEXT_RESET:
case media::CHUNK_DEMUXER_ERROR_APPEND_FAILED:
case media::CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR:
case media::AUDIO_RENDERER_ERROR:
diff --git a/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util_unittest.cc b/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util_unittest.cc
index 560f2f50ac6..c3e7120eef0 100644
--- a/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/media/webmediaplayer_util_unittest.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
namespace blink {
@@ -45,10 +47,14 @@ TEST(GetMediaURLScheme, Android) {
}
TEST(GetMediaURLScheme, Chrome) {
+ SchemeRegistry::RegisterURLSchemeAsWebUIForTest("chrome");
+ CommonSchemeRegistry::RegisterURLSchemeAsExtension("chrome-extension");
EXPECT_EQ(media::mojom::MediaURLScheme::kChrome,
GetMediaURLScheme(KURL("chrome://abc.123")));
EXPECT_EQ(media::mojom::MediaURLScheme::kChromeExtension,
GetMediaURLScheme(KURL("chrome-extension://abc.123")));
+ CommonSchemeRegistry::RemoveURLSchemeAsExtensionForTest("chrome-extension");
+ SchemeRegistry::RemoveURLSchemeAsWebUIForTest("chrome");
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_capabilities/idls.gni b/chromium/third_party/blink/renderer/modules/media_capabilities/idls.gni
deleted file mode 100644
index 0ebd31bef06..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_capabilities/idls.gni
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "media_capabilities.idl" ]
-
-modules_dictionary_idl_files = [
- "audio_configuration.idl",
- "key_system_track_configuration.idl",
- "media_configuration.idl",
- "media_capabilities_decoding_info.idl",
- "media_capabilities_info.idl",
- "media_capabilities_key_system_configuration.idl",
- "media_decoding_configuration.idl",
- "media_encoding_configuration.idl",
- "video_configuration.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_media_capabilities.idl",
- "worker_navigator_media_capabilities.idl",
-]
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 d40f3005ab1..66a0f658c07 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
@@ -70,8 +70,8 @@
#include "third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_info.h"
#include "third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h"
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
-#include "third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h"
#include "third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.h"
+#include "third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -147,6 +147,16 @@ MediaCapabilitiesDecodingInfo* CreateDecodingInfoWith(bool value) {
return info;
}
+// Utility function that will create a MediaCapabilitiesInfo object with
+// all the values set to either true or false.
+MediaCapabilitiesInfo* CreateEncodingInfoWith(bool value) {
+ MediaCapabilitiesInfo* info = MediaCapabilitiesInfo::Create();
+ info->setSupported(value);
+ info->setSmooth(value);
+ info->setPowerEfficient(value);
+ return info;
+}
+
ScriptPromise CreateResolvedPromiseToDecodingInfoWith(
bool value,
ScriptState* script_state,
@@ -258,6 +268,31 @@ bool IsValidMediaConfiguration(const MediaConfiguration* configuration) {
return configuration->hasAudio() || configuration->hasVideo();
}
+bool IsValidVideoConfiguration(const VideoConfiguration* configuration,
+ bool is_webrtc) {
+ DCHECK(configuration->hasContentType());
+ if (!IsValidMimeType(configuration->contentType(), kVideoMimeTypePrefix,
+ is_webrtc))
+ return false;
+
+ DCHECK(configuration->hasFramerate());
+ if (!IsValidFrameRate(configuration->framerate()))
+ return false;
+
+ return true;
+}
+
+bool IsValidAudioConfiguration(const AudioConfiguration* configuration,
+ bool is_webrtc) {
+ DCHECK(configuration->hasContentType());
+
+ if (!IsValidMimeType(configuration->contentType(), kAudioMimeTypePrefix,
+ is_webrtc))
+ return false;
+
+ return true;
+}
+
bool IsValidMediaDecodingConfiguration(
const MediaDecodingConfiguration* configuration,
bool is_webrtc,
@@ -294,30 +329,43 @@ bool IsValidMediaDecodingConfiguration(
}
}
- return true;
-}
-
-bool IsValidVideoConfiguration(const VideoConfiguration* configuration,
- bool is_webrtc) {
- DCHECK(configuration->hasContentType());
- if (!IsValidMimeType(configuration->contentType(), kVideoMimeTypePrefix,
- is_webrtc))
+ if (configuration->hasVideo() &&
+ !IsValidVideoConfiguration(configuration->video(), is_webrtc)) {
+ *message = "The video configuration dictionary is not valid.";
return false;
+ }
- DCHECK(configuration->hasFramerate());
- if (!IsValidFrameRate(configuration->framerate()))
+ if (configuration->hasAudio() &&
+ !IsValidAudioConfiguration(configuration->audio(), is_webrtc)) {
+ *message = "The audio configuration dictionary is not valid.";
return false;
+ }
return true;
}
-bool IsValidAudioConfiguration(const AudioConfiguration* configuration,
- bool is_webrtc) {
- DCHECK(configuration->hasContentType());
+bool IsValidMediaEncodingConfiguration(
+ const MediaEncodingConfiguration* configuration,
+ bool is_webrtc,
+ String* message) {
+ if (!IsValidMediaConfiguration(configuration)) {
+ *message =
+ "The configuration dictionary has neither |video| nor |audio| "
+ "specified and needs at least one of them.";
+ return false;
+ }
- if (!IsValidMimeType(configuration->contentType(), kAudioMimeTypePrefix,
- is_webrtc))
+ if (configuration->hasVideo() &&
+ !IsValidVideoConfiguration(configuration->video(), is_webrtc)) {
+ *message = "The video configuration dictionary is not valid.";
return false;
+ }
+
+ if (configuration->hasAudio() &&
+ !IsValidAudioConfiguration(configuration->audio(), is_webrtc)) {
+ *message = "The audio configuration dictionary is not valid.";
+ return false;
+ }
return true;
}
@@ -412,16 +460,17 @@ bool CheckMseSupport(const String& mime_type, const String& codec) {
// Media MIME API expects a vector of codec strings. We query audio and video
// separately, so |codec_string|.size() should always be 1 or 0 (when no
// codecs parameter is required for the given mime type).
- std::vector<std::string> codec_vector;
+ base::span<const std::string> codecs;
+ const std::string codec_ascii = codec.Ascii();
if (!codec.Ascii().empty())
- codec_vector.push_back(codec.Ascii());
+ codecs = base::make_span(&codec_ascii, 1);
- if (media::IsSupported != media::StreamParserFactory::IsTypeSupported(
- mime_type.Ascii(), codec_vector)) {
+ if (media::IsSupported !=
+ media::StreamParserFactory::IsTypeSupported(mime_type.Ascii(), codecs)) {
DVLOG(2) << __func__
<< " MSE does not support the content type: " << mime_type.Ascii()
- << " " << (codec_vector.empty() ? "" : codec_vector[1]);
+ << " " << (codecs.empty() ? "" : codecs.front());
return false;
}
@@ -705,21 +754,6 @@ ScriptPromise MediaCapabilities::decodingInfo(
exception_state.ThrowTypeError(message);
return ScriptPromise();
}
-
- if (config->hasVideo() &&
- !IsValidVideoConfiguration(config->video(), is_webrtc)) {
- exception_state.ThrowTypeError(
- "The video configuration dictionary is not valid.");
- return ScriptPromise();
- }
-
- if (config->hasAudio() &&
- !IsValidAudioConfiguration(config->audio(), is_webrtc)) {
- exception_state.ThrowTypeError(
- "The audio configuration dictionary is not valid.");
- return ScriptPromise();
- }
-
// Validation errors should return above.
DCHECK(message.IsEmpty());
@@ -878,7 +912,19 @@ ScriptPromise MediaCapabilities::decodingInfo(
ScriptPromise MediaCapabilities::encodingInfo(
ScriptState* script_state,
- const MediaEncodingConfiguration* configuration) {
+ const MediaEncodingConfiguration* config,
+ ExceptionState& exception_state) {
+ const base::TimeTicks request_time = base::TimeTicks::Now();
+
+ const bool is_webrtc = config->type() == "webrtc";
+ String message;
+ if (!IsValidMediaEncodingConfiguration(config, is_webrtc, &message)) {
+ exception_state.ThrowTypeError(message);
+ return ScriptPromise();
+ }
+ // Validation errors should return above.
+ DCHECK(message.IsEmpty());
+
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
// IMPORTANT: Acquire the promise before potentially synchronously resolving
@@ -886,48 +932,55 @@ ScriptPromise MediaCapabilities::encodingInfo(
// undefined. See comment above Promise() in script_promise_resolver.h
ScriptPromise promise = resolver->Promise();
- if (!IsValidMediaConfiguration(configuration)) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "The configuration dictionary has neither |video| nor |audio| "
- "specified and needs at least one of them."));
- return promise;
- }
- const bool is_webrtc = configuration->type() == "webrtc";
- if (configuration->hasVideo() &&
- !IsValidVideoConfiguration(configuration->video(), is_webrtc)) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "The video configuration dictionary is not valid."));
- return promise;
- }
+ if (is_webrtc) {
+ if (auto* handler = WebrtcEncodingInfoHandler::Instance()) {
+ const int callback_id = CreateCallbackId();
+ pending_cb_map_.insert(
+ callback_id,
+ MakeGarbageCollected<MediaCapabilities::PendingCallbackState>(
+ resolver, nullptr, request_time, absl::nullopt));
- if (configuration->hasAudio() &&
- !IsValidAudioConfiguration(configuration->audio(), is_webrtc)) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "The audio configuration dictionary is not valid."));
- return promise;
- }
+ absl::optional<String> audio_mime_type =
+ config->hasAudio()
+ ? absl::make_optional(config->audio()->contentType())
+ : absl::nullopt;
+ absl::optional<String> video_mime_type =
+ config->hasVideo()
+ ? absl::make_optional(config->video()->contentType())
+ : absl::nullopt;
+ absl::optional<String> scalability_mode =
+ config->hasVideo() && config->video()->hasScalabilityMode()
+ ? absl::make_optional(config->video()->scalabilityMode())
+ : absl::nullopt;
+ handler->EncodingInfo(
+ audio_mime_type, video_mime_type, scalability_mode,
+ WTF::Bind(&MediaCapabilities::OnWebrtcEncodingInfoSupport,
+ WrapPersistent(this), callback_id));
- if (configuration->type() == "transmission") {
- if (auto* handler = TransmissionEncodingInfoHandler::Instance()) {
- handler->EncodingInfo(ToWebMediaConfiguration(configuration),
- WTF::Bind(&OnMediaCapabilitiesEncodingInfo,
- WrapPersistent(resolver)));
return promise;
}
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError,
- "Platform error: could not get EncodingInfoHandler."));
+ // TODO(crbug.com/1187565): This should not happen unless we're out of
+ // memory or something similar. Add UMA metric to count how often it
+ // happens.
+ DCHECK(false);
+ DVLOG(2) << __func__ << " Could not get EncodingInfoHandler.";
+ MediaCapabilitiesInfo* info = CreateEncodingInfoWith(false);
+ resolver->Resolve(info);
return promise;
}
- if (configuration->type() == "record") {
+ if (config->type() == "record") {
+ if (!RuntimeEnabledFeatures::MediaCapabilitiesEncodingInfoEnabled()) {
+ exception_state.ThrowTypeError(
+ "The provided value 'record' is not a valid enum value of type "
+ "MediaEncodingType.");
+ return promise;
+ }
+
if (auto* handler = MakeGarbageCollected<MediaRecorderHandler>(
ExecutionContext::From(script_state)
->GetTaskRunner(TaskType::kInternalMediaRealTime))) {
- handler->EncodingInfo(ToWebMediaConfiguration(configuration),
+ handler->EncodingInfo(ToWebMediaConfiguration(config),
WTF::Bind(&OnMediaCapabilitiesEncodingInfo,
WrapPersistent(resolver)));
return promise;
@@ -938,10 +991,9 @@ ScriptPromise MediaCapabilities::encodingInfo(
return promise;
}
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Valid configuration |type| should be either 'transmission' or "
- "'record'."));
+ exception_state.ThrowTypeError(
+ "The provided value is not a valid enum value of type "
+ "MediaEncodingType.");
return promise;
}
@@ -1315,7 +1367,7 @@ void MediaCapabilities::GetGpuFactoriesSupport(
media::EmptyExtraData(), encryption_scheme);
OnGpuFactoriesSupport(
- callback_id, gpu_factories->IsDecoderConfigSupported(config) ==
+ callback_id, gpu_factories->IsDecoderConfigSupportedOrUnknown(config) ==
media::GpuVideoAcceleratorFactories::Supported::kTrue);
}
@@ -1401,6 +1453,10 @@ void MediaCapabilities::ResolveWebrtcDecodingCallbackIfReady(int callback_id) {
DCHECK(pending_cb_map_.Contains(callback_id));
PendingCallbackState* pending_cb = pending_cb_map_.at(callback_id);
+ // Resolve the promise if we have gathered both supported and power efficient
+ // as well as smooth. Smooth is temporarily set to the same as supported but
+ // will eventually be queried from a local database with historical
+ // performance data.
if (!pending_cb->is_supported.has_value())
return;
@@ -1433,6 +1489,45 @@ void MediaCapabilities::ResolveWebrtcDecodingCallbackIfReady(int callback_id) {
pending_cb_map_.erase(callback_id);
}
+void MediaCapabilities::ResolveWebrtcEncodingCallbackIfReady(int callback_id) {
+ DCHECK(pending_cb_map_.Contains(callback_id));
+ PendingCallbackState* pending_cb = pending_cb_map_.at(callback_id);
+
+ // Resolve the promise if we have gathered both supported and power efficient
+ // as well as smooth. Smooth is temporarily set to the same as supported but
+ // will eventually be queried from a local database with historical
+ // performance data.
+ if (!pending_cb->is_supported.has_value())
+ return;
+
+ // supported and gpu factories supported are set simultaneously.
+ DCHECK(pending_cb->is_gpu_factories_supported.has_value());
+
+ if (!pending_cb->db_is_smooth.has_value())
+ return;
+
+ if (!pending_cb->resolver->GetExecutionContext() ||
+ pending_cb->resolver->GetExecutionContext()->IsContextDestroyed()) {
+ // We're too late! Now that all the callbacks have provided state, its safe
+ // to erase the entry in the map.
+ pending_cb_map_.erase(callback_id);
+ return;
+ }
+
+ Persistent<MediaCapabilitiesInfo> info(MediaCapabilitiesInfo::Create());
+ info->setSupported(*pending_cb->is_supported);
+ info->setPowerEfficient(*pending_cb->is_gpu_factories_supported);
+ info->setSmooth(*pending_cb->db_is_smooth);
+
+ const base::TimeDelta process_time =
+ base::TimeTicks::Now() - pending_cb->request_time;
+ UMA_HISTOGRAM_TIMES("Media.Capabilities.EncodingInfo.Time.Webrtc",
+ process_time);
+
+ pending_cb->resolver->Resolve(std::move(info));
+ pending_cb_map_.erase(callback_id);
+}
+
void MediaCapabilities::OnBadWindowPrediction(
int callback_id,
const absl::optional<::media::learning::TargetHistogram>& histogram) {
@@ -1520,6 +1615,22 @@ void MediaCapabilities::OnWebrtcDecodingInfoSupport(int callback_id,
ResolveWebrtcDecodingCallbackIfReady(callback_id);
}
+void MediaCapabilities::OnWebrtcEncodingInfoSupport(int callback_id,
+ bool is_supported,
+ bool is_power_efficient) {
+ DCHECK(pending_cb_map_.Contains(callback_id));
+ PendingCallbackState* pending_cb = pending_cb_map_.at(callback_id);
+
+ pending_cb->is_supported = is_supported;
+ pending_cb->is_gpu_factories_supported = is_power_efficient;
+
+ // TODO(crbug.com/1187565): Add call in encodingInfo() to get smoothness score
+ // from database and remove this default assignment.
+ pending_cb->db_is_smooth = is_supported;
+
+ ResolveWebrtcEncodingCallbackIfReady(callback_id);
+}
+
int MediaCapabilities::CreateCallbackId() {
// Search for the next available callback ID. 0 and -1 are reserved by
// wtf::HashMap (meaning "empty" and "deleted").
diff --git a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
index babd98de260..3d6668d0036 100644
--- a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
+++ b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
@@ -52,7 +52,9 @@ class MODULES_EXPORT MediaCapabilities final
ScriptPromise decodingInfo(ScriptState*,
const MediaDecodingConfiguration*,
ExceptionState&);
- ScriptPromise encodingInfo(ScriptState*, const MediaEncodingConfiguration*);
+ ScriptPromise encodingInfo(ScriptState*,
+ const MediaEncodingConfiguration*,
+ ExceptionState&);
private:
// Stores pending callback state from and intermediate prediction values while
@@ -145,7 +147,12 @@ class MODULES_EXPORT MediaCapabilities final
bool is_supported,
bool is_power_efficient);
+ void OnWebrtcEncodingInfoSupport(int callback_id,
+ bool is_supported,
+ bool is_power_efficient);
+
void ResolveWebrtcDecodingCallbackIfReady(int callback_id);
+ void ResolveWebrtcEncodingCallbackIfReady(int callback_id);
// Creates a new (incremented) callback ID from |last_callback_id_| for
// mapping in |pending_cb_map_|.
diff --git a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.idl b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.idl
index 04d433224de..cf097d7829f 100644
--- a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.idl
+++ b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.idl
@@ -7,6 +7,6 @@
[Exposed=(Window,Worker)]
interface MediaCapabilities {
[CallWith=ScriptState, RaisesException, Measure] Promise<MediaCapabilitiesDecodingInfo> decodingInfo(MediaDecodingConfiguration configuration);
- [CallWith=ScriptState, Measure, RuntimeEnabled=MediaCapabilitiesEncodingInfo] Promise<MediaCapabilitiesInfo> encodingInfo(
+ [CallWith=ScriptState, RaisesException, Measure, RuntimeEnabled=MediaCapabilitiesWebRtc] Promise<MediaCapabilitiesInfo> encodingInfo(
MediaEncodingConfiguration configuration);
};
diff --git a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc
index d7578bfc37c..94f0a9e7b88 100644
--- a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_capabilities_info.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_decoding_configuration.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_media_encoding_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_configuration.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
@@ -183,14 +184,18 @@ class FakeMediaMetricsProvider
void SetTimeToPlayReady(base::TimeDelta elapsed) override {}
void SetContainerName(
media::mojom::blink::MediaContainerName container_name) override {}
+ void SetRendererType(
+ media::mojom::blink::RendererType renderer_type) override {}
+ void SetKeySystem(const String& key_system) override {}
+ void SetIsHardwareSecure() override {}
void SetHasPlayed() override {}
void SetHaveEnough() override {}
void SetHasAudio(media::mojom::AudioCodec audio_codec) override {}
void SetHasVideo(media::mojom::VideoCodec video_codec) override {}
void SetVideoPipelineInfo(
- media::mojom::blink::VideoDecoderInfoPtr info) override {}
+ media::mojom::blink::VideoPipelineInfoPtr info) override {}
void SetAudioPipelineInfo(
- media::mojom::blink::AudioDecoderInfoPtr info) override {}
+ media::mojom::blink::AudioPipelineInfoPtr info) override {}
private:
mojo::Receiver<media::mojom::blink::MediaMetricsProvider> receiver_{this};
@@ -346,8 +351,8 @@ class MediaCapabilitiesTestContext {
std::unique_ptr<MockLearningTaskControllerService> nnr_service_;
};
-// |kContentType|, |kCodec|, and |kCodecProfile| must match.
-const char kContentType[] = "video/webm; codecs=\"vp09.00.10.08\"";
+// |kVideoContentType|, |kCodec|, and |kCodecProfile| must match.
+const char kVideoContentType[] = "video/webm; codecs=\"vp09.00.10.08\"";
const char kAudioContentType[] = "audio/webm; codecs=\"opus\"";
const media::VideoCodecProfile kCodecProfile = media::VP9PROFILE_PROFILE0;
const media::VideoCodec kCodec = media::kCodecVP9;
@@ -355,15 +360,15 @@ const double kFramerate = 20.5;
const int kWidth = 3840;
const int kHeight = 2160;
const int kBitrate = 2391000;
-const char kWebrtcContentType[] = "video/VP9; profile-id=\"0\"";
+const char kWebrtcVideoContentType[] = "video/VP9; profile-id=\"0\"";
const char kWebrtcAudioContentType[] = "audio/opus";
// Construct AudioConfig using the constants above.
-MediaDecodingConfiguration* CreateAudioDecodingConfig(const char content_type[],
- const char type[]) {
+template <class T>
+T* CreateAudioConfig(const char content_type[], const char type[]) {
auto* audio_config = MakeGarbageCollected<AudioConfiguration>();
audio_config->setContentType(content_type);
- auto* decoding_config = MakeGarbageCollected<MediaDecodingConfiguration>();
+ auto* decoding_config = MakeGarbageCollected<T>();
decoding_config->setType(type);
decoding_config->setAudio(audio_config);
return decoding_config;
@@ -371,24 +376,32 @@ MediaDecodingConfiguration* CreateAudioDecodingConfig(const char content_type[],
// Construct media-source AudioConfig using the constants above.
MediaDecodingConfiguration* CreateAudioDecodingConfig() {
- return CreateAudioDecodingConfig(kAudioContentType, "media-source");
+ return CreateAudioConfig<MediaDecodingConfiguration>(kAudioContentType,
+ "media-source");
}
-// Construct webrtc AudioConfig using the constants above.
+// Construct webrtc decoding AudioConfig using the constants above.
MediaDecodingConfiguration* CreateWebrtcAudioDecodingConfig() {
- return CreateAudioDecodingConfig(kWebrtcAudioContentType, "webrtc");
+ return CreateAudioConfig<MediaDecodingConfiguration>(kWebrtcAudioContentType,
+ "webrtc");
+}
+
+// Construct webrtc decoding AudioConfig using the constants above.
+MediaEncodingConfiguration* CreateWebrtcAudioEncodingConfig() {
+ return CreateAudioConfig<MediaEncodingConfiguration>(kWebrtcAudioContentType,
+ "webrtc");
}
// Construct VideoConfig using the constants above.
-MediaDecodingConfiguration* CreateDecodingConfig(const char content_type[],
- const char type[]) {
+template <class T>
+T* CreateVideoConfig(const char content_type[], const char type[]) {
auto* video_config = MakeGarbageCollected<VideoConfiguration>();
video_config->setFramerate(kFramerate);
video_config->setContentType(content_type);
video_config->setWidth(kWidth);
video_config->setHeight(kHeight);
video_config->setBitrate(kBitrate);
- auto* decoding_config = MakeGarbageCollected<MediaDecodingConfiguration>();
+ auto* decoding_config = MakeGarbageCollected<T>();
decoding_config->setType(type);
decoding_config->setVideo(video_config);
return decoding_config;
@@ -396,12 +409,20 @@ MediaDecodingConfiguration* CreateDecodingConfig(const char content_type[],
// Construct media-source VideoConfig using the constants above.
MediaDecodingConfiguration* CreateDecodingConfig() {
- return CreateDecodingConfig(kContentType, "media-source");
+ return CreateVideoConfig<MediaDecodingConfiguration>(kVideoContentType,
+ "media-source");
}
-// Construct webrtc VideoConfig using the constants above.
+// Construct webrtc decoding VideoConfig using the constants above.
MediaDecodingConfiguration* CreateWebrtcDecodingConfig() {
- return CreateDecodingConfig(kWebrtcContentType, "webrtc");
+ return CreateVideoConfig<MediaDecodingConfiguration>(kWebrtcVideoContentType,
+ "webrtc");
+}
+
+// Construct webrtc encoding VideoConfig using the constants above.
+MediaEncodingConfiguration* CreateWebrtcEncodingConfig() {
+ return CreateVideoConfig<MediaEncodingConfiguration>(kWebrtcVideoContentType,
+ "webrtc");
}
// Construct PredicitonFeatures matching the CreateDecodingConfig, using the
@@ -497,7 +518,7 @@ base::FieldTrialParams MakeMlParams(double bad_window_threshold,
return params;
}
-// Wrapping deocdingInfo() call for readability. Await resolution of the promise
+// Wrapping decodingInfo() call for readability. Await resolution of the promise
// and return its info.
MediaCapabilitiesInfo* DecodingInfo(
const MediaDecodingConfiguration* decoding_config,
@@ -515,6 +536,23 @@ MediaCapabilitiesInfo* DecodingInfo(
context->GetExceptionState());
}
+// Wrapping encodingInfo() call for readability. Await resolution of the promise
+// and return its info.
+MediaCapabilitiesInfo* EncodingInfo(
+ const MediaEncodingConfiguration* encoding_config,
+ MediaCapabilitiesTestContext* context) {
+ ScriptPromise promise = context->GetMediaCapabilities()->encodingInfo(
+ context->GetScriptState(), encoding_config, context->GetExceptionState());
+
+ ScriptPromiseTester tester(context->GetScriptState(), promise);
+ tester.WaitUntilSettled();
+
+ CHECK(!tester.IsRejected()) << " Cant get info from rejected promise.";
+
+ return NativeValueTraits<MediaCapabilitiesInfo>::NativeValue(
+ context->GetIsolate(), tester.Value().V8Value(),
+ context->GetExceptionState());
+}
} // namespace
TEST(MediaCapabilitiesTests, BasicAudio) {
@@ -664,7 +702,7 @@ TEST(MediaCapabilitiesTests, PredictPowerEfficientWithGpuFactories) {
EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
.Times(2)
.WillRepeatedly(Return(true));
- EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_, _))
+ EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_))
.WillOnce(
Return(media::GpuVideoAcceleratorFactories::Supported::kTrue));
}
@@ -685,7 +723,7 @@ TEST(MediaCapabilitiesTests, PredictPowerEfficientWithGpuFactories) {
EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
.Times(2)
.WillRepeatedly(Return(true));
- EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_, _))
+ EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_))
.WillRepeatedly(
Return(media::GpuVideoAcceleratorFactories::Supported::kFalse));
@@ -962,7 +1000,7 @@ void RunCallbackPermutationTest(std::vector<PredictionType> callback_order) {
EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
.Times(2)
.WillRepeatedly(Return(true));
- EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_, _))
+ EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_))
.WillRepeatedly(
Return(media::GpuVideoAcceleratorFactories::Supported::kFalse));
}
@@ -1029,8 +1067,8 @@ TEST(MediaCapabilitiesTests, PredictionCallbackPermutations) {
} while (std::next_permutation(callback_order.begin(), callback_order.end()));
}
-// WebRTC tests.
-TEST(MediaCapabilitiesTests, WebrtcBasicAudio) {
+// WebRTC decodingInfo tests.
+TEST(MediaCapabilitiesTests, WebrtcDecodingBasicAudio) {
MediaCapabilitiesTestContext context;
ON_CALL(context.GetMockPlatform(), GetGpuFactories())
.WillByDefault(Return(nullptr));
@@ -1045,7 +1083,7 @@ TEST(MediaCapabilitiesTests, WebrtcBasicAudio) {
EXPECT_TRUE(info->powerEfficient());
}
-TEST(MediaCapabilitiesTests, WebrtcUnsupportedAudio) {
+TEST(MediaCapabilitiesTests, WebrtcDecodingUnsupportedAudio) {
MediaCapabilitiesTestContext context;
ON_CALL(context.GetMockPlatform(), GetGpuFactories())
.WillByDefault(Return(nullptr));
@@ -1053,14 +1091,14 @@ TEST(MediaCapabilitiesTests, WebrtcUnsupportedAudio) {
.Times(testing::AtMost(1));
const MediaDecodingConfiguration* kDecodingConfig =
- CreateAudioDecodingConfig("audio/FooCodec", "webrtc");
+ CreateAudioConfig<MediaDecodingConfiguration>("audio/FooCodec", "webrtc");
MediaCapabilitiesInfo* info = DecodingInfo(kDecodingConfig, &context);
EXPECT_FALSE(info->supported());
EXPECT_FALSE(info->smooth());
EXPECT_FALSE(info->powerEfficient());
}
-TEST(MediaCapabilitiesTests, WebrtcBasicVideo) {
+TEST(MediaCapabilitiesTests, WebrtcDecodingBasicVideo) {
MediaCapabilitiesTestContext context;
ON_CALL(context.GetMockPlatform(), GetGpuFactories())
.WillByDefault(Return(nullptr));
@@ -1075,7 +1113,7 @@ TEST(MediaCapabilitiesTests, WebrtcBasicVideo) {
EXPECT_FALSE(info->powerEfficient());
}
-TEST(MediaCapabilitiesTests, WebrtcUnsupportedVideo) {
+TEST(MediaCapabilitiesTests, WebrtcDecodingUnsupportedVideo) {
MediaCapabilitiesTestContext context;
ON_CALL(context.GetMockPlatform(), GetGpuFactories())
.WillByDefault(Return(nullptr));
@@ -1083,7 +1121,7 @@ TEST(MediaCapabilitiesTests, WebrtcUnsupportedVideo) {
.Times(testing::AtMost(1));
const MediaDecodingConfiguration* kDecodingConfig =
- CreateDecodingConfig("video/FooCodec", "webrtc");
+ CreateVideoConfig<MediaDecodingConfiguration>("video/FooCodec", "webrtc");
MediaCapabilitiesInfo* info = DecodingInfo(kDecodingConfig, &context);
EXPECT_FALSE(info->supported());
@@ -1091,4 +1129,66 @@ TEST(MediaCapabilitiesTests, WebrtcUnsupportedVideo) {
EXPECT_FALSE(info->powerEfficient());
}
+// WebRTC encodingInfo tests.
+TEST(MediaCapabilitiesTests, WebrtcEncodingBasicAudio) {
+ MediaCapabilitiesTestContext context;
+ ON_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .WillByDefault(Return(nullptr));
+ EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .Times(testing::AtMost(1));
+
+ const MediaEncodingConfiguration* kEncodingConfig =
+ CreateWebrtcAudioEncodingConfig();
+ MediaCapabilitiesInfo* info = EncodingInfo(kEncodingConfig, &context);
+ EXPECT_TRUE(info->supported());
+ EXPECT_TRUE(info->smooth());
+ EXPECT_TRUE(info->powerEfficient());
+}
+
+TEST(MediaCapabilitiesTests, WebrtcEncodingUnsupportedAudio) {
+ MediaCapabilitiesTestContext context;
+ ON_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .WillByDefault(Return(nullptr));
+ EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .Times(testing::AtMost(1));
+
+ const MediaEncodingConfiguration* kEncodingConfig =
+ CreateAudioConfig<MediaEncodingConfiguration>("audio/FooCodec", "webrtc");
+ MediaCapabilitiesInfo* info = EncodingInfo(kEncodingConfig, &context);
+ EXPECT_FALSE(info->supported());
+ EXPECT_FALSE(info->smooth());
+ EXPECT_FALSE(info->powerEfficient());
+}
+
+TEST(MediaCapabilitiesTests, WebrtcEncodingBasicVideo) {
+ MediaCapabilitiesTestContext context;
+ ON_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .WillByDefault(Return(nullptr));
+ EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .Times(testing::AtMost(1));
+
+ const MediaEncodingConfiguration* kEncodingConfig =
+ CreateWebrtcEncodingConfig();
+ MediaCapabilitiesInfo* info = EncodingInfo(kEncodingConfig, &context);
+ EXPECT_TRUE(info->supported());
+ EXPECT_TRUE(info->smooth());
+ EXPECT_FALSE(info->powerEfficient());
+}
+
+TEST(MediaCapabilitiesTests, WebrtcEncodingUnsupportedVideo) {
+ MediaCapabilitiesTestContext context;
+ ON_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .WillByDefault(Return(nullptr));
+ EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories())
+ .Times(testing::AtMost(1));
+
+ const MediaEncodingConfiguration* kEncodingConfig =
+ CreateVideoConfig<MediaEncodingConfiguration>("video/FooCodec", "webrtc");
+
+ MediaCapabilitiesInfo* info = EncodingInfo(kEncodingConfig, &context);
+ EXPECT_FALSE(info->supported());
+ EXPECT_FALSE(info->smooth());
+ EXPECT_FALSE(info->powerEfficient());
+}
+
} // namespace blink
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 055b6230ea6..0a2c8e7354f 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
@@ -41,7 +41,8 @@ bool MediaControlDownloadButtonElement::ShouldDisplayDownloadButton() const {
// The attribute disables the download button.
// This is run after `SupportSave()` to guarantee that it is recorded only if
// it blocks the download button from showing up.
- if (MediaElement().ControlsListInternal()->ShouldHideDownload()) {
+ if (MediaElement().ControlsListInternal()->ShouldHideDownload() &&
+ !MediaElement().UserWantsControlsVisible()) {
UseCounter::Count(MediaElement().GetDocument(),
WebFeature::kHTMLMediaElementControlsListNoDownload);
return false;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.cc
index f59c8bd46a9..f3057f3d98b 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.cc
@@ -7,9 +7,10 @@
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/touch_event.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_div_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
@@ -95,8 +96,8 @@ gfx::Size MediaControlElementsHelper::GetSizeOrDefault(
height = box->LogicalHeight().Round();
}
- if (element.GetDocument().GetLayoutView())
- zoom_factor = element.GetDocument().GetLayoutView()->ZoomFactor();
+ if (const LocalFrame* frame = element.GetDocument().GetFrame())
+ zoom_factor = frame->PageZoomFactor();
return gfx::Size(round(width / zoom_factor), round(height / zoom_factor));
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h
index d2d00fa728b..fa2f4bcdee6 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_OVERFLOW_MENU_LIST_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_OVERFLOW_MENU_LIST_ELEMENT_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc
index 435855bf08d..635f1fee905 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc
@@ -5,8 +5,11 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_boolean_scrollintoviewoptions.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/frame_request_callback_collection.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"
@@ -45,6 +48,28 @@ const QualifiedName& PlaybackRateAttrName() {
} // anonymous namespace
+class MediaControlPlaybackSpeedListElement::RequestAnimationFrameCallback final
+ : public FrameCallback {
+ public:
+ explicit RequestAnimationFrameCallback(
+ MediaControlPlaybackSpeedListElement* list)
+ : list_(list) {}
+
+ RequestAnimationFrameCallback(const RequestAnimationFrameCallback&) = delete;
+ RequestAnimationFrameCallback& operator=(
+ const RequestAnimationFrameCallback&) = delete;
+
+ void Invoke(double) override { list_->CenterCheckedItem(); }
+
+ void Trace(Visitor* visitor) const override {
+ visitor->Trace(list_);
+ FrameCallback::Trace(visitor);
+ }
+
+ private:
+ Member<MediaControlPlaybackSpeedListElement> list_;
+};
+
MediaControlPlaybackSpeedListElement::MediaControlPlaybackSpeedListElement(
MediaControlsImpl& media_controls)
: MediaControlPopupMenuElement(media_controls) {
@@ -84,6 +109,7 @@ void MediaControlPlaybackSpeedListElement::DefaultEventHandler(Event& event) {
double playback_rate =
To<Element>(target)->GetFloatingPointAttribute(PlaybackRateAttrName());
+ MediaElement().setDefaultPlaybackRate(playback_rate);
MediaElement().setPlaybackRate(playback_rate);
// Close the playback speed list.
@@ -111,6 +137,7 @@ Element* MediaControlPlaybackSpeedListElement::CreatePlaybackSpeedListItem(
if (playback_rate == MediaElement().playbackRate()) {
playback_speed_item_input->setChecked(true);
playback_speed_item->setAttribute(html_names::kAriaCheckedAttr, "true");
+ checked_item_ = playback_speed_item;
}
// Allows to focus the list entry instead of the button.
playback_speed_item->setTabIndex(0);
@@ -154,6 +181,8 @@ void MediaControlPlaybackSpeedListElement::RefreshPlaybackSpeedListMenu() {
ParserAppendChild(CreatePlaybackSpeedHeaderItem());
+ checked_item_ = nullptr;
+
// Construct a menu for playback speeds.
for (unsigned i = 0; i < base::size(kPlaybackSpeeds); i++) {
auto& playback_speed = kPlaybackSpeeds[i];
@@ -168,6 +197,25 @@ void MediaControlPlaybackSpeedListElement::RefreshPlaybackSpeedListMenu() {
"menuitemcheckbox");
ParserAppendChild(playback_speed_item);
}
+ RequestAnimationFrameCallback* callback =
+ MakeGarbageCollected<RequestAnimationFrameCallback>(this);
+ GetDocument().RequestAnimationFrame(callback);
+}
+
+void MediaControlPlaybackSpeedListElement::CenterCheckedItem() {
+ if (!checked_item_)
+ return;
+ ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
+ options->setBlock("center");
+ auto* arg =
+ MakeGarbageCollected<V8UnionBooleanOrScrollIntoViewOptions>(options);
+ checked_item_->scrollIntoView(arg);
+ checked_item_->focus();
+}
+
+void MediaControlPlaybackSpeedListElement::Trace(Visitor* visitor) const {
+ visitor->Trace(checked_item_);
+ MediaControlPopupMenuElement::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.h
index ff76bcf6c1f..a7eaf46e5ff 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.h
@@ -22,7 +22,11 @@ class MediaControlPlaybackSpeedListElement final
void SetIsWanted(bool) final;
+ void Trace(Visitor*) const override;
+
private:
+ class RequestAnimationFrameCallback;
+
void DefaultEventHandler(Event&) override;
void RefreshPlaybackSpeedListMenu();
@@ -33,6 +37,11 @@ class MediaControlPlaybackSpeedListElement final
// Creates the header element of the playback speed list.
Element* CreatePlaybackSpeedHeaderItem();
+
+ // Centers vertically the checked item in the playback speed list.
+ void CenterCheckedItem();
+
+ Member<Element> checked_item_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc
index 46973bfc97f..111b38b8ab6 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_focus_options.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/document.h"
@@ -149,11 +150,15 @@ void MediaControlPopupMenuElement::DefaultEventHandler(Event& event) {
event.stopPropagation();
event.SetDefaultHandled();
- } else if (event.type() == event_type_names::kFocus) {
+ } else if (event.type() == event_type_names::kFocus &&
+ event.target() == this) {
// When the popup menu gains focus from scrolling, switch focus
// back to the last focused item in the menu.
- if (last_focused_element_)
- last_focused_element_->focus();
+ if (last_focused_element_) {
+ FocusOptions* focus_options = FocusOptions::Create();
+ focus_options->setPreventScroll(true);
+ last_focused_element_->focus(focus_options);
+ }
}
MediaControlDivElement::DefaultEventHandler(event);
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 94e25c143aa..716a5c44c9a 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
@@ -4,12 +4,13 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/input_type_names.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/layout/layout_view.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/modules/media_controls/elements/media_control_elements_helper.h"
@@ -153,9 +154,8 @@ int MediaControlSliderElement::TrackWidth() {
}
float MediaControlSliderElement::ZoomFactor() const {
- if (!GetDocument().GetLayoutView())
- return 1;
- return GetDocument().GetLayoutView()->ZoomFactor();
+ const LocalFrame* frame = GetDocument().GetFrame();
+ return frame ? frame->PageZoomFactor() : 1;
}
void MediaControlSliderElement::NotifyElementSizeChanged() {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc
index 74111cc62a3..a87196b5502 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/user_metrics_action.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
@@ -32,10 +31,12 @@
#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
+#include "ui/display/screen_info.h"
namespace {
const int kThumbRadius = 6;
+const base::TimeDelta kRenderTimelineInterval = base::TimeDelta::FromSeconds(1);
// Only respond to main button of primary pointer(s).
bool IsValidPointerEvent(const blink::Event& event) {
@@ -57,7 +58,11 @@ namespace blink {
// +-div#thumb (created by the HTMLSliderElement)
MediaControlTimelineElement::MediaControlTimelineElement(
MediaControlsImpl& media_controls)
- : MediaControlSliderElement(media_controls) {
+ : MediaControlSliderElement(media_controls),
+ render_timeline_timer_(
+ GetDocument().GetTaskRunner(TaskType::kInternalMedia),
+ this,
+ &MediaControlTimelineElement::RenderTimelineTimerFired) {
SetShadowPseudoId(AtomicString("-webkit-media-controls-timeline"));
}
@@ -82,6 +87,13 @@ void MediaControlTimelineElement::UpdateAria() {
void MediaControlTimelineElement::SetPosition(double current_time,
bool suppress_aria) {
+ if (is_live_ && !live_anchor_time_ && current_time != 0) {
+ live_anchor_time_.emplace();
+ live_anchor_time_->clock_time_ = base::TimeTicks::Now();
+ live_anchor_time_->media_time_ = MediaElement().currentTime();
+ }
+
+ MaybeUpdateTimelineInterval();
setValue(String::Number(current_time));
if (!suppress_aria)
@@ -91,8 +103,11 @@ void MediaControlTimelineElement::SetPosition(double current_time,
}
void MediaControlTimelineElement::SetDuration(double duration) {
- double duration_value = std::isfinite(duration) ? duration : 0;
- SetFloatingPointAttribute(html_names::kMaxAttr, duration_value);
+ is_live_ = std::isinf(duration);
+ double duration_value = duration;
+ SetFloatingPointAttribute(html_names::kMaxAttr,
+ is_live_ ? 0.0 : duration_value);
+ SetFloatingPointAttribute(html_names::kMinAttr, 0.0);
RenderBarSegments();
}
@@ -109,10 +124,12 @@ void MediaControlTimelineElement::DefaultEventHandler(Event& event) {
if (BeginScrubbingEvent(event)) {
Platform::Current()->RecordAction(
UserMetricsAction("Media.Controls.ScrubbingBegin"));
+ is_scrubbing_ = true;
GetMediaControls().BeginScrubbing(MediaControlsImpl::IsTouchEvent(&event));
} else if (EndScrubbingEvent(event)) {
Platform::Current()->RecordAction(
UserMetricsAction("Media.Controls.ScrubbingEnd"));
+ is_scrubbing_ = false;
GetMediaControls().EndScrubbing();
}
@@ -163,6 +180,54 @@ bool MediaControlTimelineElement::KeepEventInNode(const Event& event) const {
event, GetLayoutObject());
}
+void MediaControlTimelineElement::OnMediaPlaying() {
+ if (!is_live_)
+ return;
+
+ render_timeline_timer_.Stop();
+}
+
+void MediaControlTimelineElement::OnMediaStoppedPlaying() {
+ if (!is_live_ || is_scrubbing_ || !live_anchor_time_)
+ return;
+
+ render_timeline_timer_.StartRepeating(kRenderTimelineInterval, FROM_HERE);
+}
+
+void MediaControlTimelineElement::OnProgress() {
+ MaybeUpdateTimelineInterval();
+ RenderBarSegments();
+}
+
+void MediaControlTimelineElement::RenderTimelineTimerFired(TimerBase*) {
+ MaybeUpdateTimelineInterval();
+ RenderBarSegments();
+}
+
+void MediaControlTimelineElement::MaybeUpdateTimelineInterval() {
+ if (!is_live_ || !MediaElement().seekable()->length() || !live_anchor_time_)
+ return;
+
+ int last_seekable = MediaElement().seekable()->length() - 1;
+ double seekable_start =
+ MediaElement().seekable()->start(last_seekable, ASSERT_NO_EXCEPTION);
+ double seekable_end =
+ MediaElement().seekable()->end(last_seekable, ASSERT_NO_EXCEPTION);
+ double expected_media_time_now =
+ live_anchor_time_->media_time_ +
+ (base::TimeTicks::Now() - live_anchor_time_->clock_time_).InSecondsF();
+
+ // Cap the current live time in seekable range.
+ if (expected_media_time_now > seekable_end) {
+ live_anchor_time_->media_time_ = seekable_end;
+ live_anchor_time_->clock_time_ = base::TimeTicks::Now();
+ expected_media_time_now = seekable_end;
+ }
+
+ SetFloatingPointAttribute(html_names::kMinAttr, seekable_start);
+ SetFloatingPointAttribute(html_names::kMaxAttr, expected_media_time_now);
+}
+
void MediaControlTimelineElement::RenderBarSegments() {
SetupBarSegments();
@@ -174,6 +239,16 @@ void MediaControlTimelineElement::RenderBarSegments() {
// buffered range containing the current play head.
TimeRanges* buffered_time_ranges = MediaElement().buffered();
DCHECK(buffered_time_ranges);
+
+ // Calculate |current_time| and |duration| for live media base on the timeline
+ // value since timeline's minimum value is not necessarily zero.
+ if (is_live_) {
+ current_time =
+ value().ToDouble() - GetFloatingPointAttribute(html_names::kMinAttr);
+ duration = GetFloatingPointAttribute(html_names::kMaxAttr) -
+ GetFloatingPointAttribute(html_names::kMinAttr);
+ }
+
if (std::isnan(duration) || std::isinf(duration) || !duration ||
std::isnan(current_time)) {
SetBeforeSegmentPosition(MediaControlSliderElement::Position(0, 0));
@@ -223,6 +298,7 @@ void MediaControlTimelineElement::RenderBarSegments() {
}
void MediaControlTimelineElement::Trace(Visitor* visitor) const {
+ visitor->Trace(render_timeline_timer_);
MediaControlSliderElement::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h
index c40ec8dd9dc..2b4546d94d2 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h
@@ -5,8 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_TIMELINE_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_TIMELINE_ELEMENT_H_
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
@@ -28,6 +31,10 @@ class MediaControlTimelineElement : public MediaControlSliderElement {
void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(*event); }
+ void OnMediaPlaying();
+ void OnMediaStoppedPlaying();
+ void OnProgress();
+
void RenderBarSegments();
// Inform the timeline that the Media Controls have been shown or hidden.
@@ -40,9 +47,18 @@ class MediaControlTimelineElement : public MediaControlSliderElement {
const char* GetNameForHistograms() const override;
private:
+ // Struct used to track the current live time.
+ struct LiveAnchorTime {
+ base::TimeTicks clock_time_;
+ double media_time_ = 0;
+ };
+
void DefaultEventHandler(Event&) override;
bool KeepEventInNode(const Event&) const override;
+ void RenderTimelineTimerFired(TimerBase*);
+ void MaybeUpdateTimelineInterval();
+
// Checks if we can begin or end a scrubbing event. If the event is a pointer
// event then it needs to start and end with valid pointer events. If the
// event is a pointer event followed by a touch event then it can only be
@@ -55,6 +71,14 @@ class MediaControlTimelineElement : public MediaControlSliderElement {
bool is_touching_ = false;
bool controls_hidden_ = false;
+
+ bool is_scrubbing_ = false;
+
+ bool is_live_ = false;
+
+ absl::optional<LiveAnchorTime> live_anchor_time_;
+
+ HeapTaskRunnerTimer<MediaControlTimelineElement> render_timeline_timer_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
index 2bb07bec78c..443d6e95860 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
@@ -112,7 +112,7 @@ void MediaControlVolumeSliderElement::CloseSlider() {
classList().Add(kClosedCSSClass);
}
-bool MediaControlVolumeSliderElement::WillRespondToMouseMoveEvents() {
+bool MediaControlVolumeSliderElement::WillRespondToMouseMoveEvents() const {
if (!isConnected() || !GetDocument().IsActive())
return false;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h
index c22d50847d9..5bc086664f4 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h
@@ -27,7 +27,7 @@ class MediaControlVolumeSliderElement final : public MediaControlSliderElement {
void CloseSlider();
// MediaControlInputElement overrides.
- bool WillRespondToMouseMoveEvents() override;
+ bool WillRespondToMouseMoveEvents() const override;
bool WillRespondToMouseClickEvents() override;
void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(*event); }
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 a3aab3c1a2c..1b17f93a2d9 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
@@ -152,6 +152,28 @@ void MaybeParserAppendChild(Element* parent, Element* child) {
parent->ParserAppendChild(child);
}
+bool ShouldShowPlaybackSpeedButton(HTMLMediaElement& media_element) {
+ // The page disabled the button via the controlsList attribute.
+ if (media_element.ControlsListInternal()->ShouldHidePlaybackRate() &&
+ !media_element.UserWantsControlsVisible()) {
+ UseCounter::Count(media_element.GetDocument(),
+ WebFeature::kHTMLMediaElementControlsListNoPlaybackRate);
+ return false;
+ }
+
+ // A MediaStream is not seekable.
+ if (media_element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream)
+ return false;
+
+ // Don't allow for live infinite streams.
+ if (media_element.duration() == std::numeric_limits<double>::infinity() &&
+ media_element.getReadyState() > HTMLMediaElement::kHaveNothing) {
+ return false;
+ }
+
+ return true;
+}
+
bool ShouldShowPictureInPictureButton(HTMLMediaElement& media_element) {
return media_element.SupportsPictureInPicture();
}
@@ -172,7 +194,8 @@ bool ShouldShowCastButton(HTMLMediaElement& media_element) {
}
// The page disabled the button via the attribute.
- if (media_element.ControlsListInternal()->ShouldHideRemotePlayback()) {
+ if (media_element.ControlsListInternal()->ShouldHideRemotePlayback() &&
+ !media_element.UserWantsControlsVisible()) {
UseCounter::Count(
media_element.GetDocument(),
WebFeature::kHTMLMediaElementControlsListNoRemotePlayback);
@@ -567,6 +590,8 @@ void MediaControlsImpl::InitializeControls() {
if (base::FeatureList::IsEnabled(media::kPlaybackSpeedButton)) {
playback_speed_button_ =
MakeGarbageCollected<MediaControlPlaybackSpeedButtonElement>(*this);
+ playback_speed_button_->SetIsWanted(
+ ShouldShowPlaybackSpeedButton(MediaElement()));
}
overflow_menu_ =
MakeGarbageCollected<MediaControlOverflowMenuButtonElement>(*this);
@@ -927,6 +952,11 @@ void MediaControlsImpl::OnControlsListUpdated() {
download_button_->SetIsWanted(
download_button_->ShouldDisplayDownloadButton());
+
+ if (playback_speed_button_) {
+ playback_speed_button_->SetIsWanted(
+ ShouldShowPlaybackSpeedButton(MediaElement()));
+ }
}
LayoutObject* MediaControlsImpl::PanelLayoutObject() {
@@ -1834,11 +1864,13 @@ void MediaControlsImpl::OnPlay() {
void MediaControlsImpl::OnPlaying() {
StartHideMediaControlsTimer();
UpdateCSSClassFromState();
+ timeline_->OnMediaPlaying();
}
void MediaControlsImpl::OnPause() {
UpdatePlayState();
UpdateTimeIndicators();
+ timeline_->OnMediaStoppedPlaying();
MakeOpaque();
StopHideMediaControlsTimer();
@@ -1963,7 +1995,7 @@ void MediaControlsImpl::ElementSizeChangedTimerFired(TimerBase*) {
}
void MediaControlsImpl::OnLoadingProgress() {
- timeline_->RenderBarSegments();
+ timeline_->OnProgress();
}
void MediaControlsImpl::ComputeWhichControlsFit() {
@@ -2163,6 +2195,7 @@ MediaControlOverflowMenuButtonElement& MediaControlsImpl::OverflowButton() {
}
void MediaControlsImpl::OnWaiting() {
+ timeline_->OnMediaStoppedPlaying();
UpdateCSSClassFromState();
}
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 07e1ad123dd..1d66036ec96 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
@@ -315,7 +315,7 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
// Node
bool IsMediaControls() const override { return true; }
- bool WillRespondToMouseMoveEvents() override { return true; }
+ bool WillRespondToMouseMoveEvents() const override { return true; }
void DefaultEventHandler(Event&) override;
bool ContainsRelatedTarget(Event*);
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 1b53f8fc3bf..388a69b30e5 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
@@ -10,9 +10,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_client.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
@@ -40,10 +38,12 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h"
+#include "third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.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/elements/media_control_overflow_menu_list_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h"
+#include "third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h"
#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_volume_slider_element.h"
@@ -55,6 +55,8 @@
#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/web_test_support.h"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
+#include "ui/display/screen_info.h"
// The MediaTimelineWidths histogram suffix expected to be encountered in these
// tests.
@@ -68,16 +70,16 @@ class FakeChromeClient : public EmptyChromeClient {
public:
FakeChromeClient() {
screen_info_.orientation_type =
- mojom::blink::ScreenOrientation::kLandscapePrimary;
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary;
}
// ChromeClient overrides.
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
return screen_info_;
}
private:
- ScreenInfo screen_info_;
+ display::ScreenInfo screen_info_;
};
class MockWebMediaPlayerForImpl : public EmptyWebMediaPlayer {
@@ -253,6 +255,12 @@ class MediaControlsImplTest : public PageTestBase,
MediaControlDownloadButtonElement* DownloadButtonElement() const {
return media_controls_->download_button_;
}
+ MediaControlFullscreenButtonElement* FullscreenButtonElement() const {
+ return media_controls_->fullscreen_button_;
+ }
+ MediaControlPlaybackSpeedButtonElement* PlaybackSpeedButtonElement() const {
+ return media_controls_->playback_speed_button_;
+ }
MediaControlPlayButtonElement* PlayButtonElement() const {
return media_controls_->play_button_;
}
@@ -550,6 +558,29 @@ TEST_F(MediaControlsImplTest, CastOverlayDisabledMediaControlsDisabled) {
EXPECT_FALSE(IsElementVisible(*cast_overlay_button));
}
+TEST_F(MediaControlsImplTest, CastButtonVisibilityDependsOnControlslistAttr) {
+ EnsureSizing();
+
+ MediaControlCastButtonElement* cast_button = CastButtonElement();
+ ASSERT_NE(nullptr, cast_button);
+
+ SimulateRouteAvailable();
+ ASSERT_TRUE(IsOverflowElementVisible(*cast_button));
+
+ MediaControls().MediaElement().setAttribute(
+ blink::html_names::kControlslistAttr, "noremoteplayback");
+ test::RunPendingTasks();
+
+ // Cast button should not be displayed because of
+ // controlslist="noremoteplayback".
+ ASSERT_FALSE(IsOverflowElementVisible(*cast_button));
+
+ // If the user explicitly shows all controls, that should override the
+ // controlsList attribute and cast button should be displayed.
+ MediaControls().MediaElement().SetUserWantsControlsVisible(true);
+ ASSERT_TRUE(IsOverflowElementVisible(*cast_button));
+}
+
TEST_F(MediaControlsImplTest, KeepControlsVisibleIfOverflowListVisible) {
Element* overflow_list = GetElementByShadowPseudoId(
MediaControls(), "-internal-media-controls-overflow-menu-list");
@@ -632,6 +663,90 @@ TEST_F(MediaControlsImplTest, DownloadButtonNotDisplayedHLS) {
test::RunPendingTasks();
SimulateLoadedMetadata();
EXPECT_FALSE(IsOverflowElementVisible(*download_button));
+
+ MediaControls().MediaElement().SetSrc(
+ "https://example.com/foo.m3u8?title=foo");
+ test::RunPendingTasks();
+ SimulateLoadedMetadata();
+ EXPECT_FALSE(IsOverflowElementVisible(*download_button));
+
+ // However, it *should* be displayed for otherwise valid sources containing
+ // the text 'm3u8'.
+ MediaControls().MediaElement().SetSrc("https://example.com/foo.m3u8.mp4");
+ test::RunPendingTasks();
+ SimulateLoadedMetadata();
+ EXPECT_TRUE(IsOverflowElementVisible(*download_button));
+}
+
+TEST_F(MediaControlsImplTest,
+ DownloadButtonVisibilityDependsOnControlslistAttr) {
+ EnsureSizing();
+
+ MediaControlDownloadButtonElement* download_button = DownloadButtonElement();
+ ASSERT_NE(nullptr, download_button);
+
+ MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4");
+ MediaControls().MediaElement().setAttribute(
+ blink::html_names::kControlslistAttr, "nodownload");
+ test::RunPendingTasks();
+ SimulateLoadedMetadata();
+
+ // Download button should not be displayed because of
+ // controlslist="nodownload".
+ EXPECT_FALSE(IsOverflowElementVisible(*download_button));
+
+ // If the user explicitly shows all controls, that should override the
+ // controlsList attribute and download button should be displayed.
+ MediaControls().MediaElement().SetUserWantsControlsVisible(true);
+ EXPECT_TRUE(IsOverflowElementVisible(*download_button));
+}
+
+TEST_F(MediaControlsImplTest,
+ FullscreenButtonDisabledDependsOnControlslistAttr) {
+ EnsureSizing();
+
+ MediaControlFullscreenButtonElement* fullscreen_button =
+ FullscreenButtonElement();
+ ASSERT_NE(nullptr, fullscreen_button);
+
+ MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4");
+ MediaControls().MediaElement().setAttribute(
+ blink::html_names::kControlslistAttr, "nofullscreen");
+ test::RunPendingTasks();
+ SimulateLoadedMetadata();
+
+ // Fullscreen button should be disabled because of
+ // controlslist="nofullscreen".
+ EXPECT_TRUE(fullscreen_button->IsDisabled());
+
+ // If the user explicitly shows all controls, that should override the
+ // controlsList attribute and fullscreen button should be enabled.
+ MediaControls().MediaElement().SetUserWantsControlsVisible(true);
+ EXPECT_FALSE(fullscreen_button->IsDisabled());
+}
+
+TEST_F(MediaControlsImplTest,
+ PlaybackSpeedButtonVisibilityDependsOnControlslistAttr) {
+ EnsureSizing();
+
+ MediaControlPlaybackSpeedButtonElement* playback_speed_button =
+ PlaybackSpeedButtonElement();
+ ASSERT_NE(nullptr, playback_speed_button);
+
+ MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4");
+ MediaControls().MediaElement().setAttribute(
+ blink::html_names::kControlslistAttr, "noplaybackrate");
+ test::RunPendingTasks();
+ SimulateLoadedMetadata();
+
+ // Fullscreen button should not be displayed because of
+ // controlslist="noplaybackrate".
+ EXPECT_FALSE(IsOverflowElementVisible(*playback_speed_button));
+
+ // If the user explicitly shows all controls, that should override the
+ // controlsList attribute and playback speed button should be displayed.
+ MediaControls().MediaElement().SetUserWantsControlsVisible(true);
+ EXPECT_TRUE(IsOverflowElementVisible(*playback_speed_button));
}
TEST_F(MediaControlsImplTest, TimelineSeekToRoundedEnd) {
@@ -963,6 +1078,7 @@ TEST_F(MediaControlsImplTest,
EXPECT_FALSE(HasAvailabilityCallbacks(remote_playback));
}
+ page_holder->GetDocument().View()->UpdateAllLifecyclePhasesForTest();
test::RunPendingTasks();
ThreadState::Current()->CollectAllGarbageForTesting();
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
index bd81bebbde5..1341cb00f96 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
@@ -8,7 +8,6 @@
#include "build/build_config.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
-#include "third_party/blink/public/common/widget/screen_info.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"
@@ -25,6 +24,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "ui/display/screen_info.h"
#if defined(OS_ANDROID)
#include "third_party/blink/public/platform/platform.h"
@@ -271,13 +271,13 @@ MediaControlsOrientationLockDelegate::ComputeOrientationLock() const {
ChromeClient& chrome_client = frame->GetChromeClient();
switch (chrome_client.GetScreenInfo(*frame).orientation_type) {
- case mojom::blink::ScreenOrientation::kPortraitPrimary:
- case mojom::blink::ScreenOrientation::kPortraitSecondary:
+ case display::mojom::blink::ScreenOrientation::kPortraitPrimary:
+ case display::mojom::blink::ScreenOrientation::kPortraitSecondary:
return device::mojom::blink::ScreenOrientationLockType::PORTRAIT;
- case mojom::blink::ScreenOrientation::kLandscapePrimary:
- case mojom::blink::ScreenOrientation::kLandscapeSecondary:
+ case display::mojom::blink::ScreenOrientation::kLandscapePrimary:
+ case display::mojom::blink::ScreenOrientation::kLandscapeSecondary:
return device::mojom::blink::ScreenOrientationLockType::LANDSCAPE;
- case mojom::blink::ScreenOrientation::kUndefined:
+ case display::mojom::blink::ScreenOrientation::kUndefined:
return device::mojom::blink::ScreenOrientationLockType::LANDSCAPE;
}
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 e35d6aec439..e794f0b0098 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
@@ -12,7 +12,6 @@
#include "services/device/public/mojom/screen_orientation.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -35,6 +34,7 @@
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
#include "ui/gfx/geometry/rect.h"
using testing::_;
@@ -138,11 +138,11 @@ class MockChromeClientForOrientationLockDelegate final
WTF::Bind(DidExitFullscreen, WrapPersistent(frame.GetDocument())));
}
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
return mock_screen_info_;
}
- ScreenInfo& MockScreenInfo() { return mock_screen_info_; }
+ display::ScreenInfo& MockScreenInfo() { return mock_screen_info_; }
MockScreenOrientation& ScreenOrientationClient() {
return mock_screen_orientation_;
@@ -150,7 +150,7 @@ class MockChromeClientForOrientationLockDelegate final
private:
MockScreenOrientation mock_screen_orientation_;
- ScreenInfo mock_screen_info_ = {};
+ display::ScreenInfo mock_screen_info_ = {};
};
class StubLocalFrameClientForOrientationLockDelegate final
@@ -366,9 +366,10 @@ class MediaControlsOrientationLockAndRotateToFullscreenDelegateTest
}
// Calls must be wrapped in ASSERT_NO_FATAL_FAILURE.
- void RotateScreenTo(mojom::blink::ScreenOrientation screen_orientation_type,
- uint16_t screen_orientation_angle) {
- ScreenInfo new_screen_info;
+ void RotateScreenTo(
+ display::mojom::blink::ScreenOrientation screen_orientation_type,
+ uint16_t screen_orientation_angle) {
+ display::ScreenInfo new_screen_info;
new_screen_info.orientation_type = screen_orientation_type;
new_screen_info.orientation_angle = screen_orientation_angle;
new_screen_info.rect = ScreenRectFromAngle(screen_orientation_angle);
@@ -587,27 +588,27 @@ TEST_F(MediaControlsOrientationLockDelegateTest, ComputeOrientationLock) {
// 100x100 has more subtilities, it depends on the current screen orientation.
MockWebMediaPlayer().MockNaturalSize() = gfx::Size(100, 100);
ChromeClient().MockScreenInfo().orientation_type =
- mojom::blink::ScreenOrientation::kUndefined;
+ display::mojom::blink::ScreenOrientation::kUndefined;
EXPECT_EQ(device::mojom::ScreenOrientationLockType::LANDSCAPE,
ComputeOrientationLock());
ChromeClient().MockScreenInfo().orientation_type =
- mojom::blink::ScreenOrientation::kPortraitPrimary;
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary;
EXPECT_EQ(device::mojom::ScreenOrientationLockType::PORTRAIT,
ComputeOrientationLock());
ChromeClient().MockScreenInfo().orientation_type =
- mojom::blink::ScreenOrientation::kPortraitPrimary;
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary;
EXPECT_EQ(device::mojom::ScreenOrientationLockType::PORTRAIT,
ComputeOrientationLock());
ChromeClient().MockScreenInfo().orientation_type =
- mojom::blink::ScreenOrientation::kLandscapePrimary;
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary;
EXPECT_EQ(device::mojom::ScreenOrientationLockType::LANDSCAPE,
ComputeOrientationLock());
ChromeClient().MockScreenInfo().orientation_type =
- mojom::blink::ScreenOrientation::kLandscapeSecondary;
+ display::mojom::blink::ScreenOrientation::kLandscapeSecondary;
EXPECT_EQ(device::mojom::ScreenOrientationLockType::LANDSCAPE,
ComputeOrientationLock());
}
@@ -636,32 +637,35 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// or naturally landscape). Similarly for a naturally landscape device.
for (int screen_angle = 0; screen_angle < 360; screen_angle += 90) {
SCOPED_TRACE(testing::Message() << "screen_angle=" << screen_angle);
- mojom::blink::ScreenOrientation screen_type =
- mojom::blink::ScreenOrientation::kUndefined;
+ display::mojom::blink::ScreenOrientation screen_type =
+ display::mojom::blink::ScreenOrientation::kUndefined;
switch (screen_angle) {
case 0:
screen_type =
natural_orientation_is_portrait_
- ? mojom::blink::ScreenOrientation::kPortraitPrimary
- : mojom::blink::ScreenOrientation::kLandscapePrimary;
+ ? display::mojom::blink::ScreenOrientation::kPortraitPrimary
+ : display::mojom::blink::ScreenOrientation::kLandscapePrimary;
break;
case 90:
screen_type =
natural_orientation_is_portrait_
- ? mojom::blink::ScreenOrientation::kLandscapePrimary
- : mojom::blink::ScreenOrientation::kPortraitSecondary;
+ ? display::mojom::blink::ScreenOrientation::kLandscapePrimary
+ : display::mojom::blink::ScreenOrientation::
+ kPortraitSecondary;
break;
case 180:
screen_type =
natural_orientation_is_portrait_
- ? mojom::blink::ScreenOrientation::kPortraitSecondary
- : mojom::blink::ScreenOrientation::kLandscapeSecondary;
+ ? display::mojom::blink::ScreenOrientation::kPortraitSecondary
+ : display::mojom::blink::ScreenOrientation::
+ kLandscapeSecondary;
break;
case 270:
screen_type =
natural_orientation_is_portrait_
- ? mojom::blink::ScreenOrientation::kLandscapeSecondary
- : mojom::blink::ScreenOrientation::kPortraitPrimary;
+ ? display::mojom::blink::ScreenOrientation::
+ kLandscapeSecondary
+ : display::mojom::blink::ScreenOrientation::kPortraitPrimary;
break;
}
ASSERT_NO_FATAL_FAILURE(RotateScreenTo(screen_type, screen_angle));
@@ -800,8 +804,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
PortraitInlineRotateToLandscapeFullscreen) {
// Naturally portrait device, initially portrait, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
PlayVideo();
@@ -814,8 +818,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to landscape triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
// MediaControlsRotateToFullscreenDelegate should enter fullscreen, so
// MediaControlsOrientationLockDelegate should lock orientation to landscape
@@ -841,8 +845,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
PortraitInlineButtonToPortraitLockedLandscapeFullscreen) {
// Naturally portrait device, initially portrait, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -861,8 +865,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
DelegateOrientationLock());
// This will trigger a screen orientation change to landscape.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
// Even though the device is still held in portrait.
RotateDeviceTo(0 /* portrait primary */);
@@ -879,8 +883,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Naturally portrait device, initially portrait device orientation but locked
// to landscape screen orientation, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -909,8 +913,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Naturally portrait device, initially portrait device orientation but locked
// to landscape screen orientation, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -938,8 +942,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Unlocking the orientation earlier will trigger a screen orientation change
// to portrait (since the device orientation was already portrait, even though
// the screen was locked to landscape).
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
// Video should remain inline, unlocked.
CheckStatePendingFullscreen();
@@ -951,8 +955,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
LandscapeInlineRotateToPortraitInline) {
// Naturally portrait device, initially landscape, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
PlayVideo();
@@ -965,8 +969,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to portrait triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
test::RunDelayedTasks(GetUnlockDelay());
// Video should remain inline, unlocked.
@@ -979,8 +983,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
LandscapeInlineButtonToLandscapeFullscreen) {
// Naturally portrait device, initially landscape, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -1015,8 +1019,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
LandscapeFullscreenRotateToPortraitInline) {
// Naturally portrait device, initially landscape, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -1032,8 +1036,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to portrait triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
test::RunDelayedTasks(GetUnlockDelay());
// MediaControlsRotateToFullscreenDelegate should exit fullscreen.
@@ -1048,8 +1052,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
LandscapeFullscreenBackToLandscapeInline) {
// Naturally portrait device, initially landscape, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -1077,8 +1081,8 @@ TEST_F(
AutoRotateDisabledPortraitInlineButtonToPortraitLockedLandscapeFullscreen) {
// Naturally portrait device, initially portrait, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
InitVideo(640, 480);
// But this time the user has disabled auto rotate, e.g. locked to portrait.
SetIsAutoRotateEnabledByUser(false);
@@ -1099,8 +1103,8 @@ TEST_F(
// This will trigger a screen orientation change to landscape, since the app's
// lock overrides the user's orientation lock (at least on Android).
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
// Even though the device is still held in portrait.
RotateDeviceTo(0 /* portrait primary */);
@@ -1118,8 +1122,8 @@ TEST_F(
// Naturally portrait device, initially portrait device orientation but locked
// to landscape screen orientation, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
// But this time the user has disabled auto rotate, e.g. locked to portrait
// (even though the app's landscape screen orientation lock overrides it).
@@ -1153,8 +1157,8 @@ TEST_F(
// Naturally portrait device, initially portrait device orientation but locked
// to landscape screen orientation, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
// But this time the user has disabled auto rotate, e.g. locked to portrait
// (even though the app's landscape screen orientation lock overrides it).
@@ -1185,8 +1189,8 @@ TEST_F(
// to portrait, since the user had locked the screen orientation to portrait,
// (which happens to also match the device orientation) and
// MediaControlsOrientationLockDelegate is no longer overriding that lock.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
// Video should remain inline, unlocked.
CheckStatePendingFullscreen();
@@ -1201,8 +1205,8 @@ TEST_F(
// locked to landscape screen orientation since the user had disabled auto
// rotate, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
// The user has disabled auto rotate, e.g. locked to portrait (even though the
// app's landscape screen orientation lock overrides it).
@@ -1242,8 +1246,8 @@ TEST_F(
// locked to landscape screen orientation since the user had disabled auto
// rotate, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(640, 480);
// The user has disabled auto rotate, e.g. locked to portrait (even though the
// app's landscape screen orientation lock overrides it).
@@ -1274,8 +1278,8 @@ TEST_F(
// to portrait even though the device orientation is landscape, since the user
// had locked the screen orientation to portrait, and
// MediaControlsOrientationLockDelegate is no longer overriding that.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
// Video should remain inline, unlocked.
CheckStatePendingFullscreen();
@@ -1287,8 +1291,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
PortraitVideoRotateEnterExit) {
// Naturally portrait device, initially landscape, with *portrait* video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
InitVideo(480, 640);
SetIsAutoRotateEnabledByUser(true);
PlayVideo();
@@ -1301,8 +1305,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to portrait triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
// MediaControlsRotateToFullscreenDelegate should enter fullscreen, so
// MediaControlsOrientationLockDelegate should lock orientation to portrait
@@ -1326,8 +1330,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to landscape triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
// MediaControlsRotateToFullscreenDelegate should exit fullscreen.
EXPECT_FALSE(Video().IsFullscreen());
@@ -1341,8 +1345,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
LandscapeDeviceRotateEnterExit) {
// Naturally *landscape* device, initially portrait, with landscape video.
natural_orientation_is_portrait_ = false;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 270));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 270));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
PlayVideo();
@@ -1355,8 +1359,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to landscape triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 0));
// MediaControlsRotateToFullscreenDelegate should enter fullscreen, so
// MediaControlsOrientationLockDelegate should lock orientation to landscape
@@ -1380,8 +1384,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate user rotating their device to portrait triggering a screen
// orientation change.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 270));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 270));
// MediaControlsRotateToFullscreenDelegate should exit fullscreen.
EXPECT_FALSE(Video().IsFullscreen());
@@ -1395,8 +1399,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
ScreenOrientationRaceCondition) {
// Naturally portrait device, initially portrait, with landscape video.
natural_orientation_is_portrait_ = true;
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary, 0));
InitVideo(640, 480);
SetIsAutoRotateEnabledByUser(true);
@@ -1415,8 +1419,8 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
DelegateOrientationLock());
// This will trigger a screen orientation change to landscape.
- ASSERT_NO_FATAL_FAILURE(
- RotateScreenTo(mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
+ ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary, 90));
// Even though the device is still held in portrait.
RotateDeviceTo(0 /* portrait primary */);
@@ -1456,7 +1460,7 @@ TEST_F(MediaControlsOrientationLockAndRotateToFullscreenDelegateTest,
// Simulate the OS processing the device orientation change after a delay of
// `kMinUnlockDelay` and hence changing the screen orientation.
ASSERT_NO_FATAL_FAILURE(RotateScreenTo(
- mojom::blink::ScreenOrientation::kLandscapeSecondary, 270));
+ display::mojom::blink::ScreenOrientation::kLandscapeSecondary, 270));
// MediaControlsOrientationLockDelegate should remain locked to landscape.
CheckStateMaybeLockedFullscreen();
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
index e5e93516df0..7e145dac017 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/user_metrics_action.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -21,6 +20,8 @@
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -269,15 +270,15 @@ MediaControlsRotateToFullscreenDelegate::ComputeScreenOrientation() const {
return SimpleOrientation::kUnknown;
ChromeClient& chrome_client = frame->GetChromeClient();
- const ScreenInfo& screen_info = chrome_client.GetScreenInfo(*frame);
+ const display::ScreenInfo& screen_info = chrome_client.GetScreenInfo(*frame);
switch (screen_info.orientation_type) {
- case mojom::blink::ScreenOrientation::kPortraitPrimary:
- case mojom::blink::ScreenOrientation::kPortraitSecondary:
+ case display::mojom::blink::ScreenOrientation::kPortraitPrimary:
+ case display::mojom::blink::ScreenOrientation::kPortraitSecondary:
return SimpleOrientation::kPortrait;
- case mojom::blink::ScreenOrientation::kLandscapePrimary:
- case mojom::blink::ScreenOrientation::kLandscapeSecondary:
+ case display::mojom::blink::ScreenOrientation::kLandscapePrimary:
+ case display::mojom::blink::ScreenOrientation::kLandscapeSecondary:
return SimpleOrientation::kLandscape;
- case mojom::blink::ScreenOrientation::kUndefined:
+ case display::mojom::blink::ScreenOrientation::kUndefined:
return SimpleOrientation::kUnknown;
}
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 e6c62d6d6d7..de6f2b3fa4c 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
@@ -7,7 +7,6 @@
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "services/device/public/mojom/screen_orientation.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.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"
@@ -31,6 +30,7 @@
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
namespace blink {
@@ -72,14 +72,14 @@ class MockChromeClient : public EmptyChromeClient {
Fullscreen::DidExitFullscreen(*frame.GetDocument());
}
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
return mock_screen_info_;
}
- ScreenInfo& MockScreenInfo() { return mock_screen_info_; }
+ display::ScreenInfo& MockScreenInfo() { return mock_screen_info_; }
private:
- ScreenInfo mock_screen_info_ = {};
+ display::ScreenInfo mock_screen_info_ = {};
};
class StubLocalFrameClient : public EmptyLocalFrameClient {
@@ -157,7 +157,7 @@ class MediaControlsRotateToFullscreenDelegateTest
}
void InitScreenAndVideo(
- mojom::blink::ScreenOrientation initial_screen_orientation,
+ display::mojom::blink::ScreenOrientation initial_screen_orientation,
gfx::Size video_size,
bool with_device_orientation = true);
@@ -169,7 +169,8 @@ class MediaControlsRotateToFullscreenDelegateTest
test::RunPendingTasks();
}
- void RotateTo(mojom::blink::ScreenOrientation new_screen_orientation);
+ void RotateTo(
+ display::mojom::blink::ScreenOrientation new_screen_orientation);
MockChromeClient& GetChromeClient() const { return *chrome_client_; }
LocalDOMWindow& GetWindow() const { return *GetDocument().domWindow(); }
@@ -188,7 +189,7 @@ class MediaControlsRotateToFullscreenDelegateTest
};
void MediaControlsRotateToFullscreenDelegateTest::InitScreenAndVideo(
- mojom::blink::ScreenOrientation initial_screen_orientation,
+ display::mojom::blink::ScreenOrientation initial_screen_orientation,
gfx::Size video_size,
bool with_device_orientation /* = true */) {
// Set initial screen orientation (called by `Attach` during `AppendChild`).
@@ -225,7 +226,7 @@ void MediaControlsRotateToFullscreenDelegateTest::PlayVideo() {
}
void MediaControlsRotateToFullscreenDelegateTest::RotateTo(
- mojom::blink::ScreenOrientation new_screen_orientation) {
+ display::mojom::blink::ScreenOrientation new_screen_orientation) {
GetChromeClient().MockScreenInfo().orientation_type = new_screen_orientation;
DispatchEvent(GetWindow(), event_type_names::kOrientationchange);
test::RunPendingTasks();
@@ -322,7 +323,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterSuccessPortraitToLandscape) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -335,7 +336,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_FALSE(GetVideo().IsFullscreen());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should enter fullscreen.
EXPECT_TRUE(GetVideo().IsFullscreen());
@@ -344,8 +345,9 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterSuccessLandscapeToPortrait) {
// Landscape screen, portrait video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kLandscapePrimary,
- gfx::Size(480, 640));
+ InitScreenAndVideo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary,
+ gfx::Size(480, 640));
EXPECT_EQ(SimpleOrientation::kLandscape, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kPortrait, ComputeVideoOrientation());
@@ -357,7 +359,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_FALSE(GetVideo().IsFullscreen());
// Rotate screen to portrait.
- RotateTo(mojom::blink::ScreenOrientation::kPortraitPrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kPortraitPrimary);
// Should enter fullscreen.
EXPECT_TRUE(GetVideo().IsFullscreen());
@@ -366,7 +368,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterSuccessSquarePortraitToLandscape) {
// Portrait screen, square video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(400, 400));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -379,7 +381,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_FALSE(GetVideo().IsFullscreen());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should enter fullscreen, since square videos are currently treated the same
// as landscape videos.
@@ -388,8 +390,9 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailWrongOrientation) {
// Landscape screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kLandscapePrimary,
- gfx::Size(640, 480));
+ InitScreenAndVideo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary,
+ gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kLandscape, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -400,7 +403,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailWrongOrientation) {
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to portrait.
- RotateTo(mojom::blink::ScreenOrientation::kPortraitPrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kPortraitPrimary);
// Should not enter fullscreen since the orientation that the device was
// rotated to does not match the orientation of the video.
@@ -410,8 +413,9 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailWrongOrientation) {
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterFailSquareWrongOrientation) {
// Landscape screen, square video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kLandscapePrimary,
- gfx::Size(400, 400));
+ InitScreenAndVideo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary,
+ gfx::Size(400, 400));
EXPECT_EQ(SimpleOrientation::kLandscape, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -422,7 +426,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to portrait.
- RotateTo(mojom::blink::ScreenOrientation::kPortraitPrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kPortraitPrimary);
// Should not enter fullscreen since square videos are treated as landscape,
// so rotating to portrait does not match the orientation of the video.
@@ -433,7 +437,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailNoControls) {
DisableControls();
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -445,7 +449,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailNoControls) {
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since video has no controls.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -454,7 +458,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailNoControls) {
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterFailNoDeviceOrientation) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480), false /* with_device_orientation */);
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -472,7 +476,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since Device Orientation is not available.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -481,7 +485,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterFailZeroDeviceOrientation) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480), false /* with_device_orientation */);
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -502,7 +506,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since Device Orientation is not available.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -510,7 +514,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailPaused) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -522,7 +526,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailPaused) {
EXPECT_FALSE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since video is paused.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -530,7 +534,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailPaused) {
TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailHidden) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -551,7 +555,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailHidden) {
EXPECT_FALSE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since video is not visible.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -560,8 +564,9 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailHidden) {
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterFail180DegreeRotation) {
// Landscape screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kLandscapeSecondary,
- gfx::Size(640, 480));
+ InitScreenAndVideo(
+ display::mojom::blink::ScreenOrientation::kLandscapeSecondary,
+ gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kLandscape, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -573,7 +578,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
// Rotate screen 180 degrees to the opposite landscape (without passing via a
// portrait orientation).
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since this is a 180 degree orientation.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -581,7 +586,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailSmall) {
// Portrait screen, small landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(300, 199));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kUnknown, ComputeVideoOrientation());
@@ -593,7 +598,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailSmall) {
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen since video is too small.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -602,7 +607,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest, EnterFailSmall) {
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterFailDocumentFullscreen) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -623,7 +628,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen on video, since document is already fullscreen.
EXPECT_TRUE(Fullscreen::IsFullscreenElement(*GetDocument().body()));
@@ -633,8 +638,9 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
ExitSuccessLandscapeFullscreenToPortraitInline) {
// Landscape screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kLandscapePrimary,
- gfx::Size(640, 480));
+ InitScreenAndVideo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary,
+ gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kLandscape, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -654,7 +660,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
// Rotate screen to portrait. This relies on the screen orientation not being
// locked by MediaControlsOrientationLockDelegate (which has its own tests).
- RotateTo(mojom::blink::ScreenOrientation::kPortraitPrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kPortraitPrimary);
// Should exit fullscreen.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -663,7 +669,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
ExitSuccessPortraitFullscreenToLandscapeInline) {
// Portrait screen, portrait video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(480, 640));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kPortrait, ComputeVideoOrientation());
@@ -684,7 +690,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
// Rotate screen to landscape. This relies on the screen orientation not being
// locked by MediaControlsOrientationLockDelegate (which has its own tests).
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should exit fullscreen.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -693,8 +699,9 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
ExitFailDocumentFullscreen) {
// Landscape screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kLandscapePrimary,
- gfx::Size(640, 480));
+ InitScreenAndVideo(
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary,
+ gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kLandscape, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -712,7 +719,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_FALSE(ObservedVisibility());
// Rotate screen to portrait.
- RotateTo(mojom::blink::ScreenOrientation::kPortraitPrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kPortraitPrimary);
// Should not exit fullscreen, since video was not the fullscreen element.
EXPECT_TRUE(Fullscreen::IsFullscreenElement(*GetDocument().body()));
@@ -722,7 +729,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterFailControlsListNoFullscreen) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -737,7 +744,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should not enter fullscreen when controlsList=nofullscreen.
EXPECT_FALSE(GetVideo().IsFullscreen());
@@ -746,7 +753,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EnterSuccessControlsListNoDownload) {
// Portrait screen, landscape video.
- InitScreenAndVideo(mojom::blink::ScreenOrientation::kPortraitPrimary,
+ InitScreenAndVideo(display::mojom::blink::ScreenOrientation::kPortraitPrimary,
gfx::Size(640, 480));
EXPECT_EQ(SimpleOrientation::kPortrait, ObservedScreenOrientation());
EXPECT_EQ(SimpleOrientation::kLandscape, ComputeVideoOrientation());
@@ -761,7 +768,7 @@ TEST_F(MediaControlsRotateToFullscreenDelegateTest,
EXPECT_TRUE(ObservedVisibility());
// Rotate screen to landscape.
- RotateTo(mojom::blink::ScreenOrientation::kLandscapePrimary);
+ RotateTo(display::mojom::blink::ScreenOrientation::kLandscapePrimary);
// Should enter fullscreen when controlsList is not set to nofullscreen.
EXPECT_TRUE(GetVideo().IsFullscreen());
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc
index 826f622a106..6fe841b31fc 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc
@@ -152,7 +152,8 @@ bool MediaControlsSharedHelpers::ShouldShowFullscreenButton(
if (!Fullscreen::FullscreenEnabled(media_element.GetDocument()))
return false;
- if (media_element.ControlsListInternal()->ShouldHideFullscreen()) {
+ if (media_element.ControlsListInternal()->ShouldHideFullscreen() &&
+ !media_element.UserWantsControlsVisible()) {
UseCounter::Count(media_element.GetDocument(),
WebFeature::kHTMLMediaElementControlsListNoFullscreen);
return false;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaControls.css b/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaControls.css
index e0782ff6794..f33684dd27e 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaControls.css
+++ b/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaControls.css
@@ -1330,24 +1330,22 @@ video::-internal-media-controls-scrubbing-message {
video::-internal-media-controls-text-track-list-kind-captions {
-webkit-appearance: none;
background-image: -internal-light-dark(-webkit-image-set(url(ic_closed_caption.svg) 1x), -webkit-image-set(url(ic_closed_caption_white.svg) 1x));
- background-size: 32px;
+ background-size: 18px;
background-repeat: no-repeat;
background-position: center center;
- height: 20px;
- width: 20px;
- margin-left: 10px;
+ height: 18px;
+ width: 18px;
vertical-align: middle;
}
video::-internal-media-controls-text-track-list-kind-subtitles {
-webkit-appearance: none;
background-image: -internal-light-dark(-webkit-image-set(url(ic_subtitles.svg) 1x), -webkit-image-set(url(ic_subtitles_white.svg) 1x));
- background-size: 32px;
+ background-size: 18px;
background-repeat: no-repeat;
background-position: center center;
- height: 20px;
- width: 20px;
- margin-left: 10px;
+ height: 18px;
+ width: 18px;
vertical-align: middle;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS
index b58e18d5a35..05cb9bd3c02 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS
@@ -1,5 +1 @@
guidou@chromium.org
-
-# Original (legacy) owner.
-emircan@chromium.org
-mcasas@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
index dd61e1f393d..0c660054cdb 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
@@ -9,9 +9,12 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
+#include "build/build_config.h"
+#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "media/base/limits.h"
#include "media/base/video_util.h"
@@ -23,6 +26,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
#include "third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h"
@@ -38,6 +42,15 @@ namespace blink {
namespace {
+const base::Feature kOneCopyCanvasCapture {
+ "OneCopyCanvasCapture",
+#if defined(OS_MAC)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
// Return the gfx::ColorSpace that the pixels resulting from calling
// ConvertToYUVFrame on |image| will be in.
gfx::ColorSpace GetImageYUVColorSpace(scoped_refptr<StaticBitmapImage> image) {
@@ -216,7 +229,36 @@ void CanvasCaptureHandler::SendNewFrame(
}
// Try async reading if image is texture backed.
- if (image->CurrentFrameKnownToBeOpaque()) {
+ if (image->CurrentFrameKnownToBeOpaque() || can_discard_alpha_) {
+ if (base::FeatureList::IsEnabled(kOneCopyCanvasCapture)) {
+ if (!accelerated_frame_pool_) {
+ accelerated_frame_pool_ =
+ std::make_unique<WebGraphicsContext3DVideoFramePool>(
+ context_provider);
+ }
+ auto blit_done_lambda = [](base::WeakPtr<CanvasCaptureHandler> handler,
+ base::TimeTicks timestamp,
+ scoped_refptr<media::VideoFrame> video_frame) {
+ if (handler)
+ handler->OnYUVPixelsReadAsync(video_frame, timestamp, true);
+ };
+ auto blit_done_callback =
+ WTF::Bind(blit_done_lambda, weak_ptr_factory_.GetWeakPtr(),
+ base::TimeTicks::Now());
+ // TODO(https://crbug.com/1224279): This assumes that all
+ // StaticBitmapImages are 8-bit sRGB. Expose the color space and pixel
+ // format that is backing `image->GetMailboxHolder()`, or, alternatively,
+ // expose an accelerated SkImage.
+ if (accelerated_frame_pool_->CopyRGBATextureToVideoFrame(
+ viz::SkColorTypeToResourceFormat(kRGBA_8888_SkColorType),
+ gfx::Size(image->width(), image->height()),
+ gfx::ColorSpace::CreateSRGB(),
+ image->IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin
+ : kBottomLeft_GrSurfaceOrigin,
+ image->GetMailboxHolder(), std::move(blit_done_callback))) {
+ return;
+ }
+ }
ReadYUVPixelsAsync(image, context_provider);
} else {
ReadARGBPixelsAsync(image, context_provider->ContextProvider());
@@ -305,11 +347,12 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
blink::WebGraphicsContext3DProvider* context_provider) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
DCHECK(context_provider);
+ DCHECK(!image->CurrentFrameKnownToBeOpaque());
const base::TimeTicks timestamp = base::TimeTicks::Now();
- const bool is_opaque = image->CurrentFrameKnownToBeOpaque();
const media::VideoPixelFormat temp_argb_pixel_format =
- media::VideoPixelFormatFromSkColorType(kN32_SkColorType, is_opaque);
+ media::VideoPixelFormatFromSkColorType(kN32_SkColorType,
+ /*is_opaque = */ false);
const gfx::Size image_size(image->width(), image->height());
scoped_refptr<media::VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
temp_argb_pixel_format, image_size, gfx::Rect(image_size), image_size,
@@ -324,8 +367,7 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
"CanvasCaptureHandler::ReadARGBPixelsAsync supports only "
"kRGBA_8888_SkColorType and kBGRA_8888_SkColorType.");
SkImageInfo info = SkImageInfo::MakeN32(
- image_size.width(), image_size.height(),
- is_opaque ? kOpaque_SkAlphaType : kUnpremul_SkAlphaType);
+ image_size.width(), image_size.height(), kUnpremul_SkAlphaType);
GLuint row_bytes;
if (!base::CheckedNumeric<size_t>(info.minRowBytes())
.AssignIfValid(&row_bytes)) {
@@ -440,17 +482,15 @@ scoped_refptr<media::VideoFrame> CanvasCaptureHandler::ConvertToYUVFrame(
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
TRACE_EVENT0("webrtc", "CanvasCaptureHandler::ConvertToYUVFrame");
- const bool is_opaque = media::IsOpaque(temp_argb_frame->format());
+ const bool skip_alpha =
+ media::IsOpaque(temp_argb_frame->format()) || can_discard_alpha_;
const uint8_t* source_ptr =
temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane);
const gfx::Size image_size = temp_argb_frame->coded_size();
const int stride = temp_argb_frame->stride(media::VideoFrame::kARGBPlane);
- // TODO(https://crbug.com/1191932): Use |is_opaque || can_discard_alpha_|
- // instead of just |is_opaque| to determine if the format should be
- // I420 versus I420A.
scoped_refptr<media::VideoFrame> video_frame = frame_pool_.CreateFrame(
- is_opaque ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
+ skip_alpha ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
image_size, gfx::Rect(image_size), image_size, base::TimeDelta());
if (!video_frame) {
DLOG(ERROR) << "Couldn't allocate video frame";
@@ -487,7 +527,7 @@ scoped_refptr<media::VideoFrame> CanvasCaptureHandler::ConvertToYUVFrame(
DLOG(ERROR) << "Couldn't convert to I420";
return nullptr;
}
- if (!is_opaque) {
+ if (!skip_alpha) {
// It is ok to use ARGB function because alpha has the same alignment for
// both ABGR and ARGB.
libyuv::ARGBExtractAlpha(
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h
index 8596212f217..1feb573b94f 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h
@@ -18,6 +18,7 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "media/base/video_frame_pool.h"
#include "media/capture/video_capturer_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/gpu/GrTypes.h"
@@ -35,6 +36,7 @@ class MediaStreamComponent;
class StaticBitmapImage;
class WebGraphicsContext3DProvider;
class WebGraphicsContext3DProviderWrapper;
+class WebGraphicsContext3DVideoFramePool;
// CanvasCaptureHandler acts as the link between Blink side HTMLCanvasElement
// and Chrome side VideoCapturerSource. It is responsible for handling
@@ -130,9 +132,10 @@ class MODULES_EXPORT CanvasCaptureHandler {
class CanvasCaptureHandlerDelegate;
media::VideoCaptureFormat capture_format_;
- bool can_discard_alpha_ = true;
+ bool can_discard_alpha_ = false;
bool ask_for_new_frame_;
media::VideoFramePool frame_pool_;
+ std::unique_ptr<WebGraphicsContext3DVideoFramePool> accelerated_frame_pool_;
absl::optional<base::TimeTicks> first_frame_ticks_;
scoped_refptr<media::VideoFrame> last_frame_;
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
index c08dece8a46..e4732c24b2f 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
@@ -228,6 +228,32 @@ TEST_P(CanvasCaptureHandlerTest, VerifyFrame) {
run_loop.RunUntilIdle();
}
+// Verifies that SkImage is processed and produces VideoFrame as expected.
+TEST_F(CanvasCaptureHandlerTest, DropAlphaDeliversOpaqueFrame) {
+ const int width = 2;
+ const int height = 2;
+ InSequence s;
+ media::VideoCapturerSource* const source = GetVideoCapturerSource(
+ static_cast<blink::MediaStreamVideoCapturerSource*>(
+ component_->Source()->GetPlatformSource()));
+ EXPECT_TRUE(source);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
+ media::VideoCaptureParams params;
+ source->SetCanDiscardAlpha(true);
+ source->StartCapture(
+ params,
+ base::BindRepeating(&CanvasCaptureHandlerTest::OnVerifyDeliveredFrame,
+ base::Unretained(this), /*opaque_frame=*/true, width,
+ height),
+ base::BindRepeating(&CanvasCaptureHandlerTest::OnRunning,
+ base::Unretained(this)));
+ canvas_capture_handler_->SendNewFrame(
+ GenerateTestImage(/*opaque_frame=*/false, width, height), nullptr);
+ run_loop.RunUntilIdle();
+}
+
// Checks that needsNewFrame() works as expected.
TEST_F(CanvasCaptureHandlerTest, CheckNeedsNewFrame) {
InSequence s;
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/idls.gni b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/idls.gni
deleted file mode 100644
index 669ac6e20f6..00000000000
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/idls.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "canvas_capture_media_stream_track.idl" ]
-
-modules_dependency_idl_files = [
- "html_canvas_element_capture.idl",
- "html_media_element_capture.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/OWNERS b/chromium/third_party/blink/renderer/modules/mediarecorder/OWNERS
index f24322a13c0..072fd09f9d4 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/OWNERS
@@ -1,7 +1,5 @@
guidou@chromium.org
handellm@google.com
-peter@chromium.org
# Original (legacy) owner.
-emircan@chromium.org
mcasas@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_opus_encoder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_opus_encoder.cc
index aa352a09492..f56afee2d81 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_opus_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_opus_encoder.cc
@@ -6,8 +6,8 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "media/base/audio_sample_types.h"
#include "media/base/audio_timestamp_helper.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_pcm_encoder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_pcm_encoder.cc
index 5e2131e3b89..3b74195f1cb 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_pcm_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_pcm_encoder.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/modules/mediarecorder/audio_track_pcm_encoder.h"
+#include "base/cxx17_backports.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "media/base/audio_sample_types.h"
#include "media/base/audio_timestamp_helper.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc
index 80af6b90964..935b5d9f7cb 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc
@@ -39,6 +39,9 @@ struct CrossThreadCopier<media::AudioParameters> {
namespace blink {
+// Max size of buffers passed on to encoders.
+const int kMaxChunkedBufferDurationMs = 60;
+
AudioTrackRecorder::CodecId AudioTrackRecorder::GetPreferredCodecId() {
return CodecId::OPUS;
}
@@ -94,6 +97,14 @@ void AudioTrackRecorder::OnSetFormat(const media::AudioParameters& params) {
// If the source is restarted, might have changed to another capture thread.
DETACH_FROM_THREAD(capture_thread_checker_);
DCHECK_CALLED_ON_VALID_THREAD(capture_thread_checker_);
+
+ int max_frames_per_chunk = params.sample_rate() *
+ kMaxChunkedBufferDurationMs /
+ base::Time::kMillisecondsPerSecond;
+
+ frames_per_chunk_ =
+ std::min(params.frames_per_buffer(), max_frames_per_chunk);
+
PostCrossThreadTask(
*encoder_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&AudioTrackEncoder::OnSetFormat, encoder_, params));
@@ -103,15 +114,22 @@ void AudioTrackRecorder::OnData(const media::AudioBus& audio_bus,
base::TimeTicks capture_time) {
DCHECK_CALLED_ON_VALID_THREAD(capture_thread_checker_);
DCHECK(!capture_time.is_null());
-
- std::unique_ptr<media::AudioBus> audio_data =
- media::AudioBus::Create(audio_bus.channels(), audio_bus.frames());
- audio_bus.CopyTo(audio_data.get());
-
- PostCrossThreadTask(
- *encoder_task_runner_.get(), FROM_HERE,
- CrossThreadBindOnce(&AudioTrackEncoder::EncodeAudio, encoder_,
- std::move(audio_data), capture_time));
+ DCHECK_GT(frames_per_chunk_, 0) << "OnSetFormat not called before OnData";
+
+ for (int chunk_start = 0; chunk_start < audio_bus.frames();
+ chunk_start += frames_per_chunk_) {
+ std::unique_ptr<media::AudioBus> audio_data =
+ media::AudioBus::Create(audio_bus.channels(), frames_per_chunk_);
+ int chunk_size = chunk_start + frames_per_chunk_ >= audio_bus.frames()
+ ? audio_bus.frames() - chunk_start
+ : frames_per_chunk_;
+ audio_bus.CopyPartialFramesTo(chunk_start, chunk_size, 0, audio_data.get());
+
+ PostCrossThreadTask(
+ *encoder_task_runner_.get(), FROM_HERE,
+ CrossThreadBindOnce(&AudioTrackEncoder::EncodeAudio, encoder_,
+ std::move(audio_data), capture_time));
+ }
}
void AudioTrackRecorder::Pause() {
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h
index 2216e1d135e..5355286bc8d 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h
@@ -100,6 +100,9 @@ class MODULES_EXPORT AudioTrackRecorder
scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
+ // Number of frames per chunked buffer passed to the encoder.
+ int frames_per_chunk_ = 0;
+
DISALLOW_COPY_AND_ASSIGN(AudioTrackRecorder);
};
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
index 851775896be..6cb703de03e 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
@@ -32,8 +32,6 @@ using ::testing::_;
namespace {
const int kDefaultSampleRate = 48000;
-// The |frames_per_buffer| field of AudioParameters is not used by ATR.
-const int kIgnoreFramesPerBuffer = 1;
// The following parameters replicate those in audio_track_recorder.cc, see this
// file for explanations.
@@ -102,6 +100,11 @@ const ATRTestParams kATRTestParams[] = {
AudioTrackRecorder::BitrateMode::CONSTANT},
};
+int FramesPerBuffer(int sample_rate) {
+ return kMediaStreamAudioTrackBufferDurationMs * sample_rate /
+ base::Time::kMillisecondsPerSecond;
+}
+
class AudioTrackRecorderTest : public testing::TestWithParam<ATRTestParams> {
public:
// Initialize |first_params_| based on test parameters, and |second_params_|
@@ -111,11 +114,11 @@ class AudioTrackRecorderTest : public testing::TestWithParam<ATRTestParams> {
first_params_(GetParam().input_format,
GetParam().channel_layout,
GetParam().sample_rate,
- kIgnoreFramesPerBuffer),
+ FramesPerBuffer(GetParam().sample_rate)),
second_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
kDefaultSampleRate,
- kIgnoreFramesPerBuffer),
+ FramesPerBuffer(kDefaultSampleRate)),
first_source_(first_params_.channels(), /* # channels */
440, /* frequency */
first_params_.sample_rate()), /* sample rate */
@@ -202,12 +205,12 @@ class AudioTrackRecorderTest : public testing::TestWithParam<ATRTestParams> {
if (codec_ == AudioTrackRecorder::CodecId::OPUS) {
// Decode |encoded_data| and check we get the expected number of frames
// per buffer.
- EXPECT_EQ(
- kDefaultSampleRate * kOpusBufferDurationMs / 1000,
- opus_decode_float(
- opus_decoder_,
- reinterpret_cast<uint8_t*>(base::data(encoded_data)),
- encoded_data.size(), opus_buffer_.get(), kFramesPerBuffer, 0));
+ EXPECT_EQ(kDefaultSampleRate * kOpusBufferDurationMs / 1000,
+ opus_decode_float(
+ opus_decoder_,
+ reinterpret_cast<uint8_t*>(base::data(encoded_data)),
+ static_cast<wtf_size_t>(encoded_data.size()),
+ opus_buffer_.get(), kFramesPerBuffer, 0));
} else if (codec_ == AudioTrackRecorder::CodecId::PCM) {
// Manually confirm that we're getting the same data out as what we
// generated from the sine wave.
@@ -246,7 +249,7 @@ class AudioTrackRecorderTest : public testing::TestWithParam<ATRTestParams> {
// Save the data we generate from the first source so that we might compare it
// later if we happen to be using the PCM encoder.
Vector<float> first_source_cache_;
- size_t first_source_cache_pos_;
+ wtf_size_t first_source_cache_pos_;
private:
// Prepares a blink track of a given MediaStreamType and attaches the native
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/idls.gni b/chromium/third_party/blink/renderer/modules/mediarecorder/idls.gni
deleted file mode 100644
index b7495f219b1..00000000000
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/idls.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "blob_event.idl",
- "media_recorder.idl",
-]
-
-modules_dictionary_idl_files = [
- "blob_event_init.idl",
- "media_recorder_options.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc
index 138a25176f0..dcae2874506 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc
@@ -16,6 +16,7 @@
#include "media/base/mime_util.h"
#include "media/base/video_codecs.h"
#include "media/base/video_frame.h"
+#include "media/muxers/live_webm_muxer_delegate.h"
#include "media/muxers/webm_muxer.h"
#include "third_party/blink/renderer/modules/mediarecorder/buildflags.h"
#include "third_party/blink/renderer/modules/mediarecorder/media_recorder.h"
@@ -290,8 +291,8 @@ bool MediaRecorderHandler::Start(int timeslice) {
webm_muxer_ = std::make_unique<media::WebmMuxer>(
CodecIdToMediaAudioCodec(audio_codec_id_), use_video_tracks,
use_audio_tracks,
- WTF::BindRepeating(&MediaRecorderHandler::WriteData,
- WrapWeakPersistent(this)));
+ std::make_unique<media::LiveWebmMuxerDelegate>(WTF::BindRepeating(
+ &MediaRecorderHandler::WriteData, WrapWeakPersistent(this))));
if (timeslice > 0) {
webm_muxer_->SetMaximumDurationToForceDataOutput(timeslice_);
}
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
index 5443a238a95..1a1d806b3aa 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
@@ -11,6 +11,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/web/modules/mediastream/encoded_video_frame.h"
#include "third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h"
#include "third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
index 1a8f354cc0d..2144e0838ce 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
@@ -11,6 +11,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/bitrate.h"
#include "media/base/video_frame.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/public/platform/platform.h"
@@ -315,9 +316,11 @@ void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size,
media::VideoEncodeAccelerator::Config::StorageType::kGpuMemoryBuffer;
}
+ // TODO(b/181797390): Use VBR bitrate mode.
const media::VideoEncodeAccelerator::Config config(
- pixel_format, input_visible_size_, codec_, bits_per_second_,
- absl::nullopt, absl::nullopt, level_, false, storage_type,
+ pixel_format, input_visible_size_, codec_,
+ media::Bitrate::ConstantBitrate(bits_per_second_), absl::nullopt,
+ absl::nullopt, level_, false, storage_type,
media::VideoEncodeAccelerator::Config::ContentType::kCamera);
if (!video_encoder_ || !video_encoder_->Initialize(config, this))
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/OWNERS b/chromium/third_party/blink/renderer/modules/mediasession/OWNERS
index 3fc0474cca2..e0bbeb1b9e8 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/mediasession/OWNERS
@@ -1,4 +1,3 @@
-foolip@chromium.org
steimel@chromium.org
per-file *_mojom_traits*.*=set noparent
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/idls.gni b/chromium/third_party/blink/renderer/modules/mediasession/idls.gni
deleted file mode 100644
index 57915a56a55..00000000000
--- a/chromium/third_party/blink/renderer/modules/mediasession/idls.gni
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "media_metadata.idl",
- "media_session.idl",
-]
-
-modules_dictionary_idl_files = [
- "media_image.idl",
- "media_metadata_init.idl",
- "media_position_state.idl",
- "media_session_action_details.idl",
- "media_session_seek_to_action_details.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_media_session.idl" ]
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 28402fa649b..dad24d2083c 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
@@ -9,6 +9,7 @@
#include "base/time/default_tick_clock.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_position_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_session_action_details.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_session_action_handler.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/DEPS b/chromium/third_party/blink/renderer/modules/mediasource/DEPS
index a7b4b9d51b3..27f03974488 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/DEPS
+++ b/chromium/third_party/blink/renderer/modules/mediasource/DEPS
@@ -1,7 +1,9 @@
include_rules = [
"-third_party/blink/renderer/modules",
+ "+base/command_line.h",
"+media/base/audio_decoder_config.h",
"+media/base/logging_override_if_enabled.h",
+ "+media/base/media_switches.h",
"+media/base/mime_util.h",
"+media/base/stream_parser.h",
"+media/base/stream_parser_buffer.h",
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/idls.gni b/chromium/third_party/blink/renderer/modules/mediasource/idls.gni
deleted file mode 100644
index 5dfa8b3e6db..00000000000
--- a/chromium/third_party/blink/renderer/modules/mediasource/idls.gni
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "media_source.idl",
- "source_buffer.idl",
- "source_buffer_list.idl",
- "track_default.idl",
- "track_default_list.idl",
- "video_playback_quality.idl",
-]
-
-modules_dictionary_idl_files = [ "source_buffer_config.idl" ]
-
-modules_dependency_idl_files = [
- "audio_track_source_buffer.idl",
- "html_video_element_media_source.idl",
- "url_media_source.idl",
- "video_track_source_buffer.idl",
-]
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 fbe5daa0c64..85679fec4ed 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -6,10 +6,12 @@
#include <memory>
+#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/logging_override_if_enabled.h"
+#include "media/base/media_switches.h"
#include "media/base/mime_util.h"
#include "media/base/supported_types.h"
#include "media/base/video_decoder_config.h"
@@ -544,16 +546,22 @@ bool MediaSource::IsTypeSupportedInternal(ExecutionContext* context,
// HTMLMediaElement knows it cannot play.
String codecs = content_type.Parameter("codecs");
MIMETypeRegistry::SupportsType get_supports_type_result;
-#if BUILDFLAG(ENABLE_PLATFORM_HEVC) && BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
- // Here, we special-case for HEVC on ChromeOS, which is only supported if
- // encrypted. isTypeSupported(fully qualified type with hevc codec) should say
- // false on such platform (except if kEnableClearHevcForTesting cmdline switch
- // is used, enabling GetSupportsType success), but addSourceBuffer(same) and
+#if BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC)
+ // Here, we special-case when encrypted HEVC is supported.
+ // isTypeSupported(fully qualified type with hevc codec) should say false on
+ // such platform (except if kEnableClearHevcForTesting cmdline switch is used,
+ // enabling GetSupportsType success), but addSourceBuffer(same) and
// changeType(same) shouldn't fail just due to having HEVC codec. We use
// |enforce_codec_specificity| to understand if we are servicing iTS (if true)
// versus aSB (if false). If servicing aSB or cT, we'll remove any detected
// hevc codec from the codecs we use in the GetSupportsType() query.
- if (!enforce_codec_specificity) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ const bool allow_hevc = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kLacrosEnablePlatformEncryptedHevc);
+#else
+ const bool allow_hevc = true;
+#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
+ if (allow_hevc && !enforce_codec_specificity) {
// Remove any detected HEVC codec from the query to GetSupportsType.
std::string filtered_codecs;
std::vector<std::string> parsed_codec_ids;
@@ -584,14 +592,13 @@ bool MediaSource::IsTypeSupportedInternal(ExecutionContext* context,
get_supports_type_result = HTMLMediaElement::GetSupportsType(
ContentType(String::FromUTF8(filtered_type.c_str())));
} else {
- // Even on ChromeOS with HEVC support, don't filter out HEVC codec when
+ // Even on platforms with HEVC support, don't filter out HEVC codec when
// servicing isTypeSupported().
get_supports_type_result = HTMLMediaElement::GetSupportsType(content_type);
}
#else
get_supports_type_result = HTMLMediaElement::GetSupportsType(content_type);
-#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) &&
- // BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
+#endif // BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC)
if (get_supports_type_result == MIMETypeRegistry::kIsNotSupported) {
DVLOG(1) << __func__ << "(" << type << ", "
@@ -744,11 +751,14 @@ void MediaSource::CompleteAttachingToMediaElement(
SetReadyState(ReadyState::kOpen);
}
-double MediaSource::duration() const {
- if (IsClosed())
+double MediaSource::GetDuration_Locked(
+ MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */) const {
+ AssertAttachmentsMutexHeldIfCrossThreadForDebugging();
+
+ if (IsClosed()) {
return std::numeric_limits<float>::quiet_NaN();
+ }
- AssertAttachmentsMutexHeldIfCrossThreadForDebugging();
return web_media_source_->Duration();
}
@@ -825,7 +835,8 @@ WebTimeRanges MediaSource::SeekableInternal(
// http://w3c.github.io/media-source/#htmlmediaelement-extensions
WebTimeRanges ranges;
- double source_duration = duration();
+ double source_duration = GetDuration_Locked(pass_key);
+
// If duration equals NaN: Return an empty TimeRanges object.
if (std::isnan(source_duration))
return ranges;
@@ -947,15 +958,38 @@ void MediaSource::setDuration(double duration,
}
}
+double MediaSource::duration() {
+ double duration_result = std::numeric_limits<float>::quiet_NaN();
+ if (IsClosed())
+ return duration_result;
+
+ // Note, here we must be open or ended, therefore we must have an attachment.
+ if (!RunUnlessElementGoneOrClosingUs(WTF::Bind(
+ [](MediaSource* self, double* result,
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key) {
+ *result = self->GetDuration_Locked(pass_key);
+ },
+ WrapPersistent(this), WTF::Unretained(&duration_result)))) {
+ // TODO(https://crbug.com/878133): Determine in specification what the
+ // specific, app-visible, result should be in this case. It seems reasonable
+ // to behave is if we are in "closed" readyState and report NaN to the app
+ // here.
+ DCHECK_EQ(duration_result, std::numeric_limits<float>::quiet_NaN());
+ }
+
+ return duration_result;
+}
+
void MediaSource::DurationChangeAlgorithm(
double new_duration,
ExceptionState* exception_state,
- MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */) {
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key) {
AssertAttachmentsMutexHeldIfCrossThreadForDebugging();
// http://w3c.github.io/media-source/#duration-change-algorithm
// 1. If the current value of duration is equal to new duration, then return.
- if (new_duration == duration())
+ double old_duration = GetDuration_Locked(pass_key);
+ if (new_duration == old_duration)
return;
// 2. If new duration is less than the highest starting presentation
@@ -988,11 +1022,11 @@ void MediaSource::DurationChangeAlgorithm(
// See also deprecated remove(new duration, old duration) behavior below.
}
- // 3. Set old duration to the current value of duration.
- double old_duration = duration();
DCHECK_LE(highest_buffered_presentation_timestamp,
std::isnan(old_duration) ? 0 : old_duration);
+ // 3. Set old duration to the current value of duration.
+ // Done for step 1 above, already.
// 4. Update duration to new duration.
web_media_source_->SetDuration(new_duration);
@@ -1205,7 +1239,7 @@ MediaSource::AttachmentAndTracer() const {
void MediaSource::EndOfStreamAlgorithm(
const WebMediaSource::EndOfStreamStatus eos_status,
- MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */) {
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key) {
AssertAttachmentsMutexHeldIfCrossThreadForDebugging();
// https://www.w3.org/TR/media-source/#end-of-stream-algorithm
@@ -1235,7 +1269,7 @@ void MediaSource::EndOfStreamAlgorithm(
// TODO(wolenetz): Consider refactoring the MarkEndOfStream implementation
// to just mark end of stream, and move the duration reduction logic to here
// so we can just run DurationChangeAlgorithm(...) here.
- double new_duration = duration();
+ double new_duration = GetDuration_Locked(pass_key);
scoped_refptr<MediaSourceAttachmentSupplement> attachment;
MediaSourceTracer* tracer;
std::tie(attachment, tracer) = AttachmentAndTracer();
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 cc8c53e035b..523543c85d9 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -80,6 +80,7 @@ class MediaSource final : public EventTargetWithInlineData,
LOCKS_EXCLUDED(attachment_link_lock_);
void setDuration(double, ExceptionState&)
LOCKS_EXCLUDED(attachment_link_lock_);
+ double duration() LOCKS_EXCLUDED(attachment_link_lock_);
DEFINE_ATTRIBUTE_EVENT_LISTENER(sourceopen, kSourceopen)
DEFINE_ATTRIBUTE_EVENT_LISTENER(sourceended, kSourceended)
@@ -125,7 +126,9 @@ class MediaSource final : public EventTargetWithInlineData,
LOCKS_EXCLUDED(attachment_link_lock_);
void Close();
bool IsClosed() const;
- double duration() const LOCKS_EXCLUDED(attachment_link_lock_);
+ double GetDuration_Locked(
+ MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */) const
+ LOCKS_EXCLUDED(attachment_link_lock_);
WebTimeRanges BufferedInternal(
MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */) const
LOCKS_EXCLUDED(attachment_link_lock_);
@@ -159,7 +162,7 @@ class MediaSource final : public EventTargetWithInlineData,
// attachment's RunExclusively() callback.
void EndOfStreamAlgorithm(
const WebMediaSource::EndOfStreamStatus,
- MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */)
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key)
LOCKS_EXCLUDED(attachment_link_lock_);
// Helper to run operations while holding cross-thread attachment's exclusive
@@ -227,7 +230,7 @@ class MediaSource final : public EventTargetWithInlineData,
void DurationChangeAlgorithm(
double new_duration,
ExceptionState*,
- MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */)
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key)
LOCKS_EXCLUDED(attachment_link_lock_);
// Usage of |*web_media_source_| must be within scope of attachment's
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc b/chromium/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc
index 2003129b0dc..fb24adf9026 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc
@@ -86,7 +86,10 @@ scoped_refptr<MediaSourceAttachment> MediaSourceRegistryImpl::LookupMediaSource(
DCHECK(IsMainThread());
DCHECK(!url.IsEmpty());
- return media_sources_.at(url);
+ auto iter = media_sources_.find(url);
+ if (iter == media_sources_.end())
+ return nullptr;
+ return iter->value;
}
MediaSourceRegistryImpl::MediaSourceRegistryImpl() {
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 b3653f110cb..fb0c0afba54 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
@@ -41,8 +41,6 @@
#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/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/encoded_audio_chunk_or_encoded_video_chunk.h"
-#include "third_party/blink/renderer/bindings/modules/v8/encoded_av_chunk_sequence_or_encoded_av_chunk.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.h"
@@ -77,6 +75,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
using blink::WebSourceBuffer;
@@ -142,22 +141,19 @@ scoped_refptr<media::StreamParserBuffer> MakeAudioStreamParserBuffer(
const EncodedAudioChunk& audio_chunk) {
// TODO(crbug.com/1144908): DecoderBuffer takes size_t size, but
// StreamParserBuffer takes int. Fix this. For now, checked_cast is used.
+ // TODO(crbug.com/1144908): Add a way for StreamParserBuffer to share the
+ // same underlying DecoderBuffer.
auto stream_parser_buffer = media::StreamParserBuffer::CopyFrom(
- static_cast<uint8_t*>(audio_chunk.data()->Data()),
- base::checked_cast<int>(audio_chunk.data()->ByteLength()),
- audio_chunk.type() == "key", media::DemuxerStream::AUDIO,
+ audio_chunk.buffer()->data(),
+ base::checked_cast<int>(audio_chunk.buffer()->data_size()),
+ audio_chunk.buffer()->is_key_frame(), media::DemuxerStream::AUDIO,
kWebCodecsAudioTrackId);
- // TODO(crbug.com/1144908): Remove or change the following to DCHECK once
- // StreamParserBuffer::CopyFrom takes size_t, not int.
- CHECK_EQ(audio_chunk.data()->ByteLength(), stream_parser_buffer->data_size());
-
// Currently, we do not populate any side_data in these converters.
DCHECK_EQ(0U, stream_parser_buffer->side_data_size());
DCHECK_EQ(nullptr, stream_parser_buffer->side_data());
- stream_parser_buffer->set_timestamp(
- base::TimeDelta::FromMicroseconds(audio_chunk.timestamp()));
+ stream_parser_buffer->set_timestamp(audio_chunk.buffer()->timestamp());
// TODO(crbug.com/1144908): Get EncodedAudioChunk to have an optional duration
// attribute, and require it to be populated for use by MSE-for-WebCodecs,
// here. For initial prototype, hard-coded 22ms is used as estimated duration.
@@ -171,30 +167,26 @@ scoped_refptr<media::StreamParserBuffer> MakeVideoStreamParserBuffer(
const EncodedVideoChunk& video_chunk) {
// TODO(crbug.com/1144908): DecoderBuffer takes size_t size, but
// StreamParserBuffer takes int. Fix this. For now, checked_cast is used.
+ // TODO(crbug.com/1144908): Add a way for StreamParserBuffer to share the
+ // same underlying DecoderBuffer.
auto stream_parser_buffer = media::StreamParserBuffer::CopyFrom(
- static_cast<uint8_t*>(video_chunk.data()->Data()),
- base::checked_cast<int>(video_chunk.data()->ByteLength()),
- video_chunk.type() == "key", media::DemuxerStream::VIDEO,
+ video_chunk.buffer()->data(),
+ base::checked_cast<int>(video_chunk.buffer()->data_size()),
+ video_chunk.buffer()->is_key_frame(), media::DemuxerStream::VIDEO,
kWebCodecsVideoTrackId);
- // TODO(crbug.com/1144908): Remove or change the following to DCHECK once
- // StreamParserBuffer::CopyFrom takes size_t, not int.
- CHECK_EQ(video_chunk.data()->ByteLength(), stream_parser_buffer->data_size());
-
// Currently, we do not populate any side_data in these converters.
DCHECK_EQ(0U, stream_parser_buffer->side_data_size());
DCHECK_EQ(nullptr, stream_parser_buffer->side_data());
- stream_parser_buffer->set_timestamp(
- base::TimeDelta::FromMicroseconds(video_chunk.timestamp()));
+ stream_parser_buffer->set_timestamp(video_chunk.buffer()->timestamp());
// TODO(crbug.com/1144908): Get EncodedVideoChunk to have an optional decode
// timestamp attribute. If it is populated, use it for the DTS of the
// StreamParserBuffer, here. For initial prototype, only in-order PTS==DTS
// chunks are supported. Out-of-order chunks may result in buffered range gaps
// or decode errors.
DCHECK(video_chunk.duration().has_value());
- stream_parser_buffer->set_duration(
- base::TimeDelta::FromMicroseconds(video_chunk.duration().value()));
+ stream_parser_buffer->set_duration(video_chunk.buffer()->duration());
return stream_parser_buffer;
}
@@ -633,11 +625,7 @@ void SourceBuffer::appendBuffer(NotShared<DOMArrayBufferView> data,
// append use-cases.
ScriptPromise SourceBuffer::appendEncodedChunks(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8EncodedChunks* chunks,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const EncodedChunks& chunks,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
DVLOG(2) << __func__ << " this=" << this;
@@ -661,7 +649,6 @@ ScriptPromise SourceBuffer::appendEncodedChunks(
auto buffer_queue = std::make_unique<media::StreamParser::BufferQueue>();
size_t size = 0;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (chunks->GetContentType()) {
case V8EncodedChunks::ContentType::kEncodedAudioChunk:
buffer_queue->emplace_back(
@@ -716,55 +703,6 @@ ScriptPromise SourceBuffer::appendEncodedChunks(
}
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (chunks.IsEncodedAudioChunk()) {
- buffer_queue->emplace_back(
- MakeAudioStreamParserBuffer(*(chunks.GetAsEncodedAudioChunk())));
- size += buffer_queue->back()->data_size() +
- buffer_queue->back()->side_data_size();
- } else if (chunks.IsEncodedVideoChunk()) {
- const auto& video_chunk = *(chunks.GetAsEncodedVideoChunk());
- if (!video_chunk.duration().has_value()) {
- MediaSource::LogAndThrowTypeError(
- exception_state,
- "EncodedVideoChunk is missing duration, required for use with "
- "SourceBuffer.");
- return ScriptPromise();
- ;
- }
- buffer_queue->emplace_back(MakeVideoStreamParserBuffer(video_chunk));
- size += buffer_queue->back()->data_size() +
- buffer_queue->back()->side_data_size();
- } else if (chunks.IsEncodedAudioChunkOrEncodedVideoChunkSequence()) {
- for (const auto& av_chunk :
- chunks.GetAsEncodedAudioChunkOrEncodedVideoChunkSequence()) {
- // TODO(crbug.com/1144908): Can null entries occur in the sequence, and
- // should they be ignored or should they cause exception? Ignoring for
- // now, if they occur.
- if (av_chunk.IsNull())
- continue;
- if (av_chunk.IsEncodedAudioChunk()) {
- buffer_queue->emplace_back(
- MakeAudioStreamParserBuffer(*(av_chunk.GetAsEncodedAudioChunk())));
- size += buffer_queue->back()->data_size() +
- buffer_queue->back()->side_data_size();
- } else if (av_chunk.IsEncodedVideoChunk()) {
- const auto& video_chunk = *(av_chunk.GetAsEncodedVideoChunk());
- if (!video_chunk.duration().has_value()) {
- MediaSource::LogAndThrowTypeError(
- exception_state,
- "EncodedVideoChunk is missing duration, required for use with "
- "SourceBuffer.");
- return ScriptPromise();
- ;
- }
- buffer_queue->emplace_back(MakeVideoStreamParserBuffer(video_chunk));
- size += buffer_queue->back()->data_size() +
- buffer_queue->back()->side_data_size();
- }
- }
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(!append_encoded_chunks_resolver_);
append_encoded_chunks_resolver_ =
@@ -951,7 +889,7 @@ void SourceBuffer::Remove_Locked(
double start,
double end,
ExceptionState* exception_state,
- MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */) {
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key) {
DCHECK(source_);
DCHECK(!updating_);
source_->AssertAttachmentsMutexHeldIfCrossThreadForDebugging();
@@ -960,7 +898,7 @@ void SourceBuffer::Remove_Locked(
// steps.
// 4. If start is negative or greater than duration, then throw a TypeError
// exception and abort these steps.
- double duration = source_->duration();
+ double duration = source_->GetDuration_Locked(pass_key);
if (start < 0 || std::isnan(duration) || start > duration) {
MediaSource::LogAndThrowTypeError(
*exception_state,
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 6592b2da07d..9947814a966 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h
@@ -53,8 +53,6 @@ namespace blink {
class AudioTrackList;
class DOMArrayBuffer;
class DOMArrayBufferView;
-class
- EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk;
class EventQueue;
class ExceptionState;
class MediaSource;
@@ -78,10 +76,6 @@ class SourceBuffer final : public EventTargetWithInlineData,
static AtomicString SegmentsKeyword();
static AtomicString SequenceKeyword();
- // Mirror the IDL's typedef for EncodedChunks.
- using EncodedChunks =
- EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk;
-
SourceBuffer(std::unique_ptr<WebSourceBuffer>, MediaSource*, EventQueue*);
~SourceBuffer() override;
@@ -94,15 +88,9 @@ class SourceBuffer final : public EventTargetWithInlineData,
void setTimestampOffset(double, ExceptionState&);
void appendBuffer(DOMArrayBuffer* data, ExceptionState&);
void appendBuffer(NotShared<DOMArrayBufferView> data, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise appendEncodedChunks(ScriptState* script_state,
const V8EncodedChunks* chunks,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise appendEncodedChunks(ScriptState*,
- const EncodedChunks&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void abort(ExceptionState&);
void remove(double start, double end, ExceptionState&);
void changeType(const String& type, ExceptionState&);
@@ -189,11 +177,10 @@ class SourceBuffer final : public EventTargetWithInlineData,
MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */);
void Abort_Locked(
MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */);
- void Remove_Locked(
- double start,
- double end,
- ExceptionState*,
- MediaSourceAttachmentSupplement::ExclusiveKey /* passkey */);
+ void Remove_Locked(double start,
+ double end,
+ ExceptionState*,
+ MediaSourceAttachmentSupplement::ExclusiveKey pass_key);
void ChangeType_Locked(
const String& type,
ExceptionState*,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn b/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn
index c2884478b0a..108eb4cbfe2 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -68,7 +68,6 @@ blink_modules_sources("mediastream") {
"media_stream_video_source.cc",
"media_stream_video_track.cc",
"media_stream_video_track.h",
- "media_stream_video_track_signal_observer.h",
"navigator_media_stream.cc",
"navigator_media_stream.h",
"overconstrained_error.cc",
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/OWNERS b/chromium/third_party/blink/renderer/modules/mediastream/OWNERS
index 947c899590e..7a520486fd4 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/mediastream/OWNERS
@@ -3,3 +3,6 @@ hbos@chromium.org
tommi@chromium.org
per-file media_stream_audio_processor*=olka@chromium.org
+per-file low_latency_video*=kron@chromium.org
+per-file webmediaplayer_ms*=kron@chromium.org
+per-file video_renderer_algorithm*=kron@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.cc b/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.cc
index a3b10444119..8d2a60e370a 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/mediastream/capture_handle_change_event.h"
-#include "third_party/blink/renderer/modules/mediastream/capture_handle.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_capture_handle.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.idl b/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.idl
index b522755e101..e0d0fe4e4e0 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.idl
+++ b/chromium/third_party/blink/renderer/modules/mediastream/capture_handle_change_event.idl
@@ -8,5 +8,5 @@
Exposed = Window, RuntimeEnabled = CaptureHandle
] interface CaptureHandleChangeEvent : Event {
constructor(DOMString type, CaptureHandleChangeEventInit eventInitDict);
- [SameObject] readonly attribute CaptureHandle captureHandle;
+ [SameObject] CaptureHandle captureHandle();
};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/identifiability_metrics.cc b/chromium/third_party/blink/renderer/modules/mediastream/identifiability_metrics.cc
index 79122a408b5..a95f05b4ee5 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/identifiability_metrics.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/identifiability_metrics.cc
@@ -8,15 +8,24 @@
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-#include "third_party/blink/renderer/bindings/modules/v8/boolean_or_constrain_boolean_parameters.h"
-#include "third_party/blink/renderer/bindings/modules/v8/boolean_or_double_or_constrain_double_range.h"
-#include "third_party/blink/renderer/bindings/modules/v8/boolean_or_media_track_constraints.h"
-#include "third_party/blink/renderer/bindings/modules/v8/double_or_constrain_double_range.h"
-#include "third_party/blink/renderer/bindings/modules/v8/long_or_constrain_long_range.h"
-#include "third_party/blink/renderer/bindings/modules/v8/point_2d_sequence_or_constrain_point_2d_parameters.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_string_sequence_or_constrain_dom_string_parameters.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_boolean_parameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_dom_string_parameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_double_range.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_long_range.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_point_2d_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraint_set.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_point_2d.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_constrainbooleanparameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_constraindoublerange_double.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_mediatrackconstraints.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindomstringparameters_string_stringsequence.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindoublerange_double.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constrainlongrange_long.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constrainpoint2dparameters_point2dsequence.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
@@ -24,12 +33,6 @@ namespace blink {
namespace {
-using ConstrainLong = LongOrConstrainLongRange;
-using ConstrainDouble = DoubleOrConstrainDoubleRange;
-using ConstrainBoolean = BooleanOrConstrainBooleanParameters;
-using ConstrainDOMString = StringOrStringSequenceOrConstrainDOMStringParameters;
-using ConstrainPoint2D = Point2DSequenceOrConstrainPoint2DParameters;
-
template <typename T>
void Visit(IdentifiableTokenBuilder& builder, const T* range) {
if (!range)
@@ -40,111 +43,119 @@ void Visit(IdentifiableTokenBuilder& builder, const T* range) {
builder.AddToken(range->hasMin() ? range->min() : IdentifiableToken());
}
-void Visit(IdentifiableTokenBuilder& builder, const ConstrainDouble& d) {
- if (d.IsDouble()) {
- builder.AddToken(d.GetAsDouble());
+void Visit(IdentifiableTokenBuilder& builder, const V8ConstrainDouble* d) {
+ if (!d) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (d.IsConstrainDoubleRange()) {
- Visit(builder, d.GetAsConstrainDoubleRange());
- return;
+ switch (d->GetContentType()) {
+ case V8ConstrainDouble::ContentType::kConstrainDoubleRange:
+ return Visit(builder, d->GetAsConstrainDoubleRange());
+ case V8ConstrainDouble::ContentType::kDouble:
+ builder.AddToken(d->GetAsDouble());
+ return;
}
- DCHECK(d.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
-void Visit(IdentifiableTokenBuilder& builder, const ConstrainLong& l) {
- if (l.IsLong()) {
- builder.AddToken(l.GetAsLong());
+void Visit(IdentifiableTokenBuilder& builder, const V8ConstrainLong* l) {
+ if (!l) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (l.IsConstrainLongRange()) {
- Visit(builder, l.GetAsConstrainLongRange());
- return;
+ switch (l->GetContentType()) {
+ case V8ConstrainLong::ContentType::kConstrainLongRange:
+ return Visit(builder, l->GetAsConstrainLongRange());
+ case V8ConstrainLong::ContentType::kLong:
+ builder.AddToken(l->GetAsLong());
+ return;
}
- DCHECK(l.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
-void Visit(IdentifiableTokenBuilder& builder, const StringOrStringSequence& s) {
- if (s.IsString()) {
- builder.AddToken(IdentifiabilityBenignStringToken(s.GetAsString()));
+void Visit(IdentifiableTokenBuilder& builder,
+ const V8UnionStringOrStringSequence* s) {
+ if (!s) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (s.IsStringSequence()) {
- for (const String& str : s.GetAsStringSequence()) {
- builder.AddToken(IdentifiabilityBenignStringToken(str));
- }
- return;
+ switch (s->GetContentType()) {
+ case V8UnionStringOrStringSequence::ContentType::kString:
+ builder.AddToken(IdentifiabilityBenignStringToken(s->GetAsString()));
+ return;
+ case V8UnionStringOrStringSequence::ContentType::kStringSequence:
+ for (const String& str : s->GetAsStringSequence()) {
+ builder.AddToken(IdentifiabilityBenignStringToken(str));
+ }
+ return;
}
- DCHECK(s.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
-void Visit(IdentifiableTokenBuilder& builder, const ConstrainDOMString& s) {
- if (s.IsString()) {
- builder.AddToken(IdentifiabilityBenignStringToken(s.GetAsString()));
- return;
- }
- if (s.IsStringSequence()) {
- for (const String& str : s.GetAsStringSequence()) {
- builder.AddToken(IdentifiabilityBenignStringToken(str));
- }
+void Visit(IdentifiableTokenBuilder& builder, const V8ConstrainDOMString* s) {
+ if (!s) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (s.IsConstrainDOMStringParameters()) {
- const ConstrainDOMStringParameters* params =
- s.GetAsConstrainDOMStringParameters();
- if (params->hasExact()) {
- Visit(builder, params->exact());
- } else {
- builder.AddToken(IdentifiableToken());
- }
- if (params->hasIdeal()) {
- Visit(builder, params->ideal());
- } else {
- builder.AddToken(IdentifiableToken());
+ switch (s->GetContentType()) {
+ case V8ConstrainDOMString::ContentType::kConstrainDOMStringParameters: {
+ const ConstrainDOMStringParameters* params =
+ s->GetAsConstrainDOMStringParameters();
+ Visit(builder, params->getExactOr(nullptr));
+ Visit(builder, params->getIdealOr(nullptr));
+ return;
}
- return;
+ case V8ConstrainDOMString::ContentType::kString:
+ builder.AddToken(IdentifiabilityBenignStringToken(s->GetAsString()));
+ return;
+ case V8ConstrainDOMString::ContentType::kStringSequence:
+ for (const String& str : s->GetAsStringSequence()) {
+ builder.AddToken(IdentifiabilityBenignStringToken(str));
+ }
+ return;
}
- DCHECK(s.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
-void Visit(IdentifiableTokenBuilder& builder, const ConstrainBoolean& b) {
- if (b.IsBoolean()) {
- builder.AddToken(b.GetAsBoolean());
+void Visit(IdentifiableTokenBuilder& builder, const V8ConstrainBoolean* b) {
+ if (!b) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (b.IsConstrainBooleanParameters()) {
- const ConstrainBooleanParameters* params =
- b.GetAsConstrainBooleanParameters();
- builder.AddToken(params->hasExact() ? params->exact()
- : IdentifiableToken());
- builder.AddToken(params->hasIdeal() ? params->ideal()
- : IdentifiableToken());
- return;
+ switch (b->GetContentType()) {
+ case V8ConstrainBoolean::ContentType::kBoolean:
+ builder.AddToken(b->GetAsBoolean());
+ return;
+ case V8ConstrainBoolean::ContentType::kConstrainBooleanParameters: {
+ const ConstrainBooleanParameters* params =
+ b->GetAsConstrainBooleanParameters();
+ builder.AddToken(params->hasExact() ? params->exact()
+ : IdentifiableToken());
+ builder.AddToken(params->hasIdeal() ? params->ideal()
+ : IdentifiableToken());
+ return;
+ }
}
- DCHECK(b.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
void Visit(IdentifiableTokenBuilder& builder,
- const BooleanOrDoubleOrConstrainDoubleRange& x) {
- if (x.IsBoolean()) {
- builder.AddToken(x.GetAsBoolean());
+ const V8UnionBooleanOrConstrainDouble* x) {
+ if (!x) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (x.IsConstrainDoubleRange()) {
- Visit(builder, x.GetAsConstrainDoubleRange());
- return;
+ switch (x->GetContentType()) {
+ case V8UnionBooleanOrConstrainDouble::ContentType::kBoolean:
+ builder.AddToken(x->GetAsBoolean());
+ return;
+ case V8UnionBooleanOrConstrainDouble::ContentType::kConstrainDoubleRange:
+ return Visit(builder, x->GetAsConstrainDoubleRange());
+ case V8UnionBooleanOrConstrainDouble::ContentType::kDouble:
+ builder.AddToken(x->GetAsDouble());
+ return;
}
- if (x.IsDouble()) {
- builder.AddToken(x.GetAsDouble());
- return;
- }
- DCHECK(x.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
void Visit(IdentifiableTokenBuilder& builder,
@@ -155,96 +166,94 @@ void Visit(IdentifiableTokenBuilder& builder,
}
}
-void Visit(IdentifiableTokenBuilder& builder, const ConstrainPoint2D& x) {
- if (x.IsPoint2DSequence()) {
- Visit(builder, x.GetAsPoint2DSequence());
+void Visit(IdentifiableTokenBuilder& builder, const V8ConstrainPoint2D* p) {
+ if (!p) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (x.IsConstrainPoint2DParameters()) {
- const ConstrainPoint2DParameters* params =
- x.GetAsConstrainPoint2DParameters();
- if (params->hasExact()) {
- Visit(builder, params->exact());
- } else {
- builder.AddToken(IdentifiableToken());
- }
- if (params->hasIdeal()) {
- Visit(builder, params->ideal());
- } else {
- builder.AddToken(IdentifiableToken());
+ switch (p->GetContentType()) {
+ case V8ConstrainPoint2D::ContentType::kConstrainPoint2DParameters: {
+ const ConstrainPoint2DParameters* params =
+ p->GetAsConstrainPoint2DParameters();
+ if (params->hasExact()) {
+ Visit(builder, params->exact());
+ } else {
+ builder.AddToken(IdentifiableToken());
+ }
+ if (params->hasIdeal()) {
+ Visit(builder, params->ideal());
+ } else {
+ builder.AddToken(IdentifiableToken());
+ }
+ return;
}
- return;
+ case V8ConstrainPoint2D::ContentType::kPoint2DSequence:
+ return Visit(builder, p->GetAsPoint2DSequence());
}
- DCHECK(x.IsNull());
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
void Visit(IdentifiableTokenBuilder& builder,
const MediaTrackConstraintSet& set) {
// TODO(crbug.com/1070871): As a workaround for code simplicity, we use a
// default value of a union type if each member is not provided in input.
- Visit(builder, set.hasWidth() ? set.width() : ConstrainLong());
- Visit(builder, set.hasHeight() ? set.height() : ConstrainLong());
- Visit(builder, set.hasAspectRatio() ? set.aspectRatio() : ConstrainDouble());
- Visit(builder, set.hasFrameRate() ? set.frameRate() : ConstrainDouble());
- Visit(builder, set.hasFacingMode() ? set.facingMode() : ConstrainDOMString());
- Visit(builder, set.hasSampleRate() ? set.sampleRate() : ConstrainLong());
- Visit(builder, set.hasSampleSize() ? set.sampleSize() : ConstrainLong());
- Visit(builder, set.hasEchoCancellation() ? set.echoCancellation()
- : ConstrainBoolean());
- Visit(builder,
- set.hasAutoGainControl() ? set.autoGainControl() : ConstrainBoolean());
- Visit(builder, set.hasLatency() ? set.latency() : ConstrainDouble());
- Visit(builder, set.hasChannelCount() ? set.channelCount() : ConstrainLong());
- Visit(builder, set.hasVideoKind() ? set.videoKind() : ConstrainDOMString());
- Visit(builder, set.hasWhiteBalanceMode() ? set.whiteBalanceMode()
- : ConstrainDOMString());
- Visit(builder,
- set.hasExposureMode() ? set.exposureMode() : ConstrainDOMString());
- Visit(builder, set.hasFocusMode() ? set.focusMode() : ConstrainDOMString());
- Visit(builder, set.hasPointsOfInterest() ? set.pointsOfInterest()
- : ConstrainPoint2D());
- Visit(builder, set.hasExposureCompensation() ? set.exposureCompensation()
- : ConstrainDouble());
- Visit(builder,
- set.hasExposureTime() ? set.exposureTime() : ConstrainDouble());
- Visit(builder,
- set.hasColorTemperature() ? set.colorTemperature() : ConstrainDouble());
- Visit(builder, set.hasIso() ? set.iso() : ConstrainDouble());
- Visit(builder, set.hasBrightness() ? set.brightness() : ConstrainDouble());
- Visit(builder, set.hasContrast() ? set.contrast() : ConstrainDouble());
- Visit(builder, set.hasSaturation() ? set.saturation() : ConstrainDouble());
- Visit(builder, set.hasSharpness() ? set.sharpness() : ConstrainDouble());
- Visit(builder,
- set.hasFocusDistance() ? set.focusDistance() : ConstrainDouble());
- Visit(builder,
- set.hasPan() ? set.pan() : BooleanOrDoubleOrConstrainDoubleRange());
- Visit(builder,
- set.hasTilt() ? set.tilt() : BooleanOrDoubleOrConstrainDoubleRange());
- Visit(builder,
- set.hasZoom() ? set.zoom() : BooleanOrDoubleOrConstrainDoubleRange());
- Visit(builder, set.hasTorch() ? set.torch() : ConstrainBoolean());
+ Visit(builder, set.getWidthOr(nullptr));
+ Visit(builder, set.getHeightOr(nullptr));
+ Visit(builder, set.getAspectRatioOr(nullptr));
+ Visit(builder, set.getFrameRateOr(nullptr));
+ Visit(builder, set.getFacingModeOr(nullptr));
+ Visit(builder, set.getSampleRateOr(nullptr));
+ Visit(builder, set.getSampleSizeOr(nullptr));
+ Visit(builder, set.getEchoCancellationOr(nullptr));
+ Visit(builder, set.getAutoGainControlOr(nullptr));
+ Visit(builder, set.getLatencyOr(nullptr));
+ Visit(builder, set.getChannelCountOr(nullptr));
+ Visit(builder, set.getVideoKindOr(nullptr));
+ Visit(builder, set.getWhiteBalanceModeOr(nullptr));
+ Visit(builder, set.getExposureModeOr(nullptr));
+ Visit(builder, set.getFocusModeOr(nullptr));
+ Visit(builder, set.getPointsOfInterestOr(nullptr));
+ Visit(builder, set.getExposureCompensationOr(nullptr));
+ Visit(builder, set.getExposureTimeOr(nullptr));
+ Visit(builder, set.getColorTemperatureOr(nullptr));
+ Visit(builder, set.getIsoOr(nullptr));
+ Visit(builder, set.getBrightnessOr(nullptr));
+ Visit(builder, set.getContrastOr(nullptr));
+ Visit(builder, set.getSaturationOr(nullptr));
+ Visit(builder, set.getSharpnessOr(nullptr));
+ Visit(builder, set.getFocusDistanceOr(nullptr));
+ Visit(builder, set.getPanOr(nullptr));
+ Visit(builder, set.getTiltOr(nullptr));
+ Visit(builder, set.getZoomOr(nullptr));
+ Visit(builder, set.getTorchOr(nullptr));
}
void Visit(IdentifiableTokenBuilder& builder,
- const BooleanOrMediaTrackConstraints& constraint) {
- if (constraint.IsBoolean()) {
- builder.AddToken(constraint.GetAsBoolean());
+ const V8UnionBooleanOrMediaTrackConstraints* constraint) {
+ if (!constraint) {
+ builder.AddToken(IdentifiableToken());
return;
}
- if (constraint.IsMediaTrackConstraints()) {
- const MediaTrackConstraints* constraints =
- constraint.GetAsMediaTrackConstraints();
- if (constraints) {
+ switch (constraint->GetContentType()) {
+ case V8UnionBooleanOrMediaTrackConstraints::ContentType::kBoolean:
+ builder.AddToken(constraint->GetAsBoolean());
+ return;
+ case V8UnionBooleanOrMediaTrackConstraints::ContentType::
+ kMediaTrackConstraints: {
+ const MediaTrackConstraints* constraints =
+ constraint->GetAsMediaTrackConstraints();
+ DCHECK(constraints);
if (constraints->hasAdvanced()) {
for (const auto& advanced : constraints->advanced()) {
Visit(builder, *advanced);
}
- return;
+ } else {
+ builder.AddToken(IdentifiableToken());
}
+ return;
}
}
- builder.AddToken(IdentifiableToken());
+ NOTREACHED();
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/idls.gni b/chromium/third_party/blink/renderer/modules/mediastream/idls.gni
deleted file mode 100644
index 440862ee1bc..00000000000
--- a/chromium/third_party/blink/renderer/modules/mediastream/idls.gni
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "capture_handle_change_event.idl",
- "input_device_info.idl",
- "media_device_info.idl",
- "media_devices.idl",
- "media_stream.idl",
- "media_stream_event.idl",
- "media_stream_track.idl",
- "media_stream_track_event.idl",
- "overconstrained_error.idl",
-]
-
-modules_dictionary_idl_files = [
- "capture_handle.idl",
- "capture_handle_change_event_init.idl",
- "capture_handle_config.idl",
- "constrain_boolean_parameters.idl",
- "constrain_dom_string_parameters.idl",
- "constrain_double_range.idl",
- "constrain_long_range.idl",
- "double_range.idl",
- "long_range.idl",
- "media_stream_constraints.idl",
- "media_stream_event_init.idl",
- "media_stream_track_event_init.idl",
- "media_track_capabilities.idl",
- "media_track_constraint_set.idl",
- "media_track_constraints.idl",
- "media_track_settings.idl",
- "media_track_supported_constraints.idl",
-]
-
-modules_dependency_idl_files = [
- "media_stream_track_content_hint.idl",
- "navigator_media_stream.idl",
- "navigator_user_media.idl",
-]
-
-modules_testing_dependency_idl_files = [ "testing/internals_media_stream.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/input_device_info.cc b/chromium/third_party/blink/renderer/modules/mediastream/input_device_info.cc
index 40c6cf6da06..c565e7474f2 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/input_device_info.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/input_device_info.cc
@@ -44,8 +44,8 @@ void InputDeviceInfo::SetVideoInputCapabilities(
max_height = std::max(max_height, format.frame_size.height());
max_frame_rate = std::max(max_frame_rate, format.frame_rate);
}
- platform_capabilities_.width = {1, max_width};
- platform_capabilities_.height = {1, max_height};
+ platform_capabilities_.width = {1, static_cast<uint32_t>(max_width)};
+ platform_capabilities_.height = {1, static_cast<uint32_t>(max_height)};
platform_capabilities_.aspect_ratio = {1.0 / max_height,
static_cast<double>(max_width)};
platform_capabilities_.frame_rate = {min_frame_rate, max_frame_rate};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/local_media_stream_audio_source.h b/chromium/third_party/blink/renderer/modules/mediastream/local_media_stream_audio_source.h
index 3db6619f01b..c30fd4b38be 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/local_media_stream_audio_source.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/local_media_stream_audio_source.h
@@ -10,6 +10,7 @@
#include <string>
#include "media/base/audio_capturer_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.cc b/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.cc
index 0ac2a0490ab..c7e8c559a2b 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.cc
@@ -6,14 +6,48 @@
#include <algorithm>
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "media/base/media_log.h"
+#include "third_party/blink/public/common/features.h"
namespace blink {
+namespace {
+
+// Default maximum post decode queue size to trigger max queue size reduction.
+constexpr int16_t kDefaultMaxPostDecodeQueueSize = 7;
+// Default count of maximum number of consecutive frames to drop during a max
+// queue size reduction. A value of 0 indicates to drop all the frames in the
+// queue when maximum queue size is reached.
+constexpr int16_t kDefaultMaxConsecutiveFramesToDrop = 0;
+// Default count of consecutive rendered frames with a new frame in the queue to
+// initiate a steady state reduction.
+constexpr int16_t kDefaultReduceSteadyThreshold = 10;
+
+} // namespace
+
+namespace features {
+
+const base::Feature kLowLatencyVideoRendererAlgorithm{
+ "LowLatencyVideoRendererAlgorithm", base::FEATURE_ENABLED_BY_DEFAULT};
+
+} // namespace features
+
LowLatencyVideoRendererAlgorithm::LowLatencyVideoRendererAlgorithm(
media::MediaLog* media_log) {
Reset();
+ max_post_decode_queue_size_ = base::GetFieldTrialParamByFeatureAsInt(
+ features::kLowLatencyVideoRendererAlgorithm, "max_post_decode_queue_size",
+ kDefaultMaxPostDecodeQueueSize);
+ max_consecutive_frames_to_drop_ = base::GetFieldTrialParamByFeatureAsInt(
+ features::kLowLatencyVideoRendererAlgorithm,
+ "max_consecutive_frames_to_drop", kDefaultMaxConsecutiveFramesToDrop);
+ reduce_steady_state_queue_size_threshold_ =
+ base::GetFieldTrialParamByFeatureAsInt(
+ features::kLowLatencyVideoRendererAlgorithm,
+ "reduce_steady_state_queue_size_threshold",
+ kDefaultReduceSteadyThreshold);
}
LowLatencyVideoRendererAlgorithm::~LowLatencyVideoRendererAlgorithm() = default;
@@ -130,10 +164,18 @@ size_t LowLatencyVideoRendererAlgorithm::DetermineModeAndNumberOfFramesToRender(
// that doesn't shortcut the drain mode. If the number of frames in the
// queue is too high, we may run out of buffers in the HW decoder resulting
// in a fallback to SW decoder.
- constexpr size_t kMaxQueueSize = 7;
- if (frame_queue_.size() > kMaxQueueSize) {
- // Clear all but the last enqueued frame and enter normal mode.
- number_of_frames_to_render = frame_queue_.size();
+ if (frame_queue_.size() > max_post_decode_queue_size_) {
+ // If max_consecutive_frames_to_drop_ = 0, clear all but the last enqueued
+ // frame and enter normal mode. Else, drop max_consecutive_frames_to_drop_
+ // frames if max_consecutive_frames_to_drop_ is less than frame queue
+ // size.
+ if (max_consecutive_frames_to_drop_ != 0) {
+ number_of_frames_to_render = std::min<uint16_t>(
+ max_consecutive_frames_to_drop_ + 1, frame_queue_.size());
+ } else {
+ // Clear all but the last enqueued frame and enter normal mode.
+ number_of_frames_to_render = frame_queue_.size();
+ }
mode_ = Mode::kNormal;
++stats_.max_size_drop_queue;
} else {
@@ -167,17 +209,17 @@ size_t LowLatencyVideoRendererAlgorithm::DetermineModeAndNumberOfFramesToRender(
bool LowLatencyVideoRendererAlgorithm::ReduceSteadyStateQueue(
size_t number_of_frames_to_render) {
- // Reduce steady state queue if we have observed 10 consecutive rendered
+ // Reduce steady state queue if we have observed
+ // `reduce_steady_state_queue_size_threshold_` count of consecutive rendered
// frames where there was a newer frame in the queue that could have been
// selected.
bool reduce_steady_state_queue = false;
- constexpr int kReduceSteadyStateQueueSizeThreshold = 10;
// Has enough time passed so that at least one frame should be rendered?
if (number_of_frames_to_render > 0) {
// Is there a newer frame in the queue that could have been rendered?
if (frame_queue_.size() >= number_of_frames_to_render + 1) {
if (++consecutive_frames_with_back_up_ >
- kReduceSteadyStateQueueSizeThreshold) {
+ reduce_steady_state_queue_size_threshold_) {
reduce_steady_state_queue = true;
consecutive_frames_with_back_up_ = 0;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.h b/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.h
index c7469041d10..6ca8513a227 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "media/base/video_frame.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -98,7 +99,7 @@ class MODULES_EXPORT LowLatencyVideoRendererAlgorithm {
// The number of consecutive render frames with a post-decode queue back-up
// (defined as greater than one frame).
- int consecutive_frames_with_back_up_;
+ uint16_t consecutive_frames_with_back_up_;
struct Stats {
int total_frames;
@@ -115,6 +116,15 @@ class MODULES_EXPORT LowLatencyVideoRendererAlgorithm {
Stats stats_;
absl::optional<base::TimeTicks> last_deadline_min_stats_recorded_;
void RecordAndResetStats();
+ // Maximum post decode queue size which should trigger a max queue size
+ // reduction.
+ uint16_t max_post_decode_queue_size_;
+ // Maximum number of frames to drop when there is a max queue size reduction.
+ // A size of 0 indicates dropping all the frames in the queue.
+ uint16_t max_consecutive_frames_to_drop_;
+ // Count of consecutive rendered frames with a newer frame in the queue which
+ // should force a steady state reduction of one frame.
+ uint16_t reduce_steady_state_queue_size_threshold_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm_unittest.cc b/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm_unittest.cc
index 8c7b206db18..4910fd0f679 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/low_latency_video_renderer_algorithm_unittest.cc
@@ -20,7 +20,7 @@ class LowLatencyVideoRendererAlgorithmTest : public testing::Test {
~LowLatencyVideoRendererAlgorithmTest() override = default;
scoped_refptr<media::VideoFrame> CreateFrame(
- size_t maximum_composition_delay_in_frames) {
+ int maximum_composition_delay_in_frames) {
const gfx::Size natural_size(8, 8);
scoped_refptr<media::VideoFrame> frame = frame_pool_.CreateFrame(
media::PIXEL_FORMAT_I420, natural_size, gfx::Rect(natural_size),
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 3e4f87d4960..5edaf3804f8 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
@@ -33,11 +33,23 @@
#include "third_party/blink/public/platform/web_string.h"
#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/v8_union_string_stringsequence.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_boolean_parameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_dom_string_parameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_double_range.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_long_range.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_constrainbooleanparameters.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_constraindoublerange_double.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindomstringparameters_string_stringsequence.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindoublerange_double.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constrainlongrange_long.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/web_feature.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -47,7 +59,6 @@
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-
namespace media_constraints_impl {
// A naked value is treated as an "ideal" value in the basic constraints,
@@ -493,153 +504,171 @@ MediaConstraints Create(ExecutionContext* context,
return CreateFromNamedConstraints(context, mandatory, optional, error_state);
}
-void CopyLongConstraint(const LongOrConstrainLongRange& blink_union_form,
+void CopyLongConstraint(const V8ConstrainLong* blink_union_form,
NakedValueDisposition naked_treatment,
LongConstraint& web_form) {
web_form.SetIsPresent(true);
- if (blink_union_form.IsLong()) {
- switch (naked_treatment) {
- case NakedValueDisposition::kTreatAsIdeal:
- web_form.SetIdeal(blink_union_form.GetAsLong());
- break;
- case NakedValueDisposition::kTreatAsExact:
- web_form.SetExact(blink_union_form.GetAsLong());
- break;
+ switch (blink_union_form->GetContentType()) {
+ case V8ConstrainLong::ContentType::kConstrainLongRange: {
+ const auto* blink_form = blink_union_form->GetAsConstrainLongRange();
+ if (blink_form->hasMin()) {
+ web_form.SetMin(blink_form->min());
+ }
+ if (blink_form->hasMax()) {
+ web_form.SetMax(blink_form->max());
+ }
+ if (blink_form->hasIdeal()) {
+ web_form.SetIdeal(blink_form->ideal());
+ }
+ if (blink_form->hasExact()) {
+ web_form.SetExact(blink_form->exact());
+ }
+ break;
}
- return;
- }
- const auto* blink_form = blink_union_form.GetAsConstrainLongRange();
- if (blink_form->hasMin()) {
- web_form.SetMin(blink_form->min());
- }
- if (blink_form->hasMax()) {
- web_form.SetMax(blink_form->max());
- }
- if (blink_form->hasIdeal()) {
- web_form.SetIdeal(blink_form->ideal());
- }
- if (blink_form->hasExact()) {
- web_form.SetExact(blink_form->exact());
+ case V8ConstrainLong::ContentType::kLong:
+ switch (naked_treatment) {
+ case NakedValueDisposition::kTreatAsIdeal:
+ web_form.SetIdeal(blink_union_form->GetAsLong());
+ break;
+ case NakedValueDisposition::kTreatAsExact:
+ web_form.SetExact(blink_union_form->GetAsLong());
+ break;
+ }
+ break;
}
}
-void CopyDoubleConstraint(const DoubleOrConstrainDoubleRange& blink_union_form,
+void CopyDoubleConstraint(const V8ConstrainDouble* blink_union_form,
NakedValueDisposition naked_treatment,
DoubleConstraint& web_form) {
web_form.SetIsPresent(true);
- if (blink_union_form.IsDouble()) {
- switch (naked_treatment) {
- case NakedValueDisposition::kTreatAsIdeal:
- web_form.SetIdeal(blink_union_form.GetAsDouble());
- break;
- case NakedValueDisposition::kTreatAsExact:
- web_form.SetExact(blink_union_form.GetAsDouble());
- break;
+ switch (blink_union_form->GetContentType()) {
+ case V8ConstrainDouble::ContentType::kConstrainDoubleRange: {
+ const auto* blink_form = blink_union_form->GetAsConstrainDoubleRange();
+ if (blink_form->hasMin()) {
+ web_form.SetMin(blink_form->min());
+ }
+ if (blink_form->hasMax()) {
+ web_form.SetMax(blink_form->max());
+ }
+ if (blink_form->hasIdeal()) {
+ web_form.SetIdeal(blink_form->ideal());
+ }
+ if (blink_form->hasExact()) {
+ web_form.SetExact(blink_form->exact());
+ }
+ break;
}
- return;
- }
- auto* blink_form = blink_union_form.GetAsConstrainDoubleRange();
- if (blink_form->hasMin()) {
- web_form.SetMin(blink_form->min());
- }
- if (blink_form->hasMax()) {
- web_form.SetMax(blink_form->max());
- }
- if (blink_form->hasIdeal()) {
- web_form.SetIdeal(blink_form->ideal());
- }
- if (blink_form->hasExact()) {
- web_form.SetExact(blink_form->exact());
+ case V8ConstrainDouble::ContentType::kDouble:
+ switch (naked_treatment) {
+ case NakedValueDisposition::kTreatAsIdeal:
+ web_form.SetIdeal(blink_union_form->GetAsDouble());
+ break;
+ case NakedValueDisposition::kTreatAsExact:
+ web_form.SetExact(blink_union_form->GetAsDouble());
+ break;
+ }
+ break;
}
}
void CopyBooleanOrDoubleConstraint(
- const BooleanOrDoubleOrConstrainDoubleRange& blink_union_form,
+ const V8UnionBooleanOrConstrainDouble* blink_union_form,
NakedValueDisposition naked_treatment,
DoubleConstraint& web_form) {
- if (blink_union_form.IsBoolean()) {
- web_form.SetIsPresent(blink_union_form.GetAsBoolean());
- return;
- }
- DoubleOrConstrainDoubleRange double_constraint;
- if (blink_union_form.IsDouble()) {
- double_constraint.SetDouble(blink_union_form.GetAsDouble());
- } else {
- DCHECK(blink_union_form.IsConstrainDoubleRange());
- double_constraint.SetConstrainDoubleRange(
- blink_union_form.GetAsConstrainDoubleRange());
- }
- CopyDoubleConstraint(double_constraint, naked_treatment, web_form);
+ switch (blink_union_form->GetContentType()) {
+ case V8UnionBooleanOrConstrainDouble::ContentType::kBoolean:
+ web_form.SetIsPresent(blink_union_form->GetAsBoolean());
+ break;
+ case V8UnionBooleanOrConstrainDouble::ContentType::kConstrainDoubleRange:
+ case V8UnionBooleanOrConstrainDouble::ContentType::kDouble:
+ CopyDoubleConstraint(blink_union_form->GetAsV8ConstrainDouble(),
+ naked_treatment, web_form);
+ break;
+ }
}
-void CopyStringConstraint(
- const StringOrStringSequenceOrConstrainDOMStringParameters&
- blink_union_form,
- NakedValueDisposition naked_treatment,
- StringConstraint& web_form) {
+void CopyStringConstraint(const V8ConstrainDOMString* blink_union_form,
+ NakedValueDisposition naked_treatment,
+ StringConstraint& web_form) {
web_form.SetIsPresent(true);
- if (blink_union_form.IsString()) {
- switch (naked_treatment) {
- case NakedValueDisposition::kTreatAsIdeal:
- web_form.SetIdeal(Vector<String>(1, blink_union_form.GetAsString()));
- break;
- case NakedValueDisposition::kTreatAsExact:
- web_form.SetExact(Vector<String>(1, blink_union_form.GetAsString()));
-
- break;
- }
- return;
- }
- if (blink_union_form.IsStringSequence()) {
- switch (naked_treatment) {
- case NakedValueDisposition::kTreatAsIdeal:
- web_form.SetIdeal(blink_union_form.GetAsStringSequence());
- break;
- case NakedValueDisposition::kTreatAsExact:
- web_form.SetExact(blink_union_form.GetAsStringSequence());
- break;
- }
- return;
- }
- auto* blink_form = blink_union_form.GetAsConstrainDOMStringParameters();
- if (blink_form->hasIdeal()) {
- if (blink_form->ideal().IsStringSequence()) {
- web_form.SetIdeal(blink_form->ideal().GetAsStringSequence());
- } else if (blink_form->ideal().IsString()) {
- web_form.SetIdeal(Vector<String>(1, blink_form->ideal().GetAsString()));
- }
- }
- if (blink_form->hasExact()) {
- if (blink_form->exact().IsStringSequence()) {
- web_form.SetExact(blink_form->exact().GetAsStringSequence());
- } else if (blink_form->exact().IsString()) {
- web_form.SetExact(Vector<String>(1, blink_form->exact().GetAsString()));
+ switch (blink_union_form->GetContentType()) {
+ case V8ConstrainDOMString::ContentType::kConstrainDOMStringParameters: {
+ const auto* blink_form =
+ blink_union_form->GetAsConstrainDOMStringParameters();
+ if (blink_form->hasIdeal()) {
+ switch (blink_form->ideal()->GetContentType()) {
+ case V8UnionStringOrStringSequence::ContentType::kString:
+ web_form.SetIdeal(
+ Vector<String>(1, blink_form->ideal()->GetAsString()));
+ break;
+ case V8UnionStringOrStringSequence::ContentType::kStringSequence:
+ web_form.SetIdeal(blink_form->ideal()->GetAsStringSequence());
+ break;
+ }
+ }
+ if (blink_form->hasExact()) {
+ switch (blink_form->exact()->GetContentType()) {
+ case V8UnionStringOrStringSequence::ContentType::kString:
+ web_form.SetExact(
+ Vector<String>(1, blink_form->exact()->GetAsString()));
+ break;
+ case V8UnionStringOrStringSequence::ContentType::kStringSequence:
+ web_form.SetExact(blink_form->exact()->GetAsStringSequence());
+ break;
+ }
+ }
+ break;
}
+ case V8ConstrainDOMString::ContentType::kString:
+ switch (naked_treatment) {
+ case NakedValueDisposition::kTreatAsIdeal:
+ web_form.SetIdeal(Vector<String>(1, blink_union_form->GetAsString()));
+ break;
+ case NakedValueDisposition::kTreatAsExact:
+ web_form.SetExact(Vector<String>(1, blink_union_form->GetAsString()));
+ break;
+ }
+ break;
+ case V8ConstrainDOMString::ContentType::kStringSequence:
+ switch (naked_treatment) {
+ case NakedValueDisposition::kTreatAsIdeal:
+ web_form.SetIdeal(blink_union_form->GetAsStringSequence());
+ break;
+ case NakedValueDisposition::kTreatAsExact:
+ web_form.SetExact(blink_union_form->GetAsStringSequence());
+ break;
+ }
+ break;
}
}
-void CopyBooleanConstraint(
- const BooleanOrConstrainBooleanParameters& blink_union_form,
- NakedValueDisposition naked_treatment,
- BooleanConstraint& web_form) {
+void CopyBooleanConstraint(const V8ConstrainBoolean* blink_union_form,
+ NakedValueDisposition naked_treatment,
+ BooleanConstraint& web_form) {
web_form.SetIsPresent(true);
- if (blink_union_form.IsBoolean()) {
- switch (naked_treatment) {
- case NakedValueDisposition::kTreatAsIdeal:
- web_form.SetIdeal(blink_union_form.GetAsBoolean());
- break;
- case NakedValueDisposition::kTreatAsExact:
- web_form.SetExact(blink_union_form.GetAsBoolean());
- break;
+ switch (blink_union_form->GetContentType()) {
+ case V8ConstrainBoolean::ContentType::kBoolean:
+ switch (naked_treatment) {
+ case NakedValueDisposition::kTreatAsIdeal:
+ web_form.SetIdeal(blink_union_form->GetAsBoolean());
+ break;
+ case NakedValueDisposition::kTreatAsExact:
+ web_form.SetExact(blink_union_form->GetAsBoolean());
+ break;
+ }
+ break;
+ case V8ConstrainBoolean::ContentType::kConstrainBooleanParameters: {
+ const auto* blink_form =
+ blink_union_form->GetAsConstrainBooleanParameters();
+ if (blink_form->hasIdeal()) {
+ web_form.SetIdeal(blink_form->ideal());
+ }
+ if (blink_form->hasExact()) {
+ web_form.SetExact(blink_form->exact());
+ }
+ break;
}
- return;
- }
- auto* blink_form = blink_union_form.GetAsConstrainBooleanParameters();
- if (blink_form->hasIdeal()) {
- web_form.SetIdeal(blink_form->ideal());
- }
- if (blink_form->hasExact()) {
- web_form.SetExact(blink_form->exact());
}
}
@@ -820,11 +849,11 @@ U GetNakedValue(T input, NakedValueDisposition which) {
return input.Exact();
}
-LongOrConstrainLongRange ConvertLong(const LongConstraint& input,
- NakedValueDisposition naked_treatment) {
- LongOrConstrainLongRange output_union;
+V8ConstrainLong* ConvertLong(const LongConstraint& input,
+ NakedValueDisposition naked_treatment) {
if (UseNakedNumeric(input, naked_treatment)) {
- output_union.SetLong(GetNakedValue<uint32_t>(input, naked_treatment));
+ return MakeGarbageCollected<V8ConstrainLong>(
+ GetNakedValue<uint32_t>(input, naked_treatment));
} else if (!input.IsUnconstrained()) {
ConstrainLongRange* output = ConstrainLongRange::Create();
if (input.HasExact())
@@ -835,17 +864,16 @@ LongOrConstrainLongRange ConvertLong(const LongConstraint& input,
output->setMax(input.Max());
if (input.HasIdeal())
output->setIdeal(input.Ideal());
- output_union.SetConstrainLongRange(output);
+ return MakeGarbageCollected<V8ConstrainLong>(output);
}
- return output_union;
+ return nullptr;
}
-DoubleOrConstrainDoubleRange ConvertDouble(
- const DoubleConstraint& input,
- NakedValueDisposition naked_treatment) {
- DoubleOrConstrainDoubleRange output_union;
+V8ConstrainDouble* ConvertDouble(const DoubleConstraint& input,
+ NakedValueDisposition naked_treatment) {
if (UseNakedNumeric(input, naked_treatment)) {
- output_union.SetDouble(GetNakedValue<double>(input, naked_treatment));
+ return MakeGarbageCollected<V8ConstrainDouble>(
+ GetNakedValue<double>(input, naked_treatment));
} else if (!input.IsUnconstrained()) {
ConstrainDoubleRange* output = ConstrainDoubleRange::Create();
if (input.HasExact())
@@ -856,17 +884,17 @@ DoubleOrConstrainDoubleRange ConvertDouble(
output->setMin(input.Min());
if (input.HasMax())
output->setMax(input.Max());
- output_union.SetConstrainDoubleRange(output);
+ return MakeGarbageCollected<V8ConstrainDouble>(output);
}
- return output_union;
+ return nullptr;
}
-BooleanOrDoubleOrConstrainDoubleRange ConvertBooleanOrDouble(
+V8UnionBooleanOrConstrainDouble* ConvertBooleanOrDouble(
const DoubleConstraint& input,
NakedValueDisposition naked_treatment) {
- BooleanOrDoubleOrConstrainDoubleRange output_union;
if (UseNakedNumeric(input, naked_treatment)) {
- output_union.SetDouble(GetNakedValue<double>(input, naked_treatment));
+ return MakeGarbageCollected<V8UnionBooleanOrConstrainDouble>(
+ GetNakedValue<double>(input, naked_treatment));
} else if (!input.IsUnconstrained()) {
ConstrainDoubleRange* output = ConstrainDoubleRange::Create();
if (input.HasExact())
@@ -877,29 +905,27 @@ BooleanOrDoubleOrConstrainDoubleRange ConvertBooleanOrDouble(
output->setMin(input.Min());
if (input.HasMax())
output->setMax(input.Max());
- output_union.SetConstrainDoubleRange(output);
+ return MakeGarbageCollected<V8UnionBooleanOrConstrainDouble>(output);
}
- return output_union;
+ return nullptr;
}
-StringOrStringSequence ConvertStringSequence(
+V8UnionStringOrStringSequence* ConvertStringSequence(
const WebVector<WebString>& input) {
- StringOrStringSequence the_strings;
if (input.size() > 1) {
Vector<String> buffer;
for (const auto& scanner : input)
buffer.push_back(scanner);
- the_strings.SetStringSequence(buffer);
+ return MakeGarbageCollected<V8UnionStringOrStringSequence>(
+ std::move(buffer));
} else if (!input.empty()) {
- the_strings.SetString(input[0]);
+ return MakeGarbageCollected<V8UnionStringOrStringSequence>(input[0]);
}
- return the_strings;
+ return nullptr;
}
-StringOrStringSequenceOrConstrainDOMStringParameters ConvertString(
- const StringConstraint& input,
- NakedValueDisposition naked_treatment) {
- StringOrStringSequenceOrConstrainDOMStringParameters output_union;
+V8ConstrainDOMString* ConvertString(const StringConstraint& input,
+ NakedValueDisposition naked_treatment) {
if (UseNakedNonNumeric(input, naked_treatment)) {
WebVector<WebString> input_buffer(
GetNakedValue<WebVector<WebString>>(input, naked_treatment));
@@ -907,10 +933,11 @@ StringOrStringSequenceOrConstrainDOMStringParameters ConvertString(
Vector<String> buffer;
for (const auto& scanner : input_buffer)
buffer.push_back(scanner);
- output_union.SetStringSequence(buffer);
+ return MakeGarbageCollected<V8ConstrainDOMString>(std::move(buffer));
} else if (!input_buffer.empty()) {
- output_union.SetString(input_buffer[0]);
+ return MakeGarbageCollected<V8ConstrainDOMString>(input_buffer[0]);
}
+ return nullptr;
} else if (!input.IsUnconstrained()) {
ConstrainDOMStringParameters* output =
ConstrainDOMStringParameters::Create();
@@ -918,26 +945,25 @@ StringOrStringSequenceOrConstrainDOMStringParameters ConvertString(
output->setExact(ConvertStringSequence(input.Exact()));
if (input.HasIdeal())
output->setIdeal(ConvertStringSequence(input.Ideal()));
- output_union.SetConstrainDOMStringParameters(output);
+ return MakeGarbageCollected<V8ConstrainDOMString>(output);
}
- return output_union;
+ return nullptr;
}
-BooleanOrConstrainBooleanParameters ConvertBoolean(
- const BooleanConstraint& input,
- NakedValueDisposition naked_treatment) {
- BooleanOrConstrainBooleanParameters output_union;
+V8ConstrainBoolean* ConvertBoolean(const BooleanConstraint& input,
+ NakedValueDisposition naked_treatment) {
if (UseNakedNonNumeric(input, naked_treatment)) {
- output_union.SetBoolean(GetNakedValue<bool>(input, naked_treatment));
+ return MakeGarbageCollected<V8ConstrainBoolean>(
+ GetNakedValue<bool>(input, naked_treatment));
} else if (!input.IsUnconstrained()) {
ConstrainBooleanParameters* output = ConstrainBooleanParameters::Create();
if (input.HasExact())
output->setExact(input.Exact());
if (input.HasIdeal())
output->setIdeal(input.Ideal());
- output_union.SetConstrainBooleanParameters(output);
+ return MakeGarbageCollected<V8ConstrainBoolean>(output);
}
- return output_union;
+ return nullptr;
}
void ConvertConstraintSet(const MediaTrackConstraintSetPlatform& input,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.h b/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.h
index 82ac3531ca1..15c04386db4 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.h
@@ -31,15 +31,14 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_CONSTRAINTS_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_CONSTRAINTS_IMPL_H_
-#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
class Dictionary;
class ExecutionContext;
+class MediaErrorState;
class MediaTrackConstraints;
namespace media_constraints_impl {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_test.cc
index 263a9530487..bccd1662c7d 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_test.cc
@@ -3,8 +3,13 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
+
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_dom_string_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindomstringparameters_string_stringsequence.h"
#include "third_party/blink/renderer/modules/mediastream/media_constraints_impl.h"
namespace blink {
@@ -162,8 +167,8 @@ TEST(MediaTrackConstraintsTest, ConvertWebSingleStringConstraint) {
MediaTrackConstraints* output =
media_constraints_impl::ConvertConstraints(input);
ASSERT_TRUE(output->hasFacingMode());
- ASSERT_TRUE(output->facingMode().IsString());
- EXPECT_EQ("foo", output->facingMode().GetAsString());
+ ASSERT_TRUE(output->facingMode()->IsString());
+ EXPECT_EQ("foo", output->facingMode()->GetAsString());
}
TEST(MediaTrackConstraintsTest, ConvertWebDoubleStringConstraint) {
@@ -181,8 +186,8 @@ TEST(MediaTrackConstraintsTest, ConvertWebDoubleStringConstraint) {
MediaTrackConstraints* output =
media_constraints_impl::ConvertConstraints(input);
ASSERT_TRUE(output->hasFacingMode());
- ASSERT_TRUE(output->facingMode().IsStringSequence());
- auto out_buffer = output->facingMode().GetAsStringSequence();
+ ASSERT_TRUE(output->facingMode()->IsStringSequence());
+ const auto& out_buffer = output->facingMode()->GetAsStringSequence();
EXPECT_EQ("foo", out_buffer[0]);
EXPECT_EQ("bar", out_buffer[1]);
}
@@ -190,8 +195,7 @@ TEST(MediaTrackConstraintsTest, ConvertWebDoubleStringConstraint) {
TEST(MediaTrackConstraintsTest, ConvertBlinkStringConstraint) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
MediaConstraints output;
- StringOrStringSequenceOrConstrainDOMStringParameters parameter;
- parameter.SetString("foo");
+ auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>("foo");
input->setFacingMode(parameter);
output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(input);
@@ -203,13 +207,11 @@ TEST(MediaTrackConstraintsTest, ConvertBlinkStringConstraint) {
TEST(MediaTrackConstraintsTest, ConvertBlinkComplexStringConstraint) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
MediaConstraints output;
- StringOrStringSequenceOrConstrainDOMStringParameters parameter;
ConstrainDOMStringParameters* subparameter =
ConstrainDOMStringParameters::Create();
- StringOrStringSequence inner_string;
- inner_string.SetString("foo");
- subparameter->setIdeal(inner_string);
- parameter.SetConstrainDOMStringParameters(subparameter);
+ subparameter->setIdeal(
+ MakeGarbageCollected<V8UnionStringOrStringSequence>("foo"));
+ auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(subparameter);
input->setFacingMode(parameter);
output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(input);
@@ -221,14 +223,13 @@ TEST(MediaTrackConstraintsTest, ConvertBlinkComplexStringConstraint) {
MediaTrackConstraints* recycled =
media_constraints_impl::ConvertConstraints(output);
ASSERT_TRUE(recycled->hasFacingMode());
- ASSERT_TRUE(recycled->facingMode().IsString());
- ASSERT_EQ("foo", recycled->facingMode().GetAsString());
+ ASSERT_TRUE(recycled->facingMode()->IsString());
+ ASSERT_EQ("foo", recycled->facingMode()->GetAsString());
}
TEST(MediaTrackConstraintsTest, NakedIsExactInAdvanced) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
- StringOrStringSequenceOrConstrainDOMStringParameters parameter;
- parameter.SetString("foo");
+ auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>("foo");
input->setFacingMode(parameter);
HeapVector<Member<MediaTrackConstraintSet>> advanced(
1, MediaTrackConstraintSet::Create());
@@ -277,19 +278,19 @@ TEST(MediaTrackConstraintsTest, IdealAndExactConvertToNaked) {
MediaTrackConstraintSet* element2 = output->advanced()[1];
ASSERT_TRUE(output->hasFacingMode());
- ASSERT_TRUE(output->facingMode().IsString());
- EXPECT_EQ("ideal", output->facingMode().GetAsString());
+ ASSERT_TRUE(output->facingMode()->IsString());
+ EXPECT_EQ("ideal", output->facingMode()->GetAsString());
ASSERT_TRUE(element1->hasFacingMode());
- ASSERT_TRUE(element1->facingMode().IsConstrainDOMStringParameters());
+ ASSERT_TRUE(element1->facingMode()->IsConstrainDOMStringParameters());
EXPECT_EQ("ideal", element1->facingMode()
- .GetAsConstrainDOMStringParameters()
+ ->GetAsConstrainDOMStringParameters()
->ideal()
- .GetAsString());
+ ->GetAsString());
ASSERT_TRUE(element2->hasFacingMode());
- ASSERT_TRUE(element2->facingMode().IsString());
- EXPECT_EQ("exact", element2->facingMode().GetAsString());
+ ASSERT_TRUE(element2->facingMode()->IsString());
+ EXPECT_EQ("exact", element2->facingMode()->GetAsString());
}
} // namespace blink
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 9d389a970e4..4b4377251af 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -6,14 +6,19 @@
#include <utility>
+#include "base/metrics/histogram_functions.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
+#include "third_party/blink/public/mojom/media/capture_handle_config.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/public/platform/web_runtime_features.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/modules/v8/v8_capture_handle_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_supported_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_domexception_overconstrainederror.h"
@@ -23,7 +28,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
-#include "third_party/blink/renderer/modules/mediastream/capture_handle_config.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/modules/mediastream/identifiability_metrics.h"
#include "third_party/blink/renderer/modules/mediastream/input_device_info.h"
#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
@@ -56,17 +61,10 @@ class PromiseResolverCallbacks final : public UserMediaRequest::Callbacks {
MediaStream* stream) override {
resolver_->Resolve(stream);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void OnError(ScriptWrappable* callback_this_value,
const V8MediaStreamError* error) override {
resolver_->Reject(error);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void OnError(ScriptWrappable* callback_this_value,
- DOMExceptionOrOverconstrainedError error) override {
- resolver_->Reject(error);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor* visitor) const override {
visitor->Trace(resolver_);
@@ -77,6 +75,14 @@ class PromiseResolverCallbacks final : public UserMediaRequest::Callbacks {
Member<ScriptPromiseResolver> resolver_;
};
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class DisplayCapturePolicyResult {
+ kDisallowed = 0,
+ kAllowed = 1,
+ kMaxValue = kAllowed
+};
+
} // namespace
const char MediaDevices::kSupplementName[] = "MediaDevices";
@@ -190,39 +196,39 @@ ScriptPromise MediaDevices::getDisplayMedia(
ScriptState* script_state,
const MediaStreamConstraints* options,
ExceptionState& exception_state) {
- return SendUserMediaRequest(script_state,
- UserMediaRequest::MediaType::kDisplayMedia,
- options, exception_state);
-}
-
-ScriptPromise MediaDevices::getCurrentBrowsingContextMedia(
- ScriptState* script_state,
- const MediaStreamConstraints* options,
- ExceptionState& exception_state) {
const ExecutionContext* const context = GetExecutionContext();
if (!context) {
exception_state.ThrowDOMException(
DOMExceptionCode::kNotSupportedError,
- "The implementation did not support the requested type of object or "
- "operation.");
+ "No media device controller available; is this a detached window?");
return ScriptPromise();
}
- // This call should not be possible otherwise, as per the RuntimeEnabled
- // in the IDL.
- CHECK(RuntimeEnabledFeatures::GetCurrentBrowsingContextMediaEnabled(context));
-
- if (!context->IsFeatureEnabled(
- mojom::blink::PermissionsPolicyFeature::kDisplayCapture,
- ReportOptions::kReportOnFailure)) {
- exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
- return ScriptPromise();
+ // The kDisplayCapturePermissionsPolicyEnabled preference controls whether
+ // the display-capture permissions-policy is applied or skipped.
+ // The kDisplayCapturePermissionsPolicyEnabled preference is translated
+ // into DisplayCapturePermissionsPolicyEnabled RuntimeEnabledFeature.
+ if (RuntimeEnabledFeatures::DisplayCapturePermissionsPolicyEnabled()) {
+ const bool capture_allowed_by_permissions_policy =
+ context->IsFeatureEnabled(
+ mojom::blink::PermissionsPolicyFeature::kDisplayCapture,
+ ReportOptions::kReportOnFailure);
+
+ base::UmaHistogramEnumeration(
+ "Media.Ui.GetDisplayMedia.DisplayCapturePolicyResult",
+ capture_allowed_by_permissions_policy
+ ? DisplayCapturePolicyResult::kAllowed
+ : DisplayCapturePolicyResult::kDisallowed);
+
+ if (!capture_allowed_by_permissions_policy) {
+ exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
+ return ScriptPromise();
+ }
}
- return SendUserMediaRequest(
- script_state,
- UserMediaRequest::MediaType::kGetCurrentBrowsingContextMedia, options,
- exception_state);
+ return SendUserMediaRequest(script_state,
+ UserMediaRequest::MediaType::kDisplayMedia,
+ options, exception_state);
}
void MediaDevices::setCaptureHandleConfig(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.h b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.h
index e6528002ba4..497b7ed02a8 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.h
@@ -60,10 +60,6 @@ class MODULES_EXPORT MediaDevices final
const MediaStreamConstraints*,
ExceptionState&);
- ScriptPromise getCurrentBrowsingContextMedia(ScriptState*,
- const MediaStreamConstraints*,
- ExceptionState&);
-
void setCaptureHandleConfig(ScriptState*,
const CaptureHandleConfig*,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.idl b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.idl
index 5442fcd7da5..f60017754d9 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.idl
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.idl
@@ -29,18 +29,6 @@
] Promise<MediaStream>
getDisplayMedia(optional MediaStreamConstraints constraints = {});
- // TODO(crbug.com/1136942): Link to the spec after the PR goes through.
- // Note: The runtime flag GetCurrentBrowsingContextMedia presupposes
- // the runtime flag GetDisplayMedia.
- // If (GetCurrentBrowsingContextMedia && !GetDisplayMedia), that's an error,
- // and permission will be denied.
- [
- RuntimeEnabled = GetCurrentBrowsingContextMedia, CallWith = ScriptState,
- RaisesException,
- MeasureAs = GetCurrentBrowsingContextMedia
- ] Promise<MediaStream>
- getCurrentBrowsingContextMedia(optional MediaStreamConstraints constraints = {});
-
// Allows an application APP to opt-in to exposing certain information to
// applications which end up capturing APP.
// TODO(crbug.com/1208868): Link to the spec once it's published.
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 ec05e7c1f23..47a6e41c54c 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
@@ -15,10 +15,10 @@
#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/bindings/modules/v8/v8_capture_handle_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_constraints.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
-#include "third_party/blink/renderer/modules/mediastream/capture_handle_config.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/weborigin/security_origin.h"
@@ -49,12 +49,12 @@ String MaxLengthCaptureHandle() {
return maxHandle;
}
-class MockMediaDevicesDispatcherHost
+class MockMediaDevicesDispatcherHost final
: public mojom::blink::MediaDevicesDispatcherHost {
public:
MockMediaDevicesDispatcherHost() {}
- ~MockMediaDevicesDispatcherHost() final {
+ ~MockMediaDevicesDispatcherHost() override {
EXPECT_FALSE(expected_capture_handle_config_);
}
@@ -193,7 +193,7 @@ class MockMediaDevicesDispatcherHost
expected_config->all_origins_permitted);
ASSERT_EQ(config->permitted_origins.size(),
expected_config->permitted_origins.size());
- for (size_t i = 0; i < config->permitted_origins.size(); ++i) {
+ for (wtf_size_t i = 0; i < config->permitted_origins.size(); ++i) {
EXPECT_TRUE(config->permitted_origins[i]->IsSameOriginWith(
expected_config->permitted_origins[i].get()));
}
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 da1ddaeb7ee..86c84cfdebc 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
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_domexception_overconstrainederror.h"
#include "third_party/blink/renderer/modules/mediastream/overconstrained_error.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
@@ -117,18 +118,10 @@ String MediaErrorState::GetErrorMessage() {
return String();
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionDOMExceptionOrOverconstrainedError* MediaErrorState::CreateError() {
DCHECK_EQ(error_type_, kConstraintError);
return MakeGarbageCollected<V8UnionDOMExceptionOrOverconstrainedError>(
MakeGarbageCollected<OverconstrainedError>(constraint_, message_));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-DOMExceptionOrOverconstrainedError MediaErrorState::CreateError() {
- DCHECK(error_type_ == kConstraintError);
- return DOMExceptionOrOverconstrainedError::FromOverconstrainedError(
- MakeGarbageCollected<OverconstrainedError>(constraint_, message_));
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
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 ec918f5dd63..6243577431a 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,12 +31,13 @@
#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/modules/v8/dom_exception_or_overconstrained_error.h"
-#include "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/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
+class ExceptionState;
class OverconstrainedError;
class V8UnionDOMExceptionOrOverconstrainedError;
@@ -57,11 +58,7 @@ class MediaErrorState {
bool CanGenerateException();
void RaiseException(ExceptionState&);
String GetErrorMessage();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionDOMExceptionOrOverconstrainedError* CreateError();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DOMExceptionOrOverconstrainedError CreateError();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
enum ErrorType { kNoError, kTypeError, kDOMException, kConstraintError };
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
index 5fc8ef0fae3..1f1f0537bbc 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
@@ -28,7 +28,6 @@
#include "media/base/channel_layout.h"
#include "media/base/limits.h"
#include "media/webrtc/helpers.h"
-#include "media/webrtc/webrtc_switches.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
@@ -38,12 +37,8 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/webrtc/api/audio/echo_canceller3_config.h"
-#include "third_party/webrtc/api/audio/echo_canceller3_config_json.h"
-#include "third_party/webrtc/api/audio/echo_canceller3_factory.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing_statistics.h"
-#include "third_party/webrtc/modules/audio_processing/typing_detection.h"
#include "third_party/webrtc_overrides/task_queue_factory.h"
namespace WTF {
@@ -63,72 +58,6 @@ using EchoCancellationType = AudioProcessingProperties::EchoCancellationType;
namespace {
-using webrtc::AudioProcessing;
-
-bool Allow48kHzApmProcessing() {
- return base::FeatureList::IsEnabled(
- ::features::kWebRtcAllow48kHzProcessingOnArm);
-}
-
-absl::optional<WebRtcHybridAgcParams> GetWebRtcHybridAgcParams() {
- if (!base::FeatureList::IsEnabled(::features::kWebRtcHybridAgc)) {
- return absl::nullopt;
- }
- return WebRtcHybridAgcParams{
- .dry_run = base::GetFieldTrialParamByFeatureAsBool(
- ::features::kWebRtcHybridAgc, "dry_run", false),
- .vad_reset_period_ms = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcHybridAgc, "vad_reset_period_ms", 1500),
- .adjacent_speech_frames_threshold =
- base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcHybridAgc, "adjacent_speech_frames_threshold",
- 12),
- .max_gain_change_db_per_second = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcHybridAgc, "max_gain_change_db_per_second", 3),
- .max_output_noise_level_dbfs = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcHybridAgc, "max_output_noise_level_dbfs", -50),
- .sse2_allowed = base::GetFieldTrialParamByFeatureAsBool(
- ::features::kWebRtcHybridAgc, "sse2_allowed", true),
- .avx2_allowed = base::GetFieldTrialParamByFeatureAsBool(
- ::features::kWebRtcHybridAgc, "avx2_allowed", true),
- .neon_allowed = base::GetFieldTrialParamByFeatureAsBool(
- ::features::kWebRtcHybridAgc, "neon_allowed", true)};
-}
-
-absl::optional<WebRtcAnalogAgcClippingControlParams>
-GetWebRtcAnalogAgcClippingControlParams() {
- if (!base::FeatureList::IsEnabled(
- ::features::kWebRtcAnalogAgcClippingControl)) {
- return absl::nullopt;
- }
- return WebRtcAnalogAgcClippingControlParams{
- .mode = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcAnalogAgcClippingControl, "mode", 0),
- .window_length = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcAnalogAgcClippingControl, "window_length", 5),
- .reference_window_length = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcAnalogAgcClippingControl,
- "reference_window_length", 5),
- .reference_window_delay = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcAnalogAgcClippingControl, "reference_window_delay",
- 5),
- .clipping_threshold = base::GetFieldTrialParamByFeatureAsDouble(
- ::features::kWebRtcAnalogAgcClippingControl, "clipping_threshold",
- -1.0),
- .crest_factor_margin = base::GetFieldTrialParamByFeatureAsDouble(
- ::features::kWebRtcAnalogAgcClippingControl, "crest_factor_margin",
- 3.0),
- .clipped_level_step = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcAnalogAgcClippingControl, "clipped_level_step",
- 15),
- .clipped_ratio_threshold = base::GetFieldTrialParamByFeatureAsDouble(
- ::features::kWebRtcAnalogAgcClippingControl,
- "clipped_ratio_threshold", 0.1),
- .clipped_wait_frames = base::GetFieldTrialParamByFeatureAsInt(
- ::features::kWebRtcAnalogAgcClippingControl, "clipped_wait_frames",
- 300)};
-}
-
constexpr int kBuffersPerSecond = 100; // 10 ms per buffer.
} // namespace
@@ -297,12 +226,11 @@ MediaStreamAudioProcessor::MediaStreamAudioProcessor(
const AudioProcessingProperties& properties,
bool use_capture_multi_channel_processing,
scoped_refptr<WebRtcAudioDeviceImpl> playout_data_source)
- : render_delay_ms_(0),
+ : render_delay_(base::TimeDelta()),
audio_delay_stats_reporter_(kBuffersPerSecond),
playout_data_source_(std::move(playout_data_source)),
main_thread_runner_(base::ThreadTaskRunnerHandle::Get()),
audio_mirroring_(false),
- typing_detected_(false),
aec_dump_agent_impl_(AecDumpAgentImpl::Create(this)),
stopped_(false),
use_capture_multi_channel_processing_(
@@ -480,8 +408,7 @@ bool MediaStreamAudioProcessor::WouldModifyAudio(
#endif
#if !defined(OS_IOS) && !defined(OS_ANDROID)
- if (properties.goog_experimental_echo_cancellation ||
- properties.goog_typing_noise_detection) {
+ if (properties.goog_experimental_echo_cancellation) {
return true;
}
#endif
@@ -497,7 +424,7 @@ bool MediaStreamAudioProcessor::WouldModifyAudio(
void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds) {
+ base::TimeDelta audio_delay) {
DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
DCHECK_GE(audio_bus->channels(), 1);
DCHECK_LE(audio_bus->channels(), media::limits::kMaxChannels);
@@ -512,10 +439,8 @@ void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
}
TRACE_EVENT1("audio", "MediaStreamAudioProcessor::OnPlayoutData",
- "delay (ms)", audio_delay_milliseconds);
- DCHECK_LT(audio_delay_milliseconds,
- std::numeric_limits<base::subtle::Atomic32>::max());
- base::subtle::Release_Store(&render_delay_ms_, audio_delay_milliseconds);
+ "delay (ms)", audio_delay.InMillisecondsF());
+ render_delay_ = audio_delay;
webrtc::StreamConfig input_stream_config(sample_rate, audio_bus->channels());
// If the input audio appears to contain upmixed mono audio, then APM is only
@@ -531,8 +456,7 @@ void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
for (int i = 0; i < static_cast<int>(input_stream_config.num_channels()); ++i)
input_ptrs[i] = audio_bus->channel(i);
- // TODO(ajm): Should AnalyzeReverseStream() account for the
- // |audio_delay_milliseconds|?
+ // TODO(ajm): Should AnalyzeReverseStream() account for the |audio_delay|?
const int apm_error = audio_processing_->AnalyzeReverseStream(
input_ptrs.data(), input_stream_config);
if (apm_error != webrtc::AudioProcessing::kNoError &&
@@ -558,7 +482,6 @@ void MediaStreamAudioProcessor::OnRenderThreadChanged() {
webrtc::AudioProcessorInterface::AudioProcessorStatistics
MediaStreamAudioProcessor::GetStats(bool has_remote_tracks) {
AudioProcessorStatistics stats;
- stats.typing_noise_detected = base::subtle::Acquire_Load(&typing_detected_);
stats.apm_statistics = audio_processing_->GetStatistics(has_remote_tracks);
return stats;
}
@@ -576,19 +499,16 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
#if defined(OS_ANDROID)
const bool goog_experimental_aec = false;
- const bool goog_typing_detection = false;
#else
const bool goog_experimental_aec =
properties.goog_experimental_echo_cancellation;
- const bool goog_typing_detection = properties.goog_typing_noise_detection;
#endif
// Return immediately if none of the goog constraints requiring
// webrtc::AudioProcessing are enabled.
if (!properties.EchoCancellationIsWebRtcProvided() &&
!goog_experimental_aec && !properties.goog_noise_suppression &&
- !properties.goog_highpass_filter && !goog_typing_detection &&
- !properties.goog_auto_gain_control &&
+ !properties.goog_highpass_filter && !properties.goog_auto_gain_control &&
!properties.goog_experimental_noise_suppression) {
// Sanity-check: WouldModifyAudio() should return true iff
// |audio_mirroring_| is true.
@@ -600,96 +520,20 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
// has determined webrtc::AudioProcessing will be used.
DCHECK(WouldModifyAudio(properties));
- // Experimental options provided at creation.
- webrtc::Config config;
- config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(
- properties.goog_experimental_noise_suppression));
-
- // TODO(bugs.webrtc.org/7494): Move logic below in ConfigAutomaticGainControl.
- // Retrieve the Hybrid AGC experiment parameters.
- // The hybrid AGC setup, that is AGC1 analog and AGC2 adaptive digital,
- // requires `goog_auto_gain_control` and `goog_experimental_auto_gain_control`
- // to be both active.
- absl::optional<WebRtcHybridAgcParams> hybrid_agc_params;
- absl::optional<WebRtcAnalogAgcClippingControlParams> clipping_control_params;
- if (properties.goog_auto_gain_control &&
- properties.goog_experimental_auto_gain_control) {
- hybrid_agc_params = GetWebRtcHybridAgcParams();
- clipping_control_params = GetWebRtcAnalogAgcClippingControlParams();
- }
- // If the experimental AGC is enabled, check for overridden config params.
- if (properties.goog_experimental_auto_gain_control) {
- auto startup_min_volume = Platform::Current()->GetAgcStartupMinimumVolume();
- auto* experimental_agc = new webrtc::ExperimentalAgc(
- /*enabled=*/true, startup_min_volume.value_or(0));
- // Disable the AGC1 adaptive digital controller if the hybrid AGC is enabled
- // and it's not running in dry-run mode.
- experimental_agc->digital_adaptive_disabled =
- hybrid_agc_params.has_value() && !hybrid_agc_params->dry_run;
- config.Set<webrtc::ExperimentalAgc>(experimental_agc);
-#if BUILDFLAG(IS_CHROMECAST)
- } else {
- // Do not use the analog controller.
- config.Set<webrtc::ExperimentalAgc>(
- new webrtc::ExperimentalAgc(/*enabled=*/false));
-#endif // BUILDFLAG(IS_CHROMECAST)
- }
-
- // Create and configure the webrtc::AudioProcessing.
+ absl::optional<int> agc_startup_min_volume =
+ Platform::Current()->GetAgcStartupMinimumVolume();
absl::optional<std::string> audio_processing_platform_config_json =
Platform::Current()->GetWebRTCAudioProcessingConfiguration();
- webrtc::AudioProcessingBuilder ap_builder;
- if (properties.EchoCancellationIsWebRtcProvided()) {
- webrtc::EchoCanceller3Config aec3_config;
- if (audio_processing_platform_config_json) {
- aec3_config = webrtc::Aec3ConfigFromJsonString(
- *audio_processing_platform_config_json);
- bool config_parameters_already_valid =
- webrtc::EchoCanceller3Config::Validate(&aec3_config);
- RTC_DCHECK(config_parameters_already_valid);
- }
- ap_builder.SetEchoControlFactory(
- std::unique_ptr<webrtc::EchoControlFactory>(
- new webrtc::EchoCanceller3Factory(aec3_config)));
- }
- audio_processing_.reset(ap_builder.Create(config));
+ audio_processing_ = CreateWebRtcAudioProcessingModule(
+ properties.ToAudioProcessingSettings(
+ use_capture_multi_channel_processing_),
+ audio_processing_platform_config_json, agc_startup_min_volume);
- // Enable the audio processing components.
+ // Register as a listener for the echo cancellation playout reference signal.
if (playout_data_source_) {
playout_data_source_->AddPlayoutSink(this);
}
-
- webrtc::AudioProcessing::Config apm_config = audio_processing_->GetConfig();
- apm_config.pipeline.multi_channel_render = true;
- apm_config.pipeline.multi_channel_capture =
- use_capture_multi_channel_processing_;
-
- absl::optional<double> gain_control_compression_gain_db;
- PopulateApmConfig(&apm_config, properties,
- audio_processing_platform_config_json,
- &gain_control_compression_gain_db);
-
- // Set up gain control functionalities.
- ConfigAutomaticGainControl(properties, hybrid_agc_params,
- clipping_control_params,
- gain_control_compression_gain_db, apm_config);
-
- if (goog_typing_detection) {
- // TODO(xians): Remove this |typing_detector_| after the typing suppression
- // is enabled by default.
- typing_detector_ = std::make_unique<webrtc::TypingDetection>();
- EnableTypingDetection(&apm_config, typing_detector_.get());
- }
-
- // Ensure that 48 kHz APM processing is always active. This overrules the
- // default setting in WebRTC of 32 kHz for ARM platforms.
- if (Allow48kHzApmProcessing()) {
- apm_config.pipeline.maximum_internal_processing_rate = 48000;
- }
-
- apm_config.residual_echo_detector.enabled = false;
- audio_processing_->ApplyConfig(apm_config);
}
void MediaStreamAudioProcessor::InitializeCaptureFifo(
@@ -807,29 +651,28 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
DCHECK(audio_processing_);
DCHECK_CALLED_ON_VALID_THREAD(capture_thread_checker_);
- base::subtle::Atomic32 render_delay_ms =
- base::subtle::Acquire_Load(&render_delay_ms_);
- int64_t capture_delay_ms = capture_delay.InMilliseconds();
- DCHECK_LT(capture_delay_ms,
- std::numeric_limits<base::subtle::Atomic32>::max());
+ const base::TimeDelta render_delay = render_delay_;
TRACE_EVENT2("audio", "MediaStreamAudioProcessor::ProcessData",
- "capture_delay_ms", capture_delay_ms, "render_delay_ms",
- render_delay_ms);
+ "capture_delay (ms)", capture_delay.InMillisecondsF(),
+ "render_delay (ms)", render_delay.InMillisecondsF());
+
+ const int64_t total_delay_ms =
+ (capture_delay + render_delay).InMilliseconds();
- const int total_delay_ms =
- static_cast<int>(capture_delay_ms) + render_delay_ms;
if (total_delay_ms > 300 && large_delay_log_count_ < 10) {
- LOG(WARNING) << "Large audio delay, capture delay: " << capture_delay_ms
- << "ms; render delay: " << render_delay_ms << "ms";
+ LOG(WARNING) << "Large audio delay, capture delay: "
+ << capture_delay.InMillisecondsF()
+ << "ms; render delay: " << render_delay.InMillisecondsF()
+ << "ms";
++large_delay_log_count_;
}
- audio_delay_stats_reporter_.ReportDelay(
- capture_delay, base::TimeDelta::FromMilliseconds(render_delay_ms));
+ audio_delay_stats_reporter_.ReportDelay(capture_delay, render_delay);
webrtc::AudioProcessing* ap = audio_processing_.get();
- ap->set_stream_delay_ms(total_delay_ms);
+ DCHECK_LE(total_delay_ms, std::numeric_limits<int>::max());
+ ap->set_stream_delay_ms(base::saturated_cast<int>(total_delay_ms));
// Keep track of the maximum number of preferred channels. The number of
// output channels of APM can increase if preferred by the sinks, but
@@ -872,16 +715,6 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
}
}
- if (typing_detector_) {
- // Ignore remote tracks to avoid unnecessary stats computation.
- auto voice_detected =
- ap->GetStatistics(false /* has_remote_tracks */).voice_detected;
- DCHECK(voice_detected.has_value());
- bool typing_detected =
- typing_detector_->Process(key_pressed, *voice_detected);
- base::subtle::Release_Store(&typing_detected_, typing_detected);
- }
-
PostCrossThreadTask(
*main_thread_runner_, FROM_HERE,
CrossThreadBindOnce(&MediaStreamAudioProcessor::UpdateAecStats,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h
index 687848f8c59..514ec6a300f 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h
@@ -7,12 +7,12 @@
#include <memory>
-#include "base/atomicops.h"
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
+#include "media/base/audio_parameters.h"
#include "media/webrtc/audio_delay_stats_reporter.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -26,13 +26,8 @@
namespace media {
class AudioBus;
-class AudioParameters;
} // namespace media
-namespace webrtc {
-class TypingDetection;
-}
-
namespace blink {
class AecDumpAgentImpl;
@@ -152,7 +147,7 @@ class MODULES_EXPORT MediaStreamAudioProcessor
// WebRtcPlayoutDataSource::Sink implementation.
void OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds) override;
+ base::TimeDelta audio_delay) override;
void OnPlayoutDataSourceChanged() override;
void OnRenderThreadChanged() override;
@@ -199,7 +194,7 @@ class MODULES_EXPORT MediaStreamAudioProcessor
// Cached value for the render delay latency. This member is accessed by
// both the capture audio thread and the render audio thread.
- base::subtle::Atomic32 render_delay_ms_;
+ std::atomic<base::TimeDelta> render_delay_;
// For reporting audio delay stats.
media::AudioDelayStatsReporter audio_delay_stats_reporter_;
@@ -210,7 +205,7 @@ class MODULES_EXPORT MediaStreamAudioProcessor
std::unique_ptr<rtc::TaskQueue> worker_queue_;
// Module to handle processing and format conversion.
- std::unique_ptr<webrtc::AudioProcessing> audio_processing_;
+ rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing_;
// FIFO to provide 10 ms capture chunks.
std::unique_ptr<MediaStreamAudioFifo> capture_fifo_;
@@ -241,12 +236,6 @@ class MODULES_EXPORT MediaStreamAudioProcessor
// Flag to enable stereo channel mirroring.
bool audio_mirroring_;
- // Typing detector. |typing_detected_| is used to show the result of typing
- // detection. It can be accessed by the capture audio thread and by the
- // libjingle thread which calls GetStats().
- std::unique_ptr<webrtc::TypingDetection> typing_detector_;
- base::subtle::Atomic32 typing_detected_;
-
// Communication with browser for AEC dump.
std::unique_ptr<AecDumpAgentImpl> aec_dump_agent_impl_;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor_test.cc
index 2e55a9dfe5d..f8875aa25c1 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor_test.cc
@@ -8,12 +8,12 @@
#include <string>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/aligned_memory.h"
#include "base/path_service.h"
-#include "base/stl_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -88,7 +88,7 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
const int packet_size = params.frames_per_buffer() * 2 * params.channels();
const size_t length = packet_size * kNumberOfPacketsForTest;
std::unique_ptr<char[]> capture_data(new char[length]);
- ReadDataFromSpeechFile(capture_data.get(), length);
+ ReadDataFromSpeechFile(capture_data.get(), static_cast<int>(length));
const int16_t* data_ptr =
reinterpret_cast<const int16_t*>(capture_data.get());
std::unique_ptr<media::AudioBus> data_bus =
@@ -129,7 +129,8 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
}
}
audio_processor->OnPlayoutData(data_bus_playout_to_use,
- params.sample_rate(), 10);
+ params.sample_rate(),
+ base::TimeDelta::FromMilliseconds(10));
}
media::AudioBus* processed_data = nullptr;
@@ -717,6 +718,7 @@ TEST_F(MediaStreamAudioProcessorTest,
EXPECT_EQ(analog_agc.clipping_predictor.reference_window_delay, 5);
EXPECT_FLOAT_EQ(analog_agc.clipping_predictor.clipping_threshold, -1.0f);
EXPECT_FLOAT_EQ(analog_agc.clipping_predictor.crest_factor_margin, 3.0f);
+ EXPECT_TRUE(analog_agc.clipping_predictor.use_predicted_step);
EXPECT_EQ(analog_agc.clipped_level_step, 15);
EXPECT_FLOAT_EQ(analog_agc.clipped_ratio_threshold, 0.1f);
EXPECT_EQ(analog_agc.clipped_wait_frames, 300);
@@ -734,7 +736,8 @@ TEST_F(MediaStreamAudioProcessorTest, TestAgcEnableClippingControl) {
{"crest_factor_margin", ".555"},
{"clipped_level_step", "255"},
{"clipped_ratio_threshold", "0.77"},
- {"clipped_wait_frames", "888"}});
+ {"clipped_wait_frames", "888"},
+ {"use_predicted_step", "false"}});
blink::AudioProcessingProperties properties;
properties.goog_auto_gain_control = true;
@@ -762,6 +765,7 @@ TEST_F(MediaStreamAudioProcessorTest, TestAgcEnableClippingControl) {
EXPECT_EQ(analog_agc.clipping_predictor.reference_window_delay, 333);
EXPECT_FLOAT_EQ(analog_agc.clipping_predictor.clipping_threshold, 4.44f);
EXPECT_FLOAT_EQ(analog_agc.clipping_predictor.crest_factor_margin, 0.555f);
+ EXPECT_FALSE(analog_agc.clipping_predictor.use_predicted_step);
EXPECT_EQ(analog_agc.clipped_level_step, 255);
EXPECT_FLOAT_EQ(analog_agc.clipped_ratio_threshold, 0.77f);
EXPECT_EQ(analog_agc.clipped_wait_frames, 888);
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl
index a63c6e37778..d43f34aa8eb 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl
@@ -7,4 +7,6 @@
dictionary MediaStreamConstraints {
(boolean or MediaTrackConstraints) video = false;
(boolean or MediaTrackConstraints) audio = false;
+ // https://wicg.github.io/prefer-current-tab/#prefer-current-tab
+ boolean preferCurrentTab = false;
};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc
index f6caec91552..536a55d7127 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc
@@ -304,8 +304,8 @@ MediaStreamSource::Capabilities ComputeCapabilitiesForVideoSource(
max_height = std::max(max_height, format.frame_size.height());
max_frame_rate = std::max(max_frame_rate, format.frame_rate);
}
- capabilities.width = {1, max_width};
- capabilities.height = {1, max_height};
+ capabilities.width = {1, static_cast<uint32_t>(max_width)};
+ capabilities.height = {1, static_cast<uint32_t>(max_height)};
capabilities.aspect_ratio = {1.0 / max_height,
static_cast<double>(max_width)};
capabilities.frame_rate = {min_frame_rate, max_frame_rate};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h
index 3d4e6f9db31..3f80b0dc10f 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h
@@ -9,6 +9,7 @@
#include "media/base/video_facing.h"
#include "media/capture/video_capture_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.h"
#include "third_party/blink/renderer/modules/mediastream/video_track_adapter_settings.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
index 39fe24fa5f8..bb569b6f757 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
@@ -1500,7 +1500,10 @@ AudioDeviceCaptureCapability::AudioDeviceCaptureCapability(
}
AudioDeviceCaptureCapability::AudioDeviceCaptureCapability(
- const AudioDeviceCaptureCapability& other) = default;
+ const AudioDeviceCaptureCapability&) = default;
+
+AudioDeviceCaptureCapability& AudioDeviceCaptureCapability::operator=(
+ const AudioDeviceCaptureCapability&) = default;
String AudioDeviceCaptureCapability::DeviceID() const {
return source_ ? String(source_->device().id.data()) : device_id_;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h
index bc3a985c398..5cdb259d884 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h
@@ -52,7 +52,8 @@ class MODULES_EXPORT AudioDeviceCaptureCapability {
// getUserMedia() with device capture for devices that are currently in use.
explicit AudioDeviceCaptureCapability(blink::MediaStreamAudioSource* source);
- AudioDeviceCaptureCapability(const AudioDeviceCaptureCapability& other);
+ AudioDeviceCaptureCapability(const AudioDeviceCaptureCapability&);
+ AudioDeviceCaptureCapability& operator=(const AudioDeviceCaptureCapability&);
// If this capability represents a device currently in use, this method
// returns a pointer to the MediaStreamAudioSource object associated with the
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc
index 77c9546cce3..9fabe28d2eb 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc
@@ -12,6 +12,7 @@
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
+#include "base/stl_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "media/base/audio_parameters.h"
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 da2a349d764..fee493c07ec 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
@@ -33,12 +33,14 @@
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_capture_handle.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_capture_handle_change_event.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_capture_handle_change_event_init.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_double_range.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_long_range.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_capabilities.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_settings.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_point_2d.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"
@@ -48,6 +50,7 @@
#include "third_party/blink/renderer/modules/imagecapture/image_capture.h"
#include "third_party/blink/renderer/modules/mediastream/apply_constraints_request.h"
#include "third_party/blink/renderer/modules/mediastream/media_constraints_impl.h"
+#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_utils.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
@@ -687,19 +690,27 @@ MediaTrackSettings* MediaStreamTrack::getSettings() const {
}
settings->setCursor(value);
}
- if (platform_settings.capture_handle.has_value()) {
- const auto& settings_handle = platform_settings.capture_handle.value();
- auto* capture_handle = CaptureHandle::Create();
- if (settings_handle.origin) {
- capture_handle->setOrigin(settings_handle.origin);
- }
- capture_handle->setHandle(settings_handle.handle);
- settings->setCaptureHandle(capture_handle);
- }
return settings;
}
+CaptureHandle* MediaStreamTrack::getCaptureHandle() const {
+ MediaStreamTrackPlatform::CaptureHandle platform_capture_handle =
+ component_->GetCaptureHandle();
+
+ if (platform_capture_handle.IsEmpty()) {
+ return nullptr;
+ }
+
+ auto* capture_handle = CaptureHandle::Create();
+ if (platform_capture_handle.origin) {
+ capture_handle->setOrigin(platform_capture_handle.origin);
+ }
+ capture_handle->setHandle(platform_capture_handle.handle);
+
+ return capture_handle;
+}
+
ScriptPromise MediaStreamTrack::applyConstraints(
ScriptState* script_state,
const MediaTrackConstraints* constraints) {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.h
index e4889c48834..fbf420dd8a8 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.h
@@ -27,8 +27,10 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_TRACK_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/modules/v8/v8_capture_handle.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/platform/mediastream/media_stream_descriptor.h"
@@ -86,6 +88,7 @@ class MODULES_EXPORT MediaStreamTrack
MediaTrackCapabilities* getCapabilities() const;
MediaTrackConstraints* getConstraints() const;
MediaTrackSettings* getSettings() const;
+ CaptureHandle* getCaptureHandle() const;
ScriptPromise applyConstraints(ScriptState*, const MediaTrackConstraints*);
// This function is called when constrains have been successfully applied.
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.idl b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.idl
index 4752701fbeb..2ccb0607a07 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.idl
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.idl
@@ -52,5 +52,7 @@ enum MediaStreamTrackState {
MediaTrackCapabilities getCapabilities();
MediaTrackConstraints getConstraints();
MediaTrackSettings getSettings();
+ [RuntimeEnabled=CaptureHandle, MeasureAs=CaptureHandle] CaptureHandle? getCaptureHandle();
+
[CallWith=ScriptState] Promise<void> applyConstraints(optional MediaTrackConstraints constraints = {});
};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
index 805b8b04a85..02ad5c1b686 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
@@ -8,18 +8,33 @@
#include "media/capture/video_capturer_source.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
+namespace {
+// TODO(crbug.com/1223353): Remove usage of Thread::Current()->GetTaskRunner()
+// when canvas capture no longer requires a task runner when trying to capture
+// a detached canvas.
+scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerFromFrame(
+ LocalFrame* frame) {
+ return frame ? frame->GetTaskRunner(TaskType::kInternalMediaRealTime)
+ : Thread::Current()->GetTaskRunner();
+}
+} // namespace
+
MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
LocalFrame* frame,
SourceStoppedCallback stop_callback,
std::unique_ptr<media::VideoCapturerSource> source)
- : frame_(frame), source_(std::move(source)) {
+ : MediaStreamVideoSource(GetTaskRunnerFromFrame(frame)),
+ frame_(frame),
+ source_(std::move(source)) {
media::VideoCaptureFormats preferred_formats = source_->GetPreferredFormats();
if (!preferred_formats.empty())
capture_params_.requested_format = preferred_formats.front();
@@ -32,7 +47,8 @@ MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
const MediaStreamDevice& device,
const media::VideoCaptureParams& capture_params,
DeviceCapturerFactoryCallback device_capturer_factory_callback)
- : frame_(frame),
+ : MediaStreamVideoSource(GetTaskRunnerFromFrame(frame)),
+ frame_(frame),
source_(device_capturer_factory_callback.Run(device.session_id())),
capture_params_(capture_params),
device_capturer_factory_callback_(
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
index a3d0f6325c4..f25aa5e2c3a 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
@@ -8,11 +8,13 @@
#include <utility>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_metadata.h"
#include "media/base/video_util.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -159,6 +161,11 @@ void MediaStreamVideoRendererSink::Start() {
CrossThreadBindOnce(&FrameDeliverer::Start,
WTF::CrossThreadUnretained(frame_deliverer_.get())));
+ auto uses_alpha =
+ base::FeatureList::IsEnabled(features::kAllowDropAlphaForMediaStream)
+ ? MediaStreamVideoSink::UsesAlpha::kDependsOnOtherSinks
+ : MediaStreamVideoSink::UsesAlpha::kDefault;
+
MediaStreamVideoSink::ConnectToTrack(
WebMediaStreamTrack(video_component_.Get()),
// This callback is run on IO thread. It is safe to use base::Unretained
@@ -168,8 +175,7 @@ void MediaStreamVideoRendererSink::Start() {
&FrameDeliverer::OnVideoFrame,
WTF::CrossThreadUnretained(frame_deliverer_.get()))),
// Local display video rendering is considered a secure link.
- MediaStreamVideoSink::IsSecure::kYes,
- MediaStreamVideoSink::UsesAlpha::kDefault);
+ MediaStreamVideoSink::IsSecure::kYes, uses_alpha);
if (video_component_->Source()->GetReadyState() ==
MediaStreamSource::kReadyStateEnded ||
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
index cb7efaf6dd6..83a53d5e61a 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <limits>
#include <memory>
+#include <numeric>
#include <utility>
#include "base/callback_helpers.h"
@@ -22,7 +23,6 @@
#include "third_party/blink/renderer/modules/mediastream/video_track_adapter.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -45,10 +45,12 @@ MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
return static_cast<MediaStreamVideoSource*>(source->GetPlatformSource());
}
-MediaStreamVideoSource::MediaStreamVideoSource() : state_(NEW) {}
+MediaStreamVideoSource::MediaStreamVideoSource(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : WebPlatformMediaStreamSource(std::move(task_runner)), state_(NEW) {}
MediaStreamVideoSource::~MediaStreamVideoSource() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (remove_last_track_callback_) {
std::move(remove_last_track_callback_).Run();
}
@@ -62,7 +64,7 @@ void MediaStreamVideoSource::AddTrack(
const VideoTrackSettingsCallback& settings_callback,
const VideoTrackFormatCallback& format_callback,
ConstraintsOnceCallback callback) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DCHECK(!base::Contains(tracks_, track));
tracks_.push_back(track);
secure_tracker_.Add(track, true);
@@ -102,7 +104,7 @@ void MediaStreamVideoSource::AddTrack(
void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track,
base::OnceClosure callback) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
{
auto it = std::find(tracks_.begin(), tracks_.end(), video_track);
DCHECK(it != tracks_.end());
@@ -170,7 +172,7 @@ void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track,
}
void MediaStreamVideoSource::DidStopSource(RestartResult result) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DCHECK(remove_last_track_callback_);
if (result == RestartResult::IS_STOPPED) {
state_ = ENDED;
@@ -199,9 +201,9 @@ void MediaStreamVideoSource::ReconfigureTrack(
void MediaStreamVideoSource::StopForRestart(RestartCallback callback,
bool send_black_frame) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (state_ != STARTED) {
- Thread::Current()->GetTaskRunner()->PostTask(
+ GetTaskRunner()->PostTask(
FROM_HERE,
WTF::Bind(std::move(callback), RestartResult::INVALID_STATE));
return;
@@ -231,13 +233,13 @@ void MediaStreamVideoSource::StopForRestart(RestartCallback callback,
}
void MediaStreamVideoSource::StopSourceForRestartImpl() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DCHECK_EQ(state_, STOPPING_FOR_RESTART);
OnStopForRestartDone(false);
}
void MediaStreamVideoSource::OnStopForRestartDone(bool did_stop_for_restart) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (state_ == ENDED) {
return;
}
@@ -254,16 +256,16 @@ void MediaStreamVideoSource::OnStopForRestartDone(bool did_stop_for_restart) {
RestartResult result = did_stop_for_restart ? RestartResult::IS_STOPPED
: RestartResult::IS_RUNNING;
- Thread::Current()->GetTaskRunner()->PostTask(
- FROM_HERE, WTF::Bind(std::move(restart_callback_), result));
+ GetTaskRunner()->PostTask(FROM_HERE,
+ WTF::Bind(std::move(restart_callback_), result));
}
void MediaStreamVideoSource::Restart(
const media::VideoCaptureFormat& new_format,
RestartCallback callback) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (state_ != STOPPED_FOR_RESTART) {
- Thread::Current()->GetTaskRunner()->PostTask(
+ GetTaskRunner()->PostTask(
FROM_HERE,
WTF::Bind(std::move(callback), RestartResult::INVALID_STATE));
return;
@@ -280,7 +282,7 @@ void MediaStreamVideoSource::RestartSourceImpl(
}
void MediaStreamVideoSource::OnRestartDone(bool did_restart) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (state_ == ENDED)
return;
@@ -295,13 +297,13 @@ void MediaStreamVideoSource::OnRestartDone(bool did_restart) {
RestartResult result =
did_restart ? RestartResult::IS_RUNNING : RestartResult::IS_STOPPED;
- Thread::Current()->GetTaskRunner()->PostTask(
- FROM_HERE, WTF::Bind(std::move(restart_callback_), result));
+ GetTaskRunner()->PostTask(FROM_HERE,
+ WTF::Bind(std::move(restart_callback_), result));
}
void MediaStreamVideoSource::UpdateHasConsumers(MediaStreamVideoTrack* track,
bool has_consumers) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
const auto it =
std::find(suspended_tracks_.begin(), suspended_tracks_.end(), track);
if (has_consumers) {
@@ -317,7 +319,7 @@ void MediaStreamVideoSource::UpdateHasConsumers(MediaStreamVideoTrack* track,
void MediaStreamVideoSource::UpdateCapturingLinkSecure(
MediaStreamVideoTrack* track,
bool is_secure) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
secure_tracker_.Update(track, is_secure);
NotifyCapturingLinkSecured(CountEncodedSinks());
}
@@ -330,24 +332,24 @@ void MediaStreamVideoSource::NotifyCapturingLinkSecured(
}
void MediaStreamVideoSource::SetDeviceRotationDetection(bool enabled) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
enable_device_rotation_detection_ = enabled;
}
base::SingleThreadTaskRunner* MediaStreamVideoSource::io_task_runner() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return Platform::Current()->GetIOTaskRunner().get();
}
absl::optional<media::VideoCaptureFormat>
MediaStreamVideoSource::GetCurrentFormat() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return absl::optional<media::VideoCaptureFormat>();
}
absl::optional<media::VideoCaptureParams>
MediaStreamVideoSource::GetCurrentCaptureParams() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return absl::optional<media::VideoCaptureParams>();
}
@@ -359,7 +361,7 @@ size_t MediaStreamVideoSource::CountEncodedSinks() const {
}
void MediaStreamVideoSource::UpdateNumEncodedSinks() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
size_t count = CountEncodedSinks();
if (count == 1) {
OnEncodedSinkEnabled();
@@ -372,7 +374,7 @@ void MediaStreamVideoSource::UpdateNumEncodedSinks() {
void MediaStreamVideoSource::DoChangeSource(
const MediaStreamDevice& new_device) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DVLOG(1) << "MediaStreamVideoSource::DoChangeSource: "
<< ", new device id = " << new_device.id
<< ", session id = " << new_device.session_id();
@@ -384,7 +386,7 @@ void MediaStreamVideoSource::DoChangeSource(
}
void MediaStreamVideoSource::DoStopSource() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DVLOG(3) << "DoStopSource()";
if (state_ == ENDED)
return;
@@ -396,7 +398,7 @@ void MediaStreamVideoSource::DoStopSource() {
void MediaStreamVideoSource::OnStartDone(
mojom::blink::MediaStreamRequestResult result) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DVLOG(3) << "OnStartDone({result =" << result << "})";
if (state_ == ENDED) {
OnLog(
@@ -421,7 +423,7 @@ void MediaStreamVideoSource::OnStartDone(
}
void MediaStreamVideoSource::FinalizeAddPendingTracks() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
std::vector<PendingTrackInfo> pending_track_descriptors;
pending_track_descriptors.swap(pending_tracks_);
for (auto& track_info : pending_track_descriptors) {
@@ -453,7 +455,7 @@ void MediaStreamVideoSource::FinalizeAddPendingTracks() {
}
void MediaStreamVideoSource::StartFrameMonitoring() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
absl::optional<media::VideoCaptureFormat> current_format = GetCurrentFormat();
double frame_rate = current_format ? current_format->frame_rate : 0.0;
if (current_format && enable_device_rotation_detection_) {
@@ -467,7 +469,7 @@ void MediaStreamVideoSource::StartFrameMonitoring() {
void MediaStreamVideoSource::SetReadyState(
WebMediaStreamSource::ReadyState state) {
DVLOG(3) << "MediaStreamVideoSource::SetReadyState state " << state;
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (!Owner().IsNull())
Owner().SetReadyState(state);
for (auto* track : tracks_)
@@ -476,7 +478,7 @@ void MediaStreamVideoSource::SetReadyState(
void MediaStreamVideoSource::SetMutedState(bool muted_state) {
DVLOG(3) << "MediaStreamVideoSource::SetMutedState state=" << muted_state;
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (!Owner().IsNull()) {
Owner().SetReadyState(muted_state ? WebMediaStreamSource::kReadyStateMuted
: WebMediaStreamSource::kReadyStateLive);
@@ -514,7 +516,7 @@ VideoCaptureFeedbackCB MediaStreamVideoSource::GetFeedbackCallback() const {
}
scoped_refptr<VideoTrackAdapter> MediaStreamVideoSource::GetTrackAdapter() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (!track_adapter_) {
track_adapter_ =
base::MakeRefCounted<VideoTrackAdapter>(io_task_runner(), GetWeakPtr());
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
index 13c6a581eae..f5329a10318 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
@@ -811,4 +811,42 @@ TEST_F(MediaStreamVideoSourceTest, CanDiscardAlpha) {
sink_alpha.DisconnectFromTrack();
}
+TEST_F(MediaStreamVideoSourceTest, CanDiscardAlphaIfOtherSinksDiscard) {
+ InSequence s;
+ WebMediaStreamTrack track = CreateTrack();
+
+ MockMediaStreamVideoSink sink_no_alpha;
+ sink_no_alpha.SetUsesAlpha(MediaStreamVideoSink::UsesAlpha::kNo);
+ MockMediaStreamVideoSink sink_depends;
+ sink_depends.SetUsesAlpha(
+ MediaStreamVideoSink::UsesAlpha::kDependsOnOtherSinks);
+ MockMediaStreamVideoSink sink_alpha;
+ sink_alpha.SetUsesAlpha(MediaStreamVideoSink::UsesAlpha::kDefault);
+
+ // Keep alpha if the only sink is DependsOnOtherSinks.
+ EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+ sink_depends.ConnectToTrack(track);
+
+ // Now alpha can be dropped since other sink drops alpha.
+ EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+ sink_no_alpha.ConnectToTrack(track);
+
+ // Alpha can not longer be dropped since a sink uses it.
+ EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+ sink_alpha.ConnectToTrack(track);
+
+ // Now that alpha track is removes, alpha can be discarded again.
+ EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+ sink_alpha.DisconnectFromTrack();
+
+ // Now that the alpha dropping track is disconnected, we keep alpha since the
+ // only sink depends on other sinks, which keeps alpha by default.
+ EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+ sink_no_alpha.DisconnectFromTrack();
+
+ // Alpha is discarded if there are no sinks connected.
+ EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+ sink_depends.DisconnectFromTrack();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
index b67b9982a03..0454bb56fee 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -19,7 +19,6 @@
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
@@ -554,8 +553,11 @@ void MediaStreamVideoTrack::AddSink(
AddSinkInternal(&sinks_, sink);
frame_deliverer_->AddCallback(sink, callback);
secure_tracker_.Add(sink, is_secure == MediaStreamVideoSink::IsSecure::kYes);
- if (uses_alpha == MediaStreamVideoSink::UsesAlpha::kDefault)
+ if (uses_alpha == MediaStreamVideoSink::UsesAlpha::kDefault) {
alpha_using_sinks_.insert(sink);
+ } else if (uses_alpha == MediaStreamVideoSink::UsesAlpha::kNo) {
+ alpha_discarding_sinks_.insert(sink);
+ }
// Request source to deliver a frame because a new sink is added.
if (!source_)
return;
@@ -563,7 +565,11 @@ void MediaStreamVideoTrack::AddSink(
RequestRefreshFrame();
source_->UpdateCapturingLinkSecure(this,
secure_tracker_.is_capturing_secure());
- source_->SetCanDiscardAlpha(alpha_using_sinks_.IsEmpty());
+ // Alpha can't be discarded if any sink uses alpha, or if the only sinks
+ // connected are kDependsOnOtherSinks.
+ const bool can_discard_alpha =
+ alpha_using_sinks_.IsEmpty() && !alpha_discarding_sinks_.IsEmpty();
+ source_->SetCanDiscardAlpha(can_discard_alpha);
if (is_screencast_)
StartTimerForRequestingFrames();
}
@@ -582,6 +588,7 @@ void MediaStreamVideoTrack::RemoveSink(WebMediaStreamSink* sink) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
RemoveSinkInternal(&sinks_, sink);
alpha_using_sinks_.erase(sink);
+ alpha_discarding_sinks_.erase(sink);
frame_deliverer_->RemoveCallback(sink);
secure_tracker_.Remove(sink);
if (!source_)
@@ -589,7 +596,10 @@ void MediaStreamVideoTrack::RemoveSink(WebMediaStreamSink* sink) {
UpdateSourceHasConsumers();
source_->UpdateCapturingLinkSecure(this,
secure_tracker_.is_capturing_secure());
- source_->SetCanDiscardAlpha(alpha_using_sinks_.IsEmpty());
+ const bool can_discard_alpha =
+ sinks_.IsEmpty() ||
+ (alpha_using_sinks_.IsEmpty() && !alpha_discarding_sinks_.IsEmpty());
+ source_->SetCanDiscardAlpha(can_discard_alpha);
// Restart the timer with existing sinks.
if (is_screencast_)
StartTimerForRequestingFrames();
@@ -701,20 +711,40 @@ void MediaStreamVideoTrack::GetSettings(
settings.display_surface = info->display_surface;
settings.logical_surface = info->logical_surface;
settings.cursor = info->cursor;
- if (info->capture_handle) {
- settings.capture_handle.emplace();
- if (!info->capture_handle->origin.opaque()) {
- settings.capture_handle->origin =
- String::FromUTF8(info->capture_handle->origin.Serialize());
- }
- settings.capture_handle->handle =
- WebString::FromUTF16(info->capture_handle->capture_handle);
- } else {
- settings.capture_handle = absl::nullopt;
- }
}
}
+MediaStreamTrackPlatform::CaptureHandle
+MediaStreamVideoTrack::GetCaptureHandle() {
+ DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
+
+ MediaStreamTrackPlatform::CaptureHandle capture_handle;
+
+ if (!source_) {
+ return capture_handle;
+ }
+
+ const MediaStreamDevice& device = source_->device();
+ if (!device.display_media_info.has_value()) {
+ return capture_handle;
+ }
+ const media::mojom::DisplayMediaInformationPtr& info =
+ device.display_media_info.value();
+
+ if (!info->capture_handle) {
+ return capture_handle;
+ }
+
+ if (!info->capture_handle->origin.opaque()) {
+ capture_handle.origin =
+ String::FromUTF8(info->capture_handle->origin.Serialize());
+ }
+ capture_handle.handle =
+ WebString::FromUTF16(info->capture_handle->capture_handle);
+
+ return capture_handle;
+}
+
void MediaStreamVideoTrack::OnReadyStateChanged(
WebMediaStreamSource::ReadyState state) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
@@ -752,19 +782,6 @@ void MediaStreamVideoTrack::OnFrameDropped(
void MediaStreamVideoTrack::SetMinimumFrameRate(double min_frame_rate) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
min_frame_rate_ = min_frame_rate;
- if (signal_observer_)
- signal_observer_->SetMinimumFrameRate(min_frame_rate);
-}
-
-MediaStreamVideoTrackSignalObserver* MediaStreamVideoTrack::SignalObserver() {
- DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
- return signal_observer_.Get();
-}
-
-void MediaStreamVideoTrack::SetSignalObserver(
- MediaStreamVideoTrackSignalObserver* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
- signal_observer_ = observer;
}
void MediaStreamVideoTrack::StartTimerForRequestingFrames() {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
index d24b524f2a2..a643df0b2cb 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
@@ -85,6 +85,7 @@ class MODULES_EXPORT MediaStreamVideoTrack : public MediaStreamTrackPlatform {
WebMediaStreamTrack::ContentHintType content_hint) override;
void StopAndNotify(base::OnceClosure callback) override;
void GetSettings(MediaStreamTrackPlatform::Settings& settings) override;
+ MediaStreamTrackPlatform::CaptureHandle GetCaptureHandle() override;
// Add |sink| to receive state changes on the main render thread and video
// frames in the |callback| method on the IO-thread.
@@ -220,6 +221,7 @@ class MODULES_EXPORT MediaStreamVideoTrack : public MediaStreamTrackPlatform {
// This is used for tracking if no connected video use alpha.
HashSet<WebMediaStreamSink*> alpha_using_sinks_;
+ HashSet<WebMediaStreamSink*> alpha_discarding_sinks_;
// Remembering our desired video size and frame rate.
int width_ = 0;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h
deleted file mode 100644
index 701bb957d96..00000000000
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track_signal_observer.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_TRACK_SIGNAL_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_TRACK_SIGNAL_OBSERVER_H_
-
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-
-namespace blink {
-
-class MediaStreamVideoTrackSignalObserver : public GarbageCollectedMixin {
- public:
- virtual ~MediaStreamVideoTrackSignalObserver() = default;
- virtual void SetMinimumFrameRate(double) = 0;
- virtual void RequestFrame() = 0;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_TRACK_SIGNAL_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/mock_encoded_video_frame.h b/chromium/third_party/blink/renderer/modules/mediastream/mock_encoded_video_frame.h
index 2ca3ec92b06..a25f1553464 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/mock_encoded_video_frame.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/mock_encoded_video_frame.h
@@ -8,6 +8,7 @@
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc b/chromium/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
index 0b20eb4770a..7d27f01c3f2 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
@@ -8,6 +8,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -18,7 +19,8 @@ MockMediaStreamVideoSource::MockMediaStreamVideoSource()
MockMediaStreamVideoSource::MockMediaStreamVideoSource(
bool respond_to_request_refresh_frame)
- : respond_to_request_refresh_frame_(respond_to_request_refresh_frame),
+ : MediaStreamVideoSource(scheduler::GetSingleThreadTaskRunnerForTesting()),
+ respond_to_request_refresh_frame_(respond_to_request_refresh_frame),
max_requested_height_(0),
max_requested_width_(0),
max_requested_frame_rate_(0.0),
@@ -27,7 +29,8 @@ MockMediaStreamVideoSource::MockMediaStreamVideoSource(
MockMediaStreamVideoSource::MockMediaStreamVideoSource(
const media::VideoCaptureFormat& format,
bool respond_to_request_refresh_frame)
- : format_(format),
+ : MediaStreamVideoSource(scheduler::GetSingleThreadTaskRunnerForTesting()),
+ format_(format),
respond_to_request_refresh_frame_(respond_to_request_refresh_frame),
max_requested_height_(format.frame_size.height()),
max_requested_width_(format.frame_size.width()),
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc b/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc
index ec7ce45585e..4f83509eb18 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc
@@ -81,7 +81,6 @@ std::string GetAudioProcesingPropertiesLogString(
"goog_audio_mirroring: %s, "
"goog_auto_gain_control: %s, "
"goog_experimental_echo_cancellation: %s, "
- "goog_typing_noise_detection: %s, "
"goog_noise_suppression: %s, "
"goog_experimental_noise_suppression: %s, "
"goog_highpass_filter: %s, "
@@ -93,7 +92,6 @@ std::string GetAudioProcesingPropertiesLogString(
bool_to_string(properties.goog_audio_mirroring),
bool_to_string(properties.goog_auto_gain_control),
bool_to_string(properties.goog_experimental_echo_cancellation),
- bool_to_string(properties.goog_typing_noise_detection),
bool_to_string(properties.goog_noise_suppression),
bool_to_string(properties.goog_experimental_noise_suppression),
bool_to_string(properties.goog_highpass_filter),
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/remote_media_stream_track_adapter.cc b/chromium/third_party/blink/renderer/modules/mediastream/remote_media_stream_track_adapter.cc
index 91415b099fc..e45fb4de2da 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/remote_media_stream_track_adapter.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/remote_media_stream_track_adapter.cc
@@ -46,8 +46,8 @@ void RemoteVideoTrackAdapter::InitializeWebVideoTrack(
std::unique_ptr<TrackObserver> observer,
bool enabled) {
DCHECK(main_thread_->BelongsToCurrentThread());
- auto video_source_ptr =
- std::make_unique<MediaStreamRemoteVideoSource>(std::move(observer));
+ auto video_source_ptr = std::make_unique<MediaStreamRemoteVideoSource>(
+ main_thread_, std::move(observer));
MediaStreamRemoteVideoSource* video_source = video_source_ptr.get();
InitializeTrack(MediaStreamSource::kTypeVideo);
track()->Source()->SetPlatformSource(std::move(video_source_ptr));
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 e18f606a1e2..bc19ca1dc12 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
@@ -28,8 +28,8 @@ namespace {
static int g_next_request_id = 0;
-// The histogram counts the number of calls to the JS API
-// getUserMedia(), getDisplayMedia() or GetCurrentBrowsingContextMedia().
+// The histogram counts the number of calls to the JS APIs
+// getUserMedia() and getDisplayMedia().
void UpdateAPICount(UserMediaRequest::MediaType media_type) {
RTCAPIName api_name = RTCAPIName::kGetUserMedia;
switch (media_type) {
@@ -39,9 +39,6 @@ void UpdateAPICount(UserMediaRequest::MediaType media_type) {
case UserMediaRequest::MediaType::kDisplayMedia:
api_name = RTCAPIName::kGetDisplayMedia;
break;
- case UserMediaRequest::MediaType::kGetCurrentBrowsingContextMedia:
- api_name = RTCAPIName::kGetCurrentBrowsingContextMedia;
- break;
}
UpdateWebRTCMethodCount(api_name);
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
index 933ff7ac4b1..55edc9d7921 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
@@ -19,7 +19,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/mediastream/media_devices.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
+#include "third_party/blink/public/mojom/media/capture_handle_config.mojom-blink.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_source.h"
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h"
#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "ui/display/screen_info.h"
using testing::_;
using testing::Mock;
@@ -483,12 +484,12 @@ class UserMediaChromeClient : public EmptyChromeClient {
screen_info_.rect = gfx::Rect(blink::kDefaultScreenCastWidth,
blink::kDefaultScreenCastHeight);
}
- const ScreenInfo& GetScreenInfo(LocalFrame&) const override {
+ const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override {
return screen_info_;
}
private:
- ScreenInfo screen_info_;
+ display::ScreenInfo screen_info_;
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
index 1300f8abc79..d42b3d7309c 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
@@ -15,13 +15,13 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "media/base/audio_parameters.h"
#include "media/capture/video_capture_types.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/mediastream/media_stream_controls.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_source.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h"
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
@@ -53,6 +53,7 @@
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+#include "ui/display/screen_info.h"
#include "ui/gfx/geometry/size.h"
namespace blink {
@@ -62,6 +63,7 @@ using blink::mojom::MediaStreamType;
using blink::mojom::StreamSelectionStrategy;
using EchoCancellationType =
blink::AudioProcessingProperties::EchoCancellationType;
+using AudioSourceErrorCode = media::AudioCapturerSource::ErrorCode;
namespace {
@@ -99,6 +101,8 @@ const char* MediaStreamRequestResultToString(MediaStreamRequestResult value) {
return "KILL_SWITCH_ON";
case MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED:
return "SYSTEM_PERMISSION_DENIED";
+ case MediaStreamRequestResult::DEVICE_IN_USE:
+ return "DEVICE_IN_USE";
case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS:
return "NUM_MEDIA_REQUEST_RESULTS";
default:
@@ -149,9 +153,7 @@ std::string GetOnTrackStartedLogString(
void InitializeAudioTrackControls(UserMediaRequest* user_media_request,
TrackControls* track_controls) {
if (user_media_request->MediaRequestType() ==
- UserMediaRequest::MediaType::kDisplayMedia ||
- user_media_request->MediaRequestType() ==
- UserMediaRequest::MediaType::kGetCurrentBrowsingContextMedia) {
+ UserMediaRequest::MediaType::kDisplayMedia) {
track_controls->requested = true;
track_controls->stream_type = MediaStreamType::DISPLAY_AUDIO_CAPTURE;
return;
@@ -187,13 +189,10 @@ void InitializeVideoTrackControls(UserMediaRequest* user_media_request,
if (user_media_request->MediaRequestType() ==
UserMediaRequest::MediaType::kDisplayMedia) {
track_controls->requested = true;
- track_controls->stream_type = MediaStreamType::DISPLAY_VIDEO_CAPTURE;
- return;
- } else if (user_media_request->MediaRequestType() ==
- UserMediaRequest::MediaType::kGetCurrentBrowsingContextMedia) {
- track_controls->requested = true;
track_controls->stream_type =
- MediaStreamType::DISPLAY_VIDEO_CAPTURE_THIS_TAB;
+ user_media_request->should_prefer_current_tab()
+ ? MediaStreamType::DISPLAY_VIDEO_CAPTURE_THIS_TAB
+ : MediaStreamType::DISPLAY_VIDEO_CAPTURE;
return;
}
@@ -1061,7 +1060,8 @@ gfx::Size UserMediaProcessor::GetScreenSize() {
gfx::Size screen_size(blink::kDefaultScreenCastWidth,
blink::kDefaultScreenCastHeight);
if (frame_) { // Can be null in tests.
- const ScreenInfo& info = frame_->GetChromeClient().GetScreenInfo(*frame_);
+ const display::ScreenInfo& info =
+ frame_->GetChromeClient().GetScreenInfo(*frame_);
screen_size = info.rect.size();
}
return screen_size;
@@ -1710,6 +1710,10 @@ void UserMediaProcessor::DelayedGetUserMediaRequestFailed(
user_media_request->Fail(UserMediaRequest::Error::kSystemPermissionDenied,
"Permission denied by system");
return;
+ case MediaStreamRequestResult::DEVICE_IN_USE:
+ user_media_request->Fail(UserMediaRequest::Error::kDeviceInUse,
+ "Device in use");
+ return;
}
NOTREACHED();
user_media_request->Fail(UserMediaRequest::Error::kPermissionDenied, "");
@@ -1774,15 +1778,19 @@ bool UserMediaProcessor::RemoveLocalSource(MediaStreamSource* source) {
String message;
if (source->GetType() == MediaStreamSource::kTypeAudio) {
auto error = MediaStreamAudioSource::From(source)->ErrorCode();
- if (error.has_value() &&
- error.value() ==
- media::AudioCapturerSource::ErrorCode::kSystemPermissions) {
- result = MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED;
- message =
- "System Permssions prevented access to audio capture device";
- } else {
- result = MediaStreamRequestResult::TRACK_START_FAILURE_AUDIO;
- message = "Failed to access audio capture device";
+ switch (error.value_or(AudioSourceErrorCode::kUnknown)) {
+ case AudioSourceErrorCode::kSystemPermissions:
+ result = MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED;
+ message =
+ "System Permssions prevented access to audio capture device";
+ break;
+ case AudioSourceErrorCode::kDeviceInUse:
+ result = MediaStreamRequestResult::DEVICE_IN_USE;
+ message = "Audio capture device already in use";
+ break;
+ default:
+ result = MediaStreamRequestResult::TRACK_START_FAILURE_AUDIO;
+ message = "Failed to access audio capture device";
}
} else {
result = MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO;
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 fc892213f5a..6035533ca0c 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
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_boolean_mediatrackconstraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_domexception_overconstrainederror.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/space_split_string.h"
@@ -48,6 +49,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/modules/mediastream/identifiability_metrics.h"
#include "third_party/blink/renderer/modules/mediastream/media_constraints_impl.h"
+#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/overconstrained_error.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
@@ -279,24 +281,26 @@ void CountVideoConstraintUses(ExecutionContext* context,
}
}
-MediaConstraints ParseOptions(ExecutionContext* context,
- const BooleanOrMediaTrackConstraints& options,
- MediaErrorState& error_state) {
- MediaConstraints constraints;
-
- if (options.IsNull()) {
- // Do nothing.
- } else if (options.IsMediaTrackConstraints()) {
- constraints = media_constraints_impl::Create(
- context, options.GetAsMediaTrackConstraints(), error_state);
- } else {
- DCHECK(options.IsBoolean());
- if (options.GetAsBoolean()) {
- constraints = media_constraints_impl::Create();
- }
- }
-
- return constraints;
+MediaConstraints ParseOptions(
+ ExecutionContext* execution_context,
+ const V8UnionBooleanOrMediaTrackConstraints* options,
+ MediaErrorState& error_state) {
+ if (!options)
+ return MediaConstraints();
+ switch (options->GetContentType()) {
+ case V8UnionBooleanOrMediaTrackConstraints::ContentType::kBoolean:
+ if (options->GetAsBoolean())
+ return media_constraints_impl::Create();
+ else
+ return MediaConstraints();
+ case V8UnionBooleanOrMediaTrackConstraints::ContentType::
+ kMediaTrackConstraints:
+ return media_constraints_impl::Create(
+ execution_context, options->GetAsMediaTrackConstraints(),
+ error_state);
+ }
+ NOTREACHED();
+ return MediaConstraints();
}
} // namespace
@@ -318,17 +322,10 @@ class UserMediaRequest::V8Callbacks final : public UserMediaRequest::Callbacks {
MediaStream* stream) override {
success_callback_->InvokeAndReportException(callback_this_value, stream);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void OnError(ScriptWrappable* callback_this_value,
const V8MediaStreamError* error) override {
error_callback_->InvokeAndReportException(callback_this_value, error);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void OnError(ScriptWrappable* callback_this_value,
- DOMExceptionOrOverconstrainedError error) override {
- error_callback_->InvokeAndReportException(callback_this_value, error);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
Member<V8NavigatorUserMediaSuccessCallback> success_callback_;
@@ -365,9 +362,7 @@ UserMediaRequest* UserMediaRequest::Create(
error_state.ThrowTypeError("Mandatory zoom constraint is not supported");
return nullptr;
}
- } else if (media_type == UserMediaRequest::MediaType::kDisplayMedia ||
- media_type ==
- UserMediaRequest::MediaType::kGetCurrentBrowsingContextMedia) {
+ } else if (media_type == UserMediaRequest::MediaType::kDisplayMedia) {
// https://w3c.github.io/mediacapture-screen-share/#mediadevices-additions
// MediaDevices Additions
// The user agent MUST reject audio-only requests.
@@ -403,9 +398,10 @@ UserMediaRequest* UserMediaRequest::Create(
return nullptr;
}
if (audio.IsNull() && video.IsNull()) {
- video = ParseOptions(context,
- BooleanOrMediaTrackConstraints::FromBoolean(true),
- error_state);
+ video = ParseOptions(
+ context,
+ MakeGarbageCollected<V8UnionBooleanOrMediaTrackConstraints>(true),
+ error_state);
if (error_state.HadException())
return nullptr;
}
@@ -423,7 +419,8 @@ UserMediaRequest* UserMediaRequest::Create(
CountVideoConstraintUses(context, video);
return MakeGarbageCollected<UserMediaRequest>(
- context, controller, media_type, audio, video, callbacks, surface);
+ context, controller, media_type, audio, video,
+ options->preferCurrentTab(), callbacks, surface);
}
UserMediaRequest* UserMediaRequest::Create(
@@ -445,7 +442,7 @@ UserMediaRequest* UserMediaRequest::CreateForTesting(
const MediaConstraints& video) {
return MakeGarbageCollected<UserMediaRequest>(
nullptr, nullptr, UserMediaRequest::MediaType::kUserMedia, audio, video,
- nullptr, IdentifiableSurface());
+ /*should_prefer_current_tab=*/false, nullptr, IdentifiableSurface());
}
UserMediaRequest::UserMediaRequest(ExecutionContext* context,
@@ -453,12 +450,14 @@ UserMediaRequest::UserMediaRequest(ExecutionContext* context,
UserMediaRequest::MediaType media_type,
MediaConstraints audio,
MediaConstraints video,
+ bool should_prefer_current_tab,
Callbacks* callbacks,
IdentifiableSurface surface)
: ExecutionContextLifecycleObserver(context),
media_type_(media_type),
audio_(audio),
video_(video),
+ should_prefer_current_tab_(should_prefer_current_tab),
should_disable_hardware_noise_suppression_(
RuntimeEnabledFeatures::DisableHardwareNoiseSuppressionEnabled(
context)),
@@ -581,15 +580,9 @@ void UserMediaRequest::FailConstraint(const String& constraint_name,
RecordIdentifiabilityMetric(surface_, GetExecutionContext(),
IdentifiabilityBenignStringToken(message));
// After this call, the execution context may be invalid.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
callbacks_->OnError(
nullptr, MakeGarbageCollected<V8MediaStreamError>(
OverconstrainedError::Create(constraint_name, message)));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- callbacks_->OnError(
- nullptr, DOMExceptionOrOverconstrainedError::FromOverconstrainedError(
- OverconstrainedError::Create(constraint_name, message)));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
is_resolved_ = true;
}
@@ -617,6 +610,7 @@ void UserMediaRequest::Fail(Error name, const String& message) {
exception_code = DOMExceptionCode::kAbortError;
break;
case Error::kTrackStart:
+ case Error::kDeviceInUse:
exception_code = DOMExceptionCode::kNotReadableError;
break;
case Error::kNotSupported:
@@ -631,16 +625,9 @@ void UserMediaRequest::Fail(Error name, const String& message) {
RecordIdentifiabilityMetric(surface_, GetExecutionContext(),
IdentifiabilityBenignStringToken(message));
// After this call, the execution context may be invalid.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
callbacks_->OnError(nullptr, MakeGarbageCollected<V8MediaStreamError>(
MakeGarbageCollected<DOMException>(
exception_code, message)));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- callbacks_->OnError(
- nullptr,
- DOMExceptionOrOverconstrainedError::FromDOMException(
- MakeGarbageCollected<DOMException>(exception_code, message)));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
is_resolved_ = true;
}
@@ -655,18 +642,10 @@ void UserMediaRequest::ContextDestroyed() {
"audio constraints=%s, video constraints=%s",
AudioConstraints().ToString().Utf8().c_str(),
VideoConstraints().ToString().Utf8().c_str()));
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
callbacks_->OnError(nullptr, MakeGarbageCollected<V8MediaStreamError>(
MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError,
"Context destroyed")));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- callbacks_->OnError(
- nullptr,
- DOMExceptionOrOverconstrainedError::FromDOMException(
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
- "Context destroyed")));
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
controller_ = nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.h b/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.h
index 12d726196a3..a9c9bfcd754 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.h
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_USER_MEDIA_REQUEST_H_
#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/renderer/bindings/modules/v8/dom_exception_or_overconstrained_error.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/bindings/modules/v8/v8_typedefs.h"
@@ -67,14 +66,11 @@ class MODULES_EXPORT UserMediaRequest final
kTrackStart,
kFailedDueToShutdown,
kKillSwitchOn,
- kSystemPermissionDenied
+ kSystemPermissionDenied,
+ kDeviceInUse
};
- enum class MediaType {
- kUserMedia,
- kDisplayMedia,
- kGetCurrentBrowsingContextMedia,
- };
+ enum class MediaType { kUserMedia, kDisplayMedia };
class Callbacks : public GarbageCollected<Callbacks> {
public:
@@ -82,13 +78,8 @@ class MODULES_EXPORT UserMediaRequest final
virtual void OnSuccess(ScriptWrappable* callback_this_value,
MediaStream*) = 0;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual void OnError(ScriptWrappable* callback_this_value,
const V8MediaStreamError* error) = 0;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- virtual void OnError(ScriptWrappable* callback_this_value,
- DOMExceptionOrOverconstrainedError) = 0;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
virtual void Trace(Visitor*) const {}
@@ -120,6 +111,7 @@ class MODULES_EXPORT UserMediaRequest final
MediaType media_type,
MediaConstraints audio,
MediaConstraints video,
+ bool should_prefer_current_tab,
Callbacks*,
IdentifiableSurface surface);
~UserMediaRequest() override;
@@ -160,12 +152,15 @@ class MODULES_EXPORT UserMediaRequest final
return has_transient_user_activation_;
}
+ bool should_prefer_current_tab() const { return should_prefer_current_tab_; }
+
void Trace(Visitor*) const override;
private:
MediaType media_type_;
MediaConstraints audio_;
MediaConstraints video_;
+ const bool should_prefer_current_tab_ = false;
bool should_disable_hardware_noise_suppression_;
bool has_transient_user_activation_ = false;
int request_id_ = -1;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc b/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc
index 99d93b4820f..e6db74514d1 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc
@@ -23,7 +23,7 @@ namespace blink {
// Size of the buffer that WebAudio processes each time, it is the same value
// as AudioNode::ProcessingSizeInFrames in WebKit.
// static
-const size_t WebAudioMediaStreamAudioSink::kWebAudioRenderBufferSize = 128;
+const int WebAudioMediaStreamAudioSink::kWebAudioRenderBufferSize = 128;
WebAudioMediaStreamAudioSink::WebAudioMediaStreamAudioSink(
MediaStreamComponent* component,
@@ -120,7 +120,7 @@ void WebAudioMediaStreamAudioSink::SetClient(
void WebAudioMediaStreamAudioSink::ProvideInput(
const WebVector<float*>& audio_data,
- size_t number_of_frames) {
+ int number_of_frames) {
NON_REENTRANT_SCOPE(provide_input_reentrancy_checker_);
DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize);
@@ -134,7 +134,7 @@ void WebAudioMediaStreamAudioSink::ProvideInput(
media::AudioBus::CreateWrapper(static_cast<int>(audio_data.size()));
}
- output_wrapper_->set_frames(static_cast<int>(number_of_frames));
+ output_wrapper_->set_frames(number_of_frames);
for (size_t i = 0; i < audio_data.size(); ++i)
output_wrapper_->SetChannelData(static_cast<int>(i), audio_data[i]);
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h b/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h
index ef1f148aab5..c12e1b1e34d 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h
@@ -46,7 +46,7 @@ class MODULES_EXPORT WebAudioMediaStreamAudioSink
public media::AudioConverter::InputCallback,
public WebMediaStreamAudioSink {
public:
- static const size_t kWebAudioRenderBufferSize;
+ static const int kWebAudioRenderBufferSize;
explicit WebAudioMediaStreamAudioSink(MediaStreamComponent* component,
int context_sample_rate);
@@ -61,7 +61,7 @@ class MODULES_EXPORT WebAudioMediaStreamAudioSink
// WebAudioSourceProvider implementation.
void SetClient(WebAudioSourceProviderClient* client) override;
void ProvideInput(const WebVector<float*>& audio_data,
- size_t number_of_frames) override;
+ int number_of_frames) override;
// Method to allow the unittests to inject its own sink parameters to avoid
// query the hardware.
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink_test.cc
index dd14e81e74a..dfc4b6ebed2 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink_test.cc
@@ -60,7 +60,7 @@ TEST_F(WebAudioMediaStreamAudioSinkTest, VerifyDataFlow) {
// Point the WebVector into memory owned by |sink_bus_|.
WebVector<float*> audio_data(static_cast<size_t>(sink_bus_->channels()));
- for (size_t i = 0; i < audio_data.size(); ++i)
+ for (int i = 0; i < sink_bus_->channels(); ++i)
audio_data[i] = sink_bus_->channel(i);
// Enable the |source_provider_| by asking for data. This will inject
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
index 5284b8391da..f1a5b76c1d0 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
@@ -59,12 +59,6 @@ struct CrossThreadCopier<viz::SurfaceId>
STATIC_ONLY(CrossThreadCopier);
};
-template <>
-struct CrossThreadCopier<media::VideoTransformation>
- : public CrossThreadCopierPassThrough<media::VideoTransformation> {
- STATIC_ONLY(CrossThreadCopier);
-};
-
} // namespace WTF
namespace blink {
@@ -1165,13 +1159,14 @@ void WebMediaPlayerMS::ActivateSurfaceLayerForVideo() {
}
}
-void WebMediaPlayerMS::OnFirstFrameReceived(media::VideoRotation video_rotation,
- bool is_opaque) {
+void WebMediaPlayerMS::OnFirstFrameReceived(
+ media::VideoTransformation video_transform,
+ bool is_opaque) {
DVLOG(1) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
has_first_frame_ = true;
- OnRotationChanged(video_rotation);
+ OnTransformChanged(video_transform);
OnOpacityChanged(is_opaque);
if (surface_layer_mode_ == WebMediaPlayer::SurfaceLayerMode::kAlways)
@@ -1199,16 +1194,17 @@ void WebMediaPlayerMS::OnOpacityChanged(bool is_opaque) {
}
}
-void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation) {
+void WebMediaPlayerMS::OnTransformChanged(
+ media::VideoTransformation video_transform) {
DVLOG(1) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- video_transformation_ = {video_rotation, 0};
+ video_transformation_ = video_transform;
if (!bridge_) {
// Keep the old |video_layer_| alive until SetCcLayer() is called with a new
// pointer, as it may use the pointer from the last call.
auto new_video_layer =
- cc::VideoLayer::Create(compositor_.get(), video_rotation);
+ cc::VideoLayer::Create(compositor_.get(), video_transformation_);
get_client()->SetCcLayer(new_video_layer.get());
video_layer_ = std::move(new_video_layer);
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
index 8e9c0d47327..00430194753 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
@@ -56,6 +56,8 @@ scoped_refptr<media::VideoFrame> CopyFrame(
if (frame->HasTextures()) {
DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB ||
frame->format() == media::PIXEL_FORMAT_XRGB ||
+ frame->format() == media::PIXEL_FORMAT_ABGR ||
+ frame->format() == media::PIXEL_FORMAT_XBGR ||
frame->format() == media::PIXEL_FORMAT_I420 ||
frame->format() == media::PIXEL_FORMAT_NV12);
auto provider = Platform::Current()->SharedMainThreadContextProvider();
@@ -83,9 +85,15 @@ scoped_refptr<media::VideoFrame> CopyFrame(
}
} else {
DCHECK(frame->IsMappable());
- DCHECK(frame->format() == media::PIXEL_FORMAT_I420A ||
- frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_NV12);
+ if (frame->format() != media::PIXEL_FORMAT_I420A &&
+ frame->format() != media::PIXEL_FORMAT_I420 &&
+ frame->format() != media::PIXEL_FORMAT_NV12 &&
+ frame->format() != media::PIXEL_FORMAT_ARGB) {
+ DLOG(WARNING) << frame->format() << " is not supported.";
+ return media::VideoFrame::CreateColorFrame(
+ frame->visible_rect().size(), 0u, 0x80, 0x80, frame->timestamp());
+ }
+
const gfx::Size& coded_size = frame->coded_size();
new_frame = media::VideoFrame::CreateFrame(
frame->format(), coded_size, frame->visible_rect(),
@@ -105,6 +113,12 @@ scoped_refptr<media::VideoFrame> CopyFrame(
new_frame->data(media::VideoFrame::kUVPlane),
new_frame->stride(media::VideoFrame::kUVPlane),
coded_size.width(), coded_size.height());
+ } else if (frame->format() == media::PIXEL_FORMAT_ARGB) {
+ libyuv::ARGBCopy(frame->data(media::VideoFrame::kARGBPlane),
+ frame->stride(media::VideoFrame::kARGBPlane),
+ new_frame->data(media::VideoFrame::kARGBPlane),
+ new_frame->stride(media::VideoFrame::kARGBPlane),
+ coded_size.width(), coded_size.height());
} else {
libyuv::I420Copy(frame->data(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kYPlane),
@@ -258,7 +272,7 @@ void WebMediaPlayerMSCompositor::EnableSubmission(
video_frame_provider_client_->StopUsingProvider();
}
- submitter_->SetRotation(transformation.rotation);
+ submitter_->SetTransform(transformation);
submitter_->SetForceSubmit(force_submit);
submitter_->EnableSubmission(id);
video_frame_provider_client_ = submitter_.get();
@@ -461,10 +475,13 @@ void WebMediaPlayerMSCompositor::PutCurrentFrame() {
base::TimeDelta WebMediaPlayerMSCompositor::GetPreferredRenderInterval() {
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
if (!rendering_frame_buffer_) {
+ DCHECK_GE(last_render_length_, base::TimeDelta());
return last_render_length_;
- } else {
- return rendering_frame_buffer_->average_frame_duration();
}
+
+ DCHECK_GE(rendering_frame_buffer_->average_frame_duration(),
+ base::TimeDelta());
+ return rendering_frame_buffer_->average_frame_duration();
}
void WebMediaPlayerMSCompositor::StartRendering() {
@@ -584,8 +601,10 @@ void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
{
base::AutoLock auto_lock(current_frame_lock_);
// Last timestamp in the stream might not have timestamp.
- if (current_frame_ && !frame->timestamp().is_zero())
+ if (current_frame_ && !frame->timestamp().is_zero() &&
+ frame->timestamp() > current_frame_->timestamp()) {
last_render_length_ = frame->timestamp() - current_frame_->timestamp();
+ }
SetCurrentFrame(std::move(frame), is_copy, absl::nullopt);
}
if (video_frame_provider_client_)
@@ -611,9 +630,10 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
bool is_first_frame = true;
bool has_frame_size_changed = false;
- absl::optional<media::VideoRotation> new_rotation = media::VIDEO_ROTATION_0;
+ absl::optional<media::VideoTransformation> new_transform =
+ media::kNoTransformation;
if (frame->metadata().transformation)
- new_rotation = frame->metadata().transformation->rotation;
+ new_transform = frame->metadata().transformation;
absl::optional<bool> new_opacity;
new_opacity = media::IsOpaque(frame->format());
@@ -622,19 +642,16 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
// We have a current frame, so determine what has changed.
is_first_frame = false;
- auto current_video_rotation = media::VIDEO_ROTATION_0;
- if (current_frame_->metadata().transformation) {
- current_video_rotation =
- current_frame_->metadata().transformation->rotation;
- }
-
+ auto current_video_transform =
+ current_frame_->metadata().transformation.value_or(
+ media::kNoTransformation);
has_frame_size_changed =
- RotationAdjustedSize(*new_rotation, frame->natural_size()) !=
- RotationAdjustedSize(current_video_rotation,
+ RotationAdjustedSize(new_transform->rotation, frame->natural_size()) !=
+ RotationAdjustedSize(current_video_transform.rotation,
current_frame_->natural_size());
- if (current_video_rotation == *new_rotation)
- new_rotation.reset();
+ if (current_video_transform == *new_transform)
+ new_transform.reset();
if (*new_opacity == media::IsOpaque(current_frame_->format()))
new_opacity.reset();
@@ -667,14 +684,14 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
*video_frame_compositor_task_runner_, FROM_HERE,
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::CheckForFrameChanges,
WrapRefCounted(this), is_first_frame,
- has_frame_size_changed, std::move(new_rotation),
+ has_frame_size_changed, std::move(new_transform),
std::move(new_opacity)));
}
void WebMediaPlayerMSCompositor::CheckForFrameChanges(
bool is_first_frame,
bool has_frame_size_changed,
- absl::optional<media::VideoRotation> new_frame_rotation,
+ absl::optional<media::VideoTransformation> new_frame_transform,
absl::optional<bool> new_frame_opacity) {
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
@@ -682,17 +699,17 @@ void WebMediaPlayerMSCompositor::CheckForFrameChanges(
PostCrossThreadTask(
*main_task_runner_, FROM_HERE,
CrossThreadBindOnce(&WebMediaPlayerMS::OnFirstFrameReceived, player_,
- *new_frame_rotation, *new_frame_opacity));
+ *new_frame_transform, *new_frame_opacity));
return;
}
- if (new_frame_rotation.has_value()) {
+ if (new_frame_transform.has_value()) {
PostCrossThreadTask(
*main_task_runner_, FROM_HERE,
- CrossThreadBindOnce(&WebMediaPlayerMS::OnRotationChanged, player_,
- *new_frame_rotation));
+ CrossThreadBindOnce(&WebMediaPlayerMS::OnTransformChanged, player_,
+ *new_frame_transform));
if (submitter_)
- submitter_->SetRotation(*new_frame_rotation);
+ submitter_->SetTransform(*new_frame_transform);
}
if (new_frame_opacity.has_value()) {
PostCrossThreadTask(*main_task_runner_, FROM_HERE,
@@ -703,10 +720,10 @@ void WebMediaPlayerMSCompositor::CheckForFrameChanges(
PostCrossThreadTask(
*main_task_runner_, FROM_HERE,
CrossThreadBindOnce(&WebMediaPlayerMS::TriggerResize, player_));
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&WebMediaPlayerMS::ResetCanvasCache, player_));
}
- PostCrossThreadTask(
- *main_task_runner_, FROM_HERE,
- CrossThreadBindOnce(&WebMediaPlayerMS::ResetCanvasCache, player_));
}
void WebMediaPlayerMSCompositor::StartRenderingInternal() {
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
index dfb68936008..5267862f11b 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
@@ -192,7 +192,7 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
void CheckForFrameChanges(
bool is_first_frame,
bool has_frame_size_changed,
- absl::optional<media::VideoRotation> new_frame_rotation,
+ absl::optional<media::VideoTransformation> new_frame_transform,
absl::optional<bool> new_frame_opacity);
void StartRenderingInternal();
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
index 466ad97d9d6..3c885eca211 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
@@ -12,7 +12,6 @@
#include "base/containers/circular_deque.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/test/gmock_callback_support.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -295,7 +294,7 @@ void MockMediaStreamVideoRenderer::QueueFrames(
int double_size_index,
media::VideoRotation rotation) {
gfx::Size standard_size = standard_size_;
- for (size_t i = 0; i < timestamp_or_frame_type.size(); i++) {
+ for (wtf_size_t i = 0; i < timestamp_or_frame_type.size(); i++) {
const int token = timestamp_or_frame_type[i];
if (static_cast<int>(i) == double_size_index) {
standard_size =
@@ -394,7 +393,7 @@ class MockWebVideoFrameSubmitter : public WebVideoFrameSubmitter {
MOCK_METHOD0(StartRendering, void());
MOCK_METHOD0(StopRendering, void());
MOCK_METHOD1(MockInitialize, void(cc::VideoFrameProvider*));
- MOCK_METHOD1(SetRotation, void(media::VideoRotation));
+ MOCK_METHOD1(SetTransform, void(media::VideoTransformation));
MOCK_METHOD1(SetIsSurfaceVisible, void(bool));
MOCK_METHOD1(SetIsPageVisible, void(bool));
MOCK_METHOD1(SetForceSubmit, void(bool));
@@ -577,8 +576,10 @@ class WebMediaPlayerMSTest
media::MediaContentType media_content_type) override {}
void DidPlayerMediaPositionStateChange(double playback_rate,
base::TimeDelta duration,
- base::TimeDelta position) override {}
+ base::TimeDelta position,
+ bool end_of_media) override {}
void DidDisableAudioOutputSinkChanges() override {}
+ void DidUseAudioServiceChange(bool uses_audio_service) override {}
void DidPlayerSizeChange(const gfx::Size& size) override {}
void DidBufferUnderflow() override {}
void DidSeek() override {}
@@ -1060,7 +1061,7 @@ TEST_P(WebMediaPlayerMSTest, RotationChange) {
timestamps = Vector<int>({33, kTestBrake});
provider->QueueFrames(timestamps, false, false, 17, media::VIDEO_ROTATION_0);
if (enable_surface_layer_for_video_) {
- EXPECT_CALL(*submitter_ptr_, SetRotation(media::VIDEO_ROTATION_0));
+ EXPECT_CALL(*submitter_ptr_, SetTransform(media::kNoTransformation));
} else {
EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStopRendering());
@@ -1077,7 +1078,9 @@ TEST_P(WebMediaPlayerMSTest, RotationChange) {
timestamps = Vector<int>({66, kTestBrake});
provider->QueueFrames(timestamps, false, false, 17, media::VIDEO_ROTATION_90);
if (enable_surface_layer_for_video_) {
- EXPECT_CALL(*submitter_ptr_, SetRotation(media::VIDEO_ROTATION_90));
+ EXPECT_CALL(
+ *submitter_ptr_,
+ SetTransform(media::VideoTransformation(media::VIDEO_ROTATION_90)));
} else {
EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStopRendering());
@@ -1443,6 +1446,34 @@ TEST_P(WebMediaPlayerMSTest, GetVideoFramePresentationMetadata) {
testing::Mock::VerifyAndClearExpectations(this);
}
+TEST_P(WebMediaPlayerMSTest, ValidPreferredInterval) {
+ InitializeWebMediaPlayerMS();
+ LoadAndGetFrameProvider(true);
+
+ const bool opaque_frame = testing::get<1>(GetParam());
+ const bool odd_size_frame = testing::get<2>(GetParam());
+
+ gfx::Size frame_size(kStandardWidth - (odd_size_frame ? kOddSizeOffset : 0),
+ kStandardHeight - (odd_size_frame ? kOddSizeOffset : 0));
+
+ auto frame = media::VideoFrame::CreateZeroInitializedFrame(
+ opaque_frame ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
+ frame_size, gfx::Rect(frame_size), frame_size,
+ base::TimeDelta::FromSeconds(10));
+
+ compositor_->EnqueueFrame(std::move(frame), true);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_GE(compositor_->GetPreferredRenderInterval(), base::TimeDelta());
+
+ frame = media::VideoFrame::CreateZeroInitializedFrame(
+ opaque_frame ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
+ frame_size, gfx::Rect(frame_size), frame_size,
+ base::TimeDelta::FromSeconds(1));
+ compositor_->EnqueueFrame(std::move(frame), true);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_GE(compositor_->GetPreferredRenderInterval(), base::TimeDelta());
+}
+
INSTANTIATE_TEST_SUITE_P(All,
WebMediaPlayerMSTest,
::testing::Combine(::testing::Bool(),
diff --git a/chromium/third_party/blink/renderer/modules/modalclosewatcher/idls.gni b/chromium/third_party/blink/renderer/modules/modalclosewatcher/idls.gni
deleted file mode 100644
index 7f813637ebc..00000000000
--- a/chromium/third_party/blink/renderer/modules/modalclosewatcher/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "modal_close_watcher.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc b/chromium/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc
index 02bf0b84f76..e1ae68ee0ca 100644
--- a/chromium/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc
+++ b/chromium/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
diff --git a/chromium/third_party/blink/renderer/modules/modules.gni b/chromium/third_party/blink/renderer/modules/modules.gni
index 86553bba594..fec3fa365e3 100644
--- a/chromium/third_party/blink/renderer/modules/modules.gni
+++ b/chromium/third_party/blink/renderer/modules/modules.gni
@@ -49,8 +49,6 @@ set_defaults("blink_modules_sources") {
# is the list normally applied to static libraries and source sets.
configs = default_compiler_configs
configs += [
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- "//build/config/compiler:no_size_t_to_int_warning",
"//third_party/blink/renderer:config",
"//third_party/blink/renderer/modules:modules_implementation",
"//third_party/blink/renderer:non_test_config",
diff --git a/chromium/third_party/blink/renderer/modules/modules_idl_files.gni b/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
deleted file mode 100644
index 5d9ce54298a..00000000000
--- a/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
+++ /dev/null
@@ -1,294 +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/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 multiple "current directories".
-
-# IDL files for a module are defined by idls.gni in the module's corresponding
-# directory. idls.gni can define certain variables to add additional IDL files
-# to the build.
-#
-# modules_idl_files = [
-# # IDL files that don't fit in one of the below categories. Typically
-# # (but not required to) defines interfaces.
-# # Spec reference: https://heycam.github.io/webidl/#idl-interfaces
-# ]
-#
-# modules_callback_function_idl_files = [
-# # IDL files that only define callback functions (note: these are distinct
-# # from callback interfaces).
-# # Spec reference: https://heycam.github.io/webidl/#dfn-callback-function).
-# # TODO(dcheng): Figure out why this is its own category.
-# ]
-#
-# modules_dictionary_idl_files = [
-# # IDL files that define dictionaries and any supporting types (such as
-# # enums) for the dictionaries.
-# # Spec reference: https://heycam.github.io/webidl/#idl-dictionaries
-# ]
-#
-# modules_dependency_idl_files = [
-# # IDL files that either define partial interfaces or target (right side
-# # of) `includes`.
-# # Spec reference: https://heycam.github.io/webidl/#dfn-partial-interface
-# # Spec reference: https://heycam.github.io/webidl/#idl-interface-mixins
-# ]
-#
-# modules_testing_dependency_idl_files = [
-# # Similar to |modules_dependency_idl_files| but limited to things that are
-# # exposed only for testing.
-# ]
-#
-# modules_typedefs_enums_only_idl_files = [
-# # IDL files that only have typedefs/enums.
-# ]
-_idl_imports = [
- "//third_party/blink/renderer/modules/accessibility/idls.gni",
- "//third_party/blink/renderer/modules/ad_auction/idls.gni",
- "//third_party/blink/renderer/modules/animationworklet/idls.gni",
- "//third_party/blink/renderer/modules/app_banner/idls.gni",
- "//third_party/blink/renderer/modules/audio_output_devices/idls.gni",
- "//third_party/blink/renderer/modules/background_fetch/idls.gni",
- "//third_party/blink/renderer/modules/background_sync/idls.gni",
- "//third_party/blink/renderer/modules/badging/idls.gni",
- "//third_party/blink/renderer/modules/battery/idls.gni",
- "//third_party/blink/renderer/modules/beacon/idls.gni",
- "//third_party/blink/renderer/modules/bluetooth/idls.gni",
- "//third_party/blink/renderer/modules/broadcastchannel/idls.gni",
- "//third_party/blink/renderer/modules/buckets/idls.gni",
- "//third_party/blink/renderer/modules/cache_storage/idls.gni",
- "//third_party/blink/renderer/modules/canvas/idls.gni",
- "//third_party/blink/renderer/modules/clipboard/idls.gni",
- "//third_party/blink/renderer/modules/compression/idls.gni",
- "//third_party/blink/renderer/modules/compute_pressure/idls.gni",
- "//third_party/blink/renderer/modules/contacts_picker/idls.gni",
- "//third_party/blink/renderer/modules/content_index/idls.gni",
- "//third_party/blink/renderer/modules/cookie_store/idls.gni",
- "//third_party/blink/renderer/modules/credentialmanager/idls.gni",
- "//third_party/blink/renderer/modules/crypto/idls.gni",
- "//third_party/blink/renderer/modules/csspaint/idls.gni",
- "//third_party/blink/renderer/modules/delegated_ink/idls.gni",
- "//third_party/blink/renderer/modules/managed_device/idls.gni",
- "//third_party/blink/renderer/modules/device_orientation/idls.gni",
- "//third_party/blink/renderer/modules/donottrack/idls.gni",
- "//third_party/blink/renderer/modules/encoding/idls.gni",
- "//third_party/blink/renderer/modules/encryptedmedia/idls.gni",
- "//third_party/blink/renderer/modules/eventsource/idls.gni",
- "//third_party/blink/renderer/modules/eyedropper/idls.gni",
- "//third_party/blink/renderer/modules/filesystem/idls.gni",
- "//third_party/blink/renderer/modules/file_system_access/idls.gni",
- "//third_party/blink/renderer/modules/font_access/idls.gni",
- "//third_party/blink/renderer/modules/gamepad/idls.gni",
- "//third_party/blink/renderer/modules/geolocation/idls.gni",
- "//third_party/blink/renderer/modules/handwriting/idls.gni",
- "//third_party/blink/renderer/modules/hid/idls.gni",
- "//third_party/blink/renderer/modules/idle/idls.gni",
- "//third_party/blink/renderer/modules/imagecapture/idls.gni",
- "//third_party/blink/renderer/modules/indexeddb/idls.gni",
- "//third_party/blink/renderer/modules/installedapp/idls.gni",
- "//third_party/blink/renderer/modules/keyboard/idls.gni",
- "//third_party/blink/renderer/modules/launch/idls.gni",
- "//third_party/blink/renderer/modules/locks/idls.gni",
- "//third_party/blink/renderer/modules/lock_screen/idls.gni",
- "//third_party/blink/renderer/modules/manifest/idls.gni",
- "//third_party/blink/renderer/modules/media_capabilities/idls.gni",
- "//third_party/blink/renderer/modules/mediacapturefromelement/idls.gni",
- "//third_party/blink/renderer/modules/mediarecorder/idls.gni",
- "//third_party/blink/renderer/modules/mediasession/idls.gni",
- "//third_party/blink/renderer/modules/mediasource/idls.gni",
- "//third_party/blink/renderer/modules/mediastream/idls.gni",
- "//third_party/blink/renderer/modules/breakout_box/idls.gni",
- "//third_party/blink/renderer/modules/modalclosewatcher/idls.gni",
- "//third_party/blink/renderer/modules/native_io/idls.gni",
- "//third_party/blink/renderer/modules/navigatorcontentutils/idls.gni",
- "//third_party/blink/renderer/modules/netinfo/idls.gni",
- "//third_party/blink/renderer/modules/nfc/idls.gni",
- "//third_party/blink/renderer/modules/notifications/idls.gni",
- "//third_party/blink/renderer/modules/payments/idls.gni",
- "//third_party/blink/renderer/modules/payments/goods/idls.gni",
- "//third_party/blink/renderer/modules/peerconnection/idls.gni",
- "//third_party/blink/renderer/modules/permissions/idls.gni",
- "//third_party/blink/renderer/modules/picture_in_picture/idls.gni",
- "//third_party/blink/renderer/modules/plugins/idls.gni",
- "//third_party/blink/renderer/modules/presentation/idls.gni",
- "//third_party/blink/renderer/modules/push_messaging/idls.gni",
- "//third_party/blink/renderer/modules/quota/idls.gni",
- "//third_party/blink/renderer/modules/remoteplayback/idls.gni",
- "//third_party/blink/renderer/modules/sanitizer_api/idls.gni",
- "//third_party/blink/renderer/modules/scheduler/idls.gni",
- "//third_party/blink/renderer/modules/screen_enumeration/idls.gni",
- "//third_party/blink/renderer/modules/screen_orientation/idls.gni",
- "//third_party/blink/renderer/modules/sensor/idls.gni",
- "//third_party/blink/renderer/modules/service_worker/idls.gni",
- "//third_party/blink/renderer/modules/shapedetection/idls.gni",
- "//third_party/blink/renderer/modules/speech/idls.gni",
- "//third_party/blink/renderer/modules/srcobject/idls.gni",
- "//third_party/blink/renderer/modules/storage/idls.gni",
- "//third_party/blink/renderer/modules/url_pattern/idls.gni",
- "//third_party/blink/renderer/modules/vibration/idls.gni",
- "//third_party/blink/renderer/modules/video_rvfc/idls.gni",
- "//third_party/blink/renderer/modules/virtualkeyboard/idls.gni",
- "//third_party/blink/renderer/modules/wake_lock/idls.gni",
- "//third_party/blink/renderer/modules/webaudio/idls.gni",
- "//third_party/blink/renderer/modules/webcodecs/idls.gni",
- "//third_party/blink/renderer/modules/webdatabase/idls.gni",
- "//third_party/blink/renderer/modules/webgl/idls.gni",
- "//third_party/blink/renderer/modules/webgpu/idls.gni",
- "//third_party/blink/renderer/modules/webid/idls.gni",
- "//third_party/blink/renderer/modules/webmidi/idls.gni",
- "//third_party/blink/renderer/modules/webshare/idls.gni",
- "//third_party/blink/renderer/modules/websockets/idls.gni",
- "//third_party/blink/renderer/modules/webtransport/idls.gni",
- "//third_party/blink/renderer/modules/webusb/idls.gni",
- "//third_party/blink/renderer/modules/xr/idls.gni",
-]
-
-# TODO(dcheng): For whatever reason, is_android doesn't seem to be defined, even
-# if using import() instead of read_file() in the foreach() loop below...
-if (!is_android) {
- _idl_imports += [
- "//third_party/blink/renderer/modules/direct_sockets/idls.gni",
- "//third_party/blink/renderer/modules/serial/idls.gni",
- ]
-}
-
-# Do not add IDL files directly to these lists. See _idl_imports above instead
-# on how to add IDL files for a module.
-modules_idl_files = []
-modules_callback_function_idl_files = []
-modules_dictionary_idl_files = []
-modules_dependency_idl_files = []
-modules_testing_dependency_idl_files = []
-modules_typedefs_enums_only_idl_files = []
-
-foreach(idl_import, _idl_imports) {
- # Avoid reassignment error by assigning to empty scope first.
- _imported = {
- }
- _imported = read_file(idl_import, "scope")
-
- # Paths are potentially relative to the location of the .gni. Rebase them
- # relative to "." so get_path_info() works as expected.
- gni_dir = get_path_info(idl_import, "dir")
-
- if (defined(_imported.modules_idl_files)) {
- modules_idl_files +=
- get_path_info(rebase_path(_imported.modules_idl_files, ".", gni_dir),
- "abspath")
- }
-
- if (defined(_imported.modules_callback_function_idl_files)) {
- modules_callback_function_idl_files +=
- get_path_info(rebase_path(_imported.modules_callback_function_idl_files,
- ".",
- gni_dir),
- "abspath")
- }
-
- if (defined(_imported.modules_dictionary_idl_files)) {
- modules_dictionary_idl_files +=
- get_path_info(
- rebase_path(_imported.modules_dictionary_idl_files, ".", gni_dir),
- "abspath")
- }
-
- if (defined(_imported.modules_dependency_idl_files)) {
- modules_dependency_idl_files +=
- get_path_info(
- rebase_path(_imported.modules_dependency_idl_files, ".", gni_dir),
- "abspath")
- }
-
- if (defined(_imported.modules_testing_dependency_idl_files)) {
- modules_testing_dependency_idl_files +=
- get_path_info(
- rebase_path(_imported.modules_testing_dependency_idl_files,
- ".",
- gni_dir),
- "abspath")
- }
-
- if (defined(_imported.modules_typedefs_enums_only_idl_files)) {
- modules_typedefs_enums_only_idl_files +=
- get_path_info(
- rebase_path(_imported.modules_typedefs_enums_only_idl_files,
- ".",
- gni_dir),
- "abspath")
- }
-}
-
-bindings_modules_output_dir = "$bindings_output_dir/modules"
-blink_modules_output_dir = "$root_gen_dir/third_party/blink/renderer/modules"
-
-modules_core_global_constructors_original_interfaces = [
- "AnimationWorkletGlobalScope",
- "AudioWorkletGlobalScope",
- "PaintWorkletGlobalScope",
- "ServiceWorkerGlobalScope",
-]
-
-# The size and the order in the following list must match to the previous one.
-modules_core_global_constructors_original_interface_basenames = [
- "animation_worklet_global_scope",
- "audio_worklet_global_scope",
- "paint_worklet_global_scope",
- "service_worker_global_scope",
-]
-
-modules_global_constructors_original_interfaces = [
- "AnimationWorkletGlobalScope",
- "AudioWorkletGlobalScope",
- "DedicatedWorkerGlobalScope",
- "PaintWorkletGlobalScope",
- "ServiceWorkerGlobalScope",
- "SharedWorkerGlobalScope",
- "Window",
-]
-
-# The size and the order in the following list must match to the previous one.
-modules_global_constructors_original_interface_basenames = [
- "animation_worklet_global_scope",
- "audio_worklet_global_scope",
- "dedicated_worker_global_scope",
- "paint_worklet_global_scope",
- "service_worker_global_scope",
- "shared_worker_global_scope",
- "window",
-]
-
-# The interfaces aren't technically files, but we can treat them as file names
-# to get process_file_template to generate lists of IDL files corresponding
-# to each interface.
-modules_core_global_constructors_generated_idl_files = process_file_template(
- modules_core_global_constructors_original_interface_basenames,
- [ "$blink_modules_output_dir/{{source_name_part}}_core_constructors.idl" ])
-modules_global_constructors_generated_idl_files = process_file_template(
- modules_global_constructors_original_interface_basenames,
- [ "$blink_modules_output_dir/{{source_name_part}}_modules_constructors.idl" ])
-
-modules_definition_idl_files = modules_dictionary_idl_files + modules_idl_files
-
-# Static IDL files
-modules_static_interface_idl_files =
- modules_callback_function_idl_files + modules_typedefs_enums_only_idl_files
-
-modules_static_dependency_idl_files =
- modules_dependency_idl_files + modules_testing_dependency_idl_files
-
-if (use_blink_v8_binding_new_idl_interface) {
- modules_generated_dependency_idl_files = []
-} else {
- modules_generated_dependency_idl_files =
- modules_core_global_constructors_generated_idl_files +
- modules_global_constructors_generated_idl_files
-}
-
-# 'modules_dependency_idl_files' is already used in Source/modules, so avoid
-# collision
-modules_all_dependency_idl_files =
- modules_static_dependency_idl_files + modules_generated_dependency_idl_files
diff --git a/chromium/third_party/blink/renderer/modules/modules_initializer.cc b/chromium/third_party/blink/renderer/modules/modules_initializer.cc
index 40786347231..ff9ed78fd22 100644
--- a/chromium/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/chromium/third_party/blink/renderer/modules/modules_initializer.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.h"
#include "third_party/blink/renderer/core/css/background_color_paint_image_generator.h"
+#include "third_party/blink/renderer/core/css/clip_path_paint_image_generator.h"
#include "third_party/blink/renderer/core/css/css_paint_image_generator.h"
#include "third_party/blink/renderer/core/dom/context_features_client_impl.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -42,8 +43,9 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h"
#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h"
#include "third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h"
-#include "third_party/blink/renderer/modules/csspaint/background_color_paint_image_generator_impl.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/background_color_paint_image_generator_impl.h"
+#include "third_party/blink/renderer/modules/csspaint/nativepaint/clip_path_paint_image_generator_impl.h"
#include "third_party/blink/renderer/modules/device_orientation/device_motion_controller.h"
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.h"
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h"
@@ -80,6 +82,7 @@
#include "third_party/blink/renderer/modules/screen_enumeration/window_screens.h"
#include "third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h"
#include "third_party/blink/renderer/modules/service_worker/navigator_service_worker.h"
+#include "third_party/blink/renderer/modules/storage/dom_window_storage.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.h"
@@ -176,6 +179,7 @@ void ModulesInitializer::Initialize() {
CSSPaintImageGenerator::Init(CSSPaintImageGeneratorImpl::Create);
BackgroundColorPaintImageGenerator::Init(
BackgroundColorPaintImageGeneratorImpl::Create);
+ ClipPathPaintImageGenerator::Init(ClipPathPaintImageGeneratorImpl::Create);
WebDatabaseHost::GetInstance().Init();
MediaSourceRegistryImpl::Init();
@@ -363,6 +367,12 @@ void ModulesInitializer::CloneSessionStorage(
storage_namespace->CloneTo(WebString::FromLatin1(clone_to_namespace));
}
+void ModulesInitializer::EvictSessionStorageCachedData(Page* page) {
+ StorageNamespace* storage_namespace = StorageNamespace::From(page);
+ if (storage_namespace)
+ storage_namespace->EvictSessionStorageCachedData();
+}
+
void ModulesInitializer::DidChangeManifest(LocalFrame& frame) {
ManifestManager::From(*frame.DomWindow())->DidChangeManifest();
}
@@ -372,8 +382,9 @@ void ModulesInitializer::NotifyOrientationChanged(LocalFrame& frame) {
->NotifyOrientationChanged();
}
-void ModulesInitializer::DidUpdateScreens(LocalFrame& frame,
- const ScreenInfos& screen_infos) {
+void ModulesInitializer::DidUpdateScreens(
+ LocalFrame& frame,
+ const display::ScreenInfos& screen_infos) {
auto* window = frame.DomWindow();
if (auto* supplement =
Supplement<LocalDOMWindow>::From<WindowScreens>(window)) {
@@ -384,6 +395,24 @@ void ModulesInitializer::DidUpdateScreens(LocalFrame& frame,
}
}
+void ModulesInitializer::SetLocalStorageArea(
+ LocalFrame& frame,
+ mojo::PendingRemote<mojom::blink::StorageArea> local_storage_area) {
+ if (!frame.DomWindow())
+ return;
+ DOMWindowStorage::From(*frame.DomWindow())
+ .InitLocalStorage(std::move(local_storage_area));
+}
+
+void ModulesInitializer::SetSessionStorageArea(
+ LocalFrame& frame,
+ mojo::PendingRemote<mojom::blink::StorageArea> session_storage_area) {
+ if (!frame.DomWindow())
+ return;
+ DOMWindowStorage::From(*frame.DomWindow())
+ .InitSessionStorage(std::move(session_storage_area));
+}
+
void ModulesInitializer::RegisterInterfaces(mojo::BinderMap& binders) {
DCHECK(Platform::Current());
binders.Add(ConvertToBaseRepeatingCallback(
diff --git a/chromium/third_party/blink/renderer/modules/modules_initializer.h b/chromium/third_party/blink/renderer/modules/modules_initializer.h
index 4769e54c4ee..aa995759f09 100644
--- a/chromium/third_party/blink/renderer/modules/modules_initializer.h
+++ b/chromium/third_party/blink/renderer/modules/modules_initializer.h
@@ -48,10 +48,17 @@ class MODULES_EXPORT ModulesInitializer : public CoreInitializer {
void CloneSessionStorage(
Page* clone_from_page,
const SessionStorageNamespaceId& clone_to_namespace) override;
+ void EvictSessionStorageCachedData(Page*) override;
void DidChangeManifest(LocalFrame&) override;
void NotifyOrientationChanged(LocalFrame&) override;
- void DidUpdateScreens(LocalFrame&, const ScreenInfos&) override;
+ void DidUpdateScreens(LocalFrame&, const display::ScreenInfos&) override;
+ void SetLocalStorageArea(LocalFrame& frame,
+ mojo::PendingRemote<mojom::blink::StorageArea>
+ local_storage_area) override;
+ void SetSessionStorageArea(LocalFrame& frame,
+ mojo::PendingRemote<mojom::blink::StorageArea>
+ session_storage_area) override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/native_io/idls.gni b/chromium/third_party/blink/renderer/modules/native_io/idls.gni
deleted file mode 100644
index 386ec2c36a5..00000000000
--- a/chromium/third_party/blink/renderer/modules/native_io/idls.gni
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "native_io_file.idl",
- "native_io_file_manager.idl",
- "native_io_file_sync.idl",
-]
-
-modules_dictionary_idl_files = [
- "native_io_read_result.idl",
- "native_io_write_result.idl",
-]
-
-modules_dependency_idl_files = [
- "window_native_io.idl",
- "worker_global_scope_native_io.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/idls.gni b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/idls.gni
deleted file mode 100644
index 08fc1d447df..00000000000
--- a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "navigator_content_utils.idl" ]
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 e5c03480e9a..de6e487e98b 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,9 +26,9 @@
#include "third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h"
-#include "base/stl_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/common/custom_handlers/protocol_handler_utils.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/common/security/protocol_handler_security_level.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.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/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -60,7 +61,7 @@ static bool VerifyCustomHandlerURLSecurity(
bool has_valid_scheme =
full_url.ProtocolIsInHTTPFamily() ||
(security_level == ProtocolHandlerSecurityLevel::kExtensionFeatures &&
- full_url.ProtocolIs("chrome-extension"));
+ CommonSchemeRegistry::IsExtensionScheme(full_url.Protocol().Ascii()));
if (!has_valid_scheme || !network::IsUrlPotentiallyTrustworthy(full_url)) {
error_message = "The scheme of the url provided must be HTTP(S).";
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 763ad3d1d3d..6ec6f9c42fb 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,6 +4,7 @@
#include "third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
diff --git a/chromium/third_party/blink/renderer/modules/netinfo/OWNERS b/chromium/third_party/blink/renderer/modules/netinfo/OWNERS
index 3498144a1e9..0b9706fa37c 100644
--- a/chromium/third_party/blink/renderer/modules/netinfo/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/netinfo/OWNERS
@@ -1,2 +1 @@
-jkarlin@chromium.org
tbansal@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/netinfo/idls.gni b/chromium/third_party/blink/renderer/modules/netinfo/idls.gni
deleted file mode 100644
index 471ef7bcd00..00000000000
--- a/chromium/third_party/blink/renderer/modules/netinfo/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "network_information.idl" ]
-
-modules_dependency_idl_files = [
- "navigator_network_information.idl",
- "worker_navigator_network_information.idl",
-]
-
-modules_testing_dependency_idl_files = [ "testing/internals_net_info.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/nfc/idls.gni b/chromium/third_party/blink/renderer/modules/nfc/idls.gni
deleted file mode 100644
index 87158dc6a63..00000000000
--- a/chromium/third_party/blink/renderer/modules/nfc/idls.gni
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "ndef_message.idl",
- "ndef_record.idl",
- "ndef_reader.idl",
- "ndef_reading_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "ndef_message_init.idl",
- "ndef_record_init.idl",
- "ndef_reading_event_init.idl",
- "ndef_scan_options.idl",
- "ndef_write_options.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc b/chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc
index a9b78254d39..6d6154d4242 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/nfc/ndef_message.h"
#include "services/device/public/mojom/nfc.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_message_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_record_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_arraybuffer_arraybufferview_ndefmessageinit_string.h"
@@ -42,7 +41,6 @@ NDEFMessage* NDEFMessage::Create(const ExecutionContext* execution_context,
return message;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
NDEFMessage* NDEFMessage::Create(const ExecutionContext* execution_context,
const V8NDEFMessageSource* source,
@@ -100,64 +98,6 @@ NDEFMessage* NDEFMessage::Create(const ExecutionContext* execution_context,
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-NDEFMessage* NDEFMessage::Create(const ExecutionContext* execution_context,
- const NDEFMessageSource& source,
- ExceptionState& exception_state) {
- // https://w3c.github.io/web-nfc/#creating-ndef-message
- if (source.IsString()) {
- NDEFMessage* message = MakeGarbageCollected<NDEFMessage>();
- message->records_.push_back(MakeGarbageCollected<NDEFRecord>(
- execution_context, source.GetAsString()));
- return message;
- }
-
- if (source.IsArrayBuffer()) {
- WTF::Vector<uint8_t> payload_data;
- size_t byte_length = source.GetAsArrayBuffer()->ByteLength();
- if (byte_length > std::numeric_limits<wtf_size_t>::max()) {
- exception_state.ThrowRangeError(
- "Buffer size exceeds maximum heap object size.");
- return nullptr;
- }
- payload_data.Append(
- static_cast<uint8_t*>(source.GetAsArrayBuffer()->Data()),
- static_cast<wtf_size_t>(byte_length));
- NDEFMessage* message = MakeGarbageCollected<NDEFMessage>();
- message->records_.push_back(MakeGarbageCollected<NDEFRecord>(
- String() /* id */, "application/octet-stream",
- std::move(payload_data)));
- return message;
- }
-
- if (source.IsArrayBufferView()) {
- size_t byte_length = source.GetAsArrayBufferView()->byteLength();
- if (byte_length > std::numeric_limits<wtf_size_t>::max()) {
- exception_state.ThrowRangeError(
- "Buffer size exceeds maximum heap object size.");
- return nullptr;
- }
- WTF::Vector<uint8_t> payload_data;
- payload_data.Append(
- static_cast<uint8_t*>(source.GetAsArrayBufferView()->BaseAddress()),
- static_cast<wtf_size_t>(byte_length));
- NDEFMessage* message = MakeGarbageCollected<NDEFMessage>();
- message->records_.push_back(MakeGarbageCollected<NDEFRecord>(
- String() /* id */, "application/octet-stream",
- std::move(payload_data)));
- return message;
- }
-
- if (source.IsNDEFMessageInit()) {
- return Create(execution_context, source.GetAsNDEFMessageInit(),
- exception_state);
- }
-
- NOTREACHED();
- return nullptr;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
NDEFMessage* NDEFMessage::CreateAsPayloadOfSmartPoster(
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_message.h b/chromium/third_party/blink/renderer/modules/nfc/ndef_message.h
index e3c8e7bdfd5..4dcfeccb23c 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_message.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_message.h
@@ -17,9 +17,6 @@ class ExceptionState;
class ExecutionContext;
class NDEFMessageInit;
class NDEFRecord;
-class StringOrArrayBufferOrArrayBufferViewOrNDEFMessageInit;
-
-using NDEFMessageSource = StringOrArrayBufferOrArrayBufferViewOrNDEFMessageInit;
class MODULES_EXPORT NDEFMessage final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -31,15 +28,9 @@ class MODULES_EXPORT NDEFMessage final : public ScriptWrappable {
const NDEFMessageInit*,
ExceptionState&,
bool is_embedded = false);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static NDEFMessage* Create(const ExecutionContext* execution_context,
const V8NDEFMessageSource* source,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static NDEFMessage* Create(const ExecutionContext*,
- const NDEFMessageSource&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static NDEFMessage* CreateAsPayloadOfSmartPoster(const ExecutionContext*,
const NDEFMessageInit*,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.cc b/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.cc
index 110a3a7bb96..02c745994e6 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.cc
@@ -6,7 +6,6 @@
#include "services/device/public/mojom/nfc.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_scan_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_write_options.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
@@ -215,11 +214,7 @@ void NDEFReader::ReadAbort() {
// https://w3c.github.io/web-nfc/#writing-content
// https://w3c.github.io/web-nfc/#the-write-method
ScriptPromise NDEFReader::write(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8NDEFMessageSource* write_message,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const NDEFMessageSource& write_message,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const NDEFWriteOptions* options,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#security-policies
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.h b/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.h
index 2963cabda9d..e31634f6c23 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_reader.h
@@ -23,9 +23,6 @@ class NDEFScanOptions;
class NDEFWriteOptions;
class NFCProxy;
class ScriptPromiseResolver;
-class StringOrArrayBufferOrArrayBufferViewOrNDEFMessageInit;
-
-using NDEFMessageSource = StringOrArrayBufferOrArrayBufferViewOrNDEFMessageInit;
class MODULES_EXPORT NDEFReader : public EventTargetWithInlineData,
public ActiveScriptWrappable<NDEFReader>,
@@ -54,17 +51,10 @@ class MODULES_EXPORT NDEFReader : public EventTargetWithInlineData,
ExceptionState& exception_state);
// Write NDEFMessageSource asynchronously to NFC tag.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise write(ScriptState* script_state,
const V8NDEFMessageSource* write_message,
const NDEFWriteOptions* options,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise write(ScriptState* script_state,
- const NDEFMessageSource& write_message,
- const NDEFWriteOptions* options,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc
index 1c3bda90e84..c526a87e3ac 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc
@@ -5,14 +5,13 @@
#include "third_party/blink/renderer/modules/nfc/ndef_record.h"
#include "services/device/public/mojom/nfc.mojom-blink.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/modules/v8/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_record_init.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_arraybuffer_arraybufferview_ndefmessageinit_string.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/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_piece.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
#include "third_party/blink/renderer/modules/nfc/ndef_message.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -23,9 +22,6 @@
namespace blink {
-using NDEFRecordDataSource =
- StringOrArrayBufferOrArrayBufferViewOrNDEFMessageInit;
-
namespace {
WTF::Vector<uint8_t> GetUTF8DataFromString(const String& string) {
@@ -35,37 +31,27 @@ WTF::Vector<uint8_t> GetUTF8DataFromString(const String& string) {
return data;
}
-bool IsBufferSource(const NDEFRecordDataSource& data) {
- return data.IsArrayBuffer() || data.IsArrayBufferView();
-}
-
-bool GetBytesOfBufferSource(const NDEFRecordDataSource& buffer_source,
+bool GetBytesOfBufferSource(const V8NDEFRecordDataSource* buffer_source,
WTF::Vector<uint8_t>* target,
ExceptionState& exception_state) {
- DCHECK(IsBufferSource(buffer_source));
- uint8_t* data;
- size_t data_length;
- if (buffer_source.IsArrayBuffer()) {
- DOMArrayBuffer* array_buffer = buffer_source.GetAsArrayBuffer();
- data = reinterpret_cast<uint8_t*>(array_buffer->Data());
- data_length = array_buffer->ByteLength();
- } else if (buffer_source.IsArrayBufferView()) {
- const DOMArrayBufferView* array_buffer_view =
- buffer_source.GetAsArrayBufferView().Get();
- data = reinterpret_cast<uint8_t*>(array_buffer_view->BaseAddress());
- data_length = array_buffer_view->byteLength();
+ DCHECK(buffer_source->IsV8BufferSource());
+ DOMArrayPiece array_piece;
+ if (buffer_source->IsArrayBuffer()) {
+ array_piece = DOMArrayPiece(buffer_source->GetAsArrayBuffer());
+ } else if (buffer_source->IsArrayBufferView()) {
+ array_piece = DOMArrayPiece(buffer_source->GetAsArrayBufferView().Get());
} else {
NOTREACHED();
- return false;
+ return true; // true to be consistent with `exception_state`.
}
wtf_size_t checked_length;
- if (!base::CheckedNumeric<wtf_size_t>(data_length)
+ if (!base::CheckedNumeric<wtf_size_t>(array_piece.ByteLength())
.AssignIfValid(&checked_length)) {
exception_state.ThrowRangeError(
"The provided buffer source exceeds the maximum supported length");
return false;
}
- target->Append(data, checked_length);
+ target->Append(array_piece.Bytes(), checked_length);
return true;
}
@@ -152,8 +138,10 @@ static NDEFRecord* CreateTextRecord(const ExecutionContext* execution_context,
const NDEFRecordInit& record,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-string-to-ndef
- if (!record.hasData() ||
- !(record.data().IsString() || IsBufferSource(record.data()))) {
+ if (
+ !record.hasData() ||
+ !(record.data()->IsString() || record.data()->IsV8BufferSource())
+ ) {
exception_state.ThrowTypeError(
"The data for 'text' NDEFRecords must be a String or a BufferSource.");
return nullptr;
@@ -176,31 +164,36 @@ static NDEFRecord* CreateTextRecord(const ExecutionContext* execution_context,
return nullptr;
}
- auto& data = record.data();
- // TODO(crbug.com/1070871): Use encodingOr("utf-8").
- String encoding_label = record.hasEncoding() ? record.encoding() : "utf-8";
+ const auto* data = record.data();
+ const String& encoding_label = record.getEncodingOr("utf-8");
WTF::Vector<uint8_t> bytes;
- if (data.IsString()) {
- if (encoding_label != "utf-8") {
- exception_state.ThrowTypeError(
- "A DOMString data source is always encoded as \"utf-8\" so other "
- "encodings are not allowed.");
- return nullptr;
- }
- StringUTF8Adaptor utf8_string(data.GetAsString());
- bytes.Append(utf8_string.data(), utf8_string.size());
- } else {
- DCHECK(IsBufferSource(data));
- if (encoding_label != "utf-8" && encoding_label != "utf-16" &&
- encoding_label != "utf-16be" && encoding_label != "utf-16le") {
- exception_state.ThrowTypeError(
- "Encoding must be either \"utf-8\", \"utf-16\", \"utf-16be\", or "
- "\"utf-16le\".");
- return nullptr;
- }
- if (!GetBytesOfBufferSource(data, &bytes, exception_state)) {
- return nullptr;
- }
+ switch (data->GetContentType()) {
+ case V8NDEFRecordDataSource::ContentType::kArrayBuffer:
+ case V8NDEFRecordDataSource::ContentType::kArrayBufferView:
+ if (encoding_label != "utf-8" && encoding_label != "utf-16" &&
+ encoding_label != "utf-16be" && encoding_label != "utf-16le") {
+ exception_state.ThrowTypeError(
+ "Encoding must be either \"utf-8\", \"utf-16\", \"utf-16be\", or "
+ "\"utf-16le\".");
+ return nullptr;
+ }
+ if (!GetBytesOfBufferSource(data, &bytes, exception_state)) {
+ return nullptr;
+ }
+ break;
+ case V8NDEFRecordDataSource::ContentType::kNDEFMessageInit:
+ NOTREACHED();
+ break;
+ case V8NDEFRecordDataSource::ContentType::kString:
+ if (encoding_label != "utf-8") {
+ exception_state.ThrowTypeError(
+ "A DOMString data source is always encoded as \"utf-8\" so other "
+ "encodings are not allowed.");
+ return nullptr;
+ }
+ StringUTF8Adaptor utf8_string(data->GetAsString());
+ bytes.Append(utf8_string.data(), utf8_string.size());
+ break;
}
return MakeGarbageCollected<NDEFRecord>(id, encoding_label, language,
@@ -212,14 +205,16 @@ static NDEFRecord* CreateUrlRecord(const String& id,
const NDEFRecordInit& record,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-url-to-ndef
- if (!record.hasData() || !record.data().IsString()) {
+ if (
+ !record.hasData() || !record.data()->IsString()
+ ) {
exception_state.ThrowTypeError(
"The data for url NDEFRecord must be a String.");
return nullptr;
}
// No need to check mediaType according to the spec.
- String url = record.data().GetAsString();
+ const String& url = record.data()->GetAsString();
if (!KURL(NullURL(), url).IsValid()) {
exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Cannot parse data for url record.");
@@ -235,7 +230,9 @@ static NDEFRecord* CreateMimeRecord(const String& id,
const NDEFRecordInit& record,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-binary-data-to-ndef
- if (!record.hasData() || !IsBufferSource(record.data())) {
+ if (
+ !record.hasData() || !record.data()->IsV8BufferSource()
+ ) {
exception_state.ThrowTypeError(
"The data for 'mime' NDEFRecord must be a BufferSource.");
return nullptr;
@@ -260,7 +257,9 @@ static NDEFRecord* CreateMimeRecord(const String& id,
static NDEFRecord* CreateUnknownRecord(const String& id,
const NDEFRecordInit& record,
ExceptionState& exception_state) {
- if (!record.hasData() || !IsBufferSource(record.data())) {
+ if (
+ !record.hasData() || !record.data()->IsV8BufferSource()
+ ) {
exception_state.ThrowTypeError(
"The data for 'unknown' NDEFRecord must be a BufferSource.");
return nullptr;
@@ -282,14 +281,17 @@ static NDEFRecord* CreateSmartPosterRecord(
const NDEFRecordInit& record,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#dfn-map-smart-poster-to-ndef
- if (!record.hasData() || !record.data().IsNDEFMessageInit()) {
+ if (
+ !record.hasData() || !record.data()->IsNDEFMessageInit()
+ ) {
exception_state.ThrowTypeError(
"The data for 'smart-poster' NDEFRecord must be an NDEFMessageInit.");
return nullptr;
}
NDEFMessage* payload_message = NDEFMessage::CreateAsPayloadOfSmartPoster(
- execution_context, record.data().GetAsNDEFMessageInit(), exception_state);
+ execution_context, record.data()->GetAsNDEFMessageInit(),
+ exception_state);
if (exception_state.HadException())
return nullptr;
DCHECK(payload_message);
@@ -307,24 +309,32 @@ static NDEFRecord* CreateExternalRecord(
const String& record_type = record.recordType();
// https://w3c.github.io/web-nfc/#dfn-map-external-data-to-ndef
- if (record.hasData() && IsBufferSource(record.data())) {
- WTF::Vector<uint8_t> bytes;
- if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
- return nullptr;
+ if (record.hasData()) {
+ switch (record.data()->GetContentType()) {
+ case V8NDEFRecordDataSource::ContentType::kArrayBuffer:
+ case V8NDEFRecordDataSource::ContentType::kArrayBufferView: {
+ Vector<uint8_t> bytes;
+ if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
+ return nullptr;
+ }
+ return MakeGarbageCollected<NDEFRecord>(
+ device::mojom::blink::NDEFRecordTypeCategory::kExternal,
+ record_type, id, bytes);
+ }
+ case V8NDEFRecordDataSource::ContentType::kNDEFMessageInit: {
+ NDEFMessage* payload_message = NDEFMessage::Create(
+ execution_context, record.data()->GetAsNDEFMessageInit(),
+ exception_state, /*is_embedded=*/true);
+ if (exception_state.HadException())
+ return nullptr;
+ DCHECK(payload_message);
+ return MakeGarbageCollected<NDEFRecord>(
+ device::mojom::blink::NDEFRecordTypeCategory::kExternal,
+ record_type, id, payload_message);
+ }
+ case V8NDEFRecordDataSource::ContentType::kString:
+ break;
}
- return MakeGarbageCollected<NDEFRecord>(
- device::mojom::blink::NDEFRecordTypeCategory::kExternal, record_type,
- id, bytes);
- } else if (record.hasData() && record.data().IsNDEFMessageInit()) {
- NDEFMessage* payload_message = NDEFMessage::Create(
- execution_context, record.data().GetAsNDEFMessageInit(),
- exception_state, /*is_embedded=*/true);
- if (exception_state.HadException())
- return nullptr;
- DCHECK(payload_message);
- return MakeGarbageCollected<NDEFRecord>(
- device::mojom::blink::NDEFRecordTypeCategory::kExternal, record_type,
- id, payload_message);
}
exception_state.ThrowTypeError(
@@ -340,24 +350,32 @@ static NDEFRecord* CreateLocalRecord(const ExecutionContext* execution_context,
const String& record_type = record.recordType();
// https://w3c.github.io/web-nfc/#dfn-map-local-type-to-ndef
- if (record.hasData() && IsBufferSource(record.data())) {
- WTF::Vector<uint8_t> bytes;
- if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
- return nullptr;
+ if (record.hasData()) {
+ switch (record.data()->GetContentType()) {
+ case V8NDEFMessageSource::ContentType::kArrayBuffer:
+ case V8NDEFMessageSource::ContentType::kArrayBufferView: {
+ Vector<uint8_t> bytes;
+ if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
+ return nullptr;
+ }
+ return MakeGarbageCollected<NDEFRecord>(
+ device::mojom::blink::NDEFRecordTypeCategory::kLocal, record_type,
+ id, bytes);
+ }
+ case V8NDEFMessageSource::ContentType::kNDEFMessageInit: {
+ NDEFMessage* payload_message = NDEFMessage::Create(
+ execution_context, record.data()->GetAsNDEFMessageInit(),
+ exception_state, /*is_embedded=*/true);
+ if (exception_state.HadException())
+ return nullptr;
+ DCHECK(payload_message);
+ return MakeGarbageCollected<NDEFRecord>(
+ device::mojom::blink::NDEFRecordTypeCategory::kLocal, record_type,
+ id, payload_message);
+ }
+ case V8NDEFMessageSource::ContentType::kString:
+ break;
}
- return MakeGarbageCollected<NDEFRecord>(
- device::mojom::blink::NDEFRecordTypeCategory::kLocal, record_type, id,
- bytes);
- } else if (record.hasData() && record.data().IsNDEFMessageInit()) {
- NDEFMessage* payload_message = NDEFMessage::Create(
- execution_context, record.data().GetAsNDEFMessageInit(),
- exception_state, /*is_embedded=*/true);
- if (exception_state.HadException())
- return nullptr;
- DCHECK(payload_message);
- return MakeGarbageCollected<NDEFRecord>(
- device::mojom::blink::NDEFRecordTypeCategory::kLocal, record_type, id,
- payload_message);
}
exception_state.ThrowTypeError(
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.h b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.h
index 9aa5de8c522..0d11d3fe4ef 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NFC_NDEF_RECORD_H_
#include "services/device/public/mojom/nfc.mojom-blink-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.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"
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc
index cbcd1ec1ac6..0fbe495855a 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc
@@ -117,7 +117,7 @@ class FakeNfcService : public device::mojom::blink::NFC {
std::move(callback).Run(nullptr);
}
void CancelWatch(uint32_t id) override {
- size_t index = watchIDs_.Find(id);
+ wtf_size_t index = watchIDs_.Find(id);
if (index != kNotFound)
watchIDs_.EraseAt(index);
}
diff --git a/chromium/third_party/blink/renderer/modules/notifications/idls.gni b/chromium/third_party/blink/renderer/modules/notifications/idls.gni
deleted file mode 100644
index c357dd01d65..00000000000
--- a/chromium/third_party/blink/renderer/modules/notifications/idls.gni
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "notification.idl",
- "notification_event.idl",
- "timestamp_trigger.idl",
-]
-
-modules_dictionary_idl_files = [
- "get_notification_options.idl",
- "notification_action.idl",
- "notification_event_init.idl",
- "notification_options.idl",
-]
-
-modules_dependency_idl_files = [
- "service_worker_global_scope_notifications.idl",
- "service_worker_registration_notifications.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification.cc b/chromium/third_party/blink/renderer/modules/notifications/notification.cc
index 6280621c47c..0372897ebe4 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification.cc
@@ -36,6 +36,7 @@
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/notifications/notification_constants.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.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"
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 b5680a964ca..7f8f6691bb7 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
@@ -4,10 +4,11 @@
#include "third_party/blink/renderer/modules/notifications/notification_data.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/notifications/notification_constants.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_unsignedlong_unsignedlongsequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_notification_action.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_notification_options.h"
#include "third_party/blink/renderer/modules/notifications/notification.h"
@@ -57,8 +58,9 @@ TEST(NotificationDataTest, ReflectProperties) {
for (size_t i = 0; i < base::size(kNotificationVibration); ++i)
vibration_pattern.push_back(kNotificationVibration[i]);
- UnsignedLongOrUnsignedLongSequence vibration_sequence;
- vibration_sequence.SetUnsignedLongSequence(vibration_pattern);
+ auto* vibration_sequence =
+ MakeGarbageCollected<V8UnionUnsignedLongOrUnsignedLongSequence>(
+ vibration_pattern);
HeapVector<Member<NotificationAction>> actions;
for (size_t i = 0; i < Notification::maxActions(); ++i) {
@@ -144,8 +146,9 @@ TEST(NotificationDataTest, SilentNotificationWithVibration) {
for (size_t i = 0; i < base::size(kNotificationVibration); ++i)
vibration_pattern.push_back(kNotificationVibration[i]);
- UnsignedLongOrUnsignedLongSequence vibration_sequence;
- vibration_sequence.SetUnsignedLongSequence(vibration_pattern);
+ auto* vibration_sequence =
+ MakeGarbageCollected<V8UnionUnsignedLongOrUnsignedLongSequence>(
+ std::move(vibration_pattern));
NotificationOptions* options =
NotificationOptions::Create(scope.GetIsolate());
@@ -243,8 +246,9 @@ TEST(NotificationDataTest, VibrationNormalization) {
for (size_t i = 0; i < base::size(kNotificationVibrationUnnormalized); ++i)
unnormalized_pattern.push_back(kNotificationVibrationUnnormalized[i]);
- UnsignedLongOrUnsignedLongSequence vibration_sequence;
- vibration_sequence.SetUnsignedLongSequence(unnormalized_pattern);
+ auto* vibration_sequence =
+ MakeGarbageCollected<V8UnionUnsignedLongOrUnsignedLongSequence>(
+ unnormalized_pattern);
NotificationOptions* options =
NotificationOptions::Create(scope.GetIsolate());
diff --git a/chromium/third_party/blink/renderer/modules/payments/OWNERS b/chromium/third_party/blink/renderer/modules/payments/OWNERS
index 88a70bcb216..d84162f7e9d 100644
--- a/chromium/third_party/blink/renderer/modules/payments/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/payments/OWNERS
@@ -1,11 +1,6 @@
-
file://components/payments/OWNERS
jinho.bang@samsung.com
-mek@chromium.org
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
-
-# Emeritus
-mathp@chromium.org
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 f562bcf08d1..e83cb122bb2 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
@@ -33,12 +33,9 @@ void AbortPaymentRespondWithObserver::OnResponseRejected(
void AbortPaymentRespondWithObserver::OnResponseFulfilled(
ScriptState* script_state,
const ScriptValue& value,
- ExceptionState::ContextType context_type,
- const char* interface_name,
- const char* property_name) {
+ const ExceptionContext& exception_context) {
DCHECK(GetExecutionContext());
- ExceptionState exception_state(script_state->GetIsolate(), context_type,
- interface_name, property_name);
+ ExceptionState exception_state(script_state->GetIsolate(), exception_context);
bool response =
ToBoolean(script_state->GetIsolate(), 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 feac2f04a0d..5d5dff52e61 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
@@ -28,9 +28,7 @@ class MODULES_EXPORT AbortPaymentRespondWithObserver final
void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
void OnResponseFulfilled(ScriptState*,
const ScriptValue&,
- ExceptionState::ContextType,
- const char* interface_name,
- const char* property_name) override;
+ const ExceptionContext&) override;
void OnNoResponse() override;
void Trace(Visitor*) const override;
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 042ba904134..62ac2ee2794 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
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/payments/basic_card_helper.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_basic_card_request.h"
#include "third_party/blink/renderer/modules/payments/payment_request.h"
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 6204aa137e9..66bcb15ee22 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
@@ -44,12 +44,9 @@ void CanMakePaymentRespondWithObserver::OnResponseRejected(
void CanMakePaymentRespondWithObserver::OnResponseFulfilled(
ScriptState* script_state,
const ScriptValue& value,
- ExceptionState::ContextType context_type,
- const char* interface_name,
- const char* property_name) {
+ const ExceptionContext& exception_context) {
DCHECK(GetExecutionContext());
- ExceptionState exception_state(script_state->GetIsolate(), context_type,
- interface_name, property_name);
+ ExceptionState exception_state(script_state->GetIsolate(), exception_context);
if (is_minimal_ui_) {
OnResponseFulfilledForMinimalUI(script_state, value, exception_state);
return;
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 54147ed8d20..ab602984345 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
@@ -30,9 +30,7 @@ class MODULES_EXPORT CanMakePaymentRespondWithObserver final
void OnResponseRejected(mojom::blink::ServiceWorkerResponseError) override;
void OnResponseFulfilled(ScriptState*,
const ScriptValue&,
- ExceptionState::ContextType,
- const char* interface_name,
- const char* property_name) override;
+ const ExceptionContext&) override;
void OnNoResponse() override;
void Trace(Visitor*) const override;
diff --git a/chromium/third_party/blink/renderer/modules/payments/goods/idls.gni b/chromium/third_party/blink/renderer/modules/payments/goods/idls.gni
deleted file mode 100644
index d9ad894da9e..00000000000
--- a/chromium/third_party/blink/renderer/modules/payments/goods/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "digital_goods_service.idl" ]
-
-modules_dictionary_idl_files = [
- "item_details.idl",
- "purchase_details.idl",
-]
-
-modules_dependency_idl_files = [ "dom_window_digital_goods.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/payments/idls.gni b/chromium/third_party/blink/renderer/modules/payments/idls.gni
deleted file mode 100644
index 407fbe42d66..00000000000
--- a/chromium/third_party/blink/renderer/modules/payments/idls.gni
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "abort_payment_event.idl",
- "can_make_payment_event.idl",
- "merchant_validation_event.idl",
- "payment_address.idl",
- "payment_instruments.idl",
- "payment_manager.idl",
- "payment_method_change_event.idl",
- "payment_request.idl",
- "payment_request_event.idl",
- "payment_request_update_event.idl",
- "payment_response.idl",
-]
-
-modules_dictionary_idl_files = [
- "address_errors.idl",
- "address_init.idl",
- "android_pay_method_data.idl",
- "basic_card_request.idl",
- "secure_payment_confirmation_request.idl",
- "can_make_payment_event_init.idl",
- "can_make_payment_response.idl",
- "image_object.idl",
- "merchant_validation_event_init.idl",
- "payer_errors.idl",
- "payment_currency_amount.idl",
- "payment_details_base.idl",
- "payment_details_init.idl",
- "payment_details_modifier.idl",
- "payment_details_update.idl",
- "payment_handler_response.idl",
- "payment_instrument.idl",
- "payment_item.idl",
- "payment_method_change_event_init.idl",
- "payment_method_data.idl",
- "payment_options.idl",
- "payment_request_details_update.idl",
- "payment_request_event_init.idl",
- "payment_request_update_event_init.idl",
- "payment_shipping_option.idl",
- "payment_validation_errors.idl",
-]
-
-modules_dependency_idl_files = [
- "html_iframe_element_payments.idl",
- "payment_app_service_worker_global_scope.idl",
- "payment_app_service_worker_registration.idl",
-]
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 a7c77c0673a..6f9966de58f 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
@@ -64,8 +64,10 @@ PaymentMethodData* ToPaymentMethodData(
DCHECK(data);
PaymentMethodData* method_data = PaymentMethodData::Create();
method_data->setSupportedMethod(data->supported_method);
- method_data->setData(
- StringDataToScriptValue(script_state, data->stringified_data));
+ ScriptValue v8_data =
+ StringDataToScriptValue(script_state, data->stringified_data);
+ if (!v8_data.IsEmpty())
+ method_data->setData(std::move(v8_data));
return method_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 8d0931ccb69..6ac437065f3 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "build/build_config.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
@@ -1554,6 +1553,10 @@ void PaymentRequest::OnError(PaymentErrorReason error,
not_supported_for_invalid_origin_or_ssl_error_ = error_message;
break;
+ case PaymentErrorReason::NOT_ALLOWED_ERROR:
+ exception_code = DOMExceptionCode::kNotAllowedError;
+ break;
+
case PaymentErrorReason::UNKNOWN:
break;
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
index e0789ff4cd4..d0e91096ad5 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
@@ -10,6 +10,7 @@
#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/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
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 83a8c9b0241..f9e51aeede3 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
@@ -50,12 +50,9 @@ void PaymentRequestRespondWithObserver::OnResponseRejected(
void PaymentRequestRespondWithObserver::OnResponseFulfilled(
ScriptState* script_state,
const ScriptValue& value,
- ExceptionState::ContextType context_type,
- const char* interface_name,
- const char* property_name) {
+ const ExceptionContext& exception_context) {
DCHECK(GetExecutionContext());
- ExceptionState exception_state(script_state->GetIsolate(), context_type,
- interface_name, property_name);
+ ExceptionState exception_state(script_state->GetIsolate(), exception_context);
PaymentHandlerResponse* response =
NativeValueTraits<PaymentHandlerResponse>::NativeValue(
script_state->GetIsolate(), value.V8Value(), exception_state);
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 4b66f94d677..a57245d45c1 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
@@ -34,9 +34,7 @@ class MODULES_EXPORT PaymentRequestRespondWithObserver final
void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
void OnResponseFulfilled(ScriptState*,
const ScriptValue&,
- ExceptionState::ContextType,
- const char* interface_name,
- const char* property_name) override;
+ const ExceptionContext&) override;
void OnNoResponse() override;
void Trace(Visitor*) const override;
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 0d4f24db1b6..9c8cf4003a0 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
@@ -4,17 +4,66 @@
#include "third_party/blink/renderer/modules/payments/payment_response.h"
+#include <utility>
+
#include "base/logging.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/bindings/modules/v8/v8_payment_validation_errors.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/credentialmanager/authenticator_assertion_response.h"
+#include "third_party/blink/renderer/modules/credentialmanager/public_key_credential.h"
#include "third_party/blink/renderer/modules/payments/payment_address.h"
#include "third_party/blink/renderer/modules/payments/payment_state_resolver.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
+namespace {
+
+using payments::mojom::blink::SecurePaymentConfirmationResponsePtr;
+
+v8::Local<v8::Value> BuildDetails(
+ ScriptState* script_state,
+ const String& json,
+ SecurePaymentConfirmationResponsePtr secure_payment_confirmation) {
+ if (secure_payment_confirmation) {
+ const auto& info = secure_payment_confirmation->credential_info;
+ auto* authenticator_response =
+ MakeGarbageCollected<AuthenticatorAssertionResponse>(
+ std::move(info->client_data_json),
+ std::move(info->authenticator_data),
+ std::move(secure_payment_confirmation->signature),
+ secure_payment_confirmation->user_handle);
+
+ auto* result = MakeGarbageCollected<PublicKeyCredential>(
+ secure_payment_confirmation->credential_info->id,
+ DOMArrayBuffer::Create(static_cast<const void*>(info->raw_id.data()),
+ info->raw_id.size()),
+ authenticator_response,
+ AuthenticationExtensionsClientOutputs::Create());
+ return result->Wrap(script_state).ToLocalChecked();
+ }
+
+ if (json.IsEmpty()) {
+ return V8ObjectBuilder(script_state).V8Value();
+ }
+
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kConstructionContext,
+ "PaymentResponse");
+ v8::Local<v8::Value> parsed_value =
+ FromJSONString(script_state->GetIsolate(), script_state->GetContext(),
+ json, exception_state);
+ if (exception_state.HadException()) {
+ exception_state.ClearException();
+ return V8ObjectBuilder(script_state).V8Value();
+ }
+
+ return parsed_value;
+}
+
+} // namespace
PaymentResponse::PaymentResponse(
ScriptState* script_state,
@@ -32,7 +81,10 @@ PaymentResponse::PaymentResponse(
payer_phone_(response->payer->phone),
payment_state_resolver_(payment_state_resolver) {
DCHECK(payment_state_resolver_);
- UpdateDetailsFromJSON(script_state, response->stringified_details);
+ ScriptState::Scope scope(script_state);
+ details_.Set(script_state->GetIsolate(),
+ BuildDetails(script_state, response->stringified_details,
+ std::move(response->secure_payment_confirmation)));
}
PaymentResponse::~PaymentResponse() = default;
@@ -49,7 +101,10 @@ void PaymentResponse::Update(
payer_name_ = response->payer->name;
payer_email_ = response->payer->email;
payer_phone_ = response->payer->phone;
- UpdateDetailsFromJSON(script_state, response->stringified_details);
+ ScriptState::Scope scope(script_state);
+ details_.Set(script_state->GetIsolate(),
+ BuildDetails(script_state, response->stringified_details,
+ std::move(response->secure_payment_confirmation)));
}
void PaymentResponse::UpdatePayerDetail(
@@ -60,30 +115,6 @@ void PaymentResponse::UpdatePayerDetail(
payer_phone_ = detail->phone;
}
-void PaymentResponse::UpdateDetailsFromJSON(ScriptState* script_state,
- const String& json) {
- ScriptState::Scope scope(script_state);
- if (json.IsEmpty()) {
- details_.Set(script_state->GetIsolate(),
- V8ObjectBuilder(script_state).V8Value());
- return;
- }
-
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kConstructionContext,
- "PaymentResponse");
- v8::Local<v8::Value> parsed_value =
- FromJSONString(script_state->GetIsolate(), script_state->GetContext(),
- json, exception_state);
- if (exception_state.HadException()) {
- exception_state.ClearException();
- details_.Set(script_state->GetIsolate(),
- V8ObjectBuilder(script_state).V8Value());
- return;
- }
- details_.Set(script_state->GetIsolate(), parsed_value);
-}
-
ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const {
V8ObjectBuilder result(script_state);
result.AddString("requestId", requestId());
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 4eb1ebef3ac..1af46c3264b 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.h
@@ -45,7 +45,6 @@ class MODULES_EXPORT PaymentResponse final
payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address);
void UpdatePayerDetail(payments::mojom::blink::PayerDetailPtr);
- void UpdateDetailsFromJSON(ScriptState* script_state, const String& json);
ScriptValue toJSONForBinding(ScriptState*) const;
diff --git a/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc b/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
index 1ed7cf0b196..3db0f198e13 100644
--- a/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h"
#include "third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -48,6 +49,25 @@ SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData(
return nullptr;
}
+ if (request->instrument()->displayName().IsEmpty()) {
+ exception_state.ThrowTypeError(
+ "The \"secure-payment-confirmation\" method requires a non-empty "
+ "\"instrument.displayName\" field.");
+ return nullptr;
+ }
+ if (request->instrument()->icon().IsEmpty()) {
+ exception_state.ThrowTypeError(
+ "The \"secure-payment-confirmation\" method requires a non-empty "
+ "\"instrument.icon\" field.");
+ return nullptr;
+ }
+ if (!KURL(request->instrument()->icon()).IsValid()) {
+ exception_state.ThrowTypeError(
+ "The \"secure-payment-confirmation\" method requires a valid URL in "
+ "the \"instrument.icon\" field.");
+ return nullptr;
+ }
+
return mojo::ConvertTo<
payments::mojom::blink::SecurePaymentConfirmationRequestPtr>(request);
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl b/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
index 1c19484d809..6985119a5ba 100644
--- a/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/rsolomakhin/secure-payment-confirmation#authenticating-a-payment
+// https://github.com/w3c/secure-payment-confirmation
enum SecurePaymentConfirmationAction {
"authenticate",
@@ -11,9 +11,12 @@ enum SecurePaymentConfirmationAction {
dictionary SecurePaymentConfirmationRequest {
SecurePaymentConfirmationAction action;
required FrozenArray<BufferSource> credentialIds;
+
// Opaque data about the current transaction provided by the issuer. As the
- // issuer is the RP of the credential, `networkData` provides protection
+ // issuer is the RP of the credential, `challenge` provides protection
// against replay attacks.
- required BufferSource networkData;
+ required BufferSource challenge;
+
+ required PaymentCredentialInstrument instrument;
unsigned long timeout;
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc b/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
index 8056093fd67..15fd339041b 100644
--- a/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
@@ -4,23 +4,28 @@
#include "third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h"
-#include <stdint.h>
+#include <cstdint>
#include "base/time/time.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h"
#include "third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace mojo {
template <>
struct TypeConverter<Vector<Vector<uint8_t>>,
- blink::HeapVector<blink::ArrayBufferOrArrayBufferView>> {
+ blink::HeapVector<blink::Member<
+ blink::V8UnionArrayBufferOrArrayBufferView>>> {
static Vector<Vector<uint8_t>> Convert(
- const blink::HeapVector<blink::ArrayBufferOrArrayBufferView>& input) {
+ const blink::HeapVector<
+ blink::Member<blink::V8UnionArrayBufferOrArrayBufferView>>& input) {
Vector<Vector<uint8_t>> result;
for (const auto& item : input) {
- result.push_back(mojo::ConvertTo<Vector<uint8_t>>(item));
+ result.push_back(mojo::ConvertTo<Vector<uint8_t>>(item.Get()));
}
return result;
}
@@ -33,13 +38,17 @@ TypeConverter<payments::mojom::blink::SecurePaymentConfirmationRequestPtr,
auto output = payments::mojom::blink::SecurePaymentConfirmationRequest::New();
output->credential_ids =
mojo::ConvertTo<Vector<Vector<uint8_t>>>(input->credentialIds());
- output->network_data = mojo::ConvertTo<Vector<uint8_t>>(input->networkData());
+ output->challenge = mojo::ConvertTo<Vector<uint8_t>>(input->challenge());
// If a timeout was not specified in JavaScript, then pass a null `timeout`
// through mojo IPC, so the browser can set a default (e.g., 3 minutes).
if (input->hasTimeout())
output->timeout = base::TimeDelta::FromMilliseconds(input->timeout());
+ output->instrument = payments::mojom::blink::PaymentCredentialInstrument::New(
+ input->instrument()->displayName(),
+ blink::KURL(input->instrument()->icon()));
+
return output;
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
index 48f247fe314..b91dafbb3c0 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -54,6 +54,10 @@ blink_modules_sources("peerconnection") {
"rtc_encoded_audio_frame.h",
"rtc_encoded_audio_frame_delegate.cc",
"rtc_encoded_audio_frame_delegate.h",
+ "rtc_encoded_audio_receiver_sink_optimizer.cc",
+ "rtc_encoded_audio_receiver_sink_optimizer.h",
+ "rtc_encoded_audio_receiver_source_optimizer.cc",
+ "rtc_encoded_audio_receiver_source_optimizer.h",
"rtc_encoded_audio_underlying_sink.cc",
"rtc_encoded_audio_underlying_sink.h",
"rtc_encoded_audio_underlying_source.cc",
@@ -144,6 +148,7 @@ blink_modules_sources("peerconnection") {
"//jingle:webrtc_glue",
"//services/metrics/public/cpp:ukm_builders",
"//third_party/abseil-cpp:absl",
+ "//third_party/blink/public/mojom:web_feature_mojo_bindings",
"//third_party/blink/renderer/modules/crypto",
"//third_party/blink/renderer/modules/mediastream",
"//third_party/blink/renderer/modules/webrtc",
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
index 8b5c0ce7d50..83aaed060a3 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
@@ -158,8 +158,9 @@ MediaStreamComponent* FakeRTCRtpReceiverImpl::Track() const {
}
Vector<String> FakeRTCRtpReceiverImpl::StreamIds() const {
- Vector<String> wtf_stream_ids(stream_ids_.size());
- for (size_t i = 0; i < stream_ids_.size(); ++i) {
+ Vector<String> wtf_stream_ids(
+ base::checked_cast<wtf_size_t>(stream_ids_.size()));
+ for (wtf_size_t i = 0; i < wtf_stream_ids.size(); ++i) {
wtf_stream_ids[i] = String::FromUTF8(stream_ids_[i]);
}
return wtf_stream_ids;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/idls.gni b/chromium/third_party/blink/renderer/modules/peerconnection/idls.gni
deleted file mode 100644
index d6b0fb6021d..00000000000
--- a/chromium/third_party/blink/renderer/modules/peerconnection/idls.gni
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "rtc_certificate.idl",
- "rtc_data_channel.idl",
- "rtc_data_channel_event.idl",
- "rtc_dtls_transport.idl",
- "rtc_dtmf_sender.idl",
- "rtc_dtmf_tone_change_event.idl",
- "rtc_encoded_video_frame.idl",
- "rtc_encoded_audio_frame.idl",
- "rtc_error.idl",
- "rtc_error_event.idl",
- "rtc_ice_candidate.idl",
- "rtc_ice_transport.idl",
- "rtc_legacy_stats_report.idl",
- "rtc_peer_connection.idl",
- "rtc_peer_connection_ice_error_event.idl",
- "rtc_peer_connection_ice_event.idl",
- "rtc_rtp_receiver.idl",
- "rtc_rtp_sender.idl",
- "rtc_rtp_transceiver.idl",
- "rtc_sctp_transport.idl",
- "rtc_session_description.idl",
- "rtc_stats_report.idl",
- "rtc_stats_response.idl",
- "rtc_track_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "rtc_answer_options.idl",
- "rtc_configuration.idl",
- "rtc_data_channel_event_init.idl",
- "rtc_data_channel_init.idl",
- "rtc_dtls_fingerprint.idl",
- "rtc_dtmf_tone_change_event_init.idl",
- "rtc_encoded_audio_frame_metadata.idl",
- "rtc_encoded_video_frame_metadata.idl",
- "rtc_error_event_init.idl",
- "rtc_error_init.idl",
- "rtc_ice_candidate_init.idl",
- "rtc_ice_candidate_pair.idl",
- "rtc_ice_gather_options.idl",
- "rtc_ice_parameters.idl",
- "rtc_ice_server.idl",
- "rtc_insertable_streams.idl",
- "rtc_offer_answer_options.idl",
- "rtc_offer_options.idl",
- "rtc_peer_connection_ice_error_event_init.idl",
- "rtc_peer_connection_ice_event_init.idl",
- "rtc_rtcp_parameters.idl",
- "rtc_rtp_capabilities.idl",
- "rtc_rtp_codec_capability.idl",
- "rtc_rtp_codec_parameters.idl",
- "rtc_rtp_coding_parameters.idl",
- "rtc_rtp_contributing_source.idl",
- "rtc_rtp_decoding_parameters.idl",
- "rtc_rtp_encoding_parameters.idl",
- "rtc_rtp_header_extension_capability.idl",
- "rtc_rtp_header_extension_parameters.idl",
- "rtc_rtp_parameters.idl",
- "rtc_rtp_receive_parameters.idl",
- "rtc_rtp_send_parameters.idl",
- "rtc_rtp_synchronization_source.idl",
- "rtc_rtp_transceiver_init.idl",
- "rtc_session_description_init.idl",
- "rtc_track_event_init.idl",
-]
-
-modules_testing_dependency_idl_files = [
- "testing/internals_rtc_certificate.idl",
- "testing/internals_rtc_peer_connection.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
index ce21648c4c2..5c44283eb31 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
@@ -160,7 +160,7 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
incoming_frame.video_frame_buffer();
scoped_refptr<media::VideoFrame> video_frame;
if (buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) {
- video_frame = static_cast<WebRtcVideoFrameAdapterInterface*>(buffer.get())
+ video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get())
->getMediaVideoFrame();
video_frame->set_timestamp(elapsed_timestamp);
} else {
@@ -290,8 +290,10 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::
}
MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<TrackObserver> observer)
- : observer_(std::move(observer)) {
+ : MediaStreamVideoSource(std::move(task_runner)),
+ observer_(std::move(observer)) {
// The callback will be automatically cleared when 'observer_' goes out of
// scope and no further callbacks will occur.
observer_->SetCallback(WTF::BindRepeating(
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h
index c9f27497713..555a5143e97 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h
@@ -25,6 +25,7 @@ class MODULES_EXPORT MediaStreamRemoteVideoSource
: public MediaStreamVideoSource {
public:
explicit MediaStreamRemoteVideoSource(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<TrackObserver> observer);
~MediaStreamRemoteVideoSource() override;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
index af94571e047..4577a834d33 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
@@ -58,7 +58,9 @@ class MediaStreamRemoteVideoSourceUnderTest
public:
explicit MediaStreamRemoteVideoSourceUnderTest(
std::unique_ptr<blink::TrackObserver> observer)
- : MediaStreamRemoteVideoSource(std::move(observer)) {}
+ : MediaStreamRemoteVideoSource(
+ scheduler::GetSingleThreadTaskRunnerForTesting(),
+ std::move(observer)) {}
using MediaStreamRemoteVideoSource::EncodedSinkInterfaceForTesting;
using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
using MediaStreamRemoteVideoSource::StartSourceImpl;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
index 600ec7a578e..0393d76ab23 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
@@ -21,7 +21,6 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
-#include "third_party/webrtc/api/video_track_source_proxy.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc b/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
index c702bfa07f4..b0405d0bcbd 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
@@ -11,11 +11,14 @@
#include <utility>
#include <vector>
+#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/synchronization/waitable_event.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "crypto/openssl_util.h"
#include "jingle/glue/thread_wrapper.h"
@@ -53,10 +56,11 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/webrtc/api/call/call_factory_interface.h"
#include "third_party/webrtc/api/peer_connection_interface.h"
#include "third_party/webrtc/api/rtc_event_log/rtc_event_log_factory.h"
-#include "third_party/webrtc/api/video_track_source_proxy.h"
+#include "third_party/webrtc/api/video_track_source_proxy_factory.h"
#include "third_party/webrtc/media/engine/fake_video_codec_factory.h"
#include "third_party/webrtc/media/engine/multiplex_codec_factory.h"
#include "third_party/webrtc/media/engine/webrtc_media_engine.h"
@@ -66,6 +70,15 @@
#include "third_party/webrtc/rtc_base/ssl_adapter.h"
#include "third_party/webrtc_overrides/task_queue_factory.h"
+namespace WTF {
+template <>
+struct CrossThreadCopier<base::RepeatingCallback<void(base::TimeDelta)>>
+ : public CrossThreadCopierPassThrough<
+ base::RepeatingCallback<void(base::TimeDelta)>> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+} // namespace WTF
+
namespace blink {
namespace {
@@ -100,7 +113,7 @@ bool IsValidPortRange(uint16_t min_port, uint16_t max_port) {
// class.
class ProxyAsyncResolverFactory final : public webrtc::AsyncResolverFactory {
public:
- ProxyAsyncResolverFactory(IpcPacketSocketFactory* ipc_psf)
+ explicit ProxyAsyncResolverFactory(IpcPacketSocketFactory* ipc_psf)
: ipc_psf_(ipc_psf) {
DCHECK(ipc_psf);
}
@@ -149,10 +162,14 @@ class PeerConnectionStaticDeps {
if (!worker_thread_) {
PostCrossThreadTask(
*chrome_worker_thread_->task_runner(), FROM_HERE,
- CrossThreadBindOnce(&PeerConnectionStaticDeps::InitializeOnThread,
- CrossThreadUnretained(this),
- CrossThreadUnretained(&worker_thread_),
- CrossThreadUnretained(&init_worker_event)));
+ CrossThreadBindOnce(
+ &PeerConnectionStaticDeps::InitializeOnThread,
+ CrossThreadUnretained(&worker_thread_),
+ CrossThreadUnretained(&init_worker_event),
+ ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ PeerConnectionStaticDeps::LogTaskLatencyWorker)),
+ ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ PeerConnectionStaticDeps::LogTaskDurationWorker))));
}
return init_worker_event;
}
@@ -161,10 +178,14 @@ class PeerConnectionStaticDeps {
if (!network_thread_) {
PostCrossThreadTask(
*chrome_network_thread_.task_runner(), FROM_HERE,
- CrossThreadBindOnce(&PeerConnectionStaticDeps::InitializeOnThread,
- CrossThreadUnretained(this),
- CrossThreadUnretained(&network_thread_),
- CrossThreadUnretained(&init_network_event)));
+ CrossThreadBindOnce(
+ &PeerConnectionStaticDeps::InitializeOnThread,
+ CrossThreadUnretained(&network_thread_),
+ CrossThreadUnretained(&init_network_event),
+ ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ PeerConnectionStaticDeps::LogTaskLatencyNetwork)),
+ ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ PeerConnectionStaticDeps::LogTaskDurationNetwork))));
}
return init_network_event;
}
@@ -173,10 +194,14 @@ class PeerConnectionStaticDeps {
if (!signaling_thread_) {
PostCrossThreadTask(
*chrome_signaling_thread_.task_runner(), FROM_HERE,
- CrossThreadBindOnce(&PeerConnectionStaticDeps::InitializeOnThread,
- CrossThreadUnretained(this),
- CrossThreadUnretained(&signaling_thread_),
- CrossThreadUnretained(&init_signaling_event)));
+ CrossThreadBindOnce(
+ &PeerConnectionStaticDeps::InitializeOnThread,
+ CrossThreadUnretained(&signaling_thread_),
+ CrossThreadUnretained(&init_signaling_event),
+ ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ PeerConnectionStaticDeps::LogTaskLatencySignaling)),
+ ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ PeerConnectionStaticDeps::LogTaskDurationSignaling))));
}
return init_signaling_event;
}
@@ -192,9 +217,53 @@ class PeerConnectionStaticDeps {
base::Thread& GetChromeNetworkThread() { return chrome_network_thread_; }
private:
- void InitializeOnThread(rtc::Thread** thread, base::WaitableEvent* event) {
+ static void LogTaskLatencyWorker(base::TimeDelta sample) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "WebRTC.PeerConnection.Latency.Worker", sample,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 50);
+ }
+ static void LogTaskDurationWorker(base::TimeDelta sample) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "WebRTC.PeerConnection.Duration.Worker", sample,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 50);
+ }
+ static void LogTaskLatencyNetwork(base::TimeDelta sample) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "WebRTC.PeerConnection.Latency.Network", sample,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 50);
+ }
+ static void LogTaskDurationNetwork(base::TimeDelta sample) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "WebRTC.PeerConnection.Duration.Network", sample,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 50);
+ }
+ static void LogTaskLatencySignaling(base::TimeDelta sample) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "WebRTC.PeerConnection.Latency.Signaling", sample,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 50);
+ }
+ static void LogTaskDurationSignaling(base::TimeDelta sample) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "WebRTC.PeerConnection.Duration.Signaling", sample,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 50);
+ }
+
+ static void InitializeOnThread(
+ rtc::Thread** thread,
+ base::WaitableEvent* event,
+ base::RepeatingCallback<void(base::TimeDelta)> latency_callback,
+ base::RepeatingCallback<void(base::TimeDelta)> duration_callback) {
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ jingle_glue::JingleThreadWrapper::current()
+ ->SetLatencyAndTaskDurationCallbacks(std::move(latency_callback),
+ std::move(duration_callback));
if (!*thread) {
*thread = jingle_glue::JingleThreadWrapper::current();
event->Signal();
@@ -354,8 +423,8 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
blink::features::kWebRtcHideLocalIpsWithMdns)) {
// Note that MdnsResponderAdapter is created on the main thread to have
// access to the connector to the service manager.
- // TODO(crbug.com/1178670): Pass MojoBindingContext and use its BIB to bind.
- mdns_responder = std::make_unique<MdnsResponderAdapter>();
+ mdns_responder =
+ std::make_unique<MdnsResponderAdapter>(*GetSupplementable());
}
#endif // BUILDFLAG(ENABLE_MDNS)
PostCrossThreadTask(
@@ -658,8 +727,8 @@ PeerConnectionDependencyFactory::CreateVideoTrackSourceProxy(
if (!PeerConnectionFactoryCreated())
CreatePeerConnectionFactory();
- return webrtc::VideoTrackSourceProxy::Create(GetSignalingThread(),
- GetNetworkThread(), source)
+ return webrtc::CreateVideoTrackSourceProxy(GetSignalingThread(),
+ GetNetworkThread(), source)
.get();
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
index 01e42a741b0..5656fa4e542 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -549,7 +549,7 @@ class InternalLegacyStatsObserver : public webrtc::StatsObserver {
list->Append(std::move(report).value());
}
- if (!list->empty()) {
+ if (!list->GetList().empty()) {
PostCrossThreadTask(
*main_thread_.get(), FROM_HERE,
CrossThreadBindOnce(&InternalLegacyStatsObserver::OnCompleteImpl,
@@ -573,7 +573,7 @@ class InternalLegacyStatsObserver : public webrtc::StatsObserver {
std::unique_ptr<base::ListValue> list,
int lid,
CrossThreadOnceFunction<void(int, base::Value)> completion_callback) {
- DCHECK(!list->empty());
+ DCHECK(!list->GetList().empty());
std::move(completion_callback).Run(lid, std::move(*list.get()));
}
@@ -676,6 +676,8 @@ class InternalStandardStatsObserver : public webrtc::RTCStatsCollectorCallback {
case webrtc::RTCStatsMemberInterface::Type::kSequenceUint64:
case webrtc::RTCStatsMemberInterface::Type::kSequenceDouble:
case webrtc::RTCStatsMemberInterface::Type::kSequenceString:
+ case webrtc::RTCStatsMemberInterface::Type::kMapStringUint64:
+ case webrtc::RTCStatsMemberInterface::Type::kMapStringDouble:
default:
return base::Value(member.ValueToString());
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc
index f6c27c5de4c..03c3f501bb1 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc
@@ -47,7 +47,7 @@ DOMTimeStamp RTCCertificate::expires() const {
HeapVector<Member<RTCDtlsFingerprint>> RTCCertificate::getFingerprints() {
std::unique_ptr<rtc::SSLCertificateStats> first_certificate_stats =
- certificate_->ssl_certificate().GetStats();
+ certificate_->GetSSLCertificate().GetStats();
HeapVector<Member<RTCDtlsFingerprint>> fingerprints;
for (rtc::SSLCertificateStats* certificate_stats =
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_configuration.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_configuration.idl
index e441fab161f..fbba82e5ef0 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_configuration.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_configuration.idl
@@ -48,15 +48,8 @@ dictionary RTCConfiguration {
[EnforceRange] octet iceCandidatePoolSize = 0;
// Nonstandard, added for Unified Plan migration
[RuntimeEnabled=RTCUnifiedPlan] SdpSemantics sdpSemantics;
- // Nonstandard, added for backward compatibility reasons during a
- // transitional phase. https://crbug.com/908377
- boolean offerExtmapAllowMixed;
[RuntimeEnabled=RtcAudioJitterBufferMaxPackets] long rtcAudioJitterBufferMaxPackets;
[RuntimeEnabled=RtcAudioJitterBufferMaxPackets] boolean rtcAudioJitterBufferFastAccelerate;
[RuntimeEnabled=RtcAudioJitterBufferMaxPackets] long rtcAudioJitterBufferMinDelayMs;
boolean encodedInsertableStreams = false;
- [DeprecateAs=ForceEncodedAudioInsertableStreams,
- RuntimeEnabled=RTCInsertableStreams] boolean forceEncodedAudioInsertableStreams = false;
- [DeprecateAs=ForceEncodedVideoInsertableStreams,
- RuntimeEnabled=RTCInsertableStreams] boolean forceEncodedVideoInsertableStreams = false;
};
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 9c531e9003a..5d95271ffa9 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
@@ -29,6 +29,7 @@
#include <string>
#include <utility>
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/events/message_event.h"
@@ -64,39 +65,60 @@ namespace blink {
namespace {
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
enum class DataChannelCounters {
- kCreated,
- kOpened,
- kReliable,
- kOrdered,
- kNegotiated,
- kBoundary
+ kCreated = 0,
+ kOpened = 1,
+ kReliable = 2,
+ kOrdered = 3,
+ kNegotiated = 4,
+ kMaxValue = kNegotiated,
+};
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class DataChannelAggregateType {
+ kUnReliableUnordered = 0,
+ kUnReliableOrdered = 1,
+ kReliableUnordered = 2,
+ kReliableOrdered = 3,
+ kMaxValue = kReliableOrdered,
};
void IncrementCounter(DataChannelCounters counter) {
- UMA_HISTOGRAM_ENUMERATION("WebRTC.DataChannelCounters", counter,
- DataChannelCounters::kBoundary);
+ base::UmaHistogramEnumeration("WebRTC.DataChannelCounters", counter);
}
void IncrementCounters(const webrtc::DataChannelInterface& channel) {
+ int aggregate_type = 0;
+
IncrementCounter(DataChannelCounters::kCreated);
- if (channel.reliable())
+ if (channel.reliable()) {
IncrementCounter(DataChannelCounters::kReliable);
- if (channel.ordered())
+ aggregate_type += 2;
+ }
+ if (channel.ordered()) {
IncrementCounter(DataChannelCounters::kOrdered);
+ aggregate_type += 1;
+ }
if (channel.negotiated())
IncrementCounter(DataChannelCounters::kNegotiated);
+ base::UmaHistogramEnumeration(
+ "WebRTC.DataChannelAggregateType",
+ static_cast<DataChannelAggregateType>(aggregate_type));
+
// Only record max retransmits and max packet life time if set.
if (channel.maxRetransmitsOpt()) {
- UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmits",
- *(channel.maxRetransmitsOpt()), 1,
- std::numeric_limits<uint16_t>::max(), 50);
+ base::UmaHistogramCustomCounts("WebRTC.DataChannelMaxRetransmits",
+ *(channel.maxRetransmitsOpt()), 1,
+ std::numeric_limits<uint16_t>::max(), 50);
}
if (channel.maxPacketLifeTime()) {
- UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxPacketLifeTime",
- *channel.maxPacketLifeTime(), 1,
- std::numeric_limits<uint16_t>::max(), 50);
+ base::UmaHistogramCustomCounts("WebRTC.DataChannelMaxPacketLifeTime",
+ *channel.maxPacketLifeTime(), 1,
+ std::numeric_limits<uint16_t>::max(), 50);
}
}
@@ -125,6 +147,40 @@ void RecordMessageSent(const webrtc::DataChannelInterface& channel,
}
}
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class DataChannelSctpErrorCode {
+ kUnspecified = 0,
+ kInvalidStreamIdentifier = 1,
+ kMissingMandatoryParameter = 2,
+ kStaleCookieError = 3,
+ kOutOfResource = 4,
+ kUnresolvableAddress = 5,
+ kUnrecognizedChunkType = 6,
+ kInvalidMandatoryParameter = 7,
+ kUnrecognizedParameters = 8,
+ kNoUserData = 9,
+ kCookieReceivedWhileShuttingDown = 10,
+ kRestartWithNewAddresses = 11,
+ kUserInitiatedAbort = 12,
+ kProtocolViolation = 13,
+ kOther = 14,
+ kMaxValue = kOther,
+};
+
+void IncrementErrorCounter(const webrtc::RTCError& error) {
+ DataChannelSctpErrorCode uma_code;
+ auto code = error.sctp_cause_code();
+ if (!code.has_value()) {
+ uma_code = DataChannelSctpErrorCode::kUnspecified;
+ } else if (*code >= static_cast<int>(DataChannelSctpErrorCode::kOther)) {
+ uma_code = DataChannelSctpErrorCode::kOther;
+ } else {
+ uma_code = static_cast<DataChannelSctpErrorCode>(*code);
+ }
+ base::UmaHistogramEnumeration("WebRTC.DataChannelSctpErrorCode", uma_code);
+}
+
void SendOnSignalingThread(
const scoped_refptr<webrtc::DataChannelInterface> channel,
const webrtc::DataBuffer data_buffer) {
@@ -547,14 +603,19 @@ void RTCDataChannel::OnStateChange(
DispatchEvent(*Event::Create(event_type_names::kClosing));
}
break;
- case webrtc::DataChannelInterface::kClosed:
+ case webrtc::DataChannelInterface::kClosed: {
feature_handle_for_scheduler_.reset();
- if (!channel()->error().ok()) {
+ auto error = channel()->error();
+ if (!error.ok()) {
+ LOG(ERROR) << "DataChannel error: \"" << error.message() << "\""
+ << ", code: " << error.sctp_cause_code().value_or(-1);
+ IncrementErrorCounter(error);
DispatchEvent(*MakeGarbageCollected<RTCErrorEvent>(
- event_type_names::kError, channel()->error()));
+ event_type_names::kError, error));
}
DispatchEvent(*Event::Create(event_type_names::kClose));
break;
+ }
default:
break;
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.cc
new file mode 100644
index 00000000000..ec1b25669f1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.cc
@@ -0,0 +1,24 @@
+#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+
+namespace blink {
+
+RtcEncodedAudioReceiverSinkOptimizer::RtcEncodedAudioReceiverSinkOptimizer(
+ UnderlyingSinkSetter set_underlying_sink,
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker> transformer)
+ : set_underlying_sink_(std::move(set_underlying_sink)),
+ transformer_(std::move(transformer)) {}
+
+UnderlyingSinkBase*
+RtcEncodedAudioReceiverSinkOptimizer::PerformInProcessOptimization(
+ ScriptState* script_state) {
+ auto* new_sink = MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>(
+ script_state, std::move(transformer_));
+
+ std::move(set_underlying_sink_).Run(WrapCrossThreadPersistent(new_sink));
+
+ return new_sink;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.h
new file mode 100644
index 00000000000..3a27e4060e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_RECEIVER_SINK_OPTIMIZER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_RECEIVER_SINK_OPTIMIZER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h"
+
+namespace blink {
+
+class UnderlyingSinkBase;
+class ScriptState;
+class RTCEncodedAudioUnderlyingSink;
+
+class MODULES_EXPORT RtcEncodedAudioReceiverSinkOptimizer
+ : public WritableStreamTransferringOptimizer {
+ public:
+ using UnderlyingSinkSetter =
+ WTF::CrossThreadOnceFunction<void(RTCEncodedAudioUnderlyingSink*)>;
+ RtcEncodedAudioReceiverSinkOptimizer(
+ UnderlyingSinkSetter,
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
+ transformer);
+ UnderlyingSinkBase* PerformInProcessOptimization(
+ ScriptState* script_state) override;
+
+ private:
+ UnderlyingSinkSetter set_underlying_sink_;
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker> transformer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_RECEIVER_SINK_OPTIMIZER_H_
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.cc
new file mode 100644
index 00000000000..0d540fa2502
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.cc
@@ -0,0 +1,31 @@
+#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+
+namespace blink {
+
+RtcEncodedAudioReceiverSourceOptimizer::RtcEncodedAudioReceiverSourceOptimizer(
+ UnderlyingSourceSetter set_underlying_source,
+ WTF::CrossThreadOnceClosure disconnect_callback)
+ : set_underlying_source_(std::move(set_underlying_source)),
+ disconnect_callback_(std::move(disconnect_callback)) {}
+
+UnderlyingSourceBase*
+RtcEncodedAudioReceiverSourceOptimizer::PerformInProcessOptimization(
+ ScriptState* script_state) {
+ ExecutionContext* context = ExecutionContext::From(script_state);
+
+ scoped_refptr<base::SingleThreadTaskRunner> current_runner =
+ context->GetTaskRunner(TaskType::kInternalMediaRealTime);
+
+ auto* new_source = MakeGarbageCollected<RTCEncodedAudioUnderlyingSource>(
+ script_state, std::move(disconnect_callback_),
+ /*is_receiver=*/true);
+
+ set_underlying_source_.Run(WrapCrossThreadPersistent(new_source),
+ std::move(current_runner));
+
+ return new_source;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.h
new file mode 100644
index 00000000000..eaba78574b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_RECEIVER_SOURCE_OPTIMIZER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_RECEIVER_SOURCE_OPTIMIZER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
+#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h"
+
+namespace blink {
+
+class UnderlyingSourceBase;
+class ScriptState;
+class RTCEncodedAudioUnderlyingSource;
+
+class MODULES_EXPORT RtcEncodedAudioReceiverSourceOptimizer
+ : public ReadableStreamTransferringOptimizer {
+ public:
+ using UnderlyingSourceSetter = WTF::CrossThreadFunction<void(
+ RTCEncodedAudioUnderlyingSource*,
+ scoped_refptr<base::SingleThreadTaskRunner>)>;
+ RtcEncodedAudioReceiverSourceOptimizer(
+ UnderlyingSourceSetter,
+ WTF::CrossThreadOnceClosure disconnect_callback);
+ UnderlyingSourceBase* PerformInProcessOptimization(
+ ScriptState* script_state) override;
+
+ private:
+ UnderlyingSourceSetter set_underlying_source_;
+ WTF::CrossThreadOnceClosure disconnect_callback_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_RECEIVER_SOURCE_OPTIMIZER_H_
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc
index 1e5feaf5a26..ffc16aec548 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc
@@ -14,9 +14,10 @@ namespace blink {
RTCEncodedAudioUnderlyingSink::RTCEncodedAudioUnderlyingSink(
ScriptState* script_state,
- TransformerCallback transformer_callback)
- : transformer_callback_(std::move(transformer_callback)) {
- DCHECK(transformer_callback_);
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
+ transformer_broker)
+ : transformer_broker_(std::move(transformer_broker)) {
+ DCHECK(transformer_broker_);
}
ScriptPromise RTCEncodedAudioUnderlyingSink::start(
@@ -32,6 +33,7 @@ ScriptPromise RTCEncodedAudioUnderlyingSink::write(
ScriptValue chunk,
WritableStreamDefaultController* controller,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
RTCEncodedAudioFrame* encoded_frame =
V8RTCEncodedAudioFrame::ToImplWithTypeCheck(script_state->GetIsolate(),
chunk.V8Value());
@@ -40,7 +42,7 @@ ScriptPromise RTCEncodedAudioUnderlyingSink::write(
return ScriptPromise();
}
- if (!transformer_callback_) {
+ if (!transformer_broker_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Stream closed");
return ScriptPromise();
@@ -53,22 +55,16 @@ ScriptPromise RTCEncodedAudioUnderlyingSink::write(
return ScriptPromise();
}
- RTCEncodedAudioStreamTransformer* transformer = transformer_callback_.Run();
- if (!transformer) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "No underlying sink");
- return ScriptPromise();
- }
-
- transformer->SendFrameToSink(std::move(webrtc_frame));
+ transformer_broker_->SendFrameToSink(std::move(webrtc_frame));
return ScriptPromise::CastUndefined(script_state);
}
ScriptPromise RTCEncodedAudioUnderlyingSink::close(ScriptState* script_state,
ExceptionState&) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Disconnect from the transformer if the sink is closed.
- if (transformer_callback_)
- transformer_callback_.Reset();
+ if (transformer_broker_)
+ transformer_broker_.reset();
return ScriptPromise::CastUndefined(script_state);
}
@@ -76,6 +72,7 @@ ScriptPromise RTCEncodedAudioUnderlyingSink::abort(
ScriptState* script_state,
ScriptValue reason,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// It is not possible to cancel any frames already sent to the WebRTC sink,
// thus abort() has the same effect as close().
return close(script_state, exception_state);
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h
index 7f7cae2d87c..1a640ace282 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h
@@ -5,8 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_UNDERLYING_SINK_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ENCODED_AUDIO_UNDERLYING_SINK_H_
+#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h"
namespace blink {
@@ -16,9 +18,9 @@ class RTCEncodedAudioStreamTransformer;
class MODULES_EXPORT RTCEncodedAudioUnderlyingSink final
: public UnderlyingSinkBase {
public:
- using TransformerCallback =
- base::RepeatingCallback<RTCEncodedAudioStreamTransformer*()>;
- RTCEncodedAudioUnderlyingSink(ScriptState*, TransformerCallback);
+ RTCEncodedAudioUnderlyingSink(
+ ScriptState*,
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>);
// UnderlyingSinkBase
ScriptPromise start(ScriptState*,
@@ -36,7 +38,9 @@ class MODULES_EXPORT RTCEncodedAudioUnderlyingSink final
void Trace(Visitor*) const override;
private:
- TransformerCallback transformer_callback_;
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
+ transformer_broker_;
+ THREAD_CHECKER(thread_checker_);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc
index c9e7862d503..67b3551c730 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc
@@ -48,17 +48,6 @@ class FakeAudioFrame : public webrtc::TransformableFrameInterface {
uint32_t GetSsrc() const override { return 0; }
};
-bool IsDOMException(ScriptState* script_state,
- ScriptValue value,
- DOMExceptionCode code) {
- auto* dom_exception = V8DOMException::ToImplWithTypeCheck(
- script_state->GetIsolate(), value.V8Value());
- if (!dom_exception)
- return false;
-
- return dom_exception->code() == static_cast<uint16_t>(code);
-}
-
} // namespace
class RTCEncodedAudioUnderlyingSinkTest : public testing::Test {
@@ -84,17 +73,7 @@ class RTCEncodedAudioUnderlyingSinkTest : public testing::Test {
RTCEncodedAudioUnderlyingSink* CreateSink(ScriptState* script_state) {
return MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>(
- script_state,
- WTF::BindRepeating(&RTCEncodedAudioUnderlyingSinkTest::GetTransformer,
- WTF::Unretained(this)));
- }
-
- RTCEncodedAudioUnderlyingSink* CreateNullCallbackSink(
- ScriptState* script_state) {
- return MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>(
- script_state,
- WTF::BindRepeating(
- []() -> RTCEncodedAudioStreamTransformer* { return nullptr; }));
+ script_state, transformer_.GetBroker());
}
RTCEncodedAudioStreamTransformer* GetTransformer() { return &transformer_; }
@@ -159,25 +138,4 @@ TEST_F(RTCEncodedAudioUnderlyingSinkTest, WriteInvalidDataFails) {
EXPECT_TRUE(dummy_exception_state.HadException());
}
-TEST_F(RTCEncodedAudioUnderlyingSinkTest, WriteToNullCallbackSinkFails) {
- V8TestingScope v8_scope;
- ScriptState* script_state = v8_scope.GetScriptState();
- auto* sink = CreateNullCallbackSink(script_state);
- auto* stream =
- WritableStream::CreateWithCountQueueingStrategy(script_state, sink, 1u);
-
- NonThrowableExceptionState exception_state;
- auto* writer = stream->getWriter(script_state, exception_state);
-
- EXPECT_CALL(*webrtc_callback_, OnTransformedFrame(_)).Times(0);
- ScriptPromiseTester write_tester(
- script_state,
- writer->write(script_state, CreateEncodedAudioFrameChunk(script_state),
- exception_state));
- write_tester.WaitUntilSettled();
- EXPECT_TRUE(write_tester.IsRejected());
- EXPECT_TRUE(IsDOMException(script_state, write_tester.Value(),
- DOMExceptionCode::kInvalidStateError));
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.cc
index 2caca05c398..f6ae1421280 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.cc
@@ -10,6 +10,8 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame_delegate.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/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/webrtc/api/frame_transformer_interface.h"
@@ -22,17 +24,20 @@ const int RTCEncodedAudioUnderlyingSource::kMinQueueDesiredSize = -60;
RTCEncodedAudioUnderlyingSource::RTCEncodedAudioUnderlyingSource(
ScriptState* script_state,
- base::OnceClosure disconnect_callback,
+ WTF::CrossThreadOnceClosure disconnect_callback,
bool is_receiver)
: UnderlyingSourceBase(script_state),
script_state_(script_state),
disconnect_callback_(std::move(disconnect_callback)),
is_receiver_(is_receiver) {
DCHECK(disconnect_callback_);
+
+ ExecutionContext* context = ExecutionContext::From(script_state);
+ task_runner_ = context->GetTaskRunner(TaskType::kInternalMediaRealTime);
}
ScriptPromise RTCEncodedAudioUnderlyingSource::pull(ScriptState* script_state) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(task_runner_->BelongsToCurrentThread());
// WebRTC is a push source without backpressure support, so nothing to do
// here.
return ScriptPromise::CastUndefined(script_state);
@@ -40,7 +45,7 @@ ScriptPromise RTCEncodedAudioUnderlyingSource::pull(ScriptState* script_state) {
ScriptPromise RTCEncodedAudioUnderlyingSource::Cancel(ScriptState* script_state,
ScriptValue reason) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (disconnect_callback_)
std::move(disconnect_callback_).Run();
return ScriptPromise::CastUndefined(script_state);
@@ -53,7 +58,7 @@ void RTCEncodedAudioUnderlyingSource::Trace(Visitor* visitor) const {
void RTCEncodedAudioUnderlyingSource::OnFrameFromSource(
std::unique_ptr<webrtc::TransformableFrameInterface> webrtc_frame) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(task_runner_->BelongsToCurrentThread());
// If the source is canceled or there are too many queued frames,
// drop the new frame.
if (!disconnect_callback_ || !Controller() ||
@@ -78,7 +83,7 @@ void RTCEncodedAudioUnderlyingSource::OnFrameFromSource(
}
void RTCEncodedAudioUnderlyingSource::Close() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (disconnect_callback_)
std::move(disconnect_callback_).Run();
@@ -86,4 +91,18 @@ void RTCEncodedAudioUnderlyingSource::Close() {
Controller()->Close();
}
+void RTCEncodedAudioUnderlyingSource::OnSourceTransferStartedOnTaskRunner() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (Controller())
+ Controller()->Close();
+}
+
+void RTCEncodedAudioUnderlyingSource::OnSourceTransferStarted() {
+ PostCrossThreadTask(
+ *task_runner_, FROM_HERE,
+ CrossThreadBindOnce(
+ &RTCEncodedAudioUnderlyingSource::OnSourceTransferStartedOnTaskRunner,
+ WrapCrossThreadPersistent(this)));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h
index 586002e9efb..33dc3a7329a 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h
@@ -20,7 +20,7 @@ class MODULES_EXPORT RTCEncodedAudioUnderlyingSource
public:
explicit RTCEncodedAudioUnderlyingSource(
ScriptState*,
- base::OnceClosure disconnect_callback,
+ WTF::CrossThreadOnceClosure disconnect_callback,
bool is_receiver);
// UnderlyingSourceBase
@@ -30,19 +30,27 @@ class MODULES_EXPORT RTCEncodedAudioUnderlyingSource
void OnFrameFromSource(std::unique_ptr<webrtc::TransformableFrameInterface>);
void Close();
+ // Called on any thread to indicate the source is being transferred to an
+ // UnderlyingSource on a different thread to this.
+ void OnSourceTransferStarted();
+
void Trace(Visitor*) const override;
private:
+ // Implements the handling of this stream being transferred to another
+ // context, called on the thread upon which the instance was created.
+ void OnSourceTransferStartedOnTaskRunner();
+
FRIEND_TEST_ALL_PREFIXES(RTCEncodedAudioUnderlyingSourceTest,
QueuedFramesAreDroppedWhenOverflow);
static const int kMinQueueDesiredSize;
const Member<ScriptState> script_state_;
- base::OnceClosure disconnect_callback_;
+ WTF::CrossThreadOnceClosure disconnect_callback_;
// Indicates if this source is for a receiver. Receiver sources
// expose CSRCs.
const bool is_receiver_;
- THREAD_CHECKER(thread_checker_);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source_test.cc
index 4621676bcdc..a95bf4a3e3e 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source_test.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/webrtc/api/frame_transformer_interface.h"
namespace blink {
@@ -37,7 +38,8 @@ class RTCEncodedAudioUnderlyingSourceTest : public testing::Test {
RTCEncodedAudioUnderlyingSource* CreateSource(ScriptState* script_state,
bool is_receiver = false) {
return MakeGarbageCollected<RTCEncodedAudioUnderlyingSource>(
- script_state, WTF::Bind(disconnect_callback_.Get()), is_receiver);
+ script_state, WTF::CrossThreadBindOnce(disconnect_callback_.Get()),
+ is_receiver);
}
protected:
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
index dcf512a9605..fee5a226817 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_gather_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_server.h"
@@ -224,10 +225,13 @@ static webrtc::PeerConnectionInterface::IceServer ConvertIceServer(
// Prefer standardized 'urls' field over deprecated 'url' field.
Vector<String> url_strings;
if (ice_server->hasUrls()) {
- if (ice_server->urls().IsString()) {
- url_strings.push_back(ice_server->urls().GetAsString());
- } else if (ice_server->urls().IsStringSequence()) {
- url_strings = ice_server->urls().GetAsStringSequence();
+ switch (ice_server->urls()->GetContentType()) {
+ case V8UnionStringOrStringSequence::ContentType::kString:
+ url_strings.push_back(ice_server->urls()->GetAsString());
+ break;
+ case V8UnionStringOrStringSequence::ContentType::kStringSequence:
+ url_strings = ice_server->urls()->GetAsStringSequence();
+ break;
}
} else if (ice_server->hasUrl()) {
url_strings.push_back(ice_server->url());
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 cb54af0ce8d..73f8554e487 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
@@ -42,15 +42,17 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/bindings/core/v8/dictionary.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_union_object_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.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/v8_media_stream_track.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_answer_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h"
@@ -76,6 +78,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/modules/crypto/crypto_result_impl.h"
#include "third_party/blink/renderer/modules/mediastream/media_constraints_impl.h"
+#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_event.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
@@ -246,24 +249,6 @@ SdpSemanticRequested GetSdpSemanticRequested(
return kSdpSemanticRequestedDefault;
}
-enum class OfferExtmapAllowMixedSetting {
- kDefault,
- kEnabled,
- kDisabled,
- kMaxValue = kDisabled
-};
-
-OfferExtmapAllowMixedSetting GetOfferExtmapAllowMixedSetting(
- const blink::RTCConfiguration* configuration) {
- if (!configuration->hasOfferExtmapAllowMixed()) {
- return OfferExtmapAllowMixedSetting::kDefault;
- }
-
- return configuration->offerExtmapAllowMixed()
- ? OfferExtmapAllowMixedSetting::kEnabled
- : OfferExtmapAllowMixedSetting::kDisabled;
-}
-
webrtc::PeerConnectionInterface::IceTransportsType IceTransportPolicyFromString(
const String& policy) {
if (policy == "relay")
@@ -320,19 +305,34 @@ webrtc::PeerConnectionInterface::RTCConfiguration ParseConfiguration(
if (RuntimeEnabledFeatures::RTCExtendDeadlineForPlanBRemovalEnabled(
context) ||
context->Url().IsLocalFile()) {
- // TODO(https://crbug.com/857004): In M97, replace this deprecation
- // warning with the throwing of an exception (Reverse Origin Trial has
- // ended).
+ // TODO(https://crbug.com/857004): In M97, when the Deprecation Trial
+ // ends, remove this code path in favor of throwing the exception below.
Deprecation::CountDeprecation(
context,
WebFeature::
kRTCPeerConnectionSdpSemanticsPlanBWithReverseOriginTrial);
} else {
- // The deadline is not being extended.
- // TODO(https://crbug.com/857004): In M93, replace this deprecation
- // warning with the throwing of an exception.
- Deprecation::CountDeprecation(
- context, WebFeature::kRTCPeerConnectionSdpSemanticsPlanB);
+ // The Deprecation Trial is not active. In this case, throw an exception
+ // if RTCDisallowPlanBOutsideDeprecationTrial is enabled.
+ if (base::FeatureList::IsEnabled(
+ features::kRTCDisallowPlanBOutsideDeprecationTrial)) {
+ // Throw Plan B exception!
+ UseCounter::Count(
+ context, WebFeature::kRTCPeerConnectionPlanBThrewAnException);
+ exception_state->ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Plan B SDP semantics is a legacy version of the Session "
+ "Description Protocol that has severe compatibility issues on "
+ "modern browsers and is no longer supported. See "
+ "https://www.chromestatus.com/feature/5823036655665152 for more "
+ "details, including the possibility of registering for a "
+ "Deprecation Trial in order to extend the Plan B deprecation "
+ "deadline for a limited amount of time.");
+ } else {
+ // Throwing is not enabled, so just show a deprecation warning.
+ Deprecation::CountDeprecation(
+ context, WebFeature::kRTCPeerConnectionSdpSemanticsPlanB);
+ }
}
} else {
DCHECK_EQ(configuration->sdpSemantics(), "unified-plan");
@@ -351,32 +351,19 @@ webrtc::PeerConnectionInterface::RTCConfiguration ParseConfiguration(
}
}
- if (configuration->hasOfferExtmapAllowMixed()) {
- web_configuration.offer_extmap_allow_mixed =
- configuration->offerExtmapAllowMixed();
- if (!web_configuration.offer_extmap_allow_mixed) {
- // Only show a deprecation warning when set to false. The default
- // is "true" as of M91.
- Deprecation::CountDeprecation(
- context, WebFeature::kRTCPeerConnectionOfferAllowExtmapMixedFalse);
- }
- } else {
- web_configuration.offer_extmap_allow_mixed =
- base::FeatureList::IsEnabled(features::kRTCOfferExtmapAllowMixed);
- }
-
if (configuration->hasIceServers()) {
WebVector<webrtc::PeerConnectionInterface::IceServer> ice_servers;
for (const RTCIceServer* ice_server : configuration->iceServers()) {
Vector<String> url_strings;
if (ice_server->hasUrls()) {
UseCounter::Count(context, WebFeature::kRTCIceServerURLs);
- const StringOrStringSequence& urls = ice_server->urls();
- if (urls.IsString()) {
- url_strings.push_back(urls.GetAsString());
- } else {
- DCHECK(urls.IsStringSequence());
- url_strings = urls.GetAsStringSequence();
+ switch (ice_server->urls()->GetContentType()) {
+ case V8UnionStringOrStringSequence::ContentType::kString:
+ url_strings.push_back(ice_server->urls()->GetAsString());
+ break;
+ case V8UnionStringOrStringSequence::ContentType::kStringSequence:
+ url_strings = ice_server->urls()->GetAsStringSequence();
+ break;
}
} else if (ice_server->hasUrl()) {
UseCounter::Count(context, WebFeature::kRTCIceServerURL);
@@ -602,16 +589,38 @@ RTCSetSessionDescriptionOperation GetRTCVoidRequestOperationType(
const RTCSessionDescriptionInit& description) {
switch (operation) {
case RTCPeerConnection::SetSdpOperationType::kSetLocalDescription:
- if (description.type() == "offer")
- return RTCSetSessionDescriptionOperation::kSetLocalDescriptionOffer;
- if (description.type() == "answer" || description.type() == "pranswer")
- return RTCSetSessionDescriptionOperation::kSetLocalDescriptionAnswer;
+ if (!description.hasType()) {
+ return RTCSetSessionDescriptionOperation::
+ kSetLocalDescriptionInvalidType;
+ }
+ switch (description.type().AsEnum()) {
+ case V8RTCSdpType::Enum::kOffer:
+ return RTCSetSessionDescriptionOperation::kSetLocalDescriptionOffer;
+ case V8RTCSdpType::Enum::kPranswer:
+ case V8RTCSdpType::Enum::kAnswer:
+ return RTCSetSessionDescriptionOperation::kSetLocalDescriptionAnswer;
+ case V8RTCSdpType::Enum::kRollback:
+ return RTCSetSessionDescriptionOperation::
+ kSetLocalDescriptionInvalidType;
+ }
+ NOTREACHED();
return RTCSetSessionDescriptionOperation::kSetLocalDescriptionInvalidType;
case RTCPeerConnection::SetSdpOperationType::kSetRemoteDescription:
- if (description.type() == "offer")
- return RTCSetSessionDescriptionOperation::kSetRemoteDescriptionOffer;
- if (description.type() == "answer" || description.type() == "pranswer")
- return RTCSetSessionDescriptionOperation::kSetRemoteDescriptionAnswer;
+ if (!description.hasType()) {
+ return RTCSetSessionDescriptionOperation::
+ kSetRemoteDescriptionInvalidType;
+ }
+ switch (description.type().AsEnum()) {
+ case V8RTCSdpType::Enum::kOffer:
+ return RTCSetSessionDescriptionOperation::kSetRemoteDescriptionOffer;
+ case V8RTCSdpType::Enum::kPranswer:
+ case V8RTCSdpType::Enum::kAnswer:
+ return RTCSetSessionDescriptionOperation::kSetRemoteDescriptionAnswer;
+ case V8RTCSdpType::Enum::kRollback:
+ return RTCSetSessionDescriptionOperation::
+ kSetRemoteDescriptionInvalidType;
+ }
+ NOTREACHED();
return RTCSetSessionDescriptionOperation::
kSetRemoteDescriptionInvalidType;
}
@@ -677,8 +686,18 @@ RTCPeerConnection* RTCPeerConnection::Create(
if (content_security_policy &&
content_security_policy->IsActiveForConnections()) {
UseCounter::Count(context, WebFeature::kRTCPeerConnectionWithActiveCsp);
+ // Count number of PeerConnections that would be blocked by CSP connect-src
+ // or one of the directive it inherits from.
+ // This is intended for evaluating whether introducing a "webrtc-src"
+ // on-off switch that inherits from connect-csp would be harmful or not.
+ // TODO(crbug.com/1225968): Remove code when decision is made.
+ if (!content_security_policy->AllowConnectToSource(
+ KURL("https://example.org"), KURL("https://example.org"),
+ RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting)) {
+ UseCounter::Count(context, WebFeature::kRTCPeerConnectionWithBlockingCsp);
+ }
}
-
if (media_constraints.IsObject()) {
UseCounter::Count(context,
WebFeature::kRTCPeerConnectionConstructorConstraints);
@@ -717,11 +736,9 @@ RTCPeerConnection* RTCPeerConnection::Create(
RTCPeerConnection* peer_connection = MakeGarbageCollected<RTCPeerConnection>(
context, std::move(configuration), rtc_configuration->hasSdpSemantics(),
- rtc_configuration->forceEncodedAudioInsertableStreams() ||
- rtc_configuration->encodedInsertableStreams(),
- rtc_configuration->forceEncodedVideoInsertableStreams() ||
- rtc_configuration->encodedInsertableStreams(),
- constraints, exception_state);
+ rtc_configuration->encodedInsertableStreams(),
+ rtc_configuration->encodedInsertableStreams(), constraints,
+ exception_state);
if (exception_state.HadException())
return nullptr;
@@ -741,9 +758,6 @@ RTCPeerConnection* RTCPeerConnection::Create(
WebFeature::kRTCPeerConnectionConstructedWithUnifiedPlan);
}
- UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.OfferExtmapAllowMixed",
- GetOfferExtmapAllowMixedSetting(rtc_configuration));
-
return peer_connection;
}
@@ -1237,23 +1251,26 @@ const CallSetupStateTracker& RTCPeerConnection::call_setup_state_tracker()
void RTCPeerConnection::NoteCallSetupStateEventPending(
RTCPeerConnection::SetSdpOperationType operation,
const RTCSessionDescriptionInit& description) {
+ if (!description.hasType())
+ return;
+
switch (operation) {
case RTCPeerConnection::SetSdpOperationType::kSetLocalDescription:
- if (description.type() == "offer") {
+ if (description.type() == V8RTCSdpType::Enum::kOffer) {
call_setup_state_tracker_.NoteOffererStateEvent(
OffererState::kSetLocalOfferPending, HasDocumentMedia());
- } else if (description.type() == "answer" ||
- description.type() == "pranswer") {
+ } else if (description.type() == V8RTCSdpType::Enum::kAnswer ||
+ description.type() == V8RTCSdpType::Enum::kPranswer) {
call_setup_state_tracker_.NoteAnswererStateEvent(
AnswererState::kSetLocalAnswerPending, HasDocumentMedia());
}
break;
case RTCPeerConnection::SetSdpOperationType::kSetRemoteDescription:
- if (description.type() == "offer") {
+ if (description.type() == V8RTCSdpType::Enum::kOffer) {
call_setup_state_tracker_.NoteAnswererStateEvent(
AnswererState::kSetRemoteOfferPending, HasDocumentMedia());
- } else if (description.type() == "answer" ||
- description.type() == "pranswer") {
+ } else if (description.type() == V8RTCSdpType::Enum::kAnswer ||
+ description.type() == V8RTCSdpType::Enum::kPranswer) {
call_setup_state_tracker_.NoteOffererStateEvent(
OffererState::kSetRemoteAnswerPending, HasDocumentMedia());
}
@@ -1411,17 +1428,22 @@ ScriptPromise RTCPeerConnection::setLocalDescription(
String sdp = session_description_init->sdp();
// https://w3c.github.io/webrtc-pc/#dom-peerconnection-setlocaldescription
// step 4.4 and 4.5: If SDP is empty, return the last created offer or answer.
- if (sdp.IsNull() || sdp.IsEmpty()) {
- if (session_description_init->type() == "offer") {
- sdp = last_offer_;
- } else if (session_description_init->type() == "answer" ||
- session_description_init->type() == "pranswer") {
- sdp = last_answer_;
+ if (sdp.IsEmpty()) {
+ switch (session_description_init->type().AsEnum()) {
+ case V8RTCSdpType::Enum::kOffer:
+ sdp = last_offer_;
+ break;
+ case V8RTCSdpType::Enum::kPranswer:
+ case V8RTCSdpType::Enum::kAnswer:
+ sdp = last_answer_;
+ break;
+ case V8RTCSdpType::Enum::kRollback:
+ break;
}
}
ParsedSessionDescription parsed_sdp =
ParsedSessionDescription::Parse(session_description_init->type(), sdp);
- if (session_description_init->type() != "rollback") {
+ if (session_description_init->type() != V8RTCSdpType::Enum::kRollback) {
RecordSdpCategoryAndMaybeEmitWarnings(parsed_sdp);
ReportSetSdpUsage(SetSdpOperationType::kSetLocalDescription, parsed_sdp);
@@ -1465,17 +1487,26 @@ ScriptPromise RTCPeerConnection::setLocalDescription(
String sdp = session_description_init->sdp();
// https://w3c.github.io/webrtc-pc/#dom-peerconnection-setlocaldescription
// step 4.4 and 4.5: If SDP is empty, return the last created offer or answer.
- if (sdp.IsNull() || sdp.IsEmpty()) {
- if (session_description_init->type() == "offer") {
- sdp = last_offer_;
- } else if (session_description_init->type() == "answer" ||
- session_description_init->type() == "pranswer") {
- sdp = last_answer_;
+ if (sdp.IsEmpty() && session_description_init->hasType()) {
+ switch (session_description_init->type().AsEnum()) {
+ case V8RTCSdpType::Enum::kOffer:
+ sdp = last_offer_;
+ break;
+ case V8RTCSdpType::Enum::kPranswer:
+ case V8RTCSdpType::Enum::kAnswer:
+ sdp = last_answer_;
+ break;
+ case V8RTCSdpType::Enum::kRollback:
+ break;
}
}
- ParsedSessionDescription parsed_sdp =
- ParsedSessionDescription::Parse(session_description_init->type(), sdp);
- if (session_description_init->type() != "rollback") {
+ ParsedSessionDescription parsed_sdp = ParsedSessionDescription::Parse(
+ session_description_init->hasType()
+ ? session_description_init->type().AsString()
+ : String(),
+ sdp);
+ if (!session_description_init->hasType() ||
+ session_description_init->type() != V8RTCSdpType::Enum::kRollback) {
RecordSdpCategoryAndMaybeEmitWarnings(parsed_sdp);
ReportSetSdpUsage(SetSdpOperationType::kSetLocalDescription, parsed_sdp);
}
@@ -1497,7 +1528,8 @@ ScriptPromise RTCPeerConnection::setLocalDescription(
WebFeature::
kRTCPeerConnectionSetLocalDescriptionLegacyNoFailureCallback);
}
- if (session_description_init->type() != "rollback") {
+ if (!session_description_init->hasType() ||
+ session_description_init->type() != V8RTCSdpType::Enum::kRollback) {
DOMException* exception = checkSdpForStateErrors(context, parsed_sdp);
if (exception) {
if (error_callback)
@@ -1542,7 +1574,8 @@ ScriptPromise RTCPeerConnection::setRemoteDescription(
DCHECK(script_state->ContextIsValid());
ParsedSessionDescription parsed_sdp =
ParsedSessionDescription::Parse(session_description_init);
- if (session_description_init->type() != "rollback") {
+ if (!session_description_init->hasType() ||
+ session_description_init->type() != V8RTCSdpType::Enum::kRollback) {
RecordSdpCategoryAndMaybeEmitWarnings(parsed_sdp);
ReportSetSdpUsage(SetSdpOperationType::kSetRemoteDescription, parsed_sdp);
}
@@ -1592,7 +1625,8 @@ ScriptPromise RTCPeerConnection::setRemoteDescription(
DCHECK(script_state->ContextIsValid());
ParsedSessionDescription parsed_sdp =
ParsedSessionDescription::Parse(session_description_init);
- if (session_description_init->type() != "rollback") {
+ if (!session_description_init->hasType() ||
+ session_description_init->type() != V8RTCSdpType::Enum::kRollback) {
RecordSdpCategoryAndMaybeEmitWarnings(parsed_sdp);
ReportSetSdpUsage(SetSdpOperationType::kSetRemoteDescription, parsed_sdp);
}
@@ -1708,13 +1742,13 @@ RTCConfiguration* RTCPeerConnection::getConfiguration(
for (const auto& webrtc_server : webrtc_configuration.servers) {
auto* ice_server = RTCIceServer::Create();
- StringOrStringSequence urls;
Vector<String> url_vector;
url_vector.ReserveCapacity(SafeCast<wtf_size_t>(webrtc_server.urls.size()));
for (const auto& url : webrtc_server.urls) {
url_vector.emplace_back(url.c_str());
}
- urls.SetStringSequence(std::move(url_vector));
+ auto* urls = MakeGarbageCollected<V8UnionStringOrStringSequence>(
+ std::move(url_vector));
ice_server->setUrls(urls);
ice_server->setUsername(webrtc_server.username.c_str());
@@ -1791,22 +1825,12 @@ void RTCPeerConnection::setConfiguration(
ScriptPromise RTCPeerConnection::generateCertificate(
ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8AlgorithmIdentifier* keygen_algorithm_arg,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier& keygen_algorithm_arg,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8AlgorithmIdentifier* keygen_algorithm,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8AlgorithmIdentifier* keygen_algorithm = keygen_algorithm_arg;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const AlgorithmIdentifier* keygen_algorithm = &keygen_algorithm_arg;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
// Normalize |keygenAlgorithm| with WebCrypto, making sure it is a recognized
// AlgorithmIdentifier.
WebCryptoAlgorithm crypto_algorithm;
- if (!NormalizeAlgorithm(script_state->GetIsolate(), keygen_algorithm_arg,
+ if (!NormalizeAlgorithm(script_state->GetIsolate(), keygen_algorithm,
kWebCryptoOperationGenerateKey, crypto_algorithm,
exception_state)) {
return ScriptPromise();
@@ -2386,11 +2410,7 @@ const HeapVector<Member<RTCRtpReceiver>>& RTCPeerConnection::getReceivers()
}
RTCRtpTransceiver* RTCPeerConnection::addTransceiver(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionMediaStreamTrackOrString* track_or_kind,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const MediaStreamTrackOrString& track_or_kind,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const RTCRtpTransceiverInit* init,
ExceptionState& exception_state) {
if (sdp_semantics_ != webrtc::SdpSemantics::kUnifiedPlan) {
@@ -2417,7 +2437,6 @@ RTCRtpTransceiver* RTCPeerConnection::addTransceiver(
}
webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>> result =
webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (track_or_kind->GetContentType()) {
case V8UnionMediaStreamTrackOrString::ContentType::kMediaStreamTrack: {
MediaStreamTrack* track = track_or_kind->GetAsMediaStreamTrack();
@@ -2446,31 +2465,6 @@ RTCRtpTransceiver* RTCPeerConnection::addTransceiver(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- 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.
- 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));
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!result.ok()) {
ThrowExceptionFromRTCError(result.error(), exception_state);
return nullptr;
@@ -2675,7 +2669,7 @@ RTCDataChannel* RTCPeerConnection::createDataChannel(
MediaStreamTrack* RTCPeerConnection::GetTrack(
MediaStreamComponent* component) const {
- return tracks_.at(component);
+ return tracks_.DeprecatedAtOrEmptyValue(component);
}
RTCRtpSender* RTCPeerConnection::FindSenderForTrackAndStream(
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 72baa89a58e..0d077326d5e 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
@@ -62,7 +62,6 @@ namespace blink {
class ExceptionState;
class MediaStreamTrack;
-class MediaStreamTrackOrString;
class RTCAnswerOptions;
class RTCConfiguration;
class RTCDTMFSender;
@@ -207,17 +206,10 @@ class MODULES_EXPORT RTCPeerConnection final
// Certificate management
// http://w3c.github.io/webrtc-pc/#sec.cert-mgmt
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static ScriptPromise generateCertificate(
ScriptState* script_state,
const V8AlgorithmIdentifier* keygen_algorithm,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static ScriptPromise generateCertificate(
- ScriptState*,
- const AlgorithmIdentifier& keygen_algorithm,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise addIceCandidate(ScriptState*,
const RTCIceCandidateInit*,
@@ -278,16 +270,10 @@ class MODULES_EXPORT RTCPeerConnection final
const HeapVector<Member<RTCRtpTransceiver>>& getTransceivers() const;
const HeapVector<Member<RTCRtpSender>>& getSenders() const;
const HeapVector<Member<RTCRtpReceiver>>& getReceivers() const;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
RTCRtpTransceiver* addTransceiver(
const V8UnionMediaStreamTrackOrString* track_or_kind,
const RTCRtpTransceiverInit* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- RTCRtpTransceiver* addTransceiver(const MediaStreamTrackOrString&,
- const RTCRtpTransceiverInit*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
RTCRtpSender* addTrack(MediaStreamTrack*, MediaStreamVector, ExceptionState&);
void removeTrack(RTCRtpSender*, ExceptionState&);
DEFINE_ATTRIBUTE_EVENT_LISTENER(track, kTrack)
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index e8cebd0061a..f99d8e726f4 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -20,7 +20,6 @@
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/threading/thread_checker.h"
#include "base/trace_event/trace_event.h"
#include "media/base/media_switches.h"
@@ -610,8 +609,11 @@ ParsedSessionDescription::ParsedSessionDescription(const String& sdp_type,
// static
ParsedSessionDescription ParsedSessionDescription::Parse(
const RTCSessionDescriptionInit* session_description_init) {
- ParsedSessionDescription temp(session_description_init->type(),
- session_description_init->sdp());
+ ParsedSessionDescription temp(
+ session_description_init->hasType()
+ ? session_description_init->type().AsString()
+ : String(),
+ session_description_init->sdp());
temp.DoParse();
return temp;
}
@@ -2778,4 +2780,5 @@ void RTCPeerConnectionHandler::ResetUMAStats() {
ice_connection_checking_start_ = base::TimeTicks();
memset(ice_state_seen_, 0, sizeof(ice_state_seen_));
}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
index 7eda91c76e4..000df302160 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
@@ -255,11 +255,28 @@ std::vector<T> ToSequence(T value) {
}
template <typename T>
+std::map<std::string, T> ToMap(const std::string& key, T value) {
+ std::map<std::string, T> map;
+ map[key] = value;
+ return map;
+}
+
+template <typename T>
void ExpectSequenceEquals(const Vector<T>& sequence, T value) {
EXPECT_EQ(sequence.size(), static_cast<size_t>(1));
EXPECT_EQ(sequence[0], value);
}
+template <typename T>
+void ExpectMapEquals(const HashMap<String, T>& map,
+ const String& key,
+ T value) {
+ EXPECT_EQ(map.size(), static_cast<size_t>(1));
+ auto it = map.find(key);
+ EXPECT_NE(it, map.end());
+ EXPECT_EQ(it->value, value);
+}
+
class RTCPeerConnectionHandlerUnderTest : public RTCPeerConnectionHandler {
public:
RTCPeerConnectionHandlerUnderTest(
@@ -934,6 +951,8 @@ TEST_F(RTCPeerConnectionHandlerTest, GetRTCStats) {
stats_defined_members->m_sequence_uint64 = ToSequence<uint64_t>(42);
stats_defined_members->m_sequence_double = ToSequence<double>(42);
stats_defined_members->m_sequence_string = ToSequence<std::string>("42");
+ stats_defined_members->m_map_string_uint64 = ToMap<uint64_t>("42", 42);
+ stats_defined_members->m_map_string_double = ToMap<double>("42", 42.0);
report->AddStats(
std::unique_ptr<const webrtc::RTCStats>(stats_defined_members.release()));
@@ -1019,11 +1038,19 @@ TEST_F(RTCPeerConnectionHandlerTest, GetRTCStats) {
ExpectSequenceEquals(member->ValueSequenceString(),
String::FromUTF8("42"));
break;
+ case webrtc::RTCStatsMemberInterface::kMapStringUint64:
+ ExpectMapEquals(member->ValueMapStringUint64(),
+ String::FromUTF8("42"), static_cast<uint64_t>(42));
+ break;
+ case webrtc::RTCStatsMemberInterface::kMapStringDouble:
+ ExpectMapEquals(member->ValueMapStringDouble(),
+ String::FromUTF8("42"), 42.0);
+ break;
default:
NOTREACHED();
}
}
- EXPECT_EQ(members.size(), static_cast<size_t>(14));
+ EXPECT_EQ(members.size(), static_cast<size_t>(16));
} else {
NOTREACHED();
}
@@ -1298,7 +1325,7 @@ TEST_F(RTCPeerConnectionHandlerTest, ThermalResourceDefaultValue) {
EXPECT_TRUE(mock_peer_connection_->adaptation_resources().IsEmpty());
pc_handler_->OnThermalStateChange(
mojom::blink::DeviceThermalState::kCritical);
-#if defined(OS_MAC)
+#if defined(OS_MAC) || defined(OS_CHROMEOS)
bool expect_disabled = false;
#else
bool expect_disabled = true;
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 666b424d4e2..e54817eee42 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
@@ -391,16 +391,10 @@ class RTCPeerConnectionTest : public testing::Test {
public:
RTCPeerConnection* CreatePC(
V8TestingScope& scope,
- const absl::optional<String>& sdp_semantics = absl::nullopt,
- bool force_encoded_audio_insertable_streams = false,
- bool force_encoded_video_insertable_streams = false) {
+ const absl::optional<String>& sdp_semantics = absl::nullopt) {
RTCConfiguration* config = RTCConfiguration::Create();
if (sdp_semantics)
config->setSdpSemantics(sdp_semantics.value());
- config->setForceEncodedAudioInsertableStreams(
- force_encoded_audio_insertable_streams);
- config->setForceEncodedVideoInsertableStreams(
- force_encoded_video_insertable_streams);
RTCIceServer* ice_server = RTCIceServer::Create();
ice_server->setUrl("stun:fake.stun.url");
HeapVector<Member<RTCIceServer>> ice_servers;
@@ -676,21 +670,6 @@ TEST_F(RTCPeerConnectionTest, CheckForComplexSdpWithSdpSemanticsUnspecified) {
pc->CheckForComplexSdp(ParsedSessionDescription::Parse(sdp)).has_value());
}
-TEST_F(RTCPeerConnectionTest, CheckInsertableStreamsConfig) {
- for (bool force_encoded_audio_insertable_streams : {true, false}) {
- for (bool force_encoded_video_insertable_streams : {true, false}) {
- V8TestingScope scope;
- Persistent<RTCPeerConnection> pc =
- CreatePC(scope, absl::nullopt, force_encoded_audio_insertable_streams,
- force_encoded_video_insertable_streams);
- EXPECT_EQ(pc->force_encoded_audio_insertable_streams(),
- force_encoded_audio_insertable_streams);
- EXPECT_EQ(pc->force_encoded_video_insertable_streams(),
- force_encoded_video_insertable_streams);
- }
- }
-}
-
enum class AsyncOperationAction {
kLeavePending,
kResolve,
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 bf483ca567e..9291c4f8a10 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
@@ -23,6 +23,8 @@
#include "third_party/blink/renderer/modules/peerconnection/identifiability_metrics.h"
#include "third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_sink_optimizer.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_receiver_source_optimizer.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_source.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h"
@@ -33,7 +35,6 @@
#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/heap/persistent.h"
-#include "third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
@@ -49,7 +50,8 @@ RTCRtpReceiver::RTCRtpReceiver(RTCPeerConnection* pc,
MediaStreamVector streams,
bool force_encoded_audio_insertable_streams,
bool force_encoded_video_insertable_streams)
- : pc_(pc),
+ : ExecutionContextLifecycleObserver(pc->GetExecutionContext()),
+ pc_(pc),
receiver_(std::move(receiver)),
track_(track),
streams_(std::move(streams)),
@@ -60,17 +62,22 @@ RTCRtpReceiver::RTCRtpReceiver(RTCPeerConnection* pc,
DCHECK(pc_);
DCHECK(receiver_);
DCHECK(track_);
- if (force_encoded_audio_insertable_streams_ && track_->kind() == "audio")
+ if (force_encoded_audio_insertable_streams_ && track_->kind() == "audio") {
+ encoded_audio_transformer_ =
+ receiver_->GetEncodedAudioStreamTransformer()->GetBroker();
RegisterEncodedAudioStreamCallback();
+ }
if (force_encoded_video_insertable_streams_ && track_->kind() == "video")
RegisterEncodedVideoStreamCallback();
}
MediaStreamTrack* RTCRtpReceiver::track() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return track_;
}
RTCDtlsTransport* RTCRtpReceiver::transport() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return transport_;
}
@@ -80,11 +87,13 @@ RTCDtlsTransport* RTCRtpReceiver::rtcpTransport() {
}
absl::optional<double> RTCRtpReceiver::playoutDelayHint() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return playout_delay_hint_;
}
void RTCRtpReceiver::setPlayoutDelayHint(absl::optional<double> hint,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (hint.has_value() && hint.value() < 0.0) {
exception_state.ThrowTypeError("playoutDelayHint can't be negative");
return;
@@ -97,6 +106,7 @@ void RTCRtpReceiver::setPlayoutDelayHint(absl::optional<double> hint,
HeapVector<Member<RTCRtpSynchronizationSource>>
RTCRtpReceiver::getSynchronizationSources(ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!script_state->ContextIsValid()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Window is detached");
@@ -139,6 +149,7 @@ RTCRtpReceiver::getSynchronizationSources(ScriptState* script_state,
HeapVector<Member<RTCRtpContributingSource>>
RTCRtpReceiver::getContributingSources(ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!script_state->ContextIsValid()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Window is detached");
@@ -179,6 +190,7 @@ RTCRtpReceiver::getContributingSources(ScriptState* script_state,
}
ScriptPromise RTCRtpReceiver::getStats(ScriptState* script_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
receiver_->GetStats(
@@ -190,6 +202,7 @@ ScriptPromise RTCRtpReceiver::getStats(ScriptState* script_state) {
RTCInsertableStreams* RTCRtpReceiver::createEncodedStreams(
ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (track_->kind() == "audio")
return createEncodedAudioStreams(script_state, exception_state);
DCHECK_EQ(track_->kind(), "video");
@@ -199,6 +212,7 @@ RTCInsertableStreams* RTCRtpReceiver::createEncodedStreams(
RTCInsertableStreams* RTCRtpReceiver::createEncodedAudioStreams(
ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!force_encoded_audio_insertable_streams_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -218,6 +232,7 @@ RTCInsertableStreams* RTCRtpReceiver::createEncodedAudioStreams(
RTCInsertableStreams* RTCRtpReceiver::createEncodedVideoStreams(
ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!force_encoded_video_insertable_streams_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -235,26 +250,32 @@ RTCInsertableStreams* RTCRtpReceiver::createEncodedVideoStreams(
}
RTCRtpReceiverPlatform* RTCRtpReceiver::platform_receiver() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return receiver_.get();
}
MediaStreamVector RTCRtpReceiver::streams() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return streams_;
}
void RTCRtpReceiver::set_streams(MediaStreamVector streams) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
streams_ = std::move(streams);
}
void RTCRtpReceiver::set_transceiver(RTCRtpTransceiver* transceiver) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
transceiver_ = transceiver;
}
void RTCRtpReceiver::set_transport(RTCDtlsTransport* transport) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
transport_ = transport;
}
void RTCRtpReceiver::UpdateSourcesIfNeeded() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!web_sources_needs_updating_)
return;
web_sources_ = receiver_->GetSources();
@@ -269,7 +290,19 @@ void RTCRtpReceiver::UpdateSourcesIfNeeded() {
WrapWeakPersistent(this)));
}
+void RTCRtpReceiver::ContextDestroyed() {
+ {
+ WTF::MutexLocker locker(audio_underlying_source_mutex_);
+ audio_from_depacketizer_underlying_source_.Clear();
+ }
+ {
+ WTF::MutexLocker locker(audio_underlying_sink_mutex_);
+ audio_to_decoder_underlying_sink_.Clear();
+ }
+}
+
void RTCRtpReceiver::SetContributingSourcesNeedsUpdating() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
web_sources_needs_updating_ = true;
}
@@ -279,13 +312,12 @@ void RTCRtpReceiver::Trace(Visitor* visitor) const {
visitor->Trace(transport_);
visitor->Trace(streams_);
visitor->Trace(transceiver_);
- visitor->Trace(audio_from_depacketizer_underlying_source_);
- visitor->Trace(audio_to_decoder_underlying_sink_);
visitor->Trace(encoded_audio_streams_);
visitor->Trace(video_from_depacketizer_underlying_source_);
visitor->Trace(video_to_decoder_underlying_sink_);
visitor->Trace(encoded_video_streams_);
ScriptWrappable::Trace(visitor);
+ ExecutionContextLifecycleObserver::Trace(visitor);
}
RTCRtpCapabilities* RTCRtpReceiver::getCapabilities(ScriptState* state,
@@ -350,6 +382,7 @@ RTCRtpCapabilities* RTCRtpReceiver::getCapabilities(ScriptState* state,
}
RTCRtpReceiveParameters* RTCRtpReceiver::getParameters() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
RTCRtpReceiveParameters* parameters = RTCRtpReceiveParameters::Create();
std::unique_ptr<webrtc::RtpParameters> webrtc_parameters =
receiver_->GetParameters();
@@ -390,72 +423,116 @@ RTCRtpReceiveParameters* RTCRtpReceiver::getParameters() {
}
void RTCRtpReceiver::RegisterEncodedAudioStreamCallback() {
- DCHECK(!platform_receiver()
- ->GetEncodedAudioStreamTransformer()
- ->HasTransformerCallback());
- DCHECK_EQ(track_->kind(), "audio");
- platform_receiver()
- ->GetEncodedAudioStreamTransformer()
- ->SetTransformerCallback(
- WTF::BindRepeating(&RTCRtpReceiver::OnAudioFrameFromDepacketizer,
- WrapWeakPersistent(this)));
+ encoded_audio_transformer_->SetTransformerCallback(
+ WTF::CrossThreadBindRepeating(
+ &RTCRtpReceiver::OnAudioFrameFromDepacketizer,
+ WrapCrossThreadWeakPersistent(this)));
}
void RTCRtpReceiver::UnregisterEncodedAudioStreamCallback() {
- DCHECK_EQ(track_->kind(), "audio");
- platform_receiver()
- ->GetEncodedAudioStreamTransformer()
- ->ResetTransformerCallback();
+ encoded_audio_transformer_->ResetTransformerCallback();
+}
+
+void RTCRtpReceiver::SetAudioUnderlyingSource(
+ RTCEncodedAudioUnderlyingSource* new_underlying_source,
+ scoped_refptr<base::SingleThreadTaskRunner> new_source_task_runner) {
+ if (!GetExecutionContext()) {
+ // If our context is destroyed, then the RTCRtpReceiver, underlying
+ // source(s), and transformer are about to be garbage collected, so there's
+ // no reason to continue.
+ return;
+ }
+ {
+ WTF::MutexLocker locker(audio_underlying_source_mutex_);
+ audio_from_depacketizer_underlying_source_->OnSourceTransferStarted();
+ audio_from_depacketizer_underlying_source_ = new_underlying_source;
+ }
+
+ encoded_audio_transformer_->SetSourceTaskRunner(
+ std::move(new_source_task_runner));
+}
+
+void RTCRtpReceiver::SetAudioUnderlyingSink(
+ RTCEncodedAudioUnderlyingSink* new_underlying_sink) {
+ if (!GetExecutionContext()) {
+ // If our context is destroyed, then the RTCRtpReceiver and underlying
+ // sink(s) are about to be garbage collected, so there's no reason to
+ // continue.
+ return;
+ }
+ WTF::MutexLocker locker(audio_underlying_sink_mutex_);
+ audio_to_decoder_underlying_sink_ = new_underlying_sink;
}
void RTCRtpReceiver::InitializeEncodedAudioStreams(ScriptState* script_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!encoded_audio_streams_);
- DCHECK(!audio_from_depacketizer_underlying_source_);
- DCHECK(!audio_to_decoder_underlying_sink_);
DCHECK(force_encoded_audio_insertable_streams_);
encoded_audio_streams_ = RTCInsertableStreams::Create();
- // Set up readable.
- audio_from_depacketizer_underlying_source_ =
- MakeGarbageCollected<RTCEncodedAudioUnderlyingSource>(
- script_state,
- WTF::Bind(&RTCRtpReceiver::UnregisterEncodedAudioStreamCallback,
- WrapWeakPersistent(this)),
- /*is_receiver=*/true);
- // The high water mark for the readable stream is set to 0 so that frames are
- // removed from the queue right away, without introducing a new buffer.
- ReadableStream* readable_stream =
- ReadableStream::CreateWithCountQueueingStrategy(
- script_state, audio_from_depacketizer_underlying_source_,
- /*high_water_mark=*/0);
- encoded_audio_streams_->setReadableStream(readable_stream);
- encoded_audio_streams_->setReadable(readable_stream);
+ {
+ WTF::MutexLocker locker(audio_underlying_source_mutex_);
+ DCHECK(!audio_from_depacketizer_underlying_source_);
+
+ // Set up readable.
+ audio_from_depacketizer_underlying_source_ =
+ MakeGarbageCollected<RTCEncodedAudioUnderlyingSource>(
+ script_state,
+ WTF::CrossThreadBindOnce(
+ &RTCRtpReceiver::UnregisterEncodedAudioStreamCallback,
+ WrapCrossThreadWeakPersistent(this)),
+ /*is_receiver=*/true);
+
+ auto set_underlying_source =
+ WTF::CrossThreadBindRepeating(&RTCRtpReceiver::SetAudioUnderlyingSource,
+ WrapCrossThreadWeakPersistent(this));
+ auto disconnect_callback = WTF::CrossThreadBindOnce(
+ &RTCRtpReceiver::UnregisterEncodedAudioStreamCallback,
+ WrapCrossThreadWeakPersistent(this));
+ // The high water mark for the readable stream is set to 0 so that frames
+ // are removed from the queue right away, without introducing a new buffer.
+ ReadableStream* readable_stream =
+ ReadableStream::CreateWithCountQueueingStrategy(
+ script_state, audio_from_depacketizer_underlying_source_,
+ /*high_water_mark=*/0, AllowPerChunkTransferring(false),
+ absl::make_unique<RtcEncodedAudioReceiverSourceOptimizer>(
+ std::move(set_underlying_source),
+ std::move(disconnect_callback)));
+ encoded_audio_streams_->setReadableStream(readable_stream);
+ encoded_audio_streams_->setReadable(readable_stream);
+ }
+
+ WritableStream* writable_stream;
+ {
+ WTF::MutexLocker locker(audio_underlying_sink_mutex_);
+ DCHECK(!audio_to_decoder_underlying_sink_);
+
+ // Set up writable.
+ audio_to_decoder_underlying_sink_ =
+ MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>(
+ script_state, encoded_audio_transformer_);
+
+ auto set_underlying_sink =
+ WTF::CrossThreadBindOnce(&RTCRtpReceiver::SetAudioUnderlyingSink,
+ WrapCrossThreadWeakPersistent(this));
+
+ // The high water mark for the stream is set to 1 so that the stream seems
+ // ready to write, but without queuing frames.
+ writable_stream = WritableStream::CreateWithCountQueueingStrategy(
+ script_state, audio_to_decoder_underlying_sink_,
+ /*high_water_mark=*/1,
+ absl::make_unique<RtcEncodedAudioReceiverSinkOptimizer>(
+ std::move(set_underlying_sink), encoded_audio_transformer_));
+ }
- // Set up writable.
- audio_to_decoder_underlying_sink_ =
- MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>(
- script_state,
- WTF::BindRepeating(
- [](RTCRtpReceiver* receiver)
- -> RTCEncodedAudioStreamTransformer* {
- return receiver ? receiver->platform_receiver()
- ->GetEncodedAudioStreamTransformer()
- : nullptr;
- },
- WrapWeakPersistent(this)));
- // The high water mark for the stream is set to 1 so that the stream seems
- // ready to write, but without queuing frames.
- WritableStream* writable_stream =
- WritableStream::CreateWithCountQueueingStrategy(
- script_state, audio_to_decoder_underlying_sink_,
- /*high_water_mark=*/1);
encoded_audio_streams_->setWritableStream(writable_stream);
encoded_audio_streams_->setWritable(writable_stream);
}
void RTCRtpReceiver::OnAudioFrameFromDepacketizer(
std::unique_ptr<webrtc::TransformableFrameInterface> encoded_audio_frame) {
+ WTF::MutexLocker locker(audio_underlying_source_mutex_);
if (audio_from_depacketizer_underlying_source_) {
audio_from_depacketizer_underlying_source_->OnFrameFromSource(
std::move(encoded_audio_frame));
@@ -463,6 +540,7 @@ void RTCRtpReceiver::OnAudioFrameFromDepacketizer(
}
void RTCRtpReceiver::RegisterEncodedVideoStreamCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!platform_receiver()
->GetEncodedVideoStreamTransformer()
->HasTransformerCallback());
@@ -475,6 +553,7 @@ void RTCRtpReceiver::RegisterEncodedVideoStreamCallback() {
}
void RTCRtpReceiver::UnregisterEncodedVideoStreamCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_EQ(track_->kind(), "video");
platform_receiver()
->GetEncodedVideoStreamTransformer()
@@ -482,6 +561,7 @@ void RTCRtpReceiver::UnregisterEncodedVideoStreamCallback() {
}
void RTCRtpReceiver::InitializeEncodedVideoStreams(ScriptState* script_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!encoded_video_streams_);
DCHECK(!video_from_depacketizer_underlying_source_);
DCHECK(!video_to_decoder_underlying_sink_);
@@ -529,6 +609,7 @@ void RTCRtpReceiver::InitializeEncodedVideoStreams(ScriptState* script_state) {
void RTCRtpReceiver::OnVideoFrameFromDepacketizer(
std::unique_ptr<webrtc::TransformableVideoFrameInterface>
encoded_video_frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (video_from_depacketizer_underlying_source_) {
video_from_depacketizer_underlying_source_->OnFrameFromSource(
std::move(encoded_video_frame));
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 f9dcde853a5..966bf93321e 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
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_contributing_source.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_receive_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_synchronization_source.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#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/platform/bindings/exception_state.h"
@@ -17,6 +18,7 @@
#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/peerconnection/rtc_encoded_audio_stream_transformer.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h"
@@ -32,7 +34,8 @@ class RTCRtpCapabilities;
class RTCRtpTransceiver;
// https://w3c.github.io/webrtc-pc/#rtcrtpreceiver-interface
-class RTCRtpReceiver final : public ScriptWrappable {
+class RTCRtpReceiver final : public ScriptWrappable,
+ public ExecutionContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -74,6 +77,9 @@ class RTCRtpReceiver final : public ScriptWrappable {
void set_transport(RTCDtlsTransport*);
void UpdateSourcesIfNeeded();
+ // ExecutionContextLifecycleObserver
+ void ContextDestroyed() override;
+
void Trace(Visitor*) const override;
private:
@@ -89,6 +95,11 @@ class RTCRtpReceiver final : public ScriptWrappable {
void OnVideoFrameFromDepacketizer(
std::unique_ptr<webrtc::TransformableVideoFrameInterface>
encoded_video_frame);
+ void SetAudioUnderlyingSource(
+ RTCEncodedAudioUnderlyingSource* new_underlying_source,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ void SetAudioUnderlyingSink(
+ RTCEncodedAudioUnderlyingSink* new_underlying_sink);
Member<RTCPeerConnection> pc_;
std::unique_ptr<RTCRtpReceiverPlatform> receiver_;
@@ -109,10 +120,17 @@ class RTCRtpReceiver final : public ScriptWrappable {
// Insertable Streams support for audio
bool force_encoded_audio_insertable_streams_;
- Member<RTCEncodedAudioUnderlyingSource>
- audio_from_depacketizer_underlying_source_;
- Member<RTCEncodedAudioUnderlyingSink> audio_to_decoder_underlying_sink_;
+ WTF::Mutex audio_underlying_source_mutex_;
+ CrossThreadPersistent<RTCEncodedAudioUnderlyingSource>
+ audio_from_depacketizer_underlying_source_
+ GUARDED_BY(audio_underlying_source_mutex_);
+ WTF::Mutex audio_underlying_sink_mutex_;
+ CrossThreadPersistent<RTCEncodedAudioUnderlyingSink>
+ audio_to_decoder_underlying_sink_
+ GUARDED_BY(audio_underlying_sink_mutex_);
Member<RTCInsertableStreams> encoded_audio_streams_;
+ scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
+ encoded_audio_transformer_;
// Insertable Streams support for video
bool force_encoded_video_insertable_streams_;
@@ -120,6 +138,8 @@ class RTCRtpReceiver final : public ScriptWrappable {
video_from_depacketizer_underlying_source_;
Member<RTCEncodedVideoUnderlyingSink> video_to_decoder_underlying_sink_;
Member<RTCInsertableStreams> encoded_video_streams_;
+
+ THREAD_CHECKER(thread_checker_);
};
} // namespace blink
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 11c46966554..49f35c9e16e 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
@@ -18,11 +18,4 @@ interface RTCRtpReceiver {
[Measure,
CallWith=ScriptState,
RaisesException] RTCInsertableStreams createEncodedStreams();
- [DeprecateAs=V8RTCRtpReceiver_CreateEncodedAudioStreams_Method,
- RuntimeEnabled=RTCInsertableStreams,
- CallWith=ScriptState, RaisesException] RTCInsertableStreams createEncodedAudioStreams();
- [DeprecateAs=V8RTCRtpReceiver_CreateEncodedVideoStreams_Method,
- RuntimeEnabled=RTCInsertableStreams,
- CallWith=ScriptState,
- RaisesException] RTCInsertableStreams createEncodedVideoStreams();
};
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 7612cd53039..d8e23c1d0fd 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
@@ -418,10 +418,12 @@ RTCRtpSender::RTCRtpSender(RTCPeerConnection* pc,
}
MediaStreamTrack* RTCRtpSender::track() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return track_;
}
RTCDtlsTransport* RTCRtpSender::transport() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return transport_;
}
@@ -432,6 +434,7 @@ RTCDtlsTransport* RTCRtpSender::rtcpTransport() {
ScriptPromise RTCRtpSender::replaceTrack(ScriptState* script_state,
MediaStreamTrack* with_track) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
if (pc_->IsClosed()) {
@@ -452,6 +455,7 @@ ScriptPromise RTCRtpSender::replaceTrack(ScriptState* script_state,
}
RTCRtpSendParameters* RTCRtpSender::getParameters() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
RTCRtpSendParameters* parameters = RTCRtpSendParameters::Create();
std::unique_ptr<webrtc::RtpParameters> webrtc_parameters =
sender_->GetParameters();
@@ -503,15 +507,9 @@ RTCRtpSendParameters* RTCRtpSender::getParameters() {
PriorityFromDouble(webrtc_encoding.bitrate_priority).c_str());
encoding->setNetworkPriority(
PriorityFromEnum(webrtc_encoding.network_priority).c_str());
- if (webrtc_encoding.num_temporal_layers) {
- if (*webrtc_encoding.num_temporal_layers == 2) {
- encoding->setScalabilityMode("L1T2");
- } else if (*webrtc_encoding.num_temporal_layers == 3) {
- encoding->setScalabilityMode("L1T3");
- } else {
- LOG(ERROR) << "Not understood value of num_temporal_layers: "
- << *webrtc_encoding.num_temporal_layers;
- }
+ if (webrtc_encoding.scalability_mode) {
+ encoding->setScalabilityMode(
+ webrtc_encoding.scalability_mode.value().c_str());
}
encoding->setAdaptivePtime(webrtc_encoding.adaptive_ptime);
encodings.push_back(encoding);
@@ -542,6 +540,7 @@ RTCRtpSendParameters* RTCRtpSender::getParameters() {
ScriptPromise RTCRtpSender::setParameters(
ScriptState* script_state,
const RTCRtpSendParameters* parameters) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
@@ -578,10 +577,12 @@ ScriptPromise RTCRtpSender::setParameters(
}
void RTCRtpSender::ClearLastReturnedParameters() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
last_returned_parameters_ = nullptr;
}
ScriptPromise RTCRtpSender::getStats(ScriptState* script_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
sender_->GetStats(
@@ -591,10 +592,12 @@ ScriptPromise RTCRtpSender::getStats(ScriptState* script_state) {
}
RTCRtpSenderPlatform* RTCRtpSender::web_sender() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return sender_.get();
}
void RTCRtpSender::SetTrack(MediaStreamTrack* track) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
track_ = track;
if (track) {
if (kind_.IsNull()) {
@@ -608,22 +611,27 @@ void RTCRtpSender::SetTrack(MediaStreamTrack* track) {
}
MediaStreamVector RTCRtpSender::streams() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return streams_;
}
void RTCRtpSender::set_streams(MediaStreamVector streams) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
streams_ = std::move(streams);
}
void RTCRtpSender::set_transceiver(RTCRtpTransceiver* transceiver) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
transceiver_ = transceiver;
}
void RTCRtpSender::set_transport(RTCDtlsTransport* transport) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
transport_ = transport;
}
RTCDTMFSender* RTCRtpSender::dtmf() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Lazy initialization of dtmf_ to avoid overhead when not used.
if (!dtmf_ && kind_ == "audio") {
auto handler = sender_->GetDtmfSender();
@@ -639,6 +647,7 @@ RTCDTMFSender* RTCRtpSender::dtmf() {
void RTCRtpSender::setStreams(HeapVector<Member<MediaStream>> streams,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (pc_->IsClosed()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -659,6 +668,7 @@ void RTCRtpSender::setStreams(HeapVector<Member<MediaStream>> streams,
RTCInsertableStreams* RTCRtpSender::createEncodedStreams(
ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (kind_ == "audio")
return createEncodedAudioStreams(script_state, exception_state);
DCHECK_EQ(kind_, "video");
@@ -668,6 +678,7 @@ RTCInsertableStreams* RTCRtpSender::createEncodedStreams(
RTCInsertableStreams* RTCRtpSender::createEncodedAudioStreams(
ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!force_encoded_audio_insertable_streams_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -687,6 +698,7 @@ RTCInsertableStreams* RTCRtpSender::createEncodedAudioStreams(
RTCInsertableStreams* RTCRtpSender::createEncodedVideoStreams(
ScriptState* script_state,
ExceptionState& exception_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!force_encoded_video_insertable_streams_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -818,20 +830,23 @@ RTCRtpCapabilities* RTCRtpSender::getCapabilities(ScriptState* state,
}
void RTCRtpSender::RegisterEncodedAudioStreamCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!web_sender()
->GetEncodedAudioStreamTransformer()
->HasTransformerCallback());
DCHECK_EQ(kind_, "audio");
web_sender()->GetEncodedAudioStreamTransformer()->SetTransformerCallback(
- WTF::BindRepeating(&RTCRtpSender::OnAudioFrameFromEncoder,
- WrapWeakPersistent(this)));
+ WTF::CrossThreadBindRepeating(&RTCRtpSender::OnAudioFrameFromEncoder,
+ WrapCrossThreadWeakPersistent(this)));
}
void RTCRtpSender::UnregisterEncodedAudioStreamCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
web_sender()->GetEncodedAudioStreamTransformer()->ResetTransformerCallback();
}
void RTCRtpSender::InitializeEncodedAudioStreams(ScriptState* script_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!audio_from_encoder_underlying_source_);
DCHECK(!audio_to_packetizer_underlying_sink_);
DCHECK(!encoded_audio_streams_);
@@ -843,8 +858,9 @@ void RTCRtpSender::InitializeEncodedAudioStreams(ScriptState* script_state) {
audio_from_encoder_underlying_source_ =
MakeGarbageCollected<RTCEncodedAudioUnderlyingSource>(
script_state,
- WTF::Bind(&RTCRtpSender::UnregisterEncodedAudioStreamCallback,
- WrapWeakPersistent(this)),
+ WTF::CrossThreadBindOnce(
+ &RTCRtpSender::UnregisterEncodedAudioStreamCallback,
+ WrapCrossThreadWeakPersistent(this)),
/*is_receiver=*/false);
// The high water mark for the readable stream is set to 0 so that frames are
// removed from the queue right away, without introducing any buffering.
@@ -859,13 +875,7 @@ void RTCRtpSender::InitializeEncodedAudioStreams(ScriptState* script_state) {
audio_to_packetizer_underlying_sink_ =
MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>(
script_state,
- WTF::BindRepeating(
- [](RTCRtpSender* sender) -> RTCEncodedAudioStreamTransformer* {
- return sender ? sender->web_sender()
- ->GetEncodedAudioStreamTransformer()
- : nullptr;
- },
- WrapWeakPersistent(this)));
+ web_sender()->GetEncodedAudioStreamTransformer()->GetBroker());
// The high water mark for the stream is set to 1 so that the stream is
// ready to write, but without queuing frames.
WritableStream* writable_stream =
@@ -878,12 +888,14 @@ void RTCRtpSender::InitializeEncodedAudioStreams(ScriptState* script_state) {
void RTCRtpSender::OnAudioFrameFromEncoder(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (audio_from_encoder_underlying_source_) {
audio_from_encoder_underlying_source_->OnFrameFromSource(std::move(frame));
}
}
void RTCRtpSender::RegisterEncodedVideoStreamCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!web_sender()
->GetEncodedVideoStreamTransformer()
->HasTransformerCallback());
@@ -894,10 +906,12 @@ void RTCRtpSender::RegisterEncodedVideoStreamCallback() {
}
void RTCRtpSender::UnregisterEncodedVideoStreamCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
web_sender()->GetEncodedVideoStreamTransformer()->ResetTransformerCallback();
}
void RTCRtpSender::InitializeEncodedVideoStreams(ScriptState* script_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!video_from_encoder_underlying_source_);
DCHECK(!video_to_packetizer_underlying_sink_);
DCHECK(!encoded_video_streams_);
@@ -943,6 +957,7 @@ void RTCRtpSender::InitializeEncodedVideoStreams(ScriptState* script_state) {
void RTCRtpSender::OnVideoFrameFromEncoder(
std::unique_ptr<webrtc::TransformableVideoFrameInterface> frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (video_from_encoder_underlying_source_) {
video_from_encoder_underlying_source_->OnFrameFromSource(std::move(frame));
}
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 edd0640ddb2..a37fb9e5f4f 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
@@ -126,6 +126,8 @@ class RTCRtpSender final : public ScriptWrappable {
Member<RTCEncodedVideoUnderlyingSource> video_from_encoder_underlying_source_;
Member<RTCEncodedVideoUnderlyingSink> video_to_packetizer_underlying_sink_;
Member<RTCInsertableStreams> encoded_video_streams_;
+
+ THREAD_CHECKER(thread_checker_);
};
} // 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 1dc5d9760ba..60b7a64f7bb 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
@@ -18,12 +18,4 @@ interface RTCRtpSender {
[Measure,
CallWith=ScriptState,
RaisesException] RTCInsertableStreams createEncodedStreams();
- [DeprecateAs=V8RTCRtpSender_CreateEncodedAudioStreams_Method,
- RuntimeEnabled=RTCInsertableStreams,
- CallWith=ScriptState,
- RaisesException] RTCInsertableStreams createEncodedAudioStreams();
- [DeprecateAs=V8RTCRtpSender_CreateEncodedVideoStreams_Method,
- RuntimeEnabled=RTCInsertableStreams,
- CallWith=ScriptState,
- RaisesException] RTCInsertableStreams createEncodedVideoStreams();
};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc
index 5bee8e86b9c..6b42cde98f4 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc
@@ -287,6 +287,9 @@ class RTCRtpSenderImpl::RTCRtpSenderInternal
new_parameters.encodings[i].rid = encoding.rid;
new_parameters.encodings[i].scale_resolution_down_by =
encoding.scale_resolution_down_by;
+ new_parameters.encodings[i].num_temporal_layers =
+ encoding.num_temporal_layers;
+ new_parameters.encodings[i].scalability_mode = encoding.scalability_mode;
new_parameters.encodings[i].adaptive_ptime = encoding.adaptive_ptime;
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
index 642a6586817..6f4bfd05880 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
@@ -142,10 +142,10 @@ class RTCRtpTransceiverImplTest : public ::testing::Test {
webrtc_transceiver->receiver().get(),
std::move(receiver_track_ref),
std::move(receiver_stream_ids)),
- blink::ToBaseOptional(webrtc_transceiver->mid()),
+ blink::ToAbslOptional(webrtc_transceiver->mid()),
webrtc_transceiver->stopped(), webrtc_transceiver->direction(),
- blink::ToBaseOptional(webrtc_transceiver->current_direction()),
- blink::ToBaseOptional(webrtc_transceiver->fired_direction()), {});
+ blink::ToAbslOptional(webrtc_transceiver->current_direction()),
+ blink::ToAbslOptional(webrtc_transceiver->fired_direction()), {});
}
protected:
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 27e6fe49357..61e8331f828 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
@@ -31,11 +31,11 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.h"
#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_session_description_init.h"
#include "third_party/blink/renderer/core/dom/dom_exception.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"
-#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description_init.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h"
namespace blink {
@@ -74,7 +74,8 @@ void RTCSessionDescriptionRequestImpl::RequestSucceeded(
requester_->NoteSessionDescriptionRequestCompleted(operation_, true);
RTCSessionDescriptionInit* description =
RTCSessionDescriptionInit::Create();
- description->setType(description_platform->GetType());
+ if (description_platform->GetType())
+ description->setType(description_platform->GetType());
description->setSdp(description_platform->Sdp());
requester_->NoteSdpCreated(
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc
index 8dd8c3506a4..3694a08f2c7 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc
@@ -15,6 +15,21 @@ namespace blink {
namespace {
+template <typename T>
+v8::Local<v8::Value> HashMapToValue(ScriptState* script_state,
+ HashMap<String, T>&& map) {
+ V8ObjectBuilder builder(script_state);
+ for (auto& it : map) {
+ builder.Add(it.key, it.value);
+ }
+ v8::Local<v8::Object> v8_object = builder.V8Value();
+ if (v8_object.IsEmpty()) {
+ NOTREACHED();
+ return v8::Undefined(script_state->GetIsolate());
+ }
+ return v8_object;
+}
+
v8::Local<v8::Value> RTCStatsToValue(ScriptState* script_state,
const RTCStats* stats) {
V8ObjectBuilder builder(script_state);
@@ -72,6 +87,14 @@ v8::Local<v8::Value> RTCStatsToValue(ScriptState* script_state,
case webrtc::RTCStatsMemberInterface::kSequenceString:
builder.Add(name, member->ValueSequenceString());
break;
+ case webrtc::RTCStatsMemberInterface::kMapStringUint64:
+ builder.Add(
+ name, HashMapToValue(script_state, member->ValueMapStringUint64()));
+ break;
+ case webrtc::RTCStatsMemberInterface::kMapStringDouble:
+ builder.Add(
+ name, HashMapToValue(script_state, member->ValueMapStringDouble()));
+ break;
default:
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/testing/mock_rtp_sender.h b/chromium/third_party/blink/renderer/modules/peerconnection/testing/mock_rtp_sender.h
index 4eeaac24340..bdf86572c6d 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/testing/mock_rtp_sender.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/testing/mock_rtp_sender.h
@@ -9,7 +9,6 @@
#include <vector>
#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/webrtc/api/media_stream_interface.h"
#include "third_party/webrtc/api/rtp_parameters.h"
#include "third_party/webrtc/api/rtp_sender_interface.h"
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/thermal_resource.cc b/chromium/third_party/blink/renderer/modules/peerconnection/thermal_resource.cc
index 23f74767657..8ad426a5c58 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/thermal_resource.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/thermal_resource.cc
@@ -17,7 +17,7 @@ const int kReportIntervalSeconds = 10;
const base::Feature kWebRtcThermalResource {
"WebRtcThermalResource",
-#if defined(OS_MAC)
+#if defined(OS_MAC) || defined(OS_CHROMEOS)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/thermal_uma_listener.h b/chromium/third_party/blink/renderer/modules/peerconnection/thermal_uma_listener.h
index 81ff5e3e050..b458d9be302 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/thermal_uma_listener.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/thermal_uma_listener.h
@@ -11,7 +11,6 @@
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc
index 91513506a3c..36bfd4d1031 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc
@@ -129,10 +129,10 @@ void TransceiverStateSurfacer::Initialize(
transceiver_states_.emplace_back(
main_task_runner_, signaling_task_runner_, webrtc_transceiver.get(),
std::move(sender_state), std::move(receiver_state),
- blink::ToBaseOptional(webrtc_transceiver->mid()),
+ blink::ToAbslOptional(webrtc_transceiver->mid()),
webrtc_transceiver->stopped(), webrtc_transceiver->direction(),
- blink::ToBaseOptional(webrtc_transceiver->current_direction()),
- blink::ToBaseOptional(webrtc_transceiver->fired_direction()),
+ blink::ToAbslOptional(webrtc_transceiver->current_direction()),
+ blink::ToAbslOptional(webrtc_transceiver->fired_direction()),
GetHeaderExtensionsNegotiated(webrtc_transceiver));
}
is_initialized_ = true;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
index b70f18f43b2..bfbf19c97f7 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
@@ -57,7 +57,7 @@ class MockAudioRendererSource : public blink::WebRtcAudioRendererSource {
MOCK_METHOD4(RenderData,
void(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds,
+ base::TimeDelta audio_delay,
base::TimeDelta* current_time));
MOCK_METHOD1(RemoveAudioRenderer, void(blink::WebRtcAudioRenderer* renderer));
MOCK_METHOD0(AudioRendererThreadStopped, void());
@@ -142,13 +142,15 @@ class MAYBE_WebRtcAudioRendererTest : public testing::Test {
web_view_(blink::WebView::Create(
/*client=*/nullptr,
/*is_hidden=*/false,
+ /*is_prerendering=*/false,
/*is_inside_portal=*/false,
/*compositing_enabled=*/false,
/*widgets_never_composited=*/false,
/*opener=*/nullptr,
mojo::NullAssociatedReceiver(),
*agent_group_scheduler_,
- /*session_storage_namespace_id=*/base::EmptyString())),
+ /*session_storage_namespace_id=*/base::EmptyString(),
+ /*page_base_background_color=*/absl::nullopt)),
web_local_frame_(
blink::WebLocalFrame::CreateMainFrame(web_view_,
&web_local_frame_client_,
diff --git a/chromium/third_party/blink/renderer/modules/permissions/idls.gni b/chromium/third_party/blink/renderer/modules/permissions/idls.gni
deleted file mode 100644
index 7512276091b..00000000000
--- a/chromium/third_party/blink/renderer/modules/permissions/idls.gni
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "permission_status.idl",
- "permissions.idl",
-]
-
-modules_dictionary_idl_files = [
- "clipboard_permission_descriptor.idl",
- "midi_permission_descriptor.idl",
- "permission_descriptor.idl",
- "push_permission_descriptor.idl",
- "camera_device_permission_descriptor.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_permissions.idl",
- "worker_navigator_permissions.idl",
-]
-
-modules_testing_dependency_idl_files = [ "testing/internals_permission.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc b/chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc
index af8dba5241d..2bc01fe5815 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc
@@ -236,11 +236,6 @@ PermissionDescriptorPtr ParsePermissionDescriptor(
return CreatePermissionDescriptor(PermissionName::FONT_ACCESS);
}
if (name == "display-capture") {
- if (!RuntimeEnabledFeatures::DisplayCapturePermissionPolicyEnabled(
- ExecutionContext::From(script_state))) {
- exception_state.ThrowTypeError("Display Capture is not enabled.");
- return nullptr;
- }
return CreatePermissionDescriptor(PermissionName::DISPLAY_CAPTURE);
}
if (name == "file-handling") {
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permissions.cc b/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
index 798a522419f..ed8f7b00832 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/metrics/histogram_functions.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/idls.gni b/chromium/third_party/blink/renderer/modules/picture_in_picture/idls.gni
deleted file mode 100644
index e678f0079c1..00000000000
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/idls.gni
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "picture_in_picture_event.idl",
- "picture_in_picture_window.idl",
-]
-
-modules_dictionary_idl_files = [
- "picture_in_picture_event_init.idl",
- "picture_in_picture_options.idl",
-]
-
-modules_dependency_idl_files = [
- "document_picture_in_picture.idl",
- "html_element_picture_in_picture.idl",
- "html_video_element_picture_in_picture.idl",
- "shadow_root_picture_in_picture.idl",
-]
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 244f2d04f78..027e3eabdf4 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
@@ -12,6 +12,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/media/display_type.h"
+#include "third_party/blink/public/common/scheme_registry.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_options.h"
@@ -27,6 +28,7 @@
#include "third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/widget/frame_widget.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -168,6 +170,7 @@ void PictureInPictureControllerImpl::EnterPictureInPicture(
Fullscreen::ExitFullscreen(*GetSupplementable());
video_element->GetWebMediaPlayer()->OnRequestPictureInPicture();
+ DCHECK(video_element->GetWebMediaPlayer()->GetSurfaceId().has_value());
session_observer_receiver_.reset();
@@ -186,7 +189,7 @@ void PictureInPictureControllerImpl::EnterPictureInPicture(
picture_in_picture_service_->StartSession(
video_element->GetWebMediaPlayer()->GetDelegateId(),
std::move(media_player_remote),
- video_element->GetWebMediaPlayer()->GetSurfaceId(),
+ video_element->GetWebMediaPlayer()->GetSurfaceId().value(),
video_element->GetWebMediaPlayer()->NaturalSize(),
ShouldShowPlayPauseButton(*video_element), std::move(session_observer),
WTF::Bind(&PictureInPictureControllerImpl::OnEnteredPictureInPicture,
@@ -339,7 +342,8 @@ bool PictureInPictureControllerImpl::IsEnterAutoPictureInPictureAllowed()
GetSupplementable()->GetFrame()->GetWidgetForLocalRoot()->DisplayMode();
is_in_pwa_window = display_mode != mojom::blink::DisplayMode::kBrowser;
}
- if (!(GetSupplementable()->Url().ProtocolIs("chrome-extension") ||
+ if (!(CommonSchemeRegistry::IsExtensionScheme(
+ GetSupplementable()->Url().Protocol().Ascii()) ||
Fullscreen::FullscreenElementFrom(*GetSupplementable()) ||
(is_in_pwa_window && GetSupplementable()->IsInWebAppScope()))) {
return false;
@@ -396,6 +400,9 @@ void PictureInPictureControllerImpl::PageVisibilityChanged() {
void PictureInPictureControllerImpl::OnPictureInPictureStateChange() {
DCHECK(picture_in_picture_element_);
DCHECK(picture_in_picture_element_->GetWebMediaPlayer());
+ DCHECK(picture_in_picture_element_->GetWebMediaPlayer()
+ ->GetSurfaceId()
+ .has_value());
// The lifetime of the MediaPlayer mojo endpoint in the renderer is tied to
// WebMediaPlayer, which is recreated by |picture_in_picture_element_| on
@@ -409,7 +416,7 @@ void PictureInPictureControllerImpl::OnPictureInPictureStateChange() {
picture_in_picture_session_->Update(
picture_in_picture_element_->GetWebMediaPlayer()->GetDelegateId(),
std::move(media_player_remote),
- picture_in_picture_element_->GetWebMediaPlayer()->GetSurfaceId(),
+ picture_in_picture_element_->GetWebMediaPlayer()->GetSurfaceId().value(),
picture_in_picture_element_->GetWebMediaPlayer()->NaturalSize(),
ShouldShowPlayPauseButton(*picture_in_picture_element_));
}
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
index 80e3875ebed..2da5301877d 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
@@ -32,6 +32,13 @@ using ::testing::_;
namespace blink {
+viz::SurfaceId TestSurfaceId() {
+ // Use a fake but valid viz::SurfaceId.
+ return {viz::FrameSinkId(1, 1),
+ viz::LocalSurfaceId(
+ 11, base::UnguessableToken::Deserialize(0x111111, 0))};
+}
+
// The MockPictureInPictureSession implements a PictureInPicture session in the
// same process as the test and guarantees that the callbacks are called in
// order for the events to be fired.
@@ -47,14 +54,14 @@ class MockPictureInPictureSession
}
~MockPictureInPictureSession() override = default;
- MOCK_METHOD1(Stop, void(StopCallback));
- MOCK_METHOD5(
- Update,
- void(uint32_t,
- mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>,
- const absl::optional<viz::SurfaceId>&,
- const gfx::Size&,
- bool));
+ MOCK_METHOD(void, Stop, (StopCallback));
+ MOCK_METHOD(void,
+ Update,
+ (uint32_t,
+ mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>,
+ const viz::SurfaceId&,
+ const gfx::Size&,
+ bool));
private:
mojo::Receiver<mojom::blink::PictureInPictureSession> receiver_;
@@ -82,22 +89,23 @@ class MockPictureInPictureService
session_remote_.InitWithNewPipeAndPassReceiver());
}
- MOCK_METHOD7(
+ MOCK_METHOD(
+ void,
StartSession,
- void(uint32_t,
- mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>,
- const absl::optional<viz::SurfaceId>&,
- const gfx::Size&,
- bool,
- mojo::PendingRemote<mojom::blink::PictureInPictureSessionObserver>,
- StartSessionCallback));
+ (uint32_t,
+ mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>,
+ const viz::SurfaceId&,
+ const gfx::Size&,
+ bool,
+ mojo::PendingRemote<mojom::blink::PictureInPictureSessionObserver>,
+ StartSessionCallback));
MockPictureInPictureSession& Session() { return *session_.get(); }
void StartSessionInternal(
uint32_t,
mojo::PendingAssociatedRemote<media::mojom::blink::MediaPlayer>,
- const absl::optional<viz::SurfaceId>&,
+ const viz::SurfaceId&,
const gfx::Size&,
bool,
mojo::PendingRemote<mojom::blink::PictureInPictureSessionObserver>,
@@ -130,24 +138,26 @@ class PictureInPictureControllerFrameClient
DISALLOW_COPY_AND_ASSIGN(PictureInPictureControllerFrameClient);
};
-class PictureInPictureControllerPlayer : public EmptyWebMediaPlayer {
+class PictureInPictureControllerPlayer final : public EmptyWebMediaPlayer {
public:
PictureInPictureControllerPlayer() = default;
- ~PictureInPictureControllerPlayer() final = default;
+ ~PictureInPictureControllerPlayer() override = default;
- double Duration() const final {
+ double Duration() const override {
if (infinity_duration_)
return std::numeric_limits<double>::infinity();
return EmptyWebMediaPlayer::Duration();
}
-
- ReadyState GetReadyState() const final { return kReadyStateHaveMetadata; }
- bool HasVideo() const final { return true; }
+ ReadyState GetReadyState() const override { return kReadyStateHaveMetadata; }
+ bool HasVideo() const override { return true; }
+ void OnRequestPictureInPicture() override { surface_id_ = TestSurfaceId(); }
+ absl::optional<viz::SurfaceId> GetSurfaceId() override { return surface_id_; }
void set_infinity_duration(bool value) { infinity_duration_ = value; }
private:
bool infinity_duration_ = false;
+ absl::optional<viz::SurfaceId> surface_id_;
DISALLOW_COPY_AND_ASSIGN(PictureInPictureControllerPlayer);
};
@@ -193,7 +203,7 @@ class PictureInPictureControllerTest : public PageTestBase {
private:
Persistent<HTMLVideoElement> video_;
- MockPictureInPictureService mock_service_;
+ testing::NiceMock<MockPictureInPictureService> mock_service_;
scoped_refptr<cc::Layer> layer_;
};
@@ -203,7 +213,7 @@ TEST_F(PictureInPictureControllerTest, EnterPictureInPictureFiresEvent) {
WebMediaPlayer* player = Video()->GetWebMediaPlayer();
EXPECT_CALL(Service(),
- StartSession(player->GetDelegateId(), _, player->GetSurfaceId(),
+ StartSession(player->GetDelegateId(), _, TestSurfaceId(),
player->NaturalSize(), true, _, _));
PictureInPictureControllerImpl::From(GetDocument())
@@ -223,7 +233,7 @@ TEST_F(PictureInPictureControllerTest, ExitPictureInPictureFiresEvent) {
WebMediaPlayer* player = Video()->GetWebMediaPlayer();
EXPECT_CALL(Service(),
- StartSession(player->GetDelegateId(), _, player->GetSurfaceId(),
+ StartSession(player->GetDelegateId(), _, TestSurfaceId(),
player->NaturalSize(), true, _, _));
PictureInPictureControllerImpl::From(GetDocument())
@@ -251,7 +261,7 @@ TEST_F(PictureInPictureControllerTest, StartObserving) {
WebMediaPlayer* player = Video()->GetWebMediaPlayer();
EXPECT_CALL(Service(),
- StartSession(player->GetDelegateId(), _, player->GetSurfaceId(),
+ StartSession(player->GetDelegateId(), _, TestSurfaceId(),
player->NaturalSize(), true, _, _));
PictureInPictureControllerImpl::From(GetDocument())
@@ -271,7 +281,7 @@ TEST_F(PictureInPictureControllerTest, StopObserving) {
WebMediaPlayer* player = Video()->GetWebMediaPlayer();
EXPECT_CALL(Service(),
- StartSession(player->GetDelegateId(), _, player->GetSurfaceId(),
+ StartSession(player->GetDelegateId(), _, TestSurfaceId(),
player->NaturalSize(), true, _, _));
PictureInPictureControllerImpl::From(GetDocument())
@@ -300,7 +310,7 @@ TEST_F(PictureInPictureControllerTest, PlayPauseButton_InfiniteDuration) {
WebMediaPlayer* player = Video()->GetWebMediaPlayer();
EXPECT_CALL(Service(),
- StartSession(player->GetDelegateId(), _, player->GetSurfaceId(),
+ StartSession(player->GetDelegateId(), _, TestSurfaceId(),
player->NaturalSize(), false, _, _));
PictureInPictureControllerImpl::From(GetDocument())
@@ -320,7 +330,7 @@ TEST_F(PictureInPictureControllerTest, PlayPauseButton_MediaSource) {
WebMediaPlayer* player = Video()->GetWebMediaPlayer();
EXPECT_CALL(Service(),
- StartSession(player->GetDelegateId(), _, player->GetSurfaceId(),
+ StartSession(player->GetDelegateId(), _, TestSurfaceId(),
player->NaturalSize(), false, _, _));
PictureInPictureControllerImpl::From(GetDocument())
diff --git a/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.cc b/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.cc
index 4bb886485c7..e88a730f72a 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.cc
+++ b/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.cc
@@ -23,17 +23,20 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/plugin_data.h"
+#include "third_party/blink/renderer/modules/plugins/dom_plugin_array.h"
+#include "third_party/blink/renderer/modules/plugins/navigator_plugins.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-DOMMimeTypeArray::DOMMimeTypeArray(LocalDOMWindow* window)
+DOMMimeTypeArray::DOMMimeTypeArray(LocalDOMWindow* window,
+ bool should_return_fixed_plugin_data)
: ExecutionContextLifecycleObserver(window),
- PluginsChangedObserver(window ? window->GetFrame()->GetPage() : nullptr) {
+ PluginsChangedObserver(window ? window->GetFrame()->GetPage() : nullptr),
+ should_return_fixed_plugin_data_(should_return_fixed_plugin_data) {
UpdatePluginData();
}
@@ -58,26 +61,16 @@ DOMMimeType* DOMMimeTypeArray::item(unsigned index) {
return dom_mime_types_[index];
}
-bool DOMMimeTypeArray::ShouldReturnEmptyPluginData(Frame* frame) {
- // See https://crbug.com/1171373 for more context. P/Nacl plugins will
- // be supported on some platforms through at least June, 2022. Since
- // some apps need to use feature detection, we need to continue returning
- // plugin data for those.
- if (frame && frame->GetSettings()->GetAllowNonEmptyNavigatorPlugins())
- return false;
- // Otherwise, depend on the feature flag, which can be disabled via
- // Finch killswitch.
- return base::FeatureList::IsEnabled(features::kNavigatorPluginsEmpty);
-}
-
-bool DOMMimeTypeArray::ShouldReturnEmptyPluginData() const {
- return ShouldReturnEmptyPluginData(DomWindow() ? DomWindow()->GetFrame()
- : nullptr);
-}
-
DOMMimeType* DOMMimeTypeArray::namedItem(const AtomicString& property_name) {
- if (ShouldReturnEmptyPluginData())
+ if (should_return_fixed_plugin_data_) {
+ // I don't know why namedItem() and NamedPropertyEnumerator go directly to
+ // the plugin data, rather than using dom_mime_types_.
+ for (const auto& mimetype : dom_mime_types_) {
+ if (mimetype->type() == property_name)
+ return mimetype;
+ }
return nullptr;
+ }
PluginData* data = GetPluginData();
if (!data)
return nullptr;
@@ -93,8 +86,12 @@ DOMMimeType* DOMMimeTypeArray::namedItem(const AtomicString& property_name) {
void DOMMimeTypeArray::NamedPropertyEnumerator(Vector<String>& property_names,
ExceptionState&) const {
- if (ShouldReturnEmptyPluginData())
+ if (should_return_fixed_plugin_data_) {
+ property_names.ReserveInitialCapacity(dom_mime_types_.size());
+ for (const auto& mimetype : dom_mime_types_)
+ property_names.UncheckedAppend(mimetype->type());
return;
+ }
PluginData* data = GetPluginData();
if (!data)
return;
@@ -119,19 +116,20 @@ PluginData* DOMMimeTypeArray::GetPluginData() const {
}
void DOMMimeTypeArray::UpdatePluginData() {
- if (ShouldReturnEmptyPluginData()) {
- dom_mime_types_.clear();
+ dom_mime_types_.clear();
+ if (should_return_fixed_plugin_data_) {
+ if (DomWindow()) {
+ dom_mime_types_ = NavigatorPlugins::plugins(*DomWindow()->navigator())
+ ->GetFixedMimeTypeArray();
+ }
return;
}
PluginData* data = GetPluginData();
- if (!data) {
- dom_mime_types_.clear();
+ if (!data)
return;
- }
HeapVector<Member<DOMMimeType>> old_dom_mime_types(
std::move(dom_mime_types_));
- dom_mime_types_.clear();
dom_mime_types_.resize(data->Mimes().size());
for (Member<DOMMimeType>& mime : old_dom_mime_types) {
diff --git a/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h b/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h
index eef7213b05b..7657e4e73ad 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h
+++ b/chromium/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h
@@ -31,7 +31,6 @@
namespace blink {
class ExceptionState;
-class Frame;
class LocalDOMWindow;
class PluginData;
@@ -41,7 +40,7 @@ class DOMMimeTypeArray final : public ScriptWrappable,
DEFINE_WRAPPERTYPEINFO();
public:
- explicit DOMMimeTypeArray(LocalDOMWindow*);
+ DOMMimeTypeArray(LocalDOMWindow*, bool should_return_fixed_plugin_data);
void UpdatePluginData();
@@ -51,8 +50,6 @@ class DOMMimeTypeArray final : public ScriptWrappable,
void NamedPropertyEnumerator(Vector<String>&, ExceptionState&) const;
bool NamedPropertyQuery(const AtomicString&, ExceptionState&) const;
- static bool ShouldReturnEmptyPluginData(Frame*);
-
// PluginsChangedObserver implementation.
void PluginsChanged() override;
@@ -62,7 +59,7 @@ class DOMMimeTypeArray final : public ScriptWrappable,
PluginData* GetPluginData() const;
void ContextDestroyed() override;
- bool ShouldReturnEmptyPluginData() const;
+ const bool should_return_fixed_plugin_data_;
HeapVector<Member<DOMMimeType>> dom_mime_types_;
};
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 53c24628f1d..af14f519bae 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
@@ -34,9 +34,11 @@
namespace blink {
-DOMPluginArray::DOMPluginArray(LocalDOMWindow* window)
+DOMPluginArray::DOMPluginArray(LocalDOMWindow* window,
+ bool should_return_fixed_plugin_data)
: ExecutionContextLifecycleObserver(window),
- PluginsChangedObserver(window ? window->GetFrame()->GetPage() : nullptr) {
+ PluginsChangedObserver(window ? window->GetFrame()->GetPage() : nullptr),
+ should_return_fixed_plugin_data_(should_return_fixed_plugin_data) {
UpdatePluginData();
}
@@ -56,6 +58,8 @@ DOMPlugin* DOMPluginArray::item(unsigned index) {
return nullptr;
if (!dom_plugins_[index]) {
+ if (should_return_fixed_plugin_data_)
+ return nullptr;
dom_plugins_[index] = MakeGarbageCollected<DOMPlugin>(
DomWindow(), *GetPluginData()->Plugins()[index]);
}
@@ -63,14 +67,16 @@ DOMPlugin* DOMPluginArray::item(unsigned index) {
return dom_plugins_[index];
}
-bool DOMPluginArray::ShouldReturnEmptyPluginData() const {
- return DOMMimeTypeArray::ShouldReturnEmptyPluginData(
- DomWindow() ? DomWindow()->GetFrame() : nullptr);
-}
-
DOMPlugin* DOMPluginArray::namedItem(const AtomicString& property_name) {
- if (ShouldReturnEmptyPluginData())
+ if (should_return_fixed_plugin_data_) {
+ // I don't know why namedItem() and NamedPropertyEnumerator go directly to
+ // the plugin data, rather than using dom_plugins_.
+ for (const auto& plugin : dom_plugins_) {
+ if (plugin->name() == property_name)
+ return plugin;
+ }
return nullptr;
+ }
PluginData* data = GetPluginData();
if (!data)
return nullptr;
@@ -87,8 +93,12 @@ DOMPlugin* DOMPluginArray::namedItem(const AtomicString& property_name) {
void DOMPluginArray::NamedPropertyEnumerator(Vector<String>& property_names,
ExceptionState&) const {
- if (ShouldReturnEmptyPluginData())
+ if (should_return_fixed_plugin_data_) {
+ property_names.ReserveInitialCapacity(dom_plugins_.size());
+ for (const auto& plugin : dom_plugins_)
+ property_names.UncheckedAppend(plugin->name());
return;
+ }
PluginData* data = GetPluginData();
if (!data)
return;
@@ -106,8 +116,6 @@ bool DOMPluginArray::NamedPropertyQuery(const AtomicString& property_name,
}
void DOMPluginArray::refresh(bool reload) {
- if (ShouldReturnEmptyPluginData())
- return;
if (!DomWindow())
return;
@@ -133,9 +141,59 @@ PluginData* DOMPluginArray::GetPluginData() const {
return DomWindow() ? DomWindow()->GetFrame()->GetPluginData() : nullptr;
}
+namespace {
+DOMPlugin* MakeFakePlugin(String plugin_name, LocalDOMWindow* window) {
+ String description = "Portable Document Format";
+ String filename = "internal-pdf-viewer";
+ auto* plugin_info = MakeGarbageCollected<PluginInfo>(
+ plugin_name, filename, description, /*background_color=*/0,
+ /*may_use_external_handler=*/false);
+ Vector<String> extensions{"pdf"};
+ for (const char* mime_type : {"application/pdf", "text/pdf"}) {
+ auto* mime_info = MakeGarbageCollected<MimeClassInfo>(
+ mime_type, description, *plugin_info, extensions);
+ plugin_info->AddMimeType(mime_info);
+ }
+ return MakeGarbageCollected<DOMPlugin>(window, *plugin_info);
+}
+} // namespace
+
+HeapVector<Member<DOMMimeType>> DOMPluginArray::GetFixedMimeTypeArray() {
+ DCHECK(should_return_fixed_plugin_data_);
+ HeapVector<Member<DOMMimeType>> mimetypes;
+ if (dom_plugins_.IsEmpty())
+ return mimetypes;
+ DCHECK_EQ(dom_plugins_[0]->length(), 2u);
+ mimetypes.push_back(dom_plugins_[0]->item(0));
+ mimetypes.push_back(dom_plugins_[0]->item(1));
+ return mimetypes;
+}
+
+bool DOMPluginArray::IsPdfViewerAvailable() {
+ DCHECK(should_return_fixed_plugin_data_);
+ auto* data = GetPluginData();
+ if (!data)
+ return false;
+ for (const Member<MimeClassInfo>& mime_info : data->Mimes()) {
+ if (mime_info->Type() == "application/pdf")
+ return true;
+ }
+ return false;
+}
+
void DOMPluginArray::UpdatePluginData() {
- if (ShouldReturnEmptyPluginData()) {
+ if (should_return_fixed_plugin_data_) {
dom_plugins_.clear();
+ if (IsPdfViewerAvailable()) {
+ // See crbug.com/1164635 and https://github.com/whatwg/html/pull/6738.
+ // To reduce fingerprinting and make plugins/mimetypes more
+ // interoperable, this is the spec'd, hard-coded list of plugins:
+ Vector<String> plugins{"PDF Viewer", "Chrome PDF Viewer",
+ "Chromium PDF Viewer", "Microsoft Edge PDF Viewer",
+ "WebKit built-in PDF"};
+ for (auto name : plugins)
+ dom_plugins_.push_back(MakeFakePlugin(name, DomWindow()));
+ }
return;
}
PluginData* data = GetPluginData();
diff --git a/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.h b/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.h
index 32c2ae804a4..dbfac2d6bdb 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.h
+++ b/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.h
@@ -40,7 +40,7 @@ class DOMPluginArray final : public ScriptWrappable,
DEFINE_WRAPPERTYPEINFO();
public:
- explicit DOMPluginArray(LocalDOMWindow*);
+ DOMPluginArray(LocalDOMWindow*, bool should_return_fixed_plugin_data);
void UpdatePluginData();
@@ -52,6 +52,12 @@ class DOMPluginArray final : public ScriptWrappable,
void refresh(bool reload);
+ // This function returns the "fixed" list of mime types, for the PDF viewer
+ // only. This function should only be used when
+ // should_return_fixed_plugin_data_ is true.
+ HeapVector<Member<DOMMimeType>> GetFixedMimeTypeArray();
+ bool IsPdfViewerAvailable();
+
// PluginsChangedObserver implementation.
void PluginsChanged() override;
@@ -61,7 +67,7 @@ class DOMPluginArray final : public ScriptWrappable,
PluginData* GetPluginData() const;
void ContextDestroyed() override;
- bool ShouldReturnEmptyPluginData() const;
+ const bool should_return_fixed_plugin_data_;
HeapVector<Member<DOMPlugin>> dom_plugins_;
};
diff --git a/chromium/third_party/blink/renderer/modules/plugins/idls.gni b/chromium/third_party/blink/renderer/modules/plugins/idls.gni
deleted file mode 100644
index c5a2cb7d0d8..00000000000
--- a/chromium/third_party/blink/renderer/modules/plugins/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "mime_type.idl",
- "mime_type_array.idl",
- "plugin.idl",
- "plugin_array.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_plugins.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.cc b/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
index 290d152edd2..1bd8382c2e6 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
+++ b/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.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/settings.h"
#include "third_party/blink/renderer/modules/plugins/dom_mime_type.h"
#include "third_party/blink/renderer/modules/plugins/dom_mime_type_array.h"
#include "third_party/blink/renderer/modules/plugins/dom_plugin_array.h"
@@ -17,8 +18,29 @@
namespace blink {
+namespace {
+bool ShouldReturnFixedPluginData(Navigator& navigator) {
+ if (auto* window = navigator.DomWindow()) {
+ if (auto* frame = window->GetFrame()) {
+ if (frame->GetSettings()->GetAllowNonEmptyNavigatorPlugins()) {
+ // See https://crbug.com/1171373 for more context. P/Nacl plugins will
+ // be supported on some platforms through at least June, 2022. Since
+ // some apps need to use feature detection, we need to continue
+ // returning plugin data for those.
+ return false;
+ }
+ }
+ }
+ // Otherwise, depend on the feature flag, which can be disabled via
+ // Finch killswitch.
+ return RuntimeEnabledFeatures::NavigatorPluginsFixedEnabled();
+}
+} // namespace
+
NavigatorPlugins::NavigatorPlugins(Navigator& navigator)
- : Supplement<Navigator>(navigator) {}
+ : Supplement<Navigator>(navigator),
+ should_return_fixed_plugin_data_(ShouldReturnFixedPluginData(navigator)) {
+}
// static
NavigatorPlugins& NavigatorPlugins::From(Navigator& navigator) {
@@ -49,6 +71,12 @@ DOMMimeTypeArray* NavigatorPlugins::mimeTypes(Navigator& navigator) {
}
// static
+bool NavigatorPlugins::pdfViewerEnabled(Navigator& navigator) {
+ return NavigatorPlugins::From(navigator).pdfViewerEnabled(
+ navigator.DomWindow());
+}
+
+// static
bool NavigatorPlugins::javaEnabled(Navigator& navigator) {
return false;
}
@@ -108,8 +136,10 @@ void RecordMimeTypes(LocalDOMWindow* window, DOMMimeTypeArray* mime_types) {
} // namespace
DOMPluginArray* NavigatorPlugins::plugins(LocalDOMWindow* window) const {
- if (!plugins_)
- plugins_ = MakeGarbageCollected<DOMPluginArray>(window);
+ if (!plugins_) {
+ plugins_ = MakeGarbageCollected<DOMPluginArray>(
+ window, should_return_fixed_plugin_data_);
+ }
DOMPluginArray* result = plugins_.Get();
RecordPlugins(window, result);
@@ -118,12 +148,17 @@ DOMPluginArray* NavigatorPlugins::plugins(LocalDOMWindow* window) const {
DOMMimeTypeArray* NavigatorPlugins::mimeTypes(LocalDOMWindow* window) const {
if (!mime_types_) {
- mime_types_ = MakeGarbageCollected<DOMMimeTypeArray>(window);
+ mime_types_ = MakeGarbageCollected<DOMMimeTypeArray>(
+ window, should_return_fixed_plugin_data_);
RecordMimeTypes(window, mime_types_.Get());
}
return mime_types_.Get();
}
+bool NavigatorPlugins::pdfViewerEnabled(LocalDOMWindow* window) const {
+ return plugins(window)->IsPdfViewerAvailable();
+}
+
void NavigatorPlugins::Trace(Visitor* visitor) const {
visitor->Trace(plugins_);
visitor->Trace(mime_types_);
diff --git a/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.h b/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.h
index 3afbdbb3dbb..599e88f1715 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.h
+++ b/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.h
@@ -25,6 +25,8 @@ class NavigatorPlugins final : public GarbageCollected<NavigatorPlugins>,
static DOMPluginArray* plugins(Navigator&);
static DOMMimeTypeArray* mimeTypes(Navigator&);
+ static bool pdfViewerEnabled(Navigator&);
+
static bool javaEnabled(Navigator&);
explicit NavigatorPlugins(Navigator&);
@@ -34,6 +36,9 @@ class NavigatorPlugins final : public GarbageCollected<NavigatorPlugins>,
private:
DOMPluginArray* plugins(LocalDOMWindow*) const;
DOMMimeTypeArray* mimeTypes(LocalDOMWindow*) const;
+ bool pdfViewerEnabled(LocalDOMWindow* window) const;
+
+ const bool should_return_fixed_plugin_data_;
mutable Member<DOMPluginArray> plugins_;
mutable Member<DOMMimeTypeArray> mime_types_;
diff --git a/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.idl b/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.idl
index 8c83f5e4462..a02dd1ef199 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.idl
+++ b/chromium/third_party/blink/renderer/modules/plugins/navigator_plugins.idl
@@ -9,4 +9,5 @@
[HighEntropy, MeasureAs=NavigatorPlugins] readonly attribute PluginArray plugins;
[HighEntropy, MeasureAs=NavigatorMimeTypes] readonly attribute MimeTypeArray mimeTypes;
[HighEntropy=Direct, Measure] boolean javaEnabled();
+ [HighEntropy, MeasureAs=NavigatorPdfViewerEnabled, RuntimeEnabled=NavigatorPluginsFixed] readonly attribute boolean pdfViewerEnabled;
};
diff --git a/chromium/third_party/blink/renderer/modules/presentation/idls.gni b/chromium/third_party/blink/renderer/modules/presentation/idls.gni
deleted file mode 100644
index f6ddfb28277..00000000000
--- a/chromium/third_party/blink/renderer/modules/presentation/idls.gni
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "presentation.idl",
- "presentation_availability.idl",
- "presentation_connection.idl",
- "presentation_connection_available_event.idl",
- "presentation_connection_close_event.idl",
- "presentation_connection_list.idl",
- "presentation_receiver.idl",
- "presentation_request.idl",
-]
-
-modules_dictionary_idl_files = [
- "presentation_connection_available_event_init.idl",
- "presentation_connection_close_event_init.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_presentation.idl" ]
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 40dad59feec..014019fca11 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/presentation/presentation_connection.h"
#include <memory>
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.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/events/event.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/idls.gni b/chromium/third_party/blink/renderer/modules/push_messaging/idls.gni
deleted file mode 100644
index 3b3cdced712..00000000000
--- a/chromium/third_party/blink/renderer/modules/push_messaging/idls.gni
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "push_event.idl",
- "push_manager.idl",
- "push_message_data.idl",
- "push_subscription.idl",
- "push_subscription_change_event.idl",
- "push_subscription_options.idl",
-]
-
-modules_dictionary_idl_files = [
- "push_event_init.idl",
- "push_subscription_change_event_init.idl",
- "push_subscription_options_init.idl",
-]
-
-modules_dependency_idl_files = [
- "service_worker_global_scope_push.idl",
- "service_worker_registration_push.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_event.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_event.cc
index e400b35c413..37169a10630 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_event.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_event.cc
@@ -4,7 +4,10 @@
#include "third_party/blink/renderer/modules/push_messaging/push_event.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_usvstring.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_push_event_init.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -19,14 +22,13 @@ PushEvent::PushEvent(const AtomicString& type,
ExceptionState& exception_state)
: ExtendableEvent(type, initializer) {
if (initializer->hasData()) {
- const ArrayBufferOrArrayBufferViewOrUSVString& message_data =
- initializer->data();
- if (message_data.IsArrayBuffer() || message_data.IsArrayBufferView()) {
- DOMArrayBuffer* buffer =
- message_data.IsArrayBufferView()
- ? message_data.GetAsArrayBufferView()->buffer()
- : message_data.GetAsArrayBuffer();
- if (!base::CheckedNumeric<uint32_t>(buffer->ByteLength()).IsValid()) {
+ const auto* message_data = initializer->data();
+ if (message_data->IsArrayBuffer() || message_data->IsArrayBufferView()) {
+ DOMArrayPiece array_piece =
+ message_data->IsArrayBuffer()
+ ? DOMArrayPiece(message_data->GetAsArrayBuffer())
+ : DOMArrayPiece(message_data->GetAsArrayBufferView().Get());
+ if (!base::CheckedNumeric<uint32_t>(array_piece.ByteLength()).IsValid()) {
exception_state.ThrowRangeError(
"The provided ArrayBuffer exceeds the maximum supported size "
"(4294967295)");
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc
index 425d3ad2e02..0e154490a90 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc
@@ -5,9 +5,11 @@
#include "third_party/blink/renderer/modules/push_messaging/push_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_push_subscription_options_init.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -49,7 +51,7 @@ void IsApplicationServerKeyValid(PushSubscriptionOptions* output) {
TEST(PushManagerTest, ValidSenderKey) {
PushSubscriptionOptionsInit* options = PushSubscriptionOptionsInit::Create();
options->setApplicationServerKey(
- ArrayBufferOrArrayBufferViewOrString::FromArrayBuffer(
+ MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
DOMArrayBuffer::Create(kApplicationServerKey,
kApplicationServerKeyLength)));
@@ -75,7 +77,8 @@ TEST(PushManagerTest, ValidBase64URLWithoutPaddingSenderKey) {
kApplicationServerKeyLength);
base64_url = base64_url.RemoveCharacters(RemovePad);
options->setApplicationServerKey(
- ArrayBufferOrArrayBufferViewOrString::FromString(base64_url));
+ MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
+ base64_url));
DummyExceptionStateForTesting exception_state;
PushSubscriptionOptions* output =
@@ -90,7 +93,7 @@ TEST(PushManagerTest, InvalidSenderKeyLength) {
memset(sender_key, 0, sizeof(sender_key));
PushSubscriptionOptionsInit* options = PushSubscriptionOptionsInit::Create();
options->setApplicationServerKey(
- ArrayBufferOrArrayBufferViewOrString::FromArrayBuffer(
+ MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
DOMArrayBuffer::Create(sender_key, kMaxKeyLength + 1)));
DummyExceptionStateForTesting exception_state;
@@ -106,7 +109,7 @@ TEST(PushManagerTest, InvalidBase64SenderKey) {
PushSubscriptionOptionsInit* options =
MakeGarbageCollected<PushSubscriptionOptionsInit>();
options->setApplicationServerKey(
- ArrayBufferOrArrayBufferViewOrString::FromString(
+ MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
Base64Encode(kApplicationServerKey)));
DummyExceptionStateForTesting exception_state;
@@ -123,9 +126,10 @@ TEST(PushManagerTest, InvalidBase64URLWithPaddingSenderKey) {
PushSubscriptionOptionsInit* options =
MakeGarbageCollected<PushSubscriptionOptionsInit>();
options->setApplicationServerKey(
- ArrayBufferOrArrayBufferViewOrString::FromString(WTF::Base64URLEncode(
- reinterpret_cast<const char*>(kApplicationServerKey),
- kApplicationServerKeyLength)));
+ MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>(
+ WTF::Base64URLEncode(
+ reinterpret_cast<const char*>(kApplicationServerKey),
+ kApplicationServerKeyLength)));
DummyExceptionStateForTesting exception_state;
PushSubscriptionOptions* output =
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 409aa11a165..7f59946b116 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
@@ -7,9 +7,10 @@
#include <memory>
#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/bindings/core/v8/v8_union_arraybuffer_arraybufferview_usvstring.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_piece.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"
@@ -26,29 +27,40 @@ PushMessageData* PushMessageData::Create(const String& message_string) {
if (message_string.IsNull())
return nullptr;
return PushMessageData::Create(
- ArrayBufferOrArrayBufferViewOrUSVString::FromUSVString(message_string));
+ MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrUSVString>(
+ message_string));
}
PushMessageData* PushMessageData::Create(
- const ArrayBufferOrArrayBufferViewOrUSVString& message_data) {
- if (message_data.IsArrayBuffer() || message_data.IsArrayBufferView()) {
- DOMArrayBuffer* buffer = message_data.IsArrayBufferView()
- ? message_data.GetAsArrayBufferView()->buffer()
- : message_data.GetAsArrayBuffer();
-
- return MakeGarbageCollected<PushMessageData>(
- static_cast<const char*>(buffer->Data()),
- base::checked_cast<wtf_size_t>(buffer->ByteLength()));
- }
-
- if (message_data.IsUSVString()) {
- std::string encoded_string = UTF8Encoding().Encode(
- message_data.GetAsUSVString(), WTF::kNoUnencodables);
- return MakeGarbageCollected<PushMessageData>(
- encoded_string.c_str(), static_cast<unsigned>(encoded_string.length()));
+ const V8UnionArrayBufferOrArrayBufferViewOrUSVString* message_data) {
+ if (!message_data)
+ return nullptr;
+ switch (message_data->GetContentType()) {
+ case V8UnionArrayBufferOrArrayBufferViewOrUSVString::ContentType::
+ kArrayBuffer: {
+ DOMArrayBuffer* buffer = message_data->GetAsArrayBuffer();
+ return MakeGarbageCollected<PushMessageData>(
+ static_cast<const char*>(buffer->Data()),
+ base::checked_cast<wtf_size_t>(buffer->ByteLength()));
+ }
+ case V8UnionArrayBufferOrArrayBufferViewOrUSVString::ContentType::
+ kArrayBufferView: {
+ DOMArrayBufferView* buffer_view =
+ message_data->GetAsArrayBufferView().Get();
+ return MakeGarbageCollected<PushMessageData>(
+ static_cast<const char*>(buffer_view->BaseAddress()),
+ base::checked_cast<wtf_size_t>(buffer_view->byteLength()));
+ }
+ case V8UnionArrayBufferOrArrayBufferViewOrUSVString::ContentType::
+ kUSVString: {
+ std::string encoded_string = UTF8Encoding().Encode(
+ message_data->GetAsUSVString(), WTF::kNoUnencodables);
+ return MakeGarbageCollected<PushMessageData>(
+ encoded_string.c_str(),
+ static_cast<unsigned>(encoded_string.length()));
+ }
}
-
- DCHECK(message_data.IsNull());
+ NOTREACHED();
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.h
index 11856018b35..802e87795f3 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.h
@@ -14,11 +14,11 @@
namespace blink {
-class ArrayBufferOrArrayBufferViewOrUSVString;
class Blob;
class DOMArrayBuffer;
class ExceptionState;
class ScriptState;
+class V8UnionArrayBufferOrArrayBufferViewOrUSVString;
class MODULES_EXPORT PushMessageData final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -26,7 +26,7 @@ class MODULES_EXPORT PushMessageData final : public ScriptWrappable {
public:
static PushMessageData* Create(const String& data);
static PushMessageData* Create(
- const ArrayBufferOrArrayBufferViewOrUSVString& data);
+ const V8UnionArrayBufferOrArrayBufferViewOrUSVString* data);
PushMessageData(const char* data, unsigned bytes_size);
~PushMessageData() override;
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 751196560fa..082210a6060 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
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options.h"
-#include "third_party/blink/renderer/bindings/modules/v8/array_buffer_or_array_buffer_view_or_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_push_subscription_options_init.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -19,7 +20,7 @@ namespace {
const int kMaxApplicationServerKeyLength = 255;
Vector<uint8_t> BufferSourceToVector(
- const ArrayBufferOrArrayBufferViewOrString& application_server_key,
+ const V8UnionBufferSourceOrString* application_server_key,
ExceptionState& exception_state) {
char* input;
size_t length;
@@ -27,28 +28,29 @@ Vector<uint8_t> BufferSourceToVector(
Vector<uint8_t> result;
// Convert the input array into a string of bytes.
- if (application_server_key.IsArrayBuffer()) {
- input =
- static_cast<char*>(application_server_key.GetAsArrayBuffer()->Data());
- length = application_server_key.GetAsArrayBuffer()->ByteLength();
- } else if (application_server_key.IsArrayBufferView()) {
- input = static_cast<char*>(
- application_server_key.GetAsArrayBufferView()->BaseAddress());
- length = application_server_key.GetAsArrayBufferView()->byteLength();
- } else if (application_server_key.IsString()) {
- if (!Base64UnpaddedURLDecode(application_server_key.GetAsString(),
- decoded_application_server_key)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidCharacterError,
- "The provided applicationServerKey is not encoded as base64url "
- "without padding.");
- return result;
- }
- input = reinterpret_cast<char*>(decoded_application_server_key.data());
- length = decoded_application_server_key.size();
- } else {
- NOTREACHED();
- return result;
+ switch (application_server_key->GetContentType()) {
+ case V8UnionBufferSourceOrString::ContentType::kArrayBuffer:
+ input = static_cast<char*>(
+ application_server_key->GetAsArrayBuffer()->Data());
+ length = application_server_key->GetAsArrayBuffer()->ByteLength();
+ break;
+ case V8UnionBufferSourceOrString::ContentType::kArrayBufferView:
+ input = static_cast<char*>(
+ application_server_key->GetAsArrayBufferView()->BaseAddress());
+ length = application_server_key->GetAsArrayBufferView()->byteLength();
+ break;
+ case V8UnionBufferSourceOrString::ContentType::kString:
+ if (!Base64UnpaddedURLDecode(application_server_key->GetAsString(),
+ decoded_application_server_key)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidCharacterError,
+ "The provided applicationServerKey is not encoded as base64url "
+ "without padding.");
+ return result;
+ }
+ input = reinterpret_cast<char*>(decoded_application_server_key.data());
+ length = decoded_application_server_key.size();
+ break;
}
// Check the validity of the sender info. It must either be a 65-byte
@@ -82,7 +84,8 @@ PushSubscriptionOptions* PushSubscriptionOptions::FromOptionsInit(
// has a default value, but we check |hasApplicationServerKey()| here for
// backward compatibility.
if (options_init->hasApplicationServerKey() &&
- !options_init->applicationServerKey().IsNull()) {
+ options_init->applicationServerKey()
+ ) {
application_server_key.AppendVector(BufferSourceToVector(
options_init->applicationServerKey(), exception_state));
}
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 2e9be23d978..1fcafa7f819 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
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/push_messaging/push_subscription.h"
-#include "base/stl_util.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/modules/push_messaging/push_subscription.h"
diff --git a/chromium/third_party/blink/renderer/modules/quota/idls.gni b/chromium/third_party/blink/renderer/modules/quota/idls.gni
deleted file mode 100644
index 59cbde178ab..00000000000
--- a/chromium/third_party/blink/renderer/modules/quota/idls.gni
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "deprecated_storage_info.idl",
- "deprecated_storage_quota.idl",
- "dom_error.idl",
- "storage_manager.idl",
-]
-
-modules_callback_function_idl_files = [ "deprecated_storage_callbacks.idl" ]
-
-modules_dictionary_idl_files = [
- "storage_estimate.idl",
- "storage_usage_details.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_storage_quota.idl",
- "window_quota.idl",
- "worker_navigator_storage_quota.idl",
-]
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 956d88a1c92..fefd1f7edb3 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
@@ -23,7 +23,7 @@ class AvailabilityCallbackWrapper final
public:
explicit AvailabilityCallbackWrapper(V8RemotePlaybackAvailabilityCallback*);
explicit AvailabilityCallbackWrapper(base::RepeatingClosure);
- ~AvailabilityCallbackWrapper() = default;
+ ~AvailabilityCallbackWrapper() override = default;
void Run(RemotePlayback*, bool new_availability);
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/idls.gni b/chromium/third_party/blink/renderer/modules/remoteplayback/idls.gni
deleted file mode 100644
index 5c61fc81eef..00000000000
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "remote_playback.idl" ]
-
-modules_dependency_idl_files = [ "html_media_element_remote_playback.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/BUILD.gn b/chromium/third_party/blink/renderer/modules/sanitizer_api/BUILD.gn
index f8c475df2a1..c8413c3b2ab 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/BUILD.gn
@@ -8,6 +8,8 @@ import("//third_party/protobuf/proto_library.gni")
blink_modules_sources("sanitizer_api") {
sources = [
+ "element_sanitizer.cc",
+ "element_sanitizer.h",
"sanitizer.cc",
"sanitizer.h",
"sanitizer_config_impl.cc",
@@ -24,12 +26,14 @@ if (use_libfuzzer) {
corpus_source_config = [ # These match source files: corpus/*.txt
"config1",
"config2",
+ "config3",
"default",
]
corpus_source_html = [ # These match source files: corpus/*.html
"simple1",
"simple2",
"simple3",
+ "simple4",
"medium1",
"medium2",
"medium3",
@@ -73,7 +77,6 @@ if (use_libfuzzer) {
deps = [
":generate_sanitizer_fuzzer_corpus",
":sanitizer_config_proto",
- "//third_party/blink/renderer/bindings/modules/v8:bindings_modules_impl_generated",
"//third_party/blink/renderer/controller:blink_bindings_test_sources",
"//third_party/blink/renderer/core:testing",
"//third_party/blink/renderer/modules:modules",
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/config3.txt b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/config3.txt
new file mode 100644
index 00000000000..473485c6ec6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/config3.txt
@@ -0,0 +1,9 @@
+allow_elements: "div"
+allow_elements: "p"
+allow_elements: "span"
+allow_elements: "em"
+allow_elements: "b"
+allow_elements: "h1"
+allow_elements: "h2"
+allow_elements: "h3"
+allow_comments: true
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium1.html b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium1.html
index 704c85dcb52..97f53c9505b 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium1.html
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium1.html
@@ -824,7 +824,6 @@
<i checked="val">text</i>
<blockquote onpointerleave="val">text</blockquote>
<time disableremoteplayback="val">text</time>
-<p disallowdocumentaccess="val">text</p>
<script onblur="val">text</script>
<em onselect="val">text</em>
<th onlostpointercapture="val">text</th>
@@ -864,7 +863,6 @@
<b onbeforeprint="val">text</b>
<eprobe onformdata="val">text</eprobe>
<dfn virtualkeyboardpolicy="val">text</dfn>
-<h1 disallowdocumentaccess="val">text</h1>
<strong onmousewheel="val">text</strong>
<var preload="val">text</var>
<applet conversiondestination="val">text</applet>
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium2.html b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium2.html
index d44be8ddb66..eac9dda8a87 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium2.html
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium2.html
@@ -22,7 +22,6 @@
<canvas onanimationend="val">text</canvas>
<li step="val">text</li>
<h5 topmargin="val">text</h5>
-<s disallowdocumentaccess="val">text</s>
<applet onloadstart="val">text</applet>
<dt ondrag="val">text</dt>
<object minlength="val">text</object>
@@ -959,7 +958,6 @@
<plaintext ondblclick="val">text</plaintext>
<br lowsrc="val">text</br>
<nolayer pattern="val">text</nolayer>
-<style disallowdocumentaccess="val">text</style>
<progress onbeforeprint="val">text</progress>
<tfoot abbr="val">text</tfoot>
<h5 controls="val">text</h5>
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium3.html b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium3.html
index 766aae878b9..db6d6af4759 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium3.html
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/medium3.html
@@ -621,7 +621,6 @@
<applet ontimezonechange="val">text</applet>
<link media="val">text</link>
<i name="val">text</i>
-<abbr disallowdocumentaccess="val">text</abbr>
<listing srcset="val">text</listing>
<code onsubmit="val">text</code>
<a onpointerout="val">text</a>
@@ -975,7 +974,6 @@
<blockquote allow="val">text</blockquote>
<footer coords="val">text</footer>
<small tabindex="val">text</small>
-<iframe disallowdocumentaccess="val">text</iframe>
<ul for="val">text</ul>
<summary nonce="val">text</summary>
<option accept="val">text</option>
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/simple4.html b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/simple4.html
new file mode 100644
index 00000000000..9f490c7bb1b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/corpus/simple4.html
@@ -0,0 +1,4 @@
+<div onclick="alert(1)">
+ <!-- a comment -->
+ <p>Hello <strong>World!</p>
+</div>
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.cc b/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.cc
new file mode 100644
index 00000000000..3e64f7c11f8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.cc
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "element_sanitizer.h"
+
+#include "third_party/blink/renderer/modules/sanitizer_api/sanitizer.h"
+
+namespace blink {
+
+void ElementSanitizer::setHTML(ScriptState* script_state,
+ Element& element,
+ const String& markup,
+ Sanitizer* sanitizer,
+ ExceptionState& exception_state) {
+ sanitizer->ElementSetHTML(script_state, element, markup, exception_state);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.h b/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.h
new file mode 100644
index 00000000000..1b9f10e9bad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.h
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SANITIZER_API_ELEMENT_SANITIZER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SANITIZER_API_ELEMENT_SANITIZER_H_
+
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class Element;
+class ExceptionState;
+class Sanitizer;
+class ScriptState;
+
+class MODULES_EXPORT ElementSanitizer final {
+ public:
+ static void setHTML(ScriptState*,
+ Element&,
+ const String&,
+ Sanitizer*,
+ ExceptionState&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SANITIZER_API_ELEMENT_SANITIZER_H_
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl b/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl
new file mode 100644
index 00000000000..b75fa2e1cf6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/sanitizer-api
+
+[
+ RuntimeEnabled=SanitizerAPI,
+ ImplementedAs=ElementSanitizer
+] partial interface Element {
+ [CEReactions, RaisesException, CallWith=ScriptState, MeasureAs=SanitizerAPIElementSetSanitized] void setHTML(DOMString markup, Sanitizer sanitizer);
+};
+
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/idls.gni b/chromium/third_party/blink/renderer/modules/sanitizer_api/idls.gni
deleted file mode 100644
index c21c59f0833..00000000000
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "sanitizer.idl" ]
-
-modules_dictionary_idl_files = [ "sanitizer_config.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc
index b30c025212b..1ba4bd0b642 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc
@@ -7,10 +7,7 @@
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node_filter.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_parse_from_string_options.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string_trustedhtml.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_document_fragment_or_document.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_trusted_html_or_document_fragment_or_document.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_sanitizer_config.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
@@ -50,7 +47,8 @@ bool ConfigIsEmpty(const SanitizerConfig* config) {
return !config ||
(!config->hasDropElements() && !config->hasBlockElements() &&
!config->hasAllowElements() && !config->hasDropAttributes() &&
- !config->hasAllowAttributes() && !config->hasAllowCustomElements());
+ !config->hasAllowAttributes() && !config->hasAllowCustomElements() &&
+ !config->hasAllowComments());
}
SanitizerConfig* SanitizerConfigCopy(const SanitizerConfig* config) {
@@ -64,6 +62,9 @@ SanitizerConfig* SanitizerConfigCopy(const SanitizerConfig* config) {
if (config->hasAllowCustomElements()) {
copy->setAllowCustomElements(config->allowCustomElements());
}
+ if (config->hasAllowComments()) {
+ copy->setAllowComments(config->allowComments());
+ }
if (config->hasAllowElements()) {
copy->setAllowElements(config->allowElements());
}
@@ -84,18 +85,13 @@ SanitizerConfig* SanitizerConfigCopy(const SanitizerConfig* config) {
Sanitizer::Sanitizer(ExecutionContext* execution_context,
const SanitizerConfig* config) {
// The spec treats an absent config as the default. We'll handle this by
- // normalizing this here to make sure the config_dictionary_ is nullptr
- // in these cases, while the config_ will be a copy of the default config.
+ // checking for this an empty dictionary and representing it as nullptr.
if (ConfigIsEmpty(config)) {
config = nullptr;
- }
-
- config_ = SanitizerConfigImpl::From(config);
- config_dictionary_ = SanitizerConfigCopy(config);
- if (!config_dictionary_) {
UseCounter::Count(execution_context,
WebFeature::kSanitizerAPIDefaultConfiguration);
}
+ config_ = SanitizerConfigImpl::From(config);
}
Sanitizer::~Sanitizer() = default;
@@ -106,85 +102,78 @@ Sanitizer* Sanitizer::Create(ExecutionContext* execution_context,
return MakeGarbageCollected<Sanitizer>(execution_context, config);
}
-String Sanitizer::sanitizeToString(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8SanitizerInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrDocumentFragmentOrDocument& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ExceptionState& exception_state) {
- return CreateMarkup(SanitizeImpl(script_state, input, exception_state),
- kChildrenOnly);
-}
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-DocumentFragment* Sanitizer::sanitize(
- ScriptState* script_state,
- const V8SanitizerInputWithTrustedHTML* input,
- ExceptionState& exception_state) {
+DocumentFragment* Sanitizer::sanitize(ScriptState* script_state,
+ const V8SanitizerInput* input,
+ ExceptionState& exception_state) {
V8SanitizerInput* new_input = nullptr;
switch (input->GetContentType()) {
- case V8SanitizerInputWithTrustedHTML::ContentType::kDocument:
+ case V8SanitizerInput::ContentType::kDocument:
new_input =
MakeGarbageCollected<V8SanitizerInput>(input->GetAsDocument());
break;
- case V8SanitizerInputWithTrustedHTML::ContentType::kDocumentFragment:
+ case V8SanitizerInput::ContentType::kDocumentFragment:
new_input = MakeGarbageCollected<V8SanitizerInput>(
input->GetAsDocumentFragment());
break;
- case V8SanitizerInputWithTrustedHTML::ContentType::kString: {
- LocalDOMWindow* window = LocalDOMWindow::From(script_state);
- if (!window) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot find current DOM window.");
- return nullptr;
- }
- new_input =
- MakeGarbageCollected<V8SanitizerInput>(TrustedTypesCheckForHTML(
- input->GetAsString(), window->GetExecutionContext(),
- exception_state));
- if (exception_state.HadException()) {
- return nullptr;
- }
- break;
- }
- case V8SanitizerInputWithTrustedHTML::ContentType::kTrustedHTML:
- new_input = MakeGarbageCollected<V8SanitizerInput>(
- input->GetAsTrustedHTML()->toString());
- break;
}
- return SanitizeImpl(script_state, new_input, exception_state);
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ DocumentFragment* fragment =
+ PrepareFragment(window, script_state, new_input, exception_state);
+ if (exception_state.HadException()) {
+ return nullptr;
+ }
+ DoSanitizing(fragment, window, exception_state);
+ return fragment;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-DocumentFragment* Sanitizer::sanitize(
- ScriptState* script_state,
- StringOrTrustedHTMLOrDocumentFragmentOrDocument& input,
- ExceptionState& exception_state) {
- StringOrDocumentFragmentOrDocument new_input;
- if (input.IsString() || input.IsNull()) {
- LocalDOMWindow* window = LocalDOMWindow::From(script_state);
- if (!window) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot find current DOM window.");
- return nullptr;
- }
- new_input.SetString(TrustedTypesCheckForHTML(
- input.GetAsString(), window->GetExecutionContext(), exception_state));
- if (exception_state.HadException()) {
- return nullptr;
- }
- } else if (input.IsTrustedHTML()) {
- new_input.SetString(input.GetAsTrustedHTML()->toString());
- } else if (input.IsDocument()) {
- new_input.SetDocument(input.GetAsDocument());
- } else if (input.IsDocumentFragment()) {
- new_input.SetDocumentFragment(input.GetAsDocumentFragment());
+
+Element* Sanitizer::sanitizeFor(ScriptState* script_state,
+ const String& local_name,
+ const String& markup,
+ ExceptionState& exception_state) {
+ if (baseline_drop_elements_.Contains(local_name.LowerASCII()))
+ return nullptr;
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ Document* inert_document = DocumentInit::Create()
+ .WithURL(window->Url())
+ .WithTypeFrom("text/html")
+ .WithExecutionContext(window)
+ .CreateDocument();
+ Element* element = inert_document->CreateElementForBinding(
+ AtomicString(local_name), exception_state);
+ if (exception_state.HadException()) {
+ exception_state.ClearException();
+ return nullptr;
+ }
+ element->setInnerHTML(markup, exception_state);
+ if (exception_state.HadException()) {
+ exception_state.ClearException();
+ return nullptr;
+ }
+ DoSanitizing(element, window, exception_state);
+ if (exception_state.HadException()) {
+ exception_state.ClearException();
+ return nullptr;
}
- return SanitizeImpl(script_state, new_input, exception_state);
+ return element;
+}
+
+void Sanitizer::ElementSetHTML(ScriptState* script_state,
+ Element& element,
+ const String& markup,
+ ExceptionState& exception_state) {
+ Element* new_element =
+ sanitizeFor(script_state, element.localName(), markup, exception_state);
+ if (exception_state.HadException())
+ return;
+ if (!new_element) {
+ exception_state.ThrowTypeError("setHTML not allowed on this element type.");
+ return;
+ }
+ element.RemoveChildren();
+ while (Node* to_be_moved = new_element->firstChild())
+ element.AppendChild(to_be_moved);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DocumentFragment* Sanitizer::PrepareFragment(LocalDOMWindow* window,
ScriptState* script_state,
const V8SanitizerInput* input,
@@ -211,162 +200,101 @@ DocumentFragment* Sanitizer::PrepareFragment(LocalDOMWindow* window,
UseCounter::Count(window->GetExecutionContext(),
WebFeature::kSanitizerAPIFromFragment);
return input->GetAsDocumentFragment();
- case V8SanitizerInput::ContentType::kString: {
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIFromString);
- Document* document =
- window->document()
- ? window->document()->implementation().createHTMLDocument()
- : DOMParser::Create(script_state)
- ->parseFromString(
- "<!DOCTYPE html><html><body></body></html>",
- "text/html", ParseFromStringOptions::Create());
- // TODO(https://crbug.com/1178774): Behavior difference need further
- // investgate.
- return document->createRange()->createContextualFragment(
- input->GetAsString(), exception_state);
- }
}
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-DocumentFragment* Sanitizer::PrepareFragment(
- LocalDOMWindow* window,
- ScriptState* script_state,
- StringOrDocumentFragmentOrDocument& input,
- ExceptionState& exception_state) {
- DocumentFragment* fragment = nullptr;
- if (!window) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot find current DOM window.");
- return nullptr;
- }
- if (input.IsDocumentFragment()) {
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIFromFragment);
- fragment = input.GetAsDocumentFragment();
- } else if (input.IsString() || input.IsNull()) {
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIFromString);
-
- Document* document =
- window->document()
- ? window->document()->implementation().createHTMLDocument()
- : DOMParser::Create(script_state)
- ->parseFromString("<!DOCTYPE html><html><body></body></html>",
- "text/html",
- ParseFromStringOptions::Create());
- // TODO(https://crbug.com/1178774): Behavior difference need further
- // investgate.
- fragment = document->createRange()->createContextualFragment(
- input.GetAsString(), exception_state);
- } else if (input.IsDocument()) {
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIFromDocument);
-
- fragment = input.GetAsDocument()->createDocumentFragment();
- fragment->CloneChildNodesFrom(*(input.GetAsDocument()->body()),
- CloneChildrenFlag::kClone);
- } else {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot find current DOM window.");
- return nullptr;
- }
- return fragment;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-DocumentFragment* Sanitizer::DoSanitizing(DocumentFragment* fragment,
- LocalDOMWindow* window,
- ExceptionState& exception_state) {
+void Sanitizer::DoSanitizing(ContainerNode* fragment,
+ LocalDOMWindow* window,
+ ExceptionState& exception_state) {
Node* node = fragment->firstChild();
while (node) {
- // Skip non-Element nodes.
- if (node->getNodeType() != Node::NodeType::kElementNode) {
- node = NodeTraversal::Next(*node, fragment);
- continue;
- }
-
- // TODO(crbug.com/1126936): Review the sanitising algorithm for non-HTMLs.
- // 1. Let |name| be |element|'s tag name.
- String name = node->nodeName().UpperASCII();
-
- // 2. Detect whether current element is a custom element or not.
- bool is_custom_element =
- CustomElement::IsValidName(AtomicString(name.LowerASCII()), false);
-
- // 3. If |kind| is `regular` and if |name| is not contained in the
- // default element allow list, then 'drop'
- if (baseline_drop_elements_.Contains(name)) {
- node = DropElement(node, fragment);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- } else if (is_custom_element && !config_.allow_custom_elements_) {
- // 4. If |kind| is `custom` and if allow_custom_elements_ is unset or set
- // to anything other than `true`, then 'drop'.
- node = DropElement(node, fragment);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- } else if (!node->IsHTMLElement()) {
- // Presently unspec-ed: If |node| is in a non-HTML namespace: Drop.
- node = DropElement(node, fragment);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- } else if (config_.drop_elements_.Contains(name)) {
- // 5. If |name| is in |config|'s [=element drop list=] then 'drop'.
- node = DropElement(node, fragment);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- } else if (config_.block_elements_.Contains(name)) {
- // 6. If |name| is in |config|'s [=element block list=] then 'block'.
- node = BlockElement(node, fragment, exception_state);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- } else if (!config_.allow_elements_.Contains(name)) {
- // 7. if |name| is not in |config|'s [=element allow list=] then 'block'.
- node = BlockElement(node, fragment, exception_state);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- } else if (IsA<HTMLTemplateElement>(node)) {
- // 8. If |element|'s [=element interface=] is {{HTMLTemplateElement}}
- // Run the steps of the [=sanitize document fragment=] algorithm on
- // |element|'s |content| attribute.
- DoSanitizing(To<HTMLTemplateElement>(node)->content(), window,
- exception_state);
- UseCounter::Count(window->GetExecutionContext(),
- WebFeature::kSanitizerAPIActionTaken);
- node = KeepElement(node, fragment, name, window);
- } else {
- node = KeepElement(node, fragment, name, window);
+ switch (node->getNodeType()) {
+ case Node::NodeType::kElementNode: {
+ // TODO(crbug.com/1126936): Review the sanitising algorithm for
+ // non-HTMLs.
+ // 1. Let |name| be |element|'s tag name.
+ String name = node->nodeName().LowerASCII();
+
+ // 2. Detect whether current element is a custom element or not.
+ bool is_custom_element =
+ CustomElement::IsValidName(AtomicString(name.LowerASCII()), false);
+
+ // 3. If |kind| is `regular` and if |name| is not contained in the
+ // default element allow list, then 'drop'
+ if (baseline_drop_elements_.Contains(name)) {
+ node = DropElement(node, fragment);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ } else if (is_custom_element && !config_.allow_custom_elements_) {
+ // 4. If |kind| is `custom` and if allow_custom_elements_ is unset or
+ // set to anything other than `true`, then 'drop'.
+ node = DropElement(node, fragment);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ } else if (!node->IsHTMLElement()) {
+ // Presently unspec-ed: If |node| is in a non-HTML namespace: Drop.
+ node = DropElement(node, fragment);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ } else if (config_.drop_elements_.Contains(name)) {
+ // 5. If |name| is in |config|'s [=element drop list=] then 'drop'.
+ node = DropElement(node, fragment);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ } else if (config_.block_elements_.Contains(name)) {
+ // 6. If |name| is in |config|'s [=element block list=] then 'block'.
+ node = BlockElement(node, fragment, exception_state);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ } else if (!config_.allow_elements_.Contains(name)) {
+ // 7. if |name| is not in |config|'s [=element allow list=] then
+ // 'block'.
+ node = BlockElement(node, fragment, exception_state);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ } else if (IsA<HTMLTemplateElement>(node)) {
+ // 8. If |element|'s [=element interface=] is {{HTMLTemplateElement}}
+ // Run the steps of the [=sanitize document fragment=] algorithm on
+ // |element|'s |content| attribute.
+ DoSanitizing(To<HTMLTemplateElement>(node)->content(), window,
+ exception_state);
+ UseCounter::Count(window->GetExecutionContext(),
+ WebFeature::kSanitizerAPIActionTaken);
+ node = KeepElement(node, fragment, name, window);
+ } else {
+ node = KeepElement(node, fragment, name, window);
+ }
+ break;
+ }
+ case Node::NodeType::kTextNode:
+ // Text node: Keep (by skipping over it).
+ node = NodeTraversal::Next(*node, fragment);
+ break;
+ case Node::NodeType::kCommentNode:
+ // Comment: Drop (unless allowed by config).
+ node = config_.allow_comments_ ? NodeTraversal::Next(*node, fragment)
+ : DropElement(node, fragment);
+ break;
+ case Node::NodeType::kDocumentNode:
+ case Node::NodeType::kDocumentFragmentNode:
+ // Document & DocumentFragment: Drop (unless it's the root).
+ node = !node->parentNode() ? NodeTraversal::Next(*node, fragment)
+ : DropElement(node, fragment);
+ break;
+ default:
+ // Default: Drop anything not explicitly handled.
+ node = DropElement(node, fragment);
+ break;
}
}
-
- return fragment;
-}
-
-DocumentFragment* Sanitizer::SanitizeImpl(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8SanitizerInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrDocumentFragmentOrDocument&
- input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ExceptionState& exception_state) {
- LocalDOMWindow* window = LocalDOMWindow::From(script_state);
- DocumentFragment* fragment =
- PrepareFragment(window, script_state, input, exception_state);
- if (exception_state.HadException()) {
- return nullptr;
- }
- return DoSanitizing(fragment, window, exception_state);
}
// If the current element needs to be dropped, remove current element entirely
// and proceed to its next sibling.
-Node* Sanitizer::DropElement(Node* node, DocumentFragment* fragment) {
+Node* Sanitizer::DropElement(Node* node, ContainerNode* fragment) {
Node* tmp = node;
node = NodeTraversal::NextSkippingChildren(*node, fragment);
tmp->remove();
@@ -376,17 +304,12 @@ Node* Sanitizer::DropElement(Node* node, DocumentFragment* fragment) {
// If the current element should be blocked, append its children after current
// node to parent node, remove current element and proceed to the next node.
Node* Sanitizer::BlockElement(Node* node,
- DocumentFragment* fragment,
+ ContainerNode* fragment,
ExceptionState& exception_state) {
- Node* parent = node->parentNode();
+ ContainerNode* parent = node->parentNode();
Node* next_sibling = node->nextSibling();
- while (node->hasChildren()) {
- Node* n = node->firstChild();
- if (next_sibling) {
- parent->insertBefore(n, next_sibling, exception_state);
- } else {
- parent->appendChild(n, exception_state);
- }
+ while (Node* child = node->firstChild()) {
+ parent->InsertBefore(child, next_sibling, exception_state);
if (exception_state.HadException()) {
return nullptr;
}
@@ -400,12 +323,14 @@ Node* Sanitizer::BlockElement(Node* node,
// Remove any attributes to be dropped from the current element, and proceed to
// the next node (preorder, depth-first traversal).
Node* Sanitizer::KeepElement(Node* node,
- DocumentFragment* fragment,
+ ContainerNode* fragment,
String& node_name,
LocalDOMWindow* window) {
Element* element = To<Element>(node);
- if (config_.allow_attributes_.at("*").Contains(node_name)) {
- } else if (config_.drop_attributes_.at("*").Contains(node_name)) {
+ if (config_.allow_attributes_.DeprecatedAtOrEmptyValue("*").Contains(
+ node_name)) {
+ } else if (config_.drop_attributes_.DeprecatedAtOrEmptyValue("*").Contains(
+ node_name)) {
for (const auto& name : element->getAttributeNames()) {
element->removeAttribute(name);
UseCounter::Count(window->GetExecutionContext(),
@@ -415,15 +340,22 @@ Node* Sanitizer::KeepElement(Node* node,
for (const auto& name : element->getAttributeNames()) {
// Attributes in drop list or not in allow list while allow list
// exists will be dropped.
- bool drop = (baseline_drop_attributes_.Contains(name) &&
- (baseline_drop_attributes_.at(name) == kVectorStar ||
- baseline_drop_attributes_.at(name).Contains(node_name))) ||
- (config_.drop_attributes_.Contains(name) &&
- (config_.drop_attributes_.at(name) == kVectorStar ||
- config_.drop_attributes_.at(name).Contains(node_name))) ||
- !(config_.allow_attributes_.Contains(name) &&
- (config_.allow_attributes_.at(name) == kVectorStar ||
- config_.allow_attributes_.at(name).Contains(node_name)));
+ bool drop =
+ (baseline_drop_attributes_.Contains(name) &&
+ (baseline_drop_attributes_.DeprecatedAtOrEmptyValue(name) ==
+ kVectorStar ||
+ baseline_drop_attributes_.DeprecatedAtOrEmptyValue(name).Contains(
+ node_name))) ||
+ (config_.drop_attributes_.Contains(name) &&
+ (config_.drop_attributes_.DeprecatedAtOrEmptyValue(name) ==
+ kVectorStar ||
+ config_.drop_attributes_.DeprecatedAtOrEmptyValue(name).Contains(
+ node_name))) ||
+ !(config_.allow_attributes_.Contains(name) &&
+ (config_.allow_attributes_.DeprecatedAtOrEmptyValue(name) ==
+ kVectorStar ||
+ config_.allow_attributes_.DeprecatedAtOrEmptyValue(name).Contains(
+ node_name)));
// 9. If |element|'s [=element interface=] is {{HTMLAnchorElement}} or
// {{HTMLAreaElement}} and |element|'s `protocol` property is
// "javascript:", then remove the `href` attribute from |element|.
@@ -463,19 +395,16 @@ Node* Sanitizer::KeepElement(Node* node,
return node;
}
-SanitizerConfig* Sanitizer::config() const {
- return SanitizerConfigCopy(config_dictionary_
- ? config_dictionary_.Get()
- : SanitizerConfigImpl::defaultConfig());
+SanitizerConfig* Sanitizer::getConfiguration() const {
+ return SanitizerConfigImpl::ToAPI(config_);
}
-SanitizerConfig* Sanitizer::defaultConfig() {
- return SanitizerConfigCopy(SanitizerConfigImpl::defaultConfig());
+SanitizerConfig* Sanitizer::getDefaultConfiguration() {
+ return SanitizerConfigCopy(SanitizerConfigImpl::DefaultConfig());
}
void Sanitizer::Trace(Visitor* visitor) const {
ScriptWrappable::Trace(visitor);
- visitor->Trace(config_dictionary_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h
index 73c3ec23b84..4676649373f 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h
@@ -14,14 +14,13 @@
namespace blink {
+class ContainerNode;
class Document;
class DocumentFragment;
class ExceptionState;
class ExecutionContext;
class SanitizerConfig;
class ScriptState;
-class StringOrDocumentFragmentOrDocument;
-class StringOrTrustedHTMLOrDocumentFragmentOrDocument;
enum ElementKind {
kCustom,
@@ -36,72 +35,52 @@ class MODULES_EXPORT Sanitizer final : public ScriptWrappable {
static Sanitizer* Create(ExecutionContext*,
const SanitizerConfig*,
ExceptionState&);
- explicit Sanitizer(ExecutionContext*, const SanitizerConfig*);
+ Sanitizer(ExecutionContext*, const SanitizerConfig*);
~Sanitizer() override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- String sanitizeToString(ScriptState* script_state,
- const V8SanitizerInput* input,
- ExceptionState& exception_state);
DocumentFragment* sanitize(ScriptState* script_state,
- const V8SanitizerInputWithTrustedHTML* input,
+ const V8SanitizerInput* input,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- String sanitizeToString(ScriptState*,
- StringOrDocumentFragmentOrDocument&,
- ExceptionState&);
- DocumentFragment* sanitize(ScriptState*,
- StringOrTrustedHTMLOrDocumentFragmentOrDocument&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- SanitizerConfig* config() const;
- static SanitizerConfig* defaultConfig();
+ Element* sanitizeFor(ScriptState* script_state,
+ const String& element,
+ const String& markup,
+ ExceptionState& exception_state);
+
+ SanitizerConfig* getConfiguration() const;
+ static SanitizerConfig* getDefaultConfiguration();
+
+ // Implementation of ElementSanitizer::SetHTML, so that we have
+ // all the sanitizer logic in one place.
+ void ElementSetHTML(ScriptState* script_state,
+ Element& element,
+ const String& markup,
+ ExceptionState& exception_state);
void Trace(Visitor*) const override;
private:
- Node* DropElement(Node*, DocumentFragment*);
- Node* BlockElement(Node*, DocumentFragment*, ExceptionState&);
- Node* KeepElement(Node*, DocumentFragment*, String&, LocalDOMWindow*);
+ Node* DropElement(Node*, ContainerNode*);
+ Node* BlockElement(Node*, ContainerNode*, ExceptionState&);
+ Node* KeepElement(Node*, ContainerNode*, String&, LocalDOMWindow*);
void ElementFormatter(HashSet<String>&, const Vector<String>&);
void AttrFormatter(HashMap<String, Vector<String>>&,
const Vector<std::pair<String, Vector<String>>>&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DocumentFragment* PrepareFragment(LocalDOMWindow* window,
ScriptState* script_state,
const V8SanitizerInput* input,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DocumentFragment* PrepareFragment(LocalDOMWindow*,
- ScriptState*,
- StringOrDocumentFragmentOrDocument&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DocumentFragment* DoSanitizing(DocumentFragment*,
- LocalDOMWindow*,
- ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DocumentFragment* SanitizeImpl(ScriptState* script_state,
- const V8SanitizerInput* input,
- ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DocumentFragment* SanitizeImpl(ScriptState*,
- StringOrDocumentFragmentOrDocument&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ void DoSanitizing(ContainerNode*, LocalDOMWindow*, ExceptionState&);
SanitizerConfigImpl config_;
- Member<const SanitizerConfig> config_dictionary_;
// TODO(lyf): make it all-oilpan.
const Vector<String> kVectorStar = Vector<String>({"*"});
const HashSet<String> baseline_drop_elements_ = {
- "APPLET", "BASE", "EMBED", "IFRAME", "NOEMBED",
- "NOFRAMES", "NOLAYER", "NOSCRIPT", "OBJECT", "FRAME",
- "FRAMESET", "PARAM", "SCRIPT"};
+ "applet", "base", "embed", "iframe", "noembed",
+ "noframes", "nolayer", "noscript", "object", "frame",
+ "frameset", "param", "script"};
const HashMap<String, Vector<String>> baseline_drop_attributes_ = {
{"onabort", kVectorStar},
{"onafterprint", kVectorStar},
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl
index 21f02b271c8..a97bfcb8bc2 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl
@@ -4,18 +4,19 @@
// https://github.com/WICG/sanitizer-api
-typedef (DOMString or DocumentFragment or Document) SanitizerInput;
-typedef (DOMString or TrustedHTML or DocumentFragment or Document) SanitizerInputWithTrustedHTML;
+typedef (DocumentFragment or Document) SanitizerInput;
[
Exposed=Window,
+ SecureContext,
RuntimeEnabled=SanitizerAPI
] interface Sanitizer {
[MeasureAs=SanitizerAPICreated, CallWith=ExecutionContext, RaisesException] constructor(optional SanitizerConfig config = {});
- [MeasureAs=SanitizerAPIToFragment, CallWith=ScriptState, RaisesException] DocumentFragment sanitize(SanitizerInputWithTrustedHTML input);
- [MeasureAs=SanitizerAPIToString, CallWith=ScriptState, RaisesException] DOMString sanitizeToString(SanitizerInput input);
+ [MeasureAs=SanitizerAPIToFragment, CallWith=ScriptState, RaisesException] DocumentFragment sanitize(SanitizerInput input);
+ [MeasureAs=SanitizerAPISanitizeFor, CallWith=ScriptState, RaisesException] Element? sanitizeFor(DOMString element, DOMString markup);
- [MeasureAs=SanitizerAPIGetConfig] SanitizerConfig config();
- [MeasureAs=SanitizerAPIGetDefaultConfig] static SanitizerConfig defaultConfig();
+ [MeasureAs=SanitizerAPIGetConfig] SanitizerConfig getConfiguration();
+ [MeasureAs=SanitizerAPIGetDefaultConfig] static SanitizerConfig getDefaultConfiguration();
};
+
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api.dict b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api.dict
index 2dfde8685bd..af1caca08b8 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api.dict
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api.dict
@@ -367,7 +367,6 @@
"inputmode"
"cellpadding"
"onmessage"
-"disallowdocumentaccess"
"h2"
"h3"
"image"
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api_fuzzer.cc b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api_fuzzer.cc
index 9ea259d7261..68dd6b092c2 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_api_fuzzer.cc
@@ -7,11 +7,12 @@
// To test out locally:
// - Assuming
// $OUT is your local build output directory with use_libbfuzzer set.
-// $GEN is the suitable 'gen' directory under $OUT. $GEN is
-// $OUT/gen/third_party_blink/renderer/modules/sanitizer_api.
+// $GEN is the suitable 'gen' directory under $OUT.
+//
// - Build:
// $ ninja -C $OUT sanitizer_api_fuzzer
// - Run with:
+// $ GEN=$OUT/gen/third_party/blink/renderer/modules/sanitizer_api
// $ $OUT/sanitizer_api_fuzzer --dict=$GEN/sanitizer_api.dict \
// $(mktemp -d) $GEN/corpus/
@@ -19,10 +20,6 @@
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_document_documentfragment_string_trustedhtml.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_document_fragment_or_document.h"
-#include "third_party/blink/renderer/bindings/modules/v8/string_or_trusted_html_or_document_fragment_or_document.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_sanitizer_config.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
@@ -81,6 +78,7 @@ void MakeConfiguration(SanitizerConfig* sanitizer_config,
sanitizer_config->setDropAttributes(drop_attributes);
}
sanitizer_config->setAllowCustomElements(proto.allow_custom_elements());
+ sanitizer_config->setAllowComments(proto.allow_comments());
}
void TextProtoFuzzer(const SanitizerConfigProto& proto,
@@ -92,28 +90,26 @@ void TextProtoFuzzer(const SanitizerConfigProto& proto,
auto* sanitizer = MakeGarbageCollected<Sanitizer>(
window->GetExecutionContext(), sanitizer_config);
- // Sanitize string given in proto. Method depends on sanitize_to_string.
- String str = proto.html_string().c_str();
- if (proto.sanitize_to_string()) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- auto* str1 = MakeGarbageCollected<
- V8UnionDocumentOrDocumentFragmentOrStringOrTrustedHTML>(str);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrTrustedHTMLOrDocumentFragmentOrDocument str1 =
- StringOrTrustedHTMLOrDocumentFragmentOrDocument::FromString(str);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- sanitizer->sanitize(script_state, str1, IGNORE_EXCEPTION_FOR_TESTING);
- } else {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- auto* str2 =
- MakeGarbageCollected<V8UnionDocumentOrDocumentFragmentOrString>(str);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrDocumentFragmentOrDocument str2 =
- StringOrDocumentFragmentOrDocument::FromString(str);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- sanitizer->sanitizeToString(script_state, str2,
- IGNORE_EXCEPTION_FOR_TESTING);
+ // Sanitize string given in proto. Use proto.string_context to decide on
+ // parsing context for sanitizeFor.
+ // TODO(1225606): This needs to be updated to also support SVG & MathML
+ // contexts, once those are implemented.
+ String markup = proto.html_string().c_str();
+ const char* string_context = nullptr;
+ switch (proto.string_context()) {
+ case SanitizerConfigProto::DIV:
+ string_context = "div";
+ break;
+ case SanitizerConfigProto::TABLE:
+ string_context = "table";
+ break;
+ case SanitizerConfigProto::TEMPLATE:
+ default:
+ string_context = "template";
+ break;
}
+ sanitizer->sanitizeFor(script_state, string_context, markup,
+ IGNORE_EXCEPTION_FOR_TESTING);
// The fuzzer will eventually run out of memory. Force the GC to run every
// N-th time. This will trigger both V8 + Oilpan GC.
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.idl b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.idl
index c5c3c860f56..d05aebbc1ad 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.idl
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.idl
@@ -11,4 +11,5 @@ dictionary SanitizerConfig {
record<DOMString, sequence<DOMString>> allowAttributes;
record<DOMString, sequence<DOMString>> dropAttributes;
boolean allowCustomElements;
+ boolean allowComments;
};
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.proto b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.proto
index 7f463efa4ed..c555303eb8d 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.proto
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.proto
@@ -16,5 +16,12 @@ message SanitizerConfigProto {
map<string, Elements> drop_attributes = 6;
optional bool allow_custom_elements = 7;
- optional bool sanitize_to_string = 8;
+ optional bool allow_comments = 8;
+
+ enum StringContext {
+ TEMPLATE = 0;
+ DIV = 1;
+ TABLE = 2;
+ }
+ optional StringContext string_context = 9;
}
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc
index 9e56ecec0cf..e7f568b1121 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h"
-#include "third_party/blink/renderer/modules/sanitizer_api/sanitizer_config.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_sanitizer_config.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -98,7 +98,6 @@ const char* kDefaultAllowAttributes[] = {"abbr",
"disabled",
"disablepictureinpicture",
"disableremoteplayback",
- "disallowdocumentaccess",
"download",
"draggable",
"elementtiming",
@@ -262,7 +261,7 @@ const char* kDefaultAllowAttributes[] = {"abbr",
void ElementFormatter(HashSet<String>& element_set,
const Vector<String>& elements) {
for (const String& s : elements) {
- element_set.insert(s.UpperASCII());
+ element_set.insert(s.LowerASCII());
}
}
@@ -276,7 +275,7 @@ void AttrFormatter(HashMap<String, Vector<String>>& attr_map,
} else {
Vector<String> elements;
for (const String& s : pair.second) {
- elements.push_back(s.UpperASCII());
+ elements.push_back(s.LowerASCII());
}
attr_map.insert(lower_attr, elements);
}
@@ -313,6 +312,21 @@ SanitizerConfigImpl GetDefaultConfigImpl() {
return config_;
}
+Vector<String> Copy(const HashSet<String>& set) {
+ Vector<String> result;
+ std::copy(std::cbegin(set), std::cend(set), std::back_inserter(result));
+ return result;
+}
+
+Vector<std::pair<String, Vector<String>>> Copy(
+ const HashMap<String, Vector<String>>& map) {
+ Vector<std::pair<String, Vector<String>>> result;
+ for (const auto& item : map) {
+ result.push_back(std::make_pair(item.key, item.value));
+ }
+ return result;
+}
+
} // anonymous namespace
// Create a SanitizerConfigImpl from a SanitizerConfig.
@@ -330,18 +344,19 @@ SanitizerConfigImpl SanitizerConfigImpl::From(const SanitizerConfig* config) {
impl.allow_custom_elements_ =
config->hasAllowCustomElements() && config->allowCustomElements();
+ impl.allow_comments_ = config->hasAllowComments() && config->allowComments();
- // Format dropElements to uppercase.
+ // Format dropElements to lower case.
if (config->hasDropElements()) {
ElementFormatter(impl.drop_elements_, config->dropElements());
}
- // Format blockElements to uppercase.
+ // Format blockElements to lower case.
if (config->hasBlockElements()) {
ElementFormatter(impl.block_elements_, config->blockElements());
}
- // Format allowElements to uppercase.
+ // Format allowElements to lower case.
if (config->hasAllowElements()) {
ElementFormatter(impl.allow_elements_, config->allowElements());
} else {
@@ -360,10 +375,42 @@ SanitizerConfigImpl SanitizerConfigImpl::From(const SanitizerConfig* config) {
impl.allow_attributes_ = GetDefaultConfigImpl().allow_attributes_;
}
+ impl.had_allow_elements_ = config->hasAllowElements();
+ impl.had_allow_attributes_ = config->hasAllowAttributes();
+ impl.had_allow_custom_elements_ = config->hasAllowCustomElements();
+
return impl;
}
-SanitizerConfig* SanitizerConfigImpl::defaultConfig() {
+SanitizerConfig* SanitizerConfigImpl::ToAPI(const SanitizerConfigImpl& impl) {
+ SanitizerConfig* config = SanitizerConfig::Create();
+
+ if (impl.had_allow_elements_) {
+ config->setAllowElements(Copy(impl.allow_elements_));
+ }
+
+ if (!impl.drop_elements_.IsEmpty()) {
+ config->setDropElements(Copy(impl.drop_elements_));
+ }
+
+ if (!impl.block_elements_.IsEmpty()) {
+ config->setBlockElements(Copy(impl.block_elements_));
+ }
+
+ if (impl.had_allow_attributes_) {
+ config->setAllowAttributes(Copy(impl.allow_attributes_));
+ }
+
+ if (!impl.drop_attributes_.IsEmpty()) {
+ config->setDropAttributes(Copy(impl.drop_attributes_));
+ }
+
+ if (impl.had_allow_custom_elements_)
+ config->setAllowCustomElements(impl.allow_custom_elements_);
+ return config;
+}
+
+SanitizerConfig* SanitizerConfigImpl::DefaultConfig() {
return GetDefaultConfig();
}
diff --git a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h
index b2d0bff65f4..274295da57f 100644
--- a/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h
+++ b/chromium/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h
@@ -30,12 +30,24 @@ struct SanitizerConfigImpl {
HashMap<String, Vector<String>> allow_attributes_;
HashMap<String, Vector<String>> drop_attributes_;
bool allow_custom_elements_;
+ bool allow_comments_;
+
+ // These members store whether the original SanitizerConfig had the
+ // corresponding members set or not. This only serves to reconstruct the
+ // SanitizerConfig* in the ToAPI method.
+ bool had_allow_elements_;
+ bool had_allow_attributes_;
+ bool had_allow_custom_elements_;
// Create a SantizerConfigImpl from a SanitizerConfig.
// Will use the default config if it received nullptr.
static SanitizerConfigImpl From(const SanitizerConfig*);
- static SanitizerConfig* defaultConfig();
+ // Create an IDL SanitizerConfig from this impl, for use in the config()
+ // accessor.
+ static SanitizerConfig* ToAPI(const SanitizerConfigImpl&);
+
+ static SanitizerConfig* DefaultConfig();
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
index 667cd3129ca..3714a701e8e 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -20,24 +20,23 @@ namespace blink {
const char DOMScheduler::kSupplementName[] = "DOMScheduler";
-DOMScheduler* DOMScheduler::scheduler(LocalDOMWindow& window) {
+DOMScheduler* DOMScheduler::scheduler(ExecutionContext& context) {
DOMScheduler* scheduler =
- Supplement<LocalDOMWindow>::From<DOMScheduler>(window);
+ Supplement<ExecutionContext>::From<DOMScheduler>(context);
if (!scheduler) {
- scheduler = MakeGarbageCollected<DOMScheduler>(&window);
- Supplement<LocalDOMWindow>::ProvideTo(window, scheduler);
+ scheduler = MakeGarbageCollected<DOMScheduler>(&context);
+ Supplement<ExecutionContext>::ProvideTo(context, scheduler);
}
return scheduler;
}
-DOMScheduler::DOMScheduler(LocalDOMWindow* window)
- : ExecutionContextLifecycleObserver(window),
- Supplement<LocalDOMWindow>(*window) {
- if (window->IsContextDestroyed())
+DOMScheduler::DOMScheduler(ExecutionContext* context)
+ : ExecutionContextLifecycleObserver(context),
+ Supplement<ExecutionContext>(*context) {
+ if (context->IsContextDestroyed())
return;
- DCHECK(window->GetScheduler());
- DCHECK(window->GetScheduler()->ToFrameScheduler());
- CreateFixedPriorityTaskQueues(window);
+ DCHECK(context->GetScheduler());
+ CreateFixedPriorityTaskQueues(context);
}
void DOMScheduler::ContextDestroyed() {
@@ -50,7 +49,7 @@ void DOMScheduler::Trace(Visitor* visitor) const {
visitor->Trace(signal_to_task_queue_map_);
ScriptWrappable::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
- Supplement<LocalDOMWindow>::Trace(visitor);
+ Supplement<ExecutionContext>::Trace(visitor);
}
ScriptPromise DOMScheduler::postTask(
@@ -65,7 +64,7 @@ ScriptPromise DOMScheduler::postTask(
"Current window is detached");
return ScriptPromise();
}
- if (options->signal() && options->signal()->aborted()) {
+ if (options->hasSignal() && options->signal()->aborted()) {
exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
"The task was aborted");
return ScriptPromise();
@@ -73,8 +72,8 @@ ScriptPromise DOMScheduler::postTask(
// Always honor the priority and the task signal if given.
DOMTaskSignal* task_signal = nullptr;
- // TODO(crbug.com/1070871): Stop using APIs for non-null.
- if (!options->hasPriorityNonNull() && IsA<DOMTaskSignal>(options->signal())) {
+ if (!options->hasPriority() && options->hasSignal() &&
+ IsA<DOMTaskSignal>(options->signal())) {
// If only a signal is given, and it is a TaskSignal rather than an
// basic AbortSignal, use it.
task_signal = To<DOMTaskSignal>(options->signal());
@@ -92,12 +91,11 @@ ScriptPromise DOMScheduler::postTask(
// own task queue. Instead, it will use the appropriate task queue from
// |fixed_priority_task_queues_|.
WebSchedulingPriority priority =
- options->hasPriorityNonNull()
- ? WebSchedulingPriorityFromString(
- AtomicString(IDLEnumAsString(options->priorityNonNull())))
- : kDefaultPriority;
+ options->hasPriority() ? WebSchedulingPriorityFromString(AtomicString(
+ IDLEnumAsString(options->priority())))
+ : kDefaultPriority;
task_signal = CreateTaskSignalFor(priority);
- if (options->signal())
+ if (options->hasSignal())
task_signal->Follow(options->signal());
}
@@ -107,18 +105,10 @@ ScriptPromise DOMScheduler::postTask(
->GetWebSchedulingTaskQueue()
->GetTaskRunner()
.get();
-
- // TODO(shaseley): We need to figure out the behavior we want for delay. For
- // now, we use behavior that is very similar to setTimeout: negative delays
- // are treated as 0, and we use the Blink scheduler's delayed task behavior.
- // We don't, however, adjust the timeout based on nested calls (yet) or clamp
- // the value to a minimal delay.
- base::TimeDelta delay =
- base::TimeDelta::FromMilliseconds(std::max(0, options->delay()));
-
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- MakeGarbageCollected<DOMTask>(this, resolver, callback_function, task_signal,
- task_runner, delay);
+ MakeGarbageCollected<DOMTask>(
+ resolver, callback_function, task_signal, task_runner,
+ base::TimeDelta::FromMilliseconds(options->delay()));
return resolver->Promise();
}
@@ -137,8 +127,8 @@ DOMTaskSignal* DOMScheduler::currentTaskSignal(ScriptState* script_state) {
return CreateTaskSignalFor(kDefaultPriority);
}
-void DOMScheduler::CreateFixedPriorityTaskQueues(LocalDOMWindow* window) {
- FrameScheduler* scheduler = window->GetScheduler()->ToFrameScheduler();
+void DOMScheduler::CreateFixedPriorityTaskQueues(ExecutionContext* context) {
+ FrameOrWorkerScheduler* scheduler = context->GetScheduler();
for (size_t i = 0; i < kWebSchedulingPriorityCount; i++) {
std::unique_ptr<WebSchedulingTaskQueue> task_queue =
scheduler->CreateWebSchedulingTaskQueue(
@@ -159,8 +149,7 @@ DOMTaskSignal* DOMScheduler::CreateTaskSignalFor(
}
void DOMScheduler::CreateTaskQueueFor(DOMTaskSignal* signal) {
- FrameScheduler* scheduler =
- GetExecutionContext()->GetScheduler()->ToFrameScheduler();
+ FrameOrWorkerScheduler* scheduler = GetExecutionContext()->GetScheduler();
DCHECK(scheduler);
WebSchedulingPriority priority =
WebSchedulingPriorityFromString(signal->priority());
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
index 2c593ce95d5..1acdcb25b7c 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -50,15 +51,15 @@ class WebSchedulingTaskQueue;
*/
class MODULES_EXPORT DOMScheduler : public ScriptWrappable,
public ExecutionContextLifecycleObserver,
- public Supplement<LocalDOMWindow> {
+ public Supplement<ExecutionContext> {
DEFINE_WRAPPERTYPEINFO();
public:
static const char kSupplementName[];
- static DOMScheduler* scheduler(LocalDOMWindow&);
+ static DOMScheduler* scheduler(ExecutionContext&);
- explicit DOMScheduler(LocalDOMWindow*);
+ explicit DOMScheduler(ExecutionContext*);
// postTask creates and queues a DOMTask and returns a Promise that will
// resolve when it completes. The task will be scheduled in the queue
@@ -115,7 +116,7 @@ class MODULES_EXPORT DOMScheduler : public ScriptWrappable,
std::unique_ptr<WebSchedulingTaskQueue> web_scheduling_task_queue_;
};
- void CreateFixedPriorityTaskQueues(LocalDOMWindow*);
+ void CreateFixedPriorityTaskQueues(ExecutionContext*);
// Create a new fixed-priority DOMTaskSignal for the given priority and set up
// the mapping in |signal_to_task_queue_map_|.
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc
index 00e032dbe24..acd4a5d45e6 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc
@@ -11,10 +11,11 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_callback.h"
#include "third_party/blink/renderer/core/dom/dom_exception.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/scheduler/dom_scheduler.h"
#include "third_party/blink/renderer/modules/scheduler/dom_task_signal.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
namespace blink {
@@ -31,20 +32,29 @@ namespace blink {
sample, base::TimeDelta::FromMilliseconds(1), \
base::TimeDelta::FromMinutes(1), 50)
-DOMTask::DOMTask(DOMScheduler* scheduler,
- ScriptPromiseResolver* resolver,
+namespace {
+void PostTaskCallbackTraceEventData(perfetto::TracedValue context,
+ const String& priority,
+ const double delay) {
+ auto dict = std::move(context).WriteDictionary();
+ dict.Add("priority", priority);
+ dict.Add("delay", delay);
+ SetCallStack(dict);
+}
+} // namespace
+
+DOMTask::DOMTask(ScriptPromiseResolver* resolver,
V8SchedulerPostTaskCallback* callback,
DOMTaskSignal* signal,
base::SingleThreadTaskRunner* task_runner,
base::TimeDelta delay)
- : scheduler_(scheduler),
- callback_(callback),
+ : callback_(callback),
resolver_(resolver),
signal_(signal),
// TODO(kdillon): Expose queuing time from base::sequence_manager so we
// don't have to recalculate it here.
- queue_time_(delay.is_zero() ? base::TimeTicks::Now()
- : base::TimeTicks()) {
+ queue_time_(delay.is_zero() ? base::TimeTicks::Now() : base::TimeTicks()),
+ delay_(delay) {
DCHECK(signal_);
DCHECK(task_runner);
DCHECK(callback_);
@@ -62,7 +72,6 @@ DOMTask::DOMTask(DOMScheduler* scheduler,
}
void DOMTask::Trace(Visitor* visitor) const {
- visitor->Trace(scheduler_);
visitor->Trace(callback_);
visitor->Trace(resolver_);
visitor->Trace(signal_);
@@ -71,10 +80,30 @@ void DOMTask::Trace(Visitor* visitor) const {
void DOMTask::Invoke() {
DCHECK(callback_);
+ // Tasks are not runnable if the document associated with this task's
+ // scheduler's global is not fully active, which happens if the
+ // ExecutionContext is detached. Note that this context can be different
+ // from the the callback's relevant context.
+ ExecutionContext* scheduler_context = resolver_->GetExecutionContext();
+ if (!scheduler_context || scheduler_context->IsContextDestroyed())
+ return;
+
ScriptState* script_state =
callback_->CallbackRelevantScriptStateOrReportError("DOMTask", "Invoke");
- if (!script_state || !script_state->ContextIsValid())
+ if (!script_state || !script_state->ContextIsValid()) {
+ DCHECK(resolver_->GetExecutionContext() &&
+ !resolver_->GetExecutionContext()->IsContextDestroyed());
+ // The scheduler's context is still attached, but the task's callback's
+ // relvant context is not. This happens, for example, if an attached main
+ // frame's scheduler schedules a task that runs a callback defined in a
+ // detached child frame. The callback's relvant context must be valid to run
+ // the callback (enforced in the bindings layer). Since we can't run this
+ // task, and therefore won't settle the associated promise, we need to clean
+ // up the ScriptPromiseResolver since it is associated with a different
+ // context.
+ resolver_->Detach();
return;
+ }
RecordTaskStartMetrics();
InvokeInternal(script_state);
@@ -86,6 +115,10 @@ void DOMTask::InvokeInternal(ScriptState* script_state) {
ScriptState::Scope scope(script_state);
v8::TryCatch try_catch(isolate);
+ DEVTOOLS_TIMELINE_TRACE_EVENT("RunPostTaskCallback",
+ PostTaskCallbackTraceEventData,
+ signal_->priority(), delay_.InMillisecondsF());
+
ExecutionContext* context = ExecutionContext::From(script_state);
DCHECK(context);
probe::AsyncTask async_task(context, &async_task_id_);
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task.h b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.h
index 72855e358b1..f9c9b6e9216 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_task.h
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.h
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
namespace blink {
-class DOMScheduler;
class DOMTaskSignal;
class ScriptState;
class V8SchedulerPostTaskCallback;
@@ -22,8 +21,7 @@ class V8SchedulerPostTaskCallback;
// callback's v8 context is invalid, in which case, the task will not be run.
class DOMTask final : public GarbageCollected<DOMTask> {
public:
- DOMTask(DOMScheduler*,
- ScriptPromiseResolver*,
+ DOMTask(ScriptPromiseResolver*,
V8SchedulerPostTaskCallback*,
DOMTaskSignal*,
base::SingleThreadTaskRunner*,
@@ -41,13 +39,16 @@ class DOMTask final : public GarbageCollected<DOMTask> {
void RecordTaskStartMetrics();
- Member<DOMScheduler> scheduler_;
TaskHandle task_handle_;
Member<V8SchedulerPostTaskCallback> callback_;
Member<ScriptPromiseResolver> resolver_;
probe::AsyncTaskId async_task_id_;
+ // Do not remove. For dynamic priority task queues, |signal_| ensures that the
+ // associated WebSchedulingTaskQueue stays alive until after this task runs,
+ // which is necessary to ensure throttling works correctly.
Member<DOMTaskSignal> signal_;
const base::TimeTicks queue_time_;
+ const base::TimeDelta delay_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.cc
index e867cf2fb04..e79212e26f1 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/scheduler/dom_task_controller.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_task_controller_init.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/scheduler/dom_task_signal.h"
@@ -11,8 +12,8 @@ namespace blink {
// static
DOMTaskController* DOMTaskController::Create(ExecutionContext* context,
- const AtomicString& priority) {
- return MakeGarbageCollected<DOMTaskController>(context, priority);
+ TaskControllerInit* init) {
+ return MakeGarbageCollected<DOMTaskController>(context, init->priority());
}
DOMTaskController::DOMTaskController(ExecutionContext* context,
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.h b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.h
index 1cd92f71d6b..4c5786f465a 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.h
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_controller.h
@@ -12,13 +12,13 @@
namespace blink {
class ExceptionState;
class ExecutionContext;
+class TaskControllerInit;
class MODULES_EXPORT DOMTaskController final : public AbortController {
DEFINE_WRAPPERTYPEINFO();
public:
- static DOMTaskController* Create(ExecutionContext*,
- const AtomicString& priority);
+ static DOMTaskController* Create(ExecutionContext*, TaskControllerInit*);
DOMTaskController(ExecutionContext*, const AtomicString& priority);
void setPriority(const AtomicString& priority, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc
index 0c2449926d2..7a17f27d748 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc
@@ -7,10 +7,10 @@
#include <utility>
#include "base/callback.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_task_priority_change_event_init.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/scheduler/task_priority_change_event.h"
-#include "third_party/blink/renderer/modules/scheduler/task_priority_change_event_init.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/idls.gni b/chromium/third_party/blink/renderer/modules/scheduler/idls.gni
deleted file mode 100644
index 581effd2904..00000000000
--- a/chromium/third_party/blink/renderer/modules/scheduler/idls.gni
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "scheduler.idl",
- "task_controller.idl",
- "task_priority_change_event.idl",
- "task_signal.idl",
-]
-
-modules_dictionary_idl_files = [
- "scheduler_post_task_options.idl",
- "task_priority_change_event_init.idl",
-]
-
-modules_dependency_idl_files = [ "window_scheduler.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl b/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl
index a06f1bc2113..8fbedd6108b 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Experimental Scheduling API Proposal:
-// https://docs.google.com/document/d/1Apz-SD-pOagGeyWxIpgOi0ARNkrCrELhPdm18eeu9tw
+// https://wicg.github.io/scheduling-apis/#sec-scheduler
+//
+// currentTaskSignal:
+// https://github.com/WICG/scheduling-apis/blob/main/explainers/post-task-propagation.md
[
- Exposed=Window,
+ Exposed=(Window,Worker),
ImplementedAs=DOMScheduler,
RuntimeEnabled=WebScheduler
] interface Scheduler {
[CallWith=ScriptState, MeasureAs=SchedulerPostTask, RaisesException] Promise<any> postTask(SchedulerPostTaskCallback callback, optional SchedulerPostTaskOptions options = {});
- [CallWith=ScriptState, MeasureAs=SchedulerCurrentTaskSignal] readonly attribute TaskSignal currentTaskSignal;
+ [CallWith=ScriptState, MeasureAs=SchedulerCurrentTaskSignal, RuntimeEnabled=SchedulerCurrentTaskSignal] readonly attribute TaskSignal currentTaskSignal;
};
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_callback.idl b/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_callback.idl
index 7dc1b251eb7..97c205c9870 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_callback.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_callback.idl
@@ -2,6 +2,5 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Experimental Scheduling API Proposal:
-// https://docs.google.com/document/d/1Apz-SD-pOagGeyWxIpgOi0ARNkrCrELhPdm18eeu9tw
+// https://wicg.github.io/scheduling-apis/#sec-scheduler
callback SchedulerPostTaskCallback = any ();
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl b/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl
index 2e9704eb05b..e8459a0c384 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Experimental Scheduling API Proposal:
-// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
+// https://wicg.github.io/scheduling-apis/#sec-task-priorities
enum TaskPriority {
"user-blocking",
"user-visible",
"background"
};
+// https://wicg.github.io/scheduling-apis/#sec-scheduler
dictionary SchedulerPostTaskOptions {
- AbortSignal? signal = null;
- TaskPriority? priority = null;
- long delay = 0;
+ AbortSignal signal;
+ TaskPriority priority;
+ [EnforceRange] unsigned long long delay = 0;
};
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_controller.idl b/chromium/third_party/blink/renderer/modules/scheduler/task_controller.idl
index 65d1f9c0ef6..7543ad13a3c 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_controller.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_controller.idl
@@ -2,16 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Experimental Scheduling API Proposal:
-// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
-
+// https://wicg.github.io/scheduling-apis/#sec-task-controller
[
- Exposed=Window,
+ Exposed=(Window,Worker),
ImplementedAs=DOMTaskController,
MeasureAs=TaskControllerConstructor,
RuntimeEnabled=WebScheduler
] interface TaskController : AbortController {
- [CallWith=ExecutionContext] constructor(optional TaskPriority priority = "user-visible");
+ [CallWith=ExecutionContext] constructor(optional TaskControllerInit init = {});
[MeasureAs=TaskControllerSetPriority, RaisesException] void setPriority(TaskPriority priority);
};
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_controller_init.idl b/chromium/third_party/blink/renderer/modules/scheduler/task_controller_init.idl
new file mode 100644
index 00000000000..0610651b124
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_controller_init.idl
@@ -0,0 +1,8 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://wicg.github.io/scheduling-apis/#sec-task-controller
+dictionary TaskControllerInit {
+ TaskPriority priority = "user-visible";
+};
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.cc b/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.cc
index b08d8cf19d4..7d4ffee98da 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.cc
@@ -28,7 +28,7 @@ const AtomicString& TaskPriorityChangeEvent::InterfaceName() const {
return event_interface_names::kTaskPriorityChangeEvent;
}
-AtomicString TaskPriorityChangeEvent::previousPriority() const {
+V8TaskPriority TaskPriorityChangeEvent::previousPriority() const {
return previous_priority_;
}
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.h b/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.h
index c4d99fb1cd4..416f303d648 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.h
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_PRIORITY_CHANGE_EVENT_H_
#include "base/macros.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_task_priority.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -27,10 +28,10 @@ class MODULES_EXPORT TaskPriorityChangeEvent final : public Event {
const AtomicString& InterfaceName() const override;
- AtomicString previousPriority() const;
+ V8TaskPriority previousPriority() const;
private:
- const AtomicString previous_priority_;
+ const V8TaskPriority previous_priority_;
DISALLOW_COPY_AND_ASSIGN(TaskPriorityChangeEvent);
};
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.idl b/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.idl
index e995c4692fb..856d610a37b 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_priority_change_event.idl
@@ -4,7 +4,7 @@
// https://wicg.github.io/scheduling-apis/#sec-task-priority-change-event
[
- Exposed=Window,
+ Exposed=(Window,Worker),
RuntimeEnabled=WebScheduler
] interface TaskPriorityChangeEvent : Event {
constructor(DOMString type, TaskPriorityChangeEventInit eventInitDict);
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_signal.idl b/chromium/third_party/blink/renderer/modules/scheduler/task_signal.idl
index 7bd080401fd..1b292008e0d 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_signal.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_signal.idl
@@ -2,11 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Experimental Scheduling API Proposal:
-// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
-
+// https://wicg.github.io/scheduling-apis/#sec-task-signal
[
- Exposed=Window,
+ Exposed=(Window,Worker),
ImplementedAs=DOMTaskSignal,
RuntimeEnabled=WebScheduler
] interface TaskSignal : AbortSignal {
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.idl b/chromium/third_party/blink/renderer/modules/scheduler/window_or_worker_scheduler.idl
index 439b421567a..5c729427d68 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/window_or_worker_scheduler.idl
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Experimental Scheduling API Proposal:
-// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
+// https://wicg.github.io/scheduling-apis/#sec-patches-html-windoworworkerglobalscope
[
- ImplementedAs=DOMScheduler
-] partial interface Window {
+ ImplementedAs=DOMScheduler,
+ Exposed=(Window,Worker)
+] partial interface mixin WindowOrWorkerGlobalScope {
[RuntimeEnabled=WebScheduler, SameObject, Replaceable] readonly attribute Scheduler scheduler;
};
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn b/chromium/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn
index fe1a04ede6d..5e8e8d9a8a4 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn
@@ -6,8 +6,6 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("screen_enumeration") {
sources = [
- "global_screen_enumeration.cc",
- "global_screen_enumeration.h",
"screen_advanced.cc",
"screen_advanced.h",
"screens.cc",
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc b/chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc
deleted file mode 100644
index bf0a211c01f..00000000000
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.h"
-
-#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
-#include "third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom-blink.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/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/screen.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/heap/heap.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "ui/display/mojom/display.mojom-blink.h"
-
-namespace blink {
-
-namespace {
-
-void DidGetDisplays(ScriptPromiseResolver* resolver,
- mojo::Remote<mojom::blink::ScreenEnumeration>,
- mojom::blink::DisplaysPtr result) {
- ScriptState* script_state = resolver->GetScriptState();
- if (!script_state->ContextIsValid())
- return;
-
- ScriptState::Scope scope(script_state);
- if (result.is_null()) {
- resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
- script_state->GetIsolate(), DOMExceptionCode::kNotAllowedError,
- "Screen information is unavailable or access is not allowed."));
- return;
- }
-
- HeapVector<Member<Screen>> screens;
- screens.ReserveInitialCapacity(result->displays.size());
- for (display::mojom::blink::DisplayPtr& display : result->displays) {
- const bool internal = display->id == result->internal_id;
- const bool primary = display->id == result->primary_id;
- // TODO(http://crbug.com/994889): Implement temporary, generated per-origin
- // unique device IDs that reset when cookies are deleted. See related:
- // web_bluetooth_device_id.h, unguessable_token.h, and uuid.h
- const String id = String::NumberToStringECMAScript(screens.size());
- screens.emplace_back(MakeGarbageCollected<Screen>(std::move(display),
- internal, primary, id));
- }
- resolver->Resolve(std::move(screens));
-}
-
-void DidHasMultipleDisplays(ScriptPromiseResolver* resolver,
- mojo::Remote<mojom::blink::ScreenEnumeration>,
- mojom::blink::MultipleDisplays result) {
- ScriptState* script_state = resolver->GetScriptState();
- if (!script_state->ContextIsValid())
- return;
-
- ScriptState::Scope scope(script_state);
- if (result == mojom::blink::MultipleDisplays::kError) {
- resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
- script_state->GetIsolate(), DOMExceptionCode::kNotAllowedError,
- "Screen information is unavailable or access is not allowed."));
- return;
- }
-
- resolver->Resolve(result == mojom::blink::MultipleDisplays::kTrue);
-}
-
-} // namespace
-
-// static
-ScriptPromise GlobalScreenEnumeration::getScreensDeprecated(
- ScriptState* script_state,
- LocalDOMWindow&,
- ExceptionState& exception_state) {
- if (!script_state->ContextIsValid()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The execution context is not valid.");
- return ScriptPromise();
- }
-
- // TODO(msw): Cache the backend connection.
- mojo::Remote<mojom::blink::ScreenEnumeration> backend;
- ExecutionContext::From(script_state)
- ->GetBrowserInterfaceBroker()
- .GetInterface(backend.BindNewPipeAndPassReceiver());
-
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- auto* raw_backend = backend.get();
- raw_backend->GetDisplays(
- WTF::Bind(&DidGetDisplays, WrapPersistent(resolver), std::move(backend)));
- return resolver->Promise();
-}
-
-// static
-ScriptPromise GlobalScreenEnumeration::isMultiScreen(
- ScriptState* script_state,
- LocalDOMWindow&,
- ExceptionState& exception_state) {
- if (!script_state->ContextIsValid()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The execution context is not valid.");
- return ScriptPromise();
- }
-
- auto* context = ExecutionContext::From(script_state);
- if (!context->IsFeatureEnabled(
- mojom::blink::PermissionsPolicyFeature::kWindowPlacement)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "Screen information is unavailable or access is not allowed.");
- return ScriptPromise();
- }
-
- // TODO(msw): Cache the backend connection.
- mojo::Remote<mojom::blink::ScreenEnumeration> backend;
- context->GetBrowserInterfaceBroker().GetInterface(
- backend.BindNewPipeAndPassReceiver());
-
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- auto* raw_backend = backend.get();
- raw_backend->HasMultipleDisplays(WTF::Bind(
- &DidHasMultipleDisplays, WrapPersistent(resolver), std::move(backend)));
- return resolver->Promise();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.h b/chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.h
deleted file mode 100644
index c773cd7e03d..00000000000
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_GLOBAL_SCREEN_ENUMERATION_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_GLOBAL_SCREEN_ENUMERATION_H_
-
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class ExceptionState;
-class LocalDOMWindow;
-class ScriptPromise;
-class ScriptState;
-
-// A proposed interface for querying the state of the device's screen space.
-// https://github.com/webscreens/window-placement
-// TODO(crbug.com/897300): Remove this; use the new WindowScreens supplement.
-class GlobalScreenEnumeration {
- STATIC_ONLY(GlobalScreenEnumeration);
-
- public:
- // Resolves to the list of |Screen| objects in the device's screen space.
- // TODO(crbug.com/897300): Remove this; use the new WindowScreens supplement.
- static ScriptPromise getScreensDeprecated(ScriptState* script_state,
- LocalDOMWindow&,
- ExceptionState& exception_state);
-
- // Resolves to true if the number of available screens is greater than one.
- // TODO(crbug.com/897300): Remove this; use Screen.isExtended.
- static ScriptPromise isMultiScreen(ScriptState* script_state,
- LocalDOMWindow&,
- ExceptionState& exception_state);
-
- // TODO(crbug.com/897300): Remove this; use Screens.onchange.
- DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(screenschange, kScreenschange)
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_GLOBAL_SCREEN_ENUMERATION_H_
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/idls.gni b/chromium/third_party/blink/renderer/modules/screen_enumeration/idls.gni
deleted file mode 100644
index bf4b1f9613e..00000000000
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/idls.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "screen_advanced.idl",
- "screens.idl",
-]
-
-modules_dependency_idl_files = [
- "screen_enumeration.idl",
- "window_screens.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.cc b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.cc
index 271c923e32c..095553c85e9 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.cc
@@ -4,24 +4,25 @@
#include "third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
-#include "third_party/blink/public/common/widget/screen_infos.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/chrome_client.h"
#include "third_party/blink/renderer/platform/wtf/text/string_statics.h"
+#include "ui/display/screen_info.h"
+#include "ui/display/screen_infos.h"
namespace blink {
namespace {
-const ScreenInfo& GetScreenInfo(LocalFrame& frame, int64_t display_id) {
+const display::ScreenInfo& GetScreenInfo(LocalFrame& frame,
+ int64_t display_id) {
const auto& screen_infos = frame.GetChromeClient().GetScreenInfos(frame);
for (const auto& screen : screen_infos.screen_infos) {
if (screen.display_id == display_id)
return screen;
}
- DEFINE_STATIC_LOCAL(ScreenInfo, kEmptyScreenInfo, ());
+ DEFINE_STATIC_LOCAL(display::ScreenInfo, kEmptyScreenInfo, ());
return kEmptyScreenInfo;
}
@@ -126,6 +127,9 @@ float ScreenAdvanced::devicePixelRatio() const {
}
const String& ScreenAdvanced::id() const {
+ // TODO(http://crbug.com/994889): Implement temporary, generated per-origin
+ // unique device IDs that reset when cookies are deleted. See related:
+ // web_bluetooth_device_id.h, unguessable_token.h, and uuid.h
NOTIMPLEMENTED_LOG_ONCE();
return g_empty_string;
}
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h
index c02c5fd7996..0a8b1c5958c 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h
@@ -33,12 +33,12 @@ class MODULES_EXPORT ScreenAdvanced final : public Screen {
bool isExtended() const override;
// Web-exposed interface (additional per-screen information):
- int left() const override;
- int top() const override;
+ int left() const;
+ int top() const;
bool isPrimary() const;
bool isInternal() const;
float devicePixelRatio() const;
- const String& id() const override;
+ const String& id() const;
Vector<String> pointerTypes() const;
const String& label() const;
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_enumeration.idl b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_enumeration.idl
deleted file mode 100644
index 6a879c702df..00000000000
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_enumeration.idl
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Permission-gated access to multi-screen information.
-// https://github.com/webscreens/window-placement
-// TODO(crbug.com/897300): Remove this in favor of new API access points.
-[
- SecureContext,
- RuntimeEnabled=WindowPlacement,
- ImplementedAs=GlobalScreenEnumeration
-] partial interface Window {
- // TODO(crbug.com/897300): Remove this; use the new WindowScreens supplement.
- [CallWith=ScriptState, RaisesException]
- Promise<sequence<Screen>> getScreensDeprecated();
-
- // TODO(crbug.com/897300): Remove this; use Screen.isExtended.
- [CallWith=ScriptState, Measure, RaisesException]
- Promise<boolean> isMultiScreen();
-
- // TODO(crbug.com/897300): Remove this; use Screens.onchange.
- [Measure] attribute EventHandler onscreenschange;
-};
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.cc b/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.cc
index 178c642e5b8..ed545c14ca0 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/modules/screen_enumeration/screens.h"
#include "base/containers/contains.h"
-#include "third_party/blink/public/common/widget/screen_info.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/local_frame.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/screen_enumeration/screen_advanced.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -58,7 +58,7 @@ void Screens::Trace(Visitor* visitor) const {
}
void Screens::UpdateScreenInfos(LocalDOMWindow* window,
- const ScreenInfos& new_infos) {
+ const display::ScreenInfos& new_infos) {
// Expect that all updates contain a non-zero set of screens.
DCHECK(!new_infos.screen_infos.empty());
@@ -72,7 +72,7 @@ void Screens::UpdateScreenInfos(LocalDOMWindow* window,
for (WTF::wtf_size_t i = 0; i < screens_.size();
/*conditionally incremented*/) {
if (base::Contains(new_infos.screen_infos, screens_[i]->DisplayId(),
- &ScreenInfo::display_id)) {
+ &display::ScreenInfo::display_id)) {
++i;
} else {
screens_.EraseAt(i);
@@ -96,7 +96,7 @@ void Screens::UpdateScreenInfos(LocalDOMWindow* window,
// before we send out any events.
current_display_id_ = new_infos.current_display_id;
- // (2) At this point, all data strutures are up to date.
+ // (2) At this point, all data structures are up to date.
// screens_ has the current set of screens.
// current_screen_ has new values pushed to it.
// (prior to this function) individual ScreenAdvanced objects have new values.
@@ -115,17 +115,24 @@ void Screens::UpdateScreenInfos(LocalDOMWindow* window,
// (5) Send change events to individual screens if they have changed.
// It's not guaranteed that screen_infos are ordered, so for each screen
// find the info that corresponds to it in old_info and new_infos.
- for (const auto& screen : screens_) {
+ //
+ // Note: we cannot use an iterator-based loop here, as iterators may be
+ // invalidated by DispatchEvent(), which may call ContextDestroyed().
+ for (wtf_size_t i = 0; i < screens_.size(); ++i) {
+ const auto& screen = screens_[i];
auto id = screen->DisplayId();
- auto new_it =
- base::ranges::find(new_infos.screen_infos, id, &ScreenInfo::display_id);
+ auto new_it = base::ranges::find(new_infos.screen_infos, id,
+ &display::ScreenInfo::display_id);
DCHECK(new_it != new_infos.screen_infos.end());
auto old_it = base::ranges::find(prev_screen_infos_.screen_infos, id,
- &ScreenInfo::display_id);
+ &display::ScreenInfo::display_id);
if (old_it != prev_screen_infos_.screen_infos.end() && *old_it != *new_it) {
// TODO(enne): http://crbug.com/1202981 only send this event when
// properties on ScreenAdvanced (vs anything in ScreenInfo) change.
screen->DispatchEvent(*Event::Create(event_type_names::kChange));
+
+ // Note: screen may no longer be valid and screens_ may have been
+ // cleared at this point via DispatchEvent calling ContextDestroyed.
}
}
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.h b/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.h
index 9d572af4ef6..90973598c46 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.h
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/screens.h
@@ -5,12 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_SCREENS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_SCREENS_H_
-#include "third_party/blink/public/common/widget/screen_infos.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.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 "ui/display/screen_infos.h"
namespace blink {
@@ -43,12 +43,13 @@ class MODULES_EXPORT Screens final : public EventTargetWithInlineData,
// Called when there is a visual property update with potentially new
// multi-screen information.
- void UpdateScreenInfos(LocalDOMWindow* window, const ScreenInfos& new_infos);
+ void UpdateScreenInfos(LocalDOMWindow* window,
+ const display::ScreenInfos& new_infos);
private:
// The ScreenInfos sent by the previous UpdateScreenInfos call.
- ScreenInfos prev_screen_infos_;
- int64_t current_display_id_ = ScreenInfo::kInvalidDisplayId;
+ display::ScreenInfos prev_screen_infos_;
+ int64_t current_display_id_ = display::ScreenInfo::kInvalidDisplayId;
HeapVector<Member<ScreenAdvanced>> screens_;
};
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/idls.gni b/chromium/third_party/blink/renderer/modules/screen_orientation/idls.gni
deleted file mode 100644
index 9b71e5a28de..00000000000
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "screen_orientation.idl" ]
-
-modules_dependency_idl_files = [ "screen_screen_orientation.idl" ]
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 de31b28f873..c66d381560b 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
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -18,19 +18,19 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-// This code assumes that mojom::blink::ScreenOrientation values are included in
-// device::mojom::blink::ScreenOrientationLockType.
+// This code assumes that display::mojom::blink::ScreenOrientation values are
+// included in device::mojom::blink::ScreenOrientationLockType.
STATIC_ASSERT_ENUM(
- blink::mojom::blink::ScreenOrientation::kPortraitPrimary,
+ display::mojom::blink::ScreenOrientation::kPortraitPrimary,
device::mojom::blink::ScreenOrientationLockType::PORTRAIT_PRIMARY);
STATIC_ASSERT_ENUM(
- blink::mojom::blink::ScreenOrientation::kPortraitSecondary,
+ display::mojom::blink::ScreenOrientation::kPortraitSecondary,
device::mojom::blink::ScreenOrientationLockType::PORTRAIT_SECONDARY);
STATIC_ASSERT_ENUM(
- blink::mojom::blink::ScreenOrientation::kLandscapePrimary,
+ display::mojom::blink::ScreenOrientation::kLandscapePrimary,
device::mojom::blink::ScreenOrientationLockType::LANDSCAPE_PRIMARY);
STATIC_ASSERT_ENUM(
- blink::mojom::blink::ScreenOrientation::kLandscapeSecondary,
+ display::mojom::blink::ScreenOrientation::kLandscapeSecondary,
device::mojom::blink::ScreenOrientationLockType::LANDSCAPE_SECONDARY);
namespace blink {
@@ -73,7 +73,7 @@ static ScreenOrientationInfo* OrientationsMap(unsigned& length) {
}
const AtomicString& ScreenOrientation::OrientationTypeToString(
- mojom::blink::ScreenOrientation orientation) {
+ display::mojom::blink::ScreenOrientation orientation) {
unsigned length = 0;
ScreenOrientationInfo* orientation_map = OrientationsMap(length);
for (unsigned i = 0; i < length; ++i) {
@@ -110,7 +110,7 @@ ScreenOrientation* ScreenOrientation::Create(LocalDOMWindow* window) {
ScreenOrientation::ScreenOrientation(LocalDOMWindow* window)
: ExecutionContextClient(window),
- type_(mojom::blink::ScreenOrientation::kUndefined),
+ type_(display::mojom::blink::ScreenOrientation::kUndefined),
angle_(0) {}
ScreenOrientation::~ScreenOrientation() = default;
@@ -131,7 +131,7 @@ uint16_t ScreenOrientation::angle() const {
return angle_;
}
-void ScreenOrientation::SetType(mojom::blink::ScreenOrientation type) {
+void ScreenOrientation::SetType(display::mojom::blink::ScreenOrientation type) {
type_ = type;
}
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.h b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.h
index 95b91315f5c..5e743904bce 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.h
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ORIENTATION_SCREEN_ORIENTATION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ORIENTATION_SCREEN_ORIENTATION_H_
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -13,6 +12,7 @@
#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"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
namespace blink {
@@ -40,7 +40,7 @@ class MODULES_EXPORT ScreenOrientation final : public EventTargetWithInlineData,
String type() const;
uint16_t angle() const;
- void SetType(mojom::blink::ScreenOrientation);
+ void SetType(display::mojom::blink::ScreenOrientation);
void SetAngle(uint16_t);
ScriptPromise lock(ScriptState*,
@@ -52,14 +52,14 @@ class MODULES_EXPORT ScreenOrientation final : public EventTargetWithInlineData,
// Helper being used by this class and LockOrientationCallback.
static const AtomicString& OrientationTypeToString(
- mojom::blink::ScreenOrientation);
+ display::mojom::blink::ScreenOrientation);
void Trace(Visitor*) const override;
private:
ScreenOrientationController* Controller();
- mojom::blink::ScreenOrientation type_;
+ display::mojom::blink::ScreenOrientation type_;
uint16_t angle_;
};
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.cc
index 74697bb52fd..d8fdf47d97d 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.cc
@@ -9,7 +9,6 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-#include "third_party/blink/public/common/widget/screen_info.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"
@@ -20,6 +19,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/modules/screen_orientation/screen_orientation.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
+#include "ui/display/screen_info.h"
namespace blink {
@@ -59,14 +59,14 @@ ScreenOrientationController::ScreenOrientationController(LocalDOMWindow& window)
// Compute the screen orientation using the orientation angle and the screen
// width / height.
-mojom::blink::ScreenOrientation ScreenOrientationController::ComputeOrientation(
- const gfx::Rect& rect,
- uint16_t rotation) {
+display::mojom::blink::ScreenOrientation
+ScreenOrientationController::ComputeOrientation(const gfx::Rect& rect,
+ uint16_t rotation) {
// Bypass orientation detection in web tests to get consistent results.
// FIXME: The screen dimension should be fixed when running the web tests
// to avoid such issues.
if (WebTestSupport::IsRunningWebTest())
- return mojom::blink::ScreenOrientation::kPortraitPrimary;
+ return display::mojom::blink::ScreenOrientation::kPortraitPrimary;
bool is_tall_display = rotation % 180 ? rect.height() < rect.width()
: rect.height() > rect.width();
@@ -79,23 +79,24 @@ mojom::blink::ScreenOrientation ScreenOrientationController::ComputeOrientation(
switch (rotation) {
case 0:
return is_tall_display
- ? mojom::blink::ScreenOrientation::kPortraitPrimary
- : mojom::blink::ScreenOrientation::kLandscapePrimary;
+ ? display::mojom::blink::ScreenOrientation::kPortraitPrimary
+ : display::mojom::blink::ScreenOrientation::kLandscapePrimary;
case 90:
return is_tall_display
- ? mojom::blink::ScreenOrientation::kLandscapePrimary
- : mojom::blink::ScreenOrientation::kPortraitSecondary;
+ ? display::mojom::blink::ScreenOrientation::kLandscapePrimary
+ : display::mojom::blink::ScreenOrientation::kPortraitSecondary;
case 180:
return is_tall_display
- ? mojom::blink::ScreenOrientation::kPortraitSecondary
- : mojom::blink::ScreenOrientation::kLandscapeSecondary;
+ ? display::mojom::blink::ScreenOrientation::kPortraitSecondary
+ : display::mojom::blink::ScreenOrientation::
+ kLandscapeSecondary;
case 270:
return is_tall_display
- ? mojom::blink::ScreenOrientation::kLandscapeSecondary
- : mojom::blink::ScreenOrientation::kPortraitPrimary;
+ ? display::mojom::blink::ScreenOrientation::kLandscapeSecondary
+ : display::mojom::blink::ScreenOrientation::kPortraitPrimary;
default:
NOTREACHED();
- return mojom::blink::ScreenOrientation::kPortraitPrimary;
+ return display::mojom::blink::ScreenOrientation::kPortraitPrimary;
}
}
@@ -104,16 +105,18 @@ void ScreenOrientationController::UpdateOrientation() {
DCHECK(GetPage());
ChromeClient& chrome_client = GetPage()->GetChromeClient();
LocalFrame& frame = *DomWindow()->GetFrame();
- const ScreenInfo& screen_info = chrome_client.GetScreenInfo(frame);
- mojom::blink::ScreenOrientation orientation_type =
+ const display::ScreenInfo& screen_info = chrome_client.GetScreenInfo(frame);
+ display::mojom::blink::ScreenOrientation orientation_type =
screen_info.orientation_type;
- if (orientation_type == mojom::blink::ScreenOrientation::kUndefined) {
+ if (orientation_type ==
+ display::mojom::blink::ScreenOrientation::kUndefined) {
// The embedder could not provide us with an orientation, deduce it
// ourselves.
orientation_type =
ComputeOrientation(screen_info.rect, screen_info.orientation_angle);
}
- DCHECK(orientation_type != mojom::blink::ScreenOrientation::kUndefined);
+ DCHECK(orientation_type !=
+ display::mojom::blink::ScreenOrientation::kUndefined);
orientation_->SetType(orientation_type);
orientation_->SetAngle(screen_info.orientation_angle);
@@ -200,14 +203,19 @@ void ScreenOrientationController::lock(
if (!screen_orientation_service_.is_bound())
return;
- CancelPendingLocks();
- pending_callback_ = std::move(callback);
- screen_orientation_service_->LockOrientation(
- orientation,
- WTF::Bind(&ScreenOrientationController::OnLockOrientationResult,
- WrapWeakPersistent(this), ++request_id_));
+ // https://jeremyroman.github.io/alternate-loading-modes/#patch-orientation-lock
+ // Step 7.3.10. Screen Orientation API.
+ // Defer to lock with |orientation| until the prerendering page is activated
+ // via appending lock operation to the post-prerendering activation steps
+ // list.
+ if (DomWindow()->document()->IsPrerendering()) {
+ DomWindow()->document()->AddPostPrerenderingActivationStep(
+ WTF::Bind(&ScreenOrientationController::LockOrientationInternal,
+ WrapWeakPersistent(this), orientation, std::move(callback)));
+ return;
+ }
- active_lock_ = true;
+ LockOrientationInternal(orientation, std::move(callback));
}
void ScreenOrientationController::unlock() {
@@ -215,9 +223,19 @@ void ScreenOrientationController::unlock() {
if (!screen_orientation_service_.is_bound())
return;
- CancelPendingLocks();
- screen_orientation_service_->UnlockOrientation();
- active_lock_ = false;
+ // https://jeremyroman.github.io/alternate-loading-modes/#patch-orientation-lock
+ // Step 7.3.10. Screen Orientation API.
+ // Defer to unlock with |orientation| until the prerendering page is activated
+ // via appending unlock operation to the post-prerendering activation steps
+ // list.
+ if (DomWindow()->document()->IsPrerendering()) {
+ DomWindow()->document()->AddPostPrerenderingActivationStep(
+ WTF::Bind(&ScreenOrientationController::UnlockOrientationInternal,
+ WrapWeakPersistent(this)));
+ return;
+ }
+
+ UnlockOrientationInternal();
}
bool ScreenOrientationController::MaybeHasActiveLock() const {
@@ -295,4 +313,23 @@ int ScreenOrientationController::GetRequestIdForTests() {
return pending_callback_ ? request_id_ : -1;
}
+void ScreenOrientationController::LockOrientationInternal(
+ device::mojom::blink::ScreenOrientationLockType orientation,
+ std::unique_ptr<WebLockOrientationCallback> callback) {
+ CancelPendingLocks();
+ pending_callback_ = std::move(callback);
+ screen_orientation_service_->LockOrientation(
+ orientation,
+ WTF::Bind(&ScreenOrientationController::OnLockOrientationResult,
+ WrapWeakPersistent(this), ++request_id_));
+
+ active_lock_ = true;
+}
+
+void ScreenOrientationController::UnlockOrientationInternal() {
+ CancelPendingLocks();
+ screen_orientation_service_->UnlockOrientation();
+ active_lock_ = false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h
index 7adce74b056..e27043b431b 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h
@@ -10,13 +10,13 @@
#include "base/macros.h"
#include "services/device/public/mojom/screen_orientation.mojom-blink.h"
#include "services/device/public/mojom/screen_orientation_lock_types.mojom-shared.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/screen_orientation/web_lock_orientation_callback.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
#include "ui/gfx/geometry/rect.h"
namespace blink {
@@ -55,8 +55,9 @@ class MODULES_EXPORT ScreenOrientationController final
friend class MediaControlsOrientationLockAndRotateToFullscreenDelegateTest;
friend class ScreenOrientationControllerTest;
- static mojom::blink::ScreenOrientation ComputeOrientation(const gfx::Rect&,
- uint16_t);
+ static display::mojom::blink::ScreenOrientation ComputeOrientation(
+ const gfx::Rect&,
+ uint16_t);
void NotifyOrientationChangedInternal();
// Inherited from ExecutionContextLifecycleObserver and
@@ -72,6 +73,11 @@ class MODULES_EXPORT ScreenOrientationController final
void CancelPendingLocks();
int GetRequestIdForTests();
+ void LockOrientationInternal(
+ device::mojom::blink::ScreenOrientationLockType orientation,
+ std::unique_ptr<WebLockOrientationCallback> callback);
+ void UnlockOrientationInternal();
+
Member<ScreenOrientation> orientation_;
bool active_lock_ = false;
HeapMojoAssociatedRemote<device::mojom::blink::ScreenOrientation>
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
index 8e81edf26d7..54a821bc4b3 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
@@ -213,10 +213,10 @@ class ScreenInfoWebFrameWidget : public frame_test_helpers::TestWebFrameWidget {
~ScreenInfoWebFrameWidget() override = default;
// frame_test_helpers::TestWebFrameWidget overrides.
- ScreenInfo GetInitialScreenInfo() override { return screen_info_; }
+ display::ScreenInfo GetInitialScreenInfo() override { return screen_info_; }
private:
- ScreenInfo screen_info_;
+ display::ScreenInfo screen_info_;
};
TEST_F(ScreenOrientationControllerTest, PageVisibilityCrash) {
@@ -286,7 +286,7 @@ TEST_F(ScreenOrientationControllerTest,
ScreenOrientation::Create(To<LocalFrame>(grandchild)->DomWindow());
// Update the screen info and ensure it propagated to the grandchild.
- blink::ScreenInfos screen_infos((blink::ScreenInfo()));
+ display::ScreenInfos screen_infos((display::ScreenInfo()));
screen_infos.mutable_current().orientation_angle = 90;
auto* web_frame_widget_base =
static_cast<WebFrameWidgetImpl*>(frame->GetWidgetForLocalRoot());
diff --git a/chromium/third_party/blink/renderer/modules/sensor/OWNERS b/chromium/third_party/blink/renderer/modules/sensor/OWNERS
index 461e969a49b..8120bc8cd5d 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/sensor/OWNERS
@@ -1,4 +1,3 @@
raphael.kubo.da.costa@intel.com
reillyg@chromium.org
rijubrata.bhaumik@intel.com
-timvolodine@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/sensor/idls.gni b/chromium/third_party/blink/renderer/modules/sensor/idls.gni
deleted file mode 100644
index d6bcf3feec6..00000000000
--- a/chromium/third_party/blink/renderer/modules/sensor/idls.gni
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "absolute_orientation_sensor.idl",
- "accelerometer.idl",
- "ambient_light_sensor.idl",
- "gravity_sensor.idl",
- "gyroscope.idl",
- "linear_acceleration_sensor.idl",
- "magnetometer.idl",
- "orientation_sensor.idl",
- "relative_orientation_sensor.idl",
- "sensor.idl",
- "sensor_error_event.idl",
-]
-
-modules_dictionary_idl_files = [
- "sensor_error_event_init.idl",
- "sensor_options.idl",
- "spatial_sensor_options.idl",
-]
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 a5996cfd5ff..815c2991b02 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc
@@ -99,7 +99,6 @@ void OrientationSensor::PopulateMatrixInternal(
DoPopulateMatrix(target_matrix, quat.x, quat.y, quat.z, quat.w);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void OrientationSensor::populateMatrix(
const V8RotationMatrixType* target_buffer,
ExceptionState& exception_state) {
@@ -117,20 +116,6 @@ void OrientationSensor::populateMatrix(
break;
}
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void OrientationSensor::populateMatrix(
- Float32ArrayOrFloat64ArrayOrDOMMatrix& matrix,
- ExceptionState& exception_state) {
- if (matrix.IsFloat32Array())
- PopulateMatrixInternal(matrix.GetAsFloat32Array().Get(), exception_state);
- else if (matrix.IsFloat64Array())
- PopulateMatrixInternal(matrix.GetAsFloat64Array().Get(), exception_state);
- else if (matrix.IsDOMMatrix())
- PopulateMatrixInternal(matrix.GetAsDOMMatrix(), exception_state);
- else
- NOTREACHED() << "Unexpected rotation matrix type.";
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool OrientationSensor::isReadingDirty() const {
return reading_dirty_ || !hasReading();
diff --git a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.h b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.h
index d40036e6447..ecf71532445 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_ORIENTATION_SENSOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_ORIENTATION_SENSOR_H_
-#include "third_party/blink/renderer/bindings/modules/v8/float32_array_or_float64_array_or_dom_matrix.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_spatial_sensor_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
@@ -18,12 +17,8 @@ class OrientationSensor : public Sensor {
public:
absl::optional<Vector<double>> quaternion();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void populateMatrix(const V8RotationMatrixType* target_buffer,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void populateMatrix(Float32ArrayOrFloat64ArrayOrDOMMatrix&, ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool isReadingDirty() const;
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 3241bdaab54..2a153541b6d 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/sensor/sensor_proxy.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "ui/display/screen_info.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/serial/idls.gni b/chromium/third_party/blink/renderer/modules/serial/idls.gni
deleted file mode 100644
index b6dcf4009f6..00000000000
--- a/chromium/third_party/blink/renderer/modules/serial/idls.gni
+++ /dev/null
@@ -1,22 +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.
-
-modules_idl_files = [
- "serial.idl",
- "serial_port.idl",
-]
-
-modules_dictionary_idl_files = [
- "serial_input_signals.idl",
- "serial_options.idl",
- "serial_output_signals.idl",
- "serial_port_filter.idl",
- "serial_port_info.idl",
- "serial_port_request_options.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_serial.idl",
- "worker_navigator_serial.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial.cc b/chromium/third_party/blink/renderer/modules/serial/serial.cc
index 5d9dfb87139..6c24b1e5a80 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial.cc
+++ b/chromium/third_party/blink/renderer/modules/serial/serial.cc
@@ -246,11 +246,13 @@ void Serial::OnServiceConnectionError() {
}
SerialPort* Serial::GetOrCreatePort(mojom::blink::SerialPortInfoPtr info) {
- SerialPort* port = port_cache_.at(TokenToString(info->token));
- if (!port) {
- port = MakeGarbageCollected<SerialPort>(this, std::move(info));
- port_cache_.insert(TokenToString(port->token()), port);
+ auto it = port_cache_.find(TokenToString(info->token));
+ if (it != port_cache_.end()) {
+ return it->value;
}
+
+ SerialPort* port = MakeGarbageCollected<SerialPort>(this, std::move(info));
+ port_cache_.insert(TokenToString(port->token()), port);
return port;
}
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port.cc b/chromium/third_party/blink/renderer/modules/serial/serial_port.cc
index 61fe6143f54..fc2023122ce 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port.cc
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/modules/serial/serial.h"
#include "third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h"
#include "third_party/blink/renderer/modules/serial/serial_port_underlying_source.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
namespace blink {
@@ -183,6 +184,12 @@ SerialPortInfo* SerialPort::getInfo() {
ScriptPromise SerialPort::open(ScriptState* script_state,
const SerialOptions* options,
ExceptionState& exception_state) {
+ if (!GetExecutionContext()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Script context has shut down.");
+ return ScriptPromise();
+ }
+
if (open_resolver_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port.h b/chromium/third_party/blink/renderer/modules/serial/serial_port.h
index 7a23b9c9943..22ea6177103 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port.h
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port.h
@@ -7,6 +7,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/serial.mojom-blink-forward.h"
+#include "services/device/public/mojom/serial.mojom-blink.h"
#include "third_party/blink/public/mojom/serial/serial.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"
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc
index 6e431ccb1d5..08ab2c7e056 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc
@@ -5,7 +5,9 @@
#include "third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/serial/serial_port.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -36,7 +38,7 @@ ScriptPromise SerialPortUnderlyingSink::write(
WritableStreamDefaultController* controller,
ExceptionState& exception_state) {
// There can only be one call to write() in progress at a time.
- DCHECK(buffer_source_.IsNull());
+ DCHECK(!buffer_source_);
DCHECK_EQ(0u, offset_);
DCHECK(!pending_operation_);
@@ -48,9 +50,8 @@ ScriptPromise SerialPortUnderlyingSink::write(
return ScriptPromise();
}
- V8ArrayBufferOrArrayBufferView::ToImpl(
- script_state->GetIsolate(), chunk.V8Value(), buffer_source_,
- UnionTypeConversionMode::kNotNullable, exception_state);
+ buffer_source_ = V8BufferSource::Create(script_state->GetIsolate(),
+ chunk.V8Value(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
@@ -168,27 +169,17 @@ void SerialPortUnderlyingSink::OnFlushOrDrain() {
void SerialPortUnderlyingSink::WriteData() {
DCHECK(data_pipe_);
DCHECK(pending_operation_);
- DCHECK(!buffer_source_.IsNull());
-
- const uint8_t* data = nullptr;
- uint32_t length = 0;
- size_t byte_size = 0;
- if (buffer_source_.IsArrayBuffer()) {
- DOMArrayBuffer* array = buffer_source_.GetAsArrayBuffer();
- byte_size = array->ByteLength();
- data = static_cast<const uint8_t*>(array->Data());
- } else {
- DOMArrayBufferView* view = buffer_source_.GetAsArrayBufferView().Get();
- byte_size = view->byteLength();
- data = static_cast<const uint8_t*>(view->BaseAddress());
- }
- if (byte_size > std::numeric_limits<uint32_t>::max()) {
+ DCHECK(buffer_source_);
+
+ DOMArrayPiece array_piece(buffer_source_);
+ if (array_piece.ByteLength() > std::numeric_limits<uint32_t>::max()) {
pending_exception_ = DOMException::Create(
"Buffer size exceeds maximum heap object size.", "DataError");
PipeClosed();
return;
}
- length = static_cast<uint32_t>(byte_size);
+ const uint8_t* data = array_piece.Bytes();
+ const uint32_t length = static_cast<uint32_t>(array_piece.ByteLength());
DCHECK_LT(offset_, length);
data += offset_;
@@ -200,7 +191,7 @@ void SerialPortUnderlyingSink::WriteData() {
case MOJO_RESULT_OK:
offset_ += num_bytes;
if (offset_ == length) {
- buffer_source_ = ArrayBufferOrArrayBufferView();
+ buffer_source_ = nullptr;
offset_ = 0;
pending_operation_->Resolve();
pending_operation_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h
index ca45ab69c8c..bd560410f8e 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h
@@ -7,7 +7,7 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
namespace blink {
@@ -50,7 +50,7 @@ class SerialPortUnderlyingSink final : public UnderlyingSinkBase {
Member<SerialPort> serial_port_;
Member<DOMException> pending_exception_;
- ArrayBufferOrArrayBufferView buffer_source_;
+ Member<V8BufferSource> buffer_source_;
uint32_t offset_ = 0;
// Only one outstanding call to write(), close() or abort() is allowed at a
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc b/chromium/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc
index 992f3a5e050..7ebeae103b1 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc
@@ -41,8 +41,8 @@ bool CrossOriginResourcePolicyChecker::IsBlocked(
return network::CrossOriginResourcePolicy::IsBlockedByHeaderValue(
response.InternalURLList().back(),
response.InternalURLList().front(), initiator_origin,
- corp_header_value, request_mode, initiator_origin,
- request_destination, policy_,
+ corp_header_value, request_mode, request_destination,
+ response.GetResponse()->RequestIncludeCredentials(), policy_,
reporter_ ? reporter_.get() : nullptr)
.has_value();
}
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
index 01938cb7201..dfe0647047e 100644
--- 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
@@ -78,7 +78,6 @@ ScriptValue ExtendableMessageEvent::data(ScriptState* script_state) const {
return ScriptValue(script_state->GetIsolate(), value);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionClientOrMessagePortOrServiceWorker* ExtendableMessageEvent::source()
const {
if (source_as_client_) {
@@ -93,21 +92,6 @@ V8UnionClientOrMessagePortOrServiceWorker* ExtendableMessageEvent::source()
}
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-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();
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MessagePortArray ExtendableMessageEvent::ports() const {
// TODO(bashi): Currently we return a copied array because the binding
@@ -151,13 +135,19 @@ ExtendableMessageEvent::ExtendableMessageEvent(
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->hasSource() and initializer->source()) {
+ switch (initializer->source()->GetContentType()) {
+ case V8UnionClientOrMessagePortOrServiceWorker::ContentType::kClient:
+ source_as_client_ = initializer->source()->GetAsClient();
+ break;
+ case V8UnionClientOrMessagePortOrServiceWorker::ContentType::kMessagePort:
+ source_as_message_port_ = initializer->source()->GetAsMessagePort();
+ break;
+ case V8UnionClientOrMessagePortOrServiceWorker::ContentType::
+ kServiceWorker:
+ source_as_service_worker_ = initializer->source()->GetAsServiceWorker();
+ break;
+ }
}
if (initializer->hasPorts())
ports_ = MakeGarbageCollected<MessagePortArray>(initializer->ports());
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
index dfa9a2341de..2bc2b26ed06 100644
--- 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
@@ -73,11 +73,7 @@ class MODULES_EXPORT ExtendableMessageEvent final : public ExtendableEvent {
bool isDataDirty() const { return false; }
const String& origin() const { return origin_; }
const String& lastEventId() const { return last_event_id_; }
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionClientOrMessagePortOrServiceWorker* source() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void source(ClientOrServiceWorkerOrMessagePort& result) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
MessagePortArray ports() const;
const AtomicString& InterfaceName() const override;
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
index 070ad8ef96c..ab8eba74858 100644
--- 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
@@ -14,6 +14,7 @@
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -220,9 +221,7 @@ void FetchRespondWithObserver::OnResponseRejected(
void FetchRespondWithObserver::OnResponseFulfilled(
ScriptState* script_state,
const ScriptValue& value,
- ExceptionState::ContextType context_type,
- const char* interface_name,
- const char* property_name) {
+ const ExceptionContext& exception_context) {
DCHECK(GetExecutionContext());
if (!V8Response::HasInstance(value.V8Value(), script_state->GetIsolate())) {
OnResponseRejected(ServiceWorkerResponseError::kNoV8Instance);
@@ -320,8 +319,8 @@ void FetchRespondWithObserver::OnResponseFulfilled(
// drained or loading begins.
fetch_api_response->side_data_blob = buffer->TakeSideDataBlob();
- ExceptionState exception_state(script_state->GetIsolate(), context_type,
- interface_name, property_name);
+ ExceptionState exception_state(script_state->GetIsolate(),
+ exception_context);
scoped_refptr<BlobDataHandle> blob_data_handle =
buffer->DrainAsBlobDataHandle(
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
index 6cbcdfe761f..3a1343e4b94 100644
--- 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
@@ -43,9 +43,7 @@ class MODULES_EXPORT FetchRespondWithObserver : public RespondWithObserver {
void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
void OnResponseFulfilled(ScriptState*,
const ScriptValue&,
- ExceptionState::ContextType context_type,
- const char* interface_name,
- const char* property_name) override;
+ const ExceptionContext& exception_context) override;
void OnNoResponse() override;
void SetEvent(FetchEvent* event);
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/idls.gni b/chromium/third_party/blink/renderer/modules/service_worker/idls.gni
deleted file mode 100644
index 6206a7a212f..00000000000
--- a/chromium/third_party/blink/renderer/modules/service_worker/idls.gni
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "client.idl",
- "clients.idl",
- "extendable_event.idl",
- "extendable_message_event.idl",
- "fetch_event.idl",
- "install_event.idl",
- "navigation_preload_manager.idl",
- "service_worker.idl",
- "service_worker_container.idl",
- "service_worker_global_scope.idl",
- "service_worker_registration.idl",
- "window_client.idl",
-]
-
-modules_dictionary_idl_files = [
- "client_query_options.idl",
- "extendable_event_init.idl",
- "extendable_message_event_init.idl",
- "fetch_event_init.idl",
- "navigation_preload_state.idl",
- "registration_options.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_service_worker.idl" ]
-
-modules_testing_dependency_idl_files =
- [ "testing/internals_service_worker.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
index 8a04139b4d8..ca056620052 100644
--- 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
@@ -66,9 +66,7 @@ void RespondWithObserver::RespondWith(ScriptState* script_state,
script_state, script_promise, exception_state,
WTF::BindRepeating(&RespondWithObserver::ResponseWasFulfilled,
WrapPersistent(this), WrapPersistent(script_state),
- exception_state.Context(),
- WTF::Unretained(exception_state.InterfaceName()),
- WTF::Unretained(exception_state.PropertyName())),
+ exception_state.GetContext()),
WTF::BindRepeating(&RespondWithObserver::ResponseWasRejected,
WrapPersistent(this),
ServiceWorkerResponseError::kPromiseRejected));
@@ -89,12 +87,9 @@ void RespondWithObserver::ResponseWasRejected(ServiceWorkerResponseError error,
void RespondWithObserver::ResponseWasFulfilled(
ScriptState* script_state,
- ExceptionState::ContextType context_type,
- const char* interface_name,
- const char* property_name,
+ const ExceptionContext& exception_context,
const ScriptValue& value) {
- OnResponseFulfilled(script_state, value, context_type, interface_name,
- property_name);
+ OnResponseFulfilled(script_state, value, exception_context);
state_ = kDone;
}
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
index 995cf65f718..8134dc5dec6 100644
--- 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
@@ -45,9 +45,7 @@ class MODULES_EXPORT RespondWithObserver
// Called when the respondWith() promise was fulfilled.
virtual void OnResponseFulfilled(ScriptState*,
const ScriptValue&,
- ExceptionState::ContextType,
- const char* interface_name,
- const char* property_name) = 0;
+ const ExceptionContext&) = 0;
// Called when the event handler finished without calling respondWith().
virtual void OnNoResponse() = 0;
@@ -65,9 +63,7 @@ class MODULES_EXPORT RespondWithObserver
void ResponseWasRejected(mojom::ServiceWorkerResponseError,
const ScriptValue&);
void ResponseWasFulfilled(ScriptState* state,
- ExceptionState::ContextType,
- const char* interface_name,
- const char* property_name,
+ const ExceptionContext&,
const ScriptValue&);
enum State { kInitial, kPending, kDone };
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
index 29a82d56a5f..ce3e6e1f332 100644
--- 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
@@ -572,16 +572,17 @@ ServiceWorkerContainer::GetOrCreateServiceWorkerRegistration(
if (info.registration_id == mojom::blink::kInvalidServiceWorkerRegistrationId)
return nullptr;
- ServiceWorkerRegistration* registration =
- service_worker_registration_objects_.at(info.registration_id);
- if (registration) {
+ auto it = service_worker_registration_objects_.find(info.registration_id);
+ if (it != service_worker_registration_objects_.end()) {
+ ServiceWorkerRegistration* registration = it->value;
registration->Attach(std::move(info));
return registration;
}
const int64_t registration_id = info.registration_id;
- registration = MakeGarbageCollected<ServiceWorkerRegistration>(
- GetSupplementable()->GetExecutionContext(), std::move(info));
+ ServiceWorkerRegistration* registration =
+ MakeGarbageCollected<ServiceWorkerRegistration>(
+ GetSupplementable()->GetExecutionContext(), std::move(info));
service_worker_registration_objects_.Set(registration_id, registration);
return registration;
}
@@ -590,13 +591,15 @@ ServiceWorker* ServiceWorkerContainer::GetOrCreateServiceWorker(
WebServiceWorkerObjectInfo info) {
if (info.version_id == mojom::blink::kInvalidServiceWorkerVersionId)
return nullptr;
- ServiceWorker* worker = service_worker_objects_.at(info.version_id);
- if (!worker) {
- const int64_t version_id = info.version_id;
- worker = ServiceWorker::Create(GetSupplementable()->GetExecutionContext(),
- std::move(info));
- service_worker_objects_.Set(version_id, worker);
- }
+
+ auto it = service_worker_objects_.find(info.version_id);
+ if (it != service_worker_objects_.end())
+ return it->value;
+
+ const int64_t version_id = info.version_id;
+ ServiceWorker* worker = ServiceWorker::Create(
+ GetSupplementable()->GetExecutionContext(), std::move(info));
+ service_worker_objects_.Set(version_id, worker);
return worker;
}
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h
index b1e60875b62..617b4980f46 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h
@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.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
index c69fe07d6c0..9c2cff1d043 100644
--- 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
@@ -43,11 +43,15 @@
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
+#include "services/network/public/mojom/cookie_manager.mojom-blink.h"
#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom-blink.h"
#include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-blink.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom.h"
@@ -703,12 +707,15 @@ ServiceWorker* ServiceWorkerGlobalScope::GetOrCreateServiceWorker(
WebServiceWorkerObjectInfo info) {
if (info.version_id == mojom::blink::kInvalidServiceWorkerVersionId)
return nullptr;
- ::blink::ServiceWorker* worker = service_worker_objects_.at(info.version_id);
- if (!worker) {
- const int64_t version_id = info.version_id;
- worker = ::blink::ServiceWorker::Create(this, std::move(info));
- service_worker_objects_.Set(version_id, worker);
- }
+
+ auto it = service_worker_objects_.find(info.version_id);
+ if (it != service_worker_objects_.end())
+ return it->value;
+
+ const int64_t version_id = info.version_id;
+ ::blink::ServiceWorker* worker =
+ ::blink::ServiceWorker::Create(this, std::move(info));
+ service_worker_objects_.Set(version_id, worker);
return worker;
}
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
index 4c9bcb6df1a..a7805463401 100644
--- 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
@@ -43,7 +43,6 @@
#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom-blink-forward.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/modules/service_worker/cross_origin_resource_policy_checker.h"
@@ -81,8 +80,6 @@ struct GlobalScopeCreationParams;
struct WebServiceWorkerError;
struct WebServiceWorkerObjectInfo;
-typedef RequestOrUSVString RequestInfo;
-
class MODULES_EXPORT ServiceWorkerGlobalScope final
: public WorkerGlobalScope,
public mojom::blink::ControllerServiceWorker,
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc
index a4ee3147fba..e6225c98973 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc
@@ -94,7 +94,7 @@ class BrowserSideSender
const mojo::DataPipeProducerHandle& handle) {
// Send |data| with null terminator.
ASSERT_TRUE(handle.is_valid());
- uint32_t written_bytes = data.size() + 1;
+ uint32_t written_bytes = static_cast<uint32_t>(data.size() + 1);
MojoResult rv = handle.WriteData(data.c_str(), &written_bytes,
MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, rv);
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.cc
index a7ac25ce930..8a261b76fa7 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.cc
@@ -40,15 +40,19 @@ void ServiceWorkerModuleTreeClient::NotifyModuleTreeLoadFinished(
}
// With top-level await: https://github.com/w3c/ServiceWorker/pull/1444
- if (!module_script->HasEmptyRecord() &&
- module_script->V8Module()->IsGraphAsync()) {
- worker_reporting_proxy.DidFailToFetchModuleScript();
- worker_global_scope->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::blink::ConsoleMessageSource::kJavaScript,
- mojom::blink::ConsoleMessageLevel::kError,
- "Top-level await is disallowed in service workers."));
- worker_global_scope->close();
- return;
+ if (!module_script->HasEmptyRecord()) {
+ v8::Local<v8::Module> record = module_script->V8Module();
+ if (record->GetStatus() >= v8::Module::kInstantiated &&
+ record->IsGraphAsync()) {
+ worker_reporting_proxy.DidFailToFetchModuleScript();
+ worker_global_scope->AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageLevel::kError,
+ "Top-level await is disallowed in service workers."));
+ worker_global_scope->close();
+ return;
+ }
}
worker_reporting_proxy.DidFetchScript();
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
index 2abdd9ae1b6..da6b496ba23 100644
--- 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
@@ -12,6 +12,7 @@
#include "third_party/blink/public/common/security_context/insecure_request_policy.h"
#include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/navigation_preload_state.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_state.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -265,10 +266,7 @@ ScriptPromise ServiceWorkerRegistration::update(
return ScriptPromise();
}
- // The fetcher is lazily loaded in a worker global scope.
auto* execution_context = ExecutionContext::From(script_state);
- if (auto* global_scope = DynamicTo<WorkerGlobalScope>(execution_context))
- global_scope->EnsureFetcher();
const FetchClientSettingsObject& settings_object =
execution_context->Fetcher()
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
index 130a853279a..3d8a8bd170e 100644
--- 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
@@ -36,6 +36,7 @@ void ServiceWorkerScriptCachedMetadataHandler::Trace(Visitor* visitor) const {
}
void ServiceWorkerScriptCachedMetadataHandler::SetCachedMetadata(
+ blink::mojom::CodeCacheHost* code_cache_host,
uint32_t data_type_id,
const uint8_t* data,
size_t size) {
@@ -47,6 +48,7 @@ void ServiceWorkerScriptCachedMetadataHandler::SetCachedMetadata(
}
void ServiceWorkerScriptCachedMetadataHandler::ClearCachedMetadata(
+ blink::mojom::CodeCacheHost* code_cache_host,
ClearCacheType type) {
if (type == kDiscardLocally)
return;
@@ -58,7 +60,8 @@ void ServiceWorkerScriptCachedMetadataHandler::ClearCachedMetadata(
scoped_refptr<CachedMetadata>
ServiceWorkerScriptCachedMetadataHandler::GetCachedMetadata(
- uint32_t data_type_id) const {
+ uint32_t data_type_id,
+ GetCachedMetadataBehavior behavior) const {
if (!cached_metadata_ || cached_metadata_->DataTypeID() != data_type_id)
return nullptr;
return cached_metadata_;
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
index 4ccf6eb85d5..91df026974f 100644
--- 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
@@ -7,7 +7,7 @@
#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/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -25,12 +25,15 @@ class ServiceWorkerScriptCachedMetadataHandler
std::unique_ptr<Vector<uint8_t>> meta_data);
~ServiceWorkerScriptCachedMetadataHandler() override;
void Trace(Visitor*) const override;
- void SetCachedMetadata(uint32_t data_type_id,
+ void SetCachedMetadata(blink::mojom::CodeCacheHost*,
+ uint32_t data_type_id,
const uint8_t*,
size_t) override;
- void ClearCachedMetadata(ClearCacheType) override;
+ void ClearCachedMetadata(blink::mojom::CodeCacheHost*,
+ ClearCacheType) override;
scoped_refptr<CachedMetadata> GetCachedMetadata(
- uint32_t data_type_id) const override;
+ uint32_t data_type_id,
+ GetCachedMetadataBehavior behavior = kCrashIfUnchecked) const override;
String Encoding() const override;
bool IsServedFromCacheStorage() const override;
void OnMemoryDump(WebProcessMemoryDump* pmd,
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
index 77ce064ec23..3b6e1c0c624 100644
--- 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
@@ -19,6 +19,8 @@
#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
+#include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
@@ -83,7 +85,7 @@ class FakeWebURLLoader final : public WebURLLoader {
// Don't handle other requests intentionally to emulate ongoing load.
}
- void SetDefersLoading(DeferType defers) override {}
+ void Freeze(WebLoaderFreezeMode) override {}
void DidChangePriority(WebURLRequest::Priority, int) override {}
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
override {
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/OWNERS b/chromium/third_party/blink/renderer/modules/shapedetection/OWNERS
index d522bc6939e..3931a46acb7 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/OWNERS
@@ -1,7 +1,4 @@
reillyg@chromium.org
-# Original (legacy) owner.
-mcasas@chromium.org
-
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/idls.gni b/chromium/third_party/blink/renderer/modules/shapedetection/idls.gni
deleted file mode 100644
index f5bd50cc4b7..00000000000
--- a/chromium/third_party/blink/renderer/modules/shapedetection/idls.gni
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "barcode_detector.idl",
- "face_detector.idl",
- "text_detector.idl",
-]
-
-modules_dictionary_idl_files = [
- "barcode_detector_options.idl",
- "detected_barcode.idl",
- "detected_face.idl",
- "detected_text.idl",
- "face_detector_options.idl",
- "landmark.idl",
-]
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 d4c2d291ced..b10b708c141 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
@@ -27,41 +27,41 @@
namespace blink {
ScriptPromise ShapeDetector::detect(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8ImageBitmapSource* image_source_ptr
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ImageBitmapSourceUnion& image_source
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DCHECK(image_source_ptr);
- const V8ImageBitmapSource& image_source = *image_source_ptr;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8ImageBitmapSource* image_source) {
+ DCHECK(image_source);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- // ImageDatas cannot be tainted by definition.
- if (image_source.IsImageData())
- return DetectShapesOnImageData(resolver, image_source.GetAsImageData());
-
- CanvasImageSource* canvas_image_source;
- if (image_source.IsHTMLImageElement()) {
- canvas_image_source = image_source.GetAsHTMLImageElement();
- } else if (image_source.IsImageBitmap()) {
- canvas_image_source = image_source.GetAsImageBitmap();
- } else if (image_source.IsHTMLVideoElement()) {
- canvas_image_source = image_source.GetAsHTMLVideoElement();
- } else if (image_source.IsHTMLCanvasElement()) {
- canvas_image_source = image_source.GetAsHTMLCanvasElement();
- } else if (image_source.IsOffscreenCanvas()) {
- canvas_image_source = image_source.GetAsOffscreenCanvas();
- } else {
- NOTREACHED() << "Unsupported CanvasImageSource";
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotSupportedError, "Unsupported source."));
- return promise;
+ CanvasImageSource* canvas_image_source = nullptr;
+ switch (image_source->GetContentType()) {
+ case V8ImageBitmapSource::ContentType::kHTMLCanvasElement:
+ canvas_image_source = image_source->GetAsHTMLCanvasElement();
+ break;
+ case V8ImageBitmapSource::ContentType::kHTMLImageElement:
+ canvas_image_source = image_source->GetAsHTMLImageElement();
+ break;
+ case V8ImageBitmapSource::ContentType::kHTMLVideoElement:
+ canvas_image_source = image_source->GetAsHTMLVideoElement();
+ break;
+ case V8ImageBitmapSource::ContentType::kImageBitmap:
+ canvas_image_source = image_source->GetAsImageBitmap();
+ break;
+ case V8ImageBitmapSource::ContentType::kImageData:
+ // ImageData cannot be tainted by definition.
+ return DetectShapesOnImageData(resolver, image_source->GetAsImageData());
+ case V8ImageBitmapSource::ContentType::kOffscreenCanvas:
+ canvas_image_source = image_source->GetAsOffscreenCanvas();
+ break;
+ case V8ImageBitmapSource::ContentType::kBlob:
+ case V8ImageBitmapSource::ContentType::kSVGImageElement:
+ case V8ImageBitmapSource::ContentType::kVideoFrame:
+ NOTREACHED() << "Unsupported CanvasImageSource";
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError, "Unsupported source."));
+ return promise;
}
+ DCHECK(canvas_image_source);
if (canvas_image_source->WouldTaintOrigin()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -69,9 +69,9 @@ ScriptPromise ShapeDetector::detect(ScriptState* script_state,
return promise;
}
- if (image_source.IsHTMLImageElement()) {
+ if (image_source->IsHTMLImageElement()) {
return DetectShapesOnImageElement(resolver,
- image_source.GetAsHTMLImageElement());
+ image_source->GetAsHTMLImageElement());
}
// TODO(mcasas): Check if |video| is actually playing a MediaStream by using
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h
index cc70fd143e1..43bc7f86bb8 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h
@@ -10,7 +10,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h"
-#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_source_union.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -21,12 +20,8 @@ class MODULES_EXPORT ShapeDetector : public ScriptWrappable {
public:
~ShapeDetector() override = default;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ScriptPromise detect(ScriptState* script_state,
const V8ImageBitmapSource* image_source);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise detect(ScriptState*, const ImageBitmapSourceUnion&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
ScriptPromise DetectShapesOnImageData(ScriptPromiseResolver*, ImageData*);
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/BUILD.gn b/chromium/third_party/blink/renderer/modules/shared_storage/BUILD.gn
new file mode 100644
index 00000000000..9eb4f6be99d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("shared_storage") {
+ sources = [
+ "shared_storage.cc",
+ "shared_storage.h",
+ "shared_storage_worklet.cc",
+ "shared_storage_worklet.h",
+ "window_shared_storage.cc",
+ "window_shared_storage.h",
+ ]
+
+ public_deps = [ "//third_party/blink/public/mojom:mojom_modules_blink" ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/DEPS b/chromium/third_party/blink/renderer/modules/shared_storage/DEPS
new file mode 100644
index 00000000000..e5844f138e1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "-third_party/blink/renderer/modules",
+ "+third_party/blink/renderer/modules/modules_export.h",
+ "+third_party/blink/renderer/modules/shared_storage",
+ "+third_party/blink/renderer/modules/v8",
+ "+third_party/blink/renderer/core",
+]
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/OWNERS b/chromium/third_party/blink/renderer/modules/shared_storage/OWNERS
new file mode 100644
index 00000000000..2051ea7ca96
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/OWNERS
@@ -0,0 +1,2 @@
+yaoxia@chromium.org
+cammie@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/breakout_box/idls.gni b/chromium/third_party/blink/renderer/modules/shared_storage/idls.gni
index 46813d67424..7873256fdb9 100644
--- a/chromium/third_party/blink/renderer/modules/breakout_box/idls.gni
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/idls.gni
@@ -3,12 +3,13 @@
# found in the LICENSE file.
modules_idl_files = [
- "media_stream_track_generator.idl",
- "media_stream_track_processor.idl",
+ "shared_storage_worklet.idl",
+ "shared_storage.idl",
]
modules_dictionary_idl_files = [
- "media_stream_track_generator_init.idl",
- "media_stream_track_processor_init.idl",
- "media_stream_track_signal.idl",
+ "shared_storage_set_method_options.idl",
+ "shared_storage_run_operation_method_options.idl",
]
+
+modules_dependency_idl_files = [ "window_shared_storage.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.cc b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
new file mode 100644
index 00000000000..f45d46198c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
@@ -0,0 +1,217 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/shared_storage/shared_storage.h"
+
+#include <memory>
+#include <utility>
+
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/features.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_content_settings_client.h"
+#include "third_party/blink/public/platform/web_security_origin.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/bindings/modules/v8/v8_binding_for_modules.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_run_operation_method_options.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_shared_storage_set_method_options.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_dom_window.h"
+#include "third_party/blink/renderer/core/probe/async_task_id.h"
+#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.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/heap/persistent.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+SharedStorage::SharedStorage() = default;
+SharedStorage::~SharedStorage() = default;
+
+void SharedStorage::Trace(Visitor* visitor) const {
+ visitor->Trace(shared_storage_worklet_);
+ ScriptWrappable::Trace(visitor);
+}
+
+ScriptPromise SharedStorage::set(ScriptState* script_state,
+ const String& key,
+ const String& value,
+ ExceptionState& exception_state) {
+ return set(script_state, key, value, SharedStorageSetMethodOptions::Create(),
+ exception_state);
+}
+
+ScriptPromise SharedStorage::set(ScriptState* script_state,
+ const String& key,
+ const String& value,
+ const SharedStorageSetMethodOptions* options,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // TODO: handle the operation
+ resolver->Resolve();
+ return promise;
+}
+
+ScriptPromise SharedStorage::append(ScriptState* script_state,
+ const String& key,
+ const String& value,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // TODO: handle the operation
+ resolver->Resolve();
+ return promise;
+}
+
+ScriptPromise SharedStorage::Delete(ScriptState* script_state,
+ const String& key,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // TODO: handle the operation
+ resolver->Resolve();
+ return promise;
+}
+
+ScriptPromise SharedStorage::clear(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // TODO: handle the operation
+ resolver->Resolve();
+ return promise;
+}
+
+ScriptPromise SharedStorage::runURLSelectionOperation(
+ ScriptState* script_state,
+ const String& name,
+ const Vector<String>& urls,
+ ExceptionState& exception_state) {
+ return runURLSelectionOperation(
+ script_state, name, urls,
+ SharedStorageRunOperationMethodOptions::Create(), exception_state);
+}
+
+ScriptPromise SharedStorage::runURLSelectionOperation(
+ ScriptState* script_state,
+ const String& name,
+ const Vector<String>& urls,
+ const SharedStorageRunOperationMethodOptions* options,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ if (urls.size() >
+ static_cast<unsigned int>(
+ features::kSharedStorageURLSelectionOperationInputURLSizeLimit
+ .Get())) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kDataError,
+ "Length of the \"urls\" parameter exceeds the size limit."));
+ return promise;
+ }
+
+ Vector<KURL> converted_urls;
+ converted_urls.ReserveInitialCapacity(urls.size());
+
+ for (const String& url : urls) {
+ KURL converted_url = execution_context->CompleteURL(url);
+ if (!converted_url.IsValid()) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kDataError,
+ "The url \"" + url + "\" is invalid."));
+ return promise;
+ }
+
+ converted_urls.push_back(converted_url);
+ }
+
+ // TODO: handle the operation
+ return promise;
+}
+
+ScriptPromise SharedStorage::runOperation(ScriptState* script_state,
+ const String& name,
+ ExceptionState& exception_state) {
+ return runOperation(script_state, name,
+ SharedStorageRunOperationMethodOptions::Create(),
+ exception_state);
+}
+
+ScriptPromise SharedStorage::runOperation(
+ ScriptState* script_state,
+ const String& name,
+ const SharedStorageRunOperationMethodOptions* options,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ resolver->Resolve();
+
+ // TODO: handle the operation
+ return promise;
+}
+
+SharedStorageWorklet* SharedStorage::worklet(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ if (shared_storage_worklet_)
+ return shared_storage_worklet_.Get();
+
+ shared_storage_worklet_ = MakeGarbageCollected<SharedStorageWorklet>(this);
+
+ return shared_storage_worklet_.Get();
+}
+
+mojom::blink::SharedStorageDocumentService*
+SharedStorage::GetSharedStorageDocumentService(
+ ExecutionContext* execution_context) {
+ CHECK(execution_context->IsWindow());
+ if (!shared_storage_document_service_.is_bound()) {
+ execution_context->GetBrowserInterfaceBroker().GetInterface(
+ shared_storage_document_service_.BindNewPipeAndPassReceiver(
+ execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ }
+ return shared_storage_document_service_.get();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.h b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.h
new file mode 100644
index 00000000000..bd8e4fa9129
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.h
@@ -0,0 +1,88 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_SHARED_STORAGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_SHARED_STORAGE_H_
+
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/feature_observer/feature_observer.mojom-blink.h"
+#include "third_party/blink/public/mojom/shared_storage/shared_storage.mojom-blink.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/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 ExceptionState;
+class ScriptState;
+class SharedStorageWorklet;
+class SharedStorageSetMethodOptions;
+class SharedStorageRunOperationMethodOptions;
+
+class MODULES_EXPORT SharedStorage final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ SharedStorage();
+ ~SharedStorage() override;
+
+ void Trace(Visitor*) const override;
+
+ // SharedStorage IDL
+ ScriptPromise set(ScriptState*,
+ const String& key,
+ const String& value,
+ ExceptionState&);
+ ScriptPromise set(ScriptState*,
+ const String& key,
+ const String& value,
+ const SharedStorageSetMethodOptions* options,
+ ExceptionState&);
+
+ ScriptPromise append(ScriptState*,
+ const String& key,
+ const String& value,
+ ExceptionState&);
+
+ ScriptPromise Delete(ScriptState*, const String& key, ExceptionState&);
+
+ ScriptPromise clear(ScriptState*, ExceptionState&);
+
+ ScriptPromise runURLSelectionOperation(ScriptState*,
+ const String& name,
+ const Vector<String>& urls,
+ ExceptionState&);
+ ScriptPromise runURLSelectionOperation(
+ ScriptState*,
+ const String& name,
+ const Vector<String>& urls,
+ const SharedStorageRunOperationMethodOptions* options,
+ ExceptionState&);
+
+ ScriptPromise runOperation(ScriptState*, const String& name, ExceptionState&);
+ ScriptPromise runOperation(
+ ScriptState*,
+ const String& name,
+ const SharedStorageRunOperationMethodOptions* options,
+ ExceptionState&);
+
+ SharedStorageWorklet* worklet(ScriptState*, ExceptionState&);
+
+ private:
+ mojom::blink::SharedStorageDocumentService* GetSharedStorageDocumentService(
+ ExecutionContext* execution_context);
+
+ mojo::Remote<mojom::blink::SharedStorageDocumentService>
+ shared_storage_document_service_;
+
+ Member<SharedStorageWorklet> shared_storage_worklet_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_SHARED_STORAGE_H_
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.idl b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.idl
new file mode 100644
index 00000000000..c9b03539bff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage.idl
@@ -0,0 +1,40 @@
+// The Shared Storage API.
+// https://github.com/pythagoraskitty/shared-storage/blob/main/README.md
+[
+ RuntimeEnabled=SharedStorageAPI,
+ Exposed=(Window)
+] interface SharedStorage {
+ [
+ CallWith=ScriptState,
+ RaisesException
+ ] Promise<any> set(DOMString key, DOMString value, optional SharedStorageSetMethodOptions options);
+
+ [
+ CallWith=ScriptState,
+ RaisesException
+ ] Promise<any> append(DOMString key, DOMString value);
+
+ [
+ CallWith=ScriptState,
+ ImplementedAs=Delete,
+ RaisesException
+ ] Promise<any> delete(DOMString key);
+
+ [
+ CallWith=ScriptState,
+ RaisesException
+ ] Promise<any> clear();
+
+ [
+ CallWith=ScriptState,
+ RaisesException
+ ] Promise<USVString> runURLSelectionOperation(DOMString name, FrozenArray<USVString> urls,
+ optional SharedStorageRunOperationMethodOptions options);
+
+ [
+ CallWith=ScriptState,
+ RaisesException
+ ] Promise<any> runOperation(DOMString name, optional SharedStorageRunOperationMethodOptions options);
+
+ [CallWith=ScriptState, RaisesException] readonly attribute SharedStorageWorklet worklet;
+};
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_run_operation_method_options.idl b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_run_operation_method_options.idl
new file mode 100644
index 00000000000..d7f22fc1c43
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_run_operation_method_options.idl
@@ -0,0 +1,3 @@
+dictionary SharedStorageRunOperationMethodOptions {
+ object data;
+};
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_set_method_options.idl b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_set_method_options.idl
new file mode 100644
index 00000000000..46a8fd61a7e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_set_method_options.idl
@@ -0,0 +1,3 @@
+dictionary SharedStorageSetMethodOptions {
+ boolean ignoreIfPresent;
+};
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc
new file mode 100644
index 00000000000..0f0fa832324
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc
@@ -0,0 +1,59 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.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_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/modules/shared_storage/shared_storage.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+
+namespace blink {
+
+SharedStorageWorklet::SharedStorageWorklet(SharedStorage* shared_storage)
+ : shared_storage_(shared_storage) {}
+
+void SharedStorageWorklet::Trace(Visitor* visitor) const {
+ visitor->Trace(shared_storage_);
+ ScriptWrappable::Trace(visitor);
+}
+
+ScriptPromise SharedStorageWorklet::addModule(ScriptState* script_state,
+ const String& module_url,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ CHECK(execution_context->IsWindow());
+
+ KURL script_source_url = execution_context->CompleteURL(module_url);
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ if (!script_source_url.IsValid()) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kDataError,
+ "The module script url is invalid."));
+ return promise;
+ }
+
+ scoped_refptr<SecurityOrigin> script_security_origin =
+ SecurityOrigin::Create(script_source_url);
+
+ if (!execution_context->GetSecurityOrigin()->IsSameOriginDomainWith(
+ script_security_origin.get())) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kDataError,
+ "Only same origin module script is allowed."));
+ return promise;
+ }
+
+ // TODO: handle the operation
+ return promise;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.h b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.h
new file mode 100644
index 00000000000..eb275adbc90
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.h
@@ -0,0 +1,41 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_SHARED_STORAGE_WORKLET_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_SHARED_STORAGE_WORKLET_H_
+
+#include "base/macros.h"
+#include "third_party/blink/public/mojom/shared_storage/shared_storage.mojom-blink.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/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class SharedStorage;
+
+// Implement the worklet attribute under window.sharedStorage.
+class MODULES_EXPORT SharedStorageWorklet final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit SharedStorageWorklet(SharedStorage*);
+ ~SharedStorageWorklet() override = default;
+
+ void Trace(Visitor*) const override;
+
+ // shared_storage_worklet.idl
+ // addModule() imports ES6 module scripts.
+ ScriptPromise addModule(ScriptState*,
+ const String& module_url,
+ ExceptionState&);
+
+ private:
+ Member<SharedStorage> shared_storage_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_SHARED_STORAGE_WORKLET_H_
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.idl b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.idl
new file mode 100644
index 00000000000..6a98856e39a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.idl
@@ -0,0 +1,9 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+ Exposed=SharedStorage
+] interface SharedStorageWorklet {
+ [CallWith=ScriptState, RaisesException] Promise<void> addModule(USVString moduleURL);
+};
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.cc b/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.cc
new file mode 100644
index 00000000000..aad22dd1a6b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.cc
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/shared_storage/window_shared_storage.h"
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/shared_storage/shared_storage.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+namespace {
+
+class WindowSharedStorageImpl final
+ : public GarbageCollected<WindowSharedStorageImpl>,
+ public Supplement<LocalDOMWindow> {
+ public:
+ static const char kSupplementName[];
+
+ static WindowSharedStorageImpl& From(LocalDOMWindow& window) {
+ WindowSharedStorageImpl* supplement =
+ Supplement<LocalDOMWindow>::template From<WindowSharedStorageImpl>(
+ window);
+ if (!supplement) {
+ supplement = MakeGarbageCollected<WindowSharedStorageImpl>(window);
+ Supplement<LocalDOMWindow>::ProvideTo(window, supplement);
+ }
+ return *supplement;
+ }
+
+ explicit WindowSharedStorageImpl(LocalDOMWindow& window)
+ : Supplement<LocalDOMWindow>(window) {}
+
+ SharedStorage* GetOrCreate(LocalDOMWindow& fetching_scope) {
+ if (!shared_storage_)
+ shared_storage_ = MakeGarbageCollected<SharedStorage>();
+ return shared_storage_;
+ }
+
+ void Trace(Visitor* visitor) const override {
+ visitor->Trace(shared_storage_);
+ Supplement<LocalDOMWindow>::Trace(visitor);
+ }
+
+ private:
+ Member<SharedStorage> shared_storage_;
+};
+
+// static
+const char WindowSharedStorageImpl::kSupplementName[] =
+ "WindowSharedStorageImpl";
+
+} // namespace
+
+SharedStorage* WindowSharedStorage::sharedStorage(LocalDOMWindow& window) {
+ return WindowSharedStorageImpl::From(window).GetOrCreate(window);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.h b/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.h
new file mode 100644
index 00000000000..27a128f6063
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.h
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_WINDOW_SHARED_STORAGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_WINDOW_SHARED_STORAGE_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class SharedStorage;
+class LocalDOMWindow;
+
+// Implement the sharedStorage attribute under Window.
+class WindowSharedStorage {
+ STATIC_ONLY(WindowSharedStorage);
+
+ public:
+ static SharedStorage* sharedStorage(LocalDOMWindow&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SHARED_STORAGE_WINDOW_SHARED_STORAGE_H_
diff --git a/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.idl b/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.idl
new file mode 100644
index 00000000000..9750bb93956
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/shared_storage/window_shared_storage.idl
@@ -0,0 +1,6 @@
+[
+ RuntimeEnabled=SharedStorageAPI,
+ ImplementedAs=WindowSharedStorage
+] partial interface Window {
+ readonly attribute SharedStorage sharedStorage;
+};
diff --git a/chromium/third_party/blink/renderer/modules/speech/OWNERS b/chromium/third_party/blink/renderer/modules/speech/OWNERS
index 5ecb2f4da44..55080402b2a 100644
--- a/chromium/third_party/blink/renderer/modules/speech/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/speech/OWNERS
@@ -1,5 +1,5 @@
-# Speech synthesis, and final approval for speech recognition
+# Speech synthesis
dmazzoni@chromium.org
-# Speech recognition - send reviews here first, then to dmazzoni for approval.
-tommi@chromium.org
+# Speech recognition
+evliu@google.com
diff --git a/chromium/third_party/blink/renderer/modules/speech/idls.gni b/chromium/third_party/blink/renderer/modules/speech/idls.gni
deleted file mode 100644
index 3d801b3cde1..00000000000
--- a/chromium/third_party/blink/renderer/modules/speech/idls.gni
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "speech_grammar.idl",
- "speech_grammar_list.idl",
- "speech_recognition.idl",
- "speech_recognition_alternative.idl",
- "speech_recognition_error_event.idl",
- "speech_recognition_event.idl",
- "speech_recognition_result.idl",
- "speech_recognition_result_list.idl",
- "speech_synthesis.idl",
- "speech_synthesis_error_event.idl",
- "speech_synthesis_event.idl",
- "speech_synthesis_utterance.idl",
- "speech_synthesis_voice.idl",
-]
-
-modules_dictionary_idl_files = [
- "speech_recognition_error_event_init.idl",
- "speech_recognition_event_init.idl",
- "speech_synthesis_error_event_init.idl",
- "speech_synthesis_event_init.idl",
-]
-
-modules_dependency_idl_files = [ "window_speech_synthesis.idl" ]
-
-modules_testing_dependency_idl_files =
- [ "testing/internals_speech_synthesis.idl" ]
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 7975d851d42..e1356092257 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
@@ -26,9 +26,12 @@
#include "third_party/blink/renderer/modules/speech/speech_recognition.h"
#include <algorithm>
+
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom-blink.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom-blink.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"
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 b2e6006ab30..06220437125 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc
@@ -236,8 +236,7 @@ void SpeechSynthesis::SentenceBoundaryEventOccurred(
}
void SpeechSynthesis::VoicesDidChange() {
- if (GetSupplementable()->GetFrame())
- DispatchEvent(*Event::Create(event_type_names::kVoiceschanged));
+ DispatchEvent(*Event::Create(event_type_names::kVoiceschanged));
}
void SpeechSynthesis::StartSpeakingImmediately() {
diff --git a/chromium/third_party/blink/renderer/modules/srcobject/idls.gni b/chromium/third_party/blink/renderer/modules/srcobject/idls.gni
deleted file mode 100644
index d845a7188e8..00000000000
--- a/chromium/third_party/blink/renderer/modules/srcobject/idls.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "html_media_element_src_object.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.cc b/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.cc
index 4b98ae5eb00..f61826af652 100644
--- a/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.cc
@@ -190,14 +190,15 @@ CachedStorageArea::CachedStorageArea(
scoped_refptr<const SecurityOrigin> origin,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
StorageNamespace* storage_namespace,
- bool is_session_storage_for_prerendering)
+ bool is_session_storage_for_prerendering,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area)
: type_(type),
origin_(std::move(origin)),
storage_namespace_(storage_namespace),
is_session_storage_for_prerendering_(is_session_storage_for_prerendering),
task_runner_(std::move(task_runner)),
areas_(MakeGarbageCollected<HeapHashMap<WeakMember<Source>, String>>()) {
- BindStorageArea();
+ BindStorageArea(std::move(storage_area));
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "DOMStorage",
ThreadScheduler::Current()->DeprecatedDefaultTaskRunner());
@@ -792,4 +793,8 @@ Vector<uint8_t> CachedStorageArea::StringToUint8Vector(
NOTREACHED();
}
+void CachedStorageArea::EvictCachedData() {
+ map_.reset();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.h b/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.h
index 68caa52aab9..969fba0412c 100644
--- a/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.h
+++ b/chromium/third_party/blink/renderer/modules/storage/cached_storage_area.h
@@ -60,11 +60,13 @@ class MODULES_EXPORT CachedStorageArea
kLocalStorage,
};
- CachedStorageArea(AreaType type,
- scoped_refptr<const SecurityOrigin> origin,
- scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
- StorageNamespace* storage_namespace,
- bool is_session_storage_for_prerendering);
+ CachedStorageArea(
+ AreaType type,
+ scoped_refptr<const SecurityOrigin> origin,
+ scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
+ StorageNamespace* storage_namespace,
+ bool is_session_storage_for_prerendering,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area = {});
// These correspond to blink::Storage.
unsigned GetLength();
@@ -102,6 +104,8 @@ class MODULES_EXPORT CachedStorageArea
return is_session_storage_for_prerendering_;
}
+ void EvictCachedData();
+
void SetRemoteAreaForTesting(
mojo::PendingRemote<mojom::blink::StorageArea> area) {
remote_area_.Bind(std::move(area));
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 9888455e907..5ee5066487d 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
@@ -19,6 +19,10 @@
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
+namespace {
+constexpr const char kAccessDeniedMessage[] =
+ "Access is denied for this document.";
+}
DOMWindowStorage::DOMWindowStorage(LocalDOMWindow& window)
: Supplement<LocalDOMWindow>(window) {}
@@ -57,11 +61,62 @@ StorageArea* DOMWindowStorage::localStorage(LocalDOMWindow& window,
StorageArea* DOMWindowStorage::sessionStorage(
ExceptionState& exception_state) const {
+ StorageArea* storage = GetOrCreateSessionStorage(exception_state, {});
+ if (!storage)
+ return nullptr;
+
+ LocalDOMWindow* window = GetSupplementable();
+ if (window->GetSecurityOrigin()->IsLocal())
+ UseCounter::Count(window, WebFeature::kFileAccessedSessionStorage);
+
+ if (!storage->CanAccessStorage()) {
+ exception_state.ThrowSecurityError(kAccessDeniedMessage);
+ return nullptr;
+ }
+ return storage;
+}
+
+StorageArea* DOMWindowStorage::localStorage(
+ ExceptionState& exception_state) const {
+ StorageArea* storage = GetOrCreateLocalStorage(exception_state, {});
+ if (!storage)
+ return nullptr;
+
+ LocalDOMWindow* window = GetSupplementable();
+ if (window->GetSecurityOrigin()->IsLocal())
+ UseCounter::Count(window, WebFeature::kFileAccessedLocalStorage);
+
+ if (!storage->CanAccessStorage()) {
+ exception_state.ThrowSecurityError(kAccessDeniedMessage);
+ return nullptr;
+ }
+ return storage;
+}
+
+void DOMWindowStorage::InitSessionStorage(
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area) const {
+ // It's safe to ignore exceptions here since this is just an optimization to
+ // avoid requesting the storage area later.
+ GetOrCreateSessionStorage(IGNORE_EXCEPTION_FOR_TESTING,
+ std::move(storage_area));
+}
+
+void DOMWindowStorage::InitLocalStorage(
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area) const {
+ // It's safe to ignore exceptions here since this is just an optimization to
+ // avoid requesting the storage area later.
+ GetOrCreateLocalStorage(IGNORE_EXCEPTION_FOR_TESTING,
+ std::move(storage_area));
+}
+
+StorageArea* DOMWindowStorage::GetOrCreateSessionStorage(
+ ExceptionState& exception_state,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area_for_init)
+ const {
LocalDOMWindow* window = GetSupplementable();
if (!window->GetFrame())
return nullptr;
- String access_denied_message = "Access is denied for this document.";
if (!window->GetSecurityOrigin()->CanAccessSessionStorage()) {
if (window->IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin))
exception_state.ThrowSecurityError(
@@ -70,21 +125,12 @@ StorageArea* DOMWindowStorage::sessionStorage(
exception_state.ThrowSecurityError(
"Storage is disabled inside 'data:' URLs.");
else
- exception_state.ThrowSecurityError(access_denied_message);
+ exception_state.ThrowSecurityError(kAccessDeniedMessage);
return nullptr;
}
- if (window->GetSecurityOrigin()->IsLocal()) {
- UseCounter::Count(window, WebFeature::kFileAccessedSessionStorage);
- }
-
- if (session_storage_) {
- if (!session_storage_->CanAccessStorage()) {
- exception_state.ThrowSecurityError(access_denied_message);
- return nullptr;
- }
+ if (session_storage_)
return session_storage_;
- }
StorageNamespace* storage_namespace =
StorageNamespace::From(window->GetFrame()->GetPage());
@@ -93,29 +139,26 @@ StorageArea* DOMWindowStorage::sessionStorage(
scoped_refptr<CachedStorageArea> cached_storage_area;
if (window->document()->IsPrerendering()) {
cached_storage_area = storage_namespace->CreateCachedAreaForPrerender(
- window->GetSecurityOrigin());
+ window->GetSecurityOrigin(), std::move(storage_area_for_init));
} else {
- cached_storage_area =
- storage_namespace->GetCachedArea(window->GetSecurityOrigin());
+ cached_storage_area = storage_namespace->GetCachedArea(
+ window->GetSecurityOrigin(), std::move(storage_area_for_init));
}
session_storage_ =
StorageArea::Create(window, std::move(cached_storage_area),
StorageArea::StorageType::kSessionStorage);
- if (!session_storage_->CanAccessStorage()) {
- exception_state.ThrowSecurityError(access_denied_message);
- return nullptr;
- }
return session_storage_;
}
-StorageArea* DOMWindowStorage::localStorage(
- ExceptionState& exception_state) const {
+StorageArea* DOMWindowStorage::GetOrCreateLocalStorage(
+ ExceptionState& exception_state,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area_for_init)
+ const {
LocalDOMWindow* window = GetSupplementable();
if (!window->GetFrame())
return nullptr;
- String access_denied_message = "Access is denied for this document.";
if (!window->GetSecurityOrigin()->CanAccessLocalStorage()) {
if (window->IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin))
exception_state.ThrowSecurityError(
@@ -124,32 +167,20 @@ StorageArea* DOMWindowStorage::localStorage(
exception_state.ThrowSecurityError(
"Storage is disabled inside 'data:' URLs.");
else
- exception_state.ThrowSecurityError(access_denied_message);
+ exception_state.ThrowSecurityError(kAccessDeniedMessage);
return nullptr;
}
- if (window->GetSecurityOrigin()->IsLocal()) {
- UseCounter::Count(window, WebFeature::kFileAccessedLocalStorage);
- }
-
- if (local_storage_) {
- if (!local_storage_->CanAccessStorage()) {
- exception_state.ThrowSecurityError(access_denied_message);
- return nullptr;
- }
- return local_storage_;
- }
if (!window->GetFrame()->GetSettings()->GetLocalStorageEnabled())
return nullptr;
+
+ if (local_storage_)
+ return local_storage_;
+
auto storage_area = StorageController::GetInstance()->GetLocalStorageArea(
- window->GetSecurityOrigin());
+ window->GetSecurityOrigin(), std::move(storage_area_for_init));
local_storage_ = StorageArea::Create(window, std::move(storage_area),
StorageArea::StorageType::kLocalStorage);
-
- if (!local_storage_->CanAccessStorage()) {
- exception_state.ThrowSecurityError(access_denied_message);
- return nullptr;
- }
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 0f260e0fa6d..a7451969b77 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
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_DOM_WINDOW_STORAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_DOM_WINDOW_STORAGE_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -30,9 +32,27 @@ class DOMWindowStorage final : public GarbageCollected<DOMWindowStorage>,
StorageArea* OptionalSessionStorage() const { return session_storage_.Get(); }
StorageArea* OptionalLocalStorage() const { return local_storage_.Get(); }
+ // These Init* methods allow initializing the StorageArea as an optimization
+ // to avoid it being requested from the browser process, which can be slow.
+ // These storage areas are ignored if a cached storage area already exists for
+ // this storage key/namespace.
+ void InitLocalStorage(
+ mojo::PendingRemote<mojom::blink::StorageArea> local_storage_area) const;
+ void InitSessionStorage(mojo::PendingRemote<mojom::blink::StorageArea>
+ session_storage_area) const;
+
void Trace(Visitor*) const override;
private:
+ StorageArea* GetOrCreateSessionStorage(
+ ExceptionState& exception_state,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area_for_init)
+ const;
+ StorageArea* GetOrCreateLocalStorage(
+ ExceptionState& exception_state,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area_for_init)
+ const;
+
mutable Member<StorageArea> session_storage_;
mutable Member<StorageArea> local_storage_;
};
diff --git a/chromium/third_party/blink/renderer/modules/storage/idls.gni b/chromium/third_party/blink/renderer/modules/storage/idls.gni
deleted file mode 100644
index 075b9410548..00000000000
--- a/chromium/third_party/blink/renderer/modules/storage/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "storage.idl",
- "storage_event.idl",
-]
-
-modules_dictionary_idl_files = [ "storage_event_init.idl" ]
-
-modules_dependency_idl_files = [ "window_storage.idl" ]
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 a40cd639f95..55986fc45dd 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_area.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_area.cc
@@ -28,6 +28,7 @@
#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/public/common/action_after_pagehide.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/task_type.h"
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_controller.cc b/chromium/third_party/blink/renderer/modules/storage/storage_controller.cc
index 105301685f6..0016639cd51 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_controller.cc
@@ -118,10 +118,12 @@ void StorageController::ClearAreasIfNeeded() {
}
scoped_refptr<CachedStorageArea> StorageController::GetLocalStorageArea(
- const SecurityOrigin* origin) {
+ const SecurityOrigin* origin,
+ mojo::PendingRemote<mojom::blink::StorageArea> local_storage_area) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
EnsureLocalStorageNamespaceCreated();
- return local_storage_namespace_->GetCachedArea(origin);
+ return local_storage_namespace_->GetCachedArea(origin,
+ std::move(local_storage_area));
}
void StorageController::AddLocalStorageInspectorStorageAgent(
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_controller.h b/chromium/third_party/blink/renderer/modules/storage/storage_controller.h
index 4e4a245ea9b..63c631f639e 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_controller.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_controller.h
@@ -33,12 +33,12 @@ class StorageNamespace;
// Singleton that manages the creation & accounting for DOMStorage objects. It
// does this by holding weak references to all session storage namespaces, and
// owning the local storage namespace internally. The total cache size is
-// exposed with |TotalCacheSize()|, and |ClearAreasIfNeeded()| will - if our
-// total cache size is larger than |total_cache_limit| - clear away any cache
+// exposed with `TotalCacheSize()`, and `ClearAreasIfNeeded()` will - if our
+// total cache size is larger than `total_cache_limit` - clear away any cache
// areas in live namespaces that no longer have references from Blink objects.
//
// SessionStorage StorageNamespace objects are created with
-// |CreateSessionStorageNamespace| and live as a supplement on the Page.
+// `CreateSessionStorageNamespace` and live as a supplement on the Page.
//
// The LocalStorage StorageNamespace object is owned internally, and
// StorageController delegates the following methods to that namespace:
@@ -78,7 +78,9 @@ class MODULES_EXPORT StorageController : public mojom::blink::DomStorageClient {
// Methods that delegate to the internal StorageNamespace used for
// LocalStorage:
- scoped_refptr<CachedStorageArea> GetLocalStorageArea(const SecurityOrigin*);
+ scoped_refptr<CachedStorageArea> GetLocalStorageArea(
+ const SecurityOrigin*,
+ mojo::PendingRemote<mojom::blink::StorageArea> local_storage_area = {});
void AddLocalStorageInspectorStorageAgent(InspectorDOMStorageAgent* agent);
void RemoveLocalStorageInspectorStorageAgent(InspectorDOMStorageAgent* agent);
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 234567d1e8b..5a2b84ca989 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc
@@ -68,7 +68,8 @@ void StorageNamespace::ProvideSessionStorageNamespaceTo(
}
scoped_refptr<CachedStorageArea> StorageNamespace::GetCachedArea(
- const SecurityOrigin* origin_ptr) {
+ const SecurityOrigin* origin_ptr,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area) {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class CacheMetrics {
@@ -103,20 +104,31 @@ scoped_refptr<CachedStorageArea> StorageNamespace::GetCachedArea(
IsSessionStorage() ? CachedStorageArea::AreaType::kSessionStorage
: CachedStorageArea::AreaType::kLocalStorage,
origin, controller_->TaskRunner(), this,
- /*is_session_storage_for_prerendering=*/false);
+ /*is_session_storage_for_prerendering=*/false, std::move(storage_area));
cached_areas_.insert(std::move(origin), result);
return result;
}
scoped_refptr<CachedStorageArea> StorageNamespace::CreateCachedAreaForPrerender(
- const SecurityOrigin* origin_ptr) {
+ const SecurityOrigin* origin_ptr,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area) {
DCHECK((IsSessionStorage()));
scoped_refptr<const SecurityOrigin> origin(origin_ptr);
return base::MakeRefCounted<CachedStorageArea>(
IsSessionStorage() ? CachedStorageArea::AreaType::kSessionStorage
: CachedStorageArea::AreaType::kLocalStorage,
origin, controller_->TaskRunner(), this,
- /*is_session_storage_for_prerendering=*/true);
+ /*is_session_storage_for_prerendering=*/true, std::move(storage_area));
+}
+
+void StorageNamespace::EvictSessionStorageCachedData() {
+ // Currently this is called to evict the cached data only when prerendering
+ // was triggered. TODO(crbug.com/1215680): investigate if more cache eviction
+ // is needed for non-prerender use cases.
+ DCHECK(IsSessionStorage());
+ for (auto& entry : cached_areas_) {
+ entry.value->EvictCachedData();
+ }
}
void StorageNamespace::CloneTo(const String& target) {
@@ -136,7 +148,7 @@ void StorageNamespace::CloneTo(const String& target) {
// First, we synchronize StorageNamespace against every cached StorageArea.
// This ensures that all StorageArea operations (e.g. Put, Delete) up to this
// point will have executed before the StorageNamespace implementation is able
- // to receive or process the following |Clone()| call. Given the above
+ // to receive or process the following `Clone()` call. Given the above
// example, this would mean that A.x=42 and B.y=13 definitely WILL be present
// in the cloned namespace.
for (auto& entry : cached_areas_) {
@@ -148,7 +160,7 @@ void StorageNamespace::CloneTo(const String& target) {
// Finally, we synchronize every StorageArea against StorageNamespace. This
// ensures that any future calls on each StorageArea cannot be received and
- // processed until after the above |Clone()| call executes. Given the example
+ // processed until after the above `Clone()` call executes. Given the example
// above, this would mean that A.x=43 definitely WILL NOT be present in the
// cloned namespace; only the original namespace will be updated, and A.x will
// still hold a value of 42 in the new clone.
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 ec3658217d6..8e52c986cb0 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
@@ -54,15 +54,15 @@ class SecurityOrigin;
// LocalStorage namespace with no (or an empty) namespace_id. The LocalStorage
// version of the StorageNamespace lives in the StorageController.
// InspectorDOMStorageAgents that are registered on this object are notified
-// through |DidDispatchStorageEvent|.
+// through `DidDispatchStorageEvent`.
//
// With the kOnionSoupDOMStorage flag off:
// The StorageNamespace basically delegates calls to GetWebStorageArea to the
-// internal WebStorageNamespace. |GetWebStorageArea| is used to get the storage
+// internal WebStorageNamespace. `GetWebStorageArea` is used to get the storage
// area for an origin.
//
// With the kOnionSoupDOMStorage flag on:
-// The StorageNamespace for SessioStorage supplement the Page. |GetCachedArea|
+// The StorageNamespace for SessionStorage supplement the Page. `GetCachedArea`
// is used to get the storage area for an origin.
class MODULES_EXPORT StorageNamespace final
: public GarbageCollected<StorageNamespace>,
@@ -82,12 +82,18 @@ class MODULES_EXPORT StorageNamespace final
// Creates a namespace for SessionStorage.
StorageNamespace(StorageController*, const String& namespace_id);
- scoped_refptr<CachedStorageArea> GetCachedArea(const SecurityOrigin* origin);
+ // |storage_area| is ignored here if a cached namespace already exists.
+ scoped_refptr<CachedStorageArea> GetCachedArea(
+ const SecurityOrigin* origin,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area = {});
scoped_refptr<CachedStorageArea> CreateCachedAreaForPrerender(
- const SecurityOrigin* origin);
+ const SecurityOrigin* origin,
+ mojo::PendingRemote<mojom::blink::StorageArea> storage_area = {});
- // Only valid to call this if |this| and |target| are session storage
+ void EvictSessionStorageCachedData();
+
+ // Only valid to call this if `this` and `target` are session storage
// namespaces.
void CloneTo(const String& target);
@@ -104,13 +110,13 @@ class MODULES_EXPORT StorageNamespace final
void Trace(Visitor* visitor) const override;
// Iterates all of the inspector agents and calls
- // |DidDispatchDOMStorageEvent|.
+ // `DidDispatchDOMStorageEvent`.
void DidDispatchStorageEvent(const SecurityOrigin* origin,
const String& key,
const String& old_value,
const String& new_value);
- // Called by areas in |cached_areas_| to bind/rebind their StorageArea
+ // Called by areas in `cached_areas_` to bind/rebind their StorageArea
// interface.
void BindStorageArea(
const scoped_refptr<const SecurityOrigin>& origin,
@@ -129,8 +135,8 @@ class MODULES_EXPORT StorageNamespace final
// Lives globally.
StorageController* controller_;
String namespace_id_;
- // |StorageNamespace| is a per-Page object and doesn't have any
- // |ExecutionContext|.
+ // `StorageNamespace` is a per-Page object and doesn't have any
+ // `ExecutionContext`.
HeapMojoRemote<mojom::blink::SessionStorageNamespace> namespace_{nullptr};
HashMap<scoped_refptr<const SecurityOrigin>,
scoped_refptr<CachedStorageArea>,
diff --git a/chromium/third_party/blink/renderer/modules/eyedropper/idls.gni b/chromium/third_party/blink/renderer/modules/subapps/BUILD.gn
index 96c64c9aeea..3aaddf4fd87 100644
--- a/chromium/third_party/blink/renderer/modules/eyedropper/idls.gni
+++ b/chromium/third_party/blink/renderer/modules/subapps/BUILD.gn
@@ -2,9 +2,11 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-modules_idl_files = [
- "color_select_event.idl",
- "eye_dropper.idl",
-]
+import("//third_party/blink/renderer/modules/modules.gni")
-modules_dictionary_idl_files = [ "color_select_event_init.idl" ]
+blink_modules_sources("subapps") {
+ sources = [
+ "sub_apps.cc",
+ "sub_apps.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/subapps/DIR_METADATA b/chromium/third_party/blink/renderer/modules/subapps/DIR_METADATA
new file mode 100644
index 00000000000..7f1ffb86b99
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/subapps/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "UI>Browser>WebAppInstalls>Desktop"
+}
diff --git a/chromium/third_party/blink/renderer/modules/subapps/OWNERS b/chromium/third_party/blink/renderer/modules/subapps/OWNERS
new file mode 100644
index 00000000000..ec8bc8b356d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/subapps/OWNERS
@@ -0,0 +1,3 @@
+file://chrome/browser/web_applications/OWNERS
+
+isandrk@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/subapps/navigator_sub_apps.idl b/chromium/third_party/blink/renderer/modules/subapps/navigator_sub_apps.idl
new file mode 100644
index 00000000000..e92d6390135
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/subapps/navigator_sub_apps.idl
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/ivansandrk/multi-apps/blob/main/explainer.md
+
+[
+ Exposed=(Window,Worker),
+ SecureContext,
+ ImplementedAs=SubApps
+] partial interface Navigator {
+ [SameObject, RuntimeEnabled=DesktopPWAsSubApps] readonly attribute SubApps subApps;
+};
diff --git a/chromium/third_party/blink/renderer/modules/subapps/sub_apps.cc b/chromium/third_party/blink/renderer/modules/subapps/sub_apps.cc
new file mode 100644
index 00000000000..0416bfdcc7a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/subapps/sub_apps.cc
@@ -0,0 +1,109 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/subapps/sub_apps.h"
+
+#include <utility>
+
+#include "base/check.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/subapps/sub_apps_provider.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/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/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+namespace {
+
+String SubAppsProviderResultToString(
+ mojom::blink::SubAppsProviderResult value) {
+ switch (value) {
+ case mojom::blink::SubAppsProviderResult::kSuccess:
+ return "success";
+ case mojom::blink::SubAppsProviderResult::kFailure:
+ return "failure";
+ }
+}
+
+// We get called back from the SubAppsProvider mojo service (inside the browser
+// process), pass on the result to the calling context.
+void OnAddSubApp(ScriptPromiseResolver* resolver,
+ mojo::Remote<mojom::blink::SubAppsProvider> /* ignored */,
+ mojom::blink::SubAppsProviderResult result) {
+ if (result == mojom::blink::SubAppsProviderResult::kSuccess) {
+ resolver->Resolve(SubAppsProviderResultToString(result));
+ } else {
+ resolver->Reject(SubAppsProviderResultToString(result));
+ }
+}
+
+} // namespace
+
+// static
+const char SubApps::kSupplementName[] = "SubApps";
+
+SubApps::SubApps(Navigator& navigator) : Supplement<Navigator>(navigator) {}
+
+// static
+SubApps* SubApps::subApps(Navigator& navigator) {
+ SubApps* subapps = Supplement<Navigator>::From<SubApps>(navigator);
+ if (!subapps) {
+ subapps = MakeGarbageCollected<SubApps>(navigator);
+ ProvideTo(navigator, subapps);
+ }
+ return subapps;
+}
+
+void SubApps::Trace(Visitor* visitor) const {
+ ScriptWrappable::Trace(visitor);
+ Supplement<Navigator>::Trace(visitor);
+}
+
+ScriptPromise SubApps::add(ScriptState* script_state,
+ const String& install_url) {
+ Navigator* const navigator = GetSupplementable();
+ // [SecureContext] from the IDL ensures this.
+ DCHECK(ExecutionContext::From(script_state)->IsSecureContext());
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+
+ if (!navigator->DomWindow()) {
+ auto* exception = MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "The object is no longer associated to a document.");
+ resolver->Reject(exception);
+ return resolver->Promise();
+ }
+
+ if (!navigator->DomWindow()->GetFrame()->IsMainFrame()) {
+ auto* exception = MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "API is only supported in top-level browsing contexts.");
+ resolver->Reject(exception);
+ return resolver->Promise();
+ }
+
+ mojo::Remote<mojom::blink::SubAppsProvider> provider;
+ ExecutionContext::From(script_state)
+ ->GetBrowserInterfaceBroker()
+ .GetInterface(provider.BindNewPipeAndPassReceiver());
+
+ auto* raw_provider = provider.get();
+ // TODO(isandrk, 1171317): Skeleton implementation which doesn't pass
+ // |install_url| for now.
+ raw_provider->Add(
+ WTF::Bind(&OnAddSubApp, WrapPersistent(resolver), std::move(provider)));
+
+ return resolver->Promise();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/subapps/sub_apps.h b/chromium/third_party/blink/renderer/modules/subapps/sub_apps.h
new file mode 100644
index 00000000000..457f37aba8b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/subapps/sub_apps.h
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SUBAPPS_SUB_APPS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SUBAPPS_SUB_APPS_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class Navigator;
+class ScriptPromise;
+class ScriptState;
+
+class SubApps : public ScriptWrappable, public Supplement<Navigator> {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static const char kSupplementName[];
+ static SubApps* subApps(Navigator&);
+
+ explicit SubApps(Navigator&);
+ SubApps(const SubApps&) = delete;
+ SubApps& operator=(const SubApps&) = delete;
+
+ // ScriptWrappable.
+ void Trace(Visitor*) const override;
+
+ // SubApps API.
+ ScriptPromise add(ScriptState*, const String&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SUBAPPS_SUB_APPS_H_
diff --git a/chromium/third_party/blink/renderer/modules/subapps/sub_apps.idl b/chromium/third_party/blink/renderer/modules/subapps/sub_apps.idl
new file mode 100644
index 00000000000..cb7fb8f964d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/subapps/sub_apps.idl
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/ivansandrk/multi-apps/blob/main/explainer.md
+
+enum SubAppsError {
+ "success",
+ "failure",
+};
+
+[
+ SecureContext
+] interface SubApps {
+ [CallWith=ScriptState] Promise<SubAppsError> add(DOMString install_url);
+};
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/BUILD.gn b/chromium/third_party/blink/renderer/modules/url_pattern/BUILD.gn
index 6bc2956e0c0..dd47096a003 100644
--- a/chromium/third_party/blink/renderer/modules/url_pattern/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/BUILD.gn
@@ -2,12 +2,19 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("url_pattern") {
sources = [
"url_pattern.cc",
"url_pattern.h",
+ "url_pattern_canon.cc",
+ "url_pattern_canon.h",
+ "url_pattern_component.cc",
+ "url_pattern_component.h",
+ "url_pattern_parser.cc",
+ "url_pattern_parser.h",
]
public_deps = [
@@ -15,3 +22,14 @@ blink_modules_sources("url_pattern") {
"//third_party/liburlpattern",
]
}
+
+if (use_libfuzzer) {
+ fuzzer_test("url_pattern_fuzzer") {
+ sources = [ "url_pattern_fuzzer.cc" ]
+ deps = [
+ "//third_party/blink/renderer/modules:modules",
+ "//third_party/blink/renderer/platform:blink_fuzzer_test_support",
+ ]
+ seed_corpus = "fuzzer_seed_corpus"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/DEPS b/chromium/third_party/blink/renderer/modules/url_pattern/DEPS
index f5a16143eb0..35dd35a70ba 100644
--- a/chromium/third_party/blink/renderer/modules/url_pattern/DEPS
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/DEPS
@@ -5,4 +5,6 @@
include_rules = [
"+base/strings/string_util.h",
"+third_party/liburlpattern",
+ "+url/url_canon.h",
+ "+url/url_util.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/2dcf128c70be5016986fa5965a89eb839fd6cc3c b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/2dcf128c70be5016986fa5965a89eb839fd6cc3c
new file mode 100644
index 00000000000..6d1f1cad6fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/2dcf128c70be5016986fa5965a89eb839fd6cc3c
@@ -0,0 +1 @@
+https://example.com/count/([0-9]+)
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/345433f6443349a932caefebc1754a7da500a885 b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/345433f6443349a932caefebc1754a7da500a885
new file mode 100644
index 00000000000..9388cc3a9d0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/345433f6443349a932caefebc1754a7da500a885
@@ -0,0 +1 @@
+https://example.com/foo
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/43e53712d966badcd72516f9a9df30486173d8bc b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/43e53712d966badcd72516f9a9df30486173d8bc
new file mode 100644
index 00000000000..ee9ccfb46eb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/43e53712d966badcd72516f9a9df30486173d8bc
@@ -0,0 +1 @@
+https://example.com::port?/foo
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/4eba2aa9b6632b032ad9affab48eed570c3a7bec b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/4eba2aa9b6632b032ad9affab48eed570c3a7bec
new file mode 100644
index 00000000000..f71ae5546df
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/4eba2aa9b6632b032ad9affab48eed570c3a7bec
@@ -0,0 +1 @@
+https://:user::pass@example.com/foo
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/60aff90a381901bfbb4fd3d1753a5a8687842821 b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/60aff90a381901bfbb4fd3d1753a5a8687842821
new file mode 100644
index 00000000000..25978ff030a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/60aff90a381901bfbb4fd3d1753a5a8687842821
@@ -0,0 +1 @@
+https://example.com/:product
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/97cccba9cd38cd5138376093447ea6382a4df220 b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/97cccba9cd38cd5138376093447ea6382a4df220
new file mode 100644
index 00000000000..581fd125184
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/97cccba9cd38cd5138376093447ea6382a4df220
@@ -0,0 +1 @@
+http{s}?://example.com/foo
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/b0c2fea6b0fbc79ebcebf728cf1c76d4b3509121 b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/b0c2fea6b0fbc79ebcebf728cf1c76d4b3509121
new file mode 100644
index 00000000000..f9d3f896b75
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/b0c2fea6b0fbc79ebcebf728cf1c76d4b3509121
@@ -0,0 +1 @@
+https://example.com/count/:value([0-9]+)
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/d376eb4568f7c9ab01409838be90c31db1a9e755 b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/d376eb4568f7c9ab01409838be90c31db1a9e755
new file mode 100644
index 00000000000..db759a3cbf4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/d376eb4568f7c9ab01409838be90c31db1a9e755
@@ -0,0 +1 @@
+https://{:sub.}?example.com/:product?/index.html
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/dc9e31b18d4686a0f8dec64b5602d5a426ab0f44 b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/dc9e31b18d4686a0f8dec64b5602d5a426ab0f44
new file mode 100644
index 00000000000..f9354e7b6d0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/dc9e31b18d4686a0f8dec64b5602d5a426ab0f44
@@ -0,0 +1 @@
+https://example.com/foo?bar#baz
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/ecac354bd05b4e6328a498c43291ad2e129134fc b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/ecac354bd05b4e6328a498c43291ad2e129134fc
new file mode 100644
index 00000000000..7d615d8c3b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/fuzzer_seed_corpus/ecac354bd05b4e6328a498c43291ad2e129134fc
@@ -0,0 +1 @@
+https://{*.}example.com/foo
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/idls.gni b/chromium/third_party/blink/renderer/modules/url_pattern/idls.gni
deleted file mode 100644
index 9f0ad7e912f..00000000000
--- a/chromium/third_party/blink/renderer/modules/url_pattern/idls.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "url_pattern.idl" ]
-
-modules_dictionary_idl_files = [
- "url_pattern_component_result.idl",
- "url_pattern_init.idl",
- "url_pattern_result.idl",
-]
-
-modules_dependency_idl_files = []
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.cc b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.cc
index e0e2f943dfb..3abf9254028 100644
--- a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.cc
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.cc
@@ -6,10 +6,13 @@
#include "base/strings/string_util.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
-#include "third_party/blink/renderer/bindings/modules/v8/usv_string_or_url_pattern_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_urlpatterninit_usvstring.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_component_result.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_result.h"
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h"
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_component.h"
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_parser.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"
@@ -17,88 +20,15 @@
#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/liburlpattern/pattern.h"
+#include "third_party/liburlpattern/tokenize.h"
namespace blink {
-// A struct representing all the information needed to match a particular
-// component of a URL.
-class URLPattern::Component final
- : public GarbageCollected<URLPattern::Component> {
- public:
- bool Match(StringView input, Vector<String>* group_list) const {
- return regexp->Match(input, /*start_from=*/0, /*match_length=*/nullptr,
- group_list) == 0;
- }
-
- void Trace(Visitor* visitor) const { visitor->Trace(regexp); }
-
- // The parsed pattern.
- liburlpattern::Pattern pattern;
-
- // The pattern compiled down to a js regular expression.
- Member<ScriptRegexp> regexp;
-
- // The names to be applied to the regular expression capture groups. Note,
- // liburlpattern regular expressions do not use named capture groups directly.
- Vector<String> name_list;
-
- Component(liburlpattern::Pattern p, ScriptRegexp* r, Vector<String> n)
- : pattern(p), regexp(r), name_list(std::move(n)) {}
-};
+using url_pattern::Component;
+using url_pattern::ValueType;
namespace {
-// The default pattern string for components that are not specified in the
-// URLPattern constructor.
-const char* kDefaultPattern = "*";
-
-// The liburlpattern::Options to use for most component patterns. We
-// default to strict mode and case sensitivity. In addition, most
-// components have no concept of a delimiter or prefix character.
-const liburlpattern::Options& DefaultOptions() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(liburlpattern::Options, options,
- ({.delimiter_list = "",
- .prefix_list = "",
- .sensitive = true,
- .strict = true}));
- return options;
-}
-
-// The liburlpattern::Options to use for hostname patterns. This uses a
-// "." delimiter controlling how far a named group like ":bar" will match
-// by default. Note, hostnames are case insensitive but we require case
-// sensitivity here. This assumes that the hostname values have already
-// been normalized to lower case as in URL().
-const liburlpattern::Options& HostnameOptions() {
- DEFINE_STATIC_LOCAL(liburlpattern::Options, options,
- ({.delimiter_list = ".",
- .prefix_list = "",
- .sensitive = true,
- .strict = true}));
- return options;
-}
-
-// The liburlpattern::Options to use for pathname patterns. This uses a
-// "/" delimiter controlling how far a named group like ":bar" will match
-// by default. It also configures "/" to be treated as an automatic
-// prefix before groups.
-const liburlpattern::Options& PathnameOptions() {
- DEFINE_STATIC_LOCAL(liburlpattern::Options, options,
- ({.delimiter_list = "/",
- .prefix_list = "/",
- .sensitive = true,
- .strict = true}));
- return options;
-}
-
-// An enum indicating whether the associated component values be operated
-// on are for patterns or URLs. Validation and canonicalization will
-// do different things depending on the type.
-enum class ValueType {
- kPattern,
- kURL,
-};
-
// Utility function to determine if a pathname is absolute or not. For
// kURL values this mainly consists of a check for a leading slash. For
// patterns we do some additional checking for escaped or grouped slashes.
@@ -128,213 +58,6 @@ bool IsAbsolutePathname(const String& pathname, ValueType type) {
return false;
}
-String StringFromCanonOutput(const url::CanonOutput& output,
- const url::Component& component) {
- return String::FromUTF8(output.data() + component.begin, component.len);
-}
-
-std::string StdStringFromCanonOutput(const url::CanonOutput& output,
- const url::Component& component) {
- return std::string(output.data() + component.begin, component.len);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the protocol component.
-absl::StatusOr<std::string> ProtocolEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- bool result = url::CanonicalizeScheme(
- input.data(), url::Component(0, static_cast<int>(input.size())),
- &canon_output, &component);
-
- if (!result) {
- return absl::InvalidArgumentError("Invalid protocol '" +
- std::string(input) + "'.");
- }
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// Utility function to canonicalize a protocol string. Throws an exception
-// if the input is invalid. The canonicalization and/or validation will
-// differ depending on whether |type| is kURL or kPattern.
-String CanonicalizeProtocol(const String& input,
- ValueType type,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- return input;
- }
-
- bool result = false;
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
- if (input.Is8Bit()) {
- StringUTF8Adaptor utf8(input);
- result = url::CanonicalizeScheme(
- utf8.data(), url::Component(0, utf8.size()), &canon_output, &component);
- } else {
- result = url::CanonicalizeScheme(input.Characters16(),
- url::Component(0, input.length()),
- &canon_output, &component);
- }
-
- if (!result) {
- exception_state.ThrowTypeError("Invalid protocol '" + input + "'.");
- return String();
- }
-
- return StringFromCanonOutput(canon_output, component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the username component.
-absl::StatusOr<std::string> UsernameEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component username_component;
- url::Component password_component;
-
- bool result = url::CanonicalizeUserInfo(
- input.data(), url::Component(0, static_cast<int>(input.size())), "",
- url::Component(0, 0), &canon_output, &username_component,
- &password_component);
-
- if (!result) {
- return absl::InvalidArgumentError("Invalid username pattern '" +
- std::string(input) + "'.");
- }
-
- return StdStringFromCanonOutput(canon_output, username_component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the password component.
-absl::StatusOr<std::string> PasswordEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component username_component;
- url::Component password_component;
-
- bool result = url::CanonicalizeUserInfo(
- "", url::Component(0, 0), input.data(),
- url::Component(0, static_cast<int>(input.size())), &canon_output,
- &username_component, &password_component);
-
- if (!result) {
- return absl::InvalidArgumentError("Invalid password pattern '" +
- std::string(input) + "'.");
- }
-
- return StdStringFromCanonOutput(canon_output, password_component);
-}
-
-// Utility function to canonicalize username and/or password strings. Throws
-// an exception if either is invalid. The canonicalization and/or validation
-// will differ depending on whether |type| is kURL or kPattern. On success
-// |username_out| and |password_out| will contain the canonical values.
-void CanonicalizeUsernameAndPassword(const String& username,
- const String& password,
- ValueType type,
- String& username_out,
- String& password_out,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- username_out = username;
- password_out = password;
- return;
- }
-
- bool result = false;
- url::RawCanonOutputT<char> canon_output;
- url::Component username_component;
- url::Component password_component;
-
- if (username && password && username.Is8Bit() && password.Is8Bit()) {
- StringUTF8Adaptor username_utf8(username);
- StringUTF8Adaptor password_utf8(password);
- result = url::CanonicalizeUserInfo(
- username_utf8.data(), url::Component(0, username_utf8.size()),
- password_utf8.data(), url::Component(0, password_utf8.size()),
- &canon_output, &username_component, &password_component);
-
- } else {
- String username16(username);
- String password16(password);
- username16.Ensure16Bit();
- password16.Ensure16Bit();
- result = url::CanonicalizeUserInfo(
- username16.Characters16(), url::Component(0, username16.length()),
- password16.Characters16(), url::Component(0, password16.length()),
- &canon_output, &username_component, &password_component);
- }
-
- if (!result) {
- exception_state.ThrowTypeError("Invalid username '" + username +
- "' and/or password '" + password + "'.");
- return;
- }
-
- if (username_component.len != -1)
- username_out = StringFromCanonOutput(canon_output, username_component);
- if (password_component.len != -1)
- password_out = StringFromCanonOutput(canon_output, password_component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the hostname component.
-absl::StatusOr<std::string> HostnameEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- bool result = url::CanonicalizeHost(
- input.data(), url::Component(0, static_cast<int>(input.size())),
- &canon_output, &component);
-
- if (!result) {
- return absl::InvalidArgumentError("Invalid hostname pattern '" +
- std::string(input) + "'.");
- }
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// Utility function to canonicalize a hostname string. Throws an exception
-// if the input is invalid. The canonicalization and/or validation will
-// differ depending on whether |type| is kURL or kPattern.
-String CanonicalizeHostname(const String& input,
- ValueType type,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- return input;
- }
-
- bool success = false;
- String result = SecurityOrigin::CanonicalizeHost(input, &success);
- if (!success) {
- exception_state.ThrowTypeError("Invalid hostname '" + input + "'.");
- return String();
- }
-
- return result;
-}
-
// Utility function to determine if the default port for the given protocol
// matches the given port number.
bool IsProtocolDefaultPort(const String& protocol, const String& port) {
@@ -353,260 +76,6 @@ bool IsProtocolDefaultPort(const String& protocol, const String& port) {
return default_port != url::PORT_UNSPECIFIED && default_port == port_number;
}
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the port component.
-absl::StatusOr<std::string> PortEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- bool result = url::CanonicalizePort(
- input.data(), url::Component(0, static_cast<int>(input.size())),
- url::PORT_UNSPECIFIED, &canon_output, &component);
-
- if (!result) {
- return absl::InvalidArgumentError("Invalid port pattern '" +
- std::string(input) + "'.");
- }
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// Utility function to canonicalize a port string. Throws an exception
-// if the input is invalid. The canonicalization and/or validation will
-// differ depending on whether |type| is kURL or kPattern. The |protocol|
-// must be provided in order to handle default ports correctly.
-String CanonicalizePort(const String& input,
- ValueType type,
- const String& protocol,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- return input;
- }
-
- int default_port = url::PORT_UNSPECIFIED;
- if (!input.IsEmpty()) {
- StringUTF8Adaptor protocol_utf8(protocol);
- default_port =
- url::DefaultPortForScheme(protocol_utf8.data(), protocol_utf8.size());
- }
-
- // Since ports only consist of digits there should be no encoding needed.
- // Therefore we directly use the UTF8 encoding version of CanonicalizePort().
- StringUTF8Adaptor utf8(input);
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
- if (!url::CanonicalizePort(utf8.data(), url::Component(0, utf8.size()),
- default_port, &canon_output, &component)) {
- exception_state.ThrowTypeError("Invalid port '" + input + "'.");
- return String();
- }
-
- return component.len == -1 ? g_empty_string
- : StringFromCanonOutput(canon_output, component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the pathname component using "standard" URL
-// behavior.
-absl::StatusOr<std::string> StandardURLPathnameEncodeCallback(
- absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- bool result = url::CanonicalizePartialPath(
- input.data(), url::Component(0, static_cast<int>(input.size())),
- &canon_output, &component);
-
- if (!result) {
- return absl::InvalidArgumentError("Invalid pathname pattern '" +
- std::string(input) + "'.");
- }
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the pathname component using "path" URL
-// behavior. This is like "cannot-be-a-base" URL behavior in the spec.
-absl::StatusOr<std::string> PathURLPathnameEncodeCallback(
- absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- url::CanonicalizePathURLPath(
- input.data(), url::Component(0, static_cast<int>(input.size())),
- &canon_output, &component);
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// Utility function to canonicalize a pathname string. Throws an exception
-// if the input is invalid. The canonicalization and/or validation will
-// differ depending on whether |type| is kURL or kPattern.
-String CanonicalizePathname(const String& protocol,
- const String& input,
- ValueType type,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- return input;
- }
-
- // Determine if we are using "standard" or "path" URL canonicalization
- // for the pathname. In spec terms the "path" URL behavior corresponds
- // to "cannot-be-a-base" URLs. We make this determination based on the
- // protocol string since we cannot look at the number of slashes between
- // components like the URL spec. If this is inadequate the developer
- // can use the baseURL property to get more strict URL behavior.
- //
- // We default to "standard" URL behavior to match how the empty protocol
- // string in the URLPattern constructor results in the pathname pattern
- // getting "standard" URL canonicalization.
- bool standard = false;
- if (protocol.IsEmpty()) {
- standard = true;
- } else if (protocol.Is8Bit()) {
- StringUTF8Adaptor utf8(protocol);
- standard = url::IsStandard(utf8.data(), url::Component(0, utf8.size()));
- } else {
- standard = url::IsStandard(protocol.Characters16(),
- url::Component(0, protocol.length()));
- }
-
- // Do not enforce absolute pathnames here since we can't enforce it
- // it consistently in the URLPattern constructor. This allows us to
- // produce a match when the exact same fixed pathname string is passed
- // to both the constructor and test()/exec(). Similarly, we use
- // url::CanonicalizePartialPath() below instead of url::CanonicalizePath()
- // to avoid pre-pending a slash at the start of the string.
-
- bool result = false;
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- const auto canonicalize_path = [&](const auto* data, int length) {
- if (standard) {
- return url::CanonicalizePartialPath(data, url::Component(0, length),
- &canon_output, &component);
- }
- url::CanonicalizePathURLPath(data, url::Component(0, length), &canon_output,
- &component);
- return true;
- };
-
- if (input.Is8Bit()) {
- StringUTF8Adaptor utf8(input);
- result = canonicalize_path(utf8.data(), utf8.size());
- } else {
- result = canonicalize_path(input.Characters16(), input.length());
- }
-
- if (!result) {
- exception_state.ThrowTypeError("Invalid pathname '" + input + "'.");
- return String();
- }
-
- return StringFromCanonOutput(canon_output, component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the search component.
-absl::StatusOr<std::string> SearchEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- url::CanonicalizeQuery(input.data(),
- url::Component(0, static_cast<int>(input.size())),
- /*converter=*/nullptr, &canon_output, &component);
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// Utility function to canonicalize a search string. Throws an exception
-// if the input is invalid. The canonicalization and/or validation will
-// differ depending on whether |type| is kURL or kPattern.
-String CanonicalizeSearch(const String& input,
- ValueType type,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- return input;
- }
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
- if (input.Is8Bit()) {
- StringUTF8Adaptor utf8(input);
- url::CanonicalizeQuery(utf8.data(), url::Component(0, utf8.size()),
- /*converter=*/nullptr, &canon_output, &component);
- } else {
- url::CanonicalizeQuery(input.Characters16(),
- url::Component(0, input.length()),
- /*converter=*/nullptr, &canon_output, &component);
- }
-
- return StringFromCanonOutput(canon_output, component);
-}
-
-// A callback to be passed to the liburlpattern::Parse() method that performs
-// validation and encoding for the hash component.
-absl::StatusOr<std::string> HashEncodeCallback(absl::string_view input) {
- if (input.empty())
- return std::string();
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
-
- url::CanonicalizeRef(input.data(),
- url::Component(0, static_cast<int>(input.size())),
- &canon_output, &component);
-
- return StdStringFromCanonOutput(canon_output, component);
-}
-
-// Utility function to canonicalize a hash string. Throws an exception
-// if the input is invalid. The canonicalization and/or validation will
-// differ depending on whether |type| is kURL or kPattern.
-String CanonicalizeHash(const String& input,
- ValueType type,
- ExceptionState& exception_state) {
- if (type == ValueType::kPattern) {
- // Canonicalization for patterns is handled during compilation via
- // encoding callbacks.
- return input;
- }
-
- url::RawCanonOutputT<char> canon_output;
- url::Component component;
- if (input.Is8Bit()) {
- StringUTF8Adaptor utf8(input);
- url::CanonicalizeRef(utf8.data(), url::Component(0, utf8.size()),
- &canon_output, &component);
- } else {
- url::CanonicalizeRef(input.Characters16(),
- url::Component(0, input.length()), &canon_output,
- &component);
- }
-
- return StringFromCanonOutput(canon_output, component);
-}
-
// A utility method that takes a URLPatternInit, splits it apart, and applies
// the individual component values in the given set of strings. The strings
// are only applied if a value is present in the init structure.
@@ -643,33 +112,37 @@ void ApplyInit(const URLPatternInit* init,
port =
base_url.Port() > 0 ? String::Number(base_url.Port()) : g_empty_string;
pathname = base_url.GetPath() ? base_url.GetPath() : g_empty_string;
-
- // Do no propagate search or hash from the base URL. This matches the
- // behavior when resolving a relative URL against a base URL.
+ search = base_url.Query() ? base_url.Query() : g_empty_string;
+ hash = base_url.HasFragmentIdentifier() ? base_url.FragmentIdentifier()
+ : g_empty_string;
}
// Apply the URLPatternInit component values on top of the default and
// baseURL values.
if (init->hasProtocol()) {
- protocol = CanonicalizeProtocol(init->protocol(), type, exception_state);
+ protocol = url_pattern::CanonicalizeProtocol(init->protocol(), type,
+ exception_state);
if (exception_state.HadException())
return;
}
if (init->hasUsername() || init->hasPassword()) {
String init_username = init->hasUsername() ? init->username() : String();
String init_password = init->hasPassword() ? init->password() : String();
- CanonicalizeUsernameAndPassword(init_username, init_password, type,
- username, password, exception_state);
+ url_pattern::CanonicalizeUsernameAndPassword(init_username, init_password,
+ type, username, password,
+ exception_state);
if (exception_state.HadException())
return;
}
if (init->hasHostname()) {
- hostname = CanonicalizeHostname(init->hostname(), type, exception_state);
+ hostname = url_pattern::CanonicalizeHostname(init->hostname(), type,
+ exception_state);
if (exception_state.HadException())
return;
}
if (init->hasPort()) {
- port = CanonicalizePort(init->port(), type, protocol, exception_state);
+ port = url_pattern::CanonicalizePort(init->port(), type, protocol,
+ exception_state);
if (exception_state.HadException())
return;
}
@@ -689,17 +162,19 @@ void ApplyInit(const URLPatternInit* init,
pathname = base_url.GetPath().Substring(0, slash_index + 1) + pathname;
}
}
- pathname = CanonicalizePathname(protocol, pathname, type, exception_state);
+ pathname = url_pattern::CanonicalizePathname(protocol, pathname, type,
+ exception_state);
if (exception_state.HadException())
return;
}
if (init->hasSearch()) {
- search = CanonicalizeSearch(init->search(), type, exception_state);
+ search =
+ url_pattern::CanonicalizeSearch(init->search(), type, exception_state);
if (exception_state.HadException())
return;
}
if (init->hasHash()) {
- hash = CanonicalizeHash(init->hash(), type, exception_state);
+ hash = url_pattern::CanonicalizeHash(init->hash(), type, exception_state);
if (exception_state.HadException())
return;
}
@@ -707,7 +182,52 @@ void ApplyInit(const URLPatternInit* init,
} // namespace
+URLPattern* URLPattern::Create(const V8URLPatternInput* input,
+ const String& base_url,
+ ExceptionState& exception_state) {
+ if (input->GetContentType() ==
+ V8URLPatternInput::ContentType::kURLPatternInit) {
+ exception_state.ThrowTypeError(
+ "Invalid second argument baseURL '" + base_url +
+ "' provided with a URLPatternInit input. Use the "
+ "URLPatternInit.baseURL property instead.");
+ return nullptr;
+ }
+
+ const auto& input_string = input->GetAsUSVString();
+
+ url_pattern::Parser parser(input_string);
+ parser.Parse(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+
+ URLPatternInit* init = parser.GetResult();
+ if (!base_url && !init->hasProtocol()) {
+ exception_state.ThrowTypeError(
+ "Relative constructor string '" + input_string +
+ "' must have a base URL passed as the second argument.");
+ return nullptr;
+ }
+
+ if (base_url)
+ init->setBaseURL(base_url);
+
+ return Create(init, parser.GetProtocolComponent(), exception_state);
+}
+
+URLPattern* URLPattern::Create(const V8URLPatternInput* input,
+ ExceptionState& exception_state) {
+ if (input->IsURLPatternInit()) {
+ return URLPattern::Create(input->GetAsURLPatternInit(),
+ /*precomputed_protocol_component=*/nullptr,
+ exception_state);
+ }
+
+ return Create(input, /*base_url=*/String(), exception_state);
+}
+
URLPattern* URLPattern::Create(const URLPatternInit* init,
+ Component* precomputed_protocol_component,
ExceptionState& exception_state) {
// Each component defaults to a wildcard matching any input. We use
// the null string as a shorthand for the default.
@@ -734,80 +254,54 @@ URLPattern* URLPattern::Create(const URLPatternInit* init,
if (IsProtocolDefaultPort(protocol, port))
port = "";
- // Compile each component pattern into a Component structure that can
- // be used for matching. Components that match any input may have a
- // nullptr Component struct pointer.
+ // Compile each component pattern into a Component structure that
+ // can be used for matching.
- auto* protocol_component =
- CompilePattern(protocol, "protocol", ProtocolEncodeCallback,
- DefaultOptions(), exception_state);
+ auto* protocol_component = precomputed_protocol_component;
+ if (!protocol_component) {
+ protocol_component =
+ Component::Compile(protocol, Component::Type::kProtocol,
+ /*protocol_component=*/nullptr, exception_state);
+ }
if (exception_state.HadException())
return nullptr;
auto* username_component =
- CompilePattern(username, "username", UsernameEncodeCallback,
- DefaultOptions(), exception_state);
+ Component::Compile(username, Component::Type::kUsername,
+ protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
auto* password_component =
- CompilePattern(password, "password", PasswordEncodeCallback,
- DefaultOptions(), exception_state);
+ Component::Compile(password, Component::Type::kPassword,
+ protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
auto* hostname_component =
- CompilePattern(hostname, "hostname", HostnameEncodeCallback,
- HostnameOptions(), exception_state);
+ Component::Compile(hostname, Component::Type::kHostname,
+ protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
- auto* port_component = CompilePattern(port, "port", PortEncodeCallback,
- DefaultOptions(), exception_state);
+ auto* port_component = Component::Compile(
+ port, Component::Type::kPort, protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
- // Different types of URLs use different canonicalization for pathname.
- // A "standard" URL flattens `.`/`..` and performs full percent encoding.
- // A "path" URL does not flatten and uses a more lax percent encoding.
- // The spec calls "path" URLs as "cannot-be-a-base-URL" URLs:
- //
- // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
- //
- // We prefer "standard" URL here by checking to see if the protocol
- // pattern matches any of the known standard protocol strings. So
- // an exact pattern of `http` will match, but so will `http{s}?` and
- // `*`.
- //
- // If the protocol pattern does not match any of the known standard URL
- // protocols then we fall back to the "path" URL behavior. This will
- // normally be triggered by `data`, `javascript`, `about`, etc. It
- // will also be triggered for custom protocol strings. We favor "path"
- // behavior here because its better to under canonicalize since the
- // developer can always manually canonicalize the pathname for a custom
- // protocol.
- //
- // ShouldTreatAsStandardURL can by a bit expensive, so only do it if we
- // actually have a pathname pattern to compile.
- liburlpattern::EncodeCallback pathname_encode = PathURLPathnameEncodeCallback;
- if (!pathname.IsNull() && ShouldTreatAsStandardURL(protocol_component)) {
- pathname_encode = StandardURLPathnameEncodeCallback;
- }
-
auto* pathname_component =
- CompilePattern(pathname, "pathname", pathname_encode, PathnameOptions(),
- exception_state);
+ Component::Compile(pathname, Component::Type::kPathname,
+ protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
- auto* search_component =
- CompilePattern(search, "search", SearchEncodeCallback, DefaultOptions(),
- exception_state);
+ auto* search_component = Component::Compile(
+ search, Component::Type::kSearch, protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
- auto* hash_component = CompilePattern(hash, "hash", HashEncodeCallback,
- DefaultOptions(), exception_state);
+ auto* hash_component = Component::Compile(
+ hash, Component::Type::kHash, protocol_component, exception_state);
if (exception_state.HadException())
return nullptr;
@@ -836,32 +330,20 @@ URLPattern::URLPattern(Component* protocol,
hash_(hash) {}
bool URLPattern::test(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8URLPatternInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const USVStringOrURLPatternInit& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& base_url,
ExceptionState& exception_state) const {
return Match(input, base_url, /*result=*/nullptr, exception_state);
}
bool URLPattern::test(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8URLPatternInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const USVStringOrURLPatternInit& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) const {
return test(input, /*base_url=*/String(), exception_state);
}
URLPatternResult* URLPattern::exec(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8URLPatternInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const USVStringOrURLPatternInit& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& base_url,
ExceptionState& exception_state) const {
URLPatternResult* result = URLPatternResult::Create();
@@ -871,69 +353,71 @@ URLPatternResult* URLPattern::exec(
}
URLPatternResult* URLPattern::exec(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8URLPatternInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const USVStringOrURLPatternInit& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) const {
return exec(input, /*base_url=*/String(), exception_state);
}
String URLPattern::protocol() const {
- if (!protocol_)
- return kDefaultPattern;
- std::string result = protocol_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return protocol_->GeneratePatternString();
}
String URLPattern::username() const {
- if (!username_)
- return kDefaultPattern;
- std::string result = username_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return username_->GeneratePatternString();
}
String URLPattern::password() const {
- if (!password_)
- return kDefaultPattern;
- std::string result = password_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return password_->GeneratePatternString();
}
String URLPattern::hostname() const {
- if (!hostname_)
- return kDefaultPattern;
- std::string result = hostname_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return hostname_->GeneratePatternString();
}
String URLPattern::port() const {
- if (!port_)
- return kDefaultPattern;
- std::string result = port_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return port_->GeneratePatternString();
}
String URLPattern::pathname() const {
- if (!pathname_)
- return kDefaultPattern;
- std::string result = pathname_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return pathname_->GeneratePatternString();
}
String URLPattern::search() const {
- if (!search_)
- return kDefaultPattern;
- std::string result = search_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return search_->GeneratePatternString();
}
String URLPattern::hash() const {
- if (!hash_)
- return kDefaultPattern;
- std::string result = hash_->pattern.GeneratePatternString();
- return String::FromUTF8(result);
+ return hash_->GeneratePatternString();
+}
+
+// static
+int URLPattern::compareComponent(const V8URLPatternComponent& component,
+ const URLPattern* left,
+ const URLPattern* right) {
+ switch (component.AsEnum()) {
+ case V8URLPatternComponent::Enum::kProtocol:
+ return url_pattern::Component::Compare(*left->protocol_,
+ *right->protocol_);
+ case V8URLPatternComponent::Enum::kUsername:
+ return url_pattern::Component::Compare(*left->username_,
+ *right->username_);
+ case V8URLPatternComponent::Enum::kPassword:
+ return url_pattern::Component::Compare(*left->password_,
+ *right->password_);
+ case V8URLPatternComponent::Enum::kHostname:
+ return url_pattern::Component::Compare(*left->hostname_,
+ *right->hostname_);
+ case V8URLPatternComponent::Enum::kPort:
+ return url_pattern::Component::Compare(*left->port_, *right->port_);
+ case V8URLPatternComponent::Enum::kPathname:
+ return url_pattern::Component::Compare(*left->pathname_,
+ *right->pathname_);
+ case V8URLPatternComponent::Enum::kSearch:
+ return url_pattern::Component::Compare(*left->search_, *right->search_);
+ case V8URLPatternComponent::Enum::kHash:
+ return url_pattern::Component::Compare(*left->hash_, *right->hash_);
+ }
+ NOTREACHED();
}
void URLPattern::Trace(Visitor* visitor) const {
@@ -948,87 +432,8 @@ void URLPattern::Trace(Visitor* visitor) const {
ScriptWrappable::Trace(visitor);
}
-// static
-URLPattern::Component* URLPattern::CompilePattern(
- const String& pattern,
- StringView component,
- liburlpattern::EncodeCallback encode_callback,
- const liburlpattern::Options& options,
- ExceptionState& exception_state) {
- // If the pattern is null then optimize by not compiling a pattern. Instead,
- // a nullptr Component is interpreted as matching any input value.
- if (pattern.IsNull())
- return nullptr;
-
- // Parse the pattern.
- StringUTF8Adaptor utf8(pattern);
- auto parse_result =
- liburlpattern::Parse(absl::string_view(utf8.data(), utf8.size()),
- std::move(encode_callback), options);
- if (!parse_result.ok()) {
- exception_state.ThrowTypeError("Invalid " + component + " pattern '" +
- pattern + "'.");
- return nullptr;
- }
-
- // Extract a regular expression string from the parsed pattern.
- std::vector<std::string> name_list;
- std::string regexp_string =
- parse_result.value().GenerateRegexString(&name_list);
-
- // Compile the regular expression to verify it is valid.
- auto case_sensitive = options.sensitive ? WTF::kTextCaseSensitive
- : WTF::kTextCaseASCIIInsensitive;
- DCHECK(base::IsStringASCII(regexp_string));
- ScriptRegexp* regexp = MakeGarbageCollected<ScriptRegexp>(
- String(regexp_string.data(), regexp_string.size()), case_sensitive,
- kMultilineDisabled, ScriptRegexp::UTF16);
- if (!regexp->IsValid()) {
- // The regular expression failed to compile. This means that some
- // custom regexp group within the pattern is illegal. Attempt to
- // compile each regexp group individually in order to identify the
- // culprit.
- for (auto& part : parse_result.value().PartList()) {
- if (part.type != liburlpattern::PartType::kRegex)
- continue;
- DCHECK(base::IsStringASCII(part.value));
- String group_value(part.value.data(), part.value.size());
- regexp = MakeGarbageCollected<ScriptRegexp>(
- group_value, case_sensitive, kMultilineDisabled, ScriptRegexp::UTF16);
- if (regexp->IsValid())
- continue;
- exception_state.ThrowTypeError("Invalid " + component + " pattern '" +
- pattern +
- "'. Custom regular expression group '" +
- group_value + "' is invalid.");
- return nullptr;
- }
- // We couldn't find a bad regexp group, but we still have an overall
- // error. This shouldn't happen, but we handle it anyway.
- exception_state.ThrowTypeError("Invalid " + component + " pattern '" +
- pattern +
- "'. An unexpected error has occurred.");
- return nullptr;
- }
-
- Vector<String> wtf_name_list;
- wtf_name_list.ReserveInitialCapacity(
- static_cast<wtf_size_t>(name_list.size()));
- for (const auto& name : name_list) {
- wtf_name_list.push_back(String::FromUTF8(name.data(), name.size()));
- }
-
- return MakeGarbageCollected<URLPattern::Component>(
- std::move(parse_result.value()), std::move(regexp),
- std::move(wtf_name_list));
-}
-
bool URLPattern::Match(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8URLPatternInput* input,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const USVStringOrURLPatternInit& input,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const String& base_url,
URLPatternResult* result,
ExceptionState& exception_state) const {
@@ -1043,84 +448,71 @@ bool URLPattern::Match(
String search(g_empty_string);
String hash(g_empty_string);
- HeapVector<USVStringOrURLPatternInit> inputs;
-
- bool is_init =
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- input->GetContentType() ==
- V8URLPatternInput::ContentType::kURLPatternInit;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- input.IsURLPatternInit();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- if (is_init) {
- if (base_url) {
- exception_state.ThrowTypeError(
- "Invalid second argument baseURL '" + base_url +
- "' provided with a URLPatternInit input. Use the "
- "URLPatternInit.baseURL property instead.");
- return false;
- }
+ HeapVector<Member<V8URLPatternInput>> inputs;
- URLPatternInit* init =
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- input->GetAsURLPatternInit();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- input.GetAsURLPatternInit();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- inputs.push_back(USVStringOrURLPatternInit::FromURLPatternInit(init));
-
- // Layer the URLPatternInit values on top of the default empty strings.
- ApplyInit(init, ValueType::kURL, protocol, username, password, hostname,
- port, pathname, search, hash, exception_state);
- if (exception_state.HadException()) {
- // Treat exceptions simply as a failure to match.
- exception_state.ClearException();
- return false;
- }
- } else {
- KURL parsed_base_url(base_url);
- if (base_url && !parsed_base_url.IsValid()) {
- // Treat as failure to match, but don't throw an exception.
- return false;
- }
+ switch (input->GetContentType()) {
+ case V8URLPatternInput::ContentType::kURLPatternInit: {
+ if (base_url) {
+ exception_state.ThrowTypeError(
+ "Invalid second argument baseURL '" + base_url +
+ "' provided with a URLPatternInit input. Use the "
+ "URLPatternInit.baseURL property instead.");
+ return false;
+ }
+
+ URLPatternInit* init = input->GetAsURLPatternInit();
+
+ inputs.push_back(MakeGarbageCollected<V8URLPatternInput>(init));
- const String& input_string =
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- input->GetAsUSVString();
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- input.GetAsUSVString();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
- inputs.push_back(USVStringOrURLPatternInit::FromUSVString(input_string));
- if (base_url)
- inputs.push_back(USVStringOrURLPatternInit::FromUSVString(base_url));
-
- // The compile the input string as a fully resolved URL.
- KURL url(parsed_base_url, input_string);
- if (!url.IsValid() || url.IsEmpty()) {
- // Treat as failure to match, but don't throw an exception.
- return false;
+ // Layer the URLPatternInit values on top of the default empty strings.
+ ApplyInit(init, ValueType::kURL, protocol, username, password, hostname,
+ port, pathname, search, hash, exception_state);
+ if (exception_state.HadException()) {
+ // Treat exceptions simply as a failure to match.
+ exception_state.ClearException();
+ return false;
+ }
+ break;
}
+ case V8URLPatternInput::ContentType::kUSVString: {
+ KURL parsed_base_url(base_url);
+ if (base_url && !parsed_base_url.IsValid()) {
+ // Treat as failure to match, but don't throw an exception.
+ return false;
+ }
+
+ const String& input_string = input->GetAsUSVString();
- // Apply the parsed URL components on top of our defaults.
- if (url.Protocol())
- protocol = url.Protocol();
- if (url.User())
- username = url.User();
- if (url.Pass())
- password = url.Pass();
- if (url.Host())
- hostname = url.Host();
- if (url.Port() > 0)
- port = String::Number(url.Port());
- if (url.GetPath())
- pathname = url.GetPath();
- if (url.Query())
- search = url.Query();
- if (url.FragmentIdentifier())
- hash = url.FragmentIdentifier();
+ inputs.push_back(MakeGarbageCollected<V8URLPatternInput>(input_string));
+ if (base_url)
+ inputs.push_back(MakeGarbageCollected<V8URLPatternInput>(base_url));
+
+ // The compile the input string as a fully resolved URL.
+ KURL url(parsed_base_url, input_string);
+ if (!url.IsValid() || url.IsEmpty()) {
+ // Treat as failure to match, but don't throw an exception.
+ return false;
+ }
+
+ // Apply the parsed URL components on top of our defaults.
+ if (url.Protocol())
+ protocol = url.Protocol();
+ if (url.User())
+ username = url.User();
+ if (url.Pass())
+ password = url.Pass();
+ if (url.Host())
+ hostname = url.Host();
+ if (url.Port() > 0)
+ port = String::Number(url.Port());
+ if (url.GetPath())
+ pathname = url.GetPath();
+ if (url.Query())
+ search = url.Query();
+ if (url.FragmentIdentifier())
+ hash = url.FragmentIdentifier();
+ break;
+ }
}
Vector<String> protocol_group_list;
@@ -1143,18 +535,25 @@ bool URLPattern::Match(
auto* search_group_list_ref = result ? &search_group_list : nullptr;
auto* hash_group_list_ref = result ? &hash_group_list : nullptr;
+ CHECK(protocol_);
+ CHECK(username_);
+ CHECK(password_);
+ CHECK(hostname_);
+ CHECK(port_);
+ CHECK(pathname_);
+ CHECK(search_);
+ CHECK(hash_);
+
// Each component of the pattern must match the corresponding component of
- // the input. If a pattern Component is nullptr, then it matches any
- // input and we can avoid running a real regular expression match.
- bool matched =
- (!protocol_ || protocol_->Match(protocol, protocol_group_list_ref)) &&
- (!username_ || username_->Match(username, username_group_list_ref)) &&
- (!password_ || password_->Match(password, password_group_list_ref)) &&
- (!hostname_ || hostname_->Match(hostname, hostname_group_list_ref)) &&
- (!port_ || port_->Match(port, port_group_list_ref)) &&
- (!pathname_ || pathname_->Match(pathname, pathname_group_list_ref)) &&
- (!search_ || search_->Match(search, search_group_list_ref)) &&
- (!hash_ || hash_->Match(hash, hash_group_list_ref));
+ // the input.
+ bool matched = protocol_->Match(protocol, protocol_group_list_ref) &&
+ username_->Match(username, username_group_list_ref) &&
+ password_->Match(password, password_group_list_ref) &&
+ hostname_->Match(hostname, hostname_group_list_ref) &&
+ port_->Match(port, port_group_list_ref) &&
+ pathname_->Match(pathname, pathname_group_list_ref) &&
+ search_->Match(search, search_group_list_ref) &&
+ hash_->Match(hash, hash_group_list_ref);
if (!matched || !result)
return matched;
@@ -1162,55 +561,32 @@ bool URLPattern::Match(
result->setInputs(std::move(inputs));
result->setProtocol(
- MakeComponentResult(protocol_, protocol, protocol_group_list));
+ MakeURLPatternComponentResult(protocol_, protocol, protocol_group_list));
result->setUsername(
- MakeComponentResult(username_, username, username_group_list));
+ MakeURLPatternComponentResult(username_, username, username_group_list));
result->setPassword(
- MakeComponentResult(password_, password, password_group_list));
+ MakeURLPatternComponentResult(password_, password, password_group_list));
result->setHostname(
- MakeComponentResult(hostname_, hostname, hostname_group_list));
- result->setPort(MakeComponentResult(port_, port, port_group_list));
+ MakeURLPatternComponentResult(hostname_, hostname, hostname_group_list));
+ result->setPort(MakeURLPatternComponentResult(port_, port, port_group_list));
result->setPathname(
- MakeComponentResult(pathname_, pathname, pathname_group_list));
- result->setSearch(MakeComponentResult(search_, search, search_group_list));
- result->setHash(MakeComponentResult(hash_, hash, hash_group_list));
+ MakeURLPatternComponentResult(pathname_, pathname, pathname_group_list));
+ result->setSearch(
+ MakeURLPatternComponentResult(search_, search, search_group_list));
+ result->setHash(MakeURLPatternComponentResult(hash_, hash, hash_group_list));
return true;
}
// static
-URLPatternComponentResult* URLPattern::MakeComponentResult(
+URLPatternComponentResult* URLPattern::MakeURLPatternComponentResult(
Component* component,
const String& input,
- const Vector<String>& group_list) {
- Vector<std::pair<String, String>> groups;
- if (!component) {
- // When there is not Component we must act as if there was a default
- // wildcard pattern with a group. The group includes the entire input.
- groups.emplace_back("0", input);
- } else {
- DCHECK_EQ(component->name_list.size(), group_list.size());
- for (wtf_size_t i = 0; i < group_list.size(); ++i) {
- groups.emplace_back(component->name_list[i], group_list[i]);
- }
- }
-
+ const Vector<String>& group_values) {
auto* result = URLPatternComponentResult::Create();
result->setInput(input);
- result->setGroups(groups);
+ result->setGroups(component->MakeGroupList(group_values));
return result;
}
-bool URLPattern::ShouldTreatAsStandardURL(Component* protocol) {
- if (!protocol)
- return true;
- const auto protocol_matches = [&](const std::string& scheme) {
- DCHECK(base::IsStringASCII(scheme));
- return protocol->Match(
- StringView(scheme.data(), static_cast<unsigned>(scheme.size())),
- /*group_list=*/nullptr);
- };
- return base::ranges::any_of(url::GetStandardSchemes(), protocol_matches);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.h b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.h
index 0609081ea0b..4dd1affda57 100644
--- a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.h
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.h
@@ -1,4 +1,3 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,27 +6,36 @@
#include "base/types/pass_key.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_component.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/liburlpattern/parse.h"
-namespace liburlpattern {
-struct Options;
-} // namespace liburlpattern
-
namespace blink {
class ExceptionState;
class URLPatternComponentResult;
class URLPatternInit;
class URLPatternResult;
-class USVStringOrURLPatternInit;
-class URLPattern : public ScriptWrappable {
+namespace url_pattern {
+class Component;
+} // namespace url_pattern
+
+class MODULES_EXPORT URLPattern : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
- class Component;
+ using Component = url_pattern::Component;
public:
+ static URLPattern* Create(const V8URLPatternInput* input,
+ const String& base_url,
+ ExceptionState& exception_state);
+
+ static URLPattern* Create(const V8URLPatternInput* input,
+ ExceptionState& exception_state);
+
static URLPattern* Create(const URLPatternInit* init,
+ Component* precomputed_protocol_component,
ExceptionState& exception_state);
URLPattern(Component* protocol,
@@ -40,33 +48,17 @@ class URLPattern : public ScriptWrappable {
Component* hash,
base::PassKey<URLPattern> key);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool test(const V8URLPatternInput* input,
const String& base_url,
ExceptionState& exception_state) const;
bool test(const V8URLPatternInput* input,
ExceptionState& exception_state) const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool test(const USVStringOrURLPatternInit& input,
- const String& base_url,
- ExceptionState& exception_state) const;
- bool test(const USVStringOrURLPatternInit& input,
- ExceptionState& exception_state) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
URLPatternResult* exec(const V8URLPatternInput* input,
const String& base_url,
ExceptionState& exception_state) const;
URLPatternResult* exec(const V8URLPatternInput* input,
ExceptionState& exception_state) const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- URLPatternResult* exec(const USVStringOrURLPatternInit& input,
- const String& base_url,
- ExceptionState& exception_state) const;
- URLPatternResult* exec(const USVStringOrURLPatternInit& input,
- ExceptionState& exception_state) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
String protocol() const;
String username() const;
@@ -77,51 +69,29 @@ class URLPattern : public ScriptWrappable {
String search() const;
String hash() const;
+ static int compareComponent(const V8URLPatternComponent& component,
+ const URLPattern* left,
+ const URLPattern* right);
+
void Trace(Visitor* visitor) const override;
private:
- // A utility function that takes a given |pattern| and compiles it into a
- // Component structure. If the |pattern| matches the given |default_pattern|
- // then nullptr may be returned without throwing an exception. In this case
- // the Component is not constructed and the nullptr value should be treated as
- // matching any input value for the component. The |component| string is used
- // for exception messages. The |encode_callback| will be used to validate and
- // encode plain text within the pattern during compilation. |options| control
- // how the pattern is compiled.
- static Component* CompilePattern(
- const String& pattern,
- StringView component,
- liburlpattern::EncodeCallback encode_callback,
- const liburlpattern::Options& options,
- ExceptionState& exception_state);
-
// A utility function to determine if a given |input| matches the pattern
// or not. Returns |true| if there is a match and |false| otherwise. If
// |result| is not nullptr then the URLPatternResult contents will be filled.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
bool Match(const V8URLPatternInput* input,
const String& base_url,
URLPatternResult* result,
ExceptionState& exception_state) const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- bool Match(const USVStringOrURLPatternInit& input,
- const String& base_url,
- URLPatternResult* result,
- ExceptionState& exception_state) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// A utility function that constructs a URLPatternComponentResult for
- // a given |component|, |input|, and |group_list|. The |component| may
- // be nullptr.
- static URLPatternComponentResult* MakeComponentResult(
+ // a given |component|, |input|, and |group_list|.
+ static URLPatternComponentResult* MakeURLPatternComponentResult(
Component* component,
const String& input,
- const Vector<String>& group_list);
-
- static bool ShouldTreatAsStandardURL(Component* protocol);
+ const Vector<String>& group_values);
- // The compiled patterns for each URL component. If a Component member is
- // nullptr then it should be treated as a wildcard matching any input.
+ // The compiled patterns for each URL component.
Member<Component> protocol_;
Member<Component> username_;
Member<Component> password_;
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.idl b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.idl
index f3a619f43fd..e2722f0119f 100644
--- a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.idl
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern.idl
@@ -4,19 +4,22 @@
typedef (USVString or URLPatternInit) URLPatternInput;
+enum URLPatternComponent { "protocol", "username", "password", "hostname",
+ "port", "pathname", "search", "hash" };
+
// https://wicg.github.io/urlpattern/
[
- SecureContext,
Exposed=(Window,Worker),
RuntimeEnabled=URLPattern
] interface URLPattern {
- [RaisesException] constructor(URLPatternInit init);
+ [RaisesException, Measure]
+ constructor(URLPatternInput input, optional USVString baseURL);
- [RaisesException]
+ [RaisesException, Measure]
boolean test(URLPatternInput input, optional USVString baseURL);
- [RaisesException]
- URLPatternResult exec(URLPatternInput input, optional USVString baseURL);
+ [RaisesException, Measure]
+ URLPatternResult? exec(URLPatternInput input, optional USVString baseURL);
readonly attribute USVString protocol;
readonly attribute USVString username;
@@ -26,4 +29,8 @@ typedef (USVString or URLPatternInit) URLPatternInput;
readonly attribute USVString pathname;
readonly attribute USVString search;
readonly attribute USVString hash;
+
+ [RuntimeEnabled=URLPatternCompareComponent, Measure]
+ static short compareComponent(URLPatternComponent component,
+ URLPattern left, URLPattern right);
};
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.cc b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.cc
new file mode 100644
index 00000000000..d05ff0666e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.cc
@@ -0,0 +1,464 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h"
+
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_component.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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/url_canon.h"
+#include "url/url_util.h"
+
+namespace blink {
+namespace url_pattern {
+
+namespace {
+
+String MaybeStripPrefix(const String& value, StringView prefix) {
+ if (value.StartsWith(prefix))
+ return value.Substring(1, value.length() - 1);
+ return value;
+}
+
+String MaybeStripSuffix(const String& value, StringView suffix) {
+ if (value.EndsWith(suffix))
+ return value.Substring(0, value.length() - 1);
+ return value;
+}
+
+String StringFromCanonOutput(const url::CanonOutput& output,
+ const url::Component& component) {
+ return String::FromUTF8(output.data() + component.begin, component.len);
+}
+
+std::string StdStringFromCanonOutput(const url::CanonOutput& output,
+ const url::Component& component) {
+ return std::string(output.data() + component.begin, component.len);
+}
+
+} // anonymous namespace
+
+absl::StatusOr<std::string> ProtocolEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ bool result = url::CanonicalizeScheme(
+ input.data(), url::Component(0, static_cast<int>(input.size())),
+ &canon_output, &component);
+
+ if (!result) {
+ return absl::InvalidArgumentError("Invalid protocol '" +
+ std::string(input) + "'.");
+ }
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+absl::StatusOr<std::string> UsernameEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component username_component;
+ url::Component password_component;
+
+ bool result = url::CanonicalizeUserInfo(
+ input.data(), url::Component(0, static_cast<int>(input.size())), "",
+ url::Component(0, 0), &canon_output, &username_component,
+ &password_component);
+
+ if (!result) {
+ return absl::InvalidArgumentError("Invalid username pattern '" +
+ std::string(input) + "'.");
+ }
+
+ return StdStringFromCanonOutput(canon_output, username_component);
+}
+
+absl::StatusOr<std::string> PasswordEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component username_component;
+ url::Component password_component;
+
+ bool result = url::CanonicalizeUserInfo(
+ "", url::Component(0, 0), input.data(),
+ url::Component(0, static_cast<int>(input.size())), &canon_output,
+ &username_component, &password_component);
+
+ if (!result) {
+ return absl::InvalidArgumentError("Invalid password pattern '" +
+ std::string(input) + "'.");
+ }
+
+ return StdStringFromCanonOutput(canon_output, password_component);
+}
+
+absl::StatusOr<std::string> HostnameEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ bool result = url::CanonicalizeHost(
+ input.data(), url::Component(0, static_cast<int>(input.size())),
+ &canon_output, &component);
+
+ if (!result) {
+ return absl::InvalidArgumentError("Invalid hostname pattern '" +
+ std::string(input) + "'.");
+ }
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+absl::StatusOr<std::string> PortEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ bool result = url::CanonicalizePort(
+ input.data(), url::Component(0, static_cast<int>(input.size())),
+ url::PORT_UNSPECIFIED, &canon_output, &component);
+
+ if (!result) {
+ return absl::InvalidArgumentError("Invalid port pattern '" +
+ std::string(input) + "'.");
+ }
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+absl::StatusOr<std::string> StandardURLPathnameEncodeCallback(
+ absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ bool result = url::CanonicalizePartialPath(
+ input.data(), url::Component(0, static_cast<int>(input.size())),
+ &canon_output, &component);
+
+ if (!result) {
+ return absl::InvalidArgumentError("Invalid pathname pattern '" +
+ std::string(input) + "'.");
+ }
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+absl::StatusOr<std::string> PathURLPathnameEncodeCallback(
+ absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ url::CanonicalizePathURLPath(
+ input.data(), url::Component(0, static_cast<int>(input.size())),
+ &canon_output, &component);
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+absl::StatusOr<std::string> SearchEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ url::CanonicalizeQuery(input.data(),
+ url::Component(0, static_cast<int>(input.size())),
+ /*converter=*/nullptr, &canon_output, &component);
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+absl::StatusOr<std::string> HashEncodeCallback(absl::string_view input) {
+ if (input.empty())
+ return std::string();
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ url::CanonicalizeRef(input.data(),
+ url::Component(0, static_cast<int>(input.size())),
+ &canon_output, &component);
+
+ return StdStringFromCanonOutput(canon_output, component);
+}
+
+String CanonicalizeProtocol(const String& input,
+ ValueType type,
+ ExceptionState& exception_state) {
+ // We allow the protocol input to optionally contain a ":" suffix. Strip
+ // this for both URL and pattern protocols.
+ String stripped = MaybeStripSuffix(input, ":");
+
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ return stripped;
+ }
+
+ bool result = false;
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+ if (stripped.Is8Bit()) {
+ StringUTF8Adaptor utf8(stripped);
+ result = url::CanonicalizeScheme(
+ utf8.data(), url::Component(0, utf8.size()), &canon_output, &component);
+ } else {
+ result = url::CanonicalizeScheme(stripped.Characters16(),
+ url::Component(0, stripped.length()),
+ &canon_output, &component);
+ }
+
+ if (!result) {
+ exception_state.ThrowTypeError("Invalid protocol '" + stripped + "'.");
+ return String();
+ }
+
+ return StringFromCanonOutput(canon_output, component);
+}
+
+void CanonicalizeUsernameAndPassword(const String& username,
+ const String& password,
+ ValueType type,
+ String& username_out,
+ String& password_out,
+ ExceptionState& exception_state) {
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ username_out = username;
+ password_out = password;
+ return;
+ }
+
+ bool result = false;
+ url::RawCanonOutputT<char> canon_output;
+ url::Component username_component;
+ url::Component password_component;
+
+ if (username && password && username.Is8Bit() && password.Is8Bit()) {
+ StringUTF8Adaptor username_utf8(username);
+ StringUTF8Adaptor password_utf8(password);
+ result = url::CanonicalizeUserInfo(
+ username_utf8.data(), url::Component(0, username_utf8.size()),
+ password_utf8.data(), url::Component(0, password_utf8.size()),
+ &canon_output, &username_component, &password_component);
+
+ } else {
+ String username16(username);
+ String password16(password);
+ username16.Ensure16Bit();
+ password16.Ensure16Bit();
+ result = url::CanonicalizeUserInfo(
+ username16.Characters16(), url::Component(0, username16.length()),
+ password16.Characters16(), url::Component(0, password16.length()),
+ &canon_output, &username_component, &password_component);
+ }
+
+ if (!result) {
+ exception_state.ThrowTypeError("Invalid username '" + username +
+ "' and/or password '" + password + "'.");
+ return;
+ }
+
+ if (username_component.len != -1)
+ username_out = StringFromCanonOutput(canon_output, username_component);
+ if (password_component.len != -1)
+ password_out = StringFromCanonOutput(canon_output, password_component);
+}
+
+String CanonicalizeHostname(const String& input,
+ ValueType type,
+ ExceptionState& exception_state) {
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ return input;
+ }
+
+ bool success = false;
+ String result = SecurityOrigin::CanonicalizeHost(input, &success);
+ if (!success) {
+ exception_state.ThrowTypeError("Invalid hostname '" + input + "'.");
+ return String();
+ }
+
+ return result;
+}
+
+String CanonicalizePort(const String& input,
+ ValueType type,
+ const String& protocol,
+ ExceptionState& exception_state) {
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ return input;
+ }
+
+ int default_port = url::PORT_UNSPECIFIED;
+ if (!input.IsEmpty()) {
+ StringUTF8Adaptor protocol_utf8(protocol);
+ default_port =
+ url::DefaultPortForScheme(protocol_utf8.data(), protocol_utf8.size());
+ }
+
+ // Since ports only consist of digits there should be no encoding needed.
+ // Therefore we directly use the UTF8 encoding version of CanonicalizePort().
+ StringUTF8Adaptor utf8(input);
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+ if (!url::CanonicalizePort(utf8.data(), url::Component(0, utf8.size()),
+ default_port, &canon_output, &component)) {
+ exception_state.ThrowTypeError("Invalid port '" + input + "'.");
+ return String();
+ }
+
+ return component.len == -1 ? g_empty_string
+ : StringFromCanonOutput(canon_output, component);
+}
+
+String CanonicalizePathname(const String& protocol,
+ const String& input,
+ ValueType type,
+ ExceptionState& exception_state) {
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ return input;
+ }
+
+ // Determine if we are using "standard" or "path" URL canonicalization
+ // for the pathname. In spec terms the "path" URL behavior corresponds
+ // to "cannot-be-a-base" URLs. We make this determination based on the
+ // protocol string since we cannot look at the number of slashes between
+ // components like the URL spec. If this is inadequate the developer
+ // can use the baseURL property to get more strict URL behavior.
+ //
+ // We default to "standard" URL behavior to match how the empty protocol
+ // string in the URLPattern constructor results in the pathname pattern
+ // getting "standard" URL canonicalization.
+ bool standard = false;
+ if (protocol.IsEmpty()) {
+ standard = true;
+ } else if (protocol.Is8Bit()) {
+ StringUTF8Adaptor utf8(protocol);
+ standard = url::IsStandard(utf8.data(), url::Component(0, utf8.size()));
+ } else {
+ standard = url::IsStandard(protocol.Characters16(),
+ url::Component(0, protocol.length()));
+ }
+
+ // Do not enforce absolute pathnames here since we can't enforce it
+ // it consistently in the URLPattern constructor. This allows us to
+ // produce a match when the exact same fixed pathname string is passed
+ // to both the constructor and test()/exec(). Similarly, we use
+ // url::CanonicalizePartialPath() below instead of url::CanonicalizePath()
+ // to avoid pre-pending a slash at the start of the string.
+
+ bool result = false;
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+
+ const auto canonicalize_path = [&](const auto* data, int length) {
+ if (standard) {
+ return url::CanonicalizePartialPath(data, url::Component(0, length),
+ &canon_output, &component);
+ }
+ url::CanonicalizePathURLPath(data, url::Component(0, length), &canon_output,
+ &component);
+ return true;
+ };
+
+ if (input.Is8Bit()) {
+ StringUTF8Adaptor utf8(input);
+ result = canonicalize_path(utf8.data(), utf8.size());
+ } else {
+ result = canonicalize_path(input.Characters16(), input.length());
+ }
+
+ if (!result) {
+ exception_state.ThrowTypeError("Invalid pathname '" + input + "'.");
+ return String();
+ }
+
+ return StringFromCanonOutput(canon_output, component);
+}
+
+String CanonicalizeSearch(const String& input,
+ ValueType type,
+ ExceptionState& exception_state) {
+ // We allow the search input to optionally contain a "?" prefix. Strip
+ // this for both URL and pattern protocols.
+ String stripped = MaybeStripPrefix(input, "?");
+
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ return stripped;
+ }
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+ if (stripped.Is8Bit()) {
+ StringUTF8Adaptor utf8(stripped);
+ url::CanonicalizeQuery(utf8.data(), url::Component(0, utf8.size()),
+ /*converter=*/nullptr, &canon_output, &component);
+ } else {
+ url::CanonicalizeQuery(stripped.Characters16(),
+ url::Component(0, stripped.length()),
+ /*converter=*/nullptr, &canon_output, &component);
+ }
+
+ return StringFromCanonOutput(canon_output, component);
+}
+
+String CanonicalizeHash(const String& input,
+ ValueType type,
+ ExceptionState& exception_state) {
+ // We allow the hash input to optionally contain a "#" prefix. Strip
+ // this for both URL and pattern protocols.
+ String stripped = MaybeStripPrefix(input, "#");
+
+ if (type == ValueType::kPattern) {
+ // Canonicalization for patterns is handled during compilation via
+ // encoding callbacks.
+ return stripped;
+ }
+
+ url::RawCanonOutputT<char> canon_output;
+ url::Component component;
+ if (stripped.Is8Bit()) {
+ StringUTF8Adaptor utf8(stripped);
+ url::CanonicalizeRef(utf8.data(), url::Component(0, utf8.size()),
+ &canon_output, &component);
+ } else {
+ url::CanonicalizeRef(stripped.Characters16(),
+ url::Component(0, stripped.length()), &canon_output,
+ &component);
+ }
+
+ return StringFromCanonOutput(canon_output, component);
+}
+
+} // namespace url_pattern
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h
new file mode 100644
index 00000000000..eb6f3b38582
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h
@@ -0,0 +1,83 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_CANON_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_CANON_H_
+
+#include "third_party/abseil-cpp/absl/status/statusor.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ExceptionState;
+
+namespace url_pattern {
+
+// An enum indicating whether the associated component values to be operated
+// on are for patterns or URLs. Validation and canonicalization will
+// do different things depending on the type.
+enum class ValueType {
+ kPattern,
+ kURL,
+};
+
+// The following functions are callbacks that may be passed to the
+// liburlpattern::Parse() method. Each performs validation and encoding for
+// a different URL component.
+//
+// Note that there are two different pathname callbacks for "standard" URLs
+// like `https://foo` // vs "path" URLs like `data:foo`. Select the correct
+// callback by calling `ShouldTreatAsStandardURL()`.
+absl::StatusOr<std::string> ProtocolEncodeCallback(absl::string_view input);
+absl::StatusOr<std::string> UsernameEncodeCallback(absl::string_view input);
+absl::StatusOr<std::string> PasswordEncodeCallback(absl::string_view input);
+absl::StatusOr<std::string> HostnameEncodeCallback(absl::string_view input);
+absl::StatusOr<std::string> PortEncodeCallback(absl::string_view input);
+absl::StatusOr<std::string> StandardURLPathnameEncodeCallback(
+ absl::string_view input);
+absl::StatusOr<std::string> PathURLPathnameEncodeCallback(
+ absl::string_view input);
+absl::StatusOr<std::string> SearchEncodeCallback(absl::string_view input);
+absl::StatusOr<std::string> HashEncodeCallback(absl::string_view input);
+
+// Utility functions to canonicalize different component strings. They will
+// throw an exception if the input is invalid. The canonicalization and/or
+// validation will only be applied if the `type` is kURL. These functions
+// simply pass through the value when the `type` is kPattern. Encoding is
+// for patterns are handled later during compilation via the encode callbacks
+// above.
+//
+// The result is returned, except for `CanonicalizeUsernameAndPassword` which
+// uses separate out parameters for the resulting username and password.
+String CanonicalizeProtocol(const String& input,
+ ValueType type,
+ ExceptionState& exception_state);
+void CanonicalizeUsernameAndPassword(const String& username,
+ const String& password,
+ ValueType type,
+ String& username_out,
+ String& password_out,
+ ExceptionState& exception_state);
+String CanonicalizeHostname(const String& input,
+ ValueType type,
+ ExceptionState& exception_state);
+String CanonicalizePort(const String& input,
+ ValueType type,
+ const String& protocol,
+ ExceptionState& exception_state);
+String CanonicalizePathname(const String& protocol,
+ const String& input,
+ ValueType type,
+ ExceptionState& exception_state);
+String CanonicalizeSearch(const String& input,
+ ValueType type,
+ ExceptionState& exception_state);
+String CanonicalizeHash(const String& input,
+ ValueType type,
+ ExceptionState& exception_state);
+
+} // namespace url_pattern
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_CANON_H_
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.cc b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.cc
new file mode 100644
index 00000000000..8e029755c12
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.cc
@@ -0,0 +1,390 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_component.h"
+
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_util.h"
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_canon.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
+#include "url/url_util.h"
+
+namespace blink {
+namespace url_pattern {
+
+namespace {
+
+// Utility method to convert a type to a string.
+StringView TypeToString(Component::Type type) {
+ switch (type) {
+ case Component::Type::kProtocol:
+ return "protocol";
+ case Component::Type::kUsername:
+ return "username";
+ case Component::Type::kPassword:
+ return "password";
+ case Component::Type::kHostname:
+ return "hostname";
+ case Component::Type::kPort:
+ return "port";
+ case Component::Type::kPathname:
+ return "pathname";
+ case Component::Type::kSearch:
+ return "search";
+ case Component::Type::kHash:
+ return "hash";
+ }
+ NOTREACHED();
+}
+
+// Utility method to get the correct encoding callback for a given type.
+liburlpattern::EncodeCallback GetEncodeCallback(Component::Type type,
+ Component* protocol_component) {
+ switch (type) {
+ case Component::Type::kProtocol:
+ return ProtocolEncodeCallback;
+ case Component::Type::kUsername:
+ return UsernameEncodeCallback;
+ case Component::Type::kPassword:
+ return PasswordEncodeCallback;
+ case Component::Type::kHostname:
+ return HostnameEncodeCallback;
+ case Component::Type::kPort:
+ return PortEncodeCallback;
+ case Component::Type::kPathname:
+ // Different types of URLs use different canonicalization for pathname.
+ // A "standard" URL flattens `.`/`..` and performs full percent encoding.
+ // A "path" URL does not flatten and uses a more lax percent encoding.
+ // The spec calls "path" URLs as "cannot-be-a-base-URL" URLs:
+ //
+ // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
+ //
+ // We prefer "standard" URL here by checking to see if the protocol
+ // pattern matches any of the known standard protocol strings. So
+ // an exact pattern of `http` will match, but so will `http{s}?` and
+ // `*`.
+ //
+ // If the protocol pattern does not match any of the known standard URL
+ // protocols then we fall back to the "path" URL behavior. This will
+ // normally be triggered by `data`, `javascript`, `about`, etc. It
+ // will also be triggered for custom protocol strings. We favor "path"
+ // behavior here because its better to under canonicalize since the
+ // developer can always manually canonicalize the pathname for a custom
+ // protocol.
+ //
+ // ShouldTreatAsStandardURL can by a bit expensive, so only do it if we
+ // actually have a pathname pattern to compile.
+ CHECK(protocol_component);
+ if (protocol_component->ShouldTreatAsStandardURL())
+ return StandardURLPathnameEncodeCallback;
+ else
+ return PathURLPathnameEncodeCallback;
+ case Component::Type::kSearch:
+ return SearchEncodeCallback;
+ case Component::Type::kHash:
+ return HashEncodeCallback;
+ }
+ NOTREACHED();
+}
+
+// Utility method to get the correct liburlpattern parse options for a given
+// type.
+const liburlpattern::Options& GetOptions(Component::Type type) {
+ using liburlpattern::Options;
+
+ // The liburlpattern::Options to use for most component patterns. We
+ // default to strict mode and case sensitivity. In addition, most
+ // components have no concept of a delimiter or prefix character.
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Options, default_options,
+ ({.delimiter_list = "",
+ .prefix_list = "",
+ .sensitive = true,
+ .strict = true}));
+
+ // The liburlpattern::Options to use for hostname patterns. This uses a
+ // "." delimiter controlling how far a named group like ":bar" will match
+ // by default. Note, hostnames are case insensitive but we require case
+ // sensitivity here. This assumes that the hostname values have already
+ // been normalized to lower case as in URL().
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Options, hostname_options,
+ ({.delimiter_list = ".",
+ .prefix_list = "",
+ .sensitive = true,
+ .strict = true}));
+
+ // The liburlpattern::Options to use for pathname patterns. This uses a
+ // "/" delimiter controlling how far a named group like ":bar" will match
+ // by default. It also configures "/" to be treated as an automatic
+ // prefix before groups.
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Options, pathname_options,
+ ({.delimiter_list = "/",
+ .prefix_list = "/",
+ .sensitive = true,
+ .strict = true}));
+
+ switch (type) {
+ case Component::Type::kHostname:
+ return hostname_options;
+ case Component::Type::kPathname:
+ return pathname_options;
+ case Component::Type::kProtocol:
+ case Component::Type::kUsername:
+ case Component::Type::kPassword:
+ case Component::Type::kPort:
+ case Component::Type::kSearch:
+ case Component::Type::kHash:
+ return default_options;
+ }
+ NOTREACHED();
+}
+
+// Utility function to return a statically allocated Part list.
+const std::vector<liburlpattern::Part>& GetWildcardOnlyPartList() {
+ using liburlpattern::Modifier;
+ using liburlpattern::Part;
+ using liburlpattern::PartType;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ std::vector<Part>, instance,
+ ({Part(PartType::kFullWildcard,
+ /*name=*/"",
+ /*prefix=*/"", /*value=*/"", /*suffix=*/"", Modifier::kNone)}));
+ return instance;
+}
+
+int ComparePart(const liburlpattern::Part& lh, const liburlpattern::Part& rh) {
+ // We prioritize PartType in the ordering so we can favor fixed text. The
+ // type ordering is:
+ //
+ // kFixed > kRegex > kSegmentWildcard > kFullWildcard.
+ //
+ // We considered kRegex greater than the wildcards because it is likely to be
+ // used for imposing some constraint and not just duplicating wildcard
+ // behavior.
+ //
+ // This comparison depends on the PartType enum in liburlpattern having the
+ // correct corresponding numeric values.
+ //
+ // Next the Modifier is considered:
+ //
+ // kNone > kOneOrMore > kOptional > kZeroOrMore.
+ //
+ // The rationale here is that requring the match group to exist is more
+ // restrictive then making it optional and requiring an exact count is more
+ // restrictive than repeating.
+ //
+ // This comparison depends on the Modifier enum in liburlpattern having the
+ // correct corresponding numeric values.
+ //
+ // Finally we lexicographically compare the text components from left to
+ // right; `prefix`, `value`, and `suffix`. Its ok to depend on simple
+ // byte-wise string comparison here because the values have all been URL
+ // encoded. This guarantees the strings contain only ASCII.
+ auto left = std::tie(lh.type, lh.modifier, lh.prefix, lh.value, lh.suffix);
+ auto right = std::tie(rh.type, rh.modifier, rh.prefix, rh.value, rh.suffix);
+ if (left < right)
+ return -1;
+ else if (left == right)
+ return 0;
+ else
+ return 1;
+}
+
+// Utility method to compare two part lists.
+int ComparePartList(const std::vector<liburlpattern::Part>& lh,
+ const std::vector<liburlpattern::Part>& rh) {
+ using liburlpattern::Modifier;
+ using liburlpattern::Part;
+ using liburlpattern::PartType;
+
+ // Begin by comparing each Part in the lists with each other. If any
+ // are not equal, then we are done.
+ size_t i = 0;
+ for (; i < lh.size() && i < rh.size(); ++i) {
+ int r = ComparePart(lh[i], rh[i]);
+ if (r)
+ return r;
+ }
+
+ // We reached the end of at least one of the lists without finding a
+ // difference. However, we must handle the case where one list is longer
+ // than the other. In this case we compare the next Part from the
+ // longer list to a synthetically created empty kFixed Part. This is
+ // necessary in order for "/foo/" to be considered more restrictive, and
+ // therefore greater, than "/foo/*".
+ if (i == lh.size() && i != rh.size())
+ return ComparePart(Part(PartType::kFixed, "", Modifier::kNone), rh[i]);
+ else if (i != lh.size() && i == rh.size())
+ return ComparePart(lh[i], Part(PartType::kFixed, "", Modifier::kNone));
+
+ // No differences were found, so declare them equal.
+ return 0;
+}
+
+} // anonymous namespace
+
+// static
+Component* Component::Compile(const String& pattern,
+ Type type,
+ Component* protocol_component,
+ ExceptionState& exception_state) {
+ // If the pattern is null then return a special Component object that matches
+ // any input as if the pattern was `*`.
+ if (pattern.IsNull()) {
+ return MakeGarbageCollected<Component>(type, base::PassKey<Component>());
+ }
+
+ const liburlpattern::Options& options = GetOptions(type);
+
+ // Parse the pattern.
+ StringUTF8Adaptor utf8(pattern);
+ auto parse_result = liburlpattern::Parse(
+ absl::string_view(utf8.data(), utf8.size()),
+ GetEncodeCallback(type, protocol_component), options);
+ if (!parse_result.ok()) {
+ exception_state.ThrowTypeError(
+ "Invalid " + TypeToString(type) + " pattern '" + pattern + "'. " +
+ String::FromUTF8(parse_result.status().message().data(),
+ parse_result.status().message().size()));
+ return nullptr;
+ }
+
+ // Extract a regular expression string from the parsed pattern.
+ std::vector<std::string> name_list;
+ std::string regexp_string =
+ parse_result.value().GenerateRegexString(&name_list);
+
+ // Compile the regular expression to verify it is valid.
+ auto case_sensitive = options.sensitive ? WTF::kTextCaseSensitive
+ : WTF::kTextCaseASCIIInsensitive;
+ DCHECK(base::IsStringASCII(regexp_string));
+ ScriptRegexp* regexp = MakeGarbageCollected<ScriptRegexp>(
+ String(regexp_string.data(), regexp_string.size()), case_sensitive,
+ kMultilineDisabled, ScriptRegexp::UTF16);
+ if (!regexp->IsValid()) {
+ // The regular expression failed to compile. This means that some
+ // custom regexp group within the pattern is illegal. Attempt to
+ // compile each regexp group individually in order to identify the
+ // culprit.
+ for (auto& part : parse_result.value().PartList()) {
+ if (part.type != liburlpattern::PartType::kRegex)
+ continue;
+ DCHECK(base::IsStringASCII(part.value));
+ String group_value(part.value.data(), part.value.size());
+ regexp = MakeGarbageCollected<ScriptRegexp>(
+ group_value, case_sensitive, kMultilineDisabled, ScriptRegexp::UTF16);
+ if (regexp->IsValid())
+ continue;
+ exception_state.ThrowTypeError("Invalid " + TypeToString(type) +
+ " pattern '" + pattern +
+ "'. Custom regular expression group '" +
+ group_value + "' is invalid.");
+ return nullptr;
+ }
+ // We couldn't find a bad regexp group, but we still have an overall
+ // error. This shouldn't happen, but we handle it anyway.
+ exception_state.ThrowTypeError("Invalid " + TypeToString(type) +
+ " pattern '" + pattern +
+ "'. An unexpected error has occurred.");
+ return nullptr;
+ }
+
+ Vector<String> wtf_name_list;
+ wtf_name_list.ReserveInitialCapacity(
+ static_cast<wtf_size_t>(name_list.size()));
+ for (const auto& name : name_list) {
+ wtf_name_list.push_back(String::FromUTF8(name.data(), name.size()));
+ }
+
+ return MakeGarbageCollected<Component>(
+ type, std::move(parse_result.value()), std::move(regexp),
+ std::move(wtf_name_list), base::PassKey<Component>());
+}
+
+// static
+int Component::Compare(const Component& lh, const Component& rh) {
+ using liburlpattern::Modifier;
+ using liburlpattern::Part;
+ using liburlpattern::PartType;
+
+ // If both the left and right components are empty wildcards, then they are
+ // effectively equal.
+ if (!lh.pattern_.has_value() && !rh.pattern_.has_value())
+ return 0;
+
+ // If one side has a real pattern and the other side is an empty component,
+ // then we have to compare to a part list with a single full wildcard.
+ if (lh.pattern_.has_value() && !rh.pattern_.has_value()) {
+ return ComparePartList(lh.pattern_->PartList(), GetWildcardOnlyPartList());
+ }
+
+ if (!lh.pattern_.has_value() && rh.pattern_.has_value()) {
+ return ComparePartList(GetWildcardOnlyPartList(), rh.pattern_->PartList());
+ }
+
+ // Otherwise compare the part lists of the patterns on each side.
+ return ComparePartList(lh.pattern_->PartList(), rh.pattern_->PartList());
+}
+
+Component::Component(Type type,
+ liburlpattern::Pattern pattern,
+ ScriptRegexp* regexp,
+ Vector<String> name_list,
+ base::PassKey<Component> key)
+ : type_(type),
+ pattern_(std::move(pattern)),
+ regexp_(regexp),
+ name_list_(std::move(name_list)) {}
+
+Component::Component(Type type, base::PassKey<Component> key)
+ : type_(type), name_list_({"0"}) {}
+
+bool Component::Match(StringView input, Vector<String>* group_list) const {
+ if (regexp_) {
+ return regexp_->Match(input, /*start_from=*/0, /*match_length=*/nullptr,
+ group_list) == 0;
+ } else {
+ if (group_list)
+ group_list->push_back(input.ToString());
+ return true;
+ }
+}
+
+String Component::GeneratePatternString() const {
+ if (pattern_.has_value())
+ return String::FromUTF8(pattern_->GeneratePatternString());
+ else
+ return "*";
+}
+
+Vector<std::pair<String, String>> Component::MakeGroupList(
+ const Vector<String>& group_values) const {
+ DCHECK_EQ(name_list_.size(), group_values.size());
+ Vector<std::pair<String, String>> result;
+ result.ReserveInitialCapacity(group_values.size());
+ for (wtf_size_t i = 0; i < group_values.size(); ++i) {
+ result.emplace_back(name_list_[i], group_values[i]);
+ }
+ return result;
+}
+
+bool Component::ShouldTreatAsStandardURL() const {
+ DCHECK(type_ == Type::kProtocol);
+ if (!pattern_.has_value())
+ return true;
+ const auto protocol_matches = [&](const std::string& scheme) {
+ DCHECK(base::IsStringASCII(scheme));
+ return Match(
+ StringView(scheme.data(), static_cast<unsigned>(scheme.size())),
+ /*group_list=*/nullptr);
+ };
+ return base::ranges::any_of(url::GetStandardSchemes(), protocol_matches);
+}
+
+void Component::Trace(Visitor* visitor) const {
+ visitor->Trace(regexp_);
+}
+
+} // namespace url_pattern
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.h b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.h
new file mode 100644
index 00000000000..31ca11e1f62
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_component.h
@@ -0,0 +1,113 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_COMPONENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_COMPONENT_H_
+
+#include "base/types/pass_key.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_regexp.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/trace_traits.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/liburlpattern/parse.h"
+#include "third_party/liburlpattern/pattern.h"
+
+namespace blink {
+
+class ExceptionState;
+
+namespace url_pattern {
+
+// A struct representing all the information needed to match a particular
+// component of a URL.
+class Component final : public GarbageCollected<Component> {
+ public:
+ // Enumeration defining the different types of components. Each component
+ // type uses a slightly different kind of character encoding. In addition,
+ // different component types using different liburlpattern parse options.
+ enum class Type {
+ kProtocol,
+ kUsername,
+ kPassword,
+ kHostname,
+ kPort,
+ kPathname,
+ kSearch,
+ kHash,
+ };
+
+ // A utility function that takes a given `pattern` and compiles it into a
+ // Component structure. If the `pattern` is null then nullptr
+ // may be returned without throwing an exception. In this case the
+ // Component is not constructed and the nullptr value should be
+ // treated as matching any input value for the component. The `type`
+ // specifies which URL component is the pattern is being compiled for. This
+ // will select the correct encoding callback, liburlpattern options, and
+ // populate errors messages with the correct component string.
+ static Component* Compile(const String& pattern,
+ Type type,
+ Component* protocol_component,
+ ExceptionState& exception_state);
+
+ // Compare the pattern strings in the two given components. This provides a
+ // mostly lexicographical ordering based on fixed text in the patterns.
+ // Matching groups and modifiers are treated such that more restrictive
+ // patterns are greater in value. Group names are not considered in the
+ // comparison.
+ static int Compare(const Component& lh, const Component& rh);
+
+ // Constructs a Component with a real `pattern` that compiled to the given
+ // `regexp`.
+ Component(Type type,
+ liburlpattern::Pattern pattern,
+ ScriptRegexp* regexp,
+ Vector<String> name_list,
+ base::PassKey<Component> key);
+
+ // Constructs an empty Component that matches any input as if it had the
+ // pattern `*`.
+ Component(Type type, base::PassKey<Component> key);
+
+ // Match the given `input` against the component pattern. Returns `true`
+ // if there is a match. If `group_list` is not nullptr, then it will be
+ // populated with group values captured by the pattern.
+ bool Match(StringView input, Vector<String>* group_list) const;
+
+ // Convert the compiled component pattern back into a pattern string. This
+ // will be functionally equivalent to the original, but may differ based on
+ // canonicalization that occurred during parsing.
+ String GeneratePatternString() const;
+
+ // Combines the given list of group values with the group names specified in
+ // the original pattern. The return result is a vector of name:value tuples.
+ Vector<std::pair<String, String>> MakeGroupList(
+ const Vector<String>& group_values) const;
+
+ // Method to determine if the URL associated with this component should be
+ // treated as a "standard" URL like `https://foo` vs a "path" URL like
+ // `data:foo`. This should only be called for kProtocol components.
+ bool ShouldTreatAsStandardURL() const;
+
+ void Trace(Visitor* visitor) const;
+
+ private:
+ const Type type_;
+
+ // The parsed pattern.
+ const absl::optional<liburlpattern::Pattern> pattern_;
+
+ // The pattern compiled down to a js regular expression.
+ const Member<ScriptRegexp> regexp_;
+
+ // The names to be applied to the regular expression capture groups. Note,
+ // liburlpattern regular expressions do not use named capture groups directly.
+ const Vector<String> name_list_;
+};
+
+} // namespace url_pattern
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_COMPONENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_fuzzer.cc b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_fuzzer.cc
new file mode 100644
index 00000000000..9760a6d6039
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_fuzzer.cc
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_urlpatterninit_usvstring.h"
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern.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/testing/blink_fuzzer_test_support.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ static BlinkFuzzerTestSupport test_support = BlinkFuzzerTestSupport();
+ DummyExceptionStateForTesting exception_state;
+ auto* input = MakeGarbageCollected<V8URLPatternInput>(
+ String::FromUTF8(reinterpret_cast<const char*>(data), size));
+ URLPattern::Create(input, exception_state);
+ V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting(
+ v8::Isolate::kFullGarbageCollection);
+ 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/modules/url_pattern/url_pattern_parser.cc b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.cc
new file mode 100644
index 00000000000..22a34bb3b0d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.cc
@@ -0,0 +1,453 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_parser.h"
+
+#include "base/notreached.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_url_pattern_init.h"
+#include "third_party/blink/renderer/modules/url_pattern/url_pattern_component.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
+#include "third_party/liburlpattern/tokenize.h"
+
+namespace blink {
+namespace url_pattern {
+
+Parser::Parser(const String& input) : input_(input), utf8_(input) {}
+
+void Parser::Parse(ExceptionState& exception_state) {
+ DCHECK_EQ(state_, StringParseState::kInit);
+ DCHECK_EQ(token_index_, 0u);
+
+ auto tokenize_result =
+ liburlpattern::Tokenize(absl::string_view(utf8_.data(), utf8_.size()),
+ liburlpattern::TokenizePolicy::kLenient);
+ if (!tokenize_result.ok()) {
+ // This should not happen with kLenient mode, but we handle it anyway.
+ exception_state.ThrowTypeError("Invalid input string '" + input_ +
+ "'. It unexpectedly fails to tokenize.");
+ return;
+ }
+
+ token_list_ = std::move(tokenize_result.value());
+ result_ = MakeGarbageCollected<URLPatternInit>();
+
+ // When constructing a pattern using structured input like
+ // `new URLPattern({ pathname: 'foo' })` any missing components will be
+ // defaulted to wildcards. In the constructor string case, however, all
+ // components are precisely defined as either empty string or a longer
+ // value. This is due to there being no way to simply "leave out" a
+ // component when writing a URL. The behavior also matches the URL
+ // constructor.
+ //
+ // To implement this we initialize components to the empty string in advance.
+ //
+ // We can't, however, do this immediately. We want to allow the baseURL to
+ // provide information for relative URLs, so we only want to set the default
+ // empty string values for components following the first component in the
+ // relative URL.
+ //
+ // We therefore wait to set the default component values until after we exit
+ // the kInit state and have determined if we are in relative or absolute mode.
+
+ // Iterate through the list of tokens and update our state machine as we go.
+ for (; token_index_ < token_list_.size(); token_index_ += token_increment_) {
+ // Reset back to our default `token_increment_` value.
+ token_increment_ = 1;
+
+ // All states must respect the end of the token list. The liburlpattern
+ // tokenizer guarantees that the last token will have the type `kEnd`.
+ if (token_list_[token_index_].type == liburlpattern::TokenType::kEnd) {
+ // If we failed to find a protocol terminator then we are still in
+ // relative mode. We now need to determine the first component of the
+ // relative URL.
+ if (state_ == StringParseState::kInit) {
+ // Reset back to the start of the input string.
+ Rewind();
+
+ // If the string begins with `?` then its a relative search component.
+ // If it starts with `#` then its a relative hash component. Otherwise
+ // its a relative pathname.
+ //
+ // In each case we initialize any components following the initial
+ // component to be empty string.
+ if (IsHashPrefix()) {
+ ChangeState(StringParseState::kHash, Skip(1));
+ } else if (IsSearchPrefix()) {
+ ChangeState(StringParseState::kSearch, Skip(1));
+ result_->setHash(g_empty_string);
+ } else {
+ ChangeState(StringParseState::kPathname, Skip(0));
+ result_->setSearch(g_empty_string);
+ result_->setHash(g_empty_string);
+ }
+ continue;
+ }
+
+ // If we failed to find an `@`, then there is no username and password.
+ // We should rewind and process the data as a hostname.
+ else if (state_ == StringParseState::kAuthority) {
+ RewindAndSetState(StringParseState::kHostname);
+ continue;
+ }
+
+ ChangeState(StringParseState::kDone, Skip(0));
+ break;
+ }
+
+ // In addition, all states must handle pattern groups. We do not permit
+ // a component to end in the middle of a pattern group. Therefore we skip
+ // past any tokens that are within `{` and `}`. Note, the tokenizer
+ // handles grouping `(` and `)` and `:foo` groups for us automatically, so
+ // we don't need special code for them here.
+ if (group_depth_ > 0) {
+ if (IsGroupClose())
+ group_depth_ -= 1;
+ else
+ continue;
+ }
+
+ if (IsGroupOpen()) {
+ group_depth_ += 1;
+ continue;
+ }
+
+ switch (state_) {
+ case StringParseState::kInit:
+ if (IsProtocolSuffix()) {
+ // We are in absolute mode and we know values will not be inherited
+ // from a base URL. Therefore initialize the rest of the components
+ // to the empty string.
+ result_->setUsername(g_empty_string);
+ result_->setPassword(g_empty_string);
+ result_->setHostname(g_empty_string);
+ result_->setPort(g_empty_string);
+ result_->setPathname(g_empty_string);
+ result_->setSearch(g_empty_string);
+ result_->setHash(g_empty_string);
+
+ // Update the state to expect the start of an absolute URL.
+ RewindAndSetState(StringParseState::kProtocol);
+ }
+ break;
+
+ case StringParseState::kProtocol:
+ // If we find the end of the protocol component...
+ if (IsProtocolSuffix()) {
+ // First we eagerly compile the protocol pattern and use it to
+ // compute if this entire URLPattern should be treated as a
+ // "standard" URL. If any of the special schemes, like `https`,
+ // match the protocol pattern then we treat it as standard.
+ ComputeShouldTreatAsStandardURL(exception_state);
+ if (exception_state.HadException())
+ return;
+
+ // Standard URLs default to `/` for the pathname.
+ if (should_treat_as_standard_url_)
+ result_->setPathname("/");
+
+ // By default we treat this as a "cannot-be-a-base-URL" or what chrome
+ // calls a "path" URL. In this case we go straight to the pathname
+ // component. The hostname and port are left with their default
+ // empty string values.
+ StringParseState next_state = StringParseState::kPathname;
+ Skip skip = Skip(1);
+
+ // If there are authority slashes, like `https://`, then
+ // we must transition to the authority section of the URLPattern.
+ if (NextIsAuthoritySlashes()) {
+ next_state = StringParseState::kAuthority;
+ skip = Skip(3);
+ }
+
+ // If there are no authority slashes, but the protocol is special
+ // then we still go to the authority section as this is a "standard"
+ // URL. This differs from the above case since we don't need to skip
+ // the extra slashes.
+ else if (should_treat_as_standard_url_) {
+ next_state = StringParseState::kAuthority;
+ }
+
+ ChangeState(next_state, skip);
+ }
+ break;
+
+ case StringParseState::kAuthority:
+ // Before going to the hostname state we must see if there is an
+ // identity of the form:
+ //
+ // <username>:<password>@<hostname>
+ //
+ // We check for this by looking for the `@` character. The username
+ // and password are themselves each optional, so the `:` may not be
+ // present. If we see the `@` we just go to the username state
+ // and let it proceed until it hits either the password separator
+ // or the `@` terminator.
+ if (IsIdentityTerminator())
+ RewindAndSetState(StringParseState::kUsername);
+
+ // Stop searching for the `@` character if we see the beginning
+ // of the pathname, search, or hash components.
+ else if (IsPathnameStart() || IsSearchPrefix() || IsHashPrefix())
+ RewindAndSetState(StringParseState::kHostname);
+ break;
+
+ case StringParseState::kUsername:
+ // If we find a `:` then transition to the password component state.
+ if (IsPasswordPrefix())
+ ChangeState(StringParseState::kPassword, Skip(1));
+
+ // If we find a `@` then transition to the hostname component state.
+ else if (IsIdentityTerminator())
+ ChangeState(StringParseState::kHostname, Skip(1));
+ break;
+
+ case StringParseState::kPassword:
+ // If we find a `@` then transition to the hostname component state.
+ if (IsIdentityTerminator())
+ ChangeState(StringParseState::kHostname, Skip(1));
+ break;
+
+ case StringParseState::kHostname:
+ // If we find a `:` then we transition to the port component state.
+ if (IsPortPrefix())
+ ChangeState(StringParseState::kPort, Skip(1));
+
+ // If we find a `/` then we transition to the pathname component state.
+ else if (IsPathnameStart())
+ ChangeState(StringParseState::kPathname, Skip(0));
+
+ // If we find a `?` then we transition to the search component state.
+ else if (IsSearchPrefix())
+ ChangeState(StringParseState::kSearch, Skip(1));
+
+ // If we find a `#` then we transition to the hash component state.
+ else if (IsHashPrefix())
+ ChangeState(StringParseState::kHash, Skip(1));
+ break;
+
+ case StringParseState::kPort:
+ // If we find a `/` then we transition to the pathname component state.
+ if (IsPathnameStart())
+ ChangeState(StringParseState::kPathname, Skip(0));
+ // If we find a `?` then we transition to the search component state.
+ else if (IsSearchPrefix())
+ ChangeState(StringParseState::kSearch, Skip(1));
+ // If we find a `#` then we transition to the hash component state.
+ else if (IsHashPrefix())
+ ChangeState(StringParseState::kHash, Skip(1));
+ break;
+ case StringParseState::kPathname:
+ // If we find a `?` then we transition to the search component state.
+ if (IsSearchPrefix())
+ ChangeState(StringParseState::kSearch, Skip(1));
+ // If we find a `#` then we transition to the hash component state.
+ else if (IsHashPrefix())
+ ChangeState(StringParseState::kHash, Skip(1));
+ break;
+ case StringParseState::kSearch:
+ // If we find a `#` then we transition to the hash component state.
+ if (IsHashPrefix())
+ ChangeState(StringParseState::kHash, Skip(1));
+ break;
+ case StringParseState::kHash:
+ // Nothing to do here as we are just looking for the end.
+ break;
+ case StringParseState::kDone:
+ NOTREACHED();
+ break;
+ };
+ }
+}
+
+void Parser::ChangeState(StringParseState new_state, Skip skip) {
+ // First we convert the tokens between `component_start_` and `token_index_`
+ // a component pattern string. This is stored in the appropriate result
+ // property based on the current `state_`.
+ switch (state_) {
+ case StringParseState::kInit:
+ // No component to set when transitioning from this state.
+ break;
+ case StringParseState::kProtocol:
+ result_->setProtocol(MakeComponentString());
+ break;
+ case StringParseState::kAuthority:
+ // No component to set when transitioning from this state.
+ break;
+ case StringParseState::kUsername:
+ result_->setUsername(MakeComponentString());
+ break;
+ case StringParseState::kPassword:
+ result_->setPassword(MakeComponentString());
+ break;
+ case StringParseState::kHostname:
+ result_->setHostname(MakeComponentString());
+ break;
+ case StringParseState::kPort:
+ result_->setPort(MakeComponentString());
+ break;
+ case StringParseState::kPathname:
+ result_->setPathname(MakeComponentString());
+ break;
+ case StringParseState::kSearch:
+ result_->setSearch(MakeComponentString());
+ break;
+ case StringParseState::kHash:
+ result_->setHash(MakeComponentString());
+ break;
+ case StringParseState::kDone:
+ NOTREACHED();
+ break;
+ }
+
+ ChangeStateWithoutSettingComponent(new_state, skip);
+}
+
+void Parser::ChangeStateWithoutSettingComponent(StringParseState new_state,
+ Skip skip) {
+ state_ = new_state;
+
+ // Now update `component_start_` to point to the new component. The `skip`
+ // argument tells us how many tokens to ignore to get to the next start.
+ component_start_ = token_index_ + skip.value();
+
+ // Next, move the `token_index_` so that the top of the loop will begin
+ // parsing the new component. We adjust the `token_increment_` down to
+ // zero as the skip value already takes into account moving to the start
+ // of the next component.
+ token_index_ += skip.value();
+ token_increment_ = 0;
+}
+
+void Parser::Rewind() {
+ token_index_ = component_start_;
+ token_increment_ = 0;
+}
+
+void Parser::RewindAndSetState(StringParseState new_state) {
+ Rewind();
+ state_ = new_state;
+}
+
+const liburlpattern::Token& Parser::SafeToken(size_t index) const {
+ if (index < token_list_.size())
+ return token_list_[index];
+ DCHECK(!token_list_.empty());
+ DCHECK(token_list_.back().type == liburlpattern::TokenType::kEnd);
+ return token_list_.back();
+}
+
+bool Parser::IsNonSpecialPatternChar(size_t index, const char* value) const {
+ const liburlpattern::Token& token = SafeToken(index);
+ return token.value == value &&
+ (token.type == liburlpattern::TokenType::kChar ||
+ token.type == liburlpattern::TokenType::kEscapedChar ||
+ token.type == liburlpattern::TokenType::kInvalidChar);
+}
+
+bool Parser::IsProtocolSuffix() const {
+ return IsNonSpecialPatternChar(token_index_, ":");
+}
+
+bool Parser::NextIsAuthoritySlashes() const {
+ return IsNonSpecialPatternChar(token_index_ + 1, "/") &&
+ IsNonSpecialPatternChar(token_index_ + 2, "/");
+}
+
+bool Parser::IsIdentityTerminator() const {
+ return IsNonSpecialPatternChar(token_index_, "@");
+}
+
+bool Parser::IsPasswordPrefix() const {
+ return IsNonSpecialPatternChar(token_index_, ":");
+}
+
+bool Parser::IsPortPrefix() const {
+ return IsNonSpecialPatternChar(token_index_, ":");
+}
+
+bool Parser::IsPathnameStart() const {
+ return IsNonSpecialPatternChar(token_index_, "/");
+}
+
+bool Parser::IsSearchPrefix() const {
+ if (IsNonSpecialPatternChar(token_index_, "?"))
+ return true;
+
+ if (token_list_[token_index_].value != "?")
+ return false;
+
+ // If we have a "?" that is not a normal character, then it must be an
+ // optional group modifier.
+ DCHECK_EQ(SafeToken(token_index_).type,
+ liburlpattern::TokenType::kOtherModifier);
+
+ // We have a `?` tokenized as a modifier. We only want to treat this as
+ // the search prefix if it would not normally be valid in a liburlpattern
+ // string. A modifier must follow a matching group. Therefore we inspect
+ // the preceding token to see if the `?` is immediately following a group
+ // construct.
+ //
+ // So if the string is:
+ //
+ // https://example.com/foo?bar
+ //
+ // Then we return true because the previous token is a `o` with type kChar.
+ // For the string:
+ //
+ // https://example.com/:name?bar
+ //
+ // Then we return false because the previous token is `:name` with type
+ // kName. If the developer intended this to be a search prefix then they
+ // would need to escape like question mark like `:name\\?bar`.
+ //
+ // Note, if `token_index_` is zero the index will wrap around and
+ // `SafeToken()` will return the kEnd token. This will correctly return true
+ // from this method as a pattern cannot normally begin with an unescaped `?`.
+ const auto& previous_token = SafeToken(token_index_ - 1);
+ return previous_token.type != liburlpattern::TokenType::kName &&
+ previous_token.type != liburlpattern::TokenType::kRegex &&
+ previous_token.type != liburlpattern::TokenType::kClose &&
+ previous_token.type != liburlpattern::TokenType::kAsterisk;
+}
+
+bool Parser::IsHashPrefix() const {
+ return IsNonSpecialPatternChar(token_index_, "#");
+}
+
+bool Parser::IsGroupOpen() const {
+ return token_list_[token_index_].type == liburlpattern::TokenType::kOpen;
+}
+
+bool Parser::IsGroupClose() const {
+ return token_list_[token_index_].type == liburlpattern::TokenType::kClose;
+}
+
+String Parser::MakeComponentString() const {
+ DCHECK_LT(token_index_, token_list_.size());
+ const auto& token = token_list_[token_index_];
+
+ size_t component_char_start = SafeToken(component_start_).index;
+
+ DCHECK_LE(component_char_start, utf8_.size());
+ DCHECK_GE(token.index, component_char_start);
+ DCHECK(token.index < utf8_.size() ||
+ (token.index == utf8_.size() &&
+ token.type == liburlpattern::TokenType::kEnd));
+
+ return String::FromUTF8(utf8_.data() + component_char_start,
+ token.index - component_char_start);
+}
+
+void Parser::ComputeShouldTreatAsStandardURL(ExceptionState& exception_state) {
+ DCHECK_EQ(state_, StringParseState::kProtocol);
+ protocol_component_ =
+ Component::Compile(MakeComponentString(), Component::Type::kProtocol,
+ /*protocol_component=*/nullptr, exception_state);
+ if (protocol_component_ && protocol_component_->ShouldTreatAsStandardURL())
+ should_treat_as_standard_url_ = true;
+}
+
+} // namespace url_pattern
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.h b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.h
new file mode 100644
index 00000000000..c3392018b79
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/url_pattern/url_pattern_parser.h
@@ -0,0 +1,192 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_PARSER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_PARSER_H_
+
+#include <vector>
+
+#include "base/types/strong_alias.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.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 liburlpattern {
+struct Token;
+} // namespace liburlpattern
+
+namespace blink {
+
+class ExceptionState;
+class URLPatternInit;
+
+namespace url_pattern {
+
+class Component;
+
+// A helper class to parse the first string passed to the URLPattern
+// constructor. In general the parser works by using the liburlpattern
+// tokenizer to first split up the input into pattern tokens. It can
+// then look through the tokens to find non-special characters that match
+// the different URL component separators. Each component is then split
+// off and stored in a `URLPatternInit` object that can be accessed via
+// `GetResult()`. The intent is that this init object should then be
+// processed as if it was passed into the constructor itself.
+class Parser final {
+ STACK_ALLOCATED();
+
+ public:
+ explicit Parser(const String& input);
+
+ // Attempt to parse the input string used to construct the Parser object.
+ // This method may only be called once. Any errors will be thrown on the
+ // give `exception_state`. Retrieve the parse result by calling
+ // `GetResult()`. A protocol component will also be eagerly compiled for
+ // absolute pattern strings. It is not compiled for relative pattern string.
+ // The compiled protocol Component can be accessed by calling
+ // `GetProtocolComponent()`.
+ void Parse(ExceptionState& exception_state);
+
+ // Return the parse result. Should only be called after `Parse()` succeeds.
+ URLPatternInit* GetResult() const { return result_; }
+
+ // Return the protocol component if it was compiled as part of parsing the
+ // input string. This should only be called after `Parse()` succeeds.
+ // This will return nullptr if the input was a relative pattern string.
+ Component* GetProtocolComponent() const { return protocol_component_; }
+
+ private:
+ enum class StringParseState {
+ kInit,
+ kProtocol,
+ kAuthority,
+ kUsername,
+ kPassword,
+ kHostname,
+ kPort,
+ kPathname,
+ kSearch,
+ kHash,
+ kDone,
+ };
+
+ using Skip = base::StrongAlias<class SkipTag, int>;
+
+ // A utility function to move from the current `state_` to `new_state`. This
+ // method will populate the component string in `result_` corresponding to the
+ // current `state_` automatically. It will also set `component_start_` and
+ // `token_index_` to point to the first token of the next section based on how
+ // many tokens the `skip` argument indicates should be ignored.
+ void ChangeState(StringParseState new_state, Skip skip);
+
+ // A utility function to move to `new_state`. This is like `ChangeState()`,
+ // but does not automatically set the component string for the current state.
+ void ChangeStateWithoutSettingComponent(StringParseState new_state,
+ Skip skip);
+
+ // Rewind the `token_index_` back to the current `component_start_`.
+ void Rewind();
+
+ // Like `Rewind()`, but also sets the state. This is used for cases where
+ // the parser needs to "look ahead" to determine what parse state to enter.
+ void RewindAndSetState(StringParseState new_state);
+
+ // Attempt to access the Token at the given `index`. If the `index` is out
+ // of bounds for the `token_list_`, then the last Token in the list is
+ // returned. This will always be a `TokenType::kEnd` token.
+ const liburlpattern::Token& SafeToken(size_t index) const;
+
+ // Returns true if the token at the given `index` is not a special pattern
+ // character and if it matches the given `value`. This simply checks that the
+ // token type is kChar, kEscapedChar, or kInvalidChar.
+ bool IsNonSpecialPatternChar(size_t index, const char* value) const;
+
+ // Returns true if the token at the given `index` is the protocol component
+ // suffix; e.g. ':'.
+ bool IsProtocolSuffix() const;
+
+ // Returns true if the next two tokens are slashes; e.g. `//`.
+ bool NextIsAuthoritySlashes() const;
+
+ // Returns true if the tokan at the given `index` is the `@` character used
+ // to separate username and password from the hostname.
+ bool IsIdentityTerminator() const;
+
+ // Returns true if the current token is the password prefix; e.g. `:`.
+ bool IsPasswordPrefix() const;
+
+ // Returns true if the current token is the port prefix; e.g. `:`.
+ bool IsPortPrefix() const;
+
+ // Returns true if the current token is the start of the pathname; e.g. `/`.
+ bool IsPathnameStart() const;
+
+ // Returns true if the current token is the search component prefix; e.g. `?`.
+ // This also takes into account if this could be a valid pattern modifier by
+ // looking at the preceding tokens.
+ bool IsSearchPrefix() const;
+
+ // Returns true if the current token is the hsah component prefix; e.g. `#`.
+ bool IsHashPrefix() const;
+
+ // These methods indicate if the current token is opening or closing a pattern
+ // grouping; e.g. `{` or `}`.
+ bool IsGroupOpen() const;
+ bool IsGroupClose() const;
+
+ // This method returns a String consisting of the tokens between
+ // `component_start_` and the current `token_index_`.
+ String MakeComponentString() const;
+
+ // Returns true if this URL should be treated as a "standard URL". These URLs
+ // automatically append a `/` for the pathname if one is not specified.
+ void ComputeShouldTreatAsStandardURL(ExceptionState& exception_state);
+
+ // The input string to the parser.
+ const String input_;
+
+ // UTF8 representation of `input_`.
+ const StringUTF8Adaptor utf8_;
+
+ // As we parse the input string we populate a `URLPatternInit` dictionary
+ // with each component pattern. This is then the final result of the parse.
+ URLPatternInit* result_ = nullptr;
+
+ // The compiled Component for the protocol. This is generated for absolute
+ // strings where we need to determine if the value should be treated as
+ // a "standard" URL.
+ Component* protocol_component_ = nullptr;
+
+ // The list of Tokens produced by calling `liburlpattern::Tokenize()` on
+ // `input_`.
+ std::vector<liburlpattern::Token> token_list_;
+
+ // The index of the first Token to include in the component string.
+ size_t component_start_ = 0;
+
+ // The index of the current Token being considered.
+ size_t token_index_ = 0;
+
+ // The value to add to `token_index_` on each turn the through the parse
+ // loop. While typically this is `1`, it is also set to `0` at times for
+ // things like state transitions, etc. It is automatically reset back to
+ // `1` at the top of the parse loop.
+ size_t token_increment_ = 1;
+
+ // The current nesting depth of `{ }` pattern groupings.
+ int group_depth_ = 0;
+
+ // The current parse state. This should only be changed via `ChangeState()`
+ // or `RewindAndSetState()`.
+ StringParseState state_ = StringParseState::kInit;
+
+ // True if we should apply parse rules as if this is a "standard" URL. If
+ // false then this is treated as a "not a base URL" or "path" URL.
+ bool should_treat_as_standard_url_ = false;
+};
+
+} // namespace url_pattern
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_URL_PATTERN_URL_PATTERN_PARSER_H_
diff --git a/chromium/third_party/blink/renderer/modules/vibration/OWNERS b/chromium/third_party/blink/renderer/modules/vibration/OWNERS
deleted file mode 100644
index 02b971fe8f5..00000000000
--- a/chromium/third_party/blink/renderer/modules/vibration/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-mvanouwerkerk@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/vibration/idls.gni b/chromium/third_party/blink/renderer/modules/vibration/idls.gni
deleted file mode 100644
index 41a2729d594..00000000000
--- a/chromium/third_party/blink/renderer/modules/vibration/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dependency_idl_files = [ "navigator_vibration.idl" ]
-
-modules_testing_dependency_idl_files = [ "testing/internals_vibration.idl" ]
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 07fb22fbad1..bcab4620f66 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
@@ -19,10 +19,11 @@
#include "third_party/blink/renderer/modules/vibration/vibration_controller.h"
+#include "base/metrics/histogram_functions.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_or_unsigned_long_sequence.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_unsignedlong_unsignedlongsequence.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"
@@ -103,15 +104,21 @@ void CollectHistogramMetrics(LocalDOMWindow* window) {
// static
VibrationController::VibrationPattern
VibrationController::SanitizeVibrationPattern(
- const UnsignedLongOrUnsignedLongSequence& input) {
- VibrationPattern pattern;
-
- if (input.IsUnsignedLong())
- pattern.push_back(input.GetAsUnsignedLong());
- else if (input.IsUnsignedLongSequence())
- pattern = input.GetAsUnsignedLongSequence();
-
- return sanitizeVibrationPatternInternal(pattern);
+ const V8UnionUnsignedLongOrUnsignedLongSequence* input) {
+ switch (input->GetContentType()) {
+ case V8UnionUnsignedLongOrUnsignedLongSequence::ContentType::
+ kUnsignedLong: {
+ VibrationPattern pattern;
+ pattern.push_back(input->GetAsUnsignedLong());
+ return sanitizeVibrationPatternInternal(pattern);
+ }
+ case V8UnionUnsignedLongOrUnsignedLongSequence::ContentType::
+ kUnsignedLongSequence:
+ return sanitizeVibrationPatternInternal(
+ input->GetAsUnsignedLongSequence());
+ }
+ NOTREACHED();
+ return {};
}
// static
diff --git a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h
index 2e1fbf8c5a6..4ae49053381 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h
+++ b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h
@@ -35,7 +35,7 @@
namespace blink {
class Navigator;
-class UnsignedLongOrUnsignedLongSequence;
+class V8UnionUnsignedLongOrUnsignedLongSequence;
class MODULES_EXPORT VibrationController final
: public GarbageCollected<VibrationController>,
@@ -55,7 +55,7 @@ class MODULES_EXPORT VibrationController final
~VibrationController() override;
static VibrationPattern SanitizeVibrationPattern(
- const UnsignedLongOrUnsignedLongSequence&);
+ const V8UnionUnsignedLongOrUnsignedLongSequence* input);
void DoVibrate(TimerBase*);
void DidVibrate();
diff --git a/chromium/third_party/blink/renderer/modules/video_rvfc/idls.gni b/chromium/third_party/blink/renderer/modules/video_rvfc/idls.gni
deleted file mode 100644
index 5590aab117c..00000000000
--- a/chromium/third_party/blink/renderer/modules/video_rvfc/idls.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_callback_function_idl_files = [ "video_frame_request_callback.idl" ]
-
-modules_dictionary_idl_files = [ "video_frame_metadata.idl" ]
-
-modules_dependency_idl_files =
- [ "html_video_element_request_video_frame_callback.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc b/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc
index 8fa9f28034e..5917e763cba 100644
--- a/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc
@@ -356,7 +356,7 @@ void VideoFrameCallbackRequesterImpl::cancelVideoFrameCallback(int id) {
void VideoFrameCallbackRequesterImpl::Trace(Visitor* visitor) const {
visitor->Trace(callback_collection_);
- Supplement<HTMLVideoElement>::Trace(visitor);
+ VideoFrameCallbackRequester::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h b/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h
index 6ed659dd780..d66cf107f5b 100644
--- a/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h
+++ b/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h
@@ -24,6 +24,7 @@ class MODULES_EXPORT VideoFrameRequestCallbackCollection final
public NameClient {
public:
explicit VideoFrameRequestCallbackCollection(ExecutionContext*);
+ ~VideoFrameRequestCallbackCollection() final = default;
using CallbackId = int;
@@ -36,7 +37,7 @@ class MODULES_EXPORT VideoFrameRequestCallbackCollection final
const char* NameInHeapSnapshot() const override {
return "VideoFrameCallback";
}
- virtual ~VideoFrameCallback() = default;
+ ~VideoFrameCallback() override = default;
virtual void Invoke(double, const VideoFrameMetadata*) = 0;
diff --git a/chromium/third_party/blink/renderer/modules/virtualkeyboard/idls.gni b/chromium/third_party/blink/renderer/modules/virtualkeyboard/idls.gni
deleted file mode 100644
index 8f0c014d5f5..00000000000
--- a/chromium/third_party/blink/renderer/modules/virtualkeyboard/idls.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "virtual_keyboard.idl",
- "virtual_keyboard_geometry_change_event.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_virtual_keyboard.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/virtualkeyboard/navigator_virtual_keyboard.idl b/chromium/third_party/blink/renderer/modules/virtualkeyboard/navigator_virtual_keyboard.idl
index edf95e28fb0..5b9350b6eb7 100644
--- a/chromium/third_party/blink/renderer/modules/virtualkeyboard/navigator_virtual_keyboard.idl
+++ b/chromium/third_party/blink/renderer/modules/virtualkeyboard/navigator_virtual_keyboard.idl
@@ -10,5 +10,5 @@
ImplementedAs=VirtualKeyboard,
RuntimeEnabled=VirtualKeyboard
] partial interface Navigator {
- [SameObject] readonly attribute VirtualKeyboard virtualKeyboard;
+ [SecureContext, SameObject] readonly attribute VirtualKeyboard virtualKeyboard;
};
diff --git a/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc b/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc
index 03a07efbdb8..0c0b93f892e 100644
--- a/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc
+++ b/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.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"
diff --git a/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.idl b/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.idl
index 384f023f5b7..d773c9e5f05 100644
--- a/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.idl
+++ b/chromium/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.idl
@@ -8,6 +8,7 @@
[
Exposed=Window,
+ SecureContext,
RuntimeEnabled=VirtualKeyboard
] interface VirtualKeyboard : EventTarget {
void show();
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/README.md b/chromium/third_party/blink/renderer/modules/wake_lock/README.md
index 4e61ecee42f..99a018cc991 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/README.md
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/README.md
@@ -6,7 +6,7 @@ This directory contains an implementation of the [Wake Lock specification], a We
At the time of writing (October 2019), system wake lock requests are always denied, as allowing them depends on a proper permission model for the requests being figured out first.
-The code required to implement the Wake Lock API is spread across multiple Chromium subsystems: Blink, `//content`, `//services` and `//chrome`. This document focuses on the Blink part, and the other subsystems are mentioned when necessary but without much detail.
+The code required to implement the Wake Lock API is spread across multiple Chromium subsystems: Blink, `//content`, `//components`, `//services` and `//chrome`. This document focuses on the Blink part, and the other subsystems are mentioned when necessary but without much detail.
## High level overview
@@ -34,7 +34,7 @@ The rest of the implementation is found in the following directories:
* `content/browser/wake_lock` [implements](/content/browser/wake_lock/wake_lock_service_impl.cc) the [`WakeLockService`](../../../public/mojom/wake_lock/wake_lock.mojom) Mojo interface defined in Blink. It is responsible for communicating with Blink and connecting Blink to `services/device/wake_lock`.
* `services/device/wake_lock` contains the [platform-specific parts of the implementation](../../../../../services/device/wake_lock/power_save_blocker) and implements the Wake Lock [Mojo interfaces].
-* `chrome/browser/wake_lock` contains the Chrome-specific side of permission management for Wake Locks. When the Blink implementation needs to either query or request permission for wake locks, the request bubbles up to this directory, where the decision is made based on the wake lock type (for testing purposes, `content_shell` always grants screen wake locks and denies system wake locks in [`shell_permission_manager.cc`](/content/shell/browser/web_test/web_test_message_filter.cc)).
+* `components/permissions/contexts` contains the permission management for Wake Locks. When the Blink implementation needs to either query or request permission for wake locks, the request bubbles up to this directory, where the decision is made based on the wake lock type (for testing purposes, `content_shell` always grants screen wake locks and denies system wake locks in [`shell_permission_manager.cc`](/content/shell/browser/web_test/web_test_message_filter.cc)).
[Mojo interfaces]: ../../../../../services/device/public/mojom/
[Wake Lock management]: https://w3c.github.io/screen-wake-lock/#managing-wake-locks
@@ -48,7 +48,8 @@ Larger parts of the Blink implementation are tested as browser and unit tests:
* `*_test.cc` and `wake_lock_test_utils.{cc,h}` are built as part of the `blink_unittests` GN target, and attempt to have coverage over most of the code in this directory.
* The unit tests in `services/device/wake_lock` test the service side of the API implementation.
-* `chrome/browser/wake_lock` has unit tests for `WakeLockPermissionContext`, and browser tests for end-to-end behavior testing.
+* `chrome/browser/wake_lock` has browser tests for end-to-end behavior testing.
+* `components/permissions/contexts` has unit tests for `WakeLockPermissionContext`.
* content_shell implements its own permission logic that mimics what is done in `//chrome` in [`shell_permission_manager.cc`](/content/shell/browser/shell_permission_manager.cc).
[web platform tests]: ../../../web_tests/external/wpt/screen-wake-lock/
@@ -67,7 +68,7 @@ const lock = await navigator.wakeLock.request("screen");
1. `WakeLock::request()` performs all the validation steps described in [the spec](https://w3c.github.io/screen-wake-lock/#the-request-method). If all checks have passed, it creates a `ScriptPromiseResolver` and calls `WakeLock::DoRequest()`.
1. `WakeLock::DoRequest()` simply forwards its arguments to `WakeLock::ObtainPermission()`. It exists as a separate method just to make writing unit tests easier, as we'd otherwise be unable to use our own `ScriptPromiseResolver`s in tests.
1. `WakeLock::ObtainPermission()` connects to the [permission service](../../../public/mojom/permissions/permission.mojom) and asynchronously requests permission for a screen wake lock.
-1. In the browser process, the permission request bubbles up through `//content` and reaches `//chrome`'s [`WakeLockPermissionContext`](/chrome/browser/wake_lock/wake_lock_permission_context.cc), where `WakeLockPermissionContext::GetPermissionStatusInternal()` always grants `CONTENT_SETTINGS_TYPE_WAKE_LOCK_SCREEN` permission requests.
+1. In the browser process, the permission request bubbles up through `//content` and reaches [`WakeLockPermissionContext`](/components/permissions/contexts/wake_lock_permission_context.cc), where `WakeLockPermissionContext::GetPermissionStatusInternal()` always grants `CONTENT_SETTINGS_TYPE_WAKE_LOCK_SCREEN` permission requests.
1. Back in Blink, the permission request callback in this case is `WakeLock::DidReceivePermissionResponse()`. It performs some sanity checks such as verifying if the page visibility changed while waiting for the permission request to be processed. If any of the checks fail, or if the permission request was denied, the `ScriptPromiseResolver` instance created earlier by `WakeLock::request()` is rejected and we stop here. If everything went well, `WakeLockManager::AcquireWakeLock()` is called.
1. If there are no existing screen wake locks, `WakeLockManager::AcquireWakeLock()` will connect to the `WakeLockService` Mojo interface, invoke its `GetWakeLock()` method to obtain a `device::mojom::blink::WakeLock` and call its `RequestWakeLock()` method.
1. `WakeLockManager::AcquireWakeLock()` creates a new `WakeLockSentinel` instance, passing `this` as the `WakeLockSentinel`'s `WakeLockManager`. This new `WakeLockSentinel` is added to its set of [active locks].
@@ -136,4 +137,4 @@ In the Chromium implementation, there currently is no "prompt" state, and no per
* Screen wake lock request are always granted without prompting or user activation checks. This is based on the existing precedent of the `<video>` tag's use of `VideoWakeLock`s: they are always requested and granted transparently, so even if the Wake Lock API implementation in Chromium started requiring stricter checks, malicious actors could still embed a `<video>` tag and prevent the screen from turning off without any user interaction.
-* System wake lock requests are always denied in `chrome/browser/wake_lock/wake_lock_permission_context.cc`. This means the entirety of the code is present and enabled in Blink, but all calls to `WakeLock.request('system')` currently return a promise that will be rejected with a `NotAllowedError`. Changing that requires figuring out a permission model for system wake lock requests, which, at the moment, is future work.
+* System wake lock requests are always denied in `components/permissions/contexts/wake_lock_permission_context.cc`. This means the entirety of the code is present and enabled in Blink, but all calls to `WakeLock.request('system')` currently return a promise that will be rejected with a `NotAllowedError`. Changing that requires figuring out a permission model for system wake lock requests, which, at the moment, is future work.
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/idls.gni b/chromium/third_party/blink/renderer/modules/wake_lock/idls.gni
deleted file mode 100644
index 685f7209b06..00000000000
--- a/chromium/third_party/blink/renderer/modules/wake_lock/idls.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-modules_idl_files = [
- "wake_lock.idl",
- "wake_lock_sentinel.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_wake_lock.idl",
- "worker_navigator_wake_lock.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
index 41446c7a760..b5fc3645f83 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
@@ -154,11 +154,25 @@ ScriptPromise WakeLock::request(ScriptState* script_state,
void WakeLock::DoRequest(WakeLockType type, ScriptPromiseResolver* resolver) {
// https://w3c.github.io/screen-wake-lock/#the-request-method
- // 8.1. Let state be the result of invoking obtain permission with
+ // 8.1. Let state be the result of requesting permission to use
// "screen-wake-lock".
- ObtainPermission(
- type, WTF::Bind(&WakeLock::DidReceivePermissionResponse,
- WrapPersistent(this), type, WrapPersistent(resolver)));
+ mojom::blink::PermissionName permission_name;
+ switch (type) {
+ case WakeLockType::kScreen:
+ permission_name = mojom::blink::PermissionName::SCREEN_WAKE_LOCK;
+ break;
+ case WakeLockType::kSystem:
+ permission_name = mojom::blink::PermissionName::SYSTEM_WAKE_LOCK;
+ break;
+ }
+
+ auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext());
+ auto* local_frame = window ? window->GetFrame() : nullptr;
+ GetPermissionService()->RequestPermission(
+ CreatePermissionDescriptor(permission_name),
+ LocalFrame::HasTransientUserActivation(local_frame),
+ WTF::Bind(&WakeLock::DidReceivePermissionResponse, WrapPersistent(this),
+ type, WrapPersistent(resolver)));
}
void WakeLock::DidReceivePermissionResponse(WakeLockType type,
@@ -225,34 +239,6 @@ void WakeLock::PageVisibilityChanged() {
manager->ClearWakeLocks();
}
-void WakeLock::ObtainPermission(
- WakeLockType type,
- base::OnceCallback<void(PermissionStatus)> callback) {
- // https://w3c.github.io/screen-wake-lock/#dfn-obtain-permission
- // Note we actually implement a simplified version of the "obtain permission"
- // algorithm that essentially just calls the "request permission to use"
- // algorithm from the Permissions spec (i.e. we do not take user activation
- // into account, nor do we consider "prompt" is a valid permission state).
- // Right now, we can do that because there is no way for Chromium's
- // permission system to get to the "prompt" state given how
- // WakeLockPermissionContext is currently implemented.
- mojom::blink::PermissionName permission_name;
- switch (type) {
- case WakeLockType::kScreen:
- permission_name = mojom::blink::PermissionName::SCREEN_WAKE_LOCK;
- break;
- case WakeLockType::kSystem:
- permission_name = mojom::blink::PermissionName::SYSTEM_WAKE_LOCK;
- break;
- }
-
- auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext());
- auto* local_frame = window ? window->GetFrame() : nullptr;
- GetPermissionService()->RequestPermission(
- CreatePermissionDescriptor(permission_name),
- LocalFrame::HasTransientUserActivation(local_frame), std::move(callback));
-}
-
PermissionService* WakeLock::GetPermissionService() {
if (!permission_service_.is_bound()) {
ConnectToPermissionService(
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.h b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.h
index 86b61674c61..76e9ebb5618 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.h
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.h
@@ -70,9 +70,6 @@ class MODULES_EXPORT WakeLock final : public ScriptWrappable,
void PageVisibilityChanged() override;
// Permission handling
- void ObtainPermission(
- WakeLockType,
- base::OnceCallback<void(mojom::blink::PermissionStatus)> callback);
mojom::blink::PermissionService* GetPermissionService();
HeapMojoRemote<mojom::blink::PermissionService> permission_service_;
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
index c3de6fa1de8..d4e5a617487 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
@@ -37,28 +37,19 @@ void RunWithStack(base::RunLoop* run_loop) {
// Helper class for WaitForPromise{Fulfillment,Rejection}(). It provides a
// function that invokes |callback| when a ScriptPromise is resolved.
-class ClosureRunnerFunction final : public ScriptFunction {
+class ClosureRunnerCallable final : public NewScriptFunction::Callable {
public:
- static v8::Local<v8::Function> CreateFunction(
- ScriptState* script_state,
- base::RepeatingClosure callback) {
- auto* function = MakeGarbageCollected<ClosureRunnerFunction>(
- script_state, std::move(callback));
- return function->BindToV8Function();
- }
-
- ClosureRunnerFunction(ScriptState* script_state,
- base::RepeatingClosure callback)
- : ScriptFunction(script_state), callback_(std::move(callback)) {}
+ explicit ClosureRunnerCallable(base::OnceClosure callback)
+ : callback_(std::move(callback)) {}
- private:
- ScriptValue Call(ScriptValue) override {
+ ScriptValue Call(ScriptState*, ScriptValue) override {
if (callback_)
std::move(callback_).Run();
return ScriptValue();
}
- base::RepeatingClosure callback_;
+ private:
+ base::OnceClosure callback_;
};
WakeLockType ToBlinkWakeLockType(device::mojom::blink::WakeLockType type) {
@@ -295,25 +286,25 @@ MockPermissionService& WakeLockTestingContext::GetPermissionService() {
return permission_service_;
}
-ScriptPromise WakeLockTestingContext::WaitForPromiseFulfillment(
- ScriptPromise promise) {
+void WakeLockTestingContext::WaitForPromiseFulfillment(ScriptPromise promise) {
base::RunLoop run_loop;
- ScriptPromise return_promise =
- promise.Then(ClosureRunnerFunction::CreateFunction(
- GetScriptState(), run_loop.QuitClosure()));
+ promise.Then(MakeGarbageCollected<NewScriptFunction>(
+ GetScriptState(),
+ MakeGarbageCollected<ClosureRunnerCallable>(run_loop.QuitClosure())));
// Execute pending microtasks, otherwise it can take a few seconds for the
// promise to resolve.
v8::MicrotasksScope::PerformCheckpoint(GetScriptState()->GetIsolate());
RunWithStack(&run_loop);
- return return_promise;
}
// Synchronously waits for |promise| to be rejected.
void WakeLockTestingContext::WaitForPromiseRejection(ScriptPromise promise) {
base::RunLoop run_loop;
- promise.Then(v8::Local<v8::Function>(),
- ClosureRunnerFunction::CreateFunction(GetScriptState(),
- run_loop.QuitClosure()));
+ promise.Then(
+ nullptr,
+ MakeGarbageCollected<NewScriptFunction>(
+ GetScriptState(),
+ MakeGarbageCollected<ClosureRunnerCallable>(run_loop.QuitClosure())));
// Execute pending microtasks, otherwise it can take a few seconds for the
// promise to resolve.
v8::MicrotasksScope::PerformCheckpoint(GetScriptState()->GetIsolate());
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h
index 4b5114be678..ddd6bf89193 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h
@@ -160,7 +160,7 @@ class WakeLockTestingContext final {
MockPermissionService& GetPermissionService();
// Synchronously waits for |promise| to be fulfilled.
- ScriptPromise WaitForPromiseFulfillment(ScriptPromise promise);
+ void WaitForPromiseFulfillment(ScriptPromise promise);
// Synchronously waits for |promise| to be rejected.
void WaitForPromiseRejection(ScriptPromise promise);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/OWNERS b/chromium/third_party/blink/renderer/modules/webaudio/OWNERS
index a837fc9b778..5248064ba91 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/webaudio/OWNERS
@@ -1,2 +1 @@
hongchan@chromium.org
-rtoy@chromium.org
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 5359becd83e..7d717a83f53 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/modules/webaudio/analyser_node.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_analyser_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 948e7672796..6487453f55f 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
@@ -28,6 +28,7 @@
#include "base/numerics/safe_conversions.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_buffer_source_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 7466cefbdc6..6b2ae86a518 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/webaudio/audio_context.h"
#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
@@ -14,6 +15,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_context_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_timestamp.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_audiocontextlatencycategory_double.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -103,18 +105,23 @@ AudioContext* AudioContext::Create(Document& document,
WebFeature::kAudioContextCrossOriginIframe);
WebAudioLatencyHint latency_hint(WebAudioLatencyHint::kCategoryInteractive);
- if (context_options->latencyHint().IsAudioContextLatencyCategory()) {
- latency_hint = WebAudioLatencyHint(
- context_options->latencyHint().GetAsAudioContextLatencyCategory());
- } else if (context_options->latencyHint().IsDouble()) {
- // This should be the requested output latency in seconds, without taking
- // into account double buffering (same as baseLatency).
- latency_hint =
- WebAudioLatencyHint(context_options->latencyHint().GetAsDouble());
-
- base::UmaHistogramTimes(
- "WebAudio.AudioContext.latencyHintMilliSeconds",
- base::TimeDelta::FromSecondsD(latency_hint.Seconds()));
+ switch (context_options->latencyHint()->GetContentType()) {
+ case V8UnionAudioContextLatencyCategoryOrDouble::ContentType::
+ kAudioContextLatencyCategory:
+ latency_hint =
+ WebAudioLatencyHint(context_options->latencyHint()
+ ->GetAsAudioContextLatencyCategory()
+ .AsString());
+ break;
+ case V8UnionAudioContextLatencyCategoryOrDouble::ContentType::kDouble:
+ // This should be the requested output latency in seconds, without taking
+ // into account double buffering (same as baseLatency).
+ latency_hint =
+ WebAudioLatencyHint(context_options->latencyHint()->GetAsDouble());
+
+ base::UmaHistogramTimes(
+ "WebAudio.AudioContext.latencyHintMilliSeconds",
+ base::TimeDelta::FromSecondsD(latency_hint.Seconds()));
}
base::UmaHistogramEnumeration(
@@ -140,6 +147,7 @@ AudioContext* AudioContext::Create(Document& document,
return nullptr;
}
+ SCOPED_UMA_HISTOGRAM_TIMER("WebAudio.AudioContext.CreateTime");
AudioContext* audio_context =
MakeGarbageCollected<AudioContext>(document, latency_hint, sample_rate);
++g_hardware_context_count;
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 b7e88eb8ff0..fc52349b101 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
@@ -10,6 +10,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/renderer/bindings/modules/v8/v8_union_audiocontextlatencycategory_double.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/frame/local_dom_window.h"
@@ -115,15 +116,17 @@ class AudioContextTest : public PageTestBase {
TEST_F(AudioContextTest, AudioContextOptions_WebAudioLatencyHint) {
AudioContextOptions* interactive_options = AudioContextOptions::Create();
interactive_options->setLatencyHint(
- AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
- "interactive"));
+ MakeGarbageCollected<V8UnionAudioContextLatencyCategoryOrDouble>(
+ V8AudioContextLatencyCategory(
+ V8AudioContextLatencyCategory::Enum::kInteractive)));
AudioContext* interactive_context = AudioContext::Create(
GetDocument(), interactive_options, ASSERT_NO_EXCEPTION);
AudioContextOptions* balanced_options = AudioContextOptions::Create();
balanced_options->setLatencyHint(
- AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
- "balanced"));
+ MakeGarbageCollected<V8UnionAudioContextLatencyCategoryOrDouble>(
+ V8AudioContextLatencyCategory(
+ V8AudioContextLatencyCategory::Enum::kBalanced)));
AudioContext* balanced_context = AudioContext::Create(
GetDocument(), balanced_options, ASSERT_NO_EXCEPTION);
EXPECT_GT(balanced_context->baseLatency(),
@@ -131,15 +134,16 @@ TEST_F(AudioContextTest, AudioContextOptions_WebAudioLatencyHint) {
AudioContextOptions* playback_options = AudioContextOptions::Create();
playback_options->setLatencyHint(
- AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
- "playback"));
+ MakeGarbageCollected<V8UnionAudioContextLatencyCategoryOrDouble>(
+ V8AudioContextLatencyCategory(
+ V8AudioContextLatencyCategory::Enum::kPlayback)));
AudioContext* playback_context = AudioContext::Create(
GetDocument(), playback_options, ASSERT_NO_EXCEPTION);
EXPECT_GT(playback_context->baseLatency(), balanced_context->baseLatency());
AudioContextOptions* exact_too_small_options = AudioContextOptions::Create();
exact_too_small_options->setLatencyHint(
- AudioContextLatencyCategoryOrDouble::FromDouble(
+ MakeGarbageCollected<V8UnionAudioContextLatencyCategoryOrDouble>(
interactive_context->baseLatency() / 2));
AudioContext* exact_too_small_context = AudioContext::Create(
GetDocument(), exact_too_small_options, ASSERT_NO_EXCEPTION);
@@ -151,14 +155,15 @@ TEST_F(AudioContextTest, AudioContextOptions_WebAudioLatencyHint) {
2;
AudioContextOptions* exact_ok_options = AudioContextOptions::Create();
exact_ok_options->setLatencyHint(
- AudioContextLatencyCategoryOrDouble::FromDouble(exact_latency_sec));
+ MakeGarbageCollected<V8UnionAudioContextLatencyCategoryOrDouble>(
+ exact_latency_sec));
AudioContext* exact_ok_context = AudioContext::Create(
GetDocument(), exact_ok_options, ASSERT_NO_EXCEPTION);
EXPECT_EQ(exact_ok_context->baseLatency(), exact_latency_sec);
AudioContextOptions* exact_too_big_options = AudioContextOptions::Create();
exact_too_big_options->setLatencyHint(
- AudioContextLatencyCategoryOrDouble::FromDouble(
+ MakeGarbageCollected<V8UnionAudioContextLatencyCategoryOrDouble>(
playback_context->baseLatency() * 2));
AudioContext* exact_too_big_context = AudioContext::Create(
GetDocument(), exact_too_big_options, ASSERT_NO_EXCEPTION);
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 c85f6d2e26f..86c26952061 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
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/modules/webaudio/audio_destination_node.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
namespace blink {
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 cffd8612df3..383240146df 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
@@ -735,7 +735,7 @@ AudioNode* AudioNode::connect(AudioNode* destination,
if (context() != destination->context()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidAccessError,
- "cannot connect to a destination "
+ "cannot connect to an AudioNode "
"belonging to a different audio context.");
return nullptr;
}
@@ -801,7 +801,7 @@ void AudioNode::connect(AudioParam* param,
if (context() != param->Context()) {
exception_state.ThrowDOMException(
- DOMExceptionCode::kSyntaxError,
+ DOMExceptionCode::kInvalidAccessError,
"cannot connect to an AudioParam "
"belonging to a different audio context.");
return;
@@ -888,6 +888,15 @@ void AudioNode::disconnect(unsigned output_index,
void AudioNode::disconnect(AudioNode* destination,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
+
+ if (context() != destination->context()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "cannot disconnect from an AudioNode "
+ "belonging to a different audio context.");
+ return;
+ }
+
BaseAudioContext::GraphAutoLocker locker(context());
unsigned number_of_disconnections = 0;
@@ -921,6 +930,15 @@ void AudioNode::disconnect(AudioNode* destination,
unsigned output_index,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
+
+ if (context() != destination->context()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "cannot disconnect from an AudioNode "
+ "belonging to a different audio context.");
+ return;
+ }
+
BaseAudioContext::GraphAutoLocker locker(context());
if (output_index >= numberOfOutputs()) {
@@ -962,6 +980,15 @@ void AudioNode::disconnect(AudioNode* destination,
unsigned input_index,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
+
+ if (context() != destination->context()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "cannot disconnect from an AudioNode "
+ "belonging to a different audio context.");
+ return;
+ }
+
BaseAudioContext::GraphAutoLocker locker(context());
if (output_index >= numberOfOutputs()) {
@@ -1004,6 +1031,15 @@ void AudioNode::disconnect(AudioNode* destination,
void AudioNode::disconnect(AudioParam* destination_param,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
+
+ if (context() != destination_param->Context()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "cannot disconnect from an AudioParam "
+ "belonging to a different audio context.");
+ return;
+ }
+
BaseAudioContext::GraphAutoLocker locker(context());
// The number of disconnection made.
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 c1fe3160917..6126000a439 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
@@ -30,7 +30,6 @@
#include "base/memory/scoped_refptr.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/webaudio/audio_graph_tracer.h"
#include "third_party/blink/renderer/modules/webaudio/inspector_helper_mixin.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
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 45e00ef9472..671a079fcb0 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -267,17 +267,19 @@ static void HandleNaNValues(float* values,
}
#elif defined(CPU_ARM_NEON)
if (number_of_values >= 4) {
- uint32x4_t defaults = static_cast<uint32x4_t>(vdupq_n_f32(default_value));
+ uint32x4_t defaults =
+ reinterpret_cast<uint32x4_t>(vdupq_n_f32(default_value));
for (k = 0; k < number_of_values; k += 4) {
float32x4_t v = vld1q_f32(values + k);
// Returns true (all ones) if v is not NaN
uint32x4_t is_not_nan = vceqq_f32(v, v);
// Get the parts that are not NaN
- uint32x4_t result = vandq_u32(is_not_nan, v);
+ uint32x4_t result =
+ vandq_u32(is_not_nan, reinterpret_cast<uint32x4_t>(v));
// Replace the parts that are NaN with the default and merge with previous
// result. (Note: vbic_u32(x, y) = x and not y)
result = vorrq_u32(result, vbicq_u32(defaults, is_not_nan));
- vst1q_f32(values + k, static_cast<float32x4_t>(result));
+ vst1q_f32(values + k, reinterpret_cast<float32x4_t>(result));
}
}
#endif
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 317af7305c5..55e36732e08 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
@@ -699,6 +699,9 @@ void AudioParamTimeline::CancelScheduledValues(
ExceptionState& exception_state) {
DCHECK(IsMainThread());
+ if (!IsNonNegativeAudioParamTime(cancel_time, exception_state))
+ return;
+
MutexLocker locker(events_lock_);
// Remove all events starting at startTime.
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h
index e1bff299fb0..4e2f933546e 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h
@@ -33,6 +33,11 @@
#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
namespace blink {
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 6af14ccb6d6..426e4315b8d 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
@@ -8,7 +8,6 @@
#include <utility>
#include "base/auto_reset.h"
-#include "base/stl_util.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/serialized_script_value.h"
@@ -17,6 +16,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_blink_audio_worklet_process_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_blink_audio_worklet_processor_constructor.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h"
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h"
#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
#include "third_party/blink/renderer/platform/bindings/callback_method_retriever.h"
@@ -40,6 +40,7 @@ AudioWorkletGlobalScope::~AudioWorkletGlobalScope() = default;
void AudioWorkletGlobalScope::Dispose() {
DCHECK(IsContextThread());
+ object_proxy_ = nullptr;
is_closing_ = true;
WorkletGlobalScope::Dispose();
}
@@ -52,19 +53,17 @@ void AudioWorkletGlobalScope::registerProcessor(
// 1. If name is an empty string, throw a NotSupportedError.
if (name.IsEmpty()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "The processor name cannot be empty.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "The processor name cannot be empty.");
return;
}
// 2. If name already exists as a key in the node name to processor
// constructor map, throw a NotSupportedError.
if (processor_definition_map_.Contains(name)) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "An AudioWorkletProcessor with name:\"" + name +
- "\" is already registered.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "An AudioWorkletProcessor with name:\"" +
+ name + "\" is already registered.");
return;
}
@@ -138,8 +137,8 @@ void AudioWorkletGlobalScope::registerProcessor(
exception_state.ThrowDOMException(
DOMExceptionCode::kNotSupportedError,
"Found a duplicate name \"" + new_param_name +
- "\" in parameterDescriptors() from the AudioWorkletProcessor " +
- "definition of \"" + name + "\".");
+ "\" in parameterDescriptors() from the AudioWorkletProcessor " +
+ "definition of \"" + name + "\".");
return;
}
@@ -154,6 +153,17 @@ void AudioWorkletGlobalScope::registerProcessor(
// 8. Append the key-value pair name → processorCtor to node name to
// processor constructor map of the associated AudioWorkletGlobalScope.
processor_definition_map_.Set(name, definition);
+
+ // 9. Queue a media element task to append the key-value pair name →
+ // parameterDescriptorSequence to the node name to parameter descriptor map
+ // of the associated BaseAudioContext.
+ if (object_proxy_) {
+ // TODO(crbug.com/1223178): |object_proxy_| is designed to outlive the
+ // global scope, so we don't need to null check but the unit test is not
+ // able to replicate the cross-thread messaging logic yet, so we skip this
+ // call in unit tests.
+ object_proxy_->SynchronizeProcessorInfoList();
+ }
}
AudioWorkletProcessor* AudioWorkletGlobalScope::CreateProcessor(
@@ -208,7 +218,7 @@ AudioWorkletProcessor* AudioWorkletGlobalScope::CreateProcessor(
AudioWorkletProcessorDefinition* AudioWorkletGlobalScope::FindDefinition(
const String& name) {
- return processor_definition_map_.at(name);
+ return processor_definition_map_.DeprecatedAtOrEmptyValue(name);
}
unsigned AudioWorkletGlobalScope::NumberOfRegisteredDefinitions() {
@@ -241,9 +251,13 @@ void AudioWorkletGlobalScope::SetSampleRate(float sample_rate) {
}
double AudioWorkletGlobalScope::currentTime() const {
- return sample_rate_ > 0.0
- ? current_frame_ / static_cast<double>(sample_rate_)
- : 0.0;
+ return sample_rate_ > 0.0 ? current_frame_ / static_cast<double>(sample_rate_)
+ : 0.0;
+}
+
+void AudioWorkletGlobalScope::SetObjectProxy(
+ AudioWorkletObjectProxy& object_proxy) {
+ object_proxy_ = &object_proxy;
}
void AudioWorkletGlobalScope::Trace(Visitor* visitor) const {
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 f6dd38283d7..c36e98cce3e 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
@@ -16,6 +16,7 @@
namespace blink {
+class AudioWorkletObjectProxy;
class AudioWorkletProcessor;
class AudioWorkletProcessorDefinition;
class CrossThreadAudioWorkletProcessorInfo;
@@ -39,7 +40,7 @@ class MODULES_EXPORT ProcessorCreationParams final {
~ProcessorCreationParams() = default;
const String& Name() const { return name_; }
- MessagePortChannel PortChannel() { return message_port_channel_; }
+ MessagePortChannel PortChannel() { return message_port_channel_; }
private:
const String name_;
@@ -82,7 +83,7 @@ class MODULES_EXPORT AudioWorkletGlobalScope final : public WorkletGlobalScope {
unsigned NumberOfRegisteredDefinitions();
std::unique_ptr<Vector<CrossThreadAudioWorkletProcessorInfo>>
- WorkletProcessorInfoListForSynchronization();
+ WorkletProcessorInfoListForSynchronization();
// Gets |processor_creation_params_| for the processor construction. If there
// is no on-going processor construction, this MUST return nullptr.
@@ -105,6 +106,8 @@ class MODULES_EXPORT AudioWorkletGlobalScope final : public WorkletGlobalScope {
return token_;
}
+ void SetObjectProxy(AudioWorkletObjectProxy&);
+
private:
bool is_closing_ = false;
@@ -125,6 +128,11 @@ class MODULES_EXPORT AudioWorkletGlobalScope final : public WorkletGlobalScope {
// Default initialized to generate a distinct token for this worklet.
const AudioWorkletToken token_;
+
+ // AudioWorkletObjectProxy manages the cross-thread messaging to
+ // AudioWorkletMessagingProxy on the main thread. AudioWorkletObjectProxy
+ // outlives AudioWorkletGlobalScope, this raw pointer is safe.
+ AudioWorkletObjectProxy* object_proxy_ = nullptr;
};
template <>
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 eaa35b1445d..23e0da652e4 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
@@ -152,8 +152,8 @@ class AudioWorkletGlobalScopeTest : public PageTestBase,
global_scope->ScriptController()->GetScriptState();
EXPECT_TRUE(script_state);
KURL js_url("https://example.com/worklet.js");
- v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- script_state->GetIsolate(), source_code, js_url);
+ v8::Local<v8::Module> module =
+ ModuleTestBase::CompileModule(script_state, source_code, js_url);
EXPECT_FALSE(module.IsEmpty());
ScriptValue exception =
ModuleRecord::Instantiate(script_state, module, js_url);
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 1bb73a34009..dcc8cbd2d86 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
@@ -6,12 +6,14 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_param_descriptor.h"
#include "third_party/blink/renderer/core/events/error_event.h"
#include "third_party/blink/renderer/core/messaging/message_channel.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
@@ -246,8 +248,8 @@ AudioWorkletNode::AudioWorkletNode(
HashMap<String, scoped_refptr<AudioParamHandler>> param_handler_map;
for (const auto& param_info : param_info_list) {
String param_name = param_info.Name().IsolatedCopy();
- AudioParamHandler::AutomationRate
- param_automation_rate(AudioParamHandler::AutomationRate::kAudio);
+ AudioParamHandler::AutomationRate param_automation_rate(
+ AudioParamHandler::AutomationRate::kAudio);
if (param_info.AutomationRate() == "k-rate")
param_automation_rate = AudioParamHandler::AutomationRate::kControl;
AudioParam* audio_param = AudioParam::Create(
@@ -269,11 +271,8 @@ AudioWorkletNode::AudioWorkletNode(
}
parameter_map_ = MakeGarbageCollected<AudioParamMap>(audio_param_map);
- SetHandler(AudioWorkletHandler::Create(*this,
- context.sampleRate(),
- name,
- param_handler_map,
- options));
+ SetHandler(AudioWorkletHandler::Create(*this, context.sampleRate(), name,
+ param_handler_map, options));
}
AudioWorkletNode* AudioWorkletNode::Create(
@@ -376,9 +375,9 @@ AudioWorkletNode* AudioWorkletNode::Create(
scoped_refptr<SerializedScriptValue> serialized_node_options =
SerializedScriptValue::Serialize(
isolate,
- ToV8(options, script_state->GetContext()->Global(), isolate),
- serialize_options,
- exception_state);
+ ToV8Traits<AudioWorkletNodeOptions>::ToV8(script_state, options)
+ .ToLocalChecked(),
+ serialize_options, exception_state);
// |serialized_node_options| can be nullptr if the option dictionary is not
// valid.
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc
index 02846cea5c0..56abb4ec576 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc
@@ -28,12 +28,13 @@ void AudioWorkletObjectProxy::DidCreateWorkerGlobalScope(
WorkerOrWorkletGlobalScope* global_scope) {
global_scope_ = To<AudioWorkletGlobalScope>(global_scope);
global_scope_->SetSampleRate(context_sample_rate_);
+ global_scope_->SetObjectProxy(*this);
}
-void AudioWorkletObjectProxy::DidEvaluateTopLevelScript(bool success) {
+void AudioWorkletObjectProxy::SynchronizeProcessorInfoList() {
DCHECK(global_scope_);
- if (!success || global_scope_->NumberOfRegisteredDefinitions() == 0)
+ if (global_scope_->NumberOfRegisteredDefinitions() == 0)
return;
std::unique_ptr<Vector<CrossThreadAudioWorkletProcessorInfo>>
@@ -43,10 +44,6 @@ void AudioWorkletObjectProxy::DidEvaluateTopLevelScript(bool success) {
if (processor_info_list->size() == 0)
return;
- // This method is called by a loading task which calls
- // WorkletModuleTreeClient::NotifyModuleTreeLoadFinished and
- // SynchronizeWorkletProcessorInfoList needs to run in FIFO order with other
- // loading tasks.
PostCrossThreadTask(
*GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalLoading),
FROM_HERE,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h
index 5f70b4cb0bb..276393bb64b 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h
@@ -12,8 +12,7 @@ namespace blink {
class AudioWorkletGlobalScope;
class AudioWorkletMessagingProxy;
-class AudioWorkletObjectProxy final
- : public ThreadedWorkletObjectProxy {
+class AudioWorkletObjectProxy final : public ThreadedWorkletObjectProxy {
public:
AudioWorkletObjectProxy(AudioWorkletMessagingProxy*,
ParentExecutionContextTaskRunners*,
@@ -21,12 +20,13 @@ class AudioWorkletObjectProxy final
// Implements WorkerReportingProxy.
void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
- void DidEvaluateTopLevelScript(bool success) override;
void WillDestroyWorkerGlobalScope() override;
+ void SynchronizeProcessorInfoList();
+
private:
CrossThreadWeakPersistent<AudioWorkletMessagingProxy>
- GetAudioWorkletMessagingProxyWeakPtr();
+ GetAudioWorkletMessagingProxyWeakPtr();
CrossThreadPersistent<AudioWorkletGlobalScope> global_scope_;
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 572f529cf6a..925e4cff701 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
@@ -37,7 +37,7 @@ class MODULES_EXPORT AudioWorkletProcessorDefinition final
const String& name,
V8BlinkAudioWorkletProcessorConstructor* constructor,
V8BlinkAudioWorkletProcessCallback* process);
- ~AudioWorkletProcessorDefinition();
+ ~AudioWorkletProcessorDefinition() final;
const String& GetName() const { return name_; }
V8BlinkAudioWorkletProcessorConstructor* ConstructorFunction() const {
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 6c12a0006ce..012510524f6 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
@@ -123,7 +123,7 @@ class AudioWorkletThreadTestBase : public PageTestBase,
ScriptState::Scope scope(script_state);
KURL js_url("https://example.com/worklet.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- script_state->GetIsolate(), "var counter = 0; ++counter;", js_url);
+ script_state, "var counter = 0; ++counter;", js_url);
EXPECT_FALSE(module.IsEmpty());
ScriptValue exception =
ModuleRecord::Instantiate(script_state, module, js_url);
@@ -417,10 +417,6 @@ class AudioWorkletThreadPriorityTest
} else {
EXPECT_EQ(actual_priority, expected_priority);
}
-#elif defined(OS_FUCHSIA)
- // The thread priority is no-op on Fuchsia. It's always NORMAL priority.
- // See crbug.com/1090245.
- EXPECT_EQ(actual_priority, base::ThreadPriority::NORMAL);
#else
EXPECT_EQ(actual_priority, expected_priority);
#endif
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 f4921715f88..037f0d64ef6 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
@@ -860,7 +860,10 @@ void BaseAudioContext::UpdateWorkletGlobalScopeOnRenderingThread() {
DCHECK(!IsMainThread());
if (TryLock()) {
- if (audio_worklet_thread_) {
+ // Even when |audio_worklet_thread_| is successfully assigned, the current
+ // render thread could still be a thread of AudioOutputDevice. Updates the
+ // the global scope only when the thread affinity is correct.
+ if (audio_worklet_thread_ && audio_worklet_thread_->IsCurrentThread()) {
AudioWorkletGlobalScope* global_scope =
To<AudioWorkletGlobalScope>(audio_worklet_thread_->GlobalScope());
DCHECK(global_scope);
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 89e5060e84f..e4233bc051f 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
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_biquad_filter_options.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 38eb05787a6..9ac2332a4c1 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
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_channel_merger_options.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 dd72c09b91a..7a426e6a570 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/modules/webaudio/channel_splitter_node.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_channel_splitter_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 1393ad1f7d5..ef77f3a1efb 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
@@ -7,6 +7,7 @@
#include <algorithm>
#include "third_party/blink/renderer/bindings/modules/v8/v8_constant_source_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 686630eb4a2..134a9fb0533 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
@@ -30,6 +30,7 @@
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_convolver_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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/audio/reverb.h"
@@ -43,7 +44,7 @@
// a good value. But, the Reverb object is multi-threaded, so we want this as
// high as possible without losing too much accuracy. Very large FFTs will have
// worse phase errors. Given these constraints 32768 is a good compromise.
-const size_t MaxFFTSize = 32768;
+const unsigned MaxFFTSize = 32768;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/cpu/arm/oscillator_kernel_neon.cc b/chromium/third_party/blink/renderer/modules/webaudio/cpu/arm/oscillator_kernel_neon.cc
index 6dc9b6ef01b..3e6bd7387ea 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/cpu/arm/oscillator_kernel_neon.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/cpu/arm/oscillator_kernel_neon.cc
@@ -56,9 +56,10 @@ std::tuple<int, double> OscillatorHandler::ProcessKRateVector(
const float32x4_t v_incr = vdupq_n_f32(4 * incr);
+ float virtual_read_index_flt = virtual_read_index;
float32x4_t v_virt_index = {
- virtual_read_index + 0 * incr, virtual_read_index + 1 * incr,
- virtual_read_index + 2 * incr, virtual_read_index + 3 * incr};
+ virtual_read_index_flt + 0 * incr, virtual_read_index_flt + 1 * incr,
+ virtual_read_index_flt + 2 * incr, virtual_read_index_flt + 3 * incr};
// Temporary arrsys to hold the read indices so we can access them
// individually to get the samples needed for interpolation.
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 3e62c31cf0b..9b0e61c11ef 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_delay_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 46803a8f012..cf4127c458d 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dynamics_compressor_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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/audio/audio_utilities.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/gain_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/gain_node.cc
index 46aa865894a..ed374a443bd 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/gain_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/gain_node.cc
@@ -24,7 +24,9 @@
*/
#include "third_party/blink/renderer/modules/webaudio/gain_node.h"
+
#include "third_party/blink/renderer/bindings/modules/v8/v8_gain_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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/audio/audio_bus.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/idls.gni b/chromium/third_party/blink/renderer/modules/webaudio/idls.gni
deleted file mode 100644
index 50e6ee361a0..00000000000
--- a/chromium/third_party/blink/renderer/modules/webaudio/idls.gni
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "analyser_node.idl",
- "audio_buffer.idl",
- "audio_buffer_source_node.idl",
- "audio_context.idl",
- "audio_destination_node.idl",
- "audio_listener.idl",
- "audio_node.idl",
- "audio_param.idl",
- "audio_param_map.idl",
- "audio_processing_event.idl",
- "audio_scheduled_source_node.idl",
- "audio_worklet.idl",
- "audio_worklet_global_scope.idl",
- "audio_worklet_node.idl",
- "audio_worklet_processor.idl",
- "base_audio_context.idl",
- "biquad_filter_node.idl",
- "channel_merger_node.idl",
- "channel_splitter_node.idl",
- "constant_source_node.idl",
- "convolver_node.idl",
- "delay_node.idl",
- "dynamics_compressor_node.idl",
- "gain_node.idl",
- "iir_filter_node.idl",
- "media_element_audio_source_node.idl",
- "media_stream_audio_destination_node.idl",
- "media_stream_audio_source_node.idl",
- "offline_audio_completion_event.idl",
- "offline_audio_context.idl",
- "oscillator_node.idl",
- "panner_node.idl",
- "periodic_wave.idl",
- "script_processor_node.idl",
- "stereo_panner_node.idl",
- "wave_shaper_node.idl",
-]
-
-modules_dictionary_idl_files = [
- "analyser_options.idl",
- "audio_buffer_options.idl",
- "audio_buffer_source_options.idl",
- "audio_context_options.idl",
- "audio_node_options.idl",
- "audio_param_descriptor.idl",
- "audio_processing_event_init.idl",
- "audio_timestamp.idl",
- "audio_worklet_node_options.idl",
- "biquad_filter_options.idl",
- "channel_merger_options.idl",
- "channel_splitter_options.idl",
- "constant_source_options.idl",
- "convolver_options.idl",
- "delay_options.idl",
- "dynamics_compressor_options.idl",
- "gain_options.idl",
- "iir_filter_options.idl",
- "media_element_audio_source_options.idl",
- "media_stream_audio_source_options.idl",
- "offline_audio_completion_event_init.idl",
- "offline_audio_context_options.idl",
- "oscillator_options.idl",
- "panner_options.idl",
- "periodic_wave_constraints.idl",
- "periodic_wave_options.idl",
- "stereo_panner_options.idl",
- "wave_shaper_options.idl",
-]
-
-modules_testing_dependency_idl_files = [ "testing/internals_web_audio.idl" ]
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 0b61c254bc6..dc7707891a0 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
@@ -9,6 +9,7 @@
#include "base/metrics/histogram_functions.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_iir_filter_options.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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/bindings/exception_messages.h"
@@ -16,6 +17,7 @@
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
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 1f179e1665b..5cdd8fcdf0e 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
@@ -33,6 +33,7 @@
#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_context.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
@@ -185,7 +186,8 @@ void MediaElementAudioSourceHandler::ProvideResamplerInput(
DCHECK(Context()->IsAudioThread());
DCHECK(MediaElement());
DCHECK(dest);
- MediaElement()->GetAudioSourceProvider().ProvideInput(dest, dest->length());
+ MediaElement()->GetAudioSourceProvider().ProvideInput(
+ dest, base::checked_cast<int>(dest->length()));
}
void MediaElementAudioSourceHandler::Process(uint32_t number_of_frames) {
@@ -213,14 +215,15 @@ void MediaElementAudioSourceHandler::Process(uint32_t number_of_frames) {
AudioSourceProvider& provider = MediaElement()->GetAudioSourceProvider();
// Grab data from the provider so that the element continues to make
// progress, even if we're going to output silence anyway.
+ const int frames_int = base::checked_cast<int>(number_of_frames);
if (multi_channel_resampler_.get()) {
DCHECK_NE(source_sample_rate_, Context()->sampleRate());
- multi_channel_resampler_->Resample(number_of_frames, output_bus);
+ multi_channel_resampler_->Resample(frames_int, output_bus);
} else {
// Bypass the resampler completely if the source is at the context's
// sample-rate.
DCHECK_EQ(source_sample_rate_, Context()->sampleRate());
- provider.ProvideInput(output_bus, number_of_frames);
+ provider.ProvideInput(output_bus, frames_int);
}
// Output silence if we don't have access to the element.
if (is_origin_tainted_) {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.h b/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.h
index b977f3ea6cb..909c42bccbd 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.h
@@ -30,6 +30,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_annotations.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider_client.h"
#include "third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h"
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 0725fe299a2..9787fabc899 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
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_node_options.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_utils.h"
#include "third_party/blink/renderer/modules/webaudio/audio_context.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
@@ -67,7 +68,7 @@ MediaStreamAudioDestinationHandler::MediaStreamAudioDestinationHandler(
AudioBus::Create(number_of_channels,
GetDeferredTaskHandler().RenderQuantumFrames())) {
SendLogMessage(String::Format("%s", __func__));
- source_.Lock()->SetAudioFormat(number_of_channels,
+ source_.Lock()->SetAudioFormat(static_cast<int>(number_of_channels),
node.context()->sampleRate());
SetInternalChannelCountMode(kExplicit);
Initialize();
@@ -107,7 +108,7 @@ void MediaStreamAudioDestinationHandler::Process(uint32_t number_of_frames) {
count, GetDeferredTaskHandler().RenderQuantumFrames());
// setAudioFormat has an internal lock. This can cause audio to
// glitch. This is outside of our control.
- source->SetAudioFormat(count, Context()->sampleRate());
+ source->SetAudioFormat(static_cast<int>(count), Context()->sampleRate());
}
}
@@ -115,7 +116,7 @@ void MediaStreamAudioDestinationHandler::Process(uint32_t number_of_frames) {
// consumeAudio has an internal lock (also used by setAudioFormat).
// This can cause audio to glitch. This is outside of our control.
- source->ConsumeAudio(mix_bus_.get(), number_of_frames);
+ source->ConsumeAudio(mix_bus_.get(), static_cast<int>(number_of_frames));
}
void MediaStreamAudioDestinationHandler::SetChannelCount(
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 dfad08b2701..63d13e2e179 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
@@ -29,6 +29,7 @@
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_audio_source_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_context.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -117,7 +118,8 @@ void MediaStreamAudioSourceHandler::Process(uint32_t number_of_frames) {
output_bus->Zero();
return;
}
- audio_source_provider_.get()->ProvideInput(output_bus, number_of_frames);
+ audio_source_provider_.get()->ProvideInput(
+ output_bus, base::checked_cast<int>(number_of_frames));
if (!is_processing_) {
SendLogMessage(String::Format("%s({number_of_frames=%u})", __func__,
number_of_frames));
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 40a93ecd17a..dd785d44248 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_offline_audio_context_options.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -98,6 +99,7 @@ OfflineAudioContext* OfflineAudioContext::Create(
return nullptr;
}
+ SCOPED_UMA_HISTOGRAM_TIMER("WebAudio.OfflineAudioContext.CreateTime");
OfflineAudioContext* audio_context =
MakeGarbageCollected<OfflineAudioContext>(
window->document(), number_of_channels, number_of_frames, sample_rate,
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 62edb21a483..de4d14770f0 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
@@ -27,6 +27,7 @@
#include <limits>
#include "build/build_config.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 1d8c20838ed..b8c37459c53 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_panner_options.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_graph_tracer.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"
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 2d79a732c8b..d713bd494d8 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
@@ -34,6 +34,7 @@
#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/modules/webaudio/audio_buffer.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 708378dd5f8..11b9610abf8 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
@@ -35,8 +35,13 @@
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace blink {
class AudioBuffer;
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 caeba117962..f92279495aa 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
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_stereo_panner_options.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
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 fc2e1c6a1dd..175371b160f 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
@@ -31,6 +31,7 @@
#include "build/build_config.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/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
#if defined(ARCH_CPU_X86_FAMILY)
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 5828029385e..f3debc4eef4 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
@@ -28,6 +28,7 @@
#include <memory>
#include "third_party/blink/renderer/bindings/modules/v8/v8_wave_shaper_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.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"
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/BUILD.gn b/chromium/third_party/blink/renderer/modules/webcodecs/BUILD.gn
index cfbf4dcb50f..d5fceceed4e 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/BUILD.gn
@@ -4,11 +4,13 @@
import("//media/media_options.gni")
import("//third_party/blink/renderer/modules/modules.gni")
+import("//third_party/libaom/options.gni")
import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
import("//third_party/protobuf/proto_library.gni")
blink_modules_sources("webcodecs") {
sources = [
+ "allow_shared_buffer_source_util.h",
"audio_data.cc",
"audio_data.h",
"audio_data_attachment.cc",
@@ -25,10 +27,14 @@ blink_modules_sources("webcodecs") {
"codec_state_helper.cc",
"codec_state_helper.h",
"codec_trace_names.h",
+ "decoder_buffer_attachment.cc",
+ "decoder_buffer_attachment.h",
"decoder_selector.cc",
"decoder_selector.h",
"decoder_template.cc",
"decoder_template.h",
+ "dom_rect_util.cc",
+ "dom_rect_util.h",
"encoded_audio_chunk.cc",
"encoded_audio_chunk.h",
"encoded_video_chunk.cc",
@@ -47,10 +53,12 @@ blink_modules_sources("webcodecs") {
"image_track.h",
"image_track_list.cc",
"image_track_list.h",
- "parsed_read_into_options.cc",
- "parsed_read_into_options.h",
- "plane.cc",
- "plane.h",
+ "parsed_copy_to_options.cc",
+ "parsed_copy_to_options.h",
+ "reclaimable_codec.cc",
+ "reclaimable_codec.h",
+ "video_color_space.cc",
+ "video_color_space.h",
"video_decoder.cc",
"video_decoder.h",
"video_decoder_broker.cc",
@@ -63,6 +71,8 @@ blink_modules_sources("webcodecs") {
"video_frame_attachment.h",
"video_frame_handle.cc",
"video_frame_handle.h",
+ "video_frame_monitor.cc",
+ "video_frame_monitor.h",
"video_frame_transfer_list.cc",
"video_frame_transfer_list.h",
"webcodecs_logger.cc",
@@ -73,9 +83,16 @@ blink_modules_sources("webcodecs") {
"//media/mojo:buildflags",
"//media/mojo/clients",
"//media/mojo/mojom",
+ "//third_party/libaom:libaom_buildflags",
"//third_party/libyuv:libyuv",
"//third_party/opus",
]
+ if (enable_libaom) {
+ deps += [ "//third_party/libaom" ]
+ }
+ if (media_use_libvpx) {
+ deps += [ "//third_party/libvpx" ]
+ }
if (media_use_openh264) {
deps += [ "//third_party/openh264:encoder" ]
}
@@ -93,6 +110,7 @@ source_set("unit_tests") {
"image_decoder_external_test.cc",
"video_decoder_broker_test.cc",
"video_encoder_test.cc",
+ "video_frame_monitor_test.cc",
"video_frame_test.cc",
]
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/DEPS b/chromium/third_party/blink/renderer/modules/webcodecs/DEPS
index 7c22b0f4633..fdb9c75b1a8 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/DEPS
@@ -20,6 +20,8 @@ include_rules = [
"+media/renderers",
"+media/video",
+ "+third_party/libaom",
+ "+third_party/libvpx",
"+third_party/libyuv",
"+ui/gfx/color_space.h",
@@ -40,5 +42,8 @@ specific_include_rules = {
],
"video_frame_test\.cc": [
"+components/viz/test/test_context_provider.h",
- ]
+ ],
+ "video_frame_monitor_test\.cc": [
+ "+base/run_loop.h",
+ ],
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h b/chromium/third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h
new file mode 100644
index 00000000000..a0b13e46875
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ALLOW_SHARED_BUFFER_SOURCE_UTIL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ALLOW_SHARED_BUFFER_SOURCE_UTIL_H_
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+
+namespace blink {
+
+using AllowSharedBufferSource =
+ V8UnionArrayBufferAllowSharedOrArrayBufferViewAllowShared;
+
+// Helper function for turning various DOMArray-like things into a pointer+size.
+template <typename T>
+base::span<T> AsSpan(const AllowSharedBufferSource* buffer_union) {
+ switch (buffer_union->GetContentType()) {
+ case AllowSharedBufferSource::ContentType::kArrayBufferAllowShared: {
+ auto* buffer = buffer_union->GetAsArrayBufferAllowShared();
+ return (buffer && !buffer->IsDetached())
+ ? base::span<T>(
+ reinterpret_cast<T*>(buffer->DataMaybeShared()),
+ buffer->ByteLength())
+ : base::span<T>();
+ }
+ case AllowSharedBufferSource::ContentType::kArrayBufferViewAllowShared: {
+ auto* buffer = buffer_union->GetAsArrayBufferViewAllowShared().Get();
+ return (buffer && !buffer->IsDetached())
+ ? base::span<T>(
+ reinterpret_cast<T*>(buffer->BaseAddressMaybeShared()),
+ buffer->byteLength())
+ : base::span<T>();
+ }
+ }
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ALLOW_SHARED_BUFFER_SOURCE_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.cc b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.cc
index 21e9675163a..23be8a150db 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.cc
@@ -4,37 +4,192 @@
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
+#include "base/compiler_specific.h"
+#include "base/numerics/checked_math.h"
#include "media/base/audio_buffer.h"
#include "media/base/audio_bus.h"
+#include "media/base/limits.h"
+#include "media/base/sample_format.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_copy_to_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_init.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
+namespace {
+
+absl::optional<V8AudioSampleFormat> MediaFormatToBlinkFormat(
+ media::SampleFormat media_format) {
+ using FormatEnum = V8AudioSampleFormat::Enum;
+
+ DCHECK(media_format != media::SampleFormat::kUnknownSampleFormat);
+
+ switch (media_format) {
+ case media::SampleFormat::kSampleFormatU8:
+ return V8AudioSampleFormat(FormatEnum::kU8);
+
+ case media::SampleFormat::kSampleFormatS16:
+ return V8AudioSampleFormat(FormatEnum::kS16);
+
+ case media::SampleFormat::kSampleFormatS24:
+ // TODO(crbug.com/1231633): ffmpeg automatically converts kSampleFormatS24
+ // to kSampleFormatS32, but we do not update our labelling. It's ok to
+ // treat the kSampleFormatS24 as kSampleFormatS32 until we update the
+ // labelling, since our code already treats S24 as S32.
+ FALLTHROUGH;
+ case media::SampleFormat::kSampleFormatS32:
+ return V8AudioSampleFormat(FormatEnum::kS32);
+
+ case media::SampleFormat::kSampleFormatF32:
+ return V8AudioSampleFormat(FormatEnum::kF32);
+
+ case media::SampleFormat::kSampleFormatPlanarU8:
+ return V8AudioSampleFormat(FormatEnum::kU8Planar);
+
+ case media::SampleFormat::kSampleFormatPlanarS16:
+ return V8AudioSampleFormat(FormatEnum::kS16Planar);
+
+ case media::SampleFormat::kSampleFormatPlanarS32:
+ return V8AudioSampleFormat(FormatEnum::kS32Planar);
+
+ case media::SampleFormat::kSampleFormatPlanarF32:
+ return V8AudioSampleFormat(FormatEnum::kF32Planar);
+
+ case media::SampleFormat::kSampleFormatAc3:
+ case media::SampleFormat::kSampleFormatEac3:
+ case media::SampleFormat::kSampleFormatMpegHAudio:
+ case media::SampleFormat::kUnknownSampleFormat:
+ return absl::nullopt;
+ }
+}
+
+media::SampleFormat BlinkFormatToMediaFormat(V8AudioSampleFormat blink_format) {
+ using FormatEnum = V8AudioSampleFormat::Enum;
+
+ DCHECK(!blink_format.IsEmpty());
+
+ switch (blink_format.AsEnum()) {
+ case FormatEnum::kU8:
+ return media::SampleFormat::kSampleFormatU8;
+
+ case FormatEnum::kS16:
+ return media::SampleFormat::kSampleFormatS16;
+
+ case FormatEnum::kS32:
+ return media::SampleFormat::kSampleFormatS32;
+
+ case FormatEnum::kF32:
+ return media::SampleFormat::kSampleFormatF32;
+
+ case FormatEnum::kU8Planar:
+ return media::SampleFormat::kSampleFormatPlanarU8;
+
+ case FormatEnum::kS16Planar:
+ return media::SampleFormat::kSampleFormatPlanarS16;
+
+ case FormatEnum::kS32Planar:
+ return media::SampleFormat::kSampleFormatPlanarS32;
+
+ case FormatEnum::kF32Planar:
+ return media::SampleFormat::kSampleFormatPlanarF32;
+ }
+}
+
+} // namespace
+
// static
AudioData* AudioData::Create(AudioDataInit* init,
ExceptionState& exception_state) {
- return MakeGarbageCollected<AudioData>(init);
+ return MakeGarbageCollected<AudioData>(init, exception_state);
}
-AudioData::AudioData(AudioDataInit* init)
- : timestamp_(init->timestamp()), buffer_(init->buffer()) {
- std::vector<const uint8_t*> wrapped_channels(buffer_->numberOfChannels());
- for (unsigned ch = 0; ch < buffer_->numberOfChannels(); ++ch) {
- wrapped_channels[ch] =
- reinterpret_cast<const uint8_t*>(buffer_->getChannelData(ch)->Data());
+AudioData::AudioData(AudioDataInit* init, ExceptionState& exception_state)
+ : format_(absl::nullopt), timestamp_(init->timestamp()) {
+ media::SampleFormat media_format = BlinkFormatToMediaFormat(init->format());
+
+ if (init->numberOfChannels() == 0) {
+ exception_state.ThrowTypeError("numberOfChannels must be greater than 0.");
+ return;
+ }
+
+ if (init->numberOfChannels() > media::limits::kMaxChannels) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ String::Format("numberOfChannels exceeds supported implementation "
+ "limits: %u vs %u.",
+ init->numberOfChannels(), media::limits::kMaxChannels));
+ return;
+ }
+
+ if (init->numberOfFrames() == 0) {
+ exception_state.ThrowTypeError("numberOfFrames must be greater than 0.");
+ return;
+ }
+
+ uint32_t bytes_per_sample =
+ media::SampleFormatToBytesPerChannel(media_format);
+
+ uint32_t total_bytes;
+ if (!base::CheckMul(bytes_per_sample, base::CheckMul(init->numberOfChannels(),
+ init->numberOfFrames()))
+ .AssignIfValid(&total_bytes)) {
+ exception_state.ThrowTypeError(
+ "AudioData allocation size exceeds implementation limits.");
+ return;
+ }
+
+ auto data_wrapper = AsSpan<const uint8_t>(init->data());
+ if (!data_wrapper.data()) {
+ exception_state.ThrowTypeError("data is detached.");
+ return;
+ }
+ if (total_bytes > data_wrapper.size()) {
+ exception_state.ThrowTypeError(
+ String::Format("data is too small: needs %u bytes, received %zu.",
+ total_bytes, data_wrapper.size()));
+ return;
}
+ std::vector<const uint8_t*> wrapped_data;
+ if (media::IsInterleaved(media_format)) {
+ // Interleaved data can directly added.
+ wrapped_data.push_back(data_wrapper.data());
+ } else {
+ // Planar data needs one pointer per channel.
+ wrapped_data.resize(init->numberOfChannels());
+
+ uint32_t plane_size_in_bytes =
+ init->numberOfFrames() *
+ media::SampleFormatToBytesPerChannel(media_format);
+
+ const uint8_t* plane_start =
+ reinterpret_cast<const uint8_t*>(data_wrapper.data());
+
+ for (unsigned ch = 0; ch < init->numberOfChannels(); ++ch)
+ wrapped_data[ch] = plane_start + ch * plane_size_in_bytes;
+ }
+
+ format_ = init->format();
+
data_ = media::AudioBuffer::CopyFrom(
- media::SampleFormat::kSampleFormatPlanarF32,
- media::GuessChannelLayout(buffer_->numberOfChannels()),
- buffer_->numberOfChannels(), buffer_->sampleRate(), buffer_->length(),
- wrapped_channels.data(), base::TimeDelta::FromMicroseconds(timestamp_));
+ media_format, media::GuessChannelLayout(init->numberOfChannels()),
+ init->numberOfChannels(), init->sampleRate(), init->numberOfFrames(),
+ wrapped_data.data(), base::TimeDelta::FromMicroseconds(timestamp_));
}
AudioData::AudioData(scoped_refptr<media::AudioBuffer> buffer)
: data_(std::move(buffer)),
- timestamp_(data_->timestamp().InMicroseconds()) {}
+ timestamp_(data_->timestamp().InMicroseconds()) {
+ media::SampleFormat media_format = data_->sample_format();
+
+ DCHECK(!media::IsBitstream(media_format));
+
+ format_ = MediaFormatToBlinkFormat(media_format);
+
+ if (!format_.has_value())
+ close();
+}
AudioData* AudioData::clone(ExceptionState& exception_state) {
if (!data_) {
@@ -48,44 +203,215 @@ AudioData* AudioData::clone(ExceptionState& exception_state) {
void AudioData::close() {
data_.reset();
- buffer_.Clear();
+ temp_bus_.reset();
+ format_ = absl::nullopt;
}
int64_t AudioData::timestamp() const {
return timestamp_;
}
-void AudioData::CopyDataToBuffer() {
- DCHECK(!buffer_);
+absl::optional<V8AudioSampleFormat> AudioData::format() const {
+ return format_;
+}
- // |this| might have been closed already.
+float AudioData::sampleRate() const {
if (!data_)
- return;
+ return 0;
- buffer_ = AudioBuffer::CreateUninitialized(
- data_->channel_count(), data_->frame_count(), data_->sample_rate());
+ return data_->sample_rate();
+}
- // AudioBuffer::CreateUninitialized() can fail if we run out of memory.
- // Crash here to prevent accessing uninitialized data below.
- CHECK(buffer_);
+uint32_t AudioData::numberOfFrames() const {
+ if (!data_)
+ return 0;
- std::vector<float*> wrapped_channels(buffer_->numberOfChannels());
- for (unsigned ch = 0; ch < buffer_->numberOfChannels(); ++ch)
- wrapped_channels[ch] = buffer_->getChannelData(ch)->Data();
+ return data_->frame_count();
+}
+
+uint32_t AudioData::numberOfChannels() const {
+ if (!data_)
+ return 0;
+
+ return data_->channel_count();
+}
+
+uint64_t AudioData::duration() const {
+ if (!data_)
+ return 0;
- // Copy the frames, converting from |buffer|'s internal format to float.
- data_->ReadAllFrames(wrapped_channels);
+ return data_->duration().InMicroseconds();
}
-AudioBuffer* AudioData::buffer() {
- if (!buffer_)
- CopyDataToBuffer();
+uint32_t AudioData::allocationSize(AudioDataCopyToOptions* copy_to_options,
+ ExceptionState& exception_state) {
+ if (!data_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "AudioData is closed.");
+ return 0;
+ }
+
+ auto format = data_->sample_format();
+ if (copy_to_options->hasFormat()) {
+ auto dest_format = BlinkFormatToMediaFormat(copy_to_options->format());
+ if (dest_format != data_->sample_format() &&
+ dest_format != media::SampleFormat::kSampleFormatPlanarF32) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "AudioData currently only supports copy conversion to f32-planar.");
+ return 0;
+ }
+
+ format = dest_format;
+ }
+
+ // Interleaved formats only have one plane, despite many channels.
+ uint32_t max_plane_index =
+ media::IsInterleaved(format) ? 0 : data_->channel_count() - 1;
+
+ // The channel isn't used in calculating the allocationSize, but we still
+ // validate it here. This prevents a failed copyTo() call following a
+ // successful allocationSize() call.
+ if (copy_to_options->planeIndex() > max_plane_index) {
+ exception_state.ThrowRangeError("Invalid planeIndex.");
+ return 0;
+ }
+
+ const uint32_t offset = copy_to_options->frameOffset();
+ const uint32_t total_frames = static_cast<uint32_t>(data_->frame_count());
+
+ if (offset >= total_frames) {
+ exception_state.ThrowRangeError(String::Format(
+ "Frame offset exceeds total frames (%u >= %u).", offset, total_frames));
+ return 0;
+ }
+
+ const uint32_t available_frames = total_frames - offset;
+ const uint32_t frame_count = copy_to_options->hasFrameCount()
+ ? copy_to_options->frameCount()
+ : available_frames;
+
+ if (frame_count > available_frames) {
+ exception_state.ThrowRangeError(
+ String::Format("Frame count exceeds available_frames frames (%u > %u).",
+ frame_count, available_frames));
+ return 0;
+ }
+
+ uint32_t sample_count = frame_count;
+
+ // For interleaved formats, frames are stored as blocks of samples. Each block
+ // has 1 sample per channel, and |sample_count| needs to be adjusted.
+ bool overflow = false;
+ if (media::IsInterleaved(format) &&
+ !base::CheckMul(frame_count, data_->channel_count())
+ .AssignIfValid(&sample_count)) {
+ overflow = true;
+ }
+
+ uint32_t allocation_size;
+ if (overflow || !base::CheckMul(sample_count,
+ media::SampleFormatToBytesPerChannel(format))
+ .AssignIfValid(&allocation_size)) {
+ exception_state.ThrowTypeError(String::Format(
+ "Provided options cause overflow when calculating allocation size."));
+ return 0;
+ }
+
+ return allocation_size;
+}
+
+void AudioData::copyTo(const AllowSharedBufferSource* destination,
+ AudioDataCopyToOptions* copy_to_options,
+ ExceptionState& exception_state) {
+ if (!data_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Cannot copy closed AudioData.");
+ return;
+ }
+
+ uint32_t copy_size_in_bytes =
+ allocationSize(copy_to_options, exception_state);
+
+ if (exception_state.HadException())
+ return;
+
+ // Validate destination buffer.
+ auto dest_wrapper = AsSpan<uint8_t>(destination);
+ if (!dest_wrapper.data()) {
+ exception_state.ThrowRangeError("destination is detached.");
+ return;
+ }
+ if (dest_wrapper.size() < static_cast<size_t>(copy_size_in_bytes)) {
+ exception_state.ThrowRangeError("destination is not large enough.");
+ return;
+ }
+
+ auto dest_format = copy_to_options->hasFormat()
+ ? BlinkFormatToMediaFormat(copy_to_options->format())
+ : data_->sample_format();
+
+ const uint8_t* src_data = nullptr;
+ size_t src_data_size = 0;
+ if (dest_format != data_->sample_format()) {
+ // NOTE: The call to allocationSize() above ensures only passthrough or
+ // f32-planar are possible by this point.
+ DCHECK_EQ(dest_format, media::SampleFormat::kSampleFormatPlanarF32);
+
+ // In case of format conversion to float32, convert the entire AudioBuffer
+ // at once and save it for future copy calls.
+ if (!temp_bus_)
+ temp_bus_ = media::AudioBuffer::WrapOrCopyToAudioBus(data_);
+
+ CHECK_LE(copy_to_options->planeIndex(),
+ static_cast<uint32_t>(temp_bus_->channels()));
+
+ src_data = reinterpret_cast<const uint8_t*>(
+ temp_bus_->channel(copy_to_options->planeIndex()));
+
+ src_data_size = sizeof(float) * temp_bus_->frames();
+ } else {
+ CHECK_LE(copy_to_options->planeIndex(),
+ static_cast<uint32_t>(data_->channel_count()));
+
+ src_data = data_->channel_data()[copy_to_options->planeIndex()];
+
+ if (media::IsInterleaved(data_->sample_format())) {
+ src_data_size = data_->data_size();
+ } else {
+ src_data_size =
+ media::SampleFormatToBytesPerChannel(data_->sample_format()) *
+ data_->frame_count();
+ }
+ }
+
+ // Copy data.
+ uint32_t offset_in_samples = copy_to_options->frameOffset();
+
+ bool overflow = false;
+ // Interleaved frames have 1 sample per channel for each block of samples.
+ if (media::IsInterleaved(dest_format) &&
+ !base::CheckMul(copy_to_options->frameOffset(), data_->channel_count())
+ .AssignIfValid(&offset_in_samples)) {
+ overflow = true;
+ }
+
+ uint32_t offset_in_bytes = 0;
+ if (overflow ||
+ !base::CheckMul(offset_in_samples,
+ media::SampleFormatToBytesPerChannel(dest_format))
+ .AssignIfValid(&offset_in_bytes)) {
+ exception_state.ThrowTypeError(String::Format(
+ "Provided options cause overflow when calculating offset."));
+ return;
+ }
- return buffer_;
+ const uint8_t* data_start = src_data + offset_in_bytes;
+ CHECK_LE(data_start + copy_size_in_bytes, src_data + src_data_size);
+ memcpy(dest_wrapper.data(), data_start, copy_size_in_bytes);
}
void AudioData::Trace(Visitor* visitor) const {
- visitor->Trace(buffer_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.h b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.h
index 007ffef480b..f5c09fb7abb 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.h
@@ -6,14 +6,17 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_AUDIO_DATA_H_
#include "media/base/audio_buffer.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_sample_format.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
-
-class ExceptionState;
class AudioDataInit;
+class AudioDataCopyToOptions;
+class ExceptionState;
class MODULES_EXPORT AudioData final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -25,7 +28,7 @@ class MODULES_EXPORT AudioData final : public ScriptWrappable {
explicit AudioData(scoped_refptr<media::AudioBuffer>);
// audio_data.idl implementation.
- explicit AudioData(AudioDataInit*);
+ explicit AudioData(AudioDataInit*, ExceptionState&);
// Creates a clone of |this|, taking on a new reference on |data_|. The cloned
// frame will not be closed when |this| is, and its lifetime should be
@@ -33,8 +36,18 @@ class MODULES_EXPORT AudioData final : public ScriptWrappable {
AudioData* clone(ExceptionState&);
void close();
+
+ absl::optional<V8AudioSampleFormat> format() const;
+ float sampleRate() const;
+ uint32_t numberOfFrames() const;
+ uint32_t numberOfChannels() const;
+ uint64_t duration() const;
int64_t timestamp() const;
- AudioBuffer* buffer();
+
+ uint32_t allocationSize(AudioDataCopyToOptions*, ExceptionState&);
+ void copyTo(const AllowSharedBufferSource* destination,
+ AudioDataCopyToOptions*,
+ ExceptionState&);
scoped_refptr<media::AudioBuffer> data() const { return data_; }
@@ -42,12 +55,14 @@ class MODULES_EXPORT AudioData final : public ScriptWrappable {
void Trace(Visitor*) const override;
private:
- void CopyDataToBuffer();
-
scoped_refptr<media::AudioBuffer> data_;
+ absl::optional<V8AudioSampleFormat> format_;
+
+ // Temporary space for converting to float32.
+ std::unique_ptr<media::AudioBus> temp_bus_;
+
int64_t timestamp_;
- Member<AudioBuffer> buffer_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.idl
index 61e8fbcb51d..17ae2889ac1 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data.idl
@@ -14,6 +14,14 @@
void close();
+ [RaisesException] unsigned long allocationSize(AudioDataCopyToOptions options);
+ [RaisesException] void copyTo(AllowSharedBufferSource destination,
+ AudioDataCopyToOptions options);
+
+ readonly attribute AudioSampleFormat format;
+ readonly attribute float sampleRate;
+ readonly attribute unsigned long numberOfFrames;
+ readonly attribute unsigned long numberOfChannels;
+ readonly attribute unsigned long long duration;
readonly attribute long long timestamp; // microseconds
- readonly attribute AudioBuffer buffer;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h
index 27de073b133..c24219a2317 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_attachment.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_AUDIO_DATA_ATTACHMENT_H_
#include "media/base/audio_buffer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_options.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_options.idl
new file mode 100644
index 00000000000..fe11320bd68
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_options.idl
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+dictionary AudioDataCopyToOptions {
+ required [EnforceRange] unsigned long planeIndex;
+ [EnforceRange] unsigned long frameCount;
+ [EnforceRange] unsigned long frameOffset = 0;
+ AudioSampleFormat format;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_init.idl
index 0ec1f52fb22..7df6ec56de3 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_init.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_init.idl
@@ -5,6 +5,10 @@
// https://github.com/WICG/web-codecs
dictionary AudioDataInit {
- required long long timestamp; // microseconds
- required AudioBuffer buffer;
+ required AudioSampleFormat format;
+ required float sampleRate;
+ required [EnforceRange] unsigned long numberOfFrames;
+ required [EnforceRange] unsigned long numberOfChannels;
+ required [EnforceRange] long long timestamp; // microseconds
+ required AllowSharedBufferSource data;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc
index 3b35bf5d2d1..57006895e52 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc
@@ -6,9 +6,13 @@
#include "media/base/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_copy_to_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_init.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/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -21,28 +25,87 @@ constexpr int64_t kTimestampInMicroSeconds = 1234;
constexpr int kChannels = 2;
constexpr int kFrames = 20;
constexpr int kSampleRate = 8000;
+constexpr int kPartialFrameCount = 5;
+constexpr int kOffset = 5;
+
+constexpr int kMicrosecondPerSecond = 1E6;
+constexpr uint64_t kExpectedDuration =
+ static_cast<int64_t>(kFrames * kMicrosecondPerSecond / kSampleRate);
+
+constexpr float kIncrement = 1.0f / 1000;
+constexpr float kEpsilon = kIncrement / 100;
} // namespace
class AudioDataTest : public testing::Test {
protected:
- AudioBuffer* CreateDefaultAudioBuffer() {
- auto* audio_buffer =
- AudioBuffer::CreateUninitialized(kChannels, kFrames, kSampleRate);
+ void VerifyPlanarData(float* data, float start_value, int count) {
+ for (int i = 0; i < count; ++i)
+ ASSERT_NEAR(data[i], start_value + i * kIncrement, kEpsilon) << "i=" << i;
+ }
+
+ AllowSharedBufferSource* CreateDefaultData() {
+ auto* buffer = DOMArrayBuffer::Create(kChannels * kFrames, sizeof(float));
for (int ch = 0; ch < kChannels; ++ch) {
- float* buffer_data = audio_buffer->getChannelData(ch)->Data();
+ float* plane_start =
+ reinterpret_cast<float*>(buffer->Data()) + ch * kFrames;
for (int i = 0; i < kFrames; ++i) {
- buffer_data[i] = static_cast<float>((i + ch * kFrames) / 1000.0f);
+ plane_start[i] = static_cast<float>((i + ch * kFrames) * kIncrement);
}
}
- return audio_buffer;
+ return MakeGarbageCollected<AllowSharedBufferSource>(buffer);
}
- AudioDataInit* CreateDefaultAudioDataInit(AudioBuffer* buffer) {
+ AudioDataInit* CreateDefaultAudioDataInit(AllowSharedBufferSource* data) {
auto* audio_data_init = AudioDataInit::Create();
- audio_data_init->setBuffer(buffer);
+ audio_data_init->setData(data);
audio_data_init->setTimestamp(kTimestampInMicroSeconds);
+ audio_data_init->setNumberOfChannels(kChannels);
+ audio_data_init->setNumberOfFrames(kFrames);
+ audio_data_init->setSampleRate(kSampleRate);
+ audio_data_init->setFormat("f32-planar");
return audio_data_init;
}
+
+ AudioData* CreateDefaultAudioData(ExceptionState& exception_state) {
+ auto* data = CreateDefaultData();
+ auto* audio_data_init = CreateDefaultAudioDataInit(data);
+ return MakeGarbageCollected<AudioData>(audio_data_init, exception_state);
+ }
+
+ AudioDataCopyToOptions* CreateCopyToOptions(int index,
+ absl::optional<uint32_t> offset,
+ absl::optional<uint32_t> count) {
+ auto* copy_to_options = AudioDataCopyToOptions::Create();
+ copy_to_options->setPlaneIndex(index);
+
+ if (offset.has_value())
+ copy_to_options->setFrameOffset(offset.value());
+
+ if (count.has_value())
+ copy_to_options->setFrameCount(count.value());
+
+ return copy_to_options;
+ }
+
+ void VerifyAllocationSize(int plane_index,
+ absl::optional<uint32_t> frame_offset,
+ absl::optional<uint32_t> frame_count,
+ bool should_throw,
+ int expected_size,
+ std::string description) {
+ V8TestingScope scope;
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+
+ auto* options = CreateCopyToOptions(plane_index, frame_offset, frame_count);
+ {
+ SCOPED_TRACE(description);
+ int allocations_size =
+ frame->allocationSize(options, scope.GetExceptionState());
+
+ EXPECT_EQ(should_throw, scope.GetExceptionState().HadException());
+ EXPECT_EQ(allocations_size, expected_size);
+ }
+ }
};
TEST_F(AudioDataTest, ConstructFromMediaBuffer) {
@@ -60,43 +123,261 @@ TEST_F(AudioDataTest, ConstructFromMediaBuffer) {
auto* frame = MakeGarbageCollected<AudioData>(media_buffer);
+ EXPECT_EQ(frame->format(), "s16");
+ EXPECT_EQ(frame->sampleRate(), static_cast<uint32_t>(kSampleRate));
+ EXPECT_EQ(frame->numberOfFrames(), static_cast<uint32_t>(kFrames));
+ EXPECT_EQ(frame->numberOfChannels(), static_cast<uint32_t>(kChannels));
+ EXPECT_EQ(frame->duration(), kExpectedDuration);
EXPECT_EQ(frame->timestamp(), kTimestampInMicroSeconds);
- EXPECT_TRUE(frame->buffer());
- EXPECT_EQ(frame->buffer()->numberOfChannels(),
- static_cast<unsigned>(channels));
- EXPECT_EQ(frame->buffer()->length(), static_cast<uint32_t>(kFrames));
-
- // The buffer's internal int16_t value should have been converted to float32.
- constexpr float kFloatIncrement =
- static_cast<float>(kIncrement) / std::numeric_limits<int16_t>::max();
- constexpr float kFloatStart =
- static_cast<float>(kStart) / std::numeric_limits<int16_t>::max();
-
- // Verify the data was properly converted.
- for (int ch = 0; ch < channels; ++ch) {
- float* internal_channel = frame->buffer()->getChannelData(ch)->Data();
- float start_value = kFloatStart + ch * kFloatIncrement * kFrames;
- for (int i = 0; i < kFrames; ++i) {
- float expected_value = start_value + i * kFloatIncrement;
- ASSERT_FLOAT_EQ(expected_value, internal_channel[i])
- << "i=" << i << ", ch=" << ch;
- }
- }
-
// The media::AudioBuffer we receive should match the original |media_buffer|.
EXPECT_EQ(frame->data(), media_buffer);
+
+ frame->close();
+ EXPECT_EQ(frame->data(), nullptr);
+ EXPECT_EQ(frame->format(), absl::nullopt);
+ EXPECT_EQ(frame->sampleRate(), 0u);
+ EXPECT_EQ(frame->numberOfFrames(), 0u);
+ EXPECT_EQ(frame->numberOfChannels(), 0u);
+ EXPECT_EQ(frame->duration(), 0u);
+
+ // Timestamp is preserved even after closing.
+ EXPECT_EQ(frame->timestamp(), kTimestampInMicroSeconds);
}
TEST_F(AudioDataTest, ConstructFromAudioDataInit) {
- auto* audio_buffer = CreateDefaultAudioBuffer();
+ V8TestingScope scope;
+ auto* buffer_source = CreateDefaultData();
- auto* audio_data_init = CreateDefaultAudioDataInit(audio_buffer);
+ auto* audio_data_init = CreateDefaultAudioDataInit(buffer_source);
- auto* frame = MakeGarbageCollected<AudioData>(audio_data_init);
+ auto* frame = MakeGarbageCollected<AudioData>(audio_data_init,
+ scope.GetExceptionState());
+ EXPECT_EQ(frame->format(), "f32-planar");
+ EXPECT_EQ(frame->sampleRate(), static_cast<uint32_t>(kSampleRate));
+ EXPECT_EQ(frame->numberOfFrames(), static_cast<uint32_t>(kFrames));
+ EXPECT_EQ(frame->numberOfChannels(), static_cast<uint32_t>(kChannels));
+ EXPECT_EQ(frame->duration(), kExpectedDuration);
EXPECT_EQ(frame->timestamp(), kTimestampInMicroSeconds);
- EXPECT_EQ(frame->buffer(), audio_buffer);
+}
+
+TEST_F(AudioDataTest, AllocationSize) {
+ // We only support the "FLTP" format for now.
+ constexpr int kTotalSizeInBytes = kFrames * sizeof(float);
+
+ // Basic cases.
+ VerifyAllocationSize(0, absl::nullopt, absl::nullopt, false,
+ kTotalSizeInBytes, "Default");
+ VerifyAllocationSize(1, absl::nullopt, absl::nullopt, false,
+ kTotalSizeInBytes, "Valid index.");
+ VerifyAllocationSize(0, 0, kFrames, false, kTotalSizeInBytes,
+ "Specifying defaults");
+
+ // Cases where we cover a subset of samples.
+ VerifyAllocationSize(0, kFrames / 2, absl::nullopt, false,
+ kTotalSizeInBytes / 2, "Valid offset, no count");
+ VerifyAllocationSize(0, kFrames / 2, kFrames / 4, false,
+ kTotalSizeInBytes / 4, "Valid offset and count");
+ VerifyAllocationSize(0, absl::nullopt, kFrames / 2, false,
+ kTotalSizeInBytes / 2, "No offset, valid count");
+
+ // Copying 0 frames is technically valid.
+ VerifyAllocationSize(0, absl::nullopt, 0, false, 0, "Frame count is 0");
+
+ // Failures
+ VerifyAllocationSize(2, absl::nullopt, absl::nullopt, true, 0,
+ "Invalid index.");
+ VerifyAllocationSize(0, kFrames, absl::nullopt, true, 0, "Offset too big");
+ VerifyAllocationSize(0, absl::nullopt, kFrames + 1, true, 0, "Count too big");
+ VerifyAllocationSize(0, 1, kFrames, true, 0, "Count too big, with offset");
+}
+
+TEST_F(AudioDataTest, CopyTo_DestinationTooSmall) {
+ V8TestingScope scope;
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+ auto* options = CreateCopyToOptions(/*index=*/0, /*offset=*/absl::nullopt,
+ /*count=*/absl::nullopt);
+
+ AllowSharedBufferSource* small_dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(
+ DOMArrayBuffer::Create(kFrames - 1, sizeof(float)));
+
+ frame->copyTo(small_dest, options, scope.GetExceptionState());
+
+ EXPECT_TRUE(scope.GetExceptionState().HadException());
+}
+
+TEST_F(AudioDataTest, CopyTo_FullFrames) {
+ V8TestingScope scope;
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+ auto* options = CreateCopyToOptions(/*index=*/0, /*offset=*/absl::nullopt,
+ /*count=*/absl::nullopt);
+
+ DOMArrayBuffer* data_copy = DOMArrayBuffer::Create(kFrames, sizeof(float));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy);
+
+ // All frames should have been copied.
+ frame->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ VerifyPlanarData(static_cast<float*>(data_copy->Data()), /*start_value=*/0,
+ /*count=*/kFrames);
+}
+
+TEST_F(AudioDataTest, CopyTo_PlaneIndex) {
+ V8TestingScope scope;
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+ auto* options = CreateCopyToOptions(/*index=*/1, /*offset=*/absl::nullopt,
+ /*count=*/absl::nullopt);
+
+ DOMArrayBuffer* data_copy = DOMArrayBuffer::Create(kFrames, sizeof(float));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy);
+
+ // All frames should have been copied.
+ frame->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ // The channel 1's start value is kFrames*in.
+ VerifyPlanarData(static_cast<float*>(data_copy->Data()),
+ /*start_value=*/kFrames * kIncrement,
+ /*count=*/kFrames);
+}
+
+TEST_F(AudioDataTest, CopyTo_Offset) {
+ V8TestingScope scope;
+
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+ auto* options =
+ CreateCopyToOptions(/*index=*/0, kOffset, /*count=*/absl::nullopt);
+
+ // |data_copy| is bigger than what we need, and that's ok.
+ DOMArrayBuffer* data_copy = DOMArrayBuffer::Create(kFrames, sizeof(float));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy);
+
+ // All frames should have been copied.
+ frame->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ VerifyPlanarData(static_cast<float*>(data_copy->Data()),
+ /*start_value=*/kOffset * kIncrement,
+ /*count=*/kFrames - kOffset);
+}
+
+TEST_F(AudioDataTest, CopyTo_PartialFrames) {
+ V8TestingScope scope;
+
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+ auto* options = CreateCopyToOptions(/*index=*/0, /*offset=*/absl::nullopt,
+ kPartialFrameCount);
+
+ DOMArrayBuffer* data_copy =
+ DOMArrayBuffer::Create(kPartialFrameCount, sizeof(float));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy);
+
+ // All frames should have been copied.
+ frame->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ VerifyPlanarData(static_cast<float*>(data_copy->Data()),
+ /*start_value=*/0, kPartialFrameCount);
+}
+
+TEST_F(AudioDataTest, CopyTo_PartialFramesAndOffset) {
+ V8TestingScope scope;
+
+ auto* frame = CreateDefaultAudioData(scope.GetExceptionState());
+ auto* options = CreateCopyToOptions(/*index=*/0, kOffset, kPartialFrameCount);
+
+ DOMArrayBuffer* data_copy =
+ DOMArrayBuffer::Create(kPartialFrameCount, sizeof(float));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy);
+
+ // All frames should have been copied.
+ frame->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ VerifyPlanarData(static_cast<float*>(data_copy->Data()),
+ /*start_value=*/kOffset * kIncrement, kPartialFrameCount);
+}
+
+TEST_F(AudioDataTest, Interleaved) {
+ V8TestingScope scope;
+
+ // Do not use a power of 2, to make it easier to verify the allocationSize()
+ // results.
+ constexpr int kInterleavedChannels = 3;
+
+ std::vector<int16_t> samples(kFrames * kInterleavedChannels);
+
+ // Populate samples.
+ for (int i = 0; i < kFrames; ++i) {
+ int block_index = i * kInterleavedChannels;
+
+ samples[block_index] = i; // channel 0
+ samples[block_index + 1] = i + kFrames; // channel 1
+ samples[block_index + 2] = i + 2 * kFrames; // channel 2
+ }
+
+ const uint8_t* data[] = {reinterpret_cast<const uint8_t*>(samples.data())};
+
+ auto media_buffer = media::AudioBuffer::CopyFrom(
+ media::SampleFormat::kSampleFormatS16,
+ media::GuessChannelLayout(kInterleavedChannels), kInterleavedChannels,
+ kSampleRate, kFrames, data, base::TimeDelta());
+
+ auto* frame = MakeGarbageCollected<AudioData>(media_buffer);
+
+ EXPECT_EQ("s16", frame->format());
+
+ // Verify that plane indexes > 1 throw, for interleaved formats.
+ auto* options = CreateCopyToOptions(/*index=*/1, kOffset, kPartialFrameCount);
+ int allocations_size =
+ frame->allocationSize(options, scope.GetExceptionState());
+
+ EXPECT_TRUE(scope.GetExceptionState().HadException());
+ scope.GetExceptionState().ClearException();
+
+ // Verify that copy conversion to a planar format supports indexes > 1,
+ // even if the source is interleaved.
+ options->setFormat(V8AudioSampleFormat::Enum::kF32Planar);
+ allocations_size = frame->allocationSize(options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ // Verify we get the expected allocation size, for valid formats.
+ options = CreateCopyToOptions(/*index=*/0, kOffset, kPartialFrameCount);
+ allocations_size = frame->allocationSize(options, scope.GetExceptionState());
+
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ // Interleaved formats take into account the number of channels.
+ EXPECT_EQ(static_cast<unsigned int>(allocations_size),
+ kPartialFrameCount * kInterleavedChannels * sizeof(uint16_t));
+
+ DOMArrayBuffer* data_copy = DOMArrayBuffer::Create(
+ kPartialFrameCount * kInterleavedChannels, sizeof(uint16_t));
+ AllowSharedBufferSource* dest =
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy);
+
+ // All frames should have been copied.
+ frame->copyTo(dest, options, scope.GetExceptionState());
+ EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+ // Verify we retrieved the right samples.
+ int16_t* copy = static_cast<int16_t*>(data_copy->Data());
+ for (int i = 0; i < kPartialFrameCount; ++i) {
+ int block_index = i * kInterleavedChannels;
+ int16_t base_value = kOffset + i;
+
+ EXPECT_EQ(copy[block_index], base_value); // channel 0
+ EXPECT_EQ(copy[block_index + 1], base_value + kFrames); // channel 1
+ EXPECT_EQ(copy[block_index + 2], base_value + 2 * kFrames); // channel 2
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
index 4974d4cb0b1..956a696f566 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_support.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_decoder_broker.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_config_eval.h"
@@ -35,10 +36,20 @@ namespace blink {
bool IsValidConfig(const AudioDecoderConfig& config,
media::AudioType& out_audio_type,
String& out_console_message) {
+ // Match codec strings from the codec registry:
+ // https://www.w3.org/TR/webcodecs-codec-registry/#audio-codec-registry
+ if (config.codec() == "ulaw") {
+ out_audio_type = {media::kCodecPCM_MULAW};
+ return true;
+ } else if (config.codec() == "alaw") {
+ out_audio_type = {media::kCodecPCM_ALAW};
+ return true;
+ }
+
media::AudioCodec codec = media::kUnknownAudioCodec;
bool is_codec_ambiguous = true;
- bool parse_succeeded = ParseAudioCodecString("", config.codec().Utf8(),
- &is_codec_ambiguous, &codec);
+ const bool parse_succeeded = ParseAudioCodecString(
+ "", config.codec().Utf8(), &is_codec_ambiguous, &codec);
if (!parse_succeeded) {
out_console_message = "Failed to parse codec string.";
@@ -60,11 +71,13 @@ AudioDecoderConfig* CopyConfig(const AudioDecoderConfig& config) {
copy->setSampleRate(config.sampleRate());
copy->setNumberOfChannels(config.numberOfChannels());
if (config.hasDescription()) {
- DOMArrayPiece buffer(config.description());
- DOMArrayBuffer* buffer_copy =
- DOMArrayBuffer::Create(buffer.Data(), buffer.ByteLength());
- copy->setDescription(
- ArrayBufferOrArrayBufferView::FromArrayBuffer(buffer_copy));
+ auto desc_wrapper = AsSpan<const uint8_t>(config.description());
+ if (!desc_wrapper.empty()) {
+ DOMArrayBuffer* buffer_copy =
+ DOMArrayBuffer::Create(desc_wrapper.data(), desc_wrapper.size());
+ copy->setDescription(
+ MakeGarbageCollected<AllowSharedBufferSource>(buffer_copy));
+ }
}
return copy;
}
@@ -187,10 +200,13 @@ CodecConfigEval AudioDecoder::MakeMediaAudioDecoderConfig(
std::vector<uint8_t> extra_data;
if (config.hasDescription()) {
- DOMArrayPiece buffer(config.description());
- uint8_t* start = static_cast<uint8_t*>(buffer.Data());
- size_t size = buffer.ByteLength();
- extra_data.assign(start, start + size);
+ // TODO(crbug.com/1179970): This should throw if description is detached.
+ auto desc_wrapper = AsSpan<const uint8_t>(config.description());
+ if (!desc_wrapper.empty()) {
+ const uint8_t* start = desc_wrapper.data();
+ const size_t size = desc_wrapper.size();
+ extra_data.assign(start, start + size);
+ }
}
media::ChannelLayout channel_layout =
@@ -226,13 +242,11 @@ CodecConfigEval AudioDecoder::MakeMediaConfig(const ConfigType& config,
}
media::StatusOr<scoped_refptr<media::DecoderBuffer>>
-AudioDecoder::MakeDecoderBuffer(const InputType& chunk) {
- auto decoder_buffer = media::DecoderBuffer::CopyFrom(
- static_cast<uint8_t*>(chunk.data()->Data()), chunk.data()->ByteLength());
- decoder_buffer->set_timestamp(
- base::TimeDelta::FromMicroseconds(chunk.timestamp()));
- decoder_buffer->set_is_key_frame(chunk.type() == "key");
- return decoder_buffer;
+AudioDecoder::MakeDecoderBuffer(const InputType& chunk, bool verify_key_frame) {
+ if (verify_key_frame && !chunk.buffer()->is_key_frame())
+ return media::Status(media::StatusCode::kKeyFrameRequired);
+
+ return chunk.buffer();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.h b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.h
index 2eac3643493..0fab19e1478 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.h
@@ -97,7 +97,8 @@ class MODULES_EXPORT AudioDecoder : public DecoderTemplate<AudioDecoderTraits> {
MediaConfigType* out_media_config,
String* out_console_message) override;
media::StatusOr<scoped_refptr<media::DecoderBuffer>> MakeDecoderBuffer(
- const InputType& chunk) override;
+ const InputType& chunk,
+ bool verify_key_frame) override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.idl
index b5c1c6503d8..34fbcc65a71 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder.idl
@@ -6,6 +6,7 @@
[
Exposed=(Window,DedicatedWorker),
+ SecureContext,
RuntimeEnabled=WebCodecs,
ActiveScriptWrappable
] interface AudioDecoder {
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder_config.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder_config.idl
index 994836026d3..62f7d7d497d 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder_config.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_decoder_config.idl
@@ -12,12 +12,12 @@ dictionary AudioDecoderConfig {
required DOMString codec;
// Rate of samples per second. 44100, 48000, etc.
- required unsigned long sampleRate;
+ required [EnforceRange] unsigned long sampleRate;
// 1, 2, etc.
- required unsigned long numberOfChannels;
+ required [EnforceRange] unsigned long numberOfChannels;
// Optional byte data required to initialize audio decoders such as Vorbis
// codebooks.
- BufferSource description;
+ AllowSharedBufferSource description;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc b/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
index 8c8e1b33693..2e704331a4e 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
@@ -17,13 +17,16 @@
#include "media/base/mime_util.h"
#include "media/base/offloading_audio_encoder.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_encoder_support.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk_metadata.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -304,19 +307,20 @@ void AudioEncoder::CallOutputCallback(
DCHECK(active_config);
if (!script_state_->ContextIsValid() || !output_callback_ ||
state_.AsEnum() != V8CodecState::Enum::kConfigured ||
- reset_count != reset_count_)
+ reset_count != reset_count_) {
return;
+ }
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- auto timestamp = encoded_buffer.timestamp - base::TimeTicks();
- auto deleter = [](void* data, size_t length, void*) {
- delete[] static_cast<uint8_t*>(data);
- };
- ArrayBufferContents data(encoded_buffer.encoded_data.release(),
- encoded_buffer.encoded_data_size, deleter);
- auto* dom_array = MakeGarbageCollected<DOMArrayBuffer>(std::move(data));
- auto* chunk =
- MakeGarbageCollected<EncodedAudioChunk>(timestamp, false, dom_array);
+
+ MarkCodecActive();
+
+ auto buffer = media::DecoderBuffer::FromArray(
+ std::move(encoded_buffer.encoded_data), encoded_buffer.encoded_data_size);
+ buffer->set_timestamp(encoded_buffer.timestamp - base::TimeTicks());
+ buffer->set_is_key_frame(true);
+ buffer->set_duration(encoded_buffer.duration);
+ auto* chunk = MakeGarbageCollected<EncodedAudioChunk>(std::move(buffer));
auto* metadata = MakeGarbageCollected<EncodedAudioChunkMetadata>();
if (first_output_after_configure_ || codec_desc.has_value()) {
@@ -329,7 +333,7 @@ void AudioEncoder::CallOutputCallback(
auto* desc_array_buf = DOMArrayBuffer::Create(codec_desc.value().data(),
codec_desc.value().size());
decoder_config->setDescription(
- ArrayBufferOrArrayBufferView::FromArrayBuffer(desc_array_buf));
+ MakeGarbageCollected<AllowSharedBufferSource>(desc_array_buf));
}
metadata->setDecoderConfig(decoder_config);
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.idl
index b5b78463d7d..44ac92ffdd5 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder.idl
@@ -6,6 +6,7 @@
[
Exposed=(Window,DedicatedWorker),
+ SecureContext,
RuntimeEnabled=WebCodecs,
ActiveScriptWrappable
] interface AudioEncoder {
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl
index ab29c942fdd..8d8f04998a9 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl
@@ -11,10 +11,10 @@ dictionary AudioEncoderConfig {
required DOMString codec;
// Rate of samples per second. 44100, 48000, etc.
- required unsigned long sampleRate;
+ required [EnforceRange] unsigned long sampleRate;
// 1, 2, etc.
- required unsigned short numberOfChannels;
+ required [EnforceRange] unsigned short numberOfChannels;
- unsigned long long bitrate;
+ [EnforceRange] unsigned long long bitrate;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_sample_format.idl b/chromium/third_party/blink/renderer/modules/webcodecs/audio_sample_format.idl
new file mode 100644
index 00000000000..bddb70af12c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_sample_format.idl
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+enum AudioSampleFormat {
+ "u8",
+ "s16",
+ "s32",
+ "f32",
+ "u8-planar",
+ "s16-planar",
+ "s32-planar",
+ "f32-planar",
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.cc b/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.cc
index 94a44c0de41..257f84f195b 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/inspector_media_context_impl.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
@@ -25,7 +26,8 @@ CodecLogger::CodecLogger(
// collected before |parent_media_log_| is destroyed.
if (!context->IsContextDestroyed()) {
parent_media_log_ = Platform::Current()->GetMediaLog(
- MediaInspectorContextImpl::From(*context), task_runner);
+ MediaInspectorContextImpl::From(*context), task_runner,
+ /*is_on_worker=*/!IsMainThread());
}
// NullMediaLog silently and safely does nothing.
@@ -37,10 +39,6 @@ CodecLogger::CodecLogger(
media_log_ = parent_media_log_->Clone();
}
-CodecLogger::CodecLogger()
- : parent_media_log_(std::make_unique<media::NullMediaLog>()),
- media_log_(parent_media_log_->Clone()) {}
-
DOMException* CodecLogger::MakeException(std::string error_msg,
media::Status status) {
media_log_->NotifyError(status);
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.h b/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.h
index 80bb6f6f9ec..0329c6e6ef9 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/codec_logger.h
@@ -30,9 +30,6 @@ class ExecutionContext;
// call Neuter() if the ExecutionContext passed to the constructor is destroyed.
class MODULES_EXPORT CodecLogger final {
public:
- // Creates a CodecLogger backed by a NullMediaLog, which does nothing.
- CodecLogger();
-
// Attempts to create CodecLogger backed by a BatchingMediaLog. Falls back to
// a NullMediaLog on failure.
CodecLogger(ExecutionContext*,
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/codec_trace_names.h b/chromium/third_party/blink/renderer/modules/webcodecs/codec_trace_names.h
index 7827b050c9c..37c5b9b3505 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/codec_trace_names.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/codec_trace_names.h
@@ -19,6 +19,7 @@ struct CodecTraceNames {
flush = codec_name + "::Flush";
handle_error = codec_name + "::HandleError";
output = codec_name + "::Ouput";
+ reset = codec_name + "::OnCodecReclaimed";
reset = codec_name + "::Reset";
reconfigure = codec_name + "::Reconfigure";
requests_counter = codec_name + " requests";
@@ -37,6 +38,7 @@ struct CodecTraceNames {
std::string flush;
std::string handle_error;
std::string output;
+ std::string reclaimed;
std::string reset;
std::string reconfigure;
std::string requests_counter;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_matrix_id.idl b/chromium/third_party/blink/renderer/modules/webcodecs/color_space_matrix_id.idl
deleted file mode 100644
index cb43732e632..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_matrix_id.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-enum ColorSpaceMatrixID {
- "RGB",
- "BT709",
- "FCC",
- "BT470BG",
- "SMPTE170M",
- "SMPTE240M",
- "YCOCG",
- "BT2020_NCL",
- "BT2020_CL",
- "YDZDX",
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl b/chromium/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl
deleted file mode 100644
index 68ef2e9ed28..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-enum ColorSpacePrimaryID {
- "BT709",
- "BT470M",
- "BT470BG",
- "SMPTE170M",
- "SMPTE240M",
- "FILM",
- "BT2020",
- "SMPTEST428_1",
- "SMPTEST431_2",
- "SMPTEST432_1",
- "EBU_3213_E",
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_range_id.idl b/chromium/third_party/blink/renderer/modules/webcodecs/color_space_range_id.idl
deleted file mode 100644
index aa29539af67..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_range_id.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-enum ColorSpaceRangeID {
- // Limited Rec.709 color range.
- "LIMITED",
-
- // Full RGB color range.
- "FULL",
-
- // Range is defined by TransferID/MatrixID.
- "DERIVED",
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_transfer_id.idl b/chromium/third_party/blink/renderer/modules/webcodecs/color_space_transfer_id.idl
deleted file mode 100644
index 2351ee27181..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/color_space_transfer_id.idl
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-enum ColorSpaceTransferID {
- "BT709",
- "GAMMA22",
- "GAMMA28",
- "SMPTE170M",
- "SMPTE240M",
- "LINEAR",
- "LOG",
- "LOG_SQRT",
- "IEC61966_2_4",
- "BT1361_ECG",
- "IEC61966_2_1",
- "BT2020_10",
- "BT2020_12",
- "SMPTEST2084",
- "SMPTEST428_1",
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.cc b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.cc
new file mode 100644
index 00000000000..f1ff7484b2f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.cc
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h"
+
+namespace blink {
+
+const void* const DecoderBufferAttachment::kAttachmentKey = nullptr;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h
new file mode 100644
index 00000000000..5222a9ccd77
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_buffer_attachment.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_BUFFER_ATTACHMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_BUFFER_ATTACHMENT_H_
+
+#include "media/base/decoder_buffer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+// Used to serialize EncodedAudioChunk and EncodedVideoChunk.
+class MODULES_EXPORT DecoderBufferAttachment
+ : public SerializedScriptValue::Attachment {
+ public:
+ using DecoderBufferVector = Vector<scoped_refptr<media::DecoderBuffer>>;
+
+ static const void* const kAttachmentKey;
+ DecoderBufferAttachment() = default;
+ ~DecoderBufferAttachment() override = default;
+
+ bool IsLockedToAgentCluster() const override { return !buffers_.IsEmpty(); }
+
+ size_t size() const { return buffers_.size(); }
+
+ DecoderBufferVector& Buffers() { return buffers_; }
+
+ const DecoderBufferVector& Buffers() const { return buffers_; }
+
+ private:
+ DecoderBufferVector buffers_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_BUFFER_ATTACHMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.cc b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
index 2247ac3c10e..fbb40f4a6a2 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/modules/webcodecs/audio_decoder.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_config_eval.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_state_helper.h"
+#include "third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h"
#include "third_party/blink/renderer/modules/webcodecs/video_decoder.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -50,19 +51,9 @@
namespace blink {
namespace {
-
constexpr const char kCategory[] = "media";
base::AtomicSequenceNumber g_sequence_num_for_counters;
-
-void GetGpuFactoriesOnMainThread(
- media::GpuVideoAcceleratorFactories** gpu_factories_out,
- base::WaitableEvent* waitable_event) {
- DCHECK(IsMainThread());
- *gpu_factories_out = Platform::Current()->GetGpuFactories();
- waitable_event->Signal();
-}
-
} // namespace
// static
@@ -88,35 +79,14 @@ DecoderTemplate<Traits>::DecoderTemplate(ScriptState* script_state,
ExecutionContext* context = GetExecutionContext();
DCHECK(context);
- // TODO(crbug.com/1151005): Use a real MediaLog in worker contexts too.
- if (IsMainThread()) {
- logger_ = std::make_unique<CodecLogger>(
- context, context->GetTaskRunner(TaskType::kInternalMedia));
- } else {
- // This will create a logger backed by a NullMediaLog, which does nothing.
- logger_ = std::make_unique<CodecLogger>();
- }
+ logger_ = std::make_unique<CodecLogger>(
+ context, context->GetTaskRunner(TaskType::kInternalMedia));
logger_->log()->SetProperty<media::MediaLogProperty::kFrameUrl>(
context->Url().GetString().Ascii());
output_cb_ = init->output();
error_cb_ = init->error();
-
- if (Traits::kNeedsGpuFactories) {
- if (IsMainThread()) {
- gpu_factories_ = Platform::Current()->GetGpuFactories();
- } else {
- base::WaitableEvent waitable_event;
- if (PostCrossThreadTask(
- *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
- CrossThreadBindOnce(&GetGpuFactoriesOnMainThread,
- CrossThreadUnretained(&gpu_factories_),
- CrossThreadUnretained(&waitable_event)))) {
- waitable_event.Wait();
- }
- }
- }
}
template <typename Traits>
@@ -142,7 +112,7 @@ bool DecoderTemplate<Traits>::IsClosed() {
template <typename Traits>
HardwarePreference DecoderTemplate<Traits>::GetHardwarePreference(
const ConfigType&) {
- return HardwarePreference::kAllow;
+ return HardwarePreference::kNoPreference;
}
template <typename Traits>
@@ -178,7 +148,10 @@ void DecoderTemplate<Traits>::configure(const ConfigType* config,
break;
}
+ MarkCodecActive();
+
state_ = V8CodecState(V8CodecState::Enum::kConfigured);
+ require_key_frame_ = true;
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kConfigure;
@@ -203,14 +176,24 @@ void DecoderTemplate<Traits>::decode(const InputType* chunk,
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kDecode;
request->reset_generation = reset_generation_;
- auto status_or_buffer = MakeDecoderBuffer(*chunk);
+ auto status_or_buffer =
+ MakeDecoderBuffer(*chunk, /*verify_key_frame=*/require_key_frame_);
if (status_or_buffer.has_value()) {
request->decoder_buffer = std::move(status_or_buffer).value();
+ require_key_frame_ = false;
} else {
request->status = std::move(status_or_buffer).error();
+ if (request->status.code() == media::StatusCode::kKeyFrameRequired) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kDataError,
+ "A key frame is required after configure() or flush().");
+ return;
+ }
}
+ MarkCodecActive();
+
requests_.push_back(request);
++num_pending_decodes_;
ProcessRequests();
@@ -225,6 +208,10 @@ ScriptPromise DecoderTemplate<Traits>::flush(ExceptionState& exception_state) {
if (ThrowIfCodecStateUnconfigured(state_, "flush", exception_state))
return ScriptPromise();
+ MarkCodecActive();
+
+ require_key_frame_ = true;
+
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kFlush;
ScriptPromiseResolver* resolver =
@@ -242,6 +229,8 @@ void DecoderTemplate<Traits>::reset(ExceptionState& exception_state) {
if (ThrowIfCodecStateClosed(state_, "reset", exception_state))
return;
+ MarkCodecActive();
+
ResetAlgorithm();
}
@@ -264,7 +253,10 @@ void DecoderTemplate<Traits>::ProcessRequests() {
// Skip processing for requests that are canceled by a recent reset().
if (request->reset_generation != reset_generation_) {
if (request->resolver) {
- request->resolver.Release()->Reject();
+ // TODO(crbug.com/1229313): We might be in a Shutdown(), in which case
+ // this may actually be due to an error or close().
+ request->resolver.Release()->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kAbortError, "Aborted due to reset()"));
}
requests_.pop_front();
continue;
@@ -305,52 +297,69 @@ bool DecoderTemplate<Traits>::ProcessConfigureRequest(Request* request) {
DCHECK_EQ(request->type, Request::Type::kConfigure);
DCHECK(request->media_config);
+ if (decoder_ &&
+ pending_decodes_.size() + 1 >
+ static_cast<size_t>(Traits::GetMaxDecodeRequests(*decoder_))) {
+ // Try again after OnDecodeDone().
+ return false;
+ }
+
// TODO(sandersd): Record this configuration as pending but don't apply it
// until there is a decode request.
+ pending_request_ = request;
+ pending_request_->StartTracing();
- if (!decoder_) {
- pending_request_ = request;
- pending_request_->StartTracing();
+ if (gpu_factories_.has_value()) {
+ ContinueConfigureWithGpuFactories(request, gpu_factories_.value());
+ } else if (Traits::kNeedsGpuFactories) {
+ RetrieveGpuFactoriesWithKnownDecoderSupport(CrossThreadBindOnce(
+ &DecoderTemplate<Traits>::ContinueConfigureWithGpuFactories,
+ WrapCrossThreadPersistent(this), WrapCrossThreadPersistent(request)));
+ } else {
+ ContinueConfigureWithGpuFactories(request, nullptr);
+ }
+ return true;
+}
+
+template <typename Traits>
+void DecoderTemplate<Traits>::ContinueConfigureWithGpuFactories(
+ Request* request,
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ DCHECK(request);
+ DCHECK_EQ(request->type, Request::Type::kConfigure);
+
+ gpu_factories_ = gpu_factories;
+ if (request->reset_generation != reset_generation_)
+ return;
+ if (!decoder_) {
decoder_ = Traits::CreateDecoder(*ExecutionContext::From(script_state_),
- gpu_factories_, logger_->log());
+ gpu_factories_.value(), logger_->log());
if (!decoder_) {
Shutdown(
logger_->MakeException("Internal error: Could not create decoder.",
media::StatusCode::kDecoderCreationFailed));
- return false;
+ return;
}
+ SetHardwarePreference(request->hw_pref.value());
// Processing continues in OnInitializeDone().
// Note: OnInitializeDone() must not call ProcessRequests() reentrantly,
// which can happen if InitializeDecoder() calls it synchronously.
initializing_sync_ = true;
-
- SetHardwarePreference(pending_request_->hw_pref.value());
Traits::InitializeDecoder(
- *decoder_, pending_request_->low_delay.value(),
- *pending_request_->media_config,
+ *decoder_, request->low_delay.value(), *request->media_config,
WTF::Bind(&DecoderTemplate::OnInitializeDone, WrapWeakPersistent(this)),
WTF::BindRepeating(&DecoderTemplate::OnOutput, WrapWeakPersistent(this),
reset_generation_));
initializing_sync_ = false;
- return true;
- }
-
- if (pending_decodes_.size() + 1 >
- size_t{Traits::GetMaxDecodeRequests(*decoder_)}) {
- // Try again after OnDecodeDone().
- return false;
+ return;
}
// Processing continues in OnFlushDone().
- pending_request_ = request;
- pending_request_->StartTracing();
-
decoder_->Decode(
media::DecoderBuffer::CreateEOSBuffer(),
WTF::Bind(&DecoderTemplate::OnFlushDone, WrapWeakPersistent(this)));
- return true;
}
template <typename Traits>
@@ -369,7 +378,7 @@ bool DecoderTemplate<Traits>::ProcessDecodeRequest(Request* request) {
}
if (pending_decodes_.size() + 1 >
- size_t{Traits::GetMaxDecodeRequests(*decoder_)}) {
+ static_cast<size_t>(Traits::GetMaxDecodeRequests(*decoder_))) {
// Try again after OnDecodeDone().
return false;
}
@@ -420,7 +429,7 @@ bool DecoderTemplate<Traits>::ProcessFlushRequest(Request* request) {
DCHECK(decoder_);
if (pending_decodes_.size() + 1 >
- size_t{Traits::GetMaxDecodeRequests(*decoder_)}) {
+ static_cast<size_t>(Traits::GetMaxDecodeRequests(*decoder_))) {
// Try again after OnDecodeDone().
return false;
}
@@ -468,8 +477,12 @@ void DecoderTemplate<Traits>::Shutdown(DOMException* exception) {
// Abort pending work (otherwise it will never complete)
if (pending_request_) {
- if (pending_request_->resolver)
- pending_request_->resolver.Release()->Reject();
+ if (pending_request_->resolver) {
+ pending_request_->resolver.Release()->Reject(
+ MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kAbortError,
+ exception ? "Aborted due to error" : "Aborted due to close()"));
+ }
pending_request_.Release()->EndTracing(/*shutting_down*/ true);
}
@@ -564,8 +577,12 @@ void DecoderTemplate<Traits>::OnFlushDone(media::Status status) {
if (is_flush && pending_request_->reset_generation != reset_generation_) {
pending_request_->EndTracing();
- // TODO(crbug.com/1201299): Emit an AbortError.
- pending_request_.Release()->resolver.Release()->Reject();
+ // We must reject the Promise for consistency in the behavior of reset().
+ // It's also possible that we already dropped outputs, so the flush() may be
+ // incomplete despite finishing successfully.
+ pending_request_.Release()->resolver.Release()->Reject(
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
+ "Aborted due to reset()"));
ProcessRequests();
return;
}
@@ -692,6 +709,8 @@ void DecoderTemplate<Traits>::OnOutput(uint32_t reset_generation,
output_cb_->InvokeAndReportException(nullptr, blink_output);
TRACE_EVENT_END0(kCategory, GetTraceNames()->output.c_str());
+
+ MarkCodecActive();
}
template <typename Traits>
@@ -718,6 +737,13 @@ void DecoderTemplate<Traits>::Trace(Visitor* visitor) const {
visitor->Trace(pending_decodes_);
ScriptWrappable::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
+ ReclaimableCodec::Trace(visitor);
+}
+
+template <typename Traits>
+void DecoderTemplate<Traits>::OnCodecReclaimed(DOMException* exception) {
+ TRACE_EVENT0(kCategory, GetTraceNames()->reclaimed.c_str());
+ Shutdown(exception);
}
template <typename Traits>
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.h b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.h
index 58522f721af..bc186b60c84 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template.h
@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/modules/webcodecs/codec_logger.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_trace_names.h"
#include "third_party/blink/renderer/modules/webcodecs/hardware_preference.h"
+#include "third_party/blink/renderer/modules/webcodecs/reclaimable_codec.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/heap.h"
@@ -39,6 +40,7 @@ template <typename Traits>
class MODULES_EXPORT DecoderTemplate
: public ScriptWrappable,
public ActiveScriptWrappable<DecoderTemplate<Traits>>,
+ public ReclaimableCodec,
public ExecutionContextLifecycleObserver {
public:
typedef typename Traits::ConfigType ConfigType;
@@ -99,8 +101,12 @@ class MODULES_EXPORT DecoderTemplate
// |chunk|. If there is an error in the conversion process, the resulting
// DecoderBuffer will be null, and |out_status| will contain a description of
// the error.
+ //
+ // When |verify_key_frame| is true, clients are expected to verify and set the
+ // DecoderBuffer::is_key_frame() value. I.e., they must process the encoded
+ // data to ensure the value is actually what the chunk says it is.
virtual media::StatusOr<scoped_refptr<media::DecoderBuffer>>
- MakeDecoderBuffer(const InputType& chunk) = 0;
+ MakeDecoderBuffer(const InputType& chunk, bool verify_key_frame) = 0;
private:
struct Request final : public GarbageCollected<Request> {
@@ -154,6 +160,9 @@ class MODULES_EXPORT DecoderTemplate
void ProcessRequests();
bool ProcessConfigureRequest(Request* request);
+ void ContinueConfigureWithGpuFactories(
+ Request* request,
+ media::GpuVideoAcceleratorFactories* factories);
bool ProcessDecodeRequest(Request* request);
bool ProcessFlushRequest(Request* request);
bool ProcessResetRequest(Request* request);
@@ -170,6 +179,9 @@ class MODULES_EXPORT DecoderTemplate
// Helper function making it easier to check |state_|.
bool IsClosed();
+ // ReclaimableCodec implementation.
+ void OnCodecReclaimed(DOMException*) override;
+
void TraceQueueSizes() const;
Member<ScriptState> script_state_;
@@ -191,7 +203,9 @@ class MODULES_EXPORT DecoderTemplate
std::unique_ptr<CodecLogger> logger_;
- media::GpuVideoAcceleratorFactories* gpu_factories_ = nullptr;
+ // Empty - GPU factories haven't been retrieved yet.
+ // nullptr - We tried to get GPU factories, but acceleration is unavailable.
+ absl::optional<media::GpuVideoAcceleratorFactories*> gpu_factories_;
// Cached config from the last kConfigure request which successfully completed
// initialization.
@@ -210,6 +224,9 @@ class MODULES_EXPORT DecoderTemplate
int trace_counter_id_;
HeapHashMap<uint32_t, Member<Request>> pending_decodes_;
+
+ // Keyframes are required after configure(), flush(), and reset().
+ bool require_key_frame_ = true;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template_test.cc
index 0bcf7de84f2..f56b122b232 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/decoder_template_test.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data_output_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h"
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.cc b/chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.cc
new file mode 100644
index 00000000000..b2d25ecdb7f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.cc
@@ -0,0 +1,90 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/dom_rect_util.h"
+
+#include <stdint.h>
+#include <cmath>
+#include <limits>
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+namespace {
+
+// Safely converts a double to a non-negative int, which matches the
+// requirements of gfx::Rect.
+int32_t ToInt31(double value,
+ const char* context,
+ const char* name,
+ ExceptionState& exception_state) {
+ // Reject NaN and +/- Infinity. Positive subnormals truncate to zero so they
+ // are fine.
+ if (!std::isfinite(value)) {
+ exception_state.ThrowTypeError(
+ String::Format("%s.%s must be finite.", context, name));
+ return 0;
+ }
+
+ // If we didn't truncate before comparison, INT_MAX + 0.1 would be rejected.
+ value = std::trunc(value);
+
+ if (value < 0) {
+ exception_state.ThrowTypeError(
+ String::Format("%s.%s cannot be negative.", context, name));
+ return 0;
+ }
+
+ if (value > std::numeric_limits<int32_t>::max()) {
+ exception_state.ThrowTypeError(
+ String::Format("%s.%s exceeds implementation limit.", context, name));
+ return 0;
+ }
+
+ return static_cast<int32_t>(value);
+}
+
+} // namespace
+
+gfx::Rect ToGfxRect(DOMRectInit* rect,
+ const char* name,
+ ExceptionState& exception_state) {
+ int32_t x = ToInt31(rect->x(), name, "x", exception_state);
+ if (exception_state.HadException())
+ return gfx::Rect();
+
+ int32_t y = ToInt31(rect->y(), name, "y", exception_state);
+ if (exception_state.HadException())
+ return gfx::Rect();
+
+ int32_t width = ToInt31(rect->width(), name, "width", exception_state);
+ if (exception_state.HadException())
+ return gfx::Rect();
+
+ int32_t height = ToInt31(rect->height(), name, "height", exception_state);
+ if (exception_state.HadException())
+ return gfx::Rect();
+
+ // |right = x + width| must fit in int. Not actually required by gfx::Rect but
+ // probably not handled by code that uses them.
+ if (static_cast<int64_t>(x) + width > std::numeric_limits<int32_t>::max()) {
+ exception_state.ThrowTypeError(
+ String::Format("%s.right exceeds implementation limit.", name));
+ return gfx::Rect();
+ }
+
+ // Same for |bottom = y + height|.
+ if (static_cast<int64_t>(y) + height > std::numeric_limits<int32_t>::max()) {
+ exception_state.ThrowTypeError(
+ String::Format("%s.bottom exceeds implementation limit.", name));
+ return gfx::Rect();
+ }
+
+ return gfx::Rect(x, y, width, height);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.h b/chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.h
new file mode 100644
index 00000000000..2bb0516d487
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/dom_rect_util.h
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DOM_RECT_UTIL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DOM_RECT_UTIL_H_
+
+#include "ui/gfx/geometry/rect.h"
+
+namespace blink {
+
+class DOMRectInit;
+class ExceptionState;
+
+// Convert a DOMRectInit to a gfx::Rect. Validates that all values (including
+// the computed |right| and |bottom|) are nonnegative and fit in an int32_t.
+// |name| is the variable name in error messages, eg. "name.x".
+gfx::Rect ToGfxRect(DOMRectInit*, const char* name, ExceptionState&);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DOM_RECT_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.cc b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.cc
index b1e56ba90b5..1110581f5d1 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.cc
@@ -7,40 +7,79 @@
#include <utility>
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk_init.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
EncodedAudioChunk* EncodedAudioChunk::Create(
const EncodedAudioChunkInit* init) {
+ auto data_wrapper = AsSpan<const uint8_t>(init->data());
+ auto buffer = data_wrapper.empty()
+ ? base::MakeRefCounted<media::DecoderBuffer>(0)
+ : media::DecoderBuffer::CopyFrom(data_wrapper.data(),
+ data_wrapper.size());
+
+ // Clamp within bounds of our internal TimeDelta-based duration. See
+ // media/base/timestamp_constants.h
auto timestamp = base::TimeDelta::FromMicroseconds(init->timestamp());
- bool key_frame = (init->type() == "key");
- DOMArrayPiece piece(init->data());
-
- // A full copy of the data happens here.
- auto* buffer = piece.IsNull()
- ? nullptr
- : DOMArrayBuffer::Create(piece.Data(), piece.ByteLength());
- return MakeGarbageCollected<EncodedAudioChunk>(timestamp, key_frame, buffer);
+ if (timestamp == media::kNoTimestamp)
+ timestamp = base::TimeDelta::FiniteMin();
+ else if (timestamp == media::kInfiniteDuration)
+ timestamp = base::TimeDelta::FiniteMax();
+ buffer->set_timestamp(timestamp);
+
+ // media::kNoTimestamp corresponds to base::TimeDelta::Min(), and internally
+ // denotes the absence of duration. We use base::TimeDelta::FiniteMax() -
+ // which is one less than base::TimeDelta::Max() - because
+ // base::TimeDelta::Max() is reserved for media::kInfiniteDuration, and is
+ // handled differently.
+ buffer->set_duration(
+ init->hasDuration()
+ ? base::TimeDelta::FromMicroseconds(std::min(
+ uint64_t{base::TimeDelta::FiniteMax().InMicroseconds()},
+ init->duration()))
+ : media::kNoTimestamp);
+
+ buffer->set_is_key_frame(init->type() == "key");
+ return MakeGarbageCollected<EncodedAudioChunk>(std::move(buffer));
}
-EncodedAudioChunk::EncodedAudioChunk(base::TimeDelta timestamp,
- bool key_frame,
- DOMArrayBuffer* buffer)
- : timestamp_(timestamp), key_frame_(key_frame), buffer_(buffer) {}
+EncodedAudioChunk::EncodedAudioChunk(scoped_refptr<media::DecoderBuffer> buffer)
+ : buffer_(std::move(buffer)) {}
String EncodedAudioChunk::type() const {
- return key_frame_ ? "key" : "delta";
+ return buffer_->is_key_frame() ? "key" : "delta";
}
int64_t EncodedAudioChunk::timestamp() const {
- return timestamp_.InMicroseconds();
+ return buffer_->timestamp().InMicroseconds();
+}
+
+absl::optional<uint64_t> EncodedAudioChunk::duration() const {
+ if (buffer_->duration() == media::kNoTimestamp)
+ return absl::nullopt;
+ return buffer_->duration().InMicroseconds();
+}
+
+uint64_t EncodedAudioChunk::byteLength() const {
+ return buffer_->data_size();
}
-DOMArrayBuffer* EncodedAudioChunk::data() const {
- return buffer_;
+void EncodedAudioChunk::copyTo(const AllowSharedBufferSource* destination,
+ ExceptionState& exception_state) {
+ // Validate destination buffer.
+ auto dest_wrapper = AsSpan<uint8_t>(destination);
+ if (!dest_wrapper.data()) {
+ exception_state.ThrowTypeError("destination is detached.");
+ return;
+ }
+ if (dest_wrapper.size() < buffer_->data_size()) {
+ exception_state.ThrowTypeError("destination is not large enough.");
+ return;
+ }
+
+ // Copy data.
+ memcpy(dest_wrapper.data(), buffer_->data(), buffer_->data_size());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h
index d7856e9459a..86c5ce94b78 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h
@@ -5,39 +5,38 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ENCODED_AUDIO_CHUNK_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ENCODED_AUDIO_CHUNK_H_
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
+#include "media/base/decoder_buffer.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
-class DOMArrayBuffer;
class EncodedAudioChunkInit;
+class ExceptionState;
class MODULES_EXPORT EncodedAudioChunk final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- EncodedAudioChunk(base::TimeDelta timestamp,
- bool key_frame,
- DOMArrayBuffer* buffer);
+ explicit EncodedAudioChunk(scoped_refptr<media::DecoderBuffer> buffer);
static EncodedAudioChunk* Create(const EncodedAudioChunkInit* init);
// encoded_audio_chunk.idl implementation.
String type() const;
int64_t timestamp() const;
- DOMArrayBuffer* data() const;
+ uint64_t byteLength() const;
+ absl::optional<uint64_t> duration() const;
+ void copyTo(const AllowSharedBufferSource* destination,
+ ExceptionState& exception_state);
- void Trace(Visitor* visitor) const override {
- visitor->Trace(buffer_);
- ScriptWrappable::Trace(visitor);
- }
+ scoped_refptr<media::DecoderBuffer> buffer() const { return buffer_; }
private:
- base::TimeDelta timestamp_;
- bool key_frame_ = false;
- Member<DOMArrayBuffer> buffer_;
+ scoped_refptr<media::DecoderBuffer> buffer_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl
index a2c69b7315c..103dfca6c53 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl
@@ -14,7 +14,8 @@ enum EncodedAudioChunkType {
constructor(EncodedAudioChunkInit init);
readonly attribute EncodedAudioChunkType type;
readonly attribute long long timestamp; // microseconds
- readonly attribute ArrayBuffer data;
-
- // TODO(chcunningham): Duration? Or better yet, should we have a unified audio/video "chunk"?
+ readonly attribute unsigned long byteLength;
+ readonly attribute unsigned long long? duration;
+ [RaisesException]
+ void copyTo(AllowSharedBufferSource destination);
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_init.idl
index 41ff9778b50..2d92fe055da 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_init.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_init.idl
@@ -6,6 +6,7 @@
dictionary EncodedAudioChunkInit {
required EncodedAudioChunkType type;
- required long long timestamp; // microseconds
- required BufferSource data;
+ required [EnforceRange] long long timestamp; // microseconds
+ [EnforceRange] unsigned long long duration; // microseconds
+ required AllowSharedBufferSource data;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.cc b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.cc
index 26beb88296d..4bb82cb2676 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.cc
@@ -7,49 +7,79 @@
#include <utility>
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk_init.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
EncodedVideoChunk* EncodedVideoChunk::Create(EncodedVideoChunkInit* init) {
+ auto data_wrapper = AsSpan<const uint8_t>(init->data());
+ auto buffer = data_wrapper.empty()
+ ? base::MakeRefCounted<media::DecoderBuffer>(0)
+ : media::DecoderBuffer::CopyFrom(data_wrapper.data(),
+ data_wrapper.size());
+
+ // Clamp within bounds of our internal TimeDelta-based duration. See
+ // media/base/timestamp_constants.h
auto timestamp = base::TimeDelta::FromMicroseconds(init->timestamp());
- bool key_frame = (init->type() == "key");
- DOMArrayPiece piece(init->data());
-
- // A full copy of the data happens here.
- auto* buffer = piece.IsNull()
- ? nullptr
- : DOMArrayBuffer::Create(piece.Data(), piece.ByteLength());
- auto* result =
- MakeGarbageCollected<EncodedVideoChunk>(timestamp, key_frame, buffer);
- if (init->hasDuration())
- result->duration_ = base::TimeDelta::FromMicroseconds(init->duration());
- return result;
+ if (timestamp == media::kNoTimestamp)
+ timestamp = base::TimeDelta::FiniteMin();
+ else if (timestamp == media::kInfiniteDuration)
+ timestamp = base::TimeDelta::FiniteMax();
+ buffer->set_timestamp(timestamp);
+
+ // media::kNoTimestamp corresponds to base::TimeDelta::Min(), and internally
+ // denotes the absence of duration. We use base::TimeDelta::FiniteMax() --
+ // which is one less than base::TimeDelta::Max() -- because
+ // base::TimeDelta::Max() is reserved for media::kInfiniteDuration, and is
+ // handled differently.
+ buffer->set_duration(
+ init->hasDuration()
+ ? base::TimeDelta::FromMicroseconds(std::min(
+ uint64_t{base::TimeDelta::FiniteMax().InMicroseconds()},
+ init->duration()))
+ : media::kNoTimestamp);
+
+ buffer->set_is_key_frame(init->type() == "key");
+ return MakeGarbageCollected<EncodedVideoChunk>(std::move(buffer));
}
-EncodedVideoChunk::EncodedVideoChunk(base::TimeDelta timestamp,
- bool key_frame,
- DOMArrayBuffer* buffer)
- : timestamp_(timestamp), key_frame_(key_frame), buffer_(buffer) {}
+EncodedVideoChunk::EncodedVideoChunk(scoped_refptr<media::DecoderBuffer> buffer)
+ : buffer_(std::move(buffer)) {}
String EncodedVideoChunk::type() const {
- return key_frame_ ? "key" : "delta";
+ return buffer_->is_key_frame() ? "key" : "delta";
}
int64_t EncodedVideoChunk::timestamp() const {
- return timestamp_.InMicroseconds();
+ return buffer_->timestamp().InMicroseconds();
}
absl::optional<uint64_t> EncodedVideoChunk::duration() const {
- if (!duration_.has_value())
+ if (buffer_->duration() == media::kNoTimestamp)
return absl::nullopt;
- return duration_->InMicroseconds();
+ return buffer_->duration().InMicroseconds();
}
-DOMArrayBuffer* EncodedVideoChunk::data() const {
- return buffer_;
+uint64_t EncodedVideoChunk::byteLength() const {
+ return buffer_->data_size();
+}
+
+void EncodedVideoChunk::copyTo(const AllowSharedBufferSource* destination,
+ ExceptionState& exception_state) {
+ // Validate destination buffer.
+ auto dest_wrapper = AsSpan<uint8_t>(destination);
+ if (!dest_wrapper.data()) {
+ exception_state.ThrowTypeError("destination is detached.");
+ return;
+ }
+ if (dest_wrapper.size() < buffer_->data_size()) {
+ exception_state.ThrowTypeError("destination is not large enough.");
+ return;
+ }
+
+ // Copy data.
+ memcpy(dest_wrapper.data(), buffer_->data(), buffer_->data_size());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h
index f6dc84a6f22..b89ccb62439 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h
@@ -5,22 +5,22 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ENCODED_VIDEO_CHUNK_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_ENCODED_VIDEO_CHUNK_H_
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
+#include "media/base/decoder_buffer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
-
-class DOMArrayBuffer;
class EncodedVideoChunkInit;
+class ExceptionState;
class MODULES_EXPORT EncodedVideoChunk final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- EncodedVideoChunk(base::TimeDelta timestamp,
- bool key_frame,
- DOMArrayBuffer* buffer);
+ explicit EncodedVideoChunk(scoped_refptr<media::DecoderBuffer> buffer);
static EncodedVideoChunk* Create(EncodedVideoChunkInit* init);
@@ -28,18 +28,14 @@ class MODULES_EXPORT EncodedVideoChunk final : public ScriptWrappable {
String type() const;
int64_t timestamp() const;
absl::optional<uint64_t> duration() const;
- DOMArrayBuffer* data() const;
+ uint64_t byteLength() const;
+ void copyTo(const AllowSharedBufferSource* destination,
+ ExceptionState& exception_state);
- void Trace(Visitor* visitor) const override {
- visitor->Trace(buffer_);
- ScriptWrappable::Trace(visitor);
- }
+ scoped_refptr<media::DecoderBuffer> buffer() const { return buffer_; }
private:
- base::TimeDelta timestamp_;
- bool key_frame_ = false;
- absl::optional<base::TimeDelta> duration_;
- Member<DOMArrayBuffer> buffer_;
+ scoped_refptr<media::DecoderBuffer> buffer_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.idl b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.idl
index 035f745e8b7..353690d4dbf 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.idl
@@ -16,5 +16,8 @@ enum EncodedVideoChunkType {
// TODO: Add frame dependency information
readonly attribute long long timestamp; // microseconds
readonly attribute unsigned long long? duration; // microseconds
- readonly attribute ArrayBuffer data;
+ readonly attribute unsigned long byteLength;
+
+ [RaisesException]
+ void copyTo(AllowSharedBufferSource destination);
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_init.idl
index a499ecf8de3..03127ed8df7 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_init.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_init.idl
@@ -6,7 +6,7 @@
dictionary EncodedVideoChunkInit {
required EncodedVideoChunkType type;
- required long long timestamp; // microseconds
- unsigned long long duration; // microseconds
- required BufferSource data;
+ required [EnforceRange] long long timestamp; // microseconds
+ [EnforceRange] unsigned long long duration; // microseconds
+ required AllowSharedBufferSource data;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_metadata.idl b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_metadata.idl
index da51cd2346c..4ae269533c8 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_metadata.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_metadata.idl
@@ -6,5 +6,5 @@
dictionary EncodedVideoChunkMetadata {
VideoDecoderConfig decoderConfig;
- unsigned long temporalLayerId;
+ [EnforceRange] unsigned long temporalLayerId;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc
index 4ab072ec0bd..78a183cb968 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc
@@ -5,7 +5,9 @@
#include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk_init.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -14,15 +16,14 @@ namespace {
class EncodedVideoChunkTest : public testing::Test {
public:
- ArrayBufferOrArrayBufferView StringToBuffer(std::string data) {
- ArrayBufferOrArrayBufferView result;
- result.SetArrayBuffer(DOMArrayBuffer::Create(data.data(), data.size()));
- return result;
+ AllowSharedBufferSource* StringToBuffer(std::string data) {
+ return MakeGarbageCollected<AllowSharedBufferSource>(
+ DOMArrayBuffer::Create(data.data(), data.size()));
}
- std::string BufferToString(DOMArrayBuffer* buffer) {
- return std::string(static_cast<char*>(buffer->Data()),
- buffer->ByteLength());
+ std::string BufferToString(const media::DecoderBuffer& buffer) {
+ return std::string(reinterpret_cast<const char*>(buffer.data()),
+ buffer.data_size());
}
};
@@ -38,7 +39,7 @@ TEST_F(EncodedVideoChunkTest, ConstructorAndAttributes) {
EXPECT_EQ(type, encoded->type());
EXPECT_EQ(timestamp, encoded->timestamp());
- EXPECT_EQ(data, BufferToString(encoded->data()));
+ EXPECT_EQ(data, BufferToString(*encoded->buffer()));
EXPECT_FALSE(encoded->duration().has_value());
}
@@ -56,7 +57,7 @@ TEST_F(EncodedVideoChunkTest, ConstructorWithDuration) {
EXPECT_EQ(type, encoded->type());
EXPECT_EQ(timestamp, encoded->timestamp());
- EXPECT_EQ(data, BufferToString(encoded->data()));
+ EXPECT_EQ(data, BufferToString(*encoded->buffer()));
ASSERT_TRUE(encoded->duration().has_value());
EXPECT_EQ(duration, encoded->duration().value());
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.cc b/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
index c9be01f1fae..e160f5944a1 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
@@ -61,14 +61,8 @@ EncoderBase<Traits>::EncoderBase(ScriptState* script_state,
state_(V8CodecState::Enum::kUnconfigured),
script_state_(script_state),
trace_counter_id_(g_sequence_num_for_counters.GetNext()) {
- // TODO(crbug.com/1151005): Use a real MediaLog in worker contexts too.
- if (IsMainThread()) {
- logger_ = std::make_unique<CodecLogger>(
- GetExecutionContext(), Thread::MainThread()->GetTaskRunner());
- } else {
- // This will create a logger backed by a NullMediaLog, which does nothing.
- logger_ = std::make_unique<CodecLogger>();
- }
+ logger_ = std::make_unique<CodecLogger>(GetExecutionContext(),
+ Thread::Current()->GetTaskRunner());
media::MediaLog* log = logger_->log();
@@ -111,6 +105,8 @@ void EncoderBase<Traits>::configure(const ConfigType* config,
return;
}
+ MarkCodecActive();
+
Request* request = MakeGarbageCollected<Request>();
request->reset_count = reset_count_;
if (media_encoder_ && active_config_ &&
@@ -151,6 +147,8 @@ void EncoderBase<Traits>::encode(InputType* input,
return;
}
+ MarkCodecActive();
+
Request* request = MakeGarbageCollected<Request>();
request->reset_count = reset_count_;
request->type = Request::Type::kEncode;
@@ -184,6 +182,8 @@ ScriptPromise EncoderBase<Traits>::flush(ExceptionState& exception_state) {
if (ThrowIfCodecStateUnconfigured(state_, "flush", exception_state))
return ScriptPromise();
+ MarkCodecActive();
+
Request* request = MakeGarbageCollected<Request>();
request->resolver =
MakeGarbageCollected<ScriptPromiseResolver>(script_state_);
@@ -201,6 +201,8 @@ void EncoderBase<Traits>::reset(ExceptionState& exception_state) {
TRACE_EVENT0(kCategory, GetTraceNames()->reset.c_str());
+ MarkCodecActive();
+
state_ = V8CodecState(V8CodecState::Enum::kUnconfigured);
ResetInternal();
media_encoder_.reset();
@@ -331,6 +333,12 @@ void EncoderBase<Traits>::ProcessFlush(Request* request) {
}
template <typename Traits>
+void EncoderBase<Traits>::OnCodecReclaimed(DOMException* exception) {
+ TRACE_EVENT0(kCategory, GetTraceNames()->reclaimed.c_str());
+ HandleError(exception);
+}
+
+template <typename Traits>
void EncoderBase<Traits>::ContextDestroyed() {
state_ = V8CodecState(V8CodecState::Enum::kClosed);
logger_->Neuter();
@@ -358,6 +366,7 @@ void EncoderBase<Traits>::Trace(Visitor* visitor) const {
visitor->Trace(requests_);
ScriptWrappable::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
+ ReclaimableCodec::Trace(visitor);
}
template <typename Traits>
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.h b/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.h
index 53bbaf68157..6970b9af5f3 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/encoder_base.h
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_logger.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_trace_names.h"
+#include "third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
@@ -29,6 +30,7 @@ template <typename Traits>
class MODULES_EXPORT EncoderBase
: public ScriptWrappable,
public ActiveScriptWrappable<EncoderBase<Traits>>,
+ public ReclaimableCodec,
public ExecutionContextLifecycleObserver {
public:
using InitType = typename Traits::Init;
@@ -124,6 +126,9 @@ class MODULES_EXPORT EncoderBase
ExceptionState&) = 0;
virtual bool VerifyCodecSupport(InternalConfigType*, ExceptionState&) = 0;
+ // ReclaimableCodec implementation.
+ void OnCodecReclaimed(DOMException*) override;
+
void TraceQueueSizes() const;
std::unique_ptr<CodecLogger> logger_;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto b/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto
index d003a56b4ed..4c085dbff77 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto
@@ -75,6 +75,8 @@ message EncodedAudioChunk {
optional uint64 timestamp = 2;
+ optional uint64 duration = 3;
+
optional bytes data = 4;
}
@@ -90,6 +92,17 @@ message VideoFrameBitmapInit {
optional bytes rgb_bitmap = 4;
}
+enum AudioSampleFormat {
+ U8 = 0;
+ S16 = 1;
+ S32 = 2;
+ F32 = 3;
+ U8_PLANAR = 4;
+ S16_PLANAR = 5;
+ S32_PLANAR = 6;
+ F32_PLANAR = 7;
+}
+
message AudioDataInit {
optional uint64 timestamp = 1;
@@ -98,6 +111,8 @@ message AudioDataInit {
optional uint32 sample_rate = 3;
repeated bytes channels = 4;
+
+ required AudioSampleFormat format = 5;
}
message EncodeVideo {
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc b/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
index 86f3acad516..3ec5d8172d2 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
@@ -7,6 +7,7 @@
#include <string>
#include "media/base/limits.h"
+#include "media/base/sample_format.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_image_bitmap_options.h"
@@ -23,6 +24,7 @@
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.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/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.pb.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
@@ -57,7 +59,7 @@ VideoDecoderConfig* MakeVideoDecoderConfig(
DOMArrayBuffer* data_copy = DOMArrayBuffer::Create(
proto.description().data(), proto.description().size());
config->setDescription(
- ArrayBufferOrArrayBufferView::FromArrayBuffer(data_copy));
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy));
return config;
}
@@ -71,7 +73,7 @@ AudioDecoderConfig* MakeAudioDecoderConfig(
DOMArrayBuffer* data_copy = DOMArrayBuffer::Create(
proto.description().data(), proto.description().size());
config->setDescription(
- ArrayBufferOrArrayBufferView::FromArrayBuffer(data_copy));
+ MakeGarbageCollected<AllowSharedBufferSource>(data_copy));
return config;
}
@@ -107,11 +109,11 @@ String ToAccelerationType(
wc_fuzzer::ConfigureVideoEncoder_EncoderAccelerationPreference type) {
switch (type) {
case wc_fuzzer::ConfigureVideoEncoder_EncoderAccelerationPreference_ALLOW:
- return "allow";
+ return "no-preference";
case wc_fuzzer::ConfigureVideoEncoder_EncoderAccelerationPreference_DENY:
- return "deny";
+ return "prefer-software";
case wc_fuzzer::ConfigureVideoEncoder_EncoderAccelerationPreference_REQUIRE:
- return "require";
+ return "prefer-hardware";
}
}
@@ -124,30 +126,76 @@ String ToChunkType(wc_fuzzer::EncodedChunkType type) {
}
}
+String ToAudioSampleFormat(wc_fuzzer::AudioSampleFormat format) {
+ switch (format) {
+ case wc_fuzzer::AudioSampleFormat::U8:
+ return "u8";
+ case wc_fuzzer::AudioSampleFormat::S16:
+ return "s16";
+ case wc_fuzzer::AudioSampleFormat::S32:
+ return "s32";
+ case wc_fuzzer::AudioSampleFormat::F32:
+ return "f32";
+ case wc_fuzzer::AudioSampleFormat::U8_PLANAR:
+ return "u8-planar";
+ case wc_fuzzer::AudioSampleFormat::S16_PLANAR:
+ return "s16-planar";
+ case wc_fuzzer::AudioSampleFormat::S32_PLANAR:
+ return "s32-planar";
+ case wc_fuzzer::AudioSampleFormat::F32_PLANAR:
+ return "f32-planar";
+ }
+}
+
+int SampleFormatToSampleSize(V8AudioSampleFormat format) {
+ using FormatEnum = V8AudioSampleFormat::Enum;
+
+ switch (format.AsEnum()) {
+ case FormatEnum::kU8:
+ case FormatEnum::kU8Planar:
+ return 1;
+
+ case FormatEnum::kS16:
+ case FormatEnum::kS16Planar:
+ return 2;
+
+ case FormatEnum::kS32:
+ case FormatEnum::kS32Planar:
+ case FormatEnum::kF32:
+ case FormatEnum::kF32Planar:
+ return 4;
+ }
+}
+
EncodedVideoChunk* MakeEncodedVideoChunk(
const wc_fuzzer::EncodedVideoChunk& proto) {
- ArrayBufferOrArrayBufferView data;
- data.SetArrayBuffer(
+ auto* data = MakeGarbageCollected<AllowSharedBufferSource>(
DOMArrayBuffer::Create(proto.data().data(), proto.data().size()));
auto* init = EncodedVideoChunkInit::Create();
init->setTimestamp(proto.timestamp());
init->setType(ToChunkType(proto.type()));
- init->setDuration(proto.duration());
init->setData(data);
+
+ if (proto.has_duration())
+ init->setDuration(proto.duration());
+
return EncodedVideoChunk::Create(init);
}
EncodedAudioChunk* MakeEncodedAudioChunk(
const wc_fuzzer::EncodedAudioChunk& proto) {
- ArrayBufferOrArrayBufferView data;
- data.SetArrayBuffer(
+ auto* data = MakeGarbageCollected<AllowSharedBufferSource>(
DOMArrayBuffer::Create(proto.data().data(), proto.data().size()));
auto* init = EncodedAudioChunkInit::Create();
init->setTimestamp(proto.timestamp());
init->setType(ToChunkType(proto.type()));
init->setData(data);
+
+ if (proto.has_duration())
+ init->setDuration(proto.duration());
+
return EncodedAudioChunk::Create(init);
}
@@ -189,12 +237,7 @@ VideoFrame* MakeVideoFrame(ScriptState* script_state,
video_frame_init->setTimestamp(proto.timestamp());
video_frame_init->setDuration(proto.duration());
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* source = MakeGarbageCollected<V8CanvasImageSource>(image_bitmap);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasImageSourceUnion source;
- source.SetImageBitmap(image_bitmap);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return VideoFrame::Create(script_state, source, video_frame_init,
IGNORE_EXCEPTION_FOR_TESTING);
@@ -202,27 +245,41 @@ VideoFrame* MakeVideoFrame(ScriptState* script_state,
AudioData* MakeAudioData(ScriptState* script_state,
const wc_fuzzer::AudioDataInit& proto) {
- if (proto.channels().size() > media::limits::kMaxChannels)
+ if (!proto.channels().size() ||
+ proto.channels().size() > media::limits::kMaxChannels)
return nullptr;
- if (proto.length() > media::limits::kMaxSamplesPerPacket)
+ if (!proto.length() || proto.length() > media::limits::kMaxSamplesPerPacket)
return nullptr;
- auto bus = AudioBus::Create(proto.channels().size(), proto.length());
- if (!bus)
- return nullptr;
+ V8AudioSampleFormat format =
+ V8AudioSampleFormat::Create(ToAudioSampleFormat(proto.format())).value();
+
+ int size_per_sample = SampleFormatToSampleSize(format);
+ int number_of_samples = proto.channels().size() * proto.length();
+
+ auto* buffer = DOMArrayBuffer::Create(number_of_samples, size_per_sample);
+
+ memset(buffer->Data(), 0, number_of_samples * size_per_sample);
+
for (int i = 0; i < proto.channels().size(); i++) {
- size_t max_size = proto.length() * sizeof(float);
- memset(bus->Channel(i)->MutableData(), 0, max_size);
+ size_t max_plane_size = proto.length() * size_per_sample;
auto* data = proto.channels().Get(i).data();
- auto size = std::min(proto.channels().Get(i).size(), max_size);
- memcpy(bus->Channel(i)->MutableData(), data, size);
+ auto size = std::min(proto.channels().Get(i).size(), max_plane_size);
+
+ void* plane_start =
+ reinterpret_cast<uint8_t*>(buffer->Data()) + i * max_plane_size;
+ memcpy(plane_start, data, size);
}
auto* init = AudioDataInit::Create();
init->setTimestamp(proto.timestamp());
- init->setBuffer(AudioBuffer::CreateFromAudioBus(bus.get()));
+ init->setNumberOfFrames(proto.length());
+ init->setNumberOfChannels(proto.channels().size());
+ init->setSampleRate(proto.sample_rate());
+ init->setFormat(format);
+ init->setData(MakeGarbageCollected<AllowSharedBufferSource>(buffer));
return AudioData::Create(init, IGNORE_EXCEPTION_FOR_TESTING);
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.cc b/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.cc
index 0445d415e7f..119ef8b4144 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.cc
@@ -57,4 +57,22 @@ void RetrieveGpuFactoriesWithKnownEncoderSupport(OutputCB callback) {
RetrieveGpuFactories(std::move(factories_callback));
}
+void RetrieveGpuFactoriesWithKnownDecoderSupport(OutputCB callback) {
+ auto on_factories_received =
+ [](OutputCB result_cb, media::GpuVideoAcceleratorFactories* factories) {
+ if (!factories || factories->IsDecoderSupportKnown()) {
+ std::move(result_cb).Run(factories);
+ } else {
+ factories->NotifyDecoderSupportKnown(ConvertToBaseOnceCallback(
+ CrossThreadBindOnce(OnSupportKnown, std::move(result_cb),
+ CrossThreadUnretained(factories))));
+ }
+ };
+
+ auto factories_callback =
+ CrossThreadBindOnce(on_factories_received, std::move(callback));
+
+ RetrieveGpuFactories(std::move(factories_callback));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h b/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h
index 405c31e284c..5728fa8e741 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h
@@ -21,11 +21,16 @@ using OutputCB = CrossThreadOnceFunction<void(
// Specifically
// 1. It gets GPU factories from the main thread when called from a worker
// 2. Makes sure that GPU factories already know about supported encoding
-// and decoding profiles.
+// profiles.
void RetrieveGpuFactoriesWithKnownEncoderSupport(OutputCB callback);
-// TODO: Add RetrieveGpuFactoriesWithKnownDecoderSupport and use it in
-// VideoDecoder.
+// Retrieves an instance of GpuVideoAcceleratorFactories ready
+// for accelerated video decoding.
+// Specifically
+// 1. It gets GPU factories from the main thread when called from a worker
+// 2. Makes sure that GPU factories already know about supported decoding
+// profiles.
+void RetrieveGpuFactoriesWithKnownDecoderSupport(OutputCB callback);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.cc b/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.cc
index 1d1fbffc8a5..9b6b89e1f6e 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.cc
@@ -9,17 +9,17 @@
namespace blink {
HardwarePreference StringToHardwarePreference(const String& value) {
- if (value == "allow")
- return HardwarePreference::kAllow;
+ if (value == "no-preference")
+ return HardwarePreference::kNoPreference;
- if (value == "require")
- return HardwarePreference::kRequire;
+ if (value == "prefer-hardware")
+ return HardwarePreference::kPreferHardware;
- if (value == "deny")
- return HardwarePreference::kDeny;
+ if (value == "prefer-software")
+ return HardwarePreference::kPreferSoftware;
NOTREACHED();
- return HardwarePreference::kAllow;
+ return HardwarePreference::kNoPreference;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.h b/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.h
index 99ed2f07e54..faa9d939dd8 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.h
@@ -9,7 +9,11 @@
namespace blink {
-enum class HardwarePreference { kAllow, kDeny, kRequire };
+enum class HardwarePreference {
+ kNoPreference,
+ kPreferSoftware,
+ kPreferHardware
+};
HardwarePreference StringToHardwarePreference(const String& value);
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.idl b/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.idl
index c025ae33d39..d0570aab67f 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/hardware_preference.idl
@@ -5,7 +5,7 @@
// https://github.com/WICG/web-codecs
enum HardwarePreference {
- "allow",
- "deny",
- "require"
+ "no-preference",
+ "prefer-software",
+ "prefer-hardware",
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/idls.gni b/chromium/third_party/blink/renderer/modules/webcodecs/idls.gni
deleted file mode 100644
index 7cebc71f583..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/idls.gni
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "audio_data.idl",
- "audio_decoder.idl",
- "audio_encoder.idl",
- "encoded_audio_chunk.idl",
- "encoded_video_chunk.idl",
- "image_decoder.idl",
- "image_track.idl",
- "image_track_list.idl",
- "plane.idl",
- "video_decoder.idl",
- "video_encoder.idl",
- "video_frame.idl",
-]
-
-modules_callback_function_idl_files = [
- "audio_data_output_callback.idl",
- "encoded_audio_chunk_output_callback.idl",
- "encoded_video_chunk_output_callback.idl",
- "video_frame_output_callback.idl",
- "webcodecs_error_callback.idl",
-]
-
-modules_dictionary_idl_files = [
- "audio_data_init.idl",
- "audio_decoder_config.idl",
- "audio_decoder_init.idl",
- "audio_decoder_support.idl",
- "audio_encoder_support.idl",
- "audio_encoder_config.idl",
- "audio_encoder_init.idl",
- "avc_encoder_config.idl",
- "encoded_audio_chunk_init.idl",
- "encoded_video_chunk_init.idl",
- "encoded_audio_chunk_metadata.idl",
- "encoded_video_chunk_metadata.idl",
- "image_decode_options.idl",
- "image_decode_result.idl",
- "image_decoder_init.idl",
- "plane_init.idl",
- "plane_layout.idl",
- "video_color_space.idl",
- "video_decoder_config.idl",
- "video_decoder_init.idl",
- "video_decoder_support.idl",
- "video_encoder_support.idl",
- "video_encoder_config.idl",
- "video_encoder_encode_options.idl",
- "video_encoder_init.idl",
- "video_frame_init.idl",
- "video_frame_plane_init.idl",
- "video_frame_read_into_options.idl",
- "video_frame_region.idl",
-]
-
-modules_typedefs_enums_only_idl_files = [
- "codec_state.idl",
- "color_space_matrix_id.idl",
- "color_space_primary_id.idl",
- "color_space_range_id.idl",
- "color_space_transfer_id.idl",
- "hardware_preference.idl",
- "video_pixel_format.idl",
-]
-
-# IDL files that either define partial interfaces or target (right side of)
-# `includes`.
-modules_dependency_idl_files = []
-
-# Similar to |modules_dependency_idl_files| but limited to things that are
-# exposed only for testing.
-modules_testing_dependency_idl_files = []
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decode_options.idl b/chromium/third_party/blink/renderer/modules/webcodecs/image_decode_options.idl
index a38fdff84e3..8cc91b44a6f 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decode_options.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decode_options.idl
@@ -6,7 +6,7 @@
dictionary ImageDecodeOptions {
// The index of the frame to decode.
- unsigned long frameIndex = 0;
+ [EnforceRange] unsigned long frameIndex = 0;
// When |completeFramesOnly| is set to false, partial progressive frames will
// be returned. When in this mode, decode() calls will resolve only once per
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder.idl b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder.idl
index 413f319b482..ed516211304 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder.idl
@@ -8,6 +8,7 @@
[
Exposed=(Window,DedicatedWorker),
RuntimeEnabled=WebCodecs,
+ SecureContext,
ImplementedAs=ImageDecoderExternal,
ActiveScriptWrappable
] interface ImageDecoder {
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc
index 9ede7c13dae..456b2095f7b 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc
@@ -135,12 +135,18 @@ ImageDecoderCore::ImageMetadata ImageDecoderCore::DecodeMetadata() {
std::unique_ptr<ImageDecoderCore::ImageDecodeResult> ImageDecoderCore::Decode(
uint32_t frame_index,
- bool complete_frames_only) {
+ bool complete_frames_only,
+ const base::AtomicFlag* abort_flag) {
DCHECK(decoder_);
auto result = std::make_unique<ImageDecodeResult>();
result->frame_index = frame_index;
+ if (abort_flag->IsSet()) {
+ result->status = Status::kAborted;
+ return result;
+ }
+
if (decoder_->Failed()) {
result->status = Status::kDecodeError;
return result;
@@ -335,8 +341,10 @@ void ImageDecoderCore::MaybeDecodeToYuv() {
void* planes[cc::kNumYUVPlanes] = {yuv_frame_->data(0), yuv_frame_->data(1),
yuv_frame_->data(2)};
- size_t row_bytes[cc::kNumYUVPlanes] = {
- yuv_frame_->stride(0), yuv_frame_->stride(1), yuv_frame_->stride(2)};
+ wtf_size_t row_bytes[cc::kNumYUVPlanes] = {
+ static_cast<wtf_size_t>(yuv_frame_->stride(0)),
+ static_cast<wtf_size_t>(yuv_frame_->stride(1)),
+ static_cast<wtf_size_t>(yuv_frame_->stride(2))};
// TODO(crbug.com/1073995): Add support for high bit depth format.
const auto color_type = kGray_8_SkColorType;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.h b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.h
index 0d38ad4e270..fdca0b17452 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_core.h
@@ -56,6 +56,7 @@ class MODULES_EXPORT ImageDecoderCore {
kNoImage, // No new images or no image could currently be decoded.
kDecodeError, // ImageDecoder::Failed() became true.
kIndexError, // |frame_index| out of range when |data_complete_| is true.
+ kAborted, // Decode was aborted by caller.
};
struct ImageDecodeResult {
@@ -76,9 +77,11 @@ class MODULES_EXPORT ImageDecoderCore {
};
// Decodes the frame at |frame_index|, returning partial frames relative to
- // the last Decode() request if |complete_frames_only| is false.
+ // the last Decode() request if |complete_frames_only| is false. |abort_flag|
+ // may be used to cancel decoding; it must outlive this Decode() call.
std::unique_ptr<ImageDecodeResult> Decode(uint32_t frame_index,
- bool complete_frames_only);
+ bool complete_frames_only,
+ const base::AtomicFlag* abort_flag);
// Calls ImageDecoder::SetData() after appending |data| to |stream_buffer_|.
// May not be called after |data_complete| becomes true.
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
index 8c04c19c40c..2cf75e3aedf 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
@@ -9,6 +9,7 @@
#include "base/task/thread_pool.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared_readablestream.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decode_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decode_result.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decoder_init.h"
@@ -19,6 +20,7 @@
#include "third_party/blink/renderer/modules/webcodecs/image_track_list.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.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/graphics/bitmap_image_metrics.h"
@@ -83,7 +85,13 @@ ImageDecoderExternal::DecodeRequest::DecodeRequest(
bool complete_frames_only)
: resolver(resolver),
frame_index(frame_index),
- complete_frames_only(complete_frames_only) {}
+ complete_frames_only(complete_frames_only),
+ abort_flag(std::make_unique<base::AtomicFlag>()) {}
+
+ImageDecoderExternal::DecodeRequest::~DecodeRequest() {
+ // This must have already been released to the decoder thread manually.
+ DCHECK(!abort_flag);
+}
void ImageDecoderExternal::DecodeRequest::Trace(Visitor* visitor) const {
visitor->Trace(resolver);
@@ -112,11 +120,19 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
tracks_(MakeGarbageCollected<ImageTrackList>(this)),
completed_property_(
MakeGarbageCollected<CompletedProperty>(GetExecutionContext())) {
+ // If the context is already destroyed we will never get an OnContextDestroyed
+ // callback, which is critical to invalidating any pending WeakPtr operations.
+ if (GetExecutionContext()->IsContextDestroyed()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Invalid context.");
+ return;
+ }
+
UseCounter::Count(GetExecutionContext(), WebFeature::kWebCodecs);
// |data| is a required field.
DCHECK(init->hasData());
- DCHECK(!init->data().IsNull());
+ DCHECK(init->data());
constexpr char kNoneOption[] = "none";
auto color_behavior = ColorBehavior::Tag();
@@ -142,13 +158,13 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
animation_option_ = AnimationOptionFromIsAnimated(*prefer_animation_);
}
- auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
+ decode_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
- if (init->data().IsReadableStream()) {
- if (init->data().GetAsReadableStream()->IsLocked() ||
- init->data().GetAsReadableStream()->IsDisturbed()) {
+ if (init->data()->IsReadableStream()) {
+ if (init->data()->GetAsReadableStream()->IsLocked() ||
+ init->data()->GetAsReadableStream()->IsDisturbed()) {
exception_state.ThrowTypeError(
"ImageDecoder can only accept readable streams that are not yet "
"locked to a reader");
@@ -156,11 +172,12 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
}
decoder_ = std::make_unique<WTF::SequenceBound<ImageDecoderCore>>(
- task_runner, mime_type_, /*data=*/nullptr, /*data_complete=*/false,
- alpha_option, color_behavior, desired_size, animation_option_);
+ decode_task_runner_, mime_type_, /*data=*/nullptr,
+ /*data_complete=*/false, alpha_option, color_behavior, desired_size,
+ animation_option_);
consumer_ = MakeGarbageCollected<ReadableStreamBytesConsumer>(
- script_state, init->data().GetAsReadableStream());
+ script_state, init->data()->GetAsReadableStream());
construction_succeeded_ = true;
@@ -171,26 +188,47 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
return;
}
- DOMArrayPiece buffer;
- if (init->data().IsArrayBuffer()) {
- buffer = DOMArrayPiece(init->data().GetAsArrayBuffer());
- } else if (init->data().IsArrayBufferView()) {
- buffer = DOMArrayPiece(init->data().GetAsArrayBufferView().Get());
- } else {
- NOTREACHED();
+ base::span<const uint8_t> buffer;
+ switch (init->data()->GetContentType()) {
+ case V8ImageBufferSource::ContentType::kArrayBufferAllowShared:
+ if (auto* data_ptr = init->data()->GetAsArrayBufferAllowShared()) {
+ if (!data_ptr->IsDetached()) {
+ buffer = base::span<const uint8_t>(
+ reinterpret_cast<const uint8_t*>(data_ptr->DataMaybeShared()),
+ data_ptr->ByteLength());
+ }
+ }
+ break;
+ case V8ImageBufferSource::ContentType::kArrayBufferViewAllowShared:
+ if (auto* data_ptr =
+ init->data()->GetAsArrayBufferViewAllowShared().Get()) {
+ if (!data_ptr->IsDetached()) {
+ buffer =
+ base::span<const uint8_t>(reinterpret_cast<const uint8_t*>(
+ data_ptr->BaseAddressMaybeShared()),
+ data_ptr->byteLength());
+ }
+ }
+ break;
+ case V8ImageBufferSource::ContentType::kReadableStream:
+ NOTREACHED();
+ break;
+ }
+
+ if (!buffer.data()) {
+ exception_state.ThrowTypeError("Provided image data was detached");
return;
}
- if (!buffer.ByteLength()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kConstraintError,
- "No image data provided");
+ if (!buffer.size()) {
+ exception_state.ThrowTypeError("No image data provided");
return;
}
auto segment_reader = SegmentReader::CreateFromSkData(
- SkData::MakeWithCopy(buffer.Data(), buffer.ByteLength()));
+ SkData::MakeWithCopy(buffer.data(), buffer.size()));
if (!segment_reader) {
- exception_state.ThrowDOMException(DOMExceptionCode::kConstraintError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
"Failed to read image data");
return;
}
@@ -199,8 +237,9 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
data_complete_ = true;
completed_property_->ResolveWithUndefined();
decoder_ = std::make_unique<WTF::SequenceBound<ImageDecoderCore>>(
- task_runner, mime_type_, std::move(segment_reader), data_complete_,
- alpha_option, color_behavior, desired_size, animation_option_);
+ decode_task_runner_, mime_type_, std::move(segment_reader),
+ data_complete_, alpha_option, color_behavior, desired_size,
+ animation_option_);
DecodeMetadata();
}
@@ -300,12 +339,18 @@ void ImageDecoderExternal::reset(DOMException* exception) {
num_submitted_decodes_ = 0u;
decode_weak_factory_.InvalidateWeakPtrs();
- // Move all state to local variables since promise resolution is reentrant.
+ // Move all state to local variables since promise resolution is re-entrant.
HeapVector<Member<DecodeRequest>> local_pending_decodes;
local_pending_decodes.swap(pending_decodes_);
- for (auto& request : local_pending_decodes)
+ for (auto& request : local_pending_decodes) {
request->resolver->Reject(exception);
+ request->abort_flag->Set();
+
+ // Since the AtomicFlag may still be referenced by the decoder sequence, we
+ // need to delete it on that sequence.
+ decode_task_runner_->DeleteSoon(FROM_HERE, std::move(request->abort_flag));
+ }
}
void ImageDecoderExternal::close() {
@@ -454,7 +499,8 @@ void ImageDecoderExternal::MaybeSatisfyPendingDecodes() {
++num_submitted_decodes_;
decoder_->AsyncCall(&ImageDecoderCore::Decode)
- .WithArgs(request->frame_index, request->complete_frames_only)
+ .WithArgs(request->frame_index, request->complete_frames_only,
+ WTF::CrossThreadUnretained(request->abort_flag.get()))
.Then(CrossThreadBindOnce(&ImageDecoderExternal::OnDecodeReady,
decode_weak_factory_.GetWeakPtr()));
}
@@ -472,6 +518,7 @@ void ImageDecoderExternal::MaybeSatisfyPendingDecodes() {
// Note: Promise resolution may invoke calls into this class.
for (auto& request : completed_decodes) {
+ DCHECK(!request->abort_flag->IsSet());
if (request->exception) {
request->resolver->Reject(request->exception);
} else if (request->range_error_message) {
@@ -481,6 +528,10 @@ void ImageDecoderExternal::MaybeSatisfyPendingDecodes() {
} else {
request->resolver->Resolve(request->result);
}
+
+ // Since the AtomicFlag may still be referenced by the decoder sequence, we
+ // need to delete it on that sequence.
+ decode_task_runner_->DeleteSoon(FROM_HERE, std::move(request->abort_flag));
}
}
@@ -501,6 +552,11 @@ void ImageDecoderExternal::OnDecodeReady(
}
request->pending = false;
+
+ // Abort always invalidates WeakPtrs, so OnDecodeReady() should never receive
+ // the kAborted status.
+ DCHECK_NE(result->status, ImageDecoderCore::Status::kAborted);
+
if (result->status == ImageDecoderCore::Status::kIndexError) {
request->range_error_message =
ExceptionMessages::IndexOutsideRange<uint32_t>(
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h
index 185d4c09270..c47c6c1b3e4 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h
@@ -126,6 +126,7 @@ class MODULES_EXPORT ImageDecoderExternal final
int pending_metadata_requests_ = 0;
// The workhorse which actually does the decoding. Bound to another sequence.
+ scoped_refptr<base::SequencedTaskRunner> decode_task_runner_;
std::unique_ptr<WTF::SequenceBound<ImageDecoderCore>> decoder_;
// List of tracks in this image. Filled in during OnMetadata().
@@ -139,6 +140,7 @@ class MODULES_EXPORT ImageDecoderExternal final
DecodeRequest(ScriptPromiseResolver* resolver,
uint32_t frame_index,
bool complete_frames_only);
+ ~DecodeRequest();
void Trace(Visitor*) const;
bool IsFinal() const;
@@ -148,6 +150,7 @@ class MODULES_EXPORT ImageDecoderExternal final
bool pending = false;
absl::optional<size_t> bytes_read_index;
Member<ImageDecodeResult> result;
+ std::unique_ptr<base::AtomicFlag> abort_flag;
absl::optional<String> range_error_message;
Member<DOMException> exception;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external_test.cc
index fc3a87b6621..507e9c7578c 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_external_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared_readablestream.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decode_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decode_result.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decoder_init.h"
@@ -45,7 +46,7 @@ class ImageDecoderTest : public testing::Test {
auto data = ReadFile(file_name);
DCHECK(!data->IsEmpty()) << "Missing file: " << file_name;
- init->setData(ArrayBufferOrArrayBufferViewOrReadableStream::FromArrayBuffer(
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(
DOMArrayBuffer::Create(std::move(data))));
return ImageDecoderExternal::Create(v8_scope->GetScriptState(), init,
v8_scope->GetExceptionState());
@@ -119,7 +120,7 @@ TEST_F(ImageDecoderTest, DecodeEmpty) {
auto* init = MakeGarbageCollected<ImageDecoderInit>();
init->setType("image/png");
- init->setData(ArrayBufferOrArrayBufferViewOrReadableStream::FromArrayBuffer(
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(
DOMArrayBuffer::Create(SharedBuffer::Create())));
auto* decoder = ImageDecoderExternal::Create(v8_scope.GetScriptState(), init,
v8_scope.GetExceptionState());
@@ -134,8 +135,7 @@ TEST_F(ImageDecoderTest, DecodeNeuteredAtConstruction) {
auto* buffer = DOMArrayBuffer::Create(SharedBuffer::Create());
init->setType("image/png");
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromArrayBuffer(buffer));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(buffer));
ArrayBufferContents contents;
ASSERT_TRUE(buffer->Transfer(v8_scope.GetIsolate(), contents));
@@ -161,8 +161,7 @@ TEST_F(ImageDecoderTest, DecodeNeuteredAtDecodeTime) {
auto* buffer = DOMArrayBuffer::Create(std::move(data));
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromArrayBuffer(buffer));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(buffer));
auto* decoder = ImageDecoderExternal::Create(v8_scope.GetScriptState(), init,
v8_scope.GetExceptionState());
@@ -293,6 +292,38 @@ TEST_F(ImageDecoderTest, DecodeCompleted) {
}
}
+TEST_F(ImageDecoderTest, DecodeAborted) {
+ V8TestingScope v8_scope;
+ constexpr char kImageType[] = "image/avif";
+ EXPECT_TRUE(IsTypeSupported(&v8_scope, kImageType));
+
+ // Use an expensive-to-decode image to try and ensure work exists to abort.
+ auto* decoder = CreateDecoder(
+ &v8_scope,
+ "images/resources/avif/red-at-12-oclock-with-color-profile-12bpc.avif",
+ kImageType);
+
+ ASSERT_TRUE(decoder);
+ ASSERT_FALSE(v8_scope.GetExceptionState().HadException());
+
+ {
+ auto promise = decoder->tracks().ready(v8_scope.GetScriptState());
+ ScriptPromiseTester tester(v8_scope.GetScriptState(), promise);
+ tester.WaitUntilSettled();
+ ASSERT_TRUE(tester.IsFulfilled());
+ }
+
+ // Setup a scenario where there should be work to abort. Since blink tests use
+ // real threads with the base::TaskEnvironment, we can't actually be sure that
+ // work hasn't completed by the time reset() is called.
+ for (int i = 0; i < 10; ++i)
+ decoder->decode();
+ decoder->reset();
+
+ // There's no way to verify work was aborted, so just ensure nothing explodes.
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_F(ImageDecoderTest, DecoderReset) {
V8TestingScope v8_scope;
constexpr char kImageType[] = "image/gif";
@@ -402,6 +433,20 @@ TEST_F(ImageDecoderTest, DecoderContextDestroyed) {
EXPECT_FALSE(decoder->HasPendingActivity());
}
+TEST_F(ImageDecoderTest, DecoderContextDestroyedBeforeCreation) {
+ V8TestingScope v8_scope;
+ constexpr char kImageType[] = "image/gif";
+ EXPECT_TRUE(IsTypeSupported(&v8_scope, kImageType));
+
+ // Destroying the context prior to construction should fail creation.
+ v8_scope.GetExecutionContext()->NotifyContextDestroyed();
+
+ auto* decoder =
+ CreateDecoder(&v8_scope, "images/resources/animated.gif", kImageType);
+ ASSERT_FALSE(decoder);
+ ASSERT_TRUE(v8_scope.GetExceptionState().HadException());
+}
+
TEST_F(ImageDecoderTest, DecoderReadableStream) {
V8TestingScope v8_scope;
constexpr char kImageType[] = "image/gif";
@@ -417,8 +462,7 @@ TEST_F(ImageDecoderTest, DecoderReadableStream) {
auto* init = MakeGarbageCollected<ImageDecoderInit>();
init->setType(kImageType);
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromReadableStream(stream));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(stream));
Persistent<ImageDecoderExternal> decoder = ImageDecoderExternal::Create(
v8_scope.GetScriptState(), init, IGNORE_EXCEPTION_FOR_TESTING);
@@ -518,8 +562,7 @@ TEST_F(ImageDecoderTest, DecoderReadableStreamAvif) {
auto* init = MakeGarbageCollected<ImageDecoderInit>();
init->setType(kImageType);
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromReadableStream(stream));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(stream));
Persistent<ImageDecoderExternal> decoder = ImageDecoderExternal::Create(
v8_scope.GetScriptState(), init, IGNORE_EXCEPTION_FOR_TESTING);
@@ -586,8 +629,7 @@ TEST_F(ImageDecoderTest, ReadableStreamAvifStillYuvDecoding) {
auto* init = MakeGarbageCollected<ImageDecoderInit>();
init->setType(kImageType);
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromReadableStream(stream));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(stream));
Persistent<ImageDecoderExternal> decoder = ImageDecoderExternal::Create(
v8_scope.GetScriptState(), init, IGNORE_EXCEPTION_FOR_TESTING);
@@ -653,8 +695,7 @@ TEST_F(ImageDecoderTest, DecodePartialImage) {
auto* array_buffer = DOMArrayBuffer::Create(128, 1);
ASSERT_TRUE(data->GetBytes(array_buffer->Data(), array_buffer->ByteLength()));
- init->setData(ArrayBufferOrArrayBufferViewOrReadableStream::FromArrayBuffer(
- array_buffer));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(array_buffer));
auto* decoder = ImageDecoderExternal::Create(v8_scope.GetScriptState(), init,
v8_scope.GetExceptionState());
ASSERT_TRUE(decoder);
@@ -699,8 +740,7 @@ TEST_F(ImageDecoderTest, DecodeClosedDuringReadableStream) {
auto* init = MakeGarbageCollected<ImageDecoderInit>();
init->setType(kImageType);
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromReadableStream(stream));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(stream));
Persistent<ImageDecoderExternal> decoder = ImageDecoderExternal::Create(
v8_scope.GetScriptState(), init, IGNORE_EXCEPTION_FOR_TESTING);
@@ -747,8 +787,7 @@ TEST_F(ImageDecoderTest, DecodeInvalidFileViaReadableStream) {
auto* init = MakeGarbageCollected<ImageDecoderInit>();
init->setType(kImageType);
- init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromReadableStream(stream));
+ init->setData(MakeGarbageCollected<V8ImageBufferSource>(stream));
Persistent<ImageDecoderExternal> decoder = ImageDecoderExternal::Create(
v8_scope.GetScriptState(), init, IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc
index a6089744fe6..4fad7c396f2 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc
@@ -7,6 +7,7 @@
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared_readablestream.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decode_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_image_decoder_init.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -125,8 +126,7 @@ DEFINE_BINARY_PROTO_FUZZER(
Persistent<DOMArrayBuffer> data_copy = DOMArrayBuffer::Create(
proto.config().data().data(), proto.config().data().size());
image_decoder_init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromArrayBuffer(
- data_copy));
+ MakeGarbageCollected<V8ImageBufferSource>(data_copy));
image_decoder_init->setPremultiplyAlpha(
ToPremultiplyAlpha(proto.config().options().premultiply_alpha()));
image_decoder_init->setColorSpaceConversion(ToColorSpaceConversion(
@@ -153,6 +153,11 @@ DEFINE_BINARY_PROTO_FUZZER(
image_decoder->close();
image_decoder = nullptr;
base::RunLoop().RunUntilIdle();
+
+ // Collect what we can after the first fuzzing loop; this keeps memory
+ // pressure down during ReadableStream fuzzing.
+ V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting(
+ v8::Isolate::kFullGarbageCollection);
}
Persistent<TestUnderlyingSource> underlying_source =
@@ -162,8 +167,7 @@ DEFINE_BINARY_PROTO_FUZZER(
underlying_source, 0);
image_decoder_init->setData(
- ArrayBufferOrArrayBufferViewOrReadableStream::FromReadableStream(
- stream));
+ MakeGarbageCollected<V8ImageBufferSource>(stream));
image_decoder = ImageDecoderExternal::Create(
script_state, image_decoder_init, IGNORE_EXCEPTION_FOR_TESTING);
image_decoder_init = nullptr;
@@ -199,6 +203,7 @@ DEFINE_BINARY_PROTO_FUZZER(
// a chain of persistent handles), so some objects may not be collected until
// a subsequent iteration. This is slow enough as is, so we compromise on one
// major GC, as opposed to the 5 used in V8GCController for unit tests.
+ base::RunLoop().RunUntilIdle();
V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting(
v8::Isolate::kFullGarbageCollection);
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl
index 1795c6aabbe..4d2cbf0dd68 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl
@@ -4,7 +4,7 @@
// https://github.com/WICG/web-codecs
-typedef (ArrayBuffer or ArrayBufferView or ReadableStream) ImageBufferSource;
+typedef ([AllowShared] ArrayBuffer or [AllowShared] ArrayBufferView or ReadableStream) ImageBufferSource;
dictionary ImageDecoderInit {
required ImageBufferSource data;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/image_track_list.idl b/chromium/third_party/blink/renderer/modules/webcodecs/image_track_list.idl
index d380cc32a9f..e96fc2c8ab3 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/image_track_list.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/image_track_list.idl
@@ -8,7 +8,7 @@
Exposed=(Window,DedicatedWorker),
RuntimeEnabled=WebCodecs
] interface ImageTrackList {
- getter ImageTrack(unsigned long index);
+ getter ImageTrack([EnforceRange] unsigned long index);
readonly attribute unsigned long length;
// Index of the currently selected track or -1 if no track is selected.
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/latency_mode.idl b/chromium/third_party/blink/renderer/modules/webcodecs/latency_mode.idl
new file mode 100644
index 00000000000..7e536890dc4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/latency_mode.idl
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+enum LatencyMode {
+ "quality",
+ "realtime"
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc b/chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc
new file mode 100644
index 00000000000..7351ae21c91
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc
@@ -0,0 +1,170 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.h"
+
+#include <algorithm>
+
+#include "base/numerics/checked_math.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_copy_to_options.h"
+#include "third_party/blink/renderer/modules/webcodecs/dom_rect_util.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
+namespace blink {
+
+ParsedCopyToOptions::ParsedCopyToOptions(VideoFrameCopyToOptions* options,
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::Rect& default_rect,
+ ExceptionState& exception_state)
+ : num_planes(
+ static_cast<wtf_size_t>(media::VideoFrame::NumPlanes(format))) {
+ // Parse rect.
+ rect = default_rect;
+ if (options->hasRect()) {
+ rect = ToGfxRect(options->rect(), "rect", exception_state);
+ if (exception_state.HadException())
+ return;
+
+ if (rect.right() > coded_size.width()) {
+ exception_state.ThrowTypeError(
+ String::Format("rect.right %i exceeds codedWidth %i.", rect.right(),
+ coded_size.width()));
+ return;
+ }
+
+ if (rect.bottom() > coded_size.height()) {
+ exception_state.ThrowTypeError(
+ String::Format("rect.bottom %u exceeds codedHeight %u.",
+ rect.bottom(), coded_size.height()));
+ return;
+ }
+ }
+
+ // Rect must be non-empty.
+ if (rect.width() == 0) {
+ exception_state.ThrowTypeError("rect.width must be nonzero.");
+ return;
+ }
+
+ if (rect.height() == 0) {
+ exception_state.ThrowTypeError("rect.height must be nonzero.");
+ return;
+ }
+
+ // Rect must be sample-aligned.
+ // TODO(crbug.com/1205166): media::VideoFrame does not enforce that visible
+ // rects are sample-aligned, so we may have to deal with this case somehow.
+ // Options:
+ // - Crop VideoFrame.visibleRect to sample boundaries and use that.
+ // (May result in differences between rendering paths.)
+ // - Expand or contract the crop to sample boundaries, potentially
+ // per-plane.
+ // - Enforce this restriction on media::VideoFrame and see if anything
+ // breaks.
+ for (wtf_size_t i = 0; i < num_planes; i++) {
+ gfx::Size sample_size = media::VideoFrame::SampleSize(format, i);
+ if (rect.x() % sample_size.width() != 0) {
+ exception_state.ThrowTypeError(String::Format(
+ "rect.x %d is not sample-aligned in plane %u.", rect.x(), i));
+ return;
+ } else if (rect.width() % sample_size.width() != 0) {
+ exception_state.ThrowTypeError(String::Format(
+ "rect.width %d is not sample-aligned in plane %u.", rect.width(), i));
+ return;
+ } else if (rect.y() % sample_size.height() != 0) {
+ exception_state.ThrowTypeError(String::Format(
+ "rect.y %d is not sample-aligned in plane %u.", rect.y(), i));
+ return;
+ } else if (rect.height() % sample_size.height() != 0) {
+ exception_state.ThrowTypeError(
+ String::Format("rect.height %d is not sample-aligned in plane %u.",
+ rect.height(), i));
+ return;
+ }
+ }
+
+ // Parse |layout|.
+ bool has_explicit_layout = options->hasLayout();
+ if (has_explicit_layout) {
+ if (options->layout().size() != num_planes) {
+ exception_state.ThrowTypeError(
+ String::Format("Invalid layout. Expected %u planes, found %u.",
+ num_planes, options->layout().size()));
+ return;
+ }
+
+ for (wtf_size_t i = 0; i < num_planes; i++) {
+ planes[i].offset = options->layout()[i]->offset();
+ planes[i].stride = options->layout()[i]->stride();
+ }
+ }
+
+ // Compute the resulting layout.
+ uint32_t end_offset[media::VideoFrame::kMaxPlanes] = {0};
+ for (wtf_size_t i = 0; i < num_planes; i++) {
+ gfx::Size sample_size = media::VideoFrame::SampleSize(format, i);
+ uint32_t sample_bytes = media::VideoFrame::BytesPerElement(format, i);
+
+ planes[i].top = rect.y() / sample_size.height();
+ planes[i].height = rect.height() / sample_size.height();
+ planes[i].left_bytes = rect.x() / sample_size.width() * sample_bytes;
+ planes[i].width_bytes = rect.width() / sample_size.width() * sample_bytes;
+
+ // If an explicit layout was not provided, planes and rows are tightly
+ // packed.
+ if (!has_explicit_layout) {
+ planes[i].offset = min_buffer_size;
+ planes[i].stride = planes[i].width_bytes;
+ } else {
+ if (planes[i].stride < planes[i].width_bytes) {
+ exception_state.ThrowTypeError(
+ String::Format("Invalid layout, plane %u must have stride at least "
+ "%u, found %u.",
+ i, planes[i].width_bytes, planes[i].stride));
+ return;
+ }
+ }
+
+ // Note: this calculation implies that the whole stride is allocated, even
+ // on the last row.
+ const auto plane_size =
+ base::CheckedNumeric<uint32_t>(planes[i].stride) * planes[i].height;
+ const auto plane_end = plane_size + planes[i].offset;
+ if (!plane_end.IsValid()) {
+ exception_state.ThrowTypeError(
+ String::Format("Invalid layout, plane %u with offset %u and stride "
+ "%u exceeds bounds.",
+ i, planes[i].offset, planes[i].stride));
+ return;
+ }
+ // Plane size is verified to fit in int for compatibility with
+ // libyuv::CopyPlane().
+ if (!plane_size.Cast<int>().IsValid()) {
+ exception_state.ThrowTypeError(
+ String::Format("Invalid layout, plane %u with stride %u exceeds "
+ "implementation limit.",
+ i, planes[i].stride));
+ return;
+ }
+ end_offset[i] = plane_end.ValueOrDie();
+ min_buffer_size = std::max(min_buffer_size, end_offset[i]);
+
+ // Verify that planes do not overlap. Only happens with explicit layouts.
+ for (wtf_size_t j = 0; j < i; j++) {
+ // If plane A ends before plane B starts, they do not overlap.
+ if (end_offset[i] <= planes[j].offset ||
+ end_offset[j] <= planes[i].offset) {
+ continue;
+ }
+ DCHECK(has_explicit_layout);
+ exception_state.ThrowTypeError(String::Format(
+ "Invalid layout, plane %u overlaps with plane %u.", i, j));
+ return;
+ }
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h b/chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.h
index 0be3464e3bb..2e4d1f59a2c 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.h
@@ -2,25 +2,26 @@
// Use 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_WEBCODECS_PARSED_READ_INTO_OPTIONS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_READ_INTO_OPTIONS_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_COPY_TO_OPTIONS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_COPY_TO_OPTIONS_H_
#include <stdint.h>
#include "media/base/video_frame.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+#include "ui/gfx/geometry/rect.h"
namespace blink {
class ExceptionState;
-class VideoFrameReadIntoOptions;
+class VideoFrameCopyToOptions;
-struct ParsedReadIntoOptions {
- ParsedReadIntoOptions(VideoFrameReadIntoOptions* options,
- media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- ExceptionState&);
+struct ParsedCopyToOptions {
+ ParsedCopyToOptions(VideoFrameCopyToOptions* options,
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::Rect& default_rect,
+ ExceptionState&);
struct Plane {
// Offset in destination buffer.
@@ -41,10 +42,13 @@ struct ParsedReadIntoOptions {
const wtf_size_t num_planes;
Plane planes[media::VideoFrame::kMaxPlanes] = {{0}};
+ // Region of coded area to copy.
+ gfx::Rect rect;
+
// Minimum size of a destination buffer that fits all planes.
uint32_t min_buffer_size = 0;
};
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_READ_INTO_OPTIONS_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_COPY_TO_OPTIONS_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc b/chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc
deleted file mode 100644
index 8506ebb84b1..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h"
-
-#include <algorithm>
-
-#include "base/numerics/checked_math.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_region.h"
-#include "third_party/blink/renderer/modules/webcodecs/plane_layout.h"
-#include "third_party/blink/renderer/modules/webcodecs/video_frame_read_into_options.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-
-namespace blink {
-
-ParsedReadIntoOptions::ParsedReadIntoOptions(VideoFrameReadIntoOptions* options,
- media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- ExceptionState& exception_state)
- : num_planes(
- static_cast<wtf_size_t>(media::VideoFrame::NumPlanes(format))) {
- uint32_t coded_width = static_cast<uint32_t>(coded_size.width());
- uint32_t coded_height = static_cast<uint32_t>(coded_size.height());
-
- // Parse |region|
- gfx::Rect region = visible_rect;
- if (options->hasRegion()) {
- uint32_t left = options->region()->left();
- uint32_t top = options->region()->top();
- uint32_t width = options->region()->width();
- uint32_t height = options->region()->height();
-
- // Implicitly checks that left <= kMaxDimension.
- if (left >= coded_width) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid region.left %u with codedWidth %u.", left,
- coded_width));
- return;
- }
-
- // If left and width are <= kMaxDimension then their sum will not overflow.
- if (width > coded_width || left + width > coded_width) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid region.width %u with region.left %u and "
- "codedWidth %u.",
- width, left, coded_width));
- return;
- }
-
- // Implicitly checks that top <= kMaxDimension.
- if (top >= coded_height) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid region.top %u with codedHeight %u.", top,
- coded_height));
- return;
- }
-
- // If top and height are <= kMaxDimension then their sum will not overflow.
- if (height > coded_height || top + height > coded_height) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid region.height %u with region.top %u and "
- "codedHeight %u.",
- height, top, coded_height));
- return;
- }
-
- region = gfx::Rect(left, top, width, height);
- }
-
- // Region must be non-empty.
- if (region.IsEmpty()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid region with width %d and height %d. Region "
- "must have nonzero area.",
- region.width(), region.height()));
- return;
- }
-
- // Region must be sample-aligned.
- // TODO(crbug.com/1205166): media::VideoFrame does not enforce that visible
- // rects are sample-aligned, so we may have to deal with this case somehow.
- // Options:
- // - Crop VideoFrame.visibleRegion to sample boundaries and use that.
- // (May result in differences between rendering paths.)
- // - Expand or contract the crop to sample boundaries, potentially
- // per-plane.
- // - Enforce this restriction on media::VideoFrame and see if anything
- // breaks.
- for (wtf_size_t i = 0; i < num_planes; i++) {
- gfx::Size sample_size = media::VideoFrame::SampleSize(format, i);
- if (region.x() % sample_size.width() != 0) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("region.left %d is not sample-aligned in plane %u.",
- region.x(), i));
- return;
- } else if (region.width() % sample_size.width() != 0) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("region.width %d is not sample-aligned in plane %u.",
- region.width(), i));
- return;
- } else if (region.y() % sample_size.height() != 0) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("region.top %d is not sample-aligned in plane %u.",
- region.y(), i));
- return;
- } else if (region.height() % sample_size.height() != 0) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("region.height %d is not sample-aligned in plane %u.",
- region.height(), i));
- return;
- }
- }
-
- // Parse |layout|.
- bool has_explicit_layout = false;
- if (options->hasLayout()) {
- // TODO(crbug.com/1205169): Consider treating missing planes as implied
- // discard.
- if (options->layout().size() != num_planes) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout. Expected %u planes, found %u.",
- num_planes, options->layout().size()));
- return;
- }
-
- // If the first plane has an offset, assume every plane has an offset and
- // stride.
- has_explicit_layout = options->layout()[0]->hasOffset();
-
- for (wtf_size_t i = 0; i < num_planes; i++) {
- if (options->layout()[i]->hasOffset() != has_explicit_layout) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout, plane %u %s an offset. "
- "Either all planes must have an offset and stride, "
- "or all planes must have neither.",
- i, has_explicit_layout ? "does not have" : "has"));
- return;
- }
- if (options->layout()[i]->hasStride() != has_explicit_layout) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout, plane %u %s a stride. "
- "Either all planes must have an offset and stride, "
- "or all planes must have neither.",
- i, has_explicit_layout ? "does not have" : "has"));
- return;
- }
- if (has_explicit_layout) {
- planes[i].offset = options->layout()[i]->offset();
- planes[i].stride = options->layout()[i]->stride();
- }
- }
- }
-
- // Compute the resulting layout.
- uint32_t end_offset[media::VideoFrame::kMaxPlanes] = {0};
- for (wtf_size_t i = 0; i < num_planes; i++) {
- gfx::Size sample_size = media::VideoFrame::SampleSize(format, i);
- uint32_t sample_bytes = media::VideoFrame::BytesPerElement(format, i);
-
- planes[i].top = region.y() / sample_size.height();
- planes[i].height = region.height() / sample_size.height();
- planes[i].left_bytes = region.x() / sample_size.width() * sample_bytes;
- planes[i].width_bytes = region.width() / sample_size.width() * sample_bytes;
-
- // If an explicit layout was not provided, planes and rows are tightly
- // packed.
- if (!has_explicit_layout) {
- planes[i].offset = min_buffer_size;
- planes[i].stride = planes[i].width_bytes;
- } else {
- if (planes[i].stride < planes[i].width_bytes) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout, plane %u must have stride at least "
- "%u, found %u.",
- i, planes[i].width_bytes, planes[i].stride));
- return;
- }
- }
-
- // Note: this calculation implies that the whole stride is allocated, even
- // on the last row.
- const auto plane_size =
- base::CheckedNumeric<uint32_t>(planes[i].stride) * planes[i].height;
- if (!plane_size.IsValid()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout, plane %u with stride %u is too "
- "large.",
- i, planes[i].stride));
- return;
- }
- const auto plane_end = plane_size + planes[i].offset;
- if (!plane_end.IsValid()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout, plane %u with offset %u and stride "
- "%u exceeds bounds.",
- i, planes[i].offset, planes[i].stride));
- return;
- }
- end_offset[i] = plane_end.ValueOrDie();
- min_buffer_size = std::max(min_buffer_size, end_offset[i]);
-
- // Verify that planes do not overlap.
- for (wtf_size_t j = 0; j < i; j++) {
- // If plane A ends before plane B starts, they do not overlap.
- if (end_offset[i] <= planes[j].offset ||
- end_offset[j] <= planes[i].offset) {
- continue;
- }
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid layout, plane %u overlaps with plane %u.", i,
- j));
- return;
- }
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/plane.cc b/chromium/third_party/blink/renderer/modules/webcodecs/plane.cc
deleted file mode 100644
index aa4b37e8360..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/plane.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/webcodecs/plane.h"
-
-#include <string.h>
-
-#include "third_party/blink/renderer/platform/bindings/exception_code.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-namespace blink {
-
-namespace {
-
-void CopyPlane(const uint8_t* plane,
- size_t copy_size,
- size_t trailing_zeros_size,
- uint8_t* dest) {
- // Copy plane bytes.
- memcpy(dest, plane, copy_size);
-
- // Zero trailing padding bytes.
- memset(dest + copy_size, 0, trailing_zeros_size);
-}
-
-} // namespace
-
-Plane::Plane(scoped_refptr<VideoFrameHandle> handle, size_t plane)
- : handle_(std::move(handle)), plane_(plane) {
-#if DCHECK_IS_ON()
- // Validate the plane index, but only if the handle is valid.
- auto local_frame = handle_->frame();
- if (local_frame) {
- DCHECK(local_frame->IsMappable() || local_frame->HasGpuMemoryBuffer());
- DCHECK_LT(plane, local_frame->layout().num_planes());
- }
-#endif // DCHECK_IS_ON()
-}
-
-uint32_t Plane::stride() const {
- auto local_frame = handle_->frame();
- if (!local_frame)
- return 0;
- // TODO(sandersd): Consider returning row_bytes() instead. This would imply
- // removing padding bytes in copyInto().
- return local_frame->stride(plane_);
-}
-
-uint32_t Plane::rows() const {
- auto local_frame = handle_->frame();
- if (!local_frame)
- return 0;
- return local_frame->rows(plane_);
-}
-
-uint32_t Plane::length() const {
- auto local_frame = handle_->frame();
- if (!local_frame)
- return 0;
-
- // Note: this could be slightly larger than the actual data size. readInto()
- // will pad with zeros.
- return local_frame->rows(plane_) * local_frame->stride(plane_);
-}
-
-void Plane::readInto(MaybeShared<DOMArrayBufferView> dst,
- ExceptionState& exception_state) {
- auto local_frame = handle_->frame();
- if (!local_frame) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot read from closed VideoFrame.");
- return;
- }
-
- // Note: these methods all return int.
- size_t rows = local_frame->rows(plane_);
- size_t row_bytes = local_frame->row_bytes(plane_);
- size_t stride = local_frame->stride(plane_);
-
- DCHECK_GT(rows, 0u); // should fail VideoFrame::IsValidConfig()
- DCHECK_GT(row_bytes, 0u); // should fail VideoFrame::IsValidConfig()
- DCHECK_GE(stride, row_bytes);
-
- size_t total_size = rows * stride;
- size_t trailing_zeros_size = stride - row_bytes;
- size_t copy_size = total_size - trailing_zeros_size;
-
- // Note: byteLength is zero if the buffer is detached.
- uint8_t* base = static_cast<uint8_t*>(dst->BaseAddressMaybeShared());
- if (!base) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Destination buffer is not valid.");
- return;
- }
- if (total_size > dst->byteLength()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "Destination buffer is not large enough.");
- return;
- }
-
- if (local_frame->IsMappable()) {
- CopyPlane(local_frame->data(plane_), copy_size, trailing_zeros_size, base);
- return;
- }
-
- DCHECK(local_frame->HasGpuMemoryBuffer());
- auto* gmb = local_frame->GetGpuMemoryBuffer();
- if (!gmb->Map()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Could not map video frame into memory.");
- return;
- }
- CopyPlane(static_cast<const uint8_t*>(gmb->memory(plane_)), copy_size,
- trailing_zeros_size, base);
- gmb->Unmap();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/plane.h b/chromium/third_party/blink/renderer/modules/webcodecs/plane.h
deleted file mode 100644
index c271016cc9c..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/plane.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PLANE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PLANE_H_
-
-#include <stdint.h>
-
-#include "base/memory/scoped_refptr.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/modules_export.h"
-#include "third_party/blink/renderer/modules/webcodecs/video_frame_handle.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-
-namespace blink {
-
-class ExceptionState;
-
-class MODULES_EXPORT Plane final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- // Construct a Plane given a |handle| and a plane index.
- // It is legal for |handle| to be invalid, the resulting Plane will also be
- // invalid.
- Plane(scoped_refptr<VideoFrameHandle> handle, size_t plane);
- ~Plane() override = default;
-
- // TODO(sandersd): Review return types. There is some implicit casting going
- // on here.
- // TODO(sandersd): Consider throwing if |handle_| is invalidated. Currently
- // everything returns 0, which is not a bad API either.
- uint32_t stride() const;
- uint32_t rows() const;
- uint32_t length() const;
-
- // Throws InvalidStateError if |handle_| has been invalidated.
- void readInto(MaybeShared<DOMArrayBufferView> dst, ExceptionState&);
-
- private:
- scoped_refptr<VideoFrameHandle> handle_;
- size_t plane_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PLANE_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/plane.idl b/chromium/third_party/blink/renderer/modules/webcodecs/plane.idl
deleted file mode 100644
index 637721a8895..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/plane.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-[
- Exposed=(Window,DedicatedWorker),
- RuntimeEnabled=WebCodecs
-] interface Plane {
- readonly attribute unsigned long stride;
- readonly attribute unsigned long rows;
- readonly attribute unsigned long length;
-
- [RaisesException] void readInto([AllowShared] ArrayBufferView dst);
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/plane_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/plane_init.idl
deleted file mode 100644
index f9b111e4cae..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/plane_init.idl
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-dictionary PlaneInit {
- // TODO(sandersd): Mark as required when |src| is removed.
- BufferSource data;
- [EnforceRange] unsigned long offset;
- required [EnforceRange] unsigned long stride;
-
- // DEPRECATED: Use |data|.
- BufferSource src;
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/plane_layout.idl b/chromium/third_party/blink/renderer/modules/webcodecs/plane_layout.idl
index 9c0ffa3d7d7..6058d277be6 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/plane_layout.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/plane_layout.idl
@@ -6,12 +6,9 @@
dictionary PlaneLayout {
// Offset into the buffer where this plane's first row begins.
- [EnforceRange] unsigned long offset;
+ required [EnforceRange] unsigned long offset;
// Distance (in bytes) between the start of each row of pixel data. Can be
// larger than size of the pixel data, eg. for alignment reasons.
- [EnforceRange] unsigned long stride;
-
- // TODO(sandersd): Add a 'discard' member to indicate that a plane should be
- // skipped.
+ required [EnforceRange] unsigned long stride;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc b/chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc
new file mode 100644
index 00000000000..13c8207bb35
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc
@@ -0,0 +1,62 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h"
+
+#include "base/feature_list.h"
+#include "base/location.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
+
+namespace blink {
+
+const base::Feature kReclaimInactiveWebCodecs{"ReclaimInactiveWebCodecs",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+namespace {
+constexpr base::TimeDelta kInactivityReclamationThreshold =
+ base::TimeDelta::FromMinutes(1);
+
+constexpr base::TimeDelta kTimerPeriod = base::TimeDelta::FromSeconds(30);
+} // namespace
+
+ReclaimableCodec::ReclaimableCodec()
+ : last_activity_(base::TimeTicks::Now()),
+ activity_timer_(Thread::Current()->GetTaskRunner(),
+ this,
+ &ReclaimableCodec::ActivityTimerFired) {
+ if (base::FeatureList::IsEnabled(kReclaimInactiveWebCodecs))
+ activity_timer_.StartRepeating(kTimerPeriod, FROM_HERE);
+}
+
+void ReclaimableCodec::MarkCodecActive() {
+ last_activity_ = base::TimeTicks::Now();
+ last_tick_was_inactive_ = false;
+}
+
+void ReclaimableCodec::ActivityTimerFired(TimerBase*) {
+ DCHECK(base::FeatureList::IsEnabled(kReclaimInactiveWebCodecs));
+
+ auto time_inactive = base::TimeTicks::Now() - last_activity_;
+
+ bool is_inactive = time_inactive < kInactivityReclamationThreshold;
+
+ // Do not immediately reclaim. Make sure the codec is inactive for 2 ticks.
+ // Otherwise, tabs that were suspended could see their codecs reclaimed
+ // immediately after being resumed.
+ if (is_inactive && last_tick_was_inactive_) {
+ activity_timer_.Stop();
+ OnCodecReclaimed(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kQuotaExceededError,
+ "Codec reclaimed due to inactivity."));
+ }
+
+ last_tick_was_inactive_ = is_inactive;
+}
+
+void ReclaimableCodec::Trace(Visitor* visitor) const {
+ visitor->Trace(activity_timer_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h b/chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h
new file mode 100644
index 00000000000..06fe2994e68
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_RECLAIMABLE_CODEC_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_RECLAIMABLE_CODEC_H_
+
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/timer.h"
+
+namespace blink {
+
+class DOMException;
+
+class MODULES_EXPORT ReclaimableCodec : public GarbageCollectedMixin {
+ public:
+ ReclaimableCodec();
+
+ // GarbageCollectedMixin override.
+ void Trace(Visitor*) const override;
+
+ protected:
+ void MarkCodecActive();
+
+ virtual void OnCodecReclaimed(DOMException*) = 0;
+
+ private:
+ void ActivityTimerFired(TimerBase*);
+ void StartTimer();
+
+ // This is used to make sure that there are two consecutive ticks of the
+ // timer, before we reclaim for inactivity. This prevents immediately
+ // reclaiming otherwise active codecs, right after a page suspended/resumed.
+ bool last_tick_was_inactive_ = false;
+
+ base::TimeTicks last_activity_;
+ HeapTaskRunnerTimer<ReclaimableCodec> activity_timer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_AUDIO_DATA_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_color_primaries.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_primaries.idl
new file mode 100644
index 00000000000..93af7c94e84
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_primaries.idl
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+enum VideoColorPrimaries {
+ "bt709", // BT.709, sRGB
+ "bt470bg", // BT.601 PAL
+ "smpte170m", // BT.601 NTSC
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.cc
new file mode 100644
index 00000000000..801c91429d7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.cc
@@ -0,0 +1,303 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/video_color_space.h"
+
+#include "media/base/video_color_space.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h"
+#include "ui/gfx/color_space.h"
+
+namespace blink {
+
+// static
+VideoColorSpace* VideoColorSpace::Create(const VideoColorSpaceInit* init) {
+ return MakeGarbageCollected<VideoColorSpace>(init);
+}
+
+VideoColorSpace::VideoColorSpace(const VideoColorSpaceInit* init) {
+ if (init->hasPrimaries())
+ primaries_ = init->primaries();
+ if (init->hasTransfer())
+ transfer_ = init->transfer();
+ if (init->hasMatrix())
+ matrix_ = init->matrix();
+ if (init->hasFullRange())
+ full_range_ = init->fullRange();
+}
+
+VideoColorSpace::VideoColorSpace(const gfx::ColorSpace& color_space) {
+ switch (color_space.GetPrimaryID()) {
+ case gfx::ColorSpace::PrimaryID::BT709:
+ primaries_ = V8VideoColorPrimaries(V8VideoColorPrimaries::Enum::kBt709);
+ break;
+ case gfx::ColorSpace::PrimaryID::BT470BG:
+ primaries_ = V8VideoColorPrimaries(V8VideoColorPrimaries::Enum::kBt470Bg);
+ break;
+ case gfx::ColorSpace::PrimaryID::SMPTE170M:
+ primaries_ =
+ V8VideoColorPrimaries(V8VideoColorPrimaries::Enum::kSmpte170M);
+ break;
+ default:
+ // Other values map to unspecified for now.
+ break;
+ }
+
+ switch (color_space.GetTransferID()) {
+ case gfx::ColorSpace::TransferID::BT709:
+ transfer_ = V8VideoTransferCharacteristics(
+ V8VideoTransferCharacteristics::Enum::kBt709);
+ break;
+ case gfx::ColorSpace::TransferID::SMPTE170M:
+ transfer_ = V8VideoTransferCharacteristics(
+ V8VideoTransferCharacteristics::Enum::kSmpte170M);
+ break;
+ case gfx::ColorSpace::TransferID::IEC61966_2_1:
+ transfer_ = V8VideoTransferCharacteristics(
+ V8VideoTransferCharacteristics::Enum::kIec6196621);
+ break;
+ default:
+ // Other values map to unspecified for now.
+ break;
+ }
+
+ switch (color_space.GetMatrixID()) {
+ case gfx::ColorSpace::MatrixID::RGB:
+ matrix_ =
+ V8VideoMatrixCoefficients(V8VideoMatrixCoefficients::Enum::kRgb);
+ break;
+ case gfx::ColorSpace::MatrixID::BT709:
+ matrix_ =
+ V8VideoMatrixCoefficients(V8VideoMatrixCoefficients::Enum::kBt709);
+ break;
+ case gfx::ColorSpace::MatrixID::BT470BG:
+ matrix_ =
+ V8VideoMatrixCoefficients(V8VideoMatrixCoefficients::Enum::kBt470Bg);
+ break;
+ case gfx::ColorSpace::MatrixID::SMPTE170M:
+ matrix_ = V8VideoMatrixCoefficients(
+ V8VideoMatrixCoefficients::Enum::kSmpte170M);
+ break;
+ default:
+ // Other values map to unspecified for now.
+ break;
+ }
+
+ switch (color_space.GetRangeID()) {
+ case gfx::ColorSpace::RangeID::LIMITED:
+ full_range_ = false;
+ break;
+ case gfx::ColorSpace::RangeID::FULL:
+ full_range_ = true;
+ break;
+ default:
+ // Other values map to unspecified. We could probably map DERIVED to a
+ // specific value, though.
+ break;
+ }
+}
+
+VideoColorSpace::VideoColorSpace(const media::VideoColorSpace& color_space) {
+ switch (color_space.primaries) {
+ case media::VideoColorSpace::PrimaryID::BT709:
+ primaries_ = V8VideoColorPrimaries(V8VideoColorPrimaries::Enum::kBt709);
+ break;
+ case media::VideoColorSpace::PrimaryID::BT470BG:
+ primaries_ = V8VideoColorPrimaries(V8VideoColorPrimaries::Enum::kBt470Bg);
+ break;
+ case media::VideoColorSpace::PrimaryID::SMPTE170M:
+ primaries_ =
+ V8VideoColorPrimaries(V8VideoColorPrimaries::Enum::kSmpte170M);
+ break;
+ default:
+ // Other values map to unspecified for now.
+ break;
+ }
+
+ switch (color_space.transfer) {
+ case media::VideoColorSpace::TransferID::BT709:
+ transfer_ = V8VideoTransferCharacteristics(
+ V8VideoTransferCharacteristics::Enum::kBt709);
+ break;
+ case media::VideoColorSpace::TransferID::SMPTE170M:
+ transfer_ = V8VideoTransferCharacteristics(
+ V8VideoTransferCharacteristics::Enum::kSmpte170M);
+ break;
+ case media::VideoColorSpace::TransferID::IEC61966_2_1:
+ transfer_ = V8VideoTransferCharacteristics(
+ V8VideoTransferCharacteristics::Enum::kIec6196621);
+ break;
+ default:
+ // Other values map to unspecified for now.
+ break;
+ }
+
+ switch (color_space.matrix) {
+ case media::VideoColorSpace::MatrixID::RGB:
+ matrix_ =
+ V8VideoMatrixCoefficients(V8VideoMatrixCoefficients::Enum::kRgb);
+ break;
+ case media::VideoColorSpace::MatrixID::BT709:
+ matrix_ =
+ V8VideoMatrixCoefficients(V8VideoMatrixCoefficients::Enum::kBt709);
+ break;
+ case media::VideoColorSpace::MatrixID::BT470BG:
+ matrix_ =
+ V8VideoMatrixCoefficients(V8VideoMatrixCoefficients::Enum::kBt470Bg);
+ break;
+ case media::VideoColorSpace::MatrixID::SMPTE170M:
+ matrix_ = V8VideoMatrixCoefficients(
+ V8VideoMatrixCoefficients::Enum::kSmpte170M);
+ break;
+ default:
+ // Other values map to unspecified for now.
+ break;
+ }
+
+ switch (color_space.range) {
+ case gfx::ColorSpace::RangeID::LIMITED:
+ full_range_ = false;
+ break;
+ case gfx::ColorSpace::RangeID::FULL:
+ full_range_ = true;
+ break;
+ default:
+ // Other values map to unspecified. We could probably map DERIVED to a
+ // specific value, though.
+ break;
+ }
+}
+
+gfx::ColorSpace VideoColorSpace::ToGfxColorSpace() const {
+ gfx::ColorSpace::PrimaryID primaries = gfx::ColorSpace::PrimaryID::INVALID;
+ if (primaries_) {
+ switch (primaries_->AsEnum()) {
+ case V8VideoColorPrimaries::Enum::kBt709:
+ primaries = gfx::ColorSpace::PrimaryID::BT709;
+ break;
+ case V8VideoColorPrimaries::Enum::kBt470Bg:
+ primaries = gfx::ColorSpace::PrimaryID::BT470BG;
+ break;
+ case V8VideoColorPrimaries::Enum::kSmpte170M:
+ primaries = gfx::ColorSpace::PrimaryID::SMPTE170M;
+ break;
+ }
+ }
+
+ gfx::ColorSpace::TransferID transfer = gfx::ColorSpace::TransferID::INVALID;
+ if (transfer_) {
+ switch (transfer_->AsEnum()) {
+ case V8VideoTransferCharacteristics::Enum::kBt709:
+ transfer = gfx::ColorSpace::TransferID::BT709;
+ break;
+ case V8VideoTransferCharacteristics::Enum::kSmpte170M:
+ transfer = gfx::ColorSpace::TransferID::SMPTE170M;
+ break;
+ case V8VideoTransferCharacteristics::Enum::kIec6196621:
+ transfer = gfx::ColorSpace::TransferID::IEC61966_2_1;
+ break;
+ }
+ }
+
+ gfx::ColorSpace::MatrixID matrix = gfx::ColorSpace::MatrixID::INVALID;
+ if (matrix_) {
+ switch (matrix_->AsEnum()) {
+ case V8VideoMatrixCoefficients::Enum::kRgb:
+ matrix = gfx::ColorSpace::MatrixID::RGB;
+ break;
+ case V8VideoMatrixCoefficients::Enum::kBt709:
+ matrix = gfx::ColorSpace::MatrixID::BT709;
+ break;
+ case V8VideoMatrixCoefficients::Enum::kBt470Bg:
+ matrix = gfx::ColorSpace::MatrixID::BT470BG;
+ break;
+ case V8VideoMatrixCoefficients::Enum::kSmpte170M:
+ matrix = gfx::ColorSpace::MatrixID::SMPTE170M;
+ break;
+ }
+ }
+
+ gfx::ColorSpace::RangeID range = gfx::ColorSpace::RangeID::INVALID;
+ if (full_range_) {
+ range = *full_range_ ? gfx::ColorSpace::RangeID::FULL
+ : gfx::ColorSpace::RangeID::LIMITED;
+ }
+
+ return gfx::ColorSpace(primaries, transfer, matrix, range);
+}
+
+media::VideoColorSpace VideoColorSpace::ToMediaColorSpace() const {
+ media::VideoColorSpace::PrimaryID primaries =
+ media::VideoColorSpace::PrimaryID::UNSPECIFIED;
+ if (primaries_) {
+ switch (primaries_->AsEnum()) {
+ case V8VideoColorPrimaries::Enum::kBt709:
+ primaries = media::VideoColorSpace::PrimaryID::BT709;
+ break;
+ case V8VideoColorPrimaries::Enum::kBt470Bg:
+ primaries = media::VideoColorSpace::PrimaryID::BT470BG;
+ break;
+ case V8VideoColorPrimaries::Enum::kSmpte170M:
+ primaries = media::VideoColorSpace::PrimaryID::SMPTE170M;
+ break;
+ }
+ }
+
+ media::VideoColorSpace::TransferID transfer =
+ media::VideoColorSpace::TransferID::UNSPECIFIED;
+ if (transfer_) {
+ switch (transfer_->AsEnum()) {
+ case V8VideoTransferCharacteristics::Enum::kBt709:
+ transfer = media::VideoColorSpace::TransferID::BT709;
+ break;
+ case V8VideoTransferCharacteristics::Enum::kSmpte170M:
+ transfer = media::VideoColorSpace::TransferID::SMPTE170M;
+ break;
+ case V8VideoTransferCharacteristics::Enum::kIec6196621:
+ transfer = media::VideoColorSpace::TransferID::IEC61966_2_1;
+ break;
+ }
+ }
+
+ media::VideoColorSpace::MatrixID matrix =
+ media::VideoColorSpace::MatrixID::UNSPECIFIED;
+ if (matrix_) {
+ switch (matrix_->AsEnum()) {
+ case V8VideoMatrixCoefficients::Enum::kRgb:
+ matrix = media::VideoColorSpace::MatrixID::RGB;
+ break;
+ case V8VideoMatrixCoefficients::Enum::kBt709:
+ matrix = media::VideoColorSpace::MatrixID::BT709;
+ break;
+ case V8VideoMatrixCoefficients::Enum::kBt470Bg:
+ matrix = media::VideoColorSpace::MatrixID::BT470BG;
+ break;
+ case V8VideoMatrixCoefficients::Enum::kSmpte170M:
+ matrix = media::VideoColorSpace::MatrixID::SMPTE170M;
+ break;
+ }
+ }
+
+ gfx::ColorSpace::RangeID range = gfx::ColorSpace::RangeID::INVALID;
+ if (full_range_) {
+ range = *full_range_ ? gfx::ColorSpace::RangeID::FULL
+ : gfx::ColorSpace::RangeID::LIMITED;
+ }
+
+ return media::VideoColorSpace(primaries, transfer, matrix, range);
+}
+
+VideoColorSpaceInit* VideoColorSpace::toJSON() const {
+ auto* init = MakeGarbageCollected<VideoColorSpaceInit>();
+ if (primaries_)
+ init->setPrimaries(*primaries_);
+ if (transfer_)
+ init->setTransfer(*transfer_);
+ if (matrix_)
+ init->setMatrix(*matrix_);
+ if (full_range_)
+ init->setFullRange(*full_range_);
+ return init;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.h
new file mode 100644
index 00000000000..19c40d4edfd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_COLOR_SPACE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_COLOR_SPACE_H_
+
+#include "media/base/video_color_space.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_primaries.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_matrix_coefficients.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_transfer_characteristics.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "ui/gfx/color_space.h"
+
+namespace blink {
+
+class VideoColorSpaceInit;
+
+class MODULES_EXPORT VideoColorSpace final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static VideoColorSpace* Create(const VideoColorSpaceInit*);
+
+ explicit VideoColorSpace() = default;
+ explicit VideoColorSpace(const VideoColorSpaceInit*);
+ explicit VideoColorSpace(const gfx::ColorSpace&);
+ explicit VideoColorSpace(const media::VideoColorSpace&);
+
+ gfx::ColorSpace ToGfxColorSpace() const;
+ media::VideoColorSpace ToMediaColorSpace() const;
+
+ absl::optional<V8VideoColorPrimaries> primaries() const { return primaries_; }
+ absl::optional<V8VideoTransferCharacteristics> transfer() const {
+ return transfer_;
+ }
+ absl::optional<V8VideoMatrixCoefficients> matrix() const { return matrix_; }
+ absl::optional<bool> fullRange() const { return full_range_; }
+
+ VideoColorSpaceInit* toJSON() const;
+
+ private:
+ absl::optional<V8VideoColorPrimaries> primaries_;
+ absl::optional<V8VideoTransferCharacteristics> transfer_;
+ absl::optional<V8VideoMatrixCoefficients> matrix_;
+ absl::optional<bool> full_range_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_COLOR_SPACE_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.idl
index 53f3c48cf19..c257ac12471 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space.idl
@@ -1,16 +1,20 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://github.com/WICG/web-codecs
-// Described in ISO 23001-8:2016
-// See also: https://source.chromium.org/chromium/chromium/src/+/master:media/base/video_color_space.h
-dictionary VideoColorSpace {
- ColorSpacePrimaryID? primaryID;
- ColorSpaceTransferID? transferID;
- ColorSpaceMatrixID? matrixID;
- ColorSpaceRangeID? rangeID;
+[
+ Exposed=(Window,DedicatedWorker),
+ RuntimeEnabled=WebCodecs
+] interface VideoColorSpace {
+ constructor(VideoColorSpaceInit init);
- // TODO(sandersd): custom primary/matrix support.
+ readonly attribute VideoColorPrimaries? primaries;
+ readonly attribute VideoTransferCharacteristics? transfer;
+ readonly attribute VideoMatrixCoefficients? matrix;
+ readonly attribute boolean? fullRange;
+
+ // Note: [Default] implementation would be correct.
+ VideoColorSpaceInit toJSON();
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space_init.idl
new file mode 100644
index 00000000000..47d06f17c57
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_color_space_init.idl
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+dictionary VideoColorSpaceInit {
+ VideoColorPrimaries primaries;
+ VideoTransferCharacteristics transfer;
+ VideoMatrixCoefficients matrix;
+ boolean fullRange;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
index ae87cbf06a5..e4b11ddf21f 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
@@ -8,13 +8,13 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
#include "base/time/time.h"
#include "media/base/decoder_buffer.h"
#include "media/base/limits.h"
#include "media/base/media_util.h"
#include "media/base/mime_util.h"
#include "media/base/supported_types.h"
+#include "media/base/video_aspect_ratio.h"
#include "media/base/video_decoder.h"
#include "media/media_buildflags.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
@@ -22,12 +22,16 @@
#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/modules/v8/v8_encoded_video_chunk.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_support.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_region.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_config_eval.h"
#include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
+#include "third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_color_space.h"
#include "third_party/blink/renderer/modules/webcodecs/video_decoder_broker.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -39,23 +43,29 @@
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/libaom/libaom_buildflags.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
+#if BUILDFLAG(ENABLE_LIBAOM)
+#include "third_party/libaom/source/libaom/aom/aom_decoder.h"
+#include "third_party/libaom/source/libaom/aom/aomdx.h"
+#endif
+
+#if BUILDFLAG(ENABLE_LIBVPX)
+#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
+#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
+#endif
+
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#include "media/filters/h264_to_annex_b_bitstream_converter.h"
#include "media/formats/mp4/box_definitions.h"
-#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
+#endif
namespace blink {
namespace {
-media::GpuVideoAcceleratorFactories* GetGpuFactoriesOnMainThread() {
- DCHECK(IsMainThread());
- return Platform::Current()->GetGpuFactories();
-}
-
void DecoderSupport_OnKnown(
VideoDecoderSupport* support,
std::unique_ptr<VideoDecoder::MediaConfigType> media_config,
@@ -63,35 +73,11 @@ void DecoderSupport_OnKnown(
media::GpuVideoAcceleratorFactories* gpu_factories) {
DCHECK(gpu_factories->IsDecoderSupportKnown());
support->setSupported(
- gpu_factories->IsDecoderConfigSupported(*media_config) ==
+ gpu_factories->IsDecoderConfigSupportedOrUnknown(*media_config) ==
media::GpuVideoAcceleratorFactories::Supported::kTrue);
resolver->Resolve(support);
}
-void DecoderSupport_OnGpuFactories(
- VideoDecoderSupport* support,
- std::unique_ptr<VideoDecoder::MediaConfigType> media_config,
- ScriptPromiseResolver* resolver,
- media::GpuVideoAcceleratorFactories* gpu_factories) {
- if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) {
- support->setSupported(false);
- resolver->Resolve(support);
- return;
- }
-
- if (gpu_factories->IsDecoderSupportKnown()) {
- DecoderSupport_OnKnown(support, std::move(media_config), resolver,
- gpu_factories);
- return;
- }
-
- gpu_factories->NotifyDecoderSupportKnown(
- ConvertToBaseOnceCallback(CrossThreadBindOnce(
- &DecoderSupport_OnKnown, WrapCrossThreadPersistent(support),
- std::move(media_config), WrapCrossThreadPersistent(resolver),
- CrossThreadUnretained(gpu_factories))));
-}
-
bool ParseCodecString(const String& codec_string,
media::VideoType& out_video_type,
String& out_console_message) {
@@ -144,107 +130,34 @@ bool IsValidConfig(const VideoDecoderConfig& config,
const uint32_t coded_height = config.codedHeight();
if (coded_width == 0 || coded_width > media::limits::kMaxDimension ||
coded_height == 0 || coded_height > media::limits::kMaxDimension) {
+ // TODO(crbug.com/1212865): Exceeding implementation limits should not
+ // throw in isConfigSupported() (the config is valid, just unsupported).
out_console_message = String::Format("Invalid coded size (%u, %u).",
coded_width, coded_height);
return false;
}
-
- // Validate visible region.
- uint32_t visible_left = 0;
- uint32_t visible_top = 0;
- uint32_t visible_width = coded_width;
- uint32_t visible_height = coded_height;
- if (config.hasVisibleRegion()) {
- visible_left = config.visibleRegion()->left();
- visible_top = config.visibleRegion()->top();
- visible_width = config.visibleRegion()->width();
- visible_height = config.visibleRegion()->height();
- } else {
- // TODO(sandersd): Plumb |execution_context| so we can log a deprecation
- // notice.
- if (config.hasCropLeft()) {
- visible_left = config.cropLeft();
- if (visible_left >= coded_width) {
- out_console_message =
- String::Format("Invalid cropLeft %u for codedWidth %u.",
- visible_left, coded_width);
- return false;
- }
- visible_width = coded_width - visible_left;
- }
- if (config.hasCropTop()) {
- visible_top = config.cropTop();
- if (visible_top >= coded_height) {
- out_console_message =
- String::Format("Invalid cropTop %u for codedHeight %u.",
- visible_top, coded_height);
- return false;
- }
- visible_width = coded_width - visible_left;
- }
- if (config.hasCropWidth())
- visible_width = config.cropWidth();
- if (config.hasCropHeight())
- visible_height = config.cropHeight();
- }
- if (visible_left >= coded_width || visible_top >= coded_height ||
- visible_width == 0 || visible_width > media::limits::kMaxDimension ||
- visible_height == 0 || visible_height > media::limits::kMaxDimension ||
- visible_left + visible_width > coded_width ||
- visible_top + visible_height > coded_height) {
- out_console_message = String::Format(
- "Invalid visible region {left: %u, top: %u, width: %u, height: %u} "
- "for coded size (%u, %u).",
- visible_left, visible_top, visible_width, visible_height, coded_width,
- coded_height);
- return false;
- }
- } else {
- if (config.hasVisibleRegion()) {
- out_console_message =
- "Invalid config, visibleRegion specified without coded size.";
- return false;
- }
- if (config.hasCropLeft()) {
- out_console_message =
- "Invalid config, cropLeft specified without coded size.";
- return false;
- }
- if (config.hasCropTop()) {
- out_console_message =
- "Invalid config, cropTop specified without coded size.";
- return false;
- }
- if (config.hasCropWidth()) {
- out_console_message =
- "Invalid config, cropWidth specified without coded size.";
- return false;
- }
- if (config.hasCropHeight()) {
- out_console_message =
- "Invalid config, cropHeight specified without coded size.";
- return false;
- }
}
- if (config.hasDisplayWidth() || config.hasDisplayHeight()) {
- if (!config.hasDisplayWidth()) {
+ if (config.hasDisplayAspectWidth() || config.hasDisplayAspectHeight()) {
+ if (!config.hasDisplayAspectWidth()) {
out_console_message =
- "Invalid config, displayHeight specified without displayWidth.";
+ "Invalid config, displayAspectHeight specified without "
+ "displayAspectWidth.";
return false;
}
- if (!config.hasDisplayHeight()) {
+ if (!config.hasDisplayAspectHeight()) {
out_console_message =
- "Invalid config, displayWidth specified without displayHeight.";
+ "Invalid config, displayAspectWidth specified without "
+ "displayAspectHeight.";
return false;
}
- uint32_t display_width = config.displayWidth();
- uint32_t display_height = config.displayHeight();
- if (display_width == 0 || display_width > media::limits::kMaxDimension ||
- display_height == 0 || display_height > media::limits::kMaxDimension) {
- out_console_message = String::Format("Invalid display size (%u, %u).",
- display_width, display_height);
+ uint32_t display_aspect_width = config.displayAspectWidth();
+ uint32_t display_aspect_height = config.displayAspectHeight();
+ if (display_aspect_width == 0 || display_aspect_height == 0) {
+ out_console_message =
+ String::Format("Invalid display aspect (%u, %u).",
+ display_aspect_width, display_aspect_height);
return false;
}
}
@@ -252,16 +165,21 @@ bool IsValidConfig(const VideoDecoderConfig& config,
return true;
}
-VideoDecoderConfig* CopyConfig(const VideoDecoderConfig& config) {
+VideoDecoderConfig* CopyConfig(const VideoDecoderConfig& config,
+ ExceptionState& exception_state) {
VideoDecoderConfig* copy = VideoDecoderConfig::Create();
copy->setCodec(config.codec());
if (config.hasDescription()) {
- DOMArrayPiece buffer(config.description());
+ auto desc_wrapper = AsSpan<const uint8_t>(config.description());
+ if (!desc_wrapper.data()) {
+ exception_state.ThrowTypeError("description is detached.");
+ return nullptr;
+ }
DOMArrayBuffer* buffer_copy =
- DOMArrayBuffer::Create(buffer.Data(), buffer.ByteLength());
+ DOMArrayBuffer::Create(desc_wrapper.data(), desc_wrapper.size());
copy->setDescription(
- ArrayBufferOrArrayBufferView::FromArrayBuffer(buffer_copy));
+ MakeGarbageCollected<AllowSharedBufferSource>(buffer_copy));
}
if (config.hasCodedWidth())
@@ -270,32 +188,17 @@ VideoDecoderConfig* CopyConfig(const VideoDecoderConfig& config) {
if (config.hasCodedHeight())
copy->setCodedHeight(config.codedHeight());
- if (config.hasVisibleRegion()) {
- auto* region = MakeGarbageCollected<VideoFrameRegion>();
- region->setLeft(config.visibleRegion()->left());
- region->setTop(config.visibleRegion()->top());
- region->setWidth(config.visibleRegion()->width());
- region->setHeight(config.visibleRegion()->height());
- copy->setVisibleRegion(region);
- }
-
- if (config.hasCropLeft())
- copy->setCropLeft(config.cropLeft());
+ if (config.hasDisplayAspectWidth())
+ copy->setDisplayAspectWidth(config.displayAspectWidth());
- if (config.hasCropTop())
- copy->setCropTop(config.cropTop());
+ if (config.hasDisplayAspectHeight())
+ copy->setDisplayAspectHeight(config.displayAspectHeight());
- if (config.hasCropWidth())
- copy->setCropWidth(config.cropWidth());
-
- if (config.hasCropHeight())
- copy->setCropHeight(config.cropHeight());
-
- if (config.hasDisplayWidth())
- copy->setDisplayWidth(config.displayWidth());
-
- if (config.hasDisplayHeight())
- copy->setDisplayHeight(config.displayHeight());
+ if (config.hasColorSpace()) {
+ VideoColorSpace* color_space =
+ MakeGarbageCollected<VideoColorSpace>(config.colorSpace());
+ copy->setColorSpace(color_space->toJSON());
+ }
if (config.hasHardwareAcceleration())
copy->setHardwareAcceleration(config.hardwareAcceleration());
@@ -306,6 +209,37 @@ VideoDecoderConfig* CopyConfig(const VideoDecoderConfig& config) {
return copy;
}
+void ParseAv1KeyFrame(const media::DecoderBuffer& buffer, bool* is_key_frame) {
+#if BUILDFLAG(ENABLE_LIBAOM)
+ aom_codec_stream_info_t stream_info = {0};
+ auto status = aom_codec_peek_stream_info(
+ &aom_codec_av1_dx_algo, buffer.data(), buffer.data_size(), &stream_info);
+ *is_key_frame = (status == AOM_CODEC_OK) && stream_info.is_kf;
+#endif
+}
+
+void ParseVpxKeyFrame(const media::DecoderBuffer& buffer,
+ media::VideoCodec codec,
+ bool* is_key_frame) {
+#if BUILDFLAG(ENABLE_LIBVPX)
+ vpx_codec_stream_info_t stream_info = {0};
+ stream_info.sz = sizeof(vpx_codec_stream_info_t);
+ auto status = vpx_codec_peek_stream_info(
+ codec == media::kCodecVP8 ? &vpx_codec_vp8_dx_algo
+ : &vpx_codec_vp9_dx_algo,
+ buffer.data(), static_cast<uint32_t>(buffer.data_size()), &stream_info);
+ *is_key_frame = (status == VPX_CODEC_OK) && stream_info.is_kf;
+#endif
+}
+
+void ParseH264KeyFrame(const media::DecoderBuffer& buffer, bool* is_key_frame) {
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+ auto result = media::mp4::AVC::AnalyzeAnnexB(
+ buffer.data(), buffer.data_size(), std::vector<media::SubsampleEntry>());
+ *is_key_frame = result.is_keyframe.value_or(false);
+#endif
+}
+
} // namespace
// static
@@ -389,7 +323,7 @@ ScriptPromise VideoDecoder::isConfigSupported(ScriptState* script_state,
ExceptionState& exception_state) {
HardwarePreference hw_pref = GetHardwareAccelerationPreference(*config);
- if (hw_pref == HardwarePreference::kRequire)
+ if (hw_pref == HardwarePreference::kPreferHardware)
return IsAcceleratedConfigSupported(script_state, config, exception_state);
media::VideoType video_type;
@@ -403,7 +337,12 @@ ScriptPromise VideoDecoder::isConfigSupported(ScriptState* script_state,
// Accept all supported configs if we are not requiring hardware only.
VideoDecoderSupport* support = VideoDecoderSupport::Create();
support->setSupported(media::IsSupportedVideoType(video_type));
- support->setConfig(CopyConfig(*config));
+
+ auto* config_copy = CopyConfig(*config, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
+
+ support->setConfig(config_copy);
return ScriptPromise::Cast(script_state, ToV8(support, script_state));
}
@@ -430,27 +369,18 @@ ScriptPromise VideoDecoder::IsAcceleratedConfigSupported(
return ScriptPromise();
}
+ auto* config_copy = CopyConfig(*config, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
+
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
VideoDecoderSupport* support = VideoDecoderSupport::Create();
- support->setConfig(CopyConfig(*config));
+ support->setConfig(config_copy);
- if (IsMainThread()) {
- media::GpuVideoAcceleratorFactories* gpu_factories =
- Platform::Current()->GetGpuFactories();
- DecoderSupport_OnGpuFactories(support, std::move(media_config), resolver,
- gpu_factories);
- } else {
- auto on_gpu_factories_cb = CrossThreadBindOnce(
- &DecoderSupport_OnGpuFactories, WrapCrossThreadPersistent(support),
- std::move(media_config), WrapCrossThreadPersistent(resolver));
-
- Thread::MainThread()->GetTaskRunner()->PostTaskAndReplyWithResult(
- FROM_HERE,
- ConvertToBaseOnceCallback(
- CrossThreadBindOnce(&GetGpuFactoriesOnMainThread)),
- ConvertToBaseOnceCallback(std::move(on_gpu_factories_cb)));
- }
+ RetrieveGpuFactoriesWithKnownDecoderSupport(CrossThreadBindOnce(
+ &DecoderSupport_OnKnown, WrapCrossThreadPersistent(support),
+ std::move(media_config), WrapCrossThreadPersistent(resolver)));
return promise;
}
@@ -484,13 +414,15 @@ CodecConfigEval VideoDecoder::MakeMediaVideoDecoderConfig(
if (!IsValidConfig(config, video_type, out_console_message))
return CodecConfigEval::kInvalid;
- // TODO(sandersd): Can we allow shared ArrayBuffers?
std::vector<uint8_t> extra_data;
if (config.hasDescription()) {
- DOMArrayPiece buffer(config.description());
- uint8_t* start = static_cast<uint8_t*>(buffer.Data());
- size_t size = buffer.ByteLength();
- extra_data.assign(start, start + size);
+ // TODO(crbug.com/1179970): This should throw if description is detached.
+ auto desc_wrapper = AsSpan<const uint8_t>(config.description());
+ if (!desc_wrapper.empty()) {
+ const uint8_t* start = desc_wrapper.data();
+ const size_t size = desc_wrapper.size();
+ extra_data.assign(start, start + size);
+ }
}
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -516,16 +448,41 @@ CodecConfigEval VideoDecoder::MakeMediaVideoDecoderConfig(
}
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
- // TODO(sandersd): Use size information from the VideoDecoderConfig when it is
- // provided, and figure out how to combine it with the avcC. Update fuzzer to
- // match.
- gfx::Size size = gfx::Size(1280, 720);
+ // Guess 720p if no coded size hint is provided. This choice should result in
+ // a preference for hardware decode.
+ gfx::Size coded_size = gfx::Size(1280, 720);
+ if (config.hasCodedWidth() && config.hasCodedHeight())
+ coded_size = gfx::Size(config.codedWidth(), config.codedHeight());
+
+ // These are meaningless.
+ // TODO(crbug.com/1214061): Remove.
+ gfx::Rect visible_rect(gfx::Point(), coded_size);
+ gfx::Size natural_size = coded_size;
+
+ // Note: Using a default-constructed VideoAspectRatio allows decoders to
+ // override using in-band metadata.
+ media::VideoAspectRatio aspect_ratio;
+ if (config.hasDisplayAspectWidth() && config.hasDisplayAspectHeight()) {
+ aspect_ratio = media::VideoAspectRatio::DAR(config.displayAspectWidth(),
+ config.displayAspectHeight());
+ }
+
+ // TODO(crbug.com/1138680): Ensure that this default value is acceptable
+ // under the WebCodecs spec. Should be BT.709 for YUV, sRGB for RGB, or
+ // whatever was explicitly set for codec strings that include a color space.
+ media::VideoColorSpace media_color_space = video_type.color_space;
+ if (config.hasColorSpace()) {
+ VideoColorSpace* color_space =
+ MakeGarbageCollected<VideoColorSpace>(config.colorSpace());
+ media_color_space = color_space->ToMediaColorSpace();
+ }
out_media_config.Initialize(
video_type.codec, video_type.profile,
- media::VideoDecoderConfig::AlphaMode::kIsOpaque, video_type.color_space,
- media::kNoTransformation, size, gfx::Rect(gfx::Point(), size), size,
+ media::VideoDecoderConfig::AlphaMode::kIsOpaque, media_color_space,
+ media::kNoTransformation, coded_size, visible_rect, natural_size,
extra_data, media::EncryptionScheme::kUnencrypted);
+ out_media_config.set_aspect_ratio(aspect_ratio);
return CodecConfigEval::kSupported;
}
@@ -543,22 +500,25 @@ CodecConfigEval VideoDecoder::MakeMediaConfig(const ConfigType& config,
String* out_console_message) {
DCHECK(out_media_config);
DCHECK(out_console_message);
- return MakeMediaVideoDecoderConfig(config, *out_media_config,
+ auto result = MakeMediaVideoDecoderConfig(config, *out_media_config,
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
- h264_converter_ /* out */,
- h264_avcc_ /* out */,
+ h264_converter_ /* out */,
+ h264_avcc_ /* out */,
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
- *out_console_message);
+ *out_console_message);
+ if (result == CodecConfigEval::kSupported)
+ current_codec_ = out_media_config->codec();
+ return result;
}
media::StatusOr<scoped_refptr<media::DecoderBuffer>>
-VideoDecoder::MakeDecoderBuffer(const InputType& chunk) {
- uint8_t* src = static_cast<uint8_t*>(chunk.data()->Data());
- size_t src_size = chunk.data()->ByteLength();
-
- scoped_refptr<media::DecoderBuffer> decoder_buffer;
+VideoDecoder::MakeDecoderBuffer(const InputType& chunk, bool verify_key_frame) {
+ scoped_refptr<media::DecoderBuffer> decoder_buffer = chunk.buffer();
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
if (h264_converter_) {
+ const uint8_t* src = chunk.buffer()->data();
+ size_t src_size = chunk.buffer()->data_size();
+
// Note: this may not be safe if support for SharedArrayBuffers is added.
uint32_t output_size = h264_converter_->CalculateNeededOutputBufferSize(
src, static_cast<uint32_t>(src_size), h264_avcc_.get());
@@ -576,23 +536,25 @@ VideoDecoder::MakeDecoderBuffer(const InputType& chunk) {
}
decoder_buffer = media::DecoderBuffer::CopyFrom(buf.data(), output_size);
+ decoder_buffer->set_timestamp(chunk.buffer()->timestamp());
+ decoder_buffer->set_duration(chunk.buffer()->duration());
}
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
- if (!decoder_buffer)
- decoder_buffer = media::DecoderBuffer::CopyFrom(src, src_size);
-
- decoder_buffer->set_timestamp(
- base::TimeDelta::FromMicroseconds(chunk.timestamp()));
-
- if (chunk.duration()) {
- // Clamp within bounds of our internal TimeDelta-based duration.
- // See media/base/timestamp_constants.h
- decoder_buffer->set_duration(base::TimeDelta::FromMicroseconds(
- std::min(base::saturated_cast<int64_t>(chunk.duration().value()),
- std::numeric_limits<int64_t>::max() - 1)));
- }
- decoder_buffer->set_is_key_frame(chunk.type() == "key");
+ bool is_key_frame = chunk.type() == "key";
+ if (verify_key_frame) {
+ if (current_codec_ == media::kCodecVP9 ||
+ current_codec_ == media::kCodecVP8) {
+ ParseVpxKeyFrame(*decoder_buffer, current_codec_, &is_key_frame);
+ } else if (current_codec_ == media::kCodecAV1) {
+ ParseAv1KeyFrame(*decoder_buffer, &is_key_frame);
+ } else if (current_codec_ == media::kCodecH264) {
+ ParseH264KeyFrame(*decoder_buffer, &is_key_frame);
+ }
+
+ if (!is_key_frame)
+ return media::Status(media::StatusCode::kKeyFrameRequired);
+ }
return decoder_buffer;
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.h
index cee14064a54..d2f19924283 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.h
@@ -115,7 +115,8 @@ class MODULES_EXPORT VideoDecoder : public DecoderTemplate<VideoDecoderTraits> {
MediaConfigType* out_media_config,
String* out_console_message) override;
media::StatusOr<scoped_refptr<media::DecoderBuffer>> MakeDecoderBuffer(
- const InputType& input) override;
+ const InputType& input,
+ bool verify_key_frame) override;
static ScriptPromise IsAcceleratedConfigSupported(ScriptState* script_state,
const VideoDecoderConfig*,
@@ -126,6 +127,8 @@ class MODULES_EXPORT VideoDecoder : public DecoderTemplate<VideoDecoderTraits> {
std::unique_ptr<media::mp4::AVCDecoderConfigurationRecord> h264_avcc_;
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
+ media::VideoCodec current_codec_ = media::kUnknownVideoCodec;
+
private:
// DecoderTemplate implementation.
HardwarePreference GetHardwarePreference(const ConfigType& config) override;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.idl
index 34659e49734..9e46667e591 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder.idl
@@ -13,6 +13,7 @@
// encoders.
[
Exposed=(Window,DedicatedWorker),
+ SecureContext,
RuntimeEnabled=WebCodecs,
ActiveScriptWrappable
] interface VideoDecoder {
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
index b3bdb2ffb23..9a2251e73ea 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
@@ -197,13 +197,13 @@ class MediaVideoTaskWrapper {
// |external_decoder_factory|.
std::unique_ptr<media::DecoderFactory> external_decoder_factory;
#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
- if (hardware_preference_ != HardwarePreference::kDeny) {
+ if (hardware_preference_ != HardwarePreference::kPreferSoftware) {
external_decoder_factory = std::make_unique<media::MojoDecoderFactory>(
media_interface_factory_.get());
}
#endif
- if (hardware_preference_ == HardwarePreference::kRequire) {
+ if (hardware_preference_ == HardwarePreference::kPreferHardware) {
decoder_factory_ = std::move(external_decoder_factory);
return;
}
@@ -310,7 +310,7 @@ class MediaVideoTaskWrapper {
std::unique_ptr<media::DecoderFactory> decoder_factory_;
std::unique_ptr<media::VideoDecoder> decoder_;
gfx::ColorSpace target_color_space_;
- HardwarePreference hardware_preference_ = HardwarePreference::kAllow;
+ HardwarePreference hardware_preference_ = HardwarePreference::kNoPreference;
bool decoder_factory_needs_update_ = true;
std::unique_ptr<media::MediaLog> media_log_;
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
index d055f86fcaf..2bba67588b5 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
@@ -85,7 +85,6 @@ class FakeMojoMediaClient : public media::MojoMediaClient {
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
media::MediaLog* media_log,
media::mojom::CommandBufferIdPtr command_buffer_id,
- media::VideoDecoderImplementation implementation,
media::RequestOverlayInfoCB request_overlay_info_cb,
const gfx::ColorSpace& target_color_space) override {
return std::make_unique<FakeGpuVideoDecoder>();
@@ -238,7 +237,7 @@ class VideoDecoderBrokerTest : public testing::Test {
std::make_unique<media::MockGpuVideoAcceleratorFactories>(nullptr);
EXPECT_CALL(*gpu_factories_, GetTaskRunner())
.WillRepeatedly(Return(media_thread_->task_runner()));
- EXPECT_CALL(*gpu_factories_, IsDecoderConfigSupported(_, _))
+ EXPECT_CALL(*gpu_factories_, IsDecoderConfigSupported(_))
.WillRepeatedly(
Return(media::GpuVideoAcceleratorFactories::Supported::kTrue));
}
@@ -364,7 +363,7 @@ TEST_F(VideoDecoderBrokerTest, Init_RequireAcceleration) {
ConstructDecoder(*v8_scope.GetExecutionContext());
EXPECT_EQ(GetDecoderType(), media::VideoDecoderType::kBroker);
- decoder_broker_->SetHardwarePreference(HardwarePreference::kRequire);
+ decoder_broker_->SetHardwarePreference(HardwarePreference::kPreferHardware);
InitializeDecoder(media::TestVideoConfig::Normal(), /*expect_success*/ false);
EXPECT_EQ(GetDecoderType(), media::VideoDecoderType::kBroker);
@@ -379,7 +378,7 @@ TEST_F(VideoDecoderBrokerTest, Init_DenyAcceleration) {
ConstructDecoder(*execution_context);
EXPECT_EQ(GetDecoderType(), media::VideoDecoderType::kBroker);
- decoder_broker_->SetHardwarePreference(HardwarePreference::kDeny);
+ decoder_broker_->SetHardwarePreference(HardwarePreference::kPreferSoftware);
// Use an extra-large video to push us towards a hardware decoder.
media::VideoDecoderConfig config = media::TestVideoConfig::ExtraLarge();
@@ -396,14 +395,14 @@ TEST_F(VideoDecoderBrokerTest, Decode_MultipleAccelerationPreferences) {
EXPECT_EQ(GetDecoderType(), media::VideoDecoderType::kBroker);
// Make sure we can decode software only.
- decoder_broker_->SetHardwarePreference(HardwarePreference::kDeny);
+ decoder_broker_->SetHardwarePreference(HardwarePreference::kPreferSoftware);
InitializeDecoder(media::TestVideoConfig::Normal());
DecodeBuffer(media::ReadTestDataFile("vp8-I-frame-320x120"));
DecodeBuffer(media::DecoderBuffer::CreateEOSBuffer());
ASSERT_EQ(1U, output_frames_.size());
// Make sure we can decoder with hardware only.
- decoder_broker_->SetHardwarePreference(HardwarePreference::kRequire);
+ decoder_broker_->SetHardwarePreference(HardwarePreference::kPreferHardware);
// Use an extra-large video to ensure we don't get a software decoder.
media::VideoDecoderConfig large_config = media::TestVideoConfig::ExtraLarge();
@@ -414,7 +413,7 @@ TEST_F(VideoDecoderBrokerTest, Decode_MultipleAccelerationPreferences) {
ASSERT_EQ(2U, output_frames_.size());
// Make sure we can decode with both HW or SW as appropriate.
- decoder_broker_->SetHardwarePreference(HardwarePreference::kAllow);
+ decoder_broker_->SetHardwarePreference(HardwarePreference::kNoPreference);
// Use a large frame to force hardware decode.
InitializeDecoder(large_config);
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl
index 8bbf71ef633..9b6e2f5a48e 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl
@@ -15,32 +15,21 @@ dictionary VideoDecoderConfig {
// avcC, vpcC, or etc.
// TODO(sandersd): Define what happens if the parsed description differs from
// the metadata below.
- BufferSource description;
+ AllowSharedBufferSource description;
// Hint about the encoded size of the content.
- // TODO(sandersd): Draft spec marks these as required.
[EnforceRange] unsigned long codedWidth;
[EnforceRange] unsigned long codedHeight;
- // Hint about the visible region of the content.
- VideoFrameRegion visibleRegion;
+ // Display aspect ratio of the content.
+ [EnforceRange] unsigned long displayAspectWidth;
+ [EnforceRange] unsigned long displayAspectHeight;
- // Hint about the pixel aspect ratio of the content.
- [EnforceRange] unsigned long displayWidth;
- [EnforceRange] unsigned long displayHeight;
+ // Hint about the color space of the content.
+ VideoColorSpaceInit colorSpace;
- // TODO(sandersd): color space.
- // TODO(sandersd): Constraints (sequential access) and requirements
- // (imagebitmap, colorspace conversion).
-
- HardwarePreference hardwareAcceleration = "allow";
+ HardwarePreference hardwareAcceleration = "no-preference";
// Hint that decoders should be configured for latency versus throughput.
boolean optimizeForLatency;
-
- // DEPRECATED: Use visibleRegion.
- [EnforceRange] unsigned long cropLeft;
- [EnforceRange] unsigned long cropTop;
- [EnforceRange] unsigned long cropWidth;
- [EnforceRange] unsigned long cropHeight;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
index 6d08bca1a86..5dd0e569cfe 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -9,6 +9,8 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
@@ -28,6 +30,7 @@
#include "media/base/video_util.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator_adapter.h"
+#include "media/video/video_encoder_fallback.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -37,20 +40,26 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_avc_encoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk_metadata.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_encode_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_support.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_state_helper.h"
#include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
+#include "third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_color_space.h"
#include "third_party/blink/renderer/platform/bindings/enumeration_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/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
@@ -79,6 +88,7 @@ namespace blink {
namespace {
constexpr const char kCategory[] = "media";
+constexpr int kMaxActiveEncodes = 5;
// Use this function in cases when we can't immediately delete |ptr| because
// there might be its methods on the call stack.
@@ -123,7 +133,7 @@ bool IsAcceleratedConfigurationSupported(
}
double max_supported_framerate =
- double{supported_profile.max_framerate_numerator} /
+ static_cast<double>(supported_profile.max_framerate_numerator) /
supported_profile.max_framerate_denominator;
if (options.framerate.has_value() &&
options.framerate.value() > max_supported_framerate) {
@@ -136,36 +146,6 @@ bool IsAcceleratedConfigurationSupported(
return found_supported_profile;
}
-std::unique_ptr<media::VideoEncoder> CreateAcceleratedVideoEncoder(
- media::VideoCodecProfile profile,
- const media::VideoEncoder::Options& options,
- media::GpuVideoAcceleratorFactories* gpu_factories) {
- if (!IsAcceleratedConfigurationSupported(profile, options, gpu_factories))
- return nullptr;
-
- auto task_runner = Thread::Current()->GetTaskRunner();
- return std::make_unique<
- media::AsyncDestroyVideoEncoder<media::VideoEncodeAcceleratorAdapter>>(
- std::make_unique<media::VideoEncodeAcceleratorAdapter>(
- gpu_factories, std::move(task_runner)));
-}
-
-std::unique_ptr<media::VideoEncoder> CreateVpxVideoEncoder() {
-#if BUILDFLAG(ENABLE_LIBVPX)
- return std::make_unique<media::VpxVideoEncoder>();
-#else
- return nullptr;
-#endif // BUILDFLAG(ENABLE_LIBVPX)
-}
-
-std::unique_ptr<media::VideoEncoder> CreateOpenH264VideoEncoder() {
-#if BUILDFLAG(ENABLE_OPENH264)
- return std::make_unique<media::OpenH264VideoEncoder>();
-#else
- return nullptr;
-#endif // BUILDFLAG(ENABLE_OPENH264)
-}
-
VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
const VideoEncoderConfig* config,
ExceptionState& exception_state) {
@@ -195,6 +175,24 @@ VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
return nullptr;
}
+ result->options.latency_mode =
+ (config->latencyMode() == "quality")
+ ? media::VideoEncoder::LatencyMode::Quality
+ : media::VideoEncoder::LatencyMode::Realtime;
+
+ if (config->hasBitrate()) {
+ uint32_t bps = base::saturated_cast<uint32_t>(config->bitrate());
+ if (config->hasBitrateMode() && config->bitrateMode() == "constant") {
+ result->options.bitrate = media::Bitrate::ConstantBitrate(bps);
+ } else {
+ // VBR in media:Bitrate supports both target and peak bitrate.
+ // Currently webcodecs doesn't expose peak bitrate
+ // (assuming unconstrained VBR), here we just set peak as 10 times
+ // target as a good enough way of expressing unconstrained VBR.
+ result->options.bitrate = media::Bitrate::VariableBitrate(bps, 10 * bps);
+ }
+ }
+
if (config->hasDisplayWidth() && config->hasDisplayHeight()) {
result->display_size.emplace(config->displayWidth(),
config->displayHeight());
@@ -203,7 +201,8 @@ VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
if (config->hasFramerate()) {
constexpr double kMinFramerate = .0001;
constexpr double kMaxFramerate = 1'000'000'000;
- if (config->framerate() < kMinFramerate ||
+ if (std::isnan(config->framerate()) ||
+ config->framerate() < kMinFramerate ||
config->framerate() > kMaxFramerate) {
exception_state.ThrowTypeError(String::Format(
"Invalid framerate; expected range from %f to %f, received %f.",
@@ -213,9 +212,6 @@ VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
result->options.framerate = config->framerate();
}
- if (config->hasBitrate())
- result->options.bitrate = config->bitrate();
-
// https://w3c.github.io/webrtc-svc/
if (config->hasScalabilityMode()) {
if (config->scalabilityMode() == "L1T2") {
@@ -228,7 +224,7 @@ VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
}
}
- // The IDL defines a default value of "allow".
+ // The IDL defines a default value of "no-preference".
DCHECK(config->hasHardwareAcceleration());
result->hw_pref = StringToHardwarePreference(
@@ -237,7 +233,6 @@ VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
bool is_codec_ambiguous = true;
result->codec = media::kUnknownVideoCodec;
result->profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
- result->color_space = media::VideoColorSpace::REC709();
result->level = 0;
result->codec_string = config->codec();
@@ -250,6 +245,11 @@ VideoEncoderTraits::ParsedConfig* ParseConfigStatic(
return nullptr;
}
+ // For now spec allows UA to always choose the output color space, so ignore
+ // whatever we parsed from the codec string. Hard-code to 601 since that is
+ // correct most often. See https://crbug.com/1241448.
+ result->color_space = media::VideoColorSpace::REC601();
+
// We are done with the parsing.
if (!config->hasAvc())
return result;
@@ -328,7 +328,16 @@ VideoEncoderConfig* CopyConfig(const VideoEncoderConfig& config) {
if (config.hasHardwareAcceleration())
result->setHardwareAcceleration(config.hardwareAcceleration());
- if (config.hasAvc() && config.avc()->format()) {
+ if (config.hasAlpha())
+ result->setAlpha(config.alpha());
+
+ if (config.hasBitrateMode())
+ result->setBitrateMode(config.bitrateMode());
+
+ if (config.hasLatencyMode())
+ result->setLatencyMode(config.latencyMode());
+
+ if (config.hasAvc() && config.avc()->hasFormat()) {
auto* avc = AvcEncoderConfig::Create();
avc->setFormat(config.avc()->format());
result->setAvc(avc);
@@ -337,6 +346,23 @@ VideoEncoderConfig* CopyConfig(const VideoEncoderConfig& config) {
return result;
}
+#if defined(OS_MAC)
+const base::Feature kWebCodecsEncoderGpuMemoryBufferReadback{
+ "WebCodecsEncoderGpuMemoryBufferReadback",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
+bool CanUseGpuMemoryBufferReadback(media::VideoPixelFormat format) {
+#if defined(OS_MAC)
+ // GMB readback only works with NV12, so only opaque buffers can be used.
+ return (format == media::PIXEL_FORMAT_XBGR ||
+ format == media::PIXEL_FORMAT_XRGB) &&
+ base::FeatureList::IsEnabled(kWebCodecsEncoderGpuMemoryBufferReadback);
+#else
+ return false;
+#endif
+}
+
} // namespace
// static
@@ -389,43 +415,86 @@ void VideoEncoder::UpdateEncoderLog(std::string encoder_name,
is_hw_accelerated);
}
+std::unique_ptr<media::VideoEncoder> CreateAcceleratedVideoEncoder(
+ media::VideoCodecProfile profile,
+ const media::VideoEncoder::Options& options,
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ if (!IsAcceleratedConfigurationSupported(profile, options, gpu_factories))
+ return nullptr;
+
+ auto task_runner = Thread::Current()->GetTaskRunner();
+ return std::make_unique<
+ media::AsyncDestroyVideoEncoder<media::VideoEncodeAcceleratorAdapter>>(
+ std::make_unique<media::VideoEncodeAcceleratorAdapter>(
+ gpu_factories, std::move(task_runner)));
+}
+
+std::unique_ptr<media::VideoEncoder> CreateVpxVideoEncoder() {
+#if BUILDFLAG(ENABLE_LIBVPX)
+ return std::make_unique<media::VpxVideoEncoder>();
+#else
+ return nullptr;
+#endif // BUILDFLAG(ENABLE_LIBVPX)
+}
+
+std::unique_ptr<media::VideoEncoder> CreateOpenH264VideoEncoder() {
+#if BUILDFLAG(ENABLE_OPENH264)
+ return std::make_unique<media::OpenH264VideoEncoder>();
+#else
+ return nullptr;
+#endif // BUILDFLAG(ENABLE_OPENH264)
+}
+
+// This method is static and takes |self| in order to make it possible to use it
+// with a weak |this|. It's needed in to avoid a persistent reference cycle.
+std::unique_ptr<media::VideoEncoder> VideoEncoder::CreateSoftwareVideoEncoder(
+ VideoEncoder* self,
+ media::VideoCodec codec) {
+ if (!self)
+ return nullptr;
+ std::unique_ptr<media::VideoEncoder> result;
+ switch (codec) {
+ case media::kCodecVP8:
+ case media::kCodecVP9:
+ result = CreateVpxVideoEncoder();
+ self->UpdateEncoderLog("VpxVideoEncoder", false);
+ break;
+ case media::kCodecH264:
+ result = CreateOpenH264VideoEncoder();
+ self->UpdateEncoderLog("OpenH264VideoEncoder", false);
+ break;
+ default:
+ break;
+ }
+ if (!result)
+ return nullptr;
+ return std::make_unique<media::OffloadingVideoEncoder>(std::move(result));
+}
+
std::unique_ptr<media::VideoEncoder> VideoEncoder::CreateMediaVideoEncoder(
const ParsedConfig& config,
media::GpuVideoAcceleratorFactories* gpu_factories) {
switch (config.hw_pref) {
- case HardwarePreference::kRequire: {
+ case HardwarePreference::kPreferHardware: {
auto result = CreateAcceleratedVideoEncoder(
config.profile, config.options, gpu_factories);
if (result)
UpdateEncoderLog("AcceleratedVideoEncoder", true);
return result;
}
- case HardwarePreference::kAllow:
+ case HardwarePreference::kNoPreference:
if (auto result = CreateAcceleratedVideoEncoder(
config.profile, config.options, gpu_factories)) {
UpdateEncoderLog("AcceleratedVideoEncoder", true);
- return result;
+ return std::make_unique<media::VideoEncoderFallback>(
+ std::move(result),
+ ConvertToBaseOnceCallback(CrossThreadBindOnce(
+ &VideoEncoder::CreateSoftwareVideoEncoder,
+ WrapCrossThreadWeakPersistent(this), config.codec)));
}
FALLTHROUGH;
- case HardwarePreference::kDeny: {
- std::unique_ptr<media::VideoEncoder> result;
- switch (config.codec) {
- case media::kCodecVP8:
- case media::kCodecVP9:
- result = CreateVpxVideoEncoder();
- UpdateEncoderLog("VpxVideoEncoder", false);
- break;
- case media::kCodecH264:
- result = CreateOpenH264VideoEncoder();
- UpdateEncoderLog("OpenH264VideoEncoder", false);
- break;
- default:
- return nullptr;
- }
- if (!result)
- return nullptr;
- return std::make_unique<media::OffloadingVideoEncoder>(std::move(result));
- }
+ case HardwarePreference::kPreferSoftware:
+ return CreateSoftwareVideoEncoder(this, config.codec);
default:
NOTREACHED();
@@ -493,7 +562,6 @@ bool VideoEncoder::CanReconfigure(ParsedConfig& original_config,
return original_config.codec == new_config.codec &&
original_config.profile == new_config.profile &&
original_config.level == new_config.level &&
- original_config.color_space == new_config.color_space &&
original_config.hw_pref == new_config.hw_pref;
}
@@ -506,6 +574,9 @@ void VideoEncoder::ProcessEncode(Request* request) {
bool keyframe = request->encodeOpts->hasKeyFrameNonNull() &&
request->encodeOpts->keyFrameNonNull();
+ active_encodes_++;
+ if (active_encodes_ == kMaxActiveEncodes)
+ stall_request_processing_ = true;
request->StartTracingVideoEncode(keyframe);
@@ -516,6 +587,12 @@ void VideoEncoder::ProcessEncode(Request* request) {
return;
}
DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_);
+
+ if (self->active_encodes_ == kMaxActiveEncodes)
+ self->stall_request_processing_ = false;
+
+ self->active_encodes_--;
+
if (!status.is_ok()) {
self->HandleError(
self->logger_->MakeException("Encoding error.", status));
@@ -528,19 +605,73 @@ void VideoEncoder::ProcessEncode(Request* request) {
// Currently underlying encoders can't handle frame backed by textures,
// so let's readback pixel data to CPU memory.
+ // TODO(crbug.com/1229845): We shouldn't be reading back frames here.
if (frame->HasTextures() && !frame->HasGpuMemoryBuffer()) {
- scoped_refptr<viz::RasterContextProvider> raster_provider;
- auto wrapper = SharedGpuContext::ContextProviderWrapper();
- if (wrapper && wrapper->ContextProvider())
- raster_provider = wrapper->ContextProvider()->RasterContextProvider();
- if (raster_provider) {
- auto* ri = raster_provider->RasterInterface();
- auto* gr_context = raster_provider->GrContext();
-
- frame = ReadbackTextureBackedFrameToMemorySync(*frame, ri, gr_context,
- &readback_frame_pool_);
+ const bool can_use_gmb = CanUseGpuMemoryBufferReadback(frame->format());
+ if (can_use_gmb && !accelerated_frame_pool_) {
+ if (auto wrapper = SharedGpuContext::ContextProviderWrapper()) {
+ accelerated_frame_pool_ =
+ std::make_unique<WebGraphicsContext3DVideoFramePool>(wrapper);
+ }
+ }
+
+ if (can_use_gmb && accelerated_frame_pool_) {
+ // This will execute shortly after CopyRGBATextureToVideoFrame()
+ // completes. |stall_request_processing_| = true will ensure that
+ // HasPendingActivity() keeps the VideoEncoder alive long enough.
+ auto blit_done_callback = [](VideoEncoder* self, bool keyframe,
+ media::VideoEncoder::StatusCB done_callback,
+ scoped_refptr<media::VideoFrame> frame) {
+ --self->requested_encodes_;
+ self->stall_request_processing_ = false;
+ self->media_encoder_->Encode(std::move(frame), keyframe,
+ std::move(done_callback));
+ };
+
+ auto origin = frame->metadata().texture_origin_is_top_left
+ ? kTopLeft_GrSurfaceOrigin
+ : kBottomLeft_GrSurfaceOrigin;
+
+ // TODO(crbug.com/1224279): This assumes that all frames are 8-bit sRGB.
+ // Expose the color space and pixel format that is backing
+ // `image->GetMailboxHolder()`, or, alternatively, expose an accelerated
+ // SkImage.
+ auto format = frame->format() == media::PIXEL_FORMAT_XBGR
+ ? viz::ResourceFormat::RGBA_8888
+ : viz::ResourceFormat::BGRA_8888;
+
+ // Stall request processing while we wait for the copy to complete. It'd
+ // be nice to not have to do this, but currently the request processing
+ // loop must execute synchronously or flush() will miss frames. Also it
+ // ensures the VideoEncoder remains alive while the copy completes.
+ stall_request_processing_ = true;
+ if (accelerated_frame_pool_->CopyRGBATextureToVideoFrame(
+ format, frame->coded_size(), gfx::ColorSpace::CreateSRGB(),
+ origin, frame->mailbox_holder(0),
+ WTF::Bind(blit_done_callback, WrapWeakPersistent(this), keyframe,
+ ConvertToBaseOnceCallback(CrossThreadBindOnce(
+ done_callback, WrapCrossThreadWeakPersistent(this),
+ WrapCrossThreadPersistent(request)))))) {
+ request->input->close();
+ return;
+ }
+
+ // Error occurred, fall through to error handling below.
+ stall_request_processing_ = false;
} else {
- frame.reset();
+ auto wrapper = SharedGpuContext::ContextProviderWrapper();
+ scoped_refptr<viz::RasterContextProvider> raster_provider;
+ if (wrapper && wrapper->ContextProvider())
+ raster_provider = wrapper->ContextProvider()->RasterContextProvider();
+ if (raster_provider) {
+ auto* ri = raster_provider->RasterInterface();
+ auto* gr_context = raster_provider->GrContext();
+
+ frame = ReadbackTextureBackedFrameToMemorySync(*frame, ri, gr_context,
+ &readback_frame_pool_);
+ } else {
+ frame.reset();
+ }
}
if (!frame) {
@@ -584,7 +715,7 @@ void VideoEncoder::ProcessConfigure(Request* request) {
stall_request_processing_ = true;
- if (active_config_->hw_pref == HardwarePreference::kDeny) {
+ if (active_config_->hw_pref == HardwarePreference::kPreferSoftware) {
ContinueConfigureWithGpuFactories(request, nullptr);
return;
}
@@ -677,13 +808,13 @@ void VideoEncoder::CallOutputCallback(
return;
}
- auto deleter = [](void* data, size_t length, void*) {
- delete[] static_cast<uint8_t*>(data);
- };
- ArrayBufferContents data(output.data.release(), output.size, deleter);
- auto* dom_array = MakeGarbageCollected<DOMArrayBuffer>(std::move(data));
- auto* chunk = MakeGarbageCollected<EncodedVideoChunk>(
- output.timestamp, output.key_frame, dom_array);
+ MarkCodecActive();
+
+ auto buffer =
+ media::DecoderBuffer::FromArray(std::move(output.data), output.size);
+ buffer->set_timestamp(output.timestamp);
+ buffer->set_is_key_frame(output.key_frame);
+ auto* chunk = MakeGarbageCollected<EncodedVideoChunk>(std::move(buffer));
auto* metadata = EncodedVideoChunkMetadata::Create();
if (active_config->options.temporal_layers > 0)
@@ -696,28 +827,22 @@ void VideoEncoder::CallOutputCallback(
decoder_config->setCodedHeight(active_config->options.frame_size.height());
decoder_config->setCodedWidth(active_config->options.frame_size.width());
- auto* visible_region = VideoFrameRegion::Create();
- decoder_config->setVisibleRegion(visible_region);
- visible_region->setTop(0);
- visible_region->setLeft(0);
- visible_region->setHeight(active_config->options.frame_size.height());
- visible_region->setWidth(active_config->options.frame_size.width());
-
if (active_config->display_size.has_value()) {
- decoder_config->setDisplayHeight(
+ decoder_config->setDisplayAspectHeight(
active_config->display_size.value().height());
- decoder_config->setDisplayWidth(
+ decoder_config->setDisplayAspectWidth(
active_config->display_size.value().width());
- } else {
- decoder_config->setDisplayHeight(visible_region->height());
- decoder_config->setDisplayWidth(visible_region->width());
}
+ VideoColorSpace* color_space =
+ MakeGarbageCollected<VideoColorSpace>(active_config->color_space);
+ decoder_config->setColorSpace(color_space->toJSON());
+
if (codec_desc.has_value()) {
auto* desc_array_buf = DOMArrayBuffer::Create(codec_desc.value().data(),
codec_desc.value().size());
decoder_config->setDescription(
- ArrayBufferOrArrayBufferView::FromArrayBuffer(desc_array_buf));
+ MakeGarbageCollected<AllowSharedBufferSource>(desc_array_buf));
}
metadata->setDecoderConfig(decoder_config);
}
@@ -731,6 +856,11 @@ void VideoEncoder::CallOutputCallback(
TRACE_EVENT_END0(kCategory, GetTraceNames()->output.c_str());
}
+void VideoEncoder::ResetInternal() {
+ Base::ResetInternal();
+ active_encodes_ = 0;
+}
+
static void isConfigSupportedWithSoftwareOnly(
ScriptPromiseResolver* resolver,
VideoEncoderSupport* support,
@@ -788,16 +918,24 @@ static void isConfigSupportedWithHardwareOnly(
class FindAnySupported final : public NewScriptFunction::Callable {
public:
ScriptValue Call(ScriptState* state, ScriptValue value) override {
- NonThrowableExceptionState exception_state;
+ ExceptionContext context(
+ ExceptionContext::Context::kConstructorOperationInvoke,
+ "VideoEncoderSupport");
+ ExceptionState exception_state(state->GetIsolate(), context);
HeapVector<Member<VideoEncoderSupport>> supports =
NativeValueTraits<IDLSequence<VideoEncoderSupport>>::NativeValue(
state->GetIsolate(), value.V8Value(), exception_state);
VideoEncoderSupport* result = nullptr;
- for (auto& support : supports) {
- result = support;
- if (result->supported())
- break;
+ // We don't really expect exceptions here, but if isConfigSupported() is
+ // given a VideoEncoderConfig with uint64 values above max JS int (2^53 - 1)
+ // creation of |supports| vector will fail. This can happen during fuzzing.
+ if (!exception_state.HadException()) {
+ for (auto& support : supports) {
+ result = support;
+ if (result->supported())
+ break;
+ }
}
return ScriptValue::From(state, result);
}
@@ -826,7 +964,7 @@ ScriptPromise VideoEncoder::isConfigSupported(ScriptState* script_state,
// put them into |promises|. Simultaneously run both versions of
// isConfigSupported(), each version fulfills its own promise.
HeapVector<ScriptPromise> promises;
- if (parsed_config->hw_pref != HardwarePreference::kDeny) {
+ if (parsed_config->hw_pref != HardwarePreference::kPreferSoftware) {
// Hardware support not denied, detect support by hardware encoders.
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
promises.push_back(resolver->Promise());
@@ -840,7 +978,7 @@ ScriptPromise VideoEncoder::isConfigSupported(ScriptState* script_state,
std::move(gpu_retrieved_callback));
}
- if (parsed_config->hw_pref != HardwarePreference::kRequire) {
+ if (parsed_config->hw_pref != HardwarePreference::kPreferHardware) {
// Hardware support not required, detect support by software encoders.
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
promises.push_back(resolver->Promise());
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.h
index ff24414b158..a2579fb9f99 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.h
@@ -14,7 +14,6 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk_output_callback.h"
#include "third_party/blink/renderer/modules/webcodecs/encoder_base.h"
-#include "third_party/blink/renderer/modules/webcodecs/gpu_factories_retriever.h"
#include "third_party/blink/renderer/modules/webcodecs/hardware_preference.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
@@ -29,6 +28,7 @@ namespace blink {
class VideoEncoderConfig;
class VideoEncoderInit;
class VideoEncoderEncodeOptions;
+class WebGraphicsContext3DVideoFramePool;
class MODULES_EXPORT VideoEncoderTraits {
public:
@@ -88,9 +88,12 @@ class MODULES_EXPORT VideoEncoder final
void ProcessEncode(Request* request) override;
void ProcessConfigure(Request* request) override;
void ProcessReconfigure(Request* request) override;
+ void ResetInternal() override;
void UpdateEncoderLog(std::string encoder_name, bool is_hw_accelerated);
-
+ static std::unique_ptr<media::VideoEncoder> CreateSoftwareVideoEncoder(
+ VideoEncoder* self,
+ media::VideoCodec codec);
ParsedConfig* ParseConfig(const VideoEncoderConfig*,
ExceptionState&) override;
@@ -108,6 +111,11 @@ class MODULES_EXPORT VideoEncoder final
scoped_refptr<media::VideoFrame> txt_frame);
media::VideoFramePool readback_frame_pool_;
+ std::unique_ptr<WebGraphicsContext3DVideoFramePool> accelerated_frame_pool_;
+
+ // The number of encoding requests currently handled by |media_encoder_|
+ // Should not exceed |kMaxActiveEncodes|.
+ int active_encodes_ = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.idl
index 0e1f58042ea..b3905278457 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder.idl
@@ -6,6 +6,7 @@
[
Exposed=(Window,DedicatedWorker),
+ SecureContext,
RuntimeEnabled=WebCodecs,
ActiveScriptWrappable
] interface VideoEncoder {
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
index 80d801c7d82..7d5fb1f5b12 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
@@ -8,10 +8,11 @@
// video_encoder.cc.
dictionary VideoEncoderConfig {
required DOMString codec;
- HardwarePreference hardwareAcceleration = "allow";
+ HardwarePreference hardwareAcceleration = "no-preference";
AlphaOption alpha = "discard";
- unsigned long long bitrate;
+ [EnforceRange] unsigned long long bitrate;
+ BitrateMode bitrateMode = "variable";
double framerate;
@@ -26,4 +27,6 @@ dictionary VideoEncoderConfig {
// Same as in WebRTC SVC (https://w3c.github.io/webrtc-svc/)
DOMString scalabilityMode;
+
+ LatencyMode latencyMode = "quality";
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc
index 351e9b3d42c..5a1f8c30fd6 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc
@@ -91,12 +91,7 @@ VideoFrame* MakeVideoFrame(ScriptState* script_state,
VideoFrameInit* video_frame_init = VideoFrameInit::Create();
video_frame_init->setTimestamp(timestamp);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* source = MakeGarbageCollected<V8CanvasImageSource>(image_bitmap);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasImageSourceUnion source;
- source.SetImageBitmap(image_bitmap);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return VideoFrame::Create(script_state, source, video_frame_init,
IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.cc
index 7b38c9ccd38..ae8f18feca9 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -4,96 +4,73 @@
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
+#include <limits>
#include <utility>
#include "base/callback_helpers.h"
+#include "base/containers/span.h"
#include "base/memory/scoped_refptr.h"
#include "base/numerics/checked_math.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/limits.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_metadata.h"
#include "media/base/video_frame_pool.h"
+#include "media/base/video_types.h"
#include "media/base/video_util.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/core/v8/array_buffer_or_array_buffer_view.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_plane_init.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_cssimagevalue_htmlcanvaselement_htmlimageelement_htmlvideoelement_imagebitmap_offscreencanvas_svgimageelement_videoframe.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_buffer_init.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_copy_to_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h"
+#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h"
-#include "third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h"
-#include "third_party/blink/renderer/modules/webcodecs/plane_layout.h"
-#include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h"
+#include "third_party/blink/renderer/modules/webcodecs/dom_rect_util.h"
+#include "third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_color_space.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/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/libyuv/include/libyuv/planar_functions.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
+#include "v8/include/v8.h"
namespace blink {
namespace {
-struct YUVReadbackContext {
- gfx::Size coded_size;
- gfx::Rect visible_rect;
- gfx::Size natural_size;
- base::TimeDelta timestamp;
- scoped_refptr<media::VideoFrame> frame;
-};
-
-void OnYUVReadbackDone(
- void* raw_ctx,
- std::unique_ptr<const SkImage::AsyncReadResult> async_result) {
- if (!async_result)
- return;
- auto* context = reinterpret_cast<YUVReadbackContext*>(raw_ctx);
- context->frame = media::VideoFrame::WrapExternalYuvData(
- media::PIXEL_FORMAT_I420, context->coded_size, context->visible_rect,
- context->natural_size, static_cast<int>(async_result->rowBytes(0)),
- static_cast<int>(async_result->rowBytes(1)),
- static_cast<int>(async_result->rowBytes(2)),
- // TODO(crbug.com/1161304): We should be able to wrap readonly memory in
- // a VideoFrame without resorting to a const_cast.
- reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(0))),
- reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(1))),
- reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(2))),
- context->timestamp);
- if (!context->frame)
- return;
- context->frame->AddDestructionObserver(
- ConvertToBaseOnceCallback(WTF::CrossThreadBindOnce(
- base::DoNothing::Once<
- std::unique_ptr<const SkImage::AsyncReadResult>>(),
- std::move(async_result))));
-}
-
media::VideoPixelFormat ToMediaPixelFormat(V8VideoPixelFormat::Enum fmt) {
switch (fmt) {
case V8VideoPixelFormat::Enum::kI420:
return media::PIXEL_FORMAT_I420;
+ case V8VideoPixelFormat::Enum::kI420A:
+ return media::PIXEL_FORMAT_I420A;
case V8VideoPixelFormat::Enum::kI422:
return media::PIXEL_FORMAT_I422;
case V8VideoPixelFormat::Enum::kI444:
return media::PIXEL_FORMAT_I444;
case V8VideoPixelFormat::Enum::kNV12:
return media::PIXEL_FORMAT_NV12;
- case V8VideoPixelFormat::Enum::kABGR:
+ case V8VideoPixelFormat::Enum::kRGBA:
return media::PIXEL_FORMAT_ABGR;
- case V8VideoPixelFormat::Enum::kXBGR:
+ case V8VideoPixelFormat::Enum::kRGBX:
return media::PIXEL_FORMAT_XBGR;
- case V8VideoPixelFormat::Enum::kARGB:
+ case V8VideoPixelFormat::Enum::kBGRA:
return media::PIXEL_FORMAT_ARGB;
- case V8VideoPixelFormat::Enum::kXRGB:
+ case V8VideoPixelFormat::Enum::kBGRX:
return media::PIXEL_FORMAT_XRGB;
}
}
@@ -220,26 +197,42 @@ bool IsSupportedPlanarFormat(const media::VideoFrame& frame) {
} // namespace
VideoFrame::VideoFrame(scoped_refptr<media::VideoFrame> frame,
- ExecutionContext* context) {
+ ExecutionContext* context,
+ std::string monitoring_source_id) {
DCHECK(frame);
- handle_ = base::MakeRefCounted<VideoFrameHandle>(std::move(frame), context);
+ handle_ = base::MakeRefCounted<VideoFrameHandle>(
+ frame, context, std::move(monitoring_source_id));
+
+ external_allocated_memory_ =
+ media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ external_allocated_memory_);
}
VideoFrame::VideoFrame(scoped_refptr<VideoFrameHandle> handle)
: handle_(std::move(handle)) {
DCHECK(handle_);
- // Note: The provided |handle| may be invalid if close() has been called while
- // a frame is in transit to another thread.
+ // The provided |handle| may be invalid if close() was called while
+ // it was being sent to another thread.
+ auto local_frame = handle_->frame();
+ if (!local_frame)
+ return;
+
+ external_allocated_memory_ = media::VideoFrame::AllocationSize(
+ local_frame->format(), local_frame->coded_size());
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ external_allocated_memory_);
+}
+
+VideoFrame::~VideoFrame() {
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ -external_allocated_memory_);
}
// static
VideoFrame* VideoFrame::Create(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8CanvasImageSource* source,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const CanvasImageSourceUnion& source,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const VideoFrameInit* init,
ExceptionState& exception_state) {
auto* image_source = ToCanvasImageSource(source, exception_state);
@@ -258,22 +251,16 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
constexpr char kAlphaKeep[] = "keep";
// Special case <video> and VideoFrame to directly use the underlying frame.
- if (
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- source->IsVideoFrame() || source->IsHTMLVideoElement()
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- source.IsVideoFrame() || source.IsHTMLVideoElement()
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ) {
+ if (source->IsVideoFrame() || source->IsHTMLVideoElement()) {
scoped_refptr<media::VideoFrame> source_frame;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
switch (source->GetContentType()) {
case V8CanvasImageSource::ContentType::kVideoFrame:
- if (!init || (!init->hasTimestamp() && !init->hasDuration() &&
- init->alpha() == kAlphaKeep)) {
+ source_frame = source->GetAsVideoFrame()->frame();
+ if (!init->hasTimestamp() && !init->hasDuration() &&
+ (init->alpha() == kAlphaKeep ||
+ media::IsOpaque(source_frame->format()))) {
return source->GetAsVideoFrame()->clone(exception_state);
}
- source_frame = source->GetAsVideoFrame()->frame();
break;
case V8CanvasImageSource::ContentType::kHTMLVideoElement:
if (auto* wmp = source->GetAsHTMLVideoElement()->GetWebMediaPlayer())
@@ -282,18 +269,6 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
default:
NOTREACHED();
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (source.IsVideoFrame()) {
- if (!init || (!init->hasTimestamp() && !init->hasDuration() &&
- init->alpha() == kAlphaKeep)) {
- return source.GetAsVideoFrame()->clone(exception_state);
- }
- source_frame = source.GetAsVideoFrame()->frame();
- } else if (source.IsHTMLVideoElement()) {
- if (auto* wmp = source.GetAsHTMLVideoElement()->GetWebMediaPlayer())
- source_frame = wmp->GetCurrentFrame();
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (!source_frame) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
@@ -301,12 +276,12 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
return nullptr;
}
- const bool force_opaque = init && init->alpha() == kAlphaDiscard &&
+ const bool force_opaque = init->alpha() == kAlphaDiscard &&
!media::IsOpaque(source_frame->format());
// We can't modify the timestamp or duration directly since there may be
// other owners accessing these fields concurrently.
- if (init && (init->hasTimestamp() || init->hasDuration() || force_opaque)) {
+ if (init->hasTimestamp() || init->hasDuration() || force_opaque) {
const auto wrapped_format =
force_opaque ? ToOpaqueMediaPixelFormat(source_frame->format())
: source_frame->format();
@@ -345,30 +320,13 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
const auto timestamp = base::TimeDelta::FromMicroseconds(
(init && init->hasTimestamp()) ? init->timestamp() : 0);
- // Note: The current PaintImage may be lazy generated, for simplicity, we just
- // ask Skia to rasterize the image for us.
- //
- // A potential optimization could use PaintImage::DecodeYuv() to decode
- // directly into a media::VideoFrame. This would improve VideoFrame from <img>
- // creation, but probably such users should be using ImageDecoder directly.
- //
- // TODO(crbug.com/1031051): PaintImage::GetSkImage() is being deprecated as we
- // move to OOPR canvas2D. In OOPR mode it will return null so we fall back to
- // GetSwSkImage(). This area should be updated once VideoFrame can wrap
- // mailboxes.
- auto sk_image = image->PaintImageForCurrentFrame().GetSkImage();
- if (!sk_image)
- sk_image = image->PaintImageForCurrentFrame().GetSwSkImage();
- if (sk_image->isLazyGenerated())
- sk_image = sk_image->makeRasterImage();
-
- const auto sk_image_info = sk_image->imageInfo();
-
+ const auto paint_image = image->PaintImageForCurrentFrame();
+ const auto sk_image_info = paint_image.GetSkImageInfo();
auto sk_color_space = sk_image_info.refColorSpace();
if (!sk_color_space)
sk_color_space = SkColorSpace::MakeSRGB();
- const auto gfx_color_space = gfx::ColorSpace(*sk_color_space);
+ auto gfx_color_space = gfx::ColorSpace(*sk_color_space);
if (!gfx_color_space.IsValid()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Invalid color space");
@@ -378,70 +336,83 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
const gfx::Size coded_size(sk_image_info.width(), sk_image_info.height());
const gfx::Rect visible_rect(coded_size);
const gfx::Size natural_size = coded_size;
+ const auto orientation = image->CurrentFrameOrientation().Orientation();
+ sk_sp<SkImage> sk_image;
scoped_refptr<media::VideoFrame> frame;
- if (sk_image->isTextureBacked()) {
- YUVReadbackContext result;
- result.coded_size = coded_size;
- result.visible_rect = visible_rect;
- result.natural_size = natural_size;
- result.timestamp = timestamp;
-
- // TODO(crbug.com/1138681): This is currently wrong for alpha == keep, but
- // we're removing readback for this flow, so it's fine for now.
-
- // While this function indicates it's asynchronous, the flushAndSubmit()
- // call below ensures it completes synchronously.
- sk_image->asyncRescaleAndReadPixelsYUV420(
- kRec709_SkYUVColorSpace, sk_color_space, sk_image_info.bounds(),
- sk_image_info.dimensions(), SkImage::RescaleGamma::kSrc,
- SkImage::RescaleMode::kRepeatedCubic, &OnYUVReadbackDone, &result);
- GrDirectContext* gr_context = image->ContextProvider()->GetGrContext();
- DCHECK(gr_context);
- gr_context->flushAndSubmit(/*syncCpu=*/true);
-
- if (!result.frame) {
- exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
- "YUV conversion error during readback");
- return nullptr;
- }
+ if (image->IsTextureBacked() && SharedGpuContext::IsGpuCompositingEnabled()) {
+ DCHECK(image->IsStaticBitmapImage());
+ auto format = media::VideoPixelFormatFromSkColorType(
+ paint_image.GetColorType(),
+ image->CurrentFrameKnownToBeOpaque() || init->alpha() == kAlphaDiscard);
+
+ auto* sbi = static_cast<StaticBitmapImage*>(image.get());
+ gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes] = {
+ sbi->GetMailboxHolder()};
+ const bool is_origin_top_left = sbi->IsOriginTopLeft();
+
+ // The sync token needs to be updated when |frame| is released, but
+ // AcceleratedStaticBitmapImage::UpdateSyncToken() is not thread-safe.
+ auto release_cb = media::BindToCurrentLoop(WTF::Bind(
+ [](scoped_refptr<Image> image, const gpu::SyncToken& sync_token) {
+ static_cast<StaticBitmapImage*>(image.get())
+ ->UpdateSyncToken(sync_token);
+ },
+ std::move(image)));
+
+ frame = media::VideoFrame::WrapNativeTextures(
+ format, mailbox_holders, std::move(release_cb), coded_size,
+ visible_rect, natural_size, timestamp);
+
+ if (frame)
+ frame->metadata().texture_origin_is_top_left = is_origin_top_left;
+
+ // Note: We could add the StaticBitmapImage to the VideoFrameHandle so we
+ // can round trip through VideoFrame back to canvas w/o any copies, but
+ // this doesn't seem like a common use case.
+ } else {
+ // Note: The current PaintImage may be lazy generated, for simplicity, we
+ // just ask Skia to rasterize the image for us.
+ //
+ // A potential optimization could use PaintImage::DecodeYuv() to decode
+ // directly into a media::VideoFrame. This would improve VideoFrame from
+ // <img> creation, but probably such users should be using ImageDecoder
+ // directly.
+ sk_image = paint_image.GetSwSkImage();
+ if (sk_image->isLazyGenerated())
+ sk_image = sk_image->makeRasterImage();
- frame = std::move(result.frame);
- frame->set_color_space(gfx::ColorSpace::CreateREC709());
- if (init && init->hasDuration()) {
- frame->metadata().frame_duration =
- base::TimeDelta::FromMicroseconds(init->duration());
- }
- return MakeGarbageCollected<VideoFrame>(
- std::move(frame), ExecutionContext::From(script_state));
- }
+ const bool force_opaque =
+ init && init->alpha() == kAlphaDiscard && !sk_image->isOpaque();
- const bool force_opaque =
- init && init->alpha() == kAlphaDiscard && !sk_image->isOpaque();
+ frame = media::CreateFromSkImage(sk_image, visible_rect, natural_size,
+ timestamp, force_opaque);
+ }
- frame = media::CreateFromSkImage(sk_image, visible_rect, natural_size,
- timestamp, force_opaque);
if (!frame) {
exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
"Failed to create video frame");
return nullptr;
}
+
frame->set_color_space(gfx_color_space);
- if (init && init->hasDuration()) {
+ if (init->hasDuration()) {
frame->metadata().frame_duration =
base::TimeDelta::FromMicroseconds(init->duration());
}
+ if (orientation != ImageOrientationEnum::kDefault) {
+ frame->metadata().transformation =
+ ImageOrientationToVideoTransformation(orientation);
+ }
return MakeGarbageCollected<VideoFrame>(
base::MakeRefCounted<VideoFrameHandle>(
std::move(frame), std::move(sk_image),
ExecutionContext::From(script_state)));
}
-// TODO(crbug.com/1198324): Merge shared logic with VideoDecoderConfig.
-// static
VideoFrame* VideoFrame::Create(ScriptState* script_state,
- const HeapVector<Member<PlaneInit>>& planes,
- const VideoFramePlaneInit* init,
+ const AllowSharedBufferSource* data,
+ const VideoFrameBufferInit* init,
ExceptionState& exception_state) {
ExecutionContext* execution_context = ExecutionContext::From(script_state);
@@ -449,180 +420,98 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
auto typed_fmt = V8VideoPixelFormat::Create(init->format());
auto media_fmt = ToMediaPixelFormat(typed_fmt->AsEnum());
- // There's no I420A pixel format, so treat I420 + 4 planes as I420A.
- if (media_fmt == media::PIXEL_FORMAT_I420 && planes.size() == 4)
- media_fmt = media::PIXEL_FORMAT_I420A;
-
// Validate coded size.
uint32_t coded_width = init->codedWidth();
uint32_t coded_height = init->codedHeight();
- if (coded_width == 0 || coded_width > media::limits::kMaxDimension ||
- coded_height == 0 || coded_height > media::limits::kMaxDimension ||
- coded_width * coded_height > media::limits::kMaxCanvas) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid coded size (%u, %u).", coded_width,
- coded_height));
+ if (coded_width == 0) {
+ exception_state.ThrowTypeError("codedWidth must be nonzero.");
return nullptr;
}
-
- const gfx::Size coded_size(coded_width, coded_height);
-
- // Validate visible rect.
- uint32_t visible_left = 0;
- uint32_t visible_top = 0;
- uint32_t visible_width = coded_width;
- uint32_t visible_height = coded_height;
- if (init->hasVisibleRegion()) {
- visible_left = init->visibleRegion()->left();
- visible_top = init->visibleRegion()->top();
- visible_width = init->visibleRegion()->width();
- visible_height = init->visibleRegion()->height();
- } else {
- if (init->hasCropLeft()) {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
- visible_left = init->cropLeft();
- if (visible_left >= coded_width) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid cropLeft %u for codedWidth %u.",
- visible_left, coded_width));
- return nullptr;
- }
- visible_width = coded_width - visible_left;
- }
- if (init->hasCropTop()) {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
- visible_top = init->cropTop();
- if (visible_top >= coded_height) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid cropTop %u for codedHeight %u.",
- visible_top, coded_height));
- return nullptr;
- }
- visible_height = coded_height - visible_top;
- }
- if (init->hasCropWidth()) {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
- visible_width = init->cropWidth();
- }
- if (init->hasCropHeight()) {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
- visible_height = init->cropHeight();
- }
+ if (coded_height == 0) {
+ exception_state.ThrowTypeError("codedHeight must be nonzero.");
+ return nullptr;
}
- if (visible_left >= coded_width || visible_top >= coded_height ||
- visible_width == 0 || visible_width > media::limits::kMaxDimension ||
- visible_height == 0 || visible_height > media::limits::kMaxDimension ||
- visible_left + visible_width > coded_width ||
- visible_top + visible_height > coded_height) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid visible region {left: %u, top: %u, width: %u, "
- "height: %u} for coded size (%u, %u).",
- visible_left, visible_top, visible_width, visible_height,
+ if (coded_width > media::limits::kMaxDimension ||
+ coded_height > media::limits::kMaxDimension ||
+ coded_width * coded_height > media::limits::kMaxCanvas) {
+ exception_state.ThrowTypeError(
+ String::Format("Coded size %u x %u exceeds implementation limit.",
coded_width, coded_height));
return nullptr;
}
+ const gfx::Size coded_size(static_cast<int>(coded_width),
+ static_cast<int>(coded_height));
+
+ // Validate visibleRect and layout.
+ VideoFrameCopyToOptions* adapted_init =
+ MakeGarbageCollected<VideoFrameCopyToOptions>();
+ if (init->hasVisibleRect())
+ adapted_init->setRect(init->visibleRect());
+ if (init->hasLayout())
+ adapted_init->setLayout(init->layout());
+
+ ParsedCopyToOptions copy_options(adapted_init, media_fmt, coded_size,
+ gfx::Rect(coded_size), exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ const gfx::Rect visible_rect = copy_options.rect;
- const gfx::Rect visible_rect(visible_left, visible_top, visible_width,
- visible_height);
+ // Validate data.
+ auto buffer = AsSpan<const uint8_t>(data);
+ if (!buffer.data()) {
+ exception_state.ThrowTypeError("data is detached.");
+ return nullptr;
+ }
+ if (buffer.size() < copy_options.min_buffer_size) {
+ exception_state.ThrowTypeError("data is not large enough.");
+ return nullptr;
+ }
// Validate natural size.
- uint32_t natural_width = visible_width;
- uint32_t natural_height = visible_height;
+ uint32_t natural_width = static_cast<uint32_t>(visible_rect.width());
+ uint32_t natural_height = static_cast<uint32_t>(visible_rect.height());
if (init->hasDisplayWidth() || init->hasDisplayHeight()) {
if (!init->hasDisplayWidth()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid display size, displayHeight specified "
- "without displayWidth."));
+ exception_state.ThrowTypeError(
+ "displayHeight specified without displayWidth.");
return nullptr;
}
if (!init->hasDisplayHeight()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid display size, displayWidth specified "
- "without displayHeight."));
+ exception_state.ThrowTypeError(
+ "displayWidth specified without displayHeight.");
return nullptr;
}
natural_width = init->displayWidth();
natural_height = init->displayHeight();
- if (natural_width == 0 || natural_width > media::limits::kMaxDimension ||
- natural_height == 0 || natural_height > media::limits::kMaxDimension) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid display size (%u, %u).", natural_width,
- natural_height));
+ if (natural_width == 0) {
+ exception_state.ThrowTypeError("displayWidth must be nonzero.");
return nullptr;
}
- }
-
- const gfx::Size natural_size(natural_width, natural_height);
-
- // Validate planes.
- if (media::VideoFrame::NumPlanes(media_fmt) != planes.size()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format("Invalid number of planes for format %s; expected %zu, "
- "received %u.",
- init->format().Ascii().c_str(),
- media::VideoFrame::NumPlanes(media_fmt), planes.size()));
- return nullptr;
- }
-
- for (wtf_size_t i = 0; i < planes.size(); ++i) {
- if (!planes[i]->hasData()) {
- if (planes[i]->hasSrc()) {
- WebCodecsLogger::From(*execution_context).LogPlaneInitSrcDeprecation();
- } else {
- // TODO(sandersd): Make |data| an actual required member.
- exception_state.ThrowTypeError(String::Format(
- "Required member 'data' is missing for plane %u.", i));
- return nullptr;
- }
- }
- }
-
- for (wtf_size_t i = 0; i < planes.size(); ++i) {
- DOMArrayPiece buffer(planes[i]->hasData() ? planes[i]->data()
- : planes[i]->src());
-
- size_t offset = 0;
- if (planes[i]->hasOffset())
- offset = planes[i]->offset();
-
- const size_t stride = planes[i]->stride();
-
- const gfx::Size plane_size =
- media::VideoFrame::PlaneSize(media_fmt, i, coded_size);
- const size_t minimum_stride = plane_size.width();
- const size_t rows = plane_size.height();
- if (stride < minimum_stride) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format(
- "The stride of plane %u is too small for the given coded size "
- "(%u, %u); expected at least %zu, received %zu",
- i, coded_width, coded_height, minimum_stride, stride));
+ if (natural_height == 0) {
+ exception_state.ThrowTypeError("displayHeight must be nonzero.");
return nullptr;
}
-
- // Note: This check requires the full stride to be provided for every row,
- // including the last.
- const auto end = base::CheckedNumeric<size_t>(stride) * rows + offset;
- if (!end.IsValid() || end.ValueOrDie() > buffer.ByteLength()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format(
- "Plane %u with %zu rows of stride %zu bytes does not fit at "
- "offset %zu in src buffer with length %zu.",
- i, rows, stride, offset, buffer.ByteLength()));
+ // There is no limit on display size in //media; 2 * kMaxDimension is
+ // arbitrary. A big difference is that //media computes display size such
+ // that at least one dimension is the same as the visible size (and the
+ // other is not smaller than the visible size), while WebCodecs apps can
+ // specify any combination.
+ //
+ // Note that at large display sizes, it can become impossible to allocate
+ // a texture large enough to render into. It may be impossible, for example,
+ // to create an ImageBitmap without also scaling down.
+ if (natural_width > 2 * media::limits::kMaxDimension ||
+ natural_height > 2 * media::limits::kMaxDimension) {
+ exception_state.ThrowTypeError(
+ String::Format("Invalid display size (%u, %u); exceeds "
+ "implementation limit.",
+ natural_width, natural_height));
return nullptr;
}
}
+ const gfx::Size natural_size(static_cast<int>(natural_width),
+ static_cast<int>(natural_height));
// Create a frame.
const auto timestamp = base::TimeDelta::FromMicroseconds(init->timestamp());
@@ -631,57 +520,56 @@ VideoFrame* VideoFrame::Create(ScriptState* script_state,
natural_size, timestamp);
if (!frame) {
exception_state.ThrowDOMException(
- DOMExceptionCode::kConstraintError,
- String::Format(
- "Failed to create a video frame with configuration {format: %s, "
- "coded_size: %s, visible_rect: %s, display_size: %s}",
- VideoPixelFormatToString(media_fmt).c_str(),
- coded_size.ToString().c_str(), visible_rect.ToString().c_str(),
- natural_size.ToString().c_str()));
+ DOMExceptionCode::kOperationError,
+ String::Format("Failed to create a VideoFrame with format: %s, "
+ "coded size: %s, visibleRect: %s, display size: %s.",
+ VideoPixelFormatToString(media_fmt).c_str(),
+ coded_size.ToString().c_str(),
+ visible_rect.ToString().c_str(),
+ natural_size.ToString().c_str()));
return nullptr;
}
+ if (init->hasColorSpace()) {
+ VideoColorSpace* video_color_space =
+ MakeGarbageCollected<VideoColorSpace>(init->colorSpace());
+ frame->set_color_space(video_color_space->ToGfxColorSpace());
+ } else {
+ // So far all WebCodecs YUV formats are planar, so this test works. That
+ // might not be the case in the future.
+ frame->set_color_space(media::IsYuvPlanar(media_fmt)
+ ? gfx::ColorSpace::CreateREC709()
+ : gfx::ColorSpace::CreateSRGB());
+ }
+
if (init->hasDuration()) {
frame->metadata().frame_duration =
base::TimeDelta::FromMicroseconds(init->duration());
}
- // Copy data.
- for (wtf_size_t i = 0; i < planes.size(); ++i) {
- DOMArrayPiece buffer(planes[i]->hasData() ? planes[i]->data()
- : planes[i]->src());
- size_t offset = 0;
- if (planes[i]->hasOffset())
- offset = planes[i]->offset();
- const size_t stride = planes[i]->stride();
-
- const gfx::Size plane_size =
- media::VideoFrame::PlaneSize(media_fmt, i, coded_size);
- const size_t minimum_stride = plane_size.width();
- const size_t rows = plane_size.height();
-
- uint8_t* src_ptr = reinterpret_cast<uint8_t*>(buffer.Data()) + offset;
- uint8_t* dst_ptr = frame->data(i);
- for (size_t row = 0; row < rows; ++row) {
- memcpy(dst_ptr, src_ptr, minimum_stride);
- src_ptr += stride;
- dst_ptr += frame->stride(i);
- }
+ // Copy planes.
+ for (wtf_size_t i = 0; i < copy_options.num_planes; ++i) {
+ libyuv::CopyPlane(buffer.data() + copy_options.planes[i].offset,
+ static_cast<int>(copy_options.planes[i].stride),
+ frame->data(i), static_cast<int>(frame->stride(i)),
+ static_cast<int>(copy_options.planes[i].width_bytes),
+ static_cast<int>(copy_options.planes[i].height));
}
return MakeGarbageCollected<VideoFrame>(std::move(frame),
ExecutionContext::From(script_state));
}
-String VideoFrame::format() const {
+absl::optional<V8VideoPixelFormat> VideoFrame::format() const {
auto local_frame = handle_->frame();
if (!local_frame || !IsSupportedPlanarFormat(*local_frame))
- return String();
+ return absl::nullopt;
switch (local_frame->format()) {
case media::PIXEL_FORMAT_I420:
- case media::PIXEL_FORMAT_I420A:
return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kI420);
+ case media::PIXEL_FORMAT_I420A:
+ return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kI420A);
case media::PIXEL_FORMAT_I422:
return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kI422);
case media::PIXEL_FORMAT_I444:
@@ -689,37 +577,19 @@ String VideoFrame::format() const {
case media::PIXEL_FORMAT_NV12:
return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kNV12);
case media::PIXEL_FORMAT_ABGR:
- return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kABGR);
+ return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kRGBA);
case media::PIXEL_FORMAT_XBGR:
- return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kXBGR);
+ return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kRGBX);
case media::PIXEL_FORMAT_ARGB:
- return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kARGB);
+ return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kBGRA);
case media::PIXEL_FORMAT_XRGB:
- return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kXRGB);
+ return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kBGRX);
default:
NOTREACHED();
- return String();
+ return absl::nullopt;
}
}
-absl::optional<HeapVector<Member<Plane>>> VideoFrame::planes() {
- // Verify that |this| has not been invalidated, and that the format is
- // supported.
- auto local_frame = handle_->frame();
- if (!local_frame || !IsSupportedPlanarFormat(*local_frame))
- return absl::nullopt;
-
- // Create a Plane for each VideoFrame plane, but only the first time.
- if (planes_.IsEmpty()) {
- for (size_t i = 0; i < local_frame->layout().num_planes(); i++) {
- // Note: |handle_| may have been invalidated since |local_frame| was read.
- planes_.push_back(MakeGarbageCollected<Plane>(handle_, i));
- }
- }
-
- return planes_;
-}
-
uint32_t VideoFrame::codedWidth() const {
auto local_frame = handle_->frame();
if (!local_frame)
@@ -734,68 +604,31 @@ uint32_t VideoFrame::codedHeight() const {
return local_frame->coded_size().height();
}
-VideoFrameRegion* VideoFrame::codedRegion() const {
- auto local_frame = handle_->frame();
- auto* region = MakeGarbageCollected<VideoFrameRegion>();
- region->setLeft(0);
- region->setTop(0);
- if (local_frame) {
- region->setWidth(local_frame->coded_size().width());
- region->setHeight(local_frame->coded_size().height());
- } else {
- region->setWidth(0);
- region->setHeight(0);
- }
- return region;
-}
-
-VideoFrameRegion* VideoFrame::visibleRegion() const {
- auto local_frame = handle_->frame();
- auto* region = MakeGarbageCollected<VideoFrameRegion>();
- if (local_frame) {
- region->setLeft(local_frame->visible_rect().x());
- region->setTop(local_frame->visible_rect().y());
- region->setWidth(local_frame->visible_rect().width());
- region->setHeight(local_frame->visible_rect().height());
- } else {
- region->setLeft(0);
- region->setTop(0);
- region->setWidth(0);
- region->setHeight(0);
- }
- return region;
-}
-
-uint32_t VideoFrame::cropLeft(ExecutionContext* execution_context) const {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
+absl::optional<DOMRectReadOnly*> VideoFrame::codedRect() {
auto local_frame = handle_->frame();
if (!local_frame)
- return 0;
- return local_frame->visible_rect().x();
-}
+ return absl::nullopt;
-uint32_t VideoFrame::cropTop(ExecutionContext* execution_context) const {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
- auto local_frame = handle_->frame();
- if (!local_frame)
- return 0;
- return local_frame->visible_rect().y();
+ if (!coded_rect_) {
+ coded_rect_ = MakeGarbageCollected<DOMRectReadOnly>(
+ 0, 0, local_frame->coded_size().width(),
+ local_frame->coded_size().height());
+ }
+ return coded_rect_;
}
-uint32_t VideoFrame::cropWidth(ExecutionContext* execution_context) const {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
+absl::optional<DOMRectReadOnly*> VideoFrame::visibleRect() {
auto local_frame = handle_->frame();
if (!local_frame)
- return 0;
- return local_frame->visible_rect().width();
-}
+ return absl::nullopt;
-uint32_t VideoFrame::cropHeight(ExecutionContext* execution_context) const {
- WebCodecsLogger::From(*execution_context).LogCropDeprecation();
- auto local_frame = handle_->frame();
- if (!local_frame)
- return 0;
- return local_frame->visible_rect().height();
+ if (!visible_rect_) {
+ visible_rect_ = MakeGarbageCollected<DOMRectReadOnly>(
+ local_frame->visible_rect().x(), local_frame->visible_rect().y(),
+ local_frame->visible_rect().width(),
+ local_frame->visible_rect().height());
+ }
+ return visible_rect_;
}
uint32_t VideoFrame::displayWidth() const {
@@ -842,11 +675,30 @@ absl::optional<uint64_t> VideoFrame::duration() const {
return local_frame->metadata().frame_duration->InMicroseconds();
}
-uint32_t VideoFrame::allocationSize(VideoFrameReadIntoOptions* options,
+VideoColorSpace* VideoFrame::colorSpace() {
+ auto local_frame = handle_->frame();
+ if (!local_frame) {
+ if (!empty_color_space_)
+ empty_color_space_ = MakeGarbageCollected<VideoColorSpace>();
+
+ return empty_color_space_;
+ }
+
+ if (!color_space_) {
+ color_space_ =
+ MakeGarbageCollected<VideoColorSpace>(local_frame->ColorSpace());
+ }
+ return color_space_;
+}
+
+uint32_t VideoFrame::allocationSize(VideoFrameCopyToOptions* options,
ExceptionState& exception_state) {
auto local_frame = handle_->frame();
- if (!local_frame)
+ if (!local_frame) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "VideoFrame is closed.");
return 0;
+ }
// TODO(crbug.com/1176464): Determine the format readback will occur in, use
// that to compute the layout.
@@ -857,28 +709,23 @@ uint32_t VideoFrame::allocationSize(VideoFrameReadIntoOptions* options,
return 0;
}
- ParsedReadIntoOptions layout(options, local_frame->format(),
- local_frame->coded_size(),
- local_frame->visible_rect(), exception_state);
+ ParsedCopyToOptions layout(options, local_frame->format(),
+ local_frame->coded_size(),
+ local_frame->visible_rect(), exception_state);
if (exception_state.HadException())
return 0;
return layout.min_buffer_size;
}
-ScriptPromise VideoFrame::readInto(ScriptState* script_state,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8BufferSource* destination,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const ArrayBufferOrArrayBufferView&
- destination,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- VideoFrameReadIntoOptions* options,
- ExceptionState& exception_state) {
+ScriptPromise VideoFrame::copyTo(ScriptState* script_state,
+ const AllowSharedBufferSource* destination,
+ VideoFrameCopyToOptions* options,
+ ExceptionState& exception_state) {
auto local_frame = handle_->frame();
if (!local_frame) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "Cannot read closed VideoFrame.");
+ "Cannot copy closed VideoFrame.");
return ScriptPromise();
}
@@ -886,22 +733,25 @@ ScriptPromise VideoFrame::readInto(ScriptState* script_state,
if (!IsSupportedPlanarFormat(*local_frame)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kNotSupportedError,
- "readInto() is not yet implemented when format is null.");
+ "copyTo() is not yet implemented when format is null.");
return ScriptPromise();
}
// Compute layout.
- ParsedReadIntoOptions layout(options, local_frame->format(),
- local_frame->coded_size(),
- local_frame->visible_rect(), exception_state);
+ ParsedCopyToOptions layout(options, local_frame->format(),
+ local_frame->coded_size(),
+ local_frame->visible_rect(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
// Validate destination buffer.
- DOMArrayPiece buffer(destination);
- if (buffer.ByteLength() < static_cast<size_t>(layout.min_buffer_size)) {
- exception_state.ThrowDOMException(DOMExceptionCode::kConstraintError,
- "destination is not large enough.");
+ auto buffer = AsSpan<uint8_t>(destination);
+ if (!buffer.data()) {
+ exception_state.ThrowTypeError("destination is detached.");
+ return ScriptPromise();
+ }
+ if (buffer.size() < layout.min_buffer_size) {
+ exception_state.ThrowTypeError("destination is not large enough.");
return ScriptPromise();
}
@@ -918,25 +768,14 @@ ScriptPromise VideoFrame::readInto(ScriptState* script_state,
// Copy data.
for (wtf_size_t i = 0; i < layout.num_planes; i++) {
- size_t src_stride = local_frame->stride(i);
- size_t dest_stride = layout.planes[i].stride;
- size_t row_bytes = layout.planes[i].width_bytes;
-
- uint8_t* src = local_frame->data(i) + layout.planes[i].top * src_stride +
+ uint8_t* src = local_frame->data(i) +
+ layout.planes[i].top * local_frame->stride(i) +
layout.planes[i].left_bytes;
- uint8_t* dest = buffer.Bytes() + layout.planes[i].offset;
-
- // TODO(crbug.com/1205176): Use libyuv::CopyPlane(). The requirements to use
- // it are a bit strange though, it computes with ints and expects
- // intermediate values (like stride * height) to fit.
- for (size_t row = 0; row < layout.planes[i].height; row++) {
- // TODO(crbug.com/1205175): Spec what happens to the gaps between
- // |row_bytes| and |dest_stride|. Probably needs to be compatible with
- // whatever libyuv does.
- memcpy(dest, src, row_bytes);
- src += src_stride;
- dest += dest_stride;
- }
+ libyuv::CopyPlane(src, static_cast<int>(local_frame->stride(i)),
+ buffer.data() + layout.planes[i].offset,
+ static_cast<int>(layout.planes[i].stride),
+ static_cast<int>(layout.planes[i].width_bytes),
+ static_cast<int>(layout.planes[i].height));
}
// Convert and return |layout|.
@@ -967,7 +806,11 @@ VideoFrame* VideoFrame::clone(ExceptionState& exception_state) {
scoped_refptr<Image> VideoFrame::GetSourceImageForCanvas(
SourceImageStatus* status,
- const FloatSize&) {
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition) {
+ // UnpremultiplyAlpha is not implemented yet.
+ DCHECK_EQ(alpha_disposition, kPremultiplyAlpha);
+
const auto local_handle = handle_->CloneForInternalUse();
if (!local_handle) {
DLOG(ERROR) << "GetSourceImageForCanvas() called for closed frame.";
@@ -1013,7 +856,8 @@ FloatSize VideoFrame::ElementSize(
const auto orientation_enum = VideoTransformationToImageOrientation(
local_frame->metadata().transformation.value_or(
media::kNoTransformation));
- auto orientation_adjusted_size = FloatSize(local_frame->natural_size());
+ auto orientation_adjusted_size =
+ FloatSize(local_frame->visible_rect().size());
if (ImageOrientation(orientation_enum).UsesWidthAsHeight())
return orientation_adjusted_size.TransposedSize();
return orientation_adjusted_size;
@@ -1046,7 +890,7 @@ IntSize VideoFrame::BitmapSourceSize() const {
return IntSize();
// ImageBitmaps should always return the size w/o respecting orientation.
- return IntSize(local_frame->natural_size());
+ return IntSize(local_frame->visible_rect().size());
}
ScriptPromise VideoFrame::CreateImageBitmap(ScriptState* script_state,
@@ -1090,7 +934,10 @@ ScriptPromise VideoFrame::CreateImageBitmap(ScriptState* script_state,
}
void VideoFrame::Trace(Visitor* visitor) const {
- visitor->Trace(planes_);
+ visitor->Trace(coded_rect_);
+ visitor->Trace(visible_rect_);
+ visitor->Trace(color_space_);
+ visitor->Trace(empty_color_space_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.h
index 29b5516f3f7..67ec46b3579 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.h
@@ -10,12 +10,12 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_region.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/webcodecs/plane.h"
+#include "third_party/blink/renderer/modules/webcodecs/allow_shared_buffer_source_util.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_handle.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
@@ -31,16 +31,16 @@ class VideoFrame;
namespace blink {
-class ArrayBufferOrArrayBufferView;
class CanvasImageSource;
+class DOMRectReadOnly;
class ExceptionState;
class ExecutionContext;
-class PlaneInit;
class ScriptPromise;
class ScriptState;
+class VideoColorSpace;
+class VideoFrameBufferInit;
+class VideoFrameCopyToOptions;
class VideoFrameInit;
-class VideoFramePlaneInit;
-class VideoFrameReadIntoOptions;
class MODULES_EXPORT VideoFrame final : public ScriptWrappable,
public CanvasImageSource,
@@ -48,64 +48,51 @@ class MODULES_EXPORT VideoFrame final : public ScriptWrappable,
DEFINE_WRAPPERTYPEINFO();
public:
- // Creates a VideoFrame with a new VideoFrameHandle wrapping |frame|.
- VideoFrame(scoped_refptr<media::VideoFrame> frame, ExecutionContext*);
+ // Creates a VideoFrame with a new VideoFrameHandle wrapping |frame|, and
+ // monitored using |monitoring_source_id|.
+ VideoFrame(scoped_refptr<media::VideoFrame> frame,
+ ExecutionContext*,
+ std::string monitoring_source_id = std::string());
// Creates a VideoFrame from an existing handle.
// All frames sharing |handle| will have their |handle_| invalidated if any of
// the frames receives a call to close().
explicit VideoFrame(scoped_refptr<VideoFrameHandle> handle);
+ ~VideoFrame() override;
+
// video_frame.idl implementation.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static VideoFrame* Create(ScriptState* script_state,
const V8CanvasImageSource* source,
const VideoFrameInit* init,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static VideoFrame* Create(ScriptState*,
- const CanvasImageSourceUnion&,
- const VideoFrameInit*,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static VideoFrame* Create(ScriptState*,
- const HeapVector<Member<PlaneInit>>&,
- const VideoFramePlaneInit*,
+ const AllowSharedBufferSource*,
+ const VideoFrameBufferInit*,
ExceptionState&);
- String format() const;
- absl::optional<HeapVector<Member<Plane>>> planes();
+ absl::optional<V8VideoPixelFormat> format() const;
+
+ absl::optional<int64_t> timestamp() const;
+ absl::optional<uint64_t> duration() const;
uint32_t codedWidth() const;
uint32_t codedHeight() const;
- VideoFrameRegion* codedRegion() const;
- VideoFrameRegion* visibleRegion() const;
-
- uint32_t cropLeft(ExecutionContext*) const;
- uint32_t cropTop(ExecutionContext*) const;
- uint32_t cropWidth(ExecutionContext*) const;
- uint32_t cropHeight(ExecutionContext*) const;
+ absl::optional<DOMRectReadOnly*> codedRect();
+ absl::optional<DOMRectReadOnly*> visibleRect();
uint32_t displayWidth() const;
uint32_t displayHeight() const;
- absl::optional<int64_t> timestamp() const;
- absl::optional<uint64_t> duration() const;
+ VideoColorSpace* colorSpace();
- uint32_t allocationSize(VideoFrameReadIntoOptions* options, ExceptionState&);
+ uint32_t allocationSize(VideoFrameCopyToOptions* options, ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise readInto(ScriptState* script_state,
- const V8BufferSource* destination,
- VideoFrameReadIntoOptions* options,
- ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ScriptPromise readInto(ScriptState*,
- const ArrayBufferOrArrayBufferView& destination,
- VideoFrameReadIntoOptions* options,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ ScriptPromise copyTo(ScriptState* script_state,
+ const AllowSharedBufferSource* destination,
+ VideoFrameCopyToOptions* options,
+ ExceptionState& exception_state);
// Invalidates |handle_|, releasing underlying media::VideoFrame references.
// This effectively "destroys" all frames sharing the same Handle.
@@ -125,8 +112,10 @@ class MODULES_EXPORT VideoFrame final : public ScriptWrappable,
private:
// CanvasImageSource implementation
- scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
- const FloatSize&) override;
+ scoped_refptr<Image> GetSourceImageForCanvas(
+ SourceImageStatus*,
+ const FloatSize&,
+ const AlphaDisposition alpha_disposition = kPremultiplyAlpha) override;
bool WouldTaintOrigin() const override;
FloatSize ElementSize(const FloatSize&,
const RespectImageOrientationEnum) const override;
@@ -142,8 +131,15 @@ class MODULES_EXPORT VideoFrame final : public ScriptWrappable,
const ImageBitmapOptions*,
ExceptionState&) override;
+ // Underlying frame
scoped_refptr<VideoFrameHandle> handle_;
- HeapVector<Member<Plane>> planes_;
+
+ // Caches
+ int64_t external_allocated_memory_;
+ Member<DOMRectReadOnly> coded_rect_;
+ Member<DOMRectReadOnly> visible_rect_;
+ Member<VideoColorSpace> color_space_;
+ Member<VideoColorSpace> empty_color_space_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.idl
index a0a9db5f938..5171e6c0360 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame.idl
@@ -4,6 +4,8 @@
// https://github.com/WICG/web-codecs
+typedef ([AllowShared] ArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource;
+
[
Exposed=(Window,DedicatedWorker),
Serializable,
@@ -11,15 +13,11 @@
] interface VideoFrame {
[CallWith=ScriptState, RaisesException]
constructor(CanvasImageSource source, optional VideoFrameInit init = {});
+
[CallWith=ScriptState, RaisesException]
- constructor(sequence<PlaneInit> planes,
- VideoFramePlaneInit init);
+ constructor(AllowSharedBufferSource data, VideoFrameBufferInit init);
- // TODO(sandersd): It's not clear whether it's better to use undefined, or a
- // special enum value to mean 'opaque format'. Undefined does result in
- // shorter branch conditions.
readonly attribute VideoPixelFormat? format;
- readonly attribute FrozenArray<Plane>? planes;
// Presentation timestamp, in microseconds.
readonly attribute long long? timestamp;
@@ -32,35 +30,32 @@
readonly attribute unsigned long codedHeight;
// Convenience accessor, origin is always (0, 0).
- readonly attribute VideoFrameRegion codedRegion;
+ readonly attribute DOMRectReadOnly? codedRect;
- // Region of this frame's pixel data that is not padding.
- readonly attribute VideoFrameRegion visibleRegion;
+ // Area of this frame's pixel data that is not padding.
+ readonly attribute DOMRectReadOnly? visibleRect;
- // Display aspect ratio of visible region.
+ // Display aspect ratio of visible rect.
readonly attribute unsigned long displayWidth;
readonly attribute unsigned long displayHeight;
- // Returns the minimum size (in bytes) of a buffer that readInto() could
- // read this frame into with the given options.
+ // Color space of the data produced by copyTo().
+ readonly attribute VideoColorSpace colorSpace;
+
+ // Returns the minimum size (in bytes) of a buffer that copyTo() could
+ // copy this frame into with the given options.
[RaisesException] unsigned long allocationSize(
- optional VideoFrameReadIntoOptions options = {});
+ optional VideoFrameCopyToOptions options = {});
- // Read the planes of this frame into |destination| according to |options|.
+ // Copy the planes of this frame into |destination| according to |options|.
// The format of the data is the same as this frame's |format|.
[CallWith=ScriptState, RaisesException]
- Promise<sequence<PlaneLayout>> readInto(
- BufferSource destination,
- optional VideoFrameReadIntoOptions options = {});
+ Promise<sequence<PlaneLayout>> copyTo(
+ AllowSharedBufferSource destination,
+ optional VideoFrameCopyToOptions options = {});
// Creates a copy of this VideoFrame, which needs to be independently closed.
[RaisesException] VideoFrame clone();
void close();
-
- // DEPRECATED: Use visibleRegion.
- [CallWith=ExecutionContext] readonly attribute unsigned long cropLeft;
- [CallWith=ExecutionContext] readonly attribute unsigned long cropTop;
- [CallWith=ExecutionContext] readonly attribute unsigned long cropWidth;
- [CallWith=ExecutionContext] readonly attribute unsigned long cropHeight;
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h
index e9e52bc24a7..6bb2c73345c 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_ATTACHMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_ATTACHMENT_H_
-#include "third_party/abseil-cpp/absl/types/optional.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/modules/webcodecs/video_frame_handle.h"
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_buffer_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_buffer_init.idl
new file mode 100644
index 00000000000..8669400c5f4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_buffer_init.idl
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+dictionary VideoFrameBufferInit {
+ required VideoPixelFormat format;
+
+ // Default layout is tightly-packed.
+ sequence<PlaneLayout> layout;
+
+ required [EnforceRange] long long timestamp; // microseconds
+ [EnforceRange] unsigned long long duration; // microseconds
+
+ required [EnforceRange] unsigned long codedWidth;
+ required [EnforceRange] unsigned long codedHeight;
+
+ DOMRectInit visibleRect;
+
+ [EnforceRange] unsigned long displayWidth;
+ [EnforceRange] unsigned long displayHeight;
+
+ VideoColorSpaceInit colorSpace;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_read_into_options.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_options.idl
index 84c62362360..d56891de17a 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_read_into_options.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_options.idl
@@ -4,10 +4,10 @@
// https://github.com/WICG/web-codecs
-dictionary VideoFrameReadIntoOptions {
- // The region to read. If unspecified, the visible region will be used. The
- // coded region can be easily specified by passing frame.codedRegion.
- VideoFrameRegion region;
+dictionary VideoFrameCopyToOptions {
+ // The area to copy. If unspecified, the visible rect will be used. The coded
+ // rect can be specified by passing frame.codedRect.
+ DOMRectInit rect;
// The layout of each plane in the buffer. This allows the offset and stride
// of each plane to be specified. If unspecified, the planes will be tightly
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.cc
index d6d390744ca..437cfaec608 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.cc
@@ -6,47 +6,62 @@
#include "media/base/video_frame.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h"
#include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h"
#include "third_party/skia/include/core/SkImage.h"
namespace blink {
VideoFrameHandle::VideoFrameHandle(scoped_refptr<media::VideoFrame> frame,
- ExecutionContext* context)
- : frame_(std::move(frame)) {
+ ExecutionContext* context,
+ std::string monitoring_source_id)
+ : frame_(std::move(frame)),
+ monitoring_source_id_(std::move(monitoring_source_id)) {
DCHECK(frame_);
DCHECK(context);
close_auditor_ = WebCodecsLogger::From(*context).GetCloseAuditor();
-
DCHECK(close_auditor_);
+
+ MaybeMonitorOpenFrame();
}
VideoFrameHandle::VideoFrameHandle(scoped_refptr<media::VideoFrame> frame,
sk_sp<SkImage> sk_image,
- ExecutionContext* context)
- : VideoFrameHandle(std::move(frame), context) {
+ ExecutionContext* context,
+ std::string monitoring_source_id)
+ : VideoFrameHandle(std::move(frame),
+ context,
+ std::move(monitoring_source_id)) {
sk_image_ = std::move(sk_image);
}
VideoFrameHandle::VideoFrameHandle(
scoped_refptr<media::VideoFrame> frame,
sk_sp<SkImage> sk_image,
- scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor> close_auditor)
+ scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor> close_auditor,
+ std::string monitoring_source_id)
: sk_image_(std::move(sk_image)),
frame_(std::move(frame)),
- close_auditor_(std::move(close_auditor)) {
+ close_auditor_(std::move(close_auditor)),
+ monitoring_source_id_(std::move(monitoring_source_id)) {
DCHECK(frame_);
DCHECK(close_auditor_);
+ MaybeMonitorOpenFrame();
}
VideoFrameHandle::VideoFrameHandle(scoped_refptr<media::VideoFrame> frame,
- sk_sp<SkImage> sk_image)
- : sk_image_(std::move(sk_image)), frame_(std::move(frame)) {
+ sk_sp<SkImage> sk_image,
+ std::string monitoring_source_id)
+ : sk_image_(std::move(sk_image)),
+ frame_(std::move(frame)),
+ monitoring_source_id_(std::move(monitoring_source_id)) {
DCHECK(frame_);
+ MaybeMonitorOpenFrame();
}
VideoFrameHandle::~VideoFrameHandle() {
+ MaybeMonitorCloseFrame();
// If we still have a valid |close_auditor_|, Invalidate() was never
// called and corresponding frames never received a call to close() before
// being garbage collected.
@@ -76,9 +91,10 @@ void VideoFrameHandle::SetCloseOnClone() {
scoped_refptr<VideoFrameHandle> VideoFrameHandle::Clone() {
WTF::MutexLocker locker(mutex_);
- auto cloned_handle = frame_ ? base::MakeRefCounted<VideoFrameHandle>(
- frame_, sk_image_, close_auditor_)
- : nullptr;
+ auto cloned_handle =
+ frame_ ? base::MakeRefCounted<VideoFrameHandle>(
+ frame_, sk_image_, close_auditor_, monitoring_source_id_)
+ : nullptr;
if (close_on_clone_)
InvalidateLocked();
@@ -88,16 +104,31 @@ scoped_refptr<VideoFrameHandle> VideoFrameHandle::Clone() {
scoped_refptr<VideoFrameHandle> VideoFrameHandle::CloneForInternalUse() {
WTF::MutexLocker locker(mutex_);
- return frame_ ? base::MakeRefCounted<VideoFrameHandle>(frame_, sk_image_)
+ return frame_ ? base::MakeRefCounted<VideoFrameHandle>(frame_, sk_image_,
+ monitoring_source_id_)
: nullptr;
}
void VideoFrameHandle::InvalidateLocked() {
mutex_.AssertAcquired();
-
+ MaybeMonitorCloseFrame();
frame_.reset();
sk_image_.reset();
close_auditor_.reset();
}
+void VideoFrameHandle::MaybeMonitorOpenFrame() {
+ if (frame_ && !monitoring_source_id_.empty()) {
+ VideoFrameMonitor::Instance().OnOpenFrame(monitoring_source_id_,
+ frame_->unique_id());
+ }
+}
+
+void VideoFrameHandle::MaybeMonitorCloseFrame() {
+ if (frame_ && !monitoring_source_id_.empty()) {
+ VideoFrameMonitor::Instance().OnCloseFrame(monitoring_source_id_,
+ frame_->unique_id());
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.h
index 77add18d690..0663e9ea328 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_handle.h
@@ -36,14 +36,23 @@ class ExecutionContext;
class MODULES_EXPORT VideoFrameHandle
: public WTF::ThreadSafeRefCounted<VideoFrameHandle> {
public:
- VideoFrameHandle(scoped_refptr<media::VideoFrame>, ExecutionContext*);
+ VideoFrameHandle(scoped_refptr<media::VideoFrame>,
+ ExecutionContext*,
+ std::string monitoring_source_id = std::string());
+ VideoFrameHandle(scoped_refptr<media::VideoFrame>,
+ sk_sp<SkImage> sk_image,
+ ExecutionContext*,
+ std::string monitoring_source_id = std::string());
VideoFrameHandle(scoped_refptr<media::VideoFrame>,
sk_sp<SkImage> sk_image,
- ExecutionContext*);
+ scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor>,
+ std::string monitoring_source_id = std::string());
VideoFrameHandle(scoped_refptr<media::VideoFrame>,
sk_sp<SkImage> sk_image,
- scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor>);
- VideoFrameHandle(scoped_refptr<media::VideoFrame>, sk_sp<SkImage> sk_image);
+ std::string monitoring_source_id = std::string());
+
+ VideoFrameHandle(const VideoFrameHandle&) = delete;
+ VideoFrameHandle& operator=(const VideoFrameHandle&) = delete;
// Returns a copy of |frame_|, which should be re-used throughout the scope
// of a function call, instead of calling frame() multiple times. Otherwise
@@ -78,6 +87,9 @@ class MODULES_EXPORT VideoFrameHandle
// |mutex_| must be held before calling into this.
void InvalidateLocked();
+ void MaybeMonitorOpenFrame();
+ void MaybeMonitorCloseFrame();
+
// Flag that prevents the creation of a new handle during the next Clone()
// call. Used as a temporary workaround for crbug.com/1182497.
bool close_on_clone_ = false;
@@ -86,6 +98,7 @@ class MODULES_EXPORT VideoFrameHandle
sk_sp<SkImage> sk_image_;
scoped_refptr<media::VideoFrame> frame_;
scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor> close_auditor_;
+ std::string monitoring_source_id_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl
index f9d8a2c4ef6..4903ddc3c6a 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl
@@ -6,7 +6,7 @@
enum AlphaOption { "discard", "keep" };
dictionary VideoFrameInit {
- long long timestamp; // microseconds
- unsigned long long duration; // microseconds
+ [EnforceRange] long long timestamp; // microseconds
+ [EnforceRange] unsigned long long duration; // microseconds
AlphaOption alpha = "keep";
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.cc
new file mode 100644
index 00000000000..4288c1e950e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.cc
@@ -0,0 +1,95 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h"
+
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+
+namespace blink {
+
+// static
+VideoFrameMonitor& VideoFrameMonitor::Instance() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(VideoFrameMonitor, instance, ());
+ return instance;
+}
+
+void VideoFrameMonitor::OnOpenFrame(const std::string& source_id,
+ int frame_id) {
+ MutexLocker locker(mutex_);
+ OnOpenFrameLocked(source_id, frame_id);
+}
+
+void VideoFrameMonitor::OnCloseFrame(const std::string& source_id,
+ int frame_id) {
+ MutexLocker locker(mutex_);
+ OnCloseFrameLocked(source_id, frame_id);
+}
+
+wtf_size_t VideoFrameMonitor::NumFrames(const std::string& source_id) {
+ MutexLocker locker(mutex_);
+ return NumFramesLocked(source_id);
+}
+
+int VideoFrameMonitor::NumRefs(const std::string& source_id, int frame_id) {
+ MutexLocker locker(mutex_);
+ return NumRefsLocked(source_id, frame_id);
+}
+
+bool VideoFrameMonitor::IsEmpty() {
+ MutexLocker locker(mutex_);
+ return map_.empty();
+}
+
+void VideoFrameMonitor::OnOpenFrameLocked(const std::string& source_id,
+ int frame_id) {
+ DCHECK(!source_id.empty());
+ mutex_.AssertAcquired();
+ FrameMap& frame_map = map_[source_id];
+ auto it_frame = frame_map.find(frame_id);
+ if (it_frame == frame_map.end()) {
+ frame_map.insert(frame_id, 1);
+ } else {
+ DCHECK_GT(it_frame->value, 0);
+ ++it_frame->value;
+ }
+}
+
+void VideoFrameMonitor::OnCloseFrameLocked(const std::string& source_id,
+ int frame_id) {
+ DCHECK(!source_id.empty());
+ mutex_.AssertAcquired();
+ auto it_source = map_.find(source_id);
+ DCHECK(it_source != map_.end());
+ FrameMap& frame_map = it_source->second;
+ auto it_frame = frame_map.find(frame_id);
+ DCHECK(it_frame != frame_map.end());
+ DCHECK_GT(it_frame->value, 0);
+ if (--it_frame->value == 0) {
+ frame_map.erase(it_frame);
+ if (frame_map.IsEmpty())
+ map_.erase(it_source);
+ }
+}
+
+wtf_size_t VideoFrameMonitor::NumFramesLocked(const std::string& source_id) {
+ DCHECK(!source_id.empty());
+ mutex_.AssertAcquired();
+ auto it = map_.find(source_id);
+ return it == map_.end() ? 0u : it->second.size();
+}
+
+int VideoFrameMonitor::NumRefsLocked(const std::string& source_id,
+ int frame_id) {
+ DCHECK(!source_id.empty());
+ mutex_.AssertAcquired();
+ auto it = map_.find(source_id);
+ if (it == map_.end())
+ return 0u;
+
+ FrameMap& frame_map = it->second;
+ auto it_frame = frame_map.find(frame_id);
+ return it_frame == frame_map.end() ? 0 : it_frame->value;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h
new file mode 100644
index 00000000000..2a3292b079b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h
@@ -0,0 +1,105 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_MONITOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_MONITOR_H_
+
+#include <map>
+#include <string>
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+
+namespace blink {
+
+// This class helps monitor usage of media::VideoFrame objects. This class does
+// not directly use VideoFrames, but references them using the ID returned by
+// media::VideoFrame::unique_id.
+// This class is an alternative to using media::VideoFrame destruction observers
+// for cases that require monitoring to stop well before the media::VideoFrame
+// is destroyed. For example, monitoring blink::VideoFrames backed by
+// media::VideoFrames, where the JS-exposed blink::VideoFrames can be closed
+// but the backing media::VideoFrames can continue to live outside the
+// blink::VideoFrames.
+// This class is a per-renderer-process singleton and relies on the fact
+// that VideoFrame IDs are unique per process. That means that the same ID
+// identifies the same frame regardless of the execution context.
+// The motivating use case for this class is keeping track of frames coming
+// from sources that have global limits in the number of in-flight frames
+// allowed. Thus, frames are monitored per source. Sources are identified with
+// a nonempty std::string, so any way to group frames can be used as long as a
+// source ID is given. std::string is chosen over the Blink-standard WTF::String
+// because:
+// 1. source IDs often come from outside Blink (e.g., camera and screen
+// device IDs)
+// 2. std::string is easier to use in a multithreaded environment.
+// All the methods of this class can be called from any thread.
+class MODULES_EXPORT VideoFrameMonitor {
+ public:
+ // Returns the singleton VideoFrameMonitor.
+ static VideoFrameMonitor& Instance();
+ VideoFrameMonitor(const VideoFrameMonitor&) = delete;
+ VideoFrameMonitor& operator=(const VideoFrameMonitor&) = delete;
+
+ // Report that a new frame with ID |frame_id| associated with the source with
+ // ID |source_id| is being monitored.
+ void OnOpenFrame(const std::string& source_id, int frame_id);
+ // Report that a new frame with ID |frame_id| associated with the source with
+ // ID |source_id| is being monitored.
+ void OnCloseFrame(const std::string& source_id, int frame_id);
+ // Reports the number of distinct monitored frames associated with
+ // |source_id|.
+ wtf_size_t NumFrames(const std::string& source_id);
+ // Reports the reference count for the frame with ID |frame_id| associated
+ // with the source with ID |source_id|.
+ int NumRefs(const std::string& source_id, int frame_id);
+
+ // Reports true if nothing is being monitored, false otherwise.
+ bool IsEmpty();
+
+ // This function returns a mutex that can be used to lock the
+ // VideoFrameMonitor so that multiple invocations to the methods below
+ // (suffixed with "Locked" can be done atomically, as a single update to
+ // the monitor. Locking the VideoFrameMonitor using GetMutex() must be done
+ // very carefully, as any invocation to any non-Locked method while the mutex
+ // is acquired will result in deadlock.
+ // For example, blink::VideoFrame objects may be automatically monitored, so
+ // they should not be created, cloned or closed while the mutex is acquired.
+ Mutex& GetMutex() { return mutex_; }
+
+ // The methods below can be called only when the mutex returned by GetMutex()
+ // has been acquired. Other than that, they are equivalent to their
+ // corresponding non-locked version.
+ void OnOpenFrameLocked(const std::string& source_id, int frame_id);
+ void OnCloseFrameLocked(const std::string& source_id, int frame_id);
+ wtf_size_t NumFramesLocked(const std::string& source_id);
+ int NumRefsLocked(const std::string& source_id, int frame_id);
+
+ private:
+ VideoFrameMonitor() = default;
+
+ // key: unique ID of a frame.
+ // value: reference count for the frame (among objects explicitly tracking
+ // the frame with VideoFrameMonitor).
+ using FrameMap = HashMap<int,
+ int,
+ WTF::IntHash<int>,
+ WTF::UnsignedWithZeroKeyHashTraits<int>>;
+
+ // key: ID of the source of the frames.
+ // value: References to frames associated to that source.
+ // Using std::map because HashMap does not directly support std::string.
+ using SourceMap = std::map<std::string, FrameMap>;
+
+ Mutex mutex_;
+ // Contains all data for VideoFrameMonitor.
+ SourceMap map_ GUARDED_BY(mutex_);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_MONITOR_H_
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor_test.cc
new file mode 100644
index 00000000000..99cafa53442
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_monitor_test.cc
@@ -0,0 +1,90 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h"
+
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+
+namespace blink {
+
+class VideoFrameMonitorTest : public testing::Test {
+ protected:
+ static void SequenceOfOperations(const std::string& source_id) {
+ VideoFrameMonitor& monitor = VideoFrameMonitor::Instance();
+
+ monitor.OnOpenFrame(source_id, 0);
+ EXPECT_EQ(monitor.NumFrames(source_id), 1u);
+
+ monitor.OnOpenFrame(source_id, 10);
+ EXPECT_EQ(monitor.NumFrames(source_id), 2u);
+
+ monitor.OnOpenFrame(source_id, 20);
+ EXPECT_EQ(monitor.NumFrames(source_id), 3u);
+
+ monitor.OnCloseFrame(source_id, 0);
+ EXPECT_EQ(monitor.NumFrames(source_id), 2u);
+
+ monitor.OnCloseFrame(source_id, 10);
+ EXPECT_EQ(monitor.NumFrames(source_id), 1u);
+
+ monitor.OnOpenFrame(source_id, 30);
+ EXPECT_EQ(monitor.NumFrames(source_id), 2u);
+
+ monitor.OnOpenFrame(source_id, 20);
+ EXPECT_EQ(monitor.NumFrames(source_id), 2u);
+ EXPECT_EQ(monitor.NumRefs(source_id, 20), 2);
+
+ // JS closes one of its VideoFrames with ID 20
+ monitor.OnCloseFrame(source_id, 20);
+ EXPECT_EQ(monitor.NumFrames(source_id), 2u);
+ EXPECT_EQ(monitor.NumRefs(source_id, 20), 1);
+
+ {
+ MutexLocker locker(monitor.GetMutex());
+ monitor.OnOpenFrameLocked(source_id, 30);
+ EXPECT_EQ(monitor.NumFramesLocked(source_id), 2u);
+ EXPECT_EQ(monitor.NumRefsLocked(source_id, 30), 2);
+
+ monitor.OnCloseFrameLocked(source_id, 20);
+ EXPECT_EQ(monitor.NumFramesLocked(source_id), 1u);
+ EXPECT_EQ(monitor.NumRefsLocked(source_id, 20), 0);
+
+ monitor.OnCloseFrameLocked(source_id, 30);
+ EXPECT_EQ(monitor.NumFramesLocked(source_id), 1u);
+ EXPECT_EQ(monitor.NumRefsLocked(source_id, 30), 1);
+ }
+
+ monitor.OnCloseFrame(source_id, 30);
+ EXPECT_EQ(monitor.NumRefs(source_id, 30), 0);
+ EXPECT_EQ(monitor.NumFrames(source_id), 0u);
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() {
+ return platform_->GetIOTaskRunner();
+ }
+
+ private:
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+};
+
+TEST_F(VideoFrameMonitorTest, TwoDevicesOnSeparateThreads) {
+ base::RunLoop loop;
+ PostCrossThreadTask(*GetIOTaskRunner(), FROM_HERE,
+ CrossThreadBindOnce(
+ [](base::RunLoop* loop) {
+ SequenceOfOperations("device2");
+ loop->Quit();
+ },
+ CrossThreadUnretained(&loop)));
+ SequenceOfOperations("device1");
+ loop.Run();
+ EXPECT_TRUE(VideoFrameMonitor::Instance().IsEmpty());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl
deleted file mode 100644
index 68bb1988803..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-dictionary VideoFramePlaneInit {
- required VideoPixelFormat format;
-
- required long long timestamp; // microseconds
- unsigned long long duration; // microseconds
-
- required [EnforceRange] unsigned long codedWidth;
- required [EnforceRange] unsigned long codedHeight;
-
- VideoFrameRegion visibleRegion;
-
- [EnforceRange] unsigned long displayWidth;
- [EnforceRange] unsigned long displayHeight;
-
- // DEPRECATED: Use visibleRegion.
- [EnforceRange] unsigned long cropLeft;
- [EnforceRange] unsigned long cropTop;
- [EnforceRange] unsigned long cropWidth;
- [EnforceRange] unsigned long cropHeight;
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_region.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_region.idl
deleted file mode 100644
index 46a1930bb92..00000000000
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_region.idl
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/web-codecs
-
-// Specifies a rectangular region of a VideoFrame. Valid regions have nonzero
-// size and are contained in the frame's coded region.
-dictionary VideoFrameRegion {
- // TODO(sandersd): Should we make the origin optional and assume (0, 0)?
- required [EnforceRange] unsigned long left;
- required [EnforceRange] unsigned long top;
- required [EnforceRange] unsigned long width;
- required [EnforceRange] unsigned long height;
-};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc
index 05c37b0fa76..0b1808ff704 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc
@@ -7,6 +7,7 @@
#include "components/viz/test/test_context_provider.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -16,6 +17,7 @@
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_handle.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h"
#include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
@@ -92,8 +94,6 @@ TEST_F(VideoFrameTest, ConstructorAndAttributes) {
EXPECT_EQ(1000u, blink_frame->timestamp().value());
EXPECT_EQ(112u, blink_frame->codedWidth());
EXPECT_EQ(208u, blink_frame->codedHeight());
- EXPECT_EQ(100u, blink_frame->visibleRegion()->width());
- EXPECT_EQ(200u, blink_frame->visibleRegion()->height());
EXPECT_EQ(media_frame, blink_frame->frame());
blink_frame->close();
@@ -101,8 +101,6 @@ TEST_F(VideoFrameTest, ConstructorAndAttributes) {
EXPECT_FALSE(blink_frame->timestamp().has_value());
EXPECT_EQ(0u, blink_frame->codedWidth());
EXPECT_EQ(0u, blink_frame->codedHeight());
- EXPECT_EQ(0u, blink_frame->visibleRegion()->width());
- EXPECT_EQ(0u, blink_frame->visibleRegion()->height());
EXPECT_EQ(nullptr, blink_frame->frame());
}
@@ -236,24 +234,14 @@ TEST_F(VideoFrameTest, ImageBitmapCreationAndZeroCopyRoundTrip) {
auto* image_bitmap = MakeGarbageCollected<ImageBitmap>(
UnacceleratedStaticBitmapImage::Create(original_image), absl::nullopt,
default_options);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* source = MakeGarbageCollected<V8CanvasImageSource>(image_bitmap);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasImageSourceUnion source;
- source.SetImageBitmap(image_bitmap);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* video_frame = VideoFrame::Create(scope.GetScriptState(), source, init,
scope.GetExceptionState());
EXPECT_EQ(video_frame->handle()->sk_image(), original_image);
{
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* ibs_source = MakeGarbageCollected<V8ImageBitmapSource>(video_frame);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- ImageBitmapSourceUnion ibs_source;
- ibs_source.SetVideoFrame(video_frame);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto promise = ImageBitmapFactories::CreateImageBitmap(
scope.GetScriptState(), ibs_source, default_options,
scope.GetExceptionState());
@@ -278,7 +266,7 @@ TEST_F(VideoFrameTest, VideoFrameFromGPUImageBitmap) {
auto context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
CanvasResourceParams resource_params;
auto resource_provider = CanvasResourceProvider::CreateSharedImageProvider(
- IntSize(100, 100), kLow_SkFilterQuality, resource_params,
+ IntSize(100, 100), cc::PaintFlags::FilterQuality::kLow, resource_params,
CanvasResourceProvider::ShouldInitialize::kNo, context_provider_wrapper,
RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
@@ -293,17 +281,171 @@ TEST_F(VideoFrameTest, VideoFrameFromGPUImageBitmap) {
auto* init = VideoFrameInit::Create();
init->setTimestamp(0);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* source = MakeGarbageCollected<V8CanvasImageSource>(image_bitmap);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- CanvasImageSourceUnion source;
- source.SetImageBitmap(image_bitmap);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* video_frame = VideoFrame::Create(scope.GetScriptState(), source, init,
scope.GetExceptionState());
ASSERT_TRUE(video_frame);
}
+TEST_F(VideoFrameTest, HandleMonitoring) {
+ V8TestingScope scope;
+ VideoFrameMonitor& monitor = VideoFrameMonitor::Instance();
+ const std::string source1 = "source1";
+ const std::string source2 = "source2";
+ EXPECT_TRUE(monitor.IsEmpty());
+
+ // Test all constructors.
+ scoped_refptr<media::VideoFrame> media_frame1 =
+ CreateDefaultBlackMediaVideoFrame();
+ scoped_refptr<media::VideoFrame> media_frame2 =
+ CreateDefaultBlackMediaVideoFrame();
+
+ auto verify_expectations =
+ [&](wtf_size_t num_frames_source1, int num_refs_frame1_source1,
+ int num_refs_frame2_source1, wtf_size_t num_frames_source2,
+ int num_refs_frame1_source2, int num_refs_frame2_source2) {
+ EXPECT_EQ(monitor.NumFrames(source1), num_frames_source1);
+ EXPECT_EQ(monitor.NumRefs(source1, media_frame1->unique_id()),
+ num_refs_frame1_source1);
+ EXPECT_EQ(monitor.NumRefs(source1, media_frame2->unique_id()),
+ num_refs_frame2_source1);
+ EXPECT_EQ(monitor.NumFrames(source2), num_frames_source2);
+ EXPECT_EQ(monitor.NumRefs(source2, media_frame1->unique_id()),
+ num_refs_frame1_source2);
+ EXPECT_EQ(monitor.NumRefs(source2, media_frame2->unique_id()),
+ num_refs_frame2_source2);
+ };
+
+ auto handle_1_1 = base::MakeRefCounted<VideoFrameHandle>(
+ media_frame1, scope.GetExecutionContext(), source1);
+ verify_expectations(/* source1 */ 1, 1, 0, /* source2 */ 0, 0, 0);
+
+ sk_sp<SkSurface> surface(SkSurface::MakeRaster(
+ SkImageInfo::MakeN32Premul(5, 5, SkColorSpace::MakeSRGB())));
+ sk_sp<SkImage> sk_image = surface->makeImageSnapshot();
+ auto handle_2_1 = base::MakeRefCounted<VideoFrameHandle>(
+ media_frame2, sk_image, scope.GetExecutionContext(), source1);
+ verify_expectations(/* source1 */ 2, 1, 1, /* source2 */ 0, 0, 0);
+
+ auto& logger = WebCodecsLogger::From(*scope.GetExecutionContext());
+ auto handle_1_1b = base::MakeRefCounted<VideoFrameHandle>(
+ media_frame1, sk_image, logger.GetCloseAuditor(), source1);
+ verify_expectations(/* source1 */ 2, 2, 1, /* source2 */ 0, 0, 0);
+
+ auto handle_1_2 =
+ base::MakeRefCounted<VideoFrameHandle>(media_frame1, sk_image, source2);
+ verify_expectations(/* source1 */ 2, 2, 1, /* source2 */ 1, 1, 0);
+
+ auto non_monitored1 = base::MakeRefCounted<VideoFrameHandle>(
+ media_frame2, sk_image, scope.GetExecutionContext());
+ verify_expectations(/* source1 */ 2, 2, 1, /* source2 */ 1, 1, 0);
+
+ auto non_monitored2 =
+ base::MakeRefCounted<VideoFrameHandle>(media_frame1, sk_image);
+ verify_expectations(/* source1 */ 2, 2, 1, /* source2 */ 1, 1, 0);
+
+ // Move constructor
+ auto handle_1_1c = std::move(handle_1_1b);
+ verify_expectations(/* source1 */ 2, 2, 1, /* source2 */ 1, 1, 0);
+
+ // Test all clone methods.
+ auto clone_1_1a = handle_1_1->Clone();
+ verify_expectations(/* source1 */ 2, 3, 1, /* source2 */ 1, 1, 0);
+
+ auto clone_1_1b = handle_1_1->CloneForInternalUse();
+ verify_expectations(/* source1 */ 2, 4, 1, /* source2 */ 1, 1, 0);
+
+ // Clone non-monitored frame
+ auto non_monitored_clone = non_monitored2->CloneForInternalUse();
+ verify_expectations(/* source1 */ 2, 4, 1, /* source2 */ 1, 1, 0);
+
+ // Test invalidate
+ handle_1_1->Invalidate();
+ verify_expectations(/* source1 */ 2, 3, 1, /* source2 */ 1, 1, 0);
+
+ // handle_1_1b was moved to handle_1_1c
+ handle_1_1c->Invalidate();
+ verify_expectations(/* source1 */ 2, 2, 1, /* source2 */ 1, 1, 0);
+
+ handle_2_1->Invalidate();
+ verify_expectations(/* source1 */ 1, 2, 0, /* source2 */ 1, 1, 0);
+
+ non_monitored1->Invalidate();
+ verify_expectations(/* source1 */ 1, 2, 0, /* source2 */ 1, 1, 0);
+
+ non_monitored2->Invalidate();
+ verify_expectations(/* source1 */ 1, 2, 0, /* source2 */ 1, 1, 0);
+
+ clone_1_1a->Invalidate();
+ verify_expectations(/* source1 */ 1, 1, 0, /* source2 */ 1, 1, 0);
+
+ // Resetting handles instead of invalidating.
+ handle_1_2.reset();
+ verify_expectations(/* source1 */ 1, 1, 0, /* source2 */ 0, 0, 0);
+
+ clone_1_1b.reset();
+ EXPECT_TRUE(monitor.IsEmpty());
+
+ // handle10 is not monitored
+ non_monitored_clone.reset();
+ EXPECT_TRUE(monitor.IsEmpty());
+}
+
+TEST_F(VideoFrameTest, VideoFrameMonitoring) {
+ V8TestingScope scope;
+ VideoFrameMonitor& monitor = VideoFrameMonitor::Instance();
+ const std::string source = "source";
+ scoped_refptr<media::VideoFrame> media_frame =
+ CreateDefaultBlackMediaVideoFrame();
+ auto verify_expectations = [&](wtf_size_t num_frames, int num_refs) {
+ EXPECT_EQ(monitor.NumFrames(source), num_frames);
+ EXPECT_EQ(monitor.NumRefs(source, media_frame->unique_id()), num_refs);
+ };
+ EXPECT_TRUE(monitor.IsEmpty());
+
+ // Test all constructors
+ auto* frame1 = MakeGarbageCollected<VideoFrame>(
+ media_frame, scope.GetExecutionContext(), source);
+ verify_expectations(1u, 1);
+
+ auto* non_monitored1 = MakeGarbageCollected<VideoFrame>(
+ media_frame, scope.GetExecutionContext());
+ verify_expectations(1u, 1);
+
+ auto monitored_handle = base::MakeRefCounted<VideoFrameHandle>(
+ media_frame, scope.GetExecutionContext(), source);
+ auto* frame2 = MakeGarbageCollected<VideoFrame>(std::move(monitored_handle));
+ verify_expectations(1u, 2);
+
+ auto non_monitored_handle = base::MakeRefCounted<VideoFrameHandle>(
+ media_frame, scope.GetExecutionContext());
+ auto* non_monitored2 =
+ MakeGarbageCollected<VideoFrame>(std::move(non_monitored_handle));
+ verify_expectations(1u, 2);
+
+ frame1->clone(scope.GetExceptionState());
+ verify_expectations(1u, 3);
+
+ auto* non_monitored_clone = non_monitored1->clone(scope.GetExceptionState());
+ verify_expectations(1u, 3);
+
+ frame1->close();
+ verify_expectations(1u, 2);
+
+ frame2->close();
+ verify_expectations(1u, 1);
+
+ non_monitored1->close();
+ non_monitored2->close();
+ non_monitored_clone->close();
+ verify_expectations(1u, 1);
+
+ // Garbage-collecting a non-closed monitored frame should reclaim it and
+ // update the monitor.
+ blink::WebHeap::CollectAllGarbageForTesting();
+ EXPECT_TRUE(monitor.IsEmpty());
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_matrix_coefficients.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_matrix_coefficients.idl
new file mode 100644
index 00000000000..020a10b61c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_matrix_coefficients.idl
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+enum VideoMatrixCoefficients {
+ "rgb", // sRGB
+ "bt709", // BT.709
+ "bt470bg", // BT.601 PAL
+ "smpte170m", // BT.601 NTSC (functionally the same as bt470bg)
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl
index 2ace03059d4..61af742036e 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl
@@ -5,27 +5,30 @@
// https://github.com/WICG/web-codecs
enum VideoPixelFormat {
- // 4:2:0 subsampled 3 plane Y,U,V or 4 plane Y,U,V,A
+ // 4:2:0 Y, U, V
"I420",
- // 4:2:2 subsampled 3 plane Y,U,V
+ // 4:2:0 Y, U, V, A
+ "I420A",
+
+ // 4:2:2 Y, U, V
"I422",
- // 4:4:4 subsampled 3 plane Y,U,V
+ // 4:4:4 Y, U, V
"I444",
- // 4:2:0 subsampled 2 plane Y,UV
+ // 4:2:0 Y, UV
"NV12",
- // 32bpp RGBA (byte-order), 1 plane.
- "ABGR",
+ // 32bpp RGBA
+ "RGBA",
- // 32bpp BGRA (byte-order), 1 plane.
- "ARGB",
+ // 32bpp RGBX (opaque)
+ "RGBX",
- // 24bpp RGBX (byte-order), 1 plane.
- "XBGR",
+ // 32bpp BGRA
+ "BGRA",
- // 24bpp BGRX (byte-order), 1 plane.
- "XRGB",
+ // 32bpp BGRX (opaque)
+ "BGRX",
};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/video_transfer_characteristics.idl b/chromium/third_party/blink/renderer/modules/webcodecs/video_transfer_characteristics.idl
new file mode 100644
index 00000000000..dd9ec7cff13
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/video_transfer_characteristics.idl
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/web-codecs
+
+enum VideoTransferCharacteristics {
+ "bt709", // BT.709
+ "smpte170m", // BT.601 (functionally the same as bt709)
+ "iec61966-2-1", // sRGB
+};
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc b/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc
index 9839724815c..e70ad64078f 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc
@@ -56,18 +56,6 @@ WebCodecsLogger::GetCloseAuditor() {
return close_auditor_;
}
-void WebCodecsLogger::LogCropDeprecation() {
- LogDeprecation(
- Deprecation::kCrop,
- "cropTop, cropLeft, cropWidth, and cropHeight are deprecated; please "
- "use visibleRegion.");
-}
-
-void WebCodecsLogger::LogPlaneInitSrcDeprecation() {
- LogDeprecation(Deprecation::kPlaneInitSrc,
- "PlaneInit.src is deprecated, please use PlaneInit.data.");
-}
-
void WebCodecsLogger::LogCloseErrors(TimerBase*) {
// If it's been a while since this class was used and there are not other
// references to |leak_status_|, stop the timer.
@@ -92,16 +80,6 @@ void WebCodecsLogger::LogCloseErrors(TimerBase*) {
close_auditor_->Clear();
}
-void WebCodecsLogger::LogDeprecation(Deprecation id, const String& message) {
- uint32_t id_bits = static_cast<uint32_t>(id);
- if (logged_deprecations_ & id_bits)
- return;
- logged_deprecations_ |= id_bits;
- GetSupplementable()->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::blink::ConsoleMessageSource::kDeprecation,
- mojom::blink::ConsoleMessageLevel::kWarning, message));
-}
-
void WebCodecsLogger::Trace(Visitor* visitor) const {
visitor->Trace(timer_);
Supplement<ExecutionContext>::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h b/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h
index f3607d2f0f2..8d5eb5da384 100644
--- a/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h
+++ b/chromium/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h
@@ -62,25 +62,14 @@ class MODULES_EXPORT WebCodecsLogger : public GarbageCollected<WebCodecsLogger>,
// Returns |close_auditor_| and starts |timer_| if needed.
scoped_refptr<VideoFrameCloseAuditor> GetCloseAuditor();
- void LogCropDeprecation();
- void LogPlaneInitSrcDeprecation();
-
void Trace(Visitor*) const override;
private:
- enum class Deprecation {
- kCrop = 1 << 0,
- kPlaneInitSrc = 1 << 1,
- };
-
void LogCloseErrors(TimerBase*);
- void LogDeprecation(Deprecation, const String& message);
base::TimeTicks last_auditor_access_;
scoped_refptr<VideoFrameCloseAuditor> close_auditor_;
HeapTaskRunnerTimer<WebCodecsLogger> timer_;
-
- uint32_t logged_deprecations_ = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/OWNERS b/chromium/third_party/blink/renderer/modules/webdatabase/OWNERS
index 8de78041ae4..c0fe97d5c76 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/OWNERS
@@ -2,5 +2,4 @@
pwnall@chromium.org
# Secondary
-jsbell@chromium.org
mek@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database.cc b/chromium/third_party/blink/renderer/modules/webdatabase/database.cc
index 30b4a903954..02ec543c59f 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/public/platform/platform.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/web_feature.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/probe/async_task_id.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -108,11 +109,17 @@ class DatabaseVersionCache {
mutex_.AssertAcquired();
String string_id = origin + "/" + name;
DCHECK(string_id.IsSafeToSendToAnotherThread());
- DatabaseGuid guid = origin_name_to_guid_.at(string_id);
- if (!guid) {
+
+ DatabaseGuid guid;
+ auto origin_name_to_guid_it = origin_name_to_guid_.find(string_id);
+ if (origin_name_to_guid_it == origin_name_to_guid_.end()) {
guid = next_guid_++;
origin_name_to_guid_.Set(string_id, guid);
+ } else {
+ guid = origin_name_to_guid_it->value;
+ DCHECK(guid);
}
+
count_.insert(guid);
return guid;
}
@@ -130,7 +137,14 @@ class DatabaseVersionCache {
// The null string is returned only if the cached version has not been set.
String GetVersion(DatabaseGuid guid) const EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
mutex_.AssertAcquired();
- return guid_to_version_.at(guid).IsolatedCopy();
+
+ String version;
+ auto guid_to_version_it = guid_to_version_.find(guid);
+ if (guid_to_version_it != guid_to_version_.end()) {
+ version = guid_to_version_it->value;
+ DCHECK(version);
+ }
+ return version.IsolatedCopy();
}
// Updates the cached version of a database.
@@ -234,6 +248,7 @@ Database::Database(DatabaseContext* database_context,
database_authorizer_(kInfoTableName),
transaction_in_progress_(false),
is_transaction_queue_enabled_(true),
+ did_try_to_count_third_party_transaction_(false),
feature_handle_for_scheduler_(
database_context->GetExecutionContext()
->GetScheduler()
@@ -821,6 +836,13 @@ void Database::RunTransaction(
return;
DCHECK(GetExecutionContext()->IsContextThread());
+
+ if (!did_try_to_count_third_party_transaction_) {
+ GetExecutionContext()->CountUseOnlyInCrossSiteIframe(
+ WebFeature::kReadOrWriteWebDatabaseThirdPartyContext);
+ did_try_to_count_third_party_transaction_ = true;
+ }
+
// FIXME: Rather than passing errorCallback to SQLTransaction and then
// sometimes firing it ourselves, this code should probably be pushed down
// into Database so that we only create the SQLTransaction if we're
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database.h b/chromium/third_party/blink/renderer/modules/webdatabase/database.h
index dcd531647e7..c1c2646857b 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database.h
@@ -194,6 +194,9 @@ class Database final : public ScriptWrappable {
bool transaction_in_progress_;
bool is_transaction_queue_enabled_;
+ // Gates a UKM counter to execute once per database instance.
+ bool did_try_to_count_third_party_transaction_;
+
// Disable BackForwardCache when using WebDatabase feature, because we do not
// handle the state inside the portal after putting the page in cache.
FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database_authorizer.cc b/chromium/third_party/blink/renderer/modules/webdatabase/database_authorizer.cc
index fcf809de244..73fb7c35ee4 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database_authorizer.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database_authorizer.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#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/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
namespace blink {
@@ -65,22 +65,58 @@ const FunctionNameList& AllowedFunctions() {
({
// SQLite functions used to help implement some operations
// ALTER TABLE helpers
- "sqlite_rename_column", "sqlite_rename_table", "sqlite_rename_test",
+ "sqlite_rename_column",
+ "sqlite_rename_table",
+ "sqlite_rename_test",
+ "sqlite_rename_quotefix",
// GLOB helpers
"glob",
// SQLite core functions
- "abs", "changes", "coalesce", "glob", "ifnull", "hex",
- "last_insert_rowid", "length", "like", "lower", "ltrim", "max", "min",
- "nullif", "quote", "replace", "round", "rtrim", "soundex",
- "sqlite_source_id", "sqlite_version", "substr", "total_changes",
- "trim", "typeof", "upper", "zeroblob",
+ "abs",
+ "changes",
+ "coalesce",
+ "glob",
+ "ifnull",
+ "hex",
+ "last_insert_rowid",
+ "length",
+ "like",
+ "lower",
+ "ltrim",
+ "max",
+ "min",
+ "nullif",
+ "quote",
+ "replace",
+ "round",
+ "rtrim",
+ "soundex",
+ "sqlite_source_id",
+ "sqlite_version",
+ "substr",
+ "total_changes",
+ "trim",
+ "typeof",
+ "upper",
+ "zeroblob",
// SQLite date and time functions
- "date", "time", "datetime", "julianday", "strftime",
+ "date",
+ "time",
+ "datetime",
+ "julianday",
+ "strftime",
// SQLite aggregate functions
// max() and min() are already in the list
- "avg", "count", "group_concat", "sum", "total",
+ "avg",
+ "count",
+ "group_concat",
+ "sum",
+ "total",
// SQLite FTS functions
- "match", "snippet", "offsets", "optimize",
+ "match",
+ "snippet",
+ "offsets",
+ "optimize",
// SQLite ICU functions
// like(), lower() and upper() are already in the list
"regexp",
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 9193c0e7417..7fe8148006f 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc
@@ -63,7 +63,8 @@ DatabaseContext* DatabaseManager::ExistingDatabaseContextFor(
DCHECK_LE(database_context_registered_count_,
database_context_instance_count_);
#endif
- return context_map_->at(context);
+ auto it = context_map_->find(context);
+ return (it == context_map_->end()) ? nullptr : it->value;
}
DatabaseContext* DatabaseManager::DatabaseContextFor(
@@ -85,7 +86,7 @@ void DatabaseManager::RegisterDatabaseContext(
void DatabaseManager::UnregisterDatabaseContext(
DatabaseContext* database_context) {
ExecutionContext* context = database_context->GetExecutionContext();
- DCHECK(context_map_->at(context));
+ DCHECK(context_map_->Contains(context));
#if DCHECK_IS_ON()
database_context_registered_count_--;
#endif
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database_tracker.cc b/chromium/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
index 357c3ddaf73..776f229eb43 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
@@ -89,17 +89,26 @@ void DatabaseTracker::AddOpenDatabase(Database* database) {
open_database_map_ = std::make_unique<DatabaseOriginMap>();
String origin_string = database->GetSecurityOrigin()->ToRawString();
- DatabaseNameMap* name_map = open_database_map_->at(origin_string);
- if (!name_map) {
+
+ DatabaseNameMap* name_map;
+ auto open_database_map_it = open_database_map_->find(origin_string);
+ if (open_database_map_it == open_database_map_->end()) {
name_map = new DatabaseNameMap();
open_database_map_->Set(origin_string, name_map);
+ } else {
+ name_map = open_database_map_it->value;
+ DCHECK(name_map);
}
- String name(database->StringIdentifier());
- DatabaseSet* database_set = name_map->at(name);
- if (!database_set) {
+ String name = database->StringIdentifier();
+ DatabaseSet* database_set;
+ auto name_map_it = name_map->find(name);
+ if (name_map_it == name_map->end()) {
database_set = new DatabaseSet();
name_map->Set(name, database_set);
+ } else {
+ database_set = name_map_it->value;
+ DCHECK(database_set);
}
database_set->insert(database);
@@ -110,15 +119,21 @@ void DatabaseTracker::RemoveOpenDatabase(Database* database) {
MutexLocker open_database_map_lock(open_database_map_guard_);
String origin_string = database->GetSecurityOrigin()->ToRawString();
DCHECK(open_database_map_);
- DatabaseNameMap* name_map = open_database_map_->at(origin_string);
- if (!name_map)
+ auto open_database_map_it = open_database_map_->find(origin_string);
+ if (open_database_map_it == open_database_map_->end())
return;
- String name(database->StringIdentifier());
- DatabaseSet* database_set = name_map->at(name);
- if (!database_set)
+ DatabaseNameMap* name_map = open_database_map_it->value;
+ DCHECK(name_map);
+
+ String name = database->StringIdentifier();
+ auto name_map_it = name_map->find(name);
+ if (name_map_it == name_map->end())
return;
+ DatabaseSet* database_set = name_map_it->value;
+ DCHECK(database_set);
+
DatabaseSet::iterator found = database_set->find(database);
if (found == database_set->end())
return;
@@ -175,14 +190,20 @@ void DatabaseTracker::CloseDatabasesImmediately(const SecurityOrigin* origin,
if (!open_database_map_)
return;
- DatabaseNameMap* name_map = open_database_map_->at(origin_string);
- if (!name_map)
+ auto open_database_map_it = open_database_map_->find(origin_string);
+ if (open_database_map_it == open_database_map_->end())
return;
- DatabaseSet* database_set = name_map->at(name);
- if (!database_set)
+ DatabaseNameMap* name_map = open_database_map_it->value;
+ DCHECK(name_map);
+
+ auto name_map_it = name_map->find(name);
+ if (name_map_it == name_map->end())
return;
+ DatabaseSet* database_set = name_map_it->value;
+ DCHECK(database_set);
+
// We have to call closeImmediately() on the context thread.
for (DatabaseSet::iterator it = database_set->begin();
it != database_set->end(); ++it) {
@@ -219,14 +240,21 @@ void DatabaseTracker::CloseOneDatabaseImmediately(const String& origin_string,
if (!open_database_map_)
return;
- DatabaseNameMap* name_map = open_database_map_->at(origin_string);
- if (!name_map)
+ auto open_database_map_it = open_database_map_->find(origin_string);
+ if (open_database_map_it == open_database_map_->end())
return;
- DatabaseSet* database_set = name_map->at(name);
- if (!database_set)
+ DatabaseNameMap* name_map = open_database_map_it->value;
+ DCHECK(name_map);
+
+ String name = database->StringIdentifier();
+ auto name_map_it = name_map->find(name);
+ if (name_map_it == name_map->end())
return;
+ DatabaseSet* database_set = name_map_it->value;
+ DCHECK(database_set);
+
if (!database_set->Contains(database))
return;
}
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 a1b76414783..c72a0c73774 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,7 +26,10 @@
#include "third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h"
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_database_callback.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/web_feature.h"
#include "third_party/blink/renderer/modules/webdatabase/database.h"
@@ -67,8 +70,15 @@ Database* DOMWindowWebDatabase::openDatabase(
if (window.GetSecurityOrigin()->IsLocal())
UseCounter::Count(window, WebFeature::kFileAccessedDatabase);
- window.CountUseOnlyInCrossSiteIframe(
- WebFeature::kOpenWebDatabaseThirdPartyContext);
+ if (window.IsCrossSiteSubframeIncludingScheme() &&
+ IsThirdPartyContextWebSQLDeprecated()) {
+ Deprecation::CountDeprecation(
+ &window, WebFeature::kOpenWebDatabaseThirdPartyContext);
+ } else {
+ // We still want to count usage even if deprecation is off.
+ window.CountUseOnlyInCrossSiteIframe(
+ WebFeature::kOpenWebDatabaseThirdPartyContext);
+ }
String error_message;
database = db_manager.OpenDatabase(&window, name, version, display_name,
@@ -85,4 +95,9 @@ Database* DOMWindowWebDatabase::openDatabase(
return database;
}
+bool DOMWindowWebDatabase::IsThirdPartyContextWebSQLDeprecated() {
+ return base::FeatureList::IsEnabled(
+ features::kDeprecateThirdPartyContextWebSQL);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h b/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h
index cfa9ac4981f..ab2536e06bb 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h
@@ -27,6 +27,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_DOM_WINDOW_WEB_DATABASE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_DOM_WINDOW_WEB_DATABASE_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/forward.h"
@@ -37,7 +38,7 @@ class ExceptionState;
class LocalDOMWindow;
class V8DatabaseCallback;
-class DOMWindowWebDatabase {
+class MODULES_EXPORT DOMWindowWebDatabase {
STATIC_ONLY(DOMWindowWebDatabase);
public:
@@ -54,6 +55,7 @@ class DOMWindowWebDatabase {
uint32_t estimated_size,
V8DatabaseCallback* creation_callback,
ExceptionState&);
+ static bool IsThirdPartyContextWebSQLDeprecated();
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database_test.cc b/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database_test.cc
new file mode 100644
index 00000000000..08e46771619
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database_test.cc
@@ -0,0 +1,22 @@
+// 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/webdatabase/dom_window_web_database.h"
+
+#include "base/feature_list.h"
+#include "base/test/scoped_feature_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace blink {
+
+TEST(DOMWindowWebDatabaseTest, IsThirdPartyContextWebSQLDeprecated) {
+ EXPECT_EQ(DOMWindowWebDatabase::IsThirdPartyContextWebSQLDeprecated(), false);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kDeprecateThirdPartyContextWebSQL);
+ EXPECT_EQ(DOMWindowWebDatabase::IsThirdPartyContextWebSQLDeprecated(), true);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/idls.gni b/chromium/third_party/blink/renderer/modules/webdatabase/idls.gni
deleted file mode 100644
index 3877456b354..00000000000
--- a/chromium/third_party/blink/renderer/modules/webdatabase/idls.gni
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "database.idl",
- "sql_error.idl",
- "sql_result_set.idl",
- "sql_result_set_row_list.idl",
- "sql_statement_callback.idl",
- "sql_statement_error_callback.idl",
- "sql_transaction.idl",
- "sql_transaction_callback.idl",
- "sql_transaction_error_callback.idl",
-]
-
-modules_dependency_idl_files = [ "window_web_database.idl" ]
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 5476f2c40c1..e19c458aff3 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
@@ -28,7 +28,7 @@
#include "third_party/blink/renderer/modules/webdatabase/sql_transaction.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
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 82835c01f0b..b5464252a82 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
@@ -30,7 +30,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/modules/webdatabase/database.h"
#include "third_party/blink/renderer/modules/webdatabase/database_authorizer.h"
#include "third_party/blink/renderer/modules/webdatabase/database_context.h"
diff --git a/chromium/third_party/blink/renderer/modules/webgl/DEPS b/chromium/third_party/blink/renderer/modules/webgl/DEPS
index 4e7a58fdd72..f890dcc095b 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webgl/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+gpu/command_buffer/client/gles2_interface.h",
"+gpu/command_buffer/client/raster_interface.h",
"+gpu/command_buffer/common/capabilities.h",
+ "+gpu/config/gpu_driver_bug_workaround_type.h",
"+gpu/config/gpu_feature_info.h",
"+media/base/video_frame.h",
"+media/base/wait_and_replace_sync_token_client.h",
diff --git a/chromium/third_party/blink/renderer/modules/webgl/OWNERS b/chromium/third_party/blink/renderer/modules/webgl/OWNERS
index 2a09b594120..5d487f47b17 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/webgl/OWNERS
@@ -1,5 +1,4 @@
bajones@chromium.org
kainino@chromium.org
kbr@chromium.org
-zmo@chromium.org
jdarpinian@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/webgl/angle_instanced_arrays.h b/chromium/third_party/blink/renderer/modules/webgl/angle_instanced_arrays.h
index 1cce2f5320b..1e3d46a54ea 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/angle_instanced_arrays.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/angle_instanced_arrays.h
@@ -31,6 +31,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_ANGLE_INSTANCED_ARRAYS_H_
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_blend_min_max.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_blend_min_max.cc
index 66bdf90ee68..ea0f01c6cd2 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_blend_min_max.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_blend_min_max.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_blend_min_max.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTBlendMinMax::EXTBlendMinMax(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_float.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_float.cc
index ff2aed72e07..d93fab0b554 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_float.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_float.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_color_buffer_float.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTColorBufferFloat::EXTColorBufferFloat(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_half_float.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_half_float.cc
index 07dde691d60..a662531b079 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_half_float.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_color_buffer_half_float.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_color_buffer_half_float.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTColorBufferHalfFloat::EXTColorBufferHalfFloat(
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.h b/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.h
index 402b4e22185..b488b94a240 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_float_blend.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_float_blend.cc
index ab91c001841..ac0f1994770 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_float_blend.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_float_blend.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_float_blend.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTFloatBlend::EXTFloatBlend(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_frag_depth.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_frag_depth.cc
index ccfc6e5f9d1..c0c2f4cedba 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_frag_depth.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_frag_depth.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_frag_depth.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTFragDepth::EXTFragDepth(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_shader_texture_lod.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_shader_texture_lod.cc
index 61c435ced80..2c51b82e428 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_shader_texture_lod.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_shader_texture_lod.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_shader_texture_lod.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTShaderTextureLOD::EXTShaderTextureLOD(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.cc
index 8ac4eb74d22..8e6957d13b1 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_texture_norm_16.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_texture_norm_16.cc
index 5fc71e9ad30..4086d1dc350 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_texture_norm_16.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_texture_norm_16.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/ext_texture_norm_16.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
EXTTextureNorm16::EXTTextureNorm16(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/gl_string_query.h b/chromium/third_party/blink/renderer/modules/webgl/gl_string_query.h
index 70aa8151ee0..6cac386b9b9 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/gl_string_query.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/gl_string_query.h
@@ -7,6 +7,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/idls.gni b/chromium/third_party/blink/renderer/modules/webgl/idls.gni
deleted file mode 100644
index 8ad7b1cdedc..00000000000
--- a/chromium/third_party/blink/renderer/modules/webgl/idls.gni
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/blink/renderer/config.gni")
-
-# Note: WebGL extensions are the most frequently added IDL files and
-# don't go through Blink's Intent to Ship process. Instead, these are
-# discussed among all browser vendors within the WebGL working group
-# as defined by the process here:
-#
-# https://www.khronos.org/registry/webgl/extensions/
-#
-# and only enabled in any browser by default once all browsers are in
-# agreement that the extension is ready to ship.
-
-modules_idl_files = [
- "angle_instanced_arrays.idl",
- "ext_blend_min_max.idl",
- "ext_color_buffer_float.idl",
- "ext_color_buffer_half_float.idl",
- "ext_disjoint_timer_query.idl",
- "ext_disjoint_timer_query_webgl2.idl",
- "ext_float_blend.idl",
- "ext_frag_depth.idl",
- "ext_shader_texture_lod.idl",
- "ext_srgb.idl",
- "ext_texture_compression_bptc.idl",
- "ext_texture_compression_rgtc.idl",
- "ext_texture_filter_anisotropic.idl",
- "ext_texture_norm_16.idl",
- "khr_parallel_shader_compile.idl",
- "oes_draw_buffers_indexed.idl",
- "oes_element_index_uint.idl",
- "oes_fbo_render_mipmap.idl",
- "oes_standard_derivatives.idl",
- "oes_texture_float.idl",
- "oes_texture_float_linear.idl",
- "oes_texture_half_float.idl",
- "oes_texture_half_float_linear.idl",
- "oes_vertex_array_object.idl",
- "ovr_multiview_2.idl",
- "webgl2_rendering_context.idl",
- "webgl_active_info.idl",
- "webgl_buffer.idl",
- "webgl_color_buffer_float.idl",
- "webgl_compressed_texture_astc.idl",
- "webgl_compressed_texture_etc.idl",
- "webgl_compressed_texture_etc1.idl",
- "webgl_compressed_texture_pvrtc.idl",
- "webgl_compressed_texture_s3tc.idl",
- "webgl_compressed_texture_s3tc_srgb.idl",
- "webgl_context_event.idl",
- "webgl_debug_renderer_info.idl",
- "webgl_debug_shaders.idl",
- "webgl_depth_texture.idl",
- "webgl_draw_buffers.idl",
- "webgl_draw_instanced_base_vertex_base_instance.idl",
- "webgl_framebuffer.idl",
- "webgl_lose_context.idl",
- "webgl_multi_draw_instanced_base_vertex_base_instance.idl",
- "webgl_multi_draw.idl",
- "webgl_program.idl",
- "webgl_query.idl",
- "webgl_renderbuffer.idl",
- "webgl_rendering_context.idl",
- "webgl_sampler.idl",
- "webgl_shader.idl",
- "webgl_shader_precision_format.idl",
- "webgl_sync.idl",
- "webgl_texture.idl",
- "webgl_timer_query_ext.idl",
- "webgl_transform_feedback.idl",
- "webgl_uniform_location.idl",
- "webgl_vertex_array_object.idl",
- "webgl_vertex_array_object_oes.idl",
- "webgl_video_texture.idl",
- "webgl_webcodecs_video_frame.idl",
-]
-
-modules_dictionary_idl_files = [
- "webgl_context_attributes.idl",
- "webgl_context_event_init.idl",
- "webgl_webcodecs_texture_info.idl",
- "webgl_webcodecs_video_frame_handle.idl",
-]
-
-modules_dependency_idl_files = [
- "webgl2_rendering_context_base.idl",
- "webgl_rendering_context_base.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc b/chromium/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc
index 792e3657f82..6a5a8f6535a 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
#include <thread>
#include "gpu/command_buffer/client/gles2_interface.h"
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.cc
index edcfddaedb2..656089b01b3 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESDrawBuffersIndexed::OESDrawBuffersIndexed(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.h b/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.h
index 79778d7a0d0..f77822c9076 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_draw_buffers_indexed.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_OES_DRAW_BUFFERS_INDEXED_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_OES_DRAW_BUFFERS_INDEXED_H_
-// #include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_element_index_uint.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_element_index_uint.cc
index 1bd7339759a..6f893dbab6f 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_element_index_uint.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_element_index_uint.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_element_index_uint.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESElementIndexUint::OESElementIndexUint(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_fbo_render_mipmap.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_fbo_render_mipmap.cc
index c5649434665..1ce923e0c4c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_fbo_render_mipmap.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_fbo_render_mipmap.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_fbo_render_mipmap.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESFboRenderMipmap::OESFboRenderMipmap(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_standard_derivatives.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_standard_derivatives.cc
index 925c825e689..2df0003586f 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_standard_derivatives.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_standard_derivatives.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_standard_derivatives.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESStandardDerivatives::OESStandardDerivatives(
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float.cc
index c7aebe23305..b3b88f76166 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_texture_float.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESTextureFloat::OESTextureFloat(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float_linear.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float_linear.cc
index c9c667e0faf..f29b0c0031a 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float_linear.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_float_linear.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_texture_float_linear.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float.cc
index b12d2d0619e..7afc4fdfc28 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_texture_half_float.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float_linear.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float_linear.cc
index af1e1aa3237..5a8df149dc9 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float_linear.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_texture_half_float_linear.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/oes_texture_half_float_linear.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.h b/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.h
index f3f1e5f7f78..a3539bf6aa9 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_OES_VERTEX_ARRAY_OBJECT_H_
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ovr_multiview_2.h b/chromium/third_party/blink/renderer/modules/webgl/ovr_multiview_2.h
index 3a2f16c74e6..196e8d5d3d3 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ovr_multiview_2.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/ovr_multiview_2.h
@@ -6,9 +6,12 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_OVR_MULTIVIEW_2_H_
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
+class WebGLTexture;
+
class OVRMultiview2 final : public WebGLExtension {
DEFINE_WRAPPERTYPEINFO();
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 154a495005d..b3ea0f1cb76 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
@@ -9,8 +9,6 @@
#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/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -111,8 +109,6 @@ CanvasRenderingContext* WebGL2RenderingContext::Factory::Create(
rendering_context->InitializeNewContext();
rendering_context->RegisterContextExtensions();
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::kWebgl2);
return rendering_context;
}
@@ -133,8 +129,6 @@ WebGL2RenderingContext::WebGL2RenderingContext(
requested_attributes,
Platform::kWebGL2ContextType) {}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* WebGL2RenderingContext::AsV8RenderingContext() {
return MakeGarbageCollected<V8RenderingContext>(this);
}
@@ -144,20 +138,6 @@ WebGL2RenderingContext::AsV8OffscreenRenderingContext() {
return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void WebGL2RenderingContext::SetCanvasGetContextResult(
- RenderingContext& result) {
- result.SetWebGL2RenderingContext(this);
-}
-
-void WebGL2RenderingContext::SetOffscreenCanvasGetContextResult(
- OffscreenRenderingContext& result) {
- result.SetWebGL2RenderingContext(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
ImageBitmap* WebGL2RenderingContext::TransferToImageBitmap(
ScriptState* script_state) {
return TransferToImageBitmapBase(script_state);
@@ -167,7 +147,9 @@ void WebGL2RenderingContext::RegisterContextExtensions() {
// Register extensions.
RegisterExtension(ext_color_buffer_float_);
RegisterExtension(ext_color_buffer_half_float_);
- RegisterExtension(ext_disjoint_timer_query_web_gl2_);
+ RegisterExtension(
+ ext_disjoint_timer_query_web_gl2_,
+ TimerQueryExtensionsEnabled() ? kApprovedExtension : kDeveloperExtension);
RegisterExtension(ext_float_blend_);
RegisterExtension(ext_texture_compression_bptc_);
RegisterExtension(ext_texture_compression_rgtc_);
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 6d6988d0629..d82df5eaca1 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
@@ -67,13 +67,8 @@ class WebGL2RenderingContext : public WebGL2RenderingContextBase {
ImageBitmap* TransferToImageBitmap(ScriptState*) final;
String ContextName() const override { return "WebGL2RenderingContext"; }
void RegisterContextExtensions() override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* AsV8RenderingContext() final;
V8OffscreenRenderingContext* AsV8OffscreenRenderingContext() final;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetCanvasGetContextResult(RenderingContext&) final;
- void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) final;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.idl
index 1b5f96ebd55..e98e0f12ce1 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.idl
@@ -5,6 +5,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7
[
+ ActiveScriptWrappable,
DoNotCheckConstants,
Exposed=(Window,Worker)
] interface WebGL2RenderingContext { };
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 02015211ecd..2f3348e5bd8 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
@@ -6,12 +6,13 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/numerics/checked_math.h"
#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
+#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/bindings/modules/v8/webgl_any.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
@@ -412,7 +413,8 @@ void WebGL2RenderingContextBase::blitFramebuffer(GLint src_x0,
GetDrawingBuffer(), user_framebuffer_bound);
ContextGL()->BlitFramebufferCHROMIUM(src_x0, src_y0, src_x1, src_y1, dst_x0,
dst_y0, dst_x1, dst_y1, mask, filter);
- MarkContextChanged(kCanvasChanged);
+ MarkContextChanged(kCanvasChanged,
+ CanvasPerformanceMonitor::DrawType::kOther);
}
bool WebGL2RenderingContextBase::ValidateTexFuncLayer(const char* function_name,
@@ -836,7 +838,7 @@ void WebGL2RenderingContextBase::readPixels(GLint x,
// Due to WebGL's same-origin restrictions, it is not possible to
// taint the origin using the WebGL API.
- DCHECK(canvas()->OriginClean());
+ DCHECK(Host()->OriginClean());
if (!ValidateValueFitNonNegInt32("readPixels", "offset", offset))
return;
@@ -3620,7 +3622,7 @@ void WebGL2RenderingContextBase::drawArraysInstanced(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawArrays);
ContextGL()->DrawArraysInstancedANGLE(mode, first, count, instance_count);
RecordUKMCanvasDrawnToAtFirstDrawCall();
}
@@ -3641,7 +3643,7 @@ void WebGL2RenderingContextBase::drawElementsInstanced(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawElements);
ContextGL()->DrawElementsInstancedANGLE(
mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)),
instance_count);
@@ -3665,7 +3667,7 @@ void WebGL2RenderingContextBase::drawRangeElements(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawElements);
ContextGL()->DrawRangeElements(
mode, start, end, count, type,
reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
@@ -3858,7 +3860,8 @@ void WebGL2RenderingContextBase::clearBufferfv(
// if they're called against the default back buffer. If support for
// extended canvas color spaces is added, this call might need to be
// added to the other versions.
- MarkContextChanged(kCanvasChanged);
+ MarkContextChanged(kCanvasChanged,
+ CanvasPerformanceMonitor::DrawType::kOther);
UpdateBuffersToAutoClear(kClearBufferfv, buffer, drawbuffer);
}
@@ -3884,7 +3887,8 @@ void WebGL2RenderingContextBase::clearBufferfv(GLenum buffer,
// if they're called against the default back buffer. If support for
// extended canvas color spaces is added, this call might need to be
// added to the other versions.
- MarkContextChanged(kCanvasChanged);
+ MarkContextChanged(kCanvasChanged,
+ CanvasPerformanceMonitor::DrawType::kOther);
UpdateBuffersToAutoClear(kClearBufferfv, buffer, drawbuffer);
}
@@ -3898,7 +3902,8 @@ void WebGL2RenderingContextBase::clearBufferfi(GLenum buffer,
ContextGL()->ClearBufferfi(buffer, drawbuffer, depth, stencil);
// This might have been used to clear the depth and stencil buffers
// of the default back buffer.
- MarkContextChanged(kCanvasChanged);
+ MarkContextChanged(kCanvasChanged,
+ CanvasPerformanceMonitor::DrawType::kOther);
UpdateBuffersToAutoClear(kClearBufferfi, buffer, drawbuffer);
}
@@ -4772,7 +4777,8 @@ bool WebGL2RenderingContextBase::ValidateTransformFeedbackPrimitiveMode(
}
}
-void WebGL2RenderingContextBase::OnBeforeDrawCall() {
+void WebGL2RenderingContextBase::OnBeforeDrawCall(
+ CanvasPerformanceMonitor::DrawType draw_type) {
if (transform_feedback_binding_->active() &&
!transform_feedback_binding_->paused()) {
for (WebGLBuffer* buffer :
@@ -4785,7 +4791,7 @@ void WebGL2RenderingContextBase::OnBeforeDrawCall() {
}
}
- WebGLRenderingContextBase::OnBeforeDrawCall();
+ WebGLRenderingContextBase::OnBeforeDrawCall(draw_type);
}
void WebGL2RenderingContextBase::bindBufferBase(GLenum target,
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 c51b1c1e3ca..f293827aefd 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
@@ -966,7 +966,7 @@ class WebGL2RenderingContextBase : public WebGLRenderingContextBase {
bool ValidateTransformFeedbackPrimitiveMode(const char* function_name,
GLenum primitive_mode);
- void OnBeforeDrawCall() override;
+ void OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType) override;
/* Uniform Buffer Objects and Transform Feedback Buffers */
void bindBufferBase(GLenum, GLuint, WebGLBuffer*);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_color_buffer_float.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_color_buffer_float.cc
index 32c682af3aa..8f57dea9e39 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_color_buffer_float.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_color_buffer_float.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/webgl_color_buffer_float.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
WebGLColorBufferFloat::WebGLColorBufferFloat(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.cc
index cf248ef6cc3..d7f17d39751 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
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 c5295832b4d..9e94ef3d74a 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
@@ -27,11 +27,9 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_CONTEXT_GROUP_H_
#include "base/macros.h"
-#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/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 {
@@ -39,6 +37,7 @@ class WebGLContextGroup final : public GarbageCollected<WebGLContextGroup>,
public NameClient {
public:
WebGLContextGroup();
+ ~WebGLContextGroup() final = default;
void AddContext(WebGLRenderingContextBase*);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_depth_texture.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_depth_texture.cc
index 8ccadaaa730..3583637b815 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_depth_texture.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_depth_texture.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/webgl_depth_texture.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContextBase* context)
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.cc
index 066b69e4b06..41010b5aa3f 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.cc
@@ -27,6 +27,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/renderer/modules/webgl/webgl_framebuffer.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h
index f634a1d79bb..b7f8df6dc1c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h
@@ -26,8 +26,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_DRAW_BUFFERS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_DRAW_BUFFERS_H_
-#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.cc
index 9a4cc5556f0..1660ef6c65c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.h
index 047f1c48e17..dd8fb3a4d34 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_draw_instanced_base_vertex_base_instance.h
@@ -26,8 +26,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_DRAW_INSTANCED_BASE_VERTEX_BASE_INSTANCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_DRAW_INSTANCED_BASE_VERTEX_BASE_INSTANCE_H_
-#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.cc
index 86d142f37fa..faf662f0414 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+
namespace blink {
WebGLExtensionScopedContext::WebGLExtensionScopedContext(
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.h
index ed3e7ef64b5..2b2ff2c8e30 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_extension.h
@@ -27,14 +27,15 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_EXTENSION_H_
#include "base/macros.h"
-#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension_name.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/heap/handle.h"
namespace blink {
+class WebGLExtension;
+class WebGLRenderingContextBase;
+
class WebGLExtensionScopedContext final {
STACK_ALLOCATED();
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 f579f7ee591..444bd0258ca 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
@@ -48,6 +48,8 @@ class WebGLFramebuffer final : public WebGLContextObject {
class WebGLAttachment : public GarbageCollected<WebGLAttachment>,
public NameClient {
public:
+ ~WebGLAttachment() override = default;
+
virtual WebGLSharedObject* Object() const = 0;
virtual bool IsSharedObject(WebGLSharedObject*) const = 0;
virtual bool Valid() const = 0;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc
index 787111f1499..5a0c97d0001 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h
index 0c3996be38d..1adf50217e5 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h
@@ -5,10 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_H_
-#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -23,61 +21,36 @@ class WebGLMultiDraw final : public WebGLExtension,
explicit WebGLMultiDraw(WebGLRenderingContextBase*);
WebGLExtensionName GetName() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawArraysWEBGL(GLenum mode,
- const V8UnionInt32ArrayOrLongSequence* firstsList,
- GLuint firstsOffset,
- const V8UnionInt32ArrayOrLongSequence* countsList,
- GLuint countsOffset,
- GLsizei drawcount) {
- multiDrawArraysImpl(mode, MakeSpan(firstsList), firstsOffset,
- MakeSpan(countsList), countsOffset, drawcount);
- }
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawArraysWEBGL(GLenum mode,
- Int32ArrayOrLongSequence firstsList,
- GLuint firstsOffset,
- Int32ArrayOrLongSequence countsList,
- GLuint countsOffset,
- GLsizei drawcount) {
+ void multiDrawArraysWEBGL(
+ GLenum mode,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* firstsList,
+ GLuint firstsOffset,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* countsList,
+ GLuint countsOffset,
+ GLsizei drawcount) {
multiDrawArraysImpl(mode, MakeSpan(firstsList), firstsOffset,
MakeSpan(countsList), countsOffset, drawcount);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void multiDrawElementsWEBGL(
GLenum mode,
- const V8UnionInt32ArrayOrLongSequence* countsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* countsList,
GLuint countsOffset,
GLenum type,
- const V8UnionInt32ArrayOrLongSequence* offsetsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* offsetsList,
GLuint offsetsOffset,
GLsizei drawcount) {
multiDrawElementsImpl(mode, MakeSpan(countsList), countsOffset, type,
MakeSpan(offsetsList), offsetsOffset, drawcount);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawElementsWEBGL(GLenum mode,
- Int32ArrayOrLongSequence countsList,
- GLuint countsOffset,
- GLenum type,
- Int32ArrayOrLongSequence offsetsList,
- GLuint offsetsOffset,
- GLsizei drawcount) {
- multiDrawElementsImpl(mode, MakeSpan(countsList), countsOffset, type,
- MakeSpan(offsetsList), offsetsOffset, drawcount);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void multiDrawArraysInstancedWEBGL(
GLenum mode,
- const V8UnionInt32ArrayOrLongSequence* firstsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* firstsList,
GLuint firstsOffset,
- const V8UnionInt32ArrayOrLongSequence* countsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* countsList,
GLuint countsOffset,
- const V8UnionInt32ArrayOrLongSequence* instanceCountsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* instanceCountsList,
GLuint instanceCountsOffset,
GLsizei drawcount) {
multiDrawArraysInstancedImpl(mode, MakeSpan(firstsList), firstsOffset,
@@ -85,48 +58,15 @@ class WebGLMultiDraw final : public WebGLExtension,
MakeSpan(instanceCountsList),
instanceCountsOffset, drawcount);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawArraysInstancedWEBGL(
- GLenum mode,
- Int32ArrayOrLongSequence firstsList,
- GLuint firstsOffset,
- Int32ArrayOrLongSequence countsList,
- GLuint countsOffset,
- Int32ArrayOrLongSequence instanceCountsList,
- GLuint instanceCountsOffset,
- GLsizei drawcount) {
- multiDrawArraysInstancedImpl(mode, MakeSpan(firstsList), firstsOffset,
- MakeSpan(countsList), countsOffset,
- MakeSpan(instanceCountsList),
- instanceCountsOffset, drawcount);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawElementsInstancedWEBGL(
- GLenum mode,
- const V8UnionInt32ArrayOrLongSequence* countsList,
- GLuint countsOffset,
- GLenum type,
- const V8UnionInt32ArrayOrLongSequence* offsetsList,
- GLuint offsetsOffset,
- const V8UnionInt32ArrayOrLongSequence* instanceCountsList,
- GLuint instanceCountsOffset,
- GLsizei drawcount) {
- multiDrawElementsInstancedImpl(mode, MakeSpan(countsList), countsOffset,
- type, MakeSpan(offsetsList), offsetsOffset,
- MakeSpan(instanceCountsList),
- instanceCountsOffset, drawcount);
- }
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void multiDrawElementsInstancedWEBGL(
GLenum mode,
- Int32ArrayOrLongSequence countsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* countsList,
GLuint countsOffset,
GLenum type,
- Int32ArrayOrLongSequence offsetsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* offsetsList,
GLuint offsetsOffset,
- Int32ArrayOrLongSequence instanceCountsList,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* instanceCountsList,
GLuint instanceCountsOffset,
GLsizei drawcount) {
multiDrawElementsInstancedImpl(mode, MakeSpan(countsList), countsOffset,
@@ -134,7 +74,6 @@ class WebGLMultiDraw final : public WebGLExtension,
MakeSpan(instanceCountsList),
instanceCountsOffset, drawcount);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
void multiDrawArraysImpl(GLenum mode,
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl
index 138db35c3c8..85f4af95aac 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl
@@ -7,36 +7,36 @@
[LegacyNoInterfaceObject]
interface WebGLMultiDraw {
void multiDrawArraysWEBGL(GLenum mode,
- (Int32Array or sequence<long>) firstsList,
+ ([AllowShared] Int32Array or sequence<long>) firstsList,
GLuint firstsOffset,
- (Int32Array or sequence<long>) countsList,
+ ([AllowShared] Int32Array or sequence<long>) countsList,
GLuint countsOffset,
GLsizei drawcount);
void multiDrawElementsWEBGL(GLenum mode,
- (Int32Array or sequence<long>) countsList,
+ ([AllowShared] Int32Array or sequence<long>) countsList,
GLuint countsOffset,
GLenum type,
- (Int32Array or sequence<long>) offsetsList,
+ ([AllowShared] Int32Array or sequence<long>) offsetsList,
GLuint offsetsOffset,
GLsizei drawcount);
void multiDrawArraysInstancedWEBGL(GLenum mode,
- (Int32Array or sequence<long>) firstsList,
+ ([AllowShared] Int32Array or sequence<long>) firstsList,
GLuint firstsOffset,
- (Int32Array or sequence<long>) countsList,
+ ([AllowShared] Int32Array or sequence<long>) countsList,
GLuint countsOffset,
- (Int32Array or sequence<long>) instanceCountsList,
+ ([AllowShared] Int32Array or sequence<long>) instanceCountsList,
GLuint instanceCountsOffset,
GLsizei drawcount);
void multiDrawElementsInstancedWEBGL(GLenum mode,
- (Int32Array or sequence<long>) countsList,
+ ([AllowShared] Int32Array or sequence<long>) countsList,
GLuint countsOffset,
GLenum type,
- (Int32Array or sequence<long>) offsetsList,
+ ([AllowShared] Int32Array or sequence<long>) offsetsList,
GLuint offsetsOffset,
- (Int32Array or sequence<long>) instanceCountsList,
+ ([AllowShared] Int32Array or sequence<long>) instanceCountsList,
GLuint instanceCountsOffset,
GLsizei drawcount);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
index e51f2c91513..6c32a9d4347 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_int32array_longsequence.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_uint32array_unsignedlongsequence.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_int32arrayallowshared_longsequence.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_uint32arrayallowshared_unsignedlongsequence.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
namespace blink {
@@ -45,45 +46,35 @@ bool WebGLMultiDrawCommon::ValidateArray(WebGLExtensionScopedContext* scoped,
return true;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
base::span<const int32_t> WebGLMultiDrawCommon::MakeSpan(
- const V8UnionInt32ArrayOrLongSequence* array) {
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* array) {
DCHECK(array);
switch (array->GetContentType()) {
- case V8UnionInt32ArrayOrLongSequence::ContentType::kInt32Array:
- return base::span<const int32_t>(array->GetAsInt32Array()->Data(),
- array->GetAsInt32Array()->length());
- case V8UnionInt32ArrayOrLongSequence::ContentType::kLongSequence:
+ case V8UnionInt32ArrayAllowSharedOrLongSequence::ContentType::
+ kInt32ArrayAllowShared:
+ return base::span<const int32_t>(
+ array->GetAsInt32ArrayAllowShared()->DataMaybeShared(),
+ array->GetAsInt32ArrayAllowShared()->length());
+ case V8UnionInt32ArrayAllowSharedOrLongSequence::ContentType::kLongSequence:
return base::span<const int32_t>(array->GetAsLongSequence().data(),
array->GetAsLongSequence().size());
}
NOTREACHED();
return {};
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-base::span<const int32_t> WebGLMultiDrawCommon::MakeSpan(
- const Int32ArrayOrLongSequence& array) {
- if (array.IsInt32Array()) {
- return base::span<const int32_t>(array.GetAsInt32Array()->Data(),
- array.GetAsInt32Array()->length());
- }
- return base::span<const int32_t>(array.GetAsLongSequence().data(),
- array.GetAsLongSequence().size());
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
// static
base::span<const uint32_t> WebGLMultiDrawCommon::MakeSpan(
- const V8UnionUint32ArrayOrUnsignedLongSequence* array) {
+ const V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence* array) {
DCHECK(array);
switch (array->GetContentType()) {
- case V8UnionUint32ArrayOrUnsignedLongSequence::ContentType::kUint32Array:
- return base::span<const uint32_t>(array->GetAsUint32Array()->Data(),
- array->GetAsUint32Array()->length());
- case V8UnionUint32ArrayOrUnsignedLongSequence::ContentType::
+ case V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence::ContentType::
+ kUint32ArrayAllowShared:
+ return base::span<const uint32_t>(
+ array->GetAsUint32ArrayAllowShared()->DataMaybeShared(),
+ array->GetAsUint32ArrayAllowShared()->length());
+ case V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence::ContentType::
kUnsignedLongSequence:
return base::span<const uint32_t>(
array->GetAsUnsignedLongSequence().data(),
@@ -92,17 +83,5 @@ base::span<const uint32_t> WebGLMultiDrawCommon::MakeSpan(
NOTREACHED();
return {};
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// static
-base::span<const uint32_t> WebGLMultiDrawCommon::MakeSpan(
- const Uint32ArrayOrUnsignedLongSequence& array) {
- if (array.IsUint32Array()) {
- return base::span<const uint32_t>(array.GetAsUint32Array()->Data(),
- array.GetAsUint32Array()->length());
- }
- return base::span<const uint32_t>(array.GetAsUnsignedLongSequence().data(),
- array.GetAsUnsignedLongSequence().size());
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h
index 5ba0c1ea442..c5d4f475025 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h
@@ -6,14 +6,13 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_COMMON_H_
#include "base/containers/span.h"
-#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h"
-#include "third_party/blink/renderer/bindings/modules/v8/uint32_array_or_unsigned_long_sequence.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
-class V8UnionInt32ArrayOrLongSequence;
-class V8UnionUint32ArrayOrUnsignedLongSequence;
+class V8UnionInt32ArrayAllowSharedOrLongSequence;
+class V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence;
class WebGLExtensionScopedContext;
class WebGLMultiDrawCommon {
@@ -29,21 +28,11 @@ class WebGLMultiDrawCommon {
GLuint offset,
GLsizei drawcount);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static base::span<const int32_t> MakeSpan(
- const V8UnionInt32ArrayOrLongSequence* array);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static base::span<const int32_t> MakeSpan(
- const Int32ArrayOrLongSequence& array);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* array);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static base::span<const uint32_t> MakeSpan(
- const V8UnionUint32ArrayOrUnsignedLongSequence* array);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static base::span<const uint32_t> MakeSpan(
- const Uint32ArrayOrUnsignedLongSequence& array);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence* array);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.cc
index 9c81715fe4f..467a3268991 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.h
index f3a88189281..49bd6fcb9aa 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.h
@@ -5,8 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_BASE_VERTEX_BASE_INSTANCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_BASE_VERTEX_BASE_INSTANCE_H_
-#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h"
-#include "third_party/blink/renderer/bindings/modules/v8/uint32_array_or_unsigned_long_sequence.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -26,16 +24,16 @@ class WebGLMultiDrawInstancedBaseVertexBaseInstance final
WebGLRenderingContextBase*);
WebGLExtensionName GetName() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void multiDrawArraysInstancedBaseInstanceWEBGL(
GLenum mode,
- const V8UnionInt32ArrayOrLongSequence* firsts_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* firsts_list,
GLuint firsts_offset,
- const V8UnionInt32ArrayOrLongSequence* counts_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* counts_list,
GLuint counts_offset,
- const V8UnionInt32ArrayOrLongSequence* instance_counts_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* instance_counts_list,
GLuint instance_counts_offset,
- const V8UnionUint32ArrayOrUnsignedLongSequence* baseinstances_list,
+ const V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence*
+ baseinstances_list,
GLuint baseinstances_offset,
GLsizei drawcount) {
multiDrawArraysInstancedBaseInstanceImpl(
@@ -43,60 +41,20 @@ class WebGLMultiDrawInstancedBaseVertexBaseInstance final
counts_offset, MakeSpan(instance_counts_list), instance_counts_offset,
MakeSpan(baseinstances_list), baseinstances_offset, drawcount);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawArraysInstancedBaseInstanceWEBGL(
- GLenum mode,
- Int32ArrayOrLongSequence firsts_list,
- GLuint firsts_offset,
- Int32ArrayOrLongSequence counts_list,
- GLuint counts_offset,
- Int32ArrayOrLongSequence instance_counts_list,
- GLuint instance_counts_offset,
- Uint32ArrayOrUnsignedLongSequence baseinstances_list,
- GLuint baseinstances_offset,
- GLsizei drawcount) {
- multiDrawArraysInstancedBaseInstanceImpl(
- mode, MakeSpan(firsts_list), firsts_offset, MakeSpan(counts_list),
- counts_offset, MakeSpan(instance_counts_list), instance_counts_offset,
- MakeSpan(baseinstances_list), baseinstances_offset, drawcount);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(
- GLenum mode,
- const V8UnionInt32ArrayOrLongSequence* counts_list,
- GLuint counts_offset,
- GLenum type,
- const V8UnionInt32ArrayOrLongSequence* offsets_list,
- GLuint offsets_offset,
- const V8UnionInt32ArrayOrLongSequence* instance_counts_list,
- GLuint instance_counts_offset,
- const V8UnionInt32ArrayOrLongSequence* basevertices_list,
- GLuint basevertices_offset,
- const V8UnionUint32ArrayOrUnsignedLongSequence* baseinstances_list,
- GLuint baseinstances_offset,
- GLsizei drawcount) {
- multiDrawElementsInstancedBaseVertexBaseInstanceImpl(
- mode, MakeSpan(counts_list), counts_offset, type,
- MakeSpan(offsets_list), offsets_offset, MakeSpan(instance_counts_list),
- instance_counts_offset, MakeSpan(basevertices_list),
- basevertices_offset, MakeSpan(baseinstances_list), baseinstances_offset,
- drawcount);
- }
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(
GLenum mode,
- Int32ArrayOrLongSequence counts_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* counts_list,
GLuint counts_offset,
GLenum type,
- Int32ArrayOrLongSequence offsets_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* offsets_list,
GLuint offsets_offset,
- Int32ArrayOrLongSequence instance_counts_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* instance_counts_list,
GLuint instance_counts_offset,
- Int32ArrayOrLongSequence basevertices_list,
+ const V8UnionInt32ArrayAllowSharedOrLongSequence* basevertices_list,
GLuint basevertices_offset,
- Uint32ArrayOrUnsignedLongSequence baseinstances_list,
+ const V8UnionUint32ArrayAllowSharedOrUnsignedLongSequence*
+ baseinstances_list,
GLuint baseinstances_offset,
GLsizei drawcount) {
multiDrawElementsInstancedBaseVertexBaseInstanceImpl(
@@ -106,7 +64,6 @@ class WebGLMultiDrawInstancedBaseVertexBaseInstance final
basevertices_offset, MakeSpan(baseinstances_list), baseinstances_offset,
drawcount);
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
void multiDrawArraysInstancedBaseInstanceImpl(
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.idl
index c9b40ecb181..a5e180697d6 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced_base_vertex_base_instance.idl
@@ -8,28 +8,28 @@
interface WebGLMultiDrawInstancedBaseVertexBaseInstance {
void multiDrawArraysInstancedBaseInstanceWEBGL(
GLenum mode,
- (Int32Array or sequence<long>) firstsList,
+ ([AllowShared] Int32Array or sequence<long>) firstsList,
GLuint firstsOffset,
- (Int32Array or sequence<long>) countsList,
+ ([AllowShared] Int32Array or sequence<long>) countsList,
GLuint countsOffset,
- (Int32Array or sequence<long>) instanceCountsList,
+ ([AllowShared] Int32Array or sequence<long>) instanceCountsList,
GLuint instanceCountsOffset,
- (Uint32Array or sequence<unsigned long>) baseInstancesList,
+ ([AllowShared] Uint32Array or sequence<unsigned long>) baseInstancesList,
GLuint baseInstancesOffset,
GLsizei drawcount);
void multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(
GLenum mode,
- (Int32Array or sequence<long>) countsList,
+ ([AllowShared] Int32Array or sequence<long>) countsList,
GLuint countsOffset,
GLenum type,
- (Int32Array or sequence<long>) offsetsList,
+ ([AllowShared] Int32Array or sequence<long>) offsetsList,
GLuint offsetsOffset,
- (Int32Array or sequence<long>) instanceCountsList,
+ ([AllowShared] Int32Array or sequence<long>) instanceCountsList,
GLuint instanceCountsOffset,
- (Int32Array or sequence<long>) baseVerticesList,
+ ([AllowShared] Int32Array or sequence<long>) baseVerticesList,
GLuint baseVerticesOffset,
- (Uint32Array or sequence<unsigned long>) baseInstancesList,
+ ([AllowShared] Uint32Array or sequence<unsigned long>) baseInstancesList,
GLuint baseInstancesOffset,
GLsizei drawcount);
};
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 e61373769a4..784b77eb0f5 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_PROGRAM_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_PROGRAM_H_
-#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_shader.h"
#include "third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h"
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.h
index 12b2a49f00b..af8814d8775 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_RENDERBUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_RENDERBUFFER_H_
-#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h"
namespace blink {
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 bd52f325f65..befbb40a0d1 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
@@ -31,8 +31,6 @@
#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/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -136,8 +134,6 @@ CanvasRenderingContext* WebGLRenderingContext::Factory::Create(
}
rendering_context->InitializeNewContext();
rendering_context->RegisterContextExtensions();
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::kWebgl);
return rendering_context;
}
@@ -158,8 +154,6 @@ WebGLRenderingContext::WebGLRenderingContext(
requested_attributes,
Platform::kWebGL1ContextType) {}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* WebGLRenderingContext::AsV8RenderingContext() {
return MakeGarbageCollected<V8RenderingContext>(this);
}
@@ -169,20 +163,6 @@ WebGLRenderingContext::AsV8OffscreenRenderingContext() {
return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void WebGLRenderingContext::SetCanvasGetContextResult(
- RenderingContext& result) {
- result.SetWebGLRenderingContext(this);
-}
-
-void WebGLRenderingContext::SetOffscreenCanvasGetContextResult(
- OffscreenRenderingContext& result) {
- result.SetWebGLRenderingContext(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
ImageBitmap* WebGLRenderingContext::TransferToImageBitmap(
ScriptState* script_state) {
return TransferToImageBitmapBase(script_state);
@@ -197,7 +177,9 @@ void WebGLRenderingContext::RegisterContextExtensions() {
RegisterExtension(angle_instanced_arrays_);
RegisterExtension(ext_blend_min_max_);
RegisterExtension(ext_color_buffer_half_float_);
- RegisterExtension(ext_disjoint_timer_query_);
+ RegisterExtension(ext_disjoint_timer_query_, TimerQueryExtensionsEnabled()
+ ? kApprovedExtension
+ : kDeveloperExtension);
RegisterExtension(ext_float_blend_);
RegisterExtension(ext_frag_depth_);
RegisterExtension(ext_shader_texture_lod_);
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 a9053170486..b478efae0b3 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
@@ -95,13 +95,8 @@ class WebGLRenderingContext final : public WebGLRenderingContextBase {
ImageBitmap* TransferToImageBitmap(ScriptState*) final;
String ContextName() const override { return "WebGLRenderingContext"; }
void RegisterContextExtensions() override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* AsV8RenderingContext() final;
V8OffscreenRenderingContext* AsV8OffscreenRenderingContext() final;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetCanvasGetContextResult(RenderingContext&) final;
- void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) final;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void Trace(Visitor*) const override;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.idl
index ab6cb064eec..61a089cf01d 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.idl
@@ -26,6 +26,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#WebGLRenderingContext
[
+ ActiveScriptWrappable,
DoNotCheckConstants,
Exposed=(Window,Worker)
] interface WebGLRenderingContext { };
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 9f9af8e5ad4..908fb0cce6e 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
@@ -28,13 +28,14 @@
#include <memory>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/numerics/checked_math.h"
-#include "base/stl_util.h"
#include "build/build_config.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_feature_info.h"
#include "media/base/video_frame.h"
#include "media/renderers/paint_canvas_video_renderer.h"
@@ -46,7 +47,6 @@
#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/v8_union_htmlcanvaselement_offscreencanvas.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"
#include "third_party/blink/renderer/core/frame/dactyloscoper.h"
@@ -373,20 +373,6 @@ class ReplaceNonASCII {
};
static bool g_should_fail_context_creation_for_testing = false;
-
-static CanvasRenderingContext::CanvasRenderingAPI GetCanvasRenderingAPIType(
- Platform::ContextType context_type) {
- switch (context_type) {
- case Platform::kWebGL1ContextType:
- return CanvasRenderingContext::CanvasRenderingAPI::kWebgl;
- case Platform::kWebGL2ContextType:
- return CanvasRenderingContext::CanvasRenderingAPI::kWebgl2;
- default:
- NOTREACHED();
- return CanvasRenderingContext::CanvasRenderingAPI::kWebgl;
- }
-}
-
} // namespace
class ScopedTexture2DRestorer {
@@ -561,16 +547,6 @@ WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
const CanvasContextCreationAttributesCore& attributes,
Platform::ContextType context_type,
Platform::GraphicsInfo* graphics_info) {
- // The host might block creation of a new WebGL context despite the
- // page settings; in particular, if WebGL contexts were lost one or
- // more times via the GL_ARB_robustness extension.
- if (host->IsWebGLBlocked()) {
- host->SetContextCreationWasBlocked();
- host->HostDispatchEvent(WebGLContextEvent::Create(
- event_type_names::kWebglcontextcreationerror,
- "Web page caused context loss and was blocked"));
- return nullptr;
- }
if ((context_type == Platform::kWebGL1ContextType &&
!host->IsWebGL1Enabled()) ||
(context_type == Platform::kWebGL2ContextType &&
@@ -581,8 +557,25 @@ WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
return nullptr;
}
- return CreateContextProviderInternal(host, attributes, context_type,
- graphics_info);
+ // We create a context *before* checking whether WebGL is blocked. This is
+ // because new context creation is effectively synchronized against the
+ // browser having a working GPU process connection, and that is in turn
+ // synchronized against any updates to the browser's set of blocked domains.
+ // See https://crbug.com/1215907#c10 for more details.
+ auto provider = CreateContextProviderInternal(host, attributes, context_type,
+ graphics_info);
+
+ // The host might block creation of a new WebGL context despite the
+ // page settings; in particular, if WebGL contexts were lost one or
+ // more times via the GL_ARB_robustness extension.
+ if (!host->IsWebGLBlocked())
+ return provider;
+
+ host->SetContextCreationWasBlocked();
+ host->HostDispatchEvent(WebGLContextEvent::Create(
+ event_type_names::kWebglcontextcreationerror,
+ "Web page caused context loss and was blocked"));
+ return nullptr;
}
void WebGLRenderingContextBase::ForceNextWebGLContextCreationToFail() {
@@ -593,6 +586,11 @@ ImageBitmap* WebGLRenderingContextBase::TransferToImageBitmapBase(
ScriptState* script_state) {
WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmapWebGL;
UseCounter::Count(ExecutionContext::From(script_state), feature);
+ if (!GetDrawingBuffer()) {
+ // Context is lost.
+ return nullptr;
+ }
+
return MakeGarbageCollected<ImageBitmap>(
GetDrawingBuffer()->TransferToStaticBitmapImage());
}
@@ -623,21 +621,23 @@ scoped_refptr<StaticBitmapImage> WebGLRenderingContextBase::GetImage() {
// graphics switching. Guard against this.
if (!GetDrawingBuffer()->ResolveAndBindForReadAndDraw())
return nullptr;
+
// Use the drawing buffer size here instead of the canvas size to ensure that
// sizing is consistent. The forced downsizing logic in Reshape() can lead to
// the drawing buffer being smaller than the canvas size.
// See https://crbug.com/845742.
IntSize size = GetDrawingBuffer()->Size();
- // Since we are grabbing a snapshot that is not for compositing, we use a
+ // We are grabbing a snapshot that is generally not for compositing, so use a
// custom resource provider. This avoids consuming compositing-specific
- // resources (e.g. GpuMemoryBuffer)
+ // resources (e.g. GpuMemoryBuffer). We tag the SharedImage with display usage
+ // since there are uncommon paths which may use this snapshot for compositing.
auto color_params = CanvasRenderingContextColorParams().GetAsResourceParams();
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::CreateSharedImageProvider(
size, GetDrawingBuffer()->FilterQuality(), color_params,
CanvasResourceProvider::ShouldInitialize::kNo,
SharedGpuContext::ContextProviderWrapper(), RasterMode::kGPU,
- is_origin_top_left_, 0u /*shared_image_usage_flags*/);
+ is_origin_top_left_, gpu::SHARED_IMAGE_USAGE_DISPLAY);
if (!resource_provider || !resource_provider->IsValid()) {
resource_provider = CanvasResourceProvider::CreateBitmapProvider(
size, GetDrawingBuffer()->FilterQuality(), color_params,
@@ -994,7 +994,11 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(
const Platform::GraphicsInfo& graphics_info,
const CanvasContextCreationAttributesCore& requested_attributes,
Platform::ContextType context_type)
- : CanvasRenderingContext(host, requested_attributes),
+ : CanvasRenderingContext(host,
+ requested_attributes,
+ context_type == Platform::kWebGL2ContextType
+ ? CanvasRenderingAPI::kWebgl2
+ : CanvasRenderingAPI::kWebgl),
context_group_(MakeGarbageCollected<WebGLContextGroup>()),
dispatch_context_lost_event_timer_(
task_runner,
@@ -1022,7 +1026,7 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(
// TODO(https://crbug.com/1208480): Move color space to being a read-write
// attribute instead of a context creation attribute.
- if (RuntimeEnabledFeatures::CanvasColorManagementEnabled()) {
+ if (RuntimeEnabledFeatures::CanvasColorManagementV2Enabled()) {
color_params_ = CanvasColorParams(requested_attributes.color_space,
requested_attributes.pixel_format,
requested_attributes.alpha);
@@ -1294,7 +1298,7 @@ void WebGLRenderingContextBase::RemoveAllCompressedTextureFormats() {
// CanvasRenderingContext supports.
unsigned WebGLRenderingContextBase::GetWebGLVersion(
const CanvasRenderingContext* context) {
- if (!context->Is3d())
+ if (!context->IsWebGL())
return 0;
return static_cast<const WebGLRenderingContextBase*>(context)->ContextType();
}
@@ -1348,7 +1352,8 @@ void WebGLRenderingContextBase::DestroyContext() {
}
void WebGLRenderingContextBase::MarkContextChanged(
- ContentChangeType change_type) {
+ ContentChangeType change_type,
+ CanvasPerformanceMonitor::DrawType draw_type) {
if (isContextLost())
return;
@@ -1368,7 +1373,7 @@ void WebGLRenderingContextBase::MarkContextChanged(
if (Host()->IsOffscreenCanvas()) {
marked_canvas_dirty_ = true;
- DidDraw();
+ DidDraw(draw_type);
return;
}
@@ -1385,8 +1390,7 @@ void WebGLRenderingContextBase::MarkContextChanged(
if (layout_box && settings->GetAcceleratedCompositingEnabled())
layout_box->ContentChanged(change_type);
}
- IntSize canvas_size = ClampedCanvasSize();
- DidDraw(SkIRect::MakeXYWH(0, 0, canvas_size.Width(), canvas_size.Height()));
+ DidDraw(draw_type);
}
}
@@ -1395,16 +1399,6 @@ WebGLRenderingContextBase::GetContextTaskRunner() {
return task_runner_;
}
-void WebGLRenderingContextBase::DidDraw(const SkIRect& dirty_rect) {
- MarkContextChanged(kCanvasChanged);
- CanvasRenderingContext::DidDraw(dirty_rect);
-}
-
-void WebGLRenderingContextBase::DidDraw() {
- MarkContextChanged(kCanvasChanged);
- CanvasRenderingContext::DidDraw();
-}
-
bool WebGLRenderingContextBase::PushFrame() {
TRACE_EVENT0("blink", "WebGLRenderingContextBase::PushFrame");
DCHECK(Host());
@@ -1659,6 +1653,7 @@ bool WebGLRenderingContextBase::PaintRenderingResultsToCanvas(
return true;
}
+ // TODO(sunnyps): Why is a texture restorer needed? See if it can be removed.
ScopedTexture2DRestorer restorer(this);
ScopedFramebufferRestorer fbo_restorer(this);
@@ -1689,6 +1684,14 @@ bool WebGLRenderingContextBase::CopyRenderingResultsFromDrawingBuffer(
if (!GetDrawingBuffer())
return false;
+ ScopedFramebufferRestorer fbo_restorer(this);
+ // In rare situations on macOS the drawing buffer can be destroyed
+ // during the resolve process, specifically during automatic
+ // graphics switching. Guard against this.
+ // This is a no-op if already called higher up the stack from here.
+ if (!GetDrawingBuffer()->ResolveAndBindForReadAndDraw())
+ return false;
+
const bool flip_y = IsOriginTopLeft() != resource_provider->IsOriginTopLeft();
if (resource_provider->IsAccelerated()) {
base::WeakPtr<WebGraphicsContext3DProviderWrapper> shared_context_wrapper =
@@ -1727,10 +1730,11 @@ bool WebGLRenderingContextBase::CopyRenderingResultsFromDrawingBuffer(
flags.setBlendMode(SkBlendMode::kSrc);
// We use this draw helper as we need to take into account the
// ImageOrientation of the UnacceleratedStaticBitmapImage.
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
image->Draw(resource_provider->Canvas(), flags, FloatRect(dest_rect),
- FloatRect(src_rect), SkSamplingOptions(),
- kRespectImageOrientation, Image::kDoNotClampImageToSourceRect,
- Image::kSyncDecode);
+ FloatRect(src_rect), draw_options,
+ Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
return true;
}
@@ -1793,6 +1797,7 @@ void WebGLRenderingContextBase::Reshape(int width, int height) {
// We don't have to mark the canvas as dirty, since the newly created image
// buffer will also start off clear (and this matches what reshape will do).
+ GetDrawingBuffer()->set_low_latency_enabled(Host()->LowLatencyEnabled());
GetDrawingBuffer()->Resize(IntSize(width, height));
if (buffer) {
@@ -2219,7 +2224,8 @@ void WebGLRenderingContextBase::clear(GLbitfield mask) {
}
ContextGL()->Clear(mask);
}
- MarkContextChanged(kCanvasChanged);
+ MarkContextChanged(kCanvasChanged,
+ CanvasPerformanceMonitor::DrawType::kOther);
}
void WebGLRenderingContextBase::clearColor(GLfloat r,
@@ -2729,7 +2735,7 @@ void WebGLRenderingContextBase::drawArrays(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawArrays);
ContextGL()->DrawArrays(mode, first, count);
RecordUKMCanvasDrawnToAtFirstDrawCall();
}
@@ -2749,7 +2755,7 @@ void WebGLRenderingContextBase::drawElements(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawElements);
ContextGL()->DrawElements(
mode, count, type,
reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
@@ -2771,7 +2777,7 @@ void WebGLRenderingContextBase::DrawArraysInstancedANGLE(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawArrays);
ContextGL()->DrawArraysInstancedANGLE(mode, first, count, primcount);
RecordUKMCanvasDrawnToAtFirstDrawCall();
}
@@ -2792,7 +2798,7 @@ void WebGLRenderingContextBase::DrawElementsInstancedANGLE(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- OnBeforeDrawCall();
+ OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType::kDrawElements);
ContextGL()->DrawElementsInstancedANGLE(
mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)),
primcount);
@@ -3124,6 +3130,9 @@ bool WebGLRenderingContextBase::ExtensionSupportedAndAllowed(
if (tracker->Draft() &&
!RuntimeEnabledFeatures::WebGLDraftExtensionsEnabled())
return false;
+ if (tracker->Developer() &&
+ !RuntimeEnabledFeatures::WebGLDeveloperExtensionsEnabled())
+ return false;
if (!tracker->Supported(this))
return false;
if (disabled_extensions_.Contains(String(tracker->ExtensionName())))
@@ -3131,6 +3140,13 @@ bool WebGLRenderingContextBase::ExtensionSupportedAndAllowed(
return true;
}
+bool WebGLRenderingContextBase::TimerQueryExtensionsEnabled() {
+ return (drawing_buffer_ && drawing_buffer_->ContextProvider() &&
+ drawing_buffer_->ContextProvider()
+ ->GetGpuFeatureInfo()
+ .IsWorkaroundEnabled(gpu::ENABLE_WEBGL_TIMER_QUERY_EXTENSIONS));
+}
+
ScriptValue WebGLRenderingContextBase::getExtension(ScriptState* script_state,
const String& name) {
WebGLExtension* extension = nullptr;
@@ -3343,8 +3359,7 @@ void WebGLRenderingContextBase::RecordShaderPrecisionFormatForStudy(
void WebGLRenderingContextBase::RecordUKMCanvasDrawnToAtFirstDrawCall() {
if (!has_been_drawn_to_) {
has_been_drawn_to_ = true;
- RecordUKMCanvasDrawnToRenderingAPI(
- GetCanvasRenderingAPIType(context_type_));
+ RecordUKMCanvasDrawnToRenderingAPI();
}
}
@@ -4694,6 +4709,12 @@ void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,
buffer.emplace(32);
data = buffer->data();
}
+
+ // Last-chance early-out, in case somehow the context was lost during
+ // the above ClearIfComposited operation.
+ if (isContextLost() || !GetDrawingBuffer())
+ return;
+
{
ScopedDrawingBufferBinder binder(GetDrawingBuffer(), framebuffer);
ContextGL()->ReadPixels(x, y, width, height, format, type, data);
@@ -5118,10 +5139,11 @@ scoped_refptr<Image> WebGLRenderingContextBase::DrawImageIntoBuffer(
PaintFlags flags;
// TODO(ccameron): WebGL should produce sRGB images.
// https://crbug.com/672299
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
image->Draw(resource_provider->Canvas(), flags, FloatRect(dest_rect),
- FloatRect(src_rect), SkSamplingOptions(),
- kRespectImageOrientation, Image::kDoNotClampImageToSourceRect,
- Image::kSyncDecode);
+ FloatRect(src_rect), draw_options,
+ Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
return resource_provider->Snapshot();
}
@@ -5296,11 +5318,7 @@ void WebGLRenderingContextBase::TexImageHelperImageData(
if (isContextLost())
return;
DCHECK(pixels);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(pixels->data());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DCHECK(!pixels->data().IsNull());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (pixels->IsBufferBaseDetached()) {
SynthesizeGLError(GL_INVALID_VALUE, func_name,
"The source data has been detached.");
@@ -5551,10 +5569,6 @@ void WebGLRenderingContextBase::TexImageViaGPU(
possible_direct_copy = Extensions3DUtil::CanUseCopyTextureCHROMIUM(target);
}
- GLint copy_x_offset = xoffset;
- GLint copy_y_offset = yoffset;
- GLenum copy_target = target;
-
// if direct copy is not possible, create a temporary texture and then copy
// from canvas to temporary texture to target texture.
if (!possible_direct_copy) {
@@ -5570,9 +5584,6 @@ void WebGLRenderingContextBase::TexImageViaGPU(
GL_CLAMP_TO_EDGE);
ContextGL()->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- copy_x_offset = 0;
- copy_y_offset = 0;
- copy_target = GL_TEXTURE_2D;
}
{
@@ -5673,7 +5684,7 @@ void WebGLRenderingContextBase::TexImageHelperCanvasRenderingContextHost(
return;
}
- bool is_webgl_canvas = context_host->Is3d();
+ bool is_webgl_canvas = context_host->IsWebGL();
WebGLRenderingContextBase* source_canvas_webgl_context = nullptr;
SourceImageStatus source_image_status = kInvalidSourceImageStatus;
scoped_refptr<Image> image;
@@ -5870,8 +5881,11 @@ void WebGLRenderingContextBase::TexImageHelperVideoFrame(
function_type = kTexSubImage;
auto local_handle = frame->handle()->CloneForInternalUse();
- if (!local_handle)
+ if (!local_handle) {
+ SynthesizeGLError(GL_INVALID_OPERATION, func_name,
+ "can't texture a closed VideoFrame.");
return;
+ }
const auto natural_size = local_handle->frame()->natural_size();
if (!ValidateTexFunc(func_name, function_type, kSourceVideoFrame, target,
@@ -5947,12 +5961,6 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
return;
}
- TexImageFunctionType function_type;
- if (function_id == kTexImage2D || function_id == kTexImage3D)
- function_type = kTexImage;
- else
- function_type = kTexSubImage;
-
// The CopyTexImage fast paths can't handle orientation, so if a non-default
// orientation is provided, we must disable them.
const auto transform = media_video_frame->metadata().transformation.value_or(
@@ -5977,6 +5985,14 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
CanUseTexImageViaGPU(format, type) &&
transform == media::kNoTransformation;
+#if defined(OS_WIN)
+ // TODO(crbug.com/1227921): When OOP GPU rasterization is disabled, uploading
+ // via the GPU becomes extremely slow.
+ const bool gpu_teximage_is_slow = !caps.supports_oop_raster;
+#else
+ const bool gpu_teximage_is_slow = false;
+#endif
+
// Callers may chose to provide a renderer which ensures that generated
// intermediates will be cached across TexImage calls for the same frame.
std::unique_ptr<media::PaintCanvasVideoRenderer> local_video_renderer;
@@ -6022,7 +6038,7 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
// TODO(crbug.com/1180879): I420A should be supported, but currently fails
// conformance/textures/misc/texture-video-transparent.html.
if (!media_video_frame->HasTextures() &&
- media::IsOpaque(media_video_frame->format()) &&
+ media::IsOpaque(media_video_frame->format()) && !gpu_teximage_is_slow &&
video_renderer->CopyVideoFrameYUVDataToGLTexture(
raster_context_provider, ContextGL(), media_video_frame, target,
texture->Object(), adjusted_internalformat, format, type, level,
@@ -6090,9 +6106,9 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
function_id == kTexImage2D || function_id == kTexSubImage2D;
#endif
- const bool can_upload_via_gpu = function_supports_gpu_teximage &&
- CanUseTexImageViaGPU(format, type) &&
- source_image_rect_is_default;
+ const bool can_upload_via_gpu =
+ function_supports_gpu_teximage && CanUseTexImageViaGPU(format, type) &&
+ source_image_rect_is_default && !gpu_teximage_is_slow;
// If we can upload via GPU, try to to use an accelerated resource provider
// configured appropriately for video. Otherwise use the software cache.
@@ -7246,7 +7262,7 @@ cc::Layer* WebGLRenderingContextBase::CcLayer() const {
}
void WebGLRenderingContextBase::SetFilterQuality(
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
if (!isContextLost() && GetDrawingBuffer()) {
GetDrawingBuffer()->SetFilterQuality(filter_quality);
}
@@ -8523,9 +8539,10 @@ bool WebGLRenderingContextBase::ValidateDrawElements(const char* function_name,
return true;
}
-void WebGLRenderingContextBase::OnBeforeDrawCall() {
+void WebGLRenderingContextBase::OnBeforeDrawCall(
+ CanvasPerformanceMonitor::DrawType draw_type) {
ClearIfComposited(kClearCallerDrawOrClear);
- MarkContextChanged(kCanvasChanged);
+ MarkContextChanged(kCanvasChanged, draw_type);
}
void WebGLRenderingContextBase::DispatchContextLostEvent(TimerBase*) {
@@ -8634,7 +8651,8 @@ void WebGLRenderingContextBase::MaybeRestoreContext(TimerBase*) {
SetupFlags();
InitializeNewContext();
- MarkContextChanged(kCanvasContextChanged);
+ MarkContextChanged(kCanvasContextChanged,
+ CanvasPerformanceMonitor::DrawType::kOther);
WebGLContextEvent* event =
WebGLContextEvent::Create(event_type_names::kWebglcontextrestored, "");
Host()->HostDispatchEvent(event);
@@ -8681,7 +8699,7 @@ CanvasResourceProvider* WebGLRenderingContextBase::
} else {
// TODO(fserb): why is this a BITMAP?
temp = CanvasResourceProvider::CreateBitmapProvider(
- size, kLow_SkFilterQuality, CanvasResourceParams(),
+ size, cc::PaintFlags::FilterQuality::kLow, CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kNo); // TODO: should this
// use the canvas's
}
@@ -8924,7 +8942,6 @@ void WebGLRenderingContextBase::RestoreUnpackParameters() {
ContextGL()->PixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment_);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionHTMLCanvasElementOrOffscreenCanvas*
WebGLRenderingContextBase::getHTMLOrOffscreenCanvas() const {
if (canvas()) {
@@ -8934,16 +8951,6 @@ WebGLRenderingContextBase::getHTMLOrOffscreenCanvas() const {
return MakeGarbageCollected<V8UnionHTMLCanvasElementOrOffscreenCanvas>(
static_cast<OffscreenCanvas*>(Host()));
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas(
- HTMLCanvasElementOrOffscreenCanvas& result) const {
- if (canvas()) {
- result.SetHTMLCanvasElement(static_cast<HTMLCanvasElement*>(Host()));
- } else {
- result.SetOffscreenCanvas(static_cast<OffscreenCanvas*>(Host()));
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void WebGLRenderingContextBase::addProgramCompletionQuery(WebGLProgram* program,
GLuint query) {
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 f0ea2d2991f..7cd14233335 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
@@ -83,7 +83,6 @@ class CanvasResourceProvider;
class EXTDisjointTimerQuery;
class EXTDisjointTimerQueryWebGL2;
class ExceptionState;
-class HTMLCanvasElementOrOffscreenCanvas;
class HTMLImageElement;
class HTMLVideoElement;
class ImageBitmap;
@@ -635,14 +634,9 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
return color_params_;
}
scoped_refptr<StaticBitmapImage> GetImage() override;
- void SetFilterQuality(SkFilterQuality) override;
- bool IsWebGL2() { return context_type_ == Platform::kWebGL2ContextType; }
+ void SetFilterQuality(cc::PaintFlags::FilterQuality) override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionHTMLCanvasElementOrOffscreenCanvas* getHTMLOrOffscreenCanvas() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void getHTMLOrOffscreenCanvas(HTMLCanvasElementOrOffscreenCanvas&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void commit();
@@ -698,7 +692,6 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
void SetupFlags();
// CanvasRenderingContext implementation.
- bool Is3d() const override { return true; }
bool IsComposited() const override { return true; }
bool IsAccelerated() const override { return true; }
bool UsingSwapChain() const override;
@@ -706,10 +699,10 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
void SetIsInHiddenPage(bool) override;
void SetIsBeingDisplayed(bool) override {}
bool PaintRenderingResultsToCanvas(SourceDrawingBuffer) override;
+ bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
+ SourceDrawingBuffer) override;
cc::Layer* CcLayer() const override;
void Stop() override;
- void DidDraw(const SkIRect&) override;
- void DidDraw() override;
void FinalizeFrame() override;
bool PushFrame() override;
@@ -728,7 +721,8 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
void DrawingBufferClientForceLostContextWithAutoRecovery() override;
virtual void DestroyContext();
- void MarkContextChanged(ContentChangeType);
+ void MarkContextChanged(ContentChangeType,
+ CanvasPerformanceMonitor::DrawType);
void OnErrorMessage(const char*, int32_t id);
@@ -918,15 +912,22 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
kApprovedExtension = 0x00,
// Extension that is behind the draft extensions runtime flag:
kDraftExtension = 0x01,
+ // Extension that is intended for development rather than
+ // deployment time.
+ kDeveloperExtension = 0x02,
};
class ExtensionTracker : public GarbageCollected<ExtensionTracker>,
public NameClient {
public:
ExtensionTracker(ExtensionFlags flags, const char* const* prefixes)
- : draft_(flags & kDraftExtension), prefixes_(prefixes) {}
+ : draft_(flags & kDraftExtension),
+ developer_(flags & kDeveloperExtension),
+ prefixes_(prefixes) {}
+ ~ExtensionTracker() override = default;
bool Draft() const { return draft_; }
+ bool Developer() const { return developer_; }
const char* const* Prefixes() const;
bool MatchesNameWithPrefixes(const String&) const;
@@ -946,6 +947,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
private:
bool draft_;
+ bool developer_;
const char* const* prefixes_;
};
@@ -991,7 +993,6 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
}
private:
- GC_PLUGIN_IGNORE("http://crbug.com/519953")
Member<T>& extension_field_;
// ExtensionTracker holds it's own reference to the extension to ensure
// that it is not deleted before this object's destructor is called
@@ -1016,6 +1017,8 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
return extension_enabled_[name];
}
+ bool TimerQueryExtensionsEnabled();
+
// ScopedDrawingBufferBinder is used for
// ReadPixels/CopyTexImage2D/CopySubImage2D to read from a multisampled
// DrawingBuffer. In this situation, we need to blit to a single sampled
@@ -1604,7 +1607,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
}
// State updates and operations necessary before or at draw call time.
- virtual void OnBeforeDrawCall();
+ virtual void OnBeforeDrawCall(CanvasPerformanceMonitor::DrawType);
// Helper functions to bufferData() and bufferSubData().
void BufferDataImpl(GLenum target,
@@ -1868,8 +1871,6 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
bool IsPaintable() const final { return GetDrawingBuffer(); }
- bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
- SourceDrawingBuffer);
void HoldReferenceToDrawingBuffer(DrawingBuffer*);
static void InitializeWebGLContextLimits(
@@ -1913,7 +1914,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
template <>
struct DowncastTraits<WebGLRenderingContextBase> {
static bool AllowFrom(const CanvasRenderingContext& context) {
- return context.Is3d();
+ return context.IsWebGL();
}
};
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 8c9c00ff7f9..0c6417d6dfe 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
@@ -469,9 +469,9 @@ interface mixin WebGLRenderingContextBase {
void attachShader(WebGLProgram program, WebGLShader shader);
void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name);
[NoAllocDirectCall] void bindBuffer(GLenum target, WebGLBuffer? buffer);
- void bindFramebuffer(GLenum target, WebGLFramebuffer? framebuffer);
+ [NoAllocDirectCall] void bindFramebuffer(GLenum target, WebGLFramebuffer? framebuffer);
void bindRenderbuffer(GLenum target, WebGLRenderbuffer? renderbuffer);
- void bindTexture(GLenum target, WebGLTexture? texture);
+ [NoAllocDirectCall] void bindTexture(GLenum target, WebGLTexture? texture);
void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void blendEquation(GLenum mode);
void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
@@ -486,11 +486,11 @@ interface mixin WebGLRenderingContextBase {
void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer data);
GLenum checkFramebufferStatus(GLenum target);
- void clear(GLbitfield mask);
- void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
- void clearDepth(GLclampf depth);
- void clearStencil(GLint s);
- void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ [NoAllocDirectCall] void clear(GLbitfield mask);
+ [NoAllocDirectCall] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ [NoAllocDirectCall] void clearDepth(GLclampf depth);
+ [NoAllocDirectCall] void clearStencil(GLint s);
+ [NoAllocDirectCall] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void compileShader(WebGLShader shader);
void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
@@ -522,12 +522,12 @@ interface mixin WebGLRenderingContextBase {
void depthRange(GLclampf zNear, GLclampf zFar);
void detachShader(WebGLProgram program, WebGLShader shader);
void disable(GLenum cap);
- void disableVertexAttribArray(GLuint index);
+ [NoAllocDirectCall] void disableVertexAttribArray(GLuint index);
[NoAllocDirectCall] void drawArrays(GLenum mode, GLint first, GLsizei count);
[NoAllocDirectCall] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset);
void enable(GLenum cap);
- void enableVertexAttribArray(GLuint index);
+ [NoAllocDirectCall] void enableVertexAttribArray(GLuint index);
void finish();
void flush();
void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer? renderbuffer);
@@ -593,7 +593,7 @@ interface mixin WebGLRenderingContextBase {
void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
void sampleCoverage(GLclampf value, GLboolean invert);
- void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+ [NoAllocDirectCall] void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
void shaderSource(WebGLShader shader, DOMString string);
void stencilFunc(GLenum func, GLint ref, GLuint mask);
void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
@@ -660,28 +660,28 @@ interface mixin WebGLRenderingContextBase {
GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, VideoFrame frame);
- void uniform1f(WebGLUniformLocation? location, GLfloat x);
+ [NoAllocDirectCall] void uniform1f(WebGLUniformLocation? location, GLfloat x);
void uniform1fv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Float32Array v);
void uniform1fv(WebGLUniformLocation? location, sequence<GLfloat> v);
- void uniform1i(WebGLUniformLocation? location, GLint x);
+ [NoAllocDirectCall] void uniform1i(WebGLUniformLocation? location, GLint x);
void uniform1iv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Int32Array v);
void uniform1iv(WebGLUniformLocation? location, sequence<GLint> v);
- void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y);
+ [NoAllocDirectCall] void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y);
void uniform2fv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Float32Array v);
void uniform2fv(WebGLUniformLocation? location, sequence<GLfloat> v);
- void uniform2i(WebGLUniformLocation? location, GLint x, GLint y);
+ [NoAllocDirectCall] void uniform2i(WebGLUniformLocation? location, GLint x, GLint y);
void uniform2iv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Int32Array v);
void uniform2iv(WebGLUniformLocation? location, sequence<GLint> v);
- void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z);
+ [NoAllocDirectCall] void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z);
void uniform3fv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Float32Array v);
void uniform3fv(WebGLUniformLocation? location, sequence<GLfloat> v);
- void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z);
+ [NoAllocDirectCall] void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z);
void uniform3iv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Int32Array v);
void uniform3iv(WebGLUniformLocation? location, sequence<GLint> v);
- void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ [NoAllocDirectCall] void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform4fv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Float32Array v);
void uniform4fv(WebGLUniformLocation? location, sequence<GLfloat> v);
- void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w);
+ [NoAllocDirectCall] void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w);
void uniform4iv(WebGLUniformLocation? location, [AllowShared, FlexibleArrayBufferView] Int32Array v);
void uniform4iv(WebGLUniformLocation? location, sequence<GLint> v);
@@ -695,22 +695,22 @@ interface mixin WebGLRenderingContextBase {
void useProgram(WebGLProgram? program);
void validateProgram(WebGLProgram program);
- void vertexAttrib1f(GLuint indx, GLfloat x);
+ [NoAllocDirectCall] void vertexAttrib1f(GLuint indx, GLfloat x);
void vertexAttrib1fv(GLuint indx, [AllowShared] Float32Array values);
void vertexAttrib1fv(GLuint indx, sequence<GLfloat> values);
- void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
+ [NoAllocDirectCall] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
void vertexAttrib2fv(GLuint indx, [AllowShared] Float32Array values);
void vertexAttrib2fv(GLuint indx, sequence<GLfloat> values);
- void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+ [NoAllocDirectCall] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
void vertexAttrib3fv(GLuint indx, [AllowShared] Float32Array values);
void vertexAttrib3fv(GLuint indx, sequence<GLfloat> values);
- void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ [NoAllocDirectCall] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void vertexAttrib4fv(GLuint indx, [AllowShared] Float32Array values);
void vertexAttrib4fv(GLuint indx, sequence<GLfloat> values);
void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, GLintptr offset);
- void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+ [NoAllocDirectCall] void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
[RuntimeEnabled=OffscreenCanvasCommit] void commit();
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h
index 5e7c896afd5..40b2219b4cc 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_platform_3d_object.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_SHARED_PLATFORM_3D_OBJECT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_SHARED_PLATFORM_3D_OBJECT_H_
-#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_shared_object.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.h
index 1bb9404ca1f..078fe6d5766 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.h
@@ -33,6 +33,15 @@
namespace blink {
+// For last-uploaded-frame-metadata API. https://crbug.com/639174
+struct WebGLVideoFrameUploadMetadata {
+ int frame_id = -1;
+ IntRect visible_rect = {};
+ base::TimeDelta timestamp = {};
+ base::TimeDelta expected_timestamp = {};
+ bool skipped = false;
+};
+
class WebGLTexture : public WebGLSharedPlatform3DObject {
DEFINE_WRAPPERTYPEINFO();
@@ -49,20 +58,11 @@ class WebGLTexture : public WebGLSharedPlatform3DObject {
static GLint ComputeLevelCount(GLsizei width, GLsizei height, GLsizei depth);
- // For last-uploaded-frame-metadata API. https://crbug.com/639174
- struct VideoFrameUploadMetadata {
- int frame_id = -1;
- IntRect visible_rect = {};
- base::TimeDelta timestamp = {};
- base::TimeDelta expected_timestamp = {};
- bool skipped = false;
- };
-
int GetLastUploadedVideoFrameId() const {
return last_uploaded_video_frame_metadata_.frame_id;
}
- void UpdateLastUploadedFrame(VideoFrameUploadMetadata frame_metadata) {
+ void UpdateLastUploadedFrame(WebGLVideoFrameUploadMetadata frame_metadata) {
last_uploaded_video_frame_metadata_ = frame_metadata;
}
@@ -96,7 +96,7 @@ class WebGLTexture : public WebGLSharedPlatform3DObject {
GLenum target_;
- VideoFrameUploadMetadata last_uploaded_video_frame_metadata_ = {};
+ WebGLVideoFrameUploadMetadata last_uploaded_video_frame_metadata_ = {};
};
} // 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 43c408cc119..a6b5697e9a4 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_TRANSFORM_FEEDBACK_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_TRANSFORM_FEEDBACK_H_
-#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_context_object.h"
#include "third_party/blink/renderer/modules/webgl/webgl_program.h"
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.cc
index bd29e7e8141..a7f3b06eed5 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.cc
@@ -14,7 +14,18 @@ WebGLUnownedTexture::WebGLUnownedTexture(WebGLRenderingContextBase* ctx,
GLenum target)
: WebGLTexture(ctx, texture, target) {}
+void WebGLUnownedTexture::OnGLDeleteTextures() {
+ // The owner of the texture name notified us that it is no longer valid.
+ // Just zero it out so we're not going to use it somewhere.
+ // Note that this will suppress the rest of the logic found in
+ // WebGLObject::DeleteObject(), since one of the first things that the method
+ // does is a check to see if |object_| is valid.
+ object_ = 0;
+}
+
void WebGLUnownedTexture::DeleteObjectImpl(gpu::gles2::GLES2Interface* gl) {
+ // Normally, we would invoke gl->DeleteTextures() here, but
+ // WebGLUnownedTexture does not own its texture name. Just zero it out.
object_ = 0;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h
index ee694dd148a..53eed52b42e 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h
@@ -14,6 +14,8 @@ namespace blink {
// provide a camera image textures until it's decided how to best expose
// the texture to the WebXR API.
// TODO(https://bugs.chromium.org/p/chromium/issues/detail?id=1104340).
+// The texture does not own its texture name - it relies on being notified that
+// the texture name has been deleted by whoever owns it.
class WebGLUnownedTexture final : public WebGLTexture {
public:
// The provided GLuint must have been created in the same
@@ -24,6 +26,10 @@ class WebGLUnownedTexture final : public WebGLTexture {
GLenum target);
~WebGLUnownedTexture() override;
+ // Used to notify the unowned texture that the owner has removed the texture
+ // name and so that it should not be used anymore.
+ void OnGLDeleteTextures();
+
private:
void DeleteObjectImpl(gpu::gles2::GLES2Interface*) override;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.cc
index 2f331639d70..60209142c55 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.cc
@@ -156,12 +156,11 @@ bool WebGLVideoTexture::releaseVideoImageWEBGL(
}
// static
-WebGLTexture::VideoFrameUploadMetadata
-WebGLVideoTexture::CreateVideoFrameUploadMetadata(
+WebGLVideoFrameUploadMetadata WebGLVideoTexture::CreateVideoFrameUploadMetadata(
const media::VideoFrame* frame,
int already_uploaded_id) {
DCHECK(frame);
- WebGLTexture::VideoFrameUploadMetadata metadata = {};
+ WebGLVideoFrameUploadMetadata metadata = {};
if (!RuntimeEnabledFeatures::ExtraWebGLVideoTextureMetadataEnabled())
return metadata;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.h
index 4661272ba26..643ed0b0f36 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.h
@@ -13,8 +13,11 @@ class VideoFrame;
namespace blink {
+class ExceptionState;
+class ExecutionContext;
class HTMLVideoElement;
class VideoFrameMetadata;
+struct WebGLVideoFrameUploadMetadata;
class WebGLVideoTexture final : public WebGLExtension {
DEFINE_WRAPPERTYPEINFO();
@@ -38,9 +41,9 @@ class WebGLVideoTexture final : public WebGLExtension {
bool releaseVideoImageWEBGL(ExecutionContext*, unsigned, ExceptionState&);
- // Helper method for filling in VideoFrameUploadMetadata. Will be default
+ // Helper method for filling in WebGLVideoFrameUploadMetadata. Will be default
// initialized (skipped = false) if the metadata API is disabled.
- static WebGLTexture::VideoFrameUploadMetadata CreateVideoFrameUploadMetadata(
+ static WebGLVideoFrameUploadMetadata CreateVideoFrameUploadMetadata(
const media::VideoFrame* frame,
int already_uploaded_id);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.idl
index fddd62916ab..329c609ce60 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_video_texture.idl
@@ -12,6 +12,6 @@
const GLenum TEXTURE_VIDEO_IMAGE = 0x9248;
const GLenum SAMPLER_VIDEO_IMAGE = 0x9249;
- [CallWith=ExecutionContext, RaisesException] VideoFrameMetadata shareVideoImageWEBGL(GLenum target, HTMLVideoElement video);
+ [CallWith=ExecutionContext, RaisesException] VideoFrameMetadata? shareVideoImageWEBGL(GLenum target, HTMLVideoElement video);
[CallWith=ExecutionContext, RaisesException] boolean releaseVideoImageWEBGL(GLenum target);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc
index 87a4d5e4358..ce3dfd2bc79 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc
@@ -9,14 +9,10 @@
#include "media/base/wait_and_replace_sync_token_client.h"
#include "media/video/gpu_memory_buffer_video_frame_pool.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_color_space_matrix_id.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_color_space_primary_id.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_color_space_range_id.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_color_space_transfer_id.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_webgl_webcodecs_texture_info.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_webgl_webcodecs_video_frame_handle.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_color_space.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
#include "third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -40,184 +36,6 @@ const char kRequiredExtension[] = "GL_OES_EGL_image_external";
const char kRequiredExtension[] = "";
#endif
-void FillVideoColorSpace(VideoColorSpace* video_color_space,
- gfx::ColorSpace& gfx_color_space) {
- gfx::ColorSpace::PrimaryID primaries = gfx_color_space.GetPrimaryID();
- absl::optional<V8ColorSpacePrimaryID> primary_id;
- switch (primaries) {
- case gfx::ColorSpace::PrimaryID::BT709:
- primary_id = V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kBT709);
- break;
- case gfx::ColorSpace::PrimaryID::BT470M:
- primary_id = V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kBT470M);
- break;
- case gfx::ColorSpace::PrimaryID::BT470BG:
- primary_id = V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kBT470BG);
- break;
- case gfx::ColorSpace::PrimaryID::SMPTE170M:
- primary_id =
- V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kSMPTE170M);
- break;
- case gfx::ColorSpace::PrimaryID::SMPTE240M:
- primary_id =
- V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kSMPTE240M);
- break;
- case gfx::ColorSpace::PrimaryID::FILM:
- primary_id = V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kFILM);
- break;
- case gfx::ColorSpace::PrimaryID::BT2020:
- primary_id = V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kBT2020);
- break;
- case gfx::ColorSpace::PrimaryID::SMPTEST428_1:
- primary_id =
- V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kSmptest4281);
- break;
- case gfx::ColorSpace::PrimaryID::SMPTEST431_2:
- primary_id =
- V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kSmptest4312);
- break;
- case gfx::ColorSpace::PrimaryID::SMPTEST432_1:
- primary_id =
- V8ColorSpacePrimaryID(V8ColorSpacePrimaryID::Enum::kSmptest4321);
- break;
- // TODO(jie.a.chen@intel.com): Need to check EBU_3213_E.
- default:;
- }
- if (primary_id) {
- video_color_space->setPrimaryID(*primary_id);
- }
-
- gfx::ColorSpace::TransferID transfer = gfx_color_space.GetTransferID();
- absl::optional<V8ColorSpaceTransferID> transfer_id;
- switch (transfer) {
- case gfx::ColorSpace::TransferID::BT709:
-#if defined(OS_MAC)
- // TODO(jie.a.chen@intel.com): BT709_APPLE is not available in WebCodecs.
- case gfx::ColorSpace::TransferID::BT709_APPLE:
-#endif
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kBT709);
- break;
- case gfx::ColorSpace::TransferID::GAMMA22:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kGAMMA22);
- break;
- case gfx::ColorSpace::TransferID::GAMMA28:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kGAMMA28);
- break;
- case gfx::ColorSpace::TransferID::SMPTE170M:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kSMPTE170M);
- break;
- case gfx::ColorSpace::TransferID::SMPTE240M:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kSMPTE240M);
- break;
- case gfx::ColorSpace::TransferID::LINEAR:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kLINEAR);
- break;
- case gfx::ColorSpace::TransferID::LOG:
- transfer_id = V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kLOG);
- break;
- case gfx::ColorSpace::TransferID::LOG_SQRT:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kLogSqrt);
- break;
- case gfx::ColorSpace::TransferID::IEC61966_2_4:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kIec6196624);
- break;
- case gfx::ColorSpace::TransferID::BT1361_ECG:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kBt1361Ecg);
- break;
- case gfx::ColorSpace::TransferID::IEC61966_2_1:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kIec6196621);
- break;
- case gfx::ColorSpace::TransferID::BT2020_10:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kBt202010);
- break;
-
- case gfx::ColorSpace::TransferID::BT2020_12:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kBt202012);
- break;
- case gfx::ColorSpace::TransferID::SMPTEST2084:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kSMPTEST2084);
- break;
- case gfx::ColorSpace::TransferID::SMPTEST428_1:
- transfer_id =
- V8ColorSpaceTransferID(V8ColorSpaceTransferID::Enum::kSmptest4281);
- break;
- default:;
- }
- if (transfer_id) {
- video_color_space->setTransferID(*transfer_id);
- }
-
- gfx::ColorSpace::MatrixID matrix = gfx_color_space.GetMatrixID();
- absl::optional<V8ColorSpaceMatrixID> matrix_id;
- switch (matrix) {
- case gfx::ColorSpace::MatrixID::RGB:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kRGB);
- break;
- case gfx::ColorSpace::MatrixID::BT709:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kBT709);
- break;
- case gfx::ColorSpace::MatrixID::FCC:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kFCC);
- break;
- case gfx::ColorSpace::MatrixID::BT470BG:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kBT470BG);
- break;
- case gfx::ColorSpace::MatrixID::SMPTE170M:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kSMPTE170M);
- break;
- case gfx::ColorSpace::MatrixID::SMPTE240M:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kSMPTE240M);
- break;
- case gfx::ColorSpace::MatrixID::YCOCG:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kYCOCG);
- break;
- case gfx::ColorSpace::MatrixID::BT2020_NCL:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kBt2020Ncl);
- break;
- case gfx::ColorSpace::MatrixID::BT2020_CL:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kBt2020Cl);
- break;
- case gfx::ColorSpace::MatrixID::YDZDX:
- matrix_id = V8ColorSpaceMatrixID(V8ColorSpaceMatrixID::Enum::kYDZDX);
- break;
- default:;
- }
- if (matrix_id) {
- video_color_space->setMatrixID(*matrix_id);
- }
-
- gfx::ColorSpace::RangeID range = gfx_color_space.GetRangeID();
- absl::optional<V8ColorSpaceRangeID> range_id;
- switch (range) {
- case gfx::ColorSpace::RangeID::LIMITED:
- range_id = V8ColorSpaceRangeID(V8ColorSpaceRangeID::Enum::kLIMITED);
- break;
- case gfx::ColorSpace::RangeID::FULL:
- range_id = V8ColorSpaceRangeID(V8ColorSpaceRangeID::Enum::kFULL);
- break;
- case gfx::ColorSpace::RangeID::DERIVED:
- range_id = V8ColorSpaceRangeID(V8ColorSpaceRangeID::Enum::kDERIVED);
- break;
- default:;
- }
- if (range_id) {
- video_color_space->setRangeID(*range_id);
- }
-}
-
void GetMediaTaskRunnerAndGpuFactoriesOnMainThread(
scoped_refptr<base::SingleThreadTaskRunner>* media_task_runner_out,
media::GpuVideoAcceleratorFactories** gpu_factories_out,
@@ -423,15 +241,12 @@ WebGLWebCodecsVideoFrameHandle* WebGLWebCodecsVideoFrame::importVideoFrame(
src_color_space = src_color_space.GetAsFullRangeRGB();
#endif
VideoColorSpace* video_frame_color_space =
- MakeGarbageCollected<VideoColorSpace>();
- FillVideoColorSpace(video_frame_color_space, src_color_space);
+ MakeGarbageCollected<VideoColorSpace>(src_color_space);
video_frame_handle->setColorSpace(video_frame_color_space);
gfx::ColorSpace dst_color_space = gfx::ColorSpace::CreateSRGB();
std::unique_ptr<gfx::ColorTransform> color_transform(
- gfx::ColorTransform::NewColorTransform(
- src_color_space, dst_color_space,
- gfx::ColorTransform::Intent::INTENT_ABSOLUTE));
+ gfx::ColorTransform::NewColorTransform(src_color_space, dst_color_space));
video_frame_handle->setColorConversionShaderFunc(
color_transform->GetShaderSource().c_str());
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h
index 644d01c105f..cac7c867f8a 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h
@@ -10,6 +10,10 @@
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
+namespace base {
+class WaitableEvent;
+} // namespace base
+
namespace media {
class GpuMemoryBufferVideoFramePool;
} // namespace media
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
index b243f9fab31..cf9279a1960 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -43,6 +43,8 @@ blink_modules_sources("webgpu") {
"gpu_device.h",
"gpu_device_lost_info.cc",
"gpu_device_lost_info.h",
+ "gpu_external_texture.cc",
+ "gpu_external_texture.h",
"gpu_map_mode.h",
"gpu_out_of_memory_error.cc",
"gpu_out_of_memory_error.h",
@@ -69,10 +71,13 @@ blink_modules_sources("webgpu") {
"gpu_shader_stage.h",
"gpu_supported_features.cc",
"gpu_supported_features.h",
+ "gpu_supported_limits.cc",
+ "gpu_supported_limits.h",
"gpu_swap_chain.cc",
"gpu_swap_chain.h",
"gpu_texture.cc",
"gpu_texture.h",
+ "gpu_texture_usage.cc",
"gpu_texture_usage.h",
"gpu_texture_view.cc",
"gpu_texture_view.h",
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/DEPS b/chromium/third_party/blink/renderer/modules/webgpu/DEPS
index 879830483db..55b27bec5c3 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webgpu/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+gpu/command_buffer/common/mailbox.h",
"+gpu/command_buffer/common/shared_image_usage.h",
"+gpu/command_buffer/common/sync_token.h",
+ "+gpu/command_buffer/client/raster_interface.h",
"+gpu/command_buffer/client/shared_image_interface.h",
"+gpu/command_buffer/client/webgpu_interface.h",
"+media/base/video_frame.h",
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/dawn_callback.h b/chromium/third_party/blink/renderer/modules/webgpu/dawn_callback.h
index 812ac5b4908..33f4aedcf6a 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_callback.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_callback.h
@@ -17,8 +17,8 @@ namespace blink {
// void* and passed to Dawn C callbacks.
//
// Example:
-// DawnCallback<F>* callback =
-// CreateDawnCallback(WTF::Bind(func, arg1));
+// DawnOnceCallback<F>* callback =
+// BindDawnOnceCallback(func, arg1);
//
// // |someDawnFunction| expects callback function with arguments:
// // Args... args, void* userdata.
@@ -26,81 +26,119 @@ namespace blink {
// GetProcs().someDawnFunction(
// callback->UnboundCallback(), callback->AsUserdata());
template <typename Callback>
-class DawnCallback;
+class DawnCallbackBase;
+
+template <typename Callback>
+class DawnOnceCallback;
+
+template <typename Callback>
+class DawnRepeatingCallback;
template <template <typename> class BaseCallbackTemplate,
typename R,
typename... Args>
-class DawnCallback<BaseCallbackTemplate<R(Args...)>> {
+class DawnCallbackBase<BaseCallbackTemplate<R(Args...)>> {
using BaseCallback = BaseCallbackTemplate<R(Args...)>;
- using UnboundCallbackFunction = R (*)(Args..., void*);
+ static constexpr bool is_once_callback =
+ std::is_same<BaseCallback, base::OnceCallback<R(Args...)>>::value;
+ static constexpr bool is_repeating_callback =
+ std::is_same<BaseCallback, base::RepeatingCallback<R(Args...)>>::value;
static_assert(
- std::is_same<BaseCallback, base::OnceCallback<R(Args...)>>::value ||
- std::is_same<BaseCallback,
- base::RepeatingCallback<R(Args...)>>::value,
+ is_once_callback || is_repeating_callback,
"Callback must be base::OnceCallback or base::RepeatingCallback");
public:
- explicit DawnCallback(BaseCallback callback)
+ explicit DawnCallbackBase(BaseCallback callback)
: callback_(std::move(callback)) {}
+ void* AsUserdata() { return static_cast<void*>(this); }
+
+ protected:
+ using UnboundCallbackFunction = R (*)(Args..., void*);
+
+ static DawnCallbackBase* FromUserdata(void* userdata) {
+ return static_cast<DawnCallbackBase*>(userdata);
+ }
+
R Run(Args... args) && {
+ static_assert(
+ is_once_callback,
+ "Run on a moved receiver must only be called on a once callback.");
return std::move(callback_).Run(std::forward<Args>(args)...);
}
R Run(Args... args) const& {
+ static_assert(is_repeating_callback,
+ "Run on a unmoved receiver must only be called on a "
+ "repeating callback.");
return callback_.Run(std::forward<Args>(args)...);
}
- void Reset() { callback_.Reset(); }
+ private:
+ BaseCallback callback_;
+};
+
+template <typename R, typename... Args>
+class DawnOnceCallback<R(Args...)>
+ : public DawnCallbackBase<base::OnceCallback<R(Args...)>> {
+ using BaseCallback = base::OnceCallback<R(Args...)>;
+
+ public:
+ using DawnCallbackBase<BaseCallback>::DawnCallbackBase;
- static R CallUnboundCallback(Args... args, void* handle) {
+ typename DawnCallbackBase<BaseCallback>::UnboundCallbackFunction
+ UnboundCallback() {
+ return CallUnboundOnceCallback;
+ }
+
+ private:
+ static R CallUnboundOnceCallback(Args... args, void* handle) {
// After this non-repeating callback is run, it should delete itself.
auto callback =
- std::unique_ptr<DawnCallback>(DawnCallback::FromUserdata(handle));
+ std::unique_ptr<DawnOnceCallback>(static_cast<DawnOnceCallback*>(
+ DawnCallbackBase<BaseCallback>::FromUserdata(handle)));
return std::move(*callback).Run(std::forward<Args>(args)...);
}
+};
- static R CallUnboundRepeatingCallback(Args... args, void* handle) {
- return DawnCallback::FromUserdata(handle)->Run(std::forward<Args>(args)...);
- }
+template <typename R, typename... Args>
+class DawnRepeatingCallback<R(Args...)>
+ : public DawnCallbackBase<base::RepeatingCallback<R(Args...)>> {
+ using BaseCallback = base::RepeatingCallback<R(Args...)>;
- UnboundCallbackFunction UnboundCallback() { return CallUnboundCallback; }
+ public:
+ using DawnCallbackBase<BaseCallback>::DawnCallbackBase;
- UnboundCallbackFunction UnboundRepeatingCallback() {
+ typename DawnCallbackBase<BaseCallback>::UnboundCallbackFunction
+ UnboundCallback() {
return CallUnboundRepeatingCallback;
}
- void* AsUserdata() { return static_cast<void*>(this); }
-
- static DawnCallback* FromUserdata(void* userdata) {
- return static_cast<DawnCallback*>(userdata);
- }
-
private:
- BaseCallback callback_;
+ static R CallUnboundRepeatingCallback(Args... args, void* handle) {
+ return static_cast<DawnRepeatingCallback*>(
+ DawnCallbackBase<BaseCallback>::FromUserdata(handle))
+ ->Run(std::forward<Args>(args)...);
+ }
};
-template <typename CallbackType>
-DawnCallback<CallbackType>* CreateDawnCallback(CallbackType cb) {
- return new DawnCallback<CallbackType>(std::move(cb));
-}
-
template <typename FunctionType, typename... BoundParameters>
-auto BindDawnCallback(FunctionType&& function,
- BoundParameters&&... bound_parameters) {
- return CreateDawnCallback(
- WTF::Bind(std::forward<FunctionType>(function),
- std::forward<BoundParameters>(bound_parameters)...));
+auto BindDawnOnceCallback(FunctionType&& function,
+ BoundParameters&&... bound_parameters) {
+ auto cb = WTF::Bind(std::forward<FunctionType>(function),
+ std::forward<BoundParameters>(bound_parameters)...);
+ return new DawnOnceCallback<typename decltype(cb)::RunType>(std::move(cb));
}
template <typename FunctionType, typename... BoundParameters>
-auto BindRepeatingDawnCallback(FunctionType&& function,
+auto BindDawnRepeatingCallback(FunctionType&& function,
BoundParameters&&... bound_parameters) {
- return CreateDawnCallback(
+ auto cb =
WTF::BindRepeating(std::forward<FunctionType>(function),
- std::forward<BoundParameters>(bound_parameters)...));
+ std::forward<BoundParameters>(bound_parameters)...);
+ return std::make_unique<
+ DawnRepeatingCallback<typename decltype(cb)::RunType>>(std::move(cb));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc b/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
index 82df52bbe86..b7159e42f50 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
@@ -6,16 +6,16 @@
#include <dawn/webgpu.h>
-#include "third_party/blink/renderer/bindings/modules/v8/double_sequence_or_gpu_color_dict.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_extent_3d_dict.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_origin_3d_dict.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_dict.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_extent_3d_dict.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_data_layout.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_index_format.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_origin_3d_dict.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_programmable_stage.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_doublesequence_gpucolordict.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpuextent3ddict_unsignedlongenforcerangesequence.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpuorigin3ddict_unsignedlongenforcerangesequence.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_shader_module.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
@@ -45,7 +45,6 @@ WGPUColor AsDawnType(const GPUColorDict* webgpu_color) {
return dawn_color;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WGPUColor AsDawnType(const V8GPUColor* webgpu_color) {
DCHECK(webgpu_color);
@@ -59,34 +58,12 @@ WGPUColor AsDawnType(const V8GPUColor* webgpu_color) {
NOTREACHED();
return WGPUColor{};
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WGPUColor AsDawnType(const DoubleSequenceOrGPUColorDict* webgpu_color) {
- DCHECK(webgpu_color);
- if (webgpu_color->IsDoubleSequence()) {
- return AsDawnColor(webgpu_color->GetAsDoubleSequence());
- } else if (webgpu_color->IsGPUColorDict()) {
- return AsDawnType(webgpu_color->GetAsGPUColorDict());
- }
- NOTREACHED();
- WGPUColor dawn_color = {};
- return dawn_color;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WGPUExtent3D AsDawnType(const V8GPUExtent3D* webgpu_extent, GPUDevice* device) {
+WGPUExtent3D AsDawnType(const V8GPUExtent3D* webgpu_extent) {
DCHECK(webgpu_extent);
// Set all extents to their default value of 1.
- // TODO (crbug.com/1206740): The last member of WGPUExtent3D (depth) is being
- // removed from Dawn soon, but until it has been removed it must be set to 1
- // or the correct value, in depthOrArrayLayers, will be ignored. Once depth
- // has been removed from WGPUExtent3D in Dawn this can be to be updated to
- // WGPUExtent3D dawn_extent = {1, 1, 1};
- WGPUExtent3D dawn_extent;
- uint32_t extent_defaults[4] = {1, 1, 1, 1};
- memcpy(&dawn_extent, extent_defaults, sizeof(WGPUExtent3D));
+ WGPUExtent3D dawn_extent = {1, 1, 1};
switch (webgpu_extent->GetContentType()) {
case V8GPUExtent3D::ContentType::kGPUExtent3DDict: {
@@ -123,92 +100,42 @@ WGPUExtent3D AsDawnType(const V8GPUExtent3D* webgpu_extent, GPUDevice* device) {
return dawn_extent;
}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-WGPUExtent3D AsDawnType(
- const UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict* webgpu_extent,
- GPUDevice* device) {
- DCHECK(webgpu_extent);
-
- // Set all extents to their default value of 1.
- // TODO (crbug.com/1206740): The last member of WGPUExtent3D (depth) is being
- // removed from Dawn soon, but until it has been removed it must be set to 1
- // or the correct value, in depthOrArrayLayers, will be ignored. Once depth
- // has been removed from WGPUExtent3D in Dawn this can be to be updated to
- // WGPUExtent3D dawn_extent = {1, 1, 1};
- WGPUExtent3D dawn_extent;
- uint32_t extent_defaults[4] = {1, 1, 1, 1};
- memcpy(&dawn_extent, extent_defaults, sizeof(WGPUExtent3D));
-
- if (webgpu_extent->IsUnsignedLongEnforceRangeSequence()) {
- const Vector<uint32_t>& webgpu_extent_sequence =
- webgpu_extent->GetAsUnsignedLongEnforceRangeSequence();
-
- // The WebGPU spec states that if the sequence isn't big enough then the
- // default values of 1 are used (which are set above).
- switch (webgpu_extent_sequence.size()) {
- default:
- dawn_extent.depthOrArrayLayers = webgpu_extent_sequence[2];
- FALLTHROUGH;
- case 2:
- dawn_extent.height = webgpu_extent_sequence[1];
- FALLTHROUGH;
- case 1:
- dawn_extent.width = webgpu_extent_sequence[0];
- FALLTHROUGH;
- case 0:
- break;
- }
-
- } else if (webgpu_extent->IsGPUExtent3DDict()) {
- const GPUExtent3DDict* webgpu_extent_3d_dict =
- webgpu_extent->GetAsGPUExtent3DDict();
- dawn_extent.width = webgpu_extent_3d_dict->width();
- dawn_extent.height = webgpu_extent_3d_dict->height();
- dawn_extent.depthOrArrayLayers =
- webgpu_extent_3d_dict->depthOrArrayLayers();
- } else {
- NOTREACHED();
- }
-
- return dawn_extent;
-}
-WGPUOrigin3D AsDawnType(
- const UnsignedLongEnforceRangeSequenceOrGPUOrigin3DDict* webgpu_origin) {
+WGPUOrigin3D AsDawnType(const V8GPUOrigin3D* webgpu_origin) {
DCHECK(webgpu_origin);
WGPUOrigin3D dawn_origin = {0, 0, 0};
- if (webgpu_origin->IsUnsignedLongEnforceRangeSequence()) {
- const Vector<uint32_t>& webgpu_origin_sequence =
- webgpu_origin->GetAsUnsignedLongEnforceRangeSequence();
-
- // The WebGPU spec states that if the sequence isn't big enough then the
- // default values of 0 are used (which are set above).
- switch (webgpu_origin_sequence.size()) {
- default:
- dawn_origin.z = webgpu_origin_sequence[2];
- FALLTHROUGH;
- case 2:
- dawn_origin.y = webgpu_origin_sequence[1];
- FALLTHROUGH;
- case 1:
- dawn_origin.x = webgpu_origin_sequence[0];
- FALLTHROUGH;
- case 0:
- break;
+ switch (webgpu_origin->GetContentType()) {
+ case V8GPUOrigin3D::ContentType::kGPUOrigin3DDict: {
+ const GPUOrigin3DDict* webgpu_origin_3d_dict =
+ webgpu_origin->GetAsGPUOrigin3DDict();
+ dawn_origin.x = webgpu_origin_3d_dict->x();
+ dawn_origin.y = webgpu_origin_3d_dict->y();
+ dawn_origin.z = webgpu_origin_3d_dict->z();
+ break;
}
+ case V8GPUOrigin3D::ContentType::kUnsignedLongEnforceRangeSequence: {
+ const Vector<uint32_t>& webgpu_origin_sequence =
+ webgpu_origin->GetAsUnsignedLongEnforceRangeSequence();
- } else if (webgpu_origin->IsGPUOrigin3DDict()) {
- const GPUOrigin3DDict* webgpu_origin_3d_dict =
- webgpu_origin->GetAsGPUOrigin3DDict();
- dawn_origin.x = webgpu_origin_3d_dict->x();
- dawn_origin.y = webgpu_origin_3d_dict->y();
- dawn_origin.z = webgpu_origin_3d_dict->z();
-
- } else {
- NOTREACHED();
+ // The WebGPU spec states that if the sequence isn't big enough then the
+ // default values of 0 are used (which are set above).
+ switch (webgpu_origin_sequence.size()) {
+ default:
+ dawn_origin.z = webgpu_origin_sequence[2];
+ FALLTHROUGH;
+ case 2:
+ dawn_origin.y = webgpu_origin_sequence[1];
+ FALLTHROUGH;
+ case 1:
+ dawn_origin.x = webgpu_origin_sequence[0];
+ FALLTHROUGH;
+ case 0:
+ break;
+ }
+ break;
+ }
}
return dawn_origin;
@@ -222,7 +149,7 @@ WGPUTextureCopyView AsDawnType(const GPUImageCopyTexture* webgpu_view,
WGPUTextureCopyView dawn_view = {};
dawn_view.texture = webgpu_view->texture()->GetHandle();
dawn_view.mipLevel = webgpu_view->mipLevel();
- dawn_view.origin = AsDawnType(&webgpu_view->origin());
+ dawn_view.origin = AsDawnType(webgpu_view->origin());
dawn_view.aspect = AsDawnEnum<WGPUTextureAspect>(webgpu_view->aspect());
return dawn_view;
@@ -284,4 +211,25 @@ OwnedProgrammableStageDescriptor AsDawnType(
return std::make_tuple(dawn_stage, std::move(entry_point_keepalive));
}
+WGPUTextureFormat AsDawnType(SkColorType color_type) {
+ switch (color_type) {
+ case SkColorType::kRGBA_8888_SkColorType:
+ return WGPUTextureFormat_RGBA8Unorm;
+ case SkColorType::kBGRA_8888_SkColorType:
+ return WGPUTextureFormat_BGRA8Unorm;
+ case SkColorType::kRGBA_1010102_SkColorType:
+ return WGPUTextureFormat_RGB10A2Unorm;
+ case SkColorType::kRGBA_F16_SkColorType:
+ return WGPUTextureFormat_RGBA16Float;
+ case SkColorType::kRGBA_F32_SkColorType:
+ return WGPUTextureFormat_RGBA32Float;
+ case SkColorType::kR8G8_unorm_SkColorType:
+ return WGPUTextureFormat_RG8Unorm;
+ case SkColorType::kR16G16_float_SkColorType:
+ return WGPUTextureFormat_RG16Float;
+ default:
+ return WGPUTextureFormat_Undefined;
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h b/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h
index 98147802445..b5356a35e76 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h
@@ -21,33 +21,23 @@
namespace blink {
-class DoubleSequenceOrGPUColorDict;
class GPUColorDict;
class GPUProgrammableStage;
class GPUImageCopyTexture;
class GPUImageDataLayout;
-class UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict;
-class UnsignedLongEnforceRangeSequenceOrGPUOrigin3DDict;
// These conversions are used multiple times and are declared here. Conversions
// used only once, for example for object construction, are defined
// individually.
WGPUColor AsDawnColor(const Vector<double>&);
WGPUColor AsDawnType(const GPUColorDict*);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WGPUColor AsDawnType(const V8GPUColor* webgpu_color);
-WGPUExtent3D AsDawnType(const V8GPUExtent3D* webgpu_extent, GPUDevice* device);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WGPUColor AsDawnType(const DoubleSequenceOrGPUColorDict*);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-// TODO(crbug.com/1181288): Remove the old IDL union version.
-WGPUExtent3D AsDawnType(
- const UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict*,
- GPUDevice* device);
-WGPUOrigin3D AsDawnType(
- const UnsignedLongEnforceRangeSequenceOrGPUOrigin3DDict*);
+WGPUExtent3D AsDawnType(const V8GPUExtent3D* webgpu_extent);
+WGPUOrigin3D AsDawnType(const V8GPUOrigin3D* webgpu_extent);
WGPUTextureCopyView AsDawnType(const GPUImageCopyTexture* webgpu_view,
GPUDevice* device);
+WGPUTextureFormat AsDawnType(SkColorType color_type);
+
const char* ValidateTextureDataLayout(const GPUImageDataLayout* webgpu_layout,
WGPUTextureDataLayout* layout);
using OwnedProgrammableStageDescriptor =
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc b/chromium/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
index 9b4b3bbf2d2..e37382f33ce 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.h"
#include "base/check.h"
+#include "base/notreached.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_index_format.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -429,8 +430,11 @@ WGPUStoreOp AsDawnEnum<WGPUStoreOp>(const WTF::String& webgpu_enum) {
if (webgpu_enum == "store") {
return WGPUStoreOp_Store;
}
+ if (webgpu_enum == "discard") {
+ return WGPUStoreOp_Discard;
+ }
if (webgpu_enum == "clear") {
- return WGPUStoreOp_Clear;
+ return WGPUStoreOp_Discard;
}
NOTREACHED();
return WGPUStoreOp_Force32;
@@ -579,16 +583,16 @@ WGPUBlendOperation AsDawnEnum<WGPUBlendOperation>(
}
template <>
-WGPUInputStepMode AsDawnEnum<WGPUInputStepMode>(
+WGPUVertexStepMode AsDawnEnum<WGPUVertexStepMode>(
const WTF::String& webgpu_enum) {
if (webgpu_enum == "vertex") {
- return WGPUInputStepMode_Vertex;
+ return WGPUVertexStepMode_Vertex;
}
if (webgpu_enum == "instance") {
- return WGPUInputStepMode_Instance;
+ return WGPUVertexStepMode_Instance;
}
NOTREACHED();
- return WGPUInputStepMode_Force32;
+ return WGPUVertexStepMode_Force32;
}
template <>
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc b/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc
index 5664f7540ca..0ffe2d1ec07 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc
@@ -19,10 +19,6 @@ DawnObjectBase::GetDawnControlClient() const {
return dawn_control_client_;
}
-gpu::webgpu::WebGPUInterface* DawnObjectBase::GetInterface() const {
- return dawn_control_client_->GetInterface();
-}
-
void DawnObjectBase::setLabel(const String& value) {
// TODO: Relay label changes to Dawn
label_ = value;
@@ -30,7 +26,11 @@ void DawnObjectBase::setLabel(const String& value) {
void DawnObjectBase::EnsureFlush() {
bool needs_flush = false;
- GetInterface()->EnsureAwaitingFlush(&needs_flush);
+ auto context_provider = GetContextProviderWeakPtr();
+ if (UNLIKELY(!context_provider))
+ return;
+ context_provider->ContextProvider()->WebGPUInterface()->EnsureAwaitingFlush(
+ &needs_flush);
if (!needs_flush) {
// We've already enqueued a task to flush, or the command buffer
// is empty. Do nothing.
@@ -38,14 +38,22 @@ void DawnObjectBase::EnsureFlush() {
}
Microtask::EnqueueMicrotask(WTF::Bind(
[](scoped_refptr<DawnControlClientHolder> dawn_control_client) {
- dawn_control_client->GetInterface()->FlushAwaitingCommands();
+ if (auto context_provider =
+ dawn_control_client->GetContextProviderWeakPtr()) {
+ context_provider->ContextProvider()
+ ->WebGPUInterface()
+ ->FlushAwaitingCommands();
+ }
},
dawn_control_client_));
}
// Flush commands up until now on this object's parent device immediately.
void DawnObjectBase::FlushNow() {
- GetInterface()->FlushCommands();
+ auto context_provider = GetContextProviderWeakPtr();
+ if (LIKELY(context_provider)) {
+ context_provider->ContextProvider()->WebGPUInterface()->FlushCommands();
+ }
}
DawnObjectImpl::DawnObjectImpl(GPUDevice* device)
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h b/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h
index c62edacbe3f..eb608ca1f04 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h
@@ -23,6 +23,7 @@
X(ComputePassEncoder, computePassEncoder) \
X(ComputePipeline, computePipeline) \
X(Device, device) \
+ X(ExternalTexture, externalTexture) \
X(Instance, instance) \
X(PipelineLayout, pipelineLayout) \
X(QuerySet, querySet) \
@@ -72,7 +73,10 @@ class DawnObjectBase {
scoped_refptr<DawnControlClientHolder> dawn_control_client);
const scoped_refptr<DawnControlClientHolder>& GetDawnControlClient() const;
- gpu::webgpu::WebGPUInterface* GetInterface() const;
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> GetContextProviderWeakPtr()
+ const {
+ return dawn_control_client_->GetContextProviderWeakPtr();
+ }
const DawnProcTable& GetProcs() const {
return dawn_control_client_->GetProcs();
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
index e3be8df8fb6..47cdbeda554 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -7,9 +7,12 @@
#include <utility>
#include "gpu/command_buffer/client/webgpu_interface.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/gpu/gpu.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/bindings/core/v8/script_promise_resolver.h"
@@ -19,6 +22,7 @@
#include "third_party/blink/renderer/core/execution_context/navigator_base.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_supported_features.h"
#include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -71,6 +75,20 @@ std::unique_ptr<WebGraphicsContext3DProvider> CreateContextProvider(
context_provider = CreateContextProviderOnMainThread(url);
}
+ // Note that we check for API blocking *after* creating the context. This is
+ // because context creation synchronizes against GpuProcessHost lifetime in
+ // the browser process, and GpuProcessHost destruction is what updates API
+ // blocking state on a GPU process crash. See https://crbug.com/1215907#c10
+ // for more details.
+ bool blocked = true;
+ mojo::Remote<mojom::blink::GpuDataManager> gpu_data_manager;
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
+ gpu_data_manager.BindNewPipeAndPassReceiver());
+ gpu_data_manager->Are3DAPIsBlockedForUrl(url, &blocked);
+ if (blocked) {
+ return nullptr;
+ }
+
// TODO(kainino): we will need a better way of accessing the GPU interface
// from multiple threads than BindToCurrentThread et al.
if (context_provider && !context_provider->BindToCurrentThread()) {
@@ -106,9 +124,19 @@ void GPU::Trace(Visitor* visitor) const {
ScriptWrappable::Trace(visitor);
Supplement<NavigatorBase>::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
+ visitor->Trace(mappable_buffers_);
}
void GPU::ContextDestroyed() {
+ if (!mappable_buffers_.IsEmpty()) {
+ // Destroy all mappable buffers. This ensures all mappings backed by
+ // shared memory are detached before the WebGPU command buffer and
+ // transfer buffers are destroyed.
+ v8::Isolate* isolate = ThreadState::Current()->GetIsolate();
+ for (GPUBuffer* buffer : mappable_buffers_) {
+ buffer->Destroy(isolate);
+ }
+ }
if (!dawn_control_client_) {
return;
}
@@ -124,7 +152,7 @@ void GPU::OnRequestAdapterCallback(ScriptState* script_state,
GPUAdapter* adapter = nullptr;
if (adapter_server_id >= 0) {
adapter = MakeGarbageCollected<GPUAdapter>(
- "Default", adapter_server_id, properties, dawn_control_client_);
+ this, "Default", adapter_server_id, properties, dawn_control_client_);
}
if (error_message) {
ExecutionContext* execution_context = ExecutionContext::From(script_state);
@@ -192,13 +220,18 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state,
} else {
// Make a new DawnControlClientHolder with the context provider we just
// made and set the lost context callback
- dawn_control_client_ = base::MakeRefCounted<DawnControlClientHolder>(
+ dawn_control_client_ = DawnControlClientHolder::Create(
std::move(context_provider),
execution_context->GetTaskRunner(TaskType::kWebGPU));
- dawn_control_client_->SetLostContextCallback();
}
}
+ // Software adapters are not currently supported.
+ if (options->forceSoftware() == true) {
+ resolver->Resolve(v8::Null(script_state->GetIsolate()));
+ return promise;
+ }
+
// For now we choose kHighPerformance by default.
gpu::webgpu::PowerPreference power_preference =
gpu::webgpu::PowerPreference::kHighPerformance;
@@ -207,7 +240,9 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state,
power_preference = gpu::webgpu::PowerPreference::kLowPower;
}
- dawn_control_client_->GetInterface()->RequestAdapterAsync(
+ auto context_provider = dawn_control_client_->GetContextProviderWeakPtr();
+ DCHECK(context_provider);
+ context_provider->ContextProvider()->WebGPUInterface()->RequestAdapterAsync(
power_preference,
WTF::Bind(&GPU::OnRequestAdapterCallback, WrapPersistent(this),
WrapPersistent(script_state), WrapPersistent(options),
@@ -218,4 +253,8 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state,
return promise;
}
+void GPU::TrackMappableBuffer(GPUBuffer* buffer) {
+ mappable_buffers_.insert(buffer);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu.h
index abdbd28995a..54ddcd9112a 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu.h
@@ -17,6 +17,7 @@ struct WGPUDeviceProperties;
namespace blink {
class GPUAdapter;
+class GPUBuffer;
class GPURequestAdapterOptions;
class NavigatorBase;
class ScriptPromiseResolver;
@@ -47,6 +48,13 @@ class GPU final : public ScriptWrappable,
ScriptPromise requestAdapter(ScriptState* script_state,
const GPURequestAdapterOptions* options);
+ // Store the buffer in a weak hash set so we can destroy it when the
+ // context is destroyed. Note: there is no need to "untrack" buffers
+ // because Oilpan automatically removes them from the weak hash set
+ // when the GPUBuffer is garbage-collected.
+ // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md#weak-collections
+ void TrackMappableBuffer(GPUBuffer* buffer);
+
private:
void OnRequestAdapterCallback(ScriptState* script_state,
const GPURequestAdapterOptions* options,
@@ -60,6 +68,7 @@ class GPU final : public ScriptWrappable,
GPUAdapter* adapter) const;
scoped_refptr<DawnControlClientHolder> dawn_control_client_;
+ HeapHashSet<WeakMember<GPUBuffer>> mappable_buffers_;
DISALLOW_COPY_AND_ASSIGN(GPU);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
index 29baf708385..44ea86fe22a 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -11,8 +11,10 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_request_adapter_options.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_supported_features.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
@@ -21,7 +23,7 @@ namespace {
WGPUDeviceProperties AsDawnType(const GPUDeviceDescriptor* descriptor) {
DCHECK_NE(nullptr, descriptor);
- auto&& feature_names = descriptor->nonGuaranteedFeatures();
+ auto&& feature_names = descriptor->requiredFeatures();
HashSet<String> feature_set;
for (auto& feature : feature_names)
@@ -43,9 +45,11 @@ WGPUDeviceProperties AsDawnType(const GPUDeviceDescriptor* descriptor) {
return requested_device_properties;
}
+
} // anonymous namespace
GPUAdapter::GPUAdapter(
+ GPU* gpu,
const String& name,
uint32_t adapter_service_id,
const WGPUDeviceProperties& properties,
@@ -53,7 +57,9 @@ GPUAdapter::GPUAdapter(
: DawnObjectBase(dawn_control_client),
name_(name),
adapter_service_id_(adapter_service_id),
- adapter_properties_(properties) {
+ adapter_properties_(properties),
+ gpu_(gpu),
+ limits_(MakeGarbageCollected<GPUSupportedLimits>()) {
InitializeFeatureNameList();
}
@@ -85,11 +91,12 @@ GPUSupportedFeatures* GPUAdapter::features() const {
return features_;
}
-void GPUAdapter::OnRequestDeviceCallback(ScriptPromiseResolver* resolver,
+void GPUAdapter::OnRequestDeviceCallback(ScriptState* script_state,
+ ScriptPromiseResolver* resolver,
const GPUDeviceDescriptor* descriptor,
WGPUDevice dawn_device) {
if (dawn_device) {
- ExecutionContext* execution_context = resolver->GetExecutionContext();
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
auto* device = MakeGarbageCollected<GPUDevice>(execution_context,
GetDawnControlClient(), this,
dawn_device, descriptor);
@@ -129,18 +136,66 @@ ScriptPromise GPUAdapter::requestDevice(ScriptState* script_state,
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
+ // Normalize the device descriptor to avoid using the deprecated fields.
+ if (descriptor->nonGuaranteedFeatures().size() > 0) {
+ AddConsoleWarning(
+ resolver->GetExecutionContext(),
+ "nonGuaranteedFeatures is deprecated. Use requiredFeatures instead.");
+ descriptor->setRequiredFeatures(descriptor->nonGuaranteedFeatures());
+ }
+ if (descriptor->hasNonGuaranteedLimits()) {
+ AddConsoleWarning(
+ resolver->GetExecutionContext(),
+ "nonGuaranteedLimits is deprecated. Use requiredLimits instead.");
+ descriptor->setRequiredLimits(descriptor->nonGuaranteedLimits());
+ }
+
+ // Validation of the limits could happen in Dawn, but until that's
+ // implemented we can do it here to preserve the spec behavior.
+ if (descriptor->hasRequiredLimits()) {
+ for (const auto& key_value_pair : descriptor->requiredLimits()) {
+ switch (
+ limits_->ValidateLimit(key_value_pair.first, key_value_pair.second)) {
+ case GPUSupportedLimits::ValidationResult::Valid:
+ break;
+ case GPUSupportedLimits::ValidationResult::BadName: {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kOperationError, "The limit name \"" +
+ key_value_pair.first +
+ "\" is not recognized."));
+ return promise;
+ }
+ case GPUSupportedLimits::ValidationResult::BadValue: {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kOperationError,
+ "The limit requested for \"" + key_value_pair.first +
+ "\" exceeds the adapter's supported limit."));
+ return promise;
+ }
+ }
+ }
+ }
+
WGPUDeviceProperties requested_device_properties = AsDawnType(descriptor);
- GetInterface()->RequestDeviceAsync(
- adapter_service_id_, requested_device_properties,
- WTF::Bind(&GPUAdapter::OnRequestDeviceCallback, WrapPersistent(this),
- WrapPersistent(resolver), WrapPersistent(descriptor)));
+ if (auto context_provider = GetContextProviderWeakPtr()) {
+ context_provider->ContextProvider()->WebGPUInterface()->RequestDeviceAsync(
+ adapter_service_id_, requested_device_properties,
+ WTF::Bind(&GPUAdapter::OnRequestDeviceCallback, WrapPersistent(this),
+ WrapPersistent(script_state), WrapPersistent(resolver),
+ WrapPersistent(descriptor)));
+ } else {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kOperationError, "WebGPU context lost"));
+ }
return promise;
}
void GPUAdapter::Trace(Visitor* visitor) const {
+ visitor->Trace(gpu_);
visitor->Trace(features_);
+ visitor->Trace(limits_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
index 58e9d24436d..1bdb75dacc7 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
@@ -15,15 +15,18 @@
namespace blink {
+class GPU;
class GPUDeviceDescriptor;
class GPUSupportedFeatures;
+class GPUSupportedLimits;
class ScriptPromiseResolver;
class GPUAdapter final : public ScriptWrappable, public DawnObjectBase {
DEFINE_WRAPPERTYPEINFO();
public:
- GPUAdapter(const String& name,
+ GPUAdapter(GPU* gpu,
+ const String& name,
uint32_t adapter_service_id,
const WGPUDeviceProperties& properties,
scoped_refptr<DawnControlClientHolder> dawn_control_client);
@@ -31,18 +34,16 @@ class GPUAdapter final : public ScriptWrappable, public DawnObjectBase {
void Trace(Visitor* visitor) const override;
const String& name() const;
+ GPU* gpu() const { return gpu_; }
GPUSupportedFeatures* features() const;
- Vector<String> extensions(ExecutionContext* execution_context);
+ GPUSupportedLimits* limits() const { return limits_; }
+
+ // Software adapters are not currently supported.
+ bool isSoftware() const { return false; }
ScriptPromise requestDevice(ScriptState* script_state,
GPUDeviceDescriptor* descriptor);
- private:
- void OnRequestDeviceCallback(ScriptPromiseResolver* resolver,
- const GPUDeviceDescriptor* descriptor,
- WGPUDevice dawn_device);
- void InitializeFeatureNameList();
-
// Console warnings should generally be attributed to a GPUDevice, but in
// cases where there is no device warnings can be surfaced here. It's expected
// that very few warning will need to be shown for a given adapter, and as a
@@ -50,10 +51,19 @@ class GPUAdapter final : public ScriptWrappable, public DawnObjectBase {
void AddConsoleWarning(ExecutionContext* execution_context,
const char* message);
+ private:
+ void OnRequestDeviceCallback(ScriptState* script_state,
+ ScriptPromiseResolver* resolver,
+ const GPUDeviceDescriptor* descriptor,
+ WGPUDevice dawn_device);
+ void InitializeFeatureNameList();
+
String name_;
uint32_t adapter_service_id_;
WGPUDeviceProperties adapter_properties_;
+ Member<GPU> gpu_;
Member<GPUSupportedFeatures> features_;
+ Member<GPUSupportedLimits> limits_;
static constexpr int kMaxAllowedConsoleWarnings = 50;
int allowed_console_warnings_remaining_ = kMaxAllowedConsoleWarnings;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
index e6993e7d190..ea7037a9860 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -9,6 +9,8 @@
] interface GPUAdapter {
[HighEntropy=Direct, MeasureAs=GPUAdapter_Name] readonly attribute DOMString name;
[SameObject] readonly attribute GPUSupportedFeatures features;
+ [SameObject] readonly attribute GPUSupportedLimits limits;
+ readonly attribute boolean isSoftware;
[CallWith=ScriptState] Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc
index c329580b7dd..e3f1e16d8ac 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc
@@ -6,44 +6,76 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_bind_group_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_bind_group_entry.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_binding.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_external_texture.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_sampler.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture_view.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
-WGPUBindGroupEntry AsDawnType(const GPUBindGroupEntry* webgpu_binding) {
+WGPUBindGroupEntry AsDawnType(
+ const GPUBindGroupEntry* webgpu_binding,
+ Vector<std::unique_ptr<WGPUExternalTextureBindingEntry>>*
+ externalTextureBindingEntries) {
WGPUBindGroupEntry dawn_binding = {};
dawn_binding.binding = webgpu_binding->binding();
- if (webgpu_binding->resource().IsGPUBufferBinding()) {
- GPUBufferBinding* buffer =
- webgpu_binding->resource().GetAsGPUBufferBinding();
- dawn_binding.offset = buffer->offset();
- dawn_binding.size = buffer->hasSize() ? buffer->size() : WGPU_WHOLE_SIZE;
- dawn_binding.buffer = AsDawnType(buffer->buffer());
-
- } else if (webgpu_binding->resource().IsGPUSampler()) {
- GPUSampler* sampler = webgpu_binding->resource().GetAsGPUSampler();
- dawn_binding.sampler = AsDawnType(sampler);
-
- } else if (webgpu_binding->resource().IsGPUTextureView()) {
- GPUTextureView* texture_view =
- webgpu_binding->resource().GetAsGPUTextureView();
- dawn_binding.textureView = AsDawnType(texture_view);
-
- } else {
- NOTREACHED();
+ switch (webgpu_binding->resource()->GetContentType()) {
+ case V8GPUBindingResource::ContentType::kGPUBufferBinding: {
+ GPUBufferBinding* buffer =
+ webgpu_binding->resource()->GetAsGPUBufferBinding();
+ dawn_binding.offset = buffer->offset();
+ dawn_binding.size = buffer->hasSize() ? buffer->size() : WGPU_WHOLE_SIZE;
+ dawn_binding.buffer = AsDawnType(buffer->buffer());
+ break;
+ }
+ case V8GPUBindingResource::ContentType::kGPUSampler:
+ dawn_binding.sampler =
+ AsDawnType(webgpu_binding->resource()->GetAsGPUSampler());
+ break;
+ case V8GPUBindingResource::ContentType::kGPUTextureView:
+ dawn_binding.textureView =
+ AsDawnType(webgpu_binding->resource()->GetAsGPUTextureView());
+ break;
+ case V8GPUBindingResource::ContentType::kGPUExternalTexture:
+ std::unique_ptr<WGPUExternalTextureBindingEntry>
+ externalTextureBindingEntry =
+ std::make_unique<WGPUExternalTextureBindingEntry>();
+ externalTextureBindingEntry->externalTexture =
+ AsDawnType(webgpu_binding->resource()->GetAsGPUExternalTexture());
+ externalTextureBindingEntry->chain.sType =
+ WGPUSType_ExternalTextureBindingEntry;
+ dawn_binding.nextInChain = reinterpret_cast<WGPUChainedStruct*>(
+ externalTextureBindingEntry.get());
+ externalTextureBindingEntries->push_back(
+ std::move(externalTextureBindingEntry));
+ break;
}
return dawn_binding;
}
+std::unique_ptr<WGPUBindGroupEntry[]> AsDawnType(
+ const HeapVector<Member<GPUBindGroupEntry>>& webgpu_objects,
+ Vector<std::unique_ptr<WGPUExternalTextureBindingEntry>>*
+ externalTextureBindingEntries) {
+ wtf_size_t count = webgpu_objects.size();
+ std::unique_ptr<WGPUBindGroupEntry[]> dawn_objects(
+ new WGPUBindGroupEntry[count]);
+ for (wtf_size_t i = 0; i < count; ++i) {
+ dawn_objects[i] =
+ AsDawnType(webgpu_objects[i].Get(), externalTextureBindingEntries);
+ }
+ return dawn_objects;
+}
+
// static
GPUBindGroup* GPUBindGroup::Create(GPUDevice* device,
const GPUBindGroupDescriptor* webgpu_desc,
@@ -53,9 +85,12 @@ GPUBindGroup* GPUBindGroup::Create(GPUDevice* device,
uint32_t entry_count = 0;
std::unique_ptr<WGPUBindGroupEntry[]> entries;
+ Vector<std::unique_ptr<WGPUExternalTextureBindingEntry>>
+ externalTextureBindingEntries;
entry_count = static_cast<uint32_t>(webgpu_desc->entries().size());
if (entry_count > 0) {
- entries = AsDawnType(webgpu_desc->entries());
+ entries =
+ AsDawnType(webgpu_desc->entries(), &externalTextureBindingEntries);
}
std::string label;
@@ -72,7 +107,8 @@ GPUBindGroup* GPUBindGroup::Create(GPUDevice* device,
GPUBindGroup* bind_group = MakeGarbageCollected<GPUBindGroup>(
device, device->GetProcs().deviceCreateBindGroup(device->GetHandle(),
&dawn_desc));
- bind_group->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ bind_group->setLabel(webgpu_desc->label());
return bind_group;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl
index c71a9ff2aec..9167e255358 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-typedef (GPUSampler or GPUTextureView or GPUBufferBinding) GPUBindingResource;
+typedef (GPUSampler or GPUTextureView or GPUBufferBinding or GPUExternalTexture) GPUBindingResource;
dictionary GPUBindGroupEntry {
required GPUIndex32 binding;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.cc
index f755b4542d8..03aaf147908 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_bind_group_layout_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_bind_group_layout_entry.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_binding_layout.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_binding_layout.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_sampler_binding_layout.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_storage_texture_binding_layout.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_binding_layout.h"
@@ -18,7 +19,9 @@ namespace blink {
WGPUBindGroupLayoutEntry AsDawnType(
const GPUBindGroupLayoutEntry* webgpu_binding,
- GPUDevice* device) {
+ GPUDevice* device,
+ Vector<std::unique_ptr<WGPUExternalTextureBindingLayout>>*
+ externalTextureBindingLayouts) {
WGPUBindGroupLayoutEntry dawn_binding = {};
dawn_binding.binding = webgpu_binding->binding();
@@ -58,18 +61,33 @@ WGPUBindGroupLayoutEntry AsDawnType(
webgpu_binding->storageTexture()->viewDimension());
}
+ if (webgpu_binding->hasExternalTexture()) {
+ std::unique_ptr<WGPUExternalTextureBindingLayout>
+ externalTextureBindingLayout =
+ std::make_unique<WGPUExternalTextureBindingLayout>();
+ externalTextureBindingLayout->chain.sType =
+ WGPUSType_ExternalTextureBindingLayout;
+ dawn_binding.nextInChain = reinterpret_cast<WGPUChainedStruct*>(
+ externalTextureBindingLayout.get());
+ externalTextureBindingLayouts->push_back(
+ std::move(externalTextureBindingLayout));
+ }
+
return dawn_binding;
}
// TODO(crbug.com/1069302): Remove when unused.
std::unique_ptr<WGPUBindGroupLayoutEntry[]> AsDawnType(
const HeapVector<Member<GPUBindGroupLayoutEntry>>& webgpu_objects,
- GPUDevice* device) {
+ GPUDevice* device,
+ Vector<std::unique_ptr<WGPUExternalTextureBindingLayout>>*
+ externalTextureBindingLayouts) {
wtf_size_t count = webgpu_objects.size();
std::unique_ptr<WGPUBindGroupLayoutEntry[]> dawn_objects(
new WGPUBindGroupLayoutEntry[count]);
for (wtf_size_t i = 0; i < count; ++i) {
- dawn_objects[i] = AsDawnType(webgpu_objects[i].Get(), device);
+ dawn_objects[i] = AsDawnType(webgpu_objects[i].Get(), device,
+ externalTextureBindingLayouts);
}
return dawn_objects;
}
@@ -84,9 +102,12 @@ GPUBindGroupLayout* GPUBindGroupLayout::Create(
uint32_t entry_count = 0;
std::unique_ptr<WGPUBindGroupLayoutEntry[]> entries;
+ Vector<std::unique_ptr<WGPUExternalTextureBindingLayout>>
+ externalTextureBindingLayouts;
entry_count = static_cast<uint32_t>(webgpu_desc->entries().size());
if (entry_count > 0) {
- entries = AsDawnType(webgpu_desc->entries(), device);
+ entries = AsDawnType(webgpu_desc->entries(), device,
+ &externalTextureBindingLayouts);
}
std::string label;
@@ -102,7 +123,8 @@ GPUBindGroupLayout* GPUBindGroupLayout::Create(
GPUBindGroupLayout* layout = MakeGarbageCollected<GPUBindGroupLayout>(
device, device->GetProcs().deviceCreateBindGroupLayout(
device->GetHandle(), &dawn_desc));
- layout->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ layout->setLabel(webgpu_desc->label());
return layout;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_entry.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_entry.idl
index 7a822f70e69..3cc3e22f958 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_entry.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_entry.idl
@@ -8,6 +8,7 @@ dictionary GPUBindGroupLayoutEntry {
GPUSamplerBindingLayout sampler;
GPUTextureBindingLayout texture;
GPUStorageTextureBindingLayout storageTexture;
+ GPUExternalTextureBindingLayout externalTexture;
};
enum GPUBindingType {
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
index 16aeac0119c..6df4660641f 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -17,6 +17,8 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_callback.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_queue.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -73,7 +75,13 @@ GPUBuffer* GPUBuffer::Create(GPUDevice* device,
GPUBuffer* buffer = MakeGarbageCollected<GPUBuffer>(
device, dawn_desc.size,
device->GetProcs().deviceCreateBuffer(device->GetHandle(), &dawn_desc));
- buffer->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ buffer->setLabel(webgpu_desc->label());
+
+ if (is_mappable) {
+ device->adapter()->gpu()->TrackMappableBuffer(buffer);
+ }
+
return buffer;
}
@@ -119,12 +127,16 @@ DOMArrayBuffer* GPUBuffer::getMappedRange(ExecutionContext* execution_context,
}
void GPUBuffer::unmap(ScriptState* script_state) {
- ResetMappingState(script_state);
+ ResetMappingState(script_state->GetIsolate());
GetProcs().bufferUnmap(GetHandle());
}
void GPUBuffer::destroy(ScriptState* script_state) {
- ResetMappingState(script_state);
+ Destroy(script_state->GetIsolate());
+}
+
+void GPUBuffer::Destroy(v8::Isolate* isolate) {
+ ResetMappingState(isolate);
GetProcs().bufferDestroy(GetHandle());
}
@@ -157,8 +169,8 @@ ScriptPromise GPUBuffer::MapAsyncImpl(ScriptState* script_state,
// And send the command, leaving remaining validation to Dawn.
auto* callback =
- BindDawnCallback(&GPUBuffer::OnMapAsyncCallback, WrapPersistent(this),
- WrapPersistent(resolver));
+ BindDawnOnceCallback(&GPUBuffer::OnMapAsyncCallback, WrapPersistent(this),
+ WrapPersistent(resolver));
GetProcs().bufferMapAsync(GetHandle(), mode, map_offset, map_size,
callback->UnboundCallback(),
@@ -198,7 +210,8 @@ DOMArrayBuffer* GPUBuffer::GetMappedRangeImpl(
// This could eventually be upgrade to the max ArrayBuffer size instead of the
// max TypedArray size. See crbug.com/951196
if (range_size > v8::TypedArray::kMaxLength) {
- exception_state.ThrowRangeError(
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kOperationError,
"getMappedRange failed, size is too large for the implementation");
return nullptr;
}
@@ -348,11 +361,10 @@ DOMArrayBuffer* GPUBuffer::CreateArrayBufferForMappedData(
return array_buffer;
}
-void GPUBuffer::ResetMappingState(ScriptState* script_state) {
+void GPUBuffer::ResetMappingState(v8::Isolate* isolate) {
mapped_ranges_.clear();
for (Member<DOMArrayBuffer>& mapped_array_buffer : mapped_array_buffers_) {
- v8::Isolate* isolate = script_state->GetIsolate();
DOMArrayBuffer* array_buffer = mapped_array_buffer.Release();
DCHECK(array_buffer->IsDetachable(isolate));
@@ -362,7 +374,17 @@ void GPUBuffer::ResetMappingState(ScriptState* script_state) {
bool did_detach = array_buffer->Transfer(isolate, contents);
// |did_detach| would be false if the buffer were already detached.
- DCHECK(did_detach);
+ // Crash if it was, as this indicates that unmapping could alias the
+ // backing store, or possibly even free it out from under the
+ // ArrayBuffer. It might be difficult to be 100% certain about this
+ // invariant, so we CHECK, even in release builds. (Actually, it would be
+ // fine if the ArrayBuffer was detached without being transferred, but
+ // this isn't a common case, so it can be revisited if needed.)
+ // TODO(crbug.com/1243842): This CHECK can currently be hit easily by JS
+ // code. We need to validate against this case by preventing the
+ // ArrayBuffer from being transferred/detached by outside code.
+ CHECK(did_detach)
+ << "An ArrayBuffer from getMappedRange() was detached before unmap()";
DCHECK(array_buffer->IsDetached());
}
mapped_array_buffers_.clear();
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.h
index 4c9de6c12e2..8851318c264 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.h
@@ -51,6 +51,8 @@ class GPUBuffer : public DawnObject<WGPUBuffer> {
void unmap(ScriptState* script_state);
void destroy(ScriptState* script_state);
+ void Destroy(v8::Isolate* isolate);
+
private:
ScriptPromise MapAsyncImpl(ScriptState* script_state,
uint32_t mode,
@@ -69,7 +71,7 @@ class GPUBuffer : public DawnObject<WGPUBuffer> {
void* data,
size_t data_length,
ExecutionContext* execution_context);
- void ResetMappingState(ScriptState* script_state);
+ void ResetMappingState(v8::Isolate* isolate);
uint64_t size_;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl
index a80a73990db..b9709c14b3f 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl
@@ -4,8 +4,9 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase {
+dictionary GPUCanvasConfiguration : GPUObjectDescriptorBase {
required GPUDevice device;
required GPUTextureFormat format;
GPUTextureUsageFlags usage = 16; // GPUTextureUsage.RENDER_ATTACHMENT
+ GPUExtent3D size;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
index ad3c2c4eacb..ae8ab88c891 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -4,15 +4,16 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_canvas_context.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/bindings/modules/v8/v8_gpu_swap_chain_descriptor.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
namespace blink {
@@ -25,25 +26,24 @@ CanvasRenderingContext* GPUCanvasContext::Factory::Create(
CanvasRenderingContext* rendering_context =
MakeGarbageCollected<GPUCanvasContext>(host, attrs);
DCHECK(host);
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::kWebgpu);
return rendering_context;
}
CanvasRenderingContext::ContextType GPUCanvasContext::Factory::GetContextType()
const {
- return CanvasRenderingContext::kContextGPUPresent;
+ return CanvasRenderingContext::kContextWebGPU;
}
GPUCanvasContext::GPUCanvasContext(
CanvasRenderingContextHost* host,
const CanvasContextCreationAttributesCore& attrs)
- : CanvasRenderingContext(host, attrs) {}
+ : CanvasRenderingContext(host, attrs, CanvasRenderingAPI::kWebgpu) {}
GPUCanvasContext::~GPUCanvasContext() {}
void GPUCanvasContext::Trace(Visitor* visitor) const {
visitor->Trace(swapchain_);
+ visitor->Trace(configured_device_);
CanvasRenderingContext::Trace(visitor);
}
@@ -53,11 +53,9 @@ const IntSize& GPUCanvasContext::CanvasSize() const {
// CanvasRenderingContext implementation
CanvasRenderingContext::ContextType GPUCanvasContext::GetContextType() const {
- return CanvasRenderingContext::kContextGPUPresent;
+ return CanvasRenderingContext::kContextWebGPU;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* GPUCanvasContext::AsV8RenderingContext() {
return MakeGarbageCollected<V8RenderingContext>(this);
}
@@ -66,24 +64,12 @@ V8OffscreenRenderingContext* GPUCanvasContext::AsV8OffscreenRenderingContext() {
return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void GPUCanvasContext::SetCanvasGetContextResult(RenderingContext& result) {
- result.SetGPUCanvasContext(this);
-}
-
-void GPUCanvasContext::SetOffscreenCanvasGetContextResult(
- OffscreenRenderingContext& result) {
- result.SetGPUCanvasContext(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
void GPUCanvasContext::Stop() {
if (swapchain_) {
swapchain_->Neuter();
swapchain_ = nullptr;
}
+ configured_device_ = nullptr;
stopped_ = true;
}
@@ -94,7 +80,55 @@ cc::Layer* GPUCanvasContext::CcLayer() const {
return nullptr;
}
-void GPUCanvasContext::SetFilterQuality(SkFilterQuality filter_quality) {
+scoped_refptr<StaticBitmapImage> GPUCanvasContext::GetImage() {
+ if (!swapchain_)
+ return nullptr;
+
+ CanvasResourceParams resource_params;
+ resource_params.SetSkColorType(viz::ResourceFormatToClosestSkColorType(
+ /*gpu_compositing=*/true, swapchain_->Format()));
+
+ auto resource_provider = CanvasResourceProvider::CreateWebGPUImageProvider(
+ IntSize(swapchain_->Size()), resource_params,
+ /*is_origin_top_left=*/true);
+ if (!resource_provider)
+ return nullptr;
+
+ if (!swapchain_->CopyToResourceProvider(resource_provider.get()))
+ return nullptr;
+
+ return resource_provider->Snapshot();
+}
+
+bool GPUCanvasContext::PaintRenderingResultsToCanvas(
+ SourceDrawingBuffer source_buffer) {
+ DCHECK_EQ(source_buffer, kBackBuffer);
+ if (!swapchain_)
+ return false;
+
+ if (Host()->ResourceProvider() &&
+ Host()->ResourceProvider()->Size() != IntSize(swapchain_->Size())) {
+ Host()->DiscardResourceProvider();
+ }
+
+ CanvasResourceProvider* resource_provider =
+ Host()->GetOrCreateCanvasResourceProvider(RasterModeHint::kPreferGPU);
+
+ return CopyRenderingResultsFromDrawingBuffer(resource_provider,
+ source_buffer);
+}
+
+bool GPUCanvasContext::CopyRenderingResultsFromDrawingBuffer(
+ CanvasResourceProvider* resource_provider,
+ SourceDrawingBuffer source_buffer) {
+ DCHECK_EQ(source_buffer, kBackBuffer);
+ if (swapchain_)
+ return swapchain_->CopyToResourceProvider(resource_provider);
+ return false;
+}
+
+void GPUCanvasContext::SetFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) {
if (filter_quality != filter_quality_) {
filter_quality_ = filter_quality;
if (swapchain_) {
@@ -121,24 +155,105 @@ ImageBitmap* GPUCanvasContext::TransferToImageBitmap(
swapchain_->TransferToStaticBitmapImage());
}
-// gpu_canvas_context.idl
+// gpu_presentation_context.idl
+V8UnionHTMLCanvasElementOrOffscreenCanvas*
+GPUCanvasContext::getHTMLOrOffscreenCanvas() const {
+ if (Host()->IsOffscreenCanvas()) {
+ return MakeGarbageCollected<V8UnionHTMLCanvasElementOrOffscreenCanvas>(
+ static_cast<OffscreenCanvas*>(Host()));
+ }
+ return MakeGarbageCollected<V8UnionHTMLCanvasElementOrOffscreenCanvas>(
+ static_cast<HTMLCanvasElement*>(Host()));
+}
+
+void GPUCanvasContext::configure(const GPUCanvasConfiguration* descriptor,
+ ExceptionState& exception_state) {
+ ConfigureInternal(descriptor, exception_state);
+}
+
+void GPUCanvasContext::unconfigure() {
+ if (stopped_) {
+ return;
+ }
+
+ if (swapchain_) {
+ // Tell any previous swapchain that it will no longer be used and can
+ // destroy all its resources (and produce errors when used).
+ swapchain_->Neuter();
+ swapchain_ = nullptr;
+ }
+
+ configured_device_ = nullptr;
+}
+
+String GPUCanvasContext::getPreferredFormat(const GPUAdapter* adapter) {
+ // TODO(crbug.com/1007166): Return actual preferred format for the swap chain.
+ return "bgra8unorm";
+}
+
+GPUTexture* GPUCanvasContext::getCurrentTexture(
+ ExceptionState& exception_state) {
+ if (!configured_device_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "context is not configured");
+ return nullptr;
+ }
+ if (!swapchain_) {
+ configured_device_->InjectError(WGPUErrorType_Validation,
+ "context configuration is invalid.");
+ return GPUTexture::CreateError(configured_device_);
+ }
+ return swapchain_->getCurrentTexture();
+}
+
+// gpu_canvas_context.idl (Deprecated)
GPUSwapChain* GPUCanvasContext::configureSwapChain(
- const GPUSwapChainDescriptor* descriptor,
+ const GPUCanvasConfiguration* descriptor,
ExceptionState& exception_state) {
+ descriptor->device()->AddConsoleWarning(
+ "configureSwapChain() is deprecated. Use configure() instead and call "
+ "getCurrentTexture() directly on the context. Note that configure() must "
+ "also be called if you want to change the size of the textures returned "
+ "by getCurrentTexture()");
+ ConfigureInternal(descriptor, exception_state, true);
+ return swapchain_;
+}
+
+String GPUCanvasContext::getSwapChainPreferredFormat(
+ ExecutionContext* execution_context,
+ GPUAdapter* adapter) {
+ adapter->AddConsoleWarning(
+ execution_context,
+ "getSwapChainPreferredFormat() is deprecated. Use getPreferredFormat() "
+ "instead.");
+ return getPreferredFormat(adapter);
+}
+
+void GPUCanvasContext::ConfigureInternal(
+ const GPUCanvasConfiguration* descriptor,
+ ExceptionState& exception_state,
+ bool deprecated_resize_behavior) {
+ DCHECK(descriptor);
+
if (stopped_) {
// This is probably not possible, or at least would only happen during page
// shutdown.
exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
"canvas has been destroyed");
- return nullptr;
+ return;
}
if (swapchain_) {
// Tell any previous swapchain that it will no longer be used and can
// destroy all its resources (and produce errors when used).
swapchain_->Neuter();
+ swapchain_ = nullptr;
}
+ // Store the configured device separately, even if the configuration fails, so
+ // that errors can be generated in the appropriate error scope.
+ configured_device_ = descriptor->device();
+
WGPUTextureUsage usage = AsDawnEnum<WGPUTextureUsage>(descriptor->usage());
WGPUTextureFormat format =
AsDawnEnum<WGPUTextureFormat>(descriptor->format());
@@ -146,32 +261,51 @@ GPUSwapChain* GPUCanvasContext::configureSwapChain(
case WGPUTextureFormat_BGRA8Unorm:
break;
case WGPUTextureFormat_RGBA16Float:
- exception_state.ThrowDOMException(
- DOMExceptionCode::kUnknownError,
+ configured_device_->InjectError(
+ WGPUErrorType_Validation,
"rgba16float swap chain is not yet supported");
- return nullptr;
+ return;
default:
- exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
- "unsupported swap chain format");
- return nullptr;
+ configured_device_->InjectError(WGPUErrorType_Validation,
+ "unsupported swap chain format");
+ return;
+ }
+
+ // Set the default size.
+ IntSize size;
+ if (deprecated_resize_behavior) {
+ // A negative size will indicate to the swap chain that it should follow the
+ // deprecated behavior of resizing to match the canvas size each frame.
+ size = IntSize(-1, -1);
+ } else if (descriptor->hasSize()) {
+ WGPUExtent3D dawn_extent = AsDawnType(descriptor->size());
+ size = IntSize(dawn_extent.width, dawn_extent.height);
+
+ if (dawn_extent.depthOrArrayLayers != 1) {
+ configured_device_->InjectError(
+ WGPUErrorType_Validation,
+ "swap chain size must have depthOrArrayLayers set to 1");
+ return;
+ }
+ if (size.IsEmpty()) {
+ configured_device_->InjectError(
+ WGPUErrorType_Validation,
+ "context width and height must be greater than 0");
+ return;
+ }
+ } else {
+ size = CanvasSize();
}
swapchain_ = MakeGarbageCollected<GPUSwapChain>(
- this, descriptor->device(), usage, format, filter_quality_);
+ this, configured_device_, usage, format, filter_quality_, size);
swapchain_->CcLayer()->SetContentsOpaque(!CreationAttributes().alpha);
- swapchain_->setLabel(descriptor->label());
+ if (descriptor->hasLabel())
+ swapchain_->setLabel(descriptor->label());
// If we don't notify the host that something has changed it may never check
// for the new cc::Layer.
Host()->SetNeedsCompositingUpdate();
-
- return swapchain_;
-}
-
-String GPUCanvasContext::getSwapChainPreferredFormat(
- const GPUAdapter* adapter) {
- // TODO(crbug.com/1007166): Return actual preferred format for the swap chain.
- return "bgra8unorm";
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
index 9acb5a08100..2283627d4b2 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
@@ -15,8 +15,10 @@
namespace blink {
class GPUAdapter;
+class GPUCanvasConfiguration;
class GPUSwapChain;
-class GPUSwapChainDescriptor;
+class GPUTexture;
+class V8UnionHTMLCanvasElementOrOffscreenCanvas;
// A GPUCanvasContext does little by itself and basically just binds a canvas
// and a GPUSwapChain together and forwards calls from one to the other.
@@ -46,22 +48,19 @@ class GPUCanvasContext : public CanvasRenderingContext {
// CanvasRenderingContext implementation
ContextType GetContextType() const override;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8RenderingContext* AsV8RenderingContext() final;
V8OffscreenRenderingContext* AsV8OffscreenRenderingContext() final;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void SetCanvasGetContextResult(RenderingContext&) final;
- void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) final;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- scoped_refptr<StaticBitmapImage> GetImage() final { return nullptr; }
+ scoped_refptr<StaticBitmapImage> GetImage() final;
+ bool PaintRenderingResultsToCanvas(SourceDrawingBuffer) final;
+ bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
+ SourceDrawingBuffer) final;
void SetIsInHiddenPage(bool) override {}
void SetIsBeingDisplayed(bool) override {}
bool isContextLost() const override { return false; }
bool IsComposited() const final { return true; }
bool IsAccelerated() const final { return true; }
bool IsOriginTopLeft() const final { return true; }
- bool Is3d() const final { return true; }
- void SetFilterQuality(SkFilterQuality) override;
+ void SetFilterQuality(cc::PaintFlags::FilterQuality) override;
bool IsPaintable() const final { return true; }
int ExternallyAllocatedBufferCountPerPixel() final { return 1; }
void Stop() final;
@@ -77,15 +76,31 @@ class GPUCanvasContext : public CanvasRenderingContext {
return false;
}
- // gpu_canvas_context.idl
- GPUSwapChain* configureSwapChain(const GPUSwapChainDescriptor* descriptor,
+ // gpu_presentation_context.idl
+ V8UnionHTMLCanvasElementOrOffscreenCanvas* getHTMLOrOffscreenCanvas() const;
+
+ void configure(const GPUCanvasConfiguration* descriptor, ExceptionState&);
+ void unconfigure();
+ String getPreferredFormat(const GPUAdapter* adapter);
+ GPUTexture* getCurrentTexture(ExceptionState&);
+
+ // gpu_canvas_context.idl (Deprecated)
+ GPUSwapChain* configureSwapChain(const GPUCanvasConfiguration* descriptor,
ExceptionState&);
- String getSwapChainPreferredFormat(const GPUAdapter* adapter);
+ String getSwapChainPreferredFormat(ExecutionContext* execution_context,
+ GPUAdapter* adapter);
private:
DISALLOW_COPY_AND_ASSIGN(GPUCanvasContext);
- SkFilterQuality filter_quality_ = kLow_SkFilterQuality;
+
+ void ConfigureInternal(const GPUCanvasConfiguration* descriptor,
+ ExceptionState&,
+ bool deprecated_resize_behavior = false);
+
+ cc::PaintFlags::FilterQuality filter_quality_ =
+ cc::PaintFlags::FilterQuality::kLow;
Member<GPUSwapChain> swapchain_;
+ Member<GPUDevice> configured_device_;
bool stopped_ = false;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
index 746f1d6d0cc..ec55b1c83fe 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
@@ -5,8 +5,17 @@
// https://gpuweb.github.io/gpuweb/
[
+ ActiveScriptWrappable,
Exposed(Window WebGPU, Worker WebGPU)
] interface GPUCanvasContext {
- [RaisesException] GPUSwapChain configureSwapChain(GPUSwapChainDescriptor descriptor);
- GPUTextureFormat getSwapChainPreferredFormat(GPUAdapter adapter);
+ [ImplementedAs=getHTMLOrOffscreenCanvas] readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;
+
+ GPUTextureFormat getPreferredFormat(GPUAdapter adapter);
+ [RaisesException] void configure(GPUCanvasConfiguration descriptor);
+ void unconfigure();
+ [RaisesException] GPUTexture getCurrentTexture();
+
+ // Deprecated
+ [RaisesException] GPUSwapChain configureSwapChain(GPUCanvasConfiguration descriptor);
+ [CallWith=ExecutionContext] GPUTextureFormat getSwapChainPreferredFormat(GPUAdapter adapter);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
index 5e0450f1ee6..c47b3a8fdc0 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
@@ -4,9 +4,6 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h"
-#include "third_party/blink/renderer/bindings/modules/v8/double_sequence_or_gpu_color_dict.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_extent_3d_dict.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_origin_3d_dict.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_command_buffer_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_command_encoder_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_compute_pass_descriptor.h"
@@ -15,6 +12,9 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_render_pass_color_attachment.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_render_pass_depth_stencil_attachment.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_render_pass_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_doublesequence_gpucolordict_gpuloadop.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_float_gpuloadop.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpuloadop_unsignedlongenforcerange.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_command_buffer.h"
@@ -39,30 +39,30 @@ WGPURenderPassColorAttachment AsDawnType(
// Deprecated path
dawn_desc.view = webgpu_desc->attachment()->GetHandle();
}
- dawn_desc.resolveTarget = webgpu_desc->resolveTarget()
+ dawn_desc.resolveTarget = webgpu_desc->hasResolveTarget()
? webgpu_desc->resolveTarget()->GetHandle()
: nullptr;
- if (webgpu_desc->loadValue().IsGPULoadOp()) {
- const WTF::String& gpuLoadOp = webgpu_desc->loadValue().GetAsGPULoadOp();
- dawn_desc.loadOp = AsDawnEnum<WGPULoadOp>(gpuLoadOp);
-
- } else if (webgpu_desc->loadValue().IsDoubleSequence()) {
- const Vector<double>& gpuColor =
- webgpu_desc->loadValue().GetAsDoubleSequence();
- dawn_desc.loadOp = WGPULoadOp_Clear;
- dawn_desc.clearColor = AsDawnColor(gpuColor);
-
- } else if (webgpu_desc->loadValue().IsGPUColorDict()) {
- const GPUColorDict* gpuColor = webgpu_desc->loadValue().GetAsGPUColorDict();
- dawn_desc.loadOp = WGPULoadOp_Clear;
- dawn_desc.clearColor = AsDawnType(gpuColor);
-
- } else {
- NOTREACHED();
+ switch (webgpu_desc->loadValue()->GetContentType()) {
+ case V8UnionGPUColorOrGPULoadOp::ContentType::kGPULoadOp:
+ dawn_desc.loadOp =
+ AsDawnEnum<WGPULoadOp>(webgpu_desc->loadValue()->GetAsGPULoadOp());
+ break;
+ case V8UnionGPUColorOrGPULoadOp::ContentType::kGPUColorDict:
+ dawn_desc.loadOp = WGPULoadOp_Clear;
+ dawn_desc.clearColor =
+ AsDawnType(webgpu_desc->loadValue()->GetAsGPUColorDict());
+ break;
+ case V8UnionGPUColorOrGPULoadOp::ContentType::kDoubleSequence:
+ dawn_desc.loadOp = WGPULoadOp_Clear;
+ dawn_desc.clearColor =
+ AsDawnColor(webgpu_desc->loadValue()->GetAsDoubleSequence());
+ break;
}
- dawn_desc.storeOp = AsDawnEnum<WGPUStoreOp>(webgpu_desc->storeOp());
+ if (webgpu_desc->hasStoreOp()) {
+ dawn_desc.storeOp = AsDawnEnum<WGPUStoreOp>(webgpu_desc->storeOp());
+ }
return dawn_desc;
}
@@ -81,35 +81,31 @@ WGPURenderPassDepthStencilAttachment AsDawnType(
dawn_desc.view = webgpu_desc->attachment()->GetHandle();
}
- if (webgpu_desc->depthLoadValue().IsGPULoadOp()) {
- const WTF::String& gpuLoadOp =
- webgpu_desc->depthLoadValue().GetAsGPULoadOp();
- dawn_desc.depthLoadOp = AsDawnEnum<WGPULoadOp>(gpuLoadOp);
- dawn_desc.clearDepth = 1.0f;
-
- } else if (webgpu_desc->depthLoadValue().IsFloat()) {
- dawn_desc.depthLoadOp = WGPULoadOp_Clear;
- dawn_desc.clearDepth = webgpu_desc->depthLoadValue().GetAsFloat();
-
- } else {
- NOTREACHED();
+ switch (webgpu_desc->depthLoadValue()->GetContentType()) {
+ case V8UnionFloatOrGPULoadOp::ContentType::kGPULoadOp:
+ dawn_desc.depthLoadOp = AsDawnEnum<WGPULoadOp>(
+ webgpu_desc->depthLoadValue()->GetAsGPULoadOp());
+ dawn_desc.clearDepth = 1.0f;
+ break;
+ case V8UnionFloatOrGPULoadOp::ContentType::kFloat:
+ dawn_desc.depthLoadOp = WGPULoadOp_Clear;
+ dawn_desc.clearDepth = webgpu_desc->depthLoadValue()->GetAsFloat();
+ break;
}
dawn_desc.depthStoreOp = AsDawnEnum<WGPUStoreOp>(webgpu_desc->depthStoreOp());
- if (webgpu_desc->stencilLoadValue().IsGPULoadOp()) {
- const WTF::String& gpuLoadOp =
- webgpu_desc->stencilLoadValue().GetAsGPULoadOp();
- dawn_desc.stencilLoadOp = AsDawnEnum<WGPULoadOp>(gpuLoadOp);
- dawn_desc.clearStencil = 0;
-
- } else if (webgpu_desc->stencilLoadValue().IsUnsignedLong()) {
- dawn_desc.stencilLoadOp = WGPULoadOp_Clear;
- dawn_desc.clearStencil =
- webgpu_desc->stencilLoadValue().GetAsUnsignedLong();
-
- } else {
- NOTREACHED();
+ switch (webgpu_desc->stencilLoadValue()->GetContentType()) {
+ case V8UnionGPULoadOpOrGPUStencilValue::ContentType::kGPULoadOp:
+ dawn_desc.stencilLoadOp = AsDawnEnum<WGPULoadOp>(
+ webgpu_desc->stencilLoadValue()->GetAsGPULoadOp());
+ dawn_desc.clearStencil = 0;
+ break;
+ case V8UnionGPULoadOpOrGPUStencilValue::ContentType::kV8GPUStencilValue:
+ dawn_desc.stencilLoadOp = WGPULoadOp_Clear;
+ dawn_desc.clearStencil =
+ webgpu_desc->stencilLoadValue()->GetAsV8GPUStencilValue();
+ break;
}
dawn_desc.stencilStoreOp =
@@ -156,20 +152,15 @@ GPUCommandEncoder* GPUCommandEncoder::Create(
const GPUCommandEncoderDescriptor* webgpu_desc) {
DCHECK(device);
DCHECK(webgpu_desc);
- ALLOW_UNUSED_LOCAL(webgpu_desc);
std::string label;
- WGPUCommandEncoderDescriptor dawn_desc = {};
- const WGPUCommandEncoderDescriptor* dawn_desc_ptr = nullptr;
- if (webgpu_desc) {
- dawn_desc = AsDawnType(webgpu_desc, &label);
- dawn_desc_ptr = &dawn_desc;
- }
+ WGPUCommandEncoderDescriptor dawn_desc = AsDawnType(webgpu_desc, &label);
GPUCommandEncoder* encoder = MakeGarbageCollected<GPUCommandEncoder>(
device, device->GetProcs().deviceCreateCommandEncoder(device->GetHandle(),
- dawn_desc_ptr));
- encoder->setLabel(webgpu_desc->label());
+ &dawn_desc));
+ if (webgpu_desc->hasLabel())
+ encoder->setLabel(webgpu_desc->label());
return encoder;
}
@@ -202,14 +193,16 @@ GPURenderPassEncoder* GPUCommandEncoder::beginRenderPass(
return nullptr;
}
- const GPULoadOpOrDoubleSequenceOrGPUColorDict load_value =
- color_attachment->loadValue();
-
- if (load_value.IsDoubleSequence() &&
- load_value.GetAsDoubleSequence().size() != 4) {
+ if (color_attachment->loadValue()->IsDoubleSequence() &&
+ color_attachment->loadValue()->GetAsDoubleSequence().size() != 4) {
exception_state.ThrowRangeError("loadValue color size must be 4");
return nullptr;
}
+
+ if (color_attachment->storeOp() == "clear") {
+ device_->AddConsoleWarning(
+ "The storeOp 'clear' has been deprecated. Use 'discard' instead.");
+ }
}
std::string label;
@@ -239,6 +232,13 @@ GPURenderPassEncoder* GPUCommandEncoder::beginRenderPass(
exception_state.ThrowTypeError("required member view is undefined.");
return nullptr;
}
+
+ if (descriptor->depthStencilAttachment()->depthStoreOp() == "clear" ||
+ descriptor->depthStencilAttachment()->stencilStoreOp() == "clear") {
+ device_->AddConsoleWarning(
+ "The storeOp 'clear' has been deprecated. Use 'discard' instead.");
+ }
+
depthStencilAttachment = AsDawnType(descriptor->depthStencilAttachment());
dawn_desc.depthStencilAttachment = &depthStencilAttachment;
} else {
@@ -254,7 +254,8 @@ GPURenderPassEncoder* GPUCommandEncoder::beginRenderPass(
GPURenderPassEncoder* encoder = MakeGarbageCollected<GPURenderPassEncoder>(
device_,
GetProcs().commandEncoderBeginRenderPass(GetHandle(), &dawn_desc));
- encoder->setLabel(descriptor->label());
+ if (descriptor->hasLabel())
+ encoder->setLabel(descriptor->label());
return encoder;
}
@@ -270,24 +271,15 @@ GPUComputePassEncoder* GPUCommandEncoder::beginComputePass(
GPUComputePassEncoder* encoder = MakeGarbageCollected<GPUComputePassEncoder>(
device_,
GetProcs().commandEncoderBeginComputePass(GetHandle(), &dawn_desc));
- encoder->setLabel(descriptor->label());
+ if (descriptor->hasLabel())
+ encoder->setLabel(descriptor->label());
return encoder;
}
void GPUCommandEncoder::copyBufferToTexture(GPUImageCopyBuffer* source,
GPUImageCopyTexture* destination,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8GPUExtent3D* copy_size
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- copy_size
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(copy_size, device_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size, device_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8GPUExtent3D* copy_size) {
+ WGPUExtent3D dawn_copy_size = AsDawnType(copy_size);
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
const char* error = nullptr;
@@ -304,18 +296,8 @@ void GPUCommandEncoder::copyBufferToTexture(GPUImageCopyBuffer* source,
void GPUCommandEncoder::copyTextureToBuffer(GPUImageCopyTexture* source,
GPUImageCopyBuffer* destination,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8GPUExtent3D* copy_size
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- copy_size
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(copy_size, device_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size, device_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ const V8GPUExtent3D* copy_size) {
+ WGPUExtent3D dawn_copy_size = AsDawnType(copy_size);
WGPUTextureCopyView dawn_source = AsDawnType(source, device_);
const char* error = nullptr;
@@ -332,20 +314,10 @@ void GPUCommandEncoder::copyTextureToBuffer(GPUImageCopyTexture* source,
void GPUCommandEncoder::copyTextureToTexture(GPUImageCopyTexture* source,
GPUImageCopyTexture* destination,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const V8GPUExtent3D* copy_size
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- copy_size
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-) {
+ const V8GPUExtent3D* copy_size) {
WGPUTextureCopyView dawn_source = AsDawnType(source, device_);
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(copy_size, device_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size, device_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ WGPUExtent3D dawn_copy_size = AsDawnType(copy_size);
GetProcs().commandEncoderCopyTextureToTexture(
GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h
index 636b706bbcc..f3999040025 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h
@@ -21,7 +21,6 @@ class GPUComputePassEncoder;
class GPURenderPassDescriptor;
class GPURenderPassEncoder;
class GPUImageCopyTexture;
-class UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict;
class GPUCommandEncoder : public DawnObject<WGPUCommandEncoder> {
DEFINE_WRAPPERTYPEINFO();
@@ -50,7 +49,6 @@ class GPUCommandEncoder : public DawnObject<WGPUCommandEncoder> {
src_offset, dst->GetHandle(),
dst_offset, size);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void copyBufferToTexture(GPUImageCopyBuffer* source,
GPUImageCopyTexture* destination,
const V8GPUExtent3D* copy_size);
@@ -60,20 +58,6 @@ class GPUCommandEncoder : public DawnObject<WGPUCommandEncoder> {
void copyTextureToTexture(GPUImageCopyTexture* source,
GPUImageCopyTexture* destination,
const V8GPUExtent3D* copy_size);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void copyBufferToTexture(
- GPUImageCopyBuffer* source,
- GPUImageCopyTexture* destination,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size);
- void copyTextureToBuffer(
- GPUImageCopyTexture* source,
- GPUImageCopyBuffer* destination,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size);
- void copyTextureToTexture(
- GPUImageCopyTexture* source,
- GPUImageCopyTexture* destination,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void pushDebugGroup(String groupLabel) {
std::string label = groupLabel.Utf8();
GetProcs().commandEncoderPushDebugGroup(GetHandle(), label.c_str());
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.cc
index 39ad7244843..6389af9111c 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.cc
@@ -60,7 +60,8 @@ GPUComputePipeline* GPUComputePipeline::Create(
GPUComputePipeline* pipeline = MakeGarbageCollected<GPUComputePipeline>(
device, device->GetProcs().deviceCreateComputePipeline(
device->GetHandle(), &dawn_desc));
- pipeline->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ pipeline->setLabel(webgpu_desc->label());
return pipeline;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc
index faeaba54637..ca3aa7fb8bf 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -9,9 +9,11 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_compute_pipeline_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_device_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_feature_name.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_render_pipeline_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_uncaptured_error_event_init.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpuoutofmemoryerror_gpuvalidationerror.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
@@ -23,6 +25,7 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_external_texture.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_out_of_memory_error.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_query_set.h"
@@ -32,28 +35,23 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_sampler.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_shader_module.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_supported_features.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_validation_error.h"
+#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
namespace {
-#ifdef USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY
Vector<String> ToStringVector(const Vector<V8GPUFeatureName>& features) {
Vector<String> str_features;
for (auto&& feature : features)
str_features.push_back(IDLEnumAsString(feature));
return str_features;
}
-#else
-const Vector<String>& ToStringVector(const Vector<String>& features) {
- return features;
-}
-#endif
} // anonymous namespace
@@ -67,24 +65,52 @@ GPUDevice::GPUDevice(ExecutionContext* execution_context,
DawnObject(dawn_control_client, dawn_device),
adapter_(adapter),
features_(MakeGarbageCollected<GPUSupportedFeatures>(
- ToStringVector(descriptor->nonGuaranteedFeatures()))),
+ ToStringVector(descriptor->requiredFeatures()))),
queue_(MakeGarbageCollected<GPUQueue>(
this,
GetProcs().deviceGetQueue(GetHandle()))),
lost_property_(MakeGarbageCollected<LostProperty>(execution_context)),
- error_callback_(BindRepeatingDawnCallback(&GPUDevice::OnUncapturedError,
+ error_callback_(BindDawnRepeatingCallback(&GPUDevice::OnUncapturedError,
WrapWeakPersistent(this))),
- lost_callback_(BindDawnCallback(&GPUDevice::OnDeviceLostError,
- WrapWeakPersistent(this))) {
+ logging_callback_(BindDawnRepeatingCallback(&GPUDevice::OnLogging,
+ WrapWeakPersistent(this))),
+ // Note: This is a *repeating* callback even though we expect it to only
+ // be called once. This is because it may be called *zero* times.
+ // Because it might never be called, the GPUDevice needs to own the
+ // allocation so it can be appropriately freed on destruction. Thus, the
+ // callback should not be a OnceCallback which self-deletes after it is
+ // called.
+ lost_callback_(BindDawnRepeatingCallback(&GPUDevice::OnDeviceLostError,
+ WrapWeakPersistent(this))) {
+ // Check is necessary because we can't assign a default in the IDL.
+ if (descriptor->hasRequiredLimits()) {
+ limits_ =
+ MakeGarbageCollected<GPUSupportedLimits>(descriptor->requiredLimits());
+ } else {
+ limits_ = MakeGarbageCollected<GPUSupportedLimits>();
+ }
+
DCHECK(dawn_device);
GetProcs().deviceSetUncapturedErrorCallback(
- GetHandle(), error_callback_->UnboundRepeatingCallback(),
+ GetHandle(), error_callback_->UnboundCallback(),
error_callback_->AsUserdata());
+ GetProcs().deviceSetLoggingCallback(GetHandle(),
+ logging_callback_->UnboundCallback(),
+ logging_callback_->AsUserdata());
GetProcs().deviceSetDeviceLostCallback(GetHandle(),
lost_callback_->UnboundCallback(),
lost_callback_->AsUserdata());
- setLabel(descriptor->label());
+ if (descriptor->hasLabel())
+ setLabel(descriptor->label());
+}
+
+GPUDevice::~GPUDevice() {
+ // Clear the callbacks since we can't handle callbacks after finalization.
+ // error_callback_, logging_callback_, and lost_callback_ will be deleted.
+ GetProcs().deviceSetUncapturedErrorCallback(GetHandle(), nullptr, nullptr);
+ GetProcs().deviceSetLoggingCallback(GetHandle(), nullptr, nullptr);
+ GetProcs().deviceSetDeviceLostCallback(GetHandle(), nullptr, nullptr);
}
void GPUDevice::InjectError(WGPUErrorType type, const char* message) {
@@ -120,14 +146,13 @@ void GPUDevice::OnUncapturedError(WGPUErrorType errorType,
GPUUncapturedErrorEventInit* init = GPUUncapturedErrorEventInit::Create();
if (errorType == WGPUErrorType_Validation) {
- auto* error = MakeGarbageCollected<GPUValidationError>(message);
init->setError(
- GPUOutOfMemoryErrorOrGPUValidationError::FromGPUValidationError(error));
+ MakeGarbageCollected<V8UnionGPUOutOfMemoryErrorOrGPUValidationError>(
+ MakeGarbageCollected<GPUValidationError>(message)));
} else if (errorType == WGPUErrorType_OutOfMemory) {
- GPUOutOfMemoryError* error = GPUOutOfMemoryError::Create();
init->setError(
- GPUOutOfMemoryErrorOrGPUValidationError::FromGPUOutOfMemoryError(
- error));
+ MakeGarbageCollected<V8UnionGPUOutOfMemoryErrorOrGPUValidationError>(
+ GPUOutOfMemoryError::Create()));
} else {
return;
}
@@ -135,13 +160,40 @@ void GPUDevice::OnUncapturedError(WGPUErrorType errorType,
event_type_names::kUncapturederror, init));
}
-void GPUDevice::OnDeviceLostError(const char* message) {
- // This function is called by a callback created by BindDawnCallback.
- // Release the unique_ptr holding it since BindDawnCallback is self-deleting.
- // This is stored as a unique_ptr because the lost callback may never be
- // called.
- lost_callback_.release();
+void GPUDevice::OnLogging(WGPULoggingType loggingType, const char* message) {
+ // Callback function for WebGPU logging return command
+ mojom::blink::ConsoleMessageLevel level;
+ switch (loggingType) {
+ case (WGPULoggingType_Verbose): {
+ level = mojom::blink::ConsoleMessageLevel::kVerbose;
+ break;
+ }
+ case (WGPULoggingType_Info): {
+ level = mojom::blink::ConsoleMessageLevel::kInfo;
+ break;
+ }
+ case (WGPULoggingType_Warning): {
+ level = mojom::blink::ConsoleMessageLevel::kWarning;
+ break;
+ }
+ case (WGPULoggingType_Error): {
+ level = mojom::blink::ConsoleMessageLevel::kError;
+ break;
+ }
+ default: {
+ level = mojom::blink::ConsoleMessageLevel::kError;
+ break;
+ }
+ }
+ ExecutionContext* execution_context = GetExecutionContext();
+ if (execution_context) {
+ auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering, level, message);
+ execution_context->AddConsoleMessage(console_message);
+ }
+}
+void GPUDevice::OnDeviceLostError(const char* message) {
AddConsoleWarning(message);
if (lost_property_->GetState() == LostProperty::kPending) {
@@ -230,17 +282,28 @@ GPUTexture* GPUDevice::createTexture(const GPUTextureDescriptor* descriptor,
}
GPUTexture* GPUDevice::experimentalImportTexture(
- HTMLVideoElement* video,
+ HTMLCanvasElement* canvas,
unsigned int usage_flags,
ExceptionState& exception_state) {
- return GPUTexture::FromVideo(
- this, video, static_cast<WGPUTextureUsage>(usage_flags), exception_state);
+ return GPUTexture::FromCanvas(this, canvas,
+ static_cast<WGPUTextureUsage>(usage_flags),
+ exception_state);
}
GPUSampler* GPUDevice::createSampler(const GPUSamplerDescriptor* descriptor) {
return GPUSampler::Create(this, descriptor);
}
+GPUExternalTexture* GPUDevice::importExternalTexture(
+ const GPUExternalTextureDescriptor* descriptor,
+ ExceptionState& exception_state) {
+ GPUExternalTexture* externalTexture =
+ GPUExternalTexture::FromVideo(this, descriptor, exception_state);
+ if (externalTexture)
+ EnsureExternalTextureDestroyed(externalTexture);
+ return externalTexture;
+}
+
GPUBindGroup* GPUDevice::createBindGroup(
const GPUBindGroupDescriptor* descriptor,
ExceptionState& exception_state) {
@@ -298,13 +361,16 @@ ScriptPromise GPUDevice::createRenderPipelineAsync(
resolver->Reject(exception_state);
} else {
auto* callback =
- BindDawnCallback(&GPUDevice::OnCreateRenderPipelineAsyncCallback,
- WrapPersistent(this), WrapPersistent(resolver));
+ BindDawnOnceCallback(&GPUDevice::OnCreateRenderPipelineAsyncCallback,
+ WrapPersistent(this), WrapPersistent(resolver));
GetProcs().deviceCreateRenderPipelineAsync(
GetHandle(), &dawn_desc_info.dawn_desc, callback->UnboundCallback(),
callback->AsUserdata());
}
+ // WebGPU guarantees that promises are resolved in finite time so we need to
+ // ensure commands are flushed.
+ EnsureFlush();
return promise;
}
@@ -329,8 +395,8 @@ ScriptPromise GPUDevice::createComputePipelineAsync(
AsDawnType(descriptor, &label, &computeStageDescriptor, this);
auto* callback =
- BindDawnCallback(&GPUDevice::OnCreateComputePipelineAsyncCallback,
- WrapPersistent(this), WrapPersistent(resolver));
+ BindDawnOnceCallback(&GPUDevice::OnCreateComputePipelineAsyncCallback,
+ WrapPersistent(this), WrapPersistent(resolver));
GetProcs().deviceCreateComputePipelineAsync(GetHandle(), &dawn_desc,
callback->UnboundCallback(),
callback->AsUserdata());
@@ -366,8 +432,8 @@ ScriptPromise GPUDevice::popErrorScope(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
auto* callback =
- BindDawnCallback(&GPUDevice::OnPopErrorScopeCallback,
- WrapPersistent(this), WrapPersistent(resolver));
+ BindDawnOnceCallback(&GPUDevice::OnPopErrorScopeCallback,
+ WrapPersistent(this), WrapPersistent(resolver));
if (!GetProcs().devicePopErrorScope(GetHandle(), callback->UnboundCallback(),
callback->AsUserdata())) {
@@ -418,10 +484,34 @@ const AtomicString& GPUDevice::InterfaceName() const {
void GPUDevice::Trace(Visitor* visitor) const {
visitor->Trace(adapter_);
visitor->Trace(features_);
+ visitor->Trace(limits_);
visitor->Trace(queue_);
visitor->Trace(lost_property_);
+ visitor->Trace(external_textures_pending_destroy_);
ExecutionContextClient::Trace(visitor);
EventTargetWithInlineData::Trace(visitor);
}
+void GPUDevice::EnsureExternalTextureDestroyed(
+ GPUExternalTexture* externalTexture) {
+ DCHECK(externalTexture);
+ external_textures_pending_destroy_.push_back(externalTexture);
+
+ if (has_pending_microtask_)
+ return;
+
+ Microtask::EnqueueMicrotask(WTF::Bind(
+ &GPUDevice::DestroyExternalTexturesMicrotask, WrapWeakPersistent(this)));
+ has_pending_microtask_ = true;
+}
+
+void GPUDevice::DestroyExternalTexturesMicrotask() {
+ has_pending_microtask_ = false;
+
+ auto externalTextures = std::move(external_textures_pending_destroy_);
+ for (Member<GPUExternalTexture> externalTexture : externalTextures) {
+ externalTexture->Destroy();
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h
index 05e8161e01b..4c71d7d6d32 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h
@@ -8,16 +8,16 @@
#include "base/memory/scoped_refptr.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/bindings/modules/v8/gpu_buffer_or_array_buffer.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_callback.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_object.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
class ExecutionContext;
-class HTMLVideoElement;
+class HTMLCanvasElement;
class GPUAdapter;
class GPUAdapter;
class GPUBuffer;
@@ -32,6 +32,8 @@ class GPUComputePipeline;
class GPUComputePipelineDescriptor;
class GPUDeviceDescriptor;
class GPUDeviceLostInfo;
+class GPUExternalTexture;
+class GPUExternalTextureDescriptor;
class GPUPipelineLayout;
class GPUPipelineLayoutDescriptor;
class GPUQuerySet;
@@ -46,6 +48,7 @@ class GPUSamplerDescriptor;
class GPUShaderModule;
class GPUShaderModuleDescriptor;
class GPUSupportedFeatures;
+class GPUSupportedLimits;
class GPUTexture;
class GPUTextureDescriptor;
class ScriptPromiseResolver;
@@ -62,12 +65,14 @@ class GPUDevice final : public EventTargetWithInlineData,
GPUAdapter* adapter,
WGPUDevice dawn_device,
const GPUDeviceDescriptor* descriptor);
+ ~GPUDevice() override;
void Trace(Visitor* visitor) const override;
// gpu_device.idl
GPUAdapter* adapter() const;
GPUSupportedFeatures* features() const;
+ GPUSupportedLimits* limits() const { return limits_; }
ScriptPromise lost(ScriptState* script_state);
GPUQueue* queue();
@@ -75,10 +80,13 @@ class GPUDevice final : public EventTargetWithInlineData,
GPUBuffer* createBuffer(const GPUBufferDescriptor* descriptor);
GPUTexture* createTexture(const GPUTextureDescriptor* descriptor,
ExceptionState& exception_state);
- GPUTexture* experimentalImportTexture(HTMLVideoElement* video,
+ GPUTexture* experimentalImportTexture(HTMLCanvasElement* canvas,
unsigned int usage_flags,
ExceptionState& exception_state);
GPUSampler* createSampler(const GPUSamplerDescriptor* descriptor);
+ GPUExternalTexture* importExternalTexture(
+ const GPUExternalTextureDescriptor* descriptor,
+ ExceptionState& exception_state);
GPUBindGroup* createBindGroup(const GPUBindGroupDescriptor* descriptor,
ExceptionState& exception_state);
@@ -123,11 +131,16 @@ class GPUDevice final : public EventTargetWithInlineData,
void InjectError(WGPUErrorType type, const char* message);
void AddConsoleWarning(const char* message);
+ void EnsureExternalTextureDestroyed(GPUExternalTexture* externalTexture);
+
private:
using LostProperty =
ScriptPromiseProperty<Member<GPUDeviceLostInfo>, ToV8UndefinedGenerator>;
+ void DestroyExternalTexturesMicrotask();
+
void OnUncapturedError(WGPUErrorType errorType, const char* message);
+ void OnLogging(WGPULoggingType loggingType, const char* message);
void OnDeviceLostError(const char* message);
void OnPopErrorScopeCallback(ScriptPromiseResolver* resolver,
@@ -146,21 +159,25 @@ class GPUDevice final : public EventTargetWithInlineData,
Member<GPUAdapter> adapter_;
Member<GPUSupportedFeatures> features_;
+ Member<GPUSupportedLimits> limits_;
Member<GPUQueue> queue_;
Member<LostProperty> lost_property_;
- std::unique_ptr<
- DawnCallback<base::RepeatingCallback<void(WGPUErrorType, const char*)>>>
+ std::unique_ptr<DawnRepeatingCallback<void(WGPUErrorType, const char*)>>
error_callback_;
+ std::unique_ptr<DawnRepeatingCallback<void(WGPULoggingType, const char*)>>
+ logging_callback_;
// lost_callback_ is stored as a unique_ptr since it may never be called.
// We need to be sure to free it on deletion of the device.
// Inside OnDeviceLostError we'll release the unique_ptr to avoid a double
// free.
- std::unique_ptr<DawnCallback<base::OnceCallback<void(const char*)>>>
- lost_callback_;
+ std::unique_ptr<DawnRepeatingCallback<void(const char*)>> lost_callback_;
static constexpr int kMaxAllowedConsoleWarnings = 500;
int allowed_console_warnings_remaining_ = kMaxAllowedConsoleWarnings;
+ bool has_pending_microtask_ = false;
+ HeapVector<Member<GPUExternalTexture>> external_textures_pending_destroy_;
+
DISALLOW_COPY_AND_ASSIGN(GPUDevice);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl
index 66927dbb589..d2e72fb68d6 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -9,7 +9,8 @@
] interface GPUDevice : EventTarget {
[SameObject] readonly attribute GPUAdapter adapter;
- readonly attribute GPUSupportedFeatures features;
+ [SameObject] readonly attribute GPUSupportedFeatures features;
+ [SameObject] readonly attribute GPUSupportedLimits limits;
[CallWith=ScriptState] readonly attribute Promise<GPUDeviceLostInfo> lost;
@@ -17,8 +18,9 @@
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
[RaisesException] GPUTexture createTexture(GPUTextureDescriptor descriptor);
- [RuntimeEnabled=WebGPUImportTexture, RaisesException] GPUTexture experimentalImportTexture(HTMLVideoElement video, GPUTextureUsageFlags usage);
+ [RuntimeEnabled=WebGPUImportTexture, RaisesException] GPUTexture experimentalImportTexture(HTMLCanvasElement canvas, GPUTextureUsageFlags usage);
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
+ [RaisesException] GPUExternalTexture importExternalTexture(GPUExternalTextureDescriptor descriptor);
[RaisesException] GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
[RaisesException] GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl
index 661d2c56857..addc5cf3ae2 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl
@@ -5,6 +5,12 @@
// https://gpuweb.github.io/gpuweb/
dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
+ sequence<GPUFeatureName> requiredFeatures = [];
+
+ // Should have a default of {}, but Blink doesn't seem to support that yet.
+ record<DOMString, GPUSize64> requiredLimits;
+
+ // Deprecated
sequence<GPUFeatureName> nonGuaranteedFeatures = [];
- GPULimits limits = {};
+ record<DOMString, GPUSize64> nonGuaranteedLimits;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
new file mode 100644
index 00000000000..560c849517a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
@@ -0,0 +1,142 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webgpu/gpu_external_texture.h"
+
+#include "media/base/video_frame.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_external_texture_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_view_descriptor.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_texture_view.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h"
+#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
+
+namespace blink {
+
+// static
+GPUExternalTexture* GPUExternalTexture::FromVideo(
+ GPUDevice* device,
+ const GPUExternalTextureDescriptor* webgpu_desc,
+ ExceptionState& exception_state) {
+ HTMLVideoElement* video = webgpu_desc->source();
+
+ if (!video || !video->videoWidth() || !video->videoHeight()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Missing video source");
+ return nullptr;
+ }
+
+ if (video->WouldTaintOrigin()) {
+ exception_state.ThrowSecurityError(
+ "Video element is tainted by cross-origin data and may not be loaded.");
+ return nullptr;
+ }
+
+ media::PaintCanvasVideoRenderer* video_renderer = nullptr;
+ scoped_refptr<media::VideoFrame> media_video_frame;
+ if (auto* wmp = video->GetWebMediaPlayer()) {
+ media_video_frame = wmp->GetCurrentFrame();
+ video_renderer = wmp->GetPaintCanvasVideoRenderer();
+ }
+
+ if (!media_video_frame || !video_renderer) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from video");
+ return nullptr;
+ }
+
+ // If the context is lost, the resource provider would be invalid.
+ auto context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
+ if (!context_provider_wrapper ||
+ context_provider_wrapper->ContextProvider()->IsContextLost())
+ return nullptr;
+
+ const CanvasResourceParams params(CanvasColorSpace::kSRGB, kN32_SkColorType,
+ kPremul_SkAlphaType);
+ const auto intrinsic_size = IntSize(media_video_frame->natural_size());
+
+ // Get a recyclable resource for producing WebGPU-compatible shared images.
+ std::unique_ptr<RecyclableCanvasResource> recyclable_canvas_resource =
+ device->GetDawnControlClient()->GetOrCreateCanvasResource(
+ intrinsic_size, params, /*is_origin_top_left=*/true);
+ if (!recyclable_canvas_resource) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from video");
+ return nullptr;
+ }
+
+ CanvasResourceProvider* resource_provider =
+ recyclable_canvas_resource->resource_provider();
+ DCHECK(resource_provider);
+
+ viz::RasterContextProvider* raster_context_provider = nullptr;
+ if (auto* context_provider = context_provider_wrapper->ContextProvider())
+ raster_context_provider = context_provider->RasterContextProvider();
+
+ // TODO(crbug.com/1174809): This isn't efficient for VideoFrames which are
+ // already available as a shared image. A WebGPUMailboxTexture should be
+ // created directly from the VideoFrame instead.
+ const auto dest_rect = gfx::Rect(media_video_frame->natural_size());
+ if (!DrawVideoFrameIntoResourceProvider(
+ std::move(media_video_frame), resource_provider,
+ raster_context_provider, dest_rect, video_renderer)) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from video");
+ return nullptr;
+ }
+
+ // Extract the format. If this format is invalid, Dawn will emit an error upon
+ // ExternalTexture creation.
+ WGPUTextureFormat format =
+ AsDawnType(resource_provider->ColorParams().GetSkColorType());
+
+ scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
+ WebGPUMailboxTexture::FromCanvasResource(
+ device->GetDawnControlClient(), device->GetHandle(),
+ WGPUTextureUsage::WGPUTextureUsage_TextureBinding,
+ std::move(recyclable_canvas_resource));
+
+ WGPUTextureViewDescriptor viewDesc = {};
+ WGPUTextureView plane0 = device->GetProcs().textureCreateView(
+ mailbox_texture->GetTexture(), &viewDesc);
+
+ WGPUExternalTextureDescriptor dawn_desc = {};
+ dawn_desc.plane0 = plane0;
+ dawn_desc.format = format;
+
+ GPUExternalTexture* externalTexture =
+ MakeGarbageCollected<GPUExternalTexture>(
+ device,
+ device->GetProcs().deviceCreateExternalTexture(device->GetHandle(),
+ &dawn_desc),
+ mailbox_texture);
+
+ // The texture view will be referenced during external texture creation, so by
+ // calling release here we ensure this texture view will be destructed when
+ // the external texture is destructed.
+ device->GetProcs().textureViewRelease(plane0);
+
+ return externalTexture;
+}
+
+GPUExternalTexture::GPUExternalTexture(
+ GPUDevice* device,
+ WGPUExternalTexture externalTexture,
+ scoped_refptr<WebGPUMailboxTexture> mailbox_texture)
+ : DawnObject<WGPUExternalTexture>(device, externalTexture),
+ mailbox_texture_(mailbox_texture) {}
+
+void GPUExternalTexture::Destroy() {
+ WGPUTexture texture = mailbox_texture_->GetTexture();
+ GetProcs().textureReference(texture);
+ mailbox_texture_.reset();
+ GetProcs().textureDestroy(texture);
+ GetProcs().textureRelease(texture);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h
new file mode 100644
index 00000000000..6980dcae31c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_EXTERNAL_TEXTURE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_EXTERNAL_TEXTURE_H_
+
+#include "third_party/blink/renderer/modules/webgpu/dawn_object.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+
+namespace blink {
+
+class ExceptionState;
+class GPUExternalTextureDescriptor;
+class WebGPUMailboxTexture;
+
+class GPUExternalTexture : public DawnObject<WGPUExternalTexture> {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static GPUExternalTexture* FromVideo(
+ GPUDevice* device,
+ const GPUExternalTextureDescriptor* webgpu_desc,
+ ExceptionState& exception_state);
+ explicit GPUExternalTexture(
+ GPUDevice* device,
+ WGPUExternalTexture externalTexture,
+ scoped_refptr<WebGPUMailboxTexture> mailbox_texture);
+ void Destroy();
+
+ private:
+ scoped_refptr<WebGPUMailboxTexture> mailbox_texture_;
+ DISALLOW_COPY_AND_ASSIGN(GPUExternalTexture);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_EXTERNAL_TEXTURE_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.idl
new file mode 100644
index 00000000000..ad737541bb2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture.idl
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://gpuweb.github.io/gpuweb/
+
+[
+ Exposed(Window WebGPU, Worker WebGPU)
+] interface GPUExternalTexture {
+};
+GPUExternalTexture includes GPUObjectBase; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_limits.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_binding_layout.idl
index 711fabdc3ff..1e83f2ff254 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_limits.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_binding_layout.idl
@@ -1,9 +1,8 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://gpuweb.github.io/gpuweb/
-dictionary GPULimits {
- GPUSize32 maxBindGroups = 4;
-};
+dictionary GPUExternalTextureBindingLayout {
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_descriptor.idl
new file mode 100644
index 00000000000..f50b768372e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_external_texture_descriptor.idl
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://gpuweb.github.io/gpuweb/
+
+dictionary GPUExternalTextureDescriptor : GPUObjectDescriptorBase {
+ required HTMLVideoElement source;
+ GPUPredefinedColorSpace colorSpace = "srgb";
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl
new file mode 100644
index 00000000000..6d9b80fc659
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+// https://gpuweb.github.io/gpuweb/
+
+dictionary GPUImageCopyExternalImage {
+ required (ImageBitmap or HTMLCanvasElement or OffscreenCanvas) source;
+ GPUOrigin2D origin = {};
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_texture_tagged.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_texture_tagged.idl
new file mode 100644
index 00000000000..79d2303e4d2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_image_copy_texture_tagged.idl
@@ -0,0 +1,14 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://gpuweb.github.io/gpuweb/
+
+enum GPUPredefinedColorSpace {
+ "srgb"
+};
+
+dictionary GPUImageCopyTextureTagged : GPUImageCopyTexture {
+ GPUPredefinedColorSpace colorSpace = "srgb";
+ boolean premultipliedAlpha = false;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.cc
index dace7846ea9..4c8ee818c16 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.cc
@@ -38,7 +38,8 @@ GPUPipelineLayout* GPUPipelineLayout::Create(
GPUPipelineLayout* layout = MakeGarbageCollected<GPUPipelineLayout>(
device, device->GetProcs().deviceCreatePipelineLayout(device->GetHandle(),
&dawn_desc));
- layout->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ layout->setLabel(webgpu_desc->label());
return layout;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
index afdd9bf806f..69b18ff81ec 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
@@ -40,7 +40,8 @@ GPUQuerySet* GPUQuerySet::Create(GPUDevice* device,
GPUQuerySet* query_set = MakeGarbageCollected<GPUQuerySet>(
device,
device->GetProcs().deviceCreateQuerySet(device->GetHandle(), &dawn_desc));
- query_set->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ query_set->setLabel(webgpu_desc->label());
return query_set;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
index 8cdfd077983..134b6cbeaf2 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -9,14 +9,19 @@
#include "gpu/command_buffer/client/webgpu_interface.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_extent_3d_dict.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_origin_2d_dict.h"
-#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_enforce_range_sequence_or_gpu_origin_3d_dict.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_imagebitmap_offscreencanvas.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_command_buffer_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_external_image.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_image_bitmap.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_texture_tagged.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_origin_2d_dict.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpuorigin2ddict_unsignedlongenforcerangesequence.h"
#include "third_party/blink/renderer/core/dom/dom_exception.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/imagebitmap/image_bitmap.h"
+#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/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
@@ -31,8 +36,7 @@ namespace blink {
namespace {
-WGPUOrigin3D GPUOrigin2DToWGPUOrigin3D(
- const UnsignedLongEnforceRangeSequenceOrGPUOrigin2DDict* webgpu_origin) {
+WGPUOrigin3D GPUOrigin2DToWGPUOrigin3D(const V8GPUOrigin2D* webgpu_origin) {
DCHECK(webgpu_origin);
WGPUOrigin3D dawn_origin = {
@@ -41,34 +45,76 @@ WGPUOrigin3D GPUOrigin2DToWGPUOrigin3D(
0,
};
- if (webgpu_origin->IsUnsignedLongEnforceRangeSequence()) {
- const Vector<uint32_t>& webgpu_origin_sequence =
- webgpu_origin->GetAsUnsignedLongEnforceRangeSequence();
- // The WebGPU spec states that if the sequence isn't big enough then the
- // default values of 0 are used (which are set above).
- switch (webgpu_origin_sequence.size()) {
- default:
- // This is a 2D origin and the depth should be 0 always.
- dawn_origin.y = webgpu_origin_sequence[1];
- FALLTHROUGH;
- case 1:
- dawn_origin.x = webgpu_origin_sequence[0];
- FALLTHROUGH;
- case 0:
- break;
+ switch (webgpu_origin->GetContentType()) {
+ case V8GPUOrigin2D::ContentType::kGPUOrigin2DDict: {
+ const GPUOrigin2DDict* webgpu_origin_2d_dict =
+ webgpu_origin->GetAsGPUOrigin2DDict();
+ dawn_origin.x = webgpu_origin_2d_dict->x();
+ dawn_origin.y = webgpu_origin_2d_dict->y();
+ break;
+ }
+ case V8GPUOrigin2D::ContentType::kUnsignedLongEnforceRangeSequence: {
+ const Vector<uint32_t>& webgpu_origin_sequence =
+ webgpu_origin->GetAsUnsignedLongEnforceRangeSequence();
+ // The WebGPU spec states that if the sequence isn't big enough then the
+ // default values of 0 are used (which are set above).
+ switch (webgpu_origin_sequence.size()) {
+ default:
+ // This is a 2D origin and the depth should be 0 always.
+ dawn_origin.y = webgpu_origin_sequence[1];
+ FALLTHROUGH;
+ case 1:
+ dawn_origin.x = webgpu_origin_sequence[0];
+ FALLTHROUGH;
+ case 0:
+ break;
+ }
+ break;
}
- } else if (webgpu_origin->IsGPUOrigin2DDict()) {
- const GPUOrigin2DDict* webgpu_origin_2d_dict =
- webgpu_origin->GetAsGPUOrigin2DDict();
- dawn_origin.x = webgpu_origin_2d_dict->x();
- dawn_origin.y = webgpu_origin_2d_dict->y();
- } else {
- NOTREACHED();
}
return dawn_origin;
}
+bool IsExternalImageWebGLCanvas(
+ const V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas* external_image
+) {
+ CanvasRenderingContextHost* canvas = nullptr;
+ switch (external_image->GetContentType()) {
+ case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
+ kHTMLCanvasElement:
+ canvas = external_image->GetAsHTMLCanvasElement();
+ break;
+ case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
+ kOffscreenCanvas:
+ canvas = external_image->GetAsOffscreenCanvas();
+ break;
+ default:
+ canvas = nullptr;
+ break;
+ }
+
+ return canvas && canvas->IsWebGL();
+}
+
+bool IsValidExternalImageDestinationFormat(
+ WGPUTextureFormat dawn_texture_format) {
+ switch (dawn_texture_format) {
+ // Not support float target format due to unclear "srgb" definition for now.
+ case WGPUTextureFormat_RGBA8Unorm:
+ case WGPUTextureFormat_RGBA8UnormSrgb:
+ case WGPUTextureFormat_BGRA8Unorm:
+ case WGPUTextureFormat_BGRA8UnormSrgb:
+ case WGPUTextureFormat_RGB10A2Unorm:
+ case WGPUTextureFormat_RG8Unorm:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// TODO(crbug.com/1197369)This duplicate code is for supporting deprecated API
+// copyImageBitmapToTexture and should be remove in future.
bool IsValidCopyIB2TDestinationFormat(WGPUTextureFormat dawn_texture_format) {
switch (dawn_texture_format) {
case WGPUTextureFormat_RGBA8Unorm:
@@ -95,10 +141,6 @@ bool IsValidCopyTextureForBrowserFormats(SkColorType src_color_type,
return false;
}
- // This function should be called after |IsValidCopyEI2TDestinationFormat|.
- // Use DCHECK to guard this assumption.
- DCHECK(IsValidCopyIB2TDestinationFormat(dst_texture_format));
-
// CopyTextureForBrowser() supports neither RGBA8UnormSrgb nor BGRA8UnormSrgb
// as dst texture format.
if (dst_texture_format == WGPUTextureFormat_RGBA8UnormSrgb ||
@@ -109,14 +151,85 @@ bool IsValidCopyTextureForBrowserFormats(SkColorType src_color_type,
return true;
}
-bool CanUploadThroughGPU(StaticBitmapImage* image, GPUTexture* dest_texture) {
- // Check src/dst texture formats are supported by CopyTextureForBrowser
- SkImageInfo image_info = image->PaintImageForCurrentFrame().GetSkImageInfo();
- return IsValidCopyTextureForBrowserFormats(image_info.colorType(),
- dest_texture->Format());
+scoped_refptr<Image> GetImageFromExternalImage(
+ const V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas*
+ external_image,
+ ExceptionState& exception_state) {
+ CanvasImageSource* source = nullptr;
+ CanvasRenderingContextHost* canvas = nullptr;
+ switch (external_image->GetContentType()) {
+ case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
+ kHTMLCanvasElement:
+ source = external_image->GetAsHTMLCanvasElement();
+ canvas = external_image->GetAsHTMLCanvasElement();
+ break;
+ case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
+ kImageBitmap:
+ source = external_image->GetAsImageBitmap();
+ break;
+ case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
+ kOffscreenCanvas:
+ source = external_image->GetAsOffscreenCanvas();
+ canvas = external_image->GetAsOffscreenCanvas();
+ break;
+ }
+
+ // Neutered external image.
+ if (source->IsNeutered()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "External Image has been detached.");
+ return nullptr;
+ }
+
+ // Placeholder source is not allowed.
+ if (source->IsPlaceholder()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Cannot copy from a canvas that has had "
+ "transferControlToOffscreen() called.");
+ return nullptr;
+ }
+
+ // Canvas element contains cross-origin data and may not be loaded
+ if (source->WouldTaintOrigin()) {
+ exception_state.ThrowSecurityError(
+ "The external image is tainted by cross-origin data.");
+ return nullptr;
+ }
+
+ if (canvas && !(canvas->IsWebGL() || canvas->IsRenderingContext2D())) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kOperationError,
+ "CopyExternalImageToTexture doesn't support canvas without 2d, webgl "
+ "or webgl2 context");
+ return nullptr;
+ }
+
+ // HTMLCanvasElement and OffscreenCanvas won't care image orientation. But for
+ // ImageBitmap, use kRespectImageOrientation will make ElementSize() behave
+ // as Size().
+ FloatSize image_size = source->ElementSize(
+ FloatSize(), // It will be ignored and won't affect size.
+ kRespectImageOrientation);
+
+ // TODO(crbug.com/1197369): Ensure kUnpremultiplyAlpha impl will also make
+ // image live on GPU if possible.
+ // Use kDontChangeAlpha here to bypass the alpha type conversion here.
+ // Left the alpha op to CopyTextureForBrowser() and CopyContentFromCPU().
+ // This will help combine more transforms (e.g. flipY, color-space)
+ // into a single blit.
+ SourceImageStatus source_image_status = kInvalidSourceImageStatus;
+ auto image = source->GetSourceImageForCanvas(&source_image_status, image_size,
+ kDontChangeAlpha);
+ if (source_image_status != kNormalSourceImageStatus) {
+ // Canvas back resource is broken, zero size, incomplete or invalid.
+ // but developer can do nothing. Return nullptr and issue an noop.
+ return nullptr;
+ }
+
+ return image;
}
-} // anonymous namespace
+} // namespace
GPUQueue::GPUQueue(GPUDevice* device, WGPUQueue queue)
: DawnObject<WGPUQueue>(device, queue) {
@@ -154,8 +267,8 @@ ScriptPromise GPUQueue::onSubmittedWorkDone(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
auto* callback =
- BindDawnCallback(&GPUQueue::OnWorkDoneCallback, WrapPersistent(this),
- WrapPersistent(resolver));
+ BindDawnOnceCallback(&GPUQueue::OnWorkDoneCallback, WrapPersistent(this),
+ WrapPersistent(resolver));
GetProcs().queueOnSubmittedWorkDone(
GetHandle(), 0u, callback->UnboundCallback(), callback->AsUserdata());
@@ -267,12 +380,7 @@ void GPUQueue::WriteBufferImpl(GPUBuffer* buffer,
void GPUQueue::writeTexture(GPUImageCopyTexture* destination,
const MaybeShared<DOMArrayBufferView>& data,
GPUImageDataLayout* data_layout,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUExtent3D* write_size,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- write_size,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
WriteTextureImpl(destination, data->BaseAddressMaybeShared(),
data->byteLength(), data_layout, write_size,
@@ -282,12 +390,7 @@ void GPUQueue::writeTexture(GPUImageCopyTexture* destination,
void GPUQueue::writeTexture(GPUImageCopyTexture* destination,
const DOMArrayBufferBase* data,
GPUImageDataLayout* data_layout,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUExtent3D* write_size,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- write_size,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
WriteTextureImpl(destination, data->DataMaybeShared(), data->ByteLength(),
data_layout, write_size, exception_state);
@@ -297,18 +400,9 @@ void GPUQueue::WriteTextureImpl(GPUImageCopyTexture* destination,
const void* data,
size_t data_size,
GPUImageDataLayout* data_layout,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUExtent3D* write_size,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- write_size,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_write_size = AsDawnType(write_size, device_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_write_size = AsDawnType(&write_size, device_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ WGPUExtent3D dawn_write_size = AsDawnType(write_size);
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUTextureDataLayout dawn_data_layout = {};
@@ -326,16 +420,152 @@ void GPUQueue::WriteTextureImpl(GPUImageCopyTexture* destination,
return;
}
-// TODO(shaobo.yan@intel.com): Implement this function
+void GPUQueue::copyExternalImageToTexture(
+ GPUImageCopyExternalImage* copyImage,
+ GPUImageCopyTextureTagged* destination,
+ const V8GPUExtent3D* copy_size,
+ ExceptionState& exception_state) {
+ // "srgb" is the only valid color space for now.
+ DCHECK_EQ(destination->colorSpace(), "srgb");
+ bool is_webgl = IsExternalImageWebGLCanvas(copyImage->source());
+
+ scoped_refptr<Image> image =
+ GetImageFromExternalImage(copyImage->source(), exception_state);
+
+ scoped_refptr<StaticBitmapImage> static_bitmap_image =
+ DynamicTo<StaticBitmapImage>(image.get());
+ if (!static_bitmap_image) {
+ device_->AddConsoleWarning(
+ "CopyExternalImageToTexture(): Browser fails extracting valid resource"
+ "from external image. This API call will return early.");
+ return;
+ }
+
+ // TODO(crbug.com/1197369): Extract alpha info and config the following
+ // CopyContentFromCPU() and CopyContentFromGPU().
+
+ WGPUExtent3D dawn_copy_size = AsDawnType(copy_size);
+
+ // Extract source origin
+ WGPUOrigin3D origin_in_external_image =
+ GPUOrigin2DToWGPUOrigin3D(copyImage->origin());
+
+ // Validate origin value
+ const bool copyRectOutOfBounds =
+ static_cast<uint32_t>(static_bitmap_image->width()) <
+ origin_in_external_image.x ||
+ static_cast<uint32_t>(static_bitmap_image->height()) <
+ origin_in_external_image.y ||
+ static_cast<uint32_t>(static_bitmap_image->width()) -
+ origin_in_external_image.x <
+ dawn_copy_size.width ||
+ static_cast<uint32_t>(static_bitmap_image->height()) -
+ origin_in_external_image.y <
+ dawn_copy_size.height;
+
+ if (copyRectOutOfBounds) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kOperationError,
+ "Copy rect is out of bounds of external image");
+ return;
+ }
+
+ // Check copy depth.
+ // the validation rule is origin.z + copy_size.depth <= 1.
+ // Since origin in external image is 2D Origin(z always equals to 0),
+ // checks copy size here only.
+ if (dawn_copy_size.depthOrArrayLayers > 1) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kOperationError,
+ "Copy depth is out of bounds of external image.");
+ return;
+ }
+
+ WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
+
+ if (!IsValidExternalImageDestinationFormat(
+ destination->texture()->Format())) {
+ GetProcs().deviceInjectError(device_->GetHandle(), WGPUErrorType_Validation,
+ "Invalid destination gpu texture format.");
+ return;
+ }
+
+ if (destination->texture()->Dimension() != WGPUTextureDimension_2D) {
+ GetProcs().deviceInjectError(device_->GetHandle(), WGPUErrorType_Validation,
+ "Dst gpu texture must be 2d.");
+ return;
+ }
+
+ WGPUTextureUsage dst_texture_usage = destination->texture()->Usage();
+
+ if ((dst_texture_usage & WGPUTextureUsage_RenderAttachment) !=
+ WGPUTextureUsage_RenderAttachment ||
+ (dst_texture_usage & WGPUTextureUsage_CopyDst) !=
+ WGPUTextureUsage_CopyDst) {
+ GetProcs().deviceInjectError(
+ device_->GetHandle(), WGPUErrorType_Validation,
+ "Destination texture needs to have CopyDst and RenderAttachment "
+ "usage.");
+ return;
+ }
+
+ // Issue the noop copy to continue validation to destination textures
+ const bool isNoopCopy = dawn_copy_size.width == 0 ||
+ dawn_copy_size.height == 0 ||
+ dawn_copy_size.depthOrArrayLayers == 0;
+
+ if (isNoopCopy) {
+ device_->AddConsoleWarning(
+ "CopyExternalImageToTexture(): It is a noop copy"
+ "({width|height|depthOrArrayLayers} equals to 0).");
+ }
+
+ // NOTE: IsOriginTopLeft for AcceleratedStaticBitmapImage
+ // will provide the correct orientation info.
+ // TODO(crbug.com/1221110): WebGL canvas image orientation seems
+ // opposite with the orientation attributes. Need to figure out whether
+ // this is expected.
+ bool is_origin_top_left = static_bitmap_image->IsOriginTopLeft();
+ bool flipY =
+ (!is_origin_top_left && !is_webgl) || (is_origin_top_left && is_webgl);
+
+ // Try GPU path first and delegate noop copy to CPU path.
+ if (static_bitmap_image->IsTextureBacked() &&
+ !isNoopCopy) { // Try GPU uploading path.
+ if (CopyContentFromGPU(static_bitmap_image.get(), origin_in_external_image,
+ dawn_copy_size, dawn_destination,
+ destination->texture()->Format(),
+ destination->premultipliedAlpha(), flipY)) {
+ return;
+ }
+ }
+ // GPU path failed, fallback to CPU path
+ static_bitmap_image = static_bitmap_image->MakeUnaccelerated();
+ DCHECK_EQ(static_bitmap_image->IsOriginTopLeft(), true);
+ flipY = is_webgl;
+
+ // CPU path is the fallback path and should always work.
+ if (!CopyContentFromCPU(static_bitmap_image.get(), origin_in_external_image,
+ dawn_copy_size, dawn_destination,
+ destination->texture()->Format(),
+ destination->premultipliedAlpha(), flipY)) {
+ exception_state.ThrowTypeError(
+ "Failed to copy content from external image.");
+ return;
+ }
+}
+
+// TODO(crbug.com/1197369): This API contains duplicated code is to stop
+// breaking current workable codes. Will be removed when it is deprecated.
void GPUQueue::copyImageBitmapToTexture(GPUImageCopyImageBitmap* source,
GPUImageCopyTexture* destination,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUExtent3D* copy_size,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict&
- copy_size,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
+ device_->AddConsoleWarning(
+ "The copyImageBitmapToTexture() has been deprecated in favor of the "
+ "copyExternalImageToTexture() "
+ "and will soon be removed.");
+
if (!source->imageBitmap()) {
exception_state.ThrowTypeError("No valid imageBitmap");
return;
@@ -350,20 +580,15 @@ void GPUQueue::copyImageBitmapToTexture(GPUImageCopyImageBitmap* source,
scoped_refptr<StaticBitmapImage> image = source->imageBitmap()->BitmapImage();
-
// TODO(shaobo.yan@intel.com) : Check that the destination GPUTexture has an
// appropriate format. Now only support texture format exactly the same. The
// compatible formats need to be defined in WebGPU spec.
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(copy_size, device_);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size, device_);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
+ WGPUExtent3D dawn_copy_size = AsDawnType(copy_size);
// Extract imageBitmap attributes
WGPUOrigin3D origin_in_image_bitmap =
- GPUOrigin2DToWGPUOrigin3D(&(source->origin()));
+ GPUOrigin2DToWGPUOrigin3D(source->origin());
// Validate copy depth
if (dawn_copy_size.depthOrArrayLayers > 1) {
@@ -393,30 +618,20 @@ void GPUQueue::copyImageBitmapToTexture(GPUImageCopyImageBitmap* source,
if (!IsValidCopyIB2TDestinationFormat(destination->texture()->Format())) {
return exception_state.ThrowTypeError("Invalid gpu texture format.");
- return;
}
bool isNoopCopy = dawn_copy_size.width == 0 || dawn_copy_size.height == 0 ||
dawn_copy_size.depthOrArrayLayers == 0;
- // Try GPU path first and delegate noop copy to CPU path.
- // The users of imageBitmap always have enough information about the
- // color space (in the future the WICG proposal 'CanvasColorSpaceProposal'
- // will bring more enhancements), so it is always acceptable to issue a
- // passthrough copy here.
if (image->IsTextureBacked() && !isNoopCopy) { // Try GPU uploading path.
- if (CanUploadThroughGPU(image.get(), destination->texture())) {
- if (CopyContentFromGPU(image.get(), origin_in_image_bitmap,
- dawn_copy_size, dawn_destination)) {
- return;
- }
- }
- // GPU path failed, fallback to CPU path
+ // Fallback to CPU path, GPU uploading requests RENDER_ATTACHMENT usage for
+ // dst texture.
image = image->MakeUnaccelerated();
}
// CPU path is the fallback path and should always work.
if (!CopyContentFromCPU(image.get(), origin_in_image_bitmap, dawn_copy_size,
- dawn_destination, destination->texture()->Format())) {
+ dawn_destination, destination->texture()->Format(),
+ image->IsPremultiplied())) {
exception_state.ThrowTypeError("Failed to copy content from imageBitmap.");
return;
}
@@ -426,7 +641,9 @@ bool GPUQueue::CopyContentFromCPU(StaticBitmapImage* image,
const WGPUOrigin3D& origin,
const WGPUExtent3D& copy_size,
const WGPUTextureCopyView& destination,
- const WGPUTextureFormat dest_texture_format) {
+ const WGPUTextureFormat dest_texture_format,
+ bool premultiplied_alpha,
+ bool flipY) {
// Prepare for uploading CPU data.
IntRect image_data_rect(origin.x, origin.y, copy_size.width,
copy_size.height);
@@ -458,7 +675,7 @@ bool GPUQueue::CopyContentFromCPU(StaticBitmapImage* image,
if (!CopyBytesFromImageBitmapForWebGPU(
image, base::span<uint8_t>(static_cast<uint8_t*>(data), size),
- image_data_rect, dest_texture_format)) {
+ image_data_rect, dest_texture_format, premultiplied_alpha, flipY)) {
// Release the buffer.
GetProcs().bufferRelease(buffer);
return false;
@@ -498,14 +715,30 @@ bool GPUQueue::CopyContentFromCPU(StaticBitmapImage* image,
bool GPUQueue::CopyContentFromGPU(StaticBitmapImage* image,
const WGPUOrigin3D& origin,
const WGPUExtent3D& copy_size,
- const WGPUTextureCopyView& destination) {
+ const WGPUTextureCopyView& destination,
+ const WGPUTextureFormat dest_texture_format,
+ bool premultiplied_alpha,
+ bool flipY) {
+ // Check src/dst texture formats are supported by CopyTextureForBrowser
+ SkImageInfo image_info = image->PaintImageForCurrentFrame().GetSkImageInfo();
+ if (!IsValidCopyTextureForBrowserFormats(image_info.colorType(),
+ dest_texture_format)) {
+ return false;
+ }
+
+ // TODO(crbug.com/1197369): config color space based on image
scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
WebGPUMailboxTexture::FromStaticBitmapImage(
GetDawnControlClient(), device_->GetHandle(),
static_cast<WGPUTextureUsage>(WGPUTextureUsage_CopyDst |
WGPUTextureUsage_CopySrc |
- WGPUTextureUsage_Sampled),
- image);
+ WGPUTextureUsage_TextureBinding),
+ image, CanvasColorSpace::kSRGB, image_info.colorType());
+
+ // Fail to associate staticBitmapImage to dawn resource.
+ if (!mailbox_texture) {
+ return false;
+ }
WGPUTexture src_texture = mailbox_texture->GetTexture();
DCHECK(src_texture != nullptr);
@@ -516,14 +749,15 @@ bool GPUQueue::CopyContentFromGPU(StaticBitmapImage* image,
WGPUCopyTextureForBrowserOptions options = {};
- // In Chromium, all the GPU-based GL textures have
- // opposite y-coordinates, so we need to correct them
- // in CopyTextureForBrowser().
- if (image->CurrentFrameOrientation().Orientation() ==
- ImageOrientationEnum::kOriginTopLeft) {
+ if (flipY) {
options.flipY = true;
}
+ options.alphaOp = image->IsPremultiplied() == premultiplied_alpha
+ ? WGPUAlphaOp_DontChange
+ : premultiplied_alpha ? WGPUAlphaOp_Premultiply
+ : WGPUAlphaOp_Unpremultiply;
+
GetProcs().queueCopyTextureForBrowser(GetHandle(), &src, &destination,
&copy_size, &options);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.h
index b8a169c9769..d084dc9cd87 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUEUE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUEUE_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
@@ -17,12 +18,13 @@ class ExceptionState;
class GPUBuffer;
class GPUCommandBuffer;
class GPUImageCopyImageBitmap;
+class GPUImageCopyExternalImage;
class GPUImageCopyTexture;
+class GPUImageCopyTextureTagged;
class GPUImageDataLayout;
class ScriptPromiseResolver;
class ScriptState;
class StaticBitmapImage;
-class UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict;
class GPUQueue : public DawnObject<WGPUQueue> {
DEFINE_WRAPPERTYPEINFO();
@@ -55,7 +57,6 @@ class GPUQueue : public DawnObject<WGPUQueue> {
uint64_t data_byte_offset,
uint64_t byte_size,
ExceptionState& exception_state);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void writeTexture(GPUImageCopyTexture* destination,
const MaybeShared<DOMArrayBufferView>& data,
GPUImageDataLayout* data_layout,
@@ -66,29 +67,14 @@ class GPUQueue : public DawnObject<WGPUQueue> {
GPUImageDataLayout* data_layout,
const V8GPUExtent3D* write_size,
ExceptionState& exception_state);
+ void copyExternalImageToTexture(GPUImageCopyExternalImage* copyImage,
+ GPUImageCopyTextureTagged* destination,
+ const V8GPUExtent3D* copySize,
+ ExceptionState& exception_state);
void copyImageBitmapToTexture(GPUImageCopyImageBitmap* source,
GPUImageCopyTexture* destination,
const V8GPUExtent3D* copy_size,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void writeTexture(
- GPUImageCopyTexture* destination,
- const MaybeShared<DOMArrayBufferView>& data,
- GPUImageDataLayout* data_layout,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& write_size,
- ExceptionState& exception_state);
- void writeTexture(
- GPUImageCopyTexture* destination,
- const DOMArrayBufferBase* data,
- GPUImageDataLayout* data_layout,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& write_size,
- ExceptionState& exception_state);
- void copyImageBitmapToTexture(
- GPUImageCopyImageBitmap* source,
- GPUImageCopyTexture* destination,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copySize,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
void OnWorkDoneCallback(ScriptPromiseResolver* resolver,
@@ -98,11 +84,16 @@ class GPUQueue : public DawnObject<WGPUQueue> {
const WGPUOrigin3D& origin,
const WGPUExtent3D& copy_size,
const WGPUTextureCopyView& destination,
- const WGPUTextureFormat dest_texture_format);
+ const WGPUTextureFormat dest_texture_format,
+ bool premultiplied_alpha,
+ bool flipY = false);
bool CopyContentFromGPU(StaticBitmapImage* image,
const WGPUOrigin3D& origin,
const WGPUExtent3D& copy_size,
- const WGPUTextureCopyView& destination);
+ const WGPUTextureCopyView& destination,
+ const WGPUTextureFormat dest_texture_format,
+ bool premultiplied_alpha,
+ bool flipY = false);
void WriteBufferImpl(GPUBuffer* buffer,
uint64_t buffer_offset,
uint64_t data_byte_length,
@@ -111,22 +102,12 @@ class GPUQueue : public DawnObject<WGPUQueue> {
uint64_t data_byte_offset,
absl::optional<uint64_t> byte_size,
ExceptionState& exception_state);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void WriteTextureImpl(GPUImageCopyTexture* destination,
const void* data,
size_t dataSize,
GPUImageDataLayout* data_layout,
const V8GPUExtent3D* write_size,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void WriteTextureImpl(
- GPUImageCopyTexture* destination,
- const void* data,
- size_t dataSize,
- GPUImageDataLayout* data_layout,
- UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& write_size,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DISALLOW_COPY_AND_ASSIGN(GPUQueue);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl
index e7fd8719e62..f5438bd9f2a 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl
@@ -38,9 +38,15 @@
GPUImageDataLayout dataLayout,
GPUExtent3D size);
+ // Deprecated
[RaisesException] void copyImageBitmapToTexture(
GPUImageCopyImageBitmap source,
GPUImageCopyTexture destination,
GPUExtent3D copySize);
+
+ [RaisesException] void copyExternalImageToTexture(
+ GPUImageCopyExternalImage source,
+ GPUImageCopyTextureTagged destination,
+ GPUExtent3D copySize);
};
GPUQueue includes GPUObjectBase;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc
index cde508d489b..5221cc34873 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc
@@ -48,7 +48,8 @@ GPURenderBundleEncoder* GPURenderBundleEncoder::Create(
MakeGarbageCollected<GPURenderBundleEncoder>(
device, device->GetProcs().deviceCreateRenderBundleEncoder(
device->GetHandle(), &dawn_desc));
- encoder->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ encoder->setLabel(webgpu_desc->label());
return encoder;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl
index 8629cc25ffd..6c44a5f72a5 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl
@@ -16,5 +16,7 @@ enum GPULoadOp {
enum GPUStoreOp {
"store",
- "clear"
+ "discard",
+
+ "clear" // Deprecated
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc
index 994335f5012..f79d0ff81f4 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h"
-#include "third_party/blink/renderer/bindings/modules/v8/double_sequence_or_gpu_color_dict.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_index_format.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_doublesequence_gpucolordict.h"
#include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h"
@@ -53,7 +52,6 @@ void GPURenderPassEncoder::setBindGroup(
dynamic_offsets_data_length, data);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void GPURenderPassEncoder::setBlendConstant(const V8GPUColor* color,
ExceptionState& exception_state) {
if (color->IsDoubleSequence() && color->GetAsDoubleSequence().size() != 4) {
@@ -64,25 +62,9 @@ void GPURenderPassEncoder::setBlendConstant(const V8GPUColor* color,
WGPUColor dawn_color = AsDawnType(color);
GetProcs().renderPassEncoderSetBlendConstant(GetHandle(), &dawn_color);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void GPURenderPassEncoder::setBlendConstant(DoubleSequenceOrGPUColorDict& color,
- ExceptionState& exception_state) {
- if (color.IsDoubleSequence() && color.GetAsDoubleSequence().size() != 4) {
- exception_state.ThrowRangeError("color size must be 4");
- return;
- }
-
- WGPUColor dawn_color = AsDawnType(&color);
- GetProcs().renderPassEncoderSetBlendConstant(GetHandle(), &dawn_color);
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void GPURenderPassEncoder::setBlendColor(
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUColor* color,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- DoubleSequenceOrGPUColorDict& color,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
device_->AddConsoleWarning(
"setBlendColor is deprecated. Use setBlendConstant instead.");
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h
index a034b741643..b0d51bef8af 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h
@@ -15,7 +15,6 @@
namespace blink {
class GPUBindGroup;
-class DoubleSequenceOrGPUColorDict;
class GPURenderBundle;
class V8GPUIndexFormat;
@@ -57,16 +56,9 @@ class GPURenderPassEncoder : public DawnObject<WGPURenderPassEncoder>,
GetProcs().renderPassEncoderSetPipeline(GetHandle(), pipeline->GetHandle());
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setBlendConstant(const V8GPUColor* color,
ExceptionState& exception_state);
void setBlendColor(const V8GPUColor* color, ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void setBlendConstant(DoubleSequenceOrGPUColorDict& color,
- ExceptionState& exception_state);
- void setBlendColor(DoubleSequenceOrGPUColorDict& color,
- ExceptionState& exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
void setStencilReference(uint32_t reference) {
GetProcs().renderPassEncoderSetStencilReference(GetHandle(), reference);
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc
index 367a9cfbdb6..e185a1a5cf6 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc
@@ -126,8 +126,10 @@ void GPUPrimitiveStateAsWGPUPrimitiveState(
dawn_state->dawn_desc.nextInChain = nullptr;
dawn_state->dawn_desc.topology =
AsDawnEnum<WGPUPrimitiveTopology>(webgpu_desc->topology());
- dawn_state->dawn_desc.stripIndexFormat =
- AsDawnEnum<WGPUIndexFormat>(webgpu_desc->stripIndexFormat());
+ if (webgpu_desc->hasStripIndexFormat()) {
+ dawn_state->dawn_desc.stripIndexFormat =
+ AsDawnEnum<WGPUIndexFormat>(webgpu_desc->stripIndexFormat());
+ }
dawn_state->dawn_desc.frontFace =
AsDawnEnum<WGPUFrontFace>(webgpu_desc->frontFace());
dawn_state->dawn_desc.cullMode =
@@ -136,7 +138,8 @@ void GPUPrimitiveStateAsWGPUPrimitiveState(
if (webgpu_desc->hasClampDepth()) {
auto* clamp_state = &dawn_state->depth_clamping_state;
clamp_state->chain.sType = WGPUSType_PrimitiveDepthClampingState;
- clamp_state->clampDepth = webgpu_desc->clampDepth();
+ clamp_state->clampDepth = webgpu_desc->clampDepth().has_value() &&
+ webgpu_desc->clampDepth().value();
dawn_state->dawn_desc.nextInChain =
reinterpret_cast<WGPUChainedStruct*>(clamp_state);
}
@@ -202,7 +205,7 @@ void AsDawnVertexBufferLayouts(
value->IsNullOrUndefined()) {
WGPUVertexBufferLayout dawn_vertex_buffer = {};
dawn_vertex_buffer.arrayStride = 0;
- dawn_vertex_buffer.stepMode = WGPUInputStepMode_Vertex;
+ dawn_vertex_buffer.stepMode = WGPUVertexStepMode_Vertex;
dawn_vertex_buffer.attributeCount = 0;
dawn_vertex_buffer.attributes = nullptr;
dawn_vertex_buffers->push_back(dawn_vertex_buffer);
@@ -219,7 +222,7 @@ void AsDawnVertexBufferLayouts(
WGPUVertexBufferLayout dawn_vertex_buffer = {};
dawn_vertex_buffer.arrayStride = vertex_buffer->arrayStride();
dawn_vertex_buffer.stepMode =
- AsDawnEnum<WGPUInputStepMode>(vertex_buffer->stepMode());
+ AsDawnEnum<WGPUVertexStepMode>(vertex_buffer->stepMode());
dawn_vertex_buffer.attributeCount =
static_cast<uint32_t>(vertex_buffer->attributes().size());
dawn_vertex_buffer.attributes = nullptr;
@@ -373,9 +376,10 @@ GPURenderPipeline* GPURenderPipeline::Create(
}
pipeline = MakeGarbageCollected<GPURenderPipeline>(
- device, device->GetProcs().deviceCreateRenderPipeline2(
+ device, device->GetProcs().deviceCreateRenderPipeline(
device->GetHandle(), &dawn_desc_info.dawn_desc));
- pipeline->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ pipeline->setLabel(webgpu_desc->label());
return pipeline;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h
index 91340d04ed1..f0f8c5cd2be 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h
@@ -61,7 +61,7 @@ struct OwnedRenderPipelineDescriptor {
OwnedRenderPipelineDescriptor& operator=(
OwnedRenderPipelineDescriptor&& desc) = delete;
- WGPURenderPipelineDescriptor2 dawn_desc = {};
+ WGPURenderPipelineDescriptor dawn_desc = {};
std::string label;
std::string vertex_entry_point;
Vector<WGPUVertexBufferLayout> buffers;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl
index 6a10358db58..a32e8f98ec0 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl
@@ -11,4 +11,5 @@ enum GPUPowerPreference {
dictionary GPURequestAdapterOptions {
GPUPowerPreference powerPreference;
+ boolean forceSoftware = false;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc
index aebb8e68015..785ad6da653 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc
@@ -55,7 +55,8 @@ GPUSampler* GPUSampler::Create(GPUDevice* device,
GPUSampler* sampler = MakeGarbageCollected<GPUSampler>(
device,
device->GetProcs().deviceCreateSampler(device->GetHandle(), &dawn_desc));
- sampler->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ sampler->setLabel(webgpu_desc->label());
return sampler;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc
index 2c448a2ae0d..edd64e05132 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc
@@ -7,6 +7,7 @@
#include <dawn/webgpu.h>
#include "gpu/command_buffer/client/webgpu_interface.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_usvstring_uint32array.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_shader_module_descriptor.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_callback.h"
@@ -32,30 +33,31 @@ GPUShaderModule* GPUShaderModule::Create(
std::string label;
WGPUShaderModuleDescriptor dawn_desc = {};
- auto wgsl_or_spirv = webgpu_desc->code();
- if (wgsl_or_spirv.IsUSVString()) {
- wgsl_code = wgsl_or_spirv.GetAsUSVString().Utf8();
-
- wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
- wgsl_desc.source = wgsl_code.c_str();
- dawn_desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc);
- } else {
- DCHECK(wgsl_or_spirv.IsUint32Array());
- NotShared<DOMUint32Array> code = wgsl_or_spirv.GetAsUint32Array();
-
- uint32_t length_words = 0;
- if (!base::CheckedNumeric<uint32_t>(code->length())
- .AssignIfValid(&length_words)) {
- exception_state.ThrowRangeError(
- "The provided ArrayBuffer exceeds the maximum supported size "
- "(4294967295)");
- return nullptr;
+ const auto* wgsl_or_spirv = webgpu_desc->code();
+ switch (wgsl_or_spirv->GetContentType()) {
+ case V8UnionUSVStringOrUint32Array::ContentType::kUSVString: {
+ wgsl_code = wgsl_or_spirv->GetAsUSVString().Utf8();
+ wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
+ wgsl_desc.source = wgsl_code.c_str();
+ dawn_desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc);
+ break;
+ }
+ case V8UnionUSVStringOrUint32Array::ContentType::kUint32Array: {
+ NotShared<DOMUint32Array> code = wgsl_or_spirv->GetAsUint32Array();
+ uint32_t length_words = 0;
+ if (!base::CheckedNumeric<uint32_t>(code->length())
+ .AssignIfValid(&length_words)) {
+ exception_state.ThrowRangeError(
+ "The provided ArrayBuffer exceeds the maximum supported size "
+ "(4294967295)");
+ return nullptr;
+ }
+ spirv_desc.chain.sType = WGPUSType_ShaderModuleSPIRVDescriptor;
+ spirv_desc.code = code->Data();
+ spirv_desc.codeSize = length_words;
+ dawn_desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&spirv_desc);
+ break;
}
-
- spirv_desc.chain.sType = WGPUSType_ShaderModuleSPIRVDescriptor;
- spirv_desc.code = code->Data();
- spirv_desc.codeSize = length_words;
- dawn_desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&spirv_desc);
}
if (webgpu_desc->hasLabel()) {
@@ -66,7 +68,8 @@ GPUShaderModule* GPUShaderModule::Create(
GPUShaderModule* shader = MakeGarbageCollected<GPUShaderModule>(
device, device->GetProcs().deviceCreateShaderModule(device->GetHandle(),
&dawn_desc));
- shader->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ shader->setLabel(webgpu_desc->label());
return shader;
}
@@ -102,8 +105,8 @@ ScriptPromise GPUShaderModule::compilationInfo(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
auto* callback =
- BindDawnCallback(&GPUShaderModule::OnCompilationInfoCallback,
- WrapPersistent(this), WrapPersistent(resolver));
+ BindDawnOnceCallback(&GPUShaderModule::OnCompilationInfoCallback,
+ WrapPersistent(this), WrapPersistent(resolver));
GetProcs().shaderModuleGetCompilationInfo(
GetHandle(), callback->UnboundCallback(), callback->AsUserdata());
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.cc
new file mode 100644
index 00000000000..15eadfa8e08
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.cc
@@ -0,0 +1,104 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h"
+
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_extent_3d_dict.h"
+
+#include <algorithm>
+
+#define SUPPORTED_LIMITS \
+ MAX(unsigned, maxTextureDimension1D, max_texture_dimension_1d_) \
+ MAX(unsigned, maxTextureDimension2D, max_texture_dimension_2d_) \
+ MAX(unsigned, maxTextureDimension3D, max_texture_dimension_3d_) \
+ MAX(unsigned, maxTextureArrayLayers, max_texture_array_layers_) \
+ MAX(unsigned, maxBindGroups, max_bind_groups_) \
+ MAX(unsigned, maxDynamicUniformBuffersPerPipelineLayout, \
+ max_dynamic_uniform_buffers_per_pipeline_layout_) \
+ MAX(unsigned, maxDynamicStorageBuffersPerPipelineLayout, \
+ max_dynamic_storage_buffers_per_pipeline_layout_) \
+ MAX(unsigned, maxSampledTexturesPerShaderStage, \
+ max_sampled_textures_per_shader_stage_) \
+ MAX(unsigned, maxSamplersPerShaderStage, max_samplers_per_shader_stage_) \
+ MAX(unsigned, maxStorageBuffersPerShaderStage, \
+ max_storage_buffers_per_shader_stage_) \
+ MAX(unsigned, maxStorageTexturesPerShaderStage, \
+ max_storage_textures_per_shader_stage_) \
+ MAX(unsigned, maxUniformBuffersPerShaderStage, \
+ max_uniform_buffers_per_shader_stage_) \
+ MAX(uint64_t, maxUniformBufferBindingSize, max_uniform_buffer_binding_size_) \
+ MAX(uint64_t, maxStorageBufferBindingSize, max_storage_buffer_binding_size_) \
+ MIN(unsigned, minUniformBufferOffsetAlignment, \
+ min_uniform_buffer_offset_alignment_) \
+ MIN(unsigned, minStorageBufferOffsetAlignment, \
+ min_storage_buffer_offset_alignment_) \
+ MAX(unsigned, maxVertexBuffers, max_vertex_buffers_) \
+ MAX(unsigned, maxVertexAttributes, max_vertex_attributes_) \
+ MAX(unsigned, maxVertexBufferArrayStride, max_vertex_buffer_array_stride_) \
+ MAX(unsigned, maxInterStageShaderComponents, \
+ max_inter_stage_shader_components_) \
+ MAX(unsigned, maxComputeWorkgroupStorageSize, \
+ max_compute_workgroup_storage_size_) \
+ MAX(unsigned, maxComputeInvocationsPerWorkgroup, \
+ max_compute_invocations_per_workgroup_) \
+ MAX(unsigned, maxComputeWorkgroupSizeX, max_compute_workgroup_size_x_) \
+ MAX(unsigned, maxComputeWorkgroupSizeY, max_compute_workgroup_size_y_) \
+ MAX(unsigned, maxComputeWorkgroupSizeZ, max_compute_workgroup_size_z_) \
+ MAX(unsigned, maxComputeWorkgroupsPerDimension, \
+ max_compute_workgroups_per_dimension_)
+
+namespace blink {
+
+GPUSupportedLimits::GPUSupportedLimits(
+ const Vector<std::pair<String, uint64_t>>& limits) {
+ for (const auto& key_value : limits) {
+#define MAX(type, name, member) \
+ if (key_value.first == #name) { \
+ member = std::max(static_cast<type>(key_value.second), member); \
+ continue; \
+ }
+#define MIN(type, name, member) \
+ if (key_value.first == #name) { \
+ member = std::min(static_cast<type>(key_value.second), member); \
+ continue; \
+ }
+ SUPPORTED_LIMITS
+#undef MIN
+#undef MAX
+
+ // Unrecognized keys should be rejected by validation prior to reaching
+ // this point.
+ NOTREACHED();
+ }
+}
+
+#define MAX(type, name, member) \
+ type GPUSupportedLimits::name() const { return member; }
+#define MIN MAX
+SUPPORTED_LIMITS
+#undef MIN
+#undef MAX
+
+GPUSupportedLimits::ValidationResult GPUSupportedLimits::ValidateLimit(
+ const String& name,
+ uint64_t value) {
+#define MAX(type, limit_name, member) \
+ if (name == #limit_name) { \
+ return value <= limit_name() ? ValidationResult::Valid \
+ : ValidationResult::BadValue; \
+ }
+#define MIN(type, limit_name, member) \
+ if (name == #limit_name) { \
+ return value >= limit_name() ? ValidationResult::Valid \
+ : ValidationResult::BadValue; \
+ }
+ SUPPORTED_LIMITS
+#undef MIN
+#undef MAX
+
+ // Unknown limit name.
+ return ValidationResult::BadName;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h
new file mode 100644
index 00000000000..ceb92462efb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.h
@@ -0,0 +1,90 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_SUPPORTED_LIMITS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_SUPPORTED_LIMITS_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class GPUSupportedLimits final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ enum class ValidationResult { Valid, BadName, BadValue };
+
+ // Create an object with the default limits.
+ GPUSupportedLimits() = default;
+
+ explicit GPUSupportedLimits(
+ const Vector<std::pair<String, uint64_t>>& limits);
+
+ GPUSupportedLimits(const GPUSupportedLimits&) = delete;
+ GPUSupportedLimits& operator=(const GPUSupportedLimits&) = delete;
+
+ ValidationResult ValidateLimit(const String& name, uint64_t value);
+
+ unsigned maxTextureDimension1D() const;
+ unsigned maxTextureDimension2D() const;
+ unsigned maxTextureDimension3D() const;
+ unsigned maxTextureArrayLayers() const;
+ unsigned maxBindGroups() const;
+ unsigned maxDynamicUniformBuffersPerPipelineLayout() const;
+ unsigned maxDynamicStorageBuffersPerPipelineLayout() const;
+ unsigned maxSampledTexturesPerShaderStage() const;
+ unsigned maxSamplersPerShaderStage() const;
+ unsigned maxStorageBuffersPerShaderStage() const;
+ unsigned maxStorageTexturesPerShaderStage() const;
+ unsigned maxUniformBuffersPerShaderStage() const;
+ uint64_t maxUniformBufferBindingSize() const;
+ uint64_t maxStorageBufferBindingSize() const;
+ unsigned minUniformBufferOffsetAlignment() const;
+ unsigned minStorageBufferOffsetAlignment() const;
+ unsigned maxVertexBuffers() const;
+ unsigned maxVertexAttributes() const;
+ unsigned maxVertexBufferArrayStride() const;
+ unsigned maxInterStageShaderComponents() const;
+ unsigned maxComputeWorkgroupStorageSize() const;
+ unsigned maxComputeInvocationsPerWorkgroup() const;
+ unsigned maxComputeWorkgroupSizeX() const;
+ unsigned maxComputeWorkgroupSizeY() const;
+ unsigned maxComputeWorkgroupSizeZ() const;
+ unsigned maxComputeWorkgroupsPerDimension() const;
+
+ private:
+ unsigned max_texture_dimension_1d_ = 8192;
+ unsigned max_texture_dimension_2d_ = 8192;
+ unsigned max_texture_dimension_3d_ = 2048;
+ unsigned max_texture_array_layers_ = 2048;
+ unsigned max_bind_groups_ = 4;
+ unsigned max_dynamic_uniform_buffers_per_pipeline_layout_ = 8;
+ unsigned max_dynamic_storage_buffers_per_pipeline_layout_ = 4;
+ unsigned max_sampled_textures_per_shader_stage_ = 16;
+ unsigned max_samplers_per_shader_stage_ = 16;
+ unsigned max_storage_buffers_per_shader_stage_ = 4;
+ unsigned max_storage_textures_per_shader_stage_ = 4;
+ unsigned max_uniform_buffers_per_shader_stage_ = 12;
+ uint64_t max_uniform_buffer_binding_size_ = 16384;
+ uint64_t max_storage_buffer_binding_size_ = 134217728;
+ unsigned min_uniform_buffer_offset_alignment_ = 256;
+ unsigned min_storage_buffer_offset_alignment_ = 256;
+ unsigned max_vertex_buffers_ = 8;
+ unsigned max_vertex_attributes_ = 16;
+ unsigned max_vertex_buffer_array_stride_ = 2048;
+ unsigned max_inter_stage_shader_components_ = 60;
+ unsigned max_compute_workgroup_storage_size_ = 16352;
+ unsigned max_compute_invocations_per_workgroup_ = 256;
+ unsigned max_compute_workgroup_size_x_ = 256;
+ unsigned max_compute_workgroup_size_y_ = 256;
+ unsigned max_compute_workgroup_size_z_ = 64;
+ unsigned max_compute_workgroups_per_dimension_ = 65535;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_SUPPORTED_LIMITS_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.idl
new file mode 100644
index 00000000000..27108abff87
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_supported_limits.idl
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://gpuweb.github.io/gpuweb/
+
+[
+ Exposed(Window WebGPU, Worker WebGPU)
+] interface GPUSupportedLimits {
+ readonly attribute unsigned long maxTextureDimension1D;
+ readonly attribute unsigned long maxTextureDimension2D;
+ readonly attribute unsigned long maxTextureDimension3D;
+ readonly attribute unsigned long maxTextureArrayLayers;
+ readonly attribute unsigned long maxBindGroups;
+ readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout;
+ readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout;
+ readonly attribute unsigned long maxSampledTexturesPerShaderStage;
+ readonly attribute unsigned long maxSamplersPerShaderStage;
+ readonly attribute unsigned long maxStorageBuffersPerShaderStage;
+ readonly attribute unsigned long maxStorageTexturesPerShaderStage;
+ readonly attribute unsigned long maxUniformBuffersPerShaderStage;
+ readonly attribute unsigned long long maxUniformBufferBindingSize;
+ readonly attribute unsigned long long maxStorageBufferBindingSize;
+ readonly attribute unsigned long minUniformBufferOffsetAlignment;
+ readonly attribute unsigned long minStorageBufferOffsetAlignment;
+ readonly attribute unsigned long maxVertexBuffers;
+ readonly attribute unsigned long maxVertexAttributes;
+ readonly attribute unsigned long maxVertexBufferArrayStride;
+ readonly attribute unsigned long maxInterStageShaderComponents;
+ readonly attribute unsigned long maxComputeWorkgroupStorageSize;
+ readonly attribute unsigned long maxComputeInvocationsPerWorkgroup;
+ readonly attribute unsigned long maxComputeWorkgroupSizeX;
+ readonly attribute unsigned long maxComputeWorkgroupSizeY;
+ readonly attribute unsigned long maxComputeWorkgroupSizeZ;
+ readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.cc
index 7054b42bf2e..4bcc04df46d 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.cc
@@ -5,10 +5,14 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h"
#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/command_buffer/client/raster_interface.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_queue.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.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/gpu/webgpu_mailbox_texture.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -19,11 +23,13 @@ GPUSwapChain::GPUSwapChain(GPUCanvasContext* context,
GPUDevice* device,
WGPUTextureUsage usage,
WGPUTextureFormat format,
- SkFilterQuality filter_quality)
+ cc::PaintFlags::FilterQuality filter_quality,
+ IntSize size)
: DawnObjectImpl(device),
context_(context),
usage_(usage),
- format_(format) {
+ format_(format),
+ size_(size) {
// TODO: Use label from GPUObjectDescriptorBase.
swap_buffers_ = base::AdoptRef(new WebGPUSwapBufferProvider(
this, GetDawnControlClient(), device->GetHandle(), usage_, format));
@@ -53,7 +59,8 @@ cc::Layer* GPUSwapChain::CcLayer() {
return swap_buffers_->CcLayer();
}
-void GPUSwapChain::SetFilterQuality(SkFilterQuality filter_quality) {
+void GPUSwapChain::SetFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) {
DCHECK(swap_buffers_);
if (swap_buffers_) {
swap_buffers_->SetFilterQuality(filter_quality);
@@ -118,22 +125,99 @@ scoped_refptr<CanvasResource> GPUSwapChain::ExportCanvasResource() {
IntSize(transferable_resource.size),
transferable_resource.mailbox_holder.texture_target, resource_params,
swap_buffers_->GetContextProviderWeakPtr(), /*resource_provider=*/nullptr,
- kLow_SkFilterQuality,
+ cc::PaintFlags::FilterQuality::kLow,
/*is_origin_top_left=*/kBottomLeft_GrSurfaceOrigin,
transferable_resource.is_overlay_candidate);
}
-// gpu_swap_chain.idl
-GPUTexture* GPUSwapChain::getCurrentTexture() {
- if (!swap_buffers_) {
- // TODO(cwallez@chromium.org) return an error texture.
- return nullptr;
+bool GPUSwapChain::CopyToResourceProvider(
+ CanvasResourceProvider* resource_provider) {
+ DCHECK(resource_provider);
+ DCHECK_EQ(resource_provider->Size(), IntSize(Size()));
+ DCHECK(resource_provider->GetSharedImageUsageFlags() &
+ gpu::SHARED_IMAGE_USAGE_WEBGPU);
+ DCHECK(resource_provider->IsOriginTopLeft());
+
+ if (!texture_)
+ return false;
+
+ if (!(usage_ & WGPUTextureUsage_CopySrc))
+ return false;
+
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> shared_context_wrapper =
+ SharedGpuContext::ContextProviderWrapper();
+ if (!shared_context_wrapper || !shared_context_wrapper->ContextProvider())
+ return false;
+
+ const auto dst_mailbox =
+ resource_provider->GetBackingMailboxForOverwrite(kUnverifiedSyncToken);
+ if (dst_mailbox.IsZero())
+ return false;
+
+ auto* ri = shared_context_wrapper->ContextProvider()->RasterInterface();
+
+ if (!GetContextProviderWeakPtr()) {
+ return false;
}
+ gpu::webgpu::WebGPUInterface* webgpu =
+ GetContextProviderWeakPtr()->ContextProvider()->WebGPUInterface();
+ gpu::webgpu::ReservedTexture reservation =
+ webgpu->ReserveTexture(device_->GetHandle());
+ DCHECK(reservation.texture);
+
+ gpu::SyncToken sync_token;
+ ri->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ webgpu->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+ webgpu->AssociateMailbox(reservation.deviceId, reservation.deviceGeneration,
+ reservation.id, reservation.generation,
+ WGPUTextureUsage_CopyDst,
+ reinterpret_cast<const GLbyte*>(&dst_mailbox));
+
+ WGPUCommandEncoder command_encoder =
+ GetProcs().deviceCreateCommandEncoder(device_->GetHandle(), nullptr);
+
+ WGPUImageCopyTexture source = {
+ .nextInChain = nullptr,
+ .texture = texture_->GetHandle(),
+ .mipLevel = 0,
+ .origin = WGPUOrigin3D{0},
+ .aspect = WGPUTextureAspect_All,
+ };
+ WGPUImageCopyTexture destination = {
+ .nextInChain = nullptr,
+ .texture = reservation.texture,
+ .mipLevel = 0,
+ .origin = WGPUOrigin3D{0},
+ .aspect = WGPUTextureAspect_All,
+ };
+ WGPUExtent3D copy_size = {
+ .width = static_cast<uint32_t>(swap_buffers_->Size().width()),
+ .height = static_cast<uint32_t>(swap_buffers_->Size().height()),
+ .depthOrArrayLayers = 1,
+ };
+ GetProcs().commandEncoderCopyTextureToTexture(command_encoder, &source,
+ &destination, &copy_size);
+ WGPUCommandBuffer command_buffer =
+ GetProcs().commandEncoderFinish(command_encoder, nullptr);
+ GetProcs().commandEncoderRelease(command_encoder);
+
+ GetProcs().queueSubmit(device_->queue()->GetHandle(), 1u, &command_buffer);
+ GetProcs().commandBufferRelease(command_buffer);
+
+ webgpu->DissociateMailbox(reservation.id, reservation.generation);
+ webgpu->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+
+ return true;
+}
+
+// gpu_swap_chain.idl
+GPUTexture* GPUSwapChain::getCurrentTexture() {
// As we are getting a new texture, we need to tell the canvas context that
// there will be a need to send a new frame to the offscreencanvas.
if (context_->IsOffscreenCanvas())
- context_->DidDraw();
+ context_->DidDraw(CanvasPerformanceMonitor::DrawType::kOther);
// Calling getCurrentTexture returns a texture that is valid until the
// animation frame it gets presented. If getCurrenTexture is called multiple
@@ -143,11 +227,23 @@ GPUTexture* GPUSwapChain::getCurrentTexture() {
return texture_;
}
- WGPUTexture dawn_client_texture =
- swap_buffers_->GetNewTexture(context_->CanvasSize());
- DCHECK(dawn_client_texture);
- texture_ =
- MakeGarbageCollected<GPUTexture>(device_, dawn_client_texture, format_);
+ if (!swap_buffers_) {
+ texture_ = GPUTexture::CreateError(device_);
+ return texture_;
+ }
+
+ // A negative size indicates we're on the deprecated path which automatically
+ // adjusts to the canvas width/height attributes.
+ // TODO(bajones@chromium.org): Remove automatic path after deprecation period.
+ IntSize texture_size = size_.Width() >= 0 ? size_ : context_->CanvasSize();
+ WGPUTexture dawn_client_texture = swap_buffers_->GetNewTexture(texture_size);
+ if (!dawn_client_texture) {
+ texture_ = GPUTexture::CreateError(device_);
+ return texture_;
+ }
+ // SwapChain buffer are 2d.
+ texture_ = MakeGarbageCollected<GPUTexture>(
+ device_, dawn_client_texture, WGPUTextureDimension_2D, format_, usage_);
return texture_;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h
index 54a2a400aaa..fa8c2642026 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h
@@ -29,14 +29,19 @@ class GPUSwapChain : public DawnObjectImpl,
GPUDevice*,
WGPUTextureUsage,
WGPUTextureFormat,
- SkFilterQuality);
+ cc::PaintFlags::FilterQuality,
+ IntSize);
~GPUSwapChain() override;
void Trace(Visitor* visitor) const override;
void Neuter();
cc::Layer* CcLayer();
- void SetFilterQuality(SkFilterQuality);
+ void SetFilterQuality(cc::PaintFlags::FilterQuality);
+
+ const gfx::Size& Size() const { return swap_buffers_->Size(); }
+
+ viz::ResourceFormat Format() const { return swap_buffers_->Format(); }
// Returns a StaticBitmapImage backed by a texture containing the current
// contents of the front buffer. This is done without any pixel copies. The
@@ -48,6 +53,10 @@ class GPUSwapChain : public DawnObjectImpl,
// encapsulate an external mailbox, synctoken and release callback.
scoped_refptr<CanvasResource> ExportCanvasResource();
+ // Copies the back buffer to given shared image resource provider which must
+ // be webgpu compatible. Returns true on success.
+ bool CopyToResourceProvider(CanvasResourceProvider*);
+
// gpu_swap_chain.idl
GPUTexture* getCurrentTexture();
@@ -62,6 +71,7 @@ class GPUSwapChain : public DawnObjectImpl,
Member<GPUCanvasContext> context_;
WGPUTextureUsage usage_;
WGPUTextureFormat format_;
+ const IntSize size_;
Member<GPUTexture> texture_;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
index 0505b29bfb2..37e0e03b431 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
@@ -5,19 +5,19 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
#include "gpu/command_buffer/client/webgpu_interface.h"
-#include "media/base/video_frame.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_view_descriptor.h"
-#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
+#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture_view.h"
+#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.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/gpu/webgpu_mailbox_texture.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h"
-#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
namespace blink {
@@ -35,7 +35,7 @@ WGPUTextureDescriptor AsDawnType(const GPUTextureDescriptor* webgpu_desc,
dawn_desc.usage = static_cast<WGPUTextureUsage>(webgpu_desc->usage());
dawn_desc.dimension =
AsDawnEnum<WGPUTextureDimension>(webgpu_desc->dimension());
- dawn_desc.size = AsDawnType(&webgpu_desc->size(), device);
+ dawn_desc.size = AsDawnType(webgpu_desc->size());
dawn_desc.format = AsDawnEnum<WGPUTextureFormat>(webgpu_desc->format());
dawn_desc.mipLevelCount = webgpu_desc->mipLevelCount();
dawn_desc.sampleCount = webgpu_desc->sampleCount();
@@ -56,9 +56,13 @@ WGPUTextureViewDescriptor AsDawnType(
WGPUTextureViewDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
- dawn_desc.format = AsDawnEnum<WGPUTextureFormat>(webgpu_desc->format());
- dawn_desc.dimension =
- AsDawnEnum<WGPUTextureViewDimension>(webgpu_desc->dimension());
+ if (webgpu_desc->hasFormat()) {
+ dawn_desc.format = AsDawnEnum<WGPUTextureFormat>(webgpu_desc->format());
+ }
+ if (webgpu_desc->hasDimension()) {
+ dawn_desc.dimension =
+ AsDawnEnum<WGPUTextureViewDimension>(webgpu_desc->dimension());
+ }
dawn_desc.baseMipLevel = webgpu_desc->baseMipLevel();
dawn_desc.mipLevelCount = webgpu_desc->mipLevelCount();
dawn_desc.baseArrayLayer = webgpu_desc->baseArrayLayer();
@@ -72,6 +76,10 @@ WGPUTextureViewDescriptor AsDawnType(
return dawn_desc;
}
+void popErrorDiscardCallback(WGPUErrorType, const char*, void*) {
+ // This callback is used to silently consume expected error messages
+}
+
} // anonymous namespace
// static
@@ -87,60 +95,81 @@ GPUTexture* GPUTexture::Create(GPUDevice* device,
GPUTexture* texture = MakeGarbageCollected<GPUTexture>(
device,
device->GetProcs().deviceCreateTexture(device->GetHandle(), &dawn_desc),
- dawn_desc.format);
- texture->setLabel(webgpu_desc->label());
+ dawn_desc.dimension, dawn_desc.format,
+ static_cast<WGPUTextureUsage>(dawn_desc.usage));
+ if (webgpu_desc->hasLabel())
+ texture->setLabel(webgpu_desc->label());
+ return texture;
+}
+
+// static
+GPUTexture* GPUTexture::CreateError(GPUDevice* device) {
+ DCHECK(device);
+
+ // Force the creation of an invalid texture and consume the errors that it
+ // causes. It would be nice if Dawn provided a more direct way of creating
+ // an error texture to simplify this.
+ WGPUTextureDescriptor dawn_desc = {};
+ device->GetProcs().devicePushErrorScope(device->GetHandle(),
+ WGPUErrorFilter_Validation);
+ GPUTexture* texture = MakeGarbageCollected<GPUTexture>(
+ device,
+ device->GetProcs().deviceCreateTexture(device->GetHandle(), &dawn_desc),
+ dawn_desc.dimension, dawn_desc.format,
+ static_cast<WGPUTextureUsage>(dawn_desc.usage));
+ device->GetProcs().devicePopErrorScope(device->GetHandle(),
+ &popErrorDiscardCallback, nullptr);
+
return texture;
}
// static
-GPUTexture* GPUTexture::FromVideo(GPUDevice* device,
- HTMLVideoElement* video,
- WGPUTextureUsage usage,
- ExceptionState& exception_state) {
- if (!video || !video->videoWidth() || !video->videoHeight()) {
+GPUTexture* GPUTexture::FromCanvas(GPUDevice* device,
+ HTMLCanvasElement* canvas,
+ WGPUTextureUsage usage,
+ ExceptionState& exception_state) {
+ if (!canvas || !canvas->width() || !canvas->height()) {
exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
- "Missing video source");
+ "Missing canvas source");
return nullptr;
}
- if (video->WouldTaintOrigin()) {
+ if (!canvas->OriginClean()) {
exception_state.ThrowSecurityError(
- "Video element contains cross-origin data and may not be loaded.");
+ "Canvas element is tainted by cross-origin data and may not be "
+ "loaded.");
return nullptr;
}
- media::PaintCanvasVideoRenderer* video_renderer = nullptr;
- scoped_refptr<media::VideoFrame> media_video_frame;
- if (auto* wmp = video->GetWebMediaPlayer()) {
- media_video_frame = wmp->GetCurrentFrame();
- video_renderer = wmp->GetPaintCanvasVideoRenderer();
- }
-
- if (!media_video_frame || !video_renderer) {
+ // TODO: Webgpu contexts also return true for Is3d(), but most of the webgl
+ // specific CanvasRenderingContext methods don't work for webgpu.
+ auto* canvas_context = canvas->RenderingContext();
+ if (!canvas_context) {
exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
- "Failed to import texture from video");
+ "Missing canvas rendering context");
return nullptr;
}
// If the context is lost, the resource provider would be invalid.
auto context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
if (!context_provider_wrapper ||
- context_provider_wrapper->ContextProvider()->IsContextLost())
+ context_provider_wrapper->ContextProvider()->IsContextLost()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Shared GPU context lost");
return nullptr;
+ }
- // TODO:(magchen@): Use kN32_SkColorType when kBGRA_8888_SkColorType is
- // supported. Set kRGBA_8888_SkColorType for now to keep recycling working.
- const CanvasResourceParams params(
- CanvasColorSpace::kSRGB, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
- const auto intrinsic_size = IntSize(media_video_frame->natural_size());
+ const CanvasResourceParams params(CanvasColorSpace::kSRGB, kN32_SkColorType,
+ kPremul_SkAlphaType);
// Get a recyclable resource for producing WebGPU-compatible shared images.
+ // First texel i.e. UV (0, 0) should be mapped to top left of the source.
std::unique_ptr<RecyclableCanvasResource> recyclable_canvas_resource =
device->GetDawnControlClient()->GetOrCreateCanvasResource(
- intrinsic_size, params, /*is_origin_top_left=*/true);
+ canvas->Size(), params, /*is_origin_top_left=*/true);
if (!recyclable_canvas_resource) {
exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
- "Failed to import texture from video");
+ "Failed to create resource provider");
return nullptr;
}
@@ -148,77 +177,72 @@ GPUTexture* GPUTexture::FromVideo(GPUDevice* device,
recyclable_canvas_resource->resource_provider();
DCHECK(resource_provider);
- viz::RasterContextProvider* raster_context_provider = nullptr;
- if (auto* context_provider = context_provider_wrapper->ContextProvider())
- raster_context_provider = context_provider->RasterContextProvider();
-
- // TODO(crbug.com/1174809): This isn't efficient for VideoFrames which are
- // already available as a shared image. A WebGPUMailboxTexture should be
- // created directly from the VideoFrame instead.
- const auto dest_rect = gfx::Rect(media_video_frame->natural_size());
- if (!DrawVideoFrameIntoResourceProvider(
- std::move(media_video_frame), resource_provider,
- raster_context_provider, dest_rect, video_renderer)) {
+ // Extract the format. This is only used to validate experimentalImportTexture
+ // right now. We may want to reflect it from this function or validate it
+ // against some input parameters.
+ WGPUTextureFormat format =
+ AsDawnType(resource_provider->ColorParams().GetSkColorType());
+ if (format == WGPUTextureFormat_Undefined) {
exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
- "Failed to import texture from video");
+ "Unsupported format for import texture");
return nullptr;
}
- // Extract the format. This is only used to validate copyImageBitmapToTexture
- // right now. We may want to reflect it from this function or validate it
- // against some input parameters.
- WGPUTextureFormat format;
- switch (resource_provider->ColorParams().GetSkColorType()) {
- case SkColorType::kRGBA_8888_SkColorType:
- format = WGPUTextureFormat_RGBA8Unorm;
- break;
- case SkColorType::kBGRA_8888_SkColorType:
- format = WGPUTextureFormat_BGRA8Unorm;
- break;
- case SkColorType::kRGBA_1010102_SkColorType:
- format = WGPUTextureFormat_RGB10A2Unorm;
- break;
- case SkColorType::kRGBA_F16_SkColorType:
- format = WGPUTextureFormat_RGBA16Float;
- break;
- case SkColorType::kRGBA_F32_SkColorType:
- format = WGPUTextureFormat_RGBA32Float;
- break;
- case SkColorType::kR8G8_unorm_SkColorType:
- format = WGPUTextureFormat_RG8Unorm;
- break;
- case SkColorType::kR16G16_float_SkColorType:
- format = WGPUTextureFormat_RG16Float;
- break;
- default:
- exception_state.ThrowDOMException(
- DOMExceptionCode::kOperationError,
- "Failed to import texture from video. Unsupported format.");
+ if (!canvas_context->CopyRenderingResultsFromDrawingBuffer(resource_provider,
+ kBackBuffer)) {
+ // Fallback to static bitmap image.
+ SourceImageStatus source_image_status = kInvalidSourceImageStatus;
+ auto image = canvas->GetSourceImageForCanvas(&source_image_status,
+ FloatSize(canvas->Size()));
+ if (source_image_status != kNormalSourceImageStatus) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to get image from canvas");
return nullptr;
+ }
+ auto* static_bitmap_image = DynamicTo<StaticBitmapImage>(image.get());
+ if (!static_bitmap_image ||
+ !static_bitmap_image->CopyToResourceProvider(resource_provider)) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from canvas");
+ return nullptr;
+ }
}
scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
WebGPUMailboxTexture::FromCanvasResource(
device->GetDawnControlClient(), device->GetHandle(), usage,
std::move(recyclable_canvas_resource));
+ DCHECK(mailbox_texture->GetTexture());
- DCHECK(mailbox_texture->GetTexture() != nullptr);
-
- return MakeGarbageCollected<GPUTexture>(device, format,
+ return MakeGarbageCollected<GPUTexture>(device, format, usage,
std::move(mailbox_texture));
}
GPUTexture::GPUTexture(GPUDevice* device,
WGPUTexture texture,
- WGPUTextureFormat format)
- : DawnObject<WGPUTexture>(device, texture), format_(format) {}
+ WGPUTextureDimension dimension,
+ WGPUTextureFormat format,
+ WGPUTextureUsage usage)
+ : DawnObject<WGPUTexture>(device, texture),
+ dimension_(dimension),
+ format_(format),
+ usage_(usage) {}
GPUTexture::GPUTexture(GPUDevice* device,
WGPUTextureFormat format,
+ WGPUTextureUsage usage,
scoped_refptr<WebGPUMailboxTexture> mailbox_texture)
: DawnObject<WGPUTexture>(device, mailbox_texture->GetTexture()),
format_(format),
- mailbox_texture_(std::move(mailbox_texture)) {}
+ usage_(usage),
+ mailbox_texture_(std::move(mailbox_texture)) {
+ // Mailbox textures are all 2d texture.
+ dimension_ = WGPUTextureDimension_2D;
+
+ // The mailbox texture releases the texture on destruction, so reference it
+ // here.
+ GetProcs().textureReference(GetHandle());
+}
GPUTextureView* GPUTexture::createView(
const GPUTextureViewDescriptor* webgpu_desc) {
@@ -228,7 +252,8 @@ GPUTextureView* GPUTexture::createView(
WGPUTextureViewDescriptor dawn_desc = AsDawnType(webgpu_desc, &label);
GPUTextureView* view = MakeGarbageCollected<GPUTextureView>(
device_, GetProcs().textureCreateView(GetHandle(), &dawn_desc));
- view->setLabel(webgpu_desc->label());
+ if (webgpu_desc->hasLabel())
+ view->setLabel(webgpu_desc->label());
return view;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h
index faf52d08059..b2507d6d78d 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h
@@ -11,7 +11,7 @@
namespace blink {
class ExceptionState;
-class HTMLVideoElement;
+class HTMLCanvasElement;
class GPUTextureDescriptor;
class GPUTextureView;
class GPUTextureViewDescriptor;
@@ -25,24 +25,34 @@ class GPUTexture : public DawnObject<WGPUTexture> {
static GPUTexture* Create(GPUDevice* device,
const GPUTextureDescriptor* webgpu_desc,
ExceptionState& exception_state);
- static GPUTexture* FromVideo(GPUDevice* device,
- HTMLVideoElement* video,
- WGPUTextureUsage usage,
- ExceptionState& exception_state);
+ static GPUTexture* CreateError(GPUDevice* device);
+ static GPUTexture* FromCanvas(GPUDevice* device,
+ HTMLCanvasElement* canvas,
+ WGPUTextureUsage usage,
+ ExceptionState& exception_state);
- GPUTexture(GPUDevice* device, WGPUTexture texture, WGPUTextureFormat format);
GPUTexture(GPUDevice* device,
+ WGPUTexture texture,
+ WGPUTextureDimension dimension,
WGPUTextureFormat format,
+ WGPUTextureUsage usage);
+ GPUTexture(GPUDevice* device,
+ WGPUTextureFormat format,
+ WGPUTextureUsage usage,
scoped_refptr<WebGPUMailboxTexture> mailbox_texture);
// gpu_texture.idl
GPUTextureView* createView(const GPUTextureViewDescriptor* webgpu_desc);
void destroy();
+ WGPUTextureDimension Dimension() { return dimension_; }
WGPUTextureFormat Format() { return format_; }
+ WGPUTextureUsage Usage() { return usage_; }
private:
+ WGPUTextureDimension dimension_;
WGPUTextureFormat format_;
+ WGPUTextureUsage usage_;
scoped_refptr<WebGPUMailboxTexture> mailbox_texture_;
DISALLOW_COPY_AND_ASSIGN(GPUTexture);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.cc
new file mode 100644
index 00000000000..bd6d3c4e90e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.cc
@@ -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.
+
+#include "third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+
+namespace blink {
+
+namespace {
+void AddConsoleWarning(ExecutionContext* execution_context,
+ const char* message) {
+ if (execution_context) {
+ auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering,
+ mojom::blink::ConsoleMessageLevel::kWarning, message);
+ execution_context->AddConsoleMessage(console_message);
+ }
+}
+} // namespace
+
+// static
+unsigned GPUTextureUsage::SAMPLED(ExecutionContext* execution_context) {
+ AddConsoleWarning(execution_context,
+ "GPUTextureUsage.SAMPLED is deprecated. "
+ "Use GPUTextureUsage.TEXTURE_BINDING instead.");
+ return kTextureBinding;
+}
+
+// static
+unsigned GPUTextureUsage::STORAGE(ExecutionContext* execution_context) {
+ AddConsoleWarning(execution_context,
+ "GPUTextureUsage.STORAGE is deprecated. "
+ "Use GPUTextureUsage.STORAGE_BINDING instead.");
+ return kStorageBinding;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h
index 0a89c18c915..cfe6db305ca 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h
@@ -5,10 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_TEXTURE_USAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_TEXTURE_USAGE_H_
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
+class ExecutionContext;
+
class GPUTextureUsage : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -16,10 +19,13 @@ class GPUTextureUsage : public ScriptWrappable {
// gpu_texture_usage.idl
static constexpr uint32_t kCopySrc = 1;
static constexpr uint32_t kCopyDst = 2;
- static constexpr uint32_t kSampled = 4;
- static constexpr uint32_t kStorage = 8;
+ static constexpr uint32_t kTextureBinding = 4;
+ static constexpr uint32_t kStorageBinding = 8;
static constexpr uint32_t kRenderAttachment = 16;
+ static unsigned SAMPLED(ExecutionContext* execution_context);
+ static unsigned STORAGE(ExecutionContext* execution_context);
+
private:
DISALLOW_COPY_AND_ASSIGN(GPUTextureUsage);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl
index f3c7235e7dc..a355c5f30a4 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl
@@ -10,7 +10,11 @@ typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
] interface GPUTextureUsage {
const unsigned long COPY_SRC = 1;
const unsigned long COPY_DST = 2;
- const unsigned long SAMPLED = 4;
- const unsigned long STORAGE = 8;
+ const unsigned long TEXTURE_BINDING = 4;
+ const unsigned long STORAGE_BINDING = 8;
const unsigned long RENDER_ATTACHMENT = 16;
+
+ // Deprecated names. Use TEXTURE_BINDING and STORAGE_BINDING instead.
+ [CallWith=ExecutionContext] static readonly attribute unsigned long SAMPLED; // 4
+ [CallWith=ExecutionContext] static readonly attribute unsigned long STORAGE; // 8
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.cc
index c3de2031715..01fd6b3246d 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.cc
@@ -21,20 +21,7 @@ GPUUncapturedErrorEvent::GPUUncapturedErrorEvent(
const AtomicString& type,
const GPUUncapturedErrorEventInit* gpuUncapturedErrorEventInitDict)
: Event(type, Bubbles::kNo, Cancelable::kYes) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const auto& old_union = gpuUncapturedErrorEventInitDict->error();
- if (old_union.IsGPUOutOfMemoryError()) {
- error_ =
- MakeGarbageCollected<V8GPUError>(old_union.GetAsGPUOutOfMemoryError());
- } else if (old_union.IsGPUValidationError()) {
- error_ =
- MakeGarbageCollected<V8GPUError>(old_union.GetAsGPUValidationError());
- } else {
- NOTREACHED();
- }
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
error_ = gpuUncapturedErrorEventInitDict->error();
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
void GPUUncapturedErrorEvent::Trace(Visitor* visitor) const {
@@ -42,15 +29,8 @@ void GPUUncapturedErrorEvent::Trace(Visitor* visitor) const {
Event::Trace(visitor);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUError* GPUUncapturedErrorEvent::error() const {
return error_;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-void GPUUncapturedErrorEvent::error(
- GPUOutOfMemoryErrorOrGPUValidationError& error) const {
- error = error_;
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h
index 9751a04423a..fa9d7b13cc8 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h
@@ -5,13 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_UNCAPTURED_ERROR_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_UNCAPTURED_ERROR_EVENT_H_
-#include "third_party/blink/renderer/bindings/modules/v8/gpu_out_of_memory_error_or_gpu_validation_error.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/modules/event_modules.h"
namespace blink {
-class GPUOutOfMemoryErrorOrGPUValidationError;
class GPUUncapturedErrorEventInit;
class GPUUncapturedErrorEvent : public Event {
@@ -26,18 +24,10 @@ class GPUUncapturedErrorEvent : public Event {
void Trace(Visitor*) const override;
// gpu_uncaptured_error_event.idl
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8GPUError* error() const;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- void error(GPUOutOfMemoryErrorOrGPUValidationError&) const;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
private:
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
Member<V8GPUError> error_;
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- GPUOutOfMemoryErrorOrGPUValidationError error_;
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DISALLOW_COPY_AND_ASSIGN(GPUUncapturedErrorEvent);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_layout.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_layout.idl
index 42c754d6b27..c6dfc05530d 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_layout.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_layout.idl
@@ -6,11 +6,11 @@
dictionary GPUVertexBufferLayout {
required GPUSize64 arrayStride;
- GPUInputStepMode stepMode = "vertex";
+ GPUVertexStepMode stepMode = "vertex";
required sequence<GPUVertexAttribute> attributes;
};
-enum GPUInputStepMode {
+enum GPUVertexStepMode {
"vertex",
"instance"
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/idls.gni b/chromium/third_party/blink/renderer/modules/webgpu/idls.gni
deleted file mode 100644
index dbb3c55710f..00000000000
--- a/chromium/third_party/blink/renderer/modules/webgpu/idls.gni
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "gpu.idl",
- "gpu_adapter.idl",
- "gpu_bind_group.idl",
- "gpu_bind_group_layout.idl",
- "gpu_buffer.idl",
- "gpu_buffer_usage.idl",
- "gpu_canvas_context.idl",
- "gpu_color_write.idl",
- "gpu_command_buffer.idl",
- "gpu_command_encoder.idl",
- "gpu_compilation_info.idl",
- "gpu_compilation_message.idl",
- "gpu_compute_pass_encoder.idl",
- "gpu_compute_pipeline.idl",
- "gpu_device.idl",
- "gpu_device_lost_info.idl",
- "gpu_map_mode.idl",
- "gpu_out_of_memory_error.idl",
- "gpu_pipeline_layout.idl",
- "gpu_query_set.idl",
- "gpu_queue.idl",
- "gpu_render_bundle.idl",
- "gpu_render_bundle_encoder.idl",
- "gpu_render_pass_encoder.idl",
- "gpu_render_pipeline.idl",
- "gpu_sampler.idl",
- "gpu_shader_module.idl",
- "gpu_shader_stage.idl",
- "gpu_supported_features.idl",
- "gpu_swap_chain.idl",
- "gpu_texture.idl",
- "gpu_texture_usage.idl",
- "gpu_texture_view.idl",
- "gpu_uncaptured_error_event.idl",
- "gpu_validation_error.idl",
-]
-
-modules_dictionary_idl_files = [
- "gpu_bind_group_descriptor.idl",
- "gpu_bind_group_entry.idl",
- "gpu_bind_group_layout_descriptor.idl",
- "gpu_bind_group_layout_entry.idl",
- "gpu_blend_component.idl",
- "gpu_blend_state.idl",
- "gpu_buffer_binding.idl",
- "gpu_buffer_binding_layout.idl",
- "gpu_buffer_descriptor.idl",
- "gpu_color_dict.idl",
- "gpu_color_state_descriptor.idl",
- "gpu_color_target_state.idl",
- "gpu_command_buffer_descriptor.idl",
- "gpu_command_encoder_descriptor.idl",
- "gpu_compute_pass_descriptor.idl",
- "gpu_compute_pipeline_descriptor.idl",
- "gpu_depth_stencil_state_descriptor.idl",
- "gpu_depth_stencil_state.idl",
- "gpu_device_descriptor.idl",
- "gpu_extent_3d_dict.idl",
- "gpu_fragment_state.idl",
- "gpu_image_copy_buffer.idl",
- "gpu_image_copy_image_bitmap.idl",
- "gpu_image_copy_texture.idl",
- "gpu_image_data_layout.idl",
- "gpu_limits.idl",
- "gpu_multisample_state.idl",
- "gpu_object_descriptor_base.idl",
- "gpu_origin_2d_dict.idl",
- "gpu_origin_3d_dict.idl",
- "gpu_pipeline_descriptor_base.idl",
- "gpu_pipeline_layout_descriptor.idl",
- "gpu_primitive_state.idl",
- "gpu_programmable_stage.idl",
- "gpu_query_set_descriptor.idl",
- "gpu_rasterization_state_descriptor.idl",
- "gpu_render_bundle_descriptor.idl",
- "gpu_render_bundle_encoder_descriptor.idl",
- "gpu_render_pass_color_attachment.idl",
- "gpu_render_pass_depth_stencil_attachment.idl",
- "gpu_render_pass_descriptor.idl",
- "gpu_render_pipeline_descriptor.idl",
- "gpu_request_adapter_options.idl",
- "gpu_sampler_binding_layout.idl",
- "gpu_sampler_descriptor.idl",
- "gpu_shader_module_descriptor.idl",
- "gpu_stencil_face_state.idl",
- "gpu_storage_texture_binding_layout.idl",
- "gpu_swap_chain_descriptor.idl",
- "gpu_texture_binding_layout.idl",
- "gpu_texture_descriptor.idl",
- "gpu_texture_view_descriptor.idl",
- "gpu_uncaptured_error_event_init.idl",
- "gpu_vertex_attribute.idl",
- "gpu_vertex_buffer_layout.idl",
- "gpu_vertex_state.idl",
-]
-
-modules_dependency_idl_files = [
- "gpu_object_base.idl",
- "gpu_pipeline_base.idl",
- "gpu_programmable_pass_encoder.idl",
- "gpu_render_encoder_base.idl",
- "navigator_gpu.idl",
- "worker_navigator_gpu.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/webid/idls.gni b/chromium/third_party/blink/renderer/modules/webid/idls.gni
deleted file mode 100644
index 2ddeca6fb12..00000000000
--- a/chromium/third_party/blink/renderer/modules/webid/idls.gni
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [ "web_id.idl" ]
-
-modules_dictionary_idl_files = [ "web_id_request_options.idl" ]
-
-modules_dependency_idl_files = [ "navigator_web_id.idl" ]
diff --git a/chromium/third_party/blink/renderer/modules/webid/web_id.cc b/chromium/third_party/blink/renderer/modules/webid/web_id.cc
index 2ef8db4c04d..be1f27054a8 100644
--- a/chromium/third_party/blink/renderer/modules/webid/web_id.cc
+++ b/chromium/third_party/blink/renderer/modules/webid/web_id.cc
@@ -134,16 +134,6 @@ WebId::WebId(ExecutionContext& context)
ScriptPromise WebId::get(ScriptState* script_state,
const WebIdRequestOptions* options,
ExceptionState& exception_state) {
- if (!options->hasProvider()) {
- exception_state.ThrowTypeError("Invalid parameters: provider required.");
- return ScriptPromise();
- }
-
- if (!options->hasRequest()) {
- exception_state.ThrowTypeError("Invalid parameters: request required.");
- return ScriptPromise();
- }
-
DCHECK(options->hasMode());
// TODO(kenrb): Add some renderer-side validation here, such as validating
@@ -161,8 +151,11 @@ ScriptPromise WebId::get(ScriptState* script_state,
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
+ String client_id = options->hasClientId() ? options->clientId() : "";
+ String nonce = options->hasNonce() ? options->nonce() : "";
+
auth_request_->RequestIdToken(
- provider, options->request(), ToRequestMode(options->mode()),
+ provider, client_id, nonce, ToRequestMode(options->mode()),
WTF::Bind(&OnRequestIdToken, WrapPersistent(resolver)));
return promise;
diff --git a/chromium/third_party/blink/renderer/modules/webid/web_id_request_options.idl b/chromium/third_party/blink/renderer/modules/webid/web_id_request_options.idl
index 8d3dc870c85..591aecfa1d9 100644
--- a/chromium/third_party/blink/renderer/modules/webid/web_id_request_options.idl
+++ b/chromium/third_party/blink/renderer/modules/webid/web_id_request_options.idl
@@ -11,8 +11,8 @@ enum Mode {
dictionary WebIdRequestOptions {
// URL for the Identity Provider.
- USVString provider;
- // Serialized request parameters.
- USVString request;
+ required USVString provider;
+ USVString client_id;
+ USVString nonce;
Mode mode = "permission";
};
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/idls.gni b/chromium/third_party/blink/renderer/modules/webmidi/idls.gni
deleted file mode 100644
index 13fdae57ed0..00000000000
--- a/chromium/third_party/blink/renderer/modules/webmidi/idls.gni
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "midi_access.idl",
- "midi_connection_event.idl",
- "midi_input.idl",
- "midi_input_map.idl",
- "midi_message_event.idl",
- "midi_output.idl",
- "midi_output_map.idl",
- "midi_port.idl",
-]
-
-modules_dictionary_idl_files = [
- "midi_connection_event_init.idl",
- "midi_message_event_init.idl",
- "midi_options.idl",
-]
-
-modules_dependency_idl_files = [ "navigator_web_midi.idl" ]
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 e16c08488a5..9a2e39223fb 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc
@@ -78,8 +78,7 @@ base::TimeTicks GetTimeOrigin(ExecutionContext* context) {
}
DCHECK(performance);
- return base::TimeTicks() +
- base::TimeDelta::FromSecondsD(performance->GetTimeOrigin());
+ return performance->GetTimeOriginInternal();
}
class MessageValidator {
diff --git a/chromium/third_party/blink/renderer/modules/webrtc/DEPS b/chromium/third_party/blink/renderer/modules/webrtc/DEPS
index f9e5e6dd262..378ca4f60f7 100644
--- a/chromium/third_party/blink/renderer/modules/webrtc/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webrtc/DEPS
@@ -10,6 +10,7 @@ include_rules = [
"+media/base/audio_parameters.h",
"+media/base/audio_pull_fifo.h",
"+media/base/audio_renderer_sink.h",
+ "+media/base/audio_timestamp_helper.h",
"+media/base/bind_to_current_loop.h",
"+media/base/channel_layout.h",
"+media/base/sample_rates.h",
diff --git a/chromium/third_party/blink/renderer/modules/webrtc/OWNERS b/chromium/third_party/blink/renderer/modules/webrtc/OWNERS
index 21ecac2ba02..59c145a10ad 100644
--- a/chromium/third_party/blink/renderer/modules/webrtc/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/webrtc/OWNERS
@@ -1 +1,3 @@
file://third_party/blink/renderer/modules/mediastream/OWNERS
+
+olka@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
index 07ad762cbd4..c78e07ca49b 100644
--- a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
@@ -32,7 +32,6 @@ void SendLogMessage(const std::string& message) {
WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
: audio_processing_id_(base::UnguessableToken::Create()),
audio_transport_callback_(nullptr),
- output_delay_ms_(0),
initialized_(false),
playing_(false),
recording_(false) {
@@ -56,7 +55,7 @@ WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() {
void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds,
+ base::TimeDelta audio_delay,
base::TimeDelta* current_time) {
{
base::AutoLock auto_lock(lock_);
@@ -79,7 +78,7 @@ void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
}
DCHECK(audio_transport_callback_);
// Store the reported audio delay locally.
- output_delay_ms_ = audio_delay_milliseconds;
+ output_delay_ = audio_delay;
}
const int frames_per_10_ms = sample_rate / 100;
@@ -114,7 +113,7 @@ void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
// Pass the render data to the playout sinks.
base::AutoLock auto_lock(lock_);
for (auto* sink : playout_sinks_)
- sink->OnPlayoutData(audio_bus, sample_rate, audio_delay_milliseconds);
+ sink->OnPlayoutData(audio_bus, sample_rate, audio_delay);
}
void WebRtcAudioDeviceImpl::RemoveAudioRenderer(
@@ -352,7 +351,9 @@ int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const {
int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const {
DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
base::AutoLock auto_lock(lock_);
- *delay_ms = static_cast<uint16_t>(output_delay_ms_);
+ const int64_t output_delay_ms = output_delay_.InMilliseconds();
+ DCHECK_LE(output_delay_ms, std::numeric_limits<uint16_t>::max());
+ *delay_ms = base::saturated_cast<uint16_t>(output_delay_ms);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h
index be3b358e9f7..11090c32305 100644
--- a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h
+++ b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h
@@ -127,7 +127,7 @@ class MODULES_EXPORT WebRtcAudioDeviceImpl
// Called on the AudioOutputDevice worker thread.
void RenderData(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds,
+ base::TimeDelta audio_delay,
base::TimeDelta* current_time) override;
// Called on the main render thread.
@@ -175,9 +175,9 @@ class MODULES_EXPORT WebRtcAudioDeviceImpl
webrtc::AudioTransport* audio_transport_callback_;
// Cached value of the current audio delay on the output/renderer side.
- int output_delay_ms_ GUARDED_BY(lock_);
+ base::TimeDelta output_delay_ GUARDED_BY(lock_);
- // Protects |renderer_|, |playout_sinks_|, |output_delay_ms_|, |playing_|,
+ // Protects |renderer_|, |playout_sinks_|, |output_delay_|, |playing_|,
// and |recording_|.
mutable base::Lock lock_;
diff --git a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc
index 2cfcc471878..fa8a93c3de9 100644
--- a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc
+++ b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/containers/contains.h"
+#include "base/containers/cxx20_erase.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
@@ -17,6 +18,7 @@
#include "media/base/audio_capturer_source.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_parameters.h"
+#include "media/base/audio_timestamp_helper.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/channel_layout.h"
#include "media/base/sample_rates.h"
@@ -701,19 +703,15 @@ void WebRtcAudioRenderer::SourceCallback(int fifo_frame_delay,
DVLOG(2) << "WRAR::SourceCallback(" << fifo_frame_delay << ", "
<< audio_bus->channels() << ", " << audio_bus->frames() << ")";
- int output_delay_milliseconds =
- static_cast<int>(audio_delay_.InMilliseconds());
- // TODO(grunell): This integer division by sample_rate will cause loss of
- // partial milliseconds, and may cause avsync drift. http://crbug.com/586540
- output_delay_milliseconds += fifo_frame_delay *
- base::Time::kMillisecondsPerSecond /
- sink_params_.sample_rate();
- DVLOG(2) << "output_delay_milliseconds: " << output_delay_milliseconds;
+ const base::TimeDelta output_delay =
+ audio_delay_ + media::AudioTimestampHelper::FramesToTime(
+ fifo_frame_delay, sink_params_.sample_rate());
+ DVLOG(2) << "output_delay (ms): " << output_delay.InMillisecondsF();
// We need to keep render data for the |source_| regardless of |state_|,
// otherwise the data will be buffered up inside |source_|.
- source_->RenderData(audio_bus, sink_params_.sample_rate(),
- output_delay_milliseconds, &current_time_);
+ source_->RenderData(audio_bus, sink_params_.sample_rate(), output_delay,
+ &current_time_);
// Avoid filling up the audio bus if we are not playing; instead
// return here and ensure that the returned value in Render() is 0.
diff --git a/chromium/third_party/blink/renderer/modules/webshare/FILE_TYPES.md b/chromium/third_party/blink/renderer/modules/webshare/FILE_TYPES.md
index 1fc4f892a88..563f57dec82 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/FILE_TYPES.md
+++ b/chromium/third_party/blink/renderer/modules/webshare/FILE_TYPES.md
@@ -5,6 +5,8 @@ The following list should be kept in sync with
- //components/browser_ui/webshare/android/java/src/org/chromium/components/browser_ui/webshare/ShareServiceImpl.java
+# Application
+ "pdf" - application/pdf
# Audio
"flac" - audio/flac
"m4a" - audio/x-m4a
diff --git a/chromium/third_party/blink/renderer/modules/webshare/idls.gni b/chromium/third_party/blink/renderer/modules/webshare/idls.gni
deleted file mode 100644
index 65bdfe7b38b..00000000000
--- a/chromium/third_party/blink/renderer/modules/webshare/idls.gni
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_dictionary_idl_files = [ "share_data.idl" ]
-
-modules_dependency_idl_files = [ "navigator_share.idl" ]
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 92edaca748a..58933b7dac4 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
+++ b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -144,8 +144,8 @@ NavigatorShare::ShareClientImpl::ShareClientImpl(
void NavigatorShare::ShareClientImpl::Callback(mojom::blink::ShareError error) {
if (navigator_) {
- DCHECK_EQ(navigator_->client_, this);
- navigator_->client_ = nullptr;
+ DCHECK(navigator_->clients_.Contains(this));
+ navigator_->clients_.erase(this);
}
if (error == mojom::blink::ShareError::OK) {
@@ -185,7 +185,7 @@ NavigatorShare& NavigatorShare::From(Navigator& navigator) {
void NavigatorShare::Trace(Visitor* visitor) const {
visitor->Trace(service_remote_);
- visitor->Trace(client_);
+ visitor->Trace(clients_);
Supplement<Navigator>::Trace(visitor);
}
@@ -227,11 +227,17 @@ ScriptPromise NavigatorShare::share(ScriptState* script_state,
? WebFeature::kWebSharePolicyAllow
: WebFeature::kWebSharePolicyDisallow);
- if (client_) {
+// This is due to a limitation on Android, where we sometimes are not advised
+// when the share completes. This goes against the web share spec to work around
+// the platform-specific bug, it is explicitly skipping section §2.1.2 step 2 of
+// the Web Share spec. https://www.w3.org/TR/web-share/#share-method
+#if !defined(OS_ANDROID)
+ if (!clients_.IsEmpty()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"A earlier share had not yet completed.");
return ScriptPromise();
}
+#endif
if (!LocalFrame::ConsumeTransientUserActivation(window->GetFrame())) {
VLOG(1) << "Share without transient activation (user gesture)";
@@ -291,13 +297,18 @@ ScriptPromise NavigatorShare::share(ScriptState* script_state,
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- client_ = MakeGarbageCollected<ShareClientImpl>(this, has_files, resolver);
+
+ ShareClientImpl* client =
+ MakeGarbageCollected<ShareClientImpl>(this, has_files, resolver);
+ clients_.insert(client);
+ ScriptPromise promise = resolver->Promise();
+
service_remote_->Share(
data->hasTitle() ? data->title() : g_empty_string,
data->hasText() ? data->text() : g_empty_string, url, std::move(files),
- WTF::Bind(&ShareClientImpl::Callback, WrapPersistent(client_.Get())));
+ WTF::Bind(&ShareClientImpl::Callback, WrapPersistent(client)));
- return resolver->Promise();
+ return promise;
}
ScriptPromise NavigatorShare::share(ScriptState* script_state,
@@ -308,9 +319,10 @@ ScriptPromise NavigatorShare::share(ScriptState* script_state,
}
void NavigatorShare::OnConnectionError() {
- if (client_) {
- client_->OnConnectionError();
- client_ = nullptr;
+ HeapHashSet<Member<ShareClientImpl>> clients;
+ clients_.swap(clients);
+ for (auto& client : clients) {
+ client->OnConnectionError();
}
service_remote_.reset();
}
diff --git a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.h b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.h
index ba4b0426c25..a4d8ce8a735 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.h
+++ b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.h
@@ -57,7 +57,10 @@ class MODULES_EXPORT NavigatorShare final
HeapMojoRemote<blink::mojom::blink::ShareService> service_remote_{nullptr};
// Represents a user's current intent to share some data.
- Member<ShareClientImpl> client_ = nullptr;
+ // This set must have at most 1 element on non-Android platforms. This is a
+ // set, and not just and object in order to work around an Android specific
+ // bug in opposition to the web-share spec.
+ HeapHashSet<Member<ShareClientImpl>> clients_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webshare/navigator_share_test.cc b/chromium/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
index 01fbfea2b20..d54a09b70a2 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
@@ -160,14 +160,8 @@ File* CreateSampleFile(ExecutionContext* context,
const String& file_name,
const String& content_type,
const String& file_contents) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
HeapVector<Member<V8BlobPart>> blob_parts;
blob_parts.push_back(MakeGarbageCollected<V8BlobPart>(file_contents));
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString> blob_parts;
- blob_parts.push_back(ArrayBufferOrArrayBufferViewOrBlobOrUSVString());
- blob_parts.back().SetUSVString(file_contents);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
FilePropertyBag file_property_bag;
file_property_bag.setType(content_type);
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 aadc7683de4..8f57ea5a439 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -42,7 +42,6 @@
#include "third_party/blink/public/platform/task_type.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/bindings/core/v8/v8_union_string_stringsequence.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/message_event.h"
@@ -83,7 +82,6 @@ void DOMWebSocket::EventQueue::Dispatch(Event* event) {
switch (state_) {
case kActive:
DCHECK(events_.IsEmpty());
- DCHECK(target_->GetExecutionContext());
target_->DispatchEvent(*event);
break;
case kPaused:
@@ -141,7 +139,6 @@ void DOMWebSocket::EventQueue::DispatchQueuedEvents() {
if (state_ == kStopped || state_ == kPaused || state_ == kUnpausePosted)
break;
DCHECK_EQ(state_, kActive);
- DCHECK(target_->GetExecutionContext());
target_->DispatchEvent(*events.TakeFirst());
// |this| can be stopped here.
}
@@ -204,25 +201,16 @@ void DOMWebSocket::LogError(const String& message) {
DOMWebSocket* DOMWebSocket::Create(ExecutionContext* context,
const String& url,
ExceptionState& exception_state) {
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return Create(
context, url,
MakeGarbageCollected<V8UnionStringOrStringSequence>(Vector<String>()),
exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- StringOrStringSequence protocols;
- return Create(context, url, protocols, exception_state);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
DOMWebSocket* DOMWebSocket::Create(
ExecutionContext* context,
const String& url,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8UnionStringOrStringSequence* protocols,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const StringOrStringSequence& protocols,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (url.IsNull()) {
exception_state.ThrowDOMException(
@@ -234,7 +222,6 @@ DOMWebSocket* DOMWebSocket::Create(
DOMWebSocket* websocket = MakeGarbageCollected<DOMWebSocket>(context);
websocket->UpdateStateIfNeeded();
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DCHECK(protocols);
switch (protocols->GetContentType()) {
case V8UnionStringOrStringSequence::ContentType::kString: {
@@ -248,19 +235,6 @@ DOMWebSocket* DOMWebSocket::Create(
exception_state);
break;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- if (protocols.IsNull()) {
- Vector<String> protocols_vector;
- websocket->Connect(url, protocols_vector, exception_state);
- } else if (protocols.IsString()) {
- Vector<String> protocols_vector;
- protocols_vector.push_back(protocols.GetAsString());
- websocket->Connect(url, protocols_vector, exception_state);
- } else {
- DCHECK(protocols.IsStringSequence());
- websocket->Connect(url, protocols.GetAsStringSequence(), exception_state);
- }
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
if (exception_state.HadException())
return nullptr;
diff --git a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h
index ddd3f110b10..6f859556070 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h
@@ -31,8 +31,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_DOM_WEBSOCKET_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_DOM_WEBSOCKET_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
+
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
@@ -59,7 +60,6 @@ class DOMArrayBuffer;
class DOMArrayBufferView;
class ExceptionState;
class ExecutionContext;
-class StringOrStringSequence;
class V8UnionStringOrStringSequence;
class MODULES_EXPORT DOMWebSocket
@@ -82,17 +82,10 @@ class MODULES_EXPORT DOMWebSocket
static DOMWebSocket* Create(ExecutionContext*,
const String& url,
ExceptionState&);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static DOMWebSocket* Create(ExecutionContext* execution_context,
const String& url,
const V8UnionStringOrStringSequence* protocols,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static DOMWebSocket* Create(ExecutionContext*,
- const String& url,
- const StringOrStringSequence& protocols,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
explicit DOMWebSocket(ExecutionContext*);
~DOMWebSocket() override;
diff --git a/chromium/third_party/blink/renderer/modules/websockets/idls.gni b/chromium/third_party/blink/renderer/modules/websockets/idls.gni
deleted file mode 100644
index 3cbe173200f..00000000000
--- a/chromium/third_party/blink/renderer/modules/websockets/idls.gni
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "close_event.idl",
- "websocket.idl",
- "websocket_stream.idl",
-]
-
-modules_dictionary_idl_files = [
- "close_event_init.idl",
- "websocket_close_info.idl",
- "websocket_connection.idl",
- "websocket_stream_options.idl",
-]
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 b8dcbd34eca..ddd89ee4c2e 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
@@ -61,7 +61,6 @@
#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/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/modules/websockets/inspector_websocket_events.h"
#include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -74,6 +73,7 @@
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
#include "v8/include/v8.h"
@@ -262,10 +262,7 @@ WebSocketChannelImpl::WebSocketChannelImpl(
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
execution_context->GetTaskRunner(TaskType::kNetworking)),
file_reading_task_runner_(
- execution_context->GetTaskRunner(TaskType::kFileReading)) {
- if (auto* scope = DynamicTo<WorkerGlobalScope>(*execution_context_))
- scope->EnsureFetcher();
-}
+ execution_context->GetTaskRunner(TaskType::kFileReading)) {}
WebSocketChannelImpl::~WebSocketChannelImpl() = default;
@@ -327,7 +324,7 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) {
message.Append(url.GetString());
message.Append("' failed: Insufficient resources");
execution_context_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageSource::kNetwork,
mojom::blink::ConsoleMessageLevel::kError, message.ToString()));
execution_context_->GetTaskRunner(TaskType::kNetworking)
->PostTask(FROM_HERE,
@@ -341,11 +338,16 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) {
connector.BindNewPipeAndPassReceiver(
execution_context_->GetTaskRunner(TaskType::kWebSocket)));
+ absl::optional<base::UnguessableToken> devtools_token;
+ probe::WillCreateWebSocket(execution_context_, identifier_, url, protocol,
+ &devtools_token);
+
connector->Connect(
url, protocols, GetBaseFetchContext()->GetSiteForCookies(),
execution_context_->UserAgent(),
handshake_client_receiver_.BindNewPipeAndPassRemote(
- execution_context_->GetTaskRunner(TaskType::kWebSocket)));
+ execution_context_->GetTaskRunner(TaskType::kWebSocket)),
+ /*throttling_profile_id=*/devtools_token);
handshake_client_receiver_.set_disconnect_with_reason_handler(
WTF::Bind(&WebSocketChannelImpl::OnConnectionError,
WrapWeakPersistent(this), FROM_HERE));
@@ -366,7 +368,6 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) {
DEVTOOLS_TIMELINE_TRACE_EVENT_INSTANT(
"WebSocketCreate", InspectorWebSocketCreateEvent::Data,
execution_context_, identifier_, url, protocol);
- probe::DidCreateWebSocket(execution_context_, identifier_, url, protocol);
return true;
}
@@ -464,6 +465,8 @@ void WebSocketChannelImpl::Close(int code, const String& reason) {
code == kCloseEventCodeNotSpecified ? kCloseEventCodeNoStatusRcvd : code);
messages_.push_back(Message(code_to_send, reason));
ProcessSendQueue();
+ // Make the page back/forward cache-able.
+ feature_handle_for_scheduler_.reset();
}
void WebSocketChannelImpl::Fail(const String& reason,
@@ -487,7 +490,7 @@ void WebSocketChannelImpl::Fail(const String& reason,
}
execution_context_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kJavaScript, level, message,
+ mojom::ConsoleMessageSource::kNetwork, level, message,
std::move(location)));
// |reason| is only for logging and should not be provided for scripts,
// hence close reason must be empty in tearDownFailedConnection.
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
index 2b9761f3587..62fdb0ce62c 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -214,7 +214,9 @@ class WebSocketChannelImplTest : public WebSocketChannelImplTestBase {
const net::SiteForCookies& site_for_cookies,
const String& user_agent,
mojo::PendingRemote<network::mojom::blink::WebSocketHandshakeClient>
- handshake_client) override {
+ handshake_client,
+ const absl::optional<base::UnguessableToken>& throttling_profile_id)
+ override {
connect_args_.push_back(ConnectArgs(url, requested_protocols,
site_for_cookies, user_agent,
std::move(handshake_client)));
@@ -309,7 +311,8 @@ class WebSocketChannelImplTest : public WebSocketChannelImplTestBase {
static Vector<uint8_t> AsVector(const char* data, size_t size) {
Vector<uint8_t> v;
- v.Append(reinterpret_cast<const uint8_t*>(data), size);
+ v.Append(reinterpret_cast<const uint8_t*>(data),
+ static_cast<wtf_size_t>(size));
return v;
}
static Vector<uint8_t> AsVector(const char* data) {
@@ -1574,7 +1577,8 @@ class MockWebSocketConnector : public mojom::blink::WebSocketConnector {
const Vector<String>&,
const net::SiteForCookies&,
const String&,
- mojo::PendingRemote<network::mojom::blink::WebSocketHandshakeClient>));
+ mojo::PendingRemote<network::mojom::blink::WebSocketHandshakeClient>,
+ const absl::optional<base::UnguessableToken>&));
};
// This can't use WebSocketChannelImplTest because it requires multiple
@@ -1610,9 +1614,8 @@ TEST_F(WebSocketChannelImplMultipleTest, ConnectionLimit) {
[&handshake_clients](
Unused, Unused, Unused, Unused,
mojo::PendingRemote<network::mojom::blink::WebSocketHandshakeClient>
- handshake_client) {
- handshake_clients.Add(std::move(handshake_client));
- };
+ handshake_client,
+ Unused) { handshake_clients.Add(std::move(handshake_client)); };
auto failure_handshake_throttle =
std::make_unique<StrictMock<MockWebSocketHandshakeThrottle>>();
@@ -1626,7 +1629,7 @@ TEST_F(WebSocketChannelImplMultipleTest, ConnectionLimit) {
{
InSequence s;
- EXPECT_CALL(connector_, Connect(_, _, _, _, _))
+ EXPECT_CALL(connector_, Connect(_, _, _, _, _, _))
.Times(WebSocketChannelImpl::kMaxWebSocketsPerRenderProcess)
.WillRepeatedly(handshake_client_add_action);
@@ -1642,7 +1645,7 @@ TEST_F(WebSocketChannelImplMultipleTest, ConnectionLimit) {
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(*successful_handshake_throttle, ThrottleHandshake(_, _));
- EXPECT_CALL(connector_, Connect(_, _, _, _, _))
+ EXPECT_CALL(connector_, Connect(_, _, _, _, _, _))
.WillOnce(handshake_client_add_action);
EXPECT_CALL(*successful_handshake_throttle, Destructor());
}
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_common_test.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_common_test.cc
index c368c119022..ffa1d36e7e5 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_common_test.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_common_test.cc
@@ -38,7 +38,7 @@ TEST(WebSocketCommonTest, IsValidSubprotocolString) {
static_cast<char>(i)) != kValidCharacters + length) {
continue;
}
- char to_check = char{i};
+ char to_check = static_cast<char>(i);
String s(&to_check, 1u);
EXPECT_FALSE(WebSocketCommon::IsValidSubprotocolString(s));
}
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator_test.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator_test.cc
index f0677310a57..958727e93eb 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator_test.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator_test.cc
@@ -18,7 +18,7 @@ class WebSocketMessageChunkAccumulatorTest : public testing::Test {
static Vector<char> Flatten(const Vector<base::span<const char>>& chunks) {
Vector<char> v;
for (const auto& chunk : chunks) {
- v.Append(chunk.data(), chunk.size());
+ v.Append(chunk.data(), base::checked_cast<wtf_size_t>(chunk.size()));
}
return v;
}
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc
index 618d873f6cf..774889b9211 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_websocket_close_info.h"
@@ -304,8 +303,15 @@ void WebSocketStream::UnderlyingSink::SendAny(ScriptState* script_state,
ExceptionState& exception_state) {
DVLOG(1) << "WebSocketStream::UnderlyingSink " << this << " SendAny()";
auto* isolate = script_state->GetIsolate();
+
if (v8chunk->IsArrayBuffer()) {
- DOMArrayBuffer* data = V8ArrayBuffer::ToImpl(v8chunk.As<v8::ArrayBuffer>());
+ DOMArrayBuffer* data = NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ isolate, v8chunk, exception_state);
+ if (exception_state.HadException()) {
+ closed_ = true;
+ is_writing_ = false;
+ return;
+ }
SendArrayBuffer(script_state, data, 0, data->ByteLength(), resolver,
std::move(callback));
return;
@@ -313,8 +319,8 @@ void WebSocketStream::UnderlyingSink::SendAny(ScriptState* script_state,
if (v8chunk->IsArrayBufferView()) {
NotShared<DOMArrayBufferView> data =
- ToNotShared<NotShared<DOMArrayBufferView>>(isolate, v8chunk,
- exception_state);
+ NativeValueTraits<NotShared<DOMArrayBufferView>>::NativeValue(
+ isolate, v8chunk, exception_state);
if (exception_state.HadException()) {
closed_ = true;
is_writing_ = false;
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/BUILD.gn b/chromium/third_party/blink/renderer/modules/webtransport/BUILD.gn
index 66edac2a9f2..00ac30842ae 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/webtransport/BUILD.gn
@@ -8,6 +8,7 @@ blink_modules_sources("webtransport") {
sources = [
"bidirectional_stream.cc",
"bidirectional_stream.h",
+ "datagram_duplex_stream.cc",
"datagram_duplex_stream.h",
"incoming_stream.cc",
"incoming_stream.h",
@@ -27,6 +28,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"bidirectional_stream_test.cc",
+ "datagram_duplex_stream_test.cc",
"incoming_stream_test.cc",
"outgoing_stream_test.cc",
"test_utils.cc",
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc b/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc
index 54c9d4ec04c..788620026ef 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc
@@ -38,7 +38,7 @@ void BidirectionalStream::Init(ExceptionState& exception_state) {
if (exception_state.HadException())
return;
- incoming_stream_->Init();
+ incoming_stream_->Init(exception_state);
}
void BidirectionalStream::OnIncomingStreamClosed(bool fin_received) {
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream_test.cc b/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream_test.cc
index 6e37b261f05..43bc56f1d85 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/bidirectional_stream_test.cc
@@ -19,11 +19,11 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/webtransport/web_transport_connector.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.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_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_bidirectional_stream.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_web_transport_options.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -172,32 +172,18 @@ class StubWebTransport : public network::mojom::blink::WebTransport {
// This class sets up a connected blink::WebTransport object using a
// StubWebTransport and provides access to both.
-class ScopedWebTransport : public mojom::blink::WebTransportConnector {
+class ScopedWebTransport {
STACK_ALLOCATED();
public:
- // For convenience, this class does work in the constructor. This is okay
- // because it is only used for testing.
- explicit ScopedWebTransport(const V8TestingScope& scope)
- : browser_interface_broker_(
- &scope.GetExecutionContext()->GetBrowserInterfaceBroker()) {
- browser_interface_broker_->SetBinderForTesting(
- mojom::blink::WebTransportConnector::Name_,
- base::BindRepeating(&ScopedWebTransport::BindConnector,
- weak_ptr_factory_.GetWeakPtr()));
- web_transport_ = WebTransport::Create(
- scope.GetScriptState(), "https://example.com/",
- MakeGarbageCollected<WebTransportOptions>(), ASSERT_NO_EXCEPTION);
-
- test::RunPendingTasks();
+ // This constructor runs the event loop.
+ explicit ScopedWebTransport(const V8TestingScope& scope) {
+ creator_.Init(scope.GetScriptState(),
+ base::BindRepeating(&ScopedWebTransport::CreateStub,
+ weak_ptr_factory_.GetWeakPtr()));
}
- ~ScopedWebTransport() override {
- browser_interface_broker_->SetBinderForTesting(
- mojom::blink::WebTransportConnector::Name_, {});
- }
-
- WebTransport* GetWebTransport() const { return web_transport_; }
+ WebTransport* GetWebTransport() const { return creator_.GetWebTransport(); }
StubWebTransport* Stub() const { return stub_.get(); }
void ResetStub() { stub_.reset(); }
@@ -205,8 +191,8 @@ class ScopedWebTransport : public mojom::blink::WebTransportConnector {
BidirectionalStream* CreateBidirectionalStream(const V8TestingScope& scope) {
auto* script_state = scope.GetScriptState();
ScriptPromise bidirectional_stream_promise =
- web_transport_->createBidirectionalStream(script_state,
- ASSERT_NO_EXCEPTION);
+ GetWebTransport()->createBidirectionalStream(script_state,
+ ASSERT_NO_EXCEPTION);
ScriptPromiseTester tester(script_state, bidirectional_stream_promise);
tester.WaitUntilSettled();
@@ -221,7 +207,7 @@ class ScopedWebTransport : public mojom::blink::WebTransportConnector {
BidirectionalStream* RemoteCreateBidirectionalStream(
const V8TestingScope& scope) {
stub_->CreateRemote();
- ReadableStream* streams = web_transport_->incomingBidirectionalStreams();
+ ReadableStream* streams = GetWebTransport()->incomingBidirectionalStreams();
v8::Local<v8::Value> v8value = ReadValueFromStream(scope, streams);
@@ -232,45 +218,15 @@ class ScopedWebTransport : public mojom::blink::WebTransportConnector {
return bidirectional_stream;
}
- // Implementation of mojom::blink::WebTransportConnector.
- void Connect(
- const KURL&,
- Vector<network::mojom::blink::WebTransportCertificateFingerprintPtr>
- fingerprints,
- mojo::PendingRemote<network::mojom::blink::WebTransportHandshakeClient>
- pending_handshake_client) override {
- mojo::Remote<network::mojom::blink::WebTransportHandshakeClient>
- handshake_client(std::move(pending_handshake_client));
-
- mojo::PendingRemote<network::mojom::blink::WebTransport>
- web_transport_to_pass;
- mojo::PendingRemote<network::mojom::blink::WebTransportClient>
- client_remote;
-
+ private:
+ void CreateStub(mojo::PendingRemote<network::mojom::blink::WebTransport>&
+ web_transport_to_pass) {
stub_ = std::make_unique<StubWebTransport>(
web_transport_to_pass.InitWithNewPipeAndPassReceiver());
-
- handshake_client->OnConnectionEstablished(
- std::move(web_transport_to_pass),
- client_remote.InitWithNewPipeAndPassReceiver());
- client_remote_.Bind(std::move(client_remote));
- }
-
- private:
- void BindConnector(mojo::ScopedMessagePipeHandle handle) {
- connector_receiver_.Bind(
- mojo::PendingReceiver<mojom::blink::WebTransportConnector>(
- std::move(handle)));
}
- // |browser_interface_broker_| is cached here because we need to use it in the
- // destructor. This means ScopedWebTransport must always be destroyed before
- // the V8TestingScope object that owns the BrowserInterfaceBrokerProxy.
- const BrowserInterfaceBrokerProxy* browser_interface_broker_;
- WebTransport* web_transport_;
+ TestWebTransportCreator creator_;
std::unique_ptr<StubWebTransport> stub_;
- mojo::Remote<network::mojom::blink::WebTransportClient> client_remote_;
- mojo::Receiver<mojom::blink::WebTransportConnector> connector_receiver_{this};
base::WeakPtrFactory<ScopedWebTransport> weak_ptr_factory_{this};
};
@@ -329,7 +285,7 @@ TEST(BidirectionalStreamTest, CreateRemotelyAndWrite) {
// This test fragment is common to CreateLocallyAndRead and
// CreateRemotelyAndRead.
-void TestRead(const V8TestingScope& scope,
+void TestRead(V8TestingScope& scope,
ScopedWebTransport* scoped_web_transport,
BidirectionalStream* bidirectional_stream) {
mojo::ScopedDataPipeProducerHandle& input_producer =
@@ -343,8 +299,9 @@ void TestRead(const V8TestingScope& scope,
v8::Local<v8::Value> v8array =
ReadValueFromStream(scope, bidirectional_stream->readable());
- DOMUint8Array* u8array =
- V8Uint8Array::ToImplWithTypeCheck(scope.GetIsolate(), v8array);
+ NotShared<DOMUint8Array> u8array =
+ NativeValueTraits<NotShared<DOMUint8Array>>::NativeValue(
+ scope.GetIsolate(), v8array, scope.GetExceptionState());
ASSERT_TRUE(u8array);
ASSERT_EQ(u8array->byteLength(), 1u);
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.cc b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.cc
new file mode 100644
index 00000000000..67056af3de6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.cc
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h"
+
+namespace blink {
+
+void DatagramDuplexStream::setIncomingMaxAge(absl::optional<double> max_age) {
+ if (!max_age.has_value() || max_age.value() > 0) {
+ incoming_max_age_ = max_age;
+ }
+}
+
+void DatagramDuplexStream::setOutgoingMaxAge(absl::optional<double> max_age) {
+ if (!max_age.has_value() || max_age.value() > 0) {
+ outgoing_max_age_ = max_age;
+
+ // WebTransport uses 0.0 to signal "implementation default".
+ web_transport_->setDatagramWritableQueueExpirationDuration(
+ max_age.value_or(0.0));
+ }
+}
+
+void DatagramDuplexStream::setIncomingHighWaterMark(int high_water_mark) {
+ if (high_water_mark >= 0) {
+ incoming_high_water_mark_ = high_water_mark;
+ }
+}
+
+void DatagramDuplexStream::setOutgoingHighWaterMark(int high_water_mark) {
+ if (high_water_mark >= 0) {
+ outgoing_high_water_mark_ = high_water_mark;
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h
index 8f6595502c7..2540ba42a9a 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h
+++ b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h
@@ -5,6 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_DATAGRAM_DUPLEX_STREAM_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_DATAGRAM_DUPLEX_STREAM_H_
+#include <stdint.h>
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webtransport/web_transport.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -15,6 +18,8 @@ namespace blink {
class ReadableStream;
class WritableStream;
+constexpr int32_t kDefaultIncomingHighWaterMark = 1;
+
class MODULES_EXPORT DatagramDuplexStream : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -23,8 +28,10 @@ class MODULES_EXPORT DatagramDuplexStream : public ScriptWrappable {
// readable and writable separately.
// TODO(ricea): Once the legacy getters are removed from WebTransport, store
// the readable and writable in this object.
- explicit DatagramDuplexStream(WebTransport* web_transport)
- : web_transport_(web_transport) {}
+ explicit DatagramDuplexStream(WebTransport* web_transport,
+ int32_t initial_outgoing_high_water_mark)
+ : web_transport_(web_transport),
+ outgoing_high_water_mark_(initial_outgoing_high_water_mark) {}
ReadableStream* readable() const {
return web_transport_->datagramReadable();
@@ -34,6 +41,18 @@ class MODULES_EXPORT DatagramDuplexStream : public ScriptWrappable {
return web_transport_->datagramWritable();
}
+ absl::optional<double> incomingMaxAge() const { return incoming_max_age_; }
+ void setIncomingMaxAge(absl::optional<double> max_age);
+
+ absl::optional<double> outgoingMaxAge() const { return outgoing_max_age_; }
+ void setOutgoingMaxAge(absl::optional<double> max_age);
+
+ int32_t incomingHighWaterMark() const { return incoming_high_water_mark_; }
+ void setIncomingHighWaterMark(int32_t high_water_mark);
+
+ int32_t outgoingHighWaterMark() const { return outgoing_high_water_mark_; }
+ void setOutgoingHighWaterMark(int32_t high_water_mark);
+
void Trace(Visitor* visitor) const override {
visitor->Trace(web_transport_);
ScriptWrappable::Trace(visitor);
@@ -41,6 +60,11 @@ class MODULES_EXPORT DatagramDuplexStream : public ScriptWrappable {
private:
const Member<WebTransport> web_transport_;
+
+ absl::optional<double> incoming_max_age_;
+ absl::optional<double> outgoing_max_age_;
+ int32_t incoming_high_water_mark_ = kDefaultIncomingHighWaterMark;
+ int32_t outgoing_high_water_mark_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.idl b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.idl
index 2a3f5ec6ddf..e32300c1e37 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.idl
+++ b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.idl
@@ -9,4 +9,9 @@
] interface DatagramDuplexStream {
readonly attribute ReadableStream readable;
readonly attribute WritableStream writable;
+
+ attribute double? incomingMaxAge;
+ attribute double? outgoingMaxAge;
+ attribute long incomingHighWaterMark;
+ attribute long outgoingHighWaterMark;
};
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream_test.cc b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream_test.cc
new file mode 100644
index 00000000000..e277dbc268d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webtransport/datagram_duplex_stream_test.cc
@@ -0,0 +1,253 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webtransport/datagram_duplex_stream.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "services/network/public/mojom/web_transport.mojom-blink.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/modules/webtransport/test_utils.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+namespace {
+
+constexpr int32_t kInitialOutgoingHighWaterMark = 1;
+
+// Tiny implementation of network::mojom::blink::WebTransport with only the
+// functionality needed for these tests.
+class StubWebTransport final : public network::mojom::blink::WebTransport {
+ public:
+ explicit StubWebTransport(
+ mojo::PendingReceiver<network::mojom::blink::WebTransport>
+ pending_receiver)
+ : receiver_(this, std::move(pending_receiver)) {}
+
+ absl::optional<base::TimeDelta> OutgoingDatagramExpirationDurationValue() {
+ return outgoing_datagram_expiration_duration_value_;
+ }
+
+ // Implementation of WebTransport.
+ void SendDatagram(base::span<const uint8_t> data,
+ base::OnceCallback<void(bool)>) override {
+ NOTREACHED();
+ }
+
+ void CreateStream(
+ mojo::ScopedDataPipeConsumerHandle output_consumer,
+ mojo::ScopedDataPipeProducerHandle input_producer,
+ base::OnceCallback<void(bool, uint32_t)> callback) override {
+ NOTREACHED();
+ }
+
+ void AcceptBidirectionalStream(
+ base::OnceCallback<void(uint32_t,
+ mojo::ScopedDataPipeConsumerHandle,
+ mojo::ScopedDataPipeProducerHandle)> callback)
+ override {
+ DCHECK(!ignored_accept_callback_);
+ // This method is always called. We have to retain the callback to avoid an
+ // error about early destruction, but never call it.
+ ignored_accept_callback_ = std::move(callback);
+ }
+
+ void AcceptUnidirectionalStream(
+ base::OnceCallback<void(uint32_t, mojo::ScopedDataPipeConsumerHandle)>
+ callback) override {
+ DCHECK(!ignored_unidirectional_stream_callback_);
+ // This method is always called. We have to retain the callback to avoid an
+ // error about early destruction, but never call it.
+ ignored_unidirectional_stream_callback_ = std::move(callback);
+ }
+
+ void SendFin(uint32_t stream_id) override {}
+
+ void AbortStream(uint32_t stream_id, uint64_t code) override {}
+
+ void SetOutgoingDatagramExpirationDuration(base::TimeDelta value) override {
+ outgoing_datagram_expiration_duration_value_ = value;
+ }
+
+ private:
+ base::OnceCallback<void(uint32_t,
+ mojo::ScopedDataPipeConsumerHandle,
+ mojo::ScopedDataPipeProducerHandle)>
+ ignored_accept_callback_;
+ base::OnceCallback<void(uint32_t, mojo::ScopedDataPipeConsumerHandle)>
+ ignored_unidirectional_stream_callback_;
+ mojo::Receiver<network::mojom::blink::WebTransport> receiver_;
+ absl::optional<base::TimeDelta> outgoing_datagram_expiration_duration_value_;
+};
+
+// This class sets up a connected blink::WebTransport object using a
+// StubWebTransport and provides access to both.
+class ScopedWebTransport final {
+ STACK_ALLOCATED();
+
+ public:
+ // This constructor runs the event loop.
+ explicit ScopedWebTransport(const V8TestingScope& scope) {
+ creator_.Init(scope.GetScriptState(),
+ WTF::BindRepeating(&ScopedWebTransport::CreateStub,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ WebTransport* GetWebTransport() const { return creator_.GetWebTransport(); }
+ StubWebTransport* Stub() const { return stub_.get(); }
+
+ private:
+ void CreateStub(mojo::PendingRemote<network::mojom::blink::WebTransport>&
+ web_transport_to_pass) {
+ stub_ = std::make_unique<StubWebTransport>(
+ web_transport_to_pass.InitWithNewPipeAndPassReceiver());
+ }
+
+ TestWebTransportCreator creator_;
+ std::unique_ptr<StubWebTransport> stub_;
+
+ base::WeakPtrFactory<ScopedWebTransport> weak_ptr_factory_{this};
+};
+
+class ScopedDatagramDuplexStream final {
+ STACK_ALLOCATED();
+
+ public:
+ ScopedDatagramDuplexStream()
+ : scoped_web_transport_(v8_testing_scope_),
+ duplex_(MakeGarbageCollected<DatagramDuplexStream>(
+ scoped_web_transport_.GetWebTransport(),
+ kInitialOutgoingHighWaterMark)) {}
+ ScopedDatagramDuplexStream(const ScopedDatagramDuplexStream&) = delete;
+ ScopedDatagramDuplexStream& operator=(const ScopedDatagramDuplexStream&) =
+ delete;
+
+ DatagramDuplexStream* Duplex() { return duplex_; }
+
+ StubWebTransport* Stub() { return scoped_web_transport_.Stub(); }
+
+ private:
+ V8TestingScope v8_testing_scope_;
+ ScopedWebTransport scoped_web_transport_;
+ DatagramDuplexStream* const duplex_;
+};
+
+TEST(DatagramDuplexStreamTest, Defaults) {
+ ScopedDatagramDuplexStream scope;
+ auto* duplex = scope.Duplex();
+ EXPECT_FALSE(duplex->incomingMaxAge().has_value());
+ EXPECT_FALSE(duplex->outgoingMaxAge().has_value());
+ EXPECT_EQ(duplex->incomingHighWaterMark(), kDefaultIncomingHighWaterMark);
+ EXPECT_EQ(duplex->outgoingHighWaterMark(), kInitialOutgoingHighWaterMark);
+}
+
+TEST(DatagramDuplexStreamTest, SetIncomingMaxAge) {
+ ScopedDatagramDuplexStream scope;
+ auto* duplex = scope.Duplex();
+
+ duplex->setIncomingMaxAge(1.0);
+ ASSERT_TRUE(duplex->incomingMaxAge().has_value());
+ EXPECT_EQ(duplex->incomingMaxAge().value(), 1.0);
+
+ duplex->setIncomingMaxAge(absl::nullopt);
+ ASSERT_FALSE(duplex->incomingMaxAge().has_value());
+
+ duplex->setIncomingMaxAge(0.0);
+ ASSERT_FALSE(duplex->incomingMaxAge().has_value());
+
+ duplex->setIncomingMaxAge(-1.0);
+ ASSERT_FALSE(duplex->incomingMaxAge().has_value());
+}
+
+TEST(DatagramDuplexStreamTest, SetOutgoingMaxAge) {
+ ScopedDatagramDuplexStream scope;
+ auto* duplex = scope.Duplex();
+ auto* stub = scope.Stub();
+
+ duplex->setOutgoingMaxAge(1.0);
+ ASSERT_TRUE(duplex->outgoingMaxAge().has_value());
+ EXPECT_EQ(duplex->outgoingMaxAge().value(), 1.0);
+ test::RunPendingTasks();
+ auto expiration_duration = stub->OutgoingDatagramExpirationDurationValue();
+ ASSERT_TRUE(expiration_duration.has_value());
+ EXPECT_EQ(expiration_duration.value(),
+ base::TimeDelta::FromMillisecondsD(1.0));
+
+ duplex->setOutgoingMaxAge(absl::nullopt);
+ ASSERT_FALSE(duplex->outgoingMaxAge().has_value());
+ test::RunPendingTasks();
+ expiration_duration = stub->OutgoingDatagramExpirationDurationValue();
+ ASSERT_TRUE(expiration_duration.has_value());
+ EXPECT_EQ(expiration_duration.value(),
+ base::TimeDelta::FromMillisecondsD(0.0));
+
+ duplex->setOutgoingMaxAge(0.5);
+ ASSERT_TRUE(duplex->outgoingMaxAge().has_value());
+ EXPECT_EQ(duplex->outgoingMaxAge().value(), 0.5);
+ test::RunPendingTasks();
+ expiration_duration = stub->OutgoingDatagramExpirationDurationValue();
+ ASSERT_TRUE(expiration_duration.has_value());
+ EXPECT_EQ(expiration_duration.value(),
+ base::TimeDelta::FromMillisecondsD(0.5));
+
+ duplex->setOutgoingMaxAge(0.0);
+ ASSERT_TRUE(duplex->outgoingMaxAge().has_value());
+ EXPECT_EQ(duplex->outgoingMaxAge().value(), 0.5); // unchanged
+ test::RunPendingTasks();
+ expiration_duration = stub->OutgoingDatagramExpirationDurationValue();
+ ASSERT_TRUE(expiration_duration.has_value());
+ EXPECT_EQ(expiration_duration.value(),
+ base::TimeDelta::FromMillisecondsD(0.5)); // Unchanged
+
+ duplex->setOutgoingMaxAge(-1.0);
+ ASSERT_TRUE(duplex->outgoingMaxAge().has_value());
+ EXPECT_EQ(duplex->outgoingMaxAge().value(), 0.5); // unchanged
+ test::RunPendingTasks();
+ expiration_duration = stub->OutgoingDatagramExpirationDurationValue();
+ ASSERT_TRUE(expiration_duration.has_value());
+ EXPECT_EQ(expiration_duration.value(),
+ base::TimeDelta::FromMillisecondsD(0.5)); // Unchanged
+}
+
+TEST(DatagramDuplexStreamTest, SetIncomingHighWaterMark) {
+ ScopedDatagramDuplexStream scope;
+ auto* duplex = scope.Duplex();
+
+ duplex->setIncomingHighWaterMark(10);
+ EXPECT_EQ(duplex->incomingHighWaterMark(), 10);
+
+ duplex->setIncomingHighWaterMark(0);
+ EXPECT_EQ(duplex->incomingHighWaterMark(), 0);
+
+ duplex->setIncomingHighWaterMark(-1);
+ EXPECT_EQ(duplex->incomingHighWaterMark(), 0);
+}
+
+TEST(DatagramDuplexStreamTest, SetOutgoingHighWaterMark) {
+ ScopedDatagramDuplexStream scope;
+ auto* duplex = scope.Duplex();
+
+ duplex->setOutgoingHighWaterMark(10);
+ EXPECT_EQ(duplex->outgoingHighWaterMark(), 10);
+
+ duplex->setOutgoingHighWaterMark(0);
+ EXPECT_EQ(duplex->outgoingHighWaterMark(), 0);
+
+ duplex->setOutgoingHighWaterMark(-1);
+ EXPECT_EQ(duplex->outgoingHighWaterMark(), 0);
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/idls.gni b/chromium/third_party/blink/renderer/modules/webtransport/idls.gni
deleted file mode 100644
index bc2c3df93d6..00000000000
--- a/chromium/third_party/blink/renderer/modules/webtransport/idls.gni
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "bidirectional_stream.idl",
- "datagram_duplex_stream.idl",
- "receive_stream.idl",
- "send_stream.idl",
- "web_transport.idl",
-]
-
-modules_dictionary_idl_files = [
- "web_transport_options.idl",
- "stream_abort_info.idl",
- "web_transport_close_info.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.cc b/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
index d29f91708b3..ec91a1ba053 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
@@ -9,7 +9,6 @@
#include <utility>
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_stream_abort_info.h"
@@ -17,6 +16,7 @@
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
#include "third_party/blink/renderer/core/streams/readable_stream_generic_reader.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
@@ -75,9 +75,15 @@ IncomingStream::IncomingStream(ScriptState* script_state,
IncomingStream::~IncomingStream() = default;
-void IncomingStream::Init() {
+void IncomingStream::Init(ExceptionState& exception_state) {
DVLOG(1) << "IncomingStream::Init() this=" << this;
+ auto* stream = MakeGarbageCollected<ReadableStream>();
+ InitWithExistingReadableStream(stream, exception_state);
+}
+void IncomingStream::InitWithExistingReadableStream(
+ ReadableStream* stream,
+ ExceptionState& exception_state) {
read_watcher_.Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE,
MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
WTF::BindRepeating(&IncomingStream::OnHandleReady,
@@ -94,9 +100,12 @@ void IncomingStream::Init() {
reading_aborted_resolver_ =
MakeGarbageCollected<ScriptPromiseResolver>(script_state_);
reading_aborted_ = reading_aborted_resolver_->Promise();
- readable_ = ReadableStream::CreateWithCountQueueingStrategy(
+ stream->InitWithCountQueueingStrategy(
script_state_,
- MakeGarbageCollected<UnderlyingSource>(script_state_, this), 1);
+ MakeGarbageCollected<UnderlyingSource>(script_state_, this), 1,
+ AllowPerChunkTransferring(false),
+ /*optimizer=*/nullptr, exception_state);
+ readable_ = stream;
}
void IncomingStream::OnIncomingStreamClosed(bool fin_received) {
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.h b/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.h
index 03342ee13eb..640f5e5a40d 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.h
+++ b/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream.h
@@ -46,8 +46,11 @@ class MODULES_EXPORT IncomingStream final
mojo::ScopedDataPipeConsumerHandle);
~IncomingStream();
- // Init() must be called before the stream is used.
- void Init();
+ // Init() or InitWithExistingReadableStream() must be called before the stream
+ // is used.
+ void Init(ExceptionState&);
+
+ void InitWithExistingReadableStream(ReadableStream*, ExceptionState&);
// Methods from the IncomingStream IDL:
// https://wicg.github.io/web-transport/#incoming-stream
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc b/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc
index 66dd2673755..1e728350741 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc
@@ -9,13 +9,13 @@
#include "base/test/mock_callback.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.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_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h"
@@ -54,7 +54,7 @@ class IncomingStreamTest : public ::testing::Test {
auto* script_state = scope.GetScriptState();
auto* incoming_stream = MakeGarbageCollected<IncomingStream>(
script_state, mock_on_abort_.Get(), std::move(data_pipe_consumer_));
- incoming_stream->Init();
+ incoming_stream->Init(ASSERT_NO_EXCEPTION);
return incoming_stream;
}
@@ -69,12 +69,13 @@ class IncomingStreamTest : public ::testing::Test {
void ClosePipe() { data_pipe_producer_.reset(); }
// Copies the contents of a v8::Value containing a Uint8Array to a Vector.
- static Vector<uint8_t> ToVector(const V8TestingScope& scope,
+ static Vector<uint8_t> ToVector(V8TestingScope& scope,
v8::Local<v8::Value> v8value) {
Vector<uint8_t> ret;
- DOMUint8Array* value =
- V8Uint8Array::ToImplWithTypeCheck(scope.GetIsolate(), v8value);
+ NotShared<DOMUint8Array> value =
+ NativeValueTraits<NotShared<DOMUint8Array>>::NativeValue(
+ scope.GetIsolate(), v8value, scope.GetExceptionState());
if (!value) {
ADD_FAILURE() << "chunk is not an Uint8Array";
return ret;
@@ -91,7 +92,7 @@ class IncomingStreamTest : public ::testing::Test {
// Performs a single read from |reader|, converting the output to the
// Iterator type. Assumes that the readable stream is not errored.
- static Iterator Read(const V8TestingScope& scope,
+ static Iterator Read(V8TestingScope& scope,
ReadableStreamDefaultReader* reader) {
auto* script_state = scope.GetScriptState();
ScriptPromise read_promise =
@@ -102,7 +103,7 @@ class IncomingStreamTest : public ::testing::Test {
return IteratorFromReadResult(scope, tester.Value().V8Value());
}
- static Iterator IteratorFromReadResult(const V8TestingScope& scope,
+ static Iterator IteratorFromReadResult(V8TestingScope& scope,
v8::Local<v8::Value> result) {
CHECK(result->IsObject());
Iterator ret;
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc b/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc
index d8b0d6e8c27..5bbb61e73f3 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc
@@ -4,20 +4,22 @@
#include "third_party/blink/renderer/modules/webtransport/outgoing_stream.h"
-#include <string.h>
+#include <cstring>
#include <utility>
#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/numerics/safe_conversions.h"
#include "mojo/public/cpp/system/simple_watcher.h"
-#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_stream_abort_info.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
#include "third_party/blink/renderer/core/streams/writable_stream.h"
#include "third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/webtransport/web_transport_stream.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -234,38 +236,20 @@ ScriptPromise OutgoingStream::SinkWrite(ScriptState* script_state,
DCHECK(!write_promise_resolver_);
DCHECK_EQ(0u, offset_);
- auto* isolate = script_state->GetIsolate();
-
- ArrayBufferOrArrayBufferView buffer_source;
- V8ArrayBufferOrArrayBufferView::ToImpl(
- isolate, chunk.V8Value(), buffer_source,
- UnionTypeConversionMode::kNotNullable, exception_state);
+ auto* buffer_source = V8BufferSource::Create(
+ script_state_->GetIsolate(), chunk.V8Value(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
-
- DCHECK(!buffer_source.IsNull());
-
- // |data| will not be valid when this function returns.
- base::span<const uint8_t> data;
- if (buffer_source.IsArrayBuffer()) {
- const auto* array_buffer = buffer_source.GetAsArrayBuffer();
- data = base::span<const uint8_t>(
- static_cast<const uint8_t*>(array_buffer->Data()),
- array_buffer->ByteLength());
- } else {
- DCHECK(buffer_source.IsArrayBufferView());
- const auto* array_buffer_view = buffer_source.GetAsArrayBufferView().Get();
- data = base::span<const uint8_t>(
- static_cast<const uint8_t*>(array_buffer_view->BaseAddress()),
- array_buffer_view->byteLength());
- }
+ DCHECK(buffer_source);
if (!data_pipe_) {
return ScriptPromise::Reject(script_state,
CreateAbortException(IsLocalAbort(false)));
}
- return WriteOrCacheData(script_state, data);
+ DOMArrayPiece array_piece(buffer_source);
+ return WriteOrCacheData(script_state,
+ {array_piece.Bytes(), array_piece.ByteLength()});
}
// Attempt to write |data|. Cache anything that could not be written
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.h b/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.h
index ec71cd30c1d..2adbde2cbed 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.h
+++ b/chromium/third_party/blink/renderer/modules/webtransport/outgoing_stream.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_OUTGOING_STREAM_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_OUTGOING_STREAM_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include "base/containers/span.h"
#include "base/types/strong_alias.h"
@@ -17,10 +17,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
-
-namespace v8 {
-class Isolate;
-}
+#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.cc b/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.cc
index 169034b1507..41a210f22d8 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.cc
@@ -40,7 +40,7 @@ void ReceiveStream::ContextDestroyed() {
void ReceiveStream::Trace(Visitor* visitor) const {
visitor->Trace(incoming_stream_);
visitor->Trace(web_transport_);
- ScriptWrappable::Trace(visitor);
+ ReadableStream::Trace(visitor);
WebTransportStream::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.h b/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.h
index 2413740fe4c..1f2e9d7e1bf 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.h
+++ b/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "mojo/public/cpp/system/data_pipe.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webtransport/incoming_stream.h"
#include "third_party/blink/renderer/modules/webtransport/web_transport_stream.h"
@@ -16,13 +17,14 @@
namespace blink {
+class ExceptionState;
class ScriptState;
class WebTransport;
// Implementation of ReceiveStream from the standard:
// https://wicg.github.io/web-transport/#receive-stream.
-class MODULES_EXPORT ReceiveStream final : public ScriptWrappable,
+class MODULES_EXPORT ReceiveStream final : public ReadableStream,
public WebTransportStream {
DEFINE_WRAPPERTYPEINFO();
@@ -34,11 +36,13 @@ class MODULES_EXPORT ReceiveStream final : public ScriptWrappable,
uint32_t stream_id,
mojo::ScopedDataPipeConsumerHandle);
- void Init() { incoming_stream_->Init(); }
+ void Init(ExceptionState& exception_state) {
+ incoming_stream_->InitWithExistingReadableStream(this, exception_state);
+ }
// Implementation of receive_stream.idl. As noted in the IDL file, these
// properties are implemented on IncomingStream in the standard.
- ReadableStream* readable() const { return incoming_stream_->Readable(); }
+ ReceiveStream* readable() { return this; }
ScriptPromise readingAborted() const {
return incoming_stream_->ReadingAborted();
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.idl b/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.idl
index d37953cae03..1b22e70b1f1 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.idl
+++ b/chromium/third_party/blink/renderer/modules/webtransport/receive_stream.idl
@@ -6,11 +6,10 @@
[ Exposed=(Window,Worker),
RuntimeEnabled=WebTransport ]
-interface ReceiveStream {
- // IncomingStream interface. In the standard this is a mixin, but we can't use
- // a mixin in the implementation because BidirectionalStream would end up
- // inheriting from two mixins, causing diamond inheritance.
- readonly attribute ReadableStream readable;
+interface ReceiveStream : ReadableStream {
+ // Deprecated attributes for backwards-compatibility.
+ // TODO(ricea): Remove these when the origin trial ends.
+ readonly attribute ReceiveStream readable;
readonly attribute Promise<StreamAbortInfo> readingAborted;
void abortReading(optional StreamAbortInfo abortInfo = {});
};
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/test_utils.cc b/chromium/third_party/blink/renderer/modules/webtransport/test_utils.cc
index c966d0f1d49..5d06dcdc363 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/test_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/test_utils.cc
@@ -6,12 +6,19 @@
#include "base/check.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_transport_options.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_generic_reader.h"
+#include "third_party/blink/renderer/modules/webtransport/web_transport.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -55,4 +62,55 @@ v8::Local<v8::Value> ReadValueFromStream(const V8TestingScope& scope,
return v8value;
}
+TestWebTransportCreator::TestWebTransportCreator() = default;
+
+void TestWebTransportCreator::Init(ScriptState* script_state,
+ CreateStubCallback create_stub) {
+ browser_interface_broker_ =
+ &ExecutionContext::From(script_state)->GetBrowserInterfaceBroker();
+ create_stub_ = std::move(create_stub);
+ browser_interface_broker_->SetBinderForTesting(
+ mojom::blink::WebTransportConnector::Name_,
+ WTF::BindRepeating(&TestWebTransportCreator::BindConnector,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_transport_ = WebTransport::Create(
+ script_state, "https://example.com/",
+ MakeGarbageCollected<WebTransportOptions>(), ASSERT_NO_EXCEPTION);
+
+ test::RunPendingTasks();
+}
+
+TestWebTransportCreator::~TestWebTransportCreator() {
+ browser_interface_broker_->SetBinderForTesting(
+ mojom::blink::WebTransportConnector::Name_, {});
+}
+
+// Implementation of mojom::blink::WebTransportConnector.
+void TestWebTransportCreator::Connect(
+ const KURL&,
+ Vector<network::mojom::blink::WebTransportCertificateFingerprintPtr>,
+ mojo::PendingRemote<network::mojom::blink::WebTransportHandshakeClient>
+ pending_handshake_client) {
+ mojo::Remote<network::mojom::blink::WebTransportHandshakeClient>
+ handshake_client(std::move(pending_handshake_client));
+
+ mojo::PendingRemote<network::mojom::blink::WebTransport>
+ web_transport_to_pass;
+
+ create_stub_.Run(web_transport_to_pass);
+
+ mojo::PendingRemote<network::mojom::blink::WebTransportClient> client_remote;
+ handshake_client->OnConnectionEstablished(
+ std::move(web_transport_to_pass),
+ client_remote.InitWithNewPipeAndPassReceiver());
+ client_remote_.Bind(std::move(client_remote));
+}
+
+void TestWebTransportCreator::BindConnector(
+ mojo::ScopedMessagePipeHandle handle) {
+ connector_receiver_.Bind(
+ mojo::PendingReceiver<mojom::blink::WebTransportConnector>(
+ std::move(handle)));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/test_utils.h b/chromium/third_party/blink/renderer/modules/webtransport/test_utils.h
index 748550825ca..2972a570ea2 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/test_utils.h
+++ b/chromium/third_party/blink/renderer/modules/webtransport/test_utils.h
@@ -8,13 +8,27 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_TEST_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_TEST_UTILS_H_
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "services/network/public/mojom/web_transport.mojom-blink.h"
+#include "third_party/blink/public/mojom/webtransport/web_transport_connector.mojom-blink.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8.h"
namespace blink {
-class V8TestingScope;
+class BrowserInterfaceBrokerProxy;
+class KURL;
class ReadableStream;
+class ScriptState;
+class V8TestingScope;
+class WebTransport;
// Creates a mojo data pipe with the normal options for WebTransportTests.
// Returns true for success. Returns false and causes a test failure
@@ -28,6 +42,48 @@ bool CreateDataPipeForWebTransportTests(
v8::Local<v8::Value> ReadValueFromStream(const V8TestingScope& scope,
ReadableStream* stream);
+// Helps create a WebTransport with a fake remote for use in tests. See for
+// example ScopedWebTransport in bidirectional_stream_test.cc for how to use it.
+class TestWebTransportCreator final
+ : public mojom::blink::WebTransportConnector {
+ DISALLOW_NEW();
+
+ public:
+ using CreateStubCallback = base::RepeatingCallback<void(
+ mojo::PendingRemote<network::mojom::blink::WebTransport>&)>;
+
+ TestWebTransportCreator();
+ ~TestWebTransportCreator() override;
+
+ // The |create_stub| callback should initialize a subclass of
+ // network::mojom::blink::WebTransport and keep it alive for as long as the
+ // WebTransport object should remain functional.
+ void Init(ScriptState* script_state, CreateStubCallback create_stub);
+
+ WebTransport* GetWebTransport() const { return web_transport_; }
+
+ // Implementation of mojom::blink::WebTransportConnector.
+ void Connect(
+ const KURL&,
+ Vector<network::mojom::blink::WebTransportCertificateFingerprintPtr>,
+ mojo::PendingRemote<network::mojom::blink::WebTransportHandshakeClient>)
+ override;
+
+ private:
+ void BindConnector(mojo::ScopedMessagePipeHandle handle);
+
+ // |browser_interface_broker_| is cached here because we need to use it in the
+ // destructor. This means ScopedWebTransporHelper must always be destroyed
+ // before the ExecutionContext that owns the BrowserInterfaceBrokerProxy.
+ const BrowserInterfaceBrokerProxy* browser_interface_broker_ = nullptr;
+ Persistent<WebTransport> web_transport_;
+ mojo::Remote<network::mojom::blink::WebTransportClient> client_remote_;
+ mojo::Receiver<mojom::blink::WebTransportConnector> connector_receiver_{this};
+ CreateStubCallback create_stub_;
+
+ base::WeakPtrFactory<TestWebTransportCreator> weak_ptr_factory_{this};
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_TEST_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/web_transport.cc b/chromium/third_party/blink/renderer/modules/webtransport/web_transport.cc
index 6c83f914b52..4813aa99e0e 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/web_transport.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/web_transport.cc
@@ -9,13 +9,14 @@
#include <utility>
#include "base/numerics/safe_conversions.h"
+#include "base/time/time.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/mojom/webtransport/web_transport_connector.mojom-blink.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_dtls_fingerprint.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_web_transport_close_info.h"
@@ -23,6 +24,7 @@
#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/web_feature.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/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
@@ -41,6 +43,7 @@
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
+#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -50,6 +53,11 @@ namespace blink {
namespace {
+// The incoming max age to to be used when datagrams.incomingMaxAge is set to
+// null.
+constexpr base::TimeDelta kDefaultIncomingMaxAge =
+ base::TimeDelta::FromSeconds(60);
+
// Creates a mojo DataPipe with the options we use for our stream data pipes. On
// success, returns true. On failure, throws an exception and returns false.
bool CreateStreamDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
@@ -78,8 +86,9 @@ bool CreateStreamDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
// Sends a datagram on write().
class WebTransport::DatagramUnderlyingSink final : public UnderlyingSinkBase {
public:
- DatagramUnderlyingSink(WebTransport* web_transport, int high_water_mark)
- : web_transport_(web_transport), high_water_mark_(high_water_mark) {}
+ DatagramUnderlyingSink(WebTransport* web_transport,
+ DatagramDuplexStream* datagrams)
+ : web_transport_(web_transport), datagrams_(datagrams) {}
ScriptPromise start(ScriptState* script_state,
WritableStreamDefaultController*,
@@ -92,22 +101,23 @@ class WebTransport::DatagramUnderlyingSink final : public UnderlyingSinkBase {
WritableStreamDefaultController*,
ExceptionState& exception_state) override {
auto v8chunk = chunk.V8Value();
+ auto* isolate = script_state->GetIsolate();
+
if (v8chunk->IsArrayBuffer()) {
- DOMArrayBuffer* data =
- V8ArrayBuffer::ToImpl(v8chunk.As<v8::ArrayBuffer>());
+ DOMArrayBuffer* data = NativeValueTraits<DOMArrayBuffer>::NativeValue(
+ isolate, v8chunk, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
return SendDatagram(
{static_cast<const uint8_t*>(data->Data()), data->ByteLength()});
}
- auto* isolate = script_state->GetIsolate();
if (v8chunk->IsArrayBufferView()) {
NotShared<DOMArrayBufferView> data =
- ToNotShared<NotShared<DOMArrayBufferView>>(isolate, v8chunk,
- exception_state);
- if (exception_state.HadException()) {
+ NativeValueTraits<NotShared<DOMArrayBufferView>>::NativeValue(
+ isolate, v8chunk, exception_state);
+ if (exception_state.HadException())
return ScriptPromise();
- }
-
return SendDatagram({static_cast<const uint8_t*>(data->buffer()->Data()) +
data->byteOffset(),
data->byteLength()});
@@ -132,6 +142,7 @@ class WebTransport::DatagramUnderlyingSink final : public UnderlyingSinkBase {
void Trace(Visitor* visitor) const override {
visitor->Trace(web_transport_);
+ visitor->Trace(datagrams_);
visitor->Trace(pending_datagrams_);
UnderlyingSinkBase::Trace(visitor);
}
@@ -152,7 +163,9 @@ class WebTransport::DatagramUnderlyingSink final : public UnderlyingSinkBase {
web_transport_->transport_remote_->SendDatagram(
data, WTF::Bind(&DatagramUnderlyingSink::OnDatagramProcessed,
WrapWeakPersistent(this)));
- if (pending_datagrams_.size() < static_cast<wtf_size_t>(high_water_mark_)) {
+ int high_water_mark = datagrams_->outgoingHighWaterMark();
+ DCHECK_GT(high_water_mark, 0);
+ if (pending_datagrams_.size() < static_cast<wtf_size_t>(high_water_mark)) {
// In this case we pretend that the datagram is processed immediately, to
// get more requests from the stream.
return ScriptPromise::CastUndefined(web_transport_->script_state_);
@@ -170,45 +183,268 @@ class WebTransport::DatagramUnderlyingSink final : public UnderlyingSinkBase {
}
Member<WebTransport> web_transport_;
- const int high_water_mark_;
+ const Member<DatagramDuplexStream> datagrams_;
HeapDeque<Member<ScriptPromiseResolver>> pending_datagrams_;
};
-// Captures a pointer to the ReadableStreamDefaultControllerWithScriptScope in
-// the Start() method, and then does nothing else. Queuing of received datagrams
-// is done inside the implementation of WebTransport.
+// Passes incoming datagrams to the datagrams.readable stream. It maintains its
+// own internal queue of datagrams so that stale datagrams won't remain in
+// ReadableStream's queue.
class WebTransport::DatagramUnderlyingSource final
: public UnderlyingSourceBase {
public:
DatagramUnderlyingSource(ScriptState* script_state,
- WebTransport* web_transport)
- : UnderlyingSourceBase(script_state), web_transport_(web_transport) {}
+ DatagramDuplexStream* datagram_duplex_stream)
+ : UnderlyingSourceBase(script_state),
+ datagram_duplex_stream_(datagram_duplex_stream),
+ expiry_timer_(ExecutionContext::From(script_state)
+ ->GetTaskRunner(TaskType::kNetworking),
+ this,
+ &DatagramUnderlyingSource::ExpiryTimerFired) {}
+
+ // Implementation of UnderlyingSourceBase.
+ ScriptPromise pull(ScriptState* script_state) override {
+ DVLOG(1) << "DatagramUnderlyingSource::pull()";
+ // If high water mark is reset to 0 and then read() is called, it should
+ // block waiting for a new datagram. So we may need to discard datagrams
+ // here.
+ DiscardExcessDatagrams();
+
+ MaybeExpireDatagrams();
+
+ if (queue_.empty()) {
+ if (close_when_queue_empty_) {
+ Controller()->Close();
+ return ScriptPromise::CastUndefined(script_state);
+ }
+
+ DCHECK(!waiting_for_datagrams_);
+ waiting_for_datagrams_ = true;
+ return ScriptPromise::CastUndefined(script_state);
+ }
+
+ const QueueEntry* entry = queue_.front();
+ queue_.pop_front();
+
+ if (queue_.empty()) {
+ expiry_timer_.Stop();
+ }
+
+ // This has to go after any mutations as it may run JavaScript, leading to
+ // re-entry.
+ Controller()->Enqueue(entry->datagram);
+
+ // JavaScript could have called some other method at this point.
+ // However, this is safe, because |close_when_queue_empty_| only ever
+ // changes from false to true, and once it is true no more datagrams will
+ // be added to |queue_|.
+ if (close_when_queue_empty_ && queue_.empty()) {
+ Controller()->Close();
+ }
- ScriptPromise Start(ScriptState* script_state) override {
- web_transport_->received_datagrams_controller_ = Controller();
return ScriptPromise::CastUndefined(script_state);
}
- ScriptPromise pull(ScriptState* script_state) override {
+ ScriptPromise Cancel(ScriptState* script_state, ScriptValue) override {
+ DVLOG(1) << "DatagramUnderlyingSource::Cancel()";
+ waiting_for_datagrams_ = false;
+ canceled_ = true;
+ DiscardQueue();
+ Controller()->NoteHasBeenCanceled();
+
return ScriptPromise::CastUndefined(script_state);
}
- ScriptPromise Cancel(ScriptState* script_state, ScriptValue reason) override {
- // Stop Enqueue() from being called again.
+ // Interface for use by WebTransport.
+ void Close() {
+ DVLOG(1) << "DatagramUnderlyingSource::Close()";
- web_transport_->received_datagrams_controller_->NoteHasBeenCanceled();
- web_transport_->received_datagrams_controller_ = nullptr;
- web_transport_ = nullptr;
- return ScriptPromise::CastUndefined(script_state);
+ if (queue_.empty()) {
+ Controller()->Close();
+ } else {
+ close_when_queue_empty_ = true;
+ }
+ }
+
+ void Error(v8::Local<v8::Value> error) {
+ DVLOG(1) << "DatagramUnderlyingSource::Error()";
+
+ waiting_for_datagrams_ = false;
+ DiscardQueue();
+ Controller()->Error(error);
+ }
+
+ void OnDatagramReceived(base::span<const uint8_t> data) {
+ DVLOG(1) << "DatagramUnderlyingSource::OnDatagramReceived() size="
+ << data.size();
+
+ // We should not receive any datagrams after Close() was called.
+ DCHECK(!close_when_queue_empty_);
+
+ if (canceled_) {
+ return;
+ }
+
+ auto* datagram = DOMUint8Array::Create(data.data(), data.size());
+
+ // This fast path is expected to be hit frequently. Avoid the queue.
+ if (waiting_for_datagrams_) {
+ DCHECK(queue_.empty());
+ waiting_for_datagrams_ = false;
+ // This may run JavaScript, so it has to be called immediately before
+ // returning to avoid confusion caused by re-entrant usage.
+ Controller()->Enqueue(datagram);
+ return;
+ }
+
+ DiscardExcessDatagrams();
+
+ auto high_water_mark = HighWaterMark();
+
+ // A high water mark of 0 has the semantics that all datagrams are discarded
+ // unless there is read pending. This might be useful to someone, so support
+ // it.
+ if (high_water_mark == 0) {
+ DCHECK(queue_.empty());
+ return;
+ }
+
+ if (queue_.size() == high_water_mark) {
+ // Need to get rid of an entry for the new one to replace.
+ queue_.pop_front();
+ }
+
+ auto now = base::TimeTicks::Now();
+ queue_.push_back(MakeGarbageCollected<QueueEntry>(datagram, now));
+ MaybeExpireDatagrams(now);
}
void Trace(Visitor* visitor) const override {
- visitor->Trace(web_transport_);
+ visitor->Trace(queue_);
+ visitor->Trace(datagram_duplex_stream_);
+ visitor->Trace(expiry_timer_);
UnderlyingSourceBase::Trace(visitor);
}
private:
- Member<WebTransport> web_transport_;
+ struct QueueEntry : GarbageCollected<QueueEntry> {
+ QueueEntry(DOMUint8Array* datagram, base::TimeTicks received_time)
+ : datagram(datagram), received_time(received_time) {}
+
+ const Member<DOMUint8Array> datagram;
+ const base::TimeTicks received_time;
+
+ void Trace(Visitor* visitor) const { visitor->Trace(datagram); }
+ };
+
+ void DiscardExcessDatagrams() {
+ DVLOG(1)
+ << "DatagramUnderlyingSource::DiscardExcessDatagrams() queue_.size="
+ << queue_.size();
+
+ wtf_size_t high_water_mark = HighWaterMark();
+
+ // The high water mark may have been set to a lower value, so the size can
+ // be greater.
+ while (queue_.size() > high_water_mark) {
+ // TODO(ricea): Maybe free the memory associated with the array
+ // buffer?
+ queue_.pop_front();
+ }
+
+ if (queue_.empty()) {
+ DVLOG(1) << "DiscardExcessDatagrams: queue size now zero";
+ expiry_timer_.Stop();
+ }
+ }
+
+ void DiscardQueue() {
+ queue_.clear();
+ expiry_timer_.Stop();
+ }
+
+ void ExpiryTimerFired(TimerBase*) {
+ DVLOG(1) << "DatagramUnderlyingSource::ExpiryTimerFired()";
+
+ MaybeExpireDatagrams();
+ }
+
+ void MaybeExpireDatagrams() { MaybeExpireDatagrams(base::TimeTicks::Now()); }
+
+ void MaybeExpireDatagrams(base::TimeTicks now) {
+ DVLOG(1) << "DatagramUnderlyingSource::MaybeExpireDatagrams() now=" << now
+ << " queue_.size=" << queue_.size();
+
+ absl::optional<double> optional_max_age =
+ datagram_duplex_stream_->incomingMaxAge();
+ bool max_age_is_default = false;
+ base::TimeDelta max_age;
+ if (optional_max_age.has_value()) {
+ max_age = base::TimeDelta::FromMillisecondsD(optional_max_age.value());
+ } else {
+ max_age_is_default = true;
+ max_age = kDefaultIncomingMaxAge;
+ }
+
+ DCHECK_GT(now, base::TimeTicks());
+
+ // base::TimeTicks can take negative values, so this subtraction won't
+ // underflow even if MaxAge() is huge.
+ base::TimeTicks older_than = now - max_age;
+
+ bool discarded = false;
+ while (!queue_.empty() && queue_.front()->received_time < older_than) {
+ discarded = true;
+ queue_.pop_front();
+ }
+
+ if (discarded && max_age_is_default) {
+ if (auto* execution_context = GetExecutionContext()) {
+ execution_context->AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kNetwork,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "Incoming datagram was discarded by WebTransport due to "
+ "reaching default incomingMaxAge"),
+ true);
+ }
+ }
+
+ if (queue_.empty()) {
+ DVLOG(1) << "MaybeExpireDatagrams queue is now empty";
+ expiry_timer_.Stop();
+ return;
+ }
+
+ base::TimeDelta age = now - queue_.front()->received_time;
+ DCHECK_GE(max_age, age);
+ base::TimeDelta time_until_next_expiry = max_age - age;
+
+ // To reduce the number of wakeups, don't try to expire any more datagrams
+ // for at least a second.
+ if (time_until_next_expiry < base::TimeDelta::FromSeconds(1)) {
+ time_until_next_expiry = base::TimeDelta::FromSeconds(1);
+ }
+
+ if (expiry_timer_.IsActive() &&
+ expiry_timer_.NextFireInterval() <= time_until_next_expiry) {
+ return;
+ }
+
+ expiry_timer_.StartOneShot(time_until_next_expiry, FROM_HERE);
+ }
+
+ wtf_size_t HighWaterMark() const {
+ return base::checked_cast<wtf_size_t>(
+ datagram_duplex_stream_->incomingHighWaterMark());
+ }
+
+ HeapDeque<Member<const QueueEntry>> queue_;
+ const Member<DatagramDuplexStream> datagram_duplex_stream_;
+ HeapTaskRunnerTimer<DatagramUnderlyingSource> expiry_timer_;
+ bool waiting_for_datagrams_ = false;
+ bool canceled_ = false;
+ bool close_when_queue_empty_ = false;
};
class WebTransport::StreamVendingUnderlyingSource final
@@ -307,7 +543,19 @@ class WebTransport::ReceiveStreamVendor final
ScriptState::Scope scope(script_state_);
auto* receive_stream = MakeGarbageCollected<ReceiveStream>(
script_state_, web_transport_, stream_id, std::move(readable));
- receive_stream->Init();
+ auto* isolate = script_state_->GetIsolate();
+ ExceptionState exception_state(
+ isolate, ExceptionState::kConstructionContext, "ReceiveStream");
+ v8::MicrotasksScope microtasks_scope(
+ isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ receive_stream->Init(exception_state);
+
+ if (exception_state.HadException()) {
+ // Abandon the stream.
+ exception_state.ClearException();
+ return;
+ }
+
// 0xfffffffe and 0xffffffff are reserved values in stream_map_.
CHECK_LT(stream_id, 0xfffffffe);
web_transport_->stream_map_.insert(stream_id, receive_stream);
@@ -396,6 +644,7 @@ WebTransport::WebTransport(ScriptState* script_state,
: ExecutionContextLifecycleObserver(context),
script_state_(script_state),
url_(NullURL(), url),
+ connector_(context),
transport_remote_(context),
handshake_client_receiver_(this, context),
client_receiver_(this, context),
@@ -513,10 +762,7 @@ void WebTransport::close(const WebTransportCloseInfo* close_info) {
}
cleanly_closed_ = true;
- if (received_datagrams_controller_) {
- received_datagrams_controller_->Close();
- received_datagrams_controller_ = nullptr;
- }
+ datagram_underlying_source_->Close();
received_streams_underlying_source_->Close();
received_bidirectional_streams_underlying_source_->Close();
@@ -538,6 +784,7 @@ void WebTransport::close(const WebTransportCloseInfo* close_info) {
}
void WebTransport::setDatagramWritableQueueExpirationDuration(double duration) {
+ // TODO(ricea): Will this crash if we are not connected yet?
transport_remote_->SetOutgoingDatagramExpirationDuration(
base::TimeDelta::FromMillisecondsD(duration));
}
@@ -547,6 +794,7 @@ void WebTransport::OnConnectionEstablished(
mojo::PendingReceiver<network::mojom::blink::WebTransportClient>
client_receiver) {
DVLOG(1) << "WebTransport::OnConnectionEstablished() this=" << this;
+ connector_.reset();
handshake_client_receiver_.reset();
probe::WebTransportConnectionEstablished(GetExecutionContext(),
@@ -586,34 +834,20 @@ void WebTransport::OnHandshakeFailed(
}
void WebTransport::OnDatagramReceived(base::span<const uint8_t> data) {
- ReadableStreamDefaultControllerWithScriptScope* controller =
- received_datagrams_controller_;
-
- // Discard datagrams if the readable has been cancelled.
- if (!controller)
- return;
-
- // The spec says we should discard older datagrams first, but that's not what
- // ReadableStream does, so instead we might need to maintain a separate queue
- // with the desired semantics. But for now we'll just use a small queue in
- // ReadableStream.
- // TODO(ricea): Figure out how to get nice semantics here.
-
- if (controller->DesiredSize() > 0) {
- auto* array = DOMUint8Array::Create(
- data.data(), base::checked_cast<wtf_size_t>(data.size()));
- controller->Enqueue(array);
- }
+ datagram_underlying_source_->OnDatagramReceived(data);
}
void WebTransport::OnIncomingStreamClosed(uint32_t stream_id,
bool fin_received) {
DVLOG(1) << "WebTransport::OnIncomingStreamClosed(" << stream_id << ", "
<< fin_received << ") this=" << this;
- WebTransportStream* stream = stream_map_.at(stream_id);
- // |stream| can be unset because of races between different ways of closing
- // |bidirectional streams.
- if (stream) {
+ auto it = stream_map_.find(stream_id);
+
+ // The stream may have already been removed from the map because of races
+ // between different ways of closing bidirectional streams.
+ if (it != stream_map_.end()) {
+ WebTransportStream* stream = it->value;
+ DCHECK(stream);
stream->OnIncomingStreamClosed(fin_received);
}
}
@@ -649,10 +883,11 @@ void WebTransport::ForgetStream(uint32_t stream_id) {
void WebTransport::Trace(Visitor* visitor) const {
visitor->Trace(datagrams_);
visitor->Trace(received_datagrams_);
- visitor->Trace(received_datagrams_controller_);
+ visitor->Trace(datagram_underlying_source_);
visitor->Trace(outgoing_datagrams_);
visitor->Trace(script_state_);
visitor->Trace(create_stream_resolvers_);
+ visitor->Trace(connector_);
visitor->Trace(transport_remote_);
visitor->Trace(handshake_client_receiver_);
visitor->Trace(client_receiver_);
@@ -704,15 +939,19 @@ void WebTransport::Init(const String& url,
auto* execution_context = GetExecutionContext();
+ bool had_csp_failure = false;
if (!execution_context->GetContentSecurityPolicyForCurrentWorld()
->AllowConnectToSource(url_, url_, RedirectStatus::kNoRedirect)) {
- // TODO(ricea): This error should probably be asynchronous like it is for
- // WebSockets and fetch.
- exception_state.ThrowSecurityError(
+ auto dom_exception = V8ThrowDOMException::CreateOrEmpty(
+ script_state_->GetIsolate(), DOMExceptionCode::kSecurityError,
"Failed to connect to '" + url_.ElidedString() + "'",
"Refused to connect to '" + url_.ElidedString() +
"' because it violates the document's Content Security Policy");
- return;
+
+ ready_resolver_->Reject(dom_exception);
+ closed_resolver_->Reject(dom_exception);
+
+ had_csp_failure = true;
}
Vector<network::mojom::blink::WebTransportCertificateFingerprintPtr>
@@ -725,41 +964,44 @@ void WebTransport::Init(const String& url,
}
}
- // TODO(ricea): Register SchedulingPolicy so that we don't get throttled and
- // to disable bfcache. Must be done before shipping.
+ if (auto* scheduler = execution_context->GetScheduler()) {
+ feature_handle_for_scheduler_ = scheduler->RegisterFeature(
+ SchedulingPolicy::Feature::kWebTransport,
+ SchedulingPolicy{SchedulingPolicy::DisableAggressiveThrottling(),
+ SchedulingPolicy::DisableBackForwardCache()});
+ }
// TODO(ricea): Check the SubresourceFilter and fail asynchronously if
// disallowed. Must be done before shipping.
- mojo::Remote<mojom::blink::WebTransportConnector> connector;
- execution_context->GetBrowserInterfaceBroker().GetInterface(
- connector.BindNewPipeAndPassReceiver(
- execution_context->GetTaskRunner(TaskType::kNetworking)));
+ if (!had_csp_failure) {
+ execution_context->GetBrowserInterfaceBroker().GetInterface(
+ connector_.BindNewPipeAndPassReceiver(
+ execution_context->GetTaskRunner(TaskType::kNetworking)));
- connector->Connect(
- url_, std::move(fingerprints),
- handshake_client_receiver_.BindNewPipeAndPassRemote(
- execution_context->GetTaskRunner(TaskType::kNetworking)));
+ connector_->Connect(
+ url_, std::move(fingerprints),
+ handshake_client_receiver_.BindNewPipeAndPassRemote(
+ execution_context->GetTaskRunner(TaskType::kNetworking)));
- handshake_client_receiver_.set_disconnect_handler(
- WTF::Bind(&WebTransport::OnConnectionError, WrapWeakPersistent(this)));
+ handshake_client_receiver_.set_disconnect_handler(
+ WTF::Bind(&WebTransport::OnConnectionError, WrapWeakPersistent(this)));
+ }
probe::WebTransportCreated(execution_context, inspector_transport_id_, url_);
- datagrams_ = MakeGarbageCollected<DatagramDuplexStream>(this);
-
- // The choice of 1 for the ReadableStream means that it will queue one
- // datagram even when read() is not being called. Unfortunately, that datagram
- // may become arbitrarily stale.
- // TODO(ricea): Consider having a datagram queue inside this class instead.
- received_datagrams_ = ReadableStream::CreateWithCountQueueingStrategy(
- script_state_,
- MakeGarbageCollected<DatagramUnderlyingSource>(script_state_, this), 1);
int outgoing_datagrams_high_water_mark = 1;
if (options.hasDatagramWritableHighWaterMark()) {
outgoing_datagrams_high_water_mark =
options.datagramWritableHighWaterMark();
}
+ datagrams_ = MakeGarbageCollected<DatagramDuplexStream>(
+ this, outgoing_datagrams_high_water_mark);
+
+ datagram_underlying_source_ =
+ MakeGarbageCollected<DatagramUnderlyingSource>(script_state_, datagrams_);
+ received_datagrams_ = ReadableStream::CreateWithCountQueueingStrategy(
+ script_state_, datagram_underlying_source_, 0);
// We create a WritableStream with high water mark 1 and try to mimic the
// given high water mark in the Sink, from two reasons:
@@ -771,9 +1013,7 @@ void WebTransport::Init(const String& url,
// datagram is added to the queue.
outgoing_datagrams_ = WritableStream::CreateWithCountQueueingStrategy(
script_state_,
- MakeGarbageCollected<DatagramUnderlyingSink>(
- this, outgoing_datagrams_high_water_mark),
- 1);
+ MakeGarbageCollected<DatagramUnderlyingSink>(this, datagrams_), 1);
received_streams_underlying_source_ =
StreamVendingUnderlyingSource::CreateWithVendor<ReceiveStreamVendor>(
@@ -808,9 +1048,12 @@ void WebTransport::Dispose() {
DVLOG(1) << "WebTransport::Dispose() this=" << this;
probe::WebTransportClosed(GetExecutionContext(), inspector_transport_id_);
stream_map_.clear();
+ connector_.reset();
transport_remote_.reset();
handshake_client_receiver_.reset();
client_receiver_.reset();
+ // Make the page back/forward cache-able.
+ feature_handle_for_scheduler_.reset();
}
void WebTransport::OnConnectionError() {
@@ -820,10 +1063,7 @@ void WebTransport::OnConnectionError() {
if (!cleanly_closed_) {
v8::Local<v8::Value> reason = V8ThrowException::CreateTypeError(
script_state_->GetIsolate(), "Connection lost.");
- if (received_datagrams_controller_) {
- received_datagrams_controller_->Error(reason);
- received_datagrams_controller_ = nullptr;
- }
+ datagram_underlying_source_->Error(reason);
received_streams_underlying_source_->Error(reason);
received_bidirectional_streams_underlying_source_->Error(reason);
WritableStreamDefaultController::ErrorIfNeeded(
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/web_transport.h b/chromium/third_party/blink/renderer/modules/webtransport/web_transport.h
index 50e604585c3..c5325bae0fa 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/web_transport.h
+++ b/chromium/third_party/blink/renderer/modules/webtransport/web_transport.h
@@ -13,6 +13,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/web_transport.mojom-blink.h"
+#include "third_party/blink/public/mojom/webtransport/web_transport_connector.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/core/execution_context/execution_context_lifecycle_observer.h"
@@ -22,6 +23,7 @@
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -30,7 +32,6 @@ namespace blink {
class DatagramDuplexStream;
class ExceptionState;
class ReadableStream;
-class ReadableStreamDefaultControllerWithScriptScope;
class ScriptPromise;
class ScriptPromiseResolver;
class ScriptState;
@@ -135,8 +136,7 @@ class MODULES_EXPORT WebTransport final
Member<DatagramDuplexStream> datagrams_;
Member<ReadableStream> received_datagrams_;
- Member<ReadableStreamDefaultControllerWithScriptScope>
- received_datagrams_controller_;
+ Member<DatagramUnderlyingSource> datagram_underlying_source_;
// This corresponds to the [[SentDatagrams]] internal slot in the standard.
Member<WritableStream> outgoing_datagrams_;
@@ -155,6 +155,7 @@ class MODULES_EXPORT WebTransport final
WTF::UnsignedWithZeroKeyHashTraits<uint32_t>>
stream_map_;
+ HeapMojoRemote<mojom::blink::WebTransportConnector> connector_;
HeapMojoRemote<network::mojom::blink::WebTransport> transport_remote_;
HeapMojoReceiver<network::mojom::blink::WebTransportHandshakeClient,
WebTransport>
@@ -180,6 +181,9 @@ class MODULES_EXPORT WebTransport final
received_bidirectional_streams_underlying_source_;
const uint64_t inspector_transport_id_;
+
+ FrameScheduler::SchedulingAffectingFeatureHandle
+ feature_handle_for_scheduler_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/web_transport.idl b/chromium/third_party/blink/renderer/modules/webtransport/web_transport.idl
index 29f8cb5b4c6..2ee5578a1ab 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/web_transport.idl
+++ b/chromium/third_party/blink/renderer/modules/webtransport/web_transport.idl
@@ -17,6 +17,11 @@
createBidirectionalStream();
readonly attribute ReadableStream incomingBidirectionalStreams;
+ readonly attribute DatagramDuplexStream datagrams;
+
+ // datagramWritable and datagramReadable are retained for backwards
+ // compatibility.
+ // TODO(ricea): Remove these before shipping.
readonly attribute WritableStream datagramWritable;
readonly attribute ReadableStream datagramReadable;
diff --git a/chromium/third_party/blink/renderer/modules/webtransport/web_transport_test.cc b/chromium/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
index 67d25b9a7bd..ce6966de2a9 100644
--- a/chromium/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
@@ -17,15 +17,14 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/webtransport/web_transport_connector.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.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"
#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/bindings/core/v8/v8_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_bidirectional_stream.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_receive_stream.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_dtls_fingerprint.h"
@@ -376,7 +375,6 @@ TEST_F(WebTransportTest, FailWithURLFragment) {
TEST_F(WebTransportTest, FailByCSP) {
V8TestingScope scope;
- auto& exception_state = scope.GetExceptionState();
scope.GetExecutionContext()
->GetContentSecurityPolicyForCurrentWorld()
->AddPolicies(ParseContentSecurityPolicies(
@@ -384,13 +382,19 @@ TEST_F(WebTransportTest, FailByCSP) {
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kHTTP,
*(scope.GetExecutionContext()->GetSecurityOrigin())));
- WebTransport::Create(scope.GetScriptState(), String("https://example.com/"),
- EmptyOptions(), exception_state);
- EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(static_cast<int>(DOMExceptionCode::kSecurityError),
- exception_state.Code());
- EXPECT_EQ("Failed to connect to 'https://example.com/'",
- exception_state.Message());
+ auto* web_transport = WebTransport::Create(
+ scope.GetScriptState(), String("https://example.com/"), EmptyOptions(),
+ ASSERT_NO_EXCEPTION);
+ ScriptPromiseTester ready_tester(scope.GetScriptState(),
+ web_transport->ready());
+ ScriptPromiseTester closed_tester(scope.GetScriptState(),
+ web_transport->closed());
+
+ test::RunPendingTasks();
+
+ EXPECT_FALSE(web_transport->HasPendingActivity());
+ EXPECT_TRUE(ready_tester.IsRejected());
+ EXPECT_TRUE(closed_tester.IsRejected());
}
TEST_F(WebTransportTest, PassCSP) {
@@ -398,7 +402,6 @@ TEST_F(WebTransportTest, PassCSP) {
// This doesn't work without the https:// prefix, even thought it should
// according to
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src.
- auto& exception_state = scope.GetExceptionState();
scope.GetExecutionContext()
->GetContentSecurityPolicyForCurrentWorld()
->AddPolicies(ParseContentSecurityPolicies(
@@ -406,9 +409,15 @@ TEST_F(WebTransportTest, PassCSP) {
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kHTTP,
*(scope.GetExecutionContext()->GetSecurityOrigin())));
- WebTransport::Create(scope.GetScriptState(), String("https://example.com/"),
- EmptyOptions(), exception_state);
- EXPECT_FALSE(exception_state.HadException());
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com/");
+ ScriptPromiseTester ready_tester(scope.GetScriptState(),
+ web_transport->ready());
+
+ EXPECT_TRUE(web_transport->HasPendingActivity());
+
+ ready_tester.WaitUntilSettled();
+ EXPECT_TRUE(ready_tester.IsFulfilled());
}
TEST_F(WebTransportTest, SendConnect) {
@@ -550,11 +559,13 @@ TEST_F(WebTransportTest, GarbageCollection) {
WeakPersistent<WebTransport> web_transport;
+ auto* isolate = scope.GetIsolate();
+
{
// The streams created when creating a WebTransport create some v8 handles.
// To ensure these are collected, we need to create a handle scope. This is
// not a problem for garbage collection in normal operation.
- v8::HandleScope handle_scope(scope.GetIsolate());
+ v8::HandleScope handle_scope(isolate);
web_transport = CreateAndConnectSuccessfully(scope, "https://example.com");
}
@@ -564,7 +575,10 @@ TEST_F(WebTransportTest, GarbageCollection) {
EXPECT_TRUE(web_transport);
- web_transport->close(nullptr);
+ {
+ v8::HandleScope handle_scope(isolate);
+ web_transport->close(nullptr);
+ }
test::RunPendingTasks();
@@ -749,18 +763,32 @@ Vector<uint8_t> GetValueAsVector(ScriptState* script_state,
}
EXPECT_FALSE(done);
- auto* array =
- V8Uint8Array::ToImplWithTypeCheck(script_state->GetIsolate(), value);
+ DummyExceptionStateForTesting exception_state;
+ auto array = NativeValueTraits<NotShared<DOMUint8Array>>::NativeValue(
+ script_state->GetIsolate(), value, exception_state);
if (!array) {
ADD_FAILURE() << "value was not a Uint8Array";
return {};
}
Vector<uint8_t> result;
- result.Append(array->Data(), array->length());
+ result.Append(array->Data(), base::checked_cast<wtf_size_t>(array->length()));
return result;
}
+bool IsDone(ScriptState* script_state, ScriptValue iterator_result) {
+ bool done = false;
+ v8::Local<v8::Value> value;
+ if (!V8UnpackIteratorResult(script_state,
+ iterator_result.V8Value().As<v8::Object>(), &done)
+ .ToLocal(&value)) {
+ ADD_FAILURE() << "unable to unpack iterator_result";
+ return false;
+ }
+
+ return done;
+}
+
TEST_F(WebTransportTest, ReceiveDatagramBeforeRead) {
V8TestingScope scope;
auto* web_transport =
@@ -803,18 +831,121 @@ TEST_F(WebTransportTest, ReceiveDatagramDuringRead) {
EXPECT_THAT(GetValueAsVector(script_state, tester.Value()), ElementsAre('A'));
}
-// This test documents the current behaviour. If you improve the behaviour,
-// change the test!
+TEST_F(WebTransportTest, CancelDatagramReadableWorks) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+ auto* readable = web_transport->datagrams()->readable();
+
+ // This datagram should be discarded.
+ const std::array<uint8_t, 1> chunk1 = {'A'};
+ client_remote_->OnDatagramReceived(chunk1);
+
+ test::RunPendingTasks();
+
+ readable->cancel(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+
+ // This datagram should also be discarded.
+ const std::array<uint8_t, 1> chunk2 = {'B'};
+ client_remote_->OnDatagramReceived(chunk2);
+
+ test::RunPendingTasks();
+}
+
+TEST_F(WebTransportTest, DatagramsStillReadableAfterClose) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+
+ const std::array<uint8_t, 1> chunk1 = {'A'};
+ client_remote_->OnDatagramReceived(chunk1);
+
+ test::RunPendingTasks();
+
+ web_transport->close(nullptr);
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+ ScriptPromise result1 = reader->read(script_state, ASSERT_NO_EXCEPTION);
+ ScriptPromiseTester tester1(script_state, result1);
+ tester1.WaitUntilSettled();
+ EXPECT_TRUE(tester1.IsFulfilled());
+ EXPECT_THAT(GetValueAsVector(script_state, tester1.Value()),
+ ElementsAre('A'));
+
+ ScriptPromise result2 = reader->read(script_state, ASSERT_NO_EXCEPTION);
+ ScriptPromiseTester tester2(script_state, result2);
+ tester2.WaitUntilSettled();
+ EXPECT_TRUE(tester2.IsFulfilled());
+ EXPECT_TRUE(IsDone(script_state, tester2.Value()));
+}
+
+TEST_F(WebTransportTest, ResettingIncomingHighWaterMarkWorksAfterClose) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+
+ const std::array<uint8_t, 1> chunk1 = {'A'};
+ client_remote_->OnDatagramReceived(chunk1);
+
+ test::RunPendingTasks();
+
+ web_transport->close(nullptr);
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+
+ web_transport->datagrams()->setIncomingHighWaterMark(0);
+ ScriptPromise result = reader->read(script_state, ASSERT_NO_EXCEPTION);
+
+ ScriptPromiseTester tester(script_state, result);
+ tester.WaitUntilSettled();
+ EXPECT_TRUE(tester.IsFulfilled());
+ EXPECT_TRUE(IsDone(script_state, tester.Value()));
+}
+
+TEST_F(WebTransportTest, TransportErrorErrorsReadableStream) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+
+ // This datagram should be discarded.
+ const std::array<uint8_t, 1> chunk1 = {'A'};
+ client_remote_->OnDatagramReceived(chunk1);
+
+ test::RunPendingTasks();
+
+ // Cause a transport error.
+ client_remote_.reset();
+
+ test::RunPendingTasks();
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+ ScriptPromise result = reader->read(script_state, ASSERT_NO_EXCEPTION);
+
+ ScriptPromiseTester tester(script_state, result);
+ tester.WaitUntilSettled();
+
+ EXPECT_TRUE(tester.IsRejected());
+}
+
TEST_F(WebTransportTest, DatagramsAreDropped) {
V8TestingScope scope;
auto* web_transport =
CreateAndConnectSuccessfully(scope, "https://example.com");
- // Chunk 'A' gets placed in the readable queue.
+ // Chunk 'A' gets placed in the source queue.
const std::array<uint8_t, 1> chunk1 = {'A'};
client_remote_->OnDatagramReceived(chunk1);
- // Chunk 'B' gets dropped, because there is no space in the readable queue.
+ // Chunk 'B' replaces chunk 'A'.
const std::array<uint8_t, 1> chunk2 = {'B'};
client_remote_->OnDatagramReceived(chunk2);
@@ -835,7 +966,7 @@ TEST_F(WebTransportTest, DatagramsAreDropped) {
EXPECT_FALSE(tester2.IsFulfilled());
EXPECT_THAT(GetValueAsVector(script_state, tester1.Value()),
- ElementsAre('A'));
+ ElementsAre('B'));
// Chunk 'C' fulfills the pending read.
const std::array<uint8_t, 1> chunk3 = {'C'};
@@ -848,6 +979,136 @@ TEST_F(WebTransportTest, DatagramsAreDropped) {
ElementsAre('C'));
}
+TEST_F(WebTransportTest, IncomingHighWaterMarkIsObeyed) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+
+ constexpr int32_t kHighWaterMark = 5;
+ web_transport->datagrams()->setIncomingHighWaterMark(kHighWaterMark);
+
+ for (int i = 0; i < kHighWaterMark + 1; ++i) {
+ const std::array<uint8_t, 1> chunk = {static_cast<uint8_t>('0' + i)};
+ client_remote_->OnDatagramReceived(chunk);
+ }
+
+ // Make sure that the calls have run.
+ test::RunPendingTasks();
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+
+ for (int i = 0; i < kHighWaterMark; ++i) {
+ ScriptPromise result = reader->read(script_state, ASSERT_NO_EXCEPTION);
+
+ ScriptPromiseTester tester(script_state, result);
+ tester.WaitUntilSettled();
+
+ EXPECT_TRUE(tester.IsFulfilled());
+ EXPECT_THAT(GetValueAsVector(script_state, tester.Value()),
+ ElementsAre('0' + i + 1));
+ }
+}
+
+TEST_F(WebTransportTest, ResettingHighWaterMarkClearsQueue) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+
+ constexpr int32_t kHighWaterMark = 5;
+ web_transport->datagrams()->setIncomingHighWaterMark(kHighWaterMark);
+
+ for (int i = 0; i < kHighWaterMark; ++i) {
+ const std::array<uint8_t, 1> chunk = {'A'};
+ client_remote_->OnDatagramReceived(chunk);
+ }
+
+ // Make sure that the calls have run.
+ test::RunPendingTasks();
+
+ web_transport->datagrams()->setIncomingHighWaterMark(0);
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+
+ ScriptPromise result = reader->read(script_state, ASSERT_NO_EXCEPTION);
+
+ ScriptPromiseTester tester(script_state, result);
+
+ // Give the promise an opportunity to settle.
+ test::RunPendingTasks();
+
+ // The queue should be empty, so read() should not have completed.
+ EXPECT_FALSE(tester.IsFulfilled());
+ EXPECT_FALSE(tester.IsRejected());
+}
+
+TEST_F(WebTransportTest, ReadIncomingDatagramWorksWithHighWaterMarkZero) {
+ V8TestingScope scope;
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+ web_transport->datagrams()->setIncomingHighWaterMark(0);
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+ ScriptPromise result = reader->read(script_state, ASSERT_NO_EXCEPTION);
+
+ const std::array<uint8_t, 1> chunk = {'A'};
+ client_remote_->OnDatagramReceived(chunk);
+
+ ScriptPromiseTester tester(script_state, result);
+ tester.WaitUntilSettled();
+ EXPECT_TRUE(tester.IsFulfilled());
+
+ EXPECT_THAT(GetValueAsVector(script_state, tester.Value()), ElementsAre('A'));
+}
+
+// We only do an extremely basic test for incomingMaxAge as overriding
+// base::TimeTicks::Now() doesn't work well in Blink and passing in a mock clock
+// would add a lot of complexity for little benefit.
+TEST_F(WebTransportTest, IncomingMaxAgeIsObeyed) {
+ V8TestingScope scope;
+
+ auto* web_transport =
+ CreateAndConnectSuccessfully(scope, "https://example.com");
+
+ web_transport->datagrams()->setIncomingHighWaterMark(2);
+
+ const std::array<uint8_t, 1> chunk1 = {'A'};
+ client_remote_->OnDatagramReceived(chunk1);
+
+ const std::array<uint8_t, 1> chunk2 = {'B'};
+ client_remote_->OnDatagramReceived(chunk2);
+
+ test::RunPendingTasks();
+
+ constexpr base::TimeDelta kMaxAge = base::TimeDelta::FromMicroseconds(1);
+ web_transport->datagrams()->setIncomingMaxAge(kMaxAge.InMillisecondsF());
+
+ test::RunDelayedTasks(kMaxAge);
+
+ auto* readable = web_transport->datagrams()->readable();
+ auto* script_state = scope.GetScriptState();
+ auto* reader =
+ readable->GetDefaultReaderForTesting(script_state, ASSERT_NO_EXCEPTION);
+
+ // The queue should be empty so the read should not complete.
+ ScriptPromise result = reader->read(script_state, ASSERT_NO_EXCEPTION);
+
+ ScriptPromiseTester tester(script_state, result);
+
+ test::RunPendingTasks();
+
+ EXPECT_FALSE(tester.IsFulfilled());
+ EXPECT_FALSE(tester.IsRejected());
+}
+
bool ValidProducerHandle(const mojo::ScopedDataPipeProducerHandle& handle) {
return handle.is_valid();
}
@@ -929,12 +1190,14 @@ TEST_F(WebTransportTest, SendStreamGarbageCollection) {
WeakPersistent<WebTransport> web_transport;
WeakPersistent<SendStream> send_stream;
+ auto* isolate = scope.GetIsolate();
+
{
// The streams created when creating a WebTransport or SendStream create
// some v8 handles. To ensure these are collected, we need to create a
// handle scope. This is not a problem for garbage collection in normal
// operation.
- v8::HandleScope handle_scope(scope.GetIsolate());
+ v8::HandleScope handle_scope(isolate);
web_transport = CreateAndConnectSuccessfully(scope, "https://example.com");
send_stream = CreateSendStreamSuccessfully(scope, web_transport);
@@ -945,7 +1208,10 @@ TEST_F(WebTransportTest, SendStreamGarbageCollection) {
EXPECT_TRUE(web_transport);
EXPECT_TRUE(send_stream);
- web_transport->close(nullptr);
+ {
+ v8::HandleScope handle_scope(isolate);
+ web_transport->close(nullptr);
+ }
test::RunPendingTasks();
@@ -1218,8 +1484,9 @@ TEST_F(WebTransportTest, CreateReceiveStream) {
ASSERT_TRUE(
V8UnpackIteratorResult(script_state, read_result.As<v8::Object>(), &done)
.ToLocal(&value));
- DOMUint8Array* u8array =
- V8Uint8Array::ToImplWithTypeCheck(scope.GetIsolate(), value);
+ NotShared<DOMUint8Array> u8array =
+ NativeValueTraits<NotShared<DOMUint8Array>>::NativeValue(
+ scope.GetIsolate(), value, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(u8array);
EXPECT_THAT(base::make_span(static_cast<uint8_t*>(u8array->Data()),
u8array->byteLength()),
diff --git a/chromium/third_party/blink/renderer/modules/webusb/idls.gni b/chromium/third_party/blink/renderer/modules/webusb/idls.gni
deleted file mode 100644
index d352c96b068..00000000000
--- a/chromium/third_party/blink/renderer/modules/webusb/idls.gni
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-modules_idl_files = [
- "usb.idl",
- "usb_alternate_interface.idl",
- "usb_configuration.idl",
- "usb_connection_event.idl",
- "usb_device.idl",
- "usb_endpoint.idl",
- "usb_in_transfer_result.idl",
- "usb_interface.idl",
- "usb_isochronous_in_transfer_packet.idl",
- "usb_isochronous_in_transfer_result.idl",
- "usb_isochronous_out_transfer_packet.idl",
- "usb_isochronous_out_transfer_result.idl",
- "usb_out_transfer_result.idl",
-]
-
-modules_dictionary_idl_files = [
- "usb_connection_event_init.idl",
- "usb_control_transfer_parameters.idl",
- "usb_device_filter.idl",
- "usb_device_request_options.idl",
-]
-
-modules_dependency_idl_files = [
- "navigator_usb.idl",
- "worker_navigator_usb.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb.cc b/chromium/third_party/blink/renderer/modules/webusb/usb.cc
index ed5c76849bf..b81aa4c18f5 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb.cc
@@ -200,15 +200,17 @@ void USB::ContextDestroyed() {
}
USBDevice* USB::GetOrCreateDevice(UsbDeviceInfoPtr device_info) {
- USBDevice* device = device_cache_.at(device_info->guid);
- if (!device) {
- String guid = device_info->guid;
- mojo::PendingRemote<UsbDevice> pipe;
- service_->GetDevice(guid, pipe.InitWithNewPipeAndPassReceiver());
- device = MakeGarbageCollected<USBDevice>(
- std::move(device_info), std::move(pipe), GetExecutionContext());
- device_cache_.insert(guid, device);
+ auto it = device_cache_.find(device_info->guid);
+ if (it != device_cache_.end()) {
+ return it->value;
}
+
+ String guid = device_info->guid;
+ mojo::PendingRemote<UsbDevice> pipe;
+ service_->GetDevice(guid, pipe.InitWithNewPipeAndPassReceiver());
+ USBDevice* device = MakeGarbageCollected<USBDevice>(
+ std::move(device_info), std::move(pipe), GetExecutionContext());
+ device_cache_.insert(guid, device);
return device;
}
@@ -248,7 +250,7 @@ void USB::OnDeviceAdded(UsbDeviceInfoPtr device_info) {
void USB::OnDeviceRemoved(UsbDeviceInfoPtr device_info) {
String guid = device_info->guid;
- USBDevice* device = device_cache_.at(guid);
+ USBDevice* device = device_cache_.DeprecatedAtOrEmptyValue(guid);
if (!device) {
device = MakeGarbageCollected<USBDevice>(
std::move(device_info), mojo::NullRemote(), GetExecutionContext());
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 4ebfe502de4..7c9fa09a125 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -96,28 +96,6 @@ String ConvertTransferStatus(const UsbTransferStatus& status) {
}
}
-bool ConvertBufferSource(const DOMArrayPiece& buffer_source,
- Vector<uint8_t>* vector,
- ScriptPromiseResolver* resolver) {
- DCHECK(!buffer_source.IsNull());
-
- if (buffer_source.IsDetached()) {
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kDetachedBuffer));
- return false;
- }
-
- if (buffer_source.ByteLength() > std::numeric_limits<wtf_size_t>::max()) {
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kDataError, kBufferTooBig));
- return false;
- }
-
- vector->Append(buffer_source.Bytes(),
- static_cast<wtf_size_t>(buffer_source.ByteLength()));
- return true;
-}
-
} // namespace
USBDevice::USBDevice(UsbDeviceInfoPtr device_info,
@@ -388,6 +366,8 @@ ScriptPromise USBDevice::controlTransferOut(
ScriptState* script_state,
const USBControlTransferParameters* setup,
const DOMArrayPiece& data) {
+ DCHECK(!data.IsNull());
+
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
if (!EnsureNoDeviceOrInterfaceChangeInProgress(resolver))
@@ -403,14 +383,23 @@ ScriptPromise USBDevice::controlTransferOut(
if (!parameters)
return promise;
- Vector<uint8_t> buffer;
- if (!ConvertBufferSource(data, &buffer, resolver))
+ if (data.IsDetached()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kDetachedBuffer));
return promise;
+ }
- unsigned transfer_length = buffer.size();
+ if (data.ByteLength() > std::numeric_limits<uint32_t>::max()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kDataError, kBufferTooBig));
+ return promise;
+ }
+
+ auto transfer_length = static_cast<uint32_t>(data.ByteLength());
device_requests_.insert(resolver);
device_->ControlTransferOut(
- std::move(parameters), buffer, 0,
+ std::move(parameters), base::make_span(data.Bytes(), data.ByteLength()),
+ 0,
WTF::Bind(&USBDevice::AsyncControlTransferOut, WrapPersistent(this),
transfer_length, WrapPersistent(resolver)));
return promise;
@@ -472,7 +461,7 @@ ScriptPromise USBDevice::transferOut(ScriptState* script_state,
return promise;
}
- unsigned transfer_length = static_cast<uint32_t>(data.ByteLength());
+ auto transfer_length = static_cast<uint32_t>(data.ByteLength());
device_requests_.insert(resolver);
device_->GenericTransferOut(
endpoint_number, base::make_span(data.Bytes(), data.ByteLength()), 0,
@@ -502,18 +491,29 @@ ScriptPromise USBDevice::isochronousTransferOut(
uint8_t endpoint_number,
const DOMArrayPiece& data,
Vector<unsigned> packet_lengths) {
+ DCHECK(!data.IsNull());
+
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
if (!EnsureEndpointAvailable(false /* out */, endpoint_number, resolver))
return promise;
- Vector<uint8_t> buffer;
- if (!ConvertBufferSource(data, &buffer, resolver))
+ if (data.IsDetached()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kDetachedBuffer));
return promise;
+ }
+
+ if (data.ByteLength() > std::numeric_limits<wtf_size_t>::max()) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kDataError, kBufferTooBig));
+ return promise;
+ }
device_requests_.insert(resolver);
device_->IsochronousTransferOut(
- endpoint_number, buffer, packet_lengths, 0,
+ endpoint_number, base::make_span(data.Bytes(), data.ByteLength()),
+ packet_lengths, 0,
WTF::Bind(&USBDevice::AsyncIsochronousTransferOut, WrapPersistent(this),
WrapPersistent(resolver)));
return promise;
@@ -915,7 +915,7 @@ void USBDevice::AsyncSelectAlternateInterface(wtf_size_t interface_index,
void USBDevice::AsyncControlTransferIn(ScriptPromiseResolver* resolver,
UsbTransferStatus status,
- const Vector<uint8_t>& data) {
+ base::span<const uint8_t> data) {
if (!MarkRequestComplete(resolver))
return;
@@ -928,7 +928,7 @@ void USBDevice::AsyncControlTransferIn(ScriptPromiseResolver* resolver,
}
}
-void USBDevice::AsyncControlTransferOut(unsigned transfer_length,
+void USBDevice::AsyncControlTransferOut(uint32_t transfer_length,
ScriptPromiseResolver* resolver,
UsbTransferStatus status) {
if (!MarkRequestComplete(resolver))
@@ -957,7 +957,7 @@ void USBDevice::AsyncClearHalt(ScriptPromiseResolver* resolver, bool success) {
void USBDevice::AsyncTransferIn(ScriptPromiseResolver* resolver,
UsbTransferStatus status,
- const Vector<uint8_t>& data) {
+ base::span<const uint8_t> data) {
if (!MarkRequestComplete(resolver))
return;
@@ -987,7 +987,7 @@ void USBDevice::AsyncTransferOut(uint32_t transfer_length,
void USBDevice::AsyncIsochronousTransferIn(
ScriptPromiseResolver* resolver,
- const Vector<uint8_t>& data,
+ base::span<const uint8_t> data,
Vector<UsbIsochronousPacketPtr> mojo_packets) {
if (!MarkRequestComplete(resolver))
return;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_device.h b/chromium/third_party/blink/renderer/modules/webusb/usb_device.h
index 4735888c039..21231db5f4d 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_device.h
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_device.h
@@ -7,6 +7,7 @@
#include <bitset>
+#include "base/containers/span.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/mojom/usb_device.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -144,20 +145,20 @@ class USBDevice : public ScriptWrappable,
bool success);
void AsyncControlTransferIn(ScriptPromiseResolver*,
device::mojom::blink::UsbTransferStatus,
- const Vector<uint8_t>&);
- void AsyncControlTransferOut(unsigned,
+ base::span<const uint8_t> data);
+ void AsyncControlTransferOut(uint32_t transfer_length,
ScriptPromiseResolver*,
device::mojom::blink::UsbTransferStatus);
void AsyncClearHalt(ScriptPromiseResolver*, bool success);
void AsyncTransferIn(ScriptPromiseResolver*,
device::mojom::blink::UsbTransferStatus,
- const Vector<uint8_t>&);
+ base::span<const uint8_t> data);
void AsyncTransferOut(uint32_t transfer_length,
ScriptPromiseResolver*,
device::mojom::blink::UsbTransferStatus);
void AsyncIsochronousTransferIn(
ScriptPromiseResolver*,
- const Vector<uint8_t>&,
+ base::span<const uint8_t> data,
Vector<device::mojom::blink::UsbIsochronousPacketPtr>);
void AsyncIsochronousTransferOut(
ScriptPromiseResolver*,
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h b/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h
index 9d75cf5b0a8..b081f7f5e26 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h
@@ -20,7 +20,7 @@ class USBInTransferResult final : public ScriptWrappable {
public:
static USBInTransferResult* Create(const String& status,
- const Vector<uint8_t>& data) {
+ base::span<const uint8_t> data) {
DOMDataView* data_view = DOMDataView::Create(
DOMArrayBuffer::Create(data.data(), data.size()), 0, data.size());
return MakeGarbageCollected<USBInTransferResult>(status, data_view);
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h b/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h
index de501a8d589..629d1ac86e8 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h
@@ -20,21 +20,21 @@ class USBOutTransferResult final : public ScriptWrappable {
}
static USBOutTransferResult* Create(const String& status,
- unsigned bytes_written) {
+ uint32_t bytes_written) {
return MakeGarbageCollected<USBOutTransferResult>(status, bytes_written);
}
- USBOutTransferResult(const String& status, unsigned bytes_written)
+ USBOutTransferResult(const String& status, uint32_t bytes_written)
: status_(status), bytes_written_(bytes_written) {}
~USBOutTransferResult() override = default;
String status() const { return status_; }
- unsigned bytesWritten() const { return bytes_written_; }
+ uint32_t bytesWritten() const { return bytes_written_; }
private:
const String status_;
- const unsigned bytes_written_;
+ const uint32_t bytes_written_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/worklet/OWNERS b/chromium/third_party/blink/renderer/modules/worklet/OWNERS
index 2129484b425..bb3760eb06c 100644
--- a/chromium/third_party/blink/renderer/modules/worklet/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/worklet/OWNERS
@@ -1,8 +1,4 @@
flackr@chromium.org
-# For AnimationWorklet-related changes
-majidvp@chromium.org
-
# For PaintWorklet-related changes
-ikilpatrick@chromium.org
xidachen@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/chromium/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
index 928441f2ba5..16d0a25ae9b 100644
--- a/chromium/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
+++ b/chromium/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -83,7 +83,7 @@ class AnimationAndPaintWorkletThreadTest : public PageTestBase,
ScriptState::Scope scope(script_state);
const KURL js_url("https://example.com/foo.js");
v8::Local<v8::Module> module = ModuleTestBase::CompileModule(
- script_state->GetIsolate(), "var counter = 0; ++counter;", js_url);
+ script_state, "var counter = 0; ++counter;", js_url);
EXPECT_FALSE(module.IsEmpty());
ScriptValue exception =
ModuleRecord::Instantiate(script_state, module, js_url);
diff --git a/chromium/third_party/blink/renderer/modules/xr/BUILD.gn b/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
index 7d1d425d400..411d6623f34 100644
--- a/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -116,7 +116,6 @@ blink_modules_sources("xr") {
"xr_webgl_depth_information.h",
"xr_webgl_layer.cc",
"xr_webgl_layer.h",
- "xr_webgl_rendering_context.h",
]
deps = [
diff --git a/chromium/third_party/blink/renderer/modules/xr/idls.gni b/chromium/third_party/blink/renderer/modules/xr/idls.gni
deleted file mode 100644
index d3480a91ed7..00000000000
--- a/chromium/third_party/blink/renderer/modules/xr/idls.gni
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/blink/renderer/config.gni")
-
-modules_idl_files = [
- "xr_anchor.idl",
- "xr_anchor_set.idl",
- "xr_bounded_reference_space.idl",
- "xr_camera.idl",
- "xr_cpu_depth_information.idl",
- "xr_depth_information.idl",
- "xr_dom_overlay_state.idl",
- "xr_frame.idl",
- "xr_hand.idl",
- "xr_joint_pose.idl",
- "xr_joint_space.idl",
- "xr_image_tracking_result.idl",
- "xr_input_source.idl",
- "xr_input_source_array.idl",
- "xr_input_source_event.idl",
- "xr_input_sources_change_event.idl",
- "xr_layer.idl",
- "xr_light_estimate.idl",
- "xr_light_probe.idl",
- "xr_plane.idl",
- "xr_plane_set.idl",
- "xr_pose.idl",
- "xr_ray.idl",
- "xr_reference_space.idl",
- "xr_reference_space_event.idl",
- "xr_render_state.idl",
- "xr_rigid_transform.idl",
- "xr_hit_test_result.idl",
- "xr_hit_test_source.idl",
- "xr_session.idl",
- "xr_session_event.idl",
- "xr_space.idl",
- "xr_system.idl",
- "xr_transient_input_hit_test_result.idl",
- "xr_transient_input_hit_test_source.idl",
- "xr_view.idl",
- "xr_viewer_pose.idl",
- "xr_viewport.idl",
- "xr_webgl_binding.idl",
- "xr_webgl_depth_information.idl",
- "xr_webgl_layer.idl",
-]
-
-modules_callback_function_idl_files = [ "xr_frame_request_callback.idl" ]
-
-modules_dictionary_idl_files = [
- "xr_depth_state_init.idl",
- "xr_dom_overlay_init.idl",
- "xr_hit_test_options_init.idl",
- "xr_input_source_event_init.idl",
- "xr_input_sources_change_event_init.idl",
- "xr_light_probe_init.idl",
- "xr_ray_direction_init.idl",
- "xr_reference_space_event_init.idl",
- "xr_render_state_init.idl",
- "xr_session_event_init.idl",
- "xr_session_init.idl",
- "xr_tracked_image_init.idl",
- "xr_transient_input_hit_test_options_init.idl",
- "xr_webgl_layer_init.idl",
-]
-
-modules_typedefs_enums_only_idl_files = [ "xr_webgl_context.idl" ]
-
-modules_dependency_idl_files = [
- "document_xr.idl",
- "html_element_xr.idl",
- "mathml_element_xr.idl",
- "navigator_xr.idl",
- "svg_element_xr.idl",
- "window_xr.idl",
-]
diff --git a/chromium/third_party/blink/renderer/modules/xr/type_converters.h b/chromium/third_party/blink/renderer/modules/xr/type_converters.h
index 1cd90a3944c..496298bd6b9 100644
--- a/chromium/third_party/blink/renderer/modules/xr/type_converters.h
+++ b/chromium/third_party/blink/renderer/modules/xr/type_converters.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_TYPE_CONVERTERS_H_
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
#include "third_party/blink/renderer/modules/xr/xr_plane.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
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 4019235b831..b4e081ac52b 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
@@ -23,7 +23,7 @@ class XRCanvasInputProvider : public GarbageCollected<XRCanvasInputProvider>,
public NameClient {
public:
XRCanvasInputProvider(XRSession*, HTMLCanvasElement*);
- virtual ~XRCanvasInputProvider();
+ ~XRCanvasInputProvider() override;
XRSession* session() const { return session_; }
HTMLCanvasElement* canvas() const { return canvas_; }
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_cpu_depth_information.cc b/chromium/third_party/blink/renderer/modules/xr/xr_cpu_depth_information.cc
index d1dd7477ee6..dc35347ac34 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_cpu_depth_information.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_cpu_depth_information.cc
@@ -7,8 +7,8 @@
#include <cmath>
#include <cstdlib>
+#include "base/cxx17_backports.h"
#include "base/numerics/checked_math.h"
-#include "base/numerics/ranges.h"
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
@@ -92,9 +92,9 @@ float XRCPUDepthInformation::getDepthInMeters(
// `norm_depth_coordinates` becomes `depth_coordinates`:
depth_coordinates.Scale(size_.width(), size_.height(), 1.0);
- uint32_t column = base::ClampToRange<uint32_t>(
+ uint32_t column = base::clamp<uint32_t>(
static_cast<uint32_t>(depth_coordinates.x()), 0, size_.width() - 1);
- uint32_t row = base::ClampToRange<uint32_t>(
+ uint32_t row = base::clamp<uint32_t>(
static_cast<uint32_t>(depth_coordinates.y()), 0, size_.height() - 1);
auto checked_index =
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_cube_map.cc b/chromium/third_party/blink/renderer/modules/xr/xr_cube_map.cc
index f9c654df547..5db04bef9f9 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_cube_map.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_cube_map.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/xr/xr_cube_map.h"
+#include "base/cxx17_backports.h"
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
#include "third_party/blink/renderer/modules/webgl/webgl_texture.h"
@@ -26,7 +27,7 @@ float HalfFloatToFloat(const uint16_t input) {
// Linear to sRGB converstion as given in
// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_framebuffer_sRGB.txt
uint8_t LinearToSrgb(float cl) {
- float cs = base::ClampToRange(
+ float cs = base::clamp(
cl < 0.0031308f ? 12.92f * cl : 1.055f * std::pow(cl, 0.41666f) - 0.055f,
0.0f, 1.0f);
return static_cast<uint8_t>(255.0f * cs + 0.5f);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc b/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
index cf4aa0e5f1d..e67ff0c4ba0 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
@@ -81,9 +81,7 @@ XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space,
}
// Must use a reference space created from the same session.
- if (reference_space->session() != session_) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
+ if (!IsSameSession(reference_space->session(), exception_state)) {
return nullptr;
}
@@ -123,15 +121,6 @@ XRAnchorSet* XRFrame::trackedAnchors() const {
XRPlaneSet* XRFrame::detectedPlanes(ExceptionState& exception_state) const {
DVLOG(3) << __func__;
- if (!session_->IsFeatureEnabled(
- device::mojom::XRSessionFeature::PLANE_DETECTION)) {
- DVLOG(2) << __func__
- << ": plane detection feature not enabled on a session";
- exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
- XRSession::kPlanesFeatureNotSupported);
- return {};
- }
-
if (!is_active_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kInactiveFrame);
@@ -161,9 +150,7 @@ XRLightEstimate* XRFrame::getLightEstimate(
}
// Must use a light probe created from the same session.
- if (light_probe->session() != session_) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
+ if (!IsSameSession(light_probe->session(), exception_state)) {
return nullptr;
}
@@ -226,15 +213,8 @@ XRPose* XRFrame::getPose(XRSpace* space,
return nullptr;
}
- if (space->session() != session_) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
- return nullptr;
- }
-
- if (basespace->session() != session_) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
+ if (!IsSameSession(space->session(), exception_state) ||
+ !IsSameSession(basespace->session(), exception_state)) {
return nullptr;
}
@@ -427,6 +407,16 @@ ScriptPromise XRFrame::CreateAnchorFromNonStationarySpace(
exception_state);
}
+bool XRFrame::IsSameSession(XRSession* space_session,
+ ExceptionState& exception_state) const {
+ if (space_session != session_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kSessionMismatch);
+ return false;
+ }
+ return true;
+}
+
HeapVector<Member<XRImageTrackingResult>> XRFrame::getImageTrackingResults(
ExceptionState& exception_state) {
return session_->ImageTrackingResults(exception_state);
@@ -434,16 +424,20 @@ HeapVector<Member<XRImageTrackingResult>> XRFrame::getImageTrackingResults(
XRJointPose* XRFrame::getJointPose(XRJointSpace* joint,
XRSpace* baseSpace,
- ExceptionState& exception_state) {
+ ExceptionState& exception_state) const {
if (!is_active_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kInactiveFrame);
return nullptr;
}
- if (session_ != baseSpace->session() || session_ != joint->session()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
+ if (!IsSameSession(baseSpace->session(), exception_state) ||
+ !IsSameSession(joint->session(), exception_state)) {
+ return nullptr;
+ }
+
+ if (!session_->CanReportPoses()) {
+ exception_state.ThrowSecurityError(kCannotReportPoses);
return nullptr;
}
@@ -460,70 +454,80 @@ XRJointPose* XRFrame::getJointPose(XRJointSpace* joint,
bool XRFrame::fillJointRadii(HeapVector<Member<XRJointSpace>>& jointSpaces,
NotShared<DOMFloat32Array> radii,
- ExceptionState& exception_state) {
+ ExceptionState& exception_state) const {
if (!is_active_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kInactiveFrame);
return false;
}
+ for (const auto& joint_space : jointSpaces) {
+ if (!IsSameSession(joint_space->session(), exception_state)) {
+ return false;
+ }
+ }
+
if (jointSpaces.size() != radii->length()) {
exception_state.ThrowTypeError(kMismatchedBufferSizes);
return false;
}
+ bool all_valid = true;
+
for (unsigned offset = 0; offset < jointSpaces.size(); offset++) {
- const XRJointSpace* jointSpace = jointSpaces[offset];
- if (session_ != jointSpace->session()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
- return false;
+ const XRJointSpace* joint_space = jointSpaces[offset];
+ if (joint_space->handHasMissingPoses()) {
+ radii->Data()[offset] = NAN;
+ all_valid = false;
+ } else {
+ radii->Data()[offset] = joint_space->radius();
}
-
- radii->Data()[offset] = jointSpace->radius();
}
- return true;
+ return all_valid;
}
bool XRFrame::fillPoses(HeapVector<Member<XRSpace>>& spaces,
XRSpace* baseSpace,
NotShared<DOMFloat32Array> transforms,
- ExceptionState& exception_state) {
+ ExceptionState& exception_state) const {
+ const unsigned floats_per_transform = 16;
+
if (!is_active_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kInactiveFrame);
return false;
}
- const unsigned floats_per_transform = 16;
+ for (const auto& space : spaces) {
+ if (!IsSameSession(space->session(), exception_state)) {
+ return false;
+ }
+ }
+
+ if (!IsSameSession(baseSpace->session(), exception_state)) {
+ return false;
+ }
if (spaces.size() * floats_per_transform > transforms->length()) {
exception_state.ThrowTypeError(kSpacesSequenceTooLarge);
return false;
}
- if (session_ != baseSpace->session()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
+ if (!session_->CanReportPoses()) {
+ exception_state.ThrowSecurityError(kCannotReportPoses);
return false;
}
bool allValid = true;
unsigned offset = 0;
for (const auto& space : spaces) {
- if (session_ != space->session()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kSessionMismatch);
- return false;
- }
-
const XRPose* pose = space->getPose(baseSpace);
if (!pose) {
for (unsigned i = 0; i < floats_per_transform; i++) {
transforms->Data()[offset + i] = NAN;
- allValid = false;
}
+ allValid = false;
} else {
const float* const poseMatrix = pose->transform()->matrix()->Data();
for (unsigned i = 0; i < floats_per_transform; i++) {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame.h b/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
index fc6df86454f..8f1fb5fb15b 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
@@ -91,14 +91,14 @@ class XRFrame final : public ScriptWrappable {
XRJointPose* getJointPose(XRJointSpace* joint,
XRSpace* baseSpace,
- ExceptionState& exception_state);
+ ExceptionState& exception_state) const;
bool fillJointRadii(HeapVector<Member<XRJointSpace>>& jointSpaces,
NotShared<DOMFloat32Array> radii,
- ExceptionState& exception_state);
+ ExceptionState& exception_state) const;
bool fillPoses(HeapVector<Member<XRSpace>>& spaces,
XRSpace* baseSpace,
NotShared<DOMFloat32Array> transforms,
- ExceptionState& exception_state);
+ ExceptionState& exception_state) const;
private:
std::unique_ptr<TransformationMatrix> GetAdjustedPoseMatrix(XRSpace*) const;
@@ -115,6 +115,10 @@ class XRFrame final : public ScriptWrappable {
XRSpace* space,
absl::optional<uint64_t> maybe_plane_id,
ExceptionState& exception_state);
+ // Helper for checking if space and frame have the same session.
+ // Sets kInvalidStateError exception state if sessions are different.
+ bool IsSameSession(XRSession* space_session,
+ ExceptionState& exception_state) const;
const Member<XRSession> session_;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl b/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
index 27d3067272a..76643021e69 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -32,11 +32,11 @@
[RuntimeEnabled=WebXRImageTracking, RaisesException, MeasureAs=XRFrameGetImageTrackingResults]
FrozenArray<XRImageTrackingResult> getImageTrackingResults();
- [RuntimeEnabled=WebXRHandInput, RaisesException]
+ [RuntimeEnabled=WebXRHandInput, RaisesException, MeasureAs=XRFrameGetJointPose]
XRJointPose? getJointPose(XRJointSpace joint, XRSpace baseSpace);
- [RuntimeEnabled=WebXRHandInput, RaisesException]
+ [RuntimeEnabled=WebXRHandInput, RaisesException, MeasureAs=XRFrameFillJointRadii]
boolean fillJointRadii(sequence<XRJointSpace> jointSpaces, Float32Array radii);
- [RuntimeEnabled=WebXRHandInput, RaisesException]
+ [RuntimeEnabled=WebXRHandInput, RaisesException, MeasureAs=XRFrameFillPoses]
boolean fillPoses(sequence<XRSpace> spaces, XRSpace baseSpace, Float32Array transforms);
// More details about the real-world understanding APIs can be found here:
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 4235c5dd078..6091be899e8 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
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_PROVIDER_H_
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/heap/disallow_new_wrapper.h"
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 dee0da7ca88..a0c0fe2bd8f 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
@@ -24,6 +24,7 @@ class XRFrameRequestCallbackCollection final
public NameClient {
public:
explicit XRFrameRequestCallbackCollection(ExecutionContext*);
+ ~XRFrameRequestCallbackCollection() override = default;
using CallbackId = int;
CallbackId RegisterCallback(V8XRFrameRequestCallback*);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.cc b/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.cc
index 0f14e55e2ba..8b79d298ac8 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.cc
@@ -30,14 +30,17 @@ bool XRGripSpace::EmulatedPosition() const {
device::mojom::blink::XRNativeOriginInformationPtr XRGripSpace::NativeOrigin()
const {
- // Grip space's native origin is equal to input source's native origin, but
- // only when using tracked pointer for input.
+ // Grip space's native origin is valid only when using tracked pointer for
+ // input.
if (input_source_->TargetRayMode() !=
device::mojom::XRTargetRayMode::POINTING) {
return nullptr;
}
- return input_source_->nativeOrigin();
+ return device::mojom::blink::XRNativeOriginInformation::
+ NewInputSourceSpaceInfo(device::mojom::blink::XRInputSourceSpaceInfo::New(
+ input_source_->source_id(),
+ device::mojom::blink::XRInputSourceSpaceType::kGrip));
}
bool XRGripSpace::IsStationary() const {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hand.cc b/chromium/third_party/blink/renderer/modules/xr/xr_hand.cc
index 2e86feedbd6..5ccad215959 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hand.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hand.cc
@@ -3,58 +3,107 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/xr/xr_hand.h"
+
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
-#include "third_party/blink/renderer/modules/xr/xr_joint_pose.h"
#include "third_party/blink/renderer/modules/xr/xr_joint_space.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
namespace blink {
+class XRHandIterationSource final
+ : public PairIterable<String, Member<XRJointSpace>>::IterationSource {
+ public:
+ explicit XRHandIterationSource(HeapVector<Member<XRJointSpace>>& joints)
+ : index_(0), joints_(joints) {}
+
+ bool Next(ScriptState*,
+ String& key,
+ Member<XRJointSpace>& value,
+ ExceptionState&) override {
+ if (index_ >= joints_.size())
+ return false;
+
+ key = MojomHandJointToString(
+ static_cast<device::mojom::blink::XRHandJoint>(index_));
+ value = joints_.at(index_);
+ index_++;
+ return true;
+ }
+
+ void Trace(Visitor* visitor) const override {
+ PairIterable<String, Member<XRJointSpace>>::IterationSource::Trace(visitor);
+ }
+
+ private:
+ wtf_size_t index_;
+ const HeapVector<Member<XRJointSpace>>& joints_;
+};
+
XRHand::XRHand(const device::mojom::blink::XRHandTrackingData* state,
- XRInputSource* input_source) {
- DCHECK_EQ(state->hand_joint_data.size(), kNumJoints);
-
- for (unsigned i = 0; i < state->hand_joint_data.size(); i++) {
- device::mojom::blink::XRHandJoint joint = state->hand_joint_data[i]->joint;
- DCHECK(static_cast<unsigned>(joint) < state->hand_joint_data.size());
-
- XRJointSpace* joint_space = MakeGarbageCollected<XRJointSpace>(
- input_source->session(),
- std::make_unique<TransformationMatrix>(
- state->hand_joint_data[i]->mojo_from_joint.matrix()),
- joint, state->hand_joint_data[i]->radius,
+ XRInputSource* input_source)
+ : joints_(kNumJoints) {
+ for (unsigned i = 0; i < kNumJoints; ++i) {
+ device::mojom::blink::XRHandJoint joint =
+ static_cast<device::mojom::blink::XRHandJoint>(i);
+ joints_[i] = MakeGarbageCollected<XRJointSpace>(
+ this, input_source->session(), nullptr, joint, 0.0f,
input_source->xr_handedness());
-
- joint_spaces_[static_cast<unsigned>(joint)] = {
- MojomHandJointToString(joint), std::move(joint_space)};
}
+
+ updateFromHandTrackingData(state, input_source);
}
XRJointSpace* XRHand::get(const String& key) {
- return std::get<THandJointsMapValue>(
- joint_spaces_[static_cast<unsigned>(StringToMojomHandJoint(key))]);
+ device::mojom::blink::XRHandJoint joint = StringToMojomHandJoint(key);
+ unsigned index = static_cast<unsigned>(joint);
+ return joints_[index];
}
-XRHand::HandJointIterationSource::HandJointIterationSource(
- const THandJointCollection& joint_spaces)
- : joint_spaces_(joint_spaces), current(0) {}
-
-bool XRHand::HandJointIterationSource::Next(ScriptState* script_state,
- THandJointsMapKey& key,
- THandJointsMapValue& value,
- ExceptionState& exception_state) {
- if (current >= joint_spaces_.size())
- return false;
- key = std::get<THandJointsMapKey>(joint_spaces_[current]);
- value = std::get<THandJointsMapValue>(joint_spaces_[current]);
- current++;
- return true;
+void XRHand::updateFromHandTrackingData(
+ const device::mojom::blink::XRHandTrackingData* state,
+ XRInputSource* input_source) {
+ bool new_missing_poses = false; // hand was updated with a null pose
+ bool new_poses = false; // hand was updated with a valid pose
+
+ for (const auto& hand_joint : state->hand_joint_data) {
+ unsigned joint_index = static_cast<unsigned>(hand_joint->joint);
+
+ std::unique_ptr<TransformationMatrix> mojo_from_joint = nullptr;
+ if (hand_joint->mojo_from_joint) {
+ new_poses = true;
+ mojo_from_joint = std::make_unique<TransformationMatrix>(
+ hand_joint->mojo_from_joint->matrix());
+ } else {
+ new_missing_poses = true;
+ }
+
+ joints_[joint_index]->UpdateTracking(std::move(mojo_from_joint),
+ hand_joint->radius);
+ }
+
+ if (new_missing_poses) {
+ // There is at least one missing pose.
+ has_missing_poses_ = true;
+ } else if (has_missing_poses_ && new_poses) {
+ // Need to check if there are any missing poses
+ has_missing_poses_ = false;
+ for (const auto& joint : joints_) {
+ if (!joint->MojoFromNative()) {
+ has_missing_poses_ = true;
+ break;
+ }
+ }
+ }
+}
+
+XRHand::IterationSource* XRHand::StartIteration(
+ ScriptState* script_state,
+ ExceptionState& exception_state) {
+ return MakeGarbageCollected<XRHandIterationSource>(joints_);
}
void XRHand::Trace(Visitor* visitor) const {
- for (const auto& key_value_pair : joint_spaces_) {
- visitor->Trace(std::get<THandJointsMapValue>(key_value_pair));
- }
+ visitor->Trace(joints_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hand.h b/chromium/third_party/blink/renderer/modules/xr/xr_hand.h
index 705cb094386..fad0f758f3a 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hand.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hand.h
@@ -22,48 +22,28 @@ class XRHand : public ScriptWrappable,
static const unsigned kNumJoints =
static_cast<unsigned>(device::mojom::blink::XRHandJoint::kMaxValue) + 1u;
- using THandJointsMapKey = String;
- using THandJointsMapValue = Member<XRJointSpace>;
- using THandJointCollection =
- std::array<std::tuple<THandJointsMapKey, THandJointsMapValue>,
- kNumJoints>;
-
public:
explicit XRHand(const device::mojom::blink::XRHandTrackingData* state,
XRInputSource* input_source);
~XRHand() override = default;
- size_t size() const { return joint_spaces_.size(); }
+ size_t size() const { return joints_.size(); }
XRJointSpace* get(const String& key);
+ void updateFromHandTrackingData(
+ const device::mojom::blink::XRHandTrackingData* state,
+ XRInputSource* input_source);
+
+ bool hasMissingPoses() const { return has_missing_poses_; }
+
void Trace(Visitor*) const override;
private:
- class HandJointIterationSource final
- : public PairIterable<THandJointsMapKey,
- THandJointsMapValue>::IterationSource {
- public:
- explicit HandJointIterationSource(const THandJointCollection& joint_spaces);
-
- bool Next(ScriptState* script_state,
- THandJointsMapKey& key,
- THandJointsMapValue& value,
- ExceptionState& exception_state) override;
-
- private:
- const THandJointCollection& joint_spaces_;
-
- uint32_t current;
- };
-
- using Iterationsource =
- PairIterable<String, Member<XRJointSpace>>::IterationSource;
- IterationSource* StartIteration(ScriptState*, ExceptionState&) override {
- return MakeGarbageCollected<HandJointIterationSource>(joint_spaces_);
- }
-
- THandJointCollection joint_spaces_;
+ IterationSource* StartIteration(ScriptState*, ExceptionState&) override;
+
+ HeapVector<Member<XRJointSpace>> joints_;
+ bool has_missing_poses_ = true;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_image_tracking_result.cc b/chromium/third_party/blink/renderer/modules/xr/xr_image_tracking_result.cc
index 7e3355f47f4..069d9a120f4 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_image_tracking_result.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_image_tracking_result.cc
@@ -48,12 +48,7 @@ XRSpace* XRImageTrackingResult::imageSpace() const {
device::mojom::blink::XRNativeOriginInformationPtr
XRImageTrackingResult::NativeOrigin() const {
- // TODO(https://crbug.com/1143575): We'll want these to correspond to an
- // actual, independent space eventually, but at the moment it's sufficient for
- // the ARCore implementation to have it be equivalent to the local reference
- // space.
- return device::mojom::blink::XRNativeOriginInformation::NewReferenceSpaceType(
- device::mojom::XRReferenceSpaceType::kLocal);
+ return device::mojom::blink::XRNativeOriginInformation::NewImageIndex(index_);
}
void XRImageTrackingResult::Trace(Visitor* visitor) const {
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 aad2065ef07..80e24f41e20 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
#include "base/time/time.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
@@ -107,10 +108,7 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom(
}
if (updated_source->state_.is_visible) {
- if (state->hand_tracking_data.get()) {
- updated_source->hand_ = MakeGarbageCollected<XRHand>(
- state->hand_tracking_data.get(), updated_source);
- }
+ updated_source->UpdateHand(state->hand_tracking_data.get());
}
updated_source->state_.emulated_position = state->emulated_position;
@@ -210,6 +208,11 @@ bool XRInputSource::InvalidatesSameObject(
}
}
+ if ((state->hand_tracking_data.get() && !hand_) ||
+ (!state->hand_tracking_data.get() && hand_)) {
+ return true;
+ }
+
return false;
}
@@ -242,6 +245,19 @@ void XRInputSource::UpdateGamepad(
}
}
+void XRInputSource::UpdateHand(
+ const device::mojom::blink::XRHandTrackingData* hand_tracking_data) {
+ if (hand_tracking_data) {
+ if (!hand_) {
+ hand_ = MakeGarbageCollected<XRHand>(hand_tracking_data, this);
+ } else {
+ hand_->updateFromHandTrackingData(hand_tracking_data, this);
+ }
+ } else {
+ hand_ = nullptr;
+ }
+}
+
absl::optional<TransformationMatrix> XRInputSource::MojoFromInput() const {
if (!mojo_from_input_.get()) {
return absl::nullopt;
@@ -256,12 +272,6 @@ absl::optional<TransformationMatrix> XRInputSource::InputFromPointer() const {
return *(input_from_pointer_.get());
}
-device::mojom::blink::XRNativeOriginInformationPtr XRInputSource::nativeOrigin()
- const {
- return device::mojom::blink::XRNativeOriginInformation::NewInputSourceId(
- this->source_id());
-}
-
void XRInputSource::OnSelectStart() {
DVLOG(3) << __func__;
// Discard duplicate events and ones after the session has ended.
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 593e25336ad..6bc690e758d 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
@@ -84,8 +84,6 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
absl::optional<TransformationMatrix> InputFromPointer() const;
- device::mojom::blink::XRNativeOriginInformationPtr nativeOrigin() const;
-
void OnSelectStart();
void OnSelectEnd();
void OnSelect();
@@ -155,6 +153,9 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
// from InvalidatesSameObject
void UpdateGamepad(const absl::optional<device::Gamepad>& gamepad);
+ void UpdateHand(
+ const device::mojom::blink::XRHandTrackingData* hand_joint_data);
+
XRInputSourceEvent* CreateInputSourceEvent(const AtomicString& type);
// These member variables all require special behavior when being copied or
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_array.cc b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_array.cc
index b6bad19e241..17b33043922 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_array.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_array.cc
@@ -29,7 +29,7 @@ XRInputSource* XRInputSourceArray::operator[](unsigned index) const {
}
XRInputSource* XRInputSourceArray::GetWithSourceId(uint32_t source_id) {
- return input_sources_.at(source_id);
+ return input_sources_.DeprecatedAtOrEmptyValue(source_id);
}
void XRInputSourceArray::RemoveWithSourceId(uint32_t source_id) {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.cc b/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.cc
index 7603f1e9bb8..ead930ab926 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.cc
@@ -10,12 +10,14 @@
namespace blink {
XRJointSpace::XRJointSpace(
+ XRHand* hand,
XRSession* session,
std::unique_ptr<TransformationMatrix> mojo_from_joint,
device::mojom::blink::XRHandJoint joint,
float radius,
device::mojom::blink::XRHandedness handedness)
: XRSpace(session),
+ hand_(hand),
mojo_from_joint_space_(std::move(mojo_from_joint)),
joint_(joint),
radius_(radius),
@@ -25,10 +27,6 @@ absl::optional<TransformationMatrix> XRJointSpace::MojoFromNative() {
return *mojo_from_joint_space_.get();
}
-bool XRJointSpace::EmulatedPosition() const {
- return false;
-}
-
device::mojom::blink::XRNativeOriginInformationPtr XRJointSpace::NativeOrigin()
const {
device::mojom::blink::XRHandJointSpaceInfoPtr joint_space_info =
@@ -39,6 +37,29 @@ device::mojom::blink::XRNativeOriginInformationPtr XRJointSpace::NativeOrigin()
std::move(joint_space_info));
}
+bool XRJointSpace::EmulatedPosition() const {
+ return false;
+}
+
+XRPose* XRJointSpace::getPose(XRSpace* other_space) {
+ // If any of the spaces belonging to the same XRHand return null when
+ // populating the pose, all the spaces of that XRHand must also return
+ // null when populating the pose.
+ if (handHasMissingPoses()) {
+ return nullptr;
+ }
+
+ // Return the base class' value if we are tracked.
+ return XRSpace::getPose(other_space);
+}
+
+void XRJointSpace::UpdateTracking(
+ std::unique_ptr<TransformationMatrix> mojo_from_joint,
+ float radius) {
+ mojo_from_joint_space_ = std::move(mojo_from_joint);
+ radius_ = radius;
+}
+
bool XRJointSpace::IsStationary() const {
return false;
}
@@ -51,7 +72,12 @@ std::string XRJointSpace::ToString() const {
return "XRJointSpace";
}
+bool XRJointSpace::handHasMissingPoses() const {
+ return hand_->hasMissingPoses();
+}
+
void XRJointSpace::Trace(Visitor* visitor) const {
+ visitor->Trace(hand_);
XRSpace::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.h
index 628203cd476..b8018f23a46 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_joint_space.h
@@ -6,6 +6,8 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_JOINT_SPACE_H_
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/modules/xr/xr_hand.h"
#include "third_party/blink/renderer/modules/xr/xr_space.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -17,7 +19,8 @@ class XRJointSpace : public XRSpace {
DEFINE_WRAPPERTYPEINFO();
public:
- XRJointSpace(XRSession* session,
+ XRJointSpace(XRHand* hand,
+ XRSession* session,
std::unique_ptr<TransformationMatrix> mojo_from_joint,
device::mojom::blink::XRHandJoint joint,
float radius,
@@ -29,20 +32,27 @@ class XRJointSpace : public XRSpace {
device::mojom::XRHandedness handedness() const { return handedness_; }
absl::optional<TransformationMatrix> MojoFromNative() override;
+ device::mojom::blink::XRNativeOriginInformationPtr NativeOrigin()
+ const override;
bool EmulatedPosition() const override;
+ XRPose* getPose(XRSpace* other_space) override;
- device::mojom::blink::XRNativeOriginInformationPtr NativeOrigin() const final;
+ void UpdateTracking(std::unique_ptr<TransformationMatrix> mojo_from_joint,
+ float radius);
bool IsStationary() const override;
std::string ToString() const override;
+ bool handHasMissingPoses() const;
+
void Trace(Visitor*) const override;
private:
- const std::unique_ptr<TransformationMatrix> mojo_from_joint_space_;
+ Member<XRHand> hand_;
+ std::unique_ptr<TransformationMatrix> mojo_from_joint_space_;
const device::mojom::blink::XRHandJoint joint_;
- const float radius_;
+ float radius_;
const device::mojom::XRHandedness handedness_;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_light_probe.h b/chromium/third_party/blink/renderer/modules/xr/xr_light_probe.h
index 4dff8c0bc3f..fd582663b3e 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_light_probe.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_light_probe.h
@@ -8,6 +8,7 @@
#include <memory>
#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.cc b/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.cc
index 51790cdb1d6..69e6c72c62f 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.cc
@@ -24,8 +24,9 @@ void XRPlaneManager::ProcessPlaneInformation(
DVLOG(3) << __func__ << ": detected_planes_data is null";
// We have received a nullopt - plane detection is not supported or
- // disabled. Mark detected_planes as null & clear stored planes.
- is_detected_planes_null_ = true;
+ // disabled. Clear stored planes (if any).
+ // The device can send either null or empty data - in both cases, it means
+ // that there are no planes available.
plane_ids_to_planes_.clear();
return;
}
@@ -39,8 +40,6 @@ void XRPlaneManager::ProcessPlaneInformation(
<< ", all planes size="
<< detected_planes_data->all_planes_ids.size();
- is_detected_planes_null_ = false;
-
HeapHashMap<uint64_t, Member<XRPlane>> updated_planes;
// First, process all planes that had their information updated (new planes
@@ -75,8 +74,10 @@ void XRPlaneManager::ProcessPlaneInformation(
}
XRPlaneSet* XRPlaneManager::GetDetectedPlanes() const {
- if (is_detected_planes_null_)
- return nullptr;
+ if (!session_->IsFeatureEnabled(
+ device::mojom::XRSessionFeature::PLANE_DETECTION)) {
+ return MakeGarbageCollected<XRPlaneSet>(HeapHashSet<Member<XRPlane>>{});
+ }
HeapHashSet<Member<XRPlane>> result;
for (auto& plane_id_and_plane : plane_ids_to_planes_) {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.h b/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.h
index ea1b01bab16..cf133fe1a52 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_plane_manager.h
@@ -33,7 +33,6 @@ class XRPlaneManager : public GarbageCollected<XRPlaneManager> {
private:
Member<XRSession> session_;
- bool is_detected_planes_null_ = true;
HeapHashMap<uint64_t, Member<XRPlane>> plane_ids_to_planes_;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc b/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
index 8be9ce9e129..c6f8e3ace42 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
@@ -136,7 +136,9 @@ DOMFloat32Array* XRRay::matrix() {
TransformationMatrix matrix;
const blink::FloatPoint3D desiredRayDirection = {
- direction_->x(), direction_->y(), direction_->z()};
+ static_cast<float>(direction_->x()),
+ static_cast<float>(direction_->y()),
+ static_cast<float>(direction_->z())};
// Translation from 0 to |origin_| is simply translation by |origin_|.
// (implicit) Step 6: Let translation be the translation matrix with
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_render_state.h b/chromium/third_party/blink/renderer/modules/xr/xr_render_state.h
index 0655cabd0db..958c5a42338 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_render_state.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_render_state.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RENDER_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RENDER_STATE_H_
+#include "third_party/abseil-cpp/absl/types/optional.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/modules/xr/xr_session.cc b/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
index 488d627568b..ec731301a58 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -12,8 +12,9 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "base/auto_reset.h"
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
+#include "base/trace_event/trace_event.h"
#include "base/types/pass_key.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -355,9 +356,9 @@ XRSession::XRSession(
UpdateVisibilityState();
// Clamp to a reasonable min/max size for the default framebuffer scale.
- default_framebuffer_scale_ = base::ClampToRange(
- device_config->default_framebuffer_scale, kMinDefaultFramebufferScale,
- kMaxDefaultFramebufferScale);
+ default_framebuffer_scale_ =
+ base::clamp(device_config->default_framebuffer_scale,
+ kMinDefaultFramebufferScale, kMaxDefaultFramebufferScale);
DVLOG(2) << __func__
<< ": supports_viewport_scaling_=" << supports_viewport_scaling_;
@@ -419,11 +420,11 @@ const String XRSession::visibilityState() const {
XRAnchorSet* XRSession::TrackedAnchors() const {
DVLOG(3) << __func__;
- HeapHashSet<Member<XRAnchor>> result;
-
- if (is_tracked_anchors_null_)
- return nullptr;
+ if (!IsFeatureEnabled(device::mojom::XRSessionFeature::ANCHORS)) {
+ return MakeGarbageCollected<XRAnchorSet>(HeapHashSet<Member<XRAnchor>>{});
+ }
+ HeapHashSet<Member<XRAnchor>> result;
for (auto& anchor_id_and_anchor : anchor_ids_to_anchors_) {
result.insert(anchor_id_and_anchor.value);
}
@@ -882,11 +883,12 @@ ScriptPromise XRSession::requestHitTestSourceForTransientInput(
: MakeGarbageCollected<XRRay>();
device::mojom::blink::XRRayPtr ray_mojo = device::mojom::blink::XRRay::New();
- ray_mojo->origin = {offsetRay->origin()->x(), offsetRay->origin()->y(),
- offsetRay->origin()->z()};
- ray_mojo->direction = {offsetRay->direction()->x(),
- offsetRay->direction()->y(),
- offsetRay->direction()->z()};
+ ray_mojo->origin = {static_cast<float>(offsetRay->origin()->x()),
+ static_cast<float>(offsetRay->origin()->y()),
+ static_cast<float>(offsetRay->origin()->z())};
+ ray_mojo->direction = {static_cast<float>(offsetRay->direction()->x()),
+ static_cast<float>(offsetRay->direction()->y()),
+ static_cast<float>(offsetRay->direction()->z())};
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
@@ -1017,9 +1019,9 @@ void XRSession::ProcessAnchorsData(
if (!tracked_anchors_data) {
DVLOG(3) << __func__ << ": tracked_anchors_data is null";
- // We have received a null ptr. Mark tracked_anchors as null & clear stored
- // anchors.
- is_tracked_anchors_null_ = true;
+ // We have received a nullptr. Clear stored anchors.
+ // The device can send either null or empty data - in both cases, it means
+ // that there are no anchors available.
anchor_ids_to_anchors_.clear();
return;
}
@@ -1034,8 +1036,6 @@ void XRSession::ProcessAnchorsData(
<< ", all anchors size="
<< tracked_anchors_data->all_anchors_ids.size();
- is_tracked_anchors_null_ = false;
-
HeapHashMap<uint64_t, Member<XRAnchor>> updated_anchors;
// First, process all anchors that had their information updated (new anchors
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 17815124577..83e74bdb219 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.h
@@ -509,7 +509,6 @@ class XRSession final
// |anchor_ids_to_pending_anchor_promises_|, and anchors that got created in
// phase 3 live in |anchor_ids_to_anchors_|.
- bool is_tracked_anchors_null_ = true;
HeapHashMap<uint64_t, Member<XRAnchor>> anchor_ids_to_anchors_;
// Set of promises returned from CreateAnchor that are still in-flight to the
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_session_viewport_scaler.cc b/chromium/third_party/blink/renderer/modules/xr/xr_session_viewport_scaler.cc
index 50d8f6da556..98bda6e52eb 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session_viewport_scaler.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session_viewport_scaler.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include <cmath>
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
namespace blink {
@@ -48,8 +48,8 @@ void XRSessionViewportScaler::ResetLoad() {
}
void XRSessionViewportScaler::UpdateRenderingTimeRatio(float new_value) {
- gpu_load_ += base::ClampToRange(kLoadDecay * (new_value - gpu_load_),
- -kMaxChange, kMaxChange);
+ gpu_load_ += base::clamp(kLoadDecay * (new_value - gpu_load_), -kMaxChange,
+ kMaxChange);
float old_scale = scale_;
if (gpu_load_ > kLoadHigh && scale_ > kMinScale) {
scale_ *= kScaleStep;
@@ -58,7 +58,7 @@ void XRSessionViewportScaler::UpdateRenderingTimeRatio(float new_value) {
scale_ /= kScaleStep;
scale_ = round(scale_ * kRound) / kRound;
}
- scale_ = base::ClampToRange(scale_, kMinScale, kMaxScale);
+ scale_ = base::clamp(scale_, kMinScale, kMaxScale);
if (scale_ != old_scale) {
ResetLoad();
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_space.cc b/chromium/third_party/blink/renderer/modules/xr/xr_space.cc
index 05a7e1635a9..a740dfe5ce2 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_space.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/xr/xr_space.h"
-#include "base/stl_util.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
#include "third_party/blink/renderer/modules/xr/xr_pose.h"
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_system.cc b/chromium/third_party/blink/renderer/modules/xr/xr_system.cc
index f8eebc0ce7d..3e35217c987 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_system.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_system.cc
@@ -121,9 +121,6 @@ const char* SessionModeToString(device::mojom::blink::XRSessionMode mode) {
return "";
}
-// TODO(crbug.com/1070871): Drop this #if-else
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY)
-
device::mojom::XRDepthUsage ParseDepthUsage(const V8XRDepthUsage& usage) {
switch (usage.AsEnum()) {
case V8XRDepthUsage::Enum::kCpuOptimized:
@@ -163,52 +160,6 @@ Vector<device::mojom::XRDepthDataFormat> ParseDepthFormats(
return result;
}
-#else
-
-device::mojom::XRDepthUsage ParseDepthUsage(const String& usage) {
- if (usage == "cpu-optimized") {
- return device::mojom::XRDepthUsage::kCPUOptimized;
- } else if (usage == "gpu-optimized") {
- return device::mojom::XRDepthUsage::kGPUOptimized;
- }
-
- NOTREACHED() << "Only strings in the enum are allowed by IDL";
- return device::mojom::XRDepthUsage::kCPUOptimized;
-}
-
-Vector<device::mojom::XRDepthUsage> ParseDepthUsages(
- const Vector<String>& usages) {
- Vector<device::mojom::XRDepthUsage> result;
-
- std::transform(usages.begin(), usages.end(), std::back_inserter(result),
- ParseDepthUsage);
-
- return result;
-}
-
-device::mojom::XRDepthDataFormat ParseDepthFormat(const String& format) {
- if (format == "luminance-alpha") {
- return device::mojom::XRDepthDataFormat::kLuminanceAlpha;
- } else if (format == "float32") {
- return device::mojom::XRDepthDataFormat::kFloat32;
- }
-
- NOTREACHED() << "Only strings in the enum are allowed by IDL";
- return device::mojom::XRDepthDataFormat::kLuminanceAlpha;
-}
-
-Vector<device::mojom::XRDepthDataFormat> ParseDepthFormats(
- const Vector<String>& formats) {
- Vector<device::mojom::XRDepthDataFormat> result;
-
- std::transform(formats.begin(), formats.end(), std::back_inserter(result),
- ParseDepthFormat);
-
- return result;
-}
-
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_DICTIONARY
-
// Converts the given string to an XRSessionFeature. If the string is
// unrecognized, returns nullopt. Based on the spec:
// https://immersive-web.github.io/webxr/#feature-name
@@ -1027,6 +978,23 @@ ScriptPromise XRSystem::InternalIsSessionSupported(
return promise;
}
+void XRSystem::RequestSessionInternal(
+ device::mojom::blink::XRSessionMode session_mode,
+ PendingRequestSessionQuery* query,
+ ExceptionState* exception_state) {
+ // The various session request methods may have other checks that would reject
+ // before needing to create the vr service, so we don't try to create it here.
+ switch (session_mode) {
+ case device::mojom::blink::XRSessionMode::kImmersiveVr:
+ case device::mojom::blink::XRSessionMode::kImmersiveAr:
+ RequestImmersiveSession(query, exception_state);
+ break;
+ case device::mojom::blink::XRSessionMode::kInline:
+ RequestInlineSession(query, exception_state);
+ break;
+ }
+}
+
void XRSystem::RequestImmersiveSession(PendingRequestSessionQuery* query,
ExceptionState* exception_state) {
DVLOG(2) << __func__;
@@ -1382,18 +1350,17 @@ ScriptPromise XRSystem::requestSession(ScriptState* script_state,
query->SetDepthSensingConfiguration(preferred_usage, preferred_format);
}
- // The various session request methods may have other checks that would reject
- // before needing to create the vr service, so we don't try to create it here.
- switch (session_mode) {
- case device::mojom::blink::XRSessionMode::kImmersiveVr:
- case device::mojom::blink::XRSessionMode::kImmersiveAr:
- RequestImmersiveSession(query, &exception_state);
- break;
- case device::mojom::blink::XRSessionMode::kInline:
- RequestInlineSession(query, &exception_state);
- break;
+ // Defer to request the session until the prerendering page is activated.
+ if (DomWindow()->document()->IsPrerendering()) {
+ // Pass a nullptr instead of |exception_state| because we can't guarantee
+ // this object is alive until the prerendering page is activate.
+ DomWindow()->document()->AddPostPrerenderingActivationStep(WTF::Bind(
+ &XRSystem::RequestSessionInternal, WrapWeakPersistent(this),
+ session_mode, WrapPersistent(query), /*exception_state=*/nullptr));
+ return promise;
}
+ RequestSessionInternal(session_mode, query, &exception_state);
return promise;
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_system.h b/chromium/third_party/blink/renderer/modules/xr/xr_system.h
index d4af864988c..c003219cecc 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_system.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_system.h
@@ -350,6 +350,10 @@ class XRSystem final : public EventTargetWithInlineData,
XRSessionInit* session_init,
mojom::ConsoleMessageLevel error_level);
+ void RequestSessionInternal(device::mojom::blink::XRSessionMode session_mode,
+ PendingRequestSessionQuery* query,
+ ExceptionState* exception_state);
+
void RequestImmersiveSession(PendingRequestSessionQuery* query,
ExceptionState* exception_state);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc b/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc
index 53a4cc4e829..c521022f0fe 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc
@@ -52,7 +52,10 @@ bool XRTargetRaySpace::EmulatedPosition() const {
device::mojom::blink::XRNativeOriginInformationPtr
XRTargetRaySpace::NativeOrigin() const {
- return input_source_->nativeOrigin();
+ return device::mojom::blink::XRNativeOriginInformation::
+ NewInputSourceSpaceInfo(device::mojom::blink::XRInputSourceSpaceInfo::New(
+ input_source_->source_id(),
+ device::mojom::blink::XRInputSourceSpaceType::kTargetRay));
}
std::string XRTargetRaySpace::ToString() const {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_utils.cc b/chromium/third_party/blink/renderer/modules/xr/xr_utils.cc
index f650f390cf0..c5d768cda6f 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_utils.cc
@@ -10,7 +10,6 @@
#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
#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_webgl_rendering_context.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
namespace blink {
@@ -67,7 +66,6 @@ DOMPointReadOnly* makeNormalizedQuaternion(double x,
w / length);
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebGLRenderingContextBase* webglRenderingContextBaseFromUnion(
const V8XRWebGLRenderingContext* context) {
DCHECK(context);
@@ -80,16 +78,6 @@ WebGLRenderingContextBase* webglRenderingContextBaseFromUnion(
NOTREACHED();
return nullptr;
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WebGLRenderingContextBase* webglRenderingContextBaseFromUnion(
- const XRWebGLRenderingContext& context) {
- if (context.IsWebGL2RenderingContext()) {
- return context.GetAsWebGL2RenderingContext();
- } else {
- return context.GetAsWebGLRenderingContext();
- }
-}
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
absl::optional<device::Pose> CreatePose(
const blink::TransformationMatrix& matrix) {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_utils.h b/chromium/third_party/blink/renderer/modules/xr/xr_utils.h
index fd088c11e58..f45428cf008 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_utils.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_utils.h
@@ -7,9 +7,9 @@
#include "device/vr/public/mojom/pose.h"
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
-#include "third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -31,13 +31,8 @@ DOMPointReadOnly* makeNormalizedQuaternion(double x,
double z,
double w);
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WebGLRenderingContextBase* webglRenderingContextBaseFromUnion(
const V8XRWebGLRenderingContext* context);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-WebGLRenderingContextBase* webglRenderingContextBaseFromUnion(
- const XRWebGLRenderingContext&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
constexpr char kUnableToNormalizeZeroLength[] =
"Unable to normalize vector of length 0.";
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 547d648672c..965e0055fc1 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 "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/modules/xr/xr_camera.h"
#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
@@ -190,6 +190,9 @@ XRCamera* XRView::camera() const {
frame_->session()->mode() ==
device::mojom::blink::XRSessionMode::kImmersiveAr;
+ DVLOG(3) << __func__ << ": camera_access_enabled=" << camera_access_enabled
+ << ", is_immersive_ar_session=" << is_immersive_ar_session;
+
if (camera_access_enabled && is_immersive_ar_session) {
// The feature is enabled and we're in immersive-ar session, so let's return
// a camera object if the camera image was received in the current frame.
@@ -223,8 +226,7 @@ void XRViewData::requestViewportScale(absl::optional<double> scale) {
if (!scale)
return;
- requested_viewport_scale_ =
- base::ClampToRange(*scale, kMinViewportScale, 1.0);
+ requested_viewport_scale_ = base::clamp(*scale, kMinViewportScale, 1.0);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.cc b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.cc
index a870e038685..a29bb2cc413 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.cc
@@ -17,18 +17,13 @@
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
#include "third_party/blink/renderer/modules/xr/xr_viewer_pose.h"
#include "third_party/blink/renderer/modules/xr/xr_webgl_layer.h"
-#include "third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
namespace blink {
XRWebGLBinding* XRWebGLBinding::Create(XRSession* session,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8XRWebGLRenderingContext* context,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const XRWebGLRenderingContext& context,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
ExceptionState& exception_state) {
if (session->ended()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
@@ -62,13 +57,8 @@ XRWebGLBinding* XRWebGLBinding::Create(XRSession* session,
return nullptr;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
return MakeGarbageCollected<XRWebGLBinding>(
session, webgl_context, context->IsWebGL2RenderingContext());
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- return MakeGarbageCollected<XRWebGLBinding>(
- session, webgl_context, context.IsWebGL2RenderingContext());
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
}
XRWebGLBinding::XRWebGLBinding(XRSession* session,
@@ -159,6 +149,8 @@ WebGLTexture* XRWebGLBinding::getReflectionCubeMap(
WebGLTexture* XRWebGLBinding::getCameraImage(XRCamera* camera,
ExceptionState& exception_state) {
+ DVLOG(3) << __func__;
+
XRFrame* frame = camera->Frame();
DCHECK(frame);
@@ -198,20 +190,8 @@ WebGLTexture* XRWebGLBinding::getCameraImage(XRCamera* camera,
XRWebGLLayer* base_layer = session->renderState()->baseLayer();
DCHECK(base_layer);
- absl::optional<gpu::MailboxHolder> camera_image_mailbox_holder =
- base_layer->CameraImageMailboxHolder();
-
- if (!camera_image_mailbox_holder) {
- DVLOG(3) << __func__ << ": camera image mailbox holder is not set";
- return nullptr;
- }
-
- GLuint texture_id = base_layer->CameraImageTextureId();
-
// This resource is owned by the XRWebGLLayer, and is freed in OnFrameEnd();
- WebGLUnownedTexture* texture = MakeGarbageCollected<WebGLUnownedTexture>(
- webgl_context_, texture_id, GL_TEXTURE_2D);
- return texture;
+ return base_layer->GetCameraTexture();
}
XRWebGLDepthInformation* XRWebGLBinding::getDepthInformation(
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.h b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.h
index a7548c81366..694d53a9a83 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_binding.h
@@ -7,7 +7,6 @@
#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_webgl_rendering_context.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
@@ -28,15 +27,9 @@ class XRWebGLBinding final : public ScriptWrappable {
XRWebGLBinding(XRSession*, WebGLRenderingContextBase*, bool webgl2);
~XRWebGLBinding() override = default;
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
static XRWebGLBinding* Create(XRSession* session,
const V8XRWebGLRenderingContext* context,
ExceptionState& exception_state);
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- static XRWebGLBinding* Create(XRSession*,
- const XRWebGLRenderingContext&,
- ExceptionState&);
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
XRSession* session() const { return session_; }
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 1605e2af509..c4d5c12aa88 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,7 +4,7 @@
#include "third_party/blink/renderer/modules/xr/xr_webgl_layer.h"
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "base/numerics/safe_conversions.h"
#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -18,7 +18,6 @@
#include "third_party/blink/renderer/modules/xr/xr_utils.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/modules/xr/xr_webgl_rendering_context.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"
@@ -41,11 +40,7 @@ const char kCleanFrameWarning[] =
} // namespace
XRWebGLLayer* XRWebGLLayer::Create(XRSession* session,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8XRWebGLRenderingContext* context,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const XRWebGLRenderingContext& context,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const XRWebGLLayerInit* initializer,
ExceptionState& exception_state) {
if (session->ended()) {
@@ -120,8 +115,8 @@ XRWebGLLayer* XRWebGLLayer::Create(XRSession* session,
// small to see or unreasonably large.
// TODO: Would be best to have the max value communicated from the service
// rather than limited to the native res.
- framebuffer_scale = base::ClampToRange(
- initializer->framebufferScaleFactor(), kFramebufferMinScale, max_scale);
+ framebuffer_scale = base::clamp(initializer->framebufferScaleFactor(),
+ kFramebufferMinScale, max_scale);
}
DoubleSize framebuffers_size = session->DefaultFramebufferSize();
@@ -295,13 +290,25 @@ HTMLCanvasElement* XRWebGLLayer::output_canvas() const {
return nullptr;
}
-uint32_t XRWebGLLayer::CameraImageTextureId() const {
- return camera_image_texture_id_;
-}
+WebGLTexture* XRWebGLLayer::GetCameraTexture() {
+ DVLOG(1) << __func__;
+
+ // We already have a WebGL texture for the camera image - return it:
+ if (camera_image_texture_) {
+ return camera_image_texture_;
+ }
+
+ // We don't have a WebGL texture, and we cannot create it - return null:
+ if (!camera_image_texture_id_) {
+ return nullptr;
+ }
-absl::optional<gpu::MailboxHolder> XRWebGLLayer::CameraImageMailboxHolder()
- const {
- return camera_image_mailbox_holder_;
+ // We don't have a WebGL texture, but we can create it, so create, store and
+ // return it:
+ camera_image_texture_ = MakeGarbageCollected<WebGLUnownedTexture>(
+ webgl_context_, camera_image_texture_id_, GL_TEXTURE_2D);
+
+ return camera_image_texture_;
}
void XRWebGLLayer::OnFrameStart(
@@ -325,7 +332,9 @@ void XRWebGLLayer::OnFrameStart(
camera_image_mailbox_holder_ = camera_image_mailbox_holder;
camera_image_texture_id_ =
GetBufferTextureId(camera_image_mailbox_holder_);
- BindBufferTexture(camera_image_mailbox_holder_);
+ DVLOG(3) << __func__
+ << ": camera_image_texture_id_=" << camera_image_texture_id_;
+ BindCameraBufferTexture(camera_image_mailbox_holder_);
}
}
}
@@ -338,10 +347,11 @@ uint32_t XRWebGLLayer::GetBufferTextureId(
<< buffer_mailbox_holder->sync_token.ToDebugString();
GLuint texture_id = gl->CreateAndTexStorage2DSharedImageCHROMIUM(
buffer_mailbox_holder->mailbox.name);
+ DVLOG(3) << __func__ << ": texture_id=" << texture_id;
return texture_id;
}
-void XRWebGLLayer::BindBufferTexture(
+void XRWebGLLayer::BindCameraBufferTexture(
const absl::optional<gpu::MailboxHolder>& buffer_mailbox_holder) {
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
@@ -390,10 +400,23 @@ void XRWebGLLayer::OnFrameEnd() {
session()->xr()->frameProvider()->SubmitWebGLLayer(this,
framebuffer_dirty);
if (camera_image_mailbox_holder_ && camera_image_texture_id_) {
- DVLOG(3) << __func__ << "Deleting camera image texture";
+ DVLOG(3) << __func__
+ << ": deleting camera image texture, camera_image_texture_id_="
+ << camera_image_texture_id_;
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
+
gl->EndSharedImageAccessDirectCHROMIUM(camera_image_texture_id_);
gl->DeleteTextures(1, &camera_image_texture_id_);
+
+ // Notify our WebGLUnownedTexture (created from
+ // camera_image_texture_id_) that we have deleted it. Also, release the
+ // reference since we no longer need it (note that it could still be
+ // kept alive by the JS application, but should be a defunct object).
+ if (camera_image_texture_) {
+ camera_image_texture_->OnGLDeleteTextures();
+ camera_image_texture_ = nullptr;
+ }
+
camera_image_texture_id_ = 0;
camera_image_mailbox_holder_ = absl::nullopt;
}
@@ -429,6 +452,7 @@ void XRWebGLLayer::Trace(Visitor* visitor) const {
visitor->Trace(right_viewport_);
visitor->Trace(webgl_context_);
visitor->Trace(framebuffer_);
+ visitor->Trace(camera_image_texture_);
XRLayer::Trace(visitor);
}
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 01ef2297f8b..23a954d94ae 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
@@ -10,10 +10,10 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_xr_webgl_layer_init.h"
#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/webgl/webgl_unowned_texture.h"
#include "third_party/blink/renderer/modules/xr/xr_layer.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
#include "third_party/blink/renderer/modules/xr/xr_view.h"
-#include "third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -40,11 +40,7 @@ class XRWebGLLayer final : public XRLayer {
~XRWebGLLayer() override;
static XRWebGLLayer* Create(XRSession*,
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const V8XRWebGLRenderingContext*,
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
- const XRWebGLRenderingContext&,
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
const XRWebGLLayerInit*,
ExceptionState&);
@@ -66,8 +62,15 @@ class XRWebGLLayer final : public XRLayer {
void UpdateViewports();
HTMLCanvasElement* output_canvas() const;
- uint32_t CameraImageTextureId() const;
- absl::optional<gpu::MailboxHolder> CameraImageMailboxHolder() const;
+
+ // Returns WebGLTexture (actually a WebGLUnownedTexture instance)
+ // corresponding to the camera image.
+ // The texture is owned by the XRWebGLLayer and will be freed in OnFrameEnd().
+ // When the texture is deleted by the layer, the returned object will have its
+ // texture name set to 0 to avoid using stale texture names in case the user
+ // code still holds references to this object.
+ // The consumers should not attempt to delete the texture themselves.
+ WebGLTexture* GetCameraTexture();
void OnFrameStart(
const absl::optional<gpu::MailboxHolder>& buffer_mailbox_holder,
@@ -87,7 +90,7 @@ class XRWebGLLayer final : public XRLayer {
uint32_t GetBufferTextureId(
const absl::optional<gpu::MailboxHolder>& buffer_mailbox_holder);
- void BindBufferTexture(
+ void BindCameraBufferTexture(
const absl::optional<gpu::MailboxHolder>& buffer_mailbox_holder);
Member<XRViewport> left_viewport_;
@@ -105,6 +108,11 @@ class XRWebGLLayer final : public XRLayer {
uint32_t clean_frame_count = 0;
uint32_t camera_image_texture_id_;
+ // WebGL texture that points to the |camera_image_texture_|. Must be notified
+ // via a call to |WebGLUnownedTexture::OnGLDeleteTextures()| when
+ // |camera_image_texture_id_| is deleted.
+ Member<WebGLUnownedTexture> camera_image_texture_;
+
absl::optional<gpu::MailboxHolder> camera_image_mailbox_holder_;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h
deleted file mode 100644
index cbf8b7aa788..00000000000
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_rendering_context.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_WEBGL_RENDERING_CONTEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_WEBGL_RENDERING_CONTEXT_H_
-
-#include "third_party/blink/renderer/bindings/modules/v8/webgl_rendering_context_or_webgl2_rendering_context.h"
-
-namespace blink {
-
-using XRWebGLRenderingContext = WebGLRenderingContextOrWebGL2RenderingContext;
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_WEBGL_RENDERING_CONTEXT_H_
diff --git a/chromium/third_party/blink/renderer/platform/BUILD.gn b/chromium/third_party/blink/renderer/platform/BUILD.gn
index 5cf25d7f4d4..50ce68c7928 100644
--- a/chromium/third_party/blink/renderer/platform/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/BUILD.gn
@@ -132,9 +132,6 @@ config("blink_platform_config") {
"//third_party/blink/renderer:config",
"//third_party/blink/renderer:inside_blink",
"//build/config/compiler:noshadowing",
-
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- "//build/config/compiler:no_size_t_to_int_warning",
]
}
@@ -253,7 +250,6 @@ source_set("platform_export") {
component("platform") {
visibility = [] # Allow re-assignment of list.
visibility = [
- "//components/pdf/common:interfaces_blink",
"//services/device/public/mojom:mojom_blink",
"//services/media_session/public/mojom:mojom_blink",
"//third_party/blink/*",
@@ -266,7 +262,6 @@ component("platform") {
sources = [
"animation/animation_translation_util.cc",
"animation/animation_translation_util.h",
- "animation/animation_utilities.h",
"animation/compositor_animation.cc",
"animation/compositor_animation.h",
"animation/compositor_animation_client.cc",
@@ -416,6 +411,7 @@ component("platform") {
"bindings/callback_method_retriever.cc",
"bindings/callback_method_retriever.h",
"bindings/custom_wrappable.h",
+ "bindings/dictionary_base.cc",
"bindings/dictionary_base.h",
"bindings/dom_data_store.cc",
"bindings/dom_data_store.h",
@@ -472,6 +468,7 @@ component("platform") {
"bindings/v8_dom_wrapper.h",
"bindings/v8_global_value_map.h",
"bindings/v8_interface_bridge.h",
+ "bindings/v8_interface_bridge_base.cc",
"bindings/v8_interface_bridge_base.h",
"bindings/v8_object_constructor.cc",
"bindings/v8_object_constructor.h",
@@ -540,7 +537,6 @@ component("platform") {
"exported/web_font.cc",
"exported/web_font_description.cc",
"exported/web_http_body.cc",
- "exported/web_http_load_info.cc",
"exported/web_icon_sizes_parser.cc",
"exported/web_image_generator.cc",
"exported/web_media_player_client.cc",
@@ -619,6 +615,8 @@ component("platform") {
"fonts/font_optical_sizing.h",
"fonts/font_orientation.cc",
"fonts/font_orientation.h",
+ "fonts/font_performance.cc",
+ "fonts/font_performance.h",
"fonts/font_platform_data.cc",
"fonts/font_platform_data.h",
"fonts/font_selection_algorithm.cc",
@@ -842,6 +840,8 @@ component("platform") {
"graphics/compositing/paint_artifact_compositor.h",
"graphics/compositing/paint_chunks_to_cc_layer.cc",
"graphics/compositing/paint_chunks_to_cc_layer.h",
+ "graphics/compositing/pending_layer.cc",
+ "graphics/compositing/pending_layer.h",
"graphics/compositing/property_tree_manager.cc",
"graphics/compositing/property_tree_manager.h",
"graphics/compositing_reasons.cc",
@@ -989,8 +989,6 @@ component("platform") {
"graphics/graphics_types.cc",
"graphics/graphics_types.h",
"graphics/graphics_types_3d.h",
- "graphics/identifiability_paint_op_digest.cc",
- "graphics/identifiability_paint_op_digest.h",
"graphics/image.cc",
"graphics/image.h",
"graphics/image_data_buffer.cc",
@@ -1081,6 +1079,8 @@ component("platform") {
"graphics/paint/paint_record_builder.h",
"graphics/paint/paint_recorder.h",
"graphics/paint/paint_shader.h",
+ "graphics/paint/paint_under_invalidation_checker.cc",
+ "graphics/paint/paint_under_invalidation_checker.h",
"graphics/paint/painted_selection_bound.h",
"graphics/paint/property_tree_state.cc",
"graphics/paint/property_tree_state.h",
@@ -1090,6 +1090,7 @@ component("platform") {
"graphics/paint/raster_invalidator.h",
"graphics/paint/ref_counted_property_tree_state.h",
"graphics/paint/scoped_display_item_fragment.h",
+ "graphics/paint/scoped_effectively_invisible.h",
"graphics/paint/scoped_paint_chunk_hint.h",
"graphics/paint/scoped_paint_chunk_properties.h",
"graphics/paint/scroll_paint_property_node.cc",
@@ -1160,12 +1161,18 @@ component("platform") {
"graphics/video_frame_image_util.h",
"graphics/video_frame_resource_provider.cc",
"graphics/video_frame_resource_provider.h",
+ "graphics/video_frame_sink_bundle.cc",
+ "graphics/video_frame_sink_bundle.h",
"graphics/video_frame_submitter.cc",
"graphics/video_frame_submitter.h",
+ "graphics/viz_util.cc",
+ "graphics/viz_util.h",
"graphics/web_graphics_context_3d_provider_util.cc",
"graphics/web_graphics_context_3d_provider_util.h",
"graphics/web_graphics_context_3d_provider_wrapper.cc",
"graphics/web_graphics_context_3d_provider_wrapper.h",
+ "graphics/web_graphics_context_3d_video_frame_pool.cc",
+ "graphics/web_graphics_context_3d_video_frame_pool.h",
"heap_observer_set.h",
"image-decoders/bmp/bmp_image_decoder.cc",
"image-decoders/bmp/bmp_image_decoder.h",
@@ -1346,8 +1353,6 @@ component("platform") {
"peerconnection/rtc_video_encoder_factory.cc",
"peerconnection/rtc_video_encoder_factory.h",
"peerconnection/rtc_void_request.h",
- "peerconnection/transmission_encoding_info_handler.cc",
- "peerconnection/transmission_encoding_info_handler.h",
"peerconnection/two_keys_adapter_map.h",
"peerconnection/video_codec_factory.cc",
"peerconnection/video_codec_factory.h",
@@ -1355,6 +1360,9 @@ component("platform") {
"peerconnection/webrtc_audio_sink.h",
"peerconnection/webrtc_decoding_info_handler.cc",
"peerconnection/webrtc_decoding_info_handler.h",
+ "peerconnection/webrtc_encoding_info_handler.cc",
+ "peerconnection/webrtc_encoding_info_handler.h",
+ "peerconnection/webrtc_util.cc",
"peerconnection/webrtc_util.h",
"peerconnection/webrtc_video_track_source.cc",
"peerconnection/webrtc_video_track_source.h",
@@ -1363,6 +1371,9 @@ component("platform") {
"resolution_units.h",
"search_engine_utils.cc",
"search_engine_utils.h",
+ "storage/blink_storage_key.cc",
+ "storage/blink_storage_key.h",
+ "storage/blink_storage_key_mojom_traits.cc",
"supplementable.cc",
"supplementable.h",
"text/bidi_character_run.h",
@@ -1470,6 +1481,7 @@ component("platform") {
"weborigin/kurl_hash.h",
"weborigin/origin_access_entry.cc",
"weborigin/origin_access_entry.h",
+ "weborigin/referrer.cc",
"weborigin/referrer.h",
"weborigin/reporting_disposition.h",
"weborigin/scheme_registry.cc",
@@ -1481,8 +1493,6 @@ component("platform") {
"weborigin/security_policy.h",
"webrtc/convert_to_webrtc_video_frame_buffer.cc",
"webrtc/convert_to_webrtc_video_frame_buffer.h",
- "webrtc/legacy_webrtc_video_frame_adapter.cc",
- "webrtc/legacy_webrtc_video_frame_adapter.h",
"webrtc/peer_connection_remote_audio_source.cc",
"webrtc/peer_connection_remote_audio_source.h",
"webrtc/track_observer.cc",
@@ -1585,8 +1595,6 @@ component("platform") {
"mac/color_mac.mm",
"mac/graphics_context_canvas.h",
"mac/graphics_context_canvas.mm",
- "mac/local_current_graphics_context.h",
- "mac/local_current_graphics_context.mm",
"mac/web_core_ns_cell_extras.h",
"mac/web_core_ns_cell_extras.mm",
"text/locale_mac.h",
@@ -1663,6 +1671,7 @@ component("platform") {
deps = [
"//base:base_static",
"//base/allocator:buildflags",
+ "//build:chromecast_buildflags",
"//build:chromeos_buildflags",
"//cc/ipc",
"//cc/mojo_embedder",
@@ -1680,6 +1689,7 @@ component("platform") {
"//media",
"//media/capture:capture_switches",
"//media/capture/mojom:video_capture",
+ "//media/webrtc:webrtc",
"//mojo/public/cpp/bindings:wtf_support",
"//services/metrics/public/cpp:ukm_builders",
"//services/network/public/mojom:mojom_shared",
@@ -1859,7 +1869,9 @@ static_library("test_support") {
"graphics/test/gpu_test_utils.cc",
"graphics/test/gpu_test_utils.h",
"graphics/test/mock_compositor_frame_sink.h",
+ "graphics/test/mock_compositor_frame_sink_client.h",
"graphics/test/mock_embedded_frame_sink_provider.h",
+ "graphics/test/mock_frame_sink_bundle.h",
"graphics/test/mock_image_decoder.h",
"graphics/test/mock_paint_canvas.h",
"testing/code_cache_loader_mock.cc",
@@ -1882,6 +1894,8 @@ static_library("test_support") {
"testing/layer_tree_host_embedder.h",
"testing/message_loop_for_mojo.h",
"testing/mock_context_lifecycle_notifier.h",
+ "testing/noop_web_url_loader.cc",
+ "testing/noop_web_url_loader.h",
"testing/paint_property_test_helpers.h",
"testing/paint_test_configurations.h",
"testing/picture_matchers.cc",
@@ -1938,6 +1952,7 @@ static_library("test_support") {
"//third_party/blink/renderer/platform/blob:test_support",
"//third_party/blink/renderer/platform/heap:test_support",
"//third_party/blink/renderer/platform/loader:test_support",
+ "//third_party/blink/renderer/platform/media:test_support",
"//third_party/blink/renderer/platform/scheduler:test_support",
]
@@ -1969,6 +1984,12 @@ test("blink_platform_unittests") {
additional_manifest_fragments =
[ "//build/config/fuchsia/test/jit_capabilities.test-cmx" ]
}
+
+ if (is_android) {
+ # Required because of an indirect dependency on //media/base/android via
+ # platform/media:unit_tests.
+ deps += [ "//media/base/android:media_java" ]
+ }
}
source_set("blink_platform_unittests_sources") {
@@ -2055,6 +2076,7 @@ source_set("blink_platform_unittests_sources") {
"graphics/compositing/chunk_to_layer_mapper_test.cc",
"graphics/compositing/paint_artifact_compositor_test.cc",
"graphics/compositing/paint_chunks_to_cc_layer_test.cc",
+ "graphics/compositing/pending_layer_test.cc",
"graphics/compositor_element_id_test.cc",
"graphics/dark_mode_color_classifier_test.cc",
"graphics/dark_mode_filter_test.cc",
@@ -2072,7 +2094,6 @@ source_set("blink_platform_unittests_sources") {
"graphics/gpu/webgpu_resource_provider_cache_test.cc",
"graphics/gpu/webgpu_swap_buffer_provider_test.cc",
"graphics/graphics_context_test.cc",
- "graphics/identifiability_paint_op_digest_unittest.cc",
"graphics/paint/cull_rect_test.cc",
"graphics/paint/display_item_client_test.cc",
"graphics/paint/display_item_raster_invalidator_test.cc",
@@ -2087,6 +2108,7 @@ source_set("blink_platform_unittests_sources") {
"graphics/paint/paint_controller_test.cc",
"graphics/paint/paint_property_node_test.cc",
"graphics/paint/paint_record_builder_test.cc",
+ "graphics/paint/paint_under_invalidation_checker_test.cc",
"graphics/paint/raster_invalidator_test.cc",
"graphics/paint/scrollbar_display_item_test.cc",
"graphics/paint_invalidation_reason_test.cc",
@@ -2096,6 +2118,7 @@ source_set("blink_platform_unittests_sources") {
"graphics/raster_dark_mode_filter_impl_test.cc",
"graphics/rw_buffer_test.cc",
"graphics/video_frame_image_util_test.cc",
+ "graphics/video_frame_sink_bundle_test.cc",
"graphics/video_frame_submitter_test.cc",
"heap_observer_set_test.cc",
"image-decoders/bmp/bmp_image_decoder_test.cc",
@@ -2118,6 +2141,7 @@ source_set("blink_platform_unittests_sources") {
"media/webaudiosourceprovider_impl_test.cc",
"mediastream/media_stream_audio_processor_options_test.cc",
"mediastream/media_stream_audio_test.cc",
+ "mediastream/media_stream_source_test.cc",
"mediastream/webrtc_uma_histograms_test.cc",
"mhtml/mhtml_parser_test.cc",
"mojo/big_string_mojom_traits_test.cc",
@@ -2140,14 +2164,17 @@ source_set("blink_platform_unittests_sources") {
"peerconnection/rtc_stats_test.cc",
"peerconnection/rtc_video_decoder_adapter_test.cc",
"peerconnection/rtc_video_decoder_stream_adapter_test.cc",
+ "peerconnection/rtc_video_encoder_factory_test.cc",
"peerconnection/rtc_video_encoder_test.cc",
"peerconnection/task_queue_factory_test.cc",
- "peerconnection/transmission_encoding_info_handler_test.cc",
"peerconnection/two_keys_adapter_map_unittest.cc",
"peerconnection/webrtc_audio_sink_test.cc",
"peerconnection/webrtc_decoding_info_handler_test.cc",
+ "peerconnection/webrtc_encoding_info_handler_test.cc",
"peerconnection/webrtc_video_track_source_test.cc",
"runtime_enabled_features_test.cc",
+ "storage/blink_storage_key_mojom_traits_test.cc",
+ "storage/blink_storage_key_test.cc",
"text/bidi_resolver_test.cc",
"text/bidi_test_harness.h",
"text/capitalize_test.cc",
@@ -2160,7 +2187,6 @@ source_set("blink_platform_unittests_sources") {
"text/platform_locale_test.cc",
"text/segmented_string_test.cc",
"text/suffix_tree_test.cc",
- "text/text_boundaries_test.cc",
"text/text_break_iterator_test.cc",
"text/text_encoding_detector_test.cc",
"text/text_run_test.cc",
@@ -2182,7 +2208,6 @@ source_set("blink_platform_unittests_sources") {
"weborigin/security_origin_test.cc",
"weborigin/security_policy_test.cc",
"webrtc/convert_to_webrtc_video_frame_buffer_test.cc",
- "webrtc/legacy_webrtc_video_frame_adapter_test.cc",
"webrtc/webrtc_video_frame_adapter_test.cc",
"widget/compositing/layer_tree_settings_unittest.cc",
"widget/compositing/layer_tree_view_unittest.cc",
@@ -2259,6 +2284,7 @@ source_set("blink_platform_unittests_sources") {
"//third_party/blink/renderer/platform/blob:unit_tests",
"//third_party/blink/renderer/platform/instrumentation:unit_tests",
"//third_party/blink/renderer/platform/loader:unit_tests",
+ "//third_party/blink/renderer/platform/media:unit_tests",
"//third_party/blink/renderer/platform/network:unit_tests",
"//third_party/blink/renderer/platform/scheduler:unit_tests",
"//third_party/blink/renderer/platform/wtf",
@@ -2338,8 +2364,6 @@ test("blink_platform_perftests") {
]
configs += [
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- "//build/config/compiler:no_size_t_to_int_warning",
"//third_party/blink/renderer/platform/wtf:wtf_config",
"//third_party/blink/renderer:config",
]
@@ -2583,7 +2607,12 @@ source_set("unit_tests") {
]
deps = [
+ ":platform",
":test_support",
+ "//base",
+ "//base/test:test_support",
+ "//cc",
+ "//components/viz/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/blink/public:test_headers",
diff --git a/chromium/third_party/blink/renderer/platform/DEPS b/chromium/third_party/blink/renderer/platform/DEPS
index 54f414356c4..5076d74f628 100644
--- a/chromium/third_party/blink/renderer/platform/DEPS
+++ b/chromium/third_party/blink/renderer/platform/DEPS
@@ -1,6 +1,7 @@
include_rules = [
# To only allow a subset of base/ in Blink, we explicitly list all
# directories and files instead of writing 'base/'.
+ "+base/allocator/buildflags.h",
"+base/allocator/partition_allocator",
"+base/android/build_info.h",
"+base/atomic_ref_count.h",
@@ -29,12 +30,14 @@ include_rules = [
"+base/metrics/histogram_macros.h",
"+base/metrics/histogram_samples.h",
"+base/metrics/sparse_histogram.h",
+ "+base/no_destructor.h",
"+base/numerics/checked_math.h",
"+base/numerics/safe_conversions.h",
"+base/process/memory.h",
"+base/rand_util.h",
"+base/run_loop.h",
"+base/strings/pattern.h",
+ "+base/strings/string_split.h",
"+base/strings/string_util.h",
"+base/strings/stringprintf.h",
"+base/synchronization/waitable_event.h",
@@ -78,6 +81,9 @@ include_rules = [
"+ui/base/cursor/cursor.h",
"+ui/base/prediction",
"+ui/base/resource/scale_factor.h",
+ "+ui/display/mojom",
+ "+ui/display/screen_info.h",
+ "+ui/display/screen_infos.h",
"+ui/gfx",
"+url",
"+webp",
diff --git a/chromium/third_party/blink/renderer/platform/OWNERS b/chromium/third_party/blink/renderer/platform/OWNERS
index 549b981ef96..c7b8717ffcf 100644
--- a/chromium/third_party/blink/renderer/platform/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/OWNERS
@@ -15,8 +15,6 @@ kojii@chromium.org
mkwst@chromium.org
noel@chromium.org
pdr@chromium.org
-pfeldman@chromium.org
-rtoy@chromium.org
schenney@chromium.org
senorblanco@chromium.org
skyostil@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/PRESUBMIT.py b/chromium/third_party/blink/renderer/platform/PRESUBMIT.py
index fe39215b5b2..c5837562a2e 100644
--- a/chromium/third_party/blink/renderer/platform/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/platform/PRESUBMIT.py
@@ -10,8 +10,42 @@ for more details about the presubmit API built into depot_tools.
import difflib
import os
import re
+import sys
+USE_PYTHON3 = True
RUNTIMEENABLED_NAME = re.compile(r'\s*name\s*:\s*"([^"]*)"')
+CHROMEOS_STATUS = "ChromeOS"
+LACROS_STATUS = "Lacros"
+
+# The ignore list will be removed once existing features adopt parity across
+# Lacros and ChromeOS.
+LACROS_CHROMEOS_FEATURE_STATUS_PARITY_IGNORE_LIST = [
+ 'BarcodeDetector', # crbug.com/1235855
+ 'DigitalGoods', # crbug.com/1235859
+ 'ForceTallerSelectPopup', # crbug.com/1235860
+ 'NetInfoDownlinkMax', # crbug.com/1235864
+ 'WebBluetooth', # crbug.com/1235867
+ 'WebBluetoothManufacturerDataFilter', # crbug.com/1235869
+ 'WebBluetoothRemoteCharacteristicNewWriteValue', # crbug.com/235870
+]
+
+
+# pyright: reportMissingImports=false
+def RuntimeEnabledFeatures(input_api, filename):
+ """Returns the features present in the specified features JSON5 file."""
+
+ # We need to wait until we have an input_api object and use this
+ # roundabout construct to import json5 because this file is
+ # eval-ed and thus doesn't have __file__.
+ try:
+ json5_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
+ '..', '..', '..', 'pyjson5', 'src')
+ sys.path.append(json5_path)
+ import json5
+ return json5.load(open(filename, encoding='utf-8'))['data']
+ finally:
+ # Restore sys.path to what it was before.
+ sys.path.remove(json5_path)
def RuntimeEnabledFeatureNames(filename):
@@ -49,10 +83,45 @@ def _CheckRuntimeEnabledFeaturesSorted(input_api, output_api):
]
+def _CheckLacrosChromeOSFeatureStatusParity(input_api, output_api):
+ """Check: runtime_enabled_features.json5 feature status parity across Lacros
+ and ChromeOS.
+ """
+
+ filename = os.path.join(input_api.PresubmitLocalPath(),
+ 'runtime_enabled_features.json5')
+ try:
+ features = RuntimeEnabledFeatures(input_api, filename)
+ # Check that all features with a status specified for ChromeOS have the
+ # same status specified for Lacros.
+ for feature in features:
+ if feature[
+ 'name'] in LACROS_CHROMEOS_FEATURE_STATUS_PARITY_IGNORE_LIST:
+ continue
+ if 'status' in feature and type(feature['status']) is dict:
+ status_dict = feature['status']
+ if (CHROMEOS_STATUS in status_dict
+ or LACROS_STATUS in status_dict) and (
+ status_dict.get(LACROS_STATUS) !=
+ status_dict.get(CHROMEOS_STATUS)):
+ return [output_api.PresubmitError('Feature {} does not have status parity '\
+ 'across Lacros and ChromeOS.'.format(feature['name']))]
+ except:
+ return [
+ output_api.PresubmitError(
+ 'Failed to parse {} for checks'.format(filename))
+ ]
+
+ return []
+
+
def _CommonChecks(input_api, output_api):
"""Checks common to both upload and commit."""
results = []
results.extend(_CheckRuntimeEnabledFeaturesSorted(input_api, output_api))
+ results.extend(
+ _CheckLacrosChromeOSFeatureStatusParity(input_api, output_api))
+
return results
diff --git a/chromium/third_party/blink/renderer/platform/animation/OWNERS b/chromium/third_party/blink/renderer/platform/animation/OWNERS
index 8a44822b898..a7d6872245b 100644
--- a/chromium/third_party/blink/renderer/platform/animation/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/animation/OWNERS
@@ -1,3 +1 @@
file://third_party/blink/renderer/core/animation/OWNERS
-
-loyso@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/animation/animation_utilities.h b/chromium/third_party/blink/renderer/platform/animation/animation_utilities.h
deleted file mode 100644
index 07cdcb97448..00000000000
--- a/chromium/third_party/blink/renderer/platform/animation/animation_utilities.h
+++ /dev/null
@@ -1,49 +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 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_ANIMATION_ANIMATION_UTILITIES_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_ANIMATION_UTILITIES_H_
-
-#include "third_party/blink/renderer/platform/geometry/blend.h"
-#include "ui/gfx/geometry/cubic_bezier.h"
-
-namespace blink {
-
-// Calculates the accuracy for evaluating a timing function for an animation
-// with the specified duration.
-inline double AccuracyForDuration(double duration) {
- double default_epsilon = gfx::CubicBezier::GetDefaultEpsilon();
- if (duration == 0) {
- return default_epsilon;
- }
- double accuracy = 1.0 / (200.0 * duration);
- // Avoid min()/max() from std here in the header, because that would require
- // inclusion of <algorithm>, which is slow to compile.
- return accuracy > default_epsilon ? accuracy : default_epsilon;
-}
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_ANIMATION_UTILITIES_H_
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 5a2f9901950..9a05eb41c66 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_delegate.h"
@@ -38,6 +37,8 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
std::unique_ptr<cc::AnimationEffectTimings> effect_timings);
explicit CompositorAnimation(scoped_refptr<cc::Animation>);
+ CompositorAnimation(const CompositorAnimation&) = delete;
+ CompositorAnimation& operator=(const CompositorAnimation&) = delete;
~CompositorAnimation() override;
cc::Animation* CcAnimation() const;
@@ -87,8 +88,6 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
scoped_refptr<cc::Animation> animation_;
CompositorAnimationDelegate* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorAnimation);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_delegate.h b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_delegate.h
index 4af75238ef0..72515ab4671 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_delegate.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_delegate.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "ui/gfx/animation/keyframe/animation_curve.h"
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc
index 25a9e0b34ae..fcf3c62e3c5 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc
@@ -66,7 +66,9 @@ TEST_F(CompositorAnimationTest, NullDelegate) {
auto curve = std::make_unique<CompositorFloatAnimationCurve>();
auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, compositor_target_property::TRANSFORM, 0, 1);
+ *curve, 0, 1,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::TRANSFORM));
int keyframe_model_id = keyframe_model->Id();
animation->AddKeyframeModel(std::move(keyframe_model));
@@ -99,7 +101,9 @@ TEST_F(CompositorAnimationTest, NotifyFromCCAfterCompositorAnimationDeletion) {
auto curve = std::make_unique<CompositorFloatAnimationCurve>();
auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, compositor_target_property::OPACITY, 0, 1);
+ *curve, 0, 1,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::OPACITY));
int keyframe_model_id = keyframe_model->Id();
animation->AddKeyframeModel(std::move(keyframe_model));
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h
index 10e73307486..a1f3454fd27 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "cc/animation/animation_timeline.h"
@@ -27,6 +26,9 @@ class PLATFORM_EXPORT CompositorAnimationTimeline {
public:
CompositorAnimationTimeline();
explicit CompositorAnimationTimeline(scoped_refptr<cc::AnimationTimeline>);
+ CompositorAnimationTimeline(const CompositorAnimationTimeline&) = delete;
+ CompositorAnimationTimeline& operator=(const CompositorAnimationTimeline&) =
+ delete;
~CompositorAnimationTimeline();
cc::AnimationTimeline* GetAnimationTimeline() const;
@@ -38,8 +40,6 @@ class PLATFORM_EXPORT CompositorAnimationTimeline {
private:
scoped_refptr<cc::AnimationTimeline> animation_timeline_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorAnimationTimeline);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h b/chromium/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h
index 25b532b4303..d950ff2b686 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h"
@@ -30,6 +29,9 @@ class PLATFORM_EXPORT CompositorColorAnimationCurve
: public CompositorAnimationCurve {
public:
CompositorColorAnimationCurve();
+ CompositorColorAnimationCurve(const CompositorColorAnimationCurve&) = delete;
+ CompositorColorAnimationCurve& operator=(
+ const CompositorColorAnimationCurve&) = delete;
~CompositorColorAnimationCurve() override;
void AddKeyframe(const CompositorColorKeyframe&);
@@ -51,8 +53,6 @@ class PLATFORM_EXPORT CompositorColorAnimationCurve
std::unique_ptr<gfx::KeyframedColorAnimationCurve>);
std::unique_ptr<gfx::KeyframedColorAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorColorAnimationCurve);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h b/chromium/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h
index 1ef2092846e..27dccca9b43 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_KEYFRAME_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_KEYFRAME_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
@@ -18,6 +17,8 @@ class PLATFORM_EXPORT CompositorColorKeyframe : public CompositorKeyframe {
public:
CompositorColorKeyframe(double time, SkColor value, const TimingFunction&);
CompositorColorKeyframe(std::unique_ptr<gfx::ColorKeyframe>);
+ CompositorColorKeyframe(const CompositorColorKeyframe&) = delete;
+ CompositorColorKeyframe& operator=(const CompositorColorKeyframe&) = delete;
~CompositorColorKeyframe() override;
// CompositorKeyframe implementation.
@@ -29,8 +30,6 @@ class PLATFORM_EXPORT CompositorColorKeyframe : public CompositorKeyframe {
private:
std::unique_ptr<gfx::ColorKeyframe> color_keyframe_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorColorKeyframe);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_filter_animation_curve.h b/chromium/third_party/blink/renderer/platform/animation/compositor_filter_animation_curve.h
index a6f6221526e..68b5a671cda 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_filter_animation_curve.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_filter_animation_curve.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h"
#include "third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h"
@@ -29,6 +28,10 @@ class PLATFORM_EXPORT CompositorFilterAnimationCurve
: public CompositorAnimationCurve {
public:
CompositorFilterAnimationCurve();
+ CompositorFilterAnimationCurve(const CompositorFilterAnimationCurve&) =
+ delete;
+ CompositorFilterAnimationCurve& operator=(
+ const CompositorFilterAnimationCurve&) = delete;
~CompositorFilterAnimationCurve() override;
void AddKeyframe(const CompositorFilterKeyframe&);
@@ -40,8 +43,6 @@ class PLATFORM_EXPORT CompositorFilterAnimationCurve
private:
std::unique_ptr<cc::KeyframedFilterAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorFilterAnimationCurve);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h b/chromium/third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h
index 08ed28a1623..96900b212ce 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_FILTER_KEYFRAME_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_FILTER_KEYFRAME_H_
-#include "base/macros.h"
#include "cc/animation/filter_animation_curve.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
@@ -20,6 +19,8 @@ class PLATFORM_EXPORT CompositorFilterKeyframe : public CompositorKeyframe {
CompositorFilterKeyframe(double time,
CompositorFilterOperations value,
const TimingFunction&);
+ CompositorFilterKeyframe(const CompositorFilterKeyframe&) = delete;
+ CompositorFilterKeyframe& operator=(const CompositorFilterKeyframe&) = delete;
~CompositorFilterKeyframe() override;
std::unique_ptr<cc::FilterKeyframe> CloneToCC() const;
@@ -30,8 +31,6 @@ class PLATFORM_EXPORT CompositorFilterKeyframe : public CompositorKeyframe {
private:
std::unique_ptr<cc::FilterKeyframe> filter_keyframe_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorFilterKeyframe);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h b/chromium/third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h
index 6a1b6303905..802149f8e39 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h"
@@ -31,6 +30,9 @@ class PLATFORM_EXPORT CompositorFloatAnimationCurve
: public CompositorAnimationCurve {
public:
CompositorFloatAnimationCurve();
+ CompositorFloatAnimationCurve(const CompositorFloatAnimationCurve&) = delete;
+ CompositorFloatAnimationCurve& operator=(
+ const CompositorFloatAnimationCurve&) = delete;
~CompositorFloatAnimationCurve() override;
void AddKeyframe(const CompositorFloatKeyframe&);
@@ -54,8 +56,6 @@ class PLATFORM_EXPORT CompositorFloatAnimationCurve
std::unique_ptr<gfx::KeyframedFloatAnimationCurve>);
std::unique_ptr<gfx::KeyframedFloatAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorFloatAnimationCurve);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_float_keyframe.h b/chromium/third_party/blink/renderer/platform/animation/compositor_float_keyframe.h
index 766ab5d7256..8f471536abb 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_float_keyframe.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_float_keyframe.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_FLOAT_KEYFRAME_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_FLOAT_KEYFRAME_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
@@ -18,6 +17,8 @@ class PLATFORM_EXPORT CompositorFloatKeyframe : public CompositorKeyframe {
public:
CompositorFloatKeyframe(double time, float value, const TimingFunction&);
CompositorFloatKeyframe(std::unique_ptr<gfx::FloatKeyframe>);
+ CompositorFloatKeyframe(const CompositorFloatKeyframe&) = delete;
+ CompositorFloatKeyframe& operator=(const CompositorFloatKeyframe&) = delete;
~CompositorFloatKeyframe() override;
// CompositorKeyframe implementation.
@@ -29,8 +30,6 @@ class PLATFORM_EXPORT CompositorFloatKeyframe : public CompositorKeyframe {
private:
std::unique_ptr<gfx::FloatKeyframe> float_keyframe_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorFloatKeyframe);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
index 2e2db63723c..6f8cc4fdd0f 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
@@ -23,44 +23,16 @@ namespace blink {
CompositorKeyframeModel::CompositorKeyframeModel(
const CompositorAnimationCurve& curve,
- compositor_target_property::Type target_property,
- int keyframe_model_id,
- int group_id)
- : CompositorKeyframeModel(
- curve,
- keyframe_model_id,
- group_id,
- KeyframeModel::TargetPropertyId(target_property)) {}
-
-CompositorKeyframeModel::CompositorKeyframeModel(
- const CompositorAnimationCurve& curve,
- compositor_target_property::Type target_property,
- int keyframe_model_id,
- int group_id,
- const AtomicString& custom_property_name)
- : CompositorKeyframeModel(
- curve,
- keyframe_model_id,
- group_id,
- KeyframeModel::TargetPropertyId(target_property,
- custom_property_name.Utf8().data())) {
- DCHECK(!custom_property_name.IsEmpty());
-}
-
-CompositorKeyframeModel::CompositorKeyframeModel(
- const CompositorAnimationCurve& curve,
- compositor_target_property::Type target_property,
int keyframe_model_id,
int group_id,
- CompositorPaintWorkletInput::NativePropertyType native_property_type)
- : CompositorKeyframeModel(
- curve,
- keyframe_model_id,
- group_id,
- KeyframeModel::TargetPropertyId(target_property,
- native_property_type)) {
- DCHECK_NE(native_property_type,
- CompositorPaintWorkletInput::NativePropertyType::kInvalid);
+ KeyframeModel::TargetPropertyId target_property_id) {
+ if (!keyframe_model_id)
+ keyframe_model_id = AnimationIdProvider::NextKeyframeModelId();
+ if (!group_id)
+ group_id = AnimationIdProvider::NextGroupId();
+ keyframe_model_ =
+ KeyframeModel::Create(curve.CloneToAnimationCurve(), keyframe_model_id,
+ group_id, std::move(target_property_id));
}
CompositorKeyframeModel::~CompositorKeyframeModel() = default;
@@ -73,19 +45,6 @@ int CompositorKeyframeModel::Group() const {
return keyframe_model_->group();
}
-CompositorKeyframeModel::CompositorKeyframeModel(
- const CompositorAnimationCurve& curve,
- int keyframe_model_id,
- int group_id,
- const KeyframeModel::TargetPropertyId& id) {
- if (!keyframe_model_id)
- keyframe_model_id = AnimationIdProvider::NextKeyframeModelId();
- if (!group_id)
- group_id = AnimationIdProvider::NextGroupId();
- keyframe_model_ = KeyframeModel::Create(curve.CloneToAnimationCurve(),
- keyframe_model_id, group_id, id);
-}
-
compositor_target_property::Type CompositorKeyframeModel::TargetProperty()
const {
return static_cast<compositor_target_property::Type>(
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
index 41249640af9..625383fcb43 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "cc/animation/keyframe_model.h"
#include "third_party/blink/renderer/platform/animation/compositor_target_property.h"
@@ -34,23 +33,15 @@ class PLATFORM_EXPORT CompositorKeyframeModel {
public:
using Direction = cc::KeyframeModel::Direction;
using FillMode = cc::KeyframeModel::FillMode;
+ using TargetPropertyId = cc::KeyframeModel::TargetPropertyId;
- CompositorKeyframeModel(const CompositorAnimationCurve&,
- compositor_target_property::Type,
- int keyframe_model_id,
- int group_id);
- // The |custom_property_name| is the name of animated custom property.
- CompositorKeyframeModel(const CompositorAnimationCurve&,
- compositor_target_property::Type,
+ CompositorKeyframeModel(const CompositorAnimationCurve& curve,
int keyframe_model_id,
int group_id,
- const AtomicString& custom_property_name);
- CompositorKeyframeModel(
- const CompositorAnimationCurve&,
- compositor_target_property::Type,
- int keyframe_model_id,
- int group_id,
- CompositorPaintWorkletInput::NativePropertyType native_property_type);
+ cc::KeyframeModel::TargetPropertyId);
+
+ CompositorKeyframeModel(const CompositorKeyframeModel&) = delete;
+ CompositorKeyframeModel& operator=(const CompositorKeyframeModel&) = delete;
~CompositorKeyframeModel();
// An id must be unique.
@@ -96,14 +87,7 @@ class PLATFORM_EXPORT CompositorKeyframeModel {
}
private:
- CompositorKeyframeModel(const CompositorAnimationCurve& curve,
- int keyframe_model_id,
- int group_id,
- const cc::KeyframeModel::TargetPropertyId& id);
-
std::unique_ptr<cc::KeyframeModel> keyframe_model_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorKeyframeModel);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc
index 98c3567a652..591bc358e18 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc
@@ -12,7 +12,9 @@ namespace blink {
TEST(WebCompositorAnimationTest, DefaultSettings) {
auto curve = std::make_unique<CompositorFloatAnimationCurve>();
auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, compositor_target_property::OPACITY, 0, 1);
+ *curve, 0, 1,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::OPACITY));
// Ensure that the defaults are correct.
EXPECT_EQ(1, keyframe_model->Iterations());
@@ -25,7 +27,9 @@ TEST(WebCompositorAnimationTest, DefaultSettings) {
TEST(WebCompositorAnimationTest, ModifiedSettings) {
auto curve = std::make_unique<CompositorFloatAnimationCurve>();
auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
- *curve, compositor_target_property::OPACITY, 0, 1);
+ *curve, 0, 1,
+ CompositorKeyframeModel::TargetPropertyId(
+ compositor_target_property::OPACITY));
keyframe_model->SetIterations(2);
keyframe_model->SetStartTime(2);
keyframe_model->SetTimeOffset(base::TimeDelta::FromSeconds(2));
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_scroll_offset_animation_curve.h b/chromium/third_party/blink/renderer/platform/animation/compositor_scroll_offset_animation_curve.h
index 90e936523b8..633c973e1e4 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_scroll_offset_animation_curve.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_scroll_offset_animation_curve.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "cc/animation/scroll_offset_animation_curve_factory.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h"
@@ -28,6 +27,10 @@ class PLATFORM_EXPORT CompositorScrollOffsetAnimationCurve
CompositorScrollOffsetAnimationCurve(FloatPoint, ScrollType);
explicit CompositorScrollOffsetAnimationCurve(
cc::ScrollOffsetAnimationCurve*);
+ CompositorScrollOffsetAnimationCurve(
+ const CompositorScrollOffsetAnimationCurve&) = delete;
+ CompositorScrollOffsetAnimationCurve& operator=(
+ const CompositorScrollOffsetAnimationCurve&) = delete;
~CompositorScrollOffsetAnimationCurve() override;
@@ -43,8 +46,6 @@ class PLATFORM_EXPORT CompositorScrollOffsetAnimationCurve
private:
std::unique_ptr<cc::ScrollOffsetAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorScrollOffsetAnimationCurve);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_animation_curve.h b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_animation_curve.h
index 0b0fe6e0ceb..9794f29ff1a 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_animation_curve.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_animation_curve.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h"
#include "third_party/blink/renderer/platform/animation/compositor_transform_keyframe.h"
@@ -29,6 +28,10 @@ class PLATFORM_EXPORT CompositorTransformAnimationCurve
: public CompositorAnimationCurve {
public:
CompositorTransformAnimationCurve();
+ CompositorTransformAnimationCurve(const CompositorTransformAnimationCurve&) =
+ delete;
+ CompositorTransformAnimationCurve& operator=(
+ const CompositorTransformAnimationCurve&) = delete;
~CompositorTransformAnimationCurve() override;
void AddKeyframe(const CompositorTransformKeyframe&);
@@ -40,8 +43,6 @@ class PLATFORM_EXPORT CompositorTransformAnimationCurve
private:
std::unique_ptr<gfx::KeyframedTransformAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorTransformAnimationCurve);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_keyframe.h b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_keyframe.h
index 47b85ca323c..b969741c80d 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_keyframe.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_keyframe.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_TRANSFORM_KEYFRAME_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_TRANSFORM_KEYFRAME_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe.h"
#include "third_party/blink/renderer/platform/animation/compositor_transform_operations.h"
#include "third_party/blink/renderer/platform/animation/timing_function.h"
@@ -19,6 +18,9 @@ class PLATFORM_EXPORT CompositorTransformKeyframe : public CompositorKeyframe {
CompositorTransformKeyframe(double time,
CompositorTransformOperations value,
const TimingFunction&);
+ CompositorTransformKeyframe(const CompositorTransformKeyframe&) = delete;
+ CompositorTransformKeyframe& operator=(const CompositorTransformKeyframe&) =
+ delete;
~CompositorTransformKeyframe() override;
std::unique_ptr<gfx::TransformKeyframe> CloneToCC() const;
@@ -29,8 +31,6 @@ class PLATFORM_EXPORT CompositorTransformKeyframe : public CompositorKeyframe {
private:
std::unique_ptr<gfx::TransformKeyframe> transform_keyframe_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorTransformKeyframe);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc
index b5f4dcab315..b0edf5ec763 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/animation/compositor_transform_operations.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
+#include "skia/ext/skia_matrix_44.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_operations.h"
@@ -62,7 +62,7 @@ void CompositorTransformOperations::AppendPerspective(double depth) {
transform_operations_.AppendPerspective(SkDoubleToScalar(depth));
}
-void CompositorTransformOperations::AppendMatrix(const SkMatrix44& matrix) {
+void CompositorTransformOperations::AppendMatrix(const skia::Matrix44& matrix) {
gfx::Transform transform(gfx::Transform::kSkipInitialization);
transform.matrix() = matrix;
transform_operations_.AppendMatrix(transform);
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.h b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.h
index 3cc95a12c40..f52f424906e 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.h
@@ -9,7 +9,9 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "ui/gfx/transform_operations.h"
-class SkMatrix44;
+namespace skia {
+class Matrix44;
+}
namespace blink {
@@ -32,7 +34,7 @@ class PLATFORM_EXPORT CompositorTransformOperations {
void AppendSkewY(double y);
void AppendSkew(double x, double y);
void AppendPerspective(double depth);
- void AppendMatrix(const SkMatrix44&);
+ void AppendMatrix(const skia::Matrix44&);
bool IsIdentity() const;
diff --git a/chromium/third_party/blink/renderer/platform/audio/OWNERS b/chromium/third_party/blink/renderer/platform/audio/OWNERS
index a837fc9b778..5248064ba91 100644
--- a/chromium/third_party/blink/renderer/platform/audio/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/audio/OWNERS
@@ -1,2 +1 @@
hongchan@chromium.org
-rtoy@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_array.h b/chromium/third_party/blink/renderer/platform/audio/audio_array.h
index 52f4af55713..ce949a2bc0a 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_array.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_array.h
@@ -31,7 +31,6 @@
#include <string.h>
-#include "base/macros.h"
#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -50,6 +49,8 @@ class AudioArray {
: allocation_(nullptr), aligned_data_(nullptr), size_(0) {
Allocate(n);
}
+ AudioArray(const AudioArray&) = delete;
+ AudioArray& operator=(const AudioArray&) = delete;
~AudioArray() { WTF::Partitions::FastFree(allocation_); }
@@ -138,8 +139,6 @@ class AudioArray {
T* allocation_;
T* aligned_data_;
uint32_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioArray);
};
typedef AudioArray<float> AudioFloatArray;
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_bus.h b/chromium/third_party/blink/renderer/platform/audio/audio_bus.h
index 8660a6bccd4..734cb5d6c22 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_bus.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_bus.h
@@ -29,7 +29,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_BUS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_BUS_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_channel.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -70,6 +69,9 @@ class PLATFORM_EXPORT AudioBus : public ThreadSafeRefCounted<AudioBus> {
uint32_t length,
bool allocate = true);
+ AudioBus(const AudioBus&) = delete;
+ AudioBus& operator=(const AudioBus&) = delete;
+
// Tells the given channel to use an externally allocated buffer.
void SetChannelMemory(unsigned channel_index,
float* storage,
@@ -177,8 +179,6 @@ class PLATFORM_EXPORT AudioBus : public ThreadSafeRefCounted<AudioBus> {
Vector<AudioChannel, 2> channels_;
int layout_;
float sample_rate_; // 0.0 if unknown or N/A
-
- DISALLOW_COPY_AND_ASSIGN(AudioBus);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_channel.cc b/chromium/third_party/blink/renderer/platform/audio/audio_channel.cc
index c32867ed9c7..e9089a2b058 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_channel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_channel.cc
@@ -35,7 +35,7 @@
namespace blink {
-void AudioChannel::ResizeSmaller(size_t new_length) {
+void AudioChannel::ResizeSmaller(uint32_t new_length) {
DCHECK_LE(new_length, length_);
length_ = new_length;
}
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_channel.h b/chromium/third_party/blink/renderer/platform/audio/audio_channel.h
index a7dbe7e2ef3..94f02729871 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_channel.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_channel.h
@@ -46,11 +46,11 @@ class PLATFORM_EXPORT AudioChannel {
// AudioFloatArray.
// Reference an external buffer.
- AudioChannel(float* storage, size_t length)
+ AudioChannel(float* storage, uint32_t length)
: length_(length), raw_pointer_(storage), silent_(false) {}
// Manage storage for us.
- explicit AudioChannel(size_t length)
+ explicit AudioChannel(uint32_t length)
: length_(length), raw_pointer_(nullptr), silent_(true) {
mem_buffer_ = std::make_unique<AudioFloatArray>(length);
}
@@ -60,7 +60,7 @@ class PLATFORM_EXPORT AudioChannel {
// Redefine the memory for this channel. |storage| represents external memory
// not managed by this object.
- void Set(float* storage, size_t length) {
+ void Set(float* storage, uint32_t length) {
mem_buffer_.reset(); // cleanup managed storage
raw_pointer_ = storage;
length_ = length;
@@ -68,11 +68,11 @@ class PLATFORM_EXPORT AudioChannel {
}
// How many sample-frames do we contain?
- size_t length() const { return length_; }
+ uint32_t length() const { return length_; }
// ResizeSmaller() can only be called with a new length <= the current length.
// The data stored in the bus will remain undisturbed.
- void ResizeSmaller(size_t new_length);
+ void ResizeSmaller(uint32_t new_length);
// Direct access to PCM sample data. Non-const accessor clears silent flag.
float* MutableData() {
@@ -122,7 +122,7 @@ class PLATFORM_EXPORT AudioChannel {
float MaxAbsValue() const;
private:
- size_t length_;
+ uint32_t length_;
float* raw_pointer_;
std::unique_ptr<AudioFloatArray> mem_buffer_;
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
index 200a350157b..1ab546ad16f 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
@@ -281,13 +281,13 @@ void AudioDelayDSPKernel::ProcessKRate(const float* source,
// carefully handling wrapping of the read pointer.
float* read_pointer = &buffer[read_index1];
- int remainder = buffer_end - read_pointer;
+ uint32_t remainder = static_cast<uint32_t>(buffer_end - read_pointer);
memcpy(sample1, read_pointer,
- sizeof(*sample1) *
- std::min(static_cast<int>(frames_to_process), remainder));
- memcpy(sample1 + remainder, buffer,
- sizeof(*sample1) *
- std::max(0, static_cast<int>(frames_to_process) - remainder));
+ sizeof(*sample1) * std::min(frames_to_process, remainder));
+ if (frames_to_process > remainder) {
+ memcpy(sample1 + remainder, buffer,
+ sizeof(*sample1) * (frames_to_process - remainder));
+ }
// If interpolation_factor = 0, we don't need to do any interpolation and
// sample1 contains the desried values. We can skip the following code.
@@ -298,13 +298,13 @@ void AudioDelayDSPKernel::ProcessKRate(const float* source,
float* sample2 = temp_buffer_.Data();
read_pointer = &buffer[read_index2];
- remainder = buffer_end - read_pointer;
+ remainder = static_cast<uint32_t>(buffer_end - read_pointer);
memcpy(sample2, read_pointer,
- sizeof(*sample1) *
- std::min(static_cast<int>(frames_to_process), remainder));
- memcpy(sample2 + remainder, buffer,
- sizeof(*sample1) *
- std::max(0, static_cast<int>(frames_to_process) - remainder));
+ sizeof(*sample1) * std::min(frames_to_process, remainder));
+ if (frames_to_process > remainder) {
+ memcpy(sample2 + remainder, buffer,
+ sizeof(*sample1) * (frames_to_process - remainder));
+ }
// Interpolate samples, where f = interpolation_factor
// dest[k] = sample1[k] + f*(sample2[k] - sample1[k]);
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 d32f68ce977..0cfcf81a327 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
@@ -52,7 +52,7 @@ namespace blink {
// that we would ever need. The current UMA stats indicates that this is, in
// fact, probably too small. There are Android devices out there with a size of
// 8000 or so. We might need to make this larger. See: crbug.com/670747
-const size_t kFIFOSize = 96 * 128;
+const uint32_t kFIFOSize = 96 * 128;
namespace {
@@ -101,7 +101,7 @@ AudioDestination::AudioDestination(AudioIOCallback& callback,
SendLogMessage(String::Format("%s({output_channels=%u})", __func__,
number_of_output_channels));
SendLogMessage(
- String::Format("%s => (FIFO size=%zu bytes)", __func__, fifo_->length()));
+ String::Format("%s => (FIFO size=%u bytes)", __func__, fifo_->length()));
// Create WebAudioDevice. blink::WebAudioDevice is designed to support the
// local input (e.g. loopback from OS audio system), but Chromium's media
// renderer does not support it currently. Thus, we use zero for the number
@@ -184,7 +184,7 @@ AudioDestination::~AudioDestination() {
}
void AudioDestination::Render(const WebVector<float*>& destination_data,
- size_t number_of_frames,
+ uint32_t number_of_frames,
double delay,
double delay_timestamp,
size_t prior_frames_skipped) {
@@ -232,7 +232,6 @@ void AudioDestination::Render(const WebVector<float*>& destination_data,
delay_timestamp, "delay (s)", delay);
}
-
void AudioDestination::RequestRender(size_t frames_requested,
size_t frames_to_render,
double delay,
@@ -398,7 +397,7 @@ bool AudioDestination::CheckBufferSize(unsigned render_quantum_frames) {
// Record the sizes if we successfully created an output device.
// Histogram for audioHardwareBufferSize
base::UmaHistogramSparse("WebAudio.AudioDestination.HardwareBufferSize",
- HardwareBufferSize());
+ static_cast<int>(HardwareBufferSize()));
// Histogram for the actual callback size used. Typically, this is the same
// as audioHardwareBufferSize, but can be adjusted depending on some
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 bb4e1743ecc..3a9dfbb560d 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
@@ -43,6 +43,11 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+namespace absl {
+template <typename>
+class optional;
+}
+
namespace blink {
class PushPullFIFO;
@@ -77,6 +82,8 @@ class PLATFORM_EXPORT AudioDestination
const WebAudioLatencyHint&,
absl::optional<float> context_sample_rate,
unsigned render_quantum_frames);
+ AudioDestination(const AudioDestination&) = delete;
+ AudioDestination& operator=(const AudioDestination&) = delete;
~AudioDestination() override;
static scoped_refptr<AudioDestination> Create(
@@ -89,7 +96,7 @@ class PLATFORM_EXPORT AudioDestination
// The actual render function (WebAudioDevice::RenderCallback) isochronously
// invoked by the media renderer. This is never called after Stop() is called.
void Render(const WebVector<float*>& destination_data,
- size_t number_of_frames,
+ uint32_t number_of_frames,
double delay,
double delay_timestamp,
size_t prior_frames_skipped) override;
@@ -193,8 +200,6 @@ class PLATFORM_EXPORT AudioDestination
// Modified only on the main thread, so it can be read without holding a lock
// there.
DeviceState device_state_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioDestination);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination_consumer.h b/chromium/third_party/blink/renderer/platform/audio/audio_destination_consumer.h
index 30ce6936b81..63ffe5bf5e2 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination_consumer.h
@@ -39,8 +39,8 @@ class AudioBus;
class PLATFORM_EXPORT AudioDestinationConsumer {
public:
- virtual void SetFormat(size_t number_of_channels, float sample_rate) = 0;
- virtual void ConsumeAudio(AudioBus*, size_t number_of_frames) = 0;
+ virtual void SetFormat(int number_of_channels, float sample_rate) = 0;
+ virtual void ConsumeAudio(AudioBus*, int number_of_frames) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_resampler.cc b/chromium/third_party/blink/renderer/platform/audio/audio_resampler.cc
index 764547e78ad..0af1ab4f3df 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_resampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_resampler.cc
@@ -75,7 +75,7 @@ void AudioResampler::Process(AudioSourceProvider* provider,
for (unsigned i = 0; i < number_of_channels; ++i) {
// Figure out how many frames we need to get from the provider, and a
// pointer to the buffer.
- size_t frames_needed;
+ unsigned frames_needed;
float* fill_pointer =
kernels_[i]->GetSourcePointer(frames_to_process, &frames_needed);
DCHECK(fill_pointer);
@@ -84,7 +84,8 @@ void AudioResampler::Process(AudioSourceProvider* provider,
}
// Ask the provider to supply the desired number of source frames.
- provider->ProvideInput(source_bus_.get(), source_bus_->length());
+ provider->ProvideInput(source_bus_.get(),
+ base::checked_cast<int>(source_bus_->length()));
// Now that we have the source data, resample each channel into the
// destination bus.
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_resampler.h b/chromium/third_party/blink/renderer/platform/audio/audio_resampler.h
index 3398214180d..d1fbcf097f6 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_resampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_resampler.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_resampler_kernel.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider.h"
@@ -47,6 +46,8 @@ class PLATFORM_EXPORT AudioResampler {
public:
AudioResampler();
AudioResampler(unsigned number_of_channels);
+ AudioResampler(const AudioResampler&) = delete;
+ AudioResampler& operator=(const AudioResampler&) = delete;
~AudioResampler() = default;
// Given an AudioSourceProvider, process() resamples the source stream into
@@ -70,8 +71,6 @@ class PLATFORM_EXPORT AudioResampler {
double rate_;
Vector<std::unique_ptr<AudioResamplerKernel>> kernels_;
scoped_refptr<AudioBus> source_bus_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioResampler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.cc
index cb8cde6f396..7dca70ececf 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.cc
@@ -45,7 +45,7 @@ AudioResamplerKernel::AudioResamplerKernel(AudioResampler* resampler)
float* AudioResamplerKernel::GetSourcePointer(
uint32_t frames_to_process,
- size_t* number_of_source_frames_needed_p) {
+ unsigned* number_of_source_frames_needed_p) {
DCHECK_LE(frames_to_process, kMaxFramesToProcess);
// Calculate the next "virtual" index. After process() is called,
@@ -61,7 +61,7 @@ float* AudioResamplerKernel::GetSourcePointer(
// Determine how many input frames we'll need.
// We need to fill the buffer up to and including endIndex (so add 1) but
// we've already buffered m_fillIndex frames from last time.
- size_t frames_needed = 1 + end_index - fill_index_;
+ unsigned frames_needed = 1 + end_index - fill_index_;
if (number_of_source_frames_needed_p)
*number_of_source_frames_needed_p = frames_needed;
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.h b/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.h
index c52fc1b44a1..a5c3d68e9bd 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_resampler_kernel.h
@@ -42,6 +42,8 @@ class PLATFORM_EXPORT AudioResamplerKernel {
public:
AudioResamplerKernel(AudioResampler*);
+ AudioResamplerKernel(const AudioResamplerKernel&) = delete;
+ AudioResamplerKernel& operator=(const AudioResamplerKernel&) = delete;
// getSourcePointer() should be called each time before process() is called.
// Given a number of frames to process (for subsequent call to process()), it
@@ -50,7 +52,7 @@ class PLATFORM_EXPORT AudioResamplerKernel {
// process() is called. framesToProcess must be less than or equal to
// MaxFramesToProcess.
float* GetSourcePointer(uint32_t frames_to_process,
- size_t* number_of_source_frames_needed);
+ unsigned* number_of_source_frames_needed);
// process() resamples framesToProcess frames from the source into
// destination. Each call to process() must be preceded by a call to
@@ -79,8 +81,6 @@ class PLATFORM_EXPORT AudioResamplerKernel {
// there will be no buffered samples.
float last_values_[2];
unsigned fill_index_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioResamplerKernel);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_source_provider.h b/chromium/third_party/blink/renderer/platform/audio/audio_source_provider.h
index 88759efbf76..3feeadf0150 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_source_provider.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_source_provider.h
@@ -30,7 +30,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_SOURCE_PROVIDER_H_
#include <cstddef>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -42,14 +41,15 @@ class AudioSourceProviderClient;
// Abstract base-class for a pull-model client.
class PLATFORM_EXPORT AudioSourceProvider {
USING_FAST_MALLOC(AudioSourceProvider);
- DISALLOW_COPY_AND_ASSIGN(AudioSourceProvider);
public:
AudioSourceProvider() = default;
+ AudioSourceProvider(const AudioSourceProvider&) = delete;
+ AudioSourceProvider& operator=(const AudioSourceProvider&) = delete;
// provideInput() gets called repeatedly to render time-slices of a continuous
// audio stream.
- virtual void ProvideInput(AudioBus* bus, uint32_t frames_to_process) = 0;
+ virtual void ProvideInput(AudioBus* bus, int frames_to_process) = 0;
// If a client is set, we call it back when the audio format is available or
// changes.
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h
index 48b71770592..c979fde6388 100644
--- a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h
+++ b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h
@@ -13,8 +13,8 @@ namespace blink {
namespace vector_math {
namespace avx {
-constexpr size_t kBitsPerRegister = 256u;
-constexpr size_t kPackedFloatsPerRegister = kBitsPerRegister / 32u;
+constexpr uint32_t kBitsPerRegister = 256u;
+constexpr uint32_t kPackedFloatsPerRegister = kBitsPerRegister / 32u;
constexpr size_t kFramesToProcessMask = ~(kPackedFloatsPerRegister - 1u);
bool IsAligned(const float*);
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h
index 90f05adf4d5..9e828938582 100644
--- a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h
+++ b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h
@@ -13,8 +13,8 @@ namespace blink {
namespace vector_math {
namespace sse {
-constexpr size_t kBitsPerRegister = 128u;
-constexpr size_t kPackedFloatsPerRegister = kBitsPerRegister / 32u;
+constexpr uint32_t kBitsPerRegister = 128u;
+constexpr uint32_t kPackedFloatsPerRegister = kBitsPerRegister / 32u;
constexpr size_t kFramesToProcessMask = ~(kPackedFloatsPerRegister - 1u);
bool IsAligned(const float*);
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
index a4577d0624b..c11ee8bc4ec 100644
--- 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
@@ -15,11 +15,11 @@ namespace vector_math {
namespace x86 {
struct FrameCounts {
- size_t scalar_for_alignment;
- size_t sse_for_alignment;
- size_t avx;
- size_t sse;
- size_t scalar;
+ uint32_t scalar_for_alignment;
+ uint32_t sse_for_alignment;
+ uint32_t avx;
+ uint32_t sse;
+ uint32_t scalar;
};
static bool CPUSupportsAVX() {
@@ -27,29 +27,30 @@ static bool CPUSupportsAVX() {
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;
+static uint32_t GetAVXAlignmentOffsetInNumberOfFloats(const float* source_p) {
+ constexpr uint32_t kBytesPerRegister = avx::kBitsPerRegister / 8u;
+ constexpr uint32_t kAlignmentOffsetMask = kBytesPerRegister - 1u;
+ uintptr_t offset =
+ reinterpret_cast<uintptr_t>(source_p) & kAlignmentOffsetMask;
DCHECK_EQ(0u, offset % sizeof(*source_p));
- return offset / sizeof(*source_p);
+ return static_cast<uint32_t>(offset / sizeof(*source_p));
}
static ALWAYS_INLINE FrameCounts
SplitFramesToProcess(const float* source_p, uint32_t frames_to_process) {
FrameCounts counts = {0u, 0u, 0u, 0u, 0u};
- const size_t avx_alignment_offset =
+ const uint32_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 =
+ const uint32_t total_for_alignment =
(avx::kPackedFloatsPerRegister - avx_alignment_offset) &
~avx::kFramesToProcessMask;
- const size_t scalar_for_alignment =
+ const uint32_t scalar_for_alignment =
total_for_alignment & ~sse::kFramesToProcessMask;
- const size_t sse_for_alignment =
+ const uint32_t sse_for_alignment =
total_for_alignment & sse::kFramesToProcessMask;
// Check which CPU features can be used based on the number of frames to
diff --git a/chromium/third_party/blink/renderer/platform/audio/direct_convolver.h b/chromium/third_party/blink/renderer/platform/audio/direct_convolver.h
index af5f461415e..1b6d19958c0 100644
--- a/chromium/third_party/blink/renderer/platform/audio/direct_convolver.h
+++ b/chromium/third_party/blink/renderer/platform/audio/direct_convolver.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -44,6 +43,8 @@ class PLATFORM_EXPORT DirectConvolver {
public:
DirectConvolver(size_t input_block_size,
std::unique_ptr<AudioFloatArray> convolution_kernel);
+ DirectConvolver(const DirectConvolver&) = delete;
+ DirectConvolver& operator=(const DirectConvolver&) = delete;
void Process(const float* source_p,
float* dest_p,
@@ -59,8 +60,6 @@ class PLATFORM_EXPORT DirectConvolver {
AudioFloatArray buffer_;
std::unique_ptr<AudioFloatArray> convolution_kernel_;
AudioFloatArray prepared_convolution_kernel_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectConvolver);
};
} // namespace blink
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 f1089317319..41b880ff988 100644
--- a/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc
@@ -41,7 +41,7 @@ namespace {
// Computes ideal band-limited half-band filter coefficients.
// In other words, filter out all frequencies higher than 0.25 * Nyquist.
-std::unique_ptr<AudioFloatArray> MakeReducedKernel(size_t size) {
+std::unique_ptr<AudioFloatArray> MakeReducedKernel(int size) {
auto reduced_kernel = std::make_unique<AudioFloatArray>(size / 2);
// Blackman window parameters.
@@ -82,7 +82,7 @@ std::unique_ptr<AudioFloatArray> MakeReducedKernel(size_t size) {
} // namespace
-DownSampler::DownSampler(size_t input_block_size)
+DownSampler::DownSampler(unsigned input_block_size)
: input_block_size_(input_block_size),
convolver_(input_block_size / 2, // runs at 1/2 source sample-rate
MakeReducedKernel(kDefaultKernelSize)),
@@ -91,10 +91,10 @@ DownSampler::DownSampler(size_t input_block_size)
void DownSampler::Process(const float* source_p,
float* dest_p,
- size_t source_frames_to_process) {
+ uint32_t source_frames_to_process) {
DCHECK_EQ(source_frames_to_process, input_block_size_);
- size_t dest_frames_to_process = source_frames_to_process / 2;
+ uint32_t dest_frames_to_process = source_frames_to_process / 2;
DCHECK_EQ(dest_frames_to_process, temp_buffer_.size());
DCHECK_EQ(convolver_.ConvolutionKernelSize(),
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 494e8a2419c..ffcc667ac85 100644
--- a/chromium/third_party/blink/renderer/platform/audio/down_sampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/down_sampler.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_DOWN_SAMPLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_DOWN_SAMPLER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -44,12 +43,14 @@ class PLATFORM_EXPORT DownSampler {
USING_FAST_MALLOC(DownSampler);
public:
- explicit DownSampler(size_t input_block_size);
+ explicit DownSampler(unsigned input_block_size);
+ DownSampler(const DownSampler&) = delete;
+ DownSampler& operator=(const DownSampler&) = delete;
// The destination buffer |destP| is of size sourceFramesToProcess / 2.
void Process(const float* source_p,
float* dest_p,
- size_t source_frames_to_process);
+ uint32_t source_frames_to_process);
void Reset();
@@ -59,7 +60,7 @@ class PLATFORM_EXPORT DownSampler {
private:
enum { kDefaultKernelSize = 256 };
- size_t input_block_size_;
+ unsigned input_block_size_;
// Half-band filter. SimpleFFTConvolver is always faster than DirectConvolver.
SimpleFFTConvolver convolver_;
@@ -69,8 +70,6 @@ class PLATFORM_EXPORT DownSampler {
// Used as delay-line (FIR filter history) for the input samples to account
// for the 0.5 term right in the middle of the kernel.
AudioFloatArray input_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(DownSampler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.h b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.h
index 985d42393d1..6d631297603 100644
--- a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.h
+++ b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -70,6 +69,8 @@ class PLATFORM_EXPORT DynamicsCompressor {
};
DynamicsCompressor(float sample_rate, unsigned number_of_channels);
+ DynamicsCompressor(const DynamicsCompressor&) = delete;
+ DynamicsCompressor& operator=(const DynamicsCompressor&) = delete;
void Process(const AudioBus* source_bus,
AudioBus* destination_bus,
@@ -111,9 +112,6 @@ class PLATFORM_EXPORT DynamicsCompressor {
// The core compressor.
DynamicsCompressorKernel compressor_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DynamicsCompressor);
};
} // namespace blink
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 5e3862d2587..25b7760184f 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
@@ -63,8 +63,8 @@ DynamicsCompressorKernel::DynamicsCompressorKernel(float sample_rate,
Reset();
metering_release_k_ =
- float{audio_utilities::DiscreteTimeConstantForSampleRate(
- kMeteringReleaseTimeConstant, sample_rate)};
+ static_cast<float>(audio_utilities::DiscreteTimeConstantForSampleRate(
+ kMeteringReleaseTimeConstant, sample_rate));
}
void DynamicsCompressorKernel::SetNumberOfChannels(
diff --git a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.h b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.h
index db2d86511c8..badbf419df3 100644
--- a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.h
+++ b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.h
@@ -30,7 +30,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_DYNAMICS_COMPRESSOR_KERNEL_H_
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -43,6 +42,8 @@ class PLATFORM_EXPORT DynamicsCompressorKernel {
public:
DynamicsCompressorKernel(float sample_rate, unsigned number_of_channels);
+ DynamicsCompressorKernel(const DynamicsCompressorKernel&) = delete;
+ DynamicsCompressorKernel& operator=(const DynamicsCompressorKernel&) = delete;
void SetNumberOfChannels(unsigned);
@@ -134,9 +135,6 @@ class PLATFORM_EXPORT DynamicsCompressorKernel {
// Internal parameter for the knee portion of the curve.
float knee_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DynamicsCompressorKernel);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc b/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc
index 69b31dffe9d..dbe23ec353b 100644
--- a/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc
@@ -88,12 +88,12 @@ FFTFrame::FFTFrame(const FFTFrame& frame)
memcpy(ImagData().Data(), frame.ImagData().Data(), nbytes);
}
-int FFTFrame::MinFFTSize() {
- return 1 << kMinFFTPow2Size;
+unsigned FFTFrame::MinFFTSize() {
+ return 1u << kMinFFTPow2Size;
}
-int FFTFrame::MaxFFTSize() {
- return 1 << kMaxFFTPow2Size;
+unsigned FFTFrame::MaxFFTSize() {
+ return 1u << kMaxFFTPow2Size;
}
void FFTFrame::Initialize(float sample_rate) {}
diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc b/chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc
index a01b3fec556..abb7be87b2e 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc
@@ -31,7 +31,7 @@
namespace blink {
-FFTConvolver::FFTConvolver(size_t fft_size)
+FFTConvolver::FFTConvolver(unsigned fft_size)
: frame_(fft_size),
read_write_index_(0),
input_buffer_(fft_size), // 2nd half of buffer is always zeroed
@@ -42,7 +42,7 @@ void FFTConvolver::Process(const FFTFrame* fft_kernel,
const float* source_p,
float* dest_p,
uint32_t frames_to_process) {
- size_t half_size = FftSize() / 2;
+ unsigned half_size = FftSize() / 2;
// framesToProcess must be an exact multiple of halfSize,
// or halfSize is a multiple of framesToProcess when halfSize >
diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_convolver.h b/chromium/third_party/blink/renderer/platform/audio/fft_convolver.h
index bc33555d4bd..daf6a3ea1ea 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_convolver.h
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_convolver.h
@@ -29,7 +29,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_FFT_CONVOLVER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_FFT_CONVOLVER_H_
-#include "base/macros.h"
#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/allocator.h"
@@ -41,7 +40,9 @@ class PLATFORM_EXPORT FFTConvolver {
public:
// fftSize must be a power of two
- FFTConvolver(size_t fft_size);
+ FFTConvolver(unsigned fft_size);
+ FFTConvolver(const FFTConvolver&) = delete;
+ FFTConvolver& operator=(const FFTConvolver&) = delete;
// For now, with multiple calls to Process(), framesToProcess MUST add up
// EXACTLY to fftSize / 2
@@ -59,7 +60,7 @@ class PLATFORM_EXPORT FFTConvolver {
void Reset();
- size_t FftSize() const { return frame_.FftSize(); }
+ unsigned FftSize() const { return frame_.FftSize(); }
private:
FFTFrame frame_;
@@ -74,8 +75,6 @@ class PLATFORM_EXPORT FFTConvolver {
// 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_;
-
- DISALLOW_COPY_AND_ASSIGN(FFTConvolver);
};
} // namespace blink
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 b53cdefbe0f..c74cbb8adfb 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
@@ -40,7 +40,7 @@
namespace blink {
-void FFTFrame::DoPaddedFFT(const float* data, size_t data_size) {
+void FFTFrame::DoPaddedFFT(const float* data, unsigned data_size) {
// Zero-pad the impulse response
AudioFloatArray padded_response(FftSize()); // zero-initialized
padded_response.CopyToRange(data, 0, data_size);
diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_frame.h b/chromium/third_party/blink/renderer/platform/audio/fft_frame.h
index 5474597147c..c5f97df3c94 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_frame.h
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_frame.h
@@ -67,8 +67,8 @@ class PLATFORM_EXPORT FFTFrame {
~FFTFrame();
// Returns the smallest and largest supported FFT lengths.
- static int MinFFTSize();
- static int MaxFFTSize();
+ static unsigned MinFFTSize();
+ static unsigned MaxFFTSize();
// Perform any initialization needed. Must be called from the main thread.
static void Initialize(float sample_rate);
@@ -100,7 +100,7 @@ class PLATFORM_EXPORT FFTFrame {
const FFTFrame& frame2,
double x);
// zero-padding with dataSize <= fftSize
- void DoPaddedFFT(const float* data, size_t data_size);
+ void DoPaddedFFT(const float* data, unsigned data_size);
double ExtractAverageGroupDelay();
void AddConstantGroupDelay(double sample_frame_delay);
// multiplies ourself with frame : effectively operator*=()
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_database.h b/chromium/third_party/blink/renderer/platform/audio/hrtf_database.h
index 5040564b726..4ba38a30f23 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_database.h
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_database.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/audio/hrtf_elevation.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -47,6 +46,8 @@ class PLATFORM_EXPORT HRTFDatabase {
public:
explicit HRTFDatabase(float sample_rate);
+ HRTFDatabase(const HRTFDatabase&) = delete;
+ HRTFDatabase& operator=(const HRTFDatabase&) = delete;
// getKernelsFromAzimuthElevation() returns a left and right ear kernel, and
// an interpolated left and right frame delay for the given azimuth and
@@ -92,8 +93,6 @@ class PLATFORM_EXPORT HRTFDatabase {
Vector<std::unique_ptr<HRTFElevation>> elevations_;
float sample_rate_;
-
- DISALLOW_COPY_AND_ASSIGN(HRTFDatabase);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/chromium/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
index 01cb98a1116..cc72f94477f 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
@@ -49,13 +49,14 @@ scoped_refptr<HRTFDatabaseLoader>
HRTFDatabaseLoader::CreateAndLoadAsynchronouslyIfNecessary(float sample_rate) {
DCHECK(IsMainThread());
- scoped_refptr<HRTFDatabaseLoader> loader = GetLoaderMap().at(sample_rate);
- if (loader) {
+ if (GetLoaderMap().Contains(sample_rate)) {
+ scoped_refptr<HRTFDatabaseLoader> loader = GetLoaderMap().at(sample_rate);
DCHECK_EQ(sample_rate, loader->DatabaseSampleRate());
return loader;
}
- loader = base::AdoptRef(new HRTFDatabaseLoader(sample_rate));
+ scoped_refptr<HRTFDatabaseLoader> loader =
+ base::AdoptRef(new HRTFDatabaseLoader(sample_rate));
GetLoaderMap().insert(sample_rate, loader.get());
loader->LoadAsynchronously();
return loader;
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.cc b/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
index e90ce4089ef..9859e53cead 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
@@ -157,7 +157,7 @@ bool HRTFElevation::CalculateKernelsForAzimuthElevation(
// Note that depending on the fftSize returned by the panner, we may be
// truncating the impulse response we just loaded in, or we might zero-pad it.
- const size_t fft_size = HRTFPanner::FftSizeForSampleRate(sample_rate);
+ const unsigned fft_size = HRTFPanner::FftSizeForSampleRate(sample_rate);
if (2 * response->length() < fft_size) {
// Need to resize the response buffer length so that it fis the fft size.
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.h b/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.h
index 59a0bbfd20b..b133b801b52 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.h
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_elevation.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/audio/hrtf_kernel.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -63,6 +62,9 @@ class PLATFORM_EXPORT HRTFElevation {
float x,
float sample_rate);
+ HRTFElevation(const HRTFElevation&) = delete;
+ HRTFElevation& operator=(const HRTFElevation&) = delete;
+
// Returns the list of left or right ear HRTFKernels for all the azimuths
// going from 0 to 360 degrees.
HRTFKernelList* KernelListL() { return kernel_list_l_.get(); }
@@ -122,8 +124,6 @@ class PLATFORM_EXPORT HRTFElevation {
std::unique_ptr<HRTFKernelList> kernel_list_r_;
double elevation_angle_;
float sample_rate_;
-
- DISALLOW_COPY_AND_ASSIGN(HRTFElevation);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
index ac96ceafe54..30a58613fc0 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
@@ -43,7 +43,7 @@ namespace blink {
// from the impulseP impulse response, and this value is returned. The length
// of the passed in AudioChannel must be a power of 2.
static float ExtractAverageGroupDelay(AudioChannel* channel,
- size_t analysis_fft_size) {
+ unsigned analysis_fft_size) {
DCHECK(channel);
float* impulse_p = channel->MutableData();
@@ -65,7 +65,7 @@ static float ExtractAverageGroupDelay(AudioChannel* channel,
}
HRTFKernel::HRTFKernel(AudioChannel* channel,
- size_t fft_size,
+ unsigned fft_size,
float sample_rate)
: frame_delay_(0), sample_rate_(sample_rate) {
DCHECK(channel);
@@ -74,12 +74,12 @@ HRTFKernel::HRTFKernel(AudioChannel* channel,
frame_delay_ = ExtractAverageGroupDelay(channel, fft_size / 2);
float* impulse_response = channel->MutableData();
- size_t response_length = channel->length();
+ uint32_t response_length = channel->length();
// We need to truncate to fit into 1/2 the FFT size (with zero padding) in
// order to do proper convolution.
// Truncate if necessary to max impulse response length allowed by FFT.
- size_t truncated_response_length = std::min(response_length, fft_size / 2);
+ unsigned truncated_response_length = std::min(response_length, fft_size / 2);
// Quick fade-out (apply window) at truncation point
unsigned number_of_fade_out_frames = static_cast<unsigned>(
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.h b/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.h
index d1859ad4887..27da98886f7 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.h
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_kernel.h
@@ -32,7 +32,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/audio/fft_frame.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -57,13 +56,15 @@ class PLATFORM_EXPORT HRTFKernel {
public:
// Note: this is destructive on the passed in AudioChannel.
// The length of channel must be a power of two.
- HRTFKernel(AudioChannel*, size_t fft_size, float sample_rate);
+ HRTFKernel(AudioChannel*, unsigned fft_size, float sample_rate);
HRTFKernel(std::unique_ptr<FFTFrame> fft_frame,
float frame_delay,
float sample_rate)
: fft_frame_(std::move(fft_frame)),
frame_delay_(frame_delay),
sample_rate_(sample_rate) {}
+ HRTFKernel(const HRTFKernel&) = delete;
+ HRTFKernel& operator=(const HRTFKernel&) = delete;
// Given two HRTFKernels, and an interpolation factor x: 0 -> 1, returns an
// interpolated HRTFKernel.
@@ -82,8 +83,6 @@ class PLATFORM_EXPORT HRTFKernel {
std::unique_ptr<FFTFrame> fft_frame_;
float frame_delay_;
float sample_rate_;
-
- DISALLOW_COPY_AND_ASSIGN(HRTFKernel);
};
typedef Vector<std::unique_ptr<HRTFKernel>> HRTFKernelList;
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc b/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc
index d919afc57a2..3dd49940d5b 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc
@@ -69,7 +69,7 @@ HRTFPanner::HRTFPanner(float sample_rate,
HRTFPanner::~HRTFPanner() = default;
-size_t HRTFPanner::FftSizeForSampleRate(float sample_rate) {
+unsigned HRTFPanner::FftSizeForSampleRate(float sample_rate) {
// The HRTF impulse responses (loaded as audio resources) are 512
// sample-frames @44.1KHz. Currently, we truncate the impulse responses to
// half this size, but an FFT-size of twice impulse response size is needed
@@ -87,12 +87,13 @@ size_t HRTFPanner::FftSizeForSampleRate(float sample_rate) {
// This is the size used for analysis frames in the HRTF kernel. The
// convolvers used by the kernel are twice this size.
- int analysis_fft_size = 1 << static_cast<unsigned>(log2(resampled_length));
+ unsigned analysis_fft_size = 1u
+ << static_cast<unsigned>(log2(resampled_length));
// Don't let the analysis size be smaller than the supported size
analysis_fft_size = std::max(analysis_fft_size, FFTFrame::MinFFTSize());
- int convolver_fft_size = 2 * analysis_fft_size;
+ unsigned convolver_fft_size = 2 * analysis_fft_size;
// Make sure this size of convolver is supported.
DCHECK_LE(convolver_fft_size, FFTFrame::MaxFFTSize());
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.h b/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.h
index 02d008b356a..52ca79d22a0 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.h
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.h
@@ -56,8 +56,8 @@ class PLATFORM_EXPORT HRTFPanner final : public Panner {
void Reset() override;
- size_t FftSize() const { return FftSizeForSampleRate(sample_rate_); }
- static size_t FftSizeForSampleRate(float sample_rate);
+ unsigned FftSize() const { return FftSizeForSampleRate(sample_rate_); }
+ static unsigned FftSizeForSampleRate(float sample_rate);
float SampleRate() const { return sample_rate_; }
diff --git a/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc b/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc
index 57db0bfdafa..64ab15de568 100644
--- a/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc
@@ -166,12 +166,12 @@ FFTSetup FFTFrame::FftSetupForSize(unsigned log2fft_size) {
return setup[log2fft_size]->GetSetup();
}
-int FFTFrame::MinFFTSize() {
- return 1 << kMinFFTPow2Size;
+unsigned FFTFrame::MinFFTSize() {
+ return 1u << kMinFFTPow2Size;
}
-int FFTFrame::MaxFFTSize() {
- return 1 << kMaxFFTPow2Size;
+unsigned FFTFrame::MaxFFTSize() {
+ return 1u << kMaxFFTPow2Size;
}
void FFTFrame::Initialize(float sample_rate) {
diff --git a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc
index efc61bbc5f8..2bf98cf06eb 100644
--- a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc
@@ -14,7 +14,7 @@ namespace blink {
MediaMultiChannelResampler::MediaMultiChannelResampler(
int channels,
double io_sample_rate_ratio,
- size_t request_frames,
+ uint32_t request_frames,
ReadCB read_cb)
: resampler_input_bus_wrapper_(media::AudioBus::CreateWrapper(channels)),
resampler_output_bus_wrapper_(
diff --git a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h
index e68a330c371..25708bf3284 100644
--- a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h
@@ -7,7 +7,6 @@
#include <memory>
#include "base/callback.h"
-#include "base/macros.h"
#include "media/base/multi_channel_resampler.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -41,9 +40,13 @@ class PLATFORM_EXPORT MediaMultiChannelResampler {
// frames of the AudioBus to be filled by |read_cb|.
MediaMultiChannelResampler(int channels,
double io_sample_rate_ratio,
- size_t request_frames,
+ uint32_t request_frames,
ReadCB read_cb);
+ MediaMultiChannelResampler(const MediaMultiChannelResampler&) = delete;
+ MediaMultiChannelResampler& operator=(const MediaMultiChannelResampler&) =
+ delete;
+
// Resamples |frames| of data from |read_cb_| into a blink::AudioBus, this
// requires creating a wrapper for the media::AudioBus on each call and so
// resampling directly into a media::AudioBus using ResampleInternal() is
@@ -73,8 +76,6 @@ class PLATFORM_EXPORT MediaMultiChannelResampler {
// The callback using a blink::AudioBus that will be called by
// ProvideResamplerInput().
ReadCB read_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaMultiChannelResampler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/panner.h b/chromium/third_party/blink/renderer/platform/audio/panner.h
index 06ceca5a7ec..bbf6b7070e1 100644
--- a/chromium/third_party/blink/renderer/platform/audio/panner.h
+++ b/chromium/third_party/blink/renderer/platform/audio/panner.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -59,6 +58,8 @@ class PLATFORM_EXPORT Panner {
unsigned render_quantum_frames,
HRTFDatabaseLoader*);
+ Panner(const Panner&) = delete;
+ Panner& operator=(const Panner&) = delete;
virtual ~Panner() = default;
virtual void Pan(double azimuth,
@@ -82,9 +83,6 @@ class PLATFORM_EXPORT Panner {
protected:
Panner() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Panner);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc b/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc
index 3317e8ad054..02990f35b92 100644
--- a/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc
@@ -150,12 +150,12 @@ FFTFrame::FFTFrame(const FFTFrame& frame)
memcpy(ImagData().Data(), frame.ImagData().Data(), nbytes);
}
-int FFTFrame::MinFFTSize() {
- return 1 << kMinFFTPow2Size;
+unsigned FFTFrame::MinFFTSize() {
+ return 1u << kMinFFTPow2Size;
}
-int FFTFrame::MaxFFTSize() {
- return 1 << kMaxFFTPow2Size;
+unsigned FFTFrame::MaxFFTSize() {
+ return 1u << kMaxFFTPow2Size;
}
void FFTFrame::Initialize(float sample_rate) {
diff --git a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc
index ea8d3d68b31..eb02977327f 100644
--- a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc
@@ -21,10 +21,10 @@ namespace {
const unsigned kMaxMessagesToLog = 100;
}
-const size_t PushPullFIFO::kMaxFIFOLength = 65536;
+const uint32_t PushPullFIFO::kMaxFIFOLength = 65536;
PushPullFIFO::PushPullFIFO(unsigned number_of_channels,
- size_t fifo_length,
+ uint32_t fifo_length,
unsigned render_quantum_frames)
: fifo_length_(fifo_length), render_quantum_frames_(render_quantum_frames) {
CHECK_LE(fifo_length_, kMaxFIFOLength);
@@ -69,7 +69,7 @@ void PushPullFIFO::Push(const AudioBus* input_bus) {
SECURITY_CHECK(input_bus->length() <= fifo_length_);
SECURITY_CHECK(index_write_ < fifo_length_);
- const size_t input_bus_length = input_bus->length();
+ const uint32_t input_bus_length = input_bus->length();
const size_t remainder = fifo_length_ - index_write_;
for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) {
@@ -112,7 +112,7 @@ void PushPullFIFO::Push(const AudioBus* input_bus) {
// Pull the data out of FIFO to |output_bus|. If remaining frame in the FIFO
// is less than the frames to pull, provides remaining frame plus the silence.
-size_t PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) {
+size_t PushPullFIFO::Pull(AudioBus* output_bus, uint32_t frames_requested) {
TRACE_EVENT2("webaudio", "PushPullFIFO::Pull", "this",
static_cast<void*>(this), "frames", frames_requested);
@@ -212,7 +212,7 @@ size_t PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) {
}
size_t PushPullFIFO::PullAndUpdateEarmark(AudioBus* output_bus,
- size_t frames_requested) {
+ uint32_t frames_requested) {
TRACE_EVENT2("webaudio", "PushPullFIFO::PullAndUpdateEarmark", "this",
static_cast<void*>(this), "frames_requested", frames_requested);
diff --git a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.h b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.h
index ad34a8b0fc3..e4ccdd647e6 100644
--- a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.h
+++ b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.h
@@ -42,14 +42,16 @@ class PLATFORM_EXPORT PushPullFIFO {
public:
// Maximum FIFO length. (512 render quanta)
- static const size_t kMaxFIFOLength;
+ static const uint32_t kMaxFIFOLength;
// |fifo_length| cannot exceed |kMaxFIFOLength|. Otherwise it crashes.
// ||render_quantum_frames| is the render size used by the audio graph. It
// |defaults to 128, the original and default render size.
explicit PushPullFIFO(unsigned number_of_channels,
- size_t fifo_length,
+ uint32_t fifo_length,
unsigned render_quantum_frames = 128);
+ PushPullFIFO(const PushPullFIFO&) = delete;
+ PushPullFIFO& operator=(const PushPullFIFO&) = delete;
~PushPullFIFO();
// Pushes the rendered frames by WebAudio engine.
@@ -69,12 +71,12 @@ class PLATFORM_EXPORT PushPullFIFO {
// - In case of underflow (FIFO empty while pull), the remaining space in the
// requested output bus will be filled with silence. Thus it will fulfill
// the request from the consumer without causing error, but with a glitch.
- size_t Pull(AudioBus* output_bus, size_t frames_requested);
+ size_t Pull(AudioBus* output_bus, uint32_t frames_requested);
// Pull and update |ear_mark_frames_| to make the dual thread rendering mode
// (i.e. AudioWorklet) more smooth. The single thread rendering does not need
// this treatment.
- size_t PullAndUpdateEarmark(AudioBus* output_bus, size_t frames_requested);
+ size_t PullAndUpdateEarmark(AudioBus* output_bus, uint32_t frames_requested);
void SetEarmarkFrames(size_t earmark_frames) {
DCHECK(IsMainThread());
@@ -82,7 +84,7 @@ class PLATFORM_EXPORT PushPullFIFO {
earmark_frames_ = earmark_frames;
}
- size_t length() const { return fifo_length_; }
+ uint32_t length() const { return fifo_length_; }
unsigned NumberOfChannels() const {
lock_.AssertAcquired();
return fifo_bus_->NumberOfChannels();
@@ -105,7 +107,7 @@ class PLATFORM_EXPORT PushPullFIFO {
private:
// The size of the FIFO.
- const size_t fifo_length_ = 0;
+ const uint32_t fifo_length_ = 0;
// The render size used by the audio graph.
const unsigned render_quantum_frames_;
@@ -122,12 +124,10 @@ class PLATFORM_EXPORT PushPullFIFO {
size_t earmark_frames_ GUARDED_BY(lock_) = 0;
// The number of frames in the FIFO actually available for pulling.
- size_t frames_available_ GUARDED_BY(lock_) = 0;
+ uint32_t frames_available_ GUARDED_BY(lock_) = 0;
size_t index_read_ GUARDED_BY(lock_) = 0;
size_t index_write_ GUARDED_BY(lock_) = 0;
scoped_refptr<AudioBus> fifo_bus_ GUARDED_BY(lock_);
-
- DISALLOW_COPY_AND_ASSIGN(PushPullFIFO);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb.cc b/chromium/third_party/blink/renderer/platform/audio/reverb.cc
index f819f3e3b1b..4b71e8ea367 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb.cc
@@ -53,12 +53,12 @@ const float kMinPower = 0.000125f;
static float CalculateNormalizationScale(AudioBus* response) {
// Normalize by RMS power
- size_t number_of_channels = response->NumberOfChannels();
- size_t length = response->length();
+ unsigned number_of_channels = response->NumberOfChannels();
+ uint32_t length = response->length();
float power = 0;
- for (size_t i = 0; i < number_of_channels; ++i) {
+ for (unsigned i = 0; i < number_of_channels; ++i) {
float channel_power = 0;
vector_math::Vsvesq(response->Channel(i)->Data(), 1, &channel_power,
length);
@@ -89,8 +89,8 @@ static float CalculateNormalizationScale(AudioBus* response) {
}
Reverb::Reverb(AudioBus* impulse_response,
- size_t render_slice_size,
- size_t max_fft_size,
+ unsigned render_slice_size,
+ unsigned max_fft_size,
bool use_background_threads,
bool normalize) {
float scale = 1;
@@ -104,8 +104,8 @@ Reverb::Reverb(AudioBus* impulse_response,
}
void Reverb::Initialize(AudioBus* impulse_response_buffer,
- size_t render_slice_size,
- size_t max_fft_size,
+ unsigned render_slice_size,
+ unsigned max_fft_size,
bool use_background_threads,
float scale) {
impulse_response_length_ = impulse_response_buffer->length();
@@ -269,7 +269,7 @@ void Reverb::Process(const AudioBus* source_bus,
}
void Reverb::Reset() {
- for (size_t i = 0; i < convolvers_.size(); ++i)
+ for (wtf_size_t i = 0; i < convolvers_.size(); ++i)
convolvers_[i]->Reset();
}
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb.h b/chromium/third_party/blink/renderer/platform/audio/reverb.h
index be330787a46..d85d08a7493 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb.h
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/reverb_convolver.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -51,10 +50,12 @@ class PLATFORM_EXPORT Reverb {
// not all occur at the same time (very bad when rendering on a real-time
// thread).
Reverb(AudioBus* impulse_response_buffer,
- size_t render_slice_size,
- size_t max_fft_size,
+ unsigned render_slice_size,
+ unsigned max_fft_size,
bool use_background_threads,
bool normalize);
+ Reverb(const Reverb&) = delete;
+ Reverb& operator=(const Reverb&) = delete;
void Process(const AudioBus* source_bus,
AudioBus* destination_bus,
@@ -66,8 +67,8 @@ class PLATFORM_EXPORT Reverb {
private:
void Initialize(AudioBus* impulse_response_buffer,
- size_t render_slice_size,
- size_t max_fft_size,
+ unsigned render_slice_size,
+ unsigned max_fft_size,
bool use_background_threads,
float scale);
@@ -80,8 +81,6 @@ class PLATFORM_EXPORT Reverb {
// For "True" stereo processing
scoped_refptr<AudioBus> temp_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(Reverb);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.cc b/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.cc
index b92806e3fec..764a0626a65 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.cc
@@ -32,19 +32,19 @@
namespace blink {
-ReverbAccumulationBuffer::ReverbAccumulationBuffer(size_t length)
+ReverbAccumulationBuffer::ReverbAccumulationBuffer(uint32_t length)
: buffer_(length), read_index_(0), read_time_frame_(0) {}
void ReverbAccumulationBuffer::ReadAndClear(float* destination,
- size_t number_of_frames) {
- size_t buffer_length = buffer_.size();
+ uint32_t number_of_frames) {
+ uint32_t buffer_length = buffer_.size();
DCHECK_LE(read_index_, buffer_length);
DCHECK_LE(number_of_frames, buffer_length);
- size_t frames_available = buffer_length - read_index_;
- size_t number_of_frames1 = std::min(number_of_frames, frames_available);
- size_t number_of_frames2 = number_of_frames - number_of_frames1;
+ uint32_t frames_available = buffer_length - read_index_;
+ uint32_t number_of_frames1 = std::min(number_of_frames, frames_available);
+ uint32_t number_of_frames2 = number_of_frames - number_of_frames1;
float* source = buffer_.Data();
memcpy(destination, source + read_index_, sizeof(float) * number_of_frames1);
@@ -61,26 +61,27 @@ void ReverbAccumulationBuffer::ReadAndClear(float* destination,
read_time_frame_ += number_of_frames;
}
-void ReverbAccumulationBuffer::UpdateReadIndex(int* read_index,
- size_t number_of_frames) const {
+void ReverbAccumulationBuffer::UpdateReadIndex(
+ uint32_t* read_index,
+ uint32_t number_of_frames) const {
// Update caller's readIndex
*read_index = (*read_index + number_of_frames) % buffer_.size();
}
-int ReverbAccumulationBuffer::Accumulate(float* source,
- size_t number_of_frames,
- int* read_index,
- size_t delay_frames) {
- size_t buffer_length = buffer_.size();
+uint32_t ReverbAccumulationBuffer::Accumulate(float* source,
+ uint32_t number_of_frames,
+ uint32_t* read_index,
+ size_t delay_frames) {
+ uint32_t buffer_length = buffer_.size();
- size_t write_index = (*read_index + delay_frames) % buffer_length;
+ uint32_t write_index = (*read_index + delay_frames) % buffer_length;
// Update caller's readIndex
*read_index = (*read_index + number_of_frames) % buffer_length;
- size_t frames_available = buffer_length - write_index;
- size_t number_of_frames1 = std::min(number_of_frames, frames_available);
- size_t number_of_frames2 = number_of_frames - number_of_frames1;
+ uint32_t frames_available = buffer_length - write_index;
+ uint32_t number_of_frames1 = std::min(number_of_frames, frames_available);
+ uint32_t number_of_frames2 = number_of_frames - number_of_frames1;
float* destination = buffer_.Data();
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.h b/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.h
index ee12f0c9d48..1e63969297a 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.h
@@ -29,7 +29,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_REVERB_ACCUMULATION_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_REVERB_ACCUMULATION_BUFFER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -45,10 +44,12 @@ class PLATFORM_EXPORT ReverbAccumulationBuffer {
DISALLOW_NEW();
public:
- ReverbAccumulationBuffer(size_t length);
+ ReverbAccumulationBuffer(uint32_t length);
+ ReverbAccumulationBuffer(const ReverbAccumulationBuffer&) = delete;
+ ReverbAccumulationBuffer& operator=(const ReverbAccumulationBuffer&) = delete;
// This will read from, then clear-out numberOfFrames
- void ReadAndClear(float* destination, size_t number_of_frames);
+ void ReadAndClear(float* destination, uint32_t number_of_frames);
// Each ReverbConvolverStage will accumulate its output at the appropriate
// delay from the read position. We need to pass in and update readIndex
@@ -56,24 +57,22 @@ class PLATFORM_EXPORT ReverbAccumulationBuffer {
// than the realtime thread calling ReadAndClear() and maintaining
// m_readIndex
// Returns the writeIndex where the accumulation took place
- int Accumulate(float* source,
- size_t number_of_frames,
- int* read_index,
- size_t delay_frames);
+ uint32_t Accumulate(float* source,
+ uint32_t number_of_frames,
+ uint32_t* read_index,
+ size_t delay_frames);
- size_t ReadIndex() const { return read_index_; }
- void UpdateReadIndex(int* read_index, size_t number_of_frames) const;
+ uint32_t ReadIndex() const { return read_index_; }
+ void UpdateReadIndex(uint32_t* read_index, uint32_t number_of_frames) const;
- size_t ReadTimeFrame() const { return read_time_frame_; }
+ uint32_t ReadTimeFrame() const { return read_time_frame_; }
void Reset();
private:
AudioFloatArray buffer_;
- size_t read_index_;
- size_t read_time_frame_; // for debugging (frame on continuous timeline)
-
- DISALLOW_COPY_AND_ASSIGN(ReverbAccumulationBuffer);
+ uint32_t read_index_;
+ uint32_t read_time_frame_; // for debugging (frame on continuous timeline)
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc
index c23912975bd..4807fbb123b 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc
@@ -55,12 +55,12 @@ const int kInputBufferSize = 8 * 16384;
// be incorrect.
const size_t kRealtimeFrameLimit = 8192 + 4096; // ~278msec @ 44.1KHz
-const size_t kMinFFTSize = 128;
-const size_t kMaxRealtimeFFTSize = 2048;
+const unsigned kMinFFTSize = 128;
+const unsigned kMaxRealtimeFFTSize = 2048;
ReverbConvolver::ReverbConvolver(AudioChannel* impulse_response,
- size_t render_slice_size,
- size_t max_fft_size,
+ unsigned render_slice_size,
+ unsigned max_fft_size,
size_t convolver_render_phase,
bool use_background_threads,
float scale)
@@ -80,17 +80,17 @@ ReverbConvolver::ReverbConvolver(AudioChannel* impulse_response,
max_realtime_fft_size_ = kMaxRealtimeFFTSize;
const float* response = impulse_response->Data();
- size_t total_response_length = impulse_response->length();
+ uint32_t total_response_length = impulse_response->length();
// The total latency is zero because the direct-convolution is used in the
// leading portion.
size_t reverb_total_latency = 0;
- size_t stage_offset = 0;
+ unsigned stage_offset = 0;
int i = 0;
- size_t fft_size = min_fft_size_;
+ unsigned fft_size = min_fft_size_;
while (stage_offset < total_response_length) {
- size_t stage_size = fft_size / 2;
+ unsigned stage_size = fft_size / 2;
// For the last stage, it's possible that stageOffset is such that we're
// straddling the end of the impulse response buffer (if we use stageSize),
@@ -100,7 +100,7 @@ ReverbConvolver::ReverbConvolver(AudioChannel* impulse_response,
// This "staggers" the time when each FFT happens so they don't all happen
// at the same time
- int render_phase = convolver_render_phase + i * render_slice_size;
+ size_t render_phase = convolver_render_phase + i * render_slice_size;
bool use_direct_convolver = !stage_offset;
@@ -151,21 +151,19 @@ ReverbConvolver::~ReverbConvolver() {
void ReverbConvolver::ProcessInBackground() {
// Process all of the stages until their read indices reach the input buffer's
// write index
- int write_index = input_buffer_.WriteIndex();
+ size_t write_index = input_buffer_.WriteIndex();
// Even though it doesn't seem like every stage needs to maintain its own
// version of readIndex we do this in case we want to run in more than one
// background thread.
- int read_index;
-
- while ((read_index = background_stages_[0]->InputReadIndex()) !=
- write_index) { // FIXME: do better to detect buffer overrun...
+ // FIXME: do better to detect buffer overrun...
+ while (background_stages_[0]->InputReadIndex() != write_index) {
// The ReverbConvolverStages need to process in amounts which evenly divide
// half the FFT size
const int kSliceSize = kMinFFTSize / 2;
// Accumulate contributions from each stage
- for (size_t i = 0; i < background_stages_.size(); ++i)
+ for (wtf_size_t i = 0; i < background_stages_.size(); ++i)
background_stages_[i]->ProcessInBackground(this, kSliceSize);
}
}
@@ -187,7 +185,7 @@ void ReverbConvolver::Process(const AudioChannel* source_channel,
input_buffer_.Write(source, frames_to_process);
// Accumulate contributions from each stage
- for (size_t i = 0; i < stages_.size(); ++i)
+ for (wtf_size_t i = 0; i < stages_.size(); ++i)
stages_[i]->Process(source, frames_to_process);
// Finally read from accumulation buffer
@@ -204,10 +202,10 @@ void ReverbConvolver::Process(const AudioChannel* source_channel,
}
void ReverbConvolver::Reset() {
- for (size_t i = 0; i < stages_.size(); ++i)
+ for (wtf_size_t i = 0; i < stages_.size(); ++i)
stages_[i]->Reset();
- for (size_t i = 0; i < background_stages_.size(); ++i)
+ for (wtf_size_t i = 0; i < background_stages_.size(); ++i)
background_stages_[i]->Reset();
accumulation_buffer_.Reset();
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.h b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.h
index 1134670d4f1..a805354c413 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.h
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.h
@@ -55,11 +55,13 @@ class PLATFORM_EXPORT ReverbConvolver {
// FFT sizes and single-precision floats. In these cases 2048 is a good
// size. If not doing multi-threaded convolution, then should not go > 8192.
ReverbConvolver(AudioChannel* impulse_response,
- size_t render_slice_size,
- size_t max_fft_size,
+ unsigned render_slice_size,
+ unsigned max_fft_size,
size_t convolver_render_phase,
bool use_background_threads,
float scale);
+ ReverbConvolver(const ReverbConvolver&) = delete;
+ ReverbConvolver& operator=(const ReverbConvolver&) = delete;
~ReverbConvolver();
void Process(const AudioChannel* source_channel,
@@ -86,17 +88,15 @@ class PLATFORM_EXPORT ReverbConvolver {
// First stage will be of size m_minFFTSize. Each next stage will be twice as
// big until we hit m_maxFFTSize.
- size_t min_fft_size_;
- size_t max_fft_size_;
+ unsigned min_fft_size_;
+ unsigned max_fft_size_;
// But don't exceed this size in the real-time thread (if we're doing
// background processing).
- size_t max_realtime_fft_size_;
+ unsigned max_realtime_fft_size_;
// Background thread and synchronization
std::unique_ptr<Thread> background_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(ReverbConvolver);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.cc b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.cc
index 9c6cf41853d..bfe8bcf2856 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.cc
@@ -44,10 +44,10 @@ ReverbConvolverStage::ReverbConvolverStage(
size_t,
size_t reverb_total_latency,
size_t stage_offset,
- size_t stage_length,
- size_t fft_size,
+ unsigned stage_length,
+ unsigned fft_size,
size_t render_phase,
- size_t render_slice_size,
+ unsigned render_slice_size,
ReverbAccumulationBuffer* accumulation_buffer,
float scale,
bool direct_mode)
@@ -102,7 +102,7 @@ ReverbConvolverStage::ReverbConvolverStage(
// can schedule at exactly the moment when the FFT will happen. This is
// coordinated with the other stages, so they don't all do their FFTs at the
// same time...
- int max_pre_delay_length = std::min(half_size, total_delay);
+ size_t max_pre_delay_length = std::min(half_size, total_delay);
pre_delay_length_ = total_delay > 0 ? render_phase % max_pre_delay_length : 0;
if (pre_delay_length_ > total_delay)
pre_delay_length_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.h b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.h
index 8c0d70e5e45..60ad2ec7fbf 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.h
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver_stage.h
@@ -31,7 +31,6 @@
#include <memory>
-#include "base/macros.h"
#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/allocator.h"
@@ -58,13 +57,15 @@ class PLATFORM_EXPORT ReverbConvolverStage {
size_t response_length,
size_t reverb_total_latency,
size_t stage_offset,
- size_t stage_length,
- size_t fft_size,
+ unsigned stage_length,
+ unsigned fft_size,
size_t render_phase,
- size_t render_slice_size,
+ unsigned render_slice_size,
ReverbAccumulationBuffer*,
float scale,
bool direct_mode = false);
+ ReverbConvolverStage(const ReverbConvolverStage&) = delete;
+ ReverbConvolverStage& operator=(const ReverbConvolverStage&) = delete;
// WARNING: framesToProcess must be such that it evenly divides the delay
// buffer size (stage_offset).
@@ -76,7 +77,7 @@ class PLATFORM_EXPORT ReverbConvolverStage {
void Reset();
// Useful for background processing
- int InputReadIndex() const { return input_read_index_; }
+ size_t InputReadIndex() const { return input_read_index_; }
private:
std::unique_ptr<FFTFrame> fft_kernel_;
@@ -85,8 +86,8 @@ class PLATFORM_EXPORT ReverbConvolverStage {
AudioFloatArray pre_delay_buffer_;
ReverbAccumulationBuffer* accumulation_buffer_;
- int accumulation_read_index_;
- int input_read_index_;
+ uint32_t accumulation_read_index_;
+ size_t input_read_index_;
size_t pre_delay_length_;
size_t post_delay_length_;
@@ -97,8 +98,6 @@ class PLATFORM_EXPORT ReverbConvolverStage {
bool direct_mode_;
std::unique_ptr<DirectConvolver> direct_convolver_;
-
- DISALLOW_COPY_AND_ASSIGN(ReverbConvolverStage);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.cc b/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.cc
index aeda171b928..3fc585aa2b1 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.cc
@@ -48,11 +48,10 @@ void ReverbInputBuffer::Write(const float* source_p, size_t number_of_frames) {
SetWriteIndex(new_index);
}
-float* ReverbInputBuffer::DirectReadFrom(int* read_index,
+float* ReverbInputBuffer::DirectReadFrom(size_t* read_index,
size_t number_of_frames) {
- size_t buffer_length = buffer_.size();
+ uint32_t buffer_length = buffer_.size();
DCHECK(read_index);
- DCHECK_GE(*read_index, 0);
DCHECK_LE(*read_index + number_of_frames, buffer_length);
float* source_p = buffer_.Data();
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.h b/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.h
index 7907204b79c..f180d966fe5 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_input_buffer.h
@@ -30,7 +30,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_REVERB_INPUT_BUFFER_H_
#include <atomic>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -44,6 +43,8 @@ class PLATFORM_EXPORT ReverbInputBuffer {
public:
ReverbInputBuffer(size_t length);
+ ReverbInputBuffer(const ReverbInputBuffer&) = delete;
+ ReverbInputBuffer& operator=(const ReverbInputBuffer&) = delete;
// The realtime audio thread keeps writing samples here.
// The assumption is that the buffer's length is evenly divisible by
@@ -62,7 +63,7 @@ class PLATFORM_EXPORT ReverbInputBuffer {
// The assumption is that the buffer's length is evenly divisible by
// numberOfFrames.
// FIXME: remove numberOfFrames restriction...
- float* DirectReadFrom(int* read_index, size_t number_of_frames);
+ float* DirectReadFrom(size_t* read_index, size_t number_of_frames);
void Reset();
@@ -77,8 +78,6 @@ class PLATFORM_EXPORT ReverbInputBuffer {
// the getter and setter to access it atomically. Don't access
// directly!
std::atomic_size_t write_index_;
-
- DISALLOW_COPY_AND_ASSIGN(ReverbInputBuffer);
};
} // namespace blink
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
index 9872313a07c..dbc32f6a10a 100644
--- a/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc
@@ -8,7 +8,7 @@
namespace blink {
SimpleFFTConvolver::SimpleFFTConvolver(
- size_t input_block_size,
+ unsigned input_block_size,
const std::unique_ptr<AudioFloatArray>& convolution_kernel)
: convolution_kernel_size_(convolution_kernel->size()),
fft_kernel_(2 * input_block_size),
@@ -27,7 +27,7 @@ SimpleFFTConvolver::SimpleFFTConvolver(
void SimpleFFTConvolver::Process(const float* source_p,
float* dest_p,
uint32_t frames_to_process) {
- size_t half_size = FftSize() / 2;
+ unsigned half_size = FftSize() / 2;
// frames_to_process must be exactly half_size.
DCHECK(source_p);
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
index f8d02e0938b..505a2eaca8a 100644
--- a/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h
+++ b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#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/allocator.h"
@@ -25,8 +24,10 @@ class PLATFORM_EXPORT SimpleFFTConvolver {
public:
SimpleFFTConvolver(
- size_t input_block_size,
+ unsigned input_block_size,
const std::unique_ptr<AudioFloatArray>& convolution_kernel);
+ SimpleFFTConvolver(const SimpleFFTConvolver&) = delete;
+ SimpleFFTConvolver& operator=(const SimpleFFTConvolver&) = delete;
void Process(const float* source_p,
float* dest_p,
@@ -34,12 +35,12 @@ class PLATFORM_EXPORT SimpleFFTConvolver {
void Reset();
- size_t ConvolutionKernelSize() const { return convolution_kernel_size_; }
+ uint32_t ConvolutionKernelSize() const { return convolution_kernel_size_; }
private:
- size_t FftSize() const { return frame_.FftSize(); }
+ unsigned FftSize() const { return frame_.FftSize(); }
- size_t convolution_kernel_size_;
+ uint32_t convolution_kernel_size_;
FFTFrame fft_kernel_;
FFTFrame frame_;
@@ -52,8 +53,6 @@ class PLATFORM_EXPORT SimpleFFTConvolver {
// 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_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleFFTConvolver);
};
} // namespace blink
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 924db3f2927..a84673f1d57 100644
--- a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc
@@ -144,7 +144,8 @@ void SincResampler::ConsumeSource(float* buffer,
// FIXME: Find a way to make the following const-correct:
bus->SetChannelMemory(0, buffer, number_of_source_frames);
- source_provider_->ProvideInput(bus.get(), number_of_source_frames);
+ source_provider_->ProvideInput(
+ bus.get(), base::checked_cast<int>(number_of_source_frames));
}
namespace {
@@ -153,11 +154,11 @@ namespace {
class BufferSourceProvider final : public AudioSourceProvider {
public:
- BufferSourceProvider(const float* source, uint32_t number_of_source_frames)
+ BufferSourceProvider(const float* source, int number_of_source_frames)
: source_(source), source_frames_available_(number_of_source_frames) {}
// Consumes samples from the in-memory buffer.
- void ProvideInput(AudioBus* bus, uint32_t frames_to_process) override {
+ void ProvideInput(AudioBus* bus, int frames_to_process) override {
DCHECK(source_);
DCHECK(bus);
if (!source_ || !bus)
@@ -166,8 +167,7 @@ class BufferSourceProvider final : public AudioSourceProvider {
float* buffer = bus->Channel(0)->MutableData();
// Clamp to number of frames available and zero-pad.
- uint32_t frames_to_copy =
- std::min(source_frames_available_, frames_to_process);
+ int frames_to_copy = std::min(source_frames_available_, frames_to_process);
memcpy(buffer, source_, sizeof(float) * frames_to_copy);
// Zero-pad if necessary.
@@ -181,14 +181,14 @@ class BufferSourceProvider final : public AudioSourceProvider {
private:
const float* source_;
- uint32_t source_frames_available_;
+ int source_frames_available_;
};
} // namespace
void SincResampler::Process(const float* source,
float* destination,
- unsigned number_of_source_frames) {
+ int number_of_source_frames) {
// Resample an in-memory buffer using an AudioSourceProvider.
BufferSourceProvider source_provider(source, number_of_source_frames);
diff --git a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.h b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.h
index 68786b6a787..65f8905f309 100644
--- a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.h
@@ -29,7 +29,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SINC_RESAMPLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SINC_RESAMPLER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -51,11 +50,14 @@ class PLATFORM_EXPORT SincResampler {
unsigned kernel_size = 32,
unsigned number_of_kernel_offsets = 32);
+ SincResampler(const SincResampler&) = delete;
+ SincResampler& operator=(const SincResampler&) = delete;
+
// Processes numberOfSourceFrames from source to produce numberOfSourceFrames
// / scaleFactor frames in destination.
void Process(const float* source,
float* destination,
- unsigned number_of_source_frames);
+ int number_of_source_frames);
// Process with input source callback function for streaming applications.
void Process(AudioSourceProvider*,
@@ -95,9 +97,6 @@ class PLATFORM_EXPORT SincResampler {
// The buffer is primed once at the very beginning of processing.
bool is_buffer_primed_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SincResampler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/stereo_panner.h b/chromium/third_party/blink/renderer/platform/audio/stereo_panner.h
index 7a58743e45c..53b0916cdfb 100644
--- a/chromium/third_party/blink/renderer/platform/audio/stereo_panner.h
+++ b/chromium/third_party/blink/renderer/platform/audio/stereo_panner.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_STEREO_PANNER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_STEREO_PANNER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -21,6 +20,8 @@ class PLATFORM_EXPORT StereoPanner {
public:
explicit StereoPanner(float sample_rate);
+ StereoPanner(const StereoPanner&) = delete;
+ StereoPanner& operator=(const StereoPanner&) = delete;
~StereoPanner() = default;
void PanWithSampleAccurateValues(const AudioBus* input_bus,
@@ -31,9 +32,6 @@ class PLATFORM_EXPORT StereoPanner {
AudioBus* output_bus,
float pan_value,
uint32_t frames_to_process);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(StereoPanner);
};
} // namespace blink
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 df78152fbc2..dba34718285 100644
--- a/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc
@@ -75,7 +75,7 @@ std::unique_ptr<AudioFloatArray> MakeKernel(size_t size) {
} // namespace
-UpSampler::UpSampler(size_t input_block_size)
+UpSampler::UpSampler(unsigned input_block_size)
: input_block_size_(input_block_size),
temp_buffer_(input_block_size),
input_buffer_(input_block_size * 2) {
@@ -96,7 +96,7 @@ UpSampler::UpSampler(size_t input_block_size)
void UpSampler::Process(const float* source_p,
float* dest_p,
- size_t source_frames_to_process) {
+ uint32_t source_frames_to_process) {
const size_t convolution_kernel_size =
direct_convolver_ ? direct_convolver_->ConvolutionKernelSize()
: simple_fft_convolver_->ConvolutionKernelSize();
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 0ee63c88940..a8597ed51d6 100644
--- a/chromium/third_party/blink/renderer/platform/audio/up_sampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/up_sampler.h
@@ -33,7 +33,6 @@
#include <memory>
-#include "base/macros.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"
@@ -47,12 +46,14 @@ class PLATFORM_EXPORT UpSampler {
USING_FAST_MALLOC(UpSampler);
public:
- explicit UpSampler(size_t input_block_size);
+ explicit UpSampler(unsigned input_block_size);
+ UpSampler(const UpSampler&) = delete;
+ UpSampler& operator=(const UpSampler&) = delete;
// The destination buffer |destP| is of size sourceFramesToProcess * 2.
void Process(const float* source_p,
float* dest_p,
- size_t source_frames_to_process);
+ uint32_t source_frames_to_process);
void Reset();
@@ -62,7 +63,7 @@ class PLATFORM_EXPORT UpSampler {
private:
enum { kDefaultKernelSize = 128 };
- size_t input_block_size_;
+ unsigned input_block_size_;
// Computes the odd sample-frames of the output.
std::unique_ptr<DirectConvolver> direct_convolver_;
@@ -75,8 +76,6 @@ class PLATFORM_EXPORT UpSampler {
// the FIR filter (convolution) used to generate the odd sample-frames of the
// output.
AudioFloatArray input_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(UpSampler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
index 542b3d2cf47..24b700d6240 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ACTIVE_SCRIPT_WRAPPABLE_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ACTIVE_SCRIPT_WRAPPABLE_BASE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "v8/include/v8.h"
@@ -19,6 +18,9 @@ namespace blink {
*/
class PLATFORM_EXPORT ActiveScriptWrappableBase : public GarbageCollectedMixin {
public:
+ ActiveScriptWrappableBase(const ActiveScriptWrappableBase&) = delete;
+ ActiveScriptWrappableBase& operator=(const ActiveScriptWrappableBase&) =
+ delete;
virtual ~ActiveScriptWrappableBase() = default;
virtual bool IsContextDestroyed() const = 0;
@@ -36,9 +38,6 @@ class PLATFORM_EXPORT ActiveScriptWrappableBase : public GarbageCollectedMixin {
protected:
ActiveScriptWrappableBase() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ActiveScriptWrappableBase);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc
index ae00908b3f7..f41ba6170d0 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc
@@ -37,23 +37,12 @@ void ActiveScriptWrappableManager::RecomputeActiveScriptWrappables(
return;
ThreadState::NoAllocationScope no_allocations(ThreadState::Current());
for (auto& pair : active_script_wrappables_) {
- if (!ScriptWrappableIsActive(*pair.first) || pair.second)
- continue;
- pair.second = pair.first.Get();
+ pair.second =
+ ScriptWrappableIsActive(*pair.first) ? pair.first.Get() : nullptr;
}
recomputed_cnt_++;
}
-void ActiveScriptWrappableManager::IterateActiveScriptWrappables(
- Visitor* visitor) {
- RecomputeActiveScriptWrappables(RecomputeMode::kRequired);
- for (auto& pair : active_script_wrappables_) {
- visitor->Trace(pair.second);
- pair.second = nullptr;
- }
- recomputed_cnt_ = 0;
-}
-
void ActiveScriptWrappableManager::
CleanupInactiveAndClearActiveScriptWrappables(
const LivenessBroker& broker) {
@@ -63,8 +52,6 @@ void ActiveScriptWrappableManager::
[broker](auto& pair) {
// If the ASW is not alive, the Member reference must be nullptr.
DCHECK(broker.IsHeapObjectAlive(pair.first) || !pair.second);
- // Clear out Member reference in any case.
- pair.second = nullptr;
return !broker.IsHeapObjectAlive(pair.first);
}),
active_script_wrappables_.end());
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h
index 2abc344ec1e..375d48b61b4 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ACTIVE_SCRIPT_WRAPPABLE_MANAGER_H_
#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.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/heap/heap.h"
@@ -19,7 +20,8 @@ namespace blink {
// ASWM integrates with the GC through prologue and weakness callbacks which are
// not allowed to allocate.
class PLATFORM_EXPORT ActiveScriptWrappableManager final
- : public GarbageCollected<ActiveScriptWrappableManager> {
+ : public GarbageCollected<ActiveScriptWrappableManager>,
+ public NameClient {
public:
enum class RecomputeMode { kOpportunistic, kRequired };
@@ -44,13 +46,11 @@ class PLATFORM_EXPORT ActiveScriptWrappableManager final
// Called during GC prologue. Not allowed to allocate.
void RecomputeActiveScriptWrappables(RecomputeMode);
- // Iterate the current set of active ScriptWrappable objects.
- //
- // Does not allocate.
- void IterateActiveScriptWrappables(Visitor*);
-
void Trace(Visitor* visitor) const;
+ // NameClient implementation.
+ const char* NameInHeapSnapshot() const final { return "Pending activities"; }
+
private:
// Called during weakness processing. Not allowed to allocate. The next Add()
// call ensures reasonable capacities.
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 dc28cd23f3d..2446d46d7df 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
@@ -26,7 +26,7 @@ class PLATFORM_EXPORT CallbackFunctionBase
: public GarbageCollected<CallbackFunctionBase>,
public NameClient {
public:
- virtual ~CallbackFunctionBase() = default;
+ ~CallbackFunctionBase() override = default;
virtual void Trace(Visitor* visitor) const;
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 620685ae3e1..08f52899d65 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
@@ -32,7 +32,7 @@ class PLATFORM_EXPORT CallbackInterfaceBase
kSingleOperation,
};
- virtual ~CallbackInterfaceBase() = default;
+ ~CallbackInterfaceBase() override = default;
virtual void Trace(Visitor*) const;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
index 652ff138557..e19f2a86ca7 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
@@ -25,6 +25,8 @@ class PLATFORM_EXPORT CallbackMethodRetriever {
public:
explicit CallbackMethodRetriever(CallbackFunctionBase* constructor);
+ CallbackMethodRetriever(const CallbackMethodRetriever&) = delete;
+ CallbackMethodRetriever& operator=(const CallbackMethodRetriever&) = delete;
// Get the prototype object from the callback function. Must be invoked prior
// to GetMethod or GetStaticMethod.
@@ -79,8 +81,6 @@ class PLATFORM_EXPORT CallbackMethodRetriever {
v8::Isolate* isolate_;
v8::Local<v8::Context> current_context_;
v8::Local<v8::Object> prototype_object_;
-
- DISALLOW_COPY_AND_ASSIGN(CallbackMethodRetriever);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h b/chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h
index 86af271f5b7..52dd13339a8 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CUSTOM_WRAPPABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CUSTOM_WRAPPABLE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -16,15 +15,14 @@ class PLATFORM_EXPORT CustomWrappable
: public GarbageCollected<CustomWrappable>,
public NameClient {
public:
- virtual ~CustomWrappable() = default;
+ CustomWrappable(const CustomWrappable&) = delete;
+ CustomWrappable& operator=(const CustomWrappable&) = delete;
+ ~CustomWrappable() override = default;
virtual void Trace(Visitor*) const {}
const char* NameInHeapSnapshot() const override { return "CustomWrappable"; }
protected:
CustomWrappable() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CustomWrappable);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.cc b/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.cc
new file mode 100644
index 00000000000..d37905b2dc4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.cc
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/bindings/dictionary_base.h"
+
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+namespace bindings {
+
+v8::MaybeLocal<v8::Value> DictionaryBase::ToV8Value(
+ ScriptState* script_state) const {
+ v8::Local<v8::Object> v8_dictionary;
+ {
+ v8::Context::Scope context_scope(script_state->GetContext());
+ v8_dictionary = v8::Object::New(script_state->GetIsolate());
+ }
+
+ if (!FillV8ObjectWithMembers(script_state, v8_dictionary))
+ return v8::MaybeLocal<v8::Value>();
+
+ return v8_dictionary;
+}
+
+} // namespace bindings
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h b/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h
index 97bebe268ba..431e08d0edd 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h
@@ -11,43 +11,36 @@
namespace blink {
+class ScriptState;
+
namespace bindings {
-// This class is the base class for all IDL dictionary implementations. This is
-// designed to collaborate with NativeValueTraits and ToV8 with supporting type
-// dispatching (SFINAE, etc.).
+// DictionaryBase is the common base class of all the IDL dictionary classes.
+// Most importantly this class provides a way of type dispatching (e.g. overload
+// resolutions, SFINAE technique, etc.) so that it's possible to distinguish
+// IDL dictionaries from anything else. Also it provides a common
+// implementation of IDL dictionaries.
class PLATFORM_EXPORT DictionaryBase : public GarbageCollected<DictionaryBase> {
public:
virtual ~DictionaryBase() = default;
- v8::Local<v8::Value> CreateV8Object(
- v8::Isolate* isolate,
- v8::Local<v8::Object> creation_context) const {
- v8::Local<v8::Context> context = creation_context->CreationContext();
- DCHECK(!context.IsEmpty());
- v8::Local<v8::Object> v8_object;
- {
- v8::Context::Scope context_scope(context);
- v8_object = v8::Object::New(isolate);
- }
- FillWithMembers(isolate, creation_context, v8_object);
- return v8_object;
- }
+ v8::MaybeLocal<v8::Value> ToV8Value(ScriptState* script_state) const;
virtual void Trace(Visitor*) const {}
protected:
DictionaryBase() = default;
- explicit DictionaryBase(v8::Isolate* isolate) {}
DictionaryBase(const DictionaryBase&) = delete;
DictionaryBase(const DictionaryBase&&) = delete;
DictionaryBase& operator=(const DictionaryBase&) = delete;
DictionaryBase& operator=(const DictionaryBase&&) = delete;
- virtual bool FillWithMembers(v8::Isolate* isolate,
- v8::Local<v8::Object> creation_context,
- v8::Local<v8::Object> v8_object) const = 0;
+ // Fills the given v8::Object with the dictionary members. Returns true on
+ // success, otherwise returns false with throwing an exception.
+ virtual bool FillV8ObjectWithMembers(
+ ScriptState* script_state,
+ v8::Local<v8::Object> v8_dictionary) const = 0;
};
} // namespace bindings
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 697b071dd95..384b5ee0272 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 "base/macros.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
@@ -110,6 +108,8 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
}
DOMDataStore(v8::Isolate* isolate, bool is_main_world);
+ DOMDataStore(const DOMDataStore&) = delete;
+ DOMDataStore& operator=(const DOMDataStore&) = delete;
// Clears all references.
void Dispose();
@@ -203,8 +203,6 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
HeapHashMap<WeakMember<const ScriptWrappable>,
TraceWrapperV8Reference<v8::Object>>
wrapper_map_;
-
- DISALLOW_COPY_AND_ASSIGN(DOMDataStore);
};
} // namespace blink
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 1f6e80bb0f3..54096d344be 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
@@ -206,7 +206,7 @@ static IsolatedWorldStableIdMap& IsolatedWorldStableIds() {
String DOMWrapperWorld::NonMainWorldStableId() const {
DCHECK(!IsMainWorld());
- return IsolatedWorldStableIds().at(GetWorldId());
+ return IsolatedWorldStableIds().DeprecatedAtOrEmptyValue(GetWorldId());
}
void DOMWrapperWorld::SetNonMainWorldStableId(int32_t world_id,
@@ -226,7 +226,8 @@ static IsolatedWorldHumanReadableNameMap& IsolatedWorldHumanReadableNames() {
String DOMWrapperWorld::NonMainWorldHumanReadableName() const {
DCHECK(!IsMainWorld());
- return IsolatedWorldHumanReadableNames().at(GetWorldId());
+ return IsolatedWorldHumanReadableNames().DeprecatedAtOrEmptyValue(
+ GetWorldId());
}
void DOMWrapperWorld::SetNonMainWorldHumanReadableName(
diff --git a/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h b/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h
index 4159ba6abcb..5f2fd424818 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h
@@ -75,7 +75,7 @@ typename std::enable_if_t<
bool>
operator==(const EnumTypeClass& lhs, const EnumTypeClass& rhs) {
DCHECK(!lhs.IsEmpty() && !rhs.IsEmpty());
- return lhs.AsCStr() == rhs.AsCStr();
+ return lhs.AsEnum() == rhs.AsEnum();
}
template <typename EnumTypeClass>
@@ -83,8 +83,41 @@ typename std::enable_if_t<
std::is_base_of<bindings::EnumerationBase, EnumTypeClass>::value,
bool>
operator!=(const EnumTypeClass& lhs, const EnumTypeClass& rhs) {
- DCHECK(!lhs.IsEmpty() && !rhs.IsEmpty());
- return lhs.AsCStr() != rhs.AsCStr();
+ return !(lhs == rhs);
+}
+
+template <typename EnumTypeClass>
+typename std::enable_if_t<
+ std::is_base_of<bindings::EnumerationBase, EnumTypeClass>::value,
+ bool>
+operator==(const EnumTypeClass& lhs, typename EnumTypeClass::Enum rhs) {
+ DCHECK(!lhs.IsEmpty());
+ return lhs.AsEnum() == rhs;
+}
+
+template <typename EnumTypeClass>
+typename std::enable_if_t<
+ std::is_base_of<bindings::EnumerationBase, EnumTypeClass>::value,
+ bool>
+operator==(typename EnumTypeClass::Enum lhs, const EnumTypeClass& rhs) {
+ DCHECK(!rhs.IsEmpty());
+ return lhs == rhs.AsEnum();
+}
+
+template <typename EnumTypeClass>
+typename std::enable_if_t<
+ std::is_base_of<bindings::EnumerationBase, EnumTypeClass>::value,
+ bool>
+operator!=(const EnumTypeClass& lhs, typename EnumTypeClass::Enum rhs) {
+ return !(lhs == rhs);
+}
+
+template <typename EnumTypeClass>
+typename std::enable_if_t<
+ std::is_base_of<bindings::EnumerationBase, EnumTypeClass>::value,
+ bool>
+operator!=(typename EnumTypeClass::Enum lhs, const EnumTypeClass& rhs) {
+ return !(lhs == rhs);
}
// Migration adapters
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_context.h b/chromium/third_party/blink/renderer/platform/bindings/exception_context.h
index dd74cc1e962..ffb2ee50c37 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/exception_context.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_context.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_CONTEXT_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -124,6 +123,13 @@ class PLATFORM_EXPORT ExceptionContext final {
const char* GetPropertyName() const { return property_name_; }
int16_t GetArgumentIndex() const { return argument_index_; }
+ // This is used for a performance hack to reduce the number of construction
+ // and destruction times of ExceptionContext when iterating over properties.
+ // Only the generated bindings code is allowed to use this hack.
+ void ChangePropertyNameAsOptimizationHack(const char* property_name) {
+ property_name_ = property_name;
+ }
+
private:
Context context_ = Context::kEmpty;
int16_t argument_index_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc
index 057f8b7d6e8..f567d346ad2 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc
@@ -32,6 +32,7 @@
#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"
namespace blink {
@@ -195,6 +196,61 @@ String ExceptionMessages::OrdinalNumber(int number) {
return String::Number(number) + suffix;
}
+String ExceptionMessages::IndexExceedsMaximumBound(const char* name,
+ bool eq,
+ const String& given,
+ const String& bound) {
+ StringBuilder result;
+ result.Append("The ");
+ result.Append(name);
+ result.Append(" provided (");
+ result.Append(given);
+ result.Append(") is greater than ");
+ result.Append(eq ? "or equal to " : "");
+ result.Append("the maximum bound (");
+ result.Append(bound);
+ result.Append(").");
+ return result.ToString();
+}
+
+String ExceptionMessages::IndexExceedsMinimumBound(const char* name,
+ bool eq,
+ const String& given,
+ const String& bound) {
+ StringBuilder result;
+ result.Append("The ");
+ result.Append(name);
+ result.Append(" provided (");
+ result.Append(given);
+ result.Append(") is less than ");
+ result.Append(eq ? "or equal to " : "");
+ result.Append("the minimum bound (");
+ result.Append(bound);
+ result.Append(").");
+ return result.ToString();
+}
+
+String ExceptionMessages::IndexOutsideRange(const char* name,
+ const String& given,
+ const String& lower_bound,
+ BoundType lower_type,
+ const String& upper_bound,
+ BoundType upper_type) {
+ StringBuilder result;
+ result.Append("The ");
+ result.Append(name);
+ result.Append(" provided (");
+ result.Append(given);
+ result.Append(") is outside the range ");
+ result.Append(lower_type == kExclusiveBound ? '(' : '[');
+ result.Append(lower_bound);
+ result.Append(", ");
+ result.Append(upper_bound);
+ result.Append(upper_type == kExclusiveBound ? ')' : ']');
+ result.Append('.');
+ return result.ToString();
+}
+
String ExceptionMessages::ReadOnly(const char* detail) {
DEFINE_STATIC_LOCAL(String, read_only, ("This object is read-only."));
return detail
@@ -202,6 +258,12 @@ String ExceptionMessages::ReadOnly(const char* detail) {
: read_only;
}
+String ExceptionMessages::SharedArrayBufferNotAllowed(
+ const char* expected_type) {
+ return String::Format("The provided %s value must not be shared.",
+ expected_type);
+}
+
String ExceptionMessages::ValueNotOfType(const char* expected_type) {
return String::Format("The provided value is not of type '%s'.",
expected_type);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h
index 0d4f4bbb097..5a95220e1f4 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h
@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/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 {
@@ -92,36 +91,16 @@ class PLATFORM_EXPORT ExceptionMessages {
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();
+ return IndexExceedsMaximumBound(name, given == bound, FormatNumber(given),
+ FormatNumber(bound));
}
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();
+ return IndexExceedsMinimumBound(name, given == bound, FormatNumber(given),
+ FormatNumber(bound));
}
template <typename NumberType>
@@ -131,19 +110,9 @@ class PLATFORM_EXPORT ExceptionMessages {
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();
+ return IndexOutsideRange(name, FormatNumber(given),
+ FormatNumber(lower_bound), lower_type,
+ FormatNumber(upper_bound), upper_type);
}
static String InvalidArity(const char* expected, unsigned provided);
@@ -158,6 +127,8 @@ class PLATFORM_EXPORT ExceptionMessages {
static String ReadOnly(const char* detail = nullptr);
+ static String SharedArrayBufferNotAllowed(const char* expected_type);
+
static String ValueNotOfType(const char* expected_type);
private:
@@ -180,6 +151,23 @@ class PLATFORM_EXPORT ExceptionMessages {
}
static String OrdinalNumber(int number);
+
+ static String IndexExceedsMaximumBound(const char* name,
+ bool eq,
+ const String& given,
+ const String& bound);
+
+ static String IndexExceedsMinimumBound(const char* name,
+ bool eq,
+ const String& given,
+ const String& bound);
+
+ static String IndexOutsideRange(const char* name,
+ const String& given,
+ const String& lower_bound,
+ BoundType lower_type,
+ const String& upper_bound,
+ BoundType upper_type);
};
template <>
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc b/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc
index 790fc65156e..36c42c9d23a 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc
@@ -194,7 +194,7 @@ void ExceptionState::PushContextScope(ContextScope* scope) {
}
void ExceptionState::PopContextScope() {
- DCHECK(!context_stack_top_);
+ DCHECK(context_stack_top_);
context_stack_top_ = context_stack_top_->GetParent();
}
@@ -207,31 +207,35 @@ String AddContextToMessage(const String& message,
const String& m = message;
switch (context.GetContext()) {
- case ExceptionState::kConstructionContext:
+ case ExceptionContext::Context::kConstructorOperationInvoke:
return ExceptionMessages::FailedToConstruct(c, m);
- case ExceptionState::kExecutionContext:
+ case ExceptionContext::Context::kOperationInvoke:
return ExceptionMessages::FailedToExecute(p, c, m);
- case ExceptionState::kGetterContext:
+ case ExceptionContext::Context::kAttributeGet:
return ExceptionMessages::FailedToGet(p, c, m);
- case ExceptionState::kSetterContext:
+ case ExceptionContext::Context::kAttributeSet:
return ExceptionMessages::FailedToSet(p, c, m);
- case ExceptionState::kEnumerationContext:
+ case ExceptionContext::Context::kNamedPropertyEnumerate:
return ExceptionMessages::FailedToEnumerate(c, m);
- case ExceptionState::kQueryContext:
+ case ExceptionContext::Context::kNamedPropertyQuery:
break;
- case ExceptionState::kIndexedGetterContext:
+ case ExceptionContext::Context::kIndexedPropertyGet:
return ExceptionMessages::FailedToGetIndexed(c, m);
- case ExceptionState::kIndexedSetterContext:
+ case ExceptionContext::Context::kIndexedPropertySet:
return ExceptionMessages::FailedToSetIndexed(c, m);
- case ExceptionState::kIndexedDeletionContext:
+ case ExceptionContext::Context::kIndexedPropertyDelete:
return ExceptionMessages::FailedToDeleteIndexed(c, m);
- case ExceptionState::kNamedGetterContext:
+ case ExceptionContext::Context::kNamedPropertyGet:
return ExceptionMessages::FailedToGetNamed(c, m);
- case ExceptionState::kNamedSetterContext:
+ case ExceptionContext::Context::kNamedPropertySet:
return ExceptionMessages::FailedToSetNamed(c, m);
- case ExceptionState::kNamedDeletionContext:
+ case ExceptionContext::Context::kNamedPropertyDelete:
return ExceptionMessages::FailedToDeleteNamed(c, m);
- case ExceptionState::kUnknownContext:
+ case ExceptionContext::Context::kDictionaryMemberGet:
+ return ExceptionMessages::FailedToGet(p, c, m);
+ case ExceptionContext::Context::kDictionaryMemberSet:
+ return ExceptionMessages::FailedToSet(p, c, m);
+ case ExceptionContext::Context::kUnknown:
break;
default:
NOTREACHED();
@@ -256,6 +260,15 @@ String ExceptionState::AddExceptionContext(
return message;
}
+void ExceptionState::PropagateException() {
+ // This is the non-inlined part of the destructor. Not inlining this part
+ // deoptimizes use cases where exceptions are thrown, but it reduces binary
+ // size and results in better performance due to improved code locality in
+ // the bindings for the most frequently used code path (cases where no
+ // exception is thrown).
+ V8ThrowException::ThrowException(isolate_, exception_.NewLocal(isolate_));
+}
+
NonThrowableExceptionState::NonThrowableExceptionState()
: ExceptionState(nullptr,
ExceptionState::kUnknownContext,
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_state.h b/chromium/third_party/blink/renderer/platform/bindings/exception_state.h
index 3f31d439537..9ba5753c7f1 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/exception_state.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_state.h
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/exception_context.h"
@@ -99,6 +98,13 @@ class PLATFORM_EXPORT ExceptionState {
~ContextScope() { exception_state_.PopContextScope(); }
+ // This is used for a performance hack to reduce the number of construction
+ // and destruction times of ContextScope when iterating over properties.
+ // Only the generated bindings code is allowed to use this hack.
+ void ChangePropertyNameAsOptimizationHack(const char* property_name) {
+ context_.ChangePropertyNameAsOptimizationHack(property_name);
+ }
+
private:
void SetParent(const ContextScope* parent) { parent_ = parent; }
const ContextScope* GetParent() const { return parent_; }
@@ -106,7 +112,7 @@ class PLATFORM_EXPORT ExceptionState {
ExceptionState& exception_state_;
const ContextScope* parent_ = nullptr;
- const ExceptionContext context_;
+ ExceptionContext context_;
friend class ExceptionState;
};
@@ -141,9 +147,12 @@ class PLATFORM_EXPORT ExceptionState {
: ExceptionState(isolate,
ExceptionContext(context_type, interface_name)) {}
+ ExceptionState(const ExceptionState&) = delete;
+ ExceptionState& operator=(const ExceptionState&) = delete;
+
~ExceptionState() {
- if (!exception_.IsEmpty()) {
- V8ThrowException::ThrowException(isolate_, exception_.NewLocal(isolate_));
+ if (UNLIKELY(!exception_.IsEmpty())) {
+ PropagateException();
}
}
@@ -197,7 +206,7 @@ class PLATFORM_EXPORT ExceptionState {
const String& Message() const { return message_; }
- v8::Local<v8::Value> GetException() {
+ virtual v8::Local<v8::Value> GetException() {
DCHECK(!exception_.IsEmpty());
return exception_.NewLocal(isolate_);
}
@@ -208,11 +217,12 @@ class PLATFORM_EXPORT ExceptionState {
return main_context_;
}
- // Deprecated APIs to get information about where this ExceptionState has
- // been created.
- ContextType Context() const { return GetContext().GetContext(); }
- const char* PropertyName() const { return GetContext().GetPropertyName(); }
- const char* InterfaceName() const { return GetContext().GetClassName(); }
+ // Returns the innermost context of the nested exception contexts.
+ const ExceptionContext& GetInnerMostContext() const {
+ if (context_stack_top_)
+ return context_stack_top_->GetContext();
+ return main_context_;
+ }
protected:
void SetException(ExceptionCode, const String&, v8::Local<v8::Value>);
@@ -222,6 +232,7 @@ class PLATFORM_EXPORT ExceptionState {
private:
void PushContextScope(ContextScope* scope);
void PopContextScope();
+ void PropagateException();
String AddExceptionContext(const String&) const;
@@ -247,7 +258,6 @@ class PLATFORM_EXPORT ExceptionState {
TraceWrapperV8Reference<v8::Value> exception_;
friend class ContextScope;
- DISALLOW_COPY_AND_ASSIGN(ExceptionState);
};
// NonThrowableExceptionState never allow call sites to throw an exception.
@@ -309,6 +319,9 @@ class PLATFORM_EXPORT DummyExceptionStateForTesting final
void ThrowWasmCompileError(const String& message) override;
void RethrowV8Exception(v8::Local<v8::Value>) override;
ExceptionState& ReturnThis() { return *this; }
+ v8::Local<v8::Value> GetException() override {
+ return v8::Local<v8::Value>();
+ }
};
// Syntax sugar for DummyExceptionStateForTesting.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.cc b/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.cc
index 1f6f792da3f..90a743b2bda 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.cc
@@ -137,7 +137,8 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
v8::Local<v8::Signature> signature,
v8::Local<v8::String> name,
const Config& config,
- const v8::CFunction* v8_c_function = nullptr) {
+ const v8::CFunction* v8_cfunction_table_data = nullptr,
+ uint32_t v8_cfunction_table_size = 0) {
v8::FunctionCallback callback = GetConfigCallback<kind>(config);
if (!callback)
return v8::Local<v8::FunctionTemplate>();
@@ -152,9 +153,10 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
(v8_cached_accessor ==
V8PrivateProperty::CachedAccessor::kWindowDocument &&
!world.IsMainWorld())) {
- function_template = v8::FunctionTemplate::New(
+ function_template = v8::FunctionTemplate::NewWithCFunctionOverloads(
isolate, callback, v8::Local<v8::Value>(), signature, length,
- v8::ConstructorBehavior::kThrow, v8_side_effect, v8_c_function);
+ v8::ConstructorBehavior::kThrow, v8_side_effect,
+ {v8_cfunction_table_data, v8_cfunction_table_size});
} else {
function_template = v8::FunctionTemplate::NewWithCache(
isolate, callback,
@@ -180,12 +182,14 @@ v8::Local<v8::Function> CreateFunction(
v8::Local<v8::Signature> signature,
v8::Local<v8::String> name,
const Config& config,
- const v8::CFunction* v8_c_function = nullptr) {
+ const v8::CFunction* v8_cfunction_table_data = nullptr,
+ uint32_t v8_cfunction_table_size = 0) {
if (!GetConfigCallback<kind>(config))
return v8::Local<v8::Function>();
return CreateFunctionTemplate<kind>(isolate, world, signature, name, config,
- v8_c_function)
+ v8_cfunction_table_data,
+ v8_cfunction_table_size)
->GetFunction(context)
.ToLocalChecked();
}
@@ -298,7 +302,8 @@ void InstallOperation(v8::Isolate* isolate,
v8::Local<v8::Template> interface_template,
v8::Local<v8::Signature> signature,
const IDLMemberInstaller::OperationConfig& config,
- const v8::CFunction* v8_c_function = nullptr) {
+ const v8::CFunction* v8_cfunction_table_data = nullptr,
+ uint32_t v8_cfunction_table_size = 0) {
if (!DoesWorldMatch(config, world))
return;
@@ -313,7 +318,8 @@ void InstallOperation(v8::Isolate* isolate,
v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
v8::Local<v8::FunctionTemplate> func =
CreateFunctionTemplate<FunctionKind::kOperation>(
- isolate, world, signature, name, config, v8_c_function);
+ isolate, world, signature, name, config, v8_cfunction_table_data,
+ v8_cfunction_table_size);
v8::Local<v8::Template> target_template;
switch (location) {
@@ -342,7 +348,8 @@ void InstallOperation(v8::Isolate* isolate,
v8::Local<v8::Object> interface_object,
v8::Local<v8::Signature> signature,
const IDLMemberInstaller::OperationConfig& config,
- const v8::CFunction* v8_c_function = nullptr) {
+ const v8::CFunction* v8_cfunction_table_data = nullptr,
+ uint32_t v8_cfunction_table_size = 0) {
if (!DoesWorldMatch(config, world))
return;
@@ -356,7 +363,8 @@ void InstallOperation(v8::Isolate* isolate,
v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
v8::Local<v8::Function> func = CreateFunction<FunctionKind::kOperation>(
- isolate, context, world, signature, name, config, v8_c_function);
+ isolate, context, world, signature, name, config, v8_cfunction_table_data,
+ v8_cfunction_table_size);
v8::Local<v8::Object> target_object;
switch (location) {
@@ -511,7 +519,8 @@ void IDLMemberInstaller::InstallOperations(
for (const auto& config : configs) {
InstallOperation(isolate, world, instance_template, prototype_template,
interface_template, signature, config.operation_config,
- &config.v8_c_function);
+ config.v8_cfunction_table_data,
+ config.v8_cfunction_table_size);
}
}
@@ -528,7 +537,8 @@ void IDLMemberInstaller::InstallOperations(
for (const auto& config : configs) {
InstallOperation(isolate, context, world, instance_object, prototype_object,
interface_object, signature, config.operation_config,
- &config.v8_c_function);
+ config.v8_cfunction_table_data,
+ config.v8_cfunction_table_size);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.h b/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.h
index 434d24663ac..2d09b2f35cd 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/idl_member_installer.h
@@ -138,7 +138,8 @@ class PLATFORM_EXPORT IDLMemberInstaller final {
struct NoAllocDirectCallOperationConfig {
OperationConfig operation_config;
- v8::CFunction v8_c_function;
+ const v8::CFunction* v8_cfunction_table_data;
+ uint32_t v8_cfunction_table_size;
};
static void InstallOperations(
v8::Isolate* isolate,
diff --git a/chromium/third_party/blink/renderer/platform/bindings/name_client.h b/chromium/third_party/blink/renderer/platform/bindings/name_client.h
index 222ea1bdeb9..f6e4cfb53b1 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/name_client.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/name_client.h
@@ -5,9 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/bindings/buildflags.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/buildflags.h"
+
+#if BUILDFLAG(USE_V8_OILPAN)
+#include "v8/include/cppgc/name-provider.h"
+#endif // BUILDFLAG(USE_V8_OILPAN)
namespace blink {
@@ -36,6 +40,26 @@ namespace blink {
// Don't:
// class Bar : public GarbageCollected<Bar> {...};
// class Baz : public Bar, public NameClient {...};
+#if BUILDFLAG(USE_V8_OILPAN)
+
+class PLATFORM_EXPORT NameClient : public cppgc::NameProvider {
+ public:
+ NameClient() = default;
+ NameClient(const NameClient&) = delete;
+ NameClient& operator=(const NameClient&) = delete;
+ ~NameClient() override = default;
+
+ // Human-readable name of this object. The DevTools heap snapshot uses
+ // this method to show the object.
+ virtual const char* NameInHeapSnapshot() const = 0;
+
+ const char* GetHumanReadableName() const final {
+ return NameInHeapSnapshot();
+ }
+};
+
+#else // !USE_V8_OILPAN
+
class PLATFORM_EXPORT NameClient {
public:
static constexpr bool HideInternalName() {
@@ -48,16 +72,17 @@ class PLATFORM_EXPORT NameClient {
}
NameClient() = default;
- ~NameClient() = default;
+ NameClient(const NameClient&) = delete;
+ NameClient& operator=(const NameClient&) = delete;
+ virtual ~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;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NameClient);
};
+#endif // !USE_V8_OILPAN
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.cc b/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.cc
index f6f78f2888b..5434fad7c18 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.cc
@@ -60,10 +60,4 @@ void NoAllocDirectCallExceptionState::ClearException() {
deferred_exception_.Reset();
}
-NoAllocDirectCallExceptionState::~NoAllocDirectCallExceptionState() {
- if (deferred_exception_) {
- host_->PostDeferrableAction(std::move(deferred_exception_));
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.h b/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.h
index 40a0e10b1dc..c782c0af414 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/no_alloc_direct_call_host.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
@@ -14,6 +15,8 @@ namespace blink {
// When a Throw* method is called, the creation of the exception object is
// deferred using the deferral mechanism provided by NoAllocDirectCallHost.
class PLATFORM_EXPORT NoAllocDirectCallExceptionState : public ExceptionState {
+ STACK_ALLOCATED();
+
public:
NoAllocDirectCallExceptionState(NoAllocDirectCallHost* host,
v8::Isolate* isolate,
@@ -21,9 +24,19 @@ class PLATFORM_EXPORT NoAllocDirectCallExceptionState : public ExceptionState {
const char* interface_name,
const char* property_name)
: ExceptionState(isolate, context_type, interface_name, property_name),
- host_(host) {}
+ host_(host),
+ deferred_exception_() // Explicit init necessary because of union.
+ {}
- virtual ~NoAllocDirectCallExceptionState();
+ // Performance hack: since this class is always allocated on the stack, we
+ // know it will never be destroyed via a base type pointer. Therefore it
+ // is safe for the destructor to be non-virtual, which allows it to be
+ // inlined.
+ ALWAYS_INLINE ~NoAllocDirectCallExceptionState() {
+ if (UNLIKELY(deferred_exception_)) {
+ host_->PostDeferrableAction(std::move(deferred_exception_));
+ }
+ }
void ThrowDOMException(DOMExceptionCode, const String& message) override;
void ThrowTypeError(const String& message) override;
@@ -37,7 +50,17 @@ class PLATFORM_EXPORT NoAllocDirectCallExceptionState : public ExceptionState {
private:
NoAllocDirectCallHost* host_;
- NoAllocDirectCallHost::DeferrableAction deferred_exception_;
+
+ // Performance hack: The use of a "union" here prevents deferred_exception_
+ // from being destroyed automatically by the destructor of
+ // NoAllocDirectCallExceptionState, which removes an unnecessary non-inlinable
+ // call to CallbackBase::~CallbackBase. It is safe to free
+ // deferred_exception_ without calling its destructor because the logic in
+ // ~NoAllocDirectCallExceptionState already guarantees that
+ // deferred_exception_'s internal reference is null.
+ union {
+ NoAllocDirectCallHost::DeferrableAction deferred_exception_;
+ };
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.cc b/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.cc
index c90185a73ac..028bd549916 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.cc
@@ -4,72 +4,8 @@
#include "third_party/blink/renderer/platform/bindings/origin_trial_features.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/runtime_enabled_features.h"
-
namespace blink {
-void InstallOriginTrialFeaturesDefault(
- const WrapperTypeInfo* wrapper_type_info,
- const ScriptState* script_state,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object) {}
-
-void InstallPendingOriginTrialFeatureDefault(OriginTrialFeature feature,
- const ScriptState* script_state) {}
-
-namespace {
-InstallOriginTrialFeaturesFunction g_install_origin_trial_features_function =
- &InstallOriginTrialFeaturesDefault;
-
-InstallPendingOriginTrialFeatureFunction
- g_install_pending_origin_trial_feature_function =
- &InstallPendingOriginTrialFeatureDefault;
-} // namespace
-
-InstallOriginTrialFeaturesFunction SetInstallOriginTrialFeaturesFunction(
- InstallOriginTrialFeaturesFunction
- new_install_origin_trial_features_function) {
- InstallOriginTrialFeaturesFunction original_function =
- g_install_origin_trial_features_function;
- g_install_origin_trial_features_function =
- new_install_origin_trial_features_function;
- return original_function;
-}
-
-InstallPendingOriginTrialFeatureFunction
-SetInstallPendingOriginTrialFeatureFunction(
- InstallPendingOriginTrialFeatureFunction
- new_install_pending_origin_trial_feature_function) {
- InstallPendingOriginTrialFeatureFunction original_function =
- g_install_pending_origin_trial_feature_function;
- g_install_pending_origin_trial_feature_function =
- new_install_pending_origin_trial_feature_function;
- return original_function;
-}
-
-void InstallOriginTrialFeatures(const WrapperTypeInfo* type,
- const ScriptState* script_state,
- v8::Local<v8::Object> prototype_object,
- v8::Local<v8::Function> interface_object) {
- (*g_install_origin_trial_features_function)(
- type, script_state, prototype_object, interface_object);
-}
-
-void InstallPendingOriginTrialFeature(OriginTrialFeature feature,
- const ScriptState* script_state) {
- DCHECK(script_state);
- DCHECK(script_state->GetContext() ==
- script_state->GetIsolate()->GetCurrentContext());
- DCHECK(script_state->PerContextData());
- DCHECK(script_state->World().IsMainWorld());
-
- (*g_install_pending_origin_trial_feature_function)(feature, script_state);
-}
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
-
namespace {
InstallPropertiesPerFeatureFuncType g_install_properties_per_feature_func;
@@ -91,6 +27,4 @@ InstallPropertiesPerFeatureFuncType SetInstallPropertiesPerFeatureFunc(
return old_func;
}
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.h b/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.h
index cfd6066cd2b..56ef540c8be 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/origin_trial_features.h
@@ -7,55 +7,10 @@
#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/text/wtf_string.h"
-#include "v8/include/v8.h"
namespace blink {
class ScriptState;
-struct WrapperTypeInfo;
-
-using InstallOriginTrialFeaturesFunction = void (*)(const WrapperTypeInfo*,
- const ScriptState*,
- v8::Local<v8::Object>,
- v8::Local<v8::Function>);
-
-using InstallPendingOriginTrialFeatureFunction = void (*)(OriginTrialFeature,
- const ScriptState*);
-
-// Sets the function to be called by |InstallOriginTrialFeatures|. The function
-// is initially set to the private |InstallOriginTrialFeaturesDefault| function,
-// but can be overridden by this function. A pointer to the previously set
-// function is returned, so that functions can be chained.
-PLATFORM_EXPORT InstallOriginTrialFeaturesFunction
- SetInstallOriginTrialFeaturesFunction(InstallOriginTrialFeaturesFunction);
-
-// Sets the function to be called by |InstallPendingOriginTrialFeature|. This
-// is initially set to the private |InstallPendingOriginTrialFeatureDefault|
-// function, but can be overridden by this function. A pointer to the previously
-// set function is returned, so that functions can be chained.
-PLATFORM_EXPORT InstallPendingOriginTrialFeatureFunction
- SetInstallPendingOriginTrialFeatureFunction(
- InstallPendingOriginTrialFeatureFunction);
-
-// Installs all of the conditionally enabled V8 bindings for the given type, in
-// a specific context. This is called in V8PerContextData, after the constructor
-// and prototype for the type have been created. It indirectly calls the
-// function set by |SetInstallOriginTrialFeaturesFunction|.
-PLATFORM_EXPORT void InstallOriginTrialFeatures(const WrapperTypeInfo*,
- const ScriptState*,
- v8::Local<v8::Object>,
- v8::Local<v8::Function>);
-
-// Installs all of the conditionally enabled V8 bindings for a feature, if
-// needed. This is called to install a newly-enabled feature on any existing
-// objects. If the target object hasn't been created, nothing is installed. The
-// enabled feature will be instead be installed when the object is created
-// (avoids forcing the creation of objects prematurely).
-PLATFORM_EXPORT void InstallPendingOriginTrialFeature(OriginTrialFeature,
- const ScriptState*);
-
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
using InstallPropertiesPerFeatureFuncType = void (*)(ScriptState*,
OriginTrialFeature);
@@ -67,8 +22,6 @@ PLATFORM_EXPORT void InstallPropertiesPerFeature(ScriptState* script_state,
PLATFORM_EXPORT InstallPropertiesPerFeatureFuncType
SetInstallPropertiesPerFeatureFunc(InstallPropertiesPerFeatureFuncType func);
-#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ORIGIN_TRIAL_FEATURES_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
index b585ced21dc..a718db3d549 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
@@ -55,9 +55,9 @@ enum class ParkingAction { kParked, kUnparked, kWritten, kRead };
void RecordStatistics(size_t size,
base::TimeDelta duration,
ParkingAction action) {
- size_t throughput_mb_s =
- static_cast<size_t>(size / duration.InSecondsF()) / 1000000;
- size_t size_kb = size / 1000;
+ int throughput_mb_s =
+ base::ClampRound(size / duration.InSecondsF() / 1000000);
+ int size_kb = static_cast<int>(size / 1000);
const char *size_histogram, *latency_histogram, *throughput_histogram;
switch (action) {
@@ -130,6 +130,9 @@ class NullableCharBuffer final {
size_ = size;
}
+ NullableCharBuffer(const NullableCharBuffer&) = delete;
+ NullableCharBuffer& operator=(const NullableCharBuffer&) = delete;
+
~NullableCharBuffer() {
if (data_)
WTF::Partitions::BufferPartition()->Free(data_);
@@ -142,8 +145,6 @@ class NullableCharBuffer final {
private:
char* data_;
size_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(NullableCharBuffer);
};
} // namespace
@@ -162,15 +163,14 @@ struct BackgroundTaskParams final {
data(data),
size(size) {}
+ BackgroundTaskParams(const BackgroundTaskParams&) = delete;
+ BackgroundTaskParams& operator=(const BackgroundTaskParams&) = delete;
~BackgroundTaskParams() { DCHECK(IsMainThread()); }
const scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner;
const scoped_refptr<ParkableStringImpl> string;
const void* data;
const size_t size;
-
- BackgroundTaskParams(BackgroundTaskParams&&) = delete;
- DISALLOW_COPY_AND_ASSIGN(BackgroundTaskParams);
};
// Valid transitions are:
@@ -346,7 +346,7 @@ const String& ParkableStringImpl::ToString() {
return string_;
}
-unsigned ParkableStringImpl::CharactersSizeInBytes() const {
+size_t ParkableStringImpl::CharactersSizeInBytes() const {
AssertOnValidThread();
if (!may_be_parked())
return string_.CharactersSizeInBytes();
@@ -546,7 +546,8 @@ String ParkableStringImpl::UnparkInternal() {
base::ElapsedTimer disk_read_timer;
DCHECK(has_on_disk_data());
metadata_->compressed_ = std::make_unique<Vector<uint8_t>>();
- metadata_->compressed_->Grow(metadata_->on_disk_metadata_->size());
+ metadata_->compressed_->Grow(
+ base::checked_cast<wtf_size_t>(metadata_->on_disk_metadata_->size()));
manager.data_allocator().Read(*metadata_->on_disk_metadata_,
metadata_->compressed_->data());
base::TimeDelta elapsed = disk_read_timer.Elapsed();
@@ -674,7 +675,7 @@ void ParkableStringImpl::CompressInBackground(
// Not using realloc() as we want the compressed data to be a regular
// WTF::Vector.
compressed->Append(reinterpret_cast<const uint8_t*>(buffer.data()),
- compressed_size);
+ base::checked_cast<wtf_size_t>(compressed_size));
}
}
base::TimeDelta thread_elapsed = thread_timer.Elapsed();
@@ -846,7 +847,7 @@ const String& ParkableString::ToString() const {
return impl_ ? impl_->ToString() : g_empty_string;
}
-wtf_size_t ParkableString::CharactersSizeInBytes() const {
+size_t ParkableString::CharactersSizeInBytes() const {
return impl_ ? impl_->CharactersSizeInBytes() : 0;
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
index 5797cd8cbad..1bd251e09cb 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
@@ -10,7 +10,6 @@
#include "base/dcheck_is_on.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/thread_annotations.h"
#include "third_party/blink/renderer/platform/disk_data_metadata.h"
@@ -65,6 +64,8 @@ class PLATFORM_EXPORT ParkableStringImpl final
scoped_refptr<StringImpl>&& impl,
std::unique_ptr<SecureDigest> digest);
+ ParkableStringImpl(const ParkableStringImpl&) = delete;
+ ParkableStringImpl& operator=(const ParkableStringImpl&) = delete;
~ParkableStringImpl();
void Lock();
@@ -87,7 +88,7 @@ class PLATFORM_EXPORT ParkableStringImpl final
return metadata_->length_;
}
- unsigned CharactersSizeInBytes() const;
+ size_t CharactersSizeInBytes() const;
size_t MemoryFootprintForDump() const;
// Returns true iff the string can be parked. This does not mean that the
@@ -228,6 +229,8 @@ class PLATFORM_EXPORT ParkableStringImpl final
// Metadata only used for parkable ParkableStrings.
struct ParkableMetadata {
ParkableMetadata(String string, std::unique_ptr<SecureDigest> digest);
+ ParkableMetadata(const ParkableMetadata&) = delete;
+ ParkableMetadata& operator=(const ParkableMetadata&) = delete;
Mutex mutex_;
unsigned int lock_depth_ GUARDED_BY(mutex_);
@@ -253,8 +256,6 @@ class PLATFORM_EXPORT ParkableStringImpl final
Age age_ : 3 GUARDED_BY(mutex_);
const bool is_8bit_ : 1;
const unsigned length_;
-
- DISALLOW_COPY_AND_ASSIGN(ParkableMetadata);
};
String string_;
@@ -277,8 +278,6 @@ class PLATFORM_EXPORT ParkableStringImpl final
FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockParkedString);
FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, ReportMemoryDump);
FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, MemoryFootprintForDump);
-
- DISALLOW_COPY_AND_ASSIGN(ParkableStringImpl);
};
#if !DCHECK_IS_ON()
@@ -320,7 +319,7 @@ class PLATFORM_EXPORT ParkableString final {
// The string is guaranteed to be valid for
// max(lifetime of a copy of the returned reference, current thread task).
const String& ToString() const;
- wtf_size_t CharactersSizeInBytes() const;
+ size_t CharactersSizeInBytes() const;
// Causes the string to be unparked. Note that the pointer must not be
// cached.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
index 1879d7527fc..cbb64d7cddb 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
@@ -273,10 +272,6 @@ void ParkableStringManager::ParkAll(ParkableStringImpl::ParkingMode mode) {
DCHECK(IsMainThread());
DCHECK(CompressionEnabled());
- size_t total_size = 0;
- for (const auto& kv : parked_strings_)
- total_size += kv.value->CharactersSizeInBytes();
-
// Parking may be synchronous, need to copy values first.
// In case of synchronous parking, |ParkableStringImpl::Park()| calls
// |OnParked()|, which moves the string from |unparked_strings_|
@@ -290,7 +285,6 @@ void ParkableStringManager::ParkAll(ParkableStringImpl::ParkingMode mode) {
for (ParkableStringImpl* str : unparked) {
str->Park(mode);
- total_size += str->CharactersSizeInBytes();
}
}
@@ -309,15 +303,16 @@ void ParkableStringManager::RecordStatisticsAfter5Minutes() const {
}
Statistics stats = ComputeStatistics();
base::UmaHistogramCounts100000("Memory.ParkableString.TotalSizeKb.5min",
- stats.original_size / 1000);
- base::UmaHistogramCounts100000("Memory.ParkableString.CompressedSizeKb.5min",
- stats.compressed_size / 1000);
+ static_cast<int>(stats.original_size / 1000));
+ base::UmaHistogramCounts100000(
+ "Memory.ParkableString.CompressedSizeKb.5min",
+ static_cast<int>(stats.compressed_size / 1000));
size_t savings = stats.compressed_original_size - stats.compressed_size;
base::UmaHistogramCounts100000("Memory.ParkableString.SavingsKb.5min",
- savings / 1000);
+ static_cast<int>(savings / 1000));
if (stats.compressed_original_size != 0) {
- size_t ratio_percentage =
- (100 * stats.compressed_size) / stats.compressed_original_size;
+ int ratio_percentage = static_cast<int>((100 * stats.compressed_size) /
+ stats.compressed_original_size);
base::UmaHistogramPercentageObsoleteDoNotUse(
"Memory.ParkableString.CompressionRatio.5min", ratio_percentage);
}
@@ -338,7 +333,7 @@ void ParkableStringManager::RecordStatisticsAfter5Minutes() const {
"Memory.ParkableString.MemorySavingsKb.5min",
std::max(0, static_cast<int>(stats.savings_size)) / 1000);
base::UmaHistogramCounts100000("Memory.ParkableString.OnDiskSizeKb.5min",
- stats.on_disk_size / 1000);
+ static_cast<int>(stats.on_disk_size / 1000));
base::UmaHistogramCounts100000(
"Memory.ParkableString.OnDiskFootprintKb.5min",
static_cast<int>(data_allocator().disk_footprint()) / 1000);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
index d08a67d00e0..71e576cfff9 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
@@ -9,7 +9,6 @@
#include <utility>
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_provider.h"
@@ -33,6 +32,10 @@ class PLATFORM_EXPORT ParkableStringManagerDumpProvider
public:
static ParkableStringManagerDumpProvider* Instance();
+ ParkableStringManagerDumpProvider(const ParkableStringManagerDumpProvider&) =
+ delete;
+ ParkableStringManagerDumpProvider& operator=(
+ const ParkableStringManagerDumpProvider&) = delete;
~ParkableStringManagerDumpProvider() override;
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs&,
@@ -40,8 +43,6 @@ class PLATFORM_EXPORT ParkableStringManagerDumpProvider
private:
ParkableStringManagerDumpProvider();
-
- DISALLOW_COPY_AND_ASSIGN(ParkableStringManagerDumpProvider);
};
// Manages all the ParkableStrings, and parks eligible strings after the
@@ -54,6 +55,8 @@ class PLATFORM_EXPORT ParkableStringManager {
struct Statistics;
static ParkableStringManager& Instance();
+ ParkableStringManager(const ParkableStringManager&) = delete;
+ ParkableStringManager& operator=(const ParkableStringManager&) = delete;
~ParkableStringManager();
void PurgeMemory();
@@ -139,7 +142,6 @@ class PLATFORM_EXPORT ParkableStringManager {
friend class ParkableStringTest;
FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, SynchronousCompression);
- DISALLOW_COPY_AND_ASSIGN(ParkableStringManager);
};
} // namespace blink
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 f21756c3b5a..7c9c5e1043f 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCOPED_PERSISTENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCOPED_PERSISTENT_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "v8/include/v8.h"
@@ -47,9 +46,10 @@ class ScopedPersistent {
public:
ScopedPersistent() = default;
-
ScopedPersistent(v8::Isolate* isolate, v8::Local<T> handle)
: handle_(isolate, handle) {}
+ ScopedPersistent(const ScopedPersistent&) = delete;
+ ScopedPersistent& operator=(const ScopedPersistent&) = delete;
~ScopedPersistent() { Clear(); }
@@ -95,8 +95,6 @@ class ScopedPersistent {
private:
v8::Persistent<T> handle_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedPersistent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_forbidden_scope.h b/chromium/third_party/blink/renderer/platform/bindings/script_forbidden_scope.h
index d749dc6a579..5e1becd9a2e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_forbidden_scope.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_forbidden_scope.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_FORBIDDEN_SCOPE_H_
#include "base/auto_reset.h"
-#include "base/macros.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/allocator.h"
@@ -18,18 +17,20 @@ namespace blink {
// Scoped disabling of script execution.
class PLATFORM_EXPORT ScriptForbiddenScope final {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(ScriptForbiddenScope);
public:
ScriptForbiddenScope() { Enter(); }
+ ScriptForbiddenScope(const ScriptForbiddenScope&) = delete;
+ ScriptForbiddenScope& operator=(const ScriptForbiddenScope&) = delete;
~ScriptForbiddenScope() { Exit(); }
class PLATFORM_EXPORT AllowUserAgentScript final {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(AllowUserAgentScript);
public:
AllowUserAgentScript() : saved_counter_(&GetMutableCounter(), 0) {}
+ AllowUserAgentScript(const AllowUserAgentScript&) = delete;
+ AllowUserAgentScript& operator=(const AllowUserAgentScript&) = delete;
~AllowUserAgentScript() { DCHECK(!IsScriptForbidden()); }
private:
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 738b754b6fb..656148c26fc 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_state.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_state.h
@@ -128,6 +128,8 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
ScriptState(v8::Local<v8::Context>,
scoped_refptr<DOMWrapperWorld>,
ExecutionContext* execution_context);
+ ScriptState(const ScriptState&) = delete;
+ ScriptState& operator=(const ScriptState&) = delete;
~ScriptState();
void Trace(Visitor*) const;
@@ -233,8 +235,6 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
static constexpr int kV8ContextPerContextDataIndex =
static_cast<int>(gin::kPerContextDataStartIndex) +
static_cast<int>(gin::kEmbedderBlink);
-
- DISALLOW_COPY_AND_ASSIGN(ScriptState);
};
// ScriptStateProtectingContext keeps the context associated with the
@@ -251,6 +251,9 @@ class ScriptStateProtectingContext final
"blink::ScriptStateProtectingContext::context_");
}
}
+ ScriptStateProtectingContext(const ScriptStateProtectingContext&) = delete;
+ ScriptStateProtectingContext& operator=(const ScriptStateProtectingContext&) =
+ delete;
void Trace(Visitor* visitor) const { visitor->Trace(script_state_); }
@@ -270,8 +273,6 @@ class ScriptStateProtectingContext final
private:
Member<ScriptState> script_state_;
ScopedPersistent<v8::Context> context_;
-
- DISALLOW_COPY_AND_ASSIGN(ScriptStateProtectingContext);
};
} // namespace blink
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 bec216913ce..023931399ca 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_
-#include "base/macros.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
@@ -55,7 +54,9 @@ class PLATFORM_EXPORT ScriptWrappable
: public GarbageCollected<ScriptWrappable>,
public NameClient {
public:
- virtual ~ScriptWrappable() = default;
+ ScriptWrappable(const ScriptWrappable&) = delete;
+ ScriptWrappable& operator=(const ScriptWrappable&) = delete;
+ ~ScriptWrappable() override = default;
// The following methods may override lifetime of ScriptWrappable objects when
// needed. In particular if |HasPendingActivity| or |HasEventListeners|
@@ -164,8 +165,6 @@ class PLATFORM_EXPORT ScriptWrappable
friend class HeapSnaphotWrapperVisitor;
friend class V8HiddenValue;
friend class V8PrivateProperty;
-
- DISALLOW_COPY_AND_ASSIGN(ScriptWrappable);
};
inline bool ScriptWrappable::UnsetMainWorldWrapperIfSet(
@@ -196,24 +195,6 @@ inline bool ScriptWrappable::UnsetMainWorldWrapperIfSet(
private: \
static const WrapperTypeInfo& wrapper_type_info_
-// Declares |GetWrapperTypeInfo| method without definition.
-//
-// This macro is used for template classes. e.g. DOMTypedArray<>.
-// To export such a template class X, we need to instantiate X with EXPORT_API,
-// i.e. "extern template class EXPORT_API X;"
-// However, once we instantiate X, we cannot specialize X after
-// the instantiation. i.e. we will see "error: explicit specialization of ...
-// after instantiation". So we cannot define X's s_wrapper_type_info in
-// generated code by using specialization. Instead, we need to implement
-// wrapper_type_info in X's cpp code, and instantiate X, i.e. "template class
-// X;".
-#define DECLARE_WRAPPERTYPEINFO() \
- public: \
- const WrapperTypeInfo* GetWrapperTypeInfo() const override; \
- \
- private: \
- typedef void end_of_declare_wrappertypeinfo_t
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_
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 87128746779..95b7c18062a 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/string_resource.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/string_resource.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_STRING_RESOURCE_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -52,6 +51,9 @@ class StringResourceBase {
string.CharactersSizeInBytes());
}
+ StringResourceBase(const StringResourceBase&) = delete;
+ StringResourceBase& operator=(const StringResourceBase&) = delete;
+
virtual ~StringResourceBase() {
#if DCHECK_IS_ON()
DCHECK(thread_id_ == WTF::CurrentThread());
@@ -111,8 +113,6 @@ class StringResourceBase {
#if DCHECK_IS_ON()
base::PlatformThreadId thread_id_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(StringResourceBase);
};
// Even though StringResource{8,16}Base are effectively empty in release mode,
@@ -138,7 +138,8 @@ class StringResource16Base : public StringResourceBase,
DCHECK(!parkable_string.Is8Bit());
}
- DISALLOW_COPY_AND_ASSIGN(StringResource16Base);
+ StringResource16Base(const StringResource16Base&) = delete;
+ StringResource16Base& operator=(const StringResource16Base&) = delete;
};
class StringResource16 final : public StringResource16Base {
@@ -149,13 +150,14 @@ class StringResource16 final : public StringResource16Base {
explicit StringResource16(const AtomicString& string)
: StringResource16Base(string) {}
+ StringResource16(const StringResource16&) = delete;
+ StringResource16& operator=(const StringResource16&) = delete;
+
size_t length() const override { return plain_string_.Impl()->length(); }
const uint16_t* data() const override {
return reinterpret_cast<const uint16_t*>(
plain_string_.Impl()->Characters16());
}
-
- DISALLOW_COPY_AND_ASSIGN(StringResource16);
};
class ParkableStringResource16 final : public StringResource16Base {
@@ -163,6 +165,9 @@ class ParkableStringResource16 final : public StringResource16Base {
explicit ParkableStringResource16(const ParkableString& string)
: StringResource16Base(string) {}
+ ParkableStringResource16(const ParkableStringResource16&) = delete;
+ ParkableStringResource16& operator=(const ParkableStringResource16&) = delete;
+
bool IsCacheable() const override {
return !parkable_string_.may_be_parked();
}
@@ -176,8 +181,6 @@ class ParkableStringResource16 final : public StringResource16Base {
const uint16_t* data() const override {
return reinterpret_cast<const uint16_t*>(parkable_string_.Characters16());
}
-
- DISALLOW_COPY_AND_ASSIGN(ParkableStringResource16);
};
class StringResource8Base : public StringResourceBase,
@@ -198,7 +201,8 @@ class StringResource8Base : public StringResourceBase,
DCHECK(parkable_string.Is8Bit());
}
- DISALLOW_COPY_AND_ASSIGN(StringResource8Base);
+ StringResource8Base(const StringResource8Base&) = delete;
+ StringResource8Base& operator=(const StringResource8Base&) = delete;
};
class StringResource8 final : public StringResource8Base {
@@ -209,12 +213,13 @@ class StringResource8 final : public StringResource8Base {
explicit StringResource8(const AtomicString& string)
: StringResource8Base(string) {}
+ StringResource8(const StringResource8&) = delete;
+ StringResource8& operator=(const StringResource8&) = delete;
+
size_t length() const override { return plain_string_.Impl()->length(); }
const char* data() const override {
return reinterpret_cast<const char*>(plain_string_.Impl()->Characters8());
}
-
- DISALLOW_COPY_AND_ASSIGN(StringResource8);
};
class ParkableStringResource8 final : public StringResource8Base {
@@ -222,6 +227,9 @@ class ParkableStringResource8 final : public StringResource8Base {
explicit ParkableStringResource8(const ParkableString& string)
: StringResource8Base(string) {}
+ ParkableStringResource8(const ParkableStringResource8&) = delete;
+ ParkableStringResource8& operator=(const ParkableStringResource8&) = delete;
+
bool IsCacheable() const override {
return !parkable_string_.may_be_parked();
}
@@ -235,8 +243,6 @@ class ParkableStringResource8 final : public StringResource8Base {
const char* data() const override {
return reinterpret_cast<const char*>(parkable_string_.Characters8());
}
-
- DISALLOW_COPY_AND_ASSIGN(ParkableStringResource8);
};
enum ExternalMode { kExternalize, kDoNotExternalize };
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 251d07bfca9..d0cb0954e79 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
@@ -56,10 +56,9 @@ inline v8::Local<v8::Value> ToV8(const bindings::DictionaryBase* dictionary,
v8::Isolate* isolate) {
if (UNLIKELY(!dictionary))
return v8::Null(isolate);
- v8::Local<v8::Value> v8_value =
- dictionary->CreateV8Object(isolate, creation_context);
- DCHECK(!v8_value.IsEmpty());
- return v8_value;
+ ScriptState* script_state =
+ ScriptState::From(creation_context->CreationContext());
+ return dictionary->ToV8Value(script_state).ToLocalChecked();
}
// Callback function
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 6cebd03d1de..7460e845821 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
@@ -8,13 +8,11 @@
#include <utility>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/buildflags.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#include "third_party/blink/renderer/platform/wtf/vector_traits.h"
-#include "v8/include/v8-cppgc.h"
#include "v8/include/v8.h"
#if BUILDFLAG(USE_V8_OILPAN)
@@ -140,7 +138,9 @@ class TraceWrapperV8Reference {
v8::TracedReference<T> handle_;
+#if BUILDFLAG(USE_V8_OILPAN)
friend struct cppgc::TraceTrait<TraceWrapperV8Reference<T>>;
+#endif // USE_V8_OILPAN
};
} // 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 b94a604962d..128672cbfb0 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
@@ -15,13 +15,14 @@ namespace blink {
// Small shim around TraceWrapperReference<v8::String> with a few
// utility methods. Internally, v8::String is represented as string
// rope.
-class GC_PLUGIN_IGNORE("crbug.com/841830")
- PLATFORM_EXPORT TraceWrapperV8String final : public NameClient {
- DISALLOW_COPY_AND_ASSIGN(TraceWrapperV8String);
+class PLATFORM_EXPORT TraceWrapperV8String final {
DISALLOW_NEW();
public:
TraceWrapperV8String() = default;
+ TraceWrapperV8String(const TraceWrapperV8String&) = delete;
+ TraceWrapperV8String& operator=(const TraceWrapperV8String&) = delete;
+ ~TraceWrapperV8String() = default;
bool IsEmpty() const { return string_.IsEmpty(); }
void Clear() { string_.Clear(); }
@@ -33,11 +34,7 @@ class GC_PLUGIN_IGNORE("crbug.com/841830")
void Concat(v8::Isolate*, const String&);
String Flatten(v8::Isolate*) const;
- virtual void Trace(Visitor* visitor) const { visitor->Trace(string_); }
-
- const char* NameInHeapSnapshot() const override {
- return "TraceWrapperV8String";
- }
+ void Trace(Visitor* visitor) const { visitor->Trace(string_); }
private:
TraceWrapperV8Reference<v8::String> string_;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h
index 1d85a49a93c..347a5364a86 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_CALLBACK_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_CALLBACK_INFO_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "v8/include/v8.h"
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc
index 9cee156712a..10a3013e3f9 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc
@@ -76,8 +76,8 @@ v8::Local<v8::Array> EnumerateCrossOriginProperties(
v8::Symbol::GetHasInstance(isolate),
v8::Symbol::GetIsConcatSpreadable(isolate),
};
- const uint32_t length =
- attributes.size() + operations.size() + base::size(default_supported);
+ const uint32_t length = static_cast<uint32_t>(
+ attributes.size() + operations.size() + base::size(default_supported));
Vector<v8::Local<v8::Value>> elements;
elements.ReserveCapacity(length);
for (const auto& attribute : attributes)
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 5a2f20c489a..9292dadc1b0 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
@@ -5,9 +5,11 @@
#include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h"
#include <memory>
+#include "third_party/blink/public/common/scheme_registry.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/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -81,7 +83,7 @@ V8DOMActivityLogger* V8DOMActivityLogger::ActivityLogger(int world_id,
// To find an activity logger that corresponds to the main world of an
// extension, we need to obtain the extension ID. Extension ID is a hostname
// of a background page's URL.
- if (!url.ProtocolIs("chrome-extension"))
+ if (!CommonSchemeRegistry::IsExtensionScheme(url.Protocol().Ascii()))
return nullptr;
return ActivityLogger(world_id, url.Host());
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 b4cdabe6856..b976f7b3b20 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,7 +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 "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
#include "third_party/blink/renderer/platform/bindings/custom_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
@@ -158,37 +158,6 @@ class V8WrapperInstantiationScope {
STACK_ALLOCATED();
public:
- V8WrapperInstantiationScope(v8::Local<v8::Object> creation_context,
- v8::Isolate* isolate,
- const WrapperTypeInfo* type)
- : context_(isolate->GetCurrentContext()),
- try_catch_(isolate),
- type_(type) {
- // creationContext should not be empty. Because if we have an
- // empty creationContext, we will end up creating
- // a new object in the context currently entered. This is wrong.
- CHECK(!creation_context.IsEmpty());
- v8::Local<v8::Context> context_for_wrapper =
- creation_context->CreationContext();
-
- // For performance, we enter the context only if the currently running
- // context is different from the context that we are about to enter.
- if (context_for_wrapper == context_)
- return;
-
- if (!BindingSecurityForPlatform::ShouldAllowWrapperCreationOrThrowException(
- isolate->GetCurrentContext(), context_for_wrapper, type_)) {
- DCHECK(try_catch_.HasCaught());
- try_catch_.ReThrow();
- access_check_failed_ = true;
- return;
- }
-
- did_enter_context_ = true;
- context_ = context_for_wrapper;
- context_->Enter();
- }
-
// This is an overload of constructor for CreateWrapperV2.
V8WrapperInstantiationScope(ScriptState* script_state,
const WrapperTypeInfo* type)
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h b/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h
index ac7c7a22708..ee712627373 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h
@@ -48,7 +48,7 @@ class V8GlobalValueMapTraits {
return old_value;
}
static v8::PersistentContainerValue Get(const Impl* impl, KeyType key) {
- return impl->at(key);
+ return impl->DeprecatedAtOrEmptyValue(key);
}
static v8::PersistentContainerValue Remove(Impl* impl, KeyType key) {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.cc
new file mode 100644
index 00000000000..19b6f64db24
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.cc
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.h"
+
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+namespace bindings {
+
+V8InterfaceBridgeBase::FeatureSelector::FeatureSelector()
+ : does_select_all_(true), selector_(OriginTrialFeature::kNonExisting) {}
+
+V8InterfaceBridgeBase::FeatureSelector::FeatureSelector(
+ OriginTrialFeature feature)
+ : selector_(feature) {}
+
+} // namespace bindings
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.h b/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.h
index 3c01116da56..d407d0d1ee0 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge_base.h
@@ -6,13 +6,13 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_BASE_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/allocator.h"
#include "v8/include/v8.h"
namespace blink {
class DOMWrapperWorld;
+enum class OriginTrialFeature : int32_t;
namespace bindings {
@@ -35,15 +35,15 @@ class PLATFORM_EXPORT V8InterfaceBridgeBase {
//
// FeatureSelector() is used for usage 1) and
// FeatureSelector(feature) is used for usage 2).
- class FeatureSelector final {
+ class PLATFORM_EXPORT FeatureSelector final {
public:
// Selects all properties not associated to any origin trial feature and
// properties associated with the origin trial features that are already
// enabled.
- FeatureSelector() : does_select_all_(true) {}
+ FeatureSelector();
// Selects only the properties that are associated to the given origin
// trial feature.
- explicit FeatureSelector(OriginTrialFeature feature) : selector_(feature) {}
+ explicit FeatureSelector(OriginTrialFeature feature);
FeatureSelector(const FeatureSelector&) = default;
FeatureSelector(FeatureSelector&&) = default;
~FeatureSelector() = default;
@@ -68,7 +68,9 @@ class PLATFORM_EXPORT V8InterfaceBridgeBase {
private:
bool does_select_all_ = false;
- OriginTrialFeature selector_ = OriginTrialFeature::kNonExisting;
+ // We intentionally avoid default member initializer for |selector_| in
+ // order not to include runtime_enabled_features.h.
+ OriginTrialFeature selector_;
};
using InstallInterfaceTemplateFuncType =
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_object_constructor.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_object_constructor.cc
index 196548f9b1a..48c2716e75f 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_object_constructor.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_object_constructor.cc
@@ -24,7 +24,6 @@
#include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h"
-#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
@@ -105,8 +104,6 @@ v8::Local<v8::Function> V8ObjectConstructor::CreateInterfaceObject(
type->InstallConditionalFeatures(context, world, v8::Local<v8::Object>(),
prototype_object, interface_object,
interface_template);
- InstallOriginTrialFeatures(type, ScriptState::From(context),
- prototype_object, interface_object);
}
return interface_object;
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 8d92ce4398b..e747045eb8d 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
@@ -171,7 +171,7 @@ void V8PerContextData::ClearData(const char* key) {
}
V8PerContextData::Data* V8PerContextData::GetData(const char* key) {
- return data_map_.at(key);
+ return data_map_.DeprecatedAtOrEmptyValue(key);
}
} // 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 bf10ab6f647..3c014e063e2 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
@@ -59,6 +59,8 @@ class PLATFORM_EXPORT V8PerContextData final
: public GarbageCollected<V8PerContextData> {
public:
explicit V8PerContextData(v8::Local<v8::Context>);
+ V8PerContextData(const V8PerContextData&) = delete;
+ V8PerContextData& operator=(const V8PerContextData&) = delete;
static V8PerContextData* From(v8::Local<v8::Context>);
@@ -151,8 +153,6 @@ class PLATFORM_EXPORT V8PerContextData final
using DataMap = HeapHashMap<const char*, Member<Data>>;
DataMap data_map_;
-
- DISALLOW_COPY_AND_ASSIGN(V8PerContextData);
};
} // namespace blink
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 1b59156a0d9..22d0f0f3746 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
@@ -288,7 +288,8 @@ V8PerIsolateData::FindOrCreateEternalNameCache(
const Vector<v8::Eternal<v8::Name>>* vector = nullptr;
if (UNLIKELY(it == eternal_name_cache_.end())) {
v8::Isolate* isolate = GetIsolate();
- Vector<v8::Eternal<v8::Name>> new_vector(names.size());
+ Vector<v8::Eternal<v8::Name>> new_vector(
+ base::checked_cast<wtf_size_t>(names.size()));
std::transform(names.begin(), names.end(), new_vector.begin(),
[isolate](const char* name) {
return v8::Eternal<v8::Name>(
@@ -360,4 +361,14 @@ V8PerIsolateData::GarbageCollectedData* V8PerIsolateData::ProfilerGroup() {
return profiler_group_;
}
+void V8PerIsolateData::SetCanvasResourceTracker(
+ V8PerIsolateData::GarbageCollectedData* canvas_resource_tracker) {
+ canvas_resource_tracker_ = canvas_resource_tracker;
+}
+
+V8PerIsolateData::GarbageCollectedData*
+V8PerIsolateData::CanvasResourceTracker() {
+ return canvas_resource_tracker_;
+}
+
} // namespace blink
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 c0423029b2b..ec72c6939f6 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,7 +29,6 @@
#include <memory>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "gin/public/gin_embedders.h"
#include "gin/public/isolate_holder.h"
#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h"
@@ -120,6 +119,9 @@ class PLATFORM_EXPORT V8PerIsolateData final {
isolate->GetData(gin::kEmbedderBlink));
}
+ V8PerIsolateData(const V8PerIsolateData&) = delete;
+ V8PerIsolateData& operator=(const V8PerIsolateData&) = delete;
+
static void WillBeDestroyed(v8::Isolate*);
static void Destroy(v8::Isolate*);
static v8::Isolate* MainThreadIsolate();
@@ -193,6 +195,9 @@ class PLATFORM_EXPORT V8PerIsolateData final {
void SetProfilerGroup(V8PerIsolateData::GarbageCollectedData*);
V8PerIsolateData::GarbageCollectedData* ProfilerGroup();
+ void SetCanvasResourceTracker(V8PerIsolateData::GarbageCollectedData*);
+ V8PerIsolateData::GarbageCollectedData* CanvasResourceTracker();
+
ActiveScriptWrappableManager* GetActiveScriptWrappableManager() const {
return active_script_wrappable_manager_;
}
@@ -264,6 +269,7 @@ class PLATFORM_EXPORT V8PerIsolateData final {
Vector<base::OnceClosure> end_of_scope_tasks_;
std::unique_ptr<Data> thread_debugger_;
Persistent<GarbageCollectedData> profiler_group_;
+ Persistent<GarbageCollectedData> canvas_resource_tracker_;
Persistent<ActiveScriptWrappableManager> active_script_wrappable_manager_;
@@ -272,8 +278,6 @@ class PLATFORM_EXPORT V8PerIsolateData final {
v8::Isolate::GCCallback prologue_callback_;
v8::Isolate::GCCallback epilogue_callback_;
size_t gc_callback_depth_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(V8PerIsolateData);
};
} // namespace blink
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 bfe5d2bc82f..6739a6e8fae 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
@@ -40,6 +40,8 @@ class PLATFORM_EXPORT V8PrivateProperty {
};
V8PrivateProperty() = default;
+ V8PrivateProperty(const V8PrivateProperty&) = delete;
+ V8PrivateProperty& operator=(const V8PrivateProperty&) = delete;
// Provides fast access to V8's private properties.
//
@@ -134,8 +136,6 @@ class PLATFORM_EXPORT V8PrivateProperty {
ScopedPersistent<v8::Private> symbol_window_document_cached_accessor_;
WTF::HashMap<const void*, v8::Eternal<v8::Private>> symbol_map_;
-
- DISALLOW_COPY_AND_ASSIGN(V8PrivateProperty);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h b/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
index e98adf9d080..7e2f0208688 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
@@ -5,10 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_SET_RETURN_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_SET_RETURN_VALUE_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/bindings/dictionary_base.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/enumeration_base.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -39,18 +40,15 @@ struct V8ReturnValue {
enum NonNullable { kNonNullable };
enum Nullable { kNullable };
- // FrozenArray or not (the integrity level = frozen or not)
- enum Frozen { kFrozen };
-
// Main world or not
enum MainWorld { kMainWorld };
+ // The return value can be a cross origin window.
+ enum MaybeCrossOriginWindow { kMaybeCrossOriginWindow };
+
// Returns the exposed object of the given type.
enum InterfaceObject { kInterfaceObject };
enum NamespaceObject { kNamespaceObject };
- enum IDLObject { kIDLObject };
-
- enum MaybeCrossOriginWindow { kMaybeCrossOriginWindow };
// Selects the appropriate creation context.
static v8::Local<v8::Object> CreationContext(
@@ -82,21 +80,6 @@ void V8SetReturnValue(const CallbackInfo& info, const v8::Local<S> value) {
info.GetReturnValue().Set(value);
}
-template <typename CallbackInfo, typename S>
-void V8SetReturnValue(const CallbackInfo& info,
- const v8::Local<S> value,
- V8ReturnValue::Frozen) {
- if (value->IsObject()) {
- bool result =
- value.template As<v8::Object>()
- ->SetIntegrityLevel(info.GetIsolate()->GetCurrentContext(),
- v8::IntegrityLevel::kFrozen)
- .ToChecked();
- CHECK(result);
- }
- info.GetReturnValue().Set(value);
-}
-
// Property descriptor
PLATFORM_EXPORT v8::Local<v8::Object> CreatePropertyDescriptorObject(
v8::Isolate* isolate,
@@ -424,14 +407,27 @@ void V8SetReturnValue(const CallbackInfo& info,
V8ReturnValue::SetWrapper(info, wrappable, creation_context);
}
-// DictionaryBase
-template <typename CallbackInfo>
+// EnumerationBase
+template <typename CallbackInfo, typename... ExtraArgs>
void V8SetReturnValue(const CallbackInfo& info,
- const bindings::DictionaryBase* dictionary) {
- DCHECK(dictionary);
- v8::Local<v8::Value> v8_value = dictionary->CreateV8Object(
- info.GetIsolate(), V8ReturnValue::CreationContext(info));
- V8SetReturnValue(info, v8_value);
+ const bindings::EnumerationBase& value,
+ v8::Isolate* isolate,
+ ExtraArgs... extra_args) {
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), value.AsString().Impl());
+}
+
+// Nullable types
+template <typename CallbackInfo, typename T, typename... ExtraArgs>
+void V8SetReturnValue(const CallbackInfo& info,
+ absl::optional<T> value,
+ ExtraArgs... extra_args) {
+ if (value.has_value()) {
+ V8SetReturnValue(info, value.value(),
+ std::forward<ExtraArgs>(extra_args)...);
+ } else {
+ info.GetReturnValue().SetNull();
+ }
}
// Exposed objects
@@ -459,19 +455,6 @@ inline void V8SetReturnValue(const v8::PropertyCallbackInfo<v8::Value>& info,
info.GetIsolate(), info.Holder(), wrapper_type_info));
}
-// Nullable types
-template <typename CallbackInfo, typename T, typename... ExtraArgs>
-void V8SetReturnValue(const CallbackInfo& info,
- absl::optional<T> value,
- ExtraArgs... extra_args) {
- if (value.has_value()) {
- V8SetReturnValue(info, value.value(),
- std::forward<ExtraArgs>(extra_args)...);
- } else {
- info.GetReturnValue().SetNull();
- }
-}
-
} // namespace bindings
} // namespace blink
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 5e75c0b40e9..35a84385dc3 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
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_VALUE_CACHE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_VALUE_CACHE_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
#include "third_party/blink/renderer/platform/bindings/v8_global_value_map.h"
@@ -124,6 +123,8 @@ class PLATFORM_EXPORT StringCache {
public:
explicit StringCache(v8::Isolate* isolate)
: string_cache_(isolate), parkable_string_cache_(isolate) {}
+ StringCache(const StringCache&) = delete;
+ StringCache& operator=(const StringCache&) = delete;
v8::Local<v8::String> V8ExternalString(v8::Isolate* isolate,
StringImpl* string_impl) {
@@ -167,8 +168,6 @@ class PLATFORM_EXPORT StringCache {
// hence lastStringImpl might be not a key of the cache (in sense of identity)
// and hence it's not refed on addition.
scoped_refptr<StringImpl> last_string_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(StringCache);
};
} // 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 81e430ed92e..240f9e109a9 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
@@ -81,6 +81,7 @@ struct PLATFORM_EXPORT WrapperTypeInfo final {
kIdlInterface,
kIdlNamespace,
kIdlCallbackInterface,
+ kIdlBufferSourceType,
kCustomWrappableKind,
};
@@ -155,7 +156,7 @@ struct PLATFORM_EXPORT WrapperTypeInfo final {
unsigned wrapper_class_id : 2; // WrapperClassId
unsigned // ActiveScriptWrappableInheritance
active_script_wrappable_inheritance : 1;
- unsigned idl_definition_kind : 2; // IdlDefinitionKind
+ unsigned idl_definition_kind : 3; // IdlDefinitionKind
};
template <typename T, int offset>
diff --git a/chromium/third_party/blink/renderer/platform/blob/BUILD.gn b/chromium/third_party/blink/renderer/platform/blob/BUILD.gn
index ff184e7af3b..6a8743d8500 100644
--- a/chromium/third_party/blink/renderer/platform/blob/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/blob/BUILD.gn
@@ -19,8 +19,6 @@ source_set("generator") {
}
blink_platform_sources("blob") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
sources = [
"blob_bytes_provider.cc",
"blob_bytes_provider.h",
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 516bba89f0f..fc723d2dd83 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
@@ -84,7 +84,7 @@ class BlobBytesStreamer {
private:
// The index of the item currently being written.
- size_t current_item_ = 0;
+ wtf_size_t current_item_ = 0;
// The offset into the current item of the first byte not yet written to the
// data pipe.
size_t current_item_offset_ = 0;
@@ -162,7 +162,8 @@ void BlobBytesProvider::AppendData(base::span<const char> data) {
data_.back()->length() + data.size() > kMaxConsolidatedItemSizeInBytes) {
AppendData(RawData::Create());
}
- data_.back()->MutableData()->Append(data.data(), data.size());
+ data_.back()->MutableData()->Append(
+ data.data(), base::checked_cast<wtf_size_t>(data.size()));
}
void BlobBytesProvider::RequestAsReply(RequestAsReplyCallback callback) {
@@ -171,7 +172,7 @@ void BlobBytesProvider::RequestAsReply(RequestAsReplyCallback callback) {
// to reduce the number of copies of data that are made here.
Vector<uint8_t> result;
for (const auto& d : data_)
- result.Append(d->data(), d->length());
+ result.Append(d->data(), base::checked_cast<wtf_size_t>(d->length()));
std::move(callback).Run(result);
}
@@ -205,9 +206,9 @@ void BlobBytesProvider::RequestAsFile(uint64_t source_offset,
// Find first data item that should be read from (by finding the first offset
// that starts after the offset we want to start reading from).
- size_t data_index =
+ wtf_size_t data_index = static_cast<wtf_size_t>(
std::upper_bound(offsets_.begin(), offsets_.end(), source_offset) -
- offsets_.begin();
+ offsets_.begin());
// Offset of the current data chunk in the overall stream provided by this
// provider.
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc
index 1a11b67b16e..227955f6c07 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc
@@ -25,17 +25,17 @@ class BlobBytesProviderTest : public testing::Test {
Platform::SetMainThreadTaskRunnerForTesting();
test_bytes1_.resize(128);
- for (size_t i = 0; i < test_bytes1_.size(); ++i)
+ for (wtf_size_t i = 0; i < test_bytes1_.size(); ++i)
test_bytes1_[i] = i % 191;
test_data1_ = RawData::Create();
test_data1_->MutableData()->AppendVector(test_bytes1_);
test_bytes2_.resize(64);
- for (size_t i = 0; i < test_bytes2_.size(); ++i)
+ for (wtf_size_t i = 0; i < test_bytes2_.size(); ++i)
test_bytes2_[i] = i;
test_data2_ = RawData::Create();
test_data2_->MutableData()->AppendVector(test_bytes2_);
test_bytes3_.resize(32);
- for (size_t i = 0; i < test_bytes3_.size(); ++i)
+ for (wtf_size_t i = 0; i < test_bytes3_.size(); ++i)
test_bytes3_[i] = (i + 10) % 137;
test_data3_ = RawData::Create();
test_data3_->MutableData()->AppendVector(test_bytes3_);
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 17aef556b52..b62dca5e303 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -276,7 +276,8 @@ void BlobData::AppendDataInternal(base::span<const char> data,
const auto& bytes_element = elements_.back()->get_bytes();
bytes_element->length += data.size();
if (should_embed_bytes && bytes_element->embedded_data) {
- bytes_element->embedded_data->Append(data.data(), data.size());
+ bytes_element->embedded_data->Append(
+ data.data(), base::checked_cast<wtf_size_t>(data.size()));
current_memory_population_ += data.size();
} else if (bytes_element->embedded_data) {
current_memory_population_ -= bytes_element->embedded_data->size();
@@ -291,7 +292,8 @@ void BlobData::AppendDataInternal(base::span<const char> data,
data.size(), absl::nullopt, std::move(bytes_provider_remote));
if (should_embed_bytes) {
bytes_element->embedded_data = Vector<uint8_t>();
- bytes_element->embedded_data->Append(data.data(), data.size());
+ bytes_element->embedded_data->Append(
+ data.data(), base::checked_cast<wtf_size_t>(data.size()));
current_memory_population_ += data.size();
}
elements_.push_back(DataElement::NewBytes(std::move(bytes_element)));
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 d6be9983000..fa905f87ed4 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.h
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.h
@@ -43,6 +43,7 @@
#include "base/thread_annotations.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -103,6 +104,8 @@ class PLATFORM_EXPORT BlobData {
explicit BlobData(
FileCompositionStatus = FileCompositionStatus::NO_UNKNOWN_SIZE_FILES);
+ BlobData(const BlobData&) = delete;
+ BlobData& operator=(const BlobData&) = delete;
~BlobData();
// Calling append* on objects returned by createFor___WithUnknownSize will
@@ -166,8 +169,6 @@ class PLATFORM_EXPORT BlobData {
Vector<mojom::blink::DataElementPtr> elements_;
size_t current_memory_population_ = 0;
BlobBytesProvider* last_bytes_provider_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(BlobData);
};
class PLATFORM_EXPORT BlobDataHandle
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc b/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc
index 146f85d4064..8f1d08efa8e 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc
@@ -99,11 +99,11 @@ class BlobDataHandleTest : public testing::Test {
small_test_data_.resize(1024);
medium_test_data_.resize(1024 * 32);
large_test_data_.resize(1024 * 512);
- for (size_t i = 0; i < small_test_data_.size(); ++i)
+ for (wtf_size_t i = 0; i < small_test_data_.size(); ++i)
small_test_data_[i] = i;
- for (size_t i = 0; i < medium_test_data_.size(); ++i)
+ for (wtf_size_t i = 0; i < medium_test_data_.size(); ++i)
medium_test_data_[i] = i % 191;
- for (size_t i = 0; i < large_test_data_.size(); ++i)
+ for (wtf_size_t i = 0; i < large_test_data_.size(); ++i)
large_test_data_[i] = i % 251;
ASSERT_LT(small_test_data_.size(),
@@ -154,7 +154,7 @@ class BlobDataHandleTest : public testing::Test {
EXPECT_EQ(type.IsNull() ? "" : type, reg.content_type);
EXPECT_EQ("", reg.content_disposition);
ASSERT_EQ(expected_elements.size(), reg.elements.size());
- for (size_t i = 0; i < expected_elements.size(); ++i) {
+ for (wtf_size_t i = 0; i < expected_elements.size(); ++i) {
const auto& expected = expected_elements[i].element;
auto& actual = reg.elements[i];
if (expected->is_bytes()) {
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_url_null_origin_map.cc b/chromium/third_party/blink/renderer/platform/blob/blob_url_null_origin_map.cc
index cfa2014920a..95c2bfb7f35 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_url_null_origin_map.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_url_null_origin_map.cc
@@ -39,7 +39,8 @@ SecurityOrigin* BlobURLNullOriginMap::Get(const KURL& blob_url) {
DCHECK_EQ(BlobURL::GetOrigin(blob_url), "null");
KURL blob_url_without_fragment = blob_url;
blob_url_without_fragment.RemoveFragmentIdentifier();
- return blob_url_null_origin_map_.at(blob_url_without_fragment.GetString());
+ return blob_url_null_origin_map_.DeprecatedAtOrEmptyValue(
+ blob_url_without_fragment.GetString());
}
BlobURLOpaqueOriginNonceMap& BlobURLOpaqueOriginNonceMap::GetInstance() {
@@ -73,7 +74,7 @@ base::UnguessableToken BlobURLOpaqueOriginNonceMap::Get(const KURL& blob_url) {
DCHECK_EQ(BlobURL::GetOrigin(blob_url), "null");
KURL blob_url_without_fragment = blob_url;
blob_url_without_fragment.RemoveFragmentIdentifier();
- return blob_url_opaque_origin_nonce_map_.at(
+ return blob_url_opaque_origin_nonce_map_.DeprecatedAtOrEmptyValue(
blob_url_without_fragment.GetString());
}
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 1bb7d53643c..4092e852556 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
@@ -15,6 +15,8 @@ namespace {
class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
public:
SimpleDataPipeGetter(const String& str) : str_(str) {}
+ SimpleDataPipeGetter(const SimpleDataPipeGetter&) = delete;
+ SimpleDataPipeGetter& operator=(const SimpleDataPipeGetter&) = delete;
~SimpleDataPipeGetter() override = default;
// network::mojom::DataPipeGetter implementation:
@@ -33,8 +35,6 @@ class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
private:
String str_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleDataPipeGetter);
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc
index d70a550fff1..b2fe4203b3b 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc
@@ -8,10 +8,14 @@
namespace blink {
-void FakeBlobURLStore::Register(mojo::PendingRemote<mojom::blink::Blob> blob,
- const KURL& url,
- RegisterCallback callback) {
+void FakeBlobURLStore::Register(
+ mojo::PendingRemote<mojom::blink::Blob> blob,
+ const KURL& url,
+ // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ const base::UnguessableToken& unsafe_agent_cluster_id,
+ RegisterCallback callback) {
registrations.insert(url, mojo::Remote<mojom::blink::Blob>(std::move(blob)));
+ agent_registrations.insert(url, unsafe_agent_cluster_id);
std::move(callback).Run();
}
@@ -21,25 +25,28 @@ void FakeBlobURLStore::Revoke(const KURL& url) {
}
void FakeBlobURLStore::Resolve(const KURL& url, ResolveCallback callback) {
- auto it = registrations.find(url);
- if (it == registrations.end()) {
- std::move(callback).Run(mojo::NullRemote());
+ auto blob_it = registrations.find(url);
+ auto agent_it = agent_registrations.find(url);
+ if (blob_it == registrations.end() || agent_it == agent_registrations.end()) {
+ std::move(callback).Run(mojo::NullRemote(), absl::nullopt);
return;
}
mojo::PendingRemote<mojom::blink::Blob> blob;
- it->value->Clone(blob.InitWithNewPipeAndPassReceiver());
- std::move(callback).Run(std::move(blob));
+ blob_it->value->Clone(blob.InitWithNewPipeAndPassReceiver());
+ std::move(callback).Run(std::move(blob), agent_it->value);
}
void FakeBlobURLStore::ResolveAsURLLoaderFactory(
const KURL&,
- mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>) {
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>,
+ ResolveAsURLLoaderFactoryCallback callback) {
NOTREACHED();
}
void FakeBlobURLStore::ResolveForNavigation(
const KURL&,
- mojo::PendingReceiver<mojom::blink::BlobURLToken>) {
+ mojo::PendingReceiver<mojom::blink::BlobURLToken>,
+ ResolveForNavigationCallback callback) {
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h
index 93b7d672a7f..95b528cef88 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h
@@ -7,6 +7,7 @@
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
+#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -20,19 +21,24 @@ namespace blink {
// Mocked BlobURLStore implementation for testing.
class FakeBlobURLStore : public mojom::blink::BlobURLStore {
public:
- void Register(mojo::PendingRemote<mojom::blink::Blob>,
- const KURL&,
- RegisterCallback) override;
+ void Register(
+ mojo::PendingRemote<mojom::blink::Blob>,
+ const KURL&,
+ // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ const base::UnguessableToken& unsafe_agent_cluster_id,
+ RegisterCallback) override;
void Revoke(const KURL&) override;
void Resolve(const KURL&, ResolveCallback) override;
void ResolveAsURLLoaderFactory(
const KURL&,
- mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>) override;
- void ResolveForNavigation(
- const KURL&,
- mojo::PendingReceiver<mojom::blink::BlobURLToken>) override;
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>,
+ ResolveAsURLLoaderFactoryCallback) override;
+ void ResolveForNavigation(const KURL&,
+ mojo::PendingReceiver<mojom::blink::BlobURLToken>,
+ ResolveForNavigationCallback) override;
HashMap<KURL, mojo::Remote<mojom::blink::Blob>> registrations;
+ HashMap<KURL, base::UnguessableToken> agent_registrations;
Vector<KURL> revocations;
};
diff --git a/chromium/third_party/blink/renderer/platform/color_data.gperf b/chromium/third_party/blink/renderer/platform/color_data.gperf
index e47326a7311..e9281252d65 100644
--- a/chromium/third_party/blink/renderer/platform/color_data.gperf
+++ b/chromium/third_party/blink/renderer/platform/color_data.gperf
@@ -2,6 +2,8 @@
#include "third_party/blink/renderer/platform/graphics/color.h"
#include <string.h>
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+
namespace blink {
%}
diff --git a/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc b/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc
index abcd7fa6a09..2f559a64ba4 100644
--- a/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc
+++ b/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc
@@ -140,7 +140,8 @@ void DiskDataAllocator::Read(const DiskDataMetadata& metadata, void* data) {
// Doesn't need locking as files support concurrent access, and we don't
// update metadata.
char* data_char = reinterpret_cast<char*>(data);
- DoRead(metadata.start_offset(), data_char, metadata.size());
+ DoRead(metadata.start_offset(), data_char,
+ base::checked_cast<int>(metadata.size()));
#if DCHECK_IS_ON()
{
diff --git a/chromium/third_party/blink/renderer/platform/exported/mediastream/OWNERS b/chromium/third_party/blink/renderer/platform/exported/mediastream/OWNERS
index b99ae052002..2ad93e6b341 100644
--- a/chromium/third_party/blink/renderer/platform/exported/mediastream/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/exported/mediastream/OWNERS
@@ -1,3 +1 @@
file://third_party/blink/common/mediastream/OWNERS
-
-per-file media_stream_audio_processor*=aluebs@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc b/chromium/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc
index 880901ee286..a542131badf 100644
--- a/chromium/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc
@@ -13,19 +13,24 @@ namespace blink {
const char WebPlatformMediaStreamSource::kSourceId[] = "sourceId";
-WebPlatformMediaStreamSource::WebPlatformMediaStreamSource() {}
+WebPlatformMediaStreamSource::WebPlatformMediaStreamSource(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)) {}
WebPlatformMediaStreamSource::~WebPlatformMediaStreamSource() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(stop_callback_.is_null());
owner_ = nullptr;
}
void WebPlatformMediaStreamSource::StopSource() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DoStopSource();
FinalizeStopSource();
}
void WebPlatformMediaStreamSource::FinalizeStopSource() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (!stop_callback_.is_null())
std::move(stop_callback_).Run(Owner());
if (Owner())
@@ -33,6 +38,7 @@ void WebPlatformMediaStreamSource::FinalizeStopSource() {
}
void WebPlatformMediaStreamSource::SetSourceMuted(bool is_muted) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
// Although this change is valid only if the ready state isn't already Ended,
// there's code further along (like in MediaStreamTrack) which filters
// that out already.
@@ -43,11 +49,13 @@ void WebPlatformMediaStreamSource::SetSourceMuted(bool is_muted) {
}
void WebPlatformMediaStreamSource::SetDevice(const MediaStreamDevice& device) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
device_ = device;
}
void WebPlatformMediaStreamSource::SetCaptureHandle(
media::mojom::CaptureHandlePtr capture_handle) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (!device_.display_media_info.has_value()) {
DVLOG(1) << "Not a display-capture device.";
return;
@@ -58,30 +66,40 @@ void WebPlatformMediaStreamSource::SetCaptureHandle(
void WebPlatformMediaStreamSource::SetStopCallback(
SourceStoppedCallback stop_callback) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(stop_callback_.is_null());
stop_callback_ = std::move(stop_callback);
}
void WebPlatformMediaStreamSource::ResetSourceStoppedCallback() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!stop_callback_.is_null());
stop_callback_.Reset();
}
void WebPlatformMediaStreamSource::ChangeSource(
const MediaStreamDevice& new_device) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DoChangeSource(new_device);
}
WebMediaStreamSource WebPlatformMediaStreamSource::Owner() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(owner_);
return WebMediaStreamSource(owner_.Get());
}
#if INSIDE_BLINK
void WebPlatformMediaStreamSource::SetOwner(MediaStreamSource* owner) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!owner_);
owner_ = owner;
}
#endif
+base::SingleThreadTaskRunner* WebPlatformMediaStreamSource::GetTaskRunner()
+ const {
+ return task_runner_.get();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/platform.cc b/chromium/third_party/blink/renderer/platform/exported/platform.cc
index 5e808a73389..0cd64e074c9 100644
--- a/chromium/third_party/blink/renderer/platform/exported/platform.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/platform.cc
@@ -44,6 +44,7 @@
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
@@ -91,6 +92,8 @@ class IdleDelayedTaskHelper : public base::SingleThreadTaskRunner {
public:
IdleDelayedTaskHelper() = default;
+ IdleDelayedTaskHelper(const IdleDelayedTaskHelper&) = delete;
+ IdleDelayedTaskHelper& operator=(const IdleDelayedTaskHelper&) = delete;
bool RunsTasksInCurrentSequence() const override { return IsMainThread(); }
@@ -118,7 +121,6 @@ class IdleDelayedTaskHelper : public base::SingleThreadTaskRunner {
private:
THREAD_CHECKER(thread_checker_);
- DISALLOW_COPY_AND_ASSIGN(IdleDelayedTaskHelper);
};
} // namespace
@@ -286,12 +288,29 @@ Platform* Platform::Current() {
return g_platform;
}
+std::unique_ptr<WebURLLoaderFactory> Platform::WrapURLLoaderFactory(
+ CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase>) {
+ return nullptr;
+}
+
std::unique_ptr<blink::WebURLLoaderFactory>
Platform::WrapSharedURLLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> factory) {
return nullptr;
}
+void Platform::CreateServiceWorkerSubresourceLoaderFactory(
+ CrossVariantMojoRemote<mojom::ServiceWorkerContainerHostInterfaceBase>
+ service_worker_container_host,
+ const WebString& client_id,
+ std::unique_ptr<network::PendingSharedURLLoaderFactory> fallback_factory,
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ scoped_refptr<base::SequencedTaskRunner> worker_timing_callback_task_runner,
+ base::RepeatingCallback<
+ void(int, mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>)>
+ worker_timing_callback) {}
+
ThreadSafeBrowserInterfaceBrokerProxy* Platform::GetBrowserInterfaceBroker() {
DEFINE_STATIC_LOCAL(DefaultBrowserInterfaceBrokerProxy, proxy, ());
return &proxy;
diff --git a/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc b/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
index e2b8b397e72..e91a7a7bbf1 100644
--- a/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
@@ -58,6 +57,8 @@ class MockVideoCaptureImpl : public VideoCaptureImpl,
pause_callback_(pause_callback),
destruct_callback_(std::move(destruct_callback)) {}
+ MockVideoCaptureImpl(const MockVideoCaptureImpl&) = delete;
+ MockVideoCaptureImpl& operator=(const MockVideoCaptureImpl&) = delete;
~MockVideoCaptureImpl() override { std::move(destruct_callback_).Run(); }
private:
@@ -109,8 +110,6 @@ class MockVideoCaptureImpl : public VideoCaptureImpl,
PauseResumeCallback* const pause_callback_;
base::OnceClosure destruct_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImpl);
};
class MockVideoCaptureImplManager : public WebVideoCaptureImplManager {
@@ -119,6 +118,10 @@ class MockVideoCaptureImplManager : public WebVideoCaptureImplManager {
base::RepeatingClosure stop_capture_callback)
: pause_callback_(pause_callback),
stop_capture_callback_(stop_capture_callback) {}
+
+ MockVideoCaptureImplManager(const MockVideoCaptureImplManager&) = delete;
+ MockVideoCaptureImplManager& operator=(const MockVideoCaptureImplManager&) =
+ delete;
~MockVideoCaptureImplManager() override {}
private:
@@ -132,8 +135,6 @@ class MockVideoCaptureImplManager : public WebVideoCaptureImplManager {
PauseResumeCallback* const pause_callback_;
const base::RepeatingClosure stop_capture_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImplManager);
};
} // namespace
@@ -151,6 +152,10 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
}
}
+ VideoCaptureImplManagerTest(const VideoCaptureImplManagerTest&) = delete;
+ VideoCaptureImplManagerTest& operator=(const VideoCaptureImplManagerTest&) =
+ delete;
+
protected:
static constexpr size_t kNumClients = 3;
std::array<base::UnguessableToken, kNumClients> session_ids_;
@@ -237,9 +242,6 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
base::RunLoop cleanup_run_loop_;
std::unique_ptr<MockVideoCaptureImplManager> manager_;
BrowserInterfaceBrokerProxy* browser_interface_broker_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest);
};
// Multiple clients with the same session id. There is only one
diff --git a/chromium/third_party/blink/renderer/platform/exported/weak_wrapper_resource_load_info_notifier.cc b/chromium/third_party/blink/renderer/platform/exported/weak_wrapper_resource_load_info_notifier.cc
index 20b0bc8ebab..3bc90ec1001 100644
--- a/chromium/third_party/blink/renderer/platform/exported/weak_wrapper_resource_load_info_notifier.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/weak_wrapper_resource_load_info_notifier.cc
@@ -4,6 +4,9 @@
#include "third_party/blink/public/platform/weak_wrapper_resource_load_info_notifier.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
+
namespace blink {
WeakWrapperResourceLoadInfoNotifier::WeakWrapperResourceLoadInfoNotifier(
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_audio_bus.cc b/chromium/third_party/blink/renderer/platform/exported/web_audio_bus.cc
index d01605f0012..1cae01219d6 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_audio_bus.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_audio_bus.cc
@@ -32,8 +32,8 @@ namespace blink {
void WebAudioBus::Initialize(unsigned number_of_channels,
size_t length,
double sample_rate) {
- scoped_refptr<AudioBus> audio_bus =
- AudioBus::Create(number_of_channels, length);
+ scoped_refptr<AudioBus> audio_bus = AudioBus::Create(
+ number_of_channels, base::checked_cast<wtf_size_t>(length));
audio_bus->SetSampleRate(sample_rate);
if (private_)
@@ -47,7 +47,7 @@ void WebAudioBus::ResizeSmaller(size_t new_length) {
DCHECK(private_);
if (private_) {
DCHECK_LE(new_length, length());
- private_->ResizeSmaller(new_length);
+ private_->ResizeSmaller(static_cast<wtf_size_t>(new_length));
}
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_audio_device.cc b/chromium/third_party/blink/renderer/platform/exported/web_audio_device.cc
index d6e20a8e703..6e3937a93a6 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_audio_device.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_audio_device.cc
@@ -28,7 +28,7 @@ namespace blink {
void WebAudioDevice::RenderCallback::Render(
const WebVector<float*>& destination_data,
- size_t number_of_frames,
+ uint32_t number_of_frames,
double delay,
double delay_timestamp,
size_t prior_frames_skipped) {}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc b/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
index 8ebd8d8cf43..d71c4d8b1c8 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
@@ -33,8 +33,8 @@
#include <memory>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc b/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc
index 1bf90c958e8..3f10fdb0024 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc
@@ -65,7 +65,8 @@ bool WebHTTPBody::ElementAt(size_t index, Element& result) const {
if (index >= private_->Elements().size())
return false;
- const FormDataElement& element = private_->Elements()[index];
+ const FormDataElement& element =
+ private_->Elements()[static_cast<wtf_size_t>(index)];
result.data.Reset();
result.file_path.Reset();
@@ -109,11 +110,11 @@ void WebHTTPBody::AppendData(const WebData& data) {
EnsureMutable();
// FIXME: FormDataElement::m_data should be a SharedBuffer<char>. Then we
// could avoid this buffer copy.
- data.ForEachSegment(
- [this](const char* segment, size_t segment_size, size_t segment_offset) {
- private_->AppendData(segment, segment_size);
- return true;
- });
+ data.ForEachSegment([this](const char* segment, size_t segment_size,
+ size_t segment_offset) {
+ private_->AppendData(segment, base::checked_cast<wtf_size_t>(segment_size));
+ return true;
+ });
}
void WebHTTPBody::AppendFileRange(
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_http_load_info.cc b/chromium/third_party/blink/renderer/platform/exported/web_http_load_info.cc
deleted file mode 100644
index f439af5eb57..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_http_load_info.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_http_load_info.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/renderer/platform/loader/fetch/resource_load_info.h"
-
-namespace blink {
-
-void WebHTTPLoadInfo::Initialize() {
- private_ = base::AdoptRef(new ResourceLoadInfo());
-}
-
-void WebHTTPLoadInfo::Reset() {
- private_.Reset();
-}
-
-void WebHTTPLoadInfo::Assign(const WebHTTPLoadInfo& r) {
- private_ = r.private_;
-}
-
-WebHTTPLoadInfo::WebHTTPLoadInfo(scoped_refptr<ResourceLoadInfo> value)
- : private_(std::move(value)) {}
-
-WebHTTPLoadInfo::operator scoped_refptr<ResourceLoadInfo>() const {
- return private_.Get();
-}
-
-int WebHTTPLoadInfo::HttpStatusCode() const {
- DCHECK(!private_.IsNull());
- return private_->http_status_code;
-}
-
-void WebHTTPLoadInfo::SetHTTPStatusCode(int status_code) {
- DCHECK(!private_.IsNull());
- private_->http_status_code = status_code;
-}
-
-WebString WebHTTPLoadInfo::HttpStatusText() const {
- DCHECK(!private_.IsNull());
- return private_->http_status_text;
-}
-
-void WebHTTPLoadInfo::SetHTTPStatusText(const WebString& status_text) {
- DCHECK(!private_.IsNull());
- private_->http_status_text = status_text;
-}
-
-static void AddHeader(HTTPHeaderMap* map,
- const WebString& name,
- const WebString& value) {
- HTTPHeaderMap::AddResult result = map->Add(name, value);
- // It is important that values are separated by '\n', not comma, otherwise
- // Set-Cookie header is not parseable.
- if (!result.is_new_entry)
- result.stored_value->value =
- result.stored_value->value + "\n" + String(value);
-}
-
-void WebHTTPLoadInfo::AddRequestHeader(const WebString& name,
- const WebString& value) {
- DCHECK(!private_.IsNull());
- AddHeader(&private_->request_headers, name, value);
-}
-
-void WebHTTPLoadInfo::AddResponseHeader(const WebString& name,
- const WebString& value) {
- DCHECK(!private_.IsNull());
- AddHeader(&private_->response_headers, name, value);
-}
-
-WebString WebHTTPLoadInfo::RequestHeadersText() const {
- DCHECK(!private_.IsNull());
- return private_->request_headers_text;
-}
-
-void WebHTTPLoadInfo::SetRequestHeadersText(const WebString& headers_text) {
- DCHECK(!private_.IsNull());
- private_->request_headers_text = headers_text;
-}
-
-WebString WebHTTPLoadInfo::ResponseHeadersText() const {
- DCHECK(!private_.IsNull());
- return private_->response_headers_text;
-}
-
-void WebHTTPLoadInfo::SetResponseHeadersText(const WebString& headers_text) {
- DCHECK(!private_.IsNull());
- private_->response_headers_text = headers_text;
-}
-
-} // 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 ae208c313c1..9d142c02693 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
@@ -136,6 +136,10 @@ void WebRuntimeFeatures::EnableAccessibilityObjectModel(bool enable) {
RuntimeEnabledFeatures::SetAccessibilityObjectModelEnabled(enable);
}
+void WebRuntimeFeatures::EnableAccessibilityPageZoom(bool enable) {
+ RuntimeEnabledFeatures::SetAccessibilityPageZoomEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableAccessibilityUseAXPositionForDocumentMarkers(
bool enable) {
RuntimeEnabledFeatures::
@@ -162,10 +166,6 @@ void WebRuntimeFeatures::EnableCacheInlineScriptCode(bool enable) {
RuntimeEnabledFeatures::SetCacheInlineScriptCodeEnabled(enable);
}
-void WebRuntimeFeatures::EnableCookiesWithoutSameSiteMustBeSecure(bool enable) {
- RuntimeEnabledFeatures::SetCookiesWithoutSameSiteMustBeSecureEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableCanvas2dImageChromium(bool enable) {
RuntimeEnabledFeatures::SetCanvas2dImageChromiumEnabled(enable);
}
@@ -178,10 +178,6 @@ void WebRuntimeFeatures::EnableCSSHexAlphaColor(bool enable) {
RuntimeEnabledFeatures::SetCSSHexAlphaColorEnabled(enable);
}
-void WebRuntimeFeatures::EnableSameSiteByDefaultCookies(bool enable) {
- RuntimeEnabledFeatures::SetSameSiteByDefaultCookiesEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableScrollTopLeftInterop(bool enable) {
RuntimeEnabledFeatures::SetScrollTopLeftInteropEnabled(enable);
}
@@ -206,6 +202,10 @@ void WebRuntimeFeatures::EnableDecodeLossyWebPImagesToYUV(bool enable) {
RuntimeEnabledFeatures::SetDecodeLossyWebPImagesToYUVEnabled(enable);
}
+void WebRuntimeFeatures::EnableDevicePosture(bool enable) {
+ RuntimeEnabledFeatures::SetDevicePostureEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableRemoveMobileViewportDoubleTap(bool enable) {
RuntimeEnabledFeatures::SetRemoveMobileViewportDoubleTapEnabled(enable);
}
@@ -344,6 +344,10 @@ void WebRuntimeFeatures::EnableScrollUnification(bool enable) {
RuntimeEnabledFeatures::SetScrollUnificationEnabled(enable);
}
+void WebRuntimeFeatures::EnableWebGLDeveloperExtensions(bool enable) {
+ RuntimeEnabledFeatures::SetWebGLDeveloperExtensionsEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableWebGLDraftExtensions(bool enable) {
RuntimeEnabledFeatures::SetWebGLDraftExtensionsEnabled(enable);
}
@@ -368,6 +372,10 @@ void WebRuntimeFeatures::EnableSharedAutofill(bool enable) {
RuntimeEnabledFeatures::SetSharedAutofillEnabled(enable);
}
+void WebRuntimeFeatures::EnableSharedStorageAPI(bool enable) {
+ RuntimeEnabledFeatures::SetSharedStorageAPIEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableSharedWorker(bool enable) {
RuntimeEnabledFeatures::SetSharedWorkerEnabled(enable);
}
@@ -388,6 +396,10 @@ void WebRuntimeFeatures::EnablePrerender2(bool enable) {
RuntimeEnabledFeatures::SetPrerender2Enabled(enable);
}
+bool WebRuntimeFeatures::IsPrerender2Enabled() {
+ return RuntimeEnabledFeatures::Prerender2EnabledByRuntimeFlag();
+}
+
void WebRuntimeFeatures::EnableV8IdleTasks(bool enable) {
RuntimeEnabledFeatures::SetV8IdleTasksEnabled(enable);
}
@@ -476,6 +488,10 @@ void WebRuntimeFeatures::EnableRestrictAutomaticLazyImageLoadingToDataSaver(
SetRestrictAutomaticLazyImageLoadingToDataSaverEnabled(enable);
}
+void WebRuntimeFeatures::EnableSecurePaymentConfirmationAPIV3(bool enable) {
+ RuntimeEnabledFeatures::SetSecurePaymentConfirmationAPIV3Enabled(enable);
+}
+
void WebRuntimeFeatures::EnableSecurePaymentConfirmationDebug(bool enable) {
RuntimeEnabledFeatures::SetSecurePaymentConfirmationDebugEnabled(enable);
}
@@ -484,18 +500,10 @@ void WebRuntimeFeatures::EnableAutoLazyLoadOnReloads(bool enable) {
RuntimeEnabledFeatures::SetAutoLazyLoadOnReloadsEnabled(enable);
}
-void WebRuntimeFeatures::EnableExpensiveBackgroundTimerThrottling(bool enable) {
- RuntimeEnabledFeatures::SetExpensiveBackgroundTimerThrottlingEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableTimerThrottlingForBackgroundTabs(bool enable) {
RuntimeEnabledFeatures::SetTimerThrottlingForBackgroundTabsEnabled(enable);
}
-void WebRuntimeFeatures::EnableTimerThrottlingForHiddenFrames(bool enable) {
- RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableSendBeaconThrowForBlobWithNonSimpleType(
bool enable) {
RuntimeEnabledFeatures::SetSendBeaconThrowForBlobWithNonSimpleTypeEnabled(
@@ -512,6 +520,16 @@ void WebRuntimeFeatures::EnableSharedArrayBufferUnrestrictedAccessAllowed(
enable);
}
+void WebRuntimeFeatures::EnableCrossOriginWebAssemblyModuleSharingAllowed(
+ bool enable) {
+ RuntimeEnabledFeatures::SetCrossOriginWebAssemblyModuleSharingAllowedEnabled(
+ enable);
+}
+
+void WebRuntimeFeatures::EnableDisplayCapturePermissionsPolicy(bool enable) {
+ RuntimeEnabledFeatures::SetDisplayCapturePermissionsPolicyEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableRemotePlaybackAPI(bool enable) {
RuntimeEnabledFeatures::SetRemotePlaybackEnabled(enable);
}
@@ -550,10 +568,6 @@ void WebRuntimeFeatures::EnableAutomationControlled(bool enable) {
RuntimeEnabledFeatures::SetAutomationControlledEnabled(enable);
}
-void WebRuntimeFeatures::EnableDisallowDocumentAccess(bool enable) {
- RuntimeEnabledFeatures::SetDisallowDocumentAccessEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableDisplayCutoutAPI(bool enable) {
RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(enable);
}
@@ -582,10 +596,6 @@ void WebRuntimeFeatures::EnableGetDisplayMedia(bool enable) {
RuntimeEnabledFeatures::SetGetDisplayMediaEnabled(enable);
}
-void WebRuntimeFeatures::EnableGetCurrentBrowsingContextMedia(bool enable) {
- RuntimeEnabledFeatures::SetGetCurrentBrowsingContextMediaEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableAllowSyncXHRInPageDismissal(bool enable) {
RuntimeEnabledFeatures::SetAllowSyncXHRInPageDismissalEnabled(enable);
}
@@ -648,6 +658,10 @@ void WebRuntimeFeatures::EnableTransformInterop(bool enable) {
RuntimeEnabledFeatures::SetTransformInteropEnabled(enable);
}
+void WebRuntimeFeatures::EnableBackfaceVisibilityInterop(bool enable) {
+ RuntimeEnabledFeatures::SetBackfaceVisibilityInteropEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableVideoWakeLockOptimisationHiddenMuted(
bool enable) {
RuntimeEnabledFeatures::SetVideoWakeLockOptimisationHiddenMutedEnabled(
@@ -662,14 +676,14 @@ void WebRuntimeFeatures::EnableRestrictGamepadAccess(bool enable) {
RuntimeEnabledFeatures::SetRestrictGamepadAccessEnabled(enable);
}
-void WebRuntimeFeatures::EnableConversionMeasurementInfraSupport(bool enable) {
- RuntimeEnabledFeatures::SetConversionMeasurementInfraSupportEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableParseUrlProtocolHandler(bool enable) {
RuntimeEnabledFeatures::SetParseUrlProtocolHandlerEnabled(enable);
}
+void WebRuntimeFeatures::EnableWebAppManifestId(bool enable) {
+ RuntimeEnabledFeatures::SetWebAppManifestIdEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableWebID(bool enable) {
RuntimeEnabledFeatures::SetWebIDEnabled(enable);
}
@@ -678,12 +692,12 @@ void WebRuntimeFeatures::EnableTargetBlankImpliesNoOpener(bool enable) {
RuntimeEnabledFeatures::SetTargetBlankImpliesNoOpenerEnabled(enable);
}
-void WebRuntimeFeatures::EnableCSSColorSchemeUARendering(bool enable) {
- RuntimeEnabledFeatures::SetCSSColorSchemeUARenderingEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableDocumentTransition(bool enable) {
RuntimeEnabledFeatures::SetDocumentTransitionEnabled(enable);
}
+void WebRuntimeFeatures::EnableCLSScrollAnchoring(bool enable) {
+ RuntimeEnabledFeatures::SetCLSScrollAnchoringEnabled(enable);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_screen_info_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_screen_info_test.cc
index 5c565ad2c88..1fb1dde8f5b 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_screen_info_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_screen_info_test.cc
@@ -2,15 +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/public/common/widget/screen_info.h"
+#include "ui/display/screen_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
TEST(ScreenInfoTest, Equality) {
- ScreenInfo screen_info1;
- ScreenInfo screen_info2;
+ display::ScreenInfo screen_info1;
+ display::ScreenInfo screen_info2;
EXPECT_EQ(screen_info1, screen_info2);
@@ -38,7 +38,7 @@ TEST(ScreenInfoTest, Equality) {
screen_info1.rect = gfx::Rect(1024, 1024);
screen_info1.available_rect = gfx::Rect(1024, 1024);
screen_info1.orientation_type =
- blink::mojom::ScreenOrientation::kLandscapePrimary;
+ display::mojom::ScreenOrientation::kLandscapePrimary;
screen_info1.orientation_angle = 90;
EXPECT_NE(screen_info1, screen_info2);
@@ -50,7 +50,7 @@ TEST(ScreenInfoTest, Equality) {
screen_info2.rect = gfx::Rect(1024, 1024);
screen_info2.available_rect = gfx::Rect(1024, 1024);
screen_info2.orientation_type =
- blink::mojom::ScreenOrientation::kLandscapePrimary;
+ display::mojom::ScreenOrientation::kLandscapePrimary;
screen_info2.orientation_angle = 90;
EXPECT_EQ(screen_info1, screen_info2);
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_string.cc b/chromium/third_party/blink/renderer/platform/exported/web_string.cc
index 1d45bdb3e1f..6e2dd1ec1f6 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_string.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_string.cc
@@ -56,7 +56,9 @@ WebString& WebString::operator=(const WebString&) = default;
WebString& WebString::operator=(WebString&&) = default;
WebString::WebString(const WebUChar* data, size_t len)
- : impl_(StringImpl::Create8BitIfPossible(data, len)) {}
+ : impl_(StringImpl::Create8BitIfPossible(
+ data,
+ base::checked_cast<wtf_size_t>(len))) {}
void WebString::Reset() {
impl_ = nullptr;
@@ -83,7 +85,8 @@ std::string WebString::Utf8(UTF8ConversionMode mode) const {
}
WebString WebString::Substring(size_t pos, size_t len) const {
- return String(impl_->Substring(pos, len));
+ return String(impl_->Substring(base::checked_cast<wtf_size_t>(pos),
+ base::checked_cast<wtf_size_t>(len)));
}
WebString WebString::FromUTF8(const char* data, size_t length) {
@@ -109,7 +112,7 @@ std::string WebString::Latin1() const {
}
WebString WebString::FromLatin1(const WebLChar* data, size_t length) {
- return String(data, length);
+ return String(data, base::checked_cast<wtf_size_t>(length));
}
std::string WebString::Ascii() const {
@@ -147,7 +150,7 @@ bool WebString::Equals(const WebString& s) const {
}
bool WebString::Equals(const char* characters, size_t length) const {
- return Equal(impl_.get(), characters, length);
+ return Equal(impl_.get(), characters, base::checked_cast<wtf_size_t>(length));
}
WebString::WebString(const WTF::String& s) : impl_(s.Impl()) {}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_thread_safe_data.cc b/chromium/third_party/blink/renderer/platform/exported/web_thread_safe_data.cc
index 19196e639d8..31ae8b13cd7 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_thread_safe_data.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_thread_safe_data.cc
@@ -36,7 +36,7 @@ namespace blink {
WebThreadSafeData::WebThreadSafeData(const char* data, size_t length) {
private_ = RawData::Create();
- private_->MutableData()->Append(data, length);
+ private_->MutableData()->Append(data, base::checked_cast<wtf_size_t>(length));
}
void WebThreadSafeData::Reset() {
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 c7ff37790c5..6cd9baac9d0 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
@@ -235,14 +235,6 @@ void WebURLRequest::SetReportUploadProgress(bool report_upload_progress) {
resource_request_->SetReportUploadProgress(report_upload_progress);
}
-void WebURLRequest::SetReportRawHeaders(bool report_raw_headers) {
- resource_request_->SetReportRawHeaders(report_raw_headers);
-}
-
-bool WebURLRequest::ReportRawHeaders() const {
- return resource_request_->ReportRawHeaders();
-}
-
mojom::blink::RequestContextType WebURLRequest::GetRequestContext() const {
return resource_request_->GetRequestContext();
}
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 a67bba839ef..0f145b1960b 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
@@ -39,10 +39,8 @@
#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
#include "services/network/public/mojom/load_timing_info.mojom.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
-#include "third_party/blink/public/platform/web_http_load_info.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -125,10 +123,6 @@ void WebURLResponse::SetLoadTiming(
resource_response_->SetResourceLoadTiming(std::move(timing));
}
-void WebURLResponse::SetHTTPLoadInfo(const WebHTTPLoadInfo& value) {
- resource_response_->SetResourceLoadInfo(value);
-}
-
base::Time WebURLResponse::ResponseTime() const {
return resource_response_->ResponseTime();
}
@@ -288,8 +282,9 @@ void WebURLResponse::SetSecurityDetails(
static_cast<ResourceResponse::SignedCertificateTimestamp>(iter));
}
Vector<String> san_list;
- san_list.Append(web_security_details.san_list.Data(),
- web_security_details.san_list.size());
+ san_list.Append(
+ web_security_details.san_list.Data(),
+ base::checked_cast<wtf_size_t>(web_security_details.san_list.size()));
Vector<AtomicString> certificate;
for (const auto& iter : web_security_details.certificate) {
AtomicString cert = iter;
@@ -379,7 +374,8 @@ int64_t WebURLResponse::GetPadding() const {
void WebURLResponse::SetUrlListViaServiceWorker(
const WebVector<WebURL>& url_list_via_service_worker) {
- Vector<KURL> url_list(url_list_via_service_worker.size());
+ Vector<KURL> url_list(
+ base::checked_cast<wtf_size_t>(url_list_via_service_worker.size()));
std::transform(url_list_via_service_worker.begin(),
url_list_via_service_worker.end(), url_list.begin(),
[](const WebURL& url) { return url; });
@@ -408,7 +404,8 @@ WebVector<WebString> WebURLResponse::CorsExposedHeaderNames() const {
void WebURLResponse::SetCorsExposedHeaderNames(
const WebVector<WebString>& header_names) {
Vector<String> exposed_header_names;
- exposed_header_names.Append(header_names.Data(), header_names.size());
+ exposed_header_names.Append(
+ header_names.Data(), base::checked_cast<wtf_size_t>(header_names.size()));
resource_response_->SetCorsExposedHeaderNames(exposed_header_names);
}
@@ -526,7 +523,7 @@ bool WebURLResponse::FromArchive() const {
}
void WebURLResponse::SetDnsAliases(const WebVector<WebString>& aliases) {
- Vector<String> dns_aliases(aliases.size());
+ Vector<String> dns_aliases(base::checked_cast<wtf_size_t>(aliases.size()));
std::transform(aliases.begin(), aliases.end(), dns_aliases.begin(),
[](const WebString& h) { return WTF::String(h); });
resource_response_->SetDnsAliases(std::move(dns_aliases));
@@ -550,6 +547,15 @@ WebURLResponse::AuthChallengeInfo() const {
return resource_response_->AuthChallengeInfo();
}
+void WebURLResponse::SetRequestIncludeCredentials(
+ bool request_include_credentials) {
+ resource_response_->SetRequestIncludeCredentials(request_include_credentials);
+}
+
+bool WebURLResponse::RequestIncludeCredentials() const {
+ return resource_response_->RequestIncludeCredentials();
+}
+
WebURLResponse::WebURLResponse(ResourceResponse& r) : resource_response_(&r) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_vector_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_vector_test.cc
index 790c49a2c6a..e25aee08545 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_vector_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_vector_test.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/public/platform/web_vector.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc b/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc
index adba8c78e0b..af6796cba39 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc
@@ -28,11 +28,12 @@ std::unique_ptr<WebVideoFrameSubmitter> WebVideoFrameSubmitter::Create(
WebContextProviderCallback context_provider_callback,
cc::VideoPlaybackRoughnessReporter::ReportingCallback
roughness_reporting_callback,
+ const viz::FrameSinkId& parent_frame_sink_id,
const cc::LayerTreeSettings& settings,
bool use_sync_primitives) {
return std::make_unique<VideoFrameSubmitter>(
std::move(context_provider_callback),
- std::move(roughness_reporting_callback),
+ std::move(roughness_reporting_callback), parent_frame_sink_id,
std::make_unique<VideoFrameResourceProvider>(settings,
use_sync_primitives));
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_request.h b/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_request.h
index 42f7e21afaf..0624b819850 100644
--- a/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_request.h
+++ b/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_request.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_EXPORTED_WRAPPED_RESOURCE_REQUEST_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_EXPORTED_WRAPPED_RESOURCE_REQUEST_H_
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -41,6 +40,8 @@ namespace blink {
// but just holds a pointer to it. It is not copyable.
class WrappedResourceRequest : public WebURLRequest {
public:
+ WrappedResourceRequest(const WrappedResourceRequest&) = delete;
+ WrappedResourceRequest& operator=(const WrappedResourceRequest&) = delete;
~WrappedResourceRequest() = default;
explicit WrappedResourceRequest(ResourceRequest& resource_request)
@@ -49,9 +50,6 @@ class WrappedResourceRequest : public WebURLRequest {
explicit WrappedResourceRequest(const ResourceRequest& resource_request)
: WrappedResourceRequest(const_cast<ResourceRequest&>(resource_request)) {
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WrappedResourceRequest);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_response.h b/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_response.h
index d67752445e0..2ff7b9771ca 100644
--- a/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_response.h
+++ b/chromium/third_party/blink/renderer/platform/exported/wrapped_resource_response.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_EXPORTED_WRAPPED_RESOURCE_RESPONSE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_EXPORTED_WRAPPED_RESOURCE_RESPONSE_H_
-#include "base/macros.h"
#include "third_party/blink/public/platform/web_url_response.h"
namespace blink {
@@ -40,6 +39,8 @@ namespace blink {
// but just holds a pointer to it. It is not copyable.
class WrappedResourceResponse : public WebURLResponse {
public:
+ WrappedResourceResponse(const WrappedResourceResponse&) = delete;
+ WrappedResourceResponse& operator=(const WrappedResourceResponse&) = delete;
~WrappedResourceResponse() = default;
explicit WrappedResourceResponse(ResourceResponse& resource_response)
@@ -48,9 +49,6 @@ class WrappedResourceResponse : public WebURLResponse {
explicit WrappedResourceResponse(const ResourceResponse& resource_response)
: WrappedResourceResponse(
const_cast<ResourceResponse&>(resource_response)) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WrappedResourceResponse);
};
} // 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 21ac41e09a8..534b74a9720 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
@@ -82,6 +82,41 @@ const AtomicString& FontCache::SystemFontFamily() {
// static
void FontCache::SetSystemFontFamily(const AtomicString&) {}
+sk_sp<SkTypeface> FontCache::CreateLocaleSpecificTypeface(
+ const FontDescription& font_description,
+ const char* locale_family_name) {
+ const char* bcp47 = font_description.LocaleOrDefault().LocaleForSkFontMgr();
+ DCHECK(bcp47);
+ SkFontMgr* font_manager =
+ font_manager_ ? font_manager_.get() : SkFontMgr::RefDefault().get();
+ sk_sp<SkTypeface> typeface(font_manager->matchFamilyStyleCharacter(
+ locale_family_name, font_description.SkiaFontStyle(), &bcp47,
+ /* bcp47Count */ 1,
+ // |matchFamilyStyleCharacter| is the only API that accepts |bcp47|, but
+ // it also checks if a character has a glyph. To look up the first
+ // match, use the space character, because all fonts are likely to have
+ // a glyph for it.
+ kSpaceCharacter));
+ if (!typeface)
+ return nullptr;
+
+ // When the specified family of the specified language does not exist, we want
+ // to fall back to the specified family of the default language, but
+ // |matchFamilyStyleCharacter| falls back to the default family of the
+ // specified language. Get the default family of the language and compare
+ // with what we get.
+ SkString skia_family_name;
+ typeface->getFamilyName(&skia_family_name);
+ sk_sp<SkTypeface> fallback(font_manager->matchFamilyStyleCharacter(
+ nullptr, font_description.SkiaFontStyle(), &bcp47,
+ /* bcp47Count */ 1, kSpaceCharacter));
+ SkString skia_fallback_name;
+ fallback->getFamilyName(&skia_fallback_name);
+ if (typeface != fallback)
+ return typeface;
+ return nullptr;
+}
+
scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
const FontDescription& font_description,
UChar32 c,
@@ -89,8 +124,16 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
FontFallbackPriority fallback_priority) {
sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
+ // Pass "serif" to |matchFamilyStyleCharacter| if the `font-family` list
+ // contains `serif`, so that it fallbacks to i18n serif fonts that has the
+ // specified character. Do this only for `serif` because other generic
+ // families do not have the lang-specific fallback list.
+ const char* generic_family_name = nullptr;
+ if (font_description.GenericFamily() == FontDescription::kSerifFamily)
+ generic_family_name = "serif";
+
AtomicString family_name = GetFamilyNameForCharacter(
- fm.get(), c, font_description, fallback_priority);
+ fm.get(), c, font_description, generic_family_name, fallback_priority);
// Return the GMS Core emoji font if FontFallbackPriority is kEmojiEmoji and
// a) no system fallback was found or b) the system fallback font's PostScript
@@ -152,6 +195,11 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
AtomicString FontCache::GetGenericFamilyNameForScript(
const AtomicString& family_name,
const FontDescription& font_description) {
+ // If this is a locale-specifc family name, |FontCache| can handle different
+ // typefaces per locale. Let it handle.
+ if (GetLocaleSpecificFamilyName(family_name))
+ return family_name;
+
// If monospace, do not apply CJK hack to find i18n fonts, because
// i18n fonts are likely not monospace. Monospace is mostly used
// for code, but when i18n characters appear in monospace, system
@@ -185,8 +233,9 @@ AtomicString FontCache::GetGenericFamilyNameForScript(
return family_name;
}
- sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- return GetFamilyNameForCharacter(fm.get(), exampler_char, font_description,
+ sk_sp<SkFontMgr> font_manager(SkFontMgr::RefDefault());
+ return GetFamilyNameForCharacter(font_manager.get(), exampler_char,
+ font_description, nullptr,
FontFallbackPriority::kText);
}
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 5f03b588f82..f76170d3bfe 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
@@ -10,13 +10,22 @@
namespace blink {
-// 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) {
+class FontCacheAndroidTest : public testing::Test {
+ protected:
+ // Returns a locale-specific `serif` typeface, or `nullptr` if the system
+ // does not have a locale-specific `serif`.
+ sk_sp<SkTypeface> CreateSerifTypeface(const LayoutLocale* locale) {
+ FontCache* font_cache = FontCache::GetFontCache();
+ FontDescription font_description;
+ font_description.SetLocale(locale);
+ font_description.SetGenericFamily(FontDescription::kSerifFamily);
+ return font_cache->CreateLocaleSpecificTypeface(font_description, "serif");
+ }
+
+ FontCachePurgePreventer purge_preventer;
+};
+
+TEST_F(FontCacheAndroidTest, FallbackFontForCharacter) {
// A Latin character in the common locale system font, but not in the
// Chinese locale-preferred font.
const UChar32 kTestChar = 228;
@@ -33,14 +42,53 @@ TEST(FontCacheAndroid, MAYBE_fallbackFontForCharacter) {
EXPECT_TRUE(font_data);
}
-TEST(FontCacheAndroid, genericFamilyNameForScript) {
+TEST_F(FontCacheAndroidTest, FallbackFontForCharacterSerif) {
+ // Test is valid only if the system has a locale-specific `serif`.
+ const LayoutLocale* ja = LayoutLocale::Get("ja");
+ sk_sp<SkTypeface> serif_ja_typeface = CreateSerifTypeface(ja);
+ if (!serif_ja_typeface)
+ return;
+
+ // When |GenericFamily| set to |kSerifFamily|, it should find the
+ // locale-specific serif font.
+ FontDescription font_description;
+ font_description.SetGenericFamily(FontDescription::kSerifFamily);
+ font_description.SetLocale(ja);
+ FontCache* font_cache = FontCache::GetFontCache();
+ ASSERT_TRUE(font_cache);
+ const UChar32 kTestChar = 0x4E00; // U+4E00 CJK UNIFIED IDEOGRAPH-4E00
+ scoped_refptr<SimpleFontData> font_data =
+ font_cache->FallbackFontForCharacter(font_description, kTestChar,
+ nullptr);
+ EXPECT_TRUE(font_data);
+ EXPECT_EQ(serif_ja_typeface.get(), font_data->PlatformData().Typeface());
+}
+
+TEST_F(FontCacheAndroidTest, LocaleSpecificTypeface) {
+ // Test is valid only if the system has a locale-specific `serif`.
+ const LayoutLocale* ja = LayoutLocale::Get("ja");
+ sk_sp<SkTypeface> serif_ja_typeface = CreateSerifTypeface(ja);
+ if (!serif_ja_typeface)
+ return;
+
+ // If the system has one, it must be different from the default font.
+ FontDescription standard_ja_description;
+ standard_ja_description.SetLocale(ja);
+ standard_ja_description.SetGenericFamily(FontDescription::kStandardFamily);
+ std::string name;
+ FontCache* font_cache = FontCache::GetFontCache();
+ sk_sp<SkTypeface> standard_ja_typeface = font_cache->CreateTypeface(
+ standard_ja_description, FontFaceCreationParams(), name);
+ EXPECT_NE(serif_ja_typeface.get(), standard_ja_typeface.get());
+}
+
+TEST(FontCacheAndroid, GenericFamilyNameForScript) {
FontDescription english;
english.SetLocale(LayoutLocale::Get("en"));
FontDescription chinese;
chinese.SetLocale(LayoutLocale::Get("zh"));
font_family_names::Init();
-
// For non-CJK, getGenericFamilyNameForScript should return the given
// familyName.
EXPECT_EQ(font_family_names::kWebkitStandard,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc
index 5e96ce4ac92..ae61e2d10cb 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc
@@ -6,6 +6,7 @@
#include "base/files/file.h"
#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
#include "base/timer/elapsed_timer.h"
#include "third_party/blink/public/common/font_unique_name_lookup/icu_fold_case_util.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
@@ -134,6 +135,7 @@ sk_sp<SkTypeface> FontUniqueNameLookupAndroid::MatchUniqueNameFromFirmwareFonts(
bool FontUniqueNameLookupAndroid::RequestedNameInQueryableFonts(
const String& font_unique_name) {
if (!queryable_fonts_) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Android.FontLookup.Blink.GetTableLatency");
Vector<String> retrieved_fonts;
android_font_lookup_service_->GetUniqueNameLookupTable(&retrieved_fonts);
queryable_fonts_ = std::move(retrieved_fonts);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h
index fae67b31126..fbc5d729d86 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h
@@ -23,6 +23,9 @@ namespace blink {
class FontUniqueNameLookupAndroid : public FontUniqueNameLookup {
public:
FontUniqueNameLookupAndroid() = default;
+ FontUniqueNameLookupAndroid(const FontUniqueNameLookupAndroid&) = delete;
+ FontUniqueNameLookupAndroid& operator=(const FontUniqueNameLookupAndroid&) =
+ delete;
~FontUniqueNameLookupAndroid() override;
bool IsFontUniqueNameLookupReadyForSyncLookup() override;
@@ -51,8 +54,6 @@ class FontUniqueNameLookupAndroid : public FontUniqueNameLookup {
WTF::Deque<NotifyFontUniqueNameLookupReady> pending_callbacks_;
absl::optional<bool> sync_available_;
absl::optional<Vector<String>> queryable_fonts_;
-
- DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupAndroid);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/character_range.h b/chromium/third_party/blink/renderer/platform/fonts/character_range.h
index 04dedacdb99..f70e3bb43c0 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/character_range.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/character_range.h
@@ -10,7 +10,14 @@ namespace blink {
struct CharacterRange {
CharacterRange(float from, float to, float ascent, float descent)
: start(from), end(to), ascent(ascent), descent(descent) {
- DCHECK_LE(start, end);
+#if DCHECK_IS_ON()
+ if (isnan(start)) {
+ // start/end can saturate in tests, but not a real world case.
+ DCHECK(isnan(end));
+ } else {
+ DCHECK_LE(start, end);
+ }
+#endif
}
float Width() const { return end - start; }
diff --git a/chromium/third_party/blink/renderer/platform/fonts/custom_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/custom_font_data.h
index cd2bc766efe..3e5fd456c60 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/custom_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/custom_font_data.h
@@ -40,6 +40,7 @@ class PLATFORM_EXPORT CustomFontData : public RefCounted<CustomFontData> {
virtual bool IsLoadingFallback() const { return false; }
virtual bool ShouldSkipDrawing() const { return false; }
virtual void ClearFontFaceSource() {}
+ virtual bool IsPendingDataUrl() const { return false; }
protected:
CustomFontData() = default;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.cc b/chromium/third_party/blink/renderer/platform/fonts/font.cc
index 00e0cdb85f3..0281384eb2a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.cc
@@ -535,7 +535,7 @@ void Font::ReportEmojiSegmentGlyphCoverage(unsigned num_clusters,
void Font::WillUseFontData(const String& text) const {
const FontFamily& family = GetFontDescription().Family();
if (font_fallback_list_ && font_fallback_list_->GetFontSelector() &&
- !family.FamilyIsEmpty())
+ !family.Family().IsEmpty())
font_fallback_list_->GetFontSelector()->WillUseFontData(
GetFontDescription(), family.Family(), text);
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.h b/chromium/third_party/blink/renderer/platform/fonts/font.h
index 4b62b555f6a..b6000b08341 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.h
@@ -41,7 +41,7 @@
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-// To avoid conflicts with the CreateWindow macro from the Windows SDK...
+// To avoid conflicts with the DrawText macro from the Windows SDK...
#undef DrawText
namespace cc {
@@ -249,12 +249,6 @@ class PLATFORM_EXPORT Font {
return EnsureFontFallbackList()->ShouldSkipDrawing();
}
- // Returns true if any of the matched @font-face rules has set a
- // advance-override value.
- bool HasAdvanceOverride() const {
- return font_fallback_list_ && font_fallback_list_->HasAdvanceOverride();
- }
-
private:
// TODO(xiaochengh): The function not only initializes null FontFallbackList,
// but also syncs invalid FontFallbackList. Rename it for better readability.
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_baseline.h b/chromium/third_party/blink/renderer/platform/fonts/font_baseline.h
index 8658a15486b..5d2778fb079 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_baseline.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_baseline.h
@@ -28,7 +28,31 @@
namespace blink {
-enum FontBaseline { kAlphabeticBaseline, kIdeographicBaseline };
+enum FontBaseline {
+ // https://drafts.csswg.org/css-inline/#alphabetic-baseline
+ kAlphabeticBaseline,
+
+ // https://drafts.csswg.org/css-inline/#central-baseline
+ kCentralBaseline,
+
+ // https://drafts.csswg.org/css-inline/#text-under-baseline
+ kTextUnderBaseline,
+
+ // https://drafts.csswg.org/css-inline/#ideographic-under-baseline
+ kIdeographicUnderBaseline,
+
+ // https://drafts.csswg.org/css-inline/#x-middle-baseline
+ kXMiddleBaseline,
+
+ // https://drafts.csswg.org/css-inline/#math-baseline
+ kMathBaseline,
+
+ // https://drafts.csswg.org/css-inline/#hanging-baseline
+ kHangingBaseline,
+
+ // https://drafts.csswg.org/css-inline/#text-over-baseline
+ kTextOverBaseline
+};
} // namespace blink
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 fa1829a7cc4..3e8ced65219 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -35,6 +35,7 @@
#include "base/debug/alias.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
+#include "base/timer/elapsed_timer.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -47,6 +48,7 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_map.h"
#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
+#include "third_party/blink/renderer/platform/fonts/font_performance.h"
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
#include "third_party/blink/renderer/platform/fonts/font_smoothing_mode.h"
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
@@ -355,8 +357,11 @@ scoped_refptr<SimpleFontData> FontCache::FallbackFontForCharacter(
if (Character::IsPrivateUse(lookup_char) ||
Character::IsNonCharacter(lookup_char))
return nullptr;
- return PlatformFallbackFontForCharacter(
+ base::ElapsedTimer timer;
+ scoped_refptr<SimpleFontData> result = PlatformFallbackFontForCharacter(
description, lookup_char, font_data_to_substitute, fallback_priority);
+ FontPerformance::AddSystemFallbackFontTime(timer.Elapsed());
+ return result;
}
void FontCache::ReleaseFontData(const SimpleFontData* font_data) {
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 01f6d8545cc..9432f4934b4 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
@@ -53,8 +53,8 @@
#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/std_lib_extras.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/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -250,6 +250,13 @@ class PLATFORM_EXPORT FontCache {
static AtomicString GetGenericFamilyNameForScript(
const AtomicString& family_name,
const FontDescription&);
+ // Locale-specific families can use different |SkTypeface| for a family name
+ // if locale is different.
+ static const char* GetLocaleSpecificFamilyName(
+ const AtomicString& family_name);
+ sk_sp<SkTypeface> CreateLocaleSpecificTypeface(
+ const FontDescription& font_description,
+ const char* locale_family_name);
#endif // defined(OS_ANDROID)
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
@@ -273,6 +280,8 @@ class PLATFORM_EXPORT FontCache {
FontFallbackMap& GetFontFallbackMap();
+ FontCache(const FontCache&) = delete;
+ FontCache& operator=(const FontCache&) = delete;
~FontCache() = default;
private:
@@ -334,6 +343,7 @@ class PLATFORM_EXPORT FontCache {
static AtomicString GetFamilyNameForCharacter(SkFontMgr*,
UChar32,
const FontDescription&,
+ const char* family_name,
FontFallbackPriority);
#endif // defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
@@ -402,8 +412,7 @@ class PLATFORM_EXPORT FontCache {
friend class SimpleFontData; // For fontDataFromFontPlatformData
friend class FontFallbackList;
-
- DISALLOW_COPY_AND_ASSIGN(FontCache);
+ FRIEND_TEST_ALL_PREFIXES(FontCacheAndroidTest, LocaleSpecificTypeface);
};
class PLATFORM_EXPORT FontCachePurgePreventer {
@@ -411,14 +420,24 @@ class PLATFORM_EXPORT FontCachePurgePreventer {
public:
FontCachePurgePreventer() { FontCache::GetFontCache()->DisablePurging(); }
+ FontCachePurgePreventer(const FontCachePurgePreventer&) = delete;
+ FontCachePurgePreventer& operator=(const FontCachePurgePreventer&) = delete;
~FontCachePurgePreventer() { FontCache::GetFontCache()->EnablePurging(); }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FontCachePurgePreventer);
};
AtomicString ToAtomicString(const SkString&);
+#if defined(OS_ANDROID)
+// static
+inline const char* FontCache::GetLocaleSpecificFamilyName(
+ const AtomicString& family_name) {
+ // Only `serif` has `fallbackFor` according to the current `fonts.xml`.
+ if (family_name == font_family_names::kWebkitSerif)
+ return "serif";
+ return nullptr;
+}
+#endif
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_H_
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 a860a0ad051..fcf08468e73 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
@@ -33,6 +33,7 @@
#include <limits>
+#include "build/build_config.h"
#include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
#include "third_party/blink/renderer/platform/fonts/opentype/font_settings.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -51,12 +52,7 @@ struct FontCacheKey {
DISALLOW_NEW();
public:
- FontCacheKey()
- : creation_params_(),
- font_size_(0),
- options_(0),
- device_scale_factor_(0),
- is_unique_match_(false) {}
+ FontCacheKey() = default;
FontCacheKey(FontFaceCreationParams creation_params,
float font_size,
unsigned options,
@@ -83,12 +79,16 @@ struct FontCacheKey {
// Convert from float with 3 digit precision before hashing.
unsigned device_scale_factor_hash = device_scale_factor_ * 1000;
unsigned hash_codes[6] = {
- creation_params_.GetHash(),
- font_size_,
- options_,
- device_scale_factor_hash,
- variation_settings_ ? variation_settings_->GetHash() : 0,
- is_unique_match_};
+ creation_params_.GetHash(),
+ font_size_,
+ options_,
+ device_scale_factor_hash,
+#if defined(OS_ANDROID)
+ (locale_.IsEmpty() ? 0 : AtomicStringHash::GetHash(locale_)) ^
+#endif // defined(OS_ANDROID)
+ (variation_settings_ ? variation_settings_->GetHash() : 0),
+ is_unique_match_
+ };
return StringHasher::HashMemory<sizeof(hash_codes)>(hash_codes);
}
@@ -100,6 +100,9 @@ struct FontCacheKey {
return creation_params_ == other.creation_params_ &&
font_size_ == other.font_size_ && options_ == other.options_ &&
device_scale_factor_ == other.device_scale_factor_ &&
+#if defined(OS_ANDROID)
+ locale_ == other.locale_ &&
+#endif // defined(OS_ANDROID)
variation_settings_equal &&
is_unique_match_ == other.is_unique_match_;
}
@@ -112,18 +115,26 @@ struct FontCacheKey {
void ClearFontSize() { font_size_ = 0; }
- private:
+#if defined(OS_ANDROID)
+ // Set the locale if the font is locale-specific. This allows different
+ // |FontPlatformData| instances for each locale.
+ void SetLocale(const AtomicString& locale) { locale_ = locale.LowerASCII(); }
+#endif // defined(OS_ANDROID)
+ private:
FontFaceCreationParams creation_params_;
- unsigned font_size_;
- unsigned options_;
+ unsigned font_size_ = 0;
+ unsigned options_ = 0;
// 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_;
+ float device_scale_factor_ = 0;
+#if defined(OS_ANDROID)
+ AtomicString locale_;
+#endif // defined(OS_ANDROID)
scoped_refptr<FontVariationSettings> variation_settings_;
- bool is_unique_match_;
+ bool is_unique_match_ = false;
};
struct FontCacheKeyHash {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h
index 6bd0fb9f878..36ebaf0ecbd 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_MEMORY_DUMP_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_MEMORY_DUMP_PROVIDER_H_
-#include "base/macros.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -19,6 +18,9 @@ class PLATFORM_EXPORT FontCacheMemoryDumpProvider final
public:
static FontCacheMemoryDumpProvider* Instance();
+ FontCacheMemoryDumpProvider(const FontCacheMemoryDumpProvider&) = delete;
+ FontCacheMemoryDumpProvider& operator=(const FontCacheMemoryDumpProvider&) =
+ delete;
~FontCacheMemoryDumpProvider() override = default;
// base::trace_event::MemoryDumpProvider implementation.
@@ -27,8 +29,6 @@ class PLATFORM_EXPORT FontCacheMemoryDumpProvider final
private:
FontCacheMemoryDumpProvider() = default;
-
- DISALLOW_COPY_AND_ASSIGN(FontCacheMemoryDumpProvider);
};
} // namespace blink
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 8eaefc6d110..9832dc4ccca 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
@@ -125,7 +125,8 @@ TEST(FontCache, getLargerThanMaxUnsignedFont) {
FontDescription font_description;
font_description.SetGenericFamily(FontDescription::kStandardFamily);
- font_description.SetComputedSize(std::numeric_limits<unsigned>::max() + 1.f);
+ font_description.SetComputedSize(
+ static_cast<float>(std::numeric_limits<unsigned>::max()) + 1.f);
FontFaceCreationParams creation_params;
scoped_refptr<blink::SimpleFontData> font_data =
font_cache->GetFontData(font_description, AtomicString());
@@ -144,4 +145,20 @@ TEST(FontCache, systemFont) {
}
#endif
+#if defined(OS_ANDROID)
+TEST(FontCache, Locale) {
+ FontCacheKey key1(FontFaceCreationParams(), /* font_size */ 16,
+ /* options */ 0, /* device_scale_factor */ 1.0f,
+ /* variation_settings */ nullptr,
+ /* is_unique_match */ false);
+ FontCacheKey key2 = key1;
+ EXPECT_EQ(key1.GetHash(), key2.GetHash());
+ EXPECT_EQ(key1, key2);
+
+ key2.SetLocale("ja");
+ EXPECT_NE(key1.GetHash(), key2.GetHash());
+ EXPECT_NE(key1, key2);
+}
+#endif // defined(OS_ANDROID)
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc b/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
index c18c2b9fdf7..c00c904754a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
@@ -77,6 +77,8 @@ FontCustomPlatformData::FontCustomPlatformData(sk_sp<SkTypeface> typeface,
FontCustomPlatformData::~FontCustomPlatformData() = default;
+// TODO(crbug.com/1205794): Optical sizing should use specified size, instead of
+// zoomed size.
FontPlatformData FontCustomPlatformData::GetFontPlatformData(
float size,
bool bold,
@@ -157,7 +159,8 @@ FontPlatformData FontCustomPlatformData::GetFontPlatformData(
}
SkFontArguments font_args;
- font_args.setVariationDesignPosition({variation.data(), variation.size()});
+ font_args.setVariationDesignPosition(
+ {variation.data(), static_cast<int>(variation.size())});
sk_sp<SkTypeface> sk_variation_font(base_typeface_->makeClone(font_args));
if (sk_variation_font) {
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 5c7df68523d..9a7617ecee5 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
@@ -32,7 +32,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CUSTOM_PLATFORM_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CUSTOM_PLATFORM_DATA_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/fonts/font_optical_sizing.h"
#include "third_party/blink/renderer/platform/fonts/font_orientation.h"
#include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
@@ -58,6 +57,8 @@ class PLATFORM_EXPORT FontCustomPlatformData
public:
static scoped_refptr<FontCustomPlatformData> Create(SharedBuffer*,
String& ots_parse_message);
+ FontCustomPlatformData(const FontCustomPlatformData&) = delete;
+ FontCustomPlatformData& operator=(const FontCustomPlatformData&) = delete;
~FontCustomPlatformData();
FontPlatformData GetFontPlatformData(
@@ -86,8 +87,6 @@ class PLATFORM_EXPORT FontCustomPlatformData
mutable bool may_be_icon_font_computed_ = false;
mutable bool may_be_icon_font_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(FontCustomPlatformData);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_data.h b/chromium/third_party/blink/renderer/platform/fonts/font_data.h
index 56e0097a693..f6f1258a0ca 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_data.h
@@ -26,13 +26,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_DATA_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/wtf/allocator/allocator.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/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -41,6 +40,8 @@ class SimpleFontData;
class PLATFORM_EXPORT FontData : public RefCounted<FontData> {
public:
FontData() = default;
+ FontData(const FontData&) = delete;
+ FontData& operator=(const FontData&) = delete;
virtual ~FontData();
@@ -52,10 +53,6 @@ class PLATFORM_EXPORT FontData : public RefCounted<FontData> {
virtual bool IsLoadingFallback() const = 0;
virtual bool IsSegmented() const = 0;
virtual bool ShouldSkipDrawing() const = 0;
- virtual bool HasAdvanceOverride() const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FontData);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.h b/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.h
index f5d5604b9c6..5c77cc0a48c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.h
@@ -72,6 +72,8 @@ class FontDataCache {
public:
FontDataCache() = default;
+ FontDataCache(const FontDataCache&) = delete;
+ FontDataCache& operator=(const FontDataCache&) = delete;
scoped_refptr<SimpleFontData> Get(const FontPlatformData*,
ShouldRetain = kRetain,
@@ -92,8 +94,6 @@ class FontDataCache {
Cache;
Cache cache_;
LinkedHashSet<scoped_refptr<SimpleFontData>> inactive_font_data_;
-
- DISALLOW_COPY_AND_ASSIGN(FontDataCache);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h b/chromium/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h
index bd576bc7002..3a861d88ddc 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h
@@ -64,6 +64,10 @@ class PLATFORM_EXPORT FontDataForRangeSet
return font_data_ && font_data_->IsLoadingFallback();
}
+ bool IsPendingDataUrlCustomFont() const {
+ return font_data_ && font_data_->IsPendingDataUrlCustomFont();
+ }
+
protected:
scoped_refptr<SimpleFontData> font_data_;
scoped_refptr<UnicodeRangeSet> range_set_;
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 781b8c14c09..98f86c9808c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -38,7 +38,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#endif
@@ -247,8 +247,7 @@ FontDescription FontDescription::SizeAdjustedFontDescription(
FontCacheKey FontDescription::CacheKey(
const FontFaceCreationParams& creation_params,
- bool is_unique_match,
- const FontSelectionRequest& font_selection_request) const {
+ bool is_unique_match) const {
unsigned options =
static_cast<unsigned>(fields_.font_optical_sizing_) << 7 | // bit 8
static_cast<unsigned>(fields_.synthetic_italic_) << 6 | // bit 7
@@ -266,6 +265,12 @@ FontCacheKey FontDescription::CacheKey(
options | font_selection_request_.GetHash() << 9,
device_scale_factor_for_key, variation_settings_,
is_unique_match);
+#if defined(OS_ANDROID)
+ if (const LayoutLocale* locale = Locale()) {
+ if (FontCache::GetLocaleSpecificFamilyName(creation_params.Family()))
+ cache_key.SetLocale(locale->LocaleForSkFontMgr());
+ }
+#endif // defined(OS_ANDROID)
return cache_key;
}
@@ -383,7 +388,7 @@ unsigned FontDescription::GetHash() const {
unsigned hash = StyleHashWithoutFamilyList();
for (const FontFamily* family = &family_list_; family;
family = family->Next()) {
- if (!family->Family().length())
+ if (family->Family().IsEmpty())
continue;
WTF::AddIntToHash(hash, WTF::AtomicStringHash::GetHash(family->Family()));
}
@@ -585,6 +590,26 @@ String FontDescription::ToString(FontVariantCaps variant) {
return "Unknown";
}
+String FontDescription::ToStringForIdl(FontVariantCaps variant) {
+ switch (variant) {
+ case FontVariantCaps::kCapsNormal:
+ return "normal";
+ case FontVariantCaps::kSmallCaps:
+ return "small-caps";
+ case FontVariantCaps::kAllSmallCaps:
+ return "all-small-caps";
+ case FontVariantCaps::kPetiteCaps:
+ return "petite-caps";
+ case FontVariantCaps::kAllPetiteCaps:
+ return "all-petite-caps";
+ case FontVariantCaps::kUnicase:
+ return "unicase";
+ case FontVariantCaps::kTitlingCaps:
+ return "titling-caps";
+ }
+ return "Unknown";
+}
+
String FontDescription::VariantLigatures::ToString() const {
return String::Format(
"common=%s, discretionary=%s, historical=%s, contextual=%s",
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 329ac05de39..bee82359953 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
@@ -95,6 +95,7 @@ class PLATFORM_EXPORT FontDescription {
kTitlingCaps
};
static String ToString(FontVariantCaps);
+ static String ToStringForIdl(FontVariantCaps);
FontDescription();
FontDescription(const FontDescription&);
@@ -281,10 +282,8 @@ class PLATFORM_EXPORT FontDescription {
float EffectiveFontSize()
const; // Returns either the computedSize or the computedPixelSize
- FontCacheKey CacheKey(
- const FontFaceCreationParams&,
- bool is_unique_match,
- const FontSelectionRequest& = FontSelectionRequest()) const;
+ FontCacheKey CacheKey(const FontFaceCreationParams&,
+ bool is_unique_match) const;
void SetFamily(const FontFamily& family) { family_list_ = family; }
void SetComputedSize(float s) { computed_size_ = clampTo<float>(s); }
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc
index a2677f2b847..7ad030c998b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc
@@ -25,7 +25,7 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_face_creation_params.h b/chromium/third_party/blink/renderer/platform/fonts/font_face_creation_params.h
index 084db9d6d8a..3956e3b3648 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_face_creation_params.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_face_creation_params.h
@@ -34,7 +34,7 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
namespace blink {
@@ -81,7 +81,7 @@ class FontFaceCreationParams {
ttc_index_(ttc_index) {}
FontFaceCreationType CreationType() const { return creation_type_; }
- AtomicString Family() const {
+ const AtomicString& Family() const {
DCHECK_EQ(creation_type_, kCreateFontByFamily);
return family_;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
index cd01d8ea627..470df1cb9dc 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
@@ -40,7 +40,10 @@ bool FontFallbackIterator::RangeSetContributesForHint(
// If it's a pending custom font, we need to make sure it can render any
// new characters, otherwise we may trigger a redundant load. In other
// cases (already loaded or not a custom font), we can use it right away.
+ // Loading data url fonts doesn't incur extra network cost, so we always
+ // load them.
if (!segmented_face->IsPendingCustomFont() ||
+ segmented_face->IsPendingDataUrlCustomFont() ||
!AlreadyLoadingRangeForHintChar(*it))
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
index 91bfccd2be5..b1b3e8071e1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.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/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
index a759bfdc53d..5b836e51d82 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/fonts/font_fallback_list.h"
+#include "base/timer/elapsed_timer.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/fonts/alternate_font_family.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
@@ -35,6 +36,7 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_map.h"
#include "third_party/blink/renderer/platform/fonts/font_family.h"
+#include "third_party/blink/renderer/platform/fonts/font_performance.h"
#include "third_party/blink/renderer/platform/fonts/segmented_font_data.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
@@ -93,6 +95,15 @@ bool FontFallbackList::ShouldSkipDrawing() const {
const SimpleFontData* FontFallbackList::DeterminePrimarySimpleFontData(
const FontDescription& font_description) {
+ base::ElapsedTimer timer;
+ const SimpleFontData* result =
+ DeterminePrimarySimpleFontDataCore(font_description);
+ FontPerformance::AddPrimaryFontTime(timer.Elapsed());
+ return result;
+}
+
+const SimpleFontData* FontFallbackList::DeterminePrimarySimpleFontDataCore(
+ const FontDescription& font_description) {
bool should_load_custom_font = true;
for (unsigned font_index = 0;; ++font_index) {
@@ -151,7 +162,7 @@ scoped_refptr<FontData> FontFallbackList::GetFontData(
for (; curr_family; curr_family = curr_family->Next()) {
family_index_++;
- if (curr_family->Family().length()) {
+ if (!curr_family->Family().IsEmpty()) {
scoped_refptr<FontData> result;
if (GetFontSelector()) {
result = GetFontSelector()->GetFontData(font_description,
@@ -203,7 +214,7 @@ FallbackListCompositeKey FontFallbackList::CompositeKey(
FallbackListCompositeKey key(font_description);
const FontFamily* current_family = &font_description.Family();
while (current_family) {
- if (current_family->Family().length()) {
+ if (!current_family->Family().IsEmpty()) {
FontFaceCreationParams params(
AdjustFamilyNameToAvoidUnsupportedFonts(current_family->Family()));
scoped_refptr<FontData> result;
@@ -258,8 +269,6 @@ const FontData* FontFallbackList::FontDataAt(
has_loading_fallback_ = true;
if (result->IsCustomFont())
has_custom_font_ = true;
- if (result->HasAdvanceOverride())
- has_advance_override_ = true;
}
return result.get();
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h
index 91a444c35f3..d373cf83754 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h
@@ -51,6 +51,8 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
return base::AdoptRef(new FontFallbackList(font_fallback_map));
}
+ FontFallbackList(const FontFallbackList&) = delete;
+ FontFallbackList& operator=(const FontFallbackList&) = delete;
~FontFallbackList();
// Returns whether the cached data is valid. We can use a FontFallbackList
@@ -114,6 +116,8 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
scoped_refptr<FontData> GetFontData(const FontDescription&);
const SimpleFontData* DeterminePrimarySimpleFontData(const FontDescription&);
+ const SimpleFontData* DeterminePrimarySimpleFontDataCore(
+ const FontDescription&);
FallbackListCompositeKey CompositeKey(const FontDescription&) const;
@@ -133,8 +137,6 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
bool is_invalid_ : 1;
base::WeakPtr<ShapeCache> shape_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(FontFallbackList);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_family.h b/chromium/third_party/blink/renderer/platform/fonts/font_family.h
index 7b26410ce0b..fa69d30313d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_family.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_family.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_FAMILY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_FAMILY_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/wtf/ref_counted.h"
@@ -45,7 +44,6 @@ class PLATFORM_EXPORT FontFamily {
void SetFamily(const AtomicString& family) { family_ = family; }
const AtomicString& Family() const { return family_; }
- bool FamilyIsEmpty() const { return family_.IsEmpty(); }
const FontFamily* Next() const;
@@ -66,14 +64,15 @@ class PLATFORM_EXPORT SharedFontFamily : public FontFamily,
public RefCounted<SharedFontFamily> {
USING_FAST_MALLOC(SharedFontFamily);
public:
+ SharedFontFamily(const SharedFontFamily&) = delete;
+ SharedFontFamily& operator=(const SharedFontFamily&) = delete;
+
static scoped_refptr<SharedFontFamily> Create() {
return base::AdoptRef(new SharedFontFamily);
}
private:
SharedFontFamily() = default;
-
- DISALLOW_COPY_AND_ASSIGN(SharedFontFamily);
};
PLATFORM_EXPORT bool operator==(const FontFamily&, const FontFamily&);
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 e86eb7063d6..62a4eb0f239 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
@@ -29,6 +29,9 @@ class PLATFORM_EXPORT FontGlobalContext {
public:
static FontGlobalContext* Get(CreateIfNeeded = kCreate);
+ FontGlobalContext(const FontGlobalContext&) = delete;
+ FontGlobalContext& operator=(const FontGlobalContext&) = delete;
+
static inline FontCache* GetFontCache(CreateIfNeeded create = kCreate) {
FontGlobalContext* context = Get(create);
return context ? &context->font_cache_ : nullptr;
@@ -79,8 +82,6 @@ class PLATFORM_EXPORT FontGlobalContext {
std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
WTF::LruCache<SkFontID, IdentifiableToken> typeface_digest_cache_;
WTF::LruCache<SkFontID, IdentifiableToken> postscript_name_digest_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(FontGlobalContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc b/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
index 32e74cf0ee3..bc2a3eb5a98 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
@@ -291,9 +291,9 @@ void FontMatchingMetrics::PublishIdentifiabilityMetrics() {
for (const auto& surface_entry : hash_maps_with_corresponding_surface_types) {
TokenToTokenHashMap* hash_map = surface_entry.first;
- const IdentifiableSurface::Type& surface_type = surface_entry.second;
- for (const auto& individual_lookup : *hash_map) {
- if (IdentifiabilityStudySettings::Get()->ShouldSample(surface_type)) {
+ const IdentifiableSurface::Type surface_type = surface_entry.second;
+ if (IdentifiabilityStudySettings::Get()->ShouldSample(surface_type)) {
+ for (const auto& individual_lookup : *hash_map) {
builder.Set(IdentifiableSurface::FromTypeAndToken(
surface_type, individual_lookup.key.token),
individual_lookup.value);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc
index e430b1175c7..2ef3e4819b4 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc
@@ -149,4 +149,70 @@ void FontMetrics::AscentDescentWithHacks(
ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
#endif
}
+
+float FontMetrics::FloatAscentInternal(FontBaseline baseline_type) const {
+ switch (baseline_type) {
+ case kAlphabeticBaseline:
+ NOTREACHED();
+ return float_ascent_;
+ case kCentralBaseline:
+ return FloatHeight() / 2;
+
+ // The following computations are based on 'dominant-baseline' support in
+ // the legacy SVG <text>.
+
+ case kTextUnderBaseline:
+ return FloatHeight();
+ case kIdeographicUnderBaseline:
+ // TODO(layout-dev): Should refer to 'ideo' in OpenType.
+ return FloatHeight();
+ case kXMiddleBaseline:
+ return float_ascent_ - XHeight() / 2;
+ case kMathBaseline:
+ // TODO(layout-dev): Should refer to 'math' in OpenType or 'bsln' value 4
+ // in TrueType AAT.
+ return float_ascent_ * 0.5f;
+ case kHangingBaseline:
+ // TODO(layout-dev): Should refer to 'hang' in OpenType or 'bsln' value 3
+ // in TrueType AAT.
+ return float_ascent_ * 0.2f;
+ case kTextOverBaseline:
+ return 0;
+ }
+ NOTREACHED();
+ return float_ascent_;
+}
+
+int FontMetrics::IntAscentInternal(FontBaseline baseline_type) const {
+ switch (baseline_type) {
+ case kAlphabeticBaseline:
+ NOTREACHED();
+ return int_ascent_;
+ case kCentralBaseline:
+ return Height() - Height() / 2;
+
+ // The following computations are based on 'dominant-baseline' support in
+ // the legacy SVG <text>.
+
+ case kTextUnderBaseline:
+ return Height();
+ case kIdeographicUnderBaseline:
+ // TODO(layout-dev): Should refer to 'ideo' in OpenType.
+ return Height();
+ case kXMiddleBaseline:
+ return int_ascent_ - static_cast<int>(XHeight() / 2);
+ case kMathBaseline:
+ // TODO(layout-dev): Should refer to 'math' in OpenType or 'bsln' value 4
+ // in TrueType AAT.
+ return int_ascent_ / 2;
+ case kHangingBaseline:
+ // TODO(layout-dev): Should refer to 'hang' in OpenType or 'bsln' value 3
+ // in TrueType AAT.
+ return int_ascent_ * 2 / 10;
+ case kTextOverBaseline:
+ return 0;
+ }
+ NOTREACHED();
+ return int_ascent_;
+}
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h
index c6472c531c8..f2506e84ac4 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h
@@ -41,14 +41,14 @@ class FontMetrics {
public:
FontMetrics()
: units_per_em_(kGDefaultUnitsPerEm),
- ascent_(0),
- descent_(0),
+ float_ascent_(0),
+ float_descent_(0),
line_gap_(0),
line_spacing_(0),
x_height_(0),
zero_width_(0),
- ascent_int_(0),
- descent_int_(0),
+ int_ascent_(0),
+ int_descent_(0),
has_x_height_(false),
has_zero_width_(false) {}
@@ -57,29 +57,27 @@ class FontMetrics {
float FloatAscent(FontBaseline baseline_type = kAlphabeticBaseline) const {
if (baseline_type == kAlphabeticBaseline)
- return ascent_;
- return FloatHeight() / 2;
+ return float_ascent_;
+ return FloatAscentInternal(baseline_type);
}
void SetAscent(float ascent) {
- ascent_ = ascent;
- ascent_int_ = static_cast<int>(lroundf(ascent));
+ float_ascent_ = ascent;
+ int_ascent_ = static_cast<int>(lroundf(ascent));
}
float FloatDescent(FontBaseline baseline_type = kAlphabeticBaseline) const {
if (baseline_type == kAlphabeticBaseline)
- return descent_;
- return FloatHeight() / 2;
+ return float_descent_;
+ return FloatHeight() - FloatAscentInternal(baseline_type);
}
void SetDescent(float descent) {
- descent_ = descent;
- descent_int_ = static_cast<int>(lroundf(descent));
+ float_descent_ = descent;
+ int_descent_ = static_cast<int>(lroundf(descent));
}
- float FloatHeight(FontBaseline baseline_type = kAlphabeticBaseline) const {
- return FloatAscent() + FloatDescent();
- }
+ float FloatHeight() const { return float_ascent_ + float_descent_; }
float FloatLineGap() const { return line_gap_; }
void SetLineGap(float line_gap) { line_gap_ = line_gap; }
@@ -99,19 +97,17 @@ class FontMetrics {
// Integer variants of certain metrics, used for HTML rendering.
int Ascent(FontBaseline baseline_type = kAlphabeticBaseline) const {
if (baseline_type == kAlphabeticBaseline)
- return ascent_int_;
- return Height() - Height() / 2;
+ return int_ascent_;
+ return IntAscentInternal(baseline_type);
}
int Descent(FontBaseline baseline_type = kAlphabeticBaseline) const {
if (baseline_type == kAlphabeticBaseline)
- return descent_int_;
- return Height() / 2;
+ return int_descent_;
+ return Height() - IntAscentInternal(baseline_type);
}
- int Height(FontBaseline baseline_type = kAlphabeticBaseline) const {
- return Ascent() + Descent();
- }
+ int Height() const { return int_ascent_ + int_descent_; }
int LineGap() const { return static_cast<int>(lroundf(line_gap_)); }
int LineSpacing() const { return static_cast<int>(lroundf(line_spacing_)); }
@@ -133,14 +129,16 @@ class FontMetrics {
return LayoutUnit::FromFloatRound(line_spacing_);
}
+ FontHeight GetFloatFontHeight(FontBaseline baseline_type) const {
+ return FontHeight(FixedAscent(baseline_type), FixedDescent(baseline_type));
+ }
+
FontHeight GetFontHeight(
FontBaseline baseline_type = kAlphabeticBaseline) const {
// TODO(kojii): In future, we'd like to use LayoutUnit metrics to support
// sub-CSS-pixel layout.
- if (baseline_type == kAlphabeticBaseline)
- return FontHeight(LayoutUnit(ascent_int_), LayoutUnit(descent_int_));
- int height = ascent_int_ + descent_int_;
- return FontHeight(LayoutUnit(height - height / 2), LayoutUnit(height / 2));
+ return FontHeight(LayoutUnit(Ascent(baseline_type)),
+ LayoutUnit(Descent(baseline_type)));
}
bool HasIdenticalAscentDescentAndLineGap(const FontMetrics& other) const {
@@ -193,10 +191,10 @@ class FontMetrics {
void Reset() {
units_per_em_ = kGDefaultUnitsPerEm;
- ascent_ = 0;
- descent_ = 0;
- ascent_int_ = 0;
- descent_int_ = 0;
+ float_ascent_ = 0;
+ float_descent_ = 0;
+ int_ascent_ = 0;
+ int_descent_ = 0;
line_gap_ = 0;
line_spacing_ = 0;
x_height_ = 0;
@@ -205,17 +203,20 @@ class FontMetrics {
underline_position_.reset();
}
+ PLATFORM_EXPORT float FloatAscentInternal(FontBaseline baseline_type) const;
+ PLATFORM_EXPORT int IntAscentInternal(FontBaseline baseline_type) const;
+
unsigned units_per_em_;
- float ascent_;
- float descent_;
+ float float_ascent_;
+ float float_descent_;
float line_gap_;
float line_spacing_;
float x_height_;
float zero_width_;
absl::optional<float> underline_thickness_ = absl::nullopt;
absl::optional<float> underline_position_ = absl::nullopt;
- int ascent_int_;
- int descent_int_;
+ int int_ascent_;
+ int int_descent_;
bool has_x_height_;
bool has_zero_width_;
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_metrics_override.h b/chromium/third_party/blink/renderer/platform/fonts/font_metrics_override.h
index af60137172d..2ae181f2a05 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_metrics_override.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_metrics_override.h
@@ -13,8 +13,6 @@ struct FontMetricsOverride {
absl::optional<float> ascent_override;
absl::optional<float> descent_override;
absl::optional<float> line_gap_override;
- absl::optional<float> advance_override;
- absl::optional<float> advance_override_vertical_upright;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_performance.cc b/chromium/third_party/blink/renderer/platform/fonts/font_performance.cc
new file mode 100644
index 00000000000..b63925079ba
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_performance.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/font_performance.h"
+
+namespace blink {
+
+base::TimeDelta FontPerformance::primary_font_;
+base::TimeDelta FontPerformance::primary_font_in_style_;
+base::TimeDelta FontPerformance::system_fallback_;
+unsigned FontPerformance::in_style_ = 0;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_performance.h b/chromium/third_party/blink/renderer/platform/fonts/font_performance.h
new file mode 100644
index 00000000000..25756aab993
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_performance.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_PERFORMANCE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_PERFORMANCE_H_
+
+#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+
+// This class collects performance data for font-related operations.
+class PLATFORM_EXPORT FontPerformance {
+ public:
+ static void DidReachFirstContentfulPaint() {
+ primary_font_ = base::TimeDelta();
+ primary_font_in_style_ = base::TimeDelta();
+ system_fallback_ = base::TimeDelta();
+ }
+
+ // The aggregated time spent in |DeterminePrimarySimpleFontData|.
+ static base::TimeDelta PrimaryFontTime() {
+ return primary_font_ + primary_font_in_style_;
+ }
+ static const base::TimeDelta& PrimaryFontTimeInStyle() {
+ return primary_font_in_style_;
+ }
+ static void AddPrimaryFontTime(base::TimeDelta time) {
+ if (UNLIKELY(!IsMainThread()))
+ return;
+ if (in_style_)
+ primary_font_in_style_ += time;
+ else
+ primary_font_ += time;
+ }
+
+ // The aggregated time spent in |FallbackFontForCharacter|.
+ static base::TimeDelta SystemFallbackFontTime() { return system_fallback_; }
+ static void AddSystemFallbackFontTime(base::TimeDelta time) {
+ system_fallback_ += time;
+ }
+
+ class StyleScope {
+ public:
+ StyleScope() { ++in_style_; }
+ ~StyleScope() {
+ DCHECK(in_style_);
+ --in_style_;
+ }
+ };
+
+ private:
+ static base::TimeDelta primary_font_;
+ static base::TimeDelta primary_font_in_style_;
+ static base::TimeDelta system_fallback_;
+ static unsigned in_style_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_PERFORMANCE_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selection_algorithm.h b/chromium/third_party/blink/renderer/platform/fonts/font_selection_algorithm.h
index 7a6258506e3..3b3849e0b86 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_selection_algorithm.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_selection_algorithm.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_SELECTION_ALGORITHM_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_SELECTION_ALGORITHM_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h b/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h
index 94fdc48faa5..da261da7ba6 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_SELECTION_TYPES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_SELECTION_TYPES_H_
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
@@ -345,7 +345,7 @@ struct FontSelectionRange {
}
FontSelectionValue clampToRange(FontSelectionValue selection_value) const {
- return base::ClampToRange(selection_value, minimum, maximum);
+ return base::clamp(selection_value, minimum, maximum);
}
FontSelectionValue minimum{FontSelectionValue(1)};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc b/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc
index ea54e9d8c6d..561397b13d1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc
@@ -27,7 +27,7 @@ AtomicString FontSelector::FamilyNameFromSettings(
return FontCache::GetGenericFamilyNameForScript(generic_family_name,
font_description);
}
-#else
+#else // !defined(OS_ANDROID)
UScriptCode script = font_description.GetScript();
if (font_description.GenericFamily() == FontDescription::kStandardFamily)
return settings.Standard(script);
@@ -45,7 +45,7 @@ AtomicString FontSelector::FamilyNameFromSettings(
return settings.Pictograph(script);
if (generic_family_name == font_family_names::kWebkitStandard)
return settings.Standard(script);
-#endif
+#endif // !defined(OS_ANDROID)
return g_empty_atom;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc
index 6fce7e20df8..2fa363a2a4e 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
-#include "base/macros.h"
#if defined(OS_ANDROID)
#include "third_party/blink/public/mojom/font_unique_name_lookup/font_unique_name_lookup.mojom-blink.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h
index 50596d5b4b3..91a5c83d0ba 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_UNIQUE_NAME_LOOKUP_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -34,6 +33,8 @@ class FontUniqueNameLookup {
virtual sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) = 0;
+ FontUniqueNameLookup(const FontUniqueNameLookup&) = delete;
+ FontUniqueNameLookup& operator=(const FontUniqueNameLookup&) = delete;
virtual ~FontUniqueNameLookup() = default;
// Below: Methods for asynchronously retrieving the FontUniqueNameLookup
@@ -62,8 +63,6 @@ class FontUniqueNameLookup {
#if defined(OS_WIN) || defined(OS_ANDROID)
std::unique_ptr<FontTableMatcher> font_table_matcher_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookup);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/glyph_metrics_map.h b/chromium/third_party/blink/renderer/platform/fonts/glyph_metrics_map.h
index d3b908b218e..a93c90c1c85 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/glyph_metrics_map.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/glyph_metrics_map.h
@@ -37,7 +37,6 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
@@ -49,6 +48,8 @@ class GlyphMetricsMap {
public:
GlyphMetricsMap() : filled_primary_page_(false) {}
+ GlyphMetricsMap(const GlyphMetricsMap&) = delete;
+ GlyphMetricsMap& operator=(const GlyphMetricsMap&) = delete;
T MetricsForGlyph(Glyph glyph) {
return LocatePage(glyph / GlyphMetricsPage::kSize)->MetricsForGlyph(glyph);
}
@@ -61,9 +62,10 @@ class GlyphMetricsMap {
private:
class GlyphMetricsPage {
USING_FAST_MALLOC(GlyphMetricsPage);
- DISALLOW_COPY_AND_ASSIGN(GlyphMetricsPage);
public:
+ GlyphMetricsPage(const GlyphMetricsPage&) = delete;
+ GlyphMetricsPage& operator=(const GlyphMetricsPage&) = delete;
static const size_t kSize =
256; // Usually covers Latin-1 in a single page.
GlyphMetricsPage() {}
@@ -95,8 +97,6 @@ class GlyphMetricsMap {
// We optimize for the page that contains glyph indices 0-255.
GlyphMetricsPage primary_page_;
std::unique_ptr<HashMap<int, std::unique_ptr<GlyphMetricsPage>>> pages_;
-
- DISALLOW_COPY_AND_ASSIGN(GlyphMetricsMap);
};
template <>
@@ -119,7 +119,7 @@ GlyphMetricsMap<T>::LocatePageSlowCase(unsigned page_number) {
filled_primary_page_ = true;
} else {
if (pages_) {
- page = pages_->at(page_number);
+ page = pages_->DeprecatedAtOrEmptyValue(page_number);
if (page)
return page;
} else {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc b/chromium/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
index 132f146e332..133a87eb8dd 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
@@ -75,7 +75,7 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
// underlying system for the font family.
if (font_manager_) {
AtomicString family_name = GetFamilyNameForCharacter(
- font_manager_.get(), c, font_description, fallback_priority);
+ font_manager_.get(), c, font_description, nullptr, fallback_priority);
if (family_name.IsEmpty())
return GetLastResortFallbackFont(font_description, kDoNotRetain);
return FontDataFromFontPlatformData(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.h b/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.h
index 0b717f25fa9..e39535ae197 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.h
@@ -12,11 +12,11 @@ namespace blink {
class FontUniqueNameLookupLinux : public FontUniqueNameLookup {
public:
FontUniqueNameLookupLinux() = default;
+ FontUniqueNameLookupLinux(const FontUniqueNameLookupLinux&) = delete;
+ FontUniqueNameLookupLinux& operator=(const FontUniqueNameLookupLinux&) =
+ delete;
~FontUniqueNameLookupLinux() override;
sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupLinux);
};
} // namespace blink
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 fb5629f9596..3c597bc2975 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
@@ -221,7 +221,8 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
![substitute_font.familyName isEqual:@"Apple Color Emoji"];
std::unique_ptr<FontPlatformData> alternate_font = FontPlatformDataFromNSFont(
- substitute_font, platform_data.size(), synthetic_bold,
+ substitute_font, platform_data.size(), font_description.SpecifiedSize(),
+ synthetic_bold,
(traits & NSFontItalicTrait) &&
!(substitute_font_traits & NSFontItalicTrait),
platform_data.Orientation(), font_description.FontOpticalSizing(),
@@ -300,8 +301,9 @@ std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData(
// stored in non-system locations. When loading fails, we do not want to use
// the returned FontPlatformData since it will not have a valid SkTypeface.
std::unique_ptr<FontPlatformData> platform_data = FontPlatformDataFromNSFont(
- platform_font, size, synthetic_bold, synthetic_italic,
- font_description.Orientation(), font_description.FontOpticalSizing(),
+ platform_font, size, font_description.SpecifiedSize(), synthetic_bold,
+ synthetic_italic, font_description.Orientation(),
+ font_description.FontOpticalSizing(),
font_description.VariationSettings());
if (!platform_data || !platform_data->Typeface()) {
return nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
index 2f6a9fde0e7..6c1c1ad116c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
@@ -33,10 +33,10 @@
#import <Foundation/Foundation.h>
#import <math.h>
+#include "base/cxx17_backports.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
-#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#import "third_party/blink/renderer/platform/wtf/hash_set.h"
#import "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
@@ -60,11 +60,11 @@ BOOL AcceptableChoice(NSFontTraitMask desired_traits,
}
BOOL BetterChoice(NSFontTraitMask desired_traits,
- int desired_weight,
+ NSInteger desired_weight,
NSFontTraitMask chosen_traits,
- int chosen_weight,
+ NSInteger chosen_weight,
NSFontTraitMask candidate_traits,
- int candidate_weight) {
+ NSInteger candidate_weight) {
if (!AcceptableChoice(desired_traits, candidate_traits))
return NO;
@@ -89,8 +89,9 @@ BOOL BetterChoice(NSFontTraitMask desired_traits,
return NO;
}
- int chosen_weight_delta_magnitude = abs(chosen_weight - desired_weight);
- int candidate_weight_delta_magnitude = abs(candidate_weight - desired_weight);
+ NSInteger chosen_weight_delta_magnitude = abs(chosen_weight - desired_weight);
+ NSInteger candidate_weight_delta_magnitude =
+ abs(candidate_weight - desired_weight);
// If both are the same distance from the desired weight, prefer the candidate
// if it is further from medium.
@@ -190,7 +191,7 @@ NSFont* MatchNSFontFamily(const AtomicString& desired_family_string,
available_family = desired_family;
}
- int app_kit_font_weight = ToAppKitFontWeight(desired_weight);
+ NSInteger app_kit_font_weight = ToAppKitFontWeight(desired_weight);
if (!available_family) {
// Match by PostScript name.
NSEnumerator* available_fonts =
@@ -225,13 +226,13 @@ NSFont* MatchNSFontFamily(const AtomicString& desired_family_string,
// Found a family, now figure out what weight and traits to use.
BOOL chose_font = false;
- int chosen_weight = 0;
+ NSInteger chosen_weight = 0;
NSFontTraitMask chosen_traits = 0;
NSString* chosen_full_name = 0;
NSArray* fonts = [font_manager availableMembersOfFontFamily:available_family];
- unsigned n = [fonts count];
- unsigned i;
+ NSUInteger n = [fonts count];
+ NSUInteger i;
for (i = 0; i < n; i++) {
NSArray* font_info = fonts[i];
@@ -273,7 +274,7 @@ NSFont* MatchNSFontFamily(const AtomicString& desired_family_string,
NSFontTraitMask actual_traits = 0;
if (desired_traits & NSFontItalicTrait)
actual_traits = [font_manager traitsOfFont:font];
- int actual_weight = [font_manager weightOfFont:font];
+ NSInteger actual_weight = [font_manager weightOfFont:font];
bool synthetic_bold = app_kit_font_weight >= 7 && actual_weight < 7;
bool synthetic_italic = (desired_traits & NSFontItalicTrait) &&
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
index ed3dfa6c4bd..ae1d8d63e0f 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
@@ -53,9 +53,14 @@ bool PLATFORM_EXPORT VariableAxisChangeEffective(SkTypeface* typeface,
SkFourByteTag axis,
float new_value);
+// Creates a FontPlatform object for specified original NSFont and font
+// parameters. size is scaled size, specified size is passed in to control
+// optical sizing and tracking, needed in particular for the San Francisco
+// system font.
std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
NSFont*,
float size,
+ float specified_size,
bool synthetic_bold,
bool synthetic_italic,
FontOrientation,
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 90a09d489d7..384765fcc1f 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
@@ -26,9 +26,9 @@
#import <AppKit/NSFont.h>
#import <AvailabilityMacros.h>
+#include "base/cxx17_backports.h"
#import "base/mac/foundation_util.h"
#import "base/mac/scoped_nsobject.h"
-#include "base/stl_util.h"
#include "third_party/blink/public/platform/mac/web_sandbox_support.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
@@ -165,6 +165,7 @@ static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font,
std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
NSFont* ns_font,
float size,
+ float specified_size,
bool synthetic_bold,
bool synthetic_italic,
FontOrientation orientation,
@@ -218,11 +219,13 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
// settings, special case 'opsz', track the number of axes reconfigured.
bool axes_reconfigured = false;
for (auto& coordinate : coordinates_to_set) {
- // Set 'opsz' to font size but allow having it overridden by
- // font-variation-settings in case it has 'opsz'.
+ // Set 'opsz' to specified size but allow having it overridden by
+ // font-variation-settings in case it has 'opsz'. Do not use font size here,
+ // but specified size in order to account for zoom.
if (coordinate.axis == kOpszTag && optical_sizing == kAutoOpticalSizing) {
- if (VariableAxisChangeEffective(typeface.get(), coordinate.axis, size)) {
- coordinate.value = SkFloatToScalar(size);
+ if (VariableAxisChangeEffective(typeface.get(), coordinate.axis,
+ specified_size)) {
+ coordinate.value = SkFloatToScalar(specified_size);
axes_reconfigured = true;
}
}
@@ -243,7 +246,7 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
}
SkFontArguments::VariationPosition variation_design_position{
- coordinates_to_set.data(), coordinates_to_set.size()};
+ coordinates_to_set.data(), static_cast<int>(coordinates_to_set.size())};
sk_sp<SkTypeface> cloned_typeface(typeface->makeClone(
SkFontArguments().setVariationDesignPosition(variation_design_position)));
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc
index e1710f6bb2a..0caa0dfd75a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc
@@ -51,9 +51,10 @@ FontFormatCheck::COLRVersion determineCOLRVersion(
} // namespace
FontFormatCheck::FontFormatCheck(sk_sp<SkData> sk_data) {
- HbScoped<hb_blob_t> font_blob(hb_blob_create(
- reinterpret_cast<const char*>(sk_data->bytes()), sk_data->size(),
- HB_MEMORY_MODE_READONLY, nullptr, nullptr));
+ HbScoped<hb_blob_t> font_blob(
+ hb_blob_create(reinterpret_cast<const char*>(sk_data->bytes()),
+ base::checked_cast<unsigned>(sk_data->size()),
+ HB_MEMORY_MODE_READONLY, nullptr, nullptr));
HbScoped<hb_face_t> face(hb_face_create(font_blob.get(), 0));
unsigned table_count = 0;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc
index c4f27cad296..3f1ec9d98b7 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc
@@ -19,8 +19,9 @@ uint32_t AtomicStringToFourByteTag(AtomicString tag) {
AtomicString FourByteTagToAtomicString(uint32_t tag) {
constexpr size_t tag_size = 4;
- LChar tag_string[tag_size] = {(tag >> 24) & 0xFF, (tag >> 16) & 0xFF,
- (tag >> 8) & 0xFF, tag & 0xFF};
+ LChar tag_string[tag_size] = {
+ static_cast<LChar>(tag >> 24), static_cast<LChar>(tag >> 16),
+ static_cast<LChar>(tag >> 8), static_cast<LChar>(tag)};
return AtomicString(tag_string, tag_size);
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h
index d5f69315f47..588eda1b3d6 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_FONT_SETTINGS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_FONT_SETTINGS_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/wtf/allocator/allocator.h"
@@ -58,6 +57,9 @@ class FontTagValuePair {
template <typename T>
class FontSettings {
public:
+ FontSettings(const FontSettings&) = delete;
+ FontSettings& operator=(const FontSettings&) = delete;
+
void Append(const T& feature) { list_.push_back(feature); }
wtf_size_t size() const { return list_.size(); }
const T& operator[](wtf_size_t index) const { return list_[index]; }
@@ -102,8 +104,6 @@ class FontSettings {
private:
Vector<T, 0> list_;
-
- DISALLOW_COPY_AND_ASSIGN(FontSettings);
};
using FontFeature = FontTagValuePair<int>;
@@ -112,13 +112,14 @@ using FontVariationAxis = FontTagValuePair<float>;
class PLATFORM_EXPORT FontFeatureSettings
: public FontSettings<FontFeature>,
public RefCounted<FontFeatureSettings> {
- DISALLOW_COPY_AND_ASSIGN(FontFeatureSettings);
-
public:
static scoped_refptr<FontFeatureSettings> Create() {
return base::AdoptRef(new FontFeatureSettings());
}
+ FontFeatureSettings(const FontFeatureSettings&) = delete;
+ FontFeatureSettings& operator=(const FontFeatureSettings&) = delete;
+
private:
FontFeatureSettings() = default;
};
@@ -126,13 +127,14 @@ class PLATFORM_EXPORT FontFeatureSettings
class PLATFORM_EXPORT FontVariationSettings
: public FontSettings<FontVariationAxis>,
public RefCounted<FontVariationSettings> {
- DISALLOW_COPY_AND_ASSIGN(FontVariationSettings);
-
public:
static scoped_refptr<FontVariationSettings> Create() {
return base::AdoptRef(new FontVariationSettings());
}
+ FontVariationSettings(const FontVariationSettings&) = delete;
+ FontVariationSettings& operator=(const FontVariationSettings&) = delete;
+
unsigned GetHash() const;
private:
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 f04b91d087b..d7450d51a2d 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
@@ -6,7 +6,7 @@
*
* ***** END LICENSE BLOCK ***** */
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
#include <hb-ot.h>
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h
index a5d640e176d..19ee94bb2f5 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_STRETCH_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_STRETCH_DATA_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/fonts/glyph.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -30,7 +29,7 @@ class PLATFORM_EXPORT OpenTypeMathStretchData {
bool is_extender;
};
- // https://mathml-refresh.github.io/mathml-core/#the-glyphassembly-table
+ // https://w3c.github.io/mathml-core/#the-glyphassembly-table
struct AssemblyParameters {
float connector_overlap{0};
unsigned repetition_count{0};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc
index 419bde25fb8..26fc4dc4c4f 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc
@@ -229,11 +229,11 @@ OpenTypeMathSupport::GetGlyphPartRecords(
auto converter =
base::BindRepeating([](hb_ot_math_glyph_part_t record)
-> OpenTypeMathStretchData::GlyphPartRecord {
- return {record.glyph,
+ return {static_cast<Glyph>(record.glyph),
HarfBuzzUnitsToFloat(record.start_connector_length),
HarfBuzzUnitsToFloat(record.end_connector_length),
HarfBuzzUnitsToFloat(record.full_advance),
- record.flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER};
+ !!(record.flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)};
});
Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
GetHarfBuzzMathRecord(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
index a8ac60b608c..b8e4fed8699 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
@@ -284,7 +284,8 @@ void OpenTypeVerticalData::GetVerticalTranslationsForGlyphs(
// For Y, try VORG first.
if (use_vorg) {
if (glyph) {
- int16_t vert_origin_yf_unit = vert_origin_y_.at(glyph);
+ int16_t vert_origin_yf_unit =
+ vert_origin_y_.DeprecatedAtOrEmptyValue(glyph);
if (vert_origin_yf_unit) {
out_xy_array[1] = -vert_origin_yf_unit * size_per_unit_;
continue;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/variable_axes_names.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/variable_axes_names.cc
index e237bddd9d2..e267430c262 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/variable_axes_names.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/variable_axes_names.cc
@@ -23,9 +23,10 @@ Vector<VariationAxis> VariableAxesNames::GetVariationAxes(
return output;
sk_sp<SkData> sk_data =
SkData::MakeFromStream(stream.get(), stream->getLength());
- HbScoped<hb_blob_t> blob(hb_blob_create(
- reinterpret_cast<const char*>(sk_data->bytes()), sk_data->size(),
- HB_MEMORY_MODE_READONLY, nullptr, nullptr));
+ HbScoped<hb_blob_t> blob(
+ hb_blob_create(reinterpret_cast<const char*>(sk_data->bytes()),
+ base::checked_cast<unsigned>(sk_data->size()),
+ HB_MEMORY_MODE_READONLY, nullptr, nullptr));
HbScoped<hb_face_t> face(hb_face_create(blob.get(), 0));
unsigned axes_count = hb_ot_var_get_axis_count(face.get());
std::unique_ptr<hb_ot_var_axis_info_t[]> axes =
@@ -52,9 +53,9 @@ Vector<VariationAxis> VariableAxesNames::GetVariationAxes(
axis.name = String(buffer.get());
}
- std::array<char, 4> tag = {HB_UNTAG(axes[i].tag)};
+ std::array<uint8_t, 4> tag = {HB_UNTAG(axes[i].tag)};
- axis.tag = String(tag.data(), tag.size());
+ axis.tag = String(reinterpret_cast<const char*>(tag.data()), tag.size());
axis.minValue = axes[i].min_value;
axis.maxValue = axes[i].max_value;
axis.defaultValue = axes[i].default_value;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/orientation_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/orientation_iterator.h
index 7d0ffade33c..0c4186e12fc 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/orientation_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/orientation_iterator.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/fonts/font_orientation.h"
#include "third_party/blink/renderer/platform/fonts/script_run_iterator.h"
#include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
@@ -28,6 +27,8 @@ class PLATFORM_EXPORT OrientationIterator {
OrientationIterator(const UChar* buffer,
unsigned buffer_size,
FontOrientation run_orientation);
+ OrientationIterator(const OrientationIterator&) = delete;
+ OrientationIterator& operator=(const OrientationIterator&) = delete;
bool Consume(unsigned* orientation_limit, RenderOrientation*);
@@ -35,8 +36,6 @@ class PLATFORM_EXPORT OrientationIterator {
std::unique_ptr<UTF16TextIterator> utf16_iterator_;
unsigned buffer_size_;
bool at_end_;
-
- DISALLOW_COPY_AND_ASSIGN(OrientationIterator);
};
} // namespace blink
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 960846f8136..11e885b79e2 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SCRIPT_RUN_ITERATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SCRIPT_RUN_ITERATOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -29,6 +28,9 @@ class PLATFORM_EXPORT ScriptRunIterator {
// the process.
ScriptRunIterator(const UChar* text, wtf_size_t length, const ScriptData*);
+ ScriptRunIterator(const ScriptRunIterator&) = delete;
+ ScriptRunIterator& operator=(const ScriptRunIterator&) = delete;
+
bool Consume(unsigned* limit, UScriptCode*);
static constexpr int kMaxScriptCount = 32;
@@ -70,8 +72,6 @@ class PLATFORM_EXPORT ScriptRunIterator {
UScriptCode common_preferred_;
const ScriptData* script_data_;
-
- DISALLOW_COPY_AND_ASSIGN(ScriptRunIterator);
};
// ScriptData is a wrapper which returns a set of scripts for a particular
@@ -86,6 +86,8 @@ class PLATFORM_EXPORT ScriptData {
ScriptData() = default;
public:
+ ScriptData(const ScriptData&) = delete;
+ ScriptData& operator=(const ScriptData&) = delete;
virtual ~ScriptData();
enum PairedBracketType {
@@ -103,9 +105,6 @@ class PLATFORM_EXPORT ScriptData {
virtual UChar32 GetPairedBracket(UChar32) const = 0;
virtual PairedBracketType GetPairedBracketType(UChar32) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ScriptData);
};
class PLATFORM_EXPORT ICUScriptData : public ScriptData {
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 946a89ea553..5fd2bb665a6 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/fonts/script_run_iterator.h"
#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -23,8 +24,17 @@ struct ScriptExpectedRun {
ScriptExpectedRun(unsigned the_limit, UScriptCode the_code)
: limit(the_limit), code(the_code) {}
+
+ bool operator==(const ScriptExpectedRun& other) const {
+ return limit == other.limit && code == other.code;
+ }
};
+std::ostream& operator<<(std::ostream& output, const ScriptExpectedRun& run) {
+ return output << String::Format("%d:%d (%s)", run.limit, run.code,
+ uscript_getName(run.code));
+}
+
class MockScriptData : public ScriptData {
public:
~MockScriptData() override = default;
@@ -317,16 +327,12 @@ class ScriptRunIteratorTest : public testing::Test {
void VerifyRuns(ScriptRunIterator* script_run_iterator,
const Vector<ScriptExpectedRun>& expect) {
+ Vector<ScriptExpectedRun> actual;
unsigned limit;
UScriptCode code;
- size_t run_count = 0;
- while (script_run_iterator->Consume(&limit, &code)) {
- ASSERT_LT(run_count, expect.size());
- ASSERT_EQ(expect[run_count].limit, limit);
- ASSERT_EQ(expect[run_count].code, code);
- ++run_count;
- }
- ASSERT_EQ(expect.size(), run_count);
+ while (script_run_iterator->Consume(&limit, &code))
+ actual.emplace_back(limit, code);
+ EXPECT_THAT(actual, testing::ContainerEq(expect));
}
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.cc b/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.cc
index 1192c79378b..967ca507c6d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.cc
@@ -85,13 +85,4 @@ bool SegmentedFontData::ShouldSkipDrawing() const {
return false;
}
-bool SegmentedFontData::HasAdvanceOverride() const {
- auto* end = faces_.end();
- for (auto* it = faces_.begin(); it != end; ++it) {
- if ((*it)->FontData()->HasAdvanceOverride())
- return true;
- }
- return false;
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h
index a2613181602..17cc3ed89ec 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h
@@ -58,7 +58,6 @@ class PLATFORM_EXPORT SegmentedFontData : public FontData {
bool IsLoadingFallback() const override;
bool IsSegmented() const override;
bool ShouldSkipDrawing() const override;
- bool HasAdvanceOverride() const override;
Vector<scoped_refptr<FontDataForRangeSet>, 1> faces_;
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h
index 2ecd858888c..f8546a8e749 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h
@@ -57,8 +57,10 @@ class PLATFORM_EXPORT CachingWordShapeIterator final {
// SVG sets SpacingDisabled because it handles spacing by themselves.
if (!run.SpacingDisabled())
- spacing_.SetSpacingAndExpansion(*font);
+ spacing_.SetSpacingAndExpansion(font->GetFontDescription());
}
+ CachingWordShapeIterator(const CachingWordShapeIterator&) = delete;
+ CachingWordShapeIterator& operator=(const CachingWordShapeIterator&) = delete;
bool Next(scoped_refptr<const ShapeResult>* word_result) {
if (UNLIKELY(text_run_.AllowTabs()))
@@ -204,8 +206,6 @@ class PLATFORM_EXPORT CachingWordShapeIterator final {
float width_so_far_; // Used only when allowTabs()
unsigned start_index_ : 31;
unsigned shape_by_word_ : 1;
-
- DISALLOW_COPY_AND_ASSIGN(CachingWordShapeIterator);
};
} // namespace blink
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 df8e43525e0..fcd8cf7c074 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
@@ -47,6 +47,8 @@ class PLATFORM_EXPORT CachingWordShaper final {
public:
explicit CachingWordShaper(const Font& font) : font_(font) {}
+ CachingWordShaper(const CachingWordShaper&) = delete;
+ CachingWordShaper& operator=(const CachingWordShaper&) = delete;
~CachingWordShaper() = default;
float Width(const TextRun&,
@@ -70,8 +72,6 @@ class PLATFORM_EXPORT CachingWordShaper final {
ShapeCache* GetShapeCache() const;
const Font& font_;
-
- DISALLOW_COPY_AND_ASSIGN(CachingWordShaper);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc
index 6ab2024741d..5397152b1ab 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
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
index 86d0e71d5b9..f7b67e61af9 100644
--- 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
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h"
+#include <unicode/utf16.h>
+
#include "third_party/blink/renderer/platform/wtf/text/case_map.h"
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
index 5fbd0880cce..55c3b94558b 100644
--- 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
@@ -7,8 +7,8 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include <hb.h>
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/font_features_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/font_features_test.cc
index dc598315d33..61205474ddf 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/font_features_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/font_features_test.cc
@@ -57,7 +57,7 @@ TEST_P(FontFeaturesByOrientationTest,
constexpr hb_tag_t vchw = HB_TAG('v', 'c', 'h', 'w');
for (unsigned value = 0; value <= 1; ++value) {
scoped_refptr<FontFeatureSettings> settings = FontFeatureSettings::Create();
- settings->Append({IsHorizontal() ? chws : vchw, value});
+ settings->Append({IsHorizontal() ? chws : vchw, static_cast<int>(value)});
FontDescription font_description;
font_description.SetOrientation(GetOrientation());
font_description.SetFeatureSettings(settings);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h
index 10d4f23588a..fcfbeb7f234 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h
@@ -86,12 +86,12 @@ struct GlyphBoundsAccumulator {
// Convert physical glyph_bounding_box to logical.
bounds = bounds.TransposedRect();
- // The glyph bounding box of a vertical run uses ideographic baseline.
- // Adjust the box Y position because the bounding box of a ShapeResult uses
- // alphabetic baseline.
+ // The glyph bounding box of a vertical run uses ideographic central
+ // baseline. Adjust the box Y position because the bounding box of a
+ // ShapeResult uses alphabetic baseline.
// See diagrams of base lines at
// https://drafts.csswg.org/css-writing-modes-3/#intro-baselines
- int baseline_adjust = font_metrics.Ascent(kIdeographicBaseline) -
+ int baseline_adjust = font_metrics.Ascent(kCentralBaseline) -
font_metrics.Ascent(kAlphabeticBaseline);
bounds.SetY(bounds.Y() + baseline_adjust);
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
index f8cff9f1d2d..450268e5612 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -92,7 +92,7 @@ HarfBuzzFace::HarfBuzzFace(FontPlatformData* platform_data, uint64_t unique_id)
HarfBuzzFontCache::AddResult result =
FontGlobalContext::GetHarfBuzzFontCache()->insert(unique_id_, nullptr);
if (result.is_new_entry) {
- HbScoped<hb_face_t> face(CreateFace());
+ HbScoped<hb_face_t> face = CreateFace();
result.stored_value->value =
CreateHbFontCacheEntry(face.get(), platform_data->Typeface());
}
@@ -364,8 +364,8 @@ static void DeleteTypefaceStream(void* stream_asset_ptr) {
}
#endif
-hb_face_t* HarfBuzzFace::CreateFace() {
- hb_face_t* face = nullptr;
+HbScoped<hb_face_t> HarfBuzzFace::CreateFace() {
+ HbScoped<hb_face_t> face;
SkTypeface* typeface = platform_data_->Typeface();
CHECK(typeface);
@@ -383,14 +383,21 @@ hb_face_t* HarfBuzzFace::CreateFace() {
hb_blob_create(reinterpret_cast<const char*>(tf_memory),
SafeCast<unsigned int>(tf_size), HB_MEMORY_MODE_READONLY,
tf_stream.release(), DeleteTypefaceStream));
- face = hb_face_create(face_blob.get(), ttc_index);
+ // hb_face_create always succeeds.
+ // Use hb_face_count to retrieve the number of recognized faces in the blob.
+ // hb_face_create_for_tables may still create a working hb_face.
+ // See https://github.com/harfbuzz/harfbuzz/issues/248 .
+ unsigned int num_hb_faces = hb_face_count(face_blob.get());
+ if (0 < num_hb_faces && static_cast<unsigned>(ttc_index) < num_hb_faces) {
+ face.reset(hb_face_create(face_blob.get(), ttc_index));
+ }
}
#endif
// Fallback to table copies if there is no in-memory access.
if (!face) {
- face = hb_face_create_for_tables(HarfBuzzSkiaGetTable,
- platform_data_->Typeface(), nullptr);
+ face.reset(hb_face_create_for_tables(HarfBuzzSkiaGetTable,
+ platform_data_->Typeface(), nullptr));
}
DCHECK(face);
@@ -445,9 +452,9 @@ static_assert(
"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 {
+hb_font_t* HarfBuzzFace::GetScaledFont(scoped_refptr<UnicodeRangeSet> range_set,
+ VerticalLayoutCallbacks vertical_layout,
+ float specified_size) const {
harfbuzz_font_data_->range_set_ = std::move(range_set);
harfbuzz_font_data_->UpdateFallbackMetricsAndScale(*platform_data_,
vertical_layout);
@@ -460,7 +467,8 @@ hb_font_t* HarfBuzzFace::GetScaledFont(
// points. After discussion on the pull request and with Apple developers, the
// meaning of HarfBuzz' hb_font_set_ptem API was changed to expect the
// equivalent of CSS pixels here.
- hb_font_set_ptem(unscaled_font_, platform_data_->size());
+ hb_font_set_ptem(unscaled_font_, specified_size > 0 ? specified_size
+ : platform_data_->size());
return unscaled_font_;
}
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
index 64437e3bafa..1811354c811 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FACE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FACE_H_
-#include "base/macros.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"
@@ -39,6 +38,7 @@
#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/character_names.h"
+#include "third_party/harfbuzz-ng/utils/hb_scoped.h"
#include <hb.h>
@@ -53,6 +53,8 @@ class HarfBuzzFace : public RefCounted<HarfBuzzFace> {
uint64_t unique_id) {
return base::AdoptRef(new HarfBuzzFace(platform_data, unique_id));
}
+ HarfBuzzFace(const HarfBuzzFace&) = delete;
+ HarfBuzzFace& operator=(const HarfBuzzFace&) = delete;
~HarfBuzzFace();
enum VerticalLayoutCallbacks { PrepareForVerticalLayout, NoVerticalLayout };
@@ -60,8 +62,12 @@ class HarfBuzzFace : public RefCounted<HarfBuzzFace> {
// 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.
+ // Passing in specified_size in order to control selecting the right value
+ // from the trak table. If not set, the size of the internal FontPlatformData
+ // object will be used.
hb_font_t* GetScaledFont(scoped_refptr<UnicodeRangeSet>,
- VerticalLayoutCallbacks) const;
+ VerticalLayoutCallbacks,
+ float specified_size = -1) const;
bool HasSpaceInLigaturesOrKerning(TypesettingFeatures);
unsigned UnitsPerEmFromHeadTable();
@@ -71,15 +77,13 @@ class HarfBuzzFace : public RefCounted<HarfBuzzFace> {
private:
HarfBuzzFace(FontPlatformData*, uint64_t);
- hb_face_t* CreateFace();
+ HbScoped<hb_face_t> CreateFace();
void PrepareHarfBuzzFontData();
FontPlatformData* platform_data_;
uint64_t unique_id_;
hb_font_t* unscaled_font_;
HarfBuzzFontData* harfbuzz_font_data_;
-
- DISALLOW_COPY_AND_ASSIGN(HarfBuzzFace);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_data.h
index 60e26cde857..97ff29b4622 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_data.h
@@ -29,6 +29,8 @@ struct HarfBuzzFontData {
space_in_gsub_(SpaceGlyphInOpenTypeTables::Unknown),
vertical_data_(nullptr),
range_set_(nullptr) {}
+ HarfBuzzFontData(const HarfBuzzFontData&) = delete;
+ HarfBuzzFontData& operator=(const HarfBuzzFontData&) = delete;
// The vertical origin and vertical advance functions in HarfBuzzFace require
// the ascent and height metrics as fallback in case no specific vertical
@@ -104,9 +106,6 @@ struct HarfBuzzFontData {
scoped_refptr<OpenTypeVerticalData> vertical_data_;
scoped_refptr<UnicodeRangeSet> range_set_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HarfBuzzFontData);
};
} // namespace blink
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
index c3527d34dc2..8ae7d3eca69 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -207,6 +207,8 @@ class HarfBuzzScopedPtr {
: ptr_(ptr), destroy_(destroy) {
DCHECK(destroy_);
}
+ HarfBuzzScopedPtr(const HarfBuzzScopedPtr&) = delete;
+ HarfBuzzScopedPtr& operator=(const HarfBuzzScopedPtr&) = delete;
~HarfBuzzScopedPtr() {
if (ptr_)
(*destroy_)(ptr_);
@@ -218,8 +220,6 @@ class HarfBuzzScopedPtr {
private:
T* ptr_;
DestroyFunction destroy_;
-
- DISALLOW_COPY_AND_ASSIGN(HarfBuzzScopedPtr);
};
struct RangeData {
@@ -294,7 +294,8 @@ inline bool ShapeRange(hb_buffer_t* buffer,
scoped_refptr<UnicodeRangeSet> current_font_range_set,
UScriptCode current_run_script,
hb_direction_t direction,
- hb_language_t language) {
+ hb_language_t language,
+ float specified_size) {
const FontPlatformData* platform_data = &(current_font->PlatformData());
HarfBuzzFace* face = platform_data->GetHarfBuzzFace();
if (!face) {
@@ -310,7 +311,8 @@ inline bool ShapeRange(hb_buffer_t* buffer,
face->GetScaledFont(std::move(current_font_range_set),
HB_DIRECTION_IS_VERTICAL(direction)
? HarfBuzzFace::PrepareForVerticalLayout
- : HarfBuzzFace::NoVerticalLayout);
+ : HarfBuzzFace::NoVerticalLayout,
+ specified_size);
hb_shape(hb_font, buffer, font_features, font_features_size);
if (!face->ShouldSubpixelPosition())
RoundHarfBuzzBufferPositions(buffer);
@@ -848,7 +850,7 @@ void HarfBuzzShaper::ShapeSegment(
: range_data->font_features.data(),
range_data->font_features.size(), adjusted_font,
current_font_data_for_range_set->Ranges(), segment.script,
- direction, language))
+ direction, language, font_description.SpecifiedSize()))
DLOG(ERROR) << "Shaping range failed.";
ExtractShapeResults(range_data, font_cycle_queued, current_queue_item,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
index ccb81df13f1..6e8ae7166e9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
@@ -6,7 +6,7 @@
#include <unicode/uscript.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
@@ -284,7 +284,7 @@ TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) {
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) {
SelectDevanagariFont();
UChar devanagari_common_string[] = {0x915, 0x94d, 0x930, 0x28, 0x20, 0x29};
- String devanagari_common_latin(devanagari_common_string, 6);
+ String devanagari_common_latin(devanagari_common_string, 6u);
HarfBuzzShaper shaper(devanagari_common_latin);
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
@@ -305,7 +305,7 @@ TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) {
SelectDevanagariFont();
UChar devanagari_common_latin_string[] = {0x915, 0x94d, 0x930, 0x20,
0x61, 0x62, 0x2E};
- HarfBuzzShaper shaper(String(devanagari_common_latin_string, 7));
+ HarfBuzzShaper shaper(String(devanagari_common_latin_string, 7u));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
// Ensure that there are only two scripts, Devanagari first, then Latin.
@@ -324,7 +324,7 @@ TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) {
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) {
UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- HarfBuzzShaper shaper(String(mixed_string, 6));
+ HarfBuzzShaper shaper(String(mixed_string, 6u));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
EXPECT_EQ(4u, TestInfo(result)->NumberOfRunsForTesting());
@@ -355,7 +355,7 @@ TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) {
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) {
UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- HarfBuzzShaper shaper(String(mixed_string, 6));
+ HarfBuzzShaper shaper(String(mixed_string, 6u));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
EXPECT_EQ(4u, TestInfo(result)->NumberOfRunsForTesting());
@@ -367,7 +367,7 @@ TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) {
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) {
UChar arabic_string[] = {0x628, 0x64A, 0x629};
- HarfBuzzShaper shaper(String(arabic_string, 3));
+ HarfBuzzShaper shaper(String(arabic_string, 3u));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
@@ -441,7 +441,7 @@ TEST_F(HarfBuzzShaperTest, ShapeLatinSegment) {
#endif
TEST_F(HarfBuzzShaperTest, MAYBE_ShapeArabicWithContext) {
UChar arabic_string[] = {0x647, 0x64A};
- HarfBuzzShaper shaper(String(arabic_string, 2));
+ HarfBuzzShaper shaper(String(arabic_string, 2u));
scoped_refptr<ShapeResult> combined =
shaper.Shape(&font, TextDirection::kRtl);
@@ -723,7 +723,7 @@ TEST_F(HarfBuzzShaperTest, NegativeLetterSpacing) {
ShapeResultSpacing<String> spacing(string);
FontDescription font_description;
font_description.SetLetterSpacing(-5);
- spacing.SetSpacing(Font(font_description));
+ spacing.SetSpacing(font_description);
result->ApplySpacing(spacing);
EXPECT_EQ(5 * 5, width - result->Width());
@@ -738,7 +738,7 @@ TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingTo0) {
ShapeResultSpacing<String> spacing(string);
FontDescription font_description;
font_description.SetLetterSpacing(-char_width);
- spacing.SetSpacing(Font(font_description));
+ spacing.SetSpacing(font_description);
result->ApplySpacing(spacing);
// EXPECT_EQ(0.0f, result->Width());
@@ -753,7 +753,7 @@ TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingToNegative) {
ShapeResultSpacing<String> spacing(string);
FontDescription font_description;
font_description.SetLetterSpacing(-2 * char_width);
- spacing.SetSpacing(Font(font_description));
+ spacing.SetSpacing(font_description);
result->ApplySpacing(spacing);
// CSS does not allow negative width, it should be clampled to 0.
@@ -908,7 +908,7 @@ TEST_F(HarfBuzzShaperTest, PositionForOffsetArabic) {
UChar arabic_string[] = {0x628, 0x64A, 0x629};
TextDirection direction = TextDirection::kRtl;
- HarfBuzzShaper shaper(String(arabic_string, 3));
+ HarfBuzzShaper shaper(String(arabic_string, 3u));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
EXPECT_EQ(0.0f, result->PositionForOffset(3));
@@ -977,7 +977,7 @@ TEST_P(IncludePartialGlyphsTest,
TEST_P(IncludePartialGlyphsTest,
OffsetForPositionMatchesPositionForOffsetArabic) {
UChar arabic_string[] = {0x628, 0x64A, 0x629};
- String string(arabic_string, 3);
+ String string(arabic_string, 3u);
TextDirection direction = TextDirection::kRtl;
HarfBuzzShaper shaper(string);
@@ -997,7 +997,7 @@ TEST_P(IncludePartialGlyphsTest,
TEST_P(IncludePartialGlyphsTest,
OffsetForPositionMatchesPositionForOffsetMixed) {
UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- String string(mixed_string, 6);
+ String string(mixed_string, 6u);
HarfBuzzShaper shaper(string);
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
@@ -1045,7 +1045,7 @@ TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingArabic) {
UChar arabic_string[] = {0x628, 0x64A, 0x629};
TextDirection direction = TextDirection::kRtl;
- HarfBuzzShaper shaper(String(arabic_string, 3));
+ HarfBuzzShaper shaper(String(arabic_string, 3u));
scoped_refptr<ShapeResult> sr = shaper.Shape(&font, direction);
sr->EnsurePositionData();
@@ -1057,7 +1057,7 @@ TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingArabic) {
TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingMixed) {
UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- HarfBuzzShaper shaper(String(mixed_string, 6));
+ HarfBuzzShaper shaper(String(mixed_string, 6u));
scoped_refptr<ShapeResult> sr = shaper.Shape(&font, TextDirection::kLtr);
sr->EnsurePositionData();
@@ -1253,7 +1253,7 @@ 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));
+ HarfBuzzShaper shaper(String(mixed_string, 8u));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
scoped_refptr<ShapeResult> composite_result =
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 e6f919a1e05..203ca8e2c81 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
@@ -17,22 +17,18 @@ namespace blink {
RunSegmenter::RunSegmenter(const UChar* buffer,
unsigned buffer_size,
- FontOrientation run_orientation,
- unsigned start_offset)
+ FontOrientation run_orientation)
: buffer_size_(buffer_size),
- start_offset_(start_offset),
- candidate_range_(NullRange(start_offset)),
+ candidate_range_(NullRange()),
script_run_iterator_(
- std::make_unique<ScriptRunIterator>(buffer + start_offset,
- buffer_size)),
+ std::make_unique<ScriptRunIterator>(buffer, buffer_size)),
orientation_iterator_(
run_orientation == FontOrientation::kVerticalMixed
- ? std::make_unique<OrientationIterator>(buffer + start_offset,
+ ? std::make_unique<OrientationIterator>(buffer,
buffer_size,
run_orientation)
: nullptr),
- symbols_iterator_(std::make_unique<SymbolsIterator>(buffer + start_offset,
- buffer_size)),
+ symbols_iterator_(std::make_unique<SymbolsIterator>(buffer, buffer_size)),
last_split_(0),
script_run_iterator_position_(0),
orientation_iterator_position_(
@@ -76,10 +72,10 @@ bool RunSegmenter::Consume(RunSegmenterRange* next_range) {
last_split_ = *std::min_element(std::begin(positions), std::end(positions));
candidate_range_.start = candidate_range_.end;
- candidate_range_.end = last_split_ + start_offset_;
+ candidate_range_.end = last_split_;
*next_range = candidate_range_;
- at_end_ = (last_split_ == buffer_size_);
+ 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 cdf2a1c5818..69ae7af2fe1 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
@@ -7,7 +7,6 @@
#include <unicode/uscript.h>
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/fonts/font_orientation.h"
#include "third_party/blink/renderer/platform/fonts/orientation_iterator.h"
#include "third_party/blink/renderer/platform/fonts/script_run_iterator.h"
@@ -35,16 +34,15 @@ class PLATFORM_EXPORT RunSegmenter {
};
// Initialize a RunSegmenter.
- RunSegmenter(const UChar* buffer,
- unsigned buffer_size,
- FontOrientation,
- unsigned start_offset = 0);
+ RunSegmenter(const UChar* buffer, unsigned buffer_size, FontOrientation);
+ RunSegmenter(const RunSegmenter&) = delete;
+ RunSegmenter& operator=(const RunSegmenter&) = delete;
bool Consume(RunSegmenterRange*);
- static RunSegmenterRange NullRange(unsigned offset = 0) {
- return {offset, offset, USCRIPT_INVALID_CODE,
- OrientationIterator::kOrientationKeep, FontFallbackPriority::kText};
+ static RunSegmenterRange NullRange() {
+ return {0, 0, USCRIPT_INVALID_CODE, OrientationIterator::kOrientationKeep,
+ FontFallbackPriority::kText};
}
private:
@@ -55,7 +53,6 @@ class PLATFORM_EXPORT RunSegmenter {
SegmentationCategory* segmentation_category);
unsigned buffer_size_;
- unsigned start_offset_;
RunSegmenterRange candidate_range_;
std::unique_ptr<ScriptRunIterator> script_run_iterator_;
std::unique_ptr<OrientationIterator> orientation_iterator_;
@@ -65,8 +62,6 @@ class PLATFORM_EXPORT RunSegmenter {
unsigned orientation_iterator_position_;
unsigned symbols_iterator_position_;
bool at_end_;
-
- DISALLOW_COPY_AND_ASSIGN(RunSegmenter);
};
} // namespace blink
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 f188a5ef68c..4e04613f442 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
@@ -251,22 +251,6 @@ TEST_F(RunSegmenterTest, NonEmojiPresentationSymbols) {
FontFallbackPriority::kText}});
}
-TEST_F(RunSegmenterTest, StartOffset) {
- String text = String::FromUTF8("abcשלום");
- text.Ensure16Bit();
-
- // skip first 3 characters
- unsigned start_offset = 3;
- Vector<SegmenterExpectedRun> expect;
- expect.push_back(SegmenterExpectedRun(
- start_offset, text.length(), USCRIPT_HEBREW,
- OrientationIterator::kOrientationKeep, FontFallbackPriority::kText));
-
- RunSegmenter run_segmenter(text.Characters16(), text.length() - start_offset,
- FontOrientation::kHorizontal, start_offset);
- VerifyRuns(&run_segmenter, expect);
-}
-
TEST_F(RunSegmenterTest, CJKBracketsAfterLatinLetter) {
CheckRunsHorizontal(
{{"A", USCRIPT_LATIN, OrientationIterator::kOrientationKeep,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
index 9dfd507dd0b..73391ecd631 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
@@ -109,6 +109,8 @@ class ShapeCache {
// TODO(cavalcantii): Investigate tradeoffs of reserving space
// in short_string_map.
}
+ ShapeCache(const ShapeCache&) = delete;
+ ShapeCache& operator=(const ShapeCache&) = delete;
ShapeCacheEntry* Add(const TextRun& run, ShapeCacheEntry entry) {
if (run.length() > SmallStringKey::Capacity())
@@ -231,8 +233,6 @@ class ShapeCache {
SmallStringMap short_string_map_;
unsigned version_ = 0;
base::WeakPtrFactory<ShapeCache> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ShapeCache);
};
inline bool operator==(const ShapeCache::SmallStringKey& a,
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 6b43a30dddf..ffce97c434e 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
@@ -892,13 +892,8 @@ void ShapeResult::ApplySpacingImpl(
}
typename ShapeResultSpacing<TextContainerType>::ComputeSpacingParameters
- parameters{
- .index = run_start_index + glyph_data.character_index,
- .original_advance = glyph_data.advance,
- .advance_override =
- IsCanvasRotationInVerticalUpright(run->canvas_rotation_)
- ? run->font_data_->GetAdvanceOverrideVerticalUpright()
- : run->font_data_->GetAdvanceOverride()};
+ parameters{.index = run_start_index + glyph_data.character_index,
+ .original_advance = glyph_data.advance};
space = spacing.ComputeSpacing(parameters, offset);
glyph_data.advance += space;
total_space_for_run += space;
@@ -1034,7 +1029,8 @@ unsigned ShapeResult::RunInfo::LimitNumGlyphs(
DCHECK_LE(limit_glyph_info->cluster, max_cluster);
// Adjust |right_glyph_info| and recompute dependent variables.
right_glyph_info = limit_glyph_info;
- num_glyphs = right_glyph_info - left_glyph_info + 1;
+ num_glyphs =
+ base::checked_cast<unsigned>(right_glyph_info - left_glyph_info + 1);
num_characters_ = right_glyph_info[1].cluster - start_cluster;
}
} else {
@@ -1063,7 +1059,8 @@ unsigned ShapeResult::RunInfo::LimitNumGlyphs(
// Adjust |right_glyph_info| and recompute dependent variables.
right_glyph_info = limit_glyph_info;
start_cluster = right_glyph_info->cluster;
- num_glyphs = right_glyph_info - left_glyph_info + 1;
+ num_glyphs =
+ base::checked_cast<unsigned>(right_glyph_info - left_glyph_info + 1);
num_characters_ = last_cluster - right_glyph_info[1].cluster;
}
}
@@ -1193,8 +1190,10 @@ void ShapeResult::InsertRun(scoped_refptr<ShapeResult::RunInfo> run) {
Vector<scoped_refptr<RunInfo>>::iterator iterator = std::lower_bound(
runs_.begin(), runs_.end(), run->start_index_,
HB_DIRECTION_IS_FORWARD(run->direction_) ? ltr_comparer : rtl_comparer);
- if (iterator != runs_.end())
- runs_.insert(iterator - runs_.begin(), std::move(run));
+ if (iterator != runs_.end()) {
+ runs_.insert(static_cast<wtf_size_t>(iterator - runs_.begin()),
+ std::move(run));
+ }
// If we didn't find an existing slot to place it, append.
if (run)
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 ee6e9762f8b..792c83dbd79 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
@@ -47,7 +47,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/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
struct hb_buffer_t;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
index a96804e8228..7b0b5bdace3 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
@@ -99,8 +99,8 @@ void ShapeResultBloberizer::CommitText() {
DVLOG(4) << " CommitText cluster starts: "
<< base::make_span(current_character_indexes_);
- size_t pending_utf8_original_size = pending_utf8_.size();
- size_t pending_utf8_character_indexes_original_size =
+ wtf_size_t pending_utf8_original_size = pending_utf8_.size();
+ wtf_size_t pending_utf8_character_indexes_original_size =
pending_utf8_character_indexes_.size();
// Do the UTF-8 conversion here.
@@ -114,7 +114,7 @@ void ShapeResultBloberizer::CommitText() {
if (current_text_.Is8Bit()) {
const LChar* latin1 = current_text_.Characters8();
wtf_size_t utf8_size = pending_utf8_.size();
- for (size_t i = from; i < to;) {
+ for (unsigned i = from; i < to;) {
pending_utf8_character_index_from_character_index[i - from] = utf8_size;
LChar cp = latin1[i++];
@@ -124,7 +124,7 @@ void ShapeResultBloberizer::CommitText() {
} else {
const UChar* utf16 = current_text_.Characters16();
wtf_size_t utf8_size = pending_utf8_.size();
- for (size_t i = from; i < to;) {
+ for (unsigned i = from; i < to;) {
pending_utf8_character_index_from_character_index[i - from] = utf8_size;
UChar32 cp;
@@ -264,11 +264,11 @@ class GlyphCallbackContext {
STACK_ALLOCATED();
public:
+ GlyphCallbackContext(const GlyphCallbackContext&) = delete;
+ GlyphCallbackContext& operator=(const GlyphCallbackContext&) = delete;
+
ShapeResultBloberizer* bloberizer;
const StringView& text;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GlyphCallbackContext);
};
} // namespace
@@ -328,13 +328,13 @@ class ClusterCallbackContext {
STACK_ALLOCATED();
public:
+ ClusterCallbackContext(const ClusterCallbackContext&) = delete;
+ ClusterCallbackContext& operator=(const ClusterCallbackContext&) = delete;
+
ShapeResultBloberizer* bloberizer;
const StringView& text;
const GlyphData& emphasis_data;
FloatPoint glyph_center;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ClusterCallbackContext);
};
} // namespace
@@ -378,6 +378,8 @@ class ClusterStarts {
public:
ClusterStarts() = default;
+ ClusterStarts(const ClusterStarts&) = delete;
+ ClusterStarts& operator=(const ClusterStarts&) = delete;
static void Accumulate(void* context,
unsigned character_index,
@@ -413,8 +415,6 @@ class ClusterStarts {
base::span<const unsigned> Data() { return cluster_starts_; }
private:
- DISALLOW_COPY_AND_ASSIGN(ClusterStarts);
-
Vector<unsigned, 256> cluster_starts_;
unsigned last_seen_character_index_ = 0;
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
index ce52b5d0327..55c455f91e4 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
@@ -35,6 +35,8 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
ShapeResultBloberizer(const FontDescription&,
float device_scale_factor,
Type);
+ ShapeResultBloberizer(const ShapeResultBloberizer&) = delete;
+ ShapeResultBloberizer& operator=(const ShapeResultBloberizer&) = delete;
struct BlobInfo {
BlobInfo(sk_sp<SkTextBlob> b, CanvasRotationInVertical r)
@@ -89,12 +91,11 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
CommitPendingRun();
pending_font_data_ = font_data;
pending_canvas_rotation_ = canvas_rotation;
+ const auto& metrics = font_data->GetFontMetrics();
pending_vertical_baseline_x_offset_ =
!IsCanvasRotationInVerticalUpright(canvas_rotation)
? 0
- : font_data->GetFontMetrics().FloatAscent() -
- font_data->GetFontMetrics().FloatAscent(
- kIdeographicBaseline);
+ : metrics.FloatAscent() - metrics.FloatAscent(kCentralBaseline);
}
pending_glyphs_.push_back(glyph);
@@ -197,8 +198,6 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
// Constructed blobs.
BlobBuffer blobs_;
float advance_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(ShapeResultBloberizer);
};
struct PLATFORM_EXPORT ShapeResultBloberizer::FillGlyphsNG
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
index 39748d0da3f..9cf817a98e2 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
@@ -548,20 +548,20 @@ TEST_F(ShapeResultBloberizerTest, LatinMultRunNG) {
CheckBlobBuffer(
bloberizer_ng.Blobs(),
{{
- // T"esti"
- {range_a.length() - 1,
+ // "Testi"
+ {static_cast<int>(range_a.length() - 1),
string.Substring(range_a.from + 1, range_a.length() - 1).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
// "ng"
- {range_b.length(),
+ {static_cast<int>(range_b.length()),
string.Substring(range_b.from, range_b.length()).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
// " ShapeResultIterator::Cop"
- {range_c.length(),
+ {static_cast<int>(range_c.length()),
string.Substring(range_c.from, range_c.length()).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
// "yRange"
- {range_d.length(),
+ {static_cast<int>(range_d.length()),
string.Substring(range_d.from, range_d.length()).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
}});
@@ -609,15 +609,15 @@ TEST_F(ShapeResultBloberizerTest, SupplementaryMultiRunNG) {
CheckBlobBuffer(bloberizer_ng.Blobs(),
{{
// "𠜎𠜱𠝹"
- {range_a.length() / 2,
+ {static_cast<int>(range_a.length() / 2),
string.Substring(range_a.from, range_a.length()).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
// "𠱓𠱸𠲖"
- {range_b.length() / 2,
+ {static_cast<int>(range_b.length() / 2),
string.Substring(range_b.from, range_b.length()).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
// "𠳏𠳕"
- {range_c.length() / 2,
+ {static_cast<int>(range_c.length() / 2),
string.Substring(range_c.from, range_c.length()).Utf8(),
ExpectedRun::ClusterDirection::Ascending},
}});
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 12303d8f7c2..cf0f0bb5340 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
@@ -24,6 +24,8 @@ class PLATFORM_EXPORT ShapeResultBuffer {
public:
ShapeResultBuffer() : has_vertical_offsets_(false) {}
+ ShapeResultBuffer(const ShapeResultBuffer&) = delete;
+ ShapeResultBuffer& operator=(const ShapeResultBuffer&) = delete;
void AppendResult(scoped_refptr<const ShapeResult> result) {
has_vertical_offsets_ |= result->HasVerticalOffsets();
@@ -64,8 +66,6 @@ class PLATFORM_EXPORT ShapeResultBuffer {
// rare.
Vector<scoped_refptr<const ShapeResult>, 64> results_;
bool has_vertical_offsets_;
-
- DISALLOW_COPY_AND_ASSIGN(ShapeResultBuffer);
};
} // namespace blink
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 68d3ca9e254..92ae0de165c 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
@@ -236,27 +236,36 @@ struct ShapeResult::RunInfo : public RefCounted<ShapeResult::RunInfo> {
}
void ExpandRangeToIncludePartialGlyphs(int offset, int* from, int* to) const {
- int start = IsLtr() ? 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 (IsLtr())
+ int start;
+
+ if (IsLtr()) {
+ start = offset + num_characters_;
+ for (unsigned i = 0; i < glyph_data_.size(); ++i) {
+ int index = offset + glyph_data_[i].character_index;
+ if (start == index)
+ continue;
end = index;
-
- if (end > *from && start < *to) {
- *from = std::min(*from, start);
- *to = std::max(*to, end);
- }
-
- if (IsLtr())
+ if (end > *from && start < *to) {
+ *from = std::min(*from, start);
+ *to = std::max(*to, end);
+ }
end = offset + num_characters_;
- else
+ start = index;
+ }
+ } else {
+ start = 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 (end > *from && start < *to) {
+ *from = std::min(*from, start);
+ *to = std::max(*to, end);
+ }
end = start;
- start = index;
+ start = index;
+ }
}
if (end > *from && start < *to) {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc
index 326648748f7..e409d7b619f 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc
@@ -11,10 +11,9 @@
namespace blink {
template <typename TextContainerType>
-bool ShapeResultSpacing<TextContainerType>::SetSpacing(const Font& font) {
- const FontDescription& font_description = font.GetFontDescription();
- if (!font_description.LetterSpacing() && !font_description.WordSpacing() &&
- !font.HasAdvanceOverride()) {
+bool ShapeResultSpacing<TextContainerType>::SetSpacing(
+ const FontDescription& font_description) {
+ if (!font_description.LetterSpacing() && !font_description.WordSpacing()) {
has_spacing_ = false;
return false;
}
@@ -43,19 +42,18 @@ void ShapeResultSpacing<TextContainerType>::SetExpansion(
template <typename TextContainerType>
void ShapeResultSpacing<TextContainerType>::SetSpacingAndExpansion(
- const Font& font) {
+ const FontDescription& font_description) {
// Available only for TextRun since it has expansion data.
NOTREACHED();
}
template <>
-void ShapeResultSpacing<TextRun>::SetSpacingAndExpansion(const Font& font) {
- const FontDescription& font_description = font.GetFontDescription();
+void ShapeResultSpacing<TextRun>::SetSpacingAndExpansion(
+ const FontDescription& font_description) {
letter_spacing_ = font_description.LetterSpacing();
word_spacing_ = font_description.WordSpacing();
expansion_ = text_.Expansion();
- has_spacing_ = letter_spacing_ || word_spacing_ || expansion_ ||
- font.HasAdvanceOverride();
+ has_spacing_ = letter_spacing_ || word_spacing_ || expansion_;
if (!has_spacing_)
return;
@@ -137,15 +135,12 @@ float ShapeResultSpacing<TextContainerType>::ComputeSpacing(
float spacing = 0;
- bool has_letter_spacing =
- letter_spacing_ || (parameters.advance_override != 1.0);
- if (has_letter_spacing && !Character::TreatAsZeroWidthSpace(character)) {
- spacing +=
- parameters.original_advance * (parameters.advance_override - 1.0) +
- letter_spacing_;
- }
+ bool has_letter_spacing = letter_spacing_;
+ if (has_letter_spacing && !Character::TreatAsZeroWidthSpace(character))
+ spacing += letter_spacing_;
- if (treat_as_space && (index || character == kNoBreakSpaceCharacter))
+ if (treat_as_space && (allow_word_spacing_anywhere_ || index ||
+ character == kNoBreakSpaceCharacter))
spacing += word_spacing_;
if (!HasExpansion())
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h
index acdecdc7419..bd17332b7d0 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h
@@ -11,7 +11,7 @@
namespace blink {
-class Font;
+class FontDescription;
// A context object to apply letter-spacing, word-spacing, and justification to
// ShapeResult.
@@ -20,7 +20,8 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
STACK_ALLOCATED();
public:
- explicit ShapeResultSpacing(const TextContainerType& text)
+ explicit ShapeResultSpacing(const TextContainerType& text,
+ bool allow_word_spacing_anywhere = false)
: text_(text),
letter_spacing_(0),
word_spacing_(0),
@@ -31,7 +32,8 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
has_spacing_(false),
normalize_space_(false),
allow_tabs_(false),
- is_after_expansion_(false) {}
+ is_after_expansion_(false),
+ allow_word_spacing_anywhere_(allow_word_spacing_anywhere) {}
const TextContainerType& Text() const { return text_; }
float LetterSpacing() const { return has_spacing_ ? letter_spacing_ : .0f; }
@@ -42,10 +44,8 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
return expansion_opportunity_count_;
}
- // Set letter-spacing, word-spacing, and advance-override. Uses a Font
- // argument instead of FontDescription as advance-override is retrieved
- // from CSS @font-face, not from style like word-spacing and letter-spacing.
- bool SetSpacing(const Font&);
+ // Set letter-spacing and word-spacing.
+ bool SetSpacing(const FontDescription&);
// Set the expansion for the justification.
void SetExpansion(float expansion,
@@ -54,9 +54,9 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
bool allows_leading_expansion = false,
bool allows_trailing_expansion = false);
- // Set letter-spacing, word-spacing, advance-override and
+ // Set letter-spacing, word-spacing, and
// justification. Available only for TextRun.
- void SetSpacingAndExpansion(const Font&);
+ void SetSpacingAndExpansion(const FontDescription&);
// Compute the sum of all spacings for the specified |index|.
// The |index| is for the |TextContainerType| given in the constructor.
@@ -65,7 +65,6 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
struct ComputeSpacingParameters {
unsigned index;
float original_advance = 0.0;
- float advance_override = 1.0;
};
float ComputeSpacing(unsigned index, float& offset) {
return ComputeSpacing(ComputeSpacingParameters{.index = index}, offset);
@@ -94,12 +93,14 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
bool normalize_space_;
bool allow_tabs_;
bool is_after_expansion_;
+ bool allow_word_spacing_anywhere_;
};
// Forward declare so no implicit instantiations happen before the
// first explicit instantiation (which would be a C++ violation).
template <>
-void ShapeResultSpacing<TextRun>::SetSpacingAndExpansion(const Font&);
+void ShapeResultSpacing<TextRun>::SetSpacingAndExpansion(
+ const FontDescription&);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_SPACING_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
index c41eeae4d4c..4c9a6203314 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -61,7 +61,7 @@ struct ShapeResultView::RunInfoPart {
bool IsRtl() const { return run_->IsRtl(); }
bool IsHorizontal() const { return run_->IsHorizontal(); }
unsigned NumCharacters() const { return num_characters_; }
- unsigned NumGlyphs() const { return range_.end - range_.begin; }
+ unsigned NumGlyphs() const { return range_.size(); }
float Width() const { return width_; }
unsigned PreviousSafeToBreakOffset(unsigned offset) const;
@@ -319,7 +319,7 @@ void ShapeResultView::AddSegments(const Segment* segments,
// Segments are in logical order, runs and parts are in visual order. Iterate
// over segments back-to-front for RTL.
DCHECK_GT(segment_count, 0u);
- unsigned last_segment_index = segment_count - 1;
+ size_t last_segment_index = segment_count - 1;
// Compute start index offset for the overall run. This is added to the start
// index of each glyph to ensure consistency with ShapeResult::SubRange
@@ -333,7 +333,7 @@ void ShapeResultView::AddSegments(const Segment* segments,
char_index_offset_ = 0;
}
- for (unsigned i = 0; i < segment_count; i++) {
+ for (size_t i = 0; i < segment_count; i++) {
const Segment& segment = segments[IsRtl() ? last_segment_index - i : i];
if (segment.result) {
DCHECK_EQ(segment.result->Direction(), Direction());
@@ -378,7 +378,8 @@ void ShapeResultView::GetRunFontData(
Vector<ShapeResult::RunFontData>* font_data) const {
for (const auto& part : RunsOrParts()) {
font_data->push_back(ShapeResult::RunFontData(
- {part.run_->font_data_.get(), part.end() - part.begin()}));
+ {part.run_->font_data_.get(),
+ static_cast<wtf_size_t>(part.end() - part.begin())}));
}
}
@@ -654,11 +655,8 @@ FloatRect ShapeResultView::ComputeInkBounds() const {
void ShapeResultView::ExpandRangeToIncludePartialGlyphs(unsigned* from,
unsigned* to) const {
- unsigned accumulated_offset = char_index_offset_;
- for (const auto& part : Parts()) {
- part.ExpandRangeToIncludePartialGlyphs(accumulated_offset, from, to);
- accumulated_offset += part.NumCharacters();
- }
+ for (const auto& part : Parts())
+ part.ExpandRangeToIncludePartialGlyphs(char_index_offset_, from, to);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
index ffdc370effd..c2fd49eef9a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
@@ -100,6 +100,8 @@ class PLATFORM_EXPORT ShapeResultView final
unsigned start_index,
unsigned end_index);
+ ShapeResultView(const ShapeResultView&) = delete;
+ ShapeResultView& operator=(const ShapeResultView&) = delete;
~ShapeResultView();
scoped_refptr<ShapeResult> CreateShapeResult() const;
@@ -221,8 +223,6 @@ class PLATFORM_EXPORT ShapeResultView final
GlyphCallback,
void* context,
const RunInfoPart& part) const;
-
- DISALLOW_COPY_AND_ASSIGN(ShapeResultView);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
index 233afb5926d..7ded608eb9a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
@@ -31,6 +31,22 @@ class ShapeResultViewTest : public testing::Test {
Font font;
};
+// http://crbug.com/1221008
+TEST_F(ShapeResultViewTest,
+ ExpandRangeToIncludePartialGlyphsWithCombiningCharacter) {
+ String string(u"abc\u0E35\u0E35\u0E35\u0E35");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result =
+ shaper.Shape(&font, TextDirection::kLtr);
+ scoped_refptr<const ShapeResultView> view = ShapeResultView::Create(
+ result.get(), result->StartIndex(), result->EndIndex());
+ unsigned from = 0;
+ unsigned end = string.length();
+ view->ExpandRangeToIncludePartialGlyphs(&from, &end);
+ EXPECT_EQ(0u, from);
+ EXPECT_EQ(string.length(), end);
+}
+
TEST_F(ShapeResultViewTest, LatinSingleView) {
String string =
To16Bit("Test run with multiple words and breaking opportunities.", 56);
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 160f2f6f6d5..ef2389c2c6b 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/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc
index fc2dc146cc8..823a1ff2057 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc
@@ -48,7 +48,7 @@ GetAssemblyParameters(const HarfBuzzFace* harfbuzz_face,
: HB_DIRECTION_BTT;
// Go over the assembly parts and determine parameters used below.
- // https://mathml-refresh.github.io/mathml-core/#the-glyphassembly-table
+ // https://w3c.github.io/mathml-core/#the-glyphassembly-table
float min_connector_overlap = HarfBuzzUnitsToFloat(
hb_ot_math_get_min_connector_overlap(hb_font, hb_stretch_axis));
float max_connector_overlap = std::numeric_limits<float>::max();
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h
index eb78f2244af..3fac7f7c218 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h
@@ -22,12 +22,12 @@ class StretchyOperatorShaper;
// TODO(https://crbug.com/1057589): Add a TextDirection parameter, so that it's
// possible to perform glyph-level (rtlm feature) or character-level mirroring
// before stretching.
-// https://mathml-refresh.github.io/mathml-core/#algorithms-for-glyph-stretching
+// https://w3c.github.io/mathml-core/#algorithms-for-glyph-stretching
class PLATFORM_EXPORT StretchyOperatorShaper final {
DISALLOW_NEW();
public:
- StretchyOperatorShaper(UChar stretchy_character,
+ StretchyOperatorShaper(UChar32 stretchy_character,
OpenTypeMathStretchData::StretchAxis stretch_axis)
: stretchy_character_(stretchy_character), stretch_axis_(stretch_axis) {}
@@ -40,8 +40,7 @@ class PLATFORM_EXPORT StretchyOperatorShaper final {
// Shape the stretched operator. The coordinates of the glyph(s) use the same
// origin as the rectangle assigned to the optional OUT Metrics parameter.
// May be called multiple times; font and direction may vary between calls.
- // https://mathml-refresh.github.io/mathml-core/#dfn-shape-a-stretchy-glyph
- // https://mathml-refresh.github.io/mathml-core/#dfn-box-metrics-of-a-stretchy-glyph
+ // https://w3c.github.io/mathml-core/#dfn-shape-a-stretchy-glyph
scoped_refptr<ShapeResult> Shape(const Font*,
float target_size,
Metrics* metrics = nullptr) const;
@@ -49,7 +48,7 @@ class PLATFORM_EXPORT StretchyOperatorShaper final {
~StretchyOperatorShaper() = default;
private:
- const UChar stretchy_character_;
+ const UChar32 stretchy_character_;
const OpenTypeMathStretchData::StretchAxis stretch_axis_;
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc
index 3d9827ddb56..cdcb122103f 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
namespace blink {
@@ -260,12 +261,30 @@ TEST_F(StretchyOperatorShaperTest, GlyphVariants) {
// h1/v1 and minimal overlap 500 is Y = 1500k + 1500.
// So target_size - Y >= 250 >> kSizeError if the assembly does not have
// more than the max number of glyphs.
- target_size = 1500 * HarfBuzzRunGlyphData::kMaxGlyphs + 1750;
+ target_size =
+ static_cast<float>(1500 * HarfBuzzRunGlyphData::kMaxGlyphs + 1750);
horizontal_shaper.Shape(&math, target_size);
vertical_shaper.Shape(&math, target_size);
}
}
+// See createStretchy() in
+// third_party/blink/web_tests/external/wpt/mathml/tools/operator-dictionary.py
+TEST_F(StretchyOperatorShaperTest, NonBMPCodePoint) {
+ Font math = CreateMathFont("operators.woff");
+
+ StretchyOperatorShaper horizontal_shaper(
+ kArabicMathematicalOperatorHahWithDal,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+
+ float target_size = 10000;
+ StretchyOperatorShaper::Metrics metrics;
+ horizontal_shaper.Shape(&math, target_size, &metrics);
+ EXPECT_NEAR(metrics.advance, target_size, kSizeError);
+ EXPECT_NEAR(metrics.ascent, 1000, kSizeError);
+ EXPECT_FLOAT_EQ(metrics.descent, 0);
+}
+
// See third_party/blink/web_tests/external/wpt/mathml/tools/largeop.py
TEST_F(StretchyOperatorShaperTest, MathItalicCorrection) {
{
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 f87d93cb92b..18ccc4db339 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
@@ -162,7 +162,7 @@ void SimpleFontData::PlatformInit(bool subpixel_ascent_descent,
#if !defined(OS_MAC)
if (metrics.fAvgCharWidth) {
- avg_char_width_ = SkScalarRoundToInt(metrics.fAvgCharWidth);
+ avg_char_width_ = SkScalarToFloat(metrics.fAvgCharWidth);
} else {
#endif
avg_char_width_ = x_height;
@@ -179,9 +179,6 @@ void SimpleFontData::PlatformInit(bool subpixel_ascent_descent,
if (int units_per_em = face->getUnitsPerEm())
font_metrics_.SetUnitsPerEm(units_per_em);
- advance_override_ = metrics_override.advance_override;
- advance_override_vertical_upright_ =
- metrics_override.advance_override_vertical_upright;
}
void SimpleFontData::PlatformGlyphInit() {
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 66b3a5917b2..dd108063410 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
@@ -143,6 +143,9 @@ class PLATFORM_EXPORT SimpleFontData : public FontData {
bool IsLoadingFallback() const override {
return custom_font_data_ ? custom_font_data_->IsLoadingFallback() : false;
}
+ bool IsPendingDataUrlCustomFont() const {
+ return custom_font_data_ ? custom_font_data_->IsPendingDataUrl() : false;
+ }
bool IsSegmented() const override;
bool ShouldSkipDrawing() const override {
return custom_font_data_ && custom_font_data_->ShouldSkipDrawing();
@@ -157,15 +160,6 @@ class PLATFORM_EXPORT SimpleFontData : public FontData {
return visual_overflow_inflation_for_descent_;
}
- bool HasAdvanceOverride() const override {
- return advance_override_.has_value();
- }
-
- float GetAdvanceOverride() const { return advance_override_.value_or(1); }
- float GetAdvanceOverrideVerticalUpright() const {
- return advance_override_vertical_upright_.value_or(1);
- }
-
protected:
SimpleFontData(
const FontPlatformData&,
@@ -199,11 +193,11 @@ class PLATFORM_EXPORT SimpleFontData : public FontData {
public:
DerivedFontData() = default;
+ DerivedFontData(const DerivedFontData&) = delete;
+ DerivedFontData& operator=(const DerivedFontData&) = delete;
scoped_refptr<SimpleFontData> small_caps;
scoped_refptr<SimpleFontData> emphasis_mark;
-
- DISALLOW_COPY_AND_ASSIGN(DerivedFontData);
};
mutable std::unique_ptr<DerivedFontData> derived_font_data_;
@@ -216,11 +210,6 @@ class PLATFORM_EXPORT SimpleFontData : public FontData {
unsigned visual_overflow_inflation_for_ascent_;
unsigned visual_overflow_inflation_for_descent_;
- // The multiplier to the advance of each letter as defined by the
- // advance-override value in @font-face.
- absl::optional<float> advance_override_;
- absl::optional<float> advance_override_vertical_upright_;
-
mutable FontHeight normalized_typo_ascent_descent_;
// See discussion on crbug.com/631032 and Skiaissue
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 d622a3e69d5..2c45028aff7 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
@@ -69,13 +69,14 @@ AtomicString FontCache::GetFamilyNameForCharacter(
SkFontMgr* fm,
UChar32 c,
const FontDescription& font_description,
+ const char* family_name,
FontFallbackPriority fallback_priority) {
DCHECK(fm);
Bcp47Vector locales =
GetBcp47LocaleForRequest(font_description, fallback_priority);
sk_sp<SkTypeface> typeface(fm->matchFamilyStyleCharacter(
- nullptr, SkFontStyle(), locales.data(), locales.size(), c));
+ family_name, SkFontStyle(), locales.data(), locales.size(), c));
if (!typeface)
return g_empty_atom;
@@ -207,7 +208,7 @@ sk_sp<SkTypeface> FontCache::CreateTypeface(
}
#endif
- AtomicString family = creation_params.Family();
+ const AtomicString& family = creation_params.Family();
DCHECK_NE(family, font_family_names::kSystemUi);
// If we're creating a fallback font (e.g. "-webkit-monospace"), convert the
// name into the fallback name (like "monospace") that fontconfig understands.
@@ -218,6 +219,16 @@ sk_sp<SkTypeface> FontCache::CreateTypeface(
name = family.Utf8();
}
+#if defined(OS_ANDROID)
+ // If this is a locale-specific family, try looking up locale-specific
+ // typeface first.
+ if (const char* locale_family = GetLocaleSpecificFamilyName(family)) {
+ if (sk_sp<SkTypeface> typeface =
+ CreateLocaleSpecificTypeface(font_description, locale_family))
+ return typeface;
+ }
+#endif // defined(OS_ANDROID)
+
#if defined(OS_WIN)
// TODO(vmpstr): Deal with paint typeface here.
if (sideloaded_fonts_) {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/small_caps_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/small_caps_iterator.h
index 8ae4857add5..5ac53fdb0b8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/small_caps_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/small_caps_iterator.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/fonts/font_orientation.h"
#include "third_party/blink/renderer/platform/fonts/script_run_iterator.h"
#include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
@@ -26,6 +25,8 @@ class PLATFORM_EXPORT SmallCapsIterator {
};
SmallCapsIterator(const UChar* buffer, unsigned buffer_size);
+ SmallCapsIterator(const SmallCapsIterator&) = delete;
+ SmallCapsIterator& operator=(const SmallCapsIterator&) = delete;
bool Consume(unsigned* caps_limit, SmallCapsBehavior*);
@@ -37,8 +38,6 @@ class PLATFORM_EXPORT SmallCapsIterator {
SmallCapsBehavior current_small_caps_behavior_;
SmallCapsBehavior previous_small_caps_behavior_;
-
- DISALLOW_COPY_AND_ASSIGN(SmallCapsIterator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator.h
index cc65327fc43..6be2274aeb7 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SYMBOLS_ITERATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SYMBOLS_ITERATOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
#include "third_party/blink/renderer/platform/fonts/utf16_ragel_iterator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -17,6 +16,8 @@ class PLATFORM_EXPORT SymbolsIterator {
public:
SymbolsIterator(const UChar* buffer, unsigned buffer_size);
+ SymbolsIterator(const SymbolsIterator&) = delete;
+ SymbolsIterator& operator=(const SymbolsIterator&) = delete;
bool Consume(unsigned* symbols_limit, FontFallbackPriority*);
@@ -26,8 +27,6 @@ class PLATFORM_EXPORT SymbolsIterator {
unsigned next_token_end_;
bool next_token_emoji_;
-
- DISALLOW_COPY_AND_ASSIGN(SymbolsIterator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.cc b/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.cc
index db814e5a8e0..c08b2cb9bd5 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.cc
@@ -22,4 +22,18 @@ String ToString(TextRenderingMode mode) {
return "Unknown";
}
+String ToStringForIdl(TextRenderingMode mode) {
+ switch (mode) {
+ case TextRenderingMode::kAutoTextRendering:
+ return "auto";
+ case TextRenderingMode::kOptimizeSpeed:
+ return "optimizeSpeed";
+ case TextRenderingMode::kOptimizeLegibility:
+ return "optimizeLegibility";
+ case TextRenderingMode::kGeometricPrecision:
+ return "geometricPrecision";
+ }
+ return "Unknown";
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.h b/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.h
index a4f97a0547a..aa5bd59c7b8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/text_rendering_mode.h
@@ -39,6 +39,7 @@ enum TextRenderingMode {
};
PLATFORM_EXPORT String ToString(TextRenderingMode);
+PLATFORM_EXPORT String ToStringForIdl(TextRenderingMode);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.cc b/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.cc
index 5122b6a2d29..6a35fc41c48 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
+#include <unicode/utf16.h>
+
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.h b/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.h
index 090af632de9..3ad6bc9de08 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/unicode_range_set.h
@@ -30,8 +30,8 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.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/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc b/chromium/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc
index fe01532716b..e45d90b1815 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc
@@ -6,7 +6,7 @@
#include <unicode/unistr.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.h
index 42340acc7f3..1c6f0376034 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.h
@@ -21,7 +21,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_UTF16_TEXT_ITERATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_UTF16_TEXT_ITERATOR_H_
-#include "base/macros.h"
+#include <unicode/utf16.h>
+
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
@@ -38,6 +39,8 @@ class PLATFORM_EXPORT UTF16TextIterator {
// 'length' denotes the maximum length of the UChar array, which might exceed
// 'endOffset'.
UTF16TextIterator(const UChar*, int length);
+ UTF16TextIterator(const UTF16TextIterator&) = delete;
+ UTF16TextIterator& operator=(const UTF16TextIterator&) = delete;
inline bool Consume(UChar32& character) {
if (offset_ >= length_)
@@ -70,8 +73,6 @@ class PLATFORM_EXPORT UTF16TextIterator {
int offset_;
int length_;
unsigned current_glyph_length_;
-
- DISALLOW_COPY_AND_ASSIGN(UTF16TextIterator);
};
} // 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 ab4caf56075..62a3edfa9c3 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/platform/fonts/vdmx_parser.h"
-#include "base/macros.h"
#include "base/sys_byteorder.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -51,6 +50,8 @@ class Buffer {
public:
Buffer(const uint8_t* buffer, size_t length)
: buffer_(buffer), length_(length), offset_(0) {}
+ Buffer(const Buffer&) = delete;
+ Buffer& operator=(const Buffer&) = delete;
bool skip(size_t numBytes) {
if (offset_ + numBytes > length_)
@@ -88,8 +89,6 @@ class Buffer {
const uint8_t* const buffer_;
const size_t length_;
size_t offset_;
-
- DISALLOW_COPY_AND_ASSIGN(Buffer);
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc b/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc
index 2c352237bba..e5f6c2963b7 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc
@@ -127,8 +127,9 @@ sk_sp<SkFontMgr> WebFontTypefaceFactory::FontManagerForVariations() {
sk_sp<SkFontMgr> WebFontTypefaceFactory::FontManagerForSbix() {
#if defined(OS_MAC)
return DefaultFontManager();
-#endif
+#else
return FreeTypeFontManager();
+#endif
}
sk_sp<SkFontMgr> WebFontTypefaceFactory::DefaultFontManager() {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
index 770702feb39..8be0b941371 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
@@ -21,6 +21,8 @@ class FallbackFamilyStyleCache {
public:
FallbackFamilyStyleCache();
+ FallbackFamilyStyleCache(const FallbackFamilyStyleCache&) = delete;
+ FallbackFamilyStyleCache& operator=(const FallbackFamilyStyleCache&) = delete;
// Places a SkTypeface object in the cache for specified language tag and
// fallback priority, taking a reference on SkTypeface. Adds the |SkTypeface|
@@ -49,8 +51,6 @@ class FallbackFamilyStyleCache {
void Clear();
private:
- DISALLOW_COPY_AND_ASSIGN(FallbackFamilyStyleCache);
-
FallbackLruCache recent_fallback_fonts_;
};
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 316f90f11ef..e2c3b26a535 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
@@ -39,9 +39,9 @@
#include <string>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/debug/alias.h"
#include "base/metrics/histogram_functions.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
@@ -57,6 +57,8 @@
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
+// For GetACP()
+#include <windows.h>
namespace blink {
@@ -107,7 +109,7 @@ int32_t EnsureMinimumFontHeightIfNeeded(int32_t font_height) {
// Adjustment for codepage 936 to make the fonts more legible in Simplified
// Chinese. Please refer to LayoutThemeFontProviderWin.cpp for more
// information.
- return (font_height < 12.0f) && (GetACP() == 936) ? 12.0f : font_height;
+ return ((font_height < 12.0f) && (GetACP() == 936)) ? 12.0f : font_height;
}
// Test-only code for matching sideloaded fonts by postscript name. This
@@ -135,7 +137,7 @@ sk_sp<SkTypeface> FindUniqueFontNameFromSideloadedFonts(
FT_Open_Args open_args = {
FT_OPEN_MEMORY,
reinterpret_cast<const FT_Byte*>(typeface_stream->getMemoryBase()),
- typeface_stream->getLength()};
+ static_cast<FT_Long>(typeface_stream->getLength())};
CHECK_EQ(FT_Err_Ok, FT_Open_Face(library, &open_args, 0, &font_face));
font_family_name = FT_Get_Postscript_Name(font_face);
FT_Done_Face(font_face);
@@ -502,7 +504,7 @@ static bool TypefacesHasWeightSuffix(const AtomicString& family,
FontSelectionValue& variant_weight) {
struct FamilyWeightSuffix {
const UChar* suffix;
- size_t length;
+ wtf_size_t length;
FontSelectionValue weight;
};
// Mapping from suffix to weight from the DirectWrite documentation.
@@ -540,7 +542,7 @@ static bool TypefacesHasStretchSuffix(const AtomicString& family,
FontSelectionValue& variant_stretch) {
struct FamilyStretchSuffix {
const UChar* suffix;
- size_t length;
+ wtf_size_t length;
FontSelectionValue stretch;
};
// Mapping from suffix to stretch value from the DirectWrite documentation.
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 7eb9e4a51fb..432c044bd35 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
@@ -35,7 +35,7 @@
#include <limits>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h
index bbe1e2dcbeb..cb5e180d589 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h
@@ -25,6 +25,8 @@ namespace blink {
class FontUniqueNameLookupWin : public FontUniqueNameLookup {
public:
FontUniqueNameLookupWin();
+ FontUniqueNameLookupWin(const FontUniqueNameLookupWin&) = delete;
+ FontUniqueNameLookupWin& operator=(const FontUniqueNameLookupWin&) = delete;
~FontUniqueNameLookupWin() override;
sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) override;
@@ -49,8 +51,6 @@ class FontUniqueNameLookupWin : public FontUniqueNameLookup {
absl::optional<bool> sync_available_;
void ReceiveReadOnlySharedMemoryRegion(
base::ReadOnlySharedMemoryRegion shared_memory_region);
-
- DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupWin);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_box.h b/chromium/third_party/blink/renderer/platform/geometry/float_box.h
index 7ed79b48588..6560df0b0a6 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_box.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_box.h
@@ -53,13 +53,8 @@ class PLATFORM_EXPORT FloatBox {
float depth)
: x_(x), y_(y), z_(z), width_(width), height_(height), depth_(depth) {}
- constexpr FloatBox(const FloatBox& box)
- : x_(box.X()),
- y_(box.Y()),
- z_(box.Z()),
- width_(box.Width()),
- height_(box.Height()),
- depth_(box.Depth()) {}
+ constexpr FloatBox(const FloatBox&) = default;
+ constexpr FloatBox& operator=(const FloatBox&) = default;
void SetOrigin(const FloatPoint3D& origin) {
x_ = origin.X();
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_point_3d.h b/chromium/third_party/blink/renderer/platform/geometry/float_point_3d.h
index bbe09db5592..2302ef3a328 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_point_3d.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_point_3d.h
@@ -44,8 +44,9 @@ class PLATFORM_EXPORT FloatPoint3D {
constexpr FloatPoint3D(const FloatPoint& p) : x_(p.X()), y_(p.Y()), z_(0) {}
- constexpr FloatPoint3D(const FloatPoint3D& p)
- : x_(p.X()), y_(p.Y()), z_(p.Z()) {}
+ constexpr FloatPoint3D(const FloatPoint3D&) = default;
+
+ constexpr FloatPoint3D& operator=(const FloatPoint3D&) = default;
FloatPoint3D(const gfx::Point3F&);
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 fe08d053e18..341468d7719 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 "base/macros.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/wtf/allocator/allocator.h"
@@ -46,6 +45,8 @@ class PLATFORM_EXPORT FloatPolygon {
public:
explicit FloatPolygon(Vector<FloatPoint> vertices);
+ FloatPolygon(const FloatPolygon&) = delete;
+ FloatPolygon& operator=(const FloatPolygon&) = delete;
const FloatPoint& VertexAt(unsigned index) const { return vertices_[index]; }
unsigned NumberOfVertices() const { return vertices_.size(); }
@@ -72,8 +73,6 @@ class PLATFORM_EXPORT FloatPolygon {
EdgeIntervalTree edge_tree_; // Each EdgeIntervalTree node stores minY, maxY,
// and a ("UserData") pointer to a
// FloatPolygonEdge.
-
- DISALLOW_COPY_AND_ASSIGN(FloatPolygon);
};
class PLATFORM_EXPORT VertexPair {
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_quad.cc b/chromium/third_party/blink/renderer/platform/geometry/float_quad.cc
index b7ae991568c..fc9ad0c1a0e 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_quad.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_quad.cc
@@ -76,8 +76,9 @@ inline bool IsPointInTriangle(const FloatPoint& p,
return (u >= 0) && (v >= 0) && (u + v <= 1);
}
-static inline float SaturateInf(float value) {
- if (UNLIKELY(std::isinf(value))) {
+static inline float ClampToIntRange(float value) {
+ if (UNLIKELY(std::isinf(value) ||
+ std::abs(value) > std::numeric_limits<int>::max())) {
return std::signbit(value) ? std::numeric_limits<int>::min()
: std::numeric_limits<int>::max();
}
@@ -85,11 +86,11 @@ static inline float SaturateInf(float value) {
}
FloatRect FloatQuad::BoundingBox() const {
- float left = SaturateInf(Min4(p1_.X(), p2_.X(), p3_.X(), p4_.X()));
- float top = SaturateInf(Min4(p1_.Y(), p2_.Y(), p3_.Y(), p4_.Y()));
+ float left = ClampToIntRange(Min4(p1_.X(), p2_.X(), p3_.X(), p4_.X()));
+ float top = ClampToIntRange(Min4(p1_.Y(), p2_.Y(), p3_.Y(), p4_.Y()));
- float right = SaturateInf(Max4(p1_.X(), p2_.X(), p3_.X(), p4_.X()));
- float bottom = SaturateInf(Max4(p1_.Y(), p2_.Y(), p3_.Y(), p4_.Y()));
+ float right = ClampToIntRange(Max4(p1_.X(), p2_.X(), p3_.X(), p4_.X()));
+ float bottom = ClampToIntRange(Max4(p1_.Y(), p2_.Y(), p3_.Y(), p4_.Y()));
return FloatRect(left, top, right - left, bottom - top);
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_quad_test.cc b/chromium/third_party/blink/renderer/platform/geometry/float_quad_test.cc
index 4827a82f62a..0794acc1537 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_quad_test.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_quad_test.cc
@@ -27,14 +27,27 @@ TEST(FloatQuadTest, BoundingBox) {
}
TEST(FloatQuadTest, BoundingBoxSaturateInf) {
- double inf = std::numeric_limits<double>::infinity();
+ constexpr double inf = std::numeric_limits<double>::infinity();
FloatQuad quad(FloatPoint(-inf, 3), FloatPoint(5, inf), FloatPoint(11, 13),
FloatPoint(17, 19));
FloatRect rect = quad.BoundingBox();
EXPECT_EQ(rect.X(), std::numeric_limits<int>::min());
EXPECT_EQ(rect.Y(), 3.0f);
EXPECT_EQ(rect.Width(), 17.0f - std::numeric_limits<int>::min());
- EXPECT_EQ(rect.Height(), std::numeric_limits<int>::max() - 3.0f);
+ EXPECT_EQ(rect.Height(),
+ static_cast<float>(std::numeric_limits<int>::max()) - 3.0f);
+}
+
+TEST(FloatQuadTest, BoundingBoxSaturateLarge) {
+ constexpr double large = std::numeric_limits<float>::max() * 4;
+ FloatQuad quad(FloatPoint(-large, 3), FloatPoint(5, large),
+ FloatPoint(11, 13), FloatPoint(17, 19));
+ FloatRect rect = quad.BoundingBox();
+ EXPECT_EQ(rect.X(), std::numeric_limits<int>::min());
+ EXPECT_EQ(rect.Y(), 3.0f);
+ EXPECT_EQ(rect.Width(), 17.0f - std::numeric_limits<int>::min());
+ EXPECT_EQ(rect.Height(),
+ static_cast<float>(std::numeric_limits<int>::max()) - 3.0f);
}
TEST(FloatQuadTest, RectIntersectionIsInclusive) {
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 f9c90559557..0b2e091fded 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
@@ -244,6 +244,39 @@ FloatRect UnionRect(const Vector<FloatRect>& rects) {
return result;
}
+FloatRect MaximumCoveredRect(const FloatRect& a, const FloatRect& b) {
+ // Check a or b by itself.
+ FloatRect maximum(a);
+ float maximum_area = a.Size().Area();
+ if (b.Size().Area() > maximum_area) {
+ maximum = b;
+ maximum_area = b.Size().Area();
+ }
+ // Check the regions that include the intersection of a and b. This can be
+ // done by taking the intersection and expanding it vertically and
+ // horizontally. These expanded intersections will both still be covered by
+ // a or b.
+ FloatRect intersection = a;
+ intersection.InclusiveIntersect(b);
+ if (!intersection.IsZero()) {
+ FloatRect vert_expanded_intersection(intersection);
+ vert_expanded_intersection.ShiftYEdgeTo(std::min(a.Y(), b.Y()));
+ vert_expanded_intersection.ShiftMaxYEdgeTo(std::max(a.MaxY(), b.MaxY()));
+ if (vert_expanded_intersection.Size().Area() > maximum_area) {
+ maximum = vert_expanded_intersection;
+ maximum_area = vert_expanded_intersection.Size().Area();
+ }
+ FloatRect horiz_expanded_intersection(intersection);
+ horiz_expanded_intersection.ShiftXEdgeTo(std::min(a.X(), b.X()));
+ horiz_expanded_intersection.ShiftMaxXEdgeTo(std::max(a.MaxX(), b.MaxX()));
+ if (horiz_expanded_intersection.Size().Area() > maximum_area) {
+ maximum = horiz_expanded_intersection;
+ maximum_area = horiz_expanded_intersection.Size().Area();
+ }
+ }
+ return maximum;
+}
+
IntRect EnclosedIntRect(const FloatRect& rect) {
IntPoint location = CeiledIntPoint(rect.Location());
IntPoint max_point = FlooredIntPoint(rect.MaxXMaxYCorner());
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 5e505b504e8..827adf6e1db 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
@@ -230,6 +230,10 @@ inline FloatRect UnionRect(const FloatRect& a, const FloatRect& b) {
PLATFORM_EXPORT FloatRect UnionRect(const Vector<FloatRect>&);
+// Return a maximum rectangle in which any point is covered by either a or b.
+PLATFORM_EXPORT FloatRect MaximumCoveredRect(const FloatRect& a,
+ const FloatRect& b);
+
inline FloatRect& operator+=(FloatRect& a, const FloatRect& b) {
a.Move(b.X(), b.Y());
a.SetWidth(a.Width() + b.Width());
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 99451c77ac4..cfa53e15339 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
@@ -282,4 +282,46 @@ TEST(FloatRectTest, InclusiveIntersect) {
EXPECT_EQ(EnclosingIntRect(rect), IntRect());
}
+TEST(FloatRectTest, MaximumCoveredRect) {
+ // X aligned and intersect: unite.
+ EXPECT_EQ(
+ FloatRect(10, 20, 30, 60),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(10, 30, 30, 50)));
+ // X aligned and adjacent: unite.
+ EXPECT_EQ(
+ FloatRect(10, 20, 30, 90),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(10, 60, 30, 50)));
+ // X aligned and separate: choose the bigger one.
+ EXPECT_EQ(
+ FloatRect(10, 61, 30, 50),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(10, 61, 30, 50)));
+ // Y aligned and intersect: unite.
+ EXPECT_EQ(
+ FloatRect(10, 20, 60, 40),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(30, 20, 40, 40)));
+ // Y aligned and adjacent: unite.
+ EXPECT_EQ(
+ FloatRect(10, 20, 70, 40),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(40, 20, 40, 40)));
+ // Y aligned and separate: choose the bigger one.
+ EXPECT_EQ(
+ FloatRect(41, 20, 40, 40),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(41, 20, 40, 40)));
+ // Get the biggest expanded intersection.
+ EXPECT_EQ(FloatRect(0, 0, 9, 19), MaximumCoveredRect(FloatRect(0, 0, 10, 10),
+ FloatRect(0, 9, 9, 10)));
+ EXPECT_EQ(FloatRect(0, 0, 19, 9), MaximumCoveredRect(FloatRect(0, 0, 10, 10),
+ FloatRect(9, 0, 10, 9)));
+ // Otherwise choose the bigger one.
+ EXPECT_EQ(
+ FloatRect(20, 30, 40, 50),
+ MaximumCoveredRect(FloatRect(10, 20, 30, 40), FloatRect(20, 30, 40, 50)));
+ EXPECT_EQ(
+ FloatRect(10, 20, 40, 50),
+ MaximumCoveredRect(FloatRect(10, 20, 40, 50), FloatRect(20, 30, 30, 40)));
+ EXPECT_EQ(
+ FloatRect(10, 20, 40, 50),
+ MaximumCoveredRect(FloatRect(10, 20, 40, 50), FloatRect(20, 30, 40, 50)));
+}
+
} // namespace blink
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 e9d4e2d465f..0f7e4089ec2 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
@@ -52,6 +52,25 @@ FloatRoundedRect::FloatRoundedRect(const FloatRect& rect,
const FloatSize& bottom_right)
: rect_(rect), radii_(top_left, top_right, bottom_left, bottom_right) {}
+void FloatRoundedRect::Radii::SetMinimumRadius(float minimum_radius) {
+ top_left_.SetWidth(std::max(minimum_radius, top_left_.Width()));
+ top_left_.SetHeight(std::max(minimum_radius, top_left_.Height()));
+ top_right_.SetWidth(std::max(minimum_radius, top_right_.Width()));
+ top_right_.SetHeight(std::max(minimum_radius, top_right_.Height()));
+ bottom_left_.SetWidth(std::max(minimum_radius, bottom_left_.Width()));
+ bottom_left_.SetHeight(std::max(minimum_radius, bottom_left_.Height()));
+ bottom_right_.SetWidth(std::max(minimum_radius, bottom_right_.Width()));
+ bottom_right_.SetHeight(std::max(minimum_radius, bottom_right_.Height()));
+}
+
+absl::optional<float> FloatRoundedRect::Radii::UniformRadius() const {
+ if (top_left_.Width() == top_left_.Height() && top_left_ == top_right_ &&
+ top_left_ == bottom_left_ && top_left_ == bottom_right_) {
+ return top_left_.Width();
+ }
+ return absl::nullopt;
+}
+
void FloatRoundedRect::Radii::Scale(float factor) {
if (factor == 1)
return;
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 b5f7e1babb5..6dec0f33671 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
@@ -31,6 +31,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_FLOAT_ROUNDED_RECT_H_
#include <iosfwd>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -57,12 +58,14 @@ class PLATFORM_EXPORT FloatRoundedRect {
top_right_(top_right),
bottom_left_(bottom_left),
bottom_right_(bottom_right) {}
+ explicit constexpr Radii(float radius)
+ : Radii(FloatSize(radius, radius),
+ FloatSize(radius, radius),
+ FloatSize(radius, radius),
+ FloatSize(radius, radius)) {}
- constexpr Radii(const FloatRoundedRect::Radii& int_radii)
- : top_left_(int_radii.TopLeft()),
- top_right_(int_radii.TopRight()),
- bottom_left_(int_radii.BottomLeft()),
- bottom_right_(int_radii.BottomRight()) {}
+ constexpr Radii(const Radii&) = default;
+ constexpr Radii& operator=(const Radii&) = default;
void SetTopLeft(const FloatSize& size) { top_left_ = size; }
void SetTopRight(const FloatSize& size) { top_right_ = size; }
@@ -73,6 +76,9 @@ class PLATFORM_EXPORT FloatRoundedRect {
constexpr const FloatSize& BottomLeft() const { return bottom_left_; }
constexpr const FloatSize& BottomRight() const { return bottom_right_; }
+ void SetMinimumRadius(float);
+ absl::optional<float> UniformRadius() const;
+
constexpr bool IsZero() const {
return top_left_.IsZero() && top_right_.IsZero() &&
bottom_left_.IsZero() && bottom_right_.IsZero();
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 8b3407f3750..8ba850825a9 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_rect.cc
@@ -83,10 +83,27 @@ void IntRect::Intersect(const IntRect& other) {
bottom = 0;
}
- location_.SetX(left);
- location_.SetY(top);
- size_.SetWidth(base::ClampSub(right, left));
- size_.SetHeight(base::ClampSub(bottom, top));
+ SetLocationAndSizeFromEdges(left, top, right, bottom);
+}
+
+bool IntRect::InclusiveIntersect(const IntRect& other) {
+ int left = std::max(X(), other.X());
+ int top = std::max(Y(), other.Y());
+ int right = std::min(MaxX(), other.MaxX());
+ int bottom = std::min(MaxY(), 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);
+ return false;
+ }
+
+ SetLocationAndSizeFromEdges(left, top, right, bottom);
+ return true;
}
void IntRect::Unite(const IntRect& other) {
@@ -119,10 +136,7 @@ void IntRect::UniteEvenIfEmpty(const IntRect& other) {
int right = std::max(MaxX(), other.MaxX());
int bottom = std::max(MaxY(), other.MaxY());
- location_.SetX(left);
- location_.SetY(top);
- size_.SetWidth(base::ClampSub(right, left));
- size_.SetHeight(base::ClampSub(bottom, top));
+ SetLocationAndSizeFromEdges(left, top, right, bottom);
}
void IntRect::Scale(float s) {
@@ -167,6 +181,39 @@ IntRect UnionRectEvenIfEmpty(const Vector<IntRect>& rects) {
return result;
}
+IntRect MaximumCoveredRect(const IntRect& a, const IntRect& b) {
+ // Check a or b by itself.
+ IntRect maximum(a);
+ auto maximum_area = a.Size().Area();
+ if (b.Size().Area() > maximum_area) {
+ maximum = b;
+ maximum_area = b.Size().Area();
+ }
+ // Check the regions that include the intersection of a and b. This can be
+ // done by taking the intersection and expanding it vertically and
+ // horizontally. These expanded intersections will both still be covered by
+ // a or b.
+ IntRect intersection = a;
+ intersection.InclusiveIntersect(b);
+ if (!intersection.Size().IsZero()) {
+ IntRect vert_expanded_intersection(intersection);
+ vert_expanded_intersection.ShiftYEdgeTo(std::min(a.Y(), b.Y()));
+ vert_expanded_intersection.ShiftMaxYEdgeTo(std::max(a.MaxY(), b.MaxY()));
+ if (vert_expanded_intersection.Size().Area() > maximum_area) {
+ maximum = vert_expanded_intersection;
+ maximum_area = vert_expanded_intersection.Size().Area();
+ }
+ IntRect horiz_expanded_intersection(intersection);
+ horiz_expanded_intersection.ShiftXEdgeTo(std::min(a.X(), b.X()));
+ horiz_expanded_intersection.ShiftMaxXEdgeTo(std::max(a.MaxX(), b.MaxX()));
+ if (horiz_expanded_intersection.Size().Area() > maximum_area) {
+ maximum = horiz_expanded_intersection;
+ maximum_area = horiz_expanded_intersection.Size().Area();
+ }
+ }
+ return maximum;
+}
+
std::ostream& operator<<(std::ostream& ostream, const IntRect& rect) {
return ostream << rect.ToString();
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/int_rect.h b/chromium/third_party/blink/renderer/platform/geometry/int_rect.h
index e1e09039a22..397dd91233f 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_rect.h
@@ -148,6 +148,16 @@ class PLATFORM_EXPORT IntRect {
}
void Intersect(const IntRect&);
+
+ // Set this rect to be the intersection of itself and the argument rect
+ // using edge-inclusive geometry. If the two rectangles overlap but the
+ // overlap region is zero-area (either because one of the two rectangles
+ // is zero-area, or because the rectangles overlap at an edge or a corner),
+ // the result is the zero-area intersection. The return value indicates
+ // whether the two rectangle actually have an intersection, since checking
+ // the result for isEmpty() is not conclusive.
+ bool InclusiveIntersect(const IntRect&);
+
void Unite(const IntRect&);
void UniteIfNonZero(const IntRect&);
@@ -197,6 +207,13 @@ class PLATFORM_EXPORT IntRect {
bool IsValid() const;
private:
+ void SetLocationAndSizeFromEdges(int left, int top, int right, int bottom) {
+ location_.SetX(left);
+ location_.SetY(top);
+ size_.SetWidth(base::ClampSub(right, left));
+ size_.SetHeight(base::ClampSub(bottom, top));
+ }
+
IntPoint location_;
IntSize size_;
};
@@ -223,6 +240,9 @@ inline IntRect UnionRectEvenIfEmpty(const IntRect& a, const IntRect& b) {
PLATFORM_EXPORT IntRect UnionRectEvenIfEmpty(const Vector<IntRect>&);
+// Return a maximum rectangle that is covered by the a or b.
+PLATFORM_EXPORT IntRect MaximumCoveredRect(const IntRect& a, const IntRect& b);
+
constexpr IntRect SaturatedRect(const IntRect& r) {
return IntRect(r.X(), r.Y(), base::ClampAdd(r.X(), r.Width()) - r.X(),
base::ClampAdd(r.Y(), r.Height()) - r.Y());
diff --git a/chromium/third_party/blink/renderer/platform/geometry/int_rect_test.cc b/chromium/third_party/blink/renderer/platform/geometry/int_rect_test.cc
index fc3de582bdd..66c4dae11b3 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_rect_test.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_rect_test.cc
@@ -17,4 +17,64 @@ TEST(IntRectTest, ToString) {
EXPECT_EQ("1,2 3x4", rect.ToString());
}
+TEST(IntRectTest, InclusiveIntersect) {
+ IntRect rect(11, 12, 0, 0);
+ EXPECT_TRUE(rect.InclusiveIntersect(IntRect(11, 12, 13, 14)));
+ EXPECT_EQ(IntRect(11, 12, 0, 0), rect);
+
+ rect = IntRect(11, 12, 13, 14);
+ EXPECT_TRUE(rect.InclusiveIntersect(IntRect(24, 8, 0, 7)));
+ EXPECT_EQ(IntRect(24, 12, 0, 3), rect);
+
+ rect = IntRect(11, 12, 13, 14);
+ EXPECT_TRUE(rect.InclusiveIntersect(IntRect(9, 15, 4, 0)));
+ EXPECT_EQ(IntRect(11, 15, 2, 0), rect);
+
+ rect = IntRect(11, 12, 0, 14);
+ EXPECT_FALSE(rect.InclusiveIntersect(IntRect(12, 13, 15, 16)));
+ EXPECT_EQ(IntRect(), rect);
+}
+
+TEST(IntRectTest, MaximumCoveredRect) {
+ // X aligned and intersect: unite.
+ EXPECT_EQ(
+ IntRect(10, 20, 30, 60),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(10, 30, 30, 50)));
+ // X aligned and adjacent: unite.
+ EXPECT_EQ(
+ IntRect(10, 20, 30, 90),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(10, 60, 30, 50)));
+ // X aligned and separate: choose the bigger one.
+ EXPECT_EQ(
+ IntRect(10, 61, 30, 50),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(10, 61, 30, 50)));
+ // Y aligned and intersect: unite.
+ EXPECT_EQ(
+ IntRect(10, 20, 60, 40),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(30, 20, 40, 40)));
+ // Y aligned and adjacent: unite.
+ EXPECT_EQ(
+ IntRect(10, 20, 70, 40),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(40, 20, 40, 40)));
+ // Y aligned and separate: choose the bigger one.
+ EXPECT_EQ(
+ IntRect(41, 20, 40, 40),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(41, 20, 40, 40)));
+ // Get the biggest expanded intersection.
+ EXPECT_EQ(IntRect(0, 0, 9, 19),
+ MaximumCoveredRect(IntRect(0, 0, 10, 10), IntRect(0, 9, 9, 10)));
+ EXPECT_EQ(IntRect(0, 0, 19, 9),
+ MaximumCoveredRect(IntRect(0, 0, 10, 10), IntRect(9, 0, 10, 9)));
+ // Otherwise choose the bigger one.
+ EXPECT_EQ(
+ IntRect(20, 30, 40, 50),
+ MaximumCoveredRect(IntRect(10, 20, 30, 40), IntRect(20, 30, 40, 50)));
+ EXPECT_EQ(
+ IntRect(10, 20, 40, 50),
+ MaximumCoveredRect(IntRect(10, 20, 40, 50), IntRect(20, 30, 30, 40)));
+ EXPECT_EQ(
+ IntRect(10, 20, 40, 50),
+ MaximumCoveredRect(IntRect(10, 20, 40, 50), IntRect(20, 30, 40, 50)));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_rect_test.cc b/chromium/third_party/blink/renderer/platform/geometry/layout_rect_test.cc
index 5dc74249ef8..b384fd62b29 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_rect_test.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_rect_test.cc
@@ -297,11 +297,11 @@ struct LayoutRectUniteTestData {
{"saturated width",
{-1000, 0, 200, 200},
{33554402, 500, 30, 100},
- {0, 0, 99999999.0f, 600}},
+ {0, 0, 99999999, 600}},
{"saturated height",
{0, -1000, 200, 200},
{0, 33554402, 100, 30},
- {0, 0, 200, 99999999.0f}},
+ {0, 0, 200, 99999999}},
};
std::ostream& operator<<(std::ostream& os,
diff --git a/chromium/third_party/blink/renderer/platform/geometry/length.cc b/chromium/third_party/blink/renderer/platform/geometry/length.cc
index ec3c41bf7ed..5ababe0c677 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/length.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/length.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/platform/geometry/length.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/blend.h"
#include "third_party/blink/renderer/platform/geometry/calculation_value.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -38,6 +37,9 @@ class CalculationValueHandleMap {
public:
CalculationValueHandleMap() = default;
+ CalculationValueHandleMap(const CalculationValueHandleMap&) = delete;
+ CalculationValueHandleMap& operator=(const CalculationValueHandleMap&) =
+ delete;
int insert(scoped_refptr<const CalculationValue> calc_value) {
DCHECK(index_);
@@ -78,8 +80,6 @@ class CalculationValueHandleMap {
private:
int index_ = 1;
HashMap<int, scoped_refptr<const CalculationValue>> map_;
-
- DISALLOW_COPY_AND_ASSIGN(CalculationValueHandleMap);
};
static CalculationValueHandleMap& CalcHandles() {
diff --git a/chromium/third_party/blink/renderer/platform/geometry/length.h b/chromium/third_party/blink/renderer/platform/geometry/length.h
index d1e007a4171..51fa54a1a50 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/length.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/length.h
@@ -64,7 +64,8 @@ class PLATFORM_EXPORT Length {
kExtendToZoom,
kDeviceWidth,
kDeviceHeight,
- kNone
+ kNone, // only valid for max-width, max-height, or contain-intrinsic-size
+ kContent // only valid for flex-basis
};
Length() : int_value_(0), quirk_(false), type_(kAuto), is_float_(false) {}
@@ -152,6 +153,7 @@ class PLATFORM_EXPORT Length {
static Length DeviceHeight() { return Length(kDeviceHeight); }
static Length None() { return Length(kNone); }
static Length FitContent() { return Length(kFitContent); }
+ static Length Content() { return Length(kContent); }
template <typename NUMBER_TYPE>
static Length Percent(NUMBER_TYPE number) {
return Length(number, kPercent);
@@ -233,7 +235,8 @@ class PLATFORM_EXPORT Length {
// as `auto`. https://www.w3.org/TR/css-sizing-3/#valdef-width-min-content
bool IsContentOrIntrinsic() const {
return GetType() == kMinContent || GetType() == kMaxContent ||
- GetType() == kFitContent || GetType() == kMinIntrinsic;
+ GetType() == kFitContent || GetType() == kMinIntrinsic ||
+ GetType() == kContent;
}
bool IsAutoOrContentOrIntrinsic() const {
return GetType() == kAuto || IsContentOrIntrinsic();
@@ -253,6 +256,7 @@ class PLATFORM_EXPORT Length {
bool IsCalculatedEqual(const Length&) const;
bool IsMinContent() const { return GetType() == kMinContent; }
bool IsMaxContent() const { return GetType() == kMaxContent; }
+ bool IsContent() const { return GetType() == kContent; }
bool IsMinIntrinsic() const { return GetType() == kMinIntrinsic; }
bool IsFillAvailable() const { return GetType() == kFillAvailable; }
bool IsFitContent() const { return GetType() == kFitContent; }
diff --git a/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc b/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc
index e1fd678021a..1b3b5fd1d24 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc
@@ -50,6 +50,7 @@ float FloatValueForLength(const Length& length, float maximum_value) {
case Length::kMaxContent:
case Length::kMinIntrinsic:
case Length::kFitContent:
+ case Length::kContent:
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
@@ -79,6 +80,7 @@ LayoutUnit MinimumValueForLengthInternal(const Length& length,
case Length::kMaxContent:
case Length::kMinIntrinsic:
case Length::kFitContent:
+ case Length::kContent:
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
@@ -103,6 +105,7 @@ LayoutUnit ValueForLength(const Length& length, LayoutUnit maximum_value) {
case Length::kMaxContent:
case Length::kMinIntrinsic:
case Length::kFitContent:
+ case Length::kContent:
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/DEPS b/chromium/third_party/blink/renderer/platform/graphics/DEPS
index 5bcee6814dd..4438120a74e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/DEPS
+++ b/chromium/third_party/blink/renderer/platform/graphics/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+third_party/blink/renderer/platform/graphics",
# Dependencies.
+ "+base/no_destructor.h",
"+base/strings/string_number_conversions.h",
"+base/strings/string_split.h",
"+base/strings/string_util.h",
@@ -18,6 +19,7 @@ include_rules = [
"+components/viz/client",
"+components/viz/common",
"+gpu/config",
+ "+gpu/command_buffer/client/context_support.h",
"+gpu/command_buffer/client/gles2_interface.h",
"+gpu/command_buffer/client/gpu_memory_buffer_manager.h",
"+gpu/command_buffer/client/raster_interface.h",
@@ -40,6 +42,9 @@ include_rules = [
"+media/media_buildflags.h",
"+media/renderers/paint_canvas_video_renderer.h",
"+media/renderers/video_resource_updater.h",
+ "+media/renderers/video_frame_rgba_to_yuva_converter.h",
+ "+media/video/gpu_video_accelerator_factories.h",
+ "+media/video/renderable_gpu_memory_buffer_video_frame_pool.h",
"+services/viz/public/mojom",
"+services/viz/public/cpp/gpu/context_provider_command_buffer.h",
"+skia",
diff --git a/chromium/third_party/blink/renderer/platform/graphics/OWNERS b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
index cb4bc1b0c5d..f515f573fb9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
@@ -20,6 +20,4 @@ mcasas@chromium.org
# Video SurfaceLayer functionality.
per-file video_frame*=file://media/OWNERS
-per-file video_frame*=lethalantidote@chromium.org
per-file surface_layer_bridge*=file://media/OWNERS
-per-file surface_layer_bridge*=lethalantidote@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 05f3624d4ea..cbc85639796 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
@@ -18,6 +18,7 @@
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/mailbox_ref.h"
#include "third_party/blink/renderer/platform/graphics/mailbox_texture_backing.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
@@ -97,7 +98,7 @@ AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
-IntSize AcceleratedStaticBitmapImage::Size() const {
+IntSize AcceleratedStaticBitmapImage::SizeInternal() const {
return IntSize(sk_image_info_.width(), sk_image_info_.height());
}
@@ -151,6 +152,45 @@ bool AcceleratedStaticBitmapImage::CopyToTexture(
return true;
}
+bool AcceleratedStaticBitmapImage::CopyToResourceProvider(
+ CanvasResourceProvider* resource_provider) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(resource_provider);
+
+ if (!IsValid())
+ return false;
+
+ DCHECK(mailbox_.IsSharedImage());
+
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> shared_context_wrapper =
+ SharedGpuContext::ContextProviderWrapper();
+ if (!shared_context_wrapper || !shared_context_wrapper->ContextProvider())
+ return false;
+
+ const auto& dst_mailbox = resource_provider->GetBackingMailboxForOverwrite(
+ MailboxSyncMode::kOrderingBarrier);
+ if (dst_mailbox.IsZero())
+ return false;
+
+ const GLenum dst_target = resource_provider->GetBackingTextureTarget();
+ const bool unpack_flip_y =
+ IsOriginTopLeft() != resource_provider->IsOriginTopLeft();
+ const bool unpack_premultiply_alpha = false;
+
+ auto* ri = shared_context_wrapper->ContextProvider()->RasterInterface();
+ DCHECK(ri);
+ ri->WaitSyncTokenCHROMIUM(mailbox_ref_->sync_token().GetConstData());
+ ri->CopySubTexture(mailbox_, dst_mailbox, dst_target, 0, 0, 0, 0,
+ Size().Width(), Size().Height(), unpack_flip_y,
+ unpack_premultiply_alpha);
+ // We need to update the texture holder's sync token to ensure that when this
+ // mailbox is recycled or deleted, it is done after the copy operation above.
+ gpu::SyncToken sync_token;
+ ri->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ mailbox_ref_->set_sync_token(sync_token);
+ return true;
+}
+
PaintImage AcceleratedStaticBitmapImage::PaintImageForCurrentFrame() {
// TODO(ccameron): This function should not ignore |colorBehavior|.
// https://crbug.com/672306
@@ -166,15 +206,13 @@ PaintImage AcceleratedStaticBitmapImage::PaintImageForCurrentFrame() {
.TakePaintImage();
}
-void AcceleratedStaticBitmapImage::Draw(
- cc::PaintCanvas* canvas,
- const cc::PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- const SkSamplingOptions& sampling,
- RespectImageOrientationEnum should_respect_image_orientation,
- ImageClampingMode image_clamping_mode,
- ImageDecodingMode decode_mode) {
+void AcceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ const ImageDrawOptions& draw_options,
+ ImageClampingMode image_clamping_mode,
+ ImageDecodingMode decode_mode) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto paint_image = PaintImageForCurrentFrame();
if (!paint_image)
@@ -185,9 +223,9 @@ void AcceleratedStaticBitmapImage::Draw(
.set_decoding_mode(paint_image_decoding_mode)
.TakePaintImage();
}
- StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect, sampling,
- image_clamping_mode,
- should_respect_image_orientation, paint_image);
+ StaticBitmapImage::DrawHelper(
+ canvas, flags, dst_rect, src_rect, draw_options.sampling_options,
+ image_clamping_mode, draw_options.respect_image_orientation, paint_image);
}
bool AcceleratedStaticBitmapImage::IsValid() const {
@@ -362,7 +400,8 @@ AcceleratedStaticBitmapImage::ConvertToColorSpace(
->SharedImageInterface()
->UsageForMailbox(mailbox_);
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- Size(), kLow_SkFilterQuality, CanvasResourceParams(image_info),
+ Size(), cc::PaintFlags::FilterQuality::kLow,
+ CanvasResourceParams(image_info),
CanvasResourceProvider::ShouldInitialize::kNo, ContextProviderWrapper(),
RasterMode::kGPU, IsOriginTopLeft(), usage_flags);
if (!provider) {
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 c078f99b8c8..5aefe220d78 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
@@ -67,7 +67,6 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
viz::ReleaseCallback release_callback);
bool CurrentFrameKnownToBeOpaque() override;
- IntSize Size() const override;
bool IsTextureBacked() const override { return true; }
scoped_refptr<StaticBitmapImage> ConvertToColorSpace(sk_sp<SkColorSpace>,
SkColorType) override;
@@ -76,8 +75,7 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
@@ -95,6 +93,10 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
bool unpack_flip_y,
const IntPoint& dest_point,
const IntRect& source_sub_rectangle) override;
+
+ bool CopyToResourceProvider(
+ CanvasResourceProvider* resource_provider) override;
+
// To be called on sender thread before performing a transfer to a different
// thread.
void Transfer() final;
@@ -141,6 +143,8 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
void CreateImageFromMailboxIfNeeded();
void InitializeTextureBacking(GLuint shared_image_texture_id);
+ IntSize SizeInternal() const override;
+
const gpu::Mailbox mailbox_;
const SkImageInfo sk_image_info_;
const GLenum texture_target_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
index 3581e51dace..917ffc020e7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
@@ -8,7 +8,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/time/tick_clock.h"
@@ -48,6 +47,10 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
explicit AnimationWorkletMutatorDispatcherImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ AnimationWorkletMutatorDispatcherImpl(
+ const AnimationWorkletMutatorDispatcherImpl&) = delete;
+ AnimationWorkletMutatorDispatcherImpl& operator=(
+ const AnimationWorkletMutatorDispatcherImpl&) = delete;
~AnimationWorkletMutatorDispatcherImpl() override;
// AnimationWorkletMutatorDispatcher implementation.
@@ -170,8 +173,6 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
base::WeakPtrFactory<AnimationWorkletMutatorDispatcherImpl> weak_factory_{
this};
-
- DISALLOW_COPY_AND_ASSIGN(AnimationWorkletMutatorDispatcherImpl);
};
} // namespace blink
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 1e810d05fe0..3b5c582a5c9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h"
#include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.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_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
@@ -72,6 +73,7 @@ BitmapImage::BitmapImage(ImageObserver* observer, bool is_multipart)
mojom::blink::ImageAnimationPolicy::kImageAnimationPolicyAllowed),
all_data_received_(false),
have_size_(false),
+ preferred_size_is_transposed_(false),
size_available_(false),
have_frame_count_(false),
repetition_count_status_(kUnknown),
@@ -93,6 +95,15 @@ scoped_refptr<SharedBuffer> BitmapImage::Data() {
return decoder_ ? decoder_->Data() : nullptr;
}
+bool BitmapImage::HasData() const {
+ return decoder_ ? decoder_->HasData() : false;
+}
+
+size_t BitmapImage::DataSize() const {
+ DCHECK(decoder_);
+ return decoder_->DataSize();
+}
+
void BitmapImage::NotifyMemoryChanged() {
if (GetImageObserver())
GetImageObserver()->DecodedSizeChangedTo(this, TotalFrameBytes());
@@ -130,29 +141,23 @@ PaintImage BitmapImage::CreatePaintImage() {
}
void BitmapImage::UpdateSize() const {
- if (!size_available_ || have_size_ || !decoder_)
+ if (have_size_ || !size_available_ || !decoder_)
return;
-
size_ = decoder_->FrameSizeAtIndex(0);
density_corrected_size_ = decoder_->DensityCorrectedSizeAtIndex(0);
- if (decoder_->OrientationAtIndex(0).UsesWidthAsHeight()) {
- size_respecting_orientation_ = size_.TransposedSize();
- density_corrected_size_respecting_orientation_ =
- density_corrected_size_.TransposedSize();
- } else {
- size_respecting_orientation_ = size_;
- density_corrected_size_respecting_orientation_ = density_corrected_size_;
- }
+ preferred_size_is_transposed_ =
+ decoder_->OrientationAtIndex(0).UsesWidthAsHeight();
have_size_ = true;
}
-IntSize BitmapImage::Size() const {
+IntSize BitmapImage::SizeWithConfig(SizeConfig config) const {
UpdateSize();
- return size_;
-}
-
-IntSize BitmapImage::DensityCorrectedSize() const {
- return density_corrected_size_.IsEmpty() ? Size() : density_corrected_size_;
+ IntSize size = size_;
+ if (config.apply_density && !density_corrected_size_.IsEmpty())
+ size = density_corrected_size_;
+ if (config.apply_orientation && preferred_size_is_transposed_)
+ return size.TransposedSize();
+ return size;
}
void BitmapImage::RecordDecodedImageType(UseCounter* use_counter) {
@@ -160,18 +165,6 @@ void BitmapImage::RecordDecodedImageType(UseCounter* use_counter) {
use_counter);
}
-IntSize BitmapImage::PreferredDisplaySize() const {
- UpdateSize();
- if (!density_corrected_size_respecting_orientation_.IsEmpty())
- return density_corrected_size_respecting_orientation_;
- return size_respecting_orientation_;
-}
-
-bool BitmapImage::HasDefaultOrientation() const {
- ImageOrientation orientation = CurrentFrameOrientation();
- return orientation == ImageOrientationEnum::kDefault;
-}
-
bool BitmapImage::GetHotSpot(IntPoint& hot_spot) const {
return decoder_ && decoder_->HotSpot(hot_spot);
}
@@ -194,7 +187,7 @@ Image::SizeAvailability BitmapImage::SetData(scoped_refptr<SharedBuffer> data,
if (!data)
return kSizeAvailable;
- int length = data->size();
+ size_t length = data->size();
if (!length)
return kSizeAvailable;
@@ -257,15 +250,13 @@ String BitmapImage::FilenameExtension() const {
return decoder_ ? decoder_->FilenameExtension() : String();
}
-void BitmapImage::Draw(
- cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- const SkSamplingOptions& sampling,
- RespectImageOrientationEnum should_respect_image_orientation,
- ImageClampingMode clamp_mode,
- ImageDecodingMode decode_mode) {
+void BitmapImage::Draw(cc::PaintCanvas* canvas,
+ const PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ const ImageDrawOptions& draw_options,
+ ImageClampingMode clamp_mode,
+ ImageDecodingMode decode_mode) {
TRACE_EVENT0("skia", "BitmapImage::draw");
PaintImage image = PaintImageForCurrentFrame();
@@ -293,7 +284,7 @@ void BitmapImage::Draw(
return; // Nothing to draw.
ImageOrientation orientation = ImageOrientationEnum::kDefault;
- if (should_respect_image_orientation == kRespectImageOrientation)
+ if (draw_options.respect_image_orientation == kRespectImageOrientation)
orientation = CurrentFrameOrientation();
PaintCanvasAutoRestore auto_restore(canvas, false);
@@ -321,7 +312,7 @@ void BitmapImage::Draw(
uint32_t stable_id = image.stable_id();
bool is_lazy_generated = image.IsLazyGenerated();
canvas->drawImageRect(std::move(image), adjusted_src_rect, adjusted_dst_rect,
- sampling, &flags,
+ draw_options.sampling_options, &flags,
WebCoreClampingModeToSkiaRectConstraint(clamp_mode));
if (is_lazy_generated) {
@@ -402,9 +393,7 @@ bool BitmapImage::CurrentFrameKnownToBeOpaque() {
}
bool BitmapImage::CurrentFrameIsComplete() {
- return decoder_
- ? decoder_->FrameIsReceivedAtIndex(PaintImage::kDefaultFrameIndex)
- : false;
+ return decoder_ && decoder_->FrameIsReceivedAtIndex(0);
}
bool BitmapImage::CurrentFrameIsLazyDecoded() {
@@ -413,16 +402,10 @@ bool BitmapImage::CurrentFrameIsLazyDecoded() {
}
ImageOrientation BitmapImage::CurrentFrameOrientation() const {
- return decoder_ ? decoder_->OrientationAtIndex(PaintImage::kDefaultFrameIndex)
+ return decoder_ ? decoder_->OrientationAtIndex(0)
: ImageOrientationEnum::kDefault;
}
-IntSize BitmapImage::CurrentFrameDensityCorrectedSize() const {
- return decoder_ ? decoder_->DensityCorrectedSizeAtIndex(
- PaintImage::kDefaultFrameIndex)
- : IntSize();
-}
-
int BitmapImage::RepetitionCount() {
if ((repetition_count_status_ == kUnknown) ||
((repetition_count_status_ == kUncertain) && all_data_received_)) {
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 8c8077c91b3..073966fb978 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
@@ -30,10 +30,8 @@
#include <memory>
#include "base/memory/weak_ptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/image-decoders/image_animation.h"
@@ -66,9 +64,7 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
bool CurrentFrameHasSingleSecurityOrigin() const override;
- IntSize Size() const override;
- IntSize PreferredDisplaySize() const override;
- bool HasDefaultOrientation() const override;
+ IntSize SizeWithConfig(SizeConfig) const override;
bool GetHotSpot(IntPoint&) const override;
String FilenameExtension() const override;
@@ -97,7 +93,6 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
size_t FrameCount() override;
PaintImage PaintImageForCurrentFrame() override;
ImageOrientation CurrentFrameOrientation() const override;
- IntSize CurrentFrameDensityCorrectedSize() const override;
PaintImage PaintImageForTesting();
void AdvanceAnimationForTesting() override {
@@ -107,8 +102,6 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
decoder_ = std::move(decoder);
}
- IntSize DensityCorrectedSize() const override;
-
// Records the decoded image type in a UseCounter. |use_counter| may be a null
// pointer.
void RecordDecodedImageType(UseCounter* use_counter);
@@ -137,8 +130,7 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
@@ -151,6 +143,8 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
void DestroyDecodedData() override;
scoped_refptr<SharedBuffer> Data() override;
+ bool HasData() const override;
+ size_t DataSize() const override;
// Notifies observers that the memory footprint has changed.
void NotifyMemoryChanged();
@@ -164,9 +158,7 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
std::unique_ptr<DeferredImageDecoder> decoder_;
mutable IntSize size_; // The size to use for the overall image (will just
// be the size of the first image).
- mutable IntSize size_respecting_orientation_;
mutable IntSize density_corrected_size_;
- mutable IntSize density_corrected_size_respecting_orientation_;
// This caches the PaintImage created with the last updated encoded data to
// ensure re-use of generated decodes. This is cleared each time the encoded
@@ -180,6 +172,8 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
bool all_data_received_ : 1; // Whether we've received all our data.
mutable bool have_size_ : 1; // Whether our |m_size| member variable has the
// final overall image size yet.
+ mutable bool preferred_size_is_transposed_ : 1; // Whether the preferred size
+ // uses width as height.
bool size_available_ : 1; // Whether we can obtain the size of the first
// image frame from ImageIO yet.
bool have_frame_count_ : 1;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
index 1674683cf77..d639e36fbfe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
@@ -76,7 +76,7 @@ void BitmapImageMetrics::CountImageJpegDensity(int image_min_side,
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, density_histogram,
("Blink.DecodedImage.JpegDensity.KiBWeighted", 1, 1000, 100));
- int image_size_kib = (image_size_bytes + 512) / 1024;
+ int image_size_kib = static_cast<int>((image_size_bytes + 512) / 1024);
if (image_size_kib > 0) {
density_histogram.CountMany(
base::saturated_cast<base::Histogram::Sample>(density_centi_bpp),
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 3160e012c17..7fd3d4415cd 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
@@ -103,6 +103,10 @@ class TestingPlatformSupportWithMaxDecodedBytes
: public TestingPlatformSupportWithMockScheduler {
public:
TestingPlatformSupportWithMaxDecodedBytes() {}
+ TestingPlatformSupportWithMaxDecodedBytes(
+ const TestingPlatformSupportWithMaxDecodedBytes&) = delete;
+ TestingPlatformSupportWithMaxDecodedBytes& operator=(
+ const TestingPlatformSupportWithMaxDecodedBytes&) = delete;
~TestingPlatformSupportWithMaxDecodedBytes() override {}
void SetMaxDecodedImageBytes(size_t max_decoded_image_bytes) {
@@ -113,8 +117,6 @@ class TestingPlatformSupportWithMaxDecodedBytes
private:
size_t max_decoded_image_bytes_ = Platform::kNoDecodedImageByteLimit;
-
- DISALLOW_COPY_AND_ASSIGN(TestingPlatformSupportWithMaxDecodedBytes);
};
class BitmapImageTest : public testing::Test {
@@ -610,19 +612,19 @@ class BitmapImageTestWithMockDecoder : public BitmapImageTest,
void DecoderBeingDestroyed() override {}
void DecodeRequested() override {}
- ImageFrame::Status GetStatus(size_t index) override {
+ ImageFrame::Status GetStatus(wtf_size_t index) override {
if (index < frame_count_ - 1 || last_frame_complete_)
return ImageFrame::Status::kFrameComplete;
return ImageFrame::Status::kFramePartial;
}
- size_t FrameCount() override { return frame_count_; }
+ wtf_size_t FrameCount() override { return frame_count_; }
int RepetitionCount() const override { return repetition_count_; }
base::TimeDelta FrameDuration() const override { return duration_; }
protected:
base::TimeDelta duration_;
int repetition_count_;
- size_t frame_count_;
+ wtf_size_t frame_count_;
bool last_frame_complete_;
};
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 9e1702e0eb7..32e39312a3a 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
@@ -258,7 +258,7 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider() {
// Calling to DidDraw because GetOrCreateResourceProvider created a new
// provider and cleared it
// TODO crbug/1090081: Check possibility to move DidDraw inside Clear.
- DidDraw(FloatRect(0.f, 0.f, size_.Width(), size_.Height()));
+ DidDraw();
if (IsAccelerated() && !layer_) {
layer_ = cc::TextureLayer::CreateForMailbox(this);
@@ -267,7 +267,7 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider() {
layer_->SetContentsOpaque(ColorParams().GetOpacityMode() == kOpaque);
layer_->SetBlendBackgroundColor(ColorParams().GetOpacityMode() != kOpaque);
layer_->SetNearestNeighbor(resource_host_->FilterQuality() ==
- kNone_SkFilterQuality);
+ cc::PaintFlags::FilterQuality::kNone);
}
if (!IsHibernating())
@@ -307,11 +307,13 @@ cc::PaintCanvas* Canvas2DLayerBridge::GetPaintCanvas() {
return ResourceProvider()->Canvas();
}
-void Canvas2DLayerBridge::SetFilterQuality(SkFilterQuality filter_quality) {
+void Canvas2DLayerBridge::SetFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) {
if (CanvasResourceProvider* resource_provider = ResourceProvider())
resource_provider->SetFilterQuality(filter_quality);
if (layer_)
- layer_->SetNearestNeighbor(filter_quality == kNone_SkFilterQuality);
+ layer_->SetNearestNeighbor(filter_quality ==
+ cc::PaintFlags::FilterQuality::kNone);
}
void Canvas2DLayerBridge::SetIsInHiddenPage(bool hidden) {
@@ -637,7 +639,7 @@ cc::Layer* Canvas2DLayerBridge::Layer() {
return layer_.get();
}
-void Canvas2DLayerBridge::DidDraw(const FloatRect& /* rect */) {
+void Canvas2DLayerBridge::DidDraw() {
if (ResourceProvider() && ResourceProvider()->needs_flush())
FinalizeFrame();
have_recorded_draw_commands_ = true;
@@ -669,9 +671,9 @@ void Canvas2DLayerBridge::FinalizeFrame() {
rate_limiter_->Tick();
}
-void Canvas2DLayerBridge::DoPaintInvalidation(const FloatRect& dirty_rect) {
+void Canvas2DLayerBridge::DoPaintInvalidation(const IntRect& dirty_rect) {
if (layer_ && raster_mode_ == RasterMode::kGPU)
- layer_->SetNeedsDisplayRect(EnclosingIntRect(dirty_rect));
+ layer_->SetNeedsDisplayRect(dirty_rect);
}
scoped_refptr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot() {
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 175b8e245b2..9511c36f003 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
@@ -30,7 +30,6 @@
#include <random>
#include <utility>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/checked_math.h"
@@ -76,6 +75,8 @@ class StaticBitmapImage;
class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
public:
Canvas2DLayerBridge(const IntSize&, RasterMode, const CanvasColorParams&);
+ Canvas2DLayerBridge(const Canvas2DLayerBridge&) = delete;
+ Canvas2DLayerBridge& operator=(const Canvas2DLayerBridge&) = delete;
~Canvas2DLayerBridge() override;
@@ -88,9 +89,9 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
void FinalizeFrame();
void SetIsInHiddenPage(bool);
void SetIsBeingDisplayed(bool);
- void SetFilterQuality(SkFilterQuality filter_quality);
- void DidDraw(const FloatRect&);
- void DoPaintInvalidation(const FloatRect& dirty_rect);
+ void SetFilterQuality(cc::PaintFlags::FilterQuality filter_quality);
+ void DidDraw();
+ void DoPaintInvalidation(const IntRect& dirty_rect);
cc::Layer* Layer();
bool Restore();
@@ -231,8 +232,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
sk_sp<cc::PaintRecord> last_recording_;
base::WeakPtrFactory<Canvas2DLayerBridge> weak_ptr_factory_{this};
-
- 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 aef538207fc..d05554dd917 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
@@ -94,9 +94,9 @@ class ImageTrackingDecodeCache : public cc::StubDecodeCache {
bitmap.allocPixelsFlags(SkImageInfo::MakeN32Premul(10, 10),
SkBitmap::kZeroPixels_AllocFlag);
sk_sp<SkImage> sk_image = SkImage::MakeFromBitmap(bitmap);
- return cc::DecodedDrawImage(sk_image, nullptr, SkSize::Make(0, 0),
- SkSize::Make(1, 1), kLow_SkFilterQuality,
- !budget_exceeded_);
+ return cc::DecodedDrawImage(
+ sk_image, nullptr, SkSize::Make(0, 0), SkSize::Make(1, 1),
+ cc::PaintFlags::FilterQuality::kLow, !budget_exceeded_);
}
void set_budget_exceeded(bool exceeded) { budget_exceeded_ = exceeded; }
@@ -341,7 +341,7 @@ TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareIfContextLost) {
}
void DrawSomething(Canvas2DLayerBridge* bridge) {
- bridge->DidDraw(FloatRect(0, 0, 1, 1));
+ bridge->DidDraw();
bridge->FinalizeFrame();
// Grabbing an image forces a flush
bridge->NewImageSnapshot();
@@ -820,11 +820,12 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
gfx::ColorSpace expected_color_space = gfx::ColorSpace::CreateSRGB();
Vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
- SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, SkM44(), 0u,
+ SkIRect::MakeWH(10, 10),
+ cc::PaintFlags::FilterQuality::kNone, SkM44(), 0u,
expected_color_space),
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
- SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkM44(), 0u,
- expected_color_space)};
+ SkIRect::MakeWH(5, 5), cc::PaintFlags::FilterQuality::kNone,
+ SkM44(), 0u, expected_color_space)};
bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u);
bridge->GetPaintCanvas()->drawImageRect(
@@ -842,11 +843,12 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) {
MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
Vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
- SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, SkM44(), 0u,
+ SkIRect::MakeWH(10, 10),
+ cc::PaintFlags::FilterQuality::kNone, SkM44(), 0u,
color_params.GetStorageGfxColorSpace()),
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
- SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkM44(), 0u,
- color_params.GetStorageGfxColorSpace())};
+ SkIRect::MakeWH(5, 5), cc::PaintFlags::FilterQuality::kNone,
+ SkM44(), 0u, color_params.GetStorageGfxColorSpace())};
bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u);
bridge->GetPaintCanvas()->drawImageRect(
@@ -865,14 +867,15 @@ TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
Vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
- SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, SkM44(), 0u,
+ SkIRect::MakeWH(10, 10),
+ cc::PaintFlags::FilterQuality::kNone, SkM44(), 0u,
color_params.GetStorageGfxColorSpace()),
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
- SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkM44(), 0u,
- color_params.GetStorageGfxColorSpace()),
+ SkIRect::MakeWH(5, 5), cc::PaintFlags::FilterQuality::kNone,
+ SkM44(), 0u, color_params.GetStorageGfxColorSpace()),
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
- SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkM44(), 0u,
- color_params.GetStorageGfxColorSpace())};
+ SkIRect::MakeWH(5, 5), cc::PaintFlags::FilterQuality::kNone,
+ SkM44(), 0u, color_params.GetStorageGfxColorSpace())};
// First 2 images are budgeted, they should remain locked after the op.
bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u);
@@ -898,10 +901,10 @@ TEST_F(Canvas2DLayerBridgeTest, QueuesCleanupTaskForLockedImages) {
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
- auto image =
- cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
- SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, SkM44(), 0u,
- color_params.GetStorageGfxColorSpace());
+ auto image = cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+ false, SkIRect::MakeWH(10, 10),
+ cc::PaintFlags::FilterQuality::kNone, SkM44(), 0u,
+ color_params.GetStorageGfxColorSpace());
bridge->GetPaintCanvas()->drawImage(image.paint_image(), 0u, 0u);
bridge->GetOrCreateResourceProvider()->FlushCanvas();
@@ -918,11 +921,12 @@ TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
Vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
- SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, SkM44(), 0u,
+ SkIRect::MakeWH(10, 10),
+ cc::PaintFlags::FilterQuality::kNone, SkM44(), 0u,
color_params.GetStorageGfxColorSpace()),
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
- SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkM44(), 0u,
- color_params.GetStorageGfxColorSpace())};
+ SkIRect::MakeWH(5, 5), cc::PaintFlags::FilterQuality::kNone,
+ SkM44(), 0u, color_params.GetStorageGfxColorSpace())};
bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u);
// Lose the context and ensure that the image provider is not used.
@@ -979,7 +983,7 @@ TEST_F(Canvas2DLayerBridgeTest, WritePixelsRestoresClipStack) {
5);
// Drawline so WritePixels has something to flush
bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
- bridge->DidDraw(FloatRect(0, 0, 1, 1));
+ bridge->DidDraw();
// WritePixels flushes recording. Post flush, a new drawing canvas is created
// that should have the matrix restored onto it.
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 628c6bca129..94ca8fd7521 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
@@ -24,14 +24,11 @@ gfx::ColorSpace CanvasColorSpaceToGfxColorSpace(CanvasColorSpace color_space) {
switch (color_space) {
case CanvasColorSpace::kSRGB:
return gfx::ColorSpace::CreateSRGB();
- break;
case CanvasColorSpace::kRec2020:
return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT2020,
gfx::ColorSpace::TransferID::GAMMA24);
- break;
case CanvasColorSpace::kP3:
return gfx::ColorSpace::CreateDisplayP3D65();
- break;
}
NOTREACHED();
}
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 57ac2e875f5..46c58065274 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -39,7 +39,7 @@
namespace blink {
CanvasResource::CanvasResource(base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params)
: owning_thread_ref_(base::PlatformThread::CurrentRef()),
owning_thread_task_runner_(Thread::Current()->GetTaskRunner()),
@@ -193,7 +193,8 @@ SkImageInfo CanvasResource::CreateSkImageInfo() const {
}
GLenum CanvasResource::GLFilter() const {
- return filter_quality_ == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
+ return filter_quality_ == cc::PaintFlags::FilterQuality::kNone ? GL_NEAREST
+ : GL_LINEAR;
}
// CanvasResourceSharedBitmap
@@ -203,7 +204,7 @@ CanvasResourceSharedBitmap::CanvasResourceSharedBitmap(
const IntSize& size,
const CanvasResourceParams& params,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality)
+ cc::PaintFlags::FilterQuality filter_quality)
: CanvasResource(std::move(provider), filter_quality, params), size_(size) {
// Software compositing lazily uses RGBA_8888 as the resource format
// everywhere but the content is expected to be rendered in N32 format.
@@ -264,7 +265,7 @@ scoped_refptr<CanvasResourceSharedBitmap> CanvasResourceSharedBitmap::Create(
const IntSize& size,
const CanvasResourceParams& params,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
auto resource = AdoptRef(new CanvasResourceSharedBitmap(
size, params, std::move(provider), filter_quality));
return resource->IsValid() ? resource : nullptr;
@@ -312,7 +313,7 @@ void CanvasResourceSharedBitmap::TakeSkImage(sk_sp<SkImage> image) {
CanvasResourceSharedImage::CanvasResourceSharedImage(
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params)
: CanvasResource(provider, filter_quality, params) {}
@@ -323,7 +324,7 @@ CanvasResourceRasterSharedImage::CanvasResourceRasterSharedImage(
const IntSize& size,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
bool is_origin_top_left,
bool is_accelerated,
@@ -354,7 +355,8 @@ CanvasResourceRasterSharedImage::CanvasResourceRasterSharedImage(
context_provider_wrapper_->ContextProvider()
->GetCapabilities())
: GL_TEXTURE_2D),
- use_oop_rasterization_(context_provider_wrapper_->ContextProvider()
+ use_oop_rasterization_(is_accelerated &&
+ context_provider_wrapper_->ContextProvider()
->GetCapabilities()
.supports_oop_raster) {
auto* gpu_memory_buffer_manager =
@@ -420,13 +422,14 @@ CanvasResourceRasterSharedImage::CanvasResourceRasterSharedImage(
if (use_oop_rasterization_)
return;
- owning_thread_data().texture_id_for_read_access =
- raster_interface->CreateAndConsumeForGpuRaster(shared_image_mailbox);
-
// For the non-accelerated case, writes are done on the CPU. So we don't need
- // a texture for writes.
+ // a texture for reads or writes.
if (!is_accelerated_)
return;
+
+ owning_thread_data().texture_id_for_read_access =
+ raster_interface->CreateAndConsumeForGpuRaster(shared_image_mailbox);
+
if (shared_image_usage_flags &
gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE) {
owning_thread_data().texture_id_for_write_access =
@@ -442,7 +445,7 @@ CanvasResourceRasterSharedImage::Create(
const IntSize& size,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
bool is_origin_top_left,
bool is_accelerated,
@@ -727,7 +730,7 @@ CanvasResourceSkiaDawnSharedImage::CanvasResourceSkiaDawnSharedImage(
const IntSize& size,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
bool is_origin_top_left,
uint32_t shared_image_usage_flags)
@@ -776,7 +779,7 @@ CanvasResourceSkiaDawnSharedImage::Create(
const IntSize& size,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
bool is_origin_top_left,
uint32_t shared_image_usage_flags) {
@@ -849,7 +852,7 @@ void CanvasResourceSkiaDawnSharedImage::BeginAccess() {
webgpu->AssociateMailbox(
reservation.deviceId, reservation.deviceGeneration,
owning_thread_data().id, owning_thread_data().generation,
- WGPUTextureUsage_Sampled | WGPUTextureUsage_RenderAttachment,
+ WGPUTextureUsage_TextureBinding | WGPUTextureUsage_RenderAttachment,
reinterpret_cast<GLbyte*>(&owning_thread_data().shared_image_mailbox));
}
@@ -1042,7 +1045,7 @@ scoped_refptr<ExternalCanvasResource> ExternalCanvasResource::Create(
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
bool is_origin_top_left,
bool is_overlay_candidate) {
TRACE_EVENT0("blink", "ExternalCanvasResource::Create");
@@ -1142,7 +1145,7 @@ ExternalCanvasResource::ExternalCanvasResource(
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
bool is_origin_top_left,
bool is_overlay_candidate)
: CanvasResource(std::move(provider), filter_quality, params),
@@ -1164,7 +1167,7 @@ scoped_refptr<CanvasResourceSwapChain> CanvasResourceSwapChain::Create(
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
TRACE_EVENT0("blink", "CanvasResourceSwapChain::Create");
auto resource = AdoptRef(new CanvasResourceSwapChain(
size, params, std::move(context_provider_wrapper), std::move(provider),
@@ -1295,7 +1298,7 @@ CanvasResourceSwapChain::CanvasResourceSwapChain(
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality)
+ cc::PaintFlags::FilterQuality filter_quality)
: CanvasResource(std::move(provider), filter_quality, params),
context_provider_wrapper_(std::move(context_provider_wrapper)),
size_(size),
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 2d0d07e2d36..59f10388b71 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -142,9 +142,13 @@ class PLATFORM_EXPORT CanvasResource
// should not be recycled for writing again but can be safely read from.
virtual void NotifyResourceLost() = 0;
- void SetFilterQuality(SkFilterQuality filter) { filter_quality_ = filter; }
+ void SetFilterQuality(cc::PaintFlags::FilterQuality filter) {
+ filter_quality_ = filter;
+ }
// The filter quality to use when the resource is drawn by the compositor.
- SkFilterQuality FilterQuality() const { return filter_quality_; }
+ cc::PaintFlags::FilterQuality FilterQuality() const {
+ return filter_quality_;
+ }
SkImageInfo CreateSkImageInfo() const;
@@ -159,7 +163,7 @@ class PLATFORM_EXPORT CanvasResource
protected:
CanvasResource(base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&);
// Called during resource destruction if the resource is destroyed on a thread
@@ -212,7 +216,7 @@ class PLATFORM_EXPORT CanvasResource
gpu::SyncToken sync_token_for_release_;
base::WeakPtr<CanvasResourceProvider> provider_;
// TODO(https://crbug.com/1157747): Merge |filter_quality_| into |params_|.
- SkFilterQuality filter_quality_;
+ cc::PaintFlags::FilterQuality filter_quality_;
CanvasResourceParams params_;
#if DCHECK_IS_ON()
bool did_call_on_destroy_ = false;
@@ -226,7 +230,7 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
const IntSize&,
const CanvasResourceParams&,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality);
+ cc::PaintFlags::FilterQuality);
~CanvasResourceSharedBitmap() override;
bool IsRecycleable() const final { return IsValid(); }
bool IsAccelerated() const final { return false; }
@@ -249,7 +253,7 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
CanvasResourceSharedBitmap(const IntSize&,
const CanvasResourceParams&,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality);
+ cc::PaintFlags::FilterQuality);
viz::SharedBitmapId shared_bitmap_id_;
base::WritableSharedMemoryMapping shared_mapping_;
@@ -272,7 +276,7 @@ class PLATFORM_EXPORT CanvasResourceSharedImage : public CanvasResource {
protected:
CanvasResourceSharedImage(base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&);
};
@@ -284,7 +288,7 @@ class PLATFORM_EXPORT CanvasResourceRasterSharedImage final
const IntSize&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&,
bool is_origin_top_left,
bool is_accelerated,
@@ -371,7 +375,7 @@ class PLATFORM_EXPORT CanvasResourceRasterSharedImage final
const IntSize&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&,
bool is_origin_top_left,
bool is_accelerated,
@@ -429,7 +433,7 @@ class PLATFORM_EXPORT CanvasResourceSkiaDawnSharedImage final
const IntSize&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&,
bool is_origin_top_left,
uint32_t shared_image_usage_flags);
@@ -502,7 +506,7 @@ class PLATFORM_EXPORT CanvasResourceSkiaDawnSharedImage final
const IntSize&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&,
bool is_origin_top_left,
uint32_t shared_image_usage_flags);
@@ -566,7 +570,7 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource {
const CanvasResourceParams&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
bool is_origin_top_left,
bool is_overlay_candidate);
@@ -603,7 +607,7 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource {
const CanvasResourceParams&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
bool is_origin_top_left,
bool is_overlay_candidate);
@@ -628,7 +632,7 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource {
const CanvasResourceParams&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality);
+ cc::PaintFlags::FilterQuality);
~CanvasResourceSwapChain() override;
bool IsRecycleable() const final { return IsValid(); }
bool IsAccelerated() const final { return true; }
@@ -667,7 +671,7 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource {
const CanvasResourceParams&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality);
+ cc::PaintFlags::FilterQuality);
const base::WeakPtr<WebGraphicsContext3DProviderWrapper>
context_provider_wrapper_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
index 8952fa0361b..7bf8efb9a21 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -249,7 +249,7 @@ bool CanvasResourceDispatcher::PrepareFrame(
auto frame_resource = std::make_unique<FrameResource>();
bool nearest_neighbor =
- canvas_resource->FilterQuality() == kNone_SkFilterQuality;
+ canvas_resource->FilterQuality() == cc::PaintFlags::FilterQuality::kNone;
canvas_resource->PrepareTransferableResource(
&resource, &frame_resource->release_callback, kVerifiedSyncToken);
@@ -439,7 +439,7 @@ void CanvasResourceDispatcher::DidDeleteSharedBitmap(const gpu::Mailbox& id) {
}
void CanvasResourceDispatcher::SetFilterQuality(
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
if (Client())
Client()->SetFilterQualityInResource(filter_quality);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
index 212f6aae43b..f32723db063 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/memory/read_only_shared_memory_region.h"
+#include "cc/paint/paint_flags.h"
#include "components/power_scheduler/power_mode_voter.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/resources/resource_id.h"
@@ -27,7 +28,8 @@ class CanvasResource;
class CanvasResourceDispatcherClient {
public:
virtual bool BeginFrame() = 0;
- virtual void SetFilterQualityInResource(SkFilterQuality filter_quality) = 0;
+ virtual void SetFilterQualityInResource(
+ cc::PaintFlags::FilterQuality filter_quality) = 0;
};
class PLATFORM_EXPORT CanvasResourceDispatcher
@@ -87,7 +89,7 @@ class PLATFORM_EXPORT CanvasResourceDispatcher
const gpu::Mailbox& id);
void DidDeleteSharedBitmap(const gpu::Mailbox& id);
- void SetFilterQuality(SkFilterQuality filter_quality);
+ void SetFilterQuality(cc::PaintFlags::FilterQuality filter_quality);
void SetPlaceholderCanvasDispatcher(int placeholder_canvas_id);
private:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc
index 03f9d5dbca9..931bac6d91c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc
@@ -94,7 +94,8 @@ class CanvasResourceDispatcherTest
void CreateCanvasResourceDispatcher() {
dispatcher_ = std::make_unique<MockCanvasResourceDispatcher>();
resource_provider_ = CanvasResourceProvider::CreateSharedBitmapProvider(
- IntSize(kWidth, kHeight), kLow_SkFilterQuality, CanvasResourceParams(),
+ IntSize(kWidth, kHeight), cc::PaintFlags::FilterQuality::kLow,
+ CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kCallClear,
dispatcher_->GetWeakPtr());
}
@@ -225,7 +226,7 @@ TEST_P(CanvasResourceDispatcherTest, DispatchFrame) {
auto canvas_resource = CanvasResourceSharedBitmap::Create(
GetSize(), CanvasResourceParams(), nullptr /* provider */,
- kLow_SkFilterQuality);
+ cc::PaintFlags::FilterQuality::kLow);
EXPECT_TRUE(!!canvas_resource);
EXPECT_EQ(canvas_resource->Size(), GetSize());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
index fcb3fee6cea..fc56ededce2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
@@ -44,7 +44,8 @@ void CanvasResourceHost::InitializeForRecording(cc::PaintCanvas* canvas) {
RestoreCanvasMatrixClipStack(canvas);
}
-void CanvasResourceHost::SetFilterQuality(SkFilterQuality filter_quality) {
+void CanvasResourceHost::SetFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) {
filter_quality_ = filter_quality;
}
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 54248cffe42..1ec45695522 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
@@ -25,13 +25,16 @@ class PLATFORM_EXPORT CanvasResourceHost {
virtual void SetNeedsCompositingUpdate() = 0;
virtual void RestoreCanvasMatrixClipStack(cc::PaintCanvas*) const = 0;
virtual void UpdateMemoryUsage() = 0;
+ virtual size_t GetMemoryUsage() const = 0;
virtual CanvasResourceProvider* GetOrCreateCanvasResourceProvider(
RasterModeHint hint) = 0;
virtual CanvasResourceProvider* GetOrCreateCanvasResourceProviderImpl(
RasterModeHint hint) = 0;
- virtual void SetFilterQuality(SkFilterQuality filter_quality);
- SkFilterQuality FilterQuality() const { return filter_quality_; }
+ virtual void SetFilterQuality(cc::PaintFlags::FilterQuality filter_quality);
+ cc::PaintFlags::FilterQuality FilterQuality() const {
+ return filter_quality_;
+ }
virtual bool LowLatencyEnabled() const { return false; }
CanvasResourceProvider* ResourceProvider() const;
@@ -47,7 +50,8 @@ class PLATFORM_EXPORT CanvasResourceHost {
void InitializeForRecording(cc::PaintCanvas* canvas);
std::unique_ptr<CanvasResourceProvider> resource_provider_;
- SkFilterQuality filter_quality_ = kLow_SkFilterQuality;
+ cc::PaintFlags::FilterQuality filter_quality_ =
+ cc::PaintFlags::FilterQuality::kLow;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc
index 5e67058c90b..5f8f48898cc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc
@@ -24,14 +24,11 @@ gfx::ColorSpace CanvasColorSpaceToGfxColorSpace(CanvasColorSpace color_space) {
switch (color_space) {
case CanvasColorSpace::kSRGB:
return gfx::ColorSpace::CreateSRGB();
- break;
case CanvasColorSpace::kRec2020:
return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT2020,
gfx::ColorSpace::TransferID::GAMMA24);
- break;
case CanvasColorSpace::kP3:
return gfx::ColorSpace::CreateDisplayP3D65();
- break;
}
NOTREACHED();
}
@@ -53,8 +50,7 @@ CanvasResourceParams::CanvasResourceParams(const SkImageInfo& info)
}
SkSurfaceProps CanvasResourceParams::GetSkSurfaceProps() const {
- bool can_use_lcd_text = (alpha_type_ == kOpaque_SkAlphaType);
- return skia::LegacyDisplayGlobals::ComputeSurfaceProps(can_use_lcd_text);
+ return skia::LegacyDisplayGlobals::ComputeSurfaceProps(CanUseLcdText());
}
uint8_t CanvasResourceParams::BytesPerPixel() const {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.h
index 53b39b29f2f..42550e5e4a4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_params.h
@@ -53,6 +53,10 @@ class PLATFORM_EXPORT CanvasResourceParams {
sk_sp<SkColorSpace> GetSkColorSpace() const;
SkAlphaType GetSkAlphaType() const { return alpha_type_; }
SkSurfaceProps GetSkSurfaceProps() const;
+ bool CanUseLcdText() const {
+ // LCD text is safe when canvas is guaranteed not to be semi-transparent.
+ return alpha_type_ == kOpaque_SkAlphaType;
+ }
// Gpu memory buffer parameters
gfx::BufferFormat GetBufferFormat() const;
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 07fa65f6120..44676067197 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,7 +6,6 @@
#include "base/bind.h"
#include "base/metrics/histogram_functions.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
@@ -74,7 +73,8 @@ bool IsGMBAllowed(IntSize size,
const CanvasResourceParams& params,
const gpu::Capabilities& caps) {
return gpu::IsImageSizeValidForGpuMemoryBufferFormat(
- gfx::Size(size), params.GetBufferFormat()) &&
+ gfx::Size(size), params.GetBufferFormat(),
+ gfx::BufferPlane::DEFAULT) &&
gpu::IsImageFromGpuMemoryBufferFormatSupported(
params.GetBufferFormat(), caps);
}
@@ -88,6 +88,8 @@ class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider {
const gfx::ColorSpace& target_color_space,
SkColorType target_color_type,
cc::PlaybackImageProvider::RasterMode raster_mode);
+ CanvasImageProvider(const CanvasImageProvider&) = delete;
+ CanvasImageProvider& operator=(const CanvasImageProvider&) = delete;
~CanvasImageProvider() override = default;
// cc::ImageProvider implementation.
@@ -108,8 +110,6 @@ class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider {
absl::optional<cc::PlaybackImageProvider> playback_image_provider_f16_;
base::WeakPtrFactory<CanvasImageProvider> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(CanvasImageProvider);
};
// * Renders to a Skia RAM-backed bitmap.
@@ -118,7 +118,7 @@ class CanvasResourceProviderBitmap : public CanvasResourceProvider {
public:
CanvasResourceProviderBitmap(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: CanvasResourceProvider(kBitmap,
@@ -163,7 +163,7 @@ class CanvasResourceProviderSharedBitmap : public CanvasResourceProviderBitmap {
public:
CanvasResourceProviderSharedBitmap(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: CanvasResourceProviderBitmap(size,
@@ -212,7 +212,7 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
public:
CanvasResourceProviderSharedImage(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
context_provider_wrapper,
@@ -224,16 +224,7 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
skia_use_dawn ? kSkiaDawnSharedImage : kSharedImage,
size,
filter_quality,
- // TODO(khushalsagar): The software path seems to be assuming N32
- // somewhere in the later pipeline but for offscreen canvas only.
- // TODO(https://crbug.com/1157747): This is RGBA, but the above
- // comment suggests N32. See if this can be N32.
- CanvasResourceParams(params.ColorSpace(),
- is_accelerated && params.GetSkColorType() !=
- kRGBA_F16_SkColorType
- ? kRGBA_8888_SkColorType
- : params.GetSkColorType(),
- params.GetSkAlphaType()),
+ params,
is_origin_top_left,
std::move(context_provider_wrapper),
nullptr /* resource_dispatcher */),
@@ -282,6 +273,10 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
return resource()->TextureTarget();
}
+ uint32_t GetSharedImageUsageFlags() const override {
+ return shared_image_usage_flags_;
+ }
+
bool WritePixels(const SkImageInfo& orig_info,
const void* pixels,
size_t row_bytes,
@@ -299,7 +294,8 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
WillDrawInternal(true);
RasterInterface()->WritePixels(
GetBackingMailboxForOverwrite(kOrderingBarrier), x, y,
- GetBackingTextureTarget(), row_bytes, orig_info, pixels);
+ GetBackingTextureTarget(), base::checked_cast<GLuint>(row_bytes),
+ orig_info, pixels);
return true;
}
@@ -674,7 +670,7 @@ class CanvasResourceProviderPassThrough final : public CanvasResourceProvider {
public:
CanvasResourceProviderPassThrough(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
context_provider_wrapper,
@@ -727,7 +723,7 @@ class CanvasResourceProviderSwapChain final : public CanvasResourceProvider {
public:
CanvasResourceProviderSwapChain(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
context_provider_wrapper,
@@ -860,9 +856,9 @@ class CanvasResourceProviderSwapChain final : public CanvasResourceProvider {
return false;
WillDraw();
- RasterInterface()->WritePixels(resource_->GetBackBufferMailbox(), x, y,
- GetBackingTextureTarget(), row_bytes,
- orig_info, pixels);
+ RasterInterface()->WritePixels(
+ resource_->GetBackBufferMailbox(), x, y, GetBackingTextureTarget(),
+ base::checked_cast<GLuint>(row_bytes), orig_info, pixels);
return true;
}
@@ -891,7 +887,7 @@ class CanvasResourceProviderSwapChain final : public CanvasResourceProvider {
std::unique_ptr<CanvasResourceProvider>
CanvasResourceProvider::CreateBitmapProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize should_initialize) {
auto provider = std::make_unique<CanvasResourceProviderBitmap>(
@@ -909,7 +905,7 @@ CanvasResourceProvider::CreateBitmapProvider(
std::unique_ptr<CanvasResourceProvider>
CanvasResourceProvider::CreateSharedBitmapProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize should_initialize,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher) {
@@ -933,7 +929,7 @@ CanvasResourceProvider::CreateSharedBitmapProvider(
std::unique_ptr<CanvasResourceProvider>
CanvasResourceProvider::CreateSharedImageProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize should_initialize,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
@@ -965,8 +961,25 @@ CanvasResourceProvider::CreateSharedImageProvider(
return nullptr;
}
+ const bool is_accelerated = raster_mode == RasterMode::kGPU;
+
+ CanvasResourceParams adjusted_params = params;
+ // TODO(https://crbug.com/1210946): Pass in params as is for all cases.
+ // Overriding the params to use RGBA instead of N32 is needed because code
+ // elsewhere assumes RGBA. OTOH the software path seems to be assuming N32
+ // somewhere in the later pipeline but for offscreen canvas only.
+ if (!(shared_image_usage_flags & gpu::SHARED_IMAGE_USAGE_WEBGPU)) {
+ adjusted_params = CanvasResourceParams(
+ params.ColorSpace(),
+ is_accelerated && params.GetSkColorType() != kRGBA_F16_SkColorType
+ ? kRGBA_8888_SkColorType
+ : params.GetSkColorType(),
+ params.GetSkAlphaType());
+ }
+
const bool is_gpu_memory_buffer_image_allowed =
- is_gpu_compositing_enabled && IsGMBAllowed(size, params, capabilities) &&
+ is_gpu_compositing_enabled &&
+ IsGMBAllowed(size, adjusted_params, capabilities) &&
Platform::Current()->GetGpuMemoryBufferManager();
if (raster_mode == RasterMode::kCPU && !is_gpu_memory_buffer_image_allowed)
@@ -975,14 +988,14 @@ CanvasResourceProvider::CreateSharedImageProvider(
// If we cannot use overlay, we have to remove the scanout flag and the
// concurrent read write flag.
if (!is_gpu_memory_buffer_image_allowed ||
- !capabilities.texture_storage_image) {
+ (is_accelerated && !capabilities.texture_storage_image)) {
shared_image_usage_flags &= ~gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
shared_image_usage_flags &= ~gpu::SHARED_IMAGE_USAGE_SCANOUT;
}
auto provider = std::make_unique<CanvasResourceProviderSharedImage>(
- size, filter_quality, params, context_provider_wrapper,
- is_origin_top_left, raster_mode == RasterMode::kGPU, skia_use_dawn,
+ size, filter_quality, adjusted_params, context_provider_wrapper,
+ is_origin_top_left, is_accelerated, skia_use_dawn,
shared_image_usage_flags);
if (provider->IsValid()) {
if (should_initialize ==
@@ -1001,7 +1014,7 @@ CanvasResourceProvider::CreateWebGPUImageProvider(
bool is_origin_top_left) {
auto context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
return CreateSharedImageProvider(
- size, kLow_SkFilterQuality, params,
+ size, cc::PaintFlags::FilterQuality::kLow, params,
CanvasResourceProvider::ShouldInitialize::kNo,
std::move(context_provider_wrapper), RasterMode::kGPU, is_origin_top_left,
gpu::SHARED_IMAGE_USAGE_WEBGPU);
@@ -1010,7 +1023,7 @@ CanvasResourceProvider::CreateWebGPUImageProvider(
std::unique_ptr<CanvasResourceProvider>
CanvasResourceProvider::CreatePassThroughProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
@@ -1051,7 +1064,7 @@ CanvasResourceProvider::CreatePassThroughProvider(
std::unique_ptr<CanvasResourceProvider>
CanvasResourceProvider::CreateSwapChainProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize should_initialize,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
@@ -1185,7 +1198,7 @@ bool CanvasResourceProvider::CanvasImageProvider::IsHardwareDecodeCache()
CanvasResourceProvider::CanvasResourceProvider(
const ResourceProviderType& type,
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
bool is_origin_top_left,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
@@ -1197,8 +1210,7 @@ CanvasResourceProvider::CanvasResourceProvider(
filter_quality_(filter_quality),
params_(params),
is_origin_top_left_(is_origin_top_left),
- snapshot_paint_image_id_(cc::PaintImage::GetNextId()),
- identifiability_paint_op_digest_(size_) {
+ snapshot_paint_image_id_(cc::PaintImage::GetNextId()) {
if (context_provider_wrapper_)
context_provider_wrapper_->AddObserver(this);
CanvasMemoryDumpProvider::Instance()->RegisterClient(this);
@@ -1354,9 +1366,6 @@ GrDirectContext* CanvasResourceProvider::GetGrContext() const {
sk_sp<cc::PaintRecord> CanvasResourceProvider::FlushCanvas() {
if (!HasRecordedDrawOps())
return nullptr;
- // Get PaintOp count before finishRecordingAsPicture() adds more, as these
- // additional ops don't correspond to canvas context operations.
- const size_t initial_paint_ops = recorder_->num_paint_ops();
sk_sp<cc::PaintRecord> last_recording = recorder_->finishRecordingAsPicture();
RasterRecord(last_recording);
needs_flush_ = false;
@@ -1364,12 +1373,6 @@ sk_sp<cc::PaintRecord> CanvasResourceProvider::FlushCanvas() {
recorder_->beginRecording(Size().Width(), Size().Height());
if (restore_clip_stack_callback_)
restore_clip_stack_callback_.Run(canvas);
- identifiability_paint_op_digest_.MaybeUpdateDigest(last_recording,
- initial_paint_ops);
- // restore_clip_stack_callback_ also adds PaintOps -- these need to be skipped
- // during identifiability digest calculation.
- identifiability_paint_op_digest_.SetPrefixSkipCount(
- recorder_->num_paint_ops());
return last_recording;
}
@@ -1384,6 +1387,8 @@ void CanvasResourceProvider::RasterRecordOOP(
sk_sp<cc::PaintRecord> last_recording,
bool needs_clear,
gpu::Mailbox mailbox) {
+ if (IsGpuContextLost())
+ return;
gpu::raster::RasterInterface* ri = RasterInterface();
SkColor background_color =
ColorParams().GetSkAlphaType() == kOpaque_SkAlphaType
@@ -1406,9 +1411,9 @@ void CanvasResourceProvider::RasterRecordOOP(
gfx::Vector2dF post_scale(1.f, 1.f);
ri->BeginRasterCHROMIUM(
- background_color, needs_clear, /*msaa_sample_count=*/0,
- /*can_use_lcd_text=*/false, ColorParams().GetStorageGfxColorSpace(),
- mailbox.name);
+ background_color, needs_clear, /*msaa_sample_count=*/1,
+ gpu::raster::MsaaMode::kDMSAA, ColorParams().CanUseLcdText(),
+ ColorParams().GetStorageGfxColorSpace(), mailbox.name);
ri->RasterCHROMIUM(list.get(), GetOrCreateCanvasImageProvider(), size,
full_raster_rect, playback_rect, post_translate,
@@ -1514,12 +1519,6 @@ void CanvasResourceProvider::OnDestroyResource() {
--num_inflight_resources_;
}
-const IdentifiabilityPaintOpDigest&
-CanvasResourceProvider::GetIdentifiablityPaintOpDigest() {
- FlushCanvas();
- return identifiability_paint_op_digest_;
-}
-
scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() {
if (canvas_resources_.IsEmpty()) {
canvas_resources_.push_back(CreateResource());
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 3043630b791..50024f2423c 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
@@ -9,7 +9,6 @@
#include "cc/raster/playback_image_provider.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
-#include "third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h"
#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
#include "third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
@@ -82,7 +81,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
using RestoreMatrixClipStackCb =
base::RepeatingCallback<void(cc::PaintCanvas*)>;
- // TODO(juanmihd@ bug/1078518) Check whether SkFilterQuality is needed in all
+ // TODO(juanmihd@ bug/1078518) Check whether FilterQuality is needed in all
// these Create methods below, or just call setFilterQuality explicitly.
// Used to determine if the provider is going to be initialized or not,
@@ -91,20 +90,20 @@ class PLATFORM_EXPORT CanvasResourceProvider
static std::unique_ptr<CanvasResourceProvider> CreateBitmapProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize initialize_provider);
static std::unique_ptr<CanvasResourceProvider> CreateSharedBitmapProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize initialize_provider,
base::WeakPtr<CanvasResourceDispatcher>);
static std::unique_ptr<CanvasResourceProvider> CreateSharedImageProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize initialize_provider,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
@@ -119,7 +118,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
static std::unique_ptr<CanvasResourceProvider> CreatePassThroughProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceDispatcher>,
@@ -127,7 +126,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
static std::unique_ptr<CanvasResourceProvider> CreateSwapChainProvider(
const IntSize& size,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasResourceParams& params,
ShouldInitialize initialize_provider,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
@@ -150,7 +149,9 @@ class PLATFORM_EXPORT CanvasResourceProvider
void ReleaseLockedImages();
sk_sp<cc::PaintRecord> FlushCanvas();
const CanvasResourceParams& ColorParams() const { return params_; }
- void SetFilterQuality(SkFilterQuality quality) { filter_quality_ = quality; }
+ void SetFilterQuality(cc::PaintFlags::FilterQuality quality) {
+ filter_quality_ = quality;
+ }
const IntSize& Size() const { return size_; }
bool IsOriginTopLeft() const { return is_origin_top_left_; }
virtual bool IsValid() const = 0;
@@ -203,7 +204,13 @@ class PLATFORM_EXPORT CanvasResourceProvider
NOTREACHED();
return nullptr;
}
+ virtual uint32_t GetSharedImageUsageFlags() const {
+ NOTREACHED();
+ return 0;
+ }
+ CanvasResourceProvider(const CanvasResourceProvider&) = delete;
+ CanvasResourceProvider& operator=(const CanvasResourceProvider&) = delete;
~CanvasResourceProvider() override;
base::WeakPtr<CanvasResourceProvider> CreateWeakPtr() {
@@ -228,14 +235,6 @@ class PLATFORM_EXPORT CanvasResourceProvider
void OnDestroyResource();
- // Gets an immutable reference to the IdentifiabilityPaintOpDigest, which
- // contains the current PaintOp digest, and taint bits (encountered
- // partially-digested images, encountered skipped ops).
- //
- // The digest is updated based on the results of every FlushCanvas(); this
- // method also calls FlushCanvas() to ensure that all operations are accounted
- // for in the digest.
- const IdentifiabilityPaintOpDigest& GetIdentifiablityPaintOpDigest();
virtual void OnAcquireRecyclableCanvasResource() {}
virtual void OnDestroyRecyclableCanvasResource(
const gpu::SyncToken& sync_token) {}
@@ -253,13 +252,15 @@ class PLATFORM_EXPORT CanvasResourceProvider
return is_origin_top_left_ ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin;
}
- SkFilterQuality FilterQuality() const { return filter_quality_; }
+ cc::PaintFlags::FilterQuality FilterQuality() const {
+ return filter_quality_;
+ }
scoped_refptr<StaticBitmapImage> SnapshotInternal(const ImageOrientation&);
scoped_refptr<CanvasResource> GetImportedResource() const;
CanvasResourceProvider(const ResourceProviderType&,
const IntSize&,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasResourceParams&,
bool is_origin_top_left,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
@@ -315,7 +316,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher_;
const IntSize size_;
- SkFilterQuality filter_quality_;
+ cc::PaintFlags::FilterQuality filter_quality_;
const CanvasResourceParams params_;
const bool is_origin_top_left_;
std::unique_ptr<CanvasImageProvider> canvas_image_provider_;
@@ -341,18 +342,12 @@ class PLATFORM_EXPORT CanvasResourceProvider
// underlying GrContext is flushed.
static constexpr int kMaxDrawsBeforeContextFlush = 50;
- size_t num_inflight_resources_ = 0;
- size_t max_inflight_resources_ = 0;
+ int num_inflight_resources_ = 0;
+ int max_inflight_resources_ = 0;
RestoreMatrixClipStackCb restore_clip_stack_callback_;
- // For identifiability metrics -- PaintOps are serialized so that digests can
- // be calculated using hashes of the serialized output.
- IdentifiabilityPaintOpDigest identifiability_paint_op_digest_;
-
base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
index 38f96e1c6d5..4971786437f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -19,7 +19,6 @@
#include "third_party/blink/renderer/platform/graphics/test/gpu_memory_buffer_test_platform.h"
#include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
#include "ui/gfx/buffer_types.h"
using testing::_;
@@ -39,7 +38,7 @@ class MockCanvasResourceDispatcherClient
MockCanvasResourceDispatcherClient() = default;
MOCK_METHOD0(BeginFrame, bool());
- MOCK_METHOD1(SetFilterQualityInResource, void(SkFilterQuality));
+ MOCK_METHOD1(SetFilterQualityInResource, void(cc::PaintFlags::FilterQuality));
};
} // anonymous namespace
@@ -82,7 +81,7 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
shared_image_usage_flags);
@@ -110,7 +109,7 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kLow_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kLow, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
@@ -139,7 +138,7 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderUnacceleratedOverlay) {
gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kLow_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kLow, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kCPU, true /*is_origin_top_left*/,
shared_image_usage_flags);
@@ -171,7 +170,7 @@ TEST_F(CanvasResourceProviderTest,
gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
shared_image_usage_flags);
@@ -226,7 +225,7 @@ TEST_F(CanvasResourceProviderTest,
gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
shared_image_usage_flags);
@@ -274,7 +273,7 @@ TEST_F(CanvasResourceProviderTest,
gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU,
true /* is_origin_top_left */, shared_image_usage_flags);
@@ -294,7 +293,7 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderBitmap) {
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreateBitmapProvider(
- kSize, kLow_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kLow, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear);
EXPECT_EQ(provider->Size(), kSize);
@@ -322,7 +321,7 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedBitmap) {
1 /* placeholder_canvas_id */, kSize);
auto provider = CanvasResourceProvider::CreateSharedBitmapProvider(
- kSize, kLow_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kLow, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
resource_dispatcher.GetWeakPtr());
@@ -353,7 +352,7 @@ TEST_F(CanvasResourceProviderTest,
gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
shared_image_usage_flags);
@@ -382,8 +381,9 @@ TEST_F(CanvasResourceProviderTest,
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreatePassThroughProvider(
- kSize, kLow_SkFilterQuality, kColorParams, context_provider_wrapper_,
- nullptr /*resource_dispatcher */, true /*is_origin_top_left*/);
+ kSize, cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ context_provider_wrapper_, nullptr /*resource_dispatcher */,
+ true /*is_origin_top_left*/);
EXPECT_EQ(provider->Size(), kSize);
EXPECT_TRUE(provider->IsValid());
@@ -406,7 +406,7 @@ TEST_F(CanvasResourceProviderTest,
mailbox, viz::ReleaseCallback(), gpu::SyncToken(), kSize,
GL_TEXTURE_2D, kColorParams,
SharedGpuContext::ContextProviderWrapper(), provider->CreateWeakPtr(),
- kMedium_SkFilterQuality, true /*is_origin_top_left*/,
+ cc::PaintFlags::FilterQuality::kMedium, true /*is_origin_top_left*/,
true /*is_overlay_candidate*/);
// NewOrRecycledResource() would return nullptr before an ImportResource().
@@ -421,16 +421,19 @@ TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_Bitmap) {
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreateBitmapProvider(
- IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear);
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear);
EXPECT_FALSE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreateBitmapProvider(
- IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear);
+ IntSize(kMaxTextureSize, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear);
EXPECT_FALSE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreateBitmapProvider(
- IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear);
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear);
EXPECT_FALSE(provider->SupportsDirectCompositing());
}
@@ -439,20 +442,23 @@ TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_SharedImage) {
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear,
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
EXPECT_TRUE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreateSharedImageProvider(
- IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear,
+ IntSize(kMaxTextureSize, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
EXPECT_TRUE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreateSharedImageProvider(
- IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear,
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
// The CanvasResourceProvider for SharedImage should not be created or valid
@@ -464,20 +470,23 @@ TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_SwapChain) {
const CanvasResourceParams kColorParams(
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreateSwapChainProvider(
- IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear,
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, nullptr /* resource_dispatcher */,
true /*is_origin_top_left*/);
EXPECT_TRUE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreateSwapChainProvider(
- IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear,
+ IntSize(kMaxTextureSize, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, nullptr /* resource_dispatcher */,
true /*is_origin_top_left*/);
EXPECT_TRUE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreateSwapChainProvider(
- IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, CanvasResourceProvider::ShouldInitialize::kCallClear,
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, nullptr /* resource_dispatcher */,
true /*is_origin_top_left*/);
@@ -490,19 +499,22 @@ TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_PassThrough) {
const CanvasResourceParams kColorParams(
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreatePassThroughProvider(
- IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, context_provider_wrapper_,
- nullptr /* resource_dispatcher */, true /*is_origin_top_left*/);
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ context_provider_wrapper_, nullptr /* resource_dispatcher */,
+ true /*is_origin_top_left*/);
EXPECT_TRUE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreatePassThroughProvider(
- IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, context_provider_wrapper_,
- nullptr /* resource_dispatcher */, true /*is_origin_top_left*/);
+ IntSize(kMaxTextureSize, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ context_provider_wrapper_, nullptr /* resource_dispatcher */,
+ true /*is_origin_top_left*/);
EXPECT_TRUE(provider->SupportsDirectCompositing());
provider = CanvasResourceProvider::CreatePassThroughProvider(
- IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
- kColorParams, context_provider_wrapper_,
- nullptr /* resource_dispatcher */, true /*is_origin_top_left*/);
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize),
+ cc::PaintFlags::FilterQuality::kLow, kColorParams,
+ context_provider_wrapper_, nullptr /* resource_dispatcher */,
+ true /*is_origin_top_left*/);
// The CanvasResourceProvider for PassThrough should not be created or valid
// if the texture size is greater than the maximum value
EXPECT_TRUE(!provider || !provider->IsValid());
@@ -514,7 +526,7 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect2DSwapChain) {
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto provider = CanvasResourceProvider::CreateSwapChainProvider(
- kSize, kLow_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kLow, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, nullptr /* resource_dispatcher */,
true /*is_origin_top_left*/);
@@ -539,13 +551,13 @@ TEST_F(CanvasResourceProviderTest, FlushForImage) {
CanvasColorSpace::kSRGB, kN32_SkColorType, kPremul_SkAlphaType);
auto src_provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
auto dst_provider = CanvasResourceProvider::CreateSharedImageProvider(
- kSize, kMedium_SkFilterQuality, kColorParams,
+ kSize, cc::PaintFlags::FilterQuality::kMedium, kColorParams,
CanvasResourceProvider::ShouldInitialize::kCallClear,
context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/,
0u /*shared_image_usage_flags*/);
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 0ab2d595a49..380658f37c0 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
@@ -27,7 +27,7 @@ TEST(CanvasResourceTest, PrepareTransferableResource_SharedBitmap) {
CanvasResourceSharedBitmap::Create(IntSize(10, 10),
CanvasResourceParams(),
nullptr, // CanvasResourceProvider
- kLow_SkFilterQuality);
+ cc::PaintFlags::FilterQuality::kLow);
EXPECT_TRUE(!!canvas_resource);
viz::TransferableResource resource;
viz::ReleaseCallback release_callback;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color.h b/chromium/third_party/blink/renderer/platform/graphics/color.h
index 44415900110..e50a866ced9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/color.h
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
typedef uint32_t SkColor;
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 ca97bde9466..95b307db5d4 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
@@ -71,7 +71,7 @@ sk_sp<SkColorSpace> ColorCorrectionTestUtils::ColorSpinSkColorSpace() {
void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
const void* actual_pixels,
const void* expected_pixels,
- int num_pixels,
+ size_t num_pixels,
PixelFormat pixel_format,
PixelsAlphaMultiply alpha_multiplied,
UnpremulRoundTripTolerance premul_unpremul_tolerance) {
@@ -94,12 +94,12 @@ void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
static_cast<const uint8_t*>(actual_pixels);
const uint8_t* expected_pixels_u8 =
static_cast<const uint8_t*>(expected_pixels);
- for (int i = 0; test_passed && i < num_pixels; i++) {
+ for (size_t i = 0; test_passed && i < num_pixels; i++) {
test_passed &=
(actual_pixels_u8[i * 4 + 3] == expected_pixels_u8[i * 4 + 3]);
int alpha_multiplier =
alpha_multiplied ? 1 : expected_pixels_u8[i * 4 + 3];
- for (int j = 0; j < 3; j++) {
+ for (size_t j = 0; j < 3; j++) {
test_passed &= IsNearlyTheSame(
actual_pixels_u8[i * 4 + j] * alpha_multiplier,
expected_pixels_u8[i * 4 + j] * alpha_multiplier,
@@ -118,7 +118,7 @@ void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
static_cast<const uint16_t*>(actual_pixels);
const uint16_t* expected_pixels_u16 =
static_cast<const uint16_t*>(expected_pixels);
- for (int i = 0; test_passed && i < num_pixels * 4; i++) {
+ for (size_t i = 0; test_passed && i < num_pixels * 4; i++) {
test_passed &=
IsNearlyTheSame(actual_pixels_u16[i], expected_pixels_u16[i],
_16161616_color_correction_tolerance);
@@ -140,7 +140,7 @@ void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
expected_pixels_f32, skcms_PixelFormat_BGRA_ffff,
skcms_AlphaFormat_Unpremul, nullptr, num_pixels));
- for (int i = 0; test_passed && i < num_pixels * 4; i++) {
+ for (size_t i = 0; test_passed && i < num_pixels * 4; i++) {
test_passed &=
IsNearlyTheSame(actual_pixels_f32[i], expected_pixels_f32[i],
floating_point_color_correction_tolerance);
@@ -152,7 +152,7 @@ void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
const float* actual_pixels_f32 = static_cast<const float*>(actual_pixels);
const float* expected_pixels_f32 =
static_cast<const float*>(expected_pixels);
- for (int i = 0; test_passed && i < num_pixels * 4; i++) {
+ for (size_t i = 0; test_passed && i < num_pixels * 4; i++) {
test_passed &=
IsNearlyTheSame(actual_pixels_f32[i], expected_pixels_f32[i],
floating_point_color_correction_tolerance);
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 f935655db82..88a7aa64ebe 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
@@ -41,7 +41,7 @@ class ColorCorrectionTestUtils {
static void CompareColorCorrectedPixels(
const void* actual_pixels,
const void* expected_pixels,
- int num_pixels,
+ size_t num_pixels,
PixelFormat pixel_format,
PixelsAlphaMultiply alpha_multiplied = kAlphaUnmultiplied,
UnpremulRoundTripTolerance premul_unpremul_tolerance =
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.cc b/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
index 72c16e2e713..022196101bc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
@@ -4,14 +4,15 @@
#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
+#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/third_party/skcms/skcms.h"
+#include "ui/display/screen_info.h"
namespace blink {
namespace color_space_utilities {
-ColorSpaceGamut GetColorSpaceGamut(const ScreenInfo& screen_info) {
+ColorSpaceGamut GetColorSpaceGamut(const display::ScreenInfo& screen_info) {
const gfx::ColorSpace& color_space =
screen_info.display_color_spaces.GetScreenInfoColorSpace();
if (!color_space.IsValid())
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.h b/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.h
index fd05280e08e..1c61434f44c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_space_gamut.h
@@ -9,9 +9,11 @@
struct skcms_ICCProfile;
-namespace blink {
-
+namespace display {
struct ScreenInfo;
+}
+
+namespace blink {
enum class ColorSpaceGamut {
// Values synced with 'Gamut' in src/tools/metrics/histograms/histograms.xml
@@ -31,7 +33,7 @@ enum class ColorSpaceGamut {
namespace color_space_utilities {
-PLATFORM_EXPORT ColorSpaceGamut GetColorSpaceGamut(const ScreenInfo&);
+PLATFORM_EXPORT ColorSpaceGamut GetColorSpaceGamut(const display::ScreenInfo&);
ColorSpaceGamut GetColorSpaceGamut(const skcms_ICCProfile*);
} // namespace color_space_utilities
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 eee9f2e4595..5d439bc5385 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
@@ -99,14 +99,16 @@ void Bt709ColorProfileData(Vector<char>& data) {
DCHECK(WTF::IsMainThread());
DCHECK(data.IsEmpty());
- data.Append(bt709ColorProfile::data(), bt709ColorProfile::size());
+ data.Append(bt709ColorProfile::data(),
+ static_cast<wtf_size_t>(bt709ColorProfile::size()));
}
void Bt601ColorProfileData(Vector<char>& data) {
DCHECK(WTF::IsMainThread());
DCHECK(data.IsEmpty());
- data.Append(bt601ColorProfile::data(), bt601ColorProfile::size());
+ data.Append(bt601ColorProfile::data(),
+ static_cast<wtf_size_t>(bt601ColorProfile::size()));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc
index 45fa6dc71e8..386427890fa 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc
@@ -11,12 +11,11 @@
namespace blink {
ChunkToLayerMapper::ChunkToLayerMapper(const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset)
+ const FloatPoint& layer_offset)
: layer_state_(layer_state),
layer_offset_(layer_offset),
chunk_state_(layer_state_),
- translation_2d_or_matrix_(
- FloatSize(-layer_offset.x(), -layer_offset.y())) {}
+ translation_2d_or_matrix_(ToFloatSize(-layer_offset)) {}
void ChunkToLayerMapper::SwitchToChunk(const PaintChunk& chunk) {
raster_effect_outset_ = chunk.raster_effect_outset;
@@ -28,8 +27,8 @@ void ChunkToLayerMapper::SwitchToChunk(const PaintChunk& chunk) {
if (new_chunk_state == layer_state_) {
has_filter_that_moves_pixels_ = false;
- translation_2d_or_matrix_ = GeometryMapper::Translation2DOrMatrix(
- FloatSize(-layer_offset_.x(), -layer_offset_.y()));
+ translation_2d_or_matrix_ =
+ GeometryMapper::Translation2DOrMatrix(ToFloatSize(-layer_offset_));
clip_rect_ = FloatClipRect();
chunk_state_ = new_chunk_state;
return;
@@ -38,8 +37,8 @@ void ChunkToLayerMapper::SwitchToChunk(const PaintChunk& chunk) {
if (&new_chunk_state.Transform() != &chunk_state_.Transform()) {
translation_2d_or_matrix_ = GeometryMapper::SourceToDestinationProjection(
new_chunk_state.Transform(), layer_state_.Transform());
- translation_2d_or_matrix_.PostTranslate(-layer_offset_.x(),
- -layer_offset_.y());
+ translation_2d_or_matrix_.PostTranslate(-layer_offset_.X(),
+ -layer_offset_.Y());
}
bool new_has_filter_that_moves_pixels = has_filter_that_moves_pixels_;
@@ -62,7 +61,7 @@ void ChunkToLayerMapper::SwitchToChunk(const PaintChunk& chunk) {
clip_rect_ =
GeometryMapper::LocalToAncestorClipRect(new_chunk_state, layer_state_);
if (!clip_rect_.IsInfinite())
- clip_rect_.MoveBy(FloatPoint(-layer_offset_.x(), -layer_offset_.y()));
+ clip_rect_.MoveBy(-layer_offset_);
}
chunk_state_ = new_chunk_state;
@@ -108,7 +107,7 @@ IntRect ChunkToLayerMapper::MapUsingGeometryMapper(const IntRect& rect) const {
if (visual_rect.Rect().IsEmpty())
return IntRect();
- visual_rect.Rect().Move(-layer_offset_.x(), -layer_offset_.y());
+ visual_rect.Rect().MoveBy(-layer_offset_);
InflateForRasterEffectOutset(visual_rect.Rect());
return EnclosingIntRect(visual_rect.Rect());
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h
index 6de917b6c51..80877db9f60 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h
@@ -23,7 +23,7 @@ class PLATFORM_EXPORT ChunkToLayerMapper {
public:
ChunkToLayerMapper(const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset);
+ const FloatPoint& layer_offset);
// This class can map from multiple chunks. Before mapping from a chunk, this
// method must be called to prepare for the chunk.
@@ -47,7 +47,7 @@ class PLATFORM_EXPORT ChunkToLayerMapper {
void InflateForRasterEffectOutset(FloatRect&) const;
const PropertyTreeState layer_state_;
- const gfx::Vector2dF layer_offset_;
+ const FloatPoint layer_offset_;
// The following fields are chunk-specific which are updated in
// SwitchToChunk().
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 cbb62881b19..cdd9e4fd750 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
@@ -52,7 +52,7 @@ class ChunkToLayerMapperTest : public testing::Test {
};
TEST_F(ChunkToLayerMapperTest, OneChunkUsingLayerState) {
- ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
+ ChunkToLayerMapper mapper(LayerState(), FloatPoint(10, 20));
auto chunk = Chunk(LayerState());
mapper.SwitchToChunk(chunk);
EXPECT_FALSE(HasFilterThatMovesPixels(mapper));
@@ -64,7 +64,7 @@ TEST_F(ChunkToLayerMapperTest, OneChunkUsingLayerState) {
}
TEST_F(ChunkToLayerMapperTest, TwoChunkUsingLayerState) {
- ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
+ ChunkToLayerMapper mapper(LayerState(), FloatPoint(10, 20));
auto chunk1 = Chunk(LayerState());
auto chunk2 = Chunk(LayerState());
@@ -86,7 +86,7 @@ TEST_F(ChunkToLayerMapperTest, TwoChunkUsingLayerState) {
}
TEST_F(ChunkToLayerMapperTest, TwoChunkSameState) {
- ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
+ ChunkToLayerMapper mapper(LayerState(), FloatPoint(10, 20));
auto transform = CreateTransform(LayerState().Transform(),
TransformationMatrix().Scale(2));
auto clip = CreateClip(LayerState().Clip(), LayerState().Transform(),
@@ -117,7 +117,7 @@ TEST_F(ChunkToLayerMapperTest, TwoChunkSameState) {
}
TEST_F(ChunkToLayerMapperTest, TwoChunkDifferentState) {
- ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
+ ChunkToLayerMapper mapper(LayerState(), FloatPoint(10, 20));
auto transform1 = CreateTransform(LayerState().Transform(),
TransformationMatrix().Scale(2));
auto clip1 = CreateClip(LayerState().Clip(), LayerState().Transform(),
@@ -153,7 +153,7 @@ TEST_F(ChunkToLayerMapperTest, TwoChunkDifferentState) {
}
TEST_F(ChunkToLayerMapperTest, SlowPath) {
- ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
+ ChunkToLayerMapper mapper(LayerState(), FloatPoint(10, 20));
auto chunk1 = Chunk(LayerState());
// Chunk2 has a blur filter. Should use the slow path.
@@ -221,7 +221,7 @@ TEST_F(ChunkToLayerMapperTest, SwitchToSiblingEffect) {
LayerState().Clip(), *effect2));
ChunkToLayerMapper mapper(chunk1.properties.GetPropertyTreeState().Unalias(),
- gfx::Vector2dF(10, 20));
+ FloatPoint(10, 20));
mapper.SwitchToChunk(chunk2);
EXPECT_FALSE(HasFilterThatMovesPixels(mapper));
}
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 fe04ff87b75..470c2d8fea2 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
@@ -5,7 +5,9 @@
#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
#include <memory>
+
#include "base/bind.h"
+#include "base/stl_util.h"
#include "base/trace_event/traced_value.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_op_buffer.h"
@@ -37,10 +39,10 @@ void ContentLayerClientImpl::AppendAdditionalInfoAsJSON(
LayerTreeFlags flags,
const cc::Layer& layer,
JSONObject& json) const {
-#if DCHECK_IS_ON()
+#if EXPENSIVE_DCHECKS_ARE_ON()
if (flags & kLayerTreeIncludesDebugInfo)
json.SetValue("paintChunkContents", paint_chunk_debug_data_->Clone());
-#endif
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
if ((flags & (kLayerTreeIncludesInvalidations |
kLayerTreeIncludesDetailedInvalidations)) &&
@@ -60,14 +62,15 @@ void ContentLayerClientImpl::AppendAdditionalInfoAsJSON(
scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
const PaintChunkSubset& paint_chunks,
- const gfx::Rect& layer_bounds,
+ const FloatPoint& layer_offset,
+ const IntSize& layer_bounds,
const PropertyTreeState& layer_state) {
if (paint_chunks.begin()->is_cacheable)
id_.emplace(paint_chunks.begin()->id);
else
id_ = absl::nullopt;
-#if DCHECK_IS_ON()
+#if EXPENSIVE_DCHECKS_ARE_ON()
paint_chunk_debug_data_ = std::make_unique<JSONArray>();
for (auto it = paint_chunks.begin(); it != paint_chunks.end(); ++it) {
auto json = std::make_unique<JSONObject>();
@@ -77,25 +80,24 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
DisplayItemList::kCompact));
paint_chunk_debug_data_->PushObject(std::move(json));
}
-#endif
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
// The raster invalidator will only handle invalidations within a cc::Layer so
// we need this invalidation if the layer's properties have changed.
if (layer_state != layer_state_)
cc_picture_layer_->SetSubtreePropertyChanged();
- gfx::Size old_layer_size = raster_invalidator_.LayerBounds().size();
- DCHECK_EQ(old_layer_size, cc_picture_layer_->bounds());
+ IntSize old_layer_bounds = raster_invalidator_.LayerBounds();
+ DCHECK_EQ(old_layer_bounds, IntSize(cc_picture_layer_->bounds()));
raster_invalidator_.Generate(raster_invalidation_function_, paint_chunks,
- layer_bounds, layer_state);
+ layer_offset, layer_bounds, layer_state);
layer_state_ = layer_state;
absl::optional<RasterUnderInvalidationCheckingParams>
raster_under_invalidation_params;
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
raster_under_invalidation_params.emplace(
- *raster_invalidator_.GetTracking(),
- IntRect(0, 0, layer_bounds.width(), layer_bounds.height()),
+ *raster_invalidator_.GetTracking(), IntRect(IntPoint(), layer_bounds),
paint_chunks.begin()->id.client.DebugName());
}
@@ -105,23 +107,23 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
// paint chunk to align the bounding box to (0, 0) and we set the layer's
// offset_to_transform_parent with the origin of the paint chunk here.
cc_picture_layer_->SetOffsetToTransformParent(
- layer_bounds.OffsetFromOrigin());
+ gfx::Vector2dF(layer_offset.X(), layer_offset.Y()));
// If nothing changed in the layer, keep the original display item list.
// Here check layer_bounds because RasterInvalidator doesn't issue raster
// invalidation when only layer_bounds changes.
- if (cc_display_item_list_ && layer_bounds.size() == old_layer_size &&
+ if (cc_display_item_list_ && layer_bounds == old_layer_bounds &&
!raster_under_invalidation_params) {
- DCHECK_EQ(cc_picture_layer_->bounds(), layer_bounds.size());
+ DCHECK_EQ(cc_picture_layer_->bounds(), gfx::Size(layer_bounds));
return cc_picture_layer_;
}
cc_display_item_list_ = PaintChunksToCcLayer::Convert(
- paint_chunks, layer_state, layer_bounds.OffsetFromOrigin(),
+ paint_chunks, layer_state, layer_offset,
cc::DisplayItemList::kTopLevelDisplayItemList,
base::OptionalOrNullptr(raster_under_invalidation_params));
- cc_picture_layer_->SetBounds(layer_bounds.size());
+ cc_picture_layer_->SetBounds(gfx::Size(layer_bounds));
cc_picture_layer_->SetHitTestable(true);
cc_picture_layer_->SetIsDrawable(
(!layer_bounds.IsEmpty() && cc_display_item_list_->TotalOpCount()) ||
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 ad92fb6e47e..8f8964b766d 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_CONTENT_LAYER_CLIENT_IMPL_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer.h"
#include "third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h"
@@ -28,11 +27,13 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
public:
ContentLayerClientImpl();
+ ContentLayerClientImpl(const ContentLayerClientImpl&) = delete;
+ ContentLayerClientImpl& operator=(const ContentLayerClientImpl&) = delete;
~ContentLayerClientImpl() override;
// cc::ContentLayerClient
gfx::Rect PaintableRegion() const final {
- return gfx::Rect(raster_invalidator_.LayerBounds().size());
+ return gfx::Rect(gfx::Size(raster_invalidator_.LayerBounds()));
}
scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() final {
return cc_display_item_list_;
@@ -53,7 +54,8 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
scoped_refptr<cc::PictureLayer> UpdateCcPictureLayer(
const PaintChunkSubset&,
- const gfx::Rect& layer_bounds,
+ const FloatPoint& layer_offset,
+ const IntSize& layer_bounds,
const PropertyTreeState&);
RasterInvalidator& GetRasterInvalidator() { return raster_invalidator_; }
@@ -73,11 +75,9 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
PropertyTreeState layer_state_;
String debug_name_;
-#if DCHECK_IS_ON()
+#if EXPENSIVE_DCHECKS_ARE_ON()
std::unique_ptr<JSONArray> paint_chunk_debug_data_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(ContentLayerClientImpl);
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
};
} // 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 4ce57017eab..ccadf255114 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
@@ -65,6 +65,13 @@ void PaintArtifactCompositor::WillBeRemovedFromFrame() {
root_layer_->RemoveAllChildren();
}
+void PaintArtifactCompositor::SetPrefersLCDText(bool prefers) {
+ if (prefers_lcd_text_ == prefers)
+ return;
+ SetNeedsUpdate();
+ prefers_lcd_text_ = prefers;
+}
+
std::unique_ptr<JSONArray> PaintArtifactCompositor::GetPendingLayersAsJSON()
const {
std::unique_ptr<JSONArray> result = std::make_unique<JSONArray>();
@@ -96,10 +103,10 @@ std::unique_ptr<JSONObject> PaintArtifactCompositor::GetLayersAsJSON(
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && !json_client) {
// The cc::Layer may come from a GraphicsLayer.
for (const auto& pending_layer : pending_layers_) {
- if (pending_layer.compositing_type ==
+ if (pending_layer.GetCompositingType() ==
PendingLayer::kPreCompositedLayer) {
- if (&pending_layer.graphics_layer->CcLayer() == layer.get()) {
- json_client = pending_layer.graphics_layer;
+ if (&pending_layer.GetGraphicsLayer()->CcLayer() == layer.get()) {
+ json_client = pending_layer.GetGraphicsLayer();
break;
}
}
@@ -107,10 +114,10 @@ std::unique_ptr<JSONObject> PaintArtifactCompositor::GetLayersAsJSON(
}
if (!transform) {
for (const auto& pending_layer : pending_layers_) {
- if (pending_layer.property_tree_state.Transform().CcNodeId(
+ if (pending_layer.GetPropertyTreeState().Transform().CcNodeId(
layer->property_tree_sequence_number()) ==
layer->transform_tree_index()) {
- transform = &pending_layer.property_tree_state.Transform();
+ transform = &pending_layer.GetPropertyTreeState().Transform();
break;
}
}
@@ -123,20 +130,20 @@ std::unique_ptr<JSONObject> PaintArtifactCompositor::GetLayersAsJSON(
scoped_refptr<cc::Layer> PaintArtifactCompositor::WrappedCcLayerForPendingLayer(
const PendingLayer& pending_layer) {
- if (pending_layer.compositing_type != PendingLayer::kForeignLayer &&
- pending_layer.compositing_type != PendingLayer::kPreCompositedLayer)
+ if (pending_layer.GetCompositingType() != PendingLayer::kForeignLayer &&
+ pending_layer.GetCompositingType() != PendingLayer::kPreCompositedLayer)
return nullptr;
cc::Layer* layer = nullptr;
FloatPoint layer_offset;
- if (pending_layer.compositing_type == PendingLayer::kPreCompositedLayer) {
- DCHECK(pending_layer.graphics_layer);
- DCHECK(!pending_layer.graphics_layer->ShouldCreateLayersAfterPaint());
- layer = &pending_layer.graphics_layer->CcLayer();
- layer_offset =
- FloatPoint(pending_layer.graphics_layer->GetOffsetFromTransformNode());
+ if (pending_layer.GetCompositingType() == PendingLayer::kPreCompositedLayer) {
+ DCHECK(pending_layer.GetGraphicsLayer());
+ DCHECK(!pending_layer.GetGraphicsLayer()->ShouldCreateLayersAfterPaint());
+ layer = &pending_layer.GetGraphicsLayer()->CcLayer();
+ layer_offset = FloatPoint(
+ pending_layer.GetGraphicsLayer()->GetOffsetFromTransformNode());
} else {
- DCHECK_EQ(pending_layer.compositing_type, PendingLayer::kForeignLayer);
+ DCHECK_EQ(pending_layer.GetCompositingType(), PendingLayer::kForeignLayer);
// UpdateTouchActionRects() depends on the layer's offset, but when the
// layer's offset changes, we do not call SetNeedsUpdate() (this is an
// optimization because the update would only cause an extra commit)
@@ -149,64 +156,49 @@ scoped_refptr<cc::Layer> PaintArtifactCompositor::WrappedCcLayerForPendingLayer(
FloatPoint(foreign_layer_display_item.VisualRect().Location());
}
layer->SetOffsetToTransformParent(gfx::Vector2dF(
- layer_offset + pending_layer.offset_of_decomposited_transforms));
+ layer_offset + pending_layer.OffsetOfDecompositedTransforms()));
return layer;
}
const TransformPaintPropertyNode&
PaintArtifactCompositor::NearestScrollTranslationForLayer(
const PendingLayer& pending_layer) {
- if (pending_layer.compositing_type != PendingLayer::kPreCompositedLayer) {
- if (const auto* scroll_translation =
- ScrollTranslationForLayer(pending_layer))
- return *scroll_translation;
- }
+ if (pending_layer.GetCompositingType() == PendingLayer::kScrollHitTestLayer)
+ return pending_layer.ScrollTranslationForScrollHitTestLayer();
- const auto& transform = pending_layer.property_tree_state.Transform();
+ const auto& transform = pending_layer.GetPropertyTreeState().Transform();
// TODO(pdr): This could be a performance issue because it crawls up the
// transform tree for each pending layer. If this is on profiles, we should
// cache a lookup of transform node to scroll translation transform node.
return transform.NearestScrollTranslationNode();
}
-const TransformPaintPropertyNode*
-PaintArtifactCompositor::ScrollTranslationForLayer(
- const PendingLayer& pending_layer) {
- DCHECK_NE(pending_layer.compositing_type, PendingLayer::kPreCompositedLayer);
- // Not checking PendingLayer::kScrollHitTestLayer because a scroll hit test
- // chunk without a direct compositing reasons can still be composited (e.g.
- // when it can't be merged into any other layer).
- if (pending_layer.chunks.size() != 1)
- return nullptr;
-
- const auto& paint_chunk = pending_layer.FirstPaintChunk();
- if (!paint_chunk.hit_test_data)
- return nullptr;
-
- return paint_chunk.hit_test_data->scroll_translation;
-}
-
scoped_refptr<cc::Layer>
PaintArtifactCompositor::ScrollHitTestLayerForPendingLayer(
const PendingLayer& pending_layer) {
- const auto* scroll_translation = ScrollTranslationForLayer(pending_layer);
- if (!scroll_translation)
+ if (pending_layer.GetCompositingType() != PendingLayer::kScrollHitTestLayer)
return nullptr;
// We shouldn't decomposite scroll transform nodes.
- DCHECK_EQ(FloatPoint(), pending_layer.offset_of_decomposited_transforms);
+ DCHECK_EQ(FloatPoint(), pending_layer.OffsetOfDecompositedTransforms());
- const auto& scroll_node = *scroll_translation->ScrollNode();
- auto scroll_element_id = scroll_node.GetCompositorElementId();
+ const auto& scroll_node =
+ *pending_layer.ScrollTranslationForScrollHitTestLayer().ScrollNode();
scoped_refptr<cc::Layer> scroll_layer;
+ auto scroll_element_id = scroll_node.GetCompositorElementId();
for (auto& existing_layer : scroll_hit_test_layers_) {
- if (existing_layer && existing_layer->element_id() == scroll_element_id)
- scroll_layer = existing_layer;
+ if (existing_layer && existing_layer->element_id() == scroll_element_id) {
+ scroll_layer = std::move(existing_layer);
+ break;
+ }
}
- if (!scroll_layer) {
+
+ if (scroll_layer) {
+ DCHECK_EQ(scroll_layer->element_id(), scroll_node.GetCompositorElementId());
+ } else {
scroll_layer = cc::Layer::Create();
- scroll_layer->SetElementId(scroll_element_id);
+ scroll_layer->SetElementId(scroll_node.GetCompositorElementId());
scroll_layer->SetHitTestable(true);
}
@@ -233,19 +225,26 @@ PaintArtifactCompositor::ScrollHitTestLayerForPendingLayer(
scoped_refptr<cc::ScrollbarLayerBase>
PaintArtifactCompositor::ScrollbarLayerForPendingLayer(
const PendingLayer& pending_layer) {
- if (pending_layer.compositing_type != PendingLayer::kScrollbarLayer)
+ if (pending_layer.GetCompositingType() != PendingLayer::kScrollbarLayer)
return nullptr;
const auto& item = pending_layer.FirstDisplayItem();
DCHECK(item.IsScrollbar());
- // We should never decomposite scroll translations, so we don't need to adjust
- // the layer's offset for decomposited transforms.
- DCHECK_EQ(FloatPoint(), pending_layer.offset_of_decomposited_transforms);
-
const auto& scrollbar_item = To<ScrollbarDisplayItem>(item);
- auto* existing_layer = ScrollbarLayer(scrollbar_item.ElementId());
- return scrollbar_item.CreateOrReuseLayer(existing_layer);
+ scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer;
+ for (auto& layer : scrollbar_layers_) {
+ if (layer && layer->element_id() == scrollbar_item.ElementId()) {
+ scrollbar_layer = std::move(layer);
+ break;
+ }
+ }
+
+ scrollbar_layer = scrollbar_item.CreateOrReuseLayer(scrollbar_layer.get());
+ scrollbar_layer->SetOffsetToTransformParent(
+ scrollbar_layer->offset_to_transform_parent() +
+ gfx::Vector2dF(pending_layer.OffsetOfDecompositedTransforms()));
+ return scrollbar_layer;
}
std::unique_ptr<ContentLayerClientImpl>
@@ -290,30 +289,30 @@ PaintArtifactCompositor::CompositedLayerForPendingLayer(
std::unique_ptr<ContentLayerClientImpl> content_layer_client =
ClientForPaintChunk(pending_layer.FirstPaintChunk());
- IntRect cc_combined_bounds = EnclosingIntRect(pending_layer.bounds);
+ FloatPoint layer_offset = pending_layer.LayerOffset();
+ IntSize layer_bounds = pending_layer.LayerBounds();
auto cc_layer = content_layer_client->UpdateCcPictureLayer(
- pending_layer.chunks, cc_combined_bounds,
- pending_layer.property_tree_state);
+ pending_layer.Chunks(), layer_offset, layer_bounds,
+ pending_layer.GetPropertyTreeState());
new_content_layer_clients.push_back(std::move(content_layer_client));
// Set properties that foreign layers would normally control for themselves
// here to avoid changing foreign layers. This includes things set by
// GraphicsLayer on the ContentsLayer() or by video clients etc.
- // TODO(pdr): Can these be set in |UpdateLayerProperties| so we can avoid a
- // full update when they change (see: |NeedsFullUpdateAfterPaintingChunk|)?
- bool contents_opaque = pending_layer.rect_known_to_be_opaque.Contains(
- FloatRect(cc_combined_bounds));
+ bool contents_opaque = pending_layer.RectKnownToBeOpaque().Contains(
+ FloatRect(layer_offset, FloatSize(layer_bounds)));
cc_layer->SetContentsOpaque(contents_opaque);
if (!contents_opaque) {
cc_layer->SetContentsOpaqueForText(
- pending_layer.text_known_to_be_on_opaque_background);
+ pending_layer.TextKnownToBeOnOpaqueBackground());
}
return cc_layer;
}
namespace {
+
cc::Layer* ForeignLayer(const PaintChunk& chunk,
const PaintArtifact& artifact) {
if (chunk.size() != 1)
@@ -336,6 +335,30 @@ bool NeedsFullUpdateAfterPaintingChunk(
if (!repainted.Matches(previous))
return true;
+ if (repainted.is_moved_from_cached_subsequence) {
+ DCHECK_EQ(previous.bounds, repainted.bounds);
+ DCHECK_EQ(previous.rect_known_to_be_opaque,
+ repainted.rect_known_to_be_opaque);
+ DCHECK_EQ(previous.text_known_to_be_on_opaque_background,
+ repainted.text_known_to_be_on_opaque_background);
+ DCHECK_EQ(previous.has_text, repainted.has_text);
+
+ // Debugging for https://crbug.com/1237389 and https://crbug.com/1230104.
+ // Before returning that a full update is not needed, check that the
+ // properties are changed, which would indicate a missing call to
+ // SetNeedsUpdate.
+ if (previous.properties != repainted.properties) {
+ NOTREACHED();
+ return true;
+ }
+
+ // Not checking ForeignLayer() here because the old ForeignDisplayItem
+ // was set to 0 when we moved the cached subsequence. This is also the
+ // reason why we check is_moved_from_cached_subsequence before checking
+ // ForeignLayer().
+ return false;
+ }
+
// Bounds are used in overlap testing.
// TODO(pdr): If the bounds shrink, that does affect overlap testing but we
// could return false to continue using less-than-optimal overlap testing in
@@ -349,11 +372,9 @@ bool NeedsFullUpdateAfterPaintingChunk(
return true;
}
- // TODO(pdr): Can the following be set in |UpdateLayerProperties| so we can
- // still do a repaint update when they change?
// Opaqueness of individual chunks is used to set the cc::Layer's contents
// opaque property.
- if (previous.known_to_be_opaque != repainted.known_to_be_opaque)
+ if (previous.rect_known_to_be_opaque != repainted.rect_known_to_be_opaque)
return true;
// Similar to opaqueness, opaqueness for text is used to set the cc::Layer's
// contents opaque for text property.
@@ -361,6 +382,19 @@ bool NeedsFullUpdateAfterPaintingChunk(
repainted.text_known_to_be_on_opaque_background) {
return true;
}
+ // |has_text| affects compositing decisions (see:
+ // |PendingLayer::MergeInternal|).
+ if (previous.has_text != repainted.has_text)
+ return true;
+
+ // Debugging for https://crbug.com/1237389 and https://crbug.com/1230104.
+ // Before returning that a full update is not needed, check that the
+ // properties are changed, which would indicate a missing call to
+ // SetNeedsUpdate.
+ if (previous.properties != repainted.properties) {
+ NOTREACHED();
+ return true;
+ }
return false;
}
@@ -405,310 +439,6 @@ bool PaintArtifactCompositor::HasComposited(
element_id);
}
-bool PaintArtifactCompositor::PropertyTreeStateChangedToRoot(
- const PropertyTreeState& state,
- PaintPropertyChangeType change) {
- const auto& root = PropertyTreeState::Root();
- return state.Transform().Changed(change, root.Transform()) ||
- state.Clip().Changed(change, root, &state.Transform()) ||
- state.Effect().Changed(change, root, &state.Transform());
-}
-
-bool PaintArtifactCompositor::PendingLayer::PropertyTreeStateChanged() const {
- auto change = PaintPropertyChangeType::kChangedOnlyNonRerasterValues;
- if (change_of_decomposited_transforms >= change)
- return true;
-
- return PropertyTreeStateChangedToRoot(property_tree_state, change);
-}
-
-PaintArtifactCompositor::PendingLayer::PendingLayer(
- const PaintChunkSubset& chunks,
- const PaintChunkIterator& first_chunk,
- CompositingType compositing_type)
- : bounds(first_chunk->bounds),
- rect_known_to_be_opaque(first_chunk->known_to_be_opaque ? bounds
- : FloatRect()),
- text_known_to_be_on_opaque_background(
- first_chunk->text_known_to_be_on_opaque_background),
- chunks(&chunks.GetPaintArtifact(), first_chunk.IndexInPaintArtifact()),
- property_tree_state(
- first_chunk->properties.GetPropertyTreeState().Unalias()),
- compositing_type(compositing_type) {
- DCHECK(!RequiresOwnLayer() || first_chunk->size() <= 1u);
-}
-
-PaintArtifactCompositor::PendingLayer::PendingLayer(
- const PreCompositedLayerInfo& pre_composited_layer)
- : chunks(pre_composited_layer.chunks),
- property_tree_state(
- pre_composited_layer.graphics_layer->GetPropertyTreeState()
- .Unalias()),
- graphics_layer(pre_composited_layer.graphics_layer),
- compositing_type(kPreCompositedLayer) {
- DCHECK(graphics_layer);
- DCHECK(!graphics_layer->ShouldCreateLayersAfterPaint());
-}
-
-FloatRect PaintArtifactCompositor::PendingLayer::UniteRectsKnownToBeOpaque(
- const FloatRect& a,
- const FloatRect& b) {
- // Check a or b by itself.
- FloatRect maximum(a);
- float maximum_area = a.Size().Area();
- if (b.Size().Area() > maximum_area) {
- maximum = b;
- maximum_area = b.Size().Area();
- }
- // Check the regions that include the intersection of a and b. This can be
- // done by taking the intersection and expanding it vertically and
- // horizontally. These expanded intersections will both still be fully opaque.
- FloatRect intersection = a;
- intersection.InclusiveIntersect(b);
- if (!intersection.IsZero()) {
- FloatRect vert_expanded_intersection(intersection);
- vert_expanded_intersection.ShiftYEdgeTo(std::min(a.Y(), b.Y()));
- vert_expanded_intersection.ShiftMaxYEdgeTo(std::max(a.MaxY(), b.MaxY()));
- if (vert_expanded_intersection.Size().Area() > maximum_area) {
- maximum = vert_expanded_intersection;
- maximum_area = vert_expanded_intersection.Size().Area();
- }
- FloatRect horiz_expanded_intersection(intersection);
- horiz_expanded_intersection.ShiftXEdgeTo(std::min(a.X(), b.X()));
- horiz_expanded_intersection.ShiftMaxXEdgeTo(std::max(a.MaxX(), b.MaxX()));
- if (horiz_expanded_intersection.Size().Area() > maximum_area) {
- maximum = horiz_expanded_intersection;
- maximum_area = horiz_expanded_intersection.Size().Area();
- }
- }
- return maximum;
-}
-
-FloatRect PaintArtifactCompositor::PendingLayer::MapRectKnownToBeOpaque(
- const PropertyTreeState& new_state) const {
- if (rect_known_to_be_opaque.IsEmpty())
- return FloatRect();
-
- FloatClipRect float_clip_rect(rect_known_to_be_opaque);
- GeometryMapper::LocalToAncestorVisualRect(property_tree_state, new_state,
- float_clip_rect);
- return float_clip_rect.IsTight() ? float_clip_rect.Rect() : FloatRect();
-}
-
-std::unique_ptr<JSONObject> PaintArtifactCompositor::PendingLayer::ToJSON()
- const {
- std::unique_ptr<JSONObject> result = std::make_unique<JSONObject>();
- result->SetArray("bounds", RectAsJSONArray(bounds));
- result->SetArray("rect_known_to_be_opaque",
- RectAsJSONArray(rect_known_to_be_opaque));
- result->SetObject("property_tree_state", property_tree_state.ToJSON());
- result->SetArray("offset_of_decomposited_transforms",
- PointAsJSONArray(offset_of_decomposited_transforms));
- std::unique_ptr<JSONArray> json_chunks = std::make_unique<JSONArray>();
- for (auto it = chunks.begin(); it != chunks.end(); ++it) {
- StringBuilder sb;
- sb.Append("index=");
- sb.AppendNumber(it.IndexInPaintArtifact());
- sb.Append(" ");
- sb.Append(it->ToString());
- json_chunks->PushString(sb.ToString());
- }
- result->SetArray("paint_chunks", std::move(json_chunks));
- return result;
-}
-
-FloatRect PaintArtifactCompositor::PendingLayer::VisualRectForOverlapTesting(
- const PropertyTreeState& ancestor_state) const {
- FloatClipRect visual_rect(bounds);
- GeometryMapper::LocalToAncestorVisualRect(
- property_tree_state, ancestor_state, visual_rect,
- kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect,
- kExpandVisualRectForAnimation);
- return visual_rect.Rect();
-}
-
-bool PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) {
- PropertyTreeState new_state = PropertyTreeState::Uninitialized();
- FloatRect guest_bounds;
- if (!CanMerge(guest, guest.property_tree_state, &new_state, &guest_bounds,
- &bounds)) {
- return false;
- }
-
- chunks.Merge(guest.chunks);
- rect_known_to_be_opaque =
- UniteRectsKnownToBeOpaque(MapRectKnownToBeOpaque(new_state),
- guest.MapRectKnownToBeOpaque(new_state));
- text_known_to_be_on_opaque_background &=
- (guest.text_known_to_be_on_opaque_background ||
- rect_known_to_be_opaque.Contains(guest_bounds));
- property_tree_state = new_state;
- change_of_decomposited_transforms =
- std::max(change_of_decomposited_transforms,
- guest.change_of_decomposited_transforms);
- return true;
-}
-
-void PaintArtifactCompositor::PendingLayer::Upcast(
- const PropertyTreeState& new_state) {
- DCHECK(!RequiresOwnLayer());
- if (property_tree_state == new_state)
- return;
-
- FloatClipRect float_clip_rect(bounds);
- GeometryMapper::LocalToAncestorVisualRect(property_tree_state, new_state,
- float_clip_rect);
- bounds = float_clip_rect.Rect();
-
- rect_known_to_be_opaque = MapRectKnownToBeOpaque(new_state);
- property_tree_state = new_state;
-}
-
-const PaintChunk& PaintArtifactCompositor::PendingLayer::FirstPaintChunk()
- const {
- DCHECK(!RequiresOwnLayer() || chunks.size() == 1);
- return *chunks.begin();
-}
-
-const DisplayItem& PaintArtifactCompositor::PendingLayer::FirstDisplayItem()
- const {
-#if DCHECK_IS_ON()
- // This method should never be called if the first paint chunk is empty.
- if (RequiresOwnLayer())
- DCHECK_EQ(FirstPaintChunk().size(), 1u);
- else
- DCHECK_GE(FirstPaintChunk().size(), 1u);
-#endif
- return *chunks.begin().DisplayItems().begin();
-}
-
-static bool HasCompositedTransformToAncestor(
- const TransformPaintPropertyNode& node,
- const TransformPaintPropertyNode& ancestor) {
- for (const auto* n = &node; n != &ancestor; n = n->UnaliasedParent()) {
- if (n->HasDirectCompositingReasons())
- return true;
- }
- return false;
-}
-
-// Returns the lowest common ancestor if there is no composited transform
-// between the two transforms.
-static const TransformPaintPropertyNode* NonCompositedLowestCommonAncestor(
- const TransformPaintPropertyNode& transform1,
- const TransformPaintPropertyNode& transform2) {
- const auto& lca = transform1.LowestCommonAncestor(transform2).Unalias();
- if (HasCompositedTransformToAncestor(transform1, lca) ||
- HasCompositedTransformToAncestor(transform2, lca))
- return nullptr;
- return &lca;
-}
-
-static bool ClipChainHasCompositedTransformTo(
- const ClipPaintPropertyNode& node,
- const ClipPaintPropertyNode& ancestor,
- const TransformPaintPropertyNode& transform) {
- for (const auto* n = &node; n != &ancestor; n = n->UnaliasedParent()) {
- if (!NonCompositedLowestCommonAncestor(n->LocalTransformSpace().Unalias(),
- transform))
- return true;
- }
- return false;
-}
-
-// Determines whether drawings based on the 'guest' state can be painted into
-// a layer with the 'home' state, and if yes, returns the common ancestor state
-// to which both layer will be upcasted.
-// A number of criteria need to be met:
-// 1. The guest effect must be a descendant of the home effect. However this
-// check is enforced by the layerization recursion. Here we assume the
-// guest has already been upcasted to the same effect.
-// 2. The guest transform and the home transform have compatible backface
-// visibility.
-// 3. The guest transform space must be within compositing boundary of the home
-// transform space.
-// 4. The local space of each clip and effect node on the ancestor chain must
-// be within compositing boundary of the home transform space.
-absl::optional<PropertyTreeState> CanUpcastWith(const PropertyTreeState& guest,
- const PropertyTreeState& home) {
- DCHECK_EQ(&home.Effect(), &guest.Effect());
-
- if (home.Transform().IsBackfaceHidden() !=
- guest.Transform().IsBackfaceHidden())
- return absl::nullopt;
-
- auto* upcast_transform =
- NonCompositedLowestCommonAncestor(home.Transform(), guest.Transform());
- if (!upcast_transform)
- return absl::nullopt;
-
- const auto& clip_lca =
- home.Clip().LowestCommonAncestor(guest.Clip()).Unalias();
- if (ClipChainHasCompositedTransformTo(home.Clip(), clip_lca,
- *upcast_transform) ||
- ClipChainHasCompositedTransformTo(guest.Clip(), clip_lca,
- *upcast_transform))
- return absl::nullopt;
-
- return PropertyTreeState(*upcast_transform, clip_lca, home.Effect());
-}
-
-// We will only allow merging if the merged-area:home-area+guest-area doesn't
-// exceed the ratio |kMergingSparsityTolerance|:1.
-static constexpr float kMergeSparsityTolerance = 6;
-
-bool PaintArtifactCompositor::PendingLayer::CanMerge(
- const PendingLayer& guest,
- const PropertyTreeState& guest_state,
- PropertyTreeState* out_merged_state,
- FloatRect* out_guest_bounds,
- FloatRect* out_merged_bounds) const {
- if (&chunks.GetPaintArtifact() != &guest.chunks.GetPaintArtifact())
- return false;
- if (RequiresOwnLayer() || guest.RequiresOwnLayer())
- return false;
- if (&property_tree_state.Effect() != &guest_state.Effect())
- return false;
-
- const absl::optional<PropertyTreeState>& merged_state =
- CanUpcastWith(guest_state, property_tree_state);
- if (!merged_state)
- return false;
-
- FloatClipRect new_home_bounds(bounds);
- GeometryMapper::LocalToAncestorVisualRect(property_tree_state, *merged_state,
- new_home_bounds);
- FloatClipRect new_guest_bounds(guest.bounds);
- GeometryMapper::LocalToAncestorVisualRect(guest_state, *merged_state,
- new_guest_bounds);
-
- FloatRect merged_bounds =
- UnionRect(new_home_bounds.Rect(), new_guest_bounds.Rect());
- // Don't check for sparcity if we may further decomposite the effect, so that
- // the merged layer may be merged to other layers with the decomposited
- // effect, which is often better than not merging even if the merged layer is
- // sparse because we may create less composited effects and render surfaces.
- if (guest_state.Effect().IsRoot() ||
- guest_state.Effect().HasDirectCompositingReasons()) {
- float sum_area = new_home_bounds.Rect().Size().Area() +
- new_guest_bounds.Rect().Size().Area();
- if (merged_bounds.Size().Area() > kMergeSparsityTolerance * sum_area)
- return false;
- }
-
- if (out_merged_state)
- *out_merged_state = *merged_state;
- if (out_guest_bounds)
- *out_guest_bounds = new_guest_bounds.Rect();
- if (out_merged_bounds)
- *out_merged_bounds = merged_bounds;
- return true;
-}
-
-bool PaintArtifactCompositor::PendingLayer::MayDrawContent() const {
- return chunks.size() > 1 || FirstPaintChunk().size() > 0;
-}
-
// Returns nullptr if 'ancestor' is not a strict ancestor of 'node'.
// Otherwise, return the child of 'ancestor' that is an ancestor of 'node' or
// 'node' itself.
@@ -725,48 +455,6 @@ static const EffectPaintPropertyNode* StrictUnaliasedChildOfAlongPath(
return nullptr;
}
-static const ClipPaintPropertyNode* HighestOutputClipBetween(
- const EffectPaintPropertyNode& ancestor,
- const EffectPaintPropertyNode& descendant) {
- const ClipPaintPropertyNode* result = nullptr;
- for (const auto* effect = &descendant; effect != &ancestor;
- effect = effect->UnaliasedParent()) {
- if (const auto* output_clip = effect->OutputClip())
- result = &output_clip->Unalias();
- }
- return result;
-}
-
-bool PaintArtifactCompositor::MightOverlap(const PendingLayer& layer_a,
- const PendingLayer& layer_b) {
- PropertyTreeState common_ancestor_state(
- layer_a.property_tree_state.Transform()
- .LowestCommonAncestor(layer_b.property_tree_state.Transform())
- .Unalias(),
- layer_a.property_tree_state.Clip()
- .LowestCommonAncestor(layer_b.property_tree_state.Clip())
- .Unalias(),
- layer_a.property_tree_state.Effect()
- .LowestCommonAncestor(layer_b.property_tree_state.Effect())
- .Unalias());
- // Move the common clip up if some effect nodes have OutputClip escaping the
- // common clip.
- if (const auto* clip_a =
- HighestOutputClipBetween(common_ancestor_state.Effect(),
- layer_a.property_tree_state.Effect())) {
- common_ancestor_state.SetClip(
- clip_a->LowestCommonAncestor(common_ancestor_state.Clip()).Unalias());
- }
- if (const auto* clip_b =
- HighestOutputClipBetween(common_ancestor_state.Effect(),
- layer_b.property_tree_state.Effect())) {
- common_ancestor_state.SetClip(
- clip_b->LowestCommonAncestor(common_ancestor_state.Clip()).Unalias());
- }
- return layer_a.VisualRectForOverlapTesting(common_ancestor_state)
- .Intersects(layer_b.VisualRectForOverlapTesting(common_ancestor_state));
-}
-
bool PaintArtifactCompositor::DecompositeEffect(
const EffectPaintPropertyNode& parent_effect,
wtf_size_t first_layer_in_parent_group_index,
@@ -779,7 +467,7 @@ bool PaintArtifactCompositor::DecompositeEffect(
// we are attempting to decomposite, than implies some previous decision
// did not allow to decomposite intermediate effects.
PendingLayer& layer = pending_layers_[layer_index];
- if (&layer.property_tree_state.Effect() != &effect)
+ if (&layer.GetPropertyTreeState().Effect() != &effect)
return false;
if (layer.RequiresOwnLayer())
return false;
@@ -789,10 +477,10 @@ bool PaintArtifactCompositor::DecompositeEffect(
PropertyTreeState group_state(effect.LocalTransformSpace().Unalias(),
effect.OutputClip()
? effect.OutputClip()->Unalias()
- : layer.property_tree_state.Clip(),
+ : layer.GetPropertyTreeState().Clip(),
effect);
absl::optional<PropertyTreeState> upcast_state =
- CanUpcastWith(layer.property_tree_state, group_state);
+ group_state.CanUpcastWith(layer.GetPropertyTreeState());
if (!upcast_state)
return false;
@@ -814,7 +502,7 @@ bool PaintArtifactCompositor::DecompositeEffect(
return false;
const auto& previous_sibling = pending_layers_[layer_index - 1];
if (previous_sibling.MayDrawContent() &&
- !previous_sibling.CanMerge(layer, *upcast_state))
+ !previous_sibling.CanMerge(layer, *upcast_state, prefers_lcd_text_))
return false;
}
}
@@ -823,75 +511,10 @@ bool PaintArtifactCompositor::DecompositeEffect(
return true;
}
-static bool EffectGroupContainsChunk(
- const EffectPaintPropertyNode& group_effect,
- const PaintChunk& chunk) {
- const auto& effect = chunk.properties.Effect().Unalias();
- return &effect == &group_effect ||
- StrictUnaliasedChildOfAlongPath(group_effect, effect);
-}
-
-static bool SkipGroupIfEffectivelyInvisible(
- const PaintChunkSubset& chunks,
- const EffectPaintPropertyNode& group,
- PaintChunkIterator& chunk_cursor) {
- // In pre-CompositeAfterPaint, existence of composited layers is decided
- // during compositing update before paint. Each chunk contains a foreign
- // layer corresponding a composited layer. We should not skip any of them to
- // ensure correct composited hit testing and animation.
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return false;
-
- // The lower bound of visibility is considered to be 0.0004f < 1/2048. With
- // 10-bit color channels (only available on the newest Macs as of 2016;
- // otherwise it's 8-bit), we see that an alpha of 1/2048 or less leads to a
- // color output of less than 0.5 in all channels, hence not visible.
- static const float kMinimumVisibleOpacity = 0.0004f;
- if (group.Opacity() >= kMinimumVisibleOpacity ||
- // TODO(crbug.com/937573): We should disable the optimization for all
- // cases that the invisible group will be composited, to ensure correct
- // composited hit testing and animation. Checking the effect node's
- // HasDirectCompositingReasons() is not enough.
- group.HasDirectCompositingReasons()) {
- return false;
- }
-
- // Fast-forward to just past the end of the chunk sequence within this
- // effect group.
- DCHECK(EffectGroupContainsChunk(group, *chunk_cursor));
- while (++chunk_cursor != chunks.end()) {
- if (!EffectGroupContainsChunk(group, *chunk_cursor))
- break;
- }
- return true;
-}
-
-static bool IsCompositedScrollHitTest(const PaintChunk& chunk) {
- if (!chunk.hit_test_data)
- return false;
- const auto* scroll_translation = chunk.hit_test_data->scroll_translation;
- return scroll_translation &&
- scroll_translation->HasDirectCompositingReasons();
-}
-
-static bool IsCompositedScrollbar(const DisplayItem& item) {
- if (const auto* scrollbar = DynamicTo<ScrollbarDisplayItem>(item)) {
- const auto* scroll_translation = scrollbar->ScrollTranslation();
- return scroll_translation &&
- scroll_translation->HasDirectCompositingReasons();
- }
- return false;
-}
-
void PaintArtifactCompositor::LayerizeGroup(
const PaintChunkSubset& chunks,
const EffectPaintPropertyNode& current_group,
PaintChunkIterator& chunk_cursor) {
- // Skip paint chunks that are effectively invisible due to opacity and don't
- // have a direct compositing reason.
- if (SkipGroupIfEffectivelyInvisible(chunks, current_group, chunk_cursor))
- return;
-
wtf_size_t first_layer_in_current_group = pending_layers_.size();
// The worst case time complexity of the algorithm is O(pqd), where
// p = the number of paint chunks.
@@ -918,19 +541,7 @@ void PaintArtifactCompositor::LayerizeGroup(
// C. The next chunk belongs to some subgroup of the current group.
const auto& chunk_effect = chunk_cursor->properties.Effect().Unalias();
if (&chunk_effect == &current_group) {
- // Case A: The next chunk belongs to the current group but no subgroup.
- PendingLayer::CompositingType compositing_type = PendingLayer::kOther;
- if (IsCompositedScrollHitTest(*chunk_cursor)) {
- compositing_type = PendingLayer::kScrollHitTestLayer;
- } else if (chunk_cursor->size()) {
- const auto& first_display_item = *chunk_cursor.DisplayItems().begin();
- if (first_display_item.IsForeignLayer())
- compositing_type = PendingLayer::kForeignLayer;
- else if (IsCompositedScrollbar(first_display_item))
- compositing_type = PendingLayer::kScrollbarLayer;
- }
-
- pending_layers_.emplace_back(chunks, chunk_cursor, compositing_type);
+ pending_layers_.emplace_back(chunks, chunk_cursor);
++chunk_cursor;
if (pending_layers_.back().RequiresOwnLayer())
continue;
@@ -962,18 +573,18 @@ void PaintArtifactCompositor::LayerizeGroup(
// layer.
PendingLayer& new_layer = pending_layers_.back();
DCHECK(!new_layer.RequiresOwnLayer());
- DCHECK_EQ(&current_group, &new_layer.property_tree_state.Effect());
+ DCHECK_EQ(&current_group, &new_layer.GetPropertyTreeState().Effect());
// This iterates pending_layers_[first_layer_in_current_group:-1] in
// reverse.
for (wtf_size_t candidate_index = pending_layers_.size() - 1;
candidate_index-- > first_layer_in_current_group;) {
PendingLayer& candidate_layer = pending_layers_[candidate_index];
- if (candidate_layer.Merge(new_layer)) {
+ if (candidate_layer.Merge(new_layer, prefers_lcd_text_)) {
pending_layers_.pop_back();
break;
}
- if (MightOverlap(new_layer, candidate_layer)) {
- new_layer.compositing_type = PendingLayer::kOverlap;
+ if (new_layer.MightOverlap(candidate_layer)) {
+ new_layer.SetCompositingType(PendingLayer::kOverlap);
break;
}
}
@@ -1126,6 +737,10 @@ static void UpdateCompositorViewportProperties(
property_tree_manager.EnsureCompositorTransformNode(
*properties.overscroll_elasticity_transform);
}
+ if (properties.overscroll_elasticity_effect) {
+ ids.overscroll_elasticity_effect =
+ properties.overscroll_elasticity_effect->GetCompositorElementId();
+ }
if (properties.page_scale) {
ids.page_scale_transform =
property_tree_manager.EnsureCompositorPageScaleTransformNode(
@@ -1147,109 +762,6 @@ static void UpdateCompositorViewportProperties(
layer_tree_host->RegisterViewportPropertyIds(ids);
}
-// Walk the pending layer list and build up a table of transform nodes that
-// can be de-composited (replaced with offset_to_transform_parent). A
-// transform node can be de-composited if:
-// 1. It is not the root transform node.
-// 2. It is a 2d translation only.
-// 3. The transform is not used for scrolling - its ScrollNode() is nullptr.
-// 4. The transform is not a StickyTranslation node.
-// 5. It has no direct compositing reasons, other than k3DTransform. Note
-// that if it has a k3DTransform reason, check #2 above ensures that it
-// isn't really 3D.
-// 6. It has FlattensInheritedTransform matching that of its direct parent.
-// 7. It has backface visibility matching its direct parent.
-// 8. No clips have local_transform_space referring to this transform node.
-// 9. No effects have local_transform_space referring to this transform node.
-// 10. All child transform nodes are also able to be de-composited.
-// This algorithm should be O(t+c+e) where t,c,e are the number of transform,
-// clip, and effect nodes in the full tree.
-void PaintArtifactCompositor::DecompositeTransforms() {
- HashMap<const TransformPaintPropertyNode*, bool> can_be_decomposited;
- HashSet<const void*> clips_and_effects_seen;
- for (const auto& pending_layer : pending_layers_) {
- const auto& property_state = pending_layer.property_tree_state;
-
- // Lambda to handle marking a transform node false, and walking up all
- // true parents and marking them false as well. This also handles
- // inserting transform_node if it isn't in the map, and keeps track of
- // clips or effects.
- auto mark_not_decompositable =
- [&can_be_decomposited](
- const TransformPaintPropertyNode* transform_node) {
- DCHECK(transform_node);
- while (transform_node && !transform_node->IsRoot()) {
- auto result = can_be_decomposited.insert(transform_node, false);
- if (!result.is_new_entry) {
- if (!result.stored_value->value)
- break;
- result.stored_value->value = false;
- }
- transform_node = &transform_node->Parent()->Unalias();
- }
- };
-
- // Add the transform and all transform parents to the map.
- for (const auto* node = &property_state.Transform();
- !node->IsRoot() && !can_be_decomposited.Contains(node);
- node = &node->Parent()->Unalias()) {
- if (!node->IsIdentityOr2DTranslation() || node->ScrollNode() ||
- node->GetStickyConstraint() ||
- node->IsAffectedByOuterViewportBoundsDelta() ||
- node->HasDirectCompositingReasonsOtherThan3dTransform() ||
- !node->FlattensInheritedTransformSameAsParent() ||
- !node->BackfaceVisibilitySameAsParent()) {
- mark_not_decompositable(node);
- break;
- }
- can_be_decomposited.insert(node, true);
- }
-
- // Add clips and effects, and their parents, that we haven't already seen.
- for (const auto* node = &property_state.Clip();
- !node->IsRoot() && !clips_and_effects_seen.Contains(node);
- node = &node->Parent()->Unalias()) {
- clips_and_effects_seen.insert(node);
- mark_not_decompositable(&node->LocalTransformSpace().Unalias());
- }
- for (const auto* node = &property_state.Effect();
- !node->IsRoot() && !clips_and_effects_seen.Contains(node);
- node = &node->Parent()->Unalias()) {
- clips_and_effects_seen.insert(node);
- mark_not_decompositable(&node->LocalTransformSpace().Unalias());
- }
-
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // The scroll translation node of a scroll hit test layer may not be
- // referenced by any pending layer's property tree state. Disallow
- // decomposition of it (and its ancestors).
- if (const auto* translation = ScrollTranslationForLayer(pending_layer))
- mark_not_decompositable(translation);
- }
- }
-
- // Now, for any transform nodes that can be de-composited, re-map their
- // transform to point to the correct parent, and set the
- // offset_to_transform_parent.
- for (auto& pending_layer : pending_layers_) {
- const auto* transform = &pending_layer.property_tree_state.Transform();
- while (!transform->IsRoot() && can_be_decomposited.at(transform)) {
- pending_layer.offset_of_decomposited_transforms +=
- transform->Translation2D();
- pending_layer.change_of_decomposited_transforms =
- std::max(pending_layer.change_of_decomposited_transforms,
- transform->NodeChanged());
- transform = &transform->Parent()->Unalias();
- }
- pending_layer.property_tree_state.SetTransform(*transform);
- // Move bounds into the new transform space.
- pending_layer.bounds.MoveBy(
- pending_layer.offset_of_decomposited_transforms);
- pending_layer.rect_known_to_be_opaque.MoveBy(
- pending_layer.offset_of_decomposited_transforms);
- }
-}
-
void PaintArtifactCompositor::Update(
const Vector<PreCompositedLayerInfo>& pre_composited_layers,
const ViewportProperties& viewport_properties,
@@ -1279,7 +791,7 @@ void PaintArtifactCompositor::Update(
// Make compositing decisions, storing the result in |pending_layers_|.
CollectPendingLayers(pre_composited_layers);
- DecompositeTransforms();
+ PendingLayer::DecompositeTransforms(pending_layers_);
LayerListBuilder layer_list_builder;
PropertyTreeManager property_tree_manager(*this, *host->property_trees(),
@@ -1307,28 +819,17 @@ void PaintArtifactCompositor::Update(
entry.in_use = false;
cc::LayerSelection layer_selection;
- for (auto& pending_layer : pending_layers_) {
- const auto& property_state = pending_layer.property_tree_state;
+ for (const auto& pending_layer : pending_layers_) {
+ const auto& property_state = pending_layer.GetPropertyTreeState();
const auto& transform = property_state.Transform();
const auto& clip = property_state.Clip();
- if (&clip.LocalTransformSpace() == &transform) {
- // Limit layer bounds to hide the areas that will be never visible
- // because of the clip.
- pending_layer.bounds.Intersect(clip.PixelSnappedClipRect().Rect());
- } else if (const auto* scroll = transform.ScrollNode()) {
- // Limit layer bounds to the scroll range to hide the areas that will
- // never be scrolled into the visible area.
- pending_layer.bounds.Intersect(FloatRect(
- IntRect(scroll->ContainerRect().Location(), scroll->ContentsSize())));
- }
-
scoped_refptr<cc::Layer> layer = CompositedLayerForPendingLayer(
pending_layer, new_content_layer_clients, new_scroll_hit_test_layers,
new_scrollbar_layers);
- UpdateLayerProperties(*layer, pending_layer, layer_selection,
- &property_tree_manager);
+ UpdateLayerProperties(*layer, pending_layer);
+ UpdateLayerSelection(*layer, pending_layer, layer_selection);
layer->SetLayerTreeHost(root_layer_->layer_tree_host());
@@ -1360,6 +861,8 @@ void PaintArtifactCompositor::Update(
// state but can be created via the scroll offset translation node.
const auto& scroll_translation =
NearestScrollTranslationForLayer(pending_layer);
+ // TODO(ScrollUnification): We may combine the following two calls to
+ // property_tree_manager.SetCcScrollNodeIsComposited(scroll_translation);
int scroll_id =
property_tree_manager.EnsureCompositorScrollNode(scroll_translation);
if (RuntimeEnabledFeatures::ScrollUnificationEnabled())
@@ -1399,7 +902,8 @@ void PaintArtifactCompositor::Update(
auto* new_end = std::remove_if(
synthesized_clip_cache_.begin(), synthesized_clip_cache_.end(),
[](const auto& entry) { return !entry.in_use; });
- synthesized_clip_cache_.Shrink(new_end - synthesized_clip_cache_.begin());
+ synthesized_clip_cache_.Shrink(
+ static_cast<wtf_size_t>(new_end - synthesized_clip_cache_.begin()));
// This should be done before UpdateRenderSurfaceForEffects() for which to
// get property tree node ids from the layers.
@@ -1432,100 +936,66 @@ void PaintArtifactCompositor::Update(
void PaintArtifactCompositor::UpdateLayerProperties(
cc::Layer& layer,
- const PendingLayer& pending_layer,
- cc::LayerSelection& layer_selection,
- PropertyTreeManager* property_tree_manager) {
+ const PendingLayer& pending_layer) {
// Properties of foreign layers are managed by their owners.
- if (pending_layer.compositing_type == PendingLayer::kForeignLayer)
+ if (pending_layer.GetCompositingType() == PendingLayer::kForeignLayer)
return;
- if (pending_layer.graphics_layer &&
- pending_layer.graphics_layer->PaintsContentOrHitTest()) {
- PaintChunkSubset chunks(pending_layer.graphics_layer->GetPaintController()
+ if (pending_layer.GetGraphicsLayer() &&
+ pending_layer.GetGraphicsLayer()->PaintsContentOrHitTest()) {
+ PaintChunkSubset chunks(pending_layer.GetGraphicsLayer()
+ ->GetPaintController()
.GetPaintArtifactShared());
PaintChunksToCcLayer::UpdateLayerProperties(
- layer, pending_layer.property_tree_state, chunks, layer_selection,
- property_tree_manager);
+ layer, pending_layer.GetPropertyTreeState(), chunks);
} else {
PaintChunksToCcLayer::UpdateLayerProperties(
- layer, pending_layer.property_tree_state, pending_layer.chunks,
- layer_selection, property_tree_manager);
+ layer, pending_layer.GetPropertyTreeState(), pending_layer.Chunks());
}
}
-void PaintArtifactCompositor::UpdateRepaintedLayer(
- PendingLayer& pending_layer,
+void PaintArtifactCompositor::UpdateLayerSelection(
+ cc::Layer& layer,
+ const PendingLayer& pending_layer,
cc::LayerSelection& layer_selection) {
- cc::Layer* layer = nullptr;
-
- switch (pending_layer.compositing_type) {
- case PendingLayer::kForeignLayer:
- // These layers are fully managed externally and do not need an update.
- return;
- case PendingLayer::kPreCompositedLayer:
- if (!pending_layer.graphics_layer->Repainted())
- return;
- layer = &pending_layer.graphics_layer->CcLayer();
- break;
- case PendingLayer::kScrollHitTestLayer: {
- // TODO(pdr): Share this code with ScrollHitTestLayerForPendingLayer.
- const auto* scroll_translation = ScrollTranslationForLayer(pending_layer);
- DCHECK(scroll_translation);
- const auto& scroll_node = *scroll_translation->ScrollNode();
- auto scroll_element_id = scroll_node.GetCompositorElementId();
- for (auto& existing_layer : scroll_hit_test_layers_) {
- if (existing_layer->element_id() == scroll_element_id) {
- layer = existing_layer.get();
- break;
- }
- }
- } break;
- case PendingLayer::kScrollbarLayer: {
- // TODO(pdr): Share this code with ScrollbarLayerForPendingLayer.
- const auto& item = pending_layer.FirstDisplayItem();
- layer = ScrollbarLayer(To<ScrollbarDisplayItem>(item).ElementId());
- } break;
- default: {
- ContentLayerClientImpl* content_layer_client = nullptr;
- const auto& first_chunk = pending_layer.FirstPaintChunk();
- for (auto& client : content_layer_clients_) {
- if (client && client->Matches(first_chunk)) {
- content_layer_client = client.get();
- break;
- }
- }
- CHECK(content_layer_client);
-
- bool all_moved_from_cached_subsequence = true;
- for (const auto& chunk : pending_layer.chunks) {
- if (!chunk.is_moved_from_cached_subsequence) {
- all_moved_from_cached_subsequence = false;
- break;
- }
- }
+ // Foreign layers cannot contain selection.
+ if (pending_layer.GetCompositingType() == PendingLayer::kForeignLayer)
+ return;
- // Checking |all_moved_from_cached_subsequence| is an optimization to
- // avoid the expensive call to |UpdateCcPictureLayer| when no repainting
- // occurs for this PendingLayer.
- if (all_moved_from_cached_subsequence) {
- // See RasterInvalidator::SetOldPaintArtifact() for the reason for this.
- content_layer_client->GetRasterInvalidator().SetOldPaintArtifact(
- &pending_layer.chunks.GetPaintArtifact());
- } else {
- IntRect cc_combined_bounds = EnclosingIntRect(pending_layer.bounds);
- content_layer_client->UpdateCcPictureLayer(
- pending_layer.chunks, cc_combined_bounds,
- pending_layer.property_tree_state);
- }
- layer = &content_layer_client->Layer();
- }
+ if (pending_layer.GetGraphicsLayer() &&
+ pending_layer.GetGraphicsLayer()->PaintsContentOrHitTest()) {
+ PaintChunkSubset chunks(pending_layer.GetGraphicsLayer()
+ ->GetPaintController()
+ .GetPaintArtifactShared());
+ PaintChunksToCcLayer::UpdateLayerSelection(
+ layer, pending_layer.GetPropertyTreeState(), chunks, layer_selection);
+ } else {
+ PaintChunksToCcLayer::UpdateLayerSelection(
+ layer, pending_layer.GetPropertyTreeState(), pending_layer.Chunks(),
+ layer_selection);
}
+}
- DCHECK(layer);
- UpdateLayerProperties(*layer, pending_layer, layer_selection);
+void PaintArtifactCompositor::UpdateRepaintedContentLayerClient(
+ const PendingLayer& pending_layer,
+ bool pending_layer_chunks_unchanged,
+ ContentLayerClientImpl& content_layer_client) {
+ // Checking |pending_layer_chunks_unchanged| is an optimization to avoid the
+ // expensive call to |UpdateCcPictureLayer| when no repainting occurs for this
+ // PendingLayer.
+ if (pending_layer_chunks_unchanged) {
+ // See RasterInvalidator::SetOldPaintArtifact() for the reason for this.
+ content_layer_client.GetRasterInvalidator().SetOldPaintArtifact(
+ &pending_layer.Chunks().GetPaintArtifact());
+ } else {
+ content_layer_client.UpdateCcPictureLayer(
+ pending_layer.Chunks(), pending_layer.LayerOffset(),
+ pending_layer.LayerBounds(), pending_layer.GetPropertyTreeState());
+ }
}
namespace {
+
// This class iterates forward over the PaintChunks in a vector of
// |PreCompositedLayerInfo|s.
class PreCompositedLayerPaintChunkFinder {
@@ -1570,6 +1040,7 @@ class PreCompositedLayerPaintChunkFinder {
Vector<PreCompositedLayerInfo>::iterator pre_composited_layer_it_;
PaintChunkSubset::Iterator subset_iterator_;
};
+
} // namespace
void PaintArtifactCompositor::UpdateRepaintedLayers(
@@ -1578,16 +1049,16 @@ void PaintArtifactCompositor::UpdateRepaintedLayers(
DCHECK(!needs_update_);
#if DCHECK_IS_ON()
- // Any property tree state change should have caused a full update. Some
- // chunks in |pre_composited_layers| with changed properties to be ignored
- // (see: SkipGroupIfEffectivelyInvisible) so we check the existing chunks in
- // |pending_layers_|.
- for (const auto& pending_layer : pending_layers_) {
- for (const auto& chunk : pending_layer.chunks) {
+ // Any property tree state change should have caused a full update.
+ for (const auto& pre_composited_layer : pre_composited_layers) {
+ if (pre_composited_layer.graphics_layer) {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
+ continue;
+ }
+ for (const auto& chunk : pre_composited_layer.chunks) {
// If this fires, a property tree value has changed but we are missing a
// call to |PaintArtifactCompositor::SetNeedsUpdate|.
- DCHECK(!PropertyTreeStateChangedToRoot(
- chunk.properties.GetPropertyTreeState().Unalias(),
+ DCHECK(!chunk.properties.GetPropertyTreeState().Unalias().ChangedToRoot(
PaintPropertyChangeType::kChangedOnlyNonRerasterValues));
}
}
@@ -1598,29 +1069,34 @@ void PaintArtifactCompositor::UpdateRepaintedLayers(
// The loop below iterates over the existing PendingLayers and issues updates.
PreCompositedLayerPaintChunkFinder repainted_chunk_finder(
pre_composited_layers);
+ auto* content_layer_client_it = content_layer_clients_.begin();
+ auto* scroll_hit_test_layer_it = scroll_hit_test_layers_.begin();
+ auto* scrollbar_layer_it = scrollbar_layers_.begin();
for (auto* pending_layer_it = pending_layers_.begin();
pending_layer_it != pending_layers_.end(); pending_layer_it++) {
- auto compositing_type = pending_layer_it->compositing_type;
- if (compositing_type == PendingLayer::kForeignLayer) {
+ auto compositing_type = pending_layer_it->GetCompositingType();
+ if (compositing_type == PendingLayer::kForeignLayer &&
+ !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
// These layers are fully managed externally and do not need an update.
} else if (compositing_type == PendingLayer::kPreCompositedLayer) {
- // These are Pre-CompositeAfterPaint layers where the raster invalidation
- // has already occurred and we just need to update the layer properties.
- DCHECK(pending_layer_it->graphics_layer);
- if (pending_layer_it->graphics_layer->Repainted()) {
- UpdateLayerProperties(pending_layer_it->graphics_layer->CcLayer(),
- *pending_layer_it, layer_selection);
+ // These are Pre-CompositeAfterPaint layers where raster invalidation has
+ // already occurred and we just need to update layer properties&selection.
+ DCHECK(pending_layer_it->GetGraphicsLayer());
+ if (pending_layer_it->GetGraphicsLayer()->Repainted()) {
+ UpdateLayerProperties(pending_layer_it->GetGraphicsLayer()->CcLayer(),
+ *pending_layer_it);
+ UpdateLayerSelection(pending_layer_it->GetGraphicsLayer()->CcLayer(),
+ *pending_layer_it, layer_selection);
}
} else {
// These are CompositeAfterPaint (or CompositeSVG) layers and we need to
- // both update the cc::Layer properties and issue raster invalidations
- // (both handled in |UpdateRepaintedLayer|). To update, we need the
- // previous PaintChunks (from the PendingLayer) and the matching repainted
- // PaintChunks (from |pre_composited_layers|). Because repaint-only
- // updates cannot add, remove, or re-order PaintChunks, we use
- // |repainted_chunk_finder| to search forward in |pre_composited_layers|
- // for the matching paint chunk which ensures this is O(chunks).
- const PaintChunk& first = *pending_layer_it->chunks.begin();
+ // both copy the repainted paint chunks and update the cc::Layer. To do
+ // this, we need the previous PaintChunks (from the PendingLayer) and the
+ // matching repainted PaintChunks (from |pre_composited_layers|). Because
+ // repaint-only updates cannot add, remove, or re-order PaintChunks,
+ // |repainted_chunk_finder| searches forward in |pre_composited_layers|
+ // for the matching paint chunk, ensuring this function is O(chunks).
+ const PaintChunk& first = *pending_layer_it->Chunks().begin();
bool did_advance = repainted_chunk_finder.AdvanceToMatching(first);
// If we do not find a matching PaintChunk, PaintChunks must have been
@@ -1628,12 +1104,56 @@ void PaintArtifactCompositor::UpdateRepaintedLayers(
// instead of a repaint update.
CHECK(did_advance);
- // Because chunks were not added, removed, or re-ordered, we can simply
- // swap in the repainted PaintArtifact and the chunk indices will still be
- // valid.
- pending_layer_it->chunks.SetPaintArtifact(
- &repainted_chunk_finder.current_artifact());
- UpdateRepaintedLayer(*pending_layer_it, layer_selection);
+ // Essentially replace the paint chunks of the pending layer with the
+ // repainted chunks in |repainted_artifact|. The pending layer's paint
+ // chunks (a |PaintChunkSubset|) actually store indices to |PaintChunk|s
+ // in a |PaintArtifact|. In repaint updates, chunks are not added,
+ // removed, or re-ordered, so we can simply swap in a repainted
+ // |PaintArtifact| instead of copying |PaintChunk|s individually.
+ const PaintArtifact& previous_artifact =
+ pending_layer_it->Chunks().GetPaintArtifact();
+ const PaintArtifact& repainted_artifact =
+ repainted_chunk_finder.current_artifact();
+ DCHECK_EQ(previous_artifact.PaintChunks().size(),
+ repainted_artifact.PaintChunks().size());
+ pending_layer_it->SetPaintArtifact(&repainted_artifact);
+
+ bool pending_layer_chunks_unchanged = true;
+ for (const auto& chunk : pending_layer_it->Chunks()) {
+ if (!chunk.is_moved_from_cached_subsequence) {
+ pending_layer_chunks_unchanged = false;
+ break;
+ }
+ }
+
+ cc::Layer* cc_layer = nullptr;
+ switch (pending_layer_it->GetCompositingType()) {
+ case PendingLayer::kPreCompositedLayer:
+ NOTREACHED();
+ break;
+ case PendingLayer::kForeignLayer:
+ continue;
+ case PendingLayer::kScrollbarLayer:
+ cc_layer = scrollbar_layer_it->get();
+ ++scrollbar_layer_it;
+ break;
+ case PendingLayer::kScrollHitTestLayer:
+ cc_layer = scroll_hit_test_layer_it->get();
+ ++scroll_hit_test_layer_it;
+ break;
+ default:
+ UpdateRepaintedContentLayerClient(*pending_layer_it,
+ pending_layer_chunks_unchanged,
+ **content_layer_client_it);
+ cc_layer = &(*content_layer_client_it)->Layer();
+ ++content_layer_client_it;
+ break;
+ }
+ DCHECK(cc_layer);
+
+ if (!pending_layer_chunks_unchanged)
+ UpdateLayerProperties(*cc_layer, *pending_layer_it);
+ UpdateLayerSelection(*cc_layer, *pending_layer_it, layer_selection);
}
}
@@ -1759,7 +1279,7 @@ void PaintArtifactCompositor::UpdateRenderSurfaceForEffects(
const Vector<const EffectPaintPropertyNode*>& blink_effects) {
// This vector is indexed by effect node id. The value is the number of
// layers and sub-render-surfaces controlled by this effect.
- Vector<int> effect_layer_counts(effect_tree.size());
+ Vector<int> effect_layer_counts(static_cast<wtf_size_t>(effect_tree.size()));
// Initialize the vector to count directly controlled layers.
for (const auto& layer : layers) {
if (layer->DrawsContent())
@@ -1769,7 +1289,7 @@ void PaintArtifactCompositor::UpdateRenderSurfaceForEffects(
// In the effect tree, parent always has lower id than children, so the
// following loop will check descendants before parents and accumulate
// effect_layer_counts.
- for (auto id = effect_tree.size() - 1;
+ for (int id = static_cast<int>(effect_tree.size() - 1);
id > cc::EffectTree::kSecondaryRootNodeId; id--) {
auto* effect = effect_tree.Node(id);
if (effect_layer_counts[id] > 1) {
@@ -1852,15 +1372,11 @@ void PaintArtifactCompositor::UpdateDebugInfo() const {
for (const auto& pending_layer : pending_layers_) {
cc::Layer* layer;
RasterInvalidationTracking* tracking = nullptr;
- switch (pending_layer.compositing_type) {
- case PendingLayer::kScrollHitTestLayer:
- layer = scroll_hit_test_layer_it->get();
- ++scroll_hit_test_layer_it;
- break;
+ switch (pending_layer.GetCompositingType()) {
case PendingLayer::kPreCompositedLayer:
tracking =
- pending_layer.graphics_layer->GetRasterInvalidationTracking();
- layer = &pending_layer.graphics_layer->CcLayer();
+ pending_layer.GetGraphicsLayer()->GetRasterInvalidationTracking();
+ layer = &pending_layer.GetGraphicsLayer()->CcLayer();
break;
case PendingLayer::kForeignLayer:
layer = To<ForeignLayerDisplayItem>(pending_layer.FirstDisplayItem())
@@ -1870,6 +1386,10 @@ void PaintArtifactCompositor::UpdateDebugInfo() const {
layer = scrollbar_layer_it->get();
++scrollbar_layer_it;
break;
+ case PendingLayer::kScrollHitTestLayer:
+ layer = scroll_hit_test_layer_it->get();
+ ++scroll_hit_test_layer_it;
+ break;
default:
tracking =
(*content_layer_client_it)->GetRasterInvalidator().GetTracking();
@@ -1879,8 +1399,8 @@ void PaintArtifactCompositor::UpdateDebugInfo() const {
}
UpdateLayerDebugInfo(
*layer,
- pending_layer.graphics_layer
- ? PaintChunk::Id(*pending_layer.graphics_layer,
+ pending_layer.GetGraphicsLayer()
+ ? PaintChunk::Id(*pending_layer.GetGraphicsLayer(),
DisplayItem::kUninitializedType)
: pending_layer.FirstPaintChunk().id,
GetCompositingReasons(pending_layer, previous_pending_layer), tracking);
@@ -1888,26 +1408,16 @@ void PaintArtifactCompositor::UpdateDebugInfo() const {
}
}
-cc::ScrollbarLayerBase* PaintArtifactCompositor::ScrollbarLayer(
- CompositorElementId element_id) {
- for (auto& layer : scrollbar_layers_) {
- if (layer->element_id() == element_id)
- return layer.get();
- }
- return nullptr;
-}
-
CompositingReasons PaintArtifactCompositor::GetCompositingReasons(
const PendingLayer& layer,
const PendingLayer* previous_layer) const {
DCHECK(layer_debug_info_enabled_);
- if (layer.graphics_layer)
- return layer.graphics_layer->GetCompositingReasons();
+ if (layer.GetGraphicsLayer())
+ return layer.GetGraphicsLayer()->GetCompositingReasons();
if (layer.RequiresOwnLayer()) {
- const auto& first_chunk = layer.FirstPaintChunk();
- if (IsCompositedScrollHitTest(first_chunk))
+ if (layer.GetCompositingType() == PendingLayer::kScrollHitTestLayer)
return CompositingReason::kOverflowScrolling;
switch (layer.FirstDisplayItem().GetType()) {
case DisplayItem::kForeignLayerCanvas:
@@ -1926,21 +1436,25 @@ CompositingReasons PaintArtifactCompositor::GetCompositingReasons(
}
CompositingReasons reasons = CompositingReason::kNone;
- if (!previous_layer || &layer.property_tree_state.Transform() !=
- &previous_layer->property_tree_state.Transform()) {
- reasons |= layer.property_tree_state.Transform()
+ if (!previous_layer ||
+ &layer.GetPropertyTreeState().Transform() !=
+ &previous_layer->GetPropertyTreeState().Transform()) {
+ reasons |= layer.GetPropertyTreeState()
+ .Transform()
.DirectCompositingReasonsForDebugging();
- if (!layer.property_tree_state.Transform().BackfaceVisibilitySameAsParent())
+ if (!layer.GetPropertyTreeState()
+ .Transform()
+ .BackfaceVisibilitySameAsParent())
reasons |= CompositingReason::kBackfaceVisibilityHidden;
}
- if (!previous_layer || &layer.property_tree_state.Effect() !=
- &previous_layer->property_tree_state.Effect()) {
- const auto& effect = layer.property_tree_state.Effect();
+ if (!previous_layer || &layer.GetPropertyTreeState().Effect() !=
+ &previous_layer->GetPropertyTreeState().Effect()) {
+ const auto& effect = layer.GetPropertyTreeState().Effect();
if (effect.HasDirectCompositingReasons())
reasons |= effect.DirectCompositingReasonsForDebugging();
if (reasons == CompositingReason::kNone &&
- layer.compositing_type == PendingLayer::kOther) {
+ layer.GetCompositingType() == PendingLayer::kOther) {
if (effect.Opacity() != 1.0f)
reasons |= CompositingReason::kOpacityWithCompositedDescendants;
if (!effect.Filter().IsEmpty())
@@ -1953,7 +1467,7 @@ CompositingReasons PaintArtifactCompositor::GetCompositingReasons(
}
if (reasons == CompositingReason::kNone &&
- layer.compositing_type == PendingLayer::kOverlap)
+ layer.GetCompositingType() == PendingLayer::kOverlap)
reasons = CompositingReason::kOverlap;
return reasons;
@@ -1969,18 +1483,37 @@ Vector<cc::Layer*> PaintArtifactCompositor::SynthesizedClipLayersForTesting()
void PaintArtifactCompositor::ClearPropertyTreeChangedState() {
for (auto& layer : pending_layers_) {
- layer.property_tree_state.ClearChangedTo(PropertyTreeState::Root());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // The chunks ref-counted property tree state keeps the |layer|'s non-ref
+ // property tree pointers alive and all chunk property tree states should
+ // be descendants of the |layer|'s. Therefore, we can just CHECK that the
+ // first chunk's references are keeping the |layer|'s property tree state
+ // alive.
+ CHECK(!layer.Chunks().IsEmpty());
+ const auto& layer_state = layer.GetPropertyTreeState();
+ const auto& first_chunk_state =
+ layer.Chunks().begin()->properties.GetPropertyTreeState();
+ CHECK(
+ layer_state.Transform().IsAncestorOf(first_chunk_state.Transform()));
+ CHECK(layer_state.Clip().IsAncestorOf(first_chunk_state.Clip()));
+ CHECK(layer_state.Effect().IsAncestorOf(first_chunk_state.Effect()));
+ }
+
+ layer.GetPropertyTreeState().ClearChangedTo(PropertyTreeState::Root());
+
PaintChunkSubset chunks =
- layer.graphics_layer && layer.graphics_layer->PaintsContentOrHitTest()
- ? PaintChunkSubset(layer.graphics_layer->GetPaintController()
+ layer.GetGraphicsLayer() &&
+ layer.GetGraphicsLayer()->PaintsContentOrHitTest()
+ ? PaintChunkSubset(layer.GetGraphicsLayer()
+ ->GetPaintController()
.GetPaintArtifactShared())
- : layer.chunks;
+ : layer.Chunks();
for (auto& chunk : chunks) {
// Calling |ClearChangedTo| for every chunk could be O(|property nodes|^2)
// in the worst case and could be optimized by caching which nodes that
// have already been cleared.
chunk.properties.GetPropertyTreeState().ClearChangedTo(
- layer.property_tree_state);
+ layer.GetPropertyTreeState());
}
}
}
@@ -1996,17 +1529,21 @@ size_t PaintArtifactCompositor::ApproximateUnsharedMemoryUsage() const {
result += client->ApproximateUnsharedMemoryUsage();
for (auto& layer : pending_layers_) {
- size_t chunks_size = layer.chunks.ApproximateUnsharedMemoryUsage();
- DCHECK_GE(chunks_size, sizeof(layer.chunks));
- result += chunks_size - sizeof(layer.chunks);
+ size_t chunks_size = layer.Chunks().ApproximateUnsharedMemoryUsage();
+ DCHECK_GE(chunks_size, sizeof(layer.Chunks()));
+ result += chunks_size - sizeof(layer.Chunks());
}
return result;
}
void PaintArtifactCompositor::SetScrollbarNeedsDisplay(
CompositorElementId element_id) {
- if (auto* scrollbar_layer = ScrollbarLayer(element_id))
- scrollbar_layer->SetNeedsDisplay();
+ for (auto& layer : scrollbar_layers_) {
+ if (layer->element_id() == element_id) {
+ layer->SetNeedsDisplay();
+ return;
+ }
+ }
}
void LayerListBuilder::Add(scoped_refptr<cc::Layer> layer) {
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 c55163be9af..695739a3517 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,7 +8,6 @@
#include <memory>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "cc/input/layer_selection_bound.h"
@@ -17,6 +16,7 @@
#include "cc/layers/picture_layer.h"
#include "cc/trees/property_tree.h"
#include "third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/pending_layer.h"
#include "third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h"
#include "third_party/blink/renderer/platform/graphics/compositing_reasons.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
@@ -43,21 +43,6 @@ class SynthesizedClip;
using CompositorScrollCallbacks = cc::ScrollCallbacks;
-// Information of a composited layer that is created during compositing update
-// in pre-CompositeAfterPaint. In CompositeAfterPaint, this is expected to
-// contain all paint chunks, as if we created one root layer that needs to be
-// future layerized.
-struct PreCompositedLayerInfo {
- // For now this is used only when graphics_layer == nullptr. This will also
- // contain the paint chunks for the graphics layer when we unify
- // PaintController for pre-CAP and CAP.
- PaintChunkSubset chunks;
- // If this is not nullptr, we should use the composited layer created by the
- // GraphicsLayer. Otherwise we should layerize |chunks|. A GraphicsLayer with
- // ShouldCreateLayersAfterPaint() == true should set this field to nullptr.
- const GraphicsLayer* graphics_layer = nullptr;
-};
-
class LayerListBuilder {
public:
void Add(scoped_refptr<cc::Layer>);
@@ -137,10 +122,13 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
public:
PaintArtifactCompositor(
base::WeakPtr<CompositorScrollCallbacks> scroll_callbacks);
+ PaintArtifactCompositor(const PaintArtifactCompositor&) = delete;
+ PaintArtifactCompositor& operator=(const PaintArtifactCompositor&) = delete;
~PaintArtifactCompositor() override;
struct ViewportProperties {
const TransformPaintPropertyNode* overscroll_elasticity_transform = nullptr;
+ const EffectPaintPropertyNode* overscroll_elasticity_effect = nullptr;
const TransformPaintPropertyNode* page_scale = nullptr;
const TransformPaintPropertyNode* inner_scroll_translation = nullptr;
const ClipPaintPropertyNode* outer_clip = nullptr;
@@ -223,6 +211,8 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
bool NeedsUpdate() const { return needs_update_; }
void ClearNeedsUpdateForTesting() { needs_update_ = false; }
+ void SetPrefersLCDText(bool);
+
// There is no mechanism for doing a paint lifecycle phase without running
// PaintArtifactCompositor::Update so this is exposed so tests can check the
// last update type.
@@ -241,11 +231,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// on any of the PropertyTrees constructed by |Update|.
bool HasComposited(CompositorElementId element_id) const;
- // Returns true if any property tree state change is >= |change|. Note that
- // this is O(|nodes|).
- static bool PropertyTreeStateChangedToRoot(const PropertyTreeState&,
- PaintPropertyChangeType change);
-
void SetLayerDebugInfoEnabled(bool);
Vector<cc::Layer*> SynthesizedClipLayersForTesting() const;
@@ -257,90 +242,17 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
void SetScrollbarNeedsDisplay(CompositorElementId element_id);
private:
- // A pending layer is a collection of paint chunks that will end up in
- // the same cc::Layer.
- struct PLATFORM_EXPORT PendingLayer {
- enum CompositingType {
- kScrollHitTestLayer,
- kPreCompositedLayer,
- kForeignLayer,
- kScrollbarLayer,
- kOverlap,
- kOther,
- };
-
- PendingLayer(const PaintChunkSubset&,
- const PaintChunkIterator&,
- CompositingType compositng_type = kOther);
- explicit PendingLayer(const PreCompositedLayerInfo&);
-
- // Merges |guest| into |this| if it can, by appending chunks of |guest|
- // after chunks of |this|, with appropriate space conversion applied to
- // both layers from their original property tree states to |merged_state|.
- // Returns whether the merge is successful.
- bool Merge(const PendingLayer& guest);
-
- // Returns true if |guest| can be merged into |this|, and sets the output
- // parameters with the property tree state and bounds of the merged layer.
- // |guest_state| is for cases that we want to check if we can merge |guest|
- // if it has |guest_state| in the future (which may be different from its
- // current state).
- bool CanMerge(const PendingLayer& guest,
- const PropertyTreeState& guest_state,
- PropertyTreeState* out_merged_state = nullptr,
- FloatRect* out_guest_bounds = nullptr,
- FloatRect* out_merged_bounds = nullptr) const;
-
- // Mutate this layer's property tree state to a more general (shallower)
- // state, thus the name "upcast". The concrete effect of this is to
- // "decomposite" some of the properties, so that fewer properties will be
- // applied by the compositor, and more properties will be applied internally
- // to the chunks as Skia commands.
- void Upcast(const PropertyTreeState&);
-
- const PaintChunk& FirstPaintChunk() const;
- const DisplayItem& FirstDisplayItem() const;
-
- // Returns the largest rect known to be opaque given two opaque rects.
- static FloatRect UniteRectsKnownToBeOpaque(const FloatRect&,
- const FloatRect&);
- FloatRect MapRectKnownToBeOpaque(const PropertyTreeState&) const;
-
- std::unique_ptr<JSONObject> ToJSON() const;
-
- FloatRect VisualRectForOverlapTesting(
- const PropertyTreeState& ancestor_state) const;
-
- bool MayDrawContent() const;
-
- bool RequiresOwnLayer() const {
- return compositing_type != kOverlap && compositing_type != kOther;
- }
-
- bool PropertyTreeStateChanged() const;
-
- // The rects are in the space of property_tree_state.
- FloatRect bounds;
- FloatRect rect_known_to_be_opaque;
- bool text_known_to_be_on_opaque_background;
- PaintChunkSubset chunks;
- PropertyTreeState property_tree_state;
- FloatPoint offset_of_decomposited_transforms;
- PaintPropertyChangeType change_of_decomposited_transforms =
- PaintPropertyChangeType::kUnchanged;
- const GraphicsLayer* graphics_layer = nullptr;
- CompositingType compositing_type;
- };
-
- static void UpdateLayerProperties(cc::Layer&,
- const PendingLayer&,
- cc::LayerSelection& layer_selection,
- PropertyTreeManager* = nullptr);
-
- void UpdateRepaintedLayer(PendingLayer& pending_layer,
- cc::LayerSelection& layer_selection);
-
- void DecompositeTransforms();
+ static void UpdateLayerProperties(cc::Layer&, const PendingLayer&);
+ static void UpdateLayerSelection(cc::Layer&,
+ const PendingLayer&,
+ cc::LayerSelection& layer_selection);
+
+ // Updates |content_layer_client| associated with a |pending_layer| following
+ // a paint. This includes updating the drawings and raster invalidation.
+ void UpdateRepaintedContentLayerClient(
+ const PendingLayer& pending_layer,
+ bool pending_layer_chunks_unchanged,
+ ContentLayerClientImpl& content_layer_client);
// Collects the PaintChunks into groups which will end up in the same
// cc layer. This is the entry point of the layerization algorithm.
@@ -366,7 +278,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
void LayerizeGroup(const PaintChunkSubset&,
const EffectPaintPropertyNode&,
PaintChunkIterator& chunk_cursor);
- static bool MightOverlap(const PendingLayer&, const PendingLayer&);
bool DecompositeEffect(const EffectPaintPropertyNode& parent_effect,
wtf_size_t first_layer_in_parent_group_index,
const EffectPaintPropertyNode& effect,
@@ -383,11 +294,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
const TransformPaintPropertyNode& NearestScrollTranslationForLayer(
const PendingLayer&);
- // If the pending layer has scroll hit test data, return the associated
- // scroll translation node.
- const TransformPaintPropertyNode* ScrollTranslationForLayer(
- const PendingLayer&);
-
// Returns the cc::Layer if the pending layer contains a foreign layer or a
// wrapper of a GraphicsLayer. If it's the latter and the graphics layer has
// been repainted, also updates the layer properties.
@@ -432,8 +338,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
void UpdateDebugInfo() const;
- cc::ScrollbarLayerBase* ScrollbarLayer(CompositorElementId);
-
// For notifying blink of composited scrolling.
base::WeakPtr<CompositorScrollCallbacks> scroll_callbacks_;
@@ -441,6 +345,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
bool needs_update_ = true;
PreviousUpdateType previous_update_for_testing_ = PreviousUpdateType::kNone;
bool layer_debug_info_enabled_ = false;
+ bool prefers_lcd_text_ = false;
scoped_refptr<cc::Layer> root_layer_;
Vector<std::unique_ptr<ContentLayerClientImpl>> content_layer_clients_;
@@ -458,8 +363,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
friend class StubChromeClientForCAP;
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 32ad106f058..0d01b1f672b 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
@@ -62,7 +62,7 @@ void SetTransform(PaintChunk& chunk,
class MockScrollCallbacks : public CompositorScrollCallbacks {
public:
- MOCK_METHOD3(DidScroll,
+ MOCK_METHOD3(DidCompositorScroll,
void(CompositorElementId,
const gfx::ScrollOffset&,
const absl::optional<cc::TargetSnapAreaElementIds>&));
@@ -87,6 +87,8 @@ class PaintArtifactCompositorTest : public testing::Test,
// Delay constructing the compositor until after the feature is set.
paint_artifact_compositor_ = std::make_unique<PaintArtifactCompositor>(
scroll_callbacks_.GetWeakPtr());
+ // Prefer compositing to lcd-text by default for tests.
+ paint_artifact_compositor_->SetPrefersLCDText(true);
// Uses a LayerTreeHostClient that will make a LayerTreeFrameSink to allow
// the compositor to run and submit frames.
@@ -228,43 +230,24 @@ class PaintArtifactCompositorTest : public testing::Test,
return -1;
}
- void AddSimpleRectChunk(TestPaintArtifact& artifact) {
- artifact.Chunk().RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
- }
-
- void UpdateWithArtifactWithOpacity(float opacity,
- bool include_preceding_chunk,
- bool include_subsequent_chunk) {
+ void UpdateWithEffectivelyInvisibleChunk(bool include_preceding_chunk,
+ bool include_subsequent_chunk) {
TestPaintArtifact artifact;
if (include_preceding_chunk)
- AddSimpleRectChunk(artifact);
- auto effect = CreateOpacityEffect(e0(), opacity);
- artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ artifact.Chunk().RectDrawing(IntRect(0, 0, 10, 10), Color::kBlack);
+ artifact.Chunk().EffectivelyInvisible().RectDrawing(IntRect(10, 0, 10, 10),
+ Color(255, 0, 0));
if (include_subsequent_chunk)
- AddSimpleRectChunk(artifact);
+ artifact.Chunk().RectDrawing(IntRect(0, 10, 10, 10), Color::kWhite);
Update(artifact.Build());
}
- using PendingLayer = PaintArtifactCompositor::PendingLayer;
-
- bool MightOverlap(const PendingLayer& a, const PendingLayer& b) {
- return PaintArtifactCompositor::MightOverlap(a, b);
- }
-
MockScrollCallbacks& ScrollCallbacks() { return scroll_callbacks_; }
PaintArtifactCompositor& GetPaintArtifactCompositor() {
return *paint_artifact_compositor_;
}
- Vector<wtf_size_t> ChunkIndices(const PendingLayer& layer) {
- Vector<wtf_size_t> indices;
- for (auto it = layer.chunks.begin(); it != layer.chunks.end(); ++it)
- indices.push_back(it.IndexInPaintArtifact());
- return indices;
- }
-
private:
MockScrollCallbacks scroll_callbacks_;
std::unique_ptr<PaintArtifactCompositor> paint_artifact_compositor_;
@@ -310,7 +293,7 @@ TEST_P(PaintArtifactCompositorTest, OneTransform) {
.RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -322,7 +305,7 @@ TEST_P(PaintArtifactCompositorTest, OneTransform) {
rects_with_color.push_back(
RectWithColor(FloatRect(0, 0, 100, 100), Color::kWhite));
rects_with_color.push_back(
- RectWithColor(FloatRect(100, 100, 200, 100), Color::kBlack));
+ RectWithColor(FloatRect(100, 0, 100, 100), Color::kBlack));
EXPECT_THAT(layer->GetPicture(),
Pointee(DrawsRectangles(rects_with_color)));
@@ -352,7 +335,7 @@ TEST_P(PaintArtifactCompositorTest, OneTransformWithAlias) {
.RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -364,7 +347,7 @@ TEST_P(PaintArtifactCompositorTest, OneTransformWithAlias) {
rects_with_color.push_back(
RectWithColor(FloatRect(0, 0, 100, 100), Color::kWhite));
rects_with_color.push_back(
- RectWithColor(FloatRect(100, 100, 200, 100), Color::kBlack));
+ RectWithColor(FloatRect(100, 0, 100, 100), Color::kBlack));
EXPECT_THAT(layer->GetPicture(),
Pointee(DrawsRectangles(rects_with_color)));
@@ -860,37 +843,36 @@ TEST_P(PaintArtifactCompositorTest, DeeplyNestedClips) {
TEST_P(PaintArtifactCompositorTest, SiblingClipsWithAlias) {
auto real_common_clip =
- CreateClip(c0(), t0(), FloatRoundedRect(0, 0, 800, 600));
+ CreateClip(c0(), t0(), FloatRoundedRect(0, 0, 80, 60));
auto common_clip = ClipPaintPropertyNodeAlias::Create(*real_common_clip);
auto real_clip1 =
- CreateClip(*common_clip, t0(), FloatRoundedRect(0, 0, 300, 200));
+ CreateClip(*common_clip, t0(), FloatRoundedRect(0, 0, 30, 20));
auto clip1 = ClipPaintPropertyNodeAlias::Create(*real_clip1);
auto real_clip2 =
- CreateClip(*common_clip, t0(), FloatRoundedRect(400, 0, 400, 600));
+ CreateClip(*common_clip, t0(), FloatRoundedRect(40, 0, 40, 60));
auto clip2 = ClipPaintPropertyNodeAlias::Create(*real_clip2);
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip1, e0())
- .RectDrawing(IntRect(0, 0, 111, 222), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 11, 22), Color::kWhite);
artifact.Chunk(t0(), *clip2, e0())
- .RectDrawing(IntRect(333, 444, 555, 666), Color::kBlack);
+ .RectDrawing(IntRect(33, 44, 55, 66), Color::kBlack);
Update(artifact.Build());
// The two chunks are merged together.
ASSERT_EQ(1u, LayerCount());
const cc::Layer* layer = LayerAt(0);
- EXPECT_THAT(
- layer->GetPicture(),
- Pointee(DrawsRectangles(Vector<RectWithColor>{
- // This is the first RectDrawing with real_clip1 applied.
- RectWithColor(FloatRect(0, 0, 111, 200), Color::kWhite),
- // This is the second RectDrawing with real_clip2 applied.
- RectWithColor(FloatRect(400, 444, 400, 156), Color::kBlack)})));
+ EXPECT_THAT(layer->GetPicture(),
+ Pointee(DrawsRectangles(Vector<RectWithColor>{
+ // This is the first RectDrawing with real_clip1 applied.
+ RectWithColor(FloatRect(0, 0, 11, 20), Color::kWhite),
+ // This is the second RectDrawing with real_clip2 applied.
+ RectWithColor(FloatRect(40, 44, 40, 16), Color::kBlack)})));
EXPECT_EQ(gfx::Transform(), layer->ScreenSpaceTransform());
const cc::ClipNode* clip_node =
GetPropertyTrees().clip_tree.Node(layer->clip_tree_index());
EXPECT_EQ(cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP, clip_node->clip_type);
- ASSERT_EQ(gfx::RectF(0, 0, 800, 600), clip_node->clip);
+ ASSERT_EQ(gfx::RectF(0, 0, 80, 60), clip_node->clip);
}
TEST_P(PaintArtifactCompositorTest, SiblingClipsWithCompositedTransform) {
@@ -1133,9 +1115,10 @@ TEST_P(PaintArtifactCompositorTest, OneScrollNodeComposited) {
EXPECT_EQ(scroll_layer->scroll_tree_index(), scroll_node.id);
absl::optional<cc::TargetSnapAreaElementIds> targets;
- EXPECT_CALL(ScrollCallbacks(), DidScroll(scroll_node.element_id,
- gfx::ScrollOffset(1, 2), targets));
- GetPropertyTrees().scroll_tree.NotifyDidScroll(
+ EXPECT_CALL(ScrollCallbacks(),
+ DidCompositorScroll(scroll_node.element_id,
+ gfx::ScrollOffset(1, 2), targets));
+ GetPropertyTrees().scroll_tree.NotifyDidCompositorScroll(
scroll_node.element_id, gfx::ScrollOffset(1, 2), targets);
EXPECT_CALL(ScrollCallbacks(),
@@ -1145,11 +1128,6 @@ TEST_P(PaintArtifactCompositorTest, OneScrollNodeComposited) {
}
TEST_P(PaintArtifactCompositorTest, OneScrollNodeNonComposited) {
- // In pre-CompositeAfterPaint, PaintArtifactCompositor doesn't see
- // non-composited scroll node.
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
CompositorElementId scroll_element_id = ScrollElementId(2);
auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
kNotScrollingOnMain, scroll_element_id);
@@ -1161,10 +1139,10 @@ TEST_P(PaintArtifactCompositorTest, OneScrollNodeNonComposited) {
.RectDrawing(IntRect(-110, 12, 170, 19), Color::kWhite);
Update(artifact.Build());
- // Node #0 reserved for null; #1 for root render surface; #2 is the blink
- // scroll translation.
- EXPECT_EQ(3u, GetPropertyTrees().scroll_tree.size());
- EXPECT_EQ(3u, GetPropertyTrees().transform_tree.size());
+ // Blink scroll nodes not referenced by composited transforms don't create
+ // cc scroll nodes.
+ EXPECT_EQ(2u, GetPropertyTrees().scroll_tree.size());
+ EXPECT_EQ(2u, GetPropertyTrees().transform_tree.size());
EXPECT_EQ(1u, LayerCount());
}
@@ -1372,8 +1350,10 @@ TEST_P(PaintArtifactCompositorTest, AncestorScrollNodes) {
t0(), 11, 13, *scroll_a, CompositingReason::kLayerForScrollingContents);
CompositorElementId scroll_element_id_b = ScrollElementId(3);
- auto scroll_b = CreateScroll(*scroll_a, ScrollState2(), kNotScrollingOnMain,
- scroll_element_id_b);
+ auto scroll_b =
+ CreateScroll(*scroll_a, ScrollState2(),
+ cc::MainThreadScrollingReason::kNotOpaqueForTextAndLCDText,
+ scroll_element_id_b);
auto scroll_translation_b =
CreateScrollTranslation(*scroll_translation_a, 37, 41, *scroll_b);
@@ -1383,35 +1363,23 @@ TEST_P(PaintArtifactCompositorTest, AncestorScrollNodes) {
Update(artifact.Build());
const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
- // Node #0 reserved for null; #1 for root render surface.
- ASSERT_EQ(4u, scroll_tree.size());
+ // Node #0 reserved for null; #1 for root render surface. #2 is for scroll_a.
+ // We don't need to create cc scroll node for scroll_b which doesn't use
+ // composited scrolling.
+ ASSERT_EQ(3u, scroll_tree.size());
const cc::ScrollNode& scroll_node_a = *scroll_tree.Node(2);
EXPECT_EQ(1, scroll_node_a.parent_id);
EXPECT_EQ(scroll_element_id_a, scroll_node_a.element_id);
EXPECT_EQ(scroll_node_a.id, ElementIdToScrollNodeIndex(scroll_element_id_a));
- // The second scrollable layer should be associated with the first scroll node
- // (a).
- EXPECT_EQ(scroll_element_id_a, ScrollableLayerAt(1)->element_id());
+ // The first scrollable layer should be associated with scroll_a.
+ EXPECT_EQ(scroll_element_id_a, ScrollableLayerAt(0)->element_id());
const cc::TransformTree& transform_tree = GetPropertyTrees().transform_tree;
const cc::TransformNode& transform_node_a =
*transform_tree.Node(scroll_node_a.transform_id);
EXPECT_TRUE(transform_node_a.local.IsIdentity());
EXPECT_EQ(gfx::ScrollOffset(-11, -13), transform_node_a.scroll_offset);
-
- const cc::ScrollNode& scroll_node_b = *scroll_tree.Node(3);
- EXPECT_EQ(scroll_node_a.id, scroll_node_b.parent_id);
- EXPECT_EQ(scroll_element_id_b, scroll_node_b.element_id);
- EXPECT_EQ(scroll_node_b.id, ElementIdToScrollNodeIndex(scroll_element_id_b));
- // The first scrollable layer should be associated with the second scroll node
- // (b).
- EXPECT_EQ(scroll_element_id_b, ScrollableLayerAt(0)->element_id());
-
- const cc::TransformNode& transform_node_b =
- *transform_tree.Node(scroll_node_b.transform_id);
- EXPECT_TRUE(transform_node_b.local.IsIdentity());
- EXPECT_EQ(gfx::ScrollOffset(-37, -41), transform_node_b.scroll_offset);
}
TEST_P(PaintArtifactCompositorTest, MergeSimpleChunks) {
@@ -1666,20 +1634,6 @@ TEST_P(PaintArtifactCompositorTest, MergeNestedWithAlias) {
}
}
-TEST_P(PaintArtifactCompositorTest, CanNotMergeAcrossPaintArtifacts) {
- TestPaintArtifact test_artifact_a;
- test_artifact_a.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
- PaintChunkSubset chunks_a(test_artifact_a.Build());
- PendingLayer layer_a(chunks_a, chunks_a.begin());
-
- TestPaintArtifact test_artifact_b;
- test_artifact_b.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
- PaintChunkSubset chunks_b(test_artifact_b.Build());
- PendingLayer layer_b(chunks_b, chunks_b.begin());
-
- EXPECT_FALSE(layer_a.CanMerge(layer_b, layer_b.property_tree_state));
-}
-
TEST_P(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-
@@ -1921,253 +1875,6 @@ TEST_P(PaintArtifactCompositorTest, OverlapTransform) {
ASSERT_EQ(3u, LayerCount());
}
-TEST_P(PaintArtifactCompositorTest, MightOverlap) {
- TestPaintArtifact artifact;
- artifact.Chunk().Bounds(IntRect(0, 0, 100, 100));
- artifact.Chunk().Bounds(IntRect(0, 0, 100, 100));
- auto t2 = CreateTransform(t0(), TransformationMatrix().Translate(99, 0),
- FloatPoint3D(100, 100, 0));
- artifact.Chunk(*t2, c0(), e0()).Bounds(IntRect(0, 0, 100, 100));
- auto t3 = CreateTransform(t0(), TransformationMatrix().Translate(100, 0),
- FloatPoint3D(100, 100, 0));
- artifact.Chunk(*t3, c0(), e0()).Bounds(IntRect(0, 0, 100, 100));
- auto t4 =
- CreateAnimatingTransform(t0(), TransformationMatrix().Translate(100, 0),
- FloatPoint3D(100, 100, 0));
- artifact.Chunk(*t4, c0(), e0()).Bounds(IntRect(0, 0, 100, 100));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- EXPECT_TRUE(
- MightOverlap(pending_layer, PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_TRUE(
- MightOverlap(pending_layer, PendingLayer(chunks, chunks.begin() + 2)));
- EXPECT_FALSE(
- MightOverlap(pending_layer, PendingLayer(chunks, chunks.begin() + 3)));
- EXPECT_TRUE(
- MightOverlap(pending_layer, PendingLayer(chunks, chunks.begin() + 4)));
-}
-
-TEST_P(PaintArtifactCompositorTest, MightOverlapCommonClipAncestor) {
- auto common_clip = CreateClip(c0(), t0(), FloatRoundedRect(0, 0, 100, 100));
- auto c1 = CreateClip(*common_clip, t0(), FloatRoundedRect(0, 100, 100, 100));
- auto c2 = CreateClip(*common_clip, t0(), FloatRoundedRect(50, 100, 100, 100));
- auto c3 =
- CreateClip(*common_clip, t0(), FloatRoundedRect(100, 100, 100, 100));
-
- TestPaintArtifact artifact;
- artifact.Chunk(t0(), *c1, e0())
- .Bounds(IntRect(0, 100, 200, 100))
- .Chunk(t0(), *c2, e0())
- .Bounds(IntRect(0, 100, 200, 100))
- .Chunk(t0(), *c3, e0())
- .Bounds(IntRect(0, 100, 200, 100));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer1(chunks, chunks.begin());
- PendingLayer pending_layer2(chunks, chunks.begin() + 1);
- PendingLayer pending_layer3(chunks, chunks.begin() + 2);
- EXPECT_FALSE(MightOverlap(pending_layer1, pending_layer3));
- EXPECT_TRUE(MightOverlap(pending_layer1, pending_layer2));
- EXPECT_TRUE(MightOverlap(pending_layer2, pending_layer3));
-}
-
-TEST_P(PaintArtifactCompositorTest, UniteRectsKnownToBeOpaque) {
- // X aligned and intersect: unite.
- EXPECT_EQ(FloatRect(10, 20, 30, 60),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(10, 30, 30, 50)));
- // X aligned and adjacent: unite.
- EXPECT_EQ(FloatRect(10, 20, 30, 90),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(10, 60, 30, 50)));
- // X aligned and separate: choose the bigger one.
- EXPECT_EQ(FloatRect(10, 61, 30, 50),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(10, 61, 30, 50)));
- // Y aligned and intersect: unite.
- EXPECT_EQ(FloatRect(10, 20, 60, 40),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(30, 20, 40, 40)));
- // Y aligned and adjacent: unite.
- EXPECT_EQ(FloatRect(10, 20, 70, 40),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(40, 20, 40, 40)));
- // Y aligned and separate: choose the bigger one.
- EXPECT_EQ(FloatRect(41, 20, 40, 40),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(41, 20, 40, 40)));
- // Get the biggest expanded intersection.
- EXPECT_EQ(FloatRect(0, 0, 9, 19),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(0, 0, 10, 10),
- FloatRect(0, 9, 9, 10)));
- EXPECT_EQ(FloatRect(0, 0, 19, 9),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(0, 0, 10, 10),
- FloatRect(9, 0, 10, 9)));
- // Otherwise choose the bigger one.
- EXPECT_EQ(FloatRect(20, 30, 40, 50),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
- FloatRect(20, 30, 40, 50)));
- EXPECT_EQ(FloatRect(10, 20, 40, 50),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 40, 50),
- FloatRect(20, 30, 30, 40)));
- EXPECT_EQ(FloatRect(10, 20, 40, 50),
- PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 40, 50),
- FloatRect(20, 30, 40, 50)));
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayer) {
- TestPaintArtifact artifact;
- artifact.Chunk().Bounds(IntRect(0, 0, 30, 40)).KnownToBeOpaque();
- artifact.Chunk().Bounds(IntRect(10, 20, 30, 40)).KnownToBeOpaque();
- artifact.Chunk().Bounds(IntRect(-5, -25, 20, 20)).KnownToBeOpaque();
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
-
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
- EXPECT_EQ(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
-
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
-
- // Bounds not equal to one PaintChunk.
- EXPECT_EQ(FloatRect(0, 0, 40, 60), pending_layer.bounds);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0, 1));
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.rect_known_to_be_opaque);
-
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 2)));
-
- EXPECT_EQ(FloatRect(-5, -25, 45, 85), pending_layer.bounds);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0, 1, 2));
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.rect_known_to_be_opaque);
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayerMergeWithGuestTransform) {
- TestPaintArtifact artifact;
- artifact.Chunk().Bounds(IntRect(0, 0, 30, 40));
- auto transform = Create2DTranslation(t0(), 20, 25);
- artifact.Chunk(*transform, c0(), e0()).Bounds(IntRect(0, 0, 50, 60));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(0, 0, 70, 85), pending_layer.bounds);
- EXPECT_EQ(PropertyTreeState::Root(), pending_layer.property_tree_state);
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayerMergeWithHomeTransform) {
- TestPaintArtifact artifact;
- auto transform = Create2DTranslation(t0(), 20, 25);
- artifact.Chunk(*transform, c0(), e0()).Bounds(IntRect(0, 0, 30, 40));
- artifact.Chunk().Bounds(IntRect(0, 0, 50, 60));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(0, 0, 50, 65), pending_layer.bounds);
- EXPECT_EQ(PropertyTreeState::Root(), pending_layer.property_tree_state);
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayerMergeWithBothTransforms) {
- TestPaintArtifact artifact;
- auto t1 = Create2DTranslation(t0(), 20, 25);
- artifact.Chunk(*t1, c0(), e0()).Bounds(IntRect(0, 0, 30, 40));
- auto t2 = Create2DTranslation(t0(), -20, -25);
- artifact.Chunk(*t2, c0(), e0()).Bounds(IntRect(0, 0, 50, 60));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(-20, -25, 70, 90), pending_layer.bounds);
- EXPECT_EQ(PropertyTreeState::Root(), pending_layer.property_tree_state);
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayerDontMergeSparse) {
- TestPaintArtifact artifact;
- artifact.Chunk().Bounds(IntRect(0, 0, 30, 40)).KnownToBeOpaque();
- artifact.Chunk().Bounds(IntRect(200, 200, 30, 40)).KnownToBeOpaque();
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
- EXPECT_EQ(chunks.begin()->properties, pending_layer.property_tree_state);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayerDontMergeSparseWithTransforms) {
- TestPaintArtifact artifact;
- auto t1 = Create2DTranslation(t0(), 20, 25);
- artifact.Chunk(*t1, c0(), e0()).Bounds(IntRect(0, 0, 30, 40));
- auto t2 = Create2DTranslation(t0(), 1000, 1000);
- artifact.Chunk(*t2, c0(), e0()).Bounds(IntRect(0, 0, 50, 60));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
- EXPECT_EQ(chunks.begin()->properties, pending_layer.property_tree_state);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
-}
-
-TEST_P(PaintArtifactCompositorTest,
- PendingLayerDontMergeSparseInCompositedEffect) {
- TestPaintArtifact artifact;
- auto t1 = Create2DTranslation(t0(), 20, 25);
- auto e1 =
- CreateOpacityEffect(e0(), 1.0f, CompositingReason::kWillChangeOpacity);
- artifact.Chunk(*t1, c0(), *e1).Bounds(IntRect(0, 0, 30, 40));
- auto t2 = Create2DTranslation(t0(), 1000, 1000);
- artifact.Chunk(*t2, c0(), *e1).Bounds(IntRect(0, 0, 50, 60));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
- EXPECT_EQ(chunks.begin()->properties, pending_layer.property_tree_state);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
-}
-
-TEST_P(PaintArtifactCompositorTest,
- PendingLayerMergeSparseInNonCompositedEffect) {
- TestPaintArtifact artifact;
- auto t1 = Create2DTranslation(t0(), 20, 25);
- auto t2 = Create2DTranslation(t0(), 1000, 1000);
- auto e1 = CreateOpacityEffect(e0(), 1.0f, CompositingReason::kNone);
- artifact.Chunk(*t1, c0(), *e1).Bounds(IntRect(0, 0, 30, 40));
- artifact.Chunk(*t2, c0(), *e1).Bounds(IntRect(0, 0, 50, 60));
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- EXPECT_EQ(FloatRect(20, 25, 1030, 1035), pending_layer.bounds);
- EXPECT_EQ(PropertyTreeState(t0(), c0(), *e1),
- pending_layer.property_tree_state);
- EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0, 1));
-}
-
-TEST_P(PaintArtifactCompositorTest, PendingLayerKnownOpaque) {
- TestPaintArtifact artifact;
- artifact.Chunk().Bounds(IntRect(0, 0, 30, 40));
- artifact.Chunk().Bounds(IntRect(0, 0, 25, 35)).KnownToBeOpaque();
- artifact.Chunk().Bounds(IntRect(0, 0, 50, 60)).KnownToBeOpaque();
- PaintChunkSubset chunks(artifact.Build());
-
- PendingLayer pending_layer(chunks, chunks.begin());
- EXPECT_TRUE(pending_layer.rect_known_to_be_opaque.IsEmpty());
-
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
- // Chunk 2 doesn't cover the entire layer, so not opaque.
- EXPECT_EQ(FloatRect(0, 0, 25, 35), pending_layer.rect_known_to_be_opaque);
- EXPECT_NE(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
-
- ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 2)));
- // Chunk 3 covers the entire layer, so now it's opaque.
- EXPECT_EQ(FloatRect(0, 0, 50, 60), pending_layer.bounds);
- EXPECT_EQ(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
-}
-
scoped_refptr<EffectPaintPropertyNode> CreateSampleEffectNodeWithElementId() {
EffectPaintPropertyNode::State state;
state.local_transform_space = &t0();
@@ -2727,196 +2434,88 @@ TEST_P(PaintArtifactCompositorTest, DecompositedEffectNotMergingDueToOverlap) {
auto transform = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(IntRect(0, 0, 50, 50), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(0, 0, 40, 40), Color::kGray);
artifact.Chunk(t0(), c0(), *effect1)
- .RectDrawing(IntRect(100, 0, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(50, 0, 40, 40), Color::kGray);
// This chunk has a transform that must be composited, thus causing effect1
// to be composited too.
artifact.Chunk(*transform, c0(), *effect1)
- .RectDrawing(IntRect(200, 0, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(100, 0, 40, 40), Color::kGray);
artifact.Chunk(t0(), c0(), *effect2)
- .RectDrawing(IntRect(200, 100, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(100, 50, 40, 40), Color::kGray);
// This chunk overlaps with the 2nd chunk, but is seemingly safe to merge.
// However because effect1 gets composited due to a composited transform,
// we can't merge with effect1 nor skip it to merge with the first chunk.
artifact.Chunk(t0(), c0(), *effect2)
- .RectDrawing(IntRect(100, 0, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(50, 0, 40, 40), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(4u, LayerCount());
const cc::Layer* layer1 = LayerAt(0);
EXPECT_EQ(gfx::Vector2dF(0.f, 0.f), layer1->offset_to_transform_parent());
- EXPECT_EQ(gfx::Size(50, 50), layer1->bounds());
+ EXPECT_EQ(gfx::Size(40, 40), layer1->bounds());
EXPECT_EQ(1, layer1->effect_tree_index());
const cc::Layer* layer2 = LayerAt(1);
- EXPECT_EQ(gfx::Vector2dF(100.f, 0.f), layer2->offset_to_transform_parent());
- EXPECT_EQ(gfx::Size(50, 50), layer2->bounds());
+ EXPECT_EQ(gfx::Vector2dF(50.f, 0.f), layer2->offset_to_transform_parent());
+ EXPECT_EQ(gfx::Size(40, 40), layer2->bounds());
const cc::EffectNode* effect_node =
GetPropertyTrees().effect_tree.Node(layer2->effect_tree_index());
EXPECT_EQ(1, effect_node->parent_id);
EXPECT_EQ(0.1f, effect_node->opacity);
const cc::Layer* layer3 = LayerAt(2);
- EXPECT_EQ(gfx::Vector2dF(200.f, 0.f), layer3->offset_to_transform_parent());
- EXPECT_EQ(gfx::Size(50, 50), layer3->bounds());
+ EXPECT_EQ(gfx::Vector2dF(100.f, 0.f), layer3->offset_to_transform_parent());
+ EXPECT_EQ(gfx::Size(40, 40), layer3->bounds());
EXPECT_EQ(effect_node->id, layer3->effect_tree_index());
const cc::Layer* layer4 = LayerAt(3);
- EXPECT_EQ(gfx::Vector2dF(100.f, 0.f), layer4->offset_to_transform_parent());
- EXPECT_EQ(gfx::Size(150, 150), layer4->bounds());
+ EXPECT_EQ(gfx::Vector2dF(50.f, 0.f), layer4->offset_to_transform_parent());
+ EXPECT_EQ(gfx::Size(90, 90), layer4->bounds());
EXPECT_EQ(1, layer4->effect_tree_index());
}
-TEST_P(PaintArtifactCompositorTest, SkipChunkWithOpacityZero) {
- UpdateWithArtifactWithOpacity(0, false, false);
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_EQ(0u, LayerCount());
- else
- EXPECT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- SkipChunkWithOpacityZeroWithPrecedingChunk) {
- UpdateWithArtifactWithOpacity(0, true, false);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest, SkipChunkWithOpacityZeroSubsequentChunk) {
- UpdateWithArtifactWithOpacity(0, false, true);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- SkipChunkWithOpacityZeroWithPrecedingAndSubsequentChunk) {
- UpdateWithArtifactWithOpacity(0, true, true);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest, SkipChunkWithTinyOpacity) {
- UpdateWithArtifactWithOpacity(0.0003f, false, false);
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_EQ(0u, LayerCount());
- else
- EXPECT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- SkipChunkWithTinyOpacityWithPrecedingChunk) {
- UpdateWithArtifactWithOpacity(0.0003f, true, false);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest, SkipChunkWithTinyOpacitySubsequentChunk) {
- UpdateWithArtifactWithOpacity(0.0003f, false, true);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- SkipChunkWithTinyOpacityWithPrecedingAndSubsequentChunk) {
- UpdateWithArtifactWithOpacity(0.0003f, true, true);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest, DontSkipChunkWithMinimumOpacity) {
- UpdateWithArtifactWithOpacity(0.0004f, false, false);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithMinimumOpacityWithPrecedingChunk) {
- UpdateWithArtifactWithOpacity(0.0004f, true, false);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithMinimumOpacitySubsequentChunk) {
- UpdateWithArtifactWithOpacity(0.0004f, false, true);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithMinimumOpacityWithPrecedingAndSubsequentChunk) {
- UpdateWithArtifactWithOpacity(0.0004f, true, true);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest, DontSkipChunkWithAboveMinimumOpacity) {
- UpdateWithArtifactWithOpacity(0.3f, false, false);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithAboveMinimumOpacityWithPrecedingChunk) {
- UpdateWithArtifactWithOpacity(0.3f, true, false);
- ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithAboveMinimumOpacitySubsequentChunk) {
- UpdateWithArtifactWithOpacity(0.3f, false, true);
+TEST_P(PaintArtifactCompositorTest, EffectivelyInvisibleChunk) {
+ UpdateWithEffectivelyInvisibleChunk(false, false);
ASSERT_EQ(1u, LayerCount());
+ EXPECT_EQ(gfx::Size(10, 10), LayerAt(0)->bounds());
+ EXPECT_FALSE(LayerAt(0)->DrawsContent());
+ EXPECT_FALSE(LayerAt(0)->GetPicture());
}
TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithAboveMinimumOpacityWithPrecedingAndSubsequentChunk) {
- UpdateWithArtifactWithOpacity(0.3f, true, true);
+ EffectivelyInvisibleChunkWithPrecedingChunk) {
+ UpdateWithEffectivelyInvisibleChunk(true, false);
ASSERT_EQ(1u, LayerCount());
+ EXPECT_EQ(gfx::Size(20, 10), LayerAt(0)->bounds());
+ EXPECT_TRUE(LayerAt(0)->DrawsContent());
+ EXPECT_THAT(LayerAt(0)->GetPicture(),
+ Pointee(DrawsRectangles(
+ {RectWithColor(FloatRect(0, 0, 10, 10), Color::kBlack)})));
}
TEST_P(PaintArtifactCompositorTest,
- DontSkipChunkWithTinyOpacityAndDirectCompositingReason) {
- auto effect = CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kCanvas);
- TestPaintArtifact artifact;
- artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
- Update(artifact.Build());
+ EffectivelyInvisibleChunkWithSubsequentChunk) {
+ UpdateWithEffectivelyInvisibleChunk(false, true);
ASSERT_EQ(1u, LayerCount());
+ EXPECT_EQ(gfx::Size(20, 20), LayerAt(0)->bounds());
+ EXPECT_TRUE(LayerAt(0)->DrawsContent());
+ EXPECT_THAT(LayerAt(0)->GetPicture(),
+ Pointee(DrawsRectangles(
+ {RectWithColor(FloatRect(0, 10, 10, 10), Color::kWhite)})));
}
TEST_P(PaintArtifactCompositorTest,
- SkipChunkWithTinyOpacityAndVisibleChildEffectNode) {
- auto tiny_effect =
- CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kNone);
- auto visible_effect =
- CreateOpacityEffect(*tiny_effect, 0.5f, CompositingReason::kNone);
- TestPaintArtifact artifact;
- artifact.Chunk(t0(), c0(), *visible_effect)
- .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
- Update(artifact.Build());
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_EQ(0u, LayerCount());
- else
- EXPECT_EQ(1u, LayerCount());
-}
-
-TEST_P(
- PaintArtifactCompositorTest,
- DontSkipChunkWithTinyOpacityAndVisibleChildEffectNodeWithCompositingParent) {
- auto tiny_effect =
- CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kCanvas);
- auto visible_effect = CreateOpacityEffect(*tiny_effect, 0.5f);
- TestPaintArtifact artifact;
- artifact.Chunk(t0(), c0(), *visible_effect)
- .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
- Update(artifact.Build());
+ EffectivelyInvisibleChunkWithPrecedingAndSubsequentChunks) {
+ UpdateWithEffectivelyInvisibleChunk(true, true);
ASSERT_EQ(1u, LayerCount());
-}
-
-TEST_P(PaintArtifactCompositorTest,
- SkipChunkWithTinyOpacityAndVisibleChildEffectNodeWithCompositingChild) {
- auto tiny_effect = CreateOpacityEffect(e0(), 0.0001f);
- auto visible_effect =
- CreateOpacityEffect(*tiny_effect, 0.5f, CompositingReason::kCanvas);
- TestPaintArtifact artifact;
- artifact.Chunk(t0(), c0(), *visible_effect)
- .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
- Update(artifact.Build());
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_EQ(0u, LayerCount());
- else
- EXPECT_EQ(1u, LayerCount());
+ EXPECT_EQ(gfx::Size(20, 20), LayerAt(0)->bounds());
+ EXPECT_TRUE(LayerAt(0)->DrawsContent());
+ EXPECT_THAT(LayerAt(0)->GetPicture(),
+ Pointee(DrawsRectangles(
+ {RectWithColor(FloatRect(0, 0, 10, 10), Color::kBlack),
+ RectWithColor(FloatRect(0, 10, 10, 10), Color::kWhite)})));
}
TEST_P(PaintArtifactCompositorTest, UpdateManagesLayerElementIds) {
@@ -3960,7 +3559,7 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaque) {
TestPaintArtifact artifact;
artifact.Chunk()
.RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack)
- .KnownToBeOpaque();
+ .RectKnownToBeOpaque(IntRect(100, 100, 200, 200));
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_TRUE(LayerAt(0)->contents_opaque());
@@ -3970,10 +3569,10 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedNonOpaque) {
TestPaintArtifact artifact;
artifact.Chunk()
.RectDrawing(IntRect(100, 100, 210, 210), Color::kBlack)
- .KnownToBeOpaque()
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
.Chunk()
.RectDrawing(IntRect(200, 200, 200, 200), Color::kBlack)
- .KnownToBeOpaque();
+ .RectKnownToBeOpaque(IntRect(200, 200, 200, 200));
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_EQ(gfx::Size(300, 300), LayerAt(0)->bounds());
@@ -3986,11 +3585,11 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedClippedToOpaque) {
auto clip1 = CreateClip(c0(), t0(), FloatRoundedRect(175, 175, 100, 100));
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip1, e0())
- .RectDrawing(IntRect(100, 100, 210, 210), Color::kBlack)
- .KnownToBeOpaque()
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
.Chunk(t0(), *clip1, e0())
- .RectDrawing(IntRect(200, 200, 200, 200), Color::kBlack)
- .KnownToBeOpaque();
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(200, 200, 200, 200));
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_EQ(gfx::Size(100, 100), LayerAt(0)->bounds());
@@ -4001,10 +3600,10 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque1) {
TestPaintArtifact artifact;
artifact.Chunk()
.RectDrawing(IntRect(100, 100, 300, 300), Color::kBlack)
- .KnownToBeOpaque()
+ .RectKnownToBeOpaque(IntRect(100, 100, 300, 300))
.Chunk()
.RectDrawing(IntRect(200, 200, 200, 200), Color::kBlack)
- .KnownToBeOpaque();
+ .RectKnownToBeOpaque(IntRect(200, 200, 200, 200));
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_EQ(gfx::Size(300, 300), LayerAt(0)->bounds());
@@ -4021,10 +3620,10 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedWithRoundedClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip1, e0())
.RectDrawing(IntRect(100, 100, 210, 210), Color::kBlack)
- .KnownToBeOpaque()
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
.Chunk(t0(), c0(), e0())
.RectDrawing(IntRect(200, 200, 100, 100), Color::kBlack)
- .KnownToBeOpaque();
+ .RectKnownToBeOpaque(IntRect(200, 200, 100, 100));
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_EQ(gfx::Size(125, 125), LayerAt(0)->bounds());
@@ -4035,10 +3634,10 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque2) {
TestPaintArtifact artifact;
artifact.Chunk()
.RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack)
- .KnownToBeOpaque()
+ .RectKnownToBeOpaque(IntRect(100, 100, 200, 200))
.Chunk()
.RectDrawing(IntRect(100, 100, 300, 300), Color::kBlack)
- .KnownToBeOpaque();
+ .RectKnownToBeOpaque(IntRect(100, 100, 300, 300));
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_EQ(gfx::Size(300, 300), LayerAt(0)->bounds());
@@ -4993,4 +4592,22 @@ TEST_P(PaintArtifactCompositorTest, PreCompositedLayerNonCompositedScrolling) {
graphics_layer.CcLayer().scroll_tree_index());
}
+TEST_P(PaintArtifactCompositorTest, RepaintIndirectScrollHitTest) {
+ CompositorElementId scroll_element_id = ScrollElementId(2);
+ auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
+ kNotScrollingOnMain, scroll_element_id);
+ auto scroll_translation = CreateScrollTranslation(t0(), 7, 9, *scroll);
+
+ TestPaintArtifact test_artifact;
+ CreateScrollableChunk(test_artifact, *scroll_translation, c0(), e0());
+ auto artifact = test_artifact.Build();
+ Update(artifact);
+ scroll_translation->ClearChangedToRoot();
+
+ Vector<PreCompositedLayerInfo> pre_composited_layers = {
+ {PaintChunkSubset(artifact)}};
+ GetPaintArtifactCompositor().UpdateRepaintedLayers(pre_composited_layers);
+ // This test passes if no CHECK occurs.
+}
+
} // 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 0e54d407aef..91166a2dc78 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
@@ -35,7 +35,7 @@ class ConversionContext {
public:
ConversionContext(const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset,
+ const FloatPoint& layer_offset,
cc::DisplayItemList& cc_list)
: layer_state_(layer_state),
layer_offset_(layer_offset),
@@ -214,7 +214,7 @@ class ConversionContext {
Vector<StateEntry> state_stack_;
const PropertyTreeState& layer_state_;
- gfx::Vector2dF layer_offset_;
+ FloatPoint layer_offset_;
bool translated_for_layer_offset_ = false;
// These fields are neve nullptr.
@@ -268,12 +268,12 @@ ConversionContext::~ConversionContext() {
}
void ConversionContext::TranslateForLayerOffsetOnce() {
- if (translated_for_layer_offset_ || layer_offset_.IsZero())
+ if (translated_for_layer_offset_ || layer_offset_ == FloatPoint())
return;
cc_list_.StartPaint();
cc_list_.push<cc::SaveOp>();
- cc_list_.push<cc::TranslateOp>(-layer_offset_.x(), -layer_offset_.y());
+ cc_list_.push<cc::TranslateOp>(-layer_offset_.X(), -layer_offset_.Y());
cc_list_.EndPaintOfPairedBegin();
translated_for_layer_offset_ = true;
}
@@ -708,6 +708,8 @@ void ConversionContext::EndTransform() {
void ConversionContext::Convert(const PaintChunkSubset& chunks) {
for (auto it = chunks.begin(); it != chunks.end(); ++it) {
const auto& chunk = *it;
+ if (chunk.effectively_invisible)
+ continue;
const auto& chunk_state = chunk.properties;
bool switched_to_chunk_state = false;
@@ -760,7 +762,7 @@ void ConversionContext::Convert(const PaintChunkSubset& chunks) {
void PaintChunksToCcLayer::ConvertInto(const PaintChunkSubset& chunks,
const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset,
+ const FloatPoint& layer_offset,
cc::DisplayItemList& cc_list) {
ConversionContext(layer_state, layer_offset, cc_list).Convert(chunks);
}
@@ -768,7 +770,7 @@ void PaintChunksToCcLayer::ConvertInto(const PaintChunkSubset& chunks,
scoped_refptr<cc::DisplayItemList> PaintChunksToCcLayer::Convert(
const PaintChunkSubset& paint_chunks,
const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset,
+ const FloatPoint& layer_offset,
cc::DisplayItemList::UsageHint hint,
RasterUnderInvalidationCheckingParams* under_invalidation_checking_params) {
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(hint);
@@ -908,7 +910,6 @@ static void UpdateNonFastScrollableRegion(
const PropertyTreeState& layer_state,
const PropertyTreeState& chunk_state,
const FloatPoint& layer_offset,
- PropertyTreeManager* property_tree_manager,
cc::Region& non_fast_scrollable_region) {
if (hit_test_data.scroll_hit_test_rect.IsEmpty())
return;
@@ -918,29 +919,15 @@ static void UpdateNonFastScrollableRegion(
// pre-CompositeAfterPaint does not paint scroll hit test data for
// composited scrollers.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- if (const auto* scroll_translation = hit_test_data.scroll_translation) {
- const auto& scroll_node = *scroll_translation->ScrollNode();
- auto scroll_element_id = scroll_node.GetCompositorElementId();
+ if (const auto scroll_translation = hit_test_data.scroll_translation) {
+ const auto* scroll_node = scroll_translation->ScrollNode();
+ DCHECK(scroll_node);
+ // TODO(crbug.com/1222613): Remove this when we fix the root cause.
+ if (!scroll_node)
+ return;
+ auto scroll_element_id = scroll_node->GetCompositorElementId();
if (layer.element_id() == scroll_element_id)
return;
- // Ensure the cc scroll node to prepare for possible descendant nodes
- // referenced by later composited layers. This can't be done by ensuring
- // parent transform node in EnsureCompositorTransformNode() if the
- // transform tree and the scroll tree have different topologies.
- // This is not necessary with ScrollUnification which ensures the
- // complete scroll tree.
- if (!RuntimeEnabledFeatures::ScrollUnificationEnabled()) {
- if (property_tree_manager) {
- property_tree_manager->EnsureCompositorScrollNode(
- *scroll_translation);
- } else {
- // A repaint-only update does not modify property tree nodes and has
- // no property tree manager. This DCHECK ensures that a scroll node
- // has already been created.
- DCHECK(scroll_translation->CcNodeId(
- layer.property_tree_sequence_number()));
- }
- }
}
}
@@ -956,8 +943,7 @@ static void UpdateNonFastScrollableRegion(
static void UpdateTouchActionWheelEventHandlerAndNonFastScrollableRegions(
cc::Layer& layer,
const PropertyTreeState& layer_state,
- const PaintChunkSubset& chunks,
- PropertyTreeManager* property_tree_manager) {
+ const PaintChunkSubset& chunks) {
gfx::Vector2dF cc_layer_offset = layer.offset_to_transform_parent();
FloatPoint layer_offset(cc_layer_offset.x(), cc_layer_offset.y());
cc::TouchActionRegion touch_action_region;
@@ -977,9 +963,9 @@ static void UpdateTouchActionWheelEventHandlerAndNonFastScrollableRegions(
UpdateWheelEventRegion(*chunk.hit_test_data, layer_state, chunk_state,
layer_offset, wheel_event_region);
}
- UpdateNonFastScrollableRegion(
- layer, *chunk.hit_test_data, layer_state, chunk_state, layer_offset,
- property_tree_manager, non_fast_scrollable_region);
+ UpdateNonFastScrollableRegion(layer, *chunk.hit_test_data, layer_state,
+ chunk_state, layer_offset,
+ non_fast_scrollable_region);
}
layer.SetTouchActionRegion(std::move(touch_action_region));
// TODO(https://crbug.com/841364): Fist condition in the "if" statement below
@@ -1022,10 +1008,11 @@ ConvertPaintedSelectionBoundToLayerSelectionBound(
return layer_bound;
}
-static void UpdateLayerSelection(cc::Layer& layer,
- const PropertyTreeState& layer_state,
- const PaintChunkSubset& chunks,
- cc::LayerSelection& layer_selection) {
+void PaintChunksToCcLayer::UpdateLayerSelection(
+ cc::Layer& layer,
+ const PropertyTreeState& layer_state,
+ const PaintChunkSubset& chunks,
+ cc::LayerSelection& layer_selection) {
gfx::Vector2dF cc_layer_offset = layer.offset_to_transform_parent();
FloatPoint layer_offset(cc_layer_offset.x(), cc_layer_offset.y());
for (const auto& chunk : chunks) {
@@ -1054,13 +1041,10 @@ static void UpdateLayerSelection(cc::Layer& layer,
void PaintChunksToCcLayer::UpdateLayerProperties(
cc::Layer& layer,
const PropertyTreeState& layer_state,
- const PaintChunkSubset& chunks,
- cc::LayerSelection& layer_selection,
- PropertyTreeManager* property_tree_manager) {
+ const PaintChunkSubset& chunks) {
UpdateBackgroundColor(layer, layer_state.Effect(), chunks);
UpdateTouchActionWheelEventHandlerAndNonFastScrollableRegions(
- layer, layer_state, chunks, property_tree_manager);
- UpdateLayerSelection(layer, layer_state, chunks, layer_selection);
+ layer, layer_state, chunks);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
index 75e93a84f8b..8eec0734b04 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
@@ -19,14 +19,10 @@ class DisplayItemList;
class Layer;
} // namespace cc
-namespace gfx {
-class Vector2dF;
-} // namespace gfx
-
namespace blink {
+class FloatPoint;
class PaintChunkSubset;
-class PropertyTreeManager;
class PropertyTreeState;
class RasterInvalidationTracking;
@@ -61,7 +57,7 @@ class PLATFORM_EXPORT PaintChunksToCcLayer {
// of layer_state.Transform().
static void ConvertInto(const PaintChunkSubset&,
const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset,
+ const FloatPoint& layer_offset,
cc::DisplayItemList&);
// Similar to ConvertInto(), but returns a finalized new list instead of
@@ -69,15 +65,17 @@ class PLATFORM_EXPORT PaintChunksToCcLayer {
static scoped_refptr<cc::DisplayItemList> Convert(
const PaintChunkSubset&,
const PropertyTreeState& layer_state,
- const gfx::Vector2dF& layer_offset,
+ const FloatPoint& layer_offset,
cc::DisplayItemList::UsageHint,
RasterUnderInvalidationCheckingParams* = nullptr);
+ static void UpdateLayerSelection(cc::Layer& layer,
+ const PropertyTreeState& layer_state,
+ const PaintChunkSubset&,
+ cc::LayerSelection& layer_selection);
static void UpdateLayerProperties(cc::Layer& layer,
const PropertyTreeState& layer_state,
- const PaintChunkSubset&,
- cc::LayerSelection& layer_selection,
- PropertyTreeManager* = nullptr);
+ const PaintChunkSubset&);
};
} // namespace blink
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 f792ec39554..65b90ebf05a 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
@@ -219,7 +219,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectGroupingSimple) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -242,7 +242,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectGroupingNested) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -275,7 +275,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectFilterGroupingNestedWithTransforms) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -322,7 +322,7 @@ TEST_P(PaintChunksToCcLayerTest, InterleavedClipEffect) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output, PaintRecordMatcher::Make(
@@ -367,7 +367,7 @@ TEST_P(PaintChunksToCcLayerTest, ClipSpaceInversion) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output,
@@ -396,7 +396,7 @@ TEST_P(PaintChunksToCcLayerTest, OpacityEffectSpaceInversion) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output,
@@ -430,7 +430,7 @@ TEST_P(PaintChunksToCcLayerTest, FilterEffectSpaceInversion) {
chunks.AddChunk(t0(), c0(), *e1);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -459,7 +459,7 @@ TEST_P(PaintChunksToCcLayerTest, NonRootLayerSimple) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(*t1, *c1, *e1), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(*t1, *c1, *e1), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output, PaintRecordMatcher::Make({cc::PaintOpType::DrawRecord}));
@@ -476,7 +476,7 @@ TEST_P(PaintChunksToCcLayerTest, NonRootLayerTransformEscape) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(*t1, *c1, *e1), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(*t1, *c1, *e1), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output,
@@ -497,7 +497,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectWithNoOutputClip) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(t0(), *c1, e0()), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(t0(), *c1, e0()), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -522,7 +522,7 @@ TEST_P(PaintChunksToCcLayerTest,
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -550,7 +550,7 @@ TEST_P(PaintChunksToCcLayerTest,
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(t0(), c0(), *e1), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(t0(), c0(), *e1), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -575,7 +575,7 @@ TEST_P(PaintChunksToCcLayerTest,
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(t0(), *c1, *e1), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(t0(), *c1, *e1), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -598,7 +598,7 @@ TEST_P(PaintChunksToCcLayerTest, VisualRect) {
cc::DisplayItemList::kTopLevelDisplayItemList);
PaintChunksToCcLayer::ConvertInto(
chunks.Build(), PropertyTreeState(*layer_transform, c0(), e0()),
- gfx::Vector2dF(100, 200), *cc_list);
+ FloatPoint(100, 200), *cc_list);
EXPECT_EQ(gfx::Rect(-50, -100, 100, 100), cc_list->VisualRectForTesting(4));
EXPECT_THAT(*cc_list->ReleaseAsRecord(),
@@ -620,7 +620,7 @@ TEST_P(PaintChunksToCcLayerTest, NoncompositedClipPath) {
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
cc::DisplayItemList::kTopLevelDisplayItemList);
PaintChunksToCcLayer::ConvertInto(chunks.Build(), PropertyTreeState::Root(),
- gfx::Vector2dF(), *cc_list);
+ FloatPoint(), *cc_list);
EXPECT_THAT(
*cc_list->ReleaseAsRecord(),
@@ -647,7 +647,7 @@ TEST_P(PaintChunksToCcLayerTest, EmptyClipsAreElided) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -677,7 +677,7 @@ TEST_P(PaintChunksToCcLayerTest, NonEmptyClipsAreStored) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -701,7 +701,7 @@ TEST_P(PaintChunksToCcLayerTest, EmptyEffectsAreStored) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -728,7 +728,7 @@ TEST_P(PaintChunksToCcLayerTest, CombineClips) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -767,7 +767,7 @@ TEST_P(PaintChunksToCcLayerTest, CombineClipsAcrossTransform) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -814,7 +814,7 @@ TEST_P(PaintChunksToCcLayerTest, CombineClipsWithRoundedRects) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -856,7 +856,7 @@ TEST_P(PaintChunksToCcLayerTest, ChunksSamePropertyTreeState) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -894,7 +894,7 @@ TEST_P(PaintChunksToCcLayerTest, NoOpForIdentityTransforms) {
chunks.AddChunk(*t1, *c2, e0());
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -922,7 +922,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectsWithSameTransform) {
chunks.AddChunk(*t1, c0(), *e2);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -950,7 +950,7 @@ TEST_P(PaintChunksToCcLayerTest, NestedEffectsWithSameTransform) {
chunks.AddChunk(*t1, c0(), *e2);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -984,7 +984,7 @@ TEST_P(PaintChunksToCcLayerTest, NoopTransformIsNotEmitted) {
chunks.AddChunk(*t4, c0(), e0());
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1015,7 +1015,7 @@ TEST_P(PaintChunksToCcLayerTest, OnlyNoopTransformIsNotEmitted) {
chunks.AddChunk(*noop_t2, c0(), e0());
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1034,7 +1034,7 @@ TEST_P(PaintChunksToCcLayerTest, NoopTransformFirstThenBackToParent) {
chunks.AddChunk(*t1, c0(), e0());
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1060,7 +1060,7 @@ TEST_P(PaintChunksToCcLayerTest, ClipUndoesNoopTransform) {
chunks.AddChunk(*noop_t2, *c1, e0());
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1088,7 +1088,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectUndoesNoopTransform) {
chunks.AddChunk(*noop_t2, c0(), *e1);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1121,7 +1121,7 @@ TEST_P(PaintChunksToCcLayerTest, NoopClipDoesNotEmitItems) {
chunks.AddChunk(t0(), *c1, e0());
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1152,7 +1152,7 @@ TEST_P(PaintChunksToCcLayerTest, EffectUndoesNoopClip) {
chunks.AddChunk(t0(), *noop_c2, *e1);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1183,7 +1183,7 @@ TEST_P(PaintChunksToCcLayerTest, SPv1ChunkEscapeLayerClipFailSafe) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(t0(), *c1, e0()), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(t0(), *c1, e0()), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
// We don't care about the exact output as long as it didn't crash.
@@ -1206,7 +1206,7 @@ TEST_P(PaintChunksToCcLayerTest, SPv1ChunkEscapeEffectClipFailSafe) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
// We don't care about the exact output as long as it didn't crash.
@@ -1227,7 +1227,7 @@ TEST_P(PaintChunksToCcLayerTest, SPv1ChunkEscapeLayerClipDoubleFault) {
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState(t0(), *c1, e0()), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState(t0(), *c1, e0()), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
// We don't care about the exact output as long as it didn't crash.
@@ -1250,7 +1250,7 @@ TEST_P(PaintChunksToCcLayerTest, NoopEffectDoesNotEmitItems) {
chunks.AddChunk(t0(), c0(), *e1);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1286,7 +1286,7 @@ TEST_P(PaintChunksToCcLayerTest, AllowChunkEscapeLayerNoopEffects) {
chunks.AddChunk(t0(), c0(), *e4);
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), layer_state, gfx::Vector2dF(),
+ chunks.Build(), layer_state, FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -1306,7 +1306,7 @@ TEST_P(PaintChunksToCcLayerTest, EmptyChunkRect) {
chunks.AddChunk(nullptr, t0(), c0(), *e1, {0, 0, 0, 0});
auto output = PaintChunksToCcLayer::Convert(
- chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.Build(), PropertyTreeState::Root(), FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output,
@@ -1333,7 +1333,7 @@ TEST_P(PaintChunksToCcLayerTest, ReferenceFilterOnEmptyChunk) {
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
cc::DisplayItemList::kTopLevelDisplayItemList);
PaintChunksToCcLayer::ConvertInto(chunks.Build(), PropertyTreeState::Root(),
- gfx::Vector2dF(5, 10), *cc_list);
+ FloatPoint(5, 10), *cc_list);
ASSERT_EQ(5u, cc_list->TotalOpCount());
// (7 16) is (12, 26) - layer_offset.
gfx::Rect expected_visual_rect(7, 16, 93, 84);
@@ -1365,7 +1365,7 @@ TEST_P(PaintChunksToCcLayerTest, ReferenceFilterOnChunkWithDrawingDisplayItem) {
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
cc::DisplayItemList::kTopLevelDisplayItemList);
PaintChunksToCcLayer::ConvertInto(chunks.Build(), PropertyTreeState::Root(),
- gfx::Vector2dF(5, 10), *cc_list);
+ FloatPoint(5, 10), *cc_list);
ASSERT_EQ(7u, cc_list->TotalOpCount());
// This is the visual rect for all filter related paint operations, which is
// the union of the draw record and the output bounds of the filter with empty
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc
new file mode 100644
index 00000000000..b319e2fe7dc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc
@@ -0,0 +1,476 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/compositing/pending_layer.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/paint/drawing_display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+
+namespace blink {
+
+namespace {
+
+const ClipPaintPropertyNode* HighestOutputClipBetween(
+ const EffectPaintPropertyNode& ancestor,
+ const EffectPaintPropertyNode& descendant) {
+ const ClipPaintPropertyNode* result = nullptr;
+ for (const auto* effect = &descendant; effect != &ancestor;
+ effect = effect->UnaliasedParent()) {
+ if (const auto* output_clip = effect->OutputClip())
+ result = &output_clip->Unalias();
+ }
+ return result;
+}
+
+// When possible, provides a clip rect that limits the visibility.
+absl::optional<FloatRect> VisibilityLimit(const PropertyTreeState& state) {
+ if (&state.Clip().LocalTransformSpace() == &state.Transform())
+ return state.Clip().PixelSnappedClipRect().Rect();
+ if (const auto* scroll = state.Transform().ScrollNode()) {
+ return FloatRect(
+ IntRect(scroll->ContainerRect().Location(), scroll->ContentsSize()));
+ }
+ return absl::nullopt;
+}
+
+bool IsCompositedScrollHitTest(const PaintChunk& chunk) {
+ if (!chunk.hit_test_data)
+ return false;
+ const auto scroll_translation = chunk.hit_test_data->scroll_translation;
+ return scroll_translation &&
+ scroll_translation->HasDirectCompositingReasons();
+}
+
+bool IsCompositedScrollbar(const DisplayItem& item) {
+ if (const auto* scrollbar = DynamicTo<ScrollbarDisplayItem>(item)) {
+ const auto* scroll_translation = scrollbar->ScrollTranslation();
+ return scroll_translation &&
+ scroll_translation->HasDirectCompositingReasons();
+ }
+ return false;
+}
+
+// Snap |bounds| if within floating-point numeric limits of an integral rect.
+void PreserveNearIntegralBounds(FloatRect& bounds) {
+ if (std::abs(std::round(bounds.X()) - bounds.X()) <=
+ std::numeric_limits<float>::epsilon() &&
+ std::abs(std::round(bounds.Y()) - bounds.Y()) <=
+ std::numeric_limits<float>::epsilon() &&
+ std::abs(std::round(bounds.MaxX()) - bounds.MaxX()) <=
+ std::numeric_limits<float>::epsilon() &&
+ std::abs(std::round(bounds.MaxY()) - bounds.MaxY()) <=
+ std::numeric_limits<float>::epsilon()) {
+ bounds = FloatRect(RoundedIntRect(bounds));
+ }
+}
+
+} // anonymous namespace
+
+PendingLayer::PendingLayer(const PaintChunkSubset& chunks,
+ const PaintChunkIterator& first_chunk)
+ : PendingLayer(chunks, *first_chunk, first_chunk.IndexInPaintArtifact()) {}
+
+PendingLayer::PendingLayer(const PaintChunkSubset& chunks,
+ const PaintChunk& first_chunk,
+ wtf_size_t first_chunk_index_in_paint_artifact)
+ : bounds_(first_chunk.bounds),
+ rect_known_to_be_opaque_(first_chunk.rect_known_to_be_opaque),
+ has_text_(first_chunk.has_text),
+ text_known_to_be_on_opaque_background_(
+ first_chunk.text_known_to_be_on_opaque_background),
+ chunks_(&chunks.GetPaintArtifact(), first_chunk_index_in_paint_artifact),
+ property_tree_state_(
+ first_chunk.properties.GetPropertyTreeState().Unalias()),
+ compositing_type_(kOther) {
+ DCHECK(!RequiresOwnLayer() || first_chunk.size() <= 1u);
+ // Though text_known_to_be_on_opaque_background is only meaningful when
+ // has_text is true, we expect text_known_to_be_on_opaque_background to be
+ // true when !has_text to simplify code.
+ DCHECK(has_text_ || text_known_to_be_on_opaque_background_);
+ if (const absl::optional<FloatRect>& visibility_limit =
+ VisibilityLimit(property_tree_state_)) {
+ bounds_.Intersect(*visibility_limit);
+ }
+
+ if (IsCompositedScrollHitTest(first_chunk)) {
+ compositing_type_ = kScrollHitTestLayer;
+ } else if (first_chunk.size()) {
+ const auto& first_display_item = FirstDisplayItem();
+ if (first_display_item.IsForeignLayer())
+ compositing_type_ = kForeignLayer;
+ else if (IsCompositedScrollbar(first_display_item))
+ compositing_type_ = kScrollbarLayer;
+ }
+}
+
+PendingLayer::PendingLayer(const PreCompositedLayerInfo& pre_composited_layer)
+ : chunks_(pre_composited_layer.chunks),
+ property_tree_state_(
+ pre_composited_layer.graphics_layer->GetPropertyTreeState()
+ .Unalias()),
+ graphics_layer_(pre_composited_layer.graphics_layer),
+ compositing_type_(kPreCompositedLayer) {
+ DCHECK(graphics_layer_);
+ DCHECK(!graphics_layer_->ShouldCreateLayersAfterPaint());
+}
+
+FloatPoint PendingLayer::LayerOffset() const {
+ // The solid color layer optimization is important for performance. Snapping
+ // the location could make the solid color drawings not cover the entire
+ // cc::Layer which would make the layer non-solid-color.
+ if (IsSolidColor())
+ return bounds_.Location();
+ // Otherwise return integral offset to reduce chance of additional blurriness.
+ return FloatPoint(FlooredIntPoint(bounds_.Location()));
+}
+
+IntSize PendingLayer::LayerBounds() const {
+ // Because solid color layers do not adjust their location (see:
+ // |PendingLayer::LayerOffset()|), we only expand their size here.
+ if (IsSolidColor())
+ return ExpandedIntSize(bounds_.Size());
+ return EnclosingIntRect(bounds_).Size();
+}
+
+FloatRect PendingLayer::MapRectKnownToBeOpaque(
+ const PropertyTreeState& new_state) const {
+ if (rect_known_to_be_opaque_.IsEmpty())
+ return FloatRect();
+
+ FloatClipRect float_clip_rect(rect_known_to_be_opaque_);
+ GeometryMapper::LocalToAncestorVisualRect(property_tree_state_, new_state,
+ float_clip_rect);
+ return float_clip_rect.IsTight() ? float_clip_rect.Rect() : FloatRect();
+}
+
+std::unique_ptr<JSONObject> PendingLayer::ToJSON() const {
+ std::unique_ptr<JSONObject> result = std::make_unique<JSONObject>();
+ result->SetArray("bounds", RectAsJSONArray(bounds_));
+ result->SetArray("rect_known_to_be_opaque",
+ RectAsJSONArray(rect_known_to_be_opaque_));
+ result->SetObject("property_tree_state", property_tree_state_.ToJSON());
+ result->SetArray("offset_of_decomposited_transforms",
+ PointAsJSONArray(offset_of_decomposited_transforms_));
+ std::unique_ptr<JSONArray> json_chunks = std::make_unique<JSONArray>();
+ for (auto it = chunks_.begin(); it != chunks_.end(); ++it) {
+ StringBuilder sb;
+ sb.Append("index=");
+ sb.AppendNumber(it.IndexInPaintArtifact());
+ sb.Append(" ");
+ sb.Append(it->ToString());
+ json_chunks->PushString(sb.ToString());
+ }
+ result->SetArray("paint_chunks", std::move(json_chunks));
+ return result;
+}
+
+FloatRect PendingLayer::VisualRectForOverlapTesting(
+ const PropertyTreeState& ancestor_state) const {
+ FloatClipRect visual_rect(bounds_);
+ GeometryMapper::LocalToAncestorVisualRect(
+ property_tree_state_, ancestor_state, visual_rect,
+ kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect,
+ kExpandVisualRectForCompositingOverlap);
+ return visual_rect.Rect();
+}
+
+void PendingLayer::Upcast(const PropertyTreeState& new_state) {
+ DCHECK(!RequiresOwnLayer());
+ if (property_tree_state_ == new_state)
+ return;
+
+ FloatClipRect float_clip_rect(bounds_);
+ GeometryMapper::LocalToAncestorVisualRect(property_tree_state_, new_state,
+ float_clip_rect);
+ bounds_ = float_clip_rect.Rect();
+
+ rect_known_to_be_opaque_ = MapRectKnownToBeOpaque(new_state);
+ property_tree_state_ = new_state;
+}
+
+const PaintChunk& PendingLayer::FirstPaintChunk() const {
+ DCHECK(!RequiresOwnLayer() || chunks_.size() == 1);
+ return *chunks_.begin();
+}
+
+const DisplayItem& PendingLayer::FirstDisplayItem() const {
+#if DCHECK_IS_ON()
+ // This method should never be called if the first paint chunk is empty.
+ if (RequiresOwnLayer())
+ DCHECK_EQ(FirstPaintChunk().size(), 1u);
+ else
+ DCHECK_GE(FirstPaintChunk().size(), 1u);
+#endif
+ return *chunks_.begin().DisplayItems().begin();
+}
+
+bool PendingLayer::MayDrawContent() const {
+ return Chunks().size() > 1 || FirstPaintChunk().size() > 0;
+}
+
+// We will only allow merging if
+// merged_area - (home_area + guest_area) <= kMergeSparsityAreaTolerance
+static constexpr float kMergeSparsityAreaTolerance = 10000;
+
+bool PendingLayer::MergeInternal(const PendingLayer& guest,
+ const PropertyTreeState& guest_state,
+ bool prefers_lcd_text,
+ bool dry_run) {
+ if (&Chunks().GetPaintArtifact() != &guest.Chunks().GetPaintArtifact())
+ return false;
+ if (RequiresOwnLayer() || guest.RequiresOwnLayer())
+ return false;
+ if (&GetPropertyTreeState().Effect() != &guest_state.Effect())
+ return false;
+
+ const absl::optional<PropertyTreeState>& merged_state =
+ GetPropertyTreeState().CanUpcastWith(guest_state);
+ if (!merged_state)
+ return false;
+
+ const absl::optional<FloatRect>& merged_visibility_limit =
+ VisibilityLimit(*merged_state);
+
+ // If the current bounds and known-to-be-opaque area already cover the entire
+ // visible area of the merged state, and the current state is already equal
+ // to the merged state, we can merge the guest immediately without needing to
+ // update any bounds at all. This simple merge fast-path avoids the cost of
+ // mapping the visual rects, below.
+ if (merged_visibility_limit && *merged_visibility_limit == bounds_ &&
+ merged_state == property_tree_state_ &&
+ rect_known_to_be_opaque_.Contains(bounds_)) {
+ if (!dry_run) {
+ chunks_.Merge(guest.Chunks());
+ text_known_to_be_on_opaque_background_ = true;
+ has_text_ |= guest.has_text_;
+ change_of_decomposited_transforms_ =
+ std::max(ChangeOfDecompositedTransforms(),
+ guest.ChangeOfDecompositedTransforms());
+ }
+ return true;
+ }
+
+ FloatClipRect new_home_bounds(bounds_);
+ GeometryMapper::LocalToAncestorVisualRect(GetPropertyTreeState(),
+ *merged_state, new_home_bounds);
+ if (merged_visibility_limit)
+ new_home_bounds.Rect().Intersect(*merged_visibility_limit);
+
+ FloatClipRect new_guest_bounds(guest.bounds_);
+ GeometryMapper::LocalToAncestorVisualRect(guest_state, *merged_state,
+ new_guest_bounds);
+ if (merged_visibility_limit)
+ new_guest_bounds.Rect().Intersect(*merged_visibility_limit);
+
+ FloatRect merged_bounds =
+ UnionRect(new_home_bounds.Rect(), new_guest_bounds.Rect());
+ float sum_area = new_home_bounds.Rect().Size().Area() +
+ new_guest_bounds.Rect().Size().Area();
+ if (merged_bounds.Size().Area() - sum_area > kMergeSparsityAreaTolerance)
+ return false;
+
+ FloatRect merged_rect_known_to_be_opaque =
+ MaximumCoveredRect(MapRectKnownToBeOpaque(*merged_state),
+ guest.MapRectKnownToBeOpaque(*merged_state));
+ bool merged_text_known_to_be_on_opaque_background =
+ text_known_to_be_on_opaque_background_;
+ if (text_known_to_be_on_opaque_background_ !=
+ guest.text_known_to_be_on_opaque_background_) {
+ if (!text_known_to_be_on_opaque_background_) {
+ if (merged_rect_known_to_be_opaque.Contains(new_home_bounds.Rect()))
+ merged_text_known_to_be_on_opaque_background = true;
+ } else if (!guest.text_known_to_be_on_opaque_background_) {
+ if (!merged_rect_known_to_be_opaque.Contains(new_guest_bounds.Rect()))
+ merged_text_known_to_be_on_opaque_background = false;
+ }
+ }
+ if (prefers_lcd_text && !merged_text_known_to_be_on_opaque_background) {
+ if (has_text_ && text_known_to_be_on_opaque_background_)
+ return false;
+ if (guest.has_text_ && guest.text_known_to_be_on_opaque_background_)
+ return false;
+ }
+
+ if (!dry_run) {
+ chunks_.Merge(guest.Chunks());
+ bounds_ = merged_bounds;
+ property_tree_state_ = *merged_state;
+ rect_known_to_be_opaque_ = merged_rect_known_to_be_opaque;
+ text_known_to_be_on_opaque_background_ =
+ merged_text_known_to_be_on_opaque_background;
+ has_text_ |= guest.has_text_;
+ change_of_decomposited_transforms_ =
+ std::max(ChangeOfDecompositedTransforms(),
+ guest.ChangeOfDecompositedTransforms());
+ // GeometryMapper::LocalToAncestorVisualRect can introduce floating-point
+ // error to the bounds. Integral bounds are important for reducing
+ // blurriness (see: PendingLayer::LayerOffset) so preserve that here.
+ PreserveNearIntegralBounds(bounds_);
+ PreserveNearIntegralBounds(rect_known_to_be_opaque_);
+ }
+ return true;
+}
+
+const TransformPaintPropertyNode&
+PendingLayer::ScrollTranslationForScrollHitTestLayer() const {
+ DCHECK_EQ(GetCompositingType(), kScrollHitTestLayer);
+ DCHECK_EQ(1u, Chunks().size());
+ const auto& paint_chunk = FirstPaintChunk();
+ DCHECK(paint_chunk.hit_test_data);
+ DCHECK(paint_chunk.hit_test_data->scroll_translation);
+ DCHECK(paint_chunk.hit_test_data->scroll_translation->ScrollNode());
+ return *paint_chunk.hit_test_data->scroll_translation;
+}
+
+bool PendingLayer::PropertyTreeStateChanged() const {
+ auto change = PaintPropertyChangeType::kChangedOnlyNonRerasterValues;
+ if (change_of_decomposited_transforms_ >= change)
+ return true;
+
+ return property_tree_state_.ChangedToRoot(change);
+}
+
+bool PendingLayer::MightOverlap(const PendingLayer& other) const {
+ PropertyTreeState common_ancestor_state(
+ property_tree_state_.Transform()
+ .LowestCommonAncestor(other.property_tree_state_.Transform())
+ .Unalias(),
+ property_tree_state_.Clip()
+ .LowestCommonAncestor(other.property_tree_state_.Clip())
+ .Unalias(),
+ property_tree_state_.Effect()
+ .LowestCommonAncestor(other.property_tree_state_.Effect())
+ .Unalias());
+ // Move the common clip up if some effect nodes have OutputClip escaping the
+ // common clip.
+ if (const auto* clip_a = HighestOutputClipBetween(
+ common_ancestor_state.Effect(), property_tree_state_.Effect())) {
+ common_ancestor_state.SetClip(
+ clip_a->LowestCommonAncestor(common_ancestor_state.Clip()).Unalias());
+ }
+ if (const auto* clip_b =
+ HighestOutputClipBetween(common_ancestor_state.Effect(),
+ other.property_tree_state_.Effect())) {
+ common_ancestor_state.SetClip(
+ clip_b->LowestCommonAncestor(common_ancestor_state.Clip()).Unalias());
+ }
+ return VisualRectForOverlapTesting(common_ancestor_state)
+ .Intersects(other.VisualRectForOverlapTesting(common_ancestor_state));
+}
+
+// Walk the pending layer list and build up a table of transform nodes that
+// can be de-composited (replaced with offset_to_transform_parent). A
+// transform node can be de-composited if:
+// 1. It is not the root transform node.
+// 2. It is a 2d translation only.
+// 3. The transform is not used for scrolling - its ScrollNode() is nullptr.
+// 4. The transform is not a StickyTranslation node.
+// 5. It has no direct compositing reasons, other than k3DTransform. Note
+// that if it has a k3DTransform reason, check #2 above ensures that it
+// isn't really 3D.
+// 6. It has FlattensInheritedTransform matching that of its direct parent.
+// 7. It has backface visibility matching its direct parent.
+// 8. No clips have local_transform_space referring to this transform node.
+// 9. No effects have local_transform_space referring to this transform node.
+// 10. All child transform nodes are also able to be de-composited.
+// This algorithm should be O(t+c+e) where t,c,e are the number of transform,
+// clip, and effect nodes in the full tree.
+void PendingLayer::DecompositeTransforms(Vector<PendingLayer>& pending_layers) {
+ HashMap<const TransformPaintPropertyNode*, bool> can_be_decomposited;
+ HashSet<const void*> clips_and_effects_seen;
+ for (const PendingLayer& pending_layer : pending_layers) {
+ const auto& property_state = pending_layer.GetPropertyTreeState();
+
+ // Lambda to handle marking a transform node false, and walking up all
+ // true parents and marking them false as well. This also handles
+ // inserting transform_node if it isn't in the map, and keeps track of
+ // clips or effects.
+ auto mark_not_decompositable =
+ [&can_be_decomposited](
+ const TransformPaintPropertyNode& transform_node) {
+ for (const auto* node = &transform_node; node && !node->IsRoot();
+ node = node->UnaliasedParent()) {
+ auto result = can_be_decomposited.insert(node, false);
+ if (!result.is_new_entry) {
+ if (!result.stored_value->value)
+ break;
+ result.stored_value->value = false;
+ }
+ }
+ };
+
+ // Add the transform and all transform parents to the map.
+ for (const auto* node = &property_state.Transform();
+ !node->IsRoot() && !can_be_decomposited.Contains(node);
+ node = &node->Parent()->Unalias()) {
+ if (!node->IsIdentityOr2DTranslation() || node->ScrollNode() ||
+ node->GetStickyConstraint() ||
+ node->IsAffectedByOuterViewportBoundsDelta() ||
+ node->HasDirectCompositingReasonsOtherThan3dTransform() ||
+ !node->FlattensInheritedTransformSameAsParent() ||
+ !node->BackfaceVisibilitySameAsParent()) {
+ mark_not_decompositable(*node);
+ break;
+ }
+ can_be_decomposited.insert(node, true);
+ }
+
+ // Add clips and effects, and their parents, that we haven't already seen.
+ for (const auto* node = &property_state.Clip();
+ !node->IsRoot() && !clips_and_effects_seen.Contains(node);
+ node = &node->Parent()->Unalias()) {
+ clips_and_effects_seen.insert(node);
+ mark_not_decompositable(node->LocalTransformSpace().Unalias());
+ }
+ for (const auto* node = &property_state.Effect();
+ !node->IsRoot() && !clips_and_effects_seen.Contains(node);
+ node = &node->Parent()->Unalias()) {
+ clips_and_effects_seen.insert(node);
+ mark_not_decompositable(node->LocalTransformSpace().Unalias());
+ }
+
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ pending_layer.GetCompositingType() == kScrollHitTestLayer) {
+ // The scroll translation node of a scroll hit test layer may not be
+ // referenced by any pending layer's property tree state. Disallow
+ // decomposition of it (and its ancestors).
+ mark_not_decompositable(
+ pending_layer.ScrollTranslationForScrollHitTestLayer());
+ }
+ }
+
+ // Now, for any transform nodes that can be de-composited, re-map their
+ // transform to point to the correct parent, and set the
+ // offset_to_transform_parent.
+ for (PendingLayer& pending_layer : pending_layers) {
+ const auto* transform = &pending_layer.GetPropertyTreeState().Transform();
+ while (!transform->IsRoot() && can_be_decomposited.at(transform)) {
+ pending_layer.offset_of_decomposited_transforms_ +=
+ transform->Translation2D();
+ pending_layer.change_of_decomposited_transforms_ =
+ std::max(pending_layer.ChangeOfDecompositedTransforms(),
+ transform->NodeChanged());
+ transform = &transform->Parent()->Unalias();
+ }
+ pending_layer.property_tree_state_.SetTransform(*transform);
+ pending_layer.bounds_.MoveBy(
+ pending_layer.OffsetOfDecompositedTransforms());
+ pending_layer.rect_known_to_be_opaque_.MoveBy(
+ pending_layer.OffsetOfDecompositedTransforms());
+ }
+}
+
+bool PendingLayer::IsSolidColor() const {
+ if (Chunks().size() != 1)
+ return false;
+ const auto& items = chunks_.begin().DisplayItems();
+ if (items.size() != 1)
+ return false;
+ auto* drawing = DynamicTo<DrawingDisplayItem>(*items.begin());
+ return drawing && drawing->IsSolidColor();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h
new file mode 100644
index 00000000000..4ab56b078ae
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h
@@ -0,0 +1,156 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PENDING_LAYER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PENDING_LAYER_H_
+
+#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
+
+namespace blink {
+
+class GraphicsLayer;
+
+// Information of a composited layer that is created during compositing update
+// in pre-CompositeAfterPaint. In CompositeAfterPaint, this is expected to
+// contain all paint chunks, as if we created one root layer that needs to be
+// future layerized.
+struct PreCompositedLayerInfo {
+ // For now this is used only when graphics_layer == nullptr. This will also
+ // contain the paint chunks for the graphics layer when we unify
+ // PaintController for pre-CAP and CAP.
+ PaintChunkSubset chunks;
+ // If this is not nullptr, we should use the composited layer created by the
+ // GraphicsLayer. Otherwise we should layerize |chunks|. A GraphicsLayer with
+ // ShouldCreateLayersAfterPaint() == true should set this field to nullptr.
+ const GraphicsLayer* graphics_layer = nullptr;
+};
+
+// A pending layer is a collection of paint chunks that will end up in the same
+// cc::Layer.
+class PLATFORM_EXPORT PendingLayer {
+ public:
+ enum CompositingType {
+ kScrollHitTestLayer,
+ kPreCompositedLayer,
+ kForeignLayer,
+ kScrollbarLayer,
+ kOverlap,
+ kOther,
+ };
+
+ PendingLayer(const PaintChunkSubset&, const PaintChunkIterator&);
+ explicit PendingLayer(const PreCompositedLayerInfo&);
+
+ // Returns the offset/bounds for the final cc::Layer, rounded if needed.
+ FloatPoint LayerOffset() const;
+ IntSize LayerBounds() const;
+
+ const FloatRect& BoundsForTesting() const { return bounds_; }
+
+ const FloatRect& RectKnownToBeOpaque() const {
+ return rect_known_to_be_opaque_;
+ }
+ bool TextKnownToBeOnOpaqueBackground() const {
+ return text_known_to_be_on_opaque_background_;
+ }
+ const PaintChunkSubset& Chunks() const { return chunks_; }
+ const PropertyTreeState& GetPropertyTreeState() const {
+ return property_tree_state_;
+ }
+ const FloatPoint& OffsetOfDecompositedTransforms() const {
+ return offset_of_decomposited_transforms_;
+ }
+ PaintPropertyChangeType ChangeOfDecompositedTransforms() const {
+ return change_of_decomposited_transforms_;
+ }
+ const GraphicsLayer* GetGraphicsLayer() const { return graphics_layer_; }
+ CompositingType GetCompositingType() const { return compositing_type_; }
+
+ void SetCompositingType(CompositingType new_type) {
+ compositing_type_ = new_type;
+ }
+
+ void SetPaintArtifact(scoped_refptr<const PaintArtifact> paint_artifact) {
+ chunks_.SetPaintArtifact(paint_artifact);
+ }
+
+ // Merges |guest| into |this| if it can, by appending chunks of |guest|
+ // after chunks of |this|, with appropriate space conversion applied to
+ // both layers from their original property tree states to |merged_state|.
+ // Returns whether the merge is successful.
+ bool Merge(const PendingLayer& guest, bool prefers_lcd_text = false) {
+ return MergeInternal(guest, guest.property_tree_state_, prefers_lcd_text,
+ /*dry_run*/ false);
+ }
+
+ // Returns true if |guest| can be merged into |this|.
+ // |guest_state| is for cases where we want to check if we can merge |guest|
+ // if it has |guest_state| in the future (which may be different from its
+ // current state).
+ bool CanMerge(const PendingLayer& guest,
+ const PropertyTreeState& guest_state,
+ bool prefers_lcd_text = false) const {
+ return const_cast<PendingLayer*>(this)->MergeInternal(
+ guest, guest_state, prefers_lcd_text, /*dry_run*/ true);
+ }
+
+ // Mutate this layer's property tree state to a more general (shallower)
+ // state, thus the name "upcast". The concrete effect of this is to
+ // "decomposite" some of the properties, so that fewer properties will be
+ // applied by the compositor, and more properties will be applied internally
+ // to the chunks as Skia commands.
+ void Upcast(const PropertyTreeState&);
+
+ const PaintChunk& FirstPaintChunk() const;
+ const DisplayItem& FirstDisplayItem() const;
+
+ const TransformPaintPropertyNode& ScrollTranslationForScrollHitTestLayer()
+ const;
+
+ std::unique_ptr<JSONObject> ToJSON() const;
+
+ bool MayDrawContent() const;
+
+ bool RequiresOwnLayer() const {
+ return compositing_type_ != kOverlap && compositing_type_ != kOther;
+ }
+
+ bool PropertyTreeStateChanged() const;
+
+ bool MightOverlap(const PendingLayer& other) const;
+
+ static void DecompositeTransforms(Vector<PendingLayer>& pending_layers);
+
+ private:
+ PendingLayer(const PaintChunkSubset&,
+ const PaintChunk& first_chunk,
+ wtf_size_t first_chunk_index_in_paint_artifact);
+ FloatRect VisualRectForOverlapTesting(
+ const PropertyTreeState& ancestor_state) const;
+ FloatRect MapRectKnownToBeOpaque(const PropertyTreeState&) const;
+ bool MergeInternal(const PendingLayer& guest,
+ const PropertyTreeState& guest_state,
+ bool prefers_lcd_text,
+ bool dry_run);
+
+ // True if this contains only a single solid color DrawingDisplayItem.
+ bool IsSolidColor() const;
+
+ // The rects are in the space of property_tree_state.
+ FloatRect bounds_;
+ FloatRect rect_known_to_be_opaque_;
+ bool has_text_ = false;
+ bool text_known_to_be_on_opaque_background_ = false;
+ PaintChunkSubset chunks_;
+ PropertyTreeState property_tree_state_;
+ FloatPoint offset_of_decomposited_transforms_;
+ PaintPropertyChangeType change_of_decomposited_transforms_ =
+ PaintPropertyChangeType::kUnchanged;
+ const GraphicsLayer* graphics_layer_ = nullptr;
+ CompositingType compositing_type_;
+};
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PENDING_LAYER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc
new file mode 100644
index 00000000000..c6525b86519
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc
@@ -0,0 +1,509 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/compositing/pending_layer.h"
+
+#include <memory>
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.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::ElementsAre;
+
+static Vector<wtf_size_t> ChunkIndices(const PendingLayer& layer) {
+ Vector<wtf_size_t> indices;
+ for (auto it = layer.Chunks().begin(); it != layer.Chunks().end(); ++it)
+ indices.push_back(it.IndexInPaintArtifact());
+ return indices;
+}
+
+TEST(PendingLayerTest, MightOverlap) {
+ TestPaintArtifact artifact;
+ artifact.Chunk().Bounds(IntRect(0, 0, 100, 100));
+ artifact.Chunk().Bounds(IntRect(0, 0, 100, 100));
+ auto t2 = CreateTransform(t0(), TransformationMatrix().Translate(99, 0),
+ FloatPoint3D(100, 100, 0));
+ artifact.Chunk(*t2, c0(), e0()).Bounds(IntRect(0, 0, 100, 100));
+ auto t3 = CreateTransform(t0(), TransformationMatrix().Translate(100, 0),
+ FloatPoint3D(100, 100, 0));
+ artifact.Chunk(*t3, c0(), e0()).Bounds(IntRect(0, 0, 100, 100));
+ auto t4 =
+ CreateAnimatingTransform(t0(), TransformationMatrix().Translate(100, 0),
+ FloatPoint3D(100, 100, 0));
+ artifact.Chunk(*t4, c0(), e0()).Bounds(IntRect(0, 0, 100, 100));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ EXPECT_TRUE(
+ pending_layer.MightOverlap(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_TRUE(
+ pending_layer.MightOverlap(PendingLayer(chunks, chunks.begin() + 2)));
+ EXPECT_FALSE(
+ pending_layer.MightOverlap(PendingLayer(chunks, chunks.begin() + 3)));
+ EXPECT_TRUE(
+ pending_layer.MightOverlap(PendingLayer(chunks, chunks.begin() + 4)));
+}
+
+TEST(PendingLayerTest, MightOverlapCommonClipAncestor) {
+ auto common_clip = CreateClip(c0(), t0(), FloatRoundedRect(0, 0, 100, 100));
+ auto c1 = CreateClip(*common_clip, t0(), FloatRoundedRect(0, 100, 100, 100));
+ auto c2 = CreateClip(*common_clip, t0(), FloatRoundedRect(50, 100, 100, 100));
+ auto c3 =
+ CreateClip(*common_clip, t0(), FloatRoundedRect(100, 100, 100, 100));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *c1, e0())
+ .Bounds(IntRect(0, 100, 200, 100))
+ .Chunk(t0(), *c2, e0())
+ .Bounds(IntRect(0, 100, 200, 100))
+ .Chunk(t0(), *c3, e0())
+ .Bounds(IntRect(0, 100, 200, 100));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer1(chunks, chunks.begin());
+ PendingLayer pending_layer2(chunks, chunks.begin() + 1);
+ PendingLayer pending_layer3(chunks, chunks.begin() + 2);
+ EXPECT_FALSE(pending_layer1.MightOverlap(pending_layer3));
+ EXPECT_TRUE(pending_layer1.MightOverlap(pending_layer2));
+ EXPECT_TRUE(pending_layer2.MightOverlap(pending_layer3));
+}
+
+TEST(PendingLayerTest, Merge) {
+ TestPaintArtifact artifact;
+ artifact.Chunk()
+ .Bounds(IntRect(0, 0, 30, 40))
+ .RectKnownToBeOpaque(IntRect(0, 0, 30, 40));
+ artifact.Chunk()
+ .Bounds(IntRect(10, 20, 30, 40))
+ .RectKnownToBeOpaque(IntRect(10, 20, 30, 40));
+ artifact.Chunk()
+ .Bounds(IntRect(-5, -25, 20, 20))
+ .RectKnownToBeOpaque(IntRect(-5, -25, 20, 20));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.BoundsForTesting());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
+ EXPECT_EQ(pending_layer.BoundsForTesting(),
+ pending_layer.RectKnownToBeOpaque());
+
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+
+ // Bounds not equal to one PaintChunk.
+ EXPECT_EQ(FloatRect(0, 0, 40, 60), pending_layer.BoundsForTesting());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0, 1));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.RectKnownToBeOpaque());
+
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 2)));
+
+ EXPECT_EQ(FloatRect(-5, -25, 45, 85), pending_layer.BoundsForTesting());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0, 1, 2));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.RectKnownToBeOpaque());
+}
+
+TEST(PendingLayerTest, MergeWithGuestTransform) {
+ TestPaintArtifact artifact;
+ artifact.Chunk().Bounds(IntRect(0, 0, 30, 40));
+ auto transform = Create2DTranslation(t0(), 20, 25);
+ artifact.Chunk(*transform, c0(), e0()).Bounds(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(0, 0, 70, 85), pending_layer.BoundsForTesting());
+ EXPECT_EQ(PropertyTreeState::Root(), pending_layer.GetPropertyTreeState());
+}
+
+TEST(PendingLayerTest, MergeWithHomeTransform) {
+ TestPaintArtifact artifact;
+ auto transform = Create2DTranslation(t0(), 20, 25);
+ artifact.Chunk(*transform, c0(), e0()).Bounds(IntRect(0, 0, 30, 40));
+ artifact.Chunk().Bounds(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(0, 0, 50, 65), pending_layer.BoundsForTesting());
+ EXPECT_EQ(PropertyTreeState::Root(), pending_layer.GetPropertyTreeState());
+}
+
+TEST(PendingLayerTest, MergeWithBothTransforms) {
+ TestPaintArtifact artifact;
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ artifact.Chunk(*t1, c0(), e0()).Bounds(IntRect(0, 0, 30, 40));
+ auto t2 = Create2DTranslation(t0(), -20, -25);
+ artifact.Chunk(*t2, c0(), e0()).Bounds(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(-20, -25, 70, 90), pending_layer.BoundsForTesting());
+ EXPECT_EQ(PropertyTreeState::Root(), pending_layer.GetPropertyTreeState());
+}
+
+TEST(PendingLayerTest, MergeSparseTinyLayers) {
+ TestPaintArtifact artifact;
+ artifact.Chunk()
+ .Bounds(IntRect(0, 0, 3, 4))
+ .RectKnownToBeOpaque(IntRect(0, 0, 3, 4));
+ artifact.Chunk()
+ .Bounds(IntRect(20, 20, 3, 4))
+ .RectKnownToBeOpaque(IntRect(20, 20, 3, 4));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(0, 0, 23, 24), pending_layer.BoundsForTesting());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0, 1));
+}
+
+TEST(PendingLayerTest, DontMergeSparse) {
+ TestPaintArtifact artifact;
+ artifact.Chunk()
+ .Bounds(IntRect(0, 0, 30, 40))
+ .RectKnownToBeOpaque(IntRect(0, 0, 30, 40));
+ artifact.Chunk()
+ .Bounds(IntRect(200, 200, 30, 40))
+ .RectKnownToBeOpaque(IntRect(200, 200, 30, 40));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.BoundsForTesting());
+ EXPECT_EQ(chunks.begin()->properties, pending_layer.GetPropertyTreeState());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
+}
+
+TEST(PendingLayerTest, PendingLayerDontMergeSparseWithTransforms) {
+ TestPaintArtifact artifact;
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ artifact.Chunk(*t1, c0(), e0()).Bounds(IntRect(0, 0, 30, 40));
+ auto t2 = Create2DTranslation(t0(), 1000, 1000);
+ artifact.Chunk(*t2, c0(), e0()).Bounds(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.BoundsForTesting());
+ EXPECT_EQ(chunks.begin()->properties, pending_layer.GetPropertyTreeState());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
+}
+
+TEST(PendingLayerTest, DontMergeSparseInCompositedEffect) {
+ TestPaintArtifact artifact;
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ auto e1 =
+ CreateOpacityEffect(e0(), 1.0f, CompositingReason::kWillChangeOpacity);
+ artifact.Chunk(*t1, c0(), *e1).Bounds(IntRect(0, 0, 30, 40));
+ auto t2 = Create2DTranslation(t0(), 1000, 1000);
+ artifact.Chunk(*t2, c0(), *e1).Bounds(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.BoundsForTesting());
+ EXPECT_EQ(chunks.begin()->properties, pending_layer.GetPropertyTreeState());
+ EXPECT_THAT(ChunkIndices(pending_layer), ElementsAre(0));
+}
+
+TEST(PendingLayerTest, MergeSparseInNonCompositedEffect) {
+ TestPaintArtifact artifact;
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ auto t2 = Create2DTranslation(t0(), 1000, 1000);
+ auto e1 = CreateOpacityEffect(e0(), 1.0f, CompositingReason::kNone);
+ artifact.Chunk(*t1, c0(), *e1).Bounds(IntRect(0, 0, 30, 40));
+ artifact.Chunk(*t2, c0(), *e1).Bounds(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ EXPECT_FALSE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+}
+
+TEST(PendingLayerTest, KnownOpaque) {
+ TestPaintArtifact artifact;
+ artifact.Chunk().Bounds(IntRect(0, 0, 30, 40));
+ artifact.Chunk()
+ .Bounds(IntRect(0, 0, 25, 35))
+ .RectKnownToBeOpaque(IntRect(0, 0, 25, 35));
+ artifact.Chunk()
+ .Bounds(IntRect(0, 0, 50, 60))
+ .RectKnownToBeOpaque(IntRect(0, 0, 50, 60));
+ PaintChunkSubset chunks(artifact.Build());
+
+ PendingLayer pending_layer(chunks, chunks.begin());
+ EXPECT_TRUE(pending_layer.RectKnownToBeOpaque().IsEmpty());
+
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 1)));
+ // Chunk 2 doesn't cover the entire layer, so not opaque.
+ EXPECT_EQ(FloatRect(0, 0, 25, 35), pending_layer.RectKnownToBeOpaque());
+ EXPECT_NE(pending_layer.BoundsForTesting(),
+ pending_layer.RectKnownToBeOpaque());
+
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunks, chunks.begin() + 2)));
+ // Chunk 3 covers the entire layer, so now it's opaque.
+ EXPECT_EQ(FloatRect(0, 0, 50, 60), pending_layer.BoundsForTesting());
+ EXPECT_EQ(pending_layer.BoundsForTesting(),
+ pending_layer.RectKnownToBeOpaque());
+}
+
+TEST(PendingLayerTest, CanNotMergeAcrossPaintArtifacts) {
+ TestPaintArtifact test_artifact_a;
+ test_artifact_a.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
+ PaintChunkSubset chunks_a(test_artifact_a.Build());
+ PendingLayer layer_a(chunks_a, chunks_a.begin());
+
+ TestPaintArtifact test_artifact_b;
+ test_artifact_b.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
+ PaintChunkSubset chunks_b(test_artifact_b.Build());
+ PendingLayer layer_b(chunks_b, chunks_b.begin());
+
+ EXPECT_FALSE(layer_a.Merge(layer_b));
+}
+
+class PendingLayerTextOpaquenessTest
+ : public testing::Test,
+ public testing::WithParamInterface<bool> {
+ protected:
+ bool PrefersLCDText() const { return GetParam(); }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+ PendingLayerTextOpaquenessTest,
+ ::testing::Values(false, true));
+
+TEST_P(PendingLayerTextOpaquenessTest, OpaqueTextAndOpaqueText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, NonOpaqueTextAndOpaqueText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .HasText()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ bool merged = layer_a.Merge(layer_b, PrefersLCDText());
+ if (PrefersLCDText()) {
+ // Not merged because merging would lose TextKnownToBeOnOpaqueBackground().
+ ASSERT_FALSE(merged);
+ } else {
+ ASSERT_TRUE(merged);
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_FALSE(layer_a.TextKnownToBeOnOpaqueBackground());
+ }
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, OpaqueTextAndNonOpaqueText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .HasText();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ bool merged = layer_a.Merge(layer_b, PrefersLCDText());
+ if (PrefersLCDText()) {
+ // Not merged because merging would lose TextKnownToBeOnOpaqueBackground().
+ ASSERT_FALSE(merged);
+ } else {
+ ASSERT_TRUE(merged);
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_FALSE(layer_a.TextKnownToBeOnOpaqueBackground());
+ }
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, NonOpaqueTextAndOpaqueTextCovered) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 100, 100), Color::kBlack)
+ .HasText()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 300, 300), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(200, 200, 100, 100))
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 300, 300), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(200, 200, 100, 100), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, OpaqueTextAndNonOpaqueTextCovered) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 100, 100), Color::kBlack)
+ .HasText();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 250, 250), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(100, 100, 210, 210), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, NoTextAndOpaqueText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(100, 100, 210, 210), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, OpaqueTextAndNoText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack);
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(100, 100, 210, 210), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, NonOpaqueNoTextAndNonOpaqueText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .HasText();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_FALSE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, NonOpaqueTextAndNonOpaqueNoText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .HasText()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack);
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 400, 400), layer_a.BoundsForTesting());
+ EXPECT_FALSE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, OpaqueNoTextAndNonOpaqueText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 100, 100), Color::kBlack)
+ .HasText();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 250, 250), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(100, 100, 210, 210), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, NonOpaqueTextAndOpaqueNoText) {
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 100, 100), Color::kBlack)
+ .HasText()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210));
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(100, 100, 250, 250), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(100, 100, 210, 210), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+TEST_P(PendingLayerTextOpaquenessTest, UnitedClippedToOpaque) {
+ // Though the second chunk has text not on opaque background, and it's not
+ // fully covered by the opaque rect of the first chunk, the non-opaque area
+ // is not visible in the final layer, so we still allow the merge.
+ auto clip1 = CreateClip(c0(), t0(), FloatRoundedRect(175, 175, 100, 100));
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *clip1, e0())
+ .RectDrawing(IntRect(100, 100, 250, 250), Color::kBlack)
+ .RectKnownToBeOpaque(IntRect(100, 100, 210, 210))
+ .HasText()
+ .TextKnownToBeOnOpaqueBackground()
+ .Chunk(t0(), *clip1, e0())
+ .RectDrawing(IntRect(200, 200, 300, 300), Color::kBlack)
+ .HasText();
+ PaintChunkSubset chunks(artifact.Build());
+ PendingLayer layer_a(chunks, chunks.begin());
+ PendingLayer layer_b(chunks, chunks.begin() + 1);
+ ASSERT_TRUE(layer_a.Merge(layer_b, PrefersLCDText()));
+ EXPECT_EQ(FloatRect(175, 175, 100, 100), layer_a.BoundsForTesting());
+ EXPECT_EQ(FloatRect(100, 100, 210, 210), layer_a.RectKnownToBeOpaque());
+ EXPECT_TRUE(layer_a.TextKnownToBeOnOpaqueBackground());
+}
+
+} // namespace blink
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 305a5d4aaee..a3ed44804f0 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
@@ -420,6 +420,18 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
EnsureCompositorTransformNode(transform_node.Parent()->Unalias());
id = GetTransformTree().Insert(cc::TransformNode(), parent_id);
+ // ScrollUnification creates the entire scroll tree and will already have done
+ // this.
+ if (!RuntimeEnabledFeatures::ScrollUnificationEnabled()) {
+ if (auto* scroll_translation_for_fixed =
+ transform_node.ScrollTranslationForFixed()) {
+ // Fixed-position can cause different topologies of the transform tree and
+ // the scroll tree. This ensures the ancestor scroll nodes of the scroll
+ // node for a descendant transform node below is created.
+ EnsureCompositorTransformNode(*scroll_translation_for_fixed);
+ }
+ }
+
cc::TransformNode& compositor_node = *GetTransformTree().Node(id);
UpdateCcTransformLocalMatrix(compositor_node, transform_node);
compositor_node.transform_changed = transform_node.NodeChangeAffectsRaster();
@@ -484,6 +496,7 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
// If this transform is a scroll offset translation, create the associated
// compositor scroll property node and adjust the compositor transform node's
// scroll offset.
+ // TODO(ScrollUnification): Move this code into EnsureCompositorScrollNodes().
if (auto* scroll_node = transform_node.ScrollNode()) {
compositor_node.scrolls = true;
compositor_node.should_be_snapped = true;
@@ -615,6 +628,9 @@ void PropertyTreeManager::CreateCompositorScrollNode(
int PropertyTreeManager::EnsureCompositorScrollNode(
const TransformPaintPropertyNode& scroll_offset_translation) {
+ // TODO(ScrollUnification): Remove this function and let
+ // EnsureCompositorScrollNodes() call EnsureCompositorTransformNode() and
+ // CreateCompositorScrollNode() directly.
const auto* scroll_node = scroll_offset_translation.ScrollNode();
DCHECK(scroll_node);
EnsureCompositorTransformNode(scroll_offset_translation);
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 380703a90ed..186ba66a10b 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,7 +5,6 @@
#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/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -60,6 +59,8 @@ class PropertyTreeManager {
cc::Layer& root_layer,
LayerListBuilder& layer_list_builder,
int new_sequence_number);
+ PropertyTreeManager(const PropertyTreeManager&) = delete;
+ PropertyTreeManager& operator=(const PropertyTreeManager&) = delete;
~PropertyTreeManager();
// A brief discourse on cc property tree nodes, identifiers, and current and
@@ -315,8 +316,6 @@ class PropertyTreeManager {
// A set of synthetic clips masks which will be applied if a layer under them
// is encountered which draws content (and thus necessitates the mask).
HashSet<int> pending_synthetic_mask_layers_;
-
- DISALLOW_COPY_AND_ASSIGN(PropertyTreeManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
index b0f2223ae2e..55baccd94ca 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -41,8 +41,9 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = {
"Has an active accelerated backdrop filter animation or transition"},
{CompositingReason::kXrOverlay, "xrOverlay",
"Is DOM overlay for WebXR immersive-ar mode"},
- {CompositingReason::kScrollDependentPosition, "scrollDependentPosition",
- "Is fixed or sticky position"},
+ {CompositingReason::kFixedPosition, "fixedPosition", "Is fixed position"},
+ {CompositingReason::kStickyPosition, "stickyPosition",
+ "Is sticky position"},
{CompositingReason::kOverflowScrolling, "overflowScrolling",
"Is a scrollable overflow element"},
{CompositingReason::kOverflowScrollingParent, "overflowScrollingParent",
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 0fc88cb5a10..2bc6d045b32 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -31,7 +31,8 @@ using CompositingReasons = uint64_t;
V(ActiveFilterAnimation) \
V(ActiveBackdropFilterAnimation) \
V(AffectedByOuterViewportBoundsDelta) \
- V(ScrollDependentPosition) \
+ V(FixedPosition) \
+ V(StickyPosition) \
V(OverflowScrolling) \
V(OverflowScrollingParent) \
V(OutOfFlowClipping) \
@@ -131,10 +132,12 @@ class PLATFORM_EXPORT CompositingReason {
kWillChangeFilter | kWillChangeOther | kBackdropFilter |
kWillChangeBackdropFilter,
+ kComboScrollDependentPosition = kFixedPosition | kStickyPosition,
+
kComboAllDirectNonStyleDeterminedReasons =
kVideo | kCanvas | kPlugin | kIFrame | kSVGRoot |
kOverflowScrollingParent | kOutOfFlowClipping | kVideoOverlay |
- kXrOverlay | kRoot | kRootScroller | kScrollDependentPosition |
+ kXrOverlay | kRoot | kRootScroller | kComboScrollDependentPosition |
kAffectedByOuterViewportBoundsDelta | kBackfaceInvisibility3DAncestor |
kDocumentTransitionSharedElement,
@@ -142,7 +145,7 @@ class PLATFORM_EXPORT CompositingReason {
kComboAllDirectNonStyleDeterminedReasons,
kComboAllCompositedScrollingDeterminedReasons =
- kScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
+ kComboScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
kOverflowScrolling,
kComboCompositedDescendants =
@@ -164,7 +167,7 @@ class PLATFORM_EXPORT CompositingReason {
kPreventingSubpixelAccumulationReasons = kWillChangeTransform,
kDirectReasonsForPaintOffsetTranslationProperty =
- kScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
+ kComboScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
kVideo | kCanvas | kPlugin | kIFrame | kSVGRoot,
kDirectReasonsForTransformProperty =
k3DTransform | kTrivial3DTransform | kWillChangeTransform |
@@ -198,11 +201,11 @@ inline bool RequiresSquashing(CompositingReasons reasons) {
}
struct CompositingReasonsStats {
- size_t overlap_layers = 0;
- size_t active_animation_layers = 0;
- size_t assumed_overlap_layers = 0;
- size_t indirect_composited_layers = 0;
- size_t total_composited_layers = 0;
+ int overlap_layers = 0;
+ int active_animation_layers = 0;
+ int assumed_overlap_layers = 0;
+ int indirect_composited_layers = 0;
+ int total_composited_layers = 0;
};
} // namespace blink
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 e4f3d18b357..2c645aa9252 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
+#include "third_party/blink/renderer/platform/graphics/color.h"
#include "ui/gfx/geometry/rect.h"
namespace blink {
@@ -68,7 +69,7 @@ void CompositorFilterOperations::AppendBlurFilter(float amount,
void CompositorFilterOperations::AppendDropShadowFilter(IntPoint offset,
float std_deviation,
- Color color) {
+ const Color& color) {
gfx::Point gfx_offset(offset.X(), offset.Y());
filter_operations_.Append(cc::FilterOperation::CreateDropShadowFilter(
gfx_offset, std_deviation, color.Rgb()));
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 a840aac49d2..414ff913168 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
@@ -8,7 +8,6 @@
#include "cc/paint/filter_operations.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_filter.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -16,6 +15,8 @@
namespace blink {
+class Color;
+
// An ordered list of filter operations.
class PLATFORM_EXPORT CompositorFilterOperations {
public:
@@ -33,7 +34,9 @@ class PLATFORM_EXPORT CompositorFilterOperations {
void AppendOpacityFilter(float amount);
void AppendBlurFilter(float amount,
SkTileMode tile_mode = SkTileMode::kDecal);
- void AppendDropShadowFilter(IntPoint offset, float std_deviation, Color);
+ void AppendDropShadowFilter(IntPoint offset,
+ float std_deviation,
+ const Color& color);
void AppendColorMatrixFilter(const cc::FilterOperation::Matrix&);
void AppendZoomFilter(float amount, int inset);
void AppendSaturatingBrightnessFilter(float amount);
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 ad7135d0466..9039b3c349f 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
@@ -35,24 +35,21 @@ CrossfadeGeneratedImage::CrossfadeGeneratedImage(
scoped_refptr<Image> from_image,
scoped_refptr<Image> to_image,
float percentage,
- FloatSize crossfade_size,
const FloatSize& size)
: GeneratedImage(size),
from_image_(std::move(from_image)),
to_image_(std::move(to_image)),
- percentage_(percentage),
- crossfade_size_(crossfade_size) {}
+ percentage_(percentage) {}
void CrossfadeGeneratedImage::DrawCrossfade(
cc::PaintCanvas* canvas,
- const SkSamplingOptions& sampling,
const PaintFlags& flags,
- RespectImageOrientationEnum respect_orientation,
+ const ImageDrawOptions& draw_options,
ImageClampingMode clamp_mode,
ImageDecodingMode decode_mode) {
FloatRect from_image_rect(FloatPoint(), FloatSize(from_image_->Size()));
FloatRect to_image_rect(FloatPoint(), FloatSize(to_image_->Size()));
- FloatRect dest_rect((FloatPoint()), crossfade_size_);
+ FloatRect dest_rect((FloatPoint()), size_);
// TODO(junov): The various effects encoded into paint should probably be
// applied here instead of inside the layer. This probably faulty behavior
@@ -70,23 +67,24 @@ void CrossfadeGeneratedImage::DrawCrossfade(
// RespectImageOrientationEnum from CrossfadeGeneratedImage::draw(). Code was
// written this way during refactoring to avoid modifying existing behavior,
// but this warrants further investigation. crbug.com/472634
- from_image_->Draw(canvas, image_flags, dest_rect, from_image_rect, sampling,
- kDoNotRespectImageOrientation, clamp_mode, decode_mode);
+ ImageDrawOptions from_draw_options;
+ from_draw_options.sampling_options = draw_options.sampling_options;
+ from_draw_options.respect_image_orientation = kDoNotRespectImageOrientation;
+ from_image_->Draw(canvas, image_flags, dest_rect, from_image_rect,
+ from_draw_options, clamp_mode, decode_mode);
image_flags.setBlendMode(SkBlendMode::kPlus);
image_flags.setColor(ScaleAlpha(flags.getColor(), percentage_));
- to_image_->Draw(canvas, image_flags, dest_rect, to_image_rect, sampling,
- respect_orientation, clamp_mode, decode_mode);
+ to_image_->Draw(canvas, image_flags, dest_rect, to_image_rect, draw_options,
+ clamp_mode, decode_mode);
}
-void CrossfadeGeneratedImage::Draw(
- cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- const SkSamplingOptions& sampling,
- RespectImageOrientationEnum respect_orientation,
- ImageClampingMode clamp_mode,
- ImageDecodingMode decode_mode) {
+void CrossfadeGeneratedImage::Draw(cc::PaintCanvas* canvas,
+ const PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ const ImageDrawOptions& draw_options,
+ ImageClampingMode clamp_mode,
+ ImageDecodingMode decode_mode) {
// Draw nothing if either of the images hasn't loaded yet.
if (from_image_ == Image::NullImage() || to_image_ == Image::NullImage())
return;
@@ -94,8 +92,7 @@ void CrossfadeGeneratedImage::Draw(
PaintCanvasAutoRestore ar(canvas, true);
canvas->clipRect(dst_rect);
canvas->concat(SkMatrix::RectToRect(src_rect, dst_rect));
- DrawCrossfade(canvas, sampling, flags, respect_orientation, clamp_mode,
- decode_mode);
+ DrawCrossfade(canvas, flags, draw_options, clamp_mode, decode_mode);
}
void CrossfadeGeneratedImage::DrawTile(
@@ -105,13 +102,14 @@ void CrossfadeGeneratedImage::DrawTile(
// Draw nothing if either of the images hasn't loaded yet.
if (from_image_ == Image::NullImage() || to_image_ == Image::NullImage())
return;
-
PaintFlags flags = context.FillFlags();
flags.setBlendMode(SkBlendMode::kSrcOver);
- FloatRect dest_rect((FloatPoint()), crossfade_size_);
- DrawCrossfade(context.Canvas(),
- context.ComputeSamplingOptions(this, dest_rect, src_rect),
- flags, respect_orientation, kClampImageToSourceRect,
+ FloatRect dest_rect((FloatPoint()), size_);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options =
+ context.ComputeSamplingOptions(this, dest_rect, src_rect);
+ draw_options.respect_image_orientation = respect_orientation;
+ DrawCrossfade(context.Canvas(), flags, draw_options, kClampImageToSourceRect,
kSyncDecode);
}
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 1fb85099846..a49ee90e3df 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
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/generated_image.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/graphics/image_observer.h"
namespace blink {
@@ -40,24 +39,23 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
scoped_refptr<Image> from_image,
scoped_refptr<Image> to_image,
float percentage,
- FloatSize crossfade_size,
const FloatSize& size) {
- return base::AdoptRef(
- new CrossfadeGeneratedImage(std::move(from_image), std::move(to_image),
- percentage, crossfade_size, size));
+ return base::AdoptRef(new CrossfadeGeneratedImage(
+ std::move(from_image), std::move(to_image), percentage, size));
}
bool HasIntrinsicSize() const override { return true; }
- IntSize Size() const override { return FlooredIntSize(crossfade_size_); }
+ IntSize SizeWithConfig(SizeConfig) const override {
+ return FlooredIntSize(size_);
+ }
protected:
void Draw(cc::PaintCanvas*,
const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
void DrawTile(GraphicsContext&,
@@ -67,14 +65,12 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
CrossfadeGeneratedImage(scoped_refptr<Image> from_image,
scoped_refptr<Image> to_image,
float percentage,
- FloatSize crossfade_size,
const FloatSize&);
private:
void DrawCrossfade(cc::PaintCanvas*,
- const SkSamplingOptions&,
const cc::PaintFlags&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode);
@@ -82,7 +78,6 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
scoped_refptr<Image> to_image_;
float percentage_;
- FloatSize crossfade_size_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
index fd23211ae43..cc993636d8e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
@@ -142,7 +142,6 @@ sk_sp<SkColorFilter> DarkModeFilter::ApplyToImage(const SkPixmap& pixmap,
}
sk_sp<SkColorFilter> DarkModeFilter::GetImageFilter() const {
- DCHECK(immutable_.settings.image_policy == DarkModeImagePolicy::kFilterAll);
DCHECK(immutable_.image_filter);
return immutable_.image_filter;
}
@@ -174,6 +173,7 @@ absl::optional<cc::PaintFlags> DarkModeFilter::ApplyToFlagsIfNeeded(
bool DarkModeFilter::ShouldApplyToColor(SkColor color, ElementRole role) {
switch (role) {
+ case ElementRole::kSVG:
case ElementRole::kText:
DCHECK(immutable_.text_classifier);
return immutable_.text_classifier->ShouldInvertColor(color) ==
@@ -189,16 +189,6 @@ bool DarkModeFilter::ShouldApplyToColor(SkColor color, ElementRole role) {
DCHECK(immutable_.background_classifier);
return immutable_.background_classifier->ShouldInvertColor(color) ==
DarkModeResult::kApplyFilter;
- case ElementRole::kSVG:
- // 1) Inline SVG images are considered as individual shapes and do not
- // have an Image object associated with them. So they do not go through
- // the regular image classification pipeline. Do not apply any filter to
- // the SVG shapes until there is a way to get the classification for the
- // entire image to which these shapes belong.
-
- // 2) Non-inline SVG images are already classified at this point and have
- // a filter applied if necessary.
- return false;
default:
return false;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
index 958c3a7be08..4e2c51fc969 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
@@ -7,12 +7,14 @@
#include <memory>
+#include "base/stl_util.h"
#include "cc/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_settings.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_types.h"
#include "third_party/blink/renderer/platform/platform_export.h"
class SkColorFilter;
+class SkPixmap;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_helper.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_helper.cc
index bc42f99f863..6a00aaf8743 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_helper.cc
@@ -98,6 +98,16 @@ void DarkModeFilterHelper::ApplyToImageIfNeeded(GraphicsContext* context,
if (!context->IsDarkModeEnabled())
return;
+ // Gradient generated images should not be classified by SkPixmap
+ if (image->IsGradientGeneratedImage()) {
+ return;
+ }
+
+ // SVGImageForContainer invert the content automatically and do not need to
+ // use the image filter on the result.
+ if (image->IsSVGImageForContainer())
+ return;
+
SkIRect rounded_src = src.roundOut();
SkIRect rounded_dst = dst.roundOut();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
index f4bbe6efae0..601d1da24f5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
@@ -26,10 +26,10 @@ TEST(DarkModeFilterTest, ApplyDarkModeToColorsAndFlags) {
SK_ColorBLACK, DarkModeFilter::ElementRole::kBackground));
EXPECT_EQ(SK_ColorWHITE,
- filter.InvertColorIfNeeded(SK_ColorWHITE,
+ filter.InvertColorIfNeeded(SK_ColorBLACK,
DarkModeFilter::ElementRole::kSVG));
EXPECT_EQ(SK_ColorBLACK,
- filter.InvertColorIfNeeded(SK_ColorBLACK,
+ filter.InvertColorIfNeeded(SK_ColorWHITE,
DarkModeFilter::ElementRole::kSVG));
cc::PaintFlags flags;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_cache.h b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_cache.h
index ca86634d350..0c52221ab50 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_cache.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_cache.h
@@ -18,6 +18,8 @@ namespace blink {
class PLATFORM_EXPORT DarkModeImageCache {
public:
DarkModeImageCache() = default;
+ DarkModeImageCache(const DarkModeImageCache&) = delete;
+ DarkModeImageCache& operator=(const DarkModeImageCache&) = delete;
~DarkModeImageCache() = default;
bool Exists(const SkIRect& src) {
@@ -64,8 +66,6 @@ class PLATFORM_EXPORT DarkModeImageCache {
};
std::unordered_map<DarkModeKey, sk_sp<SkColorFilter>, DarkModeKeyHash> cache_;
-
- DISALLOW_COPY_AND_ASSIGN(DarkModeImageCache);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
index 45bcc7ef4dc..e311783ec83 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
@@ -240,9 +240,9 @@ DarkModeResult DarkModeImageClassifier::ClassifyWithFeatures(
// The neural network expects these features to be in a specific order
// within float array. Do not change the order here without also changing
// the neural network code!
- float feature_list[]{features.is_colorful, features.color_buckets_ratio,
- features.transparency_ratio,
- features.background_ratio};
+ float feature_list[]{
+ features.is_colorful ? 1.0f : 0.0f, features.color_buckets_ratio,
+ features.transparency_ratio, features.background_ratio};
darkmode_tfnative_model::Inference(feature_list, &nn_out, &nn_temp);
result = nn_out > 0 ? DarkModeResult::kApplyFilter
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_lab_color_space.h b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_lab_color_space.h
index 4b571cb872a..999c3e5b58a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_lab_color_space.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_lab_color_space.h
@@ -54,17 +54,17 @@ class DarkModeSRGBColorSpace {
SkV3 ToLinear(const SkV3& v) const {
auto EOTF = [](float u) {
return u < 0.04045f
- ? Clamp(u / 12.92f, .0f, 1.0f)
- : Clamp(std::pow((u + 0.055f) / 1.055f, 2.4f), .0f, 1.0f);
+ ? Clamp(u / 12.92f, 0.0f, 1.0f)
+ : Clamp(std::pow((u + 0.055f) / 1.055f, 2.4f), 0.0f, 1.0f);
};
return {EOTF(v.x), EOTF(v.y), EOTF(v.z)};
}
SkV3 FromLinear(const SkV3& v) const {
auto OETF = [](float u) {
- return (u < 0.0031308f
- ? Clamp(12.92 * u, .0, 1.0)
- : Clamp(1.055 * std::pow(u, 1.0 / 2.4) - 0.055, .0, 1.0));
+ return (u < 0.0031308f ? Clamp(12.92f * u, 0.0f, 1.0f)
+ : Clamp(1.055f * std::pow(u, 1.0f / 2.4f) - 0.055f,
+ 0.0f, 1.0f));
};
return {OETF(v.x), OETF(v.y), OETF(v.z)};
}
@@ -145,7 +145,7 @@ class DarkModeLABColorSpace {
// https://en.wikipedia.org/wiki/CIELAB_color_space#Forward_transformation.
SkV3 ToXYZ(const SkV3& lab) const {
auto invf = [](float x) {
- return x > kSigma ? pow(x, 3) : 3 * kSigma2 * (x - 4.0f / 29.0f);
+ return x > kSigma ? pow(x, 3.0f) : 3.0f * kSigma2 * (x - 4.0f / 29.0f);
};
SkV3 v = {Clamp(lab.x, 0.0f, 100.0f), Clamp(lab.y, -128.0f, 128.0f),
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings_builder.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings_builder.cc
index 5e58d300e35..3ee59213759 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings_builder.cc
@@ -4,6 +4,9 @@
#include "third_party/blink/renderer/platform/graphics/dark_mode_settings_builder.h"
+#include <string>
+#include <unordered_map>
+
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -12,8 +15,6 @@
#include "third_party/blink/public/common/forcedark/forcedark_switches.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_settings.h"
-#include <string>
-
namespace blink {
namespace {
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 c44b7531c32..e5ed5a8e58e 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
@@ -197,8 +197,8 @@ bool DecodingImageGenerator::GetPixels(const SkImageInfo& dst_info,
ScopedSegmentReaderDataLocker lock_data(data_.get());
decoded = frame_generator_->DecodeAndScale(
- data_.get(), all_data_received_, frame_index, decode_info, memory,
- adjusted_row_bytes, alpha_option, client_id);
+ data_.get(), all_data_received_, static_cast<wtf_size_t>(frame_index),
+ decode_info, memory, adjusted_row_bytes, alpha_option, client_id);
}
if (decoded && needs_color_xform) {
@@ -263,7 +263,7 @@ bool DecodingImageGenerator::GetYUVAPlanes(const SkYUVAPixmaps& pixmaps,
"Decode LazyPixelRef", "LazyPixelRef", lazy_pixel_ref);
SkISize plane_sizes[3];
- size_t plane_row_bytes[3];
+ wtf_size_t plane_row_bytes[3];
void* plane_addrs[3];
// Verify sizes and extract DecodeToYUV parameters
@@ -274,7 +274,7 @@ bool DecodingImageGenerator::GetYUVAPlanes(const SkYUVAPixmaps& pixmaps,
if (plane.colorType() != pixmaps.plane(0).colorType())
return false;
plane_sizes[i] = plane.dimensions();
- plane_row_bytes[i] = plane.rowBytes();
+ plane_row_bytes[i] = base::checked_cast<wtf_size_t>(plane.rowBytes());
plane_addrs[i] = plane.writable_addr();
}
if (!pixmaps.plane(3).dimensions().isEmpty()) {
@@ -283,8 +283,8 @@ bool DecodingImageGenerator::GetYUVAPlanes(const SkYUVAPixmaps& pixmaps,
ScopedSegmentReaderDataLocker lock_data(data_.get());
return frame_generator_->DecodeToYUV(
- data_.get(), frame_index, pixmaps.plane(0).colorType(), plane_sizes,
- plane_addrs, plane_row_bytes);
+ data_.get(), static_cast<wtf_size_t>(frame_index),
+ pixmaps.plane(0).colorType(), plane_sizes, plane_addrs, plane_row_bytes);
}
SkISize DecodingImageGenerator::GetSupportedDecodeSize(
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 134e30bbef3..2950c0fdd9e 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,7 +26,6 @@
#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/public/platform/web_vector.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
@@ -66,6 +65,8 @@ class PLATFORM_EXPORT DecodingImageGenerator final
bool can_yuv_decode,
const cc::ImageHeaderMetadata& image_metadata);
+ DecodingImageGenerator(const DecodingImageGenerator&) = delete;
+ DecodingImageGenerator& operator=(const DecodingImageGenerator&) = delete;
~DecodingImageGenerator() override;
// PaintImageGenerator implementation.
@@ -111,8 +112,6 @@ class PLATFORM_EXPORT DecodingImageGenerator final
// useful for deciding which kind of decoding can be used (i.e. hardware
// acceleration or normal).
const cc::ImageHeaderMetadata image_metadata_;
-
- 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 df1e1fc4756..cfcb01c1f74 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,7 +28,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -124,14 +123,13 @@ struct DeferredFrameData {
public:
DeferredFrameData()
: orientation_(ImageOrientationEnum::kDefault), is_received_(false) {}
+ DeferredFrameData(const DeferredFrameData&) = delete;
+ DeferredFrameData& operator=(const DeferredFrameData&) = delete;
ImageOrientation orientation_;
IntSize density_corrected_size_;
base::TimeDelta duration_;
bool is_received_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeferredFrameData);
};
std::unique_ptr<DeferredImageDecoder> DeferredImageDecoder::Create(
@@ -203,7 +201,7 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator() {
info = info.makeColorType(kRGBA_F16_SkColorType);
WebVector<FrameMetadata> frames(frame_data_.size());
- for (size_t i = 0; i < frame_data_.size(); ++i) {
+ for (wtf_size_t i = 0; i < frame_data_.size(); ++i) {
frames[i].complete = frame_data_[i].is_received_;
frames[i].duration = FrameDurationAtIndex(i);
}
@@ -254,6 +252,15 @@ scoped_refptr<SharedBuffer> DeferredImageDecoder::Data() {
return parkable_image_ ? parkable_image_->Data() : nullptr;
}
+bool DeferredImageDecoder::HasData() const {
+ return parkable_image_ != nullptr;
+}
+
+size_t DeferredImageDecoder::DataSize() const {
+ DCHECK(parkable_image_);
+ return parkable_image_->size();
+}
+
void DeferredImageDecoder::SetData(scoped_refptr<SharedBuffer> data,
bool all_data_received) {
SetDataInternal(std::move(data), all_data_received, true);
@@ -297,13 +304,13 @@ IntSize DeferredImageDecoder::Size() const {
return metadata_decoder_ ? metadata_decoder_->Size() : size_;
}
-IntSize DeferredImageDecoder::FrameSizeAtIndex(size_t index) const {
+IntSize DeferredImageDecoder::FrameSizeAtIndex(wtf_size_t index) const {
// FIXME: LocalFrame size is assumed to be uniform. This might not be true for
// future supported codecs.
return metadata_decoder_ ? metadata_decoder_->FrameSizeAtIndex(index) : size_;
}
-size_t DeferredImageDecoder::FrameCount() {
+wtf_size_t DeferredImageDecoder::FrameCount() {
return metadata_decoder_ ? metadata_decoder_->FrameCount()
: frame_data_.size();
}
@@ -327,7 +334,7 @@ SkAlphaType DeferredImageDecoder::AlphaType() const {
return alpha_type;
}
-bool DeferredImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool DeferredImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
if (metadata_decoder_)
return metadata_decoder_->FrameIsReceivedAtIndex(index);
if (index < frame_data_.size())
@@ -335,7 +342,8 @@ bool DeferredImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
return false;
}
-base::TimeDelta DeferredImageDecoder::FrameDurationAtIndex(size_t index) const {
+base::TimeDelta DeferredImageDecoder::FrameDurationAtIndex(
+ wtf_size_t index) const {
base::TimeDelta duration;
if (metadata_decoder_)
duration = metadata_decoder_->FrameDurationAtIndex(index);
@@ -352,7 +360,8 @@ base::TimeDelta DeferredImageDecoder::FrameDurationAtIndex(size_t index) const {
return duration;
}
-ImageOrientation DeferredImageDecoder::OrientationAtIndex(size_t index) const {
+ImageOrientation DeferredImageDecoder::OrientationAtIndex(
+ wtf_size_t index) const {
if (metadata_decoder_)
return metadata_decoder_->Orientation();
if (index < frame_data_.size())
@@ -360,7 +369,8 @@ ImageOrientation DeferredImageDecoder::OrientationAtIndex(size_t index) const {
return ImageOrientationEnum::kDefault;
}
-IntSize DeferredImageDecoder::DensityCorrectedSizeAtIndex(size_t index) const {
+IntSize DeferredImageDecoder::DensityCorrectedSizeAtIndex(
+ wtf_size_t index) const {
if (metadata_decoder_)
return metadata_decoder_->DensityCorrectedSize();
if (index < frame_data_.size())
@@ -368,7 +378,6 @@ IntSize DeferredImageDecoder::DensityCorrectedSizeAtIndex(size_t index) const {
return Size();
}
-
size_t DeferredImageDecoder::ByteSize() const {
return parkable_image_ ? parkable_image_->size() : 0u;
}
@@ -415,7 +424,7 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() {
ActivateLazyDecoding();
- const size_t previous_size = frame_data_.size();
+ const wtf_size_t previous_size = frame_data_.size();
frame_data_.resize(metadata_decoder_->FrameCount());
// The decoder may be invalidated during a FrameCount(). Simply bail if so.
@@ -430,10 +439,11 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() {
return;
}
- for (size_t i = previous_size; i < frame_data_.size(); ++i) {
+ for (wtf_size_t i = previous_size; i < frame_data_.size(); ++i) {
frame_data_[i].duration_ = metadata_decoder_->FrameDurationAtIndex(i);
frame_data_[i].orientation_ = metadata_decoder_->Orientation();
- frame_data_[i].density_corrected_size_ = metadata_decoder_->DensityCorrectedSize();
+ frame_data_[i].density_corrected_size_ =
+ metadata_decoder_->DensityCorrectedSize();
}
// Update the is_received_ state of incomplete frames.
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 455b3bd206e..93e116308e4 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
@@ -28,7 +28,7 @@
#include <memory>
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/graphics/rw_buffer.h"
@@ -59,6 +59,8 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
static std::unique_ptr<DeferredImageDecoder> CreateForTesting(
std::unique_ptr<ImageDecoder>);
+ DeferredImageDecoder(const DeferredImageDecoder&) = delete;
+ DeferredImageDecoder& operator=(const DeferredImageDecoder&) = delete;
~DeferredImageDecoder();
String FilenameExtension() const;
@@ -66,19 +68,21 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
sk_sp<PaintImageGenerator> CreateGenerator();
scoped_refptr<SharedBuffer> Data();
+ bool HasData() const;
+ size_t DataSize() const;
void SetData(scoped_refptr<SharedBuffer> data, bool all_data_received);
bool IsSizeAvailable();
bool HasEmbeddedColorProfile() const;
IntSize Size() const;
- IntSize FrameSizeAtIndex(size_t index) const;
- size_t FrameCount();
+ IntSize FrameSizeAtIndex(wtf_size_t index) const;
+ wtf_size_t FrameCount();
bool ImageIsHighBitDepth() const { return image_is_high_bit_depth_; }
int RepetitionCount() const;
- bool FrameIsReceivedAtIndex(size_t index) const;
- base::TimeDelta FrameDurationAtIndex(size_t index) const;
- ImageOrientation OrientationAtIndex(size_t index) const;
- IntSize DensityCorrectedSizeAtIndex(size_t index) const;
+ bool FrameIsReceivedAtIndex(wtf_size_t index) const;
+ base::TimeDelta FrameDurationAtIndex(wtf_size_t index) const;
+ ImageOrientation OrientationAtIndex(wtf_size_t index) const;
+ IntSize DensityCorrectedSizeAtIndex(wtf_size_t index) const;
bool HotSpot(IntPoint&) const;
SkAlphaType AlphaType() const;
@@ -134,10 +138,8 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
Vector<DeferredFrameData> frame_data_;
// The number of received/complete frames in |frame_data_|. Note: This is also
// the index of the first unreceived/incomplete frame in |frame_data_|.
- size_t received_frame_count_ = 0;
+ wtf_size_t received_frame_count_ = 0;
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 2fe74115acb..f0526b411d5 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
@@ -105,11 +105,11 @@ class DeferredImageDecoderTest : public testing::Test,
void DecodeRequested() override { ++decode_request_count_; }
- size_t FrameCount() override { return frame_count_; }
+ wtf_size_t FrameCount() override { return frame_count_; }
int RepetitionCount() const override { return repetition_count_; }
- ImageFrame::Status GetStatus(size_t index) override { return status_; }
+ ImageFrame::Status GetStatus(wtf_size_t index) override { return status_; }
base::TimeDelta FrameDuration() const override { return frame_duration_; }
@@ -149,7 +149,7 @@ class DeferredImageDecoderTest : public testing::Test,
std::unique_ptr<cc::PaintCanvas> canvas_;
int decode_request_count_;
scoped_refptr<SharedBuffer> data_;
- size_t frame_count_;
+ wtf_size_t frame_count_;
int repetition_count_;
ImageFrame::Status status_;
base::TimeDelta frame_duration_;
@@ -392,7 +392,7 @@ TEST_F(DeferredImageDecoderTest, frameOpacity) {
size_t row_bytes = pix_info.minRowBytes();
size_t size = pix_info.computeByteSize(row_bytes);
- Vector<char> storage(size);
+ Vector<char> storage(base::checked_cast<wtf_size_t>(size));
SkPixmap pixmap(pix_info, storage.data(), row_bytes);
// Before decoding, the frame is not known to be opaque.
@@ -430,12 +430,12 @@ TEST_F(DeferredImageDecoderTest, data) {
class MultiFrameDeferredImageDecoderTest : public DeferredImageDecoderTest {
public:
- ImageFrame::Status GetStatus(size_t index) override {
+ ImageFrame::Status GetStatus(wtf_size_t index) override {
return index > last_complete_frame_ ? ImageFrame::Status::kFramePartial
: ImageFrame::Status::kFrameComplete;
}
- size_t last_complete_frame_ = 0u;
+ wtf_size_t last_complete_frame_ = 0u;
};
TEST_F(MultiFrameDeferredImageDecoderTest, PaintImage) {
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 9377d2a2fe8..84a3275c918 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
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DRAW_LOOPER_BUILDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DRAW_LOOPER_BUILDER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -55,6 +54,11 @@ class PLATFORM_EXPORT DrawLooperBuilder final {
enum ShadowAlphaMode { kShadowRespectsAlpha, kShadowIgnoresAlpha };
DrawLooperBuilder();
+ // Implementing the copy constructor properly would require writing code to
+ // copy the underlying SkLayerDrawLooper::Builder.
+ DrawLooperBuilder(const DrawLooperBuilder&) = delete;
+ DrawLooperBuilder& operator=(const DrawLooperBuilder&) = delete;
+
~DrawLooperBuilder();
// Creates the SkDrawLooper and passes ownership to the caller. The builder
@@ -70,10 +74,6 @@ 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_blend.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc
index 7617899b694..17c4d85ee57 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_blend.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
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 6c95c4453fa..47c8295f135 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
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h
index d1d8e477967..84064478590 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h
@@ -49,6 +49,25 @@ struct ComponentTransferFunction {
ComponentTransferType type;
+ bool operator==(const ComponentTransferFunction& o) const {
+ if (type != o.type)
+ return false;
+ switch (type) {
+ case FECOMPONENTTRANSFER_TYPE_IDENTITY:
+ return true;
+ case FECOMPONENTTRANSFER_TYPE_LINEAR:
+ return (slope == o.slope && intercept == o.intercept);
+ case FECOMPONENTTRANSFER_TYPE_GAMMA:
+ return (amplitude == o.amplitude && exponent == o.exponent &&
+ offset == o.offset);
+ case FECOMPONENTTRANSFER_TYPE_TABLE:
+ case FECOMPONENTTRANSFER_TYPE_DISCRETE:
+ return (table_values == o.table_values);
+ case FECOMPONENTTRANSFER_TYPE_UNKNOWN:
+ return false;
+ }
+ }
+
float slope;
float intercept;
float amplitude;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc
index 06a86980085..73623e86021 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_composite.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
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 c818046d49a..1bbac21cac6 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
@@ -27,6 +27,7 @@
#include <memory>
#include "base/numerics/checked_math.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc
index c6dd7c60369..f058dbb1c24 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc
index fe9def4b214..9ff64fc1a81 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc
index 5cfc29897e1..020c02eb0a1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_flood.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
#include "third_party/skia/include/core/SkColorFilter.h"
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 4bb3722f695..c524495f11e 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
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_lighting.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_lighting.cc
index 24547130803..f87bbcf99e3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_lighting.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_lighting.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_lighting.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/distant_light_source.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/graphics/filters/point_light_source.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc
index 7d6a7fa2d9b..248f4a31fff 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc
@@ -24,6 +24,7 @@
#include <memory>
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc
index f850571bef1..3f6143fd06b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_morphology.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc
index 2d971ce4420..e2a9a77f64b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_offset.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
index a1672ced7e8..46f443ad117 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_turbulence.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
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 0c87f02e2e4..3334929231d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
@@ -21,7 +21,6 @@
#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"
@@ -43,6 +42,8 @@ class PLATFORM_EXPORT Filter final : public GarbageCollected<Filter> {
const FloatRect& filter_region,
float scale,
UnitScaling);
+ Filter(const Filter&) = delete;
+ Filter& operator=(const Filter&) = delete;
void Trace(Visitor*) const;
@@ -71,8 +72,6 @@ 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.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc
index 1146d35ce04..86b2f32d5c6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/skia/include/core/SkColorFilter.h"
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 c2959ae634d..3b8294adf9a 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,7 +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/abseil-cpp/absl/types/optional.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"
@@ -50,6 +50,8 @@ enum FilterEffectType {
class PLATFORM_EXPORT FilterEffect : public GarbageCollected<FilterEffect> {
public:
+ FilterEffect(const FilterEffect&) = delete;
+ FilterEffect& operator=(const FilterEffect&) = delete;
virtual ~FilterEffect();
virtual void Trace(Visitor*) const;
@@ -163,8 +165,6 @@ class PLATFORM_EXPORT FilterEffect : public GarbageCollected<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 7bed4021570..730a534ef7d 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,7 +24,6 @@
#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"
@@ -39,6 +38,8 @@ class PLATFORM_EXPORT LightSource : public RefCounted<LightSource> {
public:
LightSource(LightType type) : type_(type) {}
+ LightSource(const LightSource&) = delete;
+ LightSource& operator=(const LightSource&) = delete;
virtual ~LightSource();
@@ -54,8 +55,6 @@ 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/paint_filter_builder.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.cc
index 1bea3065ec2..8e5a9a5a026 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.cc
@@ -142,8 +142,9 @@ sk_sp<PaintFilter> BuildBoxReflectFilter(const BoxReflection& reflection,
SkBlendMode::kSrcIn,
sk_make_sp<OffsetPaintFilter>(
mask_record_bounds.x(), mask_record_bounds.y(),
- sk_make_sp<ImagePaintFilter>(std::move(image), image_rect,
- image_rect, kHigh_SkFilterQuality)),
+ sk_make_sp<ImagePaintFilter>(
+ std::move(image), image_rect, image_rect,
+ cc::PaintFlags::FilterQuality::kHigh)),
input, &crop_rect);
} else {
// If the buffer is excessively big, give up and make an
@@ -159,7 +160,7 @@ sk_sp<PaintFilter> BuildBoxReflectFilter(const BoxReflection& reflection,
masked_input = input;
}
sk_sp<PaintFilter> flip_image_filter = sk_make_sp<MatrixPaintFilter>(
- reflection.ReflectionMatrix(), kLow_SkFilterQuality,
+ reflection.ReflectionMatrix(), cc::PaintFlags::FilterQuality::kLow,
std::move(masked_input));
return sk_make_sp<XfermodePaintFilter>(
SkBlendMode::kSrcOver, std::move(flip_image_filter), std::move(input));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc
index eb5033227ae..2e0b5568355 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc
@@ -38,29 +38,27 @@
namespace blink {
-void GeneratedImage::DrawPattern(
- GraphicsContext& dest_context,
- const FloatRect& src_rect,
- const FloatSize& scale,
- const FloatPoint& phase,
- SkBlendMode composite_op,
- const FloatRect& dest_rect,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum respect_orientation) {
- FloatRect tile_rect = src_rect;
- tile_rect.Expand(repeat_spacing);
+void GeneratedImage::DrawPattern(GraphicsContext& dest_context,
+ const cc::PaintFlags& base_flags,
+ const FloatRect& dest_rect,
+ const ImageTilingInfo& tiling_info,
+ const ImageDrawOptions& draw_options) {
+ FloatRect tile_rect(tiling_info.image_rect);
+ tile_rect.Expand(tiling_info.spacing);
- SkMatrix pattern_matrix = SkMatrix::Translate(phase.X(), phase.Y());
- pattern_matrix.preScale(scale.Width(), scale.Height());
+ SkMatrix pattern_matrix =
+ SkMatrix::Translate(tiling_info.phase.X(), tiling_info.phase.Y());
+ pattern_matrix.preScale(tiling_info.scale.Width(),
+ tiling_info.scale.Height());
pattern_matrix.preTranslate(tile_rect.X(), tile_rect.Y());
sk_sp<PaintShader> tile_shader =
- CreateShader(tile_rect, &pattern_matrix, src_rect, respect_orientation);
+ CreateShader(tile_rect, &pattern_matrix, tiling_info.image_rect,
+ draw_options.respect_image_orientation);
- PaintFlags fill_flags = dest_context.FillFlags();
+ PaintFlags fill_flags(base_flags);
fill_flags.setShader(std::move(tile_shader));
fill_flags.setColor(SK_ColorBLACK);
- fill_flags.setBlendMode(composite_op);
dest_context.DrawRect(dest_rect, fill_flags);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/generated_image.h
index 75c4009be58..7691166a2ec 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/generated_image.h
@@ -38,10 +38,10 @@ class PLATFORM_EXPORT GeneratedImage : public Image {
bool HasIntrinsicSize() const override { return false; }
- IntSize Size() const override { return RoundedIntSize(size_); }
- FloatSize SizeAsFloat(RespectImageOrientationEnum) const override {
- return size_;
+ IntSize SizeWithConfig(SizeConfig) const override {
+ return RoundedIntSize(size_);
}
+ FloatSize SizeWithConfigAsFloat(SizeConfig) const override { return size_; }
// Assume that generated content has no decoded data we need to worry about
void DestroyDecodedData() override {}
@@ -50,13 +50,10 @@ class PLATFORM_EXPORT GeneratedImage : public Image {
protected:
void DrawPattern(GraphicsContext&,
- const FloatRect&,
- const FloatSize&,
- const FloatPoint&,
- SkBlendMode,
- const FloatRect&,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum) final;
+ const cc::PaintFlags&,
+ const FloatRect& dest_rect,
+ const ImageTilingInfo&,
+ const ImageDrawOptions& draw_options) final;
virtual sk_sp<cc::PaintShader> CreateShader(const FloatRect& tile_rect,
const SkMatrix* pattern_matrix,
const FloatRect& src_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
index d97c59775bc..65a72b047f3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
@@ -5,51 +5,71 @@
#include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"
#include "base/check.h"
-#include "gpu/command_buffer/client/webgpu_interface.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
+// static
+scoped_refptr<DawnControlClientHolder> DawnControlClientHolder::Create(
+ std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ auto dawn_control_client_holder =
+ base::MakeRefCounted<DawnControlClientHolder>(std::move(context_provider),
+ std::move(task_runner));
+ dawn_control_client_holder->context_provider_->ContextProvider()
+ ->SetLostContextCallback(WTF::BindRepeating(
+ &DawnControlClientHolder::Destroy, dawn_control_client_holder));
+ return dawn_control_client_holder;
+}
+
DawnControlClientHolder::DawnControlClientHolder(
std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: context_provider_(std::make_unique<WebGraphicsContext3DProviderWrapper>(
std::move(context_provider))),
- interface_(GetContextProvider()->WebGPUInterface()),
- procs_(interface_->GetProcs()),
- recyclable_resource_cache_(interface_, task_runner) {}
+ task_runner_(task_runner),
+ api_channel_(context_provider_->ContextProvider()
+ ->WebGPUInterface()
+ ->GetAPIChannel()),
+ procs_(api_channel_->GetProcs()),
+ recyclable_resource_cache_(GetContextProviderWeakPtr(), task_runner) {}
-void DawnControlClientHolder::SetLostContextCallback() {
- GetContextProvider()->SetLostContextCallback(WTF::BindRepeating(
- &DawnControlClientHolder::SetContextLost, base::WrapRefCounted(this)));
-}
+DawnControlClientHolder::~DawnControlClientHolder() = default;
void DawnControlClientHolder::Destroy() {
- SetContextLost();
- interface_->DisconnectContextAndDestroyServer();
+ api_channel_->Disconnect();
+
+ // Destroy the WebGPU context.
+ // This ensures that GPU resources are eagerly reclaimed.
+ // Because we have disconnected the wire client, any JavaScript which uses
+ // WebGPU will do nothing.
+ if (context_provider_) {
+ // If the context provider is destroyed during a real lost context event, it
+ // causes the CommandBufferProxy that the context provider owns, which is
+ // what issued the lost context event in the first place, to be destroyed
+ // before the event is done being handled. This causes a crash when an
+ // outstanding AutoLock goes out of scope. To avoid this, we create a no-op
+ // task to hold a reference to the context provider until this function is
+ // done executing, and drop it after.
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce([](std::unique_ptr<WebGraphicsContext3DProviderWrapper>
+ context_provider) {},
+ std::move(context_provider_)));
+ }
}
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
DawnControlClientHolder::GetContextProviderWeakPtr() const {
+ if (!context_provider_) {
+ return nullptr;
+ }
return context_provider_->GetWeakPtr();
}
-WebGraphicsContext3DProvider* DawnControlClientHolder::GetContextProvider()
- const {
- return context_provider_->ContextProvider();
-}
-
-gpu::webgpu::WebGPUInterface* DawnControlClientHolder::GetInterface() const {
- DCHECK(interface_);
- return interface_;
-}
-
-void DawnControlClientHolder::SetContextLost() {
- lost_ = true;
-}
-
bool DawnControlClientHolder::IsContextLost() const {
- return lost_;
+ return !context_provider_;
}
std::unique_ptr<RecyclableCanvasResource>
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
index 45107df89b5..fd58ce91182 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
@@ -8,41 +8,46 @@
#include <dawn/dawn_proc_table.h>
#include <dawn/webgpu.h>
+#include "gpu/command_buffer/client/webgpu_interface.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-namespace gpu {
-namespace webgpu {
+namespace base {
-class WebGPUInterface;
+class SingleThreadTaskRunner;
-} // namespace webgpu
-} // namespace gpu
+} // namespace base
namespace blink {
-// This class holds the WebGPUInterface and a |destroyed_| flag.
-// DawnControlClientHolder::Destroy() should be called to destroy the backing
-// WebGPUInterface.
+// This class holds the WebGraphicsContext3DProviderWrapper and a strong
+// reference to the WebGPU APIChannel.
+// DawnControlClientHolder::Destroy() should be called to destroy the
+// context which will free all command buffer and GPU resources. As long
+// as the reference to the APIChannel is held, calling WebGPU procs is
+// valid.
class PLATFORM_EXPORT DawnControlClientHolder
: public RefCounted<DawnControlClientHolder> {
public:
+ static scoped_refptr<DawnControlClientHolder> Create(
+ std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
DawnControlClientHolder(
std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
void Destroy();
+ // Returns a weak pointer to |context_provider_|. If the pointer is valid and
+ // non-null, the WebGPU context has not been destroyed, and it is safe to use
+ // the WebGPU interface.
base::WeakPtr<WebGraphicsContext3DProviderWrapper> GetContextProviderWeakPtr()
const;
- WebGraphicsContext3DProvider* GetContextProvider() const;
- gpu::webgpu::WebGPUInterface* GetInterface() const;
const DawnProcTable& GetProcs() const { return procs_; }
- void SetContextLost();
bool IsContextLost() const;
- void SetLostContextCallback();
std::unique_ptr<RecyclableCanvasResource> GetOrCreateCanvasResource(
const IntSize& size,
const CanvasResourceParams& params,
@@ -50,12 +55,12 @@ class PLATFORM_EXPORT DawnControlClientHolder
private:
friend class RefCounted<DawnControlClientHolder>;
- ~DawnControlClientHolder() = default;
+ ~DawnControlClientHolder();
std::unique_ptr<WebGraphicsContext3DProviderWrapper> context_provider_;
- gpu::webgpu::WebGPUInterface* interface_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_refptr<gpu::webgpu::APIChannel> api_channel_;
DawnProcTable procs_;
- bool lost_ = false;
WebGPURecyclableResourceCache recyclable_resource_cache_;
};
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 f7b4de1a88e..27e3b27d941 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
@@ -118,7 +118,7 @@ scoped_refptr<DrawingBuffer> DrawingBuffer::Create(
PreserveDrawingBuffer preserve,
WebGLVersion webgl_version,
ChromiumImageUsage chromium_image_usage,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasColorParams& color_params,
gl::GpuPreference gpu_preference) {
if (g_should_fail_drawing_buffer_creation_for_testing) {
@@ -193,7 +193,7 @@ DrawingBuffer::DrawingBuffer(
bool want_depth,
bool want_stencil,
ChromiumImageUsage chromium_image_usage,
- SkFilterQuality filter_quality,
+ cc::PaintFlags::FilterQuality filter_quality,
const CanvasColorParams& color_params,
gl::GpuPreference gpu_preference)
: client_(client),
@@ -290,11 +290,14 @@ void DrawingBuffer::SetIsInHiddenPage(bool hidden) {
gl_->Flush();
}
-void DrawingBuffer::SetFilterQuality(SkFilterQuality filter_quality) {
+void DrawingBuffer::SetFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality) {
if (filter_quality_ != filter_quality) {
filter_quality_ = filter_quality;
- if (layer_)
- layer_->SetNearestNeighbor(filter_quality == kNone_SkFilterQuality);
+ if (layer_) {
+ layer_->SetNearestNeighbor(filter_quality ==
+ cc::PaintFlags::FilterQuality::kNone);
+ }
}
}
@@ -316,7 +319,8 @@ DrawingBuffer::RegisteredBitmap DrawingBuffer::CreateOrRecycleBitmap(
return registered.bitmap->size() !=
static_cast<gfx::Size>(size_);
});
- recycled_bitmaps_.Shrink(it - recycled_bitmaps_.begin());
+ recycled_bitmaps_.Shrink(
+ static_cast<wtf_size_t>(it - recycled_bitmaps_.begin()));
if (!recycled_bitmaps_.IsEmpty()) {
RegisteredBitmap recycled = std::move(recycled_bitmaps_.back());
@@ -729,7 +733,8 @@ scoped_refptr<CanvasResource> DrawingBuffer::ExportLowLatencyCanvasResource(
return ExternalCanvasResource::Create(
canvas_resource_buffer->mailbox, viz::ReleaseCallback(), gpu::SyncToken(),
canvas_resource_buffer->size, texture_target_, resource_params,
- context_provider_->GetWeakPtr(), resource_provider, kLow_SkFilterQuality,
+ context_provider_->GetWeakPtr(), resource_provider,
+ cc::PaintFlags::FilterQuality::kLow,
/*is_origin_top_left=*/opengl_flip_y_extension_,
/*is_overlay_candidate=*/true);
}
@@ -768,7 +773,7 @@ scoped_refptr<CanvasResource> DrawingBuffer::ExportCanvasResource() {
out_resource.mailbox_holder.sync_token, IntSize(out_resource.size),
out_resource.mailbox_holder.texture_target, resource_params,
context_provider_->GetWeakPtr(), /*resource_provider=*/nullptr,
- kLow_SkFilterQuality,
+ cc::PaintFlags::FilterQuality::kLow,
/*is_origin_top_left=*/opengl_flip_y_extension_,
out_resource.is_overlay_candidate);
}
@@ -942,7 +947,8 @@ bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
gl_->FramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
}
if (!ResizeFramebufferInternal(size)) {
- DLOG(ERROR) << "Initialization failed to allocate backbuffer.";
+ DLOG(ERROR) << "Initialization failed to allocate backbuffer of size "
+ << size.Width() << " x " << size.Height() << ".";
return false;
}
@@ -1097,7 +1103,8 @@ cc::Layer* DrawingBuffer::CcLayer() {
DCHECK(!(premultiplied_alpha_ && premultiplied_alpha_false_texture_));
layer_->SetPremultipliedAlpha(premultiplied_alpha_ ||
premultiplied_alpha_false_texture_);
- layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality);
+ layer_->SetNearestNeighbor(filter_quality_ ==
+ cc::PaintFlags::FilterQuality::kNone);
if (opengl_flip_y_extension_)
layer_->SetFlipped(false);
@@ -1532,7 +1539,7 @@ sk_sp<SkData> DrawingBuffer::PaintRenderingResultsToDataArray(
// Readback in native GL byte order (RGBA).
SkColorType color_type = kRGBA_8888_SkColorType;
base::CheckedNumeric<size_t> row_bytes = 4;
- if (RuntimeEnabledFeatures::CanvasColorManagementEnabled() &&
+ if (RuntimeEnabledFeatures::CanvasColorManagementV2Enabled() &&
back_color_buffer_->format == viz::RGBA_F16) {
color_type = kRGBA_F16_SkColorType;
row_bytes *= 2;
@@ -1596,7 +1603,7 @@ void DrawingBuffer::ReadBackFramebuffer(base::span<uint8_t> pixels,
expected_data_size *= Size().Width();
expected_data_size *= Size().Height();
- if (RuntimeEnabledFeatures::CanvasColorManagementEnabled() &&
+ if (RuntimeEnabledFeatures::CanvasColorManagementV2Enabled() &&
color_type == kRGBA_F16_SkColorType) {
data_type = (webgl_version_ > kWebGL1) ? GL_HALF_FLOAT : GL_HALF_FLOAT_OES;
expected_data_size *= 2;
@@ -1735,15 +1742,22 @@ scoped_refptr<DrawingBuffer::ColorBuffer> DrawingBuffer::CreateColorBuffer(
// the non-GMB CreateSharedImage with gpu::SHARED_IMAGE_USAGE_SCANOUT in
// order to allocate the GMB service-side and avoid a synchronous
// round-trip to the browser process here.
+ gfx::BufferUsage buffer_usage = gfx::BufferUsage::SCANOUT;
+ uint32_t additional_usage_flags = gpu::SHARED_IMAGE_USAGE_SCANOUT;
+ if (low_latency_enabled()) {
+ buffer_usage = gfx::BufferUsage::SCANOUT_FRONT_RENDERING;
+ additional_usage_flags = gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
+ }
+
gpu_memory_buffer = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
- gfx::Size(size), buffer_format, gfx::BufferUsage::SCANOUT,
- gpu::kNullSurfaceHandle, nullptr);
+ gfx::Size(size), buffer_format, buffer_usage, gpu::kNullSurfaceHandle,
+ nullptr);
if (gpu_memory_buffer) {
back_buffer_mailbox = sii->CreateSharedImage(
gpu_memory_buffer.get(), gpu_memory_buffer_manager,
storage_color_space_, origin, kPremul_SkAlphaType,
- usage | gpu::SHARED_IMAGE_USAGE_SCANOUT);
+ usage | additional_usage_flags);
}
}
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 530d2a55c73..eebcf5f8940 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
@@ -34,7 +34,6 @@
#include <memory>
#include "base/containers/span.h"
-#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"
@@ -139,10 +138,12 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
PreserveDrawingBuffer,
WebGLVersion,
ChromiumImageUsage,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasColorParams&,
gl::GpuPreference);
+ DrawingBuffer(const DrawingBuffer&) = delete;
+ DrawingBuffer& operator=(const DrawingBuffer&) = delete;
~DrawingBuffer() override;
// Destruction will be completed after all mailboxes are released.
@@ -210,8 +211,10 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
GLbitfield GetBuffersToAutoClear() const;
void SetIsInHiddenPage(bool);
- void SetFilterQuality(SkFilterQuality);
- SkFilterQuality FilterQuality() const { return filter_quality_; }
+ void SetFilterQuality(cc::PaintFlags::FilterQuality);
+ cc::PaintFlags::FilterQuality FilterQuality() const {
+ return filter_quality_;
+ }
// Whether the target for draw operations has format GL_RGBA, but is
// emulating format GL_RGB. When the target's storage is first
@@ -284,6 +287,12 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
bool UsingSwapChain() const { return using_swap_chain_; }
+ // Keep track of low latency buffer status.
+ bool low_latency_enabled() const { return low_latency_enabled_; }
+ void set_low_latency_enabled(bool low_latency_enabled) {
+ low_latency_enabled_ = low_latency_enabled;
+ }
+
// This class helps implement correct semantics for BlitFramebuffer
// when the DrawingBuffer is using a CHROMIUM image for its backing
// store and RGB emulation is in use (basically, macOS only).
@@ -321,7 +330,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
bool wants_depth,
bool wants_stencil,
ChromiumImageUsage,
- SkFilterQuality,
+ cc::PaintFlags::FilterQuality,
const CanvasColorParams&,
gl::GpuPreference gpu_preference);
@@ -386,6 +395,8 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
GLuint texture_id,
std::unique_ptr<gfx::GpuMemoryBuffer>,
gpu::Mailbox mailbox);
+ ColorBuffer(const ColorBuffer&) = delete;
+ ColorBuffer& operator=(const ColorBuffer&) = delete;
~ColorBuffer();
// The thread on which the ColorBuffer is created and the DrawingBuffer is
@@ -420,9 +431,6 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
// The sync token for when this buffer was received back from the
// compositor.
gpu::SyncToken receive_sync_token;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ColorBuffer);
};
template <typename CopyFunction>
@@ -572,6 +580,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
const bool premultiplied_alpha_;
Platform::GraphicsInfo graphics_info_;
const bool using_swap_chain_;
+ bool low_latency_enabled_ = false;
bool has_implicit_stencil_buffer_ = false;
// The texture target (2D or RECTANGLE) for our allocations.
@@ -646,7 +655,8 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
bool destruction_in_progress_ = false;
bool is_hidden_ = false;
bool has_eqaa_support = false;
- SkFilterQuality filter_quality_ = kLow_SkFilterQuality;
+ cc::PaintFlags::FilterQuality filter_quality_ =
+ cc::PaintFlags::FilterQuality::kLow;
scoped_refptr<cc::TextureLayer> layer_;
@@ -668,8 +678,6 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
gl::GpuPreference current_active_gpu_;
base::WeakPtrFactory<DrawingBuffer> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DrawingBuffer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
index 7d562aae914..96d94db7465 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
@@ -32,8 +32,8 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
@@ -687,7 +687,7 @@ TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported) {
IntSize(10, 10), premultiplied_alpha, want_alpha_channel,
want_depth_buffer, want_stencil_buffer, want_antialiasing, preserve,
DrawingBuffer::kWebGL1, DrawingBuffer::kAllowChromiumImage,
- kLow_SkFilterQuality, CanvasColorParams(),
+ cc::PaintFlags::FilterQuality::kLow, CanvasColorParams(),
gl::GpuPreference::kHighPerformance);
// When we request a depth or a stencil buffer, we will get both.
@@ -759,7 +759,7 @@ TEST_F(DrawingBufferTest,
nullptr, graphics_info, false /* using_swap_chain */, nullptr,
too_big_size, false, false, false, false, false, DrawingBuffer::kDiscard,
DrawingBuffer::kWebGL1, DrawingBuffer::kAllowChromiumImage,
- kLow_SkFilterQuality, CanvasColorParams(),
+ cc::PaintFlags::FilterQuality::kLow, CanvasColorParams(),
gl::GpuPreference::kHighPerformance);
EXPECT_EQ(too_big_drawing_buffer, nullptr);
drawing_buffer_->BeginDestruction();
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 4095cf1c4de..ae9ce514c96 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
@@ -483,7 +483,7 @@ class DrawingBufferForTests : public DrawingBuffer {
false /* wantDepth */,
false /* wantStencil */,
DrawingBuffer::kAllowChromiumImage /* ChromiumImageUsage */,
- kLow_SkFilterQuality,
+ cc::PaintFlags::FilterQuality::kLow,
CanvasColorParams(),
gl::GpuPreference::kHighPerformance),
live_(nullptr) {}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc
index 388559e7630..63646f3c89c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc
@@ -19,8 +19,8 @@ namespace {
void SplitStringHelper(const String& str, HashSet<String>& set) {
Vector<String> substrings;
str.Split(' ', substrings);
- for (size_t i = 0; i < substrings.size(); ++i)
- set.insert(substrings[i]);
+ for (const auto& substring : substrings)
+ set.insert(substring);
}
} // anonymous namespace
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 6a214156502..96ee29bbf7b 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -30,6 +29,8 @@ class PLATFORM_EXPORT Extensions3DUtil final {
// Creates a new Extensions3DUtil. If the passed GLES2Interface has been
// spontaneously lost, returns null.
static std::unique_ptr<Extensions3DUtil> Create(gpu::gles2::GLES2Interface*);
+ Extensions3DUtil(const Extensions3DUtil&) = delete;
+ Extensions3DUtil& operator=(const Extensions3DUtil&) = delete;
~Extensions3DUtil();
bool IsValid() { return is_valid_; }
@@ -49,8 +50,6 @@ 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/image_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
index 7b8f2b08249..722c88e5704 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
@@ -39,7 +39,7 @@ scoped_refptr<StaticBitmapImage> MakeAccelerated(
auto paint_image = source->PaintImageForCurrentFrame();
auto provider = CanvasResourceProvider::CreateSharedImageProvider(
- source->Size(), kLow_SkFilterQuality,
+ source->Size(), cc::PaintFlags::FilterQuality::kLow,
CanvasResourceParams(paint_image.GetSkImageInfo()),
CanvasResourceProvider::ShouldInitialize::kNo, context_provider_wrapper,
RasterMode::kGPU, source->IsOriginTopLeft(),
@@ -60,7 +60,8 @@ ImageLayerBridge::ImageLayerBridge(OpacityMode opacity_mode)
layer_ = cc::TextureLayer::CreateForMailbox(this);
layer_->SetIsDrawable(true);
layer_->SetHitTestable(true);
- layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality);
+ layer_->SetNearestNeighbor(filter_quality_ ==
+ cc::PaintFlags::FilterQuality::kNone);
if (opacity_mode_ == kOpaque) {
layer_->SetContentsOpaque(true);
layer_->SetBlendBackgroundColor(false);
@@ -155,9 +156,19 @@ bool ImageLayerBridge::PrepareTransferableResource(
const gfx::Size size(image_for_compositor->width(),
image_for_compositor->height());
- uint32_t filter =
- filter_quality_ == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
+ uint32_t filter = filter_quality_ == cc::PaintFlags::FilterQuality::kNone
+ ? GL_NEAREST
+ : GL_LINEAR;
auto mailbox_holder = image_for_compositor->GetMailboxHolder();
+
+ if (mailbox_holder.mailbox.IsZero()) {
+ // This can happen, for example, if an ImageBitmap is produced from a
+ // WebGL-rendered OffscreenCanvas and then the WebGL context is forcibly
+ // lost. This seems to be the only reliable point where this can be
+ // detected.
+ return false;
+ }
+
auto* sii = image_for_compositor->ContextProvider()->SharedImageInterface();
bool is_overlay_candidate = sii->UsageForMailbox(mailbox_holder.mailbox) &
gpu::SHARED_IMAGE_USAGE_SCANOUT;
@@ -240,7 +251,8 @@ ImageLayerBridge::RegisteredBitmap ImageLayerBridge::CreateOrRecycleBitmap(
return (registered.bitmap->size().GetArea() * src_bytes_per_pixel !=
size.GetArea() * target_bytes_per_pixel);
});
- recycled_bitmaps_.Shrink(it - recycled_bitmaps_.begin());
+ recycled_bitmaps_.Shrink(
+ static_cast<wtf_size_t>(it - recycled_bitmaps_.begin()));
if (!recycled_bitmaps_.IsEmpty()) {
RegisteredBitmap registered = std::move(recycled_bitmaps_.back());
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 3e70fe452f2..3707806a6c5 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_IMAGE_LAYER_BRIDGE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_IMAGE_LAYER_BRIDGE_H_
-#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"
@@ -32,6 +31,8 @@ class PLATFORM_EXPORT ImageLayerBridge
public cc::TextureLayerClient {
public:
ImageLayerBridge(OpacityMode);
+ ImageLayerBridge(const ImageLayerBridge&) = delete;
+ ImageLayerBridge& operator=(const ImageLayerBridge&) = delete;
~ImageLayerBridge() override;
void SetImage(scoped_refptr<StaticBitmapImage>);
@@ -47,7 +48,7 @@ class PLATFORM_EXPORT ImageLayerBridge
cc::Layer* CcLayer() const;
- void SetFilterQuality(SkFilterQuality filter_quality) {
+ void SetFilterQuality(cc::PaintFlags::FilterQuality filter_quality) {
filter_quality_ = filter_quality;
}
void SetUV(const FloatPoint& left_top, const FloatPoint& right_bottom);
@@ -86,7 +87,8 @@ class PLATFORM_EXPORT ImageLayerBridge
scoped_refptr<StaticBitmapImage> image_;
scoped_refptr<cc::TextureLayer> layer_;
- SkFilterQuality filter_quality_ = kLow_SkFilterQuality;
+ cc::PaintFlags::FilterQuality filter_quality_ =
+ cc::PaintFlags::FilterQuality::kLow;
// SharedMemory bitmaps that can be recycled.
Vector<RegisteredBitmap> recycled_bitmaps_;
@@ -94,8 +96,6 @@ 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 7b553cf5b14..dade52f2323 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -41,6 +40,8 @@ class SharedContextRateLimiter final {
public:
explicit SharedContextRateLimiter(unsigned max_pending_ticks);
+ SharedContextRateLimiter(const SharedContextRateLimiter&) = delete;
+ SharedContextRateLimiter& operator=(const SharedContextRateLimiter&) = delete;
void Tick();
void Reset();
@@ -50,8 +51,6 @@ 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_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
index 3c0219a525c..36371bc1f27 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
@@ -193,7 +193,7 @@ TEST_F(BadSharedGpuContextTest, AccelerateImageBufferSurfaceCreationFails) {
IntSize size(10, 10);
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::CreateSharedImageProvider(
- size, kLow_SkFilterQuality, CanvasResourceParams(),
+ size, cc::PaintFlags::FilterQuality::kLow, CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kNo,
SharedGpuContext::ContextProviderWrapper(), RasterMode::kGPU,
true /*is_origin_top_left*/, 0u /*shared_image_usage_flags*/);
@@ -220,7 +220,7 @@ TEST_F(SharedGpuContextTestViz, AccelerateImageBufferSurfaceAutoRecovery) {
IntSize size(10, 10);
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::CreateSharedImageProvider(
- size, kLow_SkFilterQuality, CanvasResourceParams(),
+ size, cc::PaintFlags::FilterQuality::kLow, CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kNo,
SharedGpuContext::ContextProviderWrapper(), RasterMode::kGPU,
true /*is_origin_top_left*/, 0u /*shared_image_usage_flags*/);
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 8355cb96cb4..16babfa9bcf 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
@@ -3747,7 +3747,7 @@ void WebGLImageConversion::ImageExtractor::ExtractImage(
!skia_image->colorSpace()->isSRGB();
if ((!skia_image || ignore_color_space || need_unpremultiplied ||
need_color_conversion) &&
- image_->Data()) {
+ image_->HasData()) {
// Attempt to get raw unpremultiplied image data.
const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
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 5d54e6182ec..6fff48c657a 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,7 +5,6 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
@@ -136,6 +135,8 @@ class PLATFORM_EXPORT WebGLImageConversion final {
ImageHtmlDomSource,
bool premultiply_alpha,
bool ignore_color_space);
+ ImageExtractor(const ImageExtractor&) = delete;
+ ImageExtractor& operator=(const ImageExtractor&) = delete;
const void* ImagePixelData() {
return image_pixel_locker_ ? image_pixel_locker_->Pixels() : nullptr;
@@ -162,8 +163,6 @@ 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/webgpu_image_bitmap_handler.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc
index 3fe8fd7b071..67747bab468 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc
@@ -75,7 +75,9 @@ bool CopyBytesFromImageBitmapForWebGPU(
scoped_refptr<StaticBitmapImage> image,
base::span<uint8_t> dst,
const IntRect& rect,
- const WGPUTextureFormat destination_format) {
+ const WGPUTextureFormat destination_format,
+ bool premultipliedAlpha,
+ bool flipY) {
DCHECK(image);
DCHECK_GT(dst.size(), static_cast<size_t>(0));
DCHECK(image->width() - rect.X() >= rect.Width());
@@ -95,18 +97,30 @@ bool CopyBytesFromImageBitmapForWebGPU(
PaintImage paint_image = image->PaintImageForCurrentFrame();
// Read pixel request dst info.
- // Keep premulalpha config and color space from imageBitmap and using dest
- // texture color type. This can help do conversions in ReadPixels.
+ // TODO(crbug.com/1217153): Convert to user-provided color space.
SkImageInfo info = SkImageInfo::Make(
rect.Width(), rect.Height(), sk_color_type,
- image->IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
+ premultipliedAlpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
paint_image.GetSkImageInfo().refColorSpace());
- bool read_pixels_successful = paint_image.readPixels(
- info, dst.data(), wgpu_info.wgpu_bytes_per_row, rect.X(), rect.Y());
-
- if (!read_pixels_successful) {
- return false;
+ if (!flipY) {
+ return paint_image.readPixels(
+ info, dst.data(), wgpu_info.wgpu_bytes_per_row, rect.X(), rect.Y());
+ } else {
+ // Do flipY for the bottom left image.
+ std::vector<uint8_t> flipped;
+ flipped.resize(wgpu_info.wgpu_bytes_per_row * rect.Height());
+ if (!paint_image.readPixels(info, flipped.data(),
+ wgpu_info.wgpu_bytes_per_row, rect.X(),
+ rect.Y())) {
+ return false;
+ }
+ for (int i = 0; i < rect.Height(); ++i) {
+ memcpy(
+ dst.data() + (rect.Height() - 1 - i) * wgpu_info.wgpu_bytes_per_row,
+ flipped.data() + i * wgpu_info.wgpu_bytes_per_row,
+ wgpu_info.wgpu_bytes_per_row);
+ }
}
return true;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h
index d90a8a5acfc..c26a31926f8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h
@@ -29,7 +29,9 @@ bool PLATFORM_EXPORT
CopyBytesFromImageBitmapForWebGPU(scoped_refptr<StaticBitmapImage> image,
base::span<uint8_t> dst,
const IntRect& rect,
- const WGPUTextureFormat destination_format);
+ const WGPUTextureFormat destination_format,
+ bool premultipliedAlpha,
+ bool flipY);
uint64_t PLATFORM_EXPORT
DawnTextureFormatBytesPerPixel(const WGPUTextureFormat color_type);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc
index 26f10b4d151..5a1fec4ff67 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc
@@ -59,12 +59,11 @@ bool GPUUploadingPathSupported() {
class MockWebGPUInterface : public gpu::webgpu::WebGPUInterfaceStub {
public:
MockWebGPUInterface() {
- procs_ = {};
-
// WebGPU functions the tests will call. No-op them since we don't have a
// real WebGPU device.
- procs_.deviceReference = [](WGPUDevice) {};
- procs_.deviceRelease = [](WGPUDevice) {};
+ procs()->deviceReference = [](WGPUDevice) {};
+ procs()->deviceRelease = [](WGPUDevice) {};
+ procs()->textureRelease = [](WGPUTexture) {};
}
MOCK_METHOD(gpu::webgpu::ReservedTexture,
@@ -81,11 +80,6 @@ class MockWebGPUInterface : public gpu::webgpu::WebGPUInterfaceStub {
MOCK_METHOD(void,
DissociateMailbox,
(GLuint texture_id, GLuint texture_generation));
-
- const DawnProcTable& GetProcs() const override { return procs_; }
-
- private:
- DawnProcTable procs_;
};
// The six reference pixels are: red, green, blue, white, black.
@@ -240,7 +234,7 @@ class WebGPUImageBitmapHandlerTest : public testing::Test {
std::vector<uint8_t> results(result_length, 0);
bool success = CopyBytesFromImageBitmapForWebGPU(
image, base::span<uint8_t>(results.data(), result_length), copy_rect,
- color_type);
+ color_type, image->IsPremultiplied(), /* flipY = */ false);
ASSERT_EQ(success, true);
// Compare content and results
@@ -409,11 +403,12 @@ TEST_F(WebGPUMailboxTextureTest, VerifyAccessTexture) {
*reinterpret_cast<const volatile gpu::Mailbox*>(mailbox_bytes));
})));
+ SkImageInfo image_info = bitmap->PaintImageForCurrentFrame().GetSkImageInfo();
scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
WebGPUMailboxTexture::FromStaticBitmapImage(
- dawn_control_client_, fake_device_, WGPUTextureUsage_CopySrc, bitmap);
+ dawn_control_client_, fake_device_, WGPUTextureUsage_CopySrc, bitmap,
+ CanvasColorSpace::kSRGB, image_info.colorType());
- EXPECT_TRUE(mailbox == bitmap->GetMailboxHolder().mailbox);
EXPECT_NE(mailbox_texture->GetTexture(), nullptr);
EXPECT_EQ(mailbox_texture->GetTextureIdForTest(), 1u);
EXPECT_EQ(mailbox_texture->GetTextureGenerationForTest(), 1u);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc
index 4651c0bc4c1..ea25005b160 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc
@@ -6,6 +6,7 @@
#include "gpu/command_buffer/client/webgpu_interface.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/static_bitmap_image.h"
namespace blink {
@@ -15,16 +16,56 @@ scoped_refptr<WebGPUMailboxTexture> WebGPUMailboxTexture::FromStaticBitmapImage(
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUDevice device,
WGPUTextureUsage usage,
- scoped_refptr<StaticBitmapImage> image) {
+ scoped_refptr<StaticBitmapImage> image,
+ CanvasColorSpace color_space,
+ SkColorType color_type) {
DCHECK(image->IsTextureBacked());
- auto finished_access_callback =
- WTF::Bind(&StaticBitmapImage::UpdateSyncToken, WTF::RetainedRef(image));
- return base::AdoptRef(new WebGPUMailboxTexture(
- std::move(dawn_control_client), device, usage,
- image->GetMailboxHolder().mailbox, image->GetMailboxHolder().sync_token,
- std::move(finished_access_callback),
- /*recyclable_canvas_resource=*/nullptr));
+ // TODO(crbugs.com/1217160) Mac uses IOSurface in SharedImageBackingGLImage
+ // which can be shared to dawn directly aftter passthrough command buffer
+ // supported on mac os.
+ // We should wrap the StaticBitmapImage directly for mac when passthrough
+ // command buffer has been supported.
+
+ // If the context is lost, the resource provider would be invalid.
+ auto context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
+ if (!context_provider_wrapper ||
+ context_provider_wrapper->ContextProvider()->IsContextLost())
+ return nullptr;
+
+ // Keep the same config as source image.
+ const CanvasResourceParams params(
+ color_space, color_type,
+ image->IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
+
+ // Get a recyclable resource for producing WebGPU-compatible shared images.
+ std::unique_ptr<RecyclableCanvasResource> recyclable_canvas_resource =
+ dawn_control_client->GetOrCreateCanvasResource(image->Size(), params,
+ image->IsOriginTopLeft());
+
+ // Fallback to unstable intermediate resource copy path.
+ if (!recyclable_canvas_resource) {
+ auto finished_access_callback =
+ WTF::Bind(&StaticBitmapImage::UpdateSyncToken, WTF::RetainedRef(image));
+
+ return base::AdoptRef(new WebGPUMailboxTexture(
+ std::move(dawn_control_client), device, usage,
+ image->GetMailboxHolder().mailbox, image->GetMailboxHolder().sync_token,
+ std::move(finished_access_callback),
+ /*recyclable_canvas_resource=*/nullptr));
+ }
+
+ CanvasResourceProvider* resource_provider =
+ recyclable_canvas_resource->resource_provider();
+ DCHECK(resource_provider);
+
+ if (!image->CopyToResourceProvider(resource_provider)) {
+ return nullptr;
+ }
+
+ return WebGPUMailboxTexture::FromCanvasResource(
+ dawn_control_client, device, usage,
+ std::move(recyclable_canvas_resource));
}
// static
@@ -59,9 +100,14 @@ WebGPUMailboxTexture::WebGPUMailboxTexture(
device_(device),
destroy_callback_(std::move(destroy_callback)),
recyclable_canvas_resource_(std::move(recyclable_canvas_resource)) {
+ DCHECK(dawn_control_client_->GetContextProviderWeakPtr());
+
dawn_control_client_->GetProcs().deviceReference(device_);
- gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
+ gpu::webgpu::WebGPUInterface* webgpu =
+ dawn_control_client_->GetContextProviderWeakPtr()
+ ->ContextProvider()
+ ->WebGPUInterface();
// Wait on any work using the image.
webgpu->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
@@ -84,16 +130,20 @@ WebGPUMailboxTexture::WebGPUMailboxTexture(
WebGPUMailboxTexture::~WebGPUMailboxTexture() {
DCHECK_NE(wire_texture_id_, 0u);
- gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
- webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
-
- if (destroy_callback_) {
- gpu::SyncToken finished_access_token;
- webgpu->GenUnverifiedSyncTokenCHROMIUM(finished_access_token.GetData());
- std::move(destroy_callback_).Run(finished_access_token);
+ if (auto context_provider =
+ dawn_control_client_->GetContextProviderWeakPtr()) {
+ gpu::webgpu::WebGPUInterface* webgpu =
+ context_provider->ContextProvider()->WebGPUInterface();
+ webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
+
+ if (destroy_callback_) {
+ gpu::SyncToken finished_access_token;
+ webgpu->GenUnverifiedSyncTokenCHROMIUM(finished_access_token.GetData());
+ std::move(destroy_callback_).Run(finished_access_token);
+ }
+ dawn_control_client_->GetProcs().textureRelease(texture_);
+ dawn_control_client_->GetProcs().deviceRelease(device_);
}
-
- dawn_control_client_->GetProcs().deviceRelease(device_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h
index d99bde1e6ea..b42700682ad 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h
@@ -28,7 +28,9 @@ class PLATFORM_EXPORT WebGPUMailboxTexture
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUDevice device,
WGPUTextureUsage usage,
- scoped_refptr<StaticBitmapImage> image);
+ scoped_refptr<StaticBitmapImage> image,
+ CanvasColorSpace color_space,
+ SkColorType color_type);
static scoped_refptr<WebGPUMailboxTexture> FromCanvasResource(
scoped_refptr<DawnControlClientHolder> dawn_control_client,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc
index 44b69ac42aa..52695f20cf7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc
@@ -61,9 +61,9 @@ RecyclableCanvasResource::~RecyclableCanvasResource() {
}
WebGPURecyclableResourceCache::WebGPURecyclableResourceCache(
- gpu::webgpu::WebGPUInterface* webgpu_interface,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : webgpu_interface_(webgpu_interface),
+ : context_provider_(std::move(context_provider)),
task_runner_(std::move(task_runner)) {
weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
timer_func_ = WTF::BindRepeating(
@@ -98,16 +98,18 @@ void WebGPURecyclableResourceCache::OnDestroyRecyclableResource(
int resource_size = resource_provider->Size().Width() *
resource_provider->Size().Height() *
resource_provider->ColorParams().BytesPerPixel();
- total_unused_resources_in_bytes_ += resource_size;
+ if (context_provider_) {
+ total_unused_resources_in_bytes_ += resource_size;
- // WaitSyncToken on the canvas resource.
- gpu::SyncToken finished_access_token;
- webgpu_interface_->GenUnverifiedSyncTokenCHROMIUM(
- finished_access_token.GetData());
- resource_provider->OnDestroyRecyclableCanvasResource(finished_access_token);
+ // WaitSyncToken on the canvas resource.
+ gpu::SyncToken finished_access_token;
+ auto* webgpu = context_provider_->ContextProvider()->WebGPUInterface();
+ webgpu->GenUnverifiedSyncTokenCHROMIUM(finished_access_token.GetData());
+ resource_provider->OnDestroyRecyclableCanvasResource(finished_access_token);
- unused_providers_.push_front(
- Resource(std::move(resource_provider), current_timer_id_, resource_size));
+ unused_providers_.push_front(Resource(std::move(resource_provider),
+ current_timer_id_, resource_size));
+ }
if (last_seen_max_unused_resources_in_bytes_ <
total_unused_resources_in_bytes_) {
@@ -166,9 +168,6 @@ void WebGPURecyclableResourceCache::ReleaseStaleResources() {
int stale_resource_count = 0;
for (auto it = unused_providers_.rbegin(); it != unused_providers_.rend();
++it) {
- auto timer_id_ = it->timer_id_;
- int delta;
- delta = current_timer_id_ - timer_id_;
if ((current_timer_id_ - it->timer_id_) < kTimerIdDeltaForDeletion) {
// These are the resources which are recycled and stay in the cache for
// less than kCleanUpDelayInSeconds. They are not to be deleted this time.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
index e6f210f3433..2bdfbc2d76b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
@@ -53,7 +53,7 @@ class PLATFORM_EXPORT RecyclableCanvasResource {
class PLATFORM_EXPORT WebGPURecyclableResourceCache {
public:
explicit WebGPURecyclableResourceCache(
- gpu::webgpu::WebGPUInterface* webgpu_interface,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~WebGPURecyclableResourceCache() = default;
@@ -67,7 +67,6 @@ class PLATFORM_EXPORT WebGPURecyclableResourceCache {
void OnDestroyRecyclableResource(
std::unique_ptr<CanvasResourceProvider> resource_provider);
- void ConfigureForTesting(gpu::webgpu::WebGPUInterface* webgpu_interface);
wtf_size_t CleanUpResourcesAndReturnSizeForTesting();
int GetWaitCountBeforeDeletionForTesting() {
@@ -131,7 +130,7 @@ class PLATFORM_EXPORT WebGPURecyclableResourceCache {
uint64_t last_seen_max_unused_resources_in_bytes_ = 0;
wtf_size_t last_seen_max_unused_resources_ = 0;
- gpu::webgpu::WebGPUInterface* webgpu_interface_;
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::RepeatingCallback<void()> timer_func_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc
index 9ef7fdf42b4..fbdb2e9a63c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc
@@ -36,12 +36,10 @@ void WebGPURecyclableResourceCacheTest::SetUp() {
test_context_provider_ = viz::TestContextProvider::Create();
InitializeSharedGpuContext(test_context_provider_.get(),
&image_decode_cache_);
- auto* webgpu_interface = SharedGpuContext::ContextProviderWrapper()
- ->ContextProvider()
- ->WebGPUInterface();
recyclable_resource_cache_ = std::make_unique<WebGPURecyclableResourceCache>(
- webgpu_interface, base::ThreadTaskRunnerHandle::Get());
+ SharedGpuContext::ContextProviderWrapper(),
+ base::ThreadTaskRunnerHandle::Get());
}
void WebGPURecyclableResourceCacheTest::TearDown() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index 85f167c7470..b1ddcc5e565 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -60,15 +60,24 @@ WebGPUSwapBufferProvider::~WebGPUSwapBufferProvider() {
device_ = nullptr;
}
+const gfx::Size& WebGPUSwapBufferProvider::Size() const {
+ if (current_swap_buffer_)
+ return current_swap_buffer_->size;
+
+ static constexpr gfx::Size kEmpty;
+ return kEmpty;
+}
+
cc::Layer* WebGPUSwapBufferProvider::CcLayer() {
DCHECK(!neutered_);
return layer_.get();
}
void WebGPUSwapBufferProvider::SetFilterQuality(
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
if (layer_) {
- layer_->SetNearestNeighbor(filter_quality == kNone_SkFilterQuality);
+ layer_->SetNearestNeighbor(filter_quality ==
+ cc::PaintFlags::FilterQuality::kNone);
}
}
@@ -85,9 +94,12 @@ void WebGPUSwapBufferProvider::Neuter() {
if (current_swap_buffer_) {
// Ensure we wait for previous WebGPU commands before destroying the shared
// image.
- gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
- webgpu->GenUnverifiedSyncTokenCHROMIUM(
- current_swap_buffer_->access_finished_token.GetData());
+ if (auto context_provider = GetContextProviderWeakPtr()) {
+ gpu::webgpu::WebGPUInterface* webgpu =
+ context_provider->ContextProvider()->WebGPUInterface();
+ webgpu->GenUnverifiedSyncTokenCHROMIUM(
+ current_swap_buffer_->access_finished_token.GetData());
+ }
current_swap_buffer_ = nullptr;
}
@@ -95,28 +107,66 @@ void WebGPUSwapBufferProvider::Neuter() {
neutered_ = true;
}
+std::unique_ptr<WebGPUSwapBufferProvider::SwapBuffer>
+WebGPUSwapBufferProvider::NewOrRecycledSwapBuffer(
+ gpu::SharedImageInterface* sii,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
+ const gfx::Size& size) {
+ // Recycled SwapBuffers must be the same size.
+ if (!unused_swap_buffers_.IsEmpty() &&
+ unused_swap_buffers_.back()->size != size) {
+ unused_swap_buffers_.clear();
+ }
+
+ if (unused_swap_buffers_.IsEmpty()) {
+ gpu::Mailbox mailbox = sii->CreateSharedImage(
+ format_, static_cast<gfx::Size>(size), gfx::ColorSpace::CreateSRGB(),
+ kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
+ gpu::SHARED_IMAGE_USAGE_WEBGPU |
+ gpu::SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE |
+ gpu::SHARED_IMAGE_USAGE_DISPLAY,
+ gpu::kNullSurfaceHandle);
+ gpu::SyncToken creation_token = sii->GenUnverifiedSyncToken();
+
+ unused_swap_buffers_.push_back(std::make_unique<SwapBuffer>(
+ std::move(context_provider), mailbox, creation_token, size));
+ DCHECK_EQ(unused_swap_buffers_.back()->size, size);
+ }
+
+ std::unique_ptr<SwapBuffer> swap_buffer =
+ std::move(unused_swap_buffers_.back());
+ unused_swap_buffers_.pop_back();
+
+ return swap_buffer;
+}
+
+void WebGPUSwapBufferProvider::RecycleSwapBuffer(
+ std::unique_ptr<SwapBuffer> swap_buffer) {
+ // We don't want to keep an arbitrary large number of swap buffers.
+ if (unused_swap_buffers_.size() >
+ static_cast<unsigned int>(kMaxRecycledSwapBuffers))
+ return;
+
+ unused_swap_buffers_.push_back(std::move(swap_buffer));
+}
+
WGPUTexture WebGPUSwapBufferProvider::GetNewTexture(const IntSize& size) {
DCHECK(!current_swap_buffer_);
+ auto context_provider = GetContextProviderWeakPtr();
+ if (!context_provider) {
+ return nullptr;
+ }
- gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
- gpu::SharedImageInterface* sii =
- dawn_control_client_->GetContextProvider()->SharedImageInterface();
+ gpu::webgpu::WebGPUInterface* webgpu =
+ context_provider->ContextProvider()->WebGPUInterface();
// Create a new swap buffer.
- // TODO(cwallez@chromium.org): have some recycling mechanism.
- gpu::Mailbox mailbox = sii->CreateSharedImage(
- format_, static_cast<gfx::Size>(size), gfx::ColorSpace::CreateSRGB(),
- kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
- gpu::SHARED_IMAGE_USAGE_WEBGPU |
- gpu::SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE |
- gpu::SHARED_IMAGE_USAGE_DISPLAY,
- gpu::kNullSurfaceHandle);
- gpu::SyncToken creation_token = sii->GenUnverifiedSyncToken();
-
- current_swap_buffer_ = base::AdoptRef(new SwapBuffer(
- this, mailbox, creation_token, static_cast<gfx::Size>(size)));
-
- // Ensure the shared image is allocated service-side before working with it
+ current_swap_buffer_ = NewOrRecycledSwapBuffer(
+ context_provider->ContextProvider()->SharedImageInterface(),
+ context_provider, gfx::Size(size));
+
+ // Ensure the shared image is allocated and not in use service-side before
+ // working with it
webgpu->WaitSyncTokenCHROMIUM(
current_swap_buffer_->access_finished_token.GetConstData());
@@ -148,7 +198,7 @@ bool WebGPUSwapBufferProvider::PrepareTransferableResource(
viz::TransferableResource* out_resource,
viz::ReleaseCallback* out_release_callback) {
DCHECK(!neutered_);
- if (!current_swap_buffer_ || neutered_) {
+ if (!current_swap_buffer_ || neutered_ || !GetContextProviderWeakPtr()) {
return false;
}
@@ -158,7 +208,8 @@ bool WebGPUSwapBufferProvider::PrepareTransferableResource(
// Make Dawn relinquish access to the texture so it can be used by the
// compositor. This will call wgpu::Texture::Destroy so that further accesses
// to the texture are errors.
- gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
+ gpu::webgpu::WebGPUInterface* webgpu =
+ GetContextProviderWeakPtr()->ContextProvider()->WebGPUInterface();
DCHECK_NE(wire_texture_id_, 0u);
webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
@@ -166,33 +217,33 @@ bool WebGPUSwapBufferProvider::PrepareTransferableResource(
webgpu->GenUnverifiedSyncTokenCHROMIUM(
current_swap_buffer_->access_finished_token.GetData());
- // On macOS, shared images are backed by IOSurfaces that can only be used
- // with OpenGL via the rectangle texture target. Every other shared image
- // implementation is implemented on OpenGL via some form of eglSurface and
- // eglBindTexImage (on ANGLE or system drivers) so they use the 2D texture
- // target.
- const uint32_t texture_target =
+ // On macOS, shared images are backed by IOSurfaces that can only be used with
+ // OpenGL via the rectangle texture target and are overlay candidates. Every
+ // other shared image implementation is implemented on OpenGL via some form of
+ // eglSurface and eglBindTexImage (on ANGLE or system drivers) so they use the
+ // 2D texture target and cannot always be overlay candidates.
#if defined(OS_MAC)
- GL_TEXTURE_RECTANGLE_ARB
+ const uint32_t texture_target = GL_TEXTURE_RECTANGLE_ARB;
+ const bool is_overlay_candidate = true;
#else
- GL_TEXTURE_2D
+ const uint32_t texture_target = GL_TEXTURE_2D;
+ const bool is_overlay_candidate = false;
#endif
- ;
// Populate the output resource
*out_resource = viz::TransferableResource::MakeGL(
current_swap_buffer_->mailbox, GL_LINEAR, texture_target,
current_swap_buffer_->access_finished_token, current_swap_buffer_->size,
- false);
+ is_overlay_candidate);
out_resource->color_space = gfx::ColorSpace::CreateSRGB();
out_resource->format = format_;
// This holds a ref on the SwapBuffers that will keep it alive until the
// mailbox is released (and while the release callback is running).
- *out_release_callback = WTF::Bind(
- &WebGPUSwapBufferProvider::MailboxReleased,
- scoped_refptr<WebGPUSwapBufferProvider>(this), current_swap_buffer_);
+ *out_release_callback =
+ WTF::Bind(&WebGPUSwapBufferProvider::MailboxReleased,
+ scoped_refptr<WebGPUSwapBufferProvider>(this),
+ std::move(current_swap_buffer_));
- current_swap_buffer_ = nullptr;
wire_texture_id_ = 0;
wire_texture_generation_ = 0;
@@ -200,29 +251,37 @@ bool WebGPUSwapBufferProvider::PrepareTransferableResource(
}
void WebGPUSwapBufferProvider::MailboxReleased(
- scoped_refptr<SwapBuffer> swap_buffer,
+ std::unique_ptr<SwapBuffer> swap_buffer,
const gpu::SyncToken& sync_token,
bool lost_resource) {
// Update the SyncToken to ensure that we will wait for it even if we
// immediately destroy this buffer.
swap_buffer->access_finished_token = sync_token;
+
+ if (!lost_resource)
+ RecycleSwapBuffer(std::move(swap_buffer));
}
WebGPUSwapBufferProvider::SwapBuffer::SwapBuffer(
- WebGPUSwapBufferProvider* swap_buffers,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
gpu::Mailbox mailbox,
gpu::SyncToken creation_token,
gfx::Size size)
: size(size),
mailbox(mailbox),
- swap_buffers(swap_buffers),
+ context_provider(context_provider),
access_finished_token(creation_token) {}
WebGPUSwapBufferProvider::SwapBuffer::~SwapBuffer() {
- gpu::SharedImageInterface* sii =
- swap_buffers->dawn_control_client_->GetContextProvider()
- ->SharedImageInterface();
- sii->DestroySharedImage(access_finished_token, mailbox);
+ if (context_provider) {
+ gpu::SharedImageInterface* sii =
+ context_provider->ContextProvider()->SharedImageInterface();
+ sii->DestroySharedImage(access_finished_token, mailbox);
+ }
}
+gpu::Mailbox WebGPUSwapBufferProvider::GetCurrentMailboxForTesting() const {
+ DCHECK(current_swap_buffer_);
+ return current_swap_buffer_->mailbox;
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
index 936f55bd961..b9f0147086b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
@@ -40,8 +40,10 @@ class PLATFORM_EXPORT WebGPUSwapBufferProvider
WGPUTextureFormat format);
~WebGPUSwapBufferProvider() override;
+ viz::ResourceFormat Format() const { return format_; }
+ const gfx::Size& Size() const;
cc::Layer* CcLayer();
- void SetFilterQuality(SkFilterQuality);
+ void SetFilterQuality(cc::PaintFlags::FilterQuality);
void Neuter();
WGPUTexture GetNewTexture(const IntSize& size);
@@ -54,32 +56,40 @@ class PLATFORM_EXPORT WebGPUSwapBufferProvider
viz::TransferableResource* out_resource,
viz::ReleaseCallback* out_release_callback) override;
+ gpu::Mailbox GetCurrentMailboxForTesting() const;
+
private:
// Holds resources and synchronization for one of the swapchain images.
- struct SwapBuffer : public RefCounted<SwapBuffer> {
- SwapBuffer(WebGPUSwapBufferProvider*,
- gpu::Mailbox mailbox,
- gpu::SyncToken creation_token,
- gfx::Size size);
+ struct SwapBuffer {
+ SwapBuffer(
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
+ gpu::Mailbox mailbox,
+ gpu::SyncToken creation_token,
+ gfx::Size size);
+ SwapBuffer(const SwapBuffer&) = delete;
+ SwapBuffer& operator=(const SwapBuffer&) = delete;
~SwapBuffer();
gfx::Size size;
gpu::Mailbox mailbox;
- // A reference back to the swap buffers to keep it alive while this image
- // is in flight so that the destructor can access data in the swap
- // buffers.
- scoped_refptr<WebGPUSwapBufferProvider> swap_buffers;
+ // A weak ptr to the context provider so that the destructor can
+ // destroy shared images.
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider;
// A token signaled when the previous user of the image is finished using
// it. It could be WebGPU, the compositor or the shared image creation.
gpu::SyncToken access_finished_token;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SwapBuffer);
};
- void MailboxReleased(scoped_refptr<SwapBuffer> swap_buffer,
+ std::unique_ptr<WebGPUSwapBufferProvider::SwapBuffer> NewOrRecycledSwapBuffer(
+ gpu::SharedImageInterface* sii,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
+ const gfx::Size& size);
+
+ void RecycleSwapBuffer(std::unique_ptr<SwapBuffer> swap_buffer);
+
+ void MailboxReleased(std::unique_ptr<SwapBuffer> swap_buffer,
const gpu::SyncToken& sync_token,
bool lost_resource);
@@ -91,9 +101,15 @@ class PLATFORM_EXPORT WebGPUSwapBufferProvider
WGPUTextureUsage usage_;
+ // The maximum number of in-flight swap-buffers waiting to be used for
+ // recycling.
+ static constexpr int kMaxRecycledSwapBuffers = 3;
+
+ WTF::Vector<std::unique_ptr<SwapBuffer>> unused_swap_buffers_;
+
uint32_t wire_texture_id_ = 0;
uint32_t wire_texture_generation_ = 0;
- scoped_refptr<SwapBuffer> current_swap_buffer_;
+ std::unique_ptr<SwapBuffer> current_swap_buffer_;
viz::ResourceFormat format_;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
index 3441283d043..868726df3a6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
@@ -21,12 +21,10 @@ namespace {
class MockWebGPUInterface : public gpu::webgpu::WebGPUInterfaceStub {
public:
MockWebGPUInterface() {
- procs_ = {};
-
// WebGPU functions the tests will call. No-op them since we don't have a
// real WebGPU device.
- procs_.deviceReference = [](WGPUDevice) {};
- procs_.deviceRelease = [](WGPUDevice) {};
+ procs()->deviceReference = [](WGPUDevice) {};
+ procs()->deviceRelease = [](WGPUDevice) {};
}
MOCK_METHOD1(ReserveTexture, gpu::webgpu::ReservedTexture(WGPUDevice device));
@@ -51,26 +49,28 @@ class MockWebGPUInterface : public gpu::webgpu::WebGPUInterfaceStub {
memcpy(&most_recent_waited_token, sync_token_data, sizeof(gpu::SyncToken));
}
- const DawnProcTable& GetProcs() const override { return procs_; }
-
gpu::SyncToken most_recent_generated_token;
gpu::SyncToken most_recent_waited_token;
private:
- DawnProcTable procs_;
uint64_t token_id_ = 42;
};
class FakeProviderClient : public WebGPUSwapBufferProvider::Client {
public:
- void OnTextureTransferred() override {}
+ void OnTextureTransferred() override {
+ DCHECK(texture);
+ texture = nullptr;
+ }
+
+ WGPUTexture texture;
};
class WebGPUSwapBufferProviderForTests : public WebGPUSwapBufferProvider {
public:
WebGPUSwapBufferProviderForTests(
bool* alive,
- Client* client,
+ FakeProviderClient* client,
WGPUDevice device,
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUTextureUsage usage,
@@ -80,11 +80,18 @@ class WebGPUSwapBufferProviderForTests : public WebGPUSwapBufferProvider {
device,
usage,
format),
- alive_(alive) {}
+ alive_(alive),
+ client_(client) {}
~WebGPUSwapBufferProviderForTests() override { *alive_ = false; }
+ WGPUTexture GetNewTexture(const IntSize& size) {
+ client_->texture = WebGPUSwapBufferProvider::GetNewTexture(size);
+ return client_->texture;
+ }
+
private:
bool* alive_;
+ FakeProviderClient* client_;
};
} // anonymous namespace
@@ -237,7 +244,160 @@ TEST_F(WebGPUSwapBufferProviderTest, VerifyInsertAndWaitSyncTokenCorrectly) {
gpu::SyncToken release_token;
webgpu_->GenSyncTokenCHROMIUM(release_token.GetData());
std::move(release_callback).Run(release_token, false /* lostResource */);
+
+ // Release the unused swap buffers held by the provider.
+ provider_ = nullptr;
+
EXPECT_EQ(sii_->MostRecentDestroyToken(), release_token);
}
+// Ensures swap buffers will be recycled.
+// Creates two swap buffers, destroys them, then creates them again.
+TEST_F(WebGPUSwapBufferProviderTest, ReuseSwapBuffers) {
+ const IntSize kSize(10, 10);
+
+ base::flat_set<gpu::Mailbox> shared_images = {};
+
+ viz::TransferableResource resource;
+ gpu::webgpu::ReservedTexture reservation = {
+ reinterpret_cast<WGPUTexture>(&resource), 1, 1};
+
+ // Produce swap buffers
+ viz::ReleaseCallback release_callback_1;
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+ EXPECT_TRUE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_1));
+
+ viz::ReleaseCallback release_callback_2;
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+ EXPECT_TRUE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_2));
+
+ // Destroy the swap buffers.
+ std::move(release_callback_1).Run(gpu::SyncToken(), false /* lostResource */);
+ std::move(release_callback_2).Run(gpu::SyncToken(), false /* lostResource */);
+
+ // Produce swap buffers again
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+ EXPECT_FALSE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_1));
+
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+ EXPECT_FALSE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_2));
+}
+
+// Ensures swap buffers will NOT be recycled if resized.
+// Creates two swap buffers of a size, destroys them, then creates them again
+// with a different size.
+TEST_F(WebGPUSwapBufferProviderTest, ReuseSwapBufferResize) {
+ base::flat_set<gpu::Mailbox> shared_images = {};
+
+ viz::TransferableResource resource;
+ gpu::webgpu::ReservedTexture reservation = {
+ reinterpret_cast<WGPUTexture>(&resource), 1, 1};
+
+ // Create swap buffers
+ const IntSize kSize(10, 10);
+
+ viz::ReleaseCallback release_callback_1;
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+ EXPECT_TRUE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_1));
+
+ viz::ReleaseCallback release_callback_2;
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+ EXPECT_TRUE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_2));
+
+ // Destroy swap buffers
+ std::move(release_callback_1).Run(gpu::SyncToken(), false /* lostResource */);
+ std::move(release_callback_2).Run(gpu::SyncToken(), false /* lostResource */);
+
+ // Create swap buffers again with different size.
+ const IntSize kOtherSize(20, 20);
+
+ viz::ReleaseCallback release_callback_3;
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kOtherSize));
+
+ EXPECT_TRUE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_3));
+
+ viz::ReleaseCallback release_callback_4;
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(static_cast<IntSize>(kOtherSize));
+
+ EXPECT_TRUE(
+ shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+ EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_4));
+}
+
+// Regression test for crbug.com/1236418 where calling
+// PrepareTransferableResource twice after the context is destroyed would hit a
+// DCHECK.
+TEST_F(WebGPUSwapBufferProviderTest,
+ PrepareTransferableResourceTwiceAfterDestroy) {
+ viz::TransferableResource resource;
+ gpu::webgpu::ReservedTexture reservation = {
+ reinterpret_cast<WGPUTexture>(&resource), 1, 1};
+
+ EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+ .WillOnce(Return(reservation));
+ provider_->GetNewTexture(IntSize(10, 10));
+
+ dawn_control_client_->Destroy();
+
+ viz::ReleaseCallback release_callback_1;
+ EXPECT_FALSE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_1));
+
+ viz::ReleaseCallback release_callback_2;
+ EXPECT_FALSE(provider_->PrepareTransferableResource(nullptr, &resource,
+ &release_callback_2));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
index 26f28d0cc11..d338c61d96b 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,7 +5,6 @@
#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"
@@ -60,6 +59,8 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
const IntSize&,
const gpu::Mailbox& mailbox,
GLuint texture_id);
+ ColorBuffer(const ColorBuffer&) = delete;
+ ColorBuffer& operator=(const ColorBuffer&) = delete;
~ColorBuffer();
// The thread on which the ColorBuffer is created and the DrawingBuffer is
@@ -85,9 +86,6 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
// The sync token for when this buffer was received back from the
// compositor.
gpu::SyncToken receive_sync_token;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ColorBuffer);
};
XRWebGLDrawingBuffer(DrawingBuffer*,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gradient.h b/chromium/third_party/blink/renderer/platform/graphics/gradient.h
index 5856982b129..cfa9e683d69 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient.h
@@ -29,7 +29,6 @@
#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"
@@ -89,6 +88,8 @@ class PLATFORM_EXPORT Gradient : public RefCounted<Gradient> {
ColorInterpolation = ColorInterpolation::kUnpremultiplied,
DegenerateHandling = DegenerateHandling::kAllow);
+ Gradient(const Gradient&) = delete;
+ Gradient& operator=(const Gradient&) = delete;
virtual ~Gradient();
Type GetType() const { return type_; }
@@ -140,8 +141,6 @@ class PLATFORM_EXPORT Gradient : public RefCounted<Gradient> {
mutable sk_sp<PaintShader> cached_shader_;
mutable sk_sp<SkColorFilter> color_filter_;
-
- 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 0e44fa9a12e..5ab93d0b2f0 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
@@ -35,8 +35,7 @@ void GradientGeneratedImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) {
SkRect visible_src_rect = 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 401b3aa81b8..e2b559c4645 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
@@ -45,13 +45,14 @@ class PLATFORM_EXPORT GradientGeneratedImage final : public GeneratedImage {
bool ApplyShader(PaintFlags&, const SkMatrix&) override;
+ bool IsGradientGeneratedImage() const override { return true; }
+
protected:
void Draw(cc::PaintCanvas*,
const PaintFlags&,
const FloatRect&,
const FloatRect&,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
void DrawTile(GraphicsContext&,
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 8760e2293de..a25d4aade95 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -62,6 +62,9 @@
#include "third_party/skia/include/utils/SkNullCanvas.h"
#include "ui/base/ui_base_features.h"
+// To avoid conflicts with the DrawText macro from the Windows SDK...
+#undef DrawText
+
namespace blink {
namespace {
@@ -317,7 +320,7 @@ void GraphicsContext::CompositeRecord(sk_sp<PaintRecord> record,
flags.setBlendMode(op);
SkSamplingOptions sampling(cc::PaintFlags::FilterQualityToSkSamplingOptions(
- static_cast<SkFilterQuality>(ImageInterpolationQuality())));
+ static_cast<cc::PaintFlags::FilterQuality>(ImageInterpolationQuality())));
canvas_->save();
canvas_->concat(SkMatrix::RectToRect(src, dest));
canvas_->drawImage(PaintImageBuilder::WithDefault()
@@ -329,136 +332,25 @@ void GraphicsContext::CompositeRecord(sk_sp<PaintRecord> record,
canvas_->restore();
}
-namespace {
-
-int AdjustedFocusRingOffset(int offset) {
- // For FormControlsRefresh we just use the value of outline-offset so we don't
- // need to call this method.
- DCHECK(!::features::IsFormControlsRefreshEnabled());
-
-#if defined(OS_MAC)
- return offset + 2;
-#else
- return 0;
-#endif
-}
-
-} // namespace
-
-int GraphicsContext::FocusRingOutsetExtent(int offset, int width) {
- // Unlike normal outlines (whole width is outside of the offset), focus
- // rings can be drawn with the center of the path aligned with the offset, so
- // only half of the width is outside of the offset.
- if (::features::IsFormControlsRefreshEnabled()) {
- // For FormControlsRefresh 2/3 of the width is outside of the offset.
- return offset + std::ceil(width / 3.f) * 2;
- }
-
- return AdjustedFocusRingOffset(offset) + (width + 1) / 2;
-}
-
void GraphicsContext::DrawFocusRingPath(const SkPath& path,
const Color& color,
float width,
- float border_radius) {
+ float corner_radius) {
DrawPlatformFocusRing(
path, canvas_,
DarkModeFilterHelper::ApplyToColorIfNeeded(
this, color.Rgb(), DarkModeFilter::ElementRole::kBackground),
- width, border_radius);
+ width, corner_radius);
}
-void GraphicsContext::DrawFocusRingRect(const SkRect& rect,
+void GraphicsContext::DrawFocusRingRect(const SkRRect& rrect,
const Color& color,
- float width,
- float border_radius) {
+ float width) {
DrawPlatformFocusRing(
- rect, canvas_,
+ rrect, canvas_,
DarkModeFilterHelper::ApplyToColorIfNeeded(
this, color.Rgb(), DarkModeFilter::ElementRole::kBackground),
- width, border_radius);
-}
-
-void GraphicsContext::DrawFocusRing(const Path& focus_ring_path,
- float width,
- int offset,
- const Color& color) {
- // FIXME: Implement support for offset.
- DrawFocusRingPath(focus_ring_path.GetSkPath(), color, /*width=*/width,
- /*radius=*/width);
-}
-
-void GraphicsContext::DrawFocusRingInternal(const Vector<IntRect>& rects,
- float width,
- int offset,
- float border_radius,
- const Color& color) {
- unsigned rect_count = rects.size();
- if (!rect_count)
- return;
-
- SkRegion focus_ring_region;
- if (!::features::IsFormControlsRefreshEnabled()) {
- // For FormControlsRefresh we don't need to adjust the offset.
- offset = AdjustedFocusRingOffset(offset);
- }
- for (unsigned i = 0; i < rect_count; i++) {
- SkIRect r = rects[i];
- if (r.isEmpty())
- continue;
- r.outset(offset, offset);
- focus_ring_region.op(r, SkRegion::kUnion_Op);
- }
-
- if (focus_ring_region.isEmpty())
- return;
-
- if (focus_ring_region.isRect()) {
- DrawFocusRingRect(SkRect::Make(focus_ring_region.getBounds()), color, width,
- border_radius);
- } else {
- SkPath path;
- if (focus_ring_region.getBoundaryPath(&path))
- DrawFocusRingPath(path, color, width, border_radius);
- }
-}
-
-void GraphicsContext::DrawFocusRing(const Vector<IntRect>& rects,
- float width,
- int offset,
- float border_radius,
- float min_border_width,
- const Color& color,
- mojom::blink::ColorScheme color_scheme) {
-#if defined(OS_MAC)
- const Color& inner_color = color;
-#else
- const Color& inner_color =
- color_scheme == mojom::blink::ColorScheme::kDark ? SK_ColorWHITE : color;
-#endif
- if (::features::IsFormControlsRefreshEnabled()) {
- // The focus ring is made of two borders which have a 2:1 ratio.
- const float first_border_width = (width / 3) * 2;
- const float second_border_width = width - first_border_width;
-
- // How much space the focus ring would like to take from the actual border.
- const float inside_border_width = 1;
- if (min_border_width >= inside_border_width) {
- offset -= inside_border_width;
- }
- const Color& outer_color = color_scheme == mojom::blink::ColorScheme::kDark
- ? SkColorSetRGB(0x10, 0x10, 0x10)
- : SK_ColorWHITE;
- // The outer ring is drawn first, and we overdraw to ensure no gaps or AA
- // artifacts.
- DrawFocusRingInternal(rects, first_border_width,
- offset + std::ceil(second_border_width),
- border_radius, outer_color);
- DrawFocusRingInternal(rects, first_border_width, offset, border_radius,
- inner_color);
- } else {
- DrawFocusRingInternal(rects, width, offset, border_radius, inner_color);
- }
+ width);
}
static void EnforceDotsAtEndpoints(GraphicsContext& context,
@@ -666,6 +558,17 @@ void GraphicsContext::DrawText(const Font& font,
: Font::DrawType::kGlyphsOnly);
}
+void GraphicsContext::DrawText(const Font& font,
+ const NGTextFragmentPaintInfo& text_info,
+ const FloatPoint& point,
+ const PaintFlags& flags,
+ DOMNodeId node_id) {
+ font.DrawText(canvas_, text_info, point, device_scale_factor_, node_id,
+ DarkModeFlags(this, flags, DarkModeFilter::ElementRole::kText),
+ printing_ ? Font::DrawType::kGlyphsAndClusters
+ : Font::DrawType::kGlyphsOnly);
+}
+
template <typename DrawTextFunc>
void GraphicsContext::DrawTextPasses(const DrawTextFunc& draw_text) {
TextDrawingModeFlags mode_flags = TextDrawingMode();
@@ -800,7 +703,7 @@ void GraphicsContext::DrawImage(
Image::ImageDecodingMode decode_mode,
const FloatRect& dest,
const FloatRect* src_ptr,
- bool has_filter_property,
+ bool has_disable_dark_mode_style,
SkBlendMode op,
RespectImageOrientationEnum should_respect_image_orientation) {
if (!image)
@@ -812,16 +715,17 @@ void GraphicsContext::DrawImage(
image_flags.setBlendMode(op);
image_flags.setColor(SK_ColorBLACK);
- // Do not classify the image if the element has any CSS filters.
- if (!has_filter_property) {
+ if (!has_disable_dark_mode_style) {
DarkModeFilterHelper::ApplyToImageIfNeeded(this, image, &image_flags, src,
dest);
}
-
- image->Draw(canvas_, image_flags, dest, src,
- ComputeSamplingOptions(image, dest, src),
- should_respect_image_orientation, Image::kClampImageToSourceRect,
- decode_mode);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = ComputeSamplingOptions(image, dest, src);
+ draw_options.respect_image_orientation = should_respect_image_orientation;
+ draw_options.apply_dark_mode =
+ !has_disable_dark_mode_style && IsDarkModeEnabled();
+ image->Draw(canvas_, image_flags, dest, src, draw_options,
+ Image::kClampImageToSourceRect, decode_mode);
paint_controller_.SetImagePainted();
}
@@ -830,15 +734,15 @@ void GraphicsContext::DrawImageRRect(
Image::ImageDecodingMode decode_mode,
const FloatRoundedRect& dest,
const FloatRect& src_rect,
- bool has_filter_property,
+ bool has_disable_dark_mode_style,
SkBlendMode op,
RespectImageOrientationEnum respect_orientation) {
if (!image)
return;
if (!dest.IsRounded()) {
- DrawImage(image, decode_mode, dest.Rect(), &src_rect, has_filter_property,
- op, respect_orientation);
+ DrawImage(image, decode_mode, dest.Rect(), &src_rect,
+ has_disable_dark_mode_style, op, respect_orientation);
return;
}
@@ -879,15 +783,18 @@ void GraphicsContext::DrawImageRRect(
// Clip-based fallback.
PaintCanvasAutoRestore auto_restore(canvas_, true);
canvas_->clipRRect(dest, image_flags.isAntiAlias());
- image->Draw(canvas_, image_flags, dest.Rect(), src_rect, sampling,
- respect_orientation, Image::kClampImageToSourceRect,
- decode_mode);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = sampling;
+ draw_options.respect_image_orientation = respect_orientation;
+ draw_options.apply_dark_mode = IsDarkModeEnabled();
+ image->Draw(canvas_, image_flags, dest.Rect(), src_rect, draw_options,
+ Image::kClampImageToSourceRect, decode_mode);
}
paint_controller_.SetImagePainted();
}
-SkFilterQuality GraphicsContext::ComputeFilterQuality(
+cc::PaintFlags::FilterQuality GraphicsContext::ComputeFilterQuality(
Image* image,
const FloatRect& dest,
const FloatRect& src) const {
@@ -909,23 +816,34 @@ SkFilterQuality GraphicsContext::ComputeFilterQuality(
resampling = kInterpolationLow;
}
}
- return static_cast<SkFilterQuality>(
+ return static_cast<cc::PaintFlags::FilterQuality>(
std::min(resampling, ImageInterpolationQuality()));
}
void GraphicsContext::DrawImageTiled(
Image* image,
const FloatRect& dest_rect,
- const FloatRect& src_rect,
- const FloatSize& scale_src_to_dest,
- const FloatPoint& phase,
- const FloatSize& repeat_spacing,
+ const ImageTilingInfo& tiling_info,
+ bool has_disable_dark_mode_style,
SkBlendMode op,
RespectImageOrientationEnum respect_orientation) {
if (!image)
return;
- image->DrawPattern(*this, src_rect, scale_src_to_dest, phase, op, dest_rect,
- repeat_spacing, respect_orientation);
+
+ PaintFlags image_flags = ImmutableState()->FillFlags();
+ image_flags.setBlendMode(op);
+
+ if (!has_disable_dark_mode_style) {
+ DarkModeFilterHelper::ApplyToImageIfNeeded(
+ this, image, &image_flags, tiling_info.image_rect, dest_rect);
+ }
+
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = ImageSamplingOptions();
+ draw_options.respect_image_orientation = respect_orientation;
+ draw_options.apply_dark_mode =
+ !has_disable_dark_mode_style && IsDarkModeEnabled();
+ image->DrawPattern(*this, image_flags, dest_rect, tiling_info, draw_options);
paint_controller_.SetImagePainted();
}
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 afeee01ba6a..c577637143f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -31,7 +31,6 @@
#include <memory>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/public/mojom/frame/color_scheme.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_filter.h"
@@ -68,11 +67,37 @@ class PaintController;
class Path;
struct TextRunPaintInfo;
+// Tiling parameters for the DrawImageTiled() method.
+struct ImageTilingInfo {
+ // The part of the Image (the |image| argument to the method) to tile. It's in
+ // the space of the image.
+ FloatRect image_rect;
+
+ // Scale factor from image space to destination space. Will include
+ // image-resolution information.
+ FloatSize scale{1.0f, 1.0f};
+
+ // Origin of the full image in destination space.
+ FloatPoint phase;
+
+ // Additional spacing between tiles in destination space.
+ FloatSize spacing;
+};
+
+struct ImageDrawOptions {
+ SkSamplingOptions sampling_options;
+ RespectImageOrientationEnum respect_image_orientation =
+ kRespectImageOrientation;
+ bool apply_dark_mode = false;
+};
+
class PLATFORM_EXPORT GraphicsContext {
USING_FAST_MALLOC(GraphicsContext);
public:
explicit GraphicsContext(PaintController&);
+ GraphicsContext(const GraphicsContext&) = delete;
+ GraphicsContext& operator=(const GraphicsContext&) = delete;
~GraphicsContext();
// Copy configs such as printing, dark mode, device scale factor etc. from
@@ -160,7 +185,7 @@ class PLATFORM_EXPORT GraphicsContext {
SkSamplingOptions ImageSamplingOptions() const {
return PaintFlags::FilterQualityToSkSamplingOptions(
- static_cast<SkFilterQuality>(ImageInterpolationQuality()));
+ static_cast<PaintFlags::FilterQuality>(ImageInterpolationQuality()));
}
// Specify the device scale factor which may change the way document markers
@@ -238,22 +263,20 @@ class PLATFORM_EXPORT GraphicsContext {
Image::ImageDecodingMode,
const FloatRect& dest_rect,
const FloatRect* src_rect = nullptr,
- bool has_filter_property = false,
+ bool has_disable_dark_mode_style = false,
SkBlendMode = SkBlendMode::kSrcOver,
RespectImageOrientationEnum = kRespectImageOrientation);
void DrawImageRRect(Image*,
Image::ImageDecodingMode,
const FloatRoundedRect& dest,
const FloatRect& src_rect,
- bool has_filter_property = false,
+ bool has_disable_dark_mode_style = false,
SkBlendMode = SkBlendMode::kSrcOver,
RespectImageOrientationEnum = kRespectImageOrientation);
void DrawImageTiled(Image* image,
const FloatRect& dest_rect,
- const FloatRect& src_rect,
- const FloatSize& scale_src_to_dest,
- const FloatPoint& phase,
- const FloatSize& repeat_spacing,
+ const ImageTilingInfo& tiling_info,
+ bool has_disable_dark_mode_style = false,
SkBlendMode = SkBlendMode::kSrcOver,
RespectImageOrientationEnum = kRespectImageOrientation);
@@ -311,6 +334,14 @@ class PLATFORM_EXPORT GraphicsContext {
const PaintFlags&,
DOMNodeId);
+ // TODO(layout-dev): This method is only used by NGTextPainter, see if the
+ // four parameter overload can be removed or if it can wrap this method.
+ void DrawText(const Font&,
+ const NGTextFragmentPaintInfo&,
+ const FloatPoint&,
+ const PaintFlags&,
+ DOMNodeId);
+
void DrawEmphasisMarks(const Font&,
const TextRunPaintInfo&,
const AtomicString& mark,
@@ -357,14 +388,11 @@ class PLATFORM_EXPORT GraphicsContext {
void SetDrawLooper(sk_sp<SkDrawLooper>);
- void DrawFocusRing(const Vector<IntRect>&,
- float width,
- int offset,
- float border_radius,
- float min_border_width,
- const Color&,
- mojom::blink::ColorScheme color_scheme);
- void DrawFocusRing(const Path&, float width, int offset, const Color&);
+ void DrawFocusRingPath(const SkPath&,
+ const Color&,
+ float width,
+ float corner_radius);
+ void DrawFocusRingRect(const SkRRect&, const Color&, float width);
const PaintFlags& FillFlags() const { return ImmutableState()->FillFlags(); }
// If the length of the path to be stroked is known, pass it in for correct
@@ -384,9 +412,9 @@ class PLATFORM_EXPORT GraphicsContext {
void Translate(float x, float y);
// ---------- End transformation methods -----------------
- SkFilterQuality ComputeFilterQuality(Image*,
- const FloatRect& dest,
- const FloatRect& src) const;
+ PaintFlags::FilterQuality ComputeFilterQuality(Image*,
+ const FloatRect& dest,
+ const FloatRect& src) const;
SkSamplingOptions ComputeSamplingOptions(Image* image,
const FloatRect& dest,
@@ -417,8 +445,6 @@ class PLATFORM_EXPORT GraphicsContext {
StrokeStyle);
static bool ShouldUseStrokeForTextLine(StrokeStyle);
- static int FocusRingOutsetExtent(int offset, int width);
-
void SetInDrawingRecorder(bool);
bool InDrawingRecorder() const { return in_drawing_recorder_; }
@@ -459,22 +485,6 @@ class PLATFORM_EXPORT GraphicsContext {
void SaveLayer(const SkRect* bounds, const PaintFlags*);
void RestoreLayer();
- // Helpers for drawing a focus ring (drawFocusRing)
- void DrawFocusRingPath(const SkPath&,
- const Color&,
- float width,
- float border_radius);
- void DrawFocusRingRect(const SkRect&,
- const Color&,
- float width,
- float border_radius);
-
- void DrawFocusRingInternal(const Vector<IntRect>&,
- float width,
- int offset,
- float border_radius,
- const Color&);
-
// SkCanvas wrappers.
void ClipRRect(const SkRRect&,
AntiAliasingMode = kNotAntiAliased,
@@ -542,8 +552,6 @@ class PLATFORM_EXPORT GraphicsContext {
// The current node ID, which is used for marked content in a tagged PDF.
DOMNodeId dom_node_id_ = kInvalidDOMNodeId;
-
- DISALLOW_COPY_AND_ASSIGN(GraphicsContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.cc
index 541d8cbadd5..0052bc76ff5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.cc
@@ -8,14 +8,14 @@
namespace blink {
-static inline SkFilterQuality FilterQualityForPaint(
+static inline cc::PaintFlags::FilterQuality FilterQualityForPaint(
InterpolationQuality quality) {
// The filter quality "selected" here will primarily be used when painting a
// primitive using one of the PaintFlags below. For the most part this will
// not affect things that are part of the Image class hierarchy (which use
// the unmodified m_interpolationQuality.)
- return quality != kInterpolationNone ? kLow_SkFilterQuality
- : kNone_SkFilterQuality;
+ return quality != kInterpolationNone ? cc::PaintFlags::FilterQuality::kLow
+ : cc::PaintFlags::FilterQuality::kNone;
}
GraphicsContextState::GraphicsContextState()
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 29539cc5e0b..1236ec8c251 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,7 +29,6 @@
#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/allocator.h"
@@ -47,6 +46,10 @@ class PLATFORM_EXPORT GraphicsContextStateSaver final {
context_.Save();
}
+ GraphicsContextStateSaver(const GraphicsContextStateSaver&) = delete;
+ GraphicsContextStateSaver& operator=(const GraphicsContextStateSaver&) =
+ delete;
+
~GraphicsContextStateSaver() {
if (save_and_restore_)
context_.Restore();
@@ -76,8 +79,6 @@ 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_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index b9edafba4fd..7091f84682b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -32,6 +32,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
#include "base/trace_event/traced_value.h"
#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
@@ -276,6 +277,7 @@ void GraphicsLayer::ClearPaintStateRecursively() {
bool GraphicsLayer::PaintRecursively(
GraphicsContext& context,
Vector<PreCompositedLayerInfo>& pre_composited_layers,
+ PaintController::CycleScope& cycle_scope,
PaintBenchmarkMode benchmark_mode) {
bool repainted = false;
ForAllGraphicsLayers(
@@ -285,7 +287,7 @@ bool GraphicsLayer::PaintRecursively(
layer.ClearPaintStateRecursively();
return false;
}
- layer.Paint(pre_composited_layers, benchmark_mode);
+ layer.Paint(pre_composited_layers, benchmark_mode, &cycle_scope);
repainted |= layer.repainted_;
return true;
},
@@ -312,11 +314,14 @@ bool GraphicsLayer::PaintRecursively(
void GraphicsLayer::PaintForTesting(const IntRect& interest_rect) {
Vector<PreCompositedLayerInfo> pre_composited_layers;
- Paint(pre_composited_layers, PaintBenchmarkMode::kNormal, &interest_rect);
+ PaintController::CycleScope cycle_scope;
+ Paint(pre_composited_layers, PaintBenchmarkMode::kNormal, &cycle_scope,
+ &interest_rect);
}
void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
PaintBenchmarkMode benchmark_mode,
+ PaintController::CycleScope* cycle_scope,
const IntRect* interest_rect) {
repainted_ = false;
@@ -350,6 +355,8 @@ void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
}
auto& paint_controller = GetPaintController();
+ if (cycle_scope)
+ cycle_scope->AddController(paint_controller);
absl::optional<PaintChunkSubset> previous_chunks;
if (ShouldCreateLayersAfterPaint())
@@ -364,6 +371,7 @@ void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
paint_controller.ClientCacheIsValid(*this) &&
previous_interest_rect_ == new_interest_rect;
if (!cached) {
+ paint_controller.MarkClientForValidation(*this);
GraphicsContext context(paint_controller);
DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
paint_controller.UpdateCurrentPaintChunkProperties(
@@ -375,9 +383,6 @@ void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
previous_interest_rect_ = new_interest_rect;
client_.PaintContents(this, context, painting_phase_, new_interest_rect);
paint_controller.CommitNewDisplayItems();
- // TODO(wangxianzhu): Remove this and friend class in DisplayItemClient
- // when unifying PaintController.
- Validate();
DVLOG(2) << "Painted GraphicsLayer: " << DebugName()
<< " paintable region: " << PaintableRegion().ToString();
}
@@ -404,11 +409,11 @@ void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
if (!ShouldCreateLayersAfterPaint()) {
auto& raster_invalidator = EnsureRasterInvalidator();
- gfx::Size old_layer_size = raster_invalidator.LayerBounds().size();
- gfx::Rect layer_bounds(layer_state_->offset, Size());
+ gfx::Size old_layer_size(raster_invalidator.LayerBounds());
PropertyTreeState property_tree_state = GetPropertyTreeState().Unalias();
- EnsureRasterInvalidator().Generate(raster_invalidation_function_, chunks,
- layer_bounds, property_tree_state, this);
+ EnsureRasterInvalidator().Generate(
+ raster_invalidation_function_, chunks, FloatPoint(layer_state_->offset),
+ IntSize(Size()), property_tree_state, this);
absl::optional<RasterUnderInvalidationCheckingParams>
raster_under_invalidation_params;
@@ -425,8 +430,7 @@ void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
if (raster_invalidated_ || !cc_display_item_list_ ||
old_layer_size != Size() || raster_under_invalidation_params) {
cc_display_item_list_ = PaintChunksToCcLayer::Convert(
- chunks, property_tree_state,
- gfx::Vector2dF(layer_state_->offset.X(), layer_state_->offset.Y()),
+ chunks, property_tree_state, FloatPoint(layer_state_->offset),
cc::DisplayItemList::kTopLevelDisplayItemList,
base::OptionalOrNullptr(raster_under_invalidation_params));
raster_invalidated_ = false;
@@ -439,7 +443,6 @@ void GraphicsLayer::Paint(Vector<PreCompositedLayerInfo>& pre_composited_layers,
void GraphicsLayer::SetShouldCreateLayersAfterPaint(
bool should_create_layers_after_paint) {
- DCHECK(RuntimeEnabledFeatures::CompositeSVGEnabled());
if (should_create_layers_after_paint != should_create_layers_after_paint_) {
should_create_layers_after_paint_ = should_create_layers_after_paint;
// Depending on |should_create_layers_after_paint_|, raster invalidation
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 2287e8d6dca..5ddf1addcee 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -30,7 +30,6 @@
#include <memory>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "cc/input/scroll_snap_data.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/layer.h"
@@ -55,7 +54,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace cc {
@@ -81,6 +79,8 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
public:
explicit GraphicsLayer(GraphicsLayerClient&);
+ GraphicsLayer(const GraphicsLayer&) = delete;
+ GraphicsLayer& operator=(const GraphicsLayer&) = delete;
~GraphicsLayer() override;
GraphicsLayerClient& Client() const { return client_; }
@@ -173,6 +173,7 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
// Returns true if any layer is repainted.
bool PaintRecursively(GraphicsContext&,
Vector<PreCompositedLayerInfo>&,
+ PaintController::CycleScope& cycle_scope,
PaintBenchmarkMode = PaintBenchmarkMode::kNormal);
PaintController& GetPaintController() const;
@@ -239,6 +240,7 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
void ClearPaintStateRecursively();
void Paint(Vector<PreCompositedLayerInfo>&,
PaintBenchmarkMode,
+ PaintController::CycleScope*,
const IntRect* interest_rect = nullptr);
// Adds a child without calling NotifyChildListChange(), so that adding
@@ -313,8 +315,6 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
DOMNodeId owner_node_id_ = kInvalidDOMNodeId;
CompositingReasons compositing_reasons_ = CompositingReason::kNone;
-
- DISALLOW_COPY_AND_ASSIGN(GraphicsLayer);
};
// Iterates all graphics layers that should be seen by the compositor in
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 3856e9a977c..af4b9ca7e74 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
@@ -100,12 +100,14 @@ TEST_F(GraphicsLayerTest, PaintRecursively) {
GraphicsContext context(GetPaintController());
client.SetNeedsRepaint(true);
Vector<PreCompositedLayerInfo> pre_composited_layers;
- EXPECT_TRUE(root.PaintRecursively(context, pre_composited_layers));
+ {
+ PaintController::CycleScope cycle_scope;
+ EXPECT_TRUE(
+ root.PaintRecursively(context, pre_composited_layers, cycle_scope));
+ }
EXPECT_TRUE(root.Repainted());
- root.GetPaintController().FinishCycle();
EXPECT_FALSE(layer1.Repainted());
EXPECT_TRUE(layer2.Repainted());
- layer2.GetPaintController().FinishCycle();
HitTestData hit_test_data;
hit_test_data.touch_action_rects = {{IntRect(1, 2, 3, 4)}};
@@ -129,7 +131,11 @@ TEST_F(GraphicsLayerTest, PaintRecursively) {
// Paint again with nothing changed.
client.SetNeedsRepaint(false);
pre_composited_layers.clear();
- EXPECT_FALSE(root.PaintRecursively(context, pre_composited_layers));
+ {
+ PaintController::CycleScope cycle_scope;
+ EXPECT_FALSE(
+ root.PaintRecursively(context, pre_composited_layers, cycle_scope));
+ }
EXPECT_FALSE(root.Repainted());
EXPECT_FALSE(layer1.Repainted());
EXPECT_FALSE(layer2.Repainted());
@@ -138,10 +144,13 @@ TEST_F(GraphicsLayerTest, PaintRecursively) {
// Paint again with layer1 drawing content.
layer1.SetDrawsContent(true);
pre_composited_layers.clear();
- EXPECT_TRUE(root.PaintRecursively(context, pre_composited_layers));
+ {
+ PaintController::CycleScope cycle_scope;
+ EXPECT_TRUE(
+ root.PaintRecursively(context, pre_composited_layers, cycle_scope));
+ }
EXPECT_FALSE(root.Repainted());
EXPECT_TRUE(layer1.Repainted());
- layer1.GetPaintController().FinishCycle();
EXPECT_FALSE(layer2.Repainted());
EXPECT_EQ(3u, pre_composited_layers.size());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_types.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_types.cc
index a28c5025b05..02196a7439b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_types.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_types.cc
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_types.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_types.h
index d3938dfe190..de0163b12b6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_types.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_types.h
@@ -26,9 +26,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_TYPES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_TYPES_H_
+#include "cc/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
@@ -67,9 +67,10 @@ enum StrokeStyle {
};
enum InterpolationQuality {
- kInterpolationNone = kNone_SkFilterQuality,
- kInterpolationLow = kLow_SkFilterQuality,
- kInterpolationMedium = kMedium_SkFilterQuality,
+ kInterpolationNone = static_cast<int>(cc::PaintFlags::FilterQuality::kNone),
+ kInterpolationLow = static_cast<int>(cc::PaintFlags::FilterQuality::kLow),
+ kInterpolationMedium =
+ static_cast<int>(cc::PaintFlags::FilterQuality::kMedium),
#if defined(WTF_USE_LOW_QUALITY_IMAGE_INTERPOLATION)
kInterpolationDefault = kInterpolationLow,
#else
diff --git a/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.cc b/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.cc
deleted file mode 100644
index 446bfffe17b..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h"
-
-#include <cstring>
-
-#include "gpu/command_buffer/client/raster_interface.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-
-namespace blink {
-
-namespace {
-
-// To minimize performance impact, don't exceed kMaxDigestOps during the
-// lifetime of this IdentifiabilityPaintOpDigest object.
-constexpr int kMaxDigestOps = 1 << 20;
-
-} // namespace
-
-// Storage for serialized PaintOp state.
-Vector<char>& SerializationBuffer() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Vector<char>>,
- serialization_buffer, ());
- return *serialization_buffer;
-}
-
-IdentifiabilityPaintOpDigest::IdentifiabilityPaintOpDigest(IntSize size)
- : IdentifiabilityPaintOpDigest(size, kMaxDigestOps) {}
-
-IdentifiabilityPaintOpDigest::IdentifiabilityPaintOpDigest(IntSize size,
- int max_digest_ops)
- : max_digest_ops_(max_digest_ops),
- size_(size),
- paint_cache_(cc::ClientPaintCache::kNoCachingBudget),
- serialize_options_(&image_provider_,
- /*transfer_cache=*/nullptr,
- &paint_cache_,
- /*strike_server=*/nullptr,
- /*color_space=*/nullptr,
- /*can_use_lcd_text=*/false,
- /*content_supports_distance_field_text=*/false,
- /*max_texture_size=*/0) {
- serialize_options_.for_identifiability_study = true;
- constexpr size_t kInitialSize = 16 * 1024;
- if (IdentifiabilityStudySettings::Get()->IsTypeAllowed(
- blink::IdentifiableSurface::Type::kCanvasReadback) &&
- SerializationBuffer().size() < kInitialSize) {
- SerializationBuffer().resize(kInitialSize);
- }
-}
-
-IdentifiabilityPaintOpDigest::~IdentifiabilityPaintOpDigest() = default;
-
-constexpr size_t IdentifiabilityPaintOpDigest::kInfiniteOps;
-
-void IdentifiabilityPaintOpDigest::MaybeUpdateDigest(
- const sk_sp<const cc::PaintRecord>& paint_record,
- const size_t num_ops_to_visit) {
- if (!IdentifiabilityStudySettings::Get()->IsTypeAllowed(
- blink::IdentifiableSurface::Type::kCanvasReadback)) {
- return;
- }
- if (total_ops_digested_ >= max_digest_ops_) {
- encountered_skipped_ops_ = true;
- return;
- }
-
- // Determine how many PaintOps we'll need to digest after the initial digests
- // that are skipped.
- const size_t num_ops_to_digest = num_ops_to_visit - prefix_skip_count_;
-
- // The number of PaintOps digested in this MaybeUpdateDigest() call.
- size_t cur_ops_digested = 0;
- for (const auto* op : cc::PaintRecord::Iterator(paint_record.get())) {
- // Skip initial PaintOps that don't correspond to context operations.
- if (prefix_skip_count_ > 0) {
- prefix_skip_count_--;
- continue;
- }
- // Update the digest for at most |num_ops_to_digest| operations in this
- // MaybeUpdateDigest() invocation.
- if (num_ops_to_visit != kInfiniteOps &&
- cur_ops_digested >= num_ops_to_digest)
- break;
-
- // To capture font fallback identifiability, we capture text draw operations
- // at the 2D context layer. We still need to modify the token builder digest
- // since we want to track the relative ordering of text operations and other
- // operations.
- if (op->GetType() == cc::PaintOpType::DrawTextBlob) {
- constexpr uint64_t kDrawTextBlobValue =
- UINT64_C(0x8c1587a34065ea3b); // Picked form a hat.
- builder_.AddValue(kDrawTextBlobValue);
- continue;
- }
-
- // DrawRecord PaintOps contain nested PaintOps.
- if (op->GetType() == cc::PaintOpType::DrawRecord) {
- const auto* draw_record_op = static_cast<const cc::DrawRecordOp*>(op);
- MaybeUpdateDigest(draw_record_op->record, kInfiniteOps);
- continue;
- }
-
- std::memset(SerializationBuffer().data(), 0, SerializationBuffer().size());
- size_t serialized_size;
- while ((serialized_size = op->Serialize(
- SerializationBuffer().data(), SerializationBuffer().size(),
- serialize_options_, nullptr, SkM44(), SkM44())) == 0) {
- constexpr size_t kMaxBufferSize =
- gpu::raster::RasterInterface::kDefaultMaxOpSizeHint << 2;
- if (SerializationBuffer().size() >= kMaxBufferSize) {
- encountered_skipped_ops_ = true;
- return;
- }
- SerializationBuffer().Grow(SerializationBuffer().size() << 1);
- }
- builder_.AddAtomic(base::as_bytes(
- base::make_span(SerializationBuffer().data(), serialized_size)));
- total_ops_digested_++;
- cur_ops_digested++;
- }
- DCHECK_EQ(prefix_skip_count_, 0u);
-}
-
-cc::ImageProvider::ScopedResult
-IdentifiabilityPaintOpDigest::IdentifiabilityImageProvider::GetRasterContent(
- const cc::DrawImage& draw_image) {
- // TODO(crbug.com/973801): Compute digests on images.
- outer_->encountered_partially_digested_image_ = true;
- return ScopedResult();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h b/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h
deleted file mode 100644
index 79f1916948e..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IDENTIFIABILITY_PAINT_OP_DIGEST_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IDENTIFIABILITY_PAINT_OP_DIGEST_H_
-
-#include "cc/paint/draw_image.h"
-#include "cc/paint/image_provider.h"
-#include "cc/paint/paint_cache.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
-
-namespace blink {
-
-// Manages digest calculation of operations performed on an HTML canvas using
-// the serialization of PaintOps generated by those operations.
-class PLATFORM_EXPORT IdentifiabilityPaintOpDigest {
- public:
- // Constructs based on the size of the CanvasResourceProvider.
- explicit IdentifiabilityPaintOpDigest(IntSize size);
- // For-testing constructor that allows setting a custom |max_digest_ops_|.
- IdentifiabilityPaintOpDigest(IntSize size, int max_digest_ops);
- ~IdentifiabilityPaintOpDigest();
-
- // When passed as |num_ops_to_visit| to MaybeUpdateDigest(), every
- // non-skipped PaintOp in the buffer contributes to digest calculation.
- static constexpr size_t kInfiniteOps = -1;
-
- // Maybe update the digest, if the user is participating in the study, and we
- // haven't exceeded the operation count.
- //
- // Only processes |num_ops_to_visit| PaintOps, which includes the first
- // |prefix_skip_count| PaintOps that are skipped. The prefix and suffixes that
- // aren't processed are internal rendering details, and don't correspond to
- // operations performed on the canvas context.
- void MaybeUpdateDigest(const sk_sp<const cc::PaintRecord>& paint_record,
- size_t num_ops_to_visit);
-
- // Sets the number of operations to skip in the next PaintRecord passed to
- // MaybeUpdateDigest().
- void SetPrefixSkipCount(size_t prefix_skip_count) {
- prefix_skip_count_ = prefix_skip_count;
- }
-
- // The IdentifiabilityToken (digest), based on the PaintOps observed.
- IdentifiableToken GetToken() const { return builder_.GetToken(); }
-
- bool encountered_partially_digested_image() const {
- return encountered_partially_digested_image_;
- }
-
- bool encountered_skipped_ops() const { return encountered_skipped_ops_; }
-
- private:
- class IdentifiabilityImageProvider : public cc::ImageProvider {
- public:
- explicit IdentifiabilityImageProvider(IdentifiabilityPaintOpDigest* outer)
- : outer_(outer) {}
-
- ScopedResult GetRasterContent(const cc::DrawImage& draw_image) override;
-
- private:
- IdentifiabilityPaintOpDigest* const outer_;
- };
-
- // The maximum number of ops to digest during the lifetime of this
- // IdentifiabilityPaintOpDigest object.
- const int max_digest_ops_;
-
- // Potentially updated every MaybeUpdateDigest() call.
- IdentifiableTokenBuilder builder_;
-
- // The number of PaintOps that have contributed to the current digest -- used
- // to stop updating the digest after a threshold number of operations to avoid
- // hurting performance.
- int total_ops_digested_ = 0;
-
- // How many PaintOps to skip, as set by SetPrefixSkipCount().
- size_t prefix_skip_count_ = 0;
-
- // Resources needed for PaintOp serialization.
-
- // Size of the corresponding CanvasResourceProvider.
- IntSize size_;
-
- // Fake identifiability image provider; can be used to compute image digests.
- IdentifiabilityImageProvider image_provider_{this};
-
- // Real paint cache with Put() disabled.
- cc::ClientPaintCache paint_cache_;
-
- // Used for PaintOp::Serialize() -- several options are not needed, since we
- // just need to compute a digest.
- cc::PaintOp::SerializeOptions serialize_options_;
-
- // If true, at least one DrawImage[Rect]Op was partially digested -- the whole
- // image wasn't digested for performance reasons.
- bool encountered_partially_digested_image_ = false;
-
- // If true, at least one op was skipped completely, for performance reasons.
- //
- // DrawTextBlobOps don't flip this flag to true, as they are handled
- // separately in the 2D canavs context object (to capture font fallback
- // fingerprinting). Also, prefix and suffix ops skipped don't flip this flag
- // to true.
- bool encountered_skipped_ops_ = false;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IDENTIFIABILITY_PAINT_OP_DIGEST_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest_unittest.cc b/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest_unittest.cc
deleted file mode 100644
index e1af0992129..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest_unittest.cc
+++ /dev/null
@@ -1,441 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h"
-
-#include "cc/test/skia_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/core/SkTileMode.h"
-
-namespace blink {
-
-namespace {
-
-// A IdentifiabilityStudySettingsProvider implementation that opts-into study
-// participation.
-class ActiveSettingsProvider : public IdentifiabilityStudySettingsProvider {
- public:
- bool IsActive() const override { return true; }
- bool IsAnyTypeOrSurfaceBlocked() const override { return false; }
- bool IsSurfaceAllowed(IdentifiableSurface surface) const override {
- return true;
- }
- bool IsTypeAllowed(IdentifiableSurface::Type type) const override {
- return true;
- }
- int SampleRate(IdentifiableSurface surface) const override { return 1; }
- int SampleRate(IdentifiableSurface::Type type) const override { return 1; }
-};
-
-// An RAII class that opts into study participation using
-// ActiveSettingsProvider.
-class StudyParticipationRaii {
- public:
- StudyParticipationRaii() {
- IdentifiabilityStudySettings::SetGlobalProvider(
- std::make_unique<ActiveSettingsProvider>());
- }
- ~StudyParticipationRaii() {
- IdentifiabilityStudySettings::ResetStateForTesting();
- }
-};
-
-// Arbitrary non-zero size.
-constexpr IntSize kSize(10, 10);
-
-constexpr float kScaleX = 1.0f, kScaleY = 1.0f;
-constexpr int64_t kScaleDigest = INT64_C(8258647715449129112);
-constexpr int64_t kTokenBuilderInitialDigest = INT64_C(6544625333304541877);
-
-TEST(IdentifiabilityPaintOpDigestTest, Construct) {
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, Construct_InStudy) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, InitialDigest) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(kTokenBuilderInitialDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, SimpleDigest) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::ScaleOp>(kScaleX, kScaleY);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(kScaleDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, DigestIsInitialIfNotInStudy) {
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::ScaleOp>(1.0f, 1.0f);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(kTokenBuilderInitialDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, IgnoresTextOpsContents) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest1(kSize);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest2(kSize);
- auto paint_record1 = sk_make_sp<cc::PaintRecord>();
- auto paint_record2 = sk_make_sp<cc::PaintRecord>();
- paint_record1->push<cc::DrawTextBlobOp>(
- SkTextBlob::MakeFromString("abc", SkFont(SkTypeface::MakeDefault())),
- 1.0f, 1.0f, cc::PaintFlags());
- paint_record2->push<cc::DrawTextBlobOp>(
- SkTextBlob::MakeFromString("def", SkFont(SkTypeface::MakeDefault())),
- 2.0f, 2.0f, cc::PaintFlags());
- identifiability_paintop_digest1.MaybeUpdateDigest(paint_record1,
- /*num_ops_to_visit=*/1);
- identifiability_paintop_digest2.MaybeUpdateDigest(paint_record2,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(identifiability_paintop_digest1.GetToken().ToUkmMetricValue(),
- identifiability_paintop_digest2.GetToken().ToUkmMetricValue());
- EXPECT_NE(kTokenBuilderInitialDigest,
- identifiability_paintop_digest1.GetToken().ToUkmMetricValue());
- EXPECT_EQ(INT64_C(5364951310489041526),
- identifiability_paintop_digest1.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest1.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest1.encountered_partially_digested_image());
- EXPECT_FALSE(identifiability_paintop_digest2.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest2.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, RelativeOrderingTextOpsAndOtherOps) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest1(kSize);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest2(kSize);
- auto paint_record1 = sk_make_sp<cc::PaintRecord>();
- auto paint_record2 = sk_make_sp<cc::PaintRecord>();
- paint_record1->push<cc::DrawTextBlobOp>(
- SkTextBlob::MakeFromString("abc", SkFont(SkTypeface::MakeDefault())),
- 1.0f, 1.0f, cc::PaintFlags());
- paint_record1->push<cc::ScaleOp>(kScaleX, kScaleY);
- paint_record2->push<cc::ScaleOp>(kScaleX, kScaleY);
- paint_record2->push<cc::DrawTextBlobOp>(
- SkTextBlob::MakeFromString("abc", SkFont(SkTypeface::MakeDefault())),
- 1.0f, 1.0f, cc::PaintFlags());
- identifiability_paintop_digest1.MaybeUpdateDigest(paint_record1,
- /*num_ops_to_visit=*/1);
- identifiability_paintop_digest2.MaybeUpdateDigest(paint_record2,
- /*num_ops_to_visit=*/1);
- EXPECT_NE(identifiability_paintop_digest1.GetToken().ToUkmMetricValue(),
- identifiability_paintop_digest2.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest1.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest1.encountered_partially_digested_image());
- EXPECT_FALSE(identifiability_paintop_digest2.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest2.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, SkPathDigestStability) {
- StudyParticipationRaii study_participation_raii;
- // These 2 SkPath objects will have different internal generation IDs. We
- // can't use empty paths as in that case the internal SkPathRefs (which holds
- // the ID) for each SkPath would be the same global "empty" SkPathRef, so we
- // make the SkPaths non-empty.
- SkPath path1;
- path1.rLineTo(1.0f, 0.0f);
- SkPath path2;
- path2.rLineTo(1.0f, 0.0f);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest1(kSize);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest2(kSize);
- auto paint_record1 = sk_make_sp<cc::PaintRecord>();
- auto paint_record2 = sk_make_sp<cc::PaintRecord>();
- paint_record1->push<cc::DrawPathOp>(path1, cc::PaintFlags());
- paint_record2->push<cc::DrawPathOp>(path2, cc::PaintFlags());
- identifiability_paintop_digest1.MaybeUpdateDigest(paint_record1,
- /*num_ops_to_visit=*/1);
- identifiability_paintop_digest2.MaybeUpdateDigest(paint_record2,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(identifiability_paintop_digest1.GetToken().ToUkmMetricValue(),
- identifiability_paintop_digest2.GetToken().ToUkmMetricValue());
- EXPECT_EQ(INT64_C(-1093634256342000670),
- identifiability_paintop_digest1.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest1.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest1.encountered_partially_digested_image());
- EXPECT_FALSE(identifiability_paintop_digest2.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest2.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, PaintShaderStability) {
- StudyParticipationRaii study_participation_raii;
- SkPath path;
- path.rLineTo(1.0f, 0.0f);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest1(kSize);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest2(kSize);
- auto paint_record1 = sk_make_sp<cc::PaintRecord>();
- auto paint_record2 = sk_make_sp<cc::PaintRecord>();
- auto paint_record_shader = sk_make_sp<cc::PaintRecord>();
- paint_record_shader->push<cc::ScaleOp>(2.0f, 2.0f);
- const SkRect tile = SkRect::MakeWH(100, 100);
- // These 2 shaders will have different internal generation IDs.
- cc::PaintFlags paint_flags1;
- paint_flags1.setShader(cc::PaintShader::MakePaintRecord(
- paint_record_shader, tile, SkTileMode::kClamp, SkTileMode::kClamp,
- nullptr));
- cc::PaintFlags paint_flags2;
- paint_flags2.setShader(cc::PaintShader::MakePaintRecord(
- paint_record_shader, tile, SkTileMode::kClamp, SkTileMode::kClamp,
- nullptr));
- paint_record1->push<cc::DrawPathOp>(path, paint_flags1);
- paint_record2->push<cc::DrawPathOp>(path, paint_flags2);
- identifiability_paintop_digest1.MaybeUpdateDigest(paint_record1,
- /*num_ops_to_visit=*/1);
- identifiability_paintop_digest2.MaybeUpdateDigest(paint_record2,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(identifiability_paintop_digest1.GetToken().ToUkmMetricValue(),
- identifiability_paintop_digest2.GetToken().ToUkmMetricValue());
- EXPECT_EQ(INT64_C(6157094048912696853),
- identifiability_paintop_digest1.GetToken().ToUkmMetricValue());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, BufferLeftoversDontAffectFutureDigests) {
- StudyParticipationRaii study_participation_raii;
- // Make a complex path to make a PaintOp with a large serialization.
- SkPath path;
- path.rLineTo(1.0f, 0.0f);
- path.rLineTo(1.0f, 1.0f);
- path.rLineTo(0.0f, 1.0f);
- path.rLineTo(2.0f, 0.0f);
- path.rLineTo(2.0f, 2.0f);
- path.rLineTo(0.0f, 2.0f);
- path.rLineTo(1.0f, 0.0f);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest1(kSize);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest2(kSize);
- auto paint_record1 = sk_make_sp<cc::PaintRecord>();
- auto paint_record2 = sk_make_sp<cc::PaintRecord>();
- paint_record1->push<cc::DrawPathOp>(path, cc::PaintFlags());
- paint_record2->push<cc::ScaleOp>(kScaleX, kScaleY);
- identifiability_paintop_digest1.MaybeUpdateDigest(paint_record1,
- /*num_ops_to_visit=*/1);
- identifiability_paintop_digest2.MaybeUpdateDigest(paint_record2,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(INT64_C(-8958477480441775589),
- identifiability_paintop_digest1.GetToken().ToUkmMetricValue());
- EXPECT_EQ(kScaleDigest,
- identifiability_paintop_digest2.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest1.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest1.encountered_partially_digested_image());
- EXPECT_FALSE(identifiability_paintop_digest2.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest2.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest,
- BufferLeftoversDontAffectFutureDigests_SameCanvas) {
- StudyParticipationRaii study_participation_raii;
- // Make a complex path to make a PaintOp with a large serialization.
- SkPath path;
- path.rLineTo(1.0f, 0.0f);
- path.rLineTo(1.0f, 1.0f);
- path.rLineTo(0.0f, 1.0f);
- path.rLineTo(2.0f, 0.0f);
- path.rLineTo(2.0f, 2.0f);
- path.rLineTo(0.0f, 2.0f);
- path.rLineTo(1.0f, 0.0f);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::DrawPathOp>(path, cc::PaintFlags());
- paint_record->push<cc::ScaleOp>(kScaleX, kScaleY);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/2);
- EXPECT_EQ(INT64_C(4130836803240885894),
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, IgnoresPrefixAndSuffix) {
- StudyParticipationRaii study_participation_raii;
- SkPath path1;
- path1.rLineTo(1.0f, 0.0f);
- SkPath path2;
- path2.rLineTo(0.0f, 1.0f);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::DrawPathOp>(path1, cc::PaintFlags());
- paint_record->push<cc::ScaleOp>(kScaleX, kScaleY);
- paint_record->push<cc::DrawPathOp>(path2, cc::PaintFlags());
- identifiability_paintop_digest.SetPrefixSkipCount(1);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/2);
- EXPECT_EQ(kScaleDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, IgnoresPrefixAndSuffix_MultipleOps) {
- StudyParticipationRaii study_participation_raii;
- SkPath path1;
- path1.rLineTo(1.0f, 0.0f);
- SkPath path2;
- path2.rLineTo(0.0f, 1.0f);
- SkPath path3;
- path3.rLineTo(1.0f, 1.0f);
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::DrawPathOp>(path1, cc::PaintFlags());
- paint_record->push<cc::ScaleOp>(kScaleX, kScaleY);
- paint_record->push<cc::DrawPathOp>(path2, cc::PaintFlags());
- paint_record->push<cc::DrawPathOp>(path3, cc::PaintFlags());
- identifiability_paintop_digest.SetPrefixSkipCount(1);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/2);
- EXPECT_EQ(INT64_C(8258647715449129112),
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, RecursesIntoDrawRecords) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record_inner = sk_make_sp<cc::PaintRecord>();
- auto paint_record_outer = sk_make_sp<cc::PaintRecord>();
- paint_record_inner->push<cc::ScaleOp>(kScaleX, kScaleY);
- paint_record_outer->push<cc::DrawRecordOp>(paint_record_inner);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record_outer,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(kScaleDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, RecursesIntoDrawRecords_TwoLevels) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record_inner = sk_make_sp<cc::PaintRecord>();
- auto paint_record_middle = sk_make_sp<cc::PaintRecord>();
- auto paint_record_outer = sk_make_sp<cc::PaintRecord>();
- paint_record_inner->push<cc::ScaleOp>(kScaleX, kScaleY);
- paint_record_middle->push<cc::DrawRecordOp>(paint_record_inner);
- paint_record_outer->push<cc::DrawRecordOp>(paint_record_middle);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record_outer,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(kScaleDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, StopsUpdatingDigestAfterThreshold) {
- StudyParticipationRaii study_participation_raii;
- constexpr int kMaxOperations = 5;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize,
- kMaxOperations);
- int64_t last_digest = INT64_C(0);
- for (int i = 0; i < kMaxOperations; i++) {
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::ScaleOp>(kScaleX, kScaleY);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_NE(last_digest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue())
- << i;
- last_digest = identifiability_paintop_digest.GetToken().ToUkmMetricValue();
- }
-
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::ScaleOp>(kScaleX, kScaleY);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(last_digest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_TRUE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, MassiveOpSkipped) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- SkPath path;
- // Build a massive PaintOp.
- constexpr size_t kMaxIterations = 1 << 22;
- for (size_t i = 0; i < kMaxIterations; i++)
- path.rLineTo(1.0f, 1.0f);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::DrawPathOp>(path, cc::PaintFlags());
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(kTokenBuilderInitialDigest,
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_TRUE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_FALSE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-TEST(IdentifiabilityPaintOpDigestTest, DigestImageOp) {
- StudyParticipationRaii study_participation_raii;
- IdentifiabilityPaintOpDigest identifiability_paintop_digest(kSize);
- auto paint_record = sk_make_sp<cc::PaintRecord>();
- paint_record->push<cc::DrawImageOp>(
- cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), 10.0f, 10.0f);
- identifiability_paintop_digest.MaybeUpdateDigest(paint_record,
- /*num_ops_to_visit=*/1);
- EXPECT_EQ(INT64_C(-3447989221783743109),
- identifiability_paintop_digest.GetToken().ToUkmMetricValue());
-
- EXPECT_FALSE(identifiability_paintop_digest.encountered_skipped_ops());
- EXPECT_TRUE(
- identifiability_paintop_digest.encountered_partially_digested_image());
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.cc b/chromium/third_party/blink/renderer/platform/graphics/image.cc
index 80f0a2d1e86..f2b1f5db11e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.cc
@@ -33,6 +33,7 @@
#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "cc/tiles/software_image_decode_cache.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
@@ -95,8 +96,9 @@ cc::ImageDecodeCache& Image::SharedCCDecodeCache(SkColorType color_type) {
return image_decode_cache;
}
-scoped_refptr<Image> Image::LoadPlatformResource(int resource_id,
- ui::ScaleFactor scale_factor) {
+scoped_refptr<Image> Image::LoadPlatformResource(
+ int resource_id,
+ ui::ResourceScaleFactor scale_factor) {
const WebData& resource =
Platform::Current()->GetDataResource(resource_id, scale_factor);
if (resource.IsEmpty())
@@ -164,7 +166,7 @@ Image::SizeAvailability Image::SetData(scoped_refptr<SharedBuffer> data,
if (!encoded_image_data_.get())
return kSizeAvailable;
- int length = encoded_image_data_->size();
+ size_t length = encoded_image_data_->size();
if (!length)
return kSizeAvailable;
@@ -201,9 +203,7 @@ sk_sp<PaintShader> CreatePatternShader(const PaintImage& image,
PaintFlags flags;
flags.setAntiAlias(should_antialias);
canvas->drawImageRect(
- image,
- SkRect::MakeXYWH(subset_rect.X(), subset_rect.Y(), subset_rect.Width(),
- subset_rect.Height()),
+ image, subset_rect,
SkRect::MakeWH(subset_rect.Width(), subset_rect.Height()), sampling,
&flags, SkCanvas::kStrict_SrcRectConstraint);
@@ -219,13 +219,10 @@ SkTileMode ComputeTileMode(float left, float right, float min, float max) {
} // anonymous namespace
void Image::DrawPattern(GraphicsContext& context,
- const FloatRect& float_src_rect,
- const FloatSize& scale_src_to_dest,
- const FloatPoint& phase,
- SkBlendMode composite_op,
+ const cc::PaintFlags& base_flags,
const FloatRect& dest_rect,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum respect_orientation) {
+ const ImageTilingInfo& tiling_info,
+ const ImageDrawOptions& draw_options) {
TRACE_EVENT0("skia", "Image::drawPattern");
if (dest_rect.IsEmpty())
@@ -235,63 +232,62 @@ void Image::DrawPattern(GraphicsContext& context,
if (!image)
return; // nothing to draw
- // The subset_rect is in source image space, unscaled but oriented.
- // image-resolution information is baked into the scale_src_to_dest,
+ // Fetch orientation data if needed.
+ ImageOrientation orientation = ImageOrientationEnum::kDefault;
+ if (draw_options.respect_image_orientation)
+ orientation = CurrentFrameOrientation();
+
+ // |tiling_info.image_rect| is in source image space, unscaled but oriented.
+ // image-resolution information is baked into |tiling_info.scale|,
// so we do not want to use it in computing the subset. That requires
// explicitly applying orientation here.
- IntRect subset_rect = EnclosingIntRect(float_src_rect);
+ IntRect subset_rect = EnclosingIntRect(tiling_info.image_rect);
IntSize oriented_image_size(image.width(), image.height());
- if (respect_orientation && CurrentFrameOrientation().UsesWidthAsHeight())
+ if (orientation.UsesWidthAsHeight())
oriented_image_size = oriented_image_size.TransposedSize();
subset_rect.Intersect(IntRect(IntPoint(), oriented_image_size));
if (subset_rect.IsEmpty())
return; // nothing to draw
// Apply image orientation, if necessary
- FloatSize oriented_scale = scale_src_to_dest;
- if (respect_orientation && !HasDefaultOrientation()) {
- image = ResizeAndOrientImage(image, CurrentFrameOrientation());
- }
+ if (orientation != ImageOrientationEnum::kDefault)
+ image = ResizeAndOrientImage(image, orientation);
- 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 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() + subset_rect.X() * oriented_scale.Width();
- const float adjusted_y =
- phase.Y() + subset_rect.Y() * oriented_scale.Height();
- local_matrix.setTranslate(SkFloatToScalar(adjusted_x),
- SkFloatToScalar(adjusted_y));
+ FloatRect tile_rect(subset_rect);
+ tile_rect.Scale(tiling_info.scale.Width(), tiling_info.scale.Height());
+ tile_rect.MoveBy(tiling_info.phase);
+ tile_rect.Expand(tiling_info.spacing);
+ SkMatrix local_matrix;
+ local_matrix.setTranslate(tile_rect.X(), tile_rect.Y());
// Apply the scale to have the subset correctly fill the destination.
- local_matrix.preScale(oriented_scale.Width(), oriented_scale.Height());
+ local_matrix.preScale(tiling_info.scale.Width(), tiling_info.scale.Height());
+
+ const auto tmx = ComputeTileMode(dest_rect.X(), dest_rect.MaxX(),
+ tile_rect.X(), tile_rect.MaxX());
+ const auto tmy = ComputeTileMode(dest_rect.Y(), dest_rect.MaxY(),
+ tile_rect.Y(), tile_rect.MaxY());
// Fetch this now as subsetting may swap the image.
auto image_id = image.stable_id();
- const FloatSize tile_size(
- subset_rect.Width() * oriented_scale.Width() + repeat_spacing.Width(),
- subset_rect.Height() * oriented_scale.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,
- adjusted_y + tile_size.Height());
-
SkSamplingOptions sampling_to_use =
context.ComputeSamplingOptions(this, dest_rect, FloatRect(subset_rect));
sk_sp<PaintShader> tile_shader = CreatePatternShader(
image, local_matrix, sampling_to_use, context.ShouldAntialias(),
- FloatSize(repeat_spacing.Width() / oriented_scale.Width(),
- repeat_spacing.Height() / oriented_scale.Height()),
+ FloatSize(tiling_info.spacing.Width() / tiling_info.scale.Width(),
+ tiling_info.spacing.Height() / tiling_info.scale.Height()),
tmx, tmy, subset_rect);
- PaintFlags flags = context.FillFlags();
// 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.
+ PaintFlags flags(base_flags);
flags.setColor(tile_shader ? SK_ColorBLACK : SK_ColorTRANSPARENT);
- flags.setBlendMode(composite_op);
flags.setShader(std::move(tile_shader));
context.DrawRect(dest_rect, flags);
@@ -305,6 +301,10 @@ void Image::DrawPattern(GraphicsContext& context,
}
}
+mojom::blink::ImageAnimationPolicy Image::AnimationPolicy() {
+ return mojom::blink::ImageAnimationPolicy::kImageAnimationPolicyAllowed;
+}
+
scoped_refptr<Image> Image::ImageForDefaultFrame() {
scoped_refptr<Image> image(this);
@@ -339,37 +339,25 @@ bool Image::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) {
return true;
}
-IntSize Image::Size(
- RespectImageOrientationEnum respect_image_orientation) const {
- if (respect_image_orientation == kRespectImageOrientation) {
- return PreferredDisplaySize();
- }
- return DensityCorrectedSize();
-}
-
SkBitmap Image::AsSkBitmapForCurrentFrame(
RespectImageOrientationEnum respect_image_orientation) {
PaintImage paint_image = PaintImageForCurrentFrame();
if (!paint_image)
return {};
- auto* bitmap_image = DynamicTo<BitmapImage>(this);
- IntSize density_corrected_size;
- if (bitmap_image)
- density_corrected_size = bitmap_image->DensityCorrectedSize();
+ if (auto* bitmap_image = DynamicTo<BitmapImage>(this)) {
+ const IntSize paint_image_size(paint_image.width(), paint_image.height());
+ const IntSize density_corrected_size = bitmap_image->DensityCorrectedSize();
- if (bitmap_image && (respect_image_orientation == kRespectImageOrientation ||
- !density_corrected_size.IsEmpty())) {
- ImageOrientation orientation =
- respect_image_orientation == kRespectImageOrientation
- ? bitmap_image->CurrentFrameOrientation()
- : ImageOrientationEnum::kDefault;
+ ImageOrientation orientation = ImageOrientationEnum::kDefault;
+ if (respect_image_orientation == kRespectImageOrientation)
+ orientation = bitmap_image->CurrentFrameOrientation();
FloatSize image_scale(1, 1);
- if (density_corrected_size != bitmap_image->Size()) {
- image_scale =
- FloatSize(density_corrected_size.Width() / bitmap_image->width(),
- density_corrected_size.Height() / bitmap_image->height());
+ if (density_corrected_size != paint_image_size) {
+ image_scale = FloatSize(
+ density_corrected_size.Width() / paint_image_size.Width(),
+ density_corrected_size.Height() / paint_image_size.Height());
}
paint_image = ResizeAndOrientImage(paint_image, orientation, image_scale);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.h b/chromium/third_party/blink/renderer/platform/graphics/image.h
index 04116a962f6..caea3499829 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.h
@@ -27,10 +27,9 @@
#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/public/mojom/webpreferences/web_preferences.mojom-blink.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -63,6 +62,9 @@ class WebGraphicsContext3DProvider;
class WebGraphicsContext3DProviderWrapper;
class DarkModeImageCache;
+struct ImageTilingInfo;
+struct ImageDrawOptions;
+
class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
friend class GeneratedImage;
friend class CrossfadeGeneratedImage;
@@ -70,13 +72,15 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
friend class GraphicsContext;
public:
+ Image(const Image&) = delete;
+ Image& operator=(const Image&) = delete;
virtual ~Image();
static cc::ImageDecodeCache& SharedCCDecodeCache(SkColorType);
static scoped_refptr<Image> LoadPlatformResource(
int resource_id,
- ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P);
+ ui::ResourceScaleFactor scale_factor = ui::SCALE_FACTOR_100P);
static PaintImage ResizeAndOrientImage(
const PaintImage&,
@@ -86,9 +90,11 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
InterpolationQuality = kInterpolationNone);
virtual bool IsSVGImage() const { return false; }
+ virtual bool IsSVGImageForContainer() const { return false; }
virtual bool IsBitmapImage() const { return false; }
virtual bool IsStaticBitmapImage() const { return false; }
virtual bool IsPlaceholderImage() const { return false; }
+ virtual bool IsGradientGeneratedImage() const { return false; }
virtual bool CurrentFrameKnownToBeOpaque() = 0;
@@ -106,14 +112,58 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
virtual bool HasIntrinsicSize() const { return true; }
- virtual IntSize Size() const = 0;
- virtual IntSize DensityCorrectedSize() const { return Size(); }
- IntSize Size(RespectImageOrientationEnum) const;
- virtual IntSize PreferredDisplaySize() const { return Size(); }
- virtual FloatSize SizeAsFloat(
- RespectImageOrientationEnum respect_orientation) const {
- return FloatSize(Size(respect_orientation));
+ struct SizeConfig {
+ // Apply density correction.
+ bool apply_density = false;
+
+ // Apply preferred orientation.
+ bool apply_orientation = false;
+ };
+
+ // Size of the Image optionally modified per the provided SizeConfig.
+ virtual IntSize SizeWithConfig(SizeConfig) const = 0;
+ virtual FloatSize SizeWithConfigAsFloat(SizeConfig config) const {
+ return FloatSize(SizeWithConfig(config));
+ }
+
+ // Size of the Image.
+ IntSize Size() const { return SizeWithConfig({}); }
+
+ // Size of the Image with density correction applied.
+ IntSize DensityCorrectedSize() const {
+ SizeConfig config;
+ config.apply_density = true;
+ return SizeWithConfig(config);
+ }
+
+ // Size of the Image with density correction and orientation applied
+ // regardless of any settings or style affecting orientation.
+ IntSize PreferredDisplaySize() const {
+ SizeConfig config;
+ config.apply_density = true;
+ config.apply_orientation = true;
+ return SizeWithConfig(config);
+ }
+
+ // Size of the Image with density correction applied. If the argument is
+ // kRespectImageOrientation orientation is applied as well.
+ IntSize Size(RespectImageOrientationEnum respect_orientation) const {
+ SizeConfig config;
+ config.apply_density = true;
+ config.apply_orientation = respect_orientation == kRespectImageOrientation;
+ return SizeWithConfig(config);
+ }
+
+ // Same as Size(RespectImageOrientationEnum) above, but returns a floating
+ // point representation of the size. For subclasses of Image that can have a
+ // fractional size this will return the unrounded size.
+ FloatSize SizeAsFloat(RespectImageOrientationEnum respect_orientation) const {
+ SizeConfig config;
+ config.apply_density = true;
+ config.apply_orientation = respect_orientation == kRespectImageOrientation;
+ return SizeWithConfigAsFloat(config);
}
+
IntRect Rect() const { return IntRect(IntPoint(), Size()); }
int width() const { return Size().Width(); }
int height() const { return Size().Height(); }
@@ -144,7 +194,22 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
virtual void DestroyDecodedData() = 0;
+ // In some overrides, |Data()| can be somewhat expensive (e.g. in BitmapImage,
+ // we don't use a SharedBuffer to store the image data, so |Data()| involves a
+ // copy). |HasData()| and |DataSize()| should be preferred in cases where the
+ // data itself is not needed.
+ //
+ // If a subclass overrides |Data|, it must override |HasData| and |DataSize|
+ // as well.
virtual scoped_refptr<SharedBuffer> Data() { return encoded_image_data_; }
+ // Returns true iff the encoded image data is available.
+ virtual bool HasData() const { return encoded_image_data_ != nullptr; }
+ // Returns the size of the encoded image data, in bytes. Should only be called
+ // if |HasData()| is true.
+ virtual size_t DataSize() const {
+ DCHECK(encoded_image_data_);
+ return encoded_image_data_->size();
+ }
// Animation begins whenever someone draws the image, so startAnimation() is
// not normally called. It will automatically pause once all observers no
@@ -157,9 +222,7 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
// Set animationPolicy
virtual void SetAnimationPolicy(mojom::blink::ImageAnimationPolicy) {}
- virtual mojom::blink::ImageAnimationPolicy AnimationPolicy() {
- return mojom::blink::ImageAnimationPolicy::kImageAnimationPolicyAllowed;
- }
+ virtual mojom::blink::ImageAnimationPolicy AnimationPolicy();
// Advances an animated image. For BitmapImage (e.g., animated gifs) this
// will advance to the next frame. For SVGImage, this will trigger an
@@ -207,15 +270,14 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
virtual PaintImage PaintImageForCurrentFrame() = 0;
- virtual bool HasDefaultOrientation() const { return true; }
-
// Most image types have the default orientation. Only bitmap derived image
// types need to override this method.
virtual ImageOrientation CurrentFrameOrientation() const {
return ImageOrientationEnum::kDefault;
}
-
- virtual IntSize CurrentFrameDensityCorrectedSize() const { return IntSize(); }
+ bool HasDefaultOrientation() const {
+ return CurrentFrameOrientation() == ImageOrientationEnum::kDefault;
+ }
// Correct the src rect (rotate and maybe translate it) to account for a
// non-default image orientation. The image must have non-default orientation
@@ -234,8 +296,7 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) = 0;
@@ -266,13 +327,10 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
Image(ImageObserver* = nullptr, bool is_multipart = false);
virtual void DrawPattern(GraphicsContext&,
- const FloatRect&,
- const FloatSize&,
- const FloatPoint& phase,
- SkBlendMode,
- const FloatRect&,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum);
+ const cc::PaintFlags&,
+ const FloatRect& dest_rect,
+ const ImageTilingInfo& tiling_info,
+ const ImageDrawOptions& draw_options);
// Creates and initializes a PaintImageBuilder with the metadata flags for the
// PaintImage.
@@ -295,7 +353,6 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
PaintImage::Id stable_image_id_;
const bool is_multipart_;
std::unique_ptr<DarkModeImageCache> dark_mode_image_cache_;
- DISALLOW_COPY_AND_ASSIGN(Image);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc b/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc
index 264ff541c50..666adedb4fd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc
@@ -40,6 +40,8 @@ class ExternalMemoryAllocator final : public SkBitmap::Allocator {
void* pixels,
size_t row_bytes)
: info_(info), pixels_(pixels), row_bytes_(row_bytes) {}
+ ExternalMemoryAllocator(const ExternalMemoryAllocator&) = delete;
+ ExternalMemoryAllocator& operator=(const ExternalMemoryAllocator&) = delete;
bool allocPixelRef(SkBitmap* dst) override {
const SkImageInfo& info = dst->info();
@@ -56,8 +58,6 @@ class ExternalMemoryAllocator final : public SkBitmap::Allocator {
SkImageInfo info_;
void* pixels_;
size_t row_bytes_;
-
- DISALLOW_COPY_AND_ASSIGN(ExternalMemoryAllocator);
};
} // namespace
@@ -69,7 +69,7 @@ ImageDecoderWrapper::ImageDecoderWrapper(
ImageDecoder::AlphaOption alpha_option,
ColorBehavior decoder_color_behavior,
ImageDecoder::HighBitDepthDecodingOption decoding_option,
- size_t index,
+ wtf_size_t index,
const SkImageInfo& info,
void* pixels,
size_t row_bytes,
@@ -91,7 +91,7 @@ ImageDecoderWrapper::ImageDecoderWrapper(
ImageDecoderWrapper::~ImageDecoderWrapper() = default;
bool ImageDecoderWrapper::Decode(ImageDecoderFactory* factory,
- size_t* frame_count,
+ wtf_size_t* frame_count,
bool* has_alpha) {
DCHECK(frame_count);
DCHECK(has_alpha);
@@ -201,7 +201,7 @@ bool ImageDecoderWrapper::Decode(ImageDecoderFactory* factory,
}
bool ImageDecoderWrapper::ShouldDecodeToExternalMemory(
- size_t frame_count,
+ wtf_size_t frame_count,
bool resume_decoding) const {
// Some multi-frame images need their decode cached in the decoder to allow
// future frames to reference previous frames.
@@ -261,7 +261,7 @@ bool ImageDecoderWrapper::ShouldRemoveDecoder(
void ImageDecoderWrapper::PurgeAllFramesIfNecessary(
ImageDecoder* decoder,
bool frame_was_completely_decoded,
- size_t frame_count) const {
+ wtf_size_t frame_count) const {
// We only purge all frames when we have decoded the last frame for a
// multi-frame image. This is because once the last frame is decoded, the
// animation will loop back to the first frame which does not need the last
@@ -276,7 +276,7 @@ void ImageDecoderWrapper::PurgeAllFramesIfNecessary(
if (!frame_was_completely_decoded)
return;
- const size_t last_frame_index = frame_count - 1;
+ const wtf_size_t last_frame_index = frame_count - 1;
if (frame_index_ == last_frame_index)
decoder->ClearCacheExceptFrame(kNotFound);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h b/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h
index dd83a7a75ea..0f857c874ca 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h
@@ -25,7 +25,7 @@ class ImageDecoderWrapper {
ImageDecoder::AlphaOption alpha_option,
ColorBehavior decoder_color_behavior,
ImageDecoder::HighBitDepthDecodingOption decoding_option,
- size_t index,
+ wtf_size_t index,
const SkImageInfo& info,
void* pixels,
size_t row_bytes,
@@ -35,20 +35,20 @@ class ImageDecoderWrapper {
// Returns true if the decode succeeded.
bool Decode(ImageDecoderFactory* factory,
- size_t* frame_count,
+ wtf_size_t* frame_count,
bool* has_alpha);
// Indicates that the decode failed due to a corrupt image.
bool decode_failed() const { return decode_failed_; }
private:
- bool ShouldDecodeToExternalMemory(size_t frame_count,
+ bool ShouldDecodeToExternalMemory(wtf_size_t frame_count,
bool has_cached_decoder) const;
bool ShouldRemoveDecoder(bool frame_was_completely_decoded,
bool decoded_to_external_memory) const;
void PurgeAllFramesIfNecessary(ImageDecoder* decoder,
bool frame_was_completely_decoded,
- size_t frame_count) const;
+ wtf_size_t frame_count) const;
std::unique_ptr<ImageDecoder> CreateDecoderWithData(
ImageDecoderFactory* factory) const;
@@ -58,7 +58,7 @@ class ImageDecoderWrapper {
const ImageDecoder::AlphaOption alpha_option_;
const ColorBehavior decoder_color_behavior_;
const ImageDecoder::HighBitDepthDecodingOption decoding_option_;
- const size_t frame_index_;
+ const wtf_size_t frame_index_;
const SkImageInfo info_;
void* pixels_;
const size_t row_bytes_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.cc b/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.cc
index 6a899799638..17fbeba5460 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.cc
@@ -320,7 +320,7 @@ void ImageDecodingStore::RemoveCacheIndexedByGeneratorInternal(
CopyToVector(iter->value, cache_identifier_list);
// For each cache identifier find the corresponding CacheEntry and remove it.
- for (size_t i = 0; i < cache_identifier_list.size(); ++i) {
+ for (wtf_size_t i = 0; i < cache_identifier_list.size(); ++i) {
DCHECK(cache_map->Contains(cache_identifier_list[i]));
const auto& cache_entry = cache_map->at(cache_identifier_list[i]);
DCHECK(!cache_entry->UseCount());
@@ -332,8 +332,8 @@ void ImageDecodingStore::RemoveCacheIndexedByGeneratorInternal(
void ImageDecodingStore::RemoveFromCacheListInternal(
const Vector<std::unique_ptr<CacheEntry>>& deletion_list) {
mutex_.AssertAcquired();
- for (size_t i = 0; i < deletion_list.size(); ++i)
- ordered_cache_list_.Remove(deletion_list[i].get());
+ for (const auto& entry : deletion_list)
+ ordered_cache_list_.Remove(entry.get());
}
} // namespace blink
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 99d17c19138..fabf851a878 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
@@ -29,7 +29,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ptr_util.h"
#include "cc/paint/paint_image_generator.h"
@@ -89,6 +88,8 @@ class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
use_count_(use_count),
prev_(nullptr),
next_(nullptr) {}
+ CacheEntry(const CacheEntry&) = delete;
+ CacheEntry& operator=(const CacheEntry&) = delete;
virtual ~CacheEntry() { DCHECK(!use_count_); }
@@ -112,8 +113,6 @@ class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
private:
CacheEntry* prev_;
CacheEntry* next_;
-
- DISALLOW_COPY_AND_ASSIGN(CacheEntry);
};
class DecoderCacheEntry final : public CacheEntry {
@@ -245,6 +244,8 @@ class PLATFORM_EXPORT ImageDecodingStore final {
public:
ImageDecodingStore();
+ ImageDecodingStore(const ImageDecodingStore&) = delete;
+ ImageDecodingStore& operator=(const ImageDecodingStore&) = delete;
~ImageDecodingStore();
static ImageDecodingStore& Instance();
@@ -348,8 +349,6 @@ class PLATFORM_EXPORT ImageDecodingStore final {
// - 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_decoding_store_test.cc b/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc
index 65787e1ea0a..1cb02a86470 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc
@@ -53,11 +53,11 @@ class ImageDecodingStoreTest : public testing::Test,
ASSERT_TRUE(false);
}
- ImageFrame::Status GetStatus(size_t index) override {
+ ImageFrame::Status GetStatus(wtf_size_t index) override {
return ImageFrame::kFramePartial;
}
- size_t FrameCount() override { return 1; }
+ wtf_size_t FrameCount() override { return 1; }
int RepetitionCount() const override { return kAnimationNone; }
base::TimeDelta FrameDuration() const override { return base::TimeDelta(); }
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 d7ffcbbf486..63d56575098 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
@@ -28,7 +28,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h"
#include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
@@ -102,7 +101,7 @@ ImageFrameGenerator::~ImageFrameGenerator() {
bool ImageFrameGenerator::DecodeAndScale(
SegmentReader* data,
bool all_data_received,
- size_t index,
+ wtf_size_t index,
const SkImageInfo& info,
void* pixels,
size_t row_bytes,
@@ -128,7 +127,7 @@ bool ImageFrameGenerator::DecodeAndScale(
high_bit_depth_decoding_option = ImageDecoder::kHighBitDepthToHalfFloat;
}
- size_t frame_count = 0u;
+ wtf_size_t frame_count = 0u;
bool has_alpha = true;
// |decode_failed| indicates a failure due to a corrupt image.
@@ -168,11 +167,11 @@ bool ImageFrameGenerator::DecodeAndScale(
bool ImageFrameGenerator::DecodeToYUV(
SegmentReader* data,
- size_t index,
+ wtf_size_t index,
SkColorType color_type,
const SkISize component_sizes[cc::kNumYUVPlanes],
void* planes[cc::kNumYUVPlanes],
- const size_t row_bytes[cc::kNumYUVPlanes]) {
+ const wtf_size_t row_bytes[cc::kNumYUVPlanes]) {
MutexLocker lock(generator_mutex_);
DCHECK_EQ(index, 0u);
@@ -225,19 +224,19 @@ bool ImageFrameGenerator::DecodeToYUV(
return false;
}
-void ImageFrameGenerator::SetHasAlpha(size_t index, bool has_alpha) {
+void ImageFrameGenerator::SetHasAlpha(wtf_size_t index, bool has_alpha) {
generator_mutex_.AssertAcquired();
if (index >= has_alpha_.size()) {
- const size_t old_size = has_alpha_.size();
+ const wtf_size_t old_size = has_alpha_.size();
has_alpha_.resize(index + 1);
- for (size_t i = old_size; i < has_alpha_.size(); ++i)
+ for (wtf_size_t i = old_size; i < has_alpha_.size(); ++i)
has_alpha_[i] = true;
}
has_alpha_[index] = has_alpha;
}
-bool ImageFrameGenerator::HasAlpha(size_t index) {
+bool ImageFrameGenerator::HasAlpha(wtf_size_t index) {
MutexLocker lock(generator_mutex_);
if (index < has_alpha_.size())
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 c3e5e18c8f8..f6fb39175de 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
@@ -29,7 +29,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "cc/paint/paint_image.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
@@ -56,11 +55,10 @@ class PLATFORM_EXPORT ImageDecoderFactory {
public:
ImageDecoderFactory() = default;
+ ImageDecoderFactory(const ImageDecoderFactory&) = delete;
+ ImageDecoderFactory& operator=(const ImageDecoderFactory&) = delete;
virtual ~ImageDecoderFactory() = default;
virtual std::unique_ptr<ImageDecoder> Create() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ImageDecoderFactory);
};
class PLATFORM_EXPORT ImageFrameGenerator final
@@ -75,6 +73,8 @@ class PLATFORM_EXPORT ImageFrameGenerator final
full_size, is_multi_frame, color_behavior, std::move(supported_sizes)));
}
+ ImageFrameGenerator(const ImageFrameGenerator&) = delete;
+ ImageFrameGenerator& operator=(const ImageFrameGenerator&) = delete;
~ImageFrameGenerator();
// Decodes and scales the specified frame at |index|. The dimensions and
@@ -83,7 +83,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final
// successful.
bool DecodeAndScale(SegmentReader*,
bool all_data_received,
- size_t index,
+ wtf_size_t index,
const SkImageInfo&,
void* pixels,
size_t row_bytes,
@@ -96,11 +96,11 @@ class PLATFORM_EXPORT ImageFrameGenerator final
// ImageDecoder needs something analogous to its ImageFrame cache to hold
// partial planes, and the GPU code needs to handle them.
bool DecodeToYUV(SegmentReader*,
- size_t index,
+ wtf_size_t index,
SkColorType color_type,
const SkISize component_sizes[cc::kNumYUVPlanes],
void* planes[cc::kNumYUVPlanes],
- const size_t row_bytes[cc::kNumYUVPlanes]);
+ const wtf_size_t row_bytes[cc::kNumYUVPlanes]);
const SkISize& GetFullSize() const { return full_size_; }
@@ -112,7 +112,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final
return decode_failed_;
}
- bool HasAlpha(size_t index);
+ bool HasAlpha(wtf_size_t index);
// TODO(crbug.com/943519): Do not call unless the SkROBuffer has all the data.
bool GetYUVAInfo(
@@ -148,7 +148,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final
image_decoder_factory_ = std::move(factory);
}
- void SetHasAlpha(size_t index, bool has_alpha);
+ void SetHasAlpha(wtf_size_t index, bool has_alpha);
const SkISize full_size_;
// Parameters used to create internal ImageDecoder objects.
@@ -159,7 +159,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final
mutable Mutex generator_mutex_;
bool decode_failed_ GUARDED_BY(generator_mutex_) = false;
bool yuv_decoding_failed_ GUARDED_BY(generator_mutex_) = false;
- size_t frame_count_ GUARDED_BY(generator_mutex_) = 0u;
+ wtf_size_t frame_count_ GUARDED_BY(generator_mutex_) = 0u;
Vector<bool> has_alpha_ GUARDED_BY(generator_mutex_);
struct ClientMutex {
@@ -177,8 +177,6 @@ class PLATFORM_EXPORT ImageFrameGenerator final
mutex_map_ GUARDED_BY(generator_mutex_);
std::unique_ptr<ImageDecoderFactory> image_decoder_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageFrameGenerator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc
index ccd93e214a6..618d7cdd95e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc
@@ -82,17 +82,17 @@ class ImageFrameGeneratorTest : public testing::Test,
void MemoryAllocatorSet() override { ++memory_allocator_set_count_; }
- ImageFrame::Status GetStatus(size_t index) override {
+ ImageFrame::Status GetStatus(wtf_size_t index) override {
ImageFrame::Status current_status = status_;
status_ = next_frame_status_;
return current_status;
}
- void ClearCacheExceptFrameRequested(size_t clear_except_frame) override {
+ void ClearCacheExceptFrameRequested(wtf_size_t clear_except_frame) override {
requested_clear_except_frame_ = clear_except_frame;
}
- size_t FrameCount() override { return frame_count_; }
+ wtf_size_t FrameCount() override { return frame_count_; }
int RepetitionCount() const override {
return frame_count_ == 1 ? kAnimationNone : kAnimationLoopOnce;
}
@@ -112,7 +112,7 @@ class ImageFrameGeneratorTest : public testing::Test,
void SetNextFrameStatus(ImageFrame::Status status) {
next_frame_status_ = status;
}
- void SetFrameCount(size_t count) {
+ void SetFrameCount(wtf_size_t count) {
frame_count_ = count;
if (count > 1) {
generator_ = nullptr;
@@ -136,8 +136,8 @@ class ImageFrameGeneratorTest : public testing::Test,
int memory_allocator_set_count_;
ImageFrame::Status status_;
ImageFrame::Status next_frame_status_;
- size_t frame_count_;
- size_t requested_clear_except_frame_;
+ wtf_size_t frame_count_;
+ wtf_size_t requested_clear_except_frame_;
};
TEST_F(ImageFrameGeneratorTest, GetSupportedSizes) {
@@ -149,7 +149,7 @@ TEST_F(ImageFrameGeneratorTest, GetSupportedSizes) {
struct Test {
SkISize query_size;
- size_t supported_size_index;
+ wtf_size_t supported_size_index;
} tests[] = {{SkISize::Make(1, 1), 0}, {SkISize::Make(2, 2), 0},
{SkISize::Make(25, 10), 1}, {SkISize::Make(1, 25), 1},
{SkISize::Make(50, 51), 2}, {SkISize::Make(80, 80), 3},
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 689a8554be5..9d26ce56371 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
@@ -44,6 +44,10 @@ class InterceptingCanvasBase : public SkCanvas {
class CanvasInterceptorBase {
STACK_ALLOCATED();
+ public:
+ CanvasInterceptorBase(const CanvasInterceptorBase&) = delete;
+ CanvasInterceptorBase& operator=(const CanvasInterceptorBase&) = delete;
+
protected:
CanvasInterceptorBase(InterceptingCanvasBase* canvas) : canvas_(canvas) {
++canvas_->call_nesting_depth_;
@@ -58,11 +62,11 @@ 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);
};
+ InterceptingCanvasBase(const InterceptingCanvasBase&) = delete;
+ InterceptingCanvasBase& operator=(const InterceptingCanvasBase&) = delete;
+
void ResetStepCount() { call_count_ = 0; }
protected:
@@ -130,8 +134,6 @@ 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 7fd1da947c2..d499b0e6df6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -32,8 +32,8 @@
#include <unicode/unistr.h>
+#include "base/cxx17_backports.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -271,22 +271,6 @@ String StringForSkPaintFlags(const SkPaint& paint) {
return flags_string.ToString();
}
-String FilterQualityName(SkFilterQuality filter_quality) {
- switch (filter_quality) {
- case kNone_SkFilterQuality:
- return "None";
- case kLow_SkFilterQuality:
- return "Low";
- case kMedium_SkFilterQuality:
- return "Medium";
- case kHigh_SkFilterQuality:
- return "High";
- default:
- NOTREACHED();
- return "?";
- };
-}
-
String StrokeCapName(SkPaint::Cap cap) {
switch (cap) {
case SkPaint::kButt_Cap:
@@ -335,13 +319,14 @@ std::unique_ptr<JSONObject> ObjectForSkPaint(const SkPaint& paint) {
paint_item->SetDouble("strokeWidth", paint.getStrokeWidth());
paint_item->SetDouble("strokeMiter", paint.getStrokeMiter());
paint_item->SetString("flags", StringForSkPaintFlags(paint));
- paint_item->SetString("filterLevel",
- FilterQualityName(paint.getFilterQuality()));
paint_item->SetString("strokeCap", StrokeCapName(paint.getStrokeCap()));
paint_item->SetString("strokeJoin", StrokeJoinName(paint.getStrokeJoin()));
paint_item->SetString("styleName", StyleName(paint.getStyle()));
- if (paint.getBlendMode() != SkBlendMode::kSrcOver)
- paint_item->SetString("blendMode", SkBlendMode_Name(paint.getBlendMode()));
+ const auto bm = paint.asBlendMode();
+ if (bm != SkBlendMode::kSrcOver) {
+ paint_item->SetString("blendMode",
+ bm ? SkBlendMode_Name(bm.value()) : "custom");
+ }
if (paint.getImageFilter())
paint_item->SetString("imageFilter", "SkImageFilter");
return paint_item;
@@ -358,6 +343,41 @@ String ClipOpName(SkClipOp op) {
};
}
+String FilterModeName(SkFilterMode fm) {
+ switch (fm) {
+ case SkFilterMode::kNearest:
+ return "kNearest";
+ case SkFilterMode::kLinear:
+ return "kLinear";
+ }
+ return "not reachable";
+}
+
+String MipmapModeName(SkMipmapMode mm) {
+ switch (mm) {
+ case SkMipmapMode::kNone:
+ return "kNone";
+ case SkMipmapMode::kNearest:
+ return "kNearest";
+ case SkMipmapMode::kLinear:
+ return "kLinear";
+ }
+ return "not reachable";
+}
+
+std::unique_ptr<JSONObject> ObjectForSkSamplingOptions(
+ const SkSamplingOptions& sampling) {
+ auto sampling_item = std::make_unique<JSONObject>();
+ if (sampling.useCubic) {
+ sampling_item->SetDouble("B", sampling.cubic.B);
+ sampling_item->SetDouble("C", sampling.cubic.C);
+ } else {
+ sampling_item->SetString("filter", FilterModeName(sampling.filter));
+ sampling_item->SetString("mipmap", MipmapModeName(sampling.mipmap));
+ }
+ return sampling_item;
+}
+
} // namespace
class AutoLogger
@@ -455,6 +475,7 @@ void LoggingCanvas::onDrawImage2(const SkImage* image,
JSONObject* params = logger.LogItemWithParams("drawImage");
params->SetDouble("left", left);
params->SetDouble("top", top);
+ params->SetObject("sampling", ObjectForSkSamplingOptions(sampling));
params->SetObject("image", ObjectForSkImage(image));
if (paint)
params->SetObject("paint", ObjectForSkPaint(*paint));
@@ -472,6 +493,7 @@ void LoggingCanvas::onDrawImageRect2(const SkImage* image,
params->SetObject("image", ObjectForSkImage(image));
params->SetObject("src", ObjectForSkRect(src));
params->SetObject("dst", ObjectForSkRect(dst));
+ params->SetObject("sampling", ObjectForSkSamplingOptions(sampling));
if (paint)
params->SetObject("paint", ObjectForSkPaint(*paint));
SkCanvas::onDrawImageRect2(image, src, dst, sampling, paint, constraint);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_backing.cc b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_backing.cc
index 3001841e465..23d002f6d48 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_backing.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_backing.cc
@@ -73,8 +73,8 @@ sk_sp<SkImage> MailboxTextureBacking::GetSkImageViaReadback() {
gpu::raster::RasterInterface* ri =
context_provider_wrapper_->ContextProvider()->RasterInterface();
ri->ReadbackImagePixels(mailbox_, sk_image_info_,
- sk_image_info_.minRowBytes(), 0, 0,
- writable_pixels);
+ static_cast<GLuint>(sk_image_info_.minRowBytes()),
+ 0, 0, writable_pixels);
return SkImage::MakeRasterData(sk_image_info_, std::move(image_pixels),
sk_image_info_.minRowBytes());
@@ -96,7 +96,8 @@ bool MailboxTextureBacking::readPixels(const SkImageInfo& dst_info,
gpu::raster::RasterInterface* ri =
context_provider_wrapper_->ContextProvider()->RasterInterface();
- ri->ReadbackImagePixels(mailbox_, dst_info, dst_info.minRowBytes(), src_x,
+ ri->ReadbackImagePixels(mailbox_, dst_info,
+ static_cast<GLuint>(dst_info.minRowBytes()), src_x,
src_y, dst_pixels);
return true;
} else if (sk_image_) {
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 ec71cc26ec5..6719df6340f 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
@@ -42,7 +42,7 @@ void SetSuspendAnimation(
void UpdateDispatcherFilterQuality(
base::WeakPtr<blink::CanvasResourceDispatcher> dispatcher,
- SkFilterQuality filter) {
+ cc::PaintFlags::FilterQuality filter) {
if (dispatcher) {
dispatcher->SetFilterQuality(filter);
}
@@ -86,7 +86,7 @@ void OffscreenCanvasPlaceholder::SetOffscreenCanvasDispatcher(
// quality before this function. We need to first apply the filter changes to
// the corresponding offscreen canvas.
if (filter_quality_) {
- SkFilterQuality quality = filter_quality_.value();
+ cc::PaintFlags::FilterQuality quality = filter_quality_.value();
filter_quality_ = absl::nullopt;
UpdateOffscreenCanvasFilterQuality(quality);
}
@@ -107,7 +107,7 @@ void OffscreenCanvasPlaceholder::ReleaseOffscreenCanvasFrame() {
}
void OffscreenCanvasPlaceholder::UpdateOffscreenCanvasFilterQuality(
- SkFilterQuality filter_quality) {
+ cc::PaintFlags::FilterQuality filter_quality) {
DCHECK(IsOffscreenCanvasRegistered());
if (!frame_dispatcher_task_runner_) {
filter_quality_ = filter_quality;
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 4c4c10f5dba..7aa5bbf9654 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
@@ -8,11 +8,11 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "cc/paint/paint_flags.h"
#include "components/viz/common/resources/resource_id.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
namespace blink {
@@ -48,7 +48,8 @@ class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
return placeholder_id_ != kNoPlaceholderId;
}
- void UpdateOffscreenCanvasFilterQuality(SkFilterQuality filter_quality);
+ void UpdateOffscreenCanvasFilterQuality(
+ cc::PaintFlags::FilterQuality filter_quality);
virtual bool HasCanvasCapture() const { return false; }
@@ -73,7 +74,7 @@ class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
kShouldActivateAnimation,
};
AnimationState animation_state_ = kActiveAnimation;
- absl::optional<SkFilterQuality> filter_quality_ = absl::nullopt;
+ absl::optional<cc::PaintFlags::FilterQuality> filter_quality_ = absl::nullopt;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
index fa374876259..549d69fac4b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
@@ -80,17 +80,6 @@ void CullRect::Move(const FloatSize& offset) {
}
void CullRect::ApplyTransform(const TransformPaintPropertyNode& transform) {
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
- transform.ScrollNode()) {
- // TODO(wangxianzhu): Remove this code path for CullRectUpdate.
- ApplyScrollTranslation(transform, transform);
- } else {
- ApplyTransformWithoutExpansion(transform);
- }
-}
-
-void CullRect::ApplyTransformWithoutExpansion(
- const TransformPaintPropertyNode& transform) {
if (IsInfinite())
return;
@@ -112,7 +101,7 @@ CullRect::ApplyTransformResult CullRect::ApplyScrollTranslation(
if (rect_.IsEmpty())
return kNotExpanded;
- ApplyTransformWithoutExpansion(scroll_translation);
+ ApplyTransform(scroll_translation);
// Don't expand for non-composited scrolling.
if (!scroll_translation.HasDirectCompositingReasons())
@@ -132,56 +121,15 @@ CullRect::ApplyTransformResult CullRect::ApplyScrollTranslation(
: kExpandedForPartialScrollingContents;
}
-void CullRect::ApplyTransforms(const TransformPaintPropertyNode& source,
- const TransformPaintPropertyNode& destination,
- const absl::optional<CullRect>& old_cull_rect) {
- DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
-
- Vector<const TransformPaintPropertyNode*> scroll_translations;
- for (const auto* t = &destination; t != &source; t = t->UnaliasedParent()) {
- if (!t) {
- // |source| is not an ancestor of |destination|. Simply map.
- if (!IsInfinite())
- GeometryMapper::SourceToDestinationRect(source, destination, rect_);
- return;
- }
- if (t->ScrollNode())
- scroll_translations.push_back(t);
- }
-
- const auto* last_transform = &source;
- ApplyTransformResult last_scroll_translation_result = kNotExpanded;
- for (auto it = scroll_translations.rbegin(); it != scroll_translations.rend();
- ++it) {
- const auto* scroll_translation = *it;
- if (!IsInfinite()) {
- DCHECK(scroll_translation->Parent());
- GeometryMapper::SourceToDestinationRect(
- *last_transform, *scroll_translation->Parent(), rect_);
- }
- last_scroll_translation_result =
- ApplyScrollTranslation(source, *scroll_translation);
- last_transform = scroll_translation;
- }
-
- if (!IsInfinite()) {
- GeometryMapper::SourceToDestinationRect(*last_transform, destination,
- rect_);
- }
-
- if (last_scroll_translation_result == kExpandedForPartialScrollingContents &&
- old_cull_rect &&
- !ChangedEnough(*old_cull_rect,
- &last_transform->ScrollNode()->ContentsSize())) {
- rect_ = old_cull_rect->Rect();
- }
-}
-
bool CullRect::ApplyPaintPropertiesWithoutExpansion(
const PropertyTreeState& source,
const PropertyTreeState& destination) {
FloatClipRect clip_rect =
GeometryMapper::LocalToAncestorClipRect(destination, source);
+ if (clip_rect.Rect().IsEmpty()) {
+ rect_ = IntRect();
+ return false;
+ }
if (!clip_rect.IsInfinite()) {
rect_.Intersect(EnclosingIntRect(clip_rect.Rect()));
if (rect_.IsEmpty())
@@ -248,27 +196,39 @@ bool CullRect::ApplyPaintProperties(
// this class. The client has to use infinite cull rect in the case.
// TODO(wangxianzhu): support clip rect expansion for pixel-moving filters.
const auto& effect_root = EffectPaintPropertyNode::Root();
- auto scroll_translation_it = scroll_translations.rbegin();
- for (const auto* clip : base::Reversed(clips)) {
- if (scroll_translation_it == scroll_translations.rend())
+ auto clip_it = clips.rbegin();
+ for (const auto* scroll_translation : base::Reversed(scroll_translations)) {
+ if (clip_it == clips.rend())
break;
- const auto* scroll_translation = *scroll_translation_it;
- if (&clip->LocalTransformSpace() != scroll_translation->Parent())
- continue;
- ++scroll_translation_it;
+ // Skip clips until we find one in the same space as |scroll_translation|.
+ while (clip_it != clips.rend() &&
+ &(*clip_it)->LocalTransformSpace() != scroll_translation->Parent()) {
+ clip_it++;
+ }
- if (!ApplyPaintPropertiesWithoutExpansion(
- PropertyTreeState(*last_transform, *last_clip, effect_root),
- PropertyTreeState(*scroll_translation->UnaliasedParent(), *clip,
- effect_root)))
- return false;
+ // Find the last clip in the same space as |scroll_translation|.
+ const ClipPaintPropertyNode* updated_last_clip = nullptr;
+ while (clip_it != clips.rend() &&
+ &(*clip_it)->LocalTransformSpace() == scroll_translation->Parent()) {
+ updated_last_clip = *clip_it;
+ clip_it++;
+ }
+
+ // Process all clips in the same space as |scroll_translation|.
+ if (updated_last_clip) {
+ if (!ApplyPaintPropertiesWithoutExpansion(
+ PropertyTreeState(*last_transform, *last_clip, effect_root),
+ PropertyTreeState(*scroll_translation->UnaliasedParent(),
+ *updated_last_clip, effect_root))) {
+ return false;
+ }
+ last_clip = updated_last_clip;
+ }
last_scroll_translation_result =
ApplyScrollTranslation(root.Transform(), *scroll_translation);
-
last_transform = scroll_translation;
- last_clip = clip;
}
if (!ApplyPaintPropertiesWithoutExpansion(
@@ -276,6 +236,9 @@ bool CullRect::ApplyPaintProperties(
destination))
return false;
+ if (IsInfinite())
+ return false;
+
// Since the cull rect mapping above can produce extremely large numbers in
// cases of perspective, try our best to "normalize" the result by ensuring
// that none of the rect dimensions exceed some large, but reasonable, limit.
@@ -292,15 +255,29 @@ bool CullRect::ApplyPaintProperties(
if (rect_.MaxY() > kReasonablePixelLimit)
rect_.ShiftMaxYEdgeTo(kReasonablePixelLimit);
- const IntSize* expansion_bounds = nullptr;
+ absl::optional<IntRect> expansion_bounds;
bool expanded = false;
- if (last_scroll_translation_result == kExpandedForPartialScrollingContents &&
- last_clip == &destination.Clip()) {
+ if (last_scroll_translation_result == kExpandedForPartialScrollingContents) {
DCHECK(last_transform->ScrollNode());
- expansion_bounds = &last_transform->ScrollNode()->ContentsSize();
+ expansion_bounds.emplace(IntPoint(),
+ last_transform->ScrollNode()->ContentsSize());
+ if (last_transform != &destination.Transform() ||
+ last_clip != &destination.Clip()) {
+ // Map expansion_bounds in the same way as we did for rect_ in the last
+ // ApplyPaintPropertiesWithoutExpansion().
+ FloatClipRect clip_rect = GeometryMapper::LocalToAncestorClipRect(
+ destination,
+ PropertyTreeState(*last_transform, *last_clip, effect_root));
+ if (!clip_rect.IsInfinite())
+ expansion_bounds->Intersect(EnclosingIntRect(clip_rect.Rect()));
+ GeometryMapper::SourceToDestinationRect(
+ *last_transform, destination.Transform(), *expansion_bounds);
+ }
expanded = true;
- } else if (!IsInfinite() && last_transform != &destination.Transform() &&
- destination.Transform().RequiresCullRectExpansion()) {
+ }
+
+ if (last_transform != &destination.Transform() &&
+ destination.Transform().RequiresCullRectExpansion()) {
// Direct compositing reasons such as will-change transform can cause the
// content to move arbitrarily, so there is no exact cull rect. Instead of
// using an infinite rect, we use a heuristic of expanding by
@@ -311,10 +288,14 @@ bool CullRect::ApplyPaintProperties(
LocalPixelDistanceToExpand(root.Transform(), destination.Transform());
if (rect_.Width() < pixel_distance_to_expand) {
rect_.InflateX(pixel_distance_to_expand);
+ if (expansion_bounds)
+ expansion_bounds->InflateX(pixel_distance_to_expand);
expanded = true;
}
if (rect_.Height() < pixel_distance_to_expand) {
rect_.InflateY(pixel_distance_to_expand);
+ if (expansion_bounds)
+ expansion_bounds->InflateY(pixel_distance_to_expand);
expanded = true;
}
}
@@ -326,8 +307,9 @@ bool CullRect::ApplyPaintProperties(
return expanded;
}
-bool CullRect::ChangedEnough(const CullRect& old_cull_rect,
- const IntSize* expansion_bounds) const {
+bool CullRect::ChangedEnough(
+ const CullRect& old_cull_rect,
+ const absl::optional<IntRect>& expansion_bounds) const {
DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
RuntimeEnabledFeatures::CullRectUpdateEnabled());
@@ -353,7 +335,7 @@ bool CullRect::ChangedEnough(const CullRect& old_cull_rect,
return false;
// The cull rect must have been clipped by *expansion_bounds.
- DCHECK(IntRect(IntPoint(), *expansion_bounds).Contains(rect_));
+ DCHECK(expansion_bounds->Contains(rect_));
// Even if the new cull rect doesn't include enough new area to satisfy
// the condition above, update anyway if it touches the edge of the scrolling
@@ -366,15 +348,17 @@ bool CullRect::ChangedEnough(const CullRect& old_cull_rect,
// A new rect of 0,0 100x8000 will not be |kChangedEnoughMinimumDistance|
// pixels away from the current rect. Without additional logic for this case,
// we will continue using the old cull rect.
- if (rect_.X() == 0 && old_cull_rect.Rect().X() != 0)
+ if (rect_.X() == expansion_bounds->X() &&
+ old_cull_rect.Rect().X() != expansion_bounds->X())
return true;
- if (rect_.Y() == 0 && old_cull_rect.Rect().Y() != 0)
+ if (rect_.Y() == expansion_bounds->Y() &&
+ old_cull_rect.Rect().Y() != expansion_bounds->Y())
return true;
- if (rect_.MaxX() == expansion_bounds->Width() &&
- old_cull_rect.Rect().MaxX() != expansion_bounds->Width())
+ if (rect_.MaxX() == expansion_bounds->MaxX() &&
+ old_cull_rect.Rect().MaxX() != expansion_bounds->MaxX())
return true;
- if (rect_.MaxY() == expansion_bounds->Height() &&
- old_cull_rect.Rect().MaxY() != expansion_bounds->Height())
+ if (rect_.MaxY() == expansion_bounds->MaxY() &&
+ old_cull_rect.Rect().MaxY() != expansion_bounds->MaxY())
return true;
return false;
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 6f069f7fc59..74ef50fd0fd 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CULL_RECT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CULL_RECT_H_
+#include "third_party/abseil-cpp/absl/types/optional.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/wtf/allocator/allocator.h"
@@ -43,27 +44,8 @@ class PLATFORM_EXPORT CullRect {
// Applies one transform to the cull rect. Before this function is called,
// the cull rect is in the space of the parent the transform node.
- // For CompositeAfterPaint, when the transform is a scroll translation, the
- // cull rect is converted in the following steps:
- // 1. it's clipped by the container rect,
- // 2. transformed by inverse of the scroll translation,
- // 3. expanded by thousands of pixels for composited scrolling.
- // 4. clipped by the contents rect.
- // TODO(wangxianzhu): Remove this function for CullRectUpdate.
void ApplyTransform(const TransformPaintPropertyNode&);
- // For CompositeAfterPaint only. Applies transforms from |source| (not
- // included) to |destination| (included). For each scroll translation, the
- // cull rect is converted as described in ApplyTransform(). If |old_cull_rect|
- // is provided, and the cull rect converted by the last scroll translation
- // doesn't cover the whole scrolling contents, and the new cull rect doesn't
- // change enough (by hundreds of pixels) from |old_cull_rect|, the cull rect
- // will be set to |old_cull_rect| to avoid repaint on each composited scroll.
- // TODO(wangxianzhu): Remove this function for CullRectUpdate.
- void ApplyTransforms(const TransformPaintPropertyNode& source,
- const TransformPaintPropertyNode& destination,
- const absl::optional<CullRect>& old_cull_rect);
-
// For CullRectUpdate only. Similar to the above but also applies clips and
// expands for all directly composited transforms (including scrolling and
// non-scrolling ones). |root| is used to calculate the expansion distance in
@@ -99,7 +81,6 @@ class PLATFORM_EXPORT CullRect {
const TransformPaintPropertyNode& root_transform,
const TransformPaintPropertyNode& scroll_translation);
- void ApplyTransformWithoutExpansion(const TransformPaintPropertyNode&);
// Returns false if the rect is clipped to be invisible. Otherwise returns
// true, even if the cull rect is empty due to a special 3d transform in case
// later 3d transforms make the cull rect visible again.
@@ -108,7 +89,7 @@ class PLATFORM_EXPORT CullRect {
const PropertyTreeState& destination);
bool ChangedEnough(const CullRect& old_cull_rect,
- const IntSize* bounds) const;
+ const absl::optional<IntRect>& expansion_bounds) const;
IntRect rect_;
};
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 39461edd906..3b08142304b 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
@@ -40,7 +40,7 @@ class CullRectTest : public testing::Test {
bool ChangedEnough(const IntRect& old_rect,
const IntRect& new_rect,
- const IntSize* bounds = nullptr) {
+ const absl::optional<IntRect>& bounds = absl::nullopt) {
return CullRect(new_rect).ChangedEnough(CullRect(old_rect), bounds);
}
};
@@ -305,34 +305,62 @@ TEST_F(CullRectTest, ChangedEnoughOnMovement) {
TEST_F(CullRectTest, ChangedEnoughNewRectTouchingEdge) {
ScopedCullRectUpdateForTest cull_rect_update(true);
- IntSize bounds(500, 500);
+ IntRect bounds(0, 0, 500, 500);
IntRect old_rect(100, 100, 100, 100);
// Top edge.
- EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 50, 100, 200), &bounds));
- EXPECT_TRUE(ChangedEnough(old_rect, IntRect(100, 0, 100, 200), &bounds));
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 50, 100, 200), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(100, 0, 100, 200), bounds));
// Left edge.
- EXPECT_FALSE(ChangedEnough(old_rect, IntRect(50, 100, 200, 100), &bounds));
- EXPECT_TRUE(ChangedEnough(old_rect, IntRect(0, 100, 200, 100), &bounds));
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(50, 100, 200, 100), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(0, 100, 200, 100), bounds));
// Bottom edge.
- EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 100, 100, 350), &bounds));
- EXPECT_TRUE(ChangedEnough(old_rect, IntRect(100, 100, 100, 400), &bounds));
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 100, 100, 350), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(100, 100, 100, 400), bounds));
// Right edge.
- EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 100, 350, 100), &bounds));
- EXPECT_TRUE(ChangedEnough(old_rect, IntRect(100, 100, 400, 100), &bounds));
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 100, 350, 100), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(100, 100, 400, 100), bounds));
+
+ // With offset.
+ bounds.Move(-100, 100);
+ old_rect.Move(-100, 100);
+ // Top edge.
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(0, 150, 100, 200), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(0, 100, 100, 200), bounds));
+ // Left edge.
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(-50, 200, 200, 100), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(-100, 200, 200, 100), bounds));
+ // Bottom edge.
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(0, 200, 100, 350), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(0, 200, 100, 400), bounds));
+ // Right edge.
+ EXPECT_FALSE(ChangedEnough(old_rect, IntRect(0, 200, 350, 100), bounds));
+ EXPECT_TRUE(ChangedEnough(old_rect, IntRect(0, 200, 400, 100), bounds));
}
TEST_F(CullRectTest, ChangedEnoughOldRectTouchingEdge) {
ScopedCullRectUpdateForTest cull_rect_update(true);
- IntSize bounds(500, 500);
+ IntRect bounds(0, 0, 500, 500);
IntRect new_rect(100, 100, 300, 300);
// Top edge.
- EXPECT_FALSE(ChangedEnough(IntRect(100, 0, 100, 100), new_rect, &bounds));
+ EXPECT_FALSE(ChangedEnough(IntRect(100, 0, 100, 100), new_rect, bounds));
+ // Left edge.
+ EXPECT_FALSE(ChangedEnough(IntRect(0, 100, 100, 100), new_rect, bounds));
+ // Bottom edge.
+ EXPECT_FALSE(ChangedEnough(IntRect(300, 400, 100, 100), new_rect, bounds));
+ // Right edge.
+ EXPECT_FALSE(ChangedEnough(IntRect(400, 300, 100, 100), new_rect, bounds));
+
+ // With offset.
+ bounds.Move(-100, 100);
+ new_rect.Move(-100, 100);
+ // Top edge.
+ EXPECT_FALSE(ChangedEnough(IntRect(0, 100, 100, 100), new_rect, bounds));
// Left edge.
- EXPECT_FALSE(ChangedEnough(IntRect(0, 100, 100, 100), new_rect, &bounds));
+ EXPECT_FALSE(ChangedEnough(IntRect(-100, 0, 100, 100), new_rect, bounds));
// Bottom edge.
- EXPECT_FALSE(ChangedEnough(IntRect(300, 400, 100, 100), new_rect, &bounds));
+ EXPECT_FALSE(ChangedEnough(IntRect(200, 500, 100, 100), new_rect, bounds));
// Right edge.
- EXPECT_FALSE(ChangedEnough(IntRect(400, 300, 100, 100), new_rect, &bounds));
+ EXPECT_FALSE(ChangedEnough(IntRect(300, 400, 100, 100), new_rect, bounds));
}
TEST_F(CullRectTest, ApplyPaintPropertiesSameState) {
@@ -393,7 +421,7 @@ TEST_F(CullRectTest, ApplyPaintPropertiesWithoutClipScroll) {
EXPECT_TRUE(infinite.IsInfinite());
}
-TEST_F(CullRectTest, ApplyTransformsSingleScrollWholeScrollingContents) {
+TEST_F(CullRectTest, SingleScrollWholeScrollingContents) {
ScopedCullRectUpdateForTest cull_rect_update(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
@@ -436,10 +464,10 @@ TEST_F(CullRectTest, ApplyTransformsWithOrigin) {
EXPECT_EQ(IntRect(-50, -100, 100, 400), cull_rect1.Rect());
}
-TEST_F(CullRectTest, ApplyTransformsSingleScrollPartialScrollingContents) {
+TEST_F(CullRectTest, SingleScrollPartialScrollingContents) {
ScopedCullRectUpdateForTest cull_rect_update(true);
- auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
+ auto t1 = Create2DTranslation(t0(), 1, 2);
PropertyTreeState state1(*t1, c0(), e0());
auto ref_scroll_translation_state = CreateCompositedScrollTranslationState(
@@ -475,7 +503,45 @@ TEST_F(CullRectTest, ApplyTransformsSingleScrollPartialScrollingContents) {
EXPECT_EQ(IntRect(0, 1010, 7060, 6990), cull_rect4.Rect());
}
-TEST_F(CullRectTest, ApplyTransformsEscapingScroll) {
+TEST_F(CullRectTest, TransformUnderScrollTranslation) {
+ ScopedCullRectUpdateForTest cull_rect_update(true);
+
+ auto t1 = Create2DTranslation(t0(), 1, 2);
+ PropertyTreeState state1(*t1, c0(), e0());
+ auto scroll_translation_state = CreateCompositedScrollTranslationState(
+ state1, -3000, -5000, IntRect(20, 10, 40, 50), IntSize(8000, 8000));
+ auto t2 =
+ Create2DTranslation(scroll_translation_state.Transform(), 2000, 3000);
+ PropertyTreeState state2 =
+ scroll_translation_state.GetPropertyTreeState().Unalias();
+ state2.SetTransform(*t2);
+
+ // Cases below are the same as those in SingleScrollPartialScrollingContents,
+ // except that the offset is adjusted with |t2|.
+ CullRect cull_rect1(IntRect(0, 0, 50, 100));
+ cull_rect1.ApplyPaintProperties(state1, state1, state2, absl::nullopt);
+ EXPECT_EQ(IntRect(-2000, -1990, 7050, 6990), cull_rect1.Rect());
+
+ CullRect old_cull_rect(IntRect(-2000, -1900, 7050, 6900));
+ CullRect cull_rect2(IntRect(0, 0, 50, 100));
+ // Use old_cull_rect if the new cull rect didn't change enough.
+ cull_rect2.ApplyPaintProperties(state1, state1, state2, old_cull_rect);
+ EXPECT_EQ(old_cull_rect, cull_rect2);
+
+ old_cull_rect.Move(IntSize(1000, 1000));
+ CullRect cull_rect3(IntRect(0, 0, 50, 100));
+ // Use the new cull rect if it changed enough.
+ cull_rect3.ApplyPaintProperties(state1, state1, state2, old_cull_rect);
+ EXPECT_EQ(cull_rect1, cull_rect3);
+
+ CullRect cull_rect4 = CullRect::Infinite();
+ cull_rect4.ApplyPaintProperties(state1, state1, state2, absl::nullopt);
+ // This result differs from the first result in height (7050 vs 7060)
+ // because it's not clipped by the infinite input cull rect.
+ EXPECT_EQ(IntRect(-2000, -1990, 7060, 6990), cull_rect4.Rect());
+}
+
+TEST_F(CullRectTest, TransformEscapingScroll) {
ScopedCullRectUpdateForTest cull_rect_update(true);
PropertyTreeState root = PropertyTreeState::Root();
@@ -510,7 +576,7 @@ TEST_F(CullRectTest, ApplyTransformsEscapingScroll) {
EXPECT_EQ(cull_rect1, cull_rect3);
}
-TEST_F(CullRectTest, ApplyTransformsSmallScrollContentsAfterBigScrollContents) {
+TEST_F(CullRectTest, SmallScrollContentsAfterBigScrollContents) {
ScopedCullRectUpdateForTest cull_rect_update(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
@@ -544,7 +610,7 @@ TEST_F(CullRectTest, ApplyTransformsSmallScrollContentsAfterBigScrollContents) {
EXPECT_EQ(cull_rect1, cull_rect2);
}
-TEST_F(CullRectTest, ApplyTransformsBigScrollContentsAfterSmallScrollContents) {
+TEST_F(CullRectTest, BigScrollContentsAfterSmallScrollContents) {
ScopedCullRectUpdateForTest cull_rect_update(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
@@ -664,7 +730,7 @@ TEST_F(CullRectTest, ClipAndCompositedScrollAndClip) {
auto t1 = Create2DTranslation(t0(), 0, 10000);
auto scroll_clip = CreateClip(*c1, *t1, FloatRoundedRect(0, 0, 120, 120));
auto scroll_translation = CreateCompositedScrollTranslation(
- *t1, 0, 0, IntRect(0, 0, 120, 120), IntSize(10000, 10000));
+ *t1, 0, 0, IntRect(0, 0, 120, 120), IntSize(10000, 5000));
auto c2a = CreateClip(*scroll_clip, *scroll_translation,
FloatRoundedRect(0, 300, 100, 100));
auto c2b = CreateClip(*scroll_clip, *scroll_translation,
@@ -685,7 +751,23 @@ TEST_F(CullRectTest, ClipAndCompositedScrollAndClip) {
absl::nullopt);
EXPECT_EQ(IntRect(-4000, -3700, 8100, 8100), cull_rect.Rect());
- // c2b is out of the expansion are of the composited scroll.
+ // Using c2a with old cull rect.
+ cull_rect = CullRect::Infinite();
+ cull_rect.ApplyPaintProperties(
+ root, root, PropertyTreeState(*scroll_translation, *c2a, e0()),
+ CullRect(IntRect(0, 310, 100, 100)));
+ // The new cull rect touches the left edge of the clipped expanded scrolling
+ // contents bounds, so the old cull rect is not used.
+ EXPECT_EQ(IntRect(0, 300, 100, 100), cull_rect.Rect());
+ // Composited case. The cull rect should be expanded.
+ cull_rect = CullRect::Infinite();
+ cull_rect.ApplyPaintProperties(root, root, PropertyTreeState(*t2, *c2a, e0()),
+ CullRect(IntRect(-3900, -3700, 8100, 8100)));
+ // The new cull rect touches the left edge of the clipped expanded scrolling
+ // contents bounds, so the old cull rect is not used.
+ EXPECT_EQ(IntRect(-4000, -3700, 8100, 8100), cull_rect.Rect());
+
+ // c2b is out of the expansion area of the composited scroll.
cull_rect = CullRect::Infinite();
cull_rect.ApplyPaintProperties(
root, root, PropertyTreeState(*scroll_translation, *c2b, e0()),
@@ -698,6 +780,38 @@ TEST_F(CullRectTest, ClipAndCompositedScrollAndClip) {
EXPECT_EQ(IntRect(), cull_rect.Rect());
}
+// Test for multiple clips (e.g., overflow clip and inner border radius)
+// associated with the same scroll translation.
+TEST_F(CullRectTest, MultipleClips) {
+ ScopedCullRectUpdateForTest cull_rect_update(true);
+
+ auto t1 = Create2DTranslation(t0(), 0, 0);
+ auto scroll_translation = CreateCompositedScrollTranslation(
+ *t1, 0, 0, IntRect(0, 0, 100, 100), IntSize(100, 2000));
+ auto border_radius_clip =
+ CreateClip(c0(), *t1, FloatRoundedRect(0, 0, 100, 100));
+ auto scroll_clip =
+ CreateClip(*border_radius_clip, *t1, FloatRoundedRect(0, 0, 100, 100));
+
+ PropertyTreeState root = PropertyTreeState::Root();
+ PropertyTreeState source(*t1, c0(), e0());
+ PropertyTreeState destination(*scroll_translation, *scroll_clip, e0());
+ CullRect cull_rect(IntRect(0, 0, 800, 600));
+ cull_rect.ApplyPaintProperties(root, source, destination, absl::nullopt);
+ EXPECT_EQ(IntRect(0, 0, 100, 2000), cull_rect.Rect());
+}
+
+TEST_F(CullRectTest, ClipWithNonIntegralOffsetAndZeroSize) {
+ ScopedCullRectUpdateForTest cull_rect_update(true);
+
+ auto clip = CreateClip(c0(), t0(), FloatRoundedRect(0.4, 0.6, 0, 0));
+ PropertyTreeState source = PropertyTreeState::Root();
+ PropertyTreeState destination(t0(), *clip, e0());
+ CullRect cull_rect(IntRect(0, 0, 800, 600));
+ cull_rect.ApplyPaintProperties(source, source, destination, absl::nullopt);
+ EXPECT_TRUE(cull_rect.Rect().IsEmpty());
+}
+
TEST_F(CullRectTest, IntersectsVerticalRange) {
CullRect cull_rect(IntRect(0, 0, 50, 100));
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 536a2949185..fa928283ad1 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
@@ -37,8 +37,7 @@ bool DisplayItem::EqualsForUnderInvalidation(const DisplayItem& other) const {
if (client_ != other.client_ || type_ != other.type_ ||
fragment_ != other.fragment_ ||
raster_effect_outset_ != other.raster_effect_outset_ ||
- draws_content_ != other.draws_content_ ||
- is_cacheable_ != other.is_cacheable_)
+ draws_content_ != other.draws_content_)
return false;
if (visual_rect_ != other.visual_rect_ &&
@@ -224,7 +223,7 @@ void DisplayItem::PropertiesAsJSON(JSONObject& json,
Client().SafeDebugName(client_known_to_be_alive));
if (client_known_to_be_alive) {
json.SetString("invalidation", PaintInvalidationReasonToString(
- Client().GetPaintInvalidationReason()));
+ GetPaintInvalidationReason()));
}
json.SetString("visualRect", VisualRect().ToString());
if (GetRasterEffectOutset() != RasterEffectOutset::kNone) {
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 ab66d564a71..7d3682833e2 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
@@ -8,9 +8,12 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.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/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
+#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#if DCHECK_IS_ON()
#include "third_party/blink/renderer/platform/json/json_values.h"
@@ -152,6 +155,9 @@ class PLATFORM_EXPORT DisplayItem {
kTypeLast = kScrollbarVertical,
};
+ static_assert(kTypeLast < (1 << 8),
+ "DisplayItem::Type should fit in uint8_t");
+
DisplayItem(const DisplayItem&) = delete;
DisplayItem(DisplayItem&&) = delete;
DisplayItem& operator=(const DisplayItem&) = delete;
@@ -170,6 +176,22 @@ class PLATFORM_EXPORT DisplayItem {
const DisplayItemClient& client;
const Type type;
const wtf_size_t fragment;
+
+ struct HashKey {
+ HashKey() = default;
+ explicit HashKey(const DisplayItem::Id& id)
+ : client(&id.client), type(id.type), fragment(id.fragment) {}
+ bool operator==(const HashKey& other) const {
+ return client == other.client && type == other.type &&
+ fragment == other.fragment;
+ }
+
+ const DisplayItemClient* client = nullptr;
+ DisplayItem::Type type = static_cast<DisplayItem::Type>(0);
+ wtf_size_t fragment = 0;
+ };
+
+ HashKey AsHashKey() const { return HashKey(*this); }
};
Id GetId() const { return Id(*client_, GetType(), fragment_); }
@@ -226,8 +248,16 @@ class PLATFORM_EXPORT DisplayItem {
return type_ == kScrollbarHorizontal || type_ == kScrollbarVertical;
}
- bool IsCacheable() const { return is_cacheable_; }
- void SetUncacheable() { is_cacheable_ = false; }
+ PaintInvalidationReason GetPaintInvalidationReason() const {
+ return static_cast<PaintInvalidationReason>(paint_invalidation_reason_);
+ }
+ void SetPaintInvalidationReason(PaintInvalidationReason reason) {
+ paint_invalidation_reason_ = static_cast<unsigned>(reason);
+ }
+ bool IsCacheable() const {
+ return static_cast<PaintInvalidationReason>(paint_invalidation_reason_) !=
+ PaintInvalidationReason::kUncacheable;
+ }
bool EqualsForUnderInvalidation(const DisplayItem& other) const;
@@ -253,18 +283,19 @@ class PLATFORM_EXPORT DisplayItem {
DisplayItem(const DisplayItemClient& client,
Type type,
const IntRect& visual_rect,
+ PaintInvalidationReason paint_invalidation_reason,
bool draws_content = false)
: client_(&client),
visual_rect_(visual_rect),
fragment_(0),
+ paint_invalidation_reason_(
+ static_cast<unsigned>(paint_invalidation_reason)),
type_(type),
raster_effect_outset_(
static_cast<unsigned>(client.VisualRectOutsetForRasterEffects())),
draws_content_(draws_content),
- is_cacheable_(client.IsCacheable()),
is_not_tombstone_(true),
- known_to_be_opaque_is_set_(false),
- known_to_be_opaque_(false) {
+ opaqueness_(0) {
DCHECK_EQ(client.VisualRectOutsetForRasterEffects(),
GetRasterEffectOutset());
}
@@ -291,20 +322,20 @@ class PLATFORM_EXPORT DisplayItem {
const DisplayItemClient* client_;
IntRect visual_rect_;
wtf_size_t fragment_;
- static_assert(kTypeLast < (1 << 8),
- "DisplayItem::Type should fit in uint8_t");
+ // paint_invalidation_reason_ is set during construction (or, in the case of a
+ // DisplayItem copied from the cache, shortly thereafter). Once set, it is
+ // never modified. It is used to inform raster invalidation.
+ unsigned paint_invalidation_reason_ : 8;
unsigned type_ : 8;
unsigned raster_effect_outset_ : 2;
unsigned draws_content_ : 1;
- unsigned is_cacheable_ : 1;
// This is not |is_tombstone_| to allow memset(0) to clear a display item to
// be a tombstone.
unsigned is_not_tombstone_ : 1;
protected:
- // These are for DrawingDisplayItem to save memory.
- mutable unsigned known_to_be_opaque_is_set_ : 1;
- mutable unsigned known_to_be_opaque_ : 1;
+ // For DrawingDisplayItem to save memory.
+ mutable unsigned opaqueness_ : 2;
};
inline bool operator==(const DisplayItem::Id& a, const DisplayItem::Id& b) {
@@ -321,4 +352,35 @@ PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const DisplayItem&);
} // namespace blink
+namespace WTF {
+
+template <>
+struct HashTraits<blink::DisplayItem::Id::HashKey>
+ : GenericHashTraits<blink::DisplayItem::Id::HashKey> {
+ using Key = blink::DisplayItem::Id::HashKey;
+ static void ConstructDeletedValue(Key& slot, bool) {
+ const_cast<wtf_size_t&>(slot.fragment) = kNotFound;
+ }
+ static bool IsDeletedValue(const Key& id) { return id.fragment == kNotFound; }
+};
+
+template <>
+struct DefaultHash<blink::DisplayItem::Id::HashKey> {
+ struct Hash {
+ STATIC_ONLY(Hash);
+ using Key = blink::DisplayItem::Id::HashKey;
+ static unsigned GetHash(const Key& id) {
+ unsigned hash =
+ PtrHash<const blink::DisplayItemClient>::GetHash(id.client);
+ WTF::AddIntToHash(hash, id.type);
+ WTF::AddIntToHash(hash, id.fragment);
+ return hash;
+ }
+ static bool Equal(const Key& a, const Key& b) { return a == b; }
+ static const bool safe_to_compare_to_empty_or_deleted = false;
+ };
+};
+
+} // namespace WTF
+
#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 d702c6c758f..ef2660e5310 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,7 +5,6 @@
#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/allocator.h"
@@ -20,14 +19,14 @@ class DisplayItemCacheSkipper final {
: context_(context) {
context.GetPaintController().BeginSkippingCache();
}
+ DisplayItemCacheSkipper(const DisplayItemCacheSkipper&) = delete;
+ DisplayItemCacheSkipper& operator=(const DisplayItemCacheSkipper&) = delete;
~DisplayItemCacheSkipper() {
context_.GetPaintController().EndSkippingCache();
}
private:
GraphicsContext& context_;
-
- DISALLOW_COPY_AND_ASSIGN(DisplayItemCacheSkipper);
};
} // namespace blink
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 6743c0e8962..9023fe25593 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
@@ -27,11 +27,16 @@ enum class RasterEffectOutset : uint8_t {
// dereferenced unless we can make sure the client is still alive.
class PLATFORM_EXPORT DisplayItemClient {
public:
- DisplayItemClient() {
+ DisplayItemClient()
+ : paint_invalidation_reason_(
+ static_cast<uint8_t>(PaintInvalidationReason::kJustCreated)),
+ marked_for_validation_(0) {
#if DCHECK_IS_ON()
OnCreate();
#endif
}
+ DisplayItemClient(const DisplayItemClient&) = delete;
+ DisplayItemClient& operator=(const DisplayItemClient&) = delete;
virtual ~DisplayItemClient() {
#if DCHECK_IS_ON()
OnDestroy();
@@ -71,30 +76,32 @@ class PLATFORM_EXPORT DisplayItemClient {
// However, kUncacheable overwrites any other reason.
reason != PaintInvalidationReason::kUncacheable)
return;
- paint_invalidation_reason_ = reason;
+ paint_invalidation_reason_ = static_cast<uint8_t>(reason);
}
PaintInvalidationReason GetPaintInvalidationReason() const {
- return paint_invalidation_reason_;
+ return static_cast<PaintInvalidationReason>(paint_invalidation_reason_);
}
// A client is considered "just created" if its display items have never been
// validated by any PaintController since it's created.
bool IsJustCreated() const {
- return paint_invalidation_reason_ == PaintInvalidationReason::kJustCreated;
+ return GetPaintInvalidationReason() ==
+ PaintInvalidationReason::kJustCreated;
}
// 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;
+ return GetPaintInvalidationReason() !=
+ 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;
+ return GetPaintInvalidationReason() == PaintInvalidationReason::kNone;
}
String ToString() const;
@@ -102,11 +109,15 @@ class PLATFORM_EXPORT DisplayItemClient {
private:
friend class FakeDisplayItemClient;
friend class ObjectPaintInvalidatorTest;
+ friend class PaintChunker;
friend class PaintController;
- friend class GraphicsLayer; // Temporary for Validate().
+ void MarkForValidation() const { marked_for_validation_ = 1; }
+ bool IsMarkedForValidation() const { return marked_for_validation_; }
void Validate() const {
- paint_invalidation_reason_ = PaintInvalidationReason::kNone;
+ paint_invalidation_reason_ =
+ static_cast<uint8_t>(PaintInvalidationReason::kNone);
+ marked_for_validation_ = 0;
}
#if DCHECK_IS_ON()
@@ -114,10 +125,8 @@ class PLATFORM_EXPORT DisplayItemClient {
void OnDestroy();
#endif
- mutable PaintInvalidationReason paint_invalidation_reason_ =
- PaintInvalidationReason::kJustCreated;
-
- DISALLOW_COPY_AND_ASSIGN(DisplayItemClient);
+ mutable uint8_t paint_invalidation_reason_ : 7;
+ mutable uint8_t marked_for_validation_ : 1;
};
inline bool operator==(const DisplayItemClient& client1,
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 687c374d80d..c39d0b42f75 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
@@ -5,6 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_LIST_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_LIST_H_
+#include <cstring> // memcpy, memset
+#include <type_traits>
+
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -18,13 +21,7 @@ class JSONArray;
// A container for a list of display items of various types.
class PLATFORM_EXPORT DisplayItemList {
public:
- static constexpr wtf_size_t kDefaultCapacity = 16;
-
- // Using 0 as the default value to make 0 also fall back to kDefaultCapacity.
- // The initial capacity will be allocated when the first item is appended.
- explicit DisplayItemList(wtf_size_t initial_capacity = 0)
- : initial_capacity_(initial_capacity ? initial_capacity
- : kDefaultCapacity) {}
+ DisplayItemList() = default;
~DisplayItemList();
DisplayItemList(const DisplayItemList&) = delete;
@@ -32,6 +29,10 @@ class PLATFORM_EXPORT DisplayItemList {
DisplayItemList(DisplayItemList&&) = delete;
DisplayItemList& operator=(DisplayItemList&&) = delete;
+ void ReserveCapacity(wtf_size_t initial_capacity) {
+ items_.ReserveCapacity(initial_capacity);
+ }
+
// This private section is before the public APIs because some inline public
// methods depend on the private definitions.
private:
@@ -132,7 +133,9 @@ class PLATFORM_EXPORT DisplayItemList {
: begin_(begin), end_(end) {}
Iterator begin() const { return begin_; }
Iterator end() const { return end_; }
- wtf_size_t size() const { return end_ - begin_; }
+ wtf_size_t size() const {
+ return base::checked_cast<wtf_size_t>(end_ - begin_);
+ }
// To meet the requirement of gmock ElementsAre().
using value_type = DisplayItem;
@@ -219,16 +222,13 @@ class PLATFORM_EXPORT DisplayItemList {
#endif // DCHECK_IS_ON()
private:
- ItemSlot* AllocateItemSlot() {
- if (items_.IsEmpty())
- items_.ReserveCapacity(initial_capacity_);
- items_.emplace_back();
- return &items_.back();
- }
+ static_assert(std::is_trivially_copyable<value_type>::value,
+ "DisplayItemList uses `memcpy` in several member functions; "
+ "the `value_type` used by it must be trivially copyable");
+
+ ItemSlot* AllocateItemSlot() { return &items_.emplace_back(); }
ItemSlot* AllocateItemSlots(wtf_size_t count) {
- if (items_.IsEmpty())
- items_.ReserveCapacity(initial_capacity_);
items_.Grow(size() + count);
return &items_.back() - (count - 1);
}
@@ -250,7 +250,6 @@ class PLATFORM_EXPORT DisplayItemList {
}
ItemVector items_;
- wtf_size_t initial_capacity_;
};
using DisplayItemIterator = DisplayItemList::const_iterator;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
index c37cacf588b..27207bb2ad3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
@@ -36,7 +36,7 @@ void DisplayItemRasterInvalidator::Generate() {
.stored_value->value;
value.new_visual_rect.Unite(new_item.VisualRect());
if (value.reason == PaintInvalidationReason::kNone) {
- value.reason = new_item.Client().IsCacheable()
+ value.reason = new_item.IsCacheable()
? PaintInvalidationReason::kAppeared
: PaintInvalidationReason::kUncacheable;
}
@@ -44,7 +44,7 @@ void DisplayItemRasterInvalidator::Generate() {
continue;
}
- auto reason = new_item.Client().GetPaintInvalidationReason();
+ auto reason = new_item.GetPaintInvalidationReason();
if (!IsFullPaintInvalidationReason(reason) &&
matched_old_item < latest_cached_old_item) {
// |new_item| has been moved above other cached items.
@@ -66,7 +66,8 @@ void DisplayItemRasterInvalidator::Generate() {
value.reason = reason;
}
- wtf_size_t offset = matched_old_item - old_display_items_.begin();
+ wtf_size_t offset =
+ static_cast<wtf_size_t>(matched_old_item - old_display_items_.begin());
DCHECK(!old_display_items_matched[offset]);
old_display_items_matched[offset] = true;
@@ -81,7 +82,8 @@ void DisplayItemRasterInvalidator::Generate() {
// Invalidate remaining unmatched (disappeared or uncacheable) old items.
for (auto it = old_display_items_.begin(); it != old_display_items_.end();
++it) {
- if (old_display_items_matched[it - old_display_items_.begin()])
+ if (old_display_items_matched[static_cast<wtf_size_t>(
+ it - old_display_items_.begin())])
continue;
const auto& old_item = *it;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
index 312782d691b..f07e50da566 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
@@ -6,6 +6,7 @@
#include "base/callback_helpers.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/renderer/platform/geometry/float_point.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"
@@ -21,18 +22,7 @@ class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase,
protected:
DisplayItemRasterInvalidatorTest() = default;
- Vector<RasterInvalidationInfo> GenerateRasterInvalidations() {
- GetPaintController().CommitNewDisplayItems();
- invalidator_.Generate(
- base::DoNothing(),
- PaintChunkSubset(GetPaintController().GetPaintArtifactShared()),
- // The layer rect is big enough not to clip display item raster
- // invalidation rects in the tests.
- IntRect(0, 0, 20000, 20000), PropertyTreeState::Root());
- GetPaintController().FinishCycle();
- for (auto& chunk : GetPaintController().PaintChunks())
- chunk.properties.ClearChangedTo(PropertyTreeState::Root());
-
+ Vector<RasterInvalidationInfo> GetRasterInvalidations() {
if (invalidator_.GetTracking())
return invalidator_.GetTracking()->Invalidations();
return Vector<RasterInvalidationInfo>();
@@ -43,6 +33,29 @@ class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase,
RasterInvalidator invalidator_;
};
+class RasterInvalidationCycleScope : public PaintController::CycleScope {
+ public:
+ RasterInvalidationCycleScope(PaintController& controller,
+ RasterInvalidator& invalidator)
+ : PaintController::CycleScope(controller), invalidator_(invalidator) {}
+ ~RasterInvalidationCycleScope() {
+ for (auto* controller : controllers_) {
+ controller->CommitNewDisplayItems();
+ invalidator_.Generate(
+ base::DoNothing(),
+ PaintChunkSubset(controller->GetPaintArtifactShared()),
+ // The layer bounds are big enough not to clip display item raster
+ // invalidation rects in the tests.
+ FloatPoint(), IntSize(20000, 20000), PropertyTreeState::Root());
+ for (auto& chunk : controller->PaintChunks())
+ chunk.properties.ClearChangedTo(PropertyTreeState::Root());
+ }
+ }
+
+ private:
+ RasterInvalidator& invalidator_;
+};
+
INSTANTIATE_PAINT_TEST_SUITE_P(DisplayItemRasterInvalidatorTest);
TEST_P(DisplayItemRasterInvalidatorTest,
@@ -51,20 +64,27 @@ TEST_P(DisplayItemRasterInvalidatorTest,
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, first, kForegroundType, IntRect(100, 150, 300, 300));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, IntRect(100, 150, 300, 300));
+ }
first.Invalidate(PaintInvalidationReason::kStyle);
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, first, kForegroundType, IntRect(100, 150, 300, 300));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, IntRect(100, 150, 300, 300));
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&first, "first", IntRect(100, 100, 300, 350),
PaintInvalidationReason::kStyle}));
@@ -76,21 +96,28 @@ TEST_P(DisplayItemRasterInvalidatorTest, FullInvalidationWithGeometryChange) {
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, first, kForegroundType, IntRect(100, 150, 300, 300));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, IntRect(100, 150, 300, 300));
+ }
first.Invalidate(PaintInvalidationReason::kStyle);
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(200, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, first, kForegroundType, IntRect(200, 150, 300, 300));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(200, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, IntRect(200, 150, 300, 300));
+ }
EXPECT_THAT(
- GenerateRasterInvalidations(),
+ GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&first, "first", IntRect(100, 100, 300, 350),
PaintInvalidationReason::kStyle},
@@ -104,18 +131,25 @@ TEST_P(DisplayItemRasterInvalidatorTest, RemoveItemInMiddle) {
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&second, "second", IntRect(100, 100, 200, 200),
PaintInvalidationReason::kDisappeared}));
@@ -128,25 +162,32 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrder) {
FakeDisplayItemClient unaffected("unaffected");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
-
- EXPECT_THAT(GenerateRasterInvalidations(),
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
+ }
+
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&first, "first", IntRect(100, 100, 100, 100),
PaintInvalidationReason::kReordered}));
@@ -159,20 +200,27 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateFirst) {
FakeDisplayItemClient unaffected("unaffected");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- first.Invalidate(PaintInvalidationReason::kOutline);
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ first.Invalidate(PaintInvalidationReason::kOutline);
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&first, "first", IntRect(100, 100, 100, 100),
PaintInvalidationReason::kOutline}));
@@ -185,20 +233,27 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateSecond) {
FakeDisplayItemClient unaffected("unaffected");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- second.Invalidate(PaintInvalidationReason::kOutline);
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ second.Invalidate(PaintInvalidationReason::kOutline);
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&second, "second", IntRect(100, 100, 50, 200),
PaintInvalidationReason::kOutline}));
@@ -211,21 +266,28 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderWithIncrementalInvalidation) {
FakeDisplayItemClient unaffected("unaffected");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- first.Invalidate(PaintInvalidationReason::kIncremental);
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ first.Invalidate(PaintInvalidationReason::kIncremental);
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ }
// Incremental invalidation is not applicable when the item is reordered.
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&first, "first", IntRect(100, 100, 100, 100),
PaintInvalidationReason::kReordered}));
@@ -238,18 +300,25 @@ TEST_P(DisplayItemRasterInvalidatorTest, NewItemInMiddle) {
FakeDisplayItemClient third("third");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, third, kBackgroundType, IntRect(125, 100, 200, 50));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, third, kBackgroundType, IntRect(125, 100, 200, 50));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&third, "third", IntRect(125, 100, 200, 50),
PaintInvalidationReason::kAppeared}));
@@ -265,24 +334,31 @@ TEST_P(DisplayItemRasterInvalidatorTest, Incremental) {
}
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
- for (auto& client : clients)
- DrawRect(context, *client, kBackgroundType, IntRect(initial_rect));
- GenerateRasterInvalidations();
+ for (auto& client : clients)
+ DrawRect(context, *client, kBackgroundType, IntRect(initial_rect));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- IntRect visual_rects[] = {
- IntRect(100, 100, 150, 100), IntRect(100, 100, 100, 150),
- IntRect(100, 100, 150, 80), IntRect(100, 100, 80, 150),
- IntRect(100, 100, 150, 150), IntRect(100, 100, 80, 80)};
- for (size_t i = 0; i < base::size(clients); i++) {
- clients[i]->Invalidate(PaintInvalidationReason::kIncremental);
- DrawRect(context, *clients[i], kBackgroundType, IntRect(visual_rects[i]));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ IntRect visual_rects[] = {
+ IntRect(100, 100, 150, 100), IntRect(100, 100, 100, 150),
+ IntRect(100, 100, 150, 80), IntRect(100, 100, 80, 150),
+ IntRect(100, 100, 150, 150), IntRect(100, 100, 80, 80)};
+ for (size_t i = 0; i < base::size(clients); i++) {
+ clients[i]->Invalidate(PaintInvalidationReason::kIncremental);
+ DrawRect(context, *clients[i], kBackgroundType, IntRect(visual_rects[i]));
+ }
}
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{clients[0].get(), "0",
IntRect(200, 100, 50, 100),
@@ -323,23 +399,30 @@ TEST_P(DisplayItemRasterInvalidatorTest, AddRemoveFirstAndInvalidateSecond) {
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
- DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
+ DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- first.Invalidate();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
- DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
- EXPECT_EQ(0u, NumCachedNewItems());
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ first.Invalidate();
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
+ DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
+ EXPECT_EQ(0u, NumCachedNewItems());
+ }
EXPECT_THAT(
- GenerateRasterInvalidations(),
+ GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&first, "first", IntRect(100, 100, 150, 150),
PaintInvalidationReason::kAppeared},
@@ -350,11 +433,15 @@ TEST_P(DisplayItemRasterInvalidatorTest, AddRemoveFirstAndInvalidateSecond) {
invalidator_.SetTracksRasterInvalidations(false);
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
- DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
+ DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&first, "first", IntRect(100, 100, 150, 150),
PaintInvalidationReason::kDisappeared}));
@@ -366,22 +453,29 @@ TEST_P(DisplayItemRasterInvalidatorTest, InvalidateFirstAndAddRemoveSecond) {
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- first.Invalidate();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(150, 150, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(150, 150, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
- DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ first.Invalidate();
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(150, 150, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(150, 150, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
+ DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
+ }
EXPECT_THAT(
- GenerateRasterInvalidations(),
+ GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&first, "first", IntRect(100, 100, 150, 150),
PaintInvalidationReason::kFull},
@@ -390,14 +484,18 @@ TEST_P(DisplayItemRasterInvalidatorTest, InvalidateFirstAndAddRemoveSecond) {
invalidator_.SetTracksRasterInvalidations(false);
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- first.Invalidate();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ first.Invalidate();
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ }
EXPECT_THAT(
- GenerateRasterInvalidations(),
+ GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&first, "first", IntRect(100, 100, 150, 150),
PaintInvalidationReason::kFull},
@@ -413,31 +511,38 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderWithChildren) {
FakeDisplayItemClient content2("content2");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ }
// Simulate the situation when |container1| gets a z-index that is greater
// than that of |container2|.
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
-
- EXPECT_THAT(GenerateRasterInvalidations(),
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ }
+
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&container1, "container1",
IntRect(100, 100, 100, 100),
@@ -455,32 +560,39 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderWithChildrenAndInvalidation) {
FakeDisplayItemClient content2("content2");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ }
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, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
-
- EXPECT_THAT(GenerateRasterInvalidations(),
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ 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, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ }
+
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&container1, "container1",
IntRect(100, 100, 100, 100),
@@ -511,28 +623,35 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderCrossingChunks) {
PaintChunk::Id container1_id(container1, kBackgroundType);
PaintChunk::Id container2_id(container2, kBackgroundType);
- GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
- container1_properties);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
- container2_properties);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_id, container1_properties);
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container2_id, container2_properties);
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ }
// Move content2 into container1, without invalidation.
invalidator_.SetTracksRasterInvalidations(true);
- GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
- container1_properties);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
- container2_properties);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
-
- EXPECT_THAT(GenerateRasterInvalidations(),
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_id, container1_properties);
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container2_id, container2_properties);
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ }
+
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&content2, "content2",
IntRect(100, 200, 50, 200),
@@ -547,50 +666,60 @@ TEST_P(DisplayItemRasterInvalidatorTest, SkipCache) {
FakeDisplayItemClient multicol("multicol");
FakeDisplayItemClient content("content");
GraphicsContext context(GetPaintController());
-
- InitRootChunk();
IntRect rect1(100, 100, 50, 50);
IntRect rect2(150, 100, 50, 50);
IntRect rect3(200, 100, 50, 50);
- DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
- GetPaintController().BeginSkippingCache();
- DrawRect(context, content, kForegroundType, rect1);
- DrawRect(context, content, kForegroundType, rect2);
- GetPaintController().EndSkippingCache();
- GenerateRasterInvalidations();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ }
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- // Draw again with nothing invalidated.
- EXPECT_TRUE(ClientCacheIsValid(multicol));
- DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
-
- GetPaintController().BeginSkippingCache();
- DrawRect(context, content, kForegroundType, rect1);
- DrawRect(context, content, kForegroundType, rect2);
- GetPaintController().EndSkippingCache();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ // Draw again with nothing invalidated.
+ EXPECT_TRUE(ClientCacheIsValid(multicol));
+ DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
+
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ }
- EXPECT_THAT(GenerateRasterInvalidations(),
+ EXPECT_THAT(GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&content, "content", UnionRect(rect1, rect2),
PaintInvalidationReason::kUncacheable}));
invalidator_.SetTracksRasterInvalidations(false);
invalidator_.SetTracksRasterInvalidations(true);
- InitRootChunk();
- // Now the multicol becomes 3 columns and repaints.
- multicol.Invalidate();
- DrawRect(context, multicol, kBackgroundType, IntRect(100, 100, 100, 100));
-
- GetPaintController().BeginSkippingCache();
- DrawRect(context, content, kForegroundType, rect1);
- DrawRect(context, content, kForegroundType, rect2);
- DrawRect(context, content, kForegroundType, rect3);
- GetPaintController().EndSkippingCache();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ // Now the multicol becomes 3 columns and repaints.
+ multicol.Invalidate();
+ DrawRect(context, multicol, kBackgroundType, IntRect(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(),
+ GetRasterInvalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{&multicol, "multicol",
IntRect(100, 200, 100, 100),
@@ -612,25 +741,32 @@ TEST_P(DisplayItemRasterInvalidatorTest, PartialSkipCache) {
IntRect rect2(150, 100, 50, 50);
IntRect 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();
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ InitRootChunk();
+ DrawRect(context, content, kBackgroundType, rect1);
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ DrawRect(context, content, kForegroundType, rect3);
+ }
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);
+ {
+ RasterInvalidationCycleScope cycle_scope(GetPaintController(),
+ invalidator_);
+ 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(),
+ GetRasterInvalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
&content, "content", UnionRect(rect1, UnionRect(rect2, rect3)),
PaintInvalidationReason::kUncacheable}));
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 756ae7f21df..bffc3a96f40 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
@@ -119,21 +119,36 @@ SkColor DrawingDisplayItem::BackgroundColor(float& area) const {
return SK_ColorTRANSPARENT;
}
+IntRect DrawingDisplayItem::CalculateRectKnownToBeOpaque() const {
+ IntRect rect = CalculateRectKnownToBeOpaqueForRecord(record_.get());
+ if (rect.IsEmpty()) {
+ SetOpaqueness(Opaqueness::kNone);
+ } else if (rect == VisualRect()) {
+ SetOpaqueness(Opaqueness::kFull);
+ } else {
+ DCHECK(VisualRect().Contains(rect));
+ DCHECK_EQ(GetOpaqueness(), Opaqueness::kOther);
+ }
+ return rect;
+}
+
// This is not a PaintRecord method because it's not a general opaqueness
// detection algorithm (which might be more complex and slower), but works well
// and fast for most blink painted results.
-bool DrawingDisplayItem::CalculateKnownToBeOpaque(
+IntRect DrawingDisplayItem::CalculateRectKnownToBeOpaqueForRecord(
const PaintRecord* record) const {
if (!record)
- return false;
+ return IntRect();
// This limit keeps the algorithm fast, while allowing check of enough paint
// operations for most blink painted results.
- constexpr wtf_size_t kOpCountLimit = 4;
+ constexpr wtf_size_t kOpCountLimit = 8;
+ IntRect opaque_rect;
wtf_size_t op_count = 0;
+ IntRect clip_rect = VisualRect();
for (cc::PaintOpBuffer::Iterator it(record); it; ++it) {
if (++op_count > kOpCountLimit)
- return false;
+ break;
const auto* op = *it;
// Deal with the common pattern of clipped bleed avoiding images like:
@@ -141,70 +156,155 @@ bool DrawingDisplayItem::CalculateKnownToBeOpaque(
if (op->GetType() == cc::PaintOpType::Save)
continue;
if (op->GetType() == cc::PaintOpType::ClipRect) {
- const auto* clip_rect_op = static_cast<const cc::ClipRectOp*>(op);
- if (!EnclosedIntRect(clip_rect_op->rect).Contains(VisualRect()))
- return false;
+ clip_rect.Intersect(
+ EnclosedIntRect(static_cast<const cc::ClipRectOp*>(op)->rect));
continue;
}
if (!op->IsDrawOp())
- return false;
+ break;
+ IntRect op_opaque_rect;
if (op->GetType() == cc::PaintOpType::DrawRecord) {
- return CalculateKnownToBeOpaque(
+ op_opaque_rect = CalculateRectKnownToBeOpaqueForRecord(
static_cast<const cc::DrawRecordOp*>(op)->record.get());
- }
-
- if (!op->IsPaintOpWithFlags())
- continue;
+ } else {
+ if (!op->IsPaintOpWithFlags())
+ continue;
- const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
- if (flags.getStyle() != cc::PaintFlags::kFill_Style || flags.getLooper() ||
- (flags.getBlendMode() != SkBlendMode::kSrc &&
- flags.getBlendMode() != SkBlendMode::kSrcOver) ||
- flags.getMaskFilter() || flags.getColorFilter() ||
- flags.getImageFilter() || flags.getAlpha() != SK_AlphaOPAQUE ||
- (flags.getShader() && !flags.getShader()->IsOpaque()))
- continue;
+ const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
+ if (flags.getStyle() != cc::PaintFlags::kFill_Style ||
+ flags.getLooper() ||
+ (flags.getBlendMode() != SkBlendMode::kSrc &&
+ flags.getBlendMode() != SkBlendMode::kSrcOver) ||
+ flags.getMaskFilter() || flags.getColorFilter() ||
+ flags.getImageFilter() || flags.getAlpha() != SK_AlphaOPAQUE ||
+ (flags.getShader() && !flags.getShader()->IsOpaque()))
+ continue;
- IntRect opaque_rect;
- switch (op->GetType()) {
- case cc::PaintOpType::DrawRect:
- opaque_rect =
- EnclosedIntRect(static_cast<const cc::DrawRectOp*>(op)->rect);
- break;
- case cc::PaintOpType::DrawIRect:
- opaque_rect = IntRect(static_cast<const cc::DrawIRectOp*>(op)->rect);
- break;
- case cc::PaintOpType::DrawImage: {
- const auto* draw_image_op = static_cast<const cc::DrawImageOp*>(op);
- const auto& image = draw_image_op->image;
- if (!image.IsOpaque())
+ switch (op->GetType()) {
+ case cc::PaintOpType::DrawRect:
+ op_opaque_rect =
+ EnclosedIntRect(static_cast<const cc::DrawRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawIRect:
+ op_opaque_rect =
+ IntRect(static_cast<const cc::DrawIRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawImage: {
+ const auto* draw_image_op = static_cast<const cc::DrawImageOp*>(op);
+ const auto& image = draw_image_op->image;
+ if (!image.IsOpaque())
+ continue;
+ op_opaque_rect = IntRect(draw_image_op->left, draw_image_op->top,
+ image.width(), image.height());
+ break;
+ }
+ case cc::PaintOpType::DrawImageRect: {
+ const auto* draw_image_rect_op =
+ static_cast<const cc::DrawImageRectOp*>(op);
+ const auto& image = draw_image_rect_op->image;
+ DCHECK(SkRect::MakeWH(image.width(), image.height())
+ .contains(draw_image_rect_op->src));
+ if (!image.IsOpaque())
+ continue;
+ op_opaque_rect = EnclosedIntRect(draw_image_rect_op->dst);
+ break;
+ }
+ default:
continue;
- opaque_rect = IntRect(draw_image_op->left, draw_image_op->top,
- image.width(), image.height());
- break;
- }
- case cc::PaintOpType::DrawImageRect: {
- const auto* draw_image_rect_op =
- static_cast<const cc::DrawImageRectOp*>(op);
- const auto& image = draw_image_rect_op->image;
- DCHECK(SkRect::MakeWH(image.width(), image.height())
- .contains(draw_image_rect_op->src));
- if (!image.IsOpaque())
- continue;
- opaque_rect = EnclosedIntRect(draw_image_rect_op->dst);
- break;
}
- default:
- continue;
}
- // We should never paint outside of the visual rect.
- if (opaque_rect.Contains(VisualRect()))
- return true;
+ opaque_rect = MaximumCoveredRect(opaque_rect, op_opaque_rect);
+ opaque_rect.Intersect(clip_rect);
+ if (opaque_rect == VisualRect())
+ break;
}
- return false;
+ DCHECK(VisualRect().Contains(opaque_rect) || opaque_rect.IsEmpty());
+ return opaque_rect;
+}
+
+IntRect DrawingDisplayItem::TightenVisualRect(
+ const IntRect& visual_rect,
+ sk_sp<const PaintRecord>& record) {
+ DCHECK(ShouldTightenVisualRect(record));
+
+ const auto* op = record->GetFirstOp();
+ if (!op->IsPaintOpWithFlags())
+ return visual_rect;
+
+ const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
+ // The following can cause the painted output to be outside the paint op rect.
+ if (flags.getStyle() != cc::PaintFlags::kFill_Style || flags.getLooper() ||
+ flags.getMaskFilter() || flags.getImageFilter() || flags.getShader()) {
+ return visual_rect;
+ }
+
+ // TODO(pdr): Consider using |PaintOp::GetBounds| which is a more complete
+ // implementation of the logic below.
+
+ IntRect item_rect;
+ switch (op->GetType()) {
+ case cc::PaintOpType::DrawRect:
+ item_rect =
+ EnclosingIntRect(static_cast<const cc::DrawRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawIRect:
+ item_rect = IntRect(static_cast<const cc::DrawIRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawRRect:
+ item_rect = EnclosingIntRect(
+ static_cast<const cc::DrawRRectOp*>(op)->rrect.rect());
+ break;
+ // TODO(pdr): Support image PaintOpTypes such as DrawImage{Rect}.
+ // TODO(pdr): Consider checking PaintOpType::DrawTextBlob too.
+ default:
+ return visual_rect;
+ }
+
+ // TODO(pdr): Enable this DCHECK which enforces that the original visual rect
+ // was correct and fully contains the recording.
+ // DCHECK(visual_rect.Contains(item_rect));
+ return item_rect;
+}
+
+bool DrawingDisplayItem::IsSolidColor() const {
+ if (!record_)
+ return false;
+
+ // TODO(pdr): We could use SolidColorAnalyzer::DetermineIfSolidColor instead
+ // of special-casing just single-op drawrect solid colors.
+ if (record_->size() != 1)
+ return false;
+
+ const auto* op = record_->GetFirstOp();
+ if (!op->IsPaintOpWithFlags())
+ return false;
+
+ const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
+ // The following can cause the painted output to be outside the paint op rect.
+ if (flags.getStyle() != cc::PaintFlags::kFill_Style || flags.getLooper() ||
+ flags.getMaskFilter() || flags.getImageFilter() || flags.getShader()) {
+ return false;
+ }
+
+ FloatRect solid_color_rect;
+ switch (op->GetType()) {
+ case cc::PaintOpType::DrawRect:
+ solid_color_rect =
+ FloatRect(static_cast<const cc::DrawRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawIRect:
+ solid_color_rect =
+ FloatRect(IntRect(static_cast<const cc::DrawIRectOp*>(op)->rect));
+ break;
+ default:
+ return false;
+ }
+
+ // The solid color must fully cover the visual rect.
+ return solid_color_rect.Contains(VisualRect());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
index a2e17ab5faa..1a6e96a16ca 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
@@ -23,31 +23,20 @@ class PLATFORM_EXPORT DrawingDisplayItem : public DisplayItem {
DrawingDisplayItem(const DisplayItemClient& client,
Type type,
const IntRect& visual_rect,
- sk_sp<const PaintRecord> record);
+ sk_sp<const PaintRecord> record,
+ PaintInvalidationReason paint_invalidation_reason =
+ PaintInvalidationReason::kJustCreated);
const sk_sp<const PaintRecord>& GetPaintRecord() const {
DCHECK(!IsTombstone());
return record_;
}
- bool KnownToBeOpaque() const {
- DCHECK(!IsTombstone());
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return false;
- if (!known_to_be_opaque_is_set_) {
- known_to_be_opaque_is_set_ = true;
- known_to_be_opaque_ = CalculateKnownToBeOpaque(record_.get());
- }
- return known_to_be_opaque_;
- }
- void SetKnownToBeOpaqueForTesting() {
- DCHECK(!IsTombstone());
- known_to_be_opaque_is_set_ = true;
- known_to_be_opaque_ = true;
- }
-
+ IntRect RectKnownToBeOpaque() const;
SkColor BackgroundColor(float& area) const;
+ bool IsSolidColor() const;
+
private:
friend class DisplayItem;
bool EqualsForUnderInvalidationImpl(const DrawingDisplayItem&) const;
@@ -55,23 +44,57 @@ class PLATFORM_EXPORT DrawingDisplayItem : public DisplayItem {
void PropertiesAsJSONImpl(JSONObject&) const {}
#endif
- bool CalculateKnownToBeOpaque(const PaintRecord*) const;
+ // Status of RectKnownToBeOpaque(). kOther means recalculation.
+ enum class Opaqueness { kOther, kFull, kNone };
+ Opaqueness GetOpaqueness() const {
+ return static_cast<Opaqueness>(opaqueness_);
+ }
+ void SetOpaqueness(Opaqueness opaqueness) const {
+ opaqueness_ = static_cast<unsigned>(opaqueness);
+ DCHECK_EQ(GetOpaqueness(), opaqueness);
+ }
+ IntRect CalculateRectKnownToBeOpaque() const;
+ IntRect CalculateRectKnownToBeOpaqueForRecord(const PaintRecord*) const;
+
+ // Improve the visual rect using the paint record. This can improve solid
+ // color analysis in cases when the painted content was snapped but the
+ // visual rect was not. Check |ShouldTightenVisualRect| before calling.
+ static IntRect TightenVisualRect(const IntRect& visual_rect,
+ sk_sp<const PaintRecord>& record);
+ static bool ShouldTightenVisualRect(sk_sp<const PaintRecord>& record) {
+ // We only have an optimization to tighten the visual rect for a single op.
+ return record && record->size() == 1;
+ }
sk_sp<const PaintRecord> record_;
};
// TODO(dcheng): Move this ctor back inline once the clang plugin is fixed.
DISABLE_CFI_PERF
-inline DrawingDisplayItem::DrawingDisplayItem(const DisplayItemClient& client,
- Type type,
- const IntRect& visual_rect,
- sk_sp<const PaintRecord> record)
+inline DrawingDisplayItem::DrawingDisplayItem(
+ const DisplayItemClient& client,
+ Type type,
+ const IntRect& visual_rect,
+ sk_sp<const PaintRecord> record,
+ PaintInvalidationReason paint_invalidation_reason)
: DisplayItem(client,
type,
- visual_rect,
+ UNLIKELY(ShouldTightenVisualRect(record))
+ ? TightenVisualRect(visual_rect, record)
+ : visual_rect,
+ paint_invalidation_reason,
/* draws_content*/ record && record->size()),
record_(DrawsContent() ? std::move(record) : nullptr) {
DCHECK(IsDrawing());
+ DCHECK_EQ(GetOpaqueness(), Opaqueness::kOther);
+}
+
+inline IntRect DrawingDisplayItem::RectKnownToBeOpaque() const {
+ if (GetOpaqueness() == Opaqueness::kFull)
+ return VisualRect();
+ if (GetOpaqueness() == Opaqueness::kNone)
+ return IntRect();
+ return CalculateRectKnownToBeOpaque();
}
template <>
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 e82329d24ba..ab68f529929 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
@@ -123,5 +123,40 @@ TEST_F(DrawingDisplayItemTest, EqualsForUnderInvalidation) {
EXPECT_TRUE(empty_item.EqualsForUnderInvalidation(empty_item));
}
+TEST_F(DrawingDisplayItemTest, SolidColorRect) {
+ FloatRect record_bounds(5, 6, 10, 10);
+ DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+ EnclosingIntRect(record_bounds),
+ CreateRectRecord(record_bounds));
+ EXPECT_EQ(IntRect(5, 6, 10, 10), item.VisualRect());
+ EXPECT_TRUE(item.IsSolidColor());
+}
+
+TEST_F(DrawingDisplayItemTest, NonSolidColorSnappedRect) {
+ FloatRect record_bounds(5.1, 6.9, 10, 10);
+ DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+ EnclosingIntRect(record_bounds),
+ CreateRectRecord(record_bounds));
+ EXPECT_EQ(IntRect(5, 6, 11, 11), item.VisualRect());
+ // Not solid color if the drawing does not fully cover the visual rect.
+ EXPECT_FALSE(item.IsSolidColor());
+}
+
+TEST_F(DrawingDisplayItemTest, NonSolidColorOval) {
+ FloatRect record_bounds(5, 6, 10, 10);
+
+ PaintRecorder recorder;
+ cc::PaintCanvas* canvas =
+ recorder.beginRecording(record_bounds.Width(), record_bounds.Height());
+ canvas->drawOval(record_bounds, PaintFlags());
+
+ DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+ EnclosingIntRect(record_bounds),
+ recorder.finishRecordingAsPicture());
+ EXPECT_EQ(IntRect(5, 6, 10, 10), item.VisualRect());
+ // Not solid color if the drawing does not fully cover the visual rect.
+ EXPECT_FALSE(item.IsSolidColor());
+}
+
} // namespace
} // namespace blink
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 8a36a94e320..ce8c76b795d 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
@@ -47,7 +47,8 @@ DrawingRecorder::~DrawingRecorder() {
context_.SetInDrawingRecorder(false);
context_.GetPaintController().CreateAndAppend<DrawingDisplayItem>(
- client_, type_, visual_rect_, context_.EndRecording());
+ client_, type_, visual_rect_, context_.EndRecording(),
+ client_.GetPaintInvalidationReason());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
index 7298dd1958f..2b98683d499 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
@@ -7,7 +7,7 @@
#include "base/auto_reset.h"
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/paint/drawing_display_item.h"
@@ -70,6 +70,8 @@ class PLATFORM_EXPORT DrawingRecorder {
client,
DisplayItem::PaintPhaseToDrawingType(phase)) {}
+ DrawingRecorder(const DrawingRecorder&) = delete;
+ DrawingRecorder& operator=(const DrawingRecorder&) = delete;
~DrawingRecorder();
// Sometimes we don't the the exact visual rect when we create a
@@ -83,8 +85,6 @@ class PLATFORM_EXPORT DrawingRecorder {
const DisplayItem::Type type_;
IntRect visual_rect_;
absl::optional<DOMNodeId> dom_node_id_to_restore_;
-
- DISALLOW_COPY_AND_ASSIGN(DrawingRecorder);
};
#if DCHECK_IS_ON()
@@ -93,11 +93,12 @@ class DisableListModificationCheck {
public:
DisableListModificationCheck();
+ DisableListModificationCheck(const DisableListModificationCheck&) = delete;
+ DisableListModificationCheck& operator=(const DisableListModificationCheck&) =
+ delete;
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 42eb5e04241..f5295542967 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,9 +22,12 @@ const IntRect kBounds(1, 2, 3, 4);
TEST_F(DrawingRecorderTest, Nothing) {
FakeDisplayItemClient client;
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawNothing(context, client, kForegroundType);
- CommitAndFinishCycle();
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawNothing(context, client, kForegroundType);
+ GetPaintController().CommitNewDisplayItems();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kForegroundType)));
EXPECT_FALSE(
@@ -35,9 +38,12 @@ TEST_F(DrawingRecorderTest, Nothing) {
TEST_F(DrawingRecorderTest, Rect) {
FakeDisplayItemClient client;
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, client, kForegroundType, kBounds);
- CommitAndFinishCycle();
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, client, kForegroundType, kBounds);
+ GetPaintController().CommitNewDisplayItems();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kForegroundType)));
}
@@ -45,22 +51,28 @@ TEST_F(DrawingRecorderTest, Rect) {
TEST_F(DrawingRecorderTest, Cached) {
FakeDisplayItemClient client;
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawNothing(context, client, kBackgroundType);
- DrawRect(context, client, kForegroundType, kBounds);
- CommitAndFinishCycle();
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawNothing(context, client, kBackgroundType);
+ DrawRect(context, client, kForegroundType, kBounds);
+ GetPaintController().CommitNewDisplayItems();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kBackgroundType),
IsSameId(&client, kForegroundType)));
- InitRootChunk();
- DrawNothing(context, client, kBackgroundType);
- DrawRect(context, client, kForegroundType, kBounds);
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawNothing(context, client, kBackgroundType);
+ DrawRect(context, client, kForegroundType, kBounds);
- EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(2u, NumCachedNewItems());
- CommitAndFinishCycle();
+ GetPaintController().CommitNewDisplayItems();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kBackgroundType),
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect_test.cc
index 6ab4f4aedfd..b6e72537efc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect_test.cc
@@ -62,8 +62,8 @@ TEST_F(FloatClipRectTest, Intersect) {
TEST_F(FloatClipRectTest, IntersectWithInfinite) {
FloatClipRect infinite;
- FloatRect large(0, 0, std::numeric_limits<int>::max(),
- std::numeric_limits<int>::max());
+ FloatRect large(0, 0, static_cast<float>(std::numeric_limits<int>::max()),
+ static_cast<float>(std::numeric_limits<int>::max()));
FloatClipRect unclipped(large);
unclipped.Intersect(infinite);
@@ -73,8 +73,8 @@ TEST_F(FloatClipRectTest, IntersectWithInfinite) {
TEST_F(FloatClipRectTest, InclusiveIntersectWithInfinite) {
FloatClipRect infinite;
- FloatRect large(0, 0, std::numeric_limits<int>::max(),
- std::numeric_limits<int>::max());
+ FloatRect large(0, 0, static_cast<float>(std::numeric_limits<int>::max()),
+ static_cast<float>(std::numeric_limits<int>::max()));
FloatClipRect unclipped(large);
ASSERT_TRUE(unclipped.InclusiveIntersect(infinite));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
index 978c8ff7c5c..9a97856d7a1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
@@ -19,10 +19,12 @@ ForeignLayerDisplayItem::ForeignLayerDisplayItem(
const DisplayItemClient& client,
Type type,
scoped_refptr<cc::Layer> layer,
- const IntPoint& offset)
+ const IntPoint& offset,
+ PaintInvalidationReason paint_invalidation_reason)
: DisplayItem(client,
type,
- IntRect(offset, IntSize(layer->bounds()))),
+ IntRect(offset, IntSize(layer->bounds())),
+ paint_invalidation_reason),
layer_(std::move(layer)) {
DCHECK(IsForeignLayerType(type));
}
@@ -46,6 +48,14 @@ void RecordForeignLayer(GraphicsContext& context,
const IntPoint& offset,
const PropertyTreeStateOrAlias* properties) {
PaintController& paint_controller = context.GetPaintController();
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // Only record the first fragment's cc::Layer to prevent duplicate layers.
+ // This is not needed for link highlights which do support fragmentation.
+ if (type != DisplayItem::kForeignLayerLinkHighlight &&
+ paint_controller.CurrentFragment() != 0) {
+ return;
+ }
+ }
// This is like ScopedPaintChunkProperties but uses null id because foreign
// layer chunk doesn't need an id nor a client.
absl::optional<PropertyTreeStateOrAlias> previous_properties;
@@ -54,7 +64,8 @@ void RecordForeignLayer(GraphicsContext& context,
paint_controller.UpdateCurrentPaintChunkProperties(nullptr, *properties);
}
paint_controller.CreateAndAppend<ForeignLayerDisplayItem>(
- client, type, std::move(layer), offset);
+ client, type, std::move(layer), offset,
+ client.GetPaintInvalidationReason());
if (properties) {
paint_controller.UpdateCurrentPaintChunkProperties(nullptr,
*previous_properties);
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 376ca14c390..eb9715fee91 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
@@ -27,7 +27,8 @@ class PLATFORM_EXPORT ForeignLayerDisplayItem : public DisplayItem {
ForeignLayerDisplayItem(const DisplayItemClient& client,
Type,
scoped_refptr<cc::Layer>,
- const IntPoint& offset);
+ const IntPoint& offset,
+ PaintInvalidationReason);
cc::Layer* GetLayer() const {
DCHECK(!IsTombstone());
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 db720b139ab..96410ab6674 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
@@ -9,14 +9,51 @@
namespace blink {
+namespace {
+
+// Walk up from the local transform to the ancestor. If the last transform
+// before hitting the ancestor is a fixed node, expand based on the min and
+// max scroll offsets.
+void ExpandFixedBoundsInScroller(const TransformPaintPropertyNode* local,
+ const TransformPaintPropertyNode* ancestor,
+ FloatClipRect& rect_to_map) {
+ const TransformPaintPropertyNode* current = local->UnaliasedParent();
+ const TransformPaintPropertyNode* previous = local;
+ while (current != nullptr && current != ancestor) {
+ previous = current;
+ current = current->UnaliasedParent();
+ }
+
+ const auto* node = previous->ScrollTranslationForFixed();
+ if (!node)
+ return;
+
+ DCHECK(node->ScrollNode());
+
+ // First move the rect back to the min scroll offset, by accounting for the
+ // current scroll offset.
+ FloatSize scroll_offset = node->Translation2D();
+ rect_to_map.Rect().Move(scroll_offset);
+
+ // Calculate the max scroll offset and expand by that amount. The max scroll
+ // offset is the contents size minus one viewport's worth of space (i.e. the
+ // container rect size).
+ IntSize contents_size = node->ScrollNode()->ContentsSize();
+ IntSize container_size = node->ScrollNode()->ContainerRect().Size();
+ rect_to_map.Rect().Expand(FloatSize(contents_size - container_size));
+}
+
+} // namespace
+
GeometryMapper::Translation2DOrMatrix
GeometryMapper::SourceToDestinationProjection(
const TransformPaintPropertyNode& source,
const TransformPaintPropertyNode& destination) {
bool has_animation = false;
+ bool has_fixed = false;
bool success = false;
- return SourceToDestinationProjectionInternal(source, destination,
- has_animation, success);
+ return SourceToDestinationProjectionInternal(
+ source, destination, has_animation, has_fixed, success);
}
// Returns flatten(destination_to_screen)^-1 * flatten(source_to_screen)
@@ -63,14 +100,17 @@ GeometryMapper::SourceToDestinationProjectionInternal(
const TransformPaintPropertyNode& source,
const TransformPaintPropertyNode& destination,
bool& has_animation,
+ bool& has_fixed,
bool& success) {
has_animation = false;
+ has_fixed = false;
success = true;
if (&source == &destination)
return Translation2DOrMatrix();
if (source.Parent() && &destination == &source.Parent()->Unalias()) {
+ has_fixed = source.RequiresCompositingForFixedPosition();
if (source.IsIdentityOr2DTranslation()) {
// We always use full matrix for animating transforms.
DCHECK(!source.HasActiveTransformAnimation());
@@ -95,6 +135,8 @@ GeometryMapper::SourceToDestinationProjectionInternal(
const auto& source_cache = source.GetTransformCache();
const auto& destination_cache = destination.GetTransformCache();
+ has_fixed |= source_cache.has_fixed();
+
// Case 1a (fast path of case 1b): check if source and destination are under
// the same 2d translation root.
if (source_cache.root_of_2d_translation() ==
@@ -153,11 +195,11 @@ bool GeometryMapper::LocalToAncestorVisualRect(
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
- ExpandVisualRectForAnimationOrNot expand_for_animation) {
+ ExpandVisualRectForCompositingOverlapOrNot expand) {
bool success = false;
bool result = LocalToAncestorVisualRectInternal(
local_state, ancestor_state, mapping_rect, clip_behavior,
- inclusive_behavior, expand_for_animation, success);
+ inclusive_behavior, expand, success);
DCHECK(success);
return result;
}
@@ -168,7 +210,7 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
FloatClipRect& rect_to_map,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
- ExpandVisualRectForAnimationOrNot expand_for_animation,
+ ExpandVisualRectForCompositingOverlapOrNot expand,
bool& success) {
if (local_state == ancestor_state) {
success = true;
@@ -178,13 +220,14 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
if (&local_state.Effect() != &ancestor_state.Effect()) {
return SlowLocalToAncestorVisualRectWithEffects(
local_state, ancestor_state, rect_to_map, clip_behavior,
- inclusive_behavior, expand_for_animation, success);
+ inclusive_behavior, expand, success);
}
bool has_animation = false;
+ bool has_fixed = false;
const auto& translation_2d_or_matrix = SourceToDestinationProjectionInternal(
local_state.Transform(), ancestor_state.Transform(), has_animation,
- success);
+ has_fixed, success);
if (!success) {
// A failure implies either source-to-plane or destination-to-plane being
// singular. A notable example of singular source-to-plane from valid CSS:
@@ -202,18 +245,22 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
return false;
}
- if (has_animation && expand_for_animation == kExpandVisualRectForAnimation) {
+ if (has_animation && expand == kExpandVisualRectForCompositingOverlap) {
// Assume during the animation the transform can map |rect_to_map| to
// anywhere. Ancestor clips will still apply.
// TODO(crbug.com/1026653): Use animation bounds instead of infinite rect.
rect_to_map = InfiniteLooseFloatClipRect();
} else {
translation_2d_or_matrix.MapFloatClipRect(rect_to_map);
+ if (has_fixed && expand == kExpandVisualRectForCompositingOverlap) {
+ ExpandFixedBoundsInScroller(&local_state.Transform(),
+ &ancestor_state.Transform(), rect_to_map);
+ }
}
FloatClipRect clip_rect = LocalToAncestorClipRectInternal(
local_state.Clip(), ancestor_state.Clip(), ancestor_state.Transform(),
- clip_behavior, inclusive_behavior, expand_for_animation, success);
+ clip_behavior, inclusive_behavior, expand, success);
if (success) {
// This is where we propagate the roundedness and tightness of |clip_rect|
// to |rect_to_map|.
@@ -231,8 +278,12 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
// --enable-prefer-compositing-to-lcd-text) for details.
// Ignore it for SPv1 for now.
success = true;
- rect_to_map.ClearIsTight();
+ } else if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
+ // TODO(crbug.com/803649): We still have clip hierarchy issues with fragment
+ // clips. See crbug.com/1228364 for the tests.
+ success = true;
}
+ rect_to_map.ClearIsTight();
return !rect_to_map.Rect().IsEmpty();
}
@@ -242,7 +293,7 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
- ExpandVisualRectForAnimationOrNot expand_for_animation,
+ ExpandVisualRectForCompositingOverlapOrNot expand,
bool& success) {
PropertyTreeState last_transform_and_clip_state(
local_state.Transform(), local_state.Clip(),
@@ -253,7 +304,7 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
effect && effect != &ancestor_effect;
effect = effect->UnaliasedParent()) {
if (effect->HasActiveFilterAnimation() &&
- expand_for_animation == kExpandVisualRectForAnimation) {
+ expand == kExpandVisualRectForCompositingOverlap) {
// Assume during the animation the filter can map |rect_to_map| to
// anywhere. Ancestor clips will still apply.
// TODO(crbug.com/1026653): Use animation bounds instead of infinite rect.
@@ -272,7 +323,7 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
effect->OutputClip()->Unalias(), EffectPaintPropertyNode::Root());
bool intersects = LocalToAncestorVisualRectInternal(
last_transform_and_clip_state, transform_and_clip_state, mapping_rect,
- clip_behavior, inclusive_behavior, expand_for_animation, success);
+ clip_behavior, inclusive_behavior, expand, success);
if (!success || !intersects) {
success = true;
mapping_rect = FloatClipRect(FloatRect());
@@ -288,8 +339,7 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
EffectPaintPropertyNode::Root());
bool intersects = LocalToAncestorVisualRectInternal(
last_transform_and_clip_state, final_transform_and_clip_state,
- mapping_rect, clip_behavior, inclusive_behavior, expand_for_animation,
- success);
+ mapping_rect, clip_behavior, inclusive_behavior, expand, success);
// Many effects (e.g. filters, clip-paths) can make a clip rect not tight.
mapping_rect.ClearIsTight();
@@ -308,7 +358,8 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRect(
bool success = false;
auto result = LocalToAncestorClipRectInternal(
local_clip, ancestor_clip, ancestor_state.Transform(), clip_behavior,
- kNonInclusiveIntersect, kDontExpandVisualRectForAnimation, success);
+ kNonInclusiveIntersect, kDontExpandVisualRectForCompositingOverlap,
+ success);
DCHECK(success);
// Many effects (e.g. filters, clip-paths) can make a clip rect not tight.
@@ -335,7 +386,7 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
const TransformPaintPropertyNode& ancestor_transform,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
- ExpandVisualRectForAnimationOrNot expand_for_animation,
+ ExpandVisualRectForCompositingOverlapOrNot expand,
bool& success) {
if (&descendant_clip == &ancestor_clip) {
success = true;
@@ -362,7 +413,7 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
cached_clip = clip_node->GetClipCache().GetCachedClip(clip_and_transform);
if (cached_clip && cached_clip->has_transform_animation &&
- expand_for_animation == kExpandVisualRectForAnimation) {
+ expand == kExpandVisualRectForCompositingOverlap) {
// Don't use cached clip if it's transformed by any animating transform.
cached_clip = nullptr;
}
@@ -385,6 +436,10 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
// with --enable-prefer-compositing-to-lcd-text) for details.
// Ignore it for SPv1 for now.
success = true;
+ } else if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
+ // TODO(crbug.com/803649): We still have clip hierarchy issues with
+ // fragment clips. See crbug.com/1228364 for the tests.
+ success = true;
}
return InfiniteLooseFloatClipRect();
}
@@ -394,17 +449,18 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
for (auto it = intermediate_nodes.rbegin(); it != intermediate_nodes.rend();
++it) {
bool has_animation = false;
+ bool has_fixed = false;
const auto& translation_2d_or_matrix =
SourceToDestinationProjectionInternal(
(*it)->LocalTransformSpace().Unalias(), ancestor_transform,
- has_animation, success);
+ has_animation, has_fixed, success);
if (!success) {
success = true;
return FloatClipRect(FloatRect());
}
// Don't apply this clip if it's transformed by any animating transform.
- if (has_animation && expand_for_animation == kExpandVisualRectForAnimation)
+ if (has_animation && expand == kExpandVisualRectForCompositingOverlap)
continue;
// This is where we generate the roundedness and tightness of clip rect
@@ -424,7 +480,7 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
// Clips that are inclusive intersected or expanded for animation are not
// cached at present.
DCHECK(inclusive_behavior == kInclusiveIntersect ||
- expand_for_animation == kExpandVisualRectForAnimation ||
+ expand == kExpandVisualRectForCompositingOverlap ||
descendant_clip.GetClipCache()
.GetCachedClip(clip_and_transform)
->clip_rect == clip);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
index 1b3a89b2fba..9c6a9173b98 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -18,15 +18,27 @@ namespace blink {
// Clips can use FloatRect::Intersect or FloatRect::InclusiveIntersect.
enum InclusiveIntersectOrNot { kNonInclusiveIntersect, kInclusiveIntersect };
-// Whether to expand the visual or clip rect to infinity when we meet any
-// animating transform or filter when walking from a descendant state to an
+// When performing overlap testing during compositing, we may need to expand the
+// visual rect in two cases when mapping from descendant state to ancestor
+// state: mapping through a fixed transform node to the viewport it is attached
+// to, and mapping through an animating transform or filter.
+//
+// This allows for a more conservative overlap test that assumes potentially
+// more overlap than we'd encounter otherwise, in order to reduce the need to
+// re-run overlap testing in response to things like scrolling.
+//
+// The expansion for fixed covers all coordinates where the fixed content may
+// end up when the scroller is at the end of the extents.
+//
+// For animation, the visual or clip rect is expanded to infinity when we meet
+// any animating transform or filter when walking from a descendant state to an
// ancestor state, when mapping a visual rect or getting the accumulated clip
// rect. After we expanded the rect, we will still apply ancestor clips when
// continuing walking up the tree. TODO(crbug.com/1026653): Consider animation
// bounds instead of using infinite rect.
-enum ExpandVisualRectForAnimationOrNot {
- kDontExpandVisualRectForAnimation,
- kExpandVisualRectForAnimation,
+enum ExpandVisualRectForCompositingOverlapOrNot {
+ kDontExpandVisualRectForCompositingOverlap,
+ kExpandVisualRectForCompositingOverlap,
};
// GeometryMapper is a helper class for fast computations of transformed and
@@ -186,9 +198,10 @@ class PLATFORM_EXPORT GeometryMapper {
}
bool has_animation = false;
+ bool has_fixed = false;
bool success = false;
const auto& source_to_destination = SourceToDestinationProjectionInternal(
- source, destination, has_animation, success);
+ source, destination, has_animation, has_fixed, success);
if (!success)
mapping_rect = Rect();
else
@@ -263,11 +276,11 @@ class PLATFORM_EXPORT GeometryMapper {
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior clip = kIgnoreOverlayScrollbarSize,
InclusiveIntersectOrNot intersect = kNonInclusiveIntersect,
- ExpandVisualRectForAnimationOrNot animation =
- kDontExpandVisualRectForAnimation) {
+ ExpandVisualRectForCompositingOverlapOrNot expand =
+ kDontExpandVisualRectForCompositingOverlap) {
return LocalToAncestorVisualRect(local_state.Unalias(),
ancestor_state.Unalias(), mapping_rect,
- clip, intersect, animation);
+ clip, intersect, expand);
}
static bool LocalToAncestorVisualRect(
const PropertyTreeState& local_state,
@@ -275,7 +288,8 @@ class PLATFORM_EXPORT GeometryMapper {
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize,
InclusiveIntersectOrNot = kNonInclusiveIntersect,
- ExpandVisualRectForAnimationOrNot = kDontExpandVisualRectForAnimation);
+ ExpandVisualRectForCompositingOverlapOrNot =
+ kDontExpandVisualRectForCompositingOverlap);
static void ClearCache();
@@ -289,6 +303,7 @@ class PLATFORM_EXPORT GeometryMapper {
const TransformPaintPropertyNode& source,
const TransformPaintPropertyNode& destination,
bool& has_animation,
+ bool& has_fixed,
bool& success);
static FloatClipRect LocalToAncestorClipRectInternal(
@@ -297,7 +312,7 @@ class PLATFORM_EXPORT GeometryMapper {
const TransformPaintPropertyNode& ancestor_transform,
OverlayScrollbarClipBehavior,
InclusiveIntersectOrNot,
- ExpandVisualRectForAnimationOrNot,
+ ExpandVisualRectForCompositingOverlapOrNot,
bool& success);
// The return value has the same meaning as that for
@@ -308,7 +323,7 @@ class PLATFORM_EXPORT GeometryMapper {
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior,
InclusiveIntersectOrNot,
- ExpandVisualRectForAnimationOrNot,
+ ExpandVisualRectForCompositingOverlapOrNot,
bool& success);
// The return value has the same meaning as that for
@@ -319,7 +334,7 @@ class PLATFORM_EXPORT GeometryMapper {
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior,
InclusiveIntersectOrNot,
- ExpandVisualRectForAnimationOrNot,
+ ExpandVisualRectForCompositingOverlapOrNot,
bool& success);
static void MoveRect(FloatRect& rect, const FloatSize& delta) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
index daebdde0e2a..2d5f706b0f7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
@@ -24,6 +24,8 @@ class PLATFORM_EXPORT GeometryMapperClipCache {
public:
GeometryMapperClipCache();
+ GeometryMapperClipCache(const GeometryMapperClipCache&) = delete;
+ GeometryMapperClipCache& operator=(const GeometryMapperClipCache&) = delete;
struct ClipAndTransform {
const ClipPaintPropertyNode* ancestor_clip;
@@ -72,8 +74,6 @@ class PLATFORM_EXPORT GeometryMapperClipCache {
Vector<ClipCacheEntry> clip_cache_;
unsigned cache_generation_;
-
- DISALLOW_COPY_AND_ASSIGN(GeometryMapperClipCache);
};
} // namespace blink
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 0f2a1ffcaea..5162347a8e2 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
@@ -36,7 +36,8 @@ class GeometryMapperTest : public testing::Test,
bool& success) {
GeometryMapper::LocalToAncestorVisualRectInternal(
local_state, ancestor_state, mapping_rect, kIgnoreOverlayScrollbarSize,
- kNonInclusiveIntersect, kDontExpandVisualRectForAnimation, success);
+ kNonInclusiveIntersect, kDontExpandVisualRectForCompositingOverlap,
+ success);
}
void CheckMappings();
@@ -52,7 +53,7 @@ class GeometryMapperTest : public testing::Test,
PropertyTreeStateOrAlias ancestor_state = PropertyTreeState::Root();
FloatRect input_rect;
FloatClipRect expected_visual_rect;
- absl::optional<FloatClipRect> expected_visual_rect_expanded_for_animation;
+ absl::optional<FloatClipRect> expected_visual_rect_expanded_for_compositing;
FloatSize expected_translation_2d;
absl::optional<TransformationMatrix> expected_transform;
FloatClipRect expected_clip;
@@ -94,9 +95,9 @@ void GeometryMapperTest::CheckLocalToAncestorVisualRect() {
GeometryMapper::LocalToAncestorVisualRect(
local_state, ancestor_state, actual_visual_rect,
kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect,
- kExpandVisualRectForAnimation);
- EXPECT_CLIP_RECT_EQ(expected_visual_rect_expanded_for_animation
- ? *expected_visual_rect_expanded_for_animation
+ kExpandVisualRectForCompositingOverlap);
+ EXPECT_CLIP_RECT_EQ(expected_visual_rect_expanded_for_compositing
+ ? *expected_visual_rect_expanded_for_compositing
: expected_visual_rect,
actual_visual_rect);
}
@@ -560,7 +561,7 @@ TEST_P(GeometryMapperTest, ExpandVisualRectWithClipBeforeAnimatingTransform) {
expected_visual_rect.Intersect(FloatClipRect(clip->UnsnappedClipRect()));
expected_visual_rect.Map(*expected_transform);
// The clip has animating transform, so it doesn't apply to the visual rect.
- expected_visual_rect_expanded_for_animation = InfiniteLooseFloatClipRect();
+ expected_visual_rect_expanded_for_compositing = InfiniteLooseFloatClipRect();
EXPECT_FALSE(expected_visual_rect.IsTight());
expected_clip = FloatClipRect(clip->UnsnappedClipRect());
expected_clip.Map(*expected_transform);
@@ -605,8 +606,8 @@ TEST_P(GeometryMapperTest, ExpandVisualRectWithClipAfterAnimatingTransform) {
EXPECT_TRUE(expected_clip.IsTight());
// The visual rect is expanded first to infinity because of the transform
// animation, then clipped by the clip.
- expected_visual_rect_expanded_for_animation = expected_clip;
- expected_visual_rect_expanded_for_animation->ClearIsTight();
+ expected_visual_rect_expanded_for_compositing = expected_clip;
+ expected_visual_rect_expanded_for_compositing->ClearIsTight();
CheckMappings();
}
@@ -664,9 +665,56 @@ TEST_P(GeometryMapperTest,
// The visual rect is expanded to infinity because of the transform animation,
// then clipped by clip1. clip2 doesn't apply because it's below the animating
// transform.
- expected_visual_rect_expanded_for_animation =
+ expected_visual_rect_expanded_for_compositing =
FloatClipRect(clip1->UnsnappedClipRect());
- expected_visual_rect_expanded_for_animation->ClearIsTight();
+ expected_visual_rect_expanded_for_compositing->ClearIsTight();
+ CheckMappings();
+}
+
+TEST_P(GeometryMapperTest, ExpandVisualRectForFixed) {
+ auto above_viewport = CreateTransform(t0(), TransformationMatrix());
+ auto viewport = CreateTransform(*above_viewport, TransformationMatrix());
+ auto scroll_translation = CreateScrollTranslation(
+ *viewport, -100, -200, IntRect(0, 0, 800, 600), IntSize(2400, 1800),
+ CompositingReason::kOverflowScrolling);
+
+ auto fixed_translate = TransformationMatrix().Translate(100, 0);
+
+ const FloatSize fixed_offset(200, 200);
+ TransformPaintPropertyNode::State fixed_state{fixed_offset, nullptr,
+ scroll_translation};
+ fixed_state.direct_compositing_reasons = CompositingReason::kFixedPosition;
+ auto fixed_transform =
+ TransformPaintPropertyNode::Create(*viewport, std::move(fixed_state));
+
+ const FloatSize child_of_fixed_offset(50, 50);
+ TransformPaintPropertyNode::State child_of_fixed_state{child_of_fixed_offset};
+ auto child_of_fixed = TransformPaintPropertyNode::Create(
+ *fixed_transform, std::move(child_of_fixed_state));
+
+ local_state.SetTransform(*child_of_fixed);
+ ancestor_state.SetTransform(*viewport);
+
+ const FloatSize child_of_fixed_size(100, 100);
+ input_rect = FloatRect(FloatPoint(), child_of_fixed_size);
+
+ const FloatSize descendant_offset = fixed_offset + child_of_fixed_offset;
+ expected_translation_2d = descendant_offset;
+ expected_transformed_rect =
+ FloatRect(FloatPoint(descendant_offset), child_of_fixed_size);
+ expected_visual_rect = FloatClipRect(expected_transformed_rect);
+ expected_visual_rect_expanded_for_compositing =
+ FloatClipRect(FloatRect(150, 50, 1700, 1300));
+
+ CheckMappings();
+
+ // If we're not mapping to the viewport, the fixed rect should not be
+ // expanded.
+ ancestor_state.SetTransform(*above_viewport);
+ expected_transform = TransformationMatrix().Translate(
+ descendant_offset.Width(), descendant_offset.Height());
+ expected_visual_rect.ClearIsTight();
+ expected_visual_rect_expanded_for_compositing = expected_visual_rect;
CheckMappings();
}
@@ -733,21 +781,18 @@ 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,
- // in such case, no clips are applied.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- EXPECT_FALSE(success);
- } else {
- EXPECT_TRUE(success);
- FloatClipRect expected(FloatRect(-100, 0, 100, 100));
- expected.ClearIsTight();
- EXPECT_CLIP_RECT_EQ(expected, result);
- }
+ // clip of the source state. Known bugs in pre-CompositeAfterPaint or
+ // CompositeAfterPaint without LayoutNGBlockFragmentation would make such
+ // query. In such cases, no clips are applied.
+ EXPECT_TRUE(success);
+ FloatClipRect expected(FloatRect(-100, 0, 100, 100));
+ expected.ClearIsTight();
+ EXPECT_CLIP_RECT_EQ(expected, result);
result = FloatClipRect(input_rect);
GeometryMapper::LocalToAncestorVisualRect(transform2_and_clip_state,
transform1_state, result);
- FloatClipRect expected(FloatRect(20, -40, 40, 30));
+ expected = FloatClipRect(FloatRect(20, -40, 40, 30));
// This is because the combined Rotate(45) and Rotate(-45) is not exactly a
// translation-only transform due to calculation errors.
expected.ClearIsTight();
@@ -876,9 +921,9 @@ TEST_P(GeometryMapperTest,
// The visual rect is expanded to infinity because of the filter animation,
// the clipped by clip1. clip2 doesn't apply because it's below the animating
// filter.
- expected_visual_rect_expanded_for_animation =
+ expected_visual_rect_expanded_for_compositing =
FloatClipRect(clip1->UnsnappedClipRect());
- expected_visual_rect_expanded_for_animation->ClearIsTight();
+ expected_visual_rect_expanded_for_compositing->ClearIsTight();
CheckMappings();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
index afbb15b4905..410e1eb0576 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
@@ -40,6 +40,7 @@ void GeometryMapperTransformCache::Update(
const GeometryMapperTransformCache& parent =
node.UnaliasedParent()->GetTransformCache();
+ has_fixed_ = node.RequiresCompositingForFixedPosition() || parent.has_fixed_;
// screen_transform_ will be updated only when needed.
screen_transform_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
index da3cb0d3af5..782df5cd8da 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
@@ -20,6 +20,9 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
USING_FAST_MALLOC(GeometryMapperTransformCache);
public:
GeometryMapperTransformCache() = default;
+ GeometryMapperTransformCache(const GeometryMapperTransformCache&) = delete;
+ GeometryMapperTransformCache& operator=(const GeometryMapperTransformCache&) =
+ delete;
static void ClearCache();
bool IsValid() const;
@@ -112,6 +115,8 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
plane_root_transform_->has_animation;
}
+ bool has_fixed() const { return has_fixed_; }
+
private:
friend class GeometryMapperTransformCacheTest;
@@ -203,8 +208,10 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
};
std::unique_ptr<ScreenTransform> screen_transform_;
+ // Whether or not there is a fixed position transform to the root.
+ bool has_fixed_ = false;
+
unsigned cache_generation_ = s_global_generation - 1;
- DISALLOW_COPY_AND_ASSIGN(GeometryMapperTransformCache);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
index 648fbeed327..b7fc439e33d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
@@ -53,7 +53,7 @@ String HitTestData::ToString() const {
if (scroll_translation) {
if (printed_top_level_field)
sb.Append(", ");
- sb.AppendFormat("scroll_translation: %p", scroll_translation);
+ sb.AppendFormat("scroll_translation: %p", scroll_translation.get());
}
sb.Append("}");
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 b1632dda001..c6a8afb3d36 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_
+#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/touch_action_rect.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -21,7 +22,7 @@ struct PLATFORM_EXPORT HitTestData {
// container, and whether the region allows composited scrolling depends
// whether the scroll_translation is composited.
IntRect scroll_hit_test_rect;
- const TransformPaintPropertyNode* scroll_translation = nullptr;
+ scoped_refptr<const TransformPaintPropertyNode> scroll_translation;
bool operator==(const HitTestData& rhs) const {
return touch_action_rects == rhs.touch_action_rects &&
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 d5120160bfc..4e0c040c170 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
@@ -23,7 +23,7 @@ size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const {
sk_sp<PaintRecord> PaintArtifact::GetPaintRecord(
const PropertyTreeState& replay_state) const {
return PaintChunksToCcLayer::Convert(
- PaintChunkSubset(this), replay_state, gfx::Vector2dF(),
+ PaintChunkSubset(this), replay_state, FloatPoint(),
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
}
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 1f23d41ad3c..f3a1c03ee9e 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
@@ -27,12 +27,7 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
USING_FAST_MALLOC(PaintArtifact);
public:
- explicit PaintArtifact(wtf_size_t initial_display_item_list_capacity = 0,
- wtf_size_t initial_paint_chunks_capacity = 0)
- : display_item_list_(initial_display_item_list_capacity) {
- chunks_.ReserveInitialCapacity(initial_paint_chunks_capacity);
- }
-
+ PaintArtifact() = default;
PaintArtifact(const PaintArtifact& other) = delete;
PaintArtifact& operator=(const PaintArtifact& other) = delete;
PaintArtifact(PaintArtifact&& other) = delete;
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 7ad9c06a93e..634e4ebc368 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
@@ -19,6 +19,7 @@ struct SameSizeAsPaintChunk {
PropertyTreeState properties;
IntRect bounds;
IntRect drawable_bounds;
+ IntRect rect_known_to_be_opaque;
void* hit_test_data;
void* layer_selection;
bool b[2];
@@ -34,10 +35,12 @@ bool PaintChunk::EqualsForUnderInvalidationChecking(
raster_effect_outset == other.raster_effect_outset &&
((!hit_test_data && !other.hit_test_data) ||
(hit_test_data && other.hit_test_data &&
- *hit_test_data == *other.hit_test_data));
- // known_to_be_opaque is not checked ]because it's updated when we create the
- // next chunk or release chunks. We ensure its correctness with unit tests and
- // under-invalidation checking of display items.
+ *hit_test_data == *other.hit_test_data)) &&
+ effectively_invisible == other.effectively_invisible;
+ // Derived fields like rect_known_to_be_opaque are not checked because they
+ // are updated when we create the next chunk or release chunks. We ensure
+ // their correctness with unit tests and under-invalidation checking of
+ // display items.
}
size_t PaintChunk::MemoryUsageInBytes() const {
@@ -55,10 +58,10 @@ String PaintChunk::ToString() const {
StringBuilder sb;
sb.AppendFormat(
"PaintChunk(begin=%u, end=%u, id=%s cacheable=%d props=(%s) bounds=%s "
- "known_to_be_opaque=%d",
+ "rect_known_to_be_opaque=%s effectively_invisible=%d",
begin_index, end_index, id.ToString().Utf8().c_str(), is_cacheable,
properties.ToString().Utf8().c_str(), bounds.ToString().Utf8().c_str(),
- known_to_be_opaque);
+ rect_known_to_be_opaque.ToString().Utf8().c_str(), effectively_invisible);
if (hit_test_data) {
sb.Append(", hit_test_data=");
sb.Append(hit_test_data->ToString());
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 cbf62f58051..e5a45a5c526 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
@@ -10,6 +10,7 @@
#include "base/dcheck_is_on.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/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h"
#include "third_party/blink/renderer/platform/graphics/paint/layer_selection_data.h"
@@ -36,18 +37,20 @@ struct PLATFORM_EXPORT PaintChunk {
PaintChunk(wtf_size_t begin,
wtf_size_t end,
const Id& id,
- const PropertyTreeStateOrAlias& props)
+ const PropertyTreeStateOrAlias& props,
+ bool effectively_invisible = false)
: begin_index(begin),
end_index(end),
background_color(Color::kTransparent),
background_color_area(0u),
id(id),
properties(props),
- known_to_be_opaque(false),
- text_known_to_be_on_opaque_background(false),
+ text_known_to_be_on_opaque_background(true),
+ has_text(false),
is_cacheable(id.client.IsCacheable()),
client_is_just_created(id.client.IsJustCreated()),
- is_moved_from_cached_subsequence(false) {}
+ is_moved_from_cached_subsequence(false),
+ effectively_invisible(effectively_invisible) {}
// Move a paint chunk from a cached subsequence.
PaintChunk(wtf_size_t begin, PaintChunk&& other)
@@ -61,13 +64,15 @@ struct PLATFORM_EXPORT PaintChunk {
layer_selection_data(std::move(other.layer_selection_data)),
bounds(other.bounds),
drawable_bounds(other.drawable_bounds),
+ rect_known_to_be_opaque(other.rect_known_to_be_opaque),
raster_effect_outset(other.raster_effect_outset),
- known_to_be_opaque(other.known_to_be_opaque),
text_known_to_be_on_opaque_background(
other.text_known_to_be_on_opaque_background),
+ has_text(other.has_text),
is_cacheable(other.is_cacheable),
client_is_just_created(false),
- is_moved_from_cached_subsequence(true) {
+ is_moved_from_cached_subsequence(true),
+ effectively_invisible(other.effectively_invisible) {
#if DCHECK_IS_ON()
DCHECK(other.id.client.IsAlive());
DCHECK(!other.id.client.IsJustCreated());
@@ -155,21 +160,25 @@ struct PLATFORM_EXPORT PaintChunk {
// chunk.
IntRect drawable_bounds;
+ IntRect rect_known_to_be_opaque;
+
// Some raster effects can exceed |bounds| in the rasterization space. This
// is the maximum DisplayItemClient::VisualRectOutsetForRasterEffects() of
// all clients of items in this chunk.
RasterEffectOutset raster_effect_outset = RasterEffectOutset::kNone;
- // True if the bounds are filled entirely with opaque contents.
- bool known_to_be_opaque : 1;
- // True if all text is known to be on top of an opaque background.
+ // True if all text is known to be on top of opaque backgrounds or there is
+ // not text. Though in theory the value doesn't matter when there is no text,
+ // being true can simplify code.
bool text_known_to_be_on_opaque_background : 1;
+ bool has_text : 1;
// End of derived data.
// The following fields are put here to avoid memory gap.
bool is_cacheable : 1;
bool client_is_just_created : 1;
bool is_moved_from_cached_subsequence : 1;
+ bool effectively_invisible : 1;
};
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const PaintChunk&);
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 f75d3bea48d..54b4a8ce924 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
@@ -34,6 +34,26 @@ bool PaintChunker::IsInInitialState() const {
}
#endif
+void PaintChunker::StartMarkingClientsForValidation(
+ Vector<const DisplayItemClient*>& clients_to_validate) {
+#if DCHECK_IS_ON()
+ DCHECK(IsInInitialState());
+#endif
+ DCHECK(!clients_to_validate_);
+ clients_to_validate_ = &clients_to_validate;
+}
+
+void PaintChunker::MarkClientForValidation(const DisplayItemClient& client) {
+ if (clients_to_validate_ && !client.IsMarkedForValidation()) {
+ clients_to_validate_->push_back(&client);
+ client.MarkForValidation();
+ }
+}
+
+void PaintChunker::StopMarkingClientsForValidation() {
+ clients_to_validate_ = nullptr;
+}
+
void PaintChunker::UpdateCurrentPaintChunkProperties(
const PaintChunk::Id* chunk_id,
const PropertyTreeStateOrAlias& properties) {
@@ -55,6 +75,10 @@ void PaintChunker::AppendByMoving(PaintChunk&& chunk) {
wtf_size_t next_chunk_begin_index =
chunks_->IsEmpty() ? 0 : chunks_->back().end_index;
chunks_->emplace_back(next_chunk_begin_index, std::move(chunk));
+ // This chunk was copied from the cache, so it should already be valid; hence
+ // we don't call MarkClientForValidation().
+ DCHECK(!chunks_->back().id.client.IsCacheable() ||
+ chunks_->back().id.client.IsValid());
}
bool PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) {
@@ -73,7 +97,9 @@ bool PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) {
next_chunk_id_.emplace(id);
FinalizeLastChunkProperties();
wtf_size_t begin = chunks_->IsEmpty() ? 0 : chunks_->back().end_index;
- chunks_->emplace_back(begin, begin, *next_chunk_id_, current_properties_);
+ MarkClientForValidation(next_chunk_id_->client);
+ chunks_->emplace_back(begin, begin, *next_chunk_id_, current_properties_,
+ current_effectively_invisible_);
next_chunk_id_ = absl::nullopt;
will_force_new_chunk_ = false;
return true;
@@ -103,21 +129,22 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
ProcessBackgroundColorCandidate(chunk.id, item_color, item_area);
}
- constexpr wtf_size_t kMaxRegionComplexity = 10;
if (should_compute_contents_opaque_ && item.IsDrawing()) {
const DrawingDisplayItem& drawing = To<DrawingDisplayItem>(item);
- if (drawing.KnownToBeOpaque() &&
- last_chunk_known_to_be_opaque_region_.Complexity() <
- kMaxRegionComplexity) {
- last_chunk_known_to_be_opaque_region_.Unite(item.VisualRect());
- }
- if (last_chunk_text_known_to_be_on_opaque_background_) {
+ chunk.rect_known_to_be_opaque = MaximumCoveredRect(
+ chunk.rect_known_to_be_opaque, drawing.RectKnownToBeOpaque());
+ if (chunk.text_known_to_be_on_opaque_background) {
if (const auto* paint_record = drawing.GetPaintRecord().get()) {
if (paint_record->has_draw_text_ops()) {
- last_chunk_text_known_to_be_on_opaque_background_ =
- last_chunk_known_to_be_opaque_region_.Contains(item.VisualRect());
+ chunk.has_text = true;
+ chunk.text_known_to_be_on_opaque_background =
+ chunk.rect_known_to_be_opaque.Contains(item.VisualRect());
}
}
+ } else {
+ // text_known_to_be_on_opaque_background should be initially true before
+ // we see any text.
+ DCHECK(chunk.has_text);
}
}
@@ -257,15 +284,6 @@ void PaintChunker::FinalizeLastChunkProperties() {
return;
auto& chunk = chunks_->back();
- if (should_compute_contents_opaque_) {
- chunk.known_to_be_opaque =
- last_chunk_known_to_be_opaque_region_.Contains(chunk.bounds);
- chunk.text_known_to_be_on_opaque_background =
- last_chunk_text_known_to_be_on_opaque_background_;
- last_chunk_known_to_be_opaque_region_ = Region();
- last_chunk_text_known_to_be_on_opaque_background_ = true;
- }
-
if (candidate_background_color_ != Color::kTransparent) {
chunk.background_color = candidate_background_color_;
chunk.background_color_area = candidate_background_area_;
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 3eefb4c87b6..937339226a1 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
@@ -6,10 +6,8 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNKER_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "cc/input/layer_selection_bound.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
@@ -28,6 +26,8 @@ class PLATFORM_EXPORT PaintChunker final {
public:
explicit PaintChunker(Vector<PaintChunk>& chunks) { ResetChunks(&chunks); }
+ PaintChunker(const PaintChunker&) = delete;
+ PaintChunker& operator=(const PaintChunker&) = delete;
// Finishes current chunks if any, and makes it ready to create chunks into
// the given vector if not null.
@@ -37,6 +37,11 @@ class PLATFORM_EXPORT PaintChunker final {
bool IsInInitialState() const;
#endif
+ void StartMarkingClientsForValidation(
+ Vector<const DisplayItemClient*>& clients_to_validate);
+ void MarkClientForValidation(const DisplayItemClient& client);
+ void StopMarkingClientsForValidation();
+
const PropertyTreeStateOrAlias& CurrentPaintChunkProperties() const {
return current_properties_;
}
@@ -87,6 +92,13 @@ class PLATFORM_EXPORT PaintChunker final {
// Returns true if a new chunk is created.
bool EnsureChunk() { return EnsureCurrentChunk(*next_chunk_id_); }
+ bool CurrentEffectivelyInvisible() const {
+ return current_effectively_invisible_;
+ }
+ void SetCurrentEffectivelyInvisible(bool invisible) {
+ current_effectively_invisible_ = invisible;
+ }
+
private:
// Returns true if a new chunk is created.
bool EnsureCurrentChunk(const PaintChunk::Id&);
@@ -94,6 +106,7 @@ class PLATFORM_EXPORT PaintChunker final {
void FinalizeLastChunkProperties();
Vector<PaintChunk>* chunks_ = nullptr;
+ Vector<const DisplayItemClient*>* clients_to_validate_ = nullptr;
// 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
@@ -106,20 +119,16 @@ class PLATFORM_EXPORT PaintChunker final {
PropertyTreeStateOrAlias current_properties_ =
PropertyTreeState::Uninitialized();
- Region last_chunk_known_to_be_opaque_region_;
- bool last_chunk_text_known_to_be_on_opaque_background_ = true;
-
// True when an item forces a new chunk (e.g., foreign display items), and for
// the item following a forced chunk. PaintController also forces new chunks
// before and after subsequences by calling ForceNewChunk().
bool will_force_new_chunk_ = true;
+ bool current_effectively_invisible_ = false;
bool should_compute_contents_opaque_ = true;
Color candidate_background_color_ = Color::kTransparent;
float candidate_background_area_ = 0;
-
- 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 ad5dbd0444a..349d4e820f4 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.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"
@@ -39,18 +40,33 @@ class TestChunkerDisplayItem : public DrawingDisplayItem {
const DisplayItemClient& client,
DisplayItem::Type type = DisplayItem::kDrawingFirst,
const IntRect& visual_rect = IntRect())
- : DrawingDisplayItem(client, type, visual_rect, nullptr) {}
+ : DrawingDisplayItem(client,
+ type,
+ visual_rect,
+ nullptr,
+ client.GetPaintInvalidationReason()) {}
};
+sk_sp<const PaintRecord> OpaquePaintRecord(const IntRect& visual_rect) {
+ PaintRecorder recorder;
+ auto* canvas = recorder.beginRecording(visual_rect);
+ PaintFlags flags;
+ flags.setColor(SK_ColorBLACK);
+ canvas->drawRect(visual_rect, flags);
+ return recorder.finishRecordingAsPicture();
+}
+
class TestChunkerOpaqueDisplayItem : public DrawingDisplayItem {
public:
explicit TestChunkerOpaqueDisplayItem(
const DisplayItemClient& client,
DisplayItem::Type type = DisplayItem::kDrawingFirst,
const IntRect& visual_rect = IntRect())
- : DrawingDisplayItem(client, type, visual_rect, nullptr) {
- SetKnownToBeOpaqueForTesting();
- }
+ : DrawingDisplayItem(client,
+ type,
+ visual_rect,
+ OpaquePaintRecord(visual_rect),
+ client.GetPaintInvalidationReason()) {}
};
class TestDisplayItemRequiringSeparateChunk : public ForeignLayerDisplayItem {
@@ -60,7 +76,8 @@ class TestDisplayItemRequiringSeparateChunk : public ForeignLayerDisplayItem {
: ForeignLayerDisplayItem(client,
DisplayItem::kForeignLayerPlugin,
cc::Layer::Create(),
- IntPoint()) {}
+ IntPoint(),
+ client.GetPaintInvalidationReason()) {}
};
TEST_F(PaintChunkerTest, Empty) {
@@ -136,6 +153,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
chunker.UpdateCurrentPaintChunkProperties(&id3, another_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 2, id1,
DefaultPaintChunkProperties()),
IsPaintChunk(2, 3, id2, simple_transform),
@@ -191,6 +209,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
chunker.IncrementDisplayItemIndex(item_after_restore);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(
@@ -234,6 +253,7 @@ TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms) {
TestChunkerDisplayItem item_after_restore(client_, DisplayItemType(10));
chunker.IncrementDisplayItemIndex(item_after_restore);
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 1, id1,
DefaultPaintChunkProperties()),
IsPaintChunk(1, 3, id2, simple_transform),
@@ -265,6 +285,8 @@ TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems) {
chunker.UpdateCurrentPaintChunkProperties(&id3, second_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 1, id1,
DefaultPaintChunkProperties()),
IsPaintChunk(1, 2, id3, second_transform)));
@@ -295,6 +317,7 @@ TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested) {
DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(i3);
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(
@@ -341,6 +364,7 @@ TEST_F(PaintChunkerTest, ForceNewChunkWithNewId) {
EXPECT_FALSE(chunker.WillForceNewChunk());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(IsPaintChunk(0, 2, id0, DefaultPaintChunkProperties()),
@@ -384,6 +408,7 @@ TEST_F(PaintChunkerTest, ForceNewChunkWithoutNewId) {
chunker.IncrementDisplayItemIndex(
TestChunkerDisplayItem(client_, DisplayItemType(4)));
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(IsPaintChunk(0, 2, id0, DefaultPaintChunkProperties()),
@@ -412,8 +437,9 @@ TEST_F(PaintChunkerTest, SetAndImmediatelyUnSetWillForceNewChunk) {
EXPECT_FALSE(chunker.WillForceNewChunk());
chunker.IncrementDisplayItemIndex(
TestChunkerDisplayItem(client_, DisplayItemType(1)));
- EXPECT_EQ(1u, chunks.size());
+ chunker.ResetChunks(nullptr);
+ EXPECT_EQ(1u, chunks.size());
EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 3, id0,
DefaultPaintChunkProperties())));
}
@@ -438,6 +464,7 @@ TEST_F(PaintChunkerTest, NoNewChunkForSamePropertyDifferentIds) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 6, id0,
DefaultPaintChunkProperties())));
}
@@ -466,6 +493,7 @@ TEST_F(PaintChunkerTest, ChunksFollowingForcedChunk) {
chunker.IncrementDisplayItemIndex(after_forced1);
chunker.IncrementDisplayItemIndex(after_forced2);
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(
@@ -511,6 +539,7 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
TestChunkerDisplayItem after_restore(client_, DisplayItemType(4));
chunker.IncrementDisplayItemIndex(after_restore);
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(
@@ -557,6 +586,7 @@ TEST_F(PaintChunkerTest, AddHitTestDataToCurrentChunk) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(
client_, DisplayItemType(5), IntRect(0, 0, 10, 10)));
+ chunker.ResetChunks(nullptr);
HitTestData hit_test_data;
hit_test_data.touch_action_rects = {
{IntRect(20, 30, 40, 50), TouchAction::kPan}};
@@ -615,6 +645,7 @@ TEST_F(PaintChunkerTest, AddHitTestDataToCurrentChunkWheelRegionsEnabled) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(
client_, DisplayItemType(5), IntRect(0, 0, 10, 10)));
+ chunker.ResetChunks(nullptr);
HitTestData hit_test_data;
hit_test_data.touch_action_rects = {
{IntRect(20, 30, 40, 50), TouchAction::kPan}};
@@ -667,6 +698,7 @@ TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueAllOpaqueItems) {
chunker.IncrementDisplayItemIndex(TestChunkerOpaqueDisplayItem(
client3, DisplayItemType(4), IntRect(50, 50, 100, 100)));
+ chunker.ResetChunks(nullptr);
EXPECT_THAT(
chunks,
ElementsAre(
@@ -677,9 +709,9 @@ TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueAllOpaqueItems) {
IsPaintChunk(3, 5, PaintChunk::Id(client1, DisplayItemType(3)),
properties, nullptr, IntRect(0, 0, 150, 150))));
ASSERT_EQ(3u, chunks.size());
- EXPECT_TRUE(chunks[0].known_to_be_opaque);
- EXPECT_TRUE(chunks[1].known_to_be_opaque);
- EXPECT_FALSE(chunks[2].known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[0].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 150), chunks[1].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[2].rect_known_to_be_opaque);
}
TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueWithHitTest) {
@@ -719,6 +751,8 @@ TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueWithHitTest) {
PaintChunk::Id(client1, DisplayItemType(6)), IntRect(0, 100, 200, 100),
TouchAction::kAuto, false);
+ chunker.ResetChunks(nullptr);
+
EXPECT_THAT(
chunks,
ElementsAre(
@@ -731,10 +765,10 @@ TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueWithHitTest) {
IsPaintChunk(2, 3, PaintChunk::Id(client1, DisplayItemType(5)),
properties, nullptr, IntRect(0, 0, 200, 200))));
ASSERT_EQ(4u, chunks.size());
- EXPECT_FALSE(chunks[0].known_to_be_opaque);
- EXPECT_TRUE(chunks[1].known_to_be_opaque);
- EXPECT_TRUE(chunks[2].known_to_be_opaque);
- EXPECT_FALSE(chunks[3].known_to_be_opaque);
+ EXPECT_EQ(IntRect(), chunks[0].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[1].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[2].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[3].rect_known_to_be_opaque);
}
TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueMixedOpaquenessItems) {
@@ -773,7 +807,6 @@ TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueMixedOpaquenessItems) {
TestChunkerDisplayItem(client2, DisplayItemType(7), visual_rect2));
chunker.ResetChunks(nullptr);
-
EXPECT_THAT(
chunks,
ElementsAre(
@@ -786,10 +819,10 @@ TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueMixedOpaquenessItems) {
IsPaintChunk(5, 7, PaintChunk::Id(client1, DisplayItemType(6)),
properties, nullptr, IntRect(0, 0, 100, 100))));
ASSERT_EQ(4u, chunks.size());
- EXPECT_FALSE(chunks[0].known_to_be_opaque);
- EXPECT_FALSE(chunks[1].known_to_be_opaque);
- EXPECT_TRUE(chunks[2].known_to_be_opaque);
- EXPECT_TRUE(chunks[3].known_to_be_opaque);
+ EXPECT_EQ(IntRect(), chunks[0].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(50, 50, 50, 50), chunks[1].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[2].rect_known_to_be_opaque);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), chunks[3].rect_known_to_be_opaque);
}
} // 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 8216053bedb..c2b48956d3f 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
@@ -9,14 +9,17 @@
#include "base/auto_reset.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.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/graphics/paint/ignore_paint_timing_scope.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
+PaintController::CounterForTesting* PaintController::counter_for_testing_ =
+ nullptr;
+
PaintController::PaintController(Usage usage)
: usage_(usage),
current_paint_artifact_(usage == kMultiplePaints
@@ -43,6 +46,24 @@ PaintController::~PaintController() {
#endif
}
+void PaintController::ReserveCapacity() {
+ static constexpr wtf_size_t kDefaultDisplayItemListCapacity = 16;
+ auto display_item_list_capacity = kDefaultDisplayItemListCapacity;
+ if (current_paint_artifact_) {
+ if (current_paint_artifact_->GetDisplayItemList().size()) {
+ display_item_list_capacity =
+ current_paint_artifact_->GetDisplayItemList().size();
+ }
+ new_paint_artifact_->PaintChunks().ReserveCapacity(
+ current_paint_artifact_->PaintChunks().size());
+ new_subsequences_.tree.ReserveCapacity(current_subsequences_.tree.size());
+ new_subsequences_.map.ReserveCapacityForSize(
+ current_subsequences_.map.size());
+ }
+ new_paint_artifact_->GetDisplayItemList().ReserveCapacity(
+ display_item_list_capacity);
+}
+
void PaintController::EnsureChunk() {
if (paint_chunker_.EnsureChunk())
CheckNewChunk();
@@ -111,8 +132,7 @@ bool PaintController::UseCachedItemIfPossible(const DisplayItemClient& client,
if (!ClientCacheIsValid(client))
return false;
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
- IsCheckingUnderInvalidation()) {
+ if (IsCheckingUnderInvalidation()) {
// We are checking under-invalidation of a subsequence enclosing this
// display item. Let the client continue to actually paint the display item.
return false;
@@ -126,11 +146,6 @@ bool PaintController::UseCachedItemIfPossible(const DisplayItemClient& client,
}
++num_cached_new_items_;
- if (!RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- ProcessNewItem(new_paint_artifact_->GetDisplayItemList().AppendByMoving(
- current_paint_artifact_->GetDisplayItemList()[cached_item]));
- }
-
next_item_to_match_ = cached_item + 1;
// Items before |next_item_to_match_| have been copied so we don't need to
// index them.
@@ -138,16 +153,18 @@ bool PaintController::UseCachedItemIfPossible(const DisplayItemClient& client,
next_item_to_index_ = next_item_to_match_;
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- if (!IsCheckingUnderInvalidation()) {
- under_invalidation_checking_begin_ = cached_item;
- under_invalidation_checking_end_ = cached_item + 1;
- under_invalidation_message_prefix_ = "";
- }
+ EnsureUnderInvalidationChecker().WouldUseCachedItem(cached_item);
// Return false to let the painter actually paint. We will check if the new
// painting is the same as the cached one.
return false;
}
+ DisplayItem& new_item =
+ new_paint_artifact_->GetDisplayItemList().AppendByMoving(
+ current_paint_artifact_->GetDisplayItemList()[cached_item]);
+ new_item.SetPaintInvalidationReason(PaintInvalidationReason::kNone);
+ ProcessNewItem(new_item);
+
return true;
}
@@ -162,12 +179,12 @@ bool PaintController::UseCachedSubsequenceIfPossible(
if (!ClientCacheIsValid(client))
return false;
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
- IsCheckingUnderInvalidation()) {
+ if (IsCheckingUnderInvalidation()) {
// We are checking under-invalidation of an ancestor subsequence enclosing
// this one. The ancestor subsequence is supposed to have already "copied",
// so we should let the client continue to actually paint the descendant
// subsequences without "copying".
+ ++num_cached_new_subsequences_;
return false;
}
@@ -208,16 +225,14 @@ bool PaintController::UseCachedSubsequenceIfPossible(
++num_cached_new_subsequences_;
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- DCHECK(!IsCheckingUnderInvalidation());
- under_invalidation_checking_begin_ = start_item_index;
- under_invalidation_checking_end_ = end_item_index;
- under_invalidation_message_prefix_ =
- "(In cached subsequence for " + client.DebugName() + ")";
+ EnsureUnderInvalidationChecker().WouldUseCachedSubsequence(client);
// Return false to let the painter actually paint. We will check if the new
// painting is the same as the cached one.
return false;
}
+ // This subsequence was copied from the cache, so client must already be
+ // valid, hence we don't call MarkClientForValidation(client).
AppendSubsequenceByMoving(client, subsequence_index,
markers.start_chunk_index, markers.end_chunk_index);
return true;
@@ -240,58 +255,27 @@ PaintController::GetSubsequenceMarkers(const DisplayItemClient& client) const {
return &current_subsequences_.tree[index];
}
-void PaintController::BeginSubsequence(wtf_size_t& subsequence_index,
- wtf_size_t& start_chunk_index) {
+wtf_size_t PaintController::BeginSubsequence(const DisplayItemClient& client) {
// Force new paint chunk which is required for subsequence caching.
SetWillForceNewChunk(true);
- subsequence_index = new_subsequences_.tree.size();
- new_subsequences_.tree.emplace_back();
- start_chunk_index = NumNewChunks();
+ new_subsequences_.tree.push_back(SubsequenceMarkers{&client, NumNewChunks()});
+ return new_subsequences_.tree.size() - 1;
}
-void PaintController::EndSubsequence(const DisplayItemClient& client,
- wtf_size_t subsequence_index,
- wtf_size_t start_chunk_index) {
- wtf_size_t end_chunk_index = NumNewChunks();
+void PaintController::EndSubsequence(wtf_size_t subsequence_index) {
+ auto& markers = new_subsequences_.tree[subsequence_index];
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
- IsCheckingUnderInvalidation()) {
- const SubsequenceMarkers* markers = GetSubsequenceMarkers(client);
- if (!markers) {
- if (start_chunk_index != end_chunk_index) {
- ShowSequenceUnderInvalidationError(
- "under-invalidation : unexpected subsequence", client);
- CHECK(false);
- }
- } else {
- if (markers->end_chunk_index - markers->start_chunk_index !=
- end_chunk_index - start_chunk_index) {
- ShowSequenceUnderInvalidationError(
- "under-invalidation: new subsequence wrong length", client);
- CHECK(false);
- }
- auto old_chunk_index = markers->start_chunk_index;
- for (auto new_chunk_index = start_chunk_index;
- new_chunk_index < end_chunk_index;
- ++new_chunk_index, ++old_chunk_index) {
- const auto& old_chunk =
- current_paint_artifact_->PaintChunks()[old_chunk_index];
- const auto& new_chunk =
- new_paint_artifact_->PaintChunks()[new_chunk_index];
- if (!old_chunk.EqualsForUnderInvalidationChecking(new_chunk)) {
- ShowSequenceUnderInvalidationError(
- "under-invalidation: chunk changed", client);
- CHECK(false) << "Changed chunk: " << new_chunk;
- }
- }
- }
+ if (IsCheckingUnderInvalidation()) {
+ under_invalidation_checker_->WillEndSubsequence(*markers.client,
+ markers.start_chunk_index);
}
- if (start_chunk_index == end_chunk_index) {
- // Omit the empty subsequence. The forcing-new-chunk flag set by
- // BeginSubsequence() still applies, but this not a big deal because empty
- // subsequences are not common. Also we should not clear the flag because
- // there might be unhandled flag that was set before this empty subsequence.
+ wtf_size_t end_chunk_index = NumNewChunks();
+ if (markers.start_chunk_index == end_chunk_index) {
+ // Omit the empty subsequence. The WillForceNewChunk flag set in
+ // BeginSubsequence() still applies, but it's useful to reduce churns of
+ // raster invalidation and compositing when the subsequence switches between
+ // empty and non-empty.
new_subsequences_.tree.pop_back();
return;
}
@@ -300,24 +284,23 @@ void PaintController::EndSubsequence(const DisplayItemClient& client,
SetWillForceNewChunk(true);
#if DCHECK_IS_ON()
- DCHECK(!new_subsequences_.map.Contains(&client))
- << "Multiple subsequences for client: " << client.DebugName();
+ DCHECK(!new_subsequences_.map.Contains(markers.client))
+ << "Multiple subsequences for client: " << markers.client->DebugName();
// Check tree integrity.
if (subsequence_index > 0) {
- DCHECK_GE(start_chunk_index,
+ DCHECK_GE(markers.start_chunk_index,
new_subsequences_.tree[subsequence_index - 1].end_chunk_index);
}
for (auto i = subsequence_index + 1; i < new_subsequences_.tree.size(); i++) {
auto& child_markers = new_subsequences_.tree[i];
- DCHECK_GE(child_markers.start_chunk_index, start_chunk_index);
+ DCHECK_GE(child_markers.start_chunk_index, markers.start_chunk_index);
DCHECK_LE(child_markers.end_chunk_index, end_chunk_index);
}
#endif
- new_subsequences_.map.insert(&client, subsequence_index);
- new_subsequences_.tree[subsequence_index] =
- SubsequenceMarkers{&client, start_chunk_index, end_chunk_index};
+ new_subsequences_.map.insert(markers.client, subsequence_index);
+ markers.end_chunk_index = end_chunk_index;
}
void PaintController::CheckNewItem(DisplayItem& display_item) {
@@ -342,14 +325,22 @@ void PaintController::CheckNewItem(DisplayItem& display_item) {
}
#endif
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
- CheckUnderInvalidation();
+ if (IsCheckingUnderInvalidation())
+ under_invalidation_checker_->CheckNewItem();
+}
+
+void PaintController::MarkClientForValidation(const DisplayItemClient& client) {
+ if (clients_to_validate_ && !client.IsMarkedForValidation()) {
+ clients_to_validate_->push_back(&client);
+ client.MarkForValidation();
+ }
}
void PaintController::ProcessNewItem(DisplayItem& display_item) {
if (IsSkippingCache() && usage_ == kMultiplePaints) {
display_item.Client().Invalidate(PaintInvalidationReason::kUncacheable);
- display_item.SetUncacheable();
+ display_item.SetPaintInvalidationReason(
+ PaintInvalidationReason::kUncacheable);
}
if (paint_chunker_.IncrementDisplayItemIndex(display_item))
@@ -376,6 +367,9 @@ void PaintController::CheckNewChunk() {
new_paint_chunk_id_index_map_);
}
#endif
+
+ if (IsCheckingUnderInvalidation())
+ under_invalidation_checker_->CheckNewChunk();
}
void PaintController::InvalidateAllForTesting() {
@@ -413,7 +407,7 @@ wtf_size_t PaintController::FindItemFromIdIndexMap(
const DisplayItem::Id& id,
const IdIndexMap& display_item_id_index_map,
const DisplayItemList& list) {
- auto it = display_item_id_index_map.find(IdAsHashKey(id));
+ auto it = display_item_id_index_map.find(id.AsHashKey());
if (it == display_item_id_index_map.end())
return kNotFound;
@@ -422,14 +416,15 @@ wtf_size_t PaintController::FindItemFromIdIndexMap(
if (existing_item.IsTombstone())
return kNotFound;
DCHECK_EQ(existing_item.GetId(), id);
+ DCHECK(existing_item.IsCacheable());
return index;
}
void PaintController::AddToIdIndexMap(const DisplayItem::Id& id,
wtf_size_t index,
IdIndexMap& map) {
- DCHECK(!map.Contains(IdAsHashKey(id)));
- map.insert(IdAsHashKey(id), index);
+ DCHECK(!map.Contains(id.AsHashKey()));
+ map.insert(id.AsHashKey(), index);
}
wtf_size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
@@ -446,6 +441,7 @@ wtf_size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
// We encounter an item that has already been copied which indicates we
// can't do sequential matching.
if (!item.IsTombstone() && id == item.GetId()) {
+ DCHECK(item.IsCacheable());
#if DCHECK_IS_ON()
++num_sequential_matches_;
#endif
@@ -489,26 +485,22 @@ wtf_size_t PaintController::FindOutOfOrderCachedItemForward(
}
}
+#if DCHECK_IS_ON()
// The display item newly appears while the client is not invalidated. The
// situation alone (without other kinds of under-invalidations) won't corrupt
// rendering, but causes AddItemToIndexIfNeeded() for all remaining display
// item, which is not the best for performance. In this case, the caller
// should fall back to repaint the display item.
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
-#if DCHECK_IS_ON()
- ShowDebugData();
-#endif
// Ensure our paint invalidation tests don't trigger the less performant
// situation which should be rare.
DLOG(WARNING) << "Can't find cached display item: " << id;
+ ShowDebugData();
}
+#endif
return kNotFound;
}
-// Moves a cached subsequence from current list to the new list.
-// When PaintUnderInvaldiationCheckingEnabled() we'll not actually
-// move the subsequence, but mark the begin and end of the subsequence for
-// under-invalidation checking.
void PaintController::AppendSubsequenceByMoving(const DisplayItemClient& client,
wtf_size_t subsequence_index,
wtf_size_t start_chunk_index,
@@ -520,9 +512,8 @@ void PaintController::AppendSubsequenceByMoving(const DisplayItemClient& client,
auto properties_before_subsequence = CurrentPaintChunkProperties();
#endif
- wtf_size_t new_start_chunk_index;
- wtf_size_t new_subsequence_index;
- BeginSubsequence(new_subsequence_index, new_start_chunk_index);
+ auto new_start_chunk_index = NumNewChunks();
+ auto new_subsequence_index = BeginSubsequence(client);
auto& current_chunks = current_paint_artifact_->PaintChunks();
for (auto chunk_index = start_chunk_index; chunk_index < end_chunk_index;
@@ -534,22 +525,26 @@ void PaintController::AppendSubsequenceByMoving(const DisplayItemClient& client,
}
auto& new_display_item_list = new_paint_artifact_->GetDisplayItemList();
-#if DCHECK_IS_ON()
wtf_size_t new_item_start_index = new_display_item_list.size();
-#endif
new_display_item_list.AppendSubsequenceByMoving(
current_paint_artifact_->GetDisplayItemList(),
current_chunks[start_chunk_index].begin_index,
current_chunks[end_chunk_index - 1].end_index);
-#if DCHECK_IS_ON()
+ bool skip_cache = IsSkippingCache();
for (auto& item : new_display_item_list.ItemsInRange(
new_item_start_index, new_display_item_list.size())) {
DCHECK(!item.IsTombstone());
+ // This item was copied from the cache, so client must already be valid,
+ // hence we don't call MarkClientForValidation(client).
+ item.SetPaintInvalidationReason(skip_cache || !item.IsCacheable()
+ ? PaintInvalidationReason::kUncacheable
+ : PaintInvalidationReason::kNone);
DCHECK(!item.IsCacheable() || ClientCacheIsValid(item.Client()));
+#if DCHECK_IS_ON()
CheckNewItem(item);
- }
#endif
+ }
// Keep descendant subsequence entries.
for (wtf_size_t i = subsequence_index + 1;
@@ -563,23 +558,20 @@ void PaintController::AppendSubsequenceByMoving(const DisplayItemClient& client,
new_subsequences_.tree.push_back(SubsequenceMarkers{
markers.client,
markers.start_chunk_index + new_start_chunk_index - start_chunk_index,
- markers.end_chunk_index + new_start_chunk_index - start_chunk_index});
+ markers.end_chunk_index + new_start_chunk_index - start_chunk_index,
+ /*is_moved_from_cached_subsequence*/ true});
+ ++num_cached_new_subsequences_;
}
- EndSubsequence(client, new_subsequence_index, new_start_chunk_index);
+ EndSubsequence(new_subsequence_index);
+ new_subsequences_.tree[new_subsequence_index]
+ .is_moved_from_cached_subsequence = true;
#if DCHECK_IS_ON()
DCHECK_EQ(properties_before_subsequence, CurrentPaintChunkProperties());
#endif
}
-void PaintController::ResetCurrentListIndices() {
- next_item_to_match_ = 0;
- next_item_to_index_ = 0;
- under_invalidation_checking_begin_ = 0;
- under_invalidation_checking_end_ = 0;
-}
-
DISABLE_CFI_PERF
void PaintController::CommitNewDisplayItems() {
TRACE_EVENT2(
@@ -591,8 +583,11 @@ void PaintController::CommitNewDisplayItems() {
"num_non_cached_new_items",
new_paint_artifact_->GetDisplayItemList().size() - num_cached_new_items_);
- if (usage_ == kMultiplePaints)
- UpdateUMACounts();
+ if (counter_for_testing_) {
+ counter_for_testing_->num_cached_items += num_cached_new_items_;
+ counter_for_testing_->num_cached_subsequences +=
+ num_cached_new_subsequences_;
+ }
num_cached_new_items_ = 0;
num_cached_new_subsequences_ = 0;
@@ -604,6 +599,8 @@ void PaintController::CommitNewDisplayItems() {
cache_is_all_invalid_ = false;
committed_ = true;
+ under_invalidation_checker_.reset();
+
DCHECK_EQ(new_subsequences_.map.size(), new_subsequences_.tree.size());
current_subsequences_.map.clear();
current_subsequences_.tree.clear();
@@ -611,16 +608,15 @@ void PaintController::CommitNewDisplayItems() {
current_paint_artifact_ = std::move(new_paint_artifact_);
if (usage_ == kMultiplePaints) {
- new_paint_artifact_ = base::MakeRefCounted<PaintArtifact>(
- current_paint_artifact_->GetDisplayItemList().size(),
- current_paint_artifact_->PaintChunks().size());
+ new_paint_artifact_ = base::MakeRefCounted<PaintArtifact>();
paint_chunker_.ResetChunks(&new_paint_artifact_->PaintChunks());
} else {
new_paint_artifact_ = nullptr;
paint_chunker_.ResetChunks(nullptr);
}
- ResetCurrentListIndices();
+ next_item_to_match_ = 0;
+ next_item_to_index_ = 0;
out_of_order_item_id_index_map_.clear();
#if DCHECK_IS_ON()
@@ -630,43 +626,40 @@ void PaintController::CommitNewDisplayItems() {
#endif
}
+PaintController::CycleScope::~CycleScope() {
+ for (const auto* client : clients_to_validate_) {
+ if (client->IsCacheable())
+ client->Validate();
+ }
+ for (auto* controller : controllers_)
+ controller->FinishCycle();
+}
+
+void PaintController::StartCycle(
+ Vector<const DisplayItemClient*>& clients_to_validate) {
+ // StartCycle() can only be called before the controller has painted anything.
+ DCHECK(new_paint_artifact_);
+ DCHECK(new_paint_artifact_->IsEmpty());
+ DCHECK(!clients_to_validate_);
+ if (usage_ == kTransient)
+ return;
+ clients_to_validate_ = &clients_to_validate;
+ paint_chunker_.StartMarkingClientsForValidation(clients_to_validate);
+ ReserveCapacity();
+}
+
void PaintController::FinishCycle() {
+ DCHECK(usage_ == kTransient || clients_to_validate_);
+ clients_to_validate_ = nullptr;
+ paint_chunker_.StopMarkingClientsForValidation();
if (usage_ == kTransient || !committed_)
return;
CheckNoNewPaint();
committed_ = false;
- // Validate display item clients that have validly cached subsequence or
- // display items in this PaintController.
- for (auto& item : current_subsequences_.tree) {
- if (item.client->IsCacheable())
- item.client->Validate();
- }
- for (wtf_size_t i = 0; i < current_paint_artifact_->PaintChunks().size();
- i++) {
- auto& chunk = current_paint_artifact_->PaintChunks()[i];
+ for (auto& chunk : current_paint_artifact_->PaintChunks())
chunk.client_is_just_created = false;
- const auto& client = chunk.id.client;
- if (chunk.is_moved_from_cached_subsequence) {
- // We don't need to validate the clients of paint chunks and display
- // items that are moved from a cached subsequence, because they should be
- // already valid. See http://crbug.com/1050090 for more details.
-#if DCHECK_IS_ON()
- DCHECK(!chunk.is_cacheable || ClientCacheIsValid(client));
- for (const auto& item : current_paint_artifact_->DisplayItemsInChunk(i))
- DCHECK(!item.IsCacheable() || ClientCacheIsValid(item.Client()));
-#endif
- continue;
- }
- if (client.IsCacheable())
- client.Validate();
-
- for (const auto& item : current_paint_artifact_->DisplayItemsInChunk(i)) {
- if (item.Client().IsCacheable())
- item.Client().Validate();
- }
- }
#if DCHECK_IS_ON()
if (VLOG_IS_ON(1)) {
@@ -709,89 +702,22 @@ size_t PaintController::ApproximateUnsharedMemoryUsage() const {
return memory_usage;
}
-void PaintController::ShowUnderInvalidationError(
- const char* reason,
- const DisplayItem& new_item,
- const DisplayItem* old_item) const {
- LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason;
-#if DCHECK_IS_ON()
- LOG(ERROR) << "New display item: " << new_item.AsDebugString();
- LOG(ERROR) << "Old display item: "
- << (old_item ? old_item->AsDebugString() : "None");
- LOG(ERROR) << "See http://crbug.com/619103.";
-
- const PaintRecord* new_record = nullptr;
- if (auto* new_drawing = DynamicTo<DrawingDisplayItem>(new_item))
- new_record = new_drawing->GetPaintRecord().get();
- const PaintRecord* old_record = nullptr;
- if (auto* old_drawing = DynamicTo<DrawingDisplayItem>(old_item))
- old_record = old_drawing->GetPaintRecord().get();
- LOG(INFO) << "new record:\n"
- << (new_record ? RecordAsDebugString(*new_record).Utf8() : "None");
- LOG(INFO) << "old record:\n"
- << (old_record ? RecordAsDebugString(*old_record).Utf8() : "None");
-
- ShowDebugData();
-#else
- LOG(ERROR) << "Run a build with DCHECK on to get more details.";
- LOG(ERROR) << "See http://crbug.com/619103.";
-#endif
-}
-
-void PaintController::ShowSequenceUnderInvalidationError(
- const char* reason,
- const DisplayItemClient& client) {
- LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason;
- LOG(ERROR) << "Subsequence client: " << client.DebugName();
-#if DCHECK_IS_ON()
- ShowDebugData();
-#else
- LOG(ERROR) << "Run a build with DCHECK on to get more details.";
-#endif
- LOG(ERROR) << "See http://crbug.com/619103.";
-}
-
-void PaintController::CheckUnderInvalidation() {
- DCHECK_EQ(usage_, kMultiplePaints);
+PaintUnderInvalidationChecker&
+PaintController::EnsureUnderInvalidationChecker() {
DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
-
- if (!IsCheckingUnderInvalidation())
- return;
-
- 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;
- // Match the remaining display items in the subsequence normally.
- next_item_to_match_ = next_item_to_index_ =
- under_invalidation_checking_begin_;
- return;
+ if (!under_invalidation_checker_) {
+ under_invalidation_checker_ =
+ std::make_unique<PaintUnderInvalidationChecker>(*this);
}
+ return *under_invalidation_checker_;
+}
- DisplayItem& new_item = new_paint_artifact_->GetDisplayItemList().back();
- auto old_item_index = under_invalidation_checking_begin_;
- DisplayItem* old_item =
- old_item_index < current_paint_artifact_->GetDisplayItemList().size()
- ? &current_paint_artifact_->GetDisplayItemList()[old_item_index]
- : nullptr;
-
- if (!old_item || !new_item.EqualsForUnderInvalidation(*old_item)) {
- // If we ever skipped reporting any under-invalidations, report the earliest
- // one.
- ShowUnderInvalidationError("under-invalidation: display item changed",
- new_item, old_item);
- CHECK(false);
+bool PaintController::IsCheckingUnderInvalidation() const {
+ if (under_invalidation_checker_) {
+ DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
+ return under_invalidation_checker_->IsChecking();
}
-
- // Discard the forced repainted display item and move the cached item into
- // new_display_item_list_. This is to align with the
- // non-under-invalidation-checking path to empty the original cached slot,
- // leaving only disappeared or invalidated display items in the old list after
- // painting.
- new_paint_artifact_->GetDisplayItemList().ReplaceLastByMoving(
- current_paint_artifact_->GetDisplayItemList()[old_item_index]);
-
- ++under_invalidation_checking_begin_;
+ return false;
}
void PaintController::SetFirstPainted() {
@@ -831,7 +757,7 @@ void PaintController::ValidateNewChunkId(const PaintChunk::Id& id) {
if (DisplayItem::IsForeignLayerType(id.type))
return;
- auto it = new_paint_chunk_id_index_map_.find(IdAsHashKey(id));
+ auto it = new_paint_chunk_id_index_map_.find(id.AsHashKey());
if (it != new_paint_chunk_id_index_map_.end()) {
ShowDebugData();
NOTREACHED() << "New paint chunk id " << id
@@ -841,48 +767,6 @@ void PaintController::ValidateNewChunkId(const PaintChunk::Id& id) {
#endif
}
-size_t PaintController::sum_num_items_ = 0;
-size_t PaintController::sum_num_cached_items_ = 0;
-size_t PaintController::sum_num_subsequences_ = 0;
-size_t PaintController::sum_num_cached_subsequences_ = 0;
-bool PaintController::disable_uma_reporting_ = false;
-
-void PaintController::UpdateUMACounts() {
- DCHECK_EQ(usage_, kMultiplePaints);
- sum_num_items_ += new_paint_artifact_->GetDisplayItemList().size();
- sum_num_cached_items_ += num_cached_new_items_;
- sum_num_subsequences_ += new_subsequences_.tree.size();
- sum_num_cached_subsequences_ += num_cached_new_subsequences_;
-}
-
-void PaintController::UpdateUMACountsOnFullyCached() {
- DCHECK_EQ(usage_, kMultiplePaints);
- int num_items = GetDisplayItemList().size();
- sum_num_items_ += num_items;
- sum_num_cached_items_ += num_items;
-
- int num_subsequences = current_subsequences_.tree.size();
- sum_num_subsequences_ += num_subsequences;
- sum_num_cached_subsequences_ += num_subsequences;
-}
-
-void PaintController::ReportUMACounts() {
- if (sum_num_items_ == 0 || disable_uma_reporting_)
- return;
-
- UMA_HISTOGRAM_PERCENTAGE("Blink.Paint.CachedItemPercentage",
- sum_num_cached_items_ * 100 / sum_num_items_);
- if (sum_num_subsequences_) {
- UMA_HISTOGRAM_PERCENTAGE(
- "Blink.Paint.CachedSubsequencePercentage",
- sum_num_cached_subsequences_ * 100 / sum_num_subsequences_);
- }
- sum_num_items_ = 0;
- sum_num_cached_items_ = 0;
- sum_num_subsequences_ = 0;
- sum_num_cached_subsequences_ = 0;
-}
-
bool PaintController::ShouldInvalidateDisplayItemForBenchmark() {
if (benchmark_mode_ == PaintBenchmarkMode::kCachingDisabled)
return true;
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 9d213d30832..8a2b98c2804 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,8 +8,8 @@
#include <memory>
#include <utility>
+#include "base/auto_reset.h"
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "cc/input/layer_selection_bound.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunker.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/hash_functions.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"
@@ -30,6 +29,8 @@
namespace blink {
+class PaintUnderInvalidationChecker;
+
enum class PaintBenchmarkMode {
kNormal,
kForceRasterInvalidationAndConvert,
@@ -77,12 +78,36 @@ class PLATFORM_EXPORT PaintController {
};
explicit PaintController(Usage = kMultiplePaints);
+ PaintController(const PaintController&) = delete;
+ PaintController& operator=(const PaintController&) = delete;
~PaintController();
#if DCHECK_IS_ON()
Usage GetUsage() const { return usage_; }
#endif
+ class PLATFORM_EXPORT CycleScope {
+ STACK_ALLOCATED();
+
+ public:
+ CycleScope() = default;
+ explicit CycleScope(PaintController& controller) {
+ AddController(controller);
+ }
+ void AddController(PaintController& controller) {
+ controller.StartCycle(clients_to_validate_);
+ controllers_.push_back(&controller);
+ }
+ ~CycleScope();
+
+ protected:
+ Vector<PaintController*> controllers_;
+
+ private:
+ Vector<const DisplayItemClient*> clients_to_validate_;
+ };
+ friend class CycleScope;
+
// These methods are called during painting.
// Provide a new set of paint chunk properties to apply to recorded display
@@ -98,10 +123,16 @@ class PLATFORM_EXPORT PaintController {
paint_chunker_.SetWillForceNewChunk(force);
}
bool WillForceNewChunk() const { return paint_chunker_.WillForceNewChunk(); }
-
+ void SetCurrentEffectivelyInvisible(bool invisible) {
+ paint_chunker_.SetCurrentEffectivelyInvisible(invisible);
+ }
+ bool CurrentEffectivelyInvisible() const {
+ return paint_chunker_.CurrentEffectivelyInvisible();
+ }
void EnsureChunk();
void SetShouldComputeContentsOpaque(bool should_compute) {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
paint_chunker_.SetShouldComputeContentsOpaque(should_compute);
}
@@ -130,12 +161,15 @@ class PLATFORM_EXPORT PaintController {
return new_paint_artifact_->PaintChunks().back().bounds;
}
+ void MarkClientForValidation(const DisplayItemClient& client);
+
template <typename DisplayItemClass, typename... Args>
- void CreateAndAppend(Args&&... args) {
+ void CreateAndAppend(const DisplayItemClient& client, Args&&... args) {
+ MarkClientForValidation(client);
DisplayItemClass& display_item =
new_paint_artifact_->GetDisplayItemList()
.AllocateAndConstruct<DisplayItemClass>(
- std::forward<Args>(args)...);
+ client, std::forward<Args>(args)...);
display_item.SetFragment(current_fragment_);
ProcessNewItem(display_item);
}
@@ -150,13 +184,11 @@ class PLATFORM_EXPORT PaintController {
// true. Otherwise returns false.
bool UseCachedSubsequenceIfPossible(const DisplayItemClient&);
- void BeginSubsequence(wtf_size_t& subsequence_index,
- wtf_size_t& start_chunk_index);
- // The |start| parameter should be the return value of the corresponding
- // BeginSubsequence().
- void EndSubsequence(const DisplayItemClient&,
- wtf_size_t subsequence_index,
- wtf_size_t start_chunk_index);
+ // Returns the index of the new subsequence.
+ wtf_size_t BeginSubsequence(const DisplayItemClient&);
+ // The |subsequence_index| parameter should be the return value of the
+ // corresponding BeginSubsequence().
+ void EndSubsequence(wtf_size_t subsequence_index);
void BeginSkippingCache() {
if (usage_ == kTransient)
@@ -177,14 +209,6 @@ class PLATFORM_EXPORT PaintController {
// 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 owned by this PaintController.
size_t ApproximateUnsharedMemoryUsage() const;
@@ -256,18 +280,45 @@ class PLATFORM_EXPORT PaintController {
wtf_size_t CurrentFragment() const { return current_fragment_; }
void SetCurrentFragment(wtf_size_t fragment) { current_fragment_ = fragment; }
- // The client may skip a paint when nothing changed. In the case, the client
- // calls this method to update UMA counts as a fully cached paint.
- void UpdateUMACountsOnFullyCached();
- // Reports the accumulated counts as UMA metrics, and reset them, if we have
- // enough data to report.
- static void ReportUMACounts();
+ class CounterForTesting {
+ STACK_ALLOCATED();
+ public:
+ CounterForTesting() {
+ DCHECK(!PaintController::counter_for_testing_);
+ PaintController::counter_for_testing_ = this;
+ }
+ ~CounterForTesting() {
+ DCHECK_EQ(this, PaintController::counter_for_testing_);
+ PaintController::counter_for_testing_ = nullptr;
+ }
+ void Reset() { num_cached_items = num_cached_subsequences = 0; }
+
+ size_t num_cached_items = 0;
+ size_t num_cached_subsequences = 0;
+ };
private:
friend class PaintControllerTestBase;
friend class PaintControllerPaintTestBase;
+ friend class PaintUnderInvalidationChecker;
friend class GraphicsLayer; // Temporary for ClientCacheIsValid().
+ // Called before painting to optimize memory allocation by reserving space in
+ // |new_paint_artifact_| and |new_subsequences_| based on the size of the
+ // previous ones (|current_paint_artifact_| and |current_subsequences_|).
+ void ReserveCapacity();
+
+ // Called at the beginning of a paint cycle, as defined by CycleScope.
+ void StartCycle(Vector<const DisplayItemClient*>& clients_to_validate);
+
+ // Called at the end of a paint cycle, as defined by CycleScope.
+ // 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();
+
// 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:
@@ -288,46 +339,8 @@ class PLATFORM_EXPORT PaintController {
void CheckNewItem(DisplayItem&);
void CheckNewChunk();
- struct IdAsHashKey {
- IdAsHashKey() = default;
- explicit IdAsHashKey(const DisplayItem::Id& id)
- : client(&id.client), type(id.type), fragment(id.fragment) {}
- explicit IdAsHashKey(WTF::HashTableDeletedValueType) {
- HashTraits<const DisplayItemClient*>::ConstructDeletedValue(client,
- false);
- }
- bool IsHashTableDeletedValue() const {
- return HashTraits<const DisplayItemClient*>::IsDeletedValue(client);
- }
- bool operator==(const IdAsHashKey& other) const {
- return client == other.client && type == other.type &&
- fragment == other.fragment;
- }
-
- const DisplayItemClient* client = nullptr;
- DisplayItem::Type type = static_cast<DisplayItem::Type>(0);
- wtf_size_t fragment = 0;
- };
-
- struct IdHash {
- STATIC_ONLY(IdHash);
- static unsigned GetHash(const IdAsHashKey& id) {
- unsigned hash = PtrHash<const DisplayItemClient>::GetHash(id.client);
- WTF::AddIntToHash(hash, id.type);
- WTF::AddIntToHash(hash, id.fragment);
- return hash;
- }
- static bool Equal(const IdAsHashKey& a, const IdAsHashKey& b) {
- return a == b;
- }
- static const bool safe_to_compare_to_empty_or_deleted = true;
- };
-
// Maps a display item id to the index of the display item or the paint chunk.
- using IdIndexMap = HashMap<IdAsHashKey,
- wtf_size_t,
- IdHash,
- SimpleClassHashTraits<IdAsHashKey>>;
+ using IdIndexMap = HashMap<DisplayItem::Id::HashKey, wtf_size_t>;
static wtf_size_t FindItemFromIdIndexMap(const DisplayItem::Id&,
const IdIndexMap&,
@@ -343,33 +356,13 @@ class PLATFORM_EXPORT PaintController {
wtf_size_t start_chunk_index,
wtf_size_t end_chunk_index);
- // Resets the indices (e.g. next_item_to_match_) of
- // current_paint_artifact_.GetDisplayItemList() to their initial values. This
- // should be called when the DisplayItemList in current_paint_artifact_ is
- // newly created, or is changed causing the previous indices to be invalid.
- void ResetCurrentListIndices();
-
- // The following two methods are for checking under-invalidations
- // (when RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled).
- void ShowUnderInvalidationError(const char* reason,
- const DisplayItem& new_item,
- const DisplayItem* old_item) const;
-
- void ShowSequenceUnderInvalidationError(const char* reason,
- const DisplayItemClient&);
-
- void CheckUnderInvalidation();
- bool IsCheckingUnderInvalidation() const {
- return under_invalidation_checking_end_ >
- under_invalidation_checking_begin_;
- }
-
struct SubsequenceMarkers {
const DisplayItemClient* client = nullptr;
// The start and end (not included) index of paint chunks in this
// subsequence.
wtf_size_t start_chunk_index = 0;
wtf_size_t end_chunk_index = 0;
+ bool is_moved_from_cached_subsequence = false;
};
wtf_size_t GetSubsequenceIndex(const DisplayItemClient&) const;
@@ -378,12 +371,13 @@ class PLATFORM_EXPORT PaintController {
void ValidateNewChunkId(const PaintChunk::Id&);
+ PaintUnderInvalidationChecker& EnsureUnderInvalidationChecker();
+ ALWAYS_INLINE bool IsCheckingUnderInvalidation() const;
+
#if DCHECK_IS_ON()
void ShowDebugDataInternal(DisplayItemList::JsonFlags) const;
#endif
- void UpdateUMACounts();
-
void SetBenchmarkMode(PaintBenchmarkMode);
bool ShouldInvalidateDisplayItemForBenchmark();
bool ShouldInvalidateSubsequenceForBenchmark();
@@ -409,6 +403,7 @@ class PLATFORM_EXPORT PaintController {
// CommitNewDisplayItems().
scoped_refptr<PaintArtifact> new_paint_artifact_;
PaintChunker paint_chunker_;
+ Vector<const DisplayItemClient*>* clients_to_validate_ = nullptr;
bool cache_is_all_invalid_ = true;
bool committed_ = false;
@@ -450,16 +445,7 @@ class PLATFORM_EXPORT PaintController {
IdIndexMap new_paint_chunk_id_index_map_;
#endif
- // These are set in UseCachedItemIfPossible() and
- // UseCachedSubsequenceIfPossible() when we could use cached drawing or
- // subsequence and under-invalidation checking is on, indicating the begin and
- // 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.
- wtf_size_t under_invalidation_checking_begin_ = 0;
- wtf_size_t under_invalidation_checking_end_ = 0;
-
- String under_invalidation_message_prefix_;
+ std::unique_ptr<PaintUnderInvalidationChecker> under_invalidation_checker_;
struct SubsequencesData {
// Map a client to the index into |tree|.
@@ -476,23 +462,9 @@ class PLATFORM_EXPORT PaintController {
int partial_invalidation_display_item_count_ = 0;
int partial_invalidation_subsequence_count_ = 0;
- // Accumulated counts for UMA metrics. Updated by UpdateUMACounts() and
- // UpdateUMACountsOnFullyCached(), and reported as UMA metrics and reset by
- // ReportUMACounts(). The accumulation is mainly for pre-CompositeAfterPaint
- // to sum up the data from multiple PaintControllers during a paint in
- // document life cycle update.
- static size_t sum_num_items_;
- static size_t sum_num_cached_items_;
- static size_t sum_num_subsequences_;
- static size_t sum_num_cached_subsequences_;
-
- // For testing, to disable ReportUMACounts(), to prevent the above sums from
- // being cleared.
- static bool disable_uma_reporting_;
+ static CounterForTesting* counter_for_testing_;
class PaintArtifactAsJSON;
-
- DISALLOW_COPY_AND_ASSIGN(PaintController);
};
} // namespace blink
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 9f04bc58854..b64b32dfba1 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
+#include "build/build_config.h"
#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/display_item_cache_skipper.h"
@@ -25,6 +26,16 @@ class PaintControllerTest : public PaintTestConfigurations,
public PaintControllerTestBase {
};
+class CommitCycleScope : public PaintController::CycleScope {
+ public:
+ explicit CommitCycleScope(PaintController& controller)
+ : PaintController::CycleScope(controller) {}
+ ~CommitCycleScope() {
+ for (auto* controller : controllers_)
+ controller->CommitNewDisplayItems();
+ }
+};
+
#define EXPECT_DEFAULT_ROOT_CHUNK(size) \
EXPECT_THAT(GetPaintController().PaintChunks(), \
ElementsAre(IsPaintChunk(0, size, DefaultRootChunkId(), \
@@ -37,14 +48,15 @@ INSTANTIATE_TEST_SUITE_P(
kCompositeAfterPaint,
kUnderInvalidationChecking,
kCompositeAfterPaint | kUnderInvalidationChecking));
-
TEST_P(PaintControllerTest, NestedRecorders) {
GraphicsContext context(GetPaintController());
FakeDisplayItemClient client("client");
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, client, kBackgroundType, IntRect(100, 100, 200, 200));
- CommitAndFinishCycle();
+ DrawRect(context, client, kBackgroundType, IntRect(100, 100, 200, 200));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kBackgroundType)));
@@ -55,16 +67,17 @@ TEST_P(PaintControllerTest, UpdateBasic) {
FakeDisplayItemClient first("first");
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
-
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- EXPECT_EQ(0u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
+ EXPECT_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -72,19 +85,20 @@ TEST_P(PaintControllerTest, UpdateBasic) {
IsSameId(&first, kForegroundType)));
EXPECT_DEFAULT_ROOT_CHUNK(3);
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- EXPECT_EQ(2u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(1u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(1u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -97,15 +111,17 @@ TEST_P(PaintControllerTest, UpdateSwapOrder) {
FakeDisplayItemClient second("second");
FakeDisplayItemClient unaffected("unaffected");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
- CommitAndFinishCycle();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -115,24 +131,25 @@ TEST_P(PaintControllerTest, UpdateSwapOrder) {
IsSameId(&unaffected, kBackgroundType),
IsSameId(&unaffected, kForegroundType)));
- InitRootChunk();
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
-
- EXPECT_EQ(6u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
+
+ EXPECT_EQ(6u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(2u, NumIndexedItems()); // first
- EXPECT_EQ(5u,
- NumSequentialMatches()); // second, first foreground, unaffected
- EXPECT_EQ(1u, NumOutOfOrderMatches()); // first
+ EXPECT_EQ(2u, NumIndexedItems()); // first
+ EXPECT_EQ(5u,
+ NumSequentialMatches()); // second, first foreground, unaffected
+ EXPECT_EQ(1u, NumOutOfOrderMatches()); // first
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&second, kBackgroundType),
@@ -149,15 +166,17 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
FakeDisplayItemClient second("second");
FakeDisplayItemClient unaffected("unaffected");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
- CommitAndFinishCycle();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -167,24 +186,25 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
IsSameId(&unaffected, kBackgroundType),
IsSameId(&unaffected, kForegroundType)));
- InitRootChunk();
- first.Invalidate();
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
- DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
-
- EXPECT_EQ(4u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ first.Invalidate();
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, IntRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, IntRect(300, 300, 10, 10));
+
+ EXPECT_EQ(4u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(2u, NumIndexedItems());
- EXPECT_EQ(4u, NumSequentialMatches()); // second, unaffected
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(2u, NumIndexedItems());
+ EXPECT_EQ(4u, NumSequentialMatches()); // second, unaffected
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&second, kBackgroundType),
@@ -201,31 +221,34 @@ TEST_P(PaintControllerTest, UpdateNewItemInMiddle) {
FakeDisplayItemClient second("second");
FakeDisplayItemClient third("third");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- CommitAndFinishCycle();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
IsSameId(&second, kBackgroundType)));
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, third, kBackgroundType, IntRect(125, 100, 200, 50));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, third, kBackgroundType, IntRect(125, 100, 200, 50));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- EXPECT_EQ(2u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(0u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches()); // first, second
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(0u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches()); // first, second
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -239,15 +262,17 @@ TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
FakeDisplayItemClient second("second");
FakeDisplayItemClient third("third");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, third, kBackgroundType, IntRect(300, 100, 50, 50));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, third, kForegroundType, IntRect(300, 100, 50, 50));
- CommitAndFinishCycle();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, third, kBackgroundType, IntRect(300, 100, 50, 50));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, third, kForegroundType, IntRect(300, 100, 50, 50));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -257,25 +282,26 @@ TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
IsSameId(&second, kForegroundType),
IsSameId(&third, kForegroundType)));
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, third, kBackgroundType, IntRect(300, 100, 50, 50));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, third, kForegroundType, IntRect(300, 100, 50, 50));
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, third, kBackgroundType, IntRect(300, 100, 50, 50));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, second, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, third, kForegroundType, IntRect(300, 100, 50, 50));
- EXPECT_EQ(4u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ EXPECT_EQ(4u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(2u, NumIndexedItems());
- EXPECT_EQ(4u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(2u, NumIndexedItems());
+ EXPECT_EQ(4u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -291,27 +317,31 @@ TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
FakeDisplayItemClient first("first");
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
- DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
- CommitAndFinishCycle();
+ DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
+ DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&second, kBackgroundType),
IsSameId(&second, kForegroundType)));
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- first.Invalidate();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
- DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
- EXPECT_EQ(0u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
- CommitAndFinishCycle();
+ first.Invalidate();
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
+ DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
+ EXPECT_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -320,19 +350,20 @@ TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
IsSameId(&second, kForegroundType)));
EXPECT_DEFAULT_ROOT_CHUNK(4);
- InitRootChunk();
- DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
- DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, IntRect(150, 250, 100, 100));
+ DrawRect(context, second, kForegroundType, IntRect(150, 250, 100, 100));
- EXPECT_EQ(2u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(2u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(2u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&second, kBackgroundType),
@@ -344,27 +375,31 @@ TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
FakeDisplayItemClient first("first");
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
- CommitAndFinishCycle();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
IsSameId(&first, kForegroundType)));
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- first.Invalidate();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(150, 150, 100, 100));
- DrawRect(context, first, kForegroundType, IntRect(150, 150, 100, 100));
- DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
- DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
- EXPECT_EQ(0u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
- CommitAndFinishCycle();
+ first.Invalidate();
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(150, 150, 100, 100));
+ DrawRect(context, first, kForegroundType, IntRect(150, 150, 100, 100));
+ DrawRect(context, second, kBackgroundType, IntRect(200, 200, 50, 50));
+ DrawRect(context, second, kForegroundType, IntRect(200, 200, 50, 50));
+ EXPECT_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -373,14 +408,16 @@ TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
IsSameId(&second, kForegroundType)));
EXPECT_DEFAULT_ROOT_CHUNK(4);
- InitRootChunk();
- first.Invalidate();
- second.Invalidate();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
- EXPECT_EQ(0u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ first.Invalidate();
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, IntRect(100, 100, 150, 150));
+ EXPECT_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -392,11 +429,13 @@ TEST_P(PaintControllerTest, CachedDisplayItems) {
FakeDisplayItemClient first("first");
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 150, 150));
- CommitAndFinishCycle();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 150, 150));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -414,10 +453,12 @@ TEST_P(PaintControllerTest, CachedDisplayItems) {
EXPECT_FALSE(ClientCacheIsValid(first));
EXPECT_TRUE(ClientCacheIsValid(second));
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 150, 150));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 150, 150));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 150, 150));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
@@ -447,17 +488,19 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildren) {
FakeDisplayItemClient container2("container2");
FakeDisplayItemClient content2("content2");
GraphicsContext context(GetPaintController());
- InitRootChunk();
-
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -469,19 +512,21 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildren) {
IsSameId(&content2, kForegroundType),
IsSameId(&container2, kForegroundType)));
- InitRootChunk();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- // Simulate the situation when |container1| gets a z-index that is greater
- // than that of |container2|.
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- CommitAndFinishCycle();
+ // Simulate the situation when |container1| gets a z-index that is greater
+ // than that of |container2|.
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container2, kBackgroundType),
@@ -501,17 +546,19 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
FakeDisplayItemClient container2("container2");
FakeDisplayItemClient content2("content2");
GraphicsContext context(GetPaintController());
- InitRootChunk();
-
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -523,20 +570,22 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
IsSameId(&content2, kForegroundType),
IsSameId(&container2, kForegroundType)));
- InitRootChunk();
-
- // Simulate the situation when |container1| gets a z-index that is greater
- // than that of |container2|, and |container1| is invalidated.
- container1.Invalidate();
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+
+ // Simulate the situation when |container1| gets a z-index that is greater
+ // than that of |container2|, and |container1| is invalidated.
+ container1.Invalidate();
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container2, kBackgroundType),
@@ -554,29 +603,33 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
return;
- GraphicsContext context(GetPaintController());
-
FakeDisplayItemClient root("root");
auto root_properties = DefaultPaintChunkProperties();
PaintChunk::Id root_id(root, DisplayItem::kCaret);
- GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
- root_properties);
- DrawRect(context, root, kBackgroundType, IntRect(100, 100, 100, 100));
-
FakeDisplayItemClient container("container");
auto container_properties = DefaultPaintChunkProperties();
PaintChunk::Id container_id(container, DisplayItem::kCaret);
+ GraphicsContext context(GetPaintController());
+
{
- SubsequenceRecorder r(context, container);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container_id, container_properties);
- DrawRect(context, container, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, container, kForegroundType, IntRect(100, 100, 100, 100));
- }
+ CommitCycleScope cycle_scope(GetPaintController());
- DrawRect(context, root, kForegroundType, IntRect(100, 100, 100, 100));
+ GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
+ root_properties);
+ DrawRect(context, root, kBackgroundType, IntRect(100, 100, 100, 100));
- CommitAndFinishCycle();
+ {
+ SubsequenceRecorder r(context, container);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container_id, container_properties);
+ DrawRect(context, container, kBackgroundType,
+ IntRect(100, 100, 100, 100));
+ DrawRect(context, container, kForegroundType,
+ IntRect(100, 100, 100, 100));
+ }
+
+ DrawRect(context, root, kForegroundType, IntRect(100, 100, 100, 100));
+ }
// Even though the paint properties match, |container| should receive its
// own PaintChunk because it created a subsequence.
@@ -587,12 +640,14 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
IsPaintChunk(3, 4, PaintChunk::Id(root, kForegroundType),
root_properties)));
- GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
- root_properties);
- DrawRect(context, root, kBackgroundType, IntRect(100, 100, 100, 100));
- EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(container));
- DrawRect(context, root, kForegroundType, IntRect(100, 100, 100, 100));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
+ root_properties);
+ DrawRect(context, root, kBackgroundType, IntRect(100, 100, 100, 100));
+ EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(container));
+ DrawRect(context, root, kForegroundType, IntRect(100, 100, 100, 100));
+ }
// |container| should still receive its own PaintChunk because it is a cached
// subsequence.
@@ -622,26 +677,33 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
container2_properties.SetEffect(*container2_effect);
{
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container1_id, container1_properties);
+ CommitCycleScope cycle_scope(GetPaintController());
- SubsequenceRecorder r(context, container1);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- }
- {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container2_id, container2_properties);
+ {
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_id, container1_properties);
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ SubsequenceRecorder r(context, container1);
+ DrawRect(context, container1, kBackgroundType,
+ IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType,
+ IntRect(100, 100, 100, 100));
+ }
+ {
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container2_id, container2_properties);
+
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType,
+ IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType,
+ IntRect(100, 200, 100, 100));
+ }
}
- CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -664,56 +726,61 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
ElementsAre(IsPaintChunk(0, 4, container1_id, container1_properties),
IsPaintChunk(4, 8, container2_id, container2_properties)));
- // Simulate the situation when |container1| gets a z-index that is greater
- // than that of |container2|.
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- // When under-invalidation-checking is enabled,
- // UseCachedSubsequenceIfPossible is forced off, and the client is expected
- // to create the same painting as in the previous paint.
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container2));
- {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container2_id, container2_properties);
-
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType,
- IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType,
- IntRect(100, 200, 100, 100));
- }
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container1));
- {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container1_id, container1_properties);
-
- SubsequenceRecorder r(context, container1);
- DrawRect(context, container1, kBackgroundType,
- IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, container1, kForegroundType,
- IntRect(100, 100, 100, 100));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ // Simulate the situation when |container1| gets a z-index that is greater
+ // than that of |container2|.
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ // When under-invalidation-checking is enabled,
+ // UseCachedSubsequenceIfPossible is forced off, and the client is
+ // expected to create the same painting as in the previous paint.
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
+ {
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container2_id, container2_properties);
+
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType,
+ IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType,
+ IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType,
+ IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType,
+ IntRect(100, 200, 100, 100));
+ }
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container1));
+ {
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_id, container1_properties);
+
+ SubsequenceRecorder r(context, container1);
+ DrawRect(context, container1, kBackgroundType,
+ IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType,
+ IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType,
+ IntRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType,
+ IntRect(100, 100, 100, 100));
+ }
+ } else {
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container1));
}
- } else {
- EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container2));
- EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container1));
- }
- EXPECT_EQ(8u, NumCachedNewItems());
- EXPECT_EQ(2u, NumCachedNewSubsequences());
+ EXPECT_EQ(8u, NumCachedNewItems());
+ EXPECT_EQ(2u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(0u, NumIndexedItems());
- EXPECT_EQ(0u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(0u, NumIndexedItems());
+ EXPECT_EQ(0u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container2, kBackgroundType),
@@ -746,18 +813,22 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
PaintChunk::Id container2_id(container2, kBackgroundType);
PaintChunk::Id content2_id(content2, kBackgroundType);
- InitRootChunk();
-
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
{
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType, IntRect(100, 200, 100, 100));
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ {
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType,
+ IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType,
+ IntRect(100, 200, 100, 100));
+ }
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
}
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content1, kBackgroundType),
@@ -783,42 +854,45 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
// Simulate the situation when |container2| gets a z-index that is smaller
// than that of |content1|.
- InitRootChunk();
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- // When under-invalidation-checking is enabled,
- // UseCachedSubsequenceIfPossible is forced off, and the client is expected
- // to create the same painting as in the previous paint.
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container2));
- {
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType,
- IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- DrawRect(context, container2, kForegroundType,
- IntRect(100, 200, 100, 100));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ // When under-invalidation-checking is enabled,
+ // UseCachedSubsequenceIfPossible is forced off, and the client is
+ // expected to create the same painting as in the previous paint.
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
+ {
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType,
+ IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType,
+ IntRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType,
+ IntRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType,
+ IntRect(100, 200, 100, 100));
+ }
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ } else {
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1,
+ kBackgroundType));
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1,
+ kForegroundType));
}
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- } else {
- EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container2));
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1,
- kBackgroundType));
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1,
- kForegroundType));
- }
- EXPECT_EQ(6u, NumCachedNewItems());
- EXPECT_EQ(1u, NumCachedNewSubsequences());
+ EXPECT_EQ(6u, NumCachedNewItems());
+ EXPECT_EQ(1u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(0u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(0u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container2, kBackgroundType),
@@ -854,16 +928,18 @@ TEST_P(PaintControllerTest, DisplayItemSwapOrderBeforeCachedSubsequence) {
PaintChunk::Id content3_id(content3, kBackgroundType);
IntRect rect(100, 100, 50, 200);
- InitRootChunk();
-
- DrawRect(context, content1a, kBackgroundType, rect);
- DrawRect(context, content1b, kBackgroundType, rect);
{
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType, rect);
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+
+ DrawRect(context, content1a, kBackgroundType, rect);
+ DrawRect(context, content1b, kBackgroundType, rect);
+ {
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType, rect);
+ }
+ DrawRect(context, content3, kBackgroundType, rect);
}
- DrawRect(context, content3, kBackgroundType, rect);
- CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content1a, kBackgroundType),
@@ -875,43 +951,44 @@ TEST_P(PaintControllerTest, DisplayItemSwapOrderBeforeCachedSubsequence) {
// Subsequence(container1): container1, content1b(cached), content1a(cached).
// Subsequence(container2): cached
// Subsequence(contaienr3): container3, content3
- InitRootChunk();
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1b,
- kBackgroundType));
- DrawRect(context, content1b, kBackgroundType, rect);
- EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1a,
- kBackgroundType));
- DrawRect(context, content1a, kBackgroundType, rect);
- {
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(
+ context, content1b, kBackgroundType));
+ DrawRect(context, content1b, kBackgroundType, rect);
+ EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(
+ context, content1a, kBackgroundType));
+ DrawRect(context, content1a, kBackgroundType, rect);
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType, rect);
+ }
+ EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(
+ context, content3, kBackgroundType));
+ DrawRect(context, content3, kBackgroundType, rect);
+ } else {
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(
+ context, content1b, kBackgroundType));
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(
+ context, content1a, kBackgroundType));
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container2));
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType, rect);
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content3,
+ kBackgroundType));
}
- EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(context, content3,
- kBackgroundType));
- DrawRect(context, content3, kBackgroundType, rect);
- } else {
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1b,
- kBackgroundType));
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1a,
- kBackgroundType));
- EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container2));
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content3,
- kBackgroundType));
- }
- EXPECT_EQ(4u, NumCachedNewItems());
- EXPECT_EQ(1u, NumCachedNewSubsequences());
+ EXPECT_EQ(4u, NumCachedNewItems());
+ EXPECT_EQ(1u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(1u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches());
- EXPECT_EQ(1u, NumOutOfOrderMatches());
+ EXPECT_EQ(1u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches());
+ EXPECT_EQ(1u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content1b, kBackgroundType),
@@ -926,7 +1003,6 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
constexpr wtf_size_t kFragmentCount = 3;
FakeDisplayItemClient container("container");
- // The first paint.
auto paint_container = [this, &context, &container]() {
SubsequenceRecorder r(context, container);
for (wtf_size_t i = 0; i < kFragmentCount; ++i) {
@@ -938,7 +1014,10 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
IntRect(100, 100, 100, 100));
}
};
+
+ // The first paint.
{
+ CommitCycleScope cycle_scope(GetPaintController());
ScopedPaintChunkProperties root_chunk_properties(
GetPaintController(), DefaultPaintChunkProperties(), root,
kBackgroundType);
@@ -946,7 +1025,6 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
paint_container();
DrawRect(context, root, kForegroundType, IntRect(100, 100, 100, 100));
}
- CommitAndFinishCycle();
auto check_paint_results = [this, &root, &container]() {
EXPECT_THAT(
@@ -966,6 +1044,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
// The second paint.
{
+ CommitCycleScope cycle_scope(GetPaintController());
ScopedPaintChunkProperties root_chunk_properties(
GetPaintController(), DefaultPaintChunkProperties(), root,
kBackgroundType);
@@ -981,7 +1060,6 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
}
DrawRect(context, root, kForegroundType, IntRect(100, 100, 100, 100));
}
- CommitAndFinishCycle();
// The second paint should produce the exactly same results.
check_paint_results();
@@ -1004,15 +1082,17 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
auto container2_properties = DefaultPaintChunkProperties();
container2_properties.SetEffect(*container2_effect);
- GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
- container1_properties);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
- container2_properties);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_id, container1_properties);
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container2_id, container2_properties);
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -1026,24 +1106,25 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
IsPaintChunk(2, 4, container2_id, container2_properties)));
// Move content2 into container1, without invalidation.
- GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
- container1_properties);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
- container2_properties);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
-
- EXPECT_EQ(4u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_id, container1_properties);
+ DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
+ DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container2_id, container2_properties);
+ DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+
+ EXPECT_EQ(4u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(1u, NumIndexedItems());
- EXPECT_EQ(3u, NumSequentialMatches());
- EXPECT_EQ(1u, NumOutOfOrderMatches());
+ EXPECT_EQ(1u, NumIndexedItems());
+ EXPECT_EQ(3u, NumSequentialMatches());
+ EXPECT_EQ(1u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -1069,21 +1150,23 @@ TEST_P(PaintControllerTest, OutOfOrderNoCrash) {
const DisplayItem::Type kType4 =
static_cast<DisplayItem::Type>(DisplayItem::kDrawingFirst + 3);
- InitRootChunk();
- DrawRect(context, client, kType1, IntRect(100, 100, 100, 100));
- DrawRect(context, client, kType2, IntRect(100, 100, 50, 200));
- DrawRect(context, client, kType3, IntRect(100, 100, 50, 200));
- DrawRect(context, client, kType4, IntRect(100, 100, 100, 100));
-
- CommitAndFinishCycle();
-
- InitRootChunk();
- DrawRect(context, client, kType2, IntRect(100, 100, 50, 200));
- DrawRect(context, client, kType3, IntRect(100, 100, 50, 200));
- DrawRect(context, client, kType1, IntRect(100, 100, 100, 100));
- DrawRect(context, client, kType4, IntRect(100, 100, 100, 100));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, client, kType1, IntRect(100, 100, 100, 100));
+ DrawRect(context, client, kType2, IntRect(100, 100, 50, 200));
+ DrawRect(context, client, kType3, IntRect(100, 100, 50, 200));
+ DrawRect(context, client, kType4, IntRect(100, 100, 100, 100));
+ }
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, client, kType2, IntRect(100, 100, 50, 200));
+ DrawRect(context, client, kType3, IntRect(100, 100, 50, 200));
+ DrawRect(context, client, kType1, IntRect(100, 100, 100, 100));
+ DrawRect(context, client, kType4, IntRect(100, 100, 100, 100));
+ }
}
TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
@@ -1117,35 +1200,43 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
content2_properties.SetEffect(*content2_effect);
{
- SubsequenceRecorder r(context, container1);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container1_background_id, container1_background_properties);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
-
+ CommitCycleScope cycle_scope(GetPaintController());
{
- SubsequenceRecorder r(context, content1);
+ SubsequenceRecorder r(context, container1);
GetPaintController().UpdateCurrentPaintChunkProperties(
- &content1_id, content1_properties);
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
+ &container1_background_id, container1_background_properties);
+ DrawRect(context, container1, kBackgroundType,
+ IntRect(100, 100, 100, 100));
+
+ {
+ SubsequenceRecorder r(context, content1);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &content1_id, content1_properties);
+ DrawRect(context, content1, kBackgroundType,
+ IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType,
+ IntRect(100, 100, 50, 200));
+ }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &container1_foreground_id, container1_foreground_properties);
+ DrawRect(context, container1, kForegroundType,
+ IntRect(100, 100, 100, 100));
}
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container1_foreground_id, container1_foreground_properties);
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- }
- {
- SubsequenceRecorder r(context, container2);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container2_background_id, container2_background_properties);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
{
- SubsequenceRecorder r(context, content2);
+ SubsequenceRecorder r(context, container2);
GetPaintController().UpdateCurrentPaintChunkProperties(
- &content2_id, content2_properties);
- DrawRect(context, content2, kBackgroundType, IntRect(100, 200, 50, 200));
+ &container2_background_id, container2_background_properties);
+ DrawRect(context, container2, kBackgroundType,
+ IntRect(100, 200, 100, 100));
+ {
+ SubsequenceRecorder r(context, content2);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &content2_id, content2_properties);
+ DrawRect(context, content2, kBackgroundType,
+ IntRect(100, 200, 50, 200));
+ }
}
}
- CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -1171,58 +1262,62 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
container2_background_properties),
IsPaintChunk(5, 6, content2_id, content2_properties)));
- // Invalidate container1 but not content1.
- container1.Invalidate();
- // Container2 itself now becomes empty (but still has the 'content2' child),
- // and chooses not to output subsequence info.
- container2.Invalidate();
- content2.Invalidate();
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container2));
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, content2));
- // Content2 now outputs foreground only.
- {
- SubsequenceRecorder r(context, content2);
- GetPaintController().UpdateCurrentPaintChunkProperties(&content2_id,
- content2_properties);
- DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
- }
- // Repaint container1 with foreground only.
{
- SubsequenceRecorder r(context, container1);
+ CommitCycleScope cycle_scope(GetPaintController());
+ // Invalidate container1 but not content1.
+ container1.Invalidate();
+ // Container2 itself now becomes empty (but still has the 'content2' child),
+ // and chooses not to output subsequence info.
+ container2.Invalidate();
+ content2.Invalidate();
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container1));
- // Use cached subsequence of content1.
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- // When under-invalidation-checking is enabled,
- // UseCachedSubsequenceIfPossible is forced off, and the client is
- // expected to create the same painting as in the previous paint.
+ context, container2));
+ EXPECT_FALSE(
+ SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, content2));
+ // Content2 now outputs foreground only.
+ {
+ SubsequenceRecorder r(context, content2);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &content2_id, content2_properties);
+ DrawRect(context, content2, kForegroundType, IntRect(100, 200, 50, 200));
+ }
+ // Repaint container1 with foreground only.
+ {
+ SubsequenceRecorder r(context, container1);
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, content1));
- SubsequenceRecorder r(context, content1);
+ context, container1));
+ // Use cached subsequence of content1.
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ // When under-invalidation-checking is enabled,
+ // UseCachedSubsequenceIfPossible is forced off, and the client is
+ // expected to create the same painting as in the previous paint.
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, content1));
+ SubsequenceRecorder r(context, content1);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ &content1_id, content1_properties);
+ DrawRect(context, content1, kBackgroundType,
+ IntRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType,
+ IntRect(100, 100, 50, 200));
+ } else {
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, content1));
+ }
GetPaintController().UpdateCurrentPaintChunkProperties(
- &content1_id, content1_properties);
- DrawRect(context, content1, kBackgroundType, IntRect(100, 100, 50, 200));
- DrawRect(context, content1, kForegroundType, IntRect(100, 100, 50, 200));
- } else {
- EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, content1));
+ &container1_foreground_id, container1_foreground_properties);
+ DrawRect(context, container1, kForegroundType,
+ IntRect(100, 100, 100, 100));
}
- GetPaintController().UpdateCurrentPaintChunkProperties(
- &container1_foreground_id, container1_foreground_properties);
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- }
- EXPECT_EQ(2u, NumCachedNewItems());
- EXPECT_EQ(1u, NumCachedNewSubsequences());
+ EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(1u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(0u, NumIndexedItems());
- EXPECT_EQ(0u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(0u, NumIndexedItems());
+ EXPECT_EQ(0u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content2, kForegroundType),
@@ -1248,10 +1343,8 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceKeepingDescendants) {
FakeDisplayItemClient root("root");
auto properties = DefaultPaintChunkProperties();
- PaintChunk::Id root_id(root, DisplayItem::kLayerChunk);
GraphicsContext context(GetPaintController());
- GetPaintController().UpdateCurrentPaintChunkProperties(&root_id, properties);
-
+ PaintChunk::Id root_id(root, DisplayItem::kLayerChunk);
FakeDisplayItemClient container1("container1");
PaintChunk::Id container1_bg_id(container1, kBackgroundType);
PaintChunk::Id container1_fg_id(container1, kForegroundType);
@@ -1265,33 +1358,47 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceKeepingDescendants) {
PaintChunk::Id content2a_id(content2a, kBackgroundType);
FakeDisplayItemClient content2b("content2b");
PaintChunk::Id content2b_id(content2b, kForegroundType);
-
- {
- SubsequenceRecorder r(context, container1);
- DrawRect(context, container1, kBackgroundType, IntRect(100, 100, 100, 100));
- {
- SubsequenceRecorder r(context, content1a);
- DrawRect(context, content1a, kBackgroundType, IntRect(100, 100, 50, 200));
- }
- {
- SubsequenceRecorder r(context, content1b);
- DrawRect(context, content1b, kForegroundType, IntRect(100, 100, 50, 200));
- }
- DrawRect(context, container1, kForegroundType, IntRect(100, 100, 100, 100));
- }
{
- SubsequenceRecorder r(context, container2);
- DrawRect(context, container2, kBackgroundType, IntRect(100, 200, 100, 100));
+ CommitCycleScope cycle_scope(GetPaintController());
+ GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
+ properties);
+
{
- SubsequenceRecorder r(context, content2a);
- DrawRect(context, content2a, kBackgroundType, IntRect(100, 200, 50, 200));
+ SubsequenceRecorder r(context, container1);
+ DrawRect(context, container1, kBackgroundType,
+ IntRect(100, 100, 100, 100));
+ {
+ SubsequenceRecorder r(context, content1a);
+ DrawRect(context, content1a, kBackgroundType,
+ IntRect(100, 100, 50, 200));
+ }
+ {
+ SubsequenceRecorder r(context, content1b);
+ DrawRect(context, content1b, kForegroundType,
+ IntRect(100, 100, 50, 200));
+ }
+ DrawRect(context, container1, kForegroundType,
+ IntRect(100, 100, 100, 100));
}
{
- SubsequenceRecorder r(context, content2b);
- DrawRect(context, content2b, kForegroundType, IntRect(100, 200, 50, 200));
+ SubsequenceRecorder r(context, container2);
+ DrawRect(context, container2, kBackgroundType,
+ IntRect(100, 200, 100, 100));
+ {
+ SubsequenceRecorder r(context, content2a);
+ DrawRect(context, content2a, kBackgroundType,
+ IntRect(100, 200, 50, 200));
+ }
+ {
+ SubsequenceRecorder r(context, content2b);
+ DrawRect(context, content2b, kForegroundType,
+ IntRect(100, 200, 50, 200));
+ }
}
+
+ EXPECT_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
}
- CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -1319,12 +1426,16 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceKeepingDescendants) {
IsPaintChunk(6, 7, content2b_id, properties)));
// Nothing invalidated. Should keep all subsequences.
- EXPECT_TRUE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container1));
- EXPECT_TRUE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container2));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container1));
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
- CommitAndFinishCycle();
+ EXPECT_EQ(7u, NumCachedNewItems());
+ EXPECT_EQ(6u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container1, kBackgroundType),
@@ -1353,12 +1464,16 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceKeepingDescendants) {
// Swap order of the subsequences of container1 and container2.
// Nothing invalidated. Should keep all subsequences.
- EXPECT_TRUE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container2));
- EXPECT_TRUE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container1));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container2));
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container1));
- CommitAndFinishCycle();
+ EXPECT_EQ(7u, NumCachedNewItems());
+ EXPECT_EQ(6u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&container2, kBackgroundType),
@@ -1390,20 +1505,21 @@ TEST_P(PaintControllerTest, SkipCache) {
FakeDisplayItemClient multicol("multicol");
FakeDisplayItemClient content("content");
GraphicsContext context(GetPaintController());
- InitRootChunk();
-
IntRect rect1(100, 100, 50, 50);
IntRect rect2(150, 100, 50, 50);
IntRect rect3(200, 100, 50, 50);
- DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
- GetPaintController().BeginSkippingCache();
- DrawRect(context, content, kForegroundType, rect1);
- DrawRect(context, content, kForegroundType, rect2);
- GetPaintController().EndSkippingCache();
+ DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
- CommitAndFinishCycle();
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&multicol, kBackgroundType),
@@ -1418,25 +1534,26 @@ TEST_P(PaintControllerTest, SkipCache) {
EXPECT_NE(record1, record2);
EXPECT_DEFAULT_ROOT_CHUNK(3);
- InitRootChunk();
- // Draw again with nothing invalidated.
- EXPECT_TRUE(ClientCacheIsValid(multicol));
- DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ // Draw again with nothing invalidated.
+ EXPECT_TRUE(ClientCacheIsValid(multicol));
+ DrawRect(context, multicol, kBackgroundType, IntRect(100, 200, 100, 100));
- GetPaintController().BeginSkippingCache();
- DrawRect(context, content, kForegroundType, rect1);
- DrawRect(context, content, kForegroundType, rect2);
- GetPaintController().EndSkippingCache();
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
- EXPECT_EQ(1u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ EXPECT_EQ(1u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(0u, NumIndexedItems());
- EXPECT_EQ(1u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(0u, NumIndexedItems());
+ EXPECT_EQ(1u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&multicol, kBackgroundType),
@@ -1450,31 +1567,32 @@ TEST_P(PaintControllerTest, SkipCache) {
.GetPaintRecord());
EXPECT_DEFAULT_ROOT_CHUNK(3);
- InitRootChunk();
- // Now the multicol becomes 3 columns and repaints.
- multicol.Invalidate();
- DrawRect(context, multicol, kBackgroundType, IntRect(100, 100, 100, 100));
-
- GetPaintController().BeginSkippingCache();
- DrawRect(context, content, kForegroundType, rect1);
- DrawRect(context, content, kForegroundType, rect2);
- DrawRect(context, content, kForegroundType, rect3);
- GetPaintController().EndSkippingCache();
-
- // We should repaint everything on invalidation of the scope container.
- const auto& display_item_list =
- GetPaintController().GetNewPaintArtifactShared()->GetDisplayItemList();
- EXPECT_THAT(display_item_list,
- ElementsAre(IsSameId(&multicol, kBackgroundType),
- IsSameId(&content, kForegroundType),
- IsSameId(&content, kForegroundType),
- IsSameId(&content, kForegroundType)));
- EXPECT_NE(record1,
- To<DrawingDisplayItem>(display_item_list[1]).GetPaintRecord());
- EXPECT_NE(record2,
- To<DrawingDisplayItem>(display_item_list[2]).GetPaintRecord());
-
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ // Now the multicol becomes 3 columns and repaints.
+ multicol.Invalidate();
+ DrawRect(context, multicol, kBackgroundType, IntRect(100, 100, 100, 100));
+
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ DrawRect(context, content, kForegroundType, rect3);
+ GetPaintController().EndSkippingCache();
+
+ // We should repaint everything on invalidation of the scope container.
+ const auto& display_item_list =
+ GetPaintController().GetNewPaintArtifactShared()->GetDisplayItemList();
+ EXPECT_THAT(display_item_list,
+ ElementsAre(IsSameId(&multicol, kBackgroundType),
+ IsSameId(&content, kForegroundType),
+ IsSameId(&content, kForegroundType),
+ IsSameId(&content, kForegroundType)));
+ EXPECT_NE(record1,
+ To<DrawingDisplayItem>(display_item_list[1]).GetPaintRecord());
+ EXPECT_NE(record2,
+ To<DrawingDisplayItem>(display_item_list[2]).GetPaintRecord());
+ }
EXPECT_DEFAULT_ROOT_CHUNK(4);
}
@@ -1486,14 +1604,15 @@ TEST_P(PaintControllerTest, PartialSkipCache) {
IntRect rect2(150, 100, 50, 50);
IntRect 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);
-
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, content, kBackgroundType, rect1);
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ DrawRect(context, content, kForegroundType, rect3);
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content, kBackgroundType),
@@ -1515,23 +1634,24 @@ TEST_P(PaintControllerTest, PartialSkipCache) {
EXPECT_EQ(PaintInvalidationReason::kUncacheable,
content.GetPaintInvalidationReason());
- 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_EQ(0u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ 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_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- EXPECT_EQ(0u, NumIndexedItems());
- EXPECT_EQ(0u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ EXPECT_EQ(0u, NumIndexedItems());
+ EXPECT_EQ(0u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content, kBackgroundType),
@@ -1555,17 +1675,18 @@ TEST_P(PaintControllerTest, SkipCacheDuplicatedItemAndChunkIds) {
PaintChunk::Id chunk_id(chunk_client, DisplayItem::kLayerChunk);
auto& paint_controller = GetPaintController();
- GraphicsContext context(paint_controller);
- paint_controller.BeginSkippingCache();
- paint_controller.SetWillForceNewChunk(true);
- paint_controller.UpdateCurrentPaintChunkProperties(&chunk_id, properties);
- DrawRect(context, item_client, kBackgroundType, IntRect(0, 0, 100, 100));
- paint_controller.SetWillForceNewChunk(true);
- paint_controller.UpdateCurrentPaintChunkProperties(&chunk_id, properties);
- DrawRect(context, item_client, kBackgroundType, IntRect(0, 0, 100, 100));
- paint_controller.EndSkippingCache();
-
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(paint_controller);
+ GraphicsContext context(paint_controller);
+ paint_controller.BeginSkippingCache();
+ paint_controller.SetWillForceNewChunk(true);
+ paint_controller.UpdateCurrentPaintChunkProperties(&chunk_id, properties);
+ DrawRect(context, item_client, kBackgroundType, IntRect(0, 0, 100, 100));
+ paint_controller.SetWillForceNewChunk(true);
+ paint_controller.UpdateCurrentPaintChunkProperties(&chunk_id, properties);
+ DrawRect(context, item_client, kBackgroundType, IntRect(0, 0, 100, 100));
+ paint_controller.EndSkippingCache();
+ }
EXPECT_THAT(paint_controller.GetDisplayItemList(),
ElementsAre(IsSameId(&item_client, kBackgroundType),
@@ -1583,15 +1704,15 @@ TEST_P(PaintControllerTest, SkipCacheDuplicatedItemAndChunkIds) {
TEST_P(PaintControllerTest, SmallPaintControllerHasOnePaintChunk) {
FakeDisplayItemClient client("test client");
- InitRootChunk();
- GraphicsContext context(GetPaintController());
- DrawRect(context, client, kBackgroundType, IntRect(0, 0, 100, 100));
-
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ GraphicsContext context(GetPaintController());
+ DrawRect(context, client, kBackgroundType, IntRect(0, 0, 100, 100));
+ }
EXPECT_THAT(GetPaintController().PaintChunks(),
ElementsAre(IsPaintChunk(0, 1)));
}
-
void DrawPath(GraphicsContext& context,
DisplayItemClient& client,
DisplayItem::Type type,
@@ -1664,15 +1785,17 @@ TEST_P(PaintControllerTest, InsertValidItemInFront) {
FakeDisplayItemClient fourth("fourth");
GraphicsContext context(GetPaintController());
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, third, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, fourth, kBackgroundType, IntRect(100, 100, 50, 50));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, third, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, fourth, kBackgroundType, IntRect(100, 100, 50, 50));
- EXPECT_EQ(0u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
- CommitAndFinishCycle();
+ EXPECT_EQ(0u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
IsSameId(&second, kBackgroundType),
@@ -1685,20 +1808,21 @@ TEST_P(PaintControllerTest, InsertValidItemInFront) {
// 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, IntRect(100, 100, 100, 100));
- DrawRect(context, fourth, kBackgroundType, IntRect(100, 100, 50, 50));
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, third, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, fourth, kBackgroundType, IntRect(100, 100, 50, 50));
- EXPECT_EQ(2u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- // We indexed "first" and "second" when finding the cached item for "third".
- EXPECT_EQ(2u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ // We indexed "first" and "second" when finding the cached item for "third".
+ EXPECT_EQ(2u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&third, kBackgroundType),
IsSameId(&fourth, kBackgroundType)));
@@ -1708,22 +1832,23 @@ TEST_P(PaintControllerTest, InsertValidItemInFront) {
EXPECT_TRUE(fourth.IsValid());
// Simulate "first" and "second" are scrolled back into the interest rect.
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
- DrawRect(context, third, kBackgroundType, IntRect(100, 100, 100, 100));
- DrawRect(context, fourth, kBackgroundType, IntRect(100, 100, 50, 50));
-
- EXPECT_EQ(2u, NumCachedNewItems());
- EXPECT_EQ(0u, NumCachedNewSubsequences());
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, IntRect(100, 100, 200, 200));
+ DrawRect(context, third, kBackgroundType, IntRect(100, 100, 100, 100));
+ DrawRect(context, fourth, kBackgroundType, IntRect(100, 100, 50, 50));
+
+ EXPECT_EQ(2u, NumCachedNewItems());
+ EXPECT_EQ(0u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
- // We indexed "third" and "fourth" when finding the cached item for "first".
- EXPECT_EQ(2u, NumIndexedItems());
- EXPECT_EQ(2u, NumSequentialMatches());
- EXPECT_EQ(0u, NumOutOfOrderMatches());
+ // We indexed "third" and "fourth" when finding the cached item for "first".
+ EXPECT_EQ(2u, NumIndexedItems());
+ EXPECT_EQ(2u, NumSequentialMatches());
+ EXPECT_EQ(0u, NumOutOfOrderMatches());
#endif
-
- CommitAndFinishCycle();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&first, kBackgroundType),
IsSameId(&second, kBackgroundType),
@@ -1760,25 +1885,28 @@ TEST_P(PaintControllerTest, AllowDuplicatedIdForUncacheableItem) {
EXPECT_TRUE(cacheable.IsCacheable());
EXPECT_FALSE(uncacheable.IsCacheable());
- InitRootChunk();
{
- SubsequenceRecorder recorder(context, cacheable);
- DrawRect(context, cacheable, kBackgroundType, IntRect(r));
- DrawRect(context, uncacheable, kBackgroundType, IntRect(r));
- // This should not trigger the duplicated id assert.
- DrawRect(context, uncacheable, kBackgroundType, IntRect(r));
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder recorder(context, cacheable);
+ DrawRect(context, cacheable, kBackgroundType, IntRect(r));
+ DrawRect(context, uncacheable, kBackgroundType, IntRect(r));
+ // This should not trigger the duplicated id assert.
+ DrawRect(context, uncacheable, kBackgroundType, IntRect(r));
+ }
}
-
- CommitAndFinishCycle();
EXPECT_TRUE(GetPaintController().GetDisplayItemList()[0].IsCacheable());
EXPECT_FALSE(GetPaintController().GetDisplayItemList()[1].IsCacheable());
EXPECT_FALSE(GetPaintController().GetDisplayItemList()[2].IsCacheable());
EXPECT_TRUE(cacheable.IsCacheable());
EXPECT_FALSE(uncacheable.IsCacheable());
- InitRootChunk();
- EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(cacheable));
- CommitAndFinishCycle();
+ {
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(cacheable));
+ }
EXPECT_TRUE(GetPaintController().GetDisplayItemList()[0].IsCacheable());
EXPECT_FALSE(GetPaintController().GetDisplayItemList()[1].IsCacheable());
EXPECT_FALSE(GetPaintController().GetDisplayItemList()[2].IsCacheable());
@@ -1791,19 +1919,22 @@ TEST_P(PaintControllerTest, AllowDuplicatedIdForUncacheableItem) {
TEST_P(PaintControllerTest, DuplicatedSubsequences) {
FakeDisplayItemClient client("test");
- GraphicsContext context(GetPaintController());
+ PaintController& controller = GetPaintController();
+ GraphicsContext context(controller);
auto paint_duplicated_subsequences = [&]() {
- InitRootChunk();
{
- SubsequenceRecorder r(context, client);
- DrawRect(context, client, kBackgroundType, IntRect(100, 100, 100, 100));
+ CommitCycleScope cycle_scope(controller);
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, client);
+ DrawRect(context, client, kBackgroundType, IntRect(100, 100, 100, 100));
+ }
+ {
+ SubsequenceRecorder r(context, client);
+ DrawRect(context, client, kForegroundType, IntRect(100, 100, 100, 100));
+ }
}
- {
- SubsequenceRecorder r(context, client);
- DrawRect(context, client, kForegroundType, IntRect(100, 100, 100, 100));
- }
- CommitAndFinishCycle();
};
#if DCHECK_IS_ON()
@@ -1811,27 +1942,29 @@ TEST_P(PaintControllerTest, DuplicatedSubsequences) {
"Multiple subsequences for client: \"test\"");
#else
// The following is for non-DCHECK path. No security CHECK should trigger.
- paint_duplicated_subsequences();
- // Paint again.
- InitRootChunk();
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- EXPECT_FALSE(GetPaintController().UseCachedSubsequenceIfPossible(client));
- SubsequenceRecorder r(context, client);
- DrawRect(context, client, kBackgroundType, IntRect(100, 100, 100, 100));
- } else {
- EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(client));
- }
{
- // Should not use the cached duplicated subsequence.
- EXPECT_FALSE(GetPaintController().UseCachedSubsequenceIfPossible(client));
- SubsequenceRecorder r(context, client);
- DrawRect(context, client, kForegroundType, IntRect(100, 100, 100, 100));
+ CommitCycleScope cycle_scope(GetPaintController());
+ paint_duplicated_subsequences();
+ // Paint again.
+ InitRootChunk();
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+ EXPECT_FALSE(GetPaintController().UseCachedSubsequenceIfPossible(client));
+ SubsequenceRecorder r(context, client);
+ DrawRect(context, client, kBackgroundType, IntRect(100, 100, 100, 100));
+ } else {
+ EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(client));
+ }
+ {
+ // Should not use the cached duplicated subsequence.
+ EXPECT_FALSE(GetPaintController().UseCachedSubsequenceIfPossible(client));
+ SubsequenceRecorder r(context, client);
+ DrawRect(context, client, kForegroundType, IntRect(100, 100, 100, 100));
+ }
}
- CommitAndFinishCycle();
#endif
}
-TEST_P(PaintControllerTest, DeletedClientInUnderInvaldiatedSubsequence) {
+TEST_P(PaintControllerTest, DeletedClientInUnderInvalidatedSubsequence) {
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
return;
@@ -1839,298 +1972,30 @@ TEST_P(PaintControllerTest, DeletedClientInUnderInvaldiatedSubsequence) {
auto content = std::make_unique<FakeDisplayItemClient>("content");
GraphicsContext context(GetPaintController());
- InitRootChunk();
{
- SubsequenceRecorder r(context, container);
- DrawRect(context, *content, kBackgroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
-
- content = nullptr;
- InitRootChunk();
- // Leave container not invalidated.
-#if DCHECK_IS_ON()
- ASSERT_DEATH(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container),
- "");
-#else
- // This should not crash.
- EXPECT_TRUE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container));
- CommitAndFinishCycle();
-#endif
-}
-
-class PaintControllerUnderInvalidationTest
- : public PaintControllerTestBase,
- private ScopedPaintUnderInvalidationCheckingForTest {
- public:
- PaintControllerUnderInvalidationTest()
- : PaintControllerTestBase(),
- ScopedPaintUnderInvalidationCheckingForTest(true) {}
-
- protected:
- void SetUp() override {
- testing::FLAGS_gtest_death_test_style = "threadsafe";
- }
-
- void TestChangeDrawing() {
- FakeDisplayItemClient first("first");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
-
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(200, 200, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
- }
-
- void TestMoreDrawing() {
- FakeDisplayItemClient first("first");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
-
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
- }
-
- void TestLessDrawing() {
- FakeDisplayItemClient first("first");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
-
- InitRootChunk();
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- CommitAndFinishCycle();
- }
-
- void TestChangeDrawingInSubsequence() {
- FakeDisplayItemClient first("first");
- GraphicsContext context(GetPaintController());
- InitRootChunk();
- {
- SubsequenceRecorder r(context, first);
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
-
- InitRootChunk();
- {
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, first));
- SubsequenceRecorder r(context, first);
- DrawRect(context, first, kBackgroundType, IntRect(200, 200, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
- }
-
- void TestMoreDrawingInSubsequence() {
- FakeDisplayItemClient first("first");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, first);
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
-
- InitRootChunk();
- {
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, first));
- SubsequenceRecorder r(context, first);
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
- }
-
- void TestLessDrawingInSubsequence() {
- FakeDisplayItemClient first("first");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, first);
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- DrawRect(context, first, kForegroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
-
- InitRootChunk();
- {
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, first));
- SubsequenceRecorder r(context, first);
- DrawRect(context, first, kBackgroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
- }
-
- void TestInvalidationInSubsequence() {
- FakeDisplayItemClient container("container");
- FakeDisplayItemClient content("content");
- GraphicsContext context(GetPaintController());
-
+ CommitCycleScope cycle_scope(GetPaintController());
InitRootChunk();
{
SubsequenceRecorder r(context, container);
- DrawRect(context, content, kBackgroundType, IntRect(100, 100, 300, 300));
+ DrawRect(context, *content, kBackgroundType, IntRect(100, 100, 300, 300));
}
- CommitAndFinishCycle();
-
- content.Invalidate();
- InitRootChunk();
- // Leave container not invalidated.
- {
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container));
- SubsequenceRecorder r(context, container);
- DrawRect(context, content, kBackgroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
}
- void TestSubsequenceBecomesEmpty() {
- FakeDisplayItemClient target("target");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, target);
- DrawRect(context, target, kBackgroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
-
- InitRootChunk();
- {
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, target));
- SubsequenceRecorder r(context, target);
- }
- CommitAndFinishCycle();
- }
-};
-
-TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawing) {
- EXPECT_DEATH(TestChangeDrawing(), "under-invalidation: display item changed");
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, MoreDrawing) {
- // We don't detect under-invalidation in this case, and PaintController can
- // also handle the case gracefully.
- TestMoreDrawing();
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, LessDrawing) {
- // We don't detect under-invalidation in this case, and PaintController can
- // also handle the case gracefully.
- TestLessDrawing();
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawingInSubsequence) {
- EXPECT_DEATH(TestChangeDrawingInSubsequence(),
- "In cached subsequence for first.*"
- "under-invalidation: display item changed");
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, MoreDrawingInSubsequence) {
- // TODO(wangxianzhu): Detect more drawings at the end of a subsequence.
- TestMoreDrawingInSubsequence();
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, LessDrawingInSubsequence) {
- EXPECT_DEATH(TestLessDrawingInSubsequence(),
- "In cached subsequence for first.*"
- "under-invalidation: chunk changed");
-}
-
-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
- // test cases.
- TestInvalidationInSubsequence();
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, SubsequenceBecomesEmpty) {
- EXPECT_DEATH(TestSubsequenceBecomesEmpty(),
- "In cached subsequence for target.*"
- "under-invalidation: new subsequence wrong length");
-}
-
-TEST_F(PaintControllerUnderInvalidationTest, SkipCacheInSubsequence) {
- FakeDisplayItemClient container("container");
- FakeDisplayItemClient content("content");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, container);
- {
- DisplayItemCacheSkipper cache_skipper(context);
- DrawRect(context, content, kBackgroundType, IntRect(100, 100, 300, 300));
- }
- DrawRect(context, content, kForegroundType, IntRect(200, 200, 400, 400));
- }
- CommitAndFinishCycle();
-
- InitRootChunk();
- {
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container));
- SubsequenceRecorder r(context, container);
- {
- DisplayItemCacheSkipper cache_skipper(context);
- DrawRect(context, content, kBackgroundType, IntRect(200, 200, 400, 400));
- }
- DrawRect(context, content, kForegroundType, IntRect(200, 200, 400, 400));
- }
- CommitAndFinishCycle();
-}
-
-TEST_F(PaintControllerUnderInvalidationTest,
- EmptySubsequenceInCachedSubsequence) {
- FakeDisplayItemClient container("container");
- FakeDisplayItemClient content("content");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, container);
- DrawRect(context, container, kBackgroundType, IntRect(100, 100, 300, 300));
- { SubsequenceRecorder r1(context, content); }
- DrawRect(context, container, kForegroundType, IntRect(100, 100, 300, 300));
- }
- CommitAndFinishCycle();
-
- InitRootChunk();
+ content = nullptr;
{
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container));
- SubsequenceRecorder r(context, container);
- DrawRect(context, container, kBackgroundType, IntRect(100, 100, 300, 300));
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, content));
- { SubsequenceRecorder r1(context, content); }
- DrawRect(context, container, kForegroundType, IntRect(100, 100, 300, 300));
+ CommitCycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ // Leave container not invalidated.
+#if DCHECK_IS_ON()
+ ASSERT_DEATH(
+ SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container),
+ "");
+#else
+ // This should not crash.
+ EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(context,
+ container));
+#endif
}
- 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 e1628376aea..f8839d0b145 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
@@ -45,6 +45,10 @@ class PaintControllerTestBase : public testing::Test {
DisplayItem::kUninitializedType),
paint_controller_(std::make_unique<PaintController>()) {}
+ void SetUp() override {
+ testing::FLAGS_gtest_death_test_style = "threadsafe";
+ }
+
void InitRootChunk() { InitRootChunk(GetPaintController()); }
void InitRootChunk(PaintController& paint_controller) {
paint_controller.UpdateCurrentPaintChunkProperties(
@@ -76,11 +80,6 @@ class PaintControllerTestBase : public testing::Test {
void InvalidateAll() { paint_controller_->InvalidateAllForTesting(); }
- void CommitAndFinishCycle() {
- paint_controller_->CommitNewDisplayItems();
- paint_controller_->FinishCycle();
- }
-
using SubsequenceMarkers = PaintController::SubsequenceMarkers;
const SubsequenceMarkers* GetSubsequenceMarkers(
const DisplayItemClient& client) {
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 79d99bbbc81..a161110e24c 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
@@ -27,7 +27,6 @@ PaintRecordBuilder::~PaintRecordBuilder() = default;
sk_sp<PaintRecord> PaintRecordBuilder::EndRecording(
const PropertyTreeState& replay_state) {
paint_controller_->CommitNewDisplayItems();
- paint_controller_->FinishCycle();
return paint_controller_->GetPaintArtifact().GetPaintRecord(replay_state);
}
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 efd5eb3ccdf..c78293481e1 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
@@ -36,34 +36,40 @@ TEST_F(PaintRecordBuilderTest, TransientPaintController) {
}
TEST_F(PaintRecordBuilderTest, LastingPaintController) {
- InitRootChunk();
-
+ FakeDisplayItemClient client("client");
PaintRecordBuilder builder(GetPaintController());
auto& context = builder.Context();
- EXPECT_EQ(&context.GetPaintController(), &GetPaintController());
-
- FakeDisplayItemClient client("client");
- DrawRect(context, client, kBackgroundType, IntRect(10, 10, 20, 20));
- DrawRect(context, client, kForegroundType, IntRect(15, 15, 10, 10));
- EXPECT_FALSE(ClientCacheIsValid(client));
-
MockPaintCanvas canvas;
PaintFlags flags;
- EXPECT_CALL(canvas, drawPicture(_)).Times(1);
- builder.EndRecording(canvas);
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+
+ EXPECT_EQ(&context.GetPaintController(), &GetPaintController());
+
+ DrawRect(context, client, kBackgroundType, IntRect(10, 10, 20, 20));
+ DrawRect(context, client, kForegroundType, IntRect(15, 15, 10, 10));
+ EXPECT_FALSE(ClientCacheIsValid(client));
+
+ EXPECT_CALL(canvas, drawPicture(_)).Times(1);
+ builder.EndRecording(canvas);
+ }
EXPECT_TRUE(ClientCacheIsValid(client));
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kBackgroundType),
IsSameId(&client, kForegroundType)));
- InitRootChunk();
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
- kBackgroundType));
- EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
- kForegroundType));
- EXPECT_CALL(canvas, drawPicture(_)).Times(1);
- builder.EndRecording(canvas);
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
+ kBackgroundType));
+ EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
+ kForegroundType));
+ EXPECT_CALL(canvas, drawPicture(_)).Times(1);
+ builder.EndRecording(canvas);
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kBackgroundType),
@@ -73,21 +79,27 @@ TEST_F(PaintRecordBuilderTest, LastingPaintController) {
TEST_F(PaintRecordBuilderTest, TransientAndAnotherPaintController) {
GraphicsContext context(GetPaintController());
-
- InitRootChunk();
FakeDisplayItemClient client("client");
- DrawRect(context, client, kBackgroundType, IntRect(10, 10, 20, 20));
- DrawRect(context, client, kForegroundType, IntRect(15, 15, 10, 10));
- CommitAndFinishCycle();
+ PaintRecordBuilder builder;
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, client, kBackgroundType, IntRect(10, 10, 20, 20));
+ DrawRect(context, client, kForegroundType, IntRect(15, 15, 10, 10));
+ GetPaintController().CommitNewDisplayItems();
+ }
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&client, kBackgroundType),
IsSameId(&client, kForegroundType)));
EXPECT_TRUE(ClientCacheIsValid(client));
- PaintRecordBuilder builder;
- EXPECT_NE(&builder.Context().GetPaintController(), &GetPaintController());
- DrawRect(builder.Context(), client, kBackgroundType, IntRect(10, 10, 20, 20));
- builder.EndRecording();
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ EXPECT_NE(&builder.Context().GetPaintController(), &GetPaintController());
+ DrawRect(builder.Context(), client, kBackgroundType,
+ IntRect(10, 10, 20, 20));
+ builder.EndRecording();
+ }
// The transient PaintController in PaintRecordBuilder doesn't affect the
// client's cache status in another PaintController.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.cc
new file mode 100644
index 00000000000..2781aa20523
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.cc
@@ -0,0 +1,254 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.h"
+
+#include "base/logging.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/graphics/paint/paint_controller.h"
+
+namespace blink {
+
+PaintUnderInvalidationChecker::PaintUnderInvalidationChecker(
+ PaintController& paint_controller)
+ : paint_controller_(paint_controller) {
+#if DCHECK_IS_ON()
+ DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
+ DCHECK_EQ(paint_controller_.GetUsage(), PaintController::kMultiplePaints);
+#endif
+}
+
+PaintUnderInvalidationChecker::~PaintUnderInvalidationChecker() {
+ DCHECK(!IsChecking());
+}
+
+bool PaintUnderInvalidationChecker::IsChecking() const {
+ if (old_item_index_ != kNotFound) {
+ DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
+ DCHECK(!subsequence_client_ ||
+ (old_chunk_index_ != kNotFound && new_chunk_index_ != kNotFound));
+ return true;
+ }
+
+ DCHECK(!subsequence_client_);
+ DCHECK_EQ(old_chunk_index_, kNotFound);
+ DCHECK_EQ(new_chunk_index_, kNotFound);
+ return false;
+}
+
+bool PaintUnderInvalidationChecker::IsCheckingSubsequence() const {
+ if (subsequence_client_) {
+ DCHECK(IsChecking());
+ return true;
+ }
+ return false;
+}
+
+void PaintUnderInvalidationChecker::Stop() {
+ DCHECK(IsChecking());
+ old_chunk_index_ = kNotFound;
+ new_chunk_index_ = kNotFound;
+ old_item_index_ = kNotFound;
+ subsequence_client_ = nullptr;
+}
+
+void PaintUnderInvalidationChecker::WouldUseCachedItem(
+ wtf_size_t old_item_index) {
+ DCHECK(!IsChecking());
+ old_item_index_ = old_item_index;
+}
+
+void PaintUnderInvalidationChecker::CheckNewItem() {
+ DCHECK(IsChecking());
+
+ if (paint_controller_.IsSkippingCache()) {
+ // We allow cache skipping and temporary under-invalidation in cached
+ // subsequences. See the usage of DisplayItemCacheSkipper in BoxPainter.
+ Stop();
+ // Match the remaining display items in the subsequence normally.
+ paint_controller_.next_item_to_match_ = old_item_index_;
+ paint_controller_.next_item_to_index_ = old_item_index_;
+ return;
+ }
+
+ const auto& new_item = NewDisplayItemList().back();
+ if (old_item_index_ >= OldDisplayItemList().size())
+ ShowItemError("extra display item", new_item);
+
+ auto& old_item = OldDisplayItemList()[old_item_index_];
+ if (!new_item.EqualsForUnderInvalidation(old_item))
+ ShowItemError("display item changed", new_item, &old_item);
+
+ // Discard the forced repainted display item and move the cached item into
+ // new_display_item_list_. This is to align with the
+ // non-under-invalidation-checking path to empty the original cached slot,
+ // leaving only disappeared or invalidated display items in the old list after
+ // painting.
+ NewDisplayItemList().ReplaceLastByMoving(old_item);
+ NewDisplayItemList().back().SetPaintInvalidationReason(
+ old_item.IsCacheable() ? PaintInvalidationReason::kNone
+ : PaintInvalidationReason::kUncacheable);
+
+ if (subsequence_client_) {
+ // We are checking under-invalidation of a cached subsequence.
+ ++old_item_index_;
+ } else {
+ // We have checked the single item for under-invalidation.
+ Stop();
+ }
+}
+
+void PaintUnderInvalidationChecker::WouldUseCachedSubsequence(
+ const DisplayItemClient& client) {
+ DCHECK(!IsChecking());
+
+ const auto* markers = paint_controller_.GetSubsequenceMarkers(client);
+ DCHECK(markers);
+ old_chunk_index_ = markers->start_chunk_index;
+ new_chunk_index_ = NewPaintChunks().size();
+ old_item_index_ = OldPaintChunks()[markers->start_chunk_index].begin_index;
+ subsequence_client_ = &client;
+}
+
+void PaintUnderInvalidationChecker::CheckNewChunk() {
+ DCHECK(IsChecking());
+ if (!IsCheckingSubsequence())
+ return;
+
+ if (NewPaintChunks().size() > new_chunk_index_ + 1) {
+ // Check the previous new chunk (pointed by new_chunk_index_, before the
+ // just added chunk) which is now complete. The just added chunk will be
+ // checked when it's complete later in CheckNewChunk() or
+ // WillEndSubsequence().
+ CheckNewChunkInternal();
+ }
+}
+
+void PaintUnderInvalidationChecker::WillEndSubsequence(
+ const DisplayItemClient& client,
+ wtf_size_t start_chunk_index) {
+ DCHECK(IsChecking());
+ if (!IsCheckingSubsequence())
+ return;
+
+ const auto* markers = paint_controller_.GetSubsequenceMarkers(client);
+ if (!markers) {
+ if (start_chunk_index != NewPaintChunks().size())
+ ShowSubsequenceError("unexpected subsequence", &client);
+ } else if (markers->end_chunk_index - markers->start_chunk_index !=
+ NewPaintChunks().size() - start_chunk_index) {
+ ShowSubsequenceError("new subsequence wrong length", &client);
+ } else {
+ // Now we know that the last chunk in the subsequence is complete. See also
+ // CheckNewChunk().
+ auto end_chunk_index = NewPaintChunks().size();
+ if (new_chunk_index_ < end_chunk_index) {
+ DCHECK_EQ(new_chunk_index_ + 1, end_chunk_index);
+ CheckNewChunkInternal();
+ DCHECK_EQ(new_chunk_index_, end_chunk_index);
+ }
+ }
+
+ if (subsequence_client_ == &client)
+ Stop();
+}
+
+void PaintUnderInvalidationChecker::CheckNewChunkInternal() {
+ DCHECK(subsequence_client_);
+ const auto* markers =
+ paint_controller_.GetSubsequenceMarkers(*subsequence_client_);
+ DCHECK(markers);
+ const auto& new_chunk = NewPaintChunks()[new_chunk_index_];
+ if (old_chunk_index_ >= markers->end_chunk_index) {
+ ShowSubsequenceError("extra chunk", nullptr, &new_chunk);
+ } else {
+ const auto& old_chunk = OldPaintChunks()[old_chunk_index_];
+ if (!old_chunk.EqualsForUnderInvalidationChecking(new_chunk)) {
+ ShowSubsequenceError("chunk changed", nullptr, &new_chunk, &old_chunk);
+ }
+ }
+ new_chunk_index_++;
+ old_chunk_index_++;
+}
+
+void PaintUnderInvalidationChecker::ShowItemError(
+ const char* reason,
+ const DisplayItem& new_item,
+ const DisplayItem* old_item) const {
+ if (subsequence_client_) {
+ LOG(ERROR) << "(In cached subsequence for "
+ << subsequence_client_->DebugName() << ")";
+ }
+ LOG(ERROR) << "Under-invalidation: " << reason;
+#if DCHECK_IS_ON()
+ LOG(ERROR) << "New display item: " << new_item.AsDebugString();
+ if (old_item)
+ LOG(ERROR) << "Old display item: " << old_item->AsDebugString();
+ LOG(ERROR) << "See http://crbug.com/619103.";
+
+ if (auto* new_drawing = DynamicTo<DrawingDisplayItem>(new_item)) {
+ auto* new_record = new_drawing->GetPaintRecord().get();
+ LOG(INFO) << "new record:\n"
+ << (new_record ? RecordAsDebugString(*new_record).Utf8() : "{}");
+ }
+ if (auto* old_drawing = DynamicTo<DrawingDisplayItem>(old_item)) {
+ auto* old_record = old_drawing->GetPaintRecord().get();
+ LOG(INFO) << "old record:\n"
+ << (old_record ? RecordAsDebugString(*old_record).Utf8() : "{}");
+ }
+
+ paint_controller_.ShowDebugData();
+#else
+ LOG(ERROR) << "Run a build with DCHECK on to get more details.";
+#endif
+ LOG(FATAL) << "See https://crbug.com/619103.";
+}
+
+void PaintUnderInvalidationChecker::ShowSubsequenceError(
+ const char* reason,
+ const DisplayItemClient* client,
+ const PaintChunk* new_chunk,
+ const PaintChunk* old_chunk) {
+ if (subsequence_client_) {
+ LOG(ERROR) << "(In cached subsequence for "
+ << subsequence_client_->DebugName() << ")";
+ }
+ LOG(ERROR) << "Under-invalidation: " << reason;
+ if (client) {
+ // |client| may be different from |subsequence_client_| if the error occurs
+ // in a descendant subsequence of the cached subsequence.
+ LOG(ERROR) << "Subsequence client: " << client->DebugName();
+ }
+ if (new_chunk)
+ LOG(ERROR) << "New paint chunk: " << *new_chunk;
+ if (old_chunk)
+ LOG(ERROR) << "Old paint chunk: " << *old_chunk;
+#if DCHECK_IS_ON()
+ paint_controller_.ShowDebugData();
+#else
+ LOG(ERROR) << "Run a build with DCHECK on to get more details.";
+#endif
+ LOG(FATAL) << "See https://crbug.com/619103.";
+}
+
+const Vector<PaintChunk>& PaintUnderInvalidationChecker::OldPaintChunks()
+ const {
+ return paint_controller_.current_paint_artifact_->PaintChunks();
+}
+
+const Vector<PaintChunk>& PaintUnderInvalidationChecker::NewPaintChunks()
+ const {
+ return paint_controller_.new_paint_artifact_->PaintChunks();
+}
+
+DisplayItemList& PaintUnderInvalidationChecker::OldDisplayItemList() {
+ return paint_controller_.current_paint_artifact_->GetDisplayItemList();
+}
+
+DisplayItemList& PaintUnderInvalidationChecker::NewDisplayItemList() {
+ return paint_controller_.new_paint_artifact_->GetDisplayItemList();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.h
new file mode 100644
index 00000000000..6f5ac2bbb77
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker.h
@@ -0,0 +1,76 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_UNDER_INVALIDATION_CHECKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_UNDER_INVALIDATION_CHECKER_H_
+
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class DisplayItem;
+class DisplayItemClient;
+class DisplayItemList;
+class PaintController;
+struct PaintChunk;
+
+// If RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled(),
+// when PaintController can use a cached display item or a cached subsequence,
+// it lets the client paint instead of using the cache, and this class checks
+// whether the painting is the same as the cache.
+class PaintUnderInvalidationChecker {
+ public:
+ explicit PaintUnderInvalidationChecker(PaintController& paint_controller);
+ ~PaintUnderInvalidationChecker();
+
+ bool IsChecking() const;
+
+ // Called from PaintController::UseCachedItemIfPossible() to inform that
+ // PaintController would use a cached display item if we were not checking
+ // under-invalidations.
+ void WouldUseCachedItem(wtf_size_t old_item_index);
+ void CheckNewItem();
+
+ // Called from PaintController::UseCachedSubsequenceIfPossible() to inform
+ // that PaintController would use a cached subsequence if we were not checking
+ // under-invalidations.
+ void WouldUseCachedSubsequence(const DisplayItemClient&);
+ void CheckNewChunk();
+ void WillEndSubsequence(const DisplayItemClient& client,
+ wtf_size_t start_chunk_index);
+
+ private:
+ bool IsCheckingSubsequence() const;
+ void Stop();
+ void CheckNewChunkInternal();
+ void ShowItemError(const char* reason,
+ const DisplayItem& new_item,
+ const DisplayItem* old_item = nullptr) const;
+ void ShowSubsequenceError(const char* reason,
+ const DisplayItemClient* = nullptr,
+ const PaintChunk* new_chunk = nullptr,
+ const PaintChunk* old_chunk = nullptr);
+
+ const Vector<PaintChunk>& OldPaintChunks() const;
+ const Vector<PaintChunk>& NewPaintChunks() const;
+ DisplayItemList& OldDisplayItemList();
+ DisplayItemList& NewDisplayItemList();
+
+ PaintController& paint_controller_;
+
+ // Points to the cached display item which is expected to match the nextnew
+ // display item.
+ wtf_size_t old_item_index_ = kNotFound;
+ // Points to the cached paint chunk which is expected to match the next
+ // complete new paint chunk.
+ wtf_size_t old_chunk_index_ = kNotFound;
+ // Points to the next new paint chunk which will be checked when it's
+ // complete.
+ wtf_size_t new_chunk_index_ = kNotFound;
+ const DisplayItemClient* subsequence_client_ = nullptr;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_UNDER_INVALIDATION_CHECKER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker_test.cc
new file mode 100644
index 00000000000..f93aba60037
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_under_invalidation_checker_test.cc
@@ -0,0 +1,351 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
+#include "third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
+
+using testing::ElementsAre;
+
+namespace blink {
+
+// Death tests don't work properly on Android.
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
+
+class PaintControllerUnderInvalidationTest
+ : private ScopedPaintUnderInvalidationCheckingForTest,
+ public PaintControllerTestBase {
+ public:
+ PaintControllerUnderInvalidationTest()
+ : ScopedPaintUnderInvalidationCheckingForTest(true) {}
+};
+
+TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawing) {
+ auto test = [&]() {
+ FakeDisplayItemClient first("first");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(2, 2, 3, 3));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ GetPaintController().CommitNewDisplayItems();
+ }
+ };
+
+ EXPECT_DEATH(test(),
+ "Under-invalidation: display item changed\n"
+#if DCHECK_IS_ON()
+ ".*New display item:.*2,2 3x3.*\n"
+ ".*Old display item:.*1,1 1x1"
+#endif
+ );
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, MoreDrawing) {
+ // We don't detect under-invalidation in this case, and PaintController can
+ // also handle the case gracefully.
+ FakeDisplayItemClient first("first");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ GetPaintController().CommitNewDisplayItems();
+ }
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, LessDrawing) {
+ // We don't detect under-invalidation in this case, and PaintController can
+ // also handle the case gracefully.
+ FakeDisplayItemClient first("first");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ GetPaintController().CommitNewDisplayItems();
+ }
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawingInSubsequence) {
+ auto test = [&]() {
+ FakeDisplayItemClient first("first");
+ GraphicsContext context(GetPaintController());
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, first);
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, first));
+ SubsequenceRecorder r(context, first);
+ DrawRect(context, first, kBackgroundType, IntRect(2, 2, 1, 1));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+ };
+
+ EXPECT_DEATH(test(),
+ "In cached subsequence for .*first.*\n"
+ ".*Under-invalidation: display item changed\n"
+#if DCHECK_IS_ON()
+ ".*New display item:.*2,2 1x1.*\n"
+ ".*Old display item:.*1,1 1x1"
+#endif
+ );
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, MoreDrawingInSubsequence) {
+ auto test = [&]() {
+ FakeDisplayItemClient first("first");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, first);
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, first));
+ SubsequenceRecorder r(context, first);
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 1, 1));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+ };
+
+ EXPECT_DEATH(test(),
+ "In cached subsequence for .*first.*\n"
+ ".*Under-invalidation: extra display item\n"
+#if DCHECK_IS_ON()
+ ".*New display item:.*1,1 3x3"
+#endif
+ );
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, LessDrawingInSubsequence) {
+ auto test = [&]() {
+ FakeDisplayItemClient first("first");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, first);
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 3, 3));
+ DrawRect(context, first, kForegroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, first));
+ SubsequenceRecorder r(context, first);
+ DrawRect(context, first, kBackgroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+ };
+
+ EXPECT_DEATH(test(),
+ "In cached subsequence for .*first.*\n"
+ ".*Under-invalidation: chunk changed");
+}
+
+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
+ // test cases.
+ FakeDisplayItemClient container("container");
+ FakeDisplayItemClient content("content");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, container);
+ DrawRect(context, content, kBackgroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ content.Invalidate();
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ // Leave container not invalidated.
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container));
+ SubsequenceRecorder r(context, container);
+ DrawRect(context, content, kBackgroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, SubsequenceBecomesEmpty) {
+ auto test = [&]() {
+ FakeDisplayItemClient target("target");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, target);
+ DrawRect(context, target, kBackgroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, target));
+ SubsequenceRecorder r(context, target);
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+ };
+
+ EXPECT_DEATH(test(),
+ "In cached subsequence for .*target.*\n"
+ ".*Under-invalidation: new subsequence wrong length");
+}
+
+TEST_F(PaintControllerUnderInvalidationTest, SkipCacheInSubsequence) {
+ FakeDisplayItemClient container("container");
+ FakeDisplayItemClient content("content");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, container);
+ {
+ DisplayItemCacheSkipper cache_skipper(context);
+ DrawRect(context, content, kBackgroundType, IntRect(1, 1, 3, 3));
+ }
+ DrawRect(context, content, kForegroundType, IntRect(2, 2, 4, 4));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container));
+ SubsequenceRecorder r(context, container);
+ {
+ DisplayItemCacheSkipper cache_skipper(context);
+ DrawRect(context, content, kBackgroundType, IntRect(2, 2, 4, 4));
+ }
+ DrawRect(context, content, kForegroundType, IntRect(2, 2, 4, 4));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+}
+
+TEST_F(PaintControllerUnderInvalidationTest,
+ EmptySubsequenceInCachedSubsequence) {
+ FakeDisplayItemClient container("container");
+ FakeDisplayItemClient content("content");
+ GraphicsContext context(GetPaintController());
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, container);
+ DrawRect(context, container, kBackgroundType, IntRect(1, 1, 3, 3));
+ { SubsequenceRecorder r1(context, content); }
+ DrawRect(context, container, kForegroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+
+ {
+ PaintController::CycleScope cycle_scope(GetPaintController());
+ InitRootChunk();
+ {
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, container));
+ SubsequenceRecorder r(context, container);
+ DrawRect(context, container, kBackgroundType, IntRect(1, 1, 3, 3));
+ EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+ context, content));
+ { SubsequenceRecorder r1(context, content); }
+ DrawRect(context, container, kForegroundType, IntRect(1, 1, 3, 3));
+ }
+ GetPaintController().CommitNewDisplayItems();
+ }
+}
+
+#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
+
+} // 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 d4964cf57eb..7ef128f3130 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
@@ -8,6 +8,43 @@
namespace blink {
+namespace {
+
+bool HasCompositedTransformToAncestor(
+ const TransformPaintPropertyNode& node,
+ const TransformPaintPropertyNode& ancestor) {
+ for (const auto* n = &node; n != &ancestor; n = n->UnaliasedParent()) {
+ if (n->HasDirectCompositingReasons())
+ return true;
+ }
+ return false;
+}
+
+// Returns the lowest common ancestor if there is no composited transform
+// between the two transforms.
+const TransformPaintPropertyNode* NonCompositedLowestCommonAncestor(
+ const TransformPaintPropertyNode& transform1,
+ const TransformPaintPropertyNode& transform2) {
+ const auto& lca = transform1.LowestCommonAncestor(transform2).Unalias();
+ if (HasCompositedTransformToAncestor(transform1, lca) ||
+ HasCompositedTransformToAncestor(transform2, lca))
+ return nullptr;
+ return &lca;
+}
+
+bool ClipChainHasCompositedTransformTo(
+ const ClipPaintPropertyNode& node,
+ const ClipPaintPropertyNode& ancestor,
+ const TransformPaintPropertyNode& transform) {
+ for (const auto* n = &node; n != &ancestor; n = n->UnaliasedParent()) {
+ if (!NonCompositedLowestCommonAncestor(n->LocalTransformSpace().Unalias(),
+ transform))
+ return true;
+ }
+ return false;
+}
+} // namespace
+
const PropertyTreeState& PropertyTreeState::Root() {
DEFINE_STATIC_LOCAL(
const PropertyTreeState, root,
@@ -16,9 +53,42 @@ const PropertyTreeState& PropertyTreeState::Root() {
return root;
}
-PropertyTreeState PropertyTreeStateOrAlias::Unalias() const {
- return PropertyTreeState(Transform().Unalias(), Clip().Unalias(),
- Effect().Unalias());
+bool PropertyTreeState::Changed(PaintPropertyChangeType change,
+ const PropertyTreeState& relative_to) const {
+ return Transform().Changed(change, relative_to.Transform()) ||
+ Clip().Changed(change, relative_to, &Transform()) ||
+ Effect().Changed(change, relative_to, &Transform());
+}
+
+absl::optional<PropertyTreeState> PropertyTreeState::CanUpcastWith(
+ const PropertyTreeState& guest) const {
+ // A number of criteria need to be met:
+ // 1. The guest effect must be a descendant of the home effect. However this
+ // check is enforced by the layerization recursion. Here we assume the guest
+ // has already been upcasted to the same effect.
+ // 2. The guest transform and the home transform have compatible backface
+ // visibility.
+ // 3. The guest transform space must be within compositing boundary of the
+ // home transform space.
+ // 4. The local space of each clip and effect node on the ancestor chain
+ // must be within compositing boundary of the home transform space.
+ DCHECK_EQ(&Effect(), &guest.Effect());
+
+ if (Transform().IsBackfaceHidden() != guest.Transform().IsBackfaceHidden())
+ return absl::nullopt;
+
+ auto* upcast_transform =
+ NonCompositedLowestCommonAncestor(Transform(), guest.Transform());
+ if (!upcast_transform)
+ return absl::nullopt;
+
+ const auto& clip_lca = Clip().LowestCommonAncestor(guest.Clip()).Unalias();
+ if (ClipChainHasCompositedTransformTo(Clip(), clip_lca, *upcast_transform) ||
+ ClipChainHasCompositedTransformTo(guest.Clip(), clip_lca,
+ *upcast_transform))
+ return absl::nullopt;
+
+ return PropertyTreeState(*upcast_transform, clip_lca, Effect());
}
String PropertyTreeStateOrAlias::ToString() const {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
index 54f1286ce6d..c0c327ab197 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
@@ -139,11 +139,31 @@ class PLATFORM_EXPORT PropertyTreeState : public PropertyTreeStateOrAlias {
PropertyTreeStateOrAlias::SetEffect(node);
}
+ // Returns true if any property tree state change is >= |change| relative to
+ // |relative_to|. Note that this is O(|nodes|).
+ bool Changed(PaintPropertyChangeType change,
+ const PropertyTreeState& relative_to) const;
+ bool ChangedToRoot(PaintPropertyChangeType change) const {
+ return Changed(change, Root());
+ }
+
+ // Determines whether drawings based on the 'guest' state can be painted into
+ // a layer with the 'home' state, and if yes, returns the common ancestor
+ // state to which both layer will be upcasted.
+ absl::optional<PropertyTreeState> CanUpcastWith(
+ const PropertyTreeState& guest) const;
+
private:
// For Uninitialized();
PropertyTreeState() = default;
};
+PLATFORM_EXPORT inline PropertyTreeState PropertyTreeStateOrAlias::Unalias()
+ const {
+ return PropertyTreeState(Transform().Unalias(), Clip().Unalias(),
+ Effect().Unalias());
+}
+
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&,
const PropertyTreeStateOrAlias&);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
index c92250476a6..f1f76a37db4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
@@ -59,6 +59,9 @@ const PaintChunk& RasterInvalidator::GetOldChunk(wtf_size_t index) const {
wtf_size_t RasterInvalidator::MatchNewChunkToOldChunk(
const PaintChunk& new_chunk,
wtf_size_t old_index) const {
+ if (!new_chunk.is_cacheable)
+ return kNotFound;
+
for (wtf_size_t i = old_index; i < old_paint_chunks_info_.size(); i++) {
if (new_chunk.Matches(GetOldChunk(i)))
return i;
@@ -86,11 +89,14 @@ static bool ApproximatelyEqual(const SkMatrix& a, const SkMatrix& b) {
}
PaintInvalidationReason RasterInvalidator::ChunkPropertiesChanged(
- const RefCountedPropertyTreeState& new_chunk_state,
- const RefCountedPropertyTreeState& old_chunk_state,
+ const PaintChunk& new_chunk,
+ const PaintChunk& old_chunk,
const PaintChunkInfo& new_chunk_info,
const PaintChunkInfo& old_chunk_info,
const PropertyTreeState& layer_state) const {
+ if (new_chunk.effectively_invisible != old_chunk.effectively_invisible)
+ return PaintInvalidationReason::kPaintProperty;
+
// 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.
@@ -102,11 +108,21 @@ PaintInvalidationReason RasterInvalidator::ChunkPropertiesChanged(
// 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() ||
+ const auto& new_chunk_state = new_chunk.properties;
+ bool clip_node_is_different = false;
+ bool effect_node_is_different = false;
+ if (!new_chunk.is_moved_from_cached_subsequence) {
+ clip_node_is_different =
+ &new_chunk_state.Clip() != &old_chunk.properties.Clip();
+ effect_node_is_different =
+ &new_chunk_state.Effect() != &old_chunk.properties.Effect();
+ }
+ if (effect_node_is_different ||
new_chunk_state.Effect().Changed(
PaintPropertyChangeType::kChangedOnlySimpleValues, layer_state,
- &new_chunk_state.Transform()))
+ &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() &&
@@ -137,7 +153,7 @@ PaintInvalidationReason RasterInvalidator::ChunkPropertiesChanged(
// 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() ||
+ if (clip_node_is_different ||
new_chunk_state.Clip().Changed(
PaintPropertyChangeType::kChangedOnlySimpleValues, layer_state,
&new_chunk_state.Transform()))
@@ -146,13 +162,19 @@ PaintInvalidationReason RasterInvalidator::ChunkPropertiesChanged(
return PaintInvalidationReason::kNone;
}
-// Skip the chunk for raster invalidation if it contains only one non-drawing
-// display item. We could also skip chunks containing all non-drawing display
-// items, but single non-drawing item is more common, e.g. scroll hit test.
static bool ShouldSkipForRasterInvalidation(
const PaintChunkIterator& chunk_it) {
- return chunk_it->size() == 1 &&
- !chunk_it.DisplayItems().begin()->DrawsContent();
+ // Skip the chunk if it contains only one non-drawing display item. We could
+ // also skip chunks containing all non-drawing display items, but single
+ // non-drawing item is more common, e.g. scroll hit test.
+ if (chunk_it->size() == 1 && !chunk_it.DisplayItems().begin()->DrawsContent())
+ return true;
+
+ // Foreign layers take care of raster invalidation by themselves.
+ if (DisplayItem::IsForeignLayerType(chunk_it->id.type))
+ return true;
+
+ return false;
}
// Generates raster invalidations by checking changes (appearing, disappearing,
@@ -169,8 +191,9 @@ void RasterInvalidator::GenerateRasterInvalidations(
RasterInvalidationFunction function,
const PaintChunkSubset& new_chunks,
const PropertyTreeState& layer_state,
+ bool layer_offset_changed,
Vector<PaintChunkInfo>& new_chunks_info) {
- ChunkToLayerMapper mapper(layer_state, layer_bounds_.OffsetFromOrigin());
+ ChunkToLayerMapper mapper(layer_state, layer_offset_);
Vector<bool> old_chunks_matched;
old_chunks_matched.resize(old_paint_chunks_info_.size());
wtf_size_t old_index = 0;
@@ -180,26 +203,16 @@ void RasterInvalidator::GenerateRasterInvalidations(
continue;
const auto& new_chunk = *it;
- mapper.SwitchToChunk(new_chunk);
- auto& new_chunk_info = new_chunks_info.emplace_back(*this, mapper, it);
-
- // Foreign layers take care of raster invalidation by themselves.
- if (DisplayItem::IsForeignLayerType(new_chunk.id.type))
- continue;
-
- if (!new_chunk.is_cacheable) {
- AddRasterInvalidation(
- function, new_chunk_info.bounds_in_layer, new_chunk.id.client,
- PaintInvalidationReason::kChunkUncacheable, kClientIsNew);
- continue;
- }
-
auto matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index);
if (matched_old_index == kNotFound) {
// The new chunk doesn't match any old chunk.
+ mapper.SwitchToChunk(new_chunk);
+ auto& new_chunk_info = new_chunks_info.emplace_back(*this, mapper, it);
AddRasterInvalidation(
function, new_chunk_info.bounds_in_layer, new_chunk.id.client,
- PaintInvalidationReason::kChunkAppeared, kClientIsNew);
+ new_chunk.is_cacheable ? PaintInvalidationReason::kChunkAppeared
+ : PaintInvalidationReason::kChunkUncacheable,
+ kClientIsNew);
continue;
}
@@ -212,46 +225,60 @@ void RasterInvalidator::GenerateRasterInvalidations(
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(function, old_chunk_info.bounds_in_layer,
- new_chunk.id.client, reason, kClientIsNew);
- if (old_chunk_info.bounds_in_layer != new_chunk_info.bounds_in_layer) {
- AddRasterInvalidation(function, 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.
+ auto reason = PaintInvalidationReason::kNone;
+ if (matched_old_index < max_matched_old_index)
+ reason = PaintInvalidationReason::kChunkReordered;
+
+ // No need to invalidate if the chunk is moved from cached subsequence and
+ // its paint properties didn't change relative to the layer.
+ if (!layer_offset_changed && reason == PaintInvalidationReason::kNone &&
+ new_chunk.is_moved_from_cached_subsequence &&
+ !new_chunk.properties.GetPropertyTreeState().Unalias().Changed(
+ PaintPropertyChangeType::kChangedOnlySimpleValues, layer_state)) {
+ new_chunks_info.emplace_back(old_chunk_info, it);
} 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(function, old_chunk_info, new_chunk_info,
- new_chunk.id.client);
+ mapper.SwitchToChunk(new_chunk);
+ auto& new_chunk_info = new_chunks_info.emplace_back(*this, mapper, it);
+
+ if (reason == PaintInvalidationReason::kNone) {
+ reason = ChunkPropertiesChanged(new_chunk, old_chunk, new_chunk_info,
+ old_chunk_info, layer_state);
}
- if (&new_chunks.GetPaintArtifact() != old_paint_artifact_ &&
- !new_chunk.is_moved_from_cached_subsequence) {
- DisplayItemRasterInvalidator(
- *this, function,
- old_paint_artifact_->DisplayItemsInChunk(
- old_chunk_info.index_in_paint_artifact),
- it.DisplayItems(), mapper)
- .Generate();
+ 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(function, old_chunk_info.bounds_in_layer,
+ new_chunk.id.client, reason, kClientIsNew);
+ if (old_chunk_info.bounds_in_layer != new_chunk_info.bounds_in_layer) {
+ AddRasterInvalidation(function, 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(function, old_chunk_info, new_chunk_info,
+ new_chunk.id.client);
+ }
+
+ if (&new_chunks.GetPaintArtifact() != old_paint_artifact_ &&
+ !new_chunk.is_moved_from_cached_subsequence) {
+ DisplayItemRasterInvalidator(
+ *this, function,
+ old_paint_artifact_->DisplayItemsInChunk(
+ old_chunk_info.index_in_paint_artifact),
+ it.DisplayItems(), mapper)
+ .Generate();
+ }
}
}
@@ -293,9 +320,11 @@ void RasterInvalidator::TrackRasterInvalidation(const IntRect& rect,
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();
+ String debug_name =
+ old_or_new == kClientIsOld
+ ? tracking_info_->old_client_debug_names.DeprecatedAtOrEmptyValue(
+ &client)
+ : client.DebugName();
tracking_info_->tracking.AddInvalidation(&client, debug_name, rect, reason);
}
@@ -308,13 +337,16 @@ RasterInvalidationTracking& RasterInvalidator::EnsureTracking() {
void RasterInvalidator::Generate(
RasterInvalidationFunction raster_invalidation_function,
const PaintChunkSubset& new_chunks,
- const gfx::Rect& layer_bounds,
+ const FloatPoint& layer_offset,
+ const IntSize& layer_bounds,
const PropertyTreeState& layer_state,
const DisplayItemClient* layer_client) {
if (RasterInvalidationTracking::ShouldAlwaysTrack())
EnsureTracking();
+ bool layer_offset_changed = layer_offset_ != layer_offset;
bool layer_bounds_was_empty = layer_bounds_.IsEmpty();
+ layer_offset_ = layer_offset;
layer_bounds_ = layer_bounds;
Vector<PaintChunkInfo> new_chunks_info;
@@ -323,7 +355,7 @@ void RasterInvalidator::Generate(
if (layer_bounds_was_empty || layer_bounds_.IsEmpty()) {
// Fast path if either the old bounds or the new bounds is empty. We still
// need to update new_chunks_info for the next cycle.
- ChunkToLayerMapper mapper(layer_state, layer_bounds.OffsetFromOrigin());
+ ChunkToLayerMapper mapper(layer_state, layer_offset);
for (auto it = new_chunks.begin(); it != new_chunks.end(); ++it) {
if (ShouldSkipForRasterInvalidation(it))
continue;
@@ -333,14 +365,14 @@ void RasterInvalidator::Generate(
if (!layer_bounds.IsEmpty() && !new_chunks.IsEmpty()) {
AddRasterInvalidation(
- raster_invalidation_function,
- IntRect(IntPoint(), IntSize(layer_bounds.size())),
+ raster_invalidation_function, IntRect(IntPoint(), layer_bounds),
layer_client ? *layer_client : new_chunks.begin()->id.client,
PaintInvalidationReason::kFullLayer, kClientIsNew);
}
} else {
GenerateRasterInvalidations(raster_invalidation_function, new_chunks,
- layer_state, new_chunks_info);
+ layer_state, layer_offset_changed,
+ new_chunks_info);
}
old_paint_chunks_info_ = std::move(new_chunks_info);
@@ -363,7 +395,8 @@ size_t RasterInvalidator::ApproximateUnsharedMemoryUsage() const {
void RasterInvalidator::ClearOldStates() {
old_paint_artifact_ = nullptr;
old_paint_chunks_info_.clear();
- layer_bounds_ = gfx::Rect();
+ layer_offset_ = FloatPoint();
+ layer_bounds_ = IntSize();
}
} // 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
index 632fc176375..bd6ccfb593c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
@@ -41,7 +41,8 @@ class PLATFORM_EXPORT RasterInvalidator {
// paint artifact.
void Generate(RasterInvalidationFunction,
const PaintChunkSubset&,
- const gfx::Rect& layer_bounds,
+ const FloatPoint& layer_offset,
+ const IntSize& layer_bounds,
const PropertyTreeState& layer_state,
const DisplayItemClient* layer_client = nullptr);
@@ -52,7 +53,7 @@ class PLATFORM_EXPORT RasterInvalidator {
// PaintArtifactCompositor and pass it in Generate().
void SetOldPaintArtifact(scoped_refptr<const PaintArtifact>);
- const gfx::Rect& LayerBounds() const { return layer_bounds_; }
+ const IntSize& LayerBounds() const { return layer_bounds_; }
size_t ApproximateUnsharedMemoryUsage() const;
@@ -78,6 +79,20 @@ class PLATFORM_EXPORT RasterInvalidator {
chunk_to_layer_transform(mapper.Transform()) {
}
+ PaintChunkInfo(const PaintChunkInfo& old_chunk_info,
+ const PaintChunkIterator& chunk_it)
+ : index_in_paint_artifact(chunk_it.IndexInPaintArtifact()),
+#if DCHECK_IS_ON()
+ id(chunk_it->id),
+#endif
+ bounds_in_layer(old_chunk_info.bounds_in_layer),
+ chunk_to_layer_clip(old_chunk_info.chunk_to_layer_clip),
+ chunk_to_layer_transform(old_chunk_info.chunk_to_layer_transform) {
+#if DCHECK_IS_ON()
+ DCHECK_EQ(id, old_chunk_info.id);
+#endif
+ }
+
// 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.
@@ -95,6 +110,7 @@ class PLATFORM_EXPORT RasterInvalidator {
void GenerateRasterInvalidations(RasterInvalidationFunction,
const PaintChunkSubset&,
const PropertyTreeState& layer_state,
+ bool layer_offset_changed,
Vector<PaintChunkInfo>& new_chunks_info);
ALWAYS_INLINE const PaintChunk& GetOldChunk(wtf_size_t index) const;
@@ -128,8 +144,8 @@ class PLATFORM_EXPORT RasterInvalidator {
ClientIsOldOrNew);
ALWAYS_INLINE PaintInvalidationReason
- ChunkPropertiesChanged(const RefCountedPropertyTreeState& new_chunk_state,
- const RefCountedPropertyTreeState& old_chunk_state,
+ ChunkPropertiesChanged(const PaintChunk& new_chunk,
+ const PaintChunk& old_chunk,
const PaintChunkInfo& new_chunk_info,
const PaintChunkInfo& old_chunk_info,
const PropertyTreeState& layer_state) const;
@@ -138,10 +154,11 @@ class PLATFORM_EXPORT RasterInvalidator {
template <typename Rect>
Rect ClipByLayerBounds(const Rect& r) const {
return Intersection(
- r, Rect(0, 0, layer_bounds_.width(), layer_bounds_.height()));
+ r, Rect(0, 0, layer_bounds_.Width(), layer_bounds_.Height()));
}
- gfx::Rect layer_bounds_;
+ FloatPoint layer_offset_;
+ IntSize layer_bounds_;
Vector<PaintChunkInfo> old_paint_chunks_info_;
scoped_refptr<const PaintArtifact> old_paint_artifact_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
index 86dffaabed6..583c26e1baf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
@@ -18,7 +18,8 @@ using testing::ElementsAre;
namespace blink {
-static const IntRect kDefaultLayerBounds(-9999, -7777, 18888, 16666);
+static constexpr FloatPoint kDefaultLayerOffset(-9999, -7777);
+static constexpr IntSize kDefaultLayerBounds(18888, 16666);
class RasterInvalidatorTest : public testing::Test,
public PaintTestConfigurations {
@@ -57,12 +58,13 @@ INSTANTIATE_PAINT_TEST_SUITE_P(RasterInvalidatorTest);
using MapFunction = base::RepeatingCallback<void(IntRect&)>;
static IntRect ChunkRectToLayer(const IntRect& rect,
- const IntPoint& layer_offset,
+ const FloatPoint& layer_offset,
const MapFunction& mapper = base::DoNothing()) {
auto r = rect;
mapper.Run(r);
- r.MoveBy(layer_offset);
- return r;
+ FloatRect float_rect(r);
+ float_rect.MoveBy(layer_offset);
+ return EnclosingIntRect(float_rect);
}
static bool CheckChunkInvalidation(
@@ -70,7 +72,7 @@ static bool CheckChunkInvalidation(
const PaintChunkSubset& chunks,
wtf_size_t index,
PaintInvalidationReason reason,
- const IntPoint& layer_offset,
+ const FloatPoint& layer_offset,
const absl::optional<IntRect>& chunk_rect = absl::nullopt,
const MapFunction& mapper = base::DoNothing()) {
const auto& chunk = *(chunks.begin() + index);
@@ -86,26 +88,26 @@ MATCHER_P5(ChunkInvalidation, chunks, index, reason, layer_offset, mapper, "") {
MATCHER_P3(ChunkInvalidation, chunks, index, reason, "") {
return CheckChunkInvalidation(arg, chunks, index, reason,
- -kDefaultLayerBounds.Location());
+ -kDefaultLayerOffset);
}
MATCHER_P3(IncrementalInvalidation, chunks, index, chunk_rect, "") {
return CheckChunkInvalidation(arg, chunks, index,
PaintInvalidationReason::kIncremental,
- -kDefaultLayerBounds.Location(), chunk_rect);
+ -kDefaultLayerOffset, chunk_rect);
}
TEST_P(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
PaintChunkSubset chunks(TestPaintArtifact().Chunk(0).Build());
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
const auto& client = chunks.begin()->id.client;
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(RasterInvalidationInfo{
&client, client.DebugName(),
- IntRect(IntPoint(), kDefaultLayerBounds.Size()),
+ IntRect(IntPoint(), IntSize(kDefaultLayerBounds)),
PaintInvalidationReason::kFullLayer}));
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(false);
@@ -114,35 +116,60 @@ TEST_P(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
TEST_P(RasterInvalidatorTest, LayerBounds) {
PaintChunkSubset chunks(TestPaintArtifact().Chunk(0).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
// No raster invalidations needed if layer origin doesn't change.
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
- auto new_layer_bounds = kDefaultLayerBounds;
- new_layer_bounds.Move(66, 77);
- invalidator_.Generate(base::DoNothing(), chunks, new_layer_bounds,
- DefaultPropertyTreeState());
+ auto new_layer_offset = kDefaultLayerOffset;
+ new_layer_offset.MoveBy(FloatPoint(66, 77));
+ invalidator_.Generate(base::DoNothing(), chunks, new_layer_offset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
// Change of layer origin causes change of chunk0's transform to layer.
EXPECT_THAT(
TrackedRasterInvalidations(),
ElementsAre(
ChunkInvalidation(chunks, 0, PaintInvalidationReason::kPaintProperty),
ChunkInvalidation(chunks, 0, PaintInvalidationReason::kPaintProperty,
- -new_layer_bounds.Location(), base::DoNothing())));
+ -new_layer_offset, base::DoNothing())));
+ FinishCycle(chunks);
+}
+
+TEST_P(RasterInvalidatorTest, LayerOffsetChangeWithCachedSubsequence) {
+ PaintChunkSubset chunks(TestPaintArtifact().Chunk(0).Build());
+
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
+ FinishCycle(chunks);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ auto new_layer_offset = kDefaultLayerOffset;
+ new_layer_offset.MoveBy(FloatPoint(66, 77));
+ PaintChunkSubset new_chunks(
+ TestPaintArtifact().Chunk(0).IsMovedFromCachedSubsequence().Build());
+
+ invalidator_.Generate(base::DoNothing(), new_chunks, new_layer_offset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
+ // Change of layer origin causes change of chunk0's transform to layer.
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(
+ ChunkInvalidation(chunks, 0, PaintInvalidationReason::kPaintProperty),
+ ChunkInvalidation(chunks, 0, PaintInvalidationReason::kPaintProperty,
+ -new_layer_offset, base::DoNothing())));
FinishCycle(chunks);
}
TEST_P(RasterInvalidatorTest, ReorderChunks) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
// Swap chunk 1 and 2.
@@ -153,8 +180,8 @@ TEST_P(RasterInvalidatorTest, ReorderChunks) {
.Chunk(1)
.Bounds(IntRect(11, 22, 33, 44))
.Build());
- invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
// Invalidated new chunk 2's old (as chunks[{0, 1]) and new
// (as new_chunks[{0, 2]) bounds.
EXPECT_THAT(
@@ -169,22 +196,24 @@ TEST_P(RasterInvalidatorTest, ReorderChunks) {
TEST_P(RasterInvalidatorTest, ReorderChunkSubsequences) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Chunk(3).Chunk(4).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
- // Swap chunk (1,2) and (3,4).
+ // Swap chunk (1,2) (changed) and (3,4) (moved from cached subsequence).
invalidator_.SetTracksRasterInvalidations(true);
PaintChunkSubset new_chunks(TestPaintArtifact()
.Chunk(0)
.Chunk(3)
+ .IsMovedFromCachedSubsequence()
.Chunk(4)
+ .IsMovedFromCachedSubsequence()
.Chunk(1)
.Bounds(IntRect(11, 22, 33, 44))
.Chunk(2)
.Build());
- invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
// Invalidated new chunk 3's old (as chunks[{0, 1] and new
// (as new_chunks[{0, 3]) bounds.
// Invalidated new chunk 4's new bounds. Didn't invalidate old bounds because
@@ -203,16 +232,16 @@ TEST_P(RasterInvalidatorTest, ReorderChunkSubsequences) {
TEST_P(RasterInvalidatorTest, ChunkAppearAndDisappear) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
// Chunk 1 and 2 disappeared, 3 and 4 appeared.
invalidator_.SetTracksRasterInvalidations(true);
PaintChunkSubset new_chunks(
TestPaintArtifact().Chunk(0).Chunk(3).Chunk(4).Build());
- invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
EXPECT_THAT(
TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(new_chunks, 1,
@@ -235,8 +264,8 @@ TEST_P(RasterInvalidatorTest, InvalidateDrawableBounds) {
.Bounds(bounds)
.DrawableBounds(drawable_bounds)
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
@@ -246,8 +275,8 @@ TEST_P(RasterInvalidatorTest, InvalidateDrawableBounds) {
.Bounds(bounds)
.DrawableBounds(drawable_bounds)
.Build());
- invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
// ChunkInvalidation uses the drawable_bounds. We expect raster invalidations
// based on drawable_bounds instead of bounds.
EXPECT_THAT(
@@ -261,15 +290,15 @@ TEST_P(RasterInvalidatorTest, InvalidateDrawableBounds) {
TEST_P(RasterInvalidatorTest, ChunkAppearAtEnd) {
PaintChunkSubset chunks(TestPaintArtifact().Chunk(0).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
PaintChunkSubset new_chunks(
TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build());
- invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
EXPECT_THAT(
TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(new_chunks, 1,
@@ -283,15 +312,15 @@ TEST_P(RasterInvalidatorTest, UncacheableChunks) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Chunk(1).Uncacheable().Chunk(2).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
PaintChunkSubset new_chunks(
TestPaintArtifact().Chunk(0).Chunk(2).Chunk(1).Uncacheable().Build());
- invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerBounds,
- DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), new_chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, DefaultPropertyTreeState());
EXPECT_THAT(
TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(new_chunks, 2,
@@ -320,8 +349,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
.Properties(chunk_state)
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change both clip0 and clip2.
@@ -334,8 +363,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
ClipPaintPropertyNode::State{&clip2->LocalTransformSpace(),
new_clip_rect});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
// Property change in the layer state should not trigger raster invalidation.
// |clip2| change should trigger raster invalidation.
EXPECT_THAT(TrackedRasterInvalidations(),
@@ -355,8 +384,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
.Build());
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(base::DoNothing(), new_chunks1, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), new_chunks1, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(
new_chunks1, 1, PaintInvalidationReason::kPaintProperty)));
@@ -380,8 +409,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
.Bounds(EnclosingIntRect(clip_rect.Rect()))
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change clip1 to bigger, which is still bound by clip0, resulting no actual
@@ -392,8 +421,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
ClipPaintPropertyNode::State{&clip1->LocalTransformSpace(),
new_clip_rect1});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
@@ -403,8 +432,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
ClipPaintPropertyNode::State{&clip1->LocalTransformSpace(),
new_clip_rect2});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
// |clip1| change should trigger incremental raster invalidation.
EXPECT_THAT(
TrackedRasterInvalidations(),
@@ -423,8 +452,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
new_clip_rect3});
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
// |clip1| change should trigger incremental raster invalidation.
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(IncrementalInvalidation(
@@ -433,6 +462,38 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
FinishCycle(chunks);
}
+TEST_P(RasterInvalidatorTest, ClipChangeOnCachedSubsequence) {
+ FloatRoundedRect clip_rect(-1000, -1000, 2000, 2000);
+ auto c1 = CreateClip(c0(), t0(), clip_rect);
+
+ PropertyTreeState layer_state = PropertyTreeState::Root();
+ PaintChunkSubset chunks(TestPaintArtifact()
+ .Chunk(0)
+ .Properties(t0(), *c1, e0())
+ .Bounds(EnclosingIntRect(clip_rect.Rect()))
+ .IsMovedFromCachedSubsequence()
+ .Build());
+
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
+ FinishCycle(chunks);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ FloatRoundedRect new_clip_rect(-500, -500, 1000, 1000);
+ c1->Update(*c1->Parent(), ClipPaintPropertyNode::State{&t0(), new_clip_rect});
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(
+ IncrementalInvalidation(chunks, 0, IntRect(-1000, -1000, 2000, 500)),
+ IncrementalInvalidation(chunks, 0, IntRect(-1000, -500, 500, 1000)),
+ IncrementalInvalidation(chunks, 0, IntRect(500, -500, 500, 1000)),
+ IncrementalInvalidation(chunks, 0, IntRect(-1000, 500, 2000, 500))));
+ invalidator_.SetTracksRasterInvalidations(false);
+ FinishCycle(chunks);
+}
+
// Tests the path detecting change of PaintChunkInfo::chunk_to_layer_clip.
// The chunk bounds is bigger than the clip because of the outset for raster
// effects, so incremental invalidation is not suitable.
@@ -449,22 +510,21 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeWithOutsetForRasterEffects) {
.SetRasterEffectOutset(RasterEffectOutset::kWholePixel)
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
FloatRoundedRect new_clip_rect(-2000, -2000, 4000, 4000);
clip->Update(c0(), ClipPaintPropertyNode::State{&t0(), new_clip_rect});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
auto mapper = [](IntRect& r) { r.Inflate(1); };
- EXPECT_THAT(
- TrackedRasterInvalidations(),
- ElementsAre(ChunkInvalidation(
- chunks, 0, PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(), base::BindRepeating(mapper))));
+ EXPECT_THAT(TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(
+ chunks, 0, PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerOffset, base::BindRepeating(mapper))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(chunks);
}
@@ -482,8 +542,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(*t2, *c1, e0()).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change both t1 and t2 but keep t1*t2 unchanged, to test change of
@@ -492,8 +552,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(
chunks, 0, PaintInvalidationReason::kPaintProperty)));
@@ -517,8 +577,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(*t2, *c1, e0()).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change both t1 and t2 but keep t1*t2 unchanged.
@@ -526,8 +586,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
}
@@ -545,8 +605,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
.Properties(*transform1, c0(), e0())
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change layer_transform should not cause raster invalidation in the layer.
@@ -555,8 +615,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
*layer_transform->Parent(),
TransformPaintPropertyNode::State{TransformationMatrix().Scale(10)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
@@ -569,8 +629,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
transform0->Update(*new_layer_transform, TransformPaintPropertyNode::State{
transform0->Translation2D()});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
@@ -580,8 +640,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
transform0->Update(layer_state.Transform(), TransformPaintPropertyNode::State{
transform0->Translation2D()});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
@@ -595,18 +655,17 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
TransformPaintPropertyNode::State{
transform1->Translation2D() + FloatSize(-20, -30)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
auto mapper0 = [](IntRect& r) { r.Move(10, 20); };
auto mapper1 = [](IntRect& r) { r.Move(30, 50); };
EXPECT_THAT(
TrackedRasterInvalidations(),
ElementsAre(
ChunkInvalidation(chunks, 0, PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(),
- base::BindRepeating(mapper0)),
+ -kDefaultLayerOffset, base::BindRepeating(mapper0)),
ChunkInvalidation(chunks, 0, PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(),
+ -kDefaultLayerOffset,
base::BindRepeating(mapper1))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(chunks);
@@ -622,8 +681,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
.Properties(*chunk_transform, c0(), e0())
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change chunk_transform by tiny difference, which should be ignored.
@@ -635,8 +694,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
.Scale(1.0000001)
.Rotate(0.0000001)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
@@ -650,8 +709,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
.Translate(0.0000001, -0.0000001)
.Scale(1.0000001)
.Rotate(0.0000001)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
invalidated = !TrackedRasterInvalidations().IsEmpty();
FinishCycle(chunks);
}
@@ -671,8 +730,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
.Bounds(chunk_bounds)
.Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Scale change from 1e-6 to 2e-6 should be treated as significant.
@@ -681,8 +740,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
layer_state.Transform(),
TransformPaintPropertyNode::State{TransformationMatrix().Scale(2e-6)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_FALSE(TrackedRasterInvalidations().IsEmpty());
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(chunks);
@@ -693,8 +752,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
TransformPaintPropertyNode::State{
TransformationMatrix().Scale(2e-6 + 1e-15)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(chunks);
@@ -711,8 +770,8 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(*t2, c0(), *e1).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change both t1 and t2 but keep t1*t2 unchanged, to test change of
@@ -721,14 +780,13 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
auto mapper = [](IntRect& r) { r.Inflate(60); };
- EXPECT_THAT(
- TrackedRasterInvalidations(),
- ElementsAre(ChunkInvalidation(
- chunks, 0, PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(), base::BindRepeating(mapper))));
+ EXPECT_THAT(TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(
+ chunks, 0, PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerOffset, base::BindRepeating(mapper))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(chunks);
}
@@ -748,8 +806,8 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(*t2, c0(), *e1).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
// Change both t1 and t2 but keep t1*t2 unchanged.
@@ -757,8 +815,8 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(chunks);
}
@@ -776,8 +834,8 @@ TEST_P(RasterInvalidatorTest, AliasEffectParentChanges) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(chunk_state).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
@@ -787,8 +845,8 @@ TEST_P(RasterInvalidatorTest, AliasEffectParentChanges) {
// We expect to get invalidations since the effect unaliased effect is
// actually different now.
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(
chunks, 0, PaintInvalidationReason::kPaintProperty)));
@@ -809,8 +867,8 @@ TEST_P(RasterInvalidatorTest, NestedAliasEffectParentChanges) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(chunk_state).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
@@ -821,8 +879,8 @@ TEST_P(RasterInvalidatorTest, NestedAliasEffectParentChanges) {
// We expect to get invalidations since the effect unaliased effect is
// actually different now.
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(
chunks, 0, PaintInvalidationReason::kPaintProperty)));
@@ -844,8 +902,8 @@ TEST_P(RasterInvalidatorTest, EffectWithAliasTransformWhoseParentChanges) {
PaintChunkSubset chunks(
TestPaintArtifact().Chunk(0).Properties(chunk_state).Build());
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
FinishCycle(chunks);
invalidator_.SetTracksRasterInvalidations(true);
@@ -855,8 +913,59 @@ TEST_P(RasterInvalidatorTest, EffectWithAliasTransformWhoseParentChanges) {
// We expect to get invalidations since the effect unaliased effect is
// actually different now.
- invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerBounds,
- layer_state);
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
+ EXPECT_THAT(TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(
+ chunks, 0, PaintInvalidationReason::kPaintProperty)));
+ FinishCycle(chunks);
+}
+
+TEST_P(RasterInvalidatorTest, EffectChangeSimple) {
+ PropertyTreeState layer_state = DefaultPropertyTreeState();
+ auto e1 = CreateOpacityEffect(e0(), t0(), &c0(), 0.5);
+ PropertyTreeState chunk_state(t0(), c0(), *e1);
+ PaintChunkSubset chunks(
+ TestPaintArtifact().Chunk(0).Properties(chunk_state).Build());
+
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
+ FinishCycle(chunks);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ EffectPaintPropertyNode::State state{&t0(), &c0()};
+ state.opacity = 0.9;
+ e1->Update(*e1->Parent(), std::move(state));
+
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
+ EXPECT_THAT(TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(
+ chunks, 0, PaintInvalidationReason::kPaintProperty)));
+ FinishCycle(chunks);
+}
+
+TEST_P(RasterInvalidatorTest, EffectChangeOnCachedSubsequence) {
+ PropertyTreeState layer_state = DefaultPropertyTreeState();
+ auto e1 = CreateOpacityEffect(e0(), t0(), &c0(), 0.5);
+ PropertyTreeState chunk_state(t0(), c0(), *e1);
+ PaintChunkSubset chunks(TestPaintArtifact()
+ .Chunk(0)
+ .Properties(chunk_state)
+ .IsMovedFromCachedSubsequence()
+ .Build());
+
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
+ FinishCycle(chunks);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ EffectPaintPropertyNode::State state{&t0(), &c0()};
+ state.opacity = 0.9;
+ e1->Update(*e1->Parent(), std::move(state));
+
+ invalidator_.Generate(base::DoNothing(), chunks, kDefaultLayerOffset,
+ kDefaultLayerBounds, layer_state);
EXPECT_THAT(TrackedRasterInvalidations(),
ElementsAre(ChunkInvalidation(
chunks, 0, PaintInvalidationReason::kPaintProperty)));
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 021cf196463..2d7b5f673e4 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,7 +5,6 @@
#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/allocator.h"
@@ -21,6 +20,9 @@ class ScopedDisplayItemFragment final {
original_fragment_(context.GetPaintController().CurrentFragment()) {
context.GetPaintController().SetCurrentFragment(fragment);
}
+ ScopedDisplayItemFragment(const ScopedDisplayItemFragment&) = delete;
+ ScopedDisplayItemFragment& operator=(const ScopedDisplayItemFragment&) =
+ delete;
~ScopedDisplayItemFragment() {
context_.GetPaintController().SetCurrentFragment(original_fragment_);
}
@@ -28,8 +30,6 @@ class ScopedDisplayItemFragment final {
private:
GraphicsContext& context_;
wtf_size_t original_fragment_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedDisplayItemFragment);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_effectively_invisible.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_effectively_invisible.h
new file mode 100644
index 00000000000..609a45c0353
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_effectively_invisible.h
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_EFFECTIVELY_INVISIBLE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_EFFECTIVELY_INVISIBLE_H_
+
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class ScopedEffectivelyInvisible final {
+ STACK_ALLOCATED();
+
+ public:
+ explicit ScopedEffectivelyInvisible(PaintController& paint_controller)
+ : paint_controller_(paint_controller),
+ previous_effectively_invisible_(
+ paint_controller.CurrentEffectivelyInvisible()) {
+ paint_controller.SetCurrentEffectivelyInvisible(true);
+ }
+ ScopedEffectivelyInvisible(const ScopedEffectivelyInvisible&) = delete;
+ ScopedEffectivelyInvisible& operator=(const ScopedEffectivelyInvisible&) =
+ delete;
+ ~ScopedEffectivelyInvisible() {
+ paint_controller_.SetCurrentEffectivelyInvisible(
+ previous_effectively_invisible_);
+ }
+
+ private:
+ PaintController& paint_controller_;
+ bool previous_effectively_invisible_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_EFFECTIVELY_INVISIBLE_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
index 606fec437c2..c9ad6137d79 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,7 +5,6 @@
#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 "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"
@@ -62,6 +61,10 @@ class ScopedPaintChunkProperties {
client,
type) {}
+ ScopedPaintChunkProperties(const ScopedPaintChunkProperties&) = delete;
+ ScopedPaintChunkProperties& operator=(const ScopedPaintChunkProperties&) =
+ delete;
+
~ScopedPaintChunkProperties() {
// We should not return to the previous id, because that may cause a new
// chunk to use the same id as that of the previous chunk before this
@@ -102,8 +105,6 @@ class ScopedPaintChunkProperties {
PaintController& paint_controller_;
PropertyTreeStateOrAlias previous_properties_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedPaintChunkProperties);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
index 82968401715..655c32b76d7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
@@ -23,10 +23,12 @@ ScrollbarDisplayItem::ScrollbarDisplayItem(
scoped_refptr<cc::Scrollbar> scrollbar,
const IntRect& visual_rect,
const TransformPaintPropertyNode* scroll_translation,
- CompositorElementId element_id)
+ CompositorElementId element_id,
+ PaintInvalidationReason paint_invalidation_reason)
: DisplayItem(client,
type,
visual_rect,
+ paint_invalidation_reason,
/*draws_content*/ true),
data_(new Data{std::move(scrollbar), scroll_translation, element_id}) {
DCHECK(IsScrollbar());
@@ -117,7 +119,7 @@ void ScrollbarDisplayItem::Record(
paint_controller.CreateAndAppend<ScrollbarDisplayItem>(
client, type, std::move(scrollbar), visual_rect, scroll_translation,
- element_id);
+ element_id, client.GetPaintInvalidationReason());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h
index 0bbf18a7b58..a5a4d7c50ca 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h
@@ -35,7 +35,9 @@ class PLATFORM_EXPORT ScrollbarDisplayItem final : public DisplayItem {
scoped_refptr<cc::Scrollbar>,
const IntRect& visual_rect,
const TransformPaintPropertyNode* scroll_translation,
- CompositorElementId element_id);
+ CompositorElementId element_id,
+ PaintInvalidationReason paint_invalidation_reason =
+ PaintInvalidationReason::kJustCreated);
const TransformPaintPropertyNode* ScrollTranslation() const {
DCHECK(!IsTombstone());
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 d85a143d3e6..9781d7e9cc1 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,7 +5,6 @@
#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"
@@ -36,22 +35,21 @@ class SubsequenceRecorder final {
}
SubsequenceRecorder(GraphicsContext& context, const DisplayItemClient& client)
- : paint_controller_(context.GetPaintController()), client_(client) {
- paint_controller_.BeginSubsequence(subsequence_index_, start_chunk_index_);
+ : paint_controller_(context.GetPaintController()) {
+ subsequence_index_ = paint_controller_.BeginSubsequence(client);
+ paint_controller_.MarkClientForValidation(client);
}
+ SubsequenceRecorder(const SubsequenceRecorder&) = delete;
+ SubsequenceRecorder& operator=(const SubsequenceRecorder&) = delete;
+
~SubsequenceRecorder() {
- paint_controller_.EndSubsequence(client_, subsequence_index_,
- start_chunk_index_);
+ paint_controller_.EndSubsequence(subsequence_index_);
}
private:
PaintController& paint_controller_;
- const DisplayItemClient& client_;
wtf_size_t subsequence_index_;
- wtf_size_t start_chunk_index_;
-
- DISALLOW_COPY_AND_ASSIGN(SubsequenceRecorder);
};
} // namespace blink
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 c85b65a2b93..bf844a83937 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
@@ -12,11 +12,9 @@ const TransformPaintPropertyNode& TransformPaintPropertyNode::Root() {
DEFINE_STATIC_REF(
TransformPaintPropertyNode, root,
base::AdoptRef(new TransformPaintPropertyNode(
- nullptr,
- State{
- FloatSize(), &ScrollPaintPropertyNode::Root(),
- State::Flags{false /* flattens_inherited_transform */,
- false /* in_subtree_of_page_scale */}})));
+ nullptr, State{FloatSize(), &ScrollPaintPropertyNode::Root(), nullptr,
+ State::Flags{false /* flattens_inherited_transform */,
+ false /* in_subtree_of_page_scale */}})));
return *root;
}
@@ -81,6 +79,12 @@ std::unique_ptr<JSONObject> TransformPaintPropertyNode::ToJSON() const {
}
if (state_.scroll)
json->SetString("scroll", String::Format("%p", state_.scroll.get()));
+
+ if (state_.scroll_translation_for_fixed) {
+ json->SetString(
+ "scroll_translation_for_fixed",
+ String::Format("%p", state_.scroll_translation_for_fixed.get()));
+ }
return json;
}
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 1bab0511a3b..52224357ab5 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
@@ -160,6 +160,8 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
struct State {
TransformAndOrigin transform_and_origin;
scoped_refptr<const ScrollPaintPropertyNode> scroll;
+ scoped_refptr<const TransformPaintPropertyNode>
+ scroll_translation_for_fixed;
// Use bitfield packing instead of separate bools to save space.
struct Flags {
bool flattens_inherited_transform : 1;
@@ -200,7 +202,9 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
backface_visibility != other.backface_visibility ||
rendering_context_id != other.rendering_context_id ||
compositor_element_id != other.compositor_element_id ||
- scroll != other.scroll || !StickyConstraintEquals(other) ||
+ scroll != other.scroll ||
+ scroll_translation_for_fixed != other.scroll_translation_for_fixed ||
+ !StickyConstraintEquals(other) ||
visible_frame_element_id != other.visible_frame_element_id) {
return PaintPropertyChangeType::kChangedOnlyValues;
}
@@ -322,6 +326,10 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
return state_.scroll.get();
}
+ const TransformPaintPropertyNode* ScrollTranslationForFixed() const {
+ return state_.scroll_translation_for_fixed.get();
+ }
+
// If true, this node is translated by the viewport bounds delta, which is
// used to keep bottom-fixed elements appear fixed to the bottom of the
// screen in the presence of URL bar movement.
@@ -414,9 +422,13 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
CompositingReason::kActiveTransformAnimation;
}
+ bool RequiresCompositingForFixedPosition() const {
+ return DirectCompositingReasons() & CompositingReason::kFixedPosition;
+ }
+
bool RequiresCompositingForScrollDependentPosition() const {
return DirectCompositingReasons() &
- CompositingReason::kScrollDependentPosition;
+ CompositingReason::kComboScrollDependentPosition;
}
CompositingReasons DirectCompositingReasonsForDebugging() const {
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 34e0fa15dee..f0c16a02594 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
@@ -15,8 +15,7 @@ void PaintGeneratedImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) {
PaintCanvasAutoRestore ar(canvas, true);
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 b5a7b35157b..f7b3e8057e0 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
@@ -25,8 +25,7 @@ class PLATFORM_EXPORT PaintGeneratedImage : public GeneratedImage {
const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
void DrawTile(GraphicsContext&,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc b/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc
index 57cce025621..c82e166d77d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc
@@ -24,12 +24,12 @@ class AutoSignal {
explicit AutoSignal(base::WaitableEvent* event) : event_(event) {
DCHECK(event);
}
+ AutoSignal(const AutoSignal&) = delete;
+ AutoSignal& operator=(const AutoSignal&) = delete;
~AutoSignal() { event_->Signal(); }
private:
base::WaitableEvent* event_;
-
- DISALLOW_COPY_AND_ASSIGN(AutoSignal);
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
index 5cd5a3a21e6..790ecd49cf5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
@@ -40,6 +39,9 @@ class PLATFORM_EXPORT PaintWorkletPaintDispatcher {
base::WeakPtr<PaintWorkletPaintDispatcher>* paintee);
PaintWorkletPaintDispatcher();
+ PaintWorkletPaintDispatcher(const PaintWorkletPaintDispatcher&) = delete;
+ PaintWorkletPaintDispatcher& operator=(const PaintWorkletPaintDispatcher&) =
+ delete;
// Dispatches a set of paint class instances - each represented by a
// PaintWorkletInput - to the appropriate PaintWorklet threads, asynchronously
@@ -104,8 +106,6 @@ class PLATFORM_EXPORT PaintWorkletPaintDispatcher {
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PaintWorkletPaintDispatcher> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PaintWorkletPaintDispatcher);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc
index c2d2b8a1f09..2dfb0ac3ae5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc
@@ -74,6 +74,7 @@ class MockPaintWorkletInput : public cc::PaintWorkletInput {
MOCK_CONST_METHOD0(WorkletId, int());
MOCK_CONST_METHOD0(GetPropertyKeys,
const std::vector<PaintWorkletInput::PropertyKey>&());
+ MOCK_CONST_METHOD0(IsCSSPaintWorkletInput, bool());
};
cc::PaintWorkletInput* AddPaintWorkletInputToMap(cc::PaintWorkletJobMap& map,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/parkable_image.cc b/chromium/third_party/blink/renderer/platform/graphics/parkable_image.cc
index 98ed89c98f5..3e443e5c3f5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/parkable_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/parkable_image.cc
@@ -25,9 +25,9 @@ namespace blink {
namespace {
void RecordReadStatistics(size_t size, base::TimeDelta duration) {
- size_t throughput_mb_s =
- static_cast<size_t>(size / duration.InSecondsF()) / (1024 * 1024);
- size_t size_kb = size / 1024; // in KiB
+ int throughput_mb_s =
+ static_cast<int>(size / duration.InSecondsF() / (1024 * 1024));
+ int size_kb = static_cast<int>(size / 1024); // in KiB
// Size should be <1MiB in most cases.
base::UmaHistogramCounts10000("Memory.ParkableImage.Read.Size", size_kb);
@@ -43,9 +43,9 @@ void RecordReadStatistics(size_t size, base::TimeDelta duration) {
}
void RecordWriteStatistics(size_t size, base::TimeDelta duration) {
- size_t throughput_mb_s =
- static_cast<size_t>(size / duration.InSecondsF()) / (1024 * 1024);
- size_t size_kb = size / 1024;
+ int throughput_mb_s =
+ static_cast<int>(size / duration.InSecondsF() / (1024 * 1024));
+ int size_kb = static_cast<int>(size / 1024); // in KiB
// Size should be <1MiB in most cases.
base::UmaHistogramCounts10000("Memory.ParkableImage.Write.Size", size_kb);
@@ -91,7 +91,7 @@ void AsanUnpoisonBuffer(RWBuffer* rw_buffer) {
const base::Feature kUseParkableImageSegmentReader{
"UseParkableImageSegmentReader", base::FEATURE_DISABLED_BY_DEFAULT};
-void ParkableImage::Append(WTF::SharedBuffer* buffer, size_t offset) {
+void ParkableImageImpl::Append(WTF::SharedBuffer* buffer, size_t offset) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
MutexLocker lock(lock_);
DCHECK(!frozen_);
@@ -106,7 +106,7 @@ void ParkableImage::Append(WTF::SharedBuffer* buffer, size_t offset) {
size_ = rw_buffer_->size();
}
-scoped_refptr<SharedBuffer> ParkableImage::Data() {
+scoped_refptr<SharedBuffer> ParkableImageImpl::Data() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
MutexLocker lock(lock_);
Unpark();
@@ -120,38 +120,30 @@ scoped_refptr<SharedBuffer> ParkableImage::Data() {
return shared_buffer;
}
-scoped_refptr<SegmentReader> ParkableImage::GetSegmentReader() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- if (base::FeatureList::IsEnabled(kUseParkableImageSegmentReader)) {
- return SegmentReader::CreateFromParkableImage(
- scoped_refptr<ParkableImage>(this));
- } else {
- MutexLocker lock(lock_);
- Unpark();
- DCHECK(rw_buffer_);
- // The locking and unlocking here is only needed to make sure ASAN unpoisons
- // things correctly here.
- Lock();
- scoped_refptr<ROBuffer> ro_buffer(rw_buffer_->MakeROBufferSnapshot());
- scoped_refptr<SegmentReader> segment_reader =
- SegmentReader::CreateFromROBuffer(std::move(ro_buffer));
- Unlock();
- return segment_reader;
- }
+scoped_refptr<SegmentReader> ParkableImageImpl::GetROBufferSegmentReader() {
+ MutexLocker lock(lock_);
+ Unpark();
+ DCHECK(rw_buffer_);
+ // The locking and unlocking here is only needed to make sure ASAN unpoisons
+ // things correctly here.
+ LockData();
+ scoped_refptr<ROBuffer> ro_buffer(rw_buffer_->MakeROBufferSnapshot());
+ scoped_refptr<SegmentReader> segment_reader =
+ SegmentReader::CreateFromROBuffer(std::move(ro_buffer));
+ UnlockData();
+ return segment_reader;
}
-bool ParkableImage::CanParkNow() const {
+bool ParkableImageImpl::CanParkNow() const {
DCHECK(!is_on_disk());
return is_frozen() && !is_locked() && rw_buffer_->HasNoSnapshots();
}
-ParkableImage::ParkableImage(size_t initial_capacity)
- : rw_buffer_(std::make_unique<RWBuffer>(initial_capacity)) {
- ParkableImageManager::Instance().Add(this);
-}
+ParkableImageImpl::ParkableImageImpl(size_t initial_capacity)
+ : rw_buffer_(std::make_unique<RWBuffer>(initial_capacity)) {}
-ParkableImage::~ParkableImage() {
+ParkableImageImpl::~ParkableImageImpl() {
+ DCHECK(IsMainThread());
DCHECK(!is_locked());
auto& manager = ParkableImageManager::Instance();
if (!is_below_min_parking_size() || !is_frozen())
@@ -163,16 +155,12 @@ ParkableImage::~ParkableImage() {
}
// static
-scoped_refptr<ParkableImage> ParkableImage::Create(size_t initial_capacity) {
- return base::MakeRefCounted<ParkableImage>(initial_capacity);
+scoped_refptr<ParkableImageImpl> ParkableImageImpl::Create(
+ size_t initial_capacity) {
+ return base::MakeRefCounted<ParkableImageImpl>(initial_capacity);
}
-scoped_refptr<SegmentReader> ParkableImage::MakeROSnapshot() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- return GetSegmentReader();
-}
-
-void ParkableImage::Freeze() {
+void ParkableImageImpl::Freeze() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
MutexLocker lock(lock_);
DCHECK(!frozen_);
@@ -192,7 +180,7 @@ void ParkableImage::Freeze() {
AsanPoisonBuffer(rw_buffer_.get());
}
-void ParkableImage::Lock() {
+void ParkableImageImpl::LockData() {
// Calling |Lock| only makes sense if the data is available.
DCHECK(rw_buffer_);
@@ -201,7 +189,7 @@ void ParkableImage::Lock() {
AsanUnpoisonBuffer(rw_buffer_.get());
}
-void ParkableImage::Unlock() {
+void ParkableImageImpl::UnlockData() {
// Check that we've locked it already.
DCHECK_GT(lock_depth_, 0u);
// While locked, we can never write the data to disk.
@@ -211,14 +199,14 @@ void ParkableImage::Unlock() {
// We only poison the buffer if we're able to park after unlocking.
// This is to avoid issues when creating a ROBufferSegmentReader from the
- // ParkableImage.
+ // ParkableImageImpl.
if (CanParkNow())
AsanPoisonBuffer(rw_buffer_.get());
}
// static
-void ParkableImage::WriteToDiskInBackground(
- scoped_refptr<ParkableImage> parkable_image,
+void ParkableImageImpl::WriteToDiskInBackground(
+ scoped_refptr<ParkableImageImpl> parkable_image,
scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner) {
DCHECK(!IsMainThread());
MutexLocker lock(parkable_image->lock_);
@@ -234,10 +222,12 @@ void ParkableImage::WriteToDiskInBackground(
ROBuffer::Iter it(ro_buffer.get());
Vector<char> vector;
- vector.ReserveInitialCapacity(parkable_image->size());
+ vector.ReserveInitialCapacity(
+ base::checked_cast<wtf_size_t>(parkable_image->size()));
do {
- vector.Append(reinterpret_cast<const char*>(it.data()), it.size());
+ vector.Append(reinterpret_cast<const char*>(it.data()),
+ base::checked_cast<wtf_size_t>(it.size()));
} while (it.Next());
// Release the lock while writing, so we don't block for too long.
@@ -254,19 +244,20 @@ void ParkableImage::WriteToDiskInBackground(
parkable_image->on_disk_metadata_ = std::move(metadata);
// Nothing to do if the write failed except return. Notably, we need to
- // keep around the data for the ParkableImage in this case.
+ // keep around the data for the ParkableImageImpl in this case.
if (!parkable_image->on_disk_metadata_) {
parkable_image->background_task_in_progress_ = false;
} else {
RecordWriteStatistics(parkable_image->on_disk_metadata_->size(), elapsed);
ParkableImageManager::Instance().RecordDiskWriteTime(elapsed);
- PostCrossThreadTask(*callback_task_runner, FROM_HERE,
- CrossThreadBindOnce(&ParkableImage::MaybeDiscardData,
- std::move(parkable_image)));
+ PostCrossThreadTask(
+ *callback_task_runner, FROM_HERE,
+ CrossThreadBindOnce(&ParkableImageImpl::MaybeDiscardData,
+ std::move(parkable_image)));
}
}
-void ParkableImage::MaybeDiscardData() {
+void ParkableImageImpl::MaybeDiscardData() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!is_below_min_parking_size());
@@ -284,7 +275,7 @@ void ParkableImage::MaybeDiscardData() {
DiscardData();
}
-void ParkableImage::DiscardData() {
+void ParkableImageImpl::DiscardData() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!is_locked());
AsanUnpoisonBuffer(rw_buffer_.get());
@@ -293,7 +284,7 @@ void ParkableImage::DiscardData() {
ParkableImageManager::Instance().OnWrittenToDisk(this);
}
-bool ParkableImage::MaybePark() {
+bool ParkableImageImpl::MaybePark() {
DCHECK(ParkableImageManager::IsParkableImagesToDiskEnabled());
MutexLocker lock(lock_);
@@ -315,13 +306,25 @@ bool ParkableImage::MaybePark() {
// current thread for when we have finished writing.
worker_pool::PostTask(
FROM_HERE, {base::MayBlock()},
- CrossThreadBindOnce(&ParkableImage::WriteToDiskInBackground,
- scoped_refptr<ParkableImage>(this),
+ CrossThreadBindOnce(&ParkableImageImpl::WriteToDiskInBackground,
+ scoped_refptr<ParkableImageImpl>(this),
Thread::Current()->GetTaskRunner()));
return true;
}
-void ParkableImage::Unpark() {
+// static
+size_t ParkableImageImpl::ReadFromDiskIntoBuffer(
+ DiskDataMetadata* on_disk_metadata,
+ void* buffer,
+ size_t capacity) {
+ size_t size = on_disk_metadata->size();
+ DCHECK(size <= capacity);
+ ParkableImageManager::Instance().data_allocator().Read(*on_disk_metadata,
+ buffer);
+ return size;
+}
+
+void ParkableImageImpl::Unpark() {
if (!is_on_disk()) {
AsanUnpoisonBuffer(rw_buffer_.get());
return;
@@ -329,14 +332,18 @@ void ParkableImage::Unpark() {
DCHECK(ParkableImageManager::IsParkableImagesToDiskEnabled());
- TRACE_EVENT1("blink", "ParkableImage::Unpark", "size", size());
+ TRACE_EVENT1("blink", "ParkableImageImpl::Unpark", "size", size());
DCHECK(on_disk_metadata_);
- WTF::Vector<uint8_t> vector(size());
base::ElapsedTimer timer;
- ParkableImageManager::Instance().data_allocator().Read(*on_disk_metadata_,
- vector.data());
+
+ DCHECK(!rw_buffer_);
+ rw_buffer_ = std::make_unique<RWBuffer>(
+ base::BindOnce(&ParkableImageImpl::ReadFromDiskIntoBuffer,
+ base::Unretained(on_disk_metadata_.get())),
+ size());
+
base::TimeDelta elapsed = timer.Elapsed();
RecordReadStatistics(on_disk_metadata_->size(), elapsed);
@@ -344,22 +351,80 @@ void ParkableImage::Unpark() {
ParkableImageManager::Instance().OnReadFromDisk(this);
- DCHECK(!rw_buffer_);
-
- rw_buffer_ = std::make_unique<RWBuffer>(size());
- rw_buffer_->Append(vector.data(), size());
+ DCHECK(rw_buffer_);
}
-size_t ParkableImage::size() const {
+size_t ParkableImageImpl::size() const {
return size_;
}
-bool ParkableImage::is_below_min_parking_size() const {
- return size() < ParkableImage::kMinSizeToPark;
+bool ParkableImageImpl::is_below_min_parking_size() const {
+ return size() < ParkableImageImpl::kMinSizeToPark;
}
-bool ParkableImage::is_locked() const {
+bool ParkableImageImpl::is_locked() const {
return lock_depth_ != 0;
}
+ParkableImage::ParkableImage(size_t offset)
+ : impl_(ParkableImageManager::Instance().CreateParkableImage(offset)) {
+ ParkableImageManager::Instance().Add(impl_.get());
+}
+
+ParkableImage::~ParkableImage() {
+ ParkableImageManager::Instance().DestroyParkableImage(std::move(impl_));
+}
+
+// static
+scoped_refptr<ParkableImage> ParkableImage::Create(size_t initial_capacity) {
+ return base::MakeRefCounted<ParkableImage>(initial_capacity);
+}
+
+size_t ParkableImage::size() const {
+ DCHECK(impl_);
+ return impl_->size();
+}
+
+bool ParkableImage::is_on_disk() const {
+ DCHECK(impl_);
+ return impl_->is_on_disk();
+}
+
+scoped_refptr<SegmentReader> ParkableImage::MakeROSnapshot() {
+ DCHECK(impl_);
+ DCHECK_CALLED_ON_VALID_THREAD(impl_->thread_checker_);
+
+ if (base::FeatureList::IsEnabled(kUseParkableImageSegmentReader)) {
+ return SegmentReader::CreateFromParkableImage(
+ scoped_refptr<ParkableImage>(this));
+ } else {
+ return impl_->GetROBufferSegmentReader();
+ }
+}
+
+void ParkableImage::Freeze() {
+ DCHECK(impl_);
+ impl_->Freeze();
+}
+
+scoped_refptr<SharedBuffer> ParkableImage::Data() {
+ DCHECK(impl_);
+ return impl_->Data();
+}
+
+void ParkableImage::Append(WTF::SharedBuffer* buffer, size_t offset) {
+ DCHECK(impl_);
+ impl_->Append(buffer, offset);
+}
+
+void ParkableImage::LockData() {
+ DCHECK(impl_);
+ impl_->LockData();
+}
+
+void ParkableImage::UnlockData() {
+ DCHECK(impl_);
+ impl_->UnlockData();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/parkable_image.h b/chromium/third_party/blink/renderer/platform/graphics/parkable_image.h
index 6277a15f56d..4d2135c0981 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/parkable_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/parkable_image.h
@@ -20,67 +20,50 @@ namespace blink {
class SegmentReader;
class ParkableImageManager;
-// Wraps a RWBuffer containing encoded image data. This buffer can be written
-// to/read from disk when not needed, to improve memory usage.
-class PLATFORM_EXPORT ParkableImage final
- : public ThreadSafeRefCounted<ParkableImage> {
+// Implementation of ParkableImage. See ParkableImage below.
+// We split ParkableImage like this because we want to avoid destroying the
+// content of the ParkableImage on anything besides the main thread.
+// See |ParkableImageManager::MaybeParkImages| for details on this.
+class PLATFORM_EXPORT ParkableImageImpl final
+ : public ThreadSafeRefCounted<ParkableImageImpl> {
public:
- ParkableImage& operator=(const ParkableImage&) = delete;
- ParkableImage(const ParkableImage&) = delete;
-
- ~ParkableImage();
+ ParkableImageImpl& operator=(const ParkableImage&) = delete;
+ ParkableImageImpl(const ParkableImage&) = delete;
// Smallest encoded size that will actually be parked.
static constexpr size_t kMinSizeToPark = 1024; // 1 KiB
- // Factory method to construct a ParkableImage.
- static scoped_refptr<ParkableImage> Create(size_t initial_capacity = 0);
-
- // Freezes the ParkableImage. This changes the following:
- // (1) We are no longer allowed to mutate the internal buffer (e.g. via
- // Append);
- // (2) The image may now be parked to disk.
- void Freeze() LOCKS_EXCLUDED(lock_);
-
- // Adds data to the internal buffer of ParkableImage. Cannot be called after
- // the ParkableImage has been frozen (see Freeze()). |offset| is the offset
- // from the start of |buffer| that we want to start copying the data from.
- void Append(WTF::SharedBuffer* buffer, size_t offset = 0)
- LOCKS_EXCLUDED(lock_);
-
- // Make a Read-Only snapshot of the data within ParkableImage. This may be a
- // view into the internal buffer of ParkableImage, or a copy of the data. It
- // is guaranteed to be safe to read this data from another thread at any time.
- scoped_refptr<SegmentReader> MakeROSnapshot();
-
- // Returns the data in the internal buffer. It should not be modified after
- // the ParkableImage has been frozen.
- scoped_refptr<SharedBuffer> Data() LOCKS_EXCLUDED(lock_);
-
- // Returns the size of the internal buffer. Can be called even when
- // ParkableImage has been parked.
- size_t size() const;
-
- bool is_frozen() const { return frozen_; }
-
private:
- friend class ThreadSafeRefCounted<ParkableImage>;
+ friend class ThreadSafeRefCounted<ParkableImageImpl>;
template <typename T, typename... Args>
friend scoped_refptr<T> base::MakeRefCounted(Args&&... args);
friend class ParkableImageManager;
+ friend class ParkableImage;
friend class ParkableImageBaseTest;
friend class ParkableImageSegmentReader;
// |initial_capacity| reserves space in the internal buffer, if you know how
// much data you'll be appending in advance.
- explicit ParkableImage(size_t initial_capacity = 0);
+ explicit ParkableImageImpl(size_t initial_capacity = 0);
- scoped_refptr<SegmentReader> GetSegmentReader() LOCKS_EXCLUDED(lock_);
+ ~ParkableImageImpl();
- // Locks and Unlocks the ParkableImage. A locked ParkableImage cannot be
- // parked. Every call to Lock must have a corresponding call to Unlock.
- void Lock() EXCLUSIVE_LOCKS_REQUIRED(lock_);
- void Unlock() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ // Factory method to construct a ParkableImageImpl.
+ static scoped_refptr<ParkableImageImpl> Create(size_t initial_capacity = 0);
+
+ // Implementations of the methods of the same name from ParkableImage.
+ void Freeze() LOCKS_EXCLUDED(lock_);
+ void Append(WTF::SharedBuffer* buffer, size_t offset = 0)
+ LOCKS_EXCLUDED(lock_);
+ scoped_refptr<SharedBuffer> Data() LOCKS_EXCLUDED(lock_);
+ void LockData() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ void UnlockData() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ size_t size() const;
+
+ // Returns a ROBufferSegmentReader, wrapping the internal RWBuffer.
+ scoped_refptr<SegmentReader> GetROBufferSegmentReader() LOCKS_EXCLUDED(lock_);
+
+ bool is_frozen() const { return frozen_; }
// Attempt to park to disk. Returns false if it cannot be parked right now for
// whatever reason, true if we will _attempt_ to park it to disk.
@@ -94,10 +77,16 @@ class PLATFORM_EXPORT ParkableImage final
// Tries to write the data from |rw_buffer_| to disk. Then, if the data is
// successfully written to disk, posts a task to discard |rw_buffer_|.
static void WriteToDiskInBackground(
- scoped_refptr<ParkableImage>,
+ scoped_refptr<ParkableImageImpl>,
scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner)
LOCKS_EXCLUDED(lock_);
+ // Writes the data referred to by |on_disk_metadata| from disk into the
+ // provided |buffer|. |capacity| is the size of the provided buffer.
+ static size_t ReadFromDiskIntoBuffer(DiskDataMetadata* on_disk_metadata,
+ void* buffer,
+ size_t capacity);
+
// Attempt to discard the data. This should only be called after we've written
// the data to disk. Fails if the image can not be parked at the time this is
// called for whatever reason.
@@ -107,10 +96,11 @@ class PLATFORM_EXPORT ParkableImage final
// this is only called when the image can be parked.
void DiscardData() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ // Only larger images are parked, see kMinSizeToPark for the threshold used.
bool is_below_min_parking_size() const;
- // Returns whether the ParkableImage is locked or not. See |Lock| and |Unlock|
- // for details.
+ // Returns whether the ParkableImageImpl is locked or not. See |Lock| and
+ // |Unlock| for details.
bool is_locked() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
bool is_on_disk() const EXCLUSIVE_LOCKS_REQUIRED(lock_) {
return !rw_buffer_ && on_disk_metadata_;
@@ -128,14 +118,66 @@ class PLATFORM_EXPORT ParkableImage final
// |frozen_| is only modified on the main thread.
bool frozen_ = false;
// Counts the number of Lock/Unlock calls. Incremented by Lock, decremented by
- // Unlock. The ParkableImage is unlocked iff |lock_depth_| is 0, i.e. we've
- // called Lock and Unlock the same number of times.
+ // Unlock. The ParkableImageImpl is unlocked iff |lock_depth_| is 0, i.e.
+ // we've called Lock and Unlock the same number of times.
size_t lock_depth_ GUARDED_BY(lock_) = 0;
bool background_task_in_progress_ GUARDED_BY(lock_) = false;
THREAD_CHECKER(thread_checker_);
};
+// Wraps a RWBuffer containing encoded image data. This buffer can be written
+// to/read from disk when not needed, to improve memory usage.
+class PLATFORM_EXPORT ParkableImage final
+ : public ThreadSafeRefCounted<ParkableImage> {
+ public:
+ // Factory method to construct a ParkableImage.
+ static scoped_refptr<ParkableImage> Create(size_t initial_capacity = 0);
+
+ // Creates a read-only snapshot of the ParkableImage. This can be used
+ // from other threads.
+ scoped_refptr<SegmentReader> MakeROSnapshot();
+
+ // Freezes the ParkableImage. This changes the following:
+ // (1) We are no longer allowed to mutate the internal buffer (e.g. via
+ // Append);
+ // (2) The image may now be parked to disk.
+ void Freeze() LOCKS_EXCLUDED(impl_->lock_);
+
+ // Appends data to the ParkableImage. Cannot be called after the ParkableImage
+ // has been frozen. (see: Freeze())
+ void Append(WTF::SharedBuffer* buffer, size_t offset = 0)
+ LOCKS_EXCLUDED(impl_->lock_);
+
+ // Returns a copy of the data stored in ParkableImage. Calling this will
+ // unpark the image from disk if needed.
+ scoped_refptr<SharedBuffer> Data() LOCKS_EXCLUDED(impl_->lock_);
+
+ // Returns the size of the encoded image data stored in the ParkableImage. Can
+ // be called even if the image is currently parked, and will not unpark it.
+ size_t size() const;
+
+ private:
+ friend class ThreadSafeRefCounted<ParkableImage>;
+ template <typename T, typename... Args>
+ friend scoped_refptr<T> base::MakeRefCounted(Args&&... args);
+ friend class ParkableImageManager;
+ friend class ParkableImageBaseTest;
+ friend class ParkableImageSegmentReader;
+
+ explicit ParkableImage(size_t initial_capacity = 0);
+ ~ParkableImage();
+
+ // Locks and Unlocks the ParkableImageImpl. A locked ParkableImage cannot be
+ // parked. Every call to Lock must have a corresponding call to Unlock.
+ void LockData() EXCLUSIVE_LOCKS_REQUIRED(impl_->lock_);
+ void UnlockData() EXCLUSIVE_LOCKS_REQUIRED(impl_->lock_);
+
+ bool is_on_disk() const EXCLUSIVE_LOCKS_REQUIRED(impl_->lock_);
+
+ scoped_refptr<ParkableImageImpl> impl_;
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.cc b/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.cc
index 349689f4a17..f50db27729b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.cc
@@ -87,8 +87,14 @@ void ParkableImageManager::ResetForTesting() {
total_disk_write_time_ = base::TimeDelta();
}
-void ParkableImageManager::Add(ParkableImage* image) {
+void ParkableImageManager::Add(ParkableImageImpl* impl) {
DCHECK(IsMainThread());
+#if DCHECK_IS_ON()
+ {
+ MutexLocker lock(impl->lock_);
+ DCHECK(!IsRegistered(impl));
+ }
+#endif // DCHECK_IS_ON()
MutexLocker lock(lock_);
@@ -107,7 +113,7 @@ void ParkableImageManager::Add(ParkableImage* image) {
has_posted_accounting_task_ = true;
}
- unparked_images_.insert(image);
+ unparked_images_.insert(impl);
}
void ParkableImageManager::RecordStatisticsAfter5Minutes() const {
@@ -117,12 +123,13 @@ void ParkableImageManager::RecordStatisticsAfter5Minutes() const {
Statistics stats = ComputeStatistics();
+ // In KiB
base::UmaHistogramCounts100000("Memory.ParkableImage.TotalSize.5min",
- stats.total_size / 1024); // in KiB
+ static_cast<int>(stats.total_size / 1024));
base::UmaHistogramCounts100000("Memory.ParkableImage.OnDiskSize.5min",
- stats.on_disk_size / 1024); // in KiB
+ static_cast<int>(stats.on_disk_size / 1024));
base::UmaHistogramCounts100000("Memory.ParkableImage.UnparkedSize.5min",
- stats.unparked_size / 1024); // in KiB
+ static_cast<int>(stats.unparked_size / 1024));
// Metrics related to parking only should be recorded if the feature is
// enabled.
@@ -139,7 +146,35 @@ void ParkableImageManager::RecordStatisticsAfter5Minutes() const {
}
}
-void ParkableImageManager::Remove(ParkableImage* image) {
+scoped_refptr<ParkableImageImpl> ParkableImageManager::CreateParkableImage(
+ size_t offset) {
+ MutexLocker lock(lock_);
+ scoped_refptr<ParkableImageImpl> impl = ParkableImageImpl::Create(offset);
+ return impl;
+}
+
+void ParkableImageManager::DestroyParkableImageOnMainThread(
+ scoped_refptr<ParkableImageImpl> image) {
+ DCHECK(IsMainThread());
+}
+
+void ParkableImageManager::DestroyParkableImage(
+ scoped_refptr<ParkableImageImpl> image) {
+ if (IsMainThread()) {
+ DestroyParkableImageOnMainThread(std::move(image));
+ } else {
+ auto* thread = Thread::MainThread();
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ thread->GetTaskRunner();
+ DCHECK(task_runner);
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ParkableImageManager::DestroyParkableImageOnMainThread,
+ base::Unretained(this), std::move(image)));
+ }
+}
+
+void ParkableImageManager::Remove(ParkableImageImpl* image) {
MutexLocker lock(lock_);
// Image could be on disk or unparked. Remove it in either case.
@@ -149,9 +184,9 @@ void ParkableImageManager::Remove(ParkableImage* image) {
map->erase(it);
}
-void ParkableImageManager::MoveImage(ParkableImage* image,
- WTF::HashSet<ParkableImage*>* from,
- WTF::HashSet<ParkableImage*>* to) {
+void ParkableImageManager::MoveImage(ParkableImageImpl* image,
+ WTF::HashSet<ParkableImageImpl*>* from,
+ WTF::HashSet<ParkableImageImpl*>* to) {
auto it = from->find(image);
CHECK(it != from->end());
CHECK(!to->Contains(image));
@@ -159,7 +194,7 @@ void ParkableImageManager::MoveImage(ParkableImage* image,
to->insert(image);
}
-bool ParkableImageManager::IsRegistered(ParkableImage* image) {
+bool ParkableImageManager::IsRegistered(ParkableImageImpl* image) {
MutexLocker lock(lock_);
auto* map = image->is_on_disk() ? &on_disk_images_ : &unparked_images_;
@@ -168,12 +203,12 @@ bool ParkableImageManager::IsRegistered(ParkableImage* image) {
return it != map->end();
}
-void ParkableImageManager::OnWrittenToDisk(ParkableImage* image) {
+void ParkableImageManager::OnWrittenToDisk(ParkableImageImpl* image) {
MutexLocker lock(lock_);
MoveImage(image, &unparked_images_, &on_disk_images_);
}
-void ParkableImageManager::OnReadFromDisk(ParkableImage* image) {
+void ParkableImageManager::OnReadFromDisk(ParkableImageImpl* image) {
MutexLocker lock(lock_);
MoveImage(image, &on_disk_images_, &unparked_images_);
ScheduleDelayedParkingTaskIfNeeded();
@@ -198,21 +233,22 @@ void ParkableImageManager::ScheduleDelayedParkingTaskIfNeeded() {
}
void ParkableImageManager::MaybeParkImages() {
+ // Because we only have a raw pointer to the ParkableImageImpl, we need to be
+ // very careful here to avoid a UAF.
+ // To avoid this, we make sure that ParkableImageImpl is always destroyed on
+ // the main thread, using |ParkableImageManager::DestroyParkableImage|.
DCHECK(ParkableImageManager::IsParkableImagesToDiskEnabled());
+ DCHECK(IsMainThread());
MutexLocker lock(lock_);
// This makes a copy of the pointers stored in |unparked_images_|. We iterate
// over this copy in |MaybeParkImages|, instead of |unparked_images_|
- // directly, for two reasons:
- // (1) Avoiding a deadlock when we need to park synchronously (i.e. if we have
- // already written to disk and don't need to post a background task), as
+ // directly, to avoid deadlock when we need to park synchronously (i.e. if we
+ // have already written to disk and don't need to post a background task), as
// synchronous parking calls |ParkableImageManager::OnWrittenToDisk()|;
- // (2) Keeping the images alive until we are done iterating, without locking
- // (through use of scoped_refptr instead of a raw pointer).
- WTF::Vector<scoped_refptr<ParkableImage>> unparked_images;
- for (auto* image : unparked_images_)
- unparked_images.push_back(scoped_refptr<ParkableImage>(image));
+ WTF::Vector<ParkableImageImpl*> unparked_images;
+ CopyToVector(unparked_images_, unparked_images);
// We unlock here so that we can avoid a deadlock, since if the data for the
// image is already written to disk, we can discard our copy of the data
@@ -220,7 +256,7 @@ void ParkableImageManager::MaybeParkImages() {
lock_.unlock();
bool unfrozen_images = false;
- for (auto image : unparked_images) {
+ for (auto* image : unparked_images) {
if (!image->is_frozen())
unfrozen_images = true;
image->MaybePark();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.h b/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.h
index a4f1895e4d4..dd28094540f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/parkable_image_manager.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_MANAGER_H_
#include "base/feature_list.h"
+#include "base/no_destructor.h"
#include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/disk_data_allocator.h"
#include "third_party/blink/renderer/platform/graphics/parkable_image.h"
@@ -15,6 +16,7 @@
namespace blink {
+class ParkableImageImpl;
class ParkableImage;
PLATFORM_EXPORT extern const base::Feature kParkableImagesToDisk;
@@ -43,6 +45,7 @@ class PLATFORM_EXPORT ParkableImageManager
struct Statistics;
friend class ParkableImage;
+ friend class ParkableImageImpl;
friend class base::NoDestructor<ParkableImageManager>;
friend class ParkableImageBaseTest;
@@ -52,12 +55,20 @@ class PLATFORM_EXPORT ParkableImageManager
// Register and unregister a ParkableImage with the manager. ParkableImage
// should call these when created/destructed.
- void Add(ParkableImage* image) LOCKS_EXCLUDED(lock_);
- void Remove(ParkableImage* image) LOCKS_EXCLUDED(lock_)
+ void Add(ParkableImageImpl* image) LOCKS_EXCLUDED(lock_);
+ void Remove(ParkableImageImpl* image) LOCKS_EXCLUDED(lock_)
EXCLUSIVE_LOCKS_REQUIRED(image->lock_);
- bool IsRegistered(ParkableImage* image) LOCKS_EXCLUDED(lock_)
+ scoped_refptr<ParkableImageImpl> CreateParkableImage(size_t offset);
+ void DestroyParkableImageOnMainThread(scoped_refptr<ParkableImageImpl> image)
+ LOCKS_EXCLUDED(lock_);
+ void DestroyParkableImage(scoped_refptr<ParkableImageImpl> image)
+ LOCKS_EXCLUDED(lock_);
+
+ bool IsRegistered(ParkableImageImpl* image) LOCKS_EXCLUDED(lock_)
EXCLUSIVE_LOCKS_REQUIRED(image->lock_);
+ // bool IsRegistered(ParkableImage* image) LOCKS_EXCLUDED(lock_)
+ // EXCLUSIVE_LOCKS_REQUIRED(image->impl_->lock_);
void ScheduleDelayedParkingTaskIfNeeded() EXCLUSIVE_LOCKS_REQUIRED(lock_);
void MaybeParkImages() LOCKS_EXCLUDED(lock_);
@@ -66,9 +77,9 @@ class PLATFORM_EXPORT ParkableImageManager
void RecordStatisticsAfter5Minutes() const LOCKS_EXCLUDED(lock_);
- void MoveImage(ParkableImage* image,
- WTF::HashSet<ParkableImage*>* from,
- WTF::HashSet<ParkableImage*>* to)
+ void MoveImage(ParkableImageImpl* image,
+ WTF::HashSet<ParkableImageImpl*>* from,
+ WTF::HashSet<ParkableImageImpl*>* to)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void RecordDiskWriteTime(base::TimeDelta write_time) LOCKS_EXCLUDED(lock_) {
@@ -83,8 +94,8 @@ class PLATFORM_EXPORT ParkableImageManager
// Keeps track of whether the image is unparked or on disk. ParkableImage
// should call these when written to or read from disk.
- void OnWrittenToDisk(ParkableImage* image) LOCKS_EXCLUDED(lock_);
- void OnReadFromDisk(ParkableImage* image) LOCKS_EXCLUDED(lock_);
+ void OnWrittenToDisk(ParkableImageImpl* image) LOCKS_EXCLUDED(lock_);
+ void OnReadFromDisk(ParkableImageImpl* image) LOCKS_EXCLUDED(lock_);
void SetDataAllocatorForTesting(
std::unique_ptr<DiskDataAllocator> allocator) {
@@ -112,8 +123,8 @@ class PLATFORM_EXPORT ParkableImageManager
// |on_disk_images_| keeps track of all images that do not have an in-memory
// representation. Accessing the data for any image in |on_disk_images_|
// involves a read from disk.
- WTF::HashSet<ParkableImage*> unparked_images_ GUARDED_BY(lock_);
- WTF::HashSet<ParkableImage*> on_disk_images_ GUARDED_BY(lock_);
+ WTF::HashSet<ParkableImageImpl*> unparked_images_ GUARDED_BY(lock_);
+ WTF::HashSet<ParkableImageImpl*> on_disk_images_ GUARDED_BY(lock_);
bool has_pending_parking_task_ GUARDED_BY(lock_) = false;
bool has_posted_accounting_task_ GUARDED_BY(lock_) = false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/parkable_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/parkable_image_test.cc
index 7f610acefb7..455dfa664e6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/parkable_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/parkable_image_test.cc
@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/parkable_image.h"
+#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/disk_data_allocator_test_utils.h"
#include "third_party/blink/renderer/platform/graphics/parkable_image_manager.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h"
@@ -17,6 +19,18 @@ using ThreadPoolExecutionMode =
namespace blink {
+namespace {
+class LambdaThreadDelegate : public base::PlatformThread::Delegate {
+ public:
+ explicit LambdaThreadDelegate(base::OnceCallback<void()> f)
+ : f_(std::move(f)) {}
+ void ThreadMain() override { std::move(f_).Run(); }
+
+ private:
+ base::OnceCallback<void()> f_;
+};
+} // namespace
+
// Parent for ParkableImageTest and ParkableImageNoParkingTest. The only
// difference between those two is whether parking is enabled or not.
class ParkableImageBaseTest : public ::testing::Test {
@@ -26,6 +40,7 @@ class ParkableImageBaseTest : public ::testing::Test {
ThreadPoolExecutionMode::DEFAULT) {}
void SetUp() override {
+ Platform::SetMainThreadTaskRunnerForTesting();
auto& manager = ParkableImageManager::Instance();
manager.ResetForTesting();
manager.SetDataAllocatorForTesting(
@@ -35,6 +50,7 @@ class ParkableImageBaseTest : public ::testing::Test {
void TearDown() override {
CHECK_EQ(ParkableImageManager::Instance().Size(), 0u);
task_env_.FastForwardUntilNoTasksRemain();
+ Platform::UnsetMainThreadTaskRunnerForTesting();
}
protected:
@@ -57,27 +73,30 @@ class ParkableImageBaseTest : public ::testing::Test {
}
static bool MaybePark(scoped_refptr<ParkableImage> pi) {
- return pi->MaybePark();
+ return pi->impl_->MaybePark();
}
static void Unpark(scoped_refptr<ParkableImage> pi) {
- MutexLocker lock(pi->lock_);
- pi->Unpark();
+ MutexLocker lock(pi->impl_->lock_);
+ pi->impl_->Unpark();
}
static void Lock(scoped_refptr<ParkableImage> pi) {
- MutexLocker lock(pi->lock_);
- pi->Lock();
+ MutexLocker lock(pi->impl_->lock_);
+ pi->LockData();
}
static void Unlock(scoped_refptr<ParkableImage> pi) {
- MutexLocker lock(pi->lock_);
- pi->Unlock();
+ MutexLocker lock(pi->impl_->lock_);
+ pi->UnlockData();
}
static bool is_on_disk(scoped_refptr<ParkableImage> pi) {
- MutexLocker lock(pi->lock_);
+ MutexLocker lock(pi->impl_->lock_);
return pi->is_on_disk();
}
static bool is_locked(scoped_refptr<ParkableImage> pi) {
- MutexLocker lock(pi->lock_);
- return pi->is_locked();
+ MutexLocker lock(pi->impl_->lock_);
+ return pi->impl_->is_locked();
+ }
+ static bool is_frozen(scoped_refptr<ParkableImage> pi) {
+ return pi->impl_->is_frozen();
}
scoped_refptr<ParkableImage> MakeParkableImageForTesting(const char* buffer,
@@ -98,20 +117,20 @@ class ParkableImageBaseTest : public ::testing::Test {
return false;
}
- MutexLocker lock(pi->lock_);
- pi->Lock();
+ MutexLocker lock(pi->impl_->lock_);
+ pi->LockData();
- auto ro_buffer = pi->rw_buffer_->MakeROBufferSnapshot();
+ auto ro_buffer = pi->impl_->rw_buffer_->MakeROBufferSnapshot();
ROBuffer::Iter iter(ro_buffer.get());
do {
if (memcmp(iter.data(), buffer, iter.size()) != 0) {
- pi->Unlock();
+ pi->UnlockData();
return false;
}
buffer += iter.size();
} while (iter.Next());
- pi->Unlock();
+ pi->UnlockData();
return true;
}
@@ -193,11 +212,11 @@ TEST_F(ParkableImageTest, Frozen) {
ASSERT_EQ(pi->size(), 0u);
// Starts unfrozen.
- EXPECT_FALSE(pi->is_frozen());
+ EXPECT_FALSE(is_frozen(pi));
pi->Freeze();
- EXPECT_TRUE(pi->is_frozen());
+ EXPECT_TRUE(is_frozen(pi));
}
TEST_F(ParkableImageTest, LockAndUnlock) {
@@ -534,7 +553,7 @@ TEST_F(ParkableImageTest, ManagerSimple) {
// Tests that a small image is not kept in the manager.
TEST_F(ParkableImageTest, ManagerSmall) {
- const size_t kDataSize = ParkableImage::kMinSizeToPark - 10;
+ const size_t kDataSize = ParkableImageImpl::kMinSizeToPark - 10;
char data[kDataSize];
PrepareReferenceData(data, kDataSize);
@@ -806,4 +825,52 @@ TEST_F(ParkableImageTest, ManagerRescheduleUnfrozen) {
Unlock(pi);
}
+// We want to test that trying to delete an image while we try to park it works
+// correctly. The expected behaviour is we park it, then delete. Slightly
+// inefficient, but the safest way to do it.
+TEST_F(ParkableImageTest, DestroyOnSeparateThread) {
+ const size_t kDataSize = 3.5 * 4096;
+ char data[kDataSize];
+ PrepareReferenceData(data, kDataSize);
+
+ auto& manager = ParkableImageManager::Instance();
+ EXPECT_EQ(0u, manager.Size());
+
+ auto pi = MakeParkableImageForTesting(data, kDataSize);
+ EXPECT_EQ(1u, manager.Size());
+
+ Wait5MinForStatistics();
+
+ pi->Freeze();
+
+ // Task for parking the image.
+ EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
+
+ LambdaThreadDelegate delegate{
+ base::BindLambdaForTesting([parkable_image = std::move(pi)]() mutable {
+ EXPECT_TRUE(!IsMainThread());
+ // We destroy the ParkableImage here, on a different thread. This will
+ // post a task to the main thread to actually delete it.
+ parkable_image = nullptr;
+ })};
+
+ base::PlatformThreadHandle thread_handle;
+ base::PlatformThread::Create(0, &delegate, &thread_handle);
+ base::PlatformThread::Join(thread_handle);
+
+ ASSERT_EQ(pi, nullptr);
+
+ // The manager is still aware of the ParkableImage, since the task for
+ // deleting it hasn't been run yet.
+ EXPECT_EQ(1u, manager.Size());
+ // Task for parking image, followed by task for deleting the image.
+ EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
+
+ WaitForDelayedParking();
+
+ // Now that the tasks for deleting and parking have run, the image is deleted.
+ EXPECT_EQ(0u, manager.Size());
+ EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
+}
+
} // 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 5b5d806d3d5..f2421031c7d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/path.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/path.h
@@ -29,7 +29,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PATH_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PATH_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -115,11 +114,12 @@ class PLATFORM_EXPORT Path {
// vary depending on curvature and number of segments, but should never be
// worse than that of the state-less method on Path.
class PLATFORM_EXPORT PositionCalculator {
- DISALLOW_COPY_AND_ASSIGN(PositionCalculator);
USING_FAST_MALLOC(PositionCalculator);
public:
explicit PositionCalculator(const Path&);
+ PositionCalculator(const PositionCalculator&) = delete;
+ PositionCalculator& operator=(const PositionCalculator&) = delete;
PointAndTangent PointAndNormalAtLength(float length);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/path_traversal_state.h b/chromium/third_party/blink/renderer/platform/graphics/path_traversal_state.h
index 13204e7f5d8..6b36704eecc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/path_traversal_state.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/path_traversal_state.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PATH_TRAVERSAL_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PATH_TRAVERSAL_STATE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -35,7 +34,6 @@ namespace blink {
class PLATFORM_EXPORT PathTraversalState final {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(PathTraversalState);
public:
enum PathTraversalAction {
@@ -45,6 +43,8 @@ class PLATFORM_EXPORT PathTraversalState final {
};
PathTraversalState(PathTraversalAction);
+ PathTraversalState(const PathTraversalState&) = delete;
+ PathTraversalState& operator=(const PathTraversalState&) = delete;
float CloseSubpath();
float MoveTo(const FloatPoint&);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/pattern.h b/chromium/third_party/blink/renderer/platform/graphics/pattern.h
index ba1a98aad36..d93d7232826 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/pattern.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/pattern.h
@@ -29,7 +29,6 @@
#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"
@@ -58,6 +57,8 @@ class PLATFORM_EXPORT Pattern : public RefCounted<Pattern> {
sk_sp<PaintRecord>,
const FloatRect& record_bounds,
RepeatMode = kRepeatModeXY);
+ Pattern(const Pattern&) = delete;
+ Pattern& operator=(const Pattern&) = delete;
virtual ~Pattern();
void ApplyToFlags(cc::PaintFlags&, const SkMatrix&) const;
@@ -76,9 +77,6 @@ class PLATFORM_EXPORT Pattern : public RefCounted<Pattern> {
RepeatMode repeat_mode_;
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 3521009523b..a4f5d38b6cd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
@@ -70,7 +70,7 @@ scoped_refptr<PictureSnapshot> PictureSnapshot::Load(
SkPictureRecorder recorder;
SkCanvas* canvas =
recorder.beginRecording(union_rect.Width(), union_rect.Height());
- for (size_t i = 0; i < pictures.size(); ++i) {
+ for (wtf_size_t i = 0; i < pictures.size(); ++i) {
canvas->save();
canvas->translate(tiles[i]->layer_offset.X() - union_rect.X(),
tiles[i]->layer_offset.Y() - union_rect.Y());
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 1fb23a84487..9ea4fa07a08 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h
@@ -33,7 +33,6 @@
#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"
@@ -61,6 +60,8 @@ class PLATFORM_EXPORT PictureSnapshot : public RefCounted<PictureSnapshot> {
const Vector<scoped_refptr<TilePictureStream>>&);
PictureSnapshot(sk_sp<const SkPicture>);
+ PictureSnapshot(const PictureSnapshot&) = delete;
+ PictureSnapshot& operator=(const PictureSnapshot&) = delete;
Vector<uint8_t> Replay(unsigned from_step = 0,
unsigned to_step = 0,
@@ -75,8 +76,6 @@ 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 8b5c78df6e3..c47effb661a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/public/resources/grit/blink_image_resources.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
@@ -219,7 +219,7 @@ PlaceholderImage::PlaceholderImage(ImageObserver* observer,
PlaceholderImage::~PlaceholderImage() = default;
-IntSize PlaceholderImage::Size() const {
+IntSize PlaceholderImage::SizeWithConfig(SizeConfig) const {
return size_;
}
@@ -249,9 +249,11 @@ PaintImage PlaceholderImage::PaintImageForCurrentFrame() {
}
PaintRecorder paint_recorder;
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
Draw(paint_recorder.beginRecording(FloatRect(dest_rect)), PaintFlags(),
- FloatRect(dest_rect), FloatRect(dest_rect), SkSamplingOptions(),
- kRespectImageOrientation, kClampImageToSourceRect, kSyncDecode);
+ FloatRect(dest_rect), FloatRect(dest_rect), draw_options,
+ kClampImageToSourceRect, kSyncDecode);
paint_record_for_current_frame_ = paint_recorder.finishRecordingAsPicture();
paint_record_content_id_ = PaintImage::GetNextContentId();
@@ -274,8 +276,7 @@ void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& base_flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
- const SkSamplingOptions& sampling,
- RespectImageOrientationEnum respect_orientation,
+ const ImageDrawOptions& draw_options,
ImageClampingMode image_clamping_mode,
ImageDecodingMode decode_mode) {
if (!src_rect.Intersects(FloatRect(0.0f, 0.0f,
@@ -297,7 +298,8 @@ void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
}
if (text_.IsEmpty()) {
- DrawCenteredIcon(canvas, base_flags, dest_rect, sampling,
+ DrawCenteredIcon(canvas, base_flags, dest_rect,
+ draw_options.sampling_options,
icon_and_text_scale_factor_);
return;
}
@@ -316,7 +318,8 @@ void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
(kIconWidth + 2 * kFeaturePaddingX + kPaddingBetweenIconAndText);
if (dest_rect.Width() < icon_and_text_width) {
- DrawCenteredIcon(canvas, base_flags, dest_rect, sampling,
+ DrawCenteredIcon(canvas, base_flags, dest_rect,
+ draw_options.sampling_options,
icon_and_text_scale_factor_);
return;
}
@@ -343,8 +346,8 @@ void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
}
DrawIcon(canvas, base_flags, icon_x,
- feature_y + icon_and_text_scale_factor_ * kIconPaddingY, sampling,
- icon_and_text_scale_factor_);
+ feature_y + icon_and_text_scale_factor_ * kIconPaddingY,
+ draw_options.sampling_options, icon_and_text_scale_factor_);
flags.setColor(SkColorSetARGB(0xAB, 0, 0, 0));
shared_font_->font().DrawBidiText(
@@ -354,26 +357,17 @@ void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
Font::kUseFallbackIfFontNotReady, 1.0f, flags);
}
-void PlaceholderImage::DrawPattern(
- GraphicsContext& context,
- const FloatRect& src_rect,
- const FloatSize& scale,
- const FloatPoint& phase,
- SkBlendMode mode,
- const FloatRect& dest_rect,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum respect_orientation) {
+void PlaceholderImage::DrawPattern(GraphicsContext& context,
+ const PaintFlags& base_flags,
+ const FloatRect& dest_rect,
+ const ImageTilingInfo& tiling_info,
+ const ImageDrawOptions& draw_options) {
DCHECK(context.Canvas());
-
- PaintFlags flags = context.FillFlags();
- flags.setBlendMode(mode);
-
// Ignore the pattern specifications and just draw a single placeholder image
// over the whole |dest_rect|. This is done in order to prevent repeated icons
// from cluttering tiled background images.
- Draw(context.Canvas(), flags, dest_rect, src_rect,
- context.ImageSamplingOptions(), respect_orientation,
- kClampImageToSourceRect, kUnspecifiedDecode);
+ Draw(context.Canvas(), base_flags, dest_rect, tiling_info.image_rect,
+ draw_options, kClampImageToSourceRect, kUnspecifiedDecode);
}
void PlaceholderImage::DestroyDecodedData() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
index 393f12a1a96..9cfa3f3a714 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
@@ -19,9 +19,7 @@
namespace blink {
-class FloatPoint;
class FloatRect;
-class FloatSize;
class Font;
class GraphicsContext;
class ImageObserver;
@@ -40,14 +38,13 @@ class PLATFORM_EXPORT PlaceholderImage final : public Image {
~PlaceholderImage() override;
- IntSize Size() const override;
+ IntSize SizeWithConfig(SizeConfig) const override;
void Draw(cc::PaintCanvas*,
const cc::PaintFlags&,
const FloatRect& dest_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
@@ -72,13 +69,10 @@ class PLATFORM_EXPORT PlaceholderImage final : public Image {
bool CurrentFrameKnownToBeOpaque() override;
void DrawPattern(GraphicsContext&,
- const FloatRect& src_rect,
- const FloatSize& scale,
- const FloatPoint& phase,
- SkBlendMode,
+ const cc::PaintFlags&,
const FloatRect& dest_rect,
- const FloatSize& repeat_spacing,
- RespectImageOrientationEnum) override;
+ const ImageTilingInfo& tiling_info,
+ const ImageDrawOptions& draw_options) override;
// SetData does nothing, and the passed in buffer is ignored.
SizeAvailability SetData(scoped_refptr<SharedBuffer>, bool) override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc
index 7c19ba5143b..10717b04314 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
@@ -75,10 +76,11 @@ void DrawImageExpectingGrayBoxOnly(PlaceholderImage& image,
EXPECT_CALL(canvas, drawImageRect(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(canvas, drawTextBlob(_, _, _, _)).Times(0);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
image.Draw(&canvas, PaintFlags(), dest_rect,
- FloatRect(0.0f, 0.0f, 100.0f, 100.0f), SkSamplingOptions(),
- kRespectImageOrientation, Image::kClampImageToSourceRect,
- Image::kUnspecifiedDecode);
+ FloatRect(0.0f, 0.0f, 100.0f, 100.0f), draw_options,
+ Image::kClampImageToSourceRect, Image::kUnspecifiedDecode);
}
void DrawImageExpectingIconOnly(PlaceholderImage& image,
@@ -108,10 +110,12 @@ void DrawImageExpectingIconOnly(PlaceholderImage& image,
EXPECT_CALL(canvas, drawTextBlob(_, _, _, _)).Times(0);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
+ draw_options.respect_image_orientation = kDoNotRespectImageOrientation;
image.Draw(&canvas, PaintFlags(), dest_rect,
- FloatRect(0.0f, 0.0f, 100.0f, 100.0f), SkSamplingOptions(),
- kDoNotRespectImageOrientation, Image::kClampImageToSourceRect,
- Image::kUnspecifiedDecode);
+ FloatRect(0.0f, 0.0f, 100.0f, 100.0f), draw_options,
+ Image::kClampImageToSourceRect, Image::kUnspecifiedDecode);
}
float GetExpectedPlaceholderTextWidth(const StringView& text,
@@ -198,10 +202,12 @@ void DrawImageExpectingIconAndTextLTR(PlaceholderImage& image,
0.01);
}));
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
+ draw_options.respect_image_orientation = kDoNotRespectImageOrientation;
image.Draw(&canvas, PaintFlags(), dest_rect,
- FloatRect(0.0f, 0.0f, 100.0f, 100.0f), SkSamplingOptions(),
- kDoNotRespectImageOrientation, Image::kClampImageToSourceRect,
- Image::kUnspecifiedDecode);
+ FloatRect(0.0f, 0.0f, 100.0f, 100.0f), draw_options,
+ Image::kClampImageToSourceRect, Image::kUnspecifiedDecode);
}
class TestingUnitsPlatform : public TestingPlatformSupport {
@@ -289,13 +295,15 @@ TEST_F(PlaceholderImageTest, DrawNonIntersectingSrcRect) {
EXPECT_CALL(canvas, drawImageRect(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(canvas, drawTextBlob(_, _, _, _)).Times(0);
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
+ draw_options.respect_image_orientation = kDoNotRespectImageOrientation;
PlaceholderImage::Create(nullptr, IntSize(800, 600), 0)
->Draw(&canvas, PaintFlags(), FloatRect(0.0f, 0.0f, 800.0f, 600.0f),
// The source rectangle is outside the 800x600 bounds of the image,
// so nothing should be drawn.
- FloatRect(1000.0f, 0.0f, 800.0f, 600.0f), SkSamplingOptions(),
- kDoNotRespectImageOrientation, Image::kClampImageToSourceRect,
- Image::kUnspecifiedDecode);
+ FloatRect(1000.0f, 0.0f, 800.0f, 600.0f), draw_options,
+ Image::kClampImageToSourceRect, Image::kUnspecifiedDecode);
}
TEST_F(PlaceholderImageTest, DrawWithoutOriginalResourceSize) {
@@ -451,10 +459,12 @@ TEST_F(PlaceholderImageTest, DrawWithOriginalResourceSizeRTL) {
0.01);
}));
+ ImageDrawOptions draw_options;
+ draw_options.sampling_options = SkSamplingOptions();
+ draw_options.respect_image_orientation = kDoNotRespectImageOrientation;
image->Draw(&canvas, PaintFlags(), dest_rect,
- FloatRect(0.0f, 0.0f, 100.0f, 100.0f), SkSamplingOptions(),
- kDoNotRespectImageOrientation, Image::kClampImageToSourceRect,
- Image::kUnspecifiedDecode);
+ FloatRect(0.0f, 0.0f, 100.0f, 100.0f), draw_options,
+ Image::kClampImageToSourceRect, Image::kUnspecifiedDecode);
}
TEST_F(PlaceholderImageTest, DrawSeparateImageWithDifferentScaleFactor) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/raster_dark_mode_filter_impl.h b/chromium/third_party/blink/renderer/platform/graphics/raster_dark_mode_filter_impl.h
index d0c726167b1..969e67fe1e1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/raster_dark_mode_filter_impl.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/raster_dark_mode_filter_impl.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_RASTER_DARK_MODE_FILTER_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_RASTER_DARK_MODE_FILTER_IMPL_H_
-#include "base/macros.h"
#include "cc/tiles/raster_dark_mode_filter.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_settings.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -20,6 +19,8 @@ class PLATFORM_EXPORT RasterDarkModeFilterImpl
: public cc::RasterDarkModeFilter {
public:
explicit RasterDarkModeFilterImpl(const DarkModeSettings& settings);
+ RasterDarkModeFilterImpl(const RasterDarkModeFilterImpl&) = delete;
+ RasterDarkModeFilterImpl& operator=(const RasterDarkModeFilterImpl&) = delete;
// RasterDarkModeFilter API.
sk_sp<SkColorFilter> ApplyToImage(const SkPixmap& pixmap,
@@ -27,8 +28,6 @@ class PLATFORM_EXPORT RasterDarkModeFilterImpl
private:
std::unique_ptr<DarkModeFilter> dark_mode_filter_;
-
- DISALLOW_COPY_AND_ASSIGN(RasterDarkModeFilterImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.cc
index 5e2c90d2e01..db2452284d4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.cc
@@ -246,6 +246,21 @@ RWBuffer::RWBuffer(size_t initial_capacity) {
}
}
+RWBuffer::RWBuffer(base::OnceCallback<size_t(void*, size_t)> writer,
+ size_t initial_capacity) {
+ if (initial_capacity) {
+ head_ = RWBuffer::BufferHead::Alloc(initial_capacity);
+ tail_ = &head_->block_;
+ }
+
+ size_t written = std::move(writer).Run(const_cast<void*>(tail_->startData()),
+ initial_capacity);
+ total_used_ += written;
+ tail_->used_ += written;
+
+ Validate();
+}
+
RWBuffer::~RWBuffer() {
Validate();
if (head_) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.h
index 3a357dd4497..2387403d4b7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/rw_buffer.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_RW_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_RW_BUFFER_H_
+#include "base/callback.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
@@ -42,6 +43,12 @@ class PLATFORM_EXPORT RWBuffer {
};
explicit RWBuffer(size_t initialCapacity = 0);
+ // |writer| is a function used to initialize the RWBuffer.
+ // |writer| is responsible for not writing off the edge of the buffer.
+ // |writer| should return the amount of memory written to the buffer.
+ RWBuffer(base::OnceCallback<size_t(void*, size_t)> writer,
+ size_t initial_capacity);
+
~RWBuffer();
RWBuffer& operator=(const RWBuffer&) = delete;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/rw_buffer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/rw_buffer_test.cc
index 6143a0156df..a7662c96811 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/rw_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/rw_buffer_test.cc
@@ -39,12 +39,22 @@ void check_alphabet_buffer(const ROBuffer* reader) {
check_abcs(storage.data(), size);
}
+size_t write_into_buffer(size_t reps, void* buffer, size_t capacity) {
+ size_t len = std::min(capacity, reps * sizeof(gABC));
+ for (size_t i = 0; i < len; i += 26U) {
+ memcpy(static_cast<char*>(buffer) + i, gABC,
+ std::min<size_t>(26U, len - i));
+ }
+ return len;
+}
+
class ROBufferTestThread : public base::PlatformThread::Delegate {
public:
ROBufferTestThread(scoped_refptr<ROBuffer> reader, size_t i)
: reader_(reader), i_(i) {}
ROBufferTestThread() = default;
ROBufferTestThread(const ROBufferTestThread&) = default;
+ ROBufferTestThread& operator=(const ROBufferTestThread&) = default;
void ThreadMain() override {
EXPECT_EQ((i_ + 1) * 26U, reader_->size());
@@ -159,7 +169,7 @@ TEST(RWBufferTest, HasNoSnapshotsEmpty) {
}
// Tests that |HasNoSnapshots| returns the correct value when the buffer is
-// empty.
+// non-empty.
TEST(RWBufferTest, HasNoSnapshots) {
RWBuffer buffer;
ASSERT_EQ(0u, buffer.size());
@@ -169,8 +179,10 @@ TEST(RWBufferTest, HasNoSnapshots) {
EXPECT_TRUE(buffer.HasNoSnapshots());
{
- scoped_refptr<ROBuffer> first = buffer.MakeROBufferSnapshot();
- EXPECT_FALSE(buffer.HasNoSnapshots());
+ {
+ scoped_refptr<ROBuffer> first = buffer.MakeROBufferSnapshot();
+ EXPECT_FALSE(buffer.HasNoSnapshots());
+ }
scoped_refptr<ROBuffer> second = buffer.MakeROBufferSnapshot();
EXPECT_FALSE(buffer.HasNoSnapshots());
@@ -179,4 +191,23 @@ TEST(RWBufferTest, HasNoSnapshots) {
EXPECT_TRUE(buffer.HasNoSnapshots());
}
+TEST(RWBufferTest, FunctionConstructorSmall) {
+ RWBuffer buffer(base::BindOnce(&write_into_buffer, 1), 20);
+
+ EXPECT_EQ(20U, buffer.size());
+
+ scoped_refptr<ROBuffer> roBuffer = buffer.MakeROBufferSnapshot();
+ ROBuffer::Iter iter(roBuffer.get());
+ EXPECT_EQ(0, memcmp(iter.data(), gABC, 20U));
+}
+
+TEST(RWBufferTest, FunctionConstructorLarge) {
+ RWBuffer buffer(base::BindOnce(&write_into_buffer, 1000), 1000 * 26);
+
+ EXPECT_EQ(1000U * 26, buffer.size());
+
+ auto ro_buffer = buffer.MakeROBufferSnapshot();
+ check_alphabet_buffer(ro_buffer.get());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.cc b/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.cc
index 55b62f32cc0..c7279275891 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.cc
@@ -51,7 +51,8 @@ ImagePixelLocker::ImagePixelLocker(sk_sp<const SkImage> image,
if (0 == size)
return;
- pixel_storage_.resize(size); // this will throw on failure
+ // this will throw on failure
+ pixel_storage_.resize(base::checked_cast<wtf_size_t>(size));
pixmap.reset(info, pixel_storage_.data(), row_bytes);
if (!image_->readPixels(pixmap, 0, 0))
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 1369ad7fc72..bedbb3902c9 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,7 +5,6 @@
#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/allocator.h"
@@ -22,6 +21,8 @@ class ImagePixelLocker final {
public:
ImagePixelLocker(sk_sp<const SkImage>, SkAlphaType, SkColorType);
+ ImagePixelLocker(const ImagePixelLocker&) = delete;
+ ImagePixelLocker& operator=(const ImagePixelLocker&) = delete;
const void* Pixels() const { return pixels_; }
@@ -29,8 +30,6 @@ 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 71afa00c65d..3a72d9812cd 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
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "base/allocator/partition_allocator/partition_alloc.h"
+#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
@@ -354,7 +355,8 @@ InterpolationQuality ComputeInterpolationQuality(float src_width,
SkColor ScaleAlpha(SkColor color, float alpha) {
const auto clamped_alpha = std::max(0.0f, std::min(1.0f, alpha));
- const auto rounded_alpha = std::lround(SkColorGetA(color) * clamped_alpha);
+ const auto rounded_alpha =
+ base::ClampRound<U8CPU>(SkColorGetA(color) * clamped_alpha);
return SkColorSetA(color, rounded_alpha);
}
@@ -378,83 +380,35 @@ SkRect LayoutRectToSkRect(const blink::LayoutRect& rect) {
SkFloatToScalar(rect.Height()));
}
-template <typename PrimitiveType>
-void DrawFocusRingPrimitive(const PrimitiveType&,
- cc::PaintCanvas*,
- const PaintFlags&,
- float corner_radius) {
- NOTREACHED(); // Missing an explicit specialization?
-}
-
-template <>
-void DrawFocusRingPrimitive<SkRect>(const SkRect& rect,
- cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- float corner_radius) {
- SkRRect rrect;
- rrect.setRectXY(rect, SkFloatToScalar(corner_radius),
- SkFloatToScalar(corner_radius));
- canvas->drawRRect(rrect, flags);
+static PaintFlags PaintFlagsForFocusRing(SkColor color, float width) {
+ PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setStyle(PaintFlags::kStroke_Style);
+ flags.setColor(color);
+ flags.setStrokeWidth(width);
+ return flags;
}
-template <>
-void DrawFocusRingPrimitive<SkPath>(const SkPath& path,
- cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- float corner_radius) {
- PaintFlags path_flags = flags;
- path_flags.setPathEffect(
- SkCornerPathEffect::Make(SkFloatToScalar(corner_radius)));
- canvas->drawPath(path, path_flags);
+void DrawPlatformFocusRing(const SkRRect& rrect,
+ cc::PaintCanvas* canvas,
+ SkColor color,
+ float width) {
+ canvas->drawRRect(rrect, PaintFlagsForFocusRing(color, width));
}
-template <typename PrimitiveType>
-void DrawPlatformFocusRing(const PrimitiveType& primitive,
+void DrawPlatformFocusRing(const SkPath& path,
cc::PaintCanvas* canvas,
SkColor color,
float width,
- float border_radius) {
- PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setStyle(PaintFlags::kStroke_Style);
- flags.setColor(color);
- flags.setStrokeWidth(width);
-
- if (::features::IsFormControlsRefreshEnabled()) {
- DrawFocusRingPrimitive(primitive, canvas, flags, border_radius);
- return;
+ float corner_radius) {
+ PaintFlags path_flags = PaintFlagsForFocusRing(color, width);
+ if (corner_radius) {
+ path_flags.setPathEffect(
+ SkCornerPathEffect::Make(SkFloatToScalar(corner_radius)));
}
-
-#if defined(OS_MAC)
- flags.setAlpha(64);
- const float corner_radius = (width - 1) * 0.5f;
-#else
- const float corner_radius = width;
-#endif
-
- DrawFocusRingPrimitive(primitive, canvas, flags, corner_radius);
-
-#if defined(OS_MAC)
- // Inner part
- flags.setAlpha(128);
- flags.setStrokeWidth(flags.getStrokeWidth() * 0.5f);
- DrawFocusRingPrimitive(primitive, canvas, flags, corner_radius);
-#endif
+ canvas->drawPath(path, path_flags);
}
-template void PLATFORM_EXPORT
-DrawPlatformFocusRing<SkRect>(const SkRect&,
- cc::PaintCanvas*,
- SkColor,
- float width,
- float border_radius);
-template void PLATFORM_EXPORT
-DrawPlatformFocusRing<SkPath>(const SkPath&,
- cc::PaintCanvas*,
- SkColor,
- float width,
- float border_radius);
-
sk_sp<SkData> TryAllocateSkData(size_t size) {
void* buffer = WTF::Partitions::BufferPartition()->AllocFlags(
base::PartitionAllocReturnNull | base::PartitionAllocZeroFill, size,
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 997893fef2c..0b3efb14964 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
@@ -142,12 +142,15 @@ inline float BlurRadiusToStdDev(float radius) {
return radius * 0.5f;
}
-template <typename PrimitiveType>
-void DrawPlatformFocusRing(const PrimitiveType&,
- cc::PaintCanvas*,
- SkColor,
- float width,
- float border_radius);
+void PLATFORM_EXPORT DrawPlatformFocusRing(const SkRRect&,
+ cc::PaintCanvas*,
+ SkColor,
+ float width);
+void PLATFORM_EXPORT DrawPlatformFocusRing(const SkPath&,
+ cc::PaintCanvas*,
+ SkColor,
+ float width,
+ float corner_radius);
inline SkCanvas::SrcRectConstraint WebCoreClampingModeToSkiaRectConstraint(
Image::ImageClampingMode clamp_mode) {
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 631a02551cb..c7f4210838b 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
@@ -35,11 +35,11 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
orientation);
}
-IntSize StaticBitmapImage::PreferredDisplaySize() const {
- if (orientation_.UsesWidthAsHeight())
- return Size().TransposedSize();
- else
- return Size();
+IntSize StaticBitmapImage::SizeWithConfig(SizeConfig config) const {
+ IntSize size = SizeInternal();
+ if (config.apply_orientation && orientation_.UsesWidthAsHeight())
+ size = size.TransposedSize();
+ return size;
}
void StaticBitmapImage::DrawHelper(
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 54b0b002396..57bc37ec799 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
@@ -21,6 +21,7 @@ class GLES2Interface;
} // namespace gpu
namespace blink {
+class CanvasResourceProvider;
class PLATFORM_EXPORT StaticBitmapImage : public Image {
public:
@@ -40,7 +41,7 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
// Methods overridden by all sub-classes
~StaticBitmapImage() override = default;
- IntSize PreferredDisplaySize() const override;
+ IntSize SizeWithConfig(SizeConfig) const final;
virtual scoped_refptr<StaticBitmapImage> ConvertToColorSpace(
sk_sp<SkColorSpace>,
@@ -74,6 +75,11 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
return false;
}
+ virtual bool CopyToResourceProvider(CanvasResourceProvider*) {
+ NOTREACHED();
+ return false;
+ }
+
virtual void EnsureSyncTokenVerified() { NOTREACHED(); }
virtual gpu::MailboxHolder GetMailboxHolder() const {
NOTREACHED();
@@ -92,9 +98,6 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
ImageOrientation CurrentFrameOrientation() const override {
return orientation_;
}
- bool HasDefaultOrientation() const override {
- return orientation_ == ImageOrientationEnum::kDefault;
- }
void SetOrientation(ImageOrientation orientation) {
orientation_ = orientation;
@@ -111,6 +114,8 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
RespectImageOrientationEnum,
const PaintImage&);
+ virtual IntSize SizeInternal() const = 0;
+
// The image orientation is stored here because it is only available when the
// static image is created and the underlying representations do not store
// the information. The property is set at construction based on the source of
diff --git a/chromium/third_party/blink/renderer/platform/graphics/stroke_data.cc b/chromium/third_party/blink/renderer/platform/graphics/stroke_data.cc
index 67c5002c155..ceeffb0db75 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/stroke_data.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/stroke_data.cc
@@ -37,7 +37,7 @@ namespace blink {
void StrokeData::SetLineDash(const DashArray& dashes, float dash_offset) {
// FIXME: This is lifted directly off SkiaSupport, lines 49-74
// so it is not guaranteed to work correctly.
- size_t dash_length = dashes.size();
+ wtf_size_t dash_length = dashes.size();
if (!dash_length) {
// If no dash is set, revert to solid stroke
// FIXME: do we need to set NoStroke in some cases?
@@ -46,10 +46,10 @@ void StrokeData::SetLineDash(const DashArray& dashes, float dash_offset) {
return;
}
- size_t count = !(dash_length % 2) ? dash_length : dash_length * 2;
+ wtf_size_t count = !(dash_length % 2) ? dash_length : dash_length * 2;
auto intervals = std::make_unique<SkScalar[]>(count);
- for (unsigned i = 0; i < count; i++)
+ for (wtf_size_t i = 0; i < count; i++)
intervals[i] = dashes[i % dash_length];
dash_ = SkDashPathEffect::Make(intervals.get(), count, dash_offset);
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 f4a9de25760..f9dc7fd49dd 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
@@ -8,6 +8,8 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
@@ -65,7 +67,7 @@ UnacceleratedStaticBitmapImage::~UnacceleratedStaticBitmapImage() {
}
}
-IntSize UnacceleratedStaticBitmapImage::Size() const {
+IntSize UnacceleratedStaticBitmapImage::SizeInternal() const {
return IntSize(paint_image_.width(), paint_image_.height());
}
@@ -77,18 +79,17 @@ bool UnacceleratedStaticBitmapImage::CurrentFrameKnownToBeOpaque() {
return paint_image_.IsOpaque();
}
-void UnacceleratedStaticBitmapImage::Draw(
- cc::PaintCanvas* canvas,
- const cc::PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- const SkSamplingOptions& sampling,
- RespectImageOrientationEnum should_respect_image_orientation,
- ImageClampingMode clamp_mode,
- ImageDecodingMode) {
+void UnacceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ const ImageDrawOptions& draw_options,
+ ImageClampingMode clamp_mode,
+ ImageDecodingMode) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect, sampling,
- clamp_mode, should_respect_image_orientation,
+ StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect,
+ draw_options.sampling_options, clamp_mode,
+ draw_options.respect_image_orientation,
PaintImageForCurrentFrame());
}
@@ -120,4 +121,35 @@ UnacceleratedStaticBitmapImage::ConvertToColorSpace(
return UnacceleratedStaticBitmapImage::Create(skia_image, orientation_);
}
+bool UnacceleratedStaticBitmapImage::CopyToResourceProvider(
+ CanvasResourceProvider* resource_provider) {
+ DCHECK(resource_provider);
+
+ sk_sp<SkImage> image = paint_image_.GetSwSkImage();
+ if (!image)
+ return false;
+
+ SkPixmap pixmap;
+ if (!image->peekPixels(&pixmap))
+ return false;
+
+ const void* pixels = pixmap.addr();
+ const size_t row_bytes = pixmap.rowBytes();
+ std::vector<uint8_t> flipped;
+ DCHECK(IsOriginTopLeft());
+ if (!resource_provider->IsOriginTopLeft()) {
+ const int height = pixmap.height();
+ flipped.resize(row_bytes * height);
+ for (int i = 0; i < height; ++i) {
+ memcpy(flipped.data() + i * row_bytes,
+ static_cast<const uint8_t*>(pixels) + (height - 1 - i) * row_bytes,
+ row_bytes);
+ }
+ pixels = flipped.data();
+ }
+
+ return resource_provider->WritePixels(pixmap.info(), pixels, row_bytes,
+ /*x=*/0, /*y=*/0);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
index 68da7c547c1..698ec8cecee 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
@@ -27,7 +27,6 @@ class PLATFORM_EXPORT UnacceleratedStaticBitmapImage final
ImageOrientation orientation = ImageOrientationEnum::kDefault);
bool CurrentFrameKnownToBeOpaque() override;
- IntSize Size() const override;
bool IsPremultiplied() const override;
scoped_refptr<StaticBitmapImage> ConvertToColorSpace(sk_sp<SkColorSpace>,
SkColorType) override;
@@ -36,8 +35,7 @@ class PLATFORM_EXPORT UnacceleratedStaticBitmapImage final
const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
- const SkSamplingOptions&,
- RespectImageOrientationEnum,
+ const ImageDrawOptions& draw_options,
ImageClampingMode,
ImageDecodingMode) override;
@@ -45,10 +43,14 @@ class PLATFORM_EXPORT UnacceleratedStaticBitmapImage final
void Transfer() final;
+ bool CopyToResourceProvider(CanvasResourceProvider*) override;
+
private:
UnacceleratedStaticBitmapImage(sk_sp<SkImage>, ImageOrientation);
UnacceleratedStaticBitmapImage(PaintImage, ImageOrientation);
+ IntSize SizeInternal() const override;
+
PaintImage paint_image_;
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc
index 274c9f1117e..37b1f829c29 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc
@@ -174,7 +174,8 @@ scoped_refptr<StaticBitmapImage> CreateImageFromVideoFrame(
return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
frame->mailbox_holder(0).mailbox, frame->mailbox_holder(0).sync_token,
- 0u, sk_image_info, frame->mailbox_holder(0).texture_target, true,
+ 0u, sk_image_info, frame->mailbox_holder(0).texture_target,
+ frame->metadata().texture_origin_is_top_left,
// Pass nullptr for |context_provider_wrapper|, because we don't
// know which context the mailbox came from. It is used only to
// detect when the mailbox is invalid due to context loss, and is
@@ -268,7 +269,7 @@ bool DrawVideoFrameIntoResourceProvider(
cc::PaintFlags media_flags;
media_flags.setAlpha(0xFF);
- media_flags.setFilterQuality(kLow_SkFilterQuality);
+ media_flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
media_flags.setBlendMode(SkBlendMode::kSrc);
std::unique_ptr<media::PaintCanvasVideoRenderer> local_video_renderer;
@@ -299,12 +300,12 @@ std::unique_ptr<CanvasResourceProvider> CreateResourceProviderForVideoFrame(
viz::RasterContextProvider* raster_context_provider) {
if (!ShouldCreateAcceleratedImages(raster_context_provider)) {
return CanvasResourceProvider::CreateBitmapProvider(
- size, kLow_SkFilterQuality, CanvasResourceParams(),
+ size, cc::PaintFlags::FilterQuality::kLow, CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kNo);
}
return CanvasResourceProvider::CreateSharedImageProvider(
- size, kLow_SkFilterQuality, CanvasResourceParams(),
+ size, cc::PaintFlags::FilterQuality::kLow, CanvasResourceParams(),
CanvasResourceProvider::ShouldInitialize::kNo,
SharedGpuContext::ContextProviderWrapper(), RasterMode::kGPU,
false, // Origin of GL texture is bottom left on screen
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 cae2919886b..7fff6982941 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
@@ -66,7 +66,7 @@ void VideoFrameResourceProvider::OnContextLost() {
void VideoFrameResourceProvider::AppendQuads(
viz::CompositorRenderPass* render_pass,
scoped_refptr<media::VideoFrame> frame,
- media::VideoRotation rotation,
+ media::VideoTransformation media_transform,
bool is_opaque) {
TRACE_EVENT0("media", "VideoFrameResourceProvider::AppendQuads");
DCHECK(resource_updater_);
@@ -86,28 +86,34 @@ void VideoFrameResourceProvider::AppendQuads(
resource_updater_->ObtainFrameResources(frame);
}
- gfx::Transform transform = gfx::Transform();
+ auto transform = gfx::Transform();
+
// The quad's rect is in pre-transform space so that applying the transform on
// it will produce the bounds in target space.
- gfx::Rect quad_rect = gfx::Rect(frame->natural_size());
+ auto quad_rect = gfx::Rect(frame->natural_size());
- switch (rotation) {
+ switch (media_transform.rotation) {
case media::VIDEO_ROTATION_90:
- transform.Rotate(90.0);
- transform.Translate(0.0, -quad_rect.height());
+ transform.RotateAboutZAxis(90.0);
+ transform.Translate(0, -quad_rect.height());
break;
case media::VIDEO_ROTATION_180:
- transform.Rotate(180.0);
+ transform.RotateAboutZAxis(180.0);
transform.Translate(-quad_rect.width(), -quad_rect.height());
break;
case media::VIDEO_ROTATION_270:
- transform.Rotate(270.0);
+ transform.RotateAboutZAxis(270.0);
transform.Translate(-quad_rect.width(), 0);
break;
case media::VIDEO_ROTATION_0:
break;
}
+ if (media_transform.mirrored) {
+ transform.RotateAboutYAxis(180.0);
+ transform.Translate(-quad_rect.width(), 0);
+ }
+
gfx::Rect visible_quad_rect = quad_rect;
gfx::MaskFilterInfo mask_filter_info;
float draw_opacity = 1.0f;
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 7a76c94af7c..efaa452d272 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
@@ -44,7 +44,7 @@ class PLATFORM_EXPORT VideoFrameResourceProvider {
viz::SharedBitmapReporter* shared_bitmap_reporter);
virtual void AppendQuads(viz::CompositorRenderPass*,
scoped_refptr<media::VideoFrame>,
- media::VideoRotation,
+ media::VideoTransformation,
bool is_opaque);
virtual void ReleaseFrameResources();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.cc
new file mode 100644
index 00000000000..0f9aafb30ce
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.cc
@@ -0,0 +1,270 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h"
+
+#include <memory>
+#include <tuple>
+#include <utility>
+
+#include "base/check.h"
+#include "base/containers/flat_map.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h"
+#include "third_party/blink/renderer/platform/graphics/viz_util.h"
+#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
+
+namespace blink {
+
+namespace {
+
+// We keep a thread-local map of VideoFrameSinkBundles, keyed by parent
+// FrameSinkId and whether or not the submitter is a media stream.
+using BundleKey = std::tuple<viz::FrameSinkId, bool>;
+
+// NOTE: We use flat_map because of the odd key type, relatively small
+// expected size, and relatively infrequent insertions and deletions.
+using FrameSinkBundleMap =
+ base::flat_map<BundleKey, std::unique_ptr<VideoFrameSinkBundle>>;
+
+FrameSinkBundleMap& GetThreadFrameSinkBundleMap() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<FrameSinkBundleMap>, bundles,
+ ());
+ return *bundles;
+}
+
+} // namespace
+
+VideoFrameSinkBundle::VideoFrameSinkBundle(
+ base::PassKey<VideoFrameSinkBundle>,
+ mojom::blink::EmbeddedFrameSinkProvider& provider,
+ const viz::FrameSinkId& parent_frame_sink_id,
+ bool for_media_streams)
+ : parent_frame_sink_id_(parent_frame_sink_id),
+ for_media_streams_(for_media_streams) {
+ ConnectNewBundle(provider);
+}
+
+VideoFrameSinkBundle::~VideoFrameSinkBundle() = default;
+
+// static
+VideoFrameSinkBundle& VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ mojom::blink::EmbeddedFrameSinkProvider& provider,
+ const viz::FrameSinkId& parent_frame_sink_id,
+ bool for_media_stream) {
+ const BundleKey key(parent_frame_sink_id, for_media_stream);
+ auto& bundle = GetThreadFrameSinkBundleMap()[key];
+ if (!bundle) {
+ bundle = std::make_unique<VideoFrameSinkBundle>(
+ base::PassKey<VideoFrameSinkBundle>(), provider, parent_frame_sink_id,
+ for_media_stream);
+ } else if (bundle->is_context_lost()) {
+ bundle->ConnectNewBundle(provider);
+ }
+ return *bundle;
+}
+
+// static
+VideoFrameSinkBundle* VideoFrameSinkBundle::GetSharedInstanceForTesting(
+ const viz::FrameSinkId& parent_frame_sink_id,
+ bool for_media_stream) {
+ const BundleKey key(parent_frame_sink_id, for_media_stream);
+ auto& bundles = GetThreadFrameSinkBundleMap();
+ auto it = bundles.find(key);
+ if (it == bundles.end()) {
+ return nullptr;
+ }
+ DCHECK(it->second);
+ return it->second.get();
+}
+
+// static
+void VideoFrameSinkBundle::DestroySharedInstancesForTesting() {
+ GetThreadFrameSinkBundleMap().clear();
+}
+
+void VideoFrameSinkBundle::AddClient(
+ const viz::FrameSinkId& id,
+ viz::mojom::blink::CompositorFrameSinkClient* client,
+ mojo::Remote<viz::mojom::blink::CompositorFrameSink>& sink) {
+ clients_.Set(id.sink_id(), client);
+
+ // This serves as a synchronization barrier, blocking the bundle from
+ // receiving any new messages until the service-side CompositorFrameSinkImpl
+ // has been bound for this frame sink.
+ bundle_.PauseReceiverUntilFlushCompletes(sink.FlushAsync());
+}
+
+void VideoFrameSinkBundle::RemoveClient(const viz::FrameSinkId& frame_sink_id) {
+ clients_.erase(frame_sink_id.sink_id());
+ if (!clients_.IsEmpty()) {
+ return;
+ }
+
+ // No more clients, so self-delete.
+ GetThreadFrameSinkBundleMap().erase(
+ BundleKey(parent_frame_sink_id_, for_media_streams_));
+}
+
+void VideoFrameSinkBundle::OnContextLost(
+ const viz::FrameSinkBundleId& bundle_id) {
+ if (bundle_id != id_) {
+ // If this context loss report is regarding a previously used bundle ID,
+ // we can ignore it. Someone else in the bundle already reported it and
+ // we've since connected a new bundle.
+ return;
+ }
+
+ is_context_lost_ = true;
+}
+
+void VideoFrameSinkBundle::InitializeCompositorFrameSinkType(
+ uint32_t sink_id,
+ viz::mojom::blink::CompositorFrameSinkType type) {
+ bundle_->InitializeCompositorFrameSinkType(sink_id, type);
+}
+
+void VideoFrameSinkBundle::SetNeedsBeginFrame(uint32_t sink_id,
+ bool needs_begin_frame) {
+ // These messages are not sent often, so we don't bother batching them.
+ bundle_->SetNeedsBeginFrame(sink_id, needs_begin_frame);
+}
+
+void VideoFrameSinkBundle::SubmitCompositorFrame(
+ uint32_t sink_id,
+ const viz::LocalSurfaceId& local_surface_id,
+ viz::CompositorFrame frame,
+ absl::optional<viz::HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time) {
+ auto bundled_frame = viz::mojom::blink::BundledCompositorFrame::New();
+ bundled_frame->local_surface_id = local_surface_id;
+ bundled_frame->frame = std::move(frame);
+ bundled_frame->hit_test_region_list = std::move(hit_test_region_list);
+ bundled_frame->submit_time = submit_time;
+
+ auto submission = viz::mojom::blink::BundledFrameSubmission::New();
+ submission->sink_id = sink_id;
+ submission->data = viz::mojom::blink::BundledFrameSubmissionData::NewFrame(
+ std::move(bundled_frame));
+
+ // Note that we generally expect this call to be nested while processing
+ // OnBeginFrame() notifications, rather than at a delayed time in the future.
+ // This will happen while nested within FlushNotifications(), where
+ // `defer_submissions_` is true.
+ submission_queue_.push_back(std::move(submission));
+ if (!defer_submissions_) {
+ FlushMessages();
+ }
+}
+
+void VideoFrameSinkBundle::DidNotProduceFrame(uint32_t sink_id,
+ const viz::BeginFrameAck& ack) {
+ auto submission = viz::mojom::blink::BundledFrameSubmission::New();
+ submission->sink_id = sink_id;
+ submission->data =
+ viz::mojom::blink::BundledFrameSubmissionData::NewDidNotProduceFrame(ack);
+
+ // See the note in SubmitCompositorFrame above regarding queueing.
+ submission_queue_.push_back(std::move(submission));
+ if (!defer_submissions_) {
+ FlushMessages();
+ }
+}
+
+void VideoFrameSinkBundle::DidAllocateSharedBitmap(
+ uint32_t sink_id,
+ base::ReadOnlySharedMemoryRegion region,
+ const gpu::Mailbox& id) {
+ bundle_->DidAllocateSharedBitmap(sink_id, std::move(region), id);
+}
+
+void VideoFrameSinkBundle::DidDeleteSharedBitmap(uint32_t sink_id,
+ const gpu::Mailbox& id) {
+ // These messages are not urgent, but they must be well-ordered with respect
+ // to frame submissions. Hence they are batched in the same queue and
+ // flushed whenever any other messages are fit to flush.
+ submission_queue_.push_back(viz::mojom::blink::BundledFrameSubmission::New(
+ sink_id,
+ viz::mojom::blink::BundledFrameSubmissionData::NewDidDeleteSharedBitmap(
+ id)));
+}
+
+void VideoFrameSinkBundle::FlushNotifications(
+ WTF::Vector<viz::mojom::blink::BundledReturnedResourcesPtr> acks,
+ WTF::Vector<viz::mojom::blink::BeginFrameInfoPtr> begin_frames,
+ WTF::Vector<viz::mojom::blink::BundledReturnedResourcesPtr>
+ reclaimed_resources) {
+ for (const auto& entry : acks) {
+ auto it = clients_.find(entry->sink_id);
+ if (it == clients_.end())
+ continue;
+ it->value->DidReceiveCompositorFrameAck(std::move(entry->resources));
+ }
+
+ for (const auto& entry : reclaimed_resources) {
+ auto it = clients_.find(entry->sink_id);
+ if (it == clients_.end())
+ continue;
+ it->value->ReclaimResources(std::move(entry->resources));
+ }
+
+ // When OnBeginFrame() is invoked on each client, the client will typically
+ // call back into us with either SubmitCompositorFrame or
+ // DidNotProduceFrame. Setting `defer_submissions_` to true here ensures
+ // that we'll queue those calls rather than letting them send IPC directly.
+ // Then a single batch IPC is sent with all of these at the end, via
+ // FlushMessages() below.
+ defer_submissions_ = true;
+ for (auto& entry : begin_frames) {
+ auto it = clients_.find(entry->sink_id);
+ if (it == clients_.end())
+ continue;
+ it->value->OnBeginFrame(std::move(entry->args), std::move(entry->details));
+ }
+ defer_submissions_ = false;
+
+ FlushMessages();
+}
+
+void VideoFrameSinkBundle::OnBeginFramePausedChanged(uint32_t sink_id,
+ bool paused) {
+ auto it = clients_.find(sink_id);
+ if (it == clients_.end())
+ return;
+
+ it->value->OnBeginFramePausedChanged(paused);
+}
+
+void VideoFrameSinkBundle::OnCompositorFrameTransitionDirectiveProcessed(
+ uint32_t sink_id,
+ uint32_t sequence_id) {
+ auto it = clients_.find(sink_id);
+ if (it == clients_.end())
+ return;
+
+ it->value->OnCompositorFrameTransitionDirectiveProcessed(sequence_id);
+}
+
+void VideoFrameSinkBundle::ConnectNewBundle(
+ mojom::blink::EmbeddedFrameSinkProvider& provider) {
+ DCHECK(!bundle_ || is_context_lost_);
+ is_context_lost_ = false;
+ bundle_.reset();
+ receiver_.reset();
+ id_ = GenerateFrameSinkBundleId(parent_frame_sink_id_);
+ provider.RegisterEmbeddedFrameSinkBundle(
+ parent_frame_sink_id_, id_, bundle_.BindNewPipeAndPassReceiver(),
+ receiver_.BindNewPipeAndPassRemote());
+}
+
+void VideoFrameSinkBundle::FlushMessages() {
+ if (submission_queue_.IsEmpty()) {
+ return;
+ }
+
+ WTF::Vector<viz::mojom::blink::BundledFrameSubmissionPtr> submissions;
+ std::swap(submissions, submission_queue_);
+ bundle_->Submit(std::move(submissions));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h b/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h
new file mode 100644
index 00000000000..3af4bff1308
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h
@@ -0,0 +1,140 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SINK_BUNDLE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SINK_BUNDLE_H_
+
+#include <stdint.h>
+
+#include "base/types/pass_key.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/hit_test/hit_test_region_list.h"
+#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/surfaces/frame_sink_bundle_id.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink-forward.h"
+#include "services/viz/public/mojom/compositing/frame_sink_bundle.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.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/vector.h"
+
+namespace blink {
+
+// Encapsulates a thread-local FrameSinkBundle connection for a given parent
+// FrameSinkId which contains one or more VideoFrameSubmitters. This is
+// responsible for demultiplexing batched communication from Viz, as well as for
+// aggregating and apporopriately batching most outgoing communication to Viz on
+// behalf of each VideoFrameSubmitter.
+class PLATFORM_EXPORT VideoFrameSinkBundle
+ : public viz::mojom::blink::FrameSinkBundleClient {
+ public:
+ VideoFrameSinkBundle(base::PassKey<VideoFrameSinkBundle>,
+ mojom::blink::EmbeddedFrameSinkProvider& provider,
+ const viz::FrameSinkId& parent_frame_sink_id,
+ bool for_media_streams);
+
+ VideoFrameSinkBundle(const VideoFrameSinkBundle&) = delete;
+ VideoFrameSinkBundle& operator=(const VideoFrameSinkBundle&) = delete;
+ ~VideoFrameSinkBundle() override;
+
+ // Acquires a lazily initialized VideoFrameSinkBundle instance dedicated to
+ // the given parent FrameSinkId and submitter type (media stream submitters vs
+ // video submitters cannot be bundled together) for the calling thread. If a
+ // matching instance already exists for these parameters it is reused;
+ // otherwise if a new FrameSinkBundle connection to Viz must be established
+ // for this object, it is done using `provider`.
+ static VideoFrameSinkBundle& GetOrCreateSharedInstance(
+ mojom::blink::EmbeddedFrameSinkProvider& provider,
+ const viz::FrameSinkId& parent_frame_sink_id,
+ bool for_media_streams);
+
+ // Acquires an instance that would be returned by GetOrCreateSharedInstance
+ // for the same parameters, but does not create an appropriate instance if one
+ // does not exist. Instead, this returns null in that case.
+ static VideoFrameSinkBundle* GetSharedInstanceForTesting(
+ const viz::FrameSinkId& parent_frame_sink_id,
+ bool for_media_streams);
+
+ // Ensures that all shared instances are torn down.
+ static void DestroySharedInstancesForTesting();
+
+ const viz::FrameSinkBundleId& bundle_id() const { return id_; }
+ bool is_context_lost() const { return is_context_lost_; }
+
+ // Adds a new client to this bundle, to receive batch notifications from Viz.
+ // `client` must outlive this object or be explicitly removed by
+ // RemoveClient() before being destroyed.
+ void AddClient(const viz::FrameSinkId& id,
+ viz::mojom::blink::CompositorFrameSinkClient* client,
+ mojo::Remote<viz::mojom::blink::CompositorFrameSink>& sink);
+ void RemoveClient(const viz::FrameSinkId& id);
+
+ // Notifies the bundle that one of its clients has been disconnected from Viz.
+ // `bundle_id` indicates the bundle ID that was in use by this object at the
+ // time the client was added, and is used to differentiate meaningful new
+ // disconnection events from stale ones already observed by this object.
+ void OnContextLost(const viz::FrameSinkBundleId& bundle_id);
+
+ // Helper methods used by VideoFrameSubmitters to communicate potentially
+ // batched requests to Viz. These correspond closely to methods on the
+ // CompositorFrameSink interface.
+ void InitializeCompositorFrameSinkType(
+ uint32_t sink_id,
+ viz::mojom::blink::CompositorFrameSinkType);
+ void SetNeedsBeginFrame(uint32_t sink_id, bool needs_begin_frame);
+ void SubmitCompositorFrame(
+ uint32_t sink_id,
+ const viz::LocalSurfaceId& local_surface_id,
+ viz::CompositorFrame frame,
+ absl::optional<viz::HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time);
+ void DidNotProduceFrame(uint32_t sink_id, const viz::BeginFrameAck& ack);
+ void DidAllocateSharedBitmap(uint32_t sink_id,
+ base::ReadOnlySharedMemoryRegion region,
+ const gpu::Mailbox& id);
+ void DidDeleteSharedBitmap(uint32_t sink_id, const gpu::Mailbox& id);
+
+ // viz::mojom::blink::FrameSinkBundleClient implementation:
+ void FlushNotifications(
+ WTF::Vector<viz::mojom::blink::BundledReturnedResourcesPtr> acks,
+ WTF::Vector<viz::mojom::blink::BeginFrameInfoPtr> begin_frames,
+ WTF::Vector<viz::mojom::blink::BundledReturnedResourcesPtr>
+ reclaimed_resources) override;
+ void OnBeginFramePausedChanged(uint32_t sink_id, bool paused) override;
+ void OnCompositorFrameTransitionDirectiveProcessed(
+ uint32_t sink_id,
+ uint32_t sequence_id) override;
+
+ private:
+ // Connects (or re-connects) to Viz to grant this object control over a unique
+ // FrameSinkBundle/Client interface connection. Must only be called on a newly
+ // initialized VideoFrameSinkBundle, or once the bundle's context has been
+ // lost.
+ void ConnectNewBundle(mojom::blink::EmbeddedFrameSinkProvider& provider);
+
+ void FlushMessages();
+
+ const viz::FrameSinkId parent_frame_sink_id_;
+ const bool for_media_streams_;
+
+ viz::FrameSinkBundleId id_;
+ bool is_context_lost_ = false;
+ mojo::Remote<viz::mojom::blink::FrameSinkBundle> bundle_;
+ mojo::Receiver<viz::mojom::blink::FrameSinkBundleClient> receiver_{this};
+ WTF::HashMap<uint32_t, viz::mojom::blink::CompositorFrameSinkClient*>
+ clients_;
+
+ bool defer_submissions_ = false;
+ WTF::Vector<viz::mojom::blink::BundledFrameSubmissionPtr> submission_queue_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SINK_BUNDLE_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc
new file mode 100644
index 00000000000..f15ff978e65
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc
@@ -0,0 +1,253 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h"
+
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "base/unguessable_token.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_timing_details.h"
+#include "components/viz/common/surfaces/frame_sink_bundle_id.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+#include "components/viz/test/compositor_frame_helpers.h"
+#include "services/viz/public/mojom/compositing/frame_sink_bundle.mojom-blink.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h"
+#include "third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink_client.h"
+#include "third_party/blink/renderer/platform/graphics/test/mock_embedded_frame_sink_provider.h"
+#include "third_party/blink/renderer/platform/graphics/test/mock_frame_sink_bundle.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+namespace {
+
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::UnorderedElementsAre;
+
+const viz::FrameSinkId kTestParentFrameSinkId(1, 1);
+const viz::FrameSinkId kTestDifferentParentFrameSinkId(1, 42);
+
+const viz::FrameSinkId kTestVideoSinkId1(1, 2);
+const viz::FrameSinkId kTestVideoSinkId2(1, 3);
+const viz::FrameSinkId kTestVideoSinkId3(1, 4);
+
+MATCHER(IsEmpty, "") {
+ return arg.IsEmpty();
+}
+MATCHER(IsFrame, "") {
+ return arg->data->which() ==
+ viz::mojom::blink::BundledFrameSubmissionData::Tag::kFrame;
+}
+MATCHER(IsDidNotProduceFrame, "") {
+ return arg->data->which() == viz::mojom::blink::BundledFrameSubmissionData::
+ Tag::kDidNotProduceFrame;
+}
+MATCHER_P(ForSink, sink_id, "") {
+ return arg->sink_id == sink_id;
+}
+
+viz::mojom::blink::BeginFrameInfoPtr MakeBeginFrameInfo(uint32_t sink_id) {
+ return viz::mojom::blink::BeginFrameInfo::New(
+ sink_id,
+ viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 1, 1, base::TimeTicks(),
+ base::TimeTicks(), base::TimeDelta(),
+ viz::BeginFrameArgs::NORMAL),
+ WTF::HashMap<uint32_t, viz::FrameTimingDetails>());
+}
+
+class MockFrameSinkBundleClient
+ : public viz::mojom::blink::FrameSinkBundleClient {
+ public:
+ ~MockFrameSinkBundleClient() override = default;
+
+ // viz::mojom::blink::FrameSinkBundleClient implementation:
+ MOCK_METHOD3(
+ FlushNotifications,
+ void(WTF::Vector<viz::mojom::blink::BundledReturnedResourcesPtr> acks,
+ WTF::Vector<viz::mojom::blink::BeginFrameInfoPtr> begin_frames,
+ WTF::Vector<viz::mojom::blink::BundledReturnedResourcesPtr>
+ reclaimed_resources));
+ MOCK_METHOD2(OnBeginFramePausedChanged, void(uint32_t sink_id, bool paused));
+ MOCK_METHOD2(OnCompositorFrameTransitionDirectiveProcessed,
+ void(uint32_t sink_id, uint32_t sequence_id));
+};
+
+const viz::LocalSurfaceId kTestSurfaceId(
+ 1,
+ base::UnguessableToken::Deserialize(1, 2));
+
+class VideoFrameSinkBundleTest : public testing::Test {
+ public:
+ VideoFrameSinkBundleTest() = default;
+
+ ~VideoFrameSinkBundleTest() override {
+ VideoFrameSinkBundle::DestroySharedInstancesForTesting();
+ }
+
+ void CreateTestBundle() {
+ EXPECT_CALL(frame_sink_provider(), CreateFrameSinkBundle_).Times(1);
+ test_bundle();
+ }
+
+ VideoFrameSinkBundle& test_bundle() {
+ return VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ frame_sink_provider(), kTestParentFrameSinkId,
+ /*for_media_streams=*/true);
+ }
+
+ MockEmbeddedFrameSinkProvider& frame_sink_provider() {
+ return mock_frame_sink_provider_;
+ }
+
+ MockFrameSinkBundleClient& mock_bundle_client() {
+ return mock_bundle_client_;
+ }
+
+ MockFrameSinkBundle& mock_frame_sink_bundle() {
+ return frame_sink_provider().mock_frame_sink_bundle();
+ }
+
+ private:
+ MockEmbeddedFrameSinkProvider mock_frame_sink_provider_;
+ MockFrameSinkBundleClient mock_bundle_client_;
+ base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(VideoFrameSinkBundleTest, GetOrCreateSharedInstance) {
+ // Verify that GetOrCreateSharedInstance lazily initializes an instance.
+ EXPECT_CALL(frame_sink_provider(), CreateFrameSinkBundle_).Times(1);
+ VideoFrameSinkBundle& bundle =
+ VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ frame_sink_provider(), kTestParentFrameSinkId,
+ /*for_media_streams=*/true);
+ EXPECT_FALSE(bundle.is_context_lost());
+
+ // And that acquiring an instance with the same parameters reuses the existing
+ // instance.
+ VideoFrameSinkBundle& other_bundle =
+ VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ frame_sink_provider(), kTestParentFrameSinkId,
+ /*for_media_streams=*/true);
+ EXPECT_EQ(&other_bundle, &bundle);
+
+ // And finally that acquiring an instance with either a different parent frame
+ // sink ID or a different frame type will create a new instance.
+ EXPECT_CALL(frame_sink_provider(), CreateFrameSinkBundle_).Times(1);
+ VideoFrameSinkBundle& yet_another_bundle =
+ VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ frame_sink_provider(), kTestDifferentParentFrameSinkId,
+ /*for_media_streams=*/true);
+ EXPECT_NE(&yet_another_bundle, &bundle);
+
+ EXPECT_CALL(frame_sink_provider(), CreateFrameSinkBundle_).Times(1);
+ VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ frame_sink_provider(), kTestDifferentParentFrameSinkId,
+ /*for_media_streams=*/false);
+}
+
+TEST_F(VideoFrameSinkBundleTest, Reconnect) {
+ // Verifies that a VideoFrameSinkBundle reestablishes a connection to Viz
+ // when acquired again after disconnection.
+ CreateTestBundle();
+ VideoFrameSinkBundle& bundle = test_bundle();
+ bundle.OnContextLost(bundle.bundle_id());
+
+ EXPECT_CALL(frame_sink_provider(), CreateFrameSinkBundle_).Times(1);
+ VideoFrameSinkBundle& another_bundle = test_bundle();
+ EXPECT_EQ(&another_bundle, &bundle);
+}
+
+TEST_F(VideoFrameSinkBundleTest, Cleanup) {
+ // Verifies that shared instances clean up after themselves when their last
+ // client is removed.
+ mojo::Remote<viz::mojom::blink::CompositorFrameSink> sink;
+ ignore_result(sink.BindNewPipeAndPassReceiver());
+ MockCompositorFrameSinkClient client;
+ CreateTestBundle();
+ VideoFrameSinkBundle& bundle = test_bundle();
+ bundle.AddClient(kTestVideoSinkId1, &client, sink);
+ bundle.AddClient(kTestVideoSinkId2, &client, sink);
+
+ EXPECT_EQ(&bundle, VideoFrameSinkBundle::GetSharedInstanceForTesting(
+ kTestParentFrameSinkId, true));
+ bundle.RemoveClient(kTestVideoSinkId1);
+ EXPECT_EQ(&bundle, VideoFrameSinkBundle::GetSharedInstanceForTesting(
+ kTestParentFrameSinkId, true));
+ bundle.RemoveClient(kTestVideoSinkId2);
+ EXPECT_EQ(nullptr, VideoFrameSinkBundle::GetSharedInstanceForTesting(
+ kTestParentFrameSinkId, true));
+}
+
+TEST_F(VideoFrameSinkBundleTest, PassThrough) {
+ // Verifies that as a safe default, VideoFrameSinkBundle passes frame
+ // submissions through to Viz without any batching.
+ CreateTestBundle();
+ VideoFrameSinkBundle& bundle = test_bundle();
+ bundle.SubmitCompositorFrame(
+ 2, kTestSurfaceId, viz::MakeDefaultCompositorFrame(), absl::nullopt, 0);
+ EXPECT_CALL(mock_frame_sink_bundle(),
+ Submit(ElementsAre(AllOf(IsFrame(), ForSink(2u)))))
+ .Times(1);
+ mock_frame_sink_bundle().FlushReceiver();
+
+ bundle.DidNotProduceFrame(3, viz::BeginFrameAck(1, 2, false));
+ EXPECT_CALL(mock_frame_sink_bundle(),
+ Submit(ElementsAre(AllOf(IsDidNotProduceFrame(), ForSink(3u)))));
+ mock_frame_sink_bundle().FlushReceiver();
+}
+
+TEST_F(VideoFrameSinkBundleTest, BatchSubmissionsDuringOnBeginFrame) {
+ // Verifies that submitted compositor frames (or DidNotProduceFrames) are
+ // batched when submitted during an OnBeginFrame handler, and flushed
+ // afterwords.
+ CreateTestBundle();
+ VideoFrameSinkBundle& bundle = test_bundle();
+
+ MockCompositorFrameSinkClient mock_client1;
+ MockCompositorFrameSinkClient mock_client2;
+ MockCompositorFrameSinkClient mock_client3;
+ mojo::Remote<viz::mojom::blink::CompositorFrameSink> sink;
+ ignore_result(sink.BindNewPipeAndPassReceiver());
+ bundle.AddClient(kTestVideoSinkId1, &mock_client1, sink);
+ bundle.AddClient(kTestVideoSinkId2, &mock_client2, sink);
+ bundle.AddClient(kTestVideoSinkId3, &mock_client3, sink);
+
+ // All clients will submit a frame synchronously within OnBeginFrame.
+ EXPECT_CALL(mock_client1, OnBeginFrame).Times(1).WillOnce([&] {
+ bundle.SubmitCompositorFrame(kTestVideoSinkId1.sink_id(), kTestSurfaceId,
+ viz::MakeDefaultCompositorFrame(),
+ absl::nullopt, 0);
+ });
+ EXPECT_CALL(mock_client2, OnBeginFrame).Times(1).WillOnce([&] {
+ bundle.DidNotProduceFrame(kTestVideoSinkId2.sink_id(),
+ viz::BeginFrameAck(1, 1, false));
+ });
+ EXPECT_CALL(mock_client3, OnBeginFrame).Times(1).WillOnce([&] {
+ bundle.SubmitCompositorFrame(kTestVideoSinkId3.sink_id(), kTestSurfaceId,
+ viz::MakeDefaultCompositorFrame(),
+ absl::nullopt, 0);
+ });
+
+ WTF::Vector<viz::mojom::blink::BeginFrameInfoPtr> begin_frames;
+ begin_frames.push_back(MakeBeginFrameInfo(kTestVideoSinkId1.sink_id()));
+ begin_frames.push_back(MakeBeginFrameInfo(kTestVideoSinkId2.sink_id()));
+ begin_frames.push_back(MakeBeginFrameInfo(kTestVideoSinkId3.sink_id()));
+ bundle.FlushNotifications({}, std::move(begin_frames), {});
+
+ EXPECT_CALL(
+ mock_frame_sink_bundle(),
+ Submit(UnorderedElementsAre(
+ AllOf(IsFrame(), ForSink(kTestVideoSinkId1.sink_id())),
+ AllOf(IsDidNotProduceFrame(), ForSink(kTestVideoSinkId2.sink_id())),
+ AllOf(IsFrame(), ForSink(kTestVideoSinkId3.sink_id())))))
+ .Times(1);
+ mock_frame_sink_bundle().FlushReceiver();
+}
+
+} // namespace
+} // 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 4d98fc00725..c7424e0dc51 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
@@ -8,37 +8,128 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
#include "cc/metrics/video_playback_roughness_reporter.h"
#include "components/power_scheduler/power_mode.h"
#include "components/power_scheduler/power_mode_arbiter.h"
#include "components/power_scheduler/power_mode_voter.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/returned_resource.h"
+#include "components/viz/common/surfaces/frame_sink_bundle_id.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h"
+#include "services/viz/public/mojom/compositing/frame_sink_bundle.mojom-blink.h"
#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
+#include "third_party/blink/renderer/platform/graphics/video_frame_sink_bundle.h"
#include "ui/gfx/presentation_feedback.h"
namespace blink {
+namespace {
+
+// If enabled, every VideoFrameSubmitter will share a FrameSinkBundle with every
+// other VideoFrameSubmitter living on the same thread with the same parent
+// FrameSinkId. This is used to aggregate Viz communication and substantially
+// reduce IPC traffic when many VideoFrameSubmitters are active within a frame.
+const base::Feature kUseVideoFrameSinkBundle{"UseVideoFrameSinkBundle",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace
+
+// Helper CompositorFrameSink implementation which sits locally between a
+// VideoFrameSubmitter and a thread-local FrameSinkBundle connection to Viz.
+// This queues outgoing messages so they can be delivered in batches. With
+// many active VideoFrameSubmitters in the same frame, this can significantly
+// reduce Viz communication overhead.
+class VideoFrameSubmitter::FrameSinkBundleProxy
+ : public viz::mojom::blink::CompositorFrameSink {
+ public:
+ FrameSinkBundleProxy(VideoFrameSinkBundle& bundle,
+ const viz::FrameSinkId& frame_sink_id)
+ : bundle_(bundle),
+ bundle_id_(bundle.bundle_id()),
+ frame_sink_id_(frame_sink_id) {}
+ FrameSinkBundleProxy(const FrameSinkBundleProxy&) = delete;
+ FrameSinkBundleProxy& operator=(const FrameSinkBundleProxy&) = delete;
+
+ ~FrameSinkBundleProxy() override { bundle_.RemoveClient(frame_sink_id_); }
+
+ void OnContextLost() { bundle_.OnContextLost(bundle_id_); }
+
+ // viz::mojom::Blink::CompositorFrameSink:
+ void SetNeedsBeginFrame(bool needs_begin_frame) override {
+ bundle_.SetNeedsBeginFrame(frame_sink_id_.sink_id(), needs_begin_frame);
+ }
+
+ // Not used by VideoFrameSubmitter.
+ void SetWantsAnimateOnlyBeginFrames() override { NOTREACHED(); }
+
+ void SubmitCompositorFrame(
+ const viz::LocalSurfaceId& local_surface_id,
+ viz::CompositorFrame frame,
+ absl::optional<viz::HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time) override {
+ bundle_.SubmitCompositorFrame(frame_sink_id_.sink_id(), local_surface_id,
+ std::move(frame),
+ std::move(hit_test_region_list), submit_time);
+ }
+
+ // Not used by VideoFrameSubmitter.
+ void SubmitCompositorFrameSync(
+ const viz::LocalSurfaceId& local_surface_id,
+ viz::CompositorFrame frame,
+ absl::optional<viz::HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ SubmitCompositorFrameSyncCallback callback) override {
+ NOTREACHED();
+ }
+
+ void DidNotProduceFrame(const viz::BeginFrameAck& ack) override {
+ bundle_.DidNotProduceFrame(frame_sink_id_.sink_id(), ack);
+ }
+
+ void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,
+ const gpu::Mailbox& id) override {
+ bundle_.DidAllocateSharedBitmap(frame_sink_id_.sink_id(), std::move(region),
+ id);
+ }
+
+ void DidDeleteSharedBitmap(const gpu::Mailbox& id) override {
+ bundle_.DidDeleteSharedBitmap(frame_sink_id_.sink_id(), id);
+ }
+
+ void InitializeCompositorFrameSinkType(
+ viz::mojom::blink::CompositorFrameSinkType type) override {
+ bundle_.InitializeCompositorFrameSinkType(frame_sink_id_.sink_id(), type);
+ }
+
+ private:
+ VideoFrameSinkBundle& bundle_;
+ const viz::FrameSinkBundleId bundle_id_;
+ const viz::FrameSinkId frame_sink_id_;
+};
+
VideoFrameSubmitter::VideoFrameSubmitter(
WebContextProviderCallback context_provider_callback,
cc::VideoPlaybackRoughnessReporter::ReportingCallback
roughness_reporting_callback,
+ const viz::FrameSinkId& parent_frame_sink_id,
std::unique_ptr<VideoFrameResourceProvider> resource_provider)
: context_provider_callback_(context_provider_callback),
resource_provider_(std::move(resource_provider)),
- rotation_(media::VIDEO_ROTATION_0),
+ parent_frame_sink_id_(parent_frame_sink_id),
roughness_reporter_(std::make_unique<cc::VideoPlaybackRoughnessReporter>(
std::move(roughness_reporting_callback))),
frame_trackers_(false, nullptr),
@@ -119,9 +210,9 @@ void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider,
weak_ptr_factory_.GetWeakPtr()));
}
-void VideoFrameSubmitter::SetRotation(media::VideoRotation rotation) {
+void VideoFrameSubmitter::SetTransform(media::VideoTransformation transform) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- rotation_ = rotation;
+ transform_ = transform;
}
void VideoFrameSubmitter::EnableSubmission(viz::SurfaceId surface_id) {
@@ -172,8 +263,14 @@ void VideoFrameSubmitter::OnContextLost() {
resource_provider_->OnContextLost();
- // |compositor_frame_sink_| should be reset last.
- compositor_frame_sink_.reset();
+ // NOTE: These objects should be reset last; and if `bundle_proxy`_ is set, it
+ // should be reset after `remote_frame_sink_`.
+ compositor_frame_sink_ = nullptr;
+ remote_frame_sink_.reset();
+ if (bundle_proxy_) {
+ bundle_proxy_->OnContextLost();
+ bundle_proxy_.reset();
+ }
context_provider_callback_.Run(
context_provider_,
@@ -196,10 +293,16 @@ void VideoFrameSubmitter::OnBeginFrame(
last_begin_frame_args_ = args;
- for (const auto& pair : timing_details) {
- if (viz::FrameTokenGT(pair.key, *next_frame_token_))
+ WTF::Vector<uint32_t> frame_tokens;
+ for (const auto& id : timing_details.Keys())
+ frame_tokens.push_back(id);
+ std::sort(frame_tokens.begin(), frame_tokens.end());
+
+ for (const auto& frame_token : frame_tokens) {
+ if (viz::FrameTokenGT(frame_token, *next_frame_token_))
continue;
- auto& feedback = pair.value.presentation_feedback;
+ auto& feedback =
+ timing_details.find(frame_token)->value.presentation_feedback;
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
// TODO: On Linux failure flag is unreliable, and perfectly rendered frames
// are reported as failures all the time.
@@ -209,10 +312,11 @@ void VideoFrameSubmitter::OnBeginFrame(
feedback.flags & gfx::PresentationFeedback::kFailure;
#endif
if (!presentation_failure &&
- !ignorable_submitted_frames_.contains(pair.key)) {
+ !ignorable_submitted_frames_.contains(frame_token)) {
frame_trackers_.NotifyFramePresented(
- pair.key, gfx::PresentationFeedback(
- feedback.timestamp, feedback.interval, feedback.flags));
+ frame_token,
+ gfx::PresentationFeedback(feedback.timestamp, feedback.interval,
+ feedback.flags));
// We assume that presentation feedback is reliable if
// 1. (kHWCompletion) OS told us that the frame was shown at that time
@@ -222,13 +326,13 @@ void VideoFrameSubmitter::OnBeginFrame(
gfx::PresentationFeedback::kHWCompletion |
gfx::PresentationFeedback::kVSync;
bool reliable_timestamp = feedback.flags & reliable_feedback_mask;
- roughness_reporter_->FramePresented(pair.key, feedback.timestamp,
+ roughness_reporter_->FramePresented(frame_token, feedback.timestamp,
reliable_timestamp);
}
- ignorable_submitted_frames_.erase(pair.key);
+ ignorable_submitted_frames_.erase(frame_token);
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
- "media", "VideoFrameSubmitter", TRACE_ID_LOCAL(pair.key),
+ "media", "VideoFrameSubmitter", TRACE_ID_LOCAL(frame_token),
feedback.timestamp);
}
frame_trackers_.NotifyBeginImplFrame(args);
@@ -353,9 +457,24 @@ void VideoFrameSubmitter::StartSubmitting() {
Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
provider.BindNewPipeAndPassReceiver());
- provider->CreateCompositorFrameSink(
- frame_sink_id_, receiver_.BindNewPipeAndPassRemote(),
- compositor_frame_sink_.BindNewPipeAndPassReceiver());
+ if (base::FeatureList::IsEnabled(kUseVideoFrameSinkBundle)) {
+ auto& bundle = VideoFrameSinkBundle::GetOrCreateSharedInstance(
+ *provider.get(), parent_frame_sink_id_, is_media_stream_);
+ provider->CreateBundledCompositorFrameSink(
+ frame_sink_id_, bundle.bundle_id(),
+ receiver_.BindNewPipeAndPassRemote(),
+ remote_frame_sink_.BindNewPipeAndPassReceiver());
+ bundle.AddClient(frame_sink_id_, this, remote_frame_sink_);
+ bundle_proxy_ =
+ std::make_unique<FrameSinkBundleProxy>(bundle, frame_sink_id_);
+ compositor_frame_sink_ = bundle_proxy_.get();
+ } else {
+ provider->CreateCompositorFrameSink(
+ frame_sink_id_, receiver_.BindNewPipeAndPassRemote(),
+ remote_frame_sink_.BindNewPipeAndPassReceiver());
+ compositor_frame_sink_ = remote_frame_sink_.get();
+ }
+
if (!surface_embedder_.is_bound()) {
provider->ConnectToEmbedder(frame_sink_id_,
surface_embedder_.BindNewPipeAndPassReceiver());
@@ -363,12 +482,9 @@ void VideoFrameSubmitter::StartSubmitting() {
GenerateNewSurfaceId();
}
- compositor_frame_sink_.set_disconnect_handler(base::BindOnce(
+ remote_frame_sink_.set_disconnect_handler(base::BindOnce(
&VideoFrameSubmitter::OnContextLost, base::Unretained(this)));
- if (!compositor_frame_sink_)
- return;
-
compositor_frame_sink_->InitializeCompositorFrameSinkType(
is_media_stream_ ? viz::mojom::CompositorFrameSinkType::kMediaStream
: viz::mojom::CompositorFrameSinkType::kVideo);
@@ -467,8 +583,11 @@ bool VideoFrameSubmitter::SubmitFrame(
last_frame_id_ = video_frame->unique_id();
gfx::Size frame_size(video_frame->natural_size());
- if (rotation_ == media::VIDEO_ROTATION_90 ||
- rotation_ == media::VIDEO_ROTATION_270) {
+
+ // Prefer the frame level transform if set.
+ auto transform = video_frame->metadata().transformation.value_or(transform_);
+ if (transform.rotation == media::VIDEO_ROTATION_90 ||
+ transform.rotation == media::VIDEO_ROTATION_270) {
frame_size = gfx::Size(frame_size.height(), frame_size.width());
}
@@ -493,8 +612,8 @@ bool VideoFrameSubmitter::SubmitFrame(
roughness_reporter_->FrameSubmitted(frame_token, *video_frame.get(),
last_begin_frame_args_.interval);
}
- auto compositor_frame = CreateCompositorFrame(frame_token, begin_frame_ack,
- std::move(video_frame));
+ auto compositor_frame = CreateCompositorFrame(
+ frame_token, begin_frame_ack, std::move(video_frame), transform);
WebVector<viz::ResourceId> resources;
const auto& quad_list = compositor_frame.render_pass_list.back()->quad_list;
@@ -534,8 +653,8 @@ void VideoFrameSubmitter::SubmitEmptyFrame() {
last_frame_id_.reset();
auto begin_frame_ack = viz::BeginFrameAck::CreateManualAckWithDamage();
auto frame_token = ++next_frame_token_;
- auto compositor_frame =
- CreateCompositorFrame(frame_token, begin_frame_ack, nullptr);
+ auto compositor_frame = CreateCompositorFrame(
+ frame_token, begin_frame_ack, nullptr, media::kNoTransformation);
compositor_frame_sink_->SubmitCompositorFrame(
child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
@@ -576,7 +695,8 @@ bool VideoFrameSubmitter::ShouldSubmit() const {
viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
uint32_t frame_token,
const viz::BeginFrameAck& begin_frame_ack,
- scoped_refptr<media::VideoFrame> video_frame) {
+ scoped_refptr<media::VideoFrame> video_frame,
+ media::VideoTransformation transform) {
DCHECK(!frame_size_.IsEmpty());
viz::CompositorFrame compositor_frame;
@@ -627,7 +747,7 @@ viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
video_frame->ColorSpace().GetContentColorUsage();
const bool is_opaque = media::IsOpaque(video_frame->format());
resource_provider_->AppendQuads(render_pass.get(), std::move(video_frame),
- rotation_, is_opaque);
+ transform, is_opaque);
}
compositor_frame.render_pass_list.emplace_back(std::move(render_pass));
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 a31b403af73..857fa34a138 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
@@ -46,7 +46,10 @@ class PLATFORM_EXPORT VideoFrameSubmitter
public:
VideoFrameSubmitter(WebContextProviderCallback,
cc::VideoPlaybackRoughnessReporter::ReportingCallback,
+ const viz::FrameSinkId& parent_frame_sink_id,
std::unique_ptr<VideoFrameResourceProvider>);
+ VideoFrameSubmitter(const VideoFrameSubmitter&) = delete;
+ VideoFrameSubmitter& operator=(const VideoFrameSubmitter&) = delete;
~VideoFrameSubmitter() override;
// cc::VideoFrameProvider::Client implementation.
@@ -58,7 +61,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// WebVideoFrameSubmitter implementation.
void Initialize(cc::VideoFrameProvider*, bool is_media_stream) override;
- void SetRotation(media::VideoRotation) override;
+ void SetTransform(media::VideoTransformation) override;
void EnableSubmission(viz::SurfaceId) override;
void SetIsSurfaceVisible(bool is_visible) override;
void SetIsPageVisible(bool is_visible) override;
@@ -86,6 +89,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
private:
friend class VideoFrameSubmitterTest;
+ class FrameSinkBundleProxy;
// Called during Initialize() and OnContextLost() after a new ContextGL is
// requested.
@@ -130,18 +134,31 @@ class PLATFORM_EXPORT VideoFrameSubmitter
viz::CompositorFrame CreateCompositorFrame(
uint32_t frame_token,
const viz::BeginFrameAck& begin_frame_ack,
- scoped_refptr<media::VideoFrame> video_frame);
+ scoped_refptr<media::VideoFrame> video_frame,
+ media::VideoTransformation transform);
cc::VideoFrameProvider* video_frame_provider_ = nullptr;
bool is_media_stream_ = false;
scoped_refptr<viz::RasterContextProvider> context_provider_;
- mojo::Remote<viz::mojom::blink::CompositorFrameSink> compositor_frame_sink_;
+ mojo::Remote<viz::mojom::blink::CompositorFrameSink> remote_frame_sink_;
mojo::Remote<mojom::blink::SurfaceEmbedder> surface_embedder_;
mojo::Receiver<viz::mojom::blink::CompositorFrameSinkClient> receiver_{this};
WebContextProviderCallback context_provider_callback_;
std::unique_ptr<VideoFrameResourceProvider> resource_provider_;
bool waiting_for_compositor_ack_ = false;
+ const viz::FrameSinkId parent_frame_sink_id_;
+
+ // When UseVideoFrameSinkBundle is enabled, this is initialized to a local
+ // implementation which batches outgoing Viz requests with those from other
+ // related VideoFrameSubmitters, rather than having each VideoFrameSubmitter
+ // submit their ad hoc requests directly to Viz.
+ std::unique_ptr<FrameSinkBundleProxy> bundle_proxy_;
+
+ // Points to either `remote_frame_sink_` or `bundle_proxy_` depending
+ // on whether UseVideoFrameSinkBundle is enabled.
+ viz::mojom::blink::CompositorFrameSink* compositor_frame_sink_ = nullptr;
+
// Current rendering state. Set by StartRendering() and StopRendering().
bool is_rendering_ = false;
@@ -164,7 +181,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// Needs to be initialized in implementation because media isn't a public_dep
// of blink/platform.
- media::VideoRotation rotation_;
+ media::VideoTransformation transform_;
viz::FrameSinkId frame_sink_id_;
@@ -201,8 +218,6 @@ class PLATFORM_EXPORT VideoFrameSubmitter
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<VideoFrameSubmitter> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(VideoFrameSubmitter);
};
} // namespace blink
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 141cdd2e244..93de0e9c72d 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
@@ -50,6 +50,8 @@ namespace {
class MockVideoFrameProvider : public cc::VideoFrameProvider {
public:
MockVideoFrameProvider() = default;
+ MockVideoFrameProvider(const MockVideoFrameProvider&) = delete;
+ MockVideoFrameProvider& operator=(const MockVideoFrameProvider&) = delete;
~MockVideoFrameProvider() override = default;
MOCK_METHOD1(SetVideoFrameProviderClient, void(Client*));
@@ -63,9 +65,6 @@ class MockVideoFrameProvider : public cc::VideoFrameProvider {
}
base::TimeDelta preferred_interval;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockVideoFrameProvider);
};
class VideoMockCompositorFrameSink
@@ -75,6 +74,9 @@ class VideoMockCompositorFrameSink
mojo::PendingReceiver<viz::mojom::blink::CompositorFrameSink> receiver) {
receiver_.Bind(std::move(receiver));
}
+ VideoMockCompositorFrameSink(const VideoMockCompositorFrameSink&) = delete;
+ VideoMockCompositorFrameSink& operator=(const VideoMockCompositorFrameSink&) =
+ delete;
~VideoMockCompositorFrameSink() override = default;
const viz::CompositorFrame& last_submitted_compositor_frame() const {
@@ -116,8 +118,6 @@ class VideoMockCompositorFrameSink
mojo::Receiver<viz::mojom::blink::CompositorFrameSink> receiver_{this};
viz::CompositorFrame last_submitted_compositor_frame_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoMockCompositorFrameSink);
};
class MockVideoFrameResourceProvider
@@ -130,6 +130,10 @@ class MockVideoFrameResourceProvider
blink::VideoFrameResourceProvider::Initialize(context_provider,
shared_bitmap_reporter);
}
+ MockVideoFrameResourceProvider(const MockVideoFrameResourceProvider&) =
+ delete;
+ MockVideoFrameResourceProvider& operator=(
+ const MockVideoFrameResourceProvider&) = delete;
~MockVideoFrameResourceProvider() override = default;
MOCK_METHOD2(Initialize,
@@ -137,7 +141,7 @@ class MockVideoFrameResourceProvider
MOCK_METHOD4(AppendQuads,
void(viz::CompositorRenderPass*,
scoped_refptr<media::VideoFrame>,
- media::VideoRotation,
+ media::VideoTransformation,
bool));
MOCK_METHOD0(ReleaseFrameResources, void());
MOCK_METHOD2(PrepareSendToParent,
@@ -146,9 +150,6 @@ class MockVideoFrameResourceProvider
MOCK_METHOD1(ReceiveReturnsFromParent,
void(Vector<viz::ReturnedResource> transferable_resources));
MOCK_METHOD0(ObtainContextProvider, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockVideoFrameResourceProvider);
};
} // namespace
@@ -171,7 +172,7 @@ class VideoFrameSubmitterTest : public testing::Test {
resource_provider_ = new StrictMock<MockVideoFrameResourceProvider>(
context_provider_.get(), nullptr);
submitter_ = std::make_unique<VideoFrameSubmitter>(
- base::DoNothing(), reporting_cb,
+ base::DoNothing(), reporting_cb, viz::FrameSinkId(1, 1),
base::WrapUnique<MockVideoFrameResourceProvider>(resource_provider_));
submitter_->Initialize(video_frame_provider_.get(), false);
@@ -182,7 +183,8 @@ class VideoFrameSubmitterTest : public testing::Test {
// 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_->SetIsSurfaceVisible(true);
- submitter_->compositor_frame_sink_.Bind(std::move(submitter_sink));
+ submitter_->remote_frame_sink_.Bind(std::move(submitter_sink));
+ submitter_->compositor_frame_sink_ = submitter_->remote_frame_sink_.get();
mojo::Remote<mojom::blink::SurfaceEmbedder> embedder;
ignore_result(embedder.BindNewPipeAndPassReceiver());
submitter_->surface_embedder_ = std::move(embedder);
@@ -434,7 +436,7 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
// Check to see if rotation is communicated pre-rendering.
EXPECT_FALSE(IsRendering());
- submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_90);
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_90);
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -443,7 +445,10 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_90, _));
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_90),
+ _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -453,7 +458,7 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
// Check to see if an update to rotation just before rendering is
// communicated.
- submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_180);
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_180);
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
submitter_->StartRendering();
@@ -469,7 +474,10 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_180, _));
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_180),
+ _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -480,7 +488,7 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
AckSubmittedFrame();
// Check to see if changing rotation while rendering is handled.
- submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_270);
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_270);
EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
.WillOnce(Return(true));
@@ -491,7 +499,10 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_270, _));
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_270),
+ _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -501,6 +512,58 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
task_environment_.RunUntilIdle();
}
+TEST_F(VideoFrameSubmitterTest, FrameTransformTakesPrecedent) {
+ EXPECT_FALSE(IsRendering());
+
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_90);
+
+ EXPECT_CALL(*video_frame_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(*video_frame_provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_,
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_90),
+ _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->DidReceiveFrame();
+ task_environment_.RunUntilIdle();
+ AckSubmittedFrame();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ submitter_->StartRendering();
+ task_environment_.RunUntilIdle();
+ AckSubmittedFrame();
+
+ auto frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta());
+ frame->metadata().transformation = media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_180, /*mirrored=*/true);
+
+ EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
+ .WillOnce(Return(frame));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_,
+ AppendQuads(_, _, frame->metadata().transformation.value(), _));
+ 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, {});
+ task_environment_.RunUntilIdle();
+ AckSubmittedFrame();
+}
+
TEST_F(VideoFrameSubmitterTest, OnBeginFrameSubmitsFrame) {
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
@@ -750,7 +813,7 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
gfx::Size rotated_size(1024, 1280);
{
- submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_90);
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_90);
EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
.WillOnce(Return(true));
@@ -761,7 +824,10 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_90, _));
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_90),
+ _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -777,7 +843,7 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
}
{
- submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_180);
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_180);
EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
.WillOnce(Return(true));
@@ -788,7 +854,10 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_180, _));
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_180),
+ _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -805,7 +874,7 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
}
{
- submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_270);
+ submitter_->SetTransform(media::VideoRotation::VIDEO_ROTATION_270);
EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
.WillOnce(Return(true));
@@ -816,7 +885,10 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_270, _));
+ AppendQuads(_, _,
+ media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_270),
+ _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/viz_util.cc b/chromium/third_party/blink/renderer/platform/graphics/viz_util.cc
new file mode 100644
index 00000000000..c041cd25682
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/viz_util.cc
@@ -0,0 +1,26 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <atomic>
+
+#include "components/viz/common/surfaces/frame_sink_bundle_id.h"
+#include "third_party/blink/renderer/platform/graphics/viz_util.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+namespace {
+
+std::atomic<uint32_t> g_next_bundle_id{1};
+
+} // namespace
+
+viz::FrameSinkBundleId GenerateFrameSinkBundleId(
+ const viz::FrameSinkId& parent_frame_sink_id) {
+ return viz::FrameSinkBundleId(
+ parent_frame_sink_id.client_id(),
+ g_next_bundle_id.fetch_add(1, std::memory_order_relaxed));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/viz_util.h b/chromium/third_party/blink/renderer/platform/graphics/viz_util.h
new file mode 100644
index 00000000000..b96748af8e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/viz_util.h
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIZ_UTIL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIZ_UTIL_H_
+
+#include "components/viz/common/surfaces/frame_sink_bundle_id.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+// Generates a new FrameSinkBundleId which is unique within the calling process
+// and suitable for use with the given parent frame sink ID.
+PLATFORM_EXPORT viz::FrameSinkBundleId GenerateFrameSinkBundleId(
+ const viz::FrameSinkId& parent_frame_sink_id);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIZ_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc b/chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
new file mode 100644
index 00000000000..6e08ed91fe8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
@@ -0,0 +1,131 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h"
+
+#include "components/viz/common/gpu/raster_context_provider.h"
+#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
+#include "media/renderers/video_frame_rgba_to_yuva_converter.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+#include "media/video/renderable_gpu_memory_buffer_video_frame_pool.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
+
+namespace blink {
+
+namespace {
+
+class Context : public media::RenderableGpuMemoryBufferVideoFramePool::Context {
+ public:
+ explicit Context(base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ context_provider)
+ : weak_context_provider_(context_provider) {}
+
+ std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage) override {
+ return GpuMemoryBufferManager()->CreateGpuMemoryBuffer(
+ size, format, usage, gpu::kNullSurfaceHandle, nullptr);
+ }
+
+ void CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
+ gfx::BufferPlane plane,
+ const gfx::ColorSpace& color_space,
+ GrSurfaceOrigin surface_origin,
+ SkAlphaType alpha_type,
+ uint32_t usage,
+ gpu::Mailbox& mailbox,
+ gpu::SyncToken& sync_token) override {
+ auto* sii = SharedImageInterface();
+ if (!sii)
+ return;
+ mailbox = sii->CreateSharedImage(
+ gpu_memory_buffer, GpuMemoryBufferManager(), plane, color_space,
+ surface_origin, alpha_type, usage);
+ sync_token = sii->GenVerifiedSyncToken();
+ }
+
+ void DestroySharedImage(const gpu::SyncToken& sync_token,
+ const gpu::Mailbox& mailbox) override {
+ auto* sii = SharedImageInterface();
+ if (!sii)
+ return;
+ sii->DestroySharedImage(sync_token, mailbox);
+ }
+
+ private:
+ gpu::SharedImageInterface* SharedImageInterface() const {
+ if (!weak_context_provider_)
+ return nullptr;
+ auto* context_provider = weak_context_provider_->ContextProvider();
+ if (!context_provider)
+ return nullptr;
+ return context_provider->SharedImageInterface();
+ }
+
+ gpu::GpuMemoryBufferManager* GpuMemoryBufferManager() const {
+ media::GpuVideoAcceleratorFactories* gpu_factories =
+ Platform::Current()->GetGpuFactories();
+ return gpu_factories->GpuMemoryBufferManager();
+ }
+
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ weak_context_provider_;
+};
+
+} // namespace
+
+WebGraphicsContext3DVideoFramePool::WebGraphicsContext3DVideoFramePool(
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ weak_context_provider)
+ : weak_context_provider_(weak_context_provider),
+ pool_(media::RenderableGpuMemoryBufferVideoFramePool::Create(
+ std::make_unique<Context>(weak_context_provider))) {}
+
+WebGraphicsContext3DVideoFramePool::~WebGraphicsContext3DVideoFramePool() =
+ default;
+
+bool WebGraphicsContext3DVideoFramePool::CopyRGBATextureToVideoFrame(
+ viz::ResourceFormat src_format,
+ const gfx::Size& src_size,
+ const gfx::ColorSpace& src_color_space,
+ GrSurfaceOrigin src_surface_origin,
+ const gpu::MailboxHolder& src_mailbox_holder,
+ base::OnceCallback<void(scoped_refptr<media::VideoFrame>)> callback) {
+ if (!weak_context_provider_)
+ return false;
+ auto* context_provider = weak_context_provider_->ContextProvider();
+ if (!context_provider)
+ return false;
+ auto* raster_context_provider = context_provider->RasterContextProvider();
+ if (!raster_context_provider)
+ return false;
+ // TODO(https://crbug.com/1206168): Move this functionality to the
+ // RasterInterface instead of using the GrContext (which may or may not
+ // exist).
+ if (!raster_context_provider->GrContext())
+ return false;
+
+ scoped_refptr<media::VideoFrame> dst_frame =
+ pool_->MaybeCreateVideoFrame(src_size);
+ if (!dst_frame)
+ return false;
+
+ gpu::SyncToken copy_done_sync_token;
+ const bool copy_succeeded = media::CopyRGBATextureToVideoFrame(
+ raster_context_provider, src_format, src_size, src_color_space,
+ src_surface_origin, src_mailbox_holder, dst_frame.get(),
+ copy_done_sync_token);
+ if (!copy_succeeded)
+ return false;
+
+ raster_context_provider->ContextSupport()->SignalSyncToken(
+ copy_done_sync_token, base::BindOnce(std::move(callback), dst_frame));
+ return true;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h b/chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h
new file mode 100644
index 00000000000..52504227ec4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_WEB_GRAPHICS_CONTEXT_3D_VIDEO_FRAME_POOL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_WEB_GRAPHICS_CONTEXT_3D_VIDEO_FRAME_POOL_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/viz/common/resources/resource_format.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/skia/include/gpu/GrTypes.h"
+
+namespace gfx {
+class ColorSpace;
+class Size;
+} // namespace gfx
+
+namespace gpu {
+struct MailboxHolder;
+} // namespace gpu
+
+namespace media {
+class RenderableGpuMemoryBufferVideoFramePool;
+class VideoFrame;
+} // namespace media
+
+namespace blink {
+
+class WebGraphicsContext3DProviderWrapper;
+
+// A video frame pool that will use a WebGraphicsContext3D to do an accelerated
+// RGB to YUV conversion directly into a GpuMemoryBuffer-backed
+// media::VideoFrame.
+class PLATFORM_EXPORT WebGraphicsContext3DVideoFramePool {
+ public:
+ explicit WebGraphicsContext3DVideoFramePool(
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> weak_context_provider);
+ ~WebGraphicsContext3DVideoFramePool();
+
+ using FrameReadyCallback =
+ base::OnceCallback<void(scoped_refptr<media::VideoFrame>)>;
+
+ // On success, this function will issue return true and will call the
+ // specified FrameCallback with the resulting VideoFrame when the frame
+ // is ready. On failure this will return false and not issue the specified
+ // callback.
+ bool CopyRGBATextureToVideoFrame(viz::ResourceFormat src_format,
+ const gfx::Size& src_size,
+ const gfx::ColorSpace& src_color_space,
+ GrSurfaceOrigin src_surface_origin,
+ const gpu::MailboxHolder& src_mailbox_holder,
+ FrameReadyCallback callback);
+
+ private:
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ weak_context_provider_;
+ const std::unique_ptr<media::RenderableGpuMemoryBufferVideoFramePool> pool_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_WEB_GRAPHICS_CONTEXT_3D_VIDEO_FRAME_POOL_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
index 601e1692fd2..73a7ef22a19 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -50,8 +50,6 @@ source_set("heap_unsanitized") {
}
blink_platform_sources("heap") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
sources = [
"blink_gc_memory_dump_provider.h",
"collection_support/clear_collection_scope.h",
@@ -114,6 +112,7 @@ blink_platform_sources("heap") {
"v8_wrapper/member.h",
"v8_wrapper/persistent.h",
"v8_wrapper/process_heap.h",
+ "v8_wrapper/thread_local.h",
"v8_wrapper/thread_state.cc",
"v8_wrapper/thread_state.h",
"v8_wrapper/thread_state_scopes.h",
@@ -233,8 +232,11 @@ source_set("test_support") {
"//third_party/blink/renderer/platform/wtf:buildflags",
]
+ # TODO(v8:11952): Switch to `//v8:v8_for_testing` as target once it properly
+ # depends on v8 without duplicating the whole library which causes ODR
+ # violations when `//v8:v8` is also pulled in otherwise.
if (enable_blink_heap_use_v8_oilpan) {
- deps += [ "//v8:v8_for_testing" ]
+ deps += [ "//v8:v8" ]
}
public_deps = [ "//base/test:test_support" ]
diff --git a/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md b/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
index cd86d4af018..2de4b1ca51f 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
+++ b/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
@@ -259,10 +259,10 @@ You need to trace every `Member<T>` and `WeakMember<T>` in your class. See [Trac
`UntracedMember<T>` represents a reference to a garbage collected object which is ignored by Oilpan.
-Unlike 'Member<T>', 'UntracedMember<T>' will not keep an object alive. However, unlike 'WeakMember<T>', the reference will not be cleared (i.e. set to 'nullptr') if the referenced object dies.
-Furthermore, class fields of type 'UntracedMember<T>' should not be traced by the class' tracing method.
+Unlike `Member<T>`, `UntracedMember<T>` will not keep an object alive. However, unlike `WeakMember<T>`, the reference will not be cleared (i.e. set to `nullptr`) if the referenced object dies.
+Furthermore, class fields of type `UntracedMember<T>` should not be traced by the class' tracing method.
-Users should use 'UntracedMember<T>' when implementing [custom weakness semantics](#Custom-weak-callbacks).
+Users should use `UntracedMember<T>` when implementing [custom weakness semantics](#Custom-weak-callbacks).
### Persistent, WeakPersistent, CrossThreadPersistent, CrossThreadWeakPersistent
@@ -390,7 +390,8 @@ Collections compared to other libraries used in Blink:
| - | WTF::HashCountedSet | blink::HeapHashCountedSet |
These heap collections work mostly the same way as their stdlib or WTF collection counterparts but there are some things to keep in mind.
-Heap collections do not inherit from `GarbageCollected` but are nonetheless allocated on-heap and thus must be properly traced from a `Trace` method.
+Heap collections are regular heap objects and thus must be properly traced from a `Trace` method.
+They can also be inlined into other objects for performance reasons and are allowed to be directly used on stack.
```c++
class A final : public GarbageCollected<A> {
diff --git a/chromium/third_party/blink/renderer/platform/heap/OWNERS b/chromium/third_party/blink/renderer/platform/heap/OWNERS
index 132b4d9011e..ec9cfdcd636 100644
--- a/chromium/third_party/blink/renderer/platform/heap/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/heap/OWNERS
@@ -1,5 +1,4 @@
bikineev@chromium.org
haraken@chromium.org
-kouhei@chromium.org
mlippautz@chromium.org
omerkatz@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S b/chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S
index 46466365653..db13c5dd3ff 100644
--- a/chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S
+++ b/chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S
@@ -50,8 +50,54 @@ _\fname:
#endif
.endm
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT
+ // ENABLE_PAUTH must be defined to 1 since this value will be used in
+ // bitwise-shift later!
+ #define ENABLE_PAUTH 1
+
+ #if ((__ARM_FEATURE_PAC_DEFAULT&((1<<0)|(1<<1)))==0)
+ #error Pointer authentication defines no valid key!
+ #endif
+#else
+ #define ENABLE_PAUTH 0
+#endif
+
+#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT==1)
+ // ENABLE_BTI must be defined to 1 since this value will be used in
+ // bitwise-shift later!
+ #define ENABLE_BTI 1
+#else
+ #define ENABLE_BTI 0
+#endif
+
+
+// Although Pointer Authentication and Branch Target Instructions are technically
+// seperate features they work together, i.e. the paciasp and pacibsp instructions
+// serve as BTI landing pads.
+// Therefore PA-instructions are enabled when PA _or_ BTI is enabled!
+#if ENABLE_PAUTH || ENABLE_BTI
+ // See section "Pointer Authentication" of
+ // https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros
+ // for details how to interpret __ARM_FEATURE_PAC_DEFAULT
+ #if (__ARM_FEATURE_PAC_DEFAULT & (1<<0))
+ #define PAUTH_SIGN_SP paciasp
+ #define PAUTH_AUTH_SP autiasp
+ #else
+ #define PAUTH_SIGN_SP pacibsp
+ #define PAUTH_AUTH_SP autibsp
+ #endif
+#else
+ #define PAUTH_SIGN_SP
+ #define PAUTH_AUTH_SP
+#endif
+
+
+
asm_function PushAllRegisters
.p2align 2
+
+ PAUTH_SIGN_SP
+
/* Save return address. */
sub sp, sp, #96
stp x19, x20, [sp, #80]
@@ -73,4 +119,23 @@ asm_function PushAllRegisters
* the callback didn't clobber them) and we didn't modify them either.
*/
ldr x30, [sp], #96
+
+ PAUTH_AUTH_SP
+
ret
+
+#if ENABLE_PAUTH || ENABLE_BTI
+// see
+// https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#program-property
+.pushsection .note.gnu.property, "a";
+ .balign 8
+ .long 4
+ .long 0x10
+ .long 0x5
+ .asciz "GNU"
+ .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
+ .long 4
+ .long ((ENABLE_PAUTH)<<1) | ((ENABLE_BTI)<<0) /* PAuth and BTI */
+ .long 0
+.popsection
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h
index 2a94b264498..0a864f1033e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h
+++ b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h
@@ -50,7 +50,7 @@ class HeapLinkedStack final : public GarbageCollected<HeapLinkedStack<T>> {
public:
HeapLinkedStack() { CheckType(); }
- inline size_t size() const;
+ inline wtf_size_t size() const;
inline bool IsEmpty() const;
inline void Push(const T&);
@@ -81,7 +81,7 @@ class HeapLinkedStack final : public GarbageCollected<HeapLinkedStack<T>> {
}
Member<Node> head_;
- size_t size_ = 0;
+ wtf_size_t size_ = 0;
};
template <typename T>
@@ -113,7 +113,7 @@ void HeapLinkedStack<T>::Pop() {
}
template <typename T>
-size_t HeapLinkedStack<T>::size() const {
+wtf_size_t HeapLinkedStack<T>::size() const {
return size_;
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/handle.h b/chromium/third_party/blink/renderer/platform/heap/handle.h
index 5f745e766c8..4b4fd808dac 100644
--- a/chromium/third_party/blink/renderer/platform/heap/handle.h
+++ b/chromium/third_party/blink/renderer/platform/heap/handle.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HANDLE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/heap/heap_traits.h"
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/garbage_collected.h b/chromium/third_party/blink/renderer/platform/heap/impl/garbage_collected.h
index 270f5859457..ccdeb37c637 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/garbage_collected.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/garbage_collected.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GARBAGE_COLLECTED_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GARBAGE_COLLECTED_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/gc_info.cc b/chromium/third_party/blink/renderer/platform/heap/impl/gc_info.cc
index 2be470ad6b3..a5271691470 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/gc_info.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/gc_info.cc
@@ -16,7 +16,8 @@ namespace {
constexpr size_t kEntrySize = sizeof(GCInfo*);
-PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t ComputeInitialTableLimit() {
+PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR GCInfoIndex
+ComputeInitialTableLimit() {
// (Light) experimentation suggests that Blink doesn't need more than this
// while handling content on popular web properties.
constexpr size_t kInitialWantedLimit = 512;
@@ -24,7 +25,8 @@ PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t ComputeInitialTableLimit() {
// Different OSes have different page sizes, so we have to choose the minimum
// of memory wanted and OS page size.
constexpr size_t memory_wanted = kInitialWantedLimit * kEntrySize;
- return base::RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize;
+ return static_cast<GCInfoIndex>(
+ base::RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize);
}
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t MaxTableSize() {
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/heap.h b/chromium/third_party/blink/renderer/platform/heap/impl/heap.h
index 0f8e48d8e15..687463dad0c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/heap.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/heap.h
@@ -36,7 +36,6 @@
#include <unordered_set>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/heap/impl/gc_info.h"
#include "third_party/blink/renderer/platform/heap/impl/heap_page.h"
@@ -503,8 +502,8 @@ class GarbageCollected {
// Used for passing custom sizes to MakeGarbageCollected.
struct AdditionalBytes {
- explicit AdditionalBytes(size_t bytes) : value(bytes) {}
- const size_t value;
+ explicit AdditionalBytes(wtf_size_t bytes) : value(bytes) {}
+ const wtf_size_t value;
};
template <typename T>
@@ -710,6 +709,12 @@ class LivenessBrokerFactory final {
} // namespace internal
+#if DCHECK_IS_ON()
+static constexpr bool kBlinkGCHasDebugChecks = true;
+#else
+static constexpr bool kBlinkGCHasDebugChecks = false;
+#endif // DCHECK_IS_ON()
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h b/chromium/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h
index ab8dd078c46..d58dc39401e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h
@@ -145,8 +145,8 @@ class PLATFORM_EXPORT HeapAllocator {
}
template <typename T>
- static void TraceBackingStoreIfMarked(T** slot) {
- MarkingVisitor::RetraceObject(*slot);
+ static void TraceBackingStoreIfMarked(T* object) {
+ MarkingVisitor::RetraceObject(object);
}
template <typename T, typename Traits>
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/heap_compact.cc b/chromium/third_party/blink/renderer/platform/heap/impl/heap_compact.cc
index e545551adea..1a5cf4c1215 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/heap_compact.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/heap_compact.cc
@@ -360,21 +360,21 @@ bool HeapCompact::ShouldRegisterMovingAddress() {
}
void HeapCompact::UpdateHeapResidency() {
- size_t total_arena_size = 0;
size_t total_free_list_size = 0;
compactable_arenas_ = 0;
#if DEBUG_HEAP_FREELIST
std::stringstream stream;
+ size_t total_arena_size = 0;
#endif
for (int i = BlinkGC::kVectorArenaIndex; i <= BlinkGC::kHashTableArenaIndex;
++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;
total_free_list_size += free_list_size;
#if DEBUG_HEAP_FREELIST
+ total_arena_size += arena_size;
stream << i << ": [" << arena_size << ", " << free_list_size << "], ";
#endif
// TODO: be more discriminating and consider arena
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h b/chromium/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h
index bdbed83b3f9..c5b6128f611 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h
@@ -146,7 +146,6 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
ScopeContext scope_category = kMutatorThread>
class PLATFORM_EXPORT InternalScope {
DISALLOW_NEW();
- DISALLOW_COPY_AND_ASSIGN(InternalScope);
using IdType =
std::conditional_t<scope_category == kMutatorThread, Id, ConcurrentId>;
@@ -157,6 +156,8 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
: tracer_(tracer), start_time_(base::TimeTicks::Now()), id_(id) {
StartTrace(args...);
}
+ InternalScope(const InternalScope&) = delete;
+ InternalScope& operator=(const InternalScope&) = delete;
~InternalScope() {
StopTrace();
@@ -194,12 +195,13 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
// the overall time (V8 + Blink) spent in GC on the main thread.
class PLATFORM_EXPORT BlinkGCInV8Scope {
DISALLOW_NEW();
- DISALLOW_COPY_AND_ASSIGN(BlinkGCInV8Scope);
public:
template <typename... Args>
BlinkGCInV8Scope(ThreadHeapStatsCollector* tracer)
: tracer_(tracer), start_time_(base::TimeTicks::Now()) {}
+ BlinkGCInV8Scope(const BlinkGCInV8Scope&) = delete;
+ BlinkGCInV8Scope& operator=(const BlinkGCInV8Scope&) = delete;
~BlinkGCInV8Scope() {
if (tracer_)
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc b/chromium/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc
index 8b05de2df81..e75cd53003e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.h"
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
namespace blink {
@@ -55,8 +55,10 @@ double MarkingSchedulingOracle::GetElapsedTimeInMs(base::TimeTicks start_time) {
base::TimeDelta MarkingSchedulingOracle::GetMinimumStepDuration() {
DCHECK_LT(0u, incrementally_marked_bytes_);
DCHECK(!incremental_marking_time_so_far_.is_zero());
- return incremental_marking_time_so_far_ * kMinimumMarkedBytesInStep /
- incrementally_marked_bytes_;
+ base::TimeDelta minimum_duration = incremental_marking_time_so_far_ *
+ kMinimumMarkedBytesInStep /
+ incrementally_marked_bytes_;
+ return std::min(minimum_duration, kMaximumIncrementalMarkingStepDuration);
}
base::TimeDelta MarkingSchedulingOracle::GetNextIncrementalStepDurationForTask(
@@ -75,7 +77,7 @@ base::TimeDelta MarkingSchedulingOracle::GetNextIncrementalStepDurationForTask(
if (expected_marked_bytes < actual_marked_bytes) {
// Marking is ahead of schedule, incremental marking doesn't need to
// do anything.
- return std::min(minimum_duration, kMaximumIncrementalMarkingStepDuration);
+ return minimum_duration;
}
// Assuming marking will take |kEstimatedMarkingTime|, overall there will
// be |estimated_live_bytes| live bytes to mark, and that marking speed is
@@ -90,8 +92,8 @@ base::TimeDelta MarkingSchedulingOracle::GetNextIncrementalStepDurationForTask(
incremental_marking_time_so_far_ *
(expected_marked_bytes - actual_marked_bytes) /
incrementally_marked_bytes_;
- return base::ClampToRange(marking_time_to_catch_up, minimum_duration,
- kMaximumIncrementalMarkingStepDuration);
+ return base::clamp(marking_time_to_catch_up, minimum_duration,
+ kMaximumIncrementalMarkingStepDuration);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/member.h b/chromium/third_party/blink/renderer/platform/heap/impl/member.h
index 97073bfff58..d5d373f870c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/member.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/member.h
@@ -425,6 +425,8 @@ class UntracedMember final
UntracedMember(T* raw) : Parent(raw) {}
+ UntracedMember(const UntracedMember& other) : Parent(other) {}
+
template <typename U>
UntracedMember(const Persistent<U>& other) : Parent(other) {}
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.cc b/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.cc
index 64733dc57f6..f61c39bea2e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.cc
@@ -29,7 +29,7 @@ PersistentRegionBase::~PersistentRegionBase() {
}
int PersistentRegionBase::NodesInUse() const {
- size_t persistent_count = 0;
+ int persistent_count = 0;
for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
if (!slots->slot[i].IsUnused())
@@ -58,7 +58,7 @@ void PersistentRegionBase::EnsureNodeSlots() {
void PersistentRegionBase::TraceNodesImpl(Visitor* visitor,
ShouldTraceCallback should_trace) {
free_list_head_ = nullptr;
- size_t persistent_count = 0;
+ int persistent_count = 0;
PersistentNodeSlots** prev_next = &slots_;
PersistentNodeSlots* slots = slots_;
while (slots) {
@@ -131,7 +131,7 @@ void PersistentRegion::PrepareForThreadStateTermination(ThreadState* state) {
slots = slots->next;
}
#if DCHECK_IS_ON()
- DCHECK_EQ(used_node_count_, 0u);
+ DCHECK_EQ(used_node_count_, 0);
#endif
}
@@ -186,7 +186,7 @@ void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() {
#if DCHECK_IS_ON()
ProcessHeap::CrossThreadPersistentMutex().AssertAcquired();
#endif
- size_t persistent_count = 0;
+ int persistent_count = 0;
for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
const PersistentNode& node = slots->slot[i];
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.h b/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.h
index 2f51cfa04ef..ab99685f923 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/persistent_node.h
@@ -214,7 +214,7 @@ class PLATFORM_EXPORT PersistentRegionBase {
PersistentNode* free_list_head_ = nullptr;
PersistentNodeSlots* slots_ = nullptr;
#if DCHECK_IS_ON()
- size_t used_node_count_ = 0;
+ int used_node_count_ = 0;
#endif
};
@@ -235,7 +235,7 @@ inline PersistentNode* PersistentRegionBase::AllocateNode(void* self,
void PersistentRegionBase::FreeNode(PersistentNode* persistent_node) {
#if DCHECK_IS_ON()
- DCHECK_GT(used_node_count_, 0u);
+ DCHECK_GT(used_node_count_, 0);
#endif
persistent_node->SetFreeListNext(free_list_head_);
free_list_head_ = persistent_node;
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/thread_state.h b/chromium/third_party/blink/renderer/platform/heap/impl/thread_state.h
index fa3d534bc80..48448467330 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/thread_state.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/thread_state.h
@@ -35,7 +35,6 @@
#include <memory>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/task/post_job.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
@@ -217,6 +216,9 @@ class PLATFORM_EXPORT ThreadState final {
static ThreadState* FromObject(const void*);
+ ThreadState(const ThreadState&) = delete;
+ ThreadState& operator=(const ThreadState&) = delete;
+
bool IsMainThread() const { return this == MainThreadState(); }
bool CheckThread() const { return thread_ == CurrentThread(); }
@@ -658,8 +660,6 @@ class PLATFORM_EXPORT ThreadState final {
friend class TestSupportingGC;
friend class ThreadStateSchedulingTest;
friend class UnifiedHeapController;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadState);
};
template <>
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h b/chromium/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h
index 57a4748b06b..77fc3801fc9 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h
@@ -17,12 +17,13 @@ namespace blink {
// allocations. E.g. allocations during GC.
class ThreadState::NoAllocationScope final {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(NoAllocationScope);
public:
explicit NoAllocationScope(ThreadState* state) : state_(state) {
state_->EnterNoAllocationScope();
}
+ NoAllocationScope(const NoAllocationScope&) = delete;
+ NoAllocationScope& operator=(const NoAllocationScope&) = delete;
~NoAllocationScope() { state_->LeaveNoAllocationScope(); }
private:
@@ -31,13 +32,14 @@ class ThreadState::NoAllocationScope final {
class ThreadState::SweepForbiddenScope final {
STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(SweepForbiddenScope);
public:
explicit SweepForbiddenScope(ThreadState* state) : state_(state) {
DCHECK(!state_->sweep_forbidden_);
state_->sweep_forbidden_ = true;
}
+ SweepForbiddenScope(const SweepForbiddenScope&) = delete;
+ SweepForbiddenScope& operator=(const SweepForbiddenScope&) = delete;
~SweepForbiddenScope() {
DCHECK(state_->sweep_forbidden_);
state_->sweep_forbidden_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/trace_traits.h b/chromium/third_party/blink/renderer/platform/heap/impl/trace_traits.h
index 506ead1c57e..91f8930768a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/trace_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/trace_traits.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_TRACE_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_TRACE_TRAITS_H_
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/impl/gc_info.h"
#include "third_party/blink/renderer/platform/heap/impl/heap_page.h"
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc b/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc
index 95df276bd63..c622451b270 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/platform/heap/unified_heap_controller.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h b/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h
index d8cdbc91b51..574ab5709f8 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_CONTROLLER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "v8/include/v8.h"
@@ -32,10 +31,11 @@ class ThreadState;
class PLATFORM_EXPORT UnifiedHeapController final
: public v8::EmbedderHeapTracer,
public ThreadHeapStatsObserver {
- DISALLOW_IMPLICIT_CONSTRUCTORS(UnifiedHeapController);
-
public:
+ UnifiedHeapController() = delete;
explicit UnifiedHeapController(ThreadState*);
+ UnifiedHeapController(const UnifiedHeapController&) = delete;
+ UnifiedHeapController& operator=(const UnifiedHeapController&) = delete;
~UnifiedHeapController() override;
// v8::EmbedderHeapTracer implementation.
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h b/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h
index f358b313cc1..6d0f4758011 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_MARKING_VISITOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_MARKING_VISITOR_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h"
#include "v8/include/v8.h"
@@ -23,6 +22,9 @@ struct WrapperTypeInfo;
// used from any thread.
class PLATFORM_EXPORT UnifiedHeapMarkingVisitorBase {
public:
+ UnifiedHeapMarkingVisitorBase(const UnifiedHeapMarkingVisitorBase&) = delete;
+ UnifiedHeapMarkingVisitorBase& operator=(
+ const UnifiedHeapMarkingVisitorBase&) = delete;
virtual ~UnifiedHeapMarkingVisitorBase() = default;
protected:
@@ -37,8 +39,6 @@ class PLATFORM_EXPORT UnifiedHeapMarkingVisitorBase {
private:
int task_id_;
-
- DISALLOW_COPY_AND_ASSIGN(UnifiedHeapMarkingVisitorBase);
};
// Same as the base visitor with the difference that it is bound to main thread.
@@ -56,14 +56,14 @@ class PLATFORM_EXPORT UnifiedHeapMarkingVisitor
const void*);
UnifiedHeapMarkingVisitor(ThreadState*, MarkingMode, v8::Isolate*);
+ UnifiedHeapMarkingVisitor(const UnifiedHeapMarkingVisitor&) = delete;
+ UnifiedHeapMarkingVisitor& operator=(const UnifiedHeapMarkingVisitor&) =
+ delete;
~UnifiedHeapMarkingVisitor() override = default;
protected:
using Visitor::Visit;
void Visit(const TraceWrapperV8Reference<v8::Value>&) final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(UnifiedHeapMarkingVisitor);
};
// Same as the base visitor with the difference that it is bound to a
@@ -76,6 +76,10 @@ class PLATFORM_EXPORT ConcurrentUnifiedHeapMarkingVisitor
MarkingMode,
v8::Isolate*,
int task_id);
+ ConcurrentUnifiedHeapMarkingVisitor(
+ const ConcurrentUnifiedHeapMarkingVisitor&) = delete;
+ ConcurrentUnifiedHeapMarkingVisitor& operator=(
+ const ConcurrentUnifiedHeapMarkingVisitor&) = delete;
~ConcurrentUnifiedHeapMarkingVisitor() override = default;
void FlushWorklists() override;
@@ -83,9 +87,6 @@ class PLATFORM_EXPORT ConcurrentUnifiedHeapMarkingVisitor
protected:
using Visitor::Visit;
void Visit(const TraceWrapperV8Reference<v8::Value>&) final;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConcurrentUnifiedHeapMarkingVisitor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/impl/visitor.h b/chromium/third_party/blink/renderer/platform/heap/impl/visitor.h
index 13c863a0ec8..8b16937a673 100644
--- a/chromium/third_party/blink/renderer/platform/heap/impl/visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/impl/visitor.h
@@ -213,7 +213,7 @@ class PLATFORM_EXPORT Visitor {
// Cross-component tracing interface.
template <typename V8Type>
void Trace(const TraceWrapperV8Reference<V8Type>& v8reference) {
- Visit(v8reference.template Cast<v8::Value>());
+ TraceV8ReferenceImpl(v8reference);
}
// Dynamic visitor interface.
@@ -300,6 +300,24 @@ class PLATFORM_EXPORT Visitor {
}
private:
+ template <typename V8Type>
+ void TraceV8ReferenceImpl(
+ const TraceWrapperV8Reference<V8Type>& v8reference,
+ std::enable_if_t<std::is_base_of<v8::Value, V8Type>::value>* = nullptr) {
+ Visit(v8reference.template Cast<v8::Value>());
+ }
+
+ template <typename V8Type>
+ void TraceV8ReferenceImpl(
+ const TraceWrapperV8Reference<V8Type>& v8reference,
+ std::enable_if_t<!std::is_base_of<v8::Value, V8Type>::value &&
+ std::is_base_of<v8::Data, V8Type>::value>* = nullptr) {
+ // The following cast is technically unsafe but works as the memory layout
+ // for the references is the same and V8 only needs to know that the value
+ // is a heap object.
+ Visit(v8reference.template UnsafeCast<v8::Value>());
+ }
+
template <typename T>
static void HandleWeakCell(const LivenessBroker&, const void*);
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent.h b/chromium/third_party/blink/renderer/platform/heap/persistent.h
index b9c9ae9a5d1..6540e2b9b17 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent.h
@@ -159,7 +159,7 @@ template <typename T>
struct BindUnwrapTraits<blink::CrossThreadWeakPersistent<T>> {
static blink::CrossThreadPersistent<T> Unwrap(
const blink::CrossThreadWeakPersistent<T>& wrapped) {
- return blink::CrossThreadPersistent<T>(wrapped);
+ return wrapped.Lock();
}
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.cc b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.cc
index dd1edb88b0d..e31f7721321 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.cc
@@ -5,8 +5,13 @@
#include "third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.h"
#include <inttypes.h>
+#include <ios>
+#include <sstream>
+#include <string>
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h"
#include "v8/include/cppgc/heap-statistics.h"
@@ -24,6 +29,27 @@ constexpr const char* HeapTypeString(
}
}
+void RecordType(
+ std::vector<cppgc::HeapStatistics::ObjectStatsEntry>& global_object_stats,
+ const cppgc::HeapStatistics::ObjectStatsEntry& local_object_stats,
+ size_t entry_index) {
+ global_object_stats[entry_index].allocated_bytes +=
+ local_object_stats.allocated_bytes;
+ global_object_stats[entry_index].object_count +=
+ local_object_stats.object_count;
+}
+
+// Use the id to generate a unique name as different types may provide the same
+// string as typename. This happens in component builds when cppgc creates
+// different internal types for the same C++ class when it is instantiated from
+// different libraries.
+std::string GetUniqueName(std::string name, size_t id) {
+ std::stringstream stream;
+ // Convert the id to hex to avoid it reading like an object count.
+ stream << name << " (0x" << std::hex << id << ")";
+ return stream.str();
+}
+
} // namespace
BlinkGCMemoryDumpProvider::BlinkGCMemoryDumpProvider(
@@ -33,7 +59,7 @@ BlinkGCMemoryDumpProvider::BlinkGCMemoryDumpProvider(
: thread_state_(thread_state),
heap_type_(heap_type),
dump_base_name_(
- "blink_gc/" + std::string(HeapTypeString(heap_type_)) + "/heap" +
+ "blink_gc/" + std::string(HeapTypeString(heap_type_)) +
(heap_type_ == HeapType::kBlinkWorkerThread
? "/" + base::StringPrintf(
"worker_0x%" PRIXPTR,
@@ -60,10 +86,11 @@ bool BlinkGCMemoryDumpProvider::OnMemoryDump(
::cppgc::HeapStatistics stats =
ThreadState::Current()->cpp_heap().CollectStatistics(detail_level);
- auto* heap_dump = process_memory_dump->CreateAllocatorDump(dump_base_name_);
+ auto* heap_dump =
+ process_memory_dump->CreateAllocatorDump(dump_base_name_ + "/heap");
heap_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- stats.physical_size_bytes);
+ stats.resident_size_bytes);
heap_dump->AddScalar("allocated_objects_size",
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
stats.used_size_bytes);
@@ -72,16 +99,19 @@ bool BlinkGCMemoryDumpProvider::OnMemoryDump(
return true;
}
- // Detailed statistics.
+ // Aggregate global object stats from per page statistics.
+ std::vector<cppgc::HeapStatistics::ObjectStatsEntry> global_object_stats;
+ global_object_stats.resize(stats.type_names.size());
+
+ // Detailed statistics follow.
for (const ::cppgc::HeapStatistics::SpaceStatistics& space_stats :
stats.space_stats) {
- std::string arena_dump_name = dump_base_name_ + "/" + space_stats.name;
- auto* arena_dump =
- process_memory_dump->CreateAllocatorDump(arena_dump_name);
- arena_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ auto* space_dump = process_memory_dump->CreateAllocatorDump(
+ heap_dump->absolute_name() + "/" + space_stats.name);
+ space_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- space_stats.physical_size_bytes);
- arena_dump->AddScalar("allocated_objects_size",
+ space_stats.resident_size_bytes);
+ space_dump->AddScalar("allocated_objects_size",
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
space_stats.used_size_bytes);
@@ -89,19 +119,42 @@ bool BlinkGCMemoryDumpProvider::OnMemoryDump(
for (const ::cppgc::HeapStatistics::PageStatistics& page_stats :
space_stats.page_stats) {
auto* page_dump = process_memory_dump->CreateAllocatorDump(
- arena_dump_name + "/pages/page_" +
+ space_dump->absolute_name() + "/pages/page_" +
base::NumberToString(page_count++));
+ page_dump->AddScalar("committed_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ page_stats.committed_size_bytes);
page_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- page_stats.physical_size_bytes);
+ page_stats.resident_size_bytes);
page_dump->AddScalar("allocated_objects_size",
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
page_stats.used_size_bytes);
+
+ const auto& object_stats = page_stats.object_statistics;
+ for (size_t i = 0; i < object_stats.size(); i++) {
+ if (!object_stats[i].object_count)
+ continue;
+
+ auto* page_class_dump = process_memory_dump->CreateAllocatorDump(
+ page_dump->absolute_name() + "/types/" +
+ GetUniqueName(stats.type_names[i], i));
+ page_class_dump->AddScalar(
+ base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ object_stats[i].object_count);
+ page_class_dump->AddScalar(
+ "allocated_objects_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ object_stats[i].allocated_bytes);
+
+ RecordType(global_object_stats, object_stats[i], i);
+ }
}
const ::cppgc::HeapStatistics::FreeListStatistics& free_list_stats =
space_stats.free_list_stats;
- for (wtf_size_t i = 0; i < free_list_stats.bucket_size.size(); ++i) {
+ for (size_t i = 0; i < free_list_stats.bucket_size.size(); ++i) {
constexpr size_t kDigits = 8;
std::string original_bucket_size =
base::NumberToString(free_list_stats.bucket_size[i]);
@@ -109,28 +162,40 @@ bool BlinkGCMemoryDumpProvider::OnMemoryDump(
std::string(kDigits - original_bucket_size.length(), '0') +
original_bucket_size;
auto* free_list_bucket_dump = process_memory_dump->CreateAllocatorDump(
- arena_dump_name + "/freelist/bucket_" + padded_bucket_size);
+ space_dump->absolute_name() + "/freelist/bucket_" +
+ padded_bucket_size);
free_list_bucket_dump->AddScalar(
- "free_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ "free_slot_count",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ free_list_stats.free_count[i]);
+ free_list_bucket_dump->AddScalar(
+ "free_usable_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
free_list_stats.free_size[i]);
}
+ }
- const ::cppgc::HeapStatistics::ObjectStatistics& object_stats =
- space_stats.object_stats;
- for (wtf_size_t i = 1; i < object_stats.num_types; i++) {
- if (object_stats.type_name[i].empty())
- continue;
-
- auto* class_dump = process_memory_dump->CreateAllocatorDump(
- arena_dump_name + "/classes/" + object_stats.type_name[i]);
- class_dump->AddScalar(
- "object_count", base::trace_event::MemoryAllocatorDump::kUnitsObjects,
- object_stats.type_count[i]);
- class_dump->AddScalar("object_size",
- base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- object_stats.type_bytes[i]);
- }
+ // Populate "allocated_objects" and "blink_objects/blink_gc" dumps.
+ const auto* allocated_objects_dump = process_memory_dump->CreateAllocatorDump(
+ dump_base_name_ + "/allocated_objects");
+ for (size_t i = 0; i < global_object_stats.size(); i++) {
+ auto* details = process_memory_dump->CreateAllocatorDump(
+ "blink_objects/blink_gc/" + GetUniqueName(stats.type_names[i], i));
+ details->AddScalar("allocated_objects_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ global_object_stats[i].allocated_bytes);
+ details->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ global_object_stats[i].object_count);
+ details->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ global_object_stats[i].allocated_bytes);
+ process_memory_dump->AddSuballocation(
+ details->guid(), dump_base_name_ + "/allocated_objects");
}
+ process_memory_dump->AddOwnershipEdge(allocated_objects_dump->guid(),
+ heap_dump->guid());
+
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h
index 2d81ed8ee91..ad05f4a5e59 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/hash_table.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
#include "v8/include/cppgc/custom-space.h"
#include "v8/include/cppgc/explicit-management.h"
#include "v8/include/cppgc/object-size-trait.h"
@@ -30,11 +31,16 @@ class HeapHashTableBacking final
using ValueType = typename Table::ValueType;
public:
- static ValueType* ToArray(ClassType* backing) {
+ // Although the HeapHashTableBacking is fully constructed, the array resulting
+ // from ToArray may not be fully constructed as the elements of the array are
+ // not initialized and may have null vtable pointers. Null vtable pointer
+ // violates CFI for polymorphic types.
+ NO_SANITIZE_UNRELATED_CAST ALWAYS_INLINE static ValueType* ToArray(
+ ClassType* backing) {
return reinterpret_cast<ValueType*>(backing);
}
- static ClassType* FromArray(ValueType* array) {
+ ALWAYS_INLINE static ClassType* FromArray(ValueType* array) {
return reinterpret_cast<ClassType*>(array);
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_vector_backing.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_vector_backing.h
index 68590093c5a..e2db74b9209 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_vector_backing.h
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_vector_backing.h
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/heap/trace_traits.h"
#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/container_annotations.h"
+#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
#include "third_party/blink/renderer/platform/wtf/vector_traits.h"
#include "v8/include/cppgc/allocation.h"
@@ -38,11 +39,16 @@ class HeapVectorBacking final
using ClassType = HeapVectorBacking<T, Traits>;
public:
- static T* ToArray(ClassType* backing) {
+ // Although the HeapVectorBacking is fully constructed, the array resulting
+ // from ToArray may not be fully constructed as the elements of the array are
+ // not initialized and may have null vtable pointers. Null vtable pointer
+ // violates CFI for polymorphic types.
+ NO_SANITIZE_UNRELATED_CAST ALWAYS_INLINE static T* ToArray(
+ ClassType* backing) {
return reinterpret_cast<T*>(backing);
}
- static ClassType* FromArray(T* payload) {
+ ALWAYS_INLINE static ClassType* FromArray(T* payload) {
return reinterpret_cast<ClassType*>(payload);
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h
index e81eb2f4d80..0b452aa7a68 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h"
#include "v8/include/cppgc/allocation.h"
#include "v8/include/cppgc/garbage-collected.h"
+#include "v8/include/cppgc/internal/pointer-policies.h"
#include "v8/include/cppgc/liveness-broker.h"
namespace blink {
@@ -41,6 +42,10 @@ T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) {
std::forward<Args>(args)...);
}
+static constexpr bool kBlinkGCHasDebugChecks =
+ !std::is_same<cppgc::internal::DefaultMemberCheckingPolicy,
+ cppgc::internal::DisabledCheckingPolicy>::value;
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
index b36b1d24e46..4179e550510 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
@@ -137,11 +137,11 @@ class PLATFORM_EXPORT HeapAllocator {
}
template <typename T>
- static void TraceBackingStoreIfMarked(T** slot) {
+ static void TraceBackingStoreIfMarked(T* object) {
HeapConsistency::WriteBarrierParams params;
- if (HeapConsistency::GetWriteBarrierType(slot, *slot, params) ==
+ if (HeapConsistency::GetWriteBarrierType(object, params) ==
HeapConsistency::WriteBarrierType::kMarking) {
- HeapConsistency::SteeleWriteBarrier(params, *slot);
+ HeapConsistency::SteeleWriteBarrier(params, object);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_local.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_local.h
new file mode 100644
index 00000000000..1a0c43b0eaf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_local.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_LOCAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_LOCAL_H_
+
+#include "base/compiler_specific.h"
+#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+// On component builds, always hide the thread_local variable behind a call.
+// This avoids complexity with "global-dyn" and allows to use "local-dyn"
+// instead, across all platforms. On non-component (release) builds, don't hide
+// the variable behind the call (to improve performance in access time), but use
+// different tls models on different platforms. On Windows, since chrome is
+// linked into the chrome.dll which is always linked to chrome.exe at static
+// link time (DT_NEEDED in ELF terms), use "init-exec". On Android, since the
+// library can be opened with "dlopen" (through JNI), use "local-dyn". On other
+// systems (Linux/ChromeOS/MacOS) use the fastest "local-exec".
+
+// |_____component_____|___non-component___|
+// ________|_tls_model__|_hide_|_tls_model__|_hide_|
+// Windows | local-dyn | yes | init-exec | no |
+// Android | local-dyn | yes | local-dyn | no |
+// Other | local-dyn | yes | local-exec | no |
+
+// The call is still cheaper than multiple calls through WTF/base/pthread*
+// layers.
+#if defined(COMPONENT_BUILD)
+#define BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY 1
+#else
+#define BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY 0
+#endif
+
+#if BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY
+#define BLINK_HEAP_THREAD_LOCAL_MODEL "local-dynamic"
+#else
+#if defined(OS_WIN)
+#define BLINK_HEAP_THREAD_LOCAL_MODEL "initial-exec"
+#elif defined(OS_ANDROID)
+#define BLINK_HEAP_THREAD_LOCAL_MODEL "local-dynamic"
+#else
+#define BLINK_HEAP_THREAD_LOCAL_MODEL "local-exec"
+#endif
+#endif
+
+#if defined(BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY)
+
+#define BLINK_HEAP_DECLARE_THREAD_LOCAL_GETTER(Name, Type, Member) \
+ static NOINLINE Type Name();
+#define BLINK_HEAP_DEFINE_THREAD_LOCAL_GETTER(Name, Type, Member) \
+ NOINLINE Type Name() { return Member; }
+
+#else // !defined(BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY)
+
+#define BLINK_HEAP_DECLARE_THREAD_LOCAL_GETTER(Name, Type, Member) \
+ static ALWAYS_INLINE Type Name() { return Member; }
+#define BLINK_HEAP_DEFINE_THREAD_LOCAL_GETTER(Name, Type, Member)
+
+#endif // defined(BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY)
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_LOCAL_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
index 78da3ce32f9..303c2839488 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
@@ -82,14 +82,17 @@ class BlinkRootsHandler final : public v8::EmbedderRootsHandler {
} // namespace
-// static
-base::LazyInstance<WTF::ThreadSpecific<ThreadState*>>::Leaky
- ThreadState::thread_specific_ = LAZY_INSTANCE_INITIALIZER;
+thread_local ThreadState* g_thread_specific_ CONSTINIT
+ __attribute__((tls_model(BLINK_HEAP_THREAD_LOCAL_MODEL))) = nullptr;
// static
alignas(ThreadState) uint8_t
ThreadState::main_thread_state_storage_[sizeof(ThreadState)];
+BLINK_HEAP_DEFINE_THREAD_LOCAL_GETTER(ThreadState::Current,
+ ThreadState*,
+ g_thread_specific_)
+
// static
ThreadState* ThreadState::AttachMainThread() {
return new (main_thread_state_storage_) ThreadState(gin::V8Platform::Get());
@@ -149,7 +152,7 @@ ThreadState::ThreadState(v8::Platform* platform)
allocation_handle_(cpp_heap_->GetAllocationHandle()),
heap_handle_(cpp_heap_->GetHeapHandle()),
thread_id_(CurrentThread()) {
- *(thread_specific_.Get()) = this;
+ g_thread_specific_ = this;
}
ThreadState::~ThreadState() {
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
index 8b6b1f920e0..682a0b54c5b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
@@ -6,11 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_H_
#include "base/compiler_specific.h"
-#include "base/lazy_instance.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
+#include "third_party/blink/renderer/platform/heap/v8_wrapper/thread_local.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "v8-profiler.h"
#include "v8/include/cppgc/heap-consistency.h"
@@ -61,13 +61,20 @@ using V8BuildEmbedderGraphCallback = void (*)(v8::Isolate*,
v8::EmbedderGraph*,
void*);
+// Storage for all ThreadState objects. This includes the main-thread
+// ThreadState as well. Keep it outside the class so that PLATFORM_EXPORT
+// doesn't apply to it (otherwise, clang-cl complains).
+extern thread_local ThreadState* g_thread_specific_ CONSTINIT
+ __attribute__((tls_model(BLINK_HEAP_THREAD_LOCAL_MODEL)));
+
class PLATFORM_EXPORT ThreadState final {
public:
class NoAllocationScope;
+ class GCForbiddenScope;
- static ALWAYS_INLINE ThreadState* Current() {
- return *(thread_specific_.Get());
- }
+ BLINK_HEAP_DECLARE_THREAD_LOCAL_GETTER(Current,
+ ThreadState*,
+ g_thread_specific_)
static ALWAYS_INLINE ThreadState* MainThreadState() {
return reinterpret_cast<ThreadState*>(main_thread_state_storage_);
@@ -132,10 +139,6 @@ class PLATFORM_EXPORT ThreadState final {
// Main-thread ThreadState avoids TLS completely by using a regular global.
// The object is manually managed and should not rely on global ctor/dtor.
static uint8_t main_thread_state_storage_[];
- // Storage for all ThreadState objects. This includes the main-thread
- // ThreadState as well.
- static base::LazyInstance<WTF::ThreadSpecific<ThreadState*>>::Leaky
- thread_specific_;
explicit ThreadState(v8::Platform*);
~ThreadState();
diff --git a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state_scopes.h b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state_scopes.h
index bec9605a0c6..82e71e98598 100644
--- a/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state_scopes.h
+++ b/chromium/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state_scopes.h
@@ -26,6 +26,22 @@ class ThreadState::NoAllocationScope final {
const cppgc::subtle::DisallowGarbageCollectionScope disallow_gc_;
};
+// The GCForbiddenScope class is used to prevent GC finalization
+// when it is not safe to do so.
+class ThreadState::GCForbiddenScope final {
+ STACK_ALLOCATED();
+
+ public:
+ explicit GCForbiddenScope(ThreadState* state)
+ : no_gc_(state->cpp_heap().GetHeapHandle()) {}
+
+ GCForbiddenScope(const NoAllocationScope&) = delete;
+ GCForbiddenScope& operator=(const NoAllocationScope&) = delete;
+
+ private:
+ const cppgc::subtle::NoGarbageCollectionScope no_gc_;
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_SCOPES_H_
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
index 44640ec509d..f81753809f2 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
@@ -44,6 +44,12 @@ namespace {
// known.
constexpr uint64_t kMaxAvifFileSize = 0x10000000; // 256 MB
+const char* AvifDecoderErrorMessage(const avifDecoder* decoder) {
+ // decoder->diag.error is a char array that stores a null-terminated C string.
+ return *decoder->diag.error != '\0' ? decoder->diag.error
+ : "(no error message)";
+}
+
// Builds a gfx::ColorSpace from the ITU-T H.273 (CICP) color description in the
// image. This color space is used to create the gfx::ColorTransform for the
// YUV-to-RGB conversion. If the image does not have an ICC profile, this color
@@ -197,7 +203,7 @@ void YUVAToRGBA(const avifImage* image,
avifGetPixelFormatInfo(image->yuvFormat, &format_info);
gfx::Point3F pixel;
const int max_channel_i = (1 << image->depth) - 1;
- const float max_channel = float{max_channel_i};
+ const float max_channel = static_cast<float>(max_channel_i);
for (uint32_t j = 0; j < image->height; ++j) {
const int uv_j = j >> format_info.chromaShiftY;
@@ -250,7 +256,7 @@ namespace blink {
AVIFImageDecoder::AVIFImageDecoder(AlphaOption alpha_option,
HighBitDepthDecodingOption hbd_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes,
+ wtf_size_t max_decoded_bytes,
AnimationOption animation_option)
: ImageDecoder(alpha_option, hbd_option, color_behavior, max_decoded_bytes),
animation_option_(animation_option) {}
@@ -300,14 +306,15 @@ IntSize AVIFImageDecoder::DecodedYUVSize(cc::YUVIndex index) const {
return Size();
}
-size_t AVIFImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
+wtf_size_t AVIFImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
DCHECK(IsDecodedSizeAvailable());
// Try to return the same width bytes as used by the dav1d library. This will
// allow DecodeToYUV() to copy each plane with a single memcpy() call.
//
// The comments for Dav1dPicAllocator in dav1d/picture.h require the pixel
// width be padded to a multiple of 128 pixels.
- int aligned_width = base::bits::Align(Size().Width(), 128);
+ wtf_size_t aligned_width =
+ static_cast<wtf_size_t>(base::bits::AlignUp(Size().Width(), 128));
if (index == cc::YUVIndex::kU || index == cc::YUVIndex::kV) {
aligned_width >>= chroma_shift_x_;
}
@@ -348,10 +355,15 @@ void AVIFImageDecoder::DecodeToYUV() {
DCHECK(decoder_);
DCHECK_EQ(decoded_frame_count_, 1u); // Not animation.
+ // If the image is decoded progressively, just render the highest progressive
+ // frame in image_planes_ because the callers of DecodeToYUV() assume that a
+ // complete scan will not be updated.
+ const int frame_index = progressive_ ? (decoder_->imageCount - 1) : 0;
+
// libavif cannot decode to an external buffer. So we need to copy from
// libavif's internal buffer to |image_planes_|.
// TODO(crbug.com/1099825): Enhance libavif to decode to an external buffer.
- auto ret = DecodeImage(0);
+ auto ret = DecodeImage(frame_index);
if (ret != AVIF_RESULT_OK) {
if (ret != AVIF_RESULT_WAITING_ON_IO)
SetFailed();
@@ -376,11 +388,12 @@ void AVIFImageDecoder::DecodeToYUV() {
uint32_t width = image->width;
uint32_t height = image->height;
- for (size_t plane_index = 0; plane_index < cc::kNumYUVPlanes; ++plane_index) {
+ for (wtf_size_t plane_index = 0; plane_index < cc::kNumYUVPlanes;
+ ++plane_index) {
const cc::YUVIndex plane = static_cast<cc::YUVIndex>(plane_index);
- const size_t src_row_bytes =
- base::strict_cast<size_t>(image->yuvRowBytes[plane_index]);
- const size_t dst_row_bytes = image_planes_->RowBytes(plane);
+ const wtf_size_t src_row_bytes =
+ base::strict_cast<wtf_size_t>(image->yuvRowBytes[plane_index]);
+ const wtf_size_t dst_row_bytes = image_planes_->RowBytes(plane);
if (bit_depth_ == 8) {
DCHECK_EQ(image_planes_->color_type(), kGray_8_SkColorType);
@@ -394,8 +407,8 @@ void AVIFImageDecoder::DecodeToYUV() {
reinterpret_cast<uint16_t*>(image->yuvPlanes[plane_index]);
uint16_t* dst = static_cast<uint16_t*>(image_planes_->Plane(plane));
if (image_planes_->color_type() == kA16_unorm_SkColorType) {
- const size_t src_stride = src_row_bytes / 2;
- const size_t dst_stride = dst_row_bytes / 2;
+ const wtf_size_t src_stride = src_row_bytes / 2;
+ const wtf_size_t dst_stride = dst_row_bytes / 2;
for (uint32_t j = 0; j < height; ++j) {
for (uint32_t i = 0; i < width; ++i) {
dst[j * dst_stride + i] =
@@ -425,7 +438,7 @@ int AVIFImageDecoder::RepetitionCount() const {
return decoded_frame_count_ > 1 ? kAnimationLoopInfinite : kAnimationNone;
}
-bool AVIFImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool AVIFImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
if (!IsDecodedSizeAvailable())
return false;
if (decoded_frame_count_ == 1)
@@ -434,16 +447,16 @@ bool AVIFImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
return false;
if (IsAllDataReceived())
return true;
- avifExtent dataExtent;
- if (avifDecoderNthImageMaxExtent(decoder_.get(), index, &dataExtent) !=
+ avifExtent data_extent;
+ if (avifDecoderNthImageMaxExtent(decoder_.get(), index, &data_extent) !=
AVIF_RESULT_OK) {
return false;
}
- return dataExtent.size == 0 ||
- dataExtent.offset + dataExtent.size <= data_->size();
+ return data_extent.size == 0 ||
+ data_extent.offset + data_extent.size <= data_->size();
}
-base::TimeDelta AVIFImageDecoder::FrameDurationAtIndex(size_t index) const {
+base::TimeDelta AVIFImageDecoder::FrameDurationAtIndex(wtf_size_t index) const {
return index < frame_buffer_cache_.size()
? frame_buffer_cache_[index].Duration()
: base::TimeDelta();
@@ -455,8 +468,8 @@ bool AVIFImageDecoder::ImageHasBothStillAndAnimatedSubImages() const {
if (decoded_frame_count_ > 1)
return true;
- constexpr size_t kMajorBrandOffset = 8;
- constexpr size_t kMajorBrandSize = 4;
+ constexpr wtf_size_t kMajorBrandOffset = 8;
+ constexpr wtf_size_t kMajorBrandSize = 4;
if (data_->size() < kMajorBrandOffset + kMajorBrandSize)
return false;
@@ -505,14 +518,14 @@ void AVIFImageDecoder::DecodeSize() {
ParseMetadata();
}
-size_t AVIFImageDecoder::DecodeFrameCount() {
+wtf_size_t AVIFImageDecoder::DecodeFrameCount() {
if (!Failed())
ParseMetadata();
return IsDecodedSizeAvailable() ? decoded_frame_count_
: frame_buffer_cache_.size();
}
-void AVIFImageDecoder::InitializeNewFrame(size_t index) {
+void AVIFImageDecoder::InitializeNewFrame(wtf_size_t index) {
auto& buffer = frame_buffer_cache_[index];
if (decode_to_half_float_)
buffer.SetPixelFormat(ImageFrame::PixelFormat::kRGBA_F16);
@@ -526,13 +539,42 @@ void AVIFImageDecoder::InitializeNewFrame(size_t index) {
buffer.SetDuration(base::TimeDelta::FromSecondsD(timing.duration));
}
-void AVIFImageDecoder::Decode(size_t index) {
+void AVIFImageDecoder::Decode(wtf_size_t index) {
if (Failed())
return;
UpdateAggressivePurging(index);
- auto ret = DecodeImage(index);
+ int frame_index = index;
+ // If the image is decoded progressively, find the highest progressive
+ // frame that we have received and decode from that frame index. Internally
+ // decoder_ still decodes the lower progressive frames, but they are only used
+ // as reference frames and not rendered.
+ if (progressive_) {
+ DCHECK_EQ(index, 0u);
+ // decoder_->imageIndex is the current image index. decoder_->imageIndex is
+ // initialized to -1. decoder_->imageIndex + 1 is the next image index.
+ DCHECK_LT(decoder_->imageIndex + 1, decoder_->imageCount);
+ for (frame_index = decoder_->imageIndex + 1;
+ frame_index + 1 < decoder_->imageCount; ++frame_index) {
+ avifExtent data_extent;
+ auto rv = avifDecoderNthImageMaxExtent(decoder_.get(), frame_index + 1,
+ &data_extent);
+ if (rv != AVIF_RESULT_OK) {
+ DVLOG(1) << "avifDecoderNthImageMaxExtent(" << frame_index + 1
+ << ") failed: " << avifResultToString(rv) << ": "
+ << AvifDecoderErrorMessage(decoder_.get());
+ SetFailed();
+ return;
+ }
+ if (data_extent.size != 0 &&
+ data_extent.offset + data_extent.size > data_->size()) {
+ break;
+ }
+ }
+ }
+
+ auto ret = DecodeImage(frame_index);
if (ret != AVIF_RESULT_OK) {
if (ret != AVIF_RESULT_WAITING_ON_IO)
SetFailed();
@@ -542,28 +584,32 @@ void AVIFImageDecoder::Decode(size_t index) {
const auto* image = decoder_->image;
ImageFrame& buffer = frame_buffer_cache_[index];
- DCHECK_EQ(buffer.GetStatus(), ImageFrame::kFrameEmpty);
+ DCHECK_NE(buffer.GetStatus(), ImageFrame::kFrameComplete);
- if (!InitFrameBuffer(index)) {
- DVLOG(1) << "Failed to create frame buffer...";
- SetFailed();
- return;
+ if (buffer.GetStatus() == ImageFrame::kFrameEmpty) {
+ if (!InitFrameBuffer(index)) {
+ DVLOG(1) << "Failed to create frame buffer...";
+ SetFailed();
+ return;
+ }
+ DCHECK_EQ(buffer.GetStatus(), ImageFrame::kFramePartial);
}
if (!RenderImage(image, &buffer)) {
SetFailed();
return;
}
-
ColorCorrectImage(&buffer);
-
buffer.SetPixelsChanged(true);
- buffer.SetHasAlpha(!!image->alphaPlane);
- buffer.SetStatus(ImageFrame::kFrameComplete);
- PostDecodeProcessing(index);
+
+ if (!progressive_ || frame_index + 1 == decoder_->imageCount) {
+ buffer.SetHasAlpha(!!image->alphaPlane);
+ buffer.SetStatus(ImageFrame::kFrameComplete);
+ PostDecodeProcessing(index);
+ }
}
-bool AVIFImageDecoder::CanReusePreviousFrameBuffer(size_t index) const {
+bool AVIFImageDecoder::CanReusePreviousFrameBuffer(wtf_size_t index) const {
// (a) Technically we can reuse the bitmap of the previous frame because the
// AVIF decoder handles frame dependence internally and we never need to
// preserve previous frames to decode later ones, and (b) since this function
@@ -592,7 +638,7 @@ avifResult AVIFImageDecoder::ReadFromSegmentReader(avifIO* io,
: AVIF_RESULT_WAITING_ON_IO;
}
- // It is more convenient to work with a variable of the size_t type. Since
+ // It is more convenient to work with a variable of the wtf_size_t type. Since
// offset <= io_data->reader->size() <= SIZE_MAX, this cast is safe.
size_t position = static_cast<size_t>(offset);
const size_t available_size = io_data->reader->size() - position;
@@ -639,6 +685,14 @@ bool AVIFImageDecoder::UpdateDemuxer() {
if (!decoder_)
return false;
+ // For simplicity, use a hardcoded maxThreads of 2, independent of the image
+ // size and processor count. Note: even if we want maxThreads to depend on
+ // the image size, it is impossible to do so because maxThreads is passed to
+ // dav1d_open() inside avifDecoderParse(), but the image size is not known
+ // until avifDecoderParse() returns successfully. See
+ // https://github.com/AOMediaCodec/libavif/issues/636.
+ decoder_->maxThreads = 2;
+
// TODO(wtc): Currently libavif always prioritizes the animation, but that's
// not correct. It should instead select animation or still image based on
// the preferred and major brands listed in the file.
@@ -674,6 +728,9 @@ bool AVIFImageDecoder::UpdateDemuxer() {
avifDecoderSetIO(decoder_.get(), &avif_io_);
}
+ // If all data is received, there is no point in decoding progressively.
+ decoder_->allowProgressive = !IsAllDataReceived();
+
auto ret = avifDecoderParse(decoder_.get());
if (ret == AVIF_RESULT_WAITING_ON_IO)
return true;
@@ -705,7 +762,10 @@ bool AVIFImageDecoder::UpdateDemuxer() {
}
DCHECK_GT(decoder_->imageCount, 0);
- decoded_frame_count_ = decoder_->imageCount;
+ progressive_ = decoder_->progressiveState == AVIF_PROGRESSIVE_STATE_ACTIVE;
+ // If the image is progressive, decoder_->imageCount is the number of
+ // progressive frames, but there is only one still image.
+ decoded_frame_count_ = progressive_ ? 1 : decoder_->imageCount;
bit_depth_ = container->depth;
decode_to_half_float_ =
ImageIsHighBitDepth() &&
@@ -815,13 +875,19 @@ bool AVIFImageDecoder::UpdateDemuxer() {
return SetSize(container->width, container->height);
}
-avifResult AVIFImageDecoder::DecodeImage(size_t index) {
+avifResult AVIFImageDecoder::DecodeImage(wtf_size_t index) {
const auto ret = avifDecoderNthImage(decoder_.get(), index);
// |index| should be less than what DecodeFrameCount() returns, so we should
// not get the AVIF_RESULT_NO_IMAGES_REMAINING error.
DCHECK_NE(ret, AVIF_RESULT_NO_IMAGES_REMAINING);
- if (ret != AVIF_RESULT_OK)
+ if (ret != AVIF_RESULT_OK) {
+ if (ret != AVIF_RESULT_WAITING_ON_IO) {
+ DVLOG(1) << "avifDecoderNthImage(" << index
+ << ") failed: " << avifResultToString(ret) << ": "
+ << AvifDecoderErrorMessage(decoder_.get());
+ }
return ret;
+ }
const auto* image = decoder_->image;
// Frame size must be equal to container size.
@@ -850,9 +916,11 @@ void AVIFImageDecoder::UpdateColorTransform(const gfx::ColorSpace& frame_cs,
// For YUV-to-RGB color conversion we can pass an invalid dst color space to
// skip the code for full color conversion.
+ gfx::ColorTransform::Options options;
+ options.src_bit_depth = bit_depth;
+ options.dst_bit_depth = bit_depth;
color_transform_ = gfx::ColorTransform::NewColorTransform(
- frame_cs, bit_depth, gfx::ColorSpace(), bit_depth,
- gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
+ frame_cs, gfx::ColorSpace(), options);
}
bool AVIFImageDecoder::RenderImage(const avifImage* image, ImageFrame* buffer) {
@@ -882,11 +950,11 @@ bool AVIFImageDecoder::RenderImage(const avifImage* image, ImageFrame* buffer) {
// supported.
if (IsColorSpaceSupportedByPCVR(image)) {
// Create temporary frame wrapping the YUVA planes.
- scoped_refptr<media::VideoFrame> frame;
auto pixel_format = AvifToVideoPixelFormat(image->yuvFormat, image->depth);
if (pixel_format == media::PIXEL_FORMAT_UNKNOWN)
return false;
auto size = gfx::Size(image->width, image->height);
+ scoped_refptr<media::VideoFrame> frame;
if (image->alphaPlane) {
DCHECK_EQ(pixel_format, media::PIXEL_FORMAT_I420);
pixel_format = media::PIXEL_FORMAT_I420A;
@@ -901,6 +969,8 @@ bool AVIFImageDecoder::RenderImage(const avifImage* image, ImageFrame* buffer) {
image->yuvRowBytes[1], image->yuvRowBytes[2], image->yuvPlanes[0],
image->yuvPlanes[1], image->yuvPlanes[2], base::TimeDelta());
}
+ if (!frame)
+ return false;
frame->set_color_space(frame_cs);
// Really only handles 709, 601, 2020, JPEG 8-bit conversions and uses
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h
index 8e83b88d208..4d4eff9ea46 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h
@@ -22,7 +22,7 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
AVIFImageDecoder(AlphaOption,
HighBitDepthDecodingOption,
const ColorBehavior&,
- size_t max_decoded_bytes,
+ wtf_size_t max_decoded_bytes,
AnimationOption);
AVIFImageDecoder(const AVIFImageDecoder&) = delete;
AVIFImageDecoder& operator=(const AVIFImageDecoder&) = delete;
@@ -34,13 +34,13 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
void OnSetData(SegmentReader* data) override;
cc::YUVSubsampling GetYUVSubsampling() const override;
IntSize DecodedYUVSize(cc::YUVIndex) const override;
- size_t DecodedYUVWidthBytes(cc::YUVIndex) const override;
+ wtf_size_t DecodedYUVWidthBytes(cc::YUVIndex) const override;
SkYUVColorSpace GetYUVColorSpace() const override;
uint8_t GetYUVBitDepth() const override;
void DecodeToYUV() override;
int RepetitionCount() const override;
- bool FrameIsReceivedAtIndex(size_t) const override;
- base::TimeDelta FrameDurationAtIndex(size_t) const override;
+ bool FrameIsReceivedAtIndex(wtf_size_t) const override;
+ base::TimeDelta FrameDurationAtIndex(wtf_size_t) const override;
bool ImageHasBothStillAndAnimatedSubImages() const override;
// Returns true if the data in fast_reader begins with a valid FileTypeBox
@@ -60,10 +60,10 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
// ImageDecoder:
void DecodeSize() override;
- size_t DecodeFrameCount() override;
- void InitializeNewFrame(size_t) override;
- void Decode(size_t) override;
- bool CanReusePreviousFrameBuffer(size_t) const override;
+ wtf_size_t DecodeFrameCount() override;
+ void InitializeNewFrame(wtf_size_t) override;
+ void Decode(wtf_size_t) override;
+ bool CanReusePreviousFrameBuffer(wtf_size_t) const override;
// Implements avifIOReadFunc, the |read| function in the avifIO struct.
static avifResult ReadFromSegmentReader(avifIO* io,
@@ -78,7 +78,7 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
// Decodes the frame at index |index| and checks if the frame's size, bit
// depth, and YUV format matches those reported by the container. The decoded
// frame is available in decoder_->image.
- avifResult DecodeImage(size_t index);
+ avifResult DecodeImage(wtf_size_t index);
// Updates or creates |color_transform_| for YUV-to-RGB conversion.
void UpdateColorTransform(const gfx::ColorSpace& frame_cs, int bit_depth);
@@ -97,9 +97,10 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
bool decode_to_half_float_ = false;
uint8_t chroma_shift_x_ = 0;
uint8_t chroma_shift_y_ = 0;
+ bool progressive_ = false;
// The YUV format from the container.
avifPixelFormat avif_yuv_format_ = AVIF_PIXEL_FORMAT_NONE;
- size_t decoded_frame_count_ = 0;
+ wtf_size_t decoded_frame_count_ = 0;
SkYUVColorSpace yuv_color_space_ = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
std::unique_ptr<avifDecoder, void (*)(avifDecoder*)> decoder_{nullptr,
nullptr};
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc
index e9c0f8f0d99..66f5f439888 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc
@@ -622,7 +622,7 @@ void ReadYUV(const char* file_name,
EXPECT_EQ(expected_y_size, y_size);
EXPECT_EQ(expected_uv_size, u_size);
- size_t row_bytes[3];
+ wtf_size_t row_bytes[3];
row_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY);
row_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU);
row_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV);
@@ -812,6 +812,12 @@ TEST(StaticAVIFTests, ValidImages) {
"/images/resources/avif/red-at-12-oclock-with-color-profile-12bpc.avif",
1, kAnimationNone);
#endif
+ TestByteByByteDecode(&CreateAVIFDecoder,
+ "/images/resources/avif/tiger_3layer_1res.avif", 1,
+ kAnimationNone);
+ TestByteByByteDecode(&CreateAVIFDecoder,
+ "/images/resources/avif/tiger_3layer_3res.avif", 1,
+ kAnimationNone);
}
TEST(StaticAVIFTests, YUV) {
@@ -883,6 +889,46 @@ TEST(StaticAVIFTests, SizeAvailableBeforeAllDataReceived) {
EXPECT_TRUE(decoder->IsSizeAvailable());
}
+TEST(StaticAVIFTests, ProgressiveDecoding) {
+ scoped_refptr<SharedBuffer> stream_buffer = WTF::SharedBuffer::Create();
+ scoped_refptr<SegmentReader> segment_reader =
+ SegmentReader::CreateFromSharedBuffer(stream_buffer);
+ std::unique_ptr<ImageDecoder> decoder = ImageDecoder::CreateByMimeType(
+ "image/avif", segment_reader, /*data_complete=*/false,
+ ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
+ ColorBehavior::Tag(), SkISize::MakeEmpty(),
+ ImageDecoder::AnimationOption::kUnspecified);
+
+ scoped_refptr<SharedBuffer> data =
+ ReadFile("/images/resources/avif/tiger_3layer_1res.avif");
+ ASSERT_TRUE(data.get());
+ ASSERT_EQ(data->size(), 70944u);
+
+ // This image has three layers. The first layer is 8299 bytes. Because of
+ // image headers and other overhead, if we pass exactly 8299 bytes to the
+ // decoder, the decoder does not have enough data to decode the first layer.
+ stream_buffer->Append(data->Data(), 8299u);
+ decoder->SetData(stream_buffer, /*all_data_received=*/false);
+ EXPECT_TRUE(decoder->IsSizeAvailable());
+ EXPECT_FALSE(decoder->Failed());
+ EXPECT_EQ(decoder->FrameCount(), 1u);
+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
+ ASSERT_TRUE(frame);
+ EXPECT_EQ(frame->GetStatus(), ImageFrame::kFrameEmpty);
+ EXPECT_FALSE(decoder->Failed());
+
+ // An additional 301 bytes are enough data for the decoder to decode the first
+ // layer. With progressive decoding, the frame buffer status will transition
+ // to ImageFrame::kFramePartial.
+ stream_buffer->Append(data->Data() + 8299u, 301u);
+ decoder->SetData(stream_buffer, /*all_data_received=*/false);
+ EXPECT_FALSE(decoder->Failed());
+ frame = decoder->DecodeFrameBufferAtIndex(0);
+ ASSERT_TRUE(frame);
+ EXPECT_EQ(frame->GetStatus(), ImageFrame::kFramePartial);
+ EXPECT_FALSE(decoder->Failed());
+}
+
using StaticAVIFColorTests = ::testing::TestWithParam<StaticColorCheckParam>;
INSTANTIATE_TEST_CASE_P(Parameterized,
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 c2fa20b0988..b98326a1440 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
@@ -38,11 +38,11 @@ namespace blink {
// Number of bits in .BMP used to store the file header (doesn't match
// "sizeof(BMPImageDecoder::BitmapFileHeader)" since we omit some fields and
// don't pack).
-static const size_t kSizeOfFileHeader = 14;
+static const wtf_size_t kSizeOfFileHeader = 14;
BMPImageDecoder::BMPImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes)
+ wtf_size_t max_decoded_bytes)
: ImageDecoder(alpha_option,
ImageDecoder::kDefaultBitDepth,
color_behavior,
@@ -78,7 +78,7 @@ void BMPImageDecoder::Decode(bool only_size) {
}
bool BMPImageDecoder::DecodeHelper(bool only_size) {
- size_t img_data_offset = 0;
+ wtf_size_t img_data_offset = 0;
if ((decoded_offset_ < kSizeOfFileHeader) &&
!ProcessFileHeader(img_data_offset))
return false;
@@ -95,7 +95,7 @@ bool BMPImageDecoder::DecodeHelper(bool only_size) {
return reader_->DecodeBMP(only_size);
}
-bool BMPImageDecoder::ProcessFileHeader(size_t& img_data_offset) {
+bool BMPImageDecoder::ProcessFileHeader(wtf_size_t& img_data_offset) {
// Read file header.
DCHECK(!decoded_offset_);
FastSharedBufferReader fast_reader(data_);
@@ -141,7 +141,8 @@ bool BMPImageDecoder::GetFileType(const FastSharedBufferReader& fast_reader,
return false;
file_header = fast_reader.GetConsecutiveData(decoded_offset_,
kSizeOfFileHeader, buffer);
- file_type = (uint16_t{file_header[0]} << 8) | uint8_t{file_header[1]};
+ file_type = (static_cast<uint16_t>(file_header[0]) << 8) |
+ static_cast<uint8_t>(file_header[1]);
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h
index 5b61a615952..b1081c85729 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h
@@ -42,7 +42,9 @@ class FastSharedBufferReader;
// This class decodes the BMP image format.
class PLATFORM_EXPORT BMPImageDecoder final : public ImageDecoder {
public:
- BMPImageDecoder(AlphaOption, const ColorBehavior&, size_t max_decoded_bytes);
+ BMPImageDecoder(AlphaOption,
+ const ColorBehavior&,
+ wtf_size_t max_decoded_bytes);
~BMPImageDecoder() override;
@@ -57,7 +59,7 @@ class PLATFORM_EXPORT BMPImageDecoder final : public ImageDecoder {
private:
// ImageDecoder:
void DecodeSize() override { Decode(true); }
- void Decode(size_t) override { Decode(false); }
+ void Decode(wtf_size_t) override { Decode(false); }
// Decodes the image. If |only_size| is true, stops decoding after
// calculating the image size. If decoding fails but there is no more
@@ -71,7 +73,7 @@ class PLATFORM_EXPORT BMPImageDecoder final : public ImageDecoder {
// Processes the file header at the beginning of the data. Sets
// |img_data_offset| based on the header contents. Returns true if the
// file header could be decoded.
- bool ProcessFileHeader(size_t& img_data_offset);
+ bool ProcessFileHeader(wtf_size_t& img_data_offset);
// Uses |fast_reader| and |buffer| to read the file header into |file_header|.
// Computes |file_type| from the file header. Returns whether there was
@@ -84,7 +86,7 @@ class PLATFORM_EXPORT BMPImageDecoder final : public ImageDecoder {
// An index into |data_| representing how much we've already decoded.
// Note that this only tracks data _this_ class decodes; once the
// BMPImageReader takes over this will not be updated further.
- size_t decoded_offset_;
+ wtf_size_t decoded_offset_;
// The reader used to do most of the BMP decoding.
std::unique_ptr<BMPImageReader> reader_;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
index f0952cc8013..37aa9ef4ce4 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
@@ -69,8 +69,8 @@ constexpr uint8_t nBitTo8BitlookupTable[] = {
namespace blink {
BMPImageReader::BMPImageReader(ImageDecoder* parent,
- size_t decoded_and_header_offset,
- size_t img_data_offset,
+ wtf_size_t decoded_and_header_offset,
+ wtf_size_t img_data_offset,
bool is_in_ico)
: parent_(parent),
decoded_offset_(decoded_and_header_offset),
@@ -99,7 +99,7 @@ bool BMPImageReader::DecodeBMP(bool only_size) {
if (!info_header_.size && !ReadInfoHeaderSize())
return false;
- const size_t header_end = header_offset_ + info_header_.size;
+ const wtf_size_t header_end = header_offset_ + info_header_.size;
// Read and process info header.
if ((decoded_offset_ < header_end) && !ProcessInfoHeader())
return false;
@@ -185,7 +185,7 @@ bool BMPImageReader::ReadInfoHeaderSize() {
// Don't allow the header to overflow (which would be harmless here, but
// problematic or at least confusing in other places), or to overrun the
// image data.
- const size_t header_end = header_offset_ + info_header_.size;
+ const wtf_size_t header_end = header_offset_ + info_header_.size;
if ((header_end < header_offset_) ||
(img_data_offset_ && (img_data_offset_ < header_end)))
return parent_->SetFailed();
@@ -597,10 +597,10 @@ bool BMPImageReader::ProcessBitmasks() {
// info header.
// Fail if we don't have enough file space for the bitmasks.
- const size_t header_end = header_offset_ + info_header_.size;
+ const wtf_size_t header_end = header_offset_ + info_header_.size;
const bool read_alpha = info_header_.compression == ALPHABITFIELDS;
- const size_t kBitmasksSize = read_alpha ? 16 : 12;
- const size_t bitmasks_end = header_end + kBitmasksSize;
+ const wtf_size_t kBitmasksSize = read_alpha ? 16 : 12;
+ const wtf_size_t bitmasks_end = header_end + kBitmasksSize;
if ((bitmasks_end < header_end) ||
(img_data_offset_ && (img_data_offset_ < bitmasks_end)))
return parent_->SetFailed();
@@ -688,7 +688,7 @@ bool BMPImageReader::ProcessBitmasks() {
++bit_shifts_right_[i];
// Count size of mask.
- size_t num_bits = 0;
+ wtf_size_t num_bits = 0;
for (; temp_mask & 1; temp_mask >>= 1)
++num_bits;
@@ -718,12 +718,12 @@ bool BMPImageReader::ProcessBitmasks() {
bool BMPImageReader::ProcessColorTable() {
// On non-OS/2 1.x, an extra padding byte is present, which we need to skip.
- const size_t bytes_per_color = is_os21x_ ? 3 : 4;
+ const wtf_size_t bytes_per_color = is_os21x_ ? 3 : 4;
- const size_t header_end = header_offset_ + info_header_.size;
- size_t colors_in_palette = info_header_.clr_used;
- size_t table_size_in_bytes = colors_in_palette * bytes_per_color;
- const size_t table_end = header_end + table_size_in_bytes;
+ const wtf_size_t header_end = header_offset_ + info_header_.size;
+ wtf_size_t colors_in_palette = info_header_.clr_used;
+ wtf_size_t table_size_in_bytes = colors_in_palette * bytes_per_color;
+ const wtf_size_t table_end = header_end + table_size_in_bytes;
if (table_end < header_end)
return parent_->SetFailed();
@@ -739,14 +739,14 @@ bool BMPImageReader::ProcessColorTable() {
return false;
color_table_.resize(info_header_.clr_used);
- for (size_t i = 0; i < colors_in_palette; ++i) {
+ for (wtf_size_t i = 0; i < colors_in_palette; ++i) {
color_table_[i].rgb_blue = ReadUint8(0);
color_table_[i].rgb_green = ReadUint8(1);
color_table_[i].rgb_red = ReadUint8(2);
decoded_offset_ += bytes_per_color;
}
// Explicitly zero any colors past the end of a truncated palette.
- for (size_t i = colors_in_palette; i < info_header_.clr_used; ++i) {
+ for (wtf_size_t i = colors_in_palette; i < info_header_.clr_used; ++i) {
color_table_[i].rgb_blue = 0;
color_table_[i].rgb_green = 0;
color_table_[i].rgb_red = 0;
@@ -951,16 +951,16 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessNonRLEData(
// Determine how many bytes of data the requested number of pixels
// requires.
- const size_t pixels_per_byte = 8 / info_header_.bit_count;
- const size_t bytes_per_pixel = info_header_.bit_count / 8;
- const size_t unpadded_num_bytes =
+ const wtf_size_t pixels_per_byte = 8 / info_header_.bit_count;
+ const wtf_size_t bytes_per_pixel = info_header_.bit_count / 8;
+ const wtf_size_t unpadded_num_bytes =
(info_header_.bit_count < 16)
? ((num_pixels + pixels_per_byte - 1) / pixels_per_byte)
: (num_pixels * bytes_per_pixel);
// RLE runs are zero-padded at the end to a multiple of 16 bits. Non-RLE
// data is in rows and is zero-padded to a multiple of 32 bits.
- const size_t align_bits = in_rle ? 1 : 3;
- const size_t padded_num_bytes =
+ const wtf_size_t align_bits = in_rle ? 1 : 3;
+ const wtf_size_t padded_num_bytes =
(unpadded_num_bytes + align_bits) & ~align_bits;
// Decode as many rows as we can. (For RLE, where we only want to decode
@@ -975,10 +975,10 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessNonRLEData(
// Decode pixels one byte at a time, left to right (so, starting at
// the most significant bits in the byte).
const uint8_t mask = (1 << info_header_.bit_count) - 1;
- for (size_t end_offset = decoded_offset_ + unpadded_num_bytes;
+ for (wtf_size_t end_offset = decoded_offset_ + unpadded_num_bytes;
decoded_offset_ < end_offset; ++decoded_offset_) {
uint8_t pixel_data = ReadUint8(0);
- for (size_t pixel = 0;
+ for (wtf_size_t pixel = 0;
(pixel < pixels_per_byte) && (coord_.X() < end_x); ++pixel) {
const wtf_size_t color_index =
(pixel_data >> (8 - info_header_.bit_count)) & mask;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h
index b04278c4093..147e3a6b945 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h
@@ -33,7 +33,6 @@
#include <stdint.h>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -61,9 +60,11 @@ class PLATFORM_EXPORT BMPImageReader final {
// |buffer| points at an empty ImageFrame that we'll initialize and
// fill with decoded data.
BMPImageReader(ImageDecoder* parent,
- size_t decoded_and_header_offset,
- size_t img_data_offset,
+ wtf_size_t decoded_and_header_offset,
+ wtf_size_t img_data_offset,
bool is_in_ico);
+ BMPImageReader(const BMPImageReader&) = delete;
+ BMPImageReader& operator=(const BMPImageReader&) = delete;
~BMPImageReader();
void SetBuffer(ImageFrame* buffer) { buffer_ = buffer; }
@@ -119,7 +120,7 @@ class PLATFORM_EXPORT BMPImageReader final {
uint8_t rgb_red;
};
- inline uint8_t ReadUint8(size_t offset) const {
+ inline uint8_t ReadUint8(wtf_size_t offset) const {
return fast_reader_.GetOneByte(decoded_offset_ + offset);
}
@@ -322,16 +323,16 @@ class PLATFORM_EXPORT BMPImageReader final {
FastSharedBufferReader fast_reader_{nullptr};
// An index into |data_| representing how much we've already decoded.
- size_t decoded_offset_;
+ wtf_size_t decoded_offset_;
// The file offset at which the BMP info header starts.
- size_t header_offset_;
+ wtf_size_t header_offset_;
// The file offset at which the actual image bits start. When decoding
// ICO files, this is set to 0, since it's not stored anywhere in a
// header; the reader functions expect the image data to start
// immediately after the header and (if necessary) color table.
- size_t img_data_offset_;
+ wtf_size_t img_data_offset_;
// The BMP info header.
BitmapInfoHeader info_header_;
@@ -395,8 +396,6 @@ class PLATFORM_EXPORT BMPImageReader final {
// header, thus doubling it). If |is_in_ico_| is true, this variable tracks
// whether we've begun decoding this mask yet.
bool decoding_and_mask_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(BMPImageReader);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h b/chromium/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h
index f21890fd73c..a66d17a8a11 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_FAST_SHARED_BUFFER_READER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_FAST_SHARED_BUFFER_READER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -48,6 +47,8 @@ class PLATFORM_EXPORT FastSharedBufferReader final {
public:
FastSharedBufferReader(scoped_refptr<SegmentReader> data);
+ FastSharedBufferReader(const FastSharedBufferReader&) = delete;
+ FastSharedBufferReader& operator=(const FastSharedBufferReader&) = delete;
void SetData(scoped_refptr<SegmentReader>);
@@ -89,8 +90,6 @@ class PLATFORM_EXPORT FastSharedBufferReader final {
// Data position in |data_| pointed to by |segment_|.
mutable size_t data_position_;
-
- DISALLOW_COPY_AND_ASSIGN(FastSharedBufferReader);
};
} // namespace blink
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 29490055264..eb0225a0674 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
@@ -27,7 +27,6 @@
#include <limits>
#include "third_party/blink/renderer/platform/image-decoders/segment_stream.h"
-#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
#include "third_party/skia/include/core/SkImageInfo.h"
namespace blink {
@@ -52,7 +51,7 @@ ImageFrame::DisposalMethod ConvertDisposalMethod(
GIFImageDecoder::GIFImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes)
+ wtf_size_t max_decoded_bytes)
: ImageDecoder(alpha_option,
ImageDecoder::kDefaultBitDepth,
color_behavior,
@@ -152,14 +151,14 @@ int GIFImageDecoder::RepetitionCount() const {
return repetition_count_;
}
-bool GIFImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool GIFImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
SkCodec::FrameInfo frame_info;
if (!codec_ || !codec_->getFrameInfo(index, &frame_info))
return false;
return frame_info.fFullyReceived;
}
-base::TimeDelta GIFImageDecoder::FrameDurationAtIndex(size_t index) const {
+base::TimeDelta GIFImageDecoder::FrameDurationAtIndex(wtf_size_t index) const {
if (index < frame_buffer_cache_.size())
return frame_buffer_cache_[index].Duration();
return base::TimeDelta();
@@ -171,7 +170,7 @@ bool GIFImageDecoder::SetFailed() {
return ImageDecoder::SetFailed();
}
-size_t GIFImageDecoder::ClearCacheExceptFrame(size_t index) {
+wtf_size_t GIFImageDecoder::ClearCacheExceptFrame(wtf_size_t index) {
if (frame_buffer_cache_.size() <= 1)
return 0;
@@ -179,7 +178,7 @@ size_t GIFImageDecoder::ClearCacheExceptFrame(size_t index) {
// possible that frame has been evicted. A later frame which could also
// be used as the required frame may still be cached. Try to preserve a frame
// that is still cached.
- size_t index2 = kNotFound;
+ wtf_size_t index2 = kNotFound;
if (index < frame_buffer_cache_.size()) {
const ImageFrame& frame = frame_buffer_cache_[index];
if (frame.RequiredPreviousFrameIndex() != kNotFound &&
@@ -192,14 +191,14 @@ size_t GIFImageDecoder::ClearCacheExceptFrame(size_t index) {
return ClearCacheExceptTwoFrames(index, index2);
}
-size_t GIFImageDecoder::DecodeFrameCount() {
+wtf_size_t GIFImageDecoder::DecodeFrameCount() {
if (!codec_ || segment_stream_->IsCleared())
return frame_buffer_cache_.size();
return codec_->getFrameCount();
}
-void GIFImageDecoder::InitializeNewFrame(size_t index) {
+void GIFImageDecoder::InitializeNewFrame(wtf_size_t index) {
DCHECK(codec_);
ImageFrame& frame = frame_buffer_cache_[index];
@@ -214,18 +213,18 @@ void GIFImageDecoder::InitializeNewFrame(size_t index) {
bool frame_info_received = codec_->getFrameInfo(index, &frame_info);
DCHECK(frame_info_received);
frame.SetDuration(base::TimeDelta::FromMilliseconds(frame_info.fDuration));
- size_t required_previous_frame_index;
+ wtf_size_t required_previous_frame_index;
if (frame_info.fRequiredFrame == SkCodec::kNoFrame) {
required_previous_frame_index = kNotFound;
} else {
required_previous_frame_index =
- static_cast<size_t>(frame_info.fRequiredFrame);
+ static_cast<wtf_size_t>(frame_info.fRequiredFrame);
}
frame.SetRequiredPreviousFrameIndex(required_previous_frame_index);
frame.SetDisposalMethod(ConvertDisposalMethod(frame_info.fDisposalMethod));
}
-void GIFImageDecoder::Decode(size_t index) {
+void GIFImageDecoder::Decode(wtf_size_t index) {
if (!codec_ || segment_stream_->IsCleared())
return;
@@ -240,14 +239,15 @@ void GIFImageDecoder::Decode(size_t index) {
UpdateAggressivePurging(index);
if (frame.GetStatus() == ImageFrame::kFrameEmpty) {
- size_t required_previous_frame_index = frame.RequiredPreviousFrameIndex();
+ wtf_size_t required_previous_frame_index =
+ frame.RequiredPreviousFrameIndex();
if (required_previous_frame_index == kNotFound) {
frame.AllocatePixelData(Size().Width(), Size().Height(),
ColorSpaceForSkImages());
frame.ZeroFillPixelData();
prior_frame_ = SkCodec::kNoFrame;
} else {
- size_t previous_frame_index = GetViableReferenceFrameIndex(index);
+ wtf_size_t previous_frame_index = GetViableReferenceFrameIndex(index);
if (previous_frame_index == kNotFound) {
previous_frame_index = required_previous_frame_index;
Decode(previous_frame_index);
@@ -336,17 +336,18 @@ void GIFImageDecoder::Decode(size_t index) {
}
}
-bool GIFImageDecoder::CanReusePreviousFrameBuffer(size_t frame_index) const {
+bool GIFImageDecoder::CanReusePreviousFrameBuffer(
+ wtf_size_t frame_index) const {
DCHECK_LT(frame_index, frame_buffer_cache_.size());
return frame_buffer_cache_[frame_index].GetDisposalMethod() !=
ImageFrame::kDisposeOverwritePrevious;
}
-size_t GIFImageDecoder::GetViableReferenceFrameIndex(
- size_t dependent_index) const {
+wtf_size_t GIFImageDecoder::GetViableReferenceFrameIndex(
+ wtf_size_t dependent_index) const {
DCHECK_LT(dependent_index, frame_buffer_cache_.size());
- size_t required_previous_frame_index =
+ wtf_size_t required_previous_frame_index =
frame_buffer_cache_[dependent_index].RequiredPreviousFrameIndex();
// Any frame in the range [|required_previous_frame_index|, |dependent_index|)
@@ -360,7 +361,7 @@ size_t GIFImageDecoder::GetViableReferenceFrameIndex(
DCHECK_NE(required_previous_frame_index, kNotFound);
// Loop backwards because the frames most likely to be in cache are the most
// recent.
- for (size_t i = dependent_index - 1; i != required_previous_frame_index;
+ for (wtf_size_t i = dependent_index - 1; i != required_previous_frame_index;
i--) {
const ImageFrame& frame = frame_buffer_cache_[i];
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.h
index 33838b8fb15..24e885a47e5 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/skia/include/codec/SkCodec.h"
@@ -40,39 +39,43 @@ class SegmentStream;
// This class decodes the GIF image format.
class PLATFORM_EXPORT GIFImageDecoder final : public ImageDecoder {
public:
- GIFImageDecoder(AlphaOption, const ColorBehavior&, size_t max_decoded_bytes);
+ GIFImageDecoder(AlphaOption,
+ const ColorBehavior&,
+ wtf_size_t max_decoded_bytes);
+ GIFImageDecoder(const GIFImageDecoder&) = delete;
+ GIFImageDecoder& operator=(const GIFImageDecoder&) = delete;
~GIFImageDecoder() override;
// ImageDecoder:
String FilenameExtension() const override { return "gif"; }
void OnSetData(SegmentReader* data) override;
int RepetitionCount() const override;
- bool FrameIsReceivedAtIndex(size_t) const override;
- base::TimeDelta FrameDurationAtIndex(size_t) const override;
+ bool FrameIsReceivedAtIndex(wtf_size_t) const override;
+ base::TimeDelta FrameDurationAtIndex(wtf_size_t) const override;
// CAUTION: SetFailed() deletes |codec_|. Be careful to avoid
// accessing deleted memory.
bool SetFailed() override;
- size_t ClearCacheExceptFrame(size_t) override;
+ wtf_size_t ClearCacheExceptFrame(wtf_size_t) override;
private:
// ImageDecoder:
void DecodeSize() override {}
- size_t DecodeFrameCount() override;
- void InitializeNewFrame(size_t) override;
- void Decode(size_t) override;
+ wtf_size_t DecodeFrameCount() override;
+ void InitializeNewFrame(wtf_size_t) override;
+ void Decode(wtf_size_t) override;
// When the disposal method of the frame is DisposeOverWritePrevious, the
// next frame will use a previous frame's buffer as its starting state, so
// we can't take over the data in that case. Before calling this method, the
// caller must verify that the frame exists.
- bool CanReusePreviousFrameBuffer(size_t) const override;
+ bool CanReusePreviousFrameBuffer(wtf_size_t) const override;
// When a frame depends on a previous frame's content, there is a list of
// candidate reference frames. This function will find a previous frame from
// that list which satisfies the requirements of being a reference frame
// (kFrameComplete, not kDisposeOverwritePrevious).
// If no frame is found, it returns kNotFound.
- size_t GetViableReferenceFrameIndex(size_t) const;
+ wtf_size_t GetViableReferenceFrameIndex(wtf_size_t) const;
std::unique_ptr<SkCodec> codec_;
// |codec_| owns the SegmentStream, but we need access to it to append more
@@ -80,8 +83,6 @@ class PLATFORM_EXPORT GIFImageDecoder final : public ImageDecoder {
SegmentStream* segment_stream_ = nullptr;
mutable int repetition_count_ = kAnimationLoopOnce;
int prior_frame_ = SkCodec::kNoFrame;
-
- DISALLOW_COPY_AND_ASSIGN(GIFImageDecoder);
};
} // namespace blink
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 26453874cf7..51d0d088105 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
@@ -38,12 +38,12 @@ namespace blink {
// Number of bits in .ICO/.CUR used to store the directory and its entries,
// respectively (doesn't match sizeof values for member structs since we omit
// some fields).
-static const size_t kSizeOfDirectory = 6;
-static const size_t kSizeOfDirEntry = 16;
+static const wtf_size_t kSizeOfDirectory = 6;
+static const wtf_size_t kSizeOfDirEntry = 16;
ICOImageDecoder::ICOImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes)
+ wtf_size_t max_decoded_bytes)
: ImageDecoder(alpha_option,
ImageDecoder::kDefaultBitDepth,
color_behavior,
@@ -59,7 +59,7 @@ void ICOImageDecoder::OnSetData(SegmentReader* data) {
if (*i)
(*i)->SetData(data);
}
- for (size_t i = 0; i < png_decoders_.size(); ++i)
+ for (wtf_size_t i = 0; i < png_decoders_.size(); ++i)
SetDataForPNGDecoderAtIndex(i);
}
@@ -67,7 +67,7 @@ IntSize ICOImageDecoder::Size() const {
return frame_size_.IsEmpty() ? ImageDecoder::Size() : frame_size_;
}
-IntSize ICOImageDecoder::FrameSizeAtIndex(size_t index) const {
+IntSize ICOImageDecoder::FrameSizeAtIndex(wtf_size_t index) const {
return (index && (index < dir_entries_.size())) ? dir_entries_[index].size_
: Size();
}
@@ -80,7 +80,7 @@ bool ICOImageDecoder::SetSize(unsigned width, unsigned height) {
: ((IntSize(width, height) == frame_size_) || SetFailed());
}
-bool ICOImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool ICOImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
if (index >= dir_entries_.size())
return false;
@@ -102,7 +102,8 @@ bool ICOImageDecoder::HotSpot(IntPoint& hot_spot) const {
return HotSpotAtIndex(0, hot_spot);
}
-bool ICOImageDecoder::HotSpotAtIndex(size_t index, IntPoint& hot_spot) const {
+bool ICOImageDecoder::HotSpotAtIndex(wtf_size_t index,
+ IntPoint& hot_spot) const {
if (index >= dir_entries_.size() || file_type_ != CURSOR)
return false;
@@ -120,7 +121,7 @@ bool ICOImageDecoder::CompareEntries(const IconDirectoryEntry& a,
: (a_entry_area > b_entry_area);
}
-size_t ICOImageDecoder::DecodeFrameCount() {
+wtf_size_t ICOImageDecoder::DecodeFrameCount() {
DecodeSize();
// If DecodeSize() fails, return the existing number of frames. This way
@@ -135,7 +136,7 @@ size_t ICOImageDecoder::DecodeFrameCount() {
// the file, and we still want to display these if they don't trigger decoding
// failures elsewhere.
if (!IsAllDataReceived()) {
- for (size_t i = 0; i < dir_entries_.size(); ++i) {
+ for (wtf_size_t i = 0; i < dir_entries_.size(); ++i) {
const IconDirectoryEntry& dir_entry = dir_entries_[i];
if ((dir_entry.image_offset_ + dir_entry.byte_size_) > data_->size())
return i;
@@ -144,14 +145,14 @@ size_t ICOImageDecoder::DecodeFrameCount() {
return dir_entries_.size();
}
-void ICOImageDecoder::SetDataForPNGDecoderAtIndex(size_t index) {
+void ICOImageDecoder::SetDataForPNGDecoderAtIndex(wtf_size_t index) {
if (!png_decoders_[index])
return;
png_decoders_[index]->SetData(data_.get(), IsAllDataReceived());
}
-void ICOImageDecoder::Decode(size_t index, bool only_size) {
+void ICOImageDecoder::Decode(wtf_size_t index, bool only_size) {
if (Failed() || !data_)
return;
@@ -186,7 +187,7 @@ bool ICOImageDecoder::DecodeDirectory() {
ProcessDirectoryEntries();
}
-bool ICOImageDecoder::DecodeAtIndex(size_t index) {
+bool ICOImageDecoder::DecodeAtIndex(wtf_size_t index) {
SECURITY_DCHECK(index < dir_entries_.size());
const IconDirectoryEntry& dir_entry = dir_entries_[index];
const ImageType image_type = ImageTypeAtIndex(index);
@@ -331,7 +332,7 @@ ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::ReadDirectoryEntry() {
return entry;
}
-ICOImageDecoder::ImageType ICOImageDecoder::ImageTypeAtIndex(size_t index) {
+ICOImageDecoder::ImageType ICOImageDecoder::ImageTypeAtIndex(wtf_size_t index) {
// Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic
// number.
SECURITY_DCHECK(data_);
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h
index 50154408df1..de58f086114 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h
@@ -43,16 +43,20 @@ class PNGImageDecoder;
// This class decodes the ICO and CUR image formats.
class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
public:
- ICOImageDecoder(AlphaOption, const ColorBehavior&, size_t max_decoded_bytes);
+ ICOImageDecoder(AlphaOption,
+ const ColorBehavior&,
+ wtf_size_t max_decoded_bytes);
+ ICOImageDecoder(const ICOImageDecoder&) = delete;
+ ICOImageDecoder& operator=(const ICOImageDecoder&) = delete;
~ICOImageDecoder() override;
// ImageDecoder:
String FilenameExtension() const override { return "ico"; }
void OnSetData(SegmentReader*) override;
IntSize Size() const override;
- IntSize FrameSizeAtIndex(size_t) const override;
+ IntSize FrameSizeAtIndex(wtf_size_t) const override;
bool SetSize(unsigned width, unsigned height) override;
- bool FrameIsReceivedAtIndex(size_t) const override;
+ bool FrameIsReceivedAtIndex(wtf_size_t) const override;
// CAUTION: SetFailed() deletes all readers and decoders. Be careful to
// avoid accessing deleted memory, especially when calling this from
// inside BMPImageReader!
@@ -87,12 +91,12 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
// ImageDecoder:
void DecodeSize() override { Decode(0, true); }
- size_t DecodeFrameCount() override;
- void Decode(size_t index) override { Decode(index, false); }
+ wtf_size_t DecodeFrameCount() override;
+ void Decode(wtf_size_t index) override { Decode(index, false); }
// TODO (scroggo): These functions are identical to functions in
// BMPImageReader. Share code?
- inline uint8_t ReadUint8(size_t offset) const {
+ inline uint8_t ReadUint8(wtf_size_t offset) const {
return fast_reader_.GetOneByte(decoded_offset_ + offset);
}
@@ -111,12 +115,12 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
}
// If the desired PNGImageDecoder exists, gives it the appropriate data.
- void SetDataForPNGDecoderAtIndex(size_t);
+ void SetDataForPNGDecoderAtIndex(wtf_size_t);
// Decodes the entry at |index|. If |only_size| is true, stops decoding
// after calculating the image size. If decoding fails but there is no
// more data coming, sets the "decode failure" flag.
- void Decode(size_t index, bool only_size);
+ void Decode(wtf_size_t index, bool only_size);
// Decodes the directory and directory entries at the beginning of the
// data, and initializes members. Returns true if all decoding
@@ -124,7 +128,7 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
bool DecodeDirectory();
// Decodes the specified entry.
- bool DecodeAtIndex(size_t);
+ bool DecodeAtIndex(wtf_size_t);
// Processes the ICONDIR at the beginning of the data. Returns true if
// the directory could be decoded.
@@ -137,7 +141,7 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
// Stores the hot-spot for |index| in |hot_spot| and returns true,
// or returns false if there is none.
- bool HotSpotAtIndex(size_t index, IntPoint& hot_spot) const;
+ bool HotSpotAtIndex(wtf_size_t index, IntPoint& hot_spot) const;
// Reads and returns a directory entry from the current offset into
// |data|.
@@ -145,14 +149,14 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
// Determines whether the desired entry is a BMP or PNG. Returns true
// if the type could be determined.
- ImageType ImageTypeAtIndex(size_t);
+ ImageType ImageTypeAtIndex(wtf_size_t);
FastSharedBufferReader fast_reader_{nullptr};
// An index into |data_| representing how much we've already decoded.
// Note that this only tracks data _this_ class decodes; once the
// BMPImageReader takes over this will not be updated further.
- size_t decoded_offset_ = 0;
+ wtf_size_t decoded_offset_ = 0;
// Which type of file (ICO/CUR) this is.
FileType file_type_;
@@ -164,7 +168,7 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
// Count of directory entries is parsed from header before initializing
// dir_entries_. dir_entries_ is populated only when full header
// information including directory entries is available.
- size_t dir_entries_count_ = 0;
+ wtf_size_t dir_entries_count_ = 0;
// The image decoders for the various frames.
typedef Vector<std::unique_ptr<BMPImageReader>> BMPReaders;
@@ -175,8 +179,6 @@ class PLATFORM_EXPORT ICOImageDecoder final : public ImageDecoder {
// Valid only while a BMPImageReader is decoding, this holds the size
// for the particular entry being decoded.
IntSize frame_size_;
-
- DISALLOW_COPY_AND_ASSIGN(ICOImageDecoder);
};
} // namespace blink
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 97f3920d108..1adfa9a9892 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
@@ -76,16 +76,17 @@ cc::ImageType FileExtensionToImageType(String image_extension) {
return cc::ImageType::kInvalid;
}
-size_t CalculateMaxDecodedBytes(
+wtf_size_t CalculateMaxDecodedBytes(
ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option,
const SkISize& desired_size) {
- const size_t max_decoded_bytes =
- Platform::Current() ? Platform::Current()->MaxDecodedImageBytes()
- : ImageDecoder::kNoDecodedImageByteLimit;
+ const wtf_size_t max_decoded_bytes =
+ Platform::Current()
+ ? static_cast<wtf_size_t>(Platform::Current()->MaxDecodedImageBytes())
+ : ImageDecoder::kNoDecodedImageByteLimit;
if (desired_size.isEmpty())
return max_decoded_bytes;
- const size_t num_pixels = desired_size.width() * desired_size.height();
+ const wtf_size_t num_pixels = desired_size.width() * desired_size.height();
if (high_bit_depth_decoding_option == ImageDecoder::kDefaultBitDepth)
return std::min(4 * num_pixels, max_decoded_bytes);
@@ -121,7 +122,7 @@ inline bool MatchesBMPSignature(const char* contents) {
return !memcmp(contents, "BM", 2) || !memcmp(contents, "BA", 2);
}
-constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1;
+constexpr wtf_size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1;
// static
String SniffMimeTypeInternal(scoped_refptr<SegmentReader> reader) {
@@ -164,8 +165,8 @@ String SniffMimeTypeInternal(scoped_refptr<SegmentReader> reader) {
} // namespace
-const size_t ImageDecoder::kNoDecodedImageByteLimit =
- Platform::kNoDecodedImageByteLimit;
+const wtf_size_t ImageDecoder::kNoDecodedImageByteLimit =
+ static_cast<wtf_size_t>(-1);
std::unique_ptr<ImageDecoder> ImageDecoder::Create(
scoped_refptr<SegmentReader> data,
@@ -193,7 +194,7 @@ std::unique_ptr<ImageDecoder> ImageDecoder::CreateByMimeType(
const ColorBehavior& color_behavior,
const SkISize& desired_size,
AnimationOption animation_option) {
- const size_t max_decoded_bytes =
+ const wtf_size_t max_decoded_bytes =
CalculateMaxDecodedBytes(high_bit_depth_decoding_option, desired_size);
// Note: The mime types below should match those supported by
@@ -373,7 +374,7 @@ bool ImageDecoder::IsSizeAvailable() {
}
const IntSize size = DecodedSize();
- const size_t decoded_size_bytes =
+ const wtf_size_t decoded_size_bytes =
size.Width() * size.Height() * decoded_bytes_per_pixel;
if (decoded_size_bytes > max_decoded_bytes_) {
LOG(WARNING) << "Blocked decode of oversized image: " << size.Width() << "x"
@@ -396,12 +397,12 @@ cc::ImageHeaderMetadata ImageDecoder::MakeMetadataForDecodeAcceleration()
return image_metadata;
}
-size_t ImageDecoder::FrameCount() {
- const size_t old_size = frame_buffer_cache_.size();
- const size_t new_size = DecodeFrameCount();
+wtf_size_t ImageDecoder::FrameCount() {
+ const wtf_size_t old_size = frame_buffer_cache_.size();
+ const wtf_size_t new_size = DecodeFrameCount();
if (old_size != new_size) {
frame_buffer_cache_.resize(new_size);
- for (size_t i = old_size; i < new_size; ++i) {
+ for (wtf_size_t i = old_size; i < new_size; ++i) {
frame_buffer_cache_[i].SetPremultiplyAlpha(premultiply_alpha_);
InitializeNewFrame(i);
}
@@ -409,7 +410,7 @@ size_t ImageDecoder::FrameCount() {
return new_size;
}
-ImageFrame* ImageDecoder::DecodeFrameBufferAtIndex(size_t index) {
+ImageFrame* ImageDecoder::DecodeFrameBufferAtIndex(wtf_size_t index) {
TRACE_EVENT0("blink", "ImageDecoder::DecodeFrameBufferAtIndex");
if (index >= FrameCount())
@@ -425,40 +426,40 @@ ImageFrame* ImageDecoder::DecodeFrameBufferAtIndex(size_t index) {
return frame;
}
-bool ImageDecoder::FrameHasAlphaAtIndex(size_t index) const {
+bool ImageDecoder::FrameHasAlphaAtIndex(wtf_size_t index) const {
return !FrameIsReceivedAtIndex(index) ||
frame_buffer_cache_[index].HasAlpha();
}
-bool ImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool ImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
// Animated images override this method to return the status based on the data
// received for the queried frame.
return IsAllDataReceived();
}
-bool ImageDecoder::FrameIsDecodedAtIndex(size_t index) const {
+bool ImageDecoder::FrameIsDecodedAtIndex(wtf_size_t index) const {
return index < frame_buffer_cache_.size() &&
frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameComplete;
}
-size_t ImageDecoder::FrameBytesAtIndex(size_t index) const {
+wtf_size_t ImageDecoder::FrameBytesAtIndex(wtf_size_t index) const {
if (index >= frame_buffer_cache_.size() ||
frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameEmpty)
return 0;
- size_t decoded_bytes_per_pixel = 4;
+ wtf_size_t decoded_bytes_per_pixel = 4;
if (frame_buffer_cache_[index].GetPixelFormat() ==
ImageFrame::PixelFormat::kRGBA_F16) {
decoded_bytes_per_pixel = 8;
}
IntSize size = FrameSizeAtIndex(index);
- base::CheckedNumeric<size_t> area = size.Width();
+ base::CheckedNumeric<wtf_size_t> area = size.Width();
area *= size.Height();
area *= decoded_bytes_per_pixel;
return area.ValueOrDie();
}
-size_t ImageDecoder::ClearCacheExceptFrame(size_t clear_except_frame) {
+wtf_size_t ImageDecoder::ClearCacheExceptFrame(wtf_size_t clear_except_frame) {
// Don't clear if there are no frames or only one frame.
if (frame_buffer_cache_.size() <= 1)
return 0;
@@ -477,7 +478,7 @@ size_t ImageDecoder::ClearCacheExceptFrame(size_t clear_except_frame) {
//
// If either 1 or 2 is true, store the required previous frame in
// |clear_except_frame2| so it won't be cleared.
- size_t clear_except_frame2 = kNotFound;
+ wtf_size_t clear_except_frame2 = kNotFound;
if (clear_except_frame < frame_buffer_cache_.size()) {
const ImageFrame& frame = frame_buffer_cache_[clear_except_frame];
if (!FrameStatusSufficientForSuccessors(clear_except_frame) ||
@@ -500,10 +501,11 @@ size_t ImageDecoder::ClearCacheExceptFrame(size_t clear_except_frame) {
return ClearCacheExceptTwoFrames(clear_except_frame, clear_except_frame2);
}
-size_t ImageDecoder::ClearCacheExceptTwoFrames(size_t clear_except_frame1,
- size_t clear_except_frame2) {
- size_t frame_bytes_cleared = 0;
- for (size_t i = 0; i < frame_buffer_cache_.size(); ++i) {
+wtf_size_t ImageDecoder::ClearCacheExceptTwoFrames(
+ wtf_size_t clear_except_frame1,
+ wtf_size_t clear_except_frame2) {
+ wtf_size_t frame_bytes_cleared = 0;
+ for (wtf_size_t i = 0; i < frame_buffer_cache_.size(); ++i) {
if (frame_buffer_cache_[i].GetStatus() != ImageFrame::kFrameEmpty &&
i != clear_except_frame1 && i != clear_except_frame2) {
frame_bytes_cleared += FrameBytesAtIndex(i);
@@ -513,14 +515,14 @@ size_t ImageDecoder::ClearCacheExceptTwoFrames(size_t clear_except_frame1,
return frame_bytes_cleared;
}
-void ImageDecoder::ClearFrameBuffer(size_t frame_index) {
+void ImageDecoder::ClearFrameBuffer(wtf_size_t frame_index) {
frame_buffer_cache_[frame_index].ClearPixelData();
}
-Vector<size_t> ImageDecoder::FindFramesToDecode(size_t index) const {
+Vector<wtf_size_t> ImageDecoder::FindFramesToDecode(wtf_size_t index) const {
DCHECK_LT(index, frame_buffer_cache_.size());
- Vector<size_t> frames_to_decode;
+ Vector<wtf_size_t> frames_to_decode;
do {
frames_to_decode.push_back(index);
index = frame_buffer_cache_[index].RequiredPreviousFrameIndex();
@@ -529,7 +531,7 @@ Vector<size_t> ImageDecoder::FindFramesToDecode(size_t index) const {
return frames_to_decode;
}
-bool ImageDecoder::PostDecodeProcessing(size_t index) {
+bool ImageDecoder::PostDecodeProcessing(wtf_size_t index) {
DCHECK(index < frame_buffer_cache_.size());
if (frame_buffer_cache_[index].GetStatus() != ImageFrame::kFrameComplete)
@@ -541,7 +543,7 @@ bool ImageDecoder::PostDecodeProcessing(size_t index) {
return true;
}
-void ImageDecoder::CorrectAlphaWhenFrameBufferSawNoAlpha(size_t index) {
+void ImageDecoder::CorrectAlphaWhenFrameBufferSawNoAlpha(wtf_size_t index) {
DCHECK(index < frame_buffer_cache_.size());
ImageFrame& buffer = frame_buffer_cache_[index];
@@ -592,7 +594,7 @@ void ImageDecoder::CorrectAlphaWhenFrameBufferSawNoAlpha(size_t index) {
}
}
-bool ImageDecoder::InitFrameBuffer(size_t frame_index) {
+bool ImageDecoder::InitFrameBuffer(wtf_size_t frame_index) {
DCHECK(frame_index < frame_buffer_cache_.size());
ImageFrame* const buffer = &frame_buffer_cache_[frame_index];
@@ -601,7 +603,8 @@ bool ImageDecoder::InitFrameBuffer(size_t frame_index) {
if (buffer->GetStatus() != ImageFrame::kFrameEmpty)
return true;
- size_t required_previous_frame_index = buffer->RequiredPreviousFrameIndex();
+ wtf_size_t required_previous_frame_index =
+ buffer->RequiredPreviousFrameIndex();
if (required_previous_frame_index == kNotFound) {
// This frame doesn't rely on any previous data.
if (!buffer->AllocatePixelData(Size().Width(), Size().Height(),
@@ -645,7 +648,7 @@ bool ImageDecoder::InitFrameBuffer(size_t frame_index) {
return true;
}
-void ImageDecoder::UpdateAggressivePurging(size_t index) {
+void ImageDecoder::UpdateAggressivePurging(wtf_size_t index) {
if (purge_aggressively_)
return;
@@ -661,7 +664,7 @@ void ImageDecoder::UpdateAggressivePurging(size_t index) {
// As we decode we will learn the total number of frames, and thus total
// possible image memory used.
- size_t decoded_bytes_per_pixel = 4;
+ wtf_size_t decoded_bytes_per_pixel = 4;
if (frame_buffer_cache_.size() && frame_buffer_cache_[0].GetPixelFormat() ==
ImageFrame::PixelFormat::kRGBA_F16) {
@@ -685,8 +688,8 @@ void ImageDecoder::UpdateAggressivePurging(size_t index) {
}
}
-size_t ImageDecoder::FindRequiredPreviousFrame(size_t frame_index,
- bool frame_rect_is_opaque) {
+wtf_size_t ImageDecoder::FindRequiredPreviousFrame(wtf_size_t frame_index,
+ bool frame_rect_is_opaque) {
DCHECK_LT(frame_index, frame_buffer_cache_.size());
if (!frame_index) {
// The first frame doesn't rely on any previous data.
@@ -701,7 +704,7 @@ size_t ImageDecoder::FindRequiredPreviousFrame(size_t frame_index,
// The starting state for this frame depends on the previous frame's
// disposal method.
- size_t prev_frame = frame_index - 1;
+ wtf_size_t prev_frame = frame_index - 1;
const ImageFrame* prev_buffer = &frame_buffer_cache_[prev_frame];
// Frames that use the DisposeOverwritePrevious method are effectively
@@ -750,7 +753,7 @@ ImagePlanes::ImagePlanes() {
}
ImagePlanes::ImagePlanes(void* planes[cc::kNumYUVPlanes],
- const size_t row_bytes[cc::kNumYUVPlanes],
+ const wtf_size_t row_bytes[cc::kNumYUVPlanes],
SkColorType color_type)
: color_type_(color_type) {
for (int i = 0; i < cc::kNumYUVPlanes; ++i) {
@@ -760,11 +763,11 @@ ImagePlanes::ImagePlanes(void* planes[cc::kNumYUVPlanes],
}
void* ImagePlanes::Plane(cc::YUVIndex index) {
- return planes_[static_cast<size_t>(index)];
+ return planes_[static_cast<wtf_size_t>(index)];
}
-size_t ImagePlanes::RowBytes(cc::YUVIndex index) const {
- return row_bytes_[static_cast<size_t>(index)];
+wtf_size_t ImagePlanes::RowBytes(cc::YUVIndex index) const {
+ return row_bytes_[static_cast<wtf_size_t>(index)];
}
ColorProfile::ColorProfile(const skcms_ICCProfile& profile,
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 effbfd10d45..33f0bbffc09 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
@@ -65,6 +65,8 @@ class PLATFORM_EXPORT ImagePlanes final {
public:
ImagePlanes();
+ ImagePlanes(const ImagePlanes&) = delete;
+ ImagePlanes& operator=(const ImagePlanes&) = delete;
// |color_type| is kGray_8_SkColorType if GetYUVBitDepth() == 8 and either
// kA16_float_SkColorType or kA16_unorm_SkColorType if GetYUVBitDepth() > 8.
@@ -72,22 +74,20 @@ class PLATFORM_EXPORT ImagePlanes final {
// TODO(crbug/910276): To support YUVA, ImagePlanes needs to support a
// variable number of planes.
ImagePlanes(void* planes[cc::kNumYUVPlanes],
- const size_t row_bytes[cc::kNumYUVPlanes],
+ const wtf_size_t row_bytes[cc::kNumYUVPlanes],
SkColorType color_type);
void* Plane(cc::YUVIndex);
- size_t RowBytes(cc::YUVIndex) const;
+ wtf_size_t RowBytes(cc::YUVIndex) const;
SkColorType color_type() const { return color_type_; }
void SetHasCompleteScan() { has_complete_scan_ = true; }
bool HasCompleteScan() const { return has_complete_scan_; }
private:
void* planes_[cc::kNumYUVPlanes];
- size_t row_bytes_[cc::kNumYUVPlanes];
+ wtf_size_t row_bytes_[cc::kNumYUVPlanes];
SkColorType color_type_;
bool has_complete_scan_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(ImagePlanes);
};
class PLATFORM_EXPORT ColorProfile final {
@@ -95,6 +95,8 @@ class PLATFORM_EXPORT ColorProfile final {
public:
ColorProfile(const skcms_ICCProfile&, std::unique_ptr<uint8_t[]> = nullptr);
+ ColorProfile(const ColorProfile&) = delete;
+ ColorProfile& operator=(const ColorProfile&) = delete;
static std::unique_ptr<ColorProfile> Create(const void* buffer, size_t size);
const skcms_ICCProfile* GetProfile() const { return &profile_; }
@@ -102,8 +104,6 @@ class PLATFORM_EXPORT ColorProfile final {
private:
skcms_ICCProfile profile_;
std::unique_ptr<uint8_t[]> buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(ColorProfile);
};
class PLATFORM_EXPORT ColorProfileTransform final {
@@ -112,6 +112,8 @@ class PLATFORM_EXPORT ColorProfileTransform final {
public:
ColorProfileTransform(const skcms_ICCProfile* src_profile,
const skcms_ICCProfile* dst_profile);
+ ColorProfileTransform(const ColorProfileTransform&) = delete;
+ ColorProfileTransform& operator=(const ColorProfileTransform&) = delete;
const skcms_ICCProfile* SrcProfile() const;
const skcms_ICCProfile* DstProfile() const;
@@ -119,8 +121,6 @@ class PLATFORM_EXPORT ColorProfileTransform final {
private:
const skcms_ICCProfile* src_profile_;
skcms_ICCProfile dst_profile_;
-
- DISALLOW_COPY_AND_ASSIGN(ColorProfileTransform);
};
// ImageDecoder is a base for all format-specific decoders
@@ -130,7 +130,7 @@ class PLATFORM_EXPORT ImageDecoder {
USING_FAST_MALLOC(ImageDecoder);
public:
- static const size_t kNoDecodedImageByteLimit;
+ static const wtf_size_t kNoDecodedImageByteLimit;
enum AlphaOption { kAlphaPremultiplied, kAlphaNotPremultiplied };
enum HighBitDepthDecodingOption {
@@ -166,6 +166,8 @@ class PLATFORM_EXPORT ImageDecoder {
kPreferStillImage,
};
+ ImageDecoder(const ImageDecoder&) = delete;
+ ImageDecoder& operator=(const ImageDecoder&) = delete;
virtual ~ImageDecoder() = default;
// Returns a caller-owned decoder of the appropriate type. Returns nullptr if
@@ -268,7 +270,7 @@ class PLATFORM_EXPORT ImageDecoder {
// Image decoders that support YUV decoding must override this to
// return the width of each row of the memory allocation.
- virtual size_t DecodedYUVWidthBytes(cc::YUVIndex) const {
+ virtual wtf_size_t DecodedYUVWidthBytes(cc::YUVIndex) const {
NOTREACHED();
return 0;
}
@@ -298,7 +300,7 @@ class PLATFORM_EXPORT ImageDecoder {
// sizes. This does NOT differ from Size() for GIF or WebP, since
// decoding GIF or WebP composites any smaller frames against previous
// frames to create full-size frames.
- virtual IntSize FrameSizeAtIndex(size_t) const { return Size(); }
+ virtual IntSize FrameSizeAtIndex(wtf_size_t) const { return Size(); }
// Returns whether the size is legal (i.e. not going to result in
// overflow elsewhere). If not, marks decoding as failed.
@@ -321,33 +323,33 @@ class PLATFORM_EXPORT ImageDecoder {
//
// Note: FrameCount() returns the return value of DecodeFrameCount(). For more
// information on the return value, see the comment for DecodeFrameCount().
- size_t FrameCount();
+ wtf_size_t FrameCount();
virtual int RepetitionCount() const { return kAnimationNone; }
// Decodes as much of the requested frame as possible, and returns an
// ImageDecoder-owned pointer.
- ImageFrame* DecodeFrameBufferAtIndex(size_t);
+ ImageFrame* DecodeFrameBufferAtIndex(wtf_size_t);
// Whether the requested frame has alpha.
- virtual bool FrameHasAlphaAtIndex(size_t) const;
+ virtual bool FrameHasAlphaAtIndex(wtf_size_t) const;
// Whether or not the frame is fully received.
- virtual bool FrameIsReceivedAtIndex(size_t) const;
+ virtual bool FrameIsReceivedAtIndex(wtf_size_t) const;
// Returns true if a cached complete decode is available.
- bool FrameIsDecodedAtIndex(size_t) const;
+ bool FrameIsDecodedAtIndex(wtf_size_t) const;
// Duration for displaying a frame. This method is only used by animated
// images.
- virtual base::TimeDelta FrameDurationAtIndex(size_t) const {
+ virtual base::TimeDelta FrameDurationAtIndex(wtf_size_t) const {
return base::TimeDelta();
}
// Number of bytes in the decoded frame. Returns 0 if the decoder doesn't
// have this frame cached (either because it hasn't been decoded, or because
// it has been cleared).
- virtual size_t FrameBytesAtIndex(size_t) const;
+ virtual wtf_size_t FrameBytesAtIndex(wtf_size_t) const;
ImageOrientation Orientation() const { return orientation_; }
IntSize DensityCorrectedSize() const { return density_corrected_size_; }
@@ -374,7 +376,7 @@ class PLATFORM_EXPORT ImageDecoder {
return premultiply_alpha_ ? kAlphaPremultiplied : kAlphaNotPremultiplied;
}
- size_t GetMaxDecodedBytes() const { return max_decoded_bytes_; }
+ wtf_size_t GetMaxDecodedBytes() const { return max_decoded_bytes_; }
// Sets the "decode failure" flag. For caller convenience (since so
// many callers want to return false after calling this), returns false
@@ -393,7 +395,7 @@ class PLATFORM_EXPORT ImageDecoder {
// Callers may pass WTF::kNotFound to clear all frames.
// Note: If |frame_buffer_cache_| contains only one frame, it won't be
// cleared. Returns the number of bytes of frame data actually cleared.
- virtual size_t ClearCacheExceptFrame(size_t);
+ virtual wtf_size_t ClearCacheExceptFrame(wtf_size_t);
// If the image has a cursor hot-spot, stores it in the argument
// and returns true. Otherwise returns false.
@@ -436,7 +438,7 @@ class PLATFORM_EXPORT ImageDecoder {
ImageDecoder(AlphaOption alpha_option,
HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes)
+ wtf_size_t max_decoded_bytes)
: premultiply_alpha_(alpha_option == kAlphaPremultiplied),
high_bit_depth_decoding_option_(high_bit_depth_decoding_option),
color_behavior_(color_behavior),
@@ -461,13 +463,13 @@ class PLATFORM_EXPORT ImageDecoder {
// Image formats which do not use more than one frame do not need to
// worry about this; see comments on
// ImageFrame::required_previous_frame_index_.
- size_t FindRequiredPreviousFrame(size_t frame_index,
- bool frame_rect_is_opaque);
+ wtf_size_t FindRequiredPreviousFrame(wtf_size_t frame_index,
+ bool frame_rect_is_opaque);
// This is called by ClearCacheExceptFrame() if that method decides it wants
// to preserve another frame, to avoid unnecessary redecoding.
- size_t ClearCacheExceptTwoFrames(size_t, size_t);
- virtual void ClearFrameBuffer(size_t frame_index);
+ wtf_size_t ClearCacheExceptTwoFrames(wtf_size_t, wtf_size_t);
+ virtual void ClearFrameBuffer(wtf_size_t frame_index);
// Decodes the image sufficiently to determine the image size.
virtual void DecodeSize() = 0;
@@ -486,7 +488,7 @@ class PLATFORM_EXPORT ImageDecoder {
// parsed. Alternatively, if the total frame count is available in the image
// header, this method may return the total frame count without checking how
// many frames are received.
- virtual size_t DecodeFrameCount() { return 1; }
+ virtual wtf_size_t DecodeFrameCount() { return 1; }
// Called to initialize the frame buffer with the given index, based on the
// provided and previous frame's characteristics. Returns true on success.
@@ -494,27 +496,27 @@ class PLATFORM_EXPORT ImageDecoder {
// On failure, the client should call SetFailed. This method does not call
// SetFailed itself because that might delete the object directly making this
// call.
- bool InitFrameBuffer(size_t);
+ bool InitFrameBuffer(wtf_size_t);
// Performs any decoder-specific setup of the requested frame after it has
// been newly created, e.g. setting the frame's duration or disposal method.
- virtual void InitializeNewFrame(size_t) {}
+ virtual void InitializeNewFrame(wtf_size_t) {}
// Decodes the requested frame.
- virtual void Decode(size_t) = 0;
+ virtual void Decode(wtf_size_t) = 0;
// This method is only required for animated images. It returns a vector with
// all frame indices that need to be decoded in order to succesfully decode
// the provided frame. The indices are returned in reverse order, so the
// last frame needs to be decoded first. Before calling this method, the
// caller must verify that the frame exists.
- Vector<size_t> FindFramesToDecode(size_t) const;
+ Vector<wtf_size_t> FindFramesToDecode(wtf_size_t) const;
// This is called by Decode() after decoding a frame in an animated image.
// Before calling this method, the caller must verify that the frame exists.
// @return true if the frame was fully decoded,
// false otherwise.
- bool PostDecodeProcessing(size_t);
+ bool PostDecodeProcessing(wtf_size_t);
// The GIF and PNG decoders set the default alpha setting of the ImageFrame to
// true. When the frame rect does not contain any (semi-) transparent pixels,
@@ -526,7 +528,7 @@ class PLATFORM_EXPORT ImageDecoder {
// This method should be called by the GIF and PNG decoder when the pixels in
// the frame rect do *not* contain any transparent pixels. Before calling
// this method, the caller must verify that the frame exists.
- void CorrectAlphaWhenFrameBufferSawNoAlpha(size_t);
+ void CorrectAlphaWhenFrameBufferSawNoAlpha(wtf_size_t);
scoped_refptr<SegmentReader> data_; // The encoded data.
Vector<ImageFrame, 1> frame_buffer_cache_;
@@ -541,13 +543,13 @@ class PLATFORM_EXPORT ImageDecoder {
// (and then return the downsampled size from DecodedSize()). Ignoring
// this limit can cause excessive memory use or even crashes on low-
// memory devices.
- const size_t max_decoded_bytes_;
+ const wtf_size_t max_decoded_bytes_;
// While decoding, we may learn that there are so many animation frames that
// we would go beyond our cache budget.
// If that happens, purge_aggressively_ is set to true. This signals
// future decodes to purge old frames as it goes.
- void UpdateAggressivePurging(size_t index);
+ void UpdateAggressivePurging(wtf_size_t index);
// The method is only relevant for multi-frame images.
//
@@ -594,11 +596,11 @@ class PLATFORM_EXPORT ImageDecoder {
// This methods gets called at the end of InitFrameBuffer. Subclasses can do
// format specific initialization, for e.g. alpha settings, here.
- virtual void OnInitFrameBuffer(size_t) {}
+ virtual void OnInitFrameBuffer(wtf_size_t) {}
// Called by InitFrameBuffer to determine if it can take the bitmap of the
// previous frame. This condition is different for GIF and WEBP.
- virtual bool CanReusePreviousFrameBuffer(size_t) const { return false; }
+ virtual bool CanReusePreviousFrameBuffer(wtf_size_t) const { return false; }
IntSize size_;
bool size_available_ = false;
@@ -610,8 +612,6 @@ class PLATFORM_EXPORT ImageDecoder {
bool source_to_target_color_transform_needs_update_ = false;
std::unique_ptr<ColorProfileTransform> source_to_target_color_transform_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageDecoder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.h b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.h
index 07ff94e7793..1f7b80e0caf 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.h
@@ -9,7 +9,6 @@
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -31,6 +30,8 @@ namespace blink {
class ImageDecoderBaseTest : public testing::Test {
public:
explicit ImageDecoderBaseTest(const String& format) : format_(format) {}
+ ImageDecoderBaseTest(const ImageDecoderBaseTest&) = delete;
+ ImageDecoderBaseTest& operator=(const ImageDecoderBaseTest&) = delete;
enum class FileSelection {
kAll,
@@ -77,8 +78,6 @@ class ImageDecoderBaseTest : public testing::Test {
private:
// Path to the test files.
base::FilePath data_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageDecoderBaseTest);
};
} // namespace blink
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 9e20b13e25c..775445b21ea 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
@@ -61,12 +61,12 @@ class TestImageDecoder : public ImageDecoder {
FindRequiredPreviousFrame(i, known_opaque));
}
- void InitFrames(size_t num_frames,
+ void InitFrames(wtf_size_t num_frames,
unsigned width = 100,
unsigned height = 100) {
SetSize(width, height);
frame_buffer_cache_.resize(num_frames);
- for (size_t i = 0; i < num_frames; ++i)
+ for (wtf_size_t i = 0; i < num_frames; ++i)
frame_buffer_cache_[i].SetOriginalFrameRect(IntRect(0, 0, width, height));
}
@@ -76,7 +76,7 @@ class TestImageDecoder : public ImageDecoder {
private:
bool image_is_high_bit_depth_ = false;
void DecodeSize() override {}
- void Decode(size_t index) override {}
+ void Decode(wtf_size_t index) override {}
};
TEST(ImageDecoderTest, sizeCalculationMayOverflow) {
@@ -283,7 +283,7 @@ TEST(ImageDecoderTest, clearCacheExceptFrameAll) {
}
TEST(ImageDecoderTest, clearCacheExceptFramePreverveClearExceptFrame) {
- const size_t kNumFrames = 10;
+ const wtf_size_t kNumFrames = 10;
std::unique_ptr<TestImageDecoder> decoder(
std::make_unique<TestImageDecoder>());
decoder->InitFrames(kNumFrames);
@@ -293,7 +293,7 @@ TEST(ImageDecoderTest, clearCacheExceptFramePreverveClearExceptFrame) {
decoder->ResetRequiredPreviousFrames();
decoder->ClearCacheExceptFrame(5);
- for (size_t i = 0; i < kNumFrames; ++i) {
+ for (wtf_size_t i = 0; i < kNumFrames; ++i) {
SCOPED_TRACE(testing::Message() << i);
if (i == 5)
EXPECT_EQ(ImageFrame::kFrameComplete, frame_buffers[i].GetStatus());
@@ -364,7 +364,7 @@ TEST(ImageDecoderTest, hasSufficientDataToSniffMimeTypeAvif) {
// Chimera-AV1-10bit-1280x720-2380kbps-100.avif. Since the major_brand is
// not "avif" or "avis", we must parse the compatible_brands to determine if
// this is an AVIF image.
- constexpr char kData[] = {
+ constexpr uint8_t kData[] = {
// A File Type Box.
0x00, 0x00, 0x00, 0x1c, // unsigned int(32) size; 0x1c = 28
'f', 't', 'y', 'p', // unsigned int(32) type = boxtype;
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 ecd572abfe4..fb32006501c 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
@@ -183,9 +183,9 @@ static void BlendRGBAF16Buffer(ImageFrame::PixelDataF16* dst,
// 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());
+ SkImageInfo info = SkImageInfo::Make(base::checked_cast<int>(num_pixels), 1,
+ kRGBA_F16_SkColorType, dst_alpha_type,
+ SkColorSpace::MakeSRGBLinear());
sk_sp<SkSurface> surface =
SkSurface::MakeRasterDirect(info, dst, info.minRowBytes());
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 caac09253a7..5eeaacde444 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
@@ -148,7 +148,7 @@ class PLATFORM_EXPORT ImageFrame final {
// Returns true if the pixels changed, but the bitmap has not yet been
// notified.
bool PixelsChanged() const { return pixels_changed_; }
- size_t RequiredPreviousFrameIndex() const {
+ wtf_size_t RequiredPreviousFrameIndex() const {
return required_previous_frame_index_;
}
void SetHasAlpha(bool alpha);
@@ -174,7 +174,7 @@ class PLATFORM_EXPORT ImageFrame final {
void SetPixelsChanged(bool pixels_changed) {
pixels_changed_ = pixels_changed;
}
- void SetRequiredPreviousFrameIndex(size_t previous_frame_index) {
+ void SetRequiredPreviousFrameIndex(wtf_size_t previous_frame_index) {
required_previous_frame_index_ = previous_frame_index;
}
@@ -323,7 +323,7 @@ class PLATFORM_EXPORT ImageFrame final {
// WTF::kNotFound if this frame doesn't require any previous frame.
// This is used by ImageDecoder::ClearCacheExceptFrame(), and will never
// be read for image formats that do not have multiple frames.
- size_t required_previous_frame_index_;
+ wtf_size_t required_previous_frame_index_;
};
} // 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 46a18514f3f..57579228cb5 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
@@ -229,7 +229,7 @@ static JOCTET* ReadPointerOffset(JOCTET* data,
JOCTET* start,
JOCTET* end,
bool is_big_endian) {
- unsigned max_offset = end - start;
+ unsigned max_offset = base::checked_cast<unsigned>(end - start);
unsigned offset = ReadUint32(data, is_big_endian);
if (offset > max_offset)
return nullptr;
@@ -445,8 +445,8 @@ static IntSize ComputeYUVSize(const jpeg_decompress_struct* info,
info->comp_info[component].downsampled_height);
}
-static size_t ComputeYUVWidthBytes(const jpeg_decompress_struct* info,
- int component) {
+static wtf_size_t ComputeYUVWidthBytes(const jpeg_decompress_struct* info,
+ int component) {
return info->comp_info[component].width_in_blocks * DCTSIZE;
}
@@ -465,7 +465,7 @@ class JPEGImageReader final {
USING_FAST_MALLOC(JPEGImageReader);
public:
- JPEGImageReader(JPEGImageDecoder* decoder, size_t initial_offset)
+ JPEGImageReader(JPEGImageDecoder* decoder, wtf_size_t initial_offset)
: decoder_(decoder),
needs_restart_(false),
restart_position_(initial_offset),
@@ -505,13 +505,16 @@ class JPEGImageReader final {
jpeg_save_markers(&info_, exifMarker, 0xFFFF);
}
+ JPEGImageReader(const JPEGImageReader&) = delete;
+ JPEGImageReader& operator=(const JPEGImageReader&) = delete;
+
~JPEGImageReader() { jpeg_destroy_decompress(&info_); }
void SkipBytes(long num_bytes) {
if (num_bytes <= 0)
return;
- size_t bytes_to_skip = static_cast<size_t>(num_bytes);
+ wtf_size_t bytes_to_skip = static_cast<wtf_size_t>(num_bytes);
if (bytes_to_skip < info_.src->bytes_in_buffer) {
// The next byte needed is in the buffer. Move to it.
@@ -519,14 +522,15 @@ class JPEGImageReader final {
info_.src->next_input_byte += bytes_to_skip;
} else {
// Move beyond the buffer and empty it.
- next_read_position_ =
- next_read_position_ + bytes_to_skip - info_.src->bytes_in_buffer;
+ next_read_position_ = static_cast<wtf_size_t>(
+ next_read_position_ + bytes_to_skip - info_.src->bytes_in_buffer);
info_.src->bytes_in_buffer = 0;
info_.src->next_input_byte = nullptr;
}
// This is a valid restart position.
- restart_position_ = next_read_position_ - info_.src->bytes_in_buffer;
+ restart_position_ = static_cast<wtf_size_t>(next_read_position_ -
+ info_.src->bytes_in_buffer);
// We updated |next_input_byte|, so we need to update |last_byte_set_|
// so we know not to update |restart_position_| again.
last_set_byte_ = info_.src->next_input_byte;
@@ -941,7 +945,8 @@ class JPEGImageReader final {
if (last_set_byte_ != info_.src->next_input_byte) {
// next_input_byte was updated by jpeg, meaning that it found a restart
// position.
- restart_position_ = next_read_position_ - info_.src->bytes_in_buffer;
+ restart_position_ = static_cast<wtf_size_t>(next_read_position_ -
+ info_.src->bytes_in_buffer);
}
}
@@ -958,9 +963,9 @@ class JPEGImageReader final {
// Input reading: True if we need to back up to restart_position_.
bool needs_restart_;
// If libjpeg needed to restart, this is the position to restart from.
- size_t restart_position_;
+ wtf_size_t restart_position_;
// This is the position where we will read from, unless there is a restart.
- size_t next_read_position_;
+ wtf_size_t next_read_position_;
// This is how we know to update the restart position. It is the last value
// we set to next_input_byte. libjpeg will update next_input_byte when it
// has found the next restart position, so if it no longer matches this
@@ -975,8 +980,6 @@ class JPEGImageReader final {
JSAMPARRAY samples_;
IntSize uv_size_;
-
- DISALLOW_COPY_AND_ASSIGN(JPEGImageReader);
};
void error_exit(
@@ -1022,8 +1025,8 @@ void term_source(j_decompress_ptr jd) {
JPEGImageDecoder::JPEGImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes,
- size_t offset)
+ wtf_size_t max_decoded_bytes,
+ wtf_size_t offset)
: ImageDecoder(alpha_option,
ImageDecoder::kDefaultBitDepth,
color_behavior,
@@ -1093,7 +1096,7 @@ IntSize JPEGImageDecoder::DecodedYUVSize(cc::YUVIndex index) const {
return ComputeYUVSize(info, static_cast<int>(index));
}
-size_t JPEGImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
+wtf_size_t JPEGImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
DCHECK(reader_);
const jpeg_decompress_struct* info = reader_->Info();
@@ -1102,7 +1105,7 @@ size_t JPEGImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
}
unsigned JPEGImageDecoder::DesiredScaleNumerator() const {
- size_t original_bytes = Size().Width() * Size().Height() * 4;
+ wtf_size_t original_bytes = Size().Width() * Size().Height() * 4;
if (original_bytes <= max_decoded_bytes_)
return g_scale_denominator;
@@ -1269,9 +1272,9 @@ static bool OutputRawData(JPEGImageReader* reader, ImagePlanes* image_planes) {
static_cast<JSAMPROW>(image_planes->Plane(cc::YUVIndex::kU));
JSAMPROW output_v =
static_cast<JSAMPROW>(image_planes->Plane(cc::YUVIndex::kV));
- size_t row_bytes_y = image_planes->RowBytes(cc::YUVIndex::kY);
- size_t row_bytes_u = image_planes->RowBytes(cc::YUVIndex::kU);
- size_t row_bytes_v = image_planes->RowBytes(cc::YUVIndex::kV);
+ wtf_size_t row_bytes_y = image_planes->RowBytes(cc::YUVIndex::kY);
+ wtf_size_t row_bytes_u = image_planes->RowBytes(cc::YUVIndex::kU);
+ wtf_size_t row_bytes_v = image_planes->RowBytes(cc::YUVIndex::kV);
// Request 8 or 16 scanlines: returns 0 or more scanlines.
int y_scanlines_to_read = DCTSIZE * v;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h
index bfae426ef92..9bb1ad86b3a 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h
@@ -38,8 +38,10 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
public:
JPEGImageDecoder(AlphaOption,
const ColorBehavior&,
- size_t max_decoded_bytes,
- size_t offset = 0);
+ wtf_size_t max_decoded_bytes,
+ wtf_size_t offset = 0);
+ JPEGImageDecoder(const JPEGImageDecoder&) = delete;
+ JPEGImageDecoder& operator=(const JPEGImageDecoder&) = delete;
~JPEGImageDecoder() override;
// ImageDecoder:
@@ -49,7 +51,7 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
bool SetSize(unsigned width, unsigned height) override;
cc::YUVSubsampling GetYUVSubsampling() const override;
IntSize DecodedYUVSize(cc::YUVIndex) const override;
- size_t DecodedYUVWidthBytes(cc::YUVIndex) const override;
+ wtf_size_t DecodedYUVWidthBytes(cc::YUVIndex) const override;
void DecodeToYUV() override;
SkYUVColorSpace GetYUVColorSpace() const override;
Vector<SkISize> GetSupportedDecodeSizes() const override;
@@ -86,7 +88,7 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
private:
// ImageDecoder:
void DecodeSize() override { Decode(DecodingMode::kDecodeHeader); }
- void Decode(size_t) override {
+ void Decode(wtf_size_t) override {
// Use DecodeToYUV for YUV decoding.
Decode(DecodingMode::kDecodeToBitmap);
}
@@ -101,11 +103,9 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
void Decode(DecodingMode decoding_mode);
std::unique_ptr<JPEGImageReader> reader_;
- const size_t offset_;
+ const wtf_size_t offset_;
IntSize decoded_size_;
Vector<SkISize> supported_decode_sizes_;
-
- DISALLOW_COPY_AND_ASSIGN(JPEGImageDecoder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
index e93df794e8e..4bcabceebc8 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
@@ -101,7 +101,7 @@ void ReadYUV(size_t max_decoded_bytes,
EXPECT_EQ(expected_y_size, y_size);
EXPECT_EQ(expected_uv_size, u_size);
- size_t row_bytes[3];
+ wtf_size_t row_bytes[3];
row_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY);
row_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU);
row_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV);
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc
index f9d9e418418..69354b90bf0 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc
@@ -17,20 +17,29 @@ void MakeTransferFunctionHLG01(skcms_TransferFunction* tf) {
tf, 1 / 12.0f, 2.0f, 2.0f, 1 / 0.17883277f, 0.28466892f, 0.55991073f);
}
-// Computes whether the transfer function from the parsed ICC profile
-// approximately matches the given parametric transfer function. Returns a
-// ColorProfile if it matches, or nullptr if not.
+// Computes whether the transfer function from the ColorProfile, that was
+// created from a parsed ICC profile, approximately matches the given parametric
+// transfer function. Returns a ColorProfile if it matches, or nullptr if not.
std::unique_ptr<ColorProfile> ApproximatelyMatchesTF(
- const skcms_ICCProfile* parsed,
+ const ColorProfile& profile,
const skcms_TransferFunction* tf) {
- skcms_ICCProfile parsed_test = *parsed;
- parsed_test.has_trc = true;
+ skcms_ICCProfile parsed_copy = *profile.GetProfile();
+ // Override the transfer function with a known parametric curve.
+ parsed_copy.has_trc = true;
for (int c = 0; c < 3; c++) {
- parsed_test.trc[c].table_entries = 0;
- parsed_test.trc[c].parametric = *tf;
+ parsed_copy.trc[c].table_entries = 0;
+ parsed_copy.trc[c].parametric = *tf;
}
- if (skcms_ApproximatelyEqualProfiles(parsed, &parsed_test)) {
- return std::make_unique<ColorProfile>(parsed_test);
+ if (skcms_ApproximatelyEqualProfiles(profile.GetProfile(), &parsed_copy)) {
+ // The input ColorProfile owns the buffer memory, make a new copy for
+ // the newly created one and pass the ownership of the new copy to the new
+ // color profile.
+ std::unique_ptr<uint8_t[]> owned_buffer(
+ new uint8_t[profile.GetProfile()->size]);
+ memcpy(owned_buffer.get(), profile.GetProfile()->buffer,
+ profile.GetProfile()->size);
+ parsed_copy.buffer = owned_buffer.get();
+ return std::make_unique<ColorProfile>(parsed_copy, std::move(owned_buffer));
}
return nullptr;
}
@@ -40,7 +49,7 @@ JXLImageDecoder::JXLImageDecoder(
AlphaOption alpha_option,
HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes)
+ wtf_size_t max_decoded_bytes)
: ImageDecoder(alpha_option,
high_bit_depth_decoding_option,
color_behavior,
@@ -49,7 +58,7 @@ JXLImageDecoder::JXLImageDecoder(
}
bool JXLImageDecoder::ReadBytes(size_t remaining,
- size_t* offset,
+ wtf_size_t* offset,
WTF::Vector<uint8_t>* segment,
FastSharedBufferReader* reader,
const uint8_t** jxl_data,
@@ -101,7 +110,7 @@ bool JXLImageDecoder::ReadBytes(size_t remaining,
for (;;) {
if (read) {
*offset += read;
- segment->Append(buffer, read);
+ segment->Append(buffer, base::checked_cast<wtf_size_t>(read));
}
if (segment->size() > remaining) {
*jxl_data = segment->data();
@@ -123,7 +132,7 @@ bool JXLImageDecoder::ReadBytes(size_t remaining,
return true;
}
-void JXLImageDecoder::DecodeImpl(size_t index, bool only_size) {
+void JXLImageDecoder::DecodeImpl(wtf_size_t index, bool only_size) {
if (Failed())
return;
@@ -311,8 +320,6 @@ void JXLImageDecoder::DecodeImpl(size_t index, bool only_size) {
// and set the profile to one that indicates this transfer function
// more clearly than a raw ICC profile does, so Chrome considers
// the profile as HDR.
- const skcms_ICCProfile* parsed = profile->GetProfile();
-
skcms_TransferFunction tf_pq;
skcms_TransferFunction tf_hlg01;
skcms_TransferFunction tf_hlg12;
@@ -321,7 +328,7 @@ void JXLImageDecoder::DecodeImpl(size_t index, bool only_size) {
skcms_TransferFunction_makeHLG(&tf_hlg12);
for (skcms_TransferFunction tf : {tf_pq, tf_hlg01, tf_hlg12}) {
- auto match = ApproximatelyMatchesTF(parsed, &tf);
+ auto match = ApproximatelyMatchesTF(*profile, &tf);
if (match) {
is_hdr_ = true;
profile.swap(match);
@@ -345,7 +352,7 @@ void JXLImageDecoder::DecodeImpl(size_t index, bool only_size) {
break;
}
case JXL_DEC_NEED_IMAGE_OUT_BUFFER: {
- const size_t frame_index = num_decoded_frames_++;
+ const wtf_size_t frame_index = num_decoded_frames_++;
ImageFrame& frame = frame_buffer_cache_[frame_index];
// This is guaranteed to occur after JXL_DEC_BASIC_INFO so the size
// is correct.
@@ -378,8 +385,10 @@ void JXLImageDecoder::DecodeImpl(size_t index, bool only_size) {
ImageFrame& frame =
self->frame_buffer_cache_[self->num_decoded_frames_ - 1];
void* row_dst = self->decode_to_half_float_
- ? reinterpret_cast<void*>(frame.GetAddrF16(x, y))
- : reinterpret_cast<void*>(frame.GetAddr(x, y));
+ ? reinterpret_cast<void*>(frame.GetAddrF16(
+ static_cast<int>(x), static_cast<int>(y)))
+ : reinterpret_cast<void*>(frame.GetAddr(
+ static_cast<int>(x), static_cast<int>(y)));
bool dst_premultiply = frame.PremultiplyAlpha();
@@ -454,7 +463,7 @@ bool JXLImageDecoder::MatchesJXLSignature(
return false;
}
-void JXLImageDecoder::InitializeNewFrame(size_t index) {
+void JXLImageDecoder::InitializeNewFrame(wtf_size_t index) {
auto& buffer = frame_buffer_cache_[index];
if (decode_to_half_float_)
buffer.SetPixelFormat(ImageFrame::PixelFormat::kRGBA_F16);
@@ -462,7 +471,7 @@ void JXLImageDecoder::InitializeNewFrame(size_t index) {
buffer.SetPremultiplyAlpha(premultiply_alpha_);
}
-bool JXLImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool JXLImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
return IsAllDataReceived() ||
(index < num_decoded_frames_ &&
frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameComplete);
@@ -481,14 +490,14 @@ int JXLImageDecoder::RepetitionCount() const {
return info_.animation.num_loops;
}
-base::TimeDelta JXLImageDecoder::FrameDurationAtIndex(size_t index) const {
+base::TimeDelta JXLImageDecoder::FrameDurationAtIndex(wtf_size_t index) const {
if (index < frame_durations_.size())
return base::TimeDelta::FromSecondsD(frame_durations_[index]);
return base::TimeDelta();
}
-size_t JXLImageDecoder::DecodeFrameCount() {
+wtf_size_t JXLImageDecoder::DecodeFrameCount() {
DecodeSize();
if (!info_.have_animation) {
frame_durations_.resize(1);
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.h
index 3c687c64ddb..f0619fc8e1b 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.h
@@ -45,7 +45,7 @@ class PLATFORM_EXPORT JXLImageDecoder final : public ImageDecoder {
JXLImageDecoder(AlphaOption,
HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior&,
- size_t max_decoded_bytes);
+ wtf_size_t max_decoded_bytes);
// ImageDecoder:
String FilenameExtension() const override { return "jxl"; }
@@ -57,26 +57,26 @@ class PLATFORM_EXPORT JXLImageDecoder final : public ImageDecoder {
private:
// ImageDecoder:
void DecodeSize() override { DecodeImpl(0, true); }
- size_t DecodeFrameCount() override;
- void Decode(size_t frame) override { DecodeImpl(frame); }
- void InitializeNewFrame(size_t) override;
+ wtf_size_t DecodeFrameCount() override;
+ void Decode(wtf_size_t frame) override { DecodeImpl(frame); }
+ void InitializeNewFrame(wtf_size_t) override;
// TODO(http://crbug.com/1211339): We never clear the frame buffer for now,
// as we'd need to restart the decoder from scratch. This can lead to
// excessive memory use on web site such as forums, or image collection
// sites. This should be fixed to use the existing frame cache disposal
// methods when the JPEG XL API can handle resuming decoding from
// intermediate frames.
- void ClearFrameBuffer(size_t frame_index) override {}
+ void ClearFrameBuffer(wtf_size_t frame_index) override {}
// Decodes up to a given frame. If |only_size| is true, stops decoding after
// calculating the image size. If decoding fails but there is no more
// data coming, sets the "decode failure" flag.
- void DecodeImpl(size_t frame, bool only_size = false);
+ void DecodeImpl(wtf_size_t frame, bool only_size = false);
- bool FrameIsReceivedAtIndex(size_t) const override;
- base::TimeDelta FrameDurationAtIndex(size_t) const override;
+ bool FrameIsReceivedAtIndex(wtf_size_t) const override;
+ base::TimeDelta FrameDurationAtIndex(wtf_size_t) const override;
int RepetitionCount() const override;
- bool CanReusePreviousFrameBuffer(size_t) const override { return false; }
+ bool CanReusePreviousFrameBuffer(wtf_size_t) const override { return false; }
// Reads bytes from the segment reader, after releasing input from the JXL
// decoder, which required `remaining` previous bytes to still be available.
@@ -84,17 +84,17 @@ class PLATFORM_EXPORT JXLImageDecoder final : public ImageDecoder {
// bytes are read, if possible. Returns false if not enough bytes are
// available or if Failed() was set.
bool ReadBytes(size_t remaining,
- size_t* offset,
+ wtf_size_t* offset,
WTF::Vector<uint8_t>* segment,
FastSharedBufferReader* reader,
const uint8_t** jxl_data,
size_t* jxl_size);
JxlDecoderPtr dec_ = nullptr;
- size_t offset_ = 0;
+ wtf_size_t offset_ = 0;
JxlDecoderPtr frame_count_dec_ = nullptr;
- size_t frame_count_offset_ = 0;
+ wtf_size_t frame_count_offset_ = 0;
// The image is considered to be HDR, such as using PQ or HLG transfer
// function in the color space.
@@ -108,7 +108,7 @@ class PLATFORM_EXPORT JXLImageDecoder final : public ImageDecoder {
ColorProfileTransform* xform_;
// For animation support.
- size_t num_decoded_frames_ = 0;
+ wtf_size_t num_decoded_frames_ = 0;
bool finished_ = false;
bool has_full_frame_count_ = false;
size_t size_at_last_frame_count_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder_test.cc
index 76404d8440b..d6e55d27655 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder_test.cc
@@ -115,10 +115,10 @@ void TestHDR(const char* jxl_file,
a = FromFloat16(first_pixel >> 48);
} else {
uint32_t first_pixel = *frame->GetAddr(0, 0);
- a = ((first_pixel >> 24) & 255) / 255.0;
- r = ((first_pixel >> 16) & 255) / 255.0;
- g = ((first_pixel >> 8) & 255) / 255.0;
- b = ((first_pixel >> 0) & 255) / 255.0;
+ a = ((first_pixel >> SK_A32_SHIFT) & 255) / 255.0;
+ r = ((first_pixel >> SK_R32_SHIFT) & 255) / 255.0;
+ g = ((first_pixel >> SK_G32_SHIFT) & 255) / 255.0;
+ b = ((first_pixel >> SK_B32_SHIFT) & 255) / 255.0;
}
constexpr float eps = 0.01;
EXPECT_NEAR(expected_r, r, eps);
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 8976abdb2ca..9caac485342 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
@@ -53,8 +53,8 @@ PNGImageDecoder::PNGImageDecoder(
AlphaOption alpha_option,
HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes,
- size_t offset)
+ wtf_size_t max_decoded_bytes,
+ wtf_size_t offset)
: ImageDecoder(alpha_option,
high_bit_depth_decoding_option,
color_behavior,
@@ -77,12 +77,12 @@ bool PNGImageDecoder::SetFailed() {
return ImageDecoder::SetFailed();
}
-size_t PNGImageDecoder::DecodeFrameCount() {
+wtf_size_t PNGImageDecoder::DecodeFrameCount() {
Parse(ParseQuery::kMetaData);
return Failed() ? frame_buffer_cache_.size() : reader_->FrameCount();
}
-void PNGImageDecoder::Decode(size_t index) {
+void PNGImageDecoder::Decode(wtf_size_t index) {
Parse(ParseQuery::kMetaData);
if (Failed())
@@ -90,7 +90,7 @@ void PNGImageDecoder::Decode(size_t index) {
UpdateAggressivePurging(index);
- Vector<size_t> frames_to_decode = FindFramesToDecode(index);
+ Vector<wtf_size_t> frames_to_decode = FindFramesToDecode(index);
for (auto i = frames_to_decode.rbegin(); i != frames_to_decode.rend(); i++) {
current_frame_ = *i;
if (!reader_->Decode(*data_, *i)) {
@@ -121,13 +121,13 @@ void PNGImageDecoder::Parse(ParseQuery query) {
SetFailed();
}
-void PNGImageDecoder::ClearFrameBuffer(size_t index) {
+void PNGImageDecoder::ClearFrameBuffer(wtf_size_t index) {
if (reader_)
reader_->ClearDecodeState(index);
ImageDecoder::ClearFrameBuffer(index);
}
-bool PNGImageDecoder::CanReusePreviousFrameBuffer(size_t index) const {
+bool PNGImageDecoder::CanReusePreviousFrameBuffer(wtf_size_t index) const {
DCHECK(index < frame_buffer_cache_.size());
return frame_buffer_cache_[index].GetDisposalMethod() !=
ImageFrame::kDisposeOverwritePrevious;
@@ -141,7 +141,7 @@ int PNGImageDecoder::RepetitionCount() const {
return Failed() ? kAnimationLoopOnce : repetition_count_;
}
-void PNGImageDecoder::InitializeNewFrame(size_t index) {
+void PNGImageDecoder::InitializeNewFrame(wtf_size_t index) {
const PNGImageReader::FrameInfo& frame_info = reader_->GetFrameInfo(index);
ImageFrame& buffer = frame_buffer_cache_[index];
if (decode_to_half_float_)
@@ -154,7 +154,7 @@ void PNGImageDecoder::InitializeNewFrame(size_t index) {
buffer.SetDisposalMethod(frame_info.disposal_method);
buffer.SetAlphaBlendSource(frame_info.alpha_blend);
- size_t previous_frame_index = FindRequiredPreviousFrame(index, false);
+ wtf_size_t previous_frame_index = FindRequiredPreviousFrame(index, false);
buffer.SetRequiredPreviousFrameIndex(previous_frame_index);
}
@@ -524,7 +524,6 @@ void PNGImageDecoder::RowAvailable(unsigned char* row_buffer,
png_structp png = reader_->PngPtr();
if (!InitFrameBuffer(current_frame_)) {
longjmp(JMPBUF(png), 1);
- return;
}
DCHECK_EQ(ImageFrame::kFramePartial, buffer.GetStatus());
@@ -538,12 +537,10 @@ void PNGImageDecoder::RowAvailable(unsigned char* row_buffer,
interlace_buffer_size *= 2;
if (!interlace_buffer_size.IsValid()) {
longjmp(JMPBUF(png), 1);
- return;
}
reader_->CreateInterlaceBuffer(interlace_buffer_size.ValueOrDie());
if (!reader_->InterlaceBuffer()) {
longjmp(JMPBUF(png), 1);
- return;
}
}
@@ -764,7 +761,6 @@ void PNGImageDecoder::FrameComplete() {
ImageFrame& buffer = frame_buffer_cache_[current_frame_];
if (buffer.GetStatus() == ImageFrame::kFrameEmpty) {
longjmp(JMPBUF(reader_->PngPtr()), 1);
- return;
}
if (!current_buffer_saw_alpha_)
@@ -773,7 +769,7 @@ void PNGImageDecoder::FrameComplete() {
buffer.SetStatus(ImageFrame::kFrameComplete);
}
-bool PNGImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool PNGImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
if (!IsDecodedSizeAvailable())
return false;
@@ -787,7 +783,7 @@ bool PNGImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
return reader_->FrameIsReceivedAtIndex(index);
}
-base::TimeDelta PNGImageDecoder::FrameDurationAtIndex(size_t index) const {
+base::TimeDelta PNGImageDecoder::FrameDurationAtIndex(wtf_size_t index) const {
if (index < frame_buffer_cache_.size())
return frame_buffer_cache_[index].Duration();
return base::TimeDelta();
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 482da4c85c2..604d71980f0 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,8 +38,10 @@ class PLATFORM_EXPORT PNGImageDecoder final : public ImageDecoder {
PNGImageDecoder(AlphaOption,
HighBitDepthDecodingOption,
const ColorBehavior&,
- size_t max_decoded_bytes,
- size_t offset = 0);
+ wtf_size_t max_decoded_bytes,
+ wtf_size_t offset = 0);
+ PNGImageDecoder(const PNGImageDecoder&) = delete;
+ PNGImageDecoder& operator=(const PNGImageDecoder&) = delete;
~PNGImageDecoder() override;
// ImageDecoder:
@@ -47,8 +49,8 @@ class PLATFORM_EXPORT PNGImageDecoder final : public ImageDecoder {
bool SetSize(unsigned, unsigned) override;
int RepetitionCount() const override;
bool ImageIsHighBitDepth() override;
- bool FrameIsReceivedAtIndex(size_t) const override;
- base::TimeDelta FrameDurationAtIndex(size_t) const override;
+ bool FrameIsReceivedAtIndex(wtf_size_t) const override;
+ base::TimeDelta FrameDurationAtIndex(wtf_size_t) const override;
bool SetFailed() override;
// Callbacks from libpng
@@ -65,24 +67,22 @@ class PLATFORM_EXPORT PNGImageDecoder final : public ImageDecoder {
// ImageDecoder:
void DecodeSize() override { Parse(ParseQuery::kSize); }
- void Decode(size_t) override;
+ void Decode(wtf_size_t) override;
void Parse(ParseQuery);
- size_t DecodeFrameCount() override;
- void InitializeNewFrame(size_t) override;
- void ClearFrameBuffer(size_t) override;
- bool CanReusePreviousFrameBuffer(size_t) const override;
+ wtf_size_t DecodeFrameCount() override;
+ void InitializeNewFrame(wtf_size_t) override;
+ void ClearFrameBuffer(wtf_size_t) override;
+ bool CanReusePreviousFrameBuffer(wtf_size_t) const override;
std::unique_ptr<PNGImageReader> reader_;
const unsigned offset_;
- size_t current_frame_;
+ wtf_size_t current_frame_;
int repetition_count_;
bool has_alpha_channel_;
bool current_buffer_saw_alpha_;
bool decode_to_half_float_;
- size_t bit_depth_;
+ wtf_size_t bit_depth_;
std::unique_ptr<ImageFrame::PixelData[]> color_transform_scanline_;
-
- DISALLOW_COPY_AND_ASSIGN(PNGImageDecoder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc
index 573afe77a36..1ba532af801 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc
@@ -74,7 +74,8 @@ void PNGAPI pngFailed(png_structp png, png_const_charp) {
namespace blink {
-PNGImageReader::PNGImageReader(PNGImageDecoder* decoder, size_t initial_offset)
+PNGImageReader::PNGImageReader(PNGImageDecoder* decoder,
+ wtf_size_t initial_offset)
: width_(0),
height_(0),
decoder_(decoder),
@@ -124,17 +125,17 @@ PNGImageReader::~PNGImageReader() {
// method. If the data is not consecutive, it is stored in |buffer|, which must
// have the size of (at least) |length|, but there's no need for it to be larger
// than |kPngReadBufferSize|.
-static constexpr size_t kPngReadBufferSize = 33;
+static constexpr wtf_size_t kPngReadBufferSize = 33;
const png_byte* ReadAsConstPngBytep(const FastSharedBufferReader& reader,
- size_t read_offset,
- size_t length,
+ wtf_size_t read_offset,
+ wtf_size_t length,
char* buffer) {
DCHECK_LE(length, kPngReadBufferSize);
return reinterpret_cast<const png_byte*>(
reader.GetConsecutiveData(read_offset, length, buffer));
}
-bool PNGImageReader::ShouldDecodeWithNewPNG(size_t index) const {
+bool PNGImageReader::ShouldDecodeWithNewPNG(wtf_size_t index) const {
if (!png_)
return true;
const bool first_frame_decode_in_progress = progressive_decode_offset_;
@@ -146,7 +147,7 @@ bool PNGImageReader::ShouldDecodeWithNewPNG(size_t index) const {
}
// Return false on a fatal error.
-bool PNGImageReader::Decode(SegmentReader& data, size_t index) {
+bool PNGImageReader::Decode(SegmentReader& data, wtf_size_t index) {
if (index >= frame_info_.size())
return true;
@@ -197,7 +198,7 @@ bool PNGImageReader::Decode(SegmentReader& data, size_t index) {
}
void PNGImageReader::StartFrameDecoding(const FastSharedBufferReader& reader,
- size_t index) {
+ wtf_size_t index) {
DCHECK_GT(ihdr_offset_, initial_offset_);
ProcessData(reader, initial_offset_, ihdr_offset_ - initial_offset_);
@@ -210,7 +211,7 @@ void PNGImageReader::StartFrameDecoding(const FastSharedBufferReader& reader,
// Process the IHDR chunk, but change the width and height so it reflects
// the frame's width and height. ImageDecoder will apply the x,y offset.
- constexpr size_t kHeaderSize = 25;
+ constexpr wtf_size_t kHeaderSize = 25;
char read_buffer[kHeaderSize];
const png_byte* chunk =
ReadAsConstPngBytep(reader, ihdr_offset_, kHeaderSize, read_buffer);
@@ -238,7 +239,7 @@ static inline bool IsChunk(const png_byte* chunk, const char* tag) {
bool PNGImageReader::ProgressivelyDecodeFirstFrame(
const FastSharedBufferReader& reader) {
- size_t offset = frame_info_[0].start_offset;
+ wtf_size_t offset = frame_info_[0].start_offset;
// Loop while there is enough data to do progressive decoding.
while (reader.size() >= offset + 8) {
@@ -255,7 +256,7 @@ bool PNGImageReader::ProgressivelyDecodeFirstFrame(
return true;
}
- const size_t chunk_end_offset = offset + length + 12;
+ const wtf_size_t chunk_end_offset = offset + length + 12;
DCHECK_GT(chunk_end_offset, offset);
// If this chunk was already decoded, move on to the next.
@@ -280,8 +281,8 @@ bool PNGImageReader::ProgressivelyDecodeFirstFrame(
offset += 8;
}
- size_t bytes_left_in_chunk = chunk_end_offset - offset;
- size_t bytes_decoded = ProcessData(reader, offset, bytes_left_in_chunk);
+ wtf_size_t bytes_left_in_chunk = chunk_end_offset - offset;
+ wtf_size_t bytes_decoded = ProcessData(reader, offset, bytes_left_in_chunk);
progressive_decode_offset_ = offset + bytes_decoded;
if (bytes_decoded < bytes_left_in_chunk)
return false;
@@ -312,9 +313,9 @@ void PNGImageReader::ProcessFdatChunkAsIdat(png_uint_32 fdat_length) {
}
void PNGImageReader::DecodeFrame(const FastSharedBufferReader& reader,
- size_t index) {
- size_t offset = frame_info_[index].start_offset;
- size_t end_offset = offset + frame_info_[index].byte_length;
+ wtf_size_t index) {
+ wtf_size_t offset = frame_info_[index].start_offset;
+ wtf_size_t end_offset = offset + frame_info_[index].byte_length;
char read_buffer[8];
while (offset < end_offset) {
@@ -338,9 +339,9 @@ void PNGImageReader::DecodeFrame(const FastSharedBufferReader& reader,
// Compute the CRC and compare to the stored value.
static bool CheckCrc(const FastSharedBufferReader& reader,
- size_t chunk_start,
- size_t chunk_length) {
- constexpr size_t kSizeNeededForfcTL = 26 + 4;
+ wtf_size_t chunk_start,
+ wtf_size_t chunk_length) {
+ constexpr wtf_size_t kSizeNeededForfcTL = 26 + 4;
char read_buffer[kSizeNeededForfcTL];
DCHECK_LE(chunk_length + 4u, kSizeNeededForfcTL);
const png_byte* chunk = ReadAsConstPngBytep(reader, chunk_start + 4,
@@ -406,10 +407,10 @@ bool PNGImageReader::Parse(SegmentReader& data, ParseQuery query) {
while (reader.size() >= read_offset_ + 8) {
const png_byte* chunk =
ReadAsConstPngBytep(reader, read_offset_, 8, read_buffer);
- const size_t length = png_get_uint_32(chunk);
+ const wtf_size_t length = png_get_uint_32(chunk);
if (length > PNG_UINT_31_MAX)
return false;
- size_t chunk_end_offset;
+ wtf_size_t chunk_end_offset;
if (!base::CheckAdd(read_offset_, base::CheckAdd(12, length))
.AssignIfValid(&chunk_end_offset)) {
// Overflow
@@ -503,11 +504,11 @@ bool PNGImageReader::Parse(SegmentReader& data, ParseQuery query) {
// If |length| == 0, read until the stream ends. Return number of bytes
// processed.
-size_t PNGImageReader::ProcessData(const FastSharedBufferReader& reader,
- size_t offset,
- size_t length) {
+wtf_size_t PNGImageReader::ProcessData(const FastSharedBufferReader& reader,
+ wtf_size_t offset,
+ wtf_size_t length) {
const char* segment;
- size_t total_processed_bytes = 0;
+ wtf_size_t total_processed_bytes = 0;
while (reader.size() > offset) {
size_t segment_length = reader.GetSomeData(segment, offset);
if (length > 0 && segment_length + total_processed_bytes > length)
@@ -557,7 +558,7 @@ bool PNGImageReader::ParseSize(const FastSharedBufferReader& reader) {
length = png_get_uint_32(chunk);
if (length > PNG_UINT_31_MAX)
return false;
- size_t chunk_end_offset;
+ wtf_size_t chunk_end_offset;
if (!base::CheckAdd(read_offset_, base::CheckAdd(12, length))
.AssignIfValid(&chunk_end_offset)) {
// Overflow
@@ -657,7 +658,7 @@ bool PNGImageReader::ParseSize(const FastSharedBufferReader& reader) {
return true;
}
-void PNGImageReader::ClearDecodeState(size_t index) {
+void PNGImageReader::ClearDecodeState(wtf_size_t index) {
if (index)
return;
png_destroy_read_struct(png_ ? &png_ : nullptr, info_ ? &info_ : nullptr,
@@ -667,7 +668,7 @@ void PNGImageReader::ClearDecodeState(size_t index) {
}
const PNGImageReader::FrameInfo& PNGImageReader::GetFrameInfo(
- size_t index) const {
+ wtf_size_t index) const {
DCHECK(index < frame_info_.size());
return frame_info_[index];
}
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.h b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.h
index 0ea28a4f201..371a2eef03c 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_PNG_PNG_IMAGE_READER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_PNG_PNG_IMAGE_READER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -57,15 +56,17 @@ class PLATFORM_EXPORT PNGImageReader final {
USING_FAST_MALLOC(PNGImageReader);
public:
- PNGImageReader(PNGImageDecoder*, size_t initial_offset);
+ PNGImageReader(PNGImageDecoder*, wtf_size_t initial_offset);
+ PNGImageReader(const PNGImageReader&) = delete;
+ PNGImageReader& operator=(const PNGImageReader&) = delete;
~PNGImageReader();
struct FrameInfo {
// The offset where the frame data of this frame starts.
- size_t start_offset;
+ wtf_size_t start_offset;
// The number of bytes that contain frame data, starting at start_offset.
- size_t byte_length;
- size_t duration;
+ wtf_size_t byte_length;
+ wtf_size_t duration;
IntRect frame_rect;
ImageFrame::DisposalMethod disposal_method;
ImageFrame::AlphaBlendSource alpha_blend;
@@ -76,21 +77,21 @@ class PLATFORM_EXPORT PNGImageReader final {
bool Parse(SegmentReader&, ParseQuery);
// Returns false on a fatal error.
- bool Decode(SegmentReader&, size_t);
- const FrameInfo& GetFrameInfo(size_t) const;
+ bool Decode(SegmentReader&, wtf_size_t);
+ const FrameInfo& GetFrameInfo(wtf_size_t) const;
// Number of complete frames parsed so far; includes frame 0 even if partial.
- size_t FrameCount() const { return frame_info_.size(); }
+ wtf_size_t FrameCount() const { return frame_info_.size(); }
bool ParseCompleted() const { return parse_completed_; }
- bool FrameIsReceivedAtIndex(size_t index) const {
+ bool FrameIsReceivedAtIndex(wtf_size_t index) const {
if (!index)
return FirstFrameFullyReceived();
return index < FrameCount();
}
- void ClearDecodeState(size_t);
+ void ClearDecodeState(wtf_size_t);
png_structp PngPtr() const { return png_; }
png_infop InfoPtr() const { return info_; }
@@ -110,12 +111,12 @@ class PLATFORM_EXPORT PNGImageReader final {
PNGImageDecoder* decoder_;
// The offset in the stream where the PNG image starts.
- const size_t initial_offset_;
+ const wtf_size_t initial_offset_;
// How many bytes have been read during parsing.
- size_t read_offset_;
- size_t progressive_decode_offset_;
- size_t ihdr_offset_;
- size_t idat_offset_;
+ wtf_size_t read_offset_;
+ wtf_size_t progressive_decode_offset_;
+ wtf_size_t ihdr_offset_;
+ wtf_size_t idat_offset_;
bool idat_is_part_of_animation_;
// All IDAT chunks must precede the first fdAT chunk, and all fdAT chunks
@@ -139,25 +140,25 @@ class PLATFORM_EXPORT PNGImageReader final {
// Value used for the byte_length of a FrameInfo struct to indicate that it is
// the first frame and its byte_length is not yet known. 1 is a safe value
// since the byte_length field of a frame is at least 12.
- static constexpr size_t kFirstFrameIndicator = 1;
+ static constexpr wtf_size_t kFirstFrameIndicator = 1;
// Stores information about a frame until it can be pushed to |frame_info|
// once all the frame data has been read from the stream.
FrameInfo new_frame_;
Vector<FrameInfo, 1> frame_info_;
- size_t ProcessData(const FastSharedBufferReader&,
- size_t offset,
- size_t length);
+ wtf_size_t ProcessData(const FastSharedBufferReader&,
+ wtf_size_t offset,
+ wtf_size_t length);
// Returns false on a fatal error.
bool ParseSize(const FastSharedBufferReader&);
// Returns false on an error.
bool ParseFrameInfo(const png_byte* data);
- bool ShouldDecodeWithNewPNG(size_t) const;
- void StartFrameDecoding(const FastSharedBufferReader&, size_t);
+ bool ShouldDecodeWithNewPNG(wtf_size_t) const;
+ void StartFrameDecoding(const FastSharedBufferReader&, wtf_size_t);
// Returns whether the frame was completely decoded.
bool ProgressivelyDecodeFirstFrame(const FastSharedBufferReader&);
- void DecodeFrame(const FastSharedBufferReader&, size_t);
+ void DecodeFrame(const FastSharedBufferReader&, wtf_size_t);
void ProcessFdatChunkAsIdat(png_uint_32 fdat_length);
// Returns false on a fatal error.
bool CheckSequenceNumber(const png_byte* position);
@@ -165,8 +166,6 @@ class PLATFORM_EXPORT PNGImageReader final {
return !frame_info_.IsEmpty() &&
frame_info_[0].byte_length != kFirstFrameIndicator;
}
-
- DISALLOW_COPY_AND_ASSIGN(PNGImageReader);
};
} // namespace blink
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 0343b9fbc5a..e6951edd0c6 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
@@ -7,7 +7,6 @@
#include <utility>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/graphics/parkable_image.h"
#include "third_party/blink/renderer/platform/graphics/rw_buffer.h"
@@ -63,14 +62,15 @@ sk_sp<SkData> BufferCopyAsSkData(Iter iter, size_t available) {
class SharedBufferSegmentReader final : public SegmentReader {
public:
explicit SharedBufferSegmentReader(scoped_refptr<SharedBuffer>);
+ SharedBufferSegmentReader(const SharedBufferSegmentReader&) = delete;
+ SharedBufferSegmentReader& operator=(const SharedBufferSegmentReader&) =
+ delete;
size_t size() const override;
size_t GetSomeData(const char*& data, size_t position) const override;
sk_sp<SkData> GetAsSkData() const override;
private:
scoped_refptr<SharedBuffer> shared_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedBufferSegmentReader);
};
SharedBufferSegmentReader::SharedBufferSegmentReader(
@@ -109,14 +109,14 @@ sk_sp<SkData> SharedBufferSegmentReader::GetAsSkData() const {
class DataSegmentReader final : public SegmentReader {
public:
explicit DataSegmentReader(sk_sp<SkData>);
+ DataSegmentReader(const DataSegmentReader&) = delete;
+ DataSegmentReader& operator=(const DataSegmentReader&) = delete;
size_t size() const override;
size_t GetSomeData(const char*& data, size_t position) const override;
sk_sp<SkData> GetAsSkData() const override;
private:
sk_sp<SkData> data_;
-
- DISALLOW_COPY_AND_ASSIGN(DataSegmentReader);
};
DataSegmentReader::DataSegmentReader(sk_sp<SkData> data)
@@ -144,6 +144,8 @@ sk_sp<SkData> DataSegmentReader::GetAsSkData() const {
class ROBufferSegmentReader final : public SegmentReader {
public:
explicit ROBufferSegmentReader(scoped_refptr<ROBuffer>);
+ ROBufferSegmentReader(const ROBufferSegmentReader&) = delete;
+ ROBufferSegmentReader& operator=(const ROBufferSegmentReader&) = delete;
size_t size() const override;
size_t GetSomeData(const char*& data, size_t position) const override;
@@ -155,8 +157,6 @@ class ROBufferSegmentReader final : public SegmentReader {
// Position of the first char in the current block of iter_.
mutable size_t position_of_block_ GUARDED_BY(read_mutex_);
mutable ROBuffer::Iter iter_ GUARDED_BY(read_mutex_);
-
- DISALLOW_COPY_AND_ASSIGN(ROBufferSegmentReader);
};
ROBufferSegmentReader::ROBufferSegmentReader(scoped_refptr<ROBuffer> buffer)
@@ -235,14 +235,6 @@ class ParkableImageSegmentReader : public SegmentReader {
ParkableImageSegmentReader::ParkableImageSegmentReader(
scoped_refptr<ParkableImage> image)
: parkable_image_(std::move(image)), available_(parkable_image_->size()) {
- // TODO(thiabaud): make ParkableImage only be locked when needed.
- // Currently, we take a conservative approach here and lock for the full
- // lifetime of the SegmentReader, but most of the time this is not needed
- // and we can simply lock closer to when we need to read the data from the
- // ParkableImage.
- MutexLocker lock(parkable_image_->lock_);
- parkable_image_->Unpark();
- DCHECK(parkable_image_->rw_buffer_);
}
size_t ParkableImageSegmentReader::size() const {
@@ -254,10 +246,10 @@ size_t ParkableImageSegmentReader::GetSomeData(const char*& data,
if (!parkable_image_)
return 0;
- MutexLocker lock(parkable_image_->lock_);
- DCHECK(parkable_image_->is_locked());
+ MutexLocker lock(parkable_image_->impl_->lock_);
+ DCHECK(parkable_image_->impl_->is_locked());
- RWBuffer::ROIter iter(parkable_image_->rw_buffer_.get(), available_);
+ RWBuffer::ROIter iter(parkable_image_->impl_->rw_buffer_.get(), available_);
size_t position_of_block = 0;
return BufferGetSomeData(iter, position_of_block, data, position);
@@ -267,10 +259,10 @@ sk_sp<SkData> ParkableImageSegmentReader::GetAsSkData() const {
if (!parkable_image_)
return nullptr;
- MutexLocker lock(parkable_image_->lock_);
- parkable_image_->Unpark();
+ MutexLocker lock(parkable_image_->impl_->lock_);
+ parkable_image_->impl_->Unpark();
- RWBuffer::ROIter iter(parkable_image_->rw_buffer_.get(), available_);
+ RWBuffer::ROIter iter(parkable_image_->impl_->rw_buffer_.get(), available_);
if (!iter.HasNext()) { // No need to copy because the data is contiguous.
// We lock here so that we don't get a use-after-free. ParkableImage can
@@ -278,14 +270,14 @@ sk_sp<SkData> ParkableImageSegmentReader::GetAsSkData() const {
// lifetime of the SkData. We add the ref so that the ParkableImage has a
// longer limetime than the SkData.
parkable_image_->AddRef();
- parkable_image_->Lock();
+ parkable_image_->LockData();
return SkData::MakeWithProc(
iter.data(), available_,
[](const void* ptr, void* context) -> void {
auto* parkable_image = static_cast<ParkableImage*>(context);
{
- MutexLocker lock(parkable_image->lock_);
- parkable_image->Unlock();
+ MutexLocker lock(parkable_image->impl_->lock_);
+ parkable_image->UnlockData();
}
// Don't hold the mutex while we call |Release|, since |Release| can
// free the ParkableImage, if this is the last reference to it;
@@ -301,16 +293,16 @@ sk_sp<SkData> ParkableImageSegmentReader::GetAsSkData() const {
}
void ParkableImageSegmentReader::LockData() {
- MutexLocker lock(parkable_image_->lock_);
- parkable_image_->Unpark();
+ MutexLocker lock(parkable_image_->impl_->lock_);
+ parkable_image_->impl_->Unpark();
- parkable_image_->Lock();
+ parkable_image_->LockData();
}
void ParkableImageSegmentReader::UnlockData() {
- MutexLocker lock(parkable_image_->lock_);
+ MutexLocker lock(parkable_image_->impl_->lock_);
- parkable_image_->Unlock();
+ parkable_image_->UnlockData();
}
// SegmentReader ---------------------------------------------------------------
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.h b/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.h
index c7f74389b69..7397f047f1f 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_SEGMENT_READER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_SEGMENT_READER_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/wtf/shared_buffer.h"
@@ -48,15 +47,14 @@ class PLATFORM_EXPORT SegmentReader
scoped_refptr<ParkableImage>);
SegmentReader() = default;
+ SegmentReader(const SegmentReader&) = delete;
+ SegmentReader& operator=(const SegmentReader&) = delete;
virtual ~SegmentReader() = default;
virtual size_t size() const = 0;
virtual size_t GetSomeData(const char*& data, size_t position) const = 0;
virtual sk_sp<SkData> GetAsSkData() const = 0;
virtual void LockData() {}
virtual void UnlockData() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SegmentReader);
};
} // namespace blink
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 f60acd5f85a..ee5e308a2b4 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
@@ -174,7 +174,7 @@ namespace blink {
WEBPImageDecoder::WEBPImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
- size_t max_decoded_bytes)
+ wtf_size_t max_decoded_bytes)
: ImageDecoder(alpha_option,
ImageDecoder::kDefaultBitDepth,
color_behavior,
@@ -272,7 +272,7 @@ int WEBPImageDecoder::RepetitionCount() const {
return Failed() ? kAnimationLoopOnce : repetition_count_;
}
-bool WEBPImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
+bool WEBPImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const {
if (!demux_ || demux_state_ <= WEBP_DEMUX_PARSING_HEADER)
return false;
if (!(format_flags_ & ANIMATION_FLAG))
@@ -286,7 +286,7 @@ bool WEBPImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
return frame_is_received_at_index;
}
-base::TimeDelta WEBPImageDecoder::FrameDurationAtIndex(size_t index) const {
+base::TimeDelta WEBPImageDecoder::FrameDurationAtIndex(wtf_size_t index) const {
return index < frame_buffer_cache_.size()
? frame_buffer_cache_[index].Duration()
: base::TimeDelta();
@@ -317,12 +317,12 @@ bool WEBPImageDecoder::UpdateDemuxer() {
if (IsAllDataReceived() && !consolidated_data_) {
consolidated_data_ = data_->GetAsSkData();
} else {
- buffer_.ReserveCapacity(data_->size());
+ buffer_.ReserveCapacity(base::checked_cast<wtf_size_t>(data_->size()));
while (buffer_.size() < data_->size()) {
const char* segment;
const size_t bytes = data_->GetSomeData(segment, buffer_.size());
DCHECK(bytes);
- buffer_.Append(segment, bytes);
+ buffer_.Append(segment, base::checked_cast<wtf_size_t>(bytes));
}
DCHECK_EQ(buffer_.size(), data_->size());
consolidated_data_ =
@@ -385,17 +385,17 @@ bool WEBPImageDecoder::UpdateDemuxer() {
DCHECK(IsDecodedSizeAvailable());
- size_t frame_count = WebPDemuxGetI(demux_, WEBP_FF_FRAME_COUNT);
+ wtf_size_t frame_count = WebPDemuxGetI(demux_, WEBP_FF_FRAME_COUNT);
UpdateAggressivePurging(frame_count);
return true;
}
-void WEBPImageDecoder::OnInitFrameBuffer(size_t frame_index) {
+void WEBPImageDecoder::OnInitFrameBuffer(wtf_size_t frame_index) {
// ImageDecoder::InitFrameBuffer does a DCHECK if |frame_index| exists.
ImageFrame& buffer = frame_buffer_cache_[frame_index];
- const size_t required_previous_frame_index =
+ const wtf_size_t required_previous_frame_index =
buffer.RequiredPreviousFrameIndex();
if (required_previous_frame_index == kNotFound) {
frame_background_has_alpha_ =
@@ -433,8 +433,9 @@ void WEBPImageDecoder::DecodeToYUV() {
} else {
std::unique_ptr<WebPIterator, void (*)(WebPIterator*)> webp_frame(
&webp_iter, WebPDemuxReleaseIterator);
- DecodeSingleFrameToYUV(webp_frame->fragment.bytes,
- webp_frame->fragment.size);
+ DecodeSingleFrameToYUV(
+ webp_frame->fragment.bytes,
+ base::checked_cast<wtf_size_t>(webp_frame->fragment.size));
}
}
@@ -451,13 +452,13 @@ IntSize WEBPImageDecoder::DecodedYUVSize(cc::YUVIndex index) const {
return IntSize(0, 0);
}
-size_t WEBPImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
+wtf_size_t WEBPImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const {
switch (index) {
case cc::YUVIndex::kY:
- return base::checked_cast<size_t>(Size().Width());
+ return base::checked_cast<wtf_size_t>(Size().Width());
case cc::YUVIndex::kU:
case cc::YUVIndex::kV:
- return base::checked_cast<size_t>((Size().Width() + 1) / 2);
+ return base::checked_cast<wtf_size_t>((Size().Width() + 1) / 2);
}
NOTREACHED();
return 0;
@@ -478,13 +479,14 @@ cc::YUVSubsampling WEBPImageDecoder::GetYUVSubsampling() const {
return cc::YUVSubsampling::kUnknown;
}
-bool WEBPImageDecoder::CanReusePreviousFrameBuffer(size_t frame_index) const {
+bool WEBPImageDecoder::CanReusePreviousFrameBuffer(
+ wtf_size_t frame_index) const {
DCHECK(frame_index < frame_buffer_cache_.size());
return frame_buffer_cache_[frame_index].GetAlphaBlendSource() !=
ImageFrame::kBlendAtopPreviousFrame;
}
-void WEBPImageDecoder::ClearFrameBuffer(size_t frame_index) {
+void WEBPImageDecoder::ClearFrameBuffer(wtf_size_t frame_index) {
if (demux_ && demux_state_ >= WEBP_DEMUX_PARSED_HEADER &&
frame_buffer_cache_[frame_index].GetStatus() ==
ImageFrame::kFramePartial) {
@@ -504,7 +506,8 @@ void WEBPImageDecoder::ReadColorProfile() {
const char* profile_data =
reinterpret_cast<const char*>(chunk_iterator.chunk.bytes);
- size_t profile_size = chunk_iterator.chunk.size;
+ wtf_size_t profile_size =
+ base::checked_cast<wtf_size_t>(chunk_iterator.chunk.size);
if (auto profile = ColorProfile::Create(profile_data, profile_size)) {
if (profile->GetProfile()->data_color_space == skcms_Signature_RGB) {
@@ -517,7 +520,7 @@ void WEBPImageDecoder::ReadColorProfile() {
WebPDemuxReleaseChunkIterator(&chunk_iterator);
}
-void WEBPImageDecoder::ApplyPostProcessing(size_t frame_index) {
+void WEBPImageDecoder::ApplyPostProcessing(wtf_size_t frame_index) {
ImageFrame& buffer = frame_buffer_cache_[frame_index];
int width;
int decoded_height;
@@ -605,7 +608,7 @@ void WEBPImageDecoder::ApplyPostProcessing(size_t frame_index) {
buffer.SetPixelsChanged(true);
}
-size_t WEBPImageDecoder::DecodeFrameCount() {
+wtf_size_t WEBPImageDecoder::DecodeFrameCount() {
// If UpdateDemuxer() fails, return the existing number of frames. This way if
// we get halfway through the image before decoding fails, we won't suddenly
// start reporting that the image has zero frames.
@@ -613,7 +616,7 @@ size_t WEBPImageDecoder::DecodeFrameCount() {
: frame_buffer_cache_.size();
}
-void WEBPImageDecoder::InitializeNewFrame(size_t index) {
+void WEBPImageDecoder::InitializeNewFrame(wtf_size_t index) {
if (!(format_flags_ & ANIMATION_FLAG)) {
DCHECK(!index);
return;
@@ -640,13 +643,13 @@ void WEBPImageDecoder::InitializeNewFrame(size_t index) {
WebPDemuxReleaseIterator(&animated_frame);
}
-void WEBPImageDecoder::Decode(size_t index) {
+void WEBPImageDecoder::Decode(wtf_size_t index) {
DCHECK(!IsDoingYuvDecode());
if (Failed())
return;
- Vector<size_t> frames_to_decode = FindFramesToDecode(index);
+ Vector<wtf_size_t> frames_to_decode = FindFramesToDecode(index);
DCHECK(demux_);
for (auto i = frames_to_decode.rbegin(); i != frames_to_decode.rend(); ++i) {
@@ -661,8 +664,9 @@ void WEBPImageDecoder::Decode(size_t index) {
} else {
std::unique_ptr<WebPIterator, void (*)(WebPIterator*)> webp_frame(
&webp_iter, WebPDemuxReleaseIterator);
- DecodeSingleFrame(webp_frame->fragment.bytes, webp_frame->fragment.size,
- *i);
+ DecodeSingleFrame(
+ webp_frame->fragment.bytes,
+ base::checked_cast<wtf_size_t>(webp_frame->fragment.size), *i);
}
if (Failed())
@@ -681,7 +685,7 @@ void WEBPImageDecoder::Decode(size_t index) {
}
bool WEBPImageDecoder::DecodeSingleFrameToYUV(const uint8_t* data_bytes,
- size_t data_size) {
+ wtf_size_t data_size) {
DCHECK(IsDoingYuvDecode());
DCHECK(!Failed());
@@ -737,8 +741,8 @@ bool WEBPImageDecoder::DecodeSingleFrameToYUV(const uint8_t* data_bytes,
}
bool WEBPImageDecoder::DecodeSingleFrame(const uint8_t* data_bytes,
- size_t data_size,
- size_t frame_index) {
+ wtf_size_t data_size,
+ wtf_size_t frame_index) {
DCHECK(!IsDoingYuvDecode());
if (Failed())
return false;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h
index f3164639439..4384427e46b 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h
@@ -40,10 +40,12 @@ class SkData;
namespace blink {
class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
- DISALLOW_COPY_AND_ASSIGN(WEBPImageDecoder);
-
public:
- WEBPImageDecoder(AlphaOption, const ColorBehavior&, size_t max_decoded_bytes);
+ WEBPImageDecoder(AlphaOption,
+ const ColorBehavior&,
+ wtf_size_t max_decoded_bytes);
+ WEBPImageDecoder(const WEBPImageDecoder&) = delete;
+ WEBPImageDecoder& operator=(const WEBPImageDecoder&) = delete;
~WEBPImageDecoder() override;
// ImageDecoder:
@@ -51,15 +53,15 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
void OnSetData(SegmentReader* data) override;
cc::YUVSubsampling GetYUVSubsampling() const override;
int RepetitionCount() const override;
- bool FrameIsReceivedAtIndex(size_t) const override;
- base::TimeDelta FrameDurationAtIndex(size_t) const override;
+ bool FrameIsReceivedAtIndex(wtf_size_t) const override;
+ base::TimeDelta FrameDurationAtIndex(wtf_size_t) const override;
private:
// ImageDecoder:
void DecodeSize() override { UpdateDemuxer(); }
- size_t DecodeFrameCount() override;
- void InitializeNewFrame(size_t) override;
- void Decode(size_t) override;
+ wtf_size_t DecodeFrameCount() override;
+ void InitializeNewFrame(wtf_size_t) override;
+ void Decode(wtf_size_t) override;
void DecodeToYUV() override;
SkYUVColorSpace GetYUVColorSpace() const override;
cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const override;
@@ -70,10 +72,10 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
// planes.
bool CanAllowYUVDecodingForWebP();
bool HasImagePlanes() const { return image_planes_.get(); }
- bool DecodeSingleFrameToYUV(const uint8_t* data_bytes, size_t data_size);
+ bool DecodeSingleFrameToYUV(const uint8_t* data_bytes, wtf_size_t data_size);
bool DecodeSingleFrame(const uint8_t* data_bytes,
- size_t data_size,
- size_t frame_index);
+ wtf_size_t data_size,
+ wtf_size_t frame_index);
// For WebP images, the frame status needs to be FrameComplete to decode
// subsequent frames that depend on frame |index|. The reason for this is that
@@ -103,23 +105,23 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
IntSize DecodedYUVSize(cc::YUVIndex) const override;
// Returns the width of each row of the memory allocation.
- size_t DecodedYUVWidthBytes(cc::YUVIndex) const override;
+ wtf_size_t DecodedYUVWidthBytes(cc::YUVIndex) const override;
void ReadColorProfile();
bool UpdateDemuxer();
// Set |frame_background_has_alpha_| based on this frame's characteristics.
// Before calling this method, the caller must verify that the frame exists.
- void OnInitFrameBuffer(size_t frame_index) override;
+ void OnInitFrameBuffer(wtf_size_t frame_index) override;
// When the blending method of this frame is BlendAtopPreviousFrame, the
// previous frame's buffer is necessary to decode this frame in
// ApplyPostProcessing, so we can't take over the data. Before calling this
// method, the caller must verify that the frame exists.
- bool CanReusePreviousFrameBuffer(size_t frame_index) const override;
+ bool CanReusePreviousFrameBuffer(wtf_size_t frame_index) const override;
- void ApplyPostProcessing(size_t frame_index);
- void ClearFrameBuffer(size_t frame_index) override;
+ void ApplyPostProcessing(wtf_size_t frame_index);
+ void ClearFrameBuffer(wtf_size_t frame_index) override;
WebPDemuxer* demux_;
WebPDemuxState demux_state_;
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 3154e3e45e2..cc5622a590c 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
@@ -32,7 +32,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h"
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn b/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn
index 814c58d21ff..b1837098104 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn
@@ -5,8 +5,6 @@
import("//third_party/blink/renderer/platform/platform.gni")
blink_platform_sources("instrumentation") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
sources = [
"canvas_memory_dump_provider.cc",
"canvas_memory_dump_provider.h",
@@ -57,6 +55,7 @@ source_set("unit_tests") {
deps = [
"//base",
+ "//base/allocator:buildflags",
"//base/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/canvas_memory_dump_provider.h b/chromium/third_party/blink/renderer/platform/instrumentation/canvas_memory_dump_provider.h
index 809f97a6eaa..9aadd7b305c 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/canvas_memory_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/canvas_memory_dump_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_CANVAS_MEMORY_DUMP_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_CANVAS_MEMORY_DUMP_PROVIDER_H_
-#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -28,6 +27,8 @@ class PLATFORM_EXPORT CanvasMemoryDumpProvider final
public:
static CanvasMemoryDumpProvider* Instance();
+ CanvasMemoryDumpProvider(const CanvasMemoryDumpProvider&) = delete;
+ CanvasMemoryDumpProvider& operator=(const CanvasMemoryDumpProvider&) = delete;
~CanvasMemoryDumpProvider() override = default;
// MemoryDumpProvider implementation.
@@ -42,8 +43,6 @@ class PLATFORM_EXPORT CanvasMemoryDumpProvider final
base::Lock lock_;
WTF::HashSet<CanvasMemoryDumpClient*> clients_ GUARDED_BY(lock_);
-
- DISALLOW_COPY_AND_ASSIGN(CanvasMemoryDumpProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters_memory_dump_provider.h b/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters_memory_dump_provider.h
index 76f1d6388fe..f99e609fedd 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters_memory_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters_memory_dump_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_INSTANCE_COUNTERS_MEMORY_DUMP_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_INSTANCE_COUNTERS_MEMORY_DUMP_PROVIDER_H_
-#include "base/macros.h"
#include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -18,6 +17,10 @@ class PLATFORM_EXPORT InstanceCountersMemoryDumpProvider final
public:
static InstanceCountersMemoryDumpProvider* Instance();
+ InstanceCountersMemoryDumpProvider(
+ const InstanceCountersMemoryDumpProvider&) = delete;
+ InstanceCountersMemoryDumpProvider& operator=(
+ const InstanceCountersMemoryDumpProvider&) = delete;
~InstanceCountersMemoryDumpProvider() override = default;
// MemoryDumpProvider implementation.
@@ -26,8 +29,6 @@ class PLATFORM_EXPORT InstanceCountersMemoryDumpProvider final
private:
InstanceCountersMemoryDumpProvider() = default;
-
- DISALLOW_COPY_AND_ASSIGN(InstanceCountersMemoryDumpProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h b/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h
index 87c95698569..f0bf64922c0 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_MEMORY_PRESSURE_LISTENER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_MEMORY_PRESSURE_LISTENER_H_
-#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -49,6 +48,10 @@ class PLATFORM_EXPORT MemoryPressureListenerRegistry final
static void Initialize();
MemoryPressureListenerRegistry();
+ MemoryPressureListenerRegistry(const MemoryPressureListenerRegistry&) =
+ delete;
+ MemoryPressureListenerRegistry& operator=(
+ const MemoryPressureListenerRegistry&) = delete;
void RegisterThread(Thread*) LOCKS_EXCLUDED(threads_mutex_);
void UnregisterThread(Thread*) LOCKS_EXCLUDED(threads_mutex_);
@@ -74,8 +77,6 @@ class PLATFORM_EXPORT MemoryPressureListenerRegistry final
HeapHashSet<WeakMember<MemoryPressureListener>> clients_;
HashSet<Thread*> threads_ GUARDED_BY(threads_mutex_);
Mutex threads_mutex_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureListenerRegistry);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h b/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h
index b5918c462e3..0748e6cc18f 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_PARTITION_ALLOC_MEMORY_DUMP_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_PARTITION_ALLOC_MEMORY_DUMP_PROVIDER_H_
-#include "base/macros.h"
#include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -18,6 +17,10 @@ class PLATFORM_EXPORT PartitionAllocMemoryDumpProvider final
public:
static PartitionAllocMemoryDumpProvider* Instance();
+ PartitionAllocMemoryDumpProvider(const PartitionAllocMemoryDumpProvider&) =
+ delete;
+ PartitionAllocMemoryDumpProvider& operator=(
+ const PartitionAllocMemoryDumpProvider&) = delete;
~PartitionAllocMemoryDumpProvider() override;
// MemoryDumpProvider implementation.
@@ -26,8 +29,6 @@ class PLATFORM_EXPORT PartitionAllocMemoryDumpProvider final
private:
PartitionAllocMemoryDumpProvider();
-
- DISALLOW_COPY_AND_ASSIGN(PartitionAllocMemoryDumpProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc b/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc
index 7010e7b6d75..eb9c52c85a7 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h"
+#include "base/allocator/buildflags.h"
+#include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/trace_event/process_memory_dump.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
index f7214d58e1f..b5f655fe487 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom-blink.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -29,6 +28,9 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
// Returns nullptr if instrumentation is not enabled.
static std::unique_ptr<DocumentResourceCoordinator> MaybeCreate(
const BrowserInterfaceBrokerProxy&);
+ DocumentResourceCoordinator(const DocumentResourceCoordinator&) = delete;
+ DocumentResourceCoordinator& operator=(const DocumentResourceCoordinator&) =
+ delete;
~DocumentResourceCoordinator();
void SetNetworkAlmostIdle();
@@ -49,8 +51,6 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
service_;
bool had_form_interaction_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(DocumentResourceCoordinator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h
index 32e5523a9d0..f5b75d76781 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_TRACING_MEMORY_CACHE_DUMP_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_TRACING_MEMORY_CACHE_DUMP_PROVIDER_H_
-#include "base/macros.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -34,6 +33,8 @@ class PLATFORM_EXPORT MemoryCacheDumpProvider final
public:
// This class is singleton since there is a global MemoryCache object.
static MemoryCacheDumpProvider* Instance();
+ MemoryCacheDumpProvider(const MemoryCacheDumpProvider&) = delete;
+ MemoryCacheDumpProvider& operator=(const MemoryCacheDumpProvider&) = delete;
~MemoryCacheDumpProvider() override;
// base::trace_event::MemoryDumpProvider implementation.
@@ -49,8 +50,6 @@ class PLATFORM_EXPORT MemoryCacheDumpProvider final
MemoryCacheDumpProvider();
WeakPersistent<MemoryCacheDumpClient> client_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryCacheDumpProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
index effbd5f6857..92647a6d04e 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "base/trace_event/traced_value.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -20,6 +19,8 @@ class PLATFORM_EXPORT TracedValue
: public base::trace_event::ConvertableToTraceFormat {
public:
TracedValue();
+ TracedValue(const TracedValue&) = delete;
+ TracedValue& operator=(const TracedValue&) = delete;
~TracedValue() override;
void EndDictionary();
@@ -59,8 +60,6 @@ class PLATFORM_EXPORT TracedValue
bool AppendToProto(ProtoAppender* appender) final;
void EstimateTraceMemoryOverhead(
base::trace_event::TraceEventMemoryOverhead*) final;
-
- DISALLOW_COPY_AND_ASSIGN(TracedValue);
};
// Thin wrapper around base::trace_event::TracedValueJSON.
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc
index d2043f9dd04..c4030c75404 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc
@@ -25,17 +25,16 @@ TEST(TracedValueTest, FlatDictionary) {
value->SetStringWithCopiedName("string", "string");
absl::optional<base::Value> parsed = ParseTracedValue(std::move(value));
- base::DictionaryValue* dictionary;
- ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
- int int_value;
- EXPECT_TRUE(dictionary->GetInteger("int", &int_value));
- EXPECT_EQ(2014, int_value);
- double double_value;
- EXPECT_TRUE(dictionary->GetDouble("double", &double_value));
- EXPECT_EQ(0.0, double_value);
- std::string string_value;
- EXPECT_TRUE(dictionary->GetString("string", &string_value));
- EXPECT_EQ("string", string_value);
+ ASSERT_TRUE(parsed->is_dict());
+ absl::optional<int> int_value = parsed->FindIntKey("int");
+ ASSERT_TRUE(int_value.has_value());
+ EXPECT_EQ(2014, *int_value);
+ absl::optional<double> double_value = parsed->FindDoubleKey("double");
+ ASSERT_TRUE(double_value.has_value());
+ EXPECT_EQ(0.0, *double_value);
+ std::string* string_value = parsed->FindStringKey("string");
+ ASSERT_NE(nullptr, string_value);
+ EXPECT_EQ("string", *string_value);
}
TEST(TracedValueTest, Hierarchy) {
@@ -60,42 +59,43 @@ TEST(TracedValueTest, Hierarchy) {
value->SetStringWithCopiedName("s0", "foo");
absl::optional<base::Value> parsed = ParseTracedValue(std::move(value));
- base::DictionaryValue* dictionary;
- ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
- int i0;
- EXPECT_TRUE(dictionary->GetInteger("i0", &i0));
- EXPECT_EQ(2014, i0);
- int i1;
- EXPECT_TRUE(dictionary->GetInteger("dict1.i1", &i1));
- EXPECT_EQ(2014, i1);
- bool b2;
- EXPECT_TRUE(dictionary->GetBoolean("dict1.dict2.b2", &b2));
- EXPECT_FALSE(b2);
- std::string s1;
- EXPECT_TRUE(dictionary->GetString("dict1.s1", &s1));
- EXPECT_EQ("foo", s1);
- double d0;
- EXPECT_TRUE(dictionary->GetDouble("d0", &d0));
- EXPECT_EQ(0.0, d0);
- bool b0;
- EXPECT_TRUE(dictionary->GetBoolean("b0", &b0));
- EXPECT_TRUE(b0);
- base::ListValue* a1;
- EXPECT_TRUE(dictionary->GetList("a1", &a1));
- int a1i0;
- EXPECT_TRUE(a1->GetInteger(0, &a1i0));
- EXPECT_EQ(1, a1i0);
- bool a1b1;
- EXPECT_TRUE(a1->GetBoolean(1, &a1b1));
- EXPECT_TRUE(a1b1);
- base::DictionaryValue* a1d2;
- EXPECT_TRUE(a1->GetDictionary(2, &a1d2));
- int i2;
- EXPECT_TRUE(a1d2->GetInteger("i2", &i2));
- EXPECT_EQ(3, i2);
- std::string s0;
- EXPECT_TRUE(dictionary->GetString("s0", &s0));
- EXPECT_EQ("foo", s0);
+ ASSERT_TRUE(parsed->is_dict());
+ absl::optional<int> i0 = parsed->FindIntKey("i0");
+ ASSERT_TRUE(i0.has_value());
+ EXPECT_EQ(2014, *i0);
+ absl::optional<int> i1 = parsed->FindIntPath("dict1.i1");
+ ASSERT_TRUE(i1.has_value());
+ EXPECT_EQ(2014, *i1);
+ absl::optional<bool> b2 = parsed->FindBoolPath("dict1.dict2.b2");
+ ASSERT_TRUE(b2.has_value());
+ EXPECT_FALSE(*b2);
+ std::string* s1 = parsed->FindStringPath("dict1.s1");
+ ASSERT_NE(nullptr, s1);
+ EXPECT_EQ("foo", *s1);
+ absl::optional<double> d0 = parsed->FindDoubleKey("d0");
+ ASSERT_TRUE(d0.has_value());
+ EXPECT_EQ(0.0, *d0);
+ absl::optional<bool> b0 = parsed->FindBoolKey("b0");
+ ASSERT_TRUE(b0.has_value());
+ EXPECT_TRUE(*b0);
+ base::Value* a1_value = parsed->FindListKey("a1");
+ ASSERT_NE(nullptr, a1_value);
+ ASSERT_TRUE(a1_value->is_list());
+ base::Value::ListView a1 = a1_value->GetList();
+ absl::optional<int> a1i0 = a1[0].GetIfInt();
+ ASSERT_TRUE(a1i0.has_value());
+ EXPECT_EQ(1, *a1i0);
+ absl::optional<bool> a1b1 = a1[1].GetIfBool();
+ ASSERT_TRUE(a1b1.has_value());
+ EXPECT_TRUE(*a1b1);
+ const base::Value& a1d2 = a1[2];
+ ASSERT_TRUE(a1d2.is_dict());
+ absl::optional<int> i2 = a1d2.FindIntKey("i2");
+ ASSERT_TRUE(i2.has_value());
+ EXPECT_EQ(3, *i2);
+ std::string* s0 = parsed->FindStringKey("s0");
+ ASSERT_NE(nullptr, s0);
+ EXPECT_EQ("foo", *s0);
}
TEST(TracedValueTest, Escape) {
@@ -107,23 +107,22 @@ TEST(TracedValueTest, Escape) {
value->SetStringWithCopiedName("\"s4\"", "value4");
absl::optional<base::Value> parsed = ParseTracedValue(std::move(value));
- base::DictionaryValue* dictionary;
- ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
- std::string s0;
- EXPECT_TRUE(dictionary->GetString("s0", &s0));
- EXPECT_EQ("value0\\", s0);
- std::string s1;
- EXPECT_TRUE(dictionary->GetString("s1", &s1));
- EXPECT_EQ("value\n1", s1);
- std::string s2;
- EXPECT_TRUE(dictionary->GetString("s2", &s2));
- EXPECT_EQ("\"value2\"", s2);
- std::string s3;
- EXPECT_TRUE(dictionary->GetString("s3\\", &s3));
- EXPECT_EQ("value3", s3);
- std::string s4;
- EXPECT_TRUE(dictionary->GetString("\"s4\"", &s4));
- EXPECT_EQ("value4", s4);
+ ASSERT_TRUE(parsed->is_dict());
+ std::string* s0 = parsed->FindStringKey("s0");
+ ASSERT_NE(nullptr, s0);
+ EXPECT_EQ("value0\\", *s0);
+ std::string* s1 = parsed->FindStringKey("s1");
+ ASSERT_NE(nullptr, s1);
+ EXPECT_EQ("value\n1", *s1);
+ std::string* s2 = parsed->FindStringKey("s2");
+ ASSERT_NE(nullptr, s2);
+ EXPECT_EQ("\"value2\"", *s2);
+ std::string* s3 = parsed->FindStringKey("s3\\");
+ ASSERT_NE(nullptr, s3);
+ EXPECT_EQ("value3", *s3);
+ std::string* s4 = parsed->FindStringKey("\"s4\"");
+ ASSERT_NE(nullptr, s4);
+ EXPECT_EQ("value4", *s4);
}
TEST(TracedValueTest, NonCopiedNames) {
@@ -143,27 +142,28 @@ TEST(TracedValueTest, NonCopiedNames) {
value->EndArray();
absl::optional<base::Value> parsed = ParseTracedValue(std::move(value));
- base::DictionaryValue* dictionary;
- ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
- int int_value;
- EXPECT_TRUE(dictionary->GetInteger(int_str, &int_value));
- EXPECT_EQ(2014, int_value);
- double double_value;
- EXPECT_TRUE(dictionary->GetDouble(double_str, &double_value));
- EXPECT_EQ(0.0, double_value);
- bool bool_value;
- EXPECT_TRUE(dictionary->GetBoolean(bool_str, &bool_value));
- EXPECT_TRUE(bool_value);
- std::string string_value;
- EXPECT_TRUE(dictionary->GetString(string_str, &string_value));
- EXPECT_EQ("string", string_value);
- base::ListValue* a1;
- EXPECT_TRUE(dictionary->GetList(array_str, &a1));
- int el0, el1;
- EXPECT_TRUE(a1->GetInteger(0, &el0));
- EXPECT_TRUE(a1->GetInteger(1, &el1));
- EXPECT_EQ(el0, 1);
- EXPECT_EQ(el1, 2);
+ ASSERT_TRUE(parsed->is_dict());
+ absl::optional<int> int_value = parsed->FindIntKey(int_str);
+ ASSERT_TRUE(int_value.has_value());
+ EXPECT_EQ(2014, *int_value);
+ absl::optional<double> double_value = parsed->FindDoubleKey(double_str);
+ ASSERT_TRUE(double_value.has_value());
+ EXPECT_EQ(0.0, *double_value);
+ absl::optional<bool> bool_value = parsed->FindBoolKey(bool_str);
+ ASSERT_TRUE(bool_value.has_value());
+ EXPECT_TRUE(*bool_value);
+ std::string* string_value = parsed->FindStringKey(string_str);
+ ASSERT_NE(nullptr, string_value);
+ EXPECT_EQ("string", *string_value);
+ base::Value* a1_value = parsed->FindListKey(array_str);
+ ASSERT_TRUE(a1_value->is_list());
+ base::Value::ListView a1 = a1_value->GetList();
+ absl::optional<int> el0 = a1[0].GetIfInt();
+ absl::optional<int> el1 = a1[1].GetIfInt();
+ ASSERT_TRUE(el0.has_value());
+ ASSERT_TRUE(el1.has_value());
+ EXPECT_EQ(1, *el0);
+ EXPECT_EQ(2, *el1);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h
index 80769b64ea2..5eced41f79a 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -30,6 +29,8 @@ class PLATFORM_EXPORT WebMemoryAllocatorDump final {
public:
explicit WebMemoryAllocatorDump(
base::trace_event::MemoryAllocatorDump* memory_allocator_dump);
+ WebMemoryAllocatorDump(const WebMemoryAllocatorDump&) = delete;
+ WebMemoryAllocatorDump& operator=(const WebMemoryAllocatorDump&) = delete;
// Adds a scalar attribute to the dump.
// Arguments:
@@ -53,8 +54,6 @@ class PLATFORM_EXPORT WebMemoryAllocatorDump final {
private:
base::trace_event::MemoryAllocatorDump* memory_allocator_dump_; // Not owned.
blink::WebMemoryAllocatorDumpGuid guid_;
-
- DISALLOW_COPY_AND_ASSIGN(WebMemoryAllocatorDump);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h
index 3e2c360fc25..7f8052811bb 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h
@@ -9,7 +9,6 @@
#include <unordered_map>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/trace_event/heap_profiler_allocation_context.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
@@ -51,6 +50,8 @@ class PLATFORM_EXPORT WebProcessMemoryDump final {
// Creates a standalone WebProcessMemoryDump, which owns the underlying
// ProcessMemoryDump.
WebProcessMemoryDump();
+ WebProcessMemoryDump(const WebProcessMemoryDump&) = delete;
+ WebProcessMemoryDump& operator=(const WebProcessMemoryDump&) = delete;
// Wraps (without owning) an existing ProcessMemoryDump.
explicit WebProcessMemoryDump(
@@ -162,8 +163,6 @@ class PLATFORM_EXPORT WebProcessMemoryDump final {
// Stores SkTraceMemoryDump for the current ProcessMemoryDump.
Vector<std::unique_ptr<skia::SkiaTraceMemoryDumpImpl>> sk_trace_dump_list_;
-
- DISALLOW_COPY_AND_ASSIGN(WebProcessMemoryDump);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/use_counter.h b/chromium/third_party/blink/renderer/platform/instrumentation/use_counter.h
index dd28c71e98a..bd1ffcb80de 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/use_counter.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/use_counter.h
@@ -43,15 +43,17 @@ class UseCounter : public GarbageCollectedMixin {
use_counter.CountUse(feature);
}
- public:
UseCounter() = default;
+ UseCounter(const UseCounter&) = delete;
+ UseCounter& operator=(const UseCounter&) = delete;
virtual ~UseCounter() = default;
// Counts a use of the given feature. Repeated calls are ignored.
virtual void CountUse(mojom::WebFeature feature) = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(UseCounter);
+ // Counts a use of the given feature which is being deprecated. Repeated
+ // calls are ignored.
+ virtual void CountDeprecation(mojom::WebFeature feature) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/json/OWNERS b/chromium/third_party/blink/renderer/platform/json/OWNERS
deleted file mode 100644
index 8973bb94daf..00000000000
--- a/chromium/third_party/blink/renderer/platform/json/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-pfeldman@chromium.org
-iclelland@chromium.org
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 56b11c0e8e8..5ef104c046e 100644
--- a/chromium/third_party/blink/renderer/platform/json/json_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/json/json_parser.cc
@@ -7,7 +7,6 @@
#include "base/notreached.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"
@@ -478,9 +477,7 @@ Error BuildValue(Cursor<CharType>* cursor,
bool ok;
double value = CharactersToDouble(token_start.pos,
cursor->pos - token_start.pos, &ok);
- if (Decimal::FromDouble(value).IsInfinity())
- ok = false;
- if (!ok) {
+ if (!ok || std::isinf(value)) {
*cursor = token_start;
return Error::kSyntaxError;
}
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 550023d8f10..78c4ea835fc 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,7 +4,7 @@
#include "third_party/blink/renderer/platform/json/json_parser.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
diff --git a/chromium/third_party/blink/renderer/platform/json/json_values.h b/chromium/third_party/blink/renderer/platform/json/json_values.h
index cd93b396ded..de8e81fd974 100644
--- a/chromium/third_party/blink/renderer/platform/json/json_values.h
+++ b/chromium/third_party/blink/renderer/platform/json/json_values.h
@@ -34,7 +34,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -58,11 +57,12 @@ class JSONObject;
class PLATFORM_EXPORT JSONValue {
USING_FAST_MALLOC(JSONValue);
- DISALLOW_COPY_AND_ASSIGN(JSONValue);
public:
static const int kMaxDepth = 1000;
+ JSONValue(const JSONValue&) = delete;
+ JSONValue& operator=(const JSONValue&) = delete;
virtual ~JSONValue() = default;
static std::unique_ptr<JSONValue> Null() {
@@ -231,6 +231,12 @@ class PLATFORM_EXPORT JSONArray : public JSONValue {
return static_cast<JSONArray*>(value);
}
+ static const JSONArray* Cast(const JSONValue* value) {
+ if (!value || value->GetType() != kTypeArray)
+ return nullptr;
+ return static_cast<const JSONArray*>(value);
+ }
+
static std::unique_ptr<JSONArray> From(std::unique_ptr<JSONValue> value) {
auto maybe_array = base::WrapUnique(JSONArray::Cast(value.get()));
if (maybe_array)
diff --git a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
index 00b0691175c..dcae46c2c89 100644
--- a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -12,14 +12,10 @@ make_names("make_platform_loader_generated_fetch_initiator_type_names") {
}
blink_platform_sources("loader") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
sources = [
"allowed_by_nosniff.cc",
"allowed_by_nosniff.h",
"child_url_loader_factory_bundle.cc",
- "code_cache_loader.cc",
- "code_cache_loader.h",
"cors/cors.cc",
"cors/cors.h",
"cors/cors_error_string.cc",
@@ -31,8 +27,6 @@ blink_platform_sources("loader") {
"fetch/bytes_consumer.h",
"fetch/cached_metadata.cc",
"fetch/cached_metadata.h",
- "fetch/cached_metadata_handler.cc",
- "fetch/cached_metadata_handler.h",
"fetch/client_hints_preferences.cc",
"fetch/client_hints_preferences.h",
"fetch/console_logger.h",
@@ -56,6 +50,7 @@ blink_platform_sources("loader") {
"fetch/https_state.h",
"fetch/integrity_metadata.cc",
"fetch/integrity_metadata.h",
+ "fetch/loader_freeze_mode.h",
"fetch/loading_attribute_value.h",
"fetch/loading_behavior_observer.h",
"fetch/memory_cache.cc",
@@ -78,7 +73,6 @@ blink_platform_sources("loader") {
"fetch/resource_fetcher_properties.cc",
"fetch/resource_fetcher_properties.h",
"fetch/resource_finish_observer.h",
- "fetch/resource_load_info.h",
"fetch/resource_load_observer.h",
"fetch/resource_load_priority.h",
"fetch/resource_load_scheduler.cc",
@@ -120,10 +114,16 @@ blink_platform_sources("loader") {
"fetch/trust_token_params_conversion.h",
"fetch/unique_identifier.cc",
"fetch/unique_identifier.h",
+ "fetch/url_loader/cached_metadata_handler.cc",
+ "fetch/url_loader/cached_metadata_handler.h",
+ "fetch/url_loader/code_cache_loader.cc",
+ "fetch/url_loader/code_cache_loader.h",
"fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc",
"fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h",
"fetch/url_loader/mojo_url_loader_client.cc",
"fetch/url_loader/mojo_url_loader_client.h",
+ "fetch/url_loader/navigation_body_loader.cc",
+ "fetch/url_loader/navigation_body_loader.h",
"fetch/url_loader/request_conversion.cc",
"fetch/url_loader/request_conversion.h",
"fetch/url_loader/sync_load_context.cc",
@@ -168,6 +168,7 @@ blink_platform_sources("loader") {
"//services/network/public/cpp",
"//services/network/public/mojom:mojom_blink",
"//third_party/blink/public/common:buildflags",
+ "//third_party/blink/public/common:headers",
"//third_party/blink/public/mojom:mojom_platform_blink",
"//third_party/blink/renderer/platform/blob:blob",
"//third_party/blink/renderer/platform/instrumentation:instrumentation",
@@ -194,7 +195,6 @@ source_set("unit_tests") {
"cors/cors_test.cc",
"fetch/buffering_bytes_consumer_test.cc",
"fetch/bytes_consumer_test.cc",
- "fetch/cached_metadata_handler_test.cc",
"fetch/client_hints_preferences_test.cc",
"fetch/data_pipe_bytes_consumer_test.cc",
"fetch/fetch_api_request_body_mojom_traits_test.cc",
@@ -212,8 +212,10 @@ source_set("unit_tests") {
"fetch/resource_test.cc",
"fetch/response_body_loader_test.cc",
"fetch/shared_buffer_bytes_consumer_test.cc",
- "fetch/source_keyed_cached_metadata_handler_test.cc",
+ "fetch/url_loader/cached_metadata_handler_test.cc",
"fetch/url_loader/mojo_url_loader_client_unittest.cc",
+ "fetch/url_loader/navigation_body_loader_unittest.cc",
+ "fetch/url_loader/source_keyed_cached_metadata_handler_test.cc",
"fetch/url_loader/sync_load_context_unittest.cc",
"fetch/url_loader/web_resource_request_sender_unittest.cc",
"fetch/url_loader/web_url_loader_unittest.cc",
diff --git a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
index f4db8179fc9..b0ca0bd57d9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
@@ -30,6 +30,7 @@ class MockUseCounter : public GarbageCollected<MockUseCounter>,
}
MOCK_METHOD1(CountUse, void(mojom::WebFeature));
+ MOCK_METHOD1(CountDeprecation, void(mojom::WebFeature));
};
class MockConsoleLogger : public GarbageCollected<MockConsoleLogger>,
diff --git a/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc b/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
index 5f34a63aa35..f7e9689c205 100644
--- a/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
@@ -12,6 +12,8 @@
#include "base/check.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/load_flags.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/code_cache_loader.cc b/chromium/third_party/blink/renderer/platform/loader/code_cache_loader.cc
deleted file mode 100644
index 0d7d72dc4b7..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/code_cache_loader.cc
+++ /dev/null
@@ -1,118 +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/loader/code_cache_loader.h"
-
-#include "base/bind.h"
-#include "base/task/post_task.h"
-#include "base/task/thread_pool.h"
-#include "mojo/public/cpp/base/big_buffer.h"
-#include "third_party/blink/public/platform/platform.h"
-
-namespace blink {
-
-CodeCacheLoader::CodeCacheLoader() : CodeCacheLoader(nullptr) {}
-
-CodeCacheLoader::CodeCacheLoader(base::WaitableEvent* terminate_sync_load_event)
- : terminate_sync_load_event_(terminate_sync_load_event) {}
-
-CodeCacheLoader::~CodeCacheLoader() = default;
-
-void CodeCacheLoader::FetchFromCodeCacheSynchronously(
- const WebURL& url,
- base::Time* response_time_out,
- mojo_base::BigBuffer* data_out) {
- base::WaitableEvent fetch_code_cache_event(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- base::ThreadPool::CreateSingleThreadTaskRunner({});
-
- // Also watch for terminate requests from the main thread when running on
- // worker threads.
- if (terminate_sync_load_event_) {
- terminate_watcher_.StartWatching(
- terminate_sync_load_event_,
- base::BindOnce(&CodeCacheLoader::OnTerminate,
- weak_ptr_factory_.GetWeakPtr(),
- base::Unretained(&fetch_code_cache_event)),
- task_runner);
- }
-
- FetchCodeCacheCallback callback =
- base::BindOnce(&CodeCacheLoader::ReceiveDataForSynchronousFetch,
- weak_ptr_factory_.GetWeakPtr());
-
- // It is Ok to pass |fetch_code_cache_event| with base::Unretained. Since
- // this thread is stalled, the fetch_code_cache_event will be kept alive.
- task_runner->PostTask(
- FROM_HERE, base::BindOnce(&CodeCacheLoader::FetchFromCodeCacheImpl,
- weak_ptr_factory_.GetWeakPtr(),
- mojom::CodeCacheType::kJavascript, url,
- std::move(callback),
- base::Unretained(&fetch_code_cache_event)));
-
- // Wait for the fetch from code cache to finish.
- fetch_code_cache_event.Wait();
-
- // Set the output data
- *response_time_out = response_time_for_sync_load_;
- *data_out = std::move(data_for_sync_load_);
-}
-
-void CodeCacheLoader::FetchFromCodeCache(mojom::CodeCacheType cache_type,
- const WebURL& url,
- FetchCodeCacheCallback callback) {
- FetchFromCodeCacheImpl(cache_type, url, std::move(callback), nullptr);
-}
-
-void CodeCacheLoader::FetchFromCodeCacheImpl(mojom::CodeCacheType cache_type,
- const WebURL& url,
- FetchCodeCacheCallback callback,
- base::WaitableEvent* fetch_event) {
- // This may run on a different thread for synchronous events. It is Ok to pass
- // fetch_event, because the thread is stalled and it will keep the fetch_event
- // alive.
- Platform::Current()->FetchCachedCode(
- cache_type, url,
- base::BindOnce(&CodeCacheLoader::OnReceiveCachedCode,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- fetch_event));
-}
-
-void CodeCacheLoader::OnReceiveCachedCode(FetchCodeCacheCallback callback,
- base::WaitableEvent* fetch_event,
- base::Time response_time,
- mojo_base::BigBuffer data) {
- // The loader would be destroyed once the fetch has completed. On terminate
- // the fetch event would be signalled and the fetch should complete and hence
- // we should not see this callback anymore.
- DCHECK(!terminated_);
- std::move(callback).Run(response_time, std::move(data));
- if (fetch_event)
- fetch_event->Signal();
-}
-
-void CodeCacheLoader::ReceiveDataForSynchronousFetch(
- base::Time response_time,
- mojo_base::BigBuffer data) {
- response_time_for_sync_load_ = response_time;
- data_for_sync_load_ = std::move(data);
-}
-
-void CodeCacheLoader::OnTerminate(base::WaitableEvent* fetch_event,
- base::WaitableEvent* terminate_event) {
- DCHECK(!terminated_);
- terminated_ = true;
- DCHECK(fetch_event);
- fetch_event->Signal();
-}
-
-// static
-std::unique_ptr<WebCodeCacheLoader> WebCodeCacheLoader::Create(
- base::WaitableEvent* terminate_sync_load_event) {
- return std::make_unique<CodeCacheLoader>(terminate_sync_load_event);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/code_cache_loader.h b/chromium/third_party/blink/renderer/platform/loader/code_cache_loader.h
deleted file mode 100644
index 86fc7ed02d9..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/code_cache_loader.h
+++ /dev/null
@@ -1,64 +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_LOADER_CODE_CACHE_LOADER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CODE_CACHE_LOADER_H_
-
-#include "base/containers/span.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/synchronization/waitable_event_watcher.h"
-#include "third_party/blink/public/platform/web_code_cache_loader.h"
-#include "url/gurl.h"
-
-namespace blink {
-
-// This class is loading V8 compilation code cache for scripts
-// (either separate script resources, or inline scripts in html file).
-// It is talking to the browser process and uses per-site isolated
-// cache backend to avoid cross-origin contamination.
-class BLINK_PLATFORM_EXPORT CodeCacheLoader : public WebCodeCacheLoader {
- public:
- CodeCacheLoader();
- explicit CodeCacheLoader(base::WaitableEvent* terminate_sync_load_event);
-
- ~CodeCacheLoader() override;
-
- // Fetches code cache corresponding to |url| and returns response in
- // |response_time_out| and |data_out|. |response_time_out| and |data_out|
- // cannot be nullptrs. This only fetches from the Javascript cache.
- void FetchFromCodeCacheSynchronously(const WebURL& url,
- base::Time* response_time_out,
- mojo_base::BigBuffer* data_out) override;
-
- void FetchFromCodeCache(mojom::CodeCacheType cache_type,
- const WebURL& url,
- FetchCodeCacheCallback callback) override;
-
- private:
- void FetchFromCodeCacheImpl(mojom::CodeCacheType cache_type,
- const WebURL& url,
- FetchCodeCacheCallback callback,
- base::WaitableEvent* event);
-
- void OnReceiveCachedCode(FetchCodeCacheCallback callback,
- base::WaitableEvent* event,
- base::Time response_time,
- mojo_base::BigBuffer data);
- void ReceiveDataForSynchronousFetch(base::Time response_time,
- mojo_base::BigBuffer data);
- void OnTerminate(base::WaitableEvent* fetch_event,
- base::WaitableEvent* terminate_event);
-
- base::Time response_time_for_sync_load_;
- mojo_base::BigBuffer data_for_sync_load_;
- bool terminated_ = false;
- base::WaitableEventWatcher terminate_watcher_;
- base::WaitableEvent* terminate_sync_load_event_ = nullptr;
- base::WeakPtrFactory<CodeCacheLoader> weak_ptr_factory_{this};
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CODE_CACHE_LOADER_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 919102b97d3..c0e6bab9551 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -42,9 +42,9 @@ class HTTPHeaderNameListParser {
return;
}
- size_t token_start = pos_;
+ wtf_size_t token_start = pos_;
ConsumeTokenChars();
- size_t token_size = pos_ - token_start;
+ wtf_size_t token_size = pos_ - token_start;
if (token_size == 0) {
output.clear();
return;
@@ -93,7 +93,7 @@ class HTTPHeaderNameListParser {
}
const String value_;
- size_t pos_;
+ wtf_size_t pos_;
};
} // namespace
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 b443bd7afad..1f1bdbc079d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
@@ -8,7 +8,6 @@
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/mojom/cors.mojom-blink-forward.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/network/http_header_set.h"
#include "third_party/blink/renderer/platform/platform_export.h"
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 73dfab95277..ef06613f651 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CORS_CORS_ERROR_STRING_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CORS_CORS_ERROR_STRING_H_
-#include "base/macros.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/mojom/cors.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_url_request.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.cc
index 422ac99b105..04141ebb9d9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
namespace blink {
@@ -62,12 +62,7 @@ CachedMetadata::CachedMetadata(uint32_t data_type_id,
DCHECK(data_type_id);
DCHECK(data);
- vector_.ReserveInitialCapacity(kCachedMetaDataStart + size);
- uint32_t marker = CachedMetadataHandler::kSingleEntry;
- vector_.Append(reinterpret_cast<const uint8_t*>(&marker), sizeof(uint32_t));
- vector_.Append(reinterpret_cast<const uint8_t*>(&data_type_id),
- sizeof(uint32_t));
- vector_.Append(data, size);
+ vector_ = CachedMetadata::GetSerializedData(data_type_id, data, size);
}
CachedMetadata::CachedMetadata(mojo_base::BigBuffer data) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h
index 66b6bda12f5..9b58818dc4b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h
@@ -34,6 +34,7 @@
#include <stdint.h>
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/base/big_buffer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -62,6 +63,20 @@ class PLATFORM_EXPORT CachedMetadata : public RefCounted<CachedMetadata> {
new CachedMetadata(data_type_id, data, SafeCast<wtf_size_t>(size)));
}
+ static Vector<uint8_t> GetSerializedData(uint32_t data_type_id,
+ const uint8_t* data,
+ size_t size) {
+ Vector<uint8_t> vector;
+ vector.ReserveInitialCapacity(kCachedMetaDataStart +
+ SafeCast<wtf_size_t>(size));
+ uint32_t marker = CachedMetadataHandler::kSingleEntry;
+ vector.Append(reinterpret_cast<const uint8_t*>(&marker), sizeof(uint32_t));
+ vector.Append(reinterpret_cast<const uint8_t*>(&data_type_id),
+ sizeof(uint32_t));
+ vector.Append(data, SafeCast<wtf_size_t>(size));
+ return vector;
+ }
+
static scoped_refptr<CachedMetadata> CreateFromSerializedData(
const uint8_t* data,
size_t);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
deleted file mode 100644
index d9f2f162d1b..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this sink code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-namespace {
-
-class MockPlatform final : public TestingPlatformSupportWithMockScheduler {
- public:
- MockPlatform() = default;
- ~MockPlatform() override = default;
-
- // From blink::Platform:
- void CacheMetadata(mojom::blink::CodeCacheType cache_type,
- const WebURL& url,
- base::Time,
- const uint8_t*,
- size_t) override {
- cached_urls_.push_back(url);
- }
-
- void CacheMetadataInCacheStorage(const WebURL& url,
- base::Time,
- const uint8_t*,
- size_t,
- const WebSecurityOrigin&,
- const WebString&) override {
- cache_storage_cached_urls_.push_back(url);
- }
-
- const Vector<WebURL>& CachedURLs() const { return cached_urls_; }
- const Vector<WebURL>& CacheStorageCachedURLs() const {
- return cache_storage_cached_urls_;
- }
-
- private:
- Vector<WebURL> cached_urls_;
- Vector<WebURL> cache_storage_cached_urls_;
-};
-
-ResourceResponse CreateTestResourceResponse() {
- ResourceResponse response(KURL("https://example.com/"));
- response.SetHttpStatusCode(200);
- return response;
-}
-
-void SendDataFor(const ResourceResponse& response) {
- constexpr uint8_t kTestData[] = {1, 2, 3, 4, 5};
- std::unique_ptr<CachedMetadataSender> sender = CachedMetadataSender::Create(
- response, mojom::blink::CodeCacheType::kJavascript,
- SecurityOrigin::Create(response.CurrentRequestUrl()));
- sender->Send(kTestData, sizeof(kTestData));
-}
-
-TEST(CachedMetadataHandlerTest, SendsMetadataToPlatform) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
- ResourceResponse response(CreateTestResourceResponse());
-
- SendDataFor(response);
- EXPECT_EQ(1u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- CachedMetadataHandlerTest,
- DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithSyntheticResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(new Response(...))
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
-
- SendDataFor(response);
- EXPECT_EQ(0u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- CachedMetadataHandlerTest,
- SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithPassThroughResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(fetch(evt.request.url));
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
- response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
-
- SendDataFor(response);
- EXPECT_EQ(1u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- CachedMetadataHandlerTest,
- DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(fetch(some_different_url))
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
- response.SetUrlListViaServiceWorker(
- {KURL("https://example.com/different/url")});
-
- SendDataFor(response);
- EXPECT_EQ(0u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(CachedMetadataHandlerTest,
- SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithCacheResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(cache.match(some_url));
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
- response.SetCacheStorageCacheName("dummy");
-
- SendDataFor(response);
- EXPECT_EQ(0u, mock->CachedURLs().size());
- EXPECT_EQ(1u, mock->CacheStorageCachedURLs().size());
-}
-
-} // namespace
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
index bdd7a1ffb3f..8ffd2aa64a0 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
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
#include "base/command_line.h"
-#include "base/macros.h"
#include "services/network/public/cpp/client_hints.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
@@ -47,12 +46,6 @@ void ClientHintsPreferences::CombineWith(
}
}
-bool ClientHintsPreferences::UserAgentClientHintEnabled() {
- return RuntimeEnabledFeatures::UserAgentClientHintEnabled() &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUserAgentClientHintDisable);
-}
-
void ClientHintsPreferences::UpdateFromHttpEquivAcceptCH(
const String& header_value,
const KURL& url,
@@ -70,11 +63,7 @@ void ClientHintsPreferences::UpdateFromHttpEquivAcceptCH(
// Note: .Ascii() would convert tab to ?, which is undesirable.
absl::optional<std::vector<network::mojom::WebClientHintsType>> parsed_ch =
- FilterAcceptCH(
- network::ParseClientHintsHeader(header_value.Latin1()),
- RuntimeEnabledFeatures::LangClientHintHeaderEnabled(),
- UserAgentClientHintEnabled(),
- RuntimeEnabledFeatures::PrefersColorSchemeClientHintHeaderEnabled());
+ network::ParseClientHintsHeader(header_value.Latin1());
if (!parsed_ch.has_value())
return;
@@ -101,8 +90,18 @@ bool ClientHintsPreferences::IsClientHintsAllowed(const KURL& url) {
network::IsOriginPotentiallyTrustworthy(url::Origin::Create(url));
}
-WebEnabledClientHints ClientHintsPreferences::GetWebEnabledClientHints() const {
+EnabledClientHints ClientHintsPreferences::GetEnabledClientHints() const {
return enabled_hints_;
}
+bool ClientHintsPreferences::ShouldSend(
+ network::mojom::WebClientHintsType type) const {
+ return enabled_hints_.IsEnabled(type);
+}
+
+void ClientHintsPreferences::SetShouldSend(
+ network::mojom::WebClientHintsType type) {
+ enabled_hints_.SetIsEnabled(type, true);
+}
+
} // 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 67cd5992e15..66215c913a0 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_CLIENT_HINTS_PREFERENCES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_CLIENT_HINTS_PREFERENCES_H_
-#include "third_party/blink/public/platform/web_client_hints_type.h"
+#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -41,23 +41,17 @@ class PLATFORM_EXPORT ClientHintsPreferences {
const KURL& url,
Context* context);
- bool ShouldSend(network::mojom::WebClientHintsType type) const {
- return enabled_hints_.IsEnabled(type);
- }
- void SetShouldSend(network::mojom::WebClientHintsType type) {
- enabled_hints_.SetIsEnabled(type, true);
- }
+ bool ShouldSend(network::mojom::WebClientHintsType type) const;
+ void SetShouldSend(network::mojom::WebClientHintsType type);
// 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&);
- static bool UserAgentClientHintEnabled();
-
- WebEnabledClientHints GetWebEnabledClientHints() const;
+ EnabledClientHints GetEnabledClientHints() const;
private:
- WebEnabledClientHints enabled_hints_;
+ EnabledClientHints enabled_hints_;
};
} // 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 2bf71e51959..a9fcda58b8e 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
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
+#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
@@ -12,7 +14,20 @@
namespace blink {
-class ClientHintsPreferencesTest : public testing::Test {};
+class ClientHintsPreferencesTest : public testing::Test {
+ public:
+ ClientHintsPreferencesTest() {
+ scoped_feature_list_.InitWithFeatures(
+ /*enabled_features=*/{blink::features::kUserAgentClientHint,
+ blink::features::kLangClientHintHeader,
+ blink::features::
+ kPrefersColorSchemeClientHintHeader},
+ /*disabled_features=*/{});
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
TEST_F(ClientHintsPreferencesTest, BasicSecure) {
struct TestCase {
@@ -280,8 +295,7 @@ TEST_F(ClientHintsPreferencesTest, ParseHeaders) {
for (const auto& test : test_cases) {
ClientHintsPreferences preferences;
- WebEnabledClientHints enabled_types =
- preferences.GetWebEnabledClientHints();
+ EnabledClientHints enabled_types = preferences.GetEnabledClientHints();
EXPECT_FALSE(enabled_types.IsEnabled(
network::mojom::WebClientHintsType::kDeviceMemory));
EXPECT_FALSE(
@@ -313,7 +327,7 @@ TEST_F(ClientHintsPreferencesTest, ParseHeaders) {
preferences.UpdateFromHttpEquivAcceptCH(test.accept_ch_header_value, kurl,
nullptr);
- enabled_types = preferences.GetWebEnabledClientHints();
+ enabled_types = preferences.GetEnabledClientHints();
EXPECT_EQ(test.expect_device_memory,
enabled_types.IsEnabled(
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc
index 9ae4783e87a..ba22d65d828 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc
@@ -28,7 +28,7 @@ TEST_F(DataPipeBytesConsumerTest, TwoPhaseRead) {
MOJO_RESULT_OK);
const std::string kData = "Such hospitality. I'm underwhelmed.";
- uint32_t write_size = kData.size();
+ uint32_t write_size = static_cast<uint32_t>(kData.size());
MojoResult rv = producer_handle->WriteData(kData.c_str(), &write_size,
MOJO_WRITE_DATA_FLAG_NONE);
@@ -56,7 +56,7 @@ TEST_F(DataPipeBytesConsumerTest, TwoPhaseRead_SignalError) {
MOJO_RESULT_OK);
const std::string kData = "Such hospitality. I'm underwhelmed.";
- uint32_t write_size = kData.size();
+ uint32_t write_size = static_cast<uint32_t>(kData.size());
MojoResult rv = producer_handle->WriteData(kData.c_str(), &write_size,
MOJO_WRITE_DATA_FLAG_NONE);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h b/chromium/third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h
index a2478953caf..20e1fd0e140 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h
@@ -24,6 +24,11 @@ class DetachableUseCounter final
use_counter_->CountUse(feature);
}
}
+ void CountDeprecation(mojom::WebFeature feature) override {
+ if (use_counter_) {
+ use_counter_->CountDeprecation(feature);
+ }
+ }
void Trace(Visitor* visitor) const override { visitor->Trace(use_counter_); }
void Detach() { use_counter_ = nullptr; }
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
index c578f9bfe45..e65e829f9c0 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
@@ -85,7 +85,9 @@ bool StructTraits<blink::mojom::FetchAPIRequestBodyDataView,
switch (element.type()) {
case network::DataElement::Tag::kBytes: {
const auto& bytes = element.As<network::DataElementBytes>();
- form_data->AppendData(bytes.bytes().data(), bytes.bytes().size());
+ form_data->AppendData(
+ bytes.bytes().data(),
+ base::checked_cast<wtf_size_t>(bytes.bytes().size()));
break;
}
case network::DataElement::Tag::kFile: {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
index 4576e3abe9d..bd27f3a5917 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_API_REQUEST_BODY_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_API_REQUEST_BODY_MOJOM_TRAITS_H_
+#include "services/network/public/cpp/data_element.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc
index 4dbcbc065a1..b1314db16bf 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h"
+#include "base/macros.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/base/file_mojom_traits.h"
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
index 30f55ce27b9..19e7a4dc7f2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
@@ -6,8 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_CLIENT_SETTINGS_OBJECT_H_
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
-#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
index b4ae59e5550..7b7935b148e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
@@ -52,6 +52,10 @@ struct CrossThreadFetchClientSettingsObjectData {
address_space(address_space),
insecure_requests_policy(insecure_requests_policy),
insecure_navigations_set(std::move(insecure_navigations_set)) {}
+ CrossThreadFetchClientSettingsObjectData(
+ const CrossThreadFetchClientSettingsObjectData&) = delete;
+ CrossThreadFetchClientSettingsObjectData& operator=(
+ const CrossThreadFetchClientSettingsObjectData&) = delete;
const KURL global_object_url;
const KURL base_url;
@@ -65,9 +69,6 @@ struct CrossThreadFetchClientSettingsObjectData {
const mojom::blink::InsecureRequestPolicy insecure_requests_policy;
const FetchClientSettingsObject::InsecureNavigationsSet
insecure_navigations_set;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CrossThreadFetchClientSettingsObjectData);
};
// This takes a partial snapshot of the execution context's states so that an
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 7156f8045a3..39f9561e9a8 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
@@ -33,7 +33,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
@@ -71,6 +70,8 @@ class WebScopedVirtualTimePauser;
class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
public:
FetchContext() = default;
+ FetchContext(const FetchContext&) = delete;
+ FetchContext& operator=(const FetchContext&) = delete;
static FetchContext& NullInstance() {
return *MakeGarbageCollected<FetchContext>();
@@ -193,9 +194,6 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
// Returns if the request context is for prerendering or not.
virtual bool IsPrerendering() const { return false; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FetchContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h b/chromium/third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h
new file mode 100644
index 00000000000..7380e47be30
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_LOADER_FREEZE_MODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_LOADER_FREEZE_MODE_H_
+
+#include "third_party/blink/public/platform/web_loader_freeze_mode.h"
+
+namespace blink {
+using LoaderFreezeMode = WebLoaderFreezeMode;
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_LOADER_FREEZE_MODE_H_
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 7ceb5ebf145..39d34b7d589 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
@@ -170,7 +170,8 @@ void MemoryCache::Remove(Resource* resource) {
TRACE_EVENT1("blink", "MemoryCache::evict", "resource",
resource->Url().GetString().Utf8());
- ResourceMap* resources = resource_maps_.at(resource->CacheIdentifier());
+ ResourceMap* resources =
+ resource_maps_.DeprecatedAtOrEmptyValue(resource->CacheIdentifier());
if (!resources)
return;
@@ -196,11 +197,12 @@ void MemoryCache::RemoveInternal(ResourceMap* resource_map,
bool MemoryCache::Contains(const Resource* resource) const {
if (!resource || resource->Url().IsEmpty())
return false;
- const ResourceMap* resources = resource_maps_.at(resource->CacheIdentifier());
+ const ResourceMap* resources =
+ resource_maps_.DeprecatedAtOrEmptyValue(resource->CacheIdentifier());
if (!resources)
return false;
KURL url = RemoveFragmentIdentifierIfNeeded(resource->Url());
- MemoryCacheEntry* entry = resources->at(url);
+ MemoryCacheEntry* entry = resources->DeprecatedAtOrEmptyValue(url);
return entry && resource == entry->GetResource();
}
@@ -214,11 +216,12 @@ Resource* MemoryCache::ResourceForURL(const KURL& resource_url,
if (!resource_url.IsValid() || resource_url.IsNull())
return nullptr;
DCHECK(!cache_identifier.IsNull());
- const ResourceMap* resources = resource_maps_.at(cache_identifier);
+ const ResourceMap* resources =
+ resource_maps_.DeprecatedAtOrEmptyValue(cache_identifier);
if (!resources)
return nullptr;
- MemoryCacheEntry* entry =
- resources->at(RemoveFragmentIdentifierIfNeeded(resource_url));
+ MemoryCacheEntry* entry = resources->DeprecatedAtOrEmptyValue(
+ RemoveFragmentIdentifierIfNeeded(resource_url));
if (!entry)
return nullptr;
return entry->GetResource();
@@ -230,7 +233,8 @@ HeapVector<Member<Resource>> MemoryCache::ResourcesForURL(
KURL url = RemoveFragmentIdentifierIfNeeded(resource_url);
HeapVector<Member<Resource>> results;
for (const auto& resource_map_iter : resource_maps_) {
- if (MemoryCacheEntry* entry = resource_map_iter.value->at(url)) {
+ if (MemoryCacheEntry* entry =
+ resource_map_iter.value->DeprecatedAtOrEmptyValue(url)) {
Resource* resource = entry->GetResource();
DCHECK(resource);
results.push_back(resource);
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 072f8f54e9f..60139313d1e 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
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_MEMORY_CACHE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_MEMORY_CACHE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -68,6 +67,8 @@ class PLATFORM_EXPORT MemoryCache final : public GarbageCollected<MemoryCache>,
public MemoryPressureListener {
public:
explicit MemoryCache(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ MemoryCache(const MemoryCache&) = delete;
+ MemoryCache& operator=(const MemoryCache&) = delete;
~MemoryCache() override;
void Trace(Visitor*) const override;
@@ -194,8 +195,6 @@ class PLATFORM_EXPORT MemoryCache final : public GarbageCollected<MemoryCache>,
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
friend class MemoryCacheTest;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryCache);
};
// Returns the global cache.
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 a1217b9eb1f..999d5274977 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
@@ -231,7 +231,7 @@ static void TestResourcePruningLater(ResourceFetcher* fetcher,
platform->RunUntilIdle();
// Now, the resources was pruned.
- unsigned size_without_decode =
+ size_t size_without_decode =
resource1->EncodedSize() + resource1->OverheadSize() +
resource2->EncodedSize() + resource2->OverheadSize();
EXPECT_EQ(size_without_decode, GetMemoryCache()->size());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h b/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h
index 8600f44dc2d..b425b6d1006 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h
@@ -36,11 +36,10 @@ class PLATFORM_EXPORT NullResourceFetcherProperties final
return 0;
}
bool IsPaused() const override { return false; }
- WebURLLoader::DeferType DeferType() const override {
- return WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode FreezeMode() const override {
+ return LoaderFreezeMode::kNone;
}
bool IsDetached() const override { return true; }
- bool IsLoadDeferred() const override { return false; }
bool IsLoadComplete() const override { return true; }
bool ShouldBlockLoadingSubResource() const override { return true; }
bool IsSubframeDeprioritizationEnabled() const override { return false; }
@@ -49,6 +48,10 @@ class PLATFORM_EXPORT NullResourceFetcherProperties final
}
const KURL& WebBundlePhysicalUrl() const override;
int GetOutstandingThrottledLimit() const override { return 0; }
+ scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin()
+ const override {
+ return nullptr;
+ }
private:
const Member<const FetchClientSettingsObject> fetch_client_settings_object_;
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 56face486db..1954e2c2d29 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
@@ -418,8 +418,38 @@ NOINLINE void RawResourceClientStateChecker::DidDownloadToBlob() {
NOINLINE void RawResourceClientStateChecker::NotifyFinished(
Resource* resource) {
+ // TODO(https://crbug.com/1158346): Remove these once the investigation is
+ // done.
+ const int32_t destination =
+ static_cast<int32_t>(
+ resource->GetResourceRequest().GetRequestDestination()) +
+ 0x400;
+ const int32_t context =
+ static_cast<int32_t>(resource->GetResourceRequest().GetRequestContext()) +
+ 0x800;
+ const int32_t mark1 = 0xcdcdcdcd;
+ char url[80] = {};
+ const int32_t mark2 = 0xcdcdcdcd;
+ base::debug::Alias(&destination);
+ base::debug::Alias(&context);
+ base::debug::Alias(&mark1);
+ base::debug::Alias(url);
+ base::debug::Alias(&mark2);
+
SECURITY_CHECK(state_ != kNotAddedAsClient);
SECURITY_CHECK(state_ != kNotifyFinished);
+
+ // TODO(https://crbug.com/1158346): Remove these CHECKs once the investigation
+ // is done.
+ if (!resource->ErrorOccurred()) {
+ std::string url_string =
+ resource->Url().UrlStrippedForUseAsReferrer().GetString().Utf8();
+ strncpy(url, url_string.c_str(), sizeof(url) - 1);
+
+ SECURITY_CHECK(state_ != kStarted);
+ SECURITY_CHECK(state_ != kRedirectBlocked);
+ }
+
SECURITY_CHECK(resource->ErrorOccurred() ||
(state_ == kResponseReceived || state_ == kDataReceived ||
state_ == kDataDownloaded ||
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 e12976c8812..3608238fb91 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
@@ -25,7 +25,6 @@
#include <memory>
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
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 48f308f59eb..180ec4ebe8d 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
@@ -55,6 +55,8 @@ namespace blink {
class RawResourceTest : public testing::Test {
public:
RawResourceTest() = default;
+ RawResourceTest(const RawResourceTest&) = delete;
+ RawResourceTest& operator=(const RawResourceTest&) = delete;
~RawResourceTest() override = default;
protected:
@@ -71,9 +73,6 @@ class RawResourceTest : public testing::Test {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RawResourceTest);
};
TEST_F(RawResourceTest, DontIgnoreAcceptForCacheReuse) {
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 877494c674c..75b91ab08a8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -30,8 +30,8 @@
#include <cassert>
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/time/default_clock.h"
#include "build/build_config.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
@@ -528,6 +528,10 @@ void Resource::SetSerializedCachedMetadata(mojo_base::BigBuffer data) {
DCHECK(!GetResponse().IsNull());
}
+bool Resource::CodeCacheHashRequired() const {
+ return false;
+}
+
String Resource::ReasonNotDeletable() const {
StringBuilder builder;
if (HasClientsOrObservers()) {
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 8824f5cdfb4..b9816c50d0d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -145,6 +145,8 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
kScriptTypeDoesNotMatch,
};
+ Resource(const Resource&) = delete;
+ Resource& operator=(const Resource&) = delete;
~Resource() override;
void Trace(Visitor*) const override;
@@ -271,6 +273,10 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
// should implement the resource-specific behavior.
virtual void SetSerializedCachedMetadata(mojo_base::BigBuffer data);
+ // Gets whether the serialized cached metadata must contain a hash of the
+ // source text. For resources other than ScriptResource, this is always false.
+ virtual bool CodeCacheHashRequired() const;
+
AtomicString HttpContentType() const;
bool WasCanceled() const { return error_ && error_->IsCancellation(); }
@@ -558,8 +564,6 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
// TODO(crbug.com/1127971): Remove this once the decision is made to partition
// the cache using either Network Isolation Key or scoped to per-document.
std::set<net::SchemefulSite> existing_top_frame_sites_in_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(Resource);
};
class ResourceFactory {
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 af1a1f145e6..c7ae11a4590 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
@@ -273,17 +273,6 @@ void SetReferrer(
request.SetReferrerPolicy(generated_referrer.referrer_policy);
}
-void PopulateAndAddResourceTimingInfo(Resource* resource,
- scoped_refptr<ResourceTimingInfo> info,
- base::TimeTicks response_end) {
- info->SetInitialURL(
- resource->GetResourceRequest().GetRedirectInfo().has_value()
- ? resource->GetResourceRequest().GetRedirectInfo()->original_url
- : resource->GetResourceRequest().Url());
- info->SetFinalResponse(resource->GetResponse());
- info->SetLoadResponseEnd(response_end);
-}
-
} // namespace
ResourceFetcherInit::ResourceFetcherInit(
@@ -549,7 +538,8 @@ 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);
+ const WeakMember<Resource>& resource =
+ cached_resources_map_.DeprecatedAtOrEmptyValue(url);
return resource.Get();
}
@@ -720,6 +710,10 @@ void ResourceFetcher::MakePreloadedResourceBlockOnloadIfNeeded(
non_blocking_loaders_.Contains(resource->Loader())) {
non_blocking_loaders_.erase(resource->Loader());
loaders_.insert(resource->Loader());
+ if (resource_load_observer_) {
+ resource_load_observer_->DidChangeRenderBlockingBehavior(resource,
+ params);
+ }
}
}
@@ -1177,14 +1171,6 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
return resource;
}
-void ResourceFetcher::MarkFirstPaint() {
- scheduler_->MarkFirstPaint();
-}
-
-void ResourceFetcher::MarkFirstContentfulPaint() {
- scheduler_->MarkFirstContentfulPaint();
-}
-
void ResourceFetcher::ResourceTimingReportTimerFired(TimerBase* timer) {
DCHECK_EQ(timer, &resource_timing_report_timer_);
Vector<scoped_refptr<ResourceTimingInfo>> timing_reports;
@@ -1869,7 +1855,7 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
if (scoped_refptr<ResourceTimingInfo> info =
resource_timing_info_map_.Take(resource)) {
- if (resource->GetResponse().IsHTTP()) {
+ if (resource->GetResponse().ShouldPopulateResourceTiming()) {
PopulateAndAddResourceTimingInfo(resource, info, response_end);
auto receiver = Context().TakePendingWorkerTimingReceiver(
resource->GetResponse().RequestId());
@@ -2057,11 +2043,11 @@ void ResourceFetcher::StopFetching() {
StopFetchingInternal(StopFetchingTarget::kExcludingKeepaliveLoaders);
}
-void ResourceFetcher::SetDefersLoading(WebURLLoader::DeferType defers) {
+void ResourceFetcher::SetDefersLoading(LoaderFreezeMode mode) {
for (const auto& loader : non_blocking_loaders_)
- loader->SetDefersLoading(defers);
+ loader->SetDefersLoading(mode);
for (const auto& loader : loaders_)
- loader->SetDefersLoading(defers);
+ loader->SetDefersLoading(mode);
}
void ResourceFetcher::UpdateAllImageResourcePriorities() {
@@ -2262,6 +2248,31 @@ FrameOrWorkerScheduler* ResourceFetcher::GetFrameOrWorkerScheduler() {
return frame_or_worker_scheduler_.get();
}
+void ResourceFetcher::PopulateAndAddResourceTimingInfo(
+ Resource* resource,
+ scoped_refptr<ResourceTimingInfo> info,
+ base::TimeTicks response_end) {
+ const KURL& initial_url =
+ resource->GetResourceRequest().GetRedirectInfo().has_value()
+ ? resource->GetResourceRequest().GetRedirectInfo()->original_url
+ : resource->GetResourceRequest().Url();
+
+ auto it = early_hints_preloaded_resources_.find(initial_url);
+ if (it != early_hints_preloaded_resources_.end()) {
+ early_hints_preloaded_resources_.erase(it);
+ const ResourceResponse& response = resource->GetResponse();
+ if (!response.NetworkAccessed() &&
+ (!response.WasFetchedViaServiceWorker() ||
+ response.IsServiceWorkerPassThrough())) {
+ info->SetInitiatorType("early-hints");
+ }
+ }
+
+ info->SetInitialURL(initial_url);
+ info->SetFinalResponse(resource->GetResponse());
+ info->SetLoadResponseEnd(response_end);
+}
+
void ResourceFetcher::Trace(Visitor* visitor) const {
visitor->Trace(context_);
visitor->Trace(properties_);
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 ec5ef033e0a..0f0af909e9c 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
@@ -38,6 +38,7 @@
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/preload_key.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h"
@@ -112,6 +113,8 @@ class PLATFORM_EXPORT ResourceFetcher
// ResourceFetcher creators are responsible for setting consistent objects
// in ResourceFetcherInit to ensure correctness of this ResourceFetcher.
explicit ResourceFetcher(const ResourceFetcherInit&);
+ ResourceFetcher(const ResourceFetcher&) = delete;
+ ResourceFetcher& operator=(const ResourceFetcher&) = delete;
virtual ~ResourceFetcher();
virtual void Trace(Visitor*) const;
@@ -150,14 +153,6 @@ class PLATFORM_EXPORT ResourceFetcher
const ResourceFactory&,
ResourceClient*);
- // TODO(crbug/1112515): Instead of having one-off notifications of these
- // loading milestones, we should introduce an abstract interface that
- // interested parties can hook into, to be notified of relevant loading
- // milestones.
- // These are only called for main frames.
- void MarkFirstPaint();
- void MarkFirstContentfulPaint();
-
// Returns the task runner used by this fetcher, and loading operations
// this fetcher initiates. The returned task runner will keep working even
// after ClearContext is called.
@@ -228,7 +223,7 @@ class PLATFORM_EXPORT ResourceFetcher
// Set the deferring state of each loader owned by this ResourceFetcher. This
// method must be called when the page freezing state changes.
// TODO(yhirano): Rename this to a more easily recognizable name.
- void SetDefersLoading(WebURLLoader::DeferType);
+ void SetDefersLoading(LoaderFreezeMode);
void StopFetching();
@@ -305,12 +300,6 @@ class PLATFORM_EXPORT ResourceFetcher
scheduler_->SetThrottleOptionOverride(throttle_option_override);
}
- void SetOptimizationGuideHints(
- mojom::blink::DelayCompetingLowPriorityRequestsHintsPtr
- optimization_hints) {
- scheduler_->SetOptimizationGuideHints(std::move(optimization_hints));
- }
-
void AttachWebBundleTokenIfNeeded(ResourceRequest&) const;
SubresourceWebBundleList* GetOrCreateSubresourceWebBundleList();
@@ -318,6 +307,10 @@ class PLATFORM_EXPORT ResourceFetcher
return back_forward_cache_loader_helper_;
}
+ void SetEarlyHintsPreloadedResources(HashSet<KURL> preloaded) {
+ early_hints_preloaded_resources_ = std::move(preloaded);
+ }
+
private:
friend class ResourceCacheValidationSuppressor;
enum class StopFetchingTarget {
@@ -338,7 +331,7 @@ class PLATFORM_EXPORT ResourceFetcher
ResourceType,
const ResourceRequestHead&,
ResourcePriority::VisibilityStatus,
- FetchParameters::DeferOption = FetchParameters::kNoDefer,
+ FetchParameters::DeferOption = FetchParameters::DeferOption::kNoDefer,
FetchParameters::SpeculativePreloadType =
FetchParameters::SpeculativePreloadType::kNotSpeculative,
bool is_link_preload = false);
@@ -425,6 +418,10 @@ class PLATFORM_EXPORT ResourceFetcher
void WarnUnusedPreloads();
+ void PopulateAndAddResourceTimingInfo(Resource* resource,
+ scoped_refptr<ResourceTimingInfo> info,
+ base::TimeTicks response_end);
+
Member<DetachableResourceFetcherProperties> properties_;
Member<ResourceLoadObserver> resource_load_observer_;
Member<FetchContext> context_;
@@ -463,6 +460,8 @@ class PLATFORM_EXPORT ResourceFetcher
HeapHashSet<Member<ResourceLoader>> loaders_;
HeapHashSet<Member<ResourceLoader>> non_blocking_loaders_;
+ HashSet<KURL> early_hints_preloaded_resources_;
+
std::unique_ptr<HashSet<String>> preloaded_urls_for_test_;
// TODO(altimin): Move FrameScheduler to oilpan.
@@ -492,8 +491,6 @@ class PLATFORM_EXPORT ResourceFetcher
// NOTE: This must be the last member.
base::WeakPtrFactory<ResourceFetcher> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ResourceFetcher);
};
class ResourceCacheValidationSuppressor {
@@ -507,6 +504,10 @@ class ResourceCacheValidationSuppressor {
loader_->allow_stale_resources_ = true;
}
}
+ ResourceCacheValidationSuppressor(const ResourceCacheValidationSuppressor&) =
+ delete;
+ ResourceCacheValidationSuppressor& operator=(
+ const ResourceCacheValidationSuppressor&) = delete;
~ResourceCacheValidationSuppressor() {
if (loader_)
loader_->allow_stale_resources_ = previous_state_;
@@ -515,8 +516,6 @@ class ResourceCacheValidationSuppressor {
private:
ResourceFetcher* loader_;
bool previous_state_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceCacheValidationSuppressor);
};
// Used for ResourceFetcher construction.
@@ -541,6 +540,8 @@ struct PLATFORM_EXPORT ResourceFetcherInit final {
ResourceFetcher::LoaderFactory* loader_factory,
ContextLifecycleNotifier* context_lifecycle_notifier,
BackForwardCacheLoaderHelper* back_forward_cache_loader_helper = nullptr);
+ ResourceFetcherInit(const ResourceFetcherInit&) = delete;
+ ResourceFetcherInit& operator=(const ResourceFetcherInit&) = delete;
DetachableResourceFetcherProperties* const properties;
FetchContext* const context;
@@ -558,8 +559,6 @@ struct PLATFORM_EXPORT ResourceFetcherInit final {
ResourceLoadScheduler::ThrottleOptionOverride::kNone;
LoadingBehaviorObserver* loading_behavior_observer = nullptr;
BackForwardCacheLoaderHelper* back_forward_cache_loader_helper = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceFetcherInit);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc
index 6b4603a91dd..33510d2cf22 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc
@@ -20,11 +20,14 @@ void DetachableResourceFetcherProperties::Detach() {
properties_->GetFetchClientSettingsObject());
is_main_frame_ = properties_->IsMainFrame();
paused_ = properties_->IsPaused();
+ freeze_mode_ = properties_->FreezeMode();
load_complete_ = properties_->IsLoadComplete();
is_subframe_deprioritization_enabled_ =
properties_->IsSubframeDeprioritizationEnabled();
web_bundle_physical_url_ = properties_->WebBundlePhysicalUrl();
outstanding_throttled_limit_ = properties_->GetOutstandingThrottledLimit();
+ litepage_subresource_redirect_origin_ =
+ properties_->GetLitePageSubresourceRedirectOrigin();
properties_ = nullptr;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h
index f1bffa6f477..f860d358074 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h
@@ -8,9 +8,11 @@
#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_status.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -65,19 +67,14 @@ class PLATFORM_EXPORT ResourceFetcherProperties
// https://html.spec.whatwg.org/C/webappapis.html#pause
virtual bool IsPaused() const = 0;
- // Returns the deferred status of the loading in the global context.
- virtual WebURLLoader::DeferType DeferType() const = 0;
+ // Returns the freezing mode set to this context.
+ virtual LoaderFreezeMode FreezeMode() const = 0;
// Returns whether this global context is detached. Note that in some cases
// the loading pipeline continues working after detached (e.g., for fetch()
// operations with "keepalive" specified).
virtual bool IsDetached() const = 0;
- // Returns whether the loading is deferred. When true, loading tasks keep
- // running but the data is queued in the loading pipeline on the renderer.
- // Upon resume the data is given to client modules such as scripts.
- virtual bool IsLoadDeferred() const = 0;
-
// Returns whether the main resource for this global context is loaded.
virtual bool IsLoadComplete() const = 0;
@@ -98,6 +95,11 @@ class PLATFORM_EXPORT ResourceFetcherProperties
virtual const KURL& WebBundlePhysicalUrl() const = 0;
virtual int GetOutstandingThrottledLimit() const = 0;
+
+ // Returns the LitePage origin the subresources such as images should be
+ // redirected to when the kSubresourceRedirect feature is enabled.
+ virtual scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin()
+ const = 0;
};
// A delegating ResourceFetcherProperties subclass which can be retained
@@ -137,15 +139,12 @@ class PLATFORM_EXPORT DetachableResourceFetcherProperties final
bool IsPaused() const override {
return properties_ ? properties_->IsPaused() : paused_;
}
- WebURLLoader::DeferType DeferType() const override {
- return properties_ ? properties_->DeferType() : defer_type_;
+ LoaderFreezeMode FreezeMode() const override {
+ return properties_ ? properties_->FreezeMode() : freeze_mode_;
}
bool IsDetached() const override {
return properties_ ? properties_->IsDetached() : true;
}
- bool IsLoadDeferred() const override {
- return properties_ ? properties_->IsLoadDeferred() : false;
- }
bool IsLoadComplete() const override {
return properties_ ? properties_->IsLoadComplete() : load_complete_;
}
@@ -172,6 +171,12 @@ class PLATFORM_EXPORT DetachableResourceFetcherProperties final
: outstanding_throttled_limit_;
}
+ scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin()
+ const override {
+ return properties_ ? properties_->GetLitePageSubresourceRedirectOrigin()
+ : litepage_subresource_redirect_origin_;
+ }
+
private:
// |properties_| is null if and only if detached.
Member<const ResourceFetcherProperties> properties_;
@@ -180,11 +185,12 @@ class PLATFORM_EXPORT DetachableResourceFetcherProperties final
Member<const FetchClientSettingsObject> fetch_client_settings_object_;
bool is_main_frame_ = false;
bool paused_ = false;
- WebURLLoader::DeferType defer_type_;
+ LoaderFreezeMode freeze_mode_;
bool load_complete_ = false;
bool is_subframe_deprioritization_enabled_ = false;
KURL web_bundle_physical_url_;
int outstanding_throttled_limit_ = 0;
+ scoped_refptr<SecurityOrigin> litepage_subresource_redirect_origin_;
};
} // namespace blink
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 e04b4fa1bc2..34d02891813 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
@@ -120,6 +120,8 @@ class PartialResourceRequest {
class ResourceFetcherTest : public testing::Test {
public:
ResourceFetcherTest() = default;
+ ResourceFetcherTest(const ResourceFetcherTest&) = delete;
+ ResourceFetcherTest& operator=(const ResourceFetcherTest&) = delete;
~ResourceFetcherTest() override { GetMemoryCache()->EvictResources(); }
class TestResourceLoadObserver final : public ResourceLoadObserver {
@@ -156,6 +158,9 @@ class ResourceFetcherTest : public testing::Test {
const ResourceError&,
int64_t encoded_data_length,
IsInternalRequest is_internal_request) override {}
+ void DidChangeRenderBlockingBehavior(
+ Resource* resource,
+ const FetchParameters& params) override {}
const absl::optional<PartialResourceRequest>& GetLastRequest() const {
return request_;
}
@@ -202,9 +207,6 @@ class ResourceFetcherTest : public testing::Test {
}
ScopedTestingPlatformSupport<FetchTestingPlatformSupport> platform_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ResourceFetcherTest);
};
TEST_F(ResourceFetcherTest, StartLoadAfterFrameDetach) {
@@ -796,6 +798,9 @@ class ScopedMockRedirectRequester {
: mock_factory_(mock_factory),
context_(context),
task_runner_(std::move(task_runner)) {}
+ ScopedMockRedirectRequester(const ScopedMockRedirectRequester&) = delete;
+ ScopedMockRedirectRequester& operator=(const ScopedMockRedirectRequester&) =
+ delete;
void RegisterRedirect(const WebString& from_url, const WebString& to_url) {
KURL redirect_url(from_url);
@@ -835,8 +840,6 @@ class ScopedMockRedirectRequester {
WebURLLoaderMockFactory* mock_factory_;
MockFetchContext* context_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedMockRedirectRequester);
};
TEST_F(ResourceFetcherTest, SynchronousRequest) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_info.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_info.h
deleted file mode 100644
index 2e50e2a5d2c..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_info.h
+++ /dev/null
@@ -1,47 +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.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_INFO_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_INFO_H_
-
-#include "third_party/blink/renderer/platform/network/http_header_map.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-
-namespace blink {
-
-struct ResourceLoadInfo : RefCounted<ResourceLoadInfo> {
- ResourceLoadInfo() : http_status_code(0) {}
-
- int http_status_code;
- String http_status_text;
- HTTPHeaderMap request_headers;
- HTTPHeaderMap response_headers;
- String request_headers_text;
- String response_headers_text;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_INFO_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
index 659f85ac753..56bbcca91a0 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
@@ -96,6 +96,11 @@ class PLATFORM_EXPORT ResourceLoadObserver
int64_t encoded_data_length,
IsInternalRequest) = 0;
+ // Called when the RenderBlockingBehavior given to WillSendRequest changes.
+ virtual void DidChangeRenderBlockingBehavior(
+ Resource* resource,
+ const FetchParameters& params) = 0;
+
virtual void Trace(Visitor*) const {}
};
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 c8c881f44d5..1f372a879d7 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
@@ -203,11 +203,6 @@ bool ResourceLoadScheduler::Release(
auto running_request = running_requests_.find(id);
if (running_request != running_requests_.end()) {
- if (running_request->value >= PriorityImportanceThreshold()) {
- in_flight_important_requests_--;
- DCHECK_GE(in_flight_important_requests_, 0);
- }
-
running_requests_.erase(id);
running_throttleable_requests_.erase(id);
@@ -320,16 +315,12 @@ bool ResourceLoadScheduler::GetNextPendingRequest(ClientId* id) {
// corresponding |pending_queue_update_times_|.
if (use_stoppable) {
*id = stoppable_it->client_id;
- if (ShouldDelay(pending_request_map_.find(*id)))
- return false;
stoppable_queue.erase(stoppable_it);
pending_queue_update_times_[ThrottleOption::kStoppable] = clock_->Now();
return true;
}
*id = throttleable_it->client_id;
- if (ShouldDelay(pending_request_map_.find(*id)))
- return false;
throttleable_queue.erase(throttleable_it);
pending_queue_update_times_[ThrottleOption::kThrottleable] = clock_->Now();
return true;
@@ -355,44 +346,10 @@ void ResourceLoadScheduler::MaybeRun() {
}
}
-void ResourceLoadScheduler::MarkFirstPaint() {
- if (!base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests) ||
- delay_milestone_reached_) {
- return;
- }
-
- if (ComputeDelayMilestone() ==
- mojom::blink::DelayCompetingLowPriorityRequestsDelayType::kFirstPaint) {
- DCHECK(!delay_milestone_reached_);
- delay_milestone_reached_ = true;
- MaybeRun();
- }
-}
-
-void ResourceLoadScheduler::MarkFirstContentfulPaint() {
- if (!base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests) ||
- delay_milestone_reached_) {
- return;
- }
-
- if (ComputeDelayMilestone() ==
- mojom::blink::DelayCompetingLowPriorityRequestsDelayType::
- kFirstContentfulPaint) {
- DCHECK(!delay_milestone_reached_);
- delay_milestone_reached_ = true;
- MaybeRun();
- }
-}
-
void ResourceLoadScheduler::Run(ResourceLoadScheduler::ClientId id,
ResourceLoadSchedulerClient* client,
bool throttleable,
ResourceLoadPriority priority) {
- if (priority >= PriorityImportanceThreshold()) {
- in_flight_important_requests_++;
- }
running_requests_.insert(id, priority);
if (throttleable)
running_throttleable_requests_.insert(id);
@@ -433,14 +390,10 @@ void ResourceLoadScheduler::ShowConsoleMessageIfNeeded() {
return;
const base::Time limit = clock_->Now() - base::TimeDelta::FromSeconds(60);
- ThrottleOption target_option;
- if (pending_queue_update_times_[ThrottleOption::kThrottleable] < limit &&
- !IsPendingRequestEffectivelyEmpty(ThrottleOption::kThrottleable)) {
- target_option = ThrottleOption::kThrottleable;
- } else if (pending_queue_update_times_[ThrottleOption::kStoppable] < limit &&
- !IsPendingRequestEffectivelyEmpty(ThrottleOption::kStoppable)) {
- target_option = ThrottleOption::kStoppable;
- } else {
+ if ((pending_queue_update_times_[ThrottleOption::kThrottleable] >= limit ||
+ IsPendingRequestEffectivelyEmpty(ThrottleOption::kThrottleable)) &&
+ (pending_queue_update_times_[ThrottleOption::kStoppable] >= limit ||
+ IsPendingRequestEffectivelyEmpty(ThrottleOption::kStoppable))) {
// At least, one of the top requests in pending queues was handled in the
// last 1 minutes, or there is no pending requests in the inactive queue.
return;
@@ -459,135 +412,4 @@ void ResourceLoadScheduler::SetClockForTesting(const base::Clock* clock) {
clock_ = clock;
}
-bool ResourceLoadScheduler::ShouldDelay(
- PendingRequestMap::iterator found) const {
- if (!base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests)) {
- return false;
- }
-
- // The milestone already passed. We no longer have to delay requests.
- if (delay_milestone_reached_)
- return false;
-
- // There are no inflight important requests. We don't have to delay the
- // pending request even if it has low priority.
- if (in_flight_important_requests_ == 0)
- return false;
-
- // Hidden pages already have requests throttled/deprioritized, and delaying
- // further can have undesirable effects on sites, and there's little benefit
- // to try to optimize them using this feature.
- if (frame_scheduler_lifecycle_state_ ==
- scheduler::SchedulingLifecycleState::kHidden) {
- return false;
- }
-
- // We didn't find the pending request for the id.
- if (found == pending_request_map_.end())
- return false;
-
- // The pending request is not in low priority.
- if (found->value->priority > ResourceLoadPriority::kLow)
- return false;
-
- if (features::kDelayCompetingLowPriorityRequestsDelayParam.Get() ==
- features::DelayCompetingLowPriorityRequestsDelayType::
- kUseOptimizationGuide) {
- // The optimization guide is supposed to be used, but the hints are not
- // available. Give up delaying requests.
- if (!optimization_hints_)
- return false;
- // The optimization guide suggests the default behavior (no delay).
- if (optimization_hints_->delay_type ==
- mojom::blink::DelayCompetingLowPriorityRequestsDelayType::kUnknown) {
- return false;
- }
- }
-
- // We get a chance to delay competing low priority requests. Record the fact
- // in UKM to measure the application ratio of the optimization.
- if (loading_behavior_observer_) {
- loading_behavior_observer_->DidObserveLoadingBehavior(
- kLoadingBehaviorCompetingLowPriorityRequestsDelayed);
- }
-
- return true;
-}
-
-ResourceLoadPriority ResourceLoadScheduler::PriorityImportanceThreshold() {
- // The default value defined by the field trial.
- DCHECK_EQ(
- features::DelayCompetingLowPriorityRequestsThreshold::kHigh,
- features::kDelayCompetingLowPriorityRequestsThresholdParam.default_value);
- const auto default_value = ResourceLoadPriority::kHigh;
-
- using FeatureDelayType = features::DelayCompetingLowPriorityRequestsDelayType;
- using FeaturePriorityThreshold =
- features::DelayCompetingLowPriorityRequestsThreshold;
- using MojomPriorityThreshold =
- mojom::blink::DelayCompetingLowPriorityRequestsPriorityThreshold;
-
- switch (features::kDelayCompetingLowPriorityRequestsDelayParam.Get()) {
- // Use parameters provided by the field trial.
- case FeatureDelayType::kFirstPaint:
- case FeatureDelayType::kFirstContentfulPaint:
- case FeatureDelayType::kAlways:
- switch (
- features::kDelayCompetingLowPriorityRequestsThresholdParam.Get()) {
- case FeaturePriorityThreshold::kHigh:
- return ResourceLoadPriority::kHigh;
- case FeaturePriorityThreshold::kMedium:
- return ResourceLoadPriority::kMedium;
- }
- NOTREACHED();
- // Use hints provided by the optimization guide.
- case FeatureDelayType::kUseOptimizationGuide:
- if (!optimization_hints_) {
- // The optimization guide service didn't provide the hints. Fallback to
- // the default value.
- return default_value;
- }
- switch (optimization_hints_->priority_threshold) {
- case MojomPriorityThreshold::kHigh:
- return ResourceLoadPriority::kHigh;
- case MojomPriorityThreshold::kMedium:
- return ResourceLoadPriority::kMedium;
- case MojomPriorityThreshold::kUnknown:
- // The optimization guide didn't decide the priority threshold.
- // Fallback to the default value.
- return default_value;
- }
- NOTREACHED();
- }
-}
-
-mojom::blink::DelayCompetingLowPriorityRequestsDelayType
-ResourceLoadScheduler::ComputeDelayMilestone() {
- DCHECK(base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests));
-
- using FeatureDelayType = features::DelayCompetingLowPriorityRequestsDelayType;
- using MojomDelayType =
- mojom::blink::DelayCompetingLowPriorityRequestsDelayType;
-
- switch (features::kDelayCompetingLowPriorityRequestsDelayParam.Get()) {
- // Use parameters provided by the field trial.
- case FeatureDelayType::kFirstPaint:
- return MojomDelayType::kFirstPaint;
- case FeatureDelayType::kFirstContentfulPaint:
- return MojomDelayType::kFirstContentfulPaint;
- case FeatureDelayType::kAlways:
- return MojomDelayType::kUnknown;
-
- // Use hints provided by the optimization guide.
- case FeatureDelayType::kUseOptimizationGuide:
- // Give up delaying requests when the optimization guide is enabled but
- // the hints are not available. See ShouldDelay().
- if (!optimization_hints_)
- return MojomDelayType::kUnknown;
- return optimization_hints_->delay_type;
- }
-}
-
} // 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 d33014737dd..d99083773d0 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
@@ -9,7 +9,6 @@
#include <set>
#include "base/time/time.h"
-#include "third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom-blink.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/loader/fetch/resource.h"
@@ -176,6 +175,8 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
FrameOrWorkerScheduler*,
DetachableConsoleLogger& console_logger,
LoadingBehaviorObserver* loading_behavior_observer);
+ ResourceLoadScheduler(const ResourceLoadScheduler&) = delete;
+ ResourceLoadScheduler& operator=(const ResourceLoadScheduler&) = delete;
~ResourceLoadScheduler() override;
void Trace(Visitor*) const;
@@ -233,16 +234,6 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
throttle_option_override_ = throttle_option_override;
}
- void SetOptimizationGuideHints(
- mojom::blink::DelayCompetingLowPriorityRequestsHintsPtr
- optimization_hints) {
- optimization_hints_ = std::move(optimization_hints);
- }
-
- // Indicates that some loading milestones have been reached.
- void MarkFirstPaint();
- void MarkFirstContentfulPaint();
-
private:
class ClientIdWithPriority {
public:
@@ -320,17 +311,6 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
void ShowConsoleMessageIfNeeded();
- // Returns the threshold for which a request is considered "important" based
- // on the field trial parameter or the optimization guide hints. This is used
- // for the experiment on delaying competing low priority requests.
- // See https://crbug.com/1112515 for details.
- ResourceLoadPriority PriorityImportanceThreshold();
-
- // Compute the milestone at which competing low priority requests can be
- // delayed until. Returns kUnknown when it's not possible to compute it.
- mojom::blink::DelayCompetingLowPriorityRequestsDelayType
- ComputeDelayMilestone();
-
const Member<const DetachableResourceFetcherProperties>
resource_fetcher_properties_;
@@ -387,20 +367,9 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
const base::Clock* clock_;
- int in_flight_important_requests_ = 0;
- // When this is true, the scheduler no longer needs to delay low-priority
- // resources. |ShouldDelay()| will always return false after this point.
- bool delay_milestone_reached_ = false;
-
ThrottleOptionOverride throttle_option_override_;
Member<LoadingBehaviorObserver> loading_behavior_observer_;
-
- // Hints for the DelayCompetingLowPriorityRequests optimization. See
- // https://crbug.com/1112515 for details.
- mojom::blink::DelayCompetingLowPriorityRequestsHintsPtr optimization_hints_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceLoadScheduler);
};
} // namespace blink
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 34a2cee7725..6f7f9e8638f 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
@@ -83,7 +83,7 @@ class LoadingBehaviorObserverImpl final
int32_t loading_behavior_flag_ = 0;
};
-class ResourceLoadSchedulerTestBase : public testing::Test {
+class ResourceLoadSchedulerTest : public testing::Test {
public:
class MockConsoleLogger final : public GarbageCollected<MockConsoleLogger>,
public ConsoleLogger {
@@ -114,7 +114,6 @@ class ResourceLoadSchedulerTestBase : public testing::Test {
properties->MakeDetachable(), frame_scheduler.get(),
*MakeGarbageCollected<DetachableConsoleLogger>(console_logger_),
loading_observer_behavior_.Get());
- scheduler_->SetOptimizationGuideHints(std::move(optimization_hints_));
Scheduler()->SetOutstandingLimitForTesting(1);
}
void TearDown() override { Scheduler()->Shutdown(); }
@@ -133,55 +132,14 @@ class ResourceLoadSchedulerTestBase : public testing::Test {
ResourceLoadScheduler::TrafficReportHints::InvalidInstance());
}
- bool WasDelayCompetingLowPriorityRequestsObserved() {
- return loading_observer_behavior_->loading_behavior_flag() &
- kLoadingBehaviorCompetingLowPriorityRequestsDelayed;
- }
-
protected:
base::test::ScopedFeatureList feature_list_;
Persistent<MockConsoleLogger> console_logger_;
Persistent<LoadingBehaviorObserverImpl> loading_observer_behavior_;
Persistent<ResourceLoadScheduler> scheduler_;
- mojom::blink::DelayCompetingLowPriorityRequestsHintsPtr optimization_hints_;
};
-class ResourceLoadSchedulerTest
- : public ResourceLoadSchedulerTestBase,
- public testing::WithParamInterface<
- std::tuple<base::test::ScopedFeatureList::FeatureAndParams, bool>> {
- public:
- void SetUp() override {
- std::vector<base::test::ScopedFeatureList::FeatureAndParams>
- features_with_params;
- std::vector<base::Feature> disabled_features;
-
- bool enabled = std::get<1>(GetParam());
- if (enabled) {
- features_with_params.push_back(std::get<0>(GetParam()));
- } else {
- disabled_features.push_back(std::get<0>(GetParam()).feature);
- }
-
- feature_list_.InitWithFeaturesAndParameters(features_with_params,
- disabled_features);
- ResourceLoadSchedulerTestBase::SetUp();
- }
-};
-
-INSTANTIATE_TEST_SUITE_P(
- All,
- ResourceLoadSchedulerTest,
- testing::Combine(
- // A list of FeatureAndParams structs representing a single feature and
- // an arbitrary number of parameters.
- testing::Values(base::test::ScopedFeatureList::FeatureAndParams(
- features::kDelayCompetingLowPriorityRequests,
- {{"delay_type", "always"}})),
- // A boolean indicating whether or not the feature is enabled.
- testing::Bool()));
-
-TEST_P(ResourceLoadSchedulerTest, StopStoppableRequest) {
+TEST_F(ResourceLoadSchedulerTest, StopStoppableRequest) {
Scheduler()->OnLifecycleStateChanged(
scheduler::SchedulingLifecycleState::kStopped);
// A request that disallows throttling should be queued.
@@ -227,7 +185,7 @@ TEST_P(ResourceLoadSchedulerTest, StopStoppableRequest) {
EXPECT_FALSE(Release(static_cast<ResourceLoadScheduler::ClientId>(774)));
}
-TEST_P(ResourceLoadSchedulerTest, ThrottleThrottleableRequest) {
+TEST_F(ResourceLoadSchedulerTest, ThrottleThrottleableRequest) {
Scheduler()->OnLifecycleStateChanged(
scheduler::SchedulingLifecycleState::kThrottled);
@@ -275,7 +233,7 @@ TEST_P(ResourceLoadSchedulerTest, ThrottleThrottleableRequest) {
EXPECT_FALSE(Release(static_cast<ResourceLoadScheduler::ClientId>(774)));
}
-TEST_P(ResourceLoadSchedulerTest, Throttled) {
+TEST_F(ResourceLoadSchedulerTest, Throttled) {
// The first request should be ran synchronously.
MockClient* client1 = MakeGarbageCollected<MockClient>();
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
@@ -327,7 +285,7 @@ TEST_P(ResourceLoadSchedulerTest, Throttled) {
EXPECT_TRUE(client4->WasRun());
}
-TEST_P(ResourceLoadSchedulerTest, Unthrottle) {
+TEST_F(ResourceLoadSchedulerTest, Unthrottle) {
// Push three requests.
MockClient* client1 = MakeGarbageCollected<MockClient>();
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
@@ -364,7 +322,7 @@ TEST_P(ResourceLoadSchedulerTest, Unthrottle) {
EXPECT_TRUE(Release(id1));
}
-TEST_P(ResourceLoadSchedulerTest, Stopped) {
+TEST_F(ResourceLoadSchedulerTest, Stopped) {
// Push three requests.
MockClient* client1 = MakeGarbageCollected<MockClient>();
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
@@ -406,7 +364,7 @@ TEST_P(ResourceLoadSchedulerTest, Stopped) {
EXPECT_TRUE(Release(id2));
}
-TEST_P(ResourceLoadSchedulerTest, PriorityIsConsidered) {
+TEST_F(ResourceLoadSchedulerTest, PriorityIsConsidered) {
// Push three requests.
MockClient* client1 = MakeGarbageCollected<MockClient>();
@@ -445,59 +403,26 @@ TEST_P(ResourceLoadSchedulerTest, PriorityIsConsidered) {
EXPECT_FALSE(client3->WasRun());
EXPECT_TRUE(client4->WasRun());
- if (base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests)) {
- // Allows two requests (regardless of priority). No other clients are run,
- // because the kHigh request is considered running / in-flight, so the kLow
- // priority request should be delayed behind it as per this feature.
- Scheduler()->SetOutstandingLimitForTesting(2);
-
- EXPECT_FALSE(client1->WasRun());
- EXPECT_FALSE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
-
- // ResourceLoadPriority::kLow requests will not run until client4 is
- // released.
- EXPECT_TRUE(ReleaseAndSchedule(id4));
-
- 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_TRUE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
-
- EXPECT_TRUE(WasDelayCompetingLowPriorityRequestsObserved());
- } else {
- Scheduler()->SetOutstandingLimitForTesting(2);
+ Scheduler()->SetOutstandingLimitForTesting(2);
- EXPECT_FALSE(client1->WasRun());
- EXPECT_FALSE(client2->WasRun());
- EXPECT_TRUE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
-
- Scheduler()->SetOutstandingLimitForTesting(3);
+ EXPECT_FALSE(client1->WasRun());
+ EXPECT_FALSE(client2->WasRun());
+ EXPECT_TRUE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
- EXPECT_FALSE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
- EXPECT_TRUE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
+ Scheduler()->SetOutstandingLimitForTesting(3);
- Scheduler()->SetOutstandingLimitForTesting(4);
+ EXPECT_FALSE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+ EXPECT_TRUE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
- EXPECT_TRUE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
- EXPECT_TRUE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
+ Scheduler()->SetOutstandingLimitForTesting(4);
- EXPECT_FALSE(WasDelayCompetingLowPriorityRequestsObserved());
- }
+ EXPECT_TRUE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+ EXPECT_TRUE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
// Release the rest.
EXPECT_TRUE(Release(id3));
@@ -505,7 +430,7 @@ TEST_P(ResourceLoadSchedulerTest, PriorityIsConsidered) {
EXPECT_TRUE(Release(id1));
}
-TEST_P(ResourceLoadSchedulerTest, AllowedRequestsRunInPriorityOrder) {
+TEST_F(ResourceLoadSchedulerTest, AllowedRequestsRunInPriorityOrder) {
Scheduler()->OnLifecycleStateChanged(
scheduler::SchedulingLifecycleState::kStopped);
Scheduler()->SetOutstandingLimitForTesting(0);
@@ -538,28 +463,12 @@ TEST_P(ResourceLoadSchedulerTest, AllowedRequestsRunInPriorityOrder) {
Scheduler()->OnLifecycleStateChanged(
scheduler::SchedulingLifecycleState::kThrottled);
- if (base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests)) {
- EXPECT_FALSE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
-
- EXPECT_TRUE(ReleaseAndSchedule(id2));
- EXPECT_TRUE(client1->WasRun());
-
- // Finish releasing all.
- EXPECT_TRUE(Release(id1));
-
- EXPECT_TRUE(WasDelayCompetingLowPriorityRequestsObserved());
- } else {
- EXPECT_TRUE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
-
- // Release all.
- EXPECT_TRUE(Release(id1));
- EXPECT_TRUE(Release(id2));
+ EXPECT_TRUE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
- EXPECT_FALSE(WasDelayCompetingLowPriorityRequestsObserved());
- }
+ // Release all.
+ EXPECT_TRUE(Release(id1));
+ EXPECT_TRUE(Release(id2));
// Verify high priority request ran first.
auto& order = delegate.client_order();
@@ -567,7 +476,7 @@ TEST_P(ResourceLoadSchedulerTest, AllowedRequestsRunInPriorityOrder) {
EXPECT_EQ(order[1], client1);
}
-TEST_P(ResourceLoadSchedulerTest, StoppableRequestResumesWhenThrottled) {
+TEST_F(ResourceLoadSchedulerTest, StoppableRequestResumesWhenThrottled) {
Scheduler()->OnLifecycleStateChanged(
scheduler::SchedulingLifecycleState::kStopped);
// Push two requests.
@@ -618,7 +527,7 @@ TEST_P(ResourceLoadSchedulerTest, StoppableRequestResumesWhenThrottled) {
EXPECT_TRUE(Release(id3));
}
-TEST_P(ResourceLoadSchedulerTest, SetPriority) {
+TEST_F(ResourceLoadSchedulerTest, SetPriority) {
// Push three requests.
MockClient* client1 = MakeGarbageCollected<MockClient>();
@@ -661,66 +570,30 @@ TEST_P(ResourceLoadSchedulerTest, SetPriority) {
EXPECT_FALSE(client2->WasRun());
EXPECT_FALSE(client3->WasRun());
- if (base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests)) {
- // Loosen the policy to adopt the normal limit for all. One request
- // regardless of priority can be granted.
- Scheduler()->LoosenThrottlingPolicy();
-
- // The kLow requests are still delayed behind the in-flight kHigh one, since
- // it hasn't been released yet.
- EXPECT_TRUE(client1->WasRun());
- EXPECT_FALSE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
-
- // Releasing the in-flight high priority request makes room for the next two
- // low priority requests to be granted, since the limit is two, and low
- // priority.
- EXPECT_TRUE(ReleaseAndSchedule(id1));
- EXPECT_TRUE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
-
- // kHigh priority does not help the third request here.
- Scheduler()->SetPriority(id3, ResourceLoadPriority::kHigh, 0);
-
- EXPECT_TRUE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
-
- // Release remaining clients.
- EXPECT_TRUE(Release(id3));
- EXPECT_TRUE(Release(id2));
-
- EXPECT_FALSE(WasDelayCompetingLowPriorityRequestsObserved());
- } else {
- // Loosen the policy to adopt the normal limit for all. Two requests
- // regardless of priority can be granted (including the in-flight high
- // priority request).
- Scheduler()->LoosenThrottlingPolicy();
- Scheduler()->SetOutstandingLimitForTesting(0, 2);
-
- EXPECT_TRUE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
-
- // kHigh priority does not help the third request here.
- Scheduler()->SetPriority(id3, ResourceLoadPriority::kHigh, 0);
-
- EXPECT_TRUE(client1->WasRun());
- EXPECT_TRUE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
-
- // Release all.
- EXPECT_TRUE(Release(id3));
- EXPECT_TRUE(Release(id2));
- EXPECT_TRUE(Release(id1));
-
- EXPECT_FALSE(WasDelayCompetingLowPriorityRequestsObserved());
- }
+ // Loosen the policy to adopt the normal limit for all. Two requests
+ // regardless of priority can be granted (including the in-flight high
+ // priority request).
+ Scheduler()->LoosenThrottlingPolicy();
+ Scheduler()->SetOutstandingLimitForTesting(0, 2);
+
+ EXPECT_TRUE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+ EXPECT_FALSE(client3->WasRun());
+
+ // kHigh priority does not help the third request here.
+ Scheduler()->SetPriority(id3, ResourceLoadPriority::kHigh, 0);
+
+ EXPECT_TRUE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+ EXPECT_FALSE(client3->WasRun());
+
+ // Release all.
+ EXPECT_TRUE(Release(id3));
+ EXPECT_TRUE(Release(id2));
+ EXPECT_TRUE(Release(id1));
}
-TEST_P(ResourceLoadSchedulerTest, LoosenThrottlingPolicy) {
+TEST_F(ResourceLoadSchedulerTest, LoosenThrottlingPolicy) {
MockClient* client1 = MakeGarbageCollected<MockClient>();
Scheduler()->SetOutstandingLimitForTesting(0, 0);
@@ -796,7 +669,7 @@ TEST_P(ResourceLoadSchedulerTest, LoosenThrottlingPolicy) {
EXPECT_TRUE(Release(id1));
}
-TEST_P(ResourceLoadSchedulerTest, ConsoleMessage) {
+TEST_F(ResourceLoadSchedulerTest, ConsoleMessage) {
auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
Scheduler()->SetClockForTesting(test_task_runner->GetMockClock());
Scheduler()->SetOutstandingLimitForTesting(0, 0);
@@ -841,248 +714,5 @@ TEST_P(ResourceLoadSchedulerTest, ConsoleMessage) {
EXPECT_TRUE(Release(id2));
}
-mojom::blink::DelayCompetingLowPriorityRequestsHintsPtr
-CreateOptimizationGuideHints(
- features::DelayCompetingLowPriorityRequestsDelayType delay_milestone,
- features::DelayCompetingLowPriorityRequestsThreshold priority_threshold) {
- auto optimization_hints =
- mojom::blink::DelayCompetingLowPriorityRequestsHints::New();
-
- switch (delay_milestone) {
- case features::DelayCompetingLowPriorityRequestsDelayType::kFirstPaint:
- optimization_hints->delay_type =
- mojom::blink::DelayCompetingLowPriorityRequestsDelayType::kFirstPaint;
- break;
- case features::DelayCompetingLowPriorityRequestsDelayType::
- kFirstContentfulPaint:
- optimization_hints->delay_type = mojom::blink::
- DelayCompetingLowPriorityRequestsDelayType::kFirstContentfulPaint;
- break;
- default:
- NOTREACHED();
- break;
- }
-
- switch (priority_threshold) {
- case features::DelayCompetingLowPriorityRequestsThreshold::kMedium:
- optimization_hints->priority_threshold = mojom::blink::
- DelayCompetingLowPriorityRequestsPriorityThreshold::kMedium;
- break;
- case features::DelayCompetingLowPriorityRequestsThreshold::kHigh:
- optimization_hints->priority_threshold = mojom::blink::
- DelayCompetingLowPriorityRequestsPriorityThreshold::kHigh;
- break;
- }
-
- return optimization_hints;
-}
-
-class ResourceLoadSchedulerTestDelayCompetingLowPriorityRequests
- : public ResourceLoadSchedulerTestBase,
- public testing::WithParamInterface<
- std::tuple<bool /* use_optimization_guide */,
- features::DelayCompetingLowPriorityRequestsDelayType,
- features::DelayCompetingLowPriorityRequestsThreshold>> {
- public:
- void SetUp() override {
- std::map<std::string, std::string> parameters;
- bool use_optimization_guide = std::get<0>(GetParam());
- until_ = std::get<1>(GetParam());
- priority_threshold_ = std::get<2>(GetParam());
-
- if (use_optimization_guide) {
- parameters[features::kDelayCompetingLowPriorityRequestsDelayParam.name] =
- "use_optimization_guide";
- optimization_hints_ =
- CreateOptimizationGuideHints(until_, priority_threshold_);
- } else {
- switch (until_) {
- case features::DelayCompetingLowPriorityRequestsDelayType::kFirstPaint:
- parameters[features::kDelayCompetingLowPriorityRequestsDelayParam
- .name] = "first_paint";
- break;
- case features::DelayCompetingLowPriorityRequestsDelayType::
- kFirstContentfulPaint:
- parameters[features::kDelayCompetingLowPriorityRequestsDelayParam
- .name] = "first_contentful_paint";
- break;
- default:
- NOTREACHED();
- break;
- }
- switch (priority_threshold_) {
- case features::DelayCompetingLowPriorityRequestsThreshold::kMedium:
- parameters[features::kDelayCompetingLowPriorityRequestsThresholdParam
- .name] = "medium";
- break;
- case features::DelayCompetingLowPriorityRequestsThreshold::kHigh:
- parameters[features::kDelayCompetingLowPriorityRequestsThresholdParam
- .name] = "high";
- break;
- }
- }
-
- feature_list_.InitWithFeaturesAndParameters(
- {{features::kDelayCompetingLowPriorityRequests, parameters}}, {});
- ASSERT_TRUE(base::FeatureList::IsEnabled(
- features::kDelayCompetingLowPriorityRequests));
- if (use_optimization_guide) {
- ASSERT_EQ(features::kDelayCompetingLowPriorityRequestsDelayParam.Get(),
- features::DelayCompetingLowPriorityRequestsDelayType::
- kUseOptimizationGuide);
- ASSERT_EQ(
- features::kDelayCompetingLowPriorityRequestsThresholdParam.Get(),
- features::kDelayCompetingLowPriorityRequestsThresholdParam
- .default_value);
- } else {
- ASSERT_EQ(features::kDelayCompetingLowPriorityRequestsDelayParam.Get(),
- until_);
- ASSERT_EQ(
- features::kDelayCompetingLowPriorityRequestsThresholdParam.Get(),
- priority_threshold_);
- }
- ResourceLoadSchedulerTestBase::SetUp();
- }
-
- // Returns a ResourceLoadPriority value (either kHigh, or kMedium)
- // corresponding with the priority threshold field trial parameter.
- ResourceLoadPriority ImportantPriority() {
- if (priority_threshold_ ==
- features::DelayCompetingLowPriorityRequestsThreshold::kMedium) {
- return ResourceLoadPriority::kMedium;
- }
-
- if (priority_threshold_ ==
- features::DelayCompetingLowPriorityRequestsThreshold::kHigh) {
- return ResourceLoadPriority::kHigh;
- }
-
- NOTREACHED();
- return ResourceLoadPriority::kUnresolved;
- }
-
- protected:
- features::DelayCompetingLowPriorityRequestsDelayType until_;
- features::DelayCompetingLowPriorityRequestsThreshold priority_threshold_;
-};
-
-INSTANTIATE_TEST_SUITE_P(
- All,
- ResourceLoadSchedulerTestDelayCompetingLowPriorityRequests,
- testing::Combine(
- // True when use optimization guide:
- testing::Bool(),
- // Delay type parameter:
- testing::Values(
- features::DelayCompetingLowPriorityRequestsDelayType::kFirstPaint,
- features::DelayCompetingLowPriorityRequestsDelayType::
- kFirstContentfulPaint),
- // Priority threshold parameter:
- testing::Values(
- features::DelayCompetingLowPriorityRequestsThreshold::kMedium,
- features::DelayCompetingLowPriorityRequestsThreshold::kHigh)));
-
-TEST_P(ResourceLoadSchedulerTestDelayCompetingLowPriorityRequests,
- DelayRequests) {
- ResourceLoadPriority important = ImportantPriority();
-
- // No throttling, so we can test the delay logic in an unobstructed way.
- Scheduler()->OnLifecycleStateChanged(
- scheduler::SchedulingLifecycleState::kNotThrottled);
- Scheduler()->SetOutstandingLimitForTesting(
- ResourceLoadScheduler::kOutstandingUnlimited);
-
- MockClient* important_client1 = MakeGarbageCollected<MockClient>();
- ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(important_client1, ThrottleOption::kThrottleable,
- important, 0 /* intra_priority */, &id1);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
- EXPECT_TRUE(important_client1->WasRun());
-
- MockClient* important_client2 = MakeGarbageCollected<MockClient>();
- ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(important_client2, ThrottleOption::kThrottleable,
- important, 0 /* intra_priority */, &id2);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
- EXPECT_TRUE(important_client2->WasRun());
-
- MockClient* low_client1 = MakeGarbageCollected<MockClient>();
- ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(low_client1, ThrottleOption::kThrottleable,
- ResourceLoadPriority::kLow, 0 /* intra_priority */,
- &id3);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
- EXPECT_FALSE(low_client1->WasRun());
-
- MockClient* low_client2 = MakeGarbageCollected<MockClient>();
- ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(low_client2, ThrottleOption::kThrottleable,
- ResourceLoadPriority::kLow, 0 /* intra_priority */,
- &id4);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
- EXPECT_FALSE(low_client2->WasRun());
-
- EXPECT_TRUE(ReleaseAndSchedule(id1));
-
- // Releasing one important request is not enough to grant the low priority
- // clients.
- EXPECT_FALSE(low_client1->WasRun());
- EXPECT_FALSE(low_client2->WasRun());
-
- // Triggering the loading milestone that we're not interested is not enough to
- // grant the low priority clients.
- if (until_ ==
- features::DelayCompetingLowPriorityRequestsDelayType::kFirstPaint) {
- Scheduler()->MarkFirstContentfulPaint();
- } else {
- Scheduler()->MarkFirstPaint();
- }
- EXPECT_FALSE(low_client1->WasRun());
- EXPECT_FALSE(low_client2->WasRun());
-
- // Triggering the loading milestone we are interested in *is* enough to grant
- // the low priority clients.
- Scheduler()->MarkFirstPaint();
- Scheduler()->MarkFirstContentfulPaint();
- EXPECT_TRUE(low_client1->WasRun());
- EXPECT_TRUE(low_client2->WasRun());
-
- EXPECT_TRUE(Release(id2));
- EXPECT_TRUE(Release(id3));
- EXPECT_TRUE(Release(id4));
-
- EXPECT_TRUE(WasDelayCompetingLowPriorityRequestsObserved());
-}
-
-// Tests that DelayCompetingLowPriorityRequests does not delay
-// requests for background pages.
-TEST_P(ResourceLoadSchedulerTestDelayCompetingLowPriorityRequests, Hidden) {
- ResourceLoadPriority important = ImportantPriority();
-
- // Set up hidden lifecycle state.
- Scheduler()->OnLifecycleStateChanged(
- scheduler::SchedulingLifecycleState::kHidden);
- Scheduler()->SetOutstandingLimitForTesting(
- ResourceLoadScheduler::kOutstandingUnlimited);
-
- // Make an important request.
- MockClient* important_client1 = MakeGarbageCollected<MockClient>();
- ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(important_client1, ThrottleOption::kThrottleable,
- important, 0 /* intra_priority */, &id1);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
-
- // Make a low-priority request.
- MockClient* low_client1 = MakeGarbageCollected<MockClient>();
- ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(low_client1, ThrottleOption::kThrottleable,
- ResourceLoadPriority::kLow, 0 /* intra_priority */,
- &id3);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
-
- // It should not have been delayed because the page is hidden.
- EXPECT_FALSE(WasDelayCompetingLowPriorityRequestsObserved());
-}
-
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
index 94af06e1f6e..c0e09a2db37 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "services/network/public/mojom/load_timing_info.mojom-blink.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -158,8 +157,6 @@ void ResourceLoadTiming::SetWorkerRespondWithSettled(
}
void ResourceLoadTiming::SetSendStart(base::TimeTicks send_start) {
- TRACE_EVENT_MARK_WITH_TIMESTAMP0("blink.user_timing", "requestStart",
- send_start);
send_start_ = send_start;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h
index 9d1c72ac4a1..66d459e1ef3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_TIMING_H_
#include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
#include "services/network/public/mojom/load_timing_info.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
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 a184223e52d..2645b04ae2f 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
@@ -65,7 +65,6 @@
#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/back_forward_cache_loader_helper.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
#include "third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
@@ -76,6 +75,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
#include "third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h"
#include "third_party/blink/renderer/platform/loader/mixed_content_autoupgrade_status.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
@@ -227,11 +227,14 @@ class ResourceLoader::CodeCacheRequest {
public:
CodeCacheRequest(std::unique_ptr<WebCodeCacheLoader> code_cache_loader,
const KURL& url,
- WebURLLoader::DeferType defers_loading)
+ LoaderFreezeMode freeze_mode)
: status_(kNoRequestSent),
code_cache_loader_(std::move(code_cache_loader)),
url_(url),
- defers_loading_(defers_loading) {
+ freeze_mode_(freeze_mode),
+ should_use_source_hash_(
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(
+ url.Protocol())) {
DCHECK(RuntimeEnabledFeatures::IsolatedCodeCacheEnabled());
}
@@ -240,7 +243,6 @@ class ResourceLoader::CodeCacheRequest {
// Request data from code cache.
bool FetchFromCodeCache(WebURLLoader* url_loader,
ResourceLoader* resource_loader);
- bool FetchFromCodeCacheSynchronously(ResourceLoader* resource_loader);
// Notifies about the response from webURLLoader. Stores the
// resource_response_time that is used to validate responses from
@@ -253,7 +255,7 @@ class ResourceLoader::CodeCacheRequest {
// once fetching from code cache is finished. Returns true if the
// request is handled here and hence need not be handled by the loader.
// Returns false otherwise.
- bool SetDefersLoading(WebURLLoader::DeferType defers);
+ bool SetDefersLoading(LoaderFreezeMode);
private:
enum CodeCacheRequestStatus {
@@ -281,12 +283,19 @@ class ResourceLoader::CodeCacheRequest {
CodeCacheRequestStatus status_;
std::unique_ptr<WebCodeCacheLoader> code_cache_loader_;
const WebURL url_;
- WebURLLoader::DeferType defers_loading_ =
- WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
mojo_base::BigBuffer cached_code_;
base::Time cached_code_response_time_;
base::Time resource_response_time_;
bool use_isolated_code_cache_ = false;
+ bool resource_response_arrived_ = false;
+
+ // Whether this response should use a hash of the source text to check
+ // whether a code cache entry is valid, rather than relying on response time.
+ // This could be computed as-needed based on url_, but doing so would require
+ // converting url_ from WebURL to KURL each time.
+ const bool should_use_source_hash_;
+
base::WeakPtrFactory<CodeCacheRequest> weak_ptr_factory_{this};
};
@@ -302,7 +311,7 @@ bool ResourceLoader::CodeCacheRequest::FetchFromCodeCache(
// ensure that the resource receives cached code before the response data.
// This directly calls the WebURLLoader's SetDefersLoading without going
// through ResourceLoader.
- url_loader->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ url_loader->Freeze(LoaderFreezeMode::kStrict);
WebCodeCacheLoader::FetchCodeCacheCallback callback = base::BindOnce(
&ResourceLoader::CodeCacheRequest::DidReceiveCachedCode,
@@ -312,27 +321,13 @@ bool ResourceLoader::CodeCacheRequest::FetchFromCodeCache(
return true;
}
-bool ResourceLoader::CodeCacheRequest::FetchFromCodeCacheSynchronously(
- ResourceLoader* resource_loader) {
- if (!code_cache_loader_)
- return false;
- DCHECK_EQ(status_, kNoRequestSent);
- status_ = kPendingResponse;
-
- base::Time response_time;
- mojo_base::BigBuffer data;
- code_cache_loader_->FetchFromCodeCacheSynchronously(url_, &response_time,
- &data);
- ProcessCodeCacheResponse(response_time, std::move(data), resource_loader);
- return true;
-}
-
// This is called when a response is received from the WebURLLoader. We buffer
// the response_time if the response from code cache is not available yet.
void ResourceLoader::CodeCacheRequest::DidReceiveResponse(
const base::Time& resource_response_time,
bool use_isolated_code_cache,
ResourceLoader* resource_loader) {
+ resource_response_arrived_ = true;
resource_response_time_ = resource_response_time;
use_isolated_code_cache_ = use_isolated_code_cache;
MaybeSendCachedCode(std::move(cached_code_), resource_loader);
@@ -340,12 +335,11 @@ void ResourceLoader::CodeCacheRequest::DidReceiveResponse(
// Returns true if |this| handles |defers| and therefore the callsite, i.e. the
// loader, doesn't need to take care of it). Returns false otherwise.
-bool ResourceLoader::CodeCacheRequest::SetDefersLoading(
- WebURLLoader::DeferType defers) {
- defers_loading_ = defers;
+bool ResourceLoader::CodeCacheRequest::SetDefersLoading(LoaderFreezeMode mode) {
+ freeze_mode_ = mode;
if (status_ == kPendingResponse) {
// The flag doesn't need to be handled by the loader. The value is stored
- // in |defers_loading_| and set once the response from the code cache is
+ // in |freeze_mode_| and set once the response from the code cache is
// received.
return true;
}
@@ -362,7 +356,7 @@ void ResourceLoader::CodeCacheRequest::DidReceiveCachedCode(
ProcessCodeCacheResponse(response_time, std::move(data), resource_loader);
// Reset the deferred value to its original state.
DCHECK(resource_loader);
- resource_loader->SetDefersLoading(defers_loading_);
+ resource_loader->SetDefersLoading(freeze_mode_);
}
// This is called when a response is received from code cache. If the
@@ -375,7 +369,7 @@ void ResourceLoader::CodeCacheRequest::ProcessCodeCacheResponse(
status_ = kReceivedResponse;
cached_code_response_time_ = response_time;
- if (resource_response_time_.is_null()) {
+ if (!resource_response_arrived_) {
// Wait for the response before we can send the cached code.
// TODO(crbug.com/866889): Pass this as a handle to avoid the overhead of
// copying this data.
@@ -389,24 +383,43 @@ void ResourceLoader::CodeCacheRequest::ProcessCodeCacheResponse(
void ResourceLoader::CodeCacheRequest::MaybeSendCachedCode(
mojo_base::BigBuffer data,
ResourceLoader* resource_loader) {
- if (status_ != kReceivedResponse || cached_code_response_time_.is_null() ||
- resource_response_time_.is_null()) {
+ // Wait until both responses have arrived; they can happen in either order.
+ if (status_ != kReceivedResponse || !resource_response_arrived_) {
return;
}
+ auto ClearCachedCodeIfPresent = [&]() {
+ if (data.size() != 0) {
+ resource_loader->ClearCachedCode();
+ }
+ };
+
// If the resource was fetched for service worker script or was served from
// CacheStorage via service worker then they maintain their own code cache.
// We should not use the isolated cache.
if (!use_isolated_code_cache_) {
- resource_loader->ClearCachedCode();
+ ClearCachedCodeIfPresent();
return;
}
- // If the timestamps don't match, the code cache data may be for a different
- // response. See https://crbug.com/1099587.
- if (resource_response_time_ != cached_code_response_time_) {
- resource_loader->ClearCachedCode();
- return;
+ if (should_use_source_hash_) {
+ // This resource should use a source text hash rather than a response time
+ // comparison.
+ if (!resource_loader->resource_->CodeCacheHashRequired()) {
+ // This kind of Resource doesn't support requiring a hash, so we can't
+ // send cached code to it.
+ ClearCachedCodeIfPresent();
+ return;
+ }
+ } else {
+ // If the timestamps don't match or are null, the code cache data may be for
+ // a different response. See https://crbug.com/1099587.
+ if (cached_code_response_time_.is_null() ||
+ resource_response_time_.is_null() ||
+ resource_response_time_ != cached_code_response_time_) {
+ ClearCachedCodeIfPresent();
+ return;
+ }
}
if (data.size() > 0) {
@@ -472,9 +485,21 @@ bool ResourceLoader::ShouldFetchCodeCache() {
if (!RuntimeEnabledFeatures::IsolatedCodeCacheEnabled())
return false;
+ // Since code cache requests use a per-frame interface, don't fetch cached
+ // code for keep-alive requests. These are only used for beaconing and we
+ // don't expect code cache to help there.
+ if (ShouldBeKeptAliveWhenDetached())
+ return false;
+
const ResourceRequestHead& request = resource_->GetResourceRequest();
- if (!request.Url().ProtocolIsInHTTPFamily())
+ // Aside from http and https, the only other supported protocols are those
+ // listed in the SchemeRegistry as requiring a content equality check.
+ bool should_use_source_hash =
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(
+ request.Url().Protocol());
+ if (!request.Url().ProtocolIsInHTTPFamily() && !should_use_source_hash) {
return false;
+ }
// When loading the service worker scripts, we don't need to check the
// GeneratedCodeCache. The code cache corresponding to these scripts is in
// the service worker's "installed script storage" and would be fetched along
@@ -497,8 +522,13 @@ bool ResourceLoader::ShouldFetchCodeCache() {
// These fetches should be cheap, however, requiring one additional IPC and
// no browser process disk IO since the cache index is in memory and the
// resource key should not be present.
+ //
+ // The only case where it's easy to skip a kRaw resource is when a content
+ // equality check is required, because only ScriptResource supports that
+ // requirement.
return resource_->GetType() == ResourceType::kScript ||
- resource_->GetType() == ResourceType::kRaw;
+ (resource_->GetType() == ResourceType::kRaw &&
+ !should_use_source_hash);
}
void ResourceLoader::Start() {
@@ -571,7 +601,7 @@ void ResourceLoader::Run() {
}
void ResourceLoader::DidReceiveData(base::span<const char> data) {
- DidReceiveData(data.data(), data.size());
+ DidReceiveData(data.data(), base::checked_cast<int>(data.size()));
}
void ResourceLoader::DidFinishLoadingBody() {
@@ -601,7 +631,7 @@ void ResourceLoader::StartWith(const ResourceRequestHead& request) {
DCHECK(loader_);
if (resource_->Options().synchronous_policy == kRequestSynchronously &&
- fetcher_->GetProperties().IsLoadDeferred()) {
+ fetcher_->GetProperties().FreezeMode() != LoaderFreezeMode::kNone) {
// TODO(yuzus): Evict bfcache if necessary.
Cancel();
return;
@@ -609,12 +639,12 @@ void ResourceLoader::StartWith(const ResourceRequestHead& request) {
is_downloading_to_blob_ = request.DownloadToBlob();
- SetDefersLoading(fetcher_->GetProperties().DeferType());
+ SetDefersLoading(fetcher_->GetProperties().FreezeMode());
if (ShouldFetchCodeCache()) {
code_cache_request_ = std::make_unique<CodeCacheRequest>(
fetcher_->CreateCodeCacheLoader(), request.Url(),
- fetcher_->GetProperties().DeferType());
+ fetcher_->GetProperties().FreezeMode());
}
if (is_cache_aware_loading_activated_) {
@@ -651,30 +681,30 @@ void ResourceLoader::Restart(const ResourceRequestHead& request) {
StartWith(request);
}
-void ResourceLoader::SetDefersLoading(WebURLLoader::DeferType defers) {
+void ResourceLoader::SetDefersLoading(LoaderFreezeMode mode) {
DCHECK(loader_);
- defers_ = defers;
+ freeze_mode_ = mode;
// If CodeCacheRequest handles this, then no need to handle here.
- if (code_cache_request_ && code_cache_request_->SetDefersLoading(defers))
+ if (code_cache_request_ && code_cache_request_->SetDefersLoading(mode))
return;
if (response_body_loader_) {
- if (defers != WebURLLoader::DeferType::kNotDeferred &&
+ if (mode != LoaderFreezeMode::kNone &&
!response_body_loader_->IsSuspended()) {
- response_body_loader_->Suspend(defers);
- if (defers == WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
+ response_body_loader_->Suspend(mode);
+ if (mode == LoaderFreezeMode::kBufferIncoming) {
response_body_loader_
->EvictFromBackForwardCacheIfDrainedAsBytesConsumer();
}
}
- if (defers == WebURLLoader::DeferType::kNotDeferred &&
+ if (mode == LoaderFreezeMode::kNone &&
response_body_loader_->IsSuspended()) {
response_body_loader_->Resume();
}
}
if (defers_handling_data_url_) {
- if (defers_ == WebURLLoader::DeferType::kNotDeferred) {
+ if (freeze_mode_ == LoaderFreezeMode::kNone) {
defers_handling_data_url_ = false;
GetLoadingTaskRunner()->PostTask(
FROM_HERE,
@@ -682,8 +712,8 @@ void ResourceLoader::SetDefersLoading(WebURLLoader::DeferType defers) {
}
}
- loader_->SetDefersLoading(defers);
- if (defers != WebURLLoader::DeferType::kNotDeferred) {
+ loader_->Freeze(mode);
+ if (mode != LoaderFreezeMode::kNone) {
resource_->VirtualTimePauser().UnpauseVirtualTime();
} else {
resource_->VirtualTimePauser().PauseVirtualTime();
@@ -746,12 +776,12 @@ bool ResourceLoader::WillFollowRedirect(
network::mojom::ReferrerPolicy new_referrer_policy,
const WebString& new_method,
const WebURLResponse& passed_redirect_response,
- bool& report_raw_headers,
+ bool& has_devtools_request_id,
std::vector<std::string>* removed_headers) {
DCHECK(!passed_redirect_response.IsNull());
if (passed_redirect_response.HasAuthorizationCoveredByWildcardOnPreflight()) {
- fetcher_->GetUseCounter().CountUse(
+ fetcher_->GetUseCounter().CountDeprecation(
mojom::WebFeature::kAuthorizationCoveredByWildcard);
}
@@ -884,7 +914,7 @@ bool ResourceLoader::WillFollowRedirect(
return false;
}
- report_raw_headers = new_request->ReportRawHeaders();
+ has_devtools_request_id = new_request->GetDevToolsId().has_value();
return true;
}
@@ -934,7 +964,7 @@ void ResourceLoader::DidReceiveResponseInternal(
const ResourceRequestHead& request = resource_->GetResourceRequest();
if (response.HasAuthorizationCoveredByWildcardOnPreflight()) {
- fetcher_->GetUseCounter().CountUse(
+ fetcher_->GetUseCounter().CountDeprecation(
mojom::WebFeature::kAuthorizationCoveredByWildcard);
}
@@ -1259,7 +1289,9 @@ void ResourceLoader::HandleError(const ResourceError& error) {
Restart(resource_->GetResourceRequest());
return;
}
- if (error.CorsErrorStatus()) {
+ if (error.CorsErrorStatus() &&
+ !base::FeatureList::IsEnabled(blink::features::kCORSErrorsIssueOnly)) {
+ // CORS issues are reported via network service instrumentation.
fetcher_->GetConsoleLogger().AddConsoleMessage(
mojom::ConsoleMessageSource::kJavaScript,
mojom::ConsoleMessageLevel::kError,
@@ -1536,7 +1568,7 @@ ResourceLoader::CheckResponseNosniff(
void ResourceLoader::HandleDataUrl() {
if (!IsLoading())
return;
- if (defers_ != WebURLLoader::DeferType::kNotDeferred) {
+ if (freeze_mode_ != LoaderFreezeMode::kNone) {
defers_handling_data_url_ = true;
return;
}
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 6c9c7ed33d9..248ee7304f5 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
@@ -43,6 +43,7 @@
#include "third_party/blink/public/platform/web_url_loader_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -97,7 +98,7 @@ class PLATFORM_EXPORT ResourceLoader final
void ScheduleCancel();
void Cancel();
- void SetDefersLoading(WebURLLoader::DeferType);
+ void SetDefersLoading(LoaderFreezeMode);
void DidChangePriority(ResourceLoadPriority, int intra_priority_value);
@@ -132,7 +133,7 @@ class PLATFORM_EXPORT ResourceLoader final
network::mojom::ReferrerPolicy new_referrer_policy,
const WebString& new_method,
const WebURLResponse& passed_redirect_response,
- bool& report_raw_headers,
+ bool& has_devtools_request_id,
std::vector<std::string>* removed_headers) override;
void DidSendData(uint64_t bytes_sent,
uint64_t total_bytes_to_be_sent) override;
@@ -266,7 +267,7 @@ class PLATFORM_EXPORT ResourceLoader final
absl::optional<DeferredFinishLoadingInfo> deferred_finish_loading_info_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_body_loader_;
- WebURLLoader::DeferType defers_ = WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
// True if the next call of SetDefersLoading(kNotDeferred) needs to invoke
// HandleDataURL().
bool defers_handling_data_url_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
index 06d89c4ae0a..6220a8a11ac 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
@@ -39,10 +39,6 @@ class TestCodeCacheLoader : public WebCodeCacheLoader {
~TestCodeCacheLoader() override = default;
// WebCodeCacheLoader methods:
- void FetchFromCodeCacheSynchronously(
- const WebURL& url,
- base::Time* response_time_out,
- mojo_base::BigBuffer* buffer_out) override {}
void FetchFromCodeCache(
blink::mojom::CodeCacheType cache_type,
const WebURL& url,
@@ -57,8 +53,8 @@ class TestCodeCacheLoader : public WebCodeCacheLoader {
// A mock WebURLLoader to know the status of defers flag.
class TestWebURLLoader final : public WebURLLoader {
public:
- explicit TestWebURLLoader(WebURLLoader::DeferType* const defers_flag_ptr)
- : defers_flag_ptr_(defers_flag_ptr) {}
+ explicit TestWebURLLoader(WebLoaderFreezeMode* const freeze_mode_ptr)
+ : freeze_mode_ptr_(freeze_mode_ptr) {}
~TestWebURLLoader() override = default;
void LoadSynchronously(
@@ -86,9 +82,7 @@ class TestWebURLLoader final : public WebURLLoader {
resource_load_info_notifier_wrapper,
WebURLLoaderClient*) override {}
- void SetDefersLoading(WebURLLoader::DeferType defers) override {
- *defers_flag_ptr_ = defers;
- }
+ void Freeze(WebLoaderFreezeMode mode) override { *freeze_mode_ptr_ = mode; }
void DidChangePriority(WebURLRequest::Priority, int) override {
NOTREACHED();
}
@@ -98,16 +92,16 @@ class TestWebURLLoader final : public WebURLLoader {
}
private:
- // Points to |ResourceLoaderDefersLoadingTest::web_url_loader_defers_|.
- WebURLLoader::DeferType* const defers_flag_ptr_;
+ // Points to |ResourceLoaderDefersLoadingTest::freeze_mode_|.
+ WebLoaderFreezeMode* const freeze_mode_ptr_;
};
class DeferTestLoaderFactory final : public ResourceFetcher::LoaderFactory {
public:
DeferTestLoaderFactory(
- WebURLLoader::DeferType* const defers_flag,
+ WebLoaderFreezeMode* const freeze_mode_ptr,
ProcessCodeCacheRequestCallback process_code_cache_request_callback)
- : defers_flag_(defers_flag),
+ : freeze_mode_ptr_(freeze_mode_ptr),
process_code_cache_request_callback_(
process_code_cache_request_callback) {}
@@ -119,7 +113,7 @@ class DeferTestLoaderFactory final : public ResourceFetcher::LoaderFactory {
scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
override {
- return std::make_unique<TestWebURLLoader>(defers_flag_);
+ return std::make_unique<TestWebURLLoader>(freeze_mode_ptr_);
}
std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
@@ -128,8 +122,8 @@ class DeferTestLoaderFactory final : public ResourceFetcher::LoaderFactory {
}
private:
- // Points to |ResourceLoaderDefersLoadingTest::web_url_loader_defers_|.
- WebURLLoader::DeferType* const defers_flag_;
+ // Points to |ResourceLoaderDefersLoadingTest::freeze_mode_|.
+ WebLoaderFreezeMode* const freeze_mode_ptr_;
ProcessCodeCacheRequestCallback process_code_cache_request_callback_;
};
@@ -157,7 +151,7 @@ class ResourceLoaderDefersLoadingTest : public testing::Test {
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
MakeGarbageCollected<DeferTestLoaderFactory>(
- &web_url_loader_defers_, process_code_cache_request_callback_),
+ &freeze_mode_, process_code_cache_request_callback_),
MakeGarbageCollected<MockContextLifecycleNotifier>(),
nullptr /* back_forward_cache_loader_helper */));
}
@@ -169,9 +163,8 @@ class ResourceLoaderDefersLoadingTest : public testing::Test {
ProcessCodeCacheRequestCallback process_code_cache_request_callback_;
WebCodeCacheLoader::FetchCodeCacheCallback code_cache_response_callback_;
// Passed to TestWebURLLoader (via |platform_|) and updated when its
- // SetDefersLoading method is called.
- WebURLLoader::DeferType web_url_loader_defers_ =
- WebURLLoader::DeferType::kNotDeferred;
+ // Freeze method is called.
+ WebLoaderFreezeMode freeze_mode_ = WebLoaderFreezeMode::kNone;
const KURL test_url_ = KURL("http://example.com/");
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
@@ -190,11 +183,11 @@ TEST_F(ResourceLoaderDefersLoadingTest, CodeCacheFetchCheckDefers) {
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
// After code cache fetch it should have deferred WebURLLoader.
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
DCHECK(resource);
std::move(code_cache_response_callback_).Run(base::Time(), {});
// Once the response is received it should be reset.
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kNotDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kNone);
}
TEST_F(ResourceLoaderDefersLoadingTest, CodeCacheFetchSyncReturn) {
@@ -214,7 +207,7 @@ TEST_F(ResourceLoaderDefersLoadingTest, CodeCacheFetchSyncReturn) {
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
DCHECK(resource);
// The callback would be called so it should not be deferred.
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kNotDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kNone);
}
TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToFalse) {
@@ -227,13 +220,13 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToFalse) {
FetchParameters::CreateForTest(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
// Change Defers loading to false. This should not be sent to
// WebURLLoader since a code cache request is still pending.
ResourceLoader* loader = resource->Loader();
- loader->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kNone);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
}
TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToTrue) {
@@ -246,16 +239,16 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToTrue) {
FetchParameters::CreateForTest(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
ResourceLoader* loader = resource->Loader();
- loader->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kStrict);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
std::move(code_cache_response_callback_).Run(base::Time(), {});
// Since it was requested to be deferred, it should be reset to the
// correct value.
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
}
TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToBfcacheDefer) {
@@ -268,18 +261,16 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToBfcacheDefer) {
FetchParameters::CreateForTest(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
ResourceLoader* loader = resource->Loader();
- loader->SetDefersLoading(
- WebURLLoader::DeferType::kDeferredWithBackForwardCache);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kBufferIncoming);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
std::move(code_cache_response_callback_).Run(base::Time(), {});
// Since it was requested to be deferred, it should be reset to the
// correct value.
- DCHECK_EQ(web_url_loader_defers_,
- WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kBufferIncoming);
}
TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersMultipleTimes) {
@@ -292,17 +283,17 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersMultipleTimes) {
FetchParameters fetch_parameters =
FetchParameters::CreateForTest(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
ResourceLoader* loader = resource->Loader();
- loader->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kStrict);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
- loader->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kDeferred);
+ loader->SetDefersLoading(LoaderFreezeMode::kNone);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kStrict);
std::move(code_cache_response_callback_).Run(base::Time(), {});
- DCHECK_EQ(web_url_loader_defers_, WebURLLoader::DeferType::kNotDeferred);
+ DCHECK_EQ(freeze_mode_, LoaderFreezeMode::kNone);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
index c58fa9b2612..09fd868fd78 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
@@ -27,7 +27,9 @@
#include "third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h"
#include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/testing/code_cache_loader_mock.h"
#include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h"
+#include "third_party/blink/renderer/platform/testing/noop_web_url_loader.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -47,8 +49,6 @@ const char kCnameAliasWasBlockedHistogram[] =
"SubresourceFilter.CnameAlias.Renderer.WasBlockedBasedOnAlias";
class ResourceLoaderTest : public testing::Test {
- DISALLOW_COPY_AND_ASSIGN(ResourceLoaderTest);
-
public:
enum class From {
kServiceWorker,
@@ -57,6 +57,8 @@ class ResourceLoaderTest : public testing::Test {
ResourceLoaderTest()
: foo_url_("https://foo.test"), bar_url_("https://bar.test") {}
+ ResourceLoaderTest(const ResourceLoaderTest&) = delete;
+ ResourceLoaderTest& operator=(const ResourceLoaderTest&) = delete;
protected:
using RequestMode = network::mojom::RequestMode;
@@ -88,7 +90,7 @@ class ResourceLoaderTest : public testing::Test {
std::move(freezable_task_runner));
}
std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
- return Platform::Current()->CreateCodeCacheLoader();
+ return std::make_unique<CodeCacheLoaderMock>();
}
};
@@ -105,51 +107,6 @@ class ResourceLoaderTest : public testing::Test {
MakeGarbageCollected<MockContextLifecycleNotifier>(),
nullptr /* back_forward_cache_loader_helper */));
}
-
- private:
- class NoopWebURLLoader final : public WebURLLoader {
- public:
- explicit NoopWebURLLoader(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : task_runner_(task_runner) {}
- ~NoopWebURLLoader() override = default;
- void LoadSynchronously(
- std::unique_ptr<network::ResourceRequest> request,
- scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
- bool pass_response_pipe_to_client,
- bool no_mime_sniffing,
- base::TimeDelta timeout_interval,
- WebURLLoaderClient*,
- WebURLResponse&,
- absl::optional<WebURLError>&,
- WebData&,
- int64_t& encoded_data_length,
- int64_t& encoded_body_length,
- WebBlobInfo& downloaded_blob,
- std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
- resource_load_info_notifier_wrapper) override {
- NOTREACHED();
- }
- void LoadAsynchronously(
- std::unique_ptr<network::ResourceRequest> request,
- scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
- bool no_mime_sniffing,
- std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
- resource_load_info_notifier_wrapper,
- WebURLLoaderClient*) override {}
-
- void SetDefersLoading(WebURLLoader::DeferType) override {}
- void DidChangePriority(WebURLRequest::Priority, int) override {
- NOTREACHED();
- }
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
- override {
- return task_runner_;
- }
-
- private:
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- };
};
std::ostream& operator<<(std::ostream& o, const ResourceLoaderTest::From& f) {
@@ -221,7 +178,7 @@ TEST_F(ResourceLoaderTest, LoadResponseBody) {
scoped_refptr<const SharedBuffer> buffer = resource->ResourceBuffer();
StringBuilder data;
for (const auto& span : *buffer) {
- data.Append(span.data(), span.size());
+ data.Append(span.data(), static_cast<wtf_size_t>(span.size()));
}
EXPECT_EQ(data.ToString(), "hello");
}
@@ -246,7 +203,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndNonStream) {
scoped_refptr<const SharedBuffer> buffer = resource->ResourceBuffer();
StringBuilder data;
for (const auto& span : *buffer) {
- data.Append(span.data(), span.size());
+ data.Append(span.data(), static_cast<wtf_size_t>(span.size()));
}
EXPECT_EQ(data.ToString(), "Hello World!");
}
@@ -353,7 +310,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_Sync) {
scoped_refptr<const SharedBuffer> buffer = resource->ResourceBuffer();
StringBuilder data;
for (const auto& span : *buffer) {
- data.Append(span.data(), span.size());
+ data.Append(span.data(), static_cast<wtf_size_t>(span.size()));
}
EXPECT_EQ(data.ToString(), "Hello World!");
}
@@ -393,30 +350,30 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndNonStream) {
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
// The resource should still be pending since it's deferred.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
// The resource should still be pending since it's deferred again.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
// The resource should still be pending if it's unset and set in a single
// task.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kNone);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
// The resource has a parsed body.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kNone);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kCached);
scoped_refptr<const SharedBuffer> buffer = resource->ResourceBuffer();
StringBuilder data;
for (const auto& span : *buffer) {
- data.Append(span.data(), span.size());
+ data.Append(span.data(), static_cast<wtf_size_t>(span.size()));
}
EXPECT_EQ(data.ToString(), "Hello World!");
}
@@ -437,7 +394,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndStream) {
auto* raw_resource_client = MakeGarbageCollected<TestRawResourceClient>();
Resource* resource = RawResource::Fetch(params, fetcher, raw_resource_client);
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
task_runner->RunUntilIdle();
// It's still pending because the body should not provided yet.
@@ -446,14 +403,14 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndStream) {
// The body should be provided since not deferring now, but it's still pending
// since we haven't read the body yet.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kNone);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
EXPECT_TRUE(raw_resource_client->body());
// The resource should still be pending when it's set to deferred again. No
// body is provided when deferred.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
const char* buffer;
@@ -464,15 +421,15 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndStream) {
// The resource should still be pending if it's unset and set in a single
// task. No body is provided when deferred.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kNone);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kStrict);
task_runner->RunUntilIdle();
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
result = raw_resource_client->body()->BeginRead(&buffer, &available);
EXPECT_EQ(BytesConsumer::Result::kShouldWait, result);
// Read through the bytes consumer passed back from the ResourceLoader.
- fetcher->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ fetcher->SetDefersLoading(LoaderFreezeMode::kNone);
task_runner->RunUntilIdle();
auto* test_reader = MakeGarbageCollected<BytesConsumerTestReader>(
raw_resource_client->body());
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 02f375e7b41..3dc33eeb0d0 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
@@ -88,7 +88,6 @@ ResourceRequestHead::ResourceRequestHead(const KURL& url)
http_method_(http_names::kGET),
allow_stored_credentials_(true),
report_upload_progress_(false),
- report_raw_headers_(false),
has_user_gesture_(false),
has_text_fragment_token_(false),
download_to_blob_(false),
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 dc8caf2313b..34e8eae4f55 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
@@ -31,7 +31,6 @@
#include <memory>
#include "base/containers/flat_set.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "net/cookies/site_for_cookies.h"
@@ -57,6 +56,12 @@
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+namespace network {
+namespace mojom {
+class WebBundleHandle;
+} // namespace mojom
+} // namespace network
+
namespace blink {
class EncodedFormData;
@@ -231,13 +236,6 @@ class PLATFORM_EXPORT ResourceRequestHead {
report_upload_progress_ = report_upload_progress;
}
- // Whether actual headers being sent/received should be collected and reported
- // for the request.
- bool ReportRawHeaders() const { return report_raw_headers_; }
- void SetReportRawHeaders(bool report_raw_headers) {
- report_raw_headers_ = report_raw_headers;
- }
-
// True if request was user initiated.
bool HasUserGesture() const { return has_user_gesture_; }
void SetHasUserGesture(bool);
@@ -556,7 +554,6 @@ class PLATFORM_EXPORT ResourceRequestHead {
HTTPHeaderMap http_header_fields_;
bool allow_stored_credentials_ : 1;
bool report_upload_progress_ : 1;
- bool report_raw_headers_ : 1;
bool has_user_gesture_ : 1;
bool has_text_fragment_token_ : 1;
bool download_to_blob_ : 1;
@@ -700,7 +697,7 @@ class PLATFORM_EXPORT ResourceRequestBody {
// This class is thread-bound. Do not copy/pass an instance across threads.
//
// Although request consists head and body, ResourceRequest is implemented by
-// inheriting ResourceRequestHead due in order to make it possible to use
+// inheriting ResourceRequestHead in order to make it possible to use
// property accessors through both ResourceRequestHead and ResourceRequest while
// avoiding duplicate accessor definitions.
// For those who want to add a new property in request, please implement its
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 c8e8f73a853..286aaa18ad6 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
@@ -35,7 +35,6 @@
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
@@ -82,10 +81,37 @@ ResourceResponse::SignedCertificateTimestamp::IsolatedCopy() const {
signature_data_.IsolatedCopy());
}
-ResourceResponse::ResourceResponse() : is_null_(true) {}
+ResourceResponse::ResourceResponse()
+ : was_cached_(false),
+ connection_reused_(false),
+ is_null_(true),
+ have_parsed_age_header_(false),
+ have_parsed_date_header_(false),
+ have_parsed_expires_header_(false),
+ have_parsed_last_modified_header_(false),
+ has_major_certificate_errors_(false),
+ is_legacy_tls_version_(false),
+ has_range_requested_(false),
+ timing_allow_passed_(false),
+ was_fetched_via_spdy_(false),
+ was_fetched_via_service_worker_(false),
+ did_service_worker_navigation_preload_(false),
+ async_revalidation_requested_(false),
+ is_signed_exchange_inner_response_(false),
+ was_in_prefetch_cache_(false),
+ was_cookie_in_request_(false),
+ network_accessed_(false),
+ from_archive_(false),
+ was_alternate_protocol_available_(false),
+ was_alpn_negotiated_(false),
+ has_authorization_covered_by_wildcard_on_preflight_(false),
+ is_validated_(false),
+ request_include_credentials_(true) {}
ResourceResponse::ResourceResponse(const KURL& current_request_url)
- : current_request_url_(current_request_url), is_null_(false) {}
+ : ResourceResponse() {
+ SetCurrentRequestUrl(current_request_url);
+}
ResourceResponse::ResourceResponse(const ResourceResponse&) = default;
ResourceResponse& ResourceResponse::operator=(const ResourceResponse&) =
@@ -97,6 +123,10 @@ bool ResourceResponse::IsHTTP() const {
return current_request_url_.ProtocolIsInHTTPFamily();
}
+bool ResourceResponse::ShouldPopulateResourceTiming() const {
+ return IsHTTP() || WebBundleURL().IsValid();
+}
+
const KURL& ResourceResponse::CurrentRequestUrl() const {
return current_request_url_;
}
@@ -453,15 +483,6 @@ void ResourceResponse::SetResourceLoadTiming(
resource_load_timing_ = std::move(resource_load_timing);
}
-scoped_refptr<ResourceLoadInfo> ResourceResponse::GetResourceLoadInfo() const {
- return resource_load_info_.get();
-}
-
-void ResourceResponse::SetResourceLoadInfo(
- scoped_refptr<ResourceLoadInfo> load_info) {
- resource_load_info_ = std::move(load_info);
-}
-
void ResourceResponse::SetCTPolicyCompliance(CTPolicyCompliance compliance) {
ct_policy_compliance_ = compliance;
}
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 2cd78afb977..dd750668517 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
@@ -51,7 +51,6 @@
namespace blink {
class ResourceLoadTiming;
-struct ResourceLoadInfo;
// A ResourceResponse is a "response" object used in blink. Conceptually
// it is https://fetch.spec.whatwg.org/#concept-response, but it contains
@@ -171,6 +170,12 @@ class PLATFORM_EXPORT ResourceResponse final {
bool IsNull() const { return is_null_; }
bool IsHTTP() const;
+ // When serving resources from a WebBundle, we might have resources whose
+ // source isn't a URL (like urn:uuid), but we still need to create and
+ // populate ResourceTiming entries for them, so we need to check that either
+ // response has a proper request URL or a WebBundleURL.
+ bool ShouldPopulateResourceTiming() const;
+
// The current request URL for this resource (the URL after redirects).
// Corresponds to:
// https://fetch.spec.whatwg.org/#concept-request-current-url
@@ -263,9 +268,6 @@ class PLATFORM_EXPORT ResourceResponse final {
ResourceLoadTiming* GetResourceLoadTiming() const;
void SetResourceLoadTiming(scoped_refptr<ResourceLoadTiming>);
- scoped_refptr<ResourceLoadInfo> GetResourceLoadInfo() const;
- void SetResourceLoadInfo(scoped_refptr<ResourceLoadInfo>);
-
HTTPVersion HttpVersion() const { return http_version_; }
void SetHttpVersion(HTTPVersion version) { http_version_ = version; }
@@ -520,6 +522,13 @@ class PLATFORM_EXPORT ResourceResponse final {
auth_challenge_info_ = value;
}
+ bool RequestIncludeCredentials() const {
+ return request_include_credentials_;
+ }
+ void SetRequestIncludeCredentials(bool request_include_credentials) {
+ request_include_credentials_ = request_include_credentials;
+ }
+
private:
void UpdateHeaderParsedState(const AtomicString& name);
@@ -540,93 +549,101 @@ class PLATFORM_EXPORT ResourceResponse final {
network::mojom::IPAddressSpace address_space_ =
network::mojom::IPAddressSpace::kUnknown;
- bool was_cached_ = false;
- bool connection_reused_ = false;
- bool is_null_ = false;
- mutable bool have_parsed_age_header_ = false;
- mutable bool have_parsed_date_header_ = false;
- mutable bool have_parsed_expires_header_ = false;
- mutable bool have_parsed_last_modified_header_ = false;
-
- // True if the resource was retrieved by the embedder in spite of
- // certificate errors.
- bool has_major_certificate_errors_ = false;
-
// The Certificate Transparency policy compliance status of the resource.
CTPolicyCompliance ct_policy_compliance_ =
kCTPolicyComplianceDetailsNotAvailable;
+ bool was_cached_ : 1;
+ bool connection_reused_ : 1;
+ bool is_null_ : 1;
+ mutable bool have_parsed_age_header_ : 1;
+ mutable bool have_parsed_date_header_ : 1;
+ mutable bool have_parsed_expires_header_ : 1;
+ mutable bool have_parsed_last_modified_header_ : 1;
+
+ // True if the resource was retrieved by the embedder in spite of
+ // certificate errors.
+ bool has_major_certificate_errors_ : 1;
+
// True if the response was sent over TLS 1.0 or 1.1, which are deprecated and
// will be removed in the future.
- bool is_legacy_tls_version_ = false;
+ bool is_legacy_tls_version_ : 1;
// This corresponds to the range-requested flag in the Fetch spec:
// https://fetch.spec.whatwg.org/#concept-response-range-requested-flag
- bool has_range_requested_ = false;
+ bool has_range_requested_ : 1;
// True if the Timing-Allow-Origin check passes.
// https://fetch.spec.whatwg.org/#concept-response-timing-allow-passed
- bool timing_allow_passed_ = false;
-
- // The time at which the resource's certificate expires. Null if there was no
- // certificate.
- base::Time cert_validity_start_;
+ bool timing_allow_passed_ : 1;
// Was the resource fetched over SPDY. See http://dev.chromium.org/spdy
- bool was_fetched_via_spdy_ = false;
+ bool was_fetched_via_spdy_ : 1;
// Was the resource fetched over a ServiceWorker.
- bool was_fetched_via_service_worker_ = false;
-
- // The source of the resource, if it was fetched via ServiceWorker. This is
- // kUnspecified if |was_fetched_via_service_worker| is false.
- network::mojom::FetchResponseSource service_worker_response_source_ =
- network::mojom::FetchResponseSource::kUnspecified;
+ bool was_fetched_via_service_worker_ : 1;
// True if service worker navigation preload was performed due to
// the request for this resource.
- bool did_service_worker_navigation_preload_ = false;
+ bool did_service_worker_navigation_preload_ : 1;
// 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;
+ bool async_revalidation_requested_ : 1;
// True if this resource is from an inner response of a signed exchange.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
- bool is_signed_exchange_inner_response_ = false;
+ bool is_signed_exchange_inner_response_ : 1;
// True if this resource is served from the prefetch cache.
- bool was_in_prefetch_cache_ = false;
+ bool was_in_prefetch_cache_ : 1;
// True if a cookie was sent in the request for this resource.
- bool was_cookie_in_request_ = false;
+ bool was_cookie_in_request_ : 1;
// True if this resource was loaded from the network.
- bool network_accessed_ = false;
+ bool network_accessed_ : 1;
// True if this resource was loaded from a MHTML archive.
- bool from_archive_ = false;
+ bool from_archive_ : 1;
// True if response could use alternate protocol.
- bool was_alternate_protocol_available_ = false;
+ bool was_alternate_protocol_available_ : 1;
// True if the response was delivered after ALPN is negotiated.
- bool was_alpn_negotiated_ = false;
+ bool was_alpn_negotiated_ : 1;
// True when there is an "authorization" header on the request and it is
// covered by the wildcard in the preflight response.
// TODO(crbug.com/1176753): Remove this once the investigation is done.
- bool has_authorization_covered_by_wildcard_on_preflight_ = false;
+ bool has_authorization_covered_by_wildcard_on_preflight_ : 1;
- // https://fetch.spec.whatwg.org/#concept-response-type
- network::mojom::FetchResponseType response_type_ =
- network::mojom::FetchResponseType::kDefault;
+ // Whether the resource came from the cache and validated over the network.
+ bool is_validated_ : 1;
+
+ // The request's |includeCredentials| value from the "HTTP-network fetch"
+ // algorithm.
+ // See: https://fetch.spec.whatwg.org/#concept-http-network-fetch
+ bool request_include_credentials_ : 1;
// Pre-computed padding. This should only be non-zero if |response_type| is
// set to kOpaque. In addition, it is only set if the response was provided
// by a service worker FetchEvent handler.
int64_t padding_ = 0;
+ // The time at which the resource's certificate expires. Null if there was no
+ // certificate.
+ base::Time cert_validity_start_;
+
+ // The source of the resource, if it was fetched via ServiceWorker. This is
+ // kUnspecified if |was_fetched_via_service_worker| is false.
+ network::mojom::FetchResponseSource service_worker_response_source_ =
+ network::mojom::FetchResponseSource::kUnspecified;
+
+ // https://fetch.spec.whatwg.org/#concept-response-type
+ network::mojom::FetchResponseType response_type_ =
+ network::mojom::FetchResponseType::kDefault;
+
// HTTP version used in the response, if known.
HTTPVersion http_version_ = kHTTPVersionUnknown;
@@ -642,7 +659,6 @@ class PLATFORM_EXPORT ResourceResponse final {
absl::optional<SecurityDetails> security_details_;
scoped_refptr<ResourceLoadTiming> resource_load_timing_;
- scoped_refptr<ResourceLoadInfo> resource_load_info_;
mutable CacheControlHeader cache_control_header_;
@@ -682,9 +698,6 @@ class PLATFORM_EXPORT ResourceResponse final {
net::HttpResponseInfo::ConnectionInfo connection_info_ =
net::HttpResponseInfo::ConnectionInfo::CONNECTION_INFO_UNKNOWN;
- // Whether the resource came from the cache and validated over the network.
- bool is_validated_ = false;
-
// Size of the response in bytes prior to decompression.
int64_t encoded_data_length_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
index 825ef805fbb..e9894665ebf 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
@@ -33,7 +33,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink.h"
#include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-blink.h"
@@ -58,8 +57,12 @@ class PLATFORM_EXPORT ResourceTimingInfo
return base::AdoptRef(
new ResourceTimingInfo(type, time, context, destination));
}
+ ResourceTimingInfo(const ResourceTimingInfo&) = delete;
+ ResourceTimingInfo& operator=(const ResourceTimingInfo&) = delete;
+
base::TimeTicks InitialTime() const { return initial_time_; }
+ void SetInitiatorType(const AtomicString& type) { type_ = type; }
const AtomicString& InitiatorType() const { return type_; }
void SetLoadResponseEnd(base::TimeTicks time) { load_response_end_ = time; }
@@ -139,8 +142,6 @@ class PLATFORM_EXPORT ResourceTimingInfo
// empty.
mutable mojo::PendingReceiver<mojom::blink::WorkerTimingContainer>
worker_timing_receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceTimingInfo);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
index 0f4b4ec81d2..db05064f9da 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
@@ -10,6 +10,7 @@
#include "base/auto_reset.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
+#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink.h"
#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
@@ -17,12 +18,11 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
namespace blink {
-constexpr size_t ResponseBodyLoader::kMaxNumConsumedBytesInTask;
-
constexpr size_t kDefaultMaxBufferedBodyBytesPerRequest = 100 * 1000;
class ResponseBodyLoader::DelegatingBytesConsumer final
@@ -303,7 +303,7 @@ class ResponseBodyLoader::Buffer final
"total_bytes_read", static_cast<int>(total_bytes_read_),
"added_bytes", static_cast<int>(available));
Vector<char> new_chunk;
- new_chunk.Append(buffer, available);
+ new_chunk.Append(buffer, base::checked_cast<wtf_size_t>(available));
buffered_data_.emplace_back(std::move(new_chunk));
}
@@ -506,13 +506,13 @@ void ResponseBodyLoader::Abort() {
}
}
-void ResponseBodyLoader::Suspend(WebURLLoader::DeferType suspended_state) {
+void ResponseBodyLoader::Suspend(LoaderFreezeMode mode) {
if (aborted_)
return;
- bool was_suspended = (suspended_state_ == WebURLLoader::DeferType::kDeferred);
+ bool was_suspended = (suspended_state_ == LoaderFreezeMode::kStrict);
- suspended_state_ = suspended_state;
+ suspended_state_ = mode;
if (IsSuspendedForBackForwardCache()) {
DCHECK(IsInflightNetworkRequestBackForwardCacheSupportEnabled());
// If we're already suspended (but not for back-forward cache), we might've
@@ -538,7 +538,7 @@ void ResponseBodyLoader::Resume() {
return;
DCHECK(IsSuspended());
- suspended_state_ = WebURLLoader::DeferType::kNotDeferred;
+ suspended_state_ = LoaderFreezeMode::kNone;
if (finish_signal_is_pending_) {
task_runner_->PostTask(
@@ -567,7 +567,8 @@ void ResponseBodyLoader::OnStateChange() {
size_t num_bytes_consumed = 0;
while (!aborted_ && (!IsSuspended() || IsSuspendedForBackForwardCache())) {
- if (kMaxNumConsumedBytesInTask == num_bytes_consumed) {
+ const uint32_t chunk_size = network::features::GetLoaderChunkSize();
+ if (chunk_size == num_bytes_consumed) {
// We've already consumed many bytes in this task. Defer the remaining
// to the next task.
task_runner_->PostTask(FROM_HERE,
@@ -579,8 +580,8 @@ void ResponseBodyLoader::OnStateChange() {
if (!IsSuspended() && body_buffer_ && !body_buffer_->IsEmpty()) {
// We need to empty |body_buffer_| first before reading more from
// |bytes_consumer_|.
- num_bytes_consumed += body_buffer_->DispatchChunk(
- kMaxNumConsumedBytesInTask - num_bytes_consumed);
+ num_bytes_consumed +=
+ body_buffer_->DispatchChunk(chunk_size - num_bytes_consumed);
continue;
}
@@ -595,8 +596,7 @@ void ResponseBodyLoader::OnStateChange() {
base::AutoReset<bool> auto_reset_for_in_two_phase_read(
&in_two_phase_read_, true);
- available =
- std::min(available, kMaxNumConsumedBytesInTask - num_bytes_consumed);
+ available = std::min(available, chunk_size - num_bytes_consumed);
if (IsSuspendedForBackForwardCache()) {
// Save the read data into |body_buffer_| instead.
DidBufferLoadWhileInBackForwardCache(available);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
index eeb0d66ef38..30feb86b700 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
@@ -10,10 +10,10 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
-#include "third_party/blink/public/platform/web_url_loader.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/loader/fetch/bytes_consumer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -99,18 +99,17 @@ class PLATFORM_EXPORT ResponseBodyLoader final
void Abort();
// Suspends loading.
- void Suspend(WebURLLoader::DeferType suspended_state);
+ void Suspend(LoaderFreezeMode);
// Resumes loading.
void Resume();
bool IsAborted() const { return aborted_; }
bool IsSuspended() const {
- return suspended_state_ != WebURLLoader::DeferType::kNotDeferred;
+ return suspended_state_ != LoaderFreezeMode::kNone;
}
bool IsSuspendedForBackForwardCache() const {
- return suspended_state_ ==
- WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ return suspended_state_ == LoaderFreezeMode::kBufferIncoming;
}
bool IsDrained() const {
return drained_as_datapipe_ || drained_as_bytes_consumer_;
@@ -122,13 +121,6 @@ class PLATFORM_EXPORT ResponseBodyLoader final
void Trace(Visitor*) const override;
- // The maximal number of bytes consumed in a task. When there are more bytes
- // in the data pipe, they will be consumed in following tasks. Setting a too
- // small number will generate ton of tasks but setting a too large number will
- // lead to thread janks. Also, some clients cannot handle too large chunks
- // (512k for example).
- static constexpr size_t kMaxNumConsumedBytesInTask = 64 * 1024;
-
private:
class Buffer;
class DelegatingBytesConsumer;
@@ -152,8 +144,7 @@ class PLATFORM_EXPORT ResponseBodyLoader final
const Member<ResponseBodyLoaderClient> client_;
WeakMember<BackForwardCacheLoaderHelper> back_forward_cache_loader_helper_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- WebURLLoader::DeferType suspended_state_ =
- WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode suspended_state_ = LoaderFreezeMode::kNone;
bool started_ = false;
bool aborted_ = false;
bool drained_as_datapipe_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
index 342b0ccf4ff..0f7db9686c7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
@@ -8,6 +8,7 @@
#include <string>
#include <utility>
#include "base/test/scoped_feature_list.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
@@ -44,6 +45,16 @@ class ResponseBodyLoaderTest : public testing::Test {
using Command = ReplayingBytesConsumer::Command;
using PublicState = BytesConsumer::PublicState;
using Result = BytesConsumer::Result;
+
+ static constexpr uint32_t kMaxNumConsumedBytesInTaskForTesting = 512 * 1024;
+ ResponseBodyLoaderTest() {
+ base::FieldTrialParams params;
+ params["loader_chunk_size"] =
+ base::NumberToString(kMaxNumConsumedBytesInTaskForTesting);
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ network::features::kLoaderDataPipeTuningFeature, params);
+ }
+
class TestClient final : public GarbageCollected<TestClient>,
public ResponseBodyLoaderClient {
public:
@@ -65,7 +76,7 @@ class ResponseBodyLoaderTest : public testing::Test {
void DidReceiveData(base::span<const char> data) override {
DCHECK(!finished_);
DCHECK(!failed_);
- data_.Append(data.data(), data.size());
+ data_.Append(data.data(), static_cast<wtf_size_t>(data.size()));
switch (option_) {
case Option::kNone:
break;
@@ -73,7 +84,7 @@ class ResponseBodyLoaderTest : public testing::Test {
loader_->Abort();
break;
case Option::kSuspendOnDidReceiveData:
- loader_->Suspend(WebURLLoader::DeferType::kDeferred);
+ loader_->Suspend(LoaderFreezeMode::kStrict);
break;
}
}
@@ -160,6 +171,9 @@ class ResponseBodyLoaderTest : public testing::Test {
bytes_consumer, client, task_runner,
MakeGarbageCollected<TestBackForwardCacheLoaderHelper>());
}
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
};
class ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest
@@ -346,7 +360,7 @@ TEST_F(ResponseBodyLoaderTest, Suspend) {
TEST_F(ResponseBodyLoaderTest, ReadTooBigBuffer) {
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
auto* consumer = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
- constexpr auto kMax = ResponseBodyLoader::kMaxNumConsumedBytesInTask;
+ constexpr auto kMax = kMaxNumConsumedBytesInTaskForTesting;
consumer->Add(Command(Command::kData, std::string(kMax - 1, 'a').data()));
consumer->Add(Command(Command::kData, std::string(2, 'b').data()));
@@ -487,7 +501,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
EXPECT_FALSE(client->LoadingIsFailed());
// Suspend (not for back-forward cache), then add some data to |consumer|.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferred);
+ body_loader->Suspend(LoaderFreezeMode::kStrict);
consumer->Add(Command(Command::kData, "llo"));
EXPECT_FALSE(consumer->IsCommandsEmpty());
// Simulate the "readable again" signal.
@@ -502,7 +516,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
EXPECT_FALSE(client->LoadingIsFailed());
// Suspend for back-forward cache, then add some more data to |consumer|.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ body_loader->Suspend(LoaderFreezeMode::kBufferIncoming);
consumer->Add(Command(Command::kData, "w"));
consumer->Add(Command(Command::kWait));
consumer->Add(Command(Command::kData, "o"));
@@ -546,7 +560,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
// Suspend (not for back-forward cache), then add some data to |consumer| with
// the finish signal at the end.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferred);
+ body_loader->Suspend(LoaderFreezeMode::kStrict);
consumer->Add(Command(Command::kData, "llo"));
consumer->Add(Command(Command::kDone));
// Simulate the "readable again" signal.
@@ -562,7 +576,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
EXPECT_FALSE(client->LoadingIsFailed());
// Suspend for back-forward cache.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ body_loader->Suspend(LoaderFreezeMode::kBufferIncoming);
// ResponseBodyLoader will buffer data when deferred for back-forward cache,
// but won't notify the client until it's resumed.
EXPECT_FALSE(consumer->IsCommandsEmpty());
@@ -599,7 +613,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
EXPECT_FALSE(client->LoadingIsFailed());
// Suspend for back-forward cache, then add some more data to |consumer|.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ body_loader->Suspend(LoaderFreezeMode::kBufferIncoming);
consumer->Add(Command(Command::kData, "llo"));
EXPECT_FALSE(consumer->IsCommandsEmpty());
// Simulate the "readable again" signal.
@@ -616,7 +630,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
EXPECT_FALSE(client->LoadingIsFailed());
// Suspend (not for back-forward cache), then add some data to |consumer|.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferred);
+ body_loader->Suspend(LoaderFreezeMode::kStrict);
consumer->Add(Command(Command::kData, "w"));
consumer->Add(Command(Command::kWait));
consumer->Add(Command(Command::kData, "o"));
@@ -659,7 +673,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
EXPECT_FALSE(client->LoadingIsFailed());
// Suspend, then add a long response body to |consumer|.
- body_loader->Suspend(WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ body_loader->Suspend(LoaderFreezeMode::kBufferIncoming);
std::string body(70000, '*');
consumer->Add(Command(Command::kDataAndDone, body.c_str()));
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc
index f92cdcbc868..3cf8d8e45db 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
#include "base/metrics/histogram_macros.h"
+#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -24,13 +25,17 @@ ScriptCachedMetadataHandler::ScriptCachedMetadataHandler(
std::unique_ptr<CachedMetadataSender> sender)
: sender_(std::move(sender)), encoding_(encoding) {}
+ScriptCachedMetadataHandler::~ScriptCachedMetadataHandler() = default;
+
void ScriptCachedMetadataHandler::Trace(Visitor* visitor) const {
CachedMetadataHandler::Trace(visitor);
}
-void ScriptCachedMetadataHandler::SetCachedMetadata(uint32_t data_type_id,
- const uint8_t* data,
- size_t size) {
+void ScriptCachedMetadataHandler::SetCachedMetadata(
+ blink::mojom::CodeCacheHost* code_cache_host,
+ uint32_t data_type_id,
+ const uint8_t* data,
+ size_t size) {
DCHECK(!cached_metadata_);
// Having been discarded once, the further attempts to overwrite the
// CachedMetadata are ignored. This behavior is necessary to avoid clearing
@@ -41,10 +46,11 @@ void ScriptCachedMetadataHandler::SetCachedMetadata(uint32_t data_type_id,
return;
cached_metadata_ = CachedMetadata::Create(data_type_id, data, size);
if (!disable_send_to_platform_for_testing_)
- CommitToPersistentStorage();
+ CommitToPersistentStorage(code_cache_host);
}
void ScriptCachedMetadataHandler::ClearCachedMetadata(
+ blink::mojom::CodeCacheHost* code_cache_host,
ClearCacheType cache_type) {
cached_metadata_ = nullptr;
switch (cache_type) {
@@ -54,13 +60,14 @@ void ScriptCachedMetadataHandler::ClearCachedMetadata(
cached_metadata_discarded_ = true;
break;
case kClearPersistentStorage:
- CommitToPersistentStorage();
+ CommitToPersistentStorage(code_cache_host);
break;
}
}
scoped_refptr<CachedMetadata> ScriptCachedMetadataHandler::GetCachedMetadata(
- uint32_t data_type_id) const {
+ uint32_t data_type_id,
+ GetCachedMetadataBehavior behavior) const {
if (!cached_metadata_) {
RecordState(cached_metadata_discarded_ ? StateOnGet::kWasDiscarded
: StateOnGet::kWasNeverPresent);
@@ -107,14 +114,136 @@ size_t ScriptCachedMetadataHandler::GetCodeCacheSize() const {
return (cached_metadata_) ? cached_metadata_->SerializedData().size() : 0;
}
-void ScriptCachedMetadataHandler::CommitToPersistentStorage() {
+void ScriptCachedMetadataHandler::CommitToPersistentStorage(
+ blink::mojom::CodeCacheHost* code_cache_host) {
if (cached_metadata_) {
base::span<const uint8_t> serialized_data =
cached_metadata_->SerializedData();
- sender_->Send(serialized_data.data(), serialized_data.size());
+ sender_->Send(code_cache_host, serialized_data.data(),
+ serialized_data.size());
} else {
- sender_->Send(nullptr, 0);
+ sender_->Send(code_cache_host, nullptr, 0);
+ }
+}
+
+void ScriptCachedMetadataHandlerWithHashing::Check(
+ blink::mojom::CodeCacheHost* code_cache_host,
+ const ParkableString& source_text) {
+ // If we already attempted to Check once and couldn't compute the hash, just
+ // give up.
+ if (hash_state_ == kFailedToCheck)
+ return;
+
+ DigestValue digest;
+ const String& unparked = source_text.ToString();
+ if (!ComputeDigest(kHashAlgorithmSha256,
+ static_cast<const char*>(unparked.Bytes()),
+ unparked.CharactersSizeInBytes(), digest)) {
+ // Something went wrong computing the hash. We can't use the cached
+ // metadata, but we don't need to clear it on disk.
+ ClearCachedMetadata(code_cache_host, kClearLocally);
+ hash_state_ = kFailedToCheck;
+ return;
+ }
+ CHECK_EQ(digest.size(), kSha256Bytes);
+
+ if (hash_state_ != kUninitialized) {
+ // Compare the hash of the new source text with the one previously loaded.
+ if (memcmp(digest.data(), hash_, kSha256Bytes) != 0) {
+ // If this handler was previously checked and is now being checked again
+ // with a different hash value, then something bad happened. We expect the
+ // handler to only be used with one script source text.
+ CHECK_NE(hash_state_, kChecked);
+
+ // The cached metadata is invalid because the source file has changed.
+ ClearCachedMetadata(code_cache_host, kClearPersistentStorage);
+ }
}
+
+ // Remember the computed hash so that it can be used when saving data to
+ // persistent storage.
+ memcpy(hash_, digest.data(), kSha256Bytes);
+ hash_state_ = kChecked;
+}
+
+void ScriptCachedMetadataHandlerWithHashing::SetSerializedCachedMetadata(
+ mojo_base::BigBuffer data) {
+ // We only expect to receive cached metadata from the platform once. If this
+ // triggers, it indicates an efficiency problem which is most likely
+ // unexpected in code designed to improve performance.
+ DCHECK(!cached_metadata_);
+ DCHECK_EQ(hash_state_, kUninitialized);
+
+ // kChecked and kFailedToCheck states guarantees that hash_ will never be
+ // updated again.
+ CHECK(hash_state_ != kChecked && hash_state_ != kFailedToCheck);
+
+ const uint32_t kMetadataTypeSize = sizeof(uint32_t);
+ const uint32_t kHashingHeaderSize = kMetadataTypeSize + kSha256Bytes;
+
+ // Ensure the data is big enough, otherwise discard the data.
+ if (data.size() < kHashingHeaderSize)
+ return;
+ // Ensure the marker matches, otherwise discard the data.
+ if (*reinterpret_cast<const uint32_t*>(data.data()) !=
+ CachedMetadataHandler::kSingleEntryWithHash) {
+ return;
+ }
+
+ // Split out the data into the hash and the CachedMetadata that follows.
+ memcpy(hash_, data.data() + kMetadataTypeSize, kSha256Bytes);
+ hash_state_ = kDeserialized;
+ cached_metadata_ = CachedMetadata::CreateFromSerializedData(
+ data.data() + kHashingHeaderSize, data.size() - kHashingHeaderSize);
+}
+
+scoped_refptr<CachedMetadata>
+ScriptCachedMetadataHandlerWithHashing::GetCachedMetadata(
+ uint32_t data_type_id,
+ GetCachedMetadataBehavior behavior) const {
+ // The caller should have called Check before attempting to read the cached
+ // metadata. If you just want to know whether cached metadata exists, and it's
+ // okay for that metadata to possibly mismatch with the loaded script content,
+ // then you can pass kAllowUnchecked as the second parameter.
+ if (behavior == kCrashIfUnchecked) {
+ CHECK(hash_state_ == kChecked || hash_state_ == kFailedToCheck);
+ }
+
+ scoped_refptr<CachedMetadata> result =
+ ScriptCachedMetadataHandler::GetCachedMetadata(data_type_id, behavior);
+
+ // The cached metadata should have been cleared if hash computation failed.
+ if (hash_state_ == kFailedToCheck) {
+ CHECK_EQ(result, nullptr);
+ }
+
+ return result;
+}
+
+void ScriptCachedMetadataHandlerWithHashing::CommitToPersistentStorage(
+ blink::mojom::CodeCacheHost* code_cache_host) {
+ Vector<uint8_t> serialized_data = GetSerializedCachedMetadata();
+ Sender()->Send(code_cache_host, serialized_data.data(),
+ serialized_data.size());
+}
+
+Vector<uint8_t>
+ScriptCachedMetadataHandlerWithHashing::GetSerializedCachedMetadata() const {
+ Vector<uint8_t> serialized_data;
+ if (cached_metadata_ && hash_state_ == kChecked) {
+ uint32_t marker = CachedMetadataHandler::kSingleEntryWithHash;
+ serialized_data.Append(reinterpret_cast<uint8_t*>(&marker), sizeof(marker));
+ serialized_data.Append(hash_, kSha256Bytes);
+ base::span<const uint8_t> data = cached_metadata_->SerializedData();
+ serialized_data.Append(data.data(),
+ base::checked_cast<wtf_size_t>(data.size()));
+ }
+ return serialized_data;
+}
+
+void ScriptCachedMetadataHandlerWithHashing::ResetForTesting() {
+ if (hash_state_ == kChecked)
+ hash_state_ = kDeserialized;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
index 4839b7f7350..3eb36e180d9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
@@ -8,7 +8,7 @@
#include <memory>
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.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/text_encoding.h"
@@ -27,16 +27,22 @@ class CachedMetadataSender;
// (not by Resource) by the browser process, and the cached metadata written to
// the handler is rejected if e.g. the disk cache entry has been updated and the
// handler refers to an older response.
-class PLATFORM_EXPORT ScriptCachedMetadataHandler final
+class PLATFORM_EXPORT ScriptCachedMetadataHandler
: public SingleCachedMetadataHandler {
public:
ScriptCachedMetadataHandler(const WTF::TextEncoding&,
std::unique_ptr<CachedMetadataSender>);
- ~ScriptCachedMetadataHandler() override = default;
+ ~ScriptCachedMetadataHandler() override;
void Trace(Visitor*) const override;
- void SetCachedMetadata(uint32_t, const uint8_t*, size_t) override;
- void ClearCachedMetadata(ClearCacheType) override;
- scoped_refptr<CachedMetadata> GetCachedMetadata(uint32_t) const override;
+ void SetCachedMetadata(blink::mojom::CodeCacheHost*,
+ uint32_t,
+ const uint8_t*,
+ size_t) override;
+ void ClearCachedMetadata(blink::mojom::CodeCacheHost*,
+ ClearCacheType) override;
+ scoped_refptr<CachedMetadata> GetCachedMetadata(
+ uint32_t,
+ GetCachedMetadataBehavior = kCrashIfUnchecked) const override;
// This returns the encoding at the time of ResponseReceived(). Therefore this
// does NOT reflect encoding detection from body contents, but the actual
@@ -52,21 +58,72 @@ class PLATFORM_EXPORT ScriptCachedMetadataHandler final
const String& dump_prefix) const override;
// Sets the serialized metadata retrieved from the platform's cache.
- void SetSerializedCachedMetadata(mojo_base::BigBuffer data);
+ virtual void SetSerializedCachedMetadata(mojo_base::BigBuffer data);
size_t GetCodeCacheSize() const override;
- private:
- friend class ModuleScriptTest;
+ protected:
+ virtual void CommitToPersistentStorage(blink::mojom::CodeCacheHost*);
- void CommitToPersistentStorage();
+ CachedMetadataSender* Sender() const { return sender_.get(); }
scoped_refptr<CachedMetadata> cached_metadata_;
+
+ private:
+ friend class ModuleScriptTest;
+
bool cached_metadata_discarded_ = false;
std::unique_ptr<CachedMetadataSender> sender_;
const WTF::TextEncoding encoding_;
};
+class PLATFORM_EXPORT ScriptCachedMetadataHandlerWithHashing final
+ : public ScriptCachedMetadataHandler {
+ public:
+ ScriptCachedMetadataHandlerWithHashing(
+ const WTF::TextEncoding& encoding,
+ std::unique_ptr<CachedMetadataSender> sender)
+ : ScriptCachedMetadataHandler(encoding, std::move(sender)) {}
+ ~ScriptCachedMetadataHandlerWithHashing() override = default;
+
+ // Sets the serialized metadata retrieved from the platform's cache.
+ void SetSerializedCachedMetadata(mojo_base::BigBuffer data) override;
+
+ bool HashRequired() const override { return true; }
+
+ scoped_refptr<CachedMetadata> GetCachedMetadata(
+ uint32_t,
+ GetCachedMetadataBehavior = kCrashIfUnchecked) const override;
+
+ // Pretend that the current content and hash were loaded from disk, not
+ // created by the current process.
+ void ResetForTesting();
+
+ void Check(blink::mojom::CodeCacheHost*,
+ const ParkableString& source_text) override;
+
+ Vector<uint8_t> GetSerializedCachedMetadata() const;
+
+ protected:
+ void CommitToPersistentStorage(blink::mojom::CodeCacheHost*) override;
+
+ private:
+ static const uint32_t kSha256Bytes = 256 / 8;
+ uint8_t hash_[kSha256Bytes];
+ enum HashState {
+ kUninitialized, // hash_ has not been written.
+ kDeserialized, // hash_ contains data from the code cache that has not yet
+ // been checked for matching the script text.
+
+ // Terminal states: once hash_state_ reaches one of the following, neither
+ // hash_state_ nor hash_ will ever change again.
+
+ kChecked, // hash_ contains the hash of the script text.
+ kFailedToCheck, // hash_ contains garbage. Computing the hash failed.
+ };
+ HashState hash_state_ = kUninitialized;
+};
+
// Describes a few interesting states of the ScriptCachedMetadataHandler when
// GetCachedMetadata() is called. These values are written to logs. New enum
// values can be added, but existing enums must never be renumbered or deleted
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h
index 1e6e574cb74..f9c2db1579c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h
@@ -15,6 +15,9 @@ class PLATFORM_EXPORT SharedBufferBytesConsumer final : public BytesConsumer {
public:
// |data| should not be modified after it passed to SharedBufferBytesConsumer.
explicit SharedBufferBytesConsumer(scoped_refptr<const SharedBuffer> data);
+ SharedBufferBytesConsumer(const SharedBufferBytesConsumer&) = delete;
+ SharedBufferBytesConsumer& operator=(const SharedBufferBytesConsumer&) =
+ delete;
// Implements BytesConsumer.
Result BeginRead(const char** buffer, size_t* available) override;
@@ -33,8 +36,6 @@ class PLATFORM_EXPORT SharedBufferBytesConsumer final : public BytesConsumer {
scoped_refptr<const SharedBuffer> data_;
SharedBuffer::Iterator iterator_;
size_t bytes_read_in_chunk_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(SharedBufferBytesConsumer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc
index d024238c265..a9949420f01 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
-#include "base/bit_cast.h"
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
@@ -26,28 +25,31 @@ class SourceKeyedCachedMetadataHandler::SingleKeyHandler final
SingleKeyHandler(SourceKeyedCachedMetadataHandler* parent, Key key)
: parent_(parent), key_(key) {}
- void SetCachedMetadata(uint32_t data_type_id,
+ void SetCachedMetadata(blink::mojom::CodeCacheHost* code_cache_host,
+ uint32_t data_type_id,
const uint8_t* data,
size_t size) override {
DCHECK(!parent_->cached_metadata_map_.Contains(key_));
parent_->cached_metadata_map_.insert(
key_, CachedMetadata::Create(data_type_id, data, size));
if (!disable_send_to_platform_for_testing_)
- parent_->SendToPlatform();
+ parent_->SendToPlatform(code_cache_host);
}
- void ClearCachedMetadata(ClearCacheType cache_type) override {
+ void ClearCachedMetadata(blink::mojom::CodeCacheHost* code_cache_host,
+ ClearCacheType cache_type) override {
if (cache_type == kDiscardLocally)
return;
parent_->cached_metadata_map_.erase(key_);
if (cache_type == CachedMetadataHandler::kClearPersistentStorage)
- parent_->SendToPlatform();
+ parent_->SendToPlatform(code_cache_host);
}
scoped_refptr<CachedMetadata> GetCachedMetadata(
- uint32_t data_type_id) const override {
+ uint32_t data_type_id,
+ GetCachedMetadataBehavior behavior = kCrashIfUnchecked) const override {
scoped_refptr<CachedMetadata> cached_metadata =
- parent_->cached_metadata_map_.at(key_);
+ parent_->cached_metadata_map_.DeprecatedAtOrEmptyValue(key_);
if (!cached_metadata || cached_metadata->DataTypeID() != data_type_id)
return nullptr;
return cached_metadata;
@@ -105,12 +107,13 @@ SingleCachedMetadataHandler* SourceKeyedCachedMetadataHandler::HandlerForSource(
}
void SourceKeyedCachedMetadataHandler::ClearCachedMetadata(
+ blink::mojom::CodeCacheHost* code_cache_host,
CachedMetadataHandler::ClearCacheType cache_type) {
if (cache_type == kDiscardLocally)
return;
cached_metadata_map_.clear();
if (cache_type == CachedMetadataHandler::kClearPersistentStorage)
- SendToPlatform();
+ SendToPlatform(code_cache_host);
}
String SourceKeyedCachedMetadataHandler::Encoding() const {
@@ -226,12 +229,13 @@ void SourceKeyedCachedMetadataHandler::SetSerializedCachedMetadata(
}
}
-void SourceKeyedCachedMetadataHandler::SendToPlatform() {
+void SourceKeyedCachedMetadataHandler::SendToPlatform(
+ blink::mojom::CodeCacheHost* code_cache_host) {
if (!sender_)
return;
if (cached_metadata_map_.IsEmpty()) {
- sender_->Send(nullptr, 0);
+ sender_->Send(code_cache_host, nullptr, 0);
} else {
Vector<uint8_t> serialized_data;
uint32_t marker = CachedMetadataHandler::kSourceKeyedMap;
@@ -244,10 +248,12 @@ void SourceKeyedCachedMetadataHandler::SendToPlatform() {
base::span<const uint8_t> data = metadata.value->SerializedData();
size_t entry_size = data.size();
serialized_data.Append(reinterpret_cast<const uint8_t*>(&entry_size),
- sizeof(entry_size));
- serialized_data.Append(data.data(), data.size());
+ static_cast<wtf_size_t>(sizeof(entry_size)));
+ serialized_data.Append(data.data(),
+ base::checked_cast<wtf_size_t>(data.size()));
}
- sender_->Send(serialized_data.data(), serialized_data.size());
+ sender_->Send(code_cache_host, serialized_data.data(),
+ serialized_data.size());
}
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h
index 4460985757c..004d39a6bbb 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h
@@ -7,8 +7,8 @@
#include <stdint.h>
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -32,6 +32,7 @@ class PLATFORM_EXPORT SourceKeyedCachedMetadataHandler final
SingleCachedMetadataHandler* HandlerForSource(const String& source);
void ClearCachedMetadata(
+ blink::mojom::CodeCacheHost*,
CachedMetadataHandler::ClearCacheType cache_type) override;
String Encoding() const override;
bool IsServedFromCacheStorage() const override {
@@ -73,7 +74,7 @@ class PLATFORM_EXPORT SourceKeyedCachedMetadataHandler final
static bool IsDeletedValue(const Key& value) { return value == Key{1}; }
};
- void SendToPlatform();
+ void SendToPlatform(blink::mojom::CodeCacheHost*);
// TODO(leszeks): Maybe just store the SingleKeyHandlers directly in here?
WTF::HashMap<Key, scoped_refptr<CachedMetadata>, KeyHash, KeyHashTraits>
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS
index 4f6d9b1a986..080e8daa159 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS
@@ -13,6 +13,7 @@ include_rules = [
"+net/ssl/ssl_cipher_suite_names.h",
"+net/ssl/ssl_connection_status_flags.h",
"+net/ssl/ssl_info.h",
+ "+net/test/cert_test_util.h",
"+net/traffic_annotation/network_traffic_annotation.h",
"+net/url_request/referrer_policy.h",
"+services/network/public/mojom/url_loader.mojom.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
index 950f0f3510e..47e47730bf7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.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/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.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/loader/fetch/resource_response.h"
@@ -18,7 +19,7 @@ class CachedMetadataSenderImpl : public CachedMetadataSender {
blink::mojom::CodeCacheType);
~CachedMetadataSenderImpl() override = default;
- void Send(const uint8_t*, size_t) override;
+ void Send(blink::mojom::CodeCacheHost*, const uint8_t*, size_t) override;
bool IsServedFromCacheStorage() override { return false; }
private:
@@ -41,9 +42,20 @@ CachedMetadataSenderImpl::CachedMetadataSenderImpl(
code_cache_type_ == blink::mojom::CodeCacheType::kWebAssembly);
}
-void CachedMetadataSenderImpl::Send(const uint8_t* data, size_t size) {
- Platform::Current()->CacheMetadata(code_cache_type_, response_url_,
- response_time_, data, size);
+void CachedMetadataSenderImpl::Send(
+ blink::mojom::CodeCacheHost* code_cache_host,
+ const uint8_t* data,
+ size_t size) {
+ if (code_cache_host) {
+ code_cache_host->DidGenerateCacheableMetadata(
+ code_cache_type_, response_url_, response_time_,
+ mojo_base::BigBuffer(base::make_span(data, size)));
+ } else {
+ // TODO(mythria): Update worklets to use the correct code_cache_host
+ // interface and remove this path.
+ Platform::Current()->CacheMetadata(code_cache_type_, response_url_,
+ response_time_, data, size);
+ }
}
// This is a CachedMetadataSender implementation that does nothing.
@@ -52,7 +64,7 @@ class NullCachedMetadataSender : public CachedMetadataSender {
NullCachedMetadataSender() = default;
~NullCachedMetadataSender() override = default;
- void Send(const uint8_t*, size_t) override {}
+ void Send(blink::mojom::CodeCacheHost*, const uint8_t*, size_t) override {}
bool IsServedFromCacheStorage() override { return false; }
};
@@ -64,7 +76,7 @@ class ServiceWorkerCachedMetadataSender : public CachedMetadataSender {
scoped_refptr<const SecurityOrigin>);
~ServiceWorkerCachedMetadataSender() override = default;
- void Send(const uint8_t*, size_t) override;
+ void Send(blink::mojom::CodeCacheHost*, const uint8_t*, size_t) override;
bool IsServedFromCacheStorage() override { return true; }
private:
@@ -84,10 +96,42 @@ ServiceWorkerCachedMetadataSender::ServiceWorkerCachedMetadataSender(
DCHECK(!cache_storage_cache_name_.IsNull());
}
-void ServiceWorkerCachedMetadataSender::Send(const uint8_t* data, size_t size) {
- Platform::Current()->CacheMetadataInCacheStorage(
- response_url_, response_time_, data, size,
- WebSecurityOrigin(security_origin_), cache_storage_cache_name_);
+void ServiceWorkerCachedMetadataSender::Send(
+ blink::mojom::CodeCacheHost* code_cache_host,
+ const uint8_t* data,
+ size_t size) {
+ if (code_cache_host) {
+ code_cache_host->DidGenerateCacheableMetadataInCacheStorage(
+ response_url_, response_time_,
+ mojo_base::BigBuffer(base::make_span(data, size)),
+ WebSecurityOrigin(security_origin_), cache_storage_cache_name_.Utf8());
+ } else {
+ // TODO(mythria): Update worklets to use the correct code_cache_host
+ // interface and remove this path.
+ Platform::Current()->CacheMetadataInCacheStorage(
+ response_url_, response_time_, data, size,
+ WebSecurityOrigin(security_origin_), cache_storage_cache_name_);
+ }
+}
+
+// static
+void CachedMetadataSender::SendToCodeCacheHost(
+ blink::mojom::CodeCacheHost* code_cache_host,
+ mojom::blink::CodeCacheType code_cache_type,
+ WTF::String url,
+ base::Time response_time,
+ const uint8_t* data,
+ size_t size) {
+ if (code_cache_host) {
+ code_cache_host->DidGenerateCacheableMetadata(
+ code_cache_type, KURL(url), response_time,
+ mojo_base::BigBuffer(base::make_span(data, size)));
+ } else {
+ // TODO(mythria): Update worklets to use the correct code_cache_host
+ // interface and remove this path.
+ Platform::Current()->CacheMetadata(code_cache_type, KURL(url),
+ response_time, data, size);
+ }
}
// static
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h
index a9885b34a1e..a577739b39c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h
@@ -2,12 +2,13 @@
// Use 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_CACHED_METADATA_HANDLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_CACHED_METADATA_HANDLER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CACHED_METADATA_HANDLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CACHED_METADATA_HANDLER_H_
#include <stdint.h>
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-forward.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/weborigin/security_origin.h"
@@ -17,6 +18,7 @@
namespace blink {
class CachedMetadata;
+class ParkableString;
class ResourceResponse;
class WebProcessMemoryDump;
@@ -32,8 +34,17 @@ class PLATFORM_EXPORT CachedMetadataSender {
blink::mojom::CodeCacheType,
scoped_refptr<const SecurityOrigin> requestor_origin);
+ static void SendToCodeCacheHost(blink::mojom::CodeCacheHost*,
+ mojom::blink::CodeCacheType,
+ WTF::String,
+ base::Time,
+ const uint8_t*,
+ size_t);
+
virtual ~CachedMetadataSender() = default;
- virtual void Send(const uint8_t*, size_t) = 0;
+ virtual void Send(blink::mojom::CodeCacheHost* code_cache_host,
+ const uint8_t*,
+ size_t) = 0;
// IsServedFromCacheStorage is used to alter caching strategy to be more
// aggressive. See V8CodeCache::GetCompileOptions() for an example.
@@ -66,9 +77,11 @@ class CachedMetadataHandler : public GarbageCollected<CachedMetadataHandler> {
// Enum for marking serialized cached metadatas so that the deserializers
// do not conflict.
enum CachedMetadataType : uint32_t {
- kSingleEntry, // the metadata is a single CachedMetadata entry
- kSourceKeyedMap // the metadata is multiple CachedMetadata entries keyed by
- // a source string.
+ kSingleEntry, // the metadata is a single CachedMetadata entry
+ kSourceKeyedMap, // the metadata is multiple CachedMetadata entries keyed
+ // by a source string.
+ kSingleEntryWithHash // the metadata is a content hash followed by a single
+ // CachedMetadata entry
};
virtual ~CachedMetadataHandler() = default;
@@ -76,7 +89,8 @@ class CachedMetadataHandler : public GarbageCollected<CachedMetadataHandler> {
// Reset existing metadata. Subclasses can ignore setting new metadata after
// clearing with |kDiscardLocally| to save memory.
- virtual void ClearCachedMetadata(ClearCacheType) = 0;
+ virtual void ClearCachedMetadata(blink::mojom::CodeCacheHost*,
+ ClearCacheType) = 0;
// Returns the encoding to which the cache is specific.
virtual String Encoding() const = 0;
@@ -99,7 +113,8 @@ class SingleCachedMetadataHandler : public CachedMetadataHandler {
// Caches the given metadata in association with this resource and suggests
// that the platform persist it. The dataTypeID is a pseudo-randomly chosen
// identifier that is used to distinguish data generated by the caller.
- virtual void SetCachedMetadata(uint32_t data_type_id,
+ virtual void SetCachedMetadata(blink::mojom::CodeCacheHost*,
+ uint32_t data_type_id,
const uint8_t*,
size_t) = 0;
@@ -109,16 +124,46 @@ class SingleCachedMetadataHandler : public CachedMetadataHandler {
disable_send_to_platform_for_testing_ = true;
}
+ // Defines how GetCodeCache should behave if the metadata handler requires a
+ // hash check but Check() hasn't yet been called.
+ enum GetCachedMetadataBehavior {
+ // HasCodeCache should crash the program with a runtime CHECK().
+ kCrashIfUnchecked,
+
+ // HasCodeCache should return true if the metadata handler contains data,
+ // even though that data might be stale because we haven't yet validated
+ // that it matches the current version of the script resource.
+ kAllowUnchecked,
+ };
+
// Returns cached metadata of the given type associated with this resource.
// This cached metadata can be pruned at any time.
virtual scoped_refptr<CachedMetadata> GetCachedMetadata(
- uint32_t data_type_id) const = 0;
+ uint32_t data_type_id,
+ GetCachedMetadataBehavior behavior = kCrashIfUnchecked) const = 0;
+
+ // Whether this cached metadata is required to contain a source text hash,
+ // which is used in V8CodeCache to check whether the text of a newly-loaded
+ // script matches the text when the code cache entry was written.
+ virtual bool HashRequired() const { return false; }
+
+ // If the handler requires source hashing, then Check does the following:
+ // 1. If cached metadata is present, check the hash on the cached metadata,
+ // and clear it on a mismatch.
+ // 2. Remember the source hash so that it will be included on any future calls
+ // that commit data to persistent storage.
+ // Calling Check multiple times with different source_text is disallowed.
+ virtual void Check(blink::mojom::CodeCacheHost*,
+ const ParkableString& source_text) {
+ // Do nothing.
+ }
protected:
SingleCachedMetadataHandler() = default;
+
bool disable_send_to_platform_for_testing_ = false;
};
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_CACHED_METADATA_HANDLER_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CACHED_METADATA_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
new file mode 100644
index 00000000000..330a1a62ad0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
@@ -0,0 +1,162 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this sink code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
+#include "third_party/blink/public/platform/url_conversion.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+namespace {
+
+class MockGeneratedCodeCache {
+ public:
+ const Vector<GURL>& CachedURLs() const { return cached_urls_; }
+ const Vector<GURL>& CacheStorageCachedURLs() const {
+ return cache_storage_cached_urls_;
+ }
+
+ void CacheMetadata(mojom::CodeCacheType cache_type,
+ const GURL& gurl,
+ base::Time,
+ const uint8_t*,
+ size_t) {
+ cached_urls_.push_back(gurl);
+ }
+
+ void CacheMetadataInCacheStorage(const GURL& gurl) {
+ cache_storage_cached_urls_.push_back(gurl);
+ }
+
+ private:
+ Vector<GURL> cached_urls_;
+ Vector<GURL> cache_storage_cached_urls_;
+};
+
+class CodeCacheHostMockImpl : public blink::mojom::CodeCacheHost {
+ public:
+ explicit CodeCacheHostMockImpl(MockGeneratedCodeCache* sim) : sim_(sim) {}
+
+ private:
+ // blink::mojom::CodeCacheHost implementation.
+ void DidGenerateCacheableMetadata(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ base::Time expected_response_time,
+ mojo_base::BigBuffer data) override {
+ sim_->CacheMetadata(cache_type, url, expected_response_time, data.data(),
+ data.size());
+ }
+
+ void FetchCachedCode(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ FetchCachedCodeCallback) override {}
+ void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type,
+ const GURL& url) override {}
+ void DidGenerateCacheableMetadataInCacheStorage(
+ const GURL& url,
+ base::Time expected_response_time,
+ mojo_base::BigBuffer data,
+ const url::Origin& cache_storage_origin,
+ const std::string& cache_storage_cache_name) override {
+ sim_->CacheMetadataInCacheStorage(url);
+ }
+
+ MockGeneratedCodeCache* sim_;
+};
+
+ResourceResponse CreateTestResourceResponse() {
+ ResourceResponse response(KURL("https://example.com/"));
+ response.SetHttpStatusCode(200);
+ return response;
+}
+
+void SendDataFor(const ResourceResponse& response,
+ MockGeneratedCodeCache* disk) {
+ constexpr uint8_t kTestData[] = {1, 2, 3, 4, 5};
+ std::unique_ptr<CachedMetadataSender> sender = CachedMetadataSender::Create(
+ response, mojom::CodeCacheType::kJavascript,
+ SecurityOrigin::Create(response.CurrentRequestUrl()));
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(CodeCacheHostMockImpl(disk));
+ sender->Send(code_cache_host.get(), kTestData, sizeof(kTestData));
+}
+
+TEST(CachedMetadataHandlerTest, SendsMetadataToPlatform) {
+ MockGeneratedCodeCache mock_disk_cache;
+ ResourceResponse response(CreateTestResourceResponse());
+
+ SendDataFor(response, &mock_disk_cache);
+ EXPECT_EQ(1u, mock_disk_cache.CachedURLs().size());
+ EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
+TEST(
+ CachedMetadataHandlerTest,
+ DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithSyntheticResponse) {
+ MockGeneratedCodeCache mock_disk_cache;
+
+ // Equivalent to service worker calling respondWith(new Response(...))
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+
+ SendDataFor(response, &mock_disk_cache);
+ EXPECT_EQ(0u, mock_disk_cache.CachedURLs().size());
+ EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
+TEST(
+ CachedMetadataHandlerTest,
+ SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithPassThroughResponse) {
+ MockGeneratedCodeCache mock_disk_cache;
+
+ // Equivalent to service worker calling respondWith(fetch(evt.request.url));
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+ response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
+
+ SendDataFor(response, &mock_disk_cache);
+ EXPECT_EQ(1u, mock_disk_cache.CachedURLs().size());
+ EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
+TEST(
+ CachedMetadataHandlerTest,
+ DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLResponse) {
+ MockGeneratedCodeCache mock_disk_cache;
+
+ // Equivalent to service worker calling respondWith(fetch(some_different_url))
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+ response.SetUrlListViaServiceWorker(
+ {KURL("https://example.com/different/url")});
+
+ SendDataFor(response, &mock_disk_cache);
+ EXPECT_EQ(0u, mock_disk_cache.CachedURLs().size());
+ EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
+TEST(CachedMetadataHandlerTest,
+ SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithCacheResponse) {
+ MockGeneratedCodeCache mock_disk_cache;
+
+ // Equivalent to service worker calling respondWith(cache.match(some_url));
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+ response.SetCacheStorageCacheName("dummy");
+
+ SendDataFor(response, &mock_disk_cache);
+ EXPECT_EQ(0u, mock_disk_cache.CachedURLs().size());
+ EXPECT_EQ(1u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc
new file mode 100644
index 00000000000..a3dfe454e83
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc
@@ -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.
+
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h"
+
+#include "mojo/public/cpp/base/big_buffer.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+CodeCacheLoader::CodeCacheLoader(mojom::CodeCacheHost* code_cache_host)
+ : code_cache_host_(code_cache_host) {}
+
+CodeCacheLoader::~CodeCacheLoader() = default;
+
+void CodeCacheLoader::FetchFromCodeCache(mojom::CodeCacheType cache_type,
+ const WebURL& url,
+ FetchCodeCacheCallback callback) {
+ if (code_cache_host_) {
+ code_cache_host_->FetchCachedCode(cache_type,
+ static_cast<GURL>(static_cast<KURL>(url)),
+ std::move(callback));
+ } else {
+ // TODO(mythria): This path is required for workers currently. Once we
+ // update worker requests to go through WorkerHost remove this path.
+ Platform::Current()->FetchCachedCode(cache_type, url, std::move(callback));
+ }
+}
+
+// static
+std::unique_ptr<WebCodeCacheLoader> WebCodeCacheLoader::Create(
+ mojom::CodeCacheHost* code_cache_host) {
+ return std::make_unique<CodeCacheLoader>(code_cache_host);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h
new file mode 100644
index 00000000000..9cee9696653
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.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_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_LOADER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_LOADER_H_
+
+#include "third_party/blink/public/platform/web_code_cache_loader.h"
+
+namespace blink {
+
+// This class is loading V8 compilation code cache for scripts
+// (either separate script resources, or inline scripts in html file).
+// It is talking to the browser process and uses per-site isolated
+// cache backend to avoid cross-origin contamination.
+class BLINK_PLATFORM_EXPORT CodeCacheLoader : public WebCodeCacheLoader {
+ public:
+ // |code_cache_host| is the per-frame mojo interface that should be used when
+ // fetching code cache. If this value is nullptr it uses per-process
+ // interface.
+ // TODO(mythria): Remove the per-process interface and only expect non nullptr
+ // for |code_cache_host|.
+ explicit CodeCacheLoader(mojom::CodeCacheHost* code_cache_host);
+
+ ~CodeCacheLoader() override;
+
+ void FetchFromCodeCache(mojom::CodeCacheType cache_type,
+ const WebURL& url,
+ FetchCodeCacheCallback callback) override;
+
+ private:
+ mojom::CodeCacheHost* const code_cache_host_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER__FETCH_URL_LOADER_CODE_CACHE_LOADER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
index fc24a3d3d52..f8da1813e3e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
@@ -75,6 +75,8 @@ class DedicatedOrSharedWorkerFetchContextImpl::Factory
: WebURLLoaderFactory(std::move(loader_factory),
cors_exempt_header_list,
terminate_sync_load_event) {}
+ Factory(const Factory&) = delete;
+ Factory& operator=(const Factory&) = delete;
~Factory() override = default;
std::unique_ptr<WebURLLoader> CreateURLLoader(
@@ -154,7 +156,6 @@ class DedicatedOrSharedWorkerFetchContextImpl::Factory
scoped_refptr<network::SharedURLLoaderFactory> service_worker_loader_factory_;
base::WeakPtrFactory<Factory> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(Factory);
};
DedicatedOrSharedWorkerFetchContextImpl::
@@ -392,8 +393,9 @@ DedicatedOrSharedWorkerFetchContextImpl::WrapURLLoaderFactory(
}
std::unique_ptr<WebCodeCacheLoader>
-DedicatedOrSharedWorkerFetchContextImpl::CreateCodeCacheLoader() {
- return WebCodeCacheLoader::Create(terminate_sync_load_event_);
+DedicatedOrSharedWorkerFetchContextImpl::CreateCodeCacheLoader(
+ blink::mojom::CodeCacheHost* code_cache_host) {
+ return WebCodeCacheLoader::Create(code_cache_host);
}
void DedicatedOrSharedWorkerFetchContextImpl::WillSendRequest(
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h
index 8af76b3a81e..8bfe895ff93 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h
@@ -115,7 +115,8 @@ class BLINK_PLATFORM_EXPORT DedicatedOrSharedWorkerFetchContextImpl final
std::unique_ptr<WebURLLoaderFactory> WrapURLLoaderFactory(
CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase>
url_loader_factory) override;
- std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override;
+ std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader(
+ blink::mojom::CodeCacheHost*) override;
void WillSendRequest(WebURLRequest&) override;
mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
const override;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc
index b3c1fef3d25..ee814fd0306 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc
@@ -16,6 +16,7 @@
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom.h"
@@ -24,6 +25,7 @@
#include "third_party/blink/public/platform/web_resource_request_sender.h"
#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -31,20 +33,20 @@ namespace {
constexpr size_t kDefaultMaxBufferedBodyBytesPerRequest = 100 * 1000;
constexpr base::TimeDelta kGracePeriodToFinishLoadingWhileInBackForwardCache =
- base::TimeDelta::FromSeconds(15);
+ base::TimeDelta::FromSeconds(60);
} // namespace
class MojoURLLoaderClient::DeferredMessage {
public:
DeferredMessage() = default;
+ DeferredMessage(const DeferredMessage&) = delete;
+ DeferredMessage& operator=(const DeferredMessage&) = delete;
+ virtual ~DeferredMessage() = default;
+
virtual void HandleMessage(
WebResourceRequestSender* resource_request_sender) = 0;
virtual bool IsCompletionMessage() const = 0;
- virtual ~DeferredMessage() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeferredMessage);
};
class MojoURLLoaderClient::DeferredOnReceiveResponse final
@@ -193,7 +195,7 @@ class MojoURLLoaderClient::BodyBuffer final
"total_bytes_drained", static_cast<int>(total_bytes_drained_),
"added_bytes", static_cast<int>(num_bytes));
- if (owner_->IsDeferredWithBackForwardCache()) {
+ if (owner_->freeze_mode() == WebLoaderFreezeMode::kBufferIncoming) {
owner_->DidBufferLoadWhileInBackForwardCache(num_bytes);
if (total_bytes_drained_ > max_bytes_drained_ ||
!owner_->CanContinueBufferingWhileInBackForwardCache()) {
@@ -301,14 +303,15 @@ MojoURLLoaderClient::MojoURLLoaderClient(
MojoURLLoaderClient::~MojoURLLoaderClient() = default;
-void MojoURLLoaderClient::SetDefersLoading(WebURLLoader::DeferType value) {
- deferred_state_ = value;
- if (value == WebURLLoader::DeferType::kNotDeferred) {
+void MojoURLLoaderClient::Freeze(WebLoaderFreezeMode mode) {
+ freeze_mode_ = mode;
+ if (mode == WebLoaderFreezeMode::kNone) {
StopBackForwardCacheEvictionTimer();
task_runner_->PostTask(
FROM_HERE, WTF::Bind(&MojoURLLoaderClient::FlushDeferredMessages,
weak_factory_.GetWeakPtr()));
- } else if (IsDeferredWithBackForwardCache() && !has_received_complete_ &&
+ } else if (mode == WebLoaderFreezeMode::kBufferIncoming &&
+ !has_received_complete_ &&
!back_forward_cache_eviction_timer_.IsRunning()) {
// We should evict the page associated with this load if the connection
// takes too long until it either finished or failed.
@@ -383,8 +386,7 @@ void MojoURLLoaderClient::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr response_head) {
DCHECK(!has_received_response_head_);
- if (deferred_state_ ==
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
+ if (freeze_mode_ == WebLoaderFreezeMode::kBufferIncoming) {
EvictFromBackForwardCache(
blink::mojom::RendererEvictionReason::kNetworkRequestRedirected);
@@ -459,8 +461,7 @@ void MojoURLLoaderClient::OnStartLoadingResponseBody(
return;
}
- if (deferred_state_ !=
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
+ if (freeze_mode_ != WebLoaderFreezeMode::kBufferIncoming) {
// Defer the message, storing the original body pipe.
StoreAndDispatch(
std::make_unique<DeferredOnStartLoadingResponseBody>(std::move(body)));
@@ -504,7 +505,7 @@ void MojoURLLoaderClient::OnComplete(
}
bool MojoURLLoaderClient::NeedsStoringMessage() const {
- return deferred_state_ != WebURLLoader::DeferType::kNotDeferred ||
+ return freeze_mode_ != WebLoaderFreezeMode::kNone ||
deferred_messages_.size() > 0 ||
accumulated_transfer_size_diff_during_deferred_ > 0;
}
@@ -512,7 +513,7 @@ bool MojoURLLoaderClient::NeedsStoringMessage() const {
void MojoURLLoaderClient::StoreAndDispatch(
std::unique_ptr<DeferredMessage> message) {
DCHECK(NeedsStoringMessage());
- if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred) {
+ if (freeze_mode_ != WebLoaderFreezeMode::kNone) {
deferred_messages_.emplace_back(std::move(message));
} else if (deferred_messages_.size() > 0 ||
accumulated_transfer_size_diff_during_deferred_ > 0) {
@@ -532,7 +533,7 @@ void MojoURLLoaderClient::OnConnectionClosed() {
}
void MojoURLLoaderClient::FlushDeferredMessages() {
- if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred)
+ if (freeze_mode_ != WebLoaderFreezeMode::kNone)
return;
WebVector<std::unique_ptr<DeferredMessage>> messages;
messages.Swap(deferred_messages_);
@@ -554,7 +555,7 @@ void MojoURLLoaderClient::FlushDeferredMessages() {
messages[index]->HandleMessage(resource_request_sender_);
if (!weak_this)
return;
- if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred) {
+ if (freeze_mode_ != WebLoaderFreezeMode::kNone) {
deferred_messages_.reserve(messages.size() - index - 1);
for (size_t i = index + 1; i < messages.size(); ++i)
deferred_messages_.emplace_back(std::move(messages[i]));
@@ -569,7 +570,7 @@ void MojoURLLoaderClient::FlushDeferredMessages() {
resource_request_sender_->OnTransferSizeUpdated(transfer_size_diff);
if (!weak_this)
return;
- if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred) {
+ if (freeze_mode_ != WebLoaderFreezeMode::kNone) {
if (has_completion_message) {
DCHECK_GT(messages.size(), 0u);
DCHECK(messages.back()->IsCompletionMessage());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h
index bb8a6a5ae26..3832adcbc0c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h
@@ -19,7 +19,7 @@
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-forward.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/platform/web_loader_freeze_mode.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -52,9 +52,10 @@ class BLINK_PLATFORM_EXPORT MojoURLLoaderClient final
WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper);
~MojoURLLoaderClient() override;
- // Set the defer status. If loading is deferred, received messages are not
- // dispatched to clients until it is set not deferred.
- void SetDefersLoading(WebURLLoader::DeferType value);
+ // Freezes the loader. See blink/renderer/platform/loader/README.md for the
+ // general concept of "freezing" in the loading module. See
+ // blink/public/platform/web_loader_freezing_mode.h for `mode`.
+ void Freeze(WebLoaderFreezeMode mode);
// network::mojom::URLLoaderClient implementation
void OnReceiveEarlyHints(network::mojom::EarlyHintsPtr early_hints) override;
@@ -75,10 +76,7 @@ class BLINK_PLATFORM_EXPORT MojoURLLoaderClient final
void EvictFromBackForwardCache(blink::mojom::RendererEvictionReason reason);
void DidBufferLoadWhileInBackForwardCache(size_t num_bytes);
bool CanContinueBufferingWhileInBackForwardCache();
- bool IsDeferredWithBackForwardCache() {
- return deferred_state_ ==
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache;
- }
+ WebLoaderFreezeMode freeze_mode() const { return freeze_mode_; }
private:
class BodyBuffer;
@@ -109,8 +107,7 @@ class BLINK_PLATFORM_EXPORT MojoURLLoaderClient final
bool has_received_response_head_ = false;
bool has_received_response_body_ = false;
bool has_received_complete_ = false;
- WebURLLoader::DeferType deferred_state_ =
- WebURLLoader::DeferType::kNotDeferred;
+ WebLoaderFreezeMode freeze_mode_ = WebLoaderFreezeMode::kNone;
int32_t accumulated_transfer_size_diff_during_deferred_ = 0;
WebResourceRequestSender* const resource_request_sender_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
index 845184fedeb..d2f49dc7a24 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
@@ -53,8 +53,7 @@ class MockWebResourceRequestSender : public WebResourceRequestSender {
++context_->seen_redirects;
context_->last_load_timing = head->load_timing;
if (context_->defer_on_redirect) {
- context_->url_laoder_client->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferred);
+ context_->url_laoder_client->Freeze(WebLoaderFreezeMode::kStrict);
}
}
@@ -84,8 +83,7 @@ class MockWebResourceRequestSender : public WebResourceRequestSender {
return;
context_->total_encoded_data_length += transfer_size_diff;
if (context_->defer_on_transfer_size_updated) {
- context_->url_laoder_client->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferred);
+ context_->url_laoder_client->Freeze(WebLoaderFreezeMode::kStrict);
}
}
@@ -444,13 +442,13 @@ TEST_P(WebMojoURLLoaderClientTest, Defer) {
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
@@ -469,7 +467,7 @@ TEST_P(WebMojoURLLoaderClientTest, DeferWithResponseBody) {
EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
data_pipe_consumer));
std::string msg1 = "hello";
- uint32_t size = msg1.size();
+ uint32_t size = static_cast<uint32_t>(msg1.size());
ASSERT_EQ(MOJO_RESULT_OK, data_pipe_producer->WriteData(
msg1.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(msg1.size(), size);
@@ -482,14 +480,14 @@ TEST_P(WebMojoURLLoaderClientTest, DeferWithResponseBody) {
EXPECT_FALSE(context_->complete);
EXPECT_EQ("", GetRequestPeerContextBody(context_));
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
EXPECT_EQ("", GetRequestPeerContextBody(context_));
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
EXPECT_EQ("", GetRequestPeerContextBody(context_));
@@ -506,7 +504,7 @@ TEST_P(WebMojoURLLoaderClientTest,
return;
// Call OnReceiveResponse and OnStartLoadingResponseBody while
// deferred (not for back-forward cache).
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
@@ -520,7 +518,7 @@ TEST_P(WebMojoURLLoaderClientTest,
// Write data to the response body pipe.
std::string msg1 = "he";
- uint32_t size = msg1.size();
+ uint32_t size = static_cast<uint32_t>(msg1.size());
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
msg1.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(msg1.size(), size);
@@ -528,10 +526,9 @@ TEST_P(WebMojoURLLoaderClientTest,
EXPECT_EQ("", GetRequestPeerContextBody(context_));
// Defer for back-forward cache.
- client_->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ client_->Freeze(WebLoaderFreezeMode::kBufferIncoming);
std::string msg2 = "ll";
- size = msg2.size();
+ size = static_cast<uint32_t>(msg2.size());
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
msg2.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(msg2.size(), size);
@@ -539,10 +536,9 @@ TEST_P(WebMojoURLLoaderClientTest,
EXPECT_EQ("", GetRequestPeerContextBody(context_));
// Defer not for back-forward cache again.
- client_->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ client_->Freeze(WebLoaderFreezeMode::kBufferIncoming);
std::string msg3 = "o";
- size = msg3.size();
+ size = static_cast<uint32_t>(msg3.size());
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
msg3.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(msg3.size(), size);
@@ -550,7 +546,7 @@ TEST_P(WebMojoURLLoaderClientTest,
EXPECT_EQ("", GetRequestPeerContextBody(context_));
// Stop deferring.
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(context_->received_response);
EXPECT_FALSE(context_->complete);
@@ -558,7 +554,7 @@ TEST_P(WebMojoURLLoaderClientTest,
// Write more data to the pipe while not deferred.
std::string msg4 = "world";
- size = msg4.size();
+ size = static_cast<uint32_t>(msg4.size());
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
msg4.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(msg4.size(), size);
@@ -574,8 +570,7 @@ TEST_P(WebMojoURLLoaderClientTest,
return;
// Call OnReceiveResponse, OnStartLoadingResponseBody, OnComplete while
// deferred.
- client_->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ client_->Freeze(WebLoaderFreezeMode::kBufferIncoming);
url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
@@ -591,7 +586,7 @@ TEST_P(WebMojoURLLoaderClientTest,
// Write data to the response body pipe, but don't close the connection yet.
std::string msg1 = "hello";
- uint32_t size = msg1.size();
+ uint32_t size = static_cast<uint32_t>(msg1.size());
// We expect that the other end of the pipe to be ready to read the data
// immediately.
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
@@ -602,7 +597,7 @@ TEST_P(WebMojoURLLoaderClientTest,
// Stop deferring. OnComplete message shouldn't be dispatched yet because
// we're still waiting for the response body pipe to be closed.
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(context_->received_response);
// When the body is buffered, we'll wait until the pipe is closed before
@@ -612,7 +607,7 @@ TEST_P(WebMojoURLLoaderClientTest,
// Write more data to the pipe while not deferred.
std::string msg2 = "world";
- size = msg2.size();
+ size = static_cast<uint32_t>(msg2.size());
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
msg2.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(msg2.size(), size);
@@ -632,7 +627,7 @@ TEST_P(WebMojoURLLoaderClientTest,
TEST_P(WebMojoURLLoaderClientTest, DeferBodyWithoutOnComplete) {
url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
// Call OnStartLoadingResponseBody while deferred.
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
ASSERT_EQ(MOJO_RESULT_OK,
@@ -645,7 +640,7 @@ TEST_P(WebMojoURLLoaderClientTest, DeferBodyWithoutOnComplete) {
// Write data to the response body pipe, but don't close the connection yet.
std::string msg1 = "hello";
- uint32_t size = msg1.size();
+ uint32_t size = static_cast<uint32_t>(msg1.size());
// We expect that the other end of the pipe to be ready to read the data
// immediately.
ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
@@ -655,7 +650,7 @@ TEST_P(WebMojoURLLoaderClientTest, DeferBodyWithoutOnComplete) {
EXPECT_EQ("", GetRequestPeerContextBody(context_));
// Stop deferring.
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(context_->received_response);
EXPECT_FALSE(context_->complete);
@@ -675,8 +670,7 @@ TEST_P(WebMojoURLLoaderClientTest,
return;
// Call OnReceiveResponse, OnStartLoadingResponseBody, OnComplete while
// deferred.
- client_->SetDefersLoading(
- blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ client_->Freeze(WebLoaderFreezeMode::kBufferIncoming);
url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
@@ -716,7 +710,7 @@ TEST_P(WebMojoURLLoaderClientTest,
producer_handle.reset();
// Stop deferring.
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(context_->received_response);
// When the body is buffered, BodyBuffer shouldn't be finished writing to the
@@ -725,7 +719,7 @@ TEST_P(WebMojoURLLoaderClientTest,
// Calling GetRequestPeerContextBody to read data from the new response body
// pipe will make BodyBuffer write the rest of the body to the pipe.
- uint32_t bytes_read = 0;
+ size_t bytes_read = 0;
while (bytes_read < bytes_written) {
bytes_read = GetRequestPeerContextBody(context_).size();
base::RunLoop().RunUntilIdle();
@@ -763,7 +757,7 @@ TEST_P(WebMojoURLLoaderClientTest, DeferWithTransferSizeUpdated) {
EXPECT_EQ("", GetRequestPeerContextBody(context_));
EXPECT_EQ(0, context_->total_encoded_data_length);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(context_->received_response);
@@ -771,7 +765,7 @@ TEST_P(WebMojoURLLoaderClientTest, DeferWithTransferSizeUpdated) {
EXPECT_EQ("", GetRequestPeerContextBody(context_));
EXPECT_EQ(0, context_->total_encoded_data_length);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
EXPECT_EQ("", GetRequestPeerContextBody(context_));
@@ -815,7 +809,7 @@ TEST_P(WebMojoURLLoaderClientTest, SetDeferredDuringFlushingDeferredMessage) {
EXPECT_EQ("", GetRequestPeerContextBody(context_));
EXPECT_EQ(0, context_->total_encoded_data_length);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, context_->seen_redirects);
@@ -824,7 +818,7 @@ TEST_P(WebMojoURLLoaderClientTest, SetDeferredDuringFlushingDeferredMessage) {
EXPECT_EQ("", GetRequestPeerContextBody(context_));
EXPECT_EQ(0, context_->total_encoded_data_length);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
EXPECT_EQ(0, context_->seen_redirects);
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
@@ -839,7 +833,7 @@ TEST_P(WebMojoURLLoaderClientTest, SetDeferredDuringFlushingDeferredMessage) {
EXPECT_EQ(0, context_->total_encoded_data_length);
EXPECT_FALSE(context_->cancelled);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, context_->seen_redirects);
EXPECT_TRUE(context_->received_response);
@@ -871,14 +865,14 @@ TEST_P(WebMojoURLLoaderClientTest,
EXPECT_FALSE(context_->complete);
EXPECT_EQ(0, context_->total_encoded_data_length);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kStrict);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
EXPECT_EQ(0, context_->total_encoded_data_length);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
EXPECT_EQ(0, context_->total_encoded_data_length);
@@ -889,7 +883,7 @@ TEST_P(WebMojoURLLoaderClientTest,
EXPECT_EQ(4, context_->total_encoded_data_length);
EXPECT_FALSE(context_->cancelled);
- client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ client_->Freeze(WebLoaderFreezeMode::kNone);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(context_->received_response);
EXPECT_TRUE(context_->complete);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.cc
new file mode 100644
index 00000000000..90e64589551
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.cc
@@ -0,0 +1,377 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h"
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/strcat.h"
+#include "base/trace_event/trace_event.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/loader/referrer_utils.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/web_code_cache_loader.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/web/web_navigation_params.h"
+
+namespace blink {
+
+NavigationBodyLoader::NavigationBodyLoader(
+ const KURL& original_url,
+ network::mojom::URLResponseHeadPtr response_head,
+ mojo::ScopedDataPipeConsumerHandle response_body,
+ network::mojom::URLLoaderClientEndpointsPtr endpoints,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ bool is_main_frame)
+ : response_head_(std::move(response_head)),
+ response_body_(std::move(response_body)),
+ endpoints_(std::move(endpoints)),
+ task_runner_(std::move(task_runner)),
+ handle_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ task_runner_),
+ resource_load_info_notifier_wrapper_(
+ std::move(resource_load_info_notifier_wrapper)),
+ original_url_(original_url),
+ is_main_frame_(is_main_frame) {}
+
+NavigationBodyLoader::~NavigationBodyLoader() {
+ if (!has_received_completion_ || !has_seen_end_of_data_) {
+ resource_load_info_notifier_wrapper_->NotifyResourceLoadCanceled(
+ net::ERR_ABORTED);
+ }
+}
+
+void NavigationBodyLoader::OnReceiveEarlyHints(
+ network::mojom::EarlyHintsPtr early_hints) {
+ // This has already happened in the browser process.
+ NOTREACHED();
+}
+
+void NavigationBodyLoader::OnReceiveResponse(
+ network::mojom::URLResponseHeadPtr head) {
+ // This has already happened in the browser process.
+ NOTREACHED();
+}
+
+void NavigationBodyLoader::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head) {
+ // This has already happened in the browser process.
+ NOTREACHED();
+}
+
+void NavigationBodyLoader::OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) {
+ // This has already happened in the browser process.
+ NOTREACHED();
+}
+
+void NavigationBodyLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
+ // Even if IsolatedCodeCaching is landed, this code is still used by
+ // ServiceWorker.
+ // TODO(horo, kinuko): Make a test to cover this function.
+ // TODO(https://crbug.com/930000): Add support for inline script code caching
+ // with the service worker service.
+ client_->BodyCodeCacheReceived(std::move(data));
+}
+
+void NavigationBodyLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
+ resource_load_info_notifier_wrapper_->NotifyResourceTransferSizeUpdated(
+ transfer_size_diff);
+}
+
+void NavigationBodyLoader::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle handle) {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::OnStartLoadingResponseBody",
+ "url", original_url_.GetString().Utf8());
+ DCHECK(!has_received_body_handle_);
+ DCHECK(!has_received_completion_);
+ has_received_body_handle_ = true;
+ has_seen_end_of_data_ = false;
+ handle_ = std::move(handle);
+ DCHECK(handle_.is_valid());
+ handle_watcher_.Watch(handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+ base::BindRepeating(&NavigationBodyLoader::OnReadable,
+ base::Unretained(this)));
+ OnReadable(MOJO_RESULT_OK);
+}
+
+void NavigationBodyLoader::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ // Except for errors, there must always be a response's body.
+ DCHECK(has_received_body_handle_ || status.error_code != net::OK);
+ has_received_completion_ = true;
+ status_ = status;
+ NotifyCompletionIfAppropriate();
+}
+
+void NavigationBodyLoader::SetDefersLoading(WebLoaderFreezeMode mode) {
+ if (freeze_mode_ == mode)
+ return;
+ freeze_mode_ = mode;
+ if (handle_.is_valid())
+ OnReadable(MOJO_RESULT_OK);
+}
+
+void NavigationBodyLoader::StartLoadingBody(
+ WebNavigationBodyLoader::Client* client,
+ mojom::CodeCacheHost* code_cache_host) {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::StartLoadingBody", "url",
+ original_url_.GetString().Utf8());
+ client_ = client;
+
+ base::Time response_head_response_time = response_head_->response_time;
+ resource_load_info_notifier_wrapper_->NotifyResourceResponseReceived(
+ std::move(response_head_), PreviewsTypes::PREVIEWS_OFF);
+
+ if (code_cache_host) {
+ code_cache_loader_ = WebCodeCacheLoader::Create(code_cache_host);
+ code_cache_loader_->FetchFromCodeCache(
+ mojom::CodeCacheType::kJavascript, original_url_,
+ base::BindOnce(&NavigationBodyLoader::CodeCacheReceived,
+ weak_factory_.GetWeakPtr(), base::TimeTicks::Now(),
+ response_head_response_time));
+ return;
+ }
+
+ BindURLLoaderAndStartLoadingResponseBodyIfPossible();
+}
+
+void NavigationBodyLoader::CodeCacheReceived(
+ base::TimeTicks start_time,
+ base::Time response_head_response_time,
+ base::Time response_time,
+ mojo_base::BigBuffer data) {
+ base::UmaHistogramTimes(
+ base::StrCat({"Navigation.CodeCacheTime.",
+ is_main_frame_ ? "MainFrame" : "Subframe"}),
+ base::TimeTicks::Now() - start_time);
+ // Check that the times match to ensure that the code cache data is for this
+ // response. See https://crbug.com/1099587.
+ if (response_head_response_time == response_time && client_) {
+ base::WeakPtr<NavigationBodyLoader> weak_self = weak_factory_.GetWeakPtr();
+ client_->BodyCodeCacheReceived(std::move(data));
+ if (!weak_self)
+ return;
+ }
+ code_cache_loader_.reset();
+
+ // TODO(dgozman): we should explore retrieveing code cache in parallel with
+ // receiving response or reading the first data chunk.
+ BindURLLoaderAndStartLoadingResponseBodyIfPossible();
+}
+
+void NavigationBodyLoader::BindURLLoaderAndContinue() {
+ url_loader_.Bind(std::move(endpoints_->url_loader), task_runner_);
+ url_loader_client_receiver_.Bind(std::move(endpoints_->url_loader_client),
+ task_runner_);
+ url_loader_client_receiver_.set_disconnect_handler(base::BindOnce(
+ &NavigationBodyLoader::OnConnectionClosed, base::Unretained(this)));
+}
+
+void NavigationBodyLoader::OnConnectionClosed() {
+ // If the connection aborts before the load completes, mark it as failed.
+ if (!has_received_completion_)
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+}
+
+void NavigationBodyLoader::OnReadable(MojoResult unused) {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::OnReadable", "url",
+ original_url_.GetString().Utf8());
+ if (has_seen_end_of_data_ || freeze_mode_ != WebLoaderFreezeMode::kNone ||
+ is_in_on_readable_)
+ return;
+ // Protect against reentrancy:
+ // - when the client calls SetDefersLoading;
+ // - when nested message loop starts from BodyDataReceived
+ // and we get notified by the watcher.
+ // Note: we cannot use AutoReset here since |this| may be deleted
+ // before reset.
+ is_in_on_readable_ = true;
+ base::WeakPtr<NavigationBodyLoader> weak_self = weak_factory_.GetWeakPtr();
+ ReadFromDataPipe();
+ if (!weak_self)
+ return;
+ is_in_on_readable_ = false;
+}
+
+void NavigationBodyLoader::ReadFromDataPipe() {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::ReadFromDataPipe", "url",
+ original_url_.GetString().Utf8());
+ uint32_t num_bytes_consumed = 0;
+ while (freeze_mode_ == WebLoaderFreezeMode::kNone) {
+ const void* buffer = nullptr;
+ uint32_t available = 0;
+ MojoResult result =
+ handle_->BeginReadData(&buffer, &available, MOJO_READ_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ handle_watcher_.ArmOrNotify();
+ return;
+ }
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+ has_seen_end_of_data_ = true;
+ NotifyCompletionIfAppropriate();
+ return;
+ }
+ if (result != MOJO_RESULT_OK) {
+ status_.error_code = net::ERR_FAILED;
+ has_seen_end_of_data_ = true;
+ has_received_completion_ = true;
+ NotifyCompletionIfAppropriate();
+ return;
+ }
+ const uint32_t chunk_size = network::features::GetLoaderChunkSize();
+ DCHECK_LE(num_bytes_consumed, chunk_size);
+ available = std::min(available, chunk_size - num_bytes_consumed);
+ if (available == 0) {
+ // We've already consumed many bytes in this task. Defer the remaining
+ // to the next task.
+ result = handle_->EndReadData(0);
+ DCHECK_EQ(result, MOJO_RESULT_OK);
+ handle_watcher_.ArmOrNotify();
+ return;
+ }
+ num_bytes_consumed += available;
+ base::WeakPtr<NavigationBodyLoader> weak_self = weak_factory_.GetWeakPtr();
+ client_->BodyDataReceived(
+ base::make_span(static_cast<const char*>(buffer), available));
+ if (!weak_self)
+ return;
+ result = handle_->EndReadData(available);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ }
+}
+
+void NavigationBodyLoader::NotifyCompletionIfAppropriate() {
+ if (!has_received_completion_ || !has_seen_end_of_data_)
+ return;
+
+ handle_watcher_.Cancel();
+
+ absl::optional<WebURLError> error;
+ if (status_.error_code != net::OK) {
+ error = WebURLLoader::PopulateURLError(status_, original_url_);
+ }
+
+ resource_load_info_notifier_wrapper_->NotifyResourceLoadCompleted(status_);
+
+ if (!client_)
+ return;
+
+ // |this| may be deleted after calling into client_, so clear it in advance.
+ WebNavigationBodyLoader::Client* client = client_;
+ client_ = nullptr;
+ client->BodyLoadingFinished(
+ status_.completion_time, status_.encoded_data_length,
+ status_.encoded_body_length, status_.decoded_body_length,
+ status_.should_report_corb_blocking, error);
+}
+
+void NavigationBodyLoader::
+ BindURLLoaderAndStartLoadingResponseBodyIfPossible() {
+ // Bind the mojo::URLLoaderClient interface in advance, because we will start
+ // to read from the data pipe immediately which may potentially postpone the
+ // method calls from the remote. That causes the flakiness of some layout
+ // tests.
+ // TODO(minggang): The binding was executed after OnStartLoadingResponseBody
+ // originally (prior to passing the response body from the browser process
+ // during navigation), we should try to put it back if all the
+ // webkit_layout_tests can pass in that way.
+ BindURLLoaderAndContinue();
+
+ DCHECK(response_body_.is_valid());
+ OnStartLoadingResponseBody(std::move(response_body_));
+ // Don't use |this| here as it might have been destroyed.
+}
+
+// static
+void WebNavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
+ mojom::CommonNavigationParamsPtr common_params,
+ mojom::CommitNavigationParamsPtr commit_params,
+ int request_id,
+ network::mojom::URLResponseHeadPtr response_head,
+ mojo::ScopedDataPipeConsumerHandle response_body,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ bool is_main_frame,
+ WebNavigationParams* navigation_params) {
+ // Use the original navigation url to start with. We'll replay the
+ // redirects afterwards and will eventually arrive to the final url.
+ const KURL original_url = !commit_params->original_url.is_empty()
+ ? KURL(commit_params->original_url)
+ : KURL(common_params->url);
+ KURL url = original_url;
+ resource_load_info_notifier_wrapper->NotifyResourceLoadInitiated(
+ request_id, url,
+ !commit_params->original_method.empty() ? commit_params->original_method
+ : common_params->method,
+ common_params->referrer->url,
+ // TODO(kinuko): This should use the same value as in the request that
+ // was used in browser process, i.e. what CreateResourceRequest in
+ // content/browser/loader/navigation_url_loader_impl.cc gives.
+ // (Currently we don't propagate the value from the browser on
+ // navigation commit.)
+ is_main_frame ? network::mojom::RequestDestination::kDocument
+ : network::mojom::RequestDestination::kIframe,
+ is_main_frame ? net::HIGHEST : net::LOWEST);
+ size_t redirect_count = commit_params->redirect_response.size();
+
+ if (redirect_count != commit_params->redirects.size()) {
+ // We currently incorrectly send empty redirect_response and redirect_infos
+ // on frame reloads and some cases involving throttles.
+ // TODO(https://crbug.com/1171225): Fix this.
+ DCHECK_EQ(0u, redirect_count);
+ DCHECK_EQ(0u, commit_params->redirect_infos.size());
+ DCHECK_NE(0u, commit_params->redirects.size());
+ }
+ navigation_params->redirects.reserve(redirect_count);
+ navigation_params->redirects.resize(redirect_count);
+ for (size_t i = 0; i < redirect_count; ++i) {
+ WebNavigationParams::RedirectInfo& redirect =
+ navigation_params->redirects[i];
+ auto& redirect_info = commit_params->redirect_infos[i];
+ auto& redirect_response = commit_params->redirect_response[i];
+ WebURLLoader::PopulateURLResponse(
+ url, *redirect_response, &redirect.redirect_response,
+ response_head->ssl_info.has_value(), request_id);
+ resource_load_info_notifier_wrapper->NotifyResourceRedirectReceived(
+ redirect_info, std::move(redirect_response));
+ if (url.ProtocolIsData())
+ redirect.redirect_response.SetHttpStatusCode(200);
+ redirect.new_url = KURL(redirect_info.new_url);
+ redirect.new_referrer = WebString::FromUTF8(redirect_info.new_referrer);
+ redirect.new_referrer_policy = ReferrerUtils::NetToMojoReferrerPolicy(
+ redirect_info.new_referrer_policy);
+ redirect.new_http_method = WebString::FromLatin1(redirect_info.new_method);
+ url = KURL(redirect_info.new_url);
+ }
+
+ WebURLLoader::PopulateURLResponse(
+ url, *response_head, &navigation_params->response,
+ response_head->ssl_info.has_value(), request_id);
+ if (url.ProtocolIsData())
+ navigation_params->response.SetHttpStatusCode(200);
+
+ if (url_loader_client_endpoints) {
+ navigation_params->body_loader.reset(new NavigationBodyLoader(
+ original_url, std::move(response_head), std::move(response_body),
+ std::move(url_loader_client_endpoints), task_runner,
+ std::move(resource_load_info_notifier_wrapper), is_main_frame));
+ }
+}
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h
new file mode 100644
index 00000000000..d0582624619
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h
@@ -0,0 +1,171 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_NAVIGATION_BODY_LOADER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_NAVIGATION_BODY_LOADER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/base/big_buffer.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
+#include "third_party/blink/public/platform/web_loader_freeze_mode.h"
+#include "third_party/blink/public/platform/web_navigation_body_loader.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace network {
+struct URLLoaderCompletionStatus;
+} // namespace network
+
+namespace blink {
+
+class WebCodeCacheLoader;
+
+// Navigation request is started in the browser process, and all redirects
+// and final response are received there. Then we pass URLLoader and
+// URLLoaderClient bindings to the renderer process, and create an instance
+// of this class. It receives the response body, completion status and cached
+// metadata, and dispatches them to Blink. It also ensures that completion
+// status comes to Blink after the whole body was read and cached code metadata
+// was received.
+class NavigationBodyLoader : public WebNavigationBodyLoader,
+ public network::mojom::URLLoaderClient {
+ public:
+ NavigationBodyLoader(
+ const KURL& original_url,
+ network::mojom::URLResponseHeadPtr response_head,
+ mojo::ScopedDataPipeConsumerHandle response_body,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ bool is_main_frame);
+ ~NavigationBodyLoader() override;
+
+ private:
+ // The loading flow is outlined below. NavigationBodyLoader can be safely
+ // deleted at any moment, and it will record cancelation stats, but will not
+ // notify the client.
+ //
+ // StartLoadingBody
+ // request code cache
+ // CodeCacheReceived
+ // notify client about cache
+ // BindURLLoaderAndContinue
+ // OnStartLoadingResponseBody
+ // start reading from the pipe
+ // OnReadable (zero or more times)
+ // notify client about data
+ // OnComplete (this might come before the whole body data is read,
+ // for example due to different mojo pipes being used
+ // without a relative order guarantee)
+ // save status for later use
+ // OnReadable (zero or more times)
+ // notify client about data
+ // NotifyCompletionIfAppropriate
+ // notify client about completion
+
+ // WebNavigationBodyLoader implementation.
+ void SetDefersLoading(WebLoaderFreezeMode mode) override;
+ void StartLoadingBody(WebNavigationBodyLoader::Client* client,
+ mojom::CodeCacheHost* code_cache_host) override;
+
+ // network::mojom::URLLoaderClient implementation.
+ void OnReceiveEarlyHints(network::mojom::EarlyHintsPtr early_hints) override;
+ void OnReceiveResponse(
+ network::mojom::URLResponseHeadPtr response_head) override;
+ void OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr response_head) override;
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle handle) override;
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ void CodeCacheReceived(base::TimeTicks start_time,
+ base::Time response_head_response_time,
+ base::Time response_time,
+ mojo_base::BigBuffer data);
+ void BindURLLoaderAndContinue();
+ void OnConnectionClosed();
+ void OnReadable(MojoResult unused);
+ // This method reads data from the pipe in a cycle and dispatches
+ // BodyDataReceived synchronously.
+ void ReadFromDataPipe();
+ void NotifyCompletionIfAppropriate();
+ void BindURLLoaderAndStartLoadingResponseBodyIfPossible();
+
+ NavigationBodyLoader& operator=(const NavigationBodyLoader&) = delete;
+ NavigationBodyLoader(const NavigationBodyLoader&) = delete;
+
+ // Navigation parameters.
+ network::mojom::URLResponseHeadPtr response_head_;
+ mojo::ScopedDataPipeConsumerHandle response_body_;
+ network::mojom::URLLoaderClientEndpointsPtr endpoints_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // These bindings are live while loading the response.
+ mojo::Remote<network::mojom::URLLoader> url_loader_;
+ mojo::Receiver<network::mojom::URLLoaderClient> url_loader_client_receiver_{
+ this};
+ WebNavigationBodyLoader::Client* client_ = nullptr;
+
+ // The handle and watcher are live while loading the body.
+ mojo::ScopedDataPipeConsumerHandle handle_;
+ mojo::SimpleWatcher handle_watcher_;
+
+ // This loader is live while retrieving the code cache.
+ std::unique_ptr<WebCodeCacheLoader> code_cache_loader_;
+
+ // Used to notify the navigation loading stats.
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper_;
+
+ // The final status received from network or cancelation status if aborted.
+ network::URLLoaderCompletionStatus status_;
+
+ // Whether we got the body handle to read data from.
+ bool has_received_body_handle_ = false;
+ // Whether we got the final status.
+ bool has_received_completion_ = false;
+ // Whether we got all the body data.
+ bool has_seen_end_of_data_ = false;
+
+ // Frozen body loader does not send any notifications to the client
+ // and tries not to read from the body pipe.
+ WebLoaderFreezeMode freeze_mode_ = WebLoaderFreezeMode::kNone;
+
+ // This protects against reentrancy into OnReadable,
+ // which can happen due to nested message loop triggered
+ // from iniside BodyDataReceived client notification.
+ bool is_in_on_readable_ = false;
+
+ // The original navigation url to start with.
+ const KURL original_url_;
+
+ const bool is_main_frame_;
+
+ base::WeakPtrFactory<NavigationBodyLoader> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_NAVIGATION_BODY_LOADER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc
new file mode 100644
index 00000000000..dd842dcfd3a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc
@@ -0,0 +1,355 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader.h"
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/cert/x509_util.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "net/test/cert_test_util.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/navigation/navigation_params.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_navigation_body_loader.h"
+#include "third_party/blink/public/web/web_navigation_params.h"
+
+namespace blink {
+
+namespace {
+
+class NavigationBodyLoaderTest : public ::testing::Test,
+ public WebNavigationBodyLoader::Client {
+ protected:
+ NavigationBodyLoaderTest() {}
+
+ ~NavigationBodyLoaderTest() override { base::RunLoop().RunUntilIdle(); }
+
+ MojoCreateDataPipeOptions CreateDataPipeOptions() {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = 1024;
+ return options;
+ }
+
+ void CreateBodyLoader() {
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ MojoCreateDataPipeOptions options = CreateDataPipeOptions();
+ ASSERT_EQ(mojo::CreateDataPipe(&options, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+
+ writer_ = std::move(producer_handle);
+ auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
+ endpoints->url_loader_client = client_remote_.BindNewPipeAndPassReceiver();
+ WebNavigationParams navigation_params;
+ navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
+ auto common_params = CreateCommonNavigationParams();
+ auto commit_params = CreateCommitNavigationParams();
+ WebNavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
+ std::move(common_params), std::move(commit_params), /*request_id=*/1,
+ network::mojom::URLResponseHead::New(), std::move(consumer_handle),
+ std::move(endpoints), scheduler::GetSingleThreadTaskRunnerForTesting(),
+ std::make_unique<ResourceLoadInfoNotifierWrapper>(
+ /*resource_load_info_notifier=*/nullptr),
+ /*is_main_frame=*/true, &navigation_params);
+ loader_ = std::move(navigation_params.body_loader);
+ }
+
+ void StartLoading() {
+ loader_->StartLoadingBody(this, nullptr /*code_cache_host*/);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void Write(const std::string& buffer) {
+ uint32_t size = static_cast<uint32_t>(buffer.size());
+ MojoResult result = writer_->WriteData(buffer.c_str(), &size, kNone);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ ASSERT_EQ(buffer.size(), size);
+ }
+
+ void Complete(int net_error) {
+ client_remote_->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void BodyCodeCacheReceived(mojo_base::BigBuffer data) override {}
+
+ void BodyDataReceived(base::span<const char> data) override {
+ ASSERT_TRUE(expecting_data_received_);
+ did_receive_data_ = true;
+ data_received_ += std::string(data.data(), data.size());
+ TakeActions();
+ if (run_loop_.running())
+ run_loop_.Quit();
+ }
+
+ void BodyLoadingFinished(base::TimeTicks completion_time,
+ int64_t total_encoded_data_length,
+ int64_t total_encoded_body_length,
+ int64_t total_decoded_body_length,
+ bool should_report_corb_blocking,
+ const absl::optional<WebURLError>& error) override {
+ ASSERT_TRUE(expecting_finished_);
+ did_finish_ = true;
+ error_ = error;
+ TakeActions();
+ if (run_loop_.running())
+ run_loop_.Quit();
+ }
+
+ void TakeActions() {
+ if (!buffer_to_write_.empty()) {
+ std::string buffer = buffer_to_write_;
+ buffer_to_write_ = std::string();
+ ExpectDataReceived();
+ Write(buffer);
+ }
+ if (toggle_defers_loading_) {
+ toggle_defers_loading_ = false;
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kNone);
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kStrict);
+ }
+ if (destroy_loader_) {
+ destroy_loader_ = false;
+ loader_.reset();
+ }
+ }
+
+ void ExpectDataReceived() {
+ expecting_data_received_ = true;
+ did_receive_data_ = false;
+ }
+
+ void ExpectFinished() {
+ expecting_finished_ = true;
+ did_finish_ = false;
+ }
+
+ std::string TakeDataReceived() {
+ std::string data = data_received_;
+ data_received_ = std::string();
+ return data;
+ }
+
+ void Wait() {
+ if (expecting_data_received_) {
+ if (!did_receive_data_)
+ run_loop_.Run();
+ ASSERT_TRUE(did_receive_data_);
+ expecting_data_received_ = false;
+ }
+ if (expecting_finished_) {
+ if (!did_finish_)
+ run_loop_.Run();
+ ASSERT_TRUE(did_finish_);
+ expecting_finished_ = false;
+ }
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
+ mojo::Remote<network::mojom::URLLoaderClient> client_remote_;
+ std::unique_ptr<WebNavigationBodyLoader> loader_;
+ mojo::ScopedDataPipeProducerHandle writer_;
+
+ base::RunLoop run_loop_;
+ bool expecting_data_received_ = false;
+ bool did_receive_data_ = false;
+ bool expecting_finished_ = false;
+ bool did_finish_ = false;
+ std::string buffer_to_write_;
+ bool toggle_defers_loading_ = false;
+ bool destroy_loader_ = false;
+ std::string data_received_;
+ absl::optional<WebURLError> error_;
+};
+
+TEST_F(NavigationBodyLoaderTest, SetDefersBeforeStart) {
+ CreateBodyLoader();
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kStrict);
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kNone);
+ // Should not crash.
+}
+
+TEST_F(NavigationBodyLoaderTest, DataReceived) {
+ CreateBodyLoader();
+ StartLoading();
+ ExpectDataReceived();
+ Write("hello");
+ Wait();
+ EXPECT_EQ("hello", TakeDataReceived());
+}
+
+TEST_F(NavigationBodyLoaderTest, DataReceivedFromDataReceived) {
+ CreateBodyLoader();
+ StartLoading();
+ ExpectDataReceived();
+ buffer_to_write_ = "world";
+ Write("hello");
+ Wait();
+ EXPECT_EQ("helloworld", TakeDataReceived());
+}
+
+TEST_F(NavigationBodyLoaderTest, DestroyFromDataReceived) {
+ CreateBodyLoader();
+ StartLoading();
+ ExpectDataReceived();
+ destroy_loader_ = false;
+ Write("hello");
+ Wait();
+ EXPECT_EQ("hello", TakeDataReceived());
+}
+
+TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromDataReceived) {
+ CreateBodyLoader();
+ StartLoading();
+ ExpectDataReceived();
+ toggle_defers_loading_ = true;
+ Write("hello");
+ Wait();
+ EXPECT_EQ("hello", TakeDataReceived());
+}
+
+TEST_F(NavigationBodyLoaderTest, StartDeferred) {
+ CreateBodyLoader();
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kStrict);
+ StartLoading();
+ Write("hello");
+ ExpectDataReceived();
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kNone);
+ Wait();
+ EXPECT_EQ("hello", TakeDataReceived());
+}
+
+TEST_F(NavigationBodyLoaderTest, StartDeferredWithBackForwardCache) {
+ CreateBodyLoader();
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kBufferIncoming);
+ StartLoading();
+ Write("hello");
+ ExpectDataReceived();
+ loader_->SetDefersLoading(WebLoaderFreezeMode::kNone);
+ Wait();
+ EXPECT_EQ("hello", TakeDataReceived());
+}
+
+TEST_F(NavigationBodyLoaderTest, OnCompleteThenClose) {
+ CreateBodyLoader();
+ StartLoading();
+ Complete(net::ERR_FAILED);
+ ExpectFinished();
+ writer_.reset();
+ Wait();
+ EXPECT_TRUE(error_.has_value());
+}
+
+TEST_F(NavigationBodyLoaderTest, DestroyFromOnCompleteThenClose) {
+ CreateBodyLoader();
+ StartLoading();
+ Complete(net::ERR_FAILED);
+ ExpectFinished();
+ destroy_loader_ = true;
+ writer_.reset();
+ Wait();
+ EXPECT_TRUE(error_.has_value());
+}
+
+TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromOnCompleteThenClose) {
+ CreateBodyLoader();
+ StartLoading();
+ Complete(net::ERR_FAILED);
+ ExpectFinished();
+ toggle_defers_loading_ = true;
+ writer_.reset();
+ Wait();
+ EXPECT_TRUE(error_.has_value());
+}
+
+TEST_F(NavigationBodyLoaderTest, CloseThenOnComplete) {
+ CreateBodyLoader();
+ StartLoading();
+ writer_.reset();
+ ExpectFinished();
+ Complete(net::ERR_FAILED);
+ Wait();
+ EXPECT_TRUE(error_.has_value());
+}
+
+TEST_F(NavigationBodyLoaderTest, DestroyFromCloseThenOnComplete) {
+ CreateBodyLoader();
+ StartLoading();
+ writer_.reset();
+ ExpectFinished();
+ destroy_loader_ = true;
+ Complete(net::ERR_FAILED);
+ Wait();
+ EXPECT_TRUE(error_.has_value());
+}
+
+TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromCloseThenOnComplete) {
+ CreateBodyLoader();
+ StartLoading();
+ writer_.reset();
+ ExpectFinished();
+ toggle_defers_loading_ = true;
+ Complete(net::ERR_FAILED);
+ Wait();
+ EXPECT_TRUE(error_.has_value());
+}
+
+// Tests that FillNavigationParamsResponseAndBodyLoader populates security
+// details on the response when they are present.
+TEST_F(NavigationBodyLoaderTest, FillResponseWithSecurityDetails) {
+ auto response = network::mojom::URLResponseHead::New();
+ response->ssl_info = net::SSLInfo();
+ net::CertificateList certs;
+ ASSERT_TRUE(net::LoadCertificateFiles(
+ {"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
+ ASSERT_EQ(2U, certs.size());
+
+ base::StringPiece cert0_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+ base::StringPiece cert1_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
+
+ response->ssl_info->cert =
+ net::X509Certificate::CreateFromDERCertChain({cert0_der, cert1_der});
+ net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+ &response->ssl_info->connection_status);
+
+ auto common_params = CreateCommonNavigationParams();
+ common_params->url = GURL("https://example.test");
+ auto commit_params = CreateCommitNavigationParams();
+
+ WebNavigationParams navigation_params;
+ navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
+ auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ MojoResult rv =
+ mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle);
+ ASSERT_EQ(MOJO_RESULT_OK, rv);
+ WebNavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
+ std::move(common_params), std::move(commit_params), /*request_id=*/1,
+ std::move(response), std::move(consumer_handle), std::move(endpoints),
+ scheduler::GetSingleThreadTaskRunnerForTesting(),
+ std::make_unique<ResourceLoadInfoNotifierWrapper>(
+ /*resource_load_info_notifier=*/nullptr),
+ /*is_main_frame=*/true, &navigation_params);
+ EXPECT_TRUE(
+ navigation_params.response.SecurityDetailsForTesting().has_value());
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
index 8584b3c5609..b8a8c7419bc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
@@ -63,6 +63,7 @@ const char* ImageAcceptHeader() {
namespace {
constexpr char kStylesheetAcceptHeader[] = "text/css,*/*;q=0.1";
+constexpr char kWebBundleAcceptHeader[] = "application/webbundle;v=b1";
// TODO(yhirano): Unify these with variables in
// content/public/common/content_constants.h.
@@ -365,7 +366,6 @@ void PopulateResourceRequest(const ResourceRequestHead& src,
dest->has_user_gesture = src.HasUserGesture();
dest->enable_load_timing = true;
dest->enable_upload_progress = src.ReportUploadProgress();
- dest->report_raw_headers = src.ReportRawHeaders();
// TODO(ryansturm): Remove dest->previews_state once it is no
// longer used in a network delegate. https://crbug.com/842233
dest->previews_state = static_cast<int>(src.GetPreviewsState());
@@ -410,6 +410,10 @@ void PopulateResourceRequest(const ResourceRequestHead& src,
network::mojom::RequestDestination::kImage) {
dest->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kAccept,
ImageAcceptHeader());
+ } else if (request_destination ==
+ network::mojom::RequestDestination::kWebBundle) {
+ dest->headers.SetHeader(net::HttpRequestHeaders::kAccept,
+ kWebBundleAcceptHeader);
} else {
// Calling SetHeaderIfMissing() instead of SetHeader() because JS can
// manually set an accept header on an XHR.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc
index eec248b7b95..1cfcb1c0a7a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
+#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
@@ -16,7 +18,7 @@ namespace {
// Structure holding cache metadata sent to the platform.
struct CacheMetadataEntry {
- CacheMetadataEntry(const WebURL& url,
+ CacheMetadataEntry(const GURL& url,
base::Time response_time,
const uint8_t* data,
wtf_size_t data_size)
@@ -24,30 +26,18 @@ struct CacheMetadataEntry {
this->data.Append(data, data_size);
}
- WebURL url;
+ GURL url;
base::Time response_time;
Vector<uint8_t> data;
};
-// Mock Platform implementation that provides basic crypto and caching.
-class SourceKeyedCachedMetadataHandlerMockPlatform final
- : public TestingPlatformSupportWithMockScheduler {
+// Mock GeneratedCodeCache implementation that provides basic caching.
+class MockGeneratedCodeCache {
public:
- SourceKeyedCachedMetadataHandlerMockPlatform() {}
- ~SourceKeyedCachedMetadataHandlerMockPlatform() override = default;
-
- void CacheMetadata(blink::mojom::CodeCacheType cache_type,
- const WebURL& url,
- base::Time response_time,
- const uint8_t* data,
- size_t data_size) override {
- cache_entries_.emplace_back(url, response_time, data,
- SafeCast<wtf_size_t>(data_size));
- }
-
bool HasCacheMetadataFor(const WebURL& url) {
+ GURL gurl = WebStringToGURL(url.GetString());
for (const CacheMetadataEntry& entry : cache_entries_) {
- if (entry.url == url) {
+ if (entry.url == gurl) {
return true;
}
}
@@ -56,27 +46,70 @@ class SourceKeyedCachedMetadataHandlerMockPlatform final
Vector<CacheMetadataEntry> GetCacheMetadatasFor(const WebURL& url) {
Vector<CacheMetadataEntry> url_entries;
+ GURL gurl = WebStringToGURL(url.GetString());
for (const CacheMetadataEntry& entry : cache_entries_) {
- if (entry.url == url) {
+ if (entry.url == gurl) {
url_entries.push_back(entry);
}
}
return url_entries;
}
+ void CacheMetadata(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ base::Time response_time,
+ const uint8_t* data,
+ size_t data_size) {
+ cache_entries_.emplace_back(url, response_time, data,
+ SafeCast<wtf_size_t>(data_size));
+ }
+
private:
Vector<CacheMetadataEntry> cache_entries_;
};
-// Mock CachedMetadataSender implementation that forwards data to the platform.
+class CodeCacheHostMockImpl : public blink::mojom::CodeCacheHost {
+ public:
+ CodeCacheHostMockImpl(MockGeneratedCodeCache* mock_disk_cache)
+ : mock_disk_cache_(mock_disk_cache) {}
+
+ private:
+ // blink::mojom::CodeCacheHost implementation.
+ void DidGenerateCacheableMetadata(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ base::Time expected_response_time,
+ mojo_base::BigBuffer data) override {
+ mock_disk_cache_->CacheMetadata(cache_type, url, expected_response_time,
+ data.data(), data.size());
+ }
+
+ void FetchCachedCode(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ FetchCachedCodeCallback) override {}
+ void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type,
+ const GURL& url) override {}
+ void DidGenerateCacheableMetadataInCacheStorage(
+ const GURL& url,
+ base::Time expected_response_time,
+ mojo_base::BigBuffer data,
+ const url::Origin& cache_storage_origin,
+ const std::string& cache_storage_cache_name) override {}
+
+ MockGeneratedCodeCache* mock_disk_cache_;
+};
+
+// Mock CachedMetadataSender implementation that forwards data to the
+// mock_disk_cache.
class MockCachedMetadataSender final : public CachedMetadataSender {
public:
MockCachedMetadataSender(KURL response_url) : response_url_(response_url) {}
- void Send(const uint8_t* data, size_t size) override {
- Platform::Current()->CacheMetadata(blink::mojom::CodeCacheType::kJavascript,
- response_url_, response_time_, data,
- size);
+ void Send(blink::mojom::CodeCacheHost* code_cache_host,
+ const uint8_t* data,
+ size_t size) override {
+ code_cache_host->DidGenerateCacheableMetadata(
+ blink::mojom::CodeCacheType::kJavascript, response_url_, response_time_,
+ mojo_base::BigBuffer(base::make_span(data, size)));
}
bool IsServedFromCacheStorage() override { return false; }
@@ -94,7 +127,7 @@ class MockCachedMetadataSender final : public CachedMetadataSender {
::testing::Message msg;
msg << failure_msg << " for " << actual_expression;
msg << "\n Expected: [" << expected.size() << "] { ";
- for (size_t i = 0; i < expected.size(); ++i) {
+ for (wtf_size_t i = 0; i < expected.size(); ++i) {
if (i > 0)
msg << ", ";
msg << std::hex << static_cast<int>(expected[i]);
@@ -129,7 +162,7 @@ class MockCachedMetadataSender final : public CachedMetadataSender {
actual);
}
const uint8_t* actual_data = actual->Data();
- for (size_t i = 0; i < expected.size(); ++i) {
+ for (wtf_size_t i = 0; i < expected.size(); ++i) {
if (actual_data[i] != expected[i]) {
return CachedMetadataFailure("Wrong data", actual_expression, expected,
actual);
@@ -146,8 +179,7 @@ class MockCachedMetadataSender final : public CachedMetadataSender {
TEST(SourceKeyedCachedMetadataHandlerTest,
HandlerForSource_InitiallyNonNullHandlersWithNullData) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
SourceKeyedCachedMetadataHandler* handler =
@@ -170,8 +202,11 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
TEST(SourceKeyedCachedMetadataHandlerTest,
HandlerForSource_OneHandlerSetOtherNull) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
SourceKeyedCachedMetadataHandler* handler =
@@ -187,7 +222,8 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
handler->HandlerForSource(source2);
Vector<uint8_t> data1 = {1, 2, 3};
- source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size());
+ source1_handler->SetCachedMetadata(code_cache_host.get(), 0xbeef,
+ data1.data(), data1.size());
EXPECT_NE(nullptr, source1_handler);
EXPECT_METADATA(data1, source1_handler->GetCachedMetadata(0xbeef));
@@ -197,8 +233,11 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
}
TEST(SourceKeyedCachedMetadataHandlerTest, HandlerForSource_BothHandlersSet) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
SourceKeyedCachedMetadataHandler* handler =
@@ -214,10 +253,12 @@ TEST(SourceKeyedCachedMetadataHandlerTest, HandlerForSource_BothHandlersSet) {
handler->HandlerForSource(source2);
Vector<uint8_t> data1 = {1, 2, 3};
- source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size());
+ source1_handler->SetCachedMetadata(code_cache_host.get(), 0xbeef,
+ data1.data(), data1.size());
Vector<uint8_t> data2 = {3, 4, 5, 6};
- source2_handler->SetCachedMetadata(0x5eed, data2.data(), data2.size());
+ source2_handler->SetCachedMetadata(code_cache_host.get(), 0x5eed,
+ data2.data(), data2.size());
EXPECT_NE(nullptr, source1_handler);
EXPECT_METADATA(data1, source1_handler->GetCachedMetadata(0xbeef));
@@ -227,27 +268,34 @@ TEST(SourceKeyedCachedMetadataHandlerTest, HandlerForSource_BothHandlersSet) {
}
TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_EmptyClearDoesSend) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
SourceKeyedCachedMetadataHandler* handler =
MakeGarbageCollected<SourceKeyedCachedMetadataHandler>(
WTF::TextEncoding(), std::make_unique<MockCachedMetadataSender>(url));
- // Clear and send to the platform
- handler->ClearCachedMetadata(CachedMetadataHandler::kClearPersistentStorage);
+ // Clear and send to the mock_disk_cache
+ handler->ClearCachedMetadata(code_cache_host.get(),
+ CachedMetadataHandler::kClearPersistentStorage);
- // Load from platform
+ // Load from mock_disk_cache
Vector<CacheMetadataEntry> cache_metadatas =
- platform->GetCacheMetadatasFor(url);
+ mock_disk_cache.GetCacheMetadatasFor(url);
EXPECT_EQ(1u, cache_metadatas.size());
}
TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_EachSetDoesSend) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
SourceKeyedCachedMetadataHandler* handler =
@@ -263,21 +311,26 @@ TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_EachSetDoesSend) {
handler->HandlerForSource(source2);
Vector<uint8_t> data1 = {1, 2, 3};
- source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size());
+ source1_handler->SetCachedMetadata(code_cache_host.get(), 0xbeef,
+ data1.data(), data1.size());
Vector<uint8_t> data2 = {3, 4, 5, 6};
- source2_handler->SetCachedMetadata(0x5eed, data2.data(), data2.size());
+ source2_handler->SetCachedMetadata(code_cache_host.get(), 0x5eed,
+ data2.data(), data2.size());
- // Load from platform
+ // Load from mock_disk_cache
Vector<CacheMetadataEntry> cache_metadatas =
- platform->GetCacheMetadatasFor(url);
+ mock_disk_cache.GetCacheMetadatasFor(url);
EXPECT_EQ(2u, cache_metadatas.size());
}
TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_SetWithNoSendDoesNotSend) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
SourceKeyedCachedMetadataHandler* handler =
@@ -294,22 +347,27 @@ TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_SetWithNoSendDoesNotSend) {
Vector<uint8_t> data1 = {1, 2, 3};
source1_handler->DisableSendToPlatformForTesting();
- source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size());
+ source1_handler->SetCachedMetadata(code_cache_host.get(), 0xbeef,
+ data1.data(), data1.size());
Vector<uint8_t> data2 = {3, 4, 5, 6};
- source2_handler->SetCachedMetadata(0x5eed, data2.data(), data2.size());
+ source2_handler->SetCachedMetadata(code_cache_host.get(), 0x5eed,
+ data2.data(), data2.size());
- // Load from platform
+ // Load from mock_disk_cache
Vector<CacheMetadataEntry> cache_metadatas =
- platform->GetCacheMetadatasFor(url);
+ mock_disk_cache.GetCacheMetadatasFor(url);
EXPECT_EQ(1u, cache_metadatas.size());
}
TEST(SourceKeyedCachedMetadataHandlerTest,
SerializeAndDeserialize_NoHandlersSet) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
WTF::String source1("source1");
@@ -320,16 +378,16 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
WTF::TextEncoding(),
std::make_unique<MockCachedMetadataSender>(url));
- // Clear and persist in the platform.
+ // Clear and persist in the mock_disk_cache.
handler->ClearCachedMetadata(
- CachedMetadataHandler::kClearPersistentStorage);
+ code_cache_host.get(), CachedMetadataHandler::kClearPersistentStorage);
}
- // Reload from platform
+ // Reload from mock_disk_cache
{
Vector<CacheMetadataEntry> cache_metadatas =
- platform->GetCacheMetadatasFor(url);
- // Use the last data received by the platform
+ mock_disk_cache.GetCacheMetadatasFor(url);
+ // Use the last data received by the mock_disk_cache
EXPECT_EQ(1u, cache_metadatas.size());
CacheMetadataEntry& last_cache_metadata = cache_metadatas[0];
@@ -356,8 +414,11 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
TEST(SourceKeyedCachedMetadataHandlerTest,
SerializeAndDeserialize_BothHandlersSet) {
- ScopedTestingPlatformSupport<SourceKeyedCachedMetadataHandlerMockPlatform>
- platform;
+ MockGeneratedCodeCache mock_disk_cache;
+
+ std::unique_ptr<blink::mojom::CodeCacheHost> code_cache_host =
+ std::make_unique<CodeCacheHostMockImpl>(
+ CodeCacheHostMockImpl(&mock_disk_cache));
KURL url("http://SourceKeyedCachedMetadataHandlerTest.com");
WTF::String source1("source1");
@@ -375,15 +436,17 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
SingleCachedMetadataHandler* source2_handler =
handler->HandlerForSource(source2);
- source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size());
- source2_handler->SetCachedMetadata(0x5eed, data2.data(), data2.size());
+ source1_handler->SetCachedMetadata(code_cache_host.get(), 0xbeef,
+ data1.data(), data1.size());
+ source2_handler->SetCachedMetadata(code_cache_host.get(), 0x5eed,
+ data2.data(), data2.size());
}
- // Reload from platform
+ // Reload from mock_disk_cache
{
Vector<CacheMetadataEntry> cache_metadatas =
- platform->GetCacheMetadatasFor(url);
- // Use the last data received by the platform
+ mock_disk_cache.GetCacheMetadatasFor(url);
+ // Use the last data received by the mock_disk_cache
EXPECT_EQ(2u, cache_metadatas.size());
CacheMetadataEntry& last_cache_metadata = cache_metadatas[1];
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
index 26ffb9b808c..452d4b0b7b0 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
@@ -172,8 +172,7 @@ bool SyncLoadContext::OnReceivedRedirect(
response_->head = std::move(head);
response_->redirect_info = redirect_info;
*context_for_redirect_ = this;
- resource_request_sender_->SetDefersLoading(
- WebURLLoader::DeferType::kDeferred);
+ resource_request_sender_->Freeze(WebLoaderFreezeMode::kStrict);
signals_->SignalRedirectOrResponseComplete();
return true;
}
@@ -187,8 +186,7 @@ void SyncLoadContext::FollowRedirect() {
response_->redirect_info = net::RedirectInfo();
*context_for_redirect_ = nullptr;
- resource_request_sender_->SetDefersLoading(
- WebURLLoader::DeferType::kNotDeferred);
+ resource_request_sender_->Freeze(WebLoaderFreezeMode::kNone);
}
void SyncLoadContext::CancelRedirect() {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
index c647845c7e8..3dcfe462f2a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_CONTEXT_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event_watcher.h"
#include "base/timer/timer.h"
@@ -14,11 +13,12 @@
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_request_peer.h"
#include "third_party/blink/public/platform/web_resource_request_sender.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_vector.h"
namespace base {
class WaitableEvent;
@@ -73,6 +73,8 @@ class BLINK_PLATFORM_EXPORT SyncLoadContext : public WebRequestPeer {
std::unique_ptr<ResourceLoadInfoNotifierWrapper>
resource_load_info_notifier_wrapper);
+ SyncLoadContext(const SyncLoadContext&) = delete;
+ SyncLoadContext& operator=(const SyncLoadContext&) = delete;
~SyncLoadContext() override;
void FollowRedirect();
@@ -145,8 +147,6 @@ class BLINK_PLATFORM_EXPORT SyncLoadContext : public WebRequestPeer {
class SignalHelper;
std::unique_ptr<SignalHelper> signals_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncLoadContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
index fc4310e85cc..bd932a55892 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
@@ -317,19 +317,17 @@ void WebResourceRequestSender::Cancel(
DeletePendingRequest(std::move(task_runner));
}
-void WebResourceRequestSender::SetDefersLoading(WebURLLoader::DeferType value) {
+void WebResourceRequestSender::Freeze(WebLoaderFreezeMode mode) {
if (!request_info_) {
DLOG(ERROR) << "unknown request";
return;
}
- if (value != WebURLLoader::DeferType::kNotDeferred) {
- request_info_->is_deferred = value;
- request_info_->url_loader_client->SetDefersLoading(value);
- } else if (request_info_->is_deferred !=
- WebURLLoader::DeferType::kNotDeferred) {
- request_info_->is_deferred = WebURLLoader::DeferType::kNotDeferred;
- request_info_->url_loader_client->SetDefersLoading(
- WebURLLoader::DeferType::kNotDeferred);
+ if (mode != WebLoaderFreezeMode::kNone) {
+ request_info_->freeze_mode = mode;
+ request_info_->url_loader_client->Freeze(mode);
+ } else if (request_info_->freeze_mode != WebLoaderFreezeMode::kNone) {
+ request_info_->freeze_mode = WebLoaderFreezeMode::kNone;
+ request_info_->url_loader_client->Freeze(WebLoaderFreezeMode::kNone);
FollowPendingRedirect(request_info_.get());
}
@@ -533,7 +531,7 @@ void WebResourceRequestSender::OnReceivedRedirect(
->NotifyResourceRedirectReceived(redirect_info,
std::move(response_head));
- if (request_info_->is_deferred == WebURLLoader::DeferType::kNotDeferred)
+ if (request_info_->freeze_mode == WebLoaderFreezeMode::kNone)
FollowPendingRedirect(request_info_.get());
} else {
Cancel(std::move(task_runner));
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
index 890db95c939..2d0c8c06f4f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
@@ -14,7 +14,6 @@
#include <vector>
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -77,6 +76,10 @@ class TestResourceRequestSenderDelegate
: public WebResourceRequestSenderDelegate {
public:
TestResourceRequestSenderDelegate() = default;
+ TestResourceRequestSenderDelegate(const TestResourceRequestSenderDelegate&) =
+ delete;
+ TestResourceRequestSenderDelegate& operator=(
+ const TestResourceRequestSenderDelegate&) = delete;
~TestResourceRequestSenderDelegate() override = default;
void OnRequestComplete() override {}
@@ -92,6 +95,8 @@ class TestResourceRequestSenderDelegate
public:
explicit WrapperPeer(scoped_refptr<WebRequestPeer> original_peer)
: original_peer_(std::move(original_peer)) {}
+ WrapperPeer(const WrapperPeer&) = delete;
+ WrapperPeer& operator=(const WrapperPeer&) = delete;
// WebRequestPeer overrides:
void OnUploadProgress(uint64_t position, uint64_t size) override {}
@@ -119,12 +124,7 @@ class TestResourceRequestSenderDelegate
scoped_refptr<WebRequestPeer> original_peer_;
network::mojom::URLResponseHeadPtr response_head_;
mojo::ScopedDataPipeConsumerHandle body_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(WrapperPeer);
};
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestResourceRequestSenderDelegate);
};
// A mock WebRequestPeer to receive messages from the WebResourceRequestSender.
@@ -331,7 +331,7 @@ TEST_F(WebResourceRequestSenderTest, DelegateTest) {
MOJO_RESULT_OK);
client->OnStartLoadingResponseBody(std::move(consumer_handle));
- uint32_t size = strlen(kTestPageContents);
+ uint32_t size = static_cast<uint32_t>(strlen(kTestPageContents));
auto result = producer_handle->WriteData(kTestPageContents, &size,
MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(result, MOJO_RESULT_OK);
@@ -377,7 +377,7 @@ TEST_F(WebResourceRequestSenderTest, CancelDuringCallbackWithWrapperPeer) {
ASSERT_EQ(mojo::CreateDataPipe(&options, producer_handle, consumer_handle),
MOJO_RESULT_OK);
client->OnStartLoadingResponseBody(std::move(consumer_handle));
- uint32_t size = strlen(kTestPageContents);
+ uint32_t size = static_cast<uint32_t>(strlen(kTestPageContents));
auto result = producer_handle->WriteData(kTestPageContents, &size,
MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(result, MOJO_RESULT_OK);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
index c346490cdf4..8a2b2c6b630 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
@@ -45,6 +45,7 @@
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
#include "services/network/public/cpp/http_raw_request_response_info.h"
+#include "services/network/public/cpp/ip_address_space_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
@@ -59,7 +60,6 @@
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
-#include "third_party/blink/public/common/net/ip_address_space_util.h"
#include "third_party/blink/public/common/security/security_style.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
@@ -72,7 +72,6 @@
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/public/platform/web_http_load_info.h"
#include "third_party/blink/public/platform/web_request_peer.h"
#include "third_party/blink/public/platform/web_resource_request_sender.h"
#include "third_party/blink/public/platform/web_security_origin.h"
@@ -344,7 +343,7 @@ class WebURLLoader::Context : public WebRequestPeer {
scoped_refptr<base::SingleThreadTaskRunner> GetMaybeUnfreezableTaskRunner();
void Cancel();
- void SetDefersLoading(WebURLLoader::DeferType value);
+ void Freeze(WebLoaderFreezeMode mode);
void DidChangePriority(WebURLRequest::Priority new_priority,
int intra_priority_value);
void Start(std::unique_ptr<network::ResourceRequest> request,
@@ -373,13 +372,6 @@ class WebURLLoader::Context : public WebRequestPeer {
std::unique_ptr<WebResourceRequestSender> resource_request_sender);
private:
- // The maximal number of bytes consumed in a task. When there are more bytes
- // in the data pipe, they will be consumed in following tasks. Setting a too
- // small number will generate ton of tasks but setting a too large number will
- // lead to thread janks. Also, some clients cannot handle too large chunks
- // (512k for example).
- static constexpr uint32_t kMaxNumConsumedBytesInTask = 64 * 1024;
-
~Context() override;
// Called when the body data stream is detached from the reader side.
@@ -394,13 +386,13 @@ class WebURLLoader::Context : public WebRequestPeer {
WebURLLoader* loader_;
KURL url_;
- // Controls SetSecurityStyleAndDetails() in PopulateURLResponse(). Initially
- // set to WebURLRequest::ReportRawHeaders() in Start() and gets updated in
- // WillFollowRedirect() (by the InspectorNetworkAgent) while the new
- // ReportRawHeaders() value won't be propagated to the browser process.
+ // This is set in Start() and is used by SetSecurityStyleAndDetails() to
+ // determine if security details should be added to the request for DevTools.
//
- // TODO(tyoshino): Investigate whether it's worth propagating the new value.
- bool report_raw_headers_;
+ // Additionally, if there is a redirect, WillFollowRedirect() will update this
+ // for the new request. InspectorNetworkAgent will have the chance to attach a
+ // DevTools request id to that new request, and it will propagate here.
+ bool has_devtools_request_id_;
WebURLLoaderClient* client_;
std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
@@ -417,7 +409,7 @@ class WebURLLoader::Context : public WebRequestPeer {
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner_;
mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle_;
- WebURLLoader::DeferType defers_loading_;
+ WebLoaderFreezeMode freeze_mode_ = WebLoaderFreezeMode::kNone;
const WebVector<WebString> cors_exempt_header_list_;
base::WaitableEvent* terminate_sync_load_event_;
@@ -436,9 +428,6 @@ class WebURLLoader::Context : public WebRequestPeer {
// WebURLLoader::Context -------------------------------------------------------
-// static
-constexpr uint32_t WebURLLoader::Context::kMaxNumConsumedBytesInTask;
-
WebURLLoader::Context::Context(
WebURLLoader* loader,
const WebVector<WebString>& cors_exempt_header_list,
@@ -451,7 +440,7 @@ WebURLLoader::Context::Context(
mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle,
WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
: loader_(loader),
- report_raw_headers_(false),
+ has_devtools_request_id_(false),
client_(nullptr),
freezable_task_runner_handle_(std::move(freezable_task_runner_handle)),
unfreezable_task_runner_handle_(
@@ -460,7 +449,6 @@ WebURLLoader::Context::Context(
unfreezable_task_runner_(
unfreezable_task_runner_handle_->GetTaskRunner()),
keep_alive_handle_(std::move(keep_alive_handle)),
- defers_loading_(WebURLLoader::DeferType::kNotDeferred),
cors_exempt_header_list_(cors_exempt_header_list),
terminate_sync_load_event_(terminate_sync_load_event),
request_id_(-1),
@@ -490,10 +478,10 @@ void WebURLLoader::Context::Cancel() {
loader_ = nullptr;
}
-void WebURLLoader::Context::SetDefersLoading(WebURLLoader::DeferType value) {
+void WebURLLoader::Context::Freeze(WebLoaderFreezeMode mode) {
if (request_id_ != -1)
- resource_request_sender_->SetDefersLoading(value);
- defers_loading_ = value;
+ resource_request_sender_->Freeze(mode);
+ freeze_mode_ = mode;
}
void WebURLLoader::Context::DidChangePriority(
@@ -527,7 +515,7 @@ void WebURLLoader::Context::Start(
freezable_task_runner_handle_->DidChangeRequestPriority(request->priority);
url_ = KURL(request->url);
- report_raw_headers_ = request->report_raw_headers;
+ has_devtools_request_id_ = request->devtools_request_id.has_value();
// TODO(horo): Check credentials flag is unset when credentials mode is omit.
// Check credentials flag is set when credentials mode is include.
@@ -592,7 +580,7 @@ void WebURLLoader::Context::Start(
}
if (sync_load_response) {
- DCHECK(defers_loading_ == WebURLLoader::DeferType::kNotDeferred);
+ DCHECK(freeze_mode_ == WebLoaderFreezeMode::kNone);
loader_options |= network::mojom::kURLLoadOptionSynchronous;
request->load_flags |= net::LOAD_IGNORE_LIMITS;
@@ -623,9 +611,8 @@ void WebURLLoader::Context::Start(
std::move(throttles), std::move(resource_load_info_notifier_wrapper),
back_forward_cache_loader_helper_);
- if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred) {
- resource_request_sender_->SetDefersLoading(
- WebURLLoader::DeferType::kDeferred);
+ if (freeze_mode_ != WebLoaderFreezeMode::kNone) {
+ resource_request_sender_->Freeze(WebLoaderFreezeMode::kStrict);
}
}
@@ -646,7 +633,8 @@ bool WebURLLoader::Context::OnReceivedRedirect(
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
WebURLResponse response;
- PopulateURLResponse(url_, *head, &response, report_raw_headers_, request_id_);
+ PopulateURLResponse(url_, *head, &response, has_devtools_request_id_,
+ request_id_);
url_ = KURL(redirect_info.new_url);
return client_->WillFollowRedirect(
@@ -654,7 +642,7 @@ bool WebURLLoader::Context::OnReceivedRedirect(
WebString::FromUTF8(redirect_info.new_referrer),
ReferrerUtils::NetToMojoReferrerPolicy(redirect_info.new_referrer_policy),
WebString::FromUTF8(redirect_info.new_method), response,
- report_raw_headers_, removed_headers);
+ has_devtools_request_id_, removed_headers);
}
void WebURLLoader::Context::OnReceivedResponse(
@@ -673,7 +661,8 @@ void WebURLLoader::Context::OnReceivedResponse(
DCHECK(!head->headers || !head->headers->HasHeader("clear-site-data"));
WebURLResponse response;
- PopulateURLResponse(url_, *head, &response, report_raw_headers_, request_id_);
+ PopulateURLResponse(url_, *head, &response, has_devtools_request_id_,
+ request_id_);
client_->DidReceiveResponse(response);
@@ -829,7 +818,7 @@ void WebURLLoader::PopulateURLResponse(
// answer.
//
// Implements: https://wicg.github.io/cors-rfc1918/#integration-html
- response->SetAddressSpace(CalculateResourceAddressSpace(
+ response->SetAddressSpace(network::CalculateResourceAddressSpace(
KURL(response->ResponseUrl()), head.remote_endpoint));
WebVector<WebString> cors_exposed_header_names(
@@ -871,30 +860,8 @@ void WebURLLoader::PopulateURLResponse(
response->SetLoadTiming(ToMojoLoadTiming(head.load_timing));
}
- if (head.raw_request_response_info.get()) {
- WebHTTPLoadInfo load_info;
-
- load_info.SetHTTPStatusCode(
- head.raw_request_response_info->http_status_code);
- load_info.SetHTTPStatusText(WebString::FromLatin1(
- head.raw_request_response_info->http_status_text));
-
- load_info.SetRequestHeadersText(WebString::FromLatin1(
- head.raw_request_response_info->request_headers_text));
- load_info.SetResponseHeadersText(WebString::FromLatin1(
- head.raw_request_response_info->response_headers_text));
- for (auto& header : head.raw_request_response_info->request_headers) {
- load_info.AddRequestHeader(WebString::FromLatin1(header->key),
- WebString::FromLatin1(header->value));
- }
- for (auto& header : head.raw_request_response_info->response_headers) {
- load_info.AddResponseHeader(WebString::FromLatin1(header->key),
- WebString::FromLatin1(header->value));
- }
- response->SetHTTPLoadInfo(load_info);
- }
-
response->SetAuthChallengeInfo(head.auth_challenge_info);
+ response->SetRequestIncludeCredentials(head.request_include_credentials);
const net::HttpResponseHeaders* headers = head.headers.get();
if (!headers)
@@ -984,7 +951,7 @@ void WebURLLoader::LoadSynchronously(
DCHECK(!context_->client());
context_->set_client(client);
- const bool report_raw_headers = request->report_raw_headers;
+ const bool has_devtools_request_id = request->devtools_request_id.has_value();
context_->Start(std::move(request), std::move(url_request_extra_data),
pass_response_pipe_to_client, no_mime_sniffing,
timeout_interval, &sync_load_response,
@@ -1018,7 +985,7 @@ void WebURLLoader::LoadSynchronously(
}
PopulateURLResponse(final_url, *sync_load_response.head, &response,
- report_raw_headers, context_->request_id());
+ has_devtools_request_id, context_->request_id());
encoded_data_length = sync_load_response.head->encoded_data_length;
encoded_body_length = sync_load_response.head->encoded_body_length;
if (sync_load_response.downloaded_blob) {
@@ -1058,9 +1025,9 @@ void WebURLLoader::Cancel() {
context_->Cancel();
}
-void WebURLLoader::SetDefersLoading(DeferType value) {
+void WebURLLoader::Freeze(WebLoaderFreezeMode mode) {
if (context_)
- context_->SetDefersLoading(value);
+ context_->Freeze(mode);
}
void WebURLLoader::DidChangePriority(WebURLRequest::Priority new_priority,
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
index 3ea13a94991..a93160990e2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
@@ -11,11 +11,11 @@
#include <vector>
#include "base/command_line.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
@@ -31,6 +31,7 @@
#include "net/test/cert_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
@@ -40,6 +41,7 @@
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#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_loader_freeze_mode.h"
#include "third_party/blink/public/platform/web_request_peer.h"
#include "third_party/blink/public/platform/web_resource_request_sender.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -66,6 +68,9 @@ const char kTestData[] = "blah!";
class MockResourceRequestSender : public WebResourceRequestSender {
public:
MockResourceRequestSender() = default;
+ MockResourceRequestSender(const MockResourceRequestSender&) = delete;
+ MockResourceRequestSender& operator=(const MockResourceRequestSender&) =
+ delete;
~MockResourceRequestSender() override = default;
// WebResourceRequestSender implementation:
@@ -120,10 +125,8 @@ class MockResourceRequestSender : public WebResourceRequestSender {
bool canceled() { return canceled_; }
- void SetDefersLoading(WebURLLoader::DeferType value) override {
- defers_loading_ = (value != WebURLLoader::DeferType::kNotDeferred);
- }
- bool defers_loading() const { return defers_loading_; }
+ void Freeze(WebLoaderFreezeMode mode) override { freeze_mode_ = mode; }
+ WebLoaderFreezeMode freeze_mode() const { return freeze_mode_; }
void set_sync_load_response(SyncLoadResponse&& sync_load_response) {
sync_load_response_ = std::move(sync_load_response);
@@ -132,15 +135,15 @@ class MockResourceRequestSender : public WebResourceRequestSender {
private:
scoped_refptr<WebRequestPeer> peer_;
bool canceled_ = false;
- bool defers_loading_ = false;
+ WebLoaderFreezeMode freeze_mode_ = WebLoaderFreezeMode::kNone;
SyncLoadResponse sync_load_response_;
-
- DISALLOW_COPY_AND_ASSIGN(MockResourceRequestSender);
};
class FakeURLLoaderFactory final : public network::mojom::URLLoaderFactory {
public:
FakeURLLoaderFactory() = default;
+ FakeURLLoaderFactory(const FakeURLLoaderFactory&) = delete;
+ FakeURLLoaderFactory& operator=(const FakeURLLoaderFactory&) = delete;
~FakeURLLoaderFactory() override = default;
void CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
@@ -157,9 +160,6 @@ class FakeURLLoaderFactory final : public network::mojom::URLLoaderFactory {
override {
NOTREACHED();
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FakeURLLoaderFactory);
};
class TestWebURLLoaderClient : public WebURLLoaderClient {
@@ -185,6 +185,9 @@ class TestWebURLLoaderClient : public WebURLLoaderClient {
did_receive_response_(false),
did_finish_(false) {}
+ TestWebURLLoaderClient(const TestWebURLLoaderClient&) = delete;
+ TestWebURLLoaderClient& operator=(const TestWebURLLoaderClient&) = delete;
+
~TestWebURLLoaderClient() override {
// During the deconstruction of the `loader_`, the request context will be
// released asynchronously and we must ensure that the request context has
@@ -302,8 +305,6 @@ class TestWebURLLoaderClient : public WebURLLoaderClient {
bool did_finish_;
absl::optional<WebURLError> error_;
WebURLResponse response_;
-
- DISALLOW_COPY_AND_ASSIGN(TestWebURLLoaderClient);
};
class WebURLLoaderTest : public testing::Test {
@@ -470,10 +471,10 @@ TEST_F(WebURLLoaderTest, DeleteOnFail) {
}
TEST_F(WebURLLoaderTest, DefersLoadingBeforeStart) {
- client()->loader()->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
- EXPECT_FALSE(sender()->defers_loading());
+ client()->loader()->Freeze(WebLoaderFreezeMode::kStrict);
+ EXPECT_EQ(sender()->freeze_mode(), WebLoaderFreezeMode::kNone);
DoStartAsyncRequest();
- EXPECT_TRUE(sender()->defers_loading());
+ EXPECT_EQ(sender()->freeze_mode(), WebLoaderFreezeMode::kStrict);
}
TEST_F(WebURLLoaderTest, ResponseIPEndpoint) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
index 1c1efe00432..ad6359c2bf9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
@@ -15,15 +16,14 @@
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.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_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_client.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
index e75f82f239c..2ed5e0d6c9f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
@@ -179,6 +179,8 @@ class WorkerMainScriptLoaderTest : public testing::Test {
const ResourceError&,
int64_t encoded_data_length,
IsInternalRequest));
+ MOCK_METHOD2(DidChangeRenderBlockingBehavior,
+ void(Resource* resource, const FetchParameters& params));
MOCK_METHOD1(EvictFromBackForwardCache,
void(blink::mojom::RendererEvictionReason));
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/frame_request_blocker.h b/chromium/third_party/blink/renderer/platform/loader/frame_request_blocker.h
index f362a9b13f1..9800a16d6e0 100644
--- a/chromium/third_party/blink/renderer/platform/loader/frame_request_blocker.h
+++ b/chromium/third_party/blink/renderer/platform/loader/frame_request_blocker.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FRAME_REQUEST_BLOCKER_H_
#include "base/atomic_ref_count.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list_threadsafe.h"
#include "third_party/blink/public/platform/web_frame_request_blocker.h"
@@ -18,6 +17,8 @@ namespace blink {
class FrameRequestBlocker final : public WebFrameRequestBlocker {
public:
FrameRequestBlocker();
+ FrameRequestBlocker(const FrameRequestBlocker&) = delete;
+ FrameRequestBlocker& operator=(const FrameRequestBlocker&) = delete;
// Block any new subresource requests.
void Block() override;
@@ -44,8 +45,6 @@ class FrameRequestBlocker final : public WebFrameRequestBlocker {
scoped_refptr<base::ObserverListThreadSafe<Client>> clients_;
base::AtomicRefCount blocked_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameRequestBlocker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/ftp_directory_listing.h b/chromium/third_party/blink/renderer/platform/loader/ftp_directory_listing.h
index 48673b93f10..c5f9bda28b5 100644
--- a/chromium/third_party/blink/renderer/platform/loader/ftp_directory_listing.h
+++ b/chromium/third_party/blink/renderer/platform/loader/ftp_directory_listing.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FTP_DIRECTORY_LISTING_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc b/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc
index 6a1a976b04f..cd7ca3c104e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/public/platform/internet_disconnected_web_url_loader.h"
#include "base/bind.h"
+#include "services/network/public/cpp/resource_request.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
@@ -77,7 +78,7 @@ void InternetDisconnectedWebURLLoader::LoadAsynchronously(
WebURLError(net::ERR_INTERNET_DISCONNECTED, KURL(request->url))));
}
-void InternetDisconnectedWebURLLoader::SetDefersLoading(DeferType defers) {}
+void InternetDisconnectedWebURLLoader::Freeze(WebLoaderFreezeMode) {}
void InternetDisconnectedWebURLLoader::DidChangePriority(
WebURLRequest::Priority,
diff --git a/chromium/third_party/blink/renderer/platform/loader/link_header_test.cc b/chromium/third_party/blink/renderer/platform/loader/link_header_test.cc
index ae0def9347a..7a74938d5dd 100644
--- a/chromium/third_party/blink/renderer/platform/loader/link_header_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/link_header_test.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/platform/loader/link_header.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc b/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
index a4887da5b3e..104ddf000a7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
@@ -33,23 +33,21 @@ void StaticDataNavigationBodyLoader::Finish() {
Continue();
}
-void StaticDataNavigationBodyLoader::SetDefersLoading(
- WebURLLoader::DeferType defers) {
- defers_loading_ = defers;
+void StaticDataNavigationBodyLoader::SetDefersLoading(LoaderFreezeMode mode) {
+ freeze_mode_ = mode;
Continue();
}
void StaticDataNavigationBodyLoader::StartLoadingBody(
WebNavigationBodyLoader::Client* client,
- bool use_isolated_code_cache) {
+ blink::mojom::CodeCacheHost* code_cache_host) {
DCHECK(!is_in_continue_);
client_ = client;
Continue();
}
void StaticDataNavigationBodyLoader::Continue() {
- if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred || !client_ ||
- is_in_continue_)
+ if (freeze_mode_ != LoaderFreezeMode::kNone || !client_ || is_in_continue_)
return;
// We don't want reentrancy in this method -
@@ -74,7 +72,7 @@ void StaticDataNavigationBodyLoader::Continue() {
return;
}
- if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred) {
+ if (freeze_mode_ != LoaderFreezeMode::kNone) {
is_in_continue_ = false;
return;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h b/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h
index 2bb84a785a8..115820035e4 100644
--- a/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h
@@ -5,9 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_STATIC_DATA_NAVIGATION_BODY_LOADER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_STATIC_DATA_NAVIGATION_BODY_LOADER_H_
-#include "base/containers/span.h"
#include "base/memory/weak_ptr.h"
#include "third_party/blink/public/platform/web_navigation_body_loader.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
@@ -26,17 +26,16 @@ class PLATFORM_EXPORT StaticDataNavigationBodyLoader
void Write(const SharedBuffer&);
void Finish();
- void SetDefersLoading(WebURLLoader::DeferType defers) override;
+ void SetDefersLoading(LoaderFreezeMode) override;
void StartLoadingBody(WebNavigationBodyLoader::Client*,
- bool use_isolated_code_cache) override;
+ blink::mojom::CodeCacheHost* host) override;
private:
void Continue();
scoped_refptr<SharedBuffer> data_;
WebNavigationBodyLoader::Client* client_ = nullptr;
- WebURLLoader::DeferType defers_loading_ =
- WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
bool sent_all_data_ = false;
bool received_all_data_ = false;
bool is_in_continue_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader_test.cc
index 2ff8b21589a..db4a7546325 100644
--- a/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader_test.cc
@@ -47,9 +47,9 @@ class StaticDataNavigationBodyLoaderTest
}
void TakeActions() {
- if (set_defers_loading_ != WebURLLoader::DeferType::kNotDeferred) {
- set_defers_loading_ = WebURLLoader::DeferType::kNotDeferred;
- loader_->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ if (freeze_mode_ != LoaderFreezeMode::kNone) {
+ freeze_mode_ = LoaderFreezeMode::kNone;
+ loader_->SetDefersLoading(LoaderFreezeMode::kStrict);
}
if (!buffer_to_write_.IsEmpty()) {
String buffer = buffer_to_write_;
@@ -74,21 +74,20 @@ class StaticDataNavigationBodyLoaderTest
bool expecting_finished_ = false;
bool did_finish_ = false;
String buffer_to_write_;
- WebURLLoader::DeferType set_defers_loading_ =
- WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
bool destroy_loader_ = false;
String data_received_;
};
TEST_F(StaticDataNavigationBodyLoaderTest, DataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
Write("hello");
EXPECT_EQ("hello", TakeDataReceived());
}
TEST_F(StaticDataNavigationBodyLoaderTest, WriteFromDataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
buffer_to_write_ = "world";
Write("hello");
@@ -97,30 +96,30 @@ TEST_F(StaticDataNavigationBodyLoaderTest, WriteFromDataReceived) {
TEST_F(StaticDataNavigationBodyLoaderTest,
SetDefersLoadingAndWriteFromDataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferred;
+ freeze_mode_ = LoaderFreezeMode::kStrict;
buffer_to_write_ = "world";
Write("hello");
EXPECT_EQ("hello", TakeDataReceived());
- loader_->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader_->SetDefersLoading(LoaderFreezeMode::kNone);
EXPECT_EQ("world", TakeDataReceived());
}
TEST_F(StaticDataNavigationBodyLoaderTest,
SetDefersLoadingWithBfcacheAndWriteFromDataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ freeze_mode_ = LoaderFreezeMode::kBufferIncoming;
buffer_to_write_ = "world";
Write("hello");
EXPECT_EQ("hello", TakeDataReceived());
- loader_->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader_->SetDefersLoading(LoaderFreezeMode::kNone);
EXPECT_EQ("world", TakeDataReceived());
}
TEST_F(StaticDataNavigationBodyLoaderTest, DestroyFromDataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
destroy_loader_ = false;
Write("hello");
@@ -128,9 +127,9 @@ TEST_F(StaticDataNavigationBodyLoaderTest, DestroyFromDataReceived) {
}
TEST_F(StaticDataNavigationBodyLoaderTest, SetDefersLoadingFromDataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferred;
+ freeze_mode_ = LoaderFreezeMode::kStrict;
Write("hello");
EXPECT_EQ("hello", TakeDataReceived());
Write("world");
@@ -139,9 +138,9 @@ TEST_F(StaticDataNavigationBodyLoaderTest, SetDefersLoadingFromDataReceived) {
TEST_F(StaticDataNavigationBodyLoaderTest,
SetDefersLoadingWithBfcacheFromDataReceived) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_data_received_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ freeze_mode_ = LoaderFreezeMode::kBufferIncoming;
Write("hello");
EXPECT_EQ("hello", TakeDataReceived());
Write("world");
@@ -151,7 +150,7 @@ TEST_F(StaticDataNavigationBodyLoaderTest,
TEST_F(StaticDataNavigationBodyLoaderTest, WriteThenStart) {
Write("hello");
expecting_data_received_ = true;
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
EXPECT_EQ("hello", TakeDataReceived());
expecting_finished_ = true;
loader_->Finish();
@@ -164,11 +163,11 @@ TEST_F(StaticDataNavigationBodyLoaderTest,
Write("hello");
loader_->Finish();
expecting_data_received_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferred;
- loader_->StartLoadingBody(this, false);
+ freeze_mode_ = LoaderFreezeMode::kStrict;
+ loader_->StartLoadingBody(this, nullptr);
EXPECT_EQ("hello", TakeDataReceived());
expecting_finished_ = true;
- loader_->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader_->SetDefersLoading(LoaderFreezeMode::kNone);
EXPECT_EQ("", TakeDataReceived());
EXPECT_TRUE(did_finish_);
}
@@ -178,36 +177,35 @@ TEST_F(StaticDataNavigationBodyLoaderTest,
Write("hello");
loader_->Finish();
expecting_data_received_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferredWithBackForwardCache;
- loader_->StartLoadingBody(this, false);
+ freeze_mode_ = LoaderFreezeMode::kBufferIncoming;
+ loader_->StartLoadingBody(this, nullptr);
EXPECT_EQ("hello", TakeDataReceived());
expecting_finished_ = true;
- loader_->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader_->SetDefersLoading(LoaderFreezeMode::kNone);
EXPECT_EQ("", TakeDataReceived());
EXPECT_TRUE(did_finish_);
}
TEST_F(StaticDataNavigationBodyLoaderTest, StartDeferred) {
- loader_->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
- loader_->StartLoadingBody(this, false);
+ loader_->SetDefersLoading(LoaderFreezeMode::kStrict);
+ loader_->StartLoadingBody(this, nullptr);
Write("hello");
expecting_data_received_ = true;
- loader_->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader_->SetDefersLoading(LoaderFreezeMode::kNone);
EXPECT_EQ("hello", TakeDataReceived());
}
TEST_F(StaticDataNavigationBodyLoaderTest, StartDeferredWithBackForwardCache) {
- loader_->SetDefersLoading(
- WebURLLoader::DeferType::kDeferredWithBackForwardCache);
- loader_->StartLoadingBody(this, false);
+ loader_->SetDefersLoading(LoaderFreezeMode::kBufferIncoming);
+ loader_->StartLoadingBody(this, nullptr);
Write("hello");
expecting_data_received_ = true;
- loader_->SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
+ loader_->SetDefersLoading(LoaderFreezeMode::kNone);
EXPECT_EQ("hello", TakeDataReceived());
}
TEST_F(StaticDataNavigationBodyLoaderTest, DestroyFromFinished) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_finished_ = true;
destroy_loader_ = true;
loader_->Finish();
@@ -215,18 +213,18 @@ TEST_F(StaticDataNavigationBodyLoaderTest, DestroyFromFinished) {
}
TEST_F(StaticDataNavigationBodyLoaderTest, SetDefersLoadingFromFinished) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_finished_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferred;
+ freeze_mode_ = LoaderFreezeMode::kStrict;
loader_->Finish();
EXPECT_TRUE(did_finish_);
}
TEST_F(StaticDataNavigationBodyLoaderTest,
SetDefersLoadingWithBfcacheFromFinished) {
- loader_->StartLoadingBody(this, false);
+ loader_->StartLoadingBody(this, nullptr);
expecting_finished_ = true;
- set_defers_loading_ = WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ freeze_mode_ = LoaderFreezeMode::kBufferIncoming;
loader_->Finish();
EXPECT_TRUE(did_finish_);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc
index 80c409e9594..46bf719b483 100644
--- a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc
index 2672fa5a827..8ab7e40ccb2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
+#include "base/cxx17_backports.h"
#include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/crypto.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h b/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h
index a797a8a6774..4969e24c945 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h
@@ -18,6 +18,9 @@ class FetchTestingPlatformSupport
: public TestingPlatformSupportWithMockScheduler {
public:
FetchTestingPlatformSupport();
+ FetchTestingPlatformSupport(const FetchTestingPlatformSupport&) = delete;
+ FetchTestingPlatformSupport& operator=(const FetchTestingPlatformSupport&) =
+ delete;
~FetchTestingPlatformSupport() override;
WebURLLoaderMockFactory* GetURLLoaderMockFactory();
@@ -27,8 +30,6 @@ class FetchTestingPlatformSupport
class FetchTestingWebURLLoaderMockFactory;
std::unique_ptr<WebURLLoaderMockFactory> url_loader_mock_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(FetchTestingPlatformSupport);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h b/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h
index 806f9847b9e..54d31b79fb8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h"
+#include "third_party/blink/renderer/platform/testing/code_cache_loader_mock.h"
namespace blink {
@@ -48,7 +49,7 @@ class TestLoaderFactory : public ResourceFetcher::LoaderFactory {
}
std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
- return Platform::Current()->CreateCodeCacheLoader();
+ return std::make_unique<CodeCacheLoaderMock>();
}
private:
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h b/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h
index c565a542a78..a424950a006 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h
@@ -7,6 +7,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
namespace blink {
@@ -44,9 +45,8 @@ class TestResourceFetcherProperties final : public ResourceFetcherProperties {
return service_worker_id_;
}
bool IsPaused() const override { return paused_; }
- WebURLLoader::DeferType DeferType() const override { return defer_type_; }
+ LoaderFreezeMode FreezeMode() const override { return freeze_mode_; }
bool IsDetached() const override { return false; }
- bool IsLoadDeferred() const override { return false; }
bool IsLoadComplete() const override { return load_complete_; }
bool ShouldBlockLoadingSubResource() const override {
return should_block_loading_sub_resource_;
@@ -62,6 +62,11 @@ class TestResourceFetcherProperties final : public ResourceFetcherProperties {
return IsMainFrame() ? 3 : 2;
}
+ scoped_refptr<SecurityOrigin> GetLitePageSubresourceRedirectOrigin()
+ const override {
+ return nullptr;
+ }
+
void SetIsMainFrame(bool value) { is_main_frame_ = value; }
void SetControllerServiceWorkerMode(ControllerServiceWorkerMode mode) {
service_worker_mode_ = mode;
@@ -84,7 +89,7 @@ class TestResourceFetcherProperties final : public ResourceFetcherProperties {
ControllerServiceWorkerMode::kNoController;
int64_t service_worker_id_ = 0;
bool paused_ = false;
- WebURLLoader::DeferType defer_type_ = WebURLLoader::DeferType::kNotDeferred;
+ LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
bool load_complete_ = false;
bool should_block_loading_sub_resource_ = false;
bool is_subframe_deprioritization_enabled_ = false;
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
deleted file mode 100644
index d9e77811c2b..00000000000
--- a/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc.
- *
- * 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_MAC_LOCAL_CURRENT_GRAPHICS_CONTEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MAC_LOCAL_CURRENT_GRAPHICS_CONTEXT_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/geometry/int_rect.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/allocator/allocator.h"
-
-@class NSGraphicsContext;
-
-namespace cc {
-class PaintCanvas;
-}
-
-namespace blink {
-class GraphicsContext;
-
-// This class automatically saves and restores the current NSGraphicsContext for
-// functions which call out into AppKit and rely on the currentContext being set
-class PLATFORM_EXPORT LocalCurrentGraphicsContext {
- STACK_ALLOCATED();
-
- public:
- LocalCurrentGraphicsContext(GraphicsContext&, const IntRect& dirty_rect);
- LocalCurrentGraphicsContext(cc::PaintCanvas*,
- float device_scale_factor,
- const IntRect& dirty_rect);
- ~LocalCurrentGraphicsContext();
- CGContextRef CgContext();
-
- private:
- cc::PaintCanvas* saved_canvas_;
- NSGraphicsContext* saved_ns_graphics_context_;
- bool did_set_graphics_context_;
- IntRect inflated_dirty_rect_;
- GraphicsContextCanvas graphics_context_canvas_;
-
- // Inflate an IntRect to account for any bleeding that would happen due to
- // anti-aliasing.
- IntRect InflateRectForAA(const IntRect&);
-
- DISALLOW_COPY_AND_ASSIGN(LocalCurrentGraphicsContext);
-};
-}
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MAC_LOCAL_CURRENT_GRAPHICS_CONTEXT_H_
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
deleted file mode 100644
index a1e83f15237..00000000000
--- a/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc.
- *
- * 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/platform/mac/local_current_graphics_context.h"
-
-#include <AppKit/NSGraphicsContext.h>
-#include "skia/ext/platform_canvas.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/skia/include/core/SkRegion.h"
-
-namespace blink {
-
-LocalCurrentGraphicsContext::LocalCurrentGraphicsContext(
- GraphicsContext& graphics_context,
- const IntRect& dirty_rect)
- : LocalCurrentGraphicsContext(graphics_context.Canvas(),
- graphics_context.DeviceScaleFactor(),
- dirty_rect) {}
-
-static const int kMaxDirtyRectPixelSize = 10000;
-
-static SkIRect LocalToClampedDeviceRect(cc::PaintCanvas* canvas,
- const IntRect& local) {
- const SkMatrix& matrix = canvas->getTotalMatrix();
- SkRect device;
- if (!matrix.mapRect(&device, local))
- return SkIRect();
- // Constrain the maximum size of what we paint to something reasonable. This
- // accordingly means we will not paint the entirety of truly huge native form
- // elements, which is deemed an acceptable tradeoff for this simple approach
- // to manage such an edge case.
- SkIRect idevice = device.roundOut();
- idevice.intersect(SkIRect::MakeXYWH(idevice.x(), idevice.y(),
- kMaxDirtyRectPixelSize,
- kMaxDirtyRectPixelSize));
- return idevice;
-}
-
-LocalCurrentGraphicsContext::LocalCurrentGraphicsContext(
- cc::PaintCanvas* canvas,
- float device_scale_factor,
- const IntRect& dirty_rect)
- : did_set_graphics_context_(false),
- inflated_dirty_rect_(InflateRectForAA(dirty_rect)),
- graphics_context_canvas_(
- canvas,
- LocalToClampedDeviceRect(canvas, inflated_dirty_rect_),
- device_scale_factor) {
- saved_canvas_ = canvas;
- canvas->save();
-
- CGContextRef cg_context = this->CgContext();
- if (cg_context == [[NSGraphicsContext currentContext] graphicsPort]) {
- saved_ns_graphics_context_ = 0;
- return;
- }
-
- saved_ns_graphics_context_ = [[NSGraphicsContext currentContext] retain];
- NSGraphicsContext* new_context =
- [NSGraphicsContext graphicsContextWithGraphicsPort:cg_context
- flipped:YES];
- [NSGraphicsContext setCurrentContext:new_context];
- did_set_graphics_context_ = true;
-}
-
-LocalCurrentGraphicsContext::~LocalCurrentGraphicsContext() {
- if (did_set_graphics_context_) {
- [NSGraphicsContext setCurrentContext:saved_ns_graphics_context_];
- [saved_ns_graphics_context_ release];
- }
-
- saved_canvas_->restore();
-}
-
-CGContextRef LocalCurrentGraphicsContext::CgContext() {
- // This synchronizes the CGContext to reflect the current SkCanvas state.
- // The implementation may not return the same CGContext each time.
- CGContextRef cg_context = graphics_context_canvas_.CgContext();
-
- return cg_context;
-}
-
-IntRect LocalCurrentGraphicsContext::InflateRectForAA(const IntRect& rect) {
- const int kMargin = 2;
- return IntRect(rect.X() - kMargin, rect.Y() - kMargin,
- rect.Width() + 2 * kMargin, rect.Height() + 2 * kMargin);
-}
-}
diff --git a/chromium/third_party/blink/renderer/platform/media/BUILD.gn b/chromium/third_party/blink/renderer/platform/media/BUILD.gn
new file mode 100644
index 00000000000..f37f498f7fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/BUILD.gn
@@ -0,0 +1,176 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//media/media_options.gni")
+
+# TODO(https://crbug.com/1198341): use blink_platform_sources once the code is
+# ported to Blink code conventions.
+component("media") {
+ visibility = [
+ # Note: this is here because web_media_player_impl_unittest.cc needs core
+ # and web, and platform should not depend on either.
+ "//third_party/blink/public/platform/media",
+ "//third_party/blink/renderer/core:unit_tests",
+ "//third_party/blink/renderer/platform/*",
+ ]
+ output_name = "blink_platform_media"
+ sources = [
+ "buffered_data_source_host_impl.cc",
+ "cache_util.cc",
+ "cache_util.h",
+ "cdm_result_promise.h",
+ "cdm_result_promise_helper.cc",
+ "cdm_result_promise_helper.h",
+ "cdm_session_adapter.cc",
+ "cdm_session_adapter.h",
+ "key_system_config_selector.cc",
+ "multi_buffer.cc",
+ "multi_buffer_reader.cc",
+ "multi_buffer_reader.h",
+ "new_session_cdm_result_promise.cc",
+ "new_session_cdm_result_promise.h",
+ "power_status_helper.cc",
+ "remote_playback_client_wrapper_impl.cc",
+ "resource_multi_buffer_data_provider.cc",
+ "resource_multi_buffer_data_provider.h",
+ "text_track_impl.cc",
+ "text_track_impl.h",
+ "url_index.cc",
+ "video_decode_stats_reporter.cc",
+ "video_decode_stats_reporter.h",
+ "video_frame_compositor.cc",
+ "web_content_decryption_module_access_impl.cc",
+ "web_content_decryption_module_access_impl.h",
+ "web_content_decryption_module_impl.cc",
+ "web_content_decryption_module_impl.h",
+ "web_content_decryption_module_session_impl.cc",
+ "web_content_decryption_module_session_impl.h",
+ "web_encrypted_media_client_impl.cc",
+ "web_inband_text_track_impl.cc",
+ "web_inband_text_track_impl.h",
+ "web_media_player_params.cc",
+ "web_media_source_impl.cc",
+ "web_media_source_impl.h",
+ "web_source_buffer_impl.cc",
+ "web_source_buffer_impl.h",
+ ]
+
+ configs +=
+ [ "//third_party/blink/renderer/platform:blink_platform_implementation" ]
+ deps = [
+ "//base",
+ "//cc",
+ "//components/viz/common",
+ "//media",
+ "//media:media_buildflags",
+ "//media:shared_memory_support",
+ "//media/mojo/mojom",
+ "//mojo/public/cpp/bindings",
+ "//net",
+ "//services/device/public/mojom",
+ "//services/network/public/cpp",
+ "//third_party/blink/public:blink",
+ "//third_party/blink/public/common",
+ "//third_party/blink/public/mojom:mojom_platform",
+ "//third_party/blink/renderer/platform:platform_export",
+ "//ui/gfx/geometry",
+ "//url",
+ ]
+
+ if (media_use_ffmpeg || !is_android) {
+ sources += [
+ "learning_experiment_helper.cc",
+ "multi_buffer_data_source.cc",
+ "smoothness_helper.cc",
+ "web_media_player_impl.cc",
+ ]
+ deps += [
+ "//media/learning/common",
+ "//media/learning/mojo/public/cpp",
+ "//media/remoting:remoting_constants",
+ "//third_party/blink/public/strings:strings_grit",
+ ]
+ }
+}
+
+source_set("unit_tests") {
+ visibility = [ "//third_party/blink/renderer/platform:*" ]
+ testonly = true
+
+ # TODO(https://crbug.com/1198341): enable this config once the code is ported
+ # to Blink code conventions.
+ #configs += [ "//third_party/blink/renderer/platform:blink_platform_config" ]
+ sources = [
+ "buffered_data_source_host_impl_unittest.cc",
+ "cache_util_unittest.cc",
+ "interval_map_unittest.cc",
+ "key_system_config_selector_unittest.cc",
+ "lru_unittest.cc",
+ "multi_buffer_unittest.cc",
+ "power_status_helper_unittest.cc",
+ "resource_multi_buffer_data_provider_unittest.cc",
+ "url_index_unittest.cc",
+ "video_decode_stats_reporter_unittest.cc",
+ "video_frame_compositor_unittest.cc",
+ "watch_time_reporter_unittest.cc",
+ ]
+ deps = [
+ ":media",
+ "//base",
+ "//base/test:test_support",
+ "//components/viz/common",
+ "//media",
+ "//media:test_support",
+ "//media/mojo/mojom",
+ "//mojo/public/cpp/bindings",
+ "//net",
+ "//services/device/public/mojom",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/blink/public:blink",
+ "//third_party/blink/public:test_headers",
+ "//third_party/blink/public/platform/media",
+ "//third_party/blink/renderer/platform:test_support",
+ ]
+
+ if (media_use_ffmpeg || !is_android) {
+ sources += [
+ "learning_experiment_helper_unittest.cc",
+ "multi_buffer_data_source_unittest.cc",
+ "smoothness_helper_unittest.cc",
+ ]
+ deps += [
+ "//media/learning/common",
+ "//services/network/public/mojom",
+ ]
+ }
+}
+
+source_set("test_support") {
+ visibility = [ "//third_party/blink/renderer/platform:test_support" ]
+ testonly = true
+ configs += [
+ "//third_party/blink/renderer:non_test_config",
+ # TODO(https://crbug.com/1198341): enable this config once the code is
+ # ported to Blink code conventions.
+ #"//third_party/blink/renderer/platform:blink_platform_config",
+ ]
+ sources = [
+ "testing/mock_resource_fetch_context.cc",
+ "testing/mock_resource_fetch_context.h",
+ "testing/mock_web_associated_url_loader.cc",
+ "testing/mock_web_associated_url_loader.h",
+ "testing/test_response_generator.cc",
+ "testing/test_response_generator.h",
+ ]
+ deps = [
+ "//base",
+ "//net",
+ "//testing/gmock",
+ "//third_party/blink/public:blink_headers",
+ "//third_party/blink/public/platform/media",
+ "//url",
+ ]
+ data = [ "//media/test/data/" ]
+}
diff --git a/chromium/third_party/blink/renderer/platform/media/DEPS b/chromium/third_party/blink/renderer/platform/media/DEPS
index c952b757622..91d7ee00d47 100644
--- a/chromium/third_party/blink/renderer/platform/media/DEPS
+++ b/chromium/third_party/blink/renderer/platform/media/DEPS
@@ -1,15 +1,53 @@
include_rules = [
- "+media/base/audio_timestamp_helper.h",
- "+media/base/bind_to_current_loop.h",
- "+media/base/media_log.h",
+ # Don't depend on platform/ and ./testing/.
+ "-third_party/blink/renderer/platform",
+ "-third_party/blink/renderer/platform/media/testing",
+
+ # Module.
+ "+third_party/blink/renderer/platform/media",
+
+ # Dependencies.
+ "+base/bind_post_task.h",
+ "+base/containers/circular_deque.h",
+ "+base/strings/string_number_conversions.h",
+ "+base/strings/utf_string_conversions.h",
+ "+base/task_runner.h",
+ "+base/task_runner_util.h",
+ "+cc/layers",
+ "+components/viz/common",
+ "+media/audio/null_audio_sink.h",
+ "+media/base",
+ "+media/capabilities/bucket_utility.h",
+ "+media/cdm",
+ "+media/filters",
+ "+media/learning/common",
+ "+media/learning/mojo/public/cpp",
+ "+media/media_buildflags.h",
+ "+media/mojo/mojom",
+ "+media/remoting/remoting_constants.h",
+ "+net/base/data_url.h",
+ "+net/base/net_errors.h",
+ "+net/http/http_byte_range.h",
+ "+net/http/http_version.h",
+ "+services/device/public/mojom",
+ "+third_party/blink/renderer/platform/platform_export.h",
+ "+third_party/blink/renderer/platform/weborigin",
+ "+third_party/blink/renderer/platform/wtf",
]
specific_include_rules = {
- "webaudiosourceprovider_impl_test.cc": [
- "+media/base/audio_parameters.h",
- "+media/base/fake_audio_render_callback.h",
- "+media/base/media_util.h",
- "+media/base/mock_audio_renderer_sink.h",
- ],
+ ".*_unittest.*": [
+ "+base/strings/string_split.h",
+ "+base/task/current_thread.h",
+ "+base/threading/thread.h",
+ "+components/viz/test",
+ "+media/mojo/services",
+ "+media/renderers",
+ "+gin/v8_initializer.h",
+ "+mojo/core/embedder/embedder.h",
+
+ # Allow test support dependencies.
+ "+third_party/blink/renderer/platform/media/testing",
+ ],
}
diff --git a/chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc b/chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc
new file mode 100644
index 00000000000..c4ea2a89b8d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc
@@ -0,0 +1,182 @@
+// 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/media/buffered_data_source_host_impl.h"
+
+#include "media/base/timestamp_constants.h"
+
+namespace blink {
+
+// We want a relatively small window for estimating bandwidth,
+// that way we don't need to worry too much about seeks and pause
+// throwing off the estimates.
+constexpr base::TimeDelta kDownloadHistoryWindowSeconds =
+ base::TimeDelta::FromSecondsD(10.0);
+
+// Limit the number of entries in the rate estimator queue.
+// 1024 entries should be more than enough.
+constexpr size_t kDownloadHistoryMaxEntries = 1024;
+
+// Just in case someone gives progress one byte at a time,
+// let's aggregate progress updates together until we reach
+// at least this many bytes.
+constexpr int64_t kDownloadHistoryMinBytesPerEntry = 1000;
+
+BufferedDataSourceHostImpl::BufferedDataSourceHostImpl(
+ base::RepeatingClosure progress_cb,
+ const base::TickClock* tick_clock)
+ : total_bytes_(0),
+ did_loading_progress_(false),
+ progress_cb_(std::move(progress_cb)),
+ tick_clock_(tick_clock) {}
+
+BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() = default;
+
+void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) {
+ total_bytes_ = total_bytes;
+}
+
+int64_t BufferedDataSourceHostImpl::UnloadedBytesInInterval(
+ const Interval<int64_t>& interval) const {
+ int64_t bytes = 0;
+ auto i = buffered_byte_ranges_.find(interval.begin);
+ while (i != buffered_byte_ranges_.end()) {
+ if (i.interval_begin() >= interval.end)
+ break;
+ if (!i.value()) {
+ Interval<int64_t> intersection = i.interval().Intersect(interval);
+ if (!intersection.Empty())
+ bytes += intersection.end - intersection.begin;
+ }
+ ++i;
+ }
+ return bytes;
+}
+
+void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start,
+ int64_t end) {
+ int64_t new_bytes = UnloadedBytesInInterval(Interval<int64_t>(start, end));
+ if (new_bytes > 0)
+ did_loading_progress_ = true;
+ buffered_byte_ranges_.SetInterval(start, end, 1);
+
+ base::TimeTicks now = tick_clock_->NowTicks();
+ int64_t bytes_so_far = 0;
+ if (!download_history_.empty())
+ bytes_so_far = download_history_.back().second;
+ bytes_so_far += new_bytes;
+
+ // If the difference between the last entry and the second to last entry is
+ // less than kDownloadHistoryMinBytesPerEntry, just overwrite the last entry.
+ if (download_history_.size() > 1 &&
+ download_history_.back().second - (download_history_.end() - 2)->second <
+ kDownloadHistoryMinBytesPerEntry) {
+ download_history_.back() = std::make_pair(now, bytes_so_far);
+ } else {
+ download_history_.emplace_back(now, bytes_so_far);
+ }
+ DCHECK_GE(download_history_.size(), 1u);
+ // Drop entries that are too old.
+ while (download_history_.size() > kDownloadHistoryMaxEntries ||
+ download_history_.back().first - download_history_.front().first >
+ kDownloadHistoryWindowSeconds) {
+ download_history_.pop_front();
+ }
+ progress_cb_.Run();
+}
+
+static base::TimeDelta TimeForByteOffset(int64_t byte_offset,
+ int64_t total_bytes,
+ base::TimeDelta duration) {
+ double position = static_cast<double>(byte_offset) / total_bytes;
+ // Snap to the beginning/end where the approximation can look especially bad.
+ if (position < 0.01)
+ return base::TimeDelta();
+ if (position > 0.99)
+ return duration;
+ return base::TimeDelta::FromMilliseconds(
+ static_cast<int64_t>(position * duration.InMilliseconds()));
+}
+
+void BufferedDataSourceHostImpl::AddBufferedTimeRanges(
+ media::Ranges<base::TimeDelta>* buffered_time_ranges,
+ base::TimeDelta media_duration) const {
+ DCHECK(media_duration != media::kNoTimestamp);
+ DCHECK(media_duration != media::kInfiniteDuration);
+ if (total_bytes_ && !buffered_byte_ranges_.empty()) {
+ for (const auto i : buffered_byte_ranges_) {
+ if (i.second) {
+ int64_t start = i.first.begin;
+ int64_t end = i.first.end;
+ buffered_time_ranges->Add(
+ TimeForByteOffset(start, total_bytes_, media_duration),
+ TimeForByteOffset(end, total_bytes_, media_duration));
+ }
+ }
+ }
+}
+
+bool BufferedDataSourceHostImpl::DidLoadingProgress() {
+ bool ret = did_loading_progress_;
+ did_loading_progress_ = false;
+ return ret;
+}
+
+double BufferedDataSourceHostImpl::DownloadRate() const {
+ // If the download history is really small, any estimate we make is going to
+ // be wildly inaccurate, so let's not make any estimates until we have more
+ // data.
+ if (download_history_.size() < 5)
+ return 0.0;
+
+ // The data we get is bursty, so we get multiple measuring points very close
+ // together. These bursts will often lead us to over-estimate the download
+ // rate. By iterating over the beginning of the time series and picking the
+ // data point that has the lowest download rate, we avoid over-estimating.
+ const double kVeryLargeRate = 1.0E20;
+ double download_rate = kVeryLargeRate;
+ for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) {
+ int64_t downloaded_bytes =
+ download_history_.back().second - download_history_[i].second;
+ base::TimeTicks now = tick_clock_->NowTicks();
+ base::TimeDelta download_time = now - download_history_[i].first;
+ if (download_time <= base::TimeDelta())
+ continue;
+ download_rate =
+ std::min(download_rate, downloaded_bytes / download_time.InSecondsF());
+ }
+ return download_rate == kVeryLargeRate ? 0.0 : download_rate;
+}
+
+bool BufferedDataSourceHostImpl::CanPlayThrough(
+ base::TimeDelta current_position,
+ base::TimeDelta media_duration,
+ double playback_rate) const {
+ DCHECK_GE(playback_rate, 0);
+ if (!total_bytes_ || media_duration <= base::TimeDelta() ||
+ media_duration == media::kInfiniteDuration) {
+ return false;
+ }
+ if (current_position > media_duration)
+ return true;
+
+ const int64_t byte_pos =
+ std::max<int64_t>(total_bytes_ * (current_position / media_duration), 0);
+ const int64_t unloaded_bytes =
+ UnloadedBytesInInterval(Interval<int64_t>(byte_pos, total_bytes_));
+ if (unloaded_bytes == 0)
+ return true;
+
+ double download_rate = DownloadRate();
+ return (download_rate > 0) &&
+ ((unloaded_bytes / download_rate) <
+ ((media_duration - current_position).InSecondsF() / playback_rate));
+}
+
+void BufferedDataSourceHostImpl::SetTickClockForTest(
+ const base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl_unittest.cc
new file mode 100644
index 00000000000..0c49f722664
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/buffered_data_source_host_impl_unittest.cc
@@ -0,0 +1,156 @@
+// 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/media/buffered_data_source_host_impl.h"
+
+#include "base/bind.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class BufferedDataSourceHostImplTest : public testing::Test {
+ public:
+ BufferedDataSourceHostImplTest()
+ : host_(base::BindRepeating(
+ &BufferedDataSourceHostImplTest::ProgressCallback,
+ base::Unretained(this)),
+ &clock_) {}
+ BufferedDataSourceHostImplTest(const BufferedDataSourceHostImplTest&) =
+ delete;
+ BufferedDataSourceHostImplTest& operator=(
+ const BufferedDataSourceHostImplTest&) = delete;
+
+ void Add() {
+ host_.AddBufferedTimeRanges(&ranges_, base::TimeDelta::FromSeconds(10));
+ }
+
+ void ProgressCallback() { progress_callback_calls_++; }
+
+ protected:
+ int progress_callback_calls_ = 0;
+ BufferedDataSourceHostImpl host_;
+ media::Ranges<base::TimeDelta> ranges_;
+ base::SimpleTestTickClock clock_;
+};
+
+TEST_F(BufferedDataSourceHostImplTest, Empty) {
+ EXPECT_FALSE(host_.DidLoadingProgress());
+ Add();
+ EXPECT_EQ(0u, ranges_.size());
+}
+
+TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges) {
+ host_.AddBufferedByteRange(10, 20);
+ host_.SetTotalBytes(100);
+ Add();
+ EXPECT_EQ(1u, ranges_.size());
+ EXPECT_EQ(base::TimeDelta::FromSeconds(1), ranges_.start(0));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(2), ranges_.end(0));
+}
+
+TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges_Merges) {
+ ranges_.Add(base::TimeDelta::FromSeconds(0), base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(10, 20);
+ host_.SetTotalBytes(100);
+ Add();
+ EXPECT_EQ(1u, ranges_.size());
+ EXPECT_EQ(base::TimeDelta::FromSeconds(0), ranges_.start(0));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(2), ranges_.end(0));
+}
+
+TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges_Snaps) {
+ host_.AddBufferedByteRange(5, 995);
+ host_.SetTotalBytes(1000);
+ Add();
+ EXPECT_EQ(1u, ranges_.size());
+ EXPECT_EQ(base::TimeDelta::FromSeconds(0), ranges_.start(0));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(10), ranges_.end(0));
+}
+
+TEST_F(BufferedDataSourceHostImplTest, SetTotalBytes) {
+ host_.AddBufferedByteRange(10, 20);
+ Add();
+ EXPECT_EQ(0u, ranges_.size());
+
+ host_.SetTotalBytes(100);
+ Add();
+ EXPECT_EQ(1u, ranges_.size());
+}
+
+TEST_F(BufferedDataSourceHostImplTest, DidLoadingProgress) {
+ host_.AddBufferedByteRange(10, 20);
+ EXPECT_TRUE(host_.DidLoadingProgress());
+ EXPECT_FALSE(host_.DidLoadingProgress());
+}
+
+TEST_F(BufferedDataSourceHostImplTest, CanPlayThrough) {
+ host_.SetTotalBytes(100000);
+ EXPECT_EQ(100000,
+ host_.UnloadedBytesInInterval(Interval<int64_t>(0, 100000)));
+ host_.AddBufferedByteRange(0, 10000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(10000, 20000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(20000, 30000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(30000, 40000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(40000, 50000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ EXPECT_EQ(50000, host_.UnloadedBytesInInterval(Interval<int64_t>(0, 100000)));
+ host_.AddBufferedByteRange(50000, 60000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(60000, 70000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(70000, 80000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ host_.AddBufferedByteRange(80000, 90000);
+ // Download rate is allowed to be estimated low, but not high.
+ EXPECT_LE(host_.DownloadRate(), 10000.0f);
+ EXPECT_GE(host_.DownloadRate(), 9000.0f);
+ EXPECT_EQ(10000, host_.UnloadedBytesInInterval(Interval<int64_t>(0, 100000)));
+ EXPECT_EQ(9, progress_callback_calls_);
+ // If the video is 0.1s we can't play through.
+ EXPECT_FALSE(host_.CanPlayThrough(base::TimeDelta(),
+ base::TimeDelta::FromSecondsD(0.01), 1.0));
+ // If the video is 1000s we can play through.
+ EXPECT_TRUE(host_.CanPlayThrough(base::TimeDelta(),
+ base::TimeDelta::FromSecondsD(1000.0), 1.0));
+ // No more downloads for 1000 seconds...
+ clock_.Advance(base::TimeDelta::FromSeconds(1000));
+ // Can't play through..
+ EXPECT_FALSE(host_.CanPlayThrough(base::TimeDelta(),
+ base::TimeDelta::FromSecondsD(100.0), 1.0));
+ host_.AddBufferedByteRange(90000, 100000);
+ clock_.Advance(base::TimeDelta::FromSeconds(1));
+ EXPECT_EQ(0, host_.UnloadedBytesInInterval(Interval<int64_t>(0, 100000)));
+
+ // Media is fully downloaded, so we can certainly play through, even if
+ // we only have 0.01 seconds to do it.
+ EXPECT_TRUE(host_.CanPlayThrough(base::TimeDelta(),
+ base::TimeDelta::FromSecondsD(0.01), 1.0));
+}
+
+TEST_F(BufferedDataSourceHostImplTest, CanPlayThroughSmallAdvances) {
+ host_.SetTotalBytes(20000);
+ EXPECT_EQ(20000, host_.UnloadedBytesInInterval(Interval<int64_t>(0, 20000)));
+ for (int j = 1; j <= 100; j++) {
+ host_.AddBufferedByteRange(0, j * 100);
+ clock_.Advance(base::TimeDelta::FromSecondsD(0.01));
+ }
+ // Download rate is allowed to be estimated low, but not high.
+ EXPECT_LE(host_.DownloadRate(), 10000.0f);
+ EXPECT_GE(host_.DownloadRate(), 9000.0f);
+ EXPECT_EQ(10000, host_.UnloadedBytesInInterval(Interval<int64_t>(0, 20000)));
+ EXPECT_EQ(100, progress_callback_calls_);
+ // If the video is 0.1s we can't play through.
+ EXPECT_FALSE(host_.CanPlayThrough(base::TimeDelta(),
+ base::TimeDelta::FromSecondsD(0.01), 1.0));
+ // If the video is 1000s we can play through.
+ EXPECT_TRUE(host_.CanPlayThrough(base::TimeDelta(),
+ base::TimeDelta::FromSecondsD(1000.0), 1.0));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/cache_util.cc b/chromium/third_party/blink/renderer/platform/media/cache_util.cc
new file mode 100644
index 00000000000..ec24b249475
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cache_util.cc
@@ -0,0 +1,129 @@
+// 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/media/cache_util.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/cxx17_backports.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "net/http/http_util.h"
+#include "net/http/http_version.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+
+namespace blink {
+
+using ::base::Time;
+using ::base::TimeDelta;
+using ::net::HttpVersion;
+
+enum { kHttpOK = 200, kHttpPartialContent = 206 };
+
+uint32_t GetReasonsForUncacheability(const WebURLResponse& response) {
+ uint32_t reasons = 0;
+ const int code = response.HttpStatusCode();
+ const int version = response.HttpVersion();
+ const HttpVersion http_version =
+ version == WebURLResponse::kHTTPVersion_2_0
+ ? HttpVersion(2, 0)
+ : version == WebURLResponse::kHTTPVersion_1_1
+ ? HttpVersion(1, 1)
+ : version == WebURLResponse::kHTTPVersion_1_0
+ ? HttpVersion(1, 0)
+ : version == WebURLResponse::kHTTPVersion_0_9
+ ? HttpVersion(0, 9)
+ : HttpVersion();
+ if (code != kHttpOK && code != kHttpPartialContent)
+ reasons |= kNoData;
+ if (http_version < HttpVersion(1, 1) && code == kHttpPartialContent)
+ reasons |= kPre11PartialResponse;
+ if (code == kHttpPartialContent &&
+ !net::HttpUtil::HasStrongValidators(
+ http_version, response.HttpHeaderField("etag").Utf8(),
+ response.HttpHeaderField("Last-Modified").Utf8(),
+ response.HttpHeaderField("Date").Utf8())) {
+ reasons |= kNoStrongValidatorOnPartialResponse;
+ }
+
+ std::string cache_control_header =
+ base::ToLowerASCII(response.HttpHeaderField("cache-control").Utf8());
+ if (cache_control_header.find("no-cache") != std::string::npos)
+ reasons |= kNoCache;
+ if (cache_control_header.find("no-store") != std::string::npos)
+ reasons |= kNoStore;
+ if (cache_control_header.find("must-revalidate") != std::string::npos)
+ reasons |= kHasMustRevalidate;
+
+ const TimeDelta kMinimumAgeForUsefulness =
+ TimeDelta::FromSeconds(3600); // Arbitrary value.
+
+ const char kMaxAgePrefix[] = "max-age=";
+ const size_t kMaxAgePrefixLen = base::size(kMaxAgePrefix) - 1;
+ if (cache_control_header.substr(0, kMaxAgePrefixLen) == kMaxAgePrefix) {
+ int64_t max_age_seconds;
+ base::StringToInt64(
+ base::MakeStringPiece(cache_control_header.begin() + kMaxAgePrefixLen,
+ cache_control_header.end()),
+ &max_age_seconds);
+ if (TimeDelta::FromSeconds(max_age_seconds) < kMinimumAgeForUsefulness)
+ reasons |= kShortMaxAge;
+ }
+
+ Time date;
+ Time expires;
+ if (Time::FromString(response.HttpHeaderField("Date").Utf8().data(), &date) &&
+ Time::FromString(response.HttpHeaderField("Expires").Utf8().data(),
+ &expires) &&
+ date > Time() && expires > Time() &&
+ (expires - date) < kMinimumAgeForUsefulness) {
+ reasons |= kExpiresTooSoon;
+ }
+
+ return reasons;
+}
+
+base::TimeDelta GetCacheValidUntil(const WebURLResponse& response) {
+ std::string cache_control_header =
+ base::ToLowerASCII(response.HttpHeaderField("cache-control").Utf8());
+ if (cache_control_header.find("no-cache") != std::string::npos)
+ return base::TimeDelta();
+ if (cache_control_header.find("must-revalidate") != std::string::npos)
+ return base::TimeDelta();
+
+ // Max cache timeout ~= 1 month.
+ base::TimeDelta ret = base::TimeDelta::FromDays(30);
+
+ const char kMaxAgePrefix[] = "max-age=";
+ const size_t kMaxAgePrefixLen = base::size(kMaxAgePrefix) - 1;
+ if (cache_control_header.substr(0, kMaxAgePrefixLen) == kMaxAgePrefix) {
+ int64_t max_age_seconds;
+ base::StringToInt64(
+ base::MakeStringPiece(cache_control_header.begin() + kMaxAgePrefixLen,
+ cache_control_header.end()),
+ &max_age_seconds);
+
+ ret = std::min(ret, TimeDelta::FromSeconds(max_age_seconds));
+ } else {
+ // Note that |date| may be smaller than |expires|, which means we'll
+ // return a timetick some time in the past.
+ Time date;
+ Time expires;
+ if (Time::FromString(response.HttpHeaderField("Date").Utf8().data(),
+ &date) &&
+ Time::FromString(response.HttpHeaderField("Expires").Utf8().data(),
+ &expires) &&
+ date > Time() && expires > Time()) {
+ ret = std::min(ret, expires - date);
+ }
+ }
+
+ return ret;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/cache_util.h b/chromium/third_party/blink/renderer/platform/media/cache_util.h
new file mode 100644
index 00000000000..70d94ebd583
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cache_util.h
@@ -0,0 +1,45 @@
+// 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_MEDIA_CACHE_UTIL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CACHE_UTIL_H_
+
+#include <stdint.h>
+
+#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+class WebURLResponse;
+
+// Reasons that a cached WebURLResponse will *not* prevent a future request to
+// the server. Reported via UMA, so don't change/reuse previously-existing
+// values.
+enum UncacheableReason {
+ kNoData = 1 << 0, // Not 200 or 206.
+ kPre11PartialResponse = 1 << 1, // 206 but HTTP version < 1.1.
+ kNoStrongValidatorOnPartialResponse = 1 << 2, // 206, no strong validator.
+ kShortMaxAge = 1 << 3, // Max age less than 1h (arbitrary value).
+ kExpiresTooSoon = 1 << 4, // Expires in less than 1h (arbitrary value).
+ kHasMustRevalidate = 1 << 5, // Response asks for revalidation.
+ kNoCache = 1 << 6, // Response included a no-cache header.
+ kNoStore = 1 << 7, // Response included a no-store header.
+ kMaxReason // Needs to be one more than max legitimate reason.
+};
+
+// Return the logical OR of the reasons "response" cannot be used for a future
+// request (using the disk cache), or 0 if it might be useful.
+PLATFORM_EXPORT uint32_t
+GetReasonsForUncacheability(const WebURLResponse& response);
+
+// Returns when we should evict data from this response from our
+// memory cache. Note that we may still cache data longer if
+// a audio/video tag is currently using it. Returns a TimeDelta
+// which is should be added to base::Time::Now() or base::TimeTicks::Now().
+PLATFORM_EXPORT base::TimeDelta GetCacheValidUntil(
+ const WebURLResponse& response);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CACHE_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/cache_util_unittest.cc b/chromium/third_party/blink/renderer/platform/media/cache_util_unittest.cc
new file mode 100644
index 00000000000..754f2616378
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cache_util_unittest.cc
@@ -0,0 +1,83 @@
+// 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/media/cache_util.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/cxx17_backports.h"
+#include "base/format_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+
+namespace blink {
+
+// Inputs & expected output for GetReasonsForUncacheability.
+struct GRFUTestCase {
+ WebURLResponse::HTTPVersion version;
+ int status_code;
+ const char* headers;
+ uint32_t expected_reasons;
+};
+
+// Create a new WebURLResponse object.
+static WebURLResponse CreateResponse(const GRFUTestCase& test) {
+ WebURLResponse response;
+ response.SetHttpVersion(test.version);
+ response.SetHttpStatusCode(test.status_code);
+ for (const std::string& line :
+ base::SplitString(test.headers, "\n", base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ size_t colon = line.find(": ");
+ response.AddHttpHeaderField(WebString::FromUTF8(line.substr(0, colon)),
+ WebString::FromUTF8(line.substr(colon + 2)));
+ }
+ return response;
+}
+
+TEST(CacheUtilTest, GetReasonsForUncacheability) {
+ enum { kNoReasons = 0 };
+
+ const GRFUTestCase tests[] = {
+ {WebURLResponse::kHTTPVersion_1_1, 206, "ETag: 'fooblort'", kNoReasons},
+ {WebURLResponse::kHTTPVersion_1_1, 206, "",
+ kNoStrongValidatorOnPartialResponse},
+ {WebURLResponse::kHTTPVersion_1_0, 206, "",
+ kPre11PartialResponse | kNoStrongValidatorOnPartialResponse},
+ {WebURLResponse::kHTTPVersion_1_1, 200, "cache-control: max-Age=42",
+ kShortMaxAge},
+ {WebURLResponse::kHTTPVersion_1_1, 200, "cache-control: max-Age=4200",
+ kNoReasons},
+ {WebURLResponse::kHTTPVersion_1_1, 200,
+ "Date: Tue, 22 May 2012 23:46:08 GMT\n"
+ "Expires: Tue, 22 May 2012 23:56:08 GMT",
+ kExpiresTooSoon},
+ {WebURLResponse::kHTTPVersion_1_1, 200, "cache-control: must-revalidate",
+ kHasMustRevalidate},
+ {WebURLResponse::kHTTPVersion_1_1, 200, "cache-control: no-cache",
+ kNoCache},
+ {WebURLResponse::kHTTPVersion_1_1, 200, "cache-control: no-store",
+ kNoStore},
+ {WebURLResponse::kHTTPVersion_1_1, 200,
+ "cache-control: no-cache\ncache-control: no-store", kNoCache | kNoStore},
+ };
+ for (size_t i = 0; i < base::size(tests); ++i) {
+ SCOPED_TRACE(base::StringPrintf("case: %" PRIuS
+ ", version: %d, code: %d, headers: %s",
+ i, tests[i].version, tests[i].status_code,
+ tests[i].headers));
+ EXPECT_EQ(GetReasonsForUncacheability(CreateResponse(tests[i])),
+ tests[i].expected_reasons);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/cdm_result_promise.h b/chromium/third_party/blink/renderer/platform/media/cdm_result_promise.h
new file mode 100644
index 00000000000..0a697239cbd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cdm_result_promise.h
@@ -0,0 +1,120 @@
+// 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_MEDIA_CDM_RESULT_PROMISE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CDM_RESULT_PROMISE_H_
+
+#include <stdint.h>
+
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_result.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/media/cdm_result_promise_helper.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+const char kTimeUMAPrefix[] = "TimeTo.";
+
+// Used to convert a WebContentDecryptionModuleResult into a CdmPromiseTemplate
+// so that it can be passed through Chromium. When resolve(T) is called, the
+// appropriate complete...() method on WebContentDecryptionModuleResult will be
+// invoked. If reject() is called instead,
+// WebContentDecryptionModuleResult::completeWithError() is called.
+// If constructed with a |uma_name|, CdmResultPromise will report the promise
+// result (success or rejection code) to UMA.
+template <typename... T>
+class PLATFORM_EXPORT CdmResultPromise
+ : public media::CdmPromiseTemplate<T...> {
+ public:
+ CdmResultPromise(const WebContentDecryptionModuleResult& result,
+ const std::string& key_system_uma_prefix,
+ const std::string& uma_name);
+ CdmResultPromise(const CdmResultPromise&) = delete;
+ CdmResultPromise& operator=(const CdmResultPromise&) = delete;
+ ~CdmResultPromise() override;
+
+ // media::CdmPromiseTemplate<T> implementation.
+ void resolve(const T&... result) override;
+ void reject(media::CdmPromise::Exception exception_code,
+ uint32_t system_code,
+ const std::string& error_message) override;
+
+ private:
+ using media::CdmPromiseTemplate<T...>::IsPromiseSettled;
+ using media::CdmPromiseTemplate<T...>::MarkPromiseSettled;
+ using media::CdmPromiseTemplate<T...>::RejectPromiseOnDestruction;
+
+ WebContentDecryptionModuleResult web_cdm_result_;
+
+ // UMA prefix and name to report result and time to.
+ std::string key_system_uma_prefix_;
+ std::string uma_name_;
+
+ // Time when |this| is created.
+ base::TimeTicks creation_time_;
+};
+
+template <typename... T>
+CdmResultPromise<T...>::CdmResultPromise(
+ const WebContentDecryptionModuleResult& result,
+ const std::string& key_system_uma_prefix,
+ const std::string& uma_name)
+ : web_cdm_result_(result),
+ key_system_uma_prefix_(key_system_uma_prefix),
+ uma_name_(uma_name),
+ creation_time_(base::TimeTicks::Now()) {
+ DCHECK(!key_system_uma_prefix_.empty());
+ DCHECK(!uma_name_.empty());
+}
+
+template <typename... T>
+CdmResultPromise<T...>::~CdmResultPromise() {
+ if (!IsPromiseSettled())
+ RejectPromiseOnDestruction();
+}
+
+// "inline" is needed to prevent multiple definition error.
+
+template <>
+inline void CdmResultPromise<>::resolve() {
+ MarkPromiseSettled();
+ ReportCdmResultUMA(key_system_uma_prefix_ + uma_name_, 0, SUCCESS);
+
+ // Only report time for promise resolution (not rejection).
+ base::UmaHistogramTimes(key_system_uma_prefix_ + kTimeUMAPrefix + uma_name_,
+ base::TimeTicks::Now() - creation_time_);
+
+ web_cdm_result_.Complete();
+}
+
+template <>
+inline void CdmResultPromise<media::CdmKeyInformation::KeyStatus>::resolve(
+ const media::CdmKeyInformation::KeyStatus& key_status) {
+ MarkPromiseSettled();
+ ReportCdmResultUMA(key_system_uma_prefix_ + uma_name_, 0, SUCCESS);
+
+ // Only report time for promise resolution (not rejection).
+ base::UmaHistogramTimes(key_system_uma_prefix_ + kTimeUMAPrefix + uma_name_,
+ base::TimeTicks::Now() - creation_time_);
+
+ web_cdm_result_.CompleteWithKeyStatus(ConvertCdmKeyStatus(key_status));
+}
+
+template <typename... T>
+void CdmResultPromise<T...>::reject(media::CdmPromise::Exception exception_code,
+ uint32_t system_code,
+ const std::string& error_message) {
+ MarkPromiseSettled();
+ ReportCdmResultUMA(key_system_uma_prefix_ + uma_name_, system_code,
+ ConvertCdmExceptionToResultForUMA(exception_code));
+ web_cdm_result_.CompleteWithError(ConvertCdmException(exception_code),
+ system_code,
+ WebString::FromUTF8(error_message));
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CDM_RESULT_PROMISE_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.cc b/chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.cc
new file mode 100644
index 00000000000..76168f581cf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.cc
@@ -0,0 +1,79 @@
+// 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/media/cdm_result_promise_helper.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
+
+namespace blink {
+
+CdmResultForUMA ConvertCdmExceptionToResultForUMA(
+ media::CdmPromise::Exception exception_code) {
+ switch (exception_code) {
+ case media::CdmPromise::Exception::NOT_SUPPORTED_ERROR:
+ return NOT_SUPPORTED_ERROR;
+ case media::CdmPromise::Exception::INVALID_STATE_ERROR:
+ return INVALID_STATE_ERROR;
+ case media::CdmPromise::Exception::QUOTA_EXCEEDED_ERROR:
+ return QUOTA_EXCEEDED_ERROR;
+ case media::CdmPromise::Exception::TYPE_ERROR:
+ return TYPE_ERROR;
+ }
+ NOTREACHED();
+ return INVALID_STATE_ERROR;
+}
+
+WebContentDecryptionModuleException ConvertCdmException(
+ media::CdmPromise::Exception exception_code) {
+ switch (exception_code) {
+ case media::CdmPromise::Exception::NOT_SUPPORTED_ERROR:
+ return kWebContentDecryptionModuleExceptionNotSupportedError;
+ case media::CdmPromise::Exception::INVALID_STATE_ERROR:
+ return kWebContentDecryptionModuleExceptionInvalidStateError;
+ case media::CdmPromise::Exception::QUOTA_EXCEEDED_ERROR:
+ return kWebContentDecryptionModuleExceptionQuotaExceededError;
+ case media::CdmPromise::Exception::TYPE_ERROR:
+ return kWebContentDecryptionModuleExceptionTypeError;
+ }
+ NOTREACHED();
+ return kWebContentDecryptionModuleExceptionInvalidStateError;
+}
+
+WebEncryptedMediaKeyInformation::KeyStatus ConvertCdmKeyStatus(
+ media::CdmKeyInformation::KeyStatus key_status) {
+ switch (key_status) {
+ case media::CdmKeyInformation::USABLE:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kUsable;
+ case media::CdmKeyInformation::INTERNAL_ERROR:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kInternalError;
+ case media::CdmKeyInformation::EXPIRED:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kExpired;
+ case media::CdmKeyInformation::OUTPUT_RESTRICTED:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kOutputRestricted;
+ case media::CdmKeyInformation::OUTPUT_DOWNSCALED:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kOutputDownscaled;
+ case media::CdmKeyInformation::KEY_STATUS_PENDING:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kStatusPending;
+ case media::CdmKeyInformation::RELEASED:
+ return WebEncryptedMediaKeyInformation::KeyStatus::kReleased;
+ }
+ NOTREACHED();
+ return WebEncryptedMediaKeyInformation::KeyStatus::kInternalError;
+}
+
+void ReportCdmResultUMA(const std::string& uma_name,
+ uint32_t system_code,
+ CdmResultForUMA result) {
+ if (uma_name.empty())
+ return;
+
+ // Only report system code on promise rejection.
+ if (result != CdmResultForUMA::SUCCESS)
+ base::UmaHistogramSparse(uma_name + ".SystemCode", system_code);
+
+ base::UmaHistogramEnumeration(uma_name, result, NUM_RESULT_CODES);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.h b/chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.h
new file mode 100644
index 00000000000..caf3bf5f9f1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cdm_result_promise_helper.h
@@ -0,0 +1,50 @@
+// 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_MEDIA_CDM_RESULT_PROMISE_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CDM_RESULT_PROMISE_HELPER_H_
+
+#include <string>
+
+#include "media/base/cdm_key_information.h"
+#include "media/base/cdm_promise.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_result.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+// A superset of media::ContentDecryptionModule::Exception for UMA reporting.
+// These values should never be changed as it will affect existing reporting,
+// and must match the values for CdmPromiseResult in
+// tools/metrics/histograms/enums.xml. Deprecated values should never be reused.
+enum CdmResultForUMA {
+ SUCCESS = 0,
+ NOT_SUPPORTED_ERROR = 1,
+ INVALID_STATE_ERROR = 2,
+ TYPE_ERROR = 3,
+ QUOTA_EXCEEDED_ERROR = 4,
+ // UNKNOWN_ERROR = 5, // Deprecated.
+ // CLIENT_ERROR = 6, // Deprecated.
+ // OUTPUT_ERROR = 7, // Deprecated.
+ SESSION_NOT_FOUND = 8,
+ SESSION_ALREADY_EXISTS = 9,
+ NUM_RESULT_CODES // Must be last.
+};
+
+PLATFORM_EXPORT CdmResultForUMA
+ConvertCdmExceptionToResultForUMA(media::CdmPromise::Exception exception_code);
+
+PLATFORM_EXPORT WebContentDecryptionModuleException
+ConvertCdmException(media::CdmPromise::Exception exception_code);
+
+PLATFORM_EXPORT WebEncryptedMediaKeyInformation::KeyStatus ConvertCdmKeyStatus(
+ media::CdmKeyInformation::KeyStatus key_status);
+
+PLATFORM_EXPORT void ReportCdmResultUMA(const std::string& uma_name,
+ uint32_t system_code,
+ CdmResultForUMA result);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CDM_RESULT_PROMISE_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.cc b/chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.cc
new file mode 100644
index 00000000000..32be1b7af59
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.cc
@@ -0,0 +1,267 @@
+// 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/media/cdm_session_adapter.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/containers/contains.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "media/base/cdm_factory.h"
+#include "media/base/cdm_key_information.h"
+#include "media/base/cdm_promise.h"
+#include "media/base/key_systems.h"
+#include "media/cdm/cdm_context_ref_impl.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.h"
+
+namespace blink {
+namespace {
+const char kMediaEME[] = "Media.EME.";
+const char kDot[] = ".";
+const char kCreateCdmUMAName[] = "CreateCdm";
+const char kTimeToCreateCdmUMAName[] = "CreateCdmTime";
+} // namespace
+
+CdmSessionAdapter::CdmSessionAdapter() : trace_id_(0) {}
+
+CdmSessionAdapter::~CdmSessionAdapter() = default;
+
+void CdmSessionAdapter::CreateCdm(media::CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const media::CdmConfig& cdm_config,
+ WebCdmCreatedCB web_cdm_created_cb) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "CdmSessionAdapter::CreateCdm",
+ ++trace_id_);
+
+ base::TimeTicks start_time = base::TimeTicks::Now();
+
+ // Note: WebContentDecryptionModuleImpl::Create() calls this method without
+ // holding a reference to the CdmSessionAdapter. Bind OnCdmCreated() with
+ // |this| instead of |weak_this| to prevent |this| from being destructed.
+ base::WeakPtr<CdmSessionAdapter> weak_this = weak_ptr_factory_.GetWeakPtr();
+
+ DCHECK(!web_cdm_created_cb_);
+ web_cdm_created_cb_ = std::move(web_cdm_created_cb);
+
+ cdm_factory->Create(
+ key_system, cdm_config,
+ base::BindRepeating(&CdmSessionAdapter::OnSessionMessage, weak_this),
+ base::BindRepeating(&CdmSessionAdapter::OnSessionClosed, weak_this),
+ base::BindRepeating(&CdmSessionAdapter::OnSessionKeysChange, weak_this),
+ base::BindRepeating(&CdmSessionAdapter::OnSessionExpirationUpdate,
+ weak_this),
+ base::BindOnce(&CdmSessionAdapter::OnCdmCreated, this, key_system,
+ cdm_config, start_time));
+}
+
+void CdmSessionAdapter::SetServerCertificate(
+ const std::vector<uint8_t>& certificate,
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
+ cdm_->SetServerCertificate(certificate, std::move(promise));
+}
+
+void CdmSessionAdapter::GetStatusForPolicy(
+ media::HdcpVersion min_hdcp_version,
+ std::unique_ptr<media::KeyStatusCdmPromise> promise) {
+ cdm_->GetStatusForPolicy(min_hdcp_version, std::move(promise));
+}
+
+std::unique_ptr<WebContentDecryptionModuleSessionImpl>
+CdmSessionAdapter::CreateSession(WebEncryptedMediaSessionType session_type) {
+ return std::make_unique<WebContentDecryptionModuleSessionImpl>(this,
+ session_type);
+}
+
+bool CdmSessionAdapter::RegisterSession(
+ const std::string& session_id,
+ base::WeakPtr<WebContentDecryptionModuleSessionImpl> session) {
+ // If this session ID is already registered, don't register it again.
+ if (base::Contains(sessions_, session_id))
+ return false;
+
+ sessions_[session_id] = session;
+ return true;
+}
+
+void CdmSessionAdapter::UnregisterSession(const std::string& session_id) {
+ DCHECK(base::Contains(sessions_, session_id));
+ sessions_.erase(session_id);
+}
+
+void CdmSessionAdapter::InitializeNewSession(
+ media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ media::CdmSessionType session_type,
+ std::unique_ptr<media::NewSessionCdmPromise> promise) {
+ cdm_->CreateSessionAndGenerateRequest(session_type, init_data_type, init_data,
+ std::move(promise));
+}
+
+void CdmSessionAdapter::LoadSession(
+ media::CdmSessionType session_type,
+ const std::string& session_id,
+ std::unique_ptr<media::NewSessionCdmPromise> promise) {
+ DVLOG(2) << __func__ << ": session_id = " << session_id;
+ cdm_->LoadSession(session_type, session_id, std::move(promise));
+}
+
+void CdmSessionAdapter::UpdateSession(
+ const std::string& session_id,
+ const std::vector<uint8_t>& response,
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
+ DVLOG(3) << __func__ << ": session_id = " << session_id;
+ cdm_->UpdateSession(session_id, response, std::move(promise));
+}
+
+void CdmSessionAdapter::CloseSession(
+ const std::string& session_id,
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
+ DVLOG(2) << __func__ << ": session_id = " << session_id;
+ cdm_->CloseSession(session_id, std::move(promise));
+}
+
+void CdmSessionAdapter::RemoveSession(
+ const std::string& session_id,
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
+ DVLOG(2) << __func__ << ": session_id = " << session_id;
+ cdm_->RemoveSession(session_id, std::move(promise));
+}
+
+std::unique_ptr<media::CdmContextRef> CdmSessionAdapter::GetCdmContextRef() {
+ DVLOG(2) << __func__;
+
+ if (!cdm_->GetCdmContext()) {
+ NOTREACHED() << "All CDMs should support CdmContext.";
+ return nullptr;
+ }
+
+ return std::make_unique<media::CdmContextRefImpl>(cdm_);
+}
+
+const std::string& CdmSessionAdapter::GetKeySystem() const {
+ return key_system_;
+}
+
+const std::string& CdmSessionAdapter::GetKeySystemUMAPrefix() const {
+ DCHECK(!key_system_uma_prefix_.empty());
+ return key_system_uma_prefix_;
+}
+
+const media::CdmConfig& CdmSessionAdapter::GetCdmConfig() const {
+ DCHECK(cdm_);
+ return cdm_config_;
+}
+
+void CdmSessionAdapter::OnCdmCreated(
+ const std::string& key_system,
+ const media::CdmConfig& cdm_config,
+ base::TimeTicks start_time,
+ const scoped_refptr<media::ContentDecryptionModule>& cdm,
+ const std::string& error_message) {
+ DVLOG(1) << __func__ << ": "
+ << (cdm ? "success" : "failure (" + error_message + ")");
+ DCHECK(!cdm_);
+
+ TRACE_EVENT_NESTABLE_ASYNC_END2(
+ "media", "CdmSessionAdapter::CreateCdm", trace_id_, "success",
+ (cdm ? "true" : "false"), "error_message", error_message);
+
+ auto key_system_uma_prefix =
+ kMediaEME + media::GetKeySystemNameForUMA(key_system) + kDot;
+ base::UmaHistogramBoolean(key_system_uma_prefix + kCreateCdmUMAName,
+ cdm ? true : false);
+
+ if (!cdm) {
+ std::move(web_cdm_created_cb_).Run(nullptr, error_message);
+ return;
+ }
+
+ key_system_ = key_system;
+ key_system_uma_prefix_ = std::move(key_system_uma_prefix);
+
+ // Only report time for successful CDM creation.
+ base::UmaHistogramTimes(key_system_uma_prefix_ + kTimeToCreateCdmUMAName,
+ base::TimeTicks::Now() - start_time);
+
+ cdm_config_ = cdm_config;
+
+ cdm_ = cdm;
+
+ std::move(web_cdm_created_cb_)
+ .Run(new WebContentDecryptionModuleImpl(this), "");
+}
+
+void CdmSessionAdapter::OnSessionMessage(const std::string& session_id,
+ media::CdmMessageType message_type,
+ const std::vector<uint8_t>& message) {
+ WebContentDecryptionModuleSessionImpl* session = GetSession(session_id);
+ DLOG_IF(WARNING, !session) << __func__ << " for unknown session "
+ << session_id;
+ if (session) {
+ DVLOG(3) << __func__ << ": session_id = " << session_id;
+ session->OnSessionMessage(message_type, message);
+ }
+}
+
+void CdmSessionAdapter::OnSessionKeysChange(const std::string& session_id,
+ bool has_additional_usable_key,
+ media::CdmKeysInfo keys_info) {
+ WebContentDecryptionModuleSessionImpl* session = GetSession(session_id);
+ DLOG_IF(WARNING, !session) << __func__ << " for unknown session "
+ << session_id;
+ if (session) {
+ DVLOG(2) << __func__ << ": session_id = " << session_id;
+ DVLOG(2) << " - has_additional_usable_key = " << has_additional_usable_key;
+ for (const auto& info : keys_info)
+ DVLOG(2) << " - " << *(info.get());
+
+ session->OnSessionKeysChange(has_additional_usable_key,
+ std::move(keys_info));
+ }
+}
+
+void CdmSessionAdapter::OnSessionExpirationUpdate(const std::string& session_id,
+ base::Time new_expiry_time) {
+ WebContentDecryptionModuleSessionImpl* session = GetSession(session_id);
+ DLOG_IF(WARNING, !session) << __func__ << " for unknown session "
+ << session_id;
+ if (session) {
+ DVLOG(2) << __func__ << ": session_id = " << session_id;
+ if (new_expiry_time.is_null())
+ DVLOG(2) << " - new_expiry_time = NaN";
+ else
+ DVLOG(2) << " - new_expiry_time = " << new_expiry_time;
+
+ session->OnSessionExpirationUpdate(new_expiry_time);
+ }
+}
+
+void CdmSessionAdapter::OnSessionClosed(const std::string& session_id,
+ media::CdmSessionClosedReason reason) {
+ WebContentDecryptionModuleSessionImpl* session = GetSession(session_id);
+ DLOG_IF(WARNING, !session)
+ << __func__ << " for unknown session " << session_id;
+ if (session) {
+ DVLOG(2) << __func__ << ": session_id = " << session_id
+ << ", reason = " << static_cast<int>(reason);
+ session->OnSessionClosed(reason);
+ }
+}
+
+WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::GetSession(
+ const std::string& session_id) {
+ // Since session objects may get garbage collected, it is possible that there
+ // are events coming back from the CDM and the session has been unregistered.
+ // We can not tell if the CDM is firing events at sessions that never existed.
+ auto session = sessions_.find(session_id);
+ return (session != sessions_.end()) ? session->second.get() : NULL;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.h b/chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.h
new file mode 100644
index 00000000000..b74d1945145
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/cdm_session_adapter.h
@@ -0,0 +1,177 @@
+// 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_MEDIA_CDM_SESSION_ADAPTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CDM_SESSION_ADAPTER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "media/base/cdm_config.h"
+#include "media/base/content_decryption_module.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_session.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace base {
+class Time;
+class TimeTicks;
+} // namespace base
+
+namespace media {
+class CdmContextRef;
+class CdmFactory;
+struct CdmConfig;
+} // namespace media
+
+namespace blink {
+class WebContentDecryptionModuleSessionImpl;
+
+// Owns the CDM instance and makes calls from session objects to the CDM.
+// Forwards the session ID-based callbacks of the media::ContentDecryptionModule
+// interface to the appropriate session object. Callers should hold references
+// to this class as long as they need the CDM instance.
+class PLATFORM_EXPORT CdmSessionAdapter
+ : public base::RefCounted<CdmSessionAdapter> {
+ public:
+ CdmSessionAdapter();
+ CdmSessionAdapter(const CdmSessionAdapter&) = delete;
+ CdmSessionAdapter& operator=(const CdmSessionAdapter&) = delete;
+
+ // Creates the CDM for |key_system| using |cdm_factory| and returns the result
+ // via |result|.
+ void CreateCdm(media::CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const media::CdmConfig& cdm_config,
+ WebCdmCreatedCB web_cdm_created_cb);
+
+ // Provides a server certificate to be used to encrypt messages to the
+ // license server.
+ void SetServerCertificate(const std::vector<uint8_t>& certificate,
+ std::unique_ptr<media::SimpleCdmPromise> promise);
+
+ // Gets the key status for a hypothetical key with |min_hdcp_version|
+ // requirement.
+ void GetStatusForPolicy(media::HdcpVersion min_hdcp_version,
+ std::unique_ptr<media::KeyStatusCdmPromise> promise);
+
+ // Creates a new session and adds it to the internal map. RemoveSession()
+ // must be called when destroying it, if RegisterSession() was called.
+ std::unique_ptr<WebContentDecryptionModuleSessionImpl> CreateSession(
+ WebEncryptedMediaSessionType session_type);
+
+ // Adds a session to the internal map. Called once the session is successfully
+ // initialized. Returns true if the session was registered, false if there is
+ // already an existing session with the same |session_id|.
+ bool RegisterSession(
+ const std::string& session_id,
+ base::WeakPtr<WebContentDecryptionModuleSessionImpl> session);
+
+ // Removes a session from the internal map.
+ void UnregisterSession(const std::string& session_id);
+
+ // Initializes a session with the |init_data_type|, |init_data| and
+ // |session_type| provided.
+ void InitializeNewSession(
+ media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ media::CdmSessionType session_type,
+ std::unique_ptr<media::NewSessionCdmPromise> promise);
+
+ // Loads the session specified by |session_id|.
+ void LoadSession(media::CdmSessionType session_type,
+ const std::string& session_id,
+ std::unique_ptr<media::NewSessionCdmPromise> promise);
+
+ // Updates the session specified by |session_id| with |response|.
+ void UpdateSession(const std::string& session_id,
+ const std::vector<uint8_t>& response,
+ std::unique_ptr<media::SimpleCdmPromise> promise);
+
+ // Closes the session specified by |session_id|.
+ void CloseSession(const std::string& session_id,
+ std::unique_ptr<media::SimpleCdmPromise> promise);
+
+ // Removes stored session data associated with the session specified by
+ // |session_id|.
+ void RemoveSession(const std::string& session_id,
+ std::unique_ptr<media::SimpleCdmPromise> promise);
+
+ // Returns a CdmContextRef which provides access to CdmContext and by holding
+ // the CdmContextRef, makes sure the CdmContext is kept alive.
+ std::unique_ptr<media::CdmContextRef> GetCdmContextRef();
+
+ // Returns the key system name.
+ const std::string& GetKeySystem() const;
+
+ // Returns a prefix to use for UMAs.
+ const std::string& GetKeySystemUMAPrefix() const;
+
+ // Returns the CdmConfig used in creation of CDM.
+ const media::CdmConfig& GetCdmConfig() const;
+
+ private:
+ friend class base::RefCounted<CdmSessionAdapter>;
+
+ // Session ID to WebContentDecryptionModuleSessionImpl mapping.
+ typedef std::unordered_map<
+ std::string,
+ base::WeakPtr<WebContentDecryptionModuleSessionImpl>>
+ SessionMap;
+
+ ~CdmSessionAdapter();
+
+ // Callback for CreateCdm().
+ void OnCdmCreated(const std::string& key_system,
+ const media::CdmConfig& cdm_config,
+ base::TimeTicks start_time,
+ const scoped_refptr<media::ContentDecryptionModule>& cdm,
+ const std::string& error_message);
+
+ // Callbacks for firing session events.
+ void OnSessionMessage(const std::string& session_id,
+ media::CdmMessageType message_type,
+ const std::vector<uint8_t>& message);
+ void OnSessionKeysChange(const std::string& session_id,
+ bool has_additional_usable_key,
+ media::CdmKeysInfo keys_info);
+ void OnSessionExpirationUpdate(const std::string& session_id,
+ base::Time new_expiry_time);
+ void OnSessionClosed(const std::string& session_id,
+ media::CdmSessionClosedReason reason);
+
+ // Helper function of the callbacks.
+ WebContentDecryptionModuleSessionImpl* GetSession(
+ const std::string& session_id);
+
+ scoped_refptr<media::ContentDecryptionModule> cdm_;
+
+ SessionMap sessions_;
+
+ std::string key_system_;
+ std::string key_system_uma_prefix_;
+
+ // media::CdmConfig used in creation of cdm_.
+ media::CdmConfig cdm_config_;
+
+ // A unique ID to trace CdmSessionAdapter::CreateCdm() call and the matching
+ // OnCdmCreated() call.
+ uint32_t trace_id_;
+
+ WebCdmCreatedCB web_cdm_created_cb_;
+
+ // NOTE: Weak pointers must be invalidated before all other member variables.
+ base::WeakPtrFactory<CdmSessionAdapter> weak_ptr_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CDM_SESSION_ADAPTER_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/interval_map_unittest.cc b/chromium/third_party/blink/renderer/platform/media/interval_map_unittest.cc
new file mode 100644
index 00000000000..092800beedc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/interval_map_unittest.cc
@@ -0,0 +1,275 @@
+// 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/platform/media/interval_map.h"
+
+#include <stdint.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "media/base/test_random.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+// Our tests only modifiy the interval map entries in [0..kTestSize).
+// We need this to be big enough to hit tricky corner cases, but small
+// enough that we get lots of entry duplication to clean up.
+// Also, SimpleIntervalMap uses a vector of size kTestSize to emulate
+// a intervalmap, so making this too big will the test down a lot.
+const int kTestSize = 16;
+
+class SimpleIntervalMap {
+ public:
+ SimpleIntervalMap() : data_(kTestSize) {}
+
+ void IncrementInterval(int32_t from, int32_t to, int32_t how_much) {
+ for (int32_t i = from; i < to; i++) {
+ data_[i] += how_much;
+ }
+ }
+
+ void SetInterval(int32_t from, int32_t to, int32_t how_much) {
+ for (int32_t i = from; i < to; i++) {
+ data_[i] = how_much;
+ }
+ }
+
+ int32_t operator[](int32_t index) const { return data_[index]; }
+
+ private:
+ std::vector<int32_t> data_;
+};
+
+class IntervalMapTest : public testing::Test {
+ public:
+ IntervalMapTest() : rnd_(42) {}
+ void IncrementInterval(int32_t from, int32_t to, int32_t how_much) {
+ truth_.IncrementInterval(from, to, how_much);
+ testee_.IncrementInterval(from, to, how_much);
+ std::string message =
+ base::StringPrintf("After [%d - %d) += %d", from, to, how_much);
+ Compare(message);
+ }
+
+ void SetInterval(int32_t from, int32_t to, int32_t how_much) {
+ truth_.SetInterval(from, to, how_much);
+ testee_.SetInterval(from, to, how_much);
+ std::string message =
+ base::StringPrintf("After [%d - %d) += %d", from, to, how_much);
+ Compare(message);
+ }
+
+ // Will exercise operator[] and IntervalMap::const_iterator.
+ void Compare(const std::string& message) {
+ bool had_fail = HasFailure();
+ for (int i = 0; i < kTestSize; i++) {
+ EXPECT_EQ(truth_[i], testee_[i]) << " i = " << i << " " << message;
+ }
+ EXPECT_EQ(testee_[-1], 0) << message;
+ EXPECT_EQ(testee_[kTestSize], 0) << message;
+ int32_t prev_ = 0;
+ int32_t end_of_last_interval = 0;
+ int32_t num_intervals = 0;
+ for (auto r : testee_) {
+ num_intervals++;
+ EXPECT_LT(r.first.begin, r.first.end);
+ if (r.first.begin == std::numeric_limits<int32_t>::min()) {
+ EXPECT_EQ(0, r.second);
+ } else {
+ EXPECT_EQ(end_of_last_interval, r.first.begin);
+ EXPECT_GE(r.first.begin, 0) << message;
+ EXPECT_LE(r.first.begin, kTestSize) << message;
+ EXPECT_NE(r.second, prev_) << message;
+ }
+ end_of_last_interval = r.first.end;
+ prev_ = r.second;
+ }
+ EXPECT_EQ(prev_, 0) << message;
+
+ if (HasFailure() && !had_fail) {
+ for (int i = 0; i < kTestSize; i++) {
+ LOG(ERROR) << i << ": Truth =" << truth_[i]
+ << " Testee = " << testee_[i];
+ }
+ for (auto r : testee_) {
+ LOG(ERROR) << "Interval: " << r.first.begin << " - " << r.first.end
+ << " = " << r.second;
+ }
+ }
+ }
+
+ void Clear() {
+ for (int j = 0; j < kTestSize; j++) {
+ IncrementInterval(j, j + 1, -truth_[j]);
+ }
+ }
+
+ protected:
+ media::TestRandom rnd_;
+ SimpleIntervalMap truth_;
+ IntervalMap<int32_t, int32_t> testee_;
+};
+
+TEST_F(IntervalMapTest, SimpleTest) {
+ IncrementInterval(3, 7, 4);
+ EXPECT_EQ(0, testee_[0]);
+ EXPECT_EQ(0, testee_[2]);
+ EXPECT_EQ(4, testee_[3]);
+ EXPECT_EQ(4, testee_[5]);
+ EXPECT_EQ(4, testee_[6]);
+ EXPECT_EQ(0, testee_[7]);
+ IncrementInterval(3, 7, -4);
+ EXPECT_TRUE(testee_.empty());
+}
+
+TEST_F(IntervalMapTest, SimpleIncrementTest) {
+ IncrementInterval(3, 7, 1);
+ IncrementInterval(6, 10, 2);
+ EXPECT_EQ(0, testee_[2]);
+ EXPECT_EQ(1, testee_[3]);
+ EXPECT_EQ(1, testee_[5]);
+ EXPECT_EQ(3, testee_[6]);
+ EXPECT_EQ(2, testee_[7]);
+ EXPECT_EQ(2, testee_[9]);
+ EXPECT_EQ(0, testee_[10]);
+ SetInterval(3, 12, 0);
+ EXPECT_TRUE(testee_.empty());
+}
+
+TEST_F(IntervalMapTest, IncrementJoinIntervalsTest) {
+ IncrementInterval(3, 5, 1);
+ IncrementInterval(7, 8, 1);
+ IncrementInterval(9, 11, 1);
+ IncrementInterval(5, 7, 1);
+ IncrementInterval(8, 9, 1);
+ auto i = testee_.find(5);
+ EXPECT_EQ(3, i.interval_begin());
+ EXPECT_EQ(11, i.interval_end());
+ EXPECT_EQ(1, i.value());
+}
+
+TEST_F(IntervalMapTest, SetJoinIntervalsTest) {
+ SetInterval(3, 5, 1);
+ SetInterval(7, 8, 1);
+ SetInterval(9, 11, 1);
+ SetInterval(5, 9, 1); // overwrites one interval
+ auto i = testee_.find(5);
+ EXPECT_EQ(3, i.interval_begin());
+ EXPECT_EQ(11, i.interval_end());
+ EXPECT_EQ(1, i.value());
+}
+
+TEST_F(IntervalMapTest, FindTest) {
+ IncrementInterval(5, 6, 1);
+ IncrementInterval(1, 10, 2);
+ int32_t min_value = std::numeric_limits<int32_t>::min();
+ int32_t max_value = std::numeric_limits<int32_t>::max();
+ auto i = testee_.find(0);
+ EXPECT_EQ(min_value, i.interval_begin());
+ EXPECT_EQ(1, i.interval_end());
+ EXPECT_EQ(0, i.value());
+ i = testee_.find(4);
+ EXPECT_EQ(1, i.interval_begin());
+ EXPECT_EQ(5, i.interval_end());
+ EXPECT_EQ(2, i.value());
+ i = testee_.find(5);
+ EXPECT_EQ(5, i.interval_begin());
+ EXPECT_EQ(6, i.interval_end());
+ EXPECT_EQ(3, i.value());
+ i = testee_.find(6);
+ EXPECT_EQ(6, i.interval_begin());
+ EXPECT_EQ(10, i.interval_end());
+ EXPECT_EQ(2, i.value());
+ i = testee_.find(9);
+ EXPECT_EQ(6, i.interval_begin());
+ EXPECT_EQ(10, i.interval_end());
+ EXPECT_EQ(2, i.value());
+ i = testee_.find(10);
+ EXPECT_EQ(10, i.interval_begin());
+ EXPECT_EQ(max_value, i.interval_end());
+ EXPECT_EQ(0, i.value());
+}
+
+TEST_F(IntervalMapTest, MinMaxInt) {
+ int32_t min_value = std::numeric_limits<int32_t>::min();
+ int32_t max_value = std::numeric_limits<int32_t>::max();
+
+ // Change a single value at minint
+ testee_.IncrementInterval(min_value, min_value + 1, 7);
+ EXPECT_EQ(7, testee_[min_value]);
+ EXPECT_EQ(0, testee_[min_value + 1]);
+ auto i = testee_.find(0);
+ EXPECT_EQ(min_value + 1, i.interval_begin());
+ EXPECT_EQ(max_value, i.interval_end());
+ EXPECT_EQ(0, i.value());
+ --i;
+ EXPECT_TRUE(i == testee_.find(min_value));
+ EXPECT_EQ(min_value, i.interval_begin());
+ EXPECT_EQ(min_value + 1, i.interval_end());
+ EXPECT_EQ(7, i.value());
+ testee_.clear();
+
+ // Change a single value at maxint
+ // Note that we don't actually have a way to represent a range
+ // that includes maxint as the end of the interval is non-inclusive.
+ testee_.IncrementInterval(max_value - 1, max_value, 7);
+ EXPECT_EQ(7, testee_[max_value - 1]);
+ EXPECT_EQ(0, testee_[max_value - 2]);
+ i = testee_.find(0);
+ EXPECT_EQ(min_value, i.interval_begin());
+ EXPECT_EQ(max_value - 1, i.interval_end());
+ EXPECT_EQ(0, i.value());
+ ++i;
+ EXPECT_TRUE(i == testee_.find(max_value - 1));
+ EXPECT_EQ(max_value - 1, i.interval_begin());
+ EXPECT_EQ(max_value, i.interval_end());
+ EXPECT_EQ(7, i.value());
+
+ testee_.clear();
+
+ // Change entire range (almost)
+ testee_.IncrementInterval(min_value, max_value, 17);
+ EXPECT_EQ(17, testee_[min_value]);
+ EXPECT_EQ(17, testee_[0]);
+ EXPECT_EQ(17, testee_[max_value - 1]);
+ i = testee_.find(0);
+ EXPECT_EQ(min_value, i.interval_begin());
+ EXPECT_EQ(max_value, i.interval_end());
+ EXPECT_EQ(17, i.value());
+ EXPECT_TRUE(i == testee_.find(max_value - 1));
+ EXPECT_TRUE(i == testee_.find(min_value));
+}
+
+TEST_F(IntervalMapTest, RandomIncrementTest) {
+ for (int j = 0; j < 200; j++) {
+ Clear();
+ for (int i = 0; i < 200; i++) {
+ int32_t begin = rnd_.Rand() % (kTestSize - 1);
+ int32_t end = begin + 1 + rnd_.Rand() % (kTestSize - begin - 1);
+ IncrementInterval(begin, end, (rnd_.Rand() & 32) ? 1 : -1);
+ if (HasFailure()) {
+ return;
+ }
+ }
+ }
+}
+
+TEST_F(IntervalMapTest, RandomSetTest) {
+ for (int j = 0; j < 200; j++) {
+ Clear();
+ for (int i = 0; i < 200; i++) {
+ int32_t begin = rnd_.Rand() % (kTestSize - 1);
+ int32_t end = begin + 1 + rnd_.Rand() % (kTestSize - begin - 1);
+ SetInterval(begin, end, rnd_.Rand() & 3);
+ if (HasFailure()) {
+ return;
+ }
+ }
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/key_system_config_selector.cc b/chromium/third_party/blink/renderer/platform/media/key_system_config_selector.cc
new file mode 100644
index 00000000000..373c03cbb73
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/key_system_config_selector.cc
@@ -0,0 +1,1112 @@
+// 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/media/key_system_config_selector.h"
+
+#include <stddef.h>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "media/base/cdm_config.h"
+#include "media/base/key_system_names.h"
+#include "media/base/key_systems.h"
+#include "media/base/logging_override_if_enabled.h"
+#include "media/base/media_permission.h"
+#include "media/base/media_switches.h"
+#include "media/base/mime_util.h"
+#include "media/media_buildflags.h"
+#include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/public/platform/web_media_key_system_configuration.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+
+namespace blink {
+namespace {
+
+using ::media::EmeConfigRule;
+using ::media::EmeFeatureSupport;
+using ::media::EmeMediaType;
+using ::media::EmeSessionTypeSupport;
+using ::media::EncryptionScheme;
+using EmeFeatureRequirement = WebMediaKeySystemConfiguration::Requirement;
+using EmeEncryptionScheme = WebMediaKeySystemMediaCapability::EncryptionScheme;
+
+EmeConfigRule GetSessionTypeConfigRule(EmeSessionTypeSupport support) {
+ switch (support) {
+ case EmeSessionTypeSupport::INVALID:
+ NOTREACHED();
+ return EmeConfigRule::NOT_SUPPORTED;
+ case EmeSessionTypeSupport::NOT_SUPPORTED:
+ return EmeConfigRule::NOT_SUPPORTED;
+ case EmeSessionTypeSupport::SUPPORTED_WITH_IDENTIFIER:
+ return EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED;
+ case EmeSessionTypeSupport::SUPPORTED:
+ return EmeConfigRule::PERSISTENCE_REQUIRED;
+ }
+ NOTREACHED();
+ return EmeConfigRule::NOT_SUPPORTED;
+}
+
+EmeConfigRule GetDistinctiveIdentifierConfigRule(
+ EmeFeatureSupport support,
+ EmeFeatureRequirement requirement) {
+ if (support == EmeFeatureSupport::INVALID) {
+ NOTREACHED();
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ // For NOT_ALLOWED and REQUIRED, the result is as expected. For OPTIONAL, we
+ // return the most restrictive rule that is not more restrictive than for
+ // NOT_ALLOWED or REQUIRED. Those values will be checked individually when
+ // the option is resolved.
+ //
+ // |---------------Requirement-------------------
+ // Support | NOT_ALLOWED | OPTIONAL | REQUIRED
+ // NOT_SUPPORTED | I_NOT_ALLOWED | I_NOT_ALLOWED | NOT_SUPPORTED
+ // REQUESTABLE | I_NOT_ALLOWED | SUPPORTED | I_REQUIRED
+ // ALWAYS_ENABLED | NOT_SUPPORTED | I_REQUIRED | I_REQUIRED
+ DCHECK(support == EmeFeatureSupport::NOT_SUPPORTED ||
+ support == EmeFeatureSupport::REQUESTABLE ||
+ support == EmeFeatureSupport::ALWAYS_ENABLED);
+ DCHECK(requirement == EmeFeatureRequirement::kNotAllowed ||
+ requirement == EmeFeatureRequirement::kOptional ||
+ requirement == EmeFeatureRequirement::kRequired);
+ if ((support == EmeFeatureSupport::NOT_SUPPORTED &&
+ requirement == EmeFeatureRequirement::kRequired) ||
+ (support == EmeFeatureSupport::ALWAYS_ENABLED &&
+ requirement == EmeFeatureRequirement::kNotAllowed)) {
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+ if (support == EmeFeatureSupport::REQUESTABLE &&
+ requirement == EmeFeatureRequirement::kOptional) {
+ return EmeConfigRule::SUPPORTED;
+ }
+ if (support == EmeFeatureSupport::NOT_SUPPORTED ||
+ requirement == EmeFeatureRequirement::kNotAllowed) {
+ return EmeConfigRule::IDENTIFIER_NOT_ALLOWED;
+ }
+ return EmeConfigRule::IDENTIFIER_REQUIRED;
+}
+
+EmeConfigRule GetPersistentStateConfigRule(EmeFeatureSupport support,
+ EmeFeatureRequirement requirement) {
+ if (support == EmeFeatureSupport::INVALID) {
+ NOTREACHED();
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ // For NOT_ALLOWED and REQUIRED, the result is as expected. For OPTIONAL, we
+ // return the most restrictive rule that is not more restrictive than for
+ // NOT_ALLOWED or REQUIRED. Those values will be checked individually when
+ // the option is resolved.
+ //
+ // Note that even though a distinctive identifier can not be required for
+ // persistent state, it may still be required for persistent sessions.
+ //
+ // |---------------Requirement-------------------
+ // Support | NOT_ALLOWED | OPTIONAL | REQUIRED
+ // NOT_SUPPORTED | P_NOT_ALLOWED | P_NOT_ALLOWED | NOT_SUPPORTED
+ // REQUESTABLE | P_NOT_ALLOWED | SUPPORTED | P_REQUIRED
+ // ALWAYS_ENABLED | NOT_SUPPORTED | P_REQUIRED | P_REQUIRED
+ DCHECK(support == EmeFeatureSupport::NOT_SUPPORTED ||
+ support == EmeFeatureSupport::REQUESTABLE ||
+ support == EmeFeatureSupport::ALWAYS_ENABLED);
+ DCHECK(requirement == EmeFeatureRequirement::kNotAllowed ||
+ requirement == EmeFeatureRequirement::kOptional ||
+ requirement == EmeFeatureRequirement::kRequired);
+ if ((support == EmeFeatureSupport::NOT_SUPPORTED &&
+ requirement == EmeFeatureRequirement::kRequired) ||
+ (support == EmeFeatureSupport::ALWAYS_ENABLED &&
+ requirement == EmeFeatureRequirement::kNotAllowed)) {
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+ if (support == EmeFeatureSupport::REQUESTABLE &&
+ requirement == EmeFeatureRequirement::kOptional) {
+ return EmeConfigRule::SUPPORTED;
+ }
+ if (support == EmeFeatureSupport::NOT_SUPPORTED ||
+ requirement == EmeFeatureRequirement::kNotAllowed) {
+ return EmeConfigRule::PERSISTENCE_NOT_ALLOWED;
+ }
+ return EmeConfigRule::PERSISTENCE_REQUIRED;
+}
+
+bool IsPersistentSessionType(WebEncryptedMediaSessionType sessionType) {
+ switch (sessionType) {
+ case WebEncryptedMediaSessionType::kTemporary:
+ return false;
+ case WebEncryptedMediaSessionType::kPersistentLicense:
+ return true;
+ case WebEncryptedMediaSessionType::kUnknown:
+ break;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+bool IsSupportedMediaType(const std::string& container_mime_type,
+ const std::string& codecs,
+ bool use_aes_decryptor) {
+ DVLOG(3) << __func__ << ": container_mime_type=" << container_mime_type
+ << ", codecs=" << codecs
+ << ", use_aes_decryptor=" << use_aes_decryptor;
+
+ std::vector<std::string> codec_vector;
+ media::SplitCodecs(codecs, &codec_vector);
+
+#if BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC)
+ // EME HEVC is supported on under this build flag, but it is not supported for
+ // clear playback or when using ClearKey. Remove the HEVC codec strings to
+ // avoid asking IsSupported*MediaFormat() about HEVC. EME support for HEVC
+ // profiles is described via KeySystemProperties::GetSupportedCodecs().
+ // TODO(1156282): Decouple the rest of clear vs EME codec support.
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ const bool allow_hevc = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kLacrosEnablePlatformEncryptedHevc);
+#else
+ const bool allow_hevc = true;
+#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
+ if (allow_hevc && !use_aes_decryptor &&
+ base::ToLowerASCII(container_mime_type) == "video/mp4" &&
+ !codec_vector.empty()) {
+ auto it = codec_vector.begin();
+ while (it != codec_vector.end()) {
+ media::VideoCodecProfile profile;
+ uint8_t level_idc;
+ if (ParseHEVCCodecId(*it, &profile, &level_idc))
+ codec_vector.erase(it);
+ else
+ ++it;
+ }
+
+ // Avoid calling IsSupported*MediaFormat() with an empty vector. For
+ // "video/mp4", this will return MaybeSupported, which we would otherwise
+ // consider "false" below.
+ if (codec_vector.empty())
+ return true;
+ }
+#endif // BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC)
+
+ // AesDecryptor decrypts the stream in the demuxer before it reaches the
+ // decoder so check whether the media format is supported when clear.
+ media::SupportsType support_result =
+ use_aes_decryptor
+ ? media::IsSupportedMediaFormat(container_mime_type, codec_vector)
+ : media::IsSupportedEncryptedMediaFormat(container_mime_type,
+ codec_vector);
+ return (support_result == media::IsSupported);
+}
+
+} // namespace
+
+bool KeySystemConfigSelector::WebLocalFrameDelegate::
+ IsCrossOriginToMainFrame() {
+ DCHECK(web_frame_);
+ return web_frame_->IsCrossOriginToMainFrame();
+}
+
+bool KeySystemConfigSelector::WebLocalFrameDelegate::AllowStorageAccessSync(
+ WebContentSettingsClient::StorageType storage_type) {
+ DCHECK(web_frame_);
+ WebContentSettingsClient* content_settings_client =
+ web_frame_->GetContentSettingsClient();
+ return !content_settings_client ||
+ content_settings_client->AllowStorageAccessSync(storage_type);
+}
+
+struct KeySystemConfigSelector::SelectionRequest {
+ std::string key_system;
+ WebVector<WebMediaKeySystemConfiguration> candidate_configurations;
+ SelectConfigCB cb;
+ bool was_permission_requested = false;
+ bool is_permission_granted = false;
+};
+
+// Accumulates configuration rules to determine if a feature (additional
+// configuration rule) can be added to an accumulated configuration.
+class KeySystemConfigSelector::ConfigState {
+ public:
+ ConfigState(bool was_permission_requested, bool is_permission_granted)
+ : was_permission_requested_(was_permission_requested),
+ is_permission_granted_(is_permission_granted) {}
+
+ bool IsPermissionGranted() const { return is_permission_granted_; }
+
+ // Permission is possible if it has not been denied.
+ bool IsPermissionPossible() const {
+ return is_permission_granted_ || !was_permission_requested_;
+ }
+
+ bool IsIdentifierRequired() const { return is_identifier_required_; }
+
+ bool IsIdentifierRecommended() const { return is_identifier_recommended_; }
+
+ bool AreHwSecureCodecsRequired() const {
+ return are_hw_secure_codecs_required_;
+ }
+
+ bool AreHwSecureCodesNotAllowed() const {
+ return are_hw_secure_codecs_not_allowed_;
+ }
+
+ // Checks whether a rule is compatible with all previously added rules.
+ bool IsRuleSupported(EmeConfigRule rule) const {
+ switch (rule) {
+ case EmeConfigRule::NOT_SUPPORTED:
+ return false;
+ case EmeConfigRule::IDENTIFIER_NOT_ALLOWED:
+ return !is_identifier_required_;
+ case EmeConfigRule::IDENTIFIER_REQUIRED:
+ // TODO(sandersd): Confirm if we should be refusing these rules when
+ // permission has been denied (as the spec currently says).
+ return !is_identifier_not_allowed_ && IsPermissionPossible();
+ case EmeConfigRule::IDENTIFIER_RECOMMENDED:
+ return true;
+ case EmeConfigRule::PERSISTENCE_NOT_ALLOWED:
+ return !is_persistence_required_;
+ case EmeConfigRule::PERSISTENCE_REQUIRED:
+ return !is_persistence_not_allowed_;
+ case EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED:
+ return !is_identifier_not_allowed_ && IsPermissionPossible() &&
+ !is_persistence_not_allowed_;
+ case EmeConfigRule::HW_SECURE_CODECS_NOT_ALLOWED:
+ return !are_hw_secure_codecs_required_;
+ case EmeConfigRule::HW_SECURE_CODECS_REQUIRED:
+ return !are_hw_secure_codecs_not_allowed_;
+ case EmeConfigRule::IDENTIFIER_AND_HW_SECURE_CODECS_REQUIRED:
+ return !is_identifier_not_allowed_ && IsPermissionPossible() &&
+ !are_hw_secure_codecs_not_allowed_;
+ case EmeConfigRule::IDENTIFIER_PERSISTENCE_AND_HW_SECURE_CODECS_REQUIRED:
+ return !is_identifier_not_allowed_ && IsPermissionPossible() &&
+ !is_persistence_not_allowed_ &&
+ !are_hw_secure_codecs_not_allowed_;
+ case EmeConfigRule::SUPPORTED:
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+
+ // Add a rule to the accumulated configuration state.
+ void AddRule(EmeConfigRule rule) {
+ DCHECK(IsRuleSupported(rule));
+ switch (rule) {
+ case EmeConfigRule::NOT_SUPPORTED:
+ NOTREACHED();
+ return;
+ case EmeConfigRule::IDENTIFIER_NOT_ALLOWED:
+ is_identifier_not_allowed_ = true;
+ return;
+ case EmeConfigRule::IDENTIFIER_REQUIRED:
+ is_identifier_required_ = true;
+ return;
+ case EmeConfigRule::IDENTIFIER_RECOMMENDED:
+ is_identifier_recommended_ = true;
+ return;
+ case EmeConfigRule::PERSISTENCE_NOT_ALLOWED:
+ is_persistence_not_allowed_ = true;
+ return;
+ case EmeConfigRule::PERSISTENCE_REQUIRED:
+ is_persistence_required_ = true;
+ return;
+ case EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED:
+ is_identifier_required_ = true;
+ is_persistence_required_ = true;
+ return;
+ case EmeConfigRule::HW_SECURE_CODECS_NOT_ALLOWED:
+ are_hw_secure_codecs_not_allowed_ = true;
+ return;
+ case EmeConfigRule::HW_SECURE_CODECS_REQUIRED:
+ are_hw_secure_codecs_required_ = true;
+ return;
+ case EmeConfigRule::IDENTIFIER_AND_HW_SECURE_CODECS_REQUIRED:
+ is_identifier_required_ = true;
+ are_hw_secure_codecs_required_ = true;
+ return;
+ case EmeConfigRule::IDENTIFIER_PERSISTENCE_AND_HW_SECURE_CODECS_REQUIRED:
+ is_identifier_required_ = true;
+ is_persistence_required_ = true;
+ are_hw_secure_codecs_required_ = true;
+ return;
+ case EmeConfigRule::SUPPORTED:
+ return;
+ }
+ NOTREACHED();
+ }
+
+ private:
+ // Whether permission to use a distinctive identifier was requested. If set,
+ // |is_permission_granted_| represents the final decision.
+ // (Not changed by adding rules.)
+ bool was_permission_requested_;
+
+ // Whether permission to use a distinctive identifier has been granted.
+ // (Not changed by adding rules.)
+ bool is_permission_granted_;
+
+ // Whether a rule has been added that requires or blocks a distinctive
+ // identifier.
+ bool is_identifier_required_ = false;
+ bool is_identifier_not_allowed_ = false;
+
+ // Whether a rule has been added that recommends a distinctive identifier.
+ bool is_identifier_recommended_ = false;
+
+ // Whether a rule has been added that requires or blocks persistent state.
+ bool is_persistence_required_ = false;
+ bool is_persistence_not_allowed_ = false;
+
+ // Whether a rule has been added that requires or blocks hardware-secure
+ // codecs.
+ bool are_hw_secure_codecs_required_ = false;
+ bool are_hw_secure_codecs_not_allowed_ = false;
+};
+
+KeySystemConfigSelector::KeySystemConfigSelector(
+ media::KeySystems* key_systems,
+ media::MediaPermission* media_permission,
+ std::unique_ptr<WebLocalFrameDelegate> web_frame_delegate)
+ : key_systems_(key_systems),
+ media_permission_(media_permission),
+ web_frame_delegate_(std::move(web_frame_delegate)),
+ is_supported_media_type_cb_(base::BindRepeating(&IsSupportedMediaType)) {
+ DCHECK(key_systems_);
+ DCHECK(media_permission_);
+ DCHECK(web_frame_delegate_);
+}
+
+KeySystemConfigSelector::~KeySystemConfigSelector() = default;
+
+// TODO(sandersd): Move contentType parsing from Blink to here so that invalid
+// parameters can be rejected. http://crbug.com/449690, http://crbug.com/690131
+bool KeySystemConfigSelector::IsSupportedContentType(
+ const std::string& key_system,
+ EmeMediaType media_type,
+ const std::string& container_mime_type,
+ const std::string& codecs,
+ KeySystemConfigSelector::ConfigState* config_state) {
+ DVLOG(3) << __func__ << ": key_system = " << key_system
+ << ", container_mime_type = " << container_mime_type
+ << ", codecs = " << codecs;
+
+ // From RFC6838: "Both top-level type and subtype names are case-insensitive."
+ std::string container_lower = base::ToLowerASCII(container_mime_type);
+
+ // contentTypes must provide a codec string unless the container implies a
+ // particular codec. For EME, none of the currently supported containers
+ // imply a codec, so |codecs| must be provided.
+ if (codecs.empty()) {
+ DVLOG(3) << "KeySystemConfig for " << container_mime_type
+ << " does not specify necessary codecs.";
+ return false;
+ }
+
+ // Check that |container_mime_type| and |codecs| are supported by Chrome. This
+ // is done primarily to validate extended codecs, but it also ensures that the
+ // CDM cannot support codecs that Chrome does not (which could complicate the
+ // robustness algorithm).
+ if (!is_supported_media_type_cb_.Run(
+ container_lower, codecs,
+ key_systems_->CanUseAesDecryptor(key_system))) {
+ DVLOG(3) << "Container mime type and codecs are not supported";
+ return false;
+ }
+
+ // Before checking CDM support, split |codecs| into a vector of codecs.
+ std::vector<std::string> codec_vector;
+ media::SplitCodecs(codecs, &codec_vector);
+
+ // Check that |container_lower| and |codec_vector| are supported by the CDM.
+ EmeConfigRule codecs_rule = key_systems_->GetContentTypeConfigRule(
+ key_system, media_type, container_lower, codec_vector);
+ if (!config_state->IsRuleSupported(codecs_rule)) {
+ DVLOG(3) << "Container mime type and codecs are not supported by CDM";
+ return false;
+ }
+ config_state->AddRule(codecs_rule);
+
+ return true;
+}
+
+EmeConfigRule KeySystemConfigSelector::GetEncryptionSchemeConfigRule(
+ const std::string& key_system,
+ const EmeEncryptionScheme encryption_scheme) {
+ switch (encryption_scheme) {
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysystemmediacapability-encryptionscheme
+ // "A value which is null or not present indicates to the user agent that
+ // no specific encryption scheme is required by the application, and
+ // therefore any encryption scheme is acceptable."
+ // To fully implement this, we need to get the config rules for both kCenc
+ // and kCbcs, which could be conflicting, and choose a final config rule
+ // somehow. If we end up choosing the rule for kCbcs, we could actually
+ // break legacy players which serves kCenc streams. Therefore, for backward
+ // compatibility and simplicity, we treat kNotSpecified the same as kCenc.
+ case EmeEncryptionScheme::kNotSpecified:
+ case EmeEncryptionScheme::kCenc:
+ return key_systems_->GetEncryptionSchemeConfigRule(
+ key_system, EncryptionScheme::kCenc);
+ case EmeEncryptionScheme::kCbcs:
+ case EmeEncryptionScheme::kCbcs_1_9:
+ return key_systems_->GetEncryptionSchemeConfigRule(
+ key_system, EncryptionScheme::kCbcs);
+ case EmeEncryptionScheme::kUnrecognized:
+ // https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
+ // "If encryption scheme is non-null and is not recognized or not
+ // supported by implementation, continue to the next iteration."
+ // The value provided was an empty string or some other value that is
+ // not recognized, so treat it as a scheme that is not supported.
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ NOTREACHED();
+ return EmeConfigRule::NOT_SUPPORTED;
+}
+
+bool KeySystemConfigSelector::GetSupportedCapabilities(
+ const std::string& key_system,
+ EmeMediaType media_type,
+ const WebVector<WebMediaKeySystemMediaCapability>&
+ requested_media_capabilities,
+ // Corresponds to the partial configuration, plus restrictions.
+ KeySystemConfigSelector::ConfigState* config_state,
+ std::vector<WebMediaKeySystemMediaCapability>*
+ supported_media_capabilities) {
+ // From "3.1.1.3 Get Supported Capabilities for Audio/Video Type".
+ // https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
+ // 1. Let local accumulated capabilities be a local copy of partial
+ // configuration.
+ // (Skipped as we directly update |config_state|. This is safe because we
+ // only do so when at least one requested media capability is supported.)
+ // 2. Let supported media capabilities be an empty sequence of
+ // MediaKeySystemMediaCapability dictionaries.
+ DCHECK_EQ(supported_media_capabilities->size(), 0ul);
+ // 3. For each requested media capability in requested media capabilities:
+ for (size_t i = 0; i < requested_media_capabilities.size(); i++) {
+ // 3.1. Let content type be requested media capability's contentType member.
+ // 3.2. Let robustness be requested media capability's robustness member.
+ const WebMediaKeySystemMediaCapability& capability =
+ requested_media_capabilities[i];
+ // 3.3. If contentType is the empty string, return null.
+ if (capability.mime_type.IsEmpty()) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "a capability contentType was empty.";
+ return false;
+ }
+
+ // Corresponds to the local accumulated configuration, plus restrictions.
+ ConfigState proposed_config_state = *config_state;
+
+ // 3.4-3.11. (Implemented by IsSupportedContentType().)
+ if (!capability.mime_type.ContainsOnlyASCII() ||
+ !capability.codecs.ContainsOnlyASCII() ||
+ !IsSupportedContentType(
+ key_system, media_type, capability.mime_type.Ascii(),
+ capability.codecs.Ascii(), &proposed_config_state)) {
+ DVLOG(3) << "The current capability is not supported.";
+ continue;
+ }
+
+ // 3.12. If robustness is not the empty string and contains an unrecognized
+ // value or a value not supported by implementation, continue to the
+ // next iteration. String comparison is case-sensitive.
+ // Note: If the robustness is empty, we still try to get the config rule
+ // from |key_systems_| for the empty robustness.
+ std::string requested_robustness_ascii;
+ if (!capability.robustness.IsEmpty()) {
+ if (!capability.robustness.ContainsOnlyASCII())
+ continue;
+ requested_robustness_ascii = capability.robustness.Ascii();
+ }
+ // Both of these should not be true.
+ DCHECK(!(proposed_config_state.AreHwSecureCodecsRequired() &&
+ proposed_config_state.AreHwSecureCodesNotAllowed()));
+ bool hw_secure_requirement;
+ bool* hw_secure_requirement_ptr = &hw_secure_requirement;
+ if (proposed_config_state.AreHwSecureCodecsRequired())
+ hw_secure_requirement = true;
+ else if (proposed_config_state.AreHwSecureCodesNotAllowed())
+ hw_secure_requirement = false;
+ else
+ hw_secure_requirement_ptr = nullptr;
+ EmeConfigRule robustness_rule = key_systems_->GetRobustnessConfigRule(
+ key_system, media_type, requested_robustness_ascii,
+ hw_secure_requirement_ptr);
+
+ // 3.13. If the user agent and implementation definitely support playback of
+ // encrypted media data for the combination of container, media types,
+ // robustness and local accumulated configuration in combination with
+ // restrictions:
+ if (!proposed_config_state.IsRuleSupported(robustness_rule)) {
+ DVLOG(3) << "The current robustness rule is not supported.";
+ continue;
+ }
+ proposed_config_state.AddRule(robustness_rule);
+
+ // Check for encryption scheme support.
+ // https://github.com/WICG/encrypted-media-encryption-scheme/blob/master/explainer.md.
+ EmeConfigRule encryption_scheme_rule =
+ GetEncryptionSchemeConfigRule(key_system, capability.encryption_scheme);
+ if (!proposed_config_state.IsRuleSupported(encryption_scheme_rule)) {
+ DVLOG(3) << "The current encryption scheme rule is not supported.";
+ continue;
+ }
+
+ // 3.13.1. Add requested media capability to supported media capabilities.
+ supported_media_capabilities->push_back(capability);
+
+ // 3.13.2. Add requested media capability to the {audio|video}Capabilities
+ // member of local accumulated configuration.
+ proposed_config_state.AddRule(encryption_scheme_rule);
+
+ // This is used as an intermediate variable so that |proposed_config_state|
+ // is updated in the next iteration of the for loop.
+ //
+ // Since |config_state| is also the output parameter, this also updates the
+ // "partial configuration" as specified in
+ // "Get Supported Configuration and Consent"
+ // https://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
+ // Step 16.3 and 17.3: Set the {video|audio}Capabilities member of
+ // accumulated configuration to {video|audio} capabilities.
+ //
+ // TODO(xhwang): Refactor this to be more consistent with the spec steps.
+ *config_state = proposed_config_state;
+ }
+
+ // 4. If supported media capabilities is empty, return null.
+ if (supported_media_capabilities->empty()) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "no capabilities were supported.";
+ return false;
+ }
+ // 5. Return media type capabilities.
+ // Note: |supported_media_capabilities| has already been populated.
+ return true;
+}
+
+KeySystemConfigSelector::ConfigurationSupport
+KeySystemConfigSelector::GetSupportedConfiguration(
+ const std::string& key_system,
+ const WebMediaKeySystemConfiguration& candidate,
+ ConfigState* config_state,
+ WebMediaKeySystemConfiguration* accumulated_configuration) {
+ DVLOG(3) << __func__;
+
+ // From
+ // http://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
+ // 1. Let accumulated configuration be a new MediaKeySystemConfiguration
+ // dictionary. (Done by caller.)
+ // 2. Set the label member of accumulated configuration to equal the label
+ // member of candidate configuration.
+ accumulated_configuration->label = candidate.label;
+
+ // 3. If the initDataTypes member of candidate configuration is non-empty,
+ // run the following steps:
+ if (!candidate.init_data_types.empty()) {
+ // 3.1. Let supported types be an empty sequence of DOMStrings.
+ std::vector<media::EmeInitDataType> supported_types;
+
+ // 3.2. For each value in candidate configuration's initDataTypes member:
+ for (size_t i = 0; i < candidate.init_data_types.size(); i++) {
+ // 3.2.1. Let initDataType be the value.
+ auto init_data_type = candidate.init_data_types[i];
+
+ // 3.2.2. If the implementation supports generating requests based on
+ // initDataType, add initDataType to supported types. String
+ // comparison is case-sensitive. The empty string is never
+ // supported.
+ if (key_systems_->IsSupportedInitDataType(key_system, init_data_type)) {
+ supported_types.push_back(init_data_type);
+ }
+ }
+
+ // 3.3. If supported types is empty, return null.
+ if (supported_types.empty()) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "no initDataType values were supported.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+
+ // 3.4. Set the initDataTypes member of accumulated configuration to
+ // supported types.
+ accumulated_configuration->init_data_types = supported_types;
+ }
+
+ // 4. Let distinctive identifier requirement be the value of candidate
+ // configuration's distinctiveIdentifier member.
+ EmeFeatureRequirement distinctive_identifier =
+ candidate.distinctive_identifier;
+
+ // 5. If distinctive identifier requirement is "optional" and Distinctive
+ // Identifiers are not allowed according to restrictions, set distinctive
+ // identifier requirement to "not-allowed".
+ if (distinctive_identifier == EmeFeatureRequirement::kOptional &&
+ !config_state->IsRuleSupported(EmeConfigRule::IDENTIFIER_REQUIRED)) {
+ distinctive_identifier = EmeFeatureRequirement::kNotAllowed;
+ }
+
+ // 6. Follow the steps for distinctive identifier requirement from the
+ // following list:
+ // - "required": If the implementation does not support use of
+ // Distinctive Identifier(s) in combination with accumulated
+ // configuration and restrictions, return NotSupported.
+ // - "optional": Continue with the following steps.
+ // - "not-allowed": If the implementation requires use Distinctive
+ // Identifier(s) or Distinctive Permanent Identifier(s) in
+ // combination with accumulated configuration and restrictions,
+ // return NotSupported.
+ // We also reject OPTIONAL when distinctive identifiers are ALWAYS_ENABLED and
+ // permission has already been denied. This would happen anyway later.
+ EmeFeatureSupport distinctive_identifier_support =
+ key_systems_->GetDistinctiveIdentifierSupport(key_system);
+#if !defined(OS_ANDROID)
+ // NOTE: This is an additional action we are taking here that is not in the
+ // spec currently. Specifically, we are not allowing a distinctive identifier
+ // for cross-origin frames. We do not do this on Android because there is no
+ // CDM selection available to Chrome that doesn't require a distinct
+ // identifier.
+ if (web_frame_delegate_->IsCrossOriginToMainFrame()) {
+ if (distinctive_identifier_support == EmeFeatureSupport::ALWAYS_ENABLED)
+ return CONFIGURATION_NOT_SUPPORTED;
+ distinctive_identifier_support = EmeFeatureSupport::NOT_SUPPORTED;
+ }
+#endif // !defined(OS_ANDROID)
+ EmeConfigRule di_rule = GetDistinctiveIdentifierConfigRule(
+ distinctive_identifier_support, distinctive_identifier);
+ if (!config_state->IsRuleSupported(di_rule)) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "the distinctiveIdentifier requirement was not supported.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+ config_state->AddRule(di_rule);
+
+ // 7. Set the distinctiveIdentifier member of accumulated configuration to
+ // equal distinctive identifier requirement.
+ accumulated_configuration->distinctive_identifier = distinctive_identifier;
+
+ // 8. Let persistent state requirement be equal to the value of candidate
+ // configuration's persistentState member.
+ EmeFeatureRequirement persistent_state = candidate.persistent_state;
+
+ // 9. If persistent state requirement is "optional" and persisting state is
+ // not allowed according to restrictions, set persistent state requirement
+ // to "not-allowed".
+ if (persistent_state == EmeFeatureRequirement::kOptional &&
+ !config_state->IsRuleSupported(EmeConfigRule::PERSISTENCE_REQUIRED)) {
+ persistent_state = EmeFeatureRequirement::kNotAllowed;
+ }
+
+ // 10. Follow the steps for persistent state requirement from the following
+ // list:
+ // - "required": If the implementation does not support persisting
+ // state in combination with accumulated configuration and
+ // restrictions, return NotSupported.
+ // - "optional": Continue with the following steps.
+ // - "not-allowed": If the implementation requires persisting state in
+ // combination with accumulated configuration and restrictions,
+ // return NotSupported.
+ EmeFeatureSupport persistent_state_support =
+ key_systems_->GetPersistentStateSupport(key_system);
+ // If preferences disallow local storage, then indicate persistent state is
+ // not supported.
+ if (!web_frame_delegate_->AllowStorageAccessSync(
+ WebContentSettingsClient::StorageType::kLocalStorage)) {
+ if (persistent_state_support == EmeFeatureSupport::ALWAYS_ENABLED)
+ return CONFIGURATION_NOT_SUPPORTED;
+ persistent_state_support = EmeFeatureSupport::NOT_SUPPORTED;
+ }
+ EmeConfigRule ps_rule =
+ GetPersistentStateConfigRule(persistent_state_support, persistent_state);
+ if (!config_state->IsRuleSupported(ps_rule)) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "the persistentState requirement was not supported.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+ config_state->AddRule(ps_rule);
+
+ // 11. Set the persistentState member of accumulated configuration to equal
+ // the value of persistent state requirement.
+ accumulated_configuration->persistent_state = persistent_state;
+
+ // 12. Follow the steps for the first matching condition from the following
+ // list:
+ // - If the sessionTypes member is present in candidate configuration,
+ // let session types be candidate configuration's sessionTypes member.
+ // - Otherwise, let session types be [ "temporary" ].
+ // (Done in MediaKeySystemAccessInitializer.)
+ WebVector<WebEncryptedMediaSessionType> session_types =
+ candidate.session_types;
+
+ // 13. For each value in session types:
+ for (size_t i = 0; i < session_types.size(); i++) {
+ // 13.1. Let session type be the value.
+ WebEncryptedMediaSessionType session_type = session_types[i];
+ if (session_type == WebEncryptedMediaSessionType::kUnknown) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "session type was not recognized.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+
+ // 13.2. If accumulated configuration's persistentState value is
+ // "not-allowed" and the Is persistent session type? algorithm
+ // returns true for session type return NotSupported.
+ if (accumulated_configuration->persistent_state ==
+ EmeFeatureRequirement::kNotAllowed &&
+ IsPersistentSessionType(session_type)) {
+ DVLOG(2) << "Rejecting requested configuration because persistent "
+ "sessions are not allowed.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+
+ // 13.3. If the implementation does not support session type in combination
+ // with accumulated configuration and restrictions for other reasons,
+ // return NotSupported.
+ EmeConfigRule session_type_rule = EmeConfigRule::NOT_SUPPORTED;
+ switch (session_type) {
+ case WebEncryptedMediaSessionType::kUnknown:
+ NOTREACHED();
+ return CONFIGURATION_NOT_SUPPORTED;
+ case WebEncryptedMediaSessionType::kTemporary:
+ session_type_rule = EmeConfigRule::SUPPORTED;
+ break;
+ case WebEncryptedMediaSessionType::kPersistentLicense:
+ session_type_rule = GetSessionTypeConfigRule(
+ key_systems_->GetPersistentLicenseSessionSupport(key_system));
+ break;
+ }
+
+ if (!config_state->IsRuleSupported(session_type_rule)) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "a required session type was not supported.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+ config_state->AddRule(session_type_rule);
+
+ // 13.4. If accumulated configuration's persistentState value is "optional"
+ // and the result of running the Is persistent session type?
+ // algorithm on session type is true, change accumulated
+ // configuration's persistentState value to "required".
+ if (accumulated_configuration->persistent_state ==
+ EmeFeatureRequirement::kOptional &&
+ IsPersistentSessionType(session_type)) {
+ accumulated_configuration->persistent_state =
+ EmeFeatureRequirement::kRequired;
+ }
+ }
+
+ // 14. Set the sessionTypes member of accumulated configuration to
+ // session types.
+ accumulated_configuration->session_types = session_types;
+
+ // 15. If the videoCapabilities and audioCapabilities members in candidate
+ // configuration are both empty, return NotSupported.
+ if (candidate.video_capabilities.empty() &&
+ candidate.audio_capabilities.empty()) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "neither audioCapabilities nor videoCapabilities is specified";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+
+ // 16. If the videoCapabilities member in candidate configuration is
+ // non-empty:
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities;
+ if (!candidate.video_capabilities.empty()) {
+ // 16.1. Let video capabilities be the result of executing the Get
+ // Supported Capabilities for Audio/Video Type algorithm on Video,
+ // candidate configuration's videoCapabilities member, accumulated
+ // configuration, and restrictions.
+ // 16.2. If video capabilities is null, return NotSupported.
+ if (!GetSupportedCapabilities(key_system, EmeMediaType::VIDEO,
+ candidate.video_capabilities, config_state,
+ &video_capabilities)) {
+ DVLOG(2) << "Rejecting requested configuration because the specified "
+ "videoCapabilities are not supported.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+
+ // 16.3. Set the videoCapabilities member of accumulated configuration
+ // to video capabilities.
+ accumulated_configuration->video_capabilities = video_capabilities;
+ } else {
+ // Otherwise set the videoCapabilities member of accumulated configuration
+ // to an empty sequence.
+ accumulated_configuration->video_capabilities = video_capabilities;
+ }
+
+ // 17. If the audioCapabilities member in candidate configuration is
+ // non-empty:
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities;
+ if (!candidate.audio_capabilities.empty()) {
+ // 17.1. Let audio capabilities be the result of executing the Get
+ // Supported Capabilities for Audio/Video Type algorithm on Audio,
+ // candidate configuration's audioCapabilities member, accumulated
+ // configuration, and restrictions.
+ // 17.2. If audio capabilities is null, return NotSupported.
+ if (!GetSupportedCapabilities(key_system, EmeMediaType::AUDIO,
+ candidate.audio_capabilities, config_state,
+ &audio_capabilities)) {
+ DVLOG(2) << "Rejecting requested configuration because the specified "
+ "audioCapabilities are not supported.";
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+
+ // 17.3. Set the audioCapabilities member of accumulated configuration
+ // to audio capabilities.
+ accumulated_configuration->audio_capabilities = audio_capabilities;
+ } else {
+ // Otherwise set the audioCapabilities member of accumulated configuration
+ // to an empty sequence.
+ accumulated_configuration->audio_capabilities = audio_capabilities;
+ }
+
+ // 18. If accumulated configuration's distinctiveIdentifier value is
+ // "optional", follow the steps for the first matching condition
+ // from the following list:
+ // - If the implementation requires use Distinctive Identifier(s) or
+ // Distinctive Permanent Identifier(s) for any of the combinations
+ // in accumulated configuration, change accumulated configuration's
+ // distinctiveIdentifier value to "required".
+ // - Otherwise, change accumulated configuration's
+ // distinctiveIdentifier value to "not-allowed".
+ if (accumulated_configuration->distinctive_identifier ==
+ EmeFeatureRequirement::kOptional) {
+ EmeConfigRule not_allowed_rule = GetDistinctiveIdentifierConfigRule(
+ key_systems_->GetDistinctiveIdentifierSupport(key_system),
+ EmeFeatureRequirement::kNotAllowed);
+ EmeConfigRule required_rule = GetDistinctiveIdentifierConfigRule(
+ key_systems_->GetDistinctiveIdentifierSupport(key_system),
+ EmeFeatureRequirement::kRequired);
+ bool not_allowed_supported =
+ config_state->IsRuleSupported(not_allowed_rule);
+ bool required_supported = config_state->IsRuleSupported(required_rule);
+ // If a distinctive identifier is recommend and that is a possible outcome,
+ // prefer that.
+ if (required_supported && config_state->IsIdentifierRecommended() &&
+ config_state->IsPermissionPossible()) {
+ not_allowed_supported = false;
+ }
+ if (not_allowed_supported) {
+ accumulated_configuration->distinctive_identifier =
+ EmeFeatureRequirement::kNotAllowed;
+ config_state->AddRule(not_allowed_rule);
+ } else if (required_supported) {
+ accumulated_configuration->distinctive_identifier =
+ EmeFeatureRequirement::kRequired;
+ config_state->AddRule(required_rule);
+ } else {
+ // We should not have passed step 6.
+ NOTREACHED();
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+ }
+
+ // 19. If accumulated configuration's persistentState value is "optional",
+ // follow the steps for the first matching condition from the following
+ // list:
+ // - If the implementation requires persisting state for any of the
+ // combinations in accumulated configuration, change accumulated
+ // configuration's persistentState value to "required".
+ // - Otherwise, change accumulated configuration's persistentState
+ // value to "not-allowed".
+ if (accumulated_configuration->persistent_state ==
+ EmeFeatureRequirement::kOptional) {
+ EmeConfigRule not_allowed_rule = GetPersistentStateConfigRule(
+ key_systems_->GetPersistentStateSupport(key_system),
+ EmeFeatureRequirement::kNotAllowed);
+ EmeConfigRule required_rule = GetPersistentStateConfigRule(
+ key_systems_->GetPersistentStateSupport(key_system),
+ EmeFeatureRequirement::kRequired);
+ // |persistent_state| should not be affected after it is decided.
+ DCHECK(not_allowed_rule == EmeConfigRule::NOT_SUPPORTED ||
+ not_allowed_rule == EmeConfigRule::PERSISTENCE_NOT_ALLOWED);
+ DCHECK(required_rule == EmeConfigRule::NOT_SUPPORTED ||
+ required_rule == EmeConfigRule::PERSISTENCE_REQUIRED);
+ bool not_allowed_supported =
+ config_state->IsRuleSupported(not_allowed_rule);
+ bool required_supported = config_state->IsRuleSupported(required_rule);
+ if (not_allowed_supported) {
+ accumulated_configuration->persistent_state =
+ EmeFeatureRequirement::kNotAllowed;
+ config_state->AddRule(not_allowed_rule);
+ } else if (required_supported) {
+ accumulated_configuration->persistent_state =
+ EmeFeatureRequirement::kRequired;
+ config_state->AddRule(required_rule);
+ } else {
+ // We should not have passed step 5.
+ NOTREACHED();
+ return CONFIGURATION_NOT_SUPPORTED;
+ }
+ }
+
+ // 20. If implementation in the configuration specified by the combination of
+ // the values in accumulated configuration is not supported or not allowed
+ // in the origin, return NotSupported.
+ // 21. If accumulated configuration's distinctiveIdentifier value is
+ // "required" and the Distinctive Identifier(s) associated with
+ // accumulated configuration are not unique per origin and profile
+ // and clearable:
+ // 21.1. Update restrictions to reflect that all configurations described
+ // by accumulated configuration do not have user consent.
+ // 21.2. Return ConsentDenied and restrictions.
+ // (Not required as data is unique per origin and clearable.)
+
+ // 22. Let consent status and updated restrictions be the result of running
+ // the Get Consent Status algorithm on accumulated configuration,
+ // restrictions and origin and follow the steps for the value of consent
+ // status from the following list:
+ // - "ConsentDenied": Return ConsentDenied and updated restrictions.
+ // - "InformUser": Inform the user that accumulated configuration is
+ // in use in the origin including, specifically, the information
+ // that Distinctive Identifier(s) and/or Distinctive Permanent
+ // Identifier(s) as appropriate will be used if the
+ // distinctiveIdentifier member of accumulated configuration is
+ // "required". Continue to the next step.
+ // - "Allowed": Continue to the next step.
+ // Accumulated configuration's distinctiveIdentifier should be "required" or
+ // "notallowed"" due to step 18. If it is "required", prompt the user for
+ // consent unless it has already been granted.
+ if (accumulated_configuration->distinctive_identifier ==
+ EmeFeatureRequirement::kRequired) {
+ // The caller is responsible for resolving what to do if permission is
+ // required but has been denied (it should treat it as NOT_SUPPORTED).
+ if (!config_state->IsPermissionGranted())
+ return CONFIGURATION_REQUIRES_PERMISSION;
+ }
+
+ // 23. Return accumulated configuration.
+ return CONFIGURATION_SUPPORTED;
+}
+
+void KeySystemConfigSelector::SelectConfig(
+ const WebString& key_system,
+ const WebVector<WebMediaKeySystemConfiguration>& candidate_configurations,
+ SelectConfigCB cb) {
+ // Continued from requestMediaKeySystemAccess(), step 6, from
+ // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess
+ //
+ // 6.1 If keySystem is not one of the Key Systems supported by the user
+ // agent, reject promise with a NotSupportedError. String comparison
+ // is case-sensitive.
+ if (!key_system.ContainsOnlyASCII()) {
+ std::move(cb).Run(Status::kUnsupportedKeySystem, nullptr, nullptr);
+ return;
+ }
+
+ key_systems_->UpdateIfNeeded();
+
+ std::string key_system_ascii = key_system.Ascii();
+ if (!key_systems_->IsSupportedKeySystem(key_system_ascii)) {
+ std::move(cb).Run(Status::kUnsupportedKeySystem, nullptr, nullptr);
+ return;
+ }
+
+ const bool is_encrypted_media_enabled =
+ media_permission_->IsEncryptedMediaEnabled();
+
+ // Only report this UMA at most once per renderer process.
+ static bool has_reported_encrypted_media_enabled_uma = false;
+ if (!has_reported_encrypted_media_enabled_uma) {
+ has_reported_encrypted_media_enabled_uma = true;
+ UMA_HISTOGRAM_BOOLEAN("Media.EME.EncryptedMediaEnabled",
+ is_encrypted_media_enabled);
+ }
+
+ // According to Section 9 "Common Key Systems": All user agents MUST support
+ // the common key systems described in this section.
+ // 9.1 Clear Key
+ //
+ // Therefore, always support Clear Key key system and only check settings for
+ // other key systems.
+ if (!is_encrypted_media_enabled && !media::IsClearKey(key_system_ascii)) {
+ std::move(cb).Run(Status::kUnsupportedKeySystem, nullptr, nullptr);
+ return;
+ }
+
+ // 6.2-6.4. Implemented by OnSelectConfig().
+ // TODO(sandersd): This should be async, ideally not on the main thread.
+ auto request = std::make_unique<SelectionRequest>();
+ request->key_system = key_system_ascii;
+ request->candidate_configurations = candidate_configurations;
+ request->cb = std::move(cb);
+ SelectConfigInternal(std::move(request));
+}
+
+void KeySystemConfigSelector::SelectConfigInternal(
+ std::unique_ptr<SelectionRequest> request) {
+ DVLOG(3) << __func__;
+
+ // Continued from requestMediaKeySystemAccess(), step 6, from
+ // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess
+ //
+ // 6.2. Let implementation be the implementation of keySystem.
+ // (|key_systems_| fills this role.)
+ // 6.3. For each value in supportedConfigurations:
+ for (size_t i = 0; i < request->candidate_configurations.size(); i++) {
+ // 6.3.1. Let candidate configuration be the value.
+ // 6.3.2. Let supported configuration be the result of executing the Get
+ // Supported Configuration algorithm on implementation, candidate
+ // configuration, and origin.
+ // 6.3.3. If supported configuration is not NotSupported, [initialize
+ // and return a new MediaKeySystemAccess object.]
+ ConfigState config_state(request->was_permission_requested,
+ request->is_permission_granted);
+ WebMediaKeySystemConfiguration accumulated_configuration;
+ media::CdmConfig cdm_config;
+ ConfigurationSupport support = GetSupportedConfiguration(
+ request->key_system, request->candidate_configurations[i],
+ &config_state, &accumulated_configuration);
+ switch (support) {
+ case CONFIGURATION_NOT_SUPPORTED:
+ continue;
+ case CONFIGURATION_REQUIRES_PERMISSION:
+ if (request->was_permission_requested) {
+ DVLOG(2) << "Rejecting requested configuration because "
+ << "permission was denied.";
+ continue;
+ }
+ DVLOG(3) << "Request permission.";
+ media_permission_->RequestPermission(
+ media::MediaPermission::PROTECTED_MEDIA_IDENTIFIER,
+ base::BindOnce(&KeySystemConfigSelector::OnPermissionResult,
+ weak_factory_.GetWeakPtr(), std::move(request)));
+ return;
+ case CONFIGURATION_SUPPORTED:
+ cdm_config.allow_distinctive_identifier =
+ (accumulated_configuration.distinctive_identifier ==
+ EmeFeatureRequirement::kRequired);
+ cdm_config.allow_persistent_state =
+ (accumulated_configuration.persistent_state ==
+ EmeFeatureRequirement::kRequired);
+ cdm_config.use_hw_secure_codecs =
+ config_state.AreHwSecureCodecsRequired();
+ std::move(request->cb)
+ .Run(Status::kSupported, &accumulated_configuration, &cdm_config);
+ return;
+ }
+ }
+
+ // 6.4. Reject promise with a NotSupportedError.
+ std::move(request->cb).Run(Status::kUnsupportedConfigs, nullptr, nullptr);
+}
+
+void KeySystemConfigSelector::OnPermissionResult(
+ std::unique_ptr<SelectionRequest> request,
+ bool is_permission_granted) {
+ DVLOG(3) << __func__;
+
+ request->was_permission_requested = true;
+ request->is_permission_granted = is_permission_granted;
+ SelectConfigInternal(std::move(request));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc b/chromium/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc
new file mode 100644
index 00000000000..0b8394f14a7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc
@@ -0,0 +1,1849 @@
+// 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/platform/media/key_system_config_selector.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/strings/pattern.h"
+#include "build/build_config.h"
+#include "media/base/cdm_config.h"
+#include "media/base/eme_constants.h"
+#include "media/base/key_systems.h"
+#include "media/base/media_permission.h"
+#include "media/base/mime_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/public/platform/web_encrypted_media_types.h"
+#include "third_party/blink/public/platform/web_media_key_system_configuration.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+namespace blink {
+namespace {
+
+using ::media::EmeConfigRule;
+using ::media::EmeFeatureSupport;
+using ::media::EmeInitDataType;
+using ::media::EmeMediaType;
+using ::media::EmeSessionTypeSupport;
+using MediaKeysRequirement = WebMediaKeySystemConfiguration::Requirement;
+using EncryptionScheme = WebMediaKeySystemMediaCapability::EncryptionScheme;
+
+// Key system strings. Clear Key support is hardcoded in KeySystemConfigSelector
+// so kClearKeyKeySystem is the real key system string. The rest key system
+// strings are for testing purpose only.
+const char kClearKeyKeySystem[] = "org.w3.clearkey";
+const char kSupportedKeySystem[] = "keysystem.test.supported";
+const char kUnsupportedKeySystem[] = "keysystem.test.unsupported";
+
+// Robustness strings for kSupportedKeySystem.
+const char kSupportedRobustness[] = "supported";
+const char kRecommendIdentifierRobustness[] = "recommend_identifier";
+const char kRequireIdentifierRobustness[] = "require_identifier";
+const char kDisallowHwSecureCodecRobustness[] = "disallow_hw_secure_codec";
+const char kRequireHwSecureCodecRobustness[] = "require_hw_secure_codec";
+const char kRequireIdentifierAndHwSecureCodecRobustness[] =
+ "require_identifier_and_hw_secure_codec";
+const char kRequireIdentifierPersistenceAndHwSecureCodecRobustness[] =
+ "require_identifier_persistence_and_hw_secure_codec";
+const char kUnsupportedRobustness[] = "unsupported";
+
+// Test container mime types. Supported types are prefixed with audio/video so
+// that the test can perform EmeMediaType check.
+const char kSupportedVideoContainer[] = "video/supported";
+const char kSupportedAudioContainer[] = "audio/supported";
+const char kUnsupportedContainer[] = "video/unsupported";
+const char kInvalidContainer[] = "video/invalid";
+
+// The codec strings. Supported types are prefixed with audio/video so
+// that the test can perform EmeMediaType check.
+// TODO(sandersd): Extended codec variants (requires proprietary codec support).
+// TODO(xhwang): Platform Opus is not available on all Android versions, where
+// some encrypted Opus related tests may fail. See
+// MediaCodecUtil::IsOpusDecoderAvailable() for more details.
+const char kSupportedAudioCodec[] = "audio_codec";
+const char kSupportedVideoCodec[] = "video_codec";
+const char kUnsupportedCodec[] = "unsupported_codec";
+const char kInvalidCodec[] = "foo";
+const char kRequireHwSecureCodec[] = "require_hw_secure_codec";
+const char kDisallowHwSecureCodec[] = "disallow_hw_secure_codec";
+const char kExtendedVideoCodec[] = "video_extended_codec.extended";
+const char kExtendedVideoCodecStripped[] = "video_extended_codec";
+// A special codec that is supported by the key systems, but is not supported
+// in IsSupportedMediaType() when |use_aes_decryptor| is true.
+const char kUnsupportedByAesDecryptorCodec[] = "unsupported_by_aes_decryptor";
+
+// Encryption schemes. For testing 'cenc' is supported, while 'cbcs' is not.
+// Note that WebMediaKeySystemMediaCapability defaults to kNotSpecified,
+// which is treated as 'cenc' by KeySystemConfigSelector.
+constexpr EncryptionScheme kSupportedEncryptionScheme = EncryptionScheme::kCenc;
+constexpr EncryptionScheme kDisallowHwSecureCodecEncryptionScheme =
+ EncryptionScheme::kCbcs;
+
+media::EncryptionScheme ConvertEncryptionScheme(
+ EncryptionScheme encryption_scheme) {
+ switch (encryption_scheme) {
+ case EncryptionScheme::kNotSpecified:
+ case EncryptionScheme::kCenc:
+ return media::EncryptionScheme::kCenc;
+ case EncryptionScheme::kCbcs:
+ case EncryptionScheme::kCbcs_1_9:
+ return media::EncryptionScheme::kCbcs;
+ case EncryptionScheme::kUnrecognized:
+ // Not used in these tests.
+ break;
+ }
+
+ NOTREACHED();
+ return media::EncryptionScheme::kUnencrypted;
+}
+
+WebString MakeCodecs(const std::string& a, const std::string& b) {
+ return WebString::FromUTF8(a + "," + b);
+}
+
+WebString GetSupportedVideoCodecs() {
+ return MakeCodecs(kSupportedVideoCodec, kSupportedVideoCodec);
+}
+
+WebString GetSubsetSupportedVideoCodecs() {
+ return MakeCodecs(kSupportedVideoCodec, kUnsupportedCodec);
+}
+
+WebString GetSubsetInvalidVideoCodecs() {
+ return MakeCodecs(kSupportedVideoCodec, kInvalidCodec);
+}
+
+bool IsValidContainerMimeType(const std::string& container_mime_type) {
+ return container_mime_type != kInvalidContainer;
+}
+
+bool IsValidCodec(const std::string& codec) {
+ return codec != kInvalidCodec;
+}
+
+// Returns whether |type| is compatible with |media_type|.
+bool IsCompatibleWithEmeMediaType(EmeMediaType media_type,
+ const std::string& type) {
+ if (media_type == EmeMediaType::AUDIO && base::MatchPattern(type, "video*"))
+ return false;
+
+ if (media_type == EmeMediaType::VIDEO && base::MatchPattern(type, "audio*"))
+ return false;
+
+ return true;
+}
+
+// Pretend that we support all |container_mime_type| and |codecs| except for
+// those explicitly marked as invalid.
+bool IsSupportedMediaType(const std::string& container_mime_type,
+ const std::string& codecs,
+ bool use_aes_decryptor) {
+ if (container_mime_type == kInvalidContainer)
+ return false;
+
+ std::vector<std::string> codec_vector;
+ media::SplitCodecs(codecs, &codec_vector);
+ for (const std::string& codec : codec_vector) {
+ DCHECK_NE(codec, kExtendedVideoCodecStripped)
+ << "codecs passed into this function should not be stripped";
+
+ if (codec == kInvalidCodec)
+ return false;
+
+ if (use_aes_decryptor && codec == kUnsupportedByAesDecryptorCodec)
+ return false;
+ }
+
+ return true;
+}
+
+// The IDL for MediaKeySystemConfiguration specifies some defaults, so
+// create a config object that mimics what would be created if an empty
+// dictionary was passed in.
+WebMediaKeySystemConfiguration EmptyConfiguration() {
+ // http://w3c.github.io/encrypted-media/#mediakeysystemconfiguration-dictionary
+ // If this member (sessionTypes) is not present when the dictionary
+ // is passed to requestMediaKeySystemAccess(), the dictionary will
+ // be treated as if this member is set to [ "temporary" ].
+ std::vector<WebEncryptedMediaSessionType> session_types;
+ session_types.push_back(WebEncryptedMediaSessionType::kTemporary);
+
+ WebMediaKeySystemConfiguration config;
+ config.label = "";
+ config.session_types = session_types;
+ return config;
+}
+
+// EME spec requires that at least one of |video_capabilities| and
+// |audio_capabilities| be specified. Add a single valid audio capability
+// to the EmptyConfiguration().
+WebMediaKeySystemConfiguration UsableConfiguration() {
+ // Blink code parses the contentType into mimeType and codecs, so mimic
+ // that here.
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities(1);
+ audio_capabilities[0].mime_type = kSupportedAudioContainer;
+ audio_capabilities[0].codecs = kSupportedAudioCodec;
+
+ auto config = EmptyConfiguration();
+ config.audio_capabilities = audio_capabilities;
+ return config;
+}
+
+class FakeKeySystems : public media::KeySystems {
+ public:
+ ~FakeKeySystems() override = default;
+
+ void UpdateIfNeeded() override { ++update_count; }
+
+ bool IsSupportedKeySystem(const std::string& key_system) const override {
+ // Based on EME spec, Clear Key key system is always supported.
+ return key_system == kSupportedKeySystem ||
+ key_system == kClearKeyKeySystem;
+ }
+
+ bool CanUseAesDecryptor(const std::string& key_system) const override {
+ return key_system == kClearKeyKeySystem;
+ }
+
+ // TODO(sandersd): Move implementation into KeySystemConfigSelector?
+ bool IsSupportedInitDataType(const std::string& key_system,
+ EmeInitDataType init_data_type) const override {
+ switch (init_data_type) {
+ case EmeInitDataType::UNKNOWN:
+ return false;
+ case EmeInitDataType::WEBM:
+ return init_data_type_webm_supported_;
+ case EmeInitDataType::CENC:
+ return init_data_type_cenc_supported_;
+ case EmeInitDataType::KEYIDS:
+ return init_data_type_keyids_supported_;
+ }
+ NOTREACHED();
+ return false;
+ }
+
+ EmeConfigRule GetEncryptionSchemeConfigRule(
+ const std::string& key_system,
+ media::EncryptionScheme encryption_scheme) const override {
+ if (encryption_scheme ==
+ ConvertEncryptionScheme(kSupportedEncryptionScheme)) {
+ return EmeConfigRule::SUPPORTED;
+ }
+
+ if (encryption_scheme ==
+ ConvertEncryptionScheme(kDisallowHwSecureCodecEncryptionScheme)) {
+ return EmeConfigRule::HW_SECURE_CODECS_NOT_ALLOWED;
+ }
+
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ EmeConfigRule GetContentTypeConfigRule(
+ const std::string& key_system,
+ EmeMediaType media_type,
+ const std::string& container_mime_type,
+ const std::vector<std::string>& codecs) const override {
+ DCHECK(IsValidContainerMimeType(container_mime_type))
+ << "Invalid container mime type should not be passed in";
+ if (container_mime_type == kUnsupportedContainer ||
+ !IsCompatibleWithEmeMediaType(media_type, container_mime_type)) {
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ bool hw_secure_codec_required_ = false;
+ bool hw_secure_codec_not_allowed_ = false;
+
+ for (const std::string& codec : codecs) {
+ DCHECK(IsValidCodec(codec)) << "Invalid codec should not be passed in";
+
+ if (codec == kUnsupportedCodec ||
+ !IsCompatibleWithEmeMediaType(media_type, codec)) {
+ return EmeConfigRule::NOT_SUPPORTED;
+ } else if (codec == kRequireHwSecureCodec) {
+ hw_secure_codec_required_ = true;
+ } else if (codec == kDisallowHwSecureCodec) {
+ hw_secure_codec_not_allowed_ = true;
+ }
+ }
+
+ if (hw_secure_codec_required_) {
+ if (hw_secure_codec_not_allowed_)
+ return EmeConfigRule::NOT_SUPPORTED;
+ else
+ return EmeConfigRule::HW_SECURE_CODECS_REQUIRED;
+ }
+
+ if (hw_secure_codec_not_allowed_)
+ return EmeConfigRule::HW_SECURE_CODECS_NOT_ALLOWED;
+
+ return EmeConfigRule::SUPPORTED;
+ }
+
+ EmeConfigRule GetRobustnessConfigRule(
+ const std::string& key_system,
+ EmeMediaType media_type,
+ const std::string& requested_robustness,
+ const bool* hw_secure_requirement) const override {
+ // TODO(crbug.com/1204284): Remove the `hw_secure_requirement` parameter.
+ // This only exists as a temporary solution until a larger refactoring is
+ // done. We are only testing the explicit thing it is fixing here.
+ if (hw_secure_requirement && *hw_secure_requirement &&
+ distinctive_identifier == EmeFeatureSupport::NOT_SUPPORTED) {
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+ if (requested_robustness.empty())
+ return EmeConfigRule::SUPPORTED;
+ if (requested_robustness == kSupportedRobustness)
+ return EmeConfigRule::SUPPORTED;
+ if (requested_robustness == kRequireIdentifierRobustness)
+ return EmeConfigRule::IDENTIFIER_REQUIRED;
+ if (requested_robustness == kRecommendIdentifierRobustness)
+ return EmeConfigRule::IDENTIFIER_RECOMMENDED;
+ if (requested_robustness == kDisallowHwSecureCodecRobustness)
+ return EmeConfigRule::HW_SECURE_CODECS_NOT_ALLOWED;
+ if (requested_robustness == kRequireHwSecureCodecRobustness)
+ return EmeConfigRule::HW_SECURE_CODECS_REQUIRED;
+ if (requested_robustness == kRequireIdentifierAndHwSecureCodecRobustness)
+ return EmeConfigRule::IDENTIFIER_AND_HW_SECURE_CODECS_REQUIRED;
+ if (requested_robustness ==
+ kRequireIdentifierPersistenceAndHwSecureCodecRobustness) {
+ return EmeConfigRule::
+ IDENTIFIER_PERSISTENCE_AND_HW_SECURE_CODECS_REQUIRED;
+ }
+ if (requested_robustness == kUnsupportedRobustness)
+ return EmeConfigRule::NOT_SUPPORTED;
+
+ NOTREACHED();
+ return EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ EmeSessionTypeSupport GetPersistentLicenseSessionSupport(
+ const std::string& key_system) const override {
+ return persistent_license;
+ }
+
+ EmeFeatureSupport GetPersistentStateSupport(
+ const std::string& key_system) const override {
+ return persistent_state;
+ }
+
+ EmeFeatureSupport GetDistinctiveIdentifierSupport(
+ const std::string& key_system) const override {
+ return distinctive_identifier;
+ }
+
+ bool init_data_type_webm_supported_ = false;
+ bool init_data_type_cenc_supported_ = false;
+ bool init_data_type_keyids_supported_ = false;
+
+ // INVALID so that they must be set in any test that needs them.
+ EmeSessionTypeSupport persistent_license = EmeSessionTypeSupport::INVALID;
+
+ // Every test implicitly requires these, so they must be set. They are set to
+ // values that are likely to cause tests to fail if they are accidentally
+ // depended on. Test cases explicitly depending on them should set them, as
+ // the default values may be changed.
+ EmeFeatureSupport persistent_state = EmeFeatureSupport::NOT_SUPPORTED;
+ EmeFeatureSupport distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ int update_count = 0;
+};
+
+class FakeMediaPermission : public media::MediaPermission {
+ public:
+ // MediaPermission implementation.
+ void HasPermission(Type type,
+ PermissionStatusCB permission_status_cb) override {
+ std::move(permission_status_cb).Run(is_granted);
+ }
+
+ void RequestPermission(Type type,
+ PermissionStatusCB permission_status_cb) override {
+ requests++;
+ std::move(permission_status_cb).Run(is_granted);
+ }
+
+ bool IsEncryptedMediaEnabled() override { return is_encrypted_media_enabled; }
+
+ int requests = 0;
+ bool is_granted = false;
+ bool is_encrypted_media_enabled = true;
+};
+
+class FakeWebLocalFrameDelegate
+ : public KeySystemConfigSelector::WebLocalFrameDelegate {
+ public:
+ FakeWebLocalFrameDelegate()
+ : KeySystemConfigSelector::WebLocalFrameDelegate(nullptr) {}
+ bool IsCrossOriginToMainFrame() override { return is_cross_origin_; }
+ bool AllowStorageAccessSync(
+ WebContentSettingsClient::StorageType storage_type) override {
+ if (storage_type == WebContentSettingsClient::StorageType::kLocalStorage) {
+ return local_storage_allowed_;
+ }
+ return true;
+ }
+
+ bool is_cross_origin_ = false;
+ bool local_storage_allowed_ = true;
+};
+
+} // namespace
+
+class KeySystemConfigSelectorTest : public testing::Test {
+ public:
+ KeySystemConfigSelectorTest()
+ : key_systems_(std::make_unique<FakeKeySystems>()),
+ media_permission_(std::make_unique<FakeMediaPermission>()),
+ web_frame_delegate_(std::make_unique<FakeWebLocalFrameDelegate>()) {}
+ KeySystemConfigSelectorTest(const KeySystemConfigSelectorTest&) = delete;
+ KeySystemConfigSelectorTest& operator=(const KeySystemConfigSelectorTest&) =
+ delete;
+
+ void SelectConfig() {
+ media_permission_->requests = 0;
+ succeeded_count_ = 0;
+ not_supported_count_ = 0;
+ KeySystemConfigSelector key_system_config_selector(
+ key_systems_.get(), media_permission_.get(),
+ std::move(web_frame_delegate_));
+ // Replace the delegate with a new one to handle tests that call this
+ // method multiple times. This is safe because they don't use the delegate
+ // in testing.
+ web_frame_delegate_ = std::make_unique<FakeWebLocalFrameDelegate>();
+
+ key_system_config_selector.SetIsSupportedMediaTypeCBForTesting(
+ base::BindRepeating(&IsSupportedMediaType));
+
+ key_system_config_selector.SelectConfig(
+ key_system_, configs_,
+ base::BindOnce(&KeySystemConfigSelectorTest::OnConfigSelected,
+ base::Unretained(this)));
+ }
+
+ void SelectConfigReturnsConfig() {
+ SelectConfig();
+ EXPECT_EQ(0, media_permission_->requests);
+ EXPECT_EQ(1, succeeded_count_);
+ EXPECT_EQ(0, not_supported_count_);
+ ASSERT_NE(succeeded_count_, 0);
+ }
+
+ void SelectConfigReturnsError() {
+ SelectConfig();
+ EXPECT_EQ(0, media_permission_->requests);
+ EXPECT_EQ(0, succeeded_count_);
+ EXPECT_EQ(1, not_supported_count_);
+ ASSERT_NE(not_supported_count_, 0);
+ }
+
+ void SelectConfigRequestsPermissionAndReturnsConfig() {
+ SelectConfig();
+ EXPECT_EQ(1, media_permission_->requests);
+ EXPECT_EQ(1, succeeded_count_);
+ EXPECT_EQ(0, not_supported_count_);
+ ASSERT_NE(media_permission_->requests, 0);
+ ASSERT_NE(succeeded_count_, 0);
+ }
+
+ void SelectConfigRequestsPermissionAndReturnsError() {
+ SelectConfig();
+ EXPECT_EQ(1, media_permission_->requests);
+ EXPECT_EQ(0, succeeded_count_);
+ EXPECT_EQ(1, not_supported_count_);
+ ASSERT_NE(media_permission_->requests, 0);
+ ASSERT_NE(not_supported_count_, 0);
+ }
+
+ void OnConfigSelected(KeySystemConfigSelector::Status status,
+ WebMediaKeySystemConfiguration* config,
+ media::CdmConfig* cdm_config) {
+ if (status == KeySystemConfigSelector::Status::kSupported) {
+ succeeded_count_++;
+ config_ = *config;
+ cdm_config_ = *cdm_config;
+ } else {
+ not_supported_count_++;
+ }
+ }
+
+ std::unique_ptr<FakeKeySystems> key_systems_;
+ std::unique_ptr<FakeMediaPermission> media_permission_;
+ std::unique_ptr<FakeWebLocalFrameDelegate> web_frame_delegate_;
+
+ // Held values for the call to SelectConfig().
+ WebString key_system_ = WebString::FromUTF8(kSupportedKeySystem);
+ std::vector<WebMediaKeySystemConfiguration> configs_;
+
+ // Holds the selected configuration and CdmConfig.
+ WebMediaKeySystemConfiguration config_;
+ media::CdmConfig cdm_config_;
+
+ int succeeded_count_;
+ int not_supported_count_;
+};
+
+// --- Basics ---
+
+TEST_F(KeySystemConfigSelectorTest, NoConfigs) {
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, DefaultConfig) {
+ auto config = EmptyConfiguration();
+
+ // label = "";
+ ASSERT_EQ("", config.label);
+
+ // initDataTypes = [];
+ ASSERT_EQ(0u, config.init_data_types.size());
+
+ // audioCapabilities = [];
+ ASSERT_EQ(0u, config.audio_capabilities.size());
+
+ // videoCapabilities = [];
+ ASSERT_EQ(0u, config.video_capabilities.size());
+
+ // distinctiveIdentifier = "optional";
+ ASSERT_EQ(MediaKeysRequirement::kOptional, config.distinctive_identifier);
+
+ // persistentState = "optional";
+ ASSERT_EQ(MediaKeysRequirement::kOptional, config.persistent_state);
+
+ // If this member is not present when the dictionary is passed to
+ // requestMediaKeySystemAccess(), the dictionary will be treated as
+ // if this member is set to [ "temporary" ].
+ ASSERT_EQ(1u, config.session_types.size());
+ ASSERT_EQ(WebEncryptedMediaSessionType::kTemporary, config.session_types[0]);
+}
+
+TEST_F(KeySystemConfigSelectorTest, EmptyConfig) {
+ // EME spec requires that at least one of |video_capabilities| and
+ // |audio_capabilities| be specified.
+ configs_.push_back(EmptyConfiguration());
+ SelectConfigReturnsError();
+}
+
+// Most of the tests below assume that the the usable config is valid.
+// Tests that touch |video_capabilities| and/or |audio_capabilities| can
+// modify the empty config.
+
+TEST_F(KeySystemConfigSelectorTest, UsableConfig) {
+ configs_.push_back(UsableConfiguration());
+
+ SelectConfigReturnsConfig();
+
+ EXPECT_EQ("", config_.label);
+ EXPECT_TRUE(config_.init_data_types.empty());
+ EXPECT_EQ(1u, config_.audio_capabilities.size());
+ EXPECT_TRUE(config_.video_capabilities.empty());
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.distinctive_identifier);
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.persistent_state);
+ ASSERT_EQ(1u, config_.session_types.size());
+ EXPECT_EQ(WebEncryptedMediaSessionType::kTemporary, config_.session_types[0]);
+
+ EXPECT_FALSE(cdm_config_.allow_distinctive_identifier);
+ EXPECT_FALSE(cdm_config_.allow_persistent_state);
+ EXPECT_FALSE(cdm_config_.use_hw_secure_codecs);
+}
+
+// KeySystemConfigSelector should make sure it uses up-to-date KeySystems.
+TEST_F(KeySystemConfigSelectorTest, UpdateKeySystems) {
+ configs_.push_back(UsableConfiguration());
+
+ ASSERT_EQ(key_systems_->update_count, 0);
+ SelectConfig();
+ EXPECT_EQ(key_systems_->update_count, 1);
+ SelectConfig();
+ EXPECT_EQ(key_systems_->update_count, 2);
+}
+
+TEST_F(KeySystemConfigSelectorTest, Label) {
+ auto config = UsableConfiguration();
+ config.label = "foo";
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ("foo", config_.label);
+}
+
+// --- keySystem ---
+// Empty is not tested because the empty check is in Blink.
+
+TEST_F(KeySystemConfigSelectorTest, KeySystem_NonAscii) {
+ key_system_ = "\xde\xad\xbe\xef";
+ configs_.push_back(UsableConfiguration());
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, KeySystem_Unsupported) {
+ key_system_ = kUnsupportedKeySystem;
+ configs_.push_back(UsableConfiguration());
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, KeySystem_ClearKey) {
+ key_system_ = kClearKeyKeySystem;
+ configs_.push_back(UsableConfiguration());
+ SelectConfigReturnsConfig();
+}
+
+// --- Disable EncryptedMedia ---
+
+TEST_F(KeySystemConfigSelectorTest, EncryptedMediaDisabled_ClearKey) {
+ media_permission_->is_encrypted_media_enabled = false;
+
+ // Clear Key key system is always supported.
+ key_system_ = kClearKeyKeySystem;
+ configs_.push_back(UsableConfiguration());
+ SelectConfigReturnsConfig();
+}
+
+TEST_F(KeySystemConfigSelectorTest, EncryptedMediaDisabled_Supported) {
+ media_permission_->is_encrypted_media_enabled = false;
+
+ // Other key systems are not supported.
+ key_system_ = kSupportedKeySystem;
+ configs_.push_back(UsableConfiguration());
+ SelectConfigReturnsError();
+}
+
+// --- initDataTypes ---
+
+TEST_F(KeySystemConfigSelectorTest, InitDataTypes_Empty) {
+ auto config = UsableConfiguration();
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+}
+
+TEST_F(KeySystemConfigSelectorTest, InitDataTypes_NoneSupported) {
+ key_systems_->init_data_type_webm_supported_ = true;
+
+ std::vector<EmeInitDataType> init_data_types;
+ init_data_types.push_back(EmeInitDataType::UNKNOWN);
+ init_data_types.push_back(EmeInitDataType::CENC);
+
+ auto config = UsableConfiguration();
+ config.init_data_types = init_data_types;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, InitDataTypes_SubsetSupported) {
+ key_systems_->init_data_type_webm_supported_ = true;
+
+ std::vector<EmeInitDataType> init_data_types;
+ init_data_types.push_back(EmeInitDataType::UNKNOWN);
+ init_data_types.push_back(EmeInitDataType::CENC);
+ init_data_types.push_back(EmeInitDataType::WEBM);
+
+ auto config = UsableConfiguration();
+ config.init_data_types = init_data_types;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.init_data_types.size());
+ EXPECT_EQ(EmeInitDataType::WEBM, config_.init_data_types[0]);
+}
+
+// --- distinctiveIdentifier ---
+
+TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_Default) {
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.distinctive_identifier);
+ EXPECT_FALSE(cdm_config_.allow_distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_Forced) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::ALWAYS_ENABLED;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ EXPECT_TRUE(cdm_config_.allow_distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_Blocked) {
+ key_systems_->distinctive_identifier = EmeFeatureSupport::NOT_SUPPORTED;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_RequestsPermission) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ EXPECT_TRUE(cdm_config_.allow_distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_RespectsPermission) {
+ media_permission_->is_granted = false;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_DefaultCrossOrigin) {
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+ web_frame_delegate_->is_cross_origin_ = true;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.distinctive_identifier);
+ EXPECT_FALSE(cdm_config_.allow_distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ DistinctiveIdentifier_ForcedBlockedByCrossOrigin) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::ALWAYS_ENABLED;
+ web_frame_delegate_->is_cross_origin_ = true;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+#if defined(OS_ANDROID)
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ EXPECT_TRUE(cdm_config_.allow_distinctive_identifier);
+#else
+ SelectConfigReturnsError();
+#endif // defined(OS_ANDROID)
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ DistinctiveIdentifier_RequestsPermissionBlockedByCrossOrigin) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+ web_frame_delegate_->is_cross_origin_ = true;
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+#if defined(OS_ANDROID)
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ EXPECT_TRUE(cdm_config_.allow_distinctive_identifier);
+#else
+ SelectConfigReturnsError();
+#endif // defined(OS_ANDROID)
+}
+
+// --- persistentState ---
+
+TEST_F(KeySystemConfigSelectorTest, PersistentState_Default) {
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.persistent_state);
+ EXPECT_FALSE(cdm_config_.allow_persistent_state);
+}
+
+TEST_F(KeySystemConfigSelectorTest, PersistentState_Forced) {
+ key_systems_->persistent_state = EmeFeatureSupport::ALWAYS_ENABLED;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.persistent_state);
+ EXPECT_TRUE(cdm_config_.allow_persistent_state);
+}
+
+TEST_F(KeySystemConfigSelectorTest, PersistentState_Required) {
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.persistent_state);
+ EXPECT_TRUE(cdm_config_.allow_persistent_state);
+}
+
+TEST_F(KeySystemConfigSelectorTest, PersistentState_Blocked) {
+ key_systems_->persistent_state = EmeFeatureSupport::ALWAYS_ENABLED;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kNotAllowed;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, PersistentState_BlockedByContentSettings) {
+ key_systems_->persistent_state = EmeFeatureSupport::ALWAYS_ENABLED;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+ web_frame_delegate_->local_storage_allowed_ = false;
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ PersistentState_ForcedBlockedByContentSettings) {
+ key_systems_->persistent_state = EmeFeatureSupport::ALWAYS_ENABLED;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kOptional;
+ configs_.push_back(config);
+
+ web_frame_delegate_->local_storage_allowed_ = false;
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ PersistentState_RequiredBlockedByContentSettings) {
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kRequired;
+ configs_.push_back(config);
+
+ web_frame_delegate_->local_storage_allowed_ = false;
+ SelectConfigReturnsError();
+}
+
+// --- sessionTypes ---
+
+TEST_F(KeySystemConfigSelectorTest, SessionTypes_Empty) {
+ auto config = UsableConfiguration();
+
+ // Usable configuration has [ "temporary" ].
+ std::vector<WebEncryptedMediaSessionType> session_types;
+ config.session_types = session_types;
+
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_TRUE(config_.session_types.empty());
+}
+
+TEST_F(KeySystemConfigSelectorTest, SessionTypes_SubsetSupported) {
+ // Allow persistent state, as it would be required to be successful.
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+ key_systems_->persistent_license = EmeSessionTypeSupport::NOT_SUPPORTED;
+
+ std::vector<WebEncryptedMediaSessionType> session_types;
+ session_types.push_back(WebEncryptedMediaSessionType::kTemporary);
+ session_types.push_back(WebEncryptedMediaSessionType::kPersistentLicense);
+
+ auto config = UsableConfiguration();
+ config.session_types = session_types;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, SessionTypes_AllSupported) {
+ // Allow persistent state, and expect it to be required.
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+ key_systems_->persistent_license = EmeSessionTypeSupport::SUPPORTED;
+
+ std::vector<WebEncryptedMediaSessionType> session_types;
+ session_types.push_back(WebEncryptedMediaSessionType::kTemporary);
+ session_types.push_back(WebEncryptedMediaSessionType::kPersistentLicense);
+
+ auto config = UsableConfiguration();
+ config.persistent_state = MediaKeysRequirement::kOptional;
+ config.session_types = session_types;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.persistent_state);
+ ASSERT_EQ(2u, config_.session_types.size());
+ EXPECT_EQ(WebEncryptedMediaSessionType::kTemporary, config_.session_types[0]);
+ EXPECT_EQ(WebEncryptedMediaSessionType::kPersistentLicense,
+ config_.session_types[1]);
+}
+
+TEST_F(KeySystemConfigSelectorTest, SessionTypes_PermissionCanBeRequired) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+ key_systems_->persistent_license =
+ EmeSessionTypeSupport::SUPPORTED_WITH_IDENTIFIER;
+
+ std::vector<WebEncryptedMediaSessionType> session_types;
+ session_types.push_back(WebEncryptedMediaSessionType::kPersistentLicense);
+
+ auto config = UsableConfiguration();
+ config.distinctive_identifier = MediaKeysRequirement::kOptional;
+ config.persistent_state = MediaKeysRequirement::kOptional;
+ config.session_types = session_types;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+}
+
+// --- videoCapabilities ---
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Empty) {
+ auto config = UsableConfiguration();
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_ExtendedCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kExtendedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_InvalidContainer) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kInvalidContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_UnsupportedContainer) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kUnsupportedContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_IncompatibleContainer) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedAudioContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_InvalidCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kInvalidCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_UnsupportedCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kInvalidContainer;
+ video_capabilities[0].codecs = kUnsupportedCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_IncompatibleCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedAudioCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_UnsupportedByAesDecryptorCodec_ClearKey) {
+ key_system_ = kClearKeyKeySystem;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kUnsupportedByAesDecryptorCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_UnsupportedByAesDecryptorCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kUnsupportedByAesDecryptorCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_SubsetSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kInvalidContainer;
+ video_capabilities[1].content_type = "b";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("b", config_.video_capabilities[0].content_type);
+ EXPECT_EQ(kSupportedVideoContainer, config_.video_capabilities[0].mime_type);
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_AllSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = GetSupportedVideoCodecs();
+ video_capabilities[1].content_type = "b";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = GetSupportedVideoCodecs();
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(2u, config_.video_capabilities.size());
+ EXPECT_EQ("a", config_.video_capabilities[0].content_type);
+ EXPECT_EQ("b", config_.video_capabilities[1].content_type);
+}
+
+// --- videoCapabilities Codecs ---
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Codecs_SubsetInvalid) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = GetSubsetInvalidVideoCodecs();
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Codecs_SubsetSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = GetSubsetSupportedVideoCodecs();
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Codecs_AllSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = GetSupportedVideoCodecs();
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ(GetSupportedVideoCodecs(), config_.video_capabilities[0].codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Missing_Codecs) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+// --- videoCapabilities Robustness ---
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Robustness_Empty) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ ASSERT_TRUE(video_capabilities[0].robustness.IsEmpty());
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_TRUE(config_.video_capabilities[0].robustness.IsEmpty());
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Robustness_Supported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kSupportedRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ(kSupportedRobustness, config_.video_capabilities[0].robustness);
+}
+
+TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Robustness_Unsupported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kUnsupportedRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_Robustness_PermissionCanBeRequired) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kRequireIdentifierRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_Robustness_PermissionCanBeRecommended) {
+ media_permission_->is_granted = false;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kRecommendIdentifierRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_Robustness_PermissionCanBeRecommendedAndGranted) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kRecommendIdentifierRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_Robustness_NoPermissionRecommendedCrossOrigin) {
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+ web_frame_delegate_->is_cross_origin_ = true;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kRecommendIdentifierRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+#if defined(OS_ANDROID)
+ SelectConfigRequestsPermissionAndReturnsConfig();
+#else
+ SelectConfigReturnsConfig();
+#endif // defined(OS_ANDROID)
+ EXPECT_EQ(MediaKeysRequirement::kNotAllowed, config_.distinctive_identifier);
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_EncryptionScheme_Supported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].encryption_scheme = kSupportedEncryptionScheme;
+
+ WebMediaKeySystemConfiguration config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ(kSupportedEncryptionScheme,
+ config_.video_capabilities[0].encryption_scheme);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ VideoCapabilities_EncryptionScheme_DisallowHwSecureCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].encryption_scheme =
+ kDisallowHwSecureCodecEncryptionScheme;
+
+ WebMediaKeySystemConfiguration config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ(kDisallowHwSecureCodecEncryptionScheme,
+ config_.video_capabilities[0].encryption_scheme);
+}
+
+// --- HW Secure Codecs and Robustness ---
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_RequireHwSecureCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kRequireHwSecureCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_DisallowHwSecureCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kDisallowHwSecureCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_FALSE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ HwSecureCodec_IncompatibleCodecAndRobustness) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kDisallowHwSecureCodec;
+ video_capabilities[0].robustness = kRequireHwSecureCodecRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_CompatibleCodecs) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs =
+ MakeCodecs(kRequireHwSecureCodec, kSupportedVideoCodec);
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_IncompatibleCodecs) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs =
+ MakeCodecs(kRequireHwSecureCodec, kDisallowHwSecureCodec);
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_CompatibleCapabilityCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kRequireHwSecureCodec;
+ video_capabilities[1].content_type = "supported_video_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(2u, config_.video_capabilities.size());
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_RequireAndDisallow) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kRequireHwSecureCodec;
+ video_capabilities[1].content_type = "disallow_hw_secure_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kDisallowHwSecureCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("require_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_DisallowAndRequire) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "disallow_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kDisallowHwSecureCodec;
+ video_capabilities[1].content_type = "require_hw_secure_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kRequireHwSecureCodec;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("disallow_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_FALSE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_IncompatibleCapabilities) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness = kRequireHwSecureCodecRobustness;
+ video_capabilities[1].content_type = "disallow_hw_secure_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kDisallowHwSecureCodec;
+ video_capabilities[1].robustness = kUnsupportedRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("require_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ HwSecureCodec_UnsupportedCapabilityNotAffectingRules) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "unsupported_robustness";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kDisallowHwSecureCodec;
+ video_capabilities[0].robustness = kUnsupportedRobustness;
+ video_capabilities[1].content_type = "require_hw_secure_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kRequireHwSecureCodec;
+ video_capabilities[1].robustness = kRequireHwSecureCodecRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("require_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_EncryptionScheme_Supported) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kRequireHwSecureCodec;
+ video_capabilities[0].encryption_scheme = kSupportedEncryptionScheme;
+
+ WebMediaKeySystemConfiguration config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ(kSupportedEncryptionScheme,
+ config_.video_capabilities[0].encryption_scheme);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ HwSecureCodec_EncryptionScheme_DisallowHwSecureCodec) {
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kRequireHwSecureCodec;
+ video_capabilities[0].encryption_scheme =
+ kDisallowHwSecureCodecEncryptionScheme;
+
+ WebMediaKeySystemConfiguration config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+// --- Identifier and HW Secure Robustness ---
+
+TEST_F(KeySystemConfigSelectorTest,
+ IdentifierAndHwSecureCodec_IncompatibleCodecAndRobustness) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "a";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kDisallowHwSecureCodec;
+ video_capabilities[0].robustness =
+ kRequireIdentifierAndHwSecureCodecRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ IdentifierAndHwSecureCodec_IncompatibleCapabilities) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness =
+ kRequireIdentifierAndHwSecureCodecRobustness;
+ video_capabilities[1].content_type = "disallow_hw_secure_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kDisallowHwSecureCodec;
+ video_capabilities[1].robustness = kUnsupportedRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("require_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ IdentifierAndHwSecureCodec_UnsupportedCapabilityNotAffectingRules) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "unsupported_robustness";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kDisallowHwSecureCodec;
+ video_capabilities[0].robustness = kUnsupportedRobustness;
+ video_capabilities[1].content_type = "require_hw_secure_codec";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kRequireHwSecureCodec;
+ video_capabilities[1].robustness =
+ kRequireIdentifierAndHwSecureCodecRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("require_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ HwSecureCodecAndIdentifier_IdentifierAndHwSecureCodecsDisjoint) {
+ media_permission_->is_granted = false;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::NOT_SUPPORTED;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kRequireHwSecureCodec;
+ video_capabilities[0].robustness = "";
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+// --- Identifier, Persistence and HW Secure Robustness ---
+
+TEST_F(KeySystemConfigSelectorTest,
+ IdentifierPersistenceAndHwSecureCodec_Supported) {
+ media_permission_->is_granted = true;
+ key_systems_->persistent_state = EmeFeatureSupport::REQUESTABLE;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness =
+ kRequireIdentifierPersistenceAndHwSecureCodecRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.distinctive_identifier);
+ EXPECT_EQ(MediaKeysRequirement::kRequired, config_.persistent_state);
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("require_hw_secure_codec",
+ config_.video_capabilities[0].content_type);
+ EXPECT_TRUE(cdm_config_.use_hw_secure_codecs);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ IdentifierPersistenceAndHwSecureCodec_NotSupported) {
+ media_permission_->is_granted = true;
+ key_systems_->persistent_state = EmeFeatureSupport::NOT_SUPPORTED;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "require_hw_secure_codec";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+ video_capabilities[0].robustness =
+ kRequireIdentifierPersistenceAndHwSecureCodecRobustness;
+
+ auto config = EmptyConfiguration();
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+// --- audioCapabilities ---
+// These are handled by the same code as |videoCapabilities|, so only minimal
+// additional testing is done.
+
+TEST_F(KeySystemConfigSelectorTest, AudioCapabilities_SubsetSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities(2);
+ audio_capabilities[0].content_type = "a";
+ audio_capabilities[0].mime_type = kInvalidContainer;
+ audio_capabilities[1].content_type = "b";
+ audio_capabilities[1].mime_type = kSupportedAudioContainer;
+ audio_capabilities[1].codecs = kSupportedAudioCodec;
+
+ auto config = EmptyConfiguration();
+ config.audio_capabilities = audio_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.audio_capabilities.size());
+ EXPECT_EQ("b", config_.audio_capabilities[0].content_type);
+ EXPECT_EQ(kSupportedAudioContainer, config_.audio_capabilities[0].mime_type);
+}
+
+// --- audioCapabilities and videoCapabilities ---
+
+TEST_F(KeySystemConfigSelectorTest, AudioAndVideoCapabilities_AllSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities(1);
+ audio_capabilities[0].content_type = "a";
+ audio_capabilities[0].mime_type = kSupportedAudioContainer;
+ audio_capabilities[0].codecs = kSupportedAudioCodec;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "b";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.audio_capabilities = audio_capabilities;
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.audio_capabilities.size());
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ AudioAndVideoCapabilities_AudioUnsupported) {
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities(1);
+ audio_capabilities[0].content_type = "a";
+ audio_capabilities[0].mime_type = kUnsupportedContainer;
+ audio_capabilities[0].codecs = kSupportedAudioCodec;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "b";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.audio_capabilities = audio_capabilities;
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ AudioAndVideoCapabilities_VideoUnsupported) {
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities(1);
+ audio_capabilities[0].content_type = "a";
+ audio_capabilities[0].mime_type = kSupportedAudioContainer;
+ audio_capabilities[0].codecs = kSupportedAudioCodec;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
+ video_capabilities[0].content_type = "b";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kUnsupportedCodec;
+
+ auto config = EmptyConfiguration();
+ config.audio_capabilities = audio_capabilities;
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsError();
+}
+
+// Only "a2" and "v2" are supported types.
+TEST_F(KeySystemConfigSelectorTest, AudioAndVideoCapabilities_SubsetSupported) {
+ std::vector<WebMediaKeySystemMediaCapability> audio_capabilities(3);
+ audio_capabilities[0].content_type = "a1";
+ audio_capabilities[0].mime_type = kUnsupportedContainer;
+ audio_capabilities[0].codecs = kSupportedAudioCodec;
+ audio_capabilities[1].content_type = "a2";
+ audio_capabilities[1].mime_type = kSupportedAudioContainer;
+ audio_capabilities[1].codecs = kSupportedAudioCodec;
+ audio_capabilities[2].content_type = "a3";
+ audio_capabilities[2].mime_type = kSupportedAudioContainer;
+ audio_capabilities[2].codecs = kUnsupportedCodec;
+
+ std::vector<WebMediaKeySystemMediaCapability> video_capabilities(2);
+ video_capabilities[0].content_type = "v1";
+ video_capabilities[0].mime_type = kSupportedVideoContainer;
+ video_capabilities[0].codecs = kUnsupportedCodec;
+ video_capabilities[1].content_type = "v2";
+ video_capabilities[1].mime_type = kSupportedVideoContainer;
+ video_capabilities[1].codecs = kSupportedVideoCodec;
+
+ auto config = EmptyConfiguration();
+ config.audio_capabilities = audio_capabilities;
+ config.video_capabilities = video_capabilities;
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ(1u, config_.audio_capabilities.size());
+ EXPECT_EQ("a2", config_.audio_capabilities[0].content_type);
+ ASSERT_EQ(1u, config_.video_capabilities.size());
+ EXPECT_EQ("v2", config_.video_capabilities[0].content_type);
+}
+
+// --- Multiple configurations ---
+
+TEST_F(KeySystemConfigSelectorTest, Configurations_AllSupported) {
+ auto config = UsableConfiguration();
+ config.label = "a";
+ configs_.push_back(config);
+ config.label = "b";
+ configs_.push_back(config);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ("a", config_.label);
+}
+
+TEST_F(KeySystemConfigSelectorTest, Configurations_SubsetSupported) {
+ auto config1 = UsableConfiguration();
+ config1.label = "a";
+ std::vector<EmeInitDataType> init_data_types;
+ init_data_types.push_back(EmeInitDataType::UNKNOWN);
+ config1.init_data_types = init_data_types;
+ configs_.push_back(config1);
+
+ auto config2 = UsableConfiguration();
+ config2.label = "b";
+ configs_.push_back(config2);
+
+ SelectConfigReturnsConfig();
+ ASSERT_EQ("b", config_.label);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ Configurations_FirstRequiresPermission_Allowed) {
+ media_permission_->is_granted = true;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ auto config1 = UsableConfiguration();
+ config1.label = "a";
+ config1.distinctive_identifier = MediaKeysRequirement::kRequired;
+ configs_.push_back(config1);
+
+ auto config2 = UsableConfiguration();
+ config2.label = "b";
+ configs_.push_back(config2);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ ASSERT_EQ("a", config_.label);
+}
+
+TEST_F(KeySystemConfigSelectorTest,
+ Configurations_FirstRequiresPermission_Rejected) {
+ media_permission_->is_granted = false;
+ key_systems_->distinctive_identifier = EmeFeatureSupport::REQUESTABLE;
+
+ auto config1 = UsableConfiguration();
+ config1.label = "a";
+ config1.distinctive_identifier = MediaKeysRequirement::kRequired;
+ configs_.push_back(config1);
+
+ auto config2 = UsableConfiguration();
+ config2.label = "b";
+ configs_.push_back(config2);
+
+ SelectConfigRequestsPermissionAndReturnsConfig();
+ ASSERT_EQ("b", config_.label);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/learning_experiment_helper.cc b/chromium/third_party/blink/renderer/platform/media/learning_experiment_helper.cc
new file mode 100644
index 00000000000..6c205a40f30
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/learning_experiment_helper.cc
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/learning_experiment_helper.h"
+
+namespace blink {
+
+using ::media::learning::FeatureDictionary;
+using ::media::learning::FeatureVector;
+using ::media::learning::LearningTaskController;
+using ::media::learning::TargetValue;
+
+LearningExperimentHelper::LearningExperimentHelper(
+ std::unique_ptr<LearningTaskController> controller)
+ : controller_(std::move(controller)) {}
+
+LearningExperimentHelper::~LearningExperimentHelper() {
+ CancelObservationIfNeeded();
+}
+
+void LearningExperimentHelper::BeginObservation(
+ const FeatureDictionary& dictionary) {
+ if (!controller_)
+ return;
+
+ CancelObservationIfNeeded();
+
+ // Get the features that our task needs.
+ FeatureVector features;
+ dictionary.Lookup(controller_->GetLearningTask(), &features);
+
+ observation_id_ = base::UnguessableToken::Create();
+ controller_->BeginObservation(observation_id_, features);
+}
+
+void LearningExperimentHelper::CompleteObservationIfNeeded(
+ const TargetValue& target) {
+ if (!observation_id_)
+ return;
+
+ controller_->CompleteObservation(observation_id_, target);
+ observation_id_ = base::UnguessableToken::Null();
+}
+
+void LearningExperimentHelper::CancelObservationIfNeeded() {
+ if (!observation_id_)
+ return;
+
+ controller_->CancelObservation(observation_id_);
+ observation_id_ = base::UnguessableToken::Null();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/learning_experiment_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/media/learning_experiment_helper_unittest.cc
new file mode 100644
index 00000000000..99efbd524b8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/learning_experiment_helper_unittest.cc
@@ -0,0 +1,141 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/learning_experiment_helper.h"
+
+#include <memory>
+
+#include "media/learning/common/learning_task_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+using ::media::learning::FeatureDictionary;
+using ::media::learning::FeatureValue;
+using ::media::learning::FeatureVector;
+using ::media::learning::LearningTask;
+using ::media::learning::LearningTaskController;
+using ::media::learning::ObservationCompletion;
+using ::media::learning::TargetValue;
+using ::testing::_;
+
+class MockLearningTaskController : public LearningTaskController {
+ public:
+ explicit MockLearningTaskController(const LearningTask& task) : task_(task) {}
+ MockLearningTaskController(const MockLearningTaskController&) = delete;
+ MockLearningTaskController& operator=(const MockLearningTaskController&) =
+ delete;
+ ~MockLearningTaskController() override = default;
+
+ MOCK_METHOD4(BeginObservation,
+ void(base::UnguessableToken id,
+ const FeatureVector& features,
+ const absl::optional<TargetValue>& default_value,
+ const absl::optional<ukm::SourceId>& source_id));
+ MOCK_METHOD2(CompleteObservation,
+ void(base::UnguessableToken id,
+ const ObservationCompletion& completion));
+ MOCK_METHOD1(CancelObservation, void(base::UnguessableToken id));
+ MOCK_METHOD2(UpdateDefaultTarget,
+ void(base::UnguessableToken id,
+ const absl::optional<TargetValue>& default_target));
+ MOCK_METHOD2(PredictDistribution,
+ void(const FeatureVector& features, PredictionCB callback));
+
+ const LearningTask& GetLearningTask() override { return task_; }
+
+ private:
+ LearningTask task_;
+};
+
+class LearningExperimentHelperTest : public testing::Test {
+ public:
+ void SetUp() override {
+ const std::string feature_name_1("feature 1");
+ const FeatureValue feature_value_1("feature value 1");
+
+ const std::string feature_name_2("feature 2");
+ const FeatureValue feature_value_2("feature value 2");
+
+ const std::string feature_name_3("feature 3");
+ const FeatureValue feature_value_3("feature value 3");
+ dict_.Add(feature_name_1, feature_value_1);
+ dict_.Add(feature_name_2, feature_value_2);
+ dict_.Add(feature_name_3, feature_value_3);
+
+ task_.feature_descriptions.push_back({"some other feature"});
+ task_.feature_descriptions.push_back({feature_name_3});
+ task_.feature_descriptions.push_back({feature_name_1});
+
+ std::unique_ptr<MockLearningTaskController> controller =
+ std::make_unique<MockLearningTaskController>(task_);
+ controller_raw_ = controller.get();
+
+ helper_ = std::make_unique<LearningExperimentHelper>(std::move(controller));
+ }
+
+ LearningTask task_;
+ MockLearningTaskController* controller_raw_ = nullptr;
+ std::unique_ptr<LearningExperimentHelper> helper_;
+
+ FeatureDictionary dict_;
+};
+
+TEST_F(LearningExperimentHelperTest, BeginComplete) {
+ EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _));
+ helper_->BeginObservation(dict_);
+ TargetValue target(123);
+ EXPECT_CALL(*controller_raw_,
+ CompleteObservation(_, ObservationCompletion(target)))
+ .Times(1);
+ helper_->CompleteObservationIfNeeded(target);
+
+ // Make sure that a second Complete doesn't send anything.
+ testing::Mock::VerifyAndClear(controller_raw_);
+ EXPECT_CALL(*controller_raw_,
+ CompleteObservation(_, ObservationCompletion(target)))
+ .Times(0);
+ helper_->CompleteObservationIfNeeded(target);
+}
+
+TEST_F(LearningExperimentHelperTest, BeginCancel) {
+ EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _));
+ helper_->BeginObservation(dict_);
+ EXPECT_CALL(*controller_raw_, CancelObservation(_));
+ helper_->CancelObservationIfNeeded();
+}
+
+TEST_F(LearningExperimentHelperTest, CompleteWithoutBeginDoesNothing) {
+ EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _)).Times(0);
+ EXPECT_CALL(*controller_raw_, CompleteObservation(_, _)).Times(0);
+ EXPECT_CALL(*controller_raw_, CancelObservation(_)).Times(0);
+ helper_->CompleteObservationIfNeeded(TargetValue(123));
+}
+
+TEST_F(LearningExperimentHelperTest, CancelWithoutBeginDoesNothing) {
+ EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _)).Times(0);
+ EXPECT_CALL(*controller_raw_, CompleteObservation(_, _)).Times(0);
+ EXPECT_CALL(*controller_raw_, CancelObservation(_)).Times(0);
+ helper_->CancelObservationIfNeeded();
+}
+
+TEST_F(LearningExperimentHelperTest, DoesNothingWithoutController) {
+ // Make sure that nothing crashes if there's no controller.
+ LearningExperimentHelper helper(nullptr);
+
+ // Begin / complete.
+ helper_->BeginObservation(dict_);
+ TargetValue target(123);
+ helper_->CompleteObservationIfNeeded(target);
+
+ // Begin / cancel.
+ helper_->BeginObservation(dict_);
+ helper_->CancelObservationIfNeeded();
+
+ // Cancel without begin.
+ helper_->CancelObservationIfNeeded();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/lru_unittest.cc b/chromium/third_party/blink/renderer/platform/media/lru_unittest.cc
new file mode 100644
index 00000000000..12c917b5aa7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/lru_unittest.cc
@@ -0,0 +1,235 @@
+// 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/platform/media/lru.h"
+
+#include <stddef.h>
+
+#include <list>
+
+#include "base/logging.h"
+#include "media/base/test_random.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+// Range of integer used in tests below.
+// We keep the integers small to get lots of re-use of integers.
+const int kTestIntRange = 16;
+
+class SimpleLRU {
+ public:
+ void Insert(int x) {
+ DCHECK(!Contains(x));
+ data_.push_back(x);
+ }
+
+ void Remove(int x) {
+ for (auto i = data_.begin(); i != data_.end(); ++i) {
+ if (*i == x) {
+ data_.erase(i);
+ DCHECK(!Contains(x));
+ return;
+ }
+ }
+ LOG(FATAL) << "Remove non-existing element " << x;
+ }
+
+ void Use(int x) {
+ if (Contains(x))
+ Remove(x);
+ Insert(x);
+ }
+
+ bool Empty() const { return data_.empty(); }
+
+ int Pop() {
+ DCHECK(!Empty());
+ int ret = data_.front();
+ data_.pop_front();
+ return ret;
+ }
+
+ int Peek() {
+ DCHECK(!Empty());
+ return data_.front();
+ }
+
+ bool Contains(int x) const {
+ for (auto i = data_.begin(); i != data_.end(); ++i) {
+ if (*i == x) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ size_t Size() const { return data_.size(); }
+
+ private:
+ friend class LRUTest;
+ std::list<int> data_;
+};
+
+class LRUTest : public testing::Test {
+ public:
+ LRUTest() : rnd_(42) {}
+
+ void Insert(int x) {
+ truth_.Insert(x);
+ testee_.Insert(x);
+ Compare();
+ }
+
+ void Remove(int x) {
+ truth_.Remove(x);
+ testee_.Remove(x);
+ Compare();
+ }
+
+ void Use(int x) {
+ truth_.Use(x);
+ testee_.Use(x);
+ Compare();
+ }
+
+ int Pop() {
+ int truth_value = truth_.Pop();
+ int testee_value = testee_.Pop();
+ EXPECT_EQ(truth_value, testee_value);
+ Compare();
+ return truth_value;
+ }
+
+ void Compare() {
+ EXPECT_EQ(truth_.Size(), testee_.Size());
+ auto testee_iterator = testee_.lru_.rbegin();
+ for (const auto truth : truth_.data_) {
+ EXPECT_TRUE(testee_iterator != testee_.lru_.rend());
+ EXPECT_EQ(truth, *testee_iterator);
+ ++testee_iterator;
+ }
+ EXPECT_TRUE(testee_iterator == testee_.lru_.rend());
+ }
+
+ bool Empty() const {
+ EXPECT_EQ(truth_.Empty(), testee_.Empty());
+ return truth_.Empty();
+ }
+
+ bool Contains(int i) const {
+ EXPECT_EQ(truth_.Contains(i), testee_.Contains(i));
+ return testee_.Contains(i);
+ }
+
+ void Clear() {
+ while (!Empty())
+ Pop();
+ }
+
+ int Peek() {
+ EXPECT_EQ(truth_.Peek(), testee_.Peek());
+ return testee_.Peek();
+ }
+
+ protected:
+ media::TestRandom rnd_;
+ SimpleLRU truth_;
+ LRU<int> testee_;
+};
+
+TEST_F(LRUTest, SimpleTest) {
+ Insert(1); // 1
+ Insert(2); // 1 2
+ Insert(3); // 1 2 3
+ EXPECT_EQ(1, Peek());
+ EXPECT_EQ(1, Pop()); // 2 3
+ EXPECT_EQ(2, Peek());
+ Use(2); // 3 2
+ EXPECT_EQ(3, Peek());
+ EXPECT_EQ(3, Pop()); // 2
+ EXPECT_EQ(2, Pop());
+ EXPECT_TRUE(Empty());
+}
+
+TEST_F(LRUTest, UseTest) {
+ EXPECT_TRUE(Empty());
+ // Using a value that's not on the LRU adds it.
+ Use(3); // 3
+ EXPECT_EQ(3, Peek());
+ Use(5); // 3 5
+ EXPECT_EQ(3, Peek());
+ EXPECT_TRUE(Contains(5));
+ Use(7); // 3 5 7
+ EXPECT_EQ(3, Peek());
+ EXPECT_TRUE(Contains(7));
+ // Using a value that's alraedy on the LRU moves it to the top.
+ Use(3); // 5 7 3
+ EXPECT_EQ(5, Peek());
+ EXPECT_TRUE(Contains(5));
+ EXPECT_EQ(5, Pop()); // 7 3
+ EXPECT_FALSE(Contains(5));
+ EXPECT_EQ(7, Peek());
+ EXPECT_TRUE(Contains(7));
+ EXPECT_TRUE(Contains(3));
+ Use(9); // 7 3 9
+ EXPECT_EQ(7, Peek());
+ // Using the same value again has no effect.
+ Use(9); // 7 3 9
+ EXPECT_EQ(7, Peek());
+ Use(3); // 7 9 3
+ EXPECT_EQ(7, Pop());
+ EXPECT_EQ(9, Pop());
+ EXPECT_EQ(3, Pop());
+ EXPECT_TRUE(Empty());
+}
+
+TEST_F(LRUTest, RemoveTest) {
+ Insert(5); // 5
+ Insert(4); // 5 4
+ Insert(3); // 5 4 3
+ Insert(2); // 5 4 3 2
+ Insert(1); // 5 4 3 2 1
+ EXPECT_EQ(5, Peek());
+ Remove(5); // 4 3 2 1
+ EXPECT_EQ(4, Peek());
+ Remove(1); // 4 3 2
+ EXPECT_EQ(4, Peek());
+ Remove(3); // 4 2
+ EXPECT_EQ(4, Pop());
+ EXPECT_EQ(2, Pop());
+ EXPECT_TRUE(Empty());
+}
+
+TEST_F(LRUTest, RandomTest) {
+ for (int j = 0; j < 100; j++) {
+ Clear();
+ for (int i = 0; i < 1000; i++) {
+ int value = rnd_.Rand() % kTestIntRange;
+ switch (rnd_.Rand() % 3) {
+ case 0:
+ if (!Empty())
+ Pop();
+ break;
+
+ case 1:
+ Use(value);
+ break;
+
+ case 2:
+ if (Contains(value)) {
+ Remove(value);
+ } else {
+ Insert(value);
+ }
+ break;
+ }
+ if (HasFailure()) {
+ return;
+ }
+ }
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/multi_buffer.cc b/chromium/third_party/blink/renderer/platform/media/multi_buffer.cc
new file mode 100644
index 00000000000..c1ece9eb93c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/multi_buffer.cc
@@ -0,0 +1,572 @@
+// 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/platform/media/multi_buffer.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+
+namespace blink {
+
+// Prune 80 blocks per 30 seconds.
+// This means a full cache will go away in ~5 minutes.
+enum {
+ kBlockPruneInterval = 30,
+ kBlocksPrunedPerInterval = 80,
+};
+
+// Returns the block ID closest to (but less or equal than) |pos| from |index|.
+template <class T>
+static MultiBuffer::BlockId ClosestPreviousEntry(
+ const std::map<MultiBuffer::BlockId, T>& index,
+ MultiBuffer::BlockId pos) {
+ auto i = index.upper_bound(pos);
+ DCHECK(i == index.end() || i->first > pos);
+ if (i == index.begin()) {
+ return std::numeric_limits<MultiBufferBlockId>::min();
+ }
+ --i;
+ DCHECK_LE(i->first, pos);
+ return i->first;
+}
+
+// Returns the block ID closest to (but greter than or equal to) |pos|
+// from |index|.
+template <class T>
+static MultiBuffer::BlockId ClosestNextEntry(
+ const std::map<MultiBuffer::BlockId, T>& index,
+ MultiBuffer::BlockId pos) {
+ auto i = index.lower_bound(pos);
+ if (i == index.end()) {
+ return std::numeric_limits<MultiBufferBlockId>::max();
+ }
+ DCHECK_GE(i->first, pos);
+ return i->first;
+}
+
+//
+// MultiBuffer::GlobalLRU
+//
+MultiBuffer::GlobalLRU::GlobalLRU(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : max_size_(0),
+ data_size_(0),
+ background_pruning_pending_(false),
+ task_runner_(std::move(task_runner)) {}
+
+MultiBuffer::GlobalLRU::~GlobalLRU() {
+ // By the time we're freed, all blocks should have been removed,
+ // and our sums should be zero.
+ DCHECK(lru_.Empty());
+ DCHECK_EQ(max_size_, 0);
+ DCHECK_EQ(data_size_, 0);
+}
+
+void MultiBuffer::GlobalLRU::Use(MultiBuffer* multibuffer,
+ MultiBufferBlockId block_id) {
+ GlobalBlockId id(multibuffer, block_id);
+ lru_.Use(id);
+ SchedulePrune();
+}
+
+void MultiBuffer::GlobalLRU::Insert(MultiBuffer* multibuffer,
+ MultiBufferBlockId block_id) {
+ GlobalBlockId id(multibuffer, block_id);
+ lru_.Insert(id);
+ SchedulePrune();
+}
+
+void MultiBuffer::GlobalLRU::Remove(MultiBuffer* multibuffer,
+ MultiBufferBlockId block_id) {
+ GlobalBlockId id(multibuffer, block_id);
+ lru_.Remove(id);
+}
+
+bool MultiBuffer::GlobalLRU::Contains(MultiBuffer* multibuffer,
+ MultiBufferBlockId block_id) {
+ GlobalBlockId id(multibuffer, block_id);
+ return lru_.Contains(id);
+}
+
+void MultiBuffer::GlobalLRU::IncrementDataSize(int64_t blocks) {
+ data_size_ += blocks;
+ DCHECK_GE(data_size_, 0);
+ SchedulePrune();
+}
+
+void MultiBuffer::GlobalLRU::IncrementMaxSize(int64_t blocks) {
+ max_size_ += blocks;
+ DCHECK_GE(max_size_, 0);
+ SchedulePrune();
+}
+
+bool MultiBuffer::GlobalLRU::Pruneable() const {
+ return data_size_ > max_size_ && !lru_.Empty();
+}
+
+void MultiBuffer::GlobalLRU::SchedulePrune() {
+ if (Pruneable() && !background_pruning_pending_) {
+ task_runner_->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&MultiBuffer::GlobalLRU::PruneTask, this),
+ base::TimeDelta::FromSeconds(kBlockPruneInterval));
+ background_pruning_pending_ = true;
+ }
+}
+
+void MultiBuffer::GlobalLRU::PruneTask() {
+ background_pruning_pending_ = false;
+ Prune(kBlocksPrunedPerInterval);
+ SchedulePrune();
+}
+
+void MultiBuffer::GlobalLRU::TryFree(int64_t max_to_free) {
+ // We group the blocks by multibuffer so that we can free as many blocks as
+ // possible in one call. This reduces the number of callbacks to clients
+ // when their available ranges change.
+ std::map<MultiBuffer*, std::vector<MultiBufferBlockId>> to_free;
+ int64_t freed = 0;
+ while (!lru_.Empty() && freed < max_to_free) {
+ GlobalBlockId block_id = lru_.Pop();
+ to_free[block_id.first].push_back(block_id.second);
+ freed++;
+ }
+ for (const auto& to_free_pair : to_free) {
+ to_free_pair.first->ReleaseBlocks(to_free_pair.second);
+ }
+}
+
+void MultiBuffer::GlobalLRU::TryFreeAll() {
+ // Since TryFree also allocates memory, avoid freeing everything
+ // in one large chunk to avoid running out of memory before we
+ // start freeing memory. Freeing 100 at a time should be a reasonable
+ // compromise between efficiency and not building large data structures.
+ while (true) {
+ int64_t data_size_before = data_size_;
+ TryFree(100);
+ if (data_size_ >= data_size_before)
+ break;
+ }
+}
+
+void MultiBuffer::GlobalLRU::Prune(int64_t max_to_free) {
+ TryFree(std::min(max_to_free, data_size_ - max_size_));
+}
+
+int64_t MultiBuffer::GlobalLRU::Size() const {
+ return lru_.Size();
+}
+
+//
+// MultiBuffer
+//
+MultiBuffer::MultiBuffer(int32_t block_size_shift,
+ const scoped_refptr<GlobalLRU>& global_lru)
+ : max_size_(0), block_size_shift_(block_size_shift), lru_(global_lru) {}
+
+MultiBuffer::~MultiBuffer() {
+ CHECK(pinned_.empty());
+ DCHECK_EQ(max_size_, 0);
+ // Remove all blocks from the LRU.
+ for (const auto& i : data_) {
+ lru_->Remove(this, i.first);
+ }
+ lru_->IncrementDataSize(-static_cast<int64_t>(data_.size()));
+ lru_->IncrementMaxSize(-max_size_);
+}
+
+void MultiBuffer::AddReader(const BlockId& pos, Reader* reader) {
+ std::set<Reader*>* set_of_readers = &readers_[pos];
+ bool already_waited_for = !set_of_readers->empty();
+ set_of_readers->insert(reader);
+
+ if (already_waited_for || Contains(pos)) {
+ return;
+ }
+
+ // We may need to create a new data provider to service this request.
+ // Look for an existing data provider first.
+ DataProvider* provider = nullptr;
+ BlockId closest_writer = ClosestPreviousEntry(writer_index_, pos);
+
+ if (closest_writer > pos - kMaxWaitForWriterOffset) {
+ auto i = present_.find(pos);
+ BlockId closest_block;
+ if (i.value()) {
+ // Shouldn't happen, we already tested that Contains(pos) is true.
+ NOTREACHED();
+ closest_block = pos;
+ } else if (i == present_.begin()) {
+ closest_block = -1;
+ } else {
+ closest_block = i.interval_begin() - 1;
+ }
+
+ // Make sure that there are no present blocks between the writer and
+ // the requested position, as that will cause the writer to quit.
+ if (closest_writer > closest_block) {
+ provider = writer_index_[closest_writer].get();
+ DCHECK(provider);
+ }
+ }
+ if (!provider) {
+ DCHECK(writer_index_.find(pos) == writer_index_.end());
+ writer_index_[pos] = CreateWriter(pos, is_client_audio_element_);
+ provider = writer_index_[pos].get();
+ }
+ provider->SetDeferred(false);
+}
+
+void MultiBuffer::RemoveReader(const BlockId& pos, Reader* reader) {
+ auto i = readers_.find(pos);
+ if (i == readers_.end())
+ return;
+ i->second.erase(reader);
+ if (i->second.empty()) {
+ readers_.erase(i);
+ }
+}
+
+void MultiBuffer::CleanupWriters(const BlockId& pos) {
+ BlockId p2 = pos + kMaxWaitForReaderOffset;
+ BlockId closest_writer = ClosestPreviousEntry(writer_index_, p2);
+ while (closest_writer > pos - kMaxWaitForWriterOffset) {
+ DCHECK(writer_index_[closest_writer]);
+ OnDataProviderEvent(writer_index_[closest_writer].get());
+ closest_writer = ClosestPreviousEntry(writer_index_, closest_writer - 1);
+ }
+}
+
+bool MultiBuffer::Contains(const BlockId& pos) const {
+ DCHECK(present_[pos] == 0 || present_[pos] == 1)
+ << " pos = " << pos << " present_[pos] " << present_[pos];
+ DCHECK_EQ(present_[pos], data_.find(pos) != data_.end() ? 1 : 0);
+ return !!present_[pos];
+}
+
+MultiBufferBlockId MultiBuffer::FindNextUnavailable(const BlockId& pos) const {
+ auto i = present_.find(pos);
+ if (i.value())
+ return i.interval_end();
+ return pos;
+}
+
+void MultiBuffer::NotifyAvailableRange(
+ const Interval<MultiBufferBlockId>& observer_range,
+ const Interval<MultiBufferBlockId>& new_range) {
+ std::set<Reader*> tmp;
+ for (auto i = readers_.lower_bound(observer_range.begin);
+ i != readers_.end() && i->first < observer_range.end; ++i) {
+ tmp.insert(i->second.begin(), i->second.end());
+ }
+ for (Reader* reader : tmp) {
+ reader->NotifyAvailableRange(new_range);
+ }
+}
+
+void MultiBuffer::ReleaseBlocks(const std::vector<MultiBufferBlockId>& blocks) {
+ IntervalMap<BlockId, int32_t> freed;
+ {
+ base::AutoLock auto_lock(data_lock_);
+ for (MultiBufferBlockId to_free : blocks) {
+ DCHECK(data_[to_free]);
+ DCHECK_EQ(pinned_[to_free], 0);
+ DCHECK_EQ(present_[to_free], 1);
+ data_.erase(to_free);
+ freed.IncrementInterval(to_free, to_free + 1, 1);
+ present_.IncrementInterval(to_free, to_free + 1, -1);
+ }
+ lru_->IncrementDataSize(-static_cast<int64_t>(blocks.size()));
+ }
+
+ for (auto freed_range : freed) {
+ if (freed_range.second) {
+ // Technically, there shouldn't be any observers in this range
+ // as all observers really should be pinning the range where it's
+ // actually observing.
+ NotifyAvailableRange(
+ freed_range.first,
+ // Empty range.
+ Interval<BlockId>(freed_range.first.begin, freed_range.first.begin));
+
+ auto i = present_.find(freed_range.first.begin);
+ DCHECK_EQ(i.value(), 0);
+ DCHECK_LE(i.interval_begin(), freed_range.first.begin);
+ DCHECK_LE(freed_range.first.end, i.interval_end());
+
+ if (i.interval_begin() == freed_range.first.begin) {
+ // Notify the previous range that it contains fewer blocks.
+ auto j = i;
+ --j;
+ DCHECK_EQ(j.value(), 1);
+ NotifyAvailableRange(j.interval(), j.interval());
+ }
+ if (i.interval_end() == freed_range.first.end) {
+ // Notify the following range that it contains fewer blocks.
+ auto j = i;
+ ++j;
+ DCHECK_EQ(j.value(), 1);
+ NotifyAvailableRange(j.interval(), j.interval());
+ }
+ }
+ }
+ if (data_.empty())
+ OnEmpty();
+}
+
+void MultiBuffer::OnEmpty() {}
+
+void MultiBuffer::AddProvider(std::unique_ptr<DataProvider> provider) {
+ // If there is already a provider in the same location, we delete it.
+ DCHECK(!provider->Available());
+ BlockId pos = provider->Tell();
+ writer_index_[pos] = std::move(provider);
+}
+
+std::unique_ptr<MultiBuffer::DataProvider> MultiBuffer::RemoveProvider(
+ DataProvider* provider) {
+ BlockId pos = provider->Tell();
+ auto iter = writer_index_.find(pos);
+ DCHECK(iter != writer_index_.end());
+ DCHECK_EQ(iter->second.get(), provider);
+ std::unique_ptr<DataProvider> ret = std::move(iter->second);
+ writer_index_.erase(iter);
+ return ret;
+}
+
+MultiBuffer::ProviderState MultiBuffer::SuggestProviderState(
+ const BlockId& pos) const {
+ MultiBufferBlockId next_reader_pos = ClosestNextEntry(readers_, pos);
+ if (next_reader_pos != std::numeric_limits<MultiBufferBlockId>::max() &&
+ (next_reader_pos - pos <= kMaxWaitForWriterOffset || !RangeSupported())) {
+ // Check if there is another writer between us and the next reader.
+ MultiBufferBlockId next_writer_pos =
+ ClosestNextEntry(writer_index_, pos + 1);
+ if (next_writer_pos > next_reader_pos) {
+ return ProviderStateLoad;
+ }
+ }
+
+ MultiBufferBlockId previous_reader_pos =
+ ClosestPreviousEntry(readers_, pos - 1);
+ if (previous_reader_pos != std::numeric_limits<MultiBufferBlockId>::min() &&
+ (pos - previous_reader_pos <= kMaxWaitForReaderOffset ||
+ !RangeSupported())) {
+ MultiBufferBlockId previous_writer_pos =
+ ClosestPreviousEntry(writer_index_, pos - 1);
+ if (previous_writer_pos < previous_reader_pos) {
+ return ProviderStateDefer;
+ }
+ }
+
+ return ProviderStateDead;
+}
+
+bool MultiBuffer::ProviderCollision(const BlockId& id) const {
+ // If there is a writer at the same location, it is always a collision.
+ if (writer_index_.find(id) != writer_index_.end())
+ return true;
+
+ // Data already exists at providers current position,
+ // if the URL supports ranges, we can kill the data provider.
+ if (RangeSupported() && Contains(id))
+ return true;
+
+ return false;
+}
+
+void MultiBuffer::Prune(size_t max_to_free) {
+ lru_->Prune(max_to_free);
+}
+
+void MultiBuffer::OnDataProviderEvent(DataProvider* provider_tmp) {
+ std::unique_ptr<DataProvider> provider(RemoveProvider(provider_tmp));
+ BlockId start_pos = provider->Tell();
+ BlockId pos = start_pos;
+ bool eof = false;
+ int64_t blocks_before = data_.size();
+
+ {
+ base::AutoLock auto_lock(data_lock_);
+ while (!ProviderCollision(pos) && !eof) {
+ if (!provider->Available()) {
+ AddProvider(std::move(provider));
+ break;
+ }
+ DCHECK_GE(pos, 0);
+ scoped_refptr<media::DataBuffer> data = provider->Read();
+ data_[pos] = data;
+ eof = data->end_of_stream();
+ if (!pinned_[pos])
+ lru_->Use(this, pos);
+ ++pos;
+ }
+ }
+ int64_t blocks_after = data_.size();
+ int64_t blocks_added = blocks_after - blocks_before;
+
+ if (pos > start_pos) {
+ present_.SetInterval(start_pos, pos, 1);
+ Interval<BlockId> expanded_range = present_.find(start_pos).interval();
+ NotifyAvailableRange(expanded_range, expanded_range);
+ lru_->IncrementDataSize(blocks_added);
+ Prune(blocks_added * kMaxFreesPerAdd + 1);
+ } else {
+ // Make sure to give progress reports even when there
+ // aren't any new blocks yet.
+ NotifyAvailableRange(Interval<BlockId>(start_pos, start_pos + 1),
+ Interval<BlockId>(start_pos, start_pos));
+ }
+
+ // Check that it's still there before we try to delete it.
+ // In case of EOF or a collision, we might not have called AddProvider above.
+ // Even if we did call AddProvider, calling NotifyAvailableRange can cause
+ // readers to seek or self-destruct and clean up any associated writers.
+ auto i = writer_index_.find(pos);
+ if (i != writer_index_.end() && i->second.get() == provider_tmp) {
+ switch (SuggestProviderState(pos)) {
+ case ProviderStateLoad:
+ // Not sure we actually need to do this
+ provider_tmp->SetDeferred(false);
+ break;
+ case ProviderStateDefer:
+ provider_tmp->SetDeferred(true);
+ break;
+ case ProviderStateDead:
+ RemoveProvider(provider_tmp);
+ break;
+ }
+ }
+}
+
+void MultiBuffer::MergeFrom(MultiBuffer* other) {
+ {
+ base::AutoLock auto_lock(data_lock_);
+ // Import data and update LRU.
+ size_t data_size = data_.size();
+ for (const auto& data : other->data_) {
+ if (data_.insert(std::make_pair(data.first, data.second)).second) {
+ if (!pinned_[data.first]) {
+ lru_->Insert(this, data.first);
+ }
+ }
+ }
+ lru_->IncrementDataSize(static_cast<int64_t>(data_.size() - data_size));
+ }
+ // Update present_
+ for (auto r : other->present_) {
+ if (r.second) {
+ present_.SetInterval(r.first.begin, r.first.end, 1);
+ }
+ }
+ // Notify existing readers.
+ auto last = present_.begin();
+ for (auto r : other->present_) {
+ if (r.second) {
+ auto i = present_.find(r.first.begin);
+ if (i != last) {
+ NotifyAvailableRange(i.interval(), i.interval());
+ last = i;
+ }
+ }
+ }
+}
+
+void MultiBuffer::GetBlocksThreadsafe(
+ const BlockId& from,
+ const BlockId& to,
+ std::vector<scoped_refptr<media::DataBuffer>>* output) {
+ base::AutoLock auto_lock(data_lock_);
+ auto i = data_.find(from);
+ BlockId j = from;
+ while (j <= to && i != data_.end() && i->first == j) {
+ output->push_back(i->second);
+ ++j;
+ ++i;
+ }
+}
+
+void MultiBuffer::PinRange(const BlockId& from,
+ const BlockId& to,
+ int32_t how_much) {
+ DCHECK_NE(how_much, 0);
+ DVLOG(3) << "PINRANGE [" << from << " - " << to << ") += " << how_much;
+ pinned_.IncrementInterval(from, to, how_much);
+ Interval<BlockId> modified_range(from, to);
+
+ // Iterate over all the modified ranges and check if any of them have
+ // transitioned in or out of the unlocked state. If so, we iterate over
+ // all buffers in that range and add/remove them from the LRU as approperiate.
+ // We iterate *backwards* through the ranges, with the idea that data in a
+ // continous range should be freed from the end first.
+
+ if (data_.empty())
+ return;
+
+ auto range = pinned_.find(to - 1);
+ while (1) {
+ DCHECK_GE(range.value(), 0);
+ if (range.value() == 0 || range.value() == how_much) {
+ bool pin = range.value() == how_much;
+ Interval<BlockId> transition_range =
+ modified_range.Intersect(range.interval());
+ if (transition_range.Empty())
+ break;
+
+ // For each range that has transitioned to/from a pinned state,
+ // we iterate over the corresponding ranges in |present_| to find
+ // the blocks that are actually in the multibuffer.
+ for (auto present_block_range = present_.find(transition_range.end - 1);
+ present_block_range != present_.begin(); --present_block_range) {
+ if (!present_block_range.value())
+ continue;
+ Interval<BlockId> present_transitioned_range =
+ transition_range.Intersect(present_block_range.interval());
+ if (present_transitioned_range.Empty())
+ break;
+ for (BlockId block = present_transitioned_range.end - 1;
+ block >= present_transitioned_range.begin; --block) {
+ DCHECK_GE(block, 0);
+ DCHECK(data_.find(block) != data_.end());
+ if (pin) {
+ DCHECK(pinned_[block]);
+ lru_->Remove(this, block);
+ } else {
+ DCHECK(!pinned_[block]);
+ lru_->Insert(this, block);
+ }
+ }
+ }
+ }
+ if (range == pinned_.begin())
+ break;
+ --range;
+ }
+}
+
+void MultiBuffer::PinRanges(const IntervalMap<BlockId, int32_t>& ranges) {
+ for (auto r : ranges) {
+ if (r.second != 0) {
+ PinRange(r.first.begin, r.first.end, r.second);
+ }
+ }
+}
+
+void MultiBuffer::IncrementMaxSize(int32_t size) {
+ max_size_ += size;
+ lru_->IncrementMaxSize(size);
+ DCHECK_GE(max_size_, 0);
+ // Pruning only happens when blocks are added.
+}
+
+int64_t MultiBuffer::UncommittedBytesAt(const MultiBuffer::BlockId& block) {
+ auto i = writer_index_.find(block);
+ if (writer_index_.end() == i)
+ return 0;
+ return i->second->AvailableBytes();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc b/chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
new file mode 100644
index 00000000000..fa51f3f0c43
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
@@ -0,0 +1,780 @@
+// 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/public/platform/media/multi_buffer_data_source.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
+#include "base/location.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/single_thread_task_runner.h"
+#include "media/base/media_log.h"
+#include "net/base/net_errors.h"
+#include "third_party/blink/public/platform/media/buffered_data_source_host_impl.h"
+#include "third_party/blink/renderer/platform/media/multi_buffer_reader.h"
+#include "url/gurl.h"
+
+namespace blink {
+namespace {
+
+// Minimum preload buffer.
+const int64_t kMinBufferPreload = 2 << 20; // 2 Mb
+// Maxmimum preload buffer.
+const int64_t kMaxBufferPreload = 50 << 20; // 50 Mb
+
+// If preload_ == METADATA, preloading size will be
+// shifted down this many bits. This shift turns
+// one Mb into one 32k block.
+// This seems to be the smallest amount of preload we can do without
+// ending up repeatedly closing and re-opening the connection
+// due to read calls after OnBufferingHaveEnough have been called.
+const int64_t kMetadataShift = 6;
+
+// Preload this much extra, then stop preloading until we fall below the
+// preload_seconds_.value().
+const int64_t kPreloadHighExtra = 1 << 20; // 1 Mb
+
+// Default pin region size.
+// Note that we go over this if preload is calculated high enough.
+const int64_t kDefaultPinSize = 25 << 20; // 25 Mb
+
+// If bitrate is not known, use this.
+const int64_t kDefaultBitrate = 200 * 8 << 10; // 200 Kbps.
+
+// Maximum bitrate for buffer calculations.
+const int64_t kMaxBitrate = 20 * 8 << 20; // 20 Mbps.
+
+// Maximum playback rate for buffer calculations.
+const double kMaxPlaybackRate = 25.0;
+
+// Extra buffer accumulation speed, in terms of download buffer.
+const int kSlowPreloadPercentage = 10;
+
+// Update buffer sizes every 32 progress updates.
+const int kUpdateBufferSizeFrequency = 32;
+
+// How long to we delay a seek after a read?
+constexpr base::TimeDelta kSeekDelay = base::TimeDelta::FromMilliseconds(20);
+
+} // namespace
+
+class MultiBufferDataSource::ReadOperation {
+ public:
+ ReadOperation() = delete;
+ ReadOperation(int64_t position,
+ int size,
+ uint8_t* data,
+ media::DataSource::ReadCB callback);
+ ReadOperation(const ReadOperation&) = delete;
+ ReadOperation& operator=(const ReadOperation&) = delete;
+ ~ReadOperation();
+
+ // Runs |callback_| with the given |result|, deleting the operation
+ // afterwards.
+ static void Run(std::unique_ptr<ReadOperation> read_op, int result);
+
+ int64_t position() { return position_; }
+ int size() { return size_; }
+ uint8_t* data() { return data_; }
+
+ private:
+ const int64_t position_;
+ const int size_;
+ uint8_t* data_;
+ media::DataSource::ReadCB callback_;
+};
+
+MultiBufferDataSource::ReadOperation::ReadOperation(
+ int64_t position,
+ int size,
+ uint8_t* data,
+ media::DataSource::ReadCB callback)
+ : position_(position),
+ size_(size),
+ data_(data),
+ callback_(std::move(callback)) {
+ DCHECK(!callback_.is_null());
+}
+
+MultiBufferDataSource::ReadOperation::~ReadOperation() {
+ DCHECK(callback_.is_null());
+}
+
+// static
+void MultiBufferDataSource::ReadOperation::Run(
+ std::unique_ptr<ReadOperation> read_op,
+ int result) {
+ std::move(read_op->callback_).Run(result);
+}
+
+MultiBufferDataSource::MultiBufferDataSource(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ scoped_refptr<UrlData> url_data_arg,
+ media::MediaLog* media_log,
+ BufferedDataSourceHost* host,
+ DownloadingCB downloading_cb)
+ : total_bytes_(kPositionNotSpecified),
+ streaming_(false),
+ loading_(false),
+ failed_(false),
+ render_task_runner_(task_runner),
+ url_data_(std::move(url_data_arg)),
+ stop_signal_received_(false),
+ media_has_played_(false),
+ single_origin_(true),
+ cancel_on_defer_(false),
+ preload_(AUTO),
+ bitrate_(0),
+ playback_rate_(0.0),
+ media_log_(media_log),
+ host_(host),
+ downloading_cb_(std::move(downloading_cb)) {
+ weak_ptr_ = weak_factory_.GetWeakPtr();
+ DCHECK(host_);
+ DCHECK(downloading_cb_);
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ DCHECK(url_data_.get());
+ url_data_->Use();
+ url_data_->OnRedirect(
+ base::BindOnce(&MultiBufferDataSource::OnRedirected, weak_ptr_));
+}
+
+MultiBufferDataSource::~MultiBufferDataSource() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+}
+
+bool MultiBufferDataSource::media_has_played() const {
+ return media_has_played_;
+}
+
+bool MultiBufferDataSource::AssumeFullyBuffered() const {
+ DCHECK(url_data_);
+ return !url_data_->url().SchemeIsHTTPOrHTTPS();
+}
+
+void MultiBufferDataSource::SetReader(MultiBufferReader* reader) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ base::AutoLock auto_lock(lock_);
+ reader_.reset(reader);
+}
+
+void MultiBufferDataSource::CreateResourceLoader(int64_t first_byte_position,
+ int64_t last_byte_position) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+
+ SetReader(new MultiBufferReader(
+ url_data_->multibuffer(), first_byte_position, last_byte_position,
+ base::BindRepeating(&MultiBufferDataSource::ProgressCallback, weak_ptr_),
+ render_task_runner_));
+ reader_->SetIsClientAudioElement(is_client_audio_element_);
+ UpdateBufferSizes();
+}
+
+void MultiBufferDataSource::CreateResourceLoader_Locked(
+ int64_t first_byte_position,
+ int64_t last_byte_position) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ lock_.AssertAcquired();
+
+ reader_ = std::make_unique<MultiBufferReader>(
+ url_data_->multibuffer(), first_byte_position, last_byte_position,
+ base::BindRepeating(&MultiBufferDataSource::ProgressCallback, weak_ptr_),
+ render_task_runner_);
+ UpdateBufferSizes();
+}
+
+void MultiBufferDataSource::Initialize(InitializeCB init_cb) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ DCHECK(init_cb);
+ DCHECK(!reader_.get());
+
+ init_cb_ = std::move(init_cb);
+
+ CreateResourceLoader(0, kPositionNotSpecified);
+
+ // We're not allowed to call Wait() if data is already available.
+ if (reader_->Available()) {
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MultiBufferDataSource::StartCallback, weak_ptr_));
+
+ // When the entire file is already in the cache, we won't get any more
+ // progress callbacks, which breaks some expectations. Post a task to
+ // make sure that the client gets at least one call each for the progress
+ // and loading callbacks.
+ render_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&MultiBufferDataSource::UpdateProgress,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ reader_->Wait(
+ 1, base::BindOnce(&MultiBufferDataSource::StartCallback, weak_ptr_));
+ }
+}
+
+void MultiBufferDataSource::OnRedirected(
+ const scoped_refptr<UrlData>& new_destination) {
+ if (!new_destination) {
+ // A failure occurred.
+ failed_ = true;
+ if (init_cb_) {
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MultiBufferDataSource::StartCallback, weak_ptr_));
+ } else {
+ base::AutoLock auto_lock(lock_);
+ StopInternal_Locked();
+ }
+ StopLoader();
+ return;
+ }
+ if (url_data_->url().GetOrigin() != new_destination->url().GetOrigin()) {
+ single_origin_ = false;
+ }
+ SetReader(nullptr);
+ url_data_ = std::move(new_destination);
+
+ url_data_->OnRedirect(
+ base::BindOnce(&MultiBufferDataSource::OnRedirected, weak_ptr_));
+
+ if (init_cb_) {
+ CreateResourceLoader(0, kPositionNotSpecified);
+ if (reader_->Available()) {
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MultiBufferDataSource::StartCallback, weak_ptr_));
+ } else {
+ reader_->Wait(
+ 1, base::BindOnce(&MultiBufferDataSource::StartCallback, weak_ptr_));
+ }
+ } else if (read_op_) {
+ CreateResourceLoader(read_op_->position(), kPositionNotSpecified);
+ if (reader_->Available()) {
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MultiBufferDataSource::ReadTask, weak_ptr_));
+ } else {
+ reader_->Wait(
+ 1, base::BindOnce(&MultiBufferDataSource::ReadTask, weak_ptr_));
+ }
+ }
+
+ if (redirect_cb_)
+ redirect_cb_.Run();
+}
+
+void MultiBufferDataSource::SetPreload(Preload preload) {
+ DVLOG(1) << __func__ << "(" << preload << ")";
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ preload_ = preload;
+ UpdateBufferSizes();
+}
+
+bool MultiBufferDataSource::HasSingleOrigin() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ // Before initialization completes there is no risk of leaking data. Callers
+ // are required to order checks such that this isn't a race.
+ return single_origin_;
+}
+
+bool MultiBufferDataSource::IsCorsCrossOrigin() const {
+ return url_data_->is_cors_cross_origin();
+}
+
+void MultiBufferDataSource::OnRedirect(RedirectCB callback) {
+ redirect_cb_ = std::move(callback);
+}
+
+bool MultiBufferDataSource::HasAccessControl() const {
+ return url_data_->has_access_control();
+}
+
+UrlData::CorsMode MultiBufferDataSource::cors_mode() const {
+ return url_data_->cors_mode();
+}
+
+void MultiBufferDataSource::MediaPlaybackRateChanged(double playback_rate) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ if (playback_rate < 0 || playback_rate == playback_rate_)
+ return;
+
+ playback_rate_ = playback_rate;
+ cancel_on_defer_ = false;
+ UpdateBufferSizes();
+}
+
+void MultiBufferDataSource::MediaIsPlaying() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+
+ // Always clear this since it can be set by OnBufferingHaveEnough() calls at
+ // any point in time.
+ cancel_on_defer_ = false;
+
+ if (media_has_played_)
+ return;
+
+ media_has_played_ = true;
+
+ // Once we start playing, we need preloading.
+ preload_ = AUTO;
+ UpdateBufferSizes();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DataSource implementation.
+void MultiBufferDataSource::Stop() {
+ {
+ base::AutoLock auto_lock(lock_);
+ StopInternal_Locked();
+
+ // Cleanup resources immediately if we're already on the right thread.
+ if (render_task_runner_->BelongsToCurrentThread()) {
+ reader_.reset();
+ url_data_.reset();
+ return;
+ }
+ }
+
+ render_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&MultiBufferDataSource::StopLoader,
+ weak_factory_.GetWeakPtr()));
+}
+
+void MultiBufferDataSource::Abort() {
+ base::AutoLock auto_lock(lock_);
+ DCHECK(!init_cb_);
+ if (read_op_)
+ ReadOperation::Run(std::move(read_op_), kAborted);
+
+ // Abort does not call StopLoader() since it is typically called prior to a
+ // seek or suspend. Let the loader logic make the decision about whether a new
+ // loader is necessary upon the seek or resume.
+}
+
+void MultiBufferDataSource::SetBitrate(int bitrate) {
+ render_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&MultiBufferDataSource::SetBitrateTask,
+ weak_factory_.GetWeakPtr(), bitrate));
+}
+
+void MultiBufferDataSource::OnBufferingHaveEnough(bool always_cancel) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ if (reader_ && (always_cancel || (preload_ == METADATA &&
+ !media_has_played_ && !IsStreaming()))) {
+ cancel_on_defer_ = true;
+ if (!loading_) {
+ base::AutoLock auto_lock(lock_);
+ if (read_op_) {
+ // We can't destroy the reader if a read operation is pending.
+ // UpdateLoadingState_Locked will take care of it after the
+ // operation is done.
+ return;
+ }
+ // Already locked, no need to use SetReader().
+ reader_.reset(nullptr);
+ }
+ }
+}
+
+int64_t MultiBufferDataSource::GetMemoryUsage() {
+ // TODO(hubbe): Make more accurate when url_data_ is shared.
+ return base::checked_cast<int64_t>(url_data_->CachedSize())
+ << url_data_->multibuffer()->block_size_shift();
+}
+
+GURL MultiBufferDataSource::GetUrlAfterRedirects() const {
+ return url_data_->url();
+}
+
+void MultiBufferDataSource::Read(int64_t position,
+ int size,
+ uint8_t* data,
+ media::DataSource::ReadCB read_cb) {
+ DVLOG(1) << "Read: " << position << " offset, " << size << " bytes";
+ // Reading is not allowed until after initialization.
+ DCHECK(!init_cb_);
+ DCHECK(read_cb);
+
+ {
+ base::AutoLock auto_lock(lock_);
+ DCHECK(!read_op_);
+
+ if (stop_signal_received_) {
+ std::move(read_cb).Run(kReadError);
+ return;
+ }
+
+ // Optimization: Try reading from the cache here to get back to
+ // muxing as soon as possible. This works because TryReadAt is
+ // thread-safe.
+ if (reader_) {
+ int bytes_read = reader_->TryReadAt(position, data, size);
+ if (bytes_read > 0) {
+ bytes_read_ += bytes_read;
+ seek_positions_.push_back(position + bytes_read);
+ if (seek_positions_.size() == 1) {
+ render_task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&MultiBufferDataSource::SeekTask,
+ weak_factory_.GetWeakPtr()),
+ kSeekDelay);
+ }
+
+ std::move(read_cb).Run(bytes_read);
+ return;
+ }
+ }
+ read_op_ = std::make_unique<ReadOperation>(position, size, data,
+ std::move(read_cb));
+ }
+
+ render_task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&MultiBufferDataSource::ReadTask,
+ weak_factory_.GetWeakPtr()));
+}
+
+bool MultiBufferDataSource::GetSize(int64_t* size_out) {
+ base::AutoLock auto_lock(lock_);
+ if (total_bytes_ != kPositionNotSpecified) {
+ *size_out = total_bytes_;
+ return true;
+ }
+ *size_out = 0;
+ return false;
+}
+
+bool MultiBufferDataSource::IsStreaming() {
+ return streaming_;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// This method is the place where actual read happens,
+void MultiBufferDataSource::ReadTask() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+
+ base::AutoLock auto_lock(lock_);
+ int bytes_read = 0;
+ if (stop_signal_received_ || !read_op_)
+ return;
+ DCHECK(read_op_->size());
+
+ if (!reader_)
+ CreateResourceLoader_Locked(read_op_->position(), kPositionNotSpecified);
+
+ int64_t available = reader_->AvailableAt(read_op_->position());
+ if (available < 0) {
+ // A failure has occured.
+ ReadOperation::Run(std::move(read_op_), kReadError);
+ return;
+ }
+ if (available) {
+ bytes_read =
+ static_cast<int>(std::min<int64_t>(available, read_op_->size()));
+ bytes_read =
+ reader_->TryReadAt(read_op_->position(), read_op_->data(), bytes_read);
+
+ bytes_read_ += bytes_read;
+ seek_positions_.push_back(read_op_->position() + bytes_read);
+
+ if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) {
+ // We've reached the end of the file and we didn't know the total size
+ // before. Update the total size so Read()s past the end of the file will
+ // fail like they would if we had known the file size at the beginning.
+ total_bytes_ = read_op_->position() + bytes_read;
+ if (total_bytes_ != kPositionNotSpecified)
+ host_->SetTotalBytes(total_bytes_);
+ }
+
+ ReadOperation::Run(std::move(read_op_), bytes_read);
+
+ SeekTask_Locked();
+ } else {
+ reader_->Seek(read_op_->position());
+ reader_->Wait(1, base::BindOnce(&MultiBufferDataSource::ReadTask,
+ weak_factory_.GetWeakPtr()));
+ UpdateLoadingState_Locked(false);
+ }
+}
+
+void MultiBufferDataSource::SeekTask() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ base::AutoLock auto_lock(lock_);
+ SeekTask_Locked();
+}
+
+void MultiBufferDataSource::SeekTask_Locked() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ lock_.AssertAcquired();
+
+ if (stop_signal_received_)
+ return;
+
+ // A read operation is pending, which will call SeekTask_Locked when
+ // it's done. We'll defer any seeking until the read op is done.
+ if (read_op_)
+ return;
+
+ url_data_->AddBytesRead(bytes_read_);
+ bytes_read_ = 0;
+
+ if (reader_) {
+ // If we're seeking to a new location, (not just slightly further
+ // in the file) and we have more data buffered in that new location
+ // than in our current location, then we don't actually seek anywhere.
+ // Instead we keep preloading at the old location a while longer.
+
+ int64_t pos = reader_->Tell();
+ int64_t available = reader_->Available();
+
+ // Iterate backwards, because if two positions have the same
+ // amount of buffered data, we probably want to prefer the latest
+ // one in the array.
+ for (auto i = seek_positions_.rbegin(); i != seek_positions_.rend(); ++i) {
+ int64_t new_pos = *i;
+ int64_t available_at_new_pos = reader_->AvailableAt(new_pos);
+
+ if (total_bytes_ != kPositionNotSpecified) {
+ if (new_pos + available_at_new_pos >= total_bytes_) {
+ // Buffer reaches end of file, no need to seek here.
+ continue;
+ }
+ }
+ if (available_at_new_pos < available) {
+ pos = new_pos;
+ available = available_at_new_pos;
+ }
+ }
+ reader_->Seek(pos);
+ }
+ seek_positions_.clear();
+
+ UpdateLoadingState_Locked(false);
+}
+
+void MultiBufferDataSource::StopInternal_Locked() {
+ lock_.AssertAcquired();
+ if (stop_signal_received_)
+ return;
+
+ stop_signal_received_ = true;
+
+ // Initialize() isn't part of the DataSource interface so don't call it in
+ // response to Stop().
+ init_cb_.Reset();
+
+ if (read_op_)
+ ReadOperation::Run(std::move(read_op_), kReadError);
+}
+
+void MultiBufferDataSource::StopLoader() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ SetReader(nullptr);
+}
+
+void MultiBufferDataSource::SetBitrateTask(int bitrate) {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+
+ bitrate_ = bitrate;
+ UpdateBufferSizes();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// BufferedResourceLoader callback methods.
+void MultiBufferDataSource::StartCallback() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+
+ if (!init_cb_) {
+ SetReader(nullptr);
+ return;
+ }
+
+ // All responses must be successful. Resources that are assumed to be fully
+ // buffered must have a known content length.
+ bool success =
+ reader_ && reader_->Available() > 0 && url_data_ &&
+ (!AssumeFullyBuffered() || url_data_->length() != kPositionNotSpecified);
+
+ if (success) {
+ {
+ base::AutoLock auto_lock(lock_);
+ total_bytes_ = url_data_->length();
+ }
+ streaming_ =
+ !AssumeFullyBuffered() && (total_bytes_ == kPositionNotSpecified ||
+ !url_data_->range_supported());
+
+ media_log_->SetProperty<media::MediaLogProperty::kTotalBytes>(total_bytes_);
+ media_log_->SetProperty<media::MediaLogProperty::kIsStreaming>(streaming_);
+ } else {
+ SetReader(nullptr);
+ }
+
+ // TODO(scherkus): we shouldn't have to lock to signal host(), see
+ // http://crbug.com/113712 for details.
+ base::AutoLock auto_lock(lock_);
+ if (stop_signal_received_)
+ return;
+
+ if (success) {
+ if (total_bytes_ != kPositionNotSpecified) {
+ host_->SetTotalBytes(total_bytes_);
+ if (AssumeFullyBuffered())
+ host_->AddBufferedByteRange(0, total_bytes_);
+ }
+
+ // Progress callback might be called after the start callback,
+ // make sure that we update single_origin_ now.
+ media_log_->SetProperty<media::MediaLogProperty::kIsSingleOrigin>(
+ single_origin_);
+ media_log_->SetProperty<media::MediaLogProperty::kIsRangeHeaderSupported>(
+ url_data_->range_supported());
+ }
+
+ render_task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(init_cb_), success));
+
+ UpdateBufferSizes();
+
+ // Even if data is cached, say that we're loading at this point for
+ // compatibility.
+ UpdateLoadingState_Locked(true);
+}
+
+void MultiBufferDataSource::ProgressCallback(int64_t begin, int64_t end) {
+ DVLOG(1) << __func__ << "(" << begin << ", " << end << ")";
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+
+ base::AutoLock auto_lock(lock_);
+ if (stop_signal_received_)
+ return;
+
+ if (AssumeFullyBuffered())
+ return;
+
+ if (end > begin)
+ host_->AddBufferedByteRange(begin, end);
+
+ if (buffer_size_update_counter_ > 0)
+ buffer_size_update_counter_--;
+ else
+ UpdateBufferSizes();
+
+ UpdateLoadingState_Locked(false);
+}
+
+void MultiBufferDataSource::UpdateLoadingState_Locked(bool force_loading) {
+ DVLOG(1) << __func__;
+ lock_.AssertAcquired();
+ if (AssumeFullyBuffered())
+ return;
+ // Update loading state.
+ bool is_loading = !!reader_ && reader_->IsLoading();
+ if (force_loading || is_loading != loading_) {
+ bool loading = is_loading || force_loading;
+
+ if (!loading && cancel_on_defer_) {
+ if (read_op_) {
+ // We can't destroy the reader if a read operation is pending.
+ // UpdateLoadingState_Locked will be called again when the read
+ // operation is done.
+ return;
+ }
+ // Already locked, no need to use SetReader().
+ reader_.reset(nullptr);
+ }
+
+ loading_ = loading;
+ downloading_cb_.Run(loading_);
+ }
+}
+
+void MultiBufferDataSource::UpdateProgress() {
+ DCHECK(render_task_runner_->BelongsToCurrentThread());
+ if (reader_) {
+ uint64_t available = reader_->Available();
+ uint64_t pos = reader_->Tell();
+ ProgressCallback(pos, pos + available);
+ }
+}
+
+void MultiBufferDataSource::UpdateBufferSizes() {
+ DVLOG(1) << __func__;
+ if (!reader_)
+ return;
+
+ buffer_size_update_counter_ = kUpdateBufferSizeFrequency;
+
+ // Use a default bit rate if unknown and clamp to prevent overflow.
+ int64_t bitrate = base::clamp<int64_t>(bitrate_, 0, kMaxBitrate);
+ if (bitrate == 0)
+ bitrate = kDefaultBitrate;
+
+ // Only scale the buffer window for playback rates greater than 1.0 in
+ // magnitude and clamp to prevent overflow.
+ double playback_rate = playback_rate_;
+
+ playback_rate = std::max(playback_rate, 1.0);
+ playback_rate = std::min(playback_rate, kMaxPlaybackRate);
+
+ int64_t bytes_per_second = (bitrate / 8.0) * playback_rate;
+
+ // Preload 10 seconds of data, clamped to some min/max value.
+ int64_t preload = base::clamp(preload_seconds_.value() * bytes_per_second,
+ kMinBufferPreload, kMaxBufferPreload);
+
+ // Increase buffering slowly at a rate of 10% of data downloaded so
+ // far, maxing out at the preload size.
+ int64_t extra_buffer = std::min(
+ preload, url_data_->BytesReadFromCache() * kSlowPreloadPercentage / 100);
+
+ // Add extra buffer to preload.
+ preload += extra_buffer;
+
+ // We preload this much, then we stop unil we read |preload| before resuming.
+ int64_t preload_high = preload + kPreloadHighExtra;
+
+ // We pin a few seconds of data behind the current reading position.
+ int64_t pin_backward =
+ base::clamp(keep_after_playback_seconds_.value() * bytes_per_second,
+ kMinBufferPreload, kMaxBufferPreload);
+
+ // We always pin at least kDefaultPinSize ahead of the read position.
+ // Normally, the extra space between preload_high and kDefaultPinSize will
+ // not actually have any data in it, but if it does, we don't want to throw it
+ // away right before we need it.
+ int64_t pin_forward = std::max(preload_high, kDefaultPinSize);
+
+ // Note that the buffer size is advisory as only non-pinned data is allowed
+ // to be thrown away. Most of the time we pin a region that is larger than
+ // |buffer_size|, which only makes sense because most of the time, some of
+ // the data in pinned region is not present in the cache.
+ int64_t buffer_size = std::min(
+ (preload_seconds_.value() + keep_after_playback_seconds_.value()) *
+ bytes_per_second +
+ extra_buffer * 3,
+ preload_high + pin_backward + extra_buffer);
+
+ if (url_data_->FullyCached() ||
+ (url_data_->length() != kPositionNotSpecified &&
+ url_data_->length() < kDefaultPinSize)) {
+ // We just make pin_forwards/backwards big enough to encompass the
+ // whole file regardless of where we are, with some extra margins.
+ pin_forward = std::max(pin_forward, url_data_->length() * 2);
+ pin_backward = std::max(pin_backward, url_data_->length() * 2);
+ buffer_size = url_data_->length();
+ }
+
+ reader_->SetMaxBuffer(buffer_size);
+ reader_->SetPinRange(pin_backward, pin_forward);
+
+ if (preload_ == METADATA) {
+ preload_high >>= kMetadataShift;
+ preload >>= kMetadataShift;
+ }
+ reader_->SetPreload(preload_high, preload);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc b/chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc
new file mode 100644
index 00000000000..472735c3a12
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc
@@ -0,0 +1,1880 @@
+// 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/public/platform/media/multi_buffer_data_source.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/cxx17_backports.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/task_environment.h"
+#include "media/base/media_switches.h"
+#include "media/base/media_util.h"
+#include "media/base/mock_filters.h"
+#include "media/base/test_helpers.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
+#include "third_party/blink/public/platform/media/buffered_data_source_host_impl.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/renderer/platform/media/multi_buffer_reader.h"
+#include "third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h"
+#include "third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h"
+#include "third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h"
+#include "third_party/blink/renderer/platform/media/testing/test_response_generator.h"
+
+namespace blink {
+
+using ::testing::_;
+using ::testing::Assign;
+using ::testing::Invoke;
+using ::testing::InSequence;
+using ::testing::NiceMock;
+using ::testing::StrictMock;
+
+class TestMultiBufferDataProvider;
+
+std::set<TestMultiBufferDataProvider*> test_data_providers;
+
+class TestMultiBufferDataProvider : public ResourceMultiBufferDataProvider {
+ public:
+ TestMultiBufferDataProvider(
+ UrlData* url_data,
+ MultiBuffer::BlockId pos,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : ResourceMultiBufferDataProvider(url_data,
+ pos,
+ false /* is_client_audio_element */,
+ std::move(task_runner)) {
+ CHECK(test_data_providers.insert(this).second);
+ }
+ ~TestMultiBufferDataProvider() override {
+ CHECK_EQ(static_cast<size_t>(1), test_data_providers.erase(this));
+ }
+
+ // ResourceMultiBufferDataProvider overrides.
+ void Start() override {
+ ResourceMultiBufferDataProvider::Start();
+ if (on_start_)
+ std::move(on_start_).Run();
+ }
+ void SetDeferred(bool defer) override {
+ deferred_ = defer;
+ ResourceMultiBufferDataProvider::SetDeferred(defer);
+ }
+
+ bool loading() const { return !!active_loader_; }
+ bool deferred() const { return deferred_; }
+ void RunOnStart(base::OnceClosure cb) { on_start_ = std::move(cb); }
+
+ private:
+ bool deferred_ = false;
+ base::OnceClosure on_start_;
+};
+
+class TestUrlData;
+
+class TestResourceMultiBuffer : public ResourceMultiBuffer {
+ public:
+ TestResourceMultiBuffer(
+ UrlData* url_data,
+ int shift,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : ResourceMultiBuffer(url_data, shift, task_runner),
+ task_runner_(std::move(task_runner)) {}
+
+ std::unique_ptr<MultiBuffer::DataProvider> CreateWriter(const BlockId& pos,
+ bool) override {
+ auto writer = std::make_unique<TestMultiBufferDataProvider>(url_data_, pos,
+ task_runner_);
+ writer->Start();
+ return writer;
+ }
+
+ // TODO: Make these global
+
+ TestMultiBufferDataProvider* GetProvider() {
+ EXPECT_EQ(test_data_providers.size(), 1U);
+ if (test_data_providers.size() != 1)
+ return nullptr;
+ return *test_data_providers.begin();
+ }
+ TestMultiBufferDataProvider* GetProvider_allownull() {
+ EXPECT_LE(test_data_providers.size(), 1U);
+ if (test_data_providers.size() != 1U)
+ return nullptr;
+ return *test_data_providers.begin();
+ }
+ bool HasProvider() const { return test_data_providers.size() == 1U; }
+ bool loading() {
+ if (test_data_providers.empty())
+ return false;
+ return GetProvider()->loading();
+ }
+
+ private:
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class TestUrlData : public UrlData {
+ public:
+ TestUrlData(const GURL& url,
+ CorsMode cors_mode,
+ UrlIndex* url_index,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : UrlData(url, cors_mode, url_index, task_runner),
+ block_shift_(url_index->block_shift()),
+ task_runner_(std::move(task_runner)) {}
+
+ ResourceMultiBuffer* multibuffer() override {
+ if (!test_multibuffer_.get()) {
+ test_multibuffer_ = std::make_unique<TestResourceMultiBuffer>(
+ this, block_shift_, task_runner_);
+ }
+ return test_multibuffer_.get();
+ }
+
+ TestResourceMultiBuffer* test_multibuffer() {
+ if (!test_multibuffer_.get()) {
+ test_multibuffer_ = std::make_unique<TestResourceMultiBuffer>(
+ this, block_shift_, task_runner_);
+ }
+ return test_multibuffer_.get();
+ }
+
+ private:
+ ~TestUrlData() override = default;
+
+ const int block_shift_;
+ std::unique_ptr<TestResourceMultiBuffer> test_multibuffer_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class TestUrlIndex : public UrlIndex {
+ public:
+ TestUrlIndex(ResourceFetchContext* fetch_context,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : UrlIndex(fetch_context, task_runner),
+ task_runner_(std::move(task_runner)) {}
+
+ scoped_refptr<UrlData> NewUrlData(const GURL& url,
+ UrlData::CorsMode cors_mode) override {
+ last_url_data_ = new TestUrlData(url, cors_mode, this, task_runner_);
+ return last_url_data_;
+ }
+
+ scoped_refptr<TestUrlData> last_url_data() {
+ EXPECT_TRUE(last_url_data_);
+ return last_url_data_;
+ }
+
+ size_t load_queue_size() { return loading_queue_.size(); }
+
+ private:
+ scoped_refptr<TestUrlData> last_url_data_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class MockBufferedDataSourceHost : public BufferedDataSourceHost {
+ public:
+ MockBufferedDataSourceHost() = default;
+ MockBufferedDataSourceHost(const MockBufferedDataSourceHost&) = delete;
+ MockBufferedDataSourceHost& operator=(const MockBufferedDataSourceHost&) =
+ delete;
+ ~MockBufferedDataSourceHost() override = default;
+
+ MOCK_METHOD1(SetTotalBytes, void(int64_t total_bytes));
+ MOCK_METHOD2(AddBufferedByteRange, void(int64_t start, int64_t end));
+};
+
+class MockMultiBufferDataSource : public MultiBufferDataSource {
+ public:
+ MockMultiBufferDataSource(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ scoped_refptr<UrlData> url_data,
+ BufferedDataSourceHost* host)
+ : MultiBufferDataSource(
+ task_runner,
+ std::move(url_data),
+ &media_log_,
+ host,
+ base::BindRepeating(&MockMultiBufferDataSource::set_downloading,
+ base::Unretained(this))),
+ downloading_(false) {}
+
+ MockMultiBufferDataSource(const MockMultiBufferDataSource&) = delete;
+ MockMultiBufferDataSource& operator=(const MockMultiBufferDataSource&) =
+ delete;
+
+ bool downloading() { return downloading_; }
+ void set_downloading(bool downloading) { downloading_ = downloading; }
+ bool range_supported() { return url_data_->range_supported(); }
+ void CallSeekTask() { SeekTask(); }
+
+ private:
+ // Whether the resource is downloading or deferred.
+ bool downloading_;
+ media::NullMediaLog media_log_;
+};
+
+static const int64_t kFileSize = 5000000;
+static const int64_t kFarReadPosition = 3997696;
+static const int kDataSize = 32 << 10;
+
+static const char kHttpUrl[] = "http://localhost/foo.webm";
+static const char kFileUrl[] = "file:///tmp/bar.webm";
+static const char kHttpDifferentPathUrl[] = "http://localhost/bar.webm";
+static const char kHttpDifferentOriginUrl[] = "http://127.0.0.1/foo.webm";
+
+class MultiBufferDataSourceTest : public testing::Test {
+ public:
+ MultiBufferDataSourceTest() : preload_(MultiBufferDataSource::AUTO) {
+ ON_CALL(fetch_context_, CreateUrlLoader(_))
+ .WillByDefault(Invoke([](const WebAssociatedURLLoaderOptions&) {
+ return std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
+ }));
+ }
+
+ MultiBufferDataSourceTest(const MultiBufferDataSourceTest&) = delete;
+ MultiBufferDataSourceTest& operator=(const MultiBufferDataSourceTest&) =
+ delete;
+
+ MOCK_METHOD1(OnInitialize, void(bool));
+
+ void InitializeWithCors(const char* url,
+ bool expected,
+ UrlData::CorsMode cors_mode,
+ size_t file_size = kFileSize) {
+ GURL gurl(url);
+ data_source_ = std::make_unique<MockMultiBufferDataSource>(
+ task_runner_, url_index_.GetByUrl(gurl, cors_mode, UrlIndex::kNormal),
+ &host_);
+ data_source_->SetPreload(preload_);
+
+ response_generator_ =
+ std::make_unique<TestResponseGenerator>(gurl, file_size);
+ EXPECT_CALL(*this, OnInitialize(expected));
+ data_source_->Initialize(base::BindOnce(
+ &MultiBufferDataSourceTest::OnInitialize, base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+
+ // Not really loading until after OnInitialize is called.
+ EXPECT_EQ(data_source_->downloading(), false);
+ }
+
+ void Initialize(const char* url,
+ bool expected,
+ size_t file_size = kFileSize) {
+ InitializeWithCors(url, expected, UrlData::CORS_UNSPECIFIED, file_size);
+ }
+
+ // Helper to initialize tests with a valid 200 response.
+ void InitializeWith200Response() {
+ Initialize(kHttpUrl, true);
+
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ Respond(response_generator_->Generate200());
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+ }
+
+ // Helper to initialize tests with a valid 206 response.
+ void InitializeWith206Response(size_t file_size = kFileSize) {
+ Initialize(kHttpUrl, true, file_size);
+
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ Respond(response_generator_->Generate206(0));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+ }
+
+ // Helper to initialize tests with a valid file:// response.
+ void InitializeWithFileResponse() {
+ Initialize(kFileUrl, true);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kFileSize));
+ Respond(response_generator_->GenerateFileResponse(0));
+
+ ReceiveData(kDataSize);
+ }
+
+ // Starts data source.
+ void Start() {
+ EXPECT_TRUE(data_provider());
+ EXPECT_FALSE(active_loader_allownull());
+ data_provider()->Start();
+ }
+
+ // Stops any active loaders and shuts down the data source.
+ //
+ // This typically happens when the page is closed and for our purposes is
+ // appropriate to do when tearing down a test.
+ void Stop() {
+ if (loading()) {
+ data_provider()->DidFail(response_generator_->GenerateError());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ data_source_->Stop();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void Respond(const WebURLResponse& response) {
+ EXPECT_TRUE(active_loader());
+ data_provider()->DidReceiveResponse(response);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void ReceiveDataLow(int size) {
+ EXPECT_TRUE(active_loader());
+ std::unique_ptr<char[]> data(new char[size]);
+ memset(data.get(), 0xA5, size); // Arbitrary non-zero value.
+
+ data_provider()->DidReceiveData(data.get(), size);
+ }
+
+ void ReceiveData(int size) {
+ ReceiveDataLow(size);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void FinishLoading() {
+ EXPECT_TRUE(active_loader());
+ data_provider()->DidFinishLoading();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void FailLoading() {
+ data_provider()->DidFail(response_generator_->GenerateError());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ MOCK_METHOD1(ReadCallback, void(int size));
+
+ void ReadAt(int64_t position, int64_t howmuch = kDataSize) {
+ data_source_->Read(position, howmuch, buffer_,
+ base::BindOnce(&MultiBufferDataSourceTest::ReadCallback,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void ExecuteMixedResponseSuccessTest(const WebURLResponse& response1,
+ const WebURLResponse& response2) {
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize)).Times(2);
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+
+ FinishLoading();
+ Start();
+ ReadAt(kDataSize);
+ Respond(response2);
+ ReceiveData(kDataSize);
+ FinishLoading();
+ Stop();
+ }
+
+ void ExecuteMixedResponseFailureTest(const WebURLResponse& response1,
+ const WebURLResponse& response2) {
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ // Stop() will also cause the readback to be called with kReadError, but
+ // we want to make sure it was called before Stop().
+ bool failed_ = false;
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError))
+ .WillOnce(Assign(&failed_, true));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+
+ FinishLoading();
+ Start();
+ ReadAt(kDataSize);
+ Respond(response2);
+ EXPECT_TRUE(failed_);
+ Stop();
+ }
+
+ void CheckCapacityDefer() {
+ EXPECT_EQ(2 << 20, preload_low());
+ EXPECT_EQ(3 << 20, preload_high());
+ }
+
+ void CheckReadThenDefer() {
+ EXPECT_EQ(2 << 14, preload_low());
+ EXPECT_EQ(3 << 14, preload_high());
+ }
+
+ void CheckNeverDefer() {
+ EXPECT_EQ(1LL << 40, preload_low());
+ EXPECT_EQ(1LL << 40, preload_high());
+ }
+
+ // Accessors for private variables on |data_source_|.
+ MultiBufferReader* loader() { return data_source_->reader_.get(); }
+
+ TestResourceMultiBuffer* multibuffer() {
+ return url_index_.last_url_data()->test_multibuffer();
+ }
+
+ TestMultiBufferDataProvider* data_provider() {
+ return multibuffer()->GetProvider();
+ }
+ WebAssociatedURLLoader* active_loader() {
+ EXPECT_TRUE(data_provider());
+ if (!data_provider())
+ return nullptr;
+ return data_provider()->active_loader_.get();
+ }
+ WebAssociatedURLLoader* active_loader_allownull() {
+ TestMultiBufferDataProvider* data_provider =
+ multibuffer()->GetProvider_allownull();
+ if (!data_provider)
+ return nullptr;
+ return data_provider->active_loader_.get();
+ }
+ bool loading() { return multibuffer()->loading(); }
+
+ MultiBufferDataSource::Preload preload() { return data_source_->preload_; }
+ void set_preload(MultiBufferDataSource::Preload preload) {
+ preload_ = preload;
+ }
+ int64_t preload_high() {
+ CHECK(loader());
+ return loader()->preload_high();
+ }
+ int64_t preload_low() {
+ CHECK(loader());
+ return loader()->preload_low();
+ }
+ int data_source_bitrate() { return data_source_->bitrate_; }
+ int64_t max_buffer_forward() { return loader()->max_buffer_forward_; }
+ int64_t max_buffer_backward() { return loader()->max_buffer_backward_; }
+ int64_t buffer_size() {
+ return loader()->current_buffer_size_ * 32768 /* block size */;
+ }
+ double data_source_playback_rate() { return data_source_->playback_rate_; }
+ bool is_local_source() { return data_source_->AssumeFullyBuffered(); }
+ scoped_refptr<UrlData> url_data() { return data_source_->url_data_; }
+ void set_might_be_reused_from_cache_in_future(bool value) {
+ url_data()->set_cacheable(value);
+ }
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ MultiBufferDataSource::Preload preload_;
+ NiceMock<MockResourceFetchContext> fetch_context_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_ =
+ task_environment_.GetMainThreadTaskRunner();
+ TestUrlIndex url_index_{&fetch_context_, task_runner_};
+
+ std::unique_ptr<MockMultiBufferDataSource> data_source_;
+
+ std::unique_ptr<TestResponseGenerator> response_generator_;
+
+ StrictMock<MockBufferedDataSourceHost> host_;
+
+ // Used for calling MultiBufferDataSource::Read().
+ uint8_t buffer_[kDataSize * 2];
+};
+
+TEST_F(MultiBufferDataSourceTest, Range_Supported) {
+ InitializeWith206Response();
+
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsStreaming());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_InstanceSizeUnknown) {
+ Initialize(kHttpUrl, true);
+
+ Respond(response_generator_->Generate206(
+ 0, TestResponseGenerator::kNoContentRangeInstanceSize));
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_TRUE(loading());
+ EXPECT_TRUE(data_source_->IsStreaming());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_NotFound) {
+ Initialize(kHttpUrl, false);
+ Respond(response_generator_->Generate404());
+
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_NotSupported) {
+ InitializeWith200Response();
+
+ EXPECT_TRUE(loading());
+ EXPECT_TRUE(data_source_->IsStreaming());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_NotSatisfiable) {
+ Initialize(kHttpUrl, true);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ Respond(response_generator_->GenerateResponse(416));
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+// Special carve-out for Apache versions that choose to return a 200 for
+// Range:0- ("because it's more efficient" than a 206)
+TEST_F(MultiBufferDataSourceTest, Range_SupportedButReturned200) {
+ Initialize(kHttpUrl, true);
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ WebURLResponse response = response_generator_->Generate200();
+ response.SetHttpHeaderField(WebString::FromUTF8("Accept-Ranges"),
+ WebString::FromUTF8("bytes"));
+ Respond(response);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsStreaming());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_MissingContentRange) {
+ Initialize(kHttpUrl, false);
+ Respond(response_generator_->Generate206(
+ 0, TestResponseGenerator::kNoContentRange));
+
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_MissingContentLength) {
+ Initialize(kHttpUrl, true);
+
+ // It'll manage without a Content-Length response.
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ Respond(response_generator_->Generate206(
+ 0, TestResponseGenerator::kNoContentLength));
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsStreaming());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Range_WrongContentRange) {
+ Initialize(kHttpUrl, false);
+
+ // Now it's done and will fail.
+ Respond(response_generator_->Generate206(1337));
+
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+// Test the case where the initial response from the server indicates that
+// Range requests are supported, but a later request prove otherwise.
+TEST_F(MultiBufferDataSourceTest, Range_ServerLied) {
+ InitializeWith206Response();
+
+ // Read causing a new request to be made, we will discard the data that
+ // was already read in the first request.
+ ReadAt(kFarReadPosition);
+
+ // Return a 200 in response to a range request.
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ Respond(response_generator_->Generate200());
+
+ EXPECT_TRUE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_AbortWhileReading) {
+ InitializeWith206Response();
+
+ // Make sure there's a pending read -- we'll expect it to error.
+ ReadAt(kFileSize);
+
+ // Abort!!!
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kAborted));
+ data_source_->Abort();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, File_AbortWhileReading) {
+ InitializeWithFileResponse();
+
+ // Make sure there's a pending read -- we'll expect it to error.
+ ReadAt(kFileSize);
+
+ // Abort!!!
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kAborted));
+ data_source_->Abort();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_Retry) {
+ InitializeWith206Response();
+
+ // Read to advance our position.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ // Issue a pending read but terminate the connection to force a retry.
+ ReadAt(kDataSize);
+ FinishLoading();
+ Start();
+ Respond(response_generator_->Generate206(kDataSize));
+
+ // Complete the read.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize);
+
+ EXPECT_TRUE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_RetryOnError) {
+ InitializeWith206Response();
+
+ // Read to advance our position.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ // Issue a pending read but trigger an error to force a retry.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReadAt(kDataSize);
+ base::RunLoop run_loop;
+ data_provider()->DidFail(response_generator_->GenerateError());
+ data_provider()->RunOnStart(run_loop.QuitClosure());
+ run_loop.Run();
+ Respond(response_generator_->Generate206(kDataSize));
+ ReceiveData(kDataSize);
+ FinishLoading();
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+// Make sure that we prefetch across partial responses. (crbug.com/516589)
+TEST_F(MultiBufferDataSourceTest, Http_PartialResponsePrefetch) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 3 - 1);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+
+ FinishLoading();
+ Start();
+ Respond(response2);
+ ReceiveData(kDataSize);
+ ReceiveData(kDataSize);
+ FinishLoading();
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_PartialResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ // The origin URL of response1 and response2 are same. So no error should
+ // occur.
+ ExecuteMixedResponseSuccessTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_RedirectedToDifferentPathResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ response2.SetCurrentRequestUrl(GURL(kHttpDifferentPathUrl));
+ // The origin URL of response1 and response2 are same. So no error should
+ // occur.
+ ExecuteMixedResponseSuccessTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_RedirectedToDifferentOriginResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ response2.SetCurrentRequestUrl(GURL(kHttpDifferentOriginUrl));
+ // The origin URL of response1 and response2 are different. So an error should
+ // occur.
+ ExecuteMixedResponseFailureTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_ServiceWorkerGeneratedResponseAndNormalResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetWasFetchedViaServiceWorker(true);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ // response1 is generated in a Service Worker but response2 is from a native
+ // server. So an error should occur.
+ ExecuteMixedResponseFailureTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_ServiceWorkerProxiedAndSameURLResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetWasFetchedViaServiceWorker(true);
+ std::vector<WebURL> url_list = {GURL(kHttpUrl)};
+ response1.SetUrlListViaServiceWorker(url_list);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ // The origin URL of response1 and response2 are same. So no error should
+ // occur.
+ ExecuteMixedResponseSuccessTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_ServiceWorkerProxiedAndDifferentPathResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetWasFetchedViaServiceWorker(true);
+ std::vector<WebURL> url_list = {GURL(kHttpDifferentPathUrl)};
+ response1.SetUrlListViaServiceWorker(url_list);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ // The origin URL of response1 and response2 are same. So no error should
+ // occur.
+ ExecuteMixedResponseSuccessTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_ServiceWorkerProxiedAndDifferentOriginResponse) {
+ Initialize(kHttpUrl, true);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetWasFetchedViaServiceWorker(true);
+ std::vector<WebURL> url_list = {GURL(kHttpDifferentOriginUrl)};
+ response1.SetUrlListViaServiceWorker(url_list);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ // The origin URL of response1 and response2 are different. So an error should
+ // occur.
+ ExecuteMixedResponseFailureTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ Http_MixedResponse_ServiceWorkerProxiedAndDifferentOriginResponseCors) {
+ InitializeWithCors(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetWasFetchedViaServiceWorker(true);
+ std::vector<WebURL> url_list = {GURL(kHttpDifferentOriginUrl)};
+ response1.SetUrlListViaServiceWorker(url_list);
+ WebURLResponse response2 =
+ response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+ // The origin URL of response1 and response2 are different, but a CORS check
+ // has been passed for each request, so expect success.
+ ExecuteMixedResponseSuccessTest(response1, response2);
+}
+
+TEST_F(MultiBufferDataSourceTest, File_Retry) {
+ InitializeWithFileResponse();
+
+ // Read to advance our position.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ // Issue a pending read but terminate the connection to force a retry.
+ ReadAt(kDataSize);
+ FinishLoading();
+ Start();
+ Respond(response_generator_->GenerateFileResponse(kDataSize));
+
+ // Complete the read.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_TRUE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_TooManyRetries) {
+ InitializeWith206Response();
+
+ // Make sure there's a pending read -- we'll expect it to error.
+ ReadAt(kDataSize);
+
+ for (int i = 0; i < ResourceMultiBufferDataProvider::kMaxRetries; i++) {
+ FailLoading();
+ Start();
+ Respond(response_generator_->Generate206(kDataSize));
+ }
+
+ // Stop() will also cause the readback to be called with kReadError, but
+ // we want to make sure it was called during FailLoading().
+ bool failed_ = false;
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError))
+ .WillOnce(Assign(&failed_, true));
+ FailLoading();
+ EXPECT_TRUE(failed_);
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, File_TooManyRetries) {
+ InitializeWithFileResponse();
+
+ // Make sure there's a pending read -- we'll expect it to error.
+ ReadAt(kDataSize);
+
+ for (int i = 0; i < ResourceMultiBufferDataProvider::kMaxRetries; i++) {
+ FailLoading();
+ Start();
+ Respond(response_generator_->Generate206(kDataSize));
+ }
+
+ // Stop() will also cause the readback to be called with kReadError, but
+ // we want to make sure it was called during FailLoading().
+ bool failed_ = false;
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError))
+ .WillOnce(Assign(&failed_, true));
+ FailLoading();
+ EXPECT_TRUE(failed_);
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, File_InstanceSizeUnknown) {
+ Initialize(kFileUrl, false);
+
+ Respond(
+ response_generator_->GenerateFileResponse(media::DataSource::kReadError));
+ ReceiveData(kDataSize);
+
+ EXPECT_FALSE(data_source_->downloading());
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, File_Successful) {
+ InitializeWithFileResponse();
+
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsStreaming());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, StopDuringRead) {
+ InitializeWith206Response();
+
+ uint8_t buffer[256];
+ data_source_->Read(kDataSize, base::size(buffer), buffer,
+ base::BindOnce(&MultiBufferDataSourceTest::ReadCallback,
+ base::Unretained(this)));
+
+ // The outstanding read should fail before the stop callback runs.
+ {
+ InSequence s;
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ data_source_->Stop();
+ }
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MultiBufferDataSourceTest, DefaultValues) {
+ InitializeWith206Response();
+
+ // Ensure we have sane values for default loading scenario.
+ EXPECT_EQ(MultiBufferDataSource::AUTO, preload());
+ EXPECT_EQ(2 << 20, preload_low());
+ EXPECT_EQ(3 << 20, preload_high());
+
+ EXPECT_EQ(0, data_source_bitrate());
+ EXPECT_EQ(0.0, data_source_playback_rate());
+
+ EXPECT_TRUE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, SetBitrate) {
+ InitializeWith206Response();
+
+ data_source_->SetBitrate(1234);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1234, data_source_bitrate());
+
+ // Read so far ahead to cause the loader to get recreated.
+ TestMultiBufferDataProvider* old_loader = data_provider();
+ ReadAt(kFarReadPosition);
+ Respond(response_generator_->Generate206(kFarReadPosition));
+
+ // Verify loader changed but still has same bitrate.
+ EXPECT_NE(old_loader, data_provider());
+
+ EXPECT_TRUE(loading());
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, MediaPlaybackRateChanged) {
+ InitializeWith206Response();
+
+ data_source_->MediaPlaybackRateChanged(2.0);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2.0, data_source_playback_rate());
+
+ // Read so far ahead to cause the loader to get recreated.
+ TestMultiBufferDataProvider* old_loader = data_provider();
+ ReadAt(kFarReadPosition);
+ Respond(response_generator_->Generate206(kFarReadPosition));
+
+ // Verify loader changed but still has same playback rate.
+ EXPECT_NE(old_loader, data_provider());
+
+ EXPECT_TRUE(loading());
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_Read) {
+ InitializeWith206Response();
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0, kDataSize * 2);
+
+ ReadAt(kDataSize, kDataSize);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_,
+ AddBufferedByteRange(kDataSize, kDataSize + kDataSize / 2));
+ ReceiveData(kDataSize / 2);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize / 2);
+
+ EXPECT_TRUE(data_source_->downloading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_ShareData) {
+ InitializeWith206Response();
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0, kDataSize * 2);
+
+ ReadAt(kDataSize, kDataSize);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_,
+ AddBufferedByteRange(kDataSize, kDataSize + kDataSize / 2));
+ ReceiveData(kDataSize / 2);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize / 2);
+
+ EXPECT_TRUE(data_source_->downloading());
+
+ StrictMock<MockBufferedDataSourceHost> host2;
+ MockMultiBufferDataSource source2(
+ task_runner_,
+ url_index_.GetByUrl(GURL(kHttpUrl), UrlData::CORS_UNSPECIFIED,
+ UrlIndex::kNormal),
+ &host2);
+ source2.SetPreload(preload_);
+
+ EXPECT_CALL(*this, OnInitialize(true));
+
+ // This call would not be expected if we were not sharing data.
+ EXPECT_CALL(host2, SetTotalBytes(response_generator_->content_length()));
+ EXPECT_CALL(host2, AddBufferedByteRange(0, kDataSize * 2));
+ source2.Initialize(base::BindOnce(&MultiBufferDataSourceTest::OnInitialize,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+
+ // Always loading after initialize.
+ EXPECT_EQ(source2.downloading(), true);
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_Read_Seek) {
+ InitializeWith206Response();
+
+ // Read a bit from the beginning.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ // Simulate a seek by reading a bit beyond kDataSize.
+ ReadAt(kDataSize * 2);
+
+ // We receive data leading up to but not including our read.
+ // No notification will happen, since it's progress outside
+ // of our current range.
+ ReceiveData(kDataSize);
+
+ // We now receive the rest of the data for our read.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ ReceiveData(kDataSize);
+
+ EXPECT_TRUE(data_source_->downloading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, File_Read) {
+ InitializeWithFileResponse();
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0, kDataSize * 2);
+
+ ReadAt(kDataSize, kDataSize);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReceiveData(kDataSize);
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_FinishLoading) {
+ InitializeWith206Response();
+
+ EXPECT_TRUE(data_source_->downloading());
+ // premature didFinishLoading() will cause a retry.
+ FinishLoading();
+ EXPECT_TRUE(data_source_->downloading());
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, File_FinishLoading) {
+ InitializeWithFileResponse();
+
+ ReceiveData(kDataSize);
+
+ EXPECT_FALSE(data_source_->downloading());
+ // premature didFinishLoading() will cause a retry.
+ FinishLoading();
+ EXPECT_FALSE(data_source_->downloading());
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, LocalResource_DeferStrategy) {
+ InitializeWithFileResponse();
+
+ EXPECT_EQ(MultiBufferDataSource::AUTO, preload());
+ EXPECT_TRUE(is_local_source());
+ CheckCapacityDefer();
+
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, LocalResource_PreloadMetadata_DeferStrategy) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWithFileResponse();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_TRUE(is_local_source());
+ CheckReadThenDefer();
+
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, ExternalResource_Reponse200_DeferStrategy) {
+ InitializeWith200Response();
+
+ EXPECT_EQ(MultiBufferDataSource::AUTO, preload());
+ EXPECT_FALSE(is_local_source());
+ EXPECT_FALSE(data_source_->range_supported());
+ CheckCapacityDefer();
+
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ ExternalResource_Response200_PreloadMetadata_DeferStrategy) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith200Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+ EXPECT_FALSE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, ExternalResource_Reponse206_DeferStrategy) {
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::AUTO, preload());
+ EXPECT_FALSE(is_local_source());
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckCapacityDefer();
+
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ set_might_be_reused_from_cache_in_future(true);
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ ExternalResource_Response206_PreloadMetadata_DeferStrategy) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ set_might_be_reused_from_cache_in_future(true);
+ data_source_->MediaIsPlaying();
+ CheckCapacityDefer();
+
+ set_might_be_reused_from_cache_in_future(false);
+ CheckCapacityDefer();
+
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, ExternalResource_Response206_VerifyDefer) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ // Read a bit from the beginning.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize);
+
+ ASSERT_TRUE(active_loader());
+ EXPECT_TRUE(data_provider()->deferred());
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ ExternalResource_Response206_CancelAfterDefer) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ ReadAt(kDataSize);
+
+ data_source_->OnBufferingHaveEnough(false);
+ ASSERT_TRUE(active_loader());
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ ReceiveData(kDataSize);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 4));
+ ReceiveData(kDataSize);
+
+ EXPECT_FALSE(active_loader_allownull());
+}
+
+// This test tries to trigger an edge case where the read callback
+// never happens because the reader is deleted before that happens.
+TEST_F(MultiBufferDataSourceTest,
+ ExternalResource_Response206_CancelAfterDefer2) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ ReadAt(kDataSize);
+
+ data_source_->OnBufferingHaveEnough(false);
+ ASSERT_TRUE(active_loader());
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, kDataSize + 2000));
+
+ ReceiveDataLow(2000);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2 + 2000));
+ EXPECT_CALL(host_, AddBufferedByteRange(kDataSize * 2, kDataSize * 2 + 2000));
+ ReceiveDataLow(kDataSize);
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3 + 2000));
+ ReceiveData(kDataSize);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 4 + 2000));
+ ReceiveData(kDataSize);
+
+ EXPECT_FALSE(active_loader_allownull());
+}
+
+// This test tries to trigger an edge case where the read callback
+// never happens because the reader is deleted before that happens.
+TEST_F(MultiBufferDataSourceTest,
+ ExternalResource_Response206_CancelAfterDefer3) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ ReadAt(kDataSize);
+ ASSERT_TRUE(active_loader());
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ ReceiveData(kDataSize);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 4));
+ ReceiveData(kDataSize);
+ EXPECT_EQ(data_source_->downloading(), false);
+ data_source_->Read(kDataSize * 10, kDataSize, buffer_,
+ base::BindOnce(&MultiBufferDataSourceTest::ReadCallback,
+ base::Unretained(this)));
+ data_source_->OnBufferingHaveEnough(false);
+ EXPECT_TRUE(active_loader_allownull());
+ EXPECT_CALL(*this, ReadCallback(-1));
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest,
+ ExternalResource_Response206_CancelAfterPlay) {
+ set_preload(MultiBufferDataSource::METADATA);
+ InitializeWith206Response();
+
+ EXPECT_EQ(MultiBufferDataSource::METADATA, preload());
+ EXPECT_FALSE(is_local_source());
+
+ EXPECT_TRUE(data_source_->range_supported());
+ CheckReadThenDefer();
+
+ ReadAt(kDataSize);
+
+ // Marking the media as playing should prevent deferral. It also tells the
+ // data source to start buffering beyond the initial load.
+ EXPECT_FALSE(data_source_->cancel_on_defer_for_testing());
+ data_source_->MediaIsPlaying();
+ data_source_->OnBufferingHaveEnough(false);
+ CheckCapacityDefer();
+ ASSERT_TRUE(active_loader());
+
+ // Read a bit from the beginning and ensure deferral hasn't happened yet.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize);
+ ASSERT_TRUE(active_loader());
+ data_source_->OnBufferingHaveEnough(true);
+ EXPECT_TRUE(data_source_->cancel_on_defer_for_testing());
+ ASSERT_TRUE(active_loader());
+ ASSERT_FALSE(data_provider()->deferred());
+
+ // Deliver data until capacity is reached and verify deferral.
+ int bytes_received = 0;
+ EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(testing::AtLeast(1));
+ while (active_loader_allownull() && !data_provider()->deferred()) {
+ ReceiveData(kDataSize);
+ bytes_received += kDataSize;
+ }
+ EXPECT_GT(bytes_received, 0);
+ EXPECT_LT(bytes_received + kDataSize, kFileSize);
+ EXPECT_FALSE(active_loader_allownull());
+
+ // Verify playback resumes correctly too.
+ data_source_->MediaIsPlaying();
+ EXPECT_FALSE(data_source_->cancel_on_defer_for_testing());
+
+ // A read from a previously buffered range won't create a new loader yet.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kDataSize);
+ EXPECT_FALSE(active_loader_allownull());
+
+ // Reads from an unbuffered range will though...
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kFarReadPosition);
+
+ // Receive enough data to exhaust current capacity which would destroy the
+ // loader upon deferral if the flag hasn't been cleared properly.
+ for (int i = 0; i <= (preload_high() / kDataSize) + 1; ++i) {
+ ReceiveData(kDataSize);
+ ASSERT_TRUE(active_loader());
+ }
+}
+
+TEST_F(MultiBufferDataSourceTest, SeekPastEOF) {
+ GURL gurl(kHttpUrl);
+ data_source_ = std::make_unique<MockMultiBufferDataSource>(
+ task_runner_,
+ url_index_.GetByUrl(gurl, UrlData::CORS_UNSPECIFIED, UrlIndex::kNormal),
+ &host_);
+ data_source_->SetPreload(preload_);
+
+ response_generator_ =
+ std::make_unique<TestResponseGenerator>(gurl, kDataSize + 1);
+ EXPECT_CALL(*this, OnInitialize(true));
+ data_source_->Initialize(base::BindOnce(
+ &MultiBufferDataSourceTest::OnInitialize, base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+
+ // Not really loading until after OnInitialize is called.
+ EXPECT_EQ(data_source_->downloading(), false);
+
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ Respond(response_generator_->Generate206(0));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ // Read a bit from the beginning.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, kDataSize + 1));
+ ReceiveData(1);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ FinishLoading();
+ EXPECT_CALL(*this, ReadCallback(0));
+
+ ReadAt(kDataSize + 5, kDataSize * 2);
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_RetryThenRedirect) {
+ InitializeWith206Response();
+
+ // Read to advance our position.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ // Issue a pending read but trigger an error to force a retry.
+ EXPECT_CALL(*this, ReadCallback(kDataSize - 10));
+ ReadAt(kDataSize + 10, kDataSize - 10);
+ base::RunLoop run_loop;
+ data_provider()->DidFail(response_generator_->GenerateError());
+ data_provider()->RunOnStart(run_loop.QuitClosure());
+ run_loop.Run();
+
+ // Server responds with a redirect.
+ WebURL url{GURL(kHttpDifferentPathUrl)};
+ WebURLResponse response((GURL(kHttpUrl)));
+ response.SetHttpStatusCode(307);
+ data_provider()->WillFollowRedirect(url, response);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ Respond(response_generator_->Generate206(kDataSize));
+ ReceiveData(kDataSize);
+
+ FinishLoading();
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_NotStreamingAfterRedirect) {
+ Initialize(kHttpUrl, true);
+
+ // Server responds with a redirect.
+ WebURL url{GURL(kHttpDifferentPathUrl)};
+ WebURLResponse response((GURL(kHttpUrl)));
+ response.SetHttpStatusCode(307);
+ data_provider()->WillFollowRedirect(url, response);
+
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ Respond(response_generator_->Generate206(0));
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_FALSE(data_source_->IsStreaming());
+
+ FinishLoading();
+ EXPECT_FALSE(loading());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_RangeNotSatisfiableAfterRedirect) {
+ Initialize(kHttpUrl, true);
+
+ // Server responds with a redirect.
+ WebURL url{GURL(kHttpDifferentPathUrl)};
+ WebURLResponse response((GURL(kHttpUrl)));
+ response.SetHttpStatusCode(307);
+ data_provider()->WillFollowRedirect(url, response);
+
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ Respond(response_generator_->GenerateResponse(416));
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_404AfterRedirect) {
+ Initialize(kHttpUrl, false);
+
+ // Server responds with a redirect.
+ WebURL url{GURL(kHttpDifferentPathUrl)};
+ WebURLResponse response((GURL(kHttpUrl)));
+ response.SetHttpStatusCode(307);
+ data_provider()->WillFollowRedirect(url, response);
+
+ Respond(response_generator_->Generate404());
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, LengthKnownAtEOF) {
+ Initialize(kHttpUrl, true);
+ // Server responds without content-length.
+ WebURLResponse response = response_generator_->Generate200();
+ response.ClearHttpHeaderField(WebString::FromUTF8("Content-Length"));
+ response.SetExpectedContentLength(kPositionNotSpecified);
+ Respond(response);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+ int64_t len;
+ EXPECT_FALSE(data_source_->GetSize(&len));
+ EXPECT_TRUE(data_source_->IsStreaming());
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ ReadAt(kDataSize);
+ EXPECT_CALL(host_, SetTotalBytes(kDataSize));
+ EXPECT_CALL(*this, ReadCallback(0));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ FinishLoading();
+
+ // Done loading, now we should know the length.
+ EXPECT_TRUE(data_source_->GetSize(&len));
+ EXPECT_EQ(kDataSize, len);
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, FileSizeLessThanBlockSize) {
+ Initialize(kHttpUrl, true);
+ GURL gurl(kHttpUrl);
+ WebURLResponse response(gurl);
+ response.SetHttpStatusCode(200);
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Length"),
+ WebString::FromUTF8(base::NumberToString(kDataSize / 2)));
+ response.SetExpectedContentLength(kDataSize / 2);
+ Respond(response);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize / 2));
+ EXPECT_CALL(host_, SetTotalBytes(kDataSize / 2));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize / 2);
+ FinishLoading();
+
+ int64_t len = 0;
+ EXPECT_TRUE(data_source_->GetSize(&len));
+ EXPECT_EQ(kDataSize / 2, len);
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, ResponseTypeBasic) {
+ InitializeWithCors(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+ set_preload(MultiBufferDataSource::NONE);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetType(network::mojom::FetchResponseType::kBasic);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsCorsCrossOrigin());
+
+ FinishLoading();
+}
+
+TEST_F(MultiBufferDataSourceTest, ResponseTypeCors) {
+ InitializeWithCors(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+ set_preload(MultiBufferDataSource::NONE);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetType(network::mojom::FetchResponseType::kCors);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsCorsCrossOrigin());
+
+ FinishLoading();
+}
+
+TEST_F(MultiBufferDataSourceTest, ResponseTypeDefault) {
+ InitializeWithCors(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+ set_preload(MultiBufferDataSource::NONE);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetType(network::mojom::FetchResponseType::kDefault);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+ EXPECT_FALSE(data_source_->IsCorsCrossOrigin());
+
+ FinishLoading();
+}
+
+TEST_F(MultiBufferDataSourceTest, ResponseTypeOpaque) {
+ InitializeWithCors(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+ set_preload(MultiBufferDataSource::NONE);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetType(network::mojom::FetchResponseType::kOpaque);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+ EXPECT_TRUE(data_source_->IsCorsCrossOrigin());
+
+ FinishLoading();
+}
+
+TEST_F(MultiBufferDataSourceTest, ResponseTypeOpaqueRedirect) {
+ InitializeWithCors(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+ set_preload(MultiBufferDataSource::NONE);
+ WebURLResponse response1 =
+ response_generator_->GeneratePartial206(0, kDataSize - 1);
+ response1.SetType(network::mojom::FetchResponseType::kOpaqueRedirect);
+
+ EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+ Respond(response1);
+ ReceiveData(kDataSize);
+ ReadAt(0);
+ EXPECT_TRUE(loading());
+ EXPECT_TRUE(data_source_->IsCorsCrossOrigin());
+
+ FinishLoading();
+}
+
+TEST_F(MultiBufferDataSourceTest, EtagTest) {
+ Initialize(kHttpUrl, true);
+
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ WebURLResponse response = response_generator_->Generate206(0);
+ const std::string etag("\"arglebargle glop-glyf?\"");
+ response.SetHttpHeaderField(WebString::FromUTF8("Etag"),
+ WebString::FromUTF8(etag));
+ Respond(response);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_EQ(url_data()->etag(), etag);
+}
+
+TEST_F(MultiBufferDataSourceTest, CheckBufferSizes) {
+ InitializeWith206Response(1 << 30); // 1 gb
+
+ data_source_->SetBitrate(1 << 20); // 1 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1 << 20, data_source_bitrate());
+ EXPECT_EQ(2 << 20, preload_low());
+ EXPECT_EQ(3 << 20, preload_high());
+ EXPECT_EQ(25 << 20, max_buffer_forward());
+ EXPECT_EQ(2 << 20, max_buffer_backward());
+ EXPECT_EQ(1572864 /* 1.5Mb */, buffer_size());
+
+ data_source_->SetBitrate(8 << 20); // 8 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(8 << 20, data_source_bitrate());
+ EXPECT_EQ(10 << 20, preload_low());
+ EXPECT_EQ(11 << 20, preload_high());
+ EXPECT_EQ(25 << 20, max_buffer_forward());
+ EXPECT_EQ(2 << 20, max_buffer_backward());
+ EXPECT_EQ(12 << 20, buffer_size());
+
+ data_source_->SetBitrate(16 << 20); // 16 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(16 << 20, data_source_bitrate());
+ EXPECT_EQ(20 << 20, preload_low());
+ EXPECT_EQ(21 << 20, preload_high());
+ EXPECT_EQ(25 << 20, max_buffer_forward());
+ EXPECT_EQ(4 << 20, max_buffer_backward());
+ EXPECT_EQ(24 << 20, buffer_size());
+
+ data_source_->SetBitrate(32 << 20); // 32 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(32 << 20, data_source_bitrate());
+ EXPECT_EQ(40 << 20, preload_low());
+ EXPECT_EQ(41 << 20, preload_high());
+ EXPECT_EQ(41 << 20, max_buffer_forward());
+ EXPECT_EQ(8 << 20, max_buffer_backward());
+ EXPECT_EQ(48 << 20, buffer_size());
+
+ data_source_->SetBitrate(80 << 20); // 80 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(80 << 20, data_source_bitrate());
+ EXPECT_EQ(50 << 20, preload_low());
+ EXPECT_EQ(51 << 20, preload_high());
+ EXPECT_EQ(51 << 20, max_buffer_forward());
+ EXPECT_EQ(20 << 20, max_buffer_backward());
+ EXPECT_EQ(71 << 20, buffer_size());
+}
+
+TEST_F(MultiBufferDataSourceTest, CheckBufferSizeForSmallFiles) {
+ InitializeWith206Response();
+
+ data_source_->SetBitrate(1 << 20); // 1 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1 << 20, data_source_bitrate());
+ EXPECT_EQ(2 << 20, preload_low());
+ EXPECT_EQ(3 << 20, preload_high());
+ EXPECT_EQ(25 << 20, max_buffer_forward());
+ EXPECT_EQ(kFileSize * 2, max_buffer_backward());
+ EXPECT_EQ(5013504 /* file size rounded up to blocks size */, buffer_size());
+
+ data_source_->SetBitrate(80 << 20); // 80 mbit / s
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(80 << 20, data_source_bitrate());
+ EXPECT_EQ(50 << 20, preload_low());
+ EXPECT_EQ(51 << 20, preload_high());
+ EXPECT_EQ(51 << 20, max_buffer_forward());
+ EXPECT_EQ(20 << 20, max_buffer_backward());
+ EXPECT_EQ(5013504 /* file size rounded up to blocks size */, buffer_size());
+}
+
+TEST_F(MultiBufferDataSourceTest, CheckBufferSizeAfterReadingALot) {
+ InitializeWith206Response();
+
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ const int to_read = 40;
+
+ for (int i = 1; i < to_read; i++) {
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * (i + 1)));
+ ReadAt(i * kDataSize);
+ ReceiveData(kDataSize);
+ }
+
+ data_source_->SetBitrate(1 << 20); // 1 mbit / s
+ base::RunLoop().RunUntilIdle();
+ int64_t extra_buffer = to_read / 10 * kDataSize;
+ EXPECT_EQ(1 << 20, data_source_bitrate());
+ EXPECT_EQ((2 << 20) + extra_buffer, preload_low());
+ EXPECT_EQ((3 << 20) + extra_buffer, preload_high());
+ EXPECT_EQ(25 << 20, max_buffer_forward());
+ EXPECT_EQ(kFileSize * 2, max_buffer_backward());
+ EXPECT_EQ(5013504 /* file size rounded up to blocks size */, buffer_size());
+}
+
+// Provoke an edge case where the loading state may not end up transitioning
+// back to "idle" when we're done loading.
+TEST_F(MultiBufferDataSourceTest, Http_CheckLoadingTransition) {
+ GURL gurl(kHttpUrl);
+ data_source_ = std::make_unique<MockMultiBufferDataSource>(
+ task_runner_,
+ url_index_.GetByUrl(gurl, UrlData::CORS_UNSPECIFIED, UrlIndex::kNormal),
+ &host_);
+ data_source_->SetPreload(preload_);
+
+ response_generator_ =
+ std::make_unique<TestResponseGenerator>(gurl, kDataSize * 1);
+ EXPECT_CALL(*this, OnInitialize(true));
+ data_source_->Initialize(base::BindOnce(
+ &MultiBufferDataSourceTest::OnInitialize, base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+
+ // Not really loading until after OnInitialize is called.
+ EXPECT_EQ(data_source_->downloading(), false);
+
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
+ Respond(response_generator_->Generate206(0));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+ ReceiveData(kDataSize);
+
+ EXPECT_EQ(data_source_->downloading(), true);
+ EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, kDataSize + 1));
+ ReceiveDataLow(1);
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ data_provider()->DidFinishLoading();
+
+ EXPECT_CALL(*this, ReadCallback(1));
+ data_source_->Read(kDataSize, 2, buffer_,
+ base::BindOnce(&MultiBufferDataSourceTest::ReadCallback,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+
+ // Make sure we're not downloading anymore.
+ EXPECT_EQ(data_source_->downloading(), false);
+ Stop();
+}
+
+TEST_F(MultiBufferDataSourceTest, Http_Seek_Back) {
+ InitializeWith206Response();
+
+ // Read a bit from the beginning.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+
+ ReadAt(kDataSize);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2));
+ ReceiveData(kDataSize);
+ ReadAt(kDataSize * 2);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3));
+ ReceiveData(kDataSize);
+
+ // Read some data from far ahead.
+ ReadAt(kFarReadPosition);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(kFarReadPosition,
+ kFarReadPosition + kDataSize));
+ Respond(response_generator_->Generate206(kFarReadPosition));
+ ReceiveData(kDataSize);
+
+ // This should not close the current connection, because we have
+ // more data buffered at this location than at kFarReadPosition.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+ data_source_->CallSeekTask();
+ EXPECT_EQ(kFarReadPosition + kDataSize, loader()->Tell());
+
+ // Again, no seek.
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kDataSize);
+ data_source_->CallSeekTask();
+ EXPECT_EQ(kFarReadPosition + kDataSize, loader()->Tell());
+
+ // Still no seek
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kFarReadPosition);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kDataSize);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kDataSize * 2);
+ data_source_->CallSeekTask();
+ EXPECT_EQ(kFarReadPosition + kDataSize, loader()->Tell());
+
+ // Read some data from far ahead, but right before where we read before.
+ // This time we'll have one block buffered.
+ ReadAt(kFarReadPosition - kDataSize);
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ EXPECT_CALL(host_, AddBufferedByteRange(kFarReadPosition - kDataSize,
+ kFarReadPosition + kDataSize));
+ Respond(response_generator_->Generate206(kFarReadPosition - kDataSize));
+ ReceiveData(kDataSize);
+
+ // No Seek
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(0);
+ data_source_->CallSeekTask();
+ EXPECT_EQ(kFarReadPosition, loader()->Tell());
+
+ // Seek
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ ReadAt(kDataSize * 2);
+ data_source_->CallSeekTask();
+ EXPECT_EQ(kDataSize * 3, loader()->Tell());
+
+ Stop();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.cc b/chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.cc
new file mode 100644
index 00000000000..75bf62a03e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.cc
@@ -0,0 +1,252 @@
+// 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/media/multi_buffer_reader.h"
+
+#include <stddef.h>
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "net/base/net_errors.h"
+
+namespace blink {
+
+MultiBufferReader::MultiBufferReader(
+ MultiBuffer* multibuffer,
+ int64_t start,
+ int64_t end,
+ base::RepeatingCallback<void(int64_t, int64_t)> progress_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : multibuffer_(multibuffer),
+ // If end is -1, we use a very large (but still supported) value instead.
+ end_(end == -1LL ? (1LL << (multibuffer->block_size_shift() + 30)) : end),
+ preload_high_(0),
+ preload_low_(0),
+ max_buffer_forward_(0),
+ max_buffer_backward_(0),
+ current_buffer_size_(0),
+ pinned_range_(0, 0),
+ pos_(start),
+ preload_pos_(-1),
+ loading_(true),
+ current_wait_size_(0),
+ progress_callback_(std::move(progress_callback)),
+ task_runner_(std::move(task_runner)) {
+ DCHECK_GE(start, 0);
+ DCHECK_GE(end_, 0);
+}
+
+MultiBufferReader::~MultiBufferReader() {
+ PinRange(0, 0);
+ multibuffer_->RemoveReader(preload_pos_, this);
+ multibuffer_->IncrementMaxSize(-current_buffer_size_);
+ multibuffer_->CleanupWriters(preload_pos_);
+}
+
+void MultiBufferReader::Seek(int64_t pos) {
+ DCHECK_GE(pos, 0);
+ if (pos == pos_)
+ return;
+ PinRange(block(pos - max_buffer_backward_),
+ block_ceil(pos + max_buffer_forward_));
+
+ multibuffer_->RemoveReader(preload_pos_, this);
+ MultiBufferBlockId old_preload_pos = preload_pos_;
+ preload_pos_ = block(pos);
+ pos_ = pos;
+ UpdateInternalState();
+ multibuffer_->CleanupWriters(old_preload_pos);
+}
+
+void MultiBufferReader::SetMaxBuffer(int64_t buffer_size) {
+ // Safe, because we know this doesn't actually prune the cache right away.
+ int64_t new_buffer_size = block_ceil(buffer_size);
+ multibuffer_->IncrementMaxSize(new_buffer_size - current_buffer_size_);
+ current_buffer_size_ = new_buffer_size;
+}
+
+void MultiBufferReader::SetPinRange(int64_t backward, int64_t forward) {
+ // Safe, because we know this doesn't actually prune the cache right away.
+ max_buffer_backward_ = backward;
+ max_buffer_forward_ = forward;
+ PinRange(block(pos_ - max_buffer_backward_),
+ block_ceil(pos_ + max_buffer_forward_));
+}
+
+int64_t MultiBufferReader::AvailableAt(int64_t pos) const {
+ int64_t unavailable_byte_pos =
+ static_cast<int64_t>(multibuffer_->FindNextUnavailable(block(pos)))
+ << multibuffer_->block_size_shift();
+ return std::max<int64_t>(0, unavailable_byte_pos - pos);
+}
+
+int64_t MultiBufferReader::TryReadAt(int64_t pos, uint8_t* data, int64_t len) {
+ DCHECK_GT(len, 0);
+ std::vector<scoped_refptr<media::DataBuffer>> buffers;
+ multibuffer_->GetBlocksThreadsafe(block(pos), block_ceil(pos + len),
+ &buffers);
+ int64_t bytes_read = 0;
+ for (auto& buffer : buffers) {
+ if (buffer->end_of_stream())
+ break;
+ size_t offset = pos & ((1LL << multibuffer_->block_size_shift()) - 1);
+ if (offset > static_cast<size_t>(buffer->data_size()))
+ break;
+ size_t tocopy =
+ std::min<size_t>(len - bytes_read, buffer->data_size() - offset);
+ memcpy(data, buffer->data() + offset, tocopy);
+ data += tocopy;
+ bytes_read += tocopy;
+ if (bytes_read == len)
+ break;
+ if (block(pos + tocopy) != block(pos) + 1)
+ break;
+ pos += tocopy;
+ }
+ return bytes_read;
+}
+
+int64_t MultiBufferReader::TryRead(uint8_t* data, int64_t len) {
+ int64_t bytes_read = TryReadAt(pos_, data, len);
+ Seek(pos_ + bytes_read);
+ return bytes_read;
+}
+
+int MultiBufferReader::Wait(int64_t len, base::OnceClosure cb) {
+ DCHECK_LE(pos_ + len, end_);
+ DCHECK_NE(Available(), -1);
+ DCHECK_LE(len, max_buffer_forward_);
+ current_wait_size_ = len;
+
+ cb_.Reset();
+ UpdateInternalState();
+
+ if (Available() >= current_wait_size_) {
+ return net::OK;
+ } else {
+ cb_ = std::move(cb);
+ return net::ERR_IO_PENDING;
+ }
+}
+
+void MultiBufferReader::SetPreload(int64_t preload_high, int64_t preload_low) {
+ DCHECK_GE(preload_high, preload_low);
+ multibuffer_->RemoveReader(preload_pos_, this);
+ preload_pos_ = block(pos_);
+ preload_high_ = preload_high;
+ preload_low_ = preload_low;
+ UpdateInternalState();
+}
+
+bool MultiBufferReader::IsLoading() const {
+ return loading_;
+}
+
+void MultiBufferReader::CheckWait() {
+ if (!cb_.is_null() &&
+ (Available() >= current_wait_size_ || Available() == -1)) {
+ // We redirect the call through a weak pointer to ourselves to guarantee
+ // there are no callbacks from us after we've been destroyed.
+ current_wait_size_ = 0;
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&MultiBufferReader::Call,
+ weak_factory_.GetWeakPtr(), std::move(cb_)));
+ }
+}
+
+void MultiBufferReader::Call(base::OnceClosure cb) const {
+ std::move(cb).Run();
+}
+
+void MultiBufferReader::UpdateEnd(MultiBufferBlockId p) {
+ auto i = multibuffer_->map().find(p - 1);
+ if (i != multibuffer_->map().end() && i->second->end_of_stream()) {
+ // This is an upper limit because the last-to-one block is allowed
+ // to be smaller than the rest of the blocks.
+ int64_t size_upper_limit = static_cast<int64_t>(p)
+ << multibuffer_->block_size_shift();
+ end_ = std::min(end_, size_upper_limit);
+ }
+}
+
+void MultiBufferReader::NotifyAvailableRange(
+ const Interval<MultiBufferBlockId>& range) {
+ // Update end_ if we can.
+ if (range.end > range.begin) {
+ UpdateEnd(range.end);
+ }
+ UpdateInternalState();
+ if (!progress_callback_.is_null()) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(progress_callback_,
+ static_cast<int64_t>(range.begin)
+ << multibuffer_->block_size_shift(),
+ (static_cast<int64_t>(range.end)
+ << multibuffer_->block_size_shift()) +
+ multibuffer_->UncommittedBytesAt(range.end)));
+ }
+}
+
+void MultiBufferReader::UpdateInternalState() {
+ int64_t effective_preload = loading_ ? preload_high_ : preload_low_;
+
+ loading_ = false;
+ if (preload_pos_ == -1) {
+ preload_pos_ = block(pos_);
+ DCHECK_GE(preload_pos_, 0);
+ }
+
+ // Note that we might not have been added to the multibuffer,
+ // removing ourselves is a no-op in that case.
+ multibuffer_->RemoveReader(preload_pos_, this);
+
+ // We explicitly allow preloading to go beyond the pinned region in the cache.
+ // It only happens when we want to preload something into the disk cache.
+ // Thus it is possible to have blocks between our current reading position
+ // and preload_pos_ be unavailable. When we get a Seek() call (possibly
+ // through TryRead()) we reset the preload_pos_ to the current reading
+ // position, and preload_pos_ will become the first unavailable block after
+ // our current reading position again.
+ preload_pos_ = multibuffer_->FindNextUnavailable(preload_pos_);
+ UpdateEnd(preload_pos_);
+ DCHECK_GE(preload_pos_, 0);
+
+ MultiBuffer::BlockId max_preload = block_ceil(
+ std::min(end_, pos_ + std::max(effective_preload, current_wait_size_)));
+
+ DVLOG(3) << "UpdateInternalState"
+ << " pp = " << preload_pos_
+ << " block_ceil(end_) = " << block_ceil(end_) << " end_ = " << end_
+ << " max_preload " << max_preload;
+
+ multibuffer_->SetIsClientAudioElement(is_client_audio_element_);
+ if (preload_pos_ < block_ceil(end_)) {
+ if (preload_pos_ < max_preload) {
+ loading_ = true;
+ multibuffer_->AddReader(preload_pos_, this);
+ } else if (multibuffer_->Contains(preload_pos_ - 1)) {
+ --preload_pos_;
+ multibuffer_->AddReader(preload_pos_, this);
+ }
+ }
+ CheckWait();
+}
+
+void MultiBufferReader::PinRange(MultiBuffer::BlockId begin,
+ MultiBuffer::BlockId end) {
+ // Use a rangemap to compute the diff in pinning.
+ IntervalMap<MultiBuffer::BlockId, int32_t> tmp;
+ tmp.IncrementInterval(pinned_range_.begin, pinned_range_.end, -1);
+ tmp.IncrementInterval(begin, end, 1);
+ multibuffer_->PinRanges(tmp);
+ pinned_range_.begin = begin;
+ pinned_range_.end = end;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.h b/chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.h
new file mode 100644
index 00000000000..aacc162d579
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/multi_buffer_reader.h
@@ -0,0 +1,196 @@
+// 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_MEDIA_MULTI_BUFFER_READER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_MULTI_BUFFER_READER_H_
+
+#include <stdint.h>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/platform/media/multi_buffer.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+
+// Wrapper for MultiBuffer that offers a simple byte-reading
+// interface with prefetch.
+class PLATFORM_EXPORT MultiBufferReader : public MultiBuffer::Reader {
+ public:
+ // Note that |progress_callback| is guaranteed to be called if
+ // a redirect happens and the url_data is updated. Otherwise
+ // origin checks will become insecure.
+ // Users probably want to call SetMaxBuffer & SetPreload after
+ // creating the a MultiBufferReader.
+ // The progress callback will be called when the "available range"
+ // changes. (The number of bytes available for reading before and
+ // after the current position.) The arguments for the progress
+ // callback is the first byte available (from beginning of file)
+ // and the last byte available + 1. Note that there may be other
+ // regions of available data in the cache as well.
+ // If |end| is not known, use -1.
+ MultiBufferReader(
+ MultiBuffer* multibuffer,
+ int64_t start,
+ int64_t end,
+ base::RepeatingCallback<void(int64_t, int64_t)> progress_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ ~MultiBufferReader() override;
+
+ // Returns number of bytes available for reading. At position |pos|
+ // When the rest of the file is available, the number returned will
+ // be greater than the number or readable bytes. If an error occurs,
+ // -1 is returned.
+ int64_t AvailableAt(int64_t pos) const;
+
+ // Returns number of bytes available for reading at the current position.
+ int64_t Available() const { return AvailableAt(pos_); }
+
+ // Seek to a different position.
+ // If there is a pending Wait(), it will be cancelled.
+ void Seek(int64_t pos);
+
+ // Returns the current position.
+ int64_t Tell() const { return pos_; }
+
+ // Tries to read |len| bytes from position |pos|.
+ // Returns number of bytes read.
+ // Safe to call from any thread.
+ int64_t TryReadAt(int64_t pos, uint8_t* data, int64_t len);
+
+ // Tries to read |len| bytes and update current position.
+ // Returns number of bytes read.
+ int64_t TryRead(uint8_t* data, int64_t len);
+
+ // Wait until |len| bytes are available for reading.
+ // Returns net::OK if |len| bytes are already available, otherwise it will
+ // return net::ERR_IO_PENDING and call |cb| at some point later.
+ // |len| must be smaller or equal to max_buffer_forward.
+ int Wait(int64_t len, base::OnceClosure cb);
+
+ // Set how much data we try to preload into the cache ahead of our current
+ // location. Normally, we preload until we have preload_high bytes, then
+ // stop until we fall below preload_low bytes. Note that preload can be
+ // set higher than max_buffer_forward, but the result is usually that
+ // some blocks will be freed between the current position and the preload
+ // position.
+ void SetPreload(int64_t preload_high, int64_t preload_low);
+
+ // Change how much data we pin to the cache.
+ // The range [current_position - backward ... current_position + forward)
+ // will be locked in the cache. Calling Wait() or TryRead() with values
+ // larger than |forward| is not supported.
+ void SetPinRange(int64_t backward, int64_t forward);
+
+ // Set how much memory usage we target. This memory is added to the global
+ // LRU and shared between all multibuffers. We may end up using more memory
+ // if no memory can be freed due to pinning.
+ void SetMaxBuffer(int64_t bytes);
+
+ // Returns true if we are currently loading data.
+ bool IsLoading() const;
+
+ // Reader implementation.
+ void NotifyAvailableRange(const Interval<MultiBufferBlockId>& range) override;
+
+ // Getters
+ int64_t preload_high() const { return preload_high_; }
+ int64_t preload_low() const { return preload_low_; }
+
+ // Setters
+ void SetIsClientAudioElement(bool is_client_audio_element) {
+ is_client_audio_element_ = is_client_audio_element;
+ }
+
+ private:
+ friend class MultiBufferDataSourceTest;
+
+ // Returns the block for a particular byte position.
+ MultiBufferBlockId block(int64_t byte_pos) const {
+ return byte_pos >> multibuffer_->block_size_shift();
+ }
+
+ // Returns the block for a particular byte position, rounding up.
+ MultiBufferBlockId block_ceil(int64_t byte_pos) const {
+ return block(byte_pos + (1LL << multibuffer_->block_size_shift()) - 1);
+ }
+
+ // Unpin previous range, then pin the new range.
+ void PinRange(MultiBuffer::BlockId begin, MultiBuffer::BlockId end);
+
+ // Check if wait operation can complete now.
+ void CheckWait();
+
+ // Recalculate preload_pos_ and update our entry in the multibuffer
+ // reader index. Also call CheckWait(). This function is basically
+ // called anything changes, like when we get more data or seek to
+ // a new position.
+ void UpdateInternalState();
+
+ // Update end_ if p-1 contains an end-of-stream block.
+ void UpdateEnd(MultiBufferBlockId p);
+
+ // Indirection function used to call callbacks. When we post a callback
+ // we indirect it through a weak_ptr and this function to make sure we
+ // don't call any callbacks after this object has been destroyed.
+ void Call(base::OnceClosure cb) const;
+
+ // The multibuffer we're wrapping, not owned.
+ MultiBuffer* multibuffer_;
+
+ // We're not interested in reading past this position.
+ int64_t end_;
+
+ // Defer reading once we have this much data.
+ int64_t preload_high_;
+ // Stop deferring once we have this much data.
+ int64_t preload_low_;
+
+ // Pin this much data in the cache from the current position.
+ int64_t max_buffer_forward_;
+ int64_t max_buffer_backward_;
+
+ // The amount of buffer we've added to the global LRU.
+ int64_t current_buffer_size_;
+
+ // Currently pinned range.
+ Interval<MultiBuffer::BlockId> pinned_range_;
+
+ // Current position in bytes.
+ int64_t pos_;
+
+ // Is the client an audio element?
+ bool is_client_audio_element_ = false;
+
+ // [block(pos_)..preload_pos_) are known to be in the cache.
+ // preload_pos_ is only allowed to point to a filled
+ // cache position if it is equal to end_ or pos_+preload_.
+ // This is a pointer to a slot in the cache, so the unit is
+ // blocks.
+ MultiBufferBlockId preload_pos_;
+
+ // True if we've requested data from the cache by calling WaitFor().
+ bool loading_;
+
+ // When Available() > current_wait_size_ we call cb_.
+ int64_t current_wait_size_;
+ base::OnceClosure cb_;
+
+ // Progress callback.
+ base::RepeatingCallback<void(int64_t, int64_t)> progress_callback_;
+
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::WeakPtrFactory<MultiBufferReader> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_MULTI_BUFFER_READER_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc b/chromium/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc
new file mode 100644
index 00000000000..24c9a337627
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc
@@ -0,0 +1,609 @@
+// 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/platform/media/multi_buffer.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/containers/circular_deque.h"
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "media/base/fake_single_thread_task_runner.h"
+#include "media/base/test_random.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/media/multi_buffer_reader.h"
+
+namespace blink {
+namespace {
+class FakeMultiBufferDataProvider;
+
+const int kBlockSizeShift = 8;
+const size_t kBlockSize = 1UL << kBlockSizeShift;
+
+std::vector<FakeMultiBufferDataProvider*> writers;
+
+class FakeMultiBufferDataProvider : public MultiBuffer::DataProvider {
+ public:
+ FakeMultiBufferDataProvider(MultiBufferBlockId pos,
+ size_t file_size,
+ int max_blocks_after_defer,
+ bool must_read_whole_file,
+ MultiBuffer* multibuffer,
+ media::TestRandom* rnd)
+ : pos_(pos),
+ blocks_until_deferred_(1 << 30),
+ max_blocks_after_defer_(max_blocks_after_defer),
+ file_size_(file_size),
+ must_read_whole_file_(must_read_whole_file),
+ multibuffer_(multibuffer),
+ rnd_(rnd) {
+ writers.push_back(this);
+ }
+
+ ~FakeMultiBufferDataProvider() override {
+ if (must_read_whole_file_) {
+ CHECK_GE(pos_ * kBlockSize, file_size_);
+ }
+ for (size_t i = 0; i < writers.size(); i++) {
+ if (writers[i] == this) {
+ writers[i] = writers.back();
+ writers.pop_back();
+ return;
+ }
+ }
+ LOG(FATAL) << "Couldn't find myself in writers!";
+ }
+
+ MultiBufferBlockId Tell() const override { return pos_; }
+
+ bool Available() const override { return !fifo_.empty(); }
+ int64_t AvailableBytes() const override { return 0; }
+
+ scoped_refptr<media::DataBuffer> Read() override {
+ DCHECK(Available());
+ scoped_refptr<media::DataBuffer> ret = fifo_.front();
+ fifo_.pop_front();
+ ++pos_;
+ return ret;
+ }
+
+ void SetDeferred(bool deferred) override {
+ if (deferred) {
+ if (max_blocks_after_defer_ > 0) {
+ blocks_until_deferred_ = rnd_->Rand() % max_blocks_after_defer_;
+ } else if (max_blocks_after_defer_ < 0) {
+ blocks_until_deferred_ = -max_blocks_after_defer_;
+ } else {
+ blocks_until_deferred_ = 0;
+ }
+ } else {
+ blocks_until_deferred_ = 1 << 30;
+ }
+ }
+
+ bool Advance() {
+ if (blocks_until_deferred_ == 0)
+ return false;
+ --blocks_until_deferred_;
+
+ bool ret = true;
+ auto block = base::MakeRefCounted<media::DataBuffer>(kBlockSize);
+ size_t x = 0;
+ size_t byte_pos = (fifo_.size() + pos_) * kBlockSize;
+ for (x = 0; x < kBlockSize; x++, byte_pos++) {
+ if (byte_pos >= file_size_)
+ break;
+ block->writable_data()[x] =
+ static_cast<uint8_t>((byte_pos * 15485863) >> 16);
+ }
+ block->set_data_size(static_cast<int>(x));
+ fifo_.push_back(block);
+ if (byte_pos == file_size_) {
+ fifo_.push_back(media::DataBuffer::CreateEOSBuffer());
+ ret = false;
+ }
+ multibuffer_->OnDataProviderEvent(this);
+ return ret;
+ }
+
+ private:
+ base::circular_deque<scoped_refptr<media::DataBuffer>> fifo_;
+ MultiBufferBlockId pos_;
+ int32_t blocks_until_deferred_;
+ int32_t max_blocks_after_defer_;
+ size_t file_size_;
+ bool must_read_whole_file_;
+ MultiBuffer* multibuffer_;
+ media::TestRandom* rnd_;
+};
+
+} // namespace
+
+class TestMultiBuffer : public MultiBuffer {
+ public:
+ explicit TestMultiBuffer(int32_t shift,
+ const scoped_refptr<MultiBuffer::GlobalLRU>& lru,
+ media::TestRandom* rnd)
+ : MultiBuffer(shift, lru),
+ range_supported_(false),
+ create_ok_(true),
+ max_writers_(10000),
+ file_size_(1 << 30),
+ max_blocks_after_defer_(0),
+ must_read_whole_file_(false),
+ writers_created_(0),
+ rnd_(rnd) {}
+
+ void SetMaxWriters(size_t max_writers) { max_writers_ = max_writers; }
+
+ void CheckPresentState() {
+ IntervalMap<MultiBufferBlockId, int32_t> tmp;
+ for (auto i = data_.begin(); i != data_.end(); ++i) {
+ CHECK(i->second); // Null poineters are not allowed in data_
+ CHECK_NE(!!pinned_[i->first], lru_->Contains(this, i->first))
+ << " i->first = " << i->first;
+ tmp.IncrementInterval(i->first, i->first + 1, 1);
+ }
+ IntervalMap<MultiBufferBlockId, int32_t>::const_iterator tmp_iterator =
+ tmp.begin();
+ IntervalMap<MultiBufferBlockId, int32_t>::const_iterator present_iterator =
+ present_.begin();
+ while (tmp_iterator != tmp.end() && present_iterator != present_.end()) {
+ EXPECT_EQ(tmp_iterator.interval_begin(),
+ present_iterator.interval_begin());
+ EXPECT_EQ(tmp_iterator.interval_end(), present_iterator.interval_end());
+ EXPECT_EQ(tmp_iterator.value(), present_iterator.value());
+ ++tmp_iterator;
+ ++present_iterator;
+ }
+ EXPECT_TRUE(tmp_iterator == tmp.end());
+ EXPECT_TRUE(present_iterator == present_.end());
+ }
+
+ void CheckLRUState() {
+ for (auto i = data_.begin(); i != data_.end(); ++i) {
+ CHECK(i->second); // Null poineters are not allowed in data_
+ CHECK_NE(!!pinned_[i->first], lru_->Contains(this, i->first))
+ << " i->first = " << i->first;
+ CHECK_EQ(1, present_[i->first]) << " i->first = " << i->first;
+ }
+ }
+
+ void SetFileSize(size_t file_size) { file_size_ = file_size; }
+
+ void SetMaxBlocksAfterDefer(int32_t max_blocks_after_defer) {
+ max_blocks_after_defer_ = max_blocks_after_defer;
+ }
+
+ void SetMustReadWholeFile(bool must_read_whole_file) {
+ must_read_whole_file_ = must_read_whole_file;
+ }
+
+ int32_t writers_created() const { return writers_created_; }
+
+ void SetRangeSupported(bool supported) { range_supported_ = supported; }
+
+ protected:
+ std::unique_ptr<DataProvider> CreateWriter(const MultiBufferBlockId& pos,
+ bool) override {
+ DCHECK(create_ok_);
+ writers_created_++;
+ CHECK_LT(writers.size(), max_writers_);
+ return std::unique_ptr<DataProvider>(new FakeMultiBufferDataProvider(
+ pos, file_size_, max_blocks_after_defer_, must_read_whole_file_, this,
+ rnd_));
+ }
+ void Prune(size_t max_to_free) override {
+ // Prune should not cause additional writers to be spawned.
+ create_ok_ = false;
+ MultiBuffer::Prune(max_to_free);
+ create_ok_ = true;
+ }
+
+ bool RangeSupported() const override { return range_supported_; }
+
+ private:
+ bool range_supported_;
+ bool create_ok_;
+ size_t max_writers_;
+ size_t file_size_;
+ int32_t max_blocks_after_defer_;
+ bool must_read_whole_file_;
+ int32_t writers_created_;
+ media::TestRandom* rnd_;
+};
+
+class MultiBufferTest : public testing::Test {
+ public:
+ MultiBufferTest()
+ : rnd_(42),
+ task_runner_(new media::FakeSingleThreadTaskRunner(&clock_)),
+ lru_(new MultiBuffer::GlobalLRU(task_runner_)),
+ multibuffer_(kBlockSizeShift, lru_, &rnd_) {}
+
+ void TearDown() override {
+ // Make sure we have nothing left to prune.
+ lru_->Prune(1000000);
+ // Run the outstanding callback to make sure everything is freed.
+ task_runner_->Sleep(base::TimeDelta::FromSeconds(30));
+ }
+
+ void Advance() {
+ CHECK(writers.size());
+ writers[rnd_.Rand() % writers.size()]->Advance();
+ }
+
+ bool AdvanceAll() {
+ bool advanced = false;
+ for (size_t i = 0; i < writers.size(); i++) {
+ advanced |= writers[i]->Advance();
+ }
+ multibuffer_.CheckLRUState();
+ return advanced;
+ }
+
+ protected:
+ media::TestRandom rnd_;
+ base::SimpleTestTickClock clock_;
+ scoped_refptr<media::FakeSingleThreadTaskRunner> task_runner_;
+ scoped_refptr<MultiBuffer::GlobalLRU> lru_;
+ TestMultiBuffer multibuffer_;
+};
+
+TEST_F(MultiBufferTest, ReadAll) {
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ multibuffer_.SetMustReadWholeFile(true);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPinRange(2000, 5000);
+ reader.SetPreload(1000, 1000);
+ while (pos < end) {
+ unsigned char buffer[27];
+ buffer[17] = 17;
+ size_t to_read = std::min<size_t>(end - pos, 17);
+ int64_t bytes_read = reader.TryRead(buffer, to_read);
+ if (bytes_read) {
+ EXPECT_EQ(buffer[17], 17);
+ for (int64_t i = 0; i < bytes_read; i++) {
+ uint8_t expected = static_cast<uint8_t>((pos * 15485863) >> 16);
+ EXPECT_EQ(expected, buffer[i]) << " pos = " << pos;
+ pos++;
+ }
+ } else {
+ Advance();
+ }
+ }
+}
+
+TEST_F(MultiBufferTest, ReadAllAdvanceFirst) {
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ multibuffer_.SetMustReadWholeFile(true);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPinRange(2000, 5000);
+ reader.SetPreload(1000, 1000);
+ while (pos < end) {
+ unsigned char buffer[27];
+ buffer[17] = 17;
+ size_t to_read = std::min<size_t>(end - pos, 17);
+ while (AdvanceAll()) {
+ }
+ int64_t bytes = reader.TryRead(buffer, to_read);
+ EXPECT_GT(bytes, 0);
+ EXPECT_EQ(buffer[17], 17);
+ for (int64_t i = 0; i < bytes; i++) {
+ uint8_t expected = static_cast<uint8_t>((pos * 15485863) >> 16);
+ EXPECT_EQ(expected, buffer[i]) << " pos = " << pos;
+ pos++;
+ }
+ }
+}
+
+// Checks that if the data provider provides too much data after we told it
+// to defer, we kill it.
+TEST_F(MultiBufferTest, ReadAllAdvanceFirst_NeverDefer) {
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ multibuffer_.SetMaxBlocksAfterDefer(-10000);
+ multibuffer_.SetRangeSupported(true);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPinRange(2000, 5000);
+ reader.SetPreload(1000, 1000);
+ while (pos < end) {
+ unsigned char buffer[27];
+ buffer[17] = 17;
+ size_t to_read = std::min<size_t>(end - pos, 17);
+ while (AdvanceAll()) {
+ }
+ int64_t bytes = reader.TryRead(buffer, to_read);
+ EXPECT_GT(bytes, 0);
+ EXPECT_EQ(buffer[17], 17);
+ for (int64_t i = 0; i < bytes; i++) {
+ uint8_t expected = static_cast<uint8_t>((pos * 15485863) >> 16);
+ EXPECT_EQ(expected, buffer[i]) << " pos = " << pos;
+ pos++;
+ }
+ }
+ EXPECT_GT(multibuffer_.writers_created(), 1);
+}
+
+// Same as ReadAllAdvanceFirst_NeverDefer, but the url doesn't support
+// ranges, so we don't destroy it no matter how much data it provides.
+TEST_F(MultiBufferTest, ReadAllAdvanceFirst_NeverDefer2) {
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ multibuffer_.SetMustReadWholeFile(true);
+ multibuffer_.SetMaxBlocksAfterDefer(-10000);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPinRange(2000, 5000);
+ reader.SetPreload(1000, 1000);
+ while (pos < end) {
+ unsigned char buffer[27];
+ buffer[17] = 17;
+ size_t to_read = std::min<size_t>(end - pos, 17);
+ while (AdvanceAll()) {
+ }
+ int64_t bytes = reader.TryRead(buffer, to_read);
+ EXPECT_GT(bytes, 0);
+ EXPECT_EQ(buffer[17], 17);
+ for (int64_t i = 0; i < bytes; i++) {
+ uint8_t expected = static_cast<uint8_t>((pos * 15485863) >> 16);
+ EXPECT_EQ(expected, buffer[i]) << " pos = " << pos;
+ pos++;
+ }
+ }
+}
+
+TEST_F(MultiBufferTest, LRUTest) {
+ int64_t max_size = 17;
+ int64_t current_size = 0;
+ lru_->IncrementMaxSize(max_size);
+
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPreload(10000, 10000);
+ // Note, no pinning, all data should end up in LRU.
+ EXPECT_EQ(current_size, lru_->Size());
+ current_size += max_size;
+ while (AdvanceAll()) {
+ }
+ EXPECT_EQ(current_size, lru_->Size());
+ lru_->IncrementMaxSize(-max_size);
+ lru_->Prune(3);
+ current_size -= 3;
+ EXPECT_EQ(current_size, lru_->Size());
+ lru_->Prune(3);
+ current_size -= 3;
+ EXPECT_EQ(current_size, lru_->Size());
+ lru_->Prune(1000);
+ EXPECT_EQ(0, lru_->Size());
+}
+
+TEST_F(MultiBufferTest, LRUTest2) {
+ int64_t max_size = 17;
+ int64_t current_size = 0;
+ lru_->IncrementMaxSize(max_size);
+
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPreload(10000, 10000);
+ // Note, no pinning, all data should end up in LRU.
+ EXPECT_EQ(current_size, lru_->Size());
+ current_size += max_size;
+ while (AdvanceAll()) {
+ }
+ EXPECT_EQ(current_size, lru_->Size());
+ // Pruning shouldn't do anything here, because LRU is small enough already.
+ lru_->Prune(3);
+ EXPECT_EQ(current_size, lru_->Size());
+ // However TryFree should still work
+ lru_->TryFree(3);
+ current_size -= 3;
+ EXPECT_EQ(current_size, lru_->Size());
+ lru_->TryFreeAll();
+ EXPECT_EQ(0, lru_->Size());
+ lru_->IncrementMaxSize(-max_size);
+}
+
+TEST_F(MultiBufferTest, LRUTestExpirationTest) {
+ int64_t max_size = 17;
+ int64_t current_size = 0;
+ lru_->IncrementMaxSize(max_size);
+
+ multibuffer_.SetMaxWriters(1);
+ size_t pos = 0;
+ size_t end = 10000;
+ multibuffer_.SetFileSize(10000);
+ MultiBufferReader reader(&multibuffer_, pos, end, base::NullCallback(),
+ task_runner_);
+ reader.SetPreload(10000, 10000);
+ // Note, no pinning, all data should end up in LRU.
+ EXPECT_EQ(current_size, lru_->Size());
+ current_size += max_size;
+ while (AdvanceAll()) {
+ }
+ EXPECT_EQ(current_size, lru_->Size());
+ EXPECT_FALSE(lru_->Pruneable());
+
+ // Make 3 packets pruneable.
+ lru_->IncrementMaxSize(-3);
+ max_size -= 3;
+
+ // There should be no change after 29 seconds.
+ task_runner_->Sleep(base::TimeDelta::FromSeconds(29));
+ EXPECT_EQ(current_size, lru_->Size());
+ EXPECT_TRUE(lru_->Pruneable());
+
+ // After 30 seconds, pruning should have happened.
+ task_runner_->Sleep(base::TimeDelta::FromSeconds(30));
+ current_size -= 3;
+ EXPECT_EQ(current_size, lru_->Size());
+ EXPECT_FALSE(lru_->Pruneable());
+
+ // Make the rest of the packets pruneable.
+ lru_->IncrementMaxSize(-max_size);
+
+ // After another 30 seconds, everything should be pruned.
+ task_runner_->Sleep(base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, lru_->Size());
+ EXPECT_FALSE(lru_->Pruneable());
+}
+
+class ReadHelper {
+ public:
+ ReadHelper(size_t end,
+ size_t max_read_size,
+ MultiBuffer* multibuffer,
+ media::TestRandom* rnd,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : pos_(0),
+ end_(end),
+ max_read_size_(max_read_size),
+ read_size_(0),
+ rnd_(rnd),
+ reader_(multibuffer,
+ pos_,
+ end_,
+ base::NullCallback(),
+ std::move(task_runner)) {
+ reader_.SetPinRange(2000, 5000);
+ reader_.SetPreload(1000, 1000);
+ }
+
+ bool Read() {
+ if (read_size_ == 0)
+ return true;
+ unsigned char buffer[4096];
+ CHECK_LE(read_size_, static_cast<int64_t>(sizeof(buffer)));
+ CHECK_EQ(pos_, reader_.Tell());
+ int64_t bytes_read = reader_.TryRead(buffer, read_size_);
+ if (bytes_read) {
+ for (int64_t i = 0; i < bytes_read; i++) {
+ unsigned char expected = (pos_ * 15485863) >> 16;
+ EXPECT_EQ(expected, buffer[i]) << " pos = " << pos_;
+ pos_++;
+ }
+ CHECK_EQ(pos_, reader_.Tell());
+ return true;
+ }
+ return false;
+ }
+
+ void StartRead() {
+ CHECK_EQ(pos_, reader_.Tell());
+ read_size_ = std::min(1 + rnd_->Rand() % (max_read_size_ - 1), end_ - pos_);
+ if (!Read()) {
+ reader_.Wait(read_size_,
+ base::BindOnce(&ReadHelper::WaitCB, base::Unretained(this)));
+ }
+ }
+
+ void WaitCB() { CHECK(Read()); }
+
+ void Seek() {
+ pos_ = rnd_->Rand() % end_;
+ reader_.Seek(pos_);
+ CHECK_EQ(pos_, reader_.Tell());
+ }
+
+ private:
+ int64_t pos_;
+ int64_t end_;
+ int64_t max_read_size_;
+ int64_t read_size_;
+ media::TestRandom* rnd_;
+ MultiBufferReader reader_;
+};
+
+TEST_F(MultiBufferTest, RandomTest) {
+ size_t file_size = 1000000;
+ multibuffer_.SetFileSize(file_size);
+ multibuffer_.SetMaxBlocksAfterDefer(10);
+ std::vector<ReadHelper*> read_helpers;
+ for (size_t i = 0; i < 20; i++) {
+ read_helpers.push_back(
+ new ReadHelper(file_size, 1000, &multibuffer_, &rnd_, task_runner_));
+ }
+ for (int i = 0; i < 100; i++) {
+ for (int j = 0; j < 100; j++) {
+ if (rnd_.Rand() & 1) {
+ if (!writers.empty())
+ Advance();
+ } else {
+ size_t j = rnd_.Rand() % read_helpers.size();
+ if (rnd_.Rand() % 100 < 3)
+ read_helpers[j]->Seek();
+ read_helpers[j]->StartRead();
+ }
+ }
+ multibuffer_.CheckLRUState();
+ }
+ multibuffer_.CheckPresentState();
+ while (!read_helpers.empty()) {
+ delete read_helpers.back();
+ read_helpers.pop_back();
+ }
+}
+
+TEST_F(MultiBufferTest, RandomTest_RangeSupported) {
+ size_t file_size = 1000000;
+ multibuffer_.SetFileSize(file_size);
+ multibuffer_.SetMaxBlocksAfterDefer(10);
+ std::vector<ReadHelper*> read_helpers;
+ multibuffer_.SetRangeSupported(true);
+ for (size_t i = 0; i < 20; i++) {
+ read_helpers.push_back(
+ new ReadHelper(file_size, 1000, &multibuffer_, &rnd_, task_runner_));
+ }
+ for (int i = 0; i < 100; i++) {
+ for (int j = 0; j < 100; j++) {
+ if (rnd_.Rand() & 1) {
+ if (!writers.empty())
+ Advance();
+ } else {
+ size_t j = rnd_.Rand() % read_helpers.size();
+ if (rnd_.Rand() % 100 < 3)
+ read_helpers[j]->Seek();
+ read_helpers[j]->StartRead();
+ }
+ }
+ multibuffer_.CheckLRUState();
+ }
+ multibuffer_.CheckPresentState();
+ while (!read_helpers.empty()) {
+ delete read_helpers.back();
+ read_helpers.pop_back();
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.cc b/chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.cc
new file mode 100644
index 00000000000..1c09abb75aa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.cc
@@ -0,0 +1,108 @@
+// 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/media/new_session_cdm_result_promise.h"
+
+#include "base/containers/contains.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/media/cdm_result_promise_helper.h"
+
+namespace blink {
+namespace {
+
+const char kTimeUMAPrefix[] = "TimeTo.";
+
+CdmResultForUMA ConvertStatusToUMAResult(SessionInitStatus status) {
+ switch (status) {
+ case SessionInitStatus::UNKNOWN_STATUS:
+ break;
+ case SessionInitStatus::NEW_SESSION:
+ return SUCCESS;
+ case SessionInitStatus::SESSION_NOT_FOUND:
+ return SESSION_NOT_FOUND;
+ case SessionInitStatus::SESSION_ALREADY_EXISTS:
+ return SESSION_ALREADY_EXISTS;
+ }
+ NOTREACHED();
+ return INVALID_STATE_ERROR;
+}
+
+} // namespace
+
+static WebContentDecryptionModuleResult::SessionStatus ConvertStatus(
+ SessionInitStatus status) {
+ switch (status) {
+ case SessionInitStatus::UNKNOWN_STATUS:
+ break;
+ case SessionInitStatus::NEW_SESSION:
+ return WebContentDecryptionModuleResult::kNewSession;
+ case SessionInitStatus::SESSION_NOT_FOUND:
+ return WebContentDecryptionModuleResult::kSessionNotFound;
+ case SessionInitStatus::SESSION_ALREADY_EXISTS:
+ return WebContentDecryptionModuleResult::kSessionAlreadyExists;
+ }
+ NOTREACHED();
+ return WebContentDecryptionModuleResult::kSessionNotFound;
+}
+
+NewSessionCdmResultPromise::NewSessionCdmResultPromise(
+ const WebContentDecryptionModuleResult& result,
+ const std::string& key_system_uma_prefix,
+ const std::string& uma_name,
+ SessionInitializedCB new_session_created_cb,
+ const std::vector<SessionInitStatus>& expected_statuses)
+ : web_cdm_result_(result),
+ key_system_uma_prefix_(key_system_uma_prefix),
+ uma_name_(uma_name),
+ new_session_created_cb_(std::move(new_session_created_cb)),
+ expected_statuses_(expected_statuses),
+ creation_time_(base::TimeTicks::Now()) {}
+
+NewSessionCdmResultPromise::~NewSessionCdmResultPromise() {
+ if (!IsPromiseSettled())
+ RejectPromiseOnDestruction();
+}
+
+void NewSessionCdmResultPromise::resolve(const std::string& session_id) {
+ DVLOG(1) << __func__ << ": session_id = " << session_id;
+
+ // |new_session_created_cb_| uses a WeakPtr<> and may not do anything
+ // if the session object has been destroyed.
+ SessionInitStatus status = SessionInitStatus::UNKNOWN_STATUS;
+ std::move(new_session_created_cb_).Run(session_id, &status);
+
+ if (!base::Contains(expected_statuses_, status)) {
+ reject(Exception::INVALID_STATE_ERROR, 0,
+ "Cannot finish session initialization");
+ return;
+ }
+
+ MarkPromiseSettled();
+ ReportCdmResultUMA(key_system_uma_prefix_ + uma_name_, 0,
+ ConvertStatusToUMAResult(status));
+
+ // Only report time for promise resolution (not rejection).
+ base::UmaHistogramTimes(key_system_uma_prefix_ + kTimeUMAPrefix + uma_name_,
+ base::TimeTicks::Now() - creation_time_);
+
+ web_cdm_result_.CompleteWithSession(ConvertStatus(status));
+}
+
+void NewSessionCdmResultPromise::reject(CdmPromise::Exception exception_code,
+ uint32_t system_code,
+ const std::string& error_message) {
+ DVLOG(1) << __func__ << ": system_code = " << system_code
+ << ", error_message = " << error_message;
+
+ MarkPromiseSettled();
+ ReportCdmResultUMA(key_system_uma_prefix_ + uma_name_, system_code,
+ ConvertCdmExceptionToResultForUMA(exception_code));
+ web_cdm_result_.CompleteWithError(ConvertCdmException(exception_code),
+ system_code,
+ WebString::FromUTF8(error_message));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.h b/chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.h
new file mode 100644
index 00000000000..fe2a29730ce
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/new_session_cdm_result_promise.h
@@ -0,0 +1,84 @@
+// 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_MEDIA_NEW_SESSION_CDM_RESULT_PROMISE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_NEW_SESSION_CDM_RESULT_PROMISE_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "media/base/cdm_promise.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_result.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+enum class SessionInitStatus {
+ // Unable to determine the status.
+ UNKNOWN_STATUS,
+
+ // New session has been initialized.
+ NEW_SESSION,
+
+ // CDM could not find the requested session.
+ SESSION_NOT_FOUND,
+
+ // CDM already has a non-closed session that matches the provided
+ // parameters.
+ SESSION_ALREADY_EXISTS
+};
+
+using SessionInitializedCB =
+ base::OnceCallback<void(const std::string& session_id,
+ SessionInitStatus* status)>;
+
+// Special class for resolving a new session promise. Resolving a new session
+// promise returns the session ID (as a string), but the blink promise needs
+// to get passed a SessionStatus. This class converts the session id to a
+// SessionStatus by calling |new_session_created_cb|. The value returned by
+// |new_session_created_cb| must be in |expected_statuses| for the promise to
+// be resolved. If it's not in the list, the promise will be rejected.
+class PLATFORM_EXPORT NewSessionCdmResultPromise
+ : public media::CdmPromiseTemplate<std::string> {
+ public:
+ NewSessionCdmResultPromise(
+ const WebContentDecryptionModuleResult& result,
+ const std::string& key_system_uma_prefix,
+ const std::string& uma_name,
+ SessionInitializedCB new_session_created_cb,
+ const std::vector<SessionInitStatus>& expected_statuses);
+ NewSessionCdmResultPromise(const NewSessionCdmResultPromise&) = delete;
+ NewSessionCdmResultPromise& operator=(const NewSessionCdmResultPromise&) =
+ delete;
+ ~NewSessionCdmResultPromise() override;
+
+ // media::CdmPromiseTemplate<T> implementation.
+ void resolve(const std::string& session_id) override;
+ void reject(CdmPromise::Exception exception_code,
+ uint32_t system_code,
+ const std::string& error_message) override;
+
+ private:
+ WebContentDecryptionModuleResult web_cdm_result_;
+
+ // UMA prefix and name to report result and time to.
+ std::string key_system_uma_prefix_;
+ std::string uma_name_;
+
+ // Called on resolve() to convert the session ID into a SessionInitStatus to
+ // be reported to blink. Returned status must be in |expected_statuses_| or
+ // else the promise will be rejected.
+ SessionInitializedCB new_session_created_cb_;
+ std::vector<SessionInitStatus> expected_statuses_;
+
+ // Time when |this| is created.
+ base::TimeTicks creation_time_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_NEW_SESSION_CDM_RESULT_PROMISE_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/power_status_helper.cc b/chromium/third_party/blink/renderer/platform/media/power_status_helper.cc
new file mode 100644
index 00000000000..4aa5009b427
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/power_status_helper.cc
@@ -0,0 +1,310 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/power_status_helper.h"
+
+#include <utility>
+
+#include "base/check.h"
+#include "base/check_op.h"
+#include "base/metrics/histogram_macros.h"
+#include "media/base/pipeline_metadata.h"
+#include "services/device/public/mojom/battery_status.mojom.h"
+
+namespace blink {
+namespace {
+
+using ::device::mojom::BatteryStatusPtr;
+
+static constexpr const char* kBatteryDeltaHistogram =
+ "Media.PlaybackPower.BatteryDelta";
+static constexpr const char* kElapsedTimeHistogram =
+ "Media.PlaybackPower.ElapsedTime";
+
+// Minimum enum value that we'll generate, inclusive.
+static constexpr int kMinEnumValue = 0;
+
+// Maximum enum value that we'll generate, inclusive.
+static constexpr int kMaxEnumValue =
+ PowerStatusHelper::Bits::kCodecBitsH264 |
+ PowerStatusHelper::Bits::kCodecBitsVP9Profile0 |
+ PowerStatusHelper::Bits::kCodecBitsVP9Profile2 |
+
+ PowerStatusHelper::Bits::kResolution360p |
+ PowerStatusHelper::Bits::kResolution720p |
+ PowerStatusHelper::Bits::kResolution1080p |
+
+ PowerStatusHelper::Bits::kFrameRate30 |
+ PowerStatusHelper::Bits::kFrameRate60 |
+
+ PowerStatusHelper::Bits::kFullScreenNo |
+ PowerStatusHelper::Bits::kFullScreenYes;
+
+// UMA buckets are always [uma_min, uma_max). The first bucket is an implicit
+// underflow bucket [0, uma_min), and the last is the overflow bucket
+// [uma_max, infinity). The underflow bucket isn't counted, but the overflow
+// bucket is.
+
+// Minimum bucket number. Since we always get an underflow bucket, we choose
+// the minimum bucket to be one higher than the minimum enum value. That way.
+// the minimum enum goes to the underflow bucket.
+// //tools/metrics/histograms/README.md#count-histograms_choosing-min-and-max
+// for details.
+static constexpr int kMinUmaValue = kMinEnumValue + 1;
+
+// We want to avoid using the overflow bucket. See
+// //tools/metrics/histograms/README.md#count-histograms_choosing-min-and-max
+// and UMA_HISTOGRAM_EXACT_LINEAR for details.
+
+// Max value as reported to UMA, which is the lower bound of the overflow
+// bucket. Add one, since we want the overflow bucket to be unused.
+static constexpr int kMaxUmaValue = kMaxEnumValue + 1;
+
+// Number of buckets we want, which includes the overflow bucket but not the
+// implicit underflow bucket.
+// NOTE: We add two here, else we don't quite get enough buckets. This was
+// emperically determined by checking Histogram::bucket_ranges(). It might
+// be the case that we should subtract one here and from |kMaxUmaValue|, but
+// either way, i think it works out. We just have one unused bucket at worst,
+// which won't be renumbered even if we start using it later.
+static constexpr int kNumUmaBuckets = kMaxUmaValue - kMinUmaValue + 2;
+
+// For example, if kMinEnum == 0 and kMaxEnum == 5 (inclusive), then:
+// kMinUma = 1 (0 is implicit), kMaxUma = 6, and we'll want the implicit
+// underflow bucket plus kNumUmaBuckets = 6 more.
+// [0, 1) << implicit underflow bucket, kMinEnum goes here
+// [1, 2)
+// [2, 3)
+// [3, 4)
+// [4, 5)
+// [5, 6) << kMaxEnum goes here
+// [6, infinity) << unused overflow bucket.
+
+// We can have more, but shouldn't without talking to metrics folks.
+static_assert(kNumUmaBuckets < 100, "Too many buckets");
+
+} // namespace
+
+PowerStatusHelper::PowerStatusHelper(
+ CreateBatteryMonitorCB create_battery_monitor_cb)
+ : create_battery_monitor_cb_(std::move(create_battery_monitor_cb)) {}
+
+PowerStatusHelper::~PowerStatusHelper() = default;
+
+// static
+absl::optional<int> PowerStatusHelper::BucketFor(
+ bool is_playing,
+ bool has_video,
+ media::VideoCodec codec,
+ media::VideoCodecProfile profile,
+ gfx::Size natural_size,
+ bool is_fullscreen,
+ absl::optional<int> average_fps) {
+ if (!is_playing)
+ return {};
+
+ if (!has_video)
+ return {};
+
+ int bucket = 0;
+
+ if (codec == media::VideoCodec::kCodecH264)
+ bucket |= Bits::kCodecBitsH264;
+ else if (profile == media::VP9PROFILE_PROFILE0)
+ bucket |= Bits::kCodecBitsVP9Profile0;
+ else if (profile == media::VP9PROFILE_PROFILE2)
+ bucket |= Bits::kCodecBitsVP9Profile2;
+ else
+ return {};
+
+ // We could take into account rotation, but ignore it for now.
+ if (natural_size == gfx::Size(640, 360))
+ bucket |= kResolution360p;
+ else if (natural_size == gfx::Size(1280, 720))
+ bucket |= kResolution720p;
+ else if (natural_size == gfx::Size(1920, 1080))
+ bucket |= kResolution1080p;
+ else
+ return {};
+
+ // Estimate the frame rate. Since 24 is popular, allow a wide range around
+ // 30fps, since it's likely the same for power.
+ if (!average_fps)
+ return {};
+ else if (*average_fps == 60)
+ bucket |= kFrameRate60;
+ else if (*average_fps >= 24 && *average_fps <= 30)
+ bucket |= kFrameRate30;
+ else
+ return {};
+
+ bucket |= is_fullscreen ? kFullScreenYes : kFullScreenNo;
+
+ return bucket;
+}
+
+// static
+const char* PowerStatusHelper::BatteryDeltaHistogram() {
+ return kBatteryDeltaHistogram;
+}
+
+// static
+const char* PowerStatusHelper::ElapsedTimeHistogram() {
+ return kElapsedTimeHistogram;
+}
+
+void PowerStatusHelper::SetIsPlaying(bool is_playing) {
+ is_playing_ = is_playing;
+ OnAnyStateChange();
+}
+
+void PowerStatusHelper::SetMetadata(const media::PipelineMetadata& metadata) {
+ has_video_ = metadata.has_video;
+ codec_ = metadata.video_decoder_config.codec();
+ profile_ = metadata.video_decoder_config.profile();
+ natural_size_ = metadata.video_decoder_config.natural_size();
+ OnAnyStateChange();
+}
+
+void PowerStatusHelper::SetIsFullscreen(bool is_fullscreen) {
+ is_fullscreen_ = is_fullscreen;
+ OnAnyStateChange();
+}
+
+void PowerStatusHelper::SetAverageFrameRate(absl::optional<int> average_fps) {
+ average_fps_ = average_fps;
+ OnAnyStateChange();
+}
+
+void PowerStatusHelper::UpdatePowerExperimentState(bool state) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ experiment_state_ = state;
+ OnAnyStateChange();
+}
+
+void PowerStatusHelper::OnAnyStateChange() {
+ absl::optional<int> old_bucket = current_bucket_;
+ current_bucket_.reset();
+
+ // If we're the power experiment, then we might have a bucket. Else, we
+ // definitely don't.
+ if (experiment_state_) {
+ current_bucket_ = BucketFor(is_playing_, has_video_, codec_, profile_,
+ natural_size_, is_fullscreen_, average_fps_);
+ }
+
+ // If we're changing buckets, then request power updates with a new generation
+ // id. This lets us separate readings from the old bucket.
+ if (current_bucket_ && (!old_bucket || *current_bucket_ != *old_bucket)) {
+ // Also reset the baseline, in case we're changing buckets. We don't want
+ // to include any battery drain that should have been in the first bucket.
+ StartMonitoring();
+ } else if (old_bucket && !current_bucket_) {
+ // We don't need power updates, but we had them before.
+ StopMonitoring();
+ }
+}
+
+void PowerStatusHelper::OnBatteryStatus(
+ device::mojom::BatteryStatusPtr battery_status) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ QueryNextStatus();
+
+ if (battery_status->charging) {
+ // If we're charging, then wait until we stop. Take a new baseline then.
+ battery_level_baseline_.reset();
+ return;
+ }
+
+ // Compute the amount of time since our last update. Note that, if this is
+ // the first status update since we (re)started monitoring, then the baseline
+ // should be unset, so |elapsed| will be ignored. That's good, since it could
+ // be quite far in the past since we've had an update.
+ const base::TimeTicks now = base::TimeTicks::Now();
+
+ // Convert to floating point 0-100 from 0-1.
+ const float current_level = battery_status->level * 100;
+
+ // If we don't have a baseline, then use |current_level| and |now|. In the
+ // future, we might want to wait until the battery drain is reported twice,
+ // since we don't know how much of a fractional percent remains in this
+ // initial baseline. For now, just ignore that.
+ if (!battery_level_baseline_) {
+ battery_level_baseline_ = current_level;
+ last_update_ = now;
+ return;
+ }
+
+ // Second or later update since we started monitoring / stopped charging.
+ // Compute the battery used. Note that positive numbers indicate that the
+ // battery has gone down.
+ const float delta = *battery_level_baseline_ - current_level;
+
+ DCHECK(current_bucket_);
+ DCHECK_GE(delta, 0.);
+
+ // See if we can record some nonzero battery drain and elapsed time, when
+ // converted to int. We can only record ints in UMA.
+ const int delta_int = static_cast<int>(delta);
+ const base::TimeDelta elapsed = now - last_update_;
+ const int elapsed_msec = elapsed.InMilliseconds();
+ if (delta_int > 0 && elapsed_msec > 0) {
+ // Record that we consumed |delta_int| battery percent in |elapsed_msec|.
+ base::LinearHistogram::FactoryGet(
+ BatteryDeltaHistogram(), kMinUmaValue, kMaxUmaValue, kNumUmaBuckets,
+ base::HistogramBase::kUmaTargetedHistogramFlag)
+ ->AddCount(*current_bucket_, delta_int);
+
+ base::LinearHistogram::FactoryGet(
+ ElapsedTimeHistogram(), kMinUmaValue, kMaxUmaValue, kNumUmaBuckets,
+ base::HistogramBase::kUmaTargetedHistogramFlag)
+ ->AddCount(*current_bucket_, elapsed_msec);
+
+ // Update the baseline to |current_level|, but include any fractional
+ // unrecorded amount so that we can record it later.
+ battery_level_baseline_ = current_level + (delta - delta_int);
+ // Don't bother remembering any fractional msec.
+ last_update_ = now;
+ }
+}
+
+void PowerStatusHelper::StartMonitoring() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (!battery_monitor_.is_bound()) {
+ auto pending = create_battery_monitor_cb_.Run();
+ if (!pending.is_valid())
+ return;
+ battery_monitor_.Bind(std::move(pending));
+
+ // In case it's not available for some reason, do nothing.
+ if (!battery_monitor_.is_bound())
+ return;
+
+ // Start querying for status as long as we're connected.
+ QueryNextStatus();
+ }
+
+ // Any baseline that we had should be reset, since we're called to start or
+ // restart monitoring when our bucket changes.
+ battery_level_baseline_.reset();
+}
+
+void PowerStatusHelper::StopMonitoring() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ battery_monitor_.reset();
+}
+
+void PowerStatusHelper::QueryNextStatus() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(battery_monitor_.is_bound());
+
+ // Remember that overlapping calls are not allowed by BatteryMonitor, and are
+ // treated as a connection error. Unretained since we own |battery_monitor_|.
+ battery_monitor_->QueryNextStatus(base::BindOnce(
+ &PowerStatusHelper::OnBatteryStatus, base::Unretained(this)));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/power_status_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/media/power_status_helper_unittest.cc
new file mode 100644
index 00000000000..af97b2a36ed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/power_status_helper_unittest.cc
@@ -0,0 +1,440 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/power_status_helper.h"
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "media/base/pipeline_metadata.h"
+#include "services/device/public/mojom/battery_status.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+using ::testing::Bool;
+using ::testing::Combine;
+using ::testing::Values;
+
+class PowerStatusHelperTest : public testing::Test {
+ public:
+ class MockBatteryMonitor : public device::mojom::BatteryMonitor {
+ public:
+ MOCK_METHOD0(DidGetBatteryMonitor, void());
+ MOCK_METHOD0(DidQueryNextStatus, void());
+ MOCK_METHOD0(DidDisconnect, void());
+
+ ~MockBatteryMonitor() {
+ // Mojo gets mad if we don't finish up outstanding callbacks.
+ if (callback_)
+ ProvidePowerUpdate(0, 0);
+ }
+
+ // device::mojom::BatteryMonitor
+ void QueryNextStatus(QueryNextStatusCallback callback) override {
+ DidQueryNextStatus();
+ callback_ = std::move(callback);
+ }
+
+ // Would be nice to use a MockCallback for this, but a move-only return type
+ // doesn't seem to work.
+ mojo::PendingRemote<device::mojom::BatteryMonitor> GetBatteryMonitor() {
+ DidGetBatteryMonitor();
+ switch (remote_type_) {
+ case RemoteType::kConnected:
+ case RemoteType::kDisconnected: {
+ auto pending = receiver_.BindNewPipeAndPassRemote();
+ receiver_.set_disconnect_handler(base::BindOnce(
+ &MockBatteryMonitor::DidDisconnect, base::Unretained(this)));
+ if (remote_type_ == RemoteType::kDisconnected)
+ receiver_.reset();
+ base::RunLoop().RunUntilIdle();
+ return pending;
+ }
+ case RemoteType::kEmpty:
+ return mojo::PendingRemote<device::mojom::BatteryMonitor>();
+ }
+ }
+
+ // Would be nice if this were base::MockCallback, but move-only types don't
+ // seem to work.
+ PowerStatusHelper::CreateBatteryMonitorCB cb() {
+ return base::BindRepeating(&MockBatteryMonitor::GetBatteryMonitor,
+ base::Unretained(this));
+ }
+
+ // Provide a battery update via |callback_|.
+ void ProvidePowerUpdate(bool is_charging, float current_level) {
+ EXPECT_TRUE(callback_);
+ device::mojom::BatteryStatusPtr status =
+ device::mojom::BatteryStatus::New(is_charging, 0, /* charging time */
+ 0, /* discharging time */
+ current_level);
+ std::move(callback_).Run(std::move(status));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ mojo::Receiver<device::mojom::BatteryMonitor> receiver_{this};
+
+ // If false, then GetBatteryMonitor will not return a monitor.
+ enum class RemoteType {
+ // Provide a connected remote.
+ kConnected,
+ // Provide an empty PendingRemote
+ kEmpty,
+ // Provide a PendingRemote to a disconnected remote.
+ kDisconnected
+ };
+ RemoteType remote_type_ = RemoteType::kConnected;
+
+ // Most recently provided callback.
+ QueryNextStatusCallback callback_;
+ };
+
+ void SetUp() override {
+ helper_ = std::make_unique<PowerStatusHelper>(monitor_.cb());
+ }
+
+ // Set up |helper_| to be in a state that should record. Returns the bucket.
+ // |alternate| just causes us to create a different recordable bucket.
+ int MakeRecordable(bool alternate = false) {
+ helper_->SetIsPlaying(true);
+ media::PipelineMetadata metadata;
+ metadata.has_video = true;
+ metadata.video_decoder_config = media::VideoDecoderConfig(
+ media::kCodecH264, media::H264PROFILE_MAIN,
+ media::VideoDecoderConfig::AlphaMode::kIsOpaque,
+ media::VideoColorSpace(), media::VideoTransformation(),
+ gfx::Size(0, 0), /* coded_size */
+ gfx::Rect(0, 0), /* visible rect */
+ gfx::Size(640, 360), /* natural size */
+ std::vector<uint8_t>(), /* extra_data */
+ media::EncryptionScheme::kUnencrypted);
+ helper_->SetMetadata(metadata);
+ helper_->SetAverageFrameRate(60);
+ // Use |alternate| to set fullscreen state, since that should still be
+ // recordable but in a different bucket.
+ helper_->SetIsFullscreen(alternate);
+ base::RunLoop().RunUntilIdle();
+ helper_->UpdatePowerExperimentState(true);
+ base::RunLoop().RunUntilIdle();
+
+ return PowerStatusHelper::kCodecBitsH264 |
+ PowerStatusHelper::kResolution360p |
+ PowerStatusHelper::kFrameRate60 |
+ (alternate ? PowerStatusHelper::kFullScreenYes
+ : PowerStatusHelper::kFullScreenNo);
+ }
+
+ void FastForward(base::TimeDelta delta) {
+ task_environment_.FastForwardBy(delta);
+ }
+
+ // Verify that we've added |battery_delta| and |time_delta| to |bucket| in
+ // both histograms.
+ void VerifyHistogramDelta(int bucket,
+ int battery_delta,
+ base::TimeDelta time_delta) {
+ // Since histograms are cumulative, include the new counts.
+ total_battery_delta += battery_delta;
+ total_time_delta += time_delta.InMilliseconds();
+ histogram_tester_.ExpectBucketCount(helper_->BatteryDeltaHistogram(),
+ bucket, total_battery_delta);
+ histogram_tester_.ExpectBucketCount(helper_->ElapsedTimeHistogram(), bucket,
+ total_time_delta);
+ }
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ // Previous total histogram counts. Note that we record the total in msec,
+ // rather than as a TimeDelta, so that we round the same way as the helper.
+ int total_battery_delta = 0;
+ int total_time_delta = 0; // msec
+
+ MockBatteryMonitor monitor_;
+
+ // Helper under test
+ std::unique_ptr<PowerStatusHelper> helper_;
+
+ base::HistogramTester histogram_tester_;
+};
+
+TEST_F(PowerStatusHelperTest, EmptyPendingRemoteIsOkay) {
+ // Enable power monitoring, but have the callback fail to provide a remote.
+ // This should be handled gracefully.
+
+ // Ask |monitor_| not to provide a remote, and expect that |helper_| asks.
+ monitor_.remote_type_ = MockBatteryMonitor::RemoteType::kEmpty;
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ MakeRecordable();
+}
+
+TEST_F(PowerStatusHelperTest, UnboundPendingRemoteIsOkay) {
+ // TODO: this doesn't run the "is bound" part. maybe we should just delete
+ // the "is bound" part, or switch to a disconnection handler, etc.
+ monitor_.remote_type_ = MockBatteryMonitor::RemoteType::kDisconnected;
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ MakeRecordable();
+}
+
+TEST_F(PowerStatusHelperTest, BasicReportingWithFractionalAmounts) {
+ // Send three power updates, and verify that an update is called for the
+ // last two. The update should be fractional, so that some of it is rolled
+ // over to the next call.
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ const int bucket = MakeRecordable();
+
+ const float baseline_level = 0.9;
+ // Will round to 10%.
+ const float second_level = baseline_level - 0.106;
+ // Will round to 11% (plus a little).
+ const float third_level = second_level - 0.106;
+
+ // This should be the baseline.
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, baseline_level);
+
+ // This should trigger recording.
+ base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
+ FastForward(time_delta);
+
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, second_level);
+ VerifyHistogramDelta(bucket, 10, time_delta);
+
+ // This should also record, and pick up the fractional percentage drop that
+ // wasn't included in the previous one.
+ FastForward(time_delta);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, third_level);
+ VerifyHistogramDelta(bucket, 11, time_delta);
+}
+
+TEST_F(PowerStatusHelperTest, ChargingResetsBaseline) {
+ // Send some power updates, then send an update that's marked as 'charging'.
+ // Make sure that the baseline resets.
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ const int bucket = MakeRecordable();
+
+ const float fake_baseline_level = 0.95;
+ const float baseline_level = 0.9;
+ const float second_level = baseline_level - 0.10;
+
+ // Send the fake baseline.
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, fake_baseline_level);
+
+ // Send an update that's marked as charging.
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(true, second_level);
+
+ // This should be the correct baseline.
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, baseline_level);
+
+ // This should trigger recording.
+ base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
+ FastForward(time_delta);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, second_level);
+ VerifyHistogramDelta(bucket, 10, time_delta);
+}
+
+TEST_F(PowerStatusHelperTest, ExperimentStateStopsRecording) {
+ // Verify that stopping the power experiment stops recording.
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ MakeRecordable();
+
+ EXPECT_CALL(monitor_, DidDisconnect()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(0);
+ helper_->UpdatePowerExperimentState(false);
+ base::RunLoop().RunUntilIdle();
+
+ // Call the callback to make sure nothing bad happens. It should be ignored,
+ // since it shouldn't use battery updates after the experiment stops.
+ monitor_.ProvidePowerUpdate(false, 1.0);
+}
+
+TEST_F(PowerStatusHelperTest, ChangingBucketsWorks) {
+ // Switch buckets mid-recording, and make sure that we get a new bucket and
+ // use a new baseline.
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ auto first_bucket = MakeRecordable(false);
+
+ const float fake_baseline_level = 0.95;
+ const float baseline_level = 0.9;
+ const float second_level = baseline_level - 0.10;
+
+ // Send the fake baseline.
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, fake_baseline_level);
+
+ // Switch buckets.
+ auto second_bucket = MakeRecordable(true);
+ ASSERT_NE(first_bucket, second_bucket);
+
+ // This should be the correct baseline.
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, baseline_level);
+
+ // This should trigger recording.
+ base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
+ FastForward(time_delta);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ monitor_.ProvidePowerUpdate(false, second_level);
+ VerifyHistogramDelta(second_bucket, 10, time_delta);
+}
+
+TEST_F(PowerStatusHelperTest, UnbucketedVideoStopsRecording) {
+ // If we switch to video that doesn't have a bucket, then recording should
+ // stop too.
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ MakeRecordable();
+
+ // Should disconnect when we send bad params.
+ EXPECT_CALL(monitor_, DidDisconnect()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(0);
+ helper_->SetIsPlaying(false);
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(PowerStatusHelperTest, UnbucketedFrameRateStopsRecording) {
+ // If we switch to an unbucketed frame rate, then it should stop recording.
+ EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+ MakeRecordable();
+
+ // Should disconnect when we send bad params.
+ EXPECT_CALL(monitor_, DidDisconnect()).Times(1);
+ EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(0);
+ helper_->SetAverageFrameRate({});
+ base::RunLoop().RunUntilIdle();
+}
+
+using PlaybackParamsTuple = std::tuple<bool, /* is_playing */
+ bool, /* has_video */
+ PowerStatusHelper::Bits, /* codec */
+ PowerStatusHelper::Bits, /* resolution */
+ PowerStatusHelper::Bits, /* frame rate */
+ PowerStatusHelper::Bits /* full screen */
+ >;
+
+class PowerStatusHelperBucketTest
+ : public testing::TestWithParam<PlaybackParamsTuple> {
+ public:
+ absl::optional<int> BucketFor(bool is_playing,
+ bool has_video,
+ media::VideoCodec codec,
+ media::VideoCodecProfile profile,
+ gfx::Size coded_size,
+ bool is_fullscreen,
+ absl::optional<int> average_fps) {
+ return PowerStatusHelper::BucketFor(is_playing, has_video, codec, profile,
+ coded_size, is_fullscreen, average_fps);
+ }
+};
+
+TEST_P(PowerStatusHelperBucketTest, TestBucket) {
+ // Construct a params that should end up in the bucket specified by the test
+ // parameter, if one exists.
+ bool expect_bucket = true;
+
+ bool is_playing = std::get<0>(GetParam());
+ bool has_video = std::get<1>(GetParam());
+
+ // We must be playing video to get a bucket.
+ if (!is_playing || !has_video)
+ expect_bucket = false;
+
+ auto codec_bits = std::get<2>(GetParam());
+ media::VideoCodec codec;
+ media::VideoCodecProfile profile;
+ if (codec_bits == PowerStatusHelper::Bits::kCodecBitsH264) {
+ codec = media::kCodecH264;
+ profile = media::H264PROFILE_MAIN;
+ } else if (codec_bits == PowerStatusHelper::Bits::kCodecBitsVP9Profile0) {
+ codec = media::kCodecVP9;
+ profile = media::VP9PROFILE_PROFILE0;
+ } else if (codec_bits == PowerStatusHelper::Bits::kCodecBitsVP9Profile2) {
+ codec = media::kCodecVP9;
+ profile = media::VP9PROFILE_PROFILE2;
+ } else {
+ // Some unsupported codec.
+ codec = media::kCodecVP8;
+ profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ expect_bucket = false;
+ }
+
+ auto res = std::get<3>(GetParam());
+ gfx::Size coded_size;
+ if (res == PowerStatusHelper::Bits::kResolution360p) {
+ coded_size = gfx::Size(640, 360);
+ } else if (res == PowerStatusHelper::Bits::kResolution720p) {
+ coded_size = gfx::Size(1280, 720);
+ } else if (res == PowerStatusHelper::Bits::kResolution1080p) {
+ coded_size = gfx::Size(1920, 1080);
+ } else {
+ coded_size = gfx::Size(1234, 5678);
+ expect_bucket = false;
+ }
+
+ auto fps = std::get<4>(GetParam());
+ absl::optional<int> average_fps;
+ if (fps == PowerStatusHelper::Bits::kFrameRate30) {
+ average_fps = 30;
+ } else if (fps == PowerStatusHelper::Bits::kFrameRate60) {
+ average_fps = 60;
+ } else {
+ average_fps = 90;
+ expect_bucket = false;
+ }
+
+ bool is_fullscreen =
+ (std::get<5>(GetParam()) == PowerStatusHelper::Bits::kFullScreenYes);
+
+ auto bucket = BucketFor(is_playing, has_video, codec, profile, coded_size,
+ is_fullscreen, average_fps);
+ if (!expect_bucket) {
+ EXPECT_FALSE(bucket);
+ } else {
+ EXPECT_EQ(*bucket, std::get<2>(GetParam()) | std::get<3>(GetParam()) |
+ std::get<4>(GetParam()) | std::get<5>(GetParam()));
+ }
+}
+
+// Instantiate all valid combinations, plus some that aren't.
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ PowerStatusHelperBucketTest,
+ Combine(Bool(),
+ Bool(),
+ Values(PowerStatusHelper::Bits::kCodecBitsH264,
+ PowerStatusHelper::Bits::kCodecBitsVP9Profile0,
+ PowerStatusHelper::Bits::kCodecBitsVP9Profile2,
+ PowerStatusHelper::Bits::kNotAValidBitForTesting),
+ Values(PowerStatusHelper::Bits::kResolution360p,
+ PowerStatusHelper::Bits::kResolution720p,
+ PowerStatusHelper::Bits::kResolution1080p,
+ PowerStatusHelper::Bits::kNotAValidBitForTesting),
+ Values(PowerStatusHelper::Bits::kFrameRate30,
+ PowerStatusHelper::Bits::kFrameRate60,
+ PowerStatusHelper::Bits::kNotAValidBitForTesting),
+ Values(PowerStatusHelper::Bits::kFullScreenNo,
+ PowerStatusHelper::Bits::kFullScreenYes)));
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/remote_playback_client_wrapper_impl.cc b/chromium/third_party/blink/renderer/platform/media/remote_playback_client_wrapper_impl.cc
new file mode 100644
index 00000000000..09516efa498
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/remote_playback_client_wrapper_impl.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/public/platform/media/remote_playback_client_wrapper_impl.h"
+
+#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_client.h"
+#include "third_party/blink/public/platform/web_media_player_client.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+namespace blink {
+
+RemotePlaybackClientWrapperImpl::RemotePlaybackClientWrapperImpl(
+ WebMediaPlayerClient* client)
+ : remote_playback_client_(client->RemotePlaybackClient()) {}
+
+RemotePlaybackClientWrapperImpl::~RemotePlaybackClientWrapperImpl() = default;
+
+std::string RemotePlaybackClientWrapperImpl::GetActivePresentationId() {
+ if (!remote_playback_client_)
+ return std::string();
+
+ // The presentation ID is essentially a GUID preceeded by the "mr_" prefix,
+ // which makes it ASCII compatible.
+ // If MediaRouterBase::CreatePresentationId() were changed, this line might
+ // need to be updated.
+ return remote_playback_client_->GetPresentationId().Ascii();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc b/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
new file mode 100644
index 00000000000..27c045a7fa4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
@@ -0,0 +1,576 @@
+// 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/media/resource_multi_buffer_data_provider.h"
+
+#include <stddef.h>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bits.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "net/http/http_byte_range.h"
+#include "net/http/http_request_headers.h"
+#include "services/network/public/cpp/cors/cors.h"
+#include "third_party/blink/public/common/loader/previews_state.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/platform/media/resource_fetch_context.h"
+#include "third_party/blink/public/platform/media/url_index.h"
+#include "third_party/blink/public/platform/web_network_state_notifier.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/web/web_associated_url_loader.h"
+#include "third_party/blink/renderer/platform/media/cache_util.h"
+
+namespace blink {
+
+// The number of milliseconds to wait before retrying a failed load.
+const int kLoaderFailedRetryDelayMs = 250;
+
+// Each retry, add this many MS to the delay.
+// total delay is:
+// (kLoaderPartialRetryDelayMs +
+// kAdditionalDelayPerRetryMs * (kMaxRetries - 1) / 2) * kMaxretries = 29250 ms
+const int kAdditionalDelayPerRetryMs = 50;
+
+// The number of milliseconds to wait before retrying when the server
+// decides to not give us all the data at once.
+const int kLoaderPartialRetryDelayMs = 25;
+
+const int kHttpOK = 200;
+const int kHttpPartialContent = 206;
+const int kHttpRangeNotSatisfiable = 416;
+
+ResourceMultiBufferDataProvider::ResourceMultiBufferDataProvider(
+ UrlData* url_data,
+ MultiBufferBlockId pos,
+ bool is_client_audio_element,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : pos_(pos),
+ url_data_(url_data),
+ retries_(0),
+ cors_mode_(url_data->cors_mode()),
+ origin_(url_data->url().GetOrigin()),
+ is_client_audio_element_(is_client_audio_element),
+ task_runner_(std::move(task_runner)) {
+ DCHECK(url_data_) << " pos = " << pos;
+ DCHECK_GE(pos, 0);
+}
+
+ResourceMultiBufferDataProvider::~ResourceMultiBufferDataProvider() = default;
+
+void ResourceMultiBufferDataProvider::Start() {
+ DVLOG(1) << __func__ << " @ " << byte_pos();
+ if (url_data_->length() > 0 && byte_pos() >= url_data_->length()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ResourceMultiBufferDataProvider::Terminate,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+
+ // Prepare the request.
+ WebURLRequest request(url_data_->url());
+ request.SetRequestContext(is_client_audio_element_
+ ? mojom::RequestContextType::AUDIO
+ : mojom::RequestContextType::VIDEO);
+ request.SetRequestDestination(
+ is_client_audio_element_ ? network::mojom::RequestDestination::kAudio
+ : network::mojom::RequestDestination::kVideo);
+ request.SetHttpHeaderField(
+ WebString::FromUTF8(net::HttpRequestHeaders::kRange),
+ WebString::FromUTF8(
+ net::HttpByteRange::RightUnbounded(byte_pos()).GetHeaderValue()));
+
+ if (url_data_->length() == kPositionNotSpecified &&
+ url_data_->CachedSize() == 0 && url_data_->BytesReadFromCache() == 0 &&
+ WebNetworkStateNotifier::SaveDataEnabled() &&
+ (url_data_->url().SchemeIs(url::kHttpScheme) ||
+ url_data_->url().SchemeIs(url::kHttpsScheme))) {
+ // This lets the data reduction proxy know that we don't have any previously
+ // cached data for this resource. We can only send it if this is the first
+ // request for this resource.
+ request.SetPreviewsState(request.GetPreviewsState() |
+ PreviewsTypes::kSrcVideoRedirectOn);
+ }
+
+ // We would like to send an if-match header with the request to
+ // tell the remote server that we really can't handle files other
+ // than the one we already started playing. Unfortunately, doing
+ // so will disable the http cache, and possibly other proxies
+ // along the way. See crbug/504194 and crbug/689989 for more information.
+
+ // Disable compression, compression for audio/video doesn't make sense...
+ request.SetHttpHeaderField(
+ WebString::FromUTF8(net::HttpRequestHeaders::kAcceptEncoding),
+ WebString::FromUTF8("identity;q=1, *;q=0"));
+
+ // Start resource loading.
+ WebAssociatedURLLoaderOptions options;
+ if (url_data_->cors_mode() != UrlData::CORS_UNSPECIFIED) {
+ options.expose_all_response_headers = true;
+ // The author header set is empty, no preflight should go ahead.
+ options.preflight_policy =
+ network::mojom::CorsPreflightPolicy::kPreventPreflight;
+
+ request.SetMode(network::mojom::RequestMode::kCors);
+ if (url_data_->cors_mode() != UrlData::CORS_USE_CREDENTIALS) {
+ request.SetCredentialsMode(network::mojom::CredentialsMode::kSameOrigin);
+ }
+ }
+
+ active_loader_ =
+ url_data_->url_index()->fetch_context()->CreateUrlLoader(options);
+ active_loader_->LoadAsynchronously(request, this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// MultiBuffer::DataProvider implementation.
+MultiBufferBlockId ResourceMultiBufferDataProvider::Tell() const {
+ return pos_;
+}
+
+bool ResourceMultiBufferDataProvider::Available() const {
+ if (fifo_.empty())
+ return false;
+ if (fifo_.back()->end_of_stream())
+ return true;
+ if (fifo_.front()->data_size() == block_size())
+ return true;
+ return false;
+}
+
+int64_t ResourceMultiBufferDataProvider::AvailableBytes() const {
+ int64_t bytes = 0;
+ for (const auto& i : fifo_) {
+ if (i->end_of_stream())
+ break;
+ bytes += i->data_size();
+ }
+ return bytes;
+}
+
+scoped_refptr<media::DataBuffer> ResourceMultiBufferDataProvider::Read() {
+ DCHECK(Available());
+ scoped_refptr<media::DataBuffer> ret = fifo_.front();
+ fifo_.pop_front();
+ ++pos_;
+ return ret;
+}
+
+void ResourceMultiBufferDataProvider::SetDeferred(bool deferred) {
+ if (active_loader_)
+ active_loader_->SetDefersLoading(deferred);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// WebAssociatedURLLoaderClient implementation.
+
+bool ResourceMultiBufferDataProvider::WillFollowRedirect(
+ const WebURL& new_url,
+ const WebURLResponse& redirect_response) {
+ DVLOG(1) << "willFollowRedirect";
+ redirects_to_ = new_url;
+ url_data_->set_valid_until(base::Time::Now() +
+ GetCacheValidUntil(redirect_response));
+
+ // This test is vital for security!
+ if (cors_mode_ == UrlData::CORS_UNSPECIFIED) {
+ // We allow the redirect if the origin is the same.
+ if (origin_ != redirects_to_.GetOrigin()) {
+ // We also allow the redirect if we don't have any data in the
+ // cache, as that means that no dangerous data mixing can occur.
+ if (url_data_->multibuffer()->map().empty() && fifo_.empty())
+ return true;
+
+ active_loader_.reset();
+ url_data_->Fail();
+ return false; // "this" may be deleted now.
+ }
+ }
+ return true;
+}
+
+void ResourceMultiBufferDataProvider::DidSendData(
+ uint64_t bytes_sent,
+ uint64_t total_bytes_to_be_sent) {
+ NOTIMPLEMENTED();
+}
+
+void ResourceMultiBufferDataProvider::DidReceiveResponse(
+ const WebURLResponse& response) {
+#if DCHECK_IS_ON()
+ std::string version;
+ switch (response.HttpVersion()) {
+ case WebURLResponse::kHTTPVersion_0_9:
+ version = "0.9";
+ break;
+ case WebURLResponse::kHTTPVersion_1_0:
+ version = "1.0";
+ break;
+ case WebURLResponse::kHTTPVersion_1_1:
+ version = "1.1";
+ break;
+ case WebURLResponse::kHTTPVersion_2_0:
+ version = "2.1";
+ break;
+ case WebURLResponse::kHTTPVersionUnknown:
+ version = "unknown";
+ break;
+ }
+ DVLOG(1) << "didReceiveResponse: HTTP/" << version << " "
+ << response.HttpStatusCode();
+#endif
+ DCHECK(active_loader_);
+
+ scoped_refptr<UrlData> destination_url_data(url_data_);
+
+ if (!redirects_to_.is_empty()) {
+ destination_url_data = url_data_->url_index()->GetByUrl(
+ redirects_to_, cors_mode_, UrlIndex::kNormal);
+ redirects_to_ = GURL();
+ }
+
+ base::Time last_modified;
+ if (base::Time::FromString(
+ response.HttpHeaderField("Last-Modified").Utf8().data(),
+ &last_modified)) {
+ destination_url_data->set_last_modified(last_modified);
+ }
+
+ destination_url_data->set_etag(
+ response.HttpHeaderField("ETag").Utf8().data());
+
+ destination_url_data->set_valid_until(base::Time::Now() +
+ GetCacheValidUntil(response));
+
+ destination_url_data->set_cacheable(GetReasonsForUncacheability(response) ==
+ 0);
+
+ // Expected content length can be |kPositionNotSpecified|, in that case
+ // |content_length_| is not specified and this is a streaming response.
+ int64_t content_length = response.ExpectedContentLength();
+ bool end_of_file = false;
+ bool do_fail = false;
+ // We get the response type here because aborting the loader may change it.
+ const auto response_type = response.GetType();
+ bytes_to_discard_ = 0;
+
+ // We make a strong assumption that when we reach here we have either
+ // received a response from HTTP/HTTPS protocol or the request was
+ // successful (in particular range request). So we only verify the partial
+ // response for HTTP and HTTPS protocol.
+ if (destination_url_data->url().SchemeIsHTTPOrHTTPS()) {
+ bool partial_response = (response.HttpStatusCode() == kHttpPartialContent);
+ bool ok_response = (response.HttpStatusCode() == kHttpOK);
+
+ // Check to see whether the server supports byte ranges.
+ std::string accept_ranges =
+ response.HttpHeaderField("Accept-Ranges").Utf8();
+ if (accept_ranges.find("bytes") != std::string::npos)
+ destination_url_data->set_range_supported();
+
+ // If we have verified the partial response and it is correct.
+ // It's also possible for a server to support range requests
+ // without advertising "Accept-Ranges: bytes".
+ if (partial_response &&
+ VerifyPartialResponse(response, destination_url_data)) {
+ destination_url_data->set_range_supported();
+ } else if (ok_response) {
+ // We accept a 200 response for a Range:0- request, trusting the
+ // Accept-Ranges header, because Apache thinks that's a reasonable thing
+ // to return.
+ destination_url_data->set_length(content_length);
+ bytes_to_discard_ = byte_pos();
+ } else if (response.HttpStatusCode() == kHttpRangeNotSatisfiable) {
+ // Unsatisfiable range
+ // Really, we should never request a range that doesn't exist, but
+ // if we do, let's handle it in a sane way.
+ // Note, we can't just call OnDataProviderEvent() here, because
+ // url_data_ hasn't been updated to the final destination yet.
+ end_of_file = true;
+ } else {
+ active_loader_.reset();
+ // Can't call fail until readers have been migrated to the new
+ // url data below.
+ do_fail = true;
+ }
+ } else {
+ destination_url_data->set_range_supported();
+ if (content_length != kPositionNotSpecified) {
+ destination_url_data->set_length(content_length + byte_pos());
+ }
+ }
+
+ if (!do_fail) {
+ destination_url_data =
+ url_data_->url_index()->TryInsert(destination_url_data);
+ }
+
+ // This is vital for security!
+ destination_url_data->set_is_cors_cross_origin(
+ network::cors::IsCorsCrossOriginResponseType(response_type));
+
+ // Only used for metrics.
+ {
+ WebString access_control =
+ response.HttpHeaderField("Access-Control-Allow-Origin");
+ if (!access_control.IsEmpty() && !access_control.Equals("null")) {
+ // Note: When |access_control| is not *, we should verify that it matches
+ // the requesting origin. Instead we just assume that it matches, which is
+ // probably accurate enough for metrics.
+ destination_url_data->set_has_access_control();
+ }
+ }
+
+ if (destination_url_data != url_data_) {
+ // At this point, we've encountered a redirect, or found a better url data
+ // instance for the data that we're about to download.
+
+ // First, let's take a ref on the current url data.
+ scoped_refptr<UrlData> old_url_data(url_data_);
+ destination_url_data->Use();
+
+ // Take ownership of ourselves. (From the multibuffer)
+ std::unique_ptr<DataProvider> self(
+ url_data_->multibuffer()->RemoveProvider(this));
+ url_data_ = destination_url_data.get();
+ // Give the ownership to our new owner.
+ url_data_->multibuffer()->AddProvider(std::move(self));
+
+ // Call callback to let upstream users know about the transfer.
+ // This will merge the data from the two multibuffers and
+ // cause clients to start using the new UrlData.
+ old_url_data->RedirectTo(destination_url_data);
+ }
+
+ if (do_fail) {
+ destination_url_data->Fail();
+ return; // "this" may be deleted now.
+ }
+
+ // Get the response URL since it can differ from the request URL when a
+ // service worker provided the response. Normally we would just use
+ // ResponseUrl(), but ResourceMultiBufferDataProvider disallows mixing
+ // constructed responses (new Response()) and native server responses, even if
+ // they have the same response URL.
+ GURL response_url;
+ if (!response.WasFetchedViaServiceWorker() ||
+ response.HasUrlListViaServiceWorker()) {
+ response_url = response.ResponseUrl();
+ }
+
+ // This test is vital for security!
+ if (!url_data_->ValidateDataOrigin(response_url.GetOrigin())) {
+ active_loader_.reset();
+ url_data_->Fail();
+ return; // "this" may be deleted now.
+ }
+
+ if (end_of_file) {
+ fifo_.push_back(media::DataBuffer::CreateEOSBuffer());
+ url_data_->multibuffer()->OnDataProviderEvent(this);
+ }
+}
+
+void ResourceMultiBufferDataProvider::DidReceiveData(const char* data,
+ int data_length) {
+ DVLOG(1) << "didReceiveData: " << data_length << " bytes";
+ DCHECK(!Available());
+ DCHECK(active_loader_);
+ DCHECK_GT(data_length, 0);
+
+ if (bytes_to_discard_) {
+ uint64_t tmp = std::min<uint64_t>(bytes_to_discard_, data_length);
+ data_length -= tmp;
+ data += tmp;
+ bytes_to_discard_ -= tmp;
+ if (data_length == 0)
+ return;
+ }
+
+ // When we receive data, we allow more retries.
+ retries_ = 0;
+
+ while (data_length) {
+ if (fifo_.empty() || fifo_.back()->data_size() == block_size()) {
+ fifo_.push_back(new media::DataBuffer(block_size()));
+ fifo_.back()->set_data_size(0);
+ }
+ int last_block_size = fifo_.back()->data_size();
+ int to_append = std::min<int>(data_length, block_size() - last_block_size);
+ DCHECK_GT(to_append, 0);
+ memcpy(fifo_.back()->writable_data() + last_block_size, data, to_append);
+ data += to_append;
+ fifo_.back()->set_data_size(last_block_size + to_append);
+ data_length -= to_append;
+ }
+
+ url_data_->multibuffer()->OnDataProviderEvent(this);
+
+ // Beware, this object might be deleted here.
+}
+
+void ResourceMultiBufferDataProvider::DidDownloadData(uint64_t dataLength) {
+ NOTIMPLEMENTED();
+}
+
+void ResourceMultiBufferDataProvider::DidFinishLoading() {
+ DVLOG(1) << "didFinishLoading";
+ DCHECK(active_loader_.get());
+ DCHECK(!Available());
+
+ // We're done with the loader.
+ active_loader_.reset();
+
+ // If we didn't know the |instance_size_| we do now.
+ int64_t size = byte_pos();
+
+ // This request reports something smaller than what we've seen in the past,
+ // Maybe it's transient error?
+ if (url_data_->length() != kPositionNotSpecified &&
+ size < url_data_->length()) {
+ if (retries_ < kMaxRetries) {
+ DVLOG(1) << " Partial data received.... @ pos = " << size;
+ retries_++;
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&ResourceMultiBufferDataProvider::Start,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kLoaderPartialRetryDelayMs));
+ return;
+ } else {
+ url_data_->Fail();
+ return; // "this" may be deleted now.
+ }
+ }
+
+ url_data_->set_length(size);
+ fifo_.push_back(media::DataBuffer::CreateEOSBuffer());
+
+ if (url_data_->url_index()) {
+ url_data_->url_index()->TryInsert(url_data_);
+ }
+
+ DCHECK(Available());
+ url_data_->multibuffer()->OnDataProviderEvent(this);
+
+ // Beware, this object might be deleted here.
+}
+
+void ResourceMultiBufferDataProvider::DidFail(const WebURLError& error) {
+ DVLOG(1) << "didFail: reason=" << error.reason();
+ DCHECK(active_loader_.get());
+ active_loader_.reset();
+
+ if (retries_ < kMaxRetries && pos_ != 0) {
+ retries_++;
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&ResourceMultiBufferDataProvider::Start,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(
+ kLoaderFailedRetryDelayMs + kAdditionalDelayPerRetryMs * retries_));
+ } else {
+ // We don't need to continue loading after failure.
+ // Note that calling Fail() will most likely delete this object.
+ url_data_->Fail();
+ }
+}
+
+bool ResourceMultiBufferDataProvider::ParseContentRange(
+ const std::string& content_range_str,
+ int64_t* first_byte_position,
+ int64_t* last_byte_position,
+ int64_t* instance_size) {
+ const char kUpThroughBytesUnit[] = "bytes ";
+ if (!base::StartsWith(content_range_str, kUpThroughBytesUnit,
+ base::CompareCase::SENSITIVE)) {
+ return false;
+ }
+ std::string range_spec =
+ content_range_str.substr(sizeof(kUpThroughBytesUnit) - 1);
+ size_t dash_offset = range_spec.find("-");
+ size_t slash_offset = range_spec.find("/");
+
+ if (dash_offset == std::string::npos || slash_offset == std::string::npos ||
+ slash_offset < dash_offset || slash_offset + 1 == range_spec.length()) {
+ return false;
+ }
+ if (!base::StringToInt64(range_spec.substr(0, dash_offset),
+ first_byte_position) ||
+ !base::StringToInt64(
+ range_spec.substr(dash_offset + 1, slash_offset - dash_offset - 1),
+ last_byte_position)) {
+ return false;
+ }
+ if (slash_offset == range_spec.length() - 2 &&
+ range_spec[slash_offset + 1] == '*') {
+ *instance_size = kPositionNotSpecified;
+ } else {
+ if (!base::StringToInt64(range_spec.substr(slash_offset + 1),
+ instance_size)) {
+ return false;
+ }
+ }
+ if (*last_byte_position < *first_byte_position ||
+ (*instance_size != kPositionNotSpecified &&
+ *last_byte_position >= *instance_size)) {
+ return false;
+ }
+
+ return true;
+}
+
+void ResourceMultiBufferDataProvider::Terminate() {
+ fifo_.push_back(media::DataBuffer::CreateEOSBuffer());
+ url_data_->multibuffer()->OnDataProviderEvent(this);
+}
+
+int64_t ResourceMultiBufferDataProvider::byte_pos() const {
+ int64_t ret = pos_;
+ ret += fifo_.size();
+ ret = ret << url_data_->multibuffer()->block_size_shift();
+ if (!fifo_.empty()) {
+ ret += fifo_.back()->data_size() - block_size();
+ }
+ return ret;
+}
+
+int64_t ResourceMultiBufferDataProvider::block_size() const {
+ int64_t ret = 1;
+ return ret << url_data_->multibuffer()->block_size_shift();
+}
+
+bool ResourceMultiBufferDataProvider::VerifyPartialResponse(
+ const WebURLResponse& response,
+ const scoped_refptr<UrlData>& url_data) {
+ int64_t first_byte_position, last_byte_position, instance_size;
+ if (!ParseContentRange(response.HttpHeaderField("Content-Range").Utf8(),
+ &first_byte_position, &last_byte_position,
+ &instance_size)) {
+ return false;
+ }
+
+ if (url_data->length() == kPositionNotSpecified) {
+ url_data->set_length(instance_size);
+ }
+
+ if (first_byte_position > byte_pos()) {
+ return false;
+ }
+ if (last_byte_position + 1 < byte_pos()) {
+ return false;
+ }
+ bytes_to_discard_ = byte_pos() - first_byte_position;
+
+ return true;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h b/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h
new file mode 100644
index 00000000000..888eafed37e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h
@@ -0,0 +1,135 @@
+// 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_MEDIA_RESOURCE_MULTI_BUFFER_DATA_PROVIDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_RESOURCE_MULTI_BUFFER_DATA_PROVIDER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/platform/media/multi_buffer.h"
+#include "third_party/blink/public/platform/media/url_index.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/web/web_associated_url_loader_client.h"
+#include "third_party/blink/public/web/web_frame.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "url/gurl.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+class WebAssociatedURLLoader;
+
+class PLATFORM_EXPORT ResourceMultiBufferDataProvider
+ : public MultiBuffer::DataProvider,
+ public WebAssociatedURLLoaderClient {
+ public:
+ // NUmber of times we'll retry if the connection fails.
+ enum { kMaxRetries = 30 };
+
+ ResourceMultiBufferDataProvider(
+ UrlData* url_data,
+ MultiBufferBlockId pos,
+ bool is_client_audio_element,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~ResourceMultiBufferDataProvider() override;
+
+ // Virtual for testing purposes.
+ virtual void Start();
+
+ // MultiBuffer::DataProvider implementation
+ MultiBufferBlockId Tell() const override;
+ bool Available() const override;
+ int64_t AvailableBytes() const override;
+ scoped_refptr<media::DataBuffer> Read() override;
+ void SetDeferred(bool defer) override;
+
+ // WebAssociatedURLLoaderClient implementation.
+ bool WillFollowRedirect(const WebURL& new_url,
+ const WebURLResponse& redirect_response) override;
+ void DidSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent) override;
+ void DidReceiveResponse(const WebURLResponse& response) override;
+ void DidDownloadData(uint64_t data_length) override;
+ void DidReceiveData(const char* data, int data_length) override;
+ void DidFinishLoading() override;
+ void DidFail(const WebURLError&) override;
+
+ // Use protected instead of private for testing purposes.
+ protected:
+ friend class MultiBufferDataSourceTest;
+ friend class ResourceMultiBufferDataProviderTest;
+
+ // Callback used when we're asked to fetch data after the end of the file.
+ void Terminate();
+
+ // Parse a Content-Range header into its component pieces and return true if
+ // each of the expected elements was found & parsed correctly.
+ // |*instance_size| may be set to kPositionNotSpecified if the range ends in
+ // "/*".
+ // NOTE: only public for testing! This is an implementation detail of
+ // VerifyPartialResponse (a private method).
+ static bool ParseContentRange(const std::string& content_range_str,
+ int64_t* first_byte_position,
+ int64_t* last_byte_position,
+ int64_t* instance_size);
+
+ int64_t byte_pos() const;
+ int64_t block_size() const;
+
+ // If we have made a range request, verify the response from the server.
+ bool VerifyPartialResponse(const WebURLResponse& response,
+ const scoped_refptr<UrlData>& url_data);
+
+ // Current Position.
+ MultiBufferBlockId pos_;
+
+ // This is where we actually get read data from.
+ // We don't need (or want) a scoped_refptr for this one, because
+ // we are owned by it. Note that we may change this when we encounter
+ // a redirect because we actually change ownership.
+ UrlData* url_data_;
+
+ // Temporary storage for incoming data.
+ std::list<scoped_refptr<media::DataBuffer>> fifo_;
+
+ // How many retries have we done at the current position.
+ int retries_;
+
+ // Copy of url_data_->cors_mode()
+ // const to make it obvious that redirects cannot change it.
+ const UrlData::CorsMode cors_mode_;
+
+ // The origin for the initial request.
+ // const to make it obvious that redirects cannot change it.
+ const GURL origin_;
+
+ // Keeps track of an active WebAssociatedURLLoader.
+ // Only valid while loading resource.
+ std::unique_ptr<WebAssociatedURLLoader> active_loader_;
+
+ // When we encounter a redirect, this is the source of the redirect.
+ GURL redirects_to_;
+
+ // If the server tries to gives us more bytes than we want, this how
+ // many bytes we need to discard before we get to the right place.
+ uint64_t bytes_to_discard_ = 0;
+
+ // Is the client an audio element?
+ bool is_client_audio_element_ = false;
+
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::WeakPtrFactory<ResourceMultiBufferDataProvider> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_RESOURCE_MULTI_BUFFER_DATA_PROVIDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc b/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
new file mode 100644
index 00000000000..e9dc87890d9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
@@ -0,0 +1,384 @@
+// 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/media/resource_multi_buffer_data_provider.h"
+
+#include <stdint.h>
+#include <algorithm>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/format_macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/task_environment.h"
+#include "media/base/media_log.h"
+#include "media/base/seekable_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/media/url_index.h"
+#include "third_party/blink/public/platform/web_network_state_notifier.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h"
+#include "third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h"
+
+namespace blink {
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::NiceMock;
+using ::testing::Truly;
+
+const char kHttpUrl[] = "http://test";
+const char kHttpsUrl[] = "https://test";
+const char kHttpRedirect[] = "http://test/ing";
+const char kEtag[] = "\"arglebargle glopy-glyf?\"";
+
+const int kDataSize = 1024;
+const int kHttpOK = 200;
+const int kHttpPartialContent = 206;
+
+enum NetworkState { NONE, LOADED, LOADING };
+
+static bool want_frfr = false;
+
+// Predicate that checks the Accept-Encoding request header and FRFR previews
+// state.
+static bool CorrectAcceptEncodingAndPreviewsState(
+ const WebURLRequest& request) {
+ bool has_frfr =
+ request.GetPreviewsState() & PreviewsTypes::kSrcVideoRedirectOn;
+ if (has_frfr != want_frfr) {
+ return false;
+ }
+
+ std::string value = request
+ .HttpHeaderField(WebString::FromUTF8(
+ net::HttpRequestHeaders::kAcceptEncoding))
+ .Utf8();
+ return (value.find("identity;q=1") != std::string::npos) &&
+ (value.find("*;q=0") != std::string::npos);
+}
+
+class ResourceMultiBufferDataProviderTest : public testing::Test {
+ public:
+ ResourceMultiBufferDataProviderTest() {
+ for (int i = 0; i < kDataSize; ++i) {
+ data_[i] = i;
+ }
+ ON_CALL(fetch_context_, CreateUrlLoader(_))
+ .WillByDefault(Invoke(
+ this, &ResourceMultiBufferDataProviderTest::CreateUrlLoader));
+ }
+
+ ResourceMultiBufferDataProviderTest(
+ const ResourceMultiBufferDataProviderTest&) = delete;
+ ResourceMultiBufferDataProviderTest& operator=(
+ const ResourceMultiBufferDataProviderTest&) = delete;
+
+ void Initialize(const char* url, int first_position) {
+ want_frfr = false;
+ gurl_ = GURL(url);
+ url_data_ = url_index_.GetByUrl(gurl_, UrlData::CORS_UNSPECIFIED,
+ UrlIndex::kNormal);
+ url_data_->set_etag(kEtag);
+ DCHECK(url_data_);
+ url_data_->OnRedirect(
+ base::BindOnce(&ResourceMultiBufferDataProviderTest::RedirectCallback,
+ base::Unretained(this)));
+
+ first_position_ = first_position;
+
+ std::unique_ptr<ResourceMultiBufferDataProvider> loader(
+ new ResourceMultiBufferDataProvider(
+ url_data_.get(), first_position_,
+ false /* is_client_audio_element */,
+ task_environment_.GetMainThreadTaskRunner()));
+ loader_ = loader.get();
+ url_data_->multibuffer()->AddProvider(std::move(loader));
+ }
+
+ void Start() { loader_->Start(); }
+
+ void FullResponse(int64_t instance_size, bool ok = true) {
+ WebURLResponse response(gurl_);
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Length"),
+ WebString::FromUTF8(base::StringPrintf("%" PRId64, instance_size)));
+ response.SetExpectedContentLength(instance_size);
+ response.SetHttpStatusCode(kHttpOK);
+ loader_->DidReceiveResponse(response);
+
+ if (ok) {
+ EXPECT_EQ(instance_size, url_data_->length());
+ }
+
+ EXPECT_FALSE(url_data_->range_supported());
+ }
+
+ void PartialResponse(int64_t first_position,
+ int64_t last_position,
+ int64_t instance_size) {
+ PartialResponse(first_position, last_position, instance_size, false, true);
+ }
+
+ void PartialResponse(int64_t first_position,
+ int64_t last_position,
+ int64_t instance_size,
+ bool chunked,
+ bool accept_ranges) {
+ WebURLResponse response(gurl_);
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Range"),
+ WebString::FromUTF8(
+ base::StringPrintf("bytes "
+ "%" PRId64 "-%" PRId64 "/%" PRId64,
+ first_position, last_position, instance_size)));
+
+ // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
+ int64_t content_length = -1;
+ if (chunked) {
+ response.SetHttpHeaderField(WebString::FromUTF8("Transfer-Encoding"),
+ WebString::FromUTF8("chunked"));
+ } else {
+ content_length = last_position - first_position + 1;
+ }
+ response.SetExpectedContentLength(content_length);
+
+ // A server isn't required to return Accept-Ranges even though it might.
+ if (accept_ranges) {
+ response.SetHttpHeaderField(WebString::FromUTF8("Accept-Ranges"),
+ WebString::FromUTF8("bytes"));
+ }
+
+ response.SetHttpStatusCode(kHttpPartialContent);
+ loader_->DidReceiveResponse(response);
+
+ EXPECT_EQ(instance_size, url_data_->length());
+
+ // A valid partial response should always result in this being true.
+ EXPECT_TRUE(url_data_->range_supported());
+ }
+
+ void Redirect(const char* url) {
+ WebURL new_url{GURL(url)};
+ WebURLResponse redirect_response(gurl_);
+
+ EXPECT_CALL(*this, RedirectCallback(_))
+ .WillOnce(
+ Invoke(this, &ResourceMultiBufferDataProviderTest::SetUrlData));
+
+ loader_->WillFollowRedirect(new_url, redirect_response);
+
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void StopWhenLoad() {
+ loader_ = nullptr;
+ url_data_ = nullptr;
+ }
+
+ // Helper method to write to |loader_| from |data_|.
+ void WriteLoader(int position, int size) {
+ loader_->DidReceiveData(reinterpret_cast<char*>(data_ + position), size);
+ }
+
+ void WriteData(int size) {
+ std::unique_ptr<char[]> data(new char[size]);
+ loader_->DidReceiveData(data.get(), size);
+ }
+
+ // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size].
+ void VerifyBuffer(uint8_t* buffer, int pos, int size) {
+ EXPECT_EQ(0, memcmp(buffer, data_ + pos, size));
+ }
+
+ MOCK_METHOD1(RedirectCallback, void(const scoped_refptr<UrlData>&));
+
+ void SetUrlData(const scoped_refptr<UrlData>& new_url_data) {
+ url_data_ = new_url_data;
+ }
+
+ protected:
+ std::unique_ptr<WebAssociatedURLLoader> CreateUrlLoader(
+ const WebAssociatedURLLoaderOptions& options) {
+ auto url_loader = std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
+ EXPECT_CALL(*url_loader.get(),
+ LoadAsynchronously(Truly(CorrectAcceptEncodingAndPreviewsState),
+ loader_));
+ return url_loader;
+ }
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ GURL gurl_;
+ int64_t first_position_;
+
+ NiceMock<MockResourceFetchContext> fetch_context_;
+ UrlIndex url_index_{&fetch_context_, 0,
+ task_environment_.GetMainThreadTaskRunner()};
+ scoped_refptr<UrlData> url_data_;
+ scoped_refptr<UrlData> redirected_to_;
+ // The loader is owned by the UrlData above.
+ ResourceMultiBufferDataProvider* loader_;
+
+ uint8_t data_[kDataSize];
+};
+
+TEST_F(ResourceMultiBufferDataProviderTest, StartStop) {
+ Initialize(kHttpUrl, 0);
+ Start();
+ StopWhenLoad();
+}
+
+// Tests that a bad HTTP response is recived, e.g. file not found.
+TEST_F(ResourceMultiBufferDataProviderTest, BadHttpResponse) {
+ Initialize(kHttpUrl, 0);
+ Start();
+
+ EXPECT_CALL(*this, RedirectCallback(scoped_refptr<UrlData>(nullptr)));
+
+ WebURLResponse response(gurl_);
+ response.SetHttpStatusCode(404);
+ response.SetHttpStatusText("Not Found\n");
+ loader_->DidReceiveResponse(response);
+}
+
+// Tests that partial content is requested but not fulfilled.
+TEST_F(ResourceMultiBufferDataProviderTest, NotPartialResponse) {
+ Initialize(kHttpUrl, 100);
+ Start();
+ FullResponse(1024, false);
+}
+
+// Tests that a 200 response is received.
+TEST_F(ResourceMultiBufferDataProviderTest, FullResponse) {
+ Initialize(kHttpUrl, 0);
+ Start();
+ FullResponse(1024);
+ StopWhenLoad();
+}
+
+// Tests that a partial content response is received.
+TEST_F(ResourceMultiBufferDataProviderTest, PartialResponse) {
+ Initialize(kHttpUrl, 100);
+ Start();
+ PartialResponse(100, 200, 1024);
+ StopWhenLoad();
+}
+
+TEST_F(ResourceMultiBufferDataProviderTest, PartialResponse_Chunked) {
+ Initialize(kHttpUrl, 100);
+ Start();
+ PartialResponse(100, 200, 1024, true, true);
+ StopWhenLoad();
+}
+
+TEST_F(ResourceMultiBufferDataProviderTest, PartialResponse_NoAcceptRanges) {
+ Initialize(kHttpUrl, 100);
+ Start();
+ PartialResponse(100, 200, 1024, false, false);
+ StopWhenLoad();
+}
+
+TEST_F(ResourceMultiBufferDataProviderTest,
+ PartialResponse_ChunkedNoAcceptRanges) {
+ Initialize(kHttpUrl, 100);
+ Start();
+ PartialResponse(100, 200, 1024, true, false);
+ StopWhenLoad();
+}
+
+// Tests that an invalid partial response is received.
+TEST_F(ResourceMultiBufferDataProviderTest, InvalidPartialResponse) {
+ Initialize(kHttpUrl, 0);
+ Start();
+
+ EXPECT_CALL(*this, RedirectCallback(scoped_refptr<UrlData>(nullptr)));
+
+ WebURLResponse response(gurl_);
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Range"),
+ WebString::FromUTF8(base::StringPrintf("bytes "
+ "%d-%d/%d",
+ 1, 10, 1024)));
+ response.SetExpectedContentLength(10);
+ response.SetHttpStatusCode(kHttpPartialContent);
+ loader_->DidReceiveResponse(response);
+}
+
+TEST_F(ResourceMultiBufferDataProviderTest, TestRedirects) {
+ // Test redirect.
+ Initialize(kHttpUrl, 0);
+ Start();
+ Redirect(kHttpRedirect);
+ FullResponse(1024);
+ StopWhenLoad();
+}
+
+// Tests partial response after a redirect.
+TEST_F(ResourceMultiBufferDataProviderTest, TestRedirectedPartialResponse) {
+ Initialize(kHttpUrl, 0);
+ Start();
+ PartialResponse(0, 2048, 32000);
+ Redirect(kHttpRedirect);
+ PartialResponse(2048, 4096, 32000);
+ StopWhenLoad();
+}
+
+TEST_F(ResourceMultiBufferDataProviderTest, TestSaveDataFRFRPreviewsState) {
+ struct TestCase {
+ std::string label;
+ bool enable_save_data;
+ std::string url;
+ bool want_frfr_previews_enabled;
+ };
+ const TestCase kTestCases[]{
+ {
+ "SaveData on, HTTP URL: FRFR previews state should exist.",
+ true,
+ kHttpUrl,
+ true,
+ },
+ {
+ "SaveData on, HTTPS URL: FRFR previews state should exist.",
+ true,
+ kHttpsUrl,
+ true,
+ },
+ {
+ "SaveData off, HTTP URL: FRFR previews state should not exist.",
+ false,
+ kHttpUrl,
+ false,
+ },
+ {
+ "SaveData off, HTTPS URL: FRFR previews state should not exist.",
+ false,
+ kHttpsUrl,
+ false,
+ },
+ };
+ for (const TestCase& test_case : kTestCases) {
+ SCOPED_TRACE(test_case.label);
+ WebNetworkStateNotifier::SetSaveDataEnabled(test_case.enable_save_data);
+
+ Initialize(test_case.url.c_str(), 0);
+ want_frfr = test_case.want_frfr_previews_enabled;
+
+ Start();
+ FullResponse(1024);
+ StopWhenLoad();
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/smoothness_helper.cc b/chromium/third_party/blink/renderer/platform/media/smoothness_helper.cc
new file mode 100644
index 00000000000..f8ede690c20
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/smoothness_helper.cc
@@ -0,0 +1,240 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/smoothness_helper.h"
+
+#include "base/bind.h"
+#include "base/timer/timer.h"
+#include "base/unguessable_token.h"
+#include "media/learning/common/learning_task_controller.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace blink {
+namespace {
+
+using ::media::learning::FeatureVector;
+using ::media::learning::LearningTaskController;
+using ::media::learning::TargetValue;
+
+static constexpr base::TimeDelta kSegmentSize =
+ base::TimeDelta::FromSeconds(5);
+
+// Maximum distance between NNRs for them to be consecutive.
+static constexpr base::TimeDelta kMaxNNRDistance =
+ base::TimeDelta::FromSeconds(60);
+
+// Max proportion of dropped frames in a window before we call it "not smooth".
+static constexpr float kMaxDroppedFramesPerWindow = 0.2;
+
+} // namespace
+
+// Monitor smoothness during a playback, and call back on each window.
+class SmoothnessWindowMonitor {
+ public:
+ using WindowCB = base::RepeatingCallback<void(int64_t dropped_frames,
+ int64_t decoded_frames)>;
+ SmoothnessWindowMonitor(SmoothnessHelper::Client* player, WindowCB cb)
+ : player_(player), cb_(std::move(cb)) {
+ segment_dropped_frames_ = player_->DroppedFrameCount();
+ segment_decoded_frames_ = player_->DecodedFrameCount();
+
+ update_timer_.Start(FROM_HERE, kSegmentSize,
+ base::BindRepeating(&SmoothnessWindowMonitor::OnTimer,
+ base::Unretained(this)));
+ }
+
+ ~SmoothnessWindowMonitor() = default;
+
+ // Split playback into segments of length |kSegmentSize|, and update the
+ // default value of the current playback.
+ void OnTimer() {
+ auto new_dropped_frames = player_->DroppedFrameCount();
+ auto dropped_frames = new_dropped_frames - segment_dropped_frames_;
+ segment_dropped_frames_ = new_dropped_frames;
+
+ auto new_decoded_frames = player_->DecodedFrameCount();
+ auto decoded_frames = new_decoded_frames - segment_decoded_frames_;
+ segment_decoded_frames_ = new_decoded_frames;
+
+ if (!decoded_frames)
+ return;
+
+ cb_.Run(dropped_frames, decoded_frames);
+ }
+
+ private:
+ SmoothnessHelper::Client* player_ = nullptr;
+ WindowCB cb_;
+ base::RepeatingTimer update_timer_;
+ // Current dropped, decoded frames at the start of the segment.
+ int64_t segment_decoded_frames_;
+ int64_t segment_dropped_frames_;
+};
+
+SmoothnessHelper::SmoothnessHelper(const FeatureVector& features)
+ : features_(features) {}
+
+SmoothnessHelper::~SmoothnessHelper() = default;
+
+class SmoothnessHelperImpl : public SmoothnessHelper {
+ public:
+ SmoothnessHelperImpl(
+ std::unique_ptr<LearningTaskController> consecutive_controller,
+ std::unique_ptr<LearningTaskController> nnr_controller,
+ const FeatureVector& features,
+ Client* player)
+ : SmoothnessHelper(features),
+ consecutive_bad_(std::move(consecutive_controller)),
+ consecutive_nnr_(std::move(nnr_controller)),
+ player_(player) {
+ monitor_ = std::make_unique<SmoothnessWindowMonitor>(
+ player_, base::BindRepeating(&SmoothnessHelperImpl::OnWindow,
+ base::Unretained(this)));
+ }
+
+ // This will ignore the last segment, if any, which is fine since it's not
+ // a complete segment. However, any in-progress observation will be completed
+ // with the default value if we've gotten enough data to set one.
+ ~SmoothnessHelperImpl() override = default;
+
+ // See if we've exceeded the intra-NNR distance, and reset everything. Note
+ // that this can be called even when there isn't an NNR.
+ void UpdateNNRWindow() {
+ if (!most_recent_nnr_)
+ return;
+
+ auto now = base::TimeTicks::Now();
+ auto delta = now - *most_recent_nnr_;
+ if (delta >= kMaxNNRDistance) {
+ most_recent_nnr_.reset();
+ num_consecutive_nnrs_ = 0;
+ }
+ }
+
+ void NotifyNNR() override {
+ UpdateNNRWindow();
+ most_recent_nnr_ = base::TimeTicks::Now();
+ num_consecutive_nnrs_++;
+
+ if (num_consecutive_nnrs_ > max_num_consecutive_nnrs_) {
+ max_num_consecutive_nnrs_ = num_consecutive_nnrs_;
+
+ // Insist that we've started the NNR instance, so that we enforce a
+ // minimum amount of playback time before recording anything. Though
+ // it's possible that an NNR is interesting enough to record it anyway,
+ // and we only want to elide zero-NNR observations for short playbacks.
+ if (consecutive_nnr_.is_started()) {
+ consecutive_nnr_.UpdateObservation(
+ features(), TargetValue(max_num_consecutive_nnrs_));
+ }
+ }
+ }
+
+ // Split playback into segments of length |kSegmentSize|, and update the
+ // default value of the current playback.
+ void OnWindow(int64_t dropped_frames, int64_t decoded_frames) {
+ // After the first window, start the NNR observation. We want to ignore any
+ // short playback windows. We might want to require more than one window.
+ // TODO(liberato): How many windows count as a playback for NNR?
+ if (!consecutive_nnr_.is_started()) {
+ UpdateNNRWindow();
+ consecutive_nnr_.UpdateObservation(
+ features(), TargetValue(max_num_consecutive_nnrs_));
+ }
+
+ // Compute the percentage of dropped frames for this window.
+ double pct = (static_cast<double>(dropped_frames)) / decoded_frames;
+
+ // Once we get one full window, default to 0 for the consecutive windows
+ // prediction task.
+ if (!consecutive_bad_.is_started())
+ consecutive_bad_.UpdateObservation(features(), TargetValue(0));
+
+ // If this is a bad window, extend the run of consecutive bad windows, and
+ // update the target value if this is a new longest run.
+ if (pct >= kMaxDroppedFramesPerWindow) {
+ consecutive_bad_windows_++;
+ if (consecutive_bad_windows_ > max_consecutive_bad_windows_) {
+ max_consecutive_bad_windows_ = consecutive_bad_windows_;
+ consecutive_bad_.UpdateObservation(
+ features(), TargetValue(max_consecutive_bad_windows_));
+ }
+ } else {
+ consecutive_bad_windows_ = 0;
+ // Don't update the target value, since any previous target value is still
+ // the max consecutive windows.
+ }
+ }
+
+ // Helper for different learning tasks.
+ struct Task {
+ Task(std::unique_ptr<LearningTaskController> controller)
+ : controller_(std::move(controller)) {}
+
+ Task(const Task&) = delete;
+ Task& operator=(const Task&) = delete;
+ ~Task() = default;
+
+ // Return true if and only if we've started an observation.
+ bool is_started() const { return !!id_; }
+
+ void UpdateObservation(const FeatureVector& features,
+ TargetValue current_target) {
+ target_value_ = current_target;
+ if (!is_started()) {
+ id_ = base::UnguessableToken::Create();
+ controller_->BeginObservation(*id_, features, target_value_);
+ } else {
+ controller_->UpdateDefaultTarget(*id_, target_value_);
+ }
+ }
+
+ const TargetValue& target_value() const { return target_value_; }
+
+ private:
+ // If an observation is in progress, then this is the id.
+ absl::optional<base::UnguessableToken> id_;
+ std::unique_ptr<LearningTaskController> controller_;
+ TargetValue target_value_;
+ };
+
+ // Struct to hold all of the "at least |n| consecutive bad windows" data.
+ struct Task consecutive_bad_;
+
+ int consecutive_bad_windows_ = 0;
+ int max_consecutive_bad_windows_ = 0;
+
+ struct Task consecutive_nnr_;
+
+ // Time of the most recent nnr.
+ absl::optional<base::TimeTicks> most_recent_nnr_;
+
+ // Number of NNRs that have occurred within |kMaxNNRDistance|.
+ int num_consecutive_nnrs_ = 0;
+
+ // Maximum value of |num_consecutive_nnrs_| that we've observed.
+ int max_num_consecutive_nnrs_ = 0;
+
+ // WebMediaPlayer which will tell us about the decoded / dropped frame counts.
+ Client* player_;
+
+ std::unique_ptr<SmoothnessWindowMonitor> monitor_;
+};
+
+// static
+std::unique_ptr<SmoothnessHelper> SmoothnessHelper::Create(
+ std::unique_ptr<LearningTaskController> bad_controller,
+ std::unique_ptr<LearningTaskController> nnr_controller,
+ const FeatureVector& features,
+ Client* player) {
+ return std::make_unique<SmoothnessHelperImpl>(
+ std::move(bad_controller), std::move(nnr_controller), features, player);
+}
+
+// static
+base::TimeDelta SmoothnessHelper::SegmentSizeForTesting() {
+ return kSegmentSize;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc
new file mode 100644
index 00000000000..c693c2f3d54
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc
@@ -0,0 +1,206 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/smoothness_helper.h"
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "media/learning/common/labelled_example.h"
+#include "media/learning/common/learning_task_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+using ::media::learning::FeatureValue;
+using ::media::learning::FeatureVector;
+using ::media::learning::LearningTask;
+using ::media::learning::LearningTaskController;
+using ::media::learning::ObservationCompletion;
+using ::media::learning::TargetValue;
+using ::testing::_;
+using ::testing::ResultOf;
+using ::testing::Return;
+
+// Helper for EXPECT_CALL argument matching on Optional<TargetValue>. Applies
+// matcher |m| to the TargetValue as a double. For example:
+// void Foo(absl::optional<TargetValue>);
+// EXPECT_CALL(..., Foo(OPT_TARGET(Gt(0.9)))) will expect that the value of the
+// Optional<TargetValue> passed to Foo() to be greather than 0.9 .
+#define OPT_TARGET(m) \
+ ResultOf([](const absl::optional<TargetValue>& v) { return (*v).value(); }, m)
+
+// Same as above, but expects an ObservationCompletion.
+#define COMPLETION_TARGET(m) \
+ ResultOf( \
+ [](const ObservationCompletion& x) { return x.target_value.value(); }, \
+ m)
+
+class SmoothnessHelperTest : public testing::Test {
+ class MockLearningTaskController : public LearningTaskController {
+ public:
+ MOCK_METHOD4(BeginObservation,
+ void(base::UnguessableToken id,
+ const FeatureVector& features,
+ const absl::optional<TargetValue>& default_target,
+ const absl::optional<ukm::SourceId>& source_id));
+
+ MOCK_METHOD2(CompleteObservation,
+ void(base::UnguessableToken id,
+ const ObservationCompletion& completion));
+
+ MOCK_METHOD1(CancelObservation, void(base::UnguessableToken id));
+
+ MOCK_METHOD2(UpdateDefaultTarget,
+ void(base::UnguessableToken id,
+ const absl::optional<TargetValue>& default_target));
+
+ MOCK_METHOD0(GetLearningTask, const LearningTask&());
+ MOCK_METHOD2(PredictDistribution,
+ void(const FeatureVector& features, PredictionCB callback));
+ };
+
+ class MockClient : public SmoothnessHelper::Client {
+ public:
+ ~MockClient() override = default;
+
+ MOCK_CONST_METHOD0(DecodedFrameCount, unsigned(void));
+ MOCK_CONST_METHOD0(DroppedFrameCount, unsigned(void));
+ };
+
+ public:
+ void SetUp() override {
+ auto bad_ltc = std::make_unique<MockLearningTaskController>();
+ bad_ltc_ = bad_ltc.get();
+ auto nnr_ltc = std::make_unique<MockLearningTaskController>();
+ nnr_ltc_ = nnr_ltc.get();
+ features_.push_back(FeatureValue(123));
+ helper_ = SmoothnessHelper::Create(std::move(bad_ltc), std::move(nnr_ltc),
+ features_, &client_);
+ segment_size_ = SmoothnessHelper::SegmentSizeForTesting();
+ }
+
+ // Helper for EXPECT_CALL.
+ absl::optional<TargetValue> Opt(double x) {
+ return absl::optional<TargetValue>(TargetValue(x));
+ }
+
+ void FastForwardBy(base::TimeDelta amount) {
+ task_environment_.FastForwardBy(amount);
+ }
+
+ // Set the dropped / decoded totals that will be returned by the mock client.
+ void SetFrameCounters(int dropped, int decoded) {
+ ON_CALL(client_, DroppedFrameCount()).WillByDefault(Return(dropped));
+ ON_CALL(client_, DecodedFrameCount()).WillByDefault(Return(decoded));
+ }
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ // Helper under test
+ std::unique_ptr<SmoothnessHelper> helper_;
+
+ // Max bad consecutive windows by frame drop LTC.
+ MockLearningTaskController* bad_ltc_;
+
+ // Max consecutive NNRs LTC.
+ MockLearningTaskController* nnr_ltc_;
+
+ MockClient client_;
+ FeatureVector features_;
+
+ base::TimeDelta segment_size_;
+};
+
+TEST_F(SmoothnessHelperTest, FeaturesAreReturned) {
+ EXPECT_EQ(features_, helper_->features());
+}
+
+TEST_F(SmoothnessHelperTest, MaxBadWindowsRecordsTrue) {
+ // Record three bad segments, and verify that it records 'true'.
+ SetFrameCounters(0, 0);
+ base::RunLoop().RunUntilIdle();
+ int dropped_frames = 0;
+ int total_frames = 0;
+
+ // First segment has no dropped frames. Should record 0.
+ EXPECT_CALL(*bad_ltc_, BeginObservation(_, _, OPT_TARGET(0.0), _)).Times(1);
+ SetFrameCounters(dropped_frames += 0, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // Second segment has a lot of dropped frames, so the target should increase.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(1.0))).Times(1);
+ SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // Third segment looks nice, so nothing should update.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_))).Times(0);
+ SetFrameCounters(dropped_frames += 0, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // Fourth segment has dropped frames, but the default shouldn't change.
+ // It's okay if it changes to the same value, but we just memorize that it
+ // won't change at all.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_))).Times(0);
+ SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // The last segment is also bad, and should increase the max.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(2.0))).Times(1);
+ SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+}
+
+TEST_F(SmoothnessHelperTest, NNRTaskRecordsMaxNNRs) {
+ // We should get the first target once a window has elapsed. We need some
+ // decoded frames before anything happens.
+ SetFrameCounters(0, 1);
+ EXPECT_CALL(*nnr_ltc_, BeginObservation(_, _, OPT_TARGET(0.0), _)).Times(1);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // Add some NNRs, which should be reported immediately now that a segment
+ // has started. Note that we don't care if NNRs are reported before a segment
+ // is started, because it's not really clear which behavior is right anyway.
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(1))).Times(1);
+ helper_->NotifyNNR();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // Advance time by one window, and add an NNR. It's close enough that we
+ // should be notified that the max went up.
+ FastForwardBy(segment_size_);
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(2))).Times(1);
+ helper_->NotifyNNR();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // Fast forward by a lot, so that the next NNR isn't consecutive. Nothing
+ // should be reported, because it's less than the current maximum.
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_))).Times(0);
+ FastForwardBy(base::TimeDelta::FromSeconds(1000));
+ helper_->NotifyNNR();
+ // It might be okay if this reported 2, since it's a tie.
+ helper_->NotifyNNR();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // The next NNR should advance the maximum to 3.
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(3))).Times(1);
+ helper_->NotifyNNR();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.cc b/chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.cc
new file mode 100644
index 00000000000..901f5e941d1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.cc
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h"
+
+namespace blink {
+
+MockResourceFetchContext::MockResourceFetchContext() = default;
+
+MockResourceFetchContext::~MockResourceFetchContext() = default;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h b/chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h
new file mode 100644
index 00000000000..90c312b31cf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/testing/mock_resource_fetch_context.h
@@ -0,0 +1,27 @@
+// 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_MEDIA_TESTING_MOCK_RESOURCE_FETCH_CONTEXT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TESTING_MOCK_RESOURCE_FETCH_CONTEXT_H_
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/platform/media/resource_fetch_context.h"
+
+namespace blink {
+
+class MockResourceFetchContext : public ResourceFetchContext {
+ public:
+ MockResourceFetchContext();
+ MockResourceFetchContext(const MockResourceFetchContext&) = delete;
+ MockResourceFetchContext& operator=(const MockResourceFetchContext&) = delete;
+ ~MockResourceFetchContext() override;
+
+ MOCK_METHOD1(CreateUrlLoader,
+ std::unique_ptr<WebAssociatedURLLoader>(
+ const WebAssociatedURLLoaderOptions&));
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TESTING_MOCK_RESOURCE_FETCH_CONTEXT_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.cc b/chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.cc
new file mode 100644
index 00000000000..b2cab132e20
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.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/platform/media/testing/mock_web_associated_url_loader.h"
+
+#include "third_party/blink/public/platform/web_data.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"
+
+namespace blink {
+
+MockWebAssociatedURLLoader::MockWebAssociatedURLLoader() = default;
+
+MockWebAssociatedURLLoader::~MockWebAssociatedURLLoader() = default;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h b/chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h
new file mode 100644
index 00000000000..faef0ecba02
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h
@@ -0,0 +1,33 @@
+// 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_MEDIA_TESTING_MOCK_WEB_ASSOCIATED_URL_LOADER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TESTING_MOCK_WEB_ASSOCIATED_URL_LOADER_H_
+
+#include "base/single_thread_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/web/web_associated_url_loader.h"
+
+namespace blink {
+
+class MockWebAssociatedURLLoader : public WebAssociatedURLLoader {
+ public:
+ MockWebAssociatedURLLoader();
+ MockWebAssociatedURLLoader(const MockWebAssociatedURLLoader&) = delete;
+ MockWebAssociatedURLLoader& operator=(const MockWebAssociatedURLLoader&) =
+ delete;
+ ~MockWebAssociatedURLLoader() override;
+
+ MOCK_METHOD2(LoadAsynchronously,
+ void(const WebURLRequest& request,
+ WebAssociatedURLLoaderClient* client));
+ MOCK_METHOD0(Cancel, void());
+ MOCK_METHOD1(SetDefersLoading, void(bool value));
+ MOCK_METHOD1(SetLoadingTaskRunner,
+ void(base::SingleThreadTaskRunner* task_runner));
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TESTING_MOCK_WEB_ASSOCIATED_URL_LOADER_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.cc b/chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.cc
new file mode 100644
index 00000000000..107bae56d7c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.cc
@@ -0,0 +1,107 @@
+// 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/media/testing/test_response_generator.h"
+
+#include "base/format_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "net/base/net_errors.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+namespace blink {
+
+TestResponseGenerator::TestResponseGenerator(const GURL& gurl,
+ int64_t content_length)
+ : gurl_(gurl), content_length_(content_length) {}
+
+WebURLError TestResponseGenerator::GenerateError() {
+ return WebURLError(net::ERR_ABORTED, WebURL());
+}
+
+WebURLResponse TestResponseGenerator::Generate200() {
+ WebURLResponse response(gurl_);
+ response.SetHttpStatusCode(200);
+
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Length"),
+ WebString::FromUTF8(base::NumberToString(content_length_)));
+ response.SetExpectedContentLength(content_length_);
+ return response;
+}
+
+WebURLResponse TestResponseGenerator::Generate206(int64_t first_byte_offset) {
+ return GeneratePartial206(first_byte_offset, content_length_ - 1, kNormal);
+}
+
+WebURLResponse TestResponseGenerator::Generate206(int64_t first_byte_offset,
+ Flags flags) {
+ return GeneratePartial206(first_byte_offset, content_length_ - 1, flags);
+}
+
+WebURLResponse TestResponseGenerator::GeneratePartial206(
+ int64_t first_byte_offset,
+ int64_t last_byte_offset) {
+ return GeneratePartial206(first_byte_offset, last_byte_offset, kNormal);
+}
+
+WebURLResponse TestResponseGenerator::GeneratePartial206(
+ int64_t first_byte_offset,
+ int64_t last_byte_offset,
+ Flags flags) {
+ int64_t range_content_length = content_length_ - first_byte_offset;
+
+ WebURLResponse response(gurl_);
+ response.SetHttpStatusCode(206);
+
+ if ((flags & kNoAcceptRanges) == 0) {
+ response.SetHttpHeaderField(WebString::FromUTF8("Accept-Ranges"),
+ WebString::FromUTF8("bytes"));
+ }
+
+ if ((flags & kNoContentRange) == 0) {
+ std::string content_range = base::StringPrintf(
+ "bytes %" PRId64 "-%" PRId64 "/",
+ first_byte_offset, last_byte_offset);
+ if (flags & kNoContentRangeInstanceSize)
+ content_range += "*";
+ else
+ content_range += base::StringPrintf("%" PRId64, content_length_);
+ response.SetHttpHeaderField(WebString::FromUTF8("Content-Range"),
+ WebString::FromUTF8(content_range));
+ }
+
+ if ((flags & kNoContentLength) == 0) {
+ response.SetHttpHeaderField(
+ WebString::FromUTF8("Content-Length"),
+ WebString::FromUTF8(base::NumberToString(range_content_length)));
+ response.SetExpectedContentLength(range_content_length);
+ }
+ return response;
+}
+
+WebURLResponse TestResponseGenerator::GenerateResponse(int code) {
+ WebURLResponse response(gurl_);
+ response.SetHttpStatusCode(code);
+ return response;
+}
+
+WebURLResponse TestResponseGenerator::Generate404() {
+ return GenerateResponse(404);
+}
+
+WebURLResponse TestResponseGenerator::GenerateFileResponse(
+ int64_t first_byte_offset) {
+ WebURLResponse response(gurl_);
+ response.SetHttpStatusCode(0);
+
+ if (first_byte_offset >= 0) {
+ response.SetExpectedContentLength(content_length_ - first_byte_offset);
+ } else {
+ response.SetExpectedContentLength(-1);
+ }
+ return response;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.h b/chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.h
new file mode 100644
index 00000000000..5152648f224
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/testing/test_response_generator.h
@@ -0,0 +1,82 @@
+// 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_MEDIA_TESTING_TEST_RESPONSE_GENERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TESTING_TEST_RESPONSE_GENERATOR_H_
+
+#include <stdint.h>
+
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+// Generates WebURLErrors and WebURLResponses suitable for testing purposes.
+class TestResponseGenerator {
+ public:
+ enum Flags {
+ kNormal = 0,
+ kNoAcceptRanges = 1 << 0, // Don't include Accept-Ranges in 206 response.
+ kNoContentRange = 1 << 1, // Don't include Content-Range in 206 response.
+ kNoContentLength = 1 << 2, // Don't include Content-Length in 206 response.
+ kNoContentRangeInstanceSize = 1 << 3, // Content-Range: N-M/* in 206.
+ };
+
+ // Build an HTTP response generator for the given URL. |content_length| is
+ // used to generate Content-Length and Content-Range headers.
+ TestResponseGenerator(const GURL& gurl, int64_t content_length);
+ TestResponseGenerator(const TestResponseGenerator&) = delete;
+ TestResponseGenerator& operator=(const TestResponseGenerator&) = delete;
+
+ // Generates a WebURLError object.
+ WebURLError GenerateError();
+
+ // Generates a regular HTTP 200 response.
+ WebURLResponse Generate200();
+
+ // Generates a regular HTTP 206 response starting from |first_byte_offset|
+ // until the end of the resource.
+ WebURLResponse Generate206(int64_t first_byte_offset);
+
+ // Generates a custom HTTP 206 response starting from |first_byte_offset|
+ // until the end of the resource. You can tweak what gets included in the
+ // headers via |flags|.
+ WebURLResponse Generate206(int64_t first_byte_offset, Flags flags);
+
+ // Generates a regular HTTP 206 response starting from |first_byte_offset|
+ // until |last_byte_offset|.
+ WebURLResponse GeneratePartial206(int64_t first_byte_offset,
+ int64_t last_byte_offset);
+
+ // Generates a custom HTTP 206 response starting from |first_byte_offset|
+ // until |last_byte_offset|. You can tweak what gets included in the
+ // headers via |flags|.
+ WebURLResponse GeneratePartial206(int64_t first_byte_offset,
+ int64_t last_byte_offset,
+ Flags flags);
+
+ // Generates a regular HTTP 404 response.
+ WebURLResponse Generate404();
+
+ // Generate a HTTP response with specified code.
+ WebURLResponse GenerateResponse(int code);
+
+ // Generates a file:// response starting from |first_byte_offset| until the
+ // end of the resource.
+ //
+ // If |first_byte_offset| is negative a response containing no content length
+ // will be returned.
+ WebURLResponse GenerateFileResponse(int64_t first_byte_offset);
+
+ int64_t content_length() { return content_length_; }
+
+ private:
+ GURL gurl_;
+ int64_t content_length_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TESTING_TEST_RESPONSE_GENERATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/text_track_impl.cc b/chromium/third_party/blink/renderer/platform/media/text_track_impl.cc
new file mode 100644
index 00000000000..f6661c0312b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/text_track_impl.cc
@@ -0,0 +1,65 @@
+// 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/media/text_track_impl.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "media/base/bind_to_current_loop.h"
+#include "third_party/blink/public/platform/web_inband_text_track_client.h"
+#include "third_party/blink/public/platform/web_media_player_client.h"
+#include "third_party/blink/renderer/platform/media/web_inband_text_track_impl.h"
+
+namespace blink {
+
+TextTrackImpl::TextTrackImpl(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ WebMediaPlayerClient* client,
+ std::unique_ptr<WebInbandTextTrackImpl> text_track)
+ : task_runner_(task_runner),
+ client_(client),
+ text_track_(std::move(text_track)) {
+ client_->AddTextTrack(text_track_.get());
+}
+
+TextTrackImpl::~TextTrackImpl() {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&TextTrackImpl::OnRemoveTrack, client_,
+ std::move(text_track_)));
+}
+
+void TextTrackImpl::addWebVTTCue(base::TimeDelta start,
+ base::TimeDelta end,
+ const std::string& id,
+ const std::string& content,
+ const std::string& settings) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&TextTrackImpl::OnAddCue, text_track_.get(),
+ start, end, id, content, settings));
+}
+
+void TextTrackImpl::OnAddCue(WebInbandTextTrackImpl* text_track,
+ base::TimeDelta start,
+ base::TimeDelta end,
+ const std::string& id,
+ const std::string& content,
+ const std::string& settings) {
+ if (WebInbandTextTrackClient* client = text_track->Client()) {
+ client->AddWebVTTCue(start.InSecondsF(), end.InSecondsF(),
+ WebString::FromUTF8(id), WebString::FromUTF8(content),
+ WebString::FromUTF8(settings));
+ }
+}
+
+void TextTrackImpl::OnRemoveTrack(
+ WebMediaPlayerClient* client,
+ std::unique_ptr<WebInbandTextTrackImpl> text_track) {
+ if (text_track->Client())
+ client->RemoveTextTrack(text_track.get());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/text_track_impl.h b/chromium/third_party/blink/renderer/platform/media/text_track_impl.h
new file mode 100644
index 00000000000..31bf37cf6f6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/text_track_impl.h
@@ -0,0 +1,57 @@
+// 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_MEDIA_TEXT_TRACK_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TEXT_TRACK_IMPL_H_
+
+#include <memory>
+#include <string>
+
+#include "media/base/text_track.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+class WebInbandTextTrackImpl;
+class WebMediaPlayerClient;
+
+class PLATFORM_EXPORT TextTrackImpl : public media::TextTrack {
+ public:
+ // Constructor assumes ownership of the |text_track| object.
+ TextTrackImpl(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ WebMediaPlayerClient* client,
+ std::unique_ptr<WebInbandTextTrackImpl> text_track);
+
+ TextTrackImpl(const TextTrackImpl&) = delete;
+ TextTrackImpl& operator=(const TextTrackImpl&) = delete;
+ ~TextTrackImpl() override;
+
+ void addWebVTTCue(base::TimeDelta start,
+ base::TimeDelta end,
+ const std::string& id,
+ const std::string& content,
+ const std::string& settings) override;
+
+ private:
+ static void OnAddCue(WebInbandTextTrackImpl* text_track,
+ base::TimeDelta start,
+ base::TimeDelta end,
+ const std::string& id,
+ const std::string& content,
+ const std::string& settings);
+
+ static void OnRemoveTrack(WebMediaPlayerClient* client,
+ std::unique_ptr<WebInbandTextTrackImpl> text_track);
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ WebMediaPlayerClient* client_;
+ std::unique_ptr<WebInbandTextTrackImpl> text_track_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_TEXT_TRACK_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/url_index.cc b/chromium/third_party/blink/renderer/platform/media/url_index.cc
new file mode 100644
index 00000000000..6d1cc9ef3db
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/url_index.cc
@@ -0,0 +1,340 @@
+// 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/platform/media/url_index.h"
+
+#include <set>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
+#include "media/base/media_switches.h"
+#include "third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.h"
+
+namespace blink {
+
+const int kBlockSizeShift = 15; // 1<<15 == 32kb
+const int kUrlMappingTimeoutSeconds = 300;
+
+ResourceMultiBuffer::ResourceMultiBuffer(
+ UrlData* url_data,
+ int block_shift,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : MultiBuffer(block_shift, url_data->url_index_->lru_),
+ url_data_(url_data),
+ task_runner_(std::move(task_runner)) {}
+
+ResourceMultiBuffer::~ResourceMultiBuffer() = default;
+
+std::unique_ptr<MultiBuffer::DataProvider> ResourceMultiBuffer::CreateWriter(
+ const MultiBufferBlockId& pos,
+ bool is_client_audio_element) {
+ auto writer = std::make_unique<ResourceMultiBufferDataProvider>(
+ url_data_, pos, is_client_audio_element, task_runner_);
+ writer->Start();
+ return writer;
+}
+
+bool ResourceMultiBuffer::RangeSupported() const {
+ return url_data_->range_supported_;
+}
+
+void ResourceMultiBuffer::OnEmpty() {
+ url_data_->OnEmpty();
+}
+
+UrlData::UrlData(const GURL& url,
+ CorsMode cors_mode,
+ UrlIndex* url_index,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : url_(url),
+ have_data_origin_(false),
+ cors_mode_(cors_mode),
+ has_access_control_(false),
+ url_index_(url_index),
+ length_(kPositionNotSpecified),
+ range_supported_(false),
+ cacheable_(false),
+ multibuffer_(this, url_index_->block_shift_, std::move(task_runner)) {}
+
+UrlData::~UrlData() = default;
+
+std::pair<GURL, UrlData::CorsMode> UrlData::key() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return std::make_pair(url(), cors_mode());
+}
+
+void UrlData::set_valid_until(base::Time valid_until) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ valid_until_ = valid_until;
+}
+
+void UrlData::MergeFrom(const scoped_refptr<UrlData>& other) {
+ // We're merging from another UrlData that refers to the *same*
+ // resource, so when we merge the metadata, we can use the most
+ // optimistic values.
+ if (ValidateDataOrigin(other->data_origin_)) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ valid_until_ = std::max(valid_until_, other->valid_until_);
+ // set_length() will not override the length if already known.
+ set_length(other->length_);
+ cacheable_ |= other->cacheable_;
+ range_supported_ |= other->range_supported_;
+ if (last_modified_.is_null()) {
+ last_modified_ = other->last_modified_;
+ }
+ bytes_read_from_cache_ += other->bytes_read_from_cache_;
+ // is_cors_corss_origin_ will not relax from true to false.
+ set_is_cors_cross_origin(other->is_cors_cross_origin_);
+ has_access_control_ |= other->has_access_control_;
+ multibuffer()->MergeFrom(other->multibuffer());
+ }
+}
+
+void UrlData::set_cacheable(bool cacheable) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ cacheable_ = cacheable;
+}
+
+void UrlData::set_length(int64_t length) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (length != kPositionNotSpecified) {
+ length_ = length;
+ }
+}
+
+void UrlData::set_is_cors_cross_origin(bool is_cors_cross_origin) {
+ if (is_cors_cross_origin_)
+ return;
+ is_cors_cross_origin_ = is_cors_cross_origin;
+}
+
+void UrlData::set_has_access_control() {
+ has_access_control_ = true;
+}
+
+void UrlData::RedirectTo(const scoped_refptr<UrlData>& url_data) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // Copy any cached data over to the new location.
+ url_data->multibuffer()->MergeFrom(multibuffer());
+
+ std::vector<RedirectCB> redirect_callbacks;
+ redirect_callbacks.swap(redirect_callbacks_);
+ for (RedirectCB& cb : redirect_callbacks) {
+ std::move(cb).Run(url_data);
+ }
+}
+
+void UrlData::Fail() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // Handled similar to a redirect.
+ std::vector<RedirectCB> redirect_callbacks;
+ redirect_callbacks.swap(redirect_callbacks_);
+ for (RedirectCB& cb : redirect_callbacks) {
+ std::move(cb).Run(nullptr);
+ }
+}
+
+void UrlData::OnRedirect(RedirectCB cb) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ redirect_callbacks_.push_back(std::move(cb));
+}
+
+void UrlData::Use() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ last_used_ = base::Time::Now();
+}
+
+bool UrlData::ValidateDataOrigin(const GURL& origin) {
+ if (!have_data_origin_) {
+ data_origin_ = origin;
+ have_data_origin_ = true;
+ return true;
+ }
+ if (cors_mode_ == UrlData::CORS_UNSPECIFIED) {
+ return data_origin_ == origin;
+ }
+ // The actual cors checks is done in the net layer.
+ return true;
+}
+
+void UrlData::OnEmpty() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ url_index_->RemoveUrlData(this);
+}
+
+bool UrlData::FullyCached() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (length_ == kPositionNotSpecified)
+ return false;
+ // Check that the first unavailable block in the cache is after the
+ // end of the file.
+ return (multibuffer()->FindNextUnavailable(0) << kBlockSizeShift) >= length_;
+}
+
+bool UrlData::Valid() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ base::Time now = base::Time::Now();
+ if (!range_supported_ && !FullyCached())
+ return false;
+ // When ranges are not supported, we cannot re-use cached data.
+ if (valid_until_ > now)
+ return true;
+ if (now - last_used_ <
+ base::TimeDelta::FromSeconds(kUrlMappingTimeoutSeconds))
+ return true;
+ return false;
+}
+
+void UrlData::set_last_modified(base::Time last_modified) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ last_modified_ = last_modified;
+}
+
+void UrlData::set_etag(const std::string& etag) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ etag_ = etag;
+}
+
+void UrlData::set_range_supported() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ range_supported_ = true;
+}
+
+ResourceMultiBuffer* UrlData::multibuffer() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return &multibuffer_;
+}
+
+size_t UrlData::CachedSize() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return multibuffer()->map().size();
+}
+
+UrlIndex::UrlIndex(ResourceFetchContext* fetch_context,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : UrlIndex(fetch_context, kBlockSizeShift, std::move(task_runner)) {}
+
+UrlIndex::UrlIndex(ResourceFetchContext* fetch_context,
+ int block_shift,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : fetch_context_(fetch_context),
+ lru_(new MultiBuffer::GlobalLRU(task_runner)),
+ block_shift_(block_shift),
+ memory_pressure_listener_(FROM_HERE,
+ base::BindRepeating(&UrlIndex::OnMemoryPressure,
+ base::Unretained(this))),
+ task_runner_(std::move(task_runner)) {}
+
+UrlIndex::~UrlIndex() {
+#if DCHECK_IS_ON()
+ // Verify that only |this| holds reference to UrlData instances.
+ auto dcheck_has_one_ref = [](const UrlDataMap::value_type& entry) {
+ DCHECK(entry.second->HasOneRef());
+ };
+ std::for_each(indexed_data_.begin(), indexed_data_.end(), dcheck_has_one_ref);
+#endif
+}
+
+void UrlIndex::RemoveUrlData(const scoped_refptr<UrlData>& url_data) {
+ DCHECK(url_data->multibuffer()->map().empty());
+
+ auto i = indexed_data_.find(url_data->key());
+ if (i != indexed_data_.end() && i->second == url_data)
+ indexed_data_.erase(i);
+}
+
+scoped_refptr<UrlData> UrlIndex::GetByUrl(const GURL& gurl,
+ UrlData::CorsMode cors_mode,
+ CacheMode cache_mode) {
+ if (cache_mode == kNormal) {
+ auto i = indexed_data_.find(std::make_pair(gurl, cors_mode));
+ if (i != indexed_data_.end() && i->second->Valid()) {
+ return i->second;
+ }
+ }
+
+ return NewUrlData(gurl, cors_mode);
+}
+
+scoped_refptr<UrlData> UrlIndex::NewUrlData(const GURL& url,
+ UrlData::CorsMode cors_mode) {
+ return new UrlData(url, cors_mode, this, task_runner_);
+}
+
+void UrlIndex::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+ switch (memory_pressure_level) {
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+ lru_->TryFree(128); // try to free 128 32kb blocks if possible
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+ lru_->TryFreeAll(); // try to free as many blocks as possible
+ break;
+ }
+}
+
+namespace {
+bool IsStrongEtag(const std::string& etag) {
+ return etag.size() > 2 && etag[0] == '"';
+}
+
+bool IsNewDataForSameResource(const scoped_refptr<UrlData>& new_entry,
+ const scoped_refptr<UrlData>& old_entry) {
+ if (IsStrongEtag(new_entry->etag()) && IsStrongEtag(old_entry->etag())) {
+ if (new_entry->etag() != old_entry->etag())
+ return true;
+ }
+ if (!new_entry->last_modified().is_null()) {
+ if (new_entry->last_modified() != old_entry->last_modified())
+ return true;
+ }
+ return false;
+}
+} // namespace
+
+scoped_refptr<UrlData> UrlIndex::TryInsert(
+ const scoped_refptr<UrlData>& url_data) {
+ auto iter = indexed_data_.find(url_data->key());
+ if (iter == indexed_data_.end()) {
+ // If valid and not already indexed, index it.
+ if (url_data->Valid()) {
+ indexed_data_.insert(iter, std::make_pair(url_data->key(), url_data));
+ }
+ return url_data;
+ }
+
+ // A UrlData instance for the same key is already indexed.
+
+ // If the indexed instance is the same as |url_data|,
+ // nothing needs to be done.
+ if (iter->second == url_data)
+ return url_data;
+
+ // The indexed instance is different.
+ // Check if it should be replaced with |url_data|.
+ if (IsNewDataForSameResource(url_data, iter->second)) {
+ if (url_data->Valid()) {
+ iter->second = url_data;
+ }
+ return url_data;
+ }
+
+ if (url_data->Valid()) {
+ if ((!iter->second->Valid() ||
+ url_data->CachedSize() > iter->second->CachedSize())) {
+ iter->second = url_data;
+ } else {
+ iter->second->MergeFrom(url_data);
+ }
+ }
+ return iter->second;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/url_index_unittest.cc b/chromium/third_party/blink/renderer/platform/media/url_index_unittest.cc
new file mode 100644
index 00000000000..094f1cdb07c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/url_index_unittest.cc
@@ -0,0 +1,179 @@
+// 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/platform/media/url_index.h"
+
+#include <stdint.h>
+
+#include <list>
+#include <string>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/task_environment.h"
+#include "media/base/media_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class UrlIndexTest : public testing::Test {
+ public:
+ UrlIndexTest() = default;
+
+ scoped_refptr<UrlData> GetByUrl(const GURL& gurl,
+ UrlData::CorsMode cors_mode) {
+ scoped_refptr<UrlData> ret =
+ url_index_.GetByUrl(gurl, cors_mode, UrlIndex::kNormal);
+ EXPECT_EQ(ret->url(), gurl);
+ EXPECT_EQ(ret->cors_mode(), cors_mode);
+ return ret;
+ }
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ UrlIndex url_index_{nullptr, task_environment_.GetMainThreadTaskRunner()};
+};
+
+TEST_F(UrlIndexTest, SimpleTest) {
+ GURL url1("http://foo.bar.com");
+ GURL url2("http://foo.bar.com/urgel");
+ scoped_refptr<UrlData> a = GetByUrl(url1, UrlData::CORS_UNSPECIFIED);
+ // Make sure it's valid, we still shouldn't get the same one.
+ a->Use();
+ a->set_range_supported();
+ EXPECT_TRUE(a->Valid());
+ EXPECT_EQ(a, url_index_.TryInsert(a));
+ scoped_refptr<UrlData> b = GetByUrl(url1, UrlData::CORS_ANONYMOUS);
+ b->Use();
+ b->set_range_supported();
+ EXPECT_TRUE(b->Valid());
+ EXPECT_EQ(b, url_index_.TryInsert(b));
+ scoped_refptr<UrlData> c = GetByUrl(url1, UrlData::CORS_USE_CREDENTIALS);
+ c->Use();
+ c->set_range_supported();
+ EXPECT_TRUE(c->Valid());
+ EXPECT_EQ(c, url_index_.TryInsert(c));
+ scoped_refptr<UrlData> d = GetByUrl(url2, UrlData::CORS_UNSPECIFIED);
+ d->Use();
+ d->set_range_supported();
+ EXPECT_TRUE(d->Valid());
+ EXPECT_EQ(d, url_index_.TryInsert(d));
+
+ EXPECT_NE(a, b);
+ EXPECT_NE(a, c);
+ EXPECT_NE(a, d);
+ EXPECT_NE(b, c);
+ EXPECT_NE(b, d);
+ EXPECT_NE(c, d);
+ EXPECT_EQ(a, GetByUrl(url1, UrlData::CORS_UNSPECIFIED));
+ EXPECT_EQ(b, GetByUrl(url1, UrlData::CORS_ANONYMOUS));
+ EXPECT_EQ(c, GetByUrl(url1, UrlData::CORS_USE_CREDENTIALS));
+ EXPECT_EQ(d, GetByUrl(url2, UrlData::CORS_UNSPECIFIED));
+}
+
+TEST_F(UrlIndexTest, UrlDataTest) {
+ GURL url("http://foo.bar.com");
+ scoped_refptr<UrlData> a = GetByUrl(url, UrlData::CORS_UNSPECIFIED);
+
+ // Check default values.
+ EXPECT_FALSE(a->range_supported());
+ EXPECT_FALSE(a->cacheable());
+ EXPECT_EQ(a->length(), kPositionNotSpecified);
+ EXPECT_FALSE(a->Valid());
+
+ a->set_length(117);
+ EXPECT_EQ(a->length(), 117);
+
+ a->set_cacheable(true);
+ EXPECT_TRUE(a->cacheable());
+
+ base::Time now = base::Time::Now();
+ base::Time valid_until = now + base::TimeDelta::FromSeconds(500);
+ a->set_valid_until(valid_until);
+ a->set_range_supported();
+ EXPECT_EQ(valid_until, a->valid_until());
+ EXPECT_TRUE(a->Valid());
+
+ base::Time last_modified = now - base::TimeDelta::FromSeconds(500);
+ a->set_last_modified(last_modified);
+ EXPECT_EQ(last_modified, a->last_modified());
+}
+
+TEST_F(UrlIndexTest, UseTest) {
+ GURL url("http://foo.bar.com");
+ scoped_refptr<UrlData> a = GetByUrl(url, UrlData::CORS_UNSPECIFIED);
+ EXPECT_FALSE(a->Valid());
+ a->Use();
+ a->set_range_supported();
+ EXPECT_TRUE(a->Valid());
+}
+
+TEST_F(UrlIndexTest, TryInsert) {
+ GURL url("http://foo.bar.com");
+ scoped_refptr<UrlData> a = GetByUrl(url, UrlData::CORS_UNSPECIFIED);
+ scoped_refptr<UrlData> c = GetByUrl(url, UrlData::CORS_UNSPECIFIED);
+ EXPECT_NE(a, c);
+ EXPECT_FALSE(a->Valid());
+ base::Time now = base::Time::Now();
+ base::Time last_modified = now - base::TimeDelta::FromSeconds(500);
+ base::Time valid_until = now + base::TimeDelta::FromSeconds(500);
+
+ // Not sharable yet. (no ranges)
+ EXPECT_EQ(a, url_index_.TryInsert(a));
+ EXPECT_NE(a, GetByUrl(url, UrlData::CORS_UNSPECIFIED));
+ a->set_last_modified(last_modified);
+
+ // Not sharable yet. (no ranges)
+ EXPECT_EQ(a, url_index_.TryInsert(a));
+ EXPECT_NE(a, GetByUrl(url, UrlData::CORS_UNSPECIFIED));
+
+ // Now we should be able to insert it into the index.
+ a->set_range_supported();
+ a->set_valid_until(valid_until);
+ EXPECT_TRUE(a->Valid());
+ EXPECT_EQ(a, url_index_.TryInsert(a));
+ EXPECT_EQ(a, GetByUrl(url, UrlData::CORS_UNSPECIFIED));
+
+ // |a| becomes expired...
+ a->set_valid_until(now - base::TimeDelta::FromSeconds(100));
+ EXPECT_FALSE(a->Valid());
+ scoped_refptr<UrlData> b = GetByUrl(url, UrlData::CORS_UNSPECIFIED);
+ EXPECT_NE(a, b);
+
+ b->set_range_supported();
+ b->set_valid_until(valid_until);
+ b->set_last_modified(last_modified);
+ EXPECT_TRUE(b->Valid());
+
+ EXPECT_EQ(b, url_index_.TryInsert(b));
+ EXPECT_EQ(b, GetByUrl(url, UrlData::CORS_UNSPECIFIED));
+
+ c->set_range_supported();
+ c->set_valid_until(valid_until);
+ c->set_last_modified(last_modified);
+ EXPECT_TRUE(c->Valid());
+
+ // B is still valid, so it should be preferred over C.
+ EXPECT_EQ(b, url_index_.TryInsert(c));
+ EXPECT_EQ(b, GetByUrl(url, UrlData::CORS_UNSPECIFIED));
+}
+
+TEST_F(UrlIndexTest, GetByUrlCacheDisabled) {
+ GURL url("http://foo.bar.com");
+ UrlData::CorsMode cors = UrlData::CORS_UNSPECIFIED;
+
+ scoped_refptr<UrlData> url_data =
+ url_index_.GetByUrl(url, cors, UrlIndex::kNormal);
+ url_data->Use();
+ url_data->set_range_supported();
+ EXPECT_TRUE(url_data->Valid());
+ url_index_.TryInsert(url_data);
+
+ EXPECT_EQ(url_data, url_index_.GetByUrl(url, cors, UrlIndex::kNormal));
+ EXPECT_NE(url_data, url_index_.GetByUrl(url, cors, UrlIndex::kCacheDisabled));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.cc b/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.cc
new file mode 100644
index 00000000000..25a1a1cd686
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.cc
@@ -0,0 +1,332 @@
+// 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/media/video_decode_stats_reporter.h"
+
+#include <cmath>
+#include <limits>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "media/capabilities/bucket_utility.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+
+namespace blink {
+
+VideoDecodeStatsReporter::VideoDecodeStatsReporter(
+ mojo::PendingRemote<media::mojom::VideoDecodeStatsRecorder> recorder_remote,
+ GetPipelineStatsCB get_pipeline_stats_cb,
+ media::VideoCodecProfile codec_profile,
+ const gfx::Size& natural_size,
+ std::string key_system,
+ absl::optional<media::CdmConfig> cdm_config,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const base::TickClock* tick_clock)
+ : kRecordingInterval(
+ base::TimeDelta::FromMilliseconds(kRecordingIntervalMs)),
+ kTinyFpsWindowDuration(
+ base::TimeDelta::FromMilliseconds(kTinyFpsWindowMs)),
+ recorder_remote_(std::move(recorder_remote)),
+ get_pipeline_stats_cb_(std::move(get_pipeline_stats_cb)),
+ codec_profile_(codec_profile),
+ natural_size_(media::GetSizeBucket(natural_size)),
+ key_system_(key_system),
+ use_hw_secure_codecs_(cdm_config ? cdm_config->use_hw_secure_codecs
+ : false),
+ tick_clock_(tick_clock),
+ stats_cb_timer_(tick_clock_) {
+ DCHECK(recorder_remote_.is_bound());
+ DCHECK(get_pipeline_stats_cb_);
+ DCHECK_NE(media::VIDEO_CODEC_PROFILE_UNKNOWN, codec_profile_);
+ DCHECK(!cdm_config || !key_system_.empty());
+
+ recorder_remote_.set_disconnect_handler(base::BindOnce(
+ &VideoDecodeStatsReporter::OnIpcConnectionError, base::Unretained(this)));
+ stats_cb_timer_.SetTaskRunner(task_runner);
+}
+
+VideoDecodeStatsReporter::~VideoDecodeStatsReporter() = default;
+
+void VideoDecodeStatsReporter::OnPlaying() {
+ DVLOG(2) << __func__;
+
+ if (is_playing_)
+ return;
+ is_playing_ = true;
+
+ DCHECK(!stats_cb_timer_.IsRunning());
+
+ if (ShouldBeReporting()) {
+ RunStatsTimerAtInterval(kRecordingInterval);
+ }
+}
+
+void VideoDecodeStatsReporter::OnPaused() {
+ DVLOG(2) << __func__;
+
+ if (!is_playing_)
+ return;
+ is_playing_ = false;
+
+ // Stop timer until playing resumes.
+ stats_cb_timer_.AbandonAndStop();
+}
+
+void VideoDecodeStatsReporter::OnHidden() {
+ DVLOG(2) << __func__;
+
+ if (is_backgrounded_)
+ return;
+
+ is_backgrounded_ = true;
+
+ // Stop timer until no longer hidden.
+ stats_cb_timer_.AbandonAndStop();
+}
+
+void VideoDecodeStatsReporter::OnShown() {
+ DVLOG(2) << __func__;
+
+ if (!is_backgrounded_)
+ return;
+
+ is_backgrounded_ = false;
+
+ // Only start a new record below if stable FPS has been detected. If FPS is
+ // later detected, a new record will be started at that time.
+ if (num_stable_fps_samples_ >= kRequiredStableFpsSamples) {
+ // Dropped frames are not reported during background rendering. Start a new
+ // record to avoid reporting background stats.
+ media::PipelineStatistics stats = get_pipeline_stats_cb_.Run();
+ StartNewRecord(stats.video_frames_decoded, stats.video_frames_dropped,
+ stats.video_frames_decoded_power_efficient);
+ }
+
+ if (ShouldBeReporting())
+ RunStatsTimerAtInterval(kRecordingInterval);
+}
+
+bool VideoDecodeStatsReporter::MatchesBucketedNaturalSize(
+ const gfx::Size& natural_size) const {
+ // Stored natural size should always be bucketed.
+ DCHECK(natural_size_ == media::GetSizeBucket(natural_size_));
+ return media::GetSizeBucket(natural_size) == natural_size_;
+}
+
+void VideoDecodeStatsReporter::RunStatsTimerAtInterval(
+ base::TimeDelta interval) {
+ DVLOG(2) << __func__ << " " << interval.InMicroseconds() << " us";
+ DCHECK(ShouldBeReporting());
+
+ // NOTE: Avoid optimizing with early returns if the timer is already running
+ // at |milliseconds|. Calling Start below resets the timer clock and some
+ // callers (e.g. OnVideoConfigChanged) rely on that behavior behavior.
+ stats_cb_timer_.Start(FROM_HERE, interval, this,
+ &VideoDecodeStatsReporter::UpdateStats);
+}
+
+void VideoDecodeStatsReporter::StartNewRecord(
+ uint32_t frames_decoded_offset,
+ uint32_t frames_dropped_offset,
+ uint32_t frames_decoded_power_efficient_offset) {
+ DVLOG(2) << __func__ << " "
+ << " profile:" << codec_profile_
+ << " size:" << natural_size_.ToString()
+ << " fps:" << last_observed_fps_ << " key_system:" << key_system_
+ << " use_hw_secure_codecs:" << use_hw_secure_codecs_;
+
+ // Size and frame rate should always be bucketed.
+ DCHECK(natural_size_ == media::GetSizeBucket(natural_size_));
+ DCHECK_EQ(last_observed_fps_, media::GetFpsBucket(last_observed_fps_));
+
+ // New records decoded and dropped counts should start at zero.
+ // These should never move backward.
+ DCHECK_GE(frames_decoded_offset, frames_decoded_offset_);
+ DCHECK_GE(frames_dropped_offset, frames_dropped_offset_);
+ DCHECK_GE(frames_decoded_power_efficient_offset,
+ frames_decoded_power_efficient_offset_);
+ frames_decoded_offset_ = frames_decoded_offset;
+ frames_dropped_offset_ = frames_dropped_offset;
+ frames_decoded_power_efficient_offset_ =
+ frames_decoded_power_efficient_offset;
+
+ bool use_hw_secure_codecs = use_hw_secure_codecs_;
+ auto features = media::mojom::PredictionFeatures::New(
+ codec_profile_, natural_size_, last_observed_fps_, key_system_,
+ use_hw_secure_codecs);
+
+ recorder_remote_->StartNewRecord(std::move(features));
+}
+
+void VideoDecodeStatsReporter::ResetFrameRateState() {
+ // Reinitialize all frame rate state. The next UpdateStats() call will detect
+ // the frame rate.
+ last_observed_fps_ = 0;
+ num_stable_fps_samples_ = 0;
+ num_unstable_fps_changes_ = 0;
+ num_consecutive_tiny_fps_windows_ = 0;
+ fps_stabilization_failed_ = false;
+ last_fps_stabilized_ticks_ = base::TimeTicks();
+}
+
+bool VideoDecodeStatsReporter::ShouldBeReporting() const {
+ return is_playing_ && !is_backgrounded_ && !fps_stabilization_failed_ &&
+ !natural_size_.IsEmpty() && is_ipc_connected_;
+}
+
+void VideoDecodeStatsReporter::OnIpcConnectionError() {
+ // For incognito, the IPC will fail via this path because the recording
+ // service is unavailable. Otherwise, errors are unexpected.
+ DVLOG(2) << __func__ << " IPC disconnected. Stopping reporting.";
+ is_ipc_connected_ = false;
+ stats_cb_timer_.AbandonAndStop();
+}
+
+bool VideoDecodeStatsReporter::UpdateDecodeProgress(
+ const media::PipelineStatistics& stats) {
+ DCHECK_GE(stats.video_frames_decoded, last_frames_decoded_);
+ DCHECK_GE(stats.video_frames_dropped, last_frames_dropped_);
+
+ // Check if additional frames decoded since last stats update.
+ if (stats.video_frames_decoded == last_frames_decoded_) {
+ // Relax timer if its set to a short interval for frame rate stabilization.
+ if (stats_cb_timer_.GetCurrentDelay() < kRecordingInterval) {
+ DVLOG(2) << __func__ << " No decode progress; slowing the timer";
+ RunStatsTimerAtInterval(kRecordingInterval);
+ }
+ return false;
+ }
+
+ last_frames_decoded_ = stats.video_frames_decoded;
+ last_frames_dropped_ = stats.video_frames_dropped;
+
+ return true;
+}
+
+bool VideoDecodeStatsReporter::UpdateFrameRateStability(
+ const media::PipelineStatistics& stats) {
+ // When (re)initializing, the pipeline may momentarily return an average frame
+ // duration of zero. Ignore it and wait for a real frame rate.
+ if (stats.video_frame_duration_average.is_zero())
+ return false;
+
+ // Bucket frame rate to simplify metrics aggregation.
+ int frame_rate =
+ media::GetFpsBucket(1 / stats.video_frame_duration_average.InSecondsF());
+
+ if (frame_rate != last_observed_fps_) {
+ DVLOG(2) << __func__ << " fps changed: " << last_observed_fps_ << " -> "
+ << frame_rate;
+ last_observed_fps_ = frame_rate;
+ bool was_stable = num_stable_fps_samples_ >= kRequiredStableFpsSamples;
+ num_stable_fps_samples_ = 1;
+ num_unstable_fps_changes_++;
+
+ // FrameRate just destabilized. Check if last stability window was "tiny".
+ if (was_stable) {
+ if (tick_clock_->NowTicks() - last_fps_stabilized_ticks_ <
+ kTinyFpsWindowDuration) {
+ num_consecutive_tiny_fps_windows_++;
+ DVLOG(2) << __func__ << " Last FPS window was 'tiny'. num_tiny:"
+ << num_consecutive_tiny_fps_windows_;
+
+ // Stop reporting if FPS moves around a lot. Stats may be noisy.
+ if (num_consecutive_tiny_fps_windows_ >= kMaxTinyFpsWindows) {
+ DVLOG(2) << __func__ << " Too many tiny fps windows. Stopping timer";
+ fps_stabilization_failed_ = true;
+ stats_cb_timer_.AbandonAndStop();
+ return false;
+ }
+ } else {
+ num_consecutive_tiny_fps_windows_ = 0;
+ }
+ }
+
+ if (num_unstable_fps_changes_ >= kMaxUnstableFpsChanges) {
+ // Looks like VFR video. Wait for some stream property (e.g. decoder
+ // config) to change before trying again.
+ DVLOG(2) << __func__ << " Unable to stabilize FPS. Stopping timer.";
+ fps_stabilization_failed_ = true;
+ stats_cb_timer_.AbandonAndStop();
+ return false;
+ }
+
+ // Increase the timer frequency to quickly stabilize frame rate. 3x the
+ // frame duration is used as this should be enough for a few more frames to
+ // be decoded, while also being much faster (for typical frame rates) than
+ // the regular stats polling interval.
+ RunStatsTimerAtInterval(3 * stats.video_frame_duration_average);
+ return false;
+ }
+
+ // FrameRate matched last observed!
+ num_unstable_fps_changes_ = 0;
+ num_stable_fps_samples_++;
+
+ // Wait for steady frame rate to begin recording stats.
+ if (num_stable_fps_samples_ < kRequiredStableFpsSamples) {
+ DVLOG(2) << __func__ << " fps held, awaiting stable ("
+ << num_stable_fps_samples_ << ")";
+ return false;
+ } else if (num_stable_fps_samples_ == kRequiredStableFpsSamples) {
+ DVLOG(2) << __func__ << " fps stabilized at " << frame_rate;
+ last_fps_stabilized_ticks_ = tick_clock_->NowTicks();
+
+ // FPS is locked in. Start a new record, and set timer to reporting
+ // interval.
+ StartNewRecord(stats.video_frames_decoded, stats.video_frames_dropped,
+ stats.video_frames_decoded_power_efficient);
+ RunStatsTimerAtInterval(kRecordingInterval);
+ }
+ return true;
+}
+
+void VideoDecodeStatsReporter::UpdateStats() {
+ DCHECK(ShouldBeReporting());
+
+ media::PipelineStatistics stats = get_pipeline_stats_cb_.Run();
+ DVLOG(2) << __func__ << " Raw stats -- dropped:" << stats.video_frames_dropped
+ << "/" << stats.video_frames_decoded
+ << " power efficient:" << stats.video_frames_decoded_power_efficient
+ << "/" << stats.video_frames_decoded
+ << " dur_avg:" << stats.video_frame_duration_average;
+
+ // Evaluate decode progress and update various internal state. Bail if decode
+ // is not progressing.
+ if (!UpdateDecodeProgress(stats))
+ return;
+
+ // Check frame rate for changes. Bail if frame rate needs more samples to
+ // stabilize.
+ if (!UpdateFrameRateStability(stats))
+ return;
+
+ // Don't bother recording the first record immediately after stabilization.
+ // Counts of zero don't add value.
+ if (stats.video_frames_decoded == frames_decoded_offset_)
+ return;
+
+ // Cap all counts to |frames_decoded|. We should never exceed this cap, but
+ // we have some hard to track bug where we accumulate 1 extra dropped frame
+ // in a tiny minority of cases. Dropping all frames is a strong signal we
+ // don't want to discard, so just sanitize the data and carry on.
+ uint32_t frames_decoded = stats.video_frames_decoded - frames_decoded_offset_;
+ uint32_t frames_dropped = std::min(
+ stats.video_frames_dropped - frames_dropped_offset_, frames_decoded);
+ uint32_t frames_power_efficient =
+ std::min(stats.video_frames_decoded_power_efficient -
+ frames_decoded_power_efficient_offset_,
+ frames_decoded);
+
+ auto targets = media::mojom::PredictionTargets::New(
+ frames_decoded, frames_dropped, frames_power_efficient);
+
+ DVLOG(2) << __func__ << " Recording -- dropped:" << targets->frames_dropped
+ << "/" << targets->frames_decoded
+ << " power efficient:" << targets->frames_power_efficient << "/"
+ << targets->frames_decoded;
+ recorder_remote_->UpdateRecord(std::move(targets));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.h b/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.h
new file mode 100644
index 00000000000..54c7078ba78
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter.h
@@ -0,0 +1,245 @@
+// 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_MEDIA_VIDEO_DECODE_STATS_REPORTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_VIDEO_DECODE_STATS_REPORTER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "media/base/cdm_config.h"
+#include "media/base/pipeline_status.h"
+#include "media/base/video_codecs.h"
+#include "media/mojo/mojom/video_decode_stats_recorder.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace blink {
+
+// Reports on playback smoothness and for a given video codec profile, natural
+// size, and fps. When these properties change the current report will be
+// finalized and a new report will be started. Ongoing reports are also
+// finalized at destruction and process tear-down.
+class PLATFORM_EXPORT VideoDecodeStatsReporter {
+ public:
+ using GetPipelineStatsCB =
+ base::RepeatingCallback<media::PipelineStatistics(void)>;
+
+ VideoDecodeStatsReporter(
+ mojo::PendingRemote<media::mojom::VideoDecodeStatsRecorder>
+ recorder_remote,
+ GetPipelineStatsCB get_pipeline_stats_cb,
+ media::VideoCodecProfile codec_profile,
+ const gfx::Size& natural_size,
+ std::string key_system,
+ absl::optional<media::CdmConfig> cdm_config,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const base::TickClock* tick_clock =
+ base::DefaultTickClock::GetInstance());
+ VideoDecodeStatsReporter(const VideoDecodeStatsReporter&) = delete;
+ VideoDecodeStatsReporter& operator=(const VideoDecodeStatsReporter&) = delete;
+ ~VideoDecodeStatsReporter();
+
+ void OnPlaying();
+ void OnPaused();
+ void OnHidden();
+ void OnShown();
+
+ // Returns true if given |natural_size| is a match for our internal bucketed
+ // size. This allows callers to check a size change is significant enough to
+ // motivate recreating the reporter with a the new size.
+ bool MatchesBucketedNaturalSize(const gfx::Size& natural_size) const;
+
+ // NOTE: We do not listen for playback rate changes. These implicitly change
+ // the frame rate and surface via media::PipelineStatistics'
+ // video_frame_duration_average.
+
+ private:
+ // Friends so it can see the static constants and inspect when the timer is
+ // running / should be running.
+ friend class VideoDecodeStatsReporterTest;
+ // Friends to grab internal state and verify construction parameters.
+ friend class WebMediaPlayerImplTest;
+
+ // Constants placed in header file for test visibility.
+ enum : int {
+ // Timer interval for recording stats when frame rate and other stream
+ // properties are steady.
+ kRecordingIntervalMs = 2000,
+
+ // FrameRates must remain stable for a duration greater than this amount to
+ // avoid being classified as a "tiny fps window". See |kMaxTinyFpsWindows|.
+ kTinyFpsWindowMs = 5000,
+
+ // Limits the number of consecutive "tiny fps windows", as defined by
+ // |kTinyFpsWindowMs|. If this limit is met, we will give up until some
+ // stream property (e.g. decoder config) changes before trying again. We do
+ // not wish to record stats for variable frame rate content.
+ kMaxTinyFpsWindows = 5,
+
+ // Number of consecutive samples that must bucket to the same frame rate in
+ // order for frame rate to be considered "stable" enough to start recording
+ // stats.
+ kRequiredStableFpsSamples = 5,
+
+ // Limits the number attempts to detect stable frame rate. When this limit
+ // is reached, we will give up until some stream property (e.g. decoder
+ // config) changes before trying again. We do not wish to record stats for
+ // variable frame rate content.
+ kMaxUnstableFpsChanges = 10,
+ };
+
+ // Main driver of report updates. Queries |get_pipeline_stats_cb_| for the
+ // latest stats. Detects frame rate changes and playback stalls. Sends stats
+ // the VideoDecodeStatsRecorder (browser process) for saving. Should only be
+ // called when ShouldBeReporting() == true.
+ void UpdateStats();
+
+ // Run |stats_cb_timer_| at the specified |interval|. If the timer is already
+ // running, any existing callbacks will be canceled/delayed until
+ // |interval| has elapsed.
+ void RunStatsTimerAtInterval(base::TimeDelta interval);
+
+ // Called to begin a new report following changes to stream metadata (e.g.
+ // natural size). Arguments used to update |frames_decoded_offset_|,
+ // |frames_dropped_offset_|, and |frames_decoded_power_efficient_offset| so
+ // that frame counts for this report begin at 0.
+ void StartNewRecord(uint32_t frames_decoded_offset,
+ uint32_t frames_dropped_offset,
+ uint32_t frames_decoded_power_efficient_offset);
+
+ // Reset frame rate tracking state to force a fresh attempt at detection. When
+ // a stable frame rate is successfully detected, UpdateStats() will begin a
+ // new record will begin with the detected frame rate. Note: callers must
+ // separately ensure the |stats_cb_timer_| is running for frame rate detection
+ // to occur.
+ void ResetFrameRateState();
+
+ // Called by UpdateStats() to verify decode is progressing and sanity check
+ // decode/dropped frame counts. Will manage decoded/dropped frame state and
+ // relax timer when no decode progress is made. Returns true iff decode is
+ // progressing.
+ bool UpdateDecodeProgress(const media::PipelineStatistics& stats);
+
+ // Called by UpdateStats() to do frame rate detection. Will manage frame rate
+ // state, stats timer, and will start new capabilities records when frame rate
+ // changes. Returns true iff frame rate is stable.
+ bool UpdateFrameRateStability(const media::PipelineStatistics& stats);
+
+ // Returns true if the |stats_timer_cb_| should be running. Should be called
+ // after any state change (e.g. |is_playing_|) as a check on whether to start
+ // the the timer.
+ bool ShouldBeReporting() const;
+
+ // Error handler callback when IPC hits an error.
+ void OnIpcConnectionError();
+
+ // TimeDelta wrappers around |kRecordingIntervalMs| and |kTimyFpsWindowMs|.
+ // Defined as a class member to avoid static initialization.
+ // TODO(chcunningham): convert to static constexpr when MSVC support arrives.
+ const base::TimeDelta kRecordingInterval;
+ const base::TimeDelta kTinyFpsWindowDuration;
+
+ // mojo::Remote for the recorder. The recorder runs in the browser process
+ // and finalizes the record in the event of fast render process tear down.
+ mojo::Remote<media::mojom::VideoDecodeStatsRecorder> recorder_remote_;
+
+ // Callback for retrieving playback statistics.
+ GetPipelineStatsCB get_pipeline_stats_cb_;
+
+ // Current video codec profile, used to index recorded stats.
+ const media::VideoCodecProfile codec_profile_;
+
+ // Current video natural size, used to index recorded stats. These dimensions
+ // will always be rounded to the nearest size bucket. If the original size is
+ // very small, the bucketed size will simply be empty. See GetSizeBucket().
+ const gfx::Size natural_size_;
+
+ // The name of the current key system. Empty for unencrypted playback.
+ const std::string key_system_;
+
+ // From media::CdmConfig in constructor.
+ const bool use_hw_secure_codecs_;
+
+ // Clock for |stats_cb_timer_| and getting current tick count (NowTicks()).
+ // Tests may supply a mock clock via the constructor.
+ const base::TickClock* tick_clock_;
+
+ // Timer for all stats callbacks. Timer interval will be dynamically set based
+ // on state of reporter. See calls to RunStatsTimerAtIntervalMs().
+ base::RepeatingTimer stats_cb_timer_;
+
+ // Latest frame duration bucketed into one of kFrameRateBuckets.
+ int last_observed_fps_ = 0;
+
+ // Count of consecutive samples with frame duration matching
+ // |last_observed_fps_|.
+ int num_stable_fps_samples_ = 0;
+
+ // Count of consecutive samples with frame duration NOT matching
+ // |last_obseved_fps_|. Used to throttle/limit attempts to stabilize FPS since
+ // some videos may have variable frame rate.
+ int num_unstable_fps_changes_ = 0;
+
+ // Count of consecutive stable FPS windows, where stable FPS was detected but
+ // it lasted for a very short duration before changing again.
+ int num_consecutive_tiny_fps_windows_ = 0;
+
+ // True whenever we fail to determine a stable FPS, or if windows of stable
+ // FPS are too tiny to be useful.
+ bool fps_stabilization_failed_ = false;
+
+ // Tick time of the most recent FPS stabilization. When FPS changes, this time
+ // is compared to TimeTicks::Now() to approximate the duration of the last
+ // stable FPS window.
+ base::TimeTicks last_fps_stabilized_ticks_;
+
+ // Count of frames decoded observed in last pipeline stats update. Used to
+ // check whether decode/playback has actually advanced.
+ uint32_t last_frames_decoded_ = 0;
+
+ // Count of frames dropped observed in last pipeline stats update. Used to
+ // verify that count never decreases.
+ uint32_t last_frames_dropped_ = 0;
+
+ // Notes the number of frames decoded at the start of the current video
+ // configuration (profile, resolution, fps). Should be subtracted from
+ // pipeline frames decoded stats before sending to recorder.
+ uint32_t frames_decoded_offset_ = 0;
+
+ // Notes the number of frames dropped at the start of the current video
+ // configuration (profile, resolution, fps). Should be subtracted from
+ // pipeline frames dropped stats before sending to recorder.
+ uint32_t frames_dropped_offset_ = 0;
+
+ // Notes the number of power efficiently decoded frames at the start of the
+ // current video configuration (profile, resolution, fps). Should be
+ // subtracted from pipeline frames decoded stats before sending to recorder.
+ uint32_t frames_decoded_power_efficient_offset_ = 0;
+
+ // Set true by OnPlaying(), false by OnPaused(). We should not run the
+ // |stats_cb_timer_| when not playing.
+ bool is_playing_ = false;
+
+ // Set true by OnHidden(), false by OnVisible(). We should not run the
+ // |stats_cb_timer_| when player is backgrounded.
+ bool is_backgrounded_ = false;
+
+ // Set false by UpdateStats() if an IPC error is encountered. Assumed true
+ // until an error is found.
+ bool is_ipc_connected_ = true;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_VIDEO_DECODE_STATS_REPORTER_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter_unittest.cc b/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter_unittest.cc
new file mode 100644
index 00000000000..b0250a13c9c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/video_decode_stats_reporter_unittest.cc
@@ -0,0 +1,935 @@
+// 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/media/video_decode_stats_reporter.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "media/base/cdm_config.h"
+#include "media/base/media_util.h"
+#include "media/base/video_codecs.h"
+#include "media/base/video_types.h"
+#include "media/capabilities/bucket_utility.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+#include "media/mojo/mojom/video_decode_stats_recorder.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace blink {
+
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::_;
+
+const media::VideoCodecProfile kDefaultProfile = media::VP9PROFILE_PROFILE0;
+const int kDefaultHeight = 480;
+const int kDefaultWidth = 640;
+const char kDefaultKeySystem[] = "org.w3.clearkey";
+const bool kDefaultUseHwSecureCodecs = true;
+const media::CdmConfig kDefaultCdmConfig = {false, false,
+ kDefaultUseHwSecureCodecs};
+const double kDefaultFps = 30;
+const int kDecodeCountIncrement = 20;
+const int kDroppedCountIncrement = 1;
+const int kDecodePowerEfficientCountIncrement = 1;
+
+media::VideoDecoderConfig MakeVideoConfig(media::VideoCodec codec,
+ media::VideoCodecProfile profile,
+ gfx::Size natural_size) {
+ gfx::Size coded_size = natural_size;
+ gfx::Rect visible_rect(coded_size.width(), coded_size.height());
+ return media::VideoDecoderConfig(
+ codec, profile, media::VideoDecoderConfig::AlphaMode::kIsOpaque,
+ media::VideoColorSpace::JPEG(), media::kNoTransformation, coded_size,
+ visible_rect, natural_size, media::EmptyExtraData(),
+ media::EncryptionScheme::kUnencrypted);
+}
+
+media::PipelineStatistics MakeStats(int frames_decoded,
+ int frames_dropped,
+ int power_efficient_decoded_frames,
+ double fps) {
+ // Will initialize members with reasonable defaults.
+ media::PipelineStatistics stats;
+ stats.video_frames_decoded = frames_decoded;
+ stats.video_frames_dropped = frames_dropped;
+ stats.video_frames_decoded_power_efficient = power_efficient_decoded_frames;
+ stats.video_frame_duration_average = base::TimeDelta::FromSecondsD(1.0 / fps);
+ return stats;
+}
+
+// Mock VideoDecodeStatsRecorder to verify reporter/recorder interactions.
+class RecordInterceptor : public media::mojom::VideoDecodeStatsRecorder {
+ public:
+ RecordInterceptor() = default;
+ ~RecordInterceptor() override = default;
+
+ // Until move-only types work.
+ void StartNewRecord(media::mojom::PredictionFeaturesPtr features) override {
+ MockStartNewRecord(features->profile, features->video_size,
+ features->frames_per_sec, features->key_system,
+ features->use_hw_secure_codecs);
+ }
+
+ MOCK_METHOD5(MockStartNewRecord,
+ void(media::VideoCodecProfile profile,
+ const gfx::Size& natural_size,
+ int frames_per_sec,
+ std::string key_system,
+ bool use_hw_secure_codecs));
+
+ void UpdateRecord(media::mojom::PredictionTargetsPtr targets) override {
+ MockUpdateRecord(targets->frames_decoded, targets->frames_dropped,
+ targets->frames_power_efficient);
+ }
+
+ MOCK_METHOD3(MockUpdateRecord,
+ void(uint32_t frames_decoded,
+ uint32_t frames_dropped,
+ uint32_t frames_power_efficient));
+
+ MOCK_METHOD0(FinalizeRecord, void());
+};
+
+class VideoDecodeStatsReporterTest : public ::testing::Test {
+ public:
+ VideoDecodeStatsReporterTest()
+ : kDefaultSize_(kDefaultWidth, kDefaultHeight) {}
+ ~VideoDecodeStatsReporterTest() override = default;
+
+ void SetUp() override {
+ // Make reporter with default configuration. Connects RecordInterceptor as
+ // remote mojo VideoDecodeStatsRecorder.
+ MakeReporter();
+
+ // Start each test with no decodes, no drops, and steady framerate.
+ pipeline_decoded_frames_ = 0;
+ pipeline_dropped_frames_ = 0;
+ pipeline_power_efficient_frames_ = 0;
+ pipeline_framerate_ = kDefaultFps;
+ }
+
+ void TearDown() override {
+ // Break the IPC connection if reporter still around.
+ reporter_.reset();
+
+ // Run task runner to have Mojo cleanup interceptor_.
+ task_environment_.RunUntilIdle();
+ }
+
+ media::PipelineStatistics MakeAdvancingDecodeStats() {
+ pipeline_decoded_frames_ += kDecodeCountIncrement;
+ pipeline_dropped_frames_ += kDroppedCountIncrement;
+ pipeline_power_efficient_frames_ += kDecodePowerEfficientCountIncrement;
+ return MakeStats(pipeline_decoded_frames_, pipeline_dropped_frames_,
+ pipeline_power_efficient_frames_, pipeline_framerate_);
+ }
+
+ // Peek at what MakeAdvancingDecodeStats() will return next without advancing
+ // the tracked counts.
+ media::PipelineStatistics PeekNextDecodeStats() const {
+ return MakeStats(
+ pipeline_decoded_frames_ + kDecodeCountIncrement,
+ pipeline_dropped_frames_ + kDroppedCountIncrement,
+ pipeline_power_efficient_frames_ + kDecodePowerEfficientCountIncrement,
+ pipeline_framerate_);
+ }
+
+ protected:
+ // Indicates expectations about rate of timer firing during FPS stabilization.
+ enum FpsStabiliaztionSpeed {
+ // Timer is expected to fire at rate of 3 * last observed average frame
+ // duration. This is the default for framerate detection.
+ FAST_STABILIZE_FPS,
+ // Timer is expected to fire at a rate of kRecordingInterval. This will
+ // occur
+ // when decode progress stalls during framerate detection.
+ SLOW_STABILIZE_FPS,
+ };
+
+ // Return mojo::PendingRemote<media::mojom::VideoDecodeStatsRecorder>
+ // after binding the RecordInterceptor to the receiver for a
+ // VideoDecodeStatsRecorder. The interceptor serves as a mock recorder to
+ // verify reporter/recorder interactions.
+ mojo::PendingRemote<media::mojom::VideoDecodeStatsRecorder>
+ SetupRecordInterceptor(RecordInterceptor** interceptor) {
+ // Capture a the interceptor pointer for verifying recorder calls. Lifetime
+ // will be managed by the |recorder_remote|.
+ *interceptor = new RecordInterceptor();
+ mojo::PendingRemote<media::mojom::VideoDecodeStatsRecorder> recorder_remote;
+ mojo::MakeSelfOwnedReceiver(
+ base::WrapUnique(*interceptor),
+ recorder_remote.InitWithNewPipeAndPassReceiver());
+ EXPECT_TRUE(recorder_remote.is_valid());
+ return recorder_remote;
+ }
+
+ // Inject mock objects and create a new |reporter_| to test.
+ void MakeReporter(
+ media::VideoCodecProfile profile = kDefaultProfile,
+ const gfx::Size& natural_size = gfx::Size(kDefaultWidth, kDefaultHeight),
+ const std::string key_system = kDefaultKeySystem,
+ const absl::optional<media::CdmConfig> cdm_config = kDefaultCdmConfig) {
+ reporter_ = std::make_unique<VideoDecodeStatsReporter>(
+ SetupRecordInterceptor(&interceptor_),
+ base::BindRepeating(&VideoDecodeStatsReporterTest::GetPipelineStatsCB,
+ base::Unretained(this)),
+ profile, natural_size, key_system, cdm_config,
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock());
+ }
+
+ // Fast forward the task runner (and associated tick clock) by |milliseconds|.
+ void FastForward(base::TimeDelta delta) {
+ task_environment_.FastForwardBy(delta);
+ }
+
+ bool ShouldBeReporting() const { return reporter_->ShouldBeReporting(); }
+
+ base::TimeDelta CurrentStatsCbInterval() const {
+ return reporter_->stats_cb_timer_.GetCurrentDelay();
+ }
+
+ int CurrentStableFpsSamples() const {
+ return reporter_->num_stable_fps_samples_;
+ }
+
+ // Call at the start of tests to stabilize framerate.
+ // Preconditions:
+ // 1) Reporter should not already be in playing state
+ // 2) Playing should unblock the reporter to begin reporting (e.g. not in
+ // hidden state)
+ // 3) No progress made yet toward stabilizing framerate.
+ void StartPlayingAndStabilizeFramerate(
+ media::VideoCodecProfile expected_profile = kDefaultProfile,
+ gfx::Size expected_natural_size = gfx::Size(kDefaultWidth,
+ kDefaultHeight),
+ int expected_fps = kDefaultFps,
+ std::string expected_key_system = kDefaultKeySystem,
+ bool expected_use_hw_secure_codecs = kDefaultUseHwSecureCodecs) {
+ DCHECK(!reporter_->is_playing_);
+ DCHECK_EQ(reporter_->num_stable_fps_samples_, 0);
+
+ // Setup stats callback to provide steadily advancing decode stats with a
+ // constant framerate.
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Invoke(
+ this, &VideoDecodeStatsReporterTest::MakeAdvancingDecodeStats));
+
+ // On playing should start timer at recording interval. Expect first stats
+ // CB when that interval has elapsed.
+ reporter_->OnPlaying();
+ DCHECK(ShouldBeReporting());
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(kRecordingInterval);
+
+ StabilizeFramerateAndStartNewRecord(expected_profile, expected_natural_size,
+ expected_fps, expected_key_system,
+ expected_use_hw_secure_codecs);
+ }
+
+ // Call just after detecting a change to framerate. |expected_profile|,
+ // |expected_natural_size|, and |expected_fps| will be verified against
+ // intercepted call to StartNewRecord(...) once the framerate is stabilized.
+ // |fps_timer_speed| indicates the expected timer interval to be used during
+ // stabilization (see FpsStabiliaztionSpeed definition).
+ // Preconditions:
+ // 1. Do not call if framerate already stable (know what you're testing).
+ // 2. Only call with GetPipelineStatsCB configured to return
+ // progressing decode stats with a steady framerate.
+ void StabilizeFramerateAndStartNewRecord(
+ media::VideoCodecProfile expected_profile,
+ gfx::Size expected_natural_size,
+ int expected_fps,
+ std::string expected_key_system,
+ bool expected_use_hw_secure_codecs,
+ FpsStabiliaztionSpeed fps_timer_speed = FAST_STABILIZE_FPS) {
+ ASSERT_TRUE(ShouldBeReporting());
+
+ base::TimeDelta last_frame_duration = media::kNoTimestamp;
+ uint32_t last_decoded_frames = 0;
+
+ while (CurrentStableFpsSamples() < kRequiredStableFpsSamples) {
+ media::PipelineStatistics next_stats = PeekNextDecodeStats();
+
+ // Sanity check that the stats callback is progressing decode.
+ DCHECK_GT(next_stats.video_frames_decoded, last_decoded_frames);
+ last_decoded_frames = next_stats.video_frames_decoded;
+
+ // Sanity check that the stats callback is providing steady fps.
+ if (last_frame_duration != media::kNoTimestamp) {
+ DCHECK_EQ(next_stats.video_frame_duration_average, last_frame_duration);
+ }
+ last_frame_duration = next_stats.video_frame_duration_average;
+
+ // The final iteration stabilizes framerate and starts a new record.
+ if (CurrentStableFpsSamples() == kRequiredStableFpsSamples - 1) {
+ EXPECT_CALL(*interceptor_,
+ MockStartNewRecord(expected_profile, expected_natural_size,
+ expected_fps, expected_key_system,
+ expected_use_hw_secure_codecs));
+ }
+
+ if (fps_timer_speed == FAST_STABILIZE_FPS) {
+ // Generally FPS is stabilized with a timer of ~3x the average frame
+ // duration.
+ base::TimeDelta frame_druation =
+ base::TimeDelta::FromSecondsD(1.0 / pipeline_framerate_);
+ EXPECT_EQ(CurrentStatsCbInterval(), frame_druation * 3);
+ } else {
+ // If the playback is struggling we will do it more slowly to avoid
+ // firing high frequency timers indefinitely. Store constant as a local
+ // to workaround linking confusion.
+ DCHECK_EQ(fps_timer_speed, SLOW_STABILIZE_FPS);
+
+ // fixme
+ EXPECT_EQ(CurrentStatsCbInterval(), kRecordingInterval);
+ }
+
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(CurrentStatsCbInterval());
+ }
+ }
+
+ // Advances the task runner by a single recording interval and verifies that
+ // the record is updated. The values provided to UpdateRecord(...)
+ // should match values from PeekNextDecodeStates(...), minus the offsets of
+ // |decoded_frames_offset|, |dropped_frames_offset| and
+ // |decoded_power_efficient_offset|.
+ // Preconditions:
+ // - Should only be called during regular reporting (framerate stable,
+ // not in background, not paused).
+ void AdvanceTimeAndVerifyRecordUpdate(int decoded_frames_offset,
+ int dropped_frames_offset,
+ int decoded_power_efficient_offset) {
+ DCHECK(ShouldBeReporting());
+
+ // Record updates should always occur at recording interval. Store to local
+ // variable to workaround linker confusion with test macros.
+ EXPECT_EQ(kRecordingInterval, CurrentStatsCbInterval());
+
+ media::PipelineStatistics next_stats = PeekNextDecodeStats();
+
+ // Decode stats must be advancing for record updates to be expected. Dropped
+ // frames should at least not move backward.
+ EXPECT_GT(next_stats.video_frames_decoded, pipeline_decoded_frames_);
+ EXPECT_GT(next_stats.video_frames_decoded_power_efficient,
+ pipeline_power_efficient_frames_);
+ EXPECT_GE(next_stats.video_frames_dropped, pipeline_dropped_frames_);
+
+ // Verify that UpdateRecord calls come at the recording interval with
+ // correct values.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ EXPECT_CALL(*interceptor_,
+ MockUpdateRecord(
+ next_stats.video_frames_decoded - decoded_frames_offset,
+ next_stats.video_frames_dropped - dropped_frames_offset,
+ next_stats.video_frames_decoded_power_efficient -
+ decoded_power_efficient_offset));
+ FastForward(kRecordingInterval);
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(interceptor_);
+ }
+
+ // Injected callback for fetching statistics. Each test will manage
+ // expectations and return behavior.
+ MOCK_METHOD0(GetPipelineStatsCB, media::PipelineStatistics());
+
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ // These track the last values returned by MakeAdvancingDecodeStats(). See
+ // SetUp() for initialization.
+ uint32_t pipeline_decoded_frames_;
+ uint32_t pipeline_dropped_frames_;
+ uint32_t pipeline_power_efficient_frames_;
+ double pipeline_framerate_;
+
+ // Placed as a class member to avoid static initialization costs.
+ const gfx::Size kDefaultSize_;
+
+ // Points to the interceptor that acts as a VideoDecodeStatsRecorder. The
+ // object is owned by mojo::Remote<VideoDecodeStatsRecorder>, which is itself
+ // owned by |reporter_|.
+ RecordInterceptor* interceptor_ = nullptr;
+
+ // The VideoDecodeStatsReporter being tested.
+ std::unique_ptr<VideoDecodeStatsReporter> reporter_;
+
+ // Redefined constants in fixture for easy access from tests. See
+ // video_decode_stats_reporter.h for documentation.
+ static const base::TimeDelta kRecordingInterval;
+ static const base::TimeDelta kTinyFpsWindowDuration;
+ static const int kRequiredStableFpsSamples =
+ VideoDecodeStatsReporter::kRequiredStableFpsSamples;
+ static const int kMaxUnstableFpsChanges =
+ VideoDecodeStatsReporter::kMaxUnstableFpsChanges;
+ static const int kMaxTinyFpsWindows =
+ VideoDecodeStatsReporter::kMaxTinyFpsWindows;
+};
+
+const base::TimeDelta VideoDecodeStatsReporterTest::kRecordingInterval =
+ base::TimeDelta::FromMilliseconds(
+ VideoDecodeStatsReporter::kRecordingIntervalMs);
+const base::TimeDelta VideoDecodeStatsReporterTest::kTinyFpsWindowDuration =
+ base::TimeDelta::FromMilliseconds(
+ VideoDecodeStatsReporter::kTinyFpsWindowMs);
+
+TEST_F(VideoDecodeStatsReporterTest, RecordWhilePlaying) {
+ StartPlayingAndStabilizeFramerate();
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ // Verify that UpdateRecord calls come at the recording interval with
+ // correct values.
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Once more for good measure.
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, RecordingStopsWhenPaused) {
+ StartPlayingAndStabilizeFramerate();
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // When paused, expect no stats callbacks and no record updates.
+ reporter_->OnPaused();
+ EXPECT_FALSE(ShouldBeReporting());
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ // Advance a few recording intervals just to be sure.
+ FastForward(kRecordingInterval * 3);
+
+ // Verify callbacks and record updates resume when playing again. No changes
+ // to the stream during pause, so no need to re-stabilize framerate. Offsets
+ // for stats count are still valid.
+ reporter_->OnPlaying();
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, RecordingStopsWhenHidden) {
+ StartPlayingAndStabilizeFramerate();
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // When hidden, expect no stats callbacks and no record updates.
+ reporter_->OnHidden();
+ EXPECT_FALSE(ShouldBeReporting());
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ // Advance a few recording intervals just to be sure.
+ FastForward(kRecordingInterval * 3);
+
+ // Verify updates resume when visible again. Dropped frame stats are not valid
+ // while hidden, so expect a new record to begin. GetPipelineStatsCB will be
+ // called to update offsets to ignore stats while hidden.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ EXPECT_CALL(*interceptor_,
+ MockStartNewRecord(kDefaultProfile, kDefaultSize_, kDefaultFps,
+ kDefaultKeySystem, kDefaultUseHwSecureCodecs));
+ reporter_->OnShown();
+
+ // Update offsets for new record and verify updates resume as time advances.
+ decoded_offset = pipeline_decoded_frames_;
+ dropped_offset = pipeline_dropped_frames_;
+ decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, RecordingStopsWhenNoDecodeProgress) {
+ StartPlayingAndStabilizeFramerate();
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Freeze decode stats at current values, simulating network underflow.
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Return(
+ MakeStats(pipeline_decoded_frames_, pipeline_dropped_frames_,
+ pipeline_power_efficient_frames_, pipeline_framerate_)));
+
+ // Verify record updates stop while decode is not progressing. Fast forward
+ // through several recording intervals to be sure we never call UpdateRecord.
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(3);
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ FastForward(kRecordingInterval * 3);
+
+ // Resume progressing decode!
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Invoke(
+ this, &VideoDecodeStatsReporterTest::MakeAdvancingDecodeStats));
+
+ // Verify record updates resume.
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, NewRecordStartsForFpsChange) {
+ StartPlayingAndStabilizeFramerate();
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Change FPS to 2x current rate. Future calls to GetPipelineStats will
+ // use this to compute frame duration.
+ EXPECT_EQ(pipeline_framerate_, static_cast<uint32_t>(kDefaultFps));
+ pipeline_framerate_ *= 2;
+
+ // Next stats update will not cause a record update. It will instead begin
+ // detection of the new framerate.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ FastForward(kRecordingInterval);
+
+ // A new record is started with the latest frames per second as soon as the
+ // framerate is confirmed (re-stabilized).
+ StabilizeFramerateAndStartNewRecord(kDefaultProfile, kDefaultSize_,
+ kDefaultFps * 2, kDefaultKeySystem,
+ kDefaultUseHwSecureCodecs);
+
+ // Offsets should be adjusted so the new record starts at zero.
+ decoded_offset = pipeline_decoded_frames_;
+ dropped_offset = pipeline_dropped_frames_;
+ decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ // Stats callbacks and record updates should proceed as usual.
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, FpsStabilizationFailed) {
+ // Setup stats callback to provide steadily advancing decode stats with a
+ // constant framerate.
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Invoke(
+ this, &VideoDecodeStatsReporterTest::MakeAdvancingDecodeStats));
+
+ // On playing should start timer.
+ reporter_->OnPlaying();
+ EXPECT_TRUE(ShouldBeReporting());
+
+ // OnPlaying starts the timer at the recording interval. Expect first stats
+ // CB when that interval has elapsed. This stats callback provides the first
+ // fps sample.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+
+ // We should not start nor update a record while failing to detect fps.
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _, _, _)).Times(0);
+ FastForward(kRecordingInterval);
+ int num_fps_samples = 1;
+
+ // With FPS stabilization in-progress, keep alternating framerate to thwart
+ // stabilization.
+ for (; num_fps_samples < kMaxUnstableFpsChanges; num_fps_samples++) {
+ pipeline_framerate_ =
+ (pipeline_framerate_ == kDefaultFps) ? 2 * kDefaultFps : kDefaultFps;
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(CurrentStatsCbInterval());
+ }
+
+ // Stabilization has now failed, so fast forwarding by any amount will not
+ // trigger new stats update callbacks.
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
+ FastForward(kRecordingInterval * 10);
+
+ // Pausing then playing does not kickstart reporting. We assume framerate is
+ // still variable.
+ reporter_->OnPaused();
+ reporter_->OnPlaying();
+ FastForward(kRecordingInterval * 10);
+
+ // Hidden then shown does not kickstart reporting. We assume framerate is
+ // still variable.
+ reporter_->OnHidden();
+ reporter_->OnShown();
+ FastForward(kRecordingInterval * 10);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, FpsStabilizationFailed_TinyWindows) {
+ uint32_t decoded_offset = 0;
+ uint32_t dropped_offset = 0;
+ uint32_t decoded_power_efficient_offset = 0;
+
+ // Setup stats callback to provide steadily advancing decode stats.
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Invoke(
+ this, &VideoDecodeStatsReporterTest::MakeAdvancingDecodeStats));
+
+ // On playing should start timer at recording interval. Expect first stats
+ // CB when that interval has elapsed.
+ reporter_->OnPlaying();
+ DCHECK(ShouldBeReporting());
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(kRecordingInterval);
+
+ // Repeatedly stabilize, then change the FPS after single record updates to
+ // create tiny windows.
+ for (int i = 0; i < kMaxTinyFpsWindows; i++) {
+ StabilizeFramerateAndStartNewRecord(kDefaultProfile, kDefaultSize_,
+ pipeline_framerate_, kDefaultKeySystem,
+ kDefaultUseHwSecureCodecs);
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ decoded_offset = pipeline_decoded_frames_;
+ dropped_offset = pipeline_dropped_frames_;
+ decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Changing the framerate and fast forward to detect the change.
+ pipeline_framerate_ =
+ (pipeline_framerate_ == kDefaultFps) ? 2 * kDefaultFps : kDefaultFps;
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(kRecordingInterval);
+ }
+
+ // Verify no further stats updates are made because we've hit the maximum
+ // number of tiny framerate windows.
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ FastForward(kRecordingInterval);
+
+ // Pausing then playing does not kickstart reporting. We assume framerate is
+ // still variable.
+ reporter_->OnPaused();
+ reporter_->OnPlaying();
+ FastForward(kRecordingInterval * 10);
+
+ // Hidden then shown does not kickstart reporting. We assume framerate is
+ // still variable.
+ reporter_->OnHidden();
+ reporter_->OnShown();
+ FastForward(kRecordingInterval * 10);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, ThrottleFpsTimerIfNoDecodeProgress) {
+ // Setup stats callback to provide steadily advancing decode stats with a
+ // constant framerate.
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Invoke(
+ this, &VideoDecodeStatsReporterTest::MakeAdvancingDecodeStats));
+
+ // On playing should start timer at recording interval.
+ reporter_->OnPlaying();
+ EXPECT_TRUE(ShouldBeReporting());
+
+ // OnPlaying starts the timer at the recording interval. Expect first stats
+ // CB when that interval has elapsed. This stats callback provides the first
+ // fps sample.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(kRecordingInterval);
+ int stable_fps_samples = 1;
+
+ // Now advance time to make it half way through framerate stabilization.
+ base::TimeDelta frame_duration =
+ base::TimeDelta::FromSecondsD(1.0 / pipeline_framerate_);
+ for (; stable_fps_samples < kRequiredStableFpsSamples / 2;
+ stable_fps_samples++) {
+ // The timer runs at 3x the frame duration when detecting framerate to
+ // quickly stabilize.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(frame_duration * 3);
+ }
+
+ // With stabilization still ongoing, freeze decode progress by repeatedly
+ // returning the same stats from before.
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Return(
+ MakeStats(pipeline_decoded_frames_, pipeline_dropped_frames_,
+ pipeline_power_efficient_frames_, pipeline_framerate_)));
+
+ // Advance another fps detection interval to detect that no progress was made.
+ // Verify this decreases timer frequency to standard reporting interval.
+ EXPECT_LT(CurrentStatsCbInterval(), kRecordingInterval);
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(frame_duration * 3);
+ EXPECT_EQ(CurrentStatsCbInterval(), kRecordingInterval);
+
+ // Verify stats updates continue to come in at recording interval. Verify no
+ // calls to UpdateRecord because decode progress is still frozen. Fast forward
+ // through several recording intervals to be sure nothing changes.
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(3);
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ FastForward(kRecordingInterval * 3);
+
+ // Un-freeze decode stats!
+ ON_CALL(*this, GetPipelineStatsCB())
+ .WillByDefault(Invoke(
+ this, &VideoDecodeStatsReporterTest::MakeAdvancingDecodeStats));
+
+ // Finish framerate stabilization with a slower timer frequency. The slower
+ // timer is used to avoid firing high frequency timers indefinitely for
+ // machines/networks that are struggling to keep up.
+ StabilizeFramerateAndStartNewRecord(
+ kDefaultProfile, kDefaultSize_, kDefaultFps, kDefaultKeySystem,
+ kDefaultUseHwSecureCodecs, SLOW_STABILIZE_FPS);
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+
+TEST_F(VideoDecodeStatsReporterTest, FpsBucketing) {
+ StartPlayingAndStabilizeFramerate();
+ EXPECT_EQ(kDefaultFps, pipeline_framerate_);
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ // Verify that UpdateRecord calls come at the recording interval with
+ // correct values.
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Small changes to framerate should not trigger a new record.
+ pipeline_framerate_ = kDefaultFps + .5;
+ EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _, _, _)).Times(0);
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Small changes in the other direction should also not trigger a new record.
+ pipeline_framerate_ = kDefaultFps - .5;
+ EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _, _, _)).Times(0);
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Big changes in framerate should trigger a new record.
+ pipeline_framerate_ = kDefaultFps * 2;
+
+ // Fast forward by one interval to detect framerate change.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(kRecordingInterval);
+
+ // Stabilize new framerate.
+ StabilizeFramerateAndStartNewRecord(kDefaultProfile, kDefaultSize_,
+ kDefaultFps * 2, kDefaultKeySystem,
+ kDefaultUseHwSecureCodecs);
+
+ // Update offsets for new record and verify recording.
+ decoded_offset = pipeline_decoded_frames_;
+ dropped_offset = pipeline_dropped_frames_;
+ decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // Whacky framerates should be bucketed to a more common nearby value.
+ pipeline_framerate_ = 123.4;
+
+ // Fast forward by one interval to detect framerate change.
+ EXPECT_CALL(*this, GetPipelineStatsCB());
+ FastForward(kRecordingInterval);
+
+ // Verify new record uses bucketed framerate.
+ int bucketed_fps = media::GetFpsBucket(pipeline_framerate_);
+ EXPECT_NE(bucketed_fps, pipeline_framerate_);
+ StabilizeFramerateAndStartNewRecord(kDefaultProfile, kDefaultSize_,
+ bucketed_fps, kDefaultKeySystem,
+ kDefaultUseHwSecureCodecs);
+
+ // Update offsets for new record and verify recording.
+ decoded_offset = pipeline_decoded_frames_;
+ dropped_offset = pipeline_dropped_frames_;
+ decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, ResolutionBucketing) {
+ MakeReporter();
+ EXPECT_TRUE(reporter_->MatchesBucketedNaturalSize(kDefaultSize_));
+
+ // Note that our current size fits perfectly into known buckets...
+ EXPECT_EQ(media::GetSizeBucket(kDefaultSize_), kDefaultSize_);
+
+ // A slightly smaller size should fall into the same size bucket as before.
+ gfx::Size slightly_smaller_size(kDefaultWidth - 2, kDefaultHeight - 2);
+ EXPECT_TRUE(reporter_->MatchesBucketedNaturalSize(slightly_smaller_size));
+
+ // Since the original size perfectly fits a known size bucket, any small
+ // increase should cause the next larger bucket should be chosen. This is done
+ // to surface cut off resolutions in hardware decoders. HW acceleration can be
+ // critical to smooth decode at higher resolutions.
+ gfx::Size slightly_larger_size(kDefaultWidth + 1, kDefaultHeight + 1);
+ EXPECT_FALSE(reporter_->MatchesBucketedNaturalSize(slightly_larger_size));
+
+ MakeReporter(kDefaultProfile, slightly_larger_size);
+ EXPECT_TRUE(reporter_->MatchesBucketedNaturalSize(slightly_larger_size));
+
+ // With |slightly_larger_size| describing the bottom of its bucket, we should
+ // have of room to increase a little further within this bucket, without
+ // triggering the start of a new record.
+ slightly_larger_size = gfx::Size(slightly_larger_size.width() + 1,
+ slightly_larger_size.height() + 1);
+ EXPECT_TRUE(reporter_->MatchesBucketedNaturalSize(slightly_larger_size));
+
+ // Big changes in resolution should fall into a different bucket
+ gfx::Size big_resolution(kDefaultWidth * 2, kDefaultHeight * 2);
+ EXPECT_FALSE(reporter_->MatchesBucketedNaturalSize(big_resolution));
+}
+
+TEST_F(VideoDecodeStatsReporterTest, ResolutionTooSmall) {
+ // Initialize the natural size to something tiny.
+ gfx::Size tiny_size(10, 15);
+ MakeReporter(kDefaultProfile, tiny_size);
+
+ // Tiny size should "bucket" to empty.
+ EXPECT_TRUE(reporter_->MatchesBucketedNaturalSize(gfx::Size()));
+
+ // Verify reporting has stopped because because resolution is so small. Fast
+ // forward through several intervals to verify no callbacks are made while the
+ // tiny size is in effect.
+ EXPECT_FALSE(ShouldBeReporting());
+ EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
+ EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+ FastForward(kRecordingInterval * 3);
+
+ // Change the size to something small, but reasonable.
+ const gfx::Size small_size(75, 75);
+ MakeReporter(kDefaultProfile, small_size);
+
+ // Stabilize new framerate and verify record updates come with new offsets.
+ StartPlayingAndStabilizeFramerate(kDefaultProfile,
+ media::GetSizeBucket(small_size));
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, VaryEmeProperties) {
+ // Readability helpers
+ const gfx::Size kDefaultSize(kDefaultWidth, kDefaultHeight);
+ const char kEmptyKeySystem[] = "";
+ const bool kNonDefaultHwSecureCodecs = !kDefaultUseHwSecureCodecs;
+ const media::CdmConfig kNonDefaultCdmConfig = {false, false,
+ kNonDefaultHwSecureCodecs};
+ const char kFooKeySystem[] = "fookeysytem";
+
+ // Make reporter with no EME properties.
+ MakeReporter(kDefaultProfile, kDefaultSize, kEmptyKeySystem, absl::nullopt);
+ // Verify the empty key system and non-default hw_secure_codecs.
+ StartPlayingAndStabilizeFramerate(kDefaultProfile, kDefaultSize, kDefaultFps,
+ kEmptyKeySystem, kNonDefaultHwSecureCodecs);
+
+ // Make a new reporter with a non-default, non-empty key system.
+ MakeReporter(kDefaultProfile, kDefaultSize, kFooKeySystem,
+ kNonDefaultCdmConfig);
+ // Verify non-default key system
+ StartPlayingAndStabilizeFramerate(kDefaultProfile, kDefaultSize, kDefaultFps,
+ kFooKeySystem, kNonDefaultHwSecureCodecs);
+}
+
+TEST_F(VideoDecodeStatsReporterTest, SanitizeFrameCounts) {
+ StartPlayingAndStabilizeFramerate();
+
+ // Framerate is now stable! Recorded stats should be offset by the values
+ // last provided to GetPipelineStatsCB.
+ uint32_t decoded_offset = pipeline_decoded_frames_;
+ uint32_t dropped_offset = pipeline_dropped_frames_;
+ uint32_t decoded_power_efficient_offset = pipeline_power_efficient_frames_;
+
+ // Verify that UpdateRecord calls come at the recording interval with
+ // correct values.
+ AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
+ decoded_power_efficient_offset);
+
+ // On next call for stats, advance decoded count a little and advance dropped
+ // and power efficient counts beyond the decoded count.
+ pipeline_decoded_frames_ += 10;
+ pipeline_dropped_frames_ = pipeline_decoded_frames_ + 1;
+ pipeline_power_efficient_frames_ = pipeline_decoded_frames_ + 2;
+ EXPECT_CALL(*this, GetPipelineStatsCB())
+ .WillOnce(Return(
+ MakeStats(pipeline_decoded_frames_, pipeline_dropped_frames_,
+ pipeline_power_efficient_frames_, pipeline_framerate_)));
+
+ // Expect that record update caps dropped and power efficient counts to the
+ // offset decoded count.
+ EXPECT_CALL(*interceptor_,
+ MockUpdateRecord(pipeline_decoded_frames_ - decoded_offset,
+ pipeline_decoded_frames_ - decoded_offset,
+ pipeline_decoded_frames_ - decoded_offset));
+ FastForward(kRecordingInterval);
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(interceptor_);
+
+ // Dropped and efficient counts should record correctly if subsequent updates
+ // cease to exceed decoded frame count.
+ pipeline_decoded_frames_ += 1000;
+ EXPECT_CALL(*this, GetPipelineStatsCB())
+ .WillOnce(Return(
+ MakeStats(pipeline_decoded_frames_, pipeline_dropped_frames_,
+ pipeline_power_efficient_frames_, pipeline_framerate_)));
+
+ EXPECT_CALL(*interceptor_,
+ MockUpdateRecord(pipeline_decoded_frames_ - decoded_offset,
+ pipeline_dropped_frames_ - dropped_offset,
+ pipeline_power_efficient_frames_ -
+ decoded_power_efficient_offset));
+ FastForward(kRecordingInterval);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/video_frame_compositor.cc b/chromium/third_party/blink/renderer/platform/media/video_frame_compositor.cc
new file mode 100644
index 00000000000..2ccbc4b7388
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/video_frame_compositor.cc
@@ -0,0 +1,461 @@
+// 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/media/video_frame_compositor.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_post_task.h"
+#include "base/callback_helpers.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/time/default_tick_clock.h"
+#include "base/trace_event/trace_event.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "media/base/media_switches.h"
+#include "media/base/video_frame.h"
+#include "third_party/blink/public/platform/web_video_frame_submitter.h"
+
+namespace blink {
+
+using RenderingMode = ::media::VideoRendererSink::RenderCallback::RenderingMode;
+
+// Amount of time to wait between UpdateCurrentFrame() callbacks before starting
+// background rendering to keep the Render() callbacks moving.
+const int kBackgroundRenderingTimeoutMs = 250;
+const int kForceBeginFramesTimeoutMs = 1000;
+
+// static
+constexpr const char VideoFrameCompositor::kTracingCategory[];
+
+VideoFrameCompositor::VideoFrameCompositor(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ std::unique_ptr<WebVideoFrameSubmitter> submitter)
+ : task_runner_(task_runner),
+ tick_clock_(base::DefaultTickClock::GetInstance()),
+ background_rendering_timer_(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kBackgroundRenderingTimeoutMs),
+ base::BindRepeating(&VideoFrameCompositor::BackgroundRender,
+ base::Unretained(this),
+ RenderingMode::kBackground)),
+ force_begin_frames_timer_(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kForceBeginFramesTimeoutMs),
+ base::BindRepeating(&VideoFrameCompositor::StopForceBeginFrames,
+ base::Unretained(this))),
+ submitter_(std::move(submitter)) {
+ if (submitter_) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&VideoFrameCompositor::InitializeSubmitter,
+ weak_ptr_factory_.GetWeakPtr()));
+ update_submission_state_callback_ = base::BindPostTask(
+ task_runner_,
+ base::BindRepeating(&VideoFrameCompositor::SetIsSurfaceVisible,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+cc::UpdateSubmissionStateCB
+VideoFrameCompositor::GetUpdateSubmissionStateCallback() {
+ return update_submission_state_callback_;
+}
+
+void VideoFrameCompositor::SetIsSurfaceVisible(
+ bool is_visible,
+ base::WaitableEvent* done_event) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ submitter_->SetIsSurfaceVisible(is_visible);
+ if (done_event)
+ done_event->Signal();
+}
+
+void VideoFrameCompositor::InitializeSubmitter() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ submitter_->Initialize(this, /* is_media_stream = */ false);
+}
+
+VideoFrameCompositor::~VideoFrameCompositor() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(!callback_);
+ DCHECK(!rendering_);
+ if (client_)
+ client_->StopUsingProvider();
+}
+
+void VideoFrameCompositor::EnableSubmission(
+ const viz::SurfaceId& id,
+ media::VideoTransformation transform,
+ bool force_submit) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ // If we're switching to |submitter_| from some other client, then tell it.
+ if (client_ && client_ != submitter_.get())
+ client_->StopUsingProvider();
+
+ submitter_->SetTransform(transform);
+ submitter_->SetForceSubmit(force_submit);
+ submitter_->EnableSubmission(id);
+ client_ = submitter_.get();
+ if (rendering_)
+ client_->StartRendering();
+}
+
+bool VideoFrameCompositor::IsClientSinkAvailable() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ return client_;
+}
+
+void VideoFrameCompositor::OnRendererStateUpdate(bool new_state) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(rendering_, new_state);
+ rendering_ = new_state;
+
+ if (!auto_open_close_) {
+ auto_open_close_ = std::make_unique<
+ base::trace_event::AutoOpenCloseEvent<kTracingCategory>>(
+ base::trace_event::AutoOpenCloseEvent<kTracingCategory>::Type::ASYNC,
+ "VideoPlayback");
+ }
+
+ if (rendering_) {
+ auto_open_close_->Begin();
+ } else {
+ new_processed_frame_cb_.Reset();
+ auto_open_close_->End();
+ }
+
+ if (rendering_) {
+ // Always start playback in background rendering mode, if |client_| kicks
+ // in right away it's okay.
+ BackgroundRender(RenderingMode::kStartup);
+ } else if (background_rendering_enabled_) {
+ background_rendering_timer_.Stop();
+ } else {
+ DCHECK(!background_rendering_timer_.IsRunning());
+ }
+
+ if (!IsClientSinkAvailable())
+ return;
+
+ if (rendering_)
+ client_->StartRendering();
+ else
+ client_->StopRendering();
+}
+
+void VideoFrameCompositor::SetVideoFrameProviderClient(
+ cc::VideoFrameProvider::Client* client) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (client_)
+ client_->StopUsingProvider();
+ client_ = client;
+
+ // |client_| may now be null, so verify before calling it.
+ if (rendering_ && client_)
+ client_->StartRendering();
+}
+
+scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ return current_frame_;
+}
+
+scoped_refptr<media::VideoFrame>
+VideoFrameCompositor::GetCurrentFrameOnAnyThread() {
+ base::AutoLock lock(current_frame_lock_);
+ return current_frame_;
+}
+
+void VideoFrameCompositor::SetCurrentFrame_Locked(
+ scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks expected_display_time) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT1("media", "VideoFrameCompositor::SetCurrentFrame", "frame",
+ frame->AsHumanReadableString());
+ current_frame_lock_.AssertAcquired();
+ current_frame_ = std::move(frame);
+ last_presentation_time_ = tick_clock_->NowTicks();
+ last_expected_display_time_ = expected_display_time;
+ ++presentation_counter_;
+}
+
+void VideoFrameCompositor::PutCurrentFrame() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ rendered_last_frame_ = true;
+}
+
+bool VideoFrameCompositor::UpdateCurrentFrame(base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT2("media", "VideoFrameCompositor::UpdateCurrentFrame",
+ "deadline_min", deadline_min, "deadline_max", deadline_max);
+ return CallRender(deadline_min, deadline_max, RenderingMode::kNormal);
+}
+
+bool VideoFrameCompositor::HasCurrentFrame() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ return static_cast<bool>(GetCurrentFrame());
+}
+
+base::TimeDelta VideoFrameCompositor::GetPreferredRenderInterval() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ base::AutoLock lock(callback_lock_);
+
+ if (!callback_)
+ return viz::BeginFrameArgs::MinInterval();
+ return callback_->GetPreferredRenderInterval();
+}
+
+void VideoFrameCompositor::Start(RenderCallback* callback) {
+ // Called from the media thread, so acquire the callback under lock before
+ // returning in case a Stop() call comes in before the PostTask is processed.
+ base::AutoLock lock(callback_lock_);
+ DCHECK(!callback_);
+ callback_ = callback;
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&VideoFrameCompositor::OnRendererStateUpdate,
+ weak_ptr_factory_.GetWeakPtr(), true));
+}
+
+void VideoFrameCompositor::Stop() {
+ // Called from the media thread, so release the callback under lock before
+ // returning to avoid a pending UpdateCurrentFrame() call occurring before
+ // the PostTask is processed.
+ base::AutoLock lock(callback_lock_);
+ DCHECK(callback_);
+ callback_ = nullptr;
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&VideoFrameCompositor::OnRendererStateUpdate,
+ weak_ptr_factory_.GetWeakPtr(), false));
+}
+
+void VideoFrameCompositor::PaintSingleFrame(
+ scoped_refptr<media::VideoFrame> frame,
+ bool repaint_duplicate_frame) {
+ if (!task_runner_->BelongsToCurrentThread()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&VideoFrameCompositor::PaintSingleFrame,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(frame), repaint_duplicate_frame));
+ return;
+ }
+ if (ProcessNewFrame(std::move(frame), tick_clock_->NowTicks(),
+ repaint_duplicate_frame) &&
+ IsClientSinkAvailable()) {
+ client_->DidReceiveFrame();
+ }
+}
+
+void VideoFrameCompositor::UpdateCurrentFrameIfStale(UpdateType type) {
+ TRACE_EVENT0("media", "VideoFrameCompositor::UpdateCurrentFrameIfStale");
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ // If we're not rendering, then the frame can't be stale.
+ if (!rendering_ || !is_background_rendering_)
+ return;
+
+ // If we have a client, and it is currently rendering, then it's not stale
+ // since the client is driving the frame updates at the proper rate.
+ if (type != UpdateType::kBypassClient && IsClientSinkAvailable() &&
+ client_->IsDrivingFrameUpdates()) {
+ return;
+ }
+
+ // We're rendering, but the client isn't driving the updates. See if the
+ // frame is stale, and update it.
+
+ DCHECK(!last_background_render_.is_null());
+
+ const base::TimeTicks now = tick_clock_->NowTicks();
+ const base::TimeDelta interval = now - last_background_render_;
+
+ // Cap updates to 250Hz which should be more than enough for everyone.
+ if (interval < base::TimeDelta::FromMilliseconds(4))
+ return;
+
+ {
+ base::AutoLock lock(callback_lock_);
+ // Update the interval based on the time between calls and call background
+ // render which will give this information to the client.
+ last_interval_ = interval;
+ }
+ BackgroundRender();
+}
+
+void VideoFrameCompositor::SetOnNewProcessedFrameCallback(
+ OnNewProcessedFrameCB cb) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ new_processed_frame_cb_ = std::move(cb);
+}
+
+void VideoFrameCompositor::SetOnFramePresentedCallback(
+ OnNewFramePresentedCB present_cb) {
+ base::AutoLock lock(current_frame_lock_);
+ new_presented_frame_cb_ = std::move(present_cb);
+
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&VideoFrameCompositor::StartForceBeginFrames,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void VideoFrameCompositor::StartForceBeginFrames() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (!submitter_)
+ return;
+
+ submitter_->SetForceBeginFrames(true);
+ force_begin_frames_timer_.Reset();
+}
+
+void VideoFrameCompositor::StopForceBeginFrames() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ submitter_->SetForceBeginFrames(false);
+}
+
+std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata>
+VideoFrameCompositor::GetLastPresentedFrameMetadata() {
+ auto frame_metadata =
+ std::make_unique<WebMediaPlayer::VideoFramePresentationMetadata>();
+
+ scoped_refptr<media::VideoFrame> last_frame;
+ {
+ // Manually acquire the lock instead of calling GetCurrentFrameOnAnyThread()
+ // to also fetch the other frame dependent properties.
+ base::AutoLock lock(current_frame_lock_);
+ last_frame = current_frame_;
+ frame_metadata->presentation_time = last_presentation_time_;
+ frame_metadata->expected_display_time = last_expected_display_time_;
+ frame_metadata->presented_frames = presentation_counter_;
+ }
+
+ frame_metadata->width = last_frame->visible_rect().width();
+ frame_metadata->height = last_frame->visible_rect().height();
+
+ frame_metadata->media_time = last_frame->timestamp();
+
+ frame_metadata->metadata.MergeMetadataFrom(last_frame->metadata());
+
+ {
+ base::AutoLock lock(callback_lock_);
+ if (callback_) {
+ frame_metadata->average_frame_duration =
+ callback_->GetPreferredRenderInterval();
+ }
+ frame_metadata->rendering_interval = last_interval_;
+ }
+
+ return frame_metadata;
+}
+
+bool VideoFrameCompositor::ProcessNewFrame(
+ scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks presentation_time,
+ bool repaint_duplicate_frame) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ if (frame && GetCurrentFrame() && !repaint_duplicate_frame &&
+ frame->unique_id() == GetCurrentFrame()->unique_id()) {
+ return false;
+ }
+
+ // Set the flag indicating that the current frame is unrendered, if we get a
+ // subsequent PutCurrentFrame() call it will mark it as rendered.
+ rendered_last_frame_ = false;
+
+ // Copy to a local variable to avoid potential deadlock when executing the
+ // callback.
+ OnNewFramePresentedCB frame_presented_cb;
+ {
+ base::AutoLock lock(current_frame_lock_);
+ SetCurrentFrame_Locked(std::move(frame), presentation_time);
+ frame_presented_cb = std::move(new_presented_frame_cb_);
+ }
+
+ if (new_processed_frame_cb_)
+ std::move(new_processed_frame_cb_).Run(tick_clock_->NowTicks());
+
+ if (frame_presented_cb) {
+ std::move(frame_presented_cb).Run();
+ }
+
+ return true;
+}
+
+void VideoFrameCompositor::SetIsPageVisible(bool is_visible) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (submitter_)
+ submitter_->SetIsPageVisible(is_visible);
+}
+
+void VideoFrameCompositor::SetForceSubmit(bool force_submit) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ submitter_->SetForceSubmit(force_submit);
+}
+
+base::TimeDelta VideoFrameCompositor::GetLastIntervalWithoutLock()
+ NO_THREAD_SAFETY_ANALYSIS {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ // |last_interval_| is only updated on the compositor thread, so it's safe to
+ // return it without acquiring |callback_lock_|
+ return last_interval_;
+}
+
+void VideoFrameCompositor::BackgroundRender(RenderingMode mode) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ const base::TimeTicks now = tick_clock_->NowTicks();
+ last_background_render_ = now;
+ bool new_frame = CallRender(now, now + GetLastIntervalWithoutLock(), mode);
+ if (new_frame && IsClientSinkAvailable())
+ client_->DidReceiveFrame();
+}
+
+bool VideoFrameCompositor::CallRender(base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max,
+ RenderingMode mode) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ base::AutoLock lock(callback_lock_);
+
+ if (!callback_) {
+ // Even if we no longer have a callback, return true if we have a frame
+ // which |client_| hasn't seen before.
+ return !rendered_last_frame_ && GetCurrentFrame();
+ }
+
+ DCHECK(rendering_);
+
+ // If the previous frame was never rendered and we're in the normal rendering
+ // mode and haven't just exited background rendering, let the client know.
+ //
+ // We don't signal for mode == kBackground since we expect to drop frames. We
+ // also don't signal for mode == kStartup since UpdateCurrentFrame() may occur
+ // before the PutCurrentFrame() for the kStartup induced CallRender().
+ const bool was_background_rendering = is_background_rendering_;
+ if (!rendered_last_frame_ && GetCurrentFrame() &&
+ mode == RenderingMode::kNormal && !was_background_rendering) {
+ callback_->OnFrameDropped();
+ }
+
+ const bool new_frame = ProcessNewFrame(
+ callback_->Render(deadline_min, deadline_max, mode), deadline_min, false);
+
+ // In cases where mode == kStartup we still want to treat it like background
+ // rendering mode since CallRender() wasn't generated by UpdateCurrentFrame().
+ is_background_rendering_ = mode != RenderingMode::kNormal;
+ last_interval_ = deadline_max - deadline_min;
+
+ // We may create a new frame here with background rendering, but the provider
+ // has no way of knowing that a new frame had been processed, so keep track of
+ // the new frame, and return true on the next call to |CallRender|.
+ const bool had_new_background_frame = new_background_frame_;
+ new_background_frame_ = is_background_rendering_ && new_frame;
+
+ // Restart the background rendering timer whether we're background rendering
+ // or not; in either case we should wait for |kBackgroundRenderingTimeoutMs|.
+ if (background_rendering_enabled_)
+ background_rendering_timer_.Reset();
+ return new_frame || had_new_background_frame;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/video_frame_compositor_unittest.cc b/chromium/third_party/blink/renderer/platform/media/video_frame_compositor_unittest.cc
new file mode 100644
index 00000000000..1056847e7cf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/video_frame_compositor_unittest.cc
@@ -0,0 +1,494 @@
+// 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/media/video_frame_compositor.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/test/task_environment.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "media/base/video_frame.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_video_frame_submitter.h"
+
+namespace blink {
+
+using ::base::test::RunClosure;
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::Eq;
+using ::testing::Return;
+using ::testing::StrictMock;
+
+using RenderingMode = ::media::VideoRendererSink::RenderCallback::RenderingMode;
+
+class MockWebVideoFrameSubmitter : public WebVideoFrameSubmitter {
+ public:
+ // WebVideoFrameSubmitter implementation.
+ void StopUsingProvider() override {}
+ MOCK_METHOD1(EnableSubmission, void(viz::SurfaceId));
+ MOCK_METHOD0(StartRendering, void());
+ MOCK_METHOD0(StopRendering, void());
+ MOCK_CONST_METHOD0(IsDrivingFrameUpdates, bool(void));
+ MOCK_METHOD2(Initialize, void(cc::VideoFrameProvider*, bool));
+ MOCK_METHOD1(SetTransform, void(media::VideoTransformation));
+ MOCK_METHOD1(SetIsSurfaceVisible, void(bool));
+ MOCK_METHOD1(SetIsPageVisible, void(bool));
+ MOCK_METHOD1(SetForceSubmit, void(bool));
+ MOCK_METHOD1(SetForceBeginFrames, void(bool));
+ void DidReceiveFrame() override { ++did_receive_frame_count_; }
+
+ int did_receive_frame_count() { return did_receive_frame_count_; }
+
+ private:
+ int did_receive_frame_count_ = 0;
+};
+
+class VideoFrameCompositorTest
+ : public media::VideoRendererSink::RenderCallback,
+ public testing::Test {
+ public:
+ VideoFrameCompositorTest()
+ : client_(new StrictMock<MockWebVideoFrameSubmitter>()) {}
+ VideoFrameCompositorTest(const VideoFrameCompositorTest&) = delete;
+ VideoFrameCompositorTest& operator=(const VideoFrameCompositorTest&) = delete;
+
+ void SetUp() override {
+ submitter_ = client_.get();
+
+ EXPECT_CALL(*submitter_, Initialize(_, _));
+ compositor_ = std::make_unique<VideoFrameCompositor>(task_runner_,
+ std::move(client_));
+ base::RunLoop().RunUntilIdle();
+ constexpr auto kTestTransform = media::VideoTransformation(
+ media::VideoRotation::VIDEO_ROTATION_90, /*mirrored=*/false);
+ EXPECT_CALL(*submitter_, SetTransform(Eq(kTestTransform)));
+ EXPECT_CALL(*submitter_, SetForceSubmit(false));
+ EXPECT_CALL(*submitter_, EnableSubmission(Eq(viz::SurfaceId())));
+ compositor_->EnableSubmission(viz::SurfaceId(), kTestTransform, false);
+
+ compositor_->set_tick_clock_for_testing(&tick_clock_);
+ // Disable background rendering by default.
+ compositor_->set_background_rendering_for_testing(false);
+ }
+
+ ~VideoFrameCompositorTest() override {
+ compositor_->SetVideoFrameProviderClient(nullptr);
+ }
+
+ scoped_refptr<media::VideoFrame> CreateOpaqueFrame() {
+ return CreateOpaqueFrame(8, 8);
+ }
+
+ scoped_refptr<media::VideoFrame> CreateOpaqueFrame(int width, int height) {
+ gfx::Size size(width, height);
+ return media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_I420, size,
+ gfx::Rect(size), size,
+ base::TimeDelta());
+ }
+
+ VideoFrameCompositor* compositor() { return compositor_.get(); }
+
+ VideoFrameCompositor::OnNewFramePresentedCB GetNewFramePresentedCB() {
+ return base::BindOnce(&VideoFrameCompositorTest::OnNewFramePresented,
+ base::Unretained(this));
+ }
+
+ protected:
+ // VideoRendererSink::RenderCallback implementation.
+ MOCK_METHOD3(Render,
+ scoped_refptr<media::VideoFrame>(base::TimeTicks,
+ base::TimeTicks,
+ RenderingMode));
+ MOCK_METHOD0(OnFrameDropped, void());
+ MOCK_METHOD0(OnNewFramePresented, void());
+
+ base::TimeDelta GetPreferredRenderInterval() override {
+ return preferred_render_interval_;
+ }
+
+ void StartVideoRendererSink() {
+ EXPECT_CALL(*submitter_, StartRendering());
+ const bool had_current_frame = !!compositor_->GetCurrentFrame();
+ compositor()->Start(this);
+ // If we previously had a frame, we should still have one now.
+ EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void StopVideoRendererSink(bool have_client) {
+ if (have_client)
+ EXPECT_CALL(*submitter_, StopRendering());
+ const bool had_current_frame = !!compositor_->GetCurrentFrame();
+ compositor()->Stop();
+ // If we previously had a frame, we should still have one now.
+ EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void RenderFrame() {
+ compositor()->GetCurrentFrame();
+ compositor()->PutCurrentFrame();
+ }
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ base::TimeDelta preferred_render_interval_;
+ base::SimpleTestTickClock tick_clock_;
+ StrictMock<MockWebVideoFrameSubmitter>* submitter_;
+ std::unique_ptr<StrictMock<MockWebVideoFrameSubmitter>> client_;
+ std::unique_ptr<VideoFrameCompositor> compositor_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_ =
+ task_environment_.GetMainThreadTaskRunner();
+};
+
+TEST_F(VideoFrameCompositorTest, InitialValues) {
+ EXPECT_FALSE(compositor()->GetCurrentFrame().get());
+}
+
+TEST_F(VideoFrameCompositorTest, SetIsSurfaceVisible) {
+ auto cb = compositor()->GetUpdateSubmissionStateCallback();
+
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(*submitter_, SetIsSurfaceVisible(true));
+ cb.Run(true, nullptr);
+ task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(*submitter_, SetIsSurfaceVisible(false));
+ cb.Run(false, nullptr);
+ task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ {
+ base::RunLoop run_loop;
+ base::WaitableEvent true_event;
+ EXPECT_CALL(*submitter_, SetIsSurfaceVisible(true));
+ cb.Run(true, &true_event);
+ task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_TRUE(true_event.IsSignaled());
+ }
+
+ {
+ base::RunLoop run_loop;
+ base::WaitableEvent false_event;
+ EXPECT_CALL(*submitter_, SetIsSurfaceVisible(false));
+ cb.Run(false, &false_event);
+
+ task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_TRUE(false_event.IsSignaled());
+ }
+}
+
+TEST_F(VideoFrameCompositorTest, SetIsPageVisible) {
+ EXPECT_CALL(*submitter_, SetIsPageVisible(true));
+ compositor()->SetIsPageVisible(true);
+
+ EXPECT_CALL(*submitter_, SetIsPageVisible(false));
+ compositor()->SetIsPageVisible(false);
+}
+
+TEST_F(VideoFrameCompositorTest, PaintSingleFrame) {
+ scoped_refptr<media::VideoFrame> expected =
+ media::VideoFrame::CreateEOSFrame();
+
+ // Should notify compositor synchronously.
+ EXPECT_EQ(0, submitter_->did_receive_frame_count());
+ compositor()->PaintSingleFrame(expected);
+ scoped_refptr<media::VideoFrame> actual = compositor()->GetCurrentFrame();
+ EXPECT_EQ(expected, actual);
+ EXPECT_EQ(1, submitter_->did_receive_frame_count());
+}
+
+TEST_F(VideoFrameCompositorTest, RenderFiresPresentationCallback) {
+ // Advance the clock so we can differentiate between base::TimeTicks::Now()
+ // and base::TimeTicks().
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
+
+ scoped_refptr<media::VideoFrame> opaque_frame = CreateOpaqueFrame();
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kStartup))
+ .WillRepeatedly(Return(opaque_frame));
+ EXPECT_CALL(*this, OnNewFramePresented());
+ EXPECT_CALL(*submitter_, SetForceBeginFrames(true)).Times(AnyNumber());
+ compositor()->SetOnFramePresentedCallback(GetNewFramePresentedCB());
+ StartVideoRendererSink();
+ StopVideoRendererSink(true);
+
+ auto metadata = compositor()->GetLastPresentedFrameMetadata();
+ EXPECT_NE(base::TimeTicks(), metadata->presentation_time);
+ EXPECT_NE(base::TimeTicks(), metadata->expected_display_time);
+}
+
+TEST_F(VideoFrameCompositorTest, PresentationCallbackForcesBeginFrames) {
+ // A call to the requestVideoFrameCallback() API should set ForceBeginFrames.
+ EXPECT_CALL(*submitter_, SetForceBeginFrames(true));
+ compositor()->SetOnFramePresentedCallback(GetNewFramePresentedCB());
+ base::RunLoop().RunUntilIdle();
+
+ testing::Mock::VerifyAndClear(submitter_);
+
+ // The flag should be un-set when stop receiving callbacks.
+ base::RunLoop run_loop;
+ EXPECT_CALL(*submitter_, SetForceBeginFrames(false))
+ .WillOnce(RunClosure(run_loop.QuitClosure()));
+ run_loop.Run();
+
+ testing::Mock::VerifyAndClear(submitter_);
+}
+
+TEST_F(VideoFrameCompositorTest, MultiplePresentationCallbacks) {
+ // Advance the clock so we can differentiate between base::TimeTicks::Now()
+ // and base::TimeTicks().
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
+
+ // Create frames of different sizes so we can differentiate them.
+ constexpr int kSize1 = 8;
+ constexpr int kSize2 = 16;
+ constexpr int kSize3 = 24;
+ scoped_refptr<media::VideoFrame> opaque_frame_1 =
+ CreateOpaqueFrame(kSize1, kSize1);
+ scoped_refptr<media::VideoFrame> opaque_frame_2 =
+ CreateOpaqueFrame(kSize2, kSize2);
+ scoped_refptr<media::VideoFrame> opaque_frame_3 =
+ CreateOpaqueFrame(kSize3, kSize3);
+
+ EXPECT_CALL(*this, OnNewFramePresented()).Times(1);
+ EXPECT_CALL(*submitter_, SetForceBeginFrames(_)).Times(AnyNumber());
+ compositor()->SetOnFramePresentedCallback(GetNewFramePresentedCB());
+ compositor()->PaintSingleFrame(opaque_frame_1);
+
+ auto metadata = compositor()->GetLastPresentedFrameMetadata();
+ EXPECT_EQ(metadata->width, kSize1);
+ uint32_t first_presented_frames = metadata->presented_frames;
+
+ // Callbacks are one-shot, and shouldn't fire if they are not re-queued.
+ EXPECT_CALL(*this, OnNewFramePresented()).Times(0);
+ compositor()->PaintSingleFrame(opaque_frame_2);
+
+ // We should get the 2nd frame's metadata when we query for it.
+ metadata = compositor()->GetLastPresentedFrameMetadata();
+ EXPECT_EQ(first_presented_frames + 1, metadata->presented_frames);
+ EXPECT_EQ(metadata->width, kSize2);
+
+ EXPECT_CALL(*this, OnNewFramePresented()).Times(1);
+ compositor()->SetOnFramePresentedCallback(GetNewFramePresentedCB());
+ compositor()->PaintSingleFrame(opaque_frame_3);
+
+ // The presentated frames counter should have gone up twice by now.
+ metadata = compositor()->GetLastPresentedFrameMetadata();
+ EXPECT_EQ(first_presented_frames + 2, metadata->presented_frames);
+ EXPECT_EQ(metadata->width, kSize3);
+}
+
+TEST_F(VideoFrameCompositorTest, VideoRendererSinkFrameDropped) {
+ scoped_refptr<media::VideoFrame> opaque_frame = CreateOpaqueFrame();
+
+ EXPECT_CALL(*this, Render(_, _, _)).WillRepeatedly(Return(opaque_frame));
+ StartVideoRendererSink();
+
+ EXPECT_TRUE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ // Another call should trigger a dropped frame callback.
+ EXPECT_CALL(*this, OnFrameDropped());
+ EXPECT_FALSE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ // Ensure it always happens until the frame is rendered.
+ EXPECT_CALL(*this, OnFrameDropped());
+ EXPECT_FALSE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ // Call GetCurrentFrame() but not PutCurrentFrame()
+ compositor()->GetCurrentFrame();
+
+ // The frame should still register as dropped until PutCurrentFrame is called.
+ EXPECT_CALL(*this, OnFrameDropped());
+ EXPECT_FALSE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ RenderFrame();
+ EXPECT_FALSE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ StopVideoRendererSink(true);
+}
+
+TEST_F(VideoFrameCompositorTest, StartFiresBackgroundRender) {
+ scoped_refptr<media::VideoFrame> opaque_frame = CreateOpaqueFrame();
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kStartup))
+ .WillRepeatedly(Return(opaque_frame));
+ StartVideoRendererSink();
+ StopVideoRendererSink(true);
+}
+
+TEST_F(VideoFrameCompositorTest, BackgroundRenderTicks) {
+ scoped_refptr<media::VideoFrame> opaque_frame = CreateOpaqueFrame();
+ compositor_->set_background_rendering_for_testing(true);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kStartup))
+ .WillOnce(Return(opaque_frame));
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kBackground))
+ .WillOnce(
+ DoAll(RunClosure(run_loop.QuitClosure()), Return(opaque_frame)));
+ StartVideoRendererSink();
+ run_loop.Run();
+
+ // UpdateCurrentFrame() calls should indicate they are not synthetic.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kNormal))
+ .WillOnce(Return(opaque_frame));
+ EXPECT_FALSE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ // Background rendering should tick another render callback.
+ StopVideoRendererSink(true);
+}
+
+TEST_F(VideoFrameCompositorTest,
+ UpdateCurrentFrameWorksWhenBackgroundRendered) {
+ scoped_refptr<media::VideoFrame> opaque_frame = CreateOpaqueFrame();
+ compositor_->set_background_rendering_for_testing(true);
+
+ // Background render a frame that succeeds immediately.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kStartup))
+ .WillOnce(Return(opaque_frame));
+ StartVideoRendererSink();
+
+ // The background render completes immediately, so the next call to
+ // UpdateCurrentFrame is expected to return true to account for the frame
+ // rendered in the background.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kNormal))
+ .WillOnce(Return(scoped_refptr<media::VideoFrame>(opaque_frame)));
+ EXPECT_TRUE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+ RenderFrame();
+
+ // Second call to UpdateCurrentFrame will return false as no new frame has
+ // been created since the last call.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kNormal))
+ .WillOnce(Return(scoped_refptr<media::VideoFrame>(opaque_frame)));
+ EXPECT_FALSE(
+ compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
+
+ StopVideoRendererSink(true);
+}
+
+TEST_F(VideoFrameCompositorTest, UpdateCurrentFrameIfStale) {
+ scoped_refptr<media::VideoFrame> opaque_frame_1 = CreateOpaqueFrame();
+ scoped_refptr<media::VideoFrame> opaque_frame_2 = CreateOpaqueFrame();
+ compositor_->set_background_rendering_for_testing(true);
+
+ EXPECT_CALL(*submitter_, IsDrivingFrameUpdates)
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(true));
+
+ // Starting the video renderer should return a single frame.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kStartup))
+ .WillOnce(Return(opaque_frame_1));
+ StartVideoRendererSink();
+ EXPECT_EQ(opaque_frame_1, compositor()->GetCurrentFrame());
+
+ // Since we have a client, this call should not call background render, even
+ // if a lot of time has elapsed between calls.
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
+ EXPECT_CALL(*this, Render(_, _, _)).Times(0);
+ compositor()->UpdateCurrentFrameIfStale();
+
+ // Have the client signal that it will not drive the frame clock, so that
+ // calling UpdateCurrentFrameIfStale may update the frame.
+ EXPECT_CALL(*submitter_, IsDrivingFrameUpdates)
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(false));
+
+ // Wait for background rendering to tick.
+ base::RunLoop run_loop;
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kBackground))
+ .WillOnce(
+ DoAll(RunClosure(run_loop.QuitClosure()), Return(opaque_frame_2)));
+ run_loop.Run();
+
+ // This call should still not call background render, because not enough time
+ // has elapsed since the last background render call.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kBackground)).Times(0);
+ compositor()->UpdateCurrentFrameIfStale();
+ EXPECT_EQ(opaque_frame_2, compositor()->GetCurrentFrame());
+
+ // Advancing the tick clock should allow a new frame to be requested.
+ tick_clock_.Advance(base::TimeDelta::FromMilliseconds(10));
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kBackground))
+ .WillOnce(Return(opaque_frame_1));
+ compositor()->UpdateCurrentFrameIfStale();
+ EXPECT_EQ(opaque_frame_1, compositor()->GetCurrentFrame());
+
+ // Clear our client, which means no mock function calls for Client. It will
+ // also permit UpdateCurrentFrameIfStale to update the frame.
+ compositor()->SetVideoFrameProviderClient(nullptr);
+
+ // Advancing the tick clock should allow a new frame to be requested.
+ tick_clock_.Advance(base::TimeDelta::FromMilliseconds(10));
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kBackground))
+ .WillOnce(Return(opaque_frame_2));
+ compositor()->UpdateCurrentFrameIfStale();
+ EXPECT_EQ(opaque_frame_2, compositor()->GetCurrentFrame());
+
+ // Background rendering should tick another render callback.
+ StopVideoRendererSink(false);
+}
+
+TEST_F(VideoFrameCompositorTest, UpdateCurrentFrameIfStale_ClientBypass) {
+ scoped_refptr<media::VideoFrame> opaque_frame_1 = CreateOpaqueFrame();
+ scoped_refptr<media::VideoFrame> opaque_frame_2 = CreateOpaqueFrame();
+ compositor_->set_background_rendering_for_testing(true);
+
+ EXPECT_CALL(*submitter_, IsDrivingFrameUpdates)
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(true));
+
+ // Move the clock forward. Otherwise, the current time will be 0, will appear
+ // null, and will cause DCHECKs.
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
+
+ // Starting the video renderer should return a single frame.
+ EXPECT_CALL(*this, Render(_, _, RenderingMode::kStartup))
+ .WillOnce(Return(opaque_frame_1));
+ StartVideoRendererSink();
+ EXPECT_EQ(opaque_frame_1, compositor()->GetCurrentFrame());
+
+ // This call should return true even if we have a client that is driving frame
+ // updates.
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
+ EXPECT_CALL(*this, Render(_, _, _)).WillOnce(Return(opaque_frame_2));
+ compositor()->UpdateCurrentFrameIfStale(
+ VideoFrameCompositor::UpdateType::kBypassClient);
+ EXPECT_EQ(opaque_frame_2, compositor()->GetCurrentFrame());
+
+ StopVideoRendererSink(true);
+}
+
+TEST_F(VideoFrameCompositorTest, PreferredRenderInterval) {
+ preferred_render_interval_ = base::TimeDelta::FromSeconds(1);
+ compositor_->Start(this);
+ EXPECT_EQ(compositor_->GetPreferredRenderInterval(),
+ preferred_render_interval_);
+ compositor_->Stop();
+ EXPECT_EQ(compositor_->GetPreferredRenderInterval(),
+ viz::BeginFrameArgs::MinInterval());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/watch_time_reporter_unittest.cc b/chromium/third_party/blink/renderer/platform/media/watch_time_reporter_unittest.cc
new file mode 100644
index 00000000000..fddf4b96d68
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/watch_time_reporter_unittest.cc
@@ -0,0 +1,2398 @@
+// 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 <memory>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "media/base/mock_media_log.h"
+#include "media/base/pipeline_status.h"
+#include "media/base/watch_time_keys.h"
+#include "media/mojo/mojom/media_metrics_provider.mojom.h"
+#include "media/mojo/mojom/watch_time_recorder.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/media/display_type.h"
+#include "third_party/blink/public/common/media/watch_time_component.h"
+#include "third_party/blink/public/common/media/watch_time_reporter.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+
+namespace blink {
+
+using ::media::WatchTimeKey;
+using ::testing::_;
+
+constexpr gfx::Size kSizeTooSmall = gfx::Size(101, 101);
+constexpr gfx::Size kSizeJustRight = gfx::Size(201, 201);
+
+#define EXPECT_WATCH_TIME(key, value) \
+ do { \
+ EXPECT_CALL( \
+ *this, OnWatchTimeUpdate((has_video_ && has_audio_) \
+ ? WatchTimeKey::kAudioVideo##key \
+ : has_audio_ ? WatchTimeKey::kAudio##key \
+ : WatchTimeKey::kVideo##key, \
+ value)) \
+ .RetiresOnSaturation(); \
+ } while (0)
+
+#define EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(key, value) \
+ do { \
+ if (!has_video_ || !has_audio_) \
+ break; \
+ EXPECT_CALL(*this, \
+ OnWatchTimeUpdate(WatchTimeKey::kAudioVideoMuted##key, value)) \
+ .RetiresOnSaturation(); \
+ } while (0)
+
+#define EXPECT_WATCH_TIME_IF_VIDEO(key, value) \
+ do { \
+ if (!has_video_) \
+ break; \
+ EXPECT_CALL(*this, \
+ OnWatchTimeUpdate(has_audio_ ? WatchTimeKey::kAudioVideo##key \
+ : WatchTimeKey::kVideo##key, \
+ value)) \
+ .RetiresOnSaturation(); \
+ } while (0)
+
+#define EXPECT_BACKGROUND_WATCH_TIME(key, value) \
+ do { \
+ EXPECT_CALL(*this, \
+ OnWatchTimeUpdate( \
+ (has_video_ && has_audio_) \
+ ? WatchTimeKey::kAudioVideoBackground##key \
+ : has_audio_ ? WatchTimeKey::kAudioBackground##key \
+ : WatchTimeKey::kVideoBackground##key, \
+ value)) \
+ .RetiresOnSaturation(); \
+ } while (0)
+
+#define EXPECT_WATCH_TIME_FINALIZED() \
+ EXPECT_CALL(*this, OnWatchTimeFinalized()).RetiresOnSaturation();
+
+// The following macros have .Times() values equal to the number of keys that a
+// finalize event is expected to finalize.
+#define EXPECT_POWER_WATCH_TIME_FINALIZED() \
+ EXPECT_CALL(*this, OnPowerWatchTimeFinalized()) \
+ .Times(2) \
+ .RetiresOnSaturation();
+
+#define EXPECT_CONTROLS_WATCH_TIME_FINALIZED() \
+ EXPECT_CALL(*this, OnControlsWatchTimeFinalized()) \
+ .Times(2) \
+ .RetiresOnSaturation();
+
+#define EXPECT_DISPLAY_WATCH_TIME_FINALIZED() \
+ EXPECT_CALL(*this, OnDisplayWatchTimeFinalized()) \
+ .Times(3) \
+ .RetiresOnSaturation();
+
+using WatchTimeReporterTestData = std::tuple<bool, bool>;
+class WatchTimeReporterTest
+ : public testing::TestWithParam<WatchTimeReporterTestData> {
+ public:
+ class WatchTimeInterceptor : public media::mojom::WatchTimeRecorder {
+ public:
+ WatchTimeInterceptor(WatchTimeReporterTest* parent) : parent_(parent) {}
+ WatchTimeInterceptor(const WatchTimeInterceptor&) = delete;
+ WatchTimeInterceptor& operator=(const WatchTimeInterceptor&) = delete;
+ ~WatchTimeInterceptor() override = default;
+
+ // mojom::WatchTimeRecorder implementation:
+ void RecordWatchTime(WatchTimeKey key, base::TimeDelta value) override {
+ parent_->OnWatchTimeUpdate(key, value);
+ }
+
+ void FinalizeWatchTime(
+ const std::vector<WatchTimeKey>& watch_time_keys) override {
+ if (watch_time_keys.empty()) {
+ parent_->OnWatchTimeFinalized();
+ } else {
+ for (auto key : watch_time_keys) {
+ switch (key) {
+ case WatchTimeKey::kAudioBattery:
+ case WatchTimeKey::kAudioAc:
+ case WatchTimeKey::kAudioBackgroundBattery:
+ case WatchTimeKey::kAudioBackgroundAc:
+ case WatchTimeKey::kAudioVideoBattery:
+ case WatchTimeKey::kAudioVideoAc:
+ case WatchTimeKey::kAudioVideoMutedBattery:
+ case WatchTimeKey::kAudioVideoMutedAc:
+ case WatchTimeKey::kAudioVideoBackgroundBattery:
+ case WatchTimeKey::kAudioVideoBackgroundAc:
+ case WatchTimeKey::kVideoBattery:
+ case WatchTimeKey::kVideoAc:
+ case WatchTimeKey::kVideoBackgroundBattery:
+ case WatchTimeKey::kVideoBackgroundAc:
+ parent_->OnPowerWatchTimeFinalized();
+ break;
+
+ case WatchTimeKey::kAudioNativeControlsOn:
+ case WatchTimeKey::kAudioNativeControlsOff:
+ case WatchTimeKey::kAudioVideoNativeControlsOn:
+ case WatchTimeKey::kAudioVideoNativeControlsOff:
+ case WatchTimeKey::kAudioVideoMutedNativeControlsOn:
+ case WatchTimeKey::kAudioVideoMutedNativeControlsOff:
+ case WatchTimeKey::kVideoNativeControlsOn:
+ case WatchTimeKey::kVideoNativeControlsOff:
+ parent_->OnControlsWatchTimeFinalized();
+ break;
+
+ case WatchTimeKey::kAudioVideoDisplayFullscreen:
+ case WatchTimeKey::kAudioVideoDisplayInline:
+ case WatchTimeKey::kAudioVideoDisplayPictureInPicture:
+ case WatchTimeKey::kAudioVideoMutedDisplayFullscreen:
+ case WatchTimeKey::kAudioVideoMutedDisplayInline:
+ case WatchTimeKey::kAudioVideoMutedDisplayPictureInPicture:
+ case WatchTimeKey::kVideoDisplayFullscreen:
+ case WatchTimeKey::kVideoDisplayInline:
+ case WatchTimeKey::kVideoDisplayPictureInPicture:
+ parent_->OnDisplayWatchTimeFinalized();
+ break;
+
+ case WatchTimeKey::kAudioAll:
+ case WatchTimeKey::kAudioMse:
+ case WatchTimeKey::kAudioEme:
+ case WatchTimeKey::kAudioSrc:
+ case WatchTimeKey::kAudioEmbeddedExperience:
+ case WatchTimeKey::kAudioBackgroundAll:
+ case WatchTimeKey::kAudioBackgroundMse:
+ case WatchTimeKey::kAudioBackgroundEme:
+ case WatchTimeKey::kAudioBackgroundSrc:
+ case WatchTimeKey::kAudioBackgroundEmbeddedExperience:
+ case WatchTimeKey::kAudioVideoAll:
+ case WatchTimeKey::kAudioVideoMse:
+ case WatchTimeKey::kAudioVideoEme:
+ case WatchTimeKey::kAudioVideoSrc:
+ case WatchTimeKey::kAudioVideoEmbeddedExperience:
+ case WatchTimeKey::kAudioVideoMutedAll:
+ case WatchTimeKey::kAudioVideoMutedMse:
+ case WatchTimeKey::kAudioVideoMutedEme:
+ case WatchTimeKey::kAudioVideoMutedSrc:
+ case WatchTimeKey::kAudioVideoMutedEmbeddedExperience:
+ case WatchTimeKey::kAudioVideoBackgroundAll:
+ case WatchTimeKey::kAudioVideoBackgroundMse:
+ case WatchTimeKey::kAudioVideoBackgroundEme:
+ case WatchTimeKey::kAudioVideoBackgroundSrc:
+ case WatchTimeKey::kAudioVideoBackgroundEmbeddedExperience:
+ case WatchTimeKey::kVideoAll:
+ case WatchTimeKey::kVideoMse:
+ case WatchTimeKey::kVideoEme:
+ case WatchTimeKey::kVideoSrc:
+ case WatchTimeKey::kVideoEmbeddedExperience:
+ case WatchTimeKey::kVideoBackgroundAll:
+ case WatchTimeKey::kVideoBackgroundMse:
+ case WatchTimeKey::kVideoBackgroundEme:
+ case WatchTimeKey::kVideoBackgroundSrc:
+ case WatchTimeKey::kVideoBackgroundEmbeddedExperience:
+ // These keys do not support partial finalization.
+ FAIL();
+ };
+ }
+ }
+ }
+
+ void OnError(media::PipelineStatus status) override {
+ parent_->OnError(status);
+ }
+
+ void UpdateSecondaryProperties(media::mojom::SecondaryPlaybackPropertiesPtr
+ secondary_properties) override {
+ parent_->OnUpdateSecondaryProperties(std::move(secondary_properties));
+ }
+
+ void UpdateUnderflowCount(int32_t count) override {
+ parent_->OnUnderflowUpdate(count);
+ }
+
+ void UpdateUnderflowDuration(int32_t total_completed_count,
+ base::TimeDelta total_duration) override {
+ parent_->OnUnderflowDurationUpdate(total_completed_count, total_duration);
+ }
+
+ void SetAutoplayInitiated(bool value) override {
+ parent_->OnSetAutoplayInitiated(value);
+ }
+
+ void OnDurationChanged(base::TimeDelta duration) override {
+ parent_->OnDurationChanged(duration);
+ }
+
+ void UpdateVideoDecodeStats(uint32_t video_frames_decoded,
+ uint32_t video_frames_dropped) override {
+ parent_->OnUpdateVideoDecodeStats(video_frames_decoded,
+ video_frames_dropped);
+ }
+
+ void OnCurrentTimestampChanged(base::TimeDelta duration) override {
+ parent_->OnCurrentTimestampChanged(duration);
+ }
+
+ private:
+ WatchTimeReporterTest* parent_;
+ };
+
+ class FakeMediaMetricsProvider : public media::mojom::MediaMetricsProvider {
+ public:
+ explicit FakeMediaMetricsProvider(WatchTimeReporterTest* parent)
+ : parent_(parent) {}
+ ~FakeMediaMetricsProvider() override {}
+
+ // mojom::WatchTimeRecorderProvider implementation:
+ void AcquireWatchTimeRecorder(
+ media::mojom::PlaybackPropertiesPtr properties,
+ mojo::PendingReceiver<media::mojom::WatchTimeRecorder> receiver)
+ override {
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<WatchTimeInterceptor>(parent_), std::move(receiver));
+ }
+ void AcquireVideoDecodeStatsRecorder(
+ mojo::PendingReceiver<media::mojom::VideoDecodeStatsRecorder> receiver)
+ override {
+ FAIL();
+ }
+ void AcquireLearningTaskController(
+ const std::string& taskName,
+ mojo::PendingReceiver<media::learning::mojom::LearningTaskController>
+ receiver) override {}
+ void AcquirePlaybackEventsRecorder(
+ mojo::PendingReceiver<media::mojom::PlaybackEventsRecorder> receiver)
+ override {}
+ void Initialize(bool is_mse,
+ media::mojom::MediaURLScheme url_scheme,
+ media::mojom::MediaStreamType media_stream_type) override {}
+ void OnError(media::PipelineStatus status) override {}
+ void SetIsEME() override {}
+ void SetTimeToMetadata(base::TimeDelta elapsed) override {}
+ void SetTimeToFirstFrame(base::TimeDelta elapsed) override {}
+ void SetTimeToPlayReady(base::TimeDelta elapsed) override {}
+ void SetContainerName(
+ media::container_names::MediaContainerName container_name) override {}
+ void SetRendererType(media::RendererType renderer_type) override {}
+ void SetKeySystem(const std::string& key_system) override {}
+ void SetIsHardwareSecure() override {}
+ void SetHasPlayed() override {}
+ void SetHaveEnough() override {}
+ void SetHasAudio(media::AudioCodec audio_codec) override {}
+ void SetHasVideo(media::VideoCodec video_codec) override {}
+ void SetVideoPipelineInfo(const media::VideoPipelineInfo& info) override {}
+ void SetAudioPipelineInfo(const media::AudioPipelineInfo& info) override {}
+
+ private:
+ WatchTimeReporterTest* parent_;
+ };
+
+ WatchTimeReporterTest()
+ : has_video_(std::get<0>(GetParam())),
+ has_audio_(std::get<1>(GetParam())),
+ fake_metrics_provider_(this) {}
+
+ WatchTimeReporterTest(const WatchTimeReporterTest&) = delete;
+ WatchTimeReporterTest& operator=(const WatchTimeReporterTest&) = delete;
+
+ ~WatchTimeReporterTest() override {
+ CycleReportingTimer();
+ }
+
+ protected:
+ void Initialize(bool is_mse,
+ bool is_encrypted,
+ const gfx::Size& initial_video_size) {
+ if (wtr_ && IsMonitoring())
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ wtr_ = std::make_unique<WatchTimeReporter>(
+ media::mojom::PlaybackProperties::New(
+ has_audio_, has_video_, false, false, is_mse, is_encrypted, false,
+ media::mojom::MediaStreamType::kNone),
+ initial_video_size,
+ base::BindRepeating(&WatchTimeReporterTest::GetCurrentMediaTime,
+ base::Unretained(this)),
+ base::BindRepeating(&WatchTimeReporterTest::GetPipelineStatistics,
+ base::Unretained(this)),
+ &fake_metrics_provider_, scheduler::GetSequencedTaskRunnerForTesting(),
+ task_environment_.GetMockTickClock());
+ reporting_interval_ = wtr_->reporting_interval_;
+
+ // Most tests don't care about this.
+ EXPECT_CALL(*this, GetPipelineStatistics())
+ .WillRepeatedly(testing::Return(media::PipelineStatistics()));
+ EXPECT_CALL(*this, OnUpdateVideoDecodeStats(_, _))
+ .Times(testing::AnyNumber());
+ }
+
+ void CycleReportingTimer() {
+ task_environment_.FastForwardBy(reporting_interval_);
+ }
+
+ bool IsMonitoring() const { return wtr_->reporting_timer_.IsRunning(); }
+
+ bool IsBackgroundMonitoring() const {
+ return wtr_->background_reporter_->reporting_timer_.IsRunning();
+ }
+
+ bool IsMutedMonitoring() const {
+ return wtr_->muted_reporter_ &&
+ wtr_->muted_reporter_->reporting_timer_.IsRunning();
+ }
+
+ void DisableMutedReporting() { wtr_->muted_reporter_.reset(); }
+
+ // We call directly into the reporter for this instead of using an actual
+ // PowerMonitorTestSource since that results in a posted tasks which interfere
+ // with our ability to test the timer.
+ void SetOnBatteryPower(bool on_battery_power) {
+ wtr_->power_component_->SetCurrentValue(on_battery_power);
+ }
+
+ bool IsOnBatteryPower() const {
+ return wtr_->power_component_->current_value_for_testing();
+ }
+
+ void OnPowerStateChange(bool on_battery_power) {
+ wtr_->OnPowerStateChange(on_battery_power);
+ if (wtr_->background_reporter_)
+ wtr_->background_reporter_->OnPowerStateChange(on_battery_power);
+ if (wtr_->muted_reporter_)
+ wtr_->muted_reporter_->OnPowerStateChange(on_battery_power);
+ }
+
+ void OnNativeControlsEnabled(bool enabled) {
+ enabled ? wtr_->OnNativeControlsEnabled()
+ : wtr_->OnNativeControlsDisabled();
+ }
+
+ void OnDisplayTypeChanged(DisplayType display_type) {
+ wtr_->OnDisplayTypeChanged(display_type);
+ }
+
+ enum {
+ // After |test_callback_func| is executed, should watch time continue to
+ // accumulate?
+ kAccumulationContinuesAfterTest = 1,
+
+ // |test_callback_func| for hysteresis tests enters and exits finalize mode
+ // for watch time, not all exits require a new current time update.
+ kFinalizeExitDoesNotRequireCurrentTime = 2,
+
+ // During finalize the watch time should not continue on the starting power
+ // metric. By default this means the AC metric will be finalized, but if
+ // used with |kStartOnBattery| it will be the battery metric.
+ kFinalizePowerWatchTime = 4,
+
+ // During finalize the power watch time should continue on the metric
+ // opposite the starting metric (by default it's AC, it's battery if
+ // |kStartOnBattery| is specified.
+ kTransitionPowerWatchTime = 8,
+
+ // Indicates that power watch time should be reported to the battery metric.
+ kStartOnBattery = 16,
+
+ // Indicates an extra start event may be generated during test execution.
+ kFinalizeInterleavedStartEvent = 32,
+
+ // During finalize the watch time should not continue on the starting
+ // controls metric. By default this means the NativeControsOff metric will
+ // be finalized, but if used with |kStartWithNativeControls| it will be the
+ // NativeControlsOn metric.
+ kFinalizeControlsWatchTime = 64,
+
+ // During finalize the controls watch time should continue on the metric
+ // opposite the starting metric (by default it's non-native controls, it's
+ // native controls if |kStartWithNativeControls| is specified.
+ kTransitionControlsWatchTime = 128,
+
+ // Indicates that controls watch time should be reported to the native
+ // controls metric.
+ kStartWithNativeControls = 256,
+
+ // During finalize the watch time should not continue on the starting
+ // display metric. By default this means the DisplayInline metric will be
+ // finalized, but if used with |kStartWithDisplayFullscreen| it will be the
+ // DisplayFullscreen metric.
+ kFinalizeDisplayWatchTime = 1024,
+
+ // During finalize the display watch time should continue on the metric
+ // opposite the starting metric (by default it's inline, it's fullscreen if
+ // |kStartWithDisplayFullscreen| is specified.
+ kTransitionDisplayWatchTime = 2048,
+
+ // Indicates that the watch time should be reporter to the fullscreen
+ // display metric.
+ kStartWithDisplayFullscreen = 4096,
+ };
+
+ template <int TestFlags = 0, typename HysteresisTestCallback>
+ void RunHysteresisTest(HysteresisTestCallback test_callback_func) {
+ Initialize(false, false, kSizeJustRight);
+
+ // Disable nested reporters for the hysteresis tests.
+ wtr_->background_reporter_.reset();
+ wtr_->muted_reporter_.reset();
+
+ if (TestFlags & kStartWithNativeControls)
+ OnNativeControlsEnabled(true);
+ if (TestFlags & kStartWithDisplayFullscreen)
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+
+ // Setup all current time expectations first since they need to use the
+ // InSequence macro for ease of use, but we don't want the watch time
+ // expectations to be in sequence (or expectations would depend on sorted
+ // order of histogram names).
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(10);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(12);
+ constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(15);
+ constexpr base::TimeDelta kWatchTime4 = base::TimeDelta::FromSeconds(30);
+ {
+ testing::InSequence s;
+
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1));
+
+ // Setup conditions depending on if the test will not resume watch time
+ // accumulation or not; i.e. the finalize criteria will not be undone
+ // within the hysteresis time.
+ if (TestFlags & kAccumulationContinuesAfterTest) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .Times(TestFlags & (kFinalizeExitDoesNotRequireCurrentTime |
+ kFinalizePowerWatchTime |
+ kFinalizeControlsWatchTime |
+ kFinalizeDisplayWatchTime)
+ ? 1
+ : 2)
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(kWatchTime3));
+ } else {
+ // Current time should be requested when entering the finalize state.
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .Times(TestFlags & kFinalizeInterleavedStartEvent ? 2 : 1)
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ }
+
+ if (TestFlags & kTransitionPowerWatchTime) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(kWatchTime4));
+ }
+
+ if (TestFlags & kTransitionControlsWatchTime) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(kWatchTime4));
+ }
+
+ if (TestFlags & kTransitionDisplayWatchTime) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(kWatchTime4));
+ }
+ }
+
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+ if (TestFlags & kStartOnBattery)
+ SetOnBatteryPower(true);
+ else
+ ASSERT_FALSE(IsOnBatteryPower());
+
+ EXPECT_WATCH_TIME(All, kWatchTime1);
+ EXPECT_WATCH_TIME(Src, kWatchTime1);
+ if (TestFlags & kStartOnBattery)
+ EXPECT_WATCH_TIME(Battery, kWatchTime1);
+ else
+ EXPECT_WATCH_TIME(Ac, kWatchTime1);
+ if (TestFlags & kStartWithNativeControls)
+ EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime1);
+ else
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+ if (TestFlags & kStartWithDisplayFullscreen)
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kWatchTime1);
+ else
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+
+ CycleReportingTimer();
+
+ // Invoke the test.
+ test_callback_func();
+
+ const base::TimeDelta kExpectedWatchTime =
+ TestFlags & kAccumulationContinuesAfterTest ? kWatchTime3 : kWatchTime2;
+
+ EXPECT_WATCH_TIME(All, kExpectedWatchTime);
+ EXPECT_WATCH_TIME(Src, kExpectedWatchTime);
+ const base::TimeDelta kExpectedPowerWatchTime =
+ TestFlags & kFinalizePowerWatchTime ? kWatchTime2 : kExpectedWatchTime;
+ const base::TimeDelta kExpectedContolsWatchTime =
+ TestFlags & kFinalizeControlsWatchTime ? kWatchTime2
+ : kExpectedWatchTime;
+ const base::TimeDelta kExpectedDisplayWatchTime =
+ TestFlags & kFinalizeDisplayWatchTime ? kWatchTime2
+ : kExpectedWatchTime;
+
+ if (TestFlags & kStartOnBattery)
+ EXPECT_WATCH_TIME(Battery, kExpectedPowerWatchTime);
+ else
+ EXPECT_WATCH_TIME(Ac, kExpectedPowerWatchTime);
+
+ if (TestFlags & kStartWithNativeControls)
+ EXPECT_WATCH_TIME(NativeControlsOn, kExpectedContolsWatchTime);
+ else
+ EXPECT_WATCH_TIME(NativeControlsOff, kExpectedContolsWatchTime);
+
+ if (TestFlags & kStartWithDisplayFullscreen)
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kExpectedDisplayWatchTime);
+ else
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kExpectedDisplayWatchTime);
+
+ // Special case when testing battery watch time.
+ if (TestFlags & kTransitionPowerWatchTime) {
+ ASSERT_TRUE(TestFlags & kAccumulationContinuesAfterTest)
+ << "kTransitionPowerWatchTime tests must be done with "
+ "kAccumulationContinuesAfterTest";
+
+ EXPECT_POWER_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ // Run one last cycle that is long enough to trigger a new watch time
+ // entry on the opposite of the current power watch time graph; i.e. if we
+ // started on battery we'll now record one for ac and vice versa.
+ EXPECT_WATCH_TIME(All, kWatchTime4);
+ EXPECT_WATCH_TIME(Src, kWatchTime4);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime4);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime4);
+ if (TestFlags & kStartOnBattery)
+ EXPECT_WATCH_TIME(Ac, kWatchTime4 - kWatchTime2);
+ else
+ EXPECT_WATCH_TIME(Battery, kWatchTime4 - kWatchTime2);
+ } else if (TestFlags & kTransitionControlsWatchTime) {
+ ASSERT_TRUE(TestFlags & kAccumulationContinuesAfterTest)
+ << "kTransitionControlsWatchTime tests must be done with "
+ "kAccumulationContinuesAfterTest";
+
+ EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ // Run one last cycle that is long enough to trigger a new watch time
+ // entry on the opposite of the current power watch time graph; i.e. if we
+ // started on battery we'll now record one for ac and vice versa.
+ EXPECT_WATCH_TIME(All, kWatchTime4);
+ EXPECT_WATCH_TIME(Src, kWatchTime4);
+ EXPECT_WATCH_TIME(Ac, kWatchTime4);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime4);
+ if (TestFlags & kStartWithNativeControls)
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime4 - kWatchTime2);
+ else
+ EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime4 - kWatchTime2);
+ } else if (TestFlags & kTransitionDisplayWatchTime) {
+ ASSERT_TRUE(TestFlags & kAccumulationContinuesAfterTest)
+ << "kTransitionDisplayWatchTime tests must be done with "
+ "kAccumulationContinuesAfterTest";
+
+ EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ // Run one last cycle that is long enough to trigger a new watch time
+ // entry on the opposite of the current power watch time graph; i.e. if we
+ // started on battery we'll now record one for ac and vice versa.
+ EXPECT_WATCH_TIME(All, kWatchTime4);
+ EXPECT_WATCH_TIME(Src, kWatchTime4);
+ EXPECT_WATCH_TIME(Ac, kWatchTime4);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime4);
+ if (TestFlags & kStartWithDisplayFullscreen) {
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime4 - kWatchTime2);
+ } else {
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen,
+ kWatchTime4 - kWatchTime2);
+ }
+ }
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+ }
+
+ MOCK_METHOD0(GetCurrentMediaTime, base::TimeDelta());
+ MOCK_METHOD0(GetPipelineStatistics, media::PipelineStatistics());
+
+ MOCK_METHOD0(OnWatchTimeFinalized, void(void));
+ MOCK_METHOD0(OnPowerWatchTimeFinalized, void(void));
+ MOCK_METHOD0(OnControlsWatchTimeFinalized, void(void));
+ MOCK_METHOD0(OnDisplayWatchTimeFinalized, void(void));
+ MOCK_METHOD2(OnWatchTimeUpdate, void(WatchTimeKey, base::TimeDelta));
+ MOCK_METHOD1(OnUnderflowUpdate, void(int));
+ MOCK_METHOD2(OnUnderflowDurationUpdate, void(int, base::TimeDelta));
+ MOCK_METHOD1(OnError, void(media::PipelineStatus));
+ MOCK_METHOD1(OnUpdateSecondaryProperties,
+ void(media::mojom::SecondaryPlaybackPropertiesPtr));
+ MOCK_METHOD1(OnSetAutoplayInitiated, void(bool));
+ MOCK_METHOD1(OnDurationChanged, void(base::TimeDelta));
+ MOCK_METHOD2(OnUpdateVideoDecodeStats, void(uint32_t, uint32_t));
+ MOCK_METHOD1(OnCurrentTimestampChanged, void(base::TimeDelta));
+
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ const bool has_video_;
+ const bool has_audio_;
+
+ FakeMediaMetricsProvider fake_metrics_provider_;
+ std::unique_ptr<WatchTimeReporter> wtr_;
+ base::TimeDelta reporting_interval_;
+};
+
+class DisplayTypeWatchTimeReporterTest : public WatchTimeReporterTest {};
+
+// Tests that watch time reporting is appropriately enabled or disabled.
+TEST_P(WatchTimeReporterTest, WatchTimeReporter) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillRepeatedly(testing::Return(base::TimeDelta()));
+
+ Initialize(true, true, gfx::Size());
+ wtr_->OnPlaying();
+ EXPECT_EQ(!has_video_, IsMonitoring());
+
+ Initialize(true, true, gfx::Size());
+ wtr_->OnPlaying();
+ EXPECT_EQ(!has_video_, IsMonitoring());
+
+ constexpr gfx::Size kSizeTooSmall = gfx::Size(100, 100);
+ Initialize(true, true, kSizeTooSmall);
+ wtr_->OnPlaying();
+ EXPECT_EQ(!has_video_, IsMonitoring());
+
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ Initialize(false, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ Initialize(true, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_CALL(*this, OnError(media::PIPELINE_ERROR_DECODE))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->OnError(media::PIPELINE_ERROR_DECODE);
+
+ Initialize(true, true, gfx::Size());
+ wtr_->OnPlaying();
+ EXPECT_EQ(!has_video_, IsMonitoring());
+
+ Initialize(false, false, gfx::Size());
+ wtr_->OnPlaying();
+ EXPECT_EQ(!has_video_, IsMonitoring());
+
+ Initialize(true, false, gfx::Size());
+ wtr_->OnPlaying();
+ EXPECT_EQ(!has_video_, IsMonitoring());
+
+ if (!has_video_)
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterInfiniteStartTime) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillRepeatedly(testing::Return(media::kInfiniteDuration));
+ Initialize(false, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_FALSE(IsMonitoring());
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterBasic) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ Initialize(true, true, kSizeJustRight);
+
+ media::PipelineStatistics stats;
+ stats.video_frames_decoded = 10;
+ stats.video_frames_dropped = 2;
+ if (has_video_) {
+ EXPECT_CALL(*this, GetPipelineStatistics())
+ .WillOnce(testing::Return(media::PipelineStatistics()))
+ .WillRepeatedly(testing::Return(stats));
+ EXPECT_CALL(*this, OnUpdateVideoDecodeStats(stats.video_frames_decoded,
+ stats.video_frames_dropped));
+ }
+
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
+ CycleReportingTimer();
+
+ wtr_->OnUnderflow();
+ constexpr base::TimeDelta kUnderflowDuration =
+ base::TimeDelta::FromMilliseconds(250);
+ wtr_->OnUnderflowComplete(kUnderflowDuration);
+ wtr_->OnUnderflow();
+ EXPECT_WATCH_TIME(Ac, kWatchTimeLate);
+ EXPECT_WATCH_TIME(All, kWatchTimeLate);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeLate);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeLate);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeLate);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeLate);
+ EXPECT_CALL(*this, OnUnderflowUpdate(2));
+ EXPECT_CALL(*this, OnUnderflowDurationUpdate(1, kUnderflowDuration));
+ CycleReportingTimer();
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterStatsOffsetCorrectly) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ Initialize(true, true, kSizeJustRight);
+
+ media::PipelineStatistics initial_stats;
+ initial_stats.video_frames_decoded = 10;
+ initial_stats.video_frames_dropped = 2;
+
+ media::PipelineStatistics stats;
+ stats.video_frames_decoded = 17;
+ stats.video_frames_dropped = 7;
+ if (has_video_) {
+ EXPECT_CALL(*this, GetPipelineStatistics())
+ .WillOnce(testing::Return(initial_stats))
+ .WillRepeatedly(testing::Return(stats));
+ EXPECT_CALL(
+ *this,
+ OnUpdateVideoDecodeStats(
+ stats.video_frames_decoded - initial_stats.video_frames_decoded,
+ stats.video_frames_dropped - initial_stats.video_frames_dropped));
+ }
+
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
+ CycleReportingTimer();
+
+ wtr_->OnUnderflow();
+ constexpr base::TimeDelta kUnderflowDuration =
+ base::TimeDelta::FromMilliseconds(250);
+ wtr_->OnUnderflowComplete(kUnderflowDuration);
+ wtr_->OnUnderflow();
+ EXPECT_WATCH_TIME(Ac, kWatchTimeLate);
+ EXPECT_WATCH_TIME(All, kWatchTimeLate);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeLate);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeLate);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeLate);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeLate);
+ EXPECT_CALL(*this, OnUnderflowUpdate(2));
+ EXPECT_CALL(*this, OnUnderflowDurationUpdate(1, kUnderflowDuration));
+ CycleReportingTimer();
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterDuration) {
+ constexpr base::TimeDelta kDuration1 = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kDuration2 = base::TimeDelta::FromSeconds(10);
+ Initialize(true, true, kSizeJustRight);
+
+ EXPECT_CALL(*this, OnDurationChanged(kDuration1))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->OnDurationChanged(kDuration1);
+ CycleReportingTimer();
+
+ EXPECT_CALL(*this, OnDurationChanged(kDuration2))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->OnDurationChanged(kDuration2);
+ CycleReportingTimer();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterUnderflow) {
+ constexpr base::TimeDelta kWatchTimeFirst = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(10);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(15);
+ if (has_audio_ && has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // Extra 2 for muted.
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ } else {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ }
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(All, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeFirst);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeFirst);
+ CycleReportingTimer();
+
+ wtr_->OnUnderflow();
+ wtr_->OnVolumeChange(0);
+
+ constexpr base::TimeDelta kUnderflowDuration =
+ base::TimeDelta::FromMilliseconds(250);
+ wtr_->OnUnderflowComplete(kUnderflowDuration);
+
+ // This underflow call should be ignored since it happens after the finalize.
+ // Note: We use a muted call above to trigger finalize instead of say a pause
+ // since media time will be the same in the event of a pause and no underflow
+ // should trigger after a pause in any case.
+ wtr_->OnUnderflow();
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ // Since we're using a mute event above, we'll have some muted watch time.
+ const base::TimeDelta kWatchTime = kWatchTimeLate - kWatchTimeEarly;
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime);
+
+ EXPECT_CALL(*this, OnUnderflowUpdate(1))
+ .Times((has_audio_ && has_video_) ? 2 : 1);
+ EXPECT_CALL(*this, OnUnderflowDurationUpdate(1, kUnderflowDuration));
+ CycleReportingTimer();
+
+ // Muted watch time shouldn't finalize until destruction.
+ if (has_audio_ && has_video_)
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterUnderflowSpansFinalize) {
+ constexpr base::TimeDelta kWatchTimeFirst = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(10);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(15);
+ if (has_audio_ && has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // Extra 2 for muted.
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ } else {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ }
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(All, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeFirst);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeFirst);
+ CycleReportingTimer();
+
+ wtr_->OnUnderflow();
+ wtr_->OnVolumeChange(0);
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ // Since we're using a mute event above, we'll have some muted watch time.
+ const base::TimeDelta kWatchTime = kWatchTimeLate - kWatchTimeEarly;
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_CALL(*this, OnUnderflowUpdate(1));
+ CycleReportingTimer();
+
+ // Muted watch time shouldn't finalize until destruction.
+ if (has_audio_ && has_video_)
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ // This underflow completion should be dropped since we've lost the original
+ // underflow it corresponded to in the finalize.
+ constexpr base::TimeDelta kUnderflowDuration =
+ base::TimeDelta::FromMilliseconds(250);
+ wtr_->OnUnderflowComplete(kUnderflowDuration);
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterUnderflowTooLong) {
+ constexpr base::TimeDelta kWatchTimeFirst = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(10);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(15);
+ if (has_audio_ && has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // Extra 2 for muted.
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ } else {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ }
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(All, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeFirst);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeFirst);
+ CycleReportingTimer();
+
+ wtr_->OnUnderflow();
+ wtr_->OnVolumeChange(0);
+
+ // This underflow took too long to complete so is dropped.
+ constexpr base::TimeDelta kUnderflowDuration =
+ base::TimeDelta::FromMinutes(2);
+ wtr_->OnUnderflowComplete(kUnderflowDuration);
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ // Since we're using a mute event above, we'll have some muted watch time.
+ const base::TimeDelta kWatchTime = kWatchTimeLate - kWatchTimeEarly;
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_CALL(*this, OnUnderflowUpdate(1));
+ CycleReportingTimer();
+
+ // Muted watch time shouldn't finalize until destruction.
+ if (has_audio_ && has_video_)
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterNoUnderflowDoubleReport) {
+ constexpr base::TimeDelta kWatchTimeFirst = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(10);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(15);
+ if (has_audio_ && has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ } else {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeFirst))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ }
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(All, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeFirst);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeFirst);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeFirst);
+ EXPECT_CALL(*this, OnUnderflowUpdate(1));
+ wtr_->OnUnderflow();
+ CycleReportingTimer();
+
+ EXPECT_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
+
+ // This cycle should not report another underflow.
+ CycleReportingTimer();
+
+ constexpr base::TimeDelta kUnderflowDuration =
+ base::TimeDelta::FromMilliseconds(250);
+ wtr_->OnUnderflowComplete(kUnderflowDuration);
+ EXPECT_CALL(*this, OnUnderflowDurationUpdate(1, kUnderflowDuration));
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+// Verify secondary properties pass through correctly.
+TEST_P(WatchTimeReporterTest, WatchTimeReporterSecondaryProperties) {
+ Initialize(true, true, kSizeJustRight);
+
+ auto properties = media::mojom::SecondaryPlaybackProperties::New(
+ has_audio_ ? media::kCodecAAC : media::kUnknownAudioCodec,
+ has_video_ ? media::kCodecH264 : media::kUnknownVideoCodec,
+ has_audio_ ? media::AudioCodecProfile::kXHE_AAC
+ : media::AudioCodecProfile::kUnknown,
+ has_video_ ? media::H264PROFILE_MAIN : media::VIDEO_CODEC_PROFILE_UNKNOWN,
+ has_audio_ ? media::AudioDecoderType::kMojo
+ : media::AudioDecoderType::kUnknown,
+ has_video_ ? media::VideoDecoderType::kMojo
+ : media::VideoDecoderType::kUnknown,
+ has_audio_ ? media::EncryptionScheme::kCenc
+ : media::EncryptionScheme::kUnencrypted,
+ has_video_ ? media::EncryptionScheme::kCbcs
+ : media::EncryptionScheme::kUnencrypted,
+ has_video_ ? gfx::Size(800, 600) : gfx::Size());
+
+ // Get a pointer to our original properties since we're not allowed to use
+ // lambda capture for movable types in Chromium C++ yet.
+ auto* properies_ptr = properties.get();
+
+ // Muted watch time is only reported for audio+video.
+ EXPECT_CALL(*this, OnUpdateSecondaryProperties(_))
+ .Times((has_audio_ && has_video_) ? 3 : 2)
+ .WillRepeatedly([properies_ptr](auto secondary_properties) {
+ ASSERT_TRUE(properies_ptr->Equals(*secondary_properties));
+ });
+ wtr_->UpdateSecondaryProperties(properties.Clone());
+ CycleReportingTimer();
+
+ // Ensure expectations are met before |properies| goes out of scope.
+ testing::Mock::VerifyAndClearExpectations(this);
+}
+
+TEST_P(WatchTimeReporterTest, SecondaryProperties_SizeIncreased) {
+ if (!has_video_)
+ return;
+
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillRepeatedly(testing::Return(base::TimeDelta()));
+ Initialize(false, false, kSizeTooSmall);
+ wtr_->OnPlaying();
+ EXPECT_FALSE(IsMonitoring());
+
+ EXPECT_CALL(*this, OnUpdateSecondaryProperties(_))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->UpdateSecondaryProperties(
+ media::mojom::SecondaryPlaybackProperties::New(
+ media::kUnknownAudioCodec, media::kUnknownVideoCodec,
+ media::AudioCodecProfile::kUnknown,
+ media::VIDEO_CODEC_PROFILE_UNKNOWN, media::AudioDecoderType::kUnknown,
+ media::VideoDecoderType::kUnknown,
+ media::EncryptionScheme::kUnencrypted,
+ media::EncryptionScheme::kUnencrypted, kSizeJustRight));
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, SecondaryProperties_SizeDecreased) {
+ if (!has_video_)
+ return;
+
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillRepeatedly(testing::Return(base::TimeDelta()));
+ Initialize(false, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_CALL(*this, OnUpdateSecondaryProperties(_))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->UpdateSecondaryProperties(
+ media::mojom::SecondaryPlaybackProperties::New(
+ media::kUnknownAudioCodec, media::kUnknownVideoCodec,
+ media::AudioCodecProfile::kUnknown,
+ media::VIDEO_CODEC_PROFILE_UNKNOWN, media::AudioDecoderType::kUnknown,
+ media::VideoDecoderType::kUnknown,
+ media::EncryptionScheme::kUnencrypted,
+ media::EncryptionScheme::kUnencrypted, kSizeTooSmall));
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterAutoplayInitiated) {
+ Initialize(true, true, kSizeJustRight);
+
+ EXPECT_CALL(*this, OnSetAutoplayInitiated(true))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->SetAutoplayInitiated(true);
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterShownHidden) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(25);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ wtr_->OnHidden();
+ const base::TimeDelta kExpectedWatchTime = kWatchTimeLate - kWatchTimeEarly;
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kExpectedWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kExpectedWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kExpectedWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kExpectedWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ // One call for the background, one for the foreground, and one for the muted
+ // reporter if we have audio+video.
+ EXPECT_CALL(*this, OnError(media::PIPELINE_ERROR_DECODE))
+ .Times((has_audio_ && has_video_) ? 3 : 2);
+ wtr_->OnError(media::PIPELINE_ERROR_DECODE);
+
+ const base::TimeDelta kExpectedForegroundWatchTime = kWatchTimeEarly;
+ EXPECT_WATCH_TIME(Ac, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(All, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(Eme, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(Mse, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterBackgroundHysteresis) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta())) // 2x for playing
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // 2x for shown
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // 2x for hidden
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // 1x for timer cycle.
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ Initialize(true, true, kSizeJustRight);
+ DisableMutedReporting(); // Just complicates this test.
+
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnShown();
+ wtr_->OnHidden();
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTimeLate);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTimeLate);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTimeLate);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTimeLate);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterShownHiddenBackground) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+
+ Initialize(true, true, kSizeJustRight);
+ DisableMutedReporting(); // Just complicates this test.
+
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnShown();
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTimeEarly);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTimeEarly);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTimeEarly);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ const base::TimeDelta kExpectedForegroundWatchTime =
+ kWatchTimeLate - kWatchTimeEarly;
+ EXPECT_WATCH_TIME(Ac, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(All, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(Eme, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(Mse, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kExpectedForegroundWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kExpectedForegroundWatchTime);
+ CycleReportingTimer();
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterHiddenPausedBackground) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(8);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillRepeatedly(testing::Return(kWatchTime));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnPaused();
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterHiddenSeekedBackground) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(8);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillRepeatedly(testing::Return(kWatchTime));
+ Initialize(false, true, kSizeJustRight);
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_BACKGROUND_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_->OnSeeking();
+
+ EXPECT_FALSE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterHiddenPowerBackground) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ OnPowerStateChange(true);
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime1);
+ EXPECT_POWER_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_BACKGROUND_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime2);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterHiddenControlsBackground) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ OnNativeControlsEnabled(true);
+
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime1);
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime2);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ WatchTimeReporterHiddenDisplayTypeBackground) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime1);
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime2);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime2);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterHiddenMuted) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(25);
+
+ // Expectations for when muted watch time is recorded and when it isn't.
+ if (has_audio_ && has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta())) // 2x playing.
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1)) // 2x muted.
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1)) // 2x shown.
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ } else {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta())) // 2x playing.
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1)) // 1x muted.
+ .WillOnce(testing::Return(kWatchTime1)) // 1x shown.
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ }
+
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnHidden();
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnVolumeChange(0);
+ EXPECT_TRUE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMutedMonitoring());
+
+ EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime1);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnShown();
+ EXPECT_FALSE(IsBackgroundMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ EXPECT_EQ(has_audio_ && has_video_, IsMutedMonitoring());
+
+ const base::TimeDelta kWatchTime = kWatchTime2 - kWatchTime1;
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime);
+ if (has_audio_ && has_video_)
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, WatchTimeReporterMultiplePartialFinalize) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+
+ // Transition controls and battery.
+ {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ OnNativeControlsEnabled(true);
+ OnPowerStateChange(true);
+
+ EXPECT_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_WATCH_TIME(All, kWatchTime1);
+ EXPECT_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_WATCH_TIME(Mse, kWatchTime1);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+ EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
+ EXPECT_POWER_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_WATCH_TIME(All, kWatchTime2);
+ EXPECT_WATCH_TIME(Eme, kWatchTime2);
+ EXPECT_WATCH_TIME(Mse, kWatchTime2);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime2);
+ EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+ }
+
+ // Transition display type and battery. Test only works with video.
+ if (has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+ OnPowerStateChange(true);
+
+ EXPECT_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_WATCH_TIME(All, kWatchTime1);
+ EXPECT_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_WATCH_TIME(Mse, kWatchTime1);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+ EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+ EXPECT_POWER_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_WATCH_TIME(All, kWatchTime2);
+ EXPECT_WATCH_TIME(Eme, kWatchTime2);
+ EXPECT_WATCH_TIME(Mse, kWatchTime2);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime2);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+ }
+
+ // Transition controls, battery and display type. Test only works with video.
+ if (has_video_) {
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ OnNativeControlsEnabled(true);
+ OnPowerStateChange(true);
+ OnDisplayTypeChanged(DisplayType::kPictureInPicture);
+
+ EXPECT_WATCH_TIME(Ac, kWatchTime1);
+ EXPECT_WATCH_TIME(All, kWatchTime1);
+ EXPECT_WATCH_TIME(Eme, kWatchTime1);
+ EXPECT_WATCH_TIME(Mse, kWatchTime1);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+ EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
+ EXPECT_POWER_WATCH_TIME_FINALIZED();
+ EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_WATCH_TIME(All, kWatchTime2);
+ EXPECT_WATCH_TIME(Eme, kWatchTime2);
+ EXPECT_WATCH_TIME(Mse, kWatchTime2);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayPictureInPicture,
+ kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+ }
+}
+
+// Tests that starting from a non-zero base works.
+TEST_P(WatchTimeReporterTest, WatchTimeReporterNonZeroStart) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(15);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ const base::TimeDelta kWatchTime = kWatchTime2 - kWatchTime1;
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ CycleReportingTimer();
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+// Tests that seeking causes an immediate finalization.
+TEST_P(WatchTimeReporterTest, SeekFinalizes) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_->OnSeeking();
+}
+
+// Tests that seeking can't be undone by anything other than OnPlaying().
+TEST_P(WatchTimeReporterTest, SeekOnlyClearedByPlaying) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillRepeatedly(testing::Return(kWatchTime));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_->OnSeeking();
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnHidden();
+ wtr_->OnShown();
+ wtr_->OnVolumeChange(0);
+ wtr_->OnVolumeChange(1);
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ // Because the above calls may tickle the background and muted reporters,
+ // we'll receive 2-3 finalize calls upon destruction if they exist.
+ if (has_audio_ && has_video_)
+ EXPECT_WATCH_TIME_FINALIZED();
+ EXPECT_WATCH_TIME_FINALIZED();
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+// Tests that seeking causes an immediate finalization, but does not trample a
+// previously set finalize time.
+TEST_P(WatchTimeReporterTest, SeekFinalizeDoesNotTramplePreviousFinalize) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_->OnPaused();
+ wtr_->OnSeeking();
+}
+
+// Tests that watch time is finalized upon destruction.
+TEST_P(WatchTimeReporterTest, WatchTimeReporterFinalizeOnDestruction) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+
+ // Finalize the histogram before any cycles of the timer have run.
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+// Tests that watch time categories are mapped correctly.
+TEST_P(WatchTimeReporterTest, WatchTimeCategoryMapping) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(10);
+
+ // Verify ac, all, src, non-native controls
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(false, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+
+ // Verify ac, all, mse, non-native controls
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(true, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Mse, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+
+ // Verify ac, all, eme, src, non-native controls
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(false, true, kSizeJustRight);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Eme, kWatchTime);
+ EXPECT_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+
+ // Verify all, battery, src, non-native controls
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(false, false, kSizeJustRight);
+ wtr_->OnPlaying();
+ SetOnBatteryPower(true);
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Battery, kWatchTime);
+ EXPECT_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+
+ // Verify ac, all, src, native controls
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(false, false, kSizeJustRight);
+ OnNativeControlsEnabled(true);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+
+ // Verify all, battery, src, non-native controls, display fullscreen
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(false, false, kSizeJustRight);
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+ wtr_->OnPlaying();
+ SetOnBatteryPower(true);
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Battery, kWatchTime);
+ EXPECT_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+
+ // Verify ac, all, src, native controls, display picture-in-picture
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime));
+ Initialize(false, false, kSizeJustRight);
+ OnNativeControlsEnabled(true);
+ OnDisplayTypeChanged(DisplayType::kPictureInPicture);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME(Ac, kWatchTime);
+ EXPECT_WATCH_TIME(All, kWatchTime);
+ EXPECT_WATCH_TIME(Src, kWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayPictureInPicture, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(WatchTimeReporterTest, PlayPauseHysteresisContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest>([this]() {
+ wtr_->OnPaused();
+ wtr_->OnPlaying();
+ });
+}
+
+TEST_P(WatchTimeReporterTest, PlayPauseHysteresisFinalized) {
+ RunHysteresisTest([this]() { wtr_->OnPaused(); });
+}
+
+TEST_P(WatchTimeReporterTest, OnVolumeChangeHysteresisContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest>([this]() {
+ wtr_->OnVolumeChange(0);
+ wtr_->OnVolumeChange(1);
+ });
+}
+
+TEST_P(WatchTimeReporterTest, OnVolumeChangeHysteresisFinalized) {
+ RunHysteresisTest([this]() { wtr_->OnVolumeChange(0); });
+}
+
+TEST_P(WatchTimeReporterTest, OnShownHiddenHysteresisContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest>([this]() {
+ wtr_->OnHidden();
+ wtr_->OnShown();
+ });
+}
+
+TEST_P(WatchTimeReporterTest, OnShownHiddenHysteresisFinalized) {
+ RunHysteresisTest([this]() { wtr_->OnHidden(); });
+}
+
+TEST_P(WatchTimeReporterTest, OnPowerStateChangeHysteresisBatteryContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeExitDoesNotRequireCurrentTime | kStartOnBattery>(
+ [this]() {
+ OnPowerStateChange(false);
+ OnPowerStateChange(true);
+ });
+}
+
+TEST_P(WatchTimeReporterTest, OnPowerStateChangeHysteresisBatteryFinalized) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest | kFinalizePowerWatchTime |
+ kStartOnBattery>([this]() { OnPowerStateChange(false); });
+}
+
+TEST_P(WatchTimeReporterTest, OnPowerStateChangeHysteresisAcContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeExitDoesNotRequireCurrentTime>([this]() {
+ OnPowerStateChange(true);
+ OnPowerStateChange(false);
+ });
+}
+
+TEST_P(WatchTimeReporterTest, OnPowerStateChangeHysteresisAcFinalized) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest | kFinalizePowerWatchTime>(
+ [this]() { OnPowerStateChange(true); });
+}
+
+TEST_P(WatchTimeReporterTest, OnPowerStateChangeBatteryTransitions) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest | kFinalizePowerWatchTime |
+ kStartOnBattery | kTransitionPowerWatchTime>(
+ [this]() { OnPowerStateChange(false); });
+}
+
+TEST_P(WatchTimeReporterTest, OnPowerStateChangeAcTransitions) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest | kFinalizePowerWatchTime |
+ kTransitionPowerWatchTime>(
+ [this]() { OnPowerStateChange(true); });
+}
+
+TEST_P(WatchTimeReporterTest, OnControlsChangeHysteresisNativeContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeExitDoesNotRequireCurrentTime |
+ kStartWithNativeControls>([this]() {
+ OnNativeControlsEnabled(false);
+ OnNativeControlsEnabled(true);
+ });
+}
+
+TEST_P(WatchTimeReporterTest, OnControlsChangeHysteresisNativeFinalized) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeControlsWatchTime | kStartWithNativeControls>(
+ [this]() { OnNativeControlsEnabled(false); });
+}
+
+TEST_P(WatchTimeReporterTest, OnControlsChangeHysteresisNativeOffContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeExitDoesNotRequireCurrentTime>([this]() {
+ OnNativeControlsEnabled(true);
+ OnNativeControlsEnabled(false);
+ });
+}
+
+TEST_P(WatchTimeReporterTest, OnControlsChangeHysteresisNativeOffFinalized) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeControlsWatchTime>(
+ [this]() { OnNativeControlsEnabled(true); });
+}
+
+TEST_P(WatchTimeReporterTest, OnControlsChangeToNativeOff) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeControlsWatchTime | kStartWithNativeControls |
+ kTransitionControlsWatchTime>(
+ [this]() { OnNativeControlsEnabled(false); });
+}
+
+TEST_P(WatchTimeReporterTest, OnControlsChangeToNative) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeControlsWatchTime | kTransitionControlsWatchTime>(
+ [this]() { OnNativeControlsEnabled(true); });
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ OnDisplayTypeChangeHysteresisFullscreenContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeExitDoesNotRequireCurrentTime |
+ kStartWithDisplayFullscreen>([this]() {
+ OnDisplayTypeChanged(DisplayType::kInline);
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+ });
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ OnDisplayTypeChangeHysteresisNativeFinalized) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeDisplayWatchTime | kStartWithDisplayFullscreen>(
+ [this]() { OnDisplayTypeChanged(DisplayType::kInline); });
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ OnDisplayTypeChangeHysteresisInlineContinuation) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeExitDoesNotRequireCurrentTime>([this]() {
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+ OnDisplayTypeChanged(DisplayType::kInline);
+ });
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ OnDisplayTypeChangeHysteresisNativeOffFinalized) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeDisplayWatchTime>(
+ [this]() { OnDisplayTypeChanged(DisplayType::kFullscreen); });
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ OnDisplayTypeChangeInlineToFullscreen) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeDisplayWatchTime | kStartWithDisplayFullscreen |
+ kTransitionDisplayWatchTime>(
+ [this]() { OnDisplayTypeChanged(DisplayType::kInline); });
+}
+
+TEST_P(DisplayTypeWatchTimeReporterTest,
+ OnDisplayTypeChangeFullscreenToInline) {
+ RunHysteresisTest<kAccumulationContinuesAfterTest |
+ kFinalizeDisplayWatchTime | kTransitionDisplayWatchTime>(
+ [this]() { OnDisplayTypeChanged(DisplayType::kFullscreen); });
+}
+
+// Tests that the first finalize is the only one that matters.
+TEST_P(WatchTimeReporterTest, HysteresisFinalizedWithEarliest) {
+ RunHysteresisTest([this]() {
+ wtr_->OnPaused();
+
+ // These subsequent "stop events" should do nothing since a finalize time
+ // has already been selected.
+ wtr_->OnHidden();
+ wtr_->OnVolumeChange(0);
+ });
+}
+
+// Tests that if a stop, stop, start sequence occurs, the middle stop is not
+// undone and thus finalize still occurs.
+TEST_P(WatchTimeReporterTest, HysteresisPartialExitStillFinalizes) {
+ auto stop_event = [this](size_t i) {
+ if (i == 0) {
+ wtr_->OnPaused();
+ } else if (i == 1) {
+ wtr_->OnVolumeChange(0);
+ } else {
+ ASSERT_TRUE(has_video_);
+ wtr_->OnHidden();
+ }
+ };
+
+ auto start_event = [this](size_t i) {
+ if (i == 0) {
+ wtr_->OnPlaying();
+ } else if (i == 1) {
+ wtr_->OnVolumeChange(1);
+ } else {
+ ASSERT_TRUE(has_video_);
+ wtr_->OnShown();
+ }
+ };
+
+ const size_t kTestSize = has_video_ ? 3 : 2;
+ for (size_t i = 0; i < kTestSize; ++i) {
+ for (size_t j = 0; j < kTestSize; ++j) {
+ if (i == j)
+ continue;
+
+ RunHysteresisTest<kFinalizeInterleavedStartEvent>(
+ [i, j, start_event, stop_event]() {
+ stop_event(i);
+ stop_event(j);
+ start_event(i);
+ });
+ }
+ }
+}
+
+class MutedWatchTimeReporterTest : public WatchTimeReporterTest {};
+
+TEST_P(MutedWatchTimeReporterTest, MutedHysteresis) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta())) // 2x for playing
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // 3x for unmute.
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // 2x for mute
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly)) // 1x for timer cycle.
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+ Initialize(true, true, kSizeJustRight);
+
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnVolumeChange(1);
+ wtr_->OnVolumeChange(0);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTimeEarly);
+
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_TRUE(IsMonitoring());
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTimeLate);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTimeLate);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTimeLate);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTimeLate);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTimeLate);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTimeLate);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(MutedWatchTimeReporterTest, MuteUnmute) {
+ constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillOnce(testing::Return(kWatchTimeEarly))
+ .WillRepeatedly(testing::Return(kWatchTimeLate));
+
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnVolumeChange(1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTimeEarly);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTimeEarly);
+ EXPECT_WATCH_TIME_FINALIZED();
+
+ const base::TimeDelta kExpectedUnmutedWatchTime =
+ kWatchTimeLate - kWatchTimeEarly;
+ EXPECT_WATCH_TIME(Ac, kExpectedUnmutedWatchTime);
+ EXPECT_WATCH_TIME(All, kExpectedUnmutedWatchTime);
+ EXPECT_WATCH_TIME(Eme, kExpectedUnmutedWatchTime);
+ EXPECT_WATCH_TIME(Mse, kExpectedUnmutedWatchTime);
+ EXPECT_WATCH_TIME(NativeControlsOff, kExpectedUnmutedWatchTime);
+ EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kExpectedUnmutedWatchTime);
+ CycleReportingTimer();
+
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_.reset();
+}
+
+TEST_P(MutedWatchTimeReporterTest, MutedPaused) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(8);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillRepeatedly(testing::Return(kWatchTime));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ wtr_->OnPaused();
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(MutedWatchTimeReporterTest, MutedSeeked) {
+ constexpr base::TimeDelta kWatchTime = base::TimeDelta::FromSeconds(8);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillRepeatedly(testing::Return(kWatchTime));
+ Initialize(false, true, kSizeJustRight);
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Src, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime);
+ EXPECT_WATCH_TIME_FINALIZED();
+ wtr_->OnSeeking();
+
+ EXPECT_FALSE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(MutedWatchTimeReporterTest, MutedPower) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ OnPowerStateChange(true);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime1);
+ EXPECT_POWER_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Battery, kWatchTime2 - kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime2);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(MutedWatchTimeReporterTest, MutedControls) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ OnNativeControlsEnabled(true);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime1);
+ EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOn,
+ kWatchTime2 - kWatchTime1);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+TEST_P(MutedWatchTimeReporterTest, MutedDisplayType) {
+ constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+ constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+ EXPECT_CALL(*this, GetCurrentMediaTime())
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(base::TimeDelta()))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillOnce(testing::Return(kWatchTime1))
+ .WillRepeatedly(testing::Return(kWatchTime2));
+ Initialize(true, true, kSizeJustRight);
+ wtr_->OnVolumeChange(0);
+ wtr_->OnPlaying();
+ EXPECT_TRUE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+
+ OnDisplayTypeChanged(DisplayType::kFullscreen);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayInline, kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime1);
+ EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ wtr_->OnPaused();
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Ac, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(All, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Eme, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(Mse, kWatchTime2);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(DisplayFullscreen,
+ kWatchTime2 - kWatchTime1);
+ EXPECT_MUTED_WATCH_TIME_IF_AUDIO_VIDEO(NativeControlsOff, kWatchTime2);
+ EXPECT_WATCH_TIME_FINALIZED();
+ CycleReportingTimer();
+
+ EXPECT_FALSE(IsMutedMonitoring());
+ EXPECT_FALSE(IsMonitoring());
+ wtr_.reset();
+}
+
+INSTANTIATE_TEST_SUITE_P(WatchTimeReporterTest,
+ WatchTimeReporterTest,
+ testing::ValuesIn({// has_video, has_audio
+ std::make_tuple(true, true),
+ // has_video
+ std::make_tuple(true, false),
+ // has_audio
+ std::make_tuple(false, true)}));
+
+// Separate test set since display tests only work with video.
+INSTANTIATE_TEST_SUITE_P(DisplayTypeWatchTimeReporterTest,
+ DisplayTypeWatchTimeReporterTest,
+ testing::ValuesIn({// has_video, has_audio
+ std::make_tuple(true, true),
+ // has_video
+ std::make_tuple(true, false)}));
+
+// Separate test set since muted tests only work with audio+video.
+INSTANTIATE_TEST_SUITE_P(MutedWatchTimeReporterTest,
+ MutedWatchTimeReporterTest,
+ testing::ValuesIn({
+ // has_video, has_audio
+ std::make_tuple(true, true),
+ }));
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.cc
new file mode 100644
index 00000000000..c9c7ca5dfbb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.cc
@@ -0,0 +1,97 @@
+// 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/media/web_content_decryption_module_access_impl.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/media/web_encrypted_media_client_impl.h"
+
+namespace blink {
+
+// The caller owns the created cdm (passed back using |result|).
+static void CreateCdm(
+ const base::WeakPtr<WebEncryptedMediaClientImpl>& client,
+ const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const media::CdmConfig& cdm_config,
+ std::unique_ptr<WebContentDecryptionModuleResult> result) {
+ // If |client| is gone (due to the frame getting destroyed), it is
+ // impossible to create the CDM, so fail.
+ if (!client) {
+ result->CompleteWithError(
+ kWebContentDecryptionModuleExceptionInvalidStateError, 0,
+ "Failed to create CDM.");
+ return;
+ }
+
+ client->CreateCdm(key_system, security_origin, cdm_config, std::move(result));
+}
+
+// static
+WebContentDecryptionModuleAccessImpl*
+WebContentDecryptionModuleAccessImpl::From(
+ WebContentDecryptionModuleAccess* cdm_access) {
+ return static_cast<WebContentDecryptionModuleAccessImpl*>(cdm_access);
+}
+
+std::unique_ptr<WebContentDecryptionModuleAccessImpl>
+WebContentDecryptionModuleAccessImpl::Create(
+ const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const WebMediaKeySystemConfiguration& configuration,
+ const media::CdmConfig& cdm_config,
+ const base::WeakPtr<WebEncryptedMediaClientImpl>& client) {
+ return std::make_unique<WebContentDecryptionModuleAccessImpl>(
+ key_system, security_origin, configuration, cdm_config, client);
+}
+
+WebContentDecryptionModuleAccessImpl::WebContentDecryptionModuleAccessImpl(
+ const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const WebMediaKeySystemConfiguration& configuration,
+ const media::CdmConfig& cdm_config,
+ const base::WeakPtr<WebEncryptedMediaClientImpl>& client)
+ : key_system_(key_system),
+ security_origin_(security_origin),
+ configuration_(configuration),
+ cdm_config_(cdm_config),
+ client_(client) {}
+
+WebContentDecryptionModuleAccessImpl::~WebContentDecryptionModuleAccessImpl() =
+ default;
+
+WebString WebContentDecryptionModuleAccessImpl::GetKeySystem() {
+ return key_system_;
+}
+
+WebMediaKeySystemConfiguration
+WebContentDecryptionModuleAccessImpl::GetConfiguration() {
+ return configuration_;
+}
+
+void WebContentDecryptionModuleAccessImpl::CreateContentDecryptionModule(
+ WebContentDecryptionModuleResult result,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ // This method needs to run asynchronously, as it may need to load the CDM.
+ // As this object's lifetime is controlled by MediaKeySystemAccess on the
+ // blink side, copy all values needed by CreateCdm() in case the blink object
+ // gets garbage-collected.
+ std::unique_ptr<WebContentDecryptionModuleResult> result_copy(
+ new WebContentDecryptionModuleResult(result));
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CreateCdm, client_, key_system_, security_origin_,
+ cdm_config_, std::move(result_copy)));
+}
+
+bool WebContentDecryptionModuleAccessImpl::UseHardwareSecureCodecs() const {
+ return cdm_config_.use_hw_secure_codecs;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.h b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.h
new file mode 100644
index 00000000000..f985fb3917d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.h
@@ -0,0 +1,67 @@
+// 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_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_ACCESS_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_ACCESS_IMPL_H_
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "media/base/cdm_config.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_access.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_result.h"
+#include "third_party/blink/public/platform/web_media_key_system_configuration.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+class WebEncryptedMediaClientImpl;
+
+class PLATFORM_EXPORT WebContentDecryptionModuleAccessImpl
+ : public WebContentDecryptionModuleAccess {
+ public:
+ // Allow typecasting from blink type as this is the only implementation.
+ static WebContentDecryptionModuleAccessImpl* From(
+ WebContentDecryptionModuleAccess* cdm_access);
+
+ static std::unique_ptr<WebContentDecryptionModuleAccessImpl> Create(
+ const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const WebMediaKeySystemConfiguration& configuration,
+ const media::CdmConfig& cdm_config,
+ const base::WeakPtr<WebEncryptedMediaClientImpl>& client);
+ WebContentDecryptionModuleAccessImpl(
+ const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const WebMediaKeySystemConfiguration& configuration,
+ const media::CdmConfig& cdm_config,
+ const base::WeakPtr<WebEncryptedMediaClientImpl>& client);
+ WebContentDecryptionModuleAccessImpl(
+ const WebContentDecryptionModuleAccessImpl&) = delete;
+ WebContentDecryptionModuleAccessImpl& operator=(
+ const WebContentDecryptionModuleAccessImpl&) = delete;
+ ~WebContentDecryptionModuleAccessImpl() override;
+
+ // WebContentDecryptionModuleAccess interface.
+ WebString GetKeySystem() override;
+ WebMediaKeySystemConfiguration GetConfiguration() override;
+ void CreateContentDecryptionModule(
+ WebContentDecryptionModuleResult result,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
+ bool UseHardwareSecureCodecs() const override;
+
+ private:
+ const WebString key_system_;
+ const WebSecurityOrigin security_origin_;
+ const WebMediaKeySystemConfiguration configuration_;
+ const media::CdmConfig cdm_config_;
+
+ // Keep a WeakPtr as client is owned by render_frame_impl.
+ base::WeakPtr<WebEncryptedMediaClientImpl> client_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_ACCESS_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.cc
new file mode 100644
index 00000000000..8f8b52357c6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.cc
@@ -0,0 +1,173 @@
+// 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/media/web_content_decryption_module_impl.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/check.h"
+#include "base/notreached.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "media/base/cdm_context.h"
+#include "media/base/cdm_promise.h"
+#include "media/base/content_decryption_module.h"
+#include "media/base/key_systems.h"
+#include "third_party/blink/public/platform/url_conversion.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/media/cdm_result_promise.h"
+#include "third_party/blink/renderer/platform/media/cdm_session_adapter.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.h"
+#include "url/origin.h"
+
+namespace blink {
+namespace {
+
+const char kCreateSessionSessionTypeUMAName[] = "CreateSession.SessionType";
+const char kSetServerCertificateUMAName[] = "SetServerCertificate";
+const char kGetStatusForPolicyUMAName[] = "GetStatusForPolicy";
+
+bool ConvertHdcpVersion(const WebString& hdcp_version_string,
+ media::HdcpVersion* hdcp_version) {
+ if (!hdcp_version_string.ContainsOnlyASCII())
+ return false;
+
+ std::string hdcp_version_ascii = hdcp_version_string.Ascii();
+
+ // The strings are specified in the explainer doc:
+ // https://github.com/WICG/hdcp-detection/blob/master/explainer.md
+ if (hdcp_version_ascii.empty())
+ *hdcp_version = media::HdcpVersion::kHdcpVersionNone;
+ else if (hdcp_version_ascii == "1.0")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion1_0;
+ else if (hdcp_version_ascii == "1.1")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion1_1;
+ else if (hdcp_version_ascii == "1.2")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion1_2;
+ else if (hdcp_version_ascii == "1.3")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion1_3;
+ else if (hdcp_version_ascii == "1.4")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion1_4;
+ else if (hdcp_version_ascii == "2.0")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion2_0;
+ else if (hdcp_version_ascii == "2.1")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion2_1;
+ else if (hdcp_version_ascii == "2.2")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion2_2;
+ else if (hdcp_version_ascii == "2.3")
+ *hdcp_version = media::HdcpVersion::kHdcpVersion2_3;
+ else
+ return false;
+
+ return true;
+}
+
+} // namespace
+
+void WebContentDecryptionModuleImpl::Create(
+ media::CdmFactory* cdm_factory,
+ const std::u16string& key_system,
+ const WebSecurityOrigin& security_origin,
+ const media::CdmConfig& cdm_config,
+ WebCdmCreatedCB web_cdm_created_cb) {
+ DCHECK(!security_origin.IsNull());
+ DCHECK(!key_system.empty());
+
+ // TODO(ddorwin): Guard against this in supported types check and remove this.
+ // Chromium only supports ASCII key systems.
+ if (!base::IsStringASCII(key_system)) {
+ NOTREACHED();
+ std::move(web_cdm_created_cb).Run(nullptr, "Invalid keysystem.");
+ return;
+ }
+
+ // TODO(ddorwin): This should be a DCHECK.
+ std::string key_system_ascii = base::UTF16ToASCII(key_system);
+ if (!media::KeySystems::GetInstance()->IsSupportedKeySystem(
+ key_system_ascii)) {
+ std::string message =
+ "Keysystem '" + key_system_ascii + "' is not supported.";
+ std::move(web_cdm_created_cb).Run(nullptr, message);
+ return;
+ }
+
+ // If opaque security origin, don't try to create the CDM.
+ if (security_origin.IsOpaque() || security_origin.ToString() == "null") {
+ std::move(web_cdm_created_cb)
+ .Run(nullptr, "EME use is not allowed on unique origins.");
+ return;
+ }
+
+ // CdmSessionAdapter::CreateCdm() will keep a reference to |adapter|. Then
+ // if WebContentDecryptionModuleImpl is successfully created (returned in
+ // |web_cdm_created_cb|), it will keep a reference to |adapter|. Otherwise,
+ // |adapter| will be destructed.
+ scoped_refptr<CdmSessionAdapter> adapter(new CdmSessionAdapter());
+ adapter->CreateCdm(cdm_factory, key_system_ascii, cdm_config,
+ std::move(web_cdm_created_cb));
+}
+
+WebContentDecryptionModuleImpl::WebContentDecryptionModuleImpl(
+ scoped_refptr<CdmSessionAdapter> adapter)
+ : adapter_(adapter) {
+}
+
+WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() = default;
+
+std::unique_ptr<WebContentDecryptionModuleSession>
+WebContentDecryptionModuleImpl::CreateSession(
+ WebEncryptedMediaSessionType session_type) {
+ base::UmaHistogramEnumeration(
+ adapter_->GetKeySystemUMAPrefix() + kCreateSessionSessionTypeUMAName,
+ session_type);
+ return adapter_->CreateSession(session_type);
+}
+
+void WebContentDecryptionModuleImpl::SetServerCertificate(
+ const uint8_t* server_certificate,
+ size_t server_certificate_length,
+ WebContentDecryptionModuleResult result) {
+ DCHECK(server_certificate);
+ adapter_->SetServerCertificate(
+ std::vector<uint8_t>(server_certificate,
+ server_certificate + server_certificate_length),
+ std::make_unique<CdmResultPromise<>>(result,
+ adapter_->GetKeySystemUMAPrefix(),
+ kSetServerCertificateUMAName));
+}
+
+void WebContentDecryptionModuleImpl::GetStatusForPolicy(
+ const WebString& min_hdcp_version_string,
+ WebContentDecryptionModuleResult result) {
+ media::HdcpVersion min_hdcp_version;
+ if (!ConvertHdcpVersion(min_hdcp_version_string, &min_hdcp_version)) {
+ result.CompleteWithError(kWebContentDecryptionModuleExceptionTypeError, 0,
+ "Invalid HDCP version");
+ return;
+ }
+
+ adapter_->GetStatusForPolicy(
+ min_hdcp_version,
+ std::make_unique<CdmResultPromise<media::CdmKeyInformation::KeyStatus>>(
+ result, adapter_->GetKeySystemUMAPrefix(),
+ kGetStatusForPolicyUMAName));
+}
+
+std::unique_ptr<media::CdmContextRef>
+WebContentDecryptionModuleImpl::GetCdmContextRef() {
+ return adapter_->GetCdmContextRef();
+}
+
+std::string WebContentDecryptionModuleImpl::GetKeySystem() const {
+ return adapter_->GetKeySystem();
+}
+
+media::CdmConfig WebContentDecryptionModuleImpl::GetCdmConfig() const {
+ return adapter_->GetCdmConfig();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h
new file mode 100644
index 00000000000..3d53d9f54a8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h
@@ -0,0 +1,82 @@
+// 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_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "media/base/cdm_config.h"
+#include "third_party/blink/public/platform/web_content_decryption_module.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace media {
+class CdmContextRef;
+class CdmFactory;
+struct CdmConfig;
+} // namespace media
+
+namespace blink {
+class CdmSessionAdapter;
+class WebSecurityOrigin;
+
+using WebCdmCreatedCB =
+ base::OnceCallback<void(WebContentDecryptionModule* cdm,
+ const std::string& error_message)>;
+
+class PLATFORM_EXPORT WebContentDecryptionModuleImpl
+ : public WebContentDecryptionModule {
+ public:
+ static void Create(media::CdmFactory* cdm_factory,
+ const std::u16string& key_system,
+ const WebSecurityOrigin& security_origin,
+ const media::CdmConfig& cdm_config,
+ WebCdmCreatedCB web_cdm_created_cb);
+
+ WebContentDecryptionModuleImpl(const WebContentDecryptionModuleImpl&) =
+ delete;
+ WebContentDecryptionModuleImpl& operator=(
+ const WebContentDecryptionModuleImpl&) = delete;
+ ~WebContentDecryptionModuleImpl() override;
+
+ // WebContentDecryptionModule implementation.
+ std::unique_ptr<WebContentDecryptionModuleSession> CreateSession(
+ WebEncryptedMediaSessionType session_type) override;
+ void SetServerCertificate(const uint8_t* server_certificate,
+ size_t server_certificate_length,
+ WebContentDecryptionModuleResult result) override;
+ void GetStatusForPolicy(const WebString& min_hdcp_version_string,
+ WebContentDecryptionModuleResult result) override;
+
+ std::unique_ptr<media::CdmContextRef> GetCdmContextRef();
+
+ std::string GetKeySystem() const;
+
+ media::CdmConfig GetCdmConfig() const;
+
+ private:
+ friend CdmSessionAdapter;
+
+ // Takes reference to |adapter|.
+ WebContentDecryptionModuleImpl(scoped_refptr<CdmSessionAdapter> adapter);
+
+ scoped_refptr<CdmSessionAdapter> adapter_;
+};
+
+// Allow typecasting from blink type as this is the only implementation.
+PLATFORM_EXPORT
+inline WebContentDecryptionModuleImpl* ToWebContentDecryptionModuleImpl(
+ WebContentDecryptionModule* cdm) {
+ return static_cast<WebContentDecryptionModuleImpl*>(cdm);
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.cc
new file mode 100644
index 00000000000..b4e53f5118d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.cc
@@ -0,0 +1,474 @@
+// 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/media/web_content_decryption_module_session_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/check_op.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "media/base/cdm_key_information.h"
+#include "media/base/cdm_promise.h"
+#include "media/base/content_decryption_module.h"
+#include "media/base/key_system_names.h"
+#include "media/base/key_systems.h"
+#include "media/base/limits.h"
+#include "media/cdm/cenc_utils.h"
+#include "media/cdm/json_web_key.h"
+#include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/public/platform/web_encrypted_media_key_information.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
+#include "third_party/blink/renderer/platform/media/cdm_result_promise.h"
+#include "third_party/blink/renderer/platform/media/cdm_result_promise_helper.h"
+#include "third_party/blink/renderer/platform/media/cdm_session_adapter.h"
+
+namespace blink {
+namespace {
+
+const char kCloseSessionUMAName[] = "CloseSession";
+const char kGenerateRequestUMAName[] = "GenerateRequest";
+const char kLoadSessionUMAName[] = "LoadSession";
+const char kRemoveSessionUMAName[] = "RemoveSession";
+const char kUpdateSessionUMAName[] = "UpdateSession";
+const char kKeyStatusSystemCodeUMAName[] = "KeyStatusSystemCode";
+
+media::CdmSessionType ConvertSessionType(
+ WebEncryptedMediaSessionType session_type) {
+ switch (session_type) {
+ case WebEncryptedMediaSessionType::kTemporary:
+ return media::CdmSessionType::kTemporary;
+ case WebEncryptedMediaSessionType::kPersistentLicense:
+ return media::CdmSessionType::kPersistentLicense;
+ case WebEncryptedMediaSessionType::kUnknown:
+ break;
+ }
+
+ NOTREACHED();
+ return media::CdmSessionType::kTemporary;
+}
+
+bool SanitizeInitData(media::EmeInitDataType init_data_type,
+ const unsigned char* init_data,
+ size_t init_data_length,
+ std::vector<uint8_t>* sanitized_init_data,
+ std::string* error_message) {
+ DCHECK_GT(init_data_length, 0u);
+ if (init_data_length > media::limits::kMaxInitDataLength) {
+ error_message->assign("Initialization data too long.");
+ return false;
+ }
+
+ switch (init_data_type) {
+ case media::EmeInitDataType::WEBM:
+ // |init_data| for WebM is a single key.
+ if (init_data_length > media::limits::kMaxKeyIdLength) {
+ error_message->assign("Initialization data for WebM is too long.");
+ return false;
+ }
+ sanitized_init_data->assign(init_data, init_data + init_data_length);
+ return true;
+
+ case media::EmeInitDataType::CENC:
+ sanitized_init_data->assign(init_data, init_data + init_data_length);
+ if (!media::ValidatePsshInput(*sanitized_init_data)) {
+ error_message->assign("Initialization data for CENC is incorrect.");
+ return false;
+ }
+ return true;
+
+ case media::EmeInitDataType::KEYIDS: {
+ // Extract the keys and then rebuild the message. This ensures that any
+ // extra data in the provided JSON is dropped.
+ std::string init_data_string(init_data, init_data + init_data_length);
+ media::KeyIdList key_ids;
+ if (!media::ExtractKeyIdsFromKeyIdsInitData(init_data_string, &key_ids,
+ error_message))
+ return false;
+
+ for (const auto& key_id : key_ids) {
+ if (key_id.size() < media::limits::kMinKeyIdLength ||
+ key_id.size() > media::limits::kMaxKeyIdLength) {
+ error_message->assign("Incorrect key size.");
+ return false;
+ }
+ }
+
+ media::CreateKeyIdsInitData(key_ids, sanitized_init_data);
+ return true;
+ }
+
+ case media::EmeInitDataType::UNKNOWN:
+ break;
+ }
+
+ NOTREACHED();
+ error_message->assign("Initialization data type is not supported.");
+ return false;
+}
+
+bool SanitizeSessionId(const WebString& session_id,
+ std::string* sanitized_session_id) {
+ // The user agent should thoroughly validate the sessionId value before
+ // passing it to the CDM. At a minimum, this should include checking that
+ // the length and value (e.g. alphanumeric) are reasonable.
+ if (!session_id.ContainsOnlyASCII())
+ return false;
+
+ sanitized_session_id->assign(session_id.Ascii());
+ if (sanitized_session_id->length() > media::limits::kMaxSessionIdLength)
+ return false;
+
+ // Check that |sanitized_session_id| only contains printable characters for
+ // easier logging. Note that checking alphanumeric is too strict because there
+ // are key systems using Base64 session IDs (which may include spaces). See
+ // https://crbug.com/902828.
+ for (const char c : *sanitized_session_id) {
+ if (!base::IsAsciiPrintable(c))
+ return false;
+ }
+
+ return true;
+}
+
+bool SanitizeResponse(const std::string& key_system,
+ const uint8_t* response,
+ size_t response_length,
+ std::vector<uint8_t>* sanitized_response) {
+ // The user agent should thoroughly validate the response before passing it
+ // to the CDM. This may include verifying values are within reasonable limits,
+ // stripping irrelevant data or fields, pre-parsing it, sanitizing it,
+ // and/or generating a fully sanitized version. The user agent should check
+ // that the length and values of fields are reasonable. Unknown fields should
+ // be rejected or removed.
+ if (response_length > media::limits::kMaxSessionResponseLength)
+ return false;
+
+ if (media::IsClearKey(key_system) || media::IsExternalClearKey(key_system)) {
+ std::string key_string(response, response + response_length);
+ media::KeyIdAndKeyPairs keys;
+ auto session_type = media::CdmSessionType::kTemporary;
+ if (!ExtractKeysFromJWKSet(key_string, &keys, &session_type))
+ return false;
+
+ // Must contain at least one key.
+ if (keys.empty())
+ return false;
+
+ for (const auto& key_pair : keys) {
+ if (key_pair.first.size() < media::limits::kMinKeyIdLength ||
+ key_pair.first.size() > media::limits::kMaxKeyIdLength) {
+ return false;
+ }
+ }
+
+ std::string sanitized_data = GenerateJWKSet(keys, session_type);
+ sanitized_response->assign(sanitized_data.begin(), sanitized_data.end());
+ return true;
+ }
+
+ // TODO(jrummell): Verify responses for Widevine.
+ sanitized_response->assign(response, response + response_length);
+ return true;
+}
+
+} // namespace
+
+WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
+ const scoped_refptr<CdmSessionAdapter>& adapter,
+ WebEncryptedMediaSessionType session_type)
+ : adapter_(adapter),
+ session_type_(ConvertSessionType(session_type)),
+ has_close_been_called_(false),
+ is_closed_(false) {}
+
+WebContentDecryptionModuleSessionImpl::
+ ~WebContentDecryptionModuleSessionImpl() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (!session_id_.empty()) {
+ adapter_->UnregisterSession(session_id_);
+
+ // From http://w3c.github.io/encrypted-media/#mediakeysession-interface
+ // "If a MediaKeySession object is not closed when it becomes inaccessible
+ // to the page, the CDM shall close the key session associated with the
+ // object."
+ //
+ // This object is destroyed when the corresponding blink object is no
+ // longer needed (which may be due to it becoming inaccessible to the
+ // page), so if the session is not closed and CloseSession() has not yet
+ // been called, call CloseSession() now. Since this object is being
+ // destroyed, there is no need for the promise to do anything as this
+ // session will be gone.
+ if (!is_closed_ && !has_close_been_called_) {
+ adapter_->CloseSession(session_id_,
+ std::make_unique<media::DoNothingCdmPromise<>>());
+ }
+ }
+}
+
+void WebContentDecryptionModuleSessionImpl::SetClientInterface(Client* client) {
+ client_ = client;
+}
+
+WebString WebContentDecryptionModuleSessionImpl::SessionId() const {
+ return WebString::FromUTF8(session_id_);
+}
+
+void WebContentDecryptionModuleSessionImpl::InitializeNewSession(
+ media::EmeInitDataType eme_init_data_type,
+ const unsigned char* init_data,
+ size_t init_data_length,
+ WebContentDecryptionModuleResult result) {
+ DCHECK(init_data);
+ DCHECK(session_id_.empty());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // From https://w3c.github.io/encrypted-media/#generateRequest.
+ // 6. If the Key System implementation represented by this object's cdm
+ // implementation value does not support initDataType as an Initialization
+ // Data Type, return a promise rejected with a NotSupportedError.
+ // String comparison is case-sensitive.
+ if (!IsSupportedKeySystemWithInitDataType(adapter_->GetKeySystem(),
+ eme_init_data_type)) {
+ std::string message =
+ "The initialization data type is not supported by the key system.";
+ result.CompleteWithError(
+ kWebContentDecryptionModuleExceptionNotSupportedError, 0,
+ WebString::FromUTF8(message));
+ return;
+ }
+
+ // 10.1 If the init data is not valid for initDataType, reject promise with
+ // a newly created TypeError.
+ // 10.2 Let sanitized init data be a validated and sanitized version of init
+ // data. The user agent must thoroughly validate the Initialization Data
+ // before passing it to the CDM. This includes verifying that the length
+ // and values of fields are reasonable, verifying that values are within
+ // reasonable limits, and stripping irrelevant, unsupported, or unknown
+ // data or fields. It is recommended that user agents pre-parse,
+ // sanitize, and/or generate a fully sanitized version of the
+ // Initialization Data. If the Initialization Data format specified by
+ // initDataType supports multiple entries, the user agent should remove
+ // entries that are not needed by the CDM. The user agent must not
+ // re-order entries within the Initialization Data.
+ // 10.3 If the preceding step failed, reject promise with a newly created
+ // TypeError.
+ std::vector<uint8_t> sanitized_init_data;
+ std::string message;
+ if (!SanitizeInitData(eme_init_data_type, init_data, init_data_length,
+ &sanitized_init_data, &message)) {
+ result.CompleteWithError(kWebContentDecryptionModuleExceptionTypeError, 0,
+ WebString::FromUTF8(message));
+ return;
+ }
+
+ // 10.4 If sanitized init data is empty, reject promise with a
+ // NotSupportedError.
+ if (sanitized_init_data.empty()) {
+ result.CompleteWithError(
+ kWebContentDecryptionModuleExceptionNotSupportedError, 0,
+ "No initialization data provided.");
+ return;
+ }
+
+ // 10.5 Let session id be the empty string.
+ // (Done in constructor.)
+
+ // 10.6 Let message be null.
+ // 10.7 Let message type be null.
+ // (Done by CDM.)
+
+ // 10.8 Let cdm be the CDM instance represented by this object's cdm
+ // instance value.
+ // 10.9 Use the cdm to execute the following steps:
+ adapter_->InitializeNewSession(
+ eme_init_data_type, sanitized_init_data, session_type_,
+ std::unique_ptr<media::NewSessionCdmPromise>(
+ new NewSessionCdmResultPromise(
+ result, adapter_->GetKeySystemUMAPrefix(),
+ kGenerateRequestUMAName,
+ base::BindOnce(
+ &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
+ weak_ptr_factory_.GetWeakPtr()),
+ {SessionInitStatus::NEW_SESSION})));
+}
+
+void WebContentDecryptionModuleSessionImpl::Load(
+ const WebString& session_id,
+ WebContentDecryptionModuleResult result) {
+ DCHECK(!session_id.IsEmpty());
+ DCHECK(session_id_.empty());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(session_type_ == media::CdmSessionType::kPersistentLicense);
+
+ // From https://w3c.github.io/encrypted-media/#load.
+ // 8.1 Let sanitized session ID be a validated and/or sanitized version of
+ // sessionId. The user agent should thoroughly validate the sessionId
+ // value before passing it to the CDM. At a minimum, this should include
+ // checking that the length and value (e.g. alphanumeric) are reasonable.
+ // 8.2 If the preceding step failed, or if sanitized session ID is empty,
+ // reject promise with a newly created TypeError.
+ std::string sanitized_session_id;
+ if (!SanitizeSessionId(session_id, &sanitized_session_id)) {
+ result.CompleteWithError(kWebContentDecryptionModuleExceptionTypeError, 0,
+ "Invalid session ID.");
+ return;
+ }
+
+ adapter_->LoadSession(
+ session_type_, sanitized_session_id,
+ std::unique_ptr<media::NewSessionCdmPromise>(
+ new NewSessionCdmResultPromise(
+ result, adapter_->GetKeySystemUMAPrefix(), kLoadSessionUMAName,
+ base::BindOnce(
+ &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
+ weak_ptr_factory_.GetWeakPtr()),
+ {SessionInitStatus::NEW_SESSION,
+ SessionInitStatus::SESSION_NOT_FOUND})));
+}
+
+void WebContentDecryptionModuleSessionImpl::Update(
+ const uint8_t* response,
+ size_t response_length,
+ WebContentDecryptionModuleResult result) {
+ DCHECK(response);
+ DCHECK(!session_id_.empty());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // From https://w3c.github.io/encrypted-media/#update.
+ // 6.1 Let sanitized response be a validated and/or sanitized version of
+ // response copy. The user agent should thoroughly validate the response
+ // before passing it to the CDM. This may include verifying values are
+ // within reasonable limits, stripping irrelevant data or fields,
+ // pre-parsing it, sanitizing it, and/or generating a fully sanitized
+ // version. The user agent should check that the length and values of
+ // fields are reasonable. Unknown fields should be rejected or removed.
+ // 6.2 If the preceding step failed, or if sanitized response is empty,
+ // reject promise with a newly created TypeError.
+ std::vector<uint8_t> sanitized_response;
+ if (!SanitizeResponse(adapter_->GetKeySystem(), response, response_length,
+ &sanitized_response)) {
+ result.CompleteWithError(kWebContentDecryptionModuleExceptionTypeError, 0,
+ "Invalid response.");
+ return;
+ }
+
+ adapter_->UpdateSession(
+ session_id_, sanitized_response,
+ std::make_unique<CdmResultPromise<>>(
+ result, adapter_->GetKeySystemUMAPrefix(), kUpdateSessionUMAName));
+}
+
+void WebContentDecryptionModuleSessionImpl::Close(
+ WebContentDecryptionModuleResult result) {
+ DCHECK(!session_id_.empty());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // close() shouldn't be called if the session is already closed. Since the
+ // operation is asynchronous, there is a window where close() was called
+ // just before the closed event arrives. The CDM should handle the case where
+ // close() is called after it has already closed the session. However, if
+ // we can tell the session is now closed, simply resolve the promise.
+ if (is_closed_) {
+ result.Complete();
+ return;
+ }
+
+ has_close_been_called_ = true;
+ adapter_->CloseSession(
+ session_id_,
+ std::make_unique<CdmResultPromise<>>(
+ result, adapter_->GetKeySystemUMAPrefix(), kCloseSessionUMAName));
+}
+
+void WebContentDecryptionModuleSessionImpl::Remove(
+ WebContentDecryptionModuleResult result) {
+ DCHECK(!session_id_.empty());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ adapter_->RemoveSession(
+ session_id_,
+ std::make_unique<CdmResultPromise<>>(
+ result, adapter_->GetKeySystemUMAPrefix(), kRemoveSessionUMAName));
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
+ media::CdmMessageType message_type,
+ const std::vector<uint8_t>& message) {
+ DCHECK(client_) << "Client not set before message event";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ client_->OnSessionMessage(message_type, message.data(), message.size());
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
+ bool has_additional_usable_key,
+ media::CdmKeysInfo keys_info) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WebVector<WebEncryptedMediaKeyInformation> keys(keys_info.size());
+ for (size_t i = 0; i < keys_info.size(); ++i) {
+ auto& key_info = keys_info[i];
+ keys[i].SetId(WebData(reinterpret_cast<char*>(&key_info->key_id[0]),
+ key_info->key_id.size()));
+ keys[i].SetStatus(ConvertCdmKeyStatus(key_info->status));
+ keys[i].SetSystemCode(key_info->system_code);
+
+ base::UmaHistogramSparse(
+ adapter_->GetKeySystemUMAPrefix() + kKeyStatusSystemCodeUMAName,
+ key_info->system_code);
+ }
+
+ // Now send the event to blink.
+ client_->OnSessionKeysChange(keys, has_additional_usable_key);
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
+ base::Time new_expiry_time) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // The check works around an issue in base::Time that converts null base::Time
+ // to |1601-01-01 00:00:00 UTC| in ToJsTime(). See http://crbug.com/679079
+ client_->OnSessionExpirationUpdate(
+ new_expiry_time.is_null() ? std::numeric_limits<double>::quiet_NaN()
+ : new_expiry_time.ToJsTime());
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionClosed(
+ media::CdmSessionClosedReason reason) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // Only send one closed event to blink.
+ if (is_closed_)
+ return;
+
+ is_closed_ = true;
+ client_->OnSessionClosed(reason);
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
+ const std::string& session_id,
+ SessionInitStatus* status) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // CDM will return NULL if the session to be loaded can't be found.
+ if (session_id.empty()) {
+ *status = SessionInitStatus::SESSION_NOT_FOUND;
+ return;
+ }
+
+ DCHECK(session_id_.empty()) << "Session ID may not be changed once set.";
+ session_id_ = session_id;
+ *status =
+ adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr())
+ ? SessionInitStatus::NEW_SESSION
+ : SessionInitStatus::SESSION_ALREADY_EXISTS;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.h b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.h
new file mode 100644
index 00000000000..8586a5d9edd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_content_decryption_module_session_impl.h
@@ -0,0 +1,104 @@
+// 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_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_SESSION_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_SESSION_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "media/base/content_decryption_module.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_session.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/media/new_session_cdm_result_promise.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+class CdmSessionAdapter;
+
+class PLATFORM_EXPORT WebContentDecryptionModuleSessionImpl
+ : public WebContentDecryptionModuleSession {
+ public:
+ WebContentDecryptionModuleSessionImpl(
+ const scoped_refptr<CdmSessionAdapter>& adapter,
+ WebEncryptedMediaSessionType session_type);
+ WebContentDecryptionModuleSessionImpl(
+ const WebContentDecryptionModuleSessionImpl&) = delete;
+ WebContentDecryptionModuleSessionImpl& operator=(
+ const WebContentDecryptionModuleSessionImpl&) = delete;
+ ~WebContentDecryptionModuleSessionImpl() override;
+
+ // WebContentDecryptionModuleSession implementation.
+ void SetClientInterface(Client* client) override;
+ WebString SessionId() const override;
+
+ void InitializeNewSession(media::EmeInitDataType init_data_type,
+ const unsigned char* initData,
+ size_t initDataLength,
+ WebContentDecryptionModuleResult result) override;
+ void Load(const WebString& session_id,
+ WebContentDecryptionModuleResult result) override;
+ void Update(const uint8_t* response,
+ size_t response_length,
+ WebContentDecryptionModuleResult result) override;
+ void Close(WebContentDecryptionModuleResult result) override;
+ void Remove(WebContentDecryptionModuleResult result) override;
+
+ // Callbacks.
+ void OnSessionMessage(media::CdmMessageType message_type,
+ const std::vector<uint8_t>& message);
+ void OnSessionKeysChange(bool has_additional_usable_key,
+ media::CdmKeysInfo keys_info);
+ void OnSessionExpirationUpdate(base::Time new_expiry_time);
+ void OnSessionClosed(media::CdmSessionClosedReason reason);
+
+ private:
+ // Called when a new session is created or loaded. |status| is set as
+ // appropriate, depending on whether the session already exists or not.
+ void OnSessionInitialized(const std::string& session_id,
+ SessionInitStatus* status);
+
+ scoped_refptr<CdmSessionAdapter> adapter_;
+
+ // Keep track of the session type to be passed into InitializeNewSession() and
+ // LoadSession().
+ const media::CdmSessionType session_type_;
+
+ // Non-owned pointer.
+ Client* client_;
+
+ // Session ID is the app visible ID for this session generated by the CDM.
+ // This value is not set until the CDM resolves the initializeNewSession()
+ // promise.
+ std::string session_id_;
+
+ // Keep track of whether the session has been closed or not. The session
+ // may be closed as a result of an application calling close(), or the CDM
+ // may close the session at any point.
+ // https://w3c.github.io/encrypted-media/#session-closed
+ // |has_close_been_called_| is used to keep track of whether close() has
+ // been called or not. |is_closed_| is used to keep track of whether the
+ // close event has been received or not.
+ bool has_close_been_called_;
+ bool is_closed_;
+
+ THREAD_CHECKER(thread_checker_);
+
+ // Since promises will live until they are fired, use a weak reference when
+ // creating a promise in case this class disappears before the promise
+ // actually fires.
+ base::WeakPtrFactory<WebContentDecryptionModuleSessionImpl> weak_ptr_factory_{
+ this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_CONTENT_DECRYPTION_MODULE_SESSION_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc
new file mode 100644
index 00000000000..a2602ab23e4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc
@@ -0,0 +1,189 @@
+// 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/media/web_encrypted_media_client_impl.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "media/base/key_systems.h"
+#include "media/base/media_permission.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_result.h"
+#include "third_party/blink/public/platform/web_encrypted_media_request.h"
+#include "third_party/blink/public/platform/web_media_key_system_configuration.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_access_impl.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h"
+
+namespace blink {
+namespace {
+
+// Used to name UMAs in Reporter.
+const char kKeySystemSupportUMAPrefix[] =
+ "Media.EME.RequestMediaKeySystemAccess.";
+
+// A helper function to complete WebContentDecryptionModuleResult. Used
+// to convert WebContentDecryptionModuleResult to a callback.
+void CompleteWebContentDecryptionModuleResult(
+ std::unique_ptr<WebContentDecryptionModuleResult> result,
+ WebContentDecryptionModule* cdm,
+ const std::string& error_message) {
+ DCHECK(result);
+
+ if (!cdm) {
+ result->CompleteWithError(
+ kWebContentDecryptionModuleExceptionNotSupportedError, 0,
+ WebString::FromUTF8(error_message));
+ return;
+ }
+
+ result->CompleteWithContentDecryptionModule(cdm);
+}
+
+} // namespace
+
+// Report usage of key system to UMA. There are 2 different counts logged:
+// 1. The key system is requested.
+// 2. The requested key system and options are supported.
+// Each stat is only reported once per renderer frame per key system.
+// Note that WebEncryptedMediaClientImpl is only created once by each
+// renderer frame.
+class WebEncryptedMediaClientImpl::Reporter {
+ public:
+ enum KeySystemSupportStatus {
+ KEY_SYSTEM_REQUESTED = 0,
+ KEY_SYSTEM_SUPPORTED = 1,
+ KEY_SYSTEM_SUPPORT_STATUS_COUNT
+ };
+
+ explicit Reporter(const std::string& key_system_for_uma)
+ : uma_name_(kKeySystemSupportUMAPrefix + key_system_for_uma),
+ is_request_reported_(false),
+ is_support_reported_(false) {}
+ ~Reporter() = default;
+
+ void ReportRequested() {
+ if (is_request_reported_)
+ return;
+ Report(KEY_SYSTEM_REQUESTED);
+ is_request_reported_ = true;
+ }
+
+ void ReportSupported() {
+ DCHECK(is_request_reported_);
+ if (is_support_reported_)
+ return;
+ Report(KEY_SYSTEM_SUPPORTED);
+ is_support_reported_ = true;
+ }
+
+ private:
+ void Report(KeySystemSupportStatus status) {
+ base::UmaHistogramEnumeration(uma_name_, status,
+ KEY_SYSTEM_SUPPORT_STATUS_COUNT);
+ }
+
+ const std::string uma_name_;
+ bool is_request_reported_;
+ bool is_support_reported_;
+};
+
+WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl(
+ media::CdmFactory* cdm_factory,
+ media::MediaPermission* media_permission,
+ std::unique_ptr<KeySystemConfigSelector::WebLocalFrameDelegate>
+ web_frame_delegate)
+ : cdm_factory_(cdm_factory),
+ key_system_config_selector_(media::KeySystems::GetInstance(),
+ media_permission,
+ std::move(web_frame_delegate)) {
+ DCHECK(cdm_factory_);
+}
+
+WebEncryptedMediaClientImpl::~WebEncryptedMediaClientImpl() = default;
+
+void WebEncryptedMediaClientImpl::RequestMediaKeySystemAccess(
+ WebEncryptedMediaRequest request) {
+ GetReporter(request.KeySystem())->ReportRequested();
+
+ key_system_config_selector_.SelectConfig(
+ request.KeySystem(), request.SupportedConfigurations(),
+ base::BindOnce(&WebEncryptedMediaClientImpl::OnConfigSelected,
+ weak_factory_.GetWeakPtr(), request));
+}
+
+void WebEncryptedMediaClientImpl::CreateCdm(
+ const WebString& key_system,
+ const WebSecurityOrigin& security_origin,
+ const media::CdmConfig& cdm_config,
+ std::unique_ptr<WebContentDecryptionModuleResult> result) {
+ WebContentDecryptionModuleImpl::Create(
+ cdm_factory_, key_system.Utf16(), security_origin, cdm_config,
+ base::BindOnce(&CompleteWebContentDecryptionModuleResult,
+ std::move(result)));
+}
+
+void WebEncryptedMediaClientImpl::OnConfigSelected(
+ WebEncryptedMediaRequest request,
+ KeySystemConfigSelector::Status status,
+ WebMediaKeySystemConfiguration* accumulated_configuration,
+ media::CdmConfig* cdm_config) {
+ // Update encrypted_media_supported_types_browsertest.cc if updating these
+ // strings.
+ // TODO(xhwang): Consider using different messages for kUnsupportedKeySystem
+ // and kUnsupportedConfigs.
+ const char kUnsupportedKeySystemOrConfigMessage[] =
+ "Unsupported keySystem or supportedConfigurations.";
+
+ // Handle unsupported cases first.
+ switch (status) {
+ case KeySystemConfigSelector::Status::kUnsupportedKeySystem:
+ case KeySystemConfigSelector::Status::kUnsupportedConfigs:
+ request.RequestNotSupported(kUnsupportedKeySystemOrConfigMessage);
+ return;
+ case KeySystemConfigSelector::Status::kSupported:
+ break; // Handled below.
+ }
+
+ DCHECK_EQ(status, KeySystemConfigSelector::Status::kSupported);
+ GetReporter(request.KeySystem())->ReportSupported();
+
+ // If the frame is closed while the permission prompt is displayed,
+ // the permission prompt is dismissed and this may result in the
+ // requestMediaKeySystemAccess request succeeding. However, the blink
+ // objects may have been cleared, so check if this is the case and simply
+ // reject the request.
+ WebSecurityOrigin origin = request.GetSecurityOrigin();
+ if (origin.IsNull()) {
+ request.RequestNotSupported("Unable to create MediaKeySystemAccess");
+ return;
+ }
+
+ request.RequestSucceeded(WebContentDecryptionModuleAccessImpl::Create(
+ request.KeySystem(), origin, *accumulated_configuration, *cdm_config,
+ weak_factory_.GetWeakPtr()));
+}
+
+WebEncryptedMediaClientImpl::Reporter* WebEncryptedMediaClientImpl::GetReporter(
+ const WebString& key_system) {
+ // Assumes that empty will not be found by GetKeySystemNameForUMA().
+ // TODO(sandersd): Avoid doing ASCII conversion more than once.
+ std::string key_system_ascii;
+ if (key_system.ContainsOnlyASCII())
+ key_system_ascii = key_system.Ascii();
+
+ // Return a per-frame singleton so that UMA reports will be once-per-frame.
+ std::string uma_name = media::GetKeySystemNameForUMA(key_system_ascii);
+ std::unique_ptr<Reporter>& reporter = reporters_[uma_name];
+ if (!reporter)
+ reporter = std::make_unique<Reporter>(uma_name);
+ return reporter.get();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.cc
new file mode 100644
index 00000000000..4aa2c06095c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.cc
@@ -0,0 +1,49 @@
+// 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/media/web_inband_text_track_impl.h"
+
+#include "base/check.h"
+
+namespace blink {
+
+WebInbandTextTrackImpl::WebInbandTextTrackImpl(Kind kind,
+ const WebString& label,
+ const WebString& language,
+ const WebString& id)
+ : client_(nullptr),
+ kind_(kind),
+ label_(label),
+ language_(language),
+ id_(id) {}
+
+WebInbandTextTrackImpl::~WebInbandTextTrackImpl() {
+ DCHECK(!client_);
+}
+
+void WebInbandTextTrackImpl::SetClient(WebInbandTextTrackClient* client) {
+ client_ = client;
+}
+
+WebInbandTextTrackClient* WebInbandTextTrackImpl::Client() {
+ return client_;
+}
+
+WebInbandTextTrackImpl::Kind WebInbandTextTrackImpl::GetKind() const {
+ return kind_;
+}
+
+WebString WebInbandTextTrackImpl::Label() const {
+ return label_;
+}
+
+WebString WebInbandTextTrackImpl::Language() const {
+ return language_;
+}
+
+WebString WebInbandTextTrackImpl::Id() const {
+ return id_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.h b/chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.h
new file mode 100644
index 00000000000..2612809f1ee
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_inband_text_track_impl.h
@@ -0,0 +1,43 @@
+// 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_MEDIA_WEB_INBAND_TEXT_TRACK_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_INBAND_TEXT_TRACK_IMPL_H_
+
+#include "third_party/blink/public/platform/web_inband_text_track.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT WebInbandTextTrackImpl : public WebInbandTextTrack {
+ public:
+ WebInbandTextTrackImpl(Kind kind,
+ const WebString& label,
+ const WebString& language,
+ const WebString& id);
+ WebInbandTextTrackImpl(const WebInbandTextTrackImpl&) = delete;
+ WebInbandTextTrackImpl& operator=(const WebInbandTextTrackImpl&) = delete;
+ ~WebInbandTextTrackImpl() override;
+
+ void SetClient(WebInbandTextTrackClient* client) override;
+ WebInbandTextTrackClient* Client() override;
+
+ Kind GetKind() const override;
+
+ WebString Label() const override;
+ WebString Language() const override;
+ WebString Id() const override;
+
+ private:
+ WebInbandTextTrackClient* client_;
+ Kind kind_;
+ WebString label_;
+ WebString language_;
+ WebString id_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_INBAND_TEXT_TRACK_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_media_player_impl.cc
new file mode 100644
index 00000000000..18b3ef5fe31
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_media_player_impl.cc
@@ -0,0 +1,3914 @@
+// 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/public/platform/media/web_media_player_impl.h"
+
+#include <algorithm>
+#include <cmath>
+#include <limits>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/debug/alias.h"
+#include "base/debug/crash_logging.h"
+#include "base/location.h"
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/task_runner_util.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "cc/layers/video_layer.h"
+#include "components/viz/common/gpu/raster_context_provider.h"
+#include "media/audio/null_audio_sink.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/cdm_context.h"
+#include "media/base/encryption_scheme.h"
+#include "media/base/limits.h"
+#include "media/base/media_content_type.h"
+#include "media/base/media_log.h"
+#include "media/base/media_switches.h"
+#include "media/base/media_url_demuxer.h"
+#include "media/base/memory_dump_provider_proxy.h"
+#include "media/base/text_renderer.h"
+#include "media/base/timestamp_constants.h"
+#include "media/base/video_frame.h"
+#include "media/filters/chunk_demuxer.h"
+#include "media/filters/ffmpeg_demuxer.h"
+#include "media/filters/memory_data_source.h"
+#include "media/filters/pipeline_controller.h"
+#include "media/learning/common/learning_task_controller.h"
+#include "media/learning/common/media_learning_tasks.h"
+#include "media/learning/mojo/public/cpp/mojo_learning_task_controller.h"
+#include "media/media_buildflags.h"
+#include "media/remoting/remoting_constants.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/data_url.h"
+#include "third_party/blink/public/common/media/display_type.h"
+#include "third_party/blink/public/common/media/watch_time_reporter.h"
+#include "third_party/blink/public/platform/media/power_status_helper.h"
+#include "third_party/blink/public/platform/media/url_index.h"
+#include "third_party/blink/public/platform/web_encrypted_media_types.h"
+#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
+#include "third_party/blink/public/platform/web_media_player_client.h"
+#include "third_party/blink/public/platform/web_media_player_encrypted_media_client.h"
+#include "third_party/blink/public/platform/web_media_player_source.h"
+#include "third_party/blink/public/platform/web_media_source.h"
+#include "third_party/blink/public/platform/web_runtime_features.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
+#include "third_party/blink/public/platform/web_texttrack_metadata.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/webaudiosourceprovider_impl.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
+#include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
+#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_frame.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_view.h"
+#include "third_party/blink/renderer/platform/media/text_track_impl.h"
+#include "third_party/blink/renderer/platform/media/video_decode_stats_reporter.h"
+#include "third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h"
+#include "third_party/blink/renderer/platform/media/web_inband_text_track_impl.h"
+#include "third_party/blink/renderer/platform/media/web_media_source_impl.h"
+#include "ui/gfx/geometry/size.h"
+
+#if defined(OS_ANDROID)
+#include "media/base/android/media_codec_util.h"
+#endif
+
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
+
+namespace blink {
+namespace {
+
+namespace learning = ::media::learning;
+using ::media::Demuxer;
+using ::media::MediaLogEvent;
+using ::media::MediaLogProperty;
+using ::media::MediaTrack;
+
+const char kWatchTimeHistogram[] = "Media.WebMediaPlayerImpl.WatchTime";
+
+void RecordSimpleWatchTimeUMA(media::RendererType type) {
+ UMA_HISTOGRAM_ENUMERATION(kWatchTimeHistogram, type);
+}
+
+void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
+ const std::string& device_id,
+ media::OutputDeviceStatusCB callback) {
+ sink->SwitchOutputDevice(device_id, std::move(callback));
+}
+
+bool IsBackgroundSuspendEnabled(const WebMediaPlayerImpl* wmpi) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableBackgroundMediaSuspend)) {
+ return false;
+ }
+ return wmpi->IsBackgroundMediaSuspendEnabled();
+}
+
+bool IsResumeBackgroundVideosEnabled() {
+ return base::FeatureList::IsEnabled(media::kResumeBackgroundVideo);
+}
+
+bool IsBackgroundVideoPauseOptimizationEnabled() {
+ return base::FeatureList::IsEnabled(media::kBackgroundVideoPauseOptimization);
+}
+
+bool IsNetworkStateError(WebMediaPlayer::NetworkState state) {
+ bool result = state == WebMediaPlayer::kNetworkStateFormatError ||
+ state == WebMediaPlayer::kNetworkStateNetworkError ||
+ state == WebMediaPlayer::kNetworkStateDecodeError;
+ DCHECK_EQ(state > WebMediaPlayer::kNetworkStateLoaded, result);
+ return result;
+}
+
+gfx::Size GetRotatedVideoSize(media::VideoRotation rotation,
+ gfx::Size natural_size) {
+ if (rotation == media::VIDEO_ROTATION_90 ||
+ rotation == media::VIDEO_ROTATION_270)
+ return gfx::Size(natural_size.height(), natural_size.width());
+ return natural_size;
+}
+
+void RecordEncryptedEvent(bool encrypted_event_fired) {
+ UMA_HISTOGRAM_BOOLEAN("Media.EME.EncryptedEvent", encrypted_event_fired);
+}
+
+// How much time must have elapsed since loading last progressed before we
+// assume that the decoder will have had time to complete preroll.
+constexpr base::TimeDelta kPrerollAttemptTimeout =
+ base::TimeDelta::FromSeconds(3);
+
+// Maximum number, per-WMPI, of media logs of playback rate changes.
+constexpr int kMaxNumPlaybackRateLogs = 10;
+
+int GetSwitchToLocalMessage(
+ media::MediaObserverClient::ReasonToSwitchToLocal reason) {
+ switch (reason) {
+ case media::MediaObserverClient::ReasonToSwitchToLocal::NORMAL:
+ return IDS_MEDIA_REMOTING_STOP_TEXT;
+ case media::MediaObserverClient::ReasonToSwitchToLocal::
+ POOR_PLAYBACK_QUALITY:
+ return IDS_MEDIA_REMOTING_STOP_BY_PLAYBACK_QUALITY_TEXT;
+ case media::MediaObserverClient::ReasonToSwitchToLocal::PIPELINE_ERROR:
+ return IDS_MEDIA_REMOTING_STOP_BY_ERROR_TEXT;
+ case media::MediaObserverClient::ReasonToSwitchToLocal::ROUTE_TERMINATED:
+ return WebMediaPlayerClient::kMediaRemotingStopNoText;
+ }
+ NOTREACHED();
+ // To suppress compiler warning on Windows.
+ return WebMediaPlayerClient::kMediaRemotingStopNoText;
+}
+
+// These values are persisted to UMA. Entries should not be renumbered and
+// numeric values should never be reused.
+// TODO(crbug.com/825041): This should use EncryptionScheme when kUnencrypted
+// removed.
+enum class EncryptionSchemeUMA { kCenc = 0, kCbcs = 1, kCount };
+
+EncryptionSchemeUMA DetermineEncryptionSchemeUMAValue(
+ media::EncryptionScheme encryption_scheme) {
+ if (encryption_scheme == media::EncryptionScheme::kCbcs)
+ return EncryptionSchemeUMA::kCbcs;
+
+ DCHECK_EQ(encryption_scheme, media::EncryptionScheme::kCenc);
+ return EncryptionSchemeUMA::kCenc;
+}
+
+#if BUILDFLAG(ENABLE_FFMPEG)
+// Returns true if `url` represents (or is likely to) a local file.
+bool IsLocalFile(const GURL& url) {
+ return url.SchemeIsFile() || url.SchemeIsFileSystem() ||
+ url.SchemeIs(url::kContentScheme) ||
+ url.SchemeIs(url::kContentIDScheme) ||
+ url.SchemeIs("chrome-extension");
+}
+#endif
+
+// Handles destruction of media::Renderer dependent components after the
+// renderer has been destructed on the media thread.
+void DestructionHelper(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> vfc_task_runner,
+ std::unique_ptr<Demuxer> demuxer,
+ std::unique_ptr<media::DataSource> data_source,
+ std::unique_ptr<VideoFrameCompositor> compositor,
+ std::unique_ptr<media::CdmContextRef> cdm_context_1,
+ std::unique_ptr<media::CdmContextRef> cdm_context_2,
+ std::unique_ptr<media::MediaLog> media_log,
+ std::unique_ptr<media::RendererFactorySelector> renderer_factory_selector,
+ std::unique_ptr<WebSurfaceLayerBridge> bridge,
+ bool is_chunk_demuxer) {
+ // We release `bridge` after pipeline stop to ensure layout tests receive
+ // painted video frames before test harness exit.
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(bridge));
+
+ // Since the media::Renderer is gone we can now destroy the compositor and
+ // renderer factory selector.
+ vfc_task_runner->DeleteSoon(FROM_HERE, std::move(compositor));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(renderer_factory_selector));
+
+ // ChunkDemuxer can be deleted on any thread, but other demuxers are bound to
+ // the main thread and must be deleted there now that the renderer is gone.
+ if (!is_chunk_demuxer) {
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(demuxer));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(data_source));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(cdm_context_1));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(cdm_context_2));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(media_log));
+ return;
+ }
+
+ // ChunkDemuxer's streams may contain much buffered, compressed media that
+ // may need to be paged back in during destruction. Paging delay may exceed
+ // the renderer hang monitor's threshold on at least Windows while also
+ // blocking other work on the renderer main thread, so we do the actual
+ // destruction in the background without blocking WMPI destruction or
+ // `task_runner`. On advice of task_scheduler OWNERS, MayBlock() is not
+ // used because virtual memory overhead is not considered blocking I/O; and
+ // CONTINUE_ON_SHUTDOWN is used to allow process termination to not block on
+ // completing the task.
+ base::ThreadPool::PostTask(
+ FROM_HERE,
+ {base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ base::BindOnce(
+ [](scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ std::unique_ptr<Demuxer> demuxer_to_destroy,
+ std::unique_ptr<media::CdmContextRef> cdm_context_1,
+ std::unique_ptr<media::CdmContextRef> cdm_context_2,
+ std::unique_ptr<media::MediaLog> media_log) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.MSE.DemuxerDestructionTime");
+ demuxer_to_destroy.reset();
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(cdm_context_1));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(cdm_context_2));
+ main_task_runner->DeleteSoon(FROM_HERE, std::move(media_log));
+ },
+ std::move(main_task_runner), std::move(demuxer),
+ std::move(cdm_context_1), std::move(cdm_context_2),
+ std::move(media_log)));
+}
+
+std::string SanitizeUserStringProperty(WebString value) {
+ std::string converted = value.Utf8();
+ return base::IsStringUTF8(converted) ? converted : "[invalid property]";
+}
+
+void CreateAllocation(base::trace_event::ProcessMemoryDump* pmd,
+ int32_t id,
+ const char* name,
+ int64_t bytes) {
+ if (bytes <= 0)
+ return;
+ auto full_name =
+ base::StringPrintf("media/webmediaplayer/%s/player_0x%x", name, id);
+ auto* dump = pmd->CreateAllocatorDump(full_name);
+
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes, bytes);
+
+ auto* std_allocator = base::trace_event::MemoryDumpManager::GetInstance()
+ ->system_allocator_pool_name();
+ if (std_allocator)
+ pmd->AddSuballocation(dump->guid(), std_allocator);
+}
+
+// Determine whether we should update MediaPosition in `delegate_`.
+bool MediaPositionNeedsUpdate(
+ const media_session::MediaPosition& old_position,
+ const media_session::MediaPosition& new_position) {
+ if (old_position.playback_rate() != new_position.playback_rate() ||
+ old_position.duration() != new_position.duration() ||
+ old_position.end_of_media() != new_position.end_of_media()) {
+ return true;
+ }
+
+ // Special handling for "infinite" position required to avoid calculations
+ // involving infinities.
+ if (new_position.GetPosition().is_max())
+ return !old_position.GetPosition().is_max();
+
+ // MediaPosition is potentially changed upon each OnTimeUpdate() call. In
+ // practice most of these calls happen periodically during normal playback,
+ // with unchanged rate and duration. If we want to avoid updating
+ // MediaPosition unnecessarily, we need to compare the current time
+ // calculated from the old and new MediaPositions with some tolerance. That's
+ // because we don't know the exact time when GetMediaTime() calculated the
+ // media position. We choose an arbitrary tolerance that is high enough to
+ // eliminate a lot of MediaPosition updates and low enough not to make a
+ // perceptible difference.
+ const auto drift =
+ (old_position.GetPosition() - new_position.GetPosition()).magnitude();
+ return drift > base::TimeDelta::FromMilliseconds(100);
+}
+
+// Returns whether the player uses AudioService. This is needed to enable
+// AudioStreamMonitor (for audio indicator) when not using AudioService.
+// TODO(crbug.com/1017943): Support other RendererTypes.
+bool UsesAudioService(media::RendererType renderer_type) {
+ return renderer_type != media::RendererType::kMediaFoundation;
+}
+
+} // namespace
+
+class BufferedDataSourceHostImpl;
+
+STATIC_ASSERT_ENUM(WebMediaPlayer::kCorsModeUnspecified,
+ UrlData::CORS_UNSPECIFIED);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kCorsModeAnonymous, UrlData::CORS_ANONYMOUS);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kCorsModeUseCredentials,
+ UrlData::CORS_USE_CREDENTIALS);
+
+WebMediaPlayerImpl::WebMediaPlayerImpl(
+ WebLocalFrame* frame,
+ WebMediaPlayerClient* client,
+ WebMediaPlayerEncryptedMediaClient* encrypted_client,
+ WebMediaPlayerDelegate* delegate,
+ std::unique_ptr<media::RendererFactorySelector> renderer_factory_selector,
+ UrlIndex* url_index,
+ std::unique_ptr<VideoFrameCompositor> compositor,
+ std::unique_ptr<WebMediaPlayerParams> params)
+ : frame_(frame),
+ main_task_runner_(frame->GetTaskRunner(TaskType::kMediaElementEvent)),
+ media_task_runner_(params->media_task_runner()),
+ worker_task_runner_(params->worker_task_runner()),
+ media_log_(params->take_media_log()),
+ client_(client),
+ encrypted_client_(encrypted_client),
+ delegate_(delegate),
+ delegate_has_audio_(HasUnmutedAudio()),
+ defer_load_cb_(params->defer_load_cb()),
+ adjust_allocated_memory_cb_(params->adjust_allocated_memory_cb()),
+ tick_clock_(base::DefaultTickClock::GetInstance()),
+ url_index_(url_index),
+ raster_context_provider_(params->raster_context_provider()),
+ vfc_task_runner_(params->video_frame_compositor_task_runner()),
+ compositor_(std::move(compositor)),
+ renderer_factory_selector_(std::move(renderer_factory_selector)),
+ observer_(params->media_observer()),
+ enable_instant_source_buffer_gc_(
+ params->enable_instant_source_buffer_gc()),
+ embedded_media_experience_enabled_(
+ params->embedded_media_experience_enabled()),
+ surface_layer_mode_(params->use_surface_layer_for_video()),
+ create_bridge_callback_(params->create_bridge_callback()),
+ request_routing_token_cb_(params->request_routing_token_cb()),
+ media_metrics_provider_(params->take_metrics_provider()),
+ is_background_suspend_enabled_(params->IsBackgroundSuspendEnabled()),
+ is_background_video_playback_enabled_(
+ params->IsBackgroundVideoPlaybackEnabled()),
+ is_background_video_track_optimization_supported_(
+ params->IsBackgroundVideoTrackOptimizationSupported()),
+ simple_watch_timer_(
+ base::BindRepeating(&WebMediaPlayerImpl::OnSimpleWatchTimerTick,
+ base::Unretained(this)),
+ base::BindRepeating(&WebMediaPlayerImpl::GetCurrentTimeInternal,
+ base::Unretained(this))),
+ will_play_helper_(nullptr),
+ demuxer_override_(params->TakeDemuxerOverride()),
+ power_status_helper_(params->TakePowerStatusHelper()) {
+ DVLOG(1) << __func__;
+ DCHECK(adjust_allocated_memory_cb_);
+ DCHECK(renderer_factory_selector_);
+ DCHECK(client_);
+ DCHECK(delegate_);
+
+ weak_this_ = weak_factory_.GetWeakPtr();
+
+ // Using base::Unretained(this) is safe because the `pipeline` is owned by
+ // `this` and the callback will always be made on the main task runner.
+ // Not using BindToCurrentLoop() because CreateRenderer() is a sync call.
+ auto pipeline = std::make_unique<media::PipelineImpl>(
+ media_task_runner_, main_task_runner_,
+ base::BindRepeating(&WebMediaPlayerImpl::CreateRenderer,
+ base::Unretained(this)),
+ media_log_.get());
+
+ pipeline_controller_ = std::make_unique<media::PipelineController>(
+ std::move(pipeline),
+ base::BindRepeating(&WebMediaPlayerImpl::OnPipelineSeeked, weak_this_),
+ base::BindRepeating(&WebMediaPlayerImpl::OnPipelineSuspended, weak_this_),
+ base::BindRepeating(&WebMediaPlayerImpl::OnBeforePipelineResume,
+ weak_this_),
+ base::BindRepeating(&WebMediaPlayerImpl::OnPipelineResumed, weak_this_),
+ base::BindRepeating(&WebMediaPlayerImpl::OnError, weak_this_));
+
+ buffered_data_source_host_ = std::make_unique<BufferedDataSourceHostImpl>(
+ base::BindRepeating(&WebMediaPlayerImpl::OnProgress, weak_this_),
+ tick_clock_);
+
+ // If we're supposed to force video overlays, then make sure that they're
+ // enabled all the time.
+ always_enable_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceVideoOverlays);
+
+ if (base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo))
+ overlay_mode_ = OverlayMode::kUseAndroidOverlay;
+ else
+ overlay_mode_ = OverlayMode::kNoOverlays;
+
+ delegate_id_ = delegate_->AddObserver(this);
+ delegate_->SetIdle(delegate_id_, true);
+
+ media_log_->AddEvent<MediaLogEvent::kWebMediaPlayerCreated>(
+ url::Origin(frame_->GetSecurityOrigin()).GetURL().spec());
+
+ media_log_->SetProperty<MediaLogProperty::kFrameUrl>(
+ SanitizeUserStringProperty(frame_->GetDocument().Url().GetString()));
+ media_log_->SetProperty<MediaLogProperty::kFrameTitle>(
+ SanitizeUserStringProperty(frame_->GetDocument().Title()));
+
+ if (params->initial_cdm())
+ SetCdmInternal(params->initial_cdm());
+
+ // Report a false "EncrytpedEvent" here as a baseline.
+ RecordEncryptedEvent(false);
+
+ auto on_audio_source_provider_set_client_callback = base::BindOnce(
+ [](base::WeakPtr<WebMediaPlayerImpl> self,
+ WebMediaPlayerClient* const client) {
+ if (!self)
+ return;
+ client->DidDisableAudioOutputSinkChanges();
+ },
+ weak_this_, client_);
+
+ // TODO(xhwang): When we use an external Renderer, many methods won't work,
+ // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
+ audio_source_provider_ = new WebAudioSourceProviderImpl(
+ params->audio_renderer_sink(), media_log_.get(),
+ std::move(on_audio_source_provider_set_client_callback));
+
+ if (observer_)
+ observer_->SetClient(this);
+
+ memory_usage_reporting_timer_.SetTaskRunner(
+ frame_->GetTaskRunner(TaskType::kInternalMedia));
+
+ main_thread_mem_dumper_ = std::make_unique<media::MemoryDumpProviderProxy>(
+ "WebMediaPlayer_MainThread", main_task_runner_,
+ base::BindRepeating(&WebMediaPlayerImpl::OnMainThreadMemoryDump,
+ weak_this_, media_log_->id()));
+
+ media_metrics_provider_->AcquirePlaybackEventsRecorder(
+ playback_events_recorder_.BindNewPipeAndPassReceiver());
+
+ // MediaMetricsProvider may drop the request for PlaybackEventsRecorder if
+ // it's not interested in recording these events.
+ playback_events_recorder_.reset_on_disconnect();
+
+#if defined(OS_ANDROID)
+ renderer_factory_selector_->SetRemotePlayStateChangeCB(
+ media::BindToCurrentLoop(base::BindRepeating(
+ &WebMediaPlayerImpl::OnRemotePlayStateChange, weak_this_)));
+#endif // defined (OS_ANDROID)
+}
+
+WebMediaPlayerImpl::~WebMediaPlayerImpl() {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (set_cdm_result_) {
+ DVLOG(2)
+ << "Resolve pending SetCdmInternal() when media player is destroyed.";
+ set_cdm_result_->Complete();
+ set_cdm_result_.reset();
+ }
+
+ suppress_destruction_errors_ = true;
+
+ delegate_->PlayerGone(delegate_id_);
+ delegate_->RemoveObserver(delegate_id_);
+ delegate_ = nullptr;
+
+ // Finalize any watch time metrics before destroying the pipeline.
+ watch_time_reporter_.reset();
+
+ // Unregister dump providers on their corresponding threads.
+ media_task_runner_->DeleteSoon(FROM_HERE,
+ std::move(media_thread_mem_dumper_));
+ main_thread_mem_dumper_.reset();
+
+ // The underlying Pipeline must be stopped before it is destroyed.
+ //
+ // Note: This destruction happens synchronously on the media thread and
+ // `demuxer_`, `data_source_`, `compositor_`, and `media_log_` must outlive
+ // this process. They will be destructed by the DestructionHelper below
+ // after trampolining through the media thread.
+ pipeline_controller_->Stop();
+
+ if (last_reported_memory_usage_)
+ adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
+
+ // Destruct compositor resources in the proper order.
+ client_->SetCcLayer(nullptr);
+
+ client_->MediaRemotingStopped(WebMediaPlayerClient::kMediaRemotingStopNoText);
+
+ if (!surface_layer_for_video_enabled_ && video_layer_)
+ video_layer_->StopUsingProvider();
+
+ simple_watch_timer_.Stop();
+ media_log_->OnWebMediaPlayerDestroyed();
+
+ if (data_source_)
+ data_source_->Stop();
+
+ // Disconnect from the surface layer. We still preserve the `bridge_` until
+ // after pipeline shutdown to ensure any pending frames are painted for tests.
+ if (bridge_)
+ bridge_->ClearObserver();
+
+ // Disconnect from the MediaObserver implementation since it's lifetime is
+ // tied to the RendererFactorySelector which can't be destroyed until after
+ // the Pipeline stops.
+ //
+ // Note: We can't use a WeakPtr with the RendererFactory because its methods
+ // are called on the media thread and this destruction takes place on the
+ // renderer thread.
+ if (observer_)
+ observer_->SetClient(nullptr);
+
+ // If we're in the middle of an observation, then finish it.
+ will_play_helper_.CompleteObservationIfNeeded(learning::TargetValue(false));
+
+ // Handle destruction of things that need to be destructed after the pipeline
+ // completes stopping on the media thread.
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DestructionHelper, std::move(main_task_runner_),
+ std::move(vfc_task_runner_), std::move(demuxer_),
+ std::move(data_source_), std::move(compositor_),
+ std::move(cdm_context_ref_),
+ std::move(pending_cdm_context_ref_), std::move(media_log_),
+ std::move(renderer_factory_selector_), std::move(bridge_),
+ !!chunk_demuxer_));
+}
+
+WebMediaPlayer::LoadTiming WebMediaPlayerImpl::Load(
+ LoadType load_type,
+ const WebMediaPlayerSource& source,
+ CorsMode cors_mode,
+ bool is_cache_disabled) {
+ // Only URL or MSE blob URL is supported.
+ DCHECK(source.IsURL());
+ WebURL url = source.GetAsURL();
+ DVLOG(1) << __func__ << "(" << load_type << ", " << GURL(url) << ", "
+ << cors_mode << ")";
+
+ bool is_deferred = false;
+
+ if (defer_load_cb_) {
+ is_deferred = defer_load_cb_.Run(
+ base::BindOnce(&WebMediaPlayerImpl::DoLoad, weak_this_, load_type, url,
+ cors_mode, is_cache_disabled));
+ } else {
+ DoLoad(load_type, url, cors_mode, is_cache_disabled);
+ }
+
+ return is_deferred ? LoadTiming::kDeferred : LoadTiming::kImmediate;
+}
+
+void WebMediaPlayerImpl::OnWebLayerUpdated() {}
+
+void WebMediaPlayerImpl::RegisterContentsLayer(cc::Layer* layer) {
+ DCHECK(bridge_);
+ bridge_->SetContentsOpaque(opaque_);
+ client_->SetCcLayer(layer);
+}
+
+void WebMediaPlayerImpl::UnregisterContentsLayer(cc::Layer* layer) {
+ // `client_` will unregister its cc::Layer if given a nullptr.
+ client_->SetCcLayer(nullptr);
+}
+
+void WebMediaPlayerImpl::OnSurfaceIdUpdated(viz::SurfaceId surface_id) {
+ // TODO(726619): Handle the behavior when Picture-in-Picture mode is
+ // disabled.
+ // The viz::SurfaceId may be updated when the video begins playback or when
+ // the size of the video changes.
+ if (client_)
+ client_->OnPictureInPictureStateChange();
+}
+
+void WebMediaPlayerImpl::EnableOverlay() {
+ overlay_enabled_ = true;
+ if (request_routing_token_cb_ &&
+ overlay_mode_ == OverlayMode::kUseAndroidOverlay) {
+ overlay_routing_token_is_pending_ = true;
+ token_available_cb_.Reset(
+ base::BindOnce(&WebMediaPlayerImpl::OnOverlayRoutingToken, weak_this_));
+ request_routing_token_cb_.Run(token_available_cb_.callback());
+ }
+
+ // We have requested (and maybe already have) overlay information. If the
+ // restarted decoder requests overlay information, then we'll defer providing
+ // it if it hasn't arrived yet. Otherwise, this would be a race, since we
+ // don't know if the request for overlay info or restart will complete first.
+ if (decoder_requires_restart_for_overlay_)
+ ScheduleRestart();
+}
+
+void WebMediaPlayerImpl::DisableOverlay() {
+ overlay_enabled_ = false;
+ if (overlay_mode_ == OverlayMode::kUseAndroidOverlay) {
+ token_available_cb_.Cancel();
+ overlay_routing_token_is_pending_ = false;
+ overlay_routing_token_ = media::OverlayInfo::RoutingToken();
+ }
+
+ if (decoder_requires_restart_for_overlay_)
+ ScheduleRestart();
+ else
+ MaybeSendOverlayInfoToDecoder();
+}
+
+void WebMediaPlayerImpl::EnteredFullscreen() {
+ overlay_info_.is_fullscreen = true;
+
+ // `always_enable_overlays_` implies that we're already in overlay mode, so
+ // take no action here. Otherwise, switch to an overlay if it's allowed and
+ // if it will display properly.
+ if (!always_enable_overlays_ && overlay_mode_ != OverlayMode::kNoOverlays &&
+ DoesOverlaySupportMetadata()) {
+ EnableOverlay();
+ }
+
+ // We send this only if we can send multiple calls. Otherwise, either (a)
+ // we already sent it and we don't have a callback anyway (we reset it when
+ // it's called in restart mode), or (b) we'll send this later when the surface
+ // actually arrives. GVD assumes that the first overlay info will have the
+ // routing information. Note that we set `is_fullscreen_` earlier, so that
+ // if EnableOverlay() can include fullscreen info in case it sends the overlay
+ // info before returning.
+ if (!decoder_requires_restart_for_overlay_)
+ MaybeSendOverlayInfoToDecoder();
+}
+
+void WebMediaPlayerImpl::ExitedFullscreen() {
+ overlay_info_.is_fullscreen = false;
+
+ // If we're in overlay mode, then exit it unless we're supposed to allow
+ // overlays all the time.
+ if (!always_enable_overlays_ && overlay_enabled_)
+ DisableOverlay();
+
+ // See EnteredFullscreen for why we do this.
+ if (!decoder_requires_restart_for_overlay_)
+ MaybeSendOverlayInfoToDecoder();
+}
+
+void WebMediaPlayerImpl::BecameDominantVisibleContent(bool is_dominant) {
+ if (observer_)
+ observer_->OnBecameDominantVisibleContent(is_dominant);
+}
+
+void WebMediaPlayerImpl::SetIsEffectivelyFullscreen(
+ WebFullscreenVideoStatus fullscreen_video_status) {
+ if (power_status_helper_) {
+ // We don't care about pip, so anything that's "not fullscreen" is good
+ // enough for us.
+ power_status_helper_->SetIsFullscreen(
+ fullscreen_video_status !=
+ WebFullscreenVideoStatus::kNotEffectivelyFullscreen);
+ }
+}
+
+void WebMediaPlayerImpl::OnHasNativeControlsChanged(bool has_native_controls) {
+ if (!watch_time_reporter_)
+ return;
+
+ if (has_native_controls)
+ watch_time_reporter_->OnNativeControlsEnabled();
+ else
+ watch_time_reporter_->OnNativeControlsDisabled();
+}
+
+void WebMediaPlayerImpl::OnDisplayTypeChanged(DisplayType display_type) {
+ if (surface_layer_for_video_enabled_) {
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoFrameCompositor::SetForceSubmit,
+ base::Unretained(compositor_.get()),
+ display_type == DisplayType::kPictureInPicture));
+ }
+
+ if (!watch_time_reporter_)
+ return;
+
+ switch (display_type) {
+ case DisplayType::kInline:
+ watch_time_reporter_->OnDisplayTypeInline();
+ break;
+ case DisplayType::kFullscreen:
+ watch_time_reporter_->OnDisplayTypeFullscreen();
+ break;
+ case DisplayType::kPictureInPicture:
+ watch_time_reporter_->OnDisplayTypePictureInPicture();
+
+ // Resumes playback if it was paused when hidden.
+ if (paused_when_hidden_) {
+ paused_when_hidden_ = false;
+ client_->ResumePlayback();
+ }
+ break;
+ }
+}
+
+void WebMediaPlayerImpl::DoLoad(LoadType load_type,
+ const WebURL& url,
+ CorsMode cors_mode,
+ bool is_cache_disabled) {
+ TRACE_EVENT1("media", "WebMediaPlayerImpl::DoLoad", "id", media_log_->id());
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Start a new observation. If there was one before, then we didn't play it.
+ will_play_helper_.CompleteObservationIfNeeded(learning::TargetValue(false));
+ // For now, send in an empty set of features. We should fill some in here,
+ // and / or ask blink (via `client_`) for features from the DOM.
+ learning::FeatureDictionary dict;
+ will_play_helper_.BeginObservation(dict);
+
+#if defined(OS_ANDROID)
+ // Only allow credentials if the crossorigin attribute is unspecified
+ // (kCorsModeUnspecified) or "use-credentials" (kCorsModeUseCredentials).
+ // This value is only used by the MediaPlayerRenderer.
+ // See https://crbug.com/936566.
+ //
+ // The credentials mode also has repercussions in WouldTaintOrigin(), but we
+ // access what we need from `mb_data_source_`->cors_mode() directly, instead
+ // of storing it here.
+ allow_media_player_renderer_credentials_ = cors_mode != kCorsModeAnonymous;
+#endif // defined(OS_ANDROID)
+
+ // Note: `url` may be very large, take care when making copies.
+ loaded_url_ = GURL(url);
+ load_type_ = load_type;
+
+ ReportMetrics(load_type, loaded_url_, *frame_, media_log_.get());
+
+ // Set subresource URL for crash reporting; will be truncated to 256 bytes.
+ static base::debug::CrashKeyString* subresource_url =
+ base::debug::AllocateCrashKeyString("subresource_url",
+ base::debug::CrashKeySize::Size256);
+ base::debug::SetCrashKeyString(subresource_url, loaded_url_.spec());
+
+ SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
+
+ // Do a truncation to kMaxUrlLength+1 at most; we can add ellipsis later.
+ media_log_->AddEvent<MediaLogEvent::kLoad>(
+ url.GetString().Substring(0, media::kMaxUrlLength + 1).Utf8());
+ load_start_time_ = base::TimeTicks::Now();
+
+ std::vector<media::TextTrackConfig> text_configs;
+ for (const auto& metadata : client_->GetTextTrackMetadata()) {
+ text_configs.emplace_back(
+ media::TextTrackConfig::ConvertKind(metadata.kind()), metadata.label(),
+ metadata.language(), metadata.id());
+ }
+ media_log_->SetProperty<MediaLogProperty::kTextTracks>(text_configs);
+
+ // If we're adapting, then restart the smoothness experiment.
+ if (smoothness_helper_)
+ smoothness_helper_.reset();
+
+ media_metrics_provider_->Initialize(
+ load_type == kLoadTypeMediaSource,
+ load_type == kLoadTypeURL ? GetMediaURLScheme(loaded_url_)
+ : media::mojom::MediaURLScheme::kUnknown,
+ media::mojom::MediaStreamType::kNone);
+
+ if (demuxer_override_ || load_type == kLoadTypeMediaSource) {
+ // If a demuxer override was specified or a Media Source pipeline will be
+ // used, the pipeline can start immediately.
+ StartPipeline();
+ } else {
+ // If `loaded_url_` is remoting media, starting the pipeline.
+ if (loaded_url_.SchemeIs(media::remoting::kRemotingScheme)) {
+ StartPipeline();
+ return;
+ }
+
+ // Short circuit the more complex loading path for data:// URLs. Sending
+ // them through the network based loading path just wastes memory and causes
+ // worse performance since reads become asynchronous.
+ if (loaded_url_.SchemeIs(url::kDataScheme)) {
+ std::string mime_type, charset, data;
+ if (!net::DataURL::Parse(loaded_url_, &mime_type, &charset, &data) ||
+ data.empty()) {
+ DataSourceInitialized(false);
+ return;
+ }
+
+ // Replace `loaded_url_` with an empty data:// URL since it may be large.
+ loaded_url_ = GURL("data:,");
+
+ // Mark all the data as buffered.
+ buffered_data_source_host_->SetTotalBytes(data.size());
+ buffered_data_source_host_->AddBufferedByteRange(0, data.size());
+
+ DCHECK(!mb_data_source_);
+ data_source_ = std::make_unique<media::MemoryDataSource>(std::move(data));
+ DataSourceInitialized(true);
+ return;
+ }
+
+ auto url_data = url_index_->GetByUrl(
+ url, static_cast<UrlData::CorsMode>(cors_mode),
+ is_cache_disabled ? UrlIndex::kCacheDisabled : UrlIndex::kNormal);
+ mb_data_source_ = new MultiBufferDataSource(
+ main_task_runner_, std::move(url_data), media_log_.get(),
+ buffered_data_source_host_.get(),
+ base::BindRepeating(&WebMediaPlayerImpl::NotifyDownloading,
+ weak_this_));
+ data_source_.reset(mb_data_source_);
+ mb_data_source_->OnRedirect(base::BindRepeating(
+ &WebMediaPlayerImpl::OnDataSourceRedirected, weak_this_));
+ mb_data_source_->SetPreload(preload_);
+ mb_data_source_->SetIsClientAudioElement(client_->IsAudioElement());
+ mb_data_source_->Initialize(
+ base::BindOnce(&WebMediaPlayerImpl::DataSourceInitialized, weak_this_));
+ }
+}
+
+void WebMediaPlayerImpl::Play() {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // User initiated play unlocks background video playback.
+ if (frame_->HasTransientUserActivation())
+ video_locked_when_paused_when_hidden_ = false;
+
+ // TODO(sandersd): Do we want to reset the idle timer here?
+ delegate_->SetIdle(delegate_id_, false);
+ paused_ = false;
+ pipeline_controller_->SetPlaybackRate(playback_rate_);
+ background_pause_timer_.Stop();
+
+ if (observer_)
+ observer_->OnPlaying();
+
+ // Try to create the smoothness helper, in case we were paused before.
+ UpdateSmoothnessHelper();
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnPlaying();
+
+ watch_time_reporter_->SetAutoplayInitiated(client_->WasAutoplayInitiated());
+
+ // If we're seeking we'll trigger the watch time reporter upon seek completed;
+ // we don't want to start it here since the seek time is unstable. E.g., when
+ // playing content with a positive start time we would have a zero seek time.
+ if (!Seeking()) {
+ DCHECK(watch_time_reporter_);
+ watch_time_reporter_->OnPlaying();
+ }
+
+ if (video_decode_stats_reporter_)
+ video_decode_stats_reporter_->OnPlaying();
+
+ simple_watch_timer_.Start();
+ media_metrics_provider_->SetHasPlayed();
+ media_log_->AddEvent<MediaLogEvent::kPlay>();
+
+ MaybeUpdateBufferSizesForPlayback();
+ UpdatePlayState();
+
+ // Notify the learning task, if needed.
+ will_play_helper_.CompleteObservationIfNeeded(learning::TargetValue(true));
+}
+
+void WebMediaPlayerImpl::Pause() {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // We update the paused state even when casting, since we expect pause() to be
+ // called when casting begins, and when we exit casting we should end up in a
+ // paused state.
+ paused_ = true;
+
+ // No longer paused because it was hidden.
+ paused_when_hidden_ = false;
+
+ UpdateSmoothnessHelper();
+
+ // User initiated pause locks background videos.
+ if (frame_->HasTransientUserActivation())
+ video_locked_when_paused_when_hidden_ = true;
+
+ pipeline_controller_->SetPlaybackRate(0.0);
+
+ // For states <= kReadyStateHaveMetadata, we may not have a renderer yet.
+ if (highest_ready_state_ > WebMediaPlayer::kReadyStateHaveMetadata)
+ paused_time_ = pipeline_controller_->GetMediaTime();
+
+ if (observer_)
+ observer_->OnPaused();
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnPaused();
+
+ DCHECK(watch_time_reporter_);
+ watch_time_reporter_->OnPaused();
+
+ if (video_decode_stats_reporter_)
+ video_decode_stats_reporter_->OnPaused();
+
+ simple_watch_timer_.Stop();
+ media_log_->AddEvent<MediaLogEvent::kPause>();
+
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::Seek(double seconds) {
+ DVLOG(1) << __func__ << "(" << seconds << "s)";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ media_log_->AddEvent<MediaLogEvent::kSeek>(seconds);
+ DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
+}
+
+void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT2("media", "WebMediaPlayerImpl::DoSeek", "target",
+ time.InSecondsF(), "id", media_log_->id());
+
+ ReadyState old_state = ready_state_;
+ if (ready_state_ > WebMediaPlayer::kReadyStateHaveMetadata)
+ SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
+
+ // When paused or ended, we know exactly what the current time is and can
+ // elide seeks to it. However, there are two cases that are not elided:
+ // 1) When the pipeline state is not stable.
+ // In this case we just let `pipeline_controller_` decide what to do, as
+ // it has complete information.
+ // 2) For MSE.
+ // Because the buffers may have changed between seeks, MSE seeks are
+ // never elided.
+ if (paused_ && pipeline_controller_->IsStable() &&
+ (paused_time_ == time ||
+ (ended_ && time == base::TimeDelta::FromSecondsD(Duration()))) &&
+ !chunk_demuxer_) {
+ // If the ready state was high enough before, we can indicate that the seek
+ // completed just by restoring it. Otherwise we will just wait for the real
+ // ready state change to eventually happen.
+ if (old_state == kReadyStateHaveEnoughData) {
+ main_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&WebMediaPlayerImpl::OnBufferingStateChange,
+ weak_this_, media::BUFFERING_HAVE_ENOUGH,
+ media::BUFFERING_CHANGE_REASON_UNKNOWN));
+ }
+ return;
+ }
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnSeeking();
+
+ // Call this before setting `seeking_` so that the current media time can be
+ // recorded by the reporter.
+ if (watch_time_reporter_)
+ watch_time_reporter_->OnSeeking();
+
+ // Send the seek updates only when the seek pipeline hasn't started,
+ // OnPipelineSeeked is not called yet.
+ if (!seeking_)
+ client_->DidSeek();
+
+ // TODO(sandersd): Move `seeking_` to PipelineController.
+ // TODO(sandersd): Do we want to reset the idle timer here?
+ delegate_->SetIdle(delegate_id_, false);
+ ended_ = false;
+ seeking_ = true;
+ seek_time_ = time;
+ if (paused_)
+ paused_time_ = time;
+ pipeline_controller_->Seek(time, time_updated);
+
+ // This needs to be called after Seek() so that if a resume is triggered, it
+ // is to the correct time.
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::SetRate(double rate) {
+ DVLOG(1) << __func__ << "(" << rate << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (rate != playback_rate_) {
+ LIMITED_MEDIA_LOG(INFO, media_log_.get(), num_playback_rate_logs_,
+ kMaxNumPlaybackRateLogs)
+ << "Effective playback rate changed from " << playback_rate_ << " to "
+ << rate;
+ }
+
+ playback_rate_ = rate;
+ if (!paused_)
+ pipeline_controller_->SetPlaybackRate(rate);
+
+ MaybeUpdateBufferSizesForPlayback();
+}
+
+void WebMediaPlayerImpl::SetVolume(double volume) {
+ DVLOG(1) << __func__ << "(" << volume << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ volume_ = volume;
+ pipeline_controller_->SetVolume(volume_ * volume_multiplier_);
+ if (watch_time_reporter_)
+ watch_time_reporter_->OnVolumeChange(volume);
+ client_->DidPlayerMutedStatusChange(volume == 0.0);
+
+ if (delegate_has_audio_ != HasUnmutedAudio()) {
+ delegate_has_audio_ = HasUnmutedAudio();
+ media::MediaContentType content_type = GetMediaContentType();
+ client_->DidMediaMetadataChange(delegate_has_audio_, HasVideo(),
+ content_type);
+ delegate_->DidMediaMetadataChange(delegate_id_, delegate_has_audio_,
+ HasVideo(), content_type);
+ }
+
+ // The play state is updated because the player might have left the autoplay
+ // muted state.
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::SetLatencyHint(double seconds) {
+ DVLOG(1) << __func__ << "(" << seconds << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ absl::optional<base::TimeDelta> latency_hint;
+ if (std::isfinite(seconds)) {
+ DCHECK_GE(seconds, 0);
+ latency_hint = base::TimeDelta::FromSecondsD(seconds);
+ }
+ pipeline_controller_->SetLatencyHint(latency_hint);
+}
+
+void WebMediaPlayerImpl::SetPreservesPitch(bool preserves_pitch) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ pipeline_controller_->SetPreservesPitch(preserves_pitch);
+}
+
+void WebMediaPlayerImpl::SetAutoplayInitiated(bool autoplay_initiated) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ pipeline_controller_->SetAutoplayInitiated(autoplay_initiated);
+}
+
+void WebMediaPlayerImpl::OnRequestPictureInPicture() {
+ if (!surface_layer_for_video_enabled_)
+ ActivateSurfaceLayerForVideo();
+
+ DCHECK(bridge_);
+ DCHECK(bridge_->GetSurfaceId().is_valid());
+}
+
+bool WebMediaPlayerImpl::SetSinkId(
+ const WebString& sink_id,
+ WebSetSinkIdCompleteCallback completion_callback) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DVLOG(1) << __func__;
+
+ media::OutputDeviceStatusCB callback =
+ ConvertToOutputDeviceStatusCB(std::move(completion_callback));
+ auto sink_id_utf8 = sink_id.Utf8();
+ media_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&SetSinkIdOnMediaThread, audio_source_provider_,
+ sink_id_utf8, std::move(callback)));
+ return true;
+}
+
+STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadNone, MultiBufferDataSource::NONE);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadMetaData,
+ MultiBufferDataSource::METADATA);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadAuto, MultiBufferDataSource::AUTO);
+
+void WebMediaPlayerImpl::SetPreload(WebMediaPlayer::Preload preload) {
+ DVLOG(1) << __func__ << "(" << preload << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ preload_ = static_cast<MultiBufferDataSource::Preload>(preload);
+ if (mb_data_source_)
+ mb_data_source_->SetPreload(preload_);
+}
+
+bool WebMediaPlayerImpl::HasVideo() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ return pipeline_metadata_.has_video;
+}
+
+bool WebMediaPlayerImpl::HasAudio() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ return pipeline_metadata_.has_audio;
+}
+
+void WebMediaPlayerImpl::EnabledAudioTracksChanged(
+ const WebVector<WebMediaPlayer::TrackId>& enabledTrackIds) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ std::ostringstream logstr;
+ std::vector<MediaTrack::Id> enabledMediaTrackIds;
+ for (const auto& blinkTrackId : enabledTrackIds) {
+ const auto track_id = MediaTrack::Id(blinkTrackId.Utf8().data());
+ logstr << track_id << " ";
+ enabledMediaTrackIds.push_back(track_id);
+ }
+ MEDIA_LOG(INFO, media_log_.get())
+ << "Enabled audio tracks: [" << logstr.str() << "]";
+ pipeline_controller_->OnEnabledAudioTracksChanged(enabledMediaTrackIds);
+}
+
+void WebMediaPlayerImpl::SelectedVideoTrackChanged(
+ WebMediaPlayer::TrackId* selectedTrackId) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ absl::optional<MediaTrack::Id> selected_video_track_id;
+ if (selectedTrackId && !video_track_disabled_)
+ selected_video_track_id = MediaTrack::Id(selectedTrackId->Utf8().data());
+ MEDIA_LOG(INFO, media_log_.get())
+ << "Selected video track: ["
+ << selected_video_track_id.value_or(MediaTrack::Id()) << "]";
+ pipeline_controller_->OnSelectedVideoTrackChanged(selected_video_track_id);
+}
+
+gfx::Size WebMediaPlayerImpl::NaturalSize() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ return pipeline_metadata_.natural_size;
+}
+
+gfx::Size WebMediaPlayerImpl::VisibleSize() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ scoped_refptr<media::VideoFrame> video_frame =
+ GetCurrentFrameFromCompositor();
+ if (!video_frame)
+ return gfx::Size();
+
+ return video_frame->visible_rect().size();
+}
+
+bool WebMediaPlayerImpl::Paused() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return pipeline_controller_->GetPlaybackRate() == 0.0f;
+}
+
+bool WebMediaPlayerImpl::PausedWhenHidden() const {
+ return paused_when_hidden_;
+}
+
+bool WebMediaPlayerImpl::Seeking() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
+ return false;
+
+ return seeking_;
+}
+
+double WebMediaPlayerImpl::Duration() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
+ return std::numeric_limits<double>::quiet_NaN();
+
+ // Use duration from ChunkDemuxer when present. MSE allows users to specify
+ // duration as a double. This propagates to the rest of the pipeline as a
+ // TimeDelta with potentially reduced precision (limited to Microseconds).
+ // ChunkDemuxer returns the full-precision user-specified double. This ensures
+ // users can "get" the exact duration they "set".
+ if (chunk_demuxer_)
+ return chunk_demuxer_->GetDuration();
+
+ base::TimeDelta pipeline_duration = GetPipelineMediaDuration();
+ return pipeline_duration == media::kInfiniteDuration
+ ? std::numeric_limits<double>::infinity()
+ : pipeline_duration.InSecondsF();
+}
+
+double WebMediaPlayerImpl::timelineOffset() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (pipeline_metadata_.timeline_offset.is_null())
+ return std::numeric_limits<double>::quiet_NaN();
+
+ return pipeline_metadata_.timeline_offset.ToJsTime();
+}
+
+base::TimeDelta WebMediaPlayerImpl::GetCurrentTimeInternal() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ base::TimeDelta current_time;
+ if (Seeking())
+ current_time = seek_time_;
+ else if (paused_)
+ current_time = paused_time_;
+ else
+ current_time = pipeline_controller_->GetMediaTime();
+
+ // It's possible for `current_time` to be kInfiniteDuration here if the page
+ // seeks to kInfiniteDuration (2**64 - 1) when Duration() is infinite.
+ DCHECK_GE(current_time, base::TimeDelta());
+ return current_time;
+}
+
+double WebMediaPlayerImpl::CurrentTime() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
+
+ // Even though we have an explicit ended signal, a lot of content doesn't have
+ // an accurate duration -- with some formats (e.g., VBR MP3, OGG) it can't be
+ // known without a complete play-through from beginning to end.
+ //
+ // The HTML5 spec says that upon ended, current time must equal duration. Due
+ // to the aforementioned issue, if we rely exclusively on current time, we can
+ // be a few milliseconds off of the duration.
+ const auto duration = Duration();
+ return (ended_ && !std::isinf(duration))
+ ? duration
+ : GetCurrentTimeInternal().InSecondsF();
+}
+
+bool WebMediaPlayerImpl::IsEnded() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return ended_;
+}
+
+WebMediaPlayer::NetworkState WebMediaPlayerImpl::GetNetworkState() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return network_state_;
+}
+
+WebMediaPlayer::ReadyState WebMediaPlayerImpl::GetReadyState() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return ready_state_;
+}
+
+WebMediaPlayer::SurfaceLayerMode WebMediaPlayerImpl::GetVideoSurfaceLayerMode()
+ const {
+ return surface_layer_mode_;
+}
+
+WebString WebMediaPlayerImpl::GetErrorMessage() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return WebString::FromUTF8(media_log_->GetErrorMessage());
+}
+
+WebTimeRanges WebMediaPlayerImpl::Buffered() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ media::Ranges<base::TimeDelta> buffered_time_ranges =
+ pipeline_controller_->GetBufferedTimeRanges();
+
+ const base::TimeDelta duration = GetPipelineMediaDuration();
+ if (duration != media::kInfiniteDuration) {
+ buffered_data_source_host_->AddBufferedTimeRanges(&buffered_time_ranges,
+ duration);
+ }
+ return ConvertToWebTimeRanges(buffered_time_ranges);
+}
+
+WebTimeRanges WebMediaPlayerImpl::Seekable() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (ready_state_ < WebMediaPlayer::kReadyStateHaveMetadata)
+ return WebTimeRanges();
+
+ const double seekable_end = Duration();
+
+ // Allow a special exception for seeks to zero for streaming sources with a
+ // finite duration; this allows looping to work.
+ const bool is_finite_stream = mb_data_source_ &&
+ mb_data_source_->IsStreaming() &&
+ std::isfinite(seekable_end);
+
+ // Do not change the seekable range when using the MediaPlayerRenderer. It
+ // will take care of dropping invalid seeks.
+ const bool force_seeks_to_zero =
+ !using_media_player_renderer_ && is_finite_stream;
+
+ // TODO(dalecurtis): Technically this allows seeking on media which return an
+ // infinite duration so long as DataSource::IsStreaming() is false. While not
+ // expected, disabling this breaks semi-live players, http://crbug.com/427412.
+ const WebTimeRange seekable_range(0.0,
+ force_seeks_to_zero ? 0.0 : seekable_end);
+ return WebTimeRanges(&seekable_range, 1);
+}
+
+bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
+ // TODO(sandersd): Replace with `highest_ready_state_since_seek_` if we need
+ // to ensure that preroll always gets a chance to complete.
+ // See http://crbug.com/671525.
+ //
+ // Note: Even though we get play/pause signals at kReadyStateHaveMetadata, we
+ // must attempt to preroll until kReadyStateHaveFutureData so that the
+ // canplaythrough event will be fired to the page (which may be waiting).
+ //
+ // TODO(dalecurtis): We should try signaling kReadyStateHaveFutureData upon
+ // automatic-suspend of a non-playing element to avoid wasting resources.
+ if (highest_ready_state_ >= ReadyState::kReadyStateHaveFutureData)
+ return false;
+
+ // To suspend before we reach kReadyStateHaveCurrentData is only ok
+ // if we know we're going to get woken up when we get more data, which
+ // will only happen if the network is in the "Loading" state.
+ // This happens when the network is fast, but multiple videos are loading
+ // and multiplexing gets held up waiting for available threads.
+ if (highest_ready_state_ <= ReadyState::kReadyStateHaveMetadata &&
+ network_state_ != WebMediaPlayer::kNetworkStateLoading) {
+ return true;
+ }
+
+ if (preroll_attempt_pending_)
+ return true;
+
+ // Freshly initialized; there has never been any loading progress. (Otherwise
+ // `preroll_attempt_pending_` would be true when the start time is null.)
+ if (preroll_attempt_start_time_.is_null())
+ return false;
+
+ base::TimeDelta preroll_attempt_duration =
+ tick_clock_->NowTicks() - preroll_attempt_start_time_;
+ return preroll_attempt_duration < kPrerollAttemptTimeout;
+}
+
+bool WebMediaPlayerImpl::DidLoadingProgress() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Note: Separate variables used to ensure both methods are called every time.
+ const bool pipeline_progress = pipeline_controller_->DidLoadingProgress();
+ const bool data_progress = buffered_data_source_host_->DidLoadingProgress();
+ return pipeline_progress || data_progress;
+}
+
+void WebMediaPlayerImpl::Paint(cc::PaintCanvas* canvas,
+ const gfx::Rect& rect,
+ cc::PaintFlags& flags) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
+
+ scoped_refptr<media::VideoFrame> video_frame =
+ GetCurrentFrameFromCompositor();
+ last_frame_request_time_ = tick_clock_->NowTicks();
+
+ video_renderer_.Paint(
+ video_frame, canvas, gfx::RectF(rect), flags,
+ pipeline_metadata_.video_decoder_config.video_transformation(),
+ raster_context_provider_.get());
+}
+
+scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() {
+ last_frame_request_time_ = tick_clock_->NowTicks();
+ return GetCurrentFrameFromCompositor();
+}
+
+media::PaintCanvasVideoRenderer*
+WebMediaPlayerImpl::GetPaintCanvasVideoRenderer() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return &video_renderer_;
+}
+
+bool WebMediaPlayerImpl::WouldTaintOrigin() const {
+ if (demuxer_found_hls_) {
+ // HLS manifests might pull segments from a different origin. We can't know
+ // for sure, so we conservatively say no here.
+ return true;
+ }
+
+ if (!mb_data_source_)
+ return false;
+
+ // When the resource is redirected to another origin we think it as
+ // tainted. This is actually not specified, and is under discussion.
+ // See https://github.com/whatwg/fetch/issues/737.
+ if (!mb_data_source_->HasSingleOrigin() &&
+ mb_data_source_->cors_mode() == UrlData::CORS_UNSPECIFIED) {
+ return true;
+ }
+
+ return mb_data_source_->IsCorsCrossOrigin();
+}
+
+double WebMediaPlayerImpl::MediaTimeForTimeValue(double timeValue) const {
+ return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
+}
+
+unsigned WebMediaPlayerImpl::DecodedFrameCount() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return GetPipelineStatistics().video_frames_decoded;
+}
+
+unsigned WebMediaPlayerImpl::DroppedFrameCount() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return GetPipelineStatistics().video_frames_dropped;
+}
+
+uint64_t WebMediaPlayerImpl::AudioDecodedByteCount() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return GetPipelineStatistics().audio_bytes_decoded;
+}
+
+uint64_t WebMediaPlayerImpl::VideoDecodedByteCount() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return GetPipelineStatistics().video_bytes_decoded;
+}
+
+bool WebMediaPlayerImpl::HasAvailableVideoFrame() const {
+ return has_first_frame_;
+}
+
+void WebMediaPlayerImpl::SetContentDecryptionModule(
+ WebContentDecryptionModule* cdm,
+ WebContentDecryptionModuleResult result) {
+ DVLOG(1) << __func__ << ": cdm = " << cdm;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Once the CDM is set it can't be cleared as there may be frames being
+ // decrypted on other threads. So fail this request.
+ // http://crbug.com/462365#c7.
+ if (!cdm) {
+ result.CompleteWithError(
+ kWebContentDecryptionModuleExceptionInvalidStateError, 0,
+ "The existing ContentDecryptionModule object cannot be removed at this "
+ "time.");
+ return;
+ }
+
+ // Create a local copy of `result` to avoid problems with the callback
+ // getting passed to the media thread and causing `result` to be destructed
+ // on the wrong thread in some failure conditions. Blink should prevent
+ // multiple simultaneous calls.
+ DCHECK(!set_cdm_result_);
+ set_cdm_result_ = std::make_unique<WebContentDecryptionModuleResult>(result);
+
+ SetCdmInternal(cdm);
+}
+
+void WebMediaPlayerImpl::OnEncryptedMediaInitData(
+ media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data) {
+ DCHECK(init_data_type != media::EmeInitDataType::UNKNOWN);
+
+ RecordEncryptedEvent(true);
+
+ // Recreate the watch time reporter if necessary.
+ const bool was_encrypted = is_encrypted_;
+ is_encrypted_ = true;
+ if (!was_encrypted) {
+ media_metrics_provider_->SetIsEME();
+ if (watch_time_reporter_)
+ CreateWatchTimeReporter();
+
+ // `was_encrypted` = false means we didn't have a CDM prior to observing
+ // encrypted media init data. Reset the reporter until the CDM arrives. See
+ // SetCdmInternal().
+ DCHECK(!cdm_config_);
+ video_decode_stats_reporter_.reset();
+ }
+
+ encrypted_client_->Encrypted(
+ init_data_type, init_data.data(),
+ base::saturated_cast<unsigned int>(init_data.size()));
+}
+
+void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
+ std::unique_ptr<media::MediaTracks> tracks) {
+ // For MSE/chunk_demuxer case the media track updates are handled by
+ // WebSourceBufferImpl.
+ DCHECK(demuxer_.get());
+ DCHECK(!chunk_demuxer_);
+
+ // Report the media track information to blink. Only the first audio track and
+ // the first video track are enabled by default to match blink logic.
+ bool is_first_audio_track = true;
+ bool is_first_video_track = true;
+ for (const auto& track : tracks->tracks()) {
+ if (track->type() == MediaTrack::Audio) {
+ client_->AddAudioTrack(WebString::FromUTF8(track->id().value()),
+ WebMediaPlayerClient::kAudioTrackKindMain,
+ WebString::FromUTF8(track->label().value()),
+ WebString::FromUTF8(track->language().value()),
+ is_first_audio_track);
+ is_first_audio_track = false;
+ } else if (track->type() == MediaTrack::Video) {
+ client_->AddVideoTrack(WebString::FromUTF8(track->id().value()),
+ WebMediaPlayerClient::kVideoTrackKindMain,
+ WebString::FromUTF8(track->label().value()),
+ WebString::FromUTF8(track->language().value()),
+ is_first_video_track);
+ is_first_video_track = false;
+ } else {
+ // Text tracks are not supported through this code path yet.
+ NOTREACHED();
+ }
+ }
+}
+
+void WebMediaPlayerImpl::SetCdmInternal(WebContentDecryptionModule* cdm) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(cdm);
+
+ const bool was_encrypted = is_encrypted_;
+ is_encrypted_ = true;
+
+ // Recreate the watch time reporter if necessary.
+ if (!was_encrypted) {
+ media_metrics_provider_->SetIsEME();
+ if (watch_time_reporter_)
+ CreateWatchTimeReporter();
+ }
+
+ WebContentDecryptionModuleImpl* web_cdm =
+ ToWebContentDecryptionModuleImpl(cdm);
+ auto cdm_context_ref = web_cdm->GetCdmContextRef();
+ if (!cdm_context_ref) {
+ NOTREACHED();
+ OnCdmAttached(false);
+ return;
+ }
+
+ // Arrival of `cdm_config_` and `key_system_` unblocks recording of encrypted
+ // stats. Attempt to create the stats reporter. Note, we do NOT guard this
+ // within !was_encypted above because often the CDM arrives after the call to
+ // OnEncryptedMediaInitData().
+ cdm_config_ = web_cdm->GetCdmConfig();
+ key_system_ = web_cdm->GetKeySystem();
+ DCHECK(!key_system_.empty());
+
+ media_metrics_provider_->SetKeySystem(key_system_);
+ if (cdm_config_->use_hw_secure_codecs)
+ media_metrics_provider_->SetIsHardwareSecure();
+ CreateVideoDecodeStatsReporter();
+
+ auto* cdm_context = cdm_context_ref->GetCdmContext();
+ DCHECK(cdm_context);
+
+ // Keep the reference to the CDM, as it shouldn't be destroyed until
+ // after the pipeline is done with the `cdm_context`.
+ pending_cdm_context_ref_ = std::move(cdm_context_ref);
+ pipeline_controller_->SetCdm(
+ cdm_context,
+ base::BindOnce(&WebMediaPlayerImpl::OnCdmAttached, weak_this_));
+}
+
+void WebMediaPlayerImpl::OnCdmAttached(bool success) {
+ DVLOG(1) << __func__ << ": success = " << success;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(pending_cdm_context_ref_);
+
+ // If the CDM is set from the constructor there is no promise
+ // (`set_cdm_result_`) to fulfill.
+ if (success) {
+ media_log_->SetProperty<MediaLogProperty::kIsVideoEncrypted>(true);
+
+ // This will release the previously attached CDM (if any).
+ cdm_context_ref_ = std::move(pending_cdm_context_ref_);
+ if (set_cdm_result_) {
+ set_cdm_result_->Complete();
+ set_cdm_result_.reset();
+ }
+
+ return;
+ }
+
+ pending_cdm_context_ref_.reset();
+ if (set_cdm_result_) {
+ set_cdm_result_->CompleteWithError(
+ kWebContentDecryptionModuleExceptionNotSupportedError, 0,
+ "Unable to set ContentDecryptionModule object");
+ set_cdm_result_.reset();
+ }
+}
+
+void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
+ TRACE_EVENT2("media", "WebMediaPlayerImpl::OnPipelineSeeked", "target",
+ seek_time_.InSecondsF(), "id", media_log_->id());
+ seeking_ = false;
+ seek_time_ = base::TimeDelta();
+
+ if (paused_) {
+ paused_time_ = pipeline_controller_->GetMediaTime();
+ } else {
+ DCHECK(watch_time_reporter_);
+ watch_time_reporter_->OnPlaying();
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnPlaying();
+ }
+ if (time_updated)
+ should_notify_time_changed_ = true;
+
+ // Reset underflow duration upon seek; this prevents looping videos and user
+ // actions from artificially inflating the duration.
+ underflow_timer_.reset();
+
+ // Background video optimizations are delayed when shown/hidden if pipeline
+ // is seeking.
+ UpdateBackgroundVideoOptimizationState();
+
+ // If we successfully completed a suspended startup, we need to make a call to
+ // UpdatePlayState() in case any events which should trigger a resume have
+ // occurred during startup.
+ if (attempting_suspended_start_ &&
+ pipeline_controller_->IsPipelineSuspended()) {
+ skip_metrics_due_to_startup_suspend_ = true;
+
+ // If we successfully completed a suspended startup, signal that we have
+ // reached BUFFERING_HAVE_ENOUGH so that canplay and canplaythrough fire
+ // correctly. We must unfortunately always do this because it's valid for
+ // elements to play while not visible nor even in the DOM.
+ //
+ // Note: This call is dual purpose, it is also responsible for triggering an
+ // UpdatePlayState() call which may need to resume the pipeline once Blink
+ // has been told about the ReadyState change.
+ OnBufferingStateChangeInternal(media::BUFFERING_HAVE_ENOUGH,
+ media::BUFFERING_CHANGE_REASON_UNKNOWN,
+ true);
+ }
+
+ attempting_suspended_start_ = false;
+}
+
+void WebMediaPlayerImpl::OnPipelineSuspended() {
+ // Add a log event so the player shows up as "SUSPENDED" in media-internals.
+ media_log_->AddEvent<MediaLogEvent::kSuspended>();
+
+ if (attempting_suspended_start_) {
+ DCHECK(pipeline_controller_->IsSuspended());
+ did_lazy_load_ = !has_poster_ && HasVideo();
+ }
+
+ // Tell the data source we have enough data so that it may release the
+ // connection (unless blink is waiting on us to signal play()).
+ if (mb_data_source_ && !client_->CouldPlayIfEnoughData()) {
+ // `attempting_suspended_start_` will be cleared by OnPipelineSeeked() which
+ // will occur after this method during a suspended startup.
+ if (attempting_suspended_start_ && did_lazy_load_) {
+ DCHECK(!has_first_frame_);
+ DCHECK(have_enough_after_lazy_load_cb_.IsCancelled());
+
+ // For lazy load, we won't know if the element is non-visible until a
+ // layout completes, so to avoid unnecessarily tearing down the network
+ // connection, briefly (250ms chosen arbitrarily) delay signaling "have
+ // enough" to the MultiBufferDataSource.
+ //
+ // base::Unretained() is safe here since the base::CancelableOnceClosure
+ // will cancel upon destruction of this class and `mb_data_source_` is
+ // gauranteeed to outlive us.
+ have_enough_after_lazy_load_cb_.Reset(
+ base::BindOnce(&MultiBufferDataSource::OnBufferingHaveEnough,
+ base::Unretained(mb_data_source_), true));
+ main_task_runner_->PostDelayedTask(
+ FROM_HERE, have_enough_after_lazy_load_cb_.callback(),
+ base::TimeDelta::FromMilliseconds(250));
+ } else {
+ have_enough_after_lazy_load_cb_.Cancel();
+ mb_data_source_->OnBufferingHaveEnough(true);
+ }
+ }
+
+ ReportMemoryUsage();
+
+ if (pending_suspend_resume_cycle_) {
+ pending_suspend_resume_cycle_ = false;
+ UpdatePlayState();
+ }
+}
+
+void WebMediaPlayerImpl::OnBeforePipelineResume() {
+ // Since we're resuming, cancel closing of the network connection.
+ have_enough_after_lazy_load_cb_.Cancel();
+
+ // We went through suspended startup, so the player is only just now spooling
+ // up for playback. As such adjust `load_start_time_` so it reports the same
+ // metric as what would be reported if we had not suspended at startup.
+ if (skip_metrics_due_to_startup_suspend_) {
+ // In the event that the call to SetReadyState() initiated after pipeline
+ // startup immediately tries to start playback, we should not update
+ // `load_start_time_` to avoid losing visibility into the impact of a
+ // suspended startup on the time until first frame / play ready for cases
+ // where suspended startup was applied incorrectly.
+ if (!attempting_suspended_start_)
+ load_start_time_ = base::TimeTicks::Now() - time_to_metadata_;
+ skip_metrics_due_to_startup_suspend_ = false;
+ }
+
+ // Enable video track if we disabled it in the background - this way the new
+ // renderer will attach its callbacks to the video stream properly.
+ // TODO(avayvod): Remove this when disabling and enabling video tracks in
+ // non-playing state works correctly. See https://crbug.com/678374.
+ EnableVideoTrackIfNeeded();
+ is_pipeline_resuming_ = true;
+}
+
+void WebMediaPlayerImpl::OnPipelineResumed() {
+ is_pipeline_resuming_ = false;
+
+ UpdateBackgroundVideoOptimizationState();
+}
+
+void WebMediaPlayerImpl::OnDemuxerOpened() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ client_->MediaSourceOpened(new WebMediaSourceImpl(chunk_demuxer_));
+}
+
+void WebMediaPlayerImpl::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+ DVLOG(2) << __func__ << " memory_pressure_level=" << memory_pressure_level;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(
+ base::FeatureList::IsEnabled(media::kMemoryPressureBasedSourceBufferGC));
+ DCHECK(chunk_demuxer_);
+
+ if (memory_pressure_level ==
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
+ return;
+ }
+
+ // The new value of `memory_pressure_level` will take effect on the next
+ // garbage collection. Typically this means the next SourceBuffer append()
+ // operation, since per MSE spec, the garbage collection must only occur
+ // during SourceBuffer append(). But if memory pressure is critical it might
+ // be better to perform GC immediately rather than wait for the next append
+ // and potentially get killed due to out-of-memory.
+ // So if this experiment is enabled and pressure level is critical, we'll pass
+ // down force_instant_gc==true, which will force immediate GC on
+ // SourceBufferStreams.
+ bool force_instant_gc =
+ (enable_instant_source_buffer_gc_ &&
+ memory_pressure_level ==
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
+
+ // base::Unretained is safe, since `chunk_demuxer_` is actually owned by
+ // `this` via this->demuxer_. Note the destruction of `chunk_demuxer_` is done
+ // from ~WMPI by first hopping to `media_task_runner_` to prevent race with
+ // this task.
+ media_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&media::ChunkDemuxer::OnMemoryPressure,
+ base::Unretained(chunk_demuxer_),
+ base::TimeDelta::FromSecondsD(CurrentTime()),
+ memory_pressure_level, force_instant_gc));
+}
+
+void WebMediaPlayerImpl::OnError(media::PipelineStatus status) {
+ DVLOG(1) << __func__ << ": status=" << status;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(status, media::PIPELINE_OK);
+
+ if (suppress_destruction_errors_)
+ return;
+
+#if defined(OS_ANDROID)
+ // `mb_data_source_` may be nullptr if someone passes in a m3u8 as a data://
+ // URL, since MediaPlayer doesn't support data:// URLs, fail playback now.
+ const bool found_hls =
+ base::FeatureList::IsEnabled(media::kHlsPlayer) &&
+ status == media::PipelineStatus::DEMUXER_ERROR_DETECTED_HLS;
+ if (found_hls && mb_data_source_) {
+ demuxer_found_hls_ = true;
+
+ if (observer_)
+ observer_->OnHlsManifestDetected();
+
+ UMA_HISTOGRAM_BOOLEAN("Media.WebMediaPlayerImpl.HLS.IsCorsCrossOrigin",
+ mb_data_source_->IsCorsCrossOrigin());
+ if (mb_data_source_->IsCorsCrossOrigin()) {
+ UMA_HISTOGRAM_BOOLEAN("Media.WebMediaPlayerImpl.HLS.HasAccessControl",
+ mb_data_source_->HasAccessControl());
+ }
+
+ // Note: Does not consider the full redirect chain, which could contain
+ // undetected mixed content.
+ bool frame_url_is_cryptographic = url::Origin(frame_->GetSecurityOrigin())
+ .GetURL()
+ .SchemeIsCryptographic();
+ bool manifest_url_is_cryptographic =
+ loaded_url_.SchemeIsCryptographic() &&
+ mb_data_source_->GetUrlAfterRedirects().SchemeIsCryptographic();
+ UMA_HISTOGRAM_BOOLEAN(
+ "Media.WebMediaPlayerImpl.HLS.IsMixedContent",
+ frame_url_is_cryptographic && !manifest_url_is_cryptographic);
+
+ renderer_factory_selector_->SetBaseRendererType(
+ media::RendererType::kMediaPlayer);
+
+ loaded_url_ = mb_data_source_->GetUrlAfterRedirects();
+ DCHECK(data_source_);
+ data_source_->Stop();
+ mb_data_source_ = nullptr;
+
+ pipeline_controller_->Stop();
+ SetMemoryReportingState(false);
+ media_task_runner_->DeleteSoon(FROM_HERE,
+ std::move(media_thread_mem_dumper_));
+
+ // Trampoline through the media task runner to destruct the demuxer and
+ // data source now that we're switching to HLS playback.
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ media::BindToCurrentLoop(base::BindOnce(
+ [](std::unique_ptr<Demuxer> demuxer,
+ std::unique_ptr<media::DataSource> data_source,
+ base::OnceClosure start_pipeline_cb) {
+ // Release resources before starting HLS.
+ demuxer.reset();
+ data_source.reset();
+
+ std::move(start_pipeline_cb).Run();
+ },
+ std::move(demuxer_), std::move(data_source_),
+ base::BindOnce(&WebMediaPlayerImpl::StartPipeline, weak_this_))));
+
+ return;
+ }
+
+ // We found hls in a data:// URL, fail immediately.
+ if (found_hls)
+ status = media::PIPELINE_ERROR_EXTERNAL_RENDERER_FAILED;
+#elif defined(OS_WIN)
+ // Hardware context reset is not an error. Restart to recover.
+ // TODO(crbug.com/1208618): Find a way to break the potential infinite loop of
+ // restart -> PIPELINE_ERROR_HARDWARE_CONTEXT_RESET -> restart.
+ if (status == media::PipelineStatus::PIPELINE_ERROR_HARDWARE_CONTEXT_RESET) {
+ ScheduleRestart();
+ return;
+ }
+#endif // defined(OS_ANDROID)
+
+ MaybeSetContainerNameForMetrics();
+ simple_watch_timer_.Stop();
+ media_log_->NotifyError(status);
+ media_metrics_provider_->OnError(status);
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnError(status);
+ if (watch_time_reporter_)
+ watch_time_reporter_->OnError(status);
+
+ if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing) {
+ // Any error that occurs before reaching ReadyStateHaveMetadata should
+ // be considered a format error.
+ SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
+ } else {
+ SetNetworkState(PipelineErrorToNetworkState(status));
+ }
+
+ // PipelineController::Stop() is idempotent.
+ pipeline_controller_->Stop();
+
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::OnEnded() {
+ TRACE_EVENT2("media", "WebMediaPlayerImpl::OnEnded", "duration", Duration(),
+ "id", media_log_->id());
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Ignore state changes until we've completed all outstanding operations.
+ if (!pipeline_controller_->IsStable())
+ return;
+
+ ended_ = true;
+ client_->TimeChanged();
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnEnded();
+
+ // We don't actually want this to run until `client_` calls seek() or pause(),
+ // but that should have already happened in timeChanged() and so this is
+ // expected to be a no-op.
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::OnMetadata(const media::PipelineMetadata& metadata) {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Cache the `time_to_metadata_` to use for adjusting the TimeToFirstFrame and
+ // TimeToPlayReady metrics later if we end up doing a suspended startup.
+ time_to_metadata_ = base::TimeTicks::Now() - load_start_time_;
+ media_metrics_provider_->SetTimeToMetadata(time_to_metadata_);
+ RecordTimingUMA("Media.TimeToMetadata", time_to_metadata_);
+
+ MaybeSetContainerNameForMetrics();
+
+ pipeline_metadata_ = metadata;
+ if (power_status_helper_)
+ power_status_helper_->SetMetadata(metadata);
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoRotation",
+ metadata.video_decoder_config.video_transformation().rotation,
+ media::VIDEO_ROTATION_MAX + 1);
+
+ if (HasAudio()) {
+ media_metrics_provider_->SetHasAudio(metadata.audio_decoder_config.codec());
+ RecordEncryptionScheme("Audio",
+ metadata.audio_decoder_config.encryption_scheme());
+ }
+
+ if (HasVideo()) {
+ media_metrics_provider_->SetHasVideo(metadata.video_decoder_config.codec());
+ RecordEncryptionScheme("Video",
+ metadata.video_decoder_config.encryption_scheme());
+
+ if (overlay_enabled_) {
+ // SurfaceView doesn't support rotated video, so transition back if
+ // the video is now rotated. If `always_enable_overlays_`, we keep the
+ // overlay anyway so that the state machine keeps working.
+ // TODO(liberato): verify if compositor feedback catches this. If so,
+ // then we don't need this check.
+ if (!always_enable_overlays_ && !DoesOverlaySupportMetadata())
+ DisableOverlay();
+ }
+
+ if (surface_layer_mode_ == WebMediaPlayer::SurfaceLayerMode::kAlways) {
+ ActivateSurfaceLayerForVideo();
+ } else {
+ DCHECK(!video_layer_);
+ video_layer_ = cc::VideoLayer::Create(
+ compositor_.get(),
+ pipeline_metadata_.video_decoder_config.video_transformation());
+ video_layer_->SetContentsOpaque(opaque_);
+ client_->SetCcLayer(video_layer_.get());
+ }
+ }
+
+ if (observer_)
+ observer_->OnMetadataChanged(pipeline_metadata_);
+
+ delegate_has_audio_ = HasUnmutedAudio();
+ media::MediaContentType content_type = GetMediaContentType();
+ client_->DidMediaMetadataChange(delegate_has_audio_, HasVideo(),
+ content_type);
+ delegate_->DidMediaMetadataChange(delegate_id_, delegate_has_audio_,
+ HasVideo(), content_type);
+
+ // It could happen that the demuxer successfully completed initialization
+ // (implying it had determined media metadata), but then removed all audio and
+ // video streams and the ability to demux any A/V before `metadata` was
+ // constructed and passed to us. One example is, with MSE-in-Workers, the
+ // worker owning the MediaSource could have been terminated, or the app could
+ // have explicitly removed all A/V SourceBuffers. That termination/removal
+ // could race the construction of `metadata`. Regardless of load-type, we
+ // shouldn't allow playback of a resource that has neither audio nor video.
+ // We treat lack of A/V as if there were an error in the demuxer before
+ // reaching HAVE_METADATA.
+ if (!HasVideo() && !HasAudio()) {
+ DVLOG(1) << __func__ << ": no audio and no video -> error";
+ OnError(media::PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
+ return; // Do not transition to HAVE_METADATA.
+ }
+
+ // TODO(dalecurtis): Don't create these until kReadyStateHaveFutureData; when
+ // we create them early we just increase the chances of needing to throw them
+ // away unnecessarily.
+ CreateWatchTimeReporter();
+ CreateVideoDecodeStatsReporter();
+
+ // SetReadyState() may trigger all sorts of calls into this class (e.g.,
+ // Play(), Pause(), etc) so do it last to avoid unexpected states during the
+ // calls. An exception to this is UpdatePlayState(), which is safe to call and
+ // needs to use the new ReadyState in its calculations.
+ SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::ActivateSurfaceLayerForVideo() {
+ // Note that we might or might not already be in VideoLayer mode.
+ DCHECK(!bridge_);
+
+ surface_layer_for_video_enabled_ = true;
+
+ // If we're in VideoLayer mode, then get rid of the layer.
+ if (video_layer_) {
+ client_->SetCcLayer(nullptr);
+ video_layer_ = nullptr;
+ }
+
+ bridge_ = std::move(create_bridge_callback_)
+ .Run(this, compositor_->GetUpdateSubmissionStateCallback());
+ bridge_->CreateSurfaceLayer();
+
+ // TODO(tmathmeyer) does this need support for the reflection transformation
+ // as well?
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &VideoFrameCompositor::EnableSubmission,
+ base::Unretained(compositor_.get()), bridge_->GetSurfaceId(),
+ pipeline_metadata_.video_decoder_config.video_transformation(),
+ IsInPictureInPicture()));
+ bridge_->SetContentsOpaque(opaque_);
+
+ // If the element is already in Picture-in-Picture mode, it means that it
+ // was set in this mode prior to this load, with a different
+ // WebMediaPlayerImpl. The new player needs to send its id, size and
+ // surface id to the browser process to make sure the states are properly
+ // updated.
+ // TODO(872056): the surface should be activated but for some reasons, it
+ // does not. It is possible that this will no longer be needed after 872056
+ // is fixed.
+ if (IsInPictureInPicture())
+ OnSurfaceIdUpdated(bridge_->GetSurfaceId());
+}
+
+void WebMediaPlayerImpl::OnBufferingStateChange(
+ media::BufferingState state,
+ media::BufferingStateChangeReason reason) {
+ OnBufferingStateChangeInternal(state, reason, false);
+}
+
+void WebMediaPlayerImpl::CreateVideoDecodeStatsReporter() {
+ // TODO(chcunningham): destroy reporter if we initially have video but the
+ // track gets disabled. Currently not possible in default desktop Chrome.
+ if (!HasVideo())
+ return;
+
+ // Only record stats from the local pipeline.
+ if (is_flinging_ || is_remote_rendering_ || using_media_player_renderer_)
+ return;
+
+ // Stats reporter requires a valid config. We may not have one for HLS cases
+ // where URL demuxer doesn't know details of the stream.
+ if (!pipeline_metadata_.video_decoder_config.IsValidConfig())
+ return;
+
+ // Profile must be known for use as index to save the reported stats.
+ if (pipeline_metadata_.video_decoder_config.profile() ==
+ media::VIDEO_CODEC_PROFILE_UNKNOWN) {
+ return;
+ }
+
+ // CdmConfig must be provided for use as index to save encrypted stats.
+ if (is_encrypted_ && !cdm_config_) {
+ return;
+ } else if (cdm_config_) {
+ DCHECK(!key_system_.empty());
+ }
+
+ mojo::PendingRemote<media::mojom::VideoDecodeStatsRecorder> recorder;
+ media_metrics_provider_->AcquireVideoDecodeStatsRecorder(
+ recorder.InitWithNewPipeAndPassReceiver());
+
+ // Create capabilities reporter and synchronize its initial state.
+ video_decode_stats_reporter_ = std::make_unique<VideoDecodeStatsReporter>(
+ std::move(recorder),
+ base::BindRepeating(&WebMediaPlayerImpl::GetPipelineStatistics,
+ base::Unretained(this)),
+ pipeline_metadata_.video_decoder_config.profile(),
+ pipeline_metadata_.natural_size, key_system_, cdm_config_,
+ frame_->GetTaskRunner(TaskType::kInternalMedia));
+
+ if (delegate_->IsFrameHidden())
+ video_decode_stats_reporter_->OnHidden();
+ else
+ video_decode_stats_reporter_->OnShown();
+
+ if (paused_)
+ video_decode_stats_reporter_->OnPaused();
+ else
+ video_decode_stats_reporter_->OnPlaying();
+}
+
+void WebMediaPlayerImpl::OnProgress() {
+ DVLOG(4) << __func__;
+
+ // See IsPrerollAttemptNeeded() for more details. We can't use that method
+ // here since it considers `preroll_attempt_start_time_` and for OnProgress()
+ // events we must make the attempt -- since there may not be another event.
+ if (highest_ready_state_ < ReadyState::kReadyStateHaveFutureData) {
+ // Reset the preroll attempt clock.
+ preroll_attempt_pending_ = true;
+ preroll_attempt_start_time_ = base::TimeTicks();
+
+ // Clear any 'stale' flag and give the pipeline a chance to resume. If we
+ // are already resumed, this will cause `preroll_attempt_start_time_` to
+ // be set.
+ delegate_->ClearStaleFlag(delegate_id_);
+ UpdatePlayState();
+ } else if (ready_state_ == ReadyState::kReadyStateHaveFutureData &&
+ CanPlayThrough()) {
+ SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
+ }
+}
+
+bool WebMediaPlayerImpl::CanPlayThrough() {
+ if (!base::FeatureList::IsEnabled(media::kSpecCompliantCanPlayThrough))
+ return true;
+ if (chunk_demuxer_)
+ return true;
+ if (data_source_ && data_source_->AssumeFullyBuffered())
+ return true;
+ // If we're not currently downloading, we have as much buffer as
+ // we're ever going to get, which means we say we can play through.
+ if (network_state_ == WebMediaPlayer::kNetworkStateIdle)
+ return true;
+ return buffered_data_source_host_->CanPlayThrough(
+ base::TimeDelta::FromSecondsD(CurrentTime()),
+ base::TimeDelta::FromSecondsD(Duration()),
+ playback_rate_ == 0.0 ? 1.0 : playback_rate_);
+}
+
+void WebMediaPlayerImpl::OnBufferingStateChangeInternal(
+ media::BufferingState state,
+ media::BufferingStateChangeReason reason,
+ bool for_suspended_start) {
+ DVLOG(1) << __func__ << "(" << state << ", " << reason << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Ignore buffering state changes caused by back-to-back seeking, so as not
+ // to assume the second seek has finished when it was only the first seek.
+ if (pipeline_controller_->IsPendingSeek())
+ return;
+
+ media_log_->AddEvent<MediaLogEvent::kBufferingStateChanged>(
+ media::SerializableBufferingState<
+ media::SerializableBufferingStateType::kPipeline>{
+ state, reason, for_suspended_start});
+
+ if (state == media::BUFFERING_HAVE_ENOUGH && !for_suspended_start)
+ media_metrics_provider_->SetHaveEnough();
+
+ if (state == media::BUFFERING_HAVE_ENOUGH) {
+ TRACE_EVENT1("media", "WebMediaPlayerImpl::BufferingHaveEnough", "id",
+ media_log_->id());
+ // The SetReadyState() call below may clear
+ // `skip_metrics_due_to_startup_suspend_` so report this first.
+ if (!have_reported_time_to_play_ready_ &&
+ !skip_metrics_due_to_startup_suspend_) {
+ DCHECK(!for_suspended_start);
+ have_reported_time_to_play_ready_ = true;
+ const base::TimeDelta elapsed = base::TimeTicks::Now() - load_start_time_;
+ media_metrics_provider_->SetTimeToPlayReady(elapsed);
+ RecordTimingUMA("Media.TimeToPlayReady", elapsed);
+ }
+
+ // Warning: This call may be re-entrant.
+ SetReadyState(CanPlayThrough() ? WebMediaPlayer::kReadyStateHaveEnoughData
+ : WebMediaPlayer::kReadyStateHaveFutureData);
+
+ // Let the DataSource know we have enough data -- this is the only function
+ // during which we advance to (or past) the kReadyStateHaveEnoughData state.
+ // It may use this information to update buffer sizes or release unused
+ // network connections.
+ MaybeUpdateBufferSizesForPlayback();
+ if (mb_data_source_ && !client_->CouldPlayIfEnoughData()) {
+ // For LazyLoad this will be handled during OnPipelineSuspended().
+ if (for_suspended_start && did_lazy_load_)
+ DCHECK(!have_enough_after_lazy_load_cb_.IsCancelled());
+ else
+ mb_data_source_->OnBufferingHaveEnough(false);
+ }
+
+ // Blink expects a timeChanged() in response to a seek().
+ if (should_notify_time_changed_) {
+ should_notify_time_changed_ = false;
+ client_->TimeChanged();
+ }
+
+ // Once we have enough, start reporting the total memory usage. We'll also
+ // report once playback starts.
+ ReportMemoryUsage();
+
+ // Report the amount of time it took to leave the underflow state.
+ if (underflow_timer_) {
+ auto elapsed = underflow_timer_->Elapsed();
+ RecordUnderflowDuration(elapsed);
+ watch_time_reporter_->OnUnderflowComplete(elapsed);
+ underflow_timer_.reset();
+ }
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnBufferingComplete();
+ } else {
+ // Buffering has underflowed.
+ DCHECK_EQ(state, media::BUFFERING_HAVE_NOTHING);
+
+ // Report the number of times we've entered the underflow state. Ensure we
+ // only report the value when transitioning from HAVE_ENOUGH to
+ // HAVE_NOTHING.
+ if (ready_state_ == WebMediaPlayer::kReadyStateHaveEnoughData &&
+ !seeking_) {
+ underflow_timer_ = std::make_unique<base::ElapsedTimer>();
+ watch_time_reporter_->OnUnderflow();
+ client_->DidBufferUnderflow();
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnBuffering();
+ }
+
+ // It shouldn't be possible to underflow if we've not advanced past
+ // HAVE_CURRENT_DATA.
+ DCHECK_GT(highest_ready_state_, WebMediaPlayer::kReadyStateHaveCurrentData);
+ SetReadyState(WebMediaPlayer::kReadyStateHaveCurrentData);
+ }
+
+ // If this is an NNR, then notify the smoothness helper about it. Note that
+ // it's unclear what we should do if there is no smoothness helper yet. As it
+ // is, we just discard the NNR.
+ if (state == media::BUFFERING_HAVE_NOTHING &&
+ reason == media::DECODER_UNDERFLOW && smoothness_helper_) {
+ smoothness_helper_->NotifyNNR();
+ }
+
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::OnDurationChange() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (frame_->IsAdSubframe()) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Ads.Media.Duration", GetPipelineMediaDuration(),
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromDays(1),
+ 50 /* bucket_count */);
+ }
+
+ if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
+ return;
+
+ client_->DurationChanged();
+ media::MediaContentType content_type = GetMediaContentType();
+ client_->DidMediaMetadataChange(delegate_has_audio_, HasVideo(),
+ content_type);
+ delegate_->DidMediaMetadataChange(delegate_id_, delegate_has_audio_,
+ HasVideo(), content_type);
+
+ if (watch_time_reporter_)
+ watch_time_reporter_->OnDurationChanged(GetPipelineMediaDuration());
+}
+
+void WebMediaPlayerImpl::OnAddTextTrack(const media::TextTrackConfig& config,
+ media::AddTextTrackDoneCB done_cb) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ const WebInbandTextTrackImpl::Kind web_kind =
+ static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
+ const WebString web_label = WebString::FromUTF8(config.label());
+ const WebString web_language = WebString::FromUTF8(config.language());
+ const WebString web_id = WebString::FromUTF8(config.id());
+
+ std::unique_ptr<WebInbandTextTrackImpl> web_inband_text_track(
+ new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
+
+ std::unique_ptr<media::TextTrack> text_track(new TextTrackImpl(
+ main_task_runner_, client_, std::move(web_inband_text_track)));
+
+ std::move(done_cb).Run(std::move(text_track));
+}
+
+void WebMediaPlayerImpl::OnWaiting(media::WaitingReason reason) {
+ DVLOG(2) << __func__ << ": reason=" << static_cast<int>(reason);
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ switch (reason) {
+ case media::WaitingReason::kNoCdm:
+ case media::WaitingReason::kNoDecryptionKey:
+ encrypted_client_->DidBlockPlaybackWaitingForKey();
+ // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
+ // when a key has been successfully added (e.g. OnSessionKeysChange() with
+ // `has_additional_usable_key` = true). http://crbug.com/461903
+ encrypted_client_->DidResumePlaybackBlockedForKey();
+ return;
+
+ // Ideally this should be handled by PipelineController directly without
+ // being proxied here. But currently Pipeline::Client (`this`) is passed to
+ // PipelineImpl directly without going through `pipeline_controller_`,
+ // making it difficult to do.
+ // TODO(xhwang): Handle this in PipelineController when we have a clearer
+ // picture on how to refactor WebMediaPlayerImpl, PipelineController and
+ // PipelineImpl.
+ case media::WaitingReason::kDecoderStateLost:
+ pipeline_controller_->OnDecoderStateLost();
+ return;
+ }
+}
+
+void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
+
+ TRACE_EVENT0("media", "WebMediaPlayerImpl::OnVideoNaturalSizeChange");
+
+ // The input `size` is from the decoded video frame, which is the original
+ // natural size and need to be rotated accordingly.
+ gfx::Size rotated_size = GetRotatedVideoSize(
+ pipeline_metadata_.video_decoder_config.video_transformation().rotation,
+ size);
+
+ RecordVideoNaturalSize(rotated_size);
+
+ gfx::Size old_size = pipeline_metadata_.natural_size;
+ if (rotated_size == old_size)
+ return;
+
+ pipeline_metadata_.natural_size = rotated_size;
+
+ if (using_media_player_renderer_ && old_size.IsEmpty()) {
+ // If we are using MediaPlayerRenderer and this is the first size change, we
+ // now know that there is a video track. This condition is paired with code
+ // in CreateWatchTimeReporter() that guesses the existence of a video track.
+ CreateWatchTimeReporter();
+ } else {
+ UpdateSecondaryProperties();
+ }
+
+ if (video_decode_stats_reporter_ &&
+ !video_decode_stats_reporter_->MatchesBucketedNaturalSize(
+ pipeline_metadata_.natural_size)) {
+ CreateVideoDecodeStatsReporter();
+ }
+
+ // Create or replace the smoothness helper now that we have a size.
+ UpdateSmoothnessHelper();
+
+ client_->SizeChanged();
+
+ if (observer_)
+ observer_->OnMetadataChanged(pipeline_metadata_);
+
+ client_->DidPlayerSizeChange(NaturalSize());
+}
+
+void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
+
+ opaque_ = opaque;
+ if (!surface_layer_for_video_enabled_ && video_layer_)
+ video_layer_->SetContentsOpaque(opaque_);
+ else if (bridge_->GetCcLayer())
+ bridge_->SetContentsOpaque(opaque_);
+}
+
+void WebMediaPlayerImpl::OnVideoFrameRateChange(absl::optional<int> fps) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (power_status_helper_)
+ power_status_helper_->SetAverageFrameRate(fps);
+
+ last_reported_fps_ = fps;
+ UpdateSmoothnessHelper();
+}
+
+void WebMediaPlayerImpl::OnAudioConfigChange(
+ const media::AudioDecoderConfig& config) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
+
+ const bool codec_change =
+ pipeline_metadata_.audio_decoder_config.codec() != config.codec();
+ const bool codec_profile_change =
+ pipeline_metadata_.audio_decoder_config.profile() != config.profile();
+
+ pipeline_metadata_.audio_decoder_config = config;
+
+ if (observer_)
+ observer_->OnMetadataChanged(pipeline_metadata_);
+
+ if (codec_change) {
+ media_metrics_provider_->SetHasAudio(
+ pipeline_metadata_.audio_decoder_config.codec());
+ }
+
+ if (codec_change || codec_profile_change)
+ UpdateSecondaryProperties();
+}
+
+void WebMediaPlayerImpl::OnVideoConfigChange(
+ const media::VideoDecoderConfig& config) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
+
+ const bool codec_change =
+ pipeline_metadata_.video_decoder_config.codec() != config.codec();
+ const bool codec_profile_change =
+ pipeline_metadata_.video_decoder_config.profile() != config.profile();
+
+ pipeline_metadata_.video_decoder_config = config;
+
+ if (observer_)
+ observer_->OnMetadataChanged(pipeline_metadata_);
+
+ if (codec_change) {
+ media_metrics_provider_->SetHasVideo(
+ pipeline_metadata_.video_decoder_config.codec());
+ }
+
+ if (codec_change || codec_profile_change)
+ UpdateSecondaryProperties();
+
+ if (video_decode_stats_reporter_ && codec_profile_change)
+ CreateVideoDecodeStatsReporter();
+}
+
+void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() {
+ UpdateBackgroundVideoOptimizationState();
+}
+
+void WebMediaPlayerImpl::OnAudioPipelineInfoChange(
+ const media::AudioPipelineInfo& info) {
+ media_metrics_provider_->SetAudioPipelineInfo(info);
+ if (info.decoder_type == audio_decoder_type_)
+ return;
+
+ audio_decoder_type_ = info.decoder_type;
+
+ // If there's no current reporter, there's nothing to be done.
+ if (!watch_time_reporter_)
+ return;
+
+ UpdateSecondaryProperties();
+}
+
+void WebMediaPlayerImpl::OnVideoPipelineInfoChange(
+ const media::VideoPipelineInfo& info) {
+ media_metrics_provider_->SetVideoPipelineInfo(info);
+ if (info.decoder_type == video_decoder_type_)
+ return;
+
+ video_decoder_type_ = info.decoder_type;
+
+ // If there's no current reporter, there's nothing to be done.
+ if (!watch_time_reporter_)
+ return;
+
+ UpdateSecondaryProperties();
+}
+
+void WebMediaPlayerImpl::OnFrameHidden() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Backgrounding a video requires a user gesture to resume playback.
+ if (IsHidden())
+ video_locked_when_paused_when_hidden_ = true;
+
+ if (watch_time_reporter_)
+ watch_time_reporter_->OnHidden();
+
+ if (video_decode_stats_reporter_)
+ video_decode_stats_reporter_->OnHidden();
+
+ UpdateBackgroundVideoOptimizationState();
+ UpdatePlayState();
+
+ // Schedule suspended playing media to be paused if the user doesn't come back
+ // to it within some timeout period to avoid any autoplay surprises.
+ ScheduleIdlePauseTimer();
+
+ // Notify the compositor of our page visibility status.
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoFrameCompositor::SetIsPageVisible,
+ base::Unretained(compositor_.get()), !IsHidden()));
+}
+
+void WebMediaPlayerImpl::SuspendForFrameClosed() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ was_suspended_for_frame_closed_ = true;
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::OnFrameShown() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ background_pause_timer_.Stop();
+
+ // Foreground videos don't require user gesture to continue playback.
+ video_locked_when_paused_when_hidden_ = false;
+
+ was_suspended_for_frame_closed_ = false;
+
+ if (watch_time_reporter_)
+ watch_time_reporter_->OnShown();
+
+ if (video_decode_stats_reporter_)
+ video_decode_stats_reporter_->OnShown();
+
+ // Notify the compositor of our page visibility status.
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoFrameCompositor::SetIsPageVisible,
+ base::Unretained(compositor_.get()), !IsHidden()));
+
+ UpdateBackgroundVideoOptimizationState();
+
+ if (paused_when_hidden_) {
+ paused_when_hidden_ = false;
+ client_->ResumePlayback(); // Calls UpdatePlayState() so return afterwards.
+ return;
+ }
+
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::OnIdleTimeout() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // This should never be called when stale state testing overrides are used.
+ DCHECK(!stale_state_override_for_testing_.has_value());
+
+ // If we are attempting preroll, clear the stale flag.
+ if (IsPrerollAttemptNeeded()) {
+ delegate_->ClearStaleFlag(delegate_id_);
+ return;
+ }
+
+ UpdatePlayState();
+}
+
+void WebMediaPlayerImpl::SetVolumeMultiplier(double multiplier) {
+ volume_multiplier_ = multiplier;
+ SetVolume(volume_);
+}
+
+void WebMediaPlayerImpl::SetPersistentState(bool value) {
+ overlay_info_.is_persistent_video = value;
+ MaybeSendOverlayInfoToDecoder();
+}
+
+void WebMediaPlayerImpl::SetPowerExperimentState(bool state) {
+ if (power_status_helper_)
+ power_status_helper_->UpdatePowerExperimentState(state);
+}
+
+void WebMediaPlayerImpl::ScheduleRestart() {
+ // TODO(watk): All restart logic should be moved into PipelineController.
+ if (pipeline_controller_->IsPipelineRunning() &&
+ !pipeline_controller_->IsPipelineSuspended()) {
+ pending_suspend_resume_cycle_ = true;
+ UpdatePlayState();
+ }
+}
+
+void WebMediaPlayerImpl::RequestRemotePlaybackDisabled(bool disabled) {
+ if (observer_)
+ observer_->OnRemotePlaybackDisabled(disabled);
+}
+
+#if defined(OS_ANDROID)
+void WebMediaPlayerImpl::FlingingStarted() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(!disable_pipeline_auto_suspend_);
+ disable_pipeline_auto_suspend_ = true;
+
+ is_flinging_ = true;
+
+ // Capabilities reporting should only be performed for local playbacks.
+ video_decode_stats_reporter_.reset();
+
+ // Requests to restart media pipeline. A flinging renderer will be created via
+ // the `renderer_factory_selector_`.
+ ScheduleRestart();
+}
+
+void WebMediaPlayerImpl::FlingingStopped() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(disable_pipeline_auto_suspend_);
+ disable_pipeline_auto_suspend_ = false;
+
+ is_flinging_ = false;
+
+ CreateVideoDecodeStatsReporter();
+
+ ScheduleRestart();
+}
+
+void WebMediaPlayerImpl::OnRemotePlayStateChange(
+ media::MediaStatus::State state) {
+ DCHECK(is_flinging_);
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (state == media::MediaStatus::State::PLAYING && Paused()) {
+ DVLOG(1) << __func__ << " requesting PLAY.";
+ client_->ResumePlayback();
+ } else if (state == media::MediaStatus::State::PAUSED && !Paused()) {
+ DVLOG(1) << __func__ << " requesting PAUSE.";
+ client_->PausePlayback();
+ }
+}
+#endif // defined(OS_ANDROID)
+
+void WebMediaPlayerImpl::SetPoster(const WebURL& poster) {
+ has_poster_ = !poster.IsEmpty();
+}
+
+void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (observer_ && mb_data_source_)
+ observer_->OnDataSourceInitialized(mb_data_source_->GetUrlAfterRedirects());
+
+ if (!success) {
+ SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
+ media_metrics_provider_->OnError(media::PIPELINE_ERROR_NETWORK);
+
+ // Not really necessary, since the pipeline was never started, but it at
+ // least this makes sure that the error handling code is in sync.
+ UpdatePlayState();
+
+ return;
+ }
+
+ // No point in preloading data as we'll probably just throw it away anyways.
+ if (IsStreaming() && preload_ > MultiBufferDataSource::METADATA &&
+ mb_data_source_) {
+ mb_data_source_->SetPreload(MultiBufferDataSource::METADATA);
+ }
+
+ StartPipeline();
+}
+
+void WebMediaPlayerImpl::OnDataSourceRedirected() {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(mb_data_source_);
+
+ if (WouldTaintOrigin()) {
+ audio_source_provider_->TaintOrigin();
+ }
+}
+
+void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
+ DVLOG(1) << __func__ << "(" << is_downloading << ")";
+ if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
+ SetNetworkState(WebMediaPlayer::kNetworkStateIdle);
+ else if (is_downloading &&
+ network_state_ == WebMediaPlayer::kNetworkStateIdle)
+ SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
+ if (ready_state_ == ReadyState::kReadyStateHaveFutureData && !is_downloading)
+ SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
+}
+
+void WebMediaPlayerImpl::OnOverlayRoutingToken(
+ const base::UnguessableToken& token) {
+ DCHECK(overlay_mode_ == OverlayMode::kUseAndroidOverlay);
+ // TODO(liberato): `token` should already be a RoutingToken.
+ overlay_routing_token_is_pending_ = false;
+ overlay_routing_token_ = media::OverlayInfo::RoutingToken(token);
+ MaybeSendOverlayInfoToDecoder();
+}
+
+void WebMediaPlayerImpl::OnOverlayInfoRequested(
+ bool decoder_requires_restart_for_overlay,
+ media::ProvideOverlayInfoCB provide_overlay_info_cb) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // If we get a non-null cb, a decoder is initializing and requires overlay
+ // info. If we get a null cb, a previously initialized decoder is
+ // unregistering for overlay info updates.
+ if (!provide_overlay_info_cb) {
+ decoder_requires_restart_for_overlay_ = false;
+ provide_overlay_info_cb_.Reset();
+ return;
+ }
+
+ // If `decoder_requires_restart_for_overlay` is true, we must restart the
+ // pipeline for fullscreen transitions. The decoder is unable to switch
+ // surfaces otherwise. If false, we simply need to tell the decoder about the
+ // new surface and it will handle things seamlessly.
+ // For encrypted video we pretend that the decoder doesn't require a restart
+ // because it needs an overlay all the time anyway. We'll switch into
+ // `always_enable_overlays_` mode below.
+ decoder_requires_restart_for_overlay_ =
+ (overlay_mode_ == OverlayMode::kUseAndroidOverlay && is_encrypted_)
+ ? false
+ : decoder_requires_restart_for_overlay;
+ provide_overlay_info_cb_ = std::move(provide_overlay_info_cb);
+
+ // If the decoder doesn't require restarts for surface transitions, and we're
+ // using AndroidOverlay mode, we can always enable the overlay and the decoder
+ // can choose whether or not to use it. Otherwise, we'll restart the decoder
+ // and enable the overlay on fullscreen transitions.
+ if (overlay_mode_ == OverlayMode::kUseAndroidOverlay &&
+ !decoder_requires_restart_for_overlay_) {
+ always_enable_overlays_ = true;
+ if (!overlay_enabled_)
+ EnableOverlay();
+ }
+
+ // Send the overlay info if we already have it. If not, it will be sent later.
+ MaybeSendOverlayInfoToDecoder();
+}
+
+void WebMediaPlayerImpl::MaybeSendOverlayInfoToDecoder() {
+ // If the decoder didn't request overlay info, then don't send it.
+ if (!provide_overlay_info_cb_)
+ return;
+
+ // We should send the overlay info as long as we know it. This includes the
+ // case where `!overlay_enabled_`, since we want to tell the decoder to avoid
+ // using overlays. Assuming that the decoder has requested info, the only
+ // case in which we don't want to send something is if we've requested the
+ // info but not received it yet. Then, we should wait until we do.
+ //
+ // Initialization requires this; AVDA should start with enough info to make an
+ // overlay, so that (pre-M) the initial codec is created with the right output
+ // surface; it can't switch later.
+ if (overlay_mode_ == OverlayMode::kUseAndroidOverlay) {
+ if (overlay_routing_token_is_pending_)
+ return;
+
+ overlay_info_.routing_token = overlay_routing_token_;
+ }
+
+ // If restart is required, the callback is one-shot only.
+ if (decoder_requires_restart_for_overlay_) {
+ std::move(provide_overlay_info_cb_).Run(overlay_info_);
+ } else {
+ provide_overlay_info_cb_.Run(overlay_info_);
+ }
+}
+
+std::unique_ptr<media::Renderer> WebMediaPlayerImpl::CreateRenderer(
+ absl::optional<media::RendererType> renderer_type) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Make sure that overlays are enabled if they're always allowed.
+ if (always_enable_overlays_)
+ EnableOverlay();
+
+ media::RequestOverlayInfoCB request_overlay_info_cb;
+#if defined(OS_ANDROID)
+ request_overlay_info_cb = media::BindToCurrentLoop(base::BindRepeating(
+ &WebMediaPlayerImpl::OnOverlayInfoRequested, weak_this_));
+#endif
+
+ if (renderer_type) {
+ DVLOG(1) << __func__
+ << ": renderer_type=" << static_cast<int>(renderer_type.value());
+ renderer_factory_selector_->SetBaseRendererType(renderer_type.value());
+ }
+
+ bool old_uses_audio_service = UsesAudioService(renderer_type_);
+ renderer_type_ = renderer_factory_selector_->GetCurrentRendererType();
+
+ bool new_uses_audio_service = UsesAudioService(renderer_type_);
+ if (new_uses_audio_service != old_uses_audio_service)
+ client_->DidUseAudioServiceChange(new_uses_audio_service);
+
+ media_metrics_provider_->SetRendererType(renderer_type_);
+ media_log_->SetProperty<MediaLogProperty::kRendererName>(renderer_type_);
+
+ return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer(
+ media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
+ compositor_.get(), std::move(request_overlay_info_cb),
+ client_->TargetColorSpace());
+}
+
+void WebMediaPlayerImpl::StartPipeline() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
+ media::BindToCurrentLoop(base::BindRepeating(
+ &WebMediaPlayerImpl::OnEncryptedMediaInitData, weak_this_));
+
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoFrameCompositor::SetOnNewProcessedFrameCallback,
+ base::Unretained(compositor_.get()),
+ media::BindToCurrentLoop(base::BindOnce(
+ &WebMediaPlayerImpl::OnFirstFrame, weak_this_))));
+
+#if defined(OS_ANDROID)
+ if (demuxer_found_hls_ || renderer_factory_selector_->GetCurrentFactory()
+ ->GetRequiredMediaResourceType() ==
+ media::MediaResource::Type::URL) {
+ // MediaPlayerRendererClientFactory is the only factory that a uses
+ // MediaResource::Type::URL for the moment.
+ using_media_player_renderer_ = true;
+
+ // MediaPlayerRenderer does not provide pipeline stats, so nuke capabilities
+ // reporter.
+ video_decode_stats_reporter_.reset();
+
+ SetDemuxer(std::make_unique<media::MediaUrlDemuxer>(
+ media_task_runner_, loaded_url_, frame_->GetDocument().SiteForCookies(),
+ frame_->GetDocument().TopFrameOrigin(),
+ allow_media_player_renderer_credentials_, demuxer_found_hls_));
+ pipeline_controller_->Start(media::Pipeline::StartType::kNormal,
+ demuxer_.get(), this, false, false);
+ return;
+ }
+#endif // defined(OS_ANDROID)
+
+ // Figure out which demuxer to use.
+ if (demuxer_override_) {
+ DCHECK(!chunk_demuxer_);
+
+ SetDemuxer(std::move(demuxer_override_));
+ // TODO(https://crbug.com/1076267): Should everything else after this block
+ // run in the demuxer override case?
+ } else if (load_type_ != kLoadTypeMediaSource) {
+ DCHECK(!chunk_demuxer_);
+ DCHECK(data_source_);
+
+#if BUILDFLAG(ENABLE_FFMPEG)
+ Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
+ media::BindToCurrentLoop(base::BindRepeating(
+ &WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated, weak_this_));
+
+ SetDemuxer(std::make_unique<media::FFmpegDemuxer>(
+ media_task_runner_, data_source_.get(), encrypted_media_init_data_cb,
+ media_tracks_updated_cb, media_log_.get(), IsLocalFile(loaded_url_)));
+#else
+ OnError(media::PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
+ return;
+#endif
+ } else {
+ DCHECK(!chunk_demuxer_);
+ DCHECK(!data_source_);
+
+ chunk_demuxer_ = new media::ChunkDemuxer(
+ media::BindToCurrentLoop(
+ base::BindOnce(&WebMediaPlayerImpl::OnDemuxerOpened, weak_this_)),
+ media::BindToCurrentLoop(
+ base::BindRepeating(&WebMediaPlayerImpl::OnProgress, weak_this_)),
+ encrypted_media_init_data_cb, media_log_.get());
+ SetDemuxer(std::unique_ptr<Demuxer>(chunk_demuxer_));
+
+ if (base::FeatureList::IsEnabled(
+ media::kMemoryPressureBasedSourceBufferGC)) {
+ // base::Unretained is safe because `this` owns memory_pressure_listener_.
+ memory_pressure_listener_ =
+ std::make_unique<base::MemoryPressureListener>(
+ FROM_HERE,
+ base::BindRepeating(&WebMediaPlayerImpl::OnMemoryPressure,
+ base::Unretained(this)));
+ }
+ }
+
+ // If possible attempt to avoid decoder spool up until playback starts.
+ auto start_type = media::Pipeline::StartType::kNormal;
+ if (!chunk_demuxer_ && preload_ == MultiBufferDataSource::METADATA &&
+ !client_->CouldPlayIfEnoughData() && !IsStreaming()) {
+ start_type =
+ (has_poster_ ||
+ base::FeatureList::IsEnabled(media::kPreloadMetadataLazyLoad))
+ ? media::Pipeline::StartType::kSuspendAfterMetadata
+ : media::Pipeline::StartType::kSuspendAfterMetadataForAudioOnly;
+ attempting_suspended_start_ = true;
+ }
+
+ // TODO(sandersd): FileSystem objects may also be non-static, but due to our
+ // caching layer such situations are broken already. http://crbug.com/593159
+ const bool is_static = !chunk_demuxer_;
+
+ // ... and we're ready to go!
+ // TODO(sandersd): On Android, defer Start() if the tab is not visible.
+ seeking_ = true;
+ pipeline_controller_->Start(start_type, demuxer_.get(), this, IsStreaming(),
+ is_static);
+}
+
+void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
+ DVLOG(1) << __func__ << "(" << state << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ network_state_ = state;
+ // Always notify to ensure client has the latest value.
+ client_->NetworkStateChanged();
+}
+
+void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
+ DVLOG(1) << __func__ << "(" << state << ")";
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ if (state == WebMediaPlayer::kReadyStateHaveEnoughData && data_source_ &&
+ data_source_->AssumeFullyBuffered() &&
+ network_state_ == WebMediaPlayer::kNetworkStateLoading) {
+ SetNetworkState(WebMediaPlayer::kNetworkStateLoaded);
+ }
+
+ ready_state_ = state;
+ highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
+
+ // Always notify to ensure client has the latest value.
+ client_->ReadyStateChanged();
+}
+
+scoped_refptr<WebAudioSourceProviderImpl>
+WebMediaPlayerImpl::GetAudioSourceProvider() {
+ return audio_source_provider_;
+}
+
+scoped_refptr<media::VideoFrame>
+WebMediaPlayerImpl::GetCurrentFrameFromCompositor() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
+
+ // We can't copy from protected frames.
+ if (cdm_context_ref_)
+ return nullptr;
+
+ // Can be null.
+ scoped_refptr<media::VideoFrame> video_frame =
+ compositor_->GetCurrentFrameOnAnyThread();
+
+ // base::Unretained is safe here because `compositor_` is destroyed on
+ // `vfc_task_runner_`. The destruction is queued from `this`' destructor,
+ // which also runs on `main_task_runner_`, which makes it impossible for
+ // UpdateCurrentFrameIfStale() to be queued after `compositor_`'s dtor.
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoFrameCompositor::UpdateCurrentFrameIfStale,
+ base::Unretained(compositor_.get()),
+ VideoFrameCompositor::UpdateType::kNormal));
+
+ return video_frame;
+}
+
+void WebMediaPlayerImpl::UpdatePlayState() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ bool can_auto_suspend = !disable_pipeline_auto_suspend_;
+ // For streaming videos, we only allow suspending at the very beginning of the
+ // video, and only if we know the length of the video. (If we don't know
+ // the length, it might be a dynamically generated video, and suspending
+ // will not work at all.)
+ if (IsStreaming()) {
+ bool at_beginning =
+ ready_state_ == WebMediaPlayer::kReadyStateHaveNothing ||
+ CurrentTime() == 0.0;
+ if (!at_beginning || GetPipelineMediaDuration() == media::kInfiniteDuration)
+ can_auto_suspend = false;
+ }
+
+ bool is_suspended = pipeline_controller_->IsSuspended();
+ bool is_backgrounded = IsBackgroundSuspendEnabled(this) && IsHidden();
+ PlayState state = UpdatePlayState_ComputePlayState(
+ is_flinging_, can_auto_suspend, is_suspended, is_backgrounded);
+ SetDelegateState(state.delegate_state, state.is_idle);
+ SetMemoryReportingState(state.is_memory_reporting_enabled);
+ SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
+ if (power_status_helper_) {
+ // Make sure that we're in something like steady-state before recording.
+ power_status_helper_->SetIsPlaying(
+ !paused_ && !seeking_ && !IsHidden() && !state.is_suspended &&
+ ready_state_ == kReadyStateHaveEnoughData);
+ }
+ UpdateSmoothnessHelper();
+}
+
+void WebMediaPlayerImpl::OnTimeUpdate() {
+ // When seeking the current time can go beyond the duration so we should
+ // cap the current time at the duration.
+ base::TimeDelta duration = GetPipelineMediaDuration();
+ base::TimeDelta current_time = GetCurrentTimeInternal();
+ if (current_time > duration)
+ current_time = duration;
+
+ const double effective_playback_rate =
+ paused_ || ready_state_ < kReadyStateHaveFutureData ? 0.0
+ : playback_rate_;
+
+ media_session::MediaPosition new_position(effective_playback_rate, duration,
+ current_time, ended_);
+
+ if (!MediaPositionNeedsUpdate(media_position_state_, new_position))
+ return;
+
+ DVLOG(2) << __func__ << "(" << new_position.ToString() << ")";
+ media_position_state_ = new_position;
+ client_->DidPlayerMediaPositionStateChange(effective_playback_rate, duration,
+ current_time, ended_);
+}
+
+void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
+ bool is_idle) {
+ DCHECK(delegate_);
+ DVLOG(2) << __func__ << "(" << static_cast<int>(new_state) << ", " << is_idle
+ << ")";
+
+ // Prevent duplicate delegate calls.
+ // TODO(sandersd): Move this deduplication into the delegate itself.
+ if (delegate_state_ == new_state)
+ return;
+ delegate_state_ = new_state;
+
+ switch (new_state) {
+ case DelegateState::GONE:
+ delegate_->PlayerGone(delegate_id_);
+ break;
+ case DelegateState::PLAYING: {
+ // When delegate get PlayerGone it removes all state, need to make sure
+ // it is up-to-date before calling DidPlay.
+ delegate_->DidMediaMetadataChange(delegate_id_, delegate_has_audio_,
+ HasVideo(), GetMediaContentType());
+ if (HasVideo())
+ client_->DidPlayerSizeChange(NaturalSize());
+ client_->DidPlayerStartPlaying();
+ delegate_->DidPlay(delegate_id_);
+ break;
+ }
+ case DelegateState::PAUSED:
+ client_->DidPlayerPaused(ended_);
+ delegate_->DidPause(delegate_id_, ended_);
+ break;
+ }
+
+ delegate_->SetIdle(delegate_id_, is_idle);
+}
+
+void WebMediaPlayerImpl::SetMemoryReportingState(
+ bool is_memory_reporting_enabled) {
+ if (memory_usage_reporting_timer_.IsRunning() ==
+ is_memory_reporting_enabled) {
+ return;
+ }
+
+ if (is_memory_reporting_enabled) {
+ memory_usage_reporting_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(2), this,
+ &WebMediaPlayerImpl::ReportMemoryUsage);
+ } else {
+ memory_usage_reporting_timer_.Stop();
+ ReportMemoryUsage();
+ }
+}
+
+void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DVLOG(2) << __func__ << "(" << is_suspended << ")";
+
+ // Do not change the state after an error has occurred.
+ // TODO(sandersd): Update PipelineController to remove the need for this.
+ if (IsNetworkStateError(network_state_))
+ return;
+
+ if (is_suspended) {
+ // If we were not resumed for long enough to satisfy the preroll attempt,
+ // reset the clock.
+ if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
+ preroll_attempt_pending_ = true;
+ preroll_attempt_start_time_ = base::TimeTicks();
+ }
+ pipeline_controller_->Suspend();
+ } else {
+ // When resuming, start the preroll attempt clock.
+ if (preroll_attempt_pending_) {
+ preroll_attempt_pending_ = false;
+ preroll_attempt_start_time_ = tick_clock_->NowTicks();
+ }
+ pipeline_controller_->Resume();
+ }
+}
+
+WebMediaPlayerImpl::PlayState
+WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_flinging,
+ bool can_auto_suspend,
+ bool is_suspended,
+ bool is_backgrounded) {
+ PlayState result;
+
+ bool must_suspend = was_suspended_for_frame_closed_;
+ bool is_stale = delegate_->IsStale(delegate_id_);
+
+ if (stale_state_override_for_testing_.has_value() &&
+ ready_state_ >= stale_state_override_for_testing_.value()) {
+ is_stale = true;
+ }
+
+ // This includes both data source (before pipeline startup) and pipeline
+ // errors.
+ bool has_error = IsNetworkStateError(network_state_);
+
+ // Note: Even though we get play/pause signals at kReadyStateHaveMetadata, we
+ // must attempt to preroll until kReadyStateHaveFutureData so that the
+ // canplaythrough event will be fired to the page (which may be waiting).
+ bool have_future_data =
+ highest_ready_state_ >= WebMediaPlayer::kReadyStateHaveFutureData;
+
+ // Background suspend is only enabled for paused players.
+ // In the case of players with audio the session should be kept.
+ bool background_suspended =
+ can_auto_suspend && is_backgrounded && paused_ && have_future_data;
+
+ // Idle suspension is allowed prior to kReadyStateHaveMetadata since there
+ // exist mechanisms to exit the idle state when the player is capable of
+ // reaching the kReadyStateHaveMetadata state; see didLoadingProgress().
+ //
+ // TODO(sandersd): Make the delegate suspend idle players immediately when
+ // hidden.
+ bool idle_suspended = can_auto_suspend && is_stale && paused_ && !seeking_ &&
+ !overlay_info_.is_fullscreen && !needs_first_frame_;
+
+ // If we're already suspended, see if we can wait for user interaction. Prior
+ // to kReadyStateHaveMetadata, we require `is_stale` to remain suspended.
+ // `is_stale` will be cleared when we receive data which may take us to
+ // kReadyStateHaveMetadata.
+ bool can_stay_suspended = (is_stale || have_future_data) && is_suspended &&
+ paused_ && !seeking_ && !needs_first_frame_;
+
+ // Combined suspend state.
+ result.is_suspended = must_suspend || idle_suspended ||
+ background_suspended || can_stay_suspended;
+
+ DVLOG(3) << __func__ << ": must_suspend=" << must_suspend
+ << ", idle_suspended=" << idle_suspended
+ << ", background_suspended=" << background_suspended
+ << ", can_stay_suspended=" << can_stay_suspended
+ << ", is_stale=" << is_stale
+ << ", have_future_data=" << have_future_data
+ << ", paused_=" << paused_ << ", seeking_=" << seeking_;
+
+ // We do not treat `playback_rate_` == 0 as paused. For the media session,
+ // being paused implies displaying a play button, which is incorrect in this
+ // case. For memory usage reporting, we just use the same definition (but we
+ // don't have to).
+ //
+ // Similarly, we don't consider `ended_` to be paused. Blink will immediately
+ // call pause() or seek(), so `ended_` should not affect the computation.
+ // Despite that, `ended_` does result in a separate paused state, to simplfy
+ // the contract for SetDelegateState().
+ //
+ // `has_remote_controls` indicates if the player can be controlled outside the
+ // page (e.g. via the notification controls or by audio focus events). Idle
+ // suspension does not destroy the media session, because we expect that the
+ // notification controls (and audio focus) remain. With some exceptions for
+ // background videos, the player only needs to have audio to have controls
+ // (requires `have_current_data`).
+ //
+ // `alive` indicates if the player should be present (not `GONE`) to the
+ // delegate, either paused or playing. The following must be true for the
+ // player:
+ // - `have_current_data`, since playback can't begin before that point, we
+ // need to know whether we are paused to correctly configure the session,
+ // and also because the tracks and duration are passed to DidPlay(),
+ // - `is_flinging` is false (RemotePlayback is not handled by the delegate)
+ // - `has_error` is false as player should have no errors,
+ // - `background_suspended` is false, otherwise `has_remote_controls` must
+ // be true.
+ //
+ // TODO(sandersd): If Blink told us the paused state sooner, we could detect
+ // if the remote controls are available sooner.
+
+ // Background videos with audio don't have remote controls if background
+ // suspend is enabled and resuming background videos is not (original Android
+ // behavior).
+ bool backgrounded_video_has_no_remote_controls =
+ IsBackgroundSuspendEnabled(this) && !IsResumeBackgroundVideosEnabled() &&
+ is_backgrounded && HasVideo();
+ bool have_current_data = highest_ready_state_ >= kReadyStateHaveCurrentData;
+ bool can_play = !has_error && have_current_data;
+ bool has_remote_controls =
+ HasAudio() && !backgrounded_video_has_no_remote_controls;
+ bool alive = can_play && !is_flinging && !must_suspend &&
+ (!background_suspended || has_remote_controls);
+ if (!alive) {
+ // Do not mark players as idle when flinging.
+ result.delegate_state = DelegateState::GONE;
+ result.is_idle = delegate_->IsIdle(delegate_id_) && !is_flinging;
+ } else if (paused_) {
+ // TODO(sandersd): Is it possible to have a suspended session, be ended,
+ // and not be paused? If so we should be in a PLAYING state.
+ result.delegate_state = DelegateState::PAUSED;
+ result.is_idle = !seeking_;
+ } else {
+ result.delegate_state = DelegateState::PLAYING;
+ result.is_idle = false;
+ }
+
+ // It's not critical if some cases where memory usage can change are missed,
+ // since media memory changes are usually gradual.
+ result.is_memory_reporting_enabled = !has_error && can_play && !is_flinging &&
+ !result.is_suspended &&
+ (!paused_ || seeking_);
+
+ return result;
+}
+
+void WebMediaPlayerImpl::SetDemuxer(std::unique_ptr<Demuxer> demuxer) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(!demuxer_);
+ DCHECK(!media_thread_mem_dumper_);
+ DCHECK(demuxer);
+
+ demuxer_ = std::move(demuxer);
+
+ // base::Unretained() is safe here. `demuxer_` is destroyed on the main
+ // thread, but before doing it ~WebMediaPlayerImpl() posts a media thread task
+ // that deletes media_thread_mem_dumper_ and waits for it to finish.
+ media_thread_mem_dumper_ = std::make_unique<media::MemoryDumpProviderProxy>(
+ "WebMediaPlayer_MediaThread", media_task_runner_,
+ base::BindRepeating(&WebMediaPlayerImpl::OnMediaThreadMemoryDump,
+ media_log_->id(), base::Unretained(demuxer_.get())));
+}
+
+void WebMediaPlayerImpl::ReportMemoryUsage() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // About base::Unretained() usage below: We destroy `demuxer_` on the main
+ // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
+ // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
+ // posted here must finish earlier.
+ //
+ // The exception to the above is when OnError() has been called. If we're in
+ // the error state we've already shut down the pipeline and can't rely on it
+ // to cycle the media thread before we destroy `demuxer_`. In this case skip
+ // collection of the demuxer memory stats.
+ if (demuxer_ && !IsNetworkStateError(network_state_)) {
+ base::PostTaskAndReplyWithResult(
+ media_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&Demuxer::GetMemoryUsage,
+ base::Unretained(demuxer_.get())),
+ base::BindOnce(&WebMediaPlayerImpl::FinishMemoryUsageReport,
+ weak_this_));
+ } else {
+ FinishMemoryUsageReport(0);
+ }
+}
+
+void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ const auto stats = GetPipelineStatistics();
+ const int64_t data_source_memory_usage =
+ data_source_ ? data_source_->GetMemoryUsage() : 0;
+
+ // If we have video and no video memory usage and we've rendered the first
+ // frame, assume the VideoFrameCompositor is holding onto the last frame after
+ // we've suspended the pipeline; which thus reports zero memory usage from the
+ // video renderer.
+ //
+ // Technically this should use the coded size, but that requires us to hop to
+ // the compositor to get and byte-perfect accuracy isn't important here.
+ const int64_t video_memory_usage =
+ stats.video_memory_usage +
+ ((pipeline_metadata_.has_video && !stats.video_memory_usage &&
+ has_first_frame_)
+ ? media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
+ pipeline_metadata_.natural_size)
+ : 0);
+
+ const int64_t current_memory_usage =
+ stats.audio_memory_usage + video_memory_usage + data_source_memory_usage +
+ demuxer_memory_usage;
+
+ DVLOG(3) << "Memory Usage -- Total: " << current_memory_usage
+ << " Audio: " << stats.audio_memory_usage
+ << ", Video: " << video_memory_usage
+ << ", DataSource: " << data_source_memory_usage
+ << ", Demuxer: " << demuxer_memory_usage;
+
+ const int64_t delta = current_memory_usage - last_reported_memory_usage_;
+ last_reported_memory_usage_ = current_memory_usage;
+ adjust_allocated_memory_cb_.Run(delta);
+}
+
+void WebMediaPlayerImpl::OnMainThreadMemoryDump(
+ int32_t id,
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ const auto stats = GetPipelineStatistics();
+ auto player_node_name =
+ base::StringPrintf("media/webmediaplayer/player_0x%x", id);
+ auto* player_node = pmd->CreateAllocatorDump(player_node_name);
+ player_node->AddScalar(
+ base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects, 1);
+
+ if (args.level_of_detail !=
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ bool suspended = pipeline_controller_->IsPipelineSuspended();
+ auto player_state =
+ base::StringPrintf("Paused: %d Ended: %d ReadyState: %d Suspended: %d",
+ paused_, ended_, GetReadyState(), suspended);
+ player_node->AddString("player_state", "", player_state);
+ }
+
+ CreateAllocation(pmd, id, "audio", stats.audio_memory_usage);
+ CreateAllocation(pmd, id, "video", stats.video_memory_usage);
+
+ if (data_source_)
+ CreateAllocation(pmd, id, "data_source", data_source_->GetMemoryUsage());
+}
+
+// static
+void WebMediaPlayerImpl::OnMediaThreadMemoryDump(
+ int32_t id,
+ Demuxer* demuxer,
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ if (!demuxer)
+ return;
+
+ CreateAllocation(pmd, id, "demuxer", demuxer->GetMemoryUsage());
+}
+
+void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
+ // Only schedule the pause timer if we're not paused or paused but going to
+ // resume when foregrounded, and are suspended and have audio.
+ if ((paused_ && !paused_when_hidden_) ||
+ !pipeline_controller_->IsSuspended() || !HasAudio()) {
+ return;
+ }
+
+#if defined(OS_ANDROID)
+ // Don't pause videos casted as part of RemotePlayback.
+ if (is_flinging_)
+ return;
+#endif
+
+ // Idle timeout chosen arbitrarily.
+ background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
+ client_, &WebMediaPlayerClient::PausePlayback);
+}
+
+void WebMediaPlayerImpl::CreateWatchTimeReporter() {
+ if (!HasVideo() && !HasAudio())
+ return;
+
+ // MediaPlayerRenderer does not know about tracks until playback starts.
+ // Assume audio-only unless the natural size has been detected.
+ bool has_video = pipeline_metadata_.has_video;
+ if (using_media_player_renderer_) {
+ has_video = !pipeline_metadata_.natural_size.IsEmpty();
+ }
+
+ // Create the watch time reporter and synchronize its initial state.
+ watch_time_reporter_ = std::make_unique<WatchTimeReporter>(
+ media::mojom::PlaybackProperties::New(
+ pipeline_metadata_.has_audio, has_video, false, false,
+ !!chunk_demuxer_, is_encrypted_, embedded_media_experience_enabled_,
+ media::mojom::MediaStreamType::kNone),
+ pipeline_metadata_.natural_size,
+ base::BindRepeating(&WebMediaPlayerImpl::GetCurrentTimeInternal,
+ base::Unretained(this)),
+ base::BindRepeating(&WebMediaPlayerImpl::GetPipelineStatistics,
+ base::Unretained(this)),
+ media_metrics_provider_.get(),
+ frame_->GetTaskRunner(TaskType::kInternalMedia));
+ watch_time_reporter_->OnVolumeChange(volume_);
+ watch_time_reporter_->OnDurationChanged(GetPipelineMediaDuration());
+
+ if (delegate_->IsFrameHidden())
+ watch_time_reporter_->OnHidden();
+ else
+ watch_time_reporter_->OnShown();
+
+ if (client_->HasNativeControls())
+ watch_time_reporter_->OnNativeControlsEnabled();
+ else
+ watch_time_reporter_->OnNativeControlsDisabled();
+
+ switch (client_->GetDisplayType()) {
+ case DisplayType::kInline:
+ watch_time_reporter_->OnDisplayTypeInline();
+ break;
+ case DisplayType::kFullscreen:
+ watch_time_reporter_->OnDisplayTypeFullscreen();
+ break;
+ case DisplayType::kPictureInPicture:
+ watch_time_reporter_->OnDisplayTypePictureInPicture();
+ break;
+ }
+
+ UpdateSecondaryProperties();
+
+ // If the WatchTimeReporter was recreated in the middle of playback, we want
+ // to resume playback here too since we won't get another play() call. When
+ // seeking, the seek completion will restart it if necessary.
+ if (!paused_ && !seeking_)
+ watch_time_reporter_->OnPlaying();
+}
+
+void WebMediaPlayerImpl::UpdateSecondaryProperties() {
+ watch_time_reporter_->UpdateSecondaryProperties(
+ media::mojom::SecondaryPlaybackProperties::New(
+ pipeline_metadata_.audio_decoder_config.codec(),
+ pipeline_metadata_.video_decoder_config.codec(),
+ pipeline_metadata_.audio_decoder_config.profile(),
+ pipeline_metadata_.video_decoder_config.profile(),
+ audio_decoder_type_, video_decoder_type_,
+ pipeline_metadata_.audio_decoder_config.encryption_scheme(),
+ pipeline_metadata_.video_decoder_config.encryption_scheme(),
+ pipeline_metadata_.natural_size));
+}
+
+bool WebMediaPlayerImpl::IsHidden() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ return delegate_->IsFrameHidden() && !was_suspended_for_frame_closed_;
+}
+
+bool WebMediaPlayerImpl::IsStreaming() const {
+ return data_source_ && data_source_->IsStreaming();
+}
+
+bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const {
+ return pipeline_metadata_.video_decoder_config.video_transformation() ==
+ media::kNoTransformation;
+}
+
+void WebMediaPlayerImpl::UpdateRemotePlaybackCompatibility(bool is_compatible) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ client_->RemotePlaybackCompatibilityChanged(loaded_url_, is_compatible);
+}
+
+void WebMediaPlayerImpl::ForceStaleStateForTesting(ReadyState target_state) {
+ stale_state_override_for_testing_.emplace(target_state);
+ UpdatePlayState();
+}
+
+bool WebMediaPlayerImpl::IsSuspendedForTesting() {
+ // This intentionally uses IsPipelineSuspended since we need to know when the
+ // pipeline has reached the suspended state, not when it's in suspending.
+ return pipeline_controller_->IsPipelineSuspended();
+}
+
+bool WebMediaPlayerImpl::DidLazyLoad() const {
+ return did_lazy_load_;
+}
+
+void WebMediaPlayerImpl::OnBecameVisible() {
+ have_enough_after_lazy_load_cb_.Cancel();
+ needs_first_frame_ = !has_first_frame_;
+ UpdatePlayState();
+}
+
+bool WebMediaPlayerImpl::IsOpaque() const {
+ return opaque_;
+}
+
+int WebMediaPlayerImpl::GetDelegateId() {
+ return delegate_id_;
+}
+
+absl::optional<viz::SurfaceId> WebMediaPlayerImpl::GetSurfaceId() {
+ if (!surface_layer_for_video_enabled_)
+ return absl::nullopt;
+ return bridge_->GetSurfaceId();
+}
+
+void WebMediaPlayerImpl::RequestVideoFrameCallback() {
+ compositor_->SetOnFramePresentedCallback(
+ media::BindToCurrentLoop(base::BindOnce(
+ &WebMediaPlayerImpl::OnNewFramePresentedCallback, weak_this_)));
+}
+
+void WebMediaPlayerImpl::OnNewFramePresentedCallback() {
+ client_->OnRequestVideoFrameCallback();
+}
+
+std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata>
+WebMediaPlayerImpl::GetVideoFramePresentationMetadata() {
+ return compositor_->GetLastPresentedFrameMetadata();
+}
+
+void WebMediaPlayerImpl::UpdateFrameIfStale() {
+ // base::Unretained is safe here because `compositor_` is destroyed on
+ // `vfc_task_runner_`. The destruction is queued from `this`' destructor,
+ // which also runs on `main_task_runner_`, which makes it impossible for
+ // UpdateCurrentFrameIfStale() to be queued after `compositor_`'s dtor.
+ vfc_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoFrameCompositor::UpdateCurrentFrameIfStale,
+ base::Unretained(compositor_.get()),
+ VideoFrameCompositor::UpdateType::kBypassClient));
+}
+
+base::WeakPtr<WebMediaPlayer> WebMediaPlayerImpl::AsWeakPtr() {
+ return weak_this_;
+}
+
+bool WebMediaPlayerImpl::ShouldPausePlaybackWhenHidden() const {
+ // Audio only stream is allowed to play when in background.
+ // TODO: We should check IsBackgroundOptimizationCandidate here. But we need
+ // to move the logic of checking video frames out of that function.
+ if (!HasVideo())
+ return false;
+
+ if (using_media_player_renderer_ &&
+ pipeline_metadata_.natural_size.IsEmpty()) {
+ return false;
+ }
+
+ if (!is_background_video_playback_enabled_)
+ return true;
+
+ // If suspending background video, pause any video that's not remoted or
+ // not unlocked to play in the background.
+ if (IsBackgroundSuspendEnabled(this)) {
+#if defined(OS_ANDROID)
+ if (is_flinging_)
+ return false;
+#endif
+
+ return !HasAudio() || (IsResumeBackgroundVideosEnabled() &&
+ video_locked_when_paused_when_hidden_);
+ }
+
+ // Otherwise only pause if the optimization is on and it's a video-only
+ // optimization candidate.
+ return IsBackgroundVideoPauseOptimizationEnabled() && !HasAudio() &&
+ IsBackgroundOptimizationCandidate() && !is_flinging_;
+}
+
+bool WebMediaPlayerImpl::ShouldDisableVideoWhenHidden() const {
+ // This optimization is behind the flag on all platforms, only for non-mse
+ // video. MSE video track switching on hide has gone through a field test.
+ // TODO(tmathmeyer): Passing load_type_ won't be needed after src= field
+ // testing is finished. see: http://crbug.com/709302
+ if (!is_background_video_track_optimization_supported_)
+ return false;
+
+ // Disable video track only for players with audio that match the criteria for
+ // being optimized.
+ return HasAudio() && IsBackgroundOptimizationCandidate();
+}
+
+bool WebMediaPlayerImpl::IsBackgroundOptimizationCandidate() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // Don't optimize Picture-in-Picture players.
+ if (IsInPictureInPicture())
+ return false;
+
+#if defined(OS_ANDROID)
+ // Don't optimize videos casted as part of RemotePlayback.
+ if (is_flinging_)
+ return false;
+#endif
+
+ // Don't optimize audio-only or streaming players.
+ if (!HasVideo() || IsStreaming())
+ return false;
+
+ // If frames are being captured, don't disable the track or pause the video.
+ if (IsVideoBeingCaptured())
+ return false;
+
+ // Video-only players are always optimized (paused).
+ // Don't check the keyframe distance and duration.
+ if (!HasAudio() && HasVideo())
+ return true;
+
+ // Videos shorter than the maximum allowed keyframe distance can be optimized.
+ base::TimeDelta duration = GetPipelineMediaDuration();
+
+ constexpr base::TimeDelta kMaxKeyframeDistanceToDisableBackgroundVideo =
+ base::TimeDelta::FromMilliseconds(
+ kMaxKeyframeDistanceToDisableBackgroundVideoMs);
+ if (duration < kMaxKeyframeDistanceToDisableBackgroundVideo)
+ return true;
+
+ // Otherwise, only optimize videos with shorter average keyframe distance.
+ auto stats = GetPipelineStatistics();
+ return stats.video_keyframe_distance_average <
+ kMaxKeyframeDistanceToDisableBackgroundVideo;
+}
+
+void WebMediaPlayerImpl::UpdateBackgroundVideoOptimizationState() {
+ if (IsHidden()) {
+ if (ShouldPausePlaybackWhenHidden()) {
+ PauseVideoIfNeeded();
+ } else if (is_background_status_change_cancelled_) {
+ // Only trigger updates when we don't have one already scheduled.
+ update_background_status_cb_.Reset(
+ base::BindOnce(&WebMediaPlayerImpl::DisableVideoTrackIfNeeded,
+ base::Unretained(this)));
+ is_background_status_change_cancelled_ = false;
+
+ // Defer disable track until we're sure the clip will be backgrounded for
+ // some time. Resuming may take half a second, so frequent tab switches
+ // will yield a poor user experience otherwise. http://crbug.com/709302
+ // may also cause AV sync issues if disable/enable happens too fast.
+ main_task_runner_->PostDelayedTask(
+ FROM_HERE, update_background_status_cb_.callback(),
+ base::TimeDelta::FromSeconds(10));
+ }
+ } else {
+ update_background_status_cb_.Cancel();
+ is_background_status_change_cancelled_ = true;
+ EnableVideoTrackIfNeeded();
+ }
+}
+
+void WebMediaPlayerImpl::PauseVideoIfNeeded() {
+ DCHECK(IsHidden());
+
+ // Don't pause video while the pipeline is stopped, resuming or seeking.
+ // Also if the video is paused already.
+ if (!pipeline_controller_->IsPipelineRunning() || is_pipeline_resuming_ ||
+ seeking_ || paused_)
+ return;
+
+ // client_->PausePlayback() will get `paused_when_hidden_` set to
+ // false and UpdatePlayState() called, so set the flag to true after and then
+ // return.
+ client_->PausePlayback();
+ paused_when_hidden_ = true;
+}
+
+void WebMediaPlayerImpl::EnableVideoTrackIfNeeded() {
+ // Don't change video track while the pipeline is stopped, resuming or
+ // seeking.
+ if (!pipeline_controller_->IsPipelineRunning() || is_pipeline_resuming_ ||
+ seeking_)
+ return;
+
+ if (video_track_disabled_) {
+ video_track_disabled_ = false;
+ if (client_->HasSelectedVideoTrack()) {
+ WebMediaPlayer::TrackId trackId = client_->GetSelectedVideoTrackId();
+ SelectedVideoTrackChanged(&trackId);
+ }
+ }
+}
+
+void WebMediaPlayerImpl::DisableVideoTrackIfNeeded() {
+ DCHECK(IsHidden());
+
+ // Don't change video track while the pipeline is resuming or seeking.
+ if (is_pipeline_resuming_ || seeking_)
+ return;
+
+ if (!video_track_disabled_ && ShouldDisableVideoWhenHidden()) {
+ video_track_disabled_ = true;
+ SelectedVideoTrackChanged(nullptr);
+ }
+}
+
+void WebMediaPlayerImpl::SetPipelineStatisticsForTest(
+ const media::PipelineStatistics& stats) {
+ pipeline_statistics_for_test_ = absl::make_optional(stats);
+}
+
+media::PipelineStatistics WebMediaPlayerImpl::GetPipelineStatistics() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ return pipeline_statistics_for_test_.value_or(
+ pipeline_controller_->GetStatistics());
+}
+
+void WebMediaPlayerImpl::SetPipelineMediaDurationForTest(
+ base::TimeDelta duration) {
+ pipeline_media_duration_for_test_ = absl::make_optional(duration);
+}
+
+base::TimeDelta WebMediaPlayerImpl::GetPipelineMediaDuration() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ return pipeline_media_duration_for_test_.value_or(
+ pipeline_controller_->GetMediaDuration());
+}
+
+media::MediaContentType WebMediaPlayerImpl::GetMediaContentType() const {
+ return media::DurationToMediaContentType(GetPipelineMediaDuration());
+}
+
+void WebMediaPlayerImpl::SwitchToRemoteRenderer(
+ const std::string& remote_device_friendly_name) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ DCHECK(!is_remote_rendering_);
+ is_remote_rendering_ = true;
+
+ DCHECK(!disable_pipeline_auto_suspend_);
+ disable_pipeline_auto_suspend_ = true;
+
+ // Capabilities reporting should only be performed for local playbacks.
+ video_decode_stats_reporter_.reset();
+
+ // Requests to restart media pipeline. A remote renderer will be created via
+ // the `renderer_factory_selector_`.
+ ScheduleRestart();
+ if (client_) {
+ client_->MediaRemotingStarted(
+ WebString::FromUTF8(remote_device_friendly_name));
+ }
+}
+
+void WebMediaPlayerImpl::SwitchToLocalRenderer(
+ media::MediaObserverClient::ReasonToSwitchToLocal reason) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (!is_remote_rendering_)
+ return; // Is currently with local renderer.
+ is_remote_rendering_ = false;
+
+ DCHECK(disable_pipeline_auto_suspend_);
+ disable_pipeline_auto_suspend_ = false;
+
+ // Capabilities reporting may resume now that playback is local.
+ CreateVideoDecodeStatsReporter();
+
+ // Requests to restart media pipeline. A local renderer will be created via
+ // the `renderer_factory_selector_`.
+ ScheduleRestart();
+ if (client_)
+ client_->MediaRemotingStopped(GetSwitchToLocalMessage(reason));
+}
+
+void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) {
+ DCHECK(data_source_ || chunk_demuxer_);
+
+ if (data_source_)
+ UMA_HISTOGRAM_TIMES("Media.UnderflowDuration2.SRC", duration);
+ else
+ UMA_HISTOGRAM_TIMES("Media.UnderflowDuration2.MSE", duration);
+
+ if (is_encrypted_)
+ UMA_HISTOGRAM_TIMES("Media.UnderflowDuration2.EME", duration);
+}
+
+#define UMA_HISTOGRAM_VIDEO_HEIGHT(name, sample) \
+ UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 100, 10000, 50)
+
+void WebMediaPlayerImpl::RecordVideoNaturalSize(const gfx::Size& natural_size) {
+ // Always report video natural size to MediaLog.
+ media_log_->AddEvent<MediaLogEvent::kVideoSizeChanged>(natural_size);
+ media_log_->SetProperty<MediaLogProperty::kResolution>(natural_size);
+
+ if (initial_video_height_recorded_)
+ return;
+
+ initial_video_height_recorded_ = true;
+
+ int height = natural_size.height();
+
+ if (load_type_ == kLoadTypeURL)
+ UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.SRC", height);
+ else if (load_type_ == kLoadTypeMediaSource)
+ UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.MSE", height);
+
+ if (is_encrypted_)
+ UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.EME", height);
+
+ UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.All", height);
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnNaturalSizeChanged(natural_size);
+}
+
+#undef UMA_HISTOGRAM_VIDEO_HEIGHT
+
+void WebMediaPlayerImpl::SetTickClockForTest(
+ const base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
+ buffered_data_source_host_->SetTickClockForTest(tick_clock);
+}
+
+void WebMediaPlayerImpl::OnFirstFrame(base::TimeTicks frame_time) {
+ DCHECK(!load_start_time_.is_null());
+ DCHECK(!skip_metrics_due_to_startup_suspend_);
+ has_first_frame_ = true;
+ needs_first_frame_ = false;
+ const base::TimeDelta elapsed = frame_time - load_start_time_;
+ media_metrics_provider_->SetTimeToFirstFrame(elapsed);
+ RecordTimingUMA("Media.TimeToFirstFrame", elapsed);
+
+ // Needed to signal HTMLVideoElement that it should remove the poster image.
+ if (client_ && has_poster_)
+ client_->Repaint();
+}
+
+void WebMediaPlayerImpl::RecordTimingUMA(const std::string& key,
+ base::TimeDelta elapsed) {
+ if (chunk_demuxer_)
+ base::UmaHistogramMediumTimes(key + ".MSE", elapsed);
+ else
+ base::UmaHistogramMediumTimes(key + ".SRC", elapsed);
+ if (is_encrypted_)
+ base::UmaHistogramMediumTimes(key + ".EME", elapsed);
+}
+
+void WebMediaPlayerImpl::RecordEncryptionScheme(
+ const std::string& stream_name,
+ media::EncryptionScheme encryption_scheme) {
+ DCHECK(stream_name == "Audio" || stream_name == "Video");
+
+ // If the stream is not encrypted, don't record it.
+ if (encryption_scheme == media::EncryptionScheme::kUnencrypted)
+ return;
+
+ base::UmaHistogramEnumeration(
+ "Media.EME.EncryptionScheme.Initial." + stream_name,
+ DetermineEncryptionSchemeUMAValue(encryption_scheme),
+ EncryptionSchemeUMA::kCount);
+}
+
+bool WebMediaPlayerImpl::IsInPictureInPicture() const {
+ DCHECK(client_);
+ return client_->GetDisplayType() == DisplayType::kPictureInPicture;
+}
+
+void WebMediaPlayerImpl::MaybeSetContainerNameForMetrics() {
+ // Pipeline startup failed before even getting a demuxer setup.
+ if (!demuxer_)
+ return;
+
+ // Container has already been set.
+ if (highest_ready_state_ >= WebMediaPlayer::kReadyStateHaveMetadata)
+ return;
+
+ // Only report metrics for demuxers that provide container information.
+ auto container = demuxer_->GetContainerForMetrics();
+ if (container.has_value())
+ media_metrics_provider_->SetContainerName(container.value());
+}
+
+void WebMediaPlayerImpl::MaybeUpdateBufferSizesForPlayback() {
+ // Don't increase the MultiBufferDataSource buffer size until we've reached
+ // kReadyStateHaveEnoughData. Otherwise we will unnecessarily slow down
+ // playback startup -- it can instead be done for free after playback starts.
+ if (!mb_data_source_ || highest_ready_state_ < kReadyStateHaveEnoughData)
+ return;
+
+ mb_data_source_->MediaPlaybackRateChanged(playback_rate_);
+ if (!paused_)
+ mb_data_source_->MediaIsPlaying();
+}
+
+void WebMediaPlayerImpl::OnSimpleWatchTimerTick() {
+ RecordSimpleWatchTimeUMA(renderer_type_);
+
+ if (playback_events_recorder_)
+ playback_events_recorder_->OnPipelineStatistics(GetPipelineStatistics());
+}
+
+GURL WebMediaPlayerImpl::GetSrcAfterRedirects() {
+ return mb_data_source_ ? mb_data_source_->GetUrlAfterRedirects() : GURL();
+}
+
+void WebMediaPlayerImpl::UpdateSmoothnessHelper() {
+ // If the experiment flag is off, then do nothing.
+ if (!base::FeatureList::IsEnabled(media::kMediaLearningSmoothnessExperiment))
+ return;
+
+ // If we're paused, or if we can't get all the features, then clear any
+ // smoothness helper and stop. We'll try to create it later when we're
+ // playing and have all the features.
+ if (paused_ || !HasVideo() || pipeline_metadata_.natural_size.IsEmpty() ||
+ !last_reported_fps_) {
+ smoothness_helper_.reset();
+ return;
+ }
+
+ // Fill in features.
+ // NOTE: this is a very bad way to do this, since it memorizes the order of
+ // features in the task. However, it'll do for now.
+ learning::FeatureVector features;
+ features.push_back(
+ learning::FeatureValue(pipeline_metadata_.video_decoder_config.codec()));
+ features.push_back(learning::FeatureValue(
+ pipeline_metadata_.video_decoder_config.profile()));
+ features.push_back(
+ learning::FeatureValue(pipeline_metadata_.natural_size.width()));
+ features.push_back(learning::FeatureValue(*last_reported_fps_));
+
+ // If we have a smoothness helper, and we're not changing the features, then
+ // do nothing. This prevents restarting the helper for no reason.
+ if (smoothness_helper_ && features == smoothness_helper_->features())
+ return;
+
+ // Create or restart the smoothness helper with `features`.
+ smoothness_helper_ = SmoothnessHelper::Create(
+ GetLearningTaskController(learning::tasknames::kConsecutiveBadWindows),
+ GetLearningTaskController(learning::tasknames::kConsecutiveNNRs),
+ features, this);
+}
+
+std::unique_ptr<learning::LearningTaskController>
+WebMediaPlayerImpl::GetLearningTaskController(const char* task_name) {
+ // Get the LearningTaskController for `task_id`.
+ learning::LearningTask task = learning::MediaLearningTasks::Get(task_name);
+ DCHECK_EQ(task.name, task_name);
+
+ mojo::Remote<learning::mojom::LearningTaskController> remote_ltc;
+ media_metrics_provider_->AcquireLearningTaskController(
+ task.name, remote_ltc.BindNewPipeAndPassReceiver());
+ return std::make_unique<learning::MojoLearningTaskController>(
+ task, std::move(remote_ltc));
+}
+
+bool WebMediaPlayerImpl::HasUnmutedAudio() const {
+ // Pretend that the media has no audio if it never played unmuted. This is to
+ // avoid any action related to audible media such as taking audio focus or
+ // showing a media notification. To preserve a consistent experience, it does
+ // not apply if a media was audible so the system states do not flicker
+ // depending on whether the user muted the player.
+ return HasAudio() && !client_->WasAlwaysMuted();
+}
+
+bool WebMediaPlayerImpl::IsVideoBeingCaptured() const {
+ // 5 seconds chosen arbitrarily since most videos are never captured.
+ return tick_clock_->NowTicks() - last_frame_request_time_ <
+ base::TimeDelta::FromSeconds(5);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_media_player_params.cc b/chromium/third_party/blink/renderer/platform/media/web_media_player_params.cc
new file mode 100644
index 00000000000..ca72abac7a0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_media_player_params.cc
@@ -0,0 +1,70 @@
+// 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/public/platform/media/web_media_player_params.h"
+
+#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
+#include "media/base/audio_renderer_sink.h"
+#include "media/base/demuxer.h"
+
+namespace blink {
+
+WebMediaPlayerParams::WebMediaPlayerParams(
+ std::unique_ptr<media::MediaLog> media_log,
+ const DeferLoadCB& defer_load_cb,
+ const scoped_refptr<media::SwitchableAudioRendererSink>&
+ audio_renderer_sink,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ const scoped_refptr<base::TaskRunner>& worker_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ video_frame_compositor_task_runner,
+ const AdjustAllocatedMemoryCB& adjust_allocated_memory_cb,
+ WebContentDecryptionModule* initial_cdm,
+ media::RequestRoutingTokenCallback request_routing_token_cb,
+ base::WeakPtr<media::MediaObserver> media_observer,
+ bool enable_instant_source_buffer_gc,
+ bool embedded_media_experience_enabled,
+ mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
+ CreateSurfaceLayerBridgeCB create_bridge_callback,
+ scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+ WebMediaPlayer::SurfaceLayerMode use_surface_layer_for_video,
+ bool is_background_suspend_enabled,
+ bool is_background_video_playback_enabled,
+ bool is_background_video_track_optimization_supported,
+ std::unique_ptr<media::Demuxer> demuxer_override,
+ std::unique_ptr<PowerStatusHelper> power_status_helper)
+ : defer_load_cb_(defer_load_cb),
+ audio_renderer_sink_(audio_renderer_sink),
+ media_log_(std::move(media_log)),
+ media_task_runner_(media_task_runner),
+ worker_task_runner_(worker_task_runner),
+ compositor_task_runner_(compositor_task_runner),
+ video_frame_compositor_task_runner_(video_frame_compositor_task_runner),
+ adjust_allocated_memory_cb_(adjust_allocated_memory_cb),
+ initial_cdm_(initial_cdm),
+ request_routing_token_cb_(std::move(request_routing_token_cb)),
+ media_observer_(media_observer),
+ enable_instant_source_buffer_gc_(enable_instant_source_buffer_gc),
+ embedded_media_experience_enabled_(embedded_media_experience_enabled),
+ metrics_provider_(std::move(metrics_provider)),
+ create_bridge_callback_(std::move(create_bridge_callback)),
+ raster_context_provider_(std::move(raster_context_provider)),
+ use_surface_layer_for_video_(use_surface_layer_for_video),
+ is_background_suspend_enabled_(is_background_suspend_enabled),
+ is_background_video_playback_enabled_(
+ is_background_video_playback_enabled),
+ is_background_video_track_optimization_supported_(
+ is_background_video_track_optimization_supported),
+ demuxer_override_(std::move(demuxer_override)),
+ power_status_helper_(std::move(power_status_helper)) {}
+
+WebMediaPlayerParams::~WebMediaPlayerParams() = default;
+
+std::unique_ptr<media::Demuxer> WebMediaPlayerParams::TakeDemuxerOverride() {
+ return std::move(demuxer_override_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_media_source_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_media_source_impl.cc
new file mode 100644
index 00000000000..24b0a1a23b8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_media_source_impl.cc
@@ -0,0 +1,107 @@
+// 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/media/web_media_source_impl.h"
+
+#include "base/guid.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/mime_util.h"
+#include "media/base/video_decoder_config.h"
+#include "media/filters/chunk_demuxer.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/media/web_source_buffer_impl.h"
+
+namespace blink {
+
+#define STATIC_ASSERT_MATCHING_STATUS_ENUM(webkit_name, chromium_name) \
+ static_assert(static_cast<int>(WebMediaSource::webkit_name) == \
+ static_cast<int>(media::ChunkDemuxer::chromium_name), \
+ "mismatching status enum values: " #webkit_name)
+STATIC_ASSERT_MATCHING_STATUS_ENUM(kAddStatusOk, kOk);
+STATIC_ASSERT_MATCHING_STATUS_ENUM(kAddStatusNotSupported, kNotSupported);
+STATIC_ASSERT_MATCHING_STATUS_ENUM(kAddStatusReachedIdLimit, kReachedIdLimit);
+#undef STATIC_ASSERT_MATCHING_STATUS_ENUM
+
+WebMediaSourceImpl::WebMediaSourceImpl(media::ChunkDemuxer* demuxer)
+ : demuxer_(demuxer) {
+ DCHECK(demuxer_);
+}
+
+WebMediaSourceImpl::~WebMediaSourceImpl() = default;
+
+std::unique_ptr<WebSourceBuffer> WebMediaSourceImpl::AddSourceBuffer(
+ const WebString& content_type,
+ const WebString& codecs,
+ WebMediaSource::AddStatus& out_status /* out */) {
+ std::string id = base::GenerateGUID();
+
+ out_status = static_cast<WebMediaSource::AddStatus>(
+ demuxer_->AddId(id, content_type.Utf8(), codecs.Utf8()));
+
+ if (out_status == WebMediaSource::kAddStatusOk)
+ return std::make_unique<WebSourceBufferImpl>(id, demuxer_);
+
+ return nullptr;
+}
+
+std::unique_ptr<WebSourceBuffer> WebMediaSourceImpl::AddSourceBuffer(
+ std::unique_ptr<media::AudioDecoderConfig> audio_config,
+ WebMediaSource::AddStatus& out_status /* out */) {
+ std::string id = base::GenerateGUID();
+
+ out_status = static_cast<WebMediaSource::AddStatus>(
+ demuxer_->AddId(id, std::move(audio_config)));
+
+ if (out_status == WebMediaSource::kAddStatusOk)
+ return std::make_unique<WebSourceBufferImpl>(id, demuxer_);
+
+ return nullptr;
+}
+
+std::unique_ptr<WebSourceBuffer> WebMediaSourceImpl::AddSourceBuffer(
+ std::unique_ptr<media::VideoDecoderConfig> video_config,
+ WebMediaSource::AddStatus& out_status /* out */) {
+ std::string id = base::GenerateGUID();
+
+ out_status = static_cast<WebMediaSource::AddStatus>(
+ demuxer_->AddId(id, std::move(video_config)));
+
+ if (out_status == WebMediaSource::kAddStatusOk)
+ return std::make_unique<WebSourceBufferImpl>(id, demuxer_);
+
+ return nullptr;
+}
+
+double WebMediaSourceImpl::Duration() {
+ return demuxer_->GetDuration();
+}
+
+void WebMediaSourceImpl::SetDuration(double new_duration) {
+ DCHECK_GE(new_duration, 0);
+ demuxer_->SetDuration(new_duration);
+}
+
+void WebMediaSourceImpl::MarkEndOfStream(
+ WebMediaSource::EndOfStreamStatus status) {
+ media::PipelineStatus pipeline_status = media::PIPELINE_OK;
+
+ switch (status) {
+ case WebMediaSource::kEndOfStreamStatusNoError:
+ break;
+ case WebMediaSource::kEndOfStreamStatusNetworkError:
+ pipeline_status = media::CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR;
+ break;
+ case WebMediaSource::kEndOfStreamStatusDecodeError:
+ pipeline_status = media::CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR;
+ break;
+ }
+
+ demuxer_->MarkEndOfStream(pipeline_status);
+}
+
+void WebMediaSourceImpl::UnmarkEndOfStream() {
+ demuxer_->UnmarkEndOfStream();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_media_source_impl.h b/chromium/third_party/blink/renderer/platform/media/web_media_source_impl.h
new file mode 100644
index 00000000000..efc0e468d3c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_media_source_impl.h
@@ -0,0 +1,50 @@
+// 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_MEDIA_WEB_MEDIA_SOURCE_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_MEDIA_SOURCE_IMPL_H_
+
+#include <vector>
+
+#include "third_party/blink/public/platform/web_media_source.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace media {
+class AudioDecoderConfig;
+class ChunkDemuxer;
+class VideoDecoderConfig;
+} // namespace media
+
+namespace blink {
+
+class PLATFORM_EXPORT WebMediaSourceImpl : public WebMediaSource {
+ public:
+ WebMediaSourceImpl(media::ChunkDemuxer* demuxer);
+ WebMediaSourceImpl(const WebMediaSourceImpl&) = delete;
+ WebMediaSourceImpl& operator=(const WebMediaSourceImpl&) = delete;
+ ~WebMediaSourceImpl() override;
+
+ // WebMediaSource implementation.
+ std::unique_ptr<WebSourceBuffer> AddSourceBuffer(
+ const WebString& content_type,
+ const WebString& codecs,
+ AddStatus& out_status /* out */) override;
+ std::unique_ptr<WebSourceBuffer> AddSourceBuffer(
+ std::unique_ptr<media::AudioDecoderConfig> audio_config,
+ AddStatus& out_status /* out */) override;
+ std::unique_ptr<WebSourceBuffer> AddSourceBuffer(
+ std::unique_ptr<media::VideoDecoderConfig> video_config,
+ AddStatus& out_status /* out */) override;
+ double Duration() override;
+ void SetDuration(double duration) override;
+ void MarkEndOfStream(EndOfStreamStatus status) override;
+ void UnmarkEndOfStream() override;
+
+ private:
+ media::ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl.
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_MEDIA_SOURCE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc b/chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc
new file mode 100644
index 00000000000..d57921238f9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc
@@ -0,0 +1,260 @@
+// 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/media/web_source_buffer_impl.h"
+
+#include <stdint.h>
+
+#include <cmath>
+#include <limits>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/strings/string_number_conversions.h"
+#include "media/base/media_tracks.h"
+#include "media/base/timestamp_constants.h"
+#include "media/filters/chunk_demuxer.h"
+#include "media/filters/source_buffer_parse_warnings.h"
+#include "third_party/blink/public/platform/web_media_player.h"
+#include "third_party/blink/public/platform/web_source_buffer_client.h"
+
+namespace blink {
+
+static WebSourceBufferClient::ParseWarning ParseWarningToBlink(
+ const media::SourceBufferParseWarning warning) {
+#define CHROMIUM_PARSE_WARNING_TO_BLINK_ENUM_CASE(name) \
+ case media::SourceBufferParseWarning::name: \
+ return WebSourceBufferClient::ParseWarning::name
+
+ switch (warning) {
+ CHROMIUM_PARSE_WARNING_TO_BLINK_ENUM_CASE(
+ kKeyframeTimeGreaterThanDependant);
+ CHROMIUM_PARSE_WARNING_TO_BLINK_ENUM_CASE(kMuxedSequenceMode);
+ CHROMIUM_PARSE_WARNING_TO_BLINK_ENUM_CASE(
+ kGroupEndTimestampDecreaseWithinMediaSegment);
+ }
+
+ NOTREACHED();
+ return WebSourceBufferClient::ParseWarning::kKeyframeTimeGreaterThanDependant;
+
+#undef CHROMIUM_PARSE_WARNING_TO_BLINK_ENUM_CASE
+}
+
+static base::TimeDelta DoubleToTimeDelta(double time) {
+ DCHECK(!std::isnan(time));
+ DCHECK_NE(time, -std::numeric_limits<double>::infinity());
+
+ if (time == std::numeric_limits<double>::infinity())
+ return media::kInfiniteDuration;
+
+ constexpr double max_time_in_seconds =
+ base::TimeDelta::FiniteMax().InSecondsF();
+
+ if (time >= max_time_in_seconds)
+ return base::TimeDelta::FiniteMax();
+
+ return base::TimeDelta::FromMicroseconds(
+ time * base::Time::kMicrosecondsPerSecond);
+}
+
+WebSourceBufferImpl::WebSourceBufferImpl(const std::string& id,
+ media::ChunkDemuxer* demuxer)
+ : id_(id),
+ demuxer_(demuxer),
+ client_(nullptr),
+ append_window_end_(media::kInfiniteDuration) {
+ DCHECK(demuxer_);
+ demuxer_->SetTracksWatcher(
+ id, base::BindRepeating(&WebSourceBufferImpl::InitSegmentReceived,
+ base::Unretained(this)));
+ demuxer_->SetParseWarningCallback(
+ id, base::BindRepeating(&WebSourceBufferImpl::NotifyParseWarning,
+ base::Unretained(this)));
+}
+
+WebSourceBufferImpl::~WebSourceBufferImpl() = default;
+
+void WebSourceBufferImpl::SetClient(WebSourceBufferClient* client) {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
+}
+
+bool WebSourceBufferImpl::GetGenerateTimestampsFlag() {
+ return demuxer_->GetGenerateTimestampsFlag(id_);
+}
+
+bool WebSourceBufferImpl::SetMode(WebSourceBuffer::AppendMode mode) {
+ if (demuxer_->IsParsingMediaSegment(id_))
+ return false;
+
+ switch (mode) {
+ case WebSourceBuffer::kAppendModeSegments:
+ demuxer_->SetSequenceMode(id_, false);
+ return true;
+ case WebSourceBuffer::kAppendModeSequence:
+ demuxer_->SetSequenceMode(id_, true);
+ return true;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+WebTimeRanges WebSourceBufferImpl::Buffered() {
+ media::Ranges<base::TimeDelta> ranges = demuxer_->GetBufferedRanges(id_);
+ WebTimeRanges result(ranges.size());
+ for (size_t i = 0; i < ranges.size(); i++) {
+ result[i].start = ranges.start(i).InSecondsF();
+ result[i].end = ranges.end(i).InSecondsF();
+ }
+ return result;
+}
+
+double WebSourceBufferImpl::HighestPresentationTimestamp() {
+ return demuxer_->GetHighestPresentationTimestamp(id_).InSecondsF();
+}
+
+bool WebSourceBufferImpl::EvictCodedFrames(double currentPlaybackTime,
+ size_t newDataSize) {
+ return demuxer_->EvictCodedFrames(
+ id_,
+ base::TimeDelta::FromSecondsD(currentPlaybackTime),
+ newDataSize);
+}
+
+bool WebSourceBufferImpl::Append(const unsigned char* data,
+ unsigned length,
+ double* timestamp_offset) {
+ base::TimeDelta old_offset = timestamp_offset_;
+ bool success = demuxer_->AppendData(id_, data, length, append_window_start_,
+ append_window_end_, &timestamp_offset_);
+
+ // Coded frame processing may update the timestamp offset. If the caller
+ // provides a non-nullptr |timestamp_offset| and frame processing changes the
+ // timestamp offset, report the new offset to the caller. Do not update the
+ // caller's offset otherwise, to preserve any pre-existing value that may have
+ // more than microsecond precision.
+ if (timestamp_offset && old_offset != timestamp_offset_)
+ *timestamp_offset = timestamp_offset_.InSecondsF();
+
+ return success;
+}
+
+bool WebSourceBufferImpl::AppendChunks(
+ std::unique_ptr<media::StreamParser::BufferQueue> buffer_queue,
+ double* timestamp_offset) {
+ base::TimeDelta old_offset = timestamp_offset_;
+ bool success =
+ demuxer_->AppendChunks(id_, std::move(buffer_queue), append_window_start_,
+ append_window_end_, &timestamp_offset_);
+
+ // Like in ::Append, timestamp_offset may be updated by coded frame
+ // processing.
+ // TODO(crbug.com/1144908): Consider refactoring this common bit into helper.
+ if (timestamp_offset && old_offset != timestamp_offset_)
+ *timestamp_offset = timestamp_offset_.InSecondsF();
+
+ return success;
+}
+
+void WebSourceBufferImpl::ResetParserState() {
+ demuxer_->ResetParserState(id_,
+ append_window_start_, append_window_end_,
+ &timestamp_offset_);
+
+ // TODO(wolenetz): resetParserState should be able to modify the caller
+ // timestamp offset (just like WebSourceBufferImpl::append).
+ // See http://crbug.com/370229 for further details.
+}
+
+void WebSourceBufferImpl::Remove(double start, double end) {
+ DCHECK_GE(start, 0);
+ DCHECK_GE(end, 0);
+ demuxer_->Remove(id_, DoubleToTimeDelta(start), DoubleToTimeDelta(end));
+}
+
+bool WebSourceBufferImpl::CanChangeType(const WebString& content_type,
+ const WebString& codecs) {
+ return demuxer_->CanChangeType(id_, content_type.Utf8(), codecs.Utf8());
+}
+
+void WebSourceBufferImpl::ChangeType(const WebString& content_type,
+ const WebString& codecs) {
+ // Caller must first call ResetParserState() to flush any pending frames.
+ DCHECK(!demuxer_->IsParsingMediaSegment(id_));
+
+ demuxer_->ChangeType(id_, content_type.Utf8(), codecs.Utf8());
+}
+
+bool WebSourceBufferImpl::SetTimestampOffset(double offset) {
+ if (demuxer_->IsParsingMediaSegment(id_))
+ return false;
+
+ timestamp_offset_ = DoubleToTimeDelta(offset);
+
+ // http://www.w3.org/TR/media-source/#widl-SourceBuffer-timestampOffset
+ // Step 6: If the mode attribute equals "sequence", then set the group start
+ // timestamp to new timestamp offset.
+ demuxer_->SetGroupStartTimestampIfInSequenceMode(id_, timestamp_offset_);
+ return true;
+}
+
+void WebSourceBufferImpl::SetAppendWindowStart(double start) {
+ DCHECK_GE(start, 0);
+ append_window_start_ = DoubleToTimeDelta(start);
+}
+
+void WebSourceBufferImpl::SetAppendWindowEnd(double end) {
+ DCHECK_GE(end, 0);
+ append_window_end_ = DoubleToTimeDelta(end);
+}
+
+void WebSourceBufferImpl::RemovedFromMediaSource() {
+ demuxer_->RemoveId(id_);
+ demuxer_ = nullptr;
+ client_ = nullptr;
+}
+
+WebMediaPlayer::TrackType mediaTrackTypeToBlink(media::MediaTrack::Type type) {
+ switch (type) {
+ case media::MediaTrack::Audio:
+ return WebMediaPlayer::kAudioTrack;
+ case media::MediaTrack::Text:
+ return WebMediaPlayer::kTextTrack;
+ case media::MediaTrack::Video:
+ return WebMediaPlayer::kVideoTrack;
+ }
+ NOTREACHED();
+ return WebMediaPlayer::kAudioTrack;
+}
+
+void WebSourceBufferImpl::InitSegmentReceived(
+ std::unique_ptr<media::MediaTracks> tracks) {
+ DCHECK(tracks.get());
+ DVLOG(1) << __func__ << " tracks=" << tracks->tracks().size();
+
+ std::vector<WebSourceBufferClient::MediaTrackInfo> trackInfoVector;
+ for (const auto& track : tracks->tracks()) {
+ WebSourceBufferClient::MediaTrackInfo trackInfo;
+ trackInfo.track_type = mediaTrackTypeToBlink(track->type());
+ trackInfo.id = WebString::FromUTF8(track->id().value());
+ trackInfo.byte_stream_track_id =
+ WebString::FromUTF8(base::NumberToString(track->bytestream_track_id()));
+ trackInfo.kind = WebString::FromUTF8(track->kind().value());
+ trackInfo.label = WebString::FromUTF8(track->label().value());
+ trackInfo.language = WebString::FromUTF8(track->language().value());
+ trackInfoVector.push_back(trackInfo);
+ }
+
+ client_->InitializationSegmentReceived(trackInfoVector);
+}
+
+void WebSourceBufferImpl::NotifyParseWarning(
+ const media::SourceBufferParseWarning warning) {
+ client_->NotifyParseWarning(ParseWarningToBlink(warning));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.h b/chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.h
new file mode 100644
index 00000000000..2e8b3b54f21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_source_buffer_impl.h
@@ -0,0 +1,82 @@
+// 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_MEDIA_WEB_SOURCE_BUFFER_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_SOURCE_BUFFER_IMPL_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/time/time.h"
+#include "third_party/blink/public/platform/web_source_buffer.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace media {
+class ChunkDemuxer;
+class MediaTracks;
+enum class SourceBufferParseWarning;
+} // namespace media
+
+namespace blink {
+
+class PLATFORM_EXPORT WebSourceBufferImpl : public WebSourceBuffer {
+ public:
+ WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer);
+ WebSourceBufferImpl(const WebSourceBufferImpl&) = delete;
+ WebSourceBufferImpl& operator=(const WebSourceBufferImpl&) = delete;
+ ~WebSourceBufferImpl() override;
+
+ // WebSourceBuffer implementation.
+ void SetClient(WebSourceBufferClient* client) override;
+ bool GetGenerateTimestampsFlag() override;
+ bool SetMode(AppendMode mode) override;
+ WebTimeRanges Buffered() override;
+ double HighestPresentationTimestamp() override;
+ bool EvictCodedFrames(double currentPlaybackTime,
+ size_t newDataSize) override;
+ bool Append(const unsigned char* data,
+ unsigned length,
+ double* timestamp_offset) override;
+ bool AppendChunks(
+ std::unique_ptr<media::StreamParser::BufferQueue> buffer_queue,
+ double* timestamp_offset) override;
+ void ResetParserState() override;
+ void Remove(double start, double end) override;
+ bool CanChangeType(const WebString& content_type,
+ const WebString& codecs) override;
+ void ChangeType(const WebString& content_type,
+ const WebString& codecs) override;
+ bool SetTimestampOffset(double offset) override;
+ void SetAppendWindowStart(double start) override;
+ void SetAppendWindowEnd(double end) override;
+ void RemovedFromMediaSource() override;
+
+ private:
+ // Demuxer callback handler to process an initialization segment received
+ // during an append() call.
+ void InitSegmentReceived(std::unique_ptr<media::MediaTracks> tracks);
+
+ // Demuxer callback handler to notify Blink of a non-fatal parse warning.
+ void NotifyParseWarning(const media::SourceBufferParseWarning warning);
+
+ std::string id_;
+ media::ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl.
+
+ WebSourceBufferClient* client_;
+
+ // Controls the offset applied to timestamps when processing appended media
+ // segments. It is initially 0, which indicates that no offset is being
+ // applied. Both setTimestampOffset() and append() may update this value.
+ base::TimeDelta timestamp_offset_;
+
+ base::TimeDelta append_window_start_;
+ base::TimeDelta append_window_end_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_SOURCE_BUFFER_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
index fccef3ac5dc..6d073b4fe23 100644
--- a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check_op.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
@@ -34,6 +33,8 @@ class AutoTryLock {
public:
explicit AutoTryLock(base::Lock& lock)
: lock_(lock), acquired_(lock_.Try()) {}
+ AutoTryLock(const AutoTryLock&) = delete;
+ AutoTryLock& operator=(const AutoTryLock&) = delete;
bool locked() const { return acquired_; }
@@ -47,7 +48,6 @@ class AutoTryLock {
private:
base::Lock& lock_;
const bool acquired_;
- DISALLOW_COPY_AND_ASSIGN(AutoTryLock);
};
} // namespace
@@ -59,6 +59,8 @@ class WebAudioSourceProviderImpl::TeeFilter
: public AudioRendererSink::RenderCallback {
public:
TeeFilter() : copy_required_(false) {}
+ TeeFilter(const TeeFilter&) = delete;
+ TeeFilter& operator=(const TeeFilter&) = delete;
~TeeFilter() override = default;
void Initialize(AudioRendererSink::RenderCallback* renderer,
@@ -138,8 +140,6 @@ class WebAudioSourceProviderImpl::TeeFilter
std::atomic<bool> copy_required_;
base::Lock copy_lock_;
CopyAudioCB copy_audio_bus_callback_ GUARDED_BY(copy_lock_);
-
- DISALLOW_COPY_AND_ASSIGN(TeeFilter);
};
WebAudioSourceProviderImpl::WebAudioSourceProviderImpl(
@@ -204,15 +204,14 @@ void WebAudioSourceProviderImpl::SetClient(
void WebAudioSourceProviderImpl::ProvideInput(
const WebVector<float*>& audio_data,
- size_t number_of_frames) {
+ int number_of_frames) {
if (!bus_wrapper_ ||
static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) {
bus_wrapper_ =
media::AudioBus::CreateWrapper(static_cast<int>(audio_data.size()));
}
- const int incoming_number_of_frames = static_cast<int>(number_of_frames);
- bus_wrapper_->set_frames(incoming_number_of_frames);
+ bus_wrapper_->set_frames(number_of_frames);
for (size_t i = 0; i < audio_data.size(); ++i)
bus_wrapper_->SetChannelData(static_cast<int>(i), audio_data[i]);
@@ -245,8 +244,8 @@ void WebAudioSourceProviderImpl::ProvideInput(
return;
}
- if (frames < incoming_number_of_frames)
- bus_wrapper_->ZeroFramesPartial(frames, incoming_number_of_frames - frames);
+ if (frames < number_of_frames)
+ bus_wrapper_->ZeroFramesPartial(frames, number_of_frames - frames);
bus_wrapper_->Scale(volume_);
}
diff --git a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
index 73b9605df98..b769e2a1a58 100644
--- a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
@@ -5,7 +5,6 @@
#include <stddef.h>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "media/base/audio_parameters.h"
@@ -44,6 +43,10 @@ class WebAudioSourceProviderImplTest : public testing::Test,
mock_sink_(new media::MockAudioRendererSink()),
wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_, &media_log_)) {}
+ WebAudioSourceProviderImplTest(const WebAudioSourceProviderImplTest&) =
+ delete;
+ WebAudioSourceProviderImplTest& operator=(
+ const WebAudioSourceProviderImplTest&) = delete;
virtual ~WebAudioSourceProviderImplTest() = default;
void CallAllSinkMethodsAndVerify(bool verify) {
@@ -116,8 +119,6 @@ class WebAudioSourceProviderImplTest : public testing::Test,
scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_;
base::WeakPtrFactory<WebAudioSourceProviderImplTest> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest);
};
TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) {
diff --git a/chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h
index 8a710054a2c..d84ce981e08 100644
--- a/chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_VIDEO_CONFIGURATION_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_VIDEO_CONFIGURATION_H_
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/DEPS b/chromium/third_party/blink/renderer/platform/mediastream/DEPS
index df126aab3dc..fe894df7f8f 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/DEPS
+++ b/chromium/third_party/blink/renderer/platform/mediastream/DEPS
@@ -9,6 +9,7 @@ include_rules = [
"+base/atomicops.h",
"+media/base",
"+media/webrtc/audio_processor_controls.h",
+ "+media/webrtc/webrtc_switches.h",
"+third_party/blink/renderer/platform/audio",
"+third_party/blink/renderer/platform/heap",
"+third_party/blink/renderer/platform/peerconnection/rtc_api_name.h",
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h b/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h
index 0fcc05e36bd..435550fed82 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_AEC_DUMP_AGENT_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_AEC_DUMP_AGENT_IMPL_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/mojom/mediastream/aec_dump.mojom-blink.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -25,6 +24,8 @@ class PLATFORM_EXPORT AecDumpAgentImpl : public mojom::blink::AecDumpAgent {
// This may fail in unit tests, in which case a null object is returned.
static std::unique_ptr<AecDumpAgentImpl> Create(Delegate* delegate);
+ AecDumpAgentImpl(const AecDumpAgentImpl&) = delete;
+ AecDumpAgentImpl& operator=(const AecDumpAgentImpl&) = delete;
~AecDumpAgentImpl() override;
// AecDumpAgent methods:
@@ -38,8 +39,6 @@ class PLATFORM_EXPORT AecDumpAgentImpl : public mojom::blink::AecDumpAgent {
Delegate* delegate_;
mojo::Receiver<mojom::blink::AecDumpAgent> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(AecDumpAgentImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h
index b8cb825d720..8a535bbd0db 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h
@@ -32,6 +32,9 @@ template <typename Consumer>
class MediaStreamAudioDeliverer {
public:
MediaStreamAudioDeliverer() {}
+ MediaStreamAudioDeliverer(const MediaStreamAudioDeliverer&) = delete;
+ MediaStreamAudioDeliverer& operator=(const MediaStreamAudioDeliverer&) =
+ delete;
~MediaStreamAudioDeliverer() {}
// Returns the current audio parameters. These will be invalid before the
@@ -181,8 +184,6 @@ class MediaStreamAudioDeliverer {
// Specifies the current format of the audio passing through this
// MediaStreamAudioDeliverer.
media::AudioParameters params_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioDeliverer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_level_calculator.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_level_calculator.cc
index 5ed0f496f26..e74d9a82a5f 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_level_calculator.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_level_calculator.cc
@@ -8,7 +8,6 @@
#include <limits>
#include "base/check.h"
-#include "base/stl_util.h"
#include "media/base/audio_bus.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc
index 775efa706db..2a4238dd267 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc
@@ -8,19 +8,19 @@
#include <utility>
#include "base/feature_list.h"
-#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_util.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "build/chromecast_buildflags.h"
#include "media/base/audio_parameters.h"
+#include "media/webrtc/webrtc_switches.h"
+#include "third_party/webrtc/api/audio/echo_canceller3_config.h"
+#include "third_party/webrtc/api/audio/echo_canceller3_config_json.h"
+#include "third_party/webrtc/api/audio/echo_canceller3_factory.h"
#include "third_party/webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
-#include "third_party/webrtc/modules/audio_processing/typing_detection.h"
namespace blink {
namespace {
@@ -87,13 +87,86 @@ ClippingPredictor::Mode GetClippingPredictorMode(
}
}
+bool Allow48kHzApmProcessing() {
+ return base::FeatureList::IsEnabled(
+ ::features::kWebRtcAllow48kHzProcessingOnArm);
+}
+
+absl::optional<WebRtcHybridAgcParams> GetWebRtcHybridAgcParams() {
+ if (!base::FeatureList::IsEnabled(::features::kWebRtcHybridAgc)) {
+ return absl::nullopt;
+ }
+ return WebRtcHybridAgcParams{
+ .dry_run = base::GetFieldTrialParamByFeatureAsBool(
+ ::features::kWebRtcHybridAgc, "dry_run", false),
+ .vad_reset_period_ms = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcHybridAgc, "vad_reset_period_ms", 1500),
+ .adjacent_speech_frames_threshold =
+ base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcHybridAgc, "adjacent_speech_frames_threshold",
+ 12),
+ .max_gain_change_db_per_second =
+ static_cast<float>(base::GetFieldTrialParamByFeatureAsDouble(
+ ::features::kWebRtcHybridAgc, "max_gain_change_db_per_second",
+ 3)),
+ .max_output_noise_level_dbfs =
+ static_cast<float>(base::GetFieldTrialParamByFeatureAsDouble(
+ ::features::kWebRtcHybridAgc, "max_output_noise_level_dbfs",
+ -50)),
+ .sse2_allowed = base::GetFieldTrialParamByFeatureAsBool(
+ ::features::kWebRtcHybridAgc, "sse2_allowed", true),
+ .avx2_allowed = base::GetFieldTrialParamByFeatureAsBool(
+ ::features::kWebRtcHybridAgc, "avx2_allowed", true),
+ .neon_allowed = base::GetFieldTrialParamByFeatureAsBool(
+ ::features::kWebRtcHybridAgc, "neon_allowed", true)};
+}
+
+absl::optional<WebRtcAnalogAgcClippingControlParams>
+GetWebRtcAnalogAgcClippingControlParams() {
+ if (!base::FeatureList::IsEnabled(
+ ::features::kWebRtcAnalogAgcClippingControl)) {
+ return absl::nullopt;
+ }
+ return WebRtcAnalogAgcClippingControlParams{
+ .mode = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcAnalogAgcClippingControl, "mode", 0),
+ .window_length = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcAnalogAgcClippingControl, "window_length", 5),
+ .reference_window_length = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcAnalogAgcClippingControl,
+ "reference_window_length", 5),
+ .reference_window_delay = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcAnalogAgcClippingControl, "reference_window_delay",
+ 5),
+ .clipping_threshold =
+ static_cast<float>(base::GetFieldTrialParamByFeatureAsDouble(
+ ::features::kWebRtcAnalogAgcClippingControl, "clipping_threshold",
+ -1.0)),
+ .crest_factor_margin =
+ static_cast<float>(base::GetFieldTrialParamByFeatureAsDouble(
+ ::features::kWebRtcAnalogAgcClippingControl,
+ "crest_factor_margin", 3.0)),
+ .clipped_level_step = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcAnalogAgcClippingControl, "clipped_level_step",
+ 15),
+ .clipped_ratio_threshold =
+ static_cast<float>(base::GetFieldTrialParamByFeatureAsDouble(
+ ::features::kWebRtcAnalogAgcClippingControl,
+ "clipped_ratio_threshold", 0.1)),
+ .clipped_wait_frames = base::GetFieldTrialParamByFeatureAsInt(
+ ::features::kWebRtcAnalogAgcClippingControl, "clipped_wait_frames",
+ 300),
+ .use_predicted_step = base::GetFieldTrialParamByFeatureAsBool(
+ ::features::kWebRtcAnalogAgcClippingControl, "use_predicted_step",
+ true)};
+}
+
} // namespace
void AudioProcessingProperties::DisableDefaultProperties() {
echo_cancellation_type = EchoCancellationType::kEchoCancellationDisabled;
goog_auto_gain_control = false;
goog_experimental_echo_cancellation = false;
- goog_typing_noise_detection = false;
goog_noise_suppression = false;
goog_experimental_noise_suppression = false;
goog_highpass_filter = false;
@@ -121,7 +194,6 @@ bool AudioProcessingProperties::HasSameNonReconfigurableSettings(
goog_auto_gain_control == other.goog_auto_gain_control &&
goog_experimental_echo_cancellation ==
other.goog_experimental_echo_cancellation &&
- goog_typing_noise_detection == other.goog_typing_noise_detection &&
goog_noise_suppression == other.goog_noise_suppression &&
goog_experimental_noise_suppression ==
other.goog_experimental_noise_suppression &&
@@ -131,44 +203,30 @@ bool AudioProcessingProperties::HasSameNonReconfigurableSettings(
}
media::AudioProcessingSettings
-AudioProcessingProperties::ToAudioProcessingSettings() const {
+AudioProcessingProperties::ToAudioProcessingSettings(
+ bool multi_channel_capture_processing) const {
media::AudioProcessingSettings out;
- auto convert_type =
- [](EchoCancellationType type) -> media::EchoCancellationType {
- switch (type) {
- case EchoCancellationType::kEchoCancellationDisabled:
- return media::EchoCancellationType::kDisabled;
- case EchoCancellationType::kEchoCancellationAec3:
- return media::EchoCancellationType::kAec3;
- case EchoCancellationType::kEchoCancellationSystem:
- return media::EchoCancellationType::kSystemAec;
- }
- };
-
- out.echo_cancellation = convert_type(echo_cancellation_type);
+ out.echo_cancellation =
+ echo_cancellation_type == EchoCancellationType::kEchoCancellationAec3;
out.noise_suppression =
- goog_noise_suppression ? (goog_experimental_noise_suppression
- ? media::NoiseSuppressionType::kExperimental
- : media::NoiseSuppressionType::kDefault)
- : media::NoiseSuppressionType::kDisabled;
+ goog_noise_suppression && !system_noise_suppression_activated;
+ // TODO(https://bugs.webrtc.org/5298): Also toggle transient suppression when
+ // system effects are activated?
+ out.transient_noise_suppression = goog_experimental_noise_suppression;
+
out.automatic_gain_control =
- goog_auto_gain_control
- ? (goog_experimental_auto_gain_control
- ? media::AutomaticGainControlType::kExperimental
- : media::AutomaticGainControlType::kDefault)
- : media::AutomaticGainControlType::kDisabled;
+ goog_auto_gain_control && !system_gain_control_activated;
+ out.experimental_automatic_gain_control = goog_experimental_auto_gain_control;
+
out.high_pass_filter = goog_highpass_filter;
- out.typing_detection = goog_typing_noise_detection;
+ out.multi_channel_capture_processing = multi_channel_capture_processing;
+ out.stereo_mirroring = goog_audio_mirroring;
+ // TODO(https://crbug.com/1215061): Deprecate this behavior. The constraint is
+ // no longer meaningful, but sees significant usage, so some care is required.
+ out.force_apm_creation = goog_experimental_echo_cancellation;
return out;
}
-void EnableTypingDetection(AudioProcessing::Config* apm_config,
- webrtc::TypingDetection* typing_detector) {
- apm_config->voice_detection.enabled = true;
- // Configure the update period to 1s (100 * 10ms) in the typing detector.
- typing_detector->SetParameters(0, 0, 0, 0, 0, 100);
-}
-
void StartEchoCancellationDump(AudioProcessing* audio_processing,
base::File aec_dump_file,
rtc::TaskQueue* worker_queue) {
@@ -195,31 +253,23 @@ void StopEchoCancellationDump(AudioProcessing* audio_processing) {
// TODO(bugs.webrtc.org/7494): Remove unused cases, simplify decision logic.
void ConfigAutomaticGainControl(
- const AudioProcessingProperties& properties,
+ const media::AudioProcessingSettings& settings,
const absl::optional<WebRtcHybridAgcParams>& hybrid_agc_params,
const absl::optional<WebRtcAnalogAgcClippingControlParams>&
clipping_control_params,
absl::optional<double> compression_gain_db,
AudioProcessing::Config& apm_config) {
- // If system level gain control is activated, turn off all gain control
- // functionality in WebRTC.
- if (properties.system_gain_control_activated) {
- apm_config.gain_controller1.enabled = false;
- apm_config.gain_controller2.enabled = false;
- return;
- }
-
// The AGC2 fixed digital controller is always enabled when automatic gain
// control is enabled, the experimental analog AGC is disabled and a
// compression gain is specified.
// TODO(bugs.webrtc.org/7494): Remove this option since it makes no sense to
// run a fixed digital gain after AGC1 adaptive digital.
const bool use_fixed_digital_agc2 =
- properties.goog_auto_gain_control &&
- !properties.goog_experimental_auto_gain_control &&
+ settings.automatic_gain_control &&
+ !settings.experimental_automatic_gain_control &&
compression_gain_db.has_value();
const bool use_hybrid_agc = hybrid_agc_params.has_value();
- const bool agc1_enabled = properties.goog_auto_gain_control &&
+ const bool agc1_enabled = settings.automatic_gain_control &&
(use_hybrid_agc || !use_fixed_digital_agc2);
// Configure AGC1.
@@ -236,7 +286,7 @@ void ConfigAutomaticGainControl(
// Configure AGC2.
auto& agc2_config = apm_config.gain_controller2;
- if (properties.goog_experimental_auto_gain_control) {
+ if (settings.experimental_automatic_gain_control) {
// Experimental AGC is enabled. Hybrid AGC may or may not be enabled. Config
// AGC2 with adaptive mode and the given options, while ignoring
// `use_fixed_digital_agc2`.
@@ -302,6 +352,8 @@ void ConfigAutomaticGainControl(
clipping_control_params->clipping_threshold;
clipping_predictor->crest_factor_margin =
clipping_control_params->crest_factor_margin;
+ clipping_predictor->use_predicted_step =
+ clipping_control_params->use_predicted_step;
}
} else if (use_fixed_digital_agc2) {
// Experimental AGC is disabled, thus hybrid AGC is disabled. Config AGC2
@@ -314,7 +366,7 @@ void ConfigAutomaticGainControl(
void PopulateApmConfig(
AudioProcessing::Config* apm_config,
- const AudioProcessingProperties& properties,
+ const media::AudioProcessingSettings& settings,
const absl::optional<std::string>& audio_processing_platform_config_json,
absl::optional<double>* gain_control_compression_gain_db) {
// TODO(crbug.com/895814): When Chrome uses AGC2, handle all JSON config via
@@ -328,7 +380,7 @@ void PopulateApmConfig(
&noise_suppression_level);
}
- apm_config->high_pass_filter.enabled = properties.goog_highpass_filter;
+ apm_config->high_pass_filter.enabled = settings.high_pass_filter;
if (pre_amplifier_fixed_gain_factor.has_value()) {
apm_config->pre_amplifier.enabled = true;
@@ -336,23 +388,104 @@ void PopulateApmConfig(
pre_amplifier_fixed_gain_factor.value();
}
- DCHECK(!(!properties.goog_noise_suppression &&
- properties.system_noise_suppression_activated));
- if (properties.goog_noise_suppression &&
- !properties.system_noise_suppression_activated) {
- apm_config->noise_suppression.enabled = true;
- apm_config->noise_suppression.level =
- noise_suppression_level.value_or(NoiseSuppression::kHigh);
- }
+ apm_config->noise_suppression.enabled = settings.noise_suppression;
+ apm_config->noise_suppression.level =
+ noise_suppression_level.value_or(NoiseSuppression::kHigh);
- if (properties.EchoCancellationIsWebRtcProvided()) {
- apm_config->echo_canceller.enabled = true;
+ apm_config->echo_canceller.enabled = settings.echo_cancellation;
#if defined(OS_ANDROID)
- apm_config->echo_canceller.mobile_mode = true;
+ apm_config->echo_canceller.mobile_mode = true;
#else
- apm_config->echo_canceller.mobile_mode = false;
+ apm_config->echo_canceller.mobile_mode = false;
#endif
+}
+
+rtc::scoped_refptr<webrtc::AudioProcessing> CreateWebRtcAudioProcessingModule(
+ const media::AudioProcessingSettings& settings,
+ absl::optional<std::string> audio_processing_platform_config_json,
+ absl::optional<int> agc_startup_min_volume) {
+ // Experimental options provided at creation.
+ // TODO(https://bugs.webrtc.org/5298): Replace with equivalent settings in
+ // webrtc::AudioProcessing::Config.
+ webrtc::Config config;
+ config.Set<webrtc::ExperimentalNs>(
+ new webrtc::ExperimentalNs(settings.transient_noise_suppression));
+
+ // TODO(bugs.webrtc.org/7494): Move logic below in ConfigAutomaticGainControl.
+ // Retrieve the Hybrid AGC experiment parameters.
+ // The hybrid AGC setup, that is AGC1 analog and AGC2 adaptive digital,
+ // requires gain control including analog AGC to be active.
+ absl::optional<WebRtcHybridAgcParams> hybrid_agc_params;
+ absl::optional<WebRtcAnalogAgcClippingControlParams> clipping_control_params;
+ if (settings.automatic_gain_control &&
+ settings.experimental_automatic_gain_control) {
+ hybrid_agc_params = GetWebRtcHybridAgcParams();
+ clipping_control_params = GetWebRtcAnalogAgcClippingControlParams();
}
+ // If the analog AGC is enabled, check for overridden config params.
+ if (settings.experimental_automatic_gain_control) {
+ auto* experimental_agc = new webrtc::ExperimentalAgc(
+ /*enabled=*/true, agc_startup_min_volume.value_or(0));
+ // Disable the AGC1 adaptive digital controller if the hybrid AGC is enabled
+ // and it's not running in dry-run mode.
+ experimental_agc->digital_adaptive_disabled =
+ hybrid_agc_params.has_value() && !hybrid_agc_params->dry_run;
+ config.Set<webrtc::ExperimentalAgc>(experimental_agc);
+#if BUILDFLAG(IS_CHROMECAST)
+ } else {
+ // Do not use the analog controller.
+ // This should likely be done on non-Chromecast platforms as well, but care
+ // is needed since users may be relying on the current behavior.
+ // https://crbug.com/918677#c4
+ config.Set<webrtc::ExperimentalAgc>(
+ new webrtc::ExperimentalAgc(/*enabled=*/false));
+#endif // BUILDFLAG(IS_CHROMECAST)
+ }
+
+ // Create and configure the webrtc::AudioProcessing.
+ webrtc::AudioProcessingBuilder ap_builder;
+ if (settings.echo_cancellation) {
+ webrtc::EchoCanceller3Config aec3_config;
+ if (audio_processing_platform_config_json) {
+ aec3_config = webrtc::Aec3ConfigFromJsonString(
+ *audio_processing_platform_config_json);
+ bool config_parameters_already_valid =
+ webrtc::EchoCanceller3Config::Validate(&aec3_config);
+ RTC_DCHECK(config_parameters_already_valid);
+ }
+
+ ap_builder.SetEchoControlFactory(
+ std::unique_ptr<webrtc::EchoControlFactory>(
+ new webrtc::EchoCanceller3Factory(aec3_config)));
+ }
+ rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing_module =
+ ap_builder.Create(config);
+
+ webrtc::AudioProcessing::Config apm_config =
+ audio_processing_module->GetConfig();
+ apm_config.pipeline.multi_channel_render = true;
+ apm_config.pipeline.multi_channel_capture =
+ settings.multi_channel_capture_processing;
+
+ absl::optional<double> gain_control_compression_gain_db;
+ PopulateApmConfig(&apm_config, settings,
+ audio_processing_platform_config_json,
+ &gain_control_compression_gain_db);
+
+ // Set up gain control functionalities.
+ ConfigAutomaticGainControl(settings, hybrid_agc_params,
+ clipping_control_params,
+ gain_control_compression_gain_db, apm_config);
+
+ // Ensure that 48 kHz APM processing is always active. This overrules the
+ // default setting in WebRTC of 32 kHz for ARM platforms.
+ if (Allow48kHzApmProcessing()) {
+ apm_config.pipeline.maximum_internal_processing_rate = 48000;
+ }
+
+ apm_config.residual_echo_detector.enabled = false;
+ audio_processing_module->ApplyConfig(apm_config);
+ return audio_processing_module;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
index f3c8cdb1b56..41748e44c92 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
@@ -8,26 +8,13 @@
#include <string>
#include "base/files/file.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
#include "build/build_config.h"
-#include "media/base/audio_point.h"
#include "media/base/audio_processing.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/mediastream/media_stream_request.h"
-#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/webrtc/api/media_stream_interface.h"
-#include "third_party/webrtc/media/base/media_channel.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
#include "third_party/webrtc/rtc_base/task_queue.h"
-namespace webrtc {
-
-class TypingDetection;
-
-}
-
namespace blink {
using webrtc::AudioProcessing;
@@ -67,14 +54,13 @@ struct PLATFORM_EXPORT AudioProcessingProperties {
const AudioProcessingProperties& other) const;
// Converts this struct to an equivalent media::AudioProcessingSettings.
- // TODO(https://crbug.com/878757): Eliminate this class in favor of the media
- // one.
- media::AudioProcessingSettings ToAudioProcessingSettings() const;
+ media::AudioProcessingSettings ToAudioProcessingSettings(
+ bool multi_channel_capture_processing) const;
EchoCancellationType echo_cancellation_type =
EchoCancellationType::kEchoCancellationAec3;
// Indicates whether system-level gain control and noise suppression
- // functionalities are present that fill a role comparable to the browser
+ // functionalities are active that fill a role comparable to the browser
// counterparts.
bool system_gain_control_activated = false;
bool system_noise_suppression_activated = false;
@@ -89,23 +75,34 @@ struct PLATFORM_EXPORT AudioProcessingProperties {
bool goog_audio_mirroring = false;
bool goog_auto_gain_control = true;
+ // TODO(https://crbug.com/1215061): Deprecate this constraint. The flag no
+ // longer toggles meaningful processing effects, but it still forces the audio
+ // processing module to be created and used.
bool goog_experimental_echo_cancellation =
#if defined(OS_ANDROID)
false;
#else
true;
#endif
- bool goog_typing_noise_detection = false;
bool goog_noise_suppression = true;
+ // Experimental noise suppression maps to transient suppression (keytap
+ // removal).
bool goog_experimental_noise_suppression = true;
bool goog_highpass_filter = true;
+ // TODO(bugs.webrtc.org/7494): Effectively a no-op, remove this flag.
bool goog_experimental_auto_gain_control = true;
};
-// Enables the typing detection with the given detector.
-PLATFORM_EXPORT void EnableTypingDetection(
- AudioProcessing::Config* apm_config,
- webrtc::TypingDetection* typing_detector);
+// Creates and configures a webrtc::AudioProcessing audio processing module
+// (APM), based on the provided parameters. The optional parameters
+// |audio_processing_platform_config_json| and |agc_startup_min_volume| contain
+// specific parameter tunings provided by the platform. If possible, it is
+// preferred to instead use field trials for testing new parameter sets.
+PLATFORM_EXPORT rtc::scoped_refptr<AudioProcessing>
+CreateWebRtcAudioProcessingModule(
+ const media::AudioProcessingSettings& settings,
+ absl::optional<std::string> audio_processing_platform_config_json,
+ absl::optional<int> agc_startup_min_volume);
// Starts the echo cancellation dump in
// |audio_processing|. |worker_queue| must be kept alive until either
@@ -150,20 +147,17 @@ struct PLATFORM_EXPORT WebRtcAnalogAgcClippingControlParams {
int clipped_level_step;
float clipped_ratio_threshold;
int clipped_wait_frames;
+ bool use_predicted_step;
};
-// Changes the automatic gain control configuration in `apm_config` if
-// `properties.goog_auto_gain_control` or
-// `properties.goog_experimental_auto_gain_control` are true. If both are true
-// and `hybrid_agc_params` is specified, the hybrid AGC configuration will be
-// used - i.e., analog AGC1 and adaptive digital AGC2.
-// When `properties.goog_auto_gain_control` is true,
-// `properties.goog_experimental_auto_gain_control` is false and
-// `compression_gain_db` is specified, the AGC2 fixed digital controller is
-// enabled.
+// Configures automatic gain control in `apm_config`. If analog gain control is
+// enabled and `hybrid_agc_params` is specified, then the hybrid AGC
+// configuration will be used - i.e., analog AGC1 and adaptive digital AGC2.
+// When only digital gain control is enabled and `compression_gain_db` is
+// specified, the AGC2 fixed digital controller is enabled.
// TODO(bugs.webrtc.org/7494): Clean up once hybrid AGC experiment finalized.
PLATFORM_EXPORT void ConfigAutomaticGainControl(
- const AudioProcessingProperties& properties,
+ const media::AudioProcessingSettings& settings,
const absl::optional<WebRtcHybridAgcParams>& hybrid_agc_params,
const absl::optional<WebRtcAnalogAgcClippingControlParams>&
clipping_control_params,
@@ -172,7 +166,7 @@ PLATFORM_EXPORT void ConfigAutomaticGainControl(
PLATFORM_EXPORT void PopulateApmConfig(
AudioProcessing::Config* apm_config,
- const AudioProcessingProperties& properties,
+ const media::AudioProcessingSettings& settings,
const absl::optional<std::string>& audio_processing_platform_config_json,
absl::optional<double>* gain_control_compression_gain_db);
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc
index a552b77939c..63f34ecd60f 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc
@@ -24,17 +24,17 @@ constexpr WebRtcHybridAgcParams kHybridAgcParams{
.avx2_allowed = true,
.neon_allowed = true};
-constexpr AudioProcessingProperties kAudioProcessingNoAgc{
- .goog_auto_gain_control = false,
- .goog_experimental_auto_gain_control = false};
+constexpr media::AudioProcessingSettings kAudioProcessingNoAgc{
+ .automatic_gain_control = false,
+ .experimental_automatic_gain_control = false};
-constexpr AudioProcessingProperties kAudioProcessingNoExperimentalAgc{
- .goog_auto_gain_control = true,
- .goog_experimental_auto_gain_control = false};
+constexpr media::AudioProcessingSettings kAudioProcessingNoExperimentalAgc{
+ .automatic_gain_control = true,
+ .experimental_automatic_gain_control = false};
-constexpr AudioProcessingProperties kAudioProcessingExperimentalAgc{
- .goog_auto_gain_control = true,
- .goog_experimental_auto_gain_control = true};
+constexpr media::AudioProcessingSettings kAudioProcessingExperimentalAgc{
+ .automatic_gain_control = true,
+ .experimental_automatic_gain_control = true};
constexpr double kCompressionGainDb = 10.0;
@@ -47,7 +47,8 @@ constexpr WebRtcAnalogAgcClippingControlParams kClippingControlParams{
.crest_factor_margin = 5.55f,
.clipped_level_step = 666,
.clipped_ratio_threshold = 0.777f,
- .clipped_wait_frames = 300};
+ .clipped_wait_frames = 300,
+ .use_predicted_step = true};
} // namespace
TEST(ConfigAutomaticGainControlTest, DoNotChangeApmConfig) {
@@ -68,20 +69,6 @@ TEST(ConfigAutomaticGainControlTest, DoNotChangeApmConfig) {
EXPECT_EQ(apm_config.gain_controller2, kDefaultConfig.gain_controller2);
}
-TEST(ConfigAutomaticGainControlTest, SystemAgcDeactivatesBrowserAgcs) {
- webrtc::AudioProcessing::Config apm_config;
- constexpr AudioProcessingProperties kProperties{
- .system_gain_control_activated = true,
- .goog_auto_gain_control = true,
- .goog_experimental_auto_gain_control = true};
-
- ConfigAutomaticGainControl(kProperties, kHybridAgcParams,
- kClippingControlParams,
- /*compression_gain_db=*/10.0, apm_config);
- EXPECT_FALSE(apm_config.gain_controller1.enabled);
- EXPECT_FALSE(apm_config.gain_controller2.enabled);
-}
-
TEST(ConfigAutomaticGainControlTest, EnableDefaultAGC1) {
webrtc::AudioProcessing::Config apm_config;
@@ -187,15 +174,17 @@ TEST(ConfigAutomaticGainControlTest, EnableClippingControl) {
kClippingControlParams.clipping_threshold);
EXPECT_FLOAT_EQ(clipping_predictor.crest_factor_margin,
kClippingControlParams.crest_factor_margin);
+ EXPECT_EQ(clipping_predictor.use_predicted_step,
+ kClippingControlParams.use_predicted_step);
}
TEST(PopulateApmConfigTest, DefaultWithoutConfigJson) {
webrtc::AudioProcessing::Config apm_config;
- const AudioProcessingProperties properties;
+ const media::AudioProcessingSettings settings;
absl::optional<double> gain_control_compression_gain_db;
- PopulateApmConfig(&apm_config, properties,
- absl::nullopt, // |audio_processing_platform_config_json|.
+ PopulateApmConfig(&apm_config, settings,
+ /*audio_processing_platform_config_json=*/absl::nullopt,
&gain_control_compression_gain_db);
EXPECT_FALSE(gain_control_compression_gain_db.has_value());
EXPECT_TRUE(apm_config.high_pass_filter.enabled);
@@ -214,13 +203,13 @@ TEST(PopulateApmConfigTest, DefaultWithoutConfigJson) {
TEST(PopulateApmConfigTest, SetGainsInConfigJson) {
webrtc::AudioProcessing::Config apm_config;
- const AudioProcessingProperties properties;
+ const media::AudioProcessingSettings settings;
absl::optional<std::string> audio_processing_platform_config_json =
"{\"gain_control_compression_gain_db\": 10, "
"\"pre_amplifier_fixed_gain_factor\": 2.0}";
absl::optional<double> gain_control_compression_gain_db;
- PopulateApmConfig(&apm_config, properties,
+ PopulateApmConfig(&apm_config, settings,
audio_processing_platform_config_json,
&gain_control_compression_gain_db);
EXPECT_TRUE(gain_control_compression_gain_db.has_value());
@@ -242,12 +231,12 @@ TEST(PopulateApmConfigTest, SetGainsInConfigJson) {
TEST(PopulateApmConfigTest, SetNoiseSuppressionLevelInConfigJson) {
webrtc::AudioProcessing::Config apm_config;
- const AudioProcessingProperties properties;
+ const media::AudioProcessingSettings settings;
absl::optional<std::string> audio_processing_platform_config_json =
"{\"noise_suppression_level\": 3}";
absl::optional<double> gain_control_compression_gain_db;
- PopulateApmConfig(&apm_config, properties,
+ PopulateApmConfig(&apm_config, settings,
audio_processing_platform_config_json,
&gain_control_compression_gain_db);
EXPECT_FALSE(gain_control_compression_gain_db.has_value());
@@ -265,28 +254,286 @@ TEST(PopulateApmConfigTest, SetNoiseSuppressionLevelInConfigJson) {
apm_config.echo_canceller.mobile_mode);
}
-TEST(PopulateApmConfigTest, SystemNsDeactivatesBrowserNs) {
- absl::optional<double> gain_control_compression_gain_db;
+TEST(CreateWebRtcAudioProcessingModuleTest, SetGainsInConfigJson) {
+ const media::AudioProcessingSettings settings{
+ .automatic_gain_control = true,
+ .experimental_automatic_gain_control = false};
+ absl::optional<std::string> audio_processing_platform_config_json =
+ "{\"gain_control_compression_gain_db\": 12.1212, "
+ "\"pre_amplifier_fixed_gain_factor\": 2.345}";
+
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings, audio_processing_platform_config_json,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+ // Pre-amplifier is enabled if a gain factor is specified.
+ EXPECT_TRUE(config.pre_amplifier.enabled);
+ EXPECT_FLOAT_EQ(config.pre_amplifier.fixed_gain_factor, 2.345);
+
+ // Fixed digital AGC2 is enabled if AGC is on, analog AGC is off, and a
+ // compression gain is specified.
+ EXPECT_TRUE(config.gain_controller2.enabled);
+ EXPECT_FALSE(config.gain_controller2.adaptive_digital.enabled);
+ EXPECT_FLOAT_EQ(config.gain_controller2.fixed_digital.gain_db, 12.1212);
+}
- // Verify that the default value of `noise_suppression.enabled`
- // is true, since otherwise this test does not work.
- AudioProcessingProperties properties_without_system_ns;
- properties_without_system_ns.system_noise_suppression_activated = false;
- webrtc::AudioProcessing::Config apm_config_without_system_ns;
- PopulateApmConfig(&apm_config_without_system_ns, properties_without_system_ns,
- /*audio_processing_platform_config_json=*/absl::nullopt,
- &gain_control_compression_gain_db);
- EXPECT_TRUE(apm_config_without_system_ns.noise_suppression.enabled);
-
- // Verify that the presence of a system noise suppressor deactivates the
- // browser counterpart.
- AudioProcessingProperties properties_with_system_ns;
- properties_with_system_ns.system_noise_suppression_activated = true;
- webrtc::AudioProcessing::Config apm_config_with_system_ns;
- PopulateApmConfig(&apm_config_with_system_ns, properties_with_system_ns,
- /*audio_processing_platform_config_json=*/absl::nullopt,
- &gain_control_compression_gain_db);
- EXPECT_FALSE(apm_config_with_system_ns.noise_suppression.enabled);
+TEST(CreateWebRtcAudioProcessingModuleTest,
+ SetNoiseSuppressionLevelInConfigJson) {
+ const media::AudioProcessingSettings settings{.noise_suppression = true};
+ absl::optional<std::string> audio_processing_platform_config_json =
+ "{\"noise_suppression_level\": 3}";
+
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings, audio_processing_platform_config_json,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+ EXPECT_TRUE(config.noise_suppression.enabled);
+ EXPECT_EQ(config.noise_suppression.level,
+ webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh);
+}
+
+// Verify the default audio processing effects.
+TEST(CreateWebRtcAudioProcessingModuleTest, VerifyDefaultProperties) {
+ const AudioProcessingProperties properties;
+ const media::AudioProcessingSettings settings =
+ properties.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings,
+ /*audio_processing_platform_config_json=*/absl::nullopt,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+ EXPECT_TRUE(config.pipeline.multi_channel_render);
+ EXPECT_TRUE(config.pipeline.multi_channel_capture);
+ EXPECT_EQ(config.pipeline.maximum_internal_processing_rate, 48000);
+ EXPECT_TRUE(config.high_pass_filter.enabled);
+ EXPECT_TRUE(config.echo_canceller.enabled);
+ EXPECT_TRUE(config.gain_controller1.enabled);
+ EXPECT_TRUE(config.gain_controller1.analog_gain_controller.enabled);
+ EXPECT_FALSE(config.gain_controller2.enabled);
+ EXPECT_TRUE(config.noise_suppression.enabled);
+ EXPECT_FALSE(config.voice_detection.enabled);
+ EXPECT_FALSE(config.residual_echo_detector.enabled);
+
+#if defined(OS_ANDROID)
+ // Android uses echo cancellation optimized for mobiles, and does not
+ // support keytap suppression.
+ EXPECT_TRUE(config.echo_canceller.mobile_mode);
+ EXPECT_FALSE(config.transient_suppression.enabled);
+#else
+ EXPECT_FALSE(config.echo_canceller.mobile_mode);
+ EXPECT_TRUE(config.transient_suppression.enabled);
+#endif
+}
+
+TEST(CreateWebRtcAudioProcessingModuleTest, VerifyNoiseSuppressionSettings) {
+ for (bool ns_enabled : {true, false}) {
+ const media::AudioProcessingSettings settings{.noise_suppression =
+ ns_enabled};
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings,
+ /*audio_processing_platform_config_json=*/absl::nullopt,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+ EXPECT_EQ(config.noise_suppression.enabled, ns_enabled);
+ EXPECT_EQ(config.noise_suppression.level,
+ webrtc::AudioProcessing::Config::NoiseSuppression::kHigh);
+ }
+}
+
+TEST(CreateWebRtcAudioProcessingModuleTest, VerifyEchoCancellerSettings) {
+ for (bool ec_enabled : {true, false}) {
+ const media::AudioProcessingSettings settings{.echo_cancellation =
+ ec_enabled};
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings,
+ /*audio_processing_platform_config_json=*/absl::nullopt,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+ EXPECT_EQ(config.echo_canceller.enabled, ec_enabled);
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(config.echo_canceller.mobile_mode);
+#else
+ EXPECT_FALSE(config.echo_canceller.mobile_mode);
+#endif
+ }
+}
+
+TEST(CreateWebRtcAudioProcessingModuleTest, ToggleHighPassFilter) {
+ for (bool high_pass_filter_enabled : {true, false}) {
+ const media::AudioProcessingSettings settings{.high_pass_filter =
+ high_pass_filter_enabled};
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings,
+ /*audio_processing_platform_config_json=*/absl::nullopt,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+ EXPECT_EQ(config.high_pass_filter.enabled, high_pass_filter_enabled);
+ }
+}
+
+TEST(CreateWebRtcAudioProcessingModuleTest, ToggleTransientSuppression) {
+ for (bool transient_suppression_enabled : {true, false}) {
+ const media::AudioProcessingSettings settings{
+ .transient_noise_suppression = transient_suppression_enabled};
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings,
+ /*audio_processing_platform_config_json=*/absl::nullopt,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+ EXPECT_EQ(config.transient_suppression.enabled,
+ transient_suppression_enabled);
+#else
+ // Transient suppression is not supported (nor useful) on mobile platforms.
+ EXPECT_FALSE(config.transient_suppression.enabled);
+#endif
+ }
+}
+
+// There is no way to test what echo cancellation configuration is applied, but
+// this test at least exercises the code that handles echo cancellation
+// configuration from JSON.
+TEST(CreateWebRtcAudioProcessingModuleTest,
+ ApplyEchoCancellationConfigFromJson) {
+ // Arbitrary settings to have something to parse.
+ absl::optional<std::string> audio_processing_platform_config_json =
+ "{\"aec3\": {"
+ "\"comfort_noise\": {\"noise_floor_dbfs\": -123.4567},"
+ "\"echo_model\": {\"min_noise_floor_power\": 1234567.8},"
+ "},}";
+ const media::AudioProcessingSettings settings{.echo_cancellation = true};
+ rtc::scoped_refptr<webrtc::AudioProcessing> apm =
+ CreateWebRtcAudioProcessingModule(
+ settings, audio_processing_platform_config_json,
+ /*agc_startup_min_volume=*/absl::nullopt);
+ ASSERT_TRUE(!!apm);
+ webrtc::AudioProcessing::Config config = apm->GetConfig();
+ EXPECT_TRUE(config.echo_canceller.enabled);
+}
+
+TEST(AudioProcessingPropertiesToAudioProcessingSettingsTest,
+ DefaultPropertiesAndSettingsMatch) {
+ const media::AudioProcessingSettings default_settings;
+ AudioProcessingProperties properties;
+ const media::AudioProcessingSettings generated_settings =
+ properties.ToAudioProcessingSettings(
+ default_settings.multi_channel_capture_processing);
+ EXPECT_EQ(default_settings, generated_settings);
+}
+
+TEST(AudioProcessingPropertiesToAudioProcessingSettingsTest,
+ DisableDefaultProperties) {
+ AudioProcessingProperties properties;
+ properties.DisableDefaultProperties();
+ const media::AudioProcessingSettings settings =
+ properties.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_FALSE(settings.echo_cancellation);
+ EXPECT_FALSE(settings.noise_suppression);
+ EXPECT_FALSE(settings.transient_noise_suppression);
+ EXPECT_FALSE(settings.automatic_gain_control);
+ EXPECT_FALSE(settings.experimental_automatic_gain_control);
+ EXPECT_FALSE(settings.high_pass_filter);
+ EXPECT_FALSE(settings.stereo_mirroring);
+ EXPECT_FALSE(settings.force_apm_creation);
+}
+
+TEST(AudioProcessingPropertiesToAudioProcessingSettingsTest,
+ AllBrowserPropertiesEnabled) {
+ const AudioProcessingProperties properties{
+ .echo_cancellation_type = AudioProcessingProperties::
+ EchoCancellationType::kEchoCancellationAec3,
+ .goog_audio_mirroring = true,
+ .goog_auto_gain_control = true,
+ .goog_experimental_echo_cancellation = true,
+ .goog_noise_suppression = true,
+ .goog_experimental_noise_suppression = true,
+ .goog_highpass_filter = true,
+ .goog_experimental_auto_gain_control = true};
+ const media::AudioProcessingSettings settings =
+ properties.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_TRUE(settings.echo_cancellation);
+ EXPECT_TRUE(settings.noise_suppression);
+ EXPECT_TRUE(settings.transient_noise_suppression);
+ EXPECT_TRUE(settings.automatic_gain_control);
+ EXPECT_TRUE(settings.experimental_automatic_gain_control);
+ EXPECT_TRUE(settings.high_pass_filter);
+ EXPECT_TRUE(settings.stereo_mirroring);
+ EXPECT_TRUE(settings.force_apm_creation);
+}
+
+TEST(AudioProcessingPropertiesToAudioProcessingSettingsTest,
+ SystemAecDisablesBrowserAec) {
+ AudioProcessingProperties properties{
+ .echo_cancellation_type = AudioProcessingProperties::
+ EchoCancellationType::kEchoCancellationSystem};
+ media::AudioProcessingSettings settings =
+ properties.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_FALSE(settings.echo_cancellation);
+}
+
+TEST(AudioProcessingPropertiesToAudioProcessingSettingsTest,
+ SystemNsDeactivatesBrowserNs) {
+ // Verify that noise suppression is by default enabled, since otherwise this
+ // test does not work.
+ constexpr AudioProcessingProperties kPropertiesWithoutSystemNs{
+ .system_noise_suppression_activated = false};
+ media::AudioProcessingSettings settings_without_system_ns =
+ kPropertiesWithoutSystemNs.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_TRUE(settings_without_system_ns.noise_suppression);
+
+ constexpr AudioProcessingProperties kPropertiesWithSystemNs{
+ .system_noise_suppression_activated = true};
+ media::AudioProcessingSettings settings_with_system_ns =
+ kPropertiesWithSystemNs.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_FALSE(settings_with_system_ns.noise_suppression);
+}
+
+TEST(AudioProcessingPropertiesToAudioProcessingSettingsTest,
+ SystemAgcDeactivatesBrowserAgc) {
+ // Verify that gain control is by default enabled, since otherwise this test
+ // does not work.
+ constexpr AudioProcessingProperties kPropertiesWithoutSystemAgc{
+ .system_gain_control_activated = false};
+ media::AudioProcessingSettings settings_without_system_agc =
+ kPropertiesWithoutSystemAgc.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_TRUE(settings_without_system_agc.automatic_gain_control);
+
+ constexpr AudioProcessingProperties kPropertiesWithSystemAgc{
+ .system_gain_control_activated = true};
+ media::AudioProcessingSettings settings_with_system_agc =
+ kPropertiesWithSystemAgc.ToAudioProcessingSettings(
+ /*multi_channel_capture_processing=*/true);
+ EXPECT_FALSE(settings_with_system_agc.automatic_gain_control);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
index cbfe7b887c7..d6744122379 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
@@ -43,10 +43,10 @@ MediaStreamAudioSource::MediaStreamAudioSource(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
bool is_local_source,
bool disable_local_echo)
- : is_local_source_(is_local_source),
+ : WebPlatformMediaStreamSource(std::move(task_runner)),
+ is_local_source_(is_local_source),
disable_local_echo_(disable_local_echo),
- is_stopped_(false),
- task_runner_(std::move(task_runner)) {
+ is_stopped_(false) {
LogMessage(
base::StringPrintf("%s({is_local_source=%s}, {disable_local_echo=%s})",
__func__, is_local_source ? "local" : "remote",
@@ -61,7 +61,7 @@ MediaStreamAudioSource::MediaStreamAudioSource(
false /* disable_local_echo */) {}
MediaStreamAudioSource::~MediaStreamAudioSource() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
}
// static
@@ -74,7 +74,7 @@ MediaStreamAudioSource* MediaStreamAudioSource::From(
}
bool MediaStreamAudioSource::ConnectToTrack(MediaStreamComponent* component) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DCHECK(component);
// Sanity-check that there is not already a MediaStreamAudioTrack instance
@@ -125,12 +125,12 @@ media::AudioParameters MediaStreamAudioSource::GetAudioParameters() const {
}
bool MediaStreamAudioSource::RenderToAssociatedSinkEnabled() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return device().matched_output_device_id.has_value();
}
bool MediaStreamAudioSource::AllTracksAreDisabled() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
unsigned int num_disabled_tracks = 0;
Vector<MediaStreamAudioTrack*> audio_tracks;
@@ -178,7 +178,7 @@ bool MediaStreamAudioSource::HasSameNonReconfigurableSettings(
void MediaStreamAudioSource::DoChangeSource(
const MediaStreamDevice& new_device) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (is_stopped_)
return;
@@ -188,7 +188,7 @@ void MediaStreamAudioSource::DoChangeSource(
std::unique_ptr<MediaStreamAudioTrack>
MediaStreamAudioSource::CreateMediaStreamAudioTrack(const std::string& id) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
LogMessage(base::StringPrintf("%s({id=%s}, {is_local_source=%s})", __func__,
id.c_str(),
is_local_source() ? "local" : "remote"));
@@ -196,19 +196,19 @@ MediaStreamAudioSource::CreateMediaStreamAudioTrack(const std::string& id) {
}
bool MediaStreamAudioSource::EnsureSourceIsStarted() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DVLOG(1) << "MediaStreamAudioSource@" << this << "::EnsureSourceIsStarted()";
return true;
}
void MediaStreamAudioSource::EnsureSourceIsStopped() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DVLOG(1) << "MediaStreamAudioSource@" << this << "::EnsureSourceIsStopped()";
}
void MediaStreamAudioSource::ChangeSourceImpl(
const MediaStreamDevice& new_device) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DVLOG(1) << "MediaStreamAudioSource@" << this << "::ChangeSourceImpl()";
NOTIMPLEMENTED();
}
@@ -228,14 +228,14 @@ void MediaStreamAudioSource::DeliverDataToTracks(
}
void MediaStreamAudioSource::DoStopSource() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
LogMessage(base::StringPrintf("%s()", __func__));
EnsureSourceIsStopped();
is_stopped_ = true;
}
void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
const bool did_remove_last_track = deliverer_.RemoveConsumer(track);
LogMessage(
base::StringPrintf("%s => (removed MediaStreamAudioTrack as consumer, "
@@ -258,7 +258,7 @@ void MediaStreamAudioSource::StopSourceOnError(
// Stop source when error occurs.
PostCrossThreadTask(
- *task_runner_, FROM_HERE,
+ *GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(
&MediaStreamAudioSource::StopSourceOnErrorOnTaskRunner, GetWeakPtr(),
code));
@@ -266,7 +266,7 @@ void MediaStreamAudioSource::StopSourceOnError(
void MediaStreamAudioSource::StopSourceOnErrorOnTaskRunner(
media::AudioCapturerSource::ErrorCode code) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
SetErrorCode(code);
StopSource();
}
@@ -275,21 +275,17 @@ void MediaStreamAudioSource::SetMutedState(bool muted_state) {
LogMessage(base::StringPrintf("%s({muted_state=%s})", __func__,
muted_state ? "true" : "false"));
PostCrossThreadTask(
- *task_runner_, FROM_HERE,
+ *GetTaskRunner(), FROM_HERE,
WTF::CrossThreadBindOnce(&WebPlatformMediaStreamSource::SetSourceMuted,
GetWeakPtr(), muted_state));
}
-base::SingleThreadTaskRunner* MediaStreamAudioSource::GetTaskRunner() const {
- return task_runner_.get();
-}
-
int MediaStreamAudioSource::NumPreferredChannels() const {
return deliverer_.NumPreferredChannels();
}
int MediaStreamAudioSource::NumConsumers() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
Vector<MediaStreamAudioTrack*> audio_tracks;
deliverer_.GetConsumerList(&audio_tracks);
return static_cast<int>(audio_tracks.size());
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
index ce0ba793085..66912cb8543 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
@@ -9,7 +9,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "media/base/audio_capturer_source.h"
#include "media/base/limits.h"
@@ -70,6 +69,8 @@ class PLATFORM_EXPORT MediaStreamAudioSource
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
bool is_local_source,
bool disable_local_echo);
+ MediaStreamAudioSource(const MediaStreamAudioSource&) = delete;
+ MediaStreamAudioSource& operator=(const MediaStreamAudioSource&) = delete;
~MediaStreamAudioSource() override;
// Returns the MediaStreamAudioSource instance owned by the given blink
@@ -129,7 +130,7 @@ class PLATFORM_EXPORT MediaStreamAudioSource
}
absl::optional<media::AudioCapturerSource::ErrorCode> ErrorCode() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return error_code_;
}
@@ -181,9 +182,6 @@ class PLATFORM_EXPORT MediaStreamAudioSource
// Sets muted state and notifies it to all registered tracks.
void SetMutedState(bool state);
- // Gets the TaskRunner for the main thread, for subclasses that need it.
- base::SingleThreadTaskRunner* GetTaskRunner() const;
-
// Maximum number of channels preferred by any connected track or -1 if
// unknown.
int NumPreferredChannels() const;
@@ -204,7 +202,7 @@ class PLATFORM_EXPORT MediaStreamAudioSource
void LogMessage(const std::string& message);
void SetErrorCode(media::AudioCapturerSource::ErrorCode code) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
error_code_ = code;
}
@@ -225,19 +223,12 @@ class PLATFORM_EXPORT MediaStreamAudioSource
// Manages tracks connected to this source and the audio format and data flow.
MediaStreamAudioDeliverer<MediaStreamAudioTrack> deliverer_;
- // The task runner for main thread. Also used to check that all methods that
- // could cause object graph or data flow changes are being called on the main
- // thread.
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
// Code set if this source was closed due to an error.
absl::optional<media::AudioCapturerSource::ErrorCode> error_code_;
// Provides weak pointers so that MediaStreamAudioTracks won't call
// StopAudioDeliveryTo() if this instance dies first.
base::WeakPtrFactory<MediaStreamAudioSource> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_test.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_test.cc
index 451cc4ce0b1..54e23b067c8 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_test.cc
@@ -36,8 +36,8 @@ constexpr int kMaxValueSafelyConvertableToFloat = 1 << 24;
// emits audio samples with monotonically-increasing sample values. Includes
// hooks for the unit tests to confirm lifecycle status and to change audio
// format.
-class FakeMediaStreamAudioSource : public MediaStreamAudioSource,
- public base::PlatformThread::Delegate {
+class FakeMediaStreamAudioSource final : public MediaStreamAudioSource,
+ public base::PlatformThread::Delegate {
public:
FakeMediaStreamAudioSource()
: MediaStreamAudioSource(scheduler::GetSingleThreadTaskRunnerForTesting(),
@@ -47,7 +47,11 @@ class FakeMediaStreamAudioSource : public MediaStreamAudioSource,
next_buffer_size_(kBufferSize),
sample_count_(0) {}
- ~FakeMediaStreamAudioSource() final {
+ FakeMediaStreamAudioSource(const FakeMediaStreamAudioSource&) = delete;
+ FakeMediaStreamAudioSource& operator=(const FakeMediaStreamAudioSource&) =
+ delete;
+
+ ~FakeMediaStreamAudioSource() override {
DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
EnsureSourceIsStopped();
}
@@ -123,15 +127,13 @@ class FakeMediaStreamAudioSource : public MediaStreamAudioSource,
base::subtle::Atomic32 next_buffer_size_;
std::unique_ptr<media::AudioBus> audio_bus_;
int sample_count_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeMediaStreamAudioSource);
};
// A simple WebMediaStreamAudioSink that consumes audio and confirms the
// sample values. Includes hooks for the unit tests to monitor the format and
// flow of audio, whether the audio is silent, and the propagation of the
// "enabled" state.
-class FakeMediaStreamAudioSink : public WebMediaStreamAudioSink {
+class FakeMediaStreamAudioSink final : public WebMediaStreamAudioSink {
public:
enum EnableState { NO_ENABLE_NOTIFICATION, WAS_ENABLED, WAS_DISABLED };
@@ -143,7 +145,10 @@ class FakeMediaStreamAudioSink : public WebMediaStreamAudioSink {
was_ended_(false),
enable_state_(NO_ENABLE_NOTIFICATION) {}
- ~FakeMediaStreamAudioSink() final {
+ FakeMediaStreamAudioSink(const FakeMediaStreamAudioSink&) = delete;
+ FakeMediaStreamAudioSink& operator=(const FakeMediaStreamAudioSink&) = delete;
+
+ ~FakeMediaStreamAudioSink() override {
DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
}
@@ -232,8 +237,6 @@ class FakeMediaStreamAudioSink : public WebMediaStreamAudioSink {
base::subtle::Atomic32 audio_is_silent_;
bool was_ended_;
EnableState enable_state_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeMediaStreamAudioSink);
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
index 13cd2570b7c..ba3f5edaf37 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
@@ -20,22 +20,19 @@ namespace blink {
namespace {
-void SendLogMessage(const std::string& message) {
- blink::WebRtcLogMessage("MSAT::" + message);
-}
+constexpr char kTag[] = "MSAT::";
} // namespace
MediaStreamAudioTrack::MediaStreamAudioTrack(bool is_local_track)
: MediaStreamTrackPlatform(is_local_track), is_enabled_(1) {
- SendLogMessage(
- base::StringPrintf("MediaStreamAudioTrack([this=%p] {is_local_track=%s})",
- this, (is_local_track ? "true" : "false")));
+ WebRtcLog(kTag, this, "%s({is_local_track=%s})", __func__,
+ (is_local_track ? "true" : "false"));
}
MediaStreamAudioTrack::~MediaStreamAudioTrack() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SendLogMessage(base::StringPrintf("~MediaStreamAudioTrack([this=%p])", this));
+ WebRtcLog(kTag, this, "%s()", __func__);
Stop();
}
@@ -51,7 +48,7 @@ MediaStreamAudioTrack* MediaStreamAudioTrack::From(
void MediaStreamAudioTrack::AddSink(WebMediaStreamAudioSink* sink) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SendLogMessage(base::StringPrintf("AddSink([this=%p])", this));
+ WebRtcLog(kTag, this, "%s()", __func__);
// If the track has already stopped, just notify the sink of this fact without
// adding it.
@@ -66,7 +63,7 @@ void MediaStreamAudioTrack::AddSink(WebMediaStreamAudioSink* sink) {
void MediaStreamAudioTrack::RemoveSink(WebMediaStreamAudioSink* sink) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SendLogMessage(base::StringPrintf("RemoveSink([this=%p])", this));
+ WebRtcLog(kTag, this, "%s()", __func__);
deliverer_.RemoveConsumer(sink);
}
@@ -76,8 +73,8 @@ media::AudioParameters MediaStreamAudioTrack::GetOutputFormat() const {
void MediaStreamAudioTrack::SetEnabled(bool enabled) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SendLogMessage(base::StringPrintf("SetEnabled([this=%p] {enabled=%s})", this,
- (enabled ? "true" : "false")));
+ WebRtcLog(kTag, this, "%s({enabled=%s})", __func__,
+ (enabled ? "true" : "false"));
const bool previously_enabled =
!!base::subtle::NoBarrier_AtomicExchange(&is_enabled_, enabled ? 1 : 0);
@@ -117,13 +114,13 @@ void MediaStreamAudioTrack::Start(base::OnceClosure stop_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!stop_callback.is_null());
DCHECK(stop_callback_.is_null());
- SendLogMessage(base::StringPrintf("Start([this=%p])", this));
+ WebRtcLog(kTag, this, "%s()", __func__);
stop_callback_ = std::move(stop_callback);
}
void MediaStreamAudioTrack::StopAndNotify(base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SendLogMessage(base::StringPrintf("StopAndNotify([this=%p])", this));
+ WebRtcLog(kTag, this, "%s()", __func__);
if (!stop_callback_.is_null())
std::move(stop_callback_).Run();
@@ -141,9 +138,8 @@ void MediaStreamAudioTrack::StopAndNotify(base::OnceClosure callback) {
}
void MediaStreamAudioTrack::OnSetFormat(const media::AudioParameters& params) {
- SendLogMessage(base::StringPrintf("OnSetFormat([this=%p] {params: [%s]})",
- this,
- params.AsHumanReadableString().c_str()));
+ WebRtcLog(kTag, this, "%s({params: [%s]})", __func__,
+ params.AsHumanReadableString().c_str());
deliverer_.OnSetFormat(params);
}
@@ -156,8 +152,8 @@ void MediaStreamAudioTrack::OnData(const media::AudioBus& audio_bus,
if (!received_audio_callback_) {
// Add log message with unique this pointer id to mark the audio track as
// alive at the first data callback.
- SendLogMessage(base::StringPrintf(
- "OnData([this=%p] => (audio track is alive))", this));
+
+ WebRtcLog(kTag, this, "%s() => (audio track is alive))", __func__);
received_audio_callback_ = true;
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
index d3492bf9049..02fc4f2326d 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
@@ -9,7 +9,6 @@
#include "base/atomicops.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
@@ -30,6 +29,8 @@ class MediaStreamComponent;
class PLATFORM_EXPORT MediaStreamAudioTrack : public MediaStreamTrackPlatform {
public:
explicit MediaStreamAudioTrack(bool is_local_track);
+ MediaStreamAudioTrack(const MediaStreamAudioTrack&) = delete;
+ MediaStreamAudioTrack& operator=(const MediaStreamAudioTrack&) = delete;
~MediaStreamAudioTrack() override;
@@ -123,8 +124,6 @@ class PLATFORM_EXPORT MediaStreamAudioTrack : public MediaStreamTrackPlatform {
// Provides weak pointers that are valid until Stop() is called.
base::WeakPtrFactory<MediaStreamAudioTrack> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioTrack);
};
} // namespace blink
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 bbfa611cb85..8f8d7c475fd 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
@@ -85,6 +85,12 @@ void MediaStreamComponent::GetSettings(
platform_track_->GetSettings(settings);
}
+MediaStreamTrackPlatform::CaptureHandle
+MediaStreamComponent::GetCaptureHandle() {
+ DCHECK(platform_track_);
+ return platform_track_->GetCaptureHandle();
+}
+
void MediaStreamComponent::SetContentHint(
WebMediaStreamTrack::ContentHintType hint) {
switch (hint) {
@@ -111,7 +117,7 @@ void MediaStreamComponent::SetContentHint(
void MediaStreamComponent::AudioSourceProviderImpl::ProvideInput(
AudioBus* bus,
- uint32_t frames_to_process) {
+ int frames_to_process) {
DCHECK(bus);
if (!bus)
return;
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h
index 81f8b50dbd8..ea94de0de49 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h
@@ -102,6 +102,7 @@ class PLATFORM_EXPORT MediaStreamComponent final
platform_track_ = std::move(platform_track);
}
void GetSettings(MediaStreamTrackPlatform::Settings&);
+ MediaStreamTrackPlatform::CaptureHandle GetCaptureHandle();
String ToString() const;
@@ -123,7 +124,7 @@ class PLATFORM_EXPORT MediaStreamComponent final
void Wrap(WebAudioSourceProvider*);
// blink::AudioSourceProvider
- void ProvideInput(AudioBus*, uint32_t frames_to_process) override;
+ void ProvideInput(AudioBus*, int frames_to_process) override;
private:
WebAudioSourceProvider* web_audio_source_provider_;
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 04d1a3471e0..b37a4b9297b 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
@@ -100,39 +100,23 @@ void GetSourceSettings(const blink::WebMediaStreamSource& web_source,
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16);
}
-class ConsumerWrapper final : public AudioDestinationConsumer {
- USING_FAST_MALLOC(ConsumerWrapper);
-
- public:
- static ConsumerWrapper* Create(WebAudioDestinationConsumer* consumer) {
- return new ConsumerWrapper(consumer);
- }
-
- void SetFormat(size_t number_of_channels, float sample_rate) override;
- void ConsumeAudio(AudioBus*, size_t number_of_frames) override;
-
- WebAudioDestinationConsumer* Consumer() { return consumer_; }
-
- private:
- explicit ConsumerWrapper(WebAudioDestinationConsumer* consumer)
- : consumer_(consumer) {
- // To avoid reallocation in ConsumeAudio, reserve initial capacity for most
- // common known layouts.
- bus_vector_.ReserveInitialCapacity(8);
- }
+} // namespace
- // m_consumer is not owned by this class.
- WebAudioDestinationConsumer* consumer_;
- // bus_vector_ must only be used in ConsumeAudio. The only reason it's a
- // member variable is to not have to reallocate it for each call.
- Vector<const float*> bus_vector_;
-};
+MediaStreamSource::ConsumerWrapper::ConsumerWrapper(
+ WebAudioDestinationConsumer* consumer)
+ : consumer_(consumer) {
+ // To avoid reallocation in ConsumeAudio, reserve initial capacity for most
+ // common known layouts.
+ bus_vector_.ReserveInitialCapacity(8);
+}
-void ConsumerWrapper::SetFormat(size_t number_of_channels, float sample_rate) {
+void MediaStreamSource::ConsumerWrapper::SetFormat(int number_of_channels,
+ float sample_rate) {
consumer_->SetFormat(number_of_channels, sample_rate);
}
-void ConsumerWrapper::ConsumeAudio(AudioBus* bus, size_t number_of_frames) {
+void MediaStreamSource::ConsumerWrapper::ConsumeAudio(AudioBus* bus,
+ int number_of_frames) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mediastream"),
"ConsumerWrapper::ConsumeAudio");
@@ -140,18 +124,16 @@ void ConsumerWrapper::ConsumeAudio(AudioBus* bus, size_t number_of_frames) {
return;
// Wrap AudioBus.
- size_t number_of_channels = bus->NumberOfChannels();
+ unsigned number_of_channels = bus->NumberOfChannels();
if (bus_vector_.size() != number_of_channels) {
bus_vector_.resize(number_of_channels);
}
- for (size_t i = 0; i < number_of_channels; ++i)
+ for (unsigned i = 0; i < number_of_channels; ++i)
bus_vector_[i] = bus->Channel(i)->Data();
consumer_->ConsumeAudio(bus_vector_, number_of_frames);
}
-} // namespace
-
MediaStreamSource::MediaStreamSource(const String& id,
StreamType type,
const String& name,
@@ -190,27 +172,14 @@ void MediaStreamSource::SetReadyState(ReadyState ready_state) {
// Observers may dispatch events which create and add new Observers;
// take a snapshot so as to safely iterate.
- HeapVector<Member<Observer>> observers;
- CopyToVector(observers_, observers);
- for (auto observer : observers)
- observer->SourceChangedState();
-
- // setReadyState() will be invoked via the MediaStreamComponent::dispose()
- // prefinalizer, allocating |observers|. Which means that |observers| will
- // live until the next GC (but be unreferenced by other heap objects),
- // _but_ it will potentially contain references to Observers that were
- // GCed after the MediaStreamComponent prefinalizer had completed.
- //
- // So, if the next GC is a conservative one _and_ it happens to find
- // a reference to |observers| when scanning the stack, we're in trouble
- // as it contains references to now-dead objects.
- //
- // Work around this by explicitly clearing the vector backing store.
- //
- // TODO(sof): consider adding run-time checks that disallows this kind
- // of dead object revivification by default.
- for (wtf_size_t i = 0; i < observers.size(); ++i)
- observers[i] = nullptr;
+ Vector<base::OnceClosure> observer_callbacks;
+ for (auto it = observers_.begin(); it != observers_.end(); ++it) {
+ observer_callbacks.push_back(
+ base::BindOnce(&Observer::SourceChangedState, *it));
+ }
+ for (auto& observer_callback : observer_callbacks) {
+ std::move(observer_callback).Run();
+ }
}
}
@@ -245,19 +214,18 @@ void MediaStreamSource::SetAudioProcessingProperties(
void MediaStreamSource::AddAudioConsumer(
WebAudioDestinationConsumer* consumer) {
DCHECK(requires_consumer_);
- auto* consumer_wrapper = ConsumerWrapper::Create(consumer);
+ auto consumer_wrapper = std::make_unique<ConsumerWrapper>(consumer);
MutexLocker locker(audio_consumers_lock_);
- audio_consumers_.insert(consumer_wrapper);
+ audio_consumers_.insert(consumer, std::move(consumer_wrapper));
}
bool MediaStreamSource::RemoveAudioConsumer(
WebAudioDestinationConsumer* consumer) {
DCHECK(requires_consumer_);
- auto* consumer_wrapper = ConsumerWrapper::Create(consumer);
MutexLocker locker(audio_consumers_lock_);
- auto it = audio_consumers_.find(consumer_wrapper);
+ auto it = audio_consumers_.find(consumer);
if (it == audio_consumers_.end())
return false;
audio_consumers_.erase(it);
@@ -300,30 +268,29 @@ void MediaStreamSource::GetSettings(
GetSourceSettings(WebMediaStreamSource(this), settings);
}
-void MediaStreamSource::SetAudioFormat(size_t number_of_channels,
+void MediaStreamSource::SetAudioFormat(int number_of_channels,
float sample_rate) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mediastream"),
"MediaStreamSource::SetAudioFormat");
SendLogMessage(String::Format("SetAudioFormat({id=%s}, "
"{number_of_channels=%d}, {sample_rate=%.0f})",
- Id().Utf8().c_str(),
- static_cast<int>(number_of_channels),
+ Id().Utf8().c_str(), number_of_channels,
sample_rate)
.Utf8());
DCHECK(requires_consumer_);
MutexLocker locker(audio_consumers_lock_);
- for (AudioDestinationConsumer* consumer : audio_consumers_)
+ for (auto&& consumer : audio_consumers_.Values())
consumer->SetFormat(number_of_channels, sample_rate);
}
-void MediaStreamSource::ConsumeAudio(AudioBus* bus, size_t number_of_frames) {
+void MediaStreamSource::ConsumeAudio(AudioBus* bus, int number_of_frames) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mediastream"),
"MediaStreamSource::ConsumeAudio");
DCHECK(requires_consumer_);
MutexLocker locker(audio_consumers_lock_);
- for (AudioDestinationConsumer* consumer : audio_consumers_)
+ for (auto&& consumer : audio_consumers_.Values())
consumer->ConsumeAudio(bus, number_of_frames);
}
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 cbf6778ef9e..87b9a62e928 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
@@ -133,8 +133,8 @@ class PLATFORM_EXPORT MediaStreamSource final
capabilities_ = capabilities;
}
- void SetAudioFormat(size_t number_of_channels, float sample_rate);
- void ConsumeAudio(AudioBus*, size_t number_of_frames);
+ void SetAudioFormat(int number_of_channels, float sample_rate);
+ void ConsumeAudio(AudioBus*, int number_of_frames);
// Only used if this is a WebAudio source.
// The WebAudioDestinationConsumer is not owned, and has to be disposed of
@@ -142,9 +142,6 @@ class PLATFORM_EXPORT MediaStreamSource final
bool RequiresAudioConsumer() const { return requires_consumer_; }
void AddAudioConsumer(WebAudioDestinationConsumer*);
bool RemoveAudioConsumer(WebAudioDestinationConsumer*);
- const HashSet<AudioDestinationConsumer*>& AudioConsumers() {
- return audio_consumers_;
- }
void OnDeviceCaptureHandleChange(const MediaStreamDevice& device);
@@ -153,6 +150,23 @@ class PLATFORM_EXPORT MediaStreamSource final
void Dispose();
private:
+ class PLATFORM_EXPORT ConsumerWrapper final
+ : public AudioDestinationConsumer {
+ USING_FAST_MALLOC(ConsumerWrapper);
+
+ public:
+ explicit ConsumerWrapper(WebAudioDestinationConsumer* consumer);
+
+ void SetFormat(int number_of_channels, float sample_rate) override;
+ void ConsumeAudio(AudioBus* bus, int number_of_frames) override;
+
+ // m_consumer is not owned by this class.
+ WebAudioDestinationConsumer* consumer_;
+ // bus_vector_ must only be used in ConsumeAudio. The only reason it's a
+ // member variable is to not have to reallocate it for each call.
+ Vector<const float*> bus_vector_;
+ };
+
String id_;
StreamType type_;
String name_;
@@ -162,8 +176,8 @@ class PLATFORM_EXPORT MediaStreamSource final
bool requires_consumer_;
HeapHashSet<WeakMember<Observer>> observers_;
Mutex audio_consumers_lock_;
- HashSet<AudioDestinationConsumer*> audio_consumers_
- GUARDED_BY(audio_consumers_lock_);
+ HashMap<WebAudioDestinationConsumer*, std::unique_ptr<ConsumerWrapper>>
+ audio_consumers_ GUARDED_BY(audio_consumers_lock_);
std::unique_ptr<WebPlatformMediaStreamSource> platform_source_;
MediaConstraints constraints_;
Capabilities capabilities_;
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source_test.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source_test.cc
new file mode 100644
index 00000000000..a958efeb0ab
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source_test.cc
@@ -0,0 +1,73 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
+
+#include "build/build_config.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/platform/audio/audio_bus.h"
+#include "third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+using ::testing::_;
+using ::testing::StrictMock;
+
+namespace blink {
+
+class MockWebAudioDestinationConsumer : public WebAudioDestinationConsumer {
+ public:
+ MOCK_METHOD2(SetFormat, void(int, float));
+ MOCK_METHOD2(ConsumeAudio, void(const Vector<const float*>&, int));
+};
+
+class MediaStreamSourceTest : public testing::Test {
+ public:
+ void SetUp() override {
+ source = MakeGarbageCollected<MediaStreamSource>(
+ String::FromUTF8("audio_id"), MediaStreamSource::kTypeAudio,
+ String::FromUTF8("audio_track"), false /* remote */,
+ MediaStreamSource::kReadyStateLive, true /* requires_consumer */);
+ bus = AudioBus::Create(2, 10);
+ }
+ ~MediaStreamSourceTest() override = default;
+
+ protected:
+ StrictMock<MockWebAudioDestinationConsumer> consumer;
+ Persistent<MediaStreamSource> source;
+ scoped_refptr<AudioBus> bus;
+};
+
+TEST_F(MediaStreamSourceTest, AddAudioConsumer) {
+ source->AddAudioConsumer(&consumer);
+
+ EXPECT_CALL(consumer, ConsumeAudio(_, 10));
+
+ source->ConsumeAudio(bus.get(), 10);
+}
+
+TEST_F(MediaStreamSourceTest, AddAudioConsumer_MultipleTimes) {
+ // Add the same consumer multiple times.
+ source->AddAudioConsumer(&consumer);
+ source->AddAudioConsumer(&consumer);
+ source->AddAudioConsumer(&consumer);
+
+ // Should still only get one call.
+ EXPECT_CALL(consumer, ConsumeAudio(_, 10)).Times(1);
+
+ source->ConsumeAudio(bus.get(), 10);
+}
+
+TEST_F(MediaStreamSourceTest, RemoveAudioConsumer) {
+ source->AddAudioConsumer(&consumer);
+ EXPECT_TRUE(source->RemoveAudioConsumer(&consumer));
+
+ // The consumer should get no calls.
+ EXPECT_CALL(consumer, ConsumeAudio(_, 10)).Times(0);
+
+ source->ConsumeAudio(bus.get(), 10);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.cc
index 659d01388a1..726ea44c830 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.cc
@@ -22,4 +22,9 @@ MediaStreamTrackPlatform::MediaStreamTrackPlatform(bool is_local_track)
MediaStreamTrackPlatform::~MediaStreamTrackPlatform() {}
+MediaStreamTrackPlatform::CaptureHandle
+MediaStreamTrackPlatform::GetCaptureHandle() {
+ return MediaStreamTrackPlatform::CaptureHandle();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h
index 1c0275379c2..e849fed1559 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_TRACK_PLATFORM_H_
#include "base/callback.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -18,11 +19,6 @@ class PLATFORM_EXPORT MediaStreamTrackPlatform {
public:
enum class FacingMode { kNone, kUser, kEnvironment, kLeft, kRight };
- struct CaptureHandle {
- String origin;
- String handle;
- };
-
struct Settings {
bool HasFrameRate() const { return frame_rate >= 0.0; }
bool HasWidth() const { return width >= 0; }
@@ -60,10 +56,18 @@ class PLATFORM_EXPORT MediaStreamTrackPlatform {
absl::optional<media::mojom::DisplayCaptureSurfaceType> display_surface;
absl::optional<bool> logical_surface;
absl::optional<media::mojom::CursorCaptureType> cursor;
- absl::optional<CaptureHandle> capture_handle;
+ };
+
+ struct CaptureHandle {
+ bool IsEmpty() const { return origin.IsEmpty() && handle.IsEmpty(); }
+
+ String origin;
+ String handle;
};
explicit MediaStreamTrackPlatform(bool is_local_track);
+ MediaStreamTrackPlatform(const MediaStreamTrackPlatform&) = delete;
+ MediaStreamTrackPlatform& operator=(const MediaStreamTrackPlatform&) = delete;
virtual ~MediaStreamTrackPlatform();
static MediaStreamTrackPlatform* GetTrack(const WebMediaStreamTrack& track);
@@ -80,14 +84,12 @@ class PLATFORM_EXPORT MediaStreamTrackPlatform {
// TODO(hta): Make method pure virtual when all tracks have the method.
virtual void GetSettings(Settings& settings) {}
+ virtual CaptureHandle GetCaptureHandle();
bool is_local_track() const { return is_local_track_; }
private:
const bool is_local_track_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MediaStreamTrackPlatform);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.cc
index 5034ab23340..6b911d4edc9 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.cc
@@ -42,7 +42,7 @@ MediaStreamWebAudioSource::MediaStreamWebAudioSource(
MediaStreamWebAudioSource::~MediaStreamWebAudioSource() = default;
void MediaStreamWebAudioSource::ProvideInput(AudioBus* bus,
- uint32_t frames_to_process) {
+ int frames_to_process) {
DCHECK(bus);
if (!bus)
return;
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.h
index 19659bad6b7..efcbe3dd642 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.h
@@ -34,7 +34,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -47,16 +46,17 @@ class WebAudioSourceProvider;
class PLATFORM_EXPORT MediaStreamWebAudioSource : public AudioSourceProvider {
public:
explicit MediaStreamWebAudioSource(std::unique_ptr<WebAudioSourceProvider>);
+ MediaStreamWebAudioSource(const MediaStreamWebAudioSource&) = delete;
+ MediaStreamWebAudioSource& operator=(const MediaStreamWebAudioSource&) =
+ delete;
~MediaStreamWebAudioSource() override;
private:
// blink::AudioSourceProvider implementation.
- void ProvideInput(AudioBus*, uint32_t frames_to_process) override;
+ void ProvideInput(AudioBus*, int frames_to_process) override;
std::unique_ptr<WebAudioSourceProvider> web_audio_source_provider_;
WebVector<float*> web_audio_data_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaStreamWebAudioSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h
index d6184f918fb..e333de2a0c6 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h
@@ -33,13 +33,13 @@ class WebAudioDestinationConsumer {
public:
virtual ~WebAudioDestinationConsumer() = default;
- virtual void SetFormat(size_t number_of_channels, float sample_rate) = 0;
+ virtual void SetFormat(int number_of_channels, float sample_rate) = 0;
// The size of the vector is the number of audio channels, and
// |number_of_frames| is the number of audio frames in the (possibly
// multi-channel) buffer in a planar format.
virtual void ConsumeAudio(const Vector<const float*>&,
- size_t number_of_frames) = 0;
+ int number_of_frames) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc
index 30800b44aa0..61a966d15a0 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc
@@ -29,7 +29,7 @@ WebAudioMediaStreamSource::~WebAudioMediaStreamSource() {
EnsureSourceIsStopped();
}
-void WebAudioMediaStreamSource::SetFormat(size_t number_of_channels,
+void WebAudioMediaStreamSource::SetFormat(int number_of_channels,
float sample_rate) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
VLOG(1) << "WebAudio media stream source changed format to: channels="
@@ -85,7 +85,7 @@ void WebAudioMediaStreamSource::EnsureSourceIsStopped() {
void WebAudioMediaStreamSource::ConsumeAudio(
const Vector<const float*>& audio_data,
- size_t number_of_frames) {
+ int number_of_frames) {
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("mediastream"),
"WebAudioMediaStreamSource::ConsumeAudio", "frames",
number_of_frames);
@@ -97,8 +97,10 @@ void WebAudioMediaStreamSource::ConsumeAudio(
wrapper_bus_->set_frames(number_of_frames);
DCHECK_EQ(wrapper_bus_->channels(), static_cast<int>(audio_data.size()));
- for (size_t i = 0; i < audio_data.size(); ++i)
- wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i]));
+ for (wtf_size_t i = 0; i < audio_data.size(); ++i) {
+ wrapper_bus_->SetChannelData(static_cast<int>(i),
+ const_cast<float*>(audio_data[i]));
+ }
// The following will result in zero, one, or multiple synchronous calls to
// DeliverRebufferedAudio().
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h
index 1fb5e1d9887..4f8f1681237 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h
@@ -29,6 +29,9 @@ class PLATFORM_EXPORT WebAudioMediaStreamSource final
WebAudioMediaStreamSource(
MediaStreamSource* media_stream_source,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ WebAudioMediaStreamSource(const WebAudioMediaStreamSource&) = delete;
+ WebAudioMediaStreamSource& operator=(const WebAudioMediaStreamSource&) =
+ delete;
~WebAudioMediaStreamSource() override;
@@ -38,9 +41,9 @@ class PLATFORM_EXPORT WebAudioMediaStreamSource final
// Note: Blink ensures setFormat() and consumeAudio() are not called
// concurrently across threads, but these methods could be called on any
// thread.
- void SetFormat(size_t number_of_channels, float sample_rate) override;
+ void SetFormat(int number_of_channels, float sample_rate) override;
void ConsumeAudio(const Vector<const float*>& audio_data,
- size_t number_of_frames) override;
+ int number_of_frames) override;
// Called by AudioPushFifo zero or more times during the call to
// consumeAudio(). Delivers audio data with the required buffer size to the
@@ -76,8 +79,6 @@ class PLATFORM_EXPORT WebAudioMediaStreamSource final
// This object registers with a MediaStreamSource. We keep track of
// that in order to be able to deregister before stopping this source.
Persistent<MediaStreamSource> media_stream_source_;
-
- DISALLOW_COPY_AND_ASSIGN(WebAudioMediaStreamSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h b/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h
index 3dcc068900c..8e52c90dfce 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_WEBRTC_UMA_HISTOGRAMS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_WEBRTC_UMA_HISTOGRAMS_H_
-#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
@@ -58,6 +57,9 @@ PLATFORM_EXPORT void UpdateWebRTCMethodCount(RTCAPIName api_name);
// metric at most once per session.
class PLATFORM_EXPORT PerSessionWebRTCAPIMetrics {
public:
+ PerSessionWebRTCAPIMetrics(const PerSessionWebRTCAPIMetrics&) = delete;
+ PerSessionWebRTCAPIMetrics& operator=(const PerSessionWebRTCAPIMetrics&) =
+ delete;
virtual ~PerSessionWebRTCAPIMetrics();
static PerSessionWebRTCAPIMetrics* GetInstance();
@@ -89,8 +91,6 @@ class PLATFORM_EXPORT PerSessionWebRTCAPIMetrics {
bool has_used_api_[static_cast<int>(RTCAPIName::kInvalidName)];
THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(PerSessionWebRTCAPIMetrics);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms_test.cc b/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms_test.cc
index 9be831361ca..77a946900ff 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms_test.cc
@@ -49,7 +49,6 @@ INSTANTIATE_TEST_SUITE_P(
PerSessionWebRTCAPIMetricsTest,
::testing::ValuesIn({RTCAPIName::kGetUserMedia,
RTCAPIName::kGetDisplayMedia,
- RTCAPIName::kGetCurrentBrowsingContextMedia,
RTCAPIName::kEnumerateDevices,
RTCAPIName::kRTCPeerConnection}));
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 bf6b1984efe..0dcc944a687 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,8 @@ String ConvertToPrintableCharacters(const String& text) {
// Quoted-Printable format to convert to 7-bit printable ASCII characters.
std::string utf8_text = text.Utf8();
Vector<char> encoded_text;
- QuotedPrintableEncode(utf8_text.c_str(), utf8_text.length(),
+ QuotedPrintableEncode(utf8_text.c_str(),
+ base::checked_cast<wtf_size_t>(utf8_text.length()),
true /* is_header */, encoded_text);
return String(encoded_text.data(), encoded_text.size());
}
@@ -335,7 +336,8 @@ void MHTMLArchive::GenerateMHTMLHeader(const String& boundary,
DCHECK(string_builder.ToString().ContainsOnlyASCIIOrEmpty());
std::string utf8_string = string_builder.ToString().Utf8();
- output_buffer.Append(utf8_string.c_str(), utf8_string.length());
+ output_buffer.Append(utf8_string.c_str(),
+ static_cast<wtf_size_t>(utf8_string.length()));
}
void MHTMLArchive::GenerateMHTMLPart(const String& boundary,
@@ -385,7 +387,8 @@ void MHTMLArchive::GenerateMHTMLPart(const String& boundary,
string_builder.Append("\r\n");
std::string utf8_string = string_builder.ToString().Utf8();
- output_buffer.Append(utf8_string.data(), utf8_string.length());
+ output_buffer.Append(utf8_string.data(),
+ static_cast<wtf_size_t>(utf8_string.length()));
if (!strcmp(content_encoding, kBinary)) {
for (const auto& span : *resource.data)
@@ -424,7 +427,8 @@ void MHTMLArchive::GenerateMHTMLFooterForTesting(const String& boundary,
Vector<char>& output_buffer) {
DCHECK(!boundary.IsEmpty());
std::string utf8_string = String("\r\n--" + boundary + "--\r\n").Utf8();
- output_buffer.Append(utf8_string.c_str(), utf8_string.length());
+ output_buffer.Append(utf8_string.c_str(),
+ static_cast<wtf_size_t>(utf8_string.length()));
}
void MHTMLArchive::SetMainResource(ArchiveResource* main_resource) {
@@ -440,7 +444,7 @@ void MHTMLArchive::AddSubresource(ArchiveResource* resource) {
}
ArchiveResource* MHTMLArchive::SubresourceForURL(const KURL& url) const {
- return subresources_.at(url.GetString());
+ return subresources_.DeprecatedAtOrEmptyValue(url.GetString());
}
String MHTMLArchive::GetCacheIdentifier() const {
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h b/chromium/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h
index 0ebe8827646..8542fa9b3bc 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h
+++ b/chromium/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MHTML_SHARED_BUFFER_CHUNK_READER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MHTML_SHARED_BUFFER_CHUNK_READER_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -46,6 +45,8 @@ class SharedBufferChunkReader final {
const Vector<char>& separator);
SharedBufferChunkReader(scoped_refptr<const SharedBuffer>,
const char* separator);
+ SharedBufferChunkReader(const SharedBufferChunkReader&) = delete;
+ SharedBufferChunkReader& operator=(const SharedBufferChunkReader&) = delete;
void SetSeparator(const Vector<char>&);
void SetSeparator(const char*);
@@ -72,9 +73,6 @@ class SharedBufferChunkReader final {
bool reached_end_of_file_;
Vector<char> separator_;
uint32_t separator_index_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SharedBufferChunkReader);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_headers_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_headers_mojom_traits.h
index f060efd4eeb..bc7d03cde16 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_headers_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_headers_mojom_traits.h
@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/map_traits_wtf_hash_map.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace mojo {
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote_set_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote_set_test.cc
index 300b7bec109..d30eb882cf8 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote_set_test.cc
@@ -29,7 +29,7 @@ template <HeapMojoWrapperMode Mode>
class HeapMojoAssociatedRemoteSetGCBaseTest;
template <HeapMojoWrapperMode Mode>
-class GCOwner : public GarbageCollected<GCOwner<Mode>> {
+class GCOwner final : public GarbageCollected<GCOwner<Mode>> {
public:
explicit GCOwner(MockContextLifecycleNotifier* context,
HeapMojoAssociatedRemoteSetGCBaseTest<Mode>* test)
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc
index 2683da597c1..7d4d9ca982f 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc
@@ -28,8 +28,8 @@ template <HeapMojoWrapperMode Mode, typename ContextType>
class HeapMojoReceiverSetGCBaseTest;
template <HeapMojoWrapperMode Mode, typename ContextType>
-class GCOwner : public GarbageCollected<GCOwner<Mode, ContextType>>,
- public sample::blink::Service {
+class GCOwner final : public GarbageCollected<GCOwner<Mode, ContextType>>,
+ public sample::blink::Service {
public:
explicit GCOwner(MockContextLifecycleNotifier* context,
HeapMojoReceiverSetGCBaseTest<Mode, ContextType>* test)
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_set_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_set_test.cc
index 8628a94975a..a78cee2041c 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_set_test.cc
@@ -28,7 +28,7 @@ template <HeapMojoWrapperMode Mode>
class HeapMojoRemoteSetGCBaseTest;
template <HeapMojoWrapperMode Mode>
-class GCOwner : public GarbageCollected<GCOwner<Mode>> {
+class GCOwner final : public GarbageCollected<GCOwner<Mode>> {
public:
explicit GCOwner(MockContextLifecycleNotifier* context,
HeapMojoRemoteSetGCBaseTest<Mode>* test)
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc
index 6267e5e36d3..0bb6b83ee83 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc
@@ -20,7 +20,7 @@ namespace blink {
namespace {
template <HeapMojoWrapperMode Mode>
-class GCOwner : public GarbageCollected<GCOwner<Mode>> {
+class GCOwner final : public GarbageCollected<GCOwner<Mode>> {
public:
explicit GCOwner(MockContextLifecycleNotifier* context)
: receiver_set_(context) {}
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 8d2e4f27666..3388a4e15c7 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
@@ -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 "base/macros.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
index 26c38666948..4e7c992f133 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
@@ -7,6 +7,7 @@
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
#include "mojo/public/cpp/bindings/string_traits_wtf.h"
+#include "third_party/abseil-cpp/absl/types/optional.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"
diff --git a/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc
index 0848346070c..8f0cd749080 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc
@@ -4,7 +4,6 @@
#include <cstdint>
-#include "base/macros.h"
#include "base/rand_util.h"
#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
diff --git a/chromium/third_party/blink/renderer/platform/network/BUILD.gn b/chromium/third_party/blink/renderer/platform/network/BUILD.gn
index 163d86a9bb9..3ec575c4da8 100644
--- a/chromium/third_party/blink/renderer/platform/network/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/network/BUILD.gn
@@ -22,8 +22,6 @@ group("make_generated") {
}
blink_platform_sources("network") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
sources = [
"content_security_policy_parsers.cc",
"content_security_policy_parsers.h",
diff --git a/chromium/third_party/blink/renderer/platform/network/DEPS b/chromium/third_party/blink/renderer/platform/network/DEPS
index d89e72da0dd..2ae0d9da4b2 100644
--- a/chromium/third_party/blink/renderer/platform/network/DEPS
+++ b/chromium/third_party/blink/renderer/platform/network/DEPS
@@ -7,7 +7,7 @@ include_rules = [
# Dependencies.
"+media",
- "-media/blink",
+
# net/ includes should be allowed only in a limited set of directories,
# so we have separate DEPS from platform's one.
"+net/base",
diff --git a/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h b/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
index 166eb916a62..56d7f613c01 100644
--- a/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
+++ b/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc
index 6780febfbfc..665d29106b0 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc
@@ -116,7 +116,8 @@ scoped_refptr<EncodedFormData> EncodedFormData::Create(const void* data,
scoped_refptr<EncodedFormData> EncodedFormData::Create(
base::span<const char> string) {
scoped_refptr<EncodedFormData> result = Create();
- result->AppendData(string.data(), string.size());
+ result->AppendData(string.data(),
+ base::checked_cast<wtf_size_t>(string.size()));
return result;
}
diff --git a/chromium/third_party/blink/renderer/platform/network/form_data_encoder.cc b/chromium/third_party/blink/renderer/platform/network/form_data_encoder.cc
index dfcc868a54f..c37d2069523 100644
--- a/chromium/third_party/blink/renderer/platform/network/form_data_encoder.cc
+++ b/chromium/third_party/blink/renderer/platform/network/form_data_encoder.cc
@@ -41,7 +41,7 @@ static inline void Append(Vector<char>& buffer, const char* string) {
}
static inline void Append(Vector<char>& buffer, const std::string& string) {
- buffer.Append(string.data(), string.length());
+ buffer.Append(string.data(), base::checked_cast<wtf_size_t>(string.length()));
}
static inline void AppendPercentEncoded(Vector<char>& buffer, unsigned char c) {
@@ -229,8 +229,8 @@ void FormDataEncoder::EncodeStringAsFormData(Vector<char>& buffer,
static const char kSafeCharacters[] = "-._*";
// http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
- unsigned length = string.length();
- for (unsigned i = 0; i < length; ++i) {
+ size_t length = string.length();
+ for (size_t i = 0; i < length; ++i) {
unsigned char c = string.data()[i];
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
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 b2ff60358d9..ca1d401eb14 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
@@ -67,7 +67,7 @@ class PLATFORM_EXPORT HTTPHeaderMap final {
void Clear() { headers_.clear(); }
bool Contains(const AtomicString& k) const { return headers_.Contains(k); }
const AtomicString& Get(const AtomicString& k) const {
- return headers_.at(k);
+ return headers_.DeprecatedAtOrEmptyValue(k);
}
AddResult Set(const AtomicString& k, const AtomicString& v) {
SECURITY_DCHECK(!k.Contains('\n') && !k.Contains('\r'));
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 602de86a954..f90b3ab9c7f 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
+++ b/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -119,7 +119,7 @@ template <
typename OutElement = decltype(ConvertToBlink(std::declval<InElement>()))>
Vector<OutElement> ConvertToBlink(const std::vector<InElement>& in) {
Vector<OutElement> out;
- out.ReserveCapacity(in.size());
+ out.ReserveCapacity(base::checked_cast<wtf_size_t>(in.size()));
for (const auto& element : in) {
out.push_back(ConvertToBlink(element));
}
@@ -166,8 +166,8 @@ blink::CSPSourceListPtr ConvertToBlink(const CSPSourceListPtr& source_list) {
source_list->allow_self, source_list->allow_star,
source_list->allow_response_redirects, source_list->allow_inline,
source_list->allow_eval, source_list->allow_wasm_eval,
- source_list->allow_dynamic, source_list->allow_unsafe_hashes,
- source_list->report_sample);
+ source_list->allow_wasm_unsafe_eval, source_list->allow_dynamic,
+ source_list->allow_unsafe_hashes, source_list->report_sample);
}
blink::ContentSecurityPolicyHeaderPtr ConvertToBlink(
@@ -252,7 +252,10 @@ blink::ParsedHeadersPtr ConvertToBlink(const ParsedHeadersPtr& in) {
? absl::make_optional(ConvertToBlink(in->critical_ch.value()))
: absl::nullopt,
in->xfo, ConvertToBlink(in->link_headers),
- ConvertToBlink(in->timing_allow_origin), in->bfcache_opt_in_unload);
+ ConvertToBlink(in->timing_allow_origin), in->bfcache_opt_in_unload,
+ in->reporting_endpoints.has_value()
+ ? absl::make_optional(ConvertToBlink(in->reporting_endpoints.value()))
+ : absl::nullopt);
}
} // namespace mojom
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 c8339c71e6b..5eb65e5bdf3 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_parsers.h
+++ b/chromium/third_party/blink/renderer/platform/network/http_parsers.h
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
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 c27a0eeef0a..53ddf777be3 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
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/network/http_parsers.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
#include "services/network/public/mojom/parsed_headers.mojom-blink.h"
@@ -332,8 +332,8 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) {
"set-cookie: y=3\n"
"\n";
wtf_size_t end = 0;
- bool result =
- ParseMultipartHeadersFromBody(kData, strlen(kData), &response, &end);
+ bool result = ParseMultipartHeadersFromBody(
+ kData, static_cast<wtf_size_t>(strlen(kData)), &response, &end);
EXPECT_TRUE(result);
EXPECT_EQ(strlen(kData), end);
@@ -348,8 +348,8 @@ TEST(HTTPParsersTest, ParseMultipartHeadersContentCharset) {
ResourceResponse response;
const char kData[] = "content-type: text/html; charset=utf-8\n\n";
wtf_size_t end = 0;
- bool result =
- ParseMultipartHeadersFromBody(kData, strlen(kData), &response, &end);
+ bool result = ParseMultipartHeadersFromBody(
+ kData, static_cast<wtf_size_t>(strlen(kData)), &response, &end);
EXPECT_TRUE(result);
EXPECT_EQ(strlen(kData), end);
diff --git a/chromium/third_party/blink/renderer/platform/network/network_state_notifier.h b/chromium/third_party/blink/renderer/platform/network/network_state_notifier.h
index 671356b0c62..1ba47c8215c 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_state_notifier.h
+++ b/chromium/third_party/blink/renderer/platform/network/network_state_notifier.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -97,6 +96,9 @@ class PLATFORM_EXPORT NetworkStateNotifier {
ObserverType,
NetworkStateObserver*,
scoped_refptr<base::SingleThreadTaskRunner>);
+ NetworkStateObserverHandle(const NetworkStateObserverHandle&) = delete;
+ NetworkStateObserverHandle& operator=(const NetworkStateObserverHandle&) =
+ delete;
~NetworkStateObserverHandle();
private:
@@ -104,11 +106,11 @@ class PLATFORM_EXPORT NetworkStateNotifier {
ObserverType type_;
NetworkStateObserver* observer_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkStateObserverHandle);
};
NetworkStateNotifier() : has_override_(false) {}
+ NetworkStateNotifier(const NetworkStateNotifier&) = delete;
+ NetworkStateNotifier& operator=(const NetworkStateNotifier&) = delete;
~NetworkStateNotifier() {
DCHECK(connection_observers_.IsEmpty());
@@ -370,8 +372,6 @@ class PLATFORM_EXPORT NetworkStateNotifier {
ObserverListMap on_line_state_observers_;
const uint8_t randomization_salt_ = base::RandInt(1, 20);
-
- DISALLOW_COPY_AND_ASSIGN(NetworkStateNotifier);
};
PLATFORM_EXPORT NetworkStateNotifier& GetNetworkStateNotifier();
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 81745b38d39..d00b42ff11e 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/network/network_utils.cc
@@ -133,7 +133,8 @@ Vector<char> ParseMultipartBoundary(const AtomicString& content_type_header) {
&had_charset, &boundary);
base::TrimString(boundary, " \"", &boundary);
Vector<char> result;
- result.Append(boundary.data(), boundary.size());
+ result.Append(boundary.data(),
+ base::checked_cast<wtf_size_t>(boundary.size()));
return result;
}
diff --git a/chromium/third_party/blink/renderer/platform/p2p/OWNERS b/chromium/third_party/blink/renderer/platform/p2p/OWNERS
index f73d253f31a..59e007d397d 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/p2p/OWNERS
@@ -1,3 +1,3 @@
-guidou@chromium.org
-sergeyu@chromium.org
+hta@chromium.org
+orphis@chromium.org
steveanton@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h b/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h
index 5e0a17d1d6c..9378ef1127a 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_EMPTY_NETWORK_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_EMPTY_NETWORK_MANAGER_H_
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -31,6 +30,8 @@ class EmptyNetworkManager : public rtc::NetworkManagerBase,
// |task_runner|.
PLATFORM_EXPORT explicit EmptyNetworkManager(
IpcNetworkManager* network_manager);
+ EmptyNetworkManager(const EmptyNetworkManager&) = delete;
+ EmptyNetworkManager& operator=(const EmptyNetworkManager&) = delete;
PLATFORM_EXPORT ~EmptyNetworkManager() override;
// rtc::NetworkManager:
@@ -77,8 +78,6 @@ class EmptyNetworkManager : public rtc::NetworkManagerBase,
base::WeakPtr<rtc::NetworkManager> network_manager_for_signaling_thread_;
base::WeakPtrFactory<EmptyNetworkManager> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(EmptyNetworkManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
index c991a040e18..4e7d1a46202 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_FILTERING_NETWORK_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_FILTERING_NETWORK_MANAGER_H_
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -45,6 +44,8 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
IpcNetworkManager* network_manager,
media::MediaPermission* media_permission,
bool allow_mdns_obfuscation);
+ FilteringNetworkManager(const FilteringNetworkManager&) = delete;
+ FilteringNetworkManager& operator=(const FilteringNetworkManager&) = delete;
PLATFORM_EXPORT ~FilteringNetworkManager() override;
@@ -130,8 +131,6 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
bool allow_mdns_obfuscation_ = true;
base::WeakPtrFactory<FilteringNetworkManager> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(FilteringNetworkManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
index b254b1fbae7..2f9a82ce1f3 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
@@ -11,10 +11,10 @@
#include <vector>
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/media_permission.h"
diff --git a/chromium/third_party/blink/renderer/platform/p2p/host_address_request.h b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.h
index 451ae176609..c0caa5fe87e 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/host_address_request.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "net/base/ip_address.h"
@@ -29,6 +28,9 @@ class P2PAsyncAddressResolver
using DoneCallback = base::OnceCallback<void(const Vector<net::IPAddress>&)>;
P2PAsyncAddressResolver(P2PSocketDispatcher* dispatcher);
+ P2PAsyncAddressResolver(const P2PAsyncAddressResolver&) = delete;
+ P2PAsyncAddressResolver& operator=(const P2PAsyncAddressResolver&) = delete;
+
// Start address resolve process.
void Start(const rtc::SocketAddress& addr, DoneCallback done_callback);
// Clients must unregister before exiting for cleanup.
@@ -58,8 +60,6 @@ class P2PAsyncAddressResolver
// State must be accessed from delegate thread only.
State state_;
DoneCallback done_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PAsyncAddressResolver);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
index 021d4e639a8..cc8c4238d4b 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
@@ -12,7 +12,6 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_checker.h"
@@ -77,6 +76,8 @@ class IpcPacketSocket : public rtc::AsyncPacketSocket,
public blink::P2PSocketClientDelegate {
public:
IpcPacketSocket();
+ IpcPacketSocket(const IpcPacketSocket&) = delete;
+ IpcPacketSocket& operator=(const IpcPacketSocket&) = delete;
~IpcPacketSocket() override;
// Struct to track information when a packet is received by this socket for
@@ -200,10 +201,8 @@ class IpcPacketSocket : public rtc::AsyncPacketSocket,
size_t current_discard_bytes_sequence_;
// Track the total number of packets and the number of packets discarded.
- size_t packets_discarded_;
- size_t total_packets_;
-
- DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket);
+ int packets_discarded_;
+ int total_packets_;
};
// Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
@@ -423,7 +422,8 @@ int IpcPacketSocket::SendTo(const void* data,
send_bytes_available_ -= data_size;
Vector<int8_t> data_vector;
- data_vector.Append(reinterpret_cast<const int8_t*>(data), data_size);
+ data_vector.Append(reinterpret_cast<const int8_t*>(data),
+ base::checked_cast<wtf_size_t>(data_size));
uint64_t packet_id = client_->Send(address_chrome, data_vector, options);
// Ensure packet_id is not 0. It can't be the case according to
@@ -435,7 +435,7 @@ int IpcPacketSocket::SendTo(const void* data,
TraceSendThrottlingState();
// Fake successful send. The caller ignores result anyway.
- return data_size;
+ return base::checked_cast<int>(data_size);
}
int IpcPacketSocket::Close() {
@@ -699,7 +699,7 @@ void AsyncAddressResolverImpl::Destroy(bool wait) {
void AsyncAddressResolverImpl::OnAddressResolved(
const Vector<net::IPAddress>& addresses) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- for (size_t i = 0; i < addresses.size(); ++i) {
+ for (wtf_size_t i = 0; i < addresses.size(); ++i) {
rtc::SocketAddress socket_address;
if (!jingle_glue::IPEndPointToSocketAddress(
net::IPEndPoint(addresses[i], 0), &socket_address)) {
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h
index 62bc47e203a..4fc796bc964 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -29,6 +28,8 @@ class IpcPacketSocketFactory : public rtc::PacketSocketFactory {
PLATFORM_EXPORT explicit IpcPacketSocketFactory(
P2PSocketDispatcher* socket_dispatcher,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
+ IpcPacketSocketFactory(const IpcPacketSocketFactory&) = delete;
+ IpcPacketSocketFactory& operator=(const IpcPacketSocketFactory&) = delete;
~IpcPacketSocketFactory() override;
rtc::AsyncPacketSocket* CreateUdpSocket(
@@ -56,8 +57,6 @@ class IpcPacketSocketFactory : public rtc::PacketSocketFactory {
// the dtor).
CrossThreadWeakPersistent<P2PSocketDispatcher> socket_dispatcher_;
const net::NetworkTrafficAnnotationTag traffic_annotation_;
-
- DISALLOW_COPY_AND_ASSIGN(IpcPacketSocketFactory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
index 3c725d7bd96..ad5acf41a32 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
@@ -11,8 +11,9 @@
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "services/network/public/mojom/mdns_responder.mojom-blink.h"
-#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/webrtc/rtc_base/ip_address.h"
@@ -40,14 +41,13 @@ void OnNameRemovedForAddress(
} // namespace
-MdnsResponderAdapter::MdnsResponderAdapter() {
+MdnsResponderAdapter::MdnsResponderAdapter(MojoBindingContext& context) {
mojo::PendingRemote<network::mojom::blink::MdnsResponder> client;
auto receiver = client.InitWithNewPipeAndPassReceiver();
shared_remote_client_ =
mojo::SharedRemote<network::mojom::blink::MdnsResponder>(
std::move(client));
- blink::Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
- std::move(receiver));
+ context.GetBrowserInterfaceBroker().GetInterface(std::move(receiver));
}
MdnsResponderAdapter::~MdnsResponderAdapter() = default;
diff --git a/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h
index 79a70b7c4b6..abe4b88f3b9 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h
@@ -16,6 +16,8 @@ class IPAddress;
namespace blink {
+class MojoBindingContext;
+
// This class is created on the main thread but is used only on the WebRTC
// worker threads. The MdnsResponderAdapter implements the WebRTC mDNS responder
// interface via the MdnsResponder service in Chromium, and is used to register
@@ -25,7 +27,9 @@ class PLATFORM_EXPORT MdnsResponderAdapter
public:
// The adapter should be created on the main thread to have access to the
// connector to the service manager.
- MdnsResponderAdapter();
+ explicit MdnsResponderAdapter(MojoBindingContext& context);
+ MdnsResponderAdapter(const MdnsResponderAdapter&) = delete;
+ MdnsResponderAdapter& operator=(const MdnsResponderAdapter&) = delete;
~MdnsResponderAdapter() override;
// webrtc::MdnsResponderInterface implementation.
@@ -37,8 +41,6 @@ class PLATFORM_EXPORT MdnsResponderAdapter
private:
mojo::SharedRemote<network::mojom::blink::MdnsResponder>
shared_remote_client_;
-
- DISALLOW_COPY_AND_ASSIGN(MdnsResponderAdapter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/port_allocator.cc b/chromium/third_party/blink/renderer/platform/p2p/port_allocator.cc
index 4b18e5489c4..4cc188420e6 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/port_allocator.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/port_allocator.cc
@@ -39,11 +39,6 @@ P2PPortAllocator::P2PPortAllocator(
}
set_flags(flags);
set_allow_tcp_listen(false);
- bool enable_webrtc_stun_origin =
- Platform::Current()->IsWebRtcStunOriginEnabled();
- if (enable_webrtc_stun_origin) {
- set_origin(origin_.spec());
- }
}
P2PPortAllocator::~P2PPortAllocator() {}
diff --git a/chromium/third_party/blink/renderer/platform/p2p/port_allocator.h b/chromium/third_party/blink/renderer/platform/p2p/port_allocator.h
index 018c05b2d7c..4a64b0cd1da 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/port_allocator.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/port_allocator.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/p2p/client/basic_port_allocator.h"
@@ -40,6 +39,8 @@ class PLATFORM_EXPORT P2PPortAllocator : public cricket::BasicPortAllocator {
rtc::PacketSocketFactory* socket_factory,
const Config& config,
const GURL& origin);
+ P2PPortAllocator(const P2PPortAllocator&) = delete;
+ P2PPortAllocator& operator=(const P2PPortAllocator&) = delete;
~P2PPortAllocator() override;
// Will also initialize the network manager passed into the constructor.
@@ -49,8 +50,6 @@ class PLATFORM_EXPORT P2PPortAllocator : public cricket::BasicPortAllocator {
std::unique_ptr<rtc::NetworkManager> network_manager_;
Config config_;
GURL origin_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h
index a981931f407..9f0e8e8f556 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -39,6 +38,8 @@ class P2PSocketClientImpl : public blink::P2PSocketClient,
P2PSocketClientImpl(
P2PSocketDispatcher* dispatcher,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
+ P2PSocketClientImpl(const P2PSocketClientImpl&) = delete;
+ P2PSocketClientImpl& operator=(const P2PSocketClientImpl&) = delete;
~P2PSocketClientImpl() override;
// Initialize socket of the specified |type| and connected to the
@@ -116,8 +117,6 @@ class P2PSocketClientImpl : public blink::P2PSocketClient,
mojo::Remote<network::mojom::blink::P2PSocket> socket_;
mojo::Receiver<network::mojom::blink::P2PSocketClient> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketClientImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
index bec6d355a08..b54faf00eb8 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
@@ -96,7 +96,7 @@ void P2PSocketDispatcher::NetworkListChanged(
// gets moved from blink/public to blink/renderer, and operate over
// WTF::Vector.
std::vector<net::NetworkInterface> copy(networks.size());
- for (size_t i = 0; i < networks.size(); i++)
+ for (wtf_size_t i = 0; i < networks.size(); i++)
copy[i] = networks[i];
network_list_observers_->Notify(
@@ -119,7 +119,7 @@ void P2PSocketDispatcher::RequestNetworkEventsIfNecessary() {
// gets moved from blink/public to blink/renderer, and operate over
// WTF::Vector.
std::vector<net::NetworkInterface> copy(networks_.size());
- for (size_t i = 0; i < networks_.size(); i++)
+ for (wtf_size_t i = 0; i < networks_.size(); i++)
copy[i] = networks_[i];
network_list_observers_->Notify(
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
index a178b03b79c..246fd57b9e1 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
@@ -24,7 +24,6 @@
#include <stdint.h>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
@@ -65,6 +64,8 @@ class PLATFORM_EXPORT P2PSocketDispatcher
P2PSocketDispatcher(MojoBindingContext& context,
base::PassKey<P2PSocketDispatcher>);
+ P2PSocketDispatcher(const P2PSocketDispatcher&) = delete;
+ P2PSocketDispatcher& operator=(const P2PSocketDispatcher&) = delete;
~P2PSocketDispatcher() override;
// blink::NetworkListManager interface:
@@ -112,8 +113,6 @@ class PLATFORM_EXPORT P2PSocketDispatcher
HeapMojoReceiver<network::mojom::blink::P2PNetworkNotificationClient,
P2PSocketDispatcher>
network_notification_client_receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcher);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_api_name.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_api_name.h
index fa9165862b2..f7b99bffd3e 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_api_name.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_api_name.h
@@ -20,7 +20,7 @@ enum class RTCAPIName {
kCanvasCaptureStream,
kVideoCaptureStream,
kGetDisplayMedia,
- kGetCurrentBrowsingContextMedia,
+ kGetCurrentBrowsingContextMedia, // Deprecated.
kInvalidName
};
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h
index 987aa6755ee..5fa4b8b1dbb 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_DTMF_SENDER_HANDLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_DTMF_SENDER_HANDLER_H_
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -42,6 +41,8 @@ class PLATFORM_EXPORT RtcDtmfSenderHandler final {
RtcDtmfSenderHandler(scoped_refptr<base::SingleThreadTaskRunner> main_thread,
webrtc::DtmfSenderInterface* dtmf_sender);
+ RtcDtmfSenderHandler(const RtcDtmfSenderHandler&) = delete;
+ RtcDtmfSenderHandler& operator=(const RtcDtmfSenderHandler&) = delete;
~RtcDtmfSenderHandler();
void SetClient(RtcDtmfSenderHandler::Client* client);
@@ -61,8 +62,6 @@ class PLATFORM_EXPORT RtcDtmfSenderHandler final {
// |weak_factory_| must be the last member.
base::WeakPtrFactory<RtcDtmfSenderHandler> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(RtcDtmfSenderHandler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc
index 18f46d1d094..37392db0989 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc
@@ -8,6 +8,7 @@
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -22,116 +23,202 @@ namespace {
// RTCEncodedAudioStreamTransformer cannot derive from rtc::RefCountedObject
// and post tasks referencing itself as an rtc::scoped_refptr. Instead,
// RTCEncodedAudioStreamTransformer creates a delegate using
-// rtc::RefCountedObject and posts tasks referencing the delegate, which invokes
-// the RTCEncodedAudioStreamTransformer via callbacks.
+// rtc::RefCountedObject and posts tasks referencing the delegate, which
+// invokes the RTCEncodedAudioStreamTransformer via callbacks.
class RTCEncodedAudioStreamTransformerDelegate
: public webrtc::FrameTransformerInterface {
public:
RTCEncodedAudioStreamTransformerDelegate(
- const base::WeakPtr<RTCEncodedAudioStreamTransformer>& transformer,
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
- : transformer_(transformer),
- main_task_runner_(std::move(main_task_runner)) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
+ RTCEncodedAudioStreamTransformer* transformer,
+ scoped_refptr<base::SingleThreadTaskRunner> realm_task_runner,
+ scoped_refptr<RTCEncodedAudioStreamTransformer::Broker>
+ transformer_broker)
+ : source_task_runner_(realm_task_runner),
+ transformer_broker_(std::move(transformer_broker)) {
+ DCHECK(source_task_runner_->BelongsToCurrentThread());
+ }
+
+ void SetSourceTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ WTF::MutexLocker locker(source_task_runner_mutex_);
+ source_task_runner_ = std::move(task_runner);
}
// webrtc::FrameTransformerInterface
void RegisterTransformedFrameCallback(
rtc::scoped_refptr<webrtc::TransformedFrameCallback>
send_frame_to_sink_callback) override {
- PostCrossThreadTask(
- *main_task_runner_, FROM_HERE,
- CrossThreadBindOnce(
- &RTCEncodedAudioStreamTransformer::RegisterTransformedFrameCallback,
- transformer_, std::move(send_frame_to_sink_callback)));
+ transformer_broker_->RegisterTransformedFrameCallback(
+ std::move(send_frame_to_sink_callback));
}
void UnregisterTransformedFrameCallback() override {
- PostCrossThreadTask(
- *main_task_runner_, FROM_HERE,
- CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::
- UnregisterTransformedFrameCallback,
- transformer_));
+ transformer_broker_->UnregisterTransformedFrameCallback();
}
void Transform(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) override {
+ WTF::MutexLocker locker(source_task_runner_mutex_);
auto audio_frame = base::WrapUnique(
static_cast<webrtc::TransformableFrameInterface*>(frame.release()));
PostCrossThreadTask(
- *main_task_runner_, FROM_HERE,
- CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::TransformFrame,
- transformer_, std::move(audio_frame)));
+ *source_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::Broker::
+ TransformFrameOnSourceTaskRunner,
+ transformer_broker_, std::move(audio_frame)));
}
private:
- base::WeakPtr<RTCEncodedAudioStreamTransformer> transformer_;
- const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ WTF::Mutex source_task_runner_mutex_;
+ scoped_refptr<base::SingleThreadTaskRunner> source_task_runner_
+ GUARDED_BY(source_task_runner_mutex_);
+ scoped_refptr<RTCEncodedAudioStreamTransformer::Broker> transformer_broker_;
};
} // namespace
+RTCEncodedAudioStreamTransformer::Broker::Broker(
+ RTCEncodedAudioStreamTransformer* transformer_)
+ : transformer_(transformer_) {}
+
+void RTCEncodedAudioStreamTransformer::Broker::RegisterTransformedFrameCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>
+ send_frame_to_sink_callback) {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->RegisterTransformedFrameCallback(
+ std::move(send_frame_to_sink_callback));
+ }
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::
+ UnregisterTransformedFrameCallback() {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->UnregisterTransformedFrameCallback();
+ }
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::TransformFrameOnSourceTaskRunner(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->TransformFrame(std::move(frame));
+ }
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::SetTransformerCallback(
+ TransformerCallback callback) {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->SetTransformerCallback(std::move(callback));
+ }
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::ResetTransformerCallback() {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->ResetTransformerCallback();
+ }
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::SetSourceTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->SetSourceTaskRunner(std::move(task_runner));
+ }
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::ClearTransformer() {
+ WTF::MutexLocker locker(transformer_mutex_);
+ transformer_ = nullptr;
+}
+
+void RTCEncodedAudioStreamTransformer::Broker::SendFrameToSink(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
+ WTF::MutexLocker locker(transformer_mutex_);
+ if (transformer_) {
+ transformer_->SendFrameToSink(std::move(frame));
+ }
+}
+
RTCEncodedAudioStreamTransformer::RTCEncodedAudioStreamTransformer(
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
- DCHECK(main_task_runner->BelongsToCurrentThread());
- delegate_ =
- new rtc::RefCountedObject<RTCEncodedAudioStreamTransformerDelegate>(
- weak_factory_.GetWeakPtr(), std::move(main_task_runner));
+ scoped_refptr<base::SingleThreadTaskRunner> realm_task_runner)
+ : broker_(base::AdoptRef(new Broker(this))),
+ delegate_(
+ new rtc::RefCountedObject<RTCEncodedAudioStreamTransformerDelegate>(
+ this,
+ std::move(realm_task_runner),
+ broker_)) {}
+
+RTCEncodedAudioStreamTransformer::~RTCEncodedAudioStreamTransformer() {
+ broker_->ClearTransformer();
}
void RTCEncodedAudioStreamTransformer::RegisterTransformedFrameCallback(
rtc::scoped_refptr<webrtc::TransformedFrameCallback> callback) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(sink_mutex_);
send_frame_to_sink_cb_ = callback;
}
void RTCEncodedAudioStreamTransformer::UnregisterTransformedFrameCallback() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(sink_mutex_);
send_frame_to_sink_cb_ = nullptr;
}
void RTCEncodedAudioStreamTransformer::TransformFrame(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(source_mutex_);
// If no transformer callback has been set, drop the frame.
if (!transformer_callback_)
return;
-
transformer_callback_.Run(std::move(frame));
}
void RTCEncodedAudioStreamTransformer::SendFrameToSink(
std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(sink_mutex_);
if (send_frame_to_sink_cb_)
send_frame_to_sink_cb_->OnTransformedFrame(std::move(frame));
}
void RTCEncodedAudioStreamTransformer::SetTransformerCallback(
TransformerCallback callback) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(source_mutex_);
+ DCHECK(!transformer_callback_);
transformer_callback_ = std::move(callback);
}
void RTCEncodedAudioStreamTransformer::ResetTransformerCallback() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(source_mutex_);
transformer_callback_.Reset();
}
-bool RTCEncodedAudioStreamTransformer::HasTransformerCallback() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- return !transformer_callback_.is_null();
+bool RTCEncodedAudioStreamTransformer::HasTransformerCallback() {
+ WTF::MutexLocker locker(source_mutex_);
+ return !!transformer_callback_;
}
bool RTCEncodedAudioStreamTransformer::HasTransformedFrameCallback() const {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ WTF::MutexLocker locker(sink_mutex_);
return !!send_frame_to_sink_cb_;
}
rtc::scoped_refptr<webrtc::FrameTransformerInterface>
RTCEncodedAudioStreamTransformer::Delegate() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return delegate_;
}
+void RTCEncodedAudioStreamTransformer::SetSourceTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> realm_task_runner) {
+ static_cast<RTCEncodedAudioStreamTransformerDelegate*>(delegate_.get())
+ ->SetSourceTaskRunner(std::move(realm_task_runner));
+}
+
+scoped_refptr<RTCEncodedAudioStreamTransformer::Broker>
+RTCEncodedAudioStreamTransformer::GetBroker() {
+ return broker_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h
index f1beece05fd..fd644fc0ab8 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h
@@ -14,6 +14,8 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/webrtc/api/scoped_refptr.h"
namespace base {
@@ -28,55 +30,102 @@ class TransformableFrameInterface;
namespace blink {
+using TransformerCallback = WTF::CrossThreadRepeatingFunction<void(
+ std::unique_ptr<webrtc::TransformableFrameInterface>)>;
+
class PLATFORM_EXPORT RTCEncodedAudioStreamTransformer {
public:
- using TransformerCallback = base::RepeatingCallback<void(
- std::unique_ptr<webrtc::TransformableFrameInterface>)>;
+ // A RefCounted wrapper around the Transformer class which holds a
+ // cross-thread safe weak pointer to a Transformer object. This allows us to
+ // post tasks to the Transformer from classes the transformer owns without
+ // creating a circular reference.
+ class PLATFORM_EXPORT Broker : public WTF::ThreadSafeRefCounted<Broker> {
+ public:
+ void RegisterTransformedFrameCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>
+ send_frame_to_sink_callback);
+
+ void UnregisterTransformedFrameCallback();
+
+ void TransformFrameOnSourceTaskRunner(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame);
+
+ void SetTransformerCallback(TransformerCallback callback);
+
+ void ResetTransformerCallback();
+
+ void SetSourceTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ void SendFrameToSink(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame);
+
+ private:
+ explicit Broker(RTCEncodedAudioStreamTransformer* transformer_);
+ void ClearTransformer();
+ friend class RTCEncodedAudioStreamTransformer;
+
+ WTF::Mutex transformer_mutex_;
+ RTCEncodedAudioStreamTransformer* transformer_
+ GUARDED_BY(transformer_mutex_);
+ };
+
explicit RTCEncodedAudioStreamTransformer(
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> realm_task_runner);
+ ~RTCEncodedAudioStreamTransformer();
- // Called by WebRTC to let us know about a callback object to send transformed
- // frames to the WebRTC decoder. Runs on an internal WebRTC thread.
- // The callback can run on any thread.
+ // Called by WebRTC to let us know about a callback object to send
+ // transformed frames to the WebRTC decoder. Runs on the thread which
+ // created this object. The callback can run on any thread.
void RegisterTransformedFrameCallback(
rtc::scoped_refptr<webrtc::TransformedFrameCallback>);
// Called by WebRTC to let us know that any reference to the callback object
// reported by RegisterTransformedFrameCallback() should be released since
// the callback is no longer useful and is intended for destruction.
+ // Runs on the thread which created this object.
void UnregisterTransformedFrameCallback();
// Called by WebRTC to notify of new untransformed frames from the WebRTC
- // stack. Runs on an internal WebRTC thread.
+ // stack. Runs on the most recently set source task_runner - ie changes when
+ // the stream is transferred.
void TransformFrame(std::unique_ptr<webrtc::TransformableFrameInterface>);
- // Send a transformed frame to the WebRTC sink. Must run on the main
- // thread.
+ // Send a transformed frame to the WebRTC sink. Threadsafe.
void SendFrameToSink(
std::unique_ptr<webrtc::TransformableFrameInterface> frame);
- // Set a callback to be invoked on every untransformed frame. Must run on the
- // main thread.
+ // Set a callback to be invoked on every untransformed frame. Is threadsafe.
void SetTransformerCallback(TransformerCallback);
- // Removes the callback
+ // Removes the callback. Is threadsafe.
void ResetTransformerCallback();
// Returns true if a callback has been set with SetTransformerCallback(),
- // false otherwise. Must run on the main thread.
- bool HasTransformerCallback() const;
+ // false otherwise. Is threadsafe.
+ bool HasTransformerCallback();
// Returns true if a webrtc::TransformedFrameCallback is registered.
+ // Threadsafe.
bool HasTransformedFrameCallback() const;
rtc::scoped_refptr<webrtc::FrameTransformerInterface> Delegate();
+ // Set the TaskRunner used for the Source side - to deliver frames up to the
+ // UnderlyingSource. Is threadsafe.
+ void SetSourceTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> realm_task_runner);
+
+ scoped_refptr<Broker> GetBroker();
+
private:
- THREAD_CHECKER(thread_checker_);
- rtc::scoped_refptr<webrtc::FrameTransformerInterface> delegate_;
- rtc::scoped_refptr<webrtc::TransformedFrameCallback> send_frame_to_sink_cb_;
- TransformerCallback transformer_callback_;
- base::WeakPtrFactory<RTCEncodedAudioStreamTransformer> weak_factory_{this};
+ const scoped_refptr<Broker> broker_;
+ const rtc::scoped_refptr<webrtc::FrameTransformerInterface> delegate_;
+ mutable WTF::Mutex sink_mutex_;
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback> send_frame_to_sink_cb_
+ GUARDED_BY(sink_mutex_);
+ WTF::Mutex source_mutex_;
+ TransformerCallback transformer_callback_ GUARDED_BY(source_mutex_);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc
index 030db787a2d..1fa346021d4 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc
@@ -80,8 +80,9 @@ TEST_F(RTCEncodedAudioStreamTransformerTest,
TransformerForwardsFrameToTransformerCallback) {
EXPECT_FALSE(encoded_audio_stream_transformer_.HasTransformerCallback());
encoded_audio_stream_transformer_.SetTransformerCallback(
- WTF::BindRepeating(&MockTransformerCallbackHolder::OnEncodedFrame,
- WTF::Unretained(&mock_transformer_callback_holder_)));
+ WTF::CrossThreadBindRepeating(
+ &MockTransformerCallbackHolder::OnEncodedFrame,
+ WTF::CrossThreadUnretained(&mock_transformer_callback_holder_)));
EXPECT_TRUE(encoded_audio_stream_transformer_.HasTransformerCallback());
EXPECT_CALL(mock_transformer_callback_holder_, OnEncodedFrame);
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h
index f1c2a91d74f..78f302729f4 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h
@@ -54,6 +54,8 @@ class PLATFORM_EXPORT RTCIceCandidatePlatform final
String sdp_mid,
absl::optional<uint16_t> sdp_m_line_index,
String username_fragment);
+ RTCIceCandidatePlatform(const RTCIceCandidatePlatform&) = delete;
+ RTCIceCandidatePlatform& operator=(const RTCIceCandidatePlatform&) = delete;
~RTCIceCandidatePlatform() = default;
const String& Candidate() const { return candidate_; }
@@ -92,8 +94,6 @@ class PLATFORM_EXPORT RTCIceCandidatePlatform final
String related_address_;
absl::optional<uint16_t> related_port_;
String username_fragment_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCIceCandidatePlatform);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
index 96c89946915..ce8a088907d 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
@@ -34,6 +34,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h
index a8fbc418c9e..cfa17544993 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h
index a65d67d9756..9c8af577540 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_RTP_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_RTP_SOURCE_H_
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/rtp_receiver_interface.h"
@@ -28,6 +27,8 @@ class PLATFORM_EXPORT RTCRtpSource {
};
explicit RTCRtpSource(const webrtc::RtpSource& source);
+ RTCRtpSource(const RTCRtpSource&) = delete;
+ RTCRtpSource& operator=(const RTCRtpSource&) = delete;
~RTCRtpSource();
Type SourceType() const;
@@ -40,8 +41,6 @@ class PLATFORM_EXPORT RTCRtpSource {
private:
const webrtc::RtpSource source_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCRtpSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc
index 6db77020027..1c60990bf1d 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc
@@ -1,4 +1,10 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h"
+
+#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/api/rtp_headers.h"
#include "third_party/webrtc/api/transport/rtp/rtp_source.h"
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
index 9cfb4b5ab69..0cf5b74587b 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
@@ -9,12 +9,13 @@
#include <string>
#include "base/check_op.h"
+#include "base/containers/cxx20_erase.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/webrtc/api/stats/rtc_stats.h"
#include "third_party/webrtc/api/stats/rtcstats_objects.h"
@@ -301,12 +302,38 @@ Vector<String> RTCStatsMember::ValueSequenceString() const {
DCHECK(IsDefined());
const std::vector<std::string>& sequence =
*member_->cast_to<webrtc::RTCStatsMember<std::vector<std::string>>>();
- Vector<String> wtf_sequence(sequence.size());
- for (size_t i = 0; i < sequence.size(); ++i)
+ Vector<String> wtf_sequence(base::checked_cast<wtf_size_t>(sequence.size()));
+ for (wtf_size_t i = 0; i < wtf_sequence.size(); ++i)
wtf_sequence[i] = String::FromUTF8(sequence[i]);
return wtf_sequence;
}
+HashMap<String, uint64_t> RTCStatsMember::ValueMapStringUint64() const {
+ DCHECK(IsDefined());
+ const std::map<std::string, uint64_t>& map =
+ *member_
+ ->cast_to<webrtc::RTCStatsMember<std::map<std::string, uint64_t>>>();
+ HashMap<String, uint64_t> wtf_map;
+ wtf_map.ReserveCapacityForSize(SafeCast<unsigned>(map.size()));
+ for (auto& elem : map) {
+ wtf_map.insert(String::FromUTF8(elem.first), elem.second);
+ }
+ return wtf_map;
+}
+
+HashMap<String, double> RTCStatsMember::ValueMapStringDouble() const {
+ DCHECK(IsDefined());
+ const std::map<std::string, double>& map =
+ *member_
+ ->cast_to<webrtc::RTCStatsMember<std::map<std::string, double>>>();
+ HashMap<String, double> wtf_map;
+ wtf_map.ReserveCapacityForSize(SafeCast<unsigned>(map.size()));
+ for (auto& elem : map) {
+ wtf_map.insert(String::FromUTF8(elem.first), elem.second);
+ }
+ return wtf_map;
+}
+
rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback>
CreateRTCStatsCollectorCallback(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h
index a17fef2fcc3..46debc1840e 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h
@@ -9,6 +9,7 @@
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.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/text/wtf_string.h"
#include "third_party/webrtc/api/scoped_refptr.h"
#include "third_party/webrtc/api/stats/rtc_stats.h"
@@ -112,6 +113,8 @@ class PLATFORM_EXPORT RTCStatsMember {
Vector<uint64_t> ValueSequenceUint64() const;
Vector<double> ValueSequenceDouble() const;
Vector<String> ValueSequenceString() const;
+ HashMap<String, uint64_t> ValueMapStringUint64() const;
+ HashMap<String, double> ValueMapStringDouble() const;
private:
// Reference to keep the report that owns |member_|'s stats object alive.
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
index ea34dcf6181..a1113c7acef 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
@@ -21,6 +21,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
+#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "media/base/media_log.h"
@@ -92,40 +93,10 @@ class DecoderCounter {
};
DecoderCounter* GetDecoderCounter() {
- static base::NoDestructor<DecoderCounter> s_counter;
+ static DecoderCounter s_counter;
// Note that this will init only in the first call in the ctor, so it's still
// single threaded.
- return s_counter.get();
-}
-
-// Map webrtc::SdpVideoFormat to a guess for media::VideoCodecProfile.
-media::VideoCodecProfile GuessVideoCodecProfile(
- const webrtc::SdpVideoFormat& format) {
- const webrtc::VideoCodecType video_codec_type =
- webrtc::PayloadStringToCodecType(format.name);
- switch (video_codec_type) {
- case webrtc::kVideoCodecVP8:
- return media::VP8PROFILE_ANY;
- case webrtc::kVideoCodecVP9: {
- const webrtc::VP9Profile vp9_profile =
- webrtc::ParseSdpForVP9Profile(format.parameters)
- .value_or(webrtc::VP9Profile::kProfile0);
- switch (vp9_profile) {
- case webrtc::VP9Profile::kProfile2:
- return media::VP9PROFILE_PROFILE2;
- case webrtc::VP9Profile::kProfile1:
- return media::VP9PROFILE_PROFILE1;
- case webrtc::VP9Profile::kProfile0:
- default:
- return media::VP9PROFILE_PROFILE0;
- }
- return media::VP9PROFILE_PROFILE0;
- }
- case webrtc::kVideoCodecH264:
- return media::H264PROFILE_BASELINE;
- default:
- return media::VIDEO_CODEC_PROFILE_UNKNOWN;
- }
+ return &s_counter;
}
void FinishWait(base::WaitableEvent* waiter, bool* result_out, bool result) {
@@ -154,19 +125,6 @@ void RecordReinitializationLatency(base::TimeDelta latency) {
} // namespace
// static
-std::vector<media::VideoDecoderImplementation>
-RTCVideoDecoderAdapter::SupportedImplementations() {
-#if defined(OS_WIN)
- if (base::FeatureList::IsEnabled(media::kD3D11VideoDecoder)) {
- // Push alternate ahead of default to prefer D3D11 decoders over DXVA.
- return {media::VideoDecoderImplementation::kAlternate,
- media::VideoDecoderImplementation::kDefault};
- }
-#endif
- return {media::VideoDecoderImplementation::kDefault};
-}
-
-// static
std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
media::GpuVideoAcceleratorFactories* gpu_factories,
const webrtc::SdpVideoFormat& format) {
@@ -186,41 +144,41 @@ std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
// TODO(sandersd): Predict size from level.
media::VideoDecoderConfig config(
WebRtcToMediaVideoCodec(webrtc::PayloadStringToCodecType(format.name)),
- GuessVideoCodecProfile(format),
+ WebRtcVideoFormatToMediaVideoCodecProfile(format),
media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(),
media::kNoTransformation, kDefaultSize, gfx::Rect(kDefaultSize),
kDefaultSize, media::EmptyExtraData(),
media::EncryptionScheme::kUnencrypted);
- for (auto impl : SupportedImplementations()) {
- std::unique_ptr<RTCVideoDecoderAdapter> rtc_video_decoder_adapter;
- if (gpu_factories->IsDecoderConfigSupported(impl, config) !=
- media::GpuVideoAcceleratorFactories::Supported::kFalse) {
- // Synchronously verify that the decoder can be initialized.
- rtc_video_decoder_adapter = base::WrapUnique(
- new RTCVideoDecoderAdapter(gpu_factories, config, format, impl));
- if (rtc_video_decoder_adapter->InitializeSync(config)) {
- return rtc_video_decoder_adapter;
- }
- // Initialization failed - post delete task and try next supported
- // implementation, if any.
- gpu_factories->GetTaskRunner()->DeleteSoon(
- FROM_HERE, std::move(rtc_video_decoder_adapter));
+ std::unique_ptr<RTCVideoDecoderAdapter> rtc_video_decoder_adapter;
+ if (gpu_factories->IsDecoderConfigSupported(config) !=
+ media::GpuVideoAcceleratorFactories::Supported::kFalse) {
+ // Synchronously verify that the decoder can be initialized.
+ rtc_video_decoder_adapter = base::WrapUnique(
+ new RTCVideoDecoderAdapter(gpu_factories, config, format));
+ if (rtc_video_decoder_adapter->InitializeSync(config)) {
+ return rtc_video_decoder_adapter;
}
+ // Initialization failed - post delete task and try next supported
+ // implementation, if any.
+ gpu_factories->GetTaskRunner()->DeleteSoon(
+ FROM_HERE, std::move(rtc_video_decoder_adapter));
}
+ // To mirror what RTCVideoDecoderStreamAdapter does a little more closely,
+ // record an init failure here. Otherwise, we only ever record successes.
+ base::UmaHistogramBoolean("Media.RTCVideoDecoderInitDecodeSuccess", false);
+
return nullptr;
}
RTCVideoDecoderAdapter::RTCVideoDecoderAdapter(
media::GpuVideoAcceleratorFactories* gpu_factories,
const media::VideoDecoderConfig& config,
- const webrtc::SdpVideoFormat& format,
- media::VideoDecoderImplementation implementation)
+ const webrtc::SdpVideoFormat& format)
: media_task_runner_(gpu_factories->GetTaskRunner()),
gpu_factories_(gpu_factories),
format_(format),
- implementation_(implementation),
config_(config) {
DVLOG(1) << __func__;
DETACH_FROM_SEQUENCE(decoding_sequence_checker_);
@@ -237,6 +195,7 @@ RTCVideoDecoderAdapter::~RTCVideoDecoderAdapter() {
bool RTCVideoDecoderAdapter::InitializeSync(
const media::VideoDecoderConfig& config) {
+ TRACE_EVENT0("webrtc", "RTCVideoDecoderAdapter::InitializeSync");
DVLOG(3) << __func__;
// Can be called on |worker_thread_| or |decoding_thread_|.
DCHECK(!media_task_runner_->RunsTasksInCurrentSequence());
@@ -281,11 +240,13 @@ int32_t RTCVideoDecoderAdapter::InitDecode(
current_resolution_ =
static_cast<int32_t>(codec_settings->width) * codec_settings->height;
- UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", !has_error_);
+ base::UmaHistogramBoolean("Media.RTCVideoDecoderInitDecodeSuccess",
+ !has_error_);
if (!has_error_) {
- UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderProfile",
- GuessVideoCodecProfile(format_),
- media::VIDEO_CODEC_PROFILE_MAX + 1);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.RTCVideoDecoderProfile",
+ WebRtcVideoFormatToMediaVideoCodecProfile(format_),
+ media::VIDEO_CODEC_PROFILE_MAX + 1);
}
return has_error_ ? WEBRTC_VIDEO_CODEC_UNINITIALIZED : WEBRTC_VIDEO_CODEC_OK;
}
@@ -324,21 +285,14 @@ int32_t RTCVideoDecoderAdapter::Decode(const webrtc::EncodedImage& input_image,
}
}
- // Hardware VP9 decoders don't handle more than one spatial layer. Fall back
- // to software decoding. See https://crbug.com/webrtc/9304.
+ // Fall back to software decoding if there's no support for VP9 spatial
+ // layers. See https://crbug.com/webrtc/9304.
if (video_codec_type_ == webrtc::kVideoCodecVP9 &&
- input_image.SpatialIndex().value_or(0) > 0) {
-#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
- if (!base::FeatureList::IsEnabled(media::kVp9kSVCHWDecoding)) {
- RecordRTCVideoDecoderFallbackReason(
- config_.codec(), RTCVideoDecoderFallbackReason::kSpatialLayers);
- return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
- }
-#else
+ input_image.SpatialIndex().value_or(0) > 0 &&
+ !Vp9HwSupportForSpatialLayers()) {
RecordRTCVideoDecoderFallbackReason(
config_.codec(), RTCVideoDecoderFallbackReason::kSpatialLayers);
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
-#endif // defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
}
if (missing_frames) {
@@ -361,12 +315,13 @@ int32_t RTCVideoDecoderAdapter::Decode(const webrtc::EncodedImage& input_image,
}
std::vector<uint32_t> spatial_layer_frame_size;
- size_t max_sl_index = input_image.SpatialIndex().value_or(0);
- for (size_t i = 0; i <= max_sl_index; i++) {
+ int max_sl_index = input_image.SpatialIndex().value_or(0);
+ for (int i = 0; i <= max_sl_index; i++) {
auto frame_size = input_image.SpatialLayerFrameSize(i);
if (!frame_size)
continue;
- spatial_layer_frame_size.push_back(*frame_size);
+ spatial_layer_frame_size.push_back(
+ base::checked_cast<uint32_t>(*frame_size));
}
// Convert to media::DecoderBuffer.
@@ -485,8 +440,7 @@ void RTCVideoDecoderAdapter::InitializeOnMediaThread(
media_log_ = std::make_unique<media::NullMediaLog>();
video_decoder_ = gpu_factories_->CreateVideoDecoder(
- media_log_.get(), implementation_,
- WTF::BindRepeating(&OnRequestOverlayInfo));
+ media_log_.get(), WTF::BindRepeating(&OnRequestOverlayInfo));
if (!video_decoder_) {
PostCrossThreadTask(*media_task_runner_.get(), FROM_HERE,
@@ -575,7 +529,8 @@ void RTCVideoDecoderAdapter::OnOutput(scoped_refptr<media::VideoFrame> frame) {
webrtc::VideoFrame rtc_frame =
webrtc::VideoFrame::Builder()
.set_video_frame_buffer(
- CreateWebRtcVideoFrameAdapter(std::move(frame)))
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ std::move(frame)))
.set_timestamp_rtp(static_cast<uint32_t>(timestamp.InMicroseconds()))
.set_timestamp_us(0)
.set_rotation(webrtc::kVideoRotation_0)
@@ -692,4 +647,13 @@ void RTCVideoDecoderAdapter::DecrementCurrentDecoderCountForTesting() {
GetDecoderCounter()->DecrementCount();
}
+// static
+bool RTCVideoDecoderAdapter::Vp9HwSupportForSpatialLayers() {
+ // Most hardware VP9 decoders don't handle more than one spatial layer.
+#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
+ return base::FeatureList::IsEnabled(media::kVaapiVp9kSVCHWDecoding);
+#endif
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
index 378d28381e4..073294ae44b 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
@@ -69,11 +68,6 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
// resolution streams, but they'll fall back if they adapt below the limit.
static constexpr int32_t kMaxDecoderInstances = 8;
- // Lists which implementations can be queried, this can vary based on platform
- // and enabled features.
- static std::vector<media::VideoDecoderImplementation>
- SupportedImplementations();
-
// Creates and initializes an RTCVideoDecoderAdapter. Returns nullptr if
// |format| cannot be supported.
// Called on the worker thread.
@@ -81,6 +75,9 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
media::GpuVideoAcceleratorFactories* gpu_factories,
const webrtc::SdpVideoFormat& format);
+ RTCVideoDecoderAdapter(const RTCVideoDecoderAdapter&) = delete;
+ RTCVideoDecoderAdapter& operator=(const RTCVideoDecoderAdapter&) = delete;
+
// Called on |media_task_runner_|.
~RTCVideoDecoderAdapter() override;
@@ -105,6 +102,11 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
static void IncrementCurrentDecoderCountForTesting();
static void DecrementCurrentDecoderCountForTesting();
+ // Returns true if there's VP9 HW support for spatial layers. Please note that
+ // the response from this function implicitly assumes that HW decoding is
+ // enabled and that VP9 decoding is supported in HW.
+ static bool Vp9HwSupportForSpatialLayers();
+
private:
using CreateVideoDecoderCB =
base::RepeatingCallback<std::unique_ptr<media::VideoDecoder>(
@@ -115,8 +117,7 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
// Called on the worker thread.
RTCVideoDecoderAdapter(media::GpuVideoAcceleratorFactories* gpu_factories,
const media::VideoDecoderConfig& config,
- const webrtc::SdpVideoFormat& format,
- media::VideoDecoderImplementation implementation);
+ const webrtc::SdpVideoFormat& format);
bool InitializeSync(const media::VideoDecoderConfig& config);
void InitializeOnMediaThread(const media::VideoDecoderConfig& config,
@@ -137,7 +138,6 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
const scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
media::GpuVideoAcceleratorFactories* const gpu_factories_;
const webrtc::SdpVideoFormat format_;
- const media::VideoDecoderImplementation implementation_;
media::VideoDecoderConfig config_;
// Media thread members.
@@ -173,13 +173,10 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
// Thread management.
SEQUENCE_CHECKER(media_sequence_checker_);
- SEQUENCE_CHECKER(worker_sequence_checker_);
SEQUENCE_CHECKER(decoding_sequence_checker_);
base::WeakPtr<RTCVideoDecoderAdapter> weak_this_;
base::WeakPtrFactory<RTCVideoDecoderAdapter> weak_this_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderAdapter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc
index a98729411da..02240dc85ab 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/gmock_callback_support.h"
@@ -85,6 +84,8 @@ class DecodedImageCallback : public webrtc::DecodedImageCallback {
DecodedImageCallback(
base::RepeatingCallback<void(const webrtc::VideoFrame&)> callback)
: callback_(callback) {}
+ DecodedImageCallback(const DecodedImageCallback&) = delete;
+ DecodedImageCallback& operator=(const DecodedImageCallback&) = delete;
int32_t Decoded(webrtc::VideoFrame& decodedImage) override {
callback_.Run(decodedImage);
@@ -95,14 +96,15 @@ class DecodedImageCallback : public webrtc::DecodedImageCallback {
private:
base::RepeatingCallback<void(const webrtc::VideoFrame&)> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(DecodedImageCallback);
};
} // namespace
class RTCVideoDecoderAdapterTest : public ::testing::Test {
public:
+ RTCVideoDecoderAdapterTest(const RTCVideoDecoderAdapterTest&) = delete;
+ RTCVideoDecoderAdapterTest& operator=(const RTCVideoDecoderAdapterTest&) =
+ delete;
RTCVideoDecoderAdapterTest()
: media_thread_("Media Thread"),
gpu_factories_(nullptr),
@@ -118,16 +120,14 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
.WillByDefault(Return(media_thread_.task_runner()));
EXPECT_CALL(gpu_factories_, GetTaskRunner()).Times(AtLeast(0));
- ON_CALL(gpu_factories_, IsDecoderConfigSupported(_, _))
+ ON_CALL(gpu_factories_, IsDecoderConfigSupported(_))
.WillByDefault(
Return(media::GpuVideoAcceleratorFactories::Supported::kTrue));
- EXPECT_CALL(gpu_factories_, IsDecoderConfigSupported(_, _))
- .Times(AtLeast(0));
+ EXPECT_CALL(gpu_factories_, IsDecoderConfigSupported(_)).Times(AtLeast(0));
- ON_CALL(gpu_factories_, CreateVideoDecoder(_, _, _))
+ ON_CALL(gpu_factories_, CreateVideoDecoder(_, _))
.WillByDefault(
[this](media::MediaLog* media_log,
- media::VideoDecoderImplementation impl,
const media::RequestOverlayInfoCB& request_overlay_info_cb) {
// If gpu factories tries to get a second video decoder, for
// testing purposes we will just return null.
@@ -135,7 +135,7 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
// decoder is null.
return std::move(owned_video_decoder_);
});
- EXPECT_CALL(gpu_factories_, CreateVideoDecoder(_, _, _)).Times(AtLeast(0));
+ EXPECT_CALL(gpu_factories_, CreateVideoDecoder(_, _)).Times(AtLeast(0));
}
~RTCVideoDecoderAdapterTest() {
@@ -259,8 +259,6 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
std::unique_ptr<StrictMock<MockVideoDecoder>> owned_video_decoder_;
DecodedImageCallback decoded_image_callback_;
media::VideoDecoder::OutputCB output_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderAdapterTest);
};
TEST_F(RTCVideoDecoderAdapterTest, Create_UnknownFormat) {
@@ -271,7 +269,7 @@ TEST_F(RTCVideoDecoderAdapterTest, Create_UnknownFormat) {
}
TEST_F(RTCVideoDecoderAdapterTest, Create_UnsupportedFormat) {
- EXPECT_CALL(gpu_factories_, IsDecoderConfigSupported(_, _))
+ EXPECT_CALL(gpu_factories_, IsDecoderConfigSupported(_))
.WillRepeatedly(
Return(media::GpuVideoAcceleratorFactories::Supported::kFalse));
rtc_video_decoder_adapter_ = RTCVideoDecoderAdapter::Create(
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
index e036ecbd5a0..a589c50aecf 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
@@ -7,10 +7,12 @@
#include <array>
#include <memory>
+#include "base/check.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
+#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#include "media/base/decoder_factory.h"
#include "media/base/media_util.h"
@@ -18,6 +20,7 @@
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h"
+#include "third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h"
#include "third_party/webrtc/media/base/h264_profile_level_id.h"
#include "third_party/webrtc/media/base/media_constants.h"
#include "third_party/webrtc/media/base/vp9_profile.h"
@@ -234,14 +237,10 @@ RTCVideoDecoderFactory::GetSupportedFormats() const {
// The RTCVideoDecoderAdapter is for HW decoders only, so ignore it if there
// are no gpu_factories_.
- if (gpu_factories_) {
- for (auto impl : RTCVideoDecoderAdapter::SupportedImplementations()) {
- if (gpu_factories_->IsDecoderConfigSupported(impl, config) ==
+ if (gpu_factories_ &&
+ gpu_factories_->IsDecoderConfigSupported(config) ==
media::GpuVideoAcceleratorFactories::Supported::kTrue) {
- format = VdcToWebRtcFormat(config);
- break;
- }
- }
+ format = VdcToWebRtcFormat(config);
}
if (base::FeatureList::IsEnabled(media::kUseDecoderStreamForWebRTC) &&
@@ -262,6 +261,75 @@ RTCVideoDecoderFactory::GetSupportedFormats() const {
return supported_formats;
}
+webrtc::VideoDecoderFactory::CodecSupport
+RTCVideoDecoderFactory::QueryCodecSupport(
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) const {
+ media::VideoCodec codec =
+ WebRtcToMediaVideoCodec(webrtc::PayloadStringToCodecType(format.name));
+ if (scalability_mode) {
+ absl::optional<int> spatial_layers =
+ WebRtcScalabilityModeSpatialLayers(*scalability_mode);
+
+ // Check that the scalability mode was correctly parsed and that the
+ // configuration is valid (e.g., H264 doesn't support SVC at all and VP8
+ // doesn't support spatial layers).
+ if (!spatial_layers ||
+ (codec != media::kCodecVP8 && codec != media::kCodecVP9 &&
+ codec != media::kCodecAV1) ||
+ (codec == media::kCodecVP8 && *spatial_layers > 1)) {
+ // Ivalid scalability_mode, return unsupported.
+ return {false, false};
+ }
+ DCHECK(spatial_layers);
+ // Most HW decoders cannot handle spatial layers, so return false if the
+ // configuration contains spatial layers unless we explicitly know that the
+ // HW decoder can handle spatial layers.
+ if (codec == media::kCodecVP9 && *spatial_layers > 1 &&
+ !RTCVideoDecoderAdapter::Vp9HwSupportForSpatialLayers()) {
+ return {false, false};
+ }
+ }
+
+ CheckAndWaitDecoderSupportStatusIfNeeded();
+
+ media::VideoCodecProfile codec_profile =
+ WebRtcVideoFormatToMediaVideoCodecProfile(format);
+ media::VideoDecoderConfig config(
+ codec, codec_profile, media::VideoDecoderConfig::AlphaMode::kIsOpaque,
+ media::VideoColorSpace(), media::kNoTransformation, kDefaultSize,
+ gfx::Rect(kDefaultSize), kDefaultSize, media::EmptyExtraData(),
+ media::EncryptionScheme::kUnencrypted);
+
+ webrtc::VideoDecoderFactory::CodecSupport codec_support;
+ // Check gpu_factories for powerEfficient.
+ if (gpu_factories_) {
+ if (gpu_factories_->IsDecoderConfigSupported(config) ==
+ media::GpuVideoAcceleratorFactories::Supported::kTrue) {
+ codec_support.is_power_efficient = true;
+ }
+ }
+
+ // The codec must be supported if it's power efficient.
+ codec_support.is_supported = codec_support.is_power_efficient;
+
+ // RtcDecoderStreamAdapter supports all codecs with HW support and potentially
+ // a few codecs in SW.
+ if (!codec_support.is_supported &&
+ base::FeatureList::IsEnabled(media::kUseDecoderStreamForWebRTC)) {
+ media::SupportedVideoDecoderConfigs supported_decoder_factory_configs =
+ decoder_factory_->GetSupportedVideoDecoderConfigsForWebRTC();
+ for (auto& supported_config : supported_decoder_factory_configs) {
+ if (supported_config.Matches(config)) {
+ codec_support.is_supported = true;
+ break;
+ }
+ }
+ }
+
+ return codec_support;
+}
+
RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
DVLOG(2) << __func__;
}
@@ -269,6 +337,7 @@ RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
std::unique_ptr<webrtc::VideoDecoder>
RTCVideoDecoderFactory::CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) {
+ TRACE_EVENT0("webrtc", "RTCVideoDecoderFactory::CreateVideoDecoder");
DVLOG(2) << __func__;
CheckAndWaitDecoderSupportStatusIfNeeded();
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h
index e0b06b97e92..6503dcfec3a 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/peerconnection/gpu_codec_support_waiter.h"
#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
@@ -30,6 +29,8 @@ class RTCVideoDecoderFactory : public webrtc::VideoDecoderFactory {
media::DecoderFactory* decoder_factory,
scoped_refptr<base::SequencedTaskRunner> media_task_runner,
const gfx::ColorSpace& render_color_space);
+ RTCVideoDecoderFactory(const RTCVideoDecoderFactory&) = delete;
+ RTCVideoDecoderFactory& operator=(const RTCVideoDecoderFactory&) = delete;
~RTCVideoDecoderFactory() override;
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
@@ -39,6 +40,10 @@ class RTCVideoDecoderFactory : public webrtc::VideoDecoderFactory {
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
+ webrtc::VideoDecoderFactory::CodecSupport QueryCodecSupport(
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) const override;
+
private:
void CheckAndWaitDecoderSupportStatusIfNeeded() const;
media::GpuVideoAcceleratorFactories* gpu_factories_;
@@ -48,8 +53,6 @@ class RTCVideoDecoderFactory : public webrtc::VideoDecoderFactory {
gfx::ColorSpace render_color_space_;
std::unique_ptr<GpuCodecSupportWaiter> gpu_codec_support_waiter_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.cc
index 3c7402359fd..e1bd4a9ec2f 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.cc
@@ -8,6 +8,7 @@
#include <functional>
#include <utility>
+#include "base/atomic_ref_count.h"
#include "base/callback_helpers.h"
#include "base/containers/circular_deque.h"
#include "base/feature_list.h"
@@ -17,7 +18,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
@@ -32,6 +32,7 @@
#include "media/video/gpu_video_accelerator_factories.h"
#include "media/video/video_decode_accelerator.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_fallback_recorder.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
@@ -74,36 +75,15 @@ constexpr int32_t kMaxPendingBuffers = 8;
// never completed, or (c) we're hopelessly behind.
constexpr int32_t kAbsoluteMaxPendingBuffers = 32;
-// Map webrtc::SdpVideoFormat to a guess for media::VideoCodecProfile.
-media::VideoCodecProfile GuessVideoCodecProfile(
- const webrtc::SdpVideoFormat& format) {
- const webrtc::VideoCodecType video_codec_type =
- webrtc::PayloadStringToCodecType(format.name);
- switch (video_codec_type) {
- case webrtc::kVideoCodecAV1:
- return media::AV1PROFILE_PROFILE_MAIN;
- case webrtc::kVideoCodecVP8:
- return media::VP8PROFILE_ANY;
- case webrtc::kVideoCodecVP9: {
- const webrtc::VP9Profile vp9_profile =
- webrtc::ParseSdpForVP9Profile(format.parameters)
- .value_or(webrtc::VP9Profile::kProfile0);
- switch (vp9_profile) {
- case webrtc::VP9Profile::kProfile2:
- return media::VP9PROFILE_PROFILE2;
- case webrtc::VP9Profile::kProfile1:
- return media::VP9PROFILE_PROFILE1;
- case webrtc::VP9Profile::kProfile0:
- default:
- return media::VP9PROFILE_PROFILE0;
- }
- return media::VP9PROFILE_PROFILE0;
- }
- case webrtc::kVideoCodecH264:
- return media::H264PROFILE_BASELINE;
- default:
- return media::VIDEO_CODEC_PROFILE_UNKNOWN;
- }
+// Name we'll report for hardware decoders.
+constexpr const char* kExternalDecoderName = "ExternalDecoder";
+
+// Number of RTCVideoDecoder instances right now that have started decoding.
+std::atomic_int* GetDecoderCounter() {
+ static std::atomic_int s_counter(0);
+ // Note that this will init only in the first call in the ctor, so it's still
+ // single threaded.
+ return &s_counter;
}
void RecordInitializationLatency(base::TimeDelta latency) {
@@ -113,6 +93,9 @@ void RecordInitializationLatency(base::TimeDelta latency) {
} // namespace
+// static
+constexpr gfx::Size RTCVideoDecoderStreamAdapter::kMinResolution;
+
// DemuxerStream implementation that forwards DecoderBuffer from some other
// source (i.e., VideoDecoder::Decode).
class RTCVideoDecoderStreamAdapter::InternalDemuxerStream
@@ -243,7 +226,7 @@ RTCVideoDecoderStreamAdapter::Create(
// TODO(sandersd): Predict size from level.
media::VideoDecoderConfig config(
WebRtcToMediaVideoCodec(webrtc::PayloadStringToCodecType(format.name)),
- GuessVideoCodecProfile(format),
+ WebRtcVideoFormatToMediaVideoCodecProfile(format),
media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(),
media::kNoTransformation, kDefaultSize, gfx::Rect(kDefaultSize),
kDefaultSize, media::EmptyExtraData(),
@@ -277,7 +260,10 @@ RTCVideoDecoderStreamAdapter::RTCVideoDecoderStreamAdapter(
config_(config),
max_pending_buffer_count_(kAbsoluteMaxPendingBuffers) {
DVLOG(1) << __func__;
- decoder_info_.implementation_name = "unknown";
+ // Default to hw-accelerated decoder, in case something checks before decoding
+ // a frame. It's unclear what we should report in the long run, but for now,
+ // it's better to report hardware since that's all we support anyway.
+ decoder_info_.implementation_name = kExternalDecoderName;
decoder_info_.is_hardware_accelerated = false;
DETACH_FROM_SEQUENCE(decoding_sequence_checker_);
weak_this_ = weak_this_factory_.GetWeakPtr();
@@ -286,6 +272,9 @@ RTCVideoDecoderStreamAdapter::RTCVideoDecoderStreamAdapter(
RTCVideoDecoderStreamAdapter::~RTCVideoDecoderStreamAdapter() {
DVLOG(1) << __func__;
DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+
+ if (have_started_decoding_)
+ --(*GetDecoderCounter());
}
void RTCVideoDecoderStreamAdapter::InitializeSync(
@@ -321,6 +310,8 @@ int32_t RTCVideoDecoderStreamAdapter::InitDecode(
base::AutoLock auto_lock(lock_);
init_decode_complete_ = true;
+ current_resolution_ =
+ gfx::Size(codec_settings->width, codec_settings->height);
AttemptLogInitializationState_Locked();
return has_error_ ? WEBRTC_VIDEO_CODEC_UNINITIALIZED : WEBRTC_VIDEO_CODEC_OK;
}
@@ -340,11 +331,13 @@ void RTCVideoDecoderStreamAdapter::AttemptLogInitializationState_Locked() {
logged_init_status_ = true;
- UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", !has_error_);
+ base::UmaHistogramBoolean("Media.RTCVideoDecoderInitDecodeSuccess",
+ !has_error_);
if (!has_error_) {
- UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderProfile",
- GuessVideoCodecProfile(format_),
- media::VIDEO_CODEC_PROFILE_MAX + 1);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.RTCVideoDecoderProfile",
+ WebRtcVideoFormatToMediaVideoCodecProfile(format_),
+ media::VIDEO_CODEC_PROFILE_MAX + 1);
}
}
@@ -355,23 +348,48 @@ int32_t RTCVideoDecoderStreamAdapter::Decode(
DVLOG(2) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(decoding_sequence_checker_);
- // Hardware VP9 decoders don't handle more than one spatial layer. Fall back
- // to software decoding. See https://crbug.com/webrtc/9304.
- if (video_codec_type_ == webrtc::kVideoCodecVP9 &&
- input_image.SpatialIndex().value_or(0) > 0) {
-#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
- if (!base::FeatureList::IsEnabled(media::kVp9kSVCHWDecoding)) {
- DLOG(ERROR) << __func__ << " multiple spatial layers.";
- RecordRTCVideoDecoderFallbackReason(
- config_.codec(), RTCVideoDecoderFallbackReason::kSpatialLayers);
+ // If this is the first decode, then increment the count of working decoders.
+ if (!have_started_decoding_) {
+ have_started_decoding_ = true;
+ ++(*GetDecoderCounter());
+ }
+
+#if defined(OS_ANDROID) && !BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+ const bool has_software_fallback =
+ video_codec_type_ != webrtc::kVideoCodecH264;
+#else
+ const bool has_software_fallback = true;
+#endif
+
+ // Don't allow hardware decode for small videos if there are too many
+ // decoder instances. This includes the case where our resolution drops while
+ // too many decoders exist. When DecoderStream supports software decoders,
+ // this should be moved to DecoderSelector.
+ {
+ base::AutoLock auto_lock(lock_);
+ if (has_software_fallback &&
+ current_resolution_.GetArea() < kMinResolution.GetArea() &&
+ GetDecoderCounter()->load() > kMaxDecoderInstances) {
+ // Decrement the count and clear the flag, so that other decoders don't
+ // fall back also.
+ have_started_decoding_ = false;
+ --(*GetDecoderCounter());
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
}
-#else
+ }
+
+ // Fall back to software decoding if there's no support for VP9 spatial
+ // layers. See https://crbug.com/webrtc/9304.
+ // TODO(chromium:1187565): Update RTCVideoDecoderFactory::QueryCodecSupport()
+ // if RTCVideoDecoderStream is changed to handle SW decoding and not return
+ // WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE.
+ if (video_codec_type_ == webrtc::kVideoCodecVP9 &&
+ input_image.SpatialIndex().value_or(0) > 0 &&
+ !RTCVideoDecoderAdapter::Vp9HwSupportForSpatialLayers()) {
DLOG(ERROR) << __func__ << " multiple spatial layers.";
RecordRTCVideoDecoderFallbackReason(
config_.codec(), RTCVideoDecoderFallbackReason::kSpatialLayers);
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
-#endif // defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
}
if (missing_frames) {
@@ -394,12 +412,13 @@ int32_t RTCVideoDecoderStreamAdapter::Decode(
}
std::vector<uint32_t> spatial_layer_frame_size;
- size_t max_sl_index = input_image.SpatialIndex().value_or(0);
- for (size_t i = 0; i <= max_sl_index; i++) {
+ int max_sl_index = input_image.SpatialIndex().value_or(0);
+ for (int i = 0; i <= max_sl_index; i++) {
auto frame_size = input_image.SpatialLayerFrameSize(i);
if (!frame_size)
continue;
- spatial_layer_frame_size.push_back(*frame_size);
+ spatial_layer_frame_size.push_back(
+ base::checked_cast<uint32_t>(*frame_size));
}
// Convert to media::DecoderBuffer.
@@ -449,12 +468,6 @@ int32_t RTCVideoDecoderStreamAdapter::Decode(
// drop any other non-key frame.
key_frame_required_ = true;
-#if defined(OS_ANDROID) && !BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
- const bool has_software_fallback =
- video_codec_type_ != webrtc::kVideoCodecH264;
-#else
- const bool has_software_fallback = true;
-#endif
// If we hit the absolute limit, then give up.
if (has_software_fallback &&
pending_buffer_count_ >= kAbsoluteMaxPendingBuffers) {
@@ -665,7 +678,8 @@ void RTCVideoDecoderStreamAdapter::OnFrameReady(
webrtc::VideoFrame rtc_frame =
webrtc::VideoFrame::Builder()
.set_video_frame_buffer(
- CreateWebRtcVideoFrameAdapter(std::move(frame)))
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ std::move(frame)))
.set_timestamp_rtp(static_cast<uint32_t>(timestamp.InMicroseconds()))
.set_timestamp_us(0)
.set_rotation(webrtc::kVideoRotation_0)
@@ -681,6 +695,10 @@ void RTCVideoDecoderStreamAdapter::OnFrameReady(
start_time_.reset();
}
+ // Update `current_resolution_`, in case it's changed. This lets us fall back
+ // to software, or avoid doing so, if we're over the decoder limit.
+ current_resolution_ = gfx::Size(rtc_frame.width(), rtc_frame.height());
+
// Try to read the next output, if any, regardless if this succeeded.
AttemptRead_Locked();
@@ -810,7 +828,7 @@ void RTCVideoDecoderStreamAdapter::OnDecoderChanged(
decoder_info_.is_hardware_accelerated = decoder->IsPlatformDecoder();
decoder_info_.implementation_name =
decoder->IsPlatformDecoder()
- ? "ExternalDecoder"
+ ? kExternalDecoderName
: media::GetDecoderName(decoder->GetDecoderType()) +
" (DecoderStream)";
}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h
index 6f1b5755913..ef362b4f905 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
@@ -62,6 +61,20 @@ namespace blink {
class PLATFORM_EXPORT RTCVideoDecoderStreamAdapter
: public webrtc::VideoDecoder {
public:
+ // Minimum resolution that we'll consider "not low resolution" for the purpose
+ // of falling back to software.
+#if defined(OS_CHROMEOS)
+ // Effectively opt-out CrOS, since it may cause tests to fail (b/179724180).
+ static constexpr gfx::Size kMinResolution{2, 2};
+#else
+ static constexpr gfx::Size kMinResolution{320, 240};
+#endif
+
+ // Maximum number of decoder instances we'll allow before fallback to software
+ // if the resolution is too low. We'll allow more than this for high
+ // resolution streams, but they'll fall back if they adapt below the limit.
+ static constexpr int32_t kMaxDecoderInstances = 8;
+
// Creates and initializes an RTCVideoDecoderStreamAdapter. Returns nullptr if
// |format| cannot be supported. The gpu_factories may be null, in which case
// only SW decoders will be used.
@@ -73,6 +86,10 @@ class PLATFORM_EXPORT RTCVideoDecoderStreamAdapter
const gfx::ColorSpace& render_color_space,
const webrtc::SdpVideoFormat& format);
+ RTCVideoDecoderStreamAdapter(const RTCVideoDecoderStreamAdapter&) = delete;
+ RTCVideoDecoderStreamAdapter& operator=(const RTCVideoDecoderStreamAdapter&) =
+ delete;
+
// Called on |media_task_runner_|.
~RTCVideoDecoderStreamAdapter() override;
@@ -161,6 +178,8 @@ class PLATFORM_EXPORT RTCVideoDecoderStreamAdapter
// Decoding thread members.
bool key_frame_required_ = true;
webrtc::VideoCodecType video_codec_type_ = webrtc::kVideoCodecGeneric;
+ // Has anything been sent to Decode() yet?
+ bool have_started_decoding_ = false;
// Shared members.
mutable base::Lock lock_;
@@ -184,6 +203,10 @@ class PLATFORM_EXPORT RTCVideoDecoderStreamAdapter
// Time since construction. Cleared when we record that a frame has been
// successfully decoded.
absl::optional<base::TimeTicks> start_time_ GUARDED_BY(lock_);
+ // Resolution of most recently decoded frame, or the initial resolution if we
+ // haven't decoded anything yet. Since this is updated asynchronously, it's
+ // only an approximation of "most recently".
+ gfx::Size current_resolution_ GUARDED_BY(lock_);
// Do we have an outstanding `DecoderStream::Read()`?
// Media thread only.
@@ -202,8 +225,6 @@ class PLATFORM_EXPORT RTCVideoDecoderStreamAdapter
base::WeakPtr<RTCVideoDecoderStreamAdapter> weak_this_;
base::WeakPtrFactory<RTCVideoDecoderStreamAdapter> weak_this_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderStreamAdapter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter_test.cc
index 788e4f6d90e..f4794bb6b00 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter_test.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/thread_pool.h"
@@ -118,6 +117,8 @@ class DecodedImageCallback : public webrtc::DecodedImageCallback {
explicit DecodedImageCallback(
base::RepeatingCallback<void(const webrtc::VideoFrame&)> callback)
: callback_(callback) {}
+ DecodedImageCallback(const DecodedImageCallback&) = delete;
+ DecodedImageCallback& operator=(const DecodedImageCallback&) = delete;
int32_t Decoded(webrtc::VideoFrame& decodedImage) override {
callback_.Run(decodedImage);
@@ -128,8 +129,6 @@ class DecodedImageCallback : public webrtc::DecodedImageCallback {
private:
base::RepeatingCallback<void(const webrtc::VideoFrame&)> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(DecodedImageCallback);
};
} // namespace
@@ -148,6 +147,11 @@ class RTCVideoDecoderStreamAdapterTest : public ::testing::TestWithParam<bool> {
decoder_factory_ = std::make_unique<MockDecoderFactory>();
}
+ RTCVideoDecoderStreamAdapterTest(const RTCVideoDecoderStreamAdapterTest&) =
+ delete;
+ RTCVideoDecoderStreamAdapterTest& operator=(
+ const RTCVideoDecoderStreamAdapterTest&) = delete;
+
~RTCVideoDecoderStreamAdapterTest() override {
if (!adapter_)
return;
@@ -272,8 +276,6 @@ class RTCVideoDecoderStreamAdapterTest : public ::testing::TestWithParam<bool> {
webrtc::SdpVideoFormat sdp_format_;
media::VideoDecoderConfig vda_config_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderStreamAdapterTest);
};
TEST_P(RTCVideoDecoderStreamAdapterTest, Create_UnknownFormat) {
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
index 4f5b793af90..bc987a0977f 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -10,21 +10,24 @@
#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/thread_annotations.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/bitrate.h"
#include "media/base/bitstream_buffer.h"
+#include "media/base/media_switches.h"
#include "media/base/video_bitrate_allocation.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
@@ -199,12 +202,38 @@ webrtc::VideoEncoder::EncoderInfo CopyToWebrtcEncoderInfo(
return info;
}
+media::VideoEncodeAccelerator::Config::InterLayerPredMode
+CopyFromWebRtcInterLayerPredMode(
+ const webrtc::InterLayerPredMode inter_layer_pred) {
+ switch (inter_layer_pred) {
+ case webrtc::InterLayerPredMode::kOff:
+ return media::VideoEncodeAccelerator::Config::InterLayerPredMode::kOff;
+ case webrtc::InterLayerPredMode::kOn:
+ return media::VideoEncodeAccelerator::Config::InterLayerPredMode::kOn;
+ case webrtc::InterLayerPredMode::kOnKeyPic:
+ return media::VideoEncodeAccelerator::Config::InterLayerPredMode::
+ kOnKeyPic;
+ }
+}
+
// Create VEA::Config::SpatialLayer from |codec_settings|. If some config of
// |codec_settings| is not supported, returns false.
bool CreateSpatialLayersConfig(
const webrtc::VideoCodec& codec_settings,
std::vector<media::VideoEncodeAccelerator::Config::SpatialLayer>*
- spatial_layers) {
+ spatial_layers,
+ media::VideoEncodeAccelerator::Config::InterLayerPredMode*
+ inter_layer_pred) {
+ if (codec_settings.codecType == webrtc::kVideoCodecH264 &&
+ codec_settings.H264().numberOfTemporalLayers > 1 &&
+ !RTCVideoEncoder::H264HwSupportForTemporalLayers()) {
+ DVLOG(1) << "H264 temporal layers not yet supported by HW codecs, but use"
+ << " HW codecs and leave the fallback decision to a webrtc client"
+ << " by seeing metadata in webrtc::CodecSpecificInfo";
+
+ return true;
+ }
+
if (codec_settings.codecType == webrtc::kVideoCodecVP8 &&
codec_settings.mode == webrtc::VideoCodecMode::kScreensharing &&
codec_settings.VP8().numberOfTemporalLayers > 1) {
@@ -219,15 +248,33 @@ bool CreateSpatialLayersConfig(
return false;
}
}
+
if (codec_settings.codecType == webrtc::kVideoCodecVP9 &&
- codec_settings.VP9().numberOfSpatialLayers > 1) {
+ codec_settings.VP9().numberOfSpatialLayers > 1 &&
+ !RTCVideoEncoder::Vp9HwSupportForSpatialLayers()) {
DVLOG(1)
- << "VP9 SVC not yet supported by HW codecs, falling back to sofware.";
+ << "VP9 SVC not yet supported by HW codecs, falling back to software.";
return false;
}
// We fill SpatialLayer only in temporal layer or spatial layer encoding.
switch (codec_settings.codecType) {
+ case webrtc::kVideoCodecH264:
+ if (codec_settings.H264().numberOfTemporalLayers > 1) {
+ // Though we don't support H264 SVC. We allocate 1 element in
+ // spatial_layers for temporal layer encoding.
+ spatial_layers->resize(1u);
+ auto& sl = (*spatial_layers)[0];
+ sl.width = codec_settings.width;
+ sl.height = codec_settings.height;
+ if (!ConvertKbpsToBps(codec_settings.startBitrate, &sl.bitrate_bps))
+ return false;
+ sl.framerate = codec_settings.maxFramerate;
+ sl.max_qp = base::saturated_cast<uint8_t>(codec_settings.qpMax);
+ sl.num_of_temporal_layers = base::saturated_cast<uint8_t>(
+ codec_settings.H264().numberOfTemporalLayers);
+ }
+ break;
case webrtc::kVideoCodecVP8:
if (codec_settings.VP8().numberOfTemporalLayers > 1) {
// Though there is no SVC in VP8 spec. We allocate 1 element in
@@ -249,15 +296,17 @@ bool CreateSpatialLayersConfig(
// SpatialLayer is not filled.
if (codec_settings.VP9().numberOfTemporalLayers > 1 ||
codec_settings.VP9().numberOfSpatialLayers > 1) {
- spatial_layers->resize(codec_settings.VP9().numberOfSpatialLayers);
- for (size_t i = 0; i < spatial_layers->size(); ++i) {
+ spatial_layers->clear();
+ for (size_t i = 0; i < codec_settings.VP9().numberOfSpatialLayers;
+ ++i) {
const webrtc::SpatialLayer& rtc_sl = codec_settings.spatialLayers[i];
// We ignore non active spatial layer and don't proceed further. There
// must NOT be an active higher spatial layer than non active spatial
// layer.
if (!rtc_sl.active)
break;
- auto& sl = (*spatial_layers)[i];
+ spatial_layers->emplace_back();
+ auto& sl = spatial_layers->back();
sl.width = base::checked_cast<int32_t>(rtc_sl.width);
sl.height = base::checked_cast<int32_t>(rtc_sl.height);
if (!ConvertKbpsToBps(rtc_sl.targetBitrate, &sl.bitrate_bps))
@@ -267,6 +316,16 @@ bool CreateSpatialLayersConfig(
sl.num_of_temporal_layers =
base::saturated_cast<uint8_t>(rtc_sl.numberOfTemporalLayers);
}
+
+ if (spatial_layers->size() == 1 &&
+ spatial_layers->at(0).num_of_temporal_layers == 1) {
+ // Don't report spatial layers if only the base layer is active and we
+ // have no temporar layers configured.
+ spatial_layers->clear();
+ } else {
+ *inter_layer_pred = CopyFromWebRtcInterLayerPredMode(
+ codec_settings.VP9().interLayerPred);
+ }
}
break;
default:
@@ -337,6 +396,8 @@ class RTCVideoEncoder::Impl
Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
webrtc::VideoCodecType video_codec_type,
webrtc::VideoContentType video_content_type);
+ Impl(const Impl&) = delete;
+ Impl& operator=(const Impl&) = delete;
// Create the VEA and call Initialize() on it. Called once per instantiation,
// and then the instance is bound forevermore to whichever thread made the
@@ -350,6 +411,8 @@ class RTCVideoEncoder::Impl
bool is_constrained_h264,
const std::vector<media::VideoEncodeAccelerator::Config::SpatialLayer>&
spatial_layers,
+ media::VideoEncodeAccelerator::Config::InterLayerPredMode
+ inter_layer_pred,
SignaledValue init_event);
webrtc::VideoEncoder::EncoderInfo GetEncoderInfo() const;
@@ -518,6 +581,11 @@ class RTCVideoEncoder::Impl
webrtc::kMaxPreferredPixelFormats>
preferred_pixel_formats_;
+ // The reslutions of active spatial layer, only used when |Vp9Metadata| is
+ // contained in |BitstreamBufferMetadata|. it will be updated when key frame
+ // is produced.
+ std::vector<gfx::Size> current_spatial_layer_resolutions_;
+
// Protect |status_| and |encoder_info_|. |status_| is read or written on
// |gpu_task_runner_| in Impl. It can be read in RTCVideoEncoder on other
// threads.
@@ -528,8 +596,6 @@ class RTCVideoEncoder::Impl
// Instead, we cache an error status here and return it the next time an
// interface entry point is called. This is protected by |lock_|.
int32_t status_ GUARDED_BY(lock_);
-
- DISALLOW_COPY_AND_ASSIGN(Impl);
};
RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
@@ -548,9 +614,17 @@ RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
DETACH_FROM_SEQUENCE(sequence_checker_);
// The default values of EncoderInfo.
+ // TODO(crbug.com/1228804): These settings should be set at the time
+ // RTCVideoEncoder is constructed instead of done here.
encoder_info_.scaling_settings = webrtc::VideoEncoder::ScalingSettings::kOff;
+#if defined(OS_ANDROID)
+ // MediaCodec requires 16x16 alignment, see https://crbug.com/1084702.
+ encoder_info_.requested_resolution_alignment = 16;
+ encoder_info_.apply_alignment_to_all_simulcast_layers = true;
+#else
encoder_info_.requested_resolution_alignment = 1;
encoder_info_.apply_alignment_to_all_simulcast_layers = false;
+#endif
encoder_info_.supports_native_handle = true;
encoder_info_.implementation_name = "ExternalEncoder";
encoder_info_.has_trusted_rate_controller = true;
@@ -571,6 +645,7 @@ void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
bool is_constrained_h264,
const std::vector<media::VideoEncodeAccelerator::Config::SpatialLayer>&
spatial_layers,
+ media::VideoEncodeAccelerator::Config::InterLayerPredMode inter_layer_pred,
SignaledValue init_event) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -638,12 +713,13 @@ void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
encoder_info_.preferred_pixel_formats = preferred_pixel_formats_;
}
const media::VideoEncodeAccelerator::Config config(
- pixel_format, input_visible_size_, profile, bitrate * 1000, absl::nullopt,
+ pixel_format, input_visible_size_, profile,
+ media::Bitrate::ConstantBitrate(bitrate * 1000), absl::nullopt,
absl::nullopt, absl::nullopt, is_constrained_h264, storage_type,
video_content_type_ == webrtc::VideoContentType::SCREENSHARE
? media::VideoEncodeAccelerator::Config::ContentType::kDisplay
: media::VideoEncodeAccelerator::Config::ContentType::kCamera,
- spatial_layers);
+ spatial_layers, inter_layer_pred);
if (!video_encoder_->Initialize(config, this)) {
LogAndNotifyError(FROM_HERE, "Error initializing video_encoder",
media::VideoEncodeAccelerator::kInvalidArgumentError);
@@ -856,7 +932,7 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
}
// Immediately provide all output buffers to the VEA.
- for (size_t i = 0; i < output_buffers_.size(); ++i) {
+ for (wtf_size_t i = 0; i < output_buffers_.size(); ++i) {
video_encoder_->UseOutputBitstreamBuffer(
media::BitstreamBuffer(i, output_buffers_[i].first.Duplicate(),
output_buffers_[i].first.GetSize()));
@@ -904,10 +980,16 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
if (front_timestamps.media_timestamp_ == metadata.timestamp) {
rtp_timestamp = front_timestamps.rtp_timestamp;
capture_timestamp_ms = front_timestamps.capture_time_ms;
- pending_timestamps_.pop_front();
+ // Remove pending timestamp at the top spatial layer in the case of SVC
+ // encoding.
+ if (!metadata.vp9 || metadata.vp9->end_of_picture) {
+ pending_timestamps_.pop_front();
+ }
break;
}
- pending_timestamps_.pop_front();
+ if (!metadata.vp9 || metadata.vp9->end_of_picture) {
+ pending_timestamps_.pop_front();
+ }
}
DCHECK(rtp_timestamp.has_value());
}
@@ -937,33 +1019,70 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
webrtc::CodecSpecificInfo info;
info.codecType = video_codec_type_;
switch (video_codec_type_) {
+ case webrtc::kVideoCodecH264: {
+ webrtc::CodecSpecificInfoH264& h264 = info.codecSpecific.H264;
+ h264.packetization_mode = webrtc::H264PacketizationMode::NonInterleaved;
+ h264.idr_frame = metadata.key_frame;
+ if (metadata.h264) {
+ h264.temporal_idx = metadata.h264->temporal_idx;
+ h264.base_layer_sync = metadata.h264->layer_sync;
+ } else {
+ h264.temporal_idx = webrtc::kNoTemporalIdx;
+ h264.base_layer_sync = false;
+ }
+ } break;
case webrtc::kVideoCodecVP8:
info.codecSpecific.VP8.keyIdx = -1;
break;
case webrtc::kVideoCodecVP9: {
- bool key_frame =
- image._frameType == webrtc::VideoFrameType::kVideoFrameKey;
webrtc::CodecSpecificInfoVP9& vp9 = info.codecSpecific.VP9;
- info.end_of_picture = true;
if (metadata.vp9) {
- // Temporal layer stream.
- vp9.first_frame_in_picture = true;
- vp9.inter_pic_predicted = metadata.vp9->has_reference;
- vp9.flexible_mode = true;
- vp9.non_ref_for_inter_layer_pred = false;
+ // Temporal and/or spatial layer stream.
+ if (!metadata.vp9->spatial_layer_resolutions.empty()) {
+ current_spatial_layer_resolutions_ =
+ metadata.vp9->spatial_layer_resolutions;
+ }
+
+ const uint8_t spatial_index = metadata.vp9->spatial_idx;
+ if (spatial_index >= current_spatial_layer_resolutions_.size()) {
+ LogAndNotifyError(
+ FROM_HERE, "invalid spatial index",
+ media::VideoEncodeAccelerator::kPlatformFailureError);
+ return;
+ }
+ image.SetSpatialIndex(spatial_index);
+ image._encodedWidth =
+ current_spatial_layer_resolutions_[spatial_index].width();
+ image._encodedHeight =
+ current_spatial_layer_resolutions_[spatial_index].height();
+
+ vp9.first_frame_in_picture = spatial_index == 0;
+ vp9.inter_pic_predicted = metadata.vp9->inter_pic_predicted;
+ vp9.non_ref_for_inter_layer_pred =
+ !metadata.vp9->referenced_by_upper_spatial_layers;
vp9.temporal_idx = metadata.vp9->temporal_idx;
vp9.temporal_up_switch = metadata.vp9->temporal_up_switch;
- vp9.inter_layer_predicted = false;
- vp9.gof_idx = 0;
+ vp9.inter_layer_predicted =
+ metadata.vp9->reference_lower_spatial_layers;
vp9.num_ref_pics = metadata.vp9->p_diffs.size();
for (size_t i = 0; i < metadata.vp9->p_diffs.size(); ++i)
vp9.p_diff[i] = metadata.vp9->p_diffs[i];
- vp9.ss_data_available = key_frame;
- vp9.first_active_layer = 0u;
- vp9.spatial_layer_resolution_present = true;
- vp9.num_spatial_layers = 1u;
- vp9.width[0] = image._encodedWidth;
- vp9.height[0] = image._encodedHeight;
+ vp9.ss_data_available = metadata.key_frame;
+ vp9.first_active_layer = 0;
+ vp9.num_spatial_layers = current_spatial_layer_resolutions_.size();
+ if (vp9.ss_data_available) {
+ vp9.spatial_layer_resolution_present = true;
+ vp9.gof.num_frames_in_gof = 0;
+ for (size_t i = 0; i < vp9.num_spatial_layers; ++i) {
+ vp9.width[i] =
+ current_spatial_layer_resolutions_[spatial_index].width();
+ vp9.height[i] =
+ current_spatial_layer_resolutions_[spatial_index].height();
+ }
+ }
+ vp9.flexible_mode = true;
+ vp9.gof_idx = 0;
+ info.end_of_picture = metadata.vp9->end_of_picture;
} else {
// Simple stream, neither temporal nor spatial layer stream.
vp9.flexible_mode = false;
@@ -974,9 +1093,9 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
vp9.num_spatial_layers = 1;
vp9.first_frame_in_picture = true;
vp9.spatial_layer_resolution_present = false;
- vp9.inter_pic_predicted = !key_frame;
- vp9.ss_data_available = key_frame;
- if (key_frame) {
+ vp9.inter_pic_predicted = !metadata.key_frame;
+ vp9.ss_data_available = metadata.key_frame;
+ if (vp9.ss_data_available) {
vp9.spatial_layer_resolution_present = true;
vp9.width[0] = image._encodedWidth;
vp9.height[0] = image._encodedHeight;
@@ -986,6 +1105,7 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
vp9.gof.num_ref_pics[0] = 1;
vp9.gof.pid_diff[0][0] = 1;
}
+ info.end_of_picture = true;
}
} break;
default:
@@ -1067,11 +1187,9 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
// conditions are met.
bool requires_copy =
buffer->type() != webrtc::VideoFrameBuffer::Type::kNative;
- bool optimized_scaling = false;
if (!requires_copy) {
- const WebRtcVideoFrameAdapterInterface* frame_adapter =
- static_cast<WebRtcVideoFrameAdapterInterface*>(buffer.get());
- optimized_scaling = frame_adapter->SupportsOptimizedScaling();
+ const WebRtcVideoFrameAdapter* frame_adapter =
+ static_cast<WebRtcVideoFrameAdapter*>(buffer.get());
frame = frame_adapter->getMediaVideoFrame();
const media::VideoFrame::StorageType storage = frame->storage_type();
const bool is_shmem_frame = storage == media::VideoFrame::STORAGE_SHMEM;
@@ -1085,6 +1203,16 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
const base::TimeDelta timestamp =
frame ? frame->timestamp()
: base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms());
+ // TODO(https://crbug.com/1194500): Android (e.g. android-pie-arm64-rel)
+ // and CrOS does not support the optimzed path, perhaps due to not
+ // supporting STORAGE_GPU_MEMORY_BUFFER or NV12? When this is fixed, remove
+ // the special casing on platform and the legacy code path.
+ bool optimized_scaling =
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ buffer->type() == webrtc::VideoFrameBuffer::Type::kNative;
+#else
+ false;
+#endif
if (optimized_scaling) {
DCHECK_EQ(buffer->type(), webrtc::VideoFrameBuffer::Type::kNative);
auto scaled_buffer = buffer->Scale(input_visible_size_.width(),
@@ -1111,9 +1239,8 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
return;
}
} else {
- // TODO(https://crbug.com/1194500): When LegacyWebRtcVideoFrameAdapter is
- // removed, remove this code path in favor of the above code path. This
- // will allow us to remove |input_buffers_|.
+ // TODO(https://crbug.com/1194500): Remove this code path in favor of the
+ // above code path. This will allow us to remove |input_buffers_|.
std::pair<base::UnsafeSharedMemoryRegion,
base::WritableSharedMemoryMapping>* input_buffer =
input_buffers_[index].get();
@@ -1213,7 +1340,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrameWithNativeInput() {
frame->set_timestamp(
base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms()));
} else {
- frame = static_cast<WebRtcVideoFrameAdapterInterface*>(
+ frame = static_cast<WebRtcVideoFrameAdapter*>(
next_frame->video_frame_buffer().get())
->getMediaVideoFrame();
}
@@ -1368,8 +1495,12 @@ int32_t RTCVideoEncoder::InitEncode(
std::vector<media::VideoEncodeAccelerator::Config::SpatialLayer>
spatial_layers;
- if (!CreateSpatialLayersConfig(*codec_settings, &spatial_layers))
+ auto inter_layer_pred =
+ media::VideoEncodeAccelerator::Config::InterLayerPredMode::kOff;
+ if (!CreateSpatialLayersConfig(*codec_settings, &spatial_layers,
+ &inter_layer_pred)) {
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
// This wait is necessary because this task is completed in GPU process
// asynchronously but WebRTC API is synchronous.
@@ -1385,7 +1516,7 @@ int32_t RTCVideoEncoder::InitEncode(
scoped_refptr<Impl>(impl_),
gfx::Size(codec_settings->width, codec_settings->height),
codec_settings->startBitrate, profile_, is_constrained_h264_,
- spatial_layers,
+ spatial_layers, inter_layer_pred,
SignaledValue(&initialization_waiter, &initialization_retval)));
// webrtc::VideoEncoder expects this call to be synchronous.
@@ -1492,10 +1623,32 @@ void RTCVideoEncoder::SetRates(
webrtc::VideoEncoder::EncoderInfo RTCVideoEncoder::GetEncoderInfo() const {
webrtc::VideoEncoder::EncoderInfo info;
+#if defined(OS_ANDROID)
+ // MediaCodec requires 16x16 alignment, see https://crbug.com/1084702. We
+ // normally override this in |impl_|, but sometimes this method is called
+ // before |impl_| is created, so we need to override it here too.
+ info.requested_resolution_alignment = 16;
+ info.apply_alignment_to_all_simulcast_layers = true;
+#endif
+
if (impl_)
info = impl_->GetEncoderInfo();
-
return info;
}
+// static
+bool RTCVideoEncoder::H264HwSupportForTemporalLayers() {
+ // Temporal layers are not supported by hardware encoders.
+ return false;
+}
+
+// static
+bool RTCVideoEncoder::Vp9HwSupportForSpatialLayers() {
+#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
+ return base::FeatureList::IsEnabled(media::kVaapiVp9kSVCHWEncoding);
+#endif
+ // Spatial layers are not supported by hardware encoders.
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h
index 5adc55ee7e2..1ff816a86c6 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h
@@ -12,7 +12,6 @@
#include <vector>
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "media/base/video_decoder_config.h"
@@ -47,6 +46,8 @@ class PLATFORM_EXPORT RTCVideoEncoder : public webrtc::VideoEncoder {
RTCVideoEncoder(media::VideoCodecProfile profile,
bool is_constrained_h264,
media::GpuVideoAcceleratorFactories* gpu_factories);
+ RTCVideoEncoder(const RTCVideoEncoder&) = delete;
+ RTCVideoEncoder& operator=(const RTCVideoEncoder&) = delete;
~RTCVideoEncoder() override;
// webrtc::VideoEncoder implementation. Tasks are posted to |impl_| using the
@@ -63,6 +64,11 @@ class PLATFORM_EXPORT RTCVideoEncoder : public webrtc::VideoEncoder {
const webrtc::VideoEncoder::RateControlParameters& parameters) override;
EncoderInfo GetEncoderInfo() const override;
+ // Returns true if there's H264 HW support for temporal layers.
+ static bool H264HwSupportForTemporalLayers();
+ // Returns true if there's VP9 HW support for spatial layers.
+ static bool Vp9HwSupportForSpatialLayers();
+
private:
class Impl;
friend class RTCVideoEncoder::Impl;
@@ -79,8 +85,6 @@ class PLATFORM_EXPORT RTCVideoEncoder : public webrtc::VideoEncoder {
// The RTCVideoEncoder::Impl that does all the work.
scoped_refptr<Impl> impl_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
index 5a1569b8864..bd9dd7719f5 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
@@ -13,6 +13,7 @@
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h"
+#include "third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h"
#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
#include "third_party/webrtc/api/video_codecs/video_encoder.h"
#include "third_party/webrtc/media/base/codec.h"
@@ -234,4 +235,42 @@ RTCVideoEncoderFactory::GetSupportedFormats() const {
return GetSupportedFormatsInternal(gpu_factories_).sdp_formats;
}
+webrtc::VideoEncoderFactory::CodecSupport
+RTCVideoEncoderFactory::QueryCodecSupport(
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) const {
+ media::VideoCodec codec =
+ WebRtcToMediaVideoCodec(webrtc::PayloadStringToCodecType(format.name));
+ if (scalability_mode) {
+ absl::optional<int> spatial_layers =
+ WebRtcScalabilityModeSpatialLayers(*scalability_mode);
+
+ // Check that the scalability mode was correctly parsed and that the
+ // configuration is valid (e.g., H264 doesn't support SVC at all and VP8
+ // doesn't support spatial layers).
+ if (!spatial_layers ||
+ (codec != media::kCodecVP8 && codec != media::kCodecVP9 &&
+ codec != media::kCodecAV1) ||
+ (codec == media::kCodecVP8 && *spatial_layers > 1)) {
+ // Ivalid scalability_mode, return unsupported.
+ return {false, false};
+ }
+ DCHECK(spatial_layers);
+ // Most HW encoders cannot handle spatial layers, so return false if the
+ // configuration contains spatial layers and spatial layers are not
+ // supported.
+ if (codec == media::kCodecVP9 && *spatial_layers > 1 &&
+ !RTCVideoEncoder::Vp9HwSupportForSpatialLayers()) {
+ return {false, false};
+ }
+ }
+
+ if (format.IsCodecInList(GetSupportedFormats())) {
+ // Supported and power efficient.
+ return {true, true};
+ }
+ // Unsupported.
+ return {false, false};
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h
index 0433255ba1f..77129d836d4 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h
@@ -7,8 +7,8 @@
#include <vector>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/peerconnection/gpu_codec_support_waiter.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
@@ -20,16 +20,22 @@ namespace blink {
// This class creates RTCVideoEncoder instances (each wrapping a
// media::VideoEncodeAccelerator) on behalf of the WebRTC stack.
-class RTCVideoEncoderFactory : public webrtc::VideoEncoderFactory {
+class PLATFORM_EXPORT RTCVideoEncoderFactory
+ : public webrtc::VideoEncoderFactory {
public:
explicit RTCVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories);
+ RTCVideoEncoderFactory(const RTCVideoEncoderFactory&) = delete;
+ RTCVideoEncoderFactory& operator=(const RTCVideoEncoderFactory&) = delete;
~RTCVideoEncoderFactory() override;
// webrtc::VideoEncoderFactory implementation.
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) override;
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
+ webrtc::VideoEncoderFactory::CodecSupport QueryCodecSupport(
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) const override;
private:
void CheckAndWaitEncoderSupportStatusIfNeeded() const;
@@ -37,8 +43,6 @@ class RTCVideoEncoderFactory : public webrtc::VideoEncoderFactory {
media::GpuVideoAcceleratorFactories* gpu_factories_;
GpuCodecSupportWaiter gpu_codec_support_waiter_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc
new file mode 100644
index 00000000000..f14ad53cdad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc
@@ -0,0 +1,116 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include "base/test/task_environment.h"
+#include "media/base/video_codecs.h"
+#include "media/video/mock_gpu_video_accelerator_factories.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h"
+#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
+
+using ::testing::Return;
+
+namespace blink {
+
+namespace {
+constexpr webrtc::VideoEncoderFactory::CodecSupport kSupportedPowerEfficient = {
+ true, true};
+constexpr webrtc::VideoEncoderFactory::CodecSupport kUnsupported = {false,
+ false};
+constexpr gfx::Size max_resolution = {1920, 1080};
+
+bool Equals(webrtc::VideoEncoderFactory::CodecSupport a,
+ webrtc::VideoEncoderFactory::CodecSupport b) {
+ return a.is_supported == b.is_supported &&
+ a.is_power_efficient == b.is_power_efficient;
+}
+
+class MockGpuVideoEncodeAcceleratorFactories
+ : public media::MockGpuVideoAcceleratorFactories {
+ public:
+ MockGpuVideoEncodeAcceleratorFactories()
+ : MockGpuVideoAcceleratorFactories(nullptr) {}
+
+ absl::optional<media::VideoEncodeAccelerator::SupportedProfiles>
+ GetVideoEncodeAcceleratorSupportedProfiles() override {
+ media::VideoEncodeAccelerator::SupportedProfiles profiles = {
+ {media::VP8PROFILE_ANY, max_resolution, 30, 1},
+ {media::VP9PROFILE_PROFILE0, max_resolution, 30, 1}};
+ return profiles;
+ }
+};
+
+} // anonymous namespace
+
+typedef webrtc::SdpVideoFormat Sdp;
+typedef webrtc::SdpVideoFormat::Parameters Params;
+
+class RTCVideoEncoderFactoryTest : public ::testing::Test {
+ public:
+ RTCVideoEncoderFactoryTest() : encoder_factory_(&mock_gpu_factories_) {}
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ MockGpuVideoEncodeAcceleratorFactories mock_gpu_factories_;
+ RTCVideoEncoderFactory encoder_factory_;
+};
+
+TEST_F(RTCVideoEncoderFactoryTest, QueryCodecSupportNoSvc) {
+ EXPECT_CALL(mock_gpu_factories_, IsEncoderSupportKnown())
+ .WillRepeatedly(Return(true));
+ // VP8, H264, and VP9 profile 0 are supported.
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(
+ Sdp("VP8"), /*scalability_mode=*/absl::nullopt),
+ kSupportedPowerEfficient));
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(
+ Sdp("VP9"), /*scalability_mode=*/absl::nullopt),
+ kSupportedPowerEfficient));
+
+ // H264, VP9 profile 2 and AV1 are unsupported.
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(
+ Sdp("H264", Params{{"level-asymmetry-allowed", "1"},
+ {"packetization-mode", "1"},
+ {"profile-level-id", "42001f"}}),
+ /*scalability_mode=*/absl::nullopt),
+ kUnsupported));
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(
+ Sdp("VP9", Params{{"profile-id", "2"}}),
+ /*scalability_mode=*/absl::nullopt),
+ kUnsupported));
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(
+ Sdp("AV1"), /*scalability_mode=*/absl::nullopt),
+ kUnsupported));
+}
+
+TEST_F(RTCVideoEncoderFactoryTest, QueryCodecSupportSvc) {
+ EXPECT_CALL(mock_gpu_factories_, IsEncoderSupportKnown())
+ .WillRepeatedly(Return(true));
+ // VP8 and VP9 supported for singles spatial layers.
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP8"), "L1T2"),
+ kSupportedPowerEfficient));
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP9"), "L1T3"),
+ kSupportedPowerEfficient));
+
+ // VP9 support for spatial layers is conditionally supported/unsupported.
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP9"), "L3T3"),
+ RTCVideoEncoder::Vp9HwSupportForSpatialLayers()
+ ? kSupportedPowerEfficient
+ : kUnsupported));
+
+ // Valid SVC config but AV1 is not supported.
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("AV1"), "L2T1"),
+ kUnsupported));
+
+ // Invalid SVC config even though VP8 is supported.
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("H264"), "L1T2"),
+ kUnsupported));
+ EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP8"), "L3T3"),
+ kUnsupported));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc
index 5c0f95b59f6..84dc9b4276a 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc
@@ -8,12 +8,14 @@
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread.h"
+#include "build/build_config.h"
+#include "media/base/media_switches.h"
#include "media/video/mock_gpu_video_accelerator_factories.h"
#include "media/video/mock_video_encode_accelerator.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h"
-#include "third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
#include "third_party/libyuv/include/libyuv/planar_functions.h"
#include "third_party/webrtc/api/video/i420_buffer.h"
@@ -23,13 +25,19 @@
#include "third_party/webrtc/rtc_base/time_utils.h"
using ::testing::_;
+using ::testing::AllOf;
using ::testing::AtLeast;
+using ::testing::ElementsAre;
+using ::testing::Field;
using ::testing::Invoke;
+using ::testing::IsEmpty;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::Values;
using ::testing::WithArgs;
+using SpatialLayer = media::VideoEncodeAccelerator::Config::SpatialLayer;
+
namespace blink {
namespace {
@@ -75,7 +83,12 @@ class RTCVideoEncoderTest
mock_gpu_factories_(
new media::MockGpuVideoAcceleratorFactories(nullptr)),
idle_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {
+#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
+ // TODO(crbug.com/1186051): remove once enabled by default.
+ feature_list_.InitAndEnableFeature(media::kVaapiVp9kSVCHWEncoding);
+#endif
+ }
media::MockVideoEncodeAccelerator* ExpectCreateInitAndDestroyVEA() {
// The VEA will be owned by the RTCVideoEncoder once
@@ -85,9 +98,9 @@ class RTCVideoEncoderTest
EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoEncodeAccelerator())
.WillRepeatedly(Return(mock_vea));
- EXPECT_CALL(*mock_vea, Initialize(_, _))
+ EXPECT_CALL(*mock_vea, Initialize)
.WillOnce(Invoke(this, &RTCVideoEncoderTest::Initialize));
- EXPECT_CALL(*mock_vea, UseOutputBitstreamBuffer(_)).Times(AtLeast(3));
+ EXPECT_CALL(*mock_vea, UseOutputBitstreamBuffer).Times(AtLeast(3));
EXPECT_CALL(*mock_vea, Destroy()).Times(1);
return mock_vea;
}
@@ -98,14 +111,14 @@ class RTCVideoEncoderTest
EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
.WillRepeatedly(Return(encoder_thread_.task_runner()));
- mock_vea_ = ExpectCreateInitAndDestroyVEA();
}
void TearDown() override {
DVLOG(3) << __func__;
EXPECT_TRUE(encoder_thread_.IsRunning());
RunUntilIdle();
- rtc_encoder_->Release();
+ if (rtc_encoder_)
+ rtc_encoder_->Release();
RunUntilIdle();
encoder_thread_.Stop();
}
@@ -135,6 +148,8 @@ class RTCVideoEncoderTest
ADD_FAILURE() << "Unexpected codec type: " << codec_type;
media_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
}
+
+ mock_vea_ = ExpectCreateInitAndDestroyVEA();
rtc_encoder_ = std::make_unique<RTCVideoEncoder>(media_profile, false,
mock_gpu_factories_.get());
}
@@ -143,6 +158,7 @@ class RTCVideoEncoderTest
bool Initialize(const media::VideoEncodeAccelerator::Config& config,
media::VideoEncodeAccelerator::Client* client) {
DVLOG(3) << __func__;
+ config_ = config;
client_ = client;
client_->RequireBitstreamBuffers(0, config.input_visible_size,
config.input_visible_size.GetArea());
@@ -166,8 +182,8 @@ class RTCVideoEncoderTest
return codec;
}
- webrtc::VideoCodec GetDefaultTemporalLayerCodec() {
- const webrtc::VideoCodecType codec_type = webrtc::kVideoCodecVP9;
+ webrtc::VideoCodec GetSVCLayerCodec(webrtc::VideoCodecType codec_type,
+ size_t num_spatial_layers) {
webrtc::VideoCodec codec{};
codec.codecType = codec_type;
codec.width = kInputFrameWidth;
@@ -180,19 +196,35 @@ class RTCVideoEncoderTest
codec.qpMax = 30;
codec.numberOfSimulcastStreams = 1;
codec.mode = webrtc::VideoCodecMode::kRealtimeVideo;
- webrtc::VideoCodecVP9& vp9 = *codec.VP9();
- vp9.numberOfTemporalLayers = 3;
- vp9.numberOfSpatialLayers = 1;
- webrtc::SpatialLayer& sl = codec.spatialLayers[0];
- sl.width = kInputFrameWidth;
- sl.height = kInputFrameHeight;
- sl.maxFramerate = 24;
- sl.numberOfTemporalLayers = vp9.numberOfTemporalLayers;
- sl.targetBitrate = kStartBitrate;
- sl.maxBitrate = sl.targetBitrate;
- sl.minBitrate = sl.targetBitrate;
- sl.qpMax = 30;
- sl.active = true;
+
+ switch (codec_type) {
+ case webrtc::kVideoCodecH264: {
+ webrtc::VideoCodecH264& h264 = *codec.H264();
+ h264.numberOfTemporalLayers = 2;
+ } break;
+ case webrtc::kVideoCodecVP9: {
+ webrtc::VideoCodecVP9& vp9 = *codec.VP9();
+ vp9.numberOfTemporalLayers = 3;
+ vp9.numberOfSpatialLayers = num_spatial_layers;
+ num_spatial_layers_ = num_spatial_layers;
+ constexpr int kDenom[] = {4, 2, 1};
+ for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
+ webrtc::SpatialLayer& sl = codec.spatialLayers[sid];
+ const int denom = kDenom[sid];
+ sl.width = kInputFrameWidth / denom;
+ sl.height = kInputFrameHeight / denom;
+ sl.maxFramerate = 24;
+ sl.numberOfTemporalLayers = vp9.numberOfTemporalLayers;
+ sl.targetBitrate = kStartBitrate / denom;
+ sl.maxBitrate = sl.targetBitrate / denom;
+ sl.minBitrate = sl.targetBitrate / denom;
+ sl.qpMax = 30;
+ sl.active = true;
+ }
+ } break;
+ default:
+ NOTREACHED();
+ }
return codec;
}
@@ -224,43 +256,64 @@ class RTCVideoEncoderTest
media::BitstreamBufferMetadata(0, force_keyframe, frame->timestamp()));
}
- void ReturnTemporalLayerFrameWithVp9Metadata(
+ void ReturnSVCLayerFrameWithVp9Metadata(
scoped_refptr<media::VideoFrame> frame,
bool force_keyframe) {
- int32_t bitstream_buffer_id = frame->timestamp().InMicroseconds();
- CHECK(0 <= bitstream_buffer_id && bitstream_buffer_id <= 4);
+ int32_t frame_num = frame->timestamp().InMicroseconds();
+ CHECK(0 <= frame_num && frame_num <= 4);
media::BitstreamBufferMetadata metadata(100u /* payload_size_bytes */,
force_keyframe, frame->timestamp());
- // Assume the number of TLs is three. TL structure is below.
- // TL2: [#1] /-[#3]
- // TL1: /_____[#2] /
- // TL0: [#0]-----------------[#4]
- media::Vp9Metadata vp9;
- vp9.has_reference = bitstream_buffer_id != 0 && !force_keyframe;
- vp9.temporal_up_switch = bitstream_buffer_id != 3;
- switch (bitstream_buffer_id) {
- case 0:
- vp9.temporal_idx = 0;
- break;
- case 1:
- vp9.temporal_idx = 2;
- vp9.p_diffs = {1};
- break;
- case 2:
- vp9.temporal_idx = 1;
- vp9.p_diffs = {2};
- break;
- case 3:
- vp9.temporal_idx = 2;
- vp9.p_diffs = {1, 3};
- break;
- case 4:
- vp9.temporal_idx = 0;
- vp9.p_diffs = {4};
- break;
+
+ for (size_t sid = 0; sid < num_spatial_layers_; ++sid) {
+ // Assume the number of TLs is three. TL structure is below.
+ // TL2: [#1] /-[#3]
+ // TL1: /_____[#2]
+ // TL0: [#0]-----------------[#4]
+ media::Vp9Metadata vp9;
+ vp9.inter_pic_predicted = frame_num != 0 && !force_keyframe;
+ constexpr int kNumTemporalLayers = 3;
+ vp9.temporal_up_switch = frame_num != kNumTemporalLayers;
+ switch (frame_num) {
+ case 0:
+ vp9.temporal_idx = 0;
+ break;
+ case 1:
+ vp9.temporal_idx = 2;
+ vp9.p_diffs = {1};
+ break;
+ case 2:
+ vp9.temporal_idx = 1;
+ vp9.p_diffs = {2};
+ break;
+ case 3:
+ vp9.temporal_idx = 2;
+ vp9.p_diffs = {1};
+ break;
+ case 4:
+ vp9.temporal_idx = 0;
+ vp9.p_diffs = {4};
+ break;
+ }
+ // Assume k-SVC encoding.
+ metadata.key_frame = frame_num == 0 && sid == 0;
+ vp9.spatial_idx = sid;
+ vp9.reference_lower_spatial_layers = frame_num == 0 && sid != 0;
+ vp9.referenced_by_upper_spatial_layers =
+ frame_num == 0 && (sid + 1 != num_spatial_layers_);
+ vp9.end_of_picture = (sid + 1 == num_spatial_layers_);
+ if (metadata.key_frame) {
+ constexpr int kDenom[] = {4, 2, 1};
+ for (size_t i = 0; i < num_spatial_layers_; ++i) {
+ const int denom = kDenom[i];
+ vp9.spatial_layer_resolutions.emplace_back(
+ gfx::Size(frame->coded_size().width() / denom,
+ frame->coded_size().height() / denom));
+ }
+ }
+ metadata.vp9 = vp9;
+ client_->BitstreamBufferReady(frame_num * num_spatial_layers_ + sid,
+ metadata);
}
- metadata.vp9 = vp9;
- client_->BitstreamBufferReady(bitstream_buffer_id, metadata);
}
void VerifyTimestamp(uint32_t rtp_timestamp,
@@ -275,6 +328,7 @@ class RTCVideoEncoderTest
protected:
media::MockVideoEncodeAccelerator* mock_vea_;
std::unique_ptr<RTCVideoEncoder> rtc_encoder_;
+ absl::optional<media::VideoEncodeAccelerator::Config> config_;
media::VideoEncodeAccelerator::Client* client_;
base::Thread encoder_thread_;
@@ -282,6 +336,8 @@ class RTCVideoEncoderTest
std::unique_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
std::unique_ptr<EncodedImageCallbackWrapper> callback_wrapper_;
base::WaitableEvent idle_waiter_;
+ size_t num_spatial_layers_;
+ base::test::ScopedFeatureList feature_list_;
};
TEST_P(RTCVideoEncoderTest, CreateAndInitSucceeds) {
@@ -306,18 +362,25 @@ TEST_P(RTCVideoEncoderTest, RepeatedInitSucceeds) {
rtc_encoder_->InitEncode(&codec, kVideoEncoderSettings));
}
-INSTANTIATE_TEST_SUITE_P(CodecProfiles,
- RTCVideoEncoderTest,
- Values(webrtc::kVideoCodecVP8,
- webrtc::kVideoCodecH264));
-
-TEST_F(RTCVideoEncoderTest, CreateAndInitSucceedsForTemporalLayer) {
- webrtc::VideoCodec tl_codec = GetDefaultTemporalLayerCodec();
+TEST_P(RTCVideoEncoderTest, CreateAndInitSucceedsForTemporalLayer) {
+ const webrtc::VideoCodecType codec_type = GetParam();
+ if (codec_type == webrtc::kVideoCodecVP8) {
+ GTEST_SKIP() << "VP8 temporal layer encoding is not supported";
+ return;
+ }
+ webrtc::VideoCodec tl_codec = GetSVCLayerCodec(codec_type,
+ /*num_spatial_layers=*/1);
CreateEncoder(tl_codec.codecType);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_encoder_->InitEncode(&tl_codec, kVideoEncoderSettings));
}
+INSTANTIATE_TEST_SUITE_P(CodecProfiles,
+ RTCVideoEncoderTest,
+ Values(webrtc::kVideoCodecH264,
+ webrtc::kVideoCodecVP8,
+ webrtc::kVideoCodecVP9));
+
// Checks that WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE is returned when there is
// platform error.
TEST_F(RTCVideoEncoderTest, SoftwareFallbackAfterError) {
@@ -434,8 +497,9 @@ TEST_F(RTCVideoEncoderTest, PreserveTimestamps) {
rtc_encoder_->Encode(rtc_frame, &frame_types));
}
-TEST_F(RTCVideoEncoderTest, EncodeTemporalLayer) {
- webrtc::VideoCodec tl_codec = GetDefaultTemporalLayerCodec();
+TEST_F(RTCVideoEncoderTest, EncodeVP9TemporalLayer) {
+ webrtc::VideoCodec tl_codec = GetSVCLayerCodec(webrtc::kVideoCodecVP9,
+ /*num_spatial_layers=*/1);
CreateEncoder(tl_codec.codecType);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_encoder_->InitEncode(&tl_codec, kVideoEncoderSettings));
@@ -443,13 +507,15 @@ TEST_F(RTCVideoEncoderTest, EncodeTemporalLayer) {
EXPECT_CALL(*mock_vea_, Encode(_, _))
.Times(kNumEncodeFrames)
.WillRepeatedly(Invoke(
- this, &RTCVideoEncoderTest::ReturnTemporalLayerFrameWithVp9Metadata));
+ this, &RTCVideoEncoderTest::ReturnSVCLayerFrameWithVp9Metadata));
for (size_t i = 0; i < kNumEncodeFrames; i++) {
const rtc::scoped_refptr<webrtc::I420Buffer> buffer =
webrtc::I420Buffer::Create(kInputFrameWidth, kInputFrameHeight);
FillFrameBuffer(buffer);
std::vector<webrtc::VideoFrameType> frame_types;
+ if (i == 0)
+ frame_types.emplace_back(webrtc::VideoFrameType::kVideoFrameKey);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
.set_video_frame_buffer(buffer)
@@ -461,57 +527,93 @@ TEST_F(RTCVideoEncoderTest, EncodeTemporalLayer) {
}
}
-TEST_F(RTCVideoEncoderTest, EncodeFrameWithModernAdapter) {
- const webrtc::VideoCodecType codec_type = webrtc::kVideoCodecVP8;
- CreateEncoder(codec_type);
- webrtc::VideoCodec codec = GetDefaultCodec();
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_encoder_->InitEncode(&codec, kVideoEncoderSettings));
+#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS_ASH)
+// Currently we only test spatial SVC encoding on CrOS since only CrOS platform
+// support spatial SVC encoding.
+// http://crbug.com/1226875
+TEST_F(RTCVideoEncoderTest, EncodeSpatialLayer) {
+ webrtc::VideoCodec sl_codec = GetSVCLayerCodec(webrtc::kVideoCodecVP9,
+ /*num_spatial_layers=*/3);
+ CreateEncoder(sl_codec.codecType);
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+ rtc_encoder_->InitEncode(&sl_codec, kVideoEncoderSettings));
+ size_t kNumEncodeFrames = 5u;
EXPECT_CALL(*mock_vea_, Encode(_, _))
- .Times(2)
+ .Times(kNumEncodeFrames)
.WillRepeatedly(Invoke(
- [](scoped_refptr<media::VideoFrame> frame, bool force_keyframe) {
- EXPECT_EQ(kInputFrameWidth, frame->visible_rect().width());
- EXPECT_EQ(kInputFrameHeight, frame->visible_rect().height());
- }));
+ this, &RTCVideoEncoderTest::ReturnSVCLayerFrameWithVp9Metadata));
+
+ for (size_t i = 0; i < kNumEncodeFrames; i++) {
+ const rtc::scoped_refptr<webrtc::I420Buffer> buffer =
+ webrtc::I420Buffer::Create(kInputFrameWidth, kInputFrameHeight);
+ FillFrameBuffer(buffer);
+ std::vector<webrtc::VideoFrameType> frame_types;
+ if (i == 0)
+ frame_types.emplace_back(webrtc::VideoFrameType::kVideoFrameKey);
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+ rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_rtp(0)
+ .set_timestamp_us(i)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build(),
+ &frame_types));
+ }
+}
+
+TEST_F(RTCVideoEncoderTest, CreateAndInitVP9ThreeLayerSvc) {
+ webrtc::VideoCodec tl_codec = GetSVCLayerCodec(webrtc::kVideoCodecVP9,
+ /*num_spatial_layers=*/3);
+ CreateEncoder(tl_codec.codecType);
- // Encode first frame: full size. This will pass through to the encoder.
- auto frame = media::VideoFrame::CreateBlackFrame(
- gfx::Size(kInputFrameWidth, kInputFrameHeight));
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter(
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
- frame, std::vector<scoped_refptr<media::VideoFrame>>(),
- new WebRtcVideoFrameAdapter::SharedResources(nullptr)));
- std::vector<webrtc::VideoFrameType> frame_types;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
- .set_video_frame_buffer(frame_adapter)
- .set_timestamp_rtp(0)
- .set_timestamp_us(0)
- .set_rotation(webrtc::kVideoRotation_0)
- .build(),
- &frame_types));
+ rtc_encoder_->InitEncode(&tl_codec, kVideoEncoderSettings));
+ EXPECT_THAT(
+ *config_,
+ Field(&media::VideoEncodeAccelerator::Config::spatial_layers,
+ ElementsAre(
+ AllOf(Field(&SpatialLayer::width, kInputFrameWidth / 4),
+ Field(&SpatialLayer::height, kInputFrameHeight / 4)),
+ AllOf(Field(&SpatialLayer::width, kInputFrameWidth / 2),
+ Field(&SpatialLayer::height, kInputFrameHeight / 2)),
+ AllOf(Field(&SpatialLayer::width, kInputFrameWidth),
+ Field(&SpatialLayer::height, kInputFrameHeight)))));
+}
+
+TEST_F(RTCVideoEncoderTest, CreateAndInitVP9SvcSinglecast) {
+ webrtc::VideoCodec tl_codec = GetSVCLayerCodec(webrtc::kVideoCodecVP9,
+ /*num_spatial_layers=*/3);
+ tl_codec.spatialLayers[1].active = false;
+ tl_codec.spatialLayers[2].active = false;
+ CreateEncoder(tl_codec.codecType);
- // Encode second frame: double size. This will trigger downscale prior to
- // encoder.
- frame = media::VideoFrame::CreateBlackFrame(
- gfx::Size(kInputFrameWidth * 2, kInputFrameHeight * 2));
- frame->set_timestamp(base::TimeDelta::FromMilliseconds(123456));
- frame_adapter = new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
- frame, std::vector<scoped_refptr<media::VideoFrame>>(),
- new WebRtcVideoFrameAdapter::SharedResources(nullptr));
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
- .set_video_frame_buffer(frame_adapter)
- .set_timestamp_rtp(0)
- .set_timestamp_us(0)
- .set_rotation(webrtc::kVideoRotation_0)
- .build(),
- &frame_types));
+ rtc_encoder_->InitEncode(&tl_codec, kVideoEncoderSettings));
+ EXPECT_THAT(*config_,
+ Field(&media::VideoEncodeAccelerator::Config::spatial_layers,
+ ElementsAre(AllOf(
+ Field(&SpatialLayer::width, kInputFrameWidth / 4),
+ Field(&SpatialLayer::height, kInputFrameHeight / 4)))));
}
-TEST_F(RTCVideoEncoderTest, EncodeFrameWithLegacyAdapter) {
+TEST_F(RTCVideoEncoderTest,
+ CreateAndInitVP9SvcSinglecastWithoutTemporalLayers) {
+ webrtc::VideoCodec tl_codec = GetSVCLayerCodec(webrtc::kVideoCodecVP9,
+ /*num_spatial_layers=*/3);
+ tl_codec.spatialLayers[1].active = false;
+ tl_codec.spatialLayers[2].active = false;
+ tl_codec.spatialLayers[0].numberOfTemporalLayers = 1;
+ tl_codec.VP9()->numberOfTemporalLayers = 1;
+ CreateEncoder(tl_codec.codecType);
+
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+ rtc_encoder_->InitEncode(&tl_codec, kVideoEncoderSettings));
+ EXPECT_THAT(config_->spatial_layers, IsEmpty());
+}
+#endif
+
+TEST_F(RTCVideoEncoderTest, EncodeFrameWithAdapter) {
const webrtc::VideoCodecType codec_type = webrtc::kVideoCodecVP8;
CreateEncoder(codec_type);
webrtc::VideoCodec codec = GetDefaultCodec();
@@ -530,8 +632,9 @@ TEST_F(RTCVideoEncoderTest, EncodeFrameWithLegacyAdapter) {
auto frame = media::VideoFrame::CreateBlackFrame(
gfx::Size(kInputFrameWidth, kInputFrameHeight));
rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- frame, new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr)));
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ frame, std::vector<scoped_refptr<media::VideoFrame>>(),
+ new WebRtcVideoFrameAdapter::SharedResources(nullptr)));
std::vector<webrtc::VideoFrameType> frame_types;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
@@ -547,8 +650,9 @@ TEST_F(RTCVideoEncoderTest, EncodeFrameWithLegacyAdapter) {
frame = media::VideoFrame::CreateBlackFrame(
gfx::Size(kInputFrameWidth * 2, kInputFrameHeight * 2));
frame->set_timestamp(base::TimeDelta::FromMilliseconds(123456));
- frame_adapter = new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- frame, new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr));
+ frame_adapter = new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ frame, std::vector<scoped_refptr<media::VideoFrame>>(),
+ new WebRtcVideoFrameAdapter::SharedResources(nullptr));
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
.set_video_frame_buffer(frame_adapter)
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc b/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc
deleted file mode 100644
index 52cbb46cf42..00000000000
--- a/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/containers/contains.h"
-#include "base/cpu.h"
-#include "base/logging.h"
-#include "base/system/sys_info.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h"
-#include "third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h"
-#include "third_party/blink/renderer/platform/peerconnection/audio_codec_factory.h"
-#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-#include "third_party/webrtc/api/audio_codecs/audio_encoder_factory.h"
-#include "third_party/webrtc/api/audio_codecs/audio_format.h"
-#include "third_party/webrtc/api/scoped_refptr.h"
-#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
-#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
-
-namespace blink {
-
-namespace {
-
-// Composes elements of set<string> to a string with ", " delimiter.
-String StringHashSetToString(const HashSet<String>& string_set) {
- String result;
- String delim;
- for (auto& s : string_set) {
- result = result + delim + s;
- if (delim.IsEmpty())
- delim = ", ";
- }
- return result;
-}
-
-// Composes human readable string for |info|.
-String ToString(const blink::WebMediaCapabilitiesInfo& info) {
- return String::Format("(supported:%s, smooth:%s, power_efficient:%s)",
- info.supported ? "true" : "false",
- info.smooth ? "true" : "false",
- info.power_efficient ? "true" : "false");
-}
-
-// Gets GpuVideoAcceleratorFactories instance pointer.
-// Returns nullptr if RenderThreadImpl instance is not available.
-media::GpuVideoAcceleratorFactories* GetGpuFactories() {
- return Platform::Current()->GetGpuFactories();
-}
-
-// Returns true if CPU can encode HD video smoothly.
-// The logic is borrowed from Google Meet (crbug.com/941352).
-bool CanCpuEncodeHdSmoothly() {
- const int num_processors = base::SysInfo::NumberOfProcessors();
- if (num_processors >= 4)
- return true;
- if (num_processors < 2)
- return false;
- return base::CPU().has_sse41();
-}
-
-const unsigned int kHdVideoAreaSize = 1280 * 720;
-
-} // namespace
-
-TransmissionEncodingInfoHandler* TransmissionEncodingInfoHandler::Instance() {
- DEFINE_STATIC_LOCAL(TransmissionEncodingInfoHandler, instance, ());
- return &instance;
-}
-
-// If GetGpuFactories() returns null, CreateWebrtcVideoEncoderFactory()
-// returns software encoder factory only.
-TransmissionEncodingInfoHandler::TransmissionEncodingInfoHandler()
- : TransmissionEncodingInfoHandler(
- blink::CreateHWVideoEncoderFactory(GetGpuFactories()),
- CanCpuEncodeHdSmoothly()) {}
-
-TransmissionEncodingInfoHandler::TransmissionEncodingInfoHandler(
- std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory,
- bool cpu_hd_smooth)
- : cpu_hd_smooth_(cpu_hd_smooth) {
- if (video_encoder_factory) {
- std::vector<webrtc::SdpVideoFormat> supported_video_formats =
- video_encoder_factory->GetSupportedFormats();
- for (const auto& video_format : supported_video_formats) {
- const String codec_name =
- String::FromUTF8(video_format.name).LowerASCII();
- hardware_accelerated_video_codecs_.insert(codec_name);
- }
- }
- rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory =
- blink::CreateWebrtcAudioEncoderFactory();
- std::vector<webrtc::AudioCodecSpec> supported_audio_specs =
- audio_encoder_factory->GetSupportedEncoders();
- for (const auto& audio_spec : supported_audio_specs) {
- supported_audio_codecs_.insert(
- String::FromUTF8(audio_spec.format.name).LowerASCII());
- }
- DVLOG(2) << String::Format(
- "hardware_accelerated_video_codecs_:[%s] "
- "supported_audio_codecs_:[%s]",
- StringHashSetToString(hardware_accelerated_video_codecs_).Utf8().c_str(),
- StringHashSetToString(supported_audio_codecs_).Utf8().c_str());
-}
-
-TransmissionEncodingInfoHandler::~TransmissionEncodingInfoHandler() = default;
-
-String TransmissionEncodingInfoHandler::ExtractSupportedCodecFromMimeType(
- const String& mime_type) const {
- const char* video_prefix = "video/";
- const char* audio_prefix = "audio/";
- if (mime_type.StartsWith(video_prefix)) {
- // Currently support "video/vp8" only.
- // TODO(crbug.com/941320): support "video/vp9" and "video/h264" once their
- // MIME type parser are implemented.
- const String codec_name = mime_type.Substring(strlen(video_prefix));
- if (codec_name == "vp8")
- return codec_name;
- } else if (mime_type.StartsWith(audio_prefix)) {
- const String codec_name = mime_type.Substring(strlen(audio_prefix));
- if (base::Contains(supported_audio_codecs_, codec_name))
- return codec_name;
- }
- return "";
-}
-
-bool TransmissionEncodingInfoHandler::CanCpuEncodeSmoothly(
- const blink::WebVideoConfiguration& configuration) const {
- if (configuration.width * configuration.height < kHdVideoAreaSize)
- return true;
- return cpu_hd_smooth_;
-}
-
-void TransmissionEncodingInfoHandler::EncodingInfo(
- const blink::WebMediaConfiguration& configuration,
- OnMediaCapabilitiesEncodingInfoCallback callback) const {
- DCHECK(configuration.video_configuration ||
- configuration.audio_configuration);
-
- auto info = std::make_unique<blink::WebMediaCapabilitiesInfo>();
- if (!configuration.video_configuration &&
- !configuration.audio_configuration) {
- DVLOG(2) << "Neither video nor audio configuration specified.";
- std::move(callback).Run(std::move(info));
- return;
- }
-
- // Either video or audio capabilities will be AND-ed so set |info|'s default
- // value to true.
- info->supported = info->smooth = info->power_efficient = true;
- if (configuration.video_configuration) {
- const auto& video_config = configuration.video_configuration.value();
- const String mime_type = String(video_config.mime_type).LowerASCII();
- const String codec_name = ExtractSupportedCodecFromMimeType(mime_type);
- info->supported = !codec_name.IsEmpty();
- if (info->supported) {
- const bool is_hardware_accelerated =
- base::Contains(hardware_accelerated_video_codecs_, codec_name);
- info->smooth =
- is_hardware_accelerated || CanCpuEncodeSmoothly(video_config);
- info->power_efficient = is_hardware_accelerated;
- } else {
- info->smooth = false;
- info->power_efficient = false;
- }
- DVLOG(2) << "Video MIME type:" << mime_type
- << " capabilities:" << ToString(*info);
- }
- if (configuration.audio_configuration) {
- const String mime_type =
- String(configuration.audio_configuration->mime_type).LowerASCII();
- const String codec_name = ExtractSupportedCodecFromMimeType(mime_type);
- info->supported &= !codec_name.IsEmpty();
- // Audio is always assumed to be smooth and efficient whenever it is
- // supported.
- info->smooth &= info->supported;
- info->power_efficient &= info->supported;
- DVLOG(2) << "Audio MIME type:" << mime_type
- << " capabilities:" << ToString(*info);
- }
- std::move(callback).Run(std::move(info));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h b/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h
deleted file mode 100644
index b09082f7650..00000000000
--- a/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_TRANSMISSION_ENCODING_INFO_HANDLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_TRANSMISSION_ENCODING_INFO_HANDLER_H_
-
-#include <memory>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_info.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-struct WebMediaConfiguration;
-struct WebVideoConfiguration;
-} // namespace blink
-
-namespace webrtc {
-class VideoEncoderFactory;
-} // namespace webrtc
-
-namespace blink {
-
-// blink::WebTransmissionEncodingInfoHandler implementation.
-class PLATFORM_EXPORT TransmissionEncodingInfoHandler {
- public:
- static TransmissionEncodingInfoHandler* Instance();
-
- TransmissionEncodingInfoHandler();
- // Constructor for unittest to inject VideoEncodeFactory instance and
- // |cpu_hd_smooth|.
- explicit TransmissionEncodingInfoHandler(
- std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory,
- bool cpu_hd_smooth);
- ~TransmissionEncodingInfoHandler();
-
- // Queries the capabilities of the given encoding configuration and passes
- // WebMediaCapabilitiesInfo result via callbacks.
- // It implements WICG Media Capabilities encodingInfo() call for transmission
- // encoding.
- // https://wicg.github.io/media-capabilities/#media-capabilities-interface
- using OnMediaCapabilitiesEncodingInfoCallback =
- base::OnceCallback<void(std::unique_ptr<WebMediaCapabilitiesInfo>)>;
- void EncodingInfo(const blink::WebMediaConfiguration& configuration,
- OnMediaCapabilitiesEncodingInfoCallback cb) const;
-
- private:
- // Extracts supported video/audio codec name from |mime_type|. Returns "" if
- // it is not supported.
- String ExtractSupportedCodecFromMimeType(const String& mime_type) const;
-
- // True if it can encode |configuration| smoothly via CPU.
- bool CanCpuEncodeSmoothly(
- const blink::WebVideoConfiguration& configuration) const;
-
- // List of hardware accelerated codecs.
- HashSet<String> hardware_accelerated_video_codecs_;
- // List of supported audio codecs.
- HashSet<String> supported_audio_codecs_;
-
- // True if CPU is capable to encode 720p video smoothly.
- bool cpu_hd_smooth_;
-
- DISALLOW_COPY_AND_ASSIGN(TransmissionEncodingInfoHandler);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_TRANSMISSION_ENCODING_INFO_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler_test.cc
deleted file mode 100644
index 334ad7b3aa1..00000000000
--- a/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler_test.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "media/base/video_codecs.h"
-#include "media/video/video_encode_accelerator.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/media_capabilities/web_audio_configuration.h"
-#include "third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h"
-#include "third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h"
-#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
-#include "third_party/webrtc/api/video_codecs/video_encoder.h"
-#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace blink {
-
-namespace {
-
-class FakeVideoEncoderFactory : public webrtc::VideoEncoderFactory {
- public:
- FakeVideoEncoderFactory() = default;
- ~FakeVideoEncoderFactory() override = default;
-
- void AddSupportedFormat(const webrtc::SdpVideoFormat& video_format) {
- supported_video_formats_.push_back(video_format);
- }
-
- std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
- return supported_video_formats_;
- }
-
- std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
- const webrtc::SdpVideoFormat& format) override {
- return std::unique_ptr<webrtc::VideoEncoder>();
- }
-
- private:
- std::vector<webrtc::SdpVideoFormat> supported_video_formats_;
-};
-
-} // namespace
-
-// Stores WebMediaCapabilitiesEncodingInfoCallbacks' result for verify.
-class EncodingInfoObserver {
- public:
- EncodingInfoObserver() = default;
- ~EncodingInfoObserver() = default;
-
- void OnSuccess(std::unique_ptr<blink::WebMediaCapabilitiesInfo> info) {
- info_.swap(info);
- is_success_ = true;
- }
- void OnError() { is_error_ = true; }
-
- const blink::WebMediaCapabilitiesInfo* info() const { return info_.get(); }
- bool IsCalled() const { return is_success_ || is_error_; }
- bool is_success() const { return is_success_; }
- bool is_error() const { return is_error_; }
-
- private:
- std::unique_ptr<blink::WebMediaCapabilitiesInfo> info_;
- bool is_success_;
- bool is_error_;
-};
-
-// It places callback's result to EncodingInfoObserver for testing code
-// to verify. Because blink::WebMediaCapabilitiesEncodingInfoCallbacks instance
-// is handed to TransmissionEncodingInfoHandler, we cannot directly inspect
-// OnSuccess() received argument. So it moves OnSuccess()'s received argument,
-// WebMediaCapabilitiesInfo instance, to EncodingInfoObserver instance for
-// inspection.
-class WebMediaCapabilitiesEncodingInfoCallbacksForTest {
- public:
- WebMediaCapabilitiesEncodingInfoCallbacksForTest(
- EncodingInfoObserver* observer)
- : observer_(observer) {
- DCHECK(observer_);
- }
- virtual ~WebMediaCapabilitiesEncodingInfoCallbacksForTest() = default;
-
- void OnSuccess(std::unique_ptr<blink::WebMediaCapabilitiesInfo> info) {
- observer_->OnSuccess(std::move(info));
- }
-
- void OnError() { observer_->OnError(); }
-
- private:
- EncodingInfoObserver* observer_;
-};
-
-class TransmissionEncodingInfoHandlerTest : public testing::Test {
- protected:
- blink::WebVideoConfiguration ComposeVideoConfiguration(
- const std::string& mime_type,
- const std::string& codec,
- unsigned int width = 1920,
- unsigned int height = 1080,
- double framerate = 30.0) {
- constexpr int kBitrate = 2661034;
- return blink::WebVideoConfiguration{blink::WebString::FromASCII(mime_type),
- blink::WebString::FromASCII(codec),
- width,
- height,
- kBitrate,
- framerate};
- }
-
- blink::WebAudioConfiguration ComposeAudioConfiguration(
- const std::string& mime_type,
- const std::string& codec) {
- return blink::WebAudioConfiguration{blink::WebString::FromASCII(mime_type),
- blink::WebString::FromASCII(codec),
- blink::WebString(), absl::nullopt,
- absl::nullopt};
- }
-
- blink::WebMediaConfiguration ComposeWebMediaConfigurationForVideo(
- const std::string& mime_type,
- const std::string& codec) {
- return blink::WebMediaConfiguration(
- blink::MediaConfigurationType::kTransmission, absl::nullopt,
- ComposeVideoConfiguration(mime_type, codec));
- }
-
- blink::WebMediaConfiguration ComposeWebMediaConfigurationForAudio(
- const std::string& mime_type,
- const std::string& codec) {
- return blink::WebMediaConfiguration(
- blink::MediaConfigurationType::kTransmission,
- ComposeAudioConfiguration(mime_type, codec), absl::nullopt);
- }
-
- void VerifyEncodingInfo(const TransmissionEncodingInfoHandler& handler,
- const blink::WebMediaConfiguration& configuration,
- bool expect_supported,
- bool expect_smooth,
- bool expect_power_efficient) {
- EncodingInfoObserver observer;
- auto callbacks =
- std::make_unique<WebMediaCapabilitiesEncodingInfoCallbacksForTest>(
- &observer);
- handler.EncodingInfo(
- configuration,
- base::BindOnce(
- &WebMediaCapabilitiesEncodingInfoCallbacksForTest::OnSuccess,
- base::Unretained(callbacks.get())));
-
- EXPECT_TRUE(observer.IsCalled());
- EXPECT_TRUE(observer.is_success());
- const blink::WebMediaCapabilitiesInfo* encoding_info = observer.info();
- ASSERT_TRUE(encoding_info);
- EXPECT_EQ(expect_supported, encoding_info->supported);
- EXPECT_EQ(expect_smooth, encoding_info->smooth);
- EXPECT_EQ(expect_power_efficient, encoding_info->power_efficient);
- }
-};
-
-TEST_F(TransmissionEncodingInfoHandlerTest, SupportedVideoCodec) {
- TransmissionEncodingInfoHandler handler(nullptr, false);
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForVideo("video/vp8", ""),
- true, false, false);
- // Temporarily unsupported: "video/vp9" and "video/h264".
- // TODO(crbug.com/941320): "video/vp9" and "video/h264" should be supported
- // once their MIME type parser are implemented.
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForVideo("video/vp9", ""),
- false, false, false);
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForVideo("video/h264", ""),
- false, false, false);
- // "video/webm" is not a "transmission" MIME type.
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForVideo("video/webm", "vp8"),
- false, false, false);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, SupportedAudioCodec) {
- TransmissionEncodingInfoHandler handler;
- for (const char* mime_type :
- {"audio/g722", "audio/isac", "audio/opus", "audio/pcma", "audio/pcmu"}) {
- // For audio codec, if it is supported, it is smooth.
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForAudio(mime_type, ""),
- true, true, true);
- }
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, HardwareAcceleratedVideoCodec) {
- auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
- video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"));
- TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
- false);
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForVideo("video/vp8", ""),
- true, true, true);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, SmoothVideoCodecPowerfulCpu) {
- // Assume no HW vp8 encoder.
- // Assume powerful CPU.
- TransmissionEncodingInfoHandler handler(nullptr, true);
- VerifyEncodingInfo(handler,
- ComposeWebMediaConfigurationForVideo("video/vp8", ""),
- true, true, false);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, SmoothVideoCodecVgaResolution) {
- // Assume no HW vp8 encoder.
- // Assume no powerful CPU.
- TransmissionEncodingInfoHandler handler(nullptr, false);
-
- // VP8 encoding for 640x480 video.
- blink::WebMediaConfiguration config(
- blink::MediaConfigurationType::kTransmission, absl::nullopt,
- ComposeVideoConfiguration("video/vp8", "", 640, 480));
-
- VerifyEncodingInfo(handler, config, true, true, false);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, SmoothVideoCodecBelowHdResolution) {
- // Assume no HW vp8 encoder.
- // Assume no powerful CPU.
- TransmissionEncodingInfoHandler handler(nullptr, false);
-
- // VP8 encoding for 1024x768 video. Note its area size is below 1280x720).
- blink::WebMediaConfiguration config(
- blink::MediaConfigurationType::kTransmission, absl::nullopt,
- ComposeVideoConfiguration("video/vp8", "", 1024, 768));
-
- VerifyEncodingInfo(handler, config, true, true, false);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, AudioAndVideoCodec) {
- // Both video/vp8 and audio/opus are given.
- blink::WebMediaConfiguration config(
- blink::MediaConfigurationType::kTransmission,
- ComposeAudioConfiguration("audio/opus", ""),
- ComposeVideoConfiguration("video/vp8", ""));
-
- TransmissionEncodingInfoHandler handler(nullptr, false);
- VerifyEncodingInfo(handler, config, true, false, false);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest,
- AudioAndVideoCodecWithVideoHardwareEncoder) {
- // Both video/vp8 and audio/opus are given.
- blink::WebMediaConfiguration config(
- blink::MediaConfigurationType::kTransmission,
- ComposeAudioConfiguration("audio/opus", ""),
- ComposeVideoConfiguration("video/vp8", ""));
-
- auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
- video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"));
- TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
- false);
- VerifyEncodingInfo(handler, config, true, true, true);
-}
-
-TEST_F(TransmissionEncodingInfoHandlerTest, AudioAndVideoCodecWithPowerfulCpu) {
- // Both video/vp8 and audio/opus are given.
- blink::WebMediaConfiguration config(
- blink::MediaConfigurationType::kTransmission,
- ComposeAudioConfiguration("audio/opus", ""),
- ComposeVideoConfiguration("video/vp8", ""));
-
- // Assume no HW vp8 encoder.
- // Assume powerful CPU.
- TransmissionEncodingInfoHandler handler(nullptr, true);
- VerifyEncodingInfo(handler, config, true, true, false);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc b/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc
index 511f5322f13..d47e1b4b14c 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -22,8 +21,6 @@ class TwoKeysAdapterMapTest : public ::testing::Test {
}
String str;
-
- DISALLOW_COPY_AND_ASSIGN(MoveOnlyValue);
};
TwoKeysAdapterMap<String, String, MoveOnlyValue> map_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc b/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
index efbd1454d6f..a8a6e4cd5d1 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
@@ -138,6 +138,21 @@ class EncoderAdapter : public webrtc::VideoEncoderFactory {
: software_formats;
}
+ webrtc::VideoEncoderFactory::CodecSupport QueryCodecSupport(
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) const override {
+ webrtc::VideoEncoderFactory::CodecSupport codec_support =
+ hardware_encoder_factory_
+ ? hardware_encoder_factory_->QueryCodecSupport(format,
+ scalability_mode)
+ : webrtc::VideoEncoderFactory::CodecSupport();
+ if (!codec_support.is_supported) {
+ codec_support =
+ software_encoder_factory_.QueryCodecSupport(format, scalability_mode);
+ }
+ return codec_support;
+ }
+
private:
webrtc::InternalEncoderFactory software_encoder_factory_;
const std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory_;
@@ -171,6 +186,21 @@ class DecoderAdapter : public webrtc::VideoDecoderFactory {
: software_formats;
}
+ webrtc::VideoDecoderFactory::CodecSupport QueryCodecSupport(
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) const override {
+ webrtc::VideoDecoderFactory::CodecSupport codec_support =
+ hardware_decoder_factory_
+ ? hardware_decoder_factory_->QueryCodecSupport(format,
+ scalability_mode)
+ : webrtc::VideoDecoderFactory::CodecSupport();
+ if (!codec_support.is_supported) {
+ codec_support =
+ software_decoder_factory_.QueryCodecSupport(format, scalability_mode);
+ }
+ return codec_support;
+ }
+
private:
webrtc::InternalDecoderFactory software_decoder_factory_;
const std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h
index b47ca06dc66..91a8ebd13cb 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h
@@ -13,7 +13,6 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
@@ -50,6 +49,8 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
scoped_refptr<webrtc::AudioSourceInterface> track_source,
scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+ WebRtcAudioSink(const WebRtcAudioSink&) = delete;
+ WebRtcAudioSink& operator=(const WebRtcAudioSink&) = delete;
~WebRtcAudioSink() override;
@@ -83,6 +84,8 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
scoped_refptr<webrtc::AudioSourceInterface> source,
scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+ Adapter(const Adapter&) = delete;
+ Adapter& operator=(const Adapter&) = delete;
base::SingleThreadTaskRunner* signaling_task_runner() const {
return signaling_task_runner_.get();
@@ -165,8 +168,6 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
// clock. See the comment at the implementation of UpdateTimestampAligner()
// for more details.
rtc::TimestampAligner timestamp_aligner_;
-
- DISALLOW_COPY_AND_ASSIGN(Adapter);
};
template <typename>
@@ -209,8 +210,6 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
// In debug builds, check that WebRtcAudioSink's public methods are all being
// called on the main render thread.
THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(WebRtcAudioSink);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.cc
index f85bb0664c7..255633150fe 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.cc
@@ -7,6 +7,7 @@
#include <utility>
#include <vector>
+#include "base/containers/contains.h"
#include "base/cpu.h"
#include "base/logging.h"
#include "base/system/sys_info.h"
@@ -14,6 +15,7 @@
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
#include "third_party/blink/renderer/platform/peerconnection/audio_codec_factory.h"
#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/webrtc/api/audio_codecs/audio_decoder_factory.h"
#include "third_party/webrtc/api/audio_codecs/audio_format.h"
@@ -22,42 +24,6 @@
#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
namespace blink {
-
-namespace {
-
-String ExtractCodecNameFromMimeType(const String& mime_type,
- const char* prefix) {
- if (mime_type.StartsWith(prefix)) {
- size_t length = mime_type.length() - strlen(prefix) - 1;
- const String codec_name = mime_type.Right(length);
- return codec_name;
- }
- return "";
-}
-
-webrtc::SdpVideoFormat::Parameters ConvertToSdpVideoFormatParameters(
- const ParsedContentHeaderFieldParameters& parameters) {
- webrtc::SdpVideoFormat::Parameters sdp_parameters;
- for (const auto& parameter : parameters) {
- sdp_parameters[parameter.name.Utf8()] = parameter.value.Utf8();
- }
- return sdp_parameters;
-}
-
-// Composes elements of set<string> to a string with ", " delimiter.
-String StringHashSetToString(const HashSet<String>& string_set) {
- String result;
- String delim;
- for (auto& s : string_set) {
- result = result + delim + s;
- if (delim.IsEmpty())
- delim = ", ";
- }
- return result;
-}
-
-} // namespace
-
WebrtcDecodingInfoHandler* WebrtcDecodingInfoHandler::Instance() {
DEFINE_STATIC_LOCAL(WebrtcDecodingInfoHandler, instance, ());
return &instance;
@@ -83,9 +49,6 @@ WebrtcDecodingInfoHandler::WebrtcDecodingInfoHandler(
supported_audio_codecs_.insert(
String::FromUTF8(audio_spec.format.name).LowerASCII());
}
- DVLOG(2) << String::Format(
- "supported_audio_codecs_:[%s]",
- StringHashSetToString(supported_audio_codecs_).Utf8().c_str());
}
WebrtcDecodingInfoHandler::~WebrtcDecodingInfoHandler() = default;
@@ -104,7 +67,7 @@ void WebrtcDecodingInfoHandler::DecodingInfo(
ParsedContentType audio_content_type(audio_mime_type->LowerASCII());
DCHECK(audio_content_type.IsValid());
const String codec_name =
- ExtractCodecNameFromMimeType(audio_content_type.MimeType(), "audio");
+ WebrtcCodecNameFromMimeType(audio_content_type.MimeType(), "audio");
supported = base::Contains(supported_audio_codecs_, codec_name);
// Audio is always assumed to be power efficient whenever it is
// supported.
@@ -120,7 +83,7 @@ void WebrtcDecodingInfoHandler::DecodingInfo(
ParsedContentType video_content_type(video_mime_type->LowerASCII());
DCHECK(video_content_type.IsValid());
const String codec_name =
- ExtractCodecNameFromMimeType(video_content_type.MimeType(), "video");
+ WebrtcCodecNameFromMimeType(video_content_type.MimeType(), "video");
const webrtc::SdpVideoFormat::Parameters parameters =
ConvertToSdpVideoFormatParameters(video_content_type.GetParameters());
webrtc::SdpVideoFormat sdp_video_format(codec_name.Utf8(), parameters);
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.h
index 6d54519fd90..1a2a1e9ea22 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/callback_forward.h"
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/peerconnection/audio_codec_factory.h"
#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -34,7 +34,7 @@ class PLATFORM_EXPORT WebrtcDecodingInfoHandler {
~WebrtcDecodingInfoHandler();
// Queries the capabilities of the given decoding configuration and passes
- // WebMediaCapabilitiesInfo result via callbacks.
+ // the result via callbacks.
// It implements WICG Media Capabilities decodingInfo() call for webrtc
// encoding.
// https://wicg.github.io/media-capabilities/#media-capabilities-interface
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler_test.cc
index ce32c305558..0ecd15cd8c8 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_decoding_info_handler_test.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.cc
new file mode 100644
index 00000000000..ac2b37f798f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.cc
@@ -0,0 +1,104 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/containers/contains.h"
+#include "base/cpu.h"
+#include "base/logging.h"
+#include "base/system/sys_info.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
+#include "third_party/blink/renderer/platform/peerconnection/audio_codec_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/webrtc/api/audio_codecs/audio_encoder_factory.h"
+#include "third_party/webrtc/api/audio_codecs/audio_format.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
+
+namespace blink {
+
+WebrtcEncodingInfoHandler* WebrtcEncodingInfoHandler::Instance() {
+ DEFINE_STATIC_LOCAL(WebrtcEncodingInfoHandler, instance, ());
+ return &instance;
+}
+
+WebrtcEncodingInfoHandler::WebrtcEncodingInfoHandler()
+ : WebrtcEncodingInfoHandler(blink::CreateWebrtcVideoEncoderFactory(
+ Platform::Current()->GetGpuFactories()),
+ blink::CreateWebrtcAudioEncoderFactory()) {}
+
+WebrtcEncodingInfoHandler::WebrtcEncodingInfoHandler(
+ std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory,
+ rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory)
+ : video_encoder_factory_(std::move(video_encoder_factory)),
+ audio_encoder_factory_(std::move(audio_encoder_factory)) {
+ std::vector<webrtc::AudioCodecSpec> supported_audio_specs =
+ audio_encoder_factory_->GetSupportedEncoders();
+ for (const auto& audio_spec : supported_audio_specs) {
+ supported_audio_codecs_.insert(
+ String::FromUTF8(audio_spec.format.name).LowerASCII());
+ }
+}
+
+WebrtcEncodingInfoHandler::~WebrtcEncodingInfoHandler() = default;
+
+void WebrtcEncodingInfoHandler::EncodingInfo(
+ const absl::optional<String> audio_mime_type,
+ const absl::optional<String> video_mime_type,
+ const absl::optional<String> video_scalability_mode,
+ OnMediaCapabilitiesEncodingInfoCallback callback) const {
+ DCHECK(audio_mime_type || video_mime_type);
+
+ // Set default values to true in case an audio configuration is not specified.
+ bool supported = true;
+ bool power_efficient = true;
+ if (audio_mime_type) {
+ ParsedContentType audio_content_type(audio_mime_type->LowerASCII());
+ DCHECK(audio_content_type.IsValid());
+ const String codec_name =
+ WebrtcCodecNameFromMimeType(audio_content_type.MimeType(), "audio");
+ supported = base::Contains(supported_audio_codecs_, codec_name);
+ // Audio is always assumed to be power efficient whenever it is
+ // supported.
+ power_efficient = supported;
+ DVLOG(1) << "Audio MIME type:" << codec_name << " supported:" << supported
+ << " power_efficient:" << power_efficient;
+ }
+
+ // Only check video configuration if the audio configuration was supported (or
+ // not specified).
+ if (video_mime_type && supported) {
+ // Convert video_configuration to SdpVideoFormat.
+ ParsedContentType video_content_type(video_mime_type->LowerASCII());
+ DCHECK(video_content_type.IsValid());
+ const String codec_name =
+ WebrtcCodecNameFromMimeType(video_content_type.MimeType(), "video");
+ const webrtc::SdpVideoFormat::Parameters parameters =
+ ConvertToSdpVideoFormatParameters(video_content_type.GetParameters());
+ webrtc::SdpVideoFormat sdp_video_format(codec_name.Utf8(), parameters);
+ absl::optional<std::string> scalability_mode =
+ video_scalability_mode
+ ? absl::make_optional(video_scalability_mode->Utf8())
+ : absl::nullopt;
+ webrtc::VideoEncoderFactory::CodecSupport support =
+ video_encoder_factory_->QueryCodecSupport(sdp_video_format,
+ scalability_mode);
+
+ supported = support.is_supported;
+ power_efficient = support.is_power_efficient;
+
+ DVLOG(1) << "Video MIME type:" << codec_name << " supported:" << supported
+ << " power_efficient:" << power_efficient;
+ }
+ std::move(callback).Run(supported, power_efficient);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h
new file mode 100644
index 00000000000..bfd9118ae9f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_ENCODING_INFO_HANDLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_ENCODING_INFO_HANDLER_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/platform/peerconnection/audio_codec_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT WebrtcEncodingInfoHandler {
+ public:
+ static WebrtcEncodingInfoHandler* Instance();
+
+ WebrtcEncodingInfoHandler();
+ // Constructor for unittest to inject video and audio encoder factory
+ // instances.
+ WebrtcEncodingInfoHandler(
+ std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory,
+ rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory);
+ // Not copyable or movable.
+ WebrtcEncodingInfoHandler(const WebrtcEncodingInfoHandler&) = delete;
+ WebrtcEncodingInfoHandler& operator=(const WebrtcEncodingInfoHandler&) =
+ delete;
+ ~WebrtcEncodingInfoHandler();
+
+ // Queries the capabilities of the given encoding configuration and passes
+ // the result via callbacks.
+ // It implements WICG Media Capabilities encodingInfo() call for webrtc
+ // encoding.
+ // https://wicg.github.io/media-capabilities/#media-capabilities-interface
+ using OnMediaCapabilitiesEncodingInfoCallback =
+ base::OnceCallback<void(bool, bool)>;
+ void EncodingInfo(const absl::optional<String> audio_mime_type,
+ const absl::optional<String> video_mime_type,
+ const absl::optional<String> video_scalability_mode,
+ OnMediaCapabilitiesEncodingInfoCallback callback) const;
+
+ private:
+ std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory_;
+ rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory_;
+ // List of supported audio codecs.
+ HashSet<String> supported_audio_codecs_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_ENCODING_INFO_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler_test.cc
new file mode 100644
index 00000000000..fb414314c63
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler_test.cc
@@ -0,0 +1,196 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/peerconnection/webrtc_encoding_info_handler.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/webrtc/api/audio_codecs/audio_encoder_factory.h"
+#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace blink {
+
+namespace {
+
+class MockVideoEncoderFactory : public webrtc::VideoEncoderFactory {
+ public:
+ // webrtc::VideoEncoderFactory implementation:
+ MOCK_METHOD(std::unique_ptr<webrtc::VideoEncoder>,
+ CreateVideoEncoder,
+ (const webrtc::SdpVideoFormat& format),
+ (override));
+ MOCK_METHOD(std::vector<webrtc::SdpVideoFormat>,
+ GetSupportedFormats,
+ (),
+ (const));
+ MOCK_METHOD(webrtc::VideoEncoderFactory::CodecSupport,
+ QueryCodecSupport,
+ (const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode),
+ (const, override));
+};
+
+class MediaCapabilitiesEncodingInfoCallback {
+ public:
+ void OnWebrtcEncodingInfoSupport(bool is_supported, bool is_power_efficient) {
+ is_success_ = true;
+ is_supported_ = is_supported;
+ is_power_efficient_ = is_power_efficient;
+ }
+
+ void OnError() { is_error_ = true; }
+
+ bool IsCalled() const { return is_success_ || is_error_; }
+ bool IsSuccess() const { return is_success_; }
+ bool IsError() const { return is_error_; }
+ bool IsSupported() const { return is_supported_; }
+ bool IsPowerEfficient() const { return is_power_efficient_; }
+
+ private:
+ bool is_success_ = false;
+ bool is_error_ = false;
+ bool is_supported_ = false;
+ bool is_power_efficient_ = false;
+};
+
+} // namespace
+
+typedef webrtc::VideoEncoderFactory::CodecSupport CodecSupport;
+
+class WebrtcEncodingInfoHandlerTests : public ::testing::Test {
+ public:
+ WebrtcEncodingInfoHandlerTests()
+ : mock_video_encoder_factory_(new MockVideoEncoderFactory()),
+ video_encoder_factory_(mock_video_encoder_factory_),
+ audio_encoder_factory_(blink::CreateWebrtcAudioEncoderFactory()) {}
+
+ void SetUp() override {}
+
+ void VerifyEncodingInfo(
+ const absl::optional<String> audio_mime_type,
+ const absl::optional<String> video_mime_type,
+ const absl::optional<String> video_scalability_mode,
+ const absl::optional<webrtc::SdpVideoFormat> expected_format,
+ const CodecSupport support) {
+ if (expected_format) {
+ const absl::optional<std::string> expected_scalability_mode =
+ video_scalability_mode
+ ? absl::make_optional(video_scalability_mode->Utf8())
+ : absl::nullopt;
+
+ ON_CALL(*mock_video_encoder_factory_, QueryCodecSupport)
+ .WillByDefault(testing::Invoke(
+ [expected_format, expected_scalability_mode, support](
+ const webrtc::SdpVideoFormat& format,
+ absl::optional<std::string> scalability_mode) {
+ format.IsSameCodec(*expected_format);
+ EXPECT_EQ(scalability_mode, expected_scalability_mode);
+ return support;
+ }));
+ EXPECT_CALL(*mock_video_encoder_factory_, QueryCodecSupport)
+ .Times(::testing::AtMost(1));
+ }
+ WebrtcEncodingInfoHandler encoding_info_handler(
+ std::move(video_encoder_factory_), audio_encoder_factory_);
+ MediaCapabilitiesEncodingInfoCallback encoding_info_callback;
+
+ encoding_info_handler.EncodingInfo(
+ audio_mime_type, video_mime_type, video_scalability_mode,
+ base::BindOnce(
+ &MediaCapabilitiesEncodingInfoCallback::OnWebrtcEncodingInfoSupport,
+ base::Unretained(&encoding_info_callback)));
+
+ EXPECT_TRUE(encoding_info_callback.IsCalled());
+ EXPECT_TRUE(encoding_info_callback.IsSuccess());
+ EXPECT_EQ(encoding_info_callback.IsSupported(), support.is_supported);
+ EXPECT_EQ(encoding_info_callback.IsPowerEfficient(),
+ support.is_power_efficient);
+ }
+
+ protected:
+ std::vector<webrtc::AudioCodecSpec> kSupportedAudioCodecs;
+ MockVideoEncoderFactory* mock_video_encoder_factory_;
+ std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory_;
+ rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory_;
+};
+
+TEST_F(WebrtcEncodingInfoHandlerTests, BasicAudio) {
+ VerifyEncodingInfo(
+ "audio/opus", /*video_mime_type=*/absl::nullopt,
+ /*video_scalability_mode=*/absl::nullopt,
+ /*expected_format=*/absl::nullopt,
+ CodecSupport{/*is_supported=*/true, /*is_power_efficient=*/true});
+}
+
+TEST_F(WebrtcEncodingInfoHandlerTests, UnsupportedAudio) {
+ VerifyEncodingInfo(
+ "audio/foo", /*video_mime_type=*/absl::nullopt,
+ /*video_scalability_mode=*/absl::nullopt,
+ /*expected_format=*/absl::nullopt,
+ CodecSupport{/*is_supported=*/false, /*is_power_efficient=*/false});
+}
+
+// These tests verify that the video MIME type is correctly parsed into
+// SdpVideoFormat and that the return value from
+// VideoEncoderFactory::QueryCodecSupport is correctly returned through the
+// callback.
+TEST_F(WebrtcEncodingInfoHandlerTests, BasicVideo) {
+ const webrtc::SdpVideoFormat kExpectedFormat("VP9");
+ VerifyEncodingInfo(
+ /*audio_mime_type=*/absl::nullopt, "video/VP9",
+ /*video_scalability_mode=*/absl::nullopt, kExpectedFormat,
+ CodecSupport{/*is_supported=*/true, /*is_power_efficient=*/false});
+}
+
+TEST_F(WebrtcEncodingInfoHandlerTests, BasicVideoPowerEfficient) {
+ const webrtc::SdpVideoFormat kExpectedFormat("VP9");
+ VerifyEncodingInfo(
+ /*audio_mime_type=*/absl::nullopt, "video/VP9",
+ /*video_scalability_mode=*/absl::nullopt, kExpectedFormat,
+ CodecSupport{/*is_supported=*/true, /*is_power_efficient=*/true});
+}
+
+TEST_F(WebrtcEncodingInfoHandlerTests, UnsupportedVideo) {
+ const webrtc::SdpVideoFormat kExpectedFormat(
+ "VP9", webrtc::SdpVideoFormat::Parameters{{"profile-level", "5"}});
+ VerifyEncodingInfo(
+ /*audio_mime_type=*/absl::nullopt, "video/VP9; profile-level=5",
+ /*video_scalability_mode=*/absl::nullopt, kExpectedFormat,
+ CodecSupport{/*is_supported=*/true, /*is_power_efficient=*/false});
+}
+
+TEST_F(WebrtcEncodingInfoHandlerTests, VideoWithScalabilityMode) {
+ const webrtc::SdpVideoFormat kExpectedFormat("VP9");
+ VerifyEncodingInfo(
+ /*audio_mime_type=*/absl::nullopt, "video/VP9", "L1T3", kExpectedFormat,
+ CodecSupport{/*is_supported=*/true, /*is_power_efficient=*/false});
+}
+
+TEST_F(WebrtcEncodingInfoHandlerTests, SupportedAudioUnsupportedVideo) {
+ const webrtc::SdpVideoFormat kExpectedFormat("foo");
+ VerifyEncodingInfo(
+ "audio/opus", "video/foo", /*video_scalability_mode=*/absl::nullopt,
+ kExpectedFormat,
+ CodecSupport{/*is_supported=*/false, /*is_power_efficient=*/false});
+}
+
+TEST_F(WebrtcEncodingInfoHandlerTests, SupportedVideoUnsupportedAudio) {
+ const webrtc::SdpVideoFormat kExpectedFormat("VP9");
+ VerifyEncodingInfo(
+ "audio/foo", "video/VP9", /*video_scalability_mode=*/absl::nullopt,
+ kExpectedFormat,
+ CodecSupport{/*is_supported=*/false, /*is_power_efficient=*/false});
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.cc
new file mode 100644
index 00000000000..35432931e26
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.cc
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
+
+#include <cstring>
+
+#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
+
+namespace blink {
+
+String WebrtcCodecNameFromMimeType(const String& mime_type,
+ const char* prefix) {
+ if (mime_type.StartsWith(prefix)) {
+ wtf_size_t length =
+ static_cast<wtf_size_t>(mime_type.length() - strlen(prefix) - 1);
+ const String codec_name = mime_type.Right(length);
+ return codec_name;
+ }
+ return "";
+}
+
+webrtc::SdpVideoFormat::Parameters ConvertToSdpVideoFormatParameters(
+ const ParsedContentHeaderFieldParameters& parameters) {
+ webrtc::SdpVideoFormat::Parameters sdp_parameters;
+ for (const auto& parameter : parameters) {
+ sdp_parameters[parameter.name.Utf8()] = parameter.value.Utf8();
+ }
+ return sdp_parameters;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.h
index 77426ea4d94..40f4ad8f39e 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_util.h
@@ -6,24 +6,15 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_UTIL_H_
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
namespace blink {
// TODO(crbug.com/787254): Move these template definitions out of the Blink
// exposed API when all their clients get Onion souped.
template <typename OptionalT>
-absl::optional<typename OptionalT::value_type> ToBaseOptional(
- const OptionalT& optional) {
- return optional ? absl::make_optional(*optional) : absl::nullopt;
-}
-
-template <typename OptionalT>
-absl::optional<typename OptionalT::value_type> ToBaseOptional(
- OptionalT&& optional) {
- return optional ? absl::make_optional(*optional) : absl::nullopt;
-}
-
-template <typename OptionalT>
absl::optional<typename OptionalT::value_type> ToAbslOptional(
const OptionalT& optional) {
return optional ? absl::make_optional(*optional) : absl::nullopt;
@@ -44,6 +35,11 @@ bool OptionalEquals(const OptionalT1& lhs, const OptionalT2& rhs) {
return *lhs == *rhs;
}
+String WebrtcCodecNameFromMimeType(const String& mime_type, const char* prefix);
+
+webrtc::SdpVideoFormat::Parameters ConvertToSdpVideoFormatParameters(
+ const ParsedContentHeaderFieldParameters& parameters);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
index 1b97105a38e..4b9edbf1fec 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
@@ -7,8 +7,10 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
namespace {
@@ -91,17 +93,12 @@ WebRtcVideoTrackSource::WebRtcVideoTrackSource(
media::VideoCaptureFeedbackCB callback,
media::GpuVideoAcceleratorFactories* gpu_factories)
: AdaptedVideoTrackSource(/*required_alignment=*/1),
+ adapter_resources_(
+ new WebRtcVideoFrameAdapter::SharedResources(gpu_factories)),
is_screencast_(is_screencast),
needs_denoising_(needs_denoising),
callback_(callback) {
DETACH_FROM_THREAD(thread_checker_);
- if (base::FeatureList::IsEnabled(kWebRtcUseModernFrameAdapter)) {
- adapter_resources_ =
- new WebRtcVideoFrameAdapter::SharedResources(gpu_factories);
- } else {
- legacy_adapter_resources_ =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(gpu_factories);
- }
}
WebRtcVideoTrackSource::~WebRtcVideoTrackSource() = default;
@@ -141,11 +138,7 @@ void WebRtcVideoTrackSource::SendFeedback() {
media::VideoCaptureFeedback feedback;
feedback.max_pixels = video_adapter()->GetTargetPixels();
feedback.max_framerate_fps = video_adapter()->GetMaxFramerate();
- if (base::FeatureList::IsEnabled(kWebRtcUseModernFrameAdapter)) {
- feedback.Combine(adapter_resources_->GetFeedback());
- } else {
- feedback.Combine(legacy_adapter_resources_->GetFeedback());
- }
+ feedback.Combine(adapter_resources_->GetFeedback());
callback_.Run(feedback);
}
@@ -154,7 +147,7 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
std::vector<scoped_refptr<media::VideoFrame>> scaled_frames) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
TRACE_EVENT0("media", "WebRtcVideoSource::OnFrameCaptured");
- if (!LegacyWebRtcVideoFrameAdapter::IsFrameAdaptable(frame.get())) {
+ if (!CanConvertToWebRtcVideoFrameBuffer(frame.get())) {
// Since connecting sources and sinks do not check the format, we need to
// just ignore formats that we can not handle.
LOG(ERROR) << "We cannot send frame with storage type: "
@@ -326,14 +319,9 @@ void WebRtcVideoTrackSource::DeliverFrame(
update_rect = nullptr;
}
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter;
- if (base::FeatureList::IsEnabled(kWebRtcUseModernFrameAdapter)) {
- frame_adapter = new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
- frame, std::move(scaled_frames), adapter_resources_);
- } else {
- frame_adapter = new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- frame, legacy_adapter_resources_);
- }
+ rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter(
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ frame, std::move(scaled_frames), adapter_resources_));
webrtc::VideoFrame::Builder frame_builder =
webrtc::VideoFrame::Builder()
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
index f4c05b670d2..97ef37c8fe1 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
@@ -11,7 +11,6 @@
#include "media/base/video_frame_pool.h"
#include "media/capture/video/video_capture_feedback.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
#include "third_party/webrtc/media/base/adapted_video_track_source.h"
#include "third_party/webrtc/rtc_base/timestamp_aligner.h"
@@ -43,6 +42,8 @@ class PLATFORM_EXPORT WebRtcVideoTrackSource
absl::optional<bool> needs_denoising,
media::VideoCaptureFeedbackCB callback,
media::GpuVideoAcceleratorFactories* gpu_factories);
+ WebRtcVideoTrackSource(const WebRtcVideoTrackSource&) = delete;
+ WebRtcVideoTrackSource& operator=(const WebRtcVideoTrackSource&) = delete;
~WebRtcVideoTrackSource() override;
void SetCustomFrameAdaptationParamsForTesting(
@@ -81,8 +82,6 @@ class PLATFORM_EXPORT WebRtcVideoTrackSource
// |thread_checker_| is bound to the libjingle worker thread.
THREAD_CHECKER(thread_checker_);
scoped_refptr<WebRtcVideoFrameAdapter::SharedResources> adapter_resources_;
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources>
- legacy_adapter_resources_;
// State for the timestamp translation.
rtc::TimestampAligner timestamp_aligner_;
@@ -100,8 +99,6 @@ class PLATFORM_EXPORT WebRtcVideoTrackSource
custom_frame_adaptation_params_for_testing_;
const media::VideoCaptureFeedbackCB callback_;
-
- DISALLOW_COPY_AND_ASSIGN(WebRtcVideoTrackSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source_test.cc
index b471fe6bc1e..4dc6273b1df 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source_test.cc
@@ -13,6 +13,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h"
#include "third_party/blink/renderer/platform/testing/video_frame_utils.h"
+#include "third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.h"
#include "third_party/webrtc/api/video/video_frame.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
@@ -146,7 +147,7 @@ std::vector<WebRtcVideoTrackSourceTest::ParamType> TestParams() {
std::vector<WebRtcVideoTrackSourceTest::ParamType> test_params;
// All formats for owned memory.
for (media::VideoPixelFormat format :
- LegacyWebRtcVideoFrameAdapter::AdaptableMappablePixelFormats()) {
+ GetPixelFormatsMappableToWebRtcVideoFrameBuffer()) {
test_params.emplace_back(
media::VideoFrame::StorageType::STORAGE_OWNED_MEMORY, format);
}
diff --git a/chromium/third_party/blink/renderer/platform/platform.gni b/chromium/third_party/blink/renderer/platform/platform.gni
index 98d78db7618..1fb4718b688 100644
--- a/chromium/third_party/blink/renderer/platform/platform.gni
+++ b/chromium/third_party/blink/renderer/platform/platform.gni
@@ -3,7 +3,6 @@
# found in the LICENSE file.
platform_config_add = [
- "//build/config/compiler:no_size_t_to_int_warning",
"//build/config/compiler:wexit_time_destructors",
"//third_party/blink/renderer:config",
"//third_party/blink/renderer:inside_blink",
diff --git a/chromium/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc b/chromium/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc
index b8acc5aecbb..8ed7db21825 100644
--- a/chromium/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
+#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 9158a16d4e3..8dc06627b2a 100644
--- a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -33,7 +33,7 @@
// shipped stable can have its runtime flag removed soon after.
status: {
valid_values: ["stable", "experimental", "test"],
- valid_keys: ["Android", "Win", "ChromeOS", "Mac"]
+ valid_keys: ["Android", "Win", "ChromeOS", "Mac", "Lacros"]
},
// "implied_by" or "depends_on" specifies relationship to other features:
@@ -139,8 +139,10 @@
status: "experimental",
},
{
+ name: "AccessibilityPageZoom",
+ },
+ {
name: "AccessibilityUseAXPositionForDocumentMarkers",
- status: "test",
},
{
name: "AddEventListenerAbortSignal",
@@ -174,6 +176,10 @@
status: "experimental",
},
{
+ name: "AnonymousIframe",
+ status: "test",
+ },
+ {
name: "AOMAriaProperties",
status: "stable",
},
@@ -209,6 +215,13 @@
status: "experimental",
},
{
+ name: "AutoExpandDetailsElement",
+ },
+ {
+ name: "AutofillShadowDOM",
+ status: "experimental",
+ },
+ {
name: "AutoLazyLoadOnReloads",
depends_on: ["LazyFrameLoading"],
},
@@ -237,6 +250,11 @@
name: "AutoplayIgnoresWebAudio",
settable_from_internals: true,
},
+ // When enabled, enforces new interoperable semantics for 3D transforms.
+ // See crbug.com/1008483.
+ {
+ name: "BackfaceVisibilityInterop",
+ },
{
name: "BackForwardCache",
},
@@ -316,11 +334,18 @@
name: "Canvas2dImageChromium",
},
{
+ name: "Canvas2dLayers",
+ },
+ {
name: "Canvas2dScrollPathIntoView",
status: "experimental",
},
{
name: "CanvasColorManagement",
+ status: "stable",
+ },
+ {
+ name: "CanvasColorManagementV2",
status: "experimental",
},
{
@@ -361,10 +386,22 @@
status: "experimental",
},
{
+ name: "ClipboardCustomFormats",
+ status: "experimental",
+ },
+ {
+ name: "ClipboardReadPng",
+ status: "experimental",
+ },
+ {
name: "ClipboardSvg",
status: "experimental",
},
{
+ name: "CLSScrollAnchoring",
+ status: "experimental",
+ },
+ {
name: "COLRV1Fonts",
status: "experimental",
},
@@ -373,6 +410,7 @@
},
{
name: "CompositeBGColorAnimation",
+ status: "experimental",
},
{
name: "CompositeClipPathAnimation",
@@ -386,10 +424,6 @@
status: "stable"
},
{
- name: "CompositeSVG",
- status: "stable"
- },
- {
name: "ComputedAccessibilityInfo",
status: "experimental",
},
@@ -424,15 +458,9 @@
origin_trial_feature_name: "ConversionMeasurement",
origin_trial_allows_third_party: true,
status: "experimental",
- depends_on: ["ConversionMeasurementInfraSupport"],
- },
- {
- // Feature to explicitly disable/enable the Conversion
- // Measurement API when there is not browser process side infra.
- name: "ConversionMeasurementInfraSupport",
},
{
- name: "CookiesWithoutSameSiteMustBeSecure",
+ name: "ConversionMeasurementEventSources",
status: "test",
},
{
@@ -441,6 +469,16 @@
{
name: "CorsRFC1918",
},
+ // This block isn't really used on its own. Blink doesn't really have to
+ // know about COEP:credentialless. However it is used for "declaring" the
+ // OriginTrial feature name. This is similar to:
+ // https://chromium-review.googlesource.com/c/chromium/src/+/2366778
+ // for CrossOriginOpenerPolicyReporting.
+ {
+ name: "CrossOriginEmbedderPolicyCredentialless",
+ origin_trial_feature_name: "CrossOriginEmbedderPolicyCredentiallessOriginTrial",
+ status: "experimental",
+ },
{
name: "CrossOriginIsolation",
status: "stable",
@@ -452,39 +490,31 @@
status: "experimental",
},
{
- name: "CSS3Text",
- status: "experimental",
+ name: "CrossOriginWebAssemblyModuleSharingAllowed",
},
{
- name: "CSSAccentColor",
+ name: "CSS3Text",
status: "experimental",
},
{
- name: "CSSAspectRatioInterpolation",
- status: "stable",
- },
- {
- name: "CSSAspectRatioProperty",
- status: "stable",
- },
- {
- // https://drafts.csswg.org/css-counter-styles-3
- name: "CSSAtRuleCounterStyle",
+ name: "CSSAccentColor",
status: "stable",
},
{
// Whether <image> values are allowed as counter style <symbol>
name: "CSSAtRuleCounterStyleImageSymbols",
- depends_on: ["CSSAtRuleCounterStyle"]
},
{
// https://github.com/w3c/csswg-drafts/issues/5693
// Experimental support of @counter-style rules in shadow DOM.
name: "CSSAtRuleCounterStyleInShadowDOM",
- depends_on: ["CSSAtRuleCounterStyle"],
status: "test",
},
{
+ // https://drafts.csswg.org/css-counter-styles/#counter-style-speak-as
+ name: "CSSAtRuleCounterStyleSpeakAsDescriptor"
+ },
+ {
name: "CSSCalcAsInt",
status: "test",
},
@@ -493,28 +523,41 @@
name: "CSSCalcInfinityAndNaN",
},
{
+ // https://drafts.csswg.org/css-cascade-5/#layering
+ name: "CSSCascadeLayers"
+ },
+ {
// Support case-sensitive attribute selector modifier
// https://drafts.csswg.org/selectors-4/#attribute-case
name: "CSSCaseSensitiveSelector",
status: "test",
},
{
- // When the color-scheme is supported via the CSS color-scheme property
- // (CSSColorScheme) or the meta tag (MetaColorScheme), the only UA
- // rendering change is for the canvas background and the :root element
- // color property. Enabling this runtime flag will enable dark UA
- // rendering for form controls, scrollbars, etc.
- name: "CSSColorSchemeUARendering",
- status: "stable",
+ // Support the 'only' keyword for the color-scheme property.
+ name: "CSSColorSchemeOnly",
+ status: "test",
},
{
name: "CSSColorTypedOM",
status: "experimental",
},
{
+ // Stop propagation from BODY to HTML and viewport if HTML or BODY
+ // elements have any containment applied.
+ // https://drafts.csswg.org/css-contain-2/#contain-property
+ name: "CSSContainedBodyPropagation",
+ status: "test",
+ },
+ {
+ // https://drafts.csswg.org/css-contain-3/#container-queries
name: "CSSContainerQueries",
},
{
+ // https://drafts.csswg.org/css-contain-3/#container-lengths
+ name: "CSSContainerRelativeUnits",
+ implied_by: ["CSSContainerQueries"]
+ },
+ {
// Support for contain:inline-size and contain:block-size
name: "CSSContainSize1D",
implied_by: ["CSSContainerQueries"]
@@ -535,6 +578,16 @@
status: "experimental"
},
{
+ name: "CSSDynamicRangeMediaQueries",
+ status: "experimental"
+ },
+ {
+ // Include custom properties in CSSComputedStyleDeclaration::item/length.
+ // https://crbug.com/949807
+ name: "CSSEnumeratedCustomProperties",
+ status: "test",
+ },
+ {
name: "CSSFocusVisible",
status: "stable",
},
@@ -543,26 +596,12 @@
status: "experimental",
},
{
- // @font-face descriptor advance-override.
- // https://drafts.csswg.org/css-fonts-5/#descdef-font-face-advance-override
- name: "CSSFontFaceAdvanceOverride",
- status: "test",
- depends_on: ["CSSFontMetricsOverride"],
- },
- {
// @font-face descriptor size-adjust.
// https://drafts.csswg.org/css-fonts-5/#descdef-font-face-size-adjust
name: "CSSFontFaceSizeAdjust",
status: "stable",
},
{
- // @font-face descriptors ascent-override, descent-override and
- // line-gap-override.
- // https://drafts.csswg.org/css-fonts-4/#font-metrics-override-desc
- name: "CSSFontMetricsOverride",
- status: "stable",
- },
- {
name: "CSSFontSizeAdjust",
status: "test",
},
@@ -578,6 +617,12 @@
status: "experimental",
},
{
+ // CSS animation/transition updates occur outside style recalc.
+ //
+ // https://crbug.com/1180159
+ name: "CSSIsolatedAnimationUpdates",
+ },
+ {
name: "CSSLayoutAPI",
status: "experimental",
},
@@ -615,7 +660,7 @@
},
{
name: "CSSModules",
- status: "experimental",
+ status: "stable",
},
{
name: "CSSOffsetPathRay",
@@ -647,6 +692,15 @@
status: "experimental",
},
{
+ name: "CSSPseudoHas",
+ status: "test",
+ },
+ {
+ name: "CSSPseudoHasInSnapshotProfile",
+ status: "experimental",
+ implied_by: ["CSSPseudoHas"],
+ },
+ {
// When an audio, video, or similar resource is "playing"
// or "paused".
// https://www.w3.org/TR/selectors-4/#video-state
@@ -735,21 +789,24 @@
status: "stable",
},
{
- name: "DelayAsyncScriptExecutionUntilFinishedParsing",
- },
- {
- name: "DelayAsyncScriptExecutionUntilFirstPaintOrFinishedParsing",
- },
- {
name: "DelegatedInkTrails",
- status: "experimental",
+ status: "stable",
},
{
name: "DesktopCaptureDisableLocalEchoControl",
status: "experimental",
},
{
+ name: "DesktopPWAsSubApps",
+ // No status because this blink runtime feature doesn't work by itself.
+ // It's controlled by the corresponding Chromium feature which needs to
+ // be enabled to make the whole feature work.
+ },
+ {
name: "DeviceAttributes",
+ origin_trial_feature_name: "DeviceAttributes",
+ origin_trial_os: ["chromeos"],
+ origin_trial_allows_third_party: true,
status: "experimental",
},
{
@@ -757,6 +814,10 @@
status: "experimental",
},
{
+ name: "DialogFocusNewSpecBehavior",
+ status: "stable",
+ },
+ {
name: "DigitalGoods",
origin_trial_feature_name: "DigitalGoods",
origin_trial_os: ["android", "chromeos"],
@@ -789,15 +850,12 @@
name: "DisableLayerSquashing",
},
{
- name: "DisallowDocumentAccess",
- status: "experimental",
- },
- {
- name: "DisplayCapturePermissionPolicy",
- origin_trial_feature_name: "GetCurrentBrowsingContextMedia",
- // TODO(crbug.com/1150788): Implement for Android when this is applied
- // to getDisplayMedia.
- status: {"Android": "", "default": "experimental"},
+ // When on, the display-capture permissions-policy is enforced.
+ // When off, enforcement of this permissions-policy is skipped.
+ // This is driven from the browser process by the Enterprise policy
+ // called "DisplayCapturePermissionsPolicyEnabled".
+ // TODO(crbug.com/1233969): Remove this around m100.
+ name: "DisplayCapturePermissionsPolicy",
},
{
name: "DisplayCutoutAPI",
@@ -824,7 +882,7 @@
name: "DocumentPolicyNegotiation",
origin_trial_feature_name: "DocumentPolicyNegotiation",
status: "experimental",
- depends_on: ['DocumentPolicy']
+ depends_on: ["DocumentPolicy"],
},
// Enables the ability to use Document Policy header to control feature
// SyncXHR.
@@ -837,12 +895,17 @@
// Document transitions, including shared element transitions.
// See https://github.com/WICG/shared-element-transitions
name: "DocumentTransition",
- origin_trial_feature_name: "DocumentTransition"
+ origin_trial_feature_name: "DocumentTransition",
},
{
name: "DocumentWrite",
},
{
+ name: "EarlyHintsPreloadForNavigationOptIn",
+ origin_trial_feature_name: "EarlyHintsPreloadForNavigation",
+ status: "experimental",
+ },
+ {
name: "EditContext",
settable_from_internals: true,
status: "test",
@@ -853,19 +916,15 @@
status: "stable",
},
{
- name: "EncryptedMediaEncryptionSchemeQuery",
- status: "stable",
- },
- {
- name: "EncryptedMediaHdcpPolicyCheck",
- status: "stable",
+ name: "EncryptedMediaSessionClosedReason",
+ status: "experimental",
},
{
name: "EnterKeyHintAttribute",
status: "stable",
},
{
- name: "EventTiming",
+ name: "ExceptionMetaDataForDevTools",
status: "stable",
},
{
@@ -873,10 +932,6 @@
status: "test",
},
{
- name: "ExpensiveBackgroundTimerThrottling",
- status: "stable",
- },
- {
name: "ExperimentalContentSecurityPolicyFeatures",
status: "experimental",
},
@@ -898,7 +953,7 @@
{
name: "ExperimentalJSProfiler",
origin_trial_feature_name: "ExperimentalJSProfiler",
- status: "experimental"
+ status: "stable"
},
{
name: "ExperimentalPolicies",
@@ -914,7 +969,7 @@
},
{
name: "EyeDropperAPI",
- status: "test",
+ status: "experimental",
},
{
name: "FaceDetector",
@@ -958,6 +1013,11 @@
origin_trial_os: ["win", "mac", "linux", "chromeos"],
},
{
+ name: "FileHandlingIcons",
+ depends_on: ["FileHandling"],
+ status: {"Android": "test", "default": "experimental"},
+ },
+ {
name: "FileSystem",
status: "stable",
},
@@ -966,6 +1026,12 @@
status: {"Android": "test", "default": "stable"},
},
{
+ name: "FileSystemAccessAccessHandle",
+ // No status because this blink runtime feature doesn't work by itself.
+ // It's controlled by the corresponding Chromium feature which needs to
+ // be enabled to make the whole feature work.
+ },
+ {
// In-development features for the File System Access API.
name: "FileSystemAccessAPIExperimental",
status: "experimental",
@@ -1019,6 +1085,10 @@
status: {"ChromeOS": "stable"},
},
{
+ name: "FractionalLineHeight",
+ status: "experimental",
+ },
+ {
name: "FractionalScrollOffsets",
status: "experimental",
},
@@ -1031,12 +1101,6 @@
status: "experimental",
},
{
- name: "GetCurrentBrowsingContextMedia",
- origin_trial_feature_name: "GetCurrentBrowsingContextMedia",
- depends_on: ["GetDisplayMedia"],
- status: {"Android": "", "default": "experimental"},
- },
- {
name: "GetDisplayMedia",
status: {
"Android": "experimental",
@@ -1054,7 +1118,7 @@
{
name: "HandwritingRecognition",
status: "experimental",
- // Trial also requires kHandwritingRecognitionWebPlatformApi enabled.
+ // Trial also requires kHandwritingRecognitionWebPlatformApiFinch enabled.
origin_trial_feature_name: "HandwritingRecognition",
origin_trial_os: ["chromeos"]
},
@@ -1087,11 +1151,6 @@
},
{
name: "IdleDetection",
- origin_trial_feature_name: "IdleDetection",
- status: "experimental",
- },
- {
- name: "IgnoreCrossOriginWindowWhenNamedAccessOnWindow",
status: "stable",
},
{
@@ -1100,10 +1159,6 @@
status: {"Android": "stable"},
},
{
- name: "ImportMaps",
- status: "stable"
- },
- {
name: "InertAttribute",
status: "experimental",
},
@@ -1158,7 +1213,7 @@
// provides a convenient way for testing legacy layout code path in blink
// unit tests.
name: "LayoutNG",
- implied_by: ["LayoutNGGrid", "BidiCaretAffinity", "CSSContainerQueries"],
+ implied_by: ["BidiCaretAffinity", "CSSContainerQueries"],
status: "stable",
},
{
@@ -1166,6 +1221,10 @@
implied_by: ["LayoutNGPrinting"],
},
{
+ name: "LayoutNGBlockInInline",
+ depends_on: ["LayoutNG"],
+ },
+ {
// Traverse the fragment tree when painting and hit-testing, instead of
// the layout object tree.
name: "LayoutNGFragmentTraversal",
@@ -1180,7 +1239,8 @@
},
{
name: "LayoutNGGrid",
- implied_by: ["CSSContainerQueries"],
+ depends_on: ["LayoutNG"],
+ status: "stable",
},
{
name: "LayoutNGLayoutOverflowRecalc",
@@ -1191,11 +1251,6 @@
name: "LayoutNGPrinting",
},
{
- name: "LayoutNGReplaced",
- depends_on: ["LayoutNG"],
- status: "stable",
- },
- {
name: "LayoutNGTable",
depends_on: ["LayoutNG"],
status: "stable"
@@ -1203,6 +1258,7 @@
{
name: "LayoutNGTextCombine",
depends_on: ["LayoutNG"],
+ status: "stable"
},
{
name: "LayoutNGTextControl",
@@ -1236,10 +1292,6 @@
status: "stable",
},
{
- name: "ManagedInterface",
- "implied_by": ["DeviceAttributes", "ManagedConfiguration"],
- },
- {
name: "MathMLCore",
status:"experimental",
depends_on: ["LayoutNG"],
@@ -1307,6 +1359,11 @@
status: "test",
},
{
+ // https://github.com/whatwg/html/pull/6569
+ name: "MediaMetaThemeColor",
+ status: "stable",
+ },
+ {
name: "MediaPreservesPitch",
status: "stable",
},
@@ -1350,7 +1407,7 @@
},
{
name: "MediaStreamInsertableStreams",
- status: "experimental",
+ status: "stable",
origin_trial_feature_name: "WebCodecs"
},
// This is enabled by default on Windows only. The only part that's
@@ -1404,6 +1461,10 @@
status: "stable",
},
{
+ // Controlled by blink::features::kNavigatorPluginsFixed.
+ name: "NavigatorPluginsFixed",
+ },
+ {
name: "NetInfoDownlinkMax",
// Only Android, ChromeOS support NetInfo downlinkMax, type and ontypechange now
status: {"Android": "stable", "ChromeOS": "stable", "default": "experimental"},
@@ -1659,7 +1720,7 @@
{
name: "PointerLockOptions",
origin_trial_feature_name: "PointerLockOptions",
- status: 'stable',
+ status: "stable",
},
{
name: "PointerRawUpdate",
@@ -1689,15 +1750,15 @@
},
{
name: "PrefersColorSchemeClientHintHeader",
- status: "experimental",
+ status: "stable",
},
{
name: "PrefersContrast",
depends_on: ["ForcedColors"],
},
{
- name: 'PrefersReducedData',
- status: 'experimental',
+ name: "PrefersReducedData",
+ status: "experimental",
},
// This feature is deprecated and we are evangelizing affected sites.
// See https://crbug.com/346236 for current status.
@@ -1707,6 +1768,8 @@
},
{
name: "Prerender2",
+ origin_trial_feature_name: "Prerender2",
+ origin_trial_os: ["android"],
},
{
name: "Presentation",
@@ -1718,6 +1781,13 @@
status: "experimental",
},
{
+ name: "PrivateNetworkAccessNonSecureContextsAllowed",
+ origin_trial_feature_name: "PrivateNetworkAccessNonSecureContextsAllowed",
+ origin_trial_type: "deprecation",
+ origin_trial_allows_insecure: true,
+ status: "experimental",
+ },
+ {
name: "PushMessaging",
status: "stable",
},
@@ -1730,10 +1800,6 @@
status: "experimental",
},
{
- // Enabled when blink::features::kRawClipboard is enabled.
- name: "RawClipboard",
- },
- {
name: "RemotePlayback",
status: "stable",
},
@@ -1837,11 +1903,11 @@
name: "RTCUnifiedPlanByDefault",
},
{
- name: "SameSiteByDefaultCookies",
- status: "test",
+ name: "SanitizerAPI",
+ status: "experimental",
},
{
- name: "SanitizerAPI",
+ name: "SchedulerCurrentTaskSignal",
status: "experimental",
},
// WebSpeech API with both speech recognition and synthesis functionality
@@ -1856,7 +1922,7 @@
},
{
name: "ScrollbarGutter",
- status: "experimental",
+ status: "stable",
},
{
name: "ScrollbarWidth",
@@ -1872,7 +1938,7 @@
{
name: "ScrollTimeline",
status: "experimental",
- implied_by: ['AnimationWorklet', 'CSSScrollTimeline']
+ implied_by: ["AnimationWorklet", "CSSScrollTimeline"]
},
// Implements documentElement.scrollTop/Left and bodyElement.scrollTop/Left
// as per the spec, matching other Web engines.
@@ -1886,10 +1952,13 @@
{
name: "SecurePaymentConfirmation",
origin_trial_feature_name: "SecurePaymentConfirmationV2",
- origin_trial_os: ["mac", "win"],
+ origin_trial_os: ["mac", "win", "android"],
status: "experimental",
},
{
+ name: "SecurePaymentConfirmationAPIV3",
+ },
+ {
name: "SecurePaymentConfirmationDebug",
},
{
@@ -1917,6 +1986,11 @@
status: "experimental",
},
{
+ name: "ServiceWorkerSubresourceFilter",
+ origin_trial_feature_name: "ServiceWorkerSubresourceFilter",
+ status: "experimental",
+ },
+ {
name: "SharedArrayBuffer",
},
{
@@ -1930,6 +2004,10 @@
status: "experimental",
},
{
+ name: "SharedStorageAPI",
+ status: "test",
+ },
+ {
name: "SharedWorker",
// Android does not yet support SharedWorker. crbug.com/154571
status: {"Android": "", "default": "stable"},
@@ -2063,10 +2141,6 @@
status: "stable",
},
{
- name: "TimerThrottlingForHiddenFrames",
- status: "stable",
- },
- {
name: "TimeZoneChangeEvent",
status: "experimental",
},
@@ -2090,6 +2164,7 @@
// See crbug.com/1008483.
{
name: "TransformInterop",
+ status: "stable",
},
// This is conditionally set if the platform supports translation.
{
@@ -2141,6 +2216,10 @@
status: "experimental",
},
{
+ name: "URLPatternCompareComponent",
+ status: "experimental",
+ },
+ {
name: "UserActivationSameOriginVisibility",
},
{
@@ -2148,6 +2227,11 @@
status: "stable",
},
{
+ name: "UserAgentReduction",
+ origin_trial_feature_name: "UserAgentReduction",
+ status: "experimental",
+ },
+ {
name: "UUID",
status: "stable"
},
@@ -2176,7 +2260,7 @@
},
{
name: "VirtualKeyboard",
- status: "test",
+ status: "stable",
},
{
name: "VisibilityCollapseColumn",
@@ -2192,27 +2276,42 @@
// should work with both screen and system wake locks.
name: "WakeLock",
status: "stable",
- implied_by: ['SystemWakeLock'],
+ implied_by: ["SystemWakeLock"],
},
{
name: "WebAnimationsAPI",
status: "stable",
- implied_by: ['AnimationWorklet']
+ implied_by: ["AnimationWorklet"],
},
{
name: "WebAnimationsSVG",
status: "experimental",
},
{
+ name: "WebAppLaunchHandler",
+ status: "experimental",
+ },
+ {
name: "WebAppLinkCapturing",
origin_trial_feature_name: "WebAppLinkCapturing",
origin_trial_os: ["chromeos"],
},
{
+ // This flag enables the Manifest parser to handle id field.
+ // Also enabled when blink::features::kWebAppEnableManifestId is
+ // overridden on the command line (or via chrome://flags).
+ name: "WebAppManifestId",
+ status: "experimental",
+ },
+ {
name:"WebAppsLockScreen",
status:"experimental",
},
{
+ name: "WebAppTabStrip",
+ status: "experimental",
+ },
+ {
// This flag enables the Manifest parser to handle URL Handlers.
// Also enabled when blink::features::kWebAppEnableUrlHandlers is
// overridden on the command line (or via chrome://flags).
@@ -2225,6 +2324,7 @@
name: "WebAppWindowControlsOverlay",
origin_trial_feature_name: "WebAppWindowControlsOverlay",
origin_trial_os: ["win", "mac", "linux"],
+ status: "experimental",
},
{
name: "WebAssemblyCSP",
@@ -2234,11 +2334,6 @@
origin_trial_feature_name: "WebAssemblyExceptions",
status: "test",
},
- {
- name: "WebAssemblySimd",
- origin_trial_feature_name: "WebAssemblySimd",
- status: "test",
- },
// WebAuth is disabled on Android versions prior to N (7.0) due to lack of
// supporting APIs, see runtime_features.cc.
{
@@ -2305,7 +2400,7 @@
},
{
name: "WebCodecs",
- status: "experimental",
+ status: "stable",
origin_trial_feature_name: "WebCodecs"
},
{
@@ -2313,6 +2408,10 @@
status: "experimental",
},
{
+ name: "WebGLDeveloperExtensions",
+ status: "experimental",
+ },
+ {
name: "WebGLDraftExtensions",
status: "experimental",
},
@@ -2346,17 +2445,16 @@
},
{
name: "WebOTP",
- status: {"default": "experimental", "Android": "stable"},
+ status: "stable",
},
{
name: "WebOTPAssertionFeaturePolicy",
depends_on: ["WebOTP"],
- status: {"default": "experimental", "Android": "stable"},
+ status: "stable",
},
{
name: "WebScheduler",
- origin_trial_feature_name: "WebScheduler",
- status: "experimental",
+ status: "stable",
},
// WebShare is enabled by default on Android.
{
@@ -2460,7 +2558,7 @@
// exposes requisite information about displays connected to the device.
{
name: "WindowPlacement",
- origin_trial_feature_name: "WindowPlacement",
+ origin_trial_feature_name: "WindowPlacementOT2",
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 9b6541592a9..b659b98bec2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -7,8 +7,6 @@ import("//third_party/blink/renderer/platform/platform.gni")
import("//third_party/protobuf/proto_library.gni")
blink_platform_sources("scheduler") {
- configs += [ "//build/config/compiler:noshadowing" ]
-
sources = [
"common/cancelable_closure_holder.cc",
"common/cancelable_closure_holder.h",
@@ -43,13 +41,10 @@ blink_platform_sources("scheduler") {
"common/thread_type.cc",
"common/throttling/budget_pool.cc",
"common/throttling/budget_pool.h",
- "common/throttling/budget_pool_controller.h",
"common/throttling/cpu_time_budget_pool.cc",
"common/throttling/cpu_time_budget_pool.h",
"common/throttling/task_queue_throttler.cc",
"common/throttling/task_queue_throttler.h",
- "common/throttling/throttled_time_domain.cc",
- "common/throttling/throttled_time_domain.h",
"common/throttling/wake_up_budget_pool.cc",
"common/throttling/wake_up_budget_pool.h",
"common/tracing_helper.cc",
@@ -59,12 +54,11 @@ blink_platform_sources("scheduler") {
"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_scheduling_priority.cc",
"common/web_thread_scheduler.cc",
"common/worker_pool.cc",
"main_thread/agent_group_scheduler_impl.cc",
"main_thread/agent_group_scheduler_impl.h",
- "main_thread/agent_scheduling_strategy.cc",
- "main_thread/agent_scheduling_strategy.h",
"main_thread/attribution_group.h",
"main_thread/auto_advancing_virtual_time_domain.cc",
"main_thread/auto_advancing_virtual_time_domain.h",
@@ -93,6 +87,8 @@ blink_platform_sources("scheduler") {
"main_thread/main_thread_scheduler_impl.h",
"main_thread/main_thread_task_queue.cc",
"main_thread/main_thread_task_queue.h",
+ "main_thread/main_thread_web_scheduling_task_queue_impl.cc",
+ "main_thread/main_thread_web_scheduling_task_queue_impl.h",
"main_thread/memory_purge_manager.cc",
"main_thread/memory_purge_manager.h",
"main_thread/non_waking_time_domain.cc",
@@ -113,9 +109,6 @@ blink_platform_sources("scheduler") {
"main_thread/user_model.cc",
"main_thread/user_model.h",
"main_thread/web_render_widget_scheduling_state.cc",
- "main_thread/web_scheduling_priority.cc",
- "main_thread/web_scheduling_task_queue_impl.cc",
- "main_thread/web_scheduling_task_queue_impl.h",
"main_thread/web_scoped_virtual_time_pauser.cc",
"main_thread/widget_scheduler.cc",
"main_thread/widget_scheduler.h",
@@ -154,6 +147,8 @@ blink_platform_sources("scheduler") {
"worker/non_main_thread_scheduler_impl.h",
"worker/non_main_thread_task_queue.cc",
"worker/non_main_thread_task_queue.h",
+ "worker/non_main_thread_web_scheduling_task_queue_impl.cc",
+ "worker/non_main_thread_web_scheduling_task_queue_impl.h",
"worker/worker_metrics_helper.cc",
"worker/worker_metrics_helper.h",
"worker/worker_scheduler.cc",
@@ -233,7 +228,6 @@ source_set("unit_tests") {
"common/tracing_helper_unittest.cc",
"common/ukm_task_sampler_unittest.cc",
"common/worker_pool_unittest.cc",
- "main_thread/agent_scheduling_strategy_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",
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
index 61de10d0719..f3923c230ac 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
@@ -53,7 +53,6 @@ include_rules = [
"+components/scheduling_metrics",
"+services/metrics",
- "+third_party/abseil-cpp/absl/types/optional.h",
"+third_party/blink/renderer/platform/back_forward_cache_utils.h",
"+third_party/blink/renderer/platform/bindings/parkable_string_manager.h",
"+third_party/blink/renderer/platform/instrumentation",
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/OWNERS b/chromium/third_party/blink/renderer/platform/scheduler/OWNERS
index a3f384b76b0..9f21b467660 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/OWNERS
@@ -1,7 +1,6 @@
# LON scheduling team
altimin@chromium.org
carlscab@google.com
-rmcilroy@chromium.org
skyostil@chromium.org
# MTV web scheduling API team
@@ -9,3 +8,6 @@ shaseley@chromium.org
# TOK scheduling team
kouhei@chromium.org
+
+# MON Catan team
+fdoray@chromium.org
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
index fccee47080b..309052a02f9 100644
--- 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_CANCELABLE_CLOSURE_HOLDER_H_
#include "base/cancelable_callback.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
@@ -19,6 +18,8 @@ class CancelableClosureHolder {
public:
CancelableClosureHolder();
+ CancelableClosureHolder(const CancelableClosureHolder&) = delete;
+ CancelableClosureHolder& operator=(const CancelableClosureHolder&) = delete;
~CancelableClosureHolder();
// Resets the closure to be wrapped by the cancelable callback. Cancels any
@@ -35,8 +36,6 @@ class CancelableClosureHolder {
private:
base::RepeatingClosure callback_;
base::CancelableRepeatingClosure cancelable_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(CancelableClosureHolder);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
index f6a029de1f6..3586b8e341a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
@@ -71,13 +71,8 @@ void CooperativeSchedulingManager::SafepointSlow() {
return;
// TODO(keishi): Also bail if V8 EnteredContextCount is more than 1
- // This task slice completes here.
- Thread::MainThread()->Scheduler()->OnSafepointEntered();
RunNestedLoop();
-
- // A new task slice starts here.
- Thread::MainThread()->Scheduler()->OnSafepointExited();
}
void CooperativeSchedulingManager::RunNestedLoop() {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
index 67982ca4bd0..bcefbdf09ca 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -62,6 +62,7 @@ class DummyFrameScheduler : public FrameScheduler {
void DidCommitProvisionalLoad(bool, FrameScheduler::NavigationType) override {
}
void OnFirstContentfulPaintInMainFrame() override {}
+ void OnDomContentLoaded() override {}
void OnFirstMeaningfulPaint() override {}
void OnLoad() override {}
bool IsExemptFromBudgetBasedThrottling() const override { return false; }
@@ -122,7 +123,6 @@ class DummyPageScheduler : public PageScheduler {
void SetPageVisible(bool) override {}
void SetPageFrozen(bool) override {}
void SetPageBackForwardCached(bool) override {}
- void OnFocusChanged(bool focused) override {}
void SetKeepActive(bool) override {}
bool IsMainFrameLocal() const override { return true; }
void SetIsMainFrameLocal(bool) override {}
@@ -131,7 +131,6 @@ class DummyPageScheduler : public PageScheduler {
void DisableVirtualTimeForTesting() override {}
bool VirtualTimeAllowedToAdvance() const override { return true; }
void SetInitialVirtualTime(base::Time) override {}
- void SetInitialVirtualTimeOffset(base::TimeDelta) override {}
void SetVirtualTimePolicy(VirtualTimePolicy) override {}
void GrantVirtualTimeBudget(base::TimeDelta, base::OnceClosure) override {}
void SetMaxVirtualTimeTaskStarvationCount(int) override {}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc
index 3671d7a7d9b..dc69dfc189b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc
@@ -63,29 +63,7 @@ bool IsIntensiveWakeUpThrottlingEnabled() {
// that admins get consistent behaviour that clients can't override. Otherwise
// use the base::FeatureParams.
-base::TimeDelta GetIntensiveWakeUpThrottlingDurationBetweenWakeUps() {
- DCHECK(IsIntensiveWakeUpThrottlingEnabled());
-
- // Controls the period during which at most 1 wake up from throttleable
- // TaskQueues in a page can take place.
- static const base::FeatureParam<int>
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds{
- &features::kIntensiveWakeUpThrottling,
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Name,
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default};
-
- int seconds =
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default;
- if (GetIntensiveWakeUpThrottlingPolicyOverride() ==
- PolicyOverride::NO_OVERRIDE) {
- seconds = kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds.Get();
- }
- return base::TimeDelta::FromSeconds(seconds);
-}
-
base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod() {
- DCHECK(IsIntensiveWakeUpThrottlingEnabled());
-
// Controls the time that elapses after a page is backgrounded before the
// throttling policy takes effect.
static const base::FeatureParam<int>
@@ -102,41 +80,34 @@ base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod() {
return base::TimeDelta::FromSeconds(seconds);
}
-base::TimeDelta GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate() {
- DCHECK(IsIntensiveWakeUpThrottlingEnabled());
+const base::Feature kThrottleForegroundTimers{
+ "ThrottleForegroundTimers", base::FEATURE_DISABLED_BY_DEFAULT};
- constexpr int kDefaultSeconds = 3;
-
- static const base::FeatureParam<int> kFeatureParam{
- &features::kIntensiveWakeUpThrottling,
- "inhibit_seconds_on_title_or_favicon_update_seconds", kDefaultSeconds};
-
- int seconds = kDefaultSeconds;
- if (GetIntensiveWakeUpThrottlingPolicyOverride() ==
- PolicyOverride::NO_OVERRIDE) {
- seconds = kFeatureParam.Get();
- }
-
- return base::TimeDelta::FromSeconds(seconds);
-}
-
-bool CanIntensivelyThrottleLowNestingLevel() {
- DCHECK(IsIntensiveWakeUpThrottlingEnabled());
-
- static const base::FeatureParam<bool> kFeatureParam{
- &features::kIntensiveWakeUpThrottling,
- kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Name,
- kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default};
-
- bool value =
- kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default;
- if (GetIntensiveWakeUpThrottlingPolicyOverride() ==
- PolicyOverride::NO_OVERRIDE) {
- value = kFeatureParam.Get();
- }
-
- return value;
+base::TimeDelta GetForegroundTimersThrottledWakeUpInterval() {
+ constexpr int kForegroundTimersThrottling_WakeUpIntervalMillis_Default = 100;
+ static const base::FeatureParam<int>
+ kForegroundTimersThrottledWakeUpIntervalMills{
+ &kThrottleForegroundTimers,
+ "ForegroundTimersThrottledWakeUpIntervalMills",
+ kForegroundTimersThrottling_WakeUpIntervalMillis_Default};
+ return base::TimeDelta::FromMilliseconds(
+ kForegroundTimersThrottledWakeUpIntervalMills.Get());
}
+const base::Feature kDeprioritizeDOMTimersDuringPageLoading{
+ "DeprioritizeDOMTimersDuringPageLoading",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::FeatureParam<DeprioritizeDOMTimersPhase>::Option
+ kDeprioritizeDOMTimersPhaseOptions[] = {
+ {DeprioritizeDOMTimersPhase::kOnDOMContentLoaded, "ondomcontentloaded"},
+ {DeprioritizeDOMTimersPhase::kFirstContentfulPaint, "fcp"},
+ {DeprioritizeDOMTimersPhase::kOnLoad, "onload"}};
+
+const base::FeatureParam<DeprioritizeDOMTimersPhase>
+ kDeprioritizeDOMTimersPhase{&kDeprioritizeDOMTimersDuringPageLoading,
+ "phase",
+ DeprioritizeDOMTimersPhase::kOnDOMContentLoaded,
+ &kDeprioritizeDOMTimersPhaseOptions};
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/features.h b/chromium/third_party/blink/renderer/platform/scheduler/common/features.h
index 2fc871df670..25580f735fe 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/features.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/features.h
@@ -54,26 +54,6 @@ const base::Feature kVeryHighPriorityForCompositingAfterDelay{
constexpr base::FeatureParam<int> kCompositingDelayLength{
&kVeryHighPriorityForCompositingAfterDelay, "CompositingDelayLength", 100};
-// If enabled, compositor priority will be set to kVeryHighPriority until
-// a budget has been exhausted. Once the budget runs out, the priority will
-// be set to kNormalPriority until there is enough budget to reprioritize.
-const base::Feature kVeryHighPriorityForCompositingBudget{
- "BlinkSchedulerVeryHighPriorityForCompositingBudget",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Param for kVeryHighPriorityForCompositingBudget experiment. This param
-// controls how much CPU time the compositor will be prioritized for, its
-// budget. Measured in ms.
-constexpr base::FeatureParam<int> kInitialCompositorBudgetInMilliseconds{
- &kVeryHighPriorityForCompositingBudget,
- "InitialCompositorBudgetInMilliseconds", 250};
-
-// Param for kVeryHighPriorityForCompositingBudget experiment. This param
-// controls the rate at which the budget is recovered.
-constexpr base::FeatureParam<double> kCompositorBudgetRecoveryRate{
- &kVeryHighPriorityForCompositingBudget, "CompositorBudgetRecoveryRate",
- 0.25};
-
// This feature functions as an experiment parameter for the
// VeryHighPriorityForCompositing alternating, delay, and budget experiments.
// When enabled, it does nothing unless one of these experiments is also
@@ -182,11 +162,8 @@ const base::Feature kHighPriorityDatabaseTaskType{
"HighPriorityDatabaseTaskType", base::FEATURE_DISABLED_BY_DEFAULT};
// When features::kIntensiveWakeUpThrottling is enabled, wake ups from timers
-// with a high nesting level are limited to 1 per
-// GetIntensiveWakeUpThrottlingDurationBetweenWakeUp() in a page that has been
-// backgrounded for GetIntensiveWakeUpThrottlingGracePeriod(). If
-// CanIntensivelyThrottleLowNestingLevel() is true, this policy is also applied
-// to timers with a non-zero delay and a low nesting level.
+// with a high nesting level are limited to 1 per minute on a page that has been
+// backgrounded for GetIntensiveWakeUpThrottlingGracePeriod().
//
// Intensive wake up throttling is enforced in addition to other throttling
// mechanisms:
@@ -200,18 +177,7 @@ const base::Feature kHighPriorityDatabaseTaskType{
// the managed policy override of the feature.
//
// Parameter name and default values, exposed for testing.
-constexpr int kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default =
- 60;
-constexpr const char*
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Name =
- "duration_between_wake_ups_seconds";
constexpr int kIntensiveWakeUpThrottling_GracePeriodSeconds_Default = 5 * 60;
-constexpr const char*
- kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Name =
- "can_intensively_throttle_low_nesting_level";
-constexpr const bool
- kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default =
- false;
// Exposed so that multiple tests can tinker with the policy override.
PLATFORM_EXPORT void
@@ -219,87 +185,9 @@ ClearIntensiveWakeUpThrottlingPolicyOverrideCacheForTesting();
// Determines if the feature is enabled, taking into account base::Feature
// settings and policy overrides.
PLATFORM_EXPORT bool IsIntensiveWakeUpThrottlingEnabled();
-// Duration between wake ups for the kIntensiveWakeUpThrottling feature.
-PLATFORM_EXPORT base::TimeDelta
-GetIntensiveWakeUpThrottlingDurationBetweenWakeUps();
// Grace period after hiding a page during which there is no intensive wake up
// throttling for the kIntensiveWakeUpThrottling feature.
PLATFORM_EXPORT base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod();
-// The duration for which intensive throttling should be inhibited for
-// same-origin frames when the page title or favicon is updated. 0 seconds means
-// that updating the title or favicon has no effect on intensive throttling.
-PLATFORM_EXPORT base::TimeDelta
-GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate();
-// Whether timers with a non-zero delay and a low nesting level can be
-// intensively throttled.
-PLATFORM_EXPORT bool CanIntensivelyThrottleLowNestingLevel();
-
-// Per-agent scheduling experiments.
-constexpr base::Feature kPerAgentSchedulingExperiments{
- "BlinkSchedulerPerAgentSchedulingExperiments",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Queues the per-agent scheduling experiment should affect.
-enum class PerAgentAffectedQueues {
- // Strategy only applies to non-main agent timer queues. These can be safely
- // disabled/deprioritized without causing any known issues.
- kTimerQueues,
- // Strategy applies to all non-main agent queues. This may cause some task
- // ordering issues.
- kAllQueues,
-};
-
-constexpr base::FeatureParam<PerAgentAffectedQueues>::Option
- kPerAgentQueuesOptions[] = {
- {PerAgentAffectedQueues::kTimerQueues, "timer-queues"},
- {PerAgentAffectedQueues::kAllQueues, "all-queues"}};
-
-constexpr base::FeatureParam<PerAgentAffectedQueues> kPerAgentQueues{
- &kPerAgentSchedulingExperiments, "queues",
- PerAgentAffectedQueues::kTimerQueues, &kPerAgentQueuesOptions};
-
-// Effect the per-agent scheduling strategy should have.
-enum class PerAgentSlowDownMethod {
- // Affected queues will be disabled.
- kDisable,
- // Affected queues will have their priority reduced to |kBestEffortPriority|.
- kBestEffort,
-};
-
-constexpr base::FeatureParam<PerAgentSlowDownMethod>::Option
- kPerAgentMethodOptions[] = {
- {PerAgentSlowDownMethod::kDisable, "disable"},
- {PerAgentSlowDownMethod::kBestEffort, "best-effort"}};
-
-constexpr base::FeatureParam<PerAgentSlowDownMethod> kPerAgentMethod{
- &kPerAgentSchedulingExperiments, "method", PerAgentSlowDownMethod::kDisable,
- &kPerAgentMethodOptions};
-
-// Delay to wait after the signal is reached, before "stopping" the strategy.
-constexpr base::FeatureParam<int> kPerAgentDelayMs{
- &kPerAgentSchedulingExperiments, "delay_ms", 0};
-
-// Signal the per-agent scheduling strategy should wait for.
-enum class PerAgentSignal {
- // Strategy will be active until all main frames reach First Meaningful Paint
- // (+delay, if set).
- kFirstMeaningfulPaint,
- // Strategy will be active until all main frames finish loading (+delay, if
- // set).
- kOnLoad,
- // Strategy will be active until the delay has passed since all main frames
- // were created (or navigated).
- kDelayOnly,
-};
-
-constexpr base::FeatureParam<PerAgentSignal>::Option kPerAgentSignalOptions[] =
- {{PerAgentSignal::kFirstMeaningfulPaint, "fmp"},
- {PerAgentSignal::kOnLoad, "onload"},
- {PerAgentSignal::kDelayOnly, "delay"}};
-
-constexpr base::FeatureParam<PerAgentSignal> kPerAgentSignal{
- &kPerAgentSchedulingExperiments, "signal",
- PerAgentSignal::kFirstMeaningfulPaint, &kPerAgentSignalOptions};
// If enabled, base::ThreadTaskRunnerHandle::Get() and
// base::SequencedTaskRunnerHandle::Get() returns the current active
@@ -313,8 +201,37 @@ const base::Feature kMbiCompositorTaskRunnerPerAgentSchedulingGroup{
"MbiCompositorTaskRunnerPerAgentSchedulingGroup",
base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kThrottleVisibleNotFocusedTimers{
- "ThrottleVisibleNotFocusedTimers", base::FEATURE_DISABLED_BY_DEFAULT};
+// If enabled, Javascript timers are throttled to 1 wake up per
+// GetForegroundTimersThrottledWakeUpInterval() on foreground pages.
+PLATFORM_EXPORT extern const base::Feature kThrottleForegroundTimers;
+PLATFORM_EXPORT base::TimeDelta GetForegroundTimersThrottledWakeUpInterval();
+
+// Deprioritizes JS timer tasks during a particular phase of page loading.
+PLATFORM_EXPORT extern const base::Feature
+ kDeprioritizeDOMTimersDuringPageLoading;
+
+// The phase in which we deprioritize JS timer tasks.
+enum class DeprioritizeDOMTimersPhase {
+ // Until the DOMContentLoaded event is fired.
+ kOnDOMContentLoaded,
+ // Until First Contentful Paint is reached.
+ kFirstContentfulPaint,
+ // Until the load event is fired.
+ kOnLoad,
+};
+
+PLATFORM_EXPORT extern const base::FeatureParam<
+ DeprioritizeDOMTimersPhase>::Option kDeprioritizeDOMTimersPhaseOptions[];
+
+PLATFORM_EXPORT extern const base::FeatureParam<DeprioritizeDOMTimersPhase>
+ kDeprioritizeDOMTimersPhase;
+
+// Killswitch for prioritizing cross-process postMessage forwarding.
+//
+// TODO(crbug.com/1212894): Remove after M95.
+const base::Feature kDisablePrioritizedPostMessageForwarding{
+ "DisablePrioritizedPostMessageForwarding",
+ base::FEATURE_DISABLED_BY_DEFAULT};
} // 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
index cdb59dea0f4..66ca41194df 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
@@ -100,7 +100,7 @@ IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState(
if (long_idle_period_duration >=
base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
*next_long_idle_period_delay_out = long_idle_period_duration;
- if (!idle_queue_->HasTaskToRunImmediately())
+ if (!idle_queue_->HasTaskToRunImmediatelyOrReadyDelayedTask())
return IdlePeriodState::kInLongIdlePeriodPaused;
if (long_idle_period_duration == max_long_idle_period_duration)
return IdlePeriodState::kInLongIdlePeriodWithMaxDeadline;
@@ -248,7 +248,7 @@ void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"UpdateLongIdlePeriodStateAfterIdleTask");
- if (!idle_queue_->HasTaskToRunImmediately()) {
+ if (!idle_queue_->HasTaskToRunImmediatelyOrReadyDelayedTask()) {
// If there are no more idle tasks then pause long idle period ticks until a
// new idle task is posted.
state_.UpdateState(IdlePeriodState::kInLongIdlePeriodPaused,
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
index 51c7593d95e..678417abcd2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
@@ -5,7 +5,6 @@
#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/task/task_observer.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -48,6 +47,8 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
class PLATFORM_EXPORT Delegate {
public:
Delegate();
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
virtual ~Delegate();
// If it's ok to enter a long idle period, return true. Otherwise return
@@ -69,9 +70,6 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
// 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.
@@ -97,6 +95,8 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
const char* idle_period_tracing_name,
base::TimeDelta required_quiescence_duration_before_long_idle_period,
scoped_refptr<base::sequence_manager::TaskQueue> idle_queue);
+ IdleHelper(const IdleHelper&) = delete;
+ IdleHelper& operator=(const IdleHelper&) = delete;
~IdleHelper() override;
// Prevents any further idle tasks from running.
@@ -166,6 +166,8 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
State(SchedulerHelper* helper,
Delegate* delegate,
const char* idle_period_tracing_name);
+ State(const State&) = delete;
+ State& operator=(const State&) = delete;
virtual ~State();
void UpdateState(IdlePeriodState new_state,
@@ -196,8 +198,6 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
bool running_idle_task_for_tracing_;
const char* idle_period_tracing_name_;
const char* last_sub_trace_event_name_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(State);
};
// The minimum duration of an idle period.
@@ -242,8 +242,6 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
base::WeakPtr<IdleHelper> weak_idle_helper_ptr_;
base::WeakPtrFactory<IdleHelper> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(IdleHelper);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
index 2017943ad50..16821873f5e 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task/sequence_manager/sequence_manager.h"
@@ -192,6 +191,8 @@ class BaseIdleHelperTest : public testing::Test {
base::TimeDelta::FromMicroseconds(5000));
}
+ BaseIdleHelperTest(const BaseIdleHelperTest&) = delete;
+ BaseIdleHelperTest& operator=(const BaseIdleHelperTest&) = delete;
~BaseIdleHelperTest() override = default;
void SetUp() override {
@@ -269,18 +270,15 @@ class BaseIdleHelperTest : public testing::Test {
scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
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(base::TimeDelta()) {}
+ IdleHelperTest(const IdleHelperTest&) = delete;
+ IdleHelperTest& operator=(const IdleHelperTest&) = delete;
~IdleHelperTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperTest);
};
TEST_F(IdleHelperTest, TestPostIdleTask) {
@@ -387,6 +385,10 @@ class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest {
public:
IdleHelperTestWithIdlePeriodObserver()
: BaseIdleHelperTest(base::TimeDelta()) {}
+ IdleHelperTestWithIdlePeriodObserver(
+ const IdleHelperTestWithIdlePeriodObserver&) = delete;
+ IdleHelperTestWithIdlePeriodObserver& operator=(
+ const IdleHelperTestWithIdlePeriodObserver&) = delete;
~IdleHelperTestWithIdlePeriodObserver() override = default;
@@ -403,9 +405,6 @@ class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest {
EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(cardinality);
EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(cardinality);
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperTestWithIdlePeriodObserver);
};
TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterButNotExitIdlePeriod) {
@@ -764,6 +763,10 @@ TEST_F(IdleHelperTest, CanExceedIdleDeadlineIfRequired) {
class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest {
public:
+ IdleHelperWithQuiescencePeriodTest(
+ const IdleHelperWithQuiescencePeriodTest&) = delete;
+ IdleHelperWithQuiescencePeriodTest& operator=(
+ const IdleHelperWithQuiescencePeriodTest&) = delete;
enum {
kQuiescenceDelayMs = 100,
kLongIdlePeriodMs = 50,
@@ -792,7 +795,6 @@ class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest {
}
private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperWithQuiescencePeriodTest);
};
class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
@@ -801,16 +803,17 @@ class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver()
: IdleHelperWithQuiescencePeriodTest() {}
+ IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver(
+ const IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver&) = delete;
+ IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver& operator=(
+ const IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver&) = delete;
+
~IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() override =
default;
void SetUp() override {
EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver);
};
TEST_F(IdleHelperWithQuiescencePeriodTest,
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
index 6b936e32dba..5494aff5008 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc
@@ -42,9 +42,6 @@ scheduling_metrics::ThreadType ConvertBlinkThreadType(ThreadType thread_type) {
case ThreadType::kRealtimeAudioWorkletThread:
case ThreadType::kSemiRealtimeAudioWorkletThread:
return scheduling_metrics::ThreadType::kRendererOtherBlinkThread;
- case ThreadType::kCount:
- NOTREACHED();
- return scheduling_metrics::ThreadType::kCount;
}
}
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
index 97f0bc31566..c6d89d0cde6 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
@@ -9,7 +9,6 @@
#include "components/scheduling_metrics/task_duration_metric_reporter.h"
#include "components/scheduling_metrics/thread_metrics.h"
#include "components/scheduling_metrics/total_duration_metric_reporter.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_type.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -39,6 +38,8 @@ class PLATFORM_EXPORT MetricsHelper {
public:
MetricsHelper(ThreadType thread_type, bool has_cpu_timing_for_each_task);
+ MetricsHelper(const MetricsHelper&) = delete;
+ MetricsHelper& operator=(const MetricsHelper&) = delete;
~MetricsHelper();
protected:
@@ -69,8 +70,6 @@ class PLATFORM_EXPORT MetricsHelper {
background_thread_task_duration_reporter_;
scheduling_metrics::TaskDurationMetricReporter<ThreadType>
background_thread_task_cpu_duration_reporter_;
-
- DISALLOW_COPY_AND_ASSIGN(MetricsHelper);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
index 1fdd4a2eefb..06d0e59e76d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_POLLABLE_THREAD_SAFE_FLAG_H_
#include "base/atomicops.h"
-#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -21,6 +20,8 @@ class PollableThreadSafeFlag {
public:
explicit PollableThreadSafeFlag(base::Lock* write_lock);
+ PollableThreadSafeFlag(const PollableThreadSafeFlag&) = delete;
+ PollableThreadSafeFlag& operator=(const PollableThreadSafeFlag&) = delete;
// Set the flag. May only be called if |write_lock| is held.
void SetWhileLocked(bool value);
@@ -31,8 +32,6 @@ class PollableThreadSafeFlag {
private:
base::subtle::Atomic32 flag_;
base::Lock* write_lock_; // Not owned.
-
- DISALLOW_COPY_AND_ASSIGN(PollableThreadSafeFlag);
};
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_POLLABLE_THREAD_SAFE_FLAG_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc
index dd7838db9da..bb6a96550a5 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc
@@ -13,6 +13,8 @@ namespace blink {
class TaskHandle::Runner : public WTF::ThreadSafeRefCounted<Runner> {
public:
explicit Runner(base::OnceClosure task) : task_(std::move(task)) {}
+ Runner(const Runner&) = delete;
+ Runner& operator=(const Runner&) = delete;
base::WeakPtr<Runner> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
@@ -50,8 +52,6 @@ class TaskHandle::Runner : public WTF::ThreadSafeRefCounted<Runner> {
private:
base::OnceClosure task_;
base::WeakPtrFactory<Runner> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(Runner);
};
} // 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 a020067758a..68acd4521dd 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
@@ -8,7 +8,6 @@
#include <stddef.h>
#include "base/logging.h"
-#include "base/macros.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/task/simple_task_executor.h"
#include "base/threading/thread_checker.h"
@@ -33,6 +32,8 @@ class PLATFORM_EXPORT SchedulerHelper
// object is destroyed.
explicit SchedulerHelper(
base::sequence_manager::SequenceManager* sequence_manager);
+ SchedulerHelper(const SchedulerHelper&) = delete;
+ SchedulerHelper& operator=(const SchedulerHelper&) = delete;
~SchedulerHelper() override;
// Must be invoked before running any task from the scheduler, on the thread
@@ -142,8 +143,6 @@ class PLATFORM_EXPORT SchedulerHelper
UkmTaskSampler ukm_task_sampler_;
absl::optional<base::SimpleTaskExecutor> simple_task_executor_;
-
- DISALLOW_COPY_AND_ASSIGN(SchedulerHelper);
};
} // namespace scheduler
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 bb6c5f7f8cd..ece7c549d2e 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
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/task/sequence_manager/lazy_now.h"
#include "base/task/sequence_manager/task_queue.h"
@@ -63,6 +62,8 @@ class SchedulerHelperTest : public testing::Test {
default_task_runner_ = scheduler_helper_->DefaultTaskRunner();
}
+ SchedulerHelperTest(const SchedulerHelperTest&) = delete;
+ SchedulerHelperTest& operator=(const SchedulerHelperTest&) = delete;
~SchedulerHelperTest() override = default;
void TearDown() override {
@@ -87,8 +88,6 @@ class SchedulerHelperTest : public testing::Test {
sequence_manager_;
std::unique_ptr<NonMainThreadSchedulerHelper> scheduler_helper_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(SchedulerHelperTest);
};
TEST_F(SchedulerHelperTest, TestPostDefaultTask) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
index c17e32eca01..6b7c95cfd32 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
@@ -41,7 +41,6 @@ bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) {
case Feature::kResumeEventListener:
case Feature::kContainsPlugins:
case Feature::kDocumentLoaded:
- case Feature::kRequestedGeolocationPermission:
case Feature::kRequestedNotificationsPermission:
case Feature::kRequestedMIDIPermission:
case Feature::kRequestedAudioCapturePermission:
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
index 6b806262b25..519c26d3bd4 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -27,6 +26,8 @@ namespace scheduler {
class SimpleThreadScheduler : public ThreadScheduler {
public:
SimpleThreadScheduler();
+ SimpleThreadScheduler(const SimpleThreadScheduler&) = delete;
+ SimpleThreadScheduler& operator=(const SimpleThreadScheduler&) = delete;
~SimpleThreadScheduler() override;
// Do nothing.
@@ -80,9 +81,6 @@ class SimpleThreadScheduler : public ThreadScheduler {
NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override;
void SetV8Isolate(v8::Isolate* isolate) override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SimpleThreadScheduler);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h b/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h
index c6e83f09478..72eb4bbf479 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
@@ -47,6 +46,8 @@ class SingleThreadIdleTaskRunner
class PLATFORM_EXPORT Delegate {
public:
Delegate();
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
virtual ~Delegate();
// Signals that an idle task has been posted. This will be called on the
@@ -63,9 +64,6 @@ class SingleThreadIdleTaskRunner
// Returns the current time.
virtual base::TimeTicks NowTicks() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Delegate);
};
// NOTE Category strings must have application lifetime (statics or
@@ -73,6 +71,9 @@ class SingleThreadIdleTaskRunner
SingleThreadIdleTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> idle_priority_task_runner,
Delegate* delegate);
+ SingleThreadIdleTaskRunner(const SingleThreadIdleTaskRunner&) = delete;
+ SingleThreadIdleTaskRunner& operator=(const SingleThreadIdleTaskRunner&) =
+ delete;
virtual void PostIdleTask(const base::Location& from_here,
IdleTask idle_task);
@@ -110,7 +111,6 @@ class SingleThreadIdleTaskRunner
base::trace_event::BlameContext* blame_context_; // Not owned.
base::WeakPtr<SingleThreadIdleTaskRunner> weak_scheduler_ptr_;
base::WeakPtrFactory<SingleThreadIdleTaskRunner> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(SingleThreadIdleTaskRunner);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
index 4be57405fb4..d09e0877911 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
@@ -8,7 +8,6 @@
#include "base/atomicops.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/synchronization/atomic_flag.h"
#include "base/threading/platform_thread.h"
@@ -32,6 +31,8 @@ class ThreadCPUThrottler::ThrottlingThread final
: public base::PlatformThread::Delegate {
public:
explicit ThrottlingThread(double rate);
+ ThrottlingThread(const ThrottlingThread&) = delete;
+ ThrottlingThread& operator=(const ThrottlingThread&) = delete;
~ThrottlingThread() override;
void SetThrottlingRate(double rate);
@@ -61,8 +62,6 @@ class ThreadCPUThrottler::ThrottlingThread final
base::PlatformThreadHandle throttled_thread_handle_;
base::PlatformThreadHandle throttling_thread_handle_;
base::AtomicFlag cancellation_flag_;
-
- DISALLOW_COPY_AND_ASSIGN(ThrottlingThread);
};
#ifdef USE_SIGNALS
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h
index 6bf13f31146..d68d4eb7d92 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THREAD_LOAD_TRACKER_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
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 f6fa54a39e9..5bc618b69b3 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
@@ -7,8 +7,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
-#include <random>
-
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h"
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc
index cd1298b02eb..95cb2e01531 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc
@@ -47,9 +47,6 @@ const char* GetNameForThreadType(ThreadType thread_type) {
return "Realtime AudioWorklet thread";
case ThreadType::kSemiRealtimeAudioWorkletThread:
return "Semi-Realtime AudioWorklet thread";
- case ThreadType::kCount:
- NOTREACHED();
- return nullptr;
}
return nullptr;
}
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 9c6a39003da..5c32a8d8fb4 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
@@ -7,7 +7,6 @@
#include <cstdint>
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
namespace blink {
@@ -15,43 +14,42 @@ namespace scheduler {
using base::sequence_manager::TaskQueue;
-BudgetPool::BudgetPool(const char* name,
- BudgetPoolController* budget_pool_controller)
- : name_(name),
- budget_pool_controller_(budget_pool_controller),
- is_enabled_(true) {}
+BudgetPool::BudgetPool(const char* name) : name_(name), is_enabled_(true) {}
-BudgetPool::~BudgetPool() = default;
+BudgetPool::~BudgetPool() {
+ for (auto* throttler : associated_throttlers_) {
+ throttler->RemoveBudgetPool(this);
+ }
+}
const char* BudgetPool::Name() const {
return name_;
}
-void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) {
- budget_pool_controller_->AddQueueToBudgetPool(queue, this);
- associated_task_queues_.insert(queue);
+void BudgetPool::AddThrottler(base::TimeTicks now,
+ TaskQueueThrottler* throttler) {
+ throttler->AddBudgetPool(this);
+ associated_throttlers_.insert(throttler);
if (!is_enabled_)
return;
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
+
+ throttler->UpdateQueueState(now);
}
-void BudgetPool::UnregisterQueue(TaskQueue* queue) {
- DissociateQueue(queue);
+void BudgetPool::UnregisterThrottler(TaskQueueThrottler* throttler) {
+ associated_throttlers_.erase(throttler);
}
-void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) {
- DissociateQueue(queue);
+void BudgetPool::RemoveThrottler(base::TimeTicks now,
+ TaskQueueThrottler* throttler) {
+ throttler->RemoveBudgetPool(this);
+ associated_throttlers_.erase(throttler);
if (!is_enabled_)
return;
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
-}
-
-void BudgetPool::DissociateQueue(TaskQueue* queue) {
- budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this);
- associated_task_queues_.erase(queue);
+ throttler->UpdateQueueState(now);
}
void BudgetPool::EnableThrottling(base::sequence_manager::LazyNow* lazy_now) {
@@ -61,7 +59,7 @@ void BudgetPool::EnableThrottling(base::sequence_manager::LazyNow* lazy_now) {
TRACE_EVENT0("renderer.scheduler", "BudgetPool_EnableThrottling");
- UpdateThrottlingStateForAllQueues(lazy_now->Now());
+ UpdateStateForAllThrottlers(lazy_now->Now());
}
void BudgetPool::DisableThrottling(base::sequence_manager::LazyNow* lazy_now) {
@@ -71,10 +69,7 @@ void BudgetPool::DisableThrottling(base::sequence_manager::LazyNow* lazy_now) {
TRACE_EVENT0("renderer.scheduler", "BudgetPool_DisableThrottling");
- for (TaskQueue* queue : associated_task_queues_) {
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(
- lazy_now->Now(), queue);
- }
+ UpdateStateForAllThrottlers(lazy_now->Now());
// TODO(altimin): We need to disable TimeBudgetQueues here or they will
// regenerate extra time budget when they are disabled.
@@ -85,14 +80,12 @@ bool BudgetPool::IsThrottlingEnabled() const {
}
void BudgetPool::Close() {
- DCHECK_EQ(0u, associated_task_queues_.size());
-
- budget_pool_controller_->UnregisterBudgetPool(this);
+ DCHECK_EQ(0u, associated_throttlers_.size());
}
-void BudgetPool::UpdateThrottlingStateForAllQueues(base::TimeTicks now) {
- for (TaskQueue* queue : associated_task_queues_)
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
+void BudgetPool::UpdateStateForAllThrottlers(base::TimeTicks now) {
+ for (TaskQueueThrottler* throttler : associated_throttlers_)
+ throttler->UpdateQueueState(now);
}
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h
index 5ed038f7a76..2a4ce8ace1f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h
@@ -6,20 +6,15 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/task/sequence_manager/lazy_now.h"
-#include "base/task/sequence_manager/task_queue.h"
#include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
namespace base {
-namespace sequence_manager {
-class TaskQueue;
-}
namespace trace_event {
class TracedValue;
}
@@ -28,7 +23,6 @@ class TracedValue;
namespace blink {
namespace scheduler {
-class BudgetPoolController;
enum class QueueBlockType;
// BudgetPool represents a group of task queues which share a limit
@@ -43,28 +37,21 @@ class PLATFORM_EXPORT BudgetPool {
const char* Name() const;
// Report task run time to the budget pool.
- virtual void RecordTaskRunTime(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks start_time,
+ virtual void RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time) = 0;
- // Returns the earliest time when the next pump can be scheduled to run
+ // Returns the earliest time when the next wake-up can be scheduled to run
// new tasks.
virtual base::TimeTicks GetNextAllowedRunTime(
base::TimeTicks desired_run_time) const = 0;
// Returns true if a task can run at the given time.
- virtual bool CanRunTasksAt(base::TimeTicks moment, bool is_wake_up) const = 0;
+ virtual bool CanRunTasksAt(base::TimeTicks moment) const = 0;
// Returns a point in time until which tasks are allowed to run.
// base::TimeTicks::Max() means that there are no known limits.
- virtual base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now,
- bool is_wake_up) const = 0;
-
- // Notifies budget pool that queue has work with desired run time.
- virtual void OnQueueNextWakeUpChanged(
- base::sequence_manager::TaskQueue* queue,
- base::TimeTicks now,
- base::TimeTicks desired_run_time) = 0;
+ virtual base::TimeTicks GetTimeTasksCanRunUntil(
+ base::TimeTicks now) const = 0;
// Invoked as part of a global wake up if any of the task queues associated
// with the budget pool has reached its next allowed run time. The next
@@ -79,27 +66,24 @@ class PLATFORM_EXPORT BudgetPool {
virtual void WriteIntoTrace(perfetto::TracedValue context,
base::TimeTicks now) const = 0;
- // Adds |queue| to given pool. If the pool restriction does not allow
- // a task to be run immediately and |queue| is throttled, |queue| becomes
- // disabled.
- void AddQueue(base::TimeTicks now, base::sequence_manager::TaskQueue* queue);
+ // Adds |throttler| to given pool and invokes
+ // TaskQueueThrottler::UpdateQueueState().
+ void AddThrottler(base::TimeTicks now, TaskQueueThrottler* throttler);
- // Removes |queue| from given pool. If it is throttled, it does not
- // become enabled immediately, but a wake-up is scheduled if needed.
- void RemoveQueue(base::TimeTicks now,
- base::sequence_manager::TaskQueue* queue);
+ // Removes |throttler| from given pool and invokes
+ // TaskQueueThrottler::UpdateQueueState().
+ void RemoveThrottler(base::TimeTicks now, TaskQueueThrottler* throttler);
- // Unlike RemoveQueue, does not schedule a new wake-up for the queue.
- void UnregisterQueue(base::sequence_manager::TaskQueue* queue);
+ // Unlike RemoveThrottler, does not update the queue's state.
+ void UnregisterThrottler(TaskQueueThrottler* throttler);
- // Enables this time budget pool. Queues from this pool will be
- // throttled based on their run time.
+ // Enables this budget pool, allowing it to enforce its policies on its
+ // queues.
void EnableThrottling(base::sequence_manager::LazyNow* now);
- // Disables with time budget pool. Queues from this pool will not be
- // throttled based on their run time. A call to |PumpThrottledTasks|
- // will be scheduled to enable this queues back again and respect
- // timer alignment. Internal budget level will not regenerate with time.
+ // Disables this budget pool, stopping it from enforcing its policies on its
+ // queues. UpdateQueueState() is invoked on all queues to update their wake up
+ // times and fences.
void DisableThrottling(base::sequence_manager::LazyNow* now);
bool IsThrottlingEnabled() const;
@@ -107,23 +91,18 @@ class PLATFORM_EXPORT BudgetPool {
// All queues should be removed before calling Close().
void Close();
- // Ensures that a pump is scheduled and that a fence is installed for all
+ // Ensures that a wake-up is scheduled and that a fence is installed for all
// queues in this pool, based on state of those queues and latest values from
// CanRunTasksAt/GetTimeTasksCanRunUntil/GetNextAllowedRunTime.
- void UpdateThrottlingStateForAllQueues(base::TimeTicks now);
+ void UpdateStateForAllThrottlers(base::TimeTicks now);
protected:
- BudgetPool(const char* name, BudgetPoolController* budget_pool_controller);
+ explicit BudgetPool(const char* name);
const char* name_; // NOT OWNED
- BudgetPoolController* budget_pool_controller_;
-
- HashSet<base::sequence_manager::TaskQueue*> associated_task_queues_;
+ HashSet<TaskQueueThrottler*> associated_throttlers_;
bool is_enabled_;
-
- private:
- void DissociateQueue(base::sequence_manager::TaskQueue* queue);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h
deleted file mode 100644
index 4115e97e5f3..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_CONTROLLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_CONTROLLER_H_
-
-#include "base/time/time.h"
-
-namespace blink {
-namespace scheduler {
-
-class BudgetPool;
-
-// Interface for BudgetPool to interact with TaskQueueThrottler.
-class PLATFORM_EXPORT BudgetPoolController {
- public:
- virtual ~BudgetPoolController() = default;
-
- // To be used by BudgetPool only, use BudgetPool::{Add,Remove}Queue
- // methods instead.
- virtual void AddQueueToBudgetPool(base::sequence_manager::TaskQueue* queue,
- BudgetPool* budget_pool) = 0;
- virtual void RemoveQueueFromBudgetPool(
- base::sequence_manager::TaskQueue* queue,
- BudgetPool* budget_pool) = 0;
-
- // Deletes the budget pool.
- virtual void UnregisterBudgetPool(BudgetPool* budget_pool) = 0;
-
- // Ensure that an appropriate type of the fence is installed and schedule
- // a pump for this queue when needed.
- virtual void UpdateQueueSchedulingLifecycleState(
- base::TimeTicks now,
- base::sequence_manager::TaskQueue* queue) = 0;
-
- // Returns true if the |queue| is throttled (i.e. added to TaskQueueThrottler
- // and throttling is not disabled).
- virtual bool IsThrottled(base::sequence_manager::TaskQueue* queue) const = 0;
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_CONTROLLER_H_"
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 8bbefcec551..876f309944e 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
@@ -9,7 +9,6 @@
#include <memory>
#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"
@@ -26,24 +25,16 @@ namespace scheduler {
class BudgetPoolTest : public testing::Test {
public:
BudgetPoolTest() = default;
+ BudgetPoolTest(const BudgetPoolTest&) = delete;
+ BudgetPoolTest& operator=(const BudgetPoolTest&) = delete;
~BudgetPoolTest() override = default;
void SetUp() override {
clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
null_task_runner_ = base::MakeRefCounted<base::NullTaskRunner>();
- scheduler_ = std::make_unique<MainThreadSchedulerImpl>(
- base::sequence_manager::SequenceManagerForTest::Create(
- nullptr, null_task_runner_, &clock_),
- absl::nullopt);
- task_queue_throttler_ = scheduler_->task_queue_throttler();
start_time_ = clock_.NowTicks();
}
- void TearDown() override {
- scheduler_->Shutdown();
- scheduler_.reset();
- }
-
base::TimeTicks MillisecondsAfterStart(int milliseconds) {
return start_time_ + base::TimeDelta::FromMilliseconds(milliseconds);
}
@@ -55,99 +46,58 @@ class BudgetPoolTest : public testing::Test {
protected:
base::SimpleTestTickClock clock_;
scoped_refptr<base::NullTaskRunner> null_task_runner_;
- std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
- TaskQueueThrottler* task_queue_throttler_; // NOT OWNED
+ TraceableVariableController tracing_controller_;
base::TimeTicks start_time_;
-
- DISALLOW_COPY_AND_ASSIGN(BudgetPoolTest);
};
TEST_F(BudgetPoolTest, CPUTimeBudgetPool) {
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, start_time_);
pool->SetTimeBudgetRecoveryRate(SecondsAfterStart(0), 0.1);
- EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0), false));
+ EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0)));
EXPECT_EQ(SecondsAfterStart(0),
pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
// Run an expensive task and make sure that we're throttled.
- pool->RecordTaskRunTime(nullptr, SecondsAfterStart(0),
- MillisecondsAfterStart(100));
+ pool->RecordTaskRunTime(SecondsAfterStart(0), MillisecondsAfterStart(100));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(500), false));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(500)));
EXPECT_EQ(MillisecondsAfterStart(1000),
pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(1000), false));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(1000)));
// Run a cheap task and make sure that it doesn't affect anything.
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2000), false));
- pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(2000),
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2000)));
+ pool->RecordTaskRunTime(MillisecondsAfterStart(2000),
MillisecondsAfterStart(2020));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2020), false));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2020)));
EXPECT_EQ(MillisecondsAfterStart(2020),
pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
-
- pool->Close();
-}
-
-TEST_F(BudgetPoolTest, CPUTimeBudgetPoolMinBudgetLevelToRun) {
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
-
- pool->SetMinBudgetLevelToRun(SecondsAfterStart(0),
- base::TimeDelta::FromMilliseconds(10));
- pool->SetTimeBudgetRecoveryRate(SecondsAfterStart(0), 0.1);
-
- EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0), false));
- EXPECT_EQ(SecondsAfterStart(0),
- pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
-
- pool->RecordTaskRunTime(nullptr, SecondsAfterStart(0),
- MillisecondsAfterStart(10));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(15), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(150), false));
- // We need to wait extra 100ms to get budget of 10ms.
- EXPECT_EQ(MillisecondsAfterStart(200),
- pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
-
- pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(200),
- MillisecondsAfterStart(205));
- // We can run when budget is non-negative even when it less than 10ms.
- EXPECT_EQ(MillisecondsAfterStart(205),
- pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
-
- pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(205),
- MillisecondsAfterStart(215));
- EXPECT_EQ(MillisecondsAfterStart(350),
- pool->GetNextAllowedRunTime(SecondsAfterStart(0)));
}
TEST_F(BudgetPoolTest, WakeUpBudgetPool) {
- WakeUpBudgetPool* pool =
- task_queue_throttler_->CreateWakeUpBudgetPool("test");
-
- scoped_refptr<base::sequence_manager::TaskQueue> queue =
- scheduler_->NewTaskQueueForTest();
+ std::unique_ptr<WakeUpBudgetPool> pool =
+ std::make_unique<WakeUpBudgetPool>("test");
pool->SetWakeUpInterval(base::TimeTicks(), base::TimeDelta::FromSeconds(10));
pool->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(10));
// Can't run tasks until a wake-up.
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(0)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(5)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(9)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11)));
pool->OnWakeUp(MillisecondsAfterStart(0));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0)));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5)));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11)));
// GetNextAllowedRunTime should return the desired time when in the
// wakeup window and return the next wakeup otherwise.
@@ -155,28 +105,27 @@ TEST_F(BudgetPoolTest, WakeUpBudgetPool) {
EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(10),
pool->GetNextAllowedRunTime(MillisecondsAfterStart(15)));
- pool->RecordTaskRunTime(queue.get(), MillisecondsAfterStart(5),
- MillisecondsAfterStart(7));
+ pool->RecordTaskRunTime(MillisecondsAfterStart(5), MillisecondsAfterStart(7));
// Make sure that nothing changes after a task inside wakeup window.
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0)));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5)));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11)));
EXPECT_EQ(start_time_, pool->GetNextAllowedRunTime(start_time_));
EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(10),
pool->GetNextAllowedRunTime(MillisecondsAfterStart(15)));
pool->OnWakeUp(MillisecondsAfterStart(12005));
- pool->RecordTaskRunTime(queue.get(), MillisecondsAfterStart(12005),
+ pool->RecordTaskRunTime(MillisecondsAfterStart(12005),
MillisecondsAfterStart(12007));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12005), false));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12007), false));
- EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12014), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12015), false));
- EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12016), false));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12005)));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12007)));
+ EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12014)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12015)));
+ EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12016)));
EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(20),
pool->GetNextAllowedRunTime(SecondsAfterStart(13)));
}
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 f1a3d4f20f8..1d5f1bc699e 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
@@ -17,10 +17,9 @@ using base::sequence_manager::TaskQueue;
CPUTimeBudgetPool::CPUTimeBudgetPool(
const char* name,
- BudgetPoolController* budget_pool_controller,
TraceableVariableController* tracing_controller,
base::TimeTicks now)
- : BudgetPool(name, budget_pool_controller),
+ : BudgetPool(name),
current_budget_level_(base::TimeDelta(),
"RendererScheduler.BackgroundBudgetMs",
tracing_controller,
@@ -50,13 +49,6 @@ void CPUTimeBudgetPool::SetMaxThrottlingDelay(
EnforceBudgetLevelRestrictions();
}
-void CPUTimeBudgetPool::SetMinBudgetLevelToRun(
- base::TimeTicks now,
- base::TimeDelta min_budget_level_to_run) {
- Advance(now);
- min_budget_level_to_run_ = min_budget_level_to_run;
-}
-
void CPUTimeBudgetPool::SetTimeBudgetRecoveryRate(base::TimeTicks now,
double cpu_percentage) {
Advance(now);
@@ -76,30 +68,38 @@ void CPUTimeBudgetPool::SetReportingCallback(
reporting_callback_ = reporting_callback;
}
-bool CPUTimeBudgetPool::CanRunTasksAt(base::TimeTicks moment,
- bool is_wake_up) const {
- return moment >= GetNextAllowedRunTime(moment);
+bool CPUTimeBudgetPool::CanRunTasksAt(base::TimeTicks moment) const {
+ if (!is_enabled_)
+ return true;
+ if (current_budget_level_->InMicroseconds() >= 0)
+ return true;
+ base::TimeDelta time_to_recover_budget =
+ -current_budget_level_ / cpu_percentage_;
+ if (moment - last_checkpoint_ >= time_to_recover_budget) {
+ return true;
+ }
+
+ return false;
}
base::TimeTicks CPUTimeBudgetPool::GetTimeTasksCanRunUntil(
- base::TimeTicks now,
- bool is_wake_up) const {
- if (CanRunTasksAt(now, is_wake_up))
+ base::TimeTicks now) const {
+ if (CanRunTasksAt(now))
return base::TimeTicks::Max();
return base::TimeTicks();
}
base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime(
base::TimeTicks desired_run_time) const {
- if (!is_enabled_ || current_budget_level_->InMicroseconds() >= 0)
+ if (!is_enabled_ || current_budget_level_->InMicroseconds() >= 0) {
return last_checkpoint_;
+ }
// Subtract because current_budget is negative.
- return last_checkpoint_ +
- (-current_budget_level_ + min_budget_level_to_run_) / cpu_percentage_;
+ return std::max(desired_run_time, last_checkpoint_ + (-current_budget_level_ /
+ cpu_percentage_));
}
-void CPUTimeBudgetPool::RecordTaskRunTime(TaskQueue* queue,
- base::TimeTicks start_time,
+void CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time) {
DCHECK_LE(start_time, end_time);
Advance(end_time);
@@ -115,14 +115,7 @@ void CPUTimeBudgetPool::RecordTaskRunTime(TaskQueue* queue,
}
if (current_budget_level_->InSecondsF() < 0)
- UpdateThrottlingStateForAllQueues(end_time);
-}
-
-void CPUTimeBudgetPool::OnQueueNextWakeUpChanged(
- TaskQueue* queue,
- base::TimeTicks now,
- base::TimeTicks desired_run_time) {
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
+ UpdateStateForAllThrottlers(end_time);
}
void CPUTimeBudgetPool::OnWakeUp(base::TimeTicks now) {}
@@ -137,8 +130,6 @@ void CPUTimeBudgetPool::WriteIntoTrace(perfetto::TracedValue context,
dict.Add("last_checkpoint_seconds_ago",
(now - last_checkpoint_).InSecondsF());
dict.Add("is_enabled", is_enabled_);
- dict.Add("min_budget_level_to_run_in_seconds",
- min_budget_level_to_run_.InSecondsF());
if (max_throttling_delay_) {
dict.Add("max_throttling_delay_in_seconds",
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h
index 35e6485de62..e9e6721570a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h
@@ -8,7 +8,6 @@
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
@@ -20,9 +19,10 @@ namespace scheduler {
class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool {
public:
CPUTimeBudgetPool(const char* name,
- BudgetPoolController* budget_pool_controller,
TraceableVariableController* tracing_controller,
base::TimeTicks now);
+ CPUTimeBudgetPool(const CPUTimeBudgetPool&) = delete;
+ CPUTimeBudgetPool& operator=(const CPUTimeBudgetPool&) = delete;
~CPUTimeBudgetPool() override;
@@ -39,21 +39,6 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool {
base::TimeTicks now,
absl::optional<base::TimeDelta> max_throttling_delay);
- // Set minimal budget level required to run a task. If budget pool was
- // exhausted, it needs to accumulate at least |min_budget_to_run| time units
- // to unblock and run tasks again. When unblocked, it still can run tasks
- // when budget is positive but less than this level until being blocked
- // until being blocked when budget reaches zero.
- // This is needed for integration with WakeUpBudgetPool to prevent a situation
- // when wake-up happened but time budget pool allows only one task to run at
- // the moment.
- // It is recommended to use the same value for this and WakeUpBudgetPool's
- // wake-up window length.
- // NOTE: This does not have an immediate effect and does not call
- // BudgetPoolController::UnblockQueue.
- void SetMinBudgetLevelToRun(base::TimeTicks now,
- base::TimeDelta min_budget_level_to_run);
-
// Throttle task queues from this time budget pool if tasks are running
// for more than |cpu_percentage| per cent of wall time.
// This function does not affect internal time budget level.
@@ -70,17 +55,12 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool {
base::RepeatingCallback<void(base::TimeDelta)> reporting_callback);
// BudgetPool implementation:
- void RecordTaskRunTime(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks start_time,
+ void RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time) final;
- bool CanRunTasksAt(base::TimeTicks moment, bool is_wake_up) const final;
- base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now,
- bool is_wake_up) const final;
+ bool CanRunTasksAt(base::TimeTicks moment) const final;
+ base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now) const final;
base::TimeTicks GetNextAllowedRunTime(
base::TimeTicks desired_run_time) const final;
- void OnQueueNextWakeUpChanged(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks now,
- base::TimeTicks desired_run_time) final;
void OnWakeUp(base::TimeTicks now) final;
void WriteIntoTrace(perfetto::TracedValue context,
base::TimeTicks) const final;
@@ -111,8 +91,6 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool {
// after desired run time + max throttling duration, but a guarantee
// that at least one task will be run every max_throttling_delay.
absl::optional<base::TimeDelta> max_throttling_delay_;
- // See CPUTimeBudgetPool::SetMinBudgetLevelToRun.
- base::TimeDelta min_budget_level_to_run_;
TraceableCounter<base::TimeDelta, TracingCategoryName::kInfo>
current_budget_level_;
@@ -120,8 +98,6 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool {
double cpu_percentage_;
base::RepeatingCallback<void(base::TimeDelta)> reporting_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(CPUTimeBudgetPool);
};
} // namespace scheduler
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 45ead45baf6..43c602d4649 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
@@ -13,10 +13,7 @@
#include "base/memory/ptr_util.h"
#include "base/time/tick_clock.h"
#include "third_party/abseil-cpp/absl/types/optional.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"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
@@ -25,380 +22,183 @@ namespace scheduler {
using base::sequence_manager::LazyNow;
using base::sequence_manager::TaskQueue;
-namespace {
-
-absl::optional<base::TimeTicks> NextTaskRunTime(LazyNow* lazy_now,
- TaskQueue* queue) {
- if (queue->HasTaskToRunImmediately())
- return lazy_now->Now();
- return queue->GetNextScheduledWakeUp();
-}
-
-} // namespace
-
TaskQueueThrottler::TaskQueueThrottler(
- ThreadSchedulerImpl* thread_scheduler,
- TraceableVariableController* tracing_controller)
- : control_task_runner_(thread_scheduler->ControlTaskRunner()),
- thread_scheduler_(thread_scheduler),
- tracing_controller_(tracing_controller),
- tick_clock_(thread_scheduler->GetTickClock()),
- time_domain_(new ThrottledTimeDomain()),
- allow_throttling_(true) {
- pump_throttled_tasks_closure_.Reset(base::BindRepeating(
- &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
- forward_immediate_work_callback_ =
- base::BindRepeating(&TaskQueueThrottler::OnQueueNextWakeUpChanged,
- weak_factory_.GetWeakPtr());
-
- thread_scheduler_->RegisterTimeDomain(time_domain_.get());
-}
+ base::sequence_manager::TaskQueue* task_queue,
+ const base::TickClock* tick_clock)
+ : task_queue_(task_queue), tick_clock_(tick_clock) {}
TaskQueueThrottler::~TaskQueueThrottler() {
- // It's possible for queues to be still throttled, so we need to tidy up
- // before unregistering the time domain.
- for (const TaskQueueMap::value_type& map_entry : queue_details_) {
- TaskQueue* task_queue = map_entry.key;
- if (IsThrottled(task_queue)) {
- task_queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain());
- task_queue->RemoveFence();
- }
- }
+ if (IsThrottled())
+ DisableThrottling();
- thread_scheduler_->UnregisterTimeDomain(time_domain_.get());
+ for (BudgetPool* budget_pool : budget_pools_) {
+ budget_pool->UnregisterThrottler(this);
+ }
}
-void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
- auto insert_result = queue_details_.insert(
- task_queue, std::make_unique<Metadata>(task_queue, this));
- if (!insert_result.stored_value->value->IncrementRefCount())
+void TaskQueueThrottler::IncreaseThrottleRefCount() {
+ if (throttling_ref_count_++ != 0)
return;
// Task queue is newly throttled.
TRACE_EVENT1("renderer.scheduler", "TaskQueueThrottler_TaskQueueThrottled",
- "task_queue", static_cast<void*>(task_queue));
+ "task_queue", static_cast<void*>(task_queue_));
- if (!allow_throttling_)
+ task_queue_->SetThrottler(this);
+ if (!task_queue_->IsQueueEnabled())
return;
- task_queue->SetTimeDomain(time_domain_.get());
- // This blocks any tasks from |task_queue| until PumpThrottledTasks() to
- // enforce task alignment.
- task_queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
-
- if (!task_queue->IsQueueEnabled())
- return;
-
- if (!task_queue->IsEmpty()) {
- LazyNow lazy_now(tick_clock_);
- OnQueueNextWakeUpChanged(task_queue,
- NextTaskRunTime(&lazy_now, task_queue).value());
- }
+ UpdateQueueState(tick_clock_->NowTicks());
}
-void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
- TaskQueueMap::iterator iter = queue_details_.find(task_queue);
-
- if (iter == queue_details_.end())
- return;
- if (!iter->value->DecrementRefCount())
+void TaskQueueThrottler::DecreaseThrottleRefCount() {
+ DCHECK_GT(throttling_ref_count_, 0U);
+ if (--throttling_ref_count_ != 0)
return;
TRACE_EVENT1("renderer.scheduler", "TaskQueueThrottler_TaskQueueUnthrottled",
- "task_queue", static_cast<void*>(task_queue));
-
- MaybeDeleteQueueMetadata(iter);
-
- if (!allow_throttling_)
- return;
-
- task_queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain());
- task_queue->RemoveFence();
-}
-
-bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const {
- if (!allow_throttling_)
- return false;
-
- auto find_it = queue_details_.find(task_queue);
- if (find_it == queue_details_.end())
- return false;
- return find_it->value->throttling_ref_count() > 0;
-}
-
-void TaskQueueThrottler::ShutdownTaskQueue(TaskQueue* task_queue) {
- auto find_it = queue_details_.find(task_queue);
- if (find_it == queue_details_.end())
- return;
-
- // Reset a time domain reference to a valid domain, otherwise it's possible
- // to get a stale reference when deleting queue.
- task_queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain());
- task_queue->RemoveFence();
-
- // Copy intended.
- auto budget_pools = find_it->value->budget_pools();
- for (BudgetPool* budget_pool : budget_pools) {
- budget_pool->UnregisterQueue(task_queue);
- }
-
- // Iterator may have been deleted by BudgetPool::RemoveQueue, so don't
- // use it here.
- queue_details_.erase(task_queue);
-
- // NOTE: Observer is automatically unregistered when unregistering task queue.
-}
-
-void TaskQueueThrottler::OnQueueNextWakeUpChanged(
- TaskQueue* queue,
- base::TimeTicks next_wake_up) {
- if (!control_task_runner_->RunsTasksInCurrentSequence()) {
- control_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(forward_immediate_work_callback_,
- base::RetainedRef(queue), next_wake_up));
- return;
- }
-
- TRACE_EVENT0("renderer.scheduler",
- "TaskQueueThrottler::OnQueueNextWakeUpChanged");
-
- // We don't expect this to get called for disabled queues, but we can't DCHECK
- // because of the above thread hop. Just bail out if the queue is disabled.
- if (!queue->IsQueueEnabled())
- return;
-
- base::TimeTicks now = tick_clock_->NowTicks();
- next_wake_up = std::max(now, next_wake_up);
-
- auto find_it = queue_details_.find(queue);
- if (find_it == queue_details_.end())
- return;
-
- for (BudgetPool* budget_pool : find_it->value->budget_pools()) {
- budget_pool->OnQueueNextWakeUpChanged(queue, now, next_wake_up);
- }
-
- // TODO(altimin): This probably can be removed —- budget pools should
- // schedule this.
- base::TimeTicks next_allowed_run_time =
- UpdateNextAllowedRunTime(queue, next_wake_up);
- MaybeSchedulePumpThrottledTasks(
- FROM_HERE, now, std::max(next_wake_up, next_allowed_run_time));
-}
-
-void TaskQueueThrottler::PumpThrottledTasks() {
- TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler::PumpThrottledTasks");
- pending_pump_throttled_tasks_runtime_.reset();
-
- LazyNow lazy_now(tick_clock_);
-
- // Collect BudgetPools for which at least one queue has reached its next
- // granted run time.
- HashSet<BudgetPool*> budget_pools_at_next_granted_run_time;
- for (const TaskQueueMap::value_type& map_entry : queue_details_) {
- const base::TimeTicks next_granted_run_time =
- map_entry.value->next_granted_run_time();
- if (next_granted_run_time <= lazy_now.Now()) {
- budget_pools_at_next_granted_run_time.ReserveCapacityForSize(
- map_entry.value->budget_pools().size());
- for (BudgetPool* budget_pool : map_entry.value->budget_pools())
- budget_pools_at_next_granted_run_time.insert(budget_pool);
+ "task_queue", static_cast<void*>(task_queue_));
+ DisableThrottling();
+}
+
+bool TaskQueueThrottler::IsThrottled() const {
+ return throttling_ref_count_ > 0;
+}
+
+absl::optional<base::sequence_manager::DelayedWakeUp>
+TaskQueueThrottler::GetNextAllowedWakeUpImpl(
+ LazyNow* lazy_now,
+ absl::optional<base::sequence_manager::DelayedWakeUp> next_wake_up,
+ bool has_ready_task) {
+ DCHECK(IsThrottled());
+ DCHECK(task_queue_->IsQueueEnabled());
+
+ if (has_ready_task) {
+ base::TimeTicks allowed_run_time = GetNextAllowedRunTime(lazy_now->Now());
+ // If |allowed_run_time| is null, immediate tasks can run immediately and
+ // they don't require a delayed wake up (a delayed wake up might be required
+ // for delayed tasks, see below). Otherwise, schedule a delayed wake up to
+ // update the fence in the future.
+ if (!allowed_run_time.is_null()) {
+ // WakeUpResolution::kLow is always used for throttled tasks since those
+ // tasks can tolerate having their execution being delayed.
+ return base::sequence_manager::DelayedWakeUp{
+ allowed_run_time, base::sequence_manager::WakeUpResolution::kLow};
}
}
+ if (!next_wake_up.has_value())
+ return absl::nullopt;
- // Notify BudgetPools for which at least one queue has reached its next
- // granted run time about the wake up.
- for (BudgetPool* budget_pool : budget_pools_at_next_granted_run_time)
- budget_pool->OnWakeUp(lazy_now.Now());
+ base::TimeTicks desired_run_time =
+ std::max(next_wake_up->time, lazy_now->Now());
+ base::TimeTicks allowed_run_time = GetNextAllowedRunTime(desired_run_time);
+ if (allowed_run_time.is_null())
+ allowed_run_time = desired_run_time;
- // Update throttling state for all queues.
- for (const TaskQueueMap::value_type& map_entry : queue_details_) {
- TaskQueue* task_queue = map_entry.key;
- UpdateQueueSchedulingLifecycleStateInternal(lazy_now.Now(), task_queue,
- true);
- }
+ return base::sequence_manager::DelayedWakeUp{
+ allowed_run_time, base::sequence_manager::WakeUpResolution::kLow};
}
-/* static */
-base::TimeTicks TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks unthrottled_runtime) {
- const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
- return unthrottled_runtime + one_second -
- ((unthrottled_runtime - base::TimeTicks()) % one_second);
-}
+void TaskQueueThrottler::OnHasImmediateTask() {
+ DCHECK(IsThrottled());
+ DCHECK(task_queue_->IsQueueEnabled());
-void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks(
- const base::Location& from_here,
- base::TimeTicks now,
- base::TimeTicks unaligned_runtime) {
- if (!allow_throttling_)
- return;
+ TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler::OnHasImmediateTask");
- // TODO(altimin): Consider removing alignment here.
- base::TimeTicks runtime =
- std::max(now, unaligned_runtime)
- .SnappedToNextTick(base::TimeTicks(),
- base::TimeDelta::FromSeconds(1));
- DCHECK_LE(now, runtime);
-
- // If there is a pending call to PumpThrottledTasks and it's sooner than
- // |runtime| then return.
- if (pending_pump_throttled_tasks_runtime_ &&
- runtime >= pending_pump_throttled_tasks_runtime_.value()) {
- return;
+ LazyNow lazy_now(tick_clock_);
+ if (CanRunTasksAt(lazy_now.Now())) {
+ UpdateFence(lazy_now.Now());
+ } else {
+ task_queue_->UpdateDelayedWakeUp(&lazy_now);
}
-
- pending_pump_throttled_tasks_runtime_ = runtime;
-
- pump_throttled_tasks_closure_.Cancel();
-
- base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now;
- TRACE_EVENT1("renderer.scheduler",
- "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks",
- "delay_till_next_pump_ms", delay.InMilliseconds());
- control_task_runner_->PostDelayedTask(
- from_here, pump_throttled_tasks_closure_.GetCallback(), delay);
}
-CPUTimeBudgetPool* TaskQueueThrottler::CreateCPUTimeBudgetPool(
- const char* name) {
- CPUTimeBudgetPool* time_budget_pool = new CPUTimeBudgetPool(
- name, this, tracing_controller_, tick_clock_->NowTicks());
- budget_pools_.Set(time_budget_pool, base::WrapUnique(time_budget_pool));
- return time_budget_pool;
-}
+absl::optional<base::sequence_manager::DelayedWakeUp>
+TaskQueueThrottler::GetNextAllowedWakeUp(
+ LazyNow* lazy_now,
+ absl::optional<base::sequence_manager::DelayedWakeUp> next_desired_wake_up,
+ bool has_ready_task) {
+ TRACE_EVENT0("renderer.scheduler",
+ "TaskQueueThrottler::OnNextDelayedWakeUpChanged");
-WakeUpBudgetPool* TaskQueueThrottler::CreateWakeUpBudgetPool(const char* name) {
- WakeUpBudgetPool* wake_up_budget_pool =
- new WakeUpBudgetPool(name, this, tick_clock_->NowTicks());
- budget_pools_.Set(wake_up_budget_pool, base::WrapUnique(wake_up_budget_pool));
- return wake_up_budget_pool;
+ return GetNextAllowedWakeUpImpl(lazy_now, next_desired_wake_up,
+ has_ready_task);
}
-void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
- base::TimeTicks start_time,
+void TaskQueueThrottler::OnTaskRunTimeReported(base::TimeTicks start_time,
base::TimeTicks end_time) {
- if (!IsThrottled(task_queue))
+ if (!IsThrottled())
return;
- auto find_it = queue_details_.find(task_queue);
- if (find_it == queue_details_.end())
- return;
-
- for (BudgetPool* budget_pool : find_it->value->budget_pools()) {
- budget_pool->RecordTaskRunTime(task_queue, start_time, end_time);
+ for (BudgetPool* budget_pool : budget_pools_) {
+ budget_pool->RecordTaskRunTime(start_time, end_time);
}
}
-void TaskQueueThrottler::UpdateQueueSchedulingLifecycleState(
- base::TimeTicks now,
- TaskQueue* queue) {
- UpdateQueueSchedulingLifecycleStateInternal(now, queue, false);
-}
-
-void TaskQueueThrottler::UpdateQueueSchedulingLifecycleStateInternal(
- base::TimeTicks now,
- TaskQueue* queue,
- bool is_wake_up) {
- // Clear the next granted run time, to ensure that the queue's BudgetPools
- // aren't incorrectly informed of a wake up at the next PumpThrottledTasks().
- // If necessary, an up-to-date next granted run time will be set below.
- auto find_it = queue_details_.find(queue);
- if (find_it != queue_details_.end())
- find_it->value->set_next_granted_run_time(base::TimeTicks::Max());
-
- if (!queue->IsQueueEnabled() || !IsThrottled(queue)) {
+void TaskQueueThrottler::UpdateQueueState(base::TimeTicks now) {
+ if (!task_queue_->IsQueueEnabled() || !IsThrottled())
return;
- }
-
LazyNow lazy_now(now);
-
- absl::optional<base::TimeTicks> next_desired_run_time =
- NextTaskRunTime(&lazy_now, queue);
-
- if (CanRunTasksAt(queue, now, is_wake_up)) {
- // Unblock queue if we can run tasks immediately.
- base::TimeTicks unblock_until =
- GetTimeTasksCanRunUntil(queue, now, is_wake_up);
- if (unblock_until.is_max()) {
- queue->RemoveFence();
- } else if (unblock_until > now) {
- queue->InsertFenceAt(unblock_until);
- } else {
- DCHECK_EQ(unblock_until, now);
- queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
+ if (CanRunTasksAt(now)) {
+ UpdateFence(now);
+ } else {
+ // Insert a fence of an appropriate type.
+ absl::optional<QueueBlockType> block_type = GetBlockType(now);
+ DCHECK(block_type);
+ switch (block_type.value()) {
+ case QueueBlockType::kAllTasks:
+ task_queue_->InsertFence(
+ TaskQueue::InsertFencePosition::kBeginningOfTime);
+ break;
+ case QueueBlockType::kNewTasksOnly:
+ if (!task_queue_->HasActiveFence()) {
+ // Insert a new non-fully blocking fence only when there is no fence
+ // already in order avoid undesired unblocking of old tasks.
+ task_queue_->InsertFence(TaskQueue::InsertFencePosition::kNow);
+ }
+ break;
}
-
- // Throttled time domain does not schedule wake-ups without explicitly being
- // told so. Schedule a wake up if there is a next desired run time in the
- // future, and tasks can run at that time.
- if (next_desired_run_time.has_value() &&
- next_desired_run_time.value() != now &&
- next_desired_run_time.value() < unblock_until) {
- time_domain_->SetNextTaskRunTime(next_desired_run_time.value());
- }
-
- absl::optional<base::TimeTicks> next_wake_up =
- queue->GetNextScheduledWakeUp();
- // TODO(altimin, crbug.com/813218): Find a testcase to repro freezes
- // mentioned in the bug.
- if (next_wake_up) {
- MaybeSchedulePumpThrottledTasks(
- FROM_HERE, now,
- UpdateNextAllowedRunTime(queue, next_wake_up.value()));
- }
-
- return;
+ TRACE_EVENT_INSTANT("renderer.scheduler",
+ "TaskQueueThrottler::InsertFence");
}
-
- if (!next_desired_run_time)
- return;
-
- const base::TimeTicks next_run_time =
- UpdateNextAllowedRunTime(queue, next_desired_run_time.value());
-
- // Insert a fence of an approriate type.
- absl::optional<QueueBlockType> block_type = GetQueueBlockType(now, queue);
- DCHECK(block_type);
-
- switch (block_type.value()) {
- case QueueBlockType::kAllTasks:
- queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
-
- {
- // Braces limit the scope for a declared variable. Does not compile
- // otherwise.
- TRACE_EVENT1(
- "renderer.scheduler",
- "TaskQueueThrottler::PumpThrottledTasks_ExpensiveTaskThrottled",
- "throttle_time_in_seconds",
- (next_run_time - next_desired_run_time.value()).InSecondsF());
- }
- break;
- case QueueBlockType::kNewTasksOnly:
- if (!queue->HasActiveFence()) {
- // Insert a new non-fully blocking fence only when there is no fence
- // already in order avoid undesired unblocking of old tasks.
- queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
- }
- break;
+ task_queue_->UpdateDelayedWakeUp(&lazy_now);
+}
+
+void TaskQueueThrottler::OnWakeUp(base::sequence_manager::LazyNow* lazy_now) {
+ DCHECK(IsThrottled());
+ for (BudgetPool* budget_pool : budget_pools_)
+ budget_pool->OnWakeUp(lazy_now->Now());
+
+ base::TimeTicks now = lazy_now->Now();
+ DCHECK(CanRunTasksAt(now));
+ UpdateFence(now);
+}
+
+void TaskQueueThrottler::UpdateFence(base::TimeTicks now) {
+ DCHECK(IsThrottled());
+ // Unblock queue if we can run tasks immediately.
+ base::TimeTicks unblock_until = GetTimeTasksCanRunUntil(now);
+ if (unblock_until.is_max()) {
+ task_queue_->RemoveFence();
+ } else if (unblock_until > now) {
+ task_queue_->InsertFenceAt(unblock_until);
+ } else {
+ DCHECK_EQ(unblock_until, now);
+ task_queue_->InsertFence(TaskQueue::InsertFencePosition::kNow);
}
-
- // Schedule a pump.
- MaybeSchedulePumpThrottledTasks(FROM_HERE, now, next_run_time);
}
-absl::optional<QueueBlockType> TaskQueueThrottler::GetQueueBlockType(
- base::TimeTicks now,
- TaskQueue* queue) {
- auto find_it = queue_details_.find(queue);
- if (find_it == queue_details_.end())
- return absl::nullopt;
+void TaskQueueThrottler::DisableThrottling() {
+ task_queue_->RemoveFence();
+ task_queue_->ResetThrottler();
+}
+absl::optional<QueueBlockType> TaskQueueThrottler::GetBlockType(
+ base::TimeTicks now) const {
bool has_new_tasks_only_block = false;
- for (BudgetPool* budget_pool : find_it->value->budget_pools()) {
- if (!budget_pool->CanRunTasksAt(now, false)) {
+ for (BudgetPool* budget_pool : budget_pools_) {
+ if (!budget_pool->CanRunTasksAt(now)) {
if (budget_pool->GetBlockType() == QueueBlockType::kAllTasks)
return QueueBlockType::kAllTasks;
DCHECK_EQ(budget_pool->GetBlockType(), QueueBlockType::kNewTasksOnly);
@@ -411,207 +211,54 @@ absl::optional<QueueBlockType> TaskQueueThrottler::GetQueueBlockType(
return absl::nullopt;
}
-void TaskQueueThrottler::WriteIntoTrace(perfetto::TracedValue context,
- base::TimeTicks now) const {
- auto dict = std::move(context).WriteDictionary();
- if (pending_pump_throttled_tasks_runtime_) {
- dict.Add(
- "next_throttled_tasks_pump_in_seconds",
- (pending_pump_throttled_tasks_runtime_.value() - now).InSecondsF());
- }
-
- dict.Add("allow_throttling", allow_throttling_);
-
- {
- auto time_budget_pools = dict.AddArray("time_budget_pools");
- for (const auto& budget_pool : budget_pools_) {
- budget_pool.key->WriteIntoTrace(time_budget_pools.AppendItem(), now);
- }
- }
-
- {
- auto queue_details_array = dict.AddArray("queue_details");
- for (const auto& queue_details : queue_details_) {
- auto details_dict = queue_details_array.AppendDictionary();
- details_dict.Add("queue_name", queue_details.key->GetName());
- details_dict.Add("metadata", queue_details.value);
- }
- }
+void TaskQueueThrottler::AddBudgetPool(BudgetPool* budget_pool) {
+ budget_pools_.insert(budget_pool);
}
-void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue,
- BudgetPool* budget_pool) {
- auto insert_result =
- queue_details_.insert(queue, std::make_unique<Metadata>(queue, this));
-
- Metadata* metadata = insert_result.stored_value->value.get();
-
- DCHECK(metadata->budget_pools().find(budget_pool) ==
- metadata->budget_pools().end());
-
- metadata->budget_pools().insert(budget_pool);
-}
-
-void TaskQueueThrottler::RemoveQueueFromBudgetPool(TaskQueue* queue,
- BudgetPool* budget_pool) {
- auto find_it = queue_details_.find(queue);
- DCHECK(find_it != queue_details_.end() &&
- find_it->value->budget_pools().find(budget_pool) !=
- find_it->value->budget_pools().end());
-
- find_it->value->budget_pools().erase(budget_pool);
-
- MaybeDeleteQueueMetadata(find_it);
-}
-
-void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) {
+void TaskQueueThrottler::RemoveBudgetPool(BudgetPool* budget_pool) {
budget_pools_.erase(budget_pool);
}
-base::TimeTicks TaskQueueThrottler::UpdateNextAllowedRunTime(
- TaskQueue* queue,
- base::TimeTicks desired_run_time) {
- base::TimeTicks next_run_time = desired_run_time;
-
- auto find_it = queue_details_.find(queue);
- if (find_it == queue_details_.end())
- return next_run_time;
-
- for (BudgetPool* budget_pool : find_it->value->budget_pools()) {
- next_run_time = std::max(
- next_run_time, budget_pool->GetNextAllowedRunTime(desired_run_time));
- }
-
- find_it->value->set_next_granted_run_time(next_run_time);
-
- return next_run_time;
-}
-
-bool TaskQueueThrottler::CanRunTasksAt(TaskQueue* queue,
- base::TimeTicks moment,
- bool is_wake_up) {
- auto find_it = queue_details_.find(queue);
- if (find_it == queue_details_.end())
- return true;
-
- for (BudgetPool* budget_pool : find_it->value->budget_pools()) {
- if (!budget_pool->CanRunTasksAt(moment, is_wake_up))
+bool TaskQueueThrottler::CanRunTasksAt(base::TimeTicks moment) {
+ for (BudgetPool* budget_pool : budget_pools_) {
+ if (!budget_pool->CanRunTasksAt(moment)) {
return false;
+ }
}
return true;
}
-base::TimeTicks TaskQueueThrottler::GetTimeTasksCanRunUntil(
- TaskQueue* queue,
- base::TimeTicks now,
- bool is_wake_up) const {
- // Start with no known limit for the time tasks can run until.
- base::TimeTicks result = base::TimeTicks::Max();
-
- auto find_it = queue_details_.find(queue);
- if (find_it == queue_details_.end())
- return result;
+base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(
+ base::TimeTicks desired_runtime) const {
+ // If |desired_runtime| isn't affected by any BudgetPool, TimeTicks() is
+ // returned.
+ base::TimeTicks result = base::TimeTicks();
- for (BudgetPool* budget_pool : find_it->value->budget_pools()) {
+ for (BudgetPool* budget_pool : budget_pools_) {
+ if (budget_pool->CanRunTasksAt(desired_runtime))
+ continue;
result =
- std::min(result, budget_pool->GetTimeTasksCanRunUntil(now, is_wake_up));
+ std::max(result, budget_pool->GetNextAllowedRunTime(desired_runtime));
}
-
return result;
}
-void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) {
- if (it->value->throttling_ref_count() == 0 &&
- it->value->budget_pools().IsEmpty()) {
- queue_details_.erase(it);
- }
-}
-
-void TaskQueueThrottler::DisableThrottling() {
- if (!allow_throttling_)
- return;
-
- allow_throttling_ = false;
-
- for (const auto& map_entry : queue_details_) {
- if (map_entry.value->throttling_ref_count() == 0)
- continue;
-
- TaskQueue* queue = map_entry.key;
-
- queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain());
- queue->RemoveFence();
- }
-
- pump_throttled_tasks_closure_.Cancel();
- pending_pump_throttled_tasks_runtime_ = absl::nullopt;
-
- TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler_DisableThrottling");
-}
-
-void TaskQueueThrottler::EnableThrottling() {
- if (allow_throttling_)
- return;
-
- allow_throttling_ = true;
-
- LazyNow lazy_now(tick_clock_);
-
- for (const auto& map_entry : queue_details_) {
- if (map_entry.value->throttling_ref_count() == 0)
- continue;
-
- TaskQueue* queue = map_entry.key;
-
- // Throttling is enabled and task queue should be blocked immediately
- // to enforce task alignment.
- queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
- queue->SetTimeDomain(time_domain_.get());
- UpdateQueueSchedulingLifecycleState(lazy_now.Now(), queue);
- }
-
- TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler_EnableThrottling");
-}
-
-TaskQueueThrottler::Metadata::Metadata(base::sequence_manager::TaskQueue* queue,
- TaskQueueThrottler* throttler)
- : queue_(queue), throttler_(throttler) {}
-
-TaskQueueThrottler::Metadata::~Metadata() {
- if (throttling_ref_count_ > 0)
- queue_->SetObserver(nullptr);
-}
-
-bool TaskQueueThrottler::Metadata::IncrementRefCount() {
- if (throttling_ref_count_++ == 0) {
- queue_->SetObserver(this);
- return true;
- }
- return false;
-}
+base::TimeTicks TaskQueueThrottler::GetTimeTasksCanRunUntil(
+ base::TimeTicks now) const {
+ // Start with no known limit for the time tasks can run until.
+ base::TimeTicks result = base::TimeTicks::Max();
-// Returns true if |throttling_ref_count_| is now zero.
-bool TaskQueueThrottler::Metadata::DecrementRefCount() {
- if (throttling_ref_count_ == 0)
- return false;
- if (--throttling_ref_count_ == 0) {
- queue_->SetObserver(nullptr);
- return true;
+ for (BudgetPool* budget_pool : budget_pools_) {
+ result = std::min(result, budget_pool->GetTimeTasksCanRunUntil(now));
}
- return false;
-}
-void TaskQueueThrottler::Metadata::OnQueueNextWakeUpChanged(
- base::TimeTicks wake_up) {
- throttler_->OnQueueNextWakeUpChanged(queue_, wake_up);
+ return result;
}
-void TaskQueueThrottler::Metadata::WriteIntoTrace(
- perfetto::TracedValue context) const {
+void TaskQueueThrottler::WriteIntoTrace(perfetto::TracedValue context) const {
auto dict = std::move(context).WriteDictionary();
dict.Add("throttling_ref_count", throttling_ref_count_);
- dict.Add("next_granted_run_time", next_granted_run_time_);
}
} // namespace scheduler
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 e2028aa577b..c56289aff1a 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
@@ -5,21 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_TASK_QUEUE_THROTTLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_TASK_QUEUE_THROTTLER_H_
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "base/task/sequence_manager/task_queue.h"
-#include "base/task/sequence_manager/time_domain.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.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/throttling/budget_pool.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
@@ -33,10 +24,6 @@ namespace blink {
namespace scheduler {
class BudgetPool;
-class ThreadSchedulerImpl;
-class ThrottledTimeDomain;
-class CPUTimeBudgetPool;
-class WakeUpBudgetPool;
// kNewTasksOnly prevents new tasks from running (old tasks can run normally),
// kAllTasks block queue completely.
@@ -46,201 +33,93 @@ class WakeUpBudgetPool;
// unblock some tasks.
enum class QueueBlockType { kAllTasks, kNewTasksOnly };
-// The job of the TaskQueueThrottler is to control when tasks posted on
-// throttled queues get run. The TaskQueueThrottler:
-// - runs throttled tasks once per second,
-// - controls time budget for task queues grouped in CPUTimeBudgetPools.
+// The job of the TaskQueueThrottler is to control when tasks posted on a
+// throttled queue get to run.
//
-// This is done by disabling throttled queues and running
-// a special "heart beat" function |PumpThrottledTasks| which when run
-// temporarily enables throttled queues and inserts a fence to ensure tasks
-// posted from a throttled task run next time the queue is pumped.
+// This is done by inserting a fence in the queue when it cannot run and
+// removing or updating the fence when the next allowed wake up time is reached.
//
-// Of course the TaskQueueThrottler isn't the only sub-system that wants to
-// enable or disable queues. E.g. ThreadSchedulerImpl also does this for
-// policy reasons. To prevent the systems from fighting, clients of
-// TaskQueueThrottler must use SetQueueEnabled rather than calling the function
-// directly on the queue.
+// TaskQueueThrottler assumes that it's the only system inserting fences in
+// its associated TaskQueue.
//
// There may be more than one system that wishes to throttle a queue (e.g.
// renderer suspension vs tab level suspension) so the TaskQueueThrottler keeps
-// a count of the number of systems that wish a queue to be throttled.
-// See IncreaseThrottleRefCount & DecreaseThrottleRefCount.
+// a count of the number of systems that wish the queue to be throttled. See
+// IncreaseThrottleRefCount & DecreaseThrottleRefCount.
//
// This class is main-thread only.
-class PLATFORM_EXPORT TaskQueueThrottler : public BudgetPoolController {
+class PLATFORM_EXPORT TaskQueueThrottler final
+ : public base::sequence_manager::TaskQueue::Throttler {
public:
- // We use tracing controller from ThreadSchedulerImpl because an instance
- // of this class is always its member, so has the same lifetime.
- TaskQueueThrottler(ThreadSchedulerImpl* thread_scheduler,
- TraceableVariableController* tracing_controller);
-
- ~TaskQueueThrottler() override;
-
- void OnQueueNextWakeUpChanged(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks wake_up);
-
- // BudgetPoolController implementation:
- void AddQueueToBudgetPool(base::sequence_manager::TaskQueue* queue,
- BudgetPool* budget_pool) override;
- void RemoveQueueFromBudgetPool(base::sequence_manager::TaskQueue* queue,
- BudgetPool* budget_pool) override;
- void UnregisterBudgetPool(BudgetPool* budget_pool) override;
- void UpdateQueueSchedulingLifecycleState(
- base::TimeTicks now,
- base::sequence_manager::TaskQueue* queue) override;
- bool IsThrottled(base::sequence_manager::TaskQueue* queue) const override;
+ TaskQueueThrottler(base::sequence_manager::TaskQueue* task_queue,
+ const base::TickClock* tick_clock);
+ TaskQueueThrottler(const TaskQueueThrottler&) = delete;
+ TaskQueueThrottler& operator=(const TaskQueueThrottler&) = delete;
+ ~TaskQueueThrottler();
+
+ // Updates the queue's next wake up and fence based on policies enforced
+ // by this TaskQueueThrottler's budget pools.
+ void UpdateQueueState(base::TimeTicks now);
+
+ // Returns true if the queue is throttled.
+ bool IsThrottled() const;
// Increments the throttled refcount and causes |task_queue| to be throttled
// if its not already throttled.
- void IncreaseThrottleRefCount(base::sequence_manager::TaskQueue* task_queue);
-
+ void IncreaseThrottleRefCount();
// If the refcouint is non-zero it's decremented. If the throttled refcount
// becomes zero then |task_queue| is unthrottled. If the refcount was already
// zero this function does nothing.
- void DecreaseThrottleRefCount(base::sequence_manager::TaskQueue* task_queue);
-
- // Removes |task_queue| from |queue_details| and from appropriate budget pool.
- void ShutdownTaskQueue(base::sequence_manager::TaskQueue* task_queue);
-
- // Disable throttling for all queues, this setting takes precedence over
- // all other throttling settings. Designed to be used when a global event
- // disabling throttling happens (e.g. audio is playing).
- void DisableThrottling();
-
- // Enable back global throttling.
- void EnableThrottling();
-
- const ThrottledTimeDomain* time_domain() const { return time_domain_.get(); }
-
- // TODO(altimin): Remove it.
- static base::TimeTicks AlignedThrottledRunTime(
- base::TimeTicks unthrottled_runtime);
-
- // Returned object is owned by |TaskQueueThrottler|.
- CPUTimeBudgetPool* CreateCPUTimeBudgetPool(const char* name);
- WakeUpBudgetPool* CreateWakeUpBudgetPool(const char* name);
+ void DecreaseThrottleRefCount();
// Accounts for given task for cpu-based throttling needs.
- void OnTaskRunTimeReported(base::sequence_manager::TaskQueue* task_queue,
- base::TimeTicks start_time,
+ void OnTaskRunTimeReported(base::TimeTicks start_time,
base::TimeTicks end_time);
- void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks now) const;
-
- base::WeakPtr<TaskQueueThrottler> AsWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
+ void WriteIntoTrace(perfetto::TracedValue context) const;
private:
- class Metadata : public base::sequence_manager::TaskQueue::Observer {
- public:
- Metadata(base::sequence_manager::TaskQueue* queue,
- TaskQueueThrottler* throttler);
-
- ~Metadata() override;
-
- // Returns true if |throttling_ref_count_| was zero.
- bool IncrementRefCount();
-
- // Returns true if |throttling_ref_count_| is now zero.
- bool DecrementRefCount();
-
- // TaskQueue::Observer implementation:
- void OnQueueNextWakeUpChanged(base::TimeTicks wake_up) override;
+ friend class BudgetPool;
- size_t throttling_ref_count() const { return throttling_ref_count_; }
+ absl::optional<QueueBlockType> GetBlockType(base::TimeTicks now) const;
- const HashSet<BudgetPool*>& budget_pools() const { return budget_pools_; }
+ // To be used by BudgetPool only, use BudgetPool::{Add,Remove}Queue
+ // methods instead.
+ void AddBudgetPool(BudgetPool* budget_pool);
+ void RemoveBudgetPool(BudgetPool* budget_pool);
- HashSet<BudgetPool*>& budget_pools() { return budget_pools_; }
-
- base::TimeTicks next_granted_run_time() const {
- return next_granted_run_time_;
- }
- void set_next_granted_run_time(base::TimeTicks next_granted_run_time) {
- next_granted_run_time_ = next_granted_run_time;
- }
-
- void WriteIntoTrace(perfetto::TracedValue context) const;
-
- private:
- base::sequence_manager::TaskQueue* const queue_;
- TaskQueueThrottler* const throttler_;
- size_t throttling_ref_count_ = 0;
- HashSet<BudgetPool*> budget_pools_;
-
- // The next granted run time for |queue_|. Is TimeTicks::Max() when there is
- // no next granted run time, for example when:
- // - The queue didn't request a wake up.
- // - The queue only has immediate tasks which are currently allowed to run.
- // - A wake up just happened and the next granted run time is about to be
- // re-evaluated.
- base::TimeTicks next_granted_run_time_ = base::TimeTicks::Max();
-
- DISALLOW_COPY_AND_ASSIGN(Metadata);
- };
-
- using TaskQueueMap =
- HashMap<base::sequence_manager::TaskQueue*, std::unique_ptr<Metadata>>;
-
- void PumpThrottledTasks();
-
- // Note |unthrottled_runtime| might be in the past. When this happens we
- // compute the delay to the next runtime based on now rather than
- // unthrottled_runtime.
- void MaybeSchedulePumpThrottledTasks(const base::Location& from_here,
- base::TimeTicks now,
- base::TimeTicks runtime);
-
- // Evaluate the next possible time when |queue| is allowed to run in
- // accordance with throttling policy. Returns it and stores it in |queue|'s
- // metadata.
- base::TimeTicks UpdateNextAllowedRunTime(
- base::sequence_manager::TaskQueue* queue,
- base::TimeTicks desired_run_time);
-
- bool CanRunTasksAt(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks moment,
- bool is_wake_up);
+ bool CanRunTasksAt(base::TimeTicks moment);
+ // Returns the next allowed runtime, given |desired_runtime| if it was
+ // affected by any BudgetPool, of TimeTicks() otherwise.
+ base::TimeTicks GetNextAllowedRunTime(base::TimeTicks desired_runtime) const;
// Returns the time until which tasks in |queue| can run. TimeTicks::Max()
// means that there are no known limits.
- base::TimeTicks GetTimeTasksCanRunUntil(
- base::sequence_manager::TaskQueue* queue,
- base::TimeTicks now,
- bool is_wake_up) const;
-
- void MaybeDeleteQueueMetadata(TaskQueueMap::iterator it);
+ base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now) const;
- void UpdateQueueSchedulingLifecycleStateInternal(
- base::TimeTicks now,
- base::sequence_manager::TaskQueue* queue,
- bool is_wake_up);
+ // See GetNextAllowedWakeUp().
+ absl::optional<base::sequence_manager::DelayedWakeUp>
+ GetNextAllowedWakeUpImpl(
+ base::sequence_manager::LazyNow* lazy_now,
+ absl::optional<base::sequence_manager::DelayedWakeUp> next_wake_up,
+ bool has_ready_task);
- absl::optional<QueueBlockType> GetQueueBlockType(
- base::TimeTicks now,
- base::sequence_manager::TaskQueue* queue);
+ // TaskQueue::Throttler implementation:
+ absl::optional<base::sequence_manager::DelayedWakeUp> GetNextAllowedWakeUp(
+ base::sequence_manager::LazyNow* lazy_now,
+ absl::optional<base::sequence_manager::DelayedWakeUp> next_wake_up,
+ bool has_ready_task) override;
+ void OnWakeUp(base::sequence_manager::LazyNow* lazy_now) override;
+ void OnHasImmediateTask() override;
- TaskQueueMap queue_details_;
- base::RepeatingCallback<void(base::sequence_manager::TaskQueue*,
- base::TimeTicks)>
- forward_immediate_work_callback_;
- scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
- ThreadSchedulerImpl* thread_scheduler_; // NOT OWNED
- TraceableVariableController* tracing_controller_; // NOT OWNED
- const base::TickClock* tick_clock_; // NOT OWNED
- std::unique_ptr<ThrottledTimeDomain> time_domain_;
+ void UpdateFence(base::TimeTicks now);
- CancelableClosureHolder pump_throttled_tasks_closure_;
- absl::optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_;
- bool allow_throttling_;
-
- HashMap<BudgetPool*, std::unique_ptr<BudgetPool>> budget_pools_;
-
- base::WeakPtrFactory<TaskQueueThrottler> weak_factory_{this};
+ void DisableThrottling();
- DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottler);
+ base::sequence_manager::TaskQueue* const task_queue_;
+ size_t throttling_ref_count_ = 0;
+ HashSet<BudgetPool*> budget_pools_;
+ const base::TickClock* tick_clock_;
};
} // namespace scheduler
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 ed9b0ab008d..0cad303e888 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
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
#include "base/test/bind.h"
@@ -18,9 +17,9 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.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"
#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/wtf/deque.h"
namespace blink {
@@ -35,16 +34,6 @@ 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::SequenceManager> manager,
- absl::optional<base::Time> initial_virtual_time)
- : MainThreadSchedulerImpl(std::move(manager), initial_virtual_time) {}
-};
-
void NopTask() {}
void AddOneTask(size_t* count) {
@@ -71,41 +60,65 @@ class TaskQueueThrottlerTest : public testing::Test {
public:
TaskQueueThrottlerTest()
: test_task_runner_(base::MakeRefCounted<TestMockTimeTaskRunner>()) {}
+ TaskQueueThrottlerTest(const TaskQueueThrottlerTest&) = delete;
+ TaskQueueThrottlerTest& operator=(const TaskQueueThrottlerTest&) = delete;
~TaskQueueThrottlerTest() override = default;
void SetUp() override {
// A null clock triggers some assertions.
test_task_runner_->AdvanceMockTickClock(
base::TimeDelta::FromMilliseconds(5));
+ start_time_ = test_task_runner_->NowTicks();
- scheduler_ = std::make_unique<MainThreadSchedulerImplForTest>(
- base::sequence_manager::SequenceManagerForTest::Create(
- nullptr, test_task_runner_, GetTickClock()),
- absl::nullopt);
- task_queue_throttler_ = scheduler_->task_queue_throttler();
+ sequence_manager_ = base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, GetTickClock());
wake_up_budget_pool_ =
- task_queue_throttler_->CreateWakeUpBudgetPool("Wake Up Budget Pool");
+ std::make_unique<WakeUpBudgetPool>("Wake Up Budget Pool");
wake_up_budget_pool_->SetWakeUpDuration(base::TimeDelta());
- timer_queue_ = scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
- wake_up_budget_pool_->AddQueue(base::TimeTicks(),
- timer_queue_->GetTaskQueueForTest());
- timer_task_runner_ = timer_queue_->GetTaskRunnerWithDefaultTaskType();
+ wake_up_budget_pool_->SetWakeUpInterval(base::TimeTicks(),
+ base::TimeDelta::FromSeconds(1));
+
+ timer_queue_ = CreateTaskQueue("Timer queue");
+ task_queue_throttler_ = CreateThrottlerForTaskQueue(timer_queue_.get());
+
+ wake_up_budget_pool_->AddThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
+ timer_task_runner_ = timer_queue_->task_runner();
}
void TearDown() override {
- wake_up_budget_pool_->RemoveQueue(test_task_runner_->NowTicks(),
- timer_queue_->GetTaskQueueForTest());
- wake_up_budget_pool_->Close();
- scheduler_->Shutdown();
- scheduler_.reset();
+ wake_up_budget_pool_->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
+ timer_queue_->ShutdownTaskQueue();
+ }
+
+ scoped_refptr<base::sequence_manager::TaskQueue> CreateTaskQueue(
+ const char* name) {
+ return sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec(name).SetDelayedFencesAllowed(
+ true));
+ }
+
+ std::unique_ptr<TaskQueueThrottler> CreateThrottlerForTaskQueue(
+ base::sequence_manager::TaskQueue* queue) {
+ auto throttler = std::make_unique<TaskQueueThrottler>(
+ queue, test_task_runner_->GetMockTickClock());
+ queue->SetOnTaskCompletedHandler(base::BindRepeating(
+ [](TaskQueueThrottler* throttler,
+ const base::sequence_manager::Task& task,
+ TaskQueue::TaskTiming* task_timing,
+ base::sequence_manager::LazyNow* lazy_now) {
+ task_timing->RecordTaskEnd(lazy_now);
+ throttler->OnTaskRunTimeReported(task_timing->start_time(),
+ task_timing->end_time());
+ },
+ base::Unretained(throttler.get())));
+ return throttler;
}
void ExpectThrottled(scoped_refptr<TaskQueue> timer_queue) {
size_t count = 0;
- timer_queue->task_runner()->PostDelayedTask(
+ timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&RunTenTimesTask, &count, timer_queue),
base::TimeDelta::FromMilliseconds(1));
@@ -119,7 +132,7 @@ class TaskQueueThrottlerTest : public testing::Test {
void ExpectUnthrottled(scoped_refptr<TaskQueue> timer_queue) {
size_t count = 0;
- timer_queue->task_runner()->PostDelayedTask(
+ timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&RunTenTimesTask, &count, timer_queue),
base::TimeDelta::FromMilliseconds(1));
@@ -140,27 +153,24 @@ class TaskQueueThrottlerTest : public testing::Test {
test_task_runner_->NowTicks());
}
- TaskQueue* GetTaskQueue(MainThreadTaskQueue* queue) {
- return queue->GetTaskQueueForTest();
- }
-
protected:
virtual const base::TickClock* GetTickClock() const {
return test_task_runner_->GetMockTickClock();
}
+ base::TimeTicks start_time_;
+
scoped_refptr<TestMockTimeTaskRunner> test_task_runner_;
- std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_;
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_;
// A queue that is subject to |wake_up_budget_pool_|.
- scoped_refptr<MainThreadTaskQueue> timer_queue_;
+ scoped_refptr<base::sequence_manager::TaskQueue> timer_queue_;
+ std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
- TaskQueueThrottler* task_queue_throttler_ = nullptr;
- WakeUpBudgetPool* wake_up_budget_pool_ = nullptr;
+ std::unique_ptr<WakeUpBudgetPool> wake_up_budget_pool_;
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerTest);
+ TraceableVariableController tracing_controller_;
};
// Advances mock clock every time we call NowTicks() from the scheduler.
@@ -191,6 +201,10 @@ class TaskQueueThrottlerWithAutoAdvancingTimeTest
public:
TaskQueueThrottlerWithAutoAdvancingTimeTest()
: proxy_clock_(test_task_runner_) {}
+ TaskQueueThrottlerWithAutoAdvancingTimeTest(
+ const TaskQueueThrottlerWithAutoAdvancingTimeTest&) = delete;
+ TaskQueueThrottlerWithAutoAdvancingTimeTest& operator=(
+ const TaskQueueThrottlerWithAutoAdvancingTimeTest&) = delete;
~TaskQueueThrottlerWithAutoAdvancingTimeTest() override = default;
void SetUp() override {
@@ -207,73 +221,12 @@ class TaskQueueThrottlerWithAutoAdvancingTimeTest
private:
AutoAdvancingProxyClock proxy_clock_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerWithAutoAdvancingTimeTest);
};
INSTANTIATE_TEST_SUITE_P(All,
TaskQueueThrottlerWithAutoAdvancingTimeTest,
testing::Bool());
-TEST_F(TaskQueueThrottlerTest, ThrottledTasksReportRealTime) {
- EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain()->Now(),
- test_task_runner_->NowTicks());
-
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain()->Now(),
- test_task_runner_->NowTicks());
-
- test_task_runner_->AdvanceMockTickClock(
- base::TimeDelta::FromMilliseconds(250));
- // Make sure the throttled time domain's Now() reports the same as the
- // underlying clock.
- EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain()->Now(),
- test_task_runner_->NowTicks());
-}
-
-TEST_F(TaskQueueThrottlerTest, AlignedThrottledRunTime) {
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.0)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.1)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.2)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.5)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.8)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.9)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(1.1)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(8.0)));
-
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0),
- TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(8.1)));
-}
-
namespace {
// Round up time to milliseconds to deal with autoadvancing time.
@@ -324,25 +277,21 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimerAlignment) {
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(8300.0));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
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(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(2),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(9)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TimerAlignment_Unthrottled) {
Vector<base::TimeTicks> run_times;
- base::TimeTicks start_time = test_task_runner_->NowTicks();
timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(200.0));
@@ -359,124 +308,49 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(8300.0));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ task_queue_throttler_->DecreaseThrottleRefCount();
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)),
- RoundTimeToMilliseconds(
- start_time + base::TimeDelta::FromMilliseconds(1200.0)),
- RoundTimeToMilliseconds(
- start_time + base::TimeDelta::FromMilliseconds(8300.0))));
+ ElementsAre(
+ RoundTimeToMilliseconds(start_time_ +
+ base::TimeDelta::FromMilliseconds(200.0)),
+ RoundTimeToMilliseconds(start_time_ +
+ base::TimeDelta::FromMilliseconds(800.0)),
+ RoundTimeToMilliseconds(start_time_ +
+ base::TimeDelta::FromMilliseconds(1200.0)),
+ RoundTimeToMilliseconds(start_time_ +
+ base::TimeDelta::FromMilliseconds(8300.0))));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, Refcount) {
- ExpectUnthrottled(GetTaskQueue(timer_queue_.get()));
-
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- ExpectThrottled(GetTaskQueue(timer_queue_.get()));
+ ExpectUnthrottled(timer_queue_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- ExpectThrottled(GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ ExpectThrottled(timer_queue_.get());
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- ExpectThrottled(GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ ExpectThrottled(timer_queue_.get());
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- ExpectUnthrottled(GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->DecreaseThrottleRefCount();
+ ExpectThrottled(timer_queue_.get());
- // Should be a NOP.
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- ExpectUnthrottled(GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->DecreaseThrottleRefCount();
+ ExpectUnthrottled(timer_queue_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- ExpectThrottled(GetTaskQueue(timer_queue_.get()));
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- ThrotlingAnEmptyQueueDoesNotPostPumpThrottledTasksLocked) {
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
-
- EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- OnTimeDomainHasImmediateWork_EnabledQueue) {
- task_queue_throttler_->OnQueueNextWakeUpChanged(
- GetTaskQueue(timer_queue_.get()), base::TimeTicks());
- // Check PostPumpThrottledTasksLocked was called.
- EXPECT_FALSE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- OnTimeDomainHasImmediateWork_DisabledQueue) {
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter();
- voter->SetVoteToEnable(false);
-
- task_queue_throttler_->OnQueueNextWakeUpChanged(
- GetTaskQueue(timer_queue_.get()), base::TimeTicks());
- // Check PostPumpThrottledTasksLocked was not called.
- EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- ThrottlingADisabledQueueDoesNotPostPumpThrottledTasks) {
- timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask));
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter();
- voter->SetVoteToEnable(false);
-
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
-
- // Enabling it should trigger a call to PostPumpThrottledTasksLocked.
- voter->SetVoteToEnable(true);
- EXPECT_FALSE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- ThrottlingADisabledQueueDoesNotPostPumpThrottledTasks_DelayedTask) {
- timer_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask),
- base::TimeDelta::FromMilliseconds(1));
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter();
- voter->SetVoteToEnable(false);
-
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
-
- // Enabling it should trigger a call to PostPumpThrottledTasksLocked.
- voter->SetVoteToEnable(true);
- EXPECT_FALSE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty());
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ ExpectThrottled(timer_queue_.get());
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForNonDelayedTask) {
Vector<base::TimeTicks> run_times;
// Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick.
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Posting a task should trigger the pump.
timer_task_runner_->PostTask(
@@ -492,8 +366,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForDelayedTask) {
Vector<base::TimeTicks> run_times;
// Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick.
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Posting a task should trigger the pump.
timer_task_runner_->PostDelayedTask(
@@ -508,8 +381,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForDelayedTask) {
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
SingleThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10));
timer_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask),
@@ -519,8 +391,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
SingleFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5));
timer_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask),
@@ -530,8 +401,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TwoFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
Vector<base::TimeTicks> run_times;
base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5));
@@ -560,8 +430,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TaskDelayIsBasedOnRealTime) {
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Post an initial task that should run at the first aligned time period.
timer_task_runner_->PostDelayedTask(
@@ -582,87 +451,32 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000.0)));
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TaskQueueDisabledTillPump) {
- size_t count = 0;
- timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&AddOneTask, &count));
-
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_TRUE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
-
- test_task_runner_->FastForwardUntilNoTasksRemain(); // Wait until the pump.
- EXPECT_EQ(1u, count); // The task got run.
+ EXPECT_THAT(run_times,
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
DoubleIncrementDoubleDecrement) {
- timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask));
-
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_TRUE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
+ EXPECT_FALSE(IsQueueBlocked(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ EXPECT_TRUE(IsQueueBlocked(timer_queue_.get()));
+ task_queue_throttler_->DecreaseThrottleRefCount();
+ task_queue_throttler_->DecreaseThrottleRefCount();
+ EXPECT_FALSE(IsQueueBlocked(timer_queue_.get()));
}
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- EnableVirtualTimeThenIncrement) {
- timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask));
-
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
- EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain(),
- scheduler_->GetVirtualTimeDomain());
-
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain(),
- scheduler_->GetVirtualTimeDomain());
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- IncrementThenEnableVirtualTime) {
- timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask));
-
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- EXPECT_TRUE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
-
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
- EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get())));
- EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain(),
- scheduler_->GetVirtualTimeDomain());
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) {
+TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) {
Vector<base::TimeTicks> run_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Submit two tasks. They should be aligned, and second one should be
// throttled.
@@ -677,12 +491,15 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) {
test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
+ // The 1st task runs when allowed by the WakeUpBudgetPool. The 2nd task
+ // runs when the CPU budget used by the 2nd task has recovered.
+ EXPECT_THAT(
+ run_times,
+ ElementsAre(TimeTicks() + base::TimeDelta::FromSeconds(1),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500)));
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
run_times.clear();
// Queue was removed from CPUTimeBudgetPool, only timer alignment should be
@@ -700,27 +517,24 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) {
EXPECT_THAT(
run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(4250)));
+ ElementsAre(TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + base::TimeDelta::FromMilliseconds(3250)));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- pool->Close();
+ task_queue_throttler_->DecreaseThrottleRefCount();
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EnableAndDisableCPUTimeBudgetPool) {
Vector<base::TimeTicks> run_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
EXPECT_TRUE(pool->IsThrottlingEnabled());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Post an expensive task. Pool is now throttled.
timer_task_runner_->PostDelayedTask(
@@ -763,30 +577,26 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(4000)));
+ EXPECT_THAT(run_times, ElementsAre(start_time_ +
+ base::TimeDelta::FromMilliseconds(3500)));
run_times.clear();
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->DecreaseThrottleRefCount();
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
- pool->Close();
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
}
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- ImmediateTasksTimeBudgetThrottling) {
+TEST_F(TaskQueueThrottlerTest, ImmediateTasksTimeBudgetThrottling) {
Vector<base::TimeTicks> run_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Submit two tasks. They should be aligned, and second one should be
// throttled.
@@ -799,12 +609,13 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
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(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500)));
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
run_times.clear();
// Queue was removed from CPUTimeBudgetPool, only timer alignment should be
@@ -820,63 +631,57 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EXPECT_THAT(
run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(4250)));
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(3250)));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- pool->Close();
+ task_queue_throttler_->DecreaseThrottleRefCount();
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TwoQueuesTimeBudgetThrottling) {
Vector<base::TimeTicks> run_times;
- scoped_refptr<MainThreadTaskQueue> second_queue = scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
+ scoped_refptr<base::sequence_manager::TaskQueue> second_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto second_queue_throttler = CreateThrottlerForTaskQueue(second_queue.get());
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(second_queue.get()));
- wake_up_budget_pool_->AddQueue(base::TimeTicks(),
- GetTaskQueue(second_queue.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
+ pool->AddThrottler(base::TimeTicks(), second_queue_throttler.get());
+ wake_up_budget_pool_->AddThrottler(base::TimeTicks(),
+ second_queue_throttler.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(second_queue.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ second_queue_throttler->IncreaseThrottleRefCount();
timer_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- second_queue->GetTaskRunnerWithDefaultTaskType()->PostTask(
+ second_queue->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
-
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(second_queue.get()));
+ EXPECT_THAT(
+ run_times,
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500)));
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(second_queue.get()));
- wake_up_budget_pool_->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(second_queue.get()));
+ task_queue_throttler_->DecreaseThrottleRefCount();
+ second_queue_throttler->DecreaseThrottleRefCount();
- pool->Close();
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ second_queue_throttler.get());
+ wake_up_budget_pool_->RemoveThrottler(test_task_runner_->NowTicks(),
+ second_queue_throttler.get());
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
@@ -884,15 +689,14 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
Vector<base::TimeTicks> run_times;
LazyNow lazy_now(test_task_runner_->GetMockTickClock());
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(lazy_now.Now(), 0.1);
pool->DisableThrottling(&lazy_now);
- pool->AddQueue(lazy_now.Now(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(lazy_now.Now(), task_queue_throttler_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -915,15 +719,15 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TimeBudgetThrottlingDoesNotAffectUnthrottledQueues) {
Vector<base::TimeTicks> run_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
LazyNow lazy_now(test_task_runner_->GetMockTickClock());
pool->DisableThrottling(&lazy_now);
- pool->AddQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -938,24 +742,23 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EXPECT_THAT(
run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(105),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(355)));
+ ElementsAre(start_time_ + base::TimeDelta::FromMilliseconds(100),
+ start_time_ + base::TimeDelta::FromMilliseconds(350)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, MaxThrottlingDelay) {
Vector<base::TimeTicks> run_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetMaxThrottlingDelay(base::TimeTicks(),
base::TimeDelta::FromMinutes(1));
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.001);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
for (int i = 0; i < 5; ++i) {
timer_task_runner_->PostDelayedTask(
@@ -968,32 +771,33 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, MaxThrottlingDelay) {
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)));
+ ElementsAre(
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(61250),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(121500),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(181750),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(242000)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EnableAndDisableThrottling) {
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(200));
- test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(295));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(300));
// Disable throttling - task should run immediately.
- task_queue_throttler_->DisableThrottling();
+ LazyNow lazy_now_1(test_task_runner_->GetMockTickClock());
+ wake_up_budget_pool_->DisableThrottling(&lazy_now_1);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(200));
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
+ EXPECT_THAT(run_times, ElementsAre(start_time_ +
base::TimeDelta::FromMilliseconds(300)));
run_times.clear();
@@ -1014,8 +818,8 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EXPECT_THAT(
run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(900),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1200)));
+ ElementsAre(start_time_ + base::TimeDelta::FromMilliseconds(900),
+ start_time_ + base::TimeDelta::FromMilliseconds(1200)));
run_times.clear();
// Schedule a task at 1500ms. It should be throttled because of enabled
@@ -1027,7 +831,8 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
// Throttling is enabled and new task should be aligned.
- task_queue_throttler_->EnableThrottling();
+ LazyNow lazy_now_2(test_task_runner_->GetMockTickClock());
+ wake_up_budget_pool_->EnableThrottling(&lazy_now_2);
test_task_runner_->FastForwardUntilNoTasksRemain();
@@ -1035,21 +840,20 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
base::TimeDelta::FromMilliseconds(2000)));
}
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, ReportThrottling) {
+TEST_F(TaskQueueThrottlerTest, ReportThrottling) {
Vector<base::TimeTicks> run_times;
Vector<base::TimeDelta> reported_throttling_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
pool->SetReportingCallback(
base::BindRepeating(&RecordThrottling, &reported_throttling_times));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
@@ -1065,35 +869,34 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, ReportThrottling) {
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() + base::TimeDelta::FromSeconds(1),
+ TimeTicks() + base::TimeDelta::FromSeconds(1),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500)));
EXPECT_THAT(reported_throttling_times,
- ElementsAre(base::TimeDelta::FromMilliseconds(1255),
- base::TimeDelta::FromMilliseconds(1755)));
+ ElementsAre((start_time_ - TimeTicks()) +
+ base::TimeDelta::FromMilliseconds(1250),
+ base::TimeDelta::FromMilliseconds(2250)));
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- pool->Close();
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
+ task_queue_throttler_->DecreaseThrottleRefCount();
}
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, GrantAdditionalBudget) {
+TEST_F(TaskQueueThrottlerTest, GrantAdditionalBudget) {
Vector<base::TimeTicks> run_times;
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
pool->GrantAdditionalBudget(base::TimeTicks(),
base::TimeDelta::FromMilliseconds(500));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Submit five tasks. First three will not be throttled because they have
// budget to run.
@@ -1108,76 +911,43 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, GrantAdditionalBudget) {
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)));
-
- pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ ElementsAre(TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + base::TimeDelta::FromMilliseconds(1250),
+ TimeTicks() + base::TimeDelta::FromMilliseconds(1500),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500),
+ start_time_ + base::TimeDelta::FromMilliseconds(5000)));
+
+ pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ task_queue_throttler_.get());
+ task_queue_throttler_->DecreaseThrottleRefCount();
pool->Close();
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- EnableAndDisableThrottlingAndTimeBudgets) {
- // This test checks that if time budget pool is enabled when throttling
- // is disabled, it does not throttle the queue.
- Vector<base::TimeTicks> run_times;
-
- task_queue_throttler_->DisableThrottling();
-
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
-
- LazyNow lazy_now_1(test_task_runner_->GetMockTickClock());
- pool->DisableThrottling(&lazy_now_1);
-
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
-
- test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(95));
-
- LazyNow lazy_now_2(test_task_runner_->GetMockTickClock());
- pool->EnableThrottling(&lazy_now_2);
-
- timer_task_runner_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
- base::TimeDelta::FromMilliseconds(200));
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(300)));
-}
-
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
- AddQueueToBudgetPoolWhenThrottlingDisabled) {
+ AddQueueThrottlerToBudgetPoolWhenThrottlingDisabled) {
// This test checks that a task queue is added to time budget pool
// when throttling is disabled, is does not throttle queue.
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->DisableThrottling();
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ LazyNow lazy_now_1(test_task_runner_->GetMockTickClock());
+ wake_up_budget_pool_->DisableThrottling(&lazy_now_1);
+ pool->DisableThrottling(&lazy_now_1);
+ task_queue_throttler_->IncreaseThrottleRefCount();
- test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(95));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(200));
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
+ EXPECT_THAT(run_times, ElementsAre(start_time_ +
base::TimeDelta::FromMilliseconds(300)));
}
@@ -1185,25 +955,26 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
DisabledQueueThenEnabledQueue) {
Vector<base::TimeTicks> run_times;
- scoped_refptr<MainThreadTaskQueue> second_queue = scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
+ scoped_refptr<base::sequence_manager::TaskQueue> second_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto second_queue_throttler = CreateThrottlerForTaskQueue(second_queue.get());
+ wake_up_budget_pool_->AddThrottler(base::TimeTicks(),
+ second_queue_throttler.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(second_queue.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ second_queue_throttler->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(100));
- second_queue->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask(
+ second_queue->task_runner()->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(200));
std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter();
+ timer_queue_->CreateQueueEnabledVoter();
voter->SetVoteToEnable(false);
test_task_runner_->AdvanceMockTickClock(
@@ -1226,45 +997,50 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
run_times,
ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000)));
+
+ wake_up_budget_pool_->RemoveThrottler(base::TimeTicks(),
+ second_queue_throttler.get());
}
-TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoBudgetPools) {
+TEST_F(TaskQueueThrottlerTest, TwoBudgetPools) {
Vector<base::TimeTicks> run_times;
- scoped_refptr<MainThreadTaskQueue> second_queue = scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
+ std::unique_ptr<CPUTimeBudgetPool> pool1 =
+ std::make_unique<CPUTimeBudgetPool>("test", &tracing_controller_,
+ test_task_runner_->NowTicks());
+ std::unique_ptr<CPUTimeBudgetPool> pool2 =
+ std::make_unique<CPUTimeBudgetPool>("test", &tracing_controller_,
+ test_task_runner_->NowTicks());
- wake_up_budget_pool_->AddQueue(base::TimeTicks(),
- GetTaskQueue(second_queue.get()));
+ scoped_refptr<base::sequence_manager::TaskQueue> second_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto second_queue_throttler = CreateThrottlerForTaskQueue(second_queue.get());
+
+ wake_up_budget_pool_->AddThrottler(base::TimeTicks(),
+ second_queue_throttler.get());
- CPUTimeBudgetPool* pool1 =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
pool1->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool1->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
- pool1->AddQueue(base::TimeTicks(), GetTaskQueue(second_queue.get()));
+ pool1->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
+ pool1->AddThrottler(base::TimeTicks(), second_queue_throttler.get());
- CPUTimeBudgetPool* pool2 =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
pool2->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.01);
- pool2->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool2->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(second_queue.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ second_queue_throttler->IncreaseThrottleRefCount();
timer_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- second_queue->GetTaskRunnerWithDefaultTaskType()->PostTask(
+ second_queue->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
timer_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- second_queue->GetTaskRunnerWithDefaultTaskType()->PostTask(
+ second_queue->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
@@ -1272,20 +1048,19 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoBudgetPools) {
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)));
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500),
+ start_time_ + base::TimeDelta::FromMilliseconds(5000),
+ start_time_ + base::TimeDelta::FromMilliseconds(25000)));
- wake_up_budget_pool_->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(second_queue.get()));
+ wake_up_budget_pool_->RemoveThrottler(test_task_runner_->NowTicks(),
+ second_queue_throttler.get());
}
namespace {
void RunChainedTask(Deque<base::TimeDelta> task_durations,
- scoped_refptr<MainThreadTaskQueue> queue,
+ scoped_refptr<TaskQueue> queue,
scoped_refptr<TestMockTimeTaskRunner> task_runner,
Vector<base::TimeTicks>* run_times,
base::TimeDelta delay) {
@@ -1298,7 +1073,7 @@ void RunChainedTask(Deque<base::TimeDelta> task_durations,
task_runner->AdvanceMockTickClock(task_durations.front());
task_durations.pop_front();
- queue->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask(
+ queue->task_runner()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&RunChainedTask, std::move(task_durations), queue,
task_runner, run_times, delay),
@@ -1312,8 +1087,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
base::TimeDelta::FromMilliseconds(10));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -1343,8 +1117,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
base::TimeDelta::FromMilliseconds(10));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -1377,8 +1150,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
base::TimeDelta::FromMilliseconds(10));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -1409,31 +1181,29 @@ TEST_F(TaskQueueThrottlerTest,
// of one-minute.
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_;
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_.get();
scoped_refptr<base::SingleThreadTaskRunner> one_minute_task_runner =
timer_task_runner_;
// Create another TaskQueue, throttled by another WakeUpBudgetPool with
// a wake-up interval of two minutes.
- WakeUpBudgetPool* two_minutes_pool =
- task_queue_throttler_->CreateWakeUpBudgetPool(
- "Two Minutes Interval Pool");
+ std::unique_ptr<WakeUpBudgetPool> two_minutes_pool =
+ std::make_unique<WakeUpBudgetPool>("Two Minutes Interval Pool");
two_minutes_pool->SetWakeUpDuration(base::TimeDelta());
two_minutes_pool->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(2));
- scoped_refptr<MainThreadTaskQueue> two_minutes_queue =
- scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
- two_minutes_pool->AddQueue(base::TimeTicks(),
- GetTaskQueue(two_minutes_queue.get()));
+ scoped_refptr<base::sequence_manager::TaskQueue> two_minutes_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto two_minutes_queue_throttler =
+ CreateThrottlerForTaskQueue(two_minutes_queue.get());
+ two_minutes_pool->AddThrottler(base::TimeTicks(),
+ two_minutes_queue_throttler.get());
scoped_refptr<base::SingleThreadTaskRunner> two_minutes_task_runner =
- two_minutes_queue->GetTaskRunnerWithDefaultTaskType();
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(two_minutes_queue.get()));
+ two_minutes_queue->task_runner();
+ two_minutes_queue_throttler->IncreaseThrottleRefCount();
// Post a task with a short delay to the first queue.
constexpr base::TimeDelta kShortDelay = base::TimeDelta::FromSeconds(1);
@@ -1475,39 +1245,36 @@ TEST_F(TaskQueueThrottlerTest,
EXPECT_EQ(two_minutes_pool->last_wake_up_for_testing(), absl::nullopt);
// Clean up.
- two_minutes_pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(two_minutes_queue.get()));
- two_minutes_pool->Close();
+ two_minutes_pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ two_minutes_queue_throttler.get());
}
TEST_F(TaskQueueThrottlerTest,
WakeUpBasedThrottling_MultiplePoolsWithDifferentIntervals) {
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_;
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_.get();
scoped_refptr<base::SingleThreadTaskRunner> one_minute_task_runner =
timer_task_runner_;
// Create another TaskQueue, throttled by another WakeUpBudgetPool.
- WakeUpBudgetPool* two_minutes_pool =
- task_queue_throttler_->CreateWakeUpBudgetPool(
- "Two Minutes Interval Pool");
+ std::unique_ptr<WakeUpBudgetPool> two_minutes_pool =
+ std::make_unique<WakeUpBudgetPool>("Two Minutes Interval Pool");
two_minutes_pool->SetWakeUpDuration(base::TimeDelta());
two_minutes_pool->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(2));
- scoped_refptr<MainThreadTaskQueue> two_minutes_queue =
- scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
- two_minutes_pool->AddQueue(base::TimeTicks(),
- GetTaskQueue(two_minutes_queue.get()));
+ scoped_refptr<base::sequence_manager::TaskQueue> two_minutes_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto two_minutes_queue_throttler =
+ CreateThrottlerForTaskQueue(two_minutes_queue.get());
+ two_minutes_pool->AddThrottler(base::TimeTicks(),
+ two_minutes_queue_throttler.get());
scoped_refptr<base::SingleThreadTaskRunner> two_minutes_task_runner =
- two_minutes_queue->GetTaskRunnerWithDefaultTaskType();
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(two_minutes_queue.get()));
+ two_minutes_queue->task_runner();
+ two_minutes_queue_throttler->IncreaseThrottleRefCount();
// Post tasks with a short delay to both queues.
constexpr base::TimeDelta kShortDelay = base::TimeDelta::FromSeconds(1);
@@ -1550,9 +1317,8 @@ TEST_F(TaskQueueThrottlerTest,
base::TimeTicks() + base::TimeDelta::FromMinutes(2));
// Clean up.
- two_minutes_pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(two_minutes_queue.get()));
- two_minutes_pool->Close();
+ two_minutes_pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ two_minutes_queue_throttler.get());
}
TEST_F(TaskQueueThrottlerTest,
@@ -1563,32 +1329,33 @@ TEST_F(TaskQueueThrottlerTest,
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp();
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_;
+ wake_up_budget_pool_->AllowLowerAlignmentIfNoRecentWakeUp(
+ base::TimeDelta::FromSeconds(1));
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_.get();
scoped_refptr<base::SingleThreadTaskRunner> one_minute_task_runner =
timer_task_runner_;
// Create another TaskQueue, throttled by another WakeUpBudgetPool.
- WakeUpBudgetPool* two_minutes_pool =
- task_queue_throttler_->CreateWakeUpBudgetPool(
- "Two Minutes Interval Pool");
+ std::unique_ptr<WakeUpBudgetPool> two_minutes_pool =
+ std::make_unique<WakeUpBudgetPool>("Two Minutes Interval Pool");
two_minutes_pool->SetWakeUpDuration(base::TimeDelta());
two_minutes_pool->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- two_minutes_pool->AllowUnalignedWakeUpIfNoRecentWakeUp();
- scoped_refptr<MainThreadTaskQueue> two_minutes_queue =
- scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
- two_minutes_pool->AddQueue(base::TimeTicks(),
- GetTaskQueue(two_minutes_queue.get()));
+ two_minutes_pool->AllowLowerAlignmentIfNoRecentWakeUp(
+ base::TimeDelta::FromSeconds(1));
+ scoped_refptr<base::sequence_manager::TaskQueue> two_minutes_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto two_minutes_queue_throttler =
+ CreateThrottlerForTaskQueue(two_minutes_queue.get());
+
+ two_minutes_pool->AddThrottler(base::TimeTicks(),
+ two_minutes_queue_throttler.get());
scoped_refptr<base::SingleThreadTaskRunner> two_minutes_task_runner =
- two_minutes_queue->GetTaskRunnerWithDefaultTaskType();
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(two_minutes_queue.get()));
+ two_minutes_queue->task_runner();
+ two_minutes_queue_throttler->IncreaseThrottleRefCount();
// Post tasks with short delays to both queues. They should run unaligned. The
// wake up in |one_minute_pool| should not be taken into account when
@@ -1660,9 +1427,8 @@ TEST_F(TaskQueueThrottlerTest,
start_time + base::TimeDelta::FromSeconds(606));
// Clean up.
- two_minutes_pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(two_minutes_queue.get()));
- two_minutes_pool->Close();
+ two_minutes_pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ two_minutes_queue_throttler.get());
}
TEST_F(TaskQueueThrottlerTest,
@@ -1674,31 +1440,32 @@ TEST_F(TaskQueueThrottlerTest,
// The 1st WakeUpBudgetPool doesn't allow unaligned wake ups.
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
- WakeUpBudgetPool* aligned_pool = wake_up_budget_pool_;
+ task_queue_throttler_->IncreaseThrottleRefCount();
+ WakeUpBudgetPool* aligned_pool = wake_up_budget_pool_.get();
scoped_refptr<base::SingleThreadTaskRunner> aligned_task_runner =
timer_task_runner_;
// Create another TaskQueue, throttled by another WakeUpBudgetPool. This 2nd
// WakeUpBudgetPool allows unaligned wake ups.
- WakeUpBudgetPool* unaligned_pool =
- task_queue_throttler_->CreateWakeUpBudgetPool(
- "Other Wake Up Budget Pool");
+ std::unique_ptr<WakeUpBudgetPool> unaligned_pool =
+ std::make_unique<WakeUpBudgetPool>("Other Wake Up Budget Pool");
unaligned_pool->SetWakeUpDuration(base::TimeDelta());
unaligned_pool->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- unaligned_pool->AllowUnalignedWakeUpIfNoRecentWakeUp();
- scoped_refptr<MainThreadTaskQueue> unaligned_queue = scheduler_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetCanBeThrottled(true));
- unaligned_pool->AddQueue(base::TimeTicks(),
- GetTaskQueue(unaligned_queue.get()));
+ unaligned_pool->AllowLowerAlignmentIfNoRecentWakeUp(
+ base::TimeDelta::FromSeconds(1));
+ scoped_refptr<base::sequence_manager::TaskQueue> unaligned_queue =
+ sequence_manager_->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("Second queue")
+ .SetDelayedFencesAllowed(true));
+ auto unaligned_queue_throttler =
+ CreateThrottlerForTaskQueue(unaligned_queue.get());
+
+ unaligned_pool->AddThrottler(base::TimeTicks(),
+ unaligned_queue_throttler.get());
scoped_refptr<base::SingleThreadTaskRunner> unaligned_task_runner =
- unaligned_queue->GetTaskRunnerWithDefaultTaskType();
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(unaligned_queue.get()));
+ unaligned_queue->task_runner();
+ unaligned_queue_throttler->IncreaseThrottleRefCount();
// Post tasks with short delays to both queues. The 1st task should run
// aligned, while the 2nd task should run unaligned.
@@ -1772,9 +1539,8 @@ TEST_F(TaskQueueThrottlerTest,
start_time + base::TimeDelta::FromSeconds(663));
// Clean up.
- unaligned_pool->RemoveQueue(test_task_runner_->NowTicks(),
- GetTaskQueue(unaligned_queue.get()));
- unaligned_pool->Close();
+ unaligned_pool->RemoveThrottler(test_task_runner_->NowTicks(),
+ unaligned_queue_throttler.get());
}
TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_EnableDisableThrottling) {
@@ -1786,8 +1552,7 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_EnableDisableThrottling) {
wake_up_budget_pool_->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(1));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -1829,7 +1594,7 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_EnableDisableThrottling) {
base::TimeTicks() + base::TimeDelta::FromSeconds(300)));
}
-TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_UnalignedWakeUps) {
+TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_LowAlignedWakeUps) {
// All throttled wake ups are aligned on 1-second intervals by
// TaskQueueThrottler, irrespective of BudgetPools. Start the test at a time
// aligned on a 1-minute interval, to simplify expectations.
@@ -1837,16 +1602,16 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_UnalignedWakeUps) {
const base::TimeTicks start_time = test_task_runner_->NowTicks();
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp();
+ wake_up_budget_pool_->AllowLowerAlignmentIfNoRecentWakeUp(
+ base::TimeDelta::FromSeconds(10));
timer_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
- base::TimeDelta::FromSeconds(90));
+ base::TimeDelta::FromSeconds(88));
test_task_runner_->FastForwardUntilNoTasksRemain();
@@ -1861,10 +1626,10 @@ TEST_F(TaskQueueThrottlerTest,
const base::TimeTicks initial_time = test_task_runner_->NowTicks();
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
base::TimeDelta::FromMinutes(1));
- wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp();
+ wake_up_budget_pool_->AllowLowerAlignmentIfNoRecentWakeUp(
+ base::TimeDelta::FromSeconds(1));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Task delay: Expected run time: Reason:
// 30 seconds 30 seconds >= 60 seconds after last wake up
// 80 seconds 90 seconds >= 60 seconds after last wake up
@@ -1903,8 +1668,7 @@ TEST_F(TaskQueueThrottlerTest,
TEST_F(TaskQueueThrottlerTest,
WakeUpBasedThrottling_IncreaseWakeUpIntervalBeforeWakeUp) {
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Post 2 delayed tasks when the wake up interval is 1 minute. The delay of
// the 2nd task is such that it won't be ready when the 1st task completes.
@@ -1931,8 +1695,7 @@ TEST_F(TaskQueueThrottlerTest,
TEST_F(TaskQueueThrottlerTest,
WakeUpBasedThrottling_DecreaseWakeUpIntervalBeforeWakeUp) {
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Post a delayed task when the wake up interval is 1 hour.
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
@@ -1958,8 +1721,7 @@ TEST_F(TaskQueueThrottlerTest,
base::TimeDelta::FromMilliseconds(10));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Post a 1st delayed task when the wake up interval is 1 minute.
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
@@ -1998,8 +1760,7 @@ TEST_F(TaskQueueThrottlerTest,
base::TimeDelta::FromMilliseconds(10));
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
// Post a 1st delayed task when the wake up interval is 1 hour.
wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(),
@@ -2038,16 +1799,15 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) {
wake_up_budget_pool_->SetWakeUpDuration(
base::TimeDelta::FromMilliseconds(10));
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
Deque<base::TimeDelta> task_durations =
MakeTaskDurations(9, base::TimeDelta());
@@ -2065,15 +1825,15 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) {
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)));
+ ElementsAre(TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500),
+ start_time_ + base::TimeDelta::FromMilliseconds(5000),
+ start_time_ + base::TimeDelta::FromMilliseconds(5000),
+ start_time_ + base::TimeDelta::FromMilliseconds(5000),
+ start_time_ + base::TimeDelta::FromMilliseconds(7500),
+ start_time_ + base::TimeDelta::FromMilliseconds(7500)));
}
TEST_F(TaskQueueThrottlerTest,
@@ -2081,11 +1841,11 @@ TEST_F(TaskQueueThrottlerTest,
wake_up_budget_pool_->SetWakeUpDuration(
base::TimeDelta::FromMilliseconds(10));
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
Vector<base::TimeTicks> run_times;
@@ -2101,12 +1861,10 @@ TEST_F(TaskQueueThrottlerTest,
base::TimeDelta::FromMilliseconds(300));
if (is_throttled) {
- task_queue_throttler_->DecreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->DecreaseThrottleRefCount();
is_throttled = false;
} else {
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
is_throttled = true;
}
@@ -2115,21 +1873,21 @@ TEST_F(TaskQueueThrottlerTest,
EXPECT_THAT(run_times,
ElementsAre(
- // Throttled due to cpu budget.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
+ // Throttled due to wake-up budget, then cpu budget.
+ TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
+ start_time_ + base::TimeDelta::FromMilliseconds(2500),
// Unthrottled.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3200),
- base::TimeTicks() + base::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),
+ start_time_ + base::TimeDelta::FromMilliseconds(2700),
+ start_time_ + base::TimeDelta::FromMilliseconds(2950),
+ // Throttled due to wake-up budget.
+ TimeTicks() + base::TimeDelta::FromMilliseconds(4000),
+ start_time_ + base::TimeDelta::FromMilliseconds(5000),
// Unthrottled.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6200),
- base::TimeTicks() + base::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)));
+ start_time_ + base::TimeDelta::FromMilliseconds(5200),
+ start_time_ + base::TimeDelta::FromMilliseconds(5450),
+ // Throttled due to wake-up budget, then cpu budget.
+ TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
+ start_time_ + base::TimeDelta::FromMilliseconds(7500)));
}
TEST_F(TaskQueueThrottlerTest,
@@ -2140,16 +1898,15 @@ TEST_F(TaskQueueThrottlerTest,
wake_up_budget_pool_->SetWakeUpDuration(
base::TimeDelta::FromMilliseconds(10));
- CPUTimeBudgetPool* pool =
- task_queue_throttler_->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>(
+ "test", &tracing_controller_, test_task_runner_->NowTicks());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.01);
- pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get()));
+ pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get());
Vector<base::TimeTicks> run_times;
- task_queue_throttler_->IncreaseThrottleRefCount(
- GetTaskQueue(timer_queue_.get()));
+ task_queue_throttler_->IncreaseThrottleRefCount();
timer_task_runner_->PostDelayedTask(
FROM_HERE,
@@ -2164,21 +1921,19 @@ TEST_F(TaskQueueThrottlerTest,
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() + base::TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + base::TimeDelta::FromMilliseconds(1007),
// Time budget is ~6ms and we can run one 7ms task.
- base::TimeTicks() + base::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),
- // Time budget is ~5ms and we can run one 7ms task.
- base::TimeTicks() + base::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),
- // Time budget is ~4ms and we can run one 7ms task.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(7000)));
+ TimeTicks() + base::TimeDelta::FromMilliseconds(2000),
+ // Time budget is ~0ms and we can run one 7ms tasks every
+ // 700ms.
+ start_time_ + base::TimeDelta::FromMilliseconds(2100),
+ start_time_ + base::TimeDelta::FromMilliseconds(2800),
+ start_time_ + base::TimeDelta::FromMilliseconds(3500),
+ start_time_ + base::TimeDelta::FromMilliseconds(4200),
+ start_time_ + base::TimeDelta::FromMilliseconds(4900),
+ start_time_ + base::TimeDelta::FromMilliseconds(5600),
+ start_time_ + base::TimeDelta::FromMilliseconds(6300)));
}
} // 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
deleted file mode 100644
index 69ac536ff0a..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc
+++ /dev/null
@@ -1,63 +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/common/throttling/throttled_time_domain.h"
-
-#include "base/task/sequence_manager/sequence_manager.h"
-
-namespace blink {
-namespace scheduler {
-
-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::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::SetNextTaskRunTime(base::TimeTicks run_time) {
- next_task_run_time_ = run_time;
-}
-
-absl::optional<base::TimeDelta> ThrottledTimeDomain::DelayTillNextTask(
- base::sequence_manager::LazyNow* lazy_now) {
- base::TimeTicks now = lazy_now->Now();
- if (next_task_run_time_ && next_task_run_time_ > now)
- return next_task_run_time_.value() - now;
-
- absl::optional<base::TimeTicks> next_run_time = NextScheduledRunTime();
- if (!next_run_time)
- return absl::nullopt;
-
- if (now >= next_run_time)
- return base::TimeDelta(); // Makes DoWork post an immediate continuation.
-
- // We assume the owner (i.e. TaskQueueThrottler) will manage wake-ups on our
- // behalf.
- return absl::nullopt;
-}
-
-bool ThrottledTimeDomain::MaybeFastForwardToNextTask(
- bool quit_when_idle_requested) {
- return false;
-}
-
-} // namespace scheduler
-} // namespace blink
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
deleted file mode 100644
index c8726b2c54a..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
+++ /dev/null
@@ -1,48 +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_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_
-
-#include "base/macros.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
-// relies on the owner (TaskQueueThrottler) to schedule wake-ups.
-class PLATFORM_EXPORT ThrottledTimeDomain
- : public base::sequence_manager::TimeDomain {
- public:
- ThrottledTimeDomain();
- ~ThrottledTimeDomain() override;
-
- void SetNextTaskRunTime(base::TimeTicks run_time);
-
- // TimeDomain implementation:
- base::sequence_manager::LazyNow CreateLazyNow() const override;
- base::TimeTicks Now() const override;
- absl::optional<base::TimeDelta> DelayTillNextTask(
- base::sequence_manager::LazyNow* lazy_now) override;
- bool MaybeFastForwardToNextTask(bool quit_when_idle_requested) override;
-
- 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
- // get reset, so it is valid only when in the future.
- absl::optional<base::TimeTicks> next_task_run_time_;
-
- DISALLOW_COPY_AND_ASSIGN(ThrottledTimeDomain);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_
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 f72ed30bd1b..1ffe3935bad 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
@@ -15,11 +15,8 @@ namespace scheduler {
using base::sequence_manager::TaskQueue;
-WakeUpBudgetPool::WakeUpBudgetPool(const char* name,
- BudgetPoolController* budget_pool_controller,
- base::TimeTicks now)
- : BudgetPool(name, budget_pool_controller),
- wake_up_interval_(base::TimeDelta::FromSeconds(1)) {}
+WakeUpBudgetPool::WakeUpBudgetPool(const char* name)
+ : BudgetPool(name), wake_up_interval_(base::TimeDelta::FromSeconds(1)) {}
WakeUpBudgetPool::~WakeUpBudgetPool() = default;
@@ -30,46 +27,36 @@ QueueBlockType WakeUpBudgetPool::GetBlockType() const {
void WakeUpBudgetPool::SetWakeUpInterval(base::TimeTicks now,
base::TimeDelta interval) {
wake_up_interval_ = interval;
- UpdateThrottlingStateForAllQueues(now);
+ UpdateStateForAllThrottlers(now);
}
void WakeUpBudgetPool::SetWakeUpDuration(base::TimeDelta duration) {
wake_up_duration_ = duration;
}
-void WakeUpBudgetPool::AllowUnalignedWakeUpIfNoRecentWakeUp() {
- allow_unaligned_wake_up_is_no_recent_wake_up_ = true;
+void WakeUpBudgetPool::AllowLowerAlignmentIfNoRecentWakeUp(
+ base::TimeDelta alignment) {
+ DCHECK_LE(alignment, wake_up_interval_);
+ wake_up_alignment_if_no_recent_wake_up_ = alignment;
}
-void WakeUpBudgetPool::RecordTaskRunTime(TaskQueue* queue,
- base::TimeTicks start_time,
- base::TimeTicks end_time) {
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(end_time, queue);
-}
-
-bool WakeUpBudgetPool::CanRunTasksAt(base::TimeTicks moment,
- bool is_wake_up) const {
+bool WakeUpBudgetPool::CanRunTasksAt(base::TimeTicks moment) const {
if (!is_enabled_)
return true;
if (!last_wake_up_)
return false;
- // |is_wake_up| flag means that we're in the beginning of the wake-up and
- // |OnWakeUp| has just been called. This is needed to support
- // backwards compatibility with old throttling mechanism (when
- // |wake_up_duration| is zero) and allow only one task to run.
- if (last_wake_up_ == moment && is_wake_up)
+ if (last_wake_up_ == moment)
return true;
+
return moment < last_wake_up_.value() + wake_up_duration_;
}
base::TimeTicks WakeUpBudgetPool::GetTimeTasksCanRunUntil(
- base::TimeTicks now,
- bool is_wake_up) const {
+ base::TimeTicks now) const {
if (!is_enabled_)
return base::TimeTicks::Max();
- if (!last_wake_up_)
- return base::TimeTicks();
- if (!CanRunTasksAt(now, is_wake_up))
+ DCHECK(last_wake_up_);
+ if (!CanRunTasksAt(now))
return base::TimeTicks();
return last_wake_up_.value() + wake_up_duration_;
}
@@ -86,39 +73,42 @@ base::TimeTicks WakeUpBudgetPool::GetNextAllowedRunTime(
return desired_run_time;
}
- // Do not throttle if there hasn't been a wake up in the last wake up
- // interval.
- if (allow_unaligned_wake_up_is_no_recent_wake_up_) {
- // If unaligned wake ups are allowed, the first wake up can happen at any
- // point.
- if (!last_wake_up_.has_value())
- return desired_run_time;
-
- // Unaligned wake ups can happen at most every |wake_up_interval_| after the
- // last wake up.
- auto next_unaligned_wake_up =
- std::max(desired_run_time, last_wake_up_.value() + wake_up_interval_);
-
- // Aligned wake ups happen every |wake_up_interval_|, snapped to the minute.
- auto next_aligned_wake_up = desired_run_time.SnappedToNextTick(
+ // If there hasn't been a wake up in the last wake up interval, the next wake
+ // up is simply aligned on |wake_up_alignment_if_no_recent_wake_up_|.
+ if (!wake_up_alignment_if_no_recent_wake_up_.is_zero()) {
+ // The first wake up is simply aligned on
+ // |wake_up_alignment_if_no_recent_wake_up_|.
+ if (!last_wake_up_.has_value()) {
+ return desired_run_time.SnappedToNextTick(
+ base::TimeTicks(), wake_up_alignment_if_no_recent_wake_up_);
+ }
+
+ // The next wake up is allowed at least |wake_up_interval_| after the last
+ // wake up.
+ auto next_aligned_wake_up =
+ std::max(desired_run_time, last_wake_up_.value() + wake_up_interval_)
+ .SnappedToNextTick(base::TimeTicks(),
+ wake_up_alignment_if_no_recent_wake_up_);
+
+ // A wake up is also allowed every |wake_up_interval_|.
+ auto next_wake_up_at_interval = desired_run_time.SnappedToNextTick(
base::TimeTicks(), wake_up_interval_);
// Pick the earliest of the two allowed run times.
- return std::min(next_unaligned_wake_up, next_aligned_wake_up);
+ return std::min(next_aligned_wake_up, next_wake_up_at_interval);
}
return desired_run_time.SnappedToNextTick(base::TimeTicks(),
wake_up_interval_);
}
-void WakeUpBudgetPool::OnQueueNextWakeUpChanged(
- TaskQueue* queue,
- base::TimeTicks now,
- base::TimeTicks desired_run_time) {
- budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
-}
-
void WakeUpBudgetPool::OnWakeUp(base::TimeTicks now) {
+ // To ensure that we correctly enforce wakeup limits for rapid successive
+ // wakeups, if |now| is within the last wakeup duration (e.g. |now| is 2ms
+ // after the last wakeup and |wake_up_duration_| is 3ms), this isn't counted
+ // as a new wakeup.
+ if (last_wake_up_ && now < last_wake_up_.value() + wake_up_duration_)
+ return;
last_wake_up_ = now;
}
@@ -129,12 +119,14 @@ void WakeUpBudgetPool::WriteIntoTrace(perfetto::TracedValue context,
dict.Add("name", name_);
dict.Add("wake_up_interval_in_seconds", wake_up_interval_.InSecondsF());
dict.Add("wake_up_duration_in_seconds", wake_up_duration_.InSecondsF());
+ dict.Add("wake_up_alignment_if_no_recent_wake_up_in_seconds",
+ wake_up_alignment_if_no_recent_wake_up_.InSecondsF());
if (last_wake_up_) {
dict.Add("last_wake_up_seconds_ago",
(now - last_wake_up_.value()).InSecondsF());
}
dict.Add("is_enabled", is_enabled_);
- dict.Add("task_queues", associated_task_queues_);
+ dict.Add("throttlers", associated_throttlers_);
}
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h
index 96d0952837f..fd02605fce4 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h
@@ -7,7 +7,6 @@
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace blink {
@@ -17,9 +16,9 @@ namespace scheduler {
// limited time at regular intervals.
class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool {
public:
- WakeUpBudgetPool(const char* name,
- BudgetPoolController* budget_pool_controller,
- base::TimeTicks now);
+ explicit WakeUpBudgetPool(const char* name);
+ WakeUpBudgetPool(const WakeUpBudgetPool&) = delete;
+ WakeUpBudgetPool& operator=(const WakeUpBudgetPool&) = delete;
~WakeUpBudgetPool() override;
// Sets the interval between wake ups. This can be invoked at any time. If a
@@ -31,25 +30,21 @@ class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool {
// should be called only during initialization of a WakeUpBudgetPool.
void SetWakeUpDuration(base::TimeDelta duration);
- // If called, the budget pool allows an unaligned wake up when there hasn't
- // been a wake up in the last |wake_up_interval_|.
+ // Sets a lower wake up alignment. If non-zero, the budget pool will ignore
+ // the |wake_up_interval_| and allow a wake up aligned on |alignment| if there
+ // hasn't been a wake up in the last |wake_up_interval_|.
//
// This does not have an immediate effect and should be called only during
// initialization of a WakeUpBudgetPool.
- void AllowUnalignedWakeUpIfNoRecentWakeUp();
+ void AllowLowerAlignmentIfNoRecentWakeUp(base::TimeDelta alignment);
// BudgetPool implementation:
- void RecordTaskRunTime(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks start_time,
- base::TimeTicks end_time) final;
- bool CanRunTasksAt(base::TimeTicks moment, bool is_wake_up) const final;
- base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now,
- bool is_wake_up) const final;
+ void RecordTaskRunTime(base::TimeTicks start_time,
+ base::TimeTicks end_time) final {}
+ bool CanRunTasksAt(base::TimeTicks moment) const final;
+ base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now) const final;
base::TimeTicks GetNextAllowedRunTime(
base::TimeTicks desired_run_time) const final;
- void OnQueueNextWakeUpChanged(base::sequence_manager::TaskQueue* queue,
- base::TimeTicks now,
- base::TimeTicks desired_run_time) final;
void OnWakeUp(base::TimeTicks now) final;
void WriteIntoTrace(perfetto::TracedValue context,
base::TimeTicks now) const final;
@@ -64,12 +59,9 @@ class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool {
private:
base::TimeDelta wake_up_interval_;
base::TimeDelta wake_up_duration_;
-
- bool allow_unaligned_wake_up_is_no_recent_wake_up_ = false;
+ base::TimeDelta wake_up_alignment_if_no_recent_wake_up_;
absl::optional<base::TimeTicks> last_wake_up_;
-
- DISALLOW_COPY_AND_ASSIGN(WakeUpBudgetPool);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
index 95945d7ee8a..9d1afac1aad 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
@@ -9,7 +9,6 @@
#include <unordered_set>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/typed_macros.h"
@@ -99,6 +98,8 @@ class StateTracer {
explicit StateTracer(const char* name) : name_(name), slice_is_open_(false) {
internal::ValidateTracingCategory(category);
}
+ StateTracer(const StateTracer&) = delete;
+ StateTracer& operator=(const StateTracer&) = delete;
~StateTracer() {
if (slice_is_open_)
@@ -145,8 +146,6 @@ class StateTracer {
// We have to track whether slice is open to avoid confusion since assignment,
// "absent" state and OnTraceLogEnabled can happen anytime.
bool slice_is_open_;
-
- DISALLOW_COPY_AND_ASSIGN(StateTracer);
};
// TODO(kraynov): Rename to something less generic and reflecting
@@ -169,6 +168,8 @@ class TraceableState : public TraceableVariable, private StateTracer<category> {
Trace();
}
+ TraceableState(const TraceableState&) = delete;
+
~TraceableState() override = default;
TraceableState& operator=(const T& value) {
@@ -222,8 +223,6 @@ class TraceableState : public TraceableVariable, private StateTracer<category> {
const ConverterFuncPtr converter_;
T state_;
-
- DISALLOW_COPY(TraceableState);
};
template <const char* category, typename TypedValue>
@@ -370,6 +369,8 @@ class TraceableCounter : public TraceableVariable {
return static_cast<double>(value);
}) {}
+ TraceableCounter(const TraceableCounter&) = delete;
+
TraceableCounter& operator=(const T& value) {
value_ = value;
Trace();
@@ -407,7 +408,6 @@ class TraceableCounter : public TraceableVariable {
const ConverterFuncPtr converter_;
T value_;
- DISALLOW_COPY(TraceableCounter);
};
// Add operators when it's needed.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc
index 7e3fc68ee3b..fc298f38687 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc
@@ -12,7 +12,9 @@ namespace scheduler {
UkmTaskSampler::UkmTaskSampler(double thread_time_sampling_rate,
double ukm_task_sampling_rate)
: thread_time_sampling_rate_(clampTo(thread_time_sampling_rate, 0.0, 1.0)),
- ukm_task_sampling_rate_(clampTo(ukm_task_sampling_rate, 0.0, 1.0)) {}
+ ukm_task_sampling_rate_(clampTo(ukm_task_sampling_rate, 0.0, 1.0)) {
+ random_generator_.Seed();
+}
double UkmTaskSampler::GetConditionalSamplingProbability(bool has_thread_time) {
if (thread_time_sampling_rate_ == 0.0 || ukm_task_sampling_rate_ == 0.0 ||
@@ -42,8 +44,7 @@ double UkmTaskSampler::GetConditionalSamplingProbability(bool has_thread_time) {
bool UkmTaskSampler::ShouldRecordTaskUkm(bool has_thread_time) {
double probability = GetConditionalSamplingProbability(has_thread_time);
- std::bernoulli_distribution dist(probability);
- return dist(random_generator_);
+ return random_generator_.RandDouble() < probability;
}
void UkmTaskSampler::SetUkmTaskSamplingRate(double rate) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h
index 40c95b3e7ba..4bc9276ccde 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h
@@ -5,9 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_UKM_TASK_SAMPLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_UKM_TASK_SAMPLER_H_
-#include <random>
-
#include "base/gtest_prod_util.h"
+#include "base/rand_util.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
@@ -47,7 +46,7 @@ class PLATFORM_EXPORT UkmTaskSampler {
double thread_time_sampling_rate_;
double ukm_task_sampling_rate_;
- std::mt19937_64 random_generator_;
+ base::InsecureRandomGenerator random_generator_;
};
} // namespace scheduler
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
index 9d4199b73e9..c61e4e2ad23 100644
--- 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
@@ -23,6 +23,11 @@ class PLATFORM_EXPORT UnprioritizedResourceLoadingTaskRunnerHandle
static std::unique_ptr<UnprioritizedResourceLoadingTaskRunnerHandle>
WrapTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ UnprioritizedResourceLoadingTaskRunnerHandle(
+ const UnprioritizedResourceLoadingTaskRunnerHandle&) = delete;
+ UnprioritizedResourceLoadingTaskRunnerHandle& operator=(
+ const UnprioritizedResourceLoadingTaskRunnerHandle&) = delete;
+
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
void DidChangeRequestPriority(net::RequestPriority priority) override;
@@ -35,8 +40,6 @@ class PLATFORM_EXPORT UnprioritizedResourceLoadingTaskRunnerHandle
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(UnprioritizedResourceLoadingTaskRunnerHandle);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_scheduling_priority.cc
index 6b714382b70..9328da74395 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/web_scheduling_priority.cc
@@ -10,33 +10,20 @@ namespace blink {
namespace {
-const AtomicString& UserBlockingPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, user_blocking_priority,
- ("user-blocking"));
- return user_blocking_priority;
-}
-
-const AtomicString& UserVisiblePriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, user_visible_priority,
- ("user-visible"));
- return user_visible_priority;
-}
-
-const AtomicString& BackgroundPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, background_priority, ("background"));
- return background_priority;
-}
+const char kUserBlockingPriorityKeyword[] = "user-blocking";
+const char kUserVisiblePriorityKeyword[] = "user-visible";
+const char kBackgroundPriorityKeyword[] = "background";
} // namespace
AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
switch (priority) {
case WebSchedulingPriority::kUserBlockingPriority:
- return UserBlockingPriorityKeyword();
+ return AtomicString(kUserBlockingPriorityKeyword);
case WebSchedulingPriority::kUserVisiblePriority:
- return UserVisiblePriorityKeyword();
+ return AtomicString(kUserVisiblePriorityKeyword);
case WebSchedulingPriority::kBackgroundPriority:
- return BackgroundPriorityKeyword();
+ return AtomicString(kBackgroundPriorityKeyword);
}
NOTREACHED();
@@ -45,11 +32,11 @@ AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
WebSchedulingPriority WebSchedulingPriorityFromString(
const AtomicString& priority) {
- if (priority == UserBlockingPriorityKeyword())
+ if (priority == kUserBlockingPriorityKeyword)
return WebSchedulingPriority::kUserBlockingPriority;
- if (priority == UserVisiblePriorityKeyword())
+ if (priority == kUserVisiblePriorityKeyword)
return WebSchedulingPriority::kUserVisiblePriority;
- if (priority == BackgroundPriorityKeyword())
+ if (priority == kBackgroundPriorityKeyword)
return WebSchedulingPriority::kBackgroundPriority;
NOTREACHED();
return WebSchedulingPriority::kUserVisiblePriority;
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 c5098f0fe65..d544075e707 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
@@ -64,6 +64,12 @@ WebThreadScheduler::DefaultTaskRunner() {
}
scoped_refptr<base::SingleThreadTaskRunner>
+WebThreadScheduler::InputTaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
WebThreadScheduler::CompositorTaskRunner() {
NOTREACHED();
return nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc
deleted file mode 100644
index 6f9a1844b1b..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h"
-
-#include <algorithm>
-#include <memory>
-
-#include "base/check.h"
-#include "base/feature_list.h"
-#include "base/sequence_checker.h"
-#include "base/synchronization/lock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/platform/scheduler/common/features.h"
-#include "third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
-
-namespace blink {
-namespace scheduler {
-namespace {
-
-using ::base::sequence_manager::TaskQueue;
-
-using PrioritisationType =
- ::blink::scheduler::MainThreadTaskQueue::QueueTraits::PrioritisationType;
-
-// Scheduling strategy that does nothing. This emulates the "current" shipped
-// behavior, and is the default unless overridden. Corresponds to the
-// |kNoOpStrategy| feature.
-class NoOpStrategy final : public AgentSchedulingStrategy {
- public:
- NoOpStrategy() = default;
-
- ShouldUpdatePolicy OnFrameAdded(const FrameSchedulerImpl&) override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
- ShouldUpdatePolicy OnFrameRemoved(const FrameSchedulerImpl&) override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
- ShouldUpdatePolicy OnMainFrameFirstMeaningfulPaint(
- const FrameSchedulerImpl&) override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
- ShouldUpdatePolicy OnInputEvent() override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
- ShouldUpdatePolicy OnDocumentChangedInMainFrame(
- const FrameSchedulerImpl&) override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
- ShouldUpdatePolicy OnMainFrameLoad(const FrameSchedulerImpl&) override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
- ShouldUpdatePolicy OnDelayPassed(const FrameSchedulerImpl&) override {
- VerifyValidSequence();
- return ShouldUpdatePolicy::kNo;
- }
-
- absl::optional<bool> QueueEnabledState(
- const MainThreadTaskQueue& task_queue) const override {
- VerifyValidSequence();
- return absl::nullopt;
- }
- absl::optional<TaskQueue::QueuePriority> QueuePriority(
- const MainThreadTaskQueue& task_queue) const override {
- VerifyValidSequence();
- return absl::nullopt;
- }
-
- bool ShouldNotifyOnInputEvent() const override { return false; }
-};
-
-// Strategy that keeps track of main frames reaching a certain signal to make
-// scheduling decisions. The exact behavior will be determined by parameter
-// values.
-class TrackMainFrameSignal final : public AgentSchedulingStrategy {
- public:
- TrackMainFrameSignal(Delegate& delegate,
- PerAgentAffectedQueues affected_queue_types,
- PerAgentSlowDownMethod method,
- PerAgentSignal signal,
- base::TimeDelta delay)
- : delegate_(delegate),
- affected_queue_types_(affected_queue_types),
- method_(method),
- signal_(signal),
- delay_(delay),
- waiting_for_input_(&waiting_for_input_lock_) {
- DCHECK(signal != PerAgentSignal::kDelayOnly || !delay.is_zero())
- << "Delay duration can not be zero when using |kDelayOnly|.";
- }
-
- ShouldUpdatePolicy OnFrameAdded(
- const FrameSchedulerImpl& frame_scheduler) override {
- VerifyValidSequence();
- return OnNewDocument(frame_scheduler);
- }
-
- ShouldUpdatePolicy OnFrameRemoved(
- const FrameSchedulerImpl& frame_scheduler) override {
- VerifyValidSequence();
- if (frame_scheduler.GetFrameType() !=
- FrameScheduler::FrameType::kMainFrame) {
- return ShouldUpdatePolicy::kNo;
- }
-
- main_frames_.erase(&frame_scheduler);
- main_frames_waiting_for_signal_.erase(&frame_scheduler);
- if (main_frames_waiting_for_signal_.IsEmpty())
- SetWaitingForInput(false);
-
- // TODO(talp): If the frame wasn't in the set to begin with (e.g.: because
- // it already hit FMP), or if there are still other frames in the set,
- // then we may not have to trigger a policy update. (But what about cases
- // where the current agent just changed from main to non-main?)
- return ShouldUpdatePolicy::kYes;
- }
-
- ShouldUpdatePolicy OnMainFrameFirstMeaningfulPaint(
- const FrameSchedulerImpl& frame_scheduler) override {
- VerifyValidSequence();
- DCHECK(frame_scheduler.GetFrameType() ==
- FrameScheduler::FrameType::kMainFrame);
-
- return OnSignal(frame_scheduler, PerAgentSignal::kFirstMeaningfulPaint);
- }
-
- ShouldUpdatePolicy OnInputEvent() override {
- VerifyValidSequence();
-
- // We only use input as a fail-safe for FMP, other signals are more
- // reliable.
- DCHECK_EQ(signal_, PerAgentSignal::kFirstMeaningfulPaint)
- << "OnInputEvent should only be called for FMP-based strategies.";
-
- if (main_frames_waiting_for_signal_.IsEmpty())
- return ShouldUpdatePolicy::kNo;
-
- // Ideally we would like to only remove the frame the input event is related
- // to, but we don't currently have that information. One suggestion (by
- // altimin@) is to attribute it to a widget, and apply it to all frames on
- // the page the widget is on.
- main_frames_waiting_for_signal_.clear();
- SetWaitingForInput(false);
- return ShouldUpdatePolicy::kYes;
- }
-
- ShouldUpdatePolicy OnDocumentChangedInMainFrame(
- const FrameSchedulerImpl& frame_scheduler) override {
- VerifyValidSequence();
- return OnNewDocument(frame_scheduler);
- }
-
- ShouldUpdatePolicy OnMainFrameLoad(
- const FrameSchedulerImpl& frame_scheduler) override {
- VerifyValidSequence();
- DCHECK(frame_scheduler.GetFrameType() ==
- FrameScheduler::FrameType::kMainFrame);
-
- return OnSignal(frame_scheduler, PerAgentSignal::kOnLoad);
- }
-
- ShouldUpdatePolicy OnDelayPassed(
- const FrameSchedulerImpl& frame_scheduler) override {
- VerifyValidSequence();
- return SignalReached(frame_scheduler);
- }
-
- absl::optional<bool> QueueEnabledState(
- const MainThreadTaskQueue& task_queue) const override {
- VerifyValidSequence();
-
- if (method_ == PerAgentSlowDownMethod::kDisable &&
- ShouldAffectQueue(task_queue)) {
- return false;
- }
-
- return absl::nullopt;
- }
-
- absl::optional<TaskQueue::QueuePriority> QueuePriority(
- const MainThreadTaskQueue& task_queue) const override {
- VerifyValidSequence();
-
- if (method_ == PerAgentSlowDownMethod::kBestEffort &&
- ShouldAffectQueue(task_queue)) {
- return TaskQueue::QueuePriority::kBestEffortPriority;
- }
-
- return absl::nullopt;
- }
-
- bool ShouldNotifyOnInputEvent() const override {
- if (signal_ != PerAgentSignal::kFirstMeaningfulPaint)
- return false;
-
- return waiting_for_input_.IsSet();
- }
-
- private:
- ShouldUpdatePolicy OnNewDocument(const FrameSchedulerImpl& frame_scheduler) {
- // For now we *always* return kYes here. It might be possible to optimize
- // this, but there are a number of tricky cases that need to be taken into
- // account here: (i) a non-main frame could have navigated between a main
- // and a non-main agent, possibly requiring policy update for that frame, or
- // (ii) main frame navigated to a different agent, potentially changing the
- // main/non-main classification for both the "previous" and "current" agents
- // and requiring their policies be updated.
-
- if (frame_scheduler.GetFrameType() !=
- FrameScheduler::FrameType::kMainFrame) {
- return ShouldUpdatePolicy::kYes;
- }
-
- if (signal_ == PerAgentSignal::kDelayOnly)
- delegate_.OnSetTimer(frame_scheduler, delay_);
- else if (signal_ == PerAgentSignal::kFirstMeaningfulPaint)
- SetWaitingForInput(true);
-
- main_frames_.insert(&frame_scheduler);
-
- // Only add ordinary page frames to the set of waiting frames, as
- // non-ordinary ones don't report any signals.
- if (frame_scheduler.IsOrdinary())
- main_frames_waiting_for_signal_.insert(&frame_scheduler);
-
- return ShouldUpdatePolicy::kYes;
- }
-
- bool ShouldAffectQueue(const MainThreadTaskQueue& task_queue) const {
- // Queues that don't have a frame scheduler are, by definition, not
- // associated with a frame (or agent).
- if (!task_queue.GetFrameScheduler())
- return false;
-
- if (affected_queue_types_ == PerAgentAffectedQueues::kTimerQueues &&
- task_queue.GetPrioritisationType() !=
- PrioritisationType::kJavaScriptTimer) {
- return false;
- }
-
- // Don't do anything if all main frames have reached the signal.
- if (main_frames_waiting_for_signal_.IsEmpty())
- return false;
-
- // Otherwise, affect the queue only if it doesn't belong to any main agent.
- base::UnguessableToken agent_cluster_id =
- task_queue.GetFrameScheduler()->GetAgentClusterId();
- return std::all_of(main_frames_.begin(), main_frames_.end(),
- [agent_cluster_id](const FrameSchedulerImpl* frame) {
- return frame->GetAgentClusterId() != agent_cluster_id;
- });
- }
-
- ShouldUpdatePolicy OnSignal(const FrameSchedulerImpl& frame_scheduler,
- PerAgentSignal signal) {
- if (signal != signal_)
- return ShouldUpdatePolicy::kNo;
-
- // If there is no delay, then we have reached the awaited signal.
- if (delay_.is_zero()) {
- return SignalReached(frame_scheduler);
- }
-
- // No need to update policy if we have to wait for a delay.
- delegate_.OnSetTimer(frame_scheduler, delay_);
- return ShouldUpdatePolicy::kNo;
- }
-
- ShouldUpdatePolicy SignalReached(const FrameSchedulerImpl& frame_scheduler) {
- main_frames_waiting_for_signal_.erase(&frame_scheduler);
- if (main_frames_waiting_for_signal_.IsEmpty())
- SetWaitingForInput(false);
-
- // TODO(talp): If the frame wasn't in the set to begin with (e.g.: because
- // an input event cleared it), or if there are still other frames in the
- // set, then we may not have to trigger a policy update.
- return ShouldUpdatePolicy::kYes;
- }
-
- Delegate& delegate_;
- const PerAgentAffectedQueues affected_queue_types_;
- const PerAgentSlowDownMethod method_;
- const PerAgentSignal signal_;
- const base::TimeDelta delay_;
-
- WTF::HashSet<const FrameSchedulerImpl*> main_frames_;
- WTF::HashSet<const FrameSchedulerImpl*> main_frames_waiting_for_signal_;
-
- base::Lock waiting_for_input_lock_;
- PollableThreadSafeFlag waiting_for_input_;
- void SetWaitingForInput(bool waiting_for_input) {
- if (waiting_for_input_.IsSet() != waiting_for_input) {
- base::AutoLock lock(waiting_for_input_lock_);
- waiting_for_input_.SetWhileLocked(waiting_for_input);
- }
- }
-};
-} // namespace
-
-AgentSchedulingStrategy::~AgentSchedulingStrategy() {
- VerifyValidSequence();
-}
-
-std::unique_ptr<AgentSchedulingStrategy> AgentSchedulingStrategy::Create(
- Delegate& delegate) {
- if (!base::FeatureList::IsEnabled(kPerAgentSchedulingExperiments))
- return std::make_unique<NoOpStrategy>();
-
- return std::make_unique<TrackMainFrameSignal>(
- delegate, kPerAgentQueues.Get(), kPerAgentMethod.Get(),
- kPerAgentSignal.Get(),
- base::TimeDelta::FromMilliseconds(kPerAgentDelayMs.Get()));
-}
-
-void AgentSchedulingStrategy::VerifyValidSequence() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(main_thread_sequence_checker_);
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h
deleted file mode 100644
index c37021f6052..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_SCHEDULING_STRATEGY_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_SCHEDULING_STRATEGY_H_
-
-#include "base/sequence_checker.h"
-#include "base/task/sequence_manager/task_queue.h"
-#include "base/time/time.h"
-#include "base/unguessable_token.h"
-#include "third_party/abseil-cpp/absl/types/optional.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_task_queue.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-
-namespace blink {
-namespace scheduler {
-
-// Abstract class that can be consulted to determine task queue priorities and
-// scheduling policies, that are based on the queue's Agent.
-// Strategies should only be accessed from the main thread.
-class PLATFORM_EXPORT AgentSchedulingStrategy {
- public:
- enum class ShouldUpdatePolicy {
- kNo,
- kYes,
- };
-
- class Delegate {
- public:
- Delegate() = default;
- virtual ~Delegate() = default;
-
- // Delegate should call OnDelayPassed after |delay| has passed, and pass
- // |frame_scheduler| as a parameter.
- virtual void OnSetTimer(const FrameSchedulerImpl& frame_scheduler,
- base::TimeDelta delay) = 0;
- };
-
- AgentSchedulingStrategy(const AgentSchedulingStrategy&) = delete;
- AgentSchedulingStrategy(AgentSchedulingStrategy&&) = delete;
-
- virtual ~AgentSchedulingStrategy();
-
- static std::unique_ptr<AgentSchedulingStrategy> Create(Delegate& delegate);
-
- // The following functions need to be called as appropriate to manage the
- // strategy's internal state. Will return |kYes| when a policy update should
- // be triggered.
- virtual ShouldUpdatePolicy OnFrameAdded(
- const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0;
- virtual ShouldUpdatePolicy OnFrameRemoved(
- const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0;
- virtual ShouldUpdatePolicy OnMainFrameFirstMeaningfulPaint(
- const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0;
- // FMP is not reported consistently, so input events are used as a failsafe
- // to make sure frames aren't considered waiting for FMP indefinitely. Should
- // not be called for mouse move events.
- virtual ShouldUpdatePolicy OnInputEvent() WARN_UNUSED_RESULT = 0;
- virtual ShouldUpdatePolicy OnDocumentChangedInMainFrame(
- const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0;
- virtual ShouldUpdatePolicy OnMainFrameLoad(
- const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0;
- // OnDelayPassed should be called by Delegate after the appropriate delay.
- virtual ShouldUpdatePolicy OnDelayPassed(
- const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0;
-
- // The following functions should be consulted when making scheduling
- // decisions. Will return |absl::optional| containing the desired value, or
- // |nullopt| to signify that the original scheduler's decision should not be
- // changed.
- virtual absl::optional<bool> QueueEnabledState(
- const MainThreadTaskQueue& task_queue) const = 0;
- virtual absl::optional<base::sequence_manager::TaskQueue::QueuePriority>
- QueuePriority(const MainThreadTaskQueue& task_queue) const = 0;
-
- // Returns true if the strategy is interested in getting input event
- // notifications. This is *the only* method that may be called from different
- // threads.
- virtual bool ShouldNotifyOnInputEvent() const = 0;
-
- protected:
- AgentSchedulingStrategy() = default;
-
- // Check that the strategy is used from the right (= main) thread. Should be
- // called from all public methods except ShouldNotifyOnInput().
- void VerifyValidSequence() const;
-
- private:
- SEQUENCE_CHECKER(main_thread_sequence_checker_);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_SCHEDULING_STRATEGY_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc
deleted file mode 100644
index 9f1e710bb04..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc
+++ /dev/null
@@ -1,527 +0,0 @@
-#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h"
-
-#include <memory>
-#include "base/memory/scoped_refptr.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/time/time.h"
-#include "base/unguessable_token.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/platform/scheduler/common/features.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/page_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"
-
-namespace blink {
-namespace scheduler {
-
-using FeatureAndParams = ::base::test::ScopedFeatureList::FeatureAndParams;
-using ShouldUpdatePolicy =
- ::blink::scheduler::AgentSchedulingStrategy::ShouldUpdatePolicy;
-using PrioritisationType =
- ::blink::scheduler::MainThreadTaskQueue::QueueTraits::PrioritisationType;
-
-using ::base::FieldTrialParams;
-using ::base::sequence_manager::TaskQueue;
-using ::base::test::ScopedFeatureList;
-using ::testing::_;
-using ::testing::NiceMock;
-using ::testing::Return;
-using ::testing::ReturnRef;
-using ::testing::Test;
-
-namespace {
-
-class MockDelegate : public AgentSchedulingStrategy::Delegate {
- public:
- MOCK_METHOD(void,
- OnSetTimer,
- (const FrameSchedulerImpl& frame_scheduler,
- base::TimeDelta delay));
-};
-
-class MockFrameSchedulerDelegate : public FrameScheduler::Delegate {
- public:
- MockFrameSchedulerDelegate() {
- ON_CALL(*this, GetAgentClusterId)
- .WillByDefault(ReturnRef(agent_cluster_id_));
- }
-
- MOCK_METHOD(const base::UnguessableToken&,
- GetAgentClusterId,
- (),
- (const, override));
- MOCK_METHOD(ukm::UkmRecorder*, GetUkmRecorder, ());
- MOCK_METHOD(ukm::SourceId, GetUkmSourceId, ());
- MOCK_METHOD(void, UpdateTaskTime, (base::TimeDelta));
- MOCK_METHOD(void, UpdateActiveSchedulerTrackedFeatures, (uint64_t));
-
- private:
- base::UnguessableToken agent_cluster_id_ = base::UnguessableToken::Create();
-};
-
-class MockFrameScheduler : public FrameSchedulerImpl {
- public:
- explicit MockFrameScheduler(FrameScheduler::FrameType frame_type)
- : FrameSchedulerImpl(/*main_thread_scheduler=*/nullptr,
- /*parent_page_scheduler=*/nullptr,
- /*delegate=*/&delegate_,
- /*blame_context=*/nullptr,
- /*frame_type=*/frame_type) {
- ON_CALL(*this, IsOrdinary).WillByDefault(Return(true));
- }
-
- MOCK_METHOD(bool, IsOrdinary, (), (const));
-
- private:
- NiceMock<MockFrameSchedulerDelegate> delegate_;
-};
-
-} // namespace
-
-class PerAgentSchedulingBaseTest : public Test {
- public:
- explicit PerAgentSchedulingBaseTest(
- const FieldTrialParams experiment_params) {
- feature_list_.InitWithFeaturesAndParameters(
- {{kPerAgentSchedulingExperiments, experiment_params}}, {});
- strategy_ = AgentSchedulingStrategy::Create(delegate_);
- timer_queue_->SetFrameSchedulerForTest(&subframe_);
- non_timer_queue_->SetFrameSchedulerForTest(&subframe_);
- }
-
- protected:
- ScopedFeatureList feature_list_;
- NiceMock<MockDelegate> delegate_{};
- std::unique_ptr<AgentSchedulingStrategy> strategy_;
- NiceMock<MockFrameScheduler> main_frame_{
- FrameScheduler::FrameType::kMainFrame};
- NiceMock<MockFrameScheduler> subframe_{FrameScheduler::FrameType::kSubframe};
- scoped_refptr<MainThreadTaskQueueForTest> timer_queue_{
- new MainThreadTaskQueueForTest(PrioritisationType::kJavaScriptTimer)};
- scoped_refptr<MainThreadTaskQueueForTest> non_timer_queue_{
- new MainThreadTaskQueueForTest(PrioritisationType::kRegular)};
-};
-
-class PerAgentDisableTimersUntilTimeoutStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentDisableTimersUntilTimeoutStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "timer-queues"},
- {"method", "disable"},
- {"signal", "delay"},
- {"delay_ms", "50"}}) {}
-};
-
-TEST_F(PerAgentDisableTimersUntilTimeoutStrategyTest, RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnDelayPassed(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
-}
-
-TEST_F(PerAgentDisableTimersUntilTimeoutStrategyTest, InitiatesTimer) {
- EXPECT_CALL(delegate_, OnSetTimer(_, base::TimeDelta::FromMilliseconds(50)))
- .Times(1);
-
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-}
-
-TEST_F(PerAgentDisableTimersUntilTimeoutStrategyTest,
- DisablesTimerQueueUntilTimeout) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
- ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_));
-
- EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnDelayPassed(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
-}
-
-class PerAgentDisableTimersUntilFMPStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentDisableTimersUntilFMPStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "timer-queues"},
- {"method", "disable"},
- {"signal", "fmp"}}) {}
-};
-
-TEST_F(PerAgentDisableTimersUntilFMPStrategyTest, RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
- // Only the first input event (since a main frame document was added) should
- // cause a policy update. This is necessary as we may get several input event
- // notifications, but we don't want them to re-calculate priorities as nothing
- // will change.
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo);
-}
-
-TEST_F(PerAgentDisableTimersUntilFMPStrategyTest, DisablesTimerQueueUntilFMP) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
-}
-
-class PerAgentBestEffortPriorityTimersUntilFMPStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentBestEffortPriorityTimersUntilFMPStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "timer-queues"},
- {"method", "best-effort"},
- {"signal", "fmp"}}) {}
-};
-
-TEST_F(PerAgentBestEffortPriorityTimersUntilFMPStrategyTest,
- RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
- // Only the first input event (since a main frame document was added) should
- // cause a policy update. This is necessary as we may get several input event
- // notifications, but we don't want them to re-calculate priorities as nothing
- // will change.
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo);
-}
-
-TEST_F(PerAgentBestEffortPriorityTimersUntilFMPStrategyTest,
- LowersTimerQueuePriorityUntilFMP) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueuePriority(*timer_queue_),
- testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority));
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
-}
-
-class PerAgentDisableTimersUntilLoadStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentDisableTimersUntilLoadStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "timer-queues"},
- {"method", "disable"},
- {"signal", "onload"}}) {}
-};
-
-TEST_F(PerAgentDisableTimersUntilLoadStrategyTest, RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
-}
-
-TEST_F(PerAgentDisableTimersUntilLoadStrategyTest, DisablesTimerQueue) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnMainFrameLoad(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
-}
-
-class PerAgentBestEffortPriorityTimersUntilLoadStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentBestEffortPriorityTimersUntilLoadStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "timer-queues"},
- {"method", "best-effort"},
- {"signal", "onload"}}) {}
-};
-
-TEST_F(PerAgentBestEffortPriorityTimersUntilLoadStrategyTest,
- RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
-}
-
-TEST_F(PerAgentBestEffortPriorityTimersUntilLoadStrategyTest,
- LowersTimerQueuePriority) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueuePriority(*timer_queue_),
- testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority));
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnMainFrameLoad(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
-}
-
-class PerAgentDisableAllUntilFMPStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentDisableAllUntilFMPStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "all-queues"},
- {"method", "disable"},
- {"signal", "fmp"}}) {}
-};
-
-TEST_F(PerAgentDisableAllUntilFMPStrategyTest, RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
- // Only the first input event (since a main frame document was added) should
- // cause a policy update. This is necessary as we may get several input event
- // notifications, but we don't want them to re-calculate priorities as nothing
- // will change.
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo);
-}
-
-TEST_F(PerAgentDisableAllUntilFMPStrategyTest, DisablesTimerQueueUntilFMP) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueueEnabledState(*non_timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-}
-
-class PerAgentBestEffortPriorityAllUntilFMPStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentBestEffortPriorityAllUntilFMPStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "all-queues"},
- {"method", "best-effort"},
- {"signal", "fmp"}}) {}
-};
-
-TEST_F(PerAgentBestEffortPriorityAllUntilFMPStrategyTest,
- RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
- // Only the first input event (since a main frame document was added) should
- // cause a policy update. This is necessary as we may get several input event
- // notifications, but we don't want them to re-calculate priorities as nothing
- // will change.
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo);
-}
-
-TEST_F(PerAgentBestEffortPriorityAllUntilFMPStrategyTest,
- LowersTimerQueuePriorityUntilFMP) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueuePriority(*timer_queue_),
- testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority));
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueuePriority(*non_timer_queue_),
- testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority));
-
- ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-}
-
-class PerAgentDisableAllUntilLoadStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentDisableAllUntilLoadStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "all-queues"},
- {"method", "disable"},
- {"signal", "onload"}}) {}
-};
-
-TEST_F(PerAgentDisableAllUntilLoadStrategyTest, RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
-}
-
-TEST_F(PerAgentDisableAllUntilLoadStrategyTest, DisablesTimerQueue) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueueEnabledState(*non_timer_queue_),
- testing::Optional(false));
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-
- ignore_result(strategy_->OnMainFrameLoad(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-}
-
-class PerAgentBestEffortPriorityAllUntilLoadStrategyTest
- : public PerAgentSchedulingBaseTest {
- public:
- PerAgentBestEffortPriorityAllUntilLoadStrategyTest()
- : PerAgentSchedulingBaseTest({{"queues", "all-queues"},
- {"method", "best-effort"},
- {"signal", "onload"}}) {}
-};
-
-TEST_F(PerAgentBestEffortPriorityAllUntilLoadStrategyTest,
- RequestsPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kYes);
-}
-
-TEST_F(PerAgentBestEffortPriorityAllUntilLoadStrategyTest,
- LowersTimerQueuePriority) {
- ignore_result(strategy_->OnFrameAdded(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueuePriority(*timer_queue_),
- testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority));
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_THAT(strategy_->QueuePriority(*non_timer_queue_),
- testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority));
-
- ignore_result(strategy_->OnMainFrameLoad(main_frame_));
-
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-}
-
-class PerAgentDefaultIsNoOpStrategyTest : public Test {
- public:
- PerAgentDefaultIsNoOpStrategyTest() {
- timer_queue_->SetFrameSchedulerForTest(&subframe_);
- }
-
- protected:
- NiceMock<MockDelegate> delegate_{};
- std::unique_ptr<AgentSchedulingStrategy> strategy_ =
- AgentSchedulingStrategy::Create(delegate_);
- MockFrameScheduler main_frame_{FrameScheduler::FrameType::kMainFrame};
- NiceMock<MockFrameScheduler> subframe_{FrameScheduler::FrameType::kSubframe};
- scoped_refptr<MainThreadTaskQueueForTest> timer_queue_{
- new MainThreadTaskQueueForTest(PrioritisationType::kJavaScriptTimer)};
-};
-
-TEST_F(PerAgentDefaultIsNoOpStrategyTest, DoesntRequestPolicyUpdate) {
- EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_),
- ShouldUpdatePolicy::kNo);
- EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo);
-}
-
-TEST_F(PerAgentDefaultIsNoOpStrategyTest, DoesntModifyPolicyDecisions) {
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
-}
-
-class PerAgentNonOrdinaryPageTest : public PerAgentSchedulingBaseTest {
- public:
- PerAgentNonOrdinaryPageTest()
- : PerAgentSchedulingBaseTest({{"queues", "timer-queues"},
- {"method", "disable"},
- {"signal", "onload"}}) {
- ON_CALL(non_ordinary_frame_scheduler_, IsOrdinary)
- .WillByDefault(Return(false));
- }
-
- protected:
- NiceMock<MockFrameScheduler> non_ordinary_frame_scheduler_{
- FrameScheduler::FrameType::kMainFrame};
-};
-
-TEST_F(PerAgentNonOrdinaryPageTest, DoesntWaitForNonOrdinaryFrames) {
- EXPECT_EQ(strategy_->OnFrameAdded(non_ordinary_frame_scheduler_),
- ShouldUpdatePolicy::kYes);
- EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value());
- EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value());
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h
index 4d5b3b0bf4b..dffe694b09d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h
@@ -38,7 +38,7 @@ struct AttributionGroupHash {
STATIC_ONLY(AttributionGroupHash);
static unsigned GetHash(const AttributionGroup& group) {
- return group.attribution.GetHash();
+ return static_cast<unsigned>(group.attribution.GetHash());
}
static bool Equal(const AttributionGroup& a, const AttributionGroup& b) {
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 a638dcbb7dd..4790db3430d 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
@@ -17,8 +17,7 @@ namespace scheduler {
AutoAdvancingVirtualTimeDomain::AutoAdvancingVirtualTimeDomain(
base::Time initial_time,
base::TimeTicks initial_time_ticks,
- SchedulerHelper* helper,
- BaseTimeOverridePolicy policy)
+ SchedulerHelper* helper)
: task_starvation_count_(0),
max_task_starvation_count_(0),
can_advance_virtual_time_(true),
@@ -30,14 +29,15 @@ AutoAdvancingVirtualTimeDomain::AutoAdvancingVirtualTimeDomain(
DCHECK_EQ(AutoAdvancingVirtualTimeDomain::g_time_domain_, nullptr);
AutoAdvancingVirtualTimeDomain::g_time_domain_ = this;
- // GetVirtualTime / GetVirtualTimeTicks access g_time_domain_.
- std::atomic_thread_fence(std::memory_order_seq_cst);
+ // GetVirtualTime / GetVirtualTimeTicks access |g_time_domain_|. Ensure that
+ // the write of |g_time_domain_| above propagates before the overrides to
+ // GetVirtualTime / GetVirtualTimeTicks are put in place below, by
+ // preventing reordering via a release fence.
+ std::atomic_thread_fence(std::memory_order_release);
- if (policy == BaseTimeOverridePolicy::OVERRIDE) {
- time_overrides_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>(
- &AutoAdvancingVirtualTimeDomain::GetVirtualTime,
- &AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks, nullptr);
- }
+ time_overrides_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>(
+ &AutoAdvancingVirtualTimeDomain::GetVirtualTime,
+ &AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks, nullptr);
helper_->AddTaskObserver(this);
}
@@ -47,10 +47,6 @@ AutoAdvancingVirtualTimeDomain::~AutoAdvancingVirtualTimeDomain() {
time_overrides_.reset();
- // GetVirtualTime / GetVirtualTimeTicks (the functions we may have
- // temporariliy installed in the constructor) access g_time_domain_.
- std::atomic_thread_fence(std::memory_order_seq_cst);
-
DCHECK_EQ(AutoAdvancingVirtualTimeDomain::g_time_domain_, this);
AutoAdvancingVirtualTimeDomain::g_time_domain_ = nullptr;
}
@@ -188,12 +184,22 @@ AutoAdvancingVirtualTimeDomain* AutoAdvancingVirtualTimeDomain::g_time_domain_ =
// static
base::TimeTicks AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks() {
+ // ScopedTimeClockOverrides sets the override to GetVirtualTimeTicks() as a
+ // relaxed atomic operation. To ensure that the read of |g_time_domain_| is
+ // not reordered with the read of the override, place an acquire fence before
+ // loading |g_time_domain_|.
+ std::atomic_thread_fence(std::memory_order_acquire);
DCHECK(AutoAdvancingVirtualTimeDomain::g_time_domain_);
return AutoAdvancingVirtualTimeDomain::g_time_domain_->Now();
}
// static
base::Time AutoAdvancingVirtualTimeDomain::GetVirtualTime() {
+ // ScopedTimeClockOverrides sets the override to GetVirtualTimeTicks() as a
+ // relaxed atomic operation. To ensure that the read of |g_time_domain_| is
+ // not reordered with the read of the override, place an acquire fence before
+ // loading |g_time_domain_|.
+ std::atomic_thread_fence(std::memory_order_acquire);
DCHECK(AutoAdvancingVirtualTimeDomain::g_time_domain_);
return AutoAdvancingVirtualTimeDomain::g_time_domain_->Date();
}
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 f62e52db83a..30cfb0ac60d 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AUTO_ADVANCING_VIRTUAL_TIME_DOMAIN_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AUTO_ADVANCING_VIRTUAL_TIME_DOMAIN_H_
-#include "base/macros.h"
#include "base/task/sequence_manager/time_domain.h"
#include "base/task/task_observer.h"
#include "base/time/time_override.h"
@@ -16,7 +15,12 @@ namespace scheduler {
class SchedulerHelper;
// A time domain that runs tasks sequentially in time order but doesn't sleep
-// between delayed tasks.
+// between delayed tasks. Because AutoAdvancingVirtualTimeDomain may override
+// Time/TimeTicks in a multi-threaded context, it must outlive any thread that
+// may call Time::Now() or TimeTicks::Now(). In practice, this means
+// AutoAdvancingVirtualTimeDomain can never be destroyed in production and acts
+// as a one-way switch. In tests, it should only be destroyed after all threads
+// have been joined.
//
// KEY: A-E are delayed tasks
// | A B C D E (Execution with RealTimeDomain)
@@ -28,12 +32,13 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
: public base::sequence_manager::TimeDomain,
public base::TaskObserver {
public:
- enum class BaseTimeOverridePolicy { OVERRIDE, DO_NOT_OVERRIDE };
-
AutoAdvancingVirtualTimeDomain(base::Time initial_time,
base::TimeTicks initial_time_ticks,
- SchedulerHelper* helper,
- BaseTimeOverridePolicy policy);
+ SchedulerHelper* helper);
+ AutoAdvancingVirtualTimeDomain(const AutoAdvancingVirtualTimeDomain&) =
+ delete;
+ AutoAdvancingVirtualTimeDomain& operator=(
+ const AutoAdvancingVirtualTimeDomain&) = delete;
~AutoAdvancingVirtualTimeDomain() override;
// Controls whether or not virtual time is allowed to advance, when the
@@ -43,10 +48,10 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
// If non-null, virtual time may not advance past |virtual_time_fence|.
void SetVirtualTimeFence(base::TimeTicks virtual_time_fence);
- // The maximum number amount of delayed task starvation we will allow.
- // NB a value of 0 allows infinite starvation. A reasonable value for this in
- // practice is around 1000 tasks, which should only affect rendering of the
- // heaviest pages.
+ // The maximum number of tasks we will run before advancing virtual time in
+ // order to avoid starving delayed tasks. NB a value of 0 allows infinite
+ // starvation. A reasonable value for this in practice is around 1000 tasks,
+ // which should only affect rendering of the heaviest pages.
void SetMaxVirtualTimeTaskStarvationCount(int max_task_starvation_count);
// Updates to min(NextDelayedTaskTime, |new_virtual_time|) if thats ahead of
@@ -108,8 +113,6 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
base::Time previous_time_;
std::unique_ptr<base::subtle::ScopedTimeClockOverrides> time_overrides_;
-
- DISALLOW_COPY_AND_ASSIGN(AutoAdvancingVirtualTimeDomain);
};
} // namespace scheduler
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 6afa2f817de..ef8155a2ef4 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
@@ -44,8 +44,7 @@ class AutoAdvancingVirtualTimeDomainTest : public testing::Test {
initial_time_ticks_ = test_task_runner_->NowTicks();
auto_advancing_time_domain_ =
std::make_unique<AutoAdvancingVirtualTimeDomain>(
- initial_time_, initial_time_ticks_, scheduler_helper_.get(),
- AutoAdvancingVirtualTimeDomain::BaseTimeOverridePolicy::OVERRIDE);
+ initial_time_, initial_time_ticks_, scheduler_helper_.get());
scheduler_helper_->RegisterTimeDomain(auto_advancing_time_domain_.get());
task_queue_->SetTimeDomain(auto_advancing_time_domain_.get());
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
index 0827874b665..b4c37e0f7da 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
@@ -37,9 +37,6 @@ CompositorPriorityExperiments::GetExperimentFromFeatureList() {
kVeryHighPriorityForCompositingAlternating)) {
return Experiment::kVeryHighPriorityForCompositingAlternating;
} else if (base::FeatureList::IsEnabled(
- kVeryHighPriorityForCompositingBudget)) {
- return Experiment::kVeryHighPriorityForCompositingBudget;
- } else if (base::FeatureList::IsEnabled(
kVeryHighPriorityForCompositingAfterDelay)) {
return Experiment::kVeryHighPriorityForCompositingAfterDelay;
} else {
@@ -66,29 +63,12 @@ QueuePriority CompositorPriorityExperiments::GetCompositorPriority() const {
return alternating_compositor_priority_;
case Experiment::kVeryHighPriorityForCompositingAfterDelay:
return delay_compositor_priority_;
- case Experiment::kVeryHighPriorityForCompositingBudget:
- return budget_compositor_priority_;
case Experiment::kNone:
NOTREACHED();
return QueuePriority::kNormalPriority;
}
}
-void CompositorPriorityExperiments::OnMainThreadSchedulerInitialized() {
- if (experiment_ == Experiment::kVeryHighPriorityForCompositingBudget) {
- budget_pool_controller_ = std::make_unique<CompositorBudgetPoolController>(
- this, scheduler_, scheduler_->CompositorTaskQueue().get(),
- &scheduler_->tracing_controller_,
- base::TimeDelta::FromMilliseconds(
- kInitialCompositorBudgetInMilliseconds.Get()),
- kCompositorBudgetRecoveryRate.Get());
- }
-}
-
-void CompositorPriorityExperiments::OnMainThreadSchedulerShutdown() {
- budget_pool_controller_.reset();
-}
-
void CompositorPriorityExperiments::OnWillBeginMainFrame() {
will_begin_main_frame_ = true;
}
@@ -144,82 +124,10 @@ void CompositorPriorityExperiments::OnTaskCompleted(
if (current_compositor_priority != delay_compositor_priority_)
scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
return;
- case Experiment::kVeryHighPriorityForCompositingBudget:
- budget_pool_controller_->OnTaskCompleted(queue, task_timing,
- have_seen_stop_signal);
- return;
case Experiment::kNone:
return;
}
}
-void CompositorPriorityExperiments::OnBudgetExhausted() {
- // Compositor will still be allowed to run tasks if the budget is exhausted
- // if there is no other higher priority work to be done. If a compositor task
- // is run while the budget is exhausted it will still deplete the budget which
- // will keep it at a normal priority for longer.
- budget_compositor_priority_ = QueuePriority::kNormalPriority;
- scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
-}
-
-void CompositorPriorityExperiments::OnBudgetReplenished() {
- budget_compositor_priority_ = QueuePriority::kVeryHighPriority;
- scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
-}
-
-CompositorPriorityExperiments::CompositorBudgetPoolController::
- CompositorBudgetPoolController(
- CompositorPriorityExperiments* experiment,
- MainThreadSchedulerImpl* scheduler,
- MainThreadTaskQueue* compositor_queue,
- TraceableVariableController* tracing_controller,
- base::TimeDelta min_budget,
- double budget_recovery_rate)
- : experiment_(experiment) {
- DCHECK_EQ(compositor_queue->queue_type(),
- MainThreadTaskQueue::QueueType::kCompositor);
- base::TimeTicks now = scheduler->GetTickClock()->NowTicks();
-
- compositor_budget_pool_ = std::make_unique<CPUTimeBudgetPool>(
- "CompositorBudgetPool", this, tracing_controller, now);
- compositor_budget_pool_->SetMinBudgetLevelToRun(now, min_budget);
- compositor_budget_pool_->SetTimeBudgetRecoveryRate(now, budget_recovery_rate);
- compositor_queue->AddToBudgetPool(now, compositor_budget_pool_.get());
-}
-
-CompositorPriorityExperiments::CompositorBudgetPoolController::
- ~CompositorBudgetPoolController() = default;
-
-void CompositorPriorityExperiments::CompositorBudgetPoolController::
- UpdateQueueSchedulingLifecycleState(base::TimeTicks now, TaskQueue* queue) {
- UpdateCompositorBudgetState(now);
-}
-
-void CompositorPriorityExperiments::CompositorBudgetPoolController::
- UpdateCompositorBudgetState(base::TimeTicks now) {
- bool is_exhausted =
- !compositor_budget_pool_->CanRunTasksAt(now, false /* is_wake_up */);
- if (is_exhausted_ == is_exhausted)
- return;
-
- is_exhausted_ = is_exhausted;
- if (is_exhausted_) {
- experiment_->OnBudgetExhausted();
- return;
- }
- experiment_->OnBudgetReplenished();
-}
-
-void CompositorPriorityExperiments::CompositorBudgetPoolController::
- OnTaskCompleted(MainThreadTaskQueue* queue,
- TaskQueue::TaskTiming* task_timing,
- bool have_seen_stop_signal) {
- if (have_seen_stop_signal) {
- compositor_budget_pool_->RecordTaskRunTime(
- nullptr, task_timing->start_time(), task_timing->end_time());
- }
- UpdateCompositorBudgetState(task_timing->end_time());
-}
-
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h
index 96280a3980d..4d0f8597e94 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h
@@ -8,9 +8,6 @@
#include "base/task/sequence_manager/task_queue.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/common/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/budget_pool_controller.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -20,7 +17,6 @@ namespace scheduler {
using TaskQueue = base::sequence_manager::TaskQueue;
using QueuePriority = base::sequence_manager::TaskQueue::QueuePriority;
-class CPUTimeBudgetPool;
class MainThreadSchedulerImpl;
class MainThreadTaskQueue;
@@ -37,7 +33,6 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
kVeryHighPriorityForCompositingWhenFast,
kVeryHighPriorityForCompositingAlternating,
kVeryHighPriorityForCompositingAfterDelay,
- kVeryHighPriorityForCompositingBudget
};
bool IsExperimentActive() const;
@@ -54,47 +49,7 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
void OnWillBeginMainFrame();
- void OnMainThreadSchedulerInitialized();
- void OnMainThreadSchedulerShutdown();
-
- void OnBudgetExhausted();
- void OnBudgetReplenished();
-
private:
- class CompositorBudgetPoolController : public BudgetPoolController {
- public:
- explicit CompositorBudgetPoolController(
- CompositorPriorityExperiments* experiment,
- MainThreadSchedulerImpl* scheduler,
- MainThreadTaskQueue* compositor_queue,
- TraceableVariableController* tracing_controller,
- base::TimeDelta min_budget,
- double budget_recovery_rate);
- ~CompositorBudgetPoolController() override;
-
- void UpdateQueueSchedulingLifecycleState(base::TimeTicks now,
- TaskQueue* queue) override;
-
- void UpdateCompositorBudgetState(base::TimeTicks now);
-
- void OnTaskCompleted(MainThreadTaskQueue* queue,
- TaskQueue::TaskTiming* task_timing,
- bool have_seen_stop_signal);
-
- // Unimplemented methods.
- void AddQueueToBudgetPool(TaskQueue* queue,
- BudgetPool* budget_pool) override {}
- void RemoveQueueFromBudgetPool(TaskQueue* queue,
- BudgetPool* budget_pool) override {}
- void UnregisterBudgetPool(BudgetPool* budget_pool) override {}
- bool IsThrottled(TaskQueue* queue) const override { return false; }
-
- private:
- CompositorPriorityExperiments* experiment_;
- std::unique_ptr<CPUTimeBudgetPool> compositor_budget_pool_;
- bool is_exhausted_ = false;
- };
-
static Experiment GetExperimentFromFeatureList();
enum class StopSignalType { kAnyCompositorTask, kBeginMainFrameTask };
@@ -110,9 +65,6 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
base::TimeTicks last_compositor_task_time_;
base::TimeDelta prioritize_compositing_after_delay_length_;
- QueuePriority budget_compositor_priority_ = QueuePriority::kVeryHighPriority;
- std::unique_ptr<CompositorBudgetPoolController> budget_pool_controller_;
-
const StopSignalType stop_signal_;
bool will_begin_main_frame_ = false;
};
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 04f33623a6b..97e5305c97a 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_DEADLINE_TASK_RUNNER_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -23,6 +22,8 @@ class PLATFORM_EXPORT DeadlineTaskRunner {
public:
DeadlineTaskRunner(const base::RepeatingClosure& callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ DeadlineTaskRunner(const DeadlineTaskRunner&) = delete;
+ DeadlineTaskRunner& operator=(const DeadlineTaskRunner&) = delete;
~DeadlineTaskRunner();
@@ -44,8 +45,6 @@ class PLATFORM_EXPORT DeadlineTaskRunner {
base::RepeatingClosure callback_;
base::TimeTicks deadline_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(DeadlineTaskRunner);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc
index ca1fdabd15a..72d2472bbbc 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc
@@ -41,10 +41,7 @@ FindInPageBudgetPoolController::FindInPageBudgetPoolController(
base::TimeTicks now = scheduler_->GetTickClock()->NowTicks();
find_in_page_budget_pool_ = std::make_unique<CPUTimeBudgetPool>(
- "FindInPageBudgetPool", this, &scheduler_->tracing_controller_, now);
- // Set no minimum budget for find-in-page, so that we won't delay running
- // find-in-page tasks when budget is available.
- find_in_page_budget_pool_->SetMinBudgetLevelToRun(now, base::TimeDelta());
+ "FindInPageBudgetPool", &scheduler_->tracing_controller_, now);
find_in_page_budget_pool_->SetMaxBudgetLevel(now, kFindInPageMaxBudget);
find_in_page_budget_pool_->SetTimeBudgetRecoveryRate(
now, kFindInPageBudgetRecoveryRate);
@@ -60,12 +57,12 @@ void FindInPageBudgetPoolController::OnTaskCompleted(
DCHECK(find_in_page_budget_pool_);
if (queue->GetPrioritisationType() ==
MainThreadTaskQueue::QueueTraits::PrioritisationType::kFindInPage) {
- find_in_page_budget_pool_->RecordTaskRunTime(
- nullptr, task_timing->start_time(), task_timing->end_time());
+ find_in_page_budget_pool_->RecordTaskRunTime(task_timing->start_time(),
+ task_timing->end_time());
}
- bool is_exhausted = !find_in_page_budget_pool_->CanRunTasksAt(
- task_timing->end_time(), false /* is_wake_up */);
+ bool is_exhausted =
+ !find_in_page_budget_pool_->CanRunTasksAt(task_timing->end_time());
QueuePriority task_priority = is_exhausted
? kFindInPageBudgetExhaustedPriority
: kFindInPageBudgetNotExhaustedPriority;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h
index 5042b6a0e39..37a04f8ccb2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h
@@ -7,7 +7,6 @@
#include "base/task/sequence_manager/task_queue.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
@@ -20,8 +19,7 @@ using QueuePriority = base::sequence_manager::TaskQueue::QueuePriority;
class CPUTimeBudgetPool;
class MainThreadSchedulerImpl;
-class PLATFORM_EXPORT FindInPageBudgetPoolController
- : public BudgetPoolController {
+class PLATFORM_EXPORT FindInPageBudgetPoolController {
public:
static constexpr auto kFindInPageBudgetNotExhaustedPriority =
QueuePriority::kVeryHighPriority;
@@ -29,25 +27,13 @@ class PLATFORM_EXPORT FindInPageBudgetPoolController
QueuePriority::kNormalPriority;
explicit FindInPageBudgetPoolController(MainThreadSchedulerImpl* scheduler);
- ~FindInPageBudgetPoolController() override;
+ ~FindInPageBudgetPoolController();
void OnTaskCompleted(MainThreadTaskQueue* queue,
TaskQueue::TaskTiming* task_timing);
QueuePriority CurrentTaskPriority() { return task_priority_; }
- // Unimplemented methods.
- // TODO(crbug.com/1056512): Remove these functions once we factor out the
- // budget calculating logic from BudgetPoolController.
- void UpdateQueueSchedulingLifecycleState(base::TimeTicks now,
- TaskQueue* queue) override {}
- void AddQueueToBudgetPool(TaskQueue* queue,
- BudgetPool* budget_pool) override {}
- void RemoveQueueFromBudgetPool(TaskQueue* queue,
- BudgetPool* budget_pool) override {}
- void UnregisterBudgetPool(BudgetPool* budget_pool) override {}
- bool IsThrottled(TaskQueue* queue) const override { return false; }
-
private:
MainThreadSchedulerImpl* scheduler_; // Not owned.
std::unique_ptr<CPUTimeBudgetPool> find_in_page_budget_pool_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc
index 631724eda29..ca7405afacd 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
namespace blink {
@@ -31,8 +30,6 @@ const char* FrameOriginTypeToString(FrameOriginType origin) {
return "same-origin-to-main-frame";
case FrameOriginType::kCrossOriginToMainFrame:
return "cross-origin-to-main-frame";
- case FrameOriginType::kCount:
- NOTREACHED();
}
NOTREACHED();
return nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h
index 573ba2f4afd..a6ccf25c2db 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h
@@ -16,8 +16,7 @@ enum class FrameOriginType {
kMainFrame = 0,
kSameOriginToMainFrame = 1,
kCrossOriginToMainFrame = 2,
- // TODO(dcheng): Get rid of this and use the kMaxValue idiom.
- kCount = 3,
+ kMaxValue = kCrossOriginToMainFrame,
};
FrameOriginType GetFrameOriginType(FrameScheduler* frame_scheduler);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 99e62ba04e6..7ba83284ffb 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
@@ -30,11 +30,11 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_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/main_thread/task_type_names.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
@@ -193,6 +193,11 @@ FrameSchedulerImpl::FrameSchedulerImpl(
"FrameScheduler.KeepActive",
&tracing_controller_,
KeepActiveStateToString),
+ waiting_for_dom_content_loaded_(
+ true,
+ "FrameScheduler.WaitingForDOMContentLoaded",
+ &tracing_controller_,
+ YesNoStateToString),
waiting_for_contentful_paint_(true,
"FrameScheduler.WaitingForContentfulPaint",
&tracing_controller_,
@@ -201,6 +206,10 @@ FrameSchedulerImpl::FrameSchedulerImpl(
"FrameScheduler.WaitingForMeaningfulPaint",
&tracing_controller_,
YesNoStateToString),
+ waiting_for_load_(true,
+ "FrameScheduler.WaitingForLoad",
+ &tracing_controller_,
+ YesNoStateToString),
loading_power_mode_voter_(
power_scheduler::PowerModeArbiter::GetInstance()->NewVoter(
"PowerModeVoter.Loading")) {
@@ -277,12 +286,39 @@ void FrameSchedulerImpl::RemoveThrottleableQueueFromBudgetPools(
: base::sequence_manager::LazyNow(base::TimeTicks::Now());
if (cpu_time_budget_pool) {
- cpu_time_budget_pool->RemoveQueue(lazy_now.Now(),
- task_queue->GetTaskQueue());
+ task_queue->RemoveFromBudgetPool(lazy_now.Now(), cpu_time_budget_pool);
}
- parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(
- task_queue, frame_origin_type_, &lazy_now);
+ parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(task_queue,
+ &lazy_now);
+}
+
+void FrameSchedulerImpl::MoveTaskQueuesToCorrectWakeUpBudgetPool() {
+ base::sequence_manager::LazyNow lazy_now(
+ main_thread_scheduler_->tick_clock());
+
+ // The WakeUpBudgetPool is selected based on origin state, frame visibility
+ // and page background state.
+ //
+ // For each throttled queue, check if it should be in a different
+ // WakeUpBudgetPool and make the necessary adjustments.
+ for (const auto& task_queue_and_voter :
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) {
+ auto* task_queue = task_queue_and_voter.first;
+ if (!task_queue->CanBeThrottled())
+ continue;
+
+ auto* new_wake_up_budget_pool = parent_page_scheduler_->GetWakeUpBudgetPool(
+ task_queue, frame_origin_type_, frame_visible_);
+ if (task_queue->GetWakeUpBudgetPool() == new_wake_up_budget_pool) {
+ continue;
+ }
+
+ parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(task_queue,
+ &lazy_now);
+ parent_page_scheduler_->AddQueueToWakeUpBudgetPool(
+ task_queue, frame_origin_type_, frame_visible_, &lazy_now);
+ }
}
void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
@@ -291,6 +327,8 @@ void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
return;
UMA_HISTOGRAM_BOOLEAN("RendererScheduler.IPC.FrameVisibility", frame_visible);
frame_visible_ = frame_visible;
+
+ MoveTaskQueuesToCorrectWakeUpBudgetPool();
UpdatePolicy();
}
@@ -305,39 +343,13 @@ void FrameSchedulerImpl::SetCrossOriginToMainFrame(bool cross_origin) {
return;
}
- base::sequence_manager::LazyNow lazy_now(
- main_thread_scheduler_->tick_clock());
-
- // Remove throttleable TaskQueues from their current WakeUpBudgetPool.
- //
- // The WakeUpBudgetPool is selected based on origin. TaskQueues are reinserted
- // in the appropriate WakeUpBudgetPool at the end of this method, after the
- // |frame_origin_type_| is updated.
- for (const auto& task_queue_and_voter :
- frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) {
- if (task_queue_and_voter.first->CanBeThrottled()) {
- parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(
- task_queue_and_voter.first, frame_origin_type_, &lazy_now);
- }
- }
-
- // Update the FrameOriginType.
if (cross_origin) {
frame_origin_type_ = FrameOriginType::kCrossOriginToMainFrame;
} else {
frame_origin_type_ = FrameOriginType::kSameOriginToMainFrame;
}
- // Add throttleable TaskQueues to WakeUpBudgetPool that corresponds to the
- // updated |frame_origin_type_|.
- for (const auto& task_queue_and_voter :
- frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) {
- if (task_queue_and_voter.first->CanBeThrottled()) {
- parent_page_scheduler_->AddQueueToWakeUpBudgetPool(
- task_queue_and_voter.first, frame_origin_type_, &lazy_now);
- }
- }
-
+ MoveTaskQueuesToCorrectWakeUpBudgetPool();
UpdatePolicy();
}
@@ -386,12 +398,8 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) {
return ThrottleableTaskQueueTraits().SetPrioritisationType(
QueueTraits::PrioritisationType::kBestEffort);
case TaskType::kJavascriptTimerDelayedLowNesting:
- return ThrottleableTaskQueueTraits()
- .SetPrioritisationType(
- QueueTraits::PrioritisationType::kJavaScriptTimer)
- .SetCanBeIntensivelyThrottled(
- IsIntensiveWakeUpThrottlingEnabled() &&
- CanIntensivelyThrottleLowNestingLevel());
+ return ThrottleableTaskQueueTraits().SetPrioritisationType(
+ QueueTraits::PrioritisationType::kJavaScriptTimer);
case TaskType::kJavascriptTimerDelayedHighNesting:
return ThrottleableTaskQueueTraits()
.SetPrioritisationType(
@@ -493,6 +501,27 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) {
// Navigation IPCs do not run using virtual time to avoid hanging.
case TaskType::kInternalNavigationAssociatedUnfreezable:
return DoesNotUseVirtualTimeTaskQueueTraits();
+ case TaskType::kInternalPostMessageForwarding:
+ // postMessages to remote frames hop through the scheduler so that any
+ // IPCs generated in the same task arrive first. These tasks must be
+ // pausable in order to maintain this invariant, otherwise they might run
+ // in a nested event loop before the task completes, e.g. debugger
+ // breakpoints or javascript dialogs.
+ if (base::FeatureList::IsEnabled(
+ kDisablePrioritizedPostMessageForwarding)) {
+ // This matches the pre-kInternalPostMessageForwarding behavior.
+ return PausableTaskQueueTraits();
+ } else {
+ // Freezing this task type would prevent transmission of postMessages to
+ // remote frames that occurred in unfreezable tasks or from tasks that
+ // ran prior to being frozen (e.g. freeze event handler), which is not
+ // desirable. The messages are still queued on the receiving side, which
+ // is where frozenness should be assessed.
+ return PausableTaskQueueTraits()
+ .SetCanBeFrozen(false)
+ .SetPrioritisationType(
+ QueueTraits::PrioritisationType::kPostMessageForwarding);
+ }
case TaskType::kDeprecatedNone:
case TaskType::kMainThreadTaskQueueV8:
case TaskType::kMainThreadTaskQueueCompositor:
@@ -512,7 +541,6 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) {
// The associated TaskRunner should be obtained by creating a
// WebSchedulingTaskQueue with CreateWebSchedulingTaskQueue().
case TaskType::kExperimentalWebScheduling:
- case TaskType::kCount:
// Not a valid frame-level TaskType.
NOTREACHED();
return QueueTraits();
@@ -632,16 +660,24 @@ void FrameSchedulerImpl::DidCommitProvisionalLoad(
loading_power_mode_voter_->ResetVoteAfterTimeout(
power_scheduler::PowerModeVoter::kStuckLoadingTimeout);
+ waiting_for_dom_content_loaded_ = true;
waiting_for_contentful_paint_ = true;
waiting_for_meaningful_paint_ = true;
+ waiting_for_load_ = true;
+
+ // If DeprioritizeDOMTimersDuringPageLoading is enabled, UpdatePolicy()
+ // needs to be called to change JavaScript timer task queues to low priority
+ // during reload and other navigations.
+ //
+ // TODO(shaseley): Think about merging this with MainThreadSchedulerImpl's
+ // policy update.
+ if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading)) {
+ UpdatePolicy();
+ }
}
if (is_main_frame && !is_same_document) {
task_time_ = base::TimeDelta();
- // Ignore result here, based on the assumption that
- // MTSI::DidCommitProvisionalLoad will trigger an update policy.
- ignore_result(main_thread_scheduler_->agent_scheduling_strategy()
- .OnDocumentChangedInMainFrame(*this));
}
main_thread_scheduler_->DidCommitProvisionalLoad(
@@ -941,9 +977,20 @@ SchedulingLifecycleState FrameSchedulerImpl::CalculateLifecycleState(
void FrameSchedulerImpl::OnFirstContentfulPaintInMainFrame() {
waiting_for_contentful_paint_ = false;
DCHECK_EQ(GetFrameType(), FrameScheduler::FrameType::kMainFrame);
+ parent_page_scheduler_->OnFirstContentfulPaintInMainFrame();
main_thread_scheduler_->OnMainFramePaint();
}
+void FrameSchedulerImpl::OnDomContentLoaded() {
+ waiting_for_dom_content_loaded_ = false;
+
+ if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) &&
+ kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kOnDOMContentLoaded) {
+ UpdatePolicy();
+ }
+}
+
void FrameSchedulerImpl::OnFirstMeaningfulPaint() {
waiting_for_meaningful_paint_ = false;
@@ -951,20 +998,20 @@ void FrameSchedulerImpl::OnFirstMeaningfulPaint() {
return;
main_thread_scheduler_->OnMainFramePaint();
-
- if (main_thread_scheduler_->agent_scheduling_strategy()
- .OnMainFrameFirstMeaningfulPaint(*this) ==
- AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) {
- main_thread_scheduler_->OnAgentStrategyUpdated();
- }
}
void FrameSchedulerImpl::OnLoad() {
- if (GetFrameType() == FrameScheduler::FrameType::kMainFrame) {
- // TODO(talp): Once MTSI::UpdatePolicyLocked is refactored, this can notify
- // the agent strategy directly and, if necessary, trigger the queue priority
- // update.
- main_thread_scheduler_->OnMainFrameLoad(*this);
+ waiting_for_load_ = false;
+
+ // FrameSchedulerImpl::OnFirstContentfulPaint() is NOT guaranteed to be called
+ // during the loading process, so we also try to do the recomputation in case
+ // of the DeprioritizeDOMTimersPhase::kFirstContentfulPaint option.
+ if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) &&
+ (kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kOnLoad ||
+ kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kFirstContentfulPaint)) {
+ UpdatePolicy();
}
loading_power_mode_voter_->ResetVoteAfterTimeout(
@@ -988,18 +1035,15 @@ bool FrameSchedulerImpl::IsOrdinary() const {
bool FrameSchedulerImpl::ShouldThrottleTaskQueues() const {
DCHECK(parent_page_scheduler_);
+ if (parent_page_scheduler_->ThrottleForegroundTimers())
+ return true;
if (!RuntimeEnabledFeatures::TimerThrottlingForBackgroundTabsEnabled())
return false;
if (parent_page_scheduler_->IsAudioPlaying())
return false;
if (!parent_page_scheduler_->IsPageVisible())
return true;
- if (base::FeatureList::IsEnabled(kThrottleVisibleNotFocusedTimers) &&
- !parent_page_scheduler_->IsPageFocused()) {
- return true;
- }
- return RuntimeEnabledFeatures::TimerThrottlingForHiddenFramesEnabled() &&
- !frame_visible_ && IsCrossOriginToMainFrame();
+ return !frame_visible_ && IsCrossOriginToMainFrame();
}
bool FrameSchedulerImpl::IsExemptFromBudgetBasedThrottling() const {
@@ -1029,6 +1073,9 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
return TaskQueue::QueuePriority::kVeryHighPriority;
case MainThreadTaskQueue::QueueTraits::PrioritisationType::kBestEffort:
return TaskQueue::QueuePriority::kBestEffortPriority;
+ case MainThreadTaskQueue::QueueTraits::PrioritisationType::
+ kPostMessageForwarding:
+ return TaskQueue::QueuePriority::kVeryHighPriority;
default:
break;
}
@@ -1128,14 +1175,6 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
}
}
- // Consult per-agent scheduling strategy to see if it wants to affect queue
- // priority. Done here to avoid interfering with other policy decisions.
- absl::optional<TaskQueue::QueuePriority> per_agent_priority =
- main_thread_scheduler_->agent_scheduling_strategy().QueuePriority(
- *task_queue);
- if (per_agent_priority.has_value())
- return per_agent_priority.value();
-
if (task_queue->GetPrioritisationType() ==
MainThreadTaskQueue::QueueTraits::PrioritisationType::kLoadingControl) {
return main_thread_scheduler_->should_prioritize_loading_with_compositing()
@@ -1160,6 +1199,23 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
return TaskQueue::QueuePriority::kHighestPriority;
}
+ // Deprioritize JS timer tasks to speed up the page loading process.
+ if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) &&
+ task_queue->GetPrioritisationType() ==
+ MainThreadTaskQueue::QueueTraits::PrioritisationType::
+ kJavaScriptTimer &&
+ waiting_for_load_ &&
+ (kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kOnLoad ||
+ (kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kOnDOMContentLoaded &&
+ waiting_for_dom_content_loaded_) ||
+ (kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kFirstContentfulPaint &&
+ parent_page_scheduler_->IsWaitingForMainFrameContentfulPaint()))) {
+ return TaskQueue::QueuePriority::kLowPriority;
+ }
+
if (task_queue->GetPrioritisationType() ==
MainThreadTaskQueue::QueueTraits::PrioritisationType::kInput &&
base::FeatureList::IsEnabled(
@@ -1235,12 +1291,11 @@ void FrameSchedulerImpl::OnTaskQueueCreated(
CPUTimeBudgetPool* cpu_time_budget_pool =
parent_page_scheduler_->background_cpu_time_budget_pool();
if (cpu_time_budget_pool) {
- cpu_time_budget_pool->AddQueue(lazy_now.Now(),
- task_queue->GetTaskQueue());
+ task_queue->AddToBudgetPool(lazy_now.Now(), cpu_time_budget_pool);
}
parent_page_scheduler_->AddQueueToWakeUpBudgetPool(
- task_queue, frame_origin_type_, &lazy_now);
+ task_queue, frame_origin_type_, frame_visible_, &lazy_now);
if (task_queues_throttled_) {
MainThreadTaskQueue::ThrottleHandle handle = task_queue->Throttle();
@@ -1342,12 +1397,24 @@ FrameSchedulerImpl::GetDocumentBoundWeakPtr() {
std::unique_ptr<WebSchedulingTaskQueue>
FrameSchedulerImpl::CreateWebSchedulingTaskQueue(
WebSchedulingPriority priority) {
- // Use QueueTraits here that are the same as postMessage, which is one current
- // method for scheduling script.
- scoped_refptr<MainThreadTaskQueue> task_queue =
+ // The QueueTraits for scheduler.postTask() are similar to those of
+ // setTimeout() (deferrable queue traits + throttling for delayed tasks), with
+ // the following differences:
+ // 1. All delayed tasks are intensively throttled (no nesting-level exception
+ // or policy/flag opt-out)
+ // 2. There is no separate PrioritisationType (prioritization is based on the
+ // WebSchedulingPriority, which is only set for these task queues)
+ scoped_refptr<MainThreadTaskQueue> immediate_task_queue =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- PausableTaskQueueTraits(), priority);
- return std::make_unique<WebSchedulingTaskQueueImpl>(task_queue->AsWeakPtr());
+ DeferrableTaskQueueTraits(), priority);
+ scoped_refptr<MainThreadTaskQueue> delayed_task_queue =
+ frame_task_queue_controller_->NewWebSchedulingTaskQueue(
+ DeferrableTaskQueueTraits()
+ .SetCanBeThrottled(true)
+ .SetCanBeIntensivelyThrottled(true),
+ priority);
+ return std::make_unique<MainThreadWebSchedulingTaskQueueImpl>(
+ immediate_task_queue->AsWeakPtr(), delayed_task_queue->AsWeakPtr());
}
void FrameSchedulerImpl::OnWebSchedulingTaskQueuePriorityChanged(
@@ -1356,6 +1423,18 @@ void FrameSchedulerImpl::OnWebSchedulingTaskQueuePriorityChanged(
frame_task_queue_controller_->GetQueueEnabledVoter(queue));
}
+void FrameSchedulerImpl::OnWebSchedulingTaskQueueDestroyed(
+ MainThreadTaskQueue* queue) {
+ if (queue->CanBeThrottled())
+ RemoveThrottleableQueueFromBudgetPools(queue);
+
+ CleanUpQueue(queue);
+
+ // After this is called, the queue will be destroyed. Do not attempt
+ // to use it further.
+ frame_task_queue_controller_->RemoveWebSchedulingTaskQueue(queue);
+}
+
const base::UnguessableToken& FrameSchedulerImpl::GetAgentClusterId() const {
if (!delegate_)
return base::UnguessableToken::Null();
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 fb3459936b3..3d605531049 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
@@ -11,7 +11,6 @@
#include <utility>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
@@ -19,7 +18,6 @@
#include "components/power_scheduler/power_mode_voter.h"
#include "net/base/request_priority.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
@@ -78,6 +76,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
FrameScheduler::Delegate* delegate,
base::trace_event::BlameContext* blame_context,
FrameScheduler::FrameType frame_type);
+ FrameSchedulerImpl(const FrameSchedulerImpl&) = delete;
+ FrameSchedulerImpl& operator=(const FrameSchedulerImpl&) = delete;
~FrameSchedulerImpl() override;
// FrameOrWorkerScheduler implementation:
@@ -122,6 +122,7 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
WebScopedVirtualTimePauser::VirtualTaskDuration duration) override;
void OnFirstContentfulPaintInMainFrame() override;
+ void OnDomContentLoaded() override;
void OnFirstMeaningfulPaint() override;
void OnLoad() override;
bool IsWaitingForContentfulPaint() const;
@@ -199,6 +200,7 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue(
WebSchedulingPriority) override;
void OnWebSchedulingTaskQueuePriorityChanged(MainThreadTaskQueue*);
+ void OnWebSchedulingTaskQueueDestroyed(MainThreadTaskQueue*);
const base::UnguessableToken& GetAgentClusterId() const;
@@ -242,12 +244,14 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
// loading in the frame until the reference is released during destruction.
explicit PauseSubresourceLoadingHandleImpl(
base::WeakPtr<FrameSchedulerImpl> frame_scheduler);
+ PauseSubresourceLoadingHandleImpl(
+ const PauseSubresourceLoadingHandleImpl&) = delete;
+ PauseSubresourceLoadingHandleImpl& operator=(
+ const PauseSubresourceLoadingHandleImpl&) = delete;
~PauseSubresourceLoadingHandleImpl() override;
private:
base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(PauseSubresourceLoadingHandleImpl);
};
void DetachFromPageScheduler();
@@ -292,6 +296,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
void NotifyDelegateAboutFeaturesAfterCurrentTask();
+ void MoveTaskQueuesToCorrectWakeUpBudgetPool();
+
// Create QueueTraits for the default (non-finch) task queues.
static MainThreadTaskQueue::QueueTraits ThrottleableTaskQueueTraits();
static MainThreadTaskQueue::QueueTraits DeferrableTaskQueueTraits();
@@ -373,9 +379,12 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
page_keep_active_for_tracing_;
TraceableState<bool, TracingCategoryName::kInfo>
+ waiting_for_dom_content_loaded_;
+ TraceableState<bool, TracingCategoryName::kInfo>
waiting_for_contentful_paint_;
TraceableState<bool, TracingCategoryName::kInfo>
waiting_for_meaningful_paint_;
+ TraceableState<bool, TracingCategoryName::kInfo> waiting_for_load_;
std::unique_ptr<power_scheduler::PowerModeVoter> loading_power_mode_voter_;
@@ -390,8 +399,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
invalidating_on_bfcache_restore_weak_factory_{this};
mutable base::WeakPtrFactory<FrameSchedulerImpl> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(FrameSchedulerImpl);
};
} // namespace scheduler
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 cdd2232bff4..16cb3343af1 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
@@ -16,6 +16,7 @@
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.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/task/thread_pool.h"
#include "base/test/bind.h"
@@ -23,6 +24,7 @@
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
+#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -58,6 +60,8 @@ namespace {
constexpr base::TimeDelta kDefaultThrottledWakeUpInterval =
PageSchedulerImpl::kDefaultThrottledWakeUpInterval;
+constexpr base::TimeDelta kIntensiveThrottledWakeUpInterval =
+ PageSchedulerImpl::kIntensiveThrottledWakeUpInterval;
constexpr auto kShortDelay = base::TimeDelta::FromMilliseconds(10);
// This is a wrapper around MainThreadSchedulerImpl::CreatePageScheduler, that
@@ -149,10 +153,11 @@ constexpr TaskType kAllFrameTaskTypes[] = {
TaskType::kInternalHighPriorityLocalFrame,
TaskType::kInternalInputBlocking,
TaskType::kWakeLock,
- TaskType::kWebGPU};
+ TaskType::kWebGPU,
+ TaskType::kInternalPostMessageForwarding};
static_assert(
- static_cast<int>(TaskType::kCount) == 79,
+ static_cast<int>(TaskType::kMaxValue) == 79,
"When adding a TaskType, make sure that kAllFrameTaskTypes is updated.");
void AppendToVectorTestTask(Vector<String>* vector, String value) {
@@ -411,6 +416,27 @@ class FrameSchedulerImplTest : public testing::Test {
PrioritisationType::kJavaScriptTimer));
}
+ scoped_refptr<MainThreadTaskQueue>
+ JavaScriptTimerNormalThrottleableTaskQueueForFrame(
+ FrameSchedulerImpl* frame_scheduler) {
+ return GetTaskQueueForFrame(frame_scheduler,
+ TaskType::kJavascriptTimerDelayedLowNesting);
+ }
+
+ scoped_refptr<MainThreadTaskQueue>
+ JavaScriptTimerIntensivelyThrottleableTaskQueueForFrame(
+ FrameSchedulerImpl* frame_scheduler) {
+ return GetTaskQueueForFrame(frame_scheduler,
+ TaskType::kJavascriptTimerDelayedHighNesting);
+ }
+
+ scoped_refptr<MainThreadTaskQueue>
+ JavaScriptTimerNonThrottleableTaskQueueForFrame(
+ FrameSchedulerImpl* frame_scheduler) {
+ return GetTaskQueueForFrame(frame_scheduler,
+ TaskType::kJavascriptTimerImmediate);
+ }
+
scoped_refptr<MainThreadTaskQueue> LoadingTaskQueue() {
return GetTaskQueue(FrameSchedulerImpl::LoadingTaskQueueTraits());
}
@@ -448,6 +474,12 @@ class FrameSchedulerImplTest : public testing::Test {
return frame_scheduler_->GetTaskQueue(type);
}
+ scoped_refptr<MainThreadTaskQueue> GetTaskQueueForFrame(
+ FrameSchedulerImpl* frame_scheduler,
+ TaskType type) {
+ return frame_scheduler->GetTaskQueue(type);
+ }
+
std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl>
GetResourceLoadingTaskRunnerHandleImpl() {
return frame_scheduler_->CreateResourceLoadingTaskRunnerHandleImpl();
@@ -480,6 +512,21 @@ class FrameSchedulerImplTest : public testing::Test {
/*is_web_history_inert_commit=*/false, navigation_type);
}
+ void DidCommitProvisionalLoadForFrame(
+ FrameSchedulerImpl* frame_scheduler,
+ FrameScheduler::NavigationType navigation_type) {
+ frame_scheduler->DidCommitProvisionalLoad(
+ /*is_web_history_inert_commit=*/false, navigation_type);
+ }
+
+ void OnDomContentLoadedForFrame(FrameSchedulerImpl* frame_scheduler) {
+ frame_scheduler->OnDomContentLoaded();
+ }
+
+ void OnLoadForFrame(FrameSchedulerImpl* frame_scheduler) {
+ frame_scheduler->OnLoad();
+ }
+
base::test::ScopedFeatureList& scoped_feature_list() { return feature_list_; }
base::test::ScopedFeatureList feature_list_;
@@ -564,19 +611,9 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase
public:
using Super = FrameSchedulerImplTest;
- explicit FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase(
- bool can_intensively_throttle_low_nesting_level)
- : FrameSchedulerImplTest(
- features::kIntensiveWakeUpThrottling,
- // If |can_intensively_throttle_low_nesting_level| is true, set the
- // feature param to "true". Otherwise, test the default behavior (no
- // feature params).
- can_intensively_throttle_low_nesting_level
- ? base::FieldTrialParams(
- {{kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Name,
- "true"}})
- : base::FieldTrialParams(),
- {features::kStopInBackground}) {}
+ FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase()
+ : FrameSchedulerImplTest({features::kIntensiveWakeUpThrottling},
+ {features::kStopInBackground}) {}
void SetUp() override {
Super::SetUp();
@@ -591,17 +628,12 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase
const int kNumTasks = 5;
const base::TimeDelta kGracePeriod =
GetIntensiveWakeUpThrottlingGracePeriod();
- const base::TimeDelta kIntensiveThrottlingDurationBetweenWakeUps =
- GetIntensiveWakeUpThrottlingDurationBetweenWakeUps();
};
// Test param for FrameSchedulerImplTestWithIntensiveWakeUpThrottling
struct IntensiveWakeUpThrottlingTestParam {
// TaskType used to obtain TaskRunners from the FrameScheduler.
TaskType task_type;
- // Whether the feature param to allow throttling of timers with a low nesting
- // level should be set to "true" at the beginning of the test.
- bool can_intensively_throttle_low_nesting_level;
// Whether it is expected that tasks will be intensively throttled.
bool is_intensive_throttling_expected;
};
@@ -610,28 +642,51 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottling
: public FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase,
public ::testing::WithParamInterface<IntensiveWakeUpThrottlingTestParam> {
public:
- FrameSchedulerImplTestWithIntensiveWakeUpThrottling()
- : FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase(
- GetParam().can_intensively_throttle_low_nesting_level) {}
+ FrameSchedulerImplTestWithIntensiveWakeUpThrottling() = default;
TaskType GetTaskType() const { return GetParam().task_type; }
bool IsIntensiveThrottlingExpected() const {
return GetParam().is_intensive_throttling_expected;
}
+ // Get the TaskRunner from |frame_scheduler_| using the test's task type
+ // parameter.
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
+ return GetTaskRunner(frame_scheduler_.get());
+ }
+
+ // Get the TaskRunner from the provided |frame_scheduler| using the test's
+ // task type parameter.
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
+ FrameSchedulerImpl* frame_scheduler) {
+ const TaskType task_type = GetTaskType();
+ if (task_type == TaskType::kExperimentalWebScheduling) {
+ test_web_scheduling_task_queues_.push_back(
+ frame_scheduler->CreateWebSchedulingTaskQueue(
+ WebSchedulingPriority::kUserVisiblePriority));
+ return test_web_scheduling_task_queues_.back()->GetTaskRunner();
+ }
+ return frame_scheduler->GetTaskRunner(task_type);
+ }
+
base::TimeDelta GetExpectedWakeUpInterval() const {
if (IsIntensiveThrottlingExpected())
- return kIntensiveThrottlingDurationBetweenWakeUps;
+ return kIntensiveThrottledWakeUpInterval;
return kDefaultThrottledWakeUpInterval;
}
+
+ private:
+ // Store web scheduling task queues that are created for tests so
+ // they do not get destroyed. Destroying them before their tasks finish
+ // running will break throttling.
+ Vector<std::unique_ptr<WebSchedulingTaskQueue>>
+ test_web_scheduling_task_queues_;
};
class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride
: public FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase {
public:
- FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride()
- : FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase(
- /* can_intensively_throttle_low_nesting_level=*/false) {}
+ FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride() = default;
// This should only be called once per test, and prior to the
// PageSchedulerImpl logic actually parsing the policy switch.
@@ -657,14 +712,12 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride
// We test both (ExplicitInit/LazyInit) of them.
TEST_F(FrameSchedulerImplTest, PageVisible) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
EXPECT_FALSE(throttleable_task_queue());
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
}
TEST_F(FrameSchedulerImplTest, PageHidden_ExplicitInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
page_scheduler_->SetPageVisible(false);
@@ -672,14 +725,12 @@ TEST_F(FrameSchedulerImplTest, PageHidden_ExplicitInit) {
}
TEST_F(FrameSchedulerImplTest, PageHidden_LazyInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
page_scheduler_->SetPageVisible(false);
LazyInitThrottleableTaskQueue();
EXPECT_TRUE(IsThrottled());
}
TEST_F(FrameSchedulerImplTest, PageHiddenThenVisible_ExplicitInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
page_scheduler_->SetPageVisible(false);
@@ -692,7 +743,6 @@ TEST_F(FrameSchedulerImplTest, PageHiddenThenVisible_ExplicitInit) {
TEST_F(FrameSchedulerImplTest,
FrameHiddenThenVisible_CrossOrigin_ExplicitInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
frame_scheduler_->SetFrameVisible(false);
@@ -708,33 +758,13 @@ TEST_F(FrameSchedulerImplTest,
}
TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_LazyInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
frame_scheduler_->SetFrameVisible(false);
frame_scheduler_->SetCrossOriginToMainFrame(true);
LazyInitThrottleableTaskQueue();
EXPECT_TRUE(IsThrottled());
}
-TEST_F(FrameSchedulerImplTest,
- FrameHidden_CrossOrigin_NoThrottling_ExplicitInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
- LazyInitThrottleableTaskQueue();
- EXPECT_FALSE(IsThrottled());
- frame_scheduler_->SetFrameVisible(false);
- frame_scheduler_->SetCrossOriginToMainFrame(true);
- EXPECT_FALSE(IsThrottled());
-}
-
-TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_NoThrottling_LazyInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
- frame_scheduler_->SetFrameVisible(false);
- frame_scheduler_->SetCrossOriginToMainFrame(true);
- LazyInitThrottleableTaskQueue();
- EXPECT_FALSE(IsThrottled());
-}
-
TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_ExplicitInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
frame_scheduler_->SetFrameVisible(false);
@@ -742,14 +772,12 @@ TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_ExplicitInit) {
}
TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_LazyInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
frame_scheduler_->SetFrameVisible(false);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
}
TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_ExplicitInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
EXPECT_TRUE(throttleable_task_queue());
@@ -760,7 +788,6 @@ TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_ExplicitInit) {
}
TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_LazyInit) {
- ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
frame_scheduler_->SetFrameVisible(true);
frame_scheduler_->SetCrossOriginToMainFrame(true);
LazyInitThrottleableTaskQueue();
@@ -844,8 +871,6 @@ void RePostTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
// Disable the kStopInBackground feature because it hides the effect of
// intensive wake up throttling.
TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) {
- constexpr auto kTaskPeriod = base::TimeDelta::FromSeconds(1);
-
// This TaskRunner is throttled.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
frame_scheduler_->GetTaskRunner(GetParam());
@@ -859,7 +884,7 @@ TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) {
int num_remaining_tasks =
base::TimeDelta::FromSeconds(
kIntensiveWakeUpThrottling_GracePeriodSeconds_Default)
- .IntDiv(kTaskPeriod);
+ .IntDiv(kDefaultThrottledWakeUpInterval);
task_runner->PostDelayedTask(
FROM_HERE,
base::BindOnce(&RePostTask, task_runner, kShortDelay,
@@ -869,7 +894,7 @@ TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) {
// A task should run every second.
while (num_remaining_tasks > 0) {
int previous_num_remaining_tasks = num_remaining_tasks;
- task_environment_.FastForwardBy(kTaskPeriod);
+ task_environment_.FastForwardBy(kDefaultThrottledWakeUpInterval);
EXPECT_EQ(previous_num_remaining_tasks - 1, num_remaining_tasks);
}
@@ -886,9 +911,8 @@ TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) {
// otherwise.
const base::TimeDelta expected_period_after_grace_period =
(GetParam() == TaskType::kJavascriptTimerDelayedLowNesting)
- ? kTaskPeriod
- : base::TimeDelta::FromSeconds(
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default);
+ ? kDefaultThrottledWakeUpInterval
+ : kIntensiveThrottledWakeUpInterval;
while (num_remaining_tasks > 0) {
int previous_num_remaining_tasks = num_remaining_tasks;
@@ -911,13 +935,13 @@ TEST_F(FrameSchedulerImplTest, FreezeForegroundOnlyTasks) {
ForegroundOnlyTaskQueue()->GetTaskRunnerWithDefaultTaskType()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- page_scheduler_->SetPageVisible(false);
+ frame_scheduler_->SetFrameVisible(false);
EXPECT_EQ(0, counter);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, counter);
- page_scheduler_->SetPageVisible(true);
+ frame_scheduler_->SetFrameVisible(true);
EXPECT_EQ(0, counter);
base::RunLoop().RunUntilIdle();
@@ -2767,7 +2791,8 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
// - 'V': UserVisible
// - 'B': Background
void PostWebSchedulingTestTasks(Vector<String>* run_order,
- const String& task_descriptor) {
+ const String& task_descriptor,
+ base::TimeDelta delay = base::TimeDelta()) {
std::istringstream stream(task_descriptor.Utf8());
while (!stream.eof()) {
std::string task;
@@ -2787,9 +2812,11 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
EXPECT_FALSE(true);
return;
}
- web_scheduling_task_runners_[static_cast<int>(priority)]->PostTask(
- FROM_HERE, base::BindOnce(&AppendToVectorTestTask, run_order,
- String::FromUTF8(task)));
+ web_scheduling_task_runners_[static_cast<int>(priority)]->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&AppendToVectorTestTask, run_order,
+ String::FromUTF8(task)),
+ delay);
}
}
@@ -2821,12 +2848,26 @@ TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) {
testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2"));
}
-// Verify that tasks posted with TaskType::kJavascriptTimerDelayed* run at the
-// expected time when throttled.
+TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrderDelayedTasks) {
+ Vector<String> run_order;
+
+ PostWebSchedulingTestTasks(&run_order, "U1 U2 V1 V2",
+ base::TimeDelta::FromMilliseconds(5));
+ task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)]
+ ->SetPriority(WebSchedulingPriority::kBackgroundPriority);
+
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+
+ EXPECT_THAT(run_order, testing::ElementsAre("V1", "V2", "U1", "U2"));
+}
+
+// Verify that tasks posted with TaskType::kJavascriptTimerDelayed* and
+// delayed web scheduling tasks run at the expected time when throttled.
TEST_F(FrameSchedulerImplTest, ThrottledJSTimerTasksRunTime) {
constexpr TaskType kJavaScriptTimerTaskTypes[] = {
TaskType::kJavascriptTimerDelayedLowNesting,
- TaskType::kJavascriptTimerDelayedHighNesting};
+ TaskType::kJavascriptTimerDelayedHighNesting,
+ TaskType::kExperimentalWebScheduling};
// Snap the time to a multiple of 1 second. Otherwise, the exact run time
// of throttled tasks after hiding the page will vary.
@@ -2838,10 +2879,20 @@ TEST_F(FrameSchedulerImplTest, ThrottledJSTimerTasksRunTime) {
std::map<TaskType, std::vector<base::TimeTicks>> run_times;
- // Post tasks with each Javascript Timer Task Type.
+ // Create the web scheduler task queue outside of the scope of the for loop.
+ // This is necessary because otherwise the queue is deleted before tasks run,
+ // and this breaks throttling.
+ std::unique_ptr<WebSchedulingTaskQueue> web_scheduling_task_queue =
+ frame_scheduler_->CreateWebSchedulingTaskQueue(
+ WebSchedulingPriority::kUserVisiblePriority);
+
+ // Post tasks with each Javascript Timer Task Type and with a
+ // WebSchedulingTaskQueue.
for (TaskType task_type : kJavaScriptTimerTaskTypes) {
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame_scheduler_->GetTaskRunner(task_type);
+ task_type == TaskType::kExperimentalWebScheduling
+ ? web_scheduling_task_queue->GetTaskRunner()
+ : frame_scheduler_->GetTaskRunner(task_type);
// Note: Taking the address of an element in |run_times| is safe because
// inserting elements in a map does not invalidate references.
@@ -2950,12 +3001,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
// Throttled TaskRunner to which tasks are posted in this test.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame_scheduler_->GetTaskRunner(GetTaskType());
+ GetTaskRunner();
// Snap the time to a multiple of
- // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which
+ // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which
// tasks can run after throttling is enabled will vary.
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
const base::TimeTicks test_start = base::TimeTicks::Now();
// Hide the page. This starts the delay to throttle background wake ups.
@@ -2975,12 +3026,13 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
}
task_environment_.FastForwardBy(kGracePeriod);
- EXPECT_THAT(run_times, testing::ElementsAre(
- scope_start + base::TimeDelta::FromSeconds(1),
- scope_start + base::TimeDelta::FromSeconds(2),
- scope_start + base::TimeDelta::FromSeconds(3),
- scope_start + base::TimeDelta::FromSeconds(4),
- scope_start + base::TimeDelta::FromSeconds(5)));
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
+ scope_start + kDefaultThrottledWakeUpInterval,
+ scope_start + 2 * kDefaultThrottledWakeUpInterval,
+ scope_start + 3 * kDefaultThrottledWakeUpInterval,
+ scope_start + 4 * kDefaultThrottledWakeUpInterval,
+ scope_start + 5 * kDefaultThrottledWakeUpInterval));
}
// After the grace period:
@@ -3015,7 +3067,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
kShortDelay + i * kDefaultThrottledWakeUpInterval);
}
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
if (IsIntensiveThrottlingExpected()) {
const base::TimeTicks aligned_time =
@@ -3046,7 +3098,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
base::BindOnce(&RecordRunTime, &run_times),
kDefaultThrottledWakeUpInterval);
- task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps);
+ task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval);
EXPECT_THAT(run_times, testing::ElementsAre(scope_start +
GetExpectedWakeUpInterval()));
@@ -3062,8 +3114,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
std::vector<base::TimeTicks> run_times;
const base::TimeDelta kLongDelay =
- kIntensiveThrottlingDurationBetweenWakeUps * 5 +
- kDefaultThrottledWakeUpInterval;
+ kIntensiveThrottledWakeUpInterval * 5 + kDefaultThrottledWakeUpInterval;
task_runner->PostDelayedTask(
FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kLongDelay);
@@ -3090,7 +3141,6 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
FROM_HERE, base::BindOnce(&RecordRunTime, &run_times),
kDefaultThrottledWakeUpInterval * (i + 1));
}
- page_scheduler_->OnTitleOrFaviconUpdated();
}),
kDefaultThrottledWakeUpInterval);
@@ -3128,12 +3178,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
// Throttled TaskRunner to which tasks are posted in this test.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame_scheduler_->GetTaskRunner(GetTaskType());
+ GetTaskRunner();
// Snap the time to a multiple of
- // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which
+ // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which
// tasks can run after throttling is enabled will vary.
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
const base::TimeTicks test_start = base::TimeTicks::Now();
// Hide the page. This starts the delay to throttle background wake ups.
@@ -3176,7 +3226,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
base::BindOnce(&RecordRunTime, &run_times),
kDefaultThrottledWakeUpInterval);
- task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps);
+ task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval);
EXPECT_THAT(run_times, testing::ElementsAre(scope_start +
GetExpectedWakeUpInterval()));
}
@@ -3195,11 +3245,11 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
kShortDelay + i * kDefaultThrottledWakeUpInterval);
}
- task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps);
+ task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval);
if (IsIntensiveThrottlingExpected()) {
const base::TimeTicks aligned_time =
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps;
+ scope_start + kIntensiveThrottledWakeUpInterval;
EXPECT_THAT(run_times,
testing::ElementsAre(aligned_time, aligned_time, aligned_time,
aligned_time, aligned_time));
@@ -3226,7 +3276,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
base::BindOnce(&RecordRunTime, &run_times),
kDefaultThrottledWakeUpInterval);
- task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps);
+ task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval);
EXPECT_THAT(run_times, testing::ElementsAre(scope_start +
GetExpectedWakeUpInterval()));
}
@@ -3241,8 +3291,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
EXPECT_EQ(scope_start, test_start + base::TimeDelta::FromMinutes(8));
std::vector<base::TimeTicks> run_times;
- const base::TimeDelta kLongDelay =
- kIntensiveThrottlingDurationBetweenWakeUps * 6;
+ const base::TimeDelta kLongDelay = kIntensiveThrottledWakeUpInterval * 6;
task_runner->PostDelayedTask(FROM_HERE,
base::BindOnce(&RecordRunTime, &run_times),
kLongDelay - kShortDelay);
@@ -3303,7 +3352,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
ManySameOriginFrames) {
ASSERT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame());
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame_scheduler_->GetTaskRunner(GetTaskType());
+ GetTaskRunner();
// Create a FrameScheduler that is same-origin with the main frame, and an
// associated throttled TaskRunner.
@@ -3313,12 +3362,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
FrameScheduler::FrameType::kSubframe);
ASSERT_FALSE(other_frame_scheduler->IsCrossOriginToMainFrame());
const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner =
- other_frame_scheduler->GetTaskRunner(GetTaskType());
+ GetTaskRunner(other_frame_scheduler.get());
// Snap the time to a multiple of
- // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which
+ // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which
// tasks can run after throttling is enabled will vary.
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
// Hide the page and wait until the intensive throttling grace period has
// elapsed.
@@ -3342,10 +3391,9 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
// last minute. The second task is 1-minute aligned if the TaskType supports
// intensive throttling, or 1-second aligned otherwise.
if (IsIntensiveThrottlingExpected()) {
- EXPECT_THAT(run_times,
- testing::ElementsAre(
- post_time + 2 * kDefaultThrottledWakeUpInterval,
- post_time + kIntensiveThrottlingDurationBetweenWakeUps));
+ EXPECT_THAT(run_times, testing::ElementsAre(
+ post_time + 2 * kDefaultThrottledWakeUpInterval,
+ post_time + kIntensiveThrottledWakeUpInterval));
} else {
EXPECT_THAT(
run_times,
@@ -3360,19 +3408,19 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
constexpr int kNumTasks = 3;
// |task_runner| is throttled.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame_scheduler_->GetTaskRunner(GetTaskType());
+ GetTaskRunner();
// |other_task_runner| is throttled. It belongs to a different frame on the
// same page.
const auto other_frame_scheduler = CreateFrameScheduler(
page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr,
FrameScheduler::FrameType::kSubframe);
const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner =
- frame_scheduler_->GetTaskRunner(GetTaskType());
+ GetTaskRunner(other_frame_scheduler.get());
// Fast-forward the time to a multiple of
- // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise,
+ // |kIntensiveThrottledWakeUpInterval|. Otherwise,
// the time at which tasks can run after throttling is enabled will vary.
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
// Hide the page and wait until the intensive throttling grace period has
// elapsed.
@@ -3384,36 +3432,23 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
// Wake ups are intensively throttled, since there is no throttling opt-out.
const base::TimeTicks scope_start = base::TimeTicks::Now();
std::vector<base::TimeTicks> run_times;
- for (int i = 1; i < kNumTasks + 1; ++i) {
- task_runner->PostDelayedTask(FROM_HERE,
- base::BindOnce(&RecordRunTime, &run_times),
- i * kShortDelay);
- }
- for (int i = 1; i < kNumTasks + 1; ++i) {
- task_runner->PostDelayedTask(
- FROM_HERE, base::BindOnce(&RecordRunTime, &run_times),
- kDefaultThrottledWakeUpInterval + i * kShortDelay);
- }
+ task_runner->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kShortDelay);
+ task_runner->PostDelayedTask(FROM_HERE,
+ base::BindOnce(&RecordRunTime, &run_times),
+ kDefaultThrottledWakeUpInterval + kShortDelay);
task_environment_.FastForwardUntilNoTasksRemain();
if (IsIntensiveThrottlingExpected()) {
- // Note: Wake ups can be unaligned when there is no recent wake up.
- EXPECT_THAT(
- run_times,
- testing::ElementsAre(
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps,
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps,
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps));
- } else {
+ // Note: Intensive throttling is not applied on the 1st task since there
+ // is no recent wake up.
EXPECT_THAT(run_times,
testing::ElementsAre(
scope_start + kDefaultThrottledWakeUpInterval,
+ scope_start + kIntensiveThrottledWakeUpInterval));
+ } else {
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + 2 * kDefaultThrottledWakeUpInterval,
- scope_start + 2 * kDefaultThrottledWakeUpInterval,
scope_start + 2 * kDefaultThrottledWakeUpInterval));
}
}
@@ -3462,44 +3497,31 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
}
// Fast-forward so that there is no recent wake up. Then, align the time on
- // |kIntensiveThrottlingDurationBetweenWakeUps| to simplify expectations.
- task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps);
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ // |kIntensiveThrottledWakeUpInterval| to simplify expectations.
+ task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
{
// Wake ups are intensively throttled, since there is no throttling opt-out.
const base::TimeTicks scope_start = base::TimeTicks::Now();
std::vector<base::TimeTicks> run_times;
- for (int i = 1; i < kNumTasks + 1; ++i) {
- task_runner->PostDelayedTask(FROM_HERE,
- base::BindOnce(&RecordRunTime, &run_times),
- i * kShortDelay);
- }
- for (int i = 1; i < kNumTasks + 1; ++i) {
- task_runner->PostDelayedTask(
- FROM_HERE, base::BindOnce(&RecordRunTime, &run_times),
- kDefaultThrottledWakeUpInterval + i * kShortDelay);
- }
+ task_runner->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kShortDelay);
+ task_runner->PostDelayedTask(FROM_HERE,
+ base::BindOnce(&RecordRunTime, &run_times),
+ kDefaultThrottledWakeUpInterval + kShortDelay);
task_environment_.FastForwardUntilNoTasksRemain();
if (IsIntensiveThrottlingExpected()) {
- // Note: Wake ups can be unaligned when there is no recent wake up.
- EXPECT_THAT(
- run_times,
- testing::ElementsAre(
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps,
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps,
- scope_start + kIntensiveThrottlingDurationBetweenWakeUps));
- } else {
+ // Note: Intensive throttling is not applied on the 1st task since there
+ // is no recent wake up.
EXPECT_THAT(run_times,
testing::ElementsAre(
scope_start + kDefaultThrottledWakeUpInterval,
+ scope_start + kIntensiveThrottledWakeUpInterval));
+ } else {
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + kDefaultThrottledWakeUpInterval,
- scope_start + 2 * kDefaultThrottledWakeUpInterval,
- scope_start + 2 * kDefaultThrottledWakeUpInterval,
scope_start + 2 * kDefaultThrottledWakeUpInterval));
}
}
@@ -3511,7 +3533,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
FrameChangesOriginType) {
EXPECT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame());
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame_scheduler_->GetTaskRunner(GetTaskType());
+ GetTaskRunner();
// Create a new FrameScheduler that remains cross-origin with the main frame
// throughout the test.
@@ -3521,12 +3543,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
FrameScheduler::FrameType::kSubframe);
cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true);
const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner =
- cross_origin_frame_scheduler->GetTaskRunner(GetTaskType());
+ GetTaskRunner(cross_origin_frame_scheduler.get());
// Snap the time to a multiple of
- // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which
+ // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which
// tasks can run after throttling is enabled will vary.
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
// Hide the page and wait until the intensive throttling grace period has
// elapsed.
@@ -3563,7 +3585,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
EXPECT_EQ(1, cross_origin_counter);
}
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
EXPECT_EQ(1, counter);
EXPECT_EQ(1, cross_origin_counter);
}
@@ -3572,8 +3594,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
// Post delayed tasks with long delays that aren't aligned with the wake up
// interval. They should run at aligned times, since they are cross-origin.
const base::TimeDelta kLongUnalignedDelay =
- 5 * kIntensiveThrottlingDurationBetweenWakeUps +
- kDefaultThrottledWakeUpInterval;
+ 5 * kIntensiveThrottledWakeUpInterval + kDefaultThrottledWakeUpInterval;
int counter = 0;
task_runner->PostDelayedTask(
FROM_HERE,
@@ -3599,7 +3620,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling,
EXPECT_EQ(1, cross_origin_counter);
}
- FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps);
+ FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval);
EXPECT_EQ(1, counter);
EXPECT_EQ(1, cross_origin_counter);
}
@@ -3611,22 +3632,15 @@ INSTANTIATE_TEST_SUITE_P(
testing::Values(
IntensiveWakeUpThrottlingTestParam{
/* task_type=*/TaskType::kJavascriptTimerDelayedLowNesting,
- /* can_intensively_throttle_low_nesting_level=*/false,
/* is_intensive_throttling_expected=*/false},
IntensiveWakeUpThrottlingTestParam{
- /* task_type=*/TaskType::kJavascriptTimerDelayedLowNesting,
- /* can_intensively_throttle_low_nesting_level=*/true,
+ /* task_type=*/TaskType::kJavascriptTimerDelayedHighNesting,
/* is_intensive_throttling_expected=*/true},
IntensiveWakeUpThrottlingTestParam{
- /* task_type=*/TaskType::kJavascriptTimerDelayedHighNesting,
- /* can_intensively_throttle_low_nesting_level=*/false,
+ /* task_type=*/TaskType::kExperimentalWebScheduling,
/* is_intensive_throttling_expected=*/true}),
[](const testing::TestParamInfo<IntensiveWakeUpThrottlingTestParam>& info) {
- const std::string task_type =
- TaskTypeNames::TaskTypeToString(info.param.task_type);
- if (info.param.can_intensively_throttle_low_nesting_level)
- return task_type + "_can_intensively_throttle_low_nesting_level";
- return task_type;
+ return TaskTypeNames::TaskTypeToString(info.param.task_type);
});
TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride,
@@ -3638,13 +3652,6 @@ TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride,
EXPECT_EQ(base::TimeDelta::FromSeconds(
kIntensiveWakeUpThrottling_GracePeriodSeconds_Default),
GetIntensiveWakeUpThrottlingGracePeriod());
- EXPECT_EQ(
- base::TimeDelta::FromSeconds(
- kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default),
- GetIntensiveWakeUpThrottlingDurationBetweenWakeUps());
- EXPECT_EQ(
- kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default,
- CanIntensivelyThrottleLowNestingLevel());
}
TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride,
@@ -3653,6 +3660,469 @@ TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride,
EXPECT_FALSE(IsIntensiveWakeUpThrottlingEnabled());
}
+class DeprioritizeDOMTimerTest : public FrameSchedulerImplTest {
+ public:
+ DeprioritizeDOMTimerTest(DeprioritizeDOMTimersPhase phase)
+ : FrameSchedulerImplTest(
+ blink::scheduler::kDeprioritizeDOMTimersDuringPageLoading,
+ base::FieldTrialParams(
+ {{"phase", blink::scheduler::kDeprioritizeDOMTimersPhase
+ .GetName(phase)}}),
+ {}) {}
+
+ void SetUp() override {
+ FrameSchedulerImplTest::SetUp();
+ scheduler_of_main_frame_ = CreateFrameScheduler(
+ page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr,
+ FrameScheduler::FrameType::kMainFrame);
+ }
+
+ void TearDown() override {
+ scheduler_of_main_frame_.reset();
+ FrameSchedulerImplTest::TearDown();
+ }
+
+ void ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ FrameSchedulerImpl* frame_scheduler,
+ TaskQueue::QueuePriority expected_priority) {
+ EXPECT_EQ(
+ JavaScriptTimerNormalThrottleableTaskQueueForFrame(frame_scheduler)
+ ->GetTaskQueue()
+ ->GetQueuePriority(),
+ expected_priority);
+ EXPECT_EQ(
+ JavaScriptTimerIntensivelyThrottleableTaskQueueForFrame(frame_scheduler)
+ ->GetTaskQueue()
+ ->GetQueuePriority(),
+ expected_priority);
+ EXPECT_EQ(JavaScriptTimerNonThrottleableTaskQueueForFrame(frame_scheduler)
+ ->GetTaskQueue()
+ ->GetQueuePriority(),
+ expected_priority);
+ }
+
+ protected:
+ std::unique_ptr<FrameSchedulerImpl> scheduler_of_main_frame_;
+};
+
+class DeprioritizeDOMTimerUntilDOMContentLoadedTest
+ : public DeprioritizeDOMTimerTest {
+ public:
+ DeprioritizeDOMTimerUntilDOMContentLoadedTest()
+ : DeprioritizeDOMTimerTest(
+ DeprioritizeDOMTimersPhase::kOnDOMContentLoaded) {}
+};
+
+// Test whether the JavaScript timer task queues' priorities are properly
+// updated on DOMContentLoaded event for frame load and reloads.
+TEST_F(DeprioritizeDOMTimerUntilDOMContentLoadedTest,
+ MainAndNonMainFrameLoadAndReload) {
+ FrameSchedulerImpl* frame_schedulers[2] = {scheduler_of_main_frame_.get(),
+ frame_scheduler_.get()};
+ for (FrameSchedulerImpl* frame_scheduler : frame_schedulers) {
+ // Initial priority is low.
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal when DOMContentLoaded triggered.
+ OnDomContentLoadedForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+
+ // After reload navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(frame_scheduler,
+ FrameScheduler::NavigationType::kReload);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal when DOMContentLoaded triggered.
+ OnDomContentLoadedForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+
+ // After other type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(frame_scheduler,
+ FrameScheduler::NavigationType::kOther);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal when DOMContentLoaded triggered.
+ OnDomContentLoadedForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+ }
+}
+
+class DeprioritizeDOMTimerUntilFCPTest : public DeprioritizeDOMTimerTest {
+ public:
+ DeprioritizeDOMTimerUntilFCPTest()
+ : DeprioritizeDOMTimerTest(
+ DeprioritizeDOMTimersPhase::kFirstContentfulPaint) {}
+};
+
+// Test whether the JavaScript timer task queues' priorities are properly
+// updated when FCP is triggered for frame load and reloads.
+TEST_F(DeprioritizeDOMTimerUntilFCPTest, MainAndNonMainFrameLoadAndReload) {
+ // Initial priorities are low.
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ scheduler_of_main_frame_.get(), TaskQueue::QueuePriority::kLowPriority);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler_.get(), TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal when FCP triggered.
+ scheduler_of_main_frame_->OnFirstContentfulPaintInMainFrame();
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ scheduler_of_main_frame_.get(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler_.get(), TaskQueue::QueuePriority::kNormalPriority);
+
+ // After reload type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(scheduler_of_main_frame_.get(),
+ FrameScheduler::NavigationType::kReload);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ scheduler_of_main_frame_.get(), TaskQueue::QueuePriority::kLowPriority);
+
+ DidCommitProvisionalLoadForFrame(frame_scheduler_.get(),
+ FrameScheduler::NavigationType::kReload);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler_.get(), TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal when FCP triggered.
+ scheduler_of_main_frame_->OnFirstContentfulPaintInMainFrame();
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ scheduler_of_main_frame_.get(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler_.get(), TaskQueue::QueuePriority::kNormalPriority);
+
+ // After other type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(scheduler_of_main_frame_.get(),
+ FrameScheduler::NavigationType::kOther);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ scheduler_of_main_frame_.get(), TaskQueue::QueuePriority::kLowPriority);
+
+ DidCommitProvisionalLoadForFrame(frame_scheduler_.get(),
+ FrameScheduler::NavigationType::kOther);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler_.get(), TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal when FCP triggered.
+ scheduler_of_main_frame_->OnFirstContentfulPaintInMainFrame();
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ scheduler_of_main_frame_.get(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler_.get(), TaskQueue::QueuePriority::kNormalPriority);
+}
+
+// Test that if FCP is not triggered, the JavaScript timer task queues'
+// priorities are updated when load is triggered.
+TEST_F(DeprioritizeDOMTimerUntilFCPTest, FCPNotTriggered) {
+ FrameSchedulerImpl* frame_schedulers[2] = {scheduler_of_main_frame_.get(),
+ frame_scheduler_.get()};
+ for (FrameSchedulerImpl* frame_scheduler : frame_schedulers) {
+ // Initial priority is low.
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal on load event.
+ OnLoadForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+
+ // After reload type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(frame_scheduler,
+ FrameScheduler::NavigationType::kReload);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal on load event.
+ OnLoadForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+
+ // After other type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(frame_scheduler,
+ FrameScheduler::NavigationType::kOther);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal on load event.
+ OnLoadForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+ }
+}
+
+class DeprioritizeDOMTimerUntilLoadedTest : public DeprioritizeDOMTimerTest {
+ public:
+ DeprioritizeDOMTimerUntilLoadedTest()
+ : DeprioritizeDOMTimerTest(DeprioritizeDOMTimersPhase::kOnLoad) {}
+};
+
+// Test whether the JavaScript timer task queues' priorities are properly
+// updated on load event for frame load and reloads.
+TEST_F(DeprioritizeDOMTimerUntilLoadedTest, MainAndNonMainFrameLoadAndReload) {
+ FrameSchedulerImpl* frame_schedulers[2] = {scheduler_of_main_frame_.get(),
+ frame_scheduler_.get()};
+ for (FrameSchedulerImpl* frame_scheduler : frame_schedulers) {
+ // Initial priority is low.
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal on load event.
+ OnLoadForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+
+ // After reload type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(frame_scheduler,
+ FrameScheduler::NavigationType::kReload);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal on load event.
+ OnLoadForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+
+ // After other type navigation, priority is reset to low.
+ DidCommitProvisionalLoadForFrame(frame_scheduler,
+ FrameScheduler::NavigationType::kOther);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kLowPriority);
+
+ // Priority is set to normal on load event.
+ OnLoadForFrame(frame_scheduler);
+ ExpectJavaScriptTimerTaskQueuePriorityToBe(
+ frame_scheduler, TaskQueue::QueuePriority::kNormalPriority);
+ }
+}
+
+// Verify that non-delayed kExperimentalWebScheduling tasks are not throttled.
+TEST_F(FrameSchedulerImplTest, ImmediateWebSchedulingTasksAreNotThrottled) {
+ std::vector<base::TimeTicks> run_times;
+
+ // Make sure we are *not* aligned to a 1 second boundary by aligning to a 1
+ // second boundary and moving past it a bit. If we were throttled, even
+ // non-delayed tasks will need to wait until the next aligned interval to run.
+ FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+
+ const base::TimeTicks start = base::TimeTicks::Now();
+
+ // Hide the page to start throttling timers.
+ page_scheduler_->SetPageVisible(false);
+
+ // Post a non-delayed task to a web scheduling task queue.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ frame_scheduler_
+ ->CreateWebSchedulingTaskQueue(
+ WebSchedulingPriority::kUserVisiblePriority)
+ ->GetTaskRunner();
+ task_runner->PostTask(FROM_HERE, base::BindOnce(&RecordRunTime, &run_times));
+
+ // Run any ready tasks, which includes our non-delayed non-throttled web
+ // scheduling task. If we are throttled, our task will not run.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_THAT(run_times, testing::ElementsAre(start));
+}
+
+class FrameSchedulerImplThrottleForegroundTimersEnabledTest
+ : public FrameSchedulerImplTest {
+ public:
+ FrameSchedulerImplThrottleForegroundTimersEnabledTest()
+ : FrameSchedulerImplTest({kThrottleForegroundTimers}, {}) {}
+};
+
+TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest,
+ ForegroundPageTimerThrottling) {
+ page_scheduler_->SetPageVisible(true);
+
+ // Snap the time to a multiple of 1 second.
+ FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1));
+ const base::TimeTicks start = base::TimeTicks::Now();
+
+ std::vector<base::TimeTicks> run_times;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ frame_scheduler_->GetTaskRunner(
+ TaskType::kJavascriptTimerDelayedLowNesting);
+
+ for (int i = 0; i < 5; i++) {
+ task_runner->PostDelayedTask(FROM_HERE,
+ base::BindOnce(&RecordRunTime, &run_times),
+ base::TimeDelta::FromMilliseconds(50) * i);
+ }
+
+ // Make posted tasks run.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
+ start, start + base::TimeDelta::FromMilliseconds(100),
+ start + base::TimeDelta::FromMilliseconds(100),
+ start + base::TimeDelta::FromMilliseconds(200),
+ start + base::TimeDelta::FromMilliseconds(200)));
+}
+
+// Make sure the normal throttling (1 wake up per second) is applied when the
+// page becomes non-visible
+TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest,
+ BackgroundPageTimerThrottling) {
+ page_scheduler_->SetPageVisible(false);
+
+ // Snap the time to a multiple of 1 second.
+ FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1));
+ const base::TimeTicks start = base::TimeTicks::Now();
+
+ std::vector<base::TimeTicks> run_times;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ frame_scheduler_->GetTaskRunner(
+ TaskType::kJavascriptTimerDelayedLowNesting);
+
+ for (int i = 0; i < 5; i++) {
+ task_runner->PostDelayedTask(FROM_HERE,
+ base::BindOnce(&RecordRunTime, &run_times),
+ base::TimeDelta::FromMilliseconds(50) * i);
+ }
+
+ // Make posted tasks run.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
+ start, start + base::TimeDelta::FromMilliseconds(1000),
+ start + base::TimeDelta::FromMilliseconds(1000),
+ start + base::TimeDelta::FromMilliseconds(1000),
+ start + base::TimeDelta::FromMilliseconds(1000)));
+}
+
+TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest,
+ HiddenAudiblePageimerThrottling) {
+ page_scheduler_->SetPageVisible(false);
+ page_scheduler_->AudioStateChanged(/*is_audio_playing=*/true);
+
+ // Snap the time to a multiple of 1 second.
+ FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1));
+ const base::TimeTicks start = base::TimeTicks::Now();
+
+ std::vector<base::TimeTicks> run_times;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ frame_scheduler_->GetTaskRunner(
+ TaskType::kJavascriptTimerDelayedLowNesting);
+
+ for (int i = 0; i < 5; i++) {
+ task_runner->PostDelayedTask(FROM_HERE,
+ base::BindOnce(&RecordRunTime, &run_times),
+ base::TimeDelta::FromMilliseconds(50) * i);
+ }
+
+ // Make posted tasks run.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
+ start, start + base::TimeDelta::FromMilliseconds(100),
+ start + base::TimeDelta::FromMilliseconds(100),
+ start + base::TimeDelta::FromMilliseconds(200),
+ start + base::TimeDelta::FromMilliseconds(200)));
+}
+
+TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest,
+ VisibleCrossOriginFrameThrottling) {
+ std::unique_ptr<FrameSchedulerImpl> cross_origin_frame_scheduler =
+ CreateFrameScheduler(page_scheduler_.get(),
+ frame_scheduler_delegate_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
+ page_scheduler_->SetPageVisible(true);
+ cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true);
+ const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner =
+ cross_origin_frame_scheduler->GetTaskRunner(
+ TaskType::kJavascriptTimerDelayedLowNesting);
+
+ cross_origin_frame_scheduler->SetFrameVisible(true);
+ // Snap the time to a multiple of 1 second.
+ FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1));
+ const base::TimeTicks start = base::TimeTicks::Now();
+
+ std::vector<base::TimeTicks> run_times;
+ for (int i = 0; i < 5; i++) {
+ cross_origin_task_runner->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&RecordRunTime, &run_times),
+ base::TimeDelta::FromMilliseconds(50) * i);
+ }
+
+ // Make posted tasks run.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
+ start, start + base::TimeDelta::FromMilliseconds(100),
+ start + base::TimeDelta::FromMilliseconds(100),
+ start + base::TimeDelta::FromMilliseconds(200),
+ start + base::TimeDelta::FromMilliseconds(200)));
+}
+
+TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest,
+ HiddenCrossOriginFrameThrottling) {
+ std::unique_ptr<FrameSchedulerImpl> cross_origin_frame_scheduler =
+ CreateFrameScheduler(page_scheduler_.get(),
+ frame_scheduler_delegate_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
+ page_scheduler_->SetPageVisible(true);
+ cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true);
+ const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner =
+ cross_origin_frame_scheduler->GetTaskRunner(
+ TaskType::kJavascriptTimerDelayedLowNesting);
+
+ cross_origin_frame_scheduler->SetFrameVisible(false);
+ // Snap the time to a multiple of 1 second.
+ FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1));
+ const base::TimeTicks start = base::TimeTicks::Now();
+
+ std::vector<base::TimeTicks> run_times;
+ for (int i = 0; i < 5; i++) {
+ cross_origin_task_runner->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&RecordRunTime, &run_times),
+ base::TimeDelta::FromMilliseconds(50) * i);
+ }
+
+ // Make posted tasks run.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+
+ EXPECT_THAT(run_times,
+ testing::ElementsAre(
+ start, start + base::TimeDelta::FromMilliseconds(1000),
+ start + base::TimeDelta::FromMilliseconds(1000),
+ start + base::TimeDelta::FromMilliseconds(1000),
+ start + base::TimeDelta::FromMilliseconds(1000)));
+}
+
+class FrameSchedulerImplDisablePrioritizedPostMessageForwarding
+ : public FrameSchedulerImplTest {
+ public:
+ FrameSchedulerImplDisablePrioritizedPostMessageForwarding()
+ : FrameSchedulerImplTest({kDisablePrioritizedPostMessageForwarding}, {}) {
+ }
+};
+
+TEST_F(FrameSchedulerImplTest, PostMessageForwardingHasControlPriority) {
+ auto task_queue = GetTaskQueue(TaskType::kInternalPostMessageForwarding);
+
+ EXPECT_EQ(TaskQueue::QueuePriority::kVeryHighPriority,
+ task_queue->GetTaskQueue()->GetQueuePriority());
+}
+
+TEST_F(FrameSchedulerImplDisablePrioritizedPostMessageForwarding,
+ PostMessageForwardingHasNormalPriority) {
+ auto task_queue = GetTaskQueue(TaskType::kInternalPostMessageForwarding);
+
+ EXPECT_EQ(TaskQueue::QueuePriority::kNormalPriority,
+ task_queue->GetTaskQueue()->GetQueuePriority());
+}
+
} // namespace frame_scheduler_impl_unittest
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
index 00f4fd3f5ea..75d09d5ea19 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -14,7 +14,6 @@
#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/web_scheduling_task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
@@ -69,7 +68,7 @@ FrameTaskQueueController::NewWebSchedulingTaskQueue(
QueueTraits queue_traits,
WebSchedulingPriority priority) {
// Note: we only track this |task_queue| in |all_task_queues_and_voters_|.
- // It's interacted with through the WebSchedulingTaskQueueImpl that
+ // It's interacted with through the MainThreadWebSchedulingTaskQueueImpl that
// will wrap it, rather than through this class like other task queues.
scoped_refptr<MainThreadTaskQueue> task_queue =
main_thread_scheduler_impl_->NewTaskQueue(
@@ -82,6 +81,12 @@ FrameTaskQueueController::NewWebSchedulingTaskQueue(
return task_queue;
}
+void FrameTaskQueueController::RemoveWebSchedulingTaskQueue(
+ MainThreadTaskQueue* queue) {
+ DCHECK(queue);
+ RemoveTaskQueueAndVoter(queue);
+}
+
void FrameTaskQueueController::CreateTaskQueue(
QueueTraits queue_traits) {
DCHECK(!task_queues_.Contains(queue_traits.Key()));
@@ -128,6 +133,23 @@ void FrameTaskQueueController::TaskQueueCreated(
}
}
+void FrameTaskQueueController::RemoveTaskQueueAndVoter(
+ MainThreadTaskQueue* queue) {
+ DCHECK(task_queue_enabled_voters_.Contains(queue));
+ task_queue_enabled_voters_.erase(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 == queue) {
+ found_task_queue = true;
+ all_task_queues_and_voters_.erase(it);
+ break;
+ }
+ }
+ DCHECK(found_task_queue);
+}
+
base::sequence_manager::TaskQueue::QueueEnabledVoter*
FrameTaskQueueController::GetQueueEnabledVoter(
const scoped_refptr<MainThreadTaskQueue>& task_queue) {
@@ -144,19 +166,7 @@ bool FrameTaskQueueController::RemoveResourceLoadingTaskQueue(
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);
+ RemoveTaskQueueAndVoter(task_queue.get());
return true;
}
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
index fb24d8834c9..69f1219d4f2 100644
--- 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
@@ -9,7 +9,6 @@
#include <utility>
#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"
@@ -53,19 +52,20 @@ class PLATFORM_EXPORT FrameTaskQueueController {
class Delegate {
public:
Delegate() = default;
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
virtual ~Delegate() = default;
virtual void OnTaskQueueCreated(
MainThreadTaskQueue*,
base::sequence_manager::TaskQueue::QueueEnabledVoter*) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Delegate);
};
FrameTaskQueueController(MainThreadSchedulerImpl*,
FrameSchedulerImpl*,
Delegate*);
+ FrameTaskQueueController(const FrameTaskQueueController&) = delete;
+ FrameTaskQueueController& operator=(const FrameTaskQueueController&) = delete;
~FrameTaskQueueController();
// Return the task queue associated with the given queue traits,
@@ -79,6 +79,8 @@ class PLATFORM_EXPORT FrameTaskQueueController {
MainThreadTaskQueue::QueueTraits,
WebSchedulingPriority);
+ void RemoveWebSchedulingTaskQueue(MainThreadTaskQueue*);
+
// Get the list of all task queue and voter pairs.
const Vector<TaskQueueAndEnabledVoterPair>& GetAllTaskQueuesAndVoters() const;
@@ -105,6 +107,12 @@ class PLATFORM_EXPORT FrameTaskQueueController {
void TaskQueueCreated(const scoped_refptr<MainThreadTaskQueue>&);
+ // Removes a queue from |all_task_queues_and_voters_| and
+ // |task_queue_enabled_voters_|. This method enforces that the queue is in the
+ // collection before removal. Removes are linear in the total number of task
+ // queues.
+ void RemoveTaskQueueAndVoter(MainThreadTaskQueue*);
+
// Map a set of QueueTraits to a QueueType.
// TODO(crbug.com/877245): Consider creating a new queue type kFrameNonLoading
// and use it instead of this for new queue types.
@@ -137,8 +145,6 @@ class PLATFORM_EXPORT FrameTaskQueueController {
// The list of all task queue and voter pairs for all QueueTypeInternal queue
// types.
Vector<TaskQueueAndEnabledVoterPair> all_task_queues_and_voters_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameTaskQueueController);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
index c06ef73e758..cfc6d2bd602 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -39,6 +39,9 @@ class FrameTaskQueueControllerTest : public testing::Test,
base::test::TaskEnvironment::TimeSource::MOCK_TIME,
base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED),
task_queue_created_count_(0) {}
+ FrameTaskQueueControllerTest(const FrameTaskQueueControllerTest&) = delete;
+ FrameTaskQueueControllerTest& operator=(const FrameTaskQueueControllerTest&) =
+ delete;
~FrameTaskQueueControllerTest() override = default;
@@ -124,8 +127,6 @@ class FrameTaskQueueControllerTest : public testing::Test,
private:
size_t task_queue_created_count_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameTaskQueueControllerTest);
};
TEST_F(FrameTaskQueueControllerTest, CreateAllTaskQueues) {
@@ -286,6 +287,31 @@ TEST_F(FrameTaskQueueControllerTest, AddWebSchedulingTaskQueues) {
task_queue->web_scheduling_priority().value());
}
+TEST_F(FrameTaskQueueControllerTest, RemoveWebSchedulingTaskQueues) {
+ scoped_refptr<MainThreadTaskQueue> task_queue =
+ frame_task_queue_controller_->NewWebSchedulingTaskQueue(
+ QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
+ task_queue->web_scheduling_priority().value());
+
+ scoped_refptr<MainThreadTaskQueue> task_queue2 =
+ frame_task_queue_controller_->NewWebSchedulingTaskQueue(
+ QueueTraits(), WebSchedulingPriority::kUserVisiblePriority);
+ EXPECT_EQ(2u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ EXPECT_EQ(WebSchedulingPriority::kUserVisiblePriority,
+ task_queue2->web_scheduling_priority().value());
+
+ frame_task_queue_controller_->RemoveWebSchedulingTaskQueue(task_queue.get());
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ frame_task_queue_controller_->RemoveWebSchedulingTaskQueue(task_queue2.get());
+ EXPECT_EQ(0u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+}
+
TEST_F(FrameTaskQueueControllerTest,
AddMultipleSamePriorityWebSchedulingTaskQueues) {
scoped_refptr<MainThreadTaskQueue> task_queue1 =
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 f6a962a4ca9..2367d1610e7 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_IDLE_TIME_ESTIMATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_IDLE_TIME_ESTIMATOR_H_
-#include "base/macros.h"
#include "base/task/task_observer.h"
#include "base/time/tick_clock.h"
#include "cc/base/rolling_time_delta_history.h"
@@ -22,6 +21,8 @@ class PLATFORM_EXPORT IdleTimeEstimator : public base::TaskObserver {
const base::TickClock* time_source,
int sample_count,
double estimation_percentile);
+ IdleTimeEstimator(const IdleTimeEstimator&) = delete;
+ IdleTimeEstimator& operator=(const IdleTimeEstimator&) = delete;
~IdleTimeEstimator() override;
@@ -54,8 +55,6 @@ class PLATFORM_EXPORT IdleTimeEstimator : public base::TaskObserver {
base::TimeDelta cumulative_compositor_runtime_;
int nesting_level_;
bool did_commit_;
-
- DISALLOW_COPY_AND_ASSIGN(IdleTimeEstimator);
};
} // namespace scheduler
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 c53e2399302..e02a2f9924f 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
@@ -21,8 +21,6 @@ namespace scheduler {
MAIN_THREAD_LOAD_METRIC_NAME ".Extension"
#define DURATION_PER_TASK_TYPE_METRIC_NAME \
"RendererScheduler.TaskDurationPerTaskType2"
-#define COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT \
- "RendererScheduler.TaskCountPerFrameType.HasSafePoint"
#define QUEUEING_TIME_PER_QUEUE_TYPE_METRIC_NAME \
"RendererScheduler.QueueingDurationPerQueueType"
@@ -91,10 +89,9 @@ MainThreadMetricsHelper::MainThreadMetricsHelper(
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),
- current_task_slice_start_time_(now),
- safepoints_in_current_toplevel_task_count_(0) {
+ main_thread_task_load_state_(MainThreadTaskLoadState::kUnknown) {
main_thread_load_tracker_.Resume(now);
+ random_generator_.Seed();
if (renderer_backgrounded) {
background_main_thread_load_tracker_.Resume(now);
} else {
@@ -143,37 +140,6 @@ void MainThreadMetricsHelper::ResetForTest(base::TimeTicks now) {
kThreadLoadTrackerReportingInterval);
}
-void MainThreadMetricsHelper::OnSafepointEntered(base::TimeTicks now) {
- current_task_slice_start_time_ = now;
-}
-
-void MainThreadMetricsHelper::OnSafepointExited(base::TimeTicks now) {
- safepoints_in_current_toplevel_task_count_++;
- RecordTaskSliceMetrics(now);
-}
-
-void MainThreadMetricsHelper::RecordTaskSliceMetrics(base::TimeTicks now) {
- UMA_HISTOGRAM_TIMES("RendererScheduler.TasksWithSafepoints.TaskSliceTime",
- now - current_task_slice_start_time_);
-}
-
-void MainThreadMetricsHelper::RecordMetricsForTasksWithSafepoints(
- const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
- if (safepoints_in_current_toplevel_task_count_ == 0)
- return;
-
- RecordTaskSliceMetrics(task_timing.end_time());
-
- UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
- "RendererScheduler.TasksWithSafepoints.TaskTime",
- task_timing.wall_duration(), base::TimeDelta::FromMicroseconds(1),
- base::TimeDelta::FromSeconds(1), 50);
- UMA_HISTOGRAM_COUNTS_100(
- "RendererScheduler.TasksWithSafepoints.SafepointCount",
- safepoints_in_current_toplevel_task_count_);
- safepoints_in_current_toplevel_task_count_ = 0;
-}
-
void MainThreadMetricsHelper::RecordTaskMetrics(
MainThreadTaskQueue* queue,
const base::sequence_manager::Task& task,
@@ -200,11 +166,6 @@ void MainThreadMetricsHelper::RecordTaskMetrics(
last_reported_task_ = task_timing.end_time();
- UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2",
- 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(task_timing.start_time(),
@@ -213,44 +174,16 @@ void MainThreadMetricsHelper::RecordTaskMetrics(
task_timing.end_time());
background_main_thread_load_tracker_.RecordTaskTime(task_timing.start_time(),
task_timing.end_time());
+ // WARNING: All code below must be compatible with down-sampling.
+ constexpr double kSamplingProbabily = .01;
+ bool should_sample = random_generator_.RandDouble() < kSamplingProbabily;
+ if (!should_sample)
+ return;
- if (safepoints_in_current_toplevel_task_count_ > 0) {
- FrameStatus frame_status =
- GetFrameStatus(queue ? queue->GetFrameScheduler() : nullptr);
-
- UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT,
- frame_status, FrameStatus::kCount);
- if (duration >= base::TimeDelta::FromMilliseconds(16)) {
- UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT
- ".LongerThan16ms",
- frame_status, FrameStatus::kCount);
- }
-
- if (duration >= base::TimeDelta::FromMilliseconds(50)) {
- UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT
- ".LongerThan50ms",
- frame_status, FrameStatus::kCount);
- }
-
- if (duration >= base::TimeDelta::FromMilliseconds(100)) {
- UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT
- ".LongerThan100ms",
- frame_status, FrameStatus::kCount);
- }
-
- if (duration >= base::TimeDelta::FromMilliseconds(150)) {
- UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT
- ".LongerThan150ms",
- frame_status, FrameStatus::kCount);
- }
-
- if (duration >= base::TimeDelta::FromSeconds(1)) {
- UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT
- ".LongerThan1s",
- frame_status, FrameStatus::kCount);
- }
- RecordMetricsForTasksWithSafepoints(task_timing);
- }
+ UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2",
+ base::saturated_cast<base::HistogramBase::Sample>(
+ duration.InMicroseconds()),
+ 1, 1000 * 1000, 50);
TaskType task_type = static_cast<TaskType>(task.task_type);
UseCase use_case =
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 4f60016f817..f4d0fc58e85 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_METRICS_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_METRICS_HELPER_H_
-#include "base/macros.h"
+#include "base/rand_util.h"
#include "base/time/time.h"
#include "components/scheduling_metrics/task_duration_metric_reporter.h"
#include "components/scheduling_metrics/total_duration_metric_reporter.h"
@@ -43,21 +43,19 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
bool has_cpu_timing_for_each_task,
base::TimeTicks now,
bool renderer_backgrounded);
+ MainThreadMetricsHelper(const MainThreadMetricsHelper&) = delete;
+ MainThreadMetricsHelper& operator=(const MainThreadMetricsHelper&) = delete;
~MainThreadMetricsHelper();
void RecordTaskMetrics(
MainThreadTaskQueue* queue,
const base::sequence_manager::Task& task,
const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
- void RecordTaskSliceMetrics(base::TimeTicks now);
void OnRendererForegrounded(base::TimeTicks now);
void OnRendererBackgrounded(base::TimeTicks now);
void OnRendererShutdown(base::TimeTicks now);
- void OnSafepointEntered(base::TimeTicks now);
- void OnSafepointExited(base::TimeTicks now);
-
void RecordMainThreadTaskLoad(base::TimeTicks time, double load);
void RecordForegroundMainThreadTaskLoad(base::TimeTicks time, double load);
void RecordBackgroundMainThreadTaskLoad(base::TimeTicks time, double load);
@@ -71,10 +69,6 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
void ReportLowThreadLoadForPageAlmostIdleSignal(int load_percentage);
- // Record metrics of only top-level tasks with safepoints.
- void RecordMetricsForTasksWithSafepoints(
- const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
-
MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED
// Set to true when OnRendererShutdown is called. Used to ensure that metrics
@@ -116,15 +110,7 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
scheduling_metrics::TotalDurationMetricReporter total_task_time_reporter_;
MainThreadTaskLoadState main_thread_task_load_state_;
-
- base::TimeTicks current_task_slice_start_time_;
-
- // Number of safepoints during inside the current top-level tasks in which
- // cooperative scheduling had a chance to run a task (as we don't necessarily
- // run a task in each safepoint).
- int safepoints_in_current_toplevel_task_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadMetricsHelper);
+ base::InsecureRandomGenerator random_generator_;
};
} // namespace scheduler
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 b811e6ff87a..ad51f194b3e 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
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h"
#include <memory>
-#include "base/macros.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"
@@ -52,6 +51,9 @@ class MainThreadMetricsHelperTest : public testing::Test {
: task_environment_(
base::test::TaskEnvironment::TimeSource::MOCK_TIME,
base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
+ MainThreadMetricsHelperTest(const MainThreadMetricsHelperTest&) = delete;
+ MainThreadMetricsHelperTest& operator=(const MainThreadMetricsHelperTest&) =
+ delete;
~MainThreadMetricsHelperTest() override = default;
@@ -241,8 +243,6 @@ class MainThreadMetricsHelperTest : public testing::Test {
FakePageScheduler::Builder().SetIsAudioPlaying(true).Build();
std::unique_ptr<FakePageScheduler> throtting_exempt_view_ =
FakePageScheduler::Builder().SetIsThrottlingExempt(true).Build();
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadMetricsHelperTest);
};
TEST_F(MainThreadMetricsHelperTest, GetFrameStatusTest) {
@@ -264,8 +264,5 @@ TEST_F(MainThreadMetricsHelperTest, GetFrameStatusTest) {
}
}
-// TODO(crbug.com/754656): Add tests for
-// RendererScheduler.TasksWithSafepoints histograms.
-
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc
index ca954dbac31..50178bab279 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc
@@ -28,6 +28,8 @@ constexpr char kTimePerTaskRun[] = "time_per_task_run";
class MainThreadPerfTest : public testing::Test {
public:
MainThreadPerfTest() = default;
+ MainThreadPerfTest(const MainThreadPerfTest&) = delete;
+ MainThreadPerfTest& operator=(const MainThreadPerfTest&) = delete;
~MainThreadPerfTest() override = default;
void SetUp() override {
@@ -46,8 +48,6 @@ class MainThreadPerfTest : public testing::Test {
protected:
std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
std::unique_ptr<ScopedSchedulerOverrider> scheduler_overrider_;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadPerfTest);
};
TEST_F(MainThreadPerfTest, PostTaskPerformance) {
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 9d1c2990a54..3b0a449bc05 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
@@ -23,6 +23,9 @@ class PLATFORM_EXPORT MainThreadSchedulerHelper : public SchedulerHelper {
MainThreadSchedulerHelper(
base::sequence_manager::SequenceManager* sequence_manager,
MainThreadSchedulerImpl* main_thread_scheduler);
+ MainThreadSchedulerHelper(const MainThreadSchedulerHelper&) = delete;
+ MainThreadSchedulerHelper& operator=(const MainThreadSchedulerHelper&) =
+ delete;
~MainThreadSchedulerHelper() override;
scoped_refptr<MainThreadTaskQueue> NewTaskQueue(
@@ -45,8 +48,6 @@ class PLATFORM_EXPORT MainThreadSchedulerHelper : public SchedulerHelper {
const scoped_refptr<MainThreadTaskQueue> default_task_queue_;
const scoped_refptr<MainThreadTaskQueue> control_task_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerHelper);
};
} // namespace scheduler
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 9a117a2acf4..b8f5e030998 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
@@ -42,7 +42,6 @@
#include "third_party/blink/renderer/platform/scheduler/common/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/agent_group_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.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.h"
@@ -205,8 +204,6 @@ bool IsBlockingEvent(const blink::WebInputEvent& web_input_event) {
blink::WebInputEvent::DispatchType::kBlocking;
}
-MainThreadSchedulerImpl* g_main_thread_scheduler = nullptr;
-
} // namespace
MainThreadSchedulerImpl::MainThreadSchedulerImpl(
@@ -253,8 +250,7 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
TaskType::kMainThreadTaskQueueControl)),
main_thread_only_(this, helper_.GetClock(), helper_.NowTicks()),
any_thread_(this),
- policy_may_need_update_(&any_thread_lock_),
- notify_agent_strategy_task_posted_(&any_thread_lock_) {
+ policy_may_need_update_(&any_thread_lock_) {
helper_.AttachToCurrentThread();
// Compositor task queue and default task queue should be managed by
@@ -290,18 +286,10 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
// TaskQueueThrottler requires some task runners, then initialize
// TaskQueueThrottler after task queues/runners are initialized.
- task_queue_throttler_ =
- std::make_unique<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()));
- notify_agent_strategy_on_input_event_closure_ = base::BindRepeating(
- &MainThreadSchedulerImpl::NotifyAgentSchedulerOnInputEvent,
- weak_factory_.GetWeakPtr());
- agent_strategy_delay_callback_ =
- base::BindRepeating(&MainThreadSchedulerImpl::OnAgentStrategyDelayPassed,
- weak_factory_.GetWeakPtr());
TRACE_EVENT_OBJECT_CREATED_WITH_ID(
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "MainThreadScheduler",
@@ -325,18 +313,13 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
// we choose an arbitrary initial offset.
main_thread_only().initial_virtual_time_ticks =
base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- EnableVirtualTime(BaseTimeOverridePolicy::OVERRIDE);
+ EnableVirtualTime();
SetVirtualTimePolicy(VirtualTimePolicy::kPause);
}
- main_thread_only()
- .compositor_priority_experiments.OnMainThreadSchedulerInitialized();
-
main_thread_only().current_policy.find_in_page_priority() =
find_in_page_budget_pool_controller_->CurrentTaskPriority();
- g_main_thread_scheduler = this;
-
// Explicitly set the priority of this queue since it is not managed by
// the main thread scheduler.
memory_purge_task_queue_->GetTaskQueue()->SetQueuePriority(
@@ -367,13 +350,17 @@ MainThreadSchedulerImpl::~MainThreadSchedulerImpl() {
// we could end up having stale pointers to the Blink heap which has been
// terminated by this point.
DCHECK(was_shutdown_);
-
- g_main_thread_scheduler = nullptr;
}
// static
WebThreadScheduler* WebThreadScheduler::MainThreadScheduler() {
- return g_main_thread_scheduler;
+ auto* main_thread = Thread::MainThread();
+ // Enforce that this is not called before the main thread is initialized.
+ DCHECK(main_thread && main_thread->Scheduler());
+
+ // This can return nullptr if the main thread scheduler is not a
+ // MainThreadSchedulerImpl, which can happen in tests.
+ return main_thread->Scheduler()->GetWebMainThreadScheduler();
}
MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly(
@@ -669,11 +656,8 @@ void MainThreadSchedulerImpl::Shutdown() {
base::TimeTicks now = tick_clock()->NowTicks();
main_thread_only().metrics_helper.OnRendererShutdown(now);
- main_thread_only()
- .compositor_priority_experiments.OnMainThreadSchedulerShutdown();
ShutdownAllQueues();
- task_queue_throttler_.reset();
// Shut down |helper_| first, so that the ForceUpdatePolicy() call
// from |idle_helper_| early-outs and doesn't do anything.
@@ -1363,16 +1347,6 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
break;
}
- // Make sure the per-agent scheduling strategy is notified that there was an
- // input event.
- if (type != WebInputEvent::Type::kMouseMove &&
- !notify_agent_strategy_task_posted_.IsSet() &&
- agent_scheduling_strategy_->ShouldNotifyOnInputEvent()) {
- notify_agent_strategy_task_posted_.SetWhileLocked(true);
- control_task_queue_->GetTaskRunnerWithDefaultTaskType()->PostTask(
- FROM_HERE, notify_agent_strategy_on_input_event_closure_);
- }
-
// Avoid unnecessary policy updates if the use case did not change.
UseCase use_case = ComputeCurrentUseCase(now, &unused_policy_duration);
@@ -1384,19 +1358,6 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
GetCompositorThreadOnly().last_input_type = type;
}
-void MainThreadSchedulerImpl::NotifyAgentSchedulerOnInputEvent() {
- helper_.CheckOnValidThread();
-
- if (agent_scheduling_strategy_->OnInputEvent() ==
- AgentSchedulingStrategy::ShouldUpdatePolicy::kYes &&
- !policy_may_need_update_.IsSet()) {
- OnAgentStrategyUpdated();
- }
-
- base::AutoLock lock(any_thread_lock_);
- notify_agent_strategy_task_posted_.SetWhileLocked(false);
-}
-
void MainThreadSchedulerImpl::WillPostInputEventToMainThread(
WebInputEvent::Type web_input_event_type,
const WebInputEventAttribution& web_input_event_attribution) {
@@ -1477,7 +1438,8 @@ bool MainThreadSchedulerImpl::ShouldYieldForHighPriorityWork() {
if (pair.first->GetPrioritisationType() ==
MainThreadTaskQueue::QueueTraits::PrioritisationType::
kCompositor &&
- pair.first->GetTaskQueue()->HasTaskToRunImmediately())
+ pair.first->GetTaskQueue()
+ ->HasTaskToRunImmediatelyOrReadyDelayedTask())
return true;
}
return main_thread_only().blocking_input_expected_soon;
@@ -1665,8 +1627,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
new_policy.should_prioritize_loading_with_compositing() = true;
}
- new_policy.should_disable_throttling() = main_thread_only().use_virtual_time;
-
new_policy.find_in_page_priority() =
find_in_page_budget_pool_controller_->CurrentTaskPriority();
@@ -1694,15 +1654,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
}
}
- if (new_policy.should_disable_throttling() !=
- main_thread_only().current_policy.should_disable_throttling()) {
- if (new_policy.should_disable_throttling()) {
- task_queue_throttler()->DisableThrottling();
- } else {
- task_queue_throttler()->EnableThrottling();
- }
- }
-
Policy old_policy = main_thread_only().current_policy;
main_thread_only().current_policy = new_policy;
@@ -1711,10 +1662,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
UpdateStateForAllTaskQueues(old_policy);
}
-void MainThreadSchedulerImpl::OnAgentStrategyUpdated() {
- UpdateStateForAllTaskQueues(absl::nullopt);
-}
-
void MainThreadSchedulerImpl::UpdateStateForAllTaskQueues(
absl::optional<Policy> previous_policy) {
helper_.CheckOnValidThread();
@@ -1742,11 +1689,8 @@ void MainThreadSchedulerImpl::UpdateTaskQueueState(
task_queue->GetTaskQueue()->SetQueuePriority(ComputePriority(task_queue));
if (task_queue_enabled_voter) {
- bool is_enabled_for_agent =
- agent_scheduling_strategy_->QueueEnabledState(*task_queue)
- .value_or(true);
task_queue_enabled_voter->SetVoteToEnable(
- is_enabled_for_agent && new_policy.IsQueueEnabled(task_queue));
+ new_policy.IsQueueEnabled(task_queue));
}
// Make sure if there's no voter that the task queue is enabled.
@@ -1879,13 +1823,6 @@ IdleTimeEstimator* MainThreadSchedulerImpl::GetIdleTimeEstimatorForTesting() {
}
base::TimeTicks MainThreadSchedulerImpl::EnableVirtualTime() {
- return EnableVirtualTime(main_thread_only().initial_virtual_time.is_null()
- ? BaseTimeOverridePolicy::DO_NOT_OVERRIDE
- : BaseTimeOverridePolicy::OVERRIDE);
-}
-
-base::TimeTicks MainThreadSchedulerImpl::EnableVirtualTime(
- BaseTimeOverridePolicy policy) {
if (main_thread_only().use_virtual_time)
return main_thread_only().initial_virtual_time_ticks;
main_thread_only().use_virtual_time = true;
@@ -1895,11 +1832,8 @@ base::TimeTicks MainThreadSchedulerImpl::EnableVirtualTime(
if (main_thread_only().initial_virtual_time_ticks.is_null())
main_thread_only().initial_virtual_time_ticks = tick_clock()->NowTicks();
virtual_time_domain_ = std::make_unique<AutoAdvancingVirtualTimeDomain>(
- main_thread_only().initial_virtual_time +
- main_thread_only().initial_virtual_time_offset,
- main_thread_only().initial_virtual_time_ticks +
- main_thread_only().initial_virtual_time_offset,
- &helper_, policy);
+ main_thread_only().initial_virtual_time,
+ main_thread_only().initial_virtual_time_ticks, &helper_);
RegisterTimeDomain(virtual_time_domain_.get());
DCHECK(!virtual_time_control_task_queue_);
@@ -2025,11 +1959,6 @@ void MainThreadSchedulerImpl::SetInitialVirtualTime(base::Time time) {
main_thread_only().initial_virtual_time = time;
}
-void MainThreadSchedulerImpl::SetInitialVirtualTimeOffset(
- base::TimeDelta offset) {
- main_thread_only().initial_virtual_time_offset = offset;
-}
-
void MainThreadSchedulerImpl::ApplyVirtualTimePolicy() {
switch (main_thread_only().virtual_time_policy) {
case VirtualTimePolicy::kAdvance:
@@ -2150,7 +2079,12 @@ void MainThreadSchedulerImpl::WriteIntoTraceLocked(
VirtualTimePolicyToString(main_thread_only().virtual_time_policy));
dict.Add("virtual_time", main_thread_only().use_virtual_time);
- dict.Add("page_schedulers", main_thread_only().page_schedulers);
+ dict.Add("page_schedulers", [&](perfetto::TracedValue context) {
+ auto array = std::move(context).WriteArray();
+ for (const auto* page_scheduler : main_thread_only().page_schedulers) {
+ page_scheduler->WriteIntoTrace(array.AppendItem(), optional_now);
+ }
+ });
dict.Add("policy", main_thread_only().current_policy);
@@ -2167,10 +2101,6 @@ void MainThreadSchedulerImpl::WriteIntoTraceLocked(
dict.Add("user_model", any_thread().user_model);
dict.Add("render_widget_scheduler_signals", render_widget_scheduler_signals_);
-
- dict.Add("task_queue_throttler", [&](perfetto::TracedValue context) {
- task_queue_throttler_->WriteIntoTrace(std::move(context), optional_now);
- });
}
bool MainThreadSchedulerImpl::Policy::IsQueueEnabled(
@@ -2198,7 +2128,6 @@ void MainThreadSchedulerImpl::Policy::WriteIntoTrace(
dict.Add("rail_mode", RAILModeToString(rail_mode()));
dict.Add("use_case", UseCaseToString(use_case()));
- dict.Add("should_disable_throttling", should_disable_throttling());
dict.Add("should_defer_task_queues", should_defer_task_queues());
dict.Add("should_pause_task_queues", should_pause_task_queues());
dict.Add("should_pause_task_queues_for_android_webview",
@@ -2298,36 +2227,6 @@ void MainThreadSchedulerImpl::OnMainFramePaint() {
UpdatePolicyLocked(UpdateType::kMayEarlyOutIfPolicyUnchanged);
}
-void MainThreadSchedulerImpl::OnMainFrameLoad(
- const FrameSchedulerImpl& frame_scheduler) {
- helper_.CheckOnValidThread();
- if (agent_scheduling_strategy_->OnMainFrameLoad(frame_scheduler) ==
- AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) {
- OnAgentStrategyUpdated();
- };
-}
-
-void MainThreadSchedulerImpl::OnSetTimer(
- const FrameSchedulerImpl& frame_scheduler,
- base::TimeDelta delay) {
- helper_.CheckOnValidThread();
- control_task_runner_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(agent_strategy_delay_callback_,
- frame_scheduler.GetWeakPtr()),
- delay);
-}
-
-void MainThreadSchedulerImpl::OnAgentStrategyDelayPassed(
- base::WeakPtr<const FrameSchedulerImpl> frame_scheduler) {
- helper_.CheckOnValidThread();
- if (frame_scheduler &&
- agent_scheduling_strategy_->OnDelayPassed(*frame_scheduler) ==
- AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) {
- OnAgentStrategyUpdated();
- }
-}
-
void MainThreadSchedulerImpl::ResetForNavigationLocked() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"MainThreadSchedulerImpl::ResetForNavigationLocked");
@@ -2343,9 +2242,6 @@ void MainThreadSchedulerImpl::ResetForNavigationLocked() {
main_thread_only().idle_time_estimator.Clear();
main_thread_only().have_reported_blocking_intervention_since_navigation =
false;
- for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) {
- page_scheduler->OnNavigation();
- }
UpdatePolicyLocked(UpdateType::kMayEarlyOutIfPolicyUnchanged);
UMA_HISTOGRAM_COUNTS_100("RendererScheduler.WebViewsPerScheduler",
@@ -2566,8 +2462,7 @@ base::TimeTicks MainThreadSchedulerImpl::MonotonicallyIncreasingVirtualTime() {
return GetActiveTimeDomain()->Now();
}
-WebThreadScheduler*
-MainThreadSchedulerImpl::GetWebMainThreadSchedulerForTest() {
+WebThreadScheduler* MainThreadSchedulerImpl::GetWebMainThreadScheduler() {
return this;
}
@@ -2638,22 +2533,6 @@ void MainThreadSchedulerImpl::RemovePageScheduler(
UpdatePolicyLocked(UpdateType::kMayEarlyOutIfPolicyUnchanged);
}
-void MainThreadSchedulerImpl::OnFrameAdded(
- const FrameSchedulerImpl& frame_scheduler) {
- if (agent_scheduling_strategy_->OnFrameAdded(frame_scheduler) ==
- AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) {
- OnAgentStrategyUpdated();
- }
-}
-
-void MainThreadSchedulerImpl::OnFrameRemoved(
- const FrameSchedulerImpl& frame_scheduler) {
- if (agent_scheduling_strategy_->OnFrameRemoved(frame_scheduler) ==
- AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) {
- OnAgentStrategyUpdated();
- }
-}
-
void MainThreadSchedulerImpl::OnPageFrozen() {
memory_purge_manager_.OnPageFrozen();
UpdatePolicy();
@@ -2881,6 +2760,12 @@ void MainThreadSchedulerImpl::RemoveTaskTimeObserver(
helper_.RemoveTaskTimeObserver(task_time_observer);
}
+std::unique_ptr<CPUTimeBudgetPool>
+MainThreadSchedulerImpl::CreateCPUTimeBudgetPoolForTesting(const char* name) {
+ return std::make_unique<CPUTimeBudgetPool>(name, &tracing_controller_,
+ tick_clock()->NowTicks());
+}
+
AutoAdvancingVirtualTimeDomain*
MainThreadSchedulerImpl::GetVirtualTimeDomain() {
return virtual_time_domain_.get();
@@ -3019,18 +2904,6 @@ MainThreadSchedulerImpl::ComputeCompositorPriorityFromUseCase() const {
}
}
-void MainThreadSchedulerImpl::OnSafepointEntered() {
- DCHECK(WTF::IsMainThread());
- DCHECK(!main_thread_only().IsInNestedRunloop());
- main_thread_only().metrics_helper.OnSafepointEntered(helper_.NowTicks());
-}
-
-void MainThreadSchedulerImpl::OnSafepointExited() {
- DCHECK(WTF::IsMainThread());
- DCHECK(!main_thread_only().IsInNestedRunloop());
- main_thread_only().metrics_helper.OnSafepointExited(helper_.NowTicks());
-}
-
void MainThreadSchedulerImpl::ExecuteAfterCurrentTask(
base::OnceClosure on_completion_task) {
main_thread_only().on_task_completion_callbacks.push_back(
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 b3543e7cb08..9420429c440 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
@@ -7,13 +7,11 @@
#include <map>
#include <memory>
-#include <random>
#include <stack>
#include "base/atomicops.h"
#include "base/dcheck_is_on.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/single_sample_metrics.h"
#include "base/profiler/sample_metadata.h"
@@ -31,7 +29,6 @@
#include "third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h"
#include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.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/compositor_priority_experiments.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h"
@@ -77,10 +74,10 @@ class FrameSchedulerImpl;
class PageSchedulerImpl;
class TaskQueueThrottler;
class WebRenderWidgetSchedulingState;
+class CPUTimeBudgetPool;
class PLATFORM_EXPORT MainThreadSchedulerImpl
: public ThreadSchedulerImpl,
- public AgentSchedulingStrategy::Delegate,
public IdleHelper::Delegate,
public MainThreadSchedulerHelper::Observer,
public RenderWidgetSignals::Observer,
@@ -163,6 +160,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
MainThreadSchedulerImpl(
std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
absl::optional<base::Time> initial_virtual_time);
+ MainThreadSchedulerImpl(const MainThreadSchedulerImpl&) = delete;
+ MainThreadSchedulerImpl& operator=(const MainThreadSchedulerImpl&) = delete;
~MainThreadSchedulerImpl() override;
@@ -233,7 +232,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
std::unique_ptr<ThreadScheduler::RendererPauseHandle> PauseScheduler()
override;
base::TimeTicks MonotonicallyIncreasingVirtualTime() override;
- WebThreadScheduler* GetWebMainThreadSchedulerForTest() override;
NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
return nullptr;
}
@@ -297,16 +295,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
using VirtualTimePolicy = PageScheduler::VirtualTimePolicy;
- using BaseTimeOverridePolicy =
- AutoAdvancingVirtualTimeDomain::BaseTimeOverridePolicy;
-
- // Tells the scheduler that all TaskQueues should use virtual time. Depending
- // on the initial time, picks the policy to be either overriding or not.
- base::TimeTicks EnableVirtualTime();
-
// Tells the scheduler that all TaskQueues should use virtual time. Returns
// the base::TimeTicks that virtual time offsets will be relative to.
- base::TimeTicks EnableVirtualTime(BaseTimeOverridePolicy policy);
+ base::TimeTicks EnableVirtualTime();
bool IsVirtualTimeEnabled() const;
// Migrates all task queues to real time.
@@ -316,7 +307,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
bool VirtualTimeAllowedToAdvance() const;
void SetVirtualTimePolicy(VirtualTimePolicy virtual_time_policy);
void SetInitialVirtualTime(base::Time time);
- void SetInitialVirtualTimeOffset(base::TimeDelta offset);
void SetMaxVirtualTimeTaskStarvationCount(int max_task_starvation_count);
base::TimeTicks IncrementVirtualTimePauseCount();
void DecrementVirtualTimePauseCount();
@@ -326,13 +316,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void AddPageScheduler(PageSchedulerImpl*);
void RemovePageScheduler(PageSchedulerImpl*);
- void OnFrameAdded(const FrameSchedulerImpl& frame_scheduler);
- void OnFrameRemoved(const FrameSchedulerImpl& frame_scheduler);
-
- AgentSchedulingStrategy& agent_scheduling_strategy() {
- return *agent_scheduling_strategy_;
- }
-
// Called by an associated PageScheduler when frozen or resumed.
void OnPageFrozen();
void OnPageResumed();
@@ -379,14 +362,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
AutoAdvancingVirtualTimeDomain* GetVirtualTimeDomain();
- TaskQueueThrottler* task_queue_throttler() const {
- return task_queue_throttler_.get();
- }
+ std::unique_ptr<CPUTimeBudgetPool> CreateCPUTimeBudgetPoolForTesting(
+ const char* name);
// Virtual for test.
virtual void OnMainFramePaint();
- void OnMainFrameLoad(const FrameSchedulerImpl& frame_scheduler);
- void OnAgentStrategyUpdated();
void OnShutdownTaskQueue(const scoped_refptr<MainThreadTaskQueue>& queue);
@@ -495,6 +475,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
kVirtual,
};
+ // WebThreadScheduler private implementation:
+ WebThreadScheduler* GetWebMainThreadScheduler() override;
+
static const char* TimeDomainTypeToString(TimeDomainType domain_type);
void AddAgentGroupScheduler(AgentGroupSchedulerImpl*);
@@ -527,11 +510,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
RAILMode& rail_mode() { return rail_mode_; }
RAILMode rail_mode() const { return rail_mode_; }
- bool& should_disable_throttling() { return should_disable_throttling_; }
- bool should_disable_throttling() const {
- return should_disable_throttling_;
- }
-
bool& frozen_when_backgrounded() { return frozen_when_backgrounded_; }
bool frozen_when_backgrounded() const { return frozen_when_backgrounded_; }
@@ -578,7 +556,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
bool operator==(const Policy& other) const {
return rail_mode_ == other.rail_mode_ &&
- should_disable_throttling_ == other.should_disable_throttling_ &&
frozen_when_backgrounded_ == other.frozen_when_backgrounded_ &&
should_prioritize_loading_with_compositing_ ==
other.should_prioritize_loading_with_compositing_ &&
@@ -601,7 +578,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
private:
RAILMode rail_mode_{RAILMode::kAnimation};
- bool should_disable_throttling_{false};
bool frozen_when_backgrounded_{false};
bool should_prioritize_loading_with_compositing_{false};
bool should_freeze_compositor_task_queue_{false};
@@ -627,10 +603,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
MainThreadSchedulerImpl* scheduler_; // NOT OWNED
};
- // AgentSchedulingStrategy::Delegate implementation:
- void OnSetTimer(const FrameSchedulerImpl& frame_scheduler,
- base::TimeDelta delay) override;
-
// IdleHelper::Delegate implementation:
bool CanEnterLongIdlePeriod(
base::TimeTicks now,
@@ -639,8 +611,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void OnIdlePeriodStarted() override;
void OnIdlePeriodEnded() override;
void OnPendingTasksChanged(bool has_tasks) override;
- void OnSafepointEntered() override;
- void OnSafepointExited() override;
void DispatchRequestBeginMainFrameNotExpected(bool has_tasks);
@@ -709,10 +679,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void UpdateForInputEventOnCompositorThread(const WebInputEvent& event,
InputEventState input_event_state);
- // Notifies the per-agent scheduling strategy that an input event occurred.
- void NotifyAgentSchedulerOnInputEvent();
- void OnAgentStrategyDelayPassed(base::WeakPtr<const FrameSchedulerImpl>);
-
// The task cost estimators and the UserModel need to be reset upon page
// nagigation. This function does that. Must be called from the main thread.
void ResetForNavigationLocked();
@@ -823,7 +789,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
MainThreadSchedulerHelper helper_;
scoped_refptr<MainThreadTaskQueue> idle_helper_queue_;
IdleHelper idle_helper_;
- std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
RenderWidgetSignals render_widget_scheduler_signals_;
std::unique_ptr<FindInPageBudgetPoolController>
@@ -861,12 +826,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
base::RepeatingClosure update_policy_closure_;
DeadlineTaskRunner delayed_update_policy_runner_;
CancelableClosureHolder end_renderer_hidden_idle_period_closure_;
- base::RepeatingClosure notify_agent_strategy_on_input_event_closure_;
- base::RepeatingCallback<void(base::WeakPtr<const FrameSchedulerImpl>)>
- agent_strategy_delay_callback_;
-
- std::unique_ptr<AgentSchedulingStrategy> agent_scheduling_strategy_ =
- AgentSchedulingStrategy::Create(*this);
// We have decided to improve thread safety at the cost of some boilerplate
// (the accessors) for the following data members.
@@ -933,9 +892,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
base::Time initial_virtual_time;
base::TimeTicks initial_virtual_time_ticks;
- // This is used for cross origin navigations to account for virtual time
- // advancing in the previous renderer.
- base::TimeDelta initial_virtual_time_offset;
VirtualTimePolicy virtual_time_policy;
// In VirtualTimePolicy::kDeterministicLoading virtual time is only allowed
@@ -1061,13 +1017,10 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
}
PollableThreadSafeFlag policy_may_need_update_;
- PollableThreadSafeFlag notify_agent_strategy_task_posted_;
WTF::HashSet<AgentGroupSchedulerImpl*> agent_group_schedulers_;
WebAgentGroupScheduler* current_agent_group_scheduler_{nullptr};
base::WeakPtrFactory<MainThreadSchedulerImpl> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImpl);
};
} // namespace scheduler
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 a6b55d5ebc2..61b5141a2c5 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/run_loop.h"
@@ -319,10 +318,9 @@ class MockPageSchedulerImpl : public PageSchedulerImpl {
.WillByDefault(Return(true));
ON_CALL(*this, IsMainFrameLocal).WillByDefault(Return(true));
}
- ~MockPageSchedulerImpl() override = default;
-
MockPageSchedulerImpl(const MockPageSchedulerImpl&) = delete;
MockPageSchedulerImpl& operator=(const MockPageSchedulerImpl&) = delete;
+ ~MockPageSchedulerImpl() override = default;
MOCK_METHOD(bool, RequestBeginMainFrameNotExpected, (bool));
MOCK_METHOD(bool, IsWaitingForMainFrameContentfulPaint, (), (const));
@@ -410,6 +408,10 @@ class MainThreadSchedulerImplTest : public testing::Test {
MainThreadSchedulerImplTest() : MainThreadSchedulerImplTest({}, {}) {}
+ MainThreadSchedulerImplTest(const MainThreadSchedulerImplTest&) = delete;
+ MainThreadSchedulerImplTest& operator=(const MainThreadSchedulerImplTest&) =
+ delete;
+
~MainThreadSchedulerImplTest() override = default;
void SetUp() override {
@@ -984,8 +986,6 @@ class MainThreadSchedulerImplTest : public testing::Test {
bool simulate_throttleable_task_ran_;
bool initially_ensure_usecase_none_ = true;
uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplTest);
};
TEST_F(MainThreadSchedulerImplTest, TestPostDefaultTask) {
@@ -2511,18 +2511,6 @@ TEST_F(MainThreadSchedulerImplTest, StopAndThrottleThrottleableQueue) {
EXPECT_THAT(run_order, testing::ElementsAre());
}
-TEST_F(MainThreadSchedulerImplTest, ThrottleAndPauseRenderer) {
- Vector<String> run_order;
- PostTestTasks(&run_order, "T1 T2");
-
- MainThreadTaskQueue::ThrottleHandle handle =
- throttleable_task_queue()->Throttle();
- base::RunLoop().RunUntilIdle();
- auto pause_handle = scheduler_->PauseRenderer();
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, testing::ElementsAre());
-}
-
TEST_F(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 T2");
@@ -2740,8 +2728,7 @@ TEST_F(
SYNCHRONIZED_GESTURE_ThrottleableTaskThrottling_ThrottleableQueuesStopped) {
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
- base::TimeTicks first_throttled_run_time =
- TaskQueueThrottler::AlignedThrottledRunTime(Now());
+ base::TimeTicks first_run_time = Now();
size_t count = 0;
// With the compositor task taking 10ms, there is not enough time to run this
@@ -2774,7 +2761,7 @@ TEST_F(
// 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) || (Now() > first_throttled_run_time);
+ bool expect_queue_enabled = (i == 0) || (Now() > first_run_time);
if (paused)
expect_queue_enabled = false;
EXPECT_EQ(expect_queue_enabled,
@@ -3142,8 +3129,7 @@ TEST_F(
TEST_F(MainThreadSchedulerImplTest, EnableVirtualTime) {
EXPECT_FALSE(scheduler_->IsVirtualTimeEnabled());
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
EXPECT_TRUE(scheduler_->IsVirtualTimeEnabled());
scoped_refptr<MainThreadTaskQueue> loading_tq =
scheduler_->NewLoadingTaskQueue(
@@ -3218,16 +3204,14 @@ TEST_F(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
frame_scheduler->SetFrameVisible(false);
EXPECT_TRUE(throttleable_tq->IsThrottled());
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
EXPECT_EQ(throttleable_tq->GetTaskQueue()->GetTimeDomain(),
scheduler_->GetVirtualTimeDomain());
- EXPECT_FALSE(throttleable_tq->IsThrottled());
+ EXPECT_TRUE(throttleable_tq->IsThrottled());
}
TEST_F(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) {
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
scheduler_->DisableVirtualTimeForTesting();
EXPECT_EQ(scheduler_->DefaultTaskQueue()->GetTaskQueue()->GetTimeDomain(),
scheduler_->real_time_domain());
@@ -3245,8 +3229,7 @@ TEST_F(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) {
}
TEST_F(MainThreadSchedulerImplTest, VirtualTimePauser) {
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
scheduler_->SetVirtualTimePolicy(
PageSchedulerImpl::VirtualTimePolicy::kDeterministicLoading);
@@ -3266,8 +3249,7 @@ TEST_F(MainThreadSchedulerImplTest, VirtualTimePauser) {
}
TEST_F(MainThreadSchedulerImplTest, VirtualTimePauserNonInstantTask) {
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
scheduler_->SetVirtualTimePolicy(
PageSchedulerImpl::VirtualTimePolicy::kDeterministicLoading);
@@ -3286,8 +3268,7 @@ TEST_F(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) {
// This test ensures that we do not do anything strange like stopping
// processing task queues after we encountered one task queue with
// DoNotUseVirtualTime trait.
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
scheduler_->SetVirtualTimePolicy(
PageSchedulerImpl::VirtualTimePolicy::kDeterministicLoading);
@@ -3345,11 +3326,11 @@ TEST_F(MainThreadSchedulerImplTest, Tracing) {
CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
scheduler_->AddPageScheduler(page_scheduler2.get());
- CPUTimeBudgetPool* time_budget_pool =
- scheduler_->task_queue_throttler()->CreateCPUTimeBudgetPool("test");
+ std::unique_ptr<CPUTimeBudgetPool> time_budget_pool =
+ scheduler_->CreateCPUTimeBudgetPoolForTesting("test");
- time_budget_pool->AddQueue(base::TimeTicks(),
- throttleable_task_queue()->GetTaskQueue());
+ throttleable_task_queue()->AddToBudgetPool(base::TimeTicks(),
+ time_budget_pool.get());
throttleable_task_runner_->PostTask(FROM_HERE, base::BindOnce(NullTask));
@@ -3604,8 +3585,7 @@ TEST_F(MainThreadSchedulerImplTest, TaskQueueReferenceClearedOnShutdown) {
scheduler_->OnShutdownTaskQueue(queue1);
- scheduler_->EnableVirtualTime(
- MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
+ scheduler_->EnableVirtualTime();
// Virtual time should be enabled for queue2, as it is a regular queue and
// nothing should change for queue1 because it was shut down.
@@ -3939,212 +3919,6 @@ TEST_F(VeryHighPriorityForCompositingAfterDelayExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-class VeryHighPriorityForCompositingBudgetExperimentTest
- : public MainThreadSchedulerImplTest {
- public:
- VeryHighPriorityForCompositingBudgetExperimentTest()
- : MainThreadSchedulerImplTest({kVeryHighPriorityForCompositingBudget},
- {}) {}
-};
-
-TEST_F(VeryHighPriorityForCompositingBudgetExperimentTest,
- TestCompositorPolicy_CompositorPriorityVeryHighToNormal) {
- Vector<String> run_order;
- PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
- EnableIdleTasks();
- base::RunLoop().RunUntilIdle();
-
- // Compositor is at kVeryHighPriority Initially.
- EXPECT_THAT(run_order,
- testing::ElementsAre("P1", "C1", "C2", "D1", "D2", "I1"));
- EXPECT_EQ(UseCase::kNone, CurrentUseCase());
-
- // 1000ms BeginMainFrame compositor task will exhaust the budget. Compositor
- // tasks will be run at normal priority.
- DoMainFrame();
- RunSlowCompositorTask();
-
- run_order.clear();
- PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
- EnableIdleTasks();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order,
- testing::ElementsAre("P1", "D1", "C1", "D2", "C2", "I1"));
- EXPECT_EQ(UseCase::kNone, CurrentUseCase());
-}
-
-TEST_F(VeryHighPriorityForCompositingBudgetExperimentTest,
- TestCompositorPolicy_CompositorPriorityNormalToVeryHigh) {
- // 1000ms BeginMainFrame compositor task will exhaust the budget.
- DoMainFrame();
- RunSlowCompositorTask();
-
- Vector<String> run_order;
- PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
- EnableIdleTasks();
- base::RunLoop().RunUntilIdle();
-
- // Compositor is at kNormalPriority, it will inteleave with default tasks.
- EXPECT_THAT(run_order,
- testing::ElementsAre("P1", "D1", "C1", "D2", "C2", "I1"));
- EXPECT_EQ(UseCase::kNone, CurrentUseCase());
-
- // Recover the budget.
- AdvanceTimeWithTask(12);
-
- run_order.clear();
- PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
- EnableIdleTasks();
- base::RunLoop().RunUntilIdle();
-
- // Compositor is now at kVeryHighPriority, compositing tasks will run
- // before default tasks.
- EXPECT_THAT(run_order,
- testing::ElementsAre("P1", "C1", "C2", "D1", "D2", "I1"));
- EXPECT_EQ(UseCase::kNone, CurrentUseCase());
-}
-
-class DisableNonMainTimerQueuesUntilFMPTest
- : public MainThreadSchedulerImplTest {
- public:
- DisableNonMainTimerQueuesUntilFMPTest()
- : MainThreadSchedulerImplTest({{kPerAgentSchedulingExperiments,
- {{"queues", "timer-queues"},
- {"method", "disable"},
- {"signal", "fmp"}}}}) {}
-};
-
-TEST_F(DisableNonMainTimerQueuesUntilFMPTest, DisablesOnlyNonMainTimerQueue) {
- auto page_scheduler =
- CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
-
- NiceMock<MockFrameDelegate> frame_delegate{};
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr,
- FrameScheduler::FrameType::kSubframe);
-
- scoped_refptr<MainThreadTaskQueue> throttleable_tq = QueueForTaskType(
- frame_scheduler.get(), TaskType::kJavascriptTimerDelayedLowNesting);
- ForceUpdatePolicyAndGetCurrentUseCase();
-
- EXPECT_FALSE(throttleable_tq->GetTaskQueue()->IsQueueEnabled());
-
- ignore_result(
- scheduler_->agent_scheduling_strategy().OnMainFrameFirstMeaningfulPaint(
- *main_frame_scheduler_));
- ForceUpdatePolicyAndGetCurrentUseCase();
-
- EXPECT_TRUE(throttleable_tq->GetTaskQueue()->IsQueueEnabled());
-}
-
-TEST_F(DisableNonMainTimerQueuesUntilFMPTest,
- ShouldNotifyAgentStrategyOnInput) {
- auto page_scheduler =
- CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
-
- NiceMock<MockFrameDelegate> frame_delegate{};
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr,
- FrameScheduler::FrameType::kSubframe);
-
- scoped_refptr<MainThreadTaskQueue> timer_tq = QueueForTaskType(
- frame_scheduler.get(), TaskType::kJavascriptTimerDelayedLowNesting);
-
- FakeInputEvent mouse_move_event{WebInputEvent::Type::kMouseMove,
- blink::WebInputEvent::kLeftButtonDown};
- FakeInputEvent mouse_down_event{WebInputEvent::Type::kMouseDown,
- blink::WebInputEvent::kLeftButtonDown};
- InputEventState event_state{};
-
- // Mouse move event should be ignored, meaning the queue should be disabled.
- scheduler_->DidHandleInputEventOnCompositorThread(mouse_move_event,
- event_state);
- ForceUpdatePolicyAndGetCurrentUseCase();
- EXPECT_FALSE(timer_tq->GetTaskQueue()->IsQueueEnabled());
-
- // Mouse down should cause MTSI to notify the agent scheduling strategy, which
- // should re-enable the throttleable queue.
- scheduler_->DidHandleInputEventOnCompositorThread(mouse_down_event,
- event_state);
- base::RunLoop().RunUntilIdle(); // Notification is posted to the main thread.
- EXPECT_TRUE(timer_tq->GetTaskQueue()->IsQueueEnabled());
-}
-
-class BestEffortNonMainQueuesUntilOnLoadTest
- : public MainThreadSchedulerImplTest {
- public:
- BestEffortNonMainQueuesUntilOnLoadTest()
- : MainThreadSchedulerImplTest({{kPerAgentSchedulingExperiments,
- {{"queues", "all-queues"},
- {"method", "best-effort"},
- {"signal", "onload"}}}}) {}
-};
-
-TEST_F(BestEffortNonMainQueuesUntilOnLoadTest, DeprioritizesAllNonMainQueues) {
- auto page_scheduler =
- CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
-
- NiceMock<MockFrameDelegate> frame_delegate{};
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr,
- FrameScheduler::FrameType::kSubframe);
-
- scoped_refptr<MainThreadTaskQueue> non_timer_tq =
- QueueForTaskType(frame_scheduler.get(), TaskType::kNetworking);
- ForceUpdatePolicyAndGetCurrentUseCase();
- EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(),
- TaskQueue::QueuePriority::kBestEffortPriority);
-
- scheduler_->OnMainFrameLoad(*main_frame_scheduler_);
-
- EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(),
- TaskQueue::QueuePriority::kNormalPriority);
-}
-
-class BestEffortNonMainQueuesUntilOnFMPTimeoutTest
- : public MainThreadSchedulerImplTest {
- public:
- BestEffortNonMainQueuesUntilOnFMPTimeoutTest()
- : MainThreadSchedulerImplTest({{kPerAgentSchedulingExperiments,
- {{"queues", "all-queues"},
- {"method", "best-effort"},
- {"signal", "fmp"},
- {"delay_ms", "1000"}}}}) {}
-};
-
-TEST_F(BestEffortNonMainQueuesUntilOnFMPTimeoutTest,
- DeprioritizesNonMainQueues) {
- auto page_scheduler = CreatePageScheduler(
- /* page_scheduler_delegate= */ nullptr, scheduler_.get(),
- *agent_group_scheduler_);
-
- NiceMock<MockFrameDelegate> frame_delegate{};
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler = CreateFrameScheduler(
- page_scheduler.get(), &frame_delegate, /* blame_context= */ nullptr,
- FrameScheduler::FrameType::kSubframe);
-
- scoped_refptr<MainThreadTaskQueue> non_timer_tq =
- QueueForTaskType(frame_scheduler.get(), TaskType::kNetworking);
- ForceUpdatePolicyAndGetCurrentUseCase();
- EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(),
- TaskQueue::QueuePriority::kBestEffortPriority);
-
- ignore_result(
- scheduler_->agent_scheduling_strategy().OnMainFrameFirstMeaningfulPaint(
- *main_frame_scheduler_));
-
- // Queue should still have lower priority, since we just started counting
- // towards the timeout.
- EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(),
- TaskQueue::QueuePriority::kBestEffortPriority);
-
- test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1000));
-
- EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(),
- TaskQueue::QueuePriority::kNormalPriority);
-}
-
TEST_F(MainThreadSchedulerImplTest, ThrottleHandleThrottlesQueue) {
EXPECT_FALSE(throttleable_task_queue()->IsThrottled());
{
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 eed8a8c649e..f45ef3bc99a 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
@@ -115,7 +115,14 @@ MainThreadTaskQueue::MainThreadTaskQueue(
agent_group_scheduler_(params.agent_group_scheduler),
frame_scheduler_(params.frame_scheduler) {
task_queue_ = base::MakeRefCounted<TaskQueue>(std::move(impl), spec);
+ // Throttling needs |should_notify_observers| to get task timing.
+ DCHECK(!params.queue_traits.can_be_throttled || spec.should_notify_observers)
+ << "Throttled queue is not supported with |!should_notify_observers|";
if (task_queue_->HasImpl() && spec.should_notify_observers) {
+ if (params.queue_traits.can_be_throttled) {
+ throttler_.emplace(task_queue_.get(),
+ main_thread_scheduler_->GetTickClock());
+ }
// TaskQueueImpl may be null for tests.
// TODO(scheduler-dev): Consider mapping directly to
// MainThreadSchedulerImpl::OnTaskStarted/Completed. At the moment this
@@ -128,7 +135,9 @@ MainThreadTaskQueue::MainThreadTaskQueue(
}
}
-MainThreadTaskQueue::~MainThreadTaskQueue() = default;
+MainThreadTaskQueue::~MainThreadTaskQueue() {
+ DCHECK(!wake_up_budget_pool_);
+}
void MainThreadTaskQueue::OnTaskStarted(
const base::sequence_manager::Task& task,
@@ -149,8 +158,10 @@ void MainThreadTaskQueue::OnTaskCompleted(
void MainThreadTaskQueue::OnTaskRunTimeReported(
TaskQueue::TaskTiming* task_timing) {
- main_thread_scheduler_->task_queue_throttler()->OnTaskRunTimeReported(
- task_queue_.get(), task_timing->start_time(), task_timing->end_time());
+ if (throttler_) {
+ throttler_->OnTaskRunTimeReported(task_timing->start_time(),
+ task_timing->end_time());
+ }
}
void MainThreadTaskQueue::DetachFromMainThreadScheduler() {
@@ -191,6 +202,7 @@ void MainThreadTaskQueue::DetachOnIPCTaskPostedWhileInBackForwardCache() {
void MainThreadTaskQueue::ShutdownTaskQueue() {
ClearReferencesToSchedulers();
+ throttler_.reset();
task_queue_->ShutdownTaskQueue();
}
@@ -212,11 +224,6 @@ WebAgentGroupScheduler* MainThreadTaskQueue::GetAgentGroupScheduler() {
void MainThreadTaskQueue::ClearReferencesToSchedulers() {
if (main_thread_scheduler_) {
main_thread_scheduler_->OnShutdownTaskQueue(this);
-
- if (main_thread_scheduler_->task_queue_throttler()) {
- main_thread_scheduler_->task_queue_throttler()->ShutdownTaskQueue(
- task_queue_.get());
- }
}
main_thread_scheduler_ = nullptr;
agent_group_scheduler_ = nullptr;
@@ -251,6 +258,10 @@ void MainThreadTaskQueue::SetWebSchedulingPriority(
frame_scheduler_->OnWebSchedulingTaskQueuePriorityChanged(this);
}
+void MainThreadTaskQueue::OnWebSchedulingTaskQueueDestroyed() {
+ frame_scheduler_->OnWebSchedulingTaskQueueDestroyed(this);
+}
+
absl::optional<WebSchedulingPriority>
MainThreadTaskQueue::web_scheduling_priority() const {
return web_scheduling_priority_;
@@ -258,8 +269,7 @@ MainThreadTaskQueue::web_scheduling_priority() const {
bool MainThreadTaskQueue::IsThrottled() const {
if (main_thread_scheduler_) {
- return main_thread_scheduler_->task_queue_throttler()->IsThrottled(
- task_queue_.get());
+ return throttler_.has_value() && throttler_->IsThrottled();
} else {
// When the frame detaches the task queue is removed from the throttler.
return false;
@@ -268,32 +278,29 @@ bool MainThreadTaskQueue::IsThrottled() const {
MainThreadTaskQueue::ThrottleHandle MainThreadTaskQueue::Throttle() {
DCHECK(CanBeThrottled());
- return ThrottleHandle(
- task_queue_.get()->AsWeakPtr(),
- main_thread_scheduler_->task_queue_throttler()->AsWeakPtr());
+ return ThrottleHandle(AsWeakPtr());
}
void MainThreadTaskQueue::AddToBudgetPool(base::TimeTicks now,
BudgetPool* pool) {
- pool->AddQueue(now, task_queue_.get());
+ pool->AddThrottler(now, &throttler_.value());
}
void MainThreadTaskQueue::RemoveFromBudgetPool(base::TimeTicks now,
BudgetPool* pool) {
- pool->RemoveQueue(now, task_queue_.get());
+ pool->RemoveThrottler(now, &throttler_.value());
}
-void MainThreadTaskQueue::SetImmediateWakeUpForTest() {
- if (main_thread_scheduler_) {
- main_thread_scheduler_->task_queue_throttler()->OnQueueNextWakeUpChanged(
- task_queue_.get(), base::TimeTicks());
- }
+void MainThreadTaskQueue::SetWakeUpBudgetPool(
+ WakeUpBudgetPool* wake_up_budget_pool) {
+ wake_up_budget_pool_ = wake_up_budget_pool;
}
void MainThreadTaskQueue::WriteIntoTrace(perfetto::TracedValue context) const {
auto dict = std::move(context).WriteDictionary();
dict.Add("type", queue_type_);
dict.Add("traits", queue_traits_);
+ dict.Add("throttler", throttler_);
}
void MainThreadTaskQueue::QueueTraits::WriteIntoTrace(
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 6f5c7c7aabe..5c6edb27fc5 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
@@ -13,6 +13,7 @@
#include "base/task/sequence_manager/task_queue_impl.h"
#include "base/task/sequence_manager/time_domain.h"
#include "net/base/request_priority.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h"
@@ -41,6 +42,7 @@ class TaskQueueThrottlerTest;
class FrameSchedulerImpl;
class MainThreadSchedulerImpl;
+class WakeUpBudgetPool;
// TODO(kdillon): Remove ref-counting of MainThreadTaskQueues as it's no longer
// needed.
@@ -100,29 +102,25 @@ class PLATFORM_EXPORT MainThreadTaskQueue
// the queue will remain throttled as long as the handle is alive.
class ThrottleHandle {
public:
- ThrottleHandle(base::WeakPtr<TaskQueue> task_queue,
- base::WeakPtr<TaskQueueThrottler> throttler)
- : task_queue_(std::move(task_queue)), throttler_(std::move(throttler)) {
- if (task_queue_ && throttler_)
- throttler_->IncreaseThrottleRefCount(task_queue_.get());
+ explicit ThrottleHandle(base::WeakPtr<MainThreadTaskQueue> task_queue)
+ : task_queue_(std::move(task_queue)) {
+ if (task_queue_)
+ task_queue_->throttler_->IncreaseThrottleRefCount();
}
~ThrottleHandle() {
- if (task_queue_ && throttler_)
- throttler_->DecreaseThrottleRefCount(task_queue_.get());
+ if (task_queue_)
+ task_queue_->throttler_->DecreaseThrottleRefCount();
}
// Move-only.
ThrottleHandle(ThrottleHandle&& other)
- : task_queue_(std::move(other.task_queue_)),
- throttler_(std::move(other.throttler_)) {
+ : task_queue_(std::move(other.task_queue_)) {
other.task_queue_ = nullptr;
- other.throttler_ = nullptr;
}
ThrottleHandle& operator=(ThrottleHandle&&);
private:
- base::WeakPtr<TaskQueue> task_queue_;
- base::WeakPtr<TaskQueueThrottler> throttler_;
+ base::WeakPtr<MainThreadTaskQueue> task_queue_;
};
// Returns name of the given queue type. Returned string has application
@@ -165,8 +163,9 @@ class PLATFORM_EXPORT MainThreadTaskQueue
kHighPriorityLocalFrame = 8,
kCompositor = 9, // Main-thread only.
kInput = 10,
+ kPostMessageForwarding = 11,
- kCount = 11
+ kCount = 12
};
// kPrioritisationTypeWidthBits is the number of bits required
@@ -181,6 +180,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
"Wrong Instanstiation for kPrioritisationTypeWidthBits");
QueueTraits(const QueueTraits&) = default;
+ QueueTraits& operator=(const QueueTraits&) = default;
QueueTraits SetCanBeDeferred(bool value) {
can_be_deferred = value;
@@ -458,6 +458,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue
void SetWebSchedulingPriority(WebSchedulingPriority priority);
absl::optional<WebSchedulingPriority> web_scheduling_priority() const;
+ void OnWebSchedulingTaskQueueDestroyed();
+
// TODO(kdillon): Improve MTTQ API surface so that we no longer
// need to expose the raw pointer to the queue.
TaskQueue* GetTaskQueue() { return task_queue_.get(); }
@@ -485,9 +487,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue
void AddToBudgetPool(base::TimeTicks now, BudgetPool* pool);
void RemoveFromBudgetPool(base::TimeTicks now, BudgetPool* pool);
- // This method is only used for tests. If this queue is throttled it will
- // notify the throttler that this queue should wake immediately.
- void SetImmediateWakeUpForTest();
+ void SetWakeUpBudgetPool(WakeUpBudgetPool* wake_up_budget_pool);
+ WakeUpBudgetPool* GetWakeUpBudgetPool() const { return wake_up_budget_pool_; }
base::WeakPtr<MainThreadTaskQueue> AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
@@ -511,6 +512,9 @@ class PLATFORM_EXPORT MainThreadTaskQueue
const QueueCreationParams& params,
MainThreadSchedulerImpl* main_thread_scheduler);
+ MainThreadTaskQueue(const MainThreadTaskQueue&) = delete;
+ MainThreadTaskQueue& operator=(const MainThreadTaskQueue&) = delete;
+
~MainThreadTaskQueue();
private:
@@ -527,6 +531,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
void ClearReferencesToSchedulers();
scoped_refptr<TaskQueue> task_queue_;
+ absl::optional<TaskQueueThrottler> throttler_;
const QueueType queue_type_;
const QueueTraits queue_traits_;
@@ -553,9 +558,10 @@ class PLATFORM_EXPORT MainThreadTaskQueue
// be set to a different value afterwards (except in tests).
FrameSchedulerImpl* frame_scheduler_; // NOT OWNED
- base::WeakPtrFactory<MainThreadTaskQueue> weak_ptr_factory_{this};
+ // The WakeUpBudgetPool for this TaskQueue, if any.
+ WakeUpBudgetPool* wake_up_budget_pool_{nullptr}; // NOT OWNED
- DISALLOW_COPY_AND_ASSIGN(MainThreadTaskQueue);
+ base::WeakPtrFactory<MainThreadTaskQueue> weak_ptr_factory_{this};
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc
index 5865e9999f4..712e2d0a85a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/message_loop/message_pump.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
@@ -48,6 +47,8 @@ class MockTaskObserver : public Thread::TaskObserver {
class MainThreadTest : public testing::Test {
public:
MainThreadTest() = default;
+ MainThreadTest(const MainThreadTest&) = delete;
+ MainThreadTest& operator=(const MainThreadTest&) = delete;
void SetUp() override {
clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
@@ -77,8 +78,6 @@ class MainThreadTest : public testing::Test {
std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
std::unique_ptr<ScopedSchedulerOverrider> scheduler_overrider_;
Thread* thread_;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadTest);
};
TEST_F(MainThreadTest, TestTaskObserver) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc
new file mode 100644
index 00000000000..a14b6e55102
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc
@@ -0,0 +1,81 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h"
+
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner::
+ WebSchedulingTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> immediate_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> delayed_task_runner)
+ : immediate_task_runner_(std::move(immediate_task_runner)),
+ delayed_task_runner_(std::move(delayed_task_runner)) {}
+
+bool MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner::
+ PostDelayedTask(const base::Location& location,
+ base::OnceClosure task,
+ base::TimeDelta delay) {
+ return GetTaskRunnerForDelay(delay)->PostDelayedTask(location,
+ std::move(task), delay);
+}
+
+bool MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner::
+ PostNonNestableDelayedTask(const base::Location& location,
+ base::OnceClosure task,
+ base::TimeDelta delay) {
+ return GetTaskRunnerForDelay(delay)->PostNonNestableDelayedTask(
+ location, std::move(task), delay);
+}
+
+bool MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner::
+ RunsTasksInCurrentSequence() const {
+ DCHECK_EQ(immediate_task_runner_->RunsTasksInCurrentSequence(),
+ delayed_task_runner_->RunsTasksInCurrentSequence());
+ return immediate_task_runner_->RunsTasksInCurrentSequence();
+}
+
+base::SingleThreadTaskRunner* MainThreadWebSchedulingTaskQueueImpl::
+ WebSchedulingTaskRunner::GetTaskRunnerForDelay(base::TimeDelta delay) {
+ return delay > base::TimeDelta() ? delayed_task_runner_.get()
+ : immediate_task_runner_.get();
+}
+
+MainThreadWebSchedulingTaskQueueImpl::MainThreadWebSchedulingTaskQueueImpl(
+ base::WeakPtr<MainThreadTaskQueue> immediate_task_queue,
+ base::WeakPtr<MainThreadTaskQueue> delayed_task_queue)
+ : task_runner_(base::MakeRefCounted<WebSchedulingTaskRunner>(
+ immediate_task_queue->CreateTaskRunner(
+ TaskType::kExperimentalWebScheduling),
+ delayed_task_queue->CreateTaskRunner(
+ TaskType::kExperimentalWebScheduling))),
+ immediate_task_queue_(std::move(immediate_task_queue)),
+ delayed_task_queue_(std::move(delayed_task_queue)) {}
+
+MainThreadWebSchedulingTaskQueueImpl::~MainThreadWebSchedulingTaskQueueImpl() {
+ if (immediate_task_queue_)
+ immediate_task_queue_->OnWebSchedulingTaskQueueDestroyed();
+ if (delayed_task_queue_)
+ delayed_task_queue_->OnWebSchedulingTaskQueueDestroyed();
+}
+
+void MainThreadWebSchedulingTaskQueueImpl::SetPriority(
+ WebSchedulingPriority priority) {
+ if (immediate_task_queue_)
+ immediate_task_queue_->SetWebSchedulingPriority(priority);
+ if (delayed_task_queue_)
+ delayed_task_queue_->SetWebSchedulingPriority(priority);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+MainThreadWebSchedulingTaskQueueImpl::GetTaskRunner() {
+ return task_runner_;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h
new file mode 100644
index 00000000000..33ac23e160c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
+
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
+
+#include "base/memory/scoped_refptr.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/public/web_scheduling_priority.h"
+
+namespace blink {
+namespace scheduler {
+
+class MainThreadTaskQueue;
+
+class PLATFORM_EXPORT MainThreadWebSchedulingTaskQueueImpl
+ : public WebSchedulingTaskQueue {
+ public:
+ MainThreadWebSchedulingTaskQueueImpl(
+ base::WeakPtr<MainThreadTaskQueue> immediate_task_queue,
+ base::WeakPtr<MainThreadTaskQueue> delayed_task_queue);
+ ~MainThreadWebSchedulingTaskQueueImpl() override;
+
+ void SetPriority(WebSchedulingPriority) override;
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
+
+ private:
+ // In order to throttle delayed tasks in the background, we manage two
+ // MainThreadTaskQueues and their associated TaskRunners---one for delayed
+ // tasks and one for non-delayed tasks (immediate). Rather than exposing this
+ // to the web scheduling layer, we implement a simple custom TaskRunner that
+ // handles picking the appropriate underlying TaskRunner based on the delay
+ // value and return that in GetTaskRunner().
+ class WebSchedulingTaskRunner : public base::SingleThreadTaskRunner {
+ public:
+ WebSchedulingTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> immediate_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> delayed_task_runner);
+
+ bool PostDelayedTask(const base::Location& location,
+ base::OnceClosure task,
+ base::TimeDelta delay) override;
+ bool PostNonNestableDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override;
+ bool RunsTasksInCurrentSequence() const override;
+
+ private:
+ base::SingleThreadTaskRunner* GetTaskRunnerForDelay(base::TimeDelta delay);
+
+ const scoped_refptr<base::SingleThreadTaskRunner> immediate_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> delayed_task_runner_;
+ };
+
+ scoped_refptr<WebSchedulingTaskRunner> task_runner_;
+ base::WeakPtr<MainThreadTaskQueue> immediate_task_queue_;
+ base::WeakPtr<MainThreadTaskQueue> delayed_task_queue_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
index 70508be6a54..c2393d0566f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MEMORY_PURGE_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MEMORY_PURGE_MANAGER_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/timer/timer.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -17,6 +16,8 @@ namespace blink {
class PLATFORM_EXPORT MemoryPurgeManager {
public:
MemoryPurgeManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ MemoryPurgeManager(const MemoryPurgeManager&) = delete;
+ MemoryPurgeManager& operator=(const MemoryPurgeManager&) = delete;
~MemoryPurgeManager();
// Called when a page is created or destroyed, to maintain the total count of
@@ -100,8 +101,6 @@ class PLATFORM_EXPORT MemoryPurgeManager {
// Timer to delay memory purging.
base::OneShotTimer purge_timer_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
index 9e5bb83e57f..c298db2747e 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
@@ -26,6 +26,8 @@ class MemoryPurgeManagerTest : public testing::Test {
: task_environment_(base::test::TaskEnvironment::MainThreadType::UI,
base::test::TaskEnvironment::TimeSource::MOCK_TIME),
memory_purge_manager_(task_environment_.GetMainThreadTaskRunner()) {}
+ MemoryPurgeManagerTest(const MemoryPurgeManagerTest&) = delete;
+ MemoryPurgeManagerTest& operator=(const MemoryPurgeManagerTest&) = delete;
void SetUp() override {
memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
@@ -67,8 +69,6 @@ class MemoryPurgeManagerTest : public testing::Test {
void OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel) {
memory_pressure_count_++;
}
-
- DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManagerTest);
};
// Verify that OnPageFrozen() triggers a memory pressure notification in a
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 5a3caa8f6e9..08564b41eee 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
@@ -19,7 +19,9 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.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/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"
@@ -42,11 +44,6 @@ constexpr double kDefaultMaxBackgroundBudgetLevelInSeconds = 3;
constexpr double kDefaultInitialBackgroundBudgetInSeconds = 1;
constexpr double kDefaultMaxBackgroundThrottlingDelayInSeconds = 0;
-// Given that we already align timers to 1Hz, do not report throttling if
-// it is under 3s.
-constexpr base::TimeDelta kMinimalBackgroundThrottlingDurationToReport =
- base::TimeDelta::FromSeconds(3);
-
// Delay for fully throttling the page after backgrounding.
constexpr base::TimeDelta kThrottlingDelayAfterBackgrounding =
base::TimeDelta::FromSeconds(10);
@@ -69,6 +66,12 @@ constexpr base::TimeDelta kDefaultDelayForBackgroundAndNetworkIdleTabFreezing =
constexpr base::TimeDelta kThrottledWakeUpDuration =
base::TimeDelta::FromMilliseconds(3);
+// The duration for which intensive throttling should be inhibited for
+// same-origin frames when the page title or favicon is updated.
+constexpr base::TimeDelta
+ kTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate =
+ base::TimeDelta::FromSeconds(3);
+
constexpr base::TimeDelta kDefaultDelayForTrackingIPCsPostedToCachedFrames =
base::TimeDelta::FromSeconds(15);
@@ -167,6 +170,7 @@ base::TimeDelta GetTimeToDelayIPCTrackingWhileStoredInBackForwardCache() {
} // namespace
constexpr base::TimeDelta PageSchedulerImpl::kDefaultThrottledWakeUpInterval;
+constexpr base::TimeDelta PageSchedulerImpl::kIntensiveThrottledWakeUpInterval;
PageSchedulerImpl::PageSchedulerImpl(
PageScheduler::Delegate* delegate,
@@ -179,7 +183,6 @@ PageSchedulerImpl::PageSchedulerImpl(
main_thread_scheduler_->GetTickClock()->NowTicks()),
audio_state_(AudioState::kSilent),
is_frozen_(false),
- reported_background_throttling_since_navigation_(false),
opted_out_from_aggressive_throttling_(false),
nested_runloop_(false),
is_main_frame_local_(false),
@@ -187,13 +190,16 @@ PageSchedulerImpl::PageSchedulerImpl(
are_wake_ups_intensively_throttled_(false),
keep_active_(main_thread_scheduler_->SchedulerKeepActive()),
had_recent_title_or_favicon_update_(false),
- focused_(delegate ? delegate->IsFocused() : true),
delegate_(delegate),
delay_for_background_tab_freezing_(GetDelayForBackgroundTabFreezing()),
freeze_on_network_idle_enabled_(base::FeatureList::IsEnabled(
blink::features::kFreezeBackgroundTabOnNetworkIdle)),
delay_for_background_and_network_idle_tab_freezing_(
- GetDelayForBackgroundAndNetworkIdleTabFreezing()) {
+ GetDelayForBackgroundAndNetworkIdleTabFreezing()),
+ throttle_foreground_timers_(
+ base::FeatureList::IsEnabled(kThrottleForegroundTimers)),
+ foreground_timers_throttled_wake_up_interval_(
+ GetForegroundTimersThrottledWakeUpInterval()) {
page_lifecycle_state_tracker_ = std::make_unique<PageLifecycleStateTracker>(
this, kDefaultPageVisibility == PageVisibilityState::kVisible
? PageLifecycleState::kActive
@@ -219,15 +225,6 @@ PageSchedulerImpl::~PageSchedulerImpl() {
frame_scheduler->DetachFromPageScheduler();
}
main_thread_scheduler_->RemovePageScheduler(this);
-
- if (cpu_time_budget_pool_)
- cpu_time_budget_pool_->Close();
- if (HasWakeUpBudgetPools()) {
- for (WakeUpBudgetPool* pool : AllWakeUpBudgetPools()) {
- DCHECK(pool);
- pool->Close();
- }
- }
}
// static
@@ -271,6 +268,7 @@ void PageSchedulerImpl::SetPageVisible(bool page_visible) {
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->SetPageVisibilityForTracing(page_visibility_);
+ MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate();
UpdatePolicyOnVisibilityChange(NotificationPolicy::kDoNotNotifyFrames);
NotifyFrames();
@@ -366,13 +364,6 @@ void PageSchedulerImpl::SetPageBackForwardCached(
}
}
-void PageSchedulerImpl::OnFocusChanged(bool focused) {
- DCHECK_NE(focused_, focused);
-
- focused_ = focused;
- NotifyFrames();
-}
-
void PageSchedulerImpl::SetUpIPCTaskDetection() {
DCHECK(is_stored_in_back_forward_cache_);
has_ipc_detection_enabled_ = true;
@@ -432,7 +423,6 @@ void PageSchedulerImpl::RegisterFrameSchedulerImpl(
MaybeInitializeBackgroundCPUTimeBudgetPool(&lazy_now);
frame_schedulers_.insert(frame_scheduler);
- main_thread_scheduler_->OnFrameAdded(*frame_scheduler);
frame_scheduler->UpdatePolicy();
}
@@ -449,11 +439,6 @@ std::unique_ptr<blink::FrameScheduler> PageSchedulerImpl::CreateFrameScheduler(
void PageSchedulerImpl::Unregister(FrameSchedulerImpl* frame_scheduler) {
DCHECK(frame_schedulers_.find(frame_scheduler) != frame_schedulers_.end());
frame_schedulers_.erase(frame_scheduler);
- main_thread_scheduler_->OnFrameRemoved(*frame_scheduler);
-}
-
-void PageSchedulerImpl::OnNavigation() {
- reported_background_throttling_since_navigation_ = false;
}
void PageSchedulerImpl::ReportIntervention(const String& message) {
@@ -476,10 +461,6 @@ void PageSchedulerImpl::SetInitialVirtualTime(base::Time time) {
main_thread_scheduler_->SetInitialVirtualTime(time);
}
-void PageSchedulerImpl::SetInitialVirtualTimeOffset(base::TimeDelta offset) {
- main_thread_scheduler_->SetInitialVirtualTimeOffset(offset);
-}
-
bool PageSchedulerImpl::VirtualTimeAllowedToAdvance() const {
return main_thread_scheduler_->VirtualTimeAllowedToAdvance();
}
@@ -507,6 +488,7 @@ void PageSchedulerImpl::AudioStateChanged(bool is_audio_playing) {
SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames);
NotifyFrames();
main_thread_scheduler_->OnAudioStateChanged();
+ MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate();
} else {
if (audio_state_ != AudioState::kAudible)
return;
@@ -529,6 +511,7 @@ void PageSchedulerImpl::OnAudioSilent() {
if (IsBackgrounded()) {
page_lifecycle_state_tracker_->SetPageLifecycleState(
PageLifecycleState::kHiddenBackgrounded);
+ MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate();
}
if (ShouldFreezePage()) {
main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
@@ -599,8 +582,14 @@ void PageSchedulerImpl::OnTraceLogEnabled() {
}
}
-bool PageSchedulerImpl::IsPageFocused() const {
- return focused_;
+void PageSchedulerImpl::OnFirstContentfulPaintInMainFrame() {
+ // Now we get the FCP notification here only for the main frame, notify all
+ // frames within the page to recompute priority for JS timer tasks.
+ if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) &&
+ kDeprioritizeDOMTimersPhase.Get() ==
+ DeprioritizeDOMTimersPhase::kFirstContentfulPaint) {
+ NotifyFrames();
+ }
}
bool PageSchedulerImpl::IsWaitingForMainFrameContentfulPaint() const {
@@ -621,54 +610,84 @@ bool PageSchedulerImpl::IsWaitingForMainFrameMeaningfulPaint() const {
});
}
-void PageSchedulerImpl::WriteIntoTrace(perfetto::TracedValue context) const {
+void PageSchedulerImpl::WriteIntoTrace(perfetto::TracedValue context,
+ base::TimeTicks now) const {
auto dict = std::move(context).WriteDictionary();
dict.Add("page_visible", page_visibility_ == PageVisibilityState::kVisible);
dict.Add("is_audio_playing", IsAudioPlaying());
dict.Add("is_frozen", is_frozen_);
- dict.Add("reported_background_throttling_since_navigation",
- reported_background_throttling_since_navigation_);
dict.Add("is_page_freezable", IsBackgrounded());
+ dict.Add("cpu_time_budget_pool", [&](perfetto::TracedValue context) {
+ cpu_time_budget_pool_->WriteIntoTrace(std::move(context), now);
+ });
+ dict.Add("normal_wake_up_budget_pool", [&](perfetto::TracedValue context) {
+ normal_wake_up_budget_pool_->WriteIntoTrace(std::move(context), now);
+ });
+ dict.Add("same_origin_intensive_wake_up_budget_pool",
+ [&](perfetto::TracedValue context) {
+ same_origin_intensive_wake_up_budget_pool_->WriteIntoTrace(
+ std::move(context), now);
+ });
+ dict.Add("cross_origin_intensive_wake_up_budget_pool",
+ [&](perfetto::TracedValue context) {
+ cross_origin_intensive_wake_up_budget_pool_->WriteIntoTrace(
+ std::move(context), now);
+ });
+
dict.Add("frame_schedulers", frame_schedulers_);
}
void PageSchedulerImpl::AddQueueToWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type,
+ bool frame_visible,
base::sequence_manager::LazyNow* lazy_now) {
- task_queue->AddToBudgetPool(
- lazy_now->Now(), GetWakeUpBudgetPool(task_queue, frame_origin_type));
+ DCHECK(!task_queue->GetWakeUpBudgetPool());
+ WakeUpBudgetPool* wake_up_budget_pool =
+ GetWakeUpBudgetPool(task_queue, frame_origin_type, frame_visible);
+ task_queue->AddToBudgetPool(lazy_now->Now(), wake_up_budget_pool);
+ task_queue->SetWakeUpBudgetPool(wake_up_budget_pool);
}
void PageSchedulerImpl::RemoveQueueFromWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
- FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now) {
- task_queue->RemoveFromBudgetPool(
- lazy_now->Now(), GetWakeUpBudgetPool(task_queue, frame_origin_type));
+ if (!task_queue->GetWakeUpBudgetPool())
+ return;
+ task_queue->RemoveFromBudgetPool(lazy_now->Now(),
+ task_queue->GetWakeUpBudgetPool());
+ task_queue->SetWakeUpBudgetPool(nullptr);
}
WakeUpBudgetPool* PageSchedulerImpl::GetWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
- FrameOriginType frame_origin_type) {
- if (!task_queue->CanBeIntensivelyThrottled())
- return normal_wake_up_budget_pool_;
-
- switch (frame_origin_type) {
- case FrameOriginType::kMainFrame:
- case FrameOriginType::kSameOriginToMainFrame:
- return same_origin_intensive_wake_up_budget_pool_;
- case FrameOriginType::kCrossOriginToMainFrame:
- return cross_origin_intensive_wake_up_budget_pool_;
- case FrameOriginType::kCount:
- NOTREACHED();
- return nullptr;
+ FrameOriginType frame_origin_type,
+ bool frame_visible) {
+ const bool can_be_intensively_throttled =
+ task_queue->CanBeIntensivelyThrottled();
+ const bool is_same_origin =
+ frame_origin_type == FrameOriginType::kMainFrame ||
+ frame_origin_type == FrameOriginType::kSameOriginToMainFrame;
+
+ if (IsBackgrounded()) {
+ if (can_be_intensively_throttled) {
+ if (is_same_origin)
+ return same_origin_intensive_wake_up_budget_pool_.get();
+ else
+ return cross_origin_intensive_wake_up_budget_pool_.get();
+ }
+ return normal_wake_up_budget_pool_.get();
}
+
+ if (!is_same_origin && !frame_visible)
+ return cross_origin_hidden_normal_wake_up_budget_pool_.get();
+
+ return normal_wake_up_budget_pool_.get();
}
CPUTimeBudgetPool* PageSchedulerImpl::background_cpu_time_budget_pool() {
- return cpu_time_budget_pool_;
+ return cpu_time_budget_pool_.get();
}
void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool(
@@ -676,12 +695,8 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool(
if (cpu_time_budget_pool_)
return;
- if (!RuntimeEnabledFeatures::ExpensiveBackgroundTimerThrottlingEnabled())
- return;
-
- cpu_time_budget_pool_ =
- main_thread_scheduler_->task_queue_throttler()->CreateCPUTimeBudgetPool(
- "background");
+ cpu_time_budget_pool_ = std::make_unique<CPUTimeBudgetPool>(
+ "background", &tracing_controller_, lazy_now->Now());
BackgroundThrottlingSettings settings = GetBackgroundThrottlingSettings();
@@ -707,13 +722,16 @@ void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools(
return;
normal_wake_up_budget_pool_ =
- main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
- "Page - Normal Wake Up Throttling");
+ std::make_unique<WakeUpBudgetPool>("Page - Normal Wake Up Throttling");
+ cross_origin_hidden_normal_wake_up_budget_pool_ =
+ std::make_unique<WakeUpBudgetPool>(
+ "Page - Normal Wake Up Throttling - Hidden & Crosss-Origin to Main "
+ "Frame");
same_origin_intensive_wake_up_budget_pool_ =
- main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
+ std::make_unique<WakeUpBudgetPool>(
"Page - Intensive Wake Up Throttling - Same-Origin as Main Frame");
cross_origin_intensive_wake_up_budget_pool_ =
- main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
+ std::make_unique<WakeUpBudgetPool>(
"Page - Intensive Wake Up Throttling - Cross-Origin to Main Frame");
// The Wake Up Duration and Unaligned Wake Ups Allowance are constant and set
@@ -722,34 +740,12 @@ void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools(
for (WakeUpBudgetPool* pool : AllWakeUpBudgetPools())
pool->SetWakeUpDuration(kThrottledWakeUpDuration);
- if (IsIntensiveWakeUpThrottlingEnabled()) {
- same_origin_intensive_wake_up_budget_pool_
- ->AllowUnalignedWakeUpIfNoRecentWakeUp();
- }
+ same_origin_intensive_wake_up_budget_pool_
+ ->AllowLowerAlignmentIfNoRecentWakeUp(kDefaultThrottledWakeUpInterval);
UpdateWakeUpBudgetPools(lazy_now);
}
-void PageSchedulerImpl::OnThrottlingReported(
- base::TimeDelta throttling_duration) {
- if (throttling_duration < kMinimalBackgroundThrottlingDurationToReport)
- return;
-
- if (reported_background_throttling_since_navigation_)
- return;
- reported_background_throttling_since_navigation_ = true;
-
- String message = String::Format(
- "Timer tasks have taken too much time while the page was in the "
- "background. "
- "As a result, they have been deferred for %.3f seconds. "
- "See https://www.chromestatus.com/feature/6172836527865856 "
- "for more details",
- throttling_duration.InSecondsF());
-
- delegate_->ReportIntervention(message);
-}
-
void PageSchedulerImpl::UpdatePolicyOnVisibilityChange(
NotificationPolicy notification_policy) {
base::sequence_manager::LazyNow lazy_now(
@@ -762,18 +758,15 @@ void PageSchedulerImpl::UpdatePolicyOnVisibilityChange(
are_wake_ups_intensively_throttled_ = false;
do_intensively_throttle_wake_ups_callback_.Cancel();
- UpdateWakeUpBudgetPools(&lazy_now);
} else {
if (cpu_time_budget_pool_) {
main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
FROM_HERE, do_throttle_cpu_time_callback_.GetCallback(),
kThrottlingDelayAfterBackgrounding);
}
- if (IsIntensiveWakeUpThrottlingEnabled()) {
- main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
- FROM_HERE, do_intensively_throttle_wake_ups_callback_.GetCallback(),
- GetIntensiveWakeUpThrottlingGracePeriod());
- }
+ main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
+ FROM_HERE, do_intensively_throttle_wake_ups_callback_.GetCallback(),
+ GetIntensiveWakeUpThrottlingGracePeriod());
}
if (notification_policy == NotificationPolicy::kNotifyFrames)
NotifyFrames();
@@ -790,8 +783,6 @@ void PageSchedulerImpl::DoThrottleCPUTime() {
}
void PageSchedulerImpl::DoIntensivelyThrottleWakeUps() {
- DCHECK(IsIntensiveWakeUpThrottlingEnabled());
-
do_intensively_throttle_wake_ups_callback_.Cancel();
are_wake_ups_intensively_throttled_ = true;
@@ -816,31 +807,21 @@ void PageSchedulerImpl::UpdateCPUTimeBudgetPool(
void PageSchedulerImpl::OnTitleOrFaviconUpdated() {
if (!HasWakeUpBudgetPools())
return;
-
if (are_wake_ups_intensively_throttled_ &&
!opted_out_from_aggressive_throttling_) {
// When the title of favicon is updated, intensive throttling is inhibited
// for same-origin frames. This enables alternating effects meant to grab
// the user's attention. Cross-origin frames are not affected, since they
// shouldn't be able to observe that the page title or favicon was updated.
- base::TimeDelta time_to_inhibit_intensive_throttling =
- GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate();
-
- if (time_to_inhibit_intensive_throttling.is_zero()) {
- // No inhibiting to be done.
- return;
- }
-
had_recent_title_or_favicon_update_ = true;
base::sequence_manager::LazyNow lazy_now(
main_thread_scheduler_->tick_clock());
UpdateWakeUpBudgetPools(&lazy_now);
-
// Re-enable intensive throttling from a delayed task.
reset_had_recent_title_or_favicon_update_.Cancel();
main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
FROM_HERE, reset_had_recent_title_or_favicon_update_.GetCallback(),
- time_to_inhibit_intensive_throttling);
+ kTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate);
}
}
@@ -854,15 +835,15 @@ void PageSchedulerImpl::ResetHadRecentTitleOrFaviconUpdate() {
NotifyFrames();
}
-base::TimeDelta PageSchedulerImpl::GetIntensiveWakeUpThrottlingDuration(
- bool is_same_origin) {
+base::TimeDelta PageSchedulerImpl::GetIntensiveWakeUpThrottlingInterval(
+ bool is_same_origin) const {
// Title and favicon changes only affect the same_origin wake up budget pool.
if (is_same_origin && had_recent_title_or_favicon_update_)
return kDefaultThrottledWakeUpInterval;
if (are_wake_ups_intensively_throttled_ &&
!opted_out_from_aggressive_throttling_)
- return GetIntensiveWakeUpThrottlingDurationBetweenWakeUps();
+ return kIntensiveThrottledWakeUpInterval;
else
return kDefaultThrottledWakeUpInterval;
}
@@ -872,10 +853,16 @@ void PageSchedulerImpl::UpdateWakeUpBudgetPools(
if (!same_origin_intensive_wake_up_budget_pool_)
return;
+ normal_wake_up_budget_pool_->SetWakeUpInterval(
+ lazy_now->Now(), IsBackgrounded()
+ ? kDefaultThrottledWakeUpInterval
+ : foreground_timers_throttled_wake_up_interval_);
+ cross_origin_hidden_normal_wake_up_budget_pool_->SetWakeUpInterval(
+ lazy_now->Now(), kDefaultThrottledWakeUpInterval);
same_origin_intensive_wake_up_budget_pool_->SetWakeUpInterval(
- lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(true));
+ lazy_now->Now(), GetIntensiveWakeUpThrottlingInterval(true));
cross_origin_intensive_wake_up_budget_pool_->SetWakeUpInterval(
- lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(false));
+ lazy_now->Now(), GetIntensiveWakeUpThrottlingInterval(false));
}
void PageSchedulerImpl::NotifyFrames() {
@@ -1064,6 +1051,8 @@ WebScopedVirtualTimePauser PageSchedulerImpl::CreateWebScopedVirtualTimePauser(
bool PageSchedulerImpl::HasWakeUpBudgetPools() const {
// All WakeUpBudgetPools should be initialized together.
DCHECK_EQ(!!normal_wake_up_budget_pool_,
+ !!cross_origin_hidden_normal_wake_up_budget_pool_);
+ DCHECK_EQ(!!normal_wake_up_budget_pool_,
!!same_origin_intensive_wake_up_budget_pool_);
DCHECK_EQ(!!normal_wake_up_budget_pool_,
!!cross_origin_intensive_wake_up_budget_pool_);
@@ -1071,11 +1060,23 @@ bool PageSchedulerImpl::HasWakeUpBudgetPools() const {
return !!normal_wake_up_budget_pool_;
}
+void PageSchedulerImpl::MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate() {
+ for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
+ frame_scheduler->MoveTaskQueuesToCorrectWakeUpBudgetPool();
+
+ // Update the WakeUpBudgetPools' interval everytime task queues change their
+ // attached WakeUpBudgetPools
+ base::sequence_manager::LazyNow lazy_now(
+ main_thread_scheduler_->tick_clock());
+ UpdateWakeUpBudgetPools(&lazy_now);
+}
+
std::array<WakeUpBudgetPool*, PageSchedulerImpl::kNumWakeUpBudgetPools>
PageSchedulerImpl::AllWakeUpBudgetPools() {
- return {normal_wake_up_budget_pool_,
- same_origin_intensive_wake_up_budget_pool_,
- cross_origin_intensive_wake_up_budget_pool_};
+ return {normal_wake_up_budget_pool_.get(),
+ cross_origin_hidden_normal_wake_up_budget_pool_.get(),
+ same_origin_intensive_wake_up_budget_pool_.get(),
+ cross_origin_intensive_wake_up_budget_pool_.get()};
}
// static
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 24b41b7ccae..4cd26620811 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
@@ -7,13 +7,12 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
#include "base/task/sequence_manager/task_queue.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.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/throttling/task_queue_throttler.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h"
@@ -50,11 +49,17 @@ class WakeUpBudgetPool;
class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
public:
- // Interval between throttled wake ups, when intensive throttling is disabled.
+ // Interval between throttled wake ups, without intensive throttling.
static constexpr base::TimeDelta kDefaultThrottledWakeUpInterval =
base::TimeDelta::FromSeconds(1);
+ // Interval between throttled wake ups, with intensive throttling.
+ static constexpr base::TimeDelta kIntensiveThrottledWakeUpInterval =
+ base::TimeDelta::FromMinutes(1);
+
PageSchedulerImpl(PageScheduler::Delegate*, AgentGroupSchedulerImpl&);
+ PageSchedulerImpl(const PageSchedulerImpl&) = delete;
+ PageSchedulerImpl& operator=(const PageSchedulerImpl&) = delete;
~PageSchedulerImpl() override;
@@ -63,7 +68,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
void SetPageVisible(bool page_visible) override;
void SetPageFrozen(bool) override;
void SetPageBackForwardCached(bool) override;
- void OnFocusChanged(bool focused) override;
void SetKeepActive(bool) override;
bool IsMainFrameLocal() const override;
void SetIsMainFrameLocal(bool is_local) override;
@@ -85,7 +89,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool VirtualTimeAllowedToAdvance() const override;
void SetVirtualTimePolicy(VirtualTimePolicy) override;
void SetInitialVirtualTime(base::Time time) override;
- void SetInitialVirtualTimeOffset(base::TimeDelta offset) override;
void GrantVirtualTimeBudget(
base::TimeDelta budget,
base::OnceClosure budget_exhausted_callback) override;
@@ -121,13 +124,12 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
AgentGroupSchedulerImpl& GetAgentGroupScheduler() override;
void Unregister(FrameSchedulerImpl*);
- void OnNavigation();
void OnThrottlingStatusUpdated();
void OnTraceLogEnabled();
- bool IsPageFocused() const;
+ void OnFirstContentfulPaintInMainFrame();
// Virtual for testing.
virtual bool IsWaitingForMainFrameContentfulPaint() const;
@@ -151,7 +153,9 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// frame it not a local one.
FrameSchedulerImpl* SelectFrameForUkmAttribution();
- void WriteIntoTrace(perfetto::TracedValue context) const;
+ bool ThrottleForegroundTimers() const { return throttle_foreground_timers_; }
+
+ void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks now) const;
base::WeakPtr<PageSchedulerImpl> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
@@ -196,6 +200,9 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
public:
explicit PageLifecycleStateTracker(PageSchedulerImpl*, PageLifecycleState);
+ PageLifecycleStateTracker(const PageLifecycleStateTracker&) = delete;
+ PageLifecycleStateTracker& operator=(const PageLifecycleStateTracker&) =
+ delete;
~PageLifecycleStateTracker() = default;
void SetPageLifecycleState(PageLifecycleState);
@@ -211,8 +218,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
PageSchedulerImpl* page_scheduler_impl_;
PageLifecycleState current_state_;
-
- DISALLOW_COPY_AND_ASSIGN(PageLifecycleStateTracker);
};
void RegisterFrameSchedulerImpl(FrameSchedulerImpl* frame_scheduler);
@@ -232,22 +237,22 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// a part of foregrounding the page.
void SetPageFrozenImpl(bool frozen, NotificationPolicy notification_policy);
- // Adds or removes a |task_queue| from the WakeUpBudgetPool associated with
- // |frame_origin_type|. When the FrameOriginType of a FrameScheduler changes,
- // it should remove all its TaskQueues from their current WakeUpBudgetPool and
- // add them back to the WakeUpBudgetPool appropriate for the new
- // FrameOriginType.
+ // Adds or removes a |task_queue| from the WakeUpBudgetPool. When the
+ // FrameOriginType or visibility of a FrameScheduler changes, it should remove
+ // all its TaskQueues from their current WakeUpBudgetPool and add them back to
+ // the appropriate WakeUpBudgetPool.
void AddQueueToWakeUpBudgetPool(MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type,
+ bool frame_visible,
base::sequence_manager::LazyNow* lazy_now);
void RemoveQueueFromWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
- FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now);
// Returns the WakeUpBudgetPool to use for |task_queue| which belongs to a
- // frame with |frame_origin_type|.
+ // frame with |frame_origin_type| and visibility |frame_visible|.
WakeUpBudgetPool* GetWakeUpBudgetPool(MainThreadTaskQueue* task_queue,
- FrameOriginType frame_origin_type);
+ FrameOriginType frame_origin_type,
+ bool frame_visible);
// Initializes WakeUpBudgetPools, if not already initialized.
void MaybeInitializeWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now);
@@ -256,8 +261,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
void MaybeInitializeBackgroundCPUTimeBudgetPool(
base::sequence_manager::LazyNow* lazy_now);
- void OnThrottlingReported(base::TimeDelta throttling_duration);
-
// Depending on page visibility, either turns throttling off, or schedules a
// call to enable it after a grace period.
void UpdatePolicyOnVisibilityChange(NotificationPolicy notification_policy);
@@ -265,7 +268,8 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Adjusts settings of budget pools depending on current state of the page.
void UpdateCPUTimeBudgetPool(base::sequence_manager::LazyNow* lazy_now);
void UpdateWakeUpBudgetPools(base::sequence_manager::LazyNow* lazy_now);
- base::TimeDelta GetIntensiveWakeUpThrottlingDuration(bool is_same_origin);
+ base::TimeDelta GetIntensiveWakeUpThrottlingInterval(
+ bool is_same_origin) const;
// Callback for marking page is silent after a delay since last audible
// signal.
@@ -298,8 +302,12 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Returns true if WakeUpBudgetPools were initialized.
bool HasWakeUpBudgetPools() const;
+ // Notify frames to move their task queues to the appropriate
+ // WakeUpBudgetPool.
+ void MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate();
+
// Returns all WakeUpBudgetPools owned by this PageSchedulerImpl.
- static constexpr int kNumWakeUpBudgetPools = 3;
+ static constexpr int kNumWakeUpBudgetPools = 4;
std::array<WakeUpBudgetPool*, kNumWakeUpBudgetPools> AllWakeUpBudgetPools();
TraceableVariableController tracing_controller_;
@@ -311,7 +319,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
base::TimeTicks page_visibility_changed_time_;
AudioState audio_state_;
bool is_frozen_;
- bool reported_background_throttling_since_navigation_;
bool opted_out_from_aggressive_throttling_;
bool nested_runloop_;
bool is_main_frame_local_;
@@ -319,22 +326,38 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool are_wake_ups_intensively_throttled_;
bool keep_active_;
bool had_recent_title_or_favicon_update_;
- bool focused_;
- CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr;
+ std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool_;
// Wake up budget pools for each throttling scenario:
//
- // Same-origin frame Cross-origin frame
- // Normal throttling only 1 1
- // Normal and intensive throttling 2 3
+ // For background pages:
+ // Same-origin frame Cross-origin frame
+ // Normal throttling only 1 1
+ // Normal and intensive throttling 3 4
+ //
+ // For foreground pages:
+ // Same-origin frame 1
+ // Visible cross-origin frame 1
+ // Hidden cross-origin frame 2
//
- // 1: This pool allows 1-second aligned wake ups.
- WakeUpBudgetPool* normal_wake_up_budget_pool_ = nullptr;
- // 2: This pool allows 1-second aligned wake ups if the page is not
+ // Task queues attched to these pools will be updated when:
+ // * Page background state changes
+ // * Frame visibility changes
+ // * Frame origin changes
+ //
+ // 1: This pool allows 1-second aligned wake ups when the page is backgrounded
+ // or |foreground_timers_throttled_wake_up_interval_| aligned wake ups when
+ // the page is foregrounded.
+ std::unique_ptr<WakeUpBudgetPool> normal_wake_up_budget_pool_;
+ // 2: This pool allows 1-second aligned wake ups for hidden frames in
+ // foreground pages.
+ std::unique_ptr<WakeUpBudgetPool>
+ cross_origin_hidden_normal_wake_up_budget_pool_;
+ // 3: This pool allows 1-second aligned wake ups if the page is not
// intensively throttled of if there hasn't been a wake up in the last
// minute. Otherwise, it allows 1-minute aligned wake ups.
- WakeUpBudgetPool* same_origin_intensive_wake_up_budget_pool_ = nullptr;
- // 3: This pool allows 1-second aligned wake ups if the page is not
+ std::unique_ptr<WakeUpBudgetPool> same_origin_intensive_wake_up_budget_pool_;
+ // 4: This pool allows 1-second aligned wake ups if the page is not
// intensively throttled. Otherwise, it allows 1-minute aligned wake ups.
//
// Unlike |same_origin_intensive_wake_up_budget_pool_|, this pool does not
@@ -343,7 +366,7 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// learning about each other. Concretely, this means that
// MaybeInitializeWakeUpBudgetPools() does not invoke
// AllowUnalignedWakeUpIfNoRecentWakeUp() on this pool.
- WakeUpBudgetPool* cross_origin_intensive_wake_up_budget_pool_ = nullptr;
+ std::unique_ptr<WakeUpBudgetPool> cross_origin_intensive_wake_up_budget_pool_;
PageScheduler::Delegate* delegate_;
CancelableClosureHolder do_throttle_cpu_time_callback_;
@@ -360,14 +383,17 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Delay after which a background page can be frozen if network is idle.
const base::TimeDelta delay_for_background_and_network_idle_tab_freezing_;
+ // Whether foreground timers should be always throttled.
+ const bool throttle_foreground_timers_;
+ // Interval between throttled wake ups on a foreground page.
+ const base::TimeDelta foreground_timers_throttled_wake_up_interval_;
+
bool is_stored_in_back_forward_cache_ = false;
TaskHandle set_ipc_posted_handler_task_;
base::TimeTicks stored_in_back_forward_cache_timestamp_;
std::unique_ptr<PageLifecycleStateTracker> page_lifecycle_state_tracker_;
base::WeakPtrFactory<PageSchedulerImpl> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PageSchedulerImpl);
};
} // namespace scheduler
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 03f4d864a40..e7252d20c92 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
@@ -21,7 +21,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
@@ -83,7 +82,6 @@ class MockPageSchedulerDelegate : public PageScheduler::Delegate {
void SetLocalMainFrameNetworkIsAlmostIdle(bool idle) { idle_ = idle; }
bool LocalMainFrameNetworkIsAlmostIdle() const override { return idle_; }
- bool IsFocused() const override { return true; }
private:
void ReportIntervention(const WTF::String&) override {}
@@ -1130,13 +1128,11 @@ void InitializeTrialParams() {
} // namespace
TEST_F(PageSchedulerImplTest, BackgroundTimerThrottling) {
- ScopedExpensiveBackgroundTimerThrottlingForTest
- budget_background_throttling_enabler(true);
-
InitializeTrialParams();
page_scheduler_ =
CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
EXPECT_FALSE(page_scheduler_->IsCPUTimeThrottled());
+ base::TimeTicks start_time = test_task_runner_->NowTicks();
Vector<base::TimeTicks> run_times;
frame_scheduler_ =
@@ -1185,21 +1181,18 @@ TEST_F(PageSchedulerImplTest, BackgroundTimerThrottling) {
test_task_runner_->FastForwardUntilNoTasksRemain();
// Check that tasks are aligned and throttled.
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(16),
- base::TimeTicks() + base::TimeDelta::FromSeconds(26)));
+ EXPECT_THAT(run_times,
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(16),
+ start_time + base::TimeDelta::FromSeconds(25)));
base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
}
TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
- ScopedExpensiveBackgroundTimerThrottlingForTest
- budget_background_throttling_enabler(true);
-
InitializeTrialParams();
std::unique_ptr<PageSchedulerImpl> page_scheduler =
CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
+ base::TimeTicks start_time = test_task_runner_->NowTicks();
Vector<base::TimeTicks> run_times;
@@ -1227,11 +1220,10 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(55500));
// Check that tasks are throttled.
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(21),
- base::TimeTicks() + base::TimeDelta::FromSeconds(26),
- base::TimeTicks() + base::TimeDelta::FromSeconds(51)));
+ EXPECT_THAT(run_times,
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(21),
+ start_time + base::TimeDelta::FromSeconds(25),
+ start_time + base::TimeDelta::FromSeconds(50)));
run_times.clear();
FrameScheduler::SchedulingAffectingFeatureHandle websocket_feature =
@@ -1299,9 +1291,10 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
// WebSocket is closed, budget-based throttling now applies.
EXPECT_THAT(
run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(84),
- base::TimeTicks() + base::TimeDelta::FromSeconds(109),
- base::TimeTicks() + base::TimeDelta::FromSeconds(134)));
+ ElementsAre(
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(84500),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(109500),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(134500)));
base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
}
@@ -1747,88 +1740,6 @@ TEST_F(PageSchedulerImplPageTransitionTest,
UnorderedElementsAreArray(GetExpectedBuckets()));
}
-class PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest
- : public PageSchedulerImplTest {
- public:
- PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest()
- : PageSchedulerImplTest(
- {blink::features::kStopInBackground,
- blink::scheduler::kThrottleVisibleNotFocusedTimers},
- {}) {}
-};
-
-TEST_F(PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest,
- PageVisibleWithFocus) {
- page_scheduler_->SetPageVisible(true);
- if (!page_scheduler_->IsPageFocused())
- page_scheduler_->OnFocusChanged(true);
-
- int run_count = 0;
- ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask(
- FROM_HERE,
- MakeRepeatingTask(
- ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType(),
- &run_count, base::TimeDelta::FromMilliseconds(20)),
- base::TimeDelta::FromMilliseconds(20));
-
- test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_EQ(50, run_count);
-
- // Create a new frame when the page has focus
- int frame_run_count = 0;
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
- CreateFrameScheduler(page_scheduler_.get(), nullptr, nullptr,
- FrameScheduler::FrameType::kSubframe);
- ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
- ->GetTaskRunnerWithDefaultTaskType()
- ->PostDelayedTask(
- FROM_HERE,
- MakeRepeatingTask(
- ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
- ->GetTaskRunnerWithDefaultTaskType(),
- &frame_run_count, base::TimeDelta::FromMilliseconds(20)),
- base::TimeDelta::FromMilliseconds(20));
-
- test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_EQ(50, frame_run_count);
-}
-
-TEST_F(PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest,
- PageVisibleWithoutFocus) {
- page_scheduler_->SetPageVisible(true);
- if (page_scheduler_->IsPageFocused())
- page_scheduler_->OnFocusChanged(false);
-
- int run_count = 0;
- ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask(
- FROM_HERE,
- MakeRepeatingTask(
- ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType(),
- &run_count, base::TimeDelta::FromMilliseconds(20)),
- base::TimeDelta::FromMilliseconds(20));
-
- test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_EQ(1, run_count);
-
- // Create a new frame when the page doesn't have focus
- int frame_run_count = 0;
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
- CreateFrameScheduler(page_scheduler_.get(), nullptr, nullptr,
- FrameScheduler::FrameType::kSubframe);
- ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
- ->GetTaskRunnerWithDefaultTaskType()
- ->PostDelayedTask(
- FROM_HERE,
- MakeRepeatingTask(
- ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
- ->GetTaskRunnerWithDefaultTaskType(),
- &frame_run_count, base::TimeDelta::FromMilliseconds(20)),
- base::TimeDelta::FromMilliseconds(20));
-
- test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_EQ(1, frame_run_count);
-}
-
} // namespace page_scheduler_impl_unittest
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
index 4c4863cb99f..84b1675979a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
@@ -26,6 +26,8 @@ class PLATFORM_EXPORT PendingUserInput {
public:
Monitor() = default;
+ Monitor(const Monitor&) = delete;
+ Monitor& operator=(const Monitor&) = delete;
void OnEnqueue(WebInputEvent::Type, const WebInputEventAttribution&);
void OnDequeue(WebInputEvent::Type, const WebInputEventAttribution&);
@@ -45,18 +47,16 @@ class PLATFORM_EXPORT PendingUserInput {
// A mapping between attributions to pending events.
HashMap<AttributionGroup, EventCounter> pending_events_;
-
- DISALLOW_COPY_AND_ASSIGN(Monitor);
};
PendingUserInput() = delete;
+ PendingUserInput(const PendingUserInput&) = delete;
+ PendingUserInput& operator=(const PendingUserInput&) = delete;
// Returns true if the given blink event type is considered to be sampled
// from a continuous source.
// https://wicg.github.io/is-input-pending/#continuousevents
static bool IsContinuousEventType(WebInputEvent::Type);
-
- DISALLOW_COPY_AND_ASSIGN(PendingUserInput);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc
index f08de3f8c10..7c32074ba6f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
@@ -23,14 +22,13 @@ namespace render_widget_signals_unittest {
class MockObserver : public RenderWidgetSignals::Observer {
public:
MockObserver() = default;
+ MockObserver(const MockObserver&) = delete;
+ MockObserver& operator=(const MockObserver&) = delete;
~MockObserver() override = default;
MOCK_METHOD1(SetAllRenderWidgetsHidden, void(bool hidden));
MOCK_METHOD1(SetHasVisibleRenderWidgetWithTouchHandler,
void(bool has_visible_render_widget_with_touch_handler));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockObserver);
};
class RenderWidgetSignalsTest : public testing::Test {
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
index bc24b079541..a270655fc64 100644
--- 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
@@ -23,6 +23,11 @@ class PLATFORM_EXPORT ResourceLoadingTaskRunnerHandleImpl
static std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> WrapTaskRunner(
scoped_refptr<MainThreadTaskQueue> task_runner);
+ ResourceLoadingTaskRunnerHandleImpl(
+ const ResourceLoadingTaskRunnerHandleImpl&) = delete;
+ ResourceLoadingTaskRunnerHandleImpl& operator=(
+ const ResourceLoadingTaskRunnerHandleImpl&) = delete;
+
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
void DidChangeRequestPriority(net::RequestPriority priority) override;
@@ -38,8 +43,6 @@ class PLATFORM_EXPORT ResourceLoadingTaskRunnerHandleImpl
private:
scoped_refptr<MainThreadTaskQueue> task_queue_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceLoadingTaskRunnerHandleImpl);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
index b0565ab37ae..f25ef8ff04b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -151,8 +151,8 @@ const char* TaskTypeNames::TaskTypeToString(TaskType task_type) {
return "WakeLock";
case TaskType::kWebGPU:
return "WebGPU";
- case TaskType::kCount:
- return "Count";
+ case TaskType::kInternalPostMessageForwarding:
+ return "InternalPostMessageForwarding";
}
// FrameSchedulerImpl should not call this for invalid TaskTypes.
NOTREACHED();
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 9e5667de0c0..a849d07df67 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_USER_MODEL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_USER_MODEL_H_
-#include "base/macros.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -20,6 +19,8 @@ class PLATFORM_EXPORT UserModel {
public:
UserModel();
+ UserModel(const UserModel&) = delete;
+ UserModel& operator=(const UserModel&) = delete;
// Tells us that the system started processing an input event. Must be paired
// with a call to DidFinishProcessingInputEvent.
@@ -77,8 +78,6 @@ class PLATFORM_EXPORT UserModel {
base::TimeTicks last_reset_time_;
bool is_gesture_active_; // This typically means the user's finger is down.
bool is_gesture_expected_;
-
- DISALLOW_COPY_AND_ASSIGN(UserModel);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc
deleted file mode 100644
index 30b6e4b4ea3..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h"
-
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
-
-namespace blink {
-namespace scheduler {
-
-WebSchedulingTaskQueueImpl::WebSchedulingTaskQueueImpl(
- base::WeakPtr<MainThreadTaskQueue> task_queue)
- : task_runner_(
- task_queue->CreateTaskRunner(TaskType::kExperimentalWebScheduling)),
- task_queue_(std::move(task_queue)) {}
-
-void WebSchedulingTaskQueueImpl::SetPriority(WebSchedulingPriority priority) {
- if (task_queue_)
- task_queue_->SetWebSchedulingPriority(priority);
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-WebSchedulingTaskQueueImpl::GetTaskRunner() {
- return task_runner_;
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h
deleted file mode 100644
index a4da9eaf1af..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
-
-#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
-
-#include "base/memory/scoped_refptr.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/public/web_scheduling_priority.h"
-
-namespace blink {
-namespace scheduler {
-
-class MainThreadTaskQueue;
-
-class PLATFORM_EXPORT WebSchedulingTaskQueueImpl
- : public WebSchedulingTaskQueue {
- public:
- WebSchedulingTaskQueueImpl(base::WeakPtr<MainThreadTaskQueue>);
- ~WebSchedulingTaskQueueImpl() override = default;
-
- void SetPriority(WebSchedulingPriority) override;
-
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
-
- private:
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- base::WeakPtr<MainThreadTaskQueue> task_queue_;
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h
index 83a5fdecb26..c1a0e56c194 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h
@@ -19,6 +19,8 @@ class MainThreadTaskQueue;
class WidgetScheduler : public WebWidgetScheduler {
public:
WidgetScheduler(MainThreadSchedulerImpl*);
+ WidgetScheduler(const WidgetScheduler&) = delete;
+ WidgetScheduler& operator=(const WidgetScheduler&) = delete;
~WidgetScheduler() override;
scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
@@ -27,8 +29,6 @@ class WidgetScheduler : public WebWidgetScheduler {
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
input_task_queue_enabled_voter_;
-
- DISALLOW_COPY_AND_ASSIGN(WidgetScheduler);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h b/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h
index ff9335fdf5e..18c32d68bbf 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h
@@ -8,7 +8,6 @@
#include <array>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -51,6 +50,8 @@ class AggregatedMetricReporter {
static_cast<int>(TaskClass::kCount) + 1,
base::HistogramBase::kUmaTargetedHistogramFlag),
aggregator) {}
+ AggregatedMetricReporter(const AggregatedMetricReporter&) = delete;
+ AggregatedMetricReporter& operator=(const AggregatedMetricReporter&) = delete;
~AggregatedMetricReporter() {}
@@ -82,8 +83,6 @@ class AggregatedMetricReporter {
AggregatorFuncPtr aggregator_;
THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(AggregatedMetricReporter);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h b/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h
index 6f6f4222208..302eb4cadc0 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h
@@ -36,6 +36,9 @@ class PLATFORM_EXPORT CooperativeSchedulingManager {
static CooperativeSchedulingManager* Instance();
CooperativeSchedulingManager();
+ CooperativeSchedulingManager(const CooperativeSchedulingManager&) = delete;
+ CooperativeSchedulingManager& operator=(const CooperativeSchedulingManager&) =
+ delete;
virtual ~CooperativeSchedulingManager() = default;
// Returns true if reentry is allowed in the current C++ stack.
@@ -65,8 +68,6 @@ class PLATFORM_EXPORT CooperativeSchedulingManager {
base::TimeTicks wait_until_;
const base::TickClock* clock_;
bool feature_enabled_ = true;
-
- DISALLOW_COPY_AND_ASSIGN(CooperativeSchedulingManager);
};
inline void CooperativeSchedulingManager::Safepoint() {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h b/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h
index d2ee089685f..4e48ffb5f28 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h
@@ -59,6 +59,9 @@ class PLATFORM_EXPORT EventLoop final : public WTF::RefCounted<EventLoop> {
USING_FAST_MALLOC(EventLoop);
public:
+ EventLoop(const EventLoop&) = delete;
+ EventLoop& operator=(const EventLoop&) = delete;
+
// Queues |cb| to the backing v8::MicrotaskQueue.
void EnqueueMicrotask(base::OnceClosure cb);
@@ -97,8 +100,6 @@ class PLATFORM_EXPORT EventLoop final : public WTF::RefCounted<EventLoop> {
Deque<base::OnceClosure> pending_microtasks_;
std::unique_ptr<v8::MicrotaskQueue> microtask_queue_;
HashSet<FrameOrWorkerScheduler*> schedulers_;
-
- DISALLOW_COPY_AND_ASSIGN(EventLoop);
};
} // namespace scheduler
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 8b7cf123371..eb4ccddc93f 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
@@ -10,11 +10,13 @@
#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/scheduler/public/scheduling_policy.h"
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
class FrameScheduler;
+class WebSchedulingTaskQueue;
// This is the base class of FrameScheduler and WorkerScheduler.
class PLATFORM_EXPORT FrameOrWorkerScheduler {
@@ -41,13 +43,13 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler {
public:
LifecycleObserverHandle(FrameOrWorkerScheduler* scheduler,
Observer* observer);
+ LifecycleObserverHandle(const LifecycleObserverHandle&) = delete;
+ LifecycleObserverHandle& operator=(const LifecycleObserverHandle&) = delete;
~LifecycleObserverHandle();
private:
base::WeakPtr<FrameOrWorkerScheduler> scheduler_;
Observer* observer_;
-
- DISALLOW_COPY_AND_ASSIGN(LifecycleObserverHandle);
};
// RAII handle which should be kept alive as long as the feature is active
@@ -58,11 +60,11 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler {
public:
SchedulingAffectingFeatureHandle() = default;
SchedulingAffectingFeatureHandle(SchedulingAffectingFeatureHandle&&);
- inline ~SchedulingAffectingFeatureHandle() { reset(); }
-
SchedulingAffectingFeatureHandle& operator=(
SchedulingAffectingFeatureHandle&&);
+ inline ~SchedulingAffectingFeatureHandle() { reset(); }
+
explicit operator bool() const { return scheduler_.get(); }
inline void reset() {
@@ -81,8 +83,6 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler {
SchedulingPolicy::Feature feature_ = SchedulingPolicy::Feature::kMaxValue;
SchedulingPolicy policy_;
base::WeakPtr<FrameOrWorkerScheduler> scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(SchedulingAffectingFeatureHandle);
};
virtual ~FrameOrWorkerScheduler();
@@ -118,6 +118,9 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler {
Observer*)
WARN_UNUSED_RESULT;
+ virtual std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue(
+ WebSchedulingPriority) = 0;
+
virtual FrameScheduler* ToFrameScheduler() { return nullptr; }
base::WeakPtr<FrameOrWorkerScheduler> GetWeakPtr();
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 ffba694c427..15f3c0b9e19 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
@@ -17,7 +17,6 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -32,7 +31,6 @@ class WebAgentGroupScheduler;
} // namespace scheduler
class PageScheduler;
-class WebSchedulingTaskQueue;
class FrameScheduler : public FrameOrWorkerScheduler {
public:
@@ -130,9 +128,6 @@ class FrameScheduler : public FrameOrWorkerScheduler {
virtual std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
CreateResourceLoadingMaybeUnfreezableTaskRunnerHandle() = 0;
- virtual std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue(
- WebSchedulingPriority) = 0;
-
// Returns the parent PageScheduler.
virtual PageScheduler* GetPageScheduler() const = 0;
@@ -160,6 +155,10 @@ class FrameScheduler : public FrameOrWorkerScheduler {
virtual void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
NavigationType navigation_type) = 0;
+ // Tells the scheduler that the "DOMContentLoaded" event has occurred for this
+ // frame.
+ virtual void OnDomContentLoaded() = 0;
+
// Tells the scheduler that the first contentful paint has occurred for this
// frame. Only for main frames.
virtual void OnFirstContentfulPaintInMainFrame() = 0;
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 795ed1f870a..00a40ddbc25 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
@@ -38,8 +38,6 @@ class PLATFORM_EXPORT PageScheduler {
// Returns true iff the network is idle for the local main frame.
// Always returns false if the main frame is remote.
virtual bool LocalMainFrameNetworkIsAlmostIdle() const { return true; }
- // Returns if the page has focus.
- virtual bool IsFocused() const = 0;
};
virtual ~PageScheduler() = default;
@@ -53,8 +51,6 @@ class PLATFORM_EXPORT PageScheduler {
virtual void SetPageFrozen(bool) = 0;
// Handles operations required for storing the page in the back-forward cache.
virtual void SetPageBackForwardCached(bool) = 0;
- // Handle page focus changed.
- virtual void OnFocusChanged(bool focused) = 0;
// Tells the scheduler about "keep-alive" state which can be due to:
// service workers, shared workers, or fetch keep-alive.
// If true, then the scheduler should not freeze relevant task queues.
@@ -121,10 +117,6 @@ class PLATFORM_EXPORT PageScheduler {
// This is used to set initial Date.now() while in virtual time mode.
virtual void SetInitialVirtualTime(base::Time time) = 0;
- // This is used for cross origin navigations to account for virtual time
- // advancing in the previous renderer.
- virtual void SetInitialVirtualTimeOffset(base::TimeDelta offset) = 0;
-
// Sets the virtual time policy, which is applied imemdiatly to all child
// FrameSchedulers.
virtual void SetVirtualTimePolicy(VirtualTimePolicy) = 0;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h b/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h
index cfbe0ea5ae0..2f3e648b284 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h
@@ -17,8 +17,8 @@ namespace blink {
inline bool PostCrossThreadTask(base::SequencedTaskRunner& task_runner,
const base::Location& location,
WTF::CrossThreadOnceClosure task) {
- return task_runner.PostDelayedTask(
- location, ConvertToBaseOnceCallback(std::move(task)), base::TimeDelta());
+ return task_runner.PostTask(location,
+ ConvertToBaseOnceCallback(std::move(task)));
}
inline bool PostDelayedCrossThreadTask(base::SequencedTaskRunner& task_runner,
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h
index 7512cc93e53..621b1fbc4da 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h
@@ -27,7 +27,6 @@
#include <stdint.h>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/task_observer.h"
#include "base/threading/thread.h"
@@ -110,6 +109,8 @@ class PLATFORM_EXPORT Thread {
static Thread* CompositorThread();
Thread();
+ Thread(const Thread&) = delete;
+ Thread& operator=(const Thread&) = delete;
virtual ~Thread();
// Must be called immediately after the construction.
@@ -164,8 +165,6 @@ class PLATFORM_EXPORT Thread {
// This is used to identify the actual Thread instance. This should be
// used only in Platform, and other users should ignore this.
virtual bool IsSimpleMainThread() const { return false; }
-
- DISALLOW_COPY_AND_ASSIGN(Thread);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h
index 06f559fad9f..78e1eec2153 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -29,6 +28,9 @@ class PLATFORM_EXPORT ThreadCPUThrottler final {
public:
static ThreadCPUThrottler* GetInstance();
+ ThreadCPUThrottler(const ThreadCPUThrottler&) = delete;
+ ThreadCPUThrottler& operator=(const ThreadCPUThrottler&) = delete;
+
// |rate| is a slow-down factor - passing 2.0 will make
// everything two times slower.
// Any rate less or equal to 1.0 disables throttling and
@@ -42,8 +44,6 @@ class PLATFORM_EXPORT ThreadCPUThrottler final {
class ThrottlingThread;
std::unique_ptr<ThrottlingThread> throttling_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadCPUThrottler);
};
} // namespace scheduler
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 a7e2d1ef069..1c87da1aef6 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
@@ -154,19 +154,20 @@ class PLATFORM_EXPORT ThreadScheduler {
// Associates |isolate| to the scheduler.
virtual void SetV8Isolate(v8::Isolate* isolate) = 0;
- virtual void OnSafepointEntered() {}
- virtual void OnSafepointExited() {}
-
// Test helpers.
+ virtual scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() = 0;
+
+ private:
+ // For GetWebMainThreadScheduler().
+ friend class scheduler::WebThreadScheduler;
+
// 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::WebThreadScheduler* GetWebMainThreadSchedulerForTest() {
+ virtual scheduler::WebThreadScheduler* GetWebMainThreadScheduler() {
return nullptr;
}
-
- virtual scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h
index f562745458d..e6898971e91 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h
@@ -32,7 +32,7 @@ enum class ThreadType {
kRealtimeAudioWorkletThread = 19,
kSemiRealtimeAudioWorkletThread = 20,
- kCount = 21
+ kMaxValue = kSemiRealtimeAudioWorkletThread,
};
BLINK_PLATFORM_EXPORT const char* GetNameForThreadType(ThreadType);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
index 049ecb25117..04e618dee8c 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
@@ -10,8 +10,7 @@
namespace blink {
-// Priorities for the experimental scheduling API (see
-// https://github.com/WICG/main-thread-scheduling).
+// https://wicg.github.io/scheduling-apis/#sec-task-priorities
enum class WebSchedulingPriority {
kUserBlockingPriority = 0,
kUserVisiblePriority = 1,
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h
index 0f580027676..50d783ae68d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h
@@ -12,9 +12,9 @@
namespace blink {
-// This class is used by the experimental Scheduling API to submit tasks to the
-// platform's scheduler through prioritized task queues (see
-// https://github.com/WICG/main-thread-scheduling).
+// This class is used by the Prioritized Task Scheduling API to submit tasks to
+// the platform's scheduler through prioritized task queues (see
+// https://wicg.github.io/scheduling-apis/).
class PLATFORM_EXPORT WebSchedulingTaskQueue {
public:
virtual ~WebSchedulingTaskQueue() = default;
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
index c4221032c66..e369684e390 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
@@ -35,12 +35,12 @@ class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
public:
PauseHandle(base::WeakPtr<WorkerScheduler>);
+ PauseHandle(const PauseHandle&) = delete;
+ PauseHandle& operator=(const PauseHandle&) = delete;
~PauseHandle();
private:
base::WeakPtr<WorkerScheduler> scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(PauseHandle);
};
std::unique_ptr<PauseHandle> Pause() WARN_UNUSED_RESULT;
@@ -69,6 +69,8 @@ class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
// FrameOrWorkerScheduler implementation:
void SetPreemptedForCooperativeScheduling(Preempted) override {}
+ std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue(
+ WebSchedulingPriority) override;
protected:
scoped_refptr<NonMainThreadTaskQueue> ThrottleableTaskQueue();
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
index 5ebac2e537f..7acae9fb4b0 100644
--- 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
@@ -14,14 +14,13 @@ namespace scheduler {
class PLATFORM_EXPORT CompositorMetricsHelper : public MetricsHelper {
public:
explicit CompositorMetricsHelper(bool has_cpu_timing_for_each_task);
+ CompositorMetricsHelper(const CompositorMetricsHelper&) = delete;
+ CompositorMetricsHelper& operator=(const CompositorMetricsHelper&) = delete;
~CompositorMetricsHelper();
void RecordTaskMetrics(
const base::sequence_manager::Task& task,
const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompositorMetricsHelper);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h
index 0c894171e91..a689ce9cedd 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h"
namespace blink {
@@ -14,13 +13,13 @@ namespace scheduler {
class PLATFORM_EXPORT CompositorThread : public WorkerThread {
public:
explicit CompositorThread(const ThreadCreationParams& params);
+ CompositorThread(const CompositorThread&) = delete;
+ CompositorThread& operator=(const CompositorThread&) = delete;
~CompositorThread() override;
private:
std::unique_ptr<NonMainThreadSchedulerImpl> CreateNonMainThreadScheduler(
base::sequence_manager::SequenceManager* sequence_manager) override;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorThread);
};
} // namespace scheduler
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 0779cb5c427..0c4c6c67e64 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
@@ -79,6 +79,11 @@ CompositorThreadScheduler::DefaultTaskRunner() {
}
scoped_refptr<base::SingleThreadTaskRunner>
+CompositorThreadScheduler::InputTaskRunner() {
+ return helper()->InputTaskRunner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
CompositorThreadScheduler::CompositorTaskRunner() {
NOTREACHED();
return nullptr;
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 61c35b52d82..6302f70e93c 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_SCHEDULER_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "components/scheduling_metrics/task_duration_metric_reporter.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -27,6 +26,9 @@ class PLATFORM_EXPORT CompositorThreadScheduler
public:
explicit CompositorThreadScheduler(
base::sequence_manager::SequenceManager* sequence_manager);
+ CompositorThreadScheduler(const CompositorThreadScheduler&) = delete;
+ CompositorThreadScheduler& operator=(const CompositorThreadScheduler&) =
+ delete;
~CompositorThreadScheduler() override;
@@ -41,6 +43,7 @@ class PLATFORM_EXPORT CompositorThreadScheduler
// WebThreadScheduler:
scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
bool ShouldYieldForHighPriorityWork() override;
@@ -63,8 +66,6 @@ class PLATFORM_EXPORT CompositorThreadScheduler
private:
CompositorMetricsHelper compositor_metrics_helper_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorThreadScheduler);
};
} // namespace scheduler
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 de39768060c..468aebe1334 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
@@ -20,10 +20,12 @@ NonMainThreadSchedulerHelper::NonMainThreadSchedulerHelper(
non_main_thread_scheduler_(non_main_thread_scheduler),
default_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_default_tq")
.SetShouldMonitorQuiescence(true))),
+ input_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_input_tq"))),
control_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_control_tq")
.SetShouldNotifyObservers(false))) {
InitDefaultQueues(default_task_queue_, control_task_queue_,
default_task_type);
+ input_task_queue_->SetQueuePriority(TaskQueue::kHighestPriority);
}
NonMainThreadSchedulerHelper::~NonMainThreadSchedulerHelper() {
@@ -41,6 +43,11 @@ NonMainThreadSchedulerHelper::DefaultTaskRunner() {
return default_task_queue_->GetTaskRunnerWithDefaultTaskType();
}
+const scoped_refptr<base::SingleThreadTaskRunner>&
+NonMainThreadSchedulerHelper::InputTaskRunner() {
+ return input_task_queue_->GetTaskRunnerWithDefaultTaskType();
+}
+
scoped_refptr<NonMainThreadTaskQueue>
NonMainThreadSchedulerHelper::ControlNonMainThreadTaskQueue() {
return control_task_queue_;
@@ -52,9 +59,10 @@ NonMainThreadSchedulerHelper::ControlTaskRunner() {
}
scoped_refptr<NonMainThreadTaskQueue>
-NonMainThreadSchedulerHelper::NewTaskQueue(const TaskQueue::Spec& spec) {
+NonMainThreadSchedulerHelper::NewTaskQueue(const TaskQueue::Spec& spec,
+ bool can_be_throttled) {
return sequence_manager_->CreateTaskQueueWithType<NonMainThreadTaskQueue>(
- spec, non_main_thread_scheduler_);
+ spec, non_main_thread_scheduler_, can_be_throttled);
}
void NonMainThreadSchedulerHelper::ShutdownAllQueues() {
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 c0d7440a3da..8a18cd0e2c0 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
@@ -25,10 +25,14 @@ class PLATFORM_EXPORT NonMainThreadSchedulerHelper : public SchedulerHelper {
base::sequence_manager::SequenceManager* manager,
NonMainThreadSchedulerImpl* non_main_thread_scheduler,
TaskType default_task_type);
+ NonMainThreadSchedulerHelper(const NonMainThreadSchedulerHelper&) = delete;
+ NonMainThreadSchedulerHelper& operator=(const NonMainThreadSchedulerHelper&) =
+ delete;
~NonMainThreadSchedulerHelper() override;
scoped_refptr<NonMainThreadTaskQueue> NewTaskQueue(
- const base::sequence_manager::TaskQueue::Spec& spec);
+ const base::sequence_manager::TaskQueue::Spec& spec,
+ bool can_be_throttled = false);
scoped_refptr<NonMainThreadTaskQueue> DefaultNonMainThreadTaskQueue();
scoped_refptr<NonMainThreadTaskQueue> ControlNonMainThreadTaskQueue();
@@ -38,15 +42,16 @@ class PLATFORM_EXPORT NonMainThreadSchedulerHelper : public SchedulerHelper {
const scoped_refptr<base::SingleThreadTaskRunner>& ControlTaskRunner()
override;
+ const scoped_refptr<base::SingleThreadTaskRunner>& InputTaskRunner();
+
protected:
void ShutdownAllQueues() override;
private:
NonMainThreadSchedulerImpl* non_main_thread_scheduler_; // NOT OWNED
const scoped_refptr<NonMainThreadTaskQueue> default_task_queue_;
+ const scoped_refptr<NonMainThreadTaskQueue> input_task_queue_;
const scoped_refptr<NonMainThreadTaskQueue> control_task_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerHelper);
};
} // namespace scheduler
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
index 1471095a229..3d1da66ddc3 100644
--- 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
@@ -30,11 +30,13 @@ std::unique_ptr<NonMainThreadSchedulerImpl> NonMainThreadSchedulerImpl::Create(
}
scoped_refptr<NonMainThreadTaskQueue>
-NonMainThreadSchedulerImpl::CreateTaskQueue(const char* name) {
+NonMainThreadSchedulerImpl::CreateTaskQueue(const char* name,
+ bool can_be_throttled) {
helper_.CheckOnValidThread();
return helper_.NewTaskQueue(base::sequence_manager::TaskQueue::Spec(name)
.SetShouldMonitorQuiescence(true)
- .SetTimeDomain(nullptr));
+ .SetTimeDomain(nullptr),
+ can_be_throttled);
}
void NonMainThreadSchedulerImpl::RunIdleTask(Thread::IdleTask task,
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
index 901003735df..5b32dcce581 100644
--- 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/task/sequence_manager/task_queue.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
@@ -28,6 +27,9 @@ class WorkerSchedulerProxy;
class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl {
public:
+ NonMainThreadSchedulerImpl(const NonMainThreadSchedulerImpl&) = delete;
+ NonMainThreadSchedulerImpl& operator=(const NonMainThreadSchedulerImpl&) =
+ delete;
~NonMainThreadSchedulerImpl() override;
// |sequence_manager| and |proxy| must remain valid for the entire lifetime of
@@ -96,7 +98,9 @@ class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl {
//
// virtual void Shutdown();
- scoped_refptr<NonMainThreadTaskQueue> CreateTaskQueue(const char* name);
+ scoped_refptr<NonMainThreadTaskQueue> CreateTaskQueue(
+ const char* name,
+ bool can_be_throttled = false);
scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner()
override;
@@ -116,8 +120,6 @@ class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl {
private:
NonMainThreadSchedulerHelper helper_;
-
- DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerImpl);
};
} // namespace scheduler
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
index 065986002f2..d1396f59ddc 100644
--- 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
#include "base/bind.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h"
namespace blink {
@@ -15,10 +16,17 @@ 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)
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler,
+ bool can_be_throttled)
: TaskQueue(std::move(impl), spec),
non_main_thread_scheduler_(non_main_thread_scheduler) {
+ // Throttling needs |should_notify_observers| to get task timing.
+ DCHECK(!can_be_throttled || spec.should_notify_observers)
+ << "Throttled queue is not supported with |!should_notify_observers|";
if (GetTaskQueueImpl() && spec.should_notify_observers) {
+ if (can_be_throttled) {
+ throttler_.emplace(this, non_main_thread_scheduler->GetTickClock());
+ }
// TaskQueueImpl may be null for tests.
GetTaskQueueImpl()->SetOnTaskCompletedHandler(base::BindRepeating(
&NonMainThreadTaskQueue::OnTaskCompleted, base::Unretained(this)));
@@ -27,6 +35,12 @@ NonMainThreadTaskQueue::NonMainThreadTaskQueue(
NonMainThreadTaskQueue::~NonMainThreadTaskQueue() = default;
+void NonMainThreadTaskQueue::ShutdownTaskQueue() {
+ non_main_thread_scheduler_ = nullptr;
+ throttler_.reset();
+ TaskQueue::ShutdownTaskQueue();
+}
+
void NonMainThreadTaskQueue::OnTaskCompleted(
const base::sequence_manager::Task& task,
TaskQueue::TaskTiming* task_timing,
@@ -38,5 +52,54 @@ void NonMainThreadTaskQueue::OnTaskCompleted(
}
}
+void NonMainThreadTaskQueue::AddToBudgetPool(base::TimeTicks now,
+ BudgetPool* pool) {
+ pool->AddThrottler(now, &throttler_.value());
+}
+
+void NonMainThreadTaskQueue::RemoveFromBudgetPool(base::TimeTicks now,
+ BudgetPool* pool) {
+ pool->RemoveThrottler(now, &throttler_.value());
+}
+
+void NonMainThreadTaskQueue::IncreaseThrottleRefCount() {
+ throttler_->IncreaseThrottleRefCount();
+}
+
+void NonMainThreadTaskQueue::DecreaseThrottleRefCount() {
+ throttler_->DecreaseThrottleRefCount();
+}
+
+void NonMainThreadTaskQueue::OnTaskRunTimeReported(
+ TaskQueue::TaskTiming* task_timing) {
+ if (throttler_.has_value()) {
+ throttler_->OnTaskRunTimeReported(task_timing->start_time(),
+ task_timing->end_time());
+ }
+}
+
+void NonMainThreadTaskQueue::SetWebSchedulingPriority(
+ WebSchedulingPriority priority) {
+ if (web_scheduling_priority_ == priority)
+ return;
+ web_scheduling_priority_ = priority;
+ OnWebSchedulingPriorityChanged();
+}
+
+void NonMainThreadTaskQueue::OnWebSchedulingPriorityChanged() {
+ DCHECK(web_scheduling_priority_);
+ switch (web_scheduling_priority_.value()) {
+ case WebSchedulingPriority::kUserBlockingPriority:
+ SetQueuePriority(TaskQueue::QueuePriority::kHighPriority);
+ return;
+ case WebSchedulingPriority::kUserVisiblePriority:
+ SetQueuePriority(TaskQueue::QueuePriority::kNormalPriority);
+ return;
+ case WebSchedulingPriority::kBackgroundPriority:
+ SetQueuePriority(TaskQueue::QueuePriority::kLowPriority);
+ return;
+ }
+}
+
} // 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
index 12b25539d22..55063597b71 100644
--- 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
@@ -6,8 +6,11 @@
#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/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
namespace blink {
namespace scheduler {
@@ -21,7 +24,8 @@ class PLATFORM_EXPORT NonMainThreadTaskQueue
NonMainThreadTaskQueue(
std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
const Spec& spec,
- NonMainThreadSchedulerImpl* non_main_thread_scheduler);
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler,
+ bool can_be_throttled);
~NonMainThreadTaskQueue() override;
void OnTaskCompleted(
@@ -34,6 +38,19 @@ class PLATFORM_EXPORT NonMainThreadTaskQueue
return TaskQueue::CreateTaskRunner(static_cast<int>(task_type));
}
+ bool IsThrottled() const { return throttler_->IsThrottled(); }
+
+ // Methods for setting and resetting budget pools for this task queue.
+ // Note that a task queue can be in multiple budget pools so a pool must
+ // be specified when removing.
+ void AddToBudgetPool(base::TimeTicks now, BudgetPool* pool);
+ void RemoveFromBudgetPool(base::TimeTicks now, BudgetPool* pool);
+
+ void IncreaseThrottleRefCount();
+ void DecreaseThrottleRefCount();
+
+ void ShutdownTaskQueue() override;
+
// This method returns the default task runner with task type kTaskTypeNone
// and is mostly used for tests. For most use cases, you'll want a more
// specific task runner and should use the 'CreateTaskRunner' method and pass
@@ -43,9 +60,21 @@ class PLATFORM_EXPORT NonMainThreadTaskQueue
return task_runner();
}
+ void SetWebSchedulingPriority(WebSchedulingPriority priority);
+
+ void OnTaskRunTimeReported(TaskQueue::TaskTiming* task_timing);
+
private:
+ void OnWebSchedulingPriorityChanged();
+
+ absl::optional<TaskQueueThrottler> throttler_;
+
// Not owned.
NonMainThreadSchedulerImpl* non_main_thread_scheduler_;
+
+ // |web_scheduling_priority_| is the priority of the task queue within the web
+ // scheduling API. This priority is used to determine the task queue priority.
+ absl::optional<WebSchedulingPriority> web_scheduling_priority_;
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc
new file mode 100644
index 00000000000..cc6320b41ff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h"
+
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+NonMainThreadWebSchedulingTaskQueueImpl::
+ NonMainThreadWebSchedulingTaskQueueImpl(
+ scoped_refptr<NonMainThreadTaskQueue> task_queue)
+ : task_runner_(
+ task_queue->CreateTaskRunner(TaskType::kExperimentalWebScheduling)),
+ task_queue_(std::move(task_queue)) {}
+
+void NonMainThreadWebSchedulingTaskQueueImpl::SetPriority(
+ WebSchedulingPriority priority) {
+ task_queue_->SetWebSchedulingPriority(priority);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+NonMainThreadWebSchedulingTaskQueueImpl::GetTaskRunner() {
+ return task_runner_;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h
new file mode 100644
index 00000000000..bd4e7050caa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
+
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
+
+namespace blink {
+namespace scheduler {
+
+class NonMainThreadTaskQueue;
+
+class PLATFORM_EXPORT NonMainThreadWebSchedulingTaskQueueImpl
+ : public WebSchedulingTaskQueue {
+ public:
+ explicit NonMainThreadWebSchedulingTaskQueueImpl(
+ scoped_refptr<NonMainThreadTaskQueue>);
+ ~NonMainThreadWebSchedulingTaskQueueImpl() override = default;
+
+ void SetPriority(WebSchedulingPriority) override;
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
+
+ private:
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // NonMainThreadWebSchedulingTaskQueueImpl owns this NonMainThreadTaskQueue
+ // and has the sole reference to it after its creation.
+ const scoped_refptr<NonMainThreadTaskQueue> task_queue_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_
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
index d71aab7a391..7303bf95c41 100644
--- 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
@@ -5,6 +5,7 @@
#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/abseil-cpp/absl/types/optional.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/common/thread_load_tracker.h"
@@ -18,6 +19,8 @@ class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper {
public:
explicit WorkerMetricsHelper(ThreadType thread_type,
bool has_cpu_timing_for_each_task);
+ WorkerMetricsHelper(const WorkerMetricsHelper&) = delete;
+ WorkerMetricsHelper& operator=(const WorkerMetricsHelper&) = delete;
~WorkerMetricsHelper();
void RecordTaskMetrics(
@@ -37,8 +40,6 @@ class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper {
background_dedicated_worker_per_parent_frame_status_duration_reporter_;
absl::optional<FrameOriginType> parent_frame_type_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerMetricsHelper);
};
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
index c55346e9190..91cd5b89f20 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -6,8 +6,10 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.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/non_main_thread_web_scheduling_task_queue_impl.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"
@@ -28,7 +30,8 @@ WorkerScheduler::PauseHandle::~PauseHandle() {
WorkerScheduler::WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler,
WorkerSchedulerProxy* proxy)
: throttleable_task_queue_(
- worker_thread_scheduler->CreateTaskQueue("worker_throttleable_tq")),
+ worker_thread_scheduler->CreateTaskQueue("worker_throttleable_tq",
+ true)),
pausable_task_queue_(
worker_thread_scheduler->CreateTaskQueue("worker_pausable_tq")),
unpausable_task_queue_(
@@ -90,8 +93,10 @@ void WorkerScheduler::ResumeImpl() {
}
void WorkerScheduler::SetUpThrottling() {
- if (!thread_scheduler_->task_queue_throttler())
+ if (!thread_scheduler_->wake_up_budget_pool() &&
+ !thread_scheduler_->cpu_time_budget_pool()) {
return;
+ }
base::TimeTicks now = thread_scheduler_->GetTickClock()->NowTicks();
WakeUpBudgetPool* wake_up_budget_pool =
@@ -99,14 +104,11 @@ void WorkerScheduler::SetUpThrottling() {
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());
+ throttleable_task_queue_->AddToBudgetPool(now, wake_up_budget_pool);
}
if (cpu_time_budget_pool) {
- cpu_time_budget_pool->AddQueue(now, throttleable_task_queue_.get());
+ throttleable_task_queue_->AddToBudgetPool(now, cpu_time_budget_pool);
}
}
@@ -116,11 +118,6 @@ SchedulingLifecycleState WorkerScheduler::CalculateLifecycleState(
}
void WorkerScheduler::Dispose() {
- if (TaskQueueThrottler* throttler =
- thread_scheduler_->task_queue_throttler()) {
- throttler->ShutdownTaskQueue(throttleable_task_queue_.get());
- }
-
thread_scheduler_->UnregisterWorkerScheduler(this);
for (const auto& pair : task_runners_) {
@@ -220,7 +217,7 @@ scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner(
case TaskType::kInternalHighPriorityLocalFrame:
case TaskType::kInternalInputBlocking:
case TaskType::kMainThreadTaskQueueIPCTracking:
- case TaskType::kCount:
+ case TaskType::kInternalPostMessageForwarding:
NOTREACHED();
break;
}
@@ -235,12 +232,12 @@ void WorkerScheduler::OnLifecycleStateChanged(
lifecycle_state_ = lifecycle_state;
thread_scheduler_->OnLifecycleStateChanged(lifecycle_state);
- if (TaskQueueThrottler* throttler =
- thread_scheduler_->task_queue_throttler()) {
+ if (thread_scheduler_->cpu_time_budget_pool() ||
+ thread_scheduler_->wake_up_budget_pool()) {
if (lifecycle_state_ == SchedulingLifecycleState::kThrottled) {
- throttler->IncreaseThrottleRefCount(throttleable_task_queue_.get());
+ throttleable_task_queue_->IncreaseThrottleRefCount();
} else {
- throttler->DecreaseThrottleRefCount(throttleable_task_queue_.get());
+ throttleable_task_queue_->DecreaseThrottleRefCount();
}
}
NotifyLifecycleObservers();
@@ -264,5 +261,14 @@ void WorkerScheduler::OnStartedUsingFeature(SchedulingPolicy::Feature feature,
void WorkerScheduler::OnStoppedUsingFeature(SchedulingPolicy::Feature feature,
const SchedulingPolicy& policy) {}
+std::unique_ptr<WebSchedulingTaskQueue>
+WorkerScheduler::CreateWebSchedulingTaskQueue(WebSchedulingPriority priority) {
+ scoped_refptr<NonMainThreadTaskQueue> task_queue =
+ thread_scheduler_->CreateTaskQueue("worker_web_scheduling_tq");
+ task_queue->SetWebSchedulingPriority(priority);
+ return std::make_unique<NonMainThreadWebSchedulingTaskQueueImpl>(
+ std::move(task_queue));
+}
+
} // 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
index 341d6116429..efe0b014eb0 100644
--- 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
@@ -5,7 +5,6 @@
#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/single_thread_task_runner.h"
@@ -34,6 +33,8 @@ class PLATFORM_EXPORT WorkerSchedulerProxy
: public FrameOrWorkerScheduler::Observer {
public:
explicit WorkerSchedulerProxy(FrameOrWorkerScheduler* scheduler);
+ WorkerSchedulerProxy(const WorkerSchedulerProxy&) = delete;
+ WorkerSchedulerProxy& operator=(const WorkerSchedulerProxy&) = delete;
~WorkerSchedulerProxy() override;
void OnWorkerSchedulerCreated(
@@ -85,8 +86,6 @@ class PLATFORM_EXPORT WorkerSchedulerProxy
ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId;
THREAD_CHECKER(parent_thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerProxy);
};
} // namespace scheduler
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
index 932a3418b26..6b6db450f24 100644
--- 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
@@ -6,13 +6,15 @@
#include <memory>
#include "base/bind.h"
-#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/cpu_time_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -71,7 +73,7 @@ class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
return GetWorkerSchedulersForTesting();
}
- using WorkerThreadScheduler::CreateTaskQueueThrottler;
+ using WorkerThreadScheduler::CreateBudgetPools;
using WorkerThreadScheduler::SetCPUTimeBudgetPoolForTesting;
};
@@ -99,8 +101,11 @@ class WorkerSchedulerTest : public testing::Test {
nullptr /* proxy */)) {
mock_task_runner_->AdvanceMockTickClock(
base::TimeDelta::FromMicroseconds(5000));
+ start_time_ = mock_task_runner_->NowTicks();
}
+ WorkerSchedulerTest(const WorkerSchedulerTest&) = delete;
+ WorkerSchedulerTest& operator=(const WorkerSchedulerTest&) = delete;
~WorkerSchedulerTest() override = default;
void SetUp() override {
@@ -138,8 +143,7 @@ class WorkerSchedulerTest : public testing::Test {
sequence_manager_;
std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_;
std::unique_ptr<WorkerSchedulerForTest> worker_scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerTest);
+ base::TimeTicks start_time_;
};
TEST_F(WorkerSchedulerTest, TestPostTasks) {
@@ -185,28 +189,24 @@ TEST_F(WorkerSchedulerTest, RegisterWorkerSchedulers) {
}
TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler) {
- scheduler_->CreateTaskQueueThrottler();
+ scheduler_->CreateBudgetPools();
- EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
+ EXPECT_FALSE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled());
scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
- EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
+ EXPECT_TRUE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled());
scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
- EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
+ EXPECT_TRUE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled());
// 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()));
+ EXPECT_FALSE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled());
}
TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_CreateThrottled) {
- scheduler_->CreateTaskQueueThrottler();
+ scheduler_->CreateBudgetPools();
scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
@@ -214,14 +214,13 @@ TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_CreateThrottled) {
std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
// Ensure that newly created scheduler is throttled.
- EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler2->ThrottleableTaskQueue().get()));
+ EXPECT_TRUE(worker_scheduler2->ThrottleableTaskQueue()->IsThrottled());
worker_scheduler2->Dispose();
}
TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks) {
- scheduler_->CreateTaskQueueThrottler();
+ scheduler_->CreateBudgetPools();
scheduler_->SetCPUTimeBudgetPoolForTesting(nullptr);
// Create a new |worker_scheduler| to ensure that it's properly initialised.
@@ -251,7 +250,7 @@ TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks) {
TEST_F(WorkerSchedulerTest,
ThrottleWorkerScheduler_RunThrottledTasks_CPUBudget) {
- scheduler_->CreateTaskQueueThrottler();
+ scheduler_->CreateBudgetPools();
scheduler_->cpu_time_budget_pool()->SetTimeBudgetRecoveryRate(
GetClock()->NowTicks(), 0.01);
@@ -273,12 +272,12 @@ TEST_F(WorkerSchedulerTest,
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)));
+ EXPECT_THAT(tasks,
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ start_time_ + base::TimeDelta::FromSeconds(10),
+ start_time_ + base::TimeDelta::FromSeconds(20),
+ start_time_ + base::TimeDelta::FromSeconds(30),
+ start_time_ + base::TimeDelta::FromSeconds(40)));
}
TEST_F(WorkerSchedulerTest, MAYBE_PausableTasks) {
@@ -315,6 +314,83 @@ TEST_F(WorkerSchedulerTest, MAYBE_NestedPauseHandlesTasks) {
EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2"));
}
+class NonMainThreadWebSchedulingTaskQueueTest : public WorkerSchedulerTest {
+ public:
+ void SetUp() override {
+ WorkerSchedulerTest::SetUp();
+
+ for (int i = 0; i <= static_cast<int>(WebSchedulingPriority::kLastPriority);
+ i++) {
+ WebSchedulingPriority priority = static_cast<WebSchedulingPriority>(i);
+ std::unique_ptr<WebSchedulingTaskQueue> task_queue =
+ worker_scheduler_->CreateWebSchedulingTaskQueue(priority);
+ task_queues_.push_back(std::move(task_queue));
+ }
+ }
+
+ void TearDown() override {
+ WorkerSchedulerTest::TearDown();
+ task_queues_.clear();
+ }
+
+ protected:
+ // Helper for posting tasks to a WebSchedulingTaskQueue. |task_descriptor| is
+ // a string with space delimited task identifiers. The first letter of each
+ // task identifier specifies the task queue priority:
+ // - 'U': UserBlocking
+ // - 'V': UserVisible
+ // - 'B': Background
+ void PostWebSchedulingTestTasks(Vector<String>* run_order,
+ const String& task_descriptor) {
+ std::istringstream stream(task_descriptor.Utf8());
+ while (!stream.eof()) {
+ std::string task;
+ stream >> task;
+ WebSchedulingPriority priority;
+ switch (task[0]) {
+ case 'U':
+ priority = WebSchedulingPriority::kUserBlockingPriority;
+ break;
+ case 'V':
+ priority = WebSchedulingPriority::kUserVisiblePriority;
+ break;
+ case 'B':
+ priority = WebSchedulingPriority::kBackgroundPriority;
+ break;
+ default:
+ EXPECT_FALSE(true);
+ return;
+ }
+ task_queues_[static_cast<int>(priority)]->GetTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&AppendToVectorTestTask, run_order,
+ String::FromUTF8(task)));
+ }
+ }
+ Vector<std::unique_ptr<WebSchedulingTaskQueue>> task_queues_;
+};
+
+TEST_F(NonMainThreadWebSchedulingTaskQueueTest, TasksRunInPriorityOrder) {
+ Vector<String> run_order;
+
+ PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2");
+
+ RunUntilIdle();
+ EXPECT_THAT(run_order,
+ testing::ElementsAre("U1", "U2", "V1", "V2", "B1", "B2"));
+}
+
+TEST_F(NonMainThreadWebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) {
+ Vector<String> run_order;
+
+ PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2");
+ task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)]
+ ->SetPriority(WebSchedulingPriority::kBackgroundPriority);
+
+ RunUntilIdle();
+ EXPECT_THAT(run_order,
+ testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2"));
+}
+
} // 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 35284815699..519087970f5 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
@@ -23,7 +23,9 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/process_state.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.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/event_loop.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"
@@ -117,7 +119,7 @@ WorkerThreadScheduler::WorkerThreadScheduler(
if (thread_type == ThreadType::kDedicatedWorkerThread &&
base::FeatureList::IsEnabled(kDedicatedWorkerThrottling)) {
- CreateTaskQueueThrottler();
+ CreateBudgetPools();
}
TRACE_EVENT_OBJECT_CREATED_WITH_ID(
@@ -178,7 +180,6 @@ void WorkerThreadScheduler::RemoveTaskObserver(
void WorkerThreadScheduler::Shutdown() {
DCHECK(initialized_);
- task_queue_throttler_.reset();
idle_helper_.Shutdown();
helper()->Shutdown();
}
@@ -209,10 +210,8 @@ void WorkerThreadScheduler::OnTaskCompleted(
task_timing->RecordTaskEnd(lazy_now);
worker_metrics_helper_.RecordTaskMetrics(task, *task_timing);
- if (task_queue_throttler_) {
- task_queue_throttler_->OnTaskRunTimeReported(
- task_queue, task_timing->start_time(), task_timing->end_time());
- }
+ if (task_queue != nullptr)
+ task_queue->OnTaskRunTimeReported(task_timing);
RecordTaskUkm(task_queue, task, *task_timing);
}
@@ -258,17 +257,15 @@ WorkerThreadScheduler::ControlTaskQueue() {
return helper()->ControlNonMainThreadTaskQueue();
}
-void WorkerThreadScheduler::CreateTaskQueueThrottler() {
- if (task_queue_throttler_)
+void WorkerThreadScheduler::CreateBudgetPools() {
+ if (wake_up_budget_pool_ && cpu_time_budget_pool_)
return;
- task_queue_throttler_ = std::make_unique<TaskQueueThrottler>(
- this, &traceable_variable_controller_);
+ base::TimeTicks now = GetTickClock()->NowTicks();
wake_up_budget_pool_ =
- task_queue_throttler_->CreateWakeUpBudgetPool("worker_wake_up_pool");
- cpu_time_budget_pool_ =
- task_queue_throttler_->CreateCPUTimeBudgetPool("worker_cpu_time_pool");
+ std::make_unique<WakeUpBudgetPool>("worker_wake_up_pool");
+ cpu_time_budget_pool_ = std::make_unique<CPUTimeBudgetPool>(
+ "worker_cpu_time_pool", &traceable_variable_controller_, now);
- base::TimeTicks now = GetTickClock()->NowTicks();
cpu_time_budget_pool_->SetMaxBudgetLevel(now, GetMaxBudgetLevel());
cpu_time_budget_pool_->SetTimeBudgetRecoveryRate(now,
GetBudgetRecoveryRate());
@@ -312,8 +309,8 @@ void WorkerThreadScheduler::SetUkmTaskSamplingRateForTest(double rate) {
}
void WorkerThreadScheduler::SetCPUTimeBudgetPoolForTesting(
- CPUTimeBudgetPool* cpu_time_budget_pool) {
- cpu_time_budget_pool_ = cpu_time_budget_pool;
+ std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool) {
+ cpu_time_budget_pool_ = std::move(cpu_time_budget_pool);
}
HashSet<WorkerScheduler*>&
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 de6debae895..5d431c3ecfe 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
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "components/scheduling_metrics/task_duration_metric_reporter.h"
#include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h"
@@ -31,7 +30,6 @@ namespace scheduler {
class WorkerScheduler;
class WorkerSchedulerProxy;
-class TaskQueueThrottler;
class WakeUpBudgetPool;
class CPUTimeBudgetPool;
@@ -44,6 +42,8 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl,
ThreadType thread_type,
base::sequence_manager::SequenceManager* sequence_manager,
WorkerSchedulerProxy* proxy);
+ WorkerThreadScheduler(const WorkerThreadScheduler&) = delete;
+ WorkerThreadScheduler& operator=(const WorkerThreadScheduler&) = delete;
~WorkerThreadScheduler() override;
// WebThreadScheduler implementation:
@@ -89,14 +89,11 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl,
// task queues.
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_.get();
}
- WakeUpBudgetPool* wake_up_budget_pool() const { return wake_up_budget_pool_; }
CPUTimeBudgetPool* cpu_time_budget_pool() const {
- return cpu_time_budget_pool_;
+ return cpu_time_budget_pool_.get();
}
protected:
@@ -109,9 +106,10 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl,
void OnIdlePeriodEnded() override {}
void OnPendingTasksChanged(bool new_state) override {}
- void CreateTaskQueueThrottler();
+ void CreateBudgetPools();
- void SetCPUTimeBudgetPoolForTesting(CPUTimeBudgetPool* cpu_time_budget_pool);
+ void SetCPUTimeBudgetPoolForTesting(
+ std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool);
HashSet<WorkerScheduler*>& GetWorkerSchedulersForTesting();
@@ -145,18 +143,14 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl,
// Worker schedulers associated with this thread.
HashSet<WorkerScheduler*> worker_schedulers_;
- std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
- // Owned by |task_queue_throttler_|.
- WakeUpBudgetPool* wake_up_budget_pool_ = nullptr;
- CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr;
+ std::unique_ptr<WakeUpBudgetPool> wake_up_budget_pool_;
+ std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool_;
// The status of the parent frame when the worker was created.
const FrameStatus initial_frame_status_;
const ukm::SourceId ukm_source_id_;
std::unique_ptr<ukm::UkmRecorder> ukm_recorder_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThreadScheduler);
};
} // namespace scheduler
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 2f9f37b427a..decca008b05 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
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/task/sequence_manager/test/fake_task.h"
#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
@@ -158,6 +157,9 @@ class WorkerThreadSchedulerTest : public testing::Test {
idle_task_runner_ = scheduler_->IdleTaskRunner();
}
+ WorkerThreadSchedulerTest(const WorkerThreadSchedulerTest&) = delete;
+ WorkerThreadSchedulerTest& operator=(const WorkerThreadSchedulerTest&) =
+ delete;
~WorkerThreadSchedulerTest() override = default;
void TearDown() override {
@@ -219,8 +221,6 @@ class WorkerThreadSchedulerTest : public testing::Test {
scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThreadSchedulerTest);
};
} // namespace
@@ -509,6 +509,10 @@ class WorkerThreadSchedulerWithProxyTest : public testing::Test {
scheduler_->AttachToCurrentThread();
}
+ WorkerThreadSchedulerWithProxyTest(
+ const WorkerThreadSchedulerWithProxyTest&) = delete;
+ WorkerThreadSchedulerWithProxyTest& operator=(
+ const WorkerThreadSchedulerWithProxyTest&) = delete;
~WorkerThreadSchedulerWithProxyTest() override = default;
void TearDown() override {
@@ -526,8 +530,6 @@ class WorkerThreadSchedulerWithProxyTest : public testing::Test {
std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThreadSchedulerWithProxyTest);
};
TEST_F(WorkerThreadSchedulerWithProxyTest, UkmTaskRecording) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc
index af4e41dd2a1..a320a2f42d7 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/task_executor.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -72,6 +71,8 @@ void ShutdownOnThread(Thread* thread) {
class WorkerThreadTest : public testing::Test {
public:
WorkerThreadTest() = default;
+ WorkerThreadTest(const WorkerThreadTest&) = delete;
+ WorkerThreadTest& operator=(const WorkerThreadTest&) = delete;
~WorkerThreadTest() override = default;
@@ -100,8 +101,6 @@ class WorkerThreadTest : public testing::Test {
}
std::unique_ptr<Thread> thread_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThreadTest);
};
TEST_F(WorkerThreadTest, TestDefaultTask) {
diff --git a/chromium/third_party/blink/renderer/platform/storage/OWNERS b/chromium/third_party/blink/renderer/platform/storage/OWNERS
new file mode 100644
index 00000000000..24d6d7b109a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/OWNERS
@@ -0,0 +1,9 @@
+# Primary:
+mek@chromium.org
+
+# Secondary:
+jsbell@chromium.org
+pwnall@chromium.org
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/renderer/platform/storage/blink_storage_key.cc b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key.cc
new file mode 100644
index 00000000000..6b33337dec3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key.cc
@@ -0,0 +1,68 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <ostream>
+
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
+
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+
+namespace blink {
+
+BlinkStorageKey::BlinkStorageKey()
+ : BlinkStorageKey(SecurityOrigin::CreateUniqueOpaque(), nullptr) {}
+
+BlinkStorageKey::BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin)
+ : BlinkStorageKey(std::move(origin), nullptr) {}
+
+BlinkStorageKey::BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin,
+ const base::UnguessableToken* nonce)
+ : origin_(std::move(origin)),
+ nonce_(nonce ? absl::make_optional(*nonce) : absl::nullopt) {
+ DCHECK(origin_);
+}
+
+// static
+BlinkStorageKey BlinkStorageKey::CreateWithNonce(
+ scoped_refptr<const SecurityOrigin> origin,
+ const base::UnguessableToken& nonce) {
+ DCHECK(!nonce.is_empty());
+ return BlinkStorageKey(std::move(origin), &nonce);
+}
+
+BlinkStorageKey::BlinkStorageKey(const StorageKey& storage_key)
+ : BlinkStorageKey(
+ SecurityOrigin::CreateFromUrlOrigin(storage_key.origin()),
+ storage_key.nonce() ? &storage_key.nonce().value() : nullptr) {}
+
+BlinkStorageKey::operator StorageKey() const {
+ return nonce_.has_value() ? StorageKey::CreateWithNonce(
+ origin_->ToUrlOrigin(), nonce_.value())
+ : StorageKey(origin_->ToUrlOrigin());
+}
+
+String BlinkStorageKey::ToDebugString() const {
+ return "{ origin: " + GetSecurityOrigin()->ToString() + ", nonce: " +
+ (GetNonce().has_value() ? String::FromUTF8(GetNonce()->ToString())
+ : "<null>") +
+ " }";
+}
+
+bool operator==(const BlinkStorageKey& lhs, const BlinkStorageKey& rhs) {
+ DCHECK(lhs.GetSecurityOrigin());
+ DCHECK(rhs.GetSecurityOrigin());
+ return lhs.GetSecurityOrigin()->IsSameOriginWith(
+ rhs.GetSecurityOrigin().get()) &&
+ lhs.GetNonce() == rhs.GetNonce();
+}
+
+bool operator!=(const BlinkStorageKey& lhs, const BlinkStorageKey& rhs) {
+ return !(lhs == rhs);
+}
+
+std::ostream& operator<<(std::ostream& ostream, const BlinkStorageKey& key) {
+ return ostream << key.ToDebugString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/storage/blink_storage_key.h b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key.h
new file mode 100644
index 00000000000..959619e9024
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key.h
@@ -0,0 +1,79 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_STORAGE_BLINK_STORAGE_KEY_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_STORAGE_BLINK_STORAGE_KEY_H_
+
+#include <iosfwd>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/unguessable_token.h"
+#include "third_party/blink/public/common/storage_key/storage_key.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/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// This class represents the key by which DOM Storage keys its
+// CachedStorageAreas.
+// It is typemapped to blink.mojom.StorageKey, and should stay in sync with
+// blink::StorageKey (third_party/blink/public/common/storage_key/storage_key.h)
+class PLATFORM_EXPORT BlinkStorageKey {
+ DISALLOW_NEW();
+
+ public:
+ // Creates a BlinkStorageKey with a unique opaque origin.
+ BlinkStorageKey();
+
+ // Creates a BlinkStorageKey with the given origin. `origin` must not be null.
+ // `origin` can be opaque.
+ explicit BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin);
+
+ // Creates a BlinkStorageKey converting the given StorageKey `storage_key`.
+ BlinkStorageKey(const StorageKey& storage_key);
+
+ // Converts this BlinkStorageKey into a StorageKey.
+ operator StorageKey() const;
+
+ ~BlinkStorageKey() = default;
+
+ BlinkStorageKey(const BlinkStorageKey& other) = default;
+ BlinkStorageKey& operator=(const BlinkStorageKey& other) = default;
+ BlinkStorageKey(BlinkStorageKey&& other) = default;
+ BlinkStorageKey& operator=(BlinkStorageKey&& other) = default;
+
+ static BlinkStorageKey CreateWithNonce(
+ scoped_refptr<const SecurityOrigin> origin,
+ const base::UnguessableToken& nonce);
+
+ const scoped_refptr<const SecurityOrigin>& GetSecurityOrigin() const {
+ return origin_;
+ }
+
+ const absl::optional<base::UnguessableToken>& GetNonce() const {
+ return nonce_;
+ }
+
+ String ToDebugString() const;
+
+ private:
+ BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin,
+ const base::UnguessableToken* nonce);
+
+ scoped_refptr<const SecurityOrigin> origin_;
+ absl::optional<base::UnguessableToken> nonce_;
+};
+
+PLATFORM_EXPORT
+bool operator==(const BlinkStorageKey&, const BlinkStorageKey&);
+PLATFORM_EXPORT
+bool operator!=(const BlinkStorageKey&, const BlinkStorageKey&);
+PLATFORM_EXPORT
+std::ostream& operator<<(std::ostream&, const BlinkStorageKey&);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_STORAGE_BLINK_STORAGE_KEY_H_
diff --git a/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc
new file mode 100644
index 00000000000..a0ff3990958
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h"
+
+#include "base/unguessable_token.h"
+#include "third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<blink::mojom::StorageKeyDataView, blink::BlinkStorageKey>::
+ Read(blink::mojom::StorageKeyDataView data, blink::BlinkStorageKey* out) {
+ scoped_refptr<const blink::SecurityOrigin> origin;
+ if (!data.ReadOrigin(&origin))
+ return false;
+ DCHECK(origin);
+
+ absl::optional<base::UnguessableToken> nonce;
+ if (!data.ReadNonce(&nonce))
+ return false;
+
+ if (nonce.has_value()) {
+ *out = blink::BlinkStorageKey::CreateWithNonce(std::move(origin),
+ nonce.value());
+ } else {
+ *out = blink::BlinkStorageKey(std::move(origin));
+ }
+
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h
new file mode 100644
index 00000000000..40b9fc816aa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_STORAGE_BLINK_STORAGE_KEY_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_STORAGE_BLINK_STORAGE_KEY_MOJOM_TRAITS_H_
+
+#include "third_party/blink/public/mojom/storage_key/storage_key.mojom-shared.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
+
+namespace mojo {
+
+template <>
+struct PLATFORM_EXPORT
+ StructTraits<blink::mojom::StorageKeyDataView, blink::BlinkStorageKey> {
+ static const scoped_refptr<const blink::SecurityOrigin>& origin(
+ const blink::BlinkStorageKey& input) {
+ return input.GetSecurityOrigin();
+ }
+
+ static const absl::optional<base::UnguessableToken>& nonce(
+ const blink::BlinkStorageKey& input) {
+ return input.GetNonce();
+ }
+
+ static bool Read(blink::mojom::StorageKeyDataView data,
+ blink::BlinkStorageKey* out);
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_STORAGE_BLINK_STORAGE_KEY_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc
new file mode 100644
index 00000000000..d1ba28b61ad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc
@@ -0,0 +1,144 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h"
+
+#include "base/unguessable_token.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+#include "third_party/blink/public/common/storage_key/storage_key_mojom_traits.h"
+#include "third_party/blink/public/mojom/storage_key/storage_key.mojom-blink.h"
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace blink {
+
+TEST(BlinkStorageKeyMojomTraitsTest, SerializeAndDeserialize_BlinkStorageKey) {
+ scoped_refptr<const SecurityOrigin> origin1 =
+ SecurityOrigin::CreateUniqueOpaque();
+ scoped_refptr<const SecurityOrigin> origin2 =
+ SecurityOrigin::CreateFromString("http://example.site");
+ scoped_refptr<const SecurityOrigin> origin3 =
+ SecurityOrigin::CreateFromString("https://example.site");
+ scoped_refptr<const SecurityOrigin> origin4 =
+ SecurityOrigin::CreateFromString("file:///path/to/file");
+ base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ Vector<BlinkStorageKey> keys = {
+ BlinkStorageKey(),
+ BlinkStorageKey(origin1),
+ BlinkStorageKey(origin2),
+ BlinkStorageKey(origin3),
+ BlinkStorageKey(origin4),
+ BlinkStorageKey::CreateWithNonce(origin1, nonce),
+ BlinkStorageKey::CreateWithNonce(origin2, nonce),
+ };
+
+ for (BlinkStorageKey& key : keys) {
+ BlinkStorageKey copied;
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::blink::StorageKey>(
+ key, copied));
+ EXPECT_EQ(key, copied);
+ EXPECT_TRUE(key.GetSecurityOrigin()->IsSameOriginWith(
+ copied.GetSecurityOrigin().get()));
+ EXPECT_EQ(key.GetNonce(), copied.GetNonce());
+ }
+}
+
+// Tests serializing from blink::StorageKey and deserializing to
+// blink::BlinkStorageKey.
+TEST(BlinkStorageKeyMojomTraitsTest,
+ SerializeFromStorageKey_DeserializeToBlinkStorageKey) {
+ scoped_refptr<const SecurityOrigin> origin1 =
+ SecurityOrigin::CreateUniqueOpaque();
+ scoped_refptr<const SecurityOrigin> origin2 =
+ SecurityOrigin::CreateFromString("http://example.site");
+ scoped_refptr<const SecurityOrigin> origin3 =
+ SecurityOrigin::CreateFromString("https://example.site");
+ scoped_refptr<const SecurityOrigin> origin4 =
+ SecurityOrigin::CreateFromString("file:///path/to/file");
+ base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ url::Origin url_origin1 = origin1->ToUrlOrigin();
+ url::Origin url_origin2 = origin2->ToUrlOrigin();
+ url::Origin url_origin3 = origin3->ToUrlOrigin();
+ url::Origin url_origin4 = origin4->ToUrlOrigin();
+
+ Vector<StorageKey> storage_keys = {
+ StorageKey(url_origin1),
+ StorageKey(url_origin2),
+ StorageKey(url_origin3),
+ StorageKey(url_origin4),
+ StorageKey::CreateWithNonce(url_origin1, nonce),
+ StorageKey::CreateWithNonce(url_origin2, nonce),
+ };
+ Vector<BlinkStorageKey> blink_storage_keys = {
+ BlinkStorageKey(origin1),
+ BlinkStorageKey(origin2),
+ BlinkStorageKey(origin3),
+ BlinkStorageKey(origin4),
+ BlinkStorageKey::CreateWithNonce(origin1, nonce),
+ BlinkStorageKey::CreateWithNonce(origin2, nonce),
+ };
+
+ for (size_t i = 0; i < storage_keys.size(); ++i) {
+ auto serialized = mojom::StorageKey::Serialize(&storage_keys[i]);
+
+ BlinkStorageKey deserialized;
+ EXPECT_TRUE(mojom::StorageKey::Deserialize(serialized, &deserialized));
+ EXPECT_EQ(blink_storage_keys[i], deserialized);
+ }
+}
+
+// Tests serializing from blink::StorageKey and deserializing to
+// blink::BlinkStorageKey.
+TEST(BlinkStorageKeyMojomTraitsTest,
+ SerializeFromBlinkStorageKey_DeserializeToStorageKey) {
+ url::Origin url_origin1;
+ url::Origin url_origin2 = url::Origin::Create(GURL("http://example.site"));
+ url::Origin url_origin3 = url::Origin::Create(GURL("https://example.site"));
+ url::Origin url_origin4 = url::Origin::Create(GURL("file:///path/to/file"));
+ base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ scoped_refptr<const SecurityOrigin> origin1 =
+ SecurityOrigin::CreateFromUrlOrigin(url_origin1);
+ scoped_refptr<const SecurityOrigin> origin2 =
+ SecurityOrigin::CreateFromUrlOrigin(url_origin2);
+ scoped_refptr<const SecurityOrigin> origin3 =
+ SecurityOrigin::CreateFromUrlOrigin(url_origin3);
+ scoped_refptr<const SecurityOrigin> origin4 =
+ SecurityOrigin::CreateFromUrlOrigin(url_origin4);
+
+ Vector<StorageKey> storage_keys = {
+ StorageKey(url_origin1),
+ StorageKey(url_origin2),
+ StorageKey(url_origin3),
+ StorageKey(url_origin4),
+ StorageKey::CreateWithNonce(url_origin1, nonce),
+ StorageKey::CreateWithNonce(url_origin2, nonce),
+ };
+
+ Vector<BlinkStorageKey> blink_storage_keys = {
+ BlinkStorageKey(origin1),
+ BlinkStorageKey(origin2),
+ BlinkStorageKey(origin3),
+ BlinkStorageKey(origin4),
+ BlinkStorageKey::CreateWithNonce(origin1, nonce),
+ BlinkStorageKey::CreateWithNonce(origin2, nonce),
+ };
+
+ for (size_t i = 0; i < storage_keys.size(); ++i) {
+ auto serialized = mojom::StorageKey::Serialize(&blink_storage_keys[i]);
+
+ StorageKey deserialized;
+ EXPECT_TRUE(mojom::StorageKey::Deserialize(serialized, &deserialized));
+ EXPECT_EQ(storage_keys[i], deserialized);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc
new file mode 100644
index 00000000000..1808328f1b0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc
@@ -0,0 +1,135 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/unguessable_token.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+TEST(BlinkStorageKeyTest, OpaqueOriginsDistinct) {
+ // Test that two opaque origins give distinct BlinkStorageKeys.
+ BlinkStorageKey unique_opaque1;
+ EXPECT_TRUE(unique_opaque1.GetSecurityOrigin());
+ EXPECT_TRUE(unique_opaque1.GetSecurityOrigin()->IsOpaque());
+ BlinkStorageKey unique_opaque2;
+ EXPECT_FALSE(unique_opaque2.GetSecurityOrigin()->IsSameOriginWith(
+ unique_opaque1.GetSecurityOrigin().get()));
+ EXPECT_NE(unique_opaque1, unique_opaque2);
+}
+
+TEST(BlinkStorageKeyTest, EqualityWithNonce) {
+ // Test that BlinkStorageKeys with different nonces are different.
+ scoped_refptr<const SecurityOrigin> origin =
+ SecurityOrigin::CreateFromString("https://example.com");
+ base::UnguessableToken token1 = base::UnguessableToken::Create();
+ base::UnguessableToken token2 = base::UnguessableToken::Create();
+ BlinkStorageKey key1 = BlinkStorageKey::CreateWithNonce(origin, token1);
+ BlinkStorageKey key2 = BlinkStorageKey::CreateWithNonce(origin, token1);
+ BlinkStorageKey key3 = BlinkStorageKey::CreateWithNonce(origin, token2);
+
+ EXPECT_TRUE(key1.GetSecurityOrigin()->IsSameOriginWith(
+ key2.GetSecurityOrigin().get()));
+ EXPECT_TRUE(key1.GetSecurityOrigin()->IsSameOriginWith(
+ key3.GetSecurityOrigin().get()));
+ EXPECT_TRUE(key2.GetSecurityOrigin()->IsSameOriginWith(
+ key3.GetSecurityOrigin().get()));
+
+ EXPECT_EQ(key1, key2);
+ EXPECT_NE(key1, key3);
+}
+
+TEST(BlinkStorageKeyTest, OpaqueOriginRetained) {
+ // Test that a StorageKey made from an opaque origin retains the origin.
+ scoped_refptr<const SecurityOrigin> opaque_origin =
+ SecurityOrigin::CreateUniqueOpaque();
+ scoped_refptr<const SecurityOrigin> opaque_copied =
+ opaque_origin->IsolatedCopy();
+ BlinkStorageKey from_opaque(std::move(opaque_origin));
+ EXPECT_TRUE(
+ from_opaque.GetSecurityOrigin()->IsSameOriginWith(opaque_copied.get()));
+}
+
+TEST(BlinkStorageKeyTest, CreateFromNonOpaqueOrigin) {
+ struct {
+ const char* origin;
+ } kTestCases[] = {
+ {"http://example.site"},
+ {"https://example.site"},
+ {"file:///path/to/file"},
+ };
+
+ for (const auto& test : kTestCases) {
+ scoped_refptr<const SecurityOrigin> origin =
+ SecurityOrigin::CreateFromString(test.origin);
+ ASSERT_FALSE(origin->IsOpaque());
+ scoped_refptr<const SecurityOrigin> copied = origin->IsolatedCopy();
+
+ // Test that the origin is retained.
+ BlinkStorageKey storage_key(std::move(origin));
+ EXPECT_TRUE(
+ storage_key.GetSecurityOrigin()->IsSameOriginWith(copied.get()));
+
+ // Test that two StorageKeys from the same origin are the same.
+ BlinkStorageKey storage_key_from_copy(std::move(copied));
+ EXPECT_EQ(storage_key, storage_key_from_copy);
+ }
+}
+
+// Tests that the conversion BlinkStorageKey -> StorageKey -> BlinkStorageKey is
+// the identity.
+TEST(BlinkStorageKeyTest, BlinkStorageKeyRoundTripConversion) {
+ scoped_refptr<const SecurityOrigin> origin1 =
+ SecurityOrigin::CreateUniqueOpaque();
+ scoped_refptr<const SecurityOrigin> origin2 =
+ SecurityOrigin::CreateFromString("http://example.site");
+ scoped_refptr<const SecurityOrigin> origin3 =
+ SecurityOrigin::CreateFromString("https://example.site");
+ scoped_refptr<const SecurityOrigin> origin4 =
+ SecurityOrigin::CreateFromString("file:///path/to/file");
+ base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ Vector<BlinkStorageKey> keys = {
+ BlinkStorageKey(),
+ BlinkStorageKey(origin1),
+ BlinkStorageKey(origin2),
+ BlinkStorageKey(origin3),
+ BlinkStorageKey(origin4),
+ BlinkStorageKey::CreateWithNonce(origin1, nonce),
+ BlinkStorageKey::CreateWithNonce(origin2, nonce),
+ };
+
+ for (BlinkStorageKey& key : keys) {
+ EXPECT_EQ(key, BlinkStorageKey(StorageKey(key)));
+ }
+}
+
+// Tests that the conversion StorageKey -> BlinkStorageKey -> StorageKey is the
+// identity.
+TEST(BlinkStorageKey, StorageKeyRoundTripConversion) {
+ url::Origin url_origin1;
+ url::Origin url_origin2 = url::Origin::Create(GURL("http://example.site"));
+ url::Origin url_origin3 = url::Origin::Create(GURL("https://example.site"));
+ url::Origin url_origin4 = url::Origin::Create(GURL("file:///path/to/file"));
+ base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ Vector<StorageKey> storage_keys = {
+ StorageKey(url_origin1),
+ StorageKey(url_origin2),
+ StorageKey(url_origin3),
+ StorageKey(url_origin4),
+ StorageKey::CreateWithNonce(url_origin1, nonce),
+ StorageKey::CreateWithNonce(url_origin2, nonce),
+ };
+
+ for (const auto& key : storage_keys) {
+ EXPECT_EQ(key, StorageKey(BlinkStorageKey(key)));
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/supplementable.h b/chromium/third_party/blink/renderer/platform/supplementable.h
index c75df92d07d..d699c99b4e2 100644
--- a/chromium/third_party/blink/renderer/platform/supplementable.h
+++ b/chromium/third_party/blink/renderer/platform/supplementable.h
@@ -29,7 +29,6 @@
#include <cstddef>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -160,6 +159,9 @@ class Supplement : public GarbageCollectedMixin {
template <typename T>
class Supplementable : public GarbageCollectedMixin {
public:
+ Supplementable(const Supplementable&) = delete;
+ Supplementable& operator=(const Supplementable&) = delete;
+
template <typename SupplementType>
void ProvideSupplement(SupplementType* supplement) {
#if DCHECK_IS_ON()
@@ -194,7 +196,8 @@ class Supplementable : public GarbageCollectedMixin {
"Declare a const char array kSupplementName. See Supplementable.h for "
"details.");
return static_cast<SupplementType*>(
- this->supplements_.at(SupplementType::kSupplementName));
+ this->supplements_.DeprecatedAtOrEmptyValue(
+ SupplementType::kSupplementName));
}
void ReattachThread() {
@@ -223,8 +226,6 @@ class Supplementable : public GarbageCollectedMixin {
base::PlatformThreadId attached_thread_id_;
base::PlatformThreadId creation_thread_id_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(Supplementable);
};
template <typename T>
diff --git a/chromium/third_party/blink/renderer/platform/testing/OWNERS b/chromium/third_party/blink/renderer/platform/testing/OWNERS
index 81fbf4e9384..ef21f5ed508 100644
--- a/chromium/third_party/blink/renderer/platform/testing/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/testing/OWNERS
@@ -1,4 +1,2 @@
danakj@chromium.org
dcheng@chromium.org
-
-per-file testing_platform_support_with_web_rtc.*=hbos@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc b/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
index dd55c90a14c..70cdf2a9e61 100644
--- a/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
@@ -6,19 +6,27 @@
namespace blink {
-void CodeCacheLoaderMock::FetchFromCodeCacheSynchronously(
- const WebURL& url,
- base::Time* response_time_out,
- mojo_base::BigBuffer* buffer_out) {
- *response_time_out = base::Time();
- *buffer_out = mojo_base::BigBuffer();
-}
-
void CodeCacheLoaderMock::FetchFromCodeCache(
blink::mojom::CodeCacheType cache_type,
const WebURL& url,
WebCodeCacheLoader::FetchCodeCacheCallback callback) {
- std::move(callback).Run(base::Time(), mojo_base::BigBuffer());
+ if (controller_ && controller_->delayed_) {
+ // This simple mock doesn't support multiple in-flight loads.
+ CHECK(!controller_->callback_);
+
+ controller_->callback_ = std::move(callback);
+ } else {
+ std::move(callback).Run(base::Time(), mojo_base::BigBuffer());
+ }
+}
+
+void CodeCacheLoaderMock::Controller::DelayResponse() {
+ delayed_ = true;
+}
+void CodeCacheLoaderMock::Controller::Respond(base::Time time,
+ mojo_base::BigBuffer data) {
+ CHECK(callback_);
+ std::move(callback_).Run(time, std::move(data));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h b/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
index 7878081a5d1..fb06db03e65 100644
--- a/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
+++ b/chromium/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
@@ -14,25 +14,41 @@ namespace blink {
// A simple class for mocking WebCodeCacheLoader.
class CodeCacheLoaderMock : public WebCodeCacheLoader {
public:
- CodeCacheLoaderMock() {}
+ // A class which can be owned by both this mock loader and the creator of this
+ // mock loader, which lets the creator control the behavior of the mock loader
+ // without having to retain a reference to the mock loader itself.
+ class Controller : public base::RefCounted<Controller> {
+ public:
+ void DelayResponse();
+ void Respond(base::Time time, mojo_base::BigBuffer data);
+
+ private:
+ friend class CodeCacheLoaderMock;
+ friend class base::RefCounted<Controller>;
+ ~Controller() = default;
+
+ // Whether to delay responses until Respond is called.
+ // Otherwise responses are immediate and empty.
+ bool delayed_ = false;
+
+ // Callback saved by fetch call, if delayed_ was true.
+ WebCodeCacheLoader::FetchCodeCacheCallback callback_;
+ };
+
+ explicit CodeCacheLoaderMock(scoped_refptr<Controller> controller = nullptr)
+ : controller_(std::move(controller)) {}
+ CodeCacheLoaderMock(const CodeCacheLoaderMock&) = delete;
+ CodeCacheLoaderMock& operator=(const CodeCacheLoaderMock&) = delete;
~CodeCacheLoaderMock() override = default;
// CodeCacheLoader methods:
- void FetchFromCodeCacheSynchronously(
- const WebURL& url,
- base::Time* response_time_out,
- mojo_base::BigBuffer* buffer_out) override;
void FetchFromCodeCache(
blink::mojom::CodeCacheType cache_type,
const WebURL& url,
WebCodeCacheLoader::FetchCodeCacheCallback callback) override;
- base::WeakPtr<CodeCacheLoaderMock> GetWeakPtr();
-
private:
- base::WeakPtrFactory<CodeCacheLoaderMock> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(CodeCacheLoaderMock);
+ scoped_refptr<Controller> controller_;
};
} // 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 5d07c0e5a65..e6eb1e72591 100644
--- a/chromium/third_party/blink/renderer/platform/testing/compositor_test.h
+++ b/chromium/third_party/blink/renderer/platform/testing/compositor_test.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_COMPOSITOR_TEST_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_COMPOSITOR_TEST_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -16,6 +15,8 @@ namespace blink {
class CompositorTest : public testing::Test {
public:
CompositorTest();
+ CompositorTest(const CompositorTest&) = delete;
+ CompositorTest& operator=(const CompositorTest&) = delete;
~CompositorTest() override;
protected:
@@ -23,9 +24,6 @@ class CompositorTest : public testing::Test {
// and bind it as the current ThreadTaskRunnerHandle for this thread.
scoped_refptr<base::TestMockTimeTaskRunner> runner_;
base::ThreadTaskRunnerHandle runner_handle_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompositorTest);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/fuzzed_data_provider.h b/chromium/third_party/blink/renderer/platform/testing/fuzzed_data_provider.h
index 1a28925c4bb..3629df14a9b 100644
--- a/chromium/third_party/blink/renderer/platform/testing/fuzzed_data_provider.h
+++ b/chromium/third_party/blink/renderer/platform/testing/fuzzed_data_provider.h
@@ -7,7 +7,6 @@
#include <fuzzer/FuzzedDataProvider.h>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -19,6 +18,8 @@ class FuzzedDataProvider {
public:
FuzzedDataProvider(const uint8_t* bytes, size_t num_bytes);
+ FuzzedDataProvider(const FuzzedDataProvider&) = delete;
+ FuzzedDataProvider& operator=(const FuzzedDataProvider&) = delete;
// Returns a string with length between 0 and max_length.
String ConsumeRandomLengthString(size_t max_length);
@@ -58,8 +59,6 @@ class FuzzedDataProvider {
private:
::FuzzedDataProvider provider_;
-
- DISALLOW_COPY_AND_ASSIGN(FuzzedDataProvider);
};
} // 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 b3426cd9215..f20aa2d282c 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
@@ -28,11 +28,11 @@ namespace {
scoped_refptr<SharedBuffer> ReadFile(const char* name) {
std::string file;
- if (base::ReadFileToString(base::FilePath::FromUTF8Unsafe(name), &file))
- return SharedBuffer::Create(file.data(), file.size());
- perror(name);
- exit(2);
- return SharedBuffer::Create();
+ if (!base::ReadFileToString(base::FilePath::FromUTF8Unsafe(name), &file)) {
+ perror(name);
+ exit(2);
+ }
+ return SharedBuffer::Create(file.data(), file.size());
}
struct ImageMeta {
diff --git a/chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.cc b/chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.cc
new file mode 100644
index 00000000000..a744186fff2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.cc
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/testing/noop_web_url_loader.h"
+
+#include "services/network/public/cpp/resource_request.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/web_url_request_extra_data.h"
+
+namespace blink {
+
+void NoopWebURLLoader::LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient*,
+ WebURLResponse&,
+ absl::optional<WebURLError>&,
+ WebData&,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ WebBlobInfo& downloaded_blob,
+ std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper) {
+ NOTREACHED();
+}
+
+void NoopWebURLLoader::LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ bool no_mime_sniffing,
+ std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebURLLoaderClient*) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.h b/chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.h
new file mode 100644
index 00000000000..7283c5e60e3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/noop_web_url_loader.h
@@ -0,0 +1,56 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_NOOP_WEB_URL_LOADER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_NOOP_WEB_URL_LOADER_H_
+
+#include "third_party/blink/public/platform/web_url_loader.h"
+
+namespace blink {
+
+class NoopWebURLLoader final : public WebURLLoader {
+ public:
+ explicit NoopWebURLLoader(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : task_runner_(task_runner) {}
+ ~NoopWebURLLoader() override = default;
+ void LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient*,
+ WebURLResponse&,
+ absl::optional<WebURLError>&,
+ WebData&,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ WebBlobInfo& downloaded_blob,
+ std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper) override;
+ void LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ bool no_mime_sniffing,
+ std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebURLLoaderClient*) override;
+
+ void Freeze(WebLoaderFreezeMode) override {}
+ void DidChangePriority(WebURLRequest::Priority, int) override {
+ NOTREACHED();
+ }
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
+ override {
+ return task_runner_;
+ }
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_NOOP_WEB_URL_LOADER_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 90397bd97a1..7ad3c6fcfee 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
@@ -69,7 +69,8 @@ TestPaintArtifact& TestPaintArtifact::ForeignLayer(
DEFINE_STATIC_LOCAL(LiteralDebugNameClient, client, ("ForeignLayer"));
paint_artifact_->GetDisplayItemList()
.AllocateAndConstruct<ForeignLayerDisplayItem>(
- client, DisplayItem::kForeignLayerFirst, std::move(layer), offset);
+ client, DisplayItem::kForeignLayerFirst, std::move(layer), offset,
+ client.GetPaintInvalidationReason());
DidAddDisplayItem();
return *this;
}
@@ -87,7 +88,8 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client,
paint_artifact_->GetDisplayItemList()
.AllocateAndConstruct<DrawingDisplayItem>(
client, DisplayItem::kDrawingFirst, bounds,
- recorder.finishRecordingAsPicture());
+ recorder.finishRecordingAsPicture(),
+ client.GetPaintInvalidationReason());
DidAddDisplayItem();
return *this;
}
@@ -109,8 +111,30 @@ TestPaintArtifact& TestPaintArtifact::SetRasterEffectOutset(
return *this;
}
-TestPaintArtifact& TestPaintArtifact::KnownToBeOpaque() {
- paint_artifact_->PaintChunks().back().known_to_be_opaque = true;
+TestPaintArtifact& TestPaintArtifact::RectKnownToBeOpaque(const IntRect& r) {
+ auto& chunk = paint_artifact_->PaintChunks().back();
+ chunk.rect_known_to_be_opaque = r;
+ DCHECK(chunk.bounds.Contains(r));
+ return *this;
+}
+
+TestPaintArtifact& TestPaintArtifact::TextKnownToBeOnOpaqueBackground() {
+ auto& chunk = paint_artifact_->PaintChunks().back();
+ DCHECK(chunk.has_text);
+ paint_artifact_->PaintChunks().back().text_known_to_be_on_opaque_background =
+ true;
+ return *this;
+}
+
+TestPaintArtifact& TestPaintArtifact::HasText() {
+ auto& chunk = paint_artifact_->PaintChunks().back();
+ chunk.has_text = true;
+ chunk.text_known_to_be_on_opaque_background = false;
+ return *this;
+}
+
+TestPaintArtifact& TestPaintArtifact::EffectivelyInvisible() {
+ paint_artifact_->PaintChunks().back().effectively_invisible = true;
return *this;
}
@@ -134,6 +158,11 @@ TestPaintArtifact& TestPaintArtifact::Uncacheable() {
return *this;
}
+TestPaintArtifact& TestPaintArtifact::IsMovedFromCachedSubsequence() {
+ paint_artifact_->PaintChunks().back().is_moved_from_cached_subsequence = true;
+ return *this;
+}
+
scoped_refptr<PaintArtifact> TestPaintArtifact::Build() {
return std::move(paint_artifact_);
}
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 4c9044ca2fc..d11d6514769 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
@@ -117,8 +117,12 @@ class TestPaintArtifact {
TestPaintArtifact& DrawableBounds(const IntRect&);
TestPaintArtifact& SetRasterEffectOutset(RasterEffectOutset);
- TestPaintArtifact& KnownToBeOpaque();
+ TestPaintArtifact& RectKnownToBeOpaque(const IntRect&);
+ TestPaintArtifact& TextKnownToBeOnOpaqueBackground();
+ TestPaintArtifact& HasText();
+ TestPaintArtifact& EffectivelyInvisible();
TestPaintArtifact& Uncacheable();
+ TestPaintArtifact& IsMovedFromCachedSubsequence();
// Build the paint artifact. After that, if this object has automatically
// created any display item client, the caller must retain this object when
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 12ed1318c4a..0b6ebef8352 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
@@ -109,8 +109,9 @@ WebString TestingPlatformSupport::DefaultLocale() {
return WebString::FromUTF8("en-US");
}
-WebData TestingPlatformSupport::GetDataResource(int resource_id,
- ui::ScaleFactor scale_factor) {
+WebData TestingPlatformSupport::GetDataResource(
+ int resource_id,
+ ui::ResourceScaleFactor scale_factor) {
return old_platform_
? old_platform_->GetDataResource(resource_id, scale_factor)
: WebData();
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 debac8d0477..cf6ed4f932b 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
@@ -36,7 +36,6 @@
#include "base/auto_reset.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -56,16 +55,15 @@ namespace blink {
class TestingPlatformSupport : public Platform {
public:
TestingPlatformSupport();
+ TestingPlatformSupport(const TestingPlatformSupport&) = delete;
+ TestingPlatformSupport& operator=(const TestingPlatformSupport&) = delete;
~TestingPlatformSupport() override;
// Platform:
WebString DefaultLocale() override;
- std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
- return std::make_unique<CodeCacheLoaderMock>();
- }
WebData GetDataResource(int resource_id,
- ui::ScaleFactor scale_factor) override;
+ ui::ResourceScaleFactor scale_factor) override;
WebData UncompressDataResource(int resource_id) override;
ThreadSafeBrowserInterfaceBrokerProxy* GetBrowserInterfaceBroker() override;
bool IsThreadedAnimationEnabled() override;
@@ -74,7 +72,7 @@ class TestingPlatformSupport : public Platform {
virtual void RunUntilIdle();
void SetThreadedAnimationEnabled(bool enabled);
- void SetUseZoomForDSF(bool enabeld);
+ void SetUseZoomForDSF(bool enabled);
// Overrides the handling of GetInterface on the platform's associated
// interface provider.
@@ -98,9 +96,7 @@ class TestingPlatformSupport : public Platform {
private:
bool is_threaded_animation_enabled_ = false;
- bool is_zoom_for_dsf_enabled_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(TestingPlatformSupport);
+ bool is_zoom_for_dsf_enabled_ = true;
};
// ScopedTestingPlatformSupport<MyTestingPlatformSupport> can be used to
@@ -128,8 +124,6 @@ class TestingPlatformSupport : public Platform {
// }
template <class T, typename... Args>
class ScopedTestingPlatformSupport final {
- DISALLOW_COPY_AND_ASSIGN(ScopedTestingPlatformSupport);
-
public:
explicit ScopedTestingPlatformSupport(Args&&... args) {
testing_platform_support_ =
@@ -138,6 +132,9 @@ class ScopedTestingPlatformSupport final {
DCHECK(original_platform_);
Platform::SetCurrentPlatformForTesting(testing_platform_support_.get());
}
+ ScopedTestingPlatformSupport(const ScopedTestingPlatformSupport&) = delete;
+ ScopedTestingPlatformSupport& operator=(const ScopedTestingPlatformSupport&) =
+ delete;
~ScopedTestingPlatformSupport() {
DCHECK_EQ(testing_platform_support_.get(), Platform::Current());
testing_platform_support_.reset();
@@ -158,10 +155,12 @@ class ScopedTestingPlatformSupport final {
};
class ScopedUnittestsEnvironmentSetup final {
- DISALLOW_COPY_AND_ASSIGN(ScopedUnittestsEnvironmentSetup);
-
public:
ScopedUnittestsEnvironmentSetup(int argc, char** argv);
+ ScopedUnittestsEnvironmentSetup(const ScopedUnittestsEnvironmentSetup&) =
+ delete;
+ ScopedUnittestsEnvironmentSetup& operator=(
+ const ScopedUnittestsEnvironmentSetup&) = delete;
~ScopedUnittestsEnvironmentSetup();
private:
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 6aa650b9560..0e513ee8d78 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
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/test/test_mock_time_task_runner.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h"
@@ -34,6 +33,10 @@ class MainThreadSchedulerImpl;
class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport {
public:
TestingPlatformSupportWithMockScheduler();
+ TestingPlatformSupportWithMockScheduler(
+ const TestingPlatformSupportWithMockScheduler&) = delete;
+ TestingPlatformSupportWithMockScheduler& operator=(
+ const TestingPlatformSupportWithMockScheduler&) = delete;
~TestingPlatformSupportWithMockScheduler() override;
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner() {
@@ -79,9 +82,6 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport {
base::sequence_manager::SequenceManager*
sequence_manager_; // Owned by scheduler_.
std::unique_ptr<ScopedMainThreadOverrider> main_thread_overrider_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestingPlatformSupportWithMockScheduler);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h
index 6ed243a25b7..bf166a0b550 100644
--- a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h
@@ -95,7 +95,7 @@ class LineReader {
private:
String text_;
- size_t index_;
+ wtf_size_t index_;
};
} // namespace test
diff --git a/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc b/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc
index 15da0476d4b..8f1bf358540 100644
--- a/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc
@@ -64,7 +64,8 @@ WebURL RegisterMockedURLLoadFromBase(const WebString& base_url,
void RegisterMockedURLLoad(const WebURL& full_url,
const WebString& file_path,
const WebString& mime_type,
- WebURLLoaderMockFactory* mock_factory) {
+ WebURLLoaderMockFactory* mock_factory,
+ network::mojom::IPAddressSpace address_space) {
network::mojom::LoadTimingInfoPtr timing =
network::mojom::LoadTimingInfo::New();
@@ -73,6 +74,7 @@ void RegisterMockedURLLoad(const WebURL& full_url,
response.SetHttpHeaderField(http_names::kContentType, mime_type);
response.SetHttpStatusCode(200);
response.SetLoadTiming(*timing);
+ response.SetAddressSpace(address_space);
mock_factory->RegisterURL(full_url, response, file_path);
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.h b/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.h
index 12c6f6c2f54..e6e1cea1523 100644
--- a/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_URL_TEST_HELPERS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_URL_TEST_HELPERS_H_
+#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -74,7 +75,9 @@ void RegisterMockedURLLoad(
const WebString& file_path,
const WebString& mime_type = WebString::FromUTF8("text/html"),
WebURLLoaderMockFactory* mock_factory =
- WebURLLoaderMockFactory::GetSingletonInstance());
+ WebURLLoaderMockFactory::GetSingletonInstance(),
+ network::mojom::IPAddressSpace address_space =
+ network::mojom::IPAddressSpace::kPublic);
// Unregisters a URL that has been registered, so that the same URL can be
// registered again from the another test.
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 3624ea4f6b8..ac44a4b0412 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
@@ -60,7 +60,8 @@ void WebURLLoaderMock::ServeAsynchronousRequest(
data.ForEachSegment([this, &delegate, &self](const char* segment,
size_t segment_size,
size_t segment_offset) {
- delegate->DidReceiveData(client_, segment, segment_size);
+ delegate->DidReceiveData(client_, segment,
+ base::checked_cast<int>(segment_size));
// DidReceiveData() may clear the |self| weak ptr. We stop iterating
// when that happens.
return self;
@@ -133,8 +134,8 @@ void WebURLLoaderMock::Cancel() {
factory_->CancelLoad(this);
}
-void WebURLLoaderMock::SetDefersLoading(DeferType deferred) {
- is_deferred_ = (deferred != DeferType::kNotDeferred);
+void WebURLLoaderMock::Freeze(WebLoaderFreezeMode mode) {
+ is_deferred_ = (mode != WebLoaderFreezeMode::kNone);
// Ignores setDefersLoading(false) safely.
if (!is_deferred_)
return;
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 8cb21ae9c09..5613710ab9a 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
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_WEBURL_LOADER_MOCK_H_
#include <memory>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_url_error.h"
@@ -31,6 +30,8 @@ const uint32_t kRedirectResponseOverheadBytes = 300;
class WebURLLoaderMock : public WebURLLoader {
public:
explicit WebURLLoaderMock(WebURLLoaderMockFactoryImpl* factory);
+ WebURLLoaderMock(const WebURLLoaderMock&) = delete;
+ WebURLLoaderMock& operator=(const WebURLLoaderMock&) = delete;
~WebURLLoaderMock() override;
// Simulates the asynchronous request being served.
@@ -66,7 +67,7 @@ class WebURLLoaderMock : public WebURLLoader {
std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
resource_load_info_notifier_wrapper,
WebURLLoaderClient* client) override;
- void SetDefersLoading(DeferType defer) override;
+ void Freeze(WebLoaderFreezeMode mode) override;
void DidChangePriority(WebURLRequest::Priority new_priority,
int intra_priority_value) override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
@@ -85,8 +86,6 @@ class WebURLLoaderMock : public WebURLLoader {
bool is_deferred_ = false;
base::WeakPtrFactory<WebURLLoaderMock> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WebURLLoaderMock);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
index cd79a8d3856..2ca34773005 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
@@ -12,6 +12,7 @@
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "services/network/public/cpp/resource_request.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
index 57f855118d1..a0a395567e2 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_WEBURL_LOADER_MOCK_FACTORY_IMPL_H_
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -36,6 +35,9 @@ class WebURLLoaderTestDelegate;
class WebURLLoaderMockFactoryImpl : public WebURLLoaderMockFactory {
public:
WebURLLoaderMockFactoryImpl(TestingPlatformSupport*);
+ WebURLLoaderMockFactoryImpl(const WebURLLoaderMockFactoryImpl&) = delete;
+ WebURLLoaderMockFactoryImpl& operator=(const WebURLLoaderMockFactoryImpl&) =
+ delete;
~WebURLLoaderMockFactoryImpl() override;
// WebURLLoaderMockFactory:
@@ -124,8 +126,6 @@ class WebURLLoaderMockFactoryImpl : public WebURLLoaderMockFactory {
ProtocolToResponseMap protocol_to_response_info_;
TestingPlatformSupport* platform_;
-
- DISALLOW_COPY_AND_ASSIGN(WebURLLoaderMockFactoryImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/bidi_resolver.h b/chromium/third_party/blink/renderer/platform/text/bidi_resolver.h
index 557dde19181..cf62f25ea5b 100644
--- a/chromium/third_party/blink/renderer/platform/text/bidi_resolver.h
+++ b/chromium/third_party/blink/renderer/platform/text/bidi_resolver.h
@@ -223,6 +223,8 @@ class BidiResolver final {
empty_run_(true),
trailing_space_run_(nullptr),
needs_trailing_space_(false) {}
+ BidiResolver(const BidiResolver&) = delete;
+ BidiResolver& operator=(const BidiResolver&) = delete;
#if DCHECK_IS_ON()
~BidiResolver();
@@ -380,8 +382,6 @@ class BidiResolver final {
Vector<BidiEmbedding, 8> current_explicit_embedding_sequence_;
HashMap<Run*, MidpointState<Iterator>> midpoint_state_for_isolated_run_;
-
- DISALLOW_COPY_AND_ASSIGN(BidiResolver);
};
#if DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/platform/text/bidi_resolver_test.cc b/chromium/third_party/blink/renderer/platform/text/bidi_resolver_test.cc
index 09900413b9c..6958c8b9c57 100644
--- a/chromium/third_party/blink/renderer/platform/text/bidi_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/bidi_resolver_test.cc
@@ -32,8 +32,8 @@
#include <fstream>
+#include "base/cxx17_backports.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/text/bidi_test_harness.h"
#include "third_party/blink/renderer/platform/text/text_run_iterator.h"
diff --git a/chromium/third_party/blink/renderer/platform/text/bidi_run_list.h b/chromium/third_party/blink/renderer/platform/text/bidi_run_list.h
index 27aa5db7b89..698068c316f 100644
--- a/chromium/third_party/blink/renderer/platform/text/bidi_run_list.h
+++ b/chromium/third_party/blink/renderer/platform/text/bidi_run_list.h
@@ -37,6 +37,8 @@ class BidiRunList final {
last_run_(nullptr),
logically_last_run_(nullptr),
run_count_(0) {}
+ BidiRunList(const BidiRunList&) = delete;
+ BidiRunList& operator=(const BidiRunList&) = delete;
// FIXME: Once BidiResolver no longer owns the BidiRunList,
// then ~BidiRunList should call deleteRuns() automatically.
@@ -67,8 +69,6 @@ class BidiRunList final {
Run* last_run_;
Run* logically_last_run_;
unsigned run_count_;
-
- DISALLOW_COPY_AND_ASSIGN(BidiRunList);
};
template <class Run>
diff --git a/chromium/third_party/blink/renderer/platform/text/capitalize.cc b/chromium/third_party/blink/renderer/platform/text/capitalize.cc
index a30f811e7e6..d04d9e784c8 100644
--- a/chromium/third_party/blink/renderer/platform/text/capitalize.cc
+++ b/chromium/third_party/blink/renderer/platform/text/capitalize.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/platform/text/text_break_iterator.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/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/text/character.cc b/chromium/third_party/blink/renderer/platform/text/character.cc
index 81ae1c9eec4..a9ce549c485 100644
--- a/chromium/third_party/blink/renderer/platform/text/character.cc
+++ b/chromium/third_party/blink/renderer/platform/text/character.cc
@@ -36,12 +36,12 @@
#include <unicode/uscript.h>
#include <algorithm>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/text/character_property_data.h"
#include "third_party/blink/renderer/platform/text/icu_error.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_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 {
@@ -91,12 +91,12 @@ unsigned Character::ExpansionOpportunityCount(
const TextJustify text_justify) {
if (text_justify == TextJustify::kDistribute) {
is_after_expansion = true;
- return characters.size();
+ return base::checked_cast<unsigned>(characters.size());
}
unsigned count = 0;
if (direction == TextDirection::kLtr) {
- for (unsigned i = 0; i < characters.size(); ++i) {
+ for (size_t i = 0; i < characters.size(); ++i) {
if (TreatAsSpace(characters[i])) {
count++;
is_after_expansion = true;
@@ -105,7 +105,7 @@ unsigned Character::ExpansionOpportunityCount(
}
}
} else {
- for (unsigned i = characters.size(); i > 0; --i) {
+ for (size_t i = characters.size(); i > 0; --i) {
if (TreatAsSpace(characters[i - 1])) {
count++;
is_after_expansion = true;
@@ -125,7 +125,7 @@ unsigned Character::ExpansionOpportunityCount(
const TextJustify text_justify) {
unsigned count = 0;
if (direction == TextDirection::kLtr) {
- for (unsigned i = 0; i < characters.size(); ++i) {
+ for (size_t i = 0; i < characters.size(); ++i) {
UChar32 character = characters[i];
if (TreatAsSpace(character)) {
count++;
@@ -148,7 +148,7 @@ unsigned Character::ExpansionOpportunityCount(
is_after_expansion = false;
}
} else {
- for (unsigned i = characters.size(); i > 0; --i) {
+ for (size_t i = characters.size(); i > 0; --i) {
UChar32 character = characters[i - 1];
if (TreatAsSpace(character)) {
count++;
@@ -276,7 +276,7 @@ bool Character::HasDefiniteScript(UChar32 character) {
hint_char_script != USCRIPT_COMMON;
}
-// https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis
+// https://w3c.github.io/mathml-core/#stretchy-operator-axis
static const UChar stretchy_operator_with_inline_axis[]{
0x003D, 0x005E, 0x005F, 0x007E, 0x00AF, 0x02C6, 0x02C7, 0x02C9, 0x02CD,
0x02DC, 0x02F7, 0x0302, 0x0332, 0x203E, 0x20D0, 0x20D1, 0x20D6, 0x20D7,
diff --git a/chromium/third_party/blink/renderer/platform/text/character.h b/chromium/third_party/blink/renderer/platform/text/character.h
index 329726be928..89b40cde542 100644
--- a/chromium/third_party/blink/renderer/platform/text/character.h
+++ b/chromium/third_party/blink/renderer/platform/text/character.h
@@ -31,6 +31,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_CHARACTER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_CHARACTER_H_
+#include <unicode/uchar.h>
+
#include "base/containers/span.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/character_property.h"
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 d3041b07b3f..cb8e8cf385a 100644
--- a/chromium/third_party/blink/renderer/platform/text/character_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/character_test.cc
@@ -412,7 +412,7 @@ TEST(CharacterTest, TransformedIsUprightInMixedVertical) {
}
TEST(CharacterTest, IsVerticalMathCharacter) {
- // https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis
+ // https://w3c.github.io/mathml-core/#stretchy-operator-axis
const UChar stretchy_operator_with_inline_axis[]{
0x003D, 0x005E, 0x005F, 0x007E, 0x00AF, 0x02C6, 0x02C7, 0x02C9, 0x02CD,
0x02DC, 0x02F7, 0x0302, 0x0332, 0x203E, 0x20D0, 0x20D1, 0x20D6, 0x20D7,
diff --git a/chromium/third_party/blink/renderer/platform/text/date_components.h b/chromium/third_party/blink/renderer/platform/text/date_components.h
index cbd05d3d58e..eded5600772 100644
--- a/chromium/third_party/blink/renderer/platform/text/date_components.h
+++ b/chromium/third_party/blink/renderer/platform/text/date_components.h
@@ -35,7 +35,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/text/date_time_format.h b/chromium/third_party/blink/renderer/platform/text/date_time_format.h
index bfff230af2e..eed7465f87b 100644
--- a/chromium/third_party/blink/renderer/platform/text/date_time_format.h
+++ b/chromium/third_party/blink/renderer/platform/text/date_time_format.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_DATE_TIME_FORMAT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_DATE_TIME_FORMAT_H_
-#include "base/macros.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/allocator.h"
@@ -104,11 +103,11 @@ class PLATFORM_EXPORT DateTimeFormat {
public:
TokenHandler() = default;
+ TokenHandler(const TokenHandler&) = delete;
+ TokenHandler& operator=(const TokenHandler&) = delete;
virtual ~TokenHandler() = default;
virtual void VisitField(FieldType, int number_of_pattern_characters) = 0;
virtual void VisitLiteral(const String&) = 0;
-
- DISALLOW_COPY_AND_ASSIGN(TokenHandler);
};
// Returns true if succeeded, false if failed.
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation.h b/chromium/third_party/blink/renderer/platform/text/hyphenation.h
index aa0f81114eb..0d9e78af8f1 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation.h
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
namespace blink {
@@ -35,6 +36,16 @@ class PLATFORM_EXPORT Hyphenation : public RefCounted<Hyphenation> {
static const unsigned kMinimumPrefixLength = 2;
static const unsigned kMinimumSuffixLength = 2;
+ protected:
+ bool ShouldHyphenateWord(const StringView& word) const {
+ if (word.IsEmpty())
+ return false;
+ // Avoid hyphenating capitalized words.
+ return hyphenate_capitalized_word_ || !WTF::unicode::IsUpper(word[0]);
+ }
+
+ bool hyphenate_capitalized_word_ = false;
+
private:
friend class LayoutLocale;
static scoped_refptr<Hyphenation> PlatformGetHyphenation(
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 9684f1482f1..ed67490b944 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
@@ -20,6 +20,7 @@
#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"
+#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
namespace blink {
@@ -92,9 +93,9 @@ StringView HyphenationMinikin::WordToHyphenate(
++begin;
while (begin != end && ShouldSkipTrailingChar(end[-1]))
--end;
- *num_leading_chars_out = begin - text.Characters8();
+ *num_leading_chars_out = static_cast<unsigned>(begin - text.Characters8());
CHECK_GE(end, begin);
- return StringView(begin, end - begin);
+ return StringView(begin, static_cast<unsigned>(end - begin));
}
const UChar* begin = text.Characters16();
int index = 0;
@@ -121,6 +122,7 @@ StringView HyphenationMinikin::WordToHyphenate(
}
Vector<uint8_t> HyphenationMinikin::Hyphenate(const StringView& text) const {
+ DCHECK(ShouldHyphenateWord(text));
Vector<uint8_t> result;
if (text.Is8Bit()) {
String text16_bit = text.ToString();
@@ -141,7 +143,7 @@ wtf_size_t HyphenationMinikin::LastHyphenLocation(
wtf_size_t before_index) const {
unsigned num_leading_chars;
StringView word = WordToHyphenate(text, &num_leading_chars);
- if (before_index <= num_leading_chars)
+ if (before_index <= num_leading_chars || !ShouldHyphenateWord(word))
return 0;
before_index = std::min<wtf_size_t>(before_index - num_leading_chars,
word.length() - kMinimumSuffixLength);
@@ -167,7 +169,8 @@ Vector<wtf_size_t, 8> HyphenationMinikin::HyphenLocations(
StringView word = WordToHyphenate(text, &num_leading_chars);
Vector<wtf_size_t, 8> hyphen_locations;
- if (word.length() < kMinimumPrefixLength + kMinimumSuffixLength)
+ if (word.length() < kMinimumPrefixLength + kMinimumSuffixLength ||
+ !ShouldHyphenateWord(word))
return hyphen_locations;
Vector<uint8_t> result = Hyphenate(word);
@@ -181,71 +184,81 @@ Vector<wtf_size_t, 8> HyphenationMinikin::HyphenLocations(
return hyphen_locations;
}
-using LocaleMap = HashMap<AtomicString, AtomicString, CaseFoldingHash>;
+struct HyphenatorLocaleData {
+ const char* locale = nullptr;
+ const char* locale_for_exact_match = nullptr;
+};
+
+using LocaleMap =
+ HashMap<AtomicString, const HyphenatorLocaleData*, CaseFoldingHash>;
static LocaleMap CreateLocaleFallbackMap() {
// This data is from CLDR, compiled by AOSP.
// https://android.googlesource.com/platform/frameworks/base/+/master/core/jni/android_text_Hyphenator.cpp
- using LocaleFallback = const char * [2];
+ struct LocaleFallback {
+ const char* locale;
+ HyphenatorLocaleData data;
+ };
static LocaleFallback locale_fallback_data[] = {
// English locales that fall back to en-US. The data is from CLDR. It's
// all English locales,
// minus the locales whose parent is en-001 (from supplementalData.xml,
// under <parentLocales>).
- {"en-AS", "en-us"}, // English (American Samoa)
- {"en-GU", "en-us"}, // English (Guam)
- {"en-MH", "en-us"}, // English (Marshall Islands)
- {"en-MP", "en-us"}, // English (Northern Mariana Islands)
- {"en-PR", "en-us"}, // English (Puerto Rico)
- {"en-UM", "en-us"}, // English (United States Minor Outlying Islands)
- {"en-VI", "en-us"}, // English (Virgin Islands)
+ {"en-AS", {"en-us"}}, // English (American Samoa)
+ {"en-GU", {"en-us"}}, // English (Guam)
+ {"en-MH", {"en-us"}}, // English (Marshall Islands)
+ {"en-MP", {"en-us"}}, // English (Northern Mariana Islands)
+ {"en-PR", {"en-us"}}, // English (Puerto Rico)
+ {"en-UM", {"en-us"}}, // English (United States Minor Outlying Islands)
+ {"en-VI", {"en-us"}}, // English (Virgin Islands)
// All English locales other than those falling back to en-US are mapped
- // to en-GB.
- {"en", "en-gb"},
+ // to en-GB, except that "en" is mapped to "en-us" for interoperability
+ // with other browsers.
+ {"en", {"en-gb", "en-us"}},
// For German, we're assuming the 1996 (and later) orthography by default.
- {"de", "de-1996"},
+ {"de", {"de-1996"}},
// Liechtenstein uses the Swiss hyphenation rules for the 1901
// orthography.
- {"de-LI-1901", "de-ch-1901"},
+ {"de-LI-1901", {"de-ch-1901"}},
// Norwegian is very probably Norwegian Bokmål.
- {"no", "nb"},
+ {"no", {"nb"}},
// Use mn-Cyrl. According to CLDR's likelySubtags.xml, mn is most likely
// to be mn-Cyrl.
- {"mn", "mn-cyrl"}, // Mongolian
+ {"mn", {"mn-cyrl"}}, // Mongolian
// Fall back to Ethiopic script for languages likely to be written in
// Ethiopic.
// Data is from CLDR's likelySubtags.xml.
- {"am", "und-ethi"}, // Amharic
- {"byn", "und-ethi"}, // Blin
- {"gez", "und-ethi"}, // Geʻez
- {"ti", "und-ethi"}, // Tigrinya
- {"wal", "und-ethi"}, // Wolaytta
+ {"am", {"und-ethi"}}, // Amharic
+ {"byn", {"und-ethi"}}, // Blin
+ {"gez", {"und-ethi"}}, // Geʻez
+ {"ti", {"und-ethi"}}, // Tigrinya
+ {"wal", {"und-ethi"}}, // Wolaytta
// Use Hindi as a fallback hyphenator for all languages written in
// Devanagari, etc. This makes
// sense because our Indic patterns are not really linguistic, but
// script-based.
- {"und-Beng", "bn"}, // Bengali
- {"und-Deva", "hi"}, // Devanagari -> Hindi
- {"und-Gujr", "gu"}, // Gujarati
- {"und-Guru", "pa"}, // Gurmukhi -> Punjabi
- {"und-Knda", "kn"}, // Kannada
- {"und-Mlym", "ml"}, // Malayalam
- {"und-Orya", "or"}, // Oriya
- {"und-Taml", "ta"}, // Tamil
- {"und-Telu", "te"}, // Telugu
+ {"und-Beng", {"bn"}}, // Bengali
+ {"und-Deva", {"hi"}}, // Devanagari -> Hindi
+ {"und-Gujr", {"gu"}}, // Gujarati
+ {"und-Guru", {"pa"}}, // Gurmukhi -> Punjabi
+ {"und-Knda", {"kn"}}, // Kannada
+ {"und-Mlym", {"ml"}}, // Malayalam
+ {"und-Orya", {"or"}}, // Oriya
+ {"und-Taml", {"ta"}}, // Tamil
+ {"und-Telu", {"te"}}, // Telugu
// List of locales with hyphens not to fall back.
- {"de-1901", nullptr},
- {"de-1996", nullptr},
- {"de-ch-1901", nullptr},
- {"en-gb", nullptr},
- {"en-us", nullptr},
- {"mn-cyrl", nullptr},
- {"und-ethi", nullptr},
+ {"de-1901", {"de-1901"}},
+ {"de-1996", {"de-1996"}},
+ {"de-ch-1901", {"de-ch-1901"}},
+ {"en-gb", {"en-gb"}},
+ {"en-us", {"en-us"}},
+ {"mn-cyrl", {"mn-cyrl"}},
+ {"und-ethi", {"und-ethi"}},
};
LocaleMap map;
for (const auto& it : locale_fallback_data)
- map.insert(AtomicString(it[0]), it[1]);
+ map.insert(AtomicString(it.locale), &it.data);
return map;
}
@@ -255,9 +268,9 @@ AtomicString HyphenationMinikin::MapLocale(const AtomicString& locale) {
for (AtomicString mapped_locale = locale;;) {
const auto& it = locale_fallback.find(mapped_locale);
if (it != locale_fallback.end()) {
- if (it->value)
- return it->value;
- return mapped_locale;
+ if (it->value->locale_for_exact_match && locale == mapped_locale)
+ return it->value->locale_for_exact_match;
+ return it->value->locale;
}
const wtf_size_t last_hyphen = mapped_locale.ReverseFind('-');
if (last_hyphen == kNotFound || !last_hyphen)
@@ -269,24 +282,29 @@ AtomicString HyphenationMinikin::MapLocale(const AtomicString& locale) {
scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
const AtomicString& locale) {
const AtomicString mapped_locale = HyphenationMinikin::MapLocale(locale);
- if (mapped_locale.Impl() != locale.Impl())
+ if (!EqualIgnoringASCIICase(mapped_locale, locale))
return LayoutLocale::Get(mapped_locale)->GetHyphenation();
scoped_refptr<HyphenationMinikin> hyphenation(
base::AdoptRef(new HyphenationMinikin));
- if (hyphenation->OpenDictionary(locale.LowerASCII()))
- return hyphenation;
-
- return nullptr;
+ const AtomicString lower_ascii_locale = locale.LowerASCII();
+ if (!hyphenation->OpenDictionary(lower_ascii_locale))
+ return nullptr;
+ if (lower_ascii_locale.StartsWith("de"))
+ hyphenation->hyphenate_capitalized_word_ = true;
+ return hyphenation;
}
scoped_refptr<HyphenationMinikin> HyphenationMinikin::FromFileForTesting(
+ const AtomicString& locale,
base::File file) {
scoped_refptr<HyphenationMinikin> hyphenation(
base::AdoptRef(new HyphenationMinikin));
- if (hyphenation->OpenDictionary(std::move(file)))
- return hyphenation;
- return nullptr;
+ if (!hyphenation->OpenDictionary(std::move(file)))
+ return nullptr;
+ if (locale.StartsWithIgnoringASCIICase("de"))
+ hyphenation->hyphenate_capitalized_word_ = true;
+ return hyphenation;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.h b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.h
index 4f7bfcfe3b3..dbacd4f1f8c 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.h
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.h
@@ -35,7 +35,9 @@ class PLATFORM_EXPORT HyphenationMinikin final : public Hyphenation {
static AtomicString MapLocale(const AtomicString& locale);
- static scoped_refptr<HyphenationMinikin> FromFileForTesting(base::File);
+ static scoped_refptr<HyphenationMinikin> FromFileForTesting(
+ const AtomicString& locale,
+ base::File);
private:
bool OpenDictionary(base::File);
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.cc b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.cc
index d88444b0b82..e7430a2872c 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.cc
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.cc
@@ -111,10 +111,10 @@ Hyphenator* Hyphenator::loadBinary(const uint8_t* patternData) {
void Hyphenator::hyphenate(Vector<uint8_t>* result,
const uint16_t* word,
- size_t len) {
+ wtf_size_t len) {
result->clear();
result->resize(len);
- const size_t paddedLen = len + 2; // start and stop code each count for 1
+ const wtf_size_t paddedLen = len + 2; // start and stop code each count for 1
if (patternData != nullptr && (int)len >= MIN_PREFIX + MIN_SUFFIX &&
paddedLen <= MAX_HYPHENATED_SIZE) {
uint16_t alpha_codes[MAX_HYPHENATED_SIZE];
@@ -132,16 +132,16 @@ void Hyphenator::hyphenate(Vector<uint8_t>* result,
// hyphenation, as recommended in UAX #14 (Use of Soft Hyphen)
void Hyphenator::hyphenateSoft(uint8_t* result,
const uint16_t* word,
- size_t len) {
+ wtf_size_t len) {
result[0] = 0;
- for (size_t i = 1; i < len; i++) {
+ for (wtf_size_t i = 1; i < len; i++) {
result[i] = word[i - 1] == CHAR_SOFT_HYPHEN;
}
}
bool Hyphenator::alphabetLookup(uint16_t* alpha_codes,
const uint16_t* word,
- size_t len) {
+ wtf_size_t len) {
const Header* header = getHeader();
// TODO: check header magic
uint32_t alphabetVersion = header->alphabetVersion();
@@ -150,7 +150,7 @@ bool Hyphenator::alphabetLookup(uint16_t* alpha_codes,
uint32_t min_codepoint = alphabet->min_codepoint;
uint32_t max_codepoint = alphabet->max_codepoint;
alpha_codes[0] = 0; // word start
- for (size_t i = 0; i < len; i++) {
+ for (wtf_size_t i = 0; i < len; i++) {
uint16_t c = word[i];
if (c < min_codepoint || c >= max_codepoint) {
return false;
@@ -169,7 +169,7 @@ bool Hyphenator::alphabetLookup(uint16_t* alpha_codes,
const uint32_t* begin = alphabet->data;
const uint32_t* end = begin + n_entries;
alpha_codes[0] = 0;
- for (size_t i = 0; i < len; i++) {
+ for (wtf_size_t i = 0; i < len; i++) {
uint16_t c = word[i];
auto* p = std::lower_bound(begin, end, c << 11);
if (p == end) {
@@ -195,7 +195,7 @@ bool Hyphenator::alphabetLookup(uint16_t* alpha_codes,
**/
void Hyphenator::hyphenateFromCodes(uint8_t* result,
const uint16_t* codes,
- size_t len) {
+ wtf_size_t len) {
const Header* header = getHeader();
const Trie* trie = header->trieTable();
const Pattern* pattern = header->patternTable();
@@ -203,10 +203,10 @@ void Hyphenator::hyphenateFromCodes(uint8_t* result,
uint32_t link_shift = trie->link_shift;
uint32_t link_mask = trie->link_mask;
uint32_t pattern_shift = trie->pattern_shift;
- size_t maxOffset = len - MIN_SUFFIX - 1;
- for (size_t i = 0; i < len - 1; i++) {
+ wtf_size_t maxOffset = len - MIN_SUFFIX - 1;
+ for (wtf_size_t i = 0; i < len - 1; i++) {
uint32_t node = 0; // index into Trie table
- for (size_t j = i; j < len; j++) {
+ for (wtf_size_t j = i; j < len; j++) {
uint16_t c = codes[j];
uint32_t entry = trie->data[node + c];
if ((entry & char_mask) == c) {
@@ -237,7 +237,7 @@ void Hyphenator::hyphenateFromCodes(uint8_t* result,
}
// Since the above calculation does not modify values outside
// [MIN_PREFIX, len - MIN_SUFFIX], they are left as 0.
- for (size_t i = MIN_PREFIX; i < maxOffset; i++) {
+ for (wtf_size_t i = MIN_PREFIX; i < maxOffset; i++) {
result[i] &= 1;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h
index ef7587fd493..c255f700981 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h
@@ -41,7 +41,7 @@ class Hyphenator {
// 1 means insert hyphen and break, but this will be expanded to other edits
// for nonstandard hyphenation. Example: word is "hyphen", result is [0 0 1 0
// 0 0], corresponding to "hy-phen".
- void hyphenate(Vector<uint8_t>* result, const uint16_t* word, size_t len);
+ void hyphenate(Vector<uint8_t>* result, const uint16_t* word, wtf_size_t len);
// pattern data is in binary format, as described in doc/hyb_file_format.md.
// Note: the caller is responsible for ensuring that the lifetime of the
@@ -53,16 +53,20 @@ class Hyphenator {
private:
// apply soft hyphens only, ignoring patterns
- void hyphenateSoft(uint8_t* result, const uint16_t* word, size_t len);
+ void hyphenateSoft(uint8_t* result, const uint16_t* word, wtf_size_t len);
// Try looking up word in alphabet table, return false if any code units fail
// to map. Note that this methor writes len+2 entries into alpha_codes
// (including start and stop).
- bool alphabetLookup(uint16_t* alpha_codes, const uint16_t* word, size_t len);
+ bool alphabetLookup(uint16_t* alpha_codes,
+ const uint16_t* word,
+ wtf_size_t len);
// calculate hyphenation from patterns, assuming alphabet lookup has already
// been done
- void hyphenateFromCodes(uint8_t* result, const uint16_t* codes, size_t len);
+ void hyphenateFromCodes(uint8_t* result,
+ const uint16_t* codes,
+ wtf_size_t len);
// TODO: these should become parameters, as they might vary by locale, screen
// size, and possibly explicit user control.
@@ -72,7 +76,7 @@ class Hyphenator {
// See also LONGEST_HYPHENATED_WORD in LineBreaker.cpp. Here the constant is
// used so that temporary buffers can be stack-allocated without waste, which
// is a slightly different use case. It measures UTF-16 code units.
- static const size_t MAX_HYPHENATED_SIZE = 64;
+ static const wtf_size_t MAX_HYPHENATED_SIZE = 64;
const uint8_t* patternData;
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 3905814bc3a..c4ea59763fd 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc
@@ -53,7 +53,7 @@ class HyphenationTest : public testing::Test {
path = path.AppendASCII(filename);
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (file.IsValid())
- return HyphenationMinikin::FromFileForTesting(std::move(file));
+ return HyphenationMinikin::FromFileForTesting(locale, std::move(file));
#else
if (const LayoutLocale* layout_locale = LayoutLocale::Get(locale))
return layout_locale->GetHyphenation();
@@ -105,7 +105,7 @@ TEST_F(HyphenationTest, MapLocale) {
EXPECT_EQ(HyphenationMinikin::MapLocale("de-de-xyz"), "de-1996");
EXPECT_EQ(HyphenationMinikin::MapLocale("de-li"), "de-1996");
EXPECT_EQ(HyphenationMinikin::MapLocale("de-li-1901"), "de-ch-1901");
- EXPECT_EQ(HyphenationMinikin::MapLocale("en"), "en-gb");
+ EXPECT_EQ(HyphenationMinikin::MapLocale("en"), "en-us");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-gu"), "en-us");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-gu-xyz"), "en-us");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-xyz"), "en-gb");
@@ -204,6 +204,23 @@ TEST_F(HyphenationTest, LeadingSpaces) {
EXPECT_EQ(0u, hyphenation->LastHyphenLocation(only_spaces, 3));
}
+TEST_F(HyphenationTest, NonLetters) {
+ scoped_refptr<Hyphenation> hyphenation = GetHyphenation("en-us");
+#if defined(OS_ANDROID)
+ // Hyphenation is available only for Android M MR1 or later.
+ if (!hyphenation)
+ return;
+#endif
+
+ String non_letters("**********");
+ EXPECT_EQ(0u,
+ hyphenation->LastHyphenLocation(non_letters, non_letters.length()));
+
+ non_letters.Ensure16Bit();
+ EXPECT_EQ(0u,
+ hyphenation->LastHyphenLocation(non_letters, non_letters.length()));
+}
+
TEST_F(HyphenationTest, English) {
scoped_refptr<Hyphenation> hyphenation = GetHyphenation("en-us");
#if defined(OS_ANDROID)
@@ -216,6 +233,10 @@ TEST_F(HyphenationTest, English) {
Vector<wtf_size_t, 8> locations = hyphenation->HyphenLocations("hyphenation");
EXPECT_THAT(locations, testing::AnyOf(ElementsAreArray({6, 2}),
ElementsAreArray({7, 6, 2})));
+
+ // Avoid hyphenating capitalized words.
+ locations = hyphenation->HyphenLocations("Hyphenation");
+ EXPECT_EQ(locations.size(), 0u);
}
TEST_F(HyphenationTest, German) {
@@ -231,6 +252,10 @@ TEST_F(HyphenationTest, German) {
hyphenation->HyphenLocations("konsonantien");
EXPECT_THAT(locations, ElementsAreArray({8, 5, 3}));
+ // Hyphenate capitalized words if German.
+ locations = hyphenation->HyphenLocations("Konsonantien");
+ EXPECT_THAT(locations, ElementsAreArray({8, 5, 3}));
+
// Test words with non-ASCII (> U+0080) characters.
locations = hyphenation->HyphenLocations(
"B"
diff --git a/chromium/third_party/blink/renderer/platform/text/layout_locale.cc b/chromium/third_party/blink/renderer/platform/text/layout_locale.cc
index 193803edaae..85148477b0b 100644
--- a/chromium/third_party/blink/renderer/platform/text/layout_locale.cc
+++ b/chromium/third_party/blink/renderer/platform/text/layout_locale.cc
@@ -12,7 +12,7 @@
#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/text/case_folding_hash.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include <hb.h>
@@ -42,17 +42,18 @@ PerThreadData& GetPerThreadData() {
static hb_language_t ToHarfbuzLanguage(const AtomicString& locale) {
std::string locale_as_latin1 = locale.Latin1();
return hb_language_from_string(locale_as_latin1.data(),
- locale_as_latin1.length());
+ static_cast<int>(locale_as_latin1.length()));
}
-// SkFontMgr requires script-based locale names, like "zh-Hant" and "zh-Hans",
-// instead of "zh-CN" and "zh-TW".
+// SkFontMgr uses two/three-letter language code with an optional ISO 15924
+// four-letter script code, in POSIX style (with '-' as the separator,) such as
+// "zh-Hant" and "zh-Hans". See `fonts.xml`.
static const char* ToSkFontMgrLocale(UScriptCode script) {
switch (script) {
case USCRIPT_KATAKANA_OR_HIRAGANA:
- return "ja-JP";
+ return "ja";
case USCRIPT_HANGUL:
- return "ko-KR";
+ return "ko";
case USCRIPT_SIMPLIFIED_HAN:
return "zh-Hans";
case USCRIPT_TRADITIONAL_HAN:
@@ -63,13 +64,22 @@ static const char* ToSkFontMgrLocale(UScriptCode script) {
}
const char* LayoutLocale::LocaleForSkFontMgr() const {
- if (string_for_sk_font_mgr_.empty()) {
- const char* sk_font_mgr_locale = ToSkFontMgrLocale(script_);
- string_for_sk_font_mgr_ =
- sk_font_mgr_locale ? sk_font_mgr_locale : std::string();
- if (string_for_sk_font_mgr_.empty())
- string_for_sk_font_mgr_ = string_.Ascii();
+ if (!string_for_sk_font_mgr_.empty())
+ return string_for_sk_font_mgr_.c_str();
+
+ if (const char* sk_font_mgr_locale = ToSkFontMgrLocale(script_)) {
+ string_for_sk_font_mgr_ = sk_font_mgr_locale;
+ DCHECK(!string_for_sk_font_mgr_.empty());
+ return string_for_sk_font_mgr_.c_str();
}
+
+ const icu::Locale locale(Ascii().c_str());
+ const char* language = locale.getLanguage();
+ string_for_sk_font_mgr_ = language && *language ? language : "und";
+ const char* script = locale.getScript();
+ if (script && *script)
+ string_for_sk_font_mgr_ = string_for_sk_font_mgr_ + "-" + script;
+ DCHECK(!string_for_sk_font_mgr_.empty());
return string_for_sk_font_mgr_.c_str();
}
@@ -223,7 +233,7 @@ AtomicString LayoutLocale::LocaleWithBreakKeyword(
return string_;
std::string utf8_locale = string_.Utf8();
- Vector<char> buffer(utf8_locale.length() + 11, 0);
+ Vector<char> buffer(static_cast<wtf_size_t>(utf8_locale.length() + 11), 0);
memcpy(buffer.data(), utf8_locale.c_str(), utf8_locale.length());
const char* keyword_value = nullptr;
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
index c6d549a57b9..b13df118eb9 100644
--- a/chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc
@@ -28,92 +28,130 @@ TEST(LayoutLocaleTest, GetCaseInsensitive) {
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 combinations of BCP 47 locales.
+// https://tools.ietf.org/html/bcp47
+struct LocaleTestData {
+ const char* locale;
+ UScriptCode script;
+ const char* sk_font_mgr = nullptr;
+ absl::optional<UScriptCode> script_for_han;
+} locale_test_data[] = {
+ // Country is not relevant to |SkFontMgr|.
+ {"en-US", USCRIPT_LATIN, "en"},
+
+ // Strip countries but keep scripts.
+ {"en-Latn-US", USCRIPT_LATIN, "en-Latn"},
+
+ // Common lang-script.
+ {"en-Latn", USCRIPT_LATIN, "en-Latn"},
+ {"ar-Arab", USCRIPT_ARABIC, "ar-Arab"},
+
+ // Examples from `fonts.xml`.
+ // https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/fonts.xml
+ {"und-Arab", USCRIPT_ARABIC, "und-Arab"},
+ {"und-Thai", USCRIPT_THAI, "und-Thai"},
+
+ // Common lang-region in East Asia.
+#define EXPECT_JAPANESE \
+ USCRIPT_KATAKANA_OR_HIRAGANA, "ja", USCRIPT_KATAKANA_OR_HIRAGANA
+#define EXPECT_KOREAN USCRIPT_HANGUL, "ko", USCRIPT_HANGUL
+#define EXPECT_SIMPLIFIED_CHINESE \
+ USCRIPT_SIMPLIFIED_HAN, "zh-Hans", USCRIPT_SIMPLIFIED_HAN
+#define EXPECT_TRADITIONAL_CHINESE \
+ USCRIPT_TRADITIONAL_HAN, "zh-Hant", USCRIPT_TRADITIONAL_HAN
+ {"ja-JP", EXPECT_JAPANESE},
+ {"ko-KR", EXPECT_KOREAN},
+ {"zh", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-CN", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-HK", EXPECT_TRADITIONAL_CHINESE},
+ {"zh-MO", EXPECT_TRADITIONAL_CHINESE},
+ {"zh-SG", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-TW", EXPECT_TRADITIONAL_CHINESE},
+
+ // Encompassed languages within the Chinese macrolanguage.
+ // Both "lang" and "lang-extlang" should work.
+ {"nan", EXPECT_TRADITIONAL_CHINESE},
+ {"wuu", EXPECT_SIMPLIFIED_CHINESE},
+ {"yue", EXPECT_TRADITIONAL_CHINESE},
+ {"zh-nan", EXPECT_TRADITIONAL_CHINESE},
+ {"zh-wuu", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-yue", EXPECT_TRADITIONAL_CHINESE},
+
+ // Specified scripts is honored.
+ {"zh-Hans", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-Hant", EXPECT_TRADITIONAL_CHINESE},
+
+ // Lowercase scripts should be capitalized.
+ // |SkFontMgr_Android| uses case-sensitive match, and `fonts.xml` has
+ // capitalized script names.
+ {"zh-hans", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-hant", EXPECT_TRADITIONAL_CHINESE},
+
+ // Script has priority over other subtags.
+ {"en-Hans", EXPECT_SIMPLIFIED_CHINESE},
+ {"en-Hant", EXPECT_TRADITIONAL_CHINESE},
+ {"en-Hans-TW", EXPECT_SIMPLIFIED_CHINESE},
+ {"en-Hant-CN", EXPECT_TRADITIONAL_CHINESE},
+ {"en-TW-Hans", EXPECT_SIMPLIFIED_CHINESE},
+ {"en-CN-Hant", EXPECT_TRADITIONAL_CHINESE},
+ {"wuu-Hant", EXPECT_TRADITIONAL_CHINESE},
+ {"yue-Hans", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-wuu-Hant", EXPECT_TRADITIONAL_CHINESE},
+ {"zh-yue-Hans", EXPECT_SIMPLIFIED_CHINESE},
+
+ // Lang has priority over region.
+ // icu::Locale::getDefault() returns other combinations if, for instance,
+ // English Windows with the display language set to Japanese.
+ {"ja", EXPECT_JAPANESE},
+ {"ja-US", EXPECT_JAPANESE},
+ {"ko", EXPECT_KOREAN},
+ {"ko-US", EXPECT_KOREAN},
+ {"wuu-TW", EXPECT_SIMPLIFIED_CHINESE},
+ {"yue-CN", EXPECT_TRADITIONAL_CHINESE},
+ {"zh-wuu-TW", EXPECT_SIMPLIFIED_CHINESE},
+ {"zh-yue-CN", EXPECT_TRADITIONAL_CHINESE},
+
+ // Region should not affect script, but it can influence scriptForHan.
+ {"en-CN", USCRIPT_LATIN, "en"},
+ {"en-HK", USCRIPT_LATIN, "en", USCRIPT_TRADITIONAL_HAN},
+ {"en-MO", USCRIPT_LATIN, "en", USCRIPT_TRADITIONAL_HAN},
+ {"en-SG", USCRIPT_LATIN, "en"},
+ {"en-TW", USCRIPT_LATIN, "en", USCRIPT_TRADITIONAL_HAN},
+ {"en-JP", USCRIPT_LATIN, "en", USCRIPT_KATAKANA_OR_HIRAGANA},
+ {"en-KR", USCRIPT_LATIN, "en", USCRIPT_HANGUL},
+
+ // Multiple regions are invalid, but it can still give hints for the font
+ // selection.
+ {"en-US-JP", USCRIPT_LATIN, "en", USCRIPT_KATAKANA_OR_HIRAGANA},
+};
+#undef EXPECT_JAPANESE
+#undef EXPECT_KOREAN
+#undef EXPECT_SIMPLIFIED_CHINESE
+#undef EXPECT_TRADITIONAL_CHINESE
+
+std::ostream& operator<<(std::ostream& os, const LocaleTestData& test) {
+ return os << test.locale;
+}
+class LocaleTestDataFixture : public testing::TestWithParam<LocaleTestData> {};
+
+INSTANTIATE_TEST_CASE_P(LayoutLocaleTest,
+ LocaleTestDataFixture,
+ testing::ValuesIn(locale_test_data));
+
+TEST_P(LocaleTestDataFixture, Script) {
+ const auto& test = GetParam();
+ scoped_refptr<LayoutLocale> locale =
+ LayoutLocale::CreateForTesting(test.locale);
+ EXPECT_EQ(test.script, locale->GetScript()) << test.locale;
+ EXPECT_EQ(test.script_for_han.has_value(), locale->HasScriptForHan())
+ << test.locale;
+ if (test.script_for_han) {
+ EXPECT_EQ(*test.script_for_han, locale->GetScriptForHan()) << test.locale;
+ } else {
+ EXPECT_EQ(USCRIPT_SIMPLIFIED_HAN, locale->GetScriptForHan()) << test.locale;
}
+ if (test.sk_font_mgr)
+ EXPECT_STREQ(test.sk_font_mgr, locale->LocaleForSkFontMgr()) << test.locale;
}
TEST(LayoutLocaleTest, BreakKeyword) {
@@ -164,26 +202,26 @@ TEST(LayoutLocaleTest, AcceptLanguagesChanged) {
{",en-US", USCRIPT_COMMON, nullptr},
// Single value cases.
- {"ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
- {"ko-KR", USCRIPT_HANGUL, "ko-kr"},
+ {"ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja"},
+ {"ko-KR", USCRIPT_HANGUL, "ko"},
{"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"},
+ {"ja", USCRIPT_KATAKANA_OR_HIRAGANA, "ja"},
+ {"ko", USCRIPT_HANGUL, "ko"},
{"zh", USCRIPT_SIMPLIFIED_HAN, "zh-Hans"},
// Unusual combinations.
- {"en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+ {"en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja"},
// 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"},
+ {"en-US,ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja"},
+ {"en-US,en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja"},
// Multiple Han scripts. The first one wins.
- {"ja-JP,zh-CN", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+ {"ja-JP,zh-CN", USCRIPT_KATAKANA_OR_HIRAGANA, "ja"},
{"zh-TW,ja-JP", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
};
@@ -198,7 +236,7 @@ TEST(LayoutLocaleTest, AcceptLanguagesChanged) {
ASSERT_NE(nullptr, locale) << test.accept_languages;
EXPECT_EQ(test.script, locale->GetScriptForHan()) << test.accept_languages;
- EXPECT_STRCASEEQ(test.locale, locale->LocaleForHanForSkFontMgr())
+ EXPECT_STREQ(test.locale, locale->LocaleForHanForSkFontMgr())
<< test.accept_languages;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_icu.cc b/chromium/third_party/blink/renderer/platform/text/locale_icu.cc
index e92066eff08..510913f8071 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_icu.cc
+++ b/chromium/third_party/blink/renderer/platform/text/locale_icu.cc
@@ -36,8 +36,8 @@
#include <limits>
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -249,13 +249,8 @@ void LocaleICU::InitializeCalendar() {
UCAL_FIRST_DAY_OF_WEEK) -
UCAL_SUNDAY;
- if (features::IsFormControlsRefreshEnabled()) {
- week_day_short_labels_ = CreateLabelVector(
- short_date_format_, UDAT_NARROW_WEEKDAYS, UCAL_SUNDAY, 7);
- } else {
- week_day_short_labels_ = CreateLabelVector(
- short_date_format_, UDAT_SHORT_WEEKDAYS, UCAL_SUNDAY, 7);
- }
+ week_day_short_labels_ = CreateLabelVector(
+ short_date_format_, UDAT_NARROW_WEEKDAYS, UCAL_SUNDAY, 7);
if (!week_day_short_labels_)
week_day_short_labels_ = CreateFallbackWeekDayShortLabels();
}
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_mac.mm b/chromium/third_party/blink/renderer/platform/text/locale_mac.mm
index 989dff5c5e2..aecf6eaa234 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/text/locale_mac.mm
@@ -34,8 +34,8 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.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/web_test_support.h"
@@ -48,7 +48,7 @@ namespace blink {
static inline String LanguageFromLocale(const String& locale) {
String normalized_locale = locale;
normalized_locale.Replace('-', '_');
- size_t separator_position = normalized_locale.find('_');
+ wtf_size_t separator_position = normalized_locale.find('_');
if (separator_position == kNotFound)
return normalized_locale;
return normalized_locale.Left(separator_position);
@@ -137,9 +137,7 @@ const Vector<String>& LocaleMac::WeekDayShortLabels() {
if (!week_day_short_labels_.IsEmpty())
return week_day_short_labels_;
week_day_short_labels_.ReserveCapacity(7);
- NSArray* array = features::IsFormControlsRefreshEnabled()
- ? [ShortDateFormatter() veryShortWeekdaySymbols]
- : [ShortDateFormatter() shortWeekdaySymbols];
+ NSArray* array = [ShortDateFormatter() veryShortWeekdaySymbols];
if ([array count] == 7) {
for (unsigned i = 0; i < 7; ++i)
week_day_short_labels_.push_back(String(array[i]));
@@ -156,7 +154,7 @@ unsigned LocaleMac::FirstDayOfWeek() {
// The document for NSCalendar - firstWeekday doesn't have an explanation of
// firstWeekday value. We can guess it by the document of NSDateComponents -
// weekDay, so it can be 1 through 7 and 1 is Sunday.
- return [gregorian_calendar_ firstWeekday] - 1;
+ return static_cast<unsigned>([gregorian_calendar_ firstWeekday] - 1);
}
bool LocaleMac::IsRTL() {
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_to_script_mapping.h b/chromium/third_party/blink/renderer/platform/text/locale_to_script_mapping.h
index fe373ccc681..d4aaaf02a89 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_to_script_mapping.h
+++ b/chromium/third_party/blink/renderer/platform/text/locale_to_script_mapping.h
@@ -31,12 +31,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_LOCALE_TO_SCRIPT_MAPPING_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_LOCALE_TO_SCRIPT_MAPPING_H_
+#include <unicode/uscript.h>
+
#include "base/check.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/unicode.h"
-#include <unicode/uscript.h>
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_win.cc b/chromium/third_party/blink/renderer/platform/text/locale_win.cc
index 91b00b79fa0..9bc0f5e3542 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_win.cc
+++ b/chromium/third_party/blink/renderer/platform/text/locale_win.cc
@@ -33,8 +33,8 @@
#include <limits>
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/text/date_components.h"
@@ -45,12 +45,13 @@
#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 "ui/base/ui_base_features.h"
namespace blink {
static String ExtractLanguageCode(const String& locale) {
- size_t dash_position = locale.find('-');
+ wtf_size_t dash_position = locale.find('-');
if (dash_position == kNotFound)
return locale;
return locale.Left(dash_position);
@@ -293,24 +294,14 @@ void LocaleWin::EnsureMonthLabels() {
void LocaleWin::EnsureWeekDayShortLabels() {
if (!week_day_short_labels_.IsEmpty())
return;
- const LCTYPE kTypes[7] = {LOCALE_SABBREVDAYNAME7, // Sunday
- LOCALE_SABBREVDAYNAME1, // Monday
- LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
- LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
- LOCALE_SABBREVDAYNAME6};
- const LCTYPE kTypesRefresh[7] = {
- LOCALE_SSHORTESTDAYNAME7, // Sunday
- LOCALE_SSHORTESTDAYNAME1, // Monday
- LOCALE_SSHORTESTDAYNAME2, LOCALE_SSHORTESTDAYNAME3,
- LOCALE_SSHORTESTDAYNAME4, LOCALE_SSHORTESTDAYNAME5,
- LOCALE_SSHORTESTDAYNAME6};
+ const LCTYPE kTypes[7] = {LOCALE_SSHORTESTDAYNAME7, // Sunday
+ LOCALE_SSHORTESTDAYNAME1, // Monday
+ LOCALE_SSHORTESTDAYNAME2, LOCALE_SSHORTESTDAYNAME3,
+ LOCALE_SSHORTESTDAYNAME4, LOCALE_SSHORTESTDAYNAME5,
+ LOCALE_SSHORTESTDAYNAME6};
week_day_short_labels_.ReserveCapacity(base::size(kTypes));
for (unsigned i = 0; i < base::size(kTypes); ++i) {
- if (features::IsFormControlsRefreshEnabled()) {
- week_day_short_labels_.push_back(GetLocaleInfoString(kTypesRefresh[i]));
- } else {
- week_day_short_labels_.push_back(GetLocaleInfoString(kTypes[i]));
- }
+ week_day_short_labels_.push_back(GetLocaleInfoString(kTypes[i]));
if (week_day_short_labels_.back().IsEmpty()) {
week_day_short_labels_.Shrink(0);
week_day_short_labels_.ReserveCapacity(base::size(WTF::kWeekdayName));
@@ -387,7 +378,7 @@ String LocaleWin::ShortTimeFormat() {
StringBuilder builder;
builder.Append(GetLocaleInfoString(LOCALE_STIME));
builder.Append("ss");
- size_t pos = format.ReverseFind(builder.ToString());
+ wtf_size_t pos = format.ReverseFind(builder.ToString());
if (pos != kNotFound)
format.Remove(pos, builder.length());
}
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc b/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc
index 2b132b226c7..0fbb09ac81c 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc
@@ -189,23 +189,13 @@ TEST_F(LocaleWinTest, monthLabels) {
}
TEST_F(LocaleWinTest, weekDayShortLabels) {
- if (features::IsFormControlsRefreshEnabled()) {
- EXPECT_EQ("Su", WeekDayShortLabel(kEnglishUS, kSunday));
- EXPECT_EQ("We", WeekDayShortLabel(kEnglishUS, kWednesday));
- EXPECT_EQ("Sa", WeekDayShortLabel(kEnglishUS, kSaturday));
-
- EXPECT_EQ("di", WeekDayShortLabel(kFrenchFR, kSunday));
- EXPECT_EQ("me", WeekDayShortLabel(kFrenchFR, kWednesday));
- EXPECT_EQ("sa", WeekDayShortLabel(kFrenchFR, kSaturday));
- } else {
- EXPECT_EQ("Sun", WeekDayShortLabel(kEnglishUS, kSunday));
- EXPECT_EQ("Wed", WeekDayShortLabel(kEnglishUS, kWednesday));
- EXPECT_EQ("Sat", WeekDayShortLabel(kEnglishUS, kSaturday));
-
- EXPECT_EQ("dim.", WeekDayShortLabel(kFrenchFR, kSunday));
- EXPECT_EQ("mer.", WeekDayShortLabel(kFrenchFR, kWednesday));
- EXPECT_EQ("sam.", WeekDayShortLabel(kFrenchFR, kSaturday));
- }
+ EXPECT_EQ("Su", WeekDayShortLabel(kEnglishUS, kSunday));
+ EXPECT_EQ("We", WeekDayShortLabel(kEnglishUS, kWednesday));
+ EXPECT_EQ("Sa", WeekDayShortLabel(kEnglishUS, kSaturday));
+
+ EXPECT_EQ("di", WeekDayShortLabel(kFrenchFR, kSunday));
+ EXPECT_EQ("me", WeekDayShortLabel(kFrenchFR, kWednesday));
+ EXPECT_EQ("sa", WeekDayShortLabel(kFrenchFR, kSaturday));
EXPECT_EQ("\xE6\x97\xA5", WeekDayShortLabel(kJapaneseJP, kSunday).Utf8());
EXPECT_EQ("\xE6\xB0\xB4", WeekDayShortLabel(kJapaneseJP, kWednesday).Utf8());
EXPECT_EQ("\xE5\x9C\x9F", WeekDayShortLabel(kJapaneseJP, kSaturday).Utf8());
diff --git a/chromium/third_party/blink/renderer/platform/text/mac/hyphenation_mac.cc b/chromium/third_party/blink/renderer/platform/text/mac/hyphenation_mac.cc
index eae77cf5a19..da5230902cf 100644
--- a/chromium/third_party/blink/renderer/platform/text/mac/hyphenation_mac.cc
+++ b/chromium/third_party/blink/renderer/platform/text/mac/hyphenation_mac.cc
@@ -7,6 +7,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include "base/mac/scoped_typeref.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
@@ -19,10 +20,13 @@ class HyphenationCF final : public Hyphenation {
wtf_size_t LastHyphenLocation(const StringView& text,
wtf_size_t before_index) const override {
+ if (!ShouldHyphenateWord(text))
+ return 0;
+
CFIndex result = CFStringGetHyphenationLocationBeforeIndex(
text.ToString().Impl()->CreateCFString(), before_index,
CFRangeMake(0, text.length()), 0, locale_cf_, 0);
- return result == kCFNotFound ? 0 : result;
+ return static_cast<wtf_size_t>(result == kCFNotFound ? 0 : result);
}
// While Hyphenation::FirstHyphenLocation() works good, it computes all
@@ -31,6 +35,9 @@ class HyphenationCF final : public Hyphenation {
// LastHyphenLocation() but does not support HyphenLocations().
wtf_size_t FirstHyphenLocation(const StringView& text,
wtf_size_t after_index) const override {
+ if (!ShouldHyphenateWord(text))
+ return 0;
+
after_index = std::max(after_index,
static_cast<wtf_size_t>(kMinimumPrefixLength - 1));
wtf_size_t hyphen_location = text.length();
@@ -59,7 +66,11 @@ scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
CFLocaleCreate(kCFAllocatorDefault, locale_cf_string));
if (!CFStringIsHyphenationAvailableForLocale(locale_cf))
return nullptr;
- return base::AdoptRef(new HyphenationCF(locale_cf));
+ scoped_refptr<Hyphenation> hyphenation(
+ base::AdoptRef(new HyphenationCF(locale_cf)));
+ if (locale.StartsWithIgnoringASCIICase("de"))
+ hyphenation->hyphenate_capitalized_word_ = true;
+ return hyphenation;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.cc b/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.cc
index 16a1e90ede4..241bce4f9f6 100644
--- a/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.cc
+++ b/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.cc
@@ -4,18 +4,19 @@
#include "third_party/blink/renderer/platform/text/mathml_operator_dictionary.h"
+#include "base/notreached.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
namespace blink {
namespace {
-// https://mathml-refresh.github.io/mathml-core/#operator-dictionary-compact-special-tables
+// https://w3c.github.io/mathml-core/#operator-dictionary-compact-special-tables
const char* operators_2_ascii_chars[] = {
"!!", "!=", "&&", "**", "*=", "++", "+=", "--", "-=", "->",
"..", "//", "/=", ":=", "<=", "<>", "==", ">=", "||"};
-// https://mathml-refresh.github.io/mathml-core/#operator-dictionary-categories-hexa-table
+// https://w3c.github.io/mathml-core/#operator-dictionary-categories-hexa-table
struct EntryRange {
uint16_t entry;
unsigned range_bounds_delta : 4;
@@ -30,7 +31,7 @@ static inline uint16_t ExtractCategory(const EntryRange& range) {
// The following representation is taken from the spec, and reduces storage
// requirements by mapping codepoints and category to better make use of the
// available bytes. For details see
-// https://mathml-refresh.github.io/mathml-core/#operator-dictionary.
+// https://w3c.github.io/mathml-core/#operator-dictionary.
static const EntryRange compact_dictionary[] = {
{0x8025, 0}, {0x802A, 0}, {0x402B, 0}, {0x402D, 0}, {0x802E, 0},
{0x402F, 0}, {0x803F, 1}, {0xC05C, 0}, {0x805E, 1}, {0x807C, 0},
@@ -126,7 +127,7 @@ MathMLOperatorDictionaryCategory FindCategory(
return MathMLOperatorDictionaryCategory::kNone;
// Handle special categories that are not encoded in the compact dictionary.
- // https://mathml-refresh.github.io/mathml-core/#operator-dictionary-categories-values
+ // https://w3c.github.io/mathml-core/#operator-dictionary-categories-values
if (form == MathMLOperatorDictionaryForm::kPrefix &&
((kDoubleStruckItalicCapitalDCharacter <= key &&
key <= kDoubleStruckItalicSmallDCharacter) ||
@@ -169,7 +170,7 @@ MathMLOperatorDictionaryCategory FindCategory(
return MathMLOperatorDictionaryCategory::kNone;
// An entry is found: set the properties according the category.
- // https://mathml-refresh.github.io/mathml-core/#operator-dictionary-categories-values
+ // https://w3c.github.io/mathml-core/#operator-dictionary-categories-values
switch (ExtractCategory(*entry_range)) {
case 0x0:
return MathMLOperatorDictionaryCategory::kA;
diff --git a/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.h b/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.h
index 3e3c2db0950..bd1cdbad60d 100644
--- a/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.h
+++ b/chromium/third_party/blink/renderer/platform/text/mathml_operator_dictionary.h
@@ -30,7 +30,7 @@ enum MathMLOperatorDictionaryForm { kInfix, kPrefix, kPostfix };
// FindCategory takes a UTF-16 string and form (infix, prefix, postfix) as input
// and returns the operator dictionary category for this pair, see:
-// https://mathml-refresh.github.io/mathml-core/#operator-dictionary
+// https://w3c.github.io/mathml-core/#operator-dictionary
// The returned value is never MathMLOperatorDictionaryCategory::kUndefined.
PLATFORM_EXPORT MathMLOperatorDictionaryCategory
FindCategory(const String& content, MathMLOperatorDictionaryForm);
diff --git a/chromium/third_party/blink/renderer/platform/text/platform_locale.cc b/chromium/third_party/blink/renderer/platform/text/platform_locale.cc
index 01140e220a9..06448c770ac 100644
--- a/chromium/third_party/blink/renderer/platform/text/platform_locale.cc
+++ b/chromium/third_party/blink/renderer/platform/text/platform_locale.cc
@@ -32,7 +32,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/platform/text/date_time_format.h"
@@ -49,6 +48,8 @@ class DateTimeStringBuilder : private DateTimeFormat::TokenHandler {
public:
// The argument objects must be alive until this object dies.
DateTimeStringBuilder(Locale&, const DateComponents&);
+ DateTimeStringBuilder(const DateTimeStringBuilder&) = delete;
+ DateTimeStringBuilder& operator=(const DateTimeStringBuilder&) = delete;
bool Build(const String&);
String ToString();
@@ -64,8 +65,6 @@ class DateTimeStringBuilder : private DateTimeFormat::TokenHandler {
StringBuilder builder_;
Locale& localizer_;
const DateComponents& date_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeStringBuilder);
};
DateTimeStringBuilder::DateTimeStringBuilder(Locale& localizer,
@@ -521,7 +520,7 @@ bool Locale::IsDigit(UChar ch) {
if (ch >= '0' && ch <= '9')
return true;
// Check each digit otherwise
- String ch_str(&ch, 1);
+ String ch_str(&ch, 1u);
return (ch_str == decimal_symbols_[0] || ch_str == decimal_symbols_[1] ||
ch_str == decimal_symbols_[2] || ch_str == decimal_symbols_[3] ||
ch_str == decimal_symbols_[4] || ch_str == decimal_symbols_[5] ||
@@ -533,7 +532,7 @@ bool Locale::IsDigit(UChar ch) {
bool Locale::IsDecimalSeparator(UChar ch) {
if (ch == '.')
return true;
- return LocalizedDecimalSeparator() == String(&ch, 1);
+ return LocalizedDecimalSeparator() == String(&ch, 1u);
}
// Is there a decimal separator in a string?
diff --git a/chromium/third_party/blink/renderer/platform/text/platform_locale.h b/chromium/third_party/blink/renderer/platform/text/platform_locale.h
index efa1c415d8e..04a82c940c8 100644
--- a/chromium/third_party/blink/renderer/platform/text/platform_locale.h
+++ b/chromium/third_party/blink/renderer/platform/text/platform_locale.h
@@ -28,7 +28,6 @@
#include <memory>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/text/date_components.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -181,6 +180,8 @@ class PLATFORM_EXPORT Locale {
String FormatDateTime(const DateComponents&,
FormatType = kFormatTypeUnspecified);
+ Locale(const Locale&) = delete;
+ Locale& operator=(const Locale&) = delete;
virtual ~Locale();
protected:
@@ -216,8 +217,6 @@ class PLATFORM_EXPORT Locale {
// Does the locale use single character filtering to do additional number
// input validation?
bool uses_single_char_number_filtering_;
-
- DISALLOW_COPY_AND_ASSIGN(Locale);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/segmented_string.cc b/chromium/third_party/blink/renderer/platform/text/segmented_string.cc
index 320d877be6e..d3d71e00ec3 100644
--- a/chromium/third_party/blink/renderer/platform/text/segmented_string.cc
+++ b/chromium/third_party/blink/renderer/platform/text/segmented_string.cc
@@ -73,7 +73,7 @@ void SegmentedString::Push(UChar c) {
if (current_string_.PushIfPossible(c))
return;
- Prepend(SegmentedString(String(&c, 1)), PrependType::kUnconsume);
+ Prepend(SegmentedString(String(&c, 1u)), PrependType::kUnconsume);
}
void SegmentedString::Prepend(const SegmentedSubstring& s, PrependType type) {
diff --git a/chromium/third_party/blink/renderer/platform/text/segmented_string.h b/chromium/third_party/blink/renderer/platform/text/segmented_string.h
index 7d3ada9fede..de4c9437623 100644
--- a/chromium/third_party/blink/renderer/platform/text/segmented_string.h
+++ b/chromium/third_party/blink/renderer/platform/text/segmented_string.h
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/text/suffix_tree.h b/chromium/third_party/blink/renderer/platform/text/suffix_tree.h
index 3473f70ac62..5ccc9bf2f2a 100644
--- a/chromium/third_party/blink/renderer/platform/text/suffix_tree.h
+++ b/chromium/third_party/blink/renderer/platform/text/suffix_tree.h
@@ -59,6 +59,8 @@ class SuffixTree {
SuffixTree(const String& text, unsigned depth) : depth_(depth), leaf_(true) {
Build(text);
}
+ SuffixTree(const SuffixTree&) = delete;
+ SuffixTree& operator=(const SuffixTree&) = delete;
bool MightContain(const String& query) {
Node* current = &root_;
@@ -78,6 +80,8 @@ class SuffixTree {
public:
Node(bool is_leaf = false) : is_leaf_(is_leaf) {}
+ Node(const Node&) = delete;
+ Node& operator=(const Node&) = delete;
~Node() {
for (const auto& pair : children_) {
@@ -110,8 +114,6 @@ class SuffixTree {
// TODO(tsepez): convert to base::flat_map when allowed in blink.
Vector<std::pair<int, Node*>> children_;
const bool is_leaf_;
-
- DISALLOW_COPY_AND_ASSIGN(Node);
};
void Build(const String& text) {
@@ -135,8 +137,6 @@ class SuffixTree {
// (there can be a lot of these), we alias all the leaves to this "static"
// leaf node.
Node leaf_;
-
- DISALLOW_COPY_AND_ASSIGN(SuffixTree);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/text_boundaries.cc b/chromium/third_party/blink/renderer/platform/text/text_boundaries.cc
index 9bb388a70e5..2b4cc955424 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_boundaries.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_boundaries.cc
@@ -28,50 +28,29 @@
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
-int EndOfFirstWordBoundaryContext(const UChar* characters, int length) {
- for (int i = 0; i < length;) {
- int first = i;
- UChar32 ch;
- U16_NEXT(characters, i, length, ch);
- if (!RequiresContextForWordBoundary(ch))
- return first;
- }
- return length;
-}
-
-int StartOfLastWordBoundaryContext(const UChar* characters, int length) {
- for (int i = length; i > 0;) {
- int last = i;
- UChar32 ch;
- U16_PREV(characters, 0, i, ch);
- if (!RequiresContextForWordBoundary(ch))
- return last;
- }
- return 0;
-}
-
-int FindNextWordForward(const UChar* chars, int len, int position) {
+int FindNextWordForward(const UChar* chars, unsigned len, int position) {
TextBreakIterator* it = WordBreakIterator({chars, len});
position = it->following(position);
while (position != kTextBreakDone) {
// We stop searching when the character preceeding the break
// is alphanumeric or underscore.
- if (position < len && (WTF::unicode::IsAlphanumeric(chars[position - 1]) ||
- chars[position - 1] == kLowLineCharacter))
+ if (position < static_cast<int>(len) &&
+ (WTF::unicode::IsAlphanumeric(chars[position - 1]) ||
+ chars[position - 1] == kLowLineCharacter))
return position;
position = it->following(position);
}
- return len;
+ return static_cast<int>(len);
}
-int FindNextWordBackward(const UChar* chars, int len, int position) {
+int FindNextWordBackward(const UChar* chars, unsigned len, int position) {
TextBreakIterator* it = WordBreakIterator({chars, len});
position = it->preceding(position);
@@ -88,45 +67,13 @@ int FindNextWordBackward(const UChar* chars, int len, int position) {
return 0;
}
-std::pair<int, int> FindWordBackward(const UChar* chars,
- int len,
- int position) {
- DCHECK_GE(len, 0);
- DCHECK_LE(position, len);
- if (len == 0)
- return {0, 0};
- TextBreakIterator* it = WordBreakIterator({chars, len});
- const int start = it->preceding(position);
- const int end = it->next();
- if (start < 0) {
- // There are no words at |position|.
- return {0, 0};
- }
- return {start, end};
-}
-
-std::pair<int, int> FindWordForward(const UChar* chars, int len, int position) {
- DCHECK_GE(len, 0);
- DCHECK_LE(position, len);
- if (len == 0)
- return {0, 0};
- TextBreakIterator* it = WordBreakIterator({chars, len});
- const int end = it->following(position);
- const int start = it->previous();
- if (end < 0) {
- // There are no words at |position|.
- return {len, len};
- }
- return {start, end};
-}
-
-int FindWordStartBoundary(const UChar* chars, int len, int position) {
+int FindWordStartBoundary(const UChar* chars, unsigned len, int position) {
TextBreakIterator* it = WordBreakIterator({chars, len});
it->following(position);
return it->previous();
}
-int FindWordEndBoundary(const UChar* chars, int len, int position) {
+int FindWordEndBoundary(const UChar* chars, unsigned len, int position) {
TextBreakIterator* it = WordBreakIterator({chars, len});
int end = it->following(position);
return end < 0 ? it->last() : end;
diff --git a/chromium/third_party/blink/renderer/platform/text/text_boundaries.h b/chromium/third_party/blink/renderer/platform/text/text_boundaries.h
index b1fae5eb04b..5229ea092f6 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_boundaries.h
+++ b/chromium/third_party/blink/renderer/platform/text/text_boundaries.h
@@ -26,34 +26,25 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_TEXT_BOUNDARIES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_TEXT_BOUNDARIES_H_
-#include <utility>
-
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
-inline bool RequiresContextForWordBoundary(UChar32 ch) {
- return WTF::unicode::HasLineBreakingPropertyComplexContext(ch);
-}
-
-PLATFORM_EXPORT int EndOfFirstWordBoundaryContext(const UChar* characters,
- int length);
-PLATFORM_EXPORT int StartOfLastWordBoundaryContext(const UChar* characters,
- int length);
-
// |UChar*| should be a string in logical order instead of visual order, since
// |FindWordBoundary()| uses ICU, which works on logical order strings
-PLATFORM_EXPORT std::pair<int, int> FindWordBackward(const UChar*,
- int len,
- int position);
-PLATFORM_EXPORT std::pair<int, int> FindWordForward(const UChar*,
- int len,
- int position);
-PLATFORM_EXPORT int FindWordStartBoundary(const UChar*, int len, int position);
-PLATFORM_EXPORT int FindWordEndBoundary(const UChar*, int len, int position);
-PLATFORM_EXPORT int FindNextWordBackward(const UChar*, int len, int position);
-PLATFORM_EXPORT int FindNextWordForward(const UChar*, int len, int position);
+PLATFORM_EXPORT int FindWordStartBoundary(const UChar*,
+ unsigned len,
+ int position);
+PLATFORM_EXPORT int FindWordEndBoundary(const UChar*,
+ unsigned len,
+ int position);
+PLATFORM_EXPORT int FindNextWordBackward(const UChar*,
+ unsigned len,
+ int position);
+PLATFORM_EXPORT int FindNextWordForward(const UChar*,
+ unsigned len,
+ int position);
} // namespace blink
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
deleted file mode 100644
index 82fca820d36..00000000000
--- a/chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc
+++ /dev/null
@@ -1,175 +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 <string>
-
-#include "third_party/blink/renderer/platform/text/text_boundaries.h"
-
-#include "testing/gtest/include/gtest/gtest.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 TextBoundariesTest : public testing::Test {};
-
-namespace {
-
-std::pair<String, int> ParsePositionMarker(const std::string input8) {
- String input16 = String::FromUTF8(input8.data(), input8.size());
- input16.Ensure16Bit();
- const size_t position = input16.find('|');
- DCHECK(position != kNotFound) << input8 << " should have position marker(|).";
- String output = input16.Left(position) + input16.Substring(position + 1);
- output.Ensure16Bit();
- return {output, position};
-}
-
-std::string MakeResultText(const String& text, int start, int end) {
- StringBuilder builder;
- if (start < 0 && end < 0) {
- builder.Append(text);
- } else if (start < 0) {
- builder.Append(text.Left(end));
- builder.Append('^');
- builder.Append(text.Substring(end));
- } else if (end < 0) {
- builder.Append(text.Left(start));
- builder.Append('|');
- builder.Append(text.Substring(start));
- } else {
- builder.Append(text.Left(start));
- builder.Append('^');
- builder.Append(text.Substring(start, end - start));
- builder.Append('|');
- }
- builder.Append(text.Substring(end));
- return builder.ToString().Utf8();
-}
-
-// Returns word boundray with start(^) and end(|) markes from text with
-// position(|) marker.
-std::string TryFindWordBackward(const std::string input8) {
- std::pair<String, int> string_and_offset = ParsePositionMarker(input8);
- const String text16 = string_and_offset.first;
- const int position = string_and_offset.second;
- std::pair<int, int> start_and_end =
- FindWordBackward(text16.Characters16(), text16.length(), position);
- return MakeResultText(text16, start_and_end.first, start_and_end.second);
-}
-
-// Returns word boundray with start(^) and end(|) markes from text with
-// position(|) marker.
-std::string TryFindWordForward(const std::string input8) {
- std::pair<String, int> string_and_offset = ParsePositionMarker(input8);
- const String text16 = string_and_offset.first;
- const int position = string_and_offset.second;
- std::pair<int, int> start_and_end =
- FindWordForward(text16.Characters16(), text16.length(), position);
- return MakeResultText(text16, start_and_end.first, start_and_end.second);
-}
-
-} // namespace
-
-TEST_F(TextBoundariesTest, BackwardBasic) {
- EXPECT_EQ("^|abc def", TryFindWordBackward("|abc def"));
- EXPECT_EQ("^abc| def", TryFindWordBackward("a|bc def"));
- EXPECT_EQ("^abc| def", TryFindWordBackward("ab|c def"));
- EXPECT_EQ("^abc| def", TryFindWordBackward("abc| def"));
- EXPECT_EQ("abc^ |def", TryFindWordBackward("abc |def"));
- EXPECT_EQ("abc ^def|", TryFindWordBackward("abc d|ef"));
- EXPECT_EQ("abc ^def|", TryFindWordBackward("abc de|f"));
- EXPECT_EQ("abc ^def|", TryFindWordBackward("abc def|"));
-}
-
-TEST_F(TextBoundariesTest, ForwardBasic) {
- 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 d|ef"));
- EXPECT_EQ("abc ^def|", TryFindWordForward("abc de|f"));
- EXPECT_EQ("abc def^|", TryFindWordForward("abc def|"));
-}
-
-TEST_F(TextBoundariesTest, ForwardBiDi) {
- EXPECT_EQ(u8"^\u0620\u0621\u0622| \u0623\u0624\u0625",
- TryFindWordForward(u8"|\u0620\u0621\u0622 \u0623\u0624\u0625"));
- EXPECT_EQ(u8"^\u0620\u0621\u0622| \u0623\u0624\u0625",
- TryFindWordForward(u8"\u0620|\u0621\u0622 \u0623\u0624\u0625"));
- EXPECT_EQ(u8"^\u0620\u0621\u0622| \u0623\u0624\u0625",
- TryFindWordForward(u8"\u0620\u0621|\u0622 \u0623\u0624\u0625"));
- EXPECT_EQ(u8"\u0620\u0621\u0622^ |\u0623\u0624\u0625",
- TryFindWordForward(u8"\u0620\u0621\u0622| \u0623\u0624\u0625"));
- EXPECT_EQ(u8"\u0620\u0621\u0622 ^\u0623\u0624\u0625|",
- TryFindWordForward(u8"\u0620\u0621\u0622 |\u0623\u0624\u0625"));
- EXPECT_EQ(u8"\u0620\u0621\u0622 \u0623\u0624\u0625^|",
- TryFindWordForward(u8"\u0620\u0621\u0622 \u0623\u0624\u0625|"));
-}
-
-TEST_F(TextBoundariesTest, ForwardBiDiMixed) {
- EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
- TryFindWordForward(u8"|abc\u0620\u0621\u0622"));
- EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
- TryFindWordForward(u8"ab|c\u0620\u0621\u0622"));
- EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
- TryFindWordForward(u8"abc|\u0620\u0621\u0622"))
- << "At L1/L2 boundary";
- EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
- TryFindWordForward(u8"abc\u0620|\u0621\u0622"));
-
- EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
- TryFindWordForward(u8"|\u0620\u0621\u0622xyz"));
- EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
- TryFindWordForward(u8"\u0620|\u0621\u0622xyz"));
- EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
- TryFindWordForward(u8"\u0620\u0621\u0622|xyz"))
- << "At L2/L1 boundary";
- EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
- TryFindWordForward(u8"\u0620\u0621\u0622xy|z"));
-}
-
-TEST_F(TextBoundariesTest, ForwardOne) {
- EXPECT_EQ("^a|", TryFindWordForward("|a"));
- EXPECT_EQ("a^|", TryFindWordForward("a|")) << "No word after |";
-}
-
-TEST_F(TextBoundariesTest, ForwardParenthesis) {
- EXPECT_EQ("^(|abc)", TryFindWordForward("|(abc)"));
- EXPECT_EQ("(^abc|)", TryFindWordForward("(|abc)"));
- EXPECT_EQ("(^abc|)", TryFindWordForward("(a|bc)"));
- EXPECT_EQ("(^abc|)", TryFindWordForward("(ab|c)"));
- EXPECT_EQ("(abc)^|", TryFindWordForward("(abc)|")) << "No word after |";
-}
-
-TEST_F(TextBoundariesTest, ForwardPunctuations) {
- EXPECT_EQ("^abc|,,", TryFindWordForward("|abc,,"));
- 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(" 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 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 |"))
- << "No word after |";
-}
-
-TEST_F(TextBoundariesTest, ForwardZero) {
- EXPECT_EQ("^|", TryFindWordForward("|"));
-}
-
-} // namespace blink
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 4cca10b64d5..cd1074d3363 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
@@ -23,13 +23,14 @@
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
-#include "base/stl_util.h"
+#include <unicode/uchar.h>
+#include <unicode/uvernum.h>
+
+#include "base/cxx17_backports.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-
-#include <unicode/uchar.h>
-#include <unicode/uvernum.h>
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
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 3d8a8ca8382..aa6f797dcd3 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
@@ -27,12 +27,11 @@
#include <unicode/brkiter.h>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
@@ -356,6 +355,10 @@ class PLATFORM_EXPORT NonSharedCharacterBreakIterator final {
public:
explicit NonSharedCharacterBreakIterator(const StringView&);
NonSharedCharacterBreakIterator(const UChar*, unsigned length);
+ NonSharedCharacterBreakIterator(const NonSharedCharacterBreakIterator&) =
+ delete;
+ NonSharedCharacterBreakIterator& operator=(
+ const NonSharedCharacterBreakIterator&) = delete;
~NonSharedCharacterBreakIterator();
int Next();
@@ -397,8 +400,6 @@ class PLATFORM_EXPORT NonSharedCharacterBreakIterator final {
// For 16 bit strings, we use a TextBreakIterator.
TextBreakIterator* iterator_;
-
- DISALLOW_COPY_AND_ASSIGN(NonSharedCharacterBreakIterator);
};
// Counts the number of grapheme clusters. A surrogate pair or a sequence
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 8d880fafbc7..283f5b607a5 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
@@ -29,7 +29,6 @@
#include <utility>
#include "base/logging.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/platform/text/icu_error.h"
@@ -53,6 +52,8 @@ class LineBreakIteratorPool final {
}
LineBreakIteratorPool() = default;
+ LineBreakIteratorPool(const LineBreakIteratorPool&) = delete;
+ LineBreakIteratorPool& operator=(const LineBreakIteratorPool&) = delete;
icu::BreakIterator* Take(const AtomicString& locale) {
icu::BreakIterator* iterator = nullptr;
@@ -112,8 +113,6 @@ class LineBreakIteratorPool final {
friend WTF::ThreadSpecific<LineBreakIteratorPool>::
operator LineBreakIteratorPool*();
-
- DISALLOW_COPY_AND_ASSIGN(LineBreakIteratorPool);
};
enum TextContext { kNoContext, kPriorContext, kPrimaryContext };
@@ -428,7 +427,8 @@ static UText* TextOpenLatin1(UTextWithBuffer* ut_with_buffer,
DCHECK(!text);
return nullptr;
}
- TextInit(text, &kTextLatin1Funcs, string.data(), string.size(), prior_context,
+ TextInit(text, &kTextLatin1Funcs, string.data(),
+ base::checked_cast<unsigned>(string.size()), prior_context,
prior_context_length);
return text;
}
@@ -575,7 +575,8 @@ static UText* TextOpenUTF16(UText* text,
DCHECK(!text);
return nullptr;
}
- TextInit(text, &kTextUTF16Funcs, string.data(), string.size(), prior_context,
+ TextInit(text, &kTextUTF16Funcs, string.data(),
+ base::checked_cast<unsigned>(string.size()), prior_context,
prior_context_length);
return text;
}
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 a61bbe220f2..950c76c0084 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_run.h
+++ b/chromium/third_party/blink/renderer/platform/text/text_run.h
@@ -27,7 +27,6 @@
#include <unicode/utf16.h>
#include "base/containers/span.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/tab_size.h"
diff --git a/chromium/third_party/blink/renderer/platform/text/text_run_iterator.h b/chromium/third_party/blink/renderer/platform/text/text_run_iterator.h
index 4fe8374be3f..c23a96af94f 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_run_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/text/text_run_iterator.h
@@ -43,10 +43,9 @@ class TextRunIterator {
TextRunIterator(const TextRun* text_run, unsigned offset)
: text_run_(text_run), offset_(offset), length_(text_run_->length()) {}
- TextRunIterator(const TextRunIterator& other)
- : text_run_(other.text_run_),
- offset_(other.offset_),
- length_(text_run_->length()) {}
+ TextRunIterator(const TextRunIterator&) = default;
+
+ TextRunIterator& operator=(const TextRunIterator&) = default;
unsigned Offset() const { return offset_; }
void Increment() { offset_++; }
diff --git a/chromium/third_party/blink/renderer/platform/text/unicode_range.h b/chromium/third_party/blink/renderer/platform/text/unicode_range.h
index 083606e2401..351c90d8884 100644
--- a/chromium/third_party/blink/renderer/platform/text/unicode_range.h
+++ b/chromium/third_party/blink/renderer/platform/text/unicode_range.h
@@ -36,7 +36,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_UNICODE_RANGE_H_
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/text/unicode_utilities.h b/chromium/third_party/blink/renderer/platform/text/unicode_utilities.h
index b0089d97679..b99f062bc9d 100644
--- a/chromium/third_party/blink/renderer/platform/text/unicode_utilities.h
+++ b/chromium/third_party/blink/renderer/platform/text/unicode_utilities.h
@@ -27,8 +27,8 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_UNICODE_UTILITIES_H_
#include "third_party/blink/renderer/platform/platform_export.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/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/text/unicode_utilities_test.cc b/chromium/third_party/blink/renderer/platform/text/unicode_utilities_test.cc
index 08ba1c839f4..5a7c5f16783 100644
--- a/chromium/third_party/blink/renderer/platform/text/unicode_utilities_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/unicode_utilities_test.cc
@@ -32,7 +32,7 @@
#include <unicode/uchar.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
diff --git a/chromium/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc b/chromium/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc
index c2dbbde9413..38623fc9a2c 100644
--- a/chromium/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc
+++ b/chromium/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc
@@ -51,6 +51,8 @@ void WebThemeEngineMac::PaintMacScrollBarParts(
extra_params->scrollbar_extra.is_hovering;
native_theme_extra_params.scrollbar_extra.is_overlay =
extra_params->scrollbar_extra.is_overlay;
+ native_theme_extra_params.scrollbar_extra.scale_from_dip =
+ extra_params->scrollbar_extra.scale_from_dip;
switch (extra_params->scrollbar_extra.orientation) {
case WebThemeEngine::kVerticalOnRight:
native_theme_extra_params.scrollbar_extra.orientation =
diff --git a/chromium/third_party/blink/renderer/platform/timer.h b/chromium/third_party/blink/renderer/platform/timer.h
index 1b0e302f8d2..5c8204b6949 100644
--- a/chromium/third_party/blink/renderer/platform/timer.h
+++ b/chromium/third_party/blink/renderer/platform/timer.h
@@ -28,7 +28,6 @@
#include "base/dcheck_is_on.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
@@ -46,6 +45,8 @@ namespace blink {
class PLATFORM_EXPORT TimerBase {
public:
explicit TimerBase(scoped_refptr<base::SingleThreadTaskRunner>);
+ TimerBase(const TimerBase&) = delete;
+ TimerBase& operator=(const TimerBase&) = delete;
virtual ~TimerBase();
void Start(base::TimeDelta next_fire_interval,
@@ -109,8 +110,6 @@ class PLATFORM_EXPORT TimerBase {
// Used for invalidating tasks at arbitrary times and after the timer has been
// destructed.
base::WeakPtrFactory<TimerBase> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(TimerBase);
};
template <typename TimerFiredClass>
diff --git a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc
index 83fe6f2b0a0..66c77ff1d7f 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/platform/transforms/perspective_transform_operation.h"
+#include <algorithm>
#include "third_party/blink/renderer/platform/geometry/blend.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -33,18 +34,15 @@ namespace blink {
scoped_refptr<TransformOperation> PerspectiveTransformOperation::Accumulate(
const TransformOperation& other) {
DCHECK(other.IsSameType(*this));
- double other_p = To<PerspectiveTransformOperation>(other).p_;
-
- if (p_ == 0 && other_p == 0)
- return nullptr;
+ double other_p = To<PerspectiveTransformOperation>(other).UsedPerspective();
+ double p = UsedPerspective();
// We want to solve:
// -1/p + -1/p' == -1/p'', where we know p and p'.
//
// This can be rewritten as:
// p'' == (p * p') / (p + p')
- double p = (p_ * other_p) / (p_ + other_p);
- return PerspectiveTransformOperation::Create(p);
+ return PerspectiveTransformOperation::Create((p * other_p) / (p + other_p));
}
scoped_refptr<TransformOperation> PerspectiveTransformOperation::Blend(
@@ -54,34 +52,27 @@ scoped_refptr<TransformOperation> PerspectiveTransformOperation::Blend(
if (from && !from->IsSameType(*this))
return this;
+ // https://drafts.csswg.org/css-transforms-2/#interpolation-of-transform-functions
+ // says that we should run matrix decomposition and then run the rules for
+ // interpolation of matrices, but we know what those rules are going to
+ // yield, so just do that directly.
+ double from_p_inverse, to_p_inverse;
if (blend_to_identity) {
- // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
- double p = blink::Blend(p_, 1., progress);
- return PerspectiveTransformOperation::Create(clampTo<int>(p, 0));
- }
-
- const PerspectiveTransformOperation* from_op =
- static_cast<const PerspectiveTransformOperation*>(from);
-
- TransformationMatrix from_t;
- TransformationMatrix to_t;
- from_t.ApplyPerspective(from_op ? from_op->p_ : 0);
- to_t.ApplyPerspective(p_);
- to_t.Blend(from_t, progress);
-
- TransformationMatrix::DecomposedType decomp;
- if (!to_t.Decompose(decomp)) {
- // If we can't decompose, bail out of interpolation.
- const PerspectiveTransformOperation* used_operation =
- progress > 0.5 ? this : from_op;
- return PerspectiveTransformOperation::Create(used_operation->Perspective());
- }
-
- if (decomp.perspective_z) {
- double val = -1.0 / decomp.perspective_z;
- return PerspectiveTransformOperation::Create(clampTo<double>(val, 0));
+ from_p_inverse = 1.0 / UsedPerspective();
+ to_p_inverse = 0.0;
+ } else {
+ if (from) {
+ const PerspectiveTransformOperation* from_op =
+ static_cast<const PerspectiveTransformOperation*>(from);
+ from_p_inverse = 1.0 / from_op->UsedPerspective();
+ } else {
+ from_p_inverse = 0.0;
+ }
+ to_p_inverse = 1.0 / UsedPerspective();
}
- return PerspectiveTransformOperation::Create(0);
+ double p =
+ 1.0 / std::max(0.0, blink::Blend(from_p_inverse, to_p_inverse, progress));
+ return PerspectiveTransformOperation::Create(clampTo<double>(p, 0));
}
scoped_refptr<TransformOperation> PerspectiveTransformOperation::Zoom(
diff --git a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
index cae996be739..2db2120e741 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_PERSPECTIVE_TRANSFORM_OPERATION_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_PERSPECTIVE_TRANSFORM_OPERATION_H_
+#include <algorithm>
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -40,6 +41,8 @@ class PLATFORM_EXPORT PerspectiveTransformOperation final
double Perspective() const { return p_; }
+ double UsedPerspective() const { return std::max(1.0, p_); }
+
static bool IsMatchingOperationType(OperationType type) {
return type == kPerspective;
}
@@ -56,7 +59,7 @@ class PLATFORM_EXPORT PerspectiveTransformOperation final
}
void Apply(TransformationMatrix& transform, const FloatSize&) const override {
- transform.ApplyPerspective(p_);
+ transform.ApplyPerspective(UsedPerspective());
}
scoped_refptr<TransformOperation> Accumulate(
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h
index 191c7a42efa..0d3ed966f01 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h
@@ -25,7 +25,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_TRANSFORM_OPERATION_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_TRANSFORM_OPERATION_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -65,6 +64,8 @@ class PLATFORM_EXPORT TransformOperation
};
TransformOperation() = default;
+ TransformOperation(const TransformOperation&) = delete;
+ TransformOperation& operator=(const TransformOperation&) = delete;
virtual ~TransformOperation() = default;
virtual bool operator==(const TransformOperation&) const = 0;
@@ -122,9 +123,6 @@ class PLATFORM_EXPORT TransformOperation
BoxSizeDependency b) {
return static_cast<BoxSizeDependency>(a | b);
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TransformOperation);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transform_operations_test.cc b/chromium/third_party/blink/renderer/platform/transforms/transform_operations_test.cc
index 2fbbe01c65e..383b1163e78 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transform_operations_test.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/transform_operations_test.cc
@@ -24,7 +24,7 @@
#include "third_party/blink/renderer/platform/transforms/transform_operations.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/geometry/float_box.h"
#include "third_party/blink/renderer/platform/geometry/float_box_test_helpers.h"
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 0d52ca7e8c9..2af44e770f7 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
@@ -81,6 +81,25 @@ using gfx::Quaternion;
typedef double Vector4[4];
typedef double Vector3[3];
+static void Clamp(double& value) {
+ // TODO(crbug.com/1224320): We should prevent NaN input from outside.
+ // To prevent crashes, the following clamp NaN to 0 is added.
+ value = UNLIKELY(std::isnan(value)) ? 0 : clampTo<double>(value);
+}
+
+static void ClampMatrix(TransformationMatrix::Matrix4& matrix) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ Clamp(matrix[i][j]);
+ }
+ }
+}
+
+static float ClampToFloat(double value) {
+ // TODO(crbug.com/1224320): See Clamp() about isnan.
+ return UNLIKELY(std::isnan(value)) ? 0 : clampTo<float>(value);
+}
+
// inverse(original_matrix, inverse_matrix)
//
// calculate the inverse of a 4x4 matrix
@@ -826,7 +845,6 @@ FloatPoint TransformationMatrix::ProjectPoint(const FloatPoint& p,
double y = p.Y();
double z = -(M13() * x + M23() * y + M43()) / M33();
- // FIXME: use multVecMatrix()
double out_x = x * M11() + y * M21() + z * M31() + M41();
double out_y = x * M12() + y * M22() + z * M32() + M42();
@@ -987,15 +1005,15 @@ FloatQuad TransformationMatrix::MapQuad(const FloatQuad& q) const {
TransformationMatrix& TransformationMatrix::ScaleNonUniform(double sx,
double sy) {
- matrix_[0][0] *= sx;
- matrix_[0][1] *= sx;
- matrix_[0][2] *= sx;
- matrix_[0][3] *= sx;
-
- matrix_[1][0] *= sy;
- matrix_[1][1] *= sy;
- matrix_[1][2] *= sy;
- matrix_[1][3] *= sy;
+ Clamp(matrix_[0][0] *= sx);
+ Clamp(matrix_[0][1] *= sx);
+ Clamp(matrix_[0][2] *= sx);
+ Clamp(matrix_[0][3] *= sx);
+
+ Clamp(matrix_[1][0] *= sy);
+ Clamp(matrix_[1][1] *= sy);
+ Clamp(matrix_[1][2] *= sy);
+ Clamp(matrix_[1][3] *= sy);
return *this;
}
@@ -1004,10 +1022,10 @@ TransformationMatrix& TransformationMatrix::Scale3d(double sx,
double sz) {
ScaleNonUniform(sx, sy);
- matrix_[2][0] *= sz;
- matrix_[2][1] *= sz;
- matrix_[2][2] *= sz;
- matrix_[2][3] *= sz;
+ Clamp(matrix_[2][0] *= sz);
+ Clamp(matrix_[2][1] *= sz);
+ Clamp(matrix_[2][2] *= sz);
+ Clamp(matrix_[2][3] *= sz);
return *this;
}
@@ -1178,39 +1196,42 @@ TransformationMatrix& TransformationMatrix::Rotate3d(double rx,
}
TransformationMatrix& TransformationMatrix::Translate(double tx, double ty) {
- matrix_[3][0] += tx * matrix_[0][0] + ty * matrix_[1][0];
- matrix_[3][1] += tx * matrix_[0][1] + ty * matrix_[1][1];
- matrix_[3][2] += tx * matrix_[0][2] + ty * matrix_[1][2];
- matrix_[3][3] += tx * matrix_[0][3] + ty * matrix_[1][3];
+ Clamp(matrix_[3][0] += tx * matrix_[0][0] + ty * matrix_[1][0]);
+ Clamp(matrix_[3][1] += tx * matrix_[0][1] + ty * matrix_[1][1]);
+ Clamp(matrix_[3][2] += tx * matrix_[0][2] + ty * matrix_[1][2]);
+ Clamp(matrix_[3][3] += tx * matrix_[0][3] + ty * matrix_[1][3]);
return *this;
}
TransformationMatrix& TransformationMatrix::Translate3d(double tx,
double ty,
double tz) {
- matrix_[3][0] += tx * matrix_[0][0] + ty * matrix_[1][0] + tz * matrix_[2][0];
- matrix_[3][1] += tx * matrix_[0][1] + ty * matrix_[1][1] + tz * matrix_[2][1];
- matrix_[3][2] += tx * matrix_[0][2] + ty * matrix_[1][2] + tz * matrix_[2][2];
- matrix_[3][3] += tx * matrix_[0][3] + ty * matrix_[1][3] + tz * matrix_[2][3];
+ Clamp(matrix_[3][0] +=
+ tx * matrix_[0][0] + ty * matrix_[1][0] + tz * matrix_[2][0]);
+ Clamp(matrix_[3][1] +=
+ tx * matrix_[0][1] + ty * matrix_[1][1] + tz * matrix_[2][1]);
+ Clamp(matrix_[3][2] +=
+ tx * matrix_[0][2] + ty * matrix_[1][2] + tz * matrix_[2][2]);
+ Clamp(matrix_[3][3] +=
+ tx * matrix_[0][3] + ty * matrix_[1][3] + tz * matrix_[2][3]);
return *this;
}
TransformationMatrix& TransformationMatrix::PostTranslate(double tx,
double ty) {
if (tx != 0) {
- matrix_[0][0] += matrix_[0][3] * tx;
- matrix_[1][0] += matrix_[1][3] * tx;
- matrix_[2][0] += matrix_[2][3] * tx;
- matrix_[3][0] += matrix_[3][3] * tx;
+ Clamp(matrix_[0][0] += matrix_[0][3] * tx);
+ Clamp(matrix_[1][0] += matrix_[1][3] * tx);
+ Clamp(matrix_[2][0] += matrix_[2][3] * tx);
+ Clamp(matrix_[3][0] += matrix_[3][3] * tx);
}
if (ty != 0) {
- matrix_[0][1] += matrix_[0][3] * ty;
- matrix_[1][1] += matrix_[1][3] * ty;
- matrix_[2][1] += matrix_[2][3] * ty;
- matrix_[3][1] += matrix_[3][3] * ty;
+ Clamp(matrix_[0][1] += matrix_[0][3] * ty);
+ Clamp(matrix_[1][1] += matrix_[1][3] * ty);
+ Clamp(matrix_[2][1] += matrix_[2][3] * ty);
+ Clamp(matrix_[3][1] += matrix_[3][3] * ty);
}
-
return *this;
}
@@ -1219,12 +1240,11 @@ TransformationMatrix& TransformationMatrix::PostTranslate3d(double tx,
double tz) {
PostTranslate(tx, ty);
if (tz != 0) {
- matrix_[0][2] += matrix_[0][3] * tz;
- matrix_[1][2] += matrix_[1][3] * tz;
- matrix_[2][2] += matrix_[2][3] * tz;
- matrix_[3][2] += matrix_[3][3] * tz;
+ Clamp(matrix_[0][2] += matrix_[0][3] * tz);
+ Clamp(matrix_[1][2] += matrix_[1][3] * tz);
+ Clamp(matrix_[2][2] += matrix_[2][3] * tz);
+ Clamp(matrix_[3][2] += matrix_[3][3] * tz);
}
-
return *this;
}
@@ -1260,12 +1280,12 @@ TransformationMatrix& TransformationMatrix::ApplyTransformOrigin(double x,
}
TransformationMatrix& TransformationMatrix::Zoom(double zoom_factor) {
- matrix_[0][3] /= zoom_factor;
- matrix_[1][3] /= zoom_factor;
- matrix_[2][3] /= zoom_factor;
- matrix_[3][0] *= zoom_factor;
- matrix_[3][1] *= zoom_factor;
- matrix_[3][2] *= zoom_factor;
+ Clamp(matrix_[0][3] /= zoom_factor);
+ Clamp(matrix_[1][3] /= zoom_factor);
+ Clamp(matrix_[2][3] /= zoom_factor);
+ Clamp(matrix_[3][0] *= zoom_factor);
+ Clamp(matrix_[3][1] *= zoom_factor);
+ Clamp(matrix_[3][2] *= zoom_factor);
return *this;
}
@@ -1613,33 +1633,34 @@ TransformationMatrix& TransformationMatrix::Multiply(
SetMatrix(tmp);
#endif
+ ClampMatrix(matrix_);
return *this;
}
-void TransformationMatrix::MultVecMatrix(double x,
- double y,
- double& result_x,
- double& result_y) const {
- result_x = matrix_[3][0] + x * matrix_[0][0] + y * matrix_[1][0];
- result_y = matrix_[3][1] + x * matrix_[0][1] + y * matrix_[1][1];
+FloatPoint TransformationMatrix::InternalMapPoint(
+ const FloatPoint& source_point) const {
+ double x = source_point.X();
+ double y = source_point.Y();
+ double result_x = matrix_[3][0] + x * matrix_[0][0] + y * matrix_[1][0];
+ double result_y = matrix_[3][1] + x * matrix_[0][1] + y * matrix_[1][1];
double w = matrix_[3][3] + x * matrix_[0][3] + y * matrix_[1][3];
if (w != 1 && w != 0) {
result_x /= w;
result_y /= w;
}
+ return FloatPoint(ClampToFloat(result_x), ClampToFloat(result_y));
}
-void TransformationMatrix::MultVecMatrix(double x,
- double y,
- double z,
- double& result_x,
- double& result_y,
- double& result_z) const {
- result_x =
+FloatPoint3D TransformationMatrix::InternalMapPoint(
+ const FloatPoint3D& source_point) const {
+ double x = source_point.X();
+ double y = source_point.Y();
+ double z = source_point.Z();
+ double result_x =
matrix_[3][0] + x * matrix_[0][0] + y * matrix_[1][0] + z * matrix_[2][0];
- result_y =
+ double result_y =
matrix_[3][1] + x * matrix_[0][1] + y * matrix_[1][1] + z * matrix_[2][1];
- result_z =
+ double result_z =
matrix_[3][2] + x * matrix_[0][2] + y * matrix_[1][2] + z * matrix_[2][2];
double w =
matrix_[3][3] + x * matrix_[0][3] + y * matrix_[1][3] + z * matrix_[2][3];
@@ -1648,6 +1669,8 @@ void TransformationMatrix::MultVecMatrix(double x,
result_y /= w;
result_z /= w;
}
+ return FloatPoint3D(ClampToFloat(result_x), ClampToFloat(result_y),
+ ClampToFloat(result_z));
}
bool TransformationMatrix::IsInvertible() const {
@@ -1991,6 +2014,7 @@ void TransformationMatrix::Recompose2D(const Decomposed2dType& decomp) {
// Scale transform.
Scale3d(decomp.scale_x, decomp.scale_y, 1);
+ DCHECK(!IsInvalidMatrix());
}
bool TransformationMatrix::IsIntegerTranslation() const {
@@ -2080,9 +2104,9 @@ void TransformationMatrix::ToColumnMajorFloatArray(FloatMatrix4& result) const {
result[15] = M44();
}
-SkMatrix44 TransformationMatrix::ToSkMatrix44(
+skia::Matrix44 TransformationMatrix::ToSkMatrix44(
const TransformationMatrix& matrix) {
- SkMatrix44 ret(SkMatrix44::kUninitialized_Constructor);
+ skia::Matrix44 ret(skia::Matrix44::kUninitialized_Constructor);
ret.set4x4(matrix.M11(), matrix.M12(), matrix.M13(), matrix.M14(),
matrix.M21(), matrix.M22(), matrix.M23(), matrix.M24(),
matrix.M31(), matrix.M32(), matrix.M33(), matrix.M34(),
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 3504f90c184..ef52f0f84bb 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h
@@ -33,11 +33,11 @@
#include <memory>
#include "build/build_config.h"
+#include "skia/ext/skia_matrix_44.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/wtf/allocator/allocator.h"
#include "third_party/skia/include/core/SkM44.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
namespace gfx {
class Transform;
@@ -115,7 +115,7 @@ class PLATFORM_EXPORT TransformationMatrix {
SetMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41,
m42, m43, m44);
}
- explicit TransformationMatrix(const SkMatrix44& matrix) {
+ explicit TransformationMatrix(const skia::Matrix44& matrix) {
SetMatrix(
matrix.get(0, 0), matrix.get(1, 0), matrix.get(2, 0), matrix.get(3, 0),
matrix.get(0, 1), matrix.get(1, 1), matrix.get(2, 1), matrix.get(3, 1),
@@ -444,6 +444,16 @@ class PLATFORM_EXPORT TransformationMatrix {
bool IsIntegerTranslation() const;
+ bool IsInvalidMatrix() const {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ if (std::isinf(matrix_[i][j]) || std::isnan(matrix_[i][j]))
+ return true;
+ }
+ }
+ return false;
+ }
+
// Returns true if axis-aligned 2d rects will remain axis-aligned after being
// transformed by this matrix.
bool Preserves2dAxisAlignment() const;
@@ -463,7 +473,7 @@ class PLATFORM_EXPORT TransformationMatrix {
typedef float FloatMatrix4[16];
void ToColumnMajorFloatArray(FloatMatrix4& result) const;
- static SkMatrix44 ToSkMatrix44(const TransformationMatrix&);
+ static skia::Matrix44 ToSkMatrix44(const TransformationMatrix&);
static SkM44 ToSkM44(const TransformationMatrix&);
static gfx::Transform ToTransform(const TransformationMatrix&);
@@ -472,33 +482,8 @@ class PLATFORM_EXPORT TransformationMatrix {
String ToString(bool as_matrix = false) const;
private:
- // multiply passed 2D point by matrix (assume z=0)
- void MultVecMatrix(double x, double y, double& dst_x, double& dst_y) const;
- FloatPoint InternalMapPoint(const FloatPoint& source_point) const {
- double result_x;
- double result_y;
- MultVecMatrix(source_point.X(), source_point.Y(), result_x, result_y);
- return FloatPoint(static_cast<float>(result_x),
- static_cast<float>(result_y));
- }
-
- // multiply passed 3D point by matrix
- void MultVecMatrix(double x,
- double y,
- double z,
- double& dst_x,
- double& dst_y,
- double& dst_z) const;
- FloatPoint3D InternalMapPoint(const FloatPoint3D& source_point) const {
- double result_x;
- double result_y;
- double result_z;
- MultVecMatrix(source_point.X(), source_point.Y(), source_point.Z(),
- result_x, result_y, result_z);
- return FloatPoint3D(static_cast<float>(result_x),
- static_cast<float>(result_y),
- static_cast<float>(result_z));
- }
+ FloatPoint InternalMapPoint(const FloatPoint& source_point) const;
+ FloatPoint3D InternalMapPoint(const FloatPoint3D& source_point) const;
void SetMatrix(const Matrix4& m) { memcpy(&matrix_, &m, sizeof(Matrix4)); }
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 3c21ae7a58c..f13d90c3b47 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
@@ -157,6 +157,61 @@ TEST(TransformationMatrixTest, Multiplication) {
EXPECT_EQ(expected_atimes_b, a);
}
+TEST(TransformationMatrixTest, ValidRangedMatrix) {
+ double entries[][2] = {
+ /*
+ first entry is initial matrix value
+ second entry is a factor to use transformation operations
+ */
+ {std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::infinity()},
+ {1, std::numeric_limits<double>::infinity()},
+ {-1, std::numeric_limits<double>::infinity()},
+ {1, -std::numeric_limits<double>::infinity()},
+ {
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(),
+ },
+ {
+ std::numeric_limits<double>::lowest(),
+ -std::numeric_limits<double>::infinity(),
+ },
+ };
+ for (double* entry : entries) {
+ const double mv = entry[0];
+ const double factor = entry[1];
+
+ TransformationMatrix m(mv, mv, mv, mv, mv, mv, mv, mv, mv, mv, mv, mv, mv,
+ mv, mv, mv);
+
+ EXPECT_FALSE(m.Translate(factor, factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+ EXPECT_FALSE(m.Translate3d(factor, factor, factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+
+ EXPECT_FALSE(m.PostTranslate(factor, factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+
+ EXPECT_FALSE(m.Scale(factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+ EXPECT_FALSE(m.Scale3d(factor, factor, factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+
+ EXPECT_FALSE(m.Rotate(factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+ EXPECT_FALSE(m.Zoom(factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+
+ EXPECT_FALSE(m.Skew(factor, factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+ EXPECT_FALSE(m.ApplyPerspective(factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+ EXPECT_FALSE(
+ m.ApplyTransformOrigin(factor, factor, factor).IsInvalidMatrix())
+ << "m: " << m << " factor: " << factor << '\n';
+ }
+}
+
TEST(TransformationMatrixTest, BasicOperations) {
// Just some arbitrary matrix that introduces no rounding, and is unlikely
// to commute with other operations.
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/OWNERS b/chromium/third_party/blink/renderer/platform/video_capture/OWNERS
index ea990242b25..3cec8168ab6 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/video_capture/OWNERS
@@ -1,5 +1,2 @@
guidou@chromium.org
ilnik@chromium.org
-
-# Original (legacy) owner.
-chfremer@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
index ed73ff777f1..e6d0b0afd05 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
@@ -21,10 +21,8 @@
#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
@@ -32,7 +30,9 @@
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/limits.h"
+#include "media/base/media_switches.h"
#include "media/base/video_frame.h"
+#include "media/capture/mojom/video_capture_buffer.mojom-blink.h"
#include "media/capture/mojom/video_capture_types.mojom-blink.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -49,9 +49,6 @@ constexpr int kMaxFirstFrameLogs = 5;
const base::Feature kTimeoutHangingVideoCaptureStarts{
"TimeoutHangingVideoCaptureStarts", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kMultiPlaneSharedImageCapture{
- "MultiPlaneSharedImageCapture", base::FEATURE_DISABLED_BY_DEFAULT};
-
using VideoFrameBufferHandleType = media::mojom::blink::VideoBufferHandle::Tag;
// A collection of all types of handles that we use to reference a camera buffer
@@ -105,6 +102,8 @@ struct VideoCaptureImpl::BufferContext
break;
}
}
+ BufferContext(const BufferContext&) = delete;
+ BufferContext& operator=(const BufferContext&) = delete;
VideoFrameBufferHandleType buffer_type() const { return buffer_type_; }
const uint8_t* data() const { return data_; }
@@ -142,15 +141,19 @@ struct VideoCaptureImpl::BufferContext
return gmb_resources_->gpu_memory_buffer.get();
}
- static void MailboxHolderReleased(scoped_refptr<BufferContext> buffer_context,
- const gpu::SyncToken& release_sync_token) {
+ static void MailboxHolderReleased(
+ scoped_refptr<BufferContext> buffer_context,
+ const gpu::SyncToken& release_sync_token,
+ std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer) {
if (!buffer_context->media_task_runner_->RunsTasksInCurrentSequence()) {
buffer_context->media_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&BufferContext::MailboxHolderReleased,
- buffer_context, release_sync_token));
+ FROM_HERE,
+ base::BindOnce(&BufferContext::MailboxHolderReleased, buffer_context,
+ release_sync_token, std::move(gpu_memory_buffer)));
return;
}
buffer_context->gmb_resources_->release_sync_token = release_sync_token;
+ // Free |gpu_memory_buffer|.
}
static void DestroyTextureOnMediaThread(
@@ -244,8 +247,6 @@ struct VideoCaptureImpl::BufferContext
const scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
std::unique_ptr<GpuMemoryBufferResources> gmb_resources_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferContext);
};
VideoCaptureImpl::VideoFrameBufferPreparer::VideoFrameBufferPreparer(
@@ -408,6 +409,10 @@ bool VideoCaptureImpl::VideoFrameBufferPreparer::Initialize() {
gfx::BufferUsage::SCANOUT_VEA_CPU_READ, base::DoNothing(),
video_capture_impl_.gpu_factories_->GpuMemoryBufferManager(),
video_capture_impl_.pool_);
+ if (!gpu_memory_buffer_) {
+ LOG(ERROR) << "Failed to open GpuMemoryBuffer handle";
+ return false;
+ }
}
}
// After initializing, either |frame_| or |gpu_memory_buffer_| has been set.
@@ -481,7 +486,8 @@ bool VideoCaptureImpl::VideoFrameBufferPreparer::BindVideoFrameOnMediaThread(
}
#endif // defined(OS_WIN)
if (planes.empty()) {
- if (base::FeatureList::IsEnabled(kMultiPlaneSharedImageCapture)) {
+ if (base::FeatureList::IsEnabled(
+ media::kMultiPlaneVideoCaptureSharedImages)) {
planes.push_back(gfx::BufferPlane::Y);
planes.push_back(gfx::BufferPlane::UV);
} else {
@@ -525,6 +531,10 @@ bool VideoCaptureImpl::VideoFrameBufferPreparer::BindVideoFrameOnMediaThread(
std::move(gpu_memory_buffer_), mailbox_holder_array,
base::BindOnce(&BufferContext::MailboxHolderReleased, buffer_context_),
frame_info_->timestamp);
+ if (!frame_) {
+ LOG(ERROR) << "Can't wrap GpuMemoryBuffer as VideoFrame";
+ return false;
+ }
frame_->metadata().allow_overlay = true;
frame_->metadata().read_lock_fences_enabled = true;
return true;
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.h b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.h
index cb17cd69429..e454fe18181 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.h
+++ b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.h
@@ -8,7 +8,7 @@
#include <stdint.h>
#include <map>
-#include "base/macros.h"
+#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/unsafe_shared_memory_pool.h"
#include "base/memory/weak_ptr.h"
@@ -61,6 +61,8 @@ class PLATFORM_EXPORT VideoCaptureImpl
VideoCaptureImpl(media::VideoCaptureSessionId session_id,
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
BrowserInterfaceBrokerProxy* browser_interface_broker);
+ VideoCaptureImpl(const VideoCaptureImpl&) = delete;
+ VideoCaptureImpl& operator=(const VideoCaptureImpl&) = delete;
~VideoCaptureImpl() override;
// Stop/resume delivering video frames to clients, based on flag |suspend|.
@@ -289,8 +291,6 @@ class PLATFORM_EXPORT VideoCaptureImpl
// media::VideoFrames constructed in OnBufferReceived() from buffers cached
// in |client_buffers_|.
base::WeakPtrFactory<VideoCaptureImpl> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
index 2daae34e9b5..c5e46302132 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/test/bind.h"
@@ -15,6 +14,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "media/capture/mojom/video_capture.mojom-blink.h"
+#include "media/capture/mojom/video_capture_buffer.mojom-blink.h"
#include "media/capture/mojom/video_capture_types.mojom-blink.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -58,6 +58,8 @@ class MockMojoVideoCaptureHost : public media::mojom::blink::VideoCaptureHost {
.WillByDefault(InvokeWithoutArgs(
this, &MockMojoVideoCaptureHost::increase_released_buffer_count));
}
+ MockMojoVideoCaptureHost(const MockMojoVideoCaptureHost&) = delete;
+ MockMojoVideoCaptureHost& operator=(const MockMojoVideoCaptureHost&) = delete;
// Start() can't be mocked directly due to move-only |observer|.
void Start(const base::UnguessableToken& device_id,
@@ -113,8 +115,6 @@ class MockMojoVideoCaptureHost : public media::mojom::blink::VideoCaptureHost {
private:
int released_buffer_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MockMojoVideoCaptureHost);
};
// This class encapsulates a VideoCaptureImpl under test and the necessary
@@ -175,6 +175,8 @@ class VideoCaptureImplTest : public ::testing::Test {
video_capture_impl_->SetGpuMemoryBufferSupportForTesting(
std::make_unique<FakeGpuMemoryBufferSupport>());
}
+ VideoCaptureImplTest(const VideoCaptureImplTest&) = delete;
+ VideoCaptureImplTest& operator=(const VideoCaptureImplTest&) = delete;
protected:
// These four mocks are used to create callbacks for the different oeprations.
@@ -268,9 +270,6 @@ class VideoCaptureImplTest : public ::testing::Test {
media::VideoCaptureParams params_small_;
media::VideoCaptureParams params_large_;
base::test::ScopedFeatureList feature_list_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest);
};
TEST_F(VideoCaptureImplTest, Simple) {
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc b/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
index 5323f86a0f2..39a27059962 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -104,8 +104,9 @@ class KURLCharsetConverter final : public url::CharsetConverter {
void ConvertFromUTF16(const char16_t* input,
int input_length,
url::CanonOutput* output) override {
- std::string encoded = encoding_->Encode(
- String(input, input_length), WTF::kURLEncodedEntitiesForUnencodables);
+ std::string encoded =
+ encoding_->Encode(String(input, static_cast<unsigned>(input_length)),
+ WTF::kURLEncodedEntitiesForUnencodables);
output->Append(encoded.c_str(), static_cast<int>(encoded.length()));
}
@@ -442,7 +443,28 @@ String KURL::GetPath() const {
return ComponentString(parsed_.path);
}
+namespace {
+
+bool IsASCIITabOrNewline(UChar ch) {
+ return ch == '\t' || ch == '\r' || ch == '\n';
+}
+
+// See https://url.spec.whatwg.org/#concept-basic-url-parser:
+// 3. Remove all ASCII tab or newline from |input|.
+//
+// Matches url::RemoveURLWhitespace.
+String RemoveURLWhitespace(const String& input) {
+ return input.RemoveCharacters(IsASCIITabOrNewline);
+}
+
+} // namespace
+
bool KURL::SetProtocol(const String& protocol) {
+ // We should remove whitespace from |protocol| according to spec, but Firefox
+ // and Safari don't do it.
+ // - https://url.spec.whatwg.org/#dom-url-protocol
+ // - https://github.com/whatwg/url/issues/609
+
// Firefox and IE remove everything after the first ':'.
wtf_size_t separator_position = protocol.find(':');
String new_protocol = protocol.Substring(0, separator_position);
@@ -511,16 +533,9 @@ bool KURL::SetProtocol(const String& protocol) {
return true;
}
-void KURL::SetHost(const String& host) {
- StringUTF8Adaptor host_utf8(host);
- url::Replacements<char> replacements;
- replacements.SetHost(CharactersOrEmpty(host_utf8),
- url::Component(0, host_utf8.size()));
- ReplaceComponents(replacements);
-}
+namespace {
-static String ParsePortFromStringPosition(const String& value,
- unsigned port_start) {
+String ParsePortFromStringPosition(const String& value, unsigned port_start) {
// "008080junk" needs to be treated as port "8080" and "000" as "0".
size_t length = value.length();
unsigned port_end = port_start;
@@ -532,11 +547,45 @@ static String ParsePortFromStringPosition(const String& value,
return value.Substring(port_start, port_end - port_start);
}
-void KURL::SetHostAndPort(const String& host_and_port) {
+// Align with https://url.spec.whatwg.org/#host-state step 3, and also with the
+// IsAuthorityTerminator() function in //url/third_party/mozilla/url_parse.cc.
+bool IsEndOfHost(UChar ch) {
+ return ch == '/' || ch == '?' || ch == '#';
+}
+
+bool IsEndOfHostSpecial(UChar ch) {
+ return IsEndOfHost(ch) || ch == '\\';
+}
+
+wtf_size_t FindHostEnd(const String& host, bool is_special) {
+ wtf_size_t end = host.Find(is_special ? IsEndOfHostSpecial : IsEndOfHost);
+ if (end == kNotFound)
+ end = host.length();
+ return end;
+}
+
+} // namespace
+
+void KURL::SetHost(const String& input) {
+ String host = RemoveURLWhitespace(input);
+ wtf_size_t value_end = FindHostEnd(host, IsHierarchical());
+ String truncated_host = host.Substring(0, value_end);
+ StringUTF8Adaptor host_utf8(truncated_host);
+ url::Replacements<char> replacements;
+ replacements.SetHost(CharactersOrEmpty(host_utf8),
+ url::Component(0, host_utf8.size()));
+ ReplaceComponents(replacements);
+}
+
+void KURL::SetHostAndPort(const String& input) {
// This method intentionally does very sloppy parsing for backwards
// compatibility. See https://url.spec.whatwg.org/#host-state for what we
// theoretically should be doing.
+ String orig_host_and_port = RemoveURLWhitespace(input);
+ wtf_size_t value_end = FindHostEnd(orig_host_and_port, IsHierarchical());
+ String host_and_port = orig_host_and_port.Substring(0, value_end);
+
// This logic for handling IPv6 addresses is adapted from ParseServerInfo in
// //url/third_party/mozilla/url_parse.cc. There's a slight behaviour
// difference for compatibility with the tests: the first colon after the
@@ -549,32 +598,39 @@ void KURL::SetHostAndPort(const String& host_and_port) {
wtf_size_t colon = host_and_port.find(':', ipv6_terminator);
+ // Legacy behavior: ignore input if host part is empty
if (colon == 0)
return;
+ String host;
+ String port;
if (colon == kNotFound) {
- // |host_and_port| does not include a port, so only overwrite the host.
+ host = host_and_port;
+ } else {
+ host = host_and_port.Substring(0, colon);
+ port = ParsePortFromStringPosition(host_and_port, colon + 1);
+ }
+
+ // Replace host and port separately in order to maintain the original port if
+ // a valid host and invalid port are provided together.
+
+ // Replace host first.
+ {
url::Replacements<char> replacements;
- StringUTF8Adaptor host_utf8(host_and_port);
+ StringUTF8Adaptor host_utf8(host);
replacements.SetHost(CharactersOrEmpty(host_utf8),
url::Component(0, host_utf8.size()));
ReplaceComponents(replacements);
- return;
}
- String host = host_and_port.Substring(0, colon);
- String port = ParsePortFromStringPosition(host_and_port, colon + 1);
-
- StringUTF8Adaptor host_utf8(host);
- StringUTF8Adaptor port_utf8(port);
-
- url::Replacements<char> replacements;
- replacements.SetHost(CharactersOrEmpty(host_utf8),
- url::Component(0, host_utf8.size()));
- if (port_utf8.size())
+ // Replace port next.
+ if (is_valid_ && !port.IsEmpty()) {
+ url::Replacements<char> replacements;
+ StringUTF8Adaptor port_utf8(port);
replacements.SetPort(CharactersOrEmpty(port_utf8),
url::Component(0, port_utf8.size()));
- ReplaceComponents(replacements);
+ ReplaceComponents(replacements, /*preserve_validity=*/true);
+ }
}
void KURL::RemovePort() {
@@ -585,7 +641,8 @@ void KURL::RemovePort() {
ReplaceComponents(replacements);
}
-void KURL::SetPort(const String& port) {
+void KURL::SetPort(const String& input) {
+ String port = RemoveURLWhitespace(input);
String parsed_port = ParsePortFromStringPosition(port, 0);
if (!parsed_port.IsEmpty())
SetPort(parsed_port.ToUInt());
@@ -614,6 +671,9 @@ void KURL::SetUser(const String& user) {
// The canonicalizer will clear any usernames that are empty, so we
// don't have to explicitly call ClearUsername() here.
+ //
+ // Unlike other setters, we do not remove whitespace per spec:
+ // https://url.spec.whatwg.org/#dom-url-username
StringUTF8Adaptor user_utf8(user);
url::Replacements<char> replacements;
replacements.SetUsername(CharactersOrEmpty(user_utf8),
@@ -629,6 +689,9 @@ void KURL::SetPass(const String& pass) {
// The canonicalizer will clear any passwords that are empty, so we
// don't have to explicitly call ClearUsername() here.
+ //
+ // Unlike other setters, we do not remove whitespace per spec:
+ // https://url.spec.whatwg.org/#dom-url-password
StringUTF8Adaptor pass_utf8(pass);
url::Replacements<char> replacements;
replacements.SetPassword(CharactersOrEmpty(pass_utf8),
@@ -636,12 +699,13 @@ void KURL::SetPass(const String& pass) {
ReplaceComponents(replacements);
}
-void KURL::SetFragmentIdentifier(const String& fragment) {
+void KURL::SetFragmentIdentifier(const String& input) {
// This function is commonly called to clear the ref, which we
// normally don't have, so we optimize this case.
- if (fragment.IsNull() && !parsed_.ref.is_valid())
+ if (input.IsNull() && !parsed_.ref.is_valid())
return;
+ String fragment = RemoveURLWhitespace(input);
StringUTF8Adaptor fragment_utf8(fragment);
url::Replacements<char> replacements;
@@ -660,7 +724,8 @@ void KURL::RemoveFragmentIdentifier() {
ReplaceComponents(replacements);
}
-void KURL::SetQuery(const String& query) {
+void KURL::SetQuery(const String& input) {
+ String query = RemoveURLWhitespace(input);
StringUTF8Adaptor query_utf8(query);
url::Replacements<char> replacements;
if (query.IsNull()) {
@@ -684,9 +749,10 @@ void KURL::SetQuery(const String& query) {
ReplaceComponents(replacements);
}
-void KURL::SetPath(const String& path) {
+void KURL::SetPath(const String& input) {
// Empty paths will be canonicalized to "/", so we don't have to worry
// about calling ClearPath().
+ String path = RemoveURLWhitespace(input);
StringUTF8Adaptor path_utf8(path);
url::Replacements<char> replacements;
replacements.SetPath(CharactersOrEmpty(path_utf8),
@@ -708,7 +774,7 @@ String EncodeWithURLEscapeSequences(const String& not_encoded_string) {
UTF8Encoding().Encode(not_encoded_string, WTF::kNoUnencodables);
url::RawCanonOutputT<char> buffer;
- int input_length = utf8.length();
+ int input_length = base::checked_cast<int>(utf8.length());
if (buffer.capacity() < input_length * 3)
buffer.Resize(input_length * 3);
@@ -935,18 +1001,21 @@ String KURL::ComponentString(const url::Component& component) const {
}
template <typename CHAR>
-void KURL::ReplaceComponents(const url::Replacements<CHAR>& replacements) {
+void KURL::ReplaceComponents(const url::Replacements<CHAR>& replacements,
+ bool preserve_validity) {
url::RawCanonOutputT<char> output;
url::Parsed new_parsed;
StringUTF8Adaptor utf8(string_);
- is_valid_ =
+ bool replacements_valid =
url::ReplaceComponents(utf8.data(), utf8.size(), parsed_, replacements,
nullptr, &output, &new_parsed);
-
- parsed_ = new_parsed;
- string_ = AtomicString::FromUTF8(output.data(), output.length());
- InitProtocolMetadata();
+ if (replacements_valid || !preserve_validity) {
+ is_valid_ = replacements_valid;
+ parsed_ = new_parsed;
+ string_ = AtomicString::FromUTF8(output.data(), output.length());
+ InitProtocolMetadata();
+ }
}
bool KURL::IsSafeToSendToAnotherThread() const {
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl.h b/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
index 71cc2901db1..e7ff81b7fe1 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
@@ -254,8 +254,11 @@ class PLATFORM_EXPORT KURL {
String ComponentString(const url::Component&) const;
StringView StringViewForInvalidComponent() const;
+ // If |preserve_validity| is true, refuse to make changes that would make the
+ // KURL invalid.
template <typename CHAR>
- void ReplaceComponents(const url::Replacements<CHAR>&);
+ void ReplaceComponents(const url::Replacements<CHAR>&,
+ bool preserve_validity = false);
void InitInnerURL();
void InitProtocolMetadata();
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 56be0c870fc..53b1b80de41 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -35,7 +35,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
@@ -261,7 +261,7 @@ TEST(KURLTest, DecodeURLEscapeSequences) {
UChar invalid_expected_helper[6] = {0x00e4, 0x00a0, 0x00e5,
0x00a5, 0x00bd, 0};
String invalid_expected(
- reinterpret_cast<const ::UChar*>(invalid_expected_helper), 5);
+ reinterpret_cast<const ::UChar*>(invalid_expected_helper), 5u);
EXPECT_EQ(invalid_expected, invalid);
}
@@ -299,7 +299,7 @@ TEST(KURLTest, EncodeWithURLEscapeSequences) {
// Also test that it gets converted to UTF-8 properly.
UChar wide_input_helper[3] = {0x4f60, 0x597d, 0};
- String wide_input(reinterpret_cast<const ::UChar*>(wide_input_helper), 2);
+ String wide_input(reinterpret_cast<const ::UChar*>(wide_input_helper), 2u);
String wide_reference("%E4%BD%A0%E5%A5%BD");
String wide_output = EncodeWithURLEscapeSequences(wide_input);
EXPECT_EQ(wide_reference, wide_output);
@@ -1093,12 +1093,17 @@ enum class PortIsValid {
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().
+ // strict checking. However, unlike the constructor, invalid ports are
+ // ignored.
+ //
+ // 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.
+ // SetPort() truncates to the initial numerical prefix, and then truncates
+ // the numerical port value to a uint16_t. If such a prefix is empty, then
+ // the call is ignored.
kInSetPort
};
@@ -1109,6 +1114,9 @@ struct PortTestCase {
const PortIsValid is_valid;
};
+// port used if SetHostAndPort/SetPort is a no-op
+constexpr int kNoopPort = 8888;
+
// The tested behaviour matches the implementation. It doesn't necessarily match
// the URL Standard.
const PortTestCase port_test_cases[] = {
@@ -1118,18 +1126,20 @@ const PortTestCase port_test_cases[] = {
{"0", 0, 0, PortIsValid::kAlways},
{"1", 1, 1, PortIsValid::kAlways},
{"00000000000000000000000000000000000443", 443, 443, PortIsValid::kAlways},
- {"+80", 0, 8888, PortIsValid::kInSetHostAndPort},
- {"-80", 0, 8888, PortIsValid::kInSetHostAndPort},
+ {"+80", 0, kNoopPort, PortIsValid::kInSetPort},
+ {"-80", 0, kNoopPort, PortIsValid::kInSetPort},
{"443e0", 0, 443, PortIsValid::kInSetHostAndPort},
{"0x80", 0, 0, PortIsValid::kInSetHostAndPort},
{"8%30", 0, 8, PortIsValid::kInSetHostAndPort},
- {" 443", 0, 8888, PortIsValid::kInSetHostAndPort},
+ {" 443", 0, kNoopPort, PortIsValid::kInSetPort},
{"443 ", 0, 443, PortIsValid::kInSetHostAndPort},
- {":443", 0, 8888, PortIsValid::kInSetHostAndPort},
- {"65535", 65535, 65535, PortIsValid::kAlways},
+ {":443", 0, kNoopPort, PortIsValid::kInSetPort},
{"65534", 65534, 65534, PortIsValid::kAlways},
+ {"65535", 65535, 65535, PortIsValid::kAlways},
+ {"65535junk", 0, 65535, PortIsValid::kInSetHostAndPort},
{"65536", 0, 0, PortIsValid::kInSetPort},
{"65537", 0, 1, PortIsValid::kInSetPort},
+ {"65537junk", 0, 1, PortIsValid::kInSetPort},
{"2147483647", 0, 65535, PortIsValid::kInSetPort},
{"2147483648", 0, 0, PortIsValid::kInSetPort},
{"2147483649", 0, 1, PortIsValid::kInSetPort},
@@ -1173,7 +1183,7 @@ TEST_P(KURLPortTest, ConstructRelative) {
TEST_P(KURLPortTest, SetPort) {
const auto& param = GetParam();
- KURL url("http://a:8888/");
+ KURL url("http://a:" + String::Number(kNoopPort) + "/");
url.SetPort(param.input);
EXPECT_EQ(url.Port(), param.set_port_output);
EXPECT_EQ(url.IsValid(), true);
@@ -1181,24 +1191,22 @@ TEST_P(KURLPortTest, SetPort) {
TEST_P(KURLPortTest, SetHostAndPort) {
const auto& param = GetParam();
- KURL url("http://a:8888/");
+ KURL url("http://a:" + String::Number(kNoopPort) + "/");
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);
+ EXPECT_EQ(url.Port(), kNoopPort);
break;
}
+ EXPECT_EQ(url.IsValid(), true);
}
INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.h b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.h
index 5113a406bd3..785cbad2b61 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.h
@@ -58,7 +58,10 @@ class PLATFORM_EXPORT OriginAccessEntry {
network::mojom::CorsDomainMatchMode,
network::mojom::CorsOriginAccessMatchPriority priority =
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
+ OriginAccessEntry(const OriginAccessEntry&) = delete;
+ OriginAccessEntry& operator=(const OriginAccessEntry&) = delete;
OriginAccessEntry(OriginAccessEntry&& from);
+ // TODO: add operator=(OriginAccessEntry&&)?
network::cors::OriginAccessEntry::MatchResult MatchesOrigin(
const SecurityOrigin&) const;
@@ -71,8 +74,6 @@ class PLATFORM_EXPORT OriginAccessEntry {
private:
network::cors::OriginAccessEntry private_;
-
- DISALLOW_COPY_AND_ASSIGN(OriginAccessEntry);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/referrer.cc b/chromium/third_party/blink/renderer/platform/weborigin/referrer.cc
new file mode 100644
index 00000000000..bdb12ff874a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/weborigin/referrer.cc
@@ -0,0 +1,40 @@
+/*
+ * 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/platform/weborigin/referrer.h"
+
+#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+
+namespace blink {
+
+Referrer::Referrer()
+ : referrer_policy(network::mojom::ReferrerPolicy::kDefault) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/referrer.h b/chromium/third_party/blink/renderer/platform/weborigin/referrer.h
index 2a647708193..47bddfd404a 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/referrer.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/referrer.h
@@ -31,21 +31,22 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REFERRER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REFERRER_H_
-#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.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/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
-struct Referrer {
+struct PLATFORM_EXPORT Referrer {
DISALLOW_NEW();
Referrer(const String& referrer,
network::mojom::ReferrerPolicy referrer_policy)
: referrer(referrer), referrer_policy(referrer_policy) {
DCHECK(referrer == NoReferrer() || KURL(NullURL(), referrer).IsValid());
}
- Referrer() : referrer_policy(network::mojom::ReferrerPolicy::kDefault) {}
+ Referrer();
// We use these strings instead of "no-referrer" and "client" in the spec.
static String NoReferrer() { return String(); }
static String ClientReferrerString() { return "about:client"; }
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
index 541170707bf..492184972ab 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
@@ -104,6 +104,8 @@ class URLSchemesRegistry final {
URLSchemesSet error_schemes;
URLSchemesSet wasm_eval_csp_schemes;
URLSchemesSet allowing_shared_array_buffer_schemes;
+ URLSchemesSet web_ui_schemes;
+ URLSchemesSet code_cache_with_hashing_schemes;
private:
friend const URLSchemesRegistry& GetURLSchemesRegistry();
@@ -111,7 +113,7 @@ class URLSchemesRegistry final {
friend URLSchemesRegistry& GetMutableURLSchemesRegistryForTest();
static URLSchemesRegistry& GetInstance() {
- DEFINE_STATIC_LOCAL(URLSchemesRegistry, schemes, ());
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(URLSchemesRegistry, schemes, ());
return schemes;
}
};
@@ -415,8 +417,9 @@ bool SchemeRegistry::SchemeShouldBypassContentSecurityPolicy(
// get() returns 0 (PolicyAreaNone) if there is no entry in the map.
// Thus by default, schemes do not bypass CSP.
- return (GetURLSchemesRegistry().content_security_policy_bypassing_schemes.at(
- scheme) &
+ return (GetURLSchemesRegistry()
+ .content_security_policy_bypassing_schemes
+ .DeprecatedAtOrEmptyValue(scheme) &
policy_areas) == policy_areas;
}
@@ -449,4 +452,48 @@ bool SchemeRegistry::SchemeSupportsWasmEvalCSP(const String& scheme) {
return GetURLSchemesRegistry().wasm_eval_csp_schemes.Contains(scheme);
}
+void SchemeRegistry::RegisterURLSchemeAsWebUI(const String& scheme) {
+ DCHECK_EQ(scheme, scheme.LowerASCII());
+ GetMutableURLSchemesRegistry().web_ui_schemes.insert(scheme);
+}
+
+void SchemeRegistry::RemoveURLSchemeAsWebUI(const String& scheme) {
+ GetMutableURLSchemesRegistry().web_ui_schemes.erase(scheme);
+}
+
+bool SchemeRegistry::IsWebUIScheme(const String& scheme) {
+ if (scheme.IsEmpty())
+ return false;
+ DCHECK_EQ(scheme, scheme.LowerASCII());
+ return GetURLSchemesRegistry().web_ui_schemes.Contains(scheme);
+}
+
+void SchemeRegistry::RegisterURLSchemeAsWebUIForTest(const String& scheme) {
+ DCHECK_EQ(scheme, scheme.LowerASCII());
+ GetMutableURLSchemesRegistryForTest().web_ui_schemes.insert(scheme);
+}
+
+void SchemeRegistry::RemoveURLSchemeAsWebUIForTest(const String& scheme) {
+ GetMutableURLSchemesRegistryForTest().web_ui_schemes.erase(scheme);
+}
+
+void SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(
+ const String& scheme) {
+ DCHECK_EQ(scheme, scheme.LowerASCII());
+ GetMutableURLSchemesRegistry().code_cache_with_hashing_schemes.insert(scheme);
+}
+
+void SchemeRegistry::RemoveURLSchemeAsCodeCacheWithHashing(
+ const String& scheme) {
+ GetMutableURLSchemesRegistry().code_cache_with_hashing_schemes.erase(scheme);
+}
+
+bool SchemeRegistry::SchemeSupportsCodeCacheWithHashing(const String& scheme) {
+ if (scheme.IsEmpty())
+ return false;
+ DCHECK_EQ(scheme, scheme.LowerASCII());
+ return GetURLSchemesRegistry().code_cache_with_hashing_schemes.Contains(
+ scheme);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h
index b8ed5e9c2f5..f16a86db80e 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h
@@ -155,6 +155,25 @@ class PLATFORM_EXPORT SchemeRegistry {
static void RegisterURLSchemeAsAllowingWasmEvalCSP(const String& scheme);
static bool SchemeSupportsWasmEvalCSP(const String& scheme);
+ // Schemes that represent trusted browser UI.
+ // TODO(chromium:1197375) Reconsider usages of this category. Are there
+ // meaningful ways to define more abstract permissions or requirements that
+ // could be used instead?
+ static void RegisterURLSchemeAsWebUI(const String& scheme);
+ static void RemoveURLSchemeAsWebUI(const String& scheme);
+ static bool IsWebUIScheme(const String& scheme);
+
+ // Like the above, but without threading safety checks.
+ static void RegisterURLSchemeAsWebUIForTest(const String& scheme);
+ static void RemoveURLSchemeAsWebUIForTest(const String& scheme);
+
+ // Schemes which can use code caching but must check in the renderer whether
+ // the script content has changed rather than relying on a response time match
+ // from the network cache.
+ static void RegisterURLSchemeAsCodeCacheWithHashing(const String& scheme);
+ static void RemoveURLSchemeAsCodeCacheWithHashing(const String& scheme);
+ static bool SchemeSupportsCodeCacheWithHashing(const String& scheme);
+
private:
static const URLSchemesSet& LocalSchemes();
};
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry_test.cc
index 0ff1ebf987f..8cde34b1514 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry_test.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/scheme_registry.h"
+#include "third_party/blink/renderer/platform/wtf/threading.h"
namespace blink {
namespace {
@@ -14,6 +16,9 @@ const char kTestScheme2[] = "test-scheme-2";
class SchemeRegistryTest : public testing::Test {
void TearDown() override {
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RemoveURLSchemeRegisteredAsBypassingContentSecurityPolicy(
kTestScheme);
}
@@ -27,6 +32,9 @@ TEST_F(SchemeRegistryTest, NoCSPBypass) {
}
TEST_F(SchemeRegistryTest, FullCSPBypass) {
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
kTestScheme);
EXPECT_TRUE(
@@ -40,6 +48,9 @@ TEST_F(SchemeRegistryTest, FullCSPBypass) {
}
TEST_F(SchemeRegistryTest, PartialCSPBypass) {
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
kTestScheme, SchemeRegistry::kPolicyAreaImage);
EXPECT_FALSE(
@@ -61,6 +72,9 @@ TEST_F(SchemeRegistryTest, BypassSecureContextCheck) {
EXPECT_FALSE(SchemeRegistry::SchemeShouldBypassSecureContextCheck(scheme2));
EXPECT_FALSE(SchemeRegistry::SchemeShouldBypassSecureContextCheck(scheme3));
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
SchemeRegistry::RegisterURLSchemeBypassingSecureContextCheck("random-scheme");
EXPECT_FALSE(SchemeRegistry::SchemeShouldBypassSecureContextCheck(scheme1));
@@ -68,5 +82,94 @@ TEST_F(SchemeRegistryTest, BypassSecureContextCheck) {
EXPECT_TRUE(SchemeRegistry::SchemeShouldBypassSecureContextCheck(scheme3));
}
+TEST_F(SchemeRegistryTest, WebUIScheme) {
+ const char* kChromeUIScheme = "chrome";
+ EXPECT_FALSE(SchemeRegistry::IsWebUIScheme(kTestScheme));
+ EXPECT_FALSE(SchemeRegistry::IsWebUIScheme(kChromeUIScheme));
+
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
+ SchemeRegistry::RegisterURLSchemeAsWebUI(kTestScheme);
+
+ EXPECT_TRUE(SchemeRegistry::IsWebUIScheme(kTestScheme));
+ EXPECT_FALSE(SchemeRegistry::IsWebUIScheme(kChromeUIScheme));
+
+ SchemeRegistry::RegisterURLSchemeAsWebUI(kChromeUIScheme);
+
+ EXPECT_TRUE(SchemeRegistry::IsWebUIScheme(kTestScheme));
+ EXPECT_TRUE(SchemeRegistry::IsWebUIScheme(kChromeUIScheme));
+
+ SchemeRegistry::RemoveURLSchemeAsWebUI(kTestScheme);
+
+ EXPECT_FALSE(SchemeRegistry::IsWebUIScheme(kTestScheme));
+ EXPECT_TRUE(SchemeRegistry::IsWebUIScheme(kChromeUIScheme));
+
+ SchemeRegistry::RemoveURLSchemeAsWebUI(kChromeUIScheme);
+
+ EXPECT_FALSE(SchemeRegistry::IsWebUIScheme(kTestScheme));
+ EXPECT_FALSE(SchemeRegistry::IsWebUIScheme(kChromeUIScheme));
+}
+
+TEST_F(SchemeRegistryTest, ExtensionScheme) {
+ const char* kExtensionScheme = "chrome-extension";
+ EXPECT_FALSE(CommonSchemeRegistry::IsExtensionScheme(kTestScheme));
+ EXPECT_FALSE(CommonSchemeRegistry::IsExtensionScheme(kExtensionScheme));
+
+#if DCHECK_IS_ON()
+ WTF::SetIsBeforeThreadCreatedForTest(); // Required for next operation:
+#endif
+ CommonSchemeRegistry::RegisterURLSchemeAsExtension(kExtensionScheme);
+
+ EXPECT_FALSE(CommonSchemeRegistry::IsExtensionScheme(kTestScheme));
+ EXPECT_TRUE(CommonSchemeRegistry::IsExtensionScheme(kExtensionScheme));
+
+ CommonSchemeRegistry::RegisterURLSchemeAsExtension(kTestScheme);
+
+ EXPECT_TRUE(CommonSchemeRegistry::IsExtensionScheme(kTestScheme));
+ EXPECT_TRUE(CommonSchemeRegistry::IsExtensionScheme(kExtensionScheme));
+
+ CommonSchemeRegistry::RemoveURLSchemeAsExtensionForTest(kExtensionScheme);
+
+ EXPECT_TRUE(CommonSchemeRegistry::IsExtensionScheme(kTestScheme));
+ EXPECT_FALSE(CommonSchemeRegistry::IsExtensionScheme(kExtensionScheme));
+
+ CommonSchemeRegistry::RemoveURLSchemeAsExtensionForTest(kTestScheme);
+
+ EXPECT_FALSE(CommonSchemeRegistry::IsExtensionScheme(kTestScheme));
+ EXPECT_FALSE(CommonSchemeRegistry::IsExtensionScheme(kExtensionScheme));
+}
+
+TEST_F(SchemeRegistryTest, CodeCacheWithHashing) {
+ const char* kChromeUIScheme = "chrome";
+ EXPECT_FALSE(SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kTestScheme));
+ EXPECT_FALSE(
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kChromeUIScheme));
+
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(kTestScheme);
+
+ EXPECT_TRUE(SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kTestScheme));
+ EXPECT_FALSE(
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kChromeUIScheme));
+
+ SchemeRegistry::RegisterURLSchemeAsCodeCacheWithHashing(kChromeUIScheme);
+
+ EXPECT_TRUE(SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kTestScheme));
+ EXPECT_TRUE(
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kChromeUIScheme));
+
+ SchemeRegistry::RemoveURLSchemeAsCodeCacheWithHashing(kTestScheme);
+
+ EXPECT_FALSE(SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kTestScheme));
+ EXPECT_TRUE(
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kChromeUIScheme));
+
+ SchemeRegistry::RemoveURLSchemeAsCodeCacheWithHashing(kChromeUIScheme);
+
+ EXPECT_FALSE(SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kTestScheme));
+ EXPECT_FALSE(
+ SchemeRegistry::SchemeSupportsCodeCacheWithHashing(kChromeUIScheme));
+}
+
} // namespace
} // namespace blink
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 28c9d9b6fea..72de1b6cd6c 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -33,7 +33,7 @@
#include <memory>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -105,6 +105,9 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
static scoped_refptr<SecurityOrigin> CreateFromUrlOrigin(const url::Origin&);
url::Origin ToUrlOrigin() const;
+ SecurityOrigin(const SecurityOrigin&) = delete;
+ SecurityOrigin& operator=(const SecurityOrigin&) = delete;
+
// Some URL schemes use nested URLs for their security context. For example,
// filesystem URLs look like the following:
//
@@ -435,8 +438,6 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
// For opaque origins, tracks the non-opaque origin from which the opaque
// origin is derived.
const scoped_refptr<const SecurityOrigin> precursor_origin_;
-
- DISALLOW_COPY_AND_ASSIGN(SecurityOrigin);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin_hash.h b/chromium/third_party/blink/renderer/platform/weborigin/security_origin_hash.h
index dc1fa4b0a0c..636b0e1f3e5 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin_hash.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin_hash.h
@@ -31,6 +31,7 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.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/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
index d1c4d02c8a5..587ed2a58a4 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
@@ -32,7 +32,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/scoped_command_line.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy_unittest.h"
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 cd783a47db7..4ebbed336eb 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
@@ -30,10 +30,15 @@
#include <memory>
+#include "base/command_line.h"
+#include "base/no_destructor.h"
#include "base/strings/pattern.h"
+#include "base/strings/string_split.h"
+#include "build/build_config.h"
#include "services/network/public/cpp/cors/origin_access_list.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
+#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
@@ -92,9 +97,6 @@ Referrer SecurityPolicy::GenerateReferrer(
if (!referrer_url.IsValid())
return Referrer(Referrer::NoReferrer(), referrer_policy_no_default);
- if (SecurityOrigin::ShouldUseInnerURL(url))
- return Referrer(Referrer::NoReferrer(), referrer_policy_no_default);
-
// 5. Let referrerOrigin be the result of stripping referrerSource for use as
// a referrer, with the origin-only flag set to true.
KURL referrer_origin = referrer_url;
@@ -309,4 +311,45 @@ bool SecurityPolicy::ReferrerPolicyFromHeaderValue(
return true;
}
+#if defined(OS_FUCHSIA)
+namespace {
+std::vector<url::Origin> GetSharedArrayBufferOrigins() {
+ std::string switch_value =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kSharedArrayBufferAllowedOrigins);
+ std::vector<std::string> list =
+ SplitString(switch_value, ",", base::WhitespaceHandling::TRIM_WHITESPACE,
+ base::SplitResult::SPLIT_WANT_NONEMPTY);
+ std::vector<url::Origin> result;
+ for (auto& origin : list) {
+ GURL url(origin);
+ if (!url.is_valid() || url.scheme() != url::kHttpsScheme) {
+ LOG(FATAL) << "Invalid --" << switches::kSharedArrayBufferAllowedOrigins
+ << " specified: " << switch_value;
+ }
+ result.push_back(url::Origin::Create(url));
+ }
+ return result;
+}
+} // namespace
+#endif // defined(OS_FUCHSIA)
+
+// static
+bool SecurityPolicy::IsSharedArrayBufferAlwaysAllowedForOrigin(
+ const SecurityOrigin* security_origin) {
+#if defined(OS_FUCHSIA)
+ static base::NoDestructor<std::vector<url::Origin>> allowed_origins(
+ GetSharedArrayBufferOrigins());
+ url::Origin origin = security_origin->ToUrlOrigin();
+ for (const url::Origin& allowed_origin : *allowed_origins) {
+ if (origin.scheme() == allowed_origin.scheme() &&
+ origin.DomainIs(allowed_origin.host()) &&
+ origin.port() == allowed_origin.port()) {
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
} // namespace blink
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 66a9ffa22fc..1a617c33473 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
@@ -95,6 +95,9 @@ class PLATFORM_EXPORT SecurityPolicy {
const String& header_value,
ReferrerPolicyLegacyKeywordsSupport,
network::mojom::ReferrerPolicy* result);
+
+ static bool IsSharedArrayBufferAlwaysAllowedForOrigin(
+ const SecurityOrigin* origin);
};
} // namespace blink
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 d0d788f285c..bf0c74421cf 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
@@ -147,6 +147,10 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
kInsecureURLB, kInsecureOriginA},
{network::mojom::ReferrerPolicy::kSameOrigin, kInsecureURLA,
kInsecureURLB, nullptr},
+ {network::mojom::ReferrerPolicy::kSameOrigin, kInsecureURLB,
+ kFilesystemURL, nullptr},
+ {network::mojom::ReferrerPolicy::kSameOrigin, kInsecureURLB, kBlobURL,
+ nullptr},
{network::mojom::ReferrerPolicy::kStrictOrigin, kInsecureURLA,
kInsecureURLB, kInsecureOriginA},
{network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
@@ -234,11 +238,11 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
// blob, filesystem, and invalid URL handling
{network::mojom::ReferrerPolicy::kAlways, kInsecureURLA, kBlobURL,
- nullptr},
+ kInsecureURLA},
{network::mojom::ReferrerPolicy::kAlways, kBlobURL, kInsecureURLA,
nullptr},
{network::mojom::ReferrerPolicy::kAlways, kInsecureURLA, kFilesystemURL,
- nullptr},
+ kInsecureURLA},
{network::mojom::ReferrerPolicy::kAlways, kFilesystemURL, kInsecureURLA,
nullptr},
{network::mojom::ReferrerPolicy::kAlways, kInsecureURLA, kInvalidURL,
@@ -413,6 +417,8 @@ TEST(SecurityPolicyTest, TrustworthySafelist) {
class SecurityPolicyAccessTest : public testing::Test {
public:
SecurityPolicyAccessTest() = default;
+ SecurityPolicyAccessTest(const SecurityPolicyAccessTest&) = delete;
+ SecurityPolicyAccessTest& operator=(const SecurityPolicyAccessTest&) = delete;
~SecurityPolicyAccessTest() override = default;
void SetUp() override {
@@ -452,8 +458,6 @@ class SecurityPolicyAccessTest : public testing::Test {
scoped_refptr<const SecurityOrigin> http_example_origin_;
scoped_refptr<const SecurityOrigin> https_chromium_origin_;
scoped_refptr<const SecurityOrigin> https_google_origin_;
-
- DISALLOW_COPY_AND_ASSIGN(SecurityPolicyAccessTest);
};
// TODO(toyoshim): Simplify origin access related tests since all we need here
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc b/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc
index 843b48e1f2b..85c8c80035a 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc
@@ -22,7 +22,6 @@
#include "third_party/libyuv/include/libyuv/scale.h"
#include "third_party/webrtc/api/video/i420_buffer.h"
#include "third_party/webrtc/common_video/include/video_frame_buffer.h"
-#include "third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
#include "ui/gfx/gpu_memory_buffer.h"
@@ -194,10 +193,12 @@ scoped_refptr<media::VideoFrame> MakeScaledI420VideoFrame(
scoped_refptr<blink::WebRtcVideoFrameAdapter::SharedResources>
shared_resources) {
// ARGB pixel format may be produced by readback of texture backed frames.
- DCHECK(source_frame->format() == media::PIXEL_FORMAT_NV12 ||
- source_frame->format() == media::PIXEL_FORMAT_I420 ||
+ DCHECK(source_frame->format() == media::PIXEL_FORMAT_I420 ||
source_frame->format() == media::PIXEL_FORMAT_I420A ||
- source_frame->format() == media::PIXEL_FORMAT_ARGB);
+ source_frame->format() == media::PIXEL_FORMAT_ARGB ||
+ source_frame->format() == media::PIXEL_FORMAT_XRGB ||
+ source_frame->format() == media::PIXEL_FORMAT_ABGR ||
+ source_frame->format() == media::PIXEL_FORMAT_XBGR);
const bool has_alpha = source_frame->format() == media::PIXEL_FORMAT_I420A;
// Convert to I420 and scale to the natural size specified in
// |source_frame|.
@@ -241,52 +242,41 @@ scoped_refptr<media::VideoFrame> MakeScaledI420VideoFrame(
dst_frame->coded_size().width(),
dst_frame->coded_size().height(), libyuv::kFilterBox);
break;
- case media::PIXEL_FORMAT_NV12: {
- webrtc::NV12ToI420Scaler scaler;
- scaler.NV12ToI420Scale(
- source_frame->visible_data(media::VideoFrame::kYPlane),
- source_frame->stride(media::VideoFrame::kYPlane),
- source_frame->visible_data(media::VideoFrame::kUVPlane),
- source_frame->stride(media::VideoFrame::kUVPlane),
- source_frame->visible_rect().width(),
- source_frame->visible_rect().height(),
- dst_frame->data(media::VideoFrame::kYPlane),
- dst_frame->stride(media::VideoFrame::kYPlane),
- dst_frame->data(media::VideoFrame::kUPlane),
- dst_frame->stride(media::VideoFrame::kUPlane),
- dst_frame->data(media::VideoFrame::kVPlane),
- dst_frame->stride(media::VideoFrame::kVPlane),
- dst_frame->coded_size().width(), dst_frame->coded_size().height());
- } break;
- case media::PIXEL_FORMAT_ARGB: {
+ case media::PIXEL_FORMAT_XRGB:
+ case media::PIXEL_FORMAT_ARGB:
+ case media::PIXEL_FORMAT_XBGR:
+ case media::PIXEL_FORMAT_ABGR: {
+ auto convert_func = (source_frame->format() == media::PIXEL_FORMAT_XRGB ||
+ source_frame->format() == media::PIXEL_FORMAT_ARGB)
+ ? libyuv::ARGBToI420
+ : libyuv::ABGRToI420;
+
auto visible_size = source_frame->visible_rect().size();
if (visible_size == dst_frame->coded_size()) {
// Direct conversion to dst_frame with no scaling.
- libyuv::ARGBToI420(
- source_frame->visible_data(media::VideoFrame::kARGBPlane),
- source_frame->stride(media::VideoFrame::kARGBPlane),
- dst_frame->data(media::VideoFrame::kYPlane),
- dst_frame->stride(media::VideoFrame::kYPlane),
- dst_frame->data(media::VideoFrame::kUPlane),
- dst_frame->stride(media::VideoFrame::kUPlane),
- dst_frame->data(media::VideoFrame::kVPlane),
- dst_frame->stride(media::VideoFrame::kVPlane), visible_size.width(),
- visible_size.height());
+ convert_func(source_frame->visible_data(media::VideoFrame::kARGBPlane),
+ source_frame->stride(media::VideoFrame::kARGBPlane),
+ dst_frame->data(media::VideoFrame::kYPlane),
+ dst_frame->stride(media::VideoFrame::kYPlane),
+ dst_frame->data(media::VideoFrame::kUPlane),
+ dst_frame->stride(media::VideoFrame::kUPlane),
+ dst_frame->data(media::VideoFrame::kVPlane),
+ dst_frame->stride(media::VideoFrame::kVPlane),
+ visible_size.width(), visible_size.height());
} else {
// Convert to I420 tmp image and then scale to the dst_frame.
auto tmp_frame = shared_resources->CreateTemporaryFrame(
media::PIXEL_FORMAT_I420, visible_size, gfx::Rect(visible_size),
visible_size, source_frame->timestamp());
- libyuv::ARGBToI420(
- source_frame->visible_data(media::VideoFrame::kARGBPlane),
- source_frame->stride(media::VideoFrame::kARGBPlane),
- tmp_frame->data(media::VideoFrame::kYPlane),
- tmp_frame->stride(media::VideoFrame::kYPlane),
- tmp_frame->data(media::VideoFrame::kUPlane),
- tmp_frame->stride(media::VideoFrame::kUPlane),
- tmp_frame->data(media::VideoFrame::kVPlane),
- tmp_frame->stride(media::VideoFrame::kVPlane), visible_size.width(),
- visible_size.height());
+ convert_func(source_frame->visible_data(media::VideoFrame::kARGBPlane),
+ source_frame->stride(media::VideoFrame::kARGBPlane),
+ tmp_frame->data(media::VideoFrame::kYPlane),
+ tmp_frame->stride(media::VideoFrame::kYPlane),
+ tmp_frame->data(media::VideoFrame::kUPlane),
+ tmp_frame->stride(media::VideoFrame::kUPlane),
+ tmp_frame->data(media::VideoFrame::kVPlane),
+ tmp_frame->stride(media::VideoFrame::kVPlane),
+ visible_size.width(), visible_size.height());
libyuv::I420Scale(tmp_frame->data(media::VideoFrame::kYPlane),
tmp_frame->stride(media::VideoFrame::kYPlane),
tmp_frame->data(media::VideoFrame::kUPlane),
@@ -346,11 +336,12 @@ scoped_refptr<media::VideoFrame> MaybeConvertAndScaleFrame(
RTC_DCHECK(source_frame->format() == media::PIXEL_FORMAT_I420 ||
source_frame->format() == media::PIXEL_FORMAT_I420A ||
source_frame->format() == media::PIXEL_FORMAT_NV12 ||
- source_frame->format() == media::PIXEL_FORMAT_ARGB);
+ source_frame->format() == media::PIXEL_FORMAT_ARGB ||
+ source_frame->format() == media::PIXEL_FORMAT_XRGB ||
+ source_frame->format() == media::PIXEL_FORMAT_ABGR ||
+ source_frame->format() == media::PIXEL_FORMAT_XBGR);
RTC_DCHECK(shared_resources);
- const bool allow_nv12_output =
- base::FeatureList::IsEnabled(blink::features::kWebRtcLibvpxEncodeNV12);
const bool source_is_i420 =
source_frame->format() == media::PIXEL_FORMAT_I420 ||
source_frame->format() == media::PIXEL_FORMAT_I420A;
@@ -359,18 +350,16 @@ scoped_refptr<media::VideoFrame> MaybeConvertAndScaleFrame(
const bool no_scaling_needed =
source_frame->natural_size() == source_frame->visible_rect().size();
- if (((source_is_nv12 && allow_nv12_output) || source_is_i420) &&
- no_scaling_needed) {
+ if ((source_is_nv12 || source_is_i420) && no_scaling_needed) {
// |source_frame| already has correct pixel format and resolution.
return source_frame;
- } else if (source_is_nv12 && allow_nv12_output) {
- // Output NV12 only if it is allowed and no conversion is needed.
+ } else if (source_is_nv12) {
+ // Output NV12 only if no conversion is needed.
return MakeScaledNV12VideoFrame(std::move(source_frame),
std::move(shared_resources));
- } else {
- return MakeScaledI420VideoFrame(std::move(source_frame),
- std::move(shared_resources));
}
+ return MakeScaledI420VideoFrame(std::move(source_frame),
+ std::move(shared_resources));
}
} // anonymous namespace
@@ -395,7 +384,9 @@ GetPixelFormatsMappableToWebRtcVideoFrameBuffer() {
static constexpr const media::VideoPixelFormat
kGetPixelFormatsMappableToWebRtcVideoFrameBuffer[] = {
media::PIXEL_FORMAT_I420, media::PIXEL_FORMAT_I420A,
- media::PIXEL_FORMAT_NV12};
+ media::PIXEL_FORMAT_NV12, media::PIXEL_FORMAT_ARGB,
+ media::PIXEL_FORMAT_XRGB, media::PIXEL_FORMAT_ABGR,
+ media::PIXEL_FORMAT_XBGR};
return base::make_span(kGetPixelFormatsMappableToWebRtcVideoFrameBuffer);
}
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer_test.cc b/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer_test.cc
index 789be57ffb1..a7332a9593c 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer_test.cc
@@ -5,11 +5,9 @@
#include "third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.h"
#include "base/strings/strcat.h"
-#include "base/test/scoped_feature_list.h"
#include "media/base/video_frame.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/testing/video_frame_utils.h"
#include "third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
@@ -77,37 +75,6 @@ INSTANTIATE_TEST_CASE_P(
media::VideoPixelFormatToString(std::get<1>(info.param))});
});
-TEST(ConvertToWebRtcVideoFrameBufferTest, ToI420DownScaleGmb) {
- base::test::ScopedFeatureList scoped_feautre_list;
- scoped_feautre_list.InitAndDisableFeature(
- blink::features::kWebRtcLibvpxEncodeNV12);
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
- scoped_refptr<WebRtcVideoFrameAdapter::SharedResources> resources =
- new WebRtcVideoFrameAdapter::SharedResources(nullptr);
- auto gmb_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by GpuMemoryBuffer.
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_buffer =
- ConvertToWebRtcVideoFrameBuffer(std::move(gmb_frame), resources);
- EXPECT_EQ(gmb_frame_buffer->width(), kNaturalSize.width());
- EXPECT_EQ(gmb_frame_buffer->height(), kNaturalSize.height());
-
- // The I420 frame should have the same size as the natural size
- auto i420_frame = gmb_frame_buffer->ToI420();
- ASSERT_TRUE(i420_frame);
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
- auto* get_i420_frame = gmb_frame_buffer->GetI420();
- ASSERT_TRUE(get_i420_frame);
- EXPECT_EQ(get_i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(get_i420_frame->height(), kNaturalSize.height());
-}
-
TEST(ConvertToWebRtcVideoFrameBufferTest, ToI420ADownScale) {
const gfx::Size kCodedSize(1280, 960);
const gfx::Rect kVisibleRect(0, 120, 1280, 720);
@@ -136,9 +103,6 @@ TEST(ConvertToWebRtcVideoFrameBufferTest, ToI420ADownScale) {
TEST(ConvertToWebRtcVideoFrameBufferTest,
Nv12WrapsGmbWhenNoScalingNeeededWithFeature) {
- base::test::ScopedFeatureList scoped_feautre_list;
- scoped_feautre_list.InitAndEnableFeature(
- blink::features::kWebRtcLibvpxEncodeNV12);
const gfx::Size kCodedSize(1280, 960);
const gfx::Rect kVisibleRect(0, 120, 1280, 720);
// Same size as visible rect so no scaling.
@@ -174,9 +138,6 @@ TEST(ConvertToWebRtcVideoFrameBufferTest,
}
TEST(ConvertToWebRtcVideoFrameBufferTest, Nv12ScalesGmbWithFeature) {
- base::test::ScopedFeatureList scoped_feautre_list;
- scoped_feautre_list.InitAndEnableFeature(
- blink::features::kWebRtcLibvpxEncodeNV12);
const gfx::Size kCodedSize(1280, 960);
const gfx::Rect kVisibleRect(0, 120, 1280, 720);
const gfx::Size kNaturalSize(640, 360);
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc b/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc
deleted file mode 100644
index 5fc37657049..00000000000
--- a/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc
+++ /dev/null
@@ -1,623 +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/webrtc/legacy_webrtc_video_frame_adapter.h"
-
-#include "base/callback_helpers.h"
-#include "base/containers/contains.h"
-#include "base/containers/span.h"
-#include "base/logging.h"
-#include "base/threading/thread_restrictions.h"
-#include "gpu/command_buffer/client/raster_interface.h"
-#include "media/base/video_util.h"
-#include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/libyuv/include/libyuv/convert.h"
-#include "third_party/libyuv/include/libyuv/convert_from_argb.h"
-#include "third_party/libyuv/include/libyuv/scale.h"
-#include "third_party/webrtc/api/video/i420_buffer.h"
-#include "third_party/webrtc/common_video/include/video_frame_buffer.h"
-#include "third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h"
-#include "third_party/webrtc/rtc_base/ref_counted_object.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-namespace {
-
-class I420FrameAdapter : public webrtc::I420BufferInterface {
- public:
- explicit I420FrameAdapter(scoped_refptr<media::VideoFrame> frame)
- : frame_(std::move(frame)) {
- DCHECK_EQ(frame_->format(), media::PIXEL_FORMAT_I420);
- DCHECK_EQ(frame_->visible_rect().size(), frame_->natural_size());
- }
-
- int width() const override { return frame_->visible_rect().width(); }
- int height() const override { return frame_->visible_rect().height(); }
-
- const uint8_t* DataY() const override {
- return frame_->visible_data(media::VideoFrame::kYPlane);
- }
-
- const uint8_t* DataU() const override {
- return frame_->visible_data(media::VideoFrame::kUPlane);
- }
-
- const uint8_t* DataV() const override {
- return frame_->visible_data(media::VideoFrame::kVPlane);
- }
-
- int StrideY() const override {
- return frame_->stride(media::VideoFrame::kYPlane);
- }
-
- int StrideU() const override {
- return frame_->stride(media::VideoFrame::kUPlane);
- }
-
- int StrideV() const override {
- return frame_->stride(media::VideoFrame::kVPlane);
- }
-
- protected:
- scoped_refptr<media::VideoFrame> frame_;
-};
-
-class I420AFrameAdapter : public webrtc::I420ABufferInterface {
- public:
- explicit I420AFrameAdapter(scoped_refptr<media::VideoFrame> frame)
- : frame_(std::move(frame)) {
- DCHECK_EQ(frame_->format(), media::PIXEL_FORMAT_I420A);
- DCHECK_EQ(frame_->visible_rect().size(), frame_->natural_size());
- }
-
- int width() const override { return frame_->visible_rect().width(); }
- int height() const override { return frame_->visible_rect().height(); }
-
- const uint8_t* DataY() const override {
- return frame_->visible_data(media::VideoFrame::kYPlane);
- }
-
- const uint8_t* DataU() const override {
- return frame_->visible_data(media::VideoFrame::kUPlane);
- }
-
- const uint8_t* DataV() const override {
- return frame_->visible_data(media::VideoFrame::kVPlane);
- }
-
- const uint8_t* DataA() const override {
- return frame_->visible_data(media::VideoFrame::kAPlane);
- }
-
- int StrideY() const override {
- return frame_->stride(media::VideoFrame::kYPlane);
- }
-
- int StrideU() const override {
- return frame_->stride(media::VideoFrame::kUPlane);
- }
-
- int StrideV() const override {
- return frame_->stride(media::VideoFrame::kVPlane);
- }
-
- int StrideA() const override {
- return frame_->stride(media::VideoFrame::kAPlane);
- }
-
- protected:
- scoped_refptr<media::VideoFrame> frame_;
-};
-
-class NV12FrameAdapter : public webrtc::NV12BufferInterface {
- public:
- explicit NV12FrameAdapter(scoped_refptr<media::VideoFrame> frame)
- : frame_(std::move(frame)) {
- DCHECK_EQ(frame_->format(), media::PIXEL_FORMAT_NV12);
- DCHECK_EQ(frame_->visible_rect().size(), frame_->natural_size());
- }
-
- int width() const override { return frame_->visible_rect().width(); }
- int height() const override { return frame_->visible_rect().height(); }
-
- const uint8_t* DataY() const override {
- return frame_->visible_data(media::VideoFrame::kYPlane);
- }
-
- const uint8_t* DataUV() const override {
- return frame_->visible_data(media::VideoFrame::kUVPlane);
- }
-
- int StrideY() const override {
- return frame_->stride(media::VideoFrame::kYPlane);
- }
-
- int StrideUV() const override {
- return frame_->stride(media::VideoFrame::kUVPlane);
- }
-
- rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override {
- rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer;
- i420_buffer = webrtc::I420Buffer::Create(width(), height());
- libyuv::NV12ToI420(DataY(), StrideY(), DataUV(), StrideUV(),
- i420_buffer->MutableDataY(), i420_buffer->StrideY(),
- i420_buffer->MutableDataU(), i420_buffer->StrideU(),
- i420_buffer->MutableDataV(), i420_buffer->StrideV(),
- width(), height());
- return i420_buffer;
- }
-
- protected:
- scoped_refptr<media::VideoFrame> frame_;
-};
-
-rtc::scoped_refptr<webrtc::VideoFrameBuffer> MakeFrameAdapter(
- scoped_refptr<media::VideoFrame> video_frame) {
- switch (video_frame->format()) {
- case media::PIXEL_FORMAT_I420:
- return new rtc::RefCountedObject<I420FrameAdapter>(
- std::move(video_frame));
- case media::PIXEL_FORMAT_I420A:
- return new rtc::RefCountedObject<I420AFrameAdapter>(
- std::move(video_frame));
- case media::PIXEL_FORMAT_NV12:
- return new rtc::RefCountedObject<NV12FrameAdapter>(
- std::move(video_frame));
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-scoped_refptr<media::VideoFrame> MakeScaledI420VideoFrame(
- scoped_refptr<media::VideoFrame> source_frame,
- scoped_refptr<blink::LegacyWebRtcVideoFrameAdapter::SharedResources>
- shared_resources) {
- // ARGB pixel format may be produced by readback of texture backed frames.
- DCHECK(source_frame->format() == media::PIXEL_FORMAT_NV12 ||
- source_frame->format() == media::PIXEL_FORMAT_I420 ||
- source_frame->format() == media::PIXEL_FORMAT_I420A ||
- source_frame->format() == media::PIXEL_FORMAT_ARGB);
- const bool has_alpha = source_frame->format() == media::PIXEL_FORMAT_I420A;
- // Convert to I420 and scale to the natural size specified in
- // |source_frame|.
- auto dst_frame = shared_resources->CreateFrame(
- has_alpha ? media::PIXEL_FORMAT_I420A : media::PIXEL_FORMAT_I420,
- source_frame->natural_size(), gfx::Rect(source_frame->natural_size()),
- source_frame->natural_size(), source_frame->timestamp());
- if (!dst_frame) {
- LOG(ERROR) << "Failed to create I420 frame from pool.";
- return nullptr;
- }
- dst_frame->metadata().MergeMetadataFrom(source_frame->metadata());
-
- switch (source_frame->format()) {
- case media::PIXEL_FORMAT_I420A:
- libyuv::ScalePlane(source_frame->visible_data(media::VideoFrame::kAPlane),
- source_frame->stride(media::VideoFrame::kAPlane),
- source_frame->visible_rect().width(),
- source_frame->visible_rect().height(),
- dst_frame->data(media::VideoFrame::kAPlane),
- dst_frame->stride(media::VideoFrame::kAPlane),
- dst_frame->coded_size().width(),
- dst_frame->coded_size().height(), libyuv::kFilterBox);
- // Fallthrough to I420 in order to scale the YUV planes as well.
- ABSL_FALLTHROUGH_INTENDED;
- case media::PIXEL_FORMAT_I420:
- libyuv::I420Scale(source_frame->visible_data(media::VideoFrame::kYPlane),
- source_frame->stride(media::VideoFrame::kYPlane),
- source_frame->visible_data(media::VideoFrame::kUPlane),
- source_frame->stride(media::VideoFrame::kUPlane),
- source_frame->visible_data(media::VideoFrame::kVPlane),
- source_frame->stride(media::VideoFrame::kVPlane),
- source_frame->visible_rect().width(),
- source_frame->visible_rect().height(),
- dst_frame->data(media::VideoFrame::kYPlane),
- dst_frame->stride(media::VideoFrame::kYPlane),
- dst_frame->data(media::VideoFrame::kUPlane),
- dst_frame->stride(media::VideoFrame::kUPlane),
- dst_frame->data(media::VideoFrame::kVPlane),
- dst_frame->stride(media::VideoFrame::kVPlane),
- dst_frame->coded_size().width(),
- dst_frame->coded_size().height(), libyuv::kFilterBox);
- break;
- case media::PIXEL_FORMAT_NV12: {
- webrtc::NV12ToI420Scaler scaler;
- scaler.NV12ToI420Scale(
- source_frame->visible_data(media::VideoFrame::kYPlane),
- source_frame->stride(media::VideoFrame::kYPlane),
- source_frame->visible_data(media::VideoFrame::kUVPlane),
- source_frame->stride(media::VideoFrame::kUVPlane),
- source_frame->visible_rect().width(),
- source_frame->visible_rect().height(),
- dst_frame->data(media::VideoFrame::kYPlane),
- dst_frame->stride(media::VideoFrame::kYPlane),
- dst_frame->data(media::VideoFrame::kUPlane),
- dst_frame->stride(media::VideoFrame::kUPlane),
- dst_frame->data(media::VideoFrame::kVPlane),
- dst_frame->stride(media::VideoFrame::kVPlane),
- dst_frame->coded_size().width(), dst_frame->coded_size().height());
- } break;
- case media::PIXEL_FORMAT_ARGB: {
- auto visible_size = source_frame->visible_rect().size();
- if (visible_size == dst_frame->coded_size()) {
- // Direct conversion to dst_frame with no scaling.
- libyuv::ARGBToI420(
- source_frame->visible_data(media::VideoFrame::kARGBPlane),
- source_frame->stride(media::VideoFrame::kARGBPlane),
- dst_frame->data(media::VideoFrame::kYPlane),
- dst_frame->stride(media::VideoFrame::kYPlane),
- dst_frame->data(media::VideoFrame::kUPlane),
- dst_frame->stride(media::VideoFrame::kUPlane),
- dst_frame->data(media::VideoFrame::kVPlane),
- dst_frame->stride(media::VideoFrame::kVPlane), visible_size.width(),
- visible_size.height());
- } else {
- // Convert to I420 tmp image and then scale to the dst_frame.
- auto tmp_frame = shared_resources->CreateTemporaryFrame(
- media::PIXEL_FORMAT_I420, visible_size, gfx::Rect(visible_size),
- visible_size, source_frame->timestamp());
- libyuv::ARGBToI420(
- source_frame->visible_data(media::VideoFrame::kARGBPlane),
- source_frame->stride(media::VideoFrame::kARGBPlane),
- tmp_frame->data(media::VideoFrame::kYPlane),
- tmp_frame->stride(media::VideoFrame::kYPlane),
- tmp_frame->data(media::VideoFrame::kUPlane),
- tmp_frame->stride(media::VideoFrame::kUPlane),
- tmp_frame->data(media::VideoFrame::kVPlane),
- tmp_frame->stride(media::VideoFrame::kVPlane), visible_size.width(),
- visible_size.height());
- libyuv::I420Scale(tmp_frame->data(media::VideoFrame::kYPlane),
- tmp_frame->stride(media::VideoFrame::kYPlane),
- tmp_frame->data(media::VideoFrame::kUPlane),
- tmp_frame->stride(media::VideoFrame::kUPlane),
- tmp_frame->data(media::VideoFrame::kVPlane),
- tmp_frame->stride(media::VideoFrame::kVPlane),
- visible_size.width(), visible_size.height(),
- dst_frame->data(media::VideoFrame::kYPlane),
- dst_frame->stride(media::VideoFrame::kYPlane),
- dst_frame->data(media::VideoFrame::kUPlane),
- dst_frame->stride(media::VideoFrame::kUPlane),
- dst_frame->data(media::VideoFrame::kVPlane),
- dst_frame->stride(media::VideoFrame::kVPlane),
- dst_frame->coded_size().width(),
- dst_frame->coded_size().height(), libyuv::kFilterBox);
- }
- } break;
- default:
- NOTREACHED();
- }
- return dst_frame;
-}
-
-scoped_refptr<media::VideoFrame> MakeScaledNV12VideoFrame(
- scoped_refptr<media::VideoFrame> source_frame,
- scoped_refptr<blink::LegacyWebRtcVideoFrameAdapter::SharedResources>
- shared_resources) {
- DCHECK_EQ(source_frame->format(), media::PIXEL_FORMAT_NV12);
- auto dst_frame = shared_resources->CreateFrame(
- media::PIXEL_FORMAT_NV12, source_frame->natural_size(),
- gfx::Rect(source_frame->natural_size()), source_frame->natural_size(),
- source_frame->timestamp());
- dst_frame->metadata().MergeMetadataFrom(source_frame->metadata());
- const auto& nv12_planes = dst_frame->layout().planes();
- libyuv::NV12Scale(source_frame->visible_data(media::VideoFrame::kYPlane),
- source_frame->stride(media::VideoFrame::kYPlane),
- source_frame->visible_data(media::VideoFrame::kUVPlane),
- source_frame->stride(media::VideoFrame::kUVPlane),
- source_frame->visible_rect().width(),
- source_frame->visible_rect().height(),
- dst_frame->data(media::VideoFrame::kYPlane),
- nv12_planes[media::VideoFrame::kYPlane].stride,
- dst_frame->data(media::VideoFrame::kUVPlane),
- nv12_planes[media::VideoFrame::kUVPlane].stride,
- dst_frame->coded_size().width(),
- dst_frame->coded_size().height(), libyuv::kFilterBox);
- return dst_frame;
-}
-
-scoped_refptr<media::VideoFrame> MaybeConvertAndScaleFrame(
- scoped_refptr<media::VideoFrame> source_frame,
- scoped_refptr<blink::LegacyWebRtcVideoFrameAdapter::SharedResources>
- shared_resources) {
- if (!source_frame)
- return nullptr;
- // Texture frames may be readback in ARGB format.
- RTC_DCHECK(source_frame->format() == media::PIXEL_FORMAT_I420 ||
- source_frame->format() == media::PIXEL_FORMAT_I420A ||
- source_frame->format() == media::PIXEL_FORMAT_NV12 ||
- source_frame->format() == media::PIXEL_FORMAT_ARGB);
- RTC_DCHECK(shared_resources);
-
- const bool allow_nv12_output =
- base::FeatureList::IsEnabled(blink::features::kWebRtcLibvpxEncodeNV12);
- const bool source_is_i420 =
- source_frame->format() == media::PIXEL_FORMAT_I420 ||
- source_frame->format() == media::PIXEL_FORMAT_I420A;
- const bool source_is_nv12 =
- source_frame->format() == media::PIXEL_FORMAT_NV12;
- const bool no_scaling_needed =
- source_frame->natural_size() == source_frame->visible_rect().size();
-
- if (((source_is_nv12 && allow_nv12_output) || source_is_i420) &&
- no_scaling_needed) {
- // |source_frame| already has correct pixel format and resolution.
- return source_frame;
- } else if (source_is_nv12 && allow_nv12_output) {
- // Output NV12 only if it is allowed and no conversion is needed.
- return MakeScaledNV12VideoFrame(std::move(source_frame),
- std::move(shared_resources));
- } else {
- return MakeScaledI420VideoFrame(std::move(source_frame),
- std::move(shared_resources));
- }
-}
-
-static void CreateContextProviderOnMainThread(
- scoped_refptr<viz::RasterContextProvider>* result,
- base::WaitableEvent* waitable_event) {
- *result = blink::Platform::Current()->SharedCompositorWorkerContextProvider();
- waitable_event->Signal();
-}
-
-} // anonymous namespace
-
-namespace blink {
-
-scoped_refptr<media::VideoFrame>
-LegacyWebRtcVideoFrameAdapter::SharedResources::CreateFrame(
- media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp) {
- return pool_.CreateFrame(format, coded_size, visible_rect, natural_size,
- timestamp);
-}
-
-scoped_refptr<media::VideoFrame>
-LegacyWebRtcVideoFrameAdapter::SharedResources::CreateTemporaryFrame(
- media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp) {
- return pool_for_tmp_frames_.CreateFrame(format, coded_size, visible_rect,
- natural_size, timestamp);
-}
-
-scoped_refptr<viz::RasterContextProvider>
-LegacyWebRtcVideoFrameAdapter::SharedResources::GetRasterContextProvider() {
- base::AutoLock auto_lock(context_provider_lock_);
- if (raster_context_provider_) {
- // Reuse created context provider if it's alive.
- viz::RasterContextProvider::ScopedRasterContextLock lock(
- raster_context_provider_.get());
- if (lock.RasterInterface()->GetGraphicsResetStatusKHR() == GL_NO_ERROR)
- return raster_context_provider_;
- }
-
- // Recreate the context provider.
- base::WaitableEvent waitable_event;
- PostCrossThreadTask(
- *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
- CrossThreadBindOnce(&CreateContextProviderOnMainThread,
- CrossThreadUnretained(&raster_context_provider_),
- CrossThreadUnretained(&waitable_event)));
-
- // This wait is necessary because this task is completed via main thread
- // asynchronously but WebRTC API is synchronous.
- base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
- waitable_event.Wait();
-
- return raster_context_provider_;
-}
-
-scoped_refptr<media::VideoFrame>
-LegacyWebRtcVideoFrameAdapter::SharedResources::ConstructVideoFrameFromTexture(
- scoped_refptr<media::VideoFrame> source_frame) {
- RTC_DCHECK(source_frame->HasTextures());
-
- scoped_refptr<viz::RasterContextProvider> raster_context_provider =
- GetRasterContextProvider();
- if (!raster_context_provider) {
- return nullptr;
- }
- viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
- raster_context_provider.get());
-
- auto* ri = scoped_context.RasterInterface();
- auto* gr_context = raster_context_provider->GrContext();
-
- if (!ri) {
- return nullptr;
- }
-
- return media::ReadbackTextureBackedFrameToMemorySync(
- *source_frame, ri, gr_context, &pool_for_mapped_frames_);
-}
-
-scoped_refptr<media::VideoFrame>
-LegacyWebRtcVideoFrameAdapter::SharedResources::ConstructVideoFrameFromGpu(
- scoped_refptr<media::VideoFrame> source_frame) {
- CHECK(source_frame);
- // NV12 is the only supported format.
- DCHECK_EQ(source_frame->format(), media::PIXEL_FORMAT_NV12);
- DCHECK_EQ(source_frame->storage_type(),
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
-
- // This is necessary because mapping may require waiting on IO thread,
- // but webrtc API is synchronous.
- base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
-
- return media::ConvertToMemoryMappedFrame(std::move(source_frame));
-}
-
-void LegacyWebRtcVideoFrameAdapter::SharedResources::SetFeedback(
- const media::VideoCaptureFeedback& feedback) {
- base::AutoLock auto_lock(feedback_lock_);
- last_feedback_ = feedback;
-}
-
-media::VideoCaptureFeedback
-LegacyWebRtcVideoFrameAdapter::SharedResources::GetFeedback() {
- base::AutoLock auto_lock(feedback_lock_);
- return last_feedback_;
-}
-
-LegacyWebRtcVideoFrameAdapter::SharedResources::SharedResources(
- media::GpuVideoAcceleratorFactories* gpu_factories)
- : gpu_factories_(gpu_factories) {}
-
-LegacyWebRtcVideoFrameAdapter::SharedResources::~SharedResources() = default;
-
-LegacyWebRtcVideoFrameAdapter::LegacyWebRtcVideoFrameAdapter(
- scoped_refptr<media::VideoFrame> frame)
- : LegacyWebRtcVideoFrameAdapter(frame, nullptr) {}
-
-LegacyWebRtcVideoFrameAdapter::LegacyWebRtcVideoFrameAdapter(
- scoped_refptr<media::VideoFrame> frame,
- scoped_refptr<SharedResources> shared_resources)
- : frame_(std::move(frame)), shared_resources_(shared_resources) {}
-
-LegacyWebRtcVideoFrameAdapter::~LegacyWebRtcVideoFrameAdapter() {
- if (shared_resources_) {
- shared_resources_->SetFeedback(
- media::VideoCaptureFeedback().RequireMapped(was_mapped_));
- }
-}
-
-webrtc::VideoFrameBuffer::Type LegacyWebRtcVideoFrameAdapter::type() const {
- return Type::kNative;
-}
-
-int LegacyWebRtcVideoFrameAdapter::width() const {
- return frame_->natural_size().width();
-}
-
-int LegacyWebRtcVideoFrameAdapter::height() const {
- return frame_->natural_size().height();
-}
-
-// static
-bool LegacyWebRtcVideoFrameAdapter::IsFrameAdaptable(
- const media::VideoFrame* frame) {
- // Currently accept I420, I420A, NV12 formats in a mapped frame,
- // or a texture or GPU memory buffer frame.
- return (frame->IsMappable() &&
- base::Contains(AdaptableMappablePixelFormats(), frame->format())) ||
- frame->storage_type() ==
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER ||
- frame->HasTextures();
-}
-
-// static
-base::span<const media::VideoPixelFormat>
-LegacyWebRtcVideoFrameAdapter::AdaptableMappablePixelFormats() {
- static constexpr const media::VideoPixelFormat
- kAdaptableMappablePixelFormats[] = {media::PIXEL_FORMAT_I420,
- media::PIXEL_FORMAT_I420A,
- media::PIXEL_FORMAT_NV12};
- return base::make_span(kAdaptableMappablePixelFormats);
-}
-
-rtc::scoped_refptr<webrtc::VideoFrameBuffer>
-LegacyWebRtcVideoFrameAdapter::CreateFrameAdapter() const {
- DCHECK(IsFrameAdaptable(frame_.get()))
- << "Can not create WebRTC frame adapter for frame "
- << frame_->AsHumanReadableString();
-
- was_mapped_ = true;
- if (frame_->storage_type() ==
- media::VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER) {
- auto video_frame =
- shared_resources_
- ? shared_resources_->ConstructVideoFrameFromGpu(frame_)
- : nullptr;
- video_frame = MaybeConvertAndScaleFrame(video_frame, shared_resources_);
- if (!video_frame) {
- return MakeFrameAdapter(media::VideoFrame::CreateColorFrame(
- frame_->natural_size(), 0u, 0x80, 0x80, frame_->timestamp()));
- }
- return MakeFrameAdapter(std::move(video_frame));
- } else if (frame_->HasTextures()) {
- auto video_frame =
- shared_resources_
- ? shared_resources_->ConstructVideoFrameFromTexture(frame_)
- : nullptr;
- video_frame = MaybeConvertAndScaleFrame(video_frame, shared_resources_);
- if (!video_frame) {
- DLOG(ERROR) << "Texture backed frame cannot be accessed.";
- return MakeFrameAdapter(media::VideoFrame::CreateColorFrame(
- frame_->natural_size(), 0u, 0x80, 0x80, frame_->timestamp()));
- }
- return MakeFrameAdapter(std::move(video_frame));
- }
-
- // Since scaling is required, hard-apply both the cropping and scaling
- // before we hand the frame over to WebRTC.
- scoped_refptr<media::VideoFrame> scaled_frame =
- MaybeConvertAndScaleFrame(frame_, shared_resources_);
- return MakeFrameAdapter(std::move(scaled_frame));
-}
-
-rtc::scoped_refptr<webrtc::I420BufferInterface>
-LegacyWebRtcVideoFrameAdapter::ToI420() {
- base::AutoLock auto_lock(adapter_lock_);
- if (!frame_adapter_) {
- frame_adapter_ = CreateFrameAdapter();
- }
- return frame_adapter_->ToI420();
-}
-
-rtc::scoped_refptr<webrtc::VideoFrameBuffer>
-LegacyWebRtcVideoFrameAdapter::GetMappedFrameBuffer(
- rtc::ArrayView<webrtc::VideoFrameBuffer::Type> types) {
- base::AutoLock auto_lock(adapter_lock_);
- if (!frame_adapter_) {
- frame_adapter_ = CreateFrameAdapter();
- }
- if (base::Contains(types, frame_adapter_->type())) {
- return frame_adapter_;
- }
- return nullptr;
-}
-
-rtc::scoped_refptr<webrtc::VideoFrameBuffer>
-LegacyWebRtcVideoFrameAdapter::CropAndScale(int offset_x,
- int offset_y,
- int crop_width,
- int crop_height,
- int scaled_width,
- int scaled_height) {
- base::AutoLock auto_lock(adapter_lock_);
- if (!frame_adapter_) {
- frame_adapter_ = CreateFrameAdapter();
- }
- return frame_adapter_->CropAndScale(offset_x, offset_y, crop_width,
- crop_height, scaled_width, scaled_height);
-}
-
-const webrtc::I420BufferInterface* LegacyWebRtcVideoFrameAdapter::GetI420()
- const {
- base::AutoLock auto_lock(adapter_lock_);
- if (!frame_adapter_) {
- frame_adapter_ = CreateFrameAdapter();
- }
- if (frame_adapter_->type() == webrtc::VideoFrameBuffer::Type::kI420) {
- return frame_adapter_->GetI420();
- }
- if (frame_adapter_->type() == webrtc::VideoFrameBuffer::Type::kI420A) {
- return frame_adapter_->GetI420A();
- }
- return nullptr;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h b/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h
deleted file mode 100644
index db3aca9eefe..00000000000
--- a/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h
+++ /dev/null
@@ -1,167 +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_WEBRTC_LEGACY_WEBRTC_VIDEO_FRAME_ADAPTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_LEGACY_WEBRTC_VIDEO_FRAME_ADAPTER_H_
-
-#include <stdint.h>
-
-#include "base/containers/span.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "components/viz/common/gpu/raster_context_provider.h"
-#include "media/base/video_frame.h"
-#include "media/base/video_frame_pool.h"
-#include "media/capture/video/video_capture_feedback.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
-#include "third_party/webrtc/api/video/video_frame_buffer.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace blink {
-
-// Thin adapter from media::VideoFrame to webrtc::VideoFrameBuffer. This
-// implementation is read-only and will return null if trying to get a
-// non-const pointer to the pixel data. This object will be accessed from
-// different threads, but that's safe since it's read-only.
-//
-// 3 types of frames can be adapted, either,
-// - The frame is mappable in either I420, I420A or NV12 pixel formats.
-// - Or, the frame is on a GPU Memory Buffer in NV12.
-// - Or, the frame has textures.
-// Creators of LegacyWebRtcVideoFrameAdapter can ensure the frame is convertible
-// by calling |IsFrameAdaptable| before constructing this object.
-class PLATFORM_EXPORT LegacyWebRtcVideoFrameAdapter
- : public WebRtcVideoFrameAdapterInterface {
- public:
- class PLATFORM_EXPORT SharedResources
- : public base::RefCountedThreadSafe<SharedResources> {
- public:
- explicit SharedResources(
- media::GpuVideoAcceleratorFactories* gpu_factories);
-
- // Create frames for requested output format and resolution.
- virtual scoped_refptr<media::VideoFrame> CreateFrame(
- media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp);
-
- // Temporary frames may have a different format or size than scaled frames.
- // However, VideoFramePool doesn't work nicely if the requested frame size
- // or format changes on the fly. Therefore a separate pool is used for
- // temporary frames.
- virtual scoped_refptr<media::VideoFrame> CreateTemporaryFrame(
- media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp);
-
- virtual scoped_refptr<viz::RasterContextProvider>
- GetRasterContextProvider();
-
- // Constructs a VideoFrame from a texture by invoking RasterInterface,
- // which would perform a blocking call to a GPU process.
- // The pixel data is copied and may be in ARGB pixel format in some cases,
- // So additional conversion to I420 would be needed.
- virtual scoped_refptr<media::VideoFrame> ConstructVideoFrameFromTexture(
- scoped_refptr<media::VideoFrame> source_frame);
-
- // Constructs a VideoFrame from a GMB. Unless it's a Windows DXGI GMB,
- // the buffer is mapped to the memory and wrapped by a VideoFrame with no
- // copies. For DXGI buffers a blocking call to GPU process is made to
- // copy pixel data.
- virtual scoped_refptr<media::VideoFrame> ConstructVideoFrameFromGpu(
- scoped_refptr<media::VideoFrame> source_frame);
-
- // Used to report feedback from an adapter upon destruction.
- void SetFeedback(const media::VideoCaptureFeedback& feedback);
-
- // Returns the most recently stored feedback.
- media::VideoCaptureFeedback GetFeedback();
-
- protected:
- friend class base::RefCountedThreadSafe<SharedResources>;
- virtual ~SharedResources();
-
- private:
- media::VideoFramePool pool_;
- media::VideoFramePool pool_for_mapped_frames_;
- media::VideoFramePool pool_for_tmp_frames_;
-
- base::Lock context_provider_lock_;
- scoped_refptr<viz::RasterContextProvider> raster_context_provider_
- GUARDED_BY(context_provider_lock_);
-
- media::GpuVideoAcceleratorFactories* gpu_factories_;
-
- base::Lock feedback_lock_;
-
- // Contains feedback from the most recently destroyed Adapter.
- media::VideoCaptureFeedback last_feedback_ GUARDED_BY(feedback_lock_);
- };
-
- // Returns true if |frame| is adaptable to a webrtc::VideoFrameBuffer.
- static bool IsFrameAdaptable(const media::VideoFrame* frame);
- static base::span<const media::VideoPixelFormat>
- AdaptableMappablePixelFormats();
-
- explicit LegacyWebRtcVideoFrameAdapter(
- scoped_refptr<media::VideoFrame> frame);
- LegacyWebRtcVideoFrameAdapter(
- scoped_refptr<media::VideoFrame> frame,
- scoped_refptr<SharedResources> shared_resources);
-
- bool SupportsOptimizedScaling() const override { return false; }
- scoped_refptr<media::VideoFrame> getMediaVideoFrame() const override {
- return frame_;
- }
-
- private:
- Type type() const override;
- int width() const override;
- int height() const override;
-
- rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override;
- const webrtc::I420BufferInterface* GetI420() const override;
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> GetMappedFrameBuffer(
- rtc::ArrayView<webrtc::VideoFrameBuffer::Type> types) override;
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> CropAndScale(
- int offset_x,
- int offset_y,
- int crop_width,
- int crop_height,
- int scaled_width,
- int scaled_height) override;
-
- protected:
- ~LegacyWebRtcVideoFrameAdapter() override;
-
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> CreateFrameAdapter() const;
-
- mutable base::Lock adapter_lock_;
-
- // Used to cache result of CreateFrameAdapter. Which is called from const
- // GetI420().
- mutable rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter_
- GUARDED_BY(adapter_lock_);
-
- scoped_refptr<media::VideoFrame> frame_;
-
- mutable scoped_refptr<SharedResources> shared_resources_;
-
- media::GpuVideoAcceleratorFactories* gpu_factories_;
-
- mutable bool was_mapped_ = false;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_LEGACY_WEBRTC_VIDEO_FRAME_ADAPTER_H_
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter_test.cc b/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter_test.cc
deleted file mode 100644
index 19885d347fd..00000000000
--- a/chromium/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter_test.cc
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h"
-
-#include "base/strings/strcat.h"
-#include "base/test/scoped_feature_list.h"
-#include "media/base/video_frame.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/platform/testing/video_frame_utils.h"
-#include "third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h"
-#include "third_party/webrtc/api/video/video_frame_buffer.h"
-#include "third_party/webrtc/rtc_base/ref_counted_object.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-using ::testing::_;
-using ::testing::Return;
-
-namespace blink {
-
-class LegacyWebRtcVideoFrameAdapterParamTest
- : public ::testing::TestWithParam<
- std::tuple<media::VideoFrame::StorageType, media::VideoPixelFormat>> {
- public:
- LegacyWebRtcVideoFrameAdapterParamTest()
- : resources_(
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr)) {}
-
- protected:
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources_;
-};
-
-namespace {
-std::vector<LegacyWebRtcVideoFrameAdapterParamTest::ParamType> TestParams() {
- std::vector<LegacyWebRtcVideoFrameAdapterParamTest::ParamType> test_params;
- // All formats for owned memory.
- for (media::VideoPixelFormat format :
- LegacyWebRtcVideoFrameAdapter::AdaptableMappablePixelFormats()) {
- test_params.emplace_back(
- media::VideoFrame::StorageType::STORAGE_OWNED_MEMORY, format);
- }
- test_params.emplace_back(
- media::VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER,
- media::VideoPixelFormat::PIXEL_FORMAT_NV12);
- return test_params;
-}
-} // namespace
-
-TEST_P(LegacyWebRtcVideoFrameAdapterParamTest, WidthAndHeight) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
-
- media::VideoFrame::StorageType storage_type = std::get<0>(GetParam());
- media::VideoPixelFormat pixel_format = std::get<1>(GetParam());
- scoped_refptr<media::VideoFrame> frame = CreateTestFrame(
- kCodedSize, kVisibleRect, kNaturalSize, storage_type, pixel_format);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter =
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(std::move(frame),
- resources_);
- EXPECT_EQ(frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(frame_adapter->height(), kNaturalSize.height());
-}
-
-TEST_P(LegacyWebRtcVideoFrameAdapterParamTest, ToI420) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
-
- media::VideoFrame::StorageType storage_type = std::get<0>(GetParam());
- media::VideoPixelFormat pixel_format = std::get<1>(GetParam());
- scoped_refptr<media::VideoFrame> frame = CreateTestFrame(
- kCodedSize, kVisibleRect, kNaturalSize, storage_type, pixel_format);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter =
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(std::move(frame),
- resources_);
-
- // The I420 frame should have the same size as the natural size.
- auto i420_frame = frame_adapter->ToI420();
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
-}
-
-INSTANTIATE_TEST_CASE_P(
- LegacyWebRtcVideoFrameAdapterParamTest,
- LegacyWebRtcVideoFrameAdapterParamTest,
- ::testing::ValuesIn(TestParams()),
- [](const auto& info) {
- return base::StrCat(
- {media::VideoFrame::StorageTypeToString(std::get<0>(info.param)), "_",
- media::VideoPixelFormatToString(std::get<1>(info.param))});
- });
-
-TEST(LegacyWebRtcVideoFrameAdapterTest, ToI420DownScaleGmb) {
- base::test::ScopedFeatureList scoped_feautre_list;
- scoped_feautre_list.InitAndDisableFeature(
- blink::features::kWebRtcLibvpxEncodeNV12);
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
- auto gmb_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by GpuMemoryBuffer.
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(gmb_frame), resources));
- EXPECT_EQ(gmb_frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(gmb_frame_adapter->height(), kNaturalSize.height());
-
- // The I420 frame should have the same size as the natural size
- auto i420_frame = gmb_frame_adapter->ToI420();
- ASSERT_TRUE(i420_frame);
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
- auto* get_i420_frame = gmb_frame_adapter->GetI420();
- ASSERT_TRUE(get_i420_frame);
- EXPECT_EQ(get_i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(get_i420_frame->height(), kNaturalSize.height());
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest, ToI420ADownScale) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by owned memory.
- auto owned_memory_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_OWNED_MEMORY,
- media::VideoPixelFormat::PIXEL_FORMAT_I420A);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> owned_memory_frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame), resources));
- EXPECT_EQ(owned_memory_frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(owned_memory_frame_adapter->height(), kNaturalSize.height());
-
- // The I420A frame should have the same size as the natural size
- auto i420a_frame = owned_memory_frame_adapter->ToI420();
- ASSERT_TRUE(i420a_frame);
- EXPECT_EQ(webrtc::VideoFrameBuffer::Type::kI420A, i420a_frame->type());
- EXPECT_EQ(i420a_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420a_frame->height(), kNaturalSize.height());
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest,
- Nv12WrapsGmbWhenNoScalingNeeededWithFeature) {
- base::test::ScopedFeatureList scoped_feautre_list;
- scoped_feautre_list.InitAndEnableFeature(
- blink::features::kWebRtcLibvpxEncodeNV12);
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- // Same size as visible rect so no scaling.
- const gfx::Size kNaturalSize = kVisibleRect.size();
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
-
- auto gmb_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by GpuMemoryBuffer.
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(gmb_frame,
- resources));
- EXPECT_EQ(gmb_frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(gmb_frame_adapter->height(), kNaturalSize.height());
-
- // Under feature, expect that the adapted frame is NV12 with frame should
- // have the same size as the natural size.
- std::vector<webrtc::VideoFrameBuffer::Type> nv12_type{
- webrtc::VideoFrameBuffer::Type::kNV12};
- auto nv12_frame = gmb_frame_adapter->GetMappedFrameBuffer(nv12_type);
- ASSERT_TRUE(nv12_frame);
- EXPECT_EQ(webrtc::VideoFrameBuffer::Type::kNV12, nv12_frame->type());
- EXPECT_EQ(nv12_frame->width(), kNaturalSize.width());
- EXPECT_EQ(nv12_frame->height(), kNaturalSize.height());
-
- // Even though we have an NV12 frame, ToI420 should return an I420 frame.
- std::vector<webrtc::VideoFrameBuffer::Type> i420_type{
- webrtc::VideoFrameBuffer::Type::kI420};
- EXPECT_FALSE(gmb_frame_adapter->GetMappedFrameBuffer(i420_type));
- auto i420_frame = gmb_frame_adapter->ToI420();
- ASSERT_TRUE(i420_frame);
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest, Nv12ScalesGmbWithFeature) {
- base::test::ScopedFeatureList scoped_feautre_list;
- scoped_feautre_list.InitAndEnableFeature(
- blink::features::kWebRtcLibvpxEncodeNV12);
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
-
- auto gmb_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by GpuMemoryBuffer.
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(gmb_frame,
- resources));
- EXPECT_EQ(gmb_frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(gmb_frame_adapter->height(), kNaturalSize.height());
-
- // Under feature, expect that the adapted frame is NV12 with frame should
- // have the same size as the natural size.
- std::vector<webrtc::VideoFrameBuffer::Type> nv12_type{
- webrtc::VideoFrameBuffer::Type::kNV12};
- auto nv12_frame = gmb_frame_adapter->GetMappedFrameBuffer(nv12_type);
- ASSERT_TRUE(nv12_frame);
- EXPECT_EQ(webrtc::VideoFrameBuffer::Type::kNV12, nv12_frame->type());
- EXPECT_EQ(nv12_frame->width(), kNaturalSize.width());
- EXPECT_EQ(nv12_frame->height(), kNaturalSize.height());
-
- // Even though we have an NV12 frame, ToI420 should return an I420 frame.
- std::vector<webrtc::VideoFrameBuffer::Type> i420_type{
- webrtc::VideoFrameBuffer::Type::kI420};
- EXPECT_FALSE(gmb_frame_adapter->GetMappedFrameBuffer(i420_type));
- auto i420_frame = gmb_frame_adapter->ToI420();
- ASSERT_TRUE(i420_frame);
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest, Nv12OwnedMemoryFrame) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize = kVisibleRect.size();
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by owned memory.
- auto owned_memory_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_OWNED_MEMORY,
- media::VideoPixelFormat::PIXEL_FORMAT_NV12);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> owned_memory_frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame), resources));
- EXPECT_EQ(owned_memory_frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(owned_memory_frame_adapter->height(), kNaturalSize.height());
-
- // The NV12 frame should have the same size as the visible rect size
- std::vector<webrtc::VideoFrameBuffer::Type> nv12_type{
- webrtc::VideoFrameBuffer::Type::kNV12};
- auto nv12_frame = owned_memory_frame_adapter->GetMappedFrameBuffer(nv12_type);
- ASSERT_TRUE(nv12_frame);
- EXPECT_EQ(webrtc::VideoFrameBuffer::Type::kNV12, nv12_frame->type());
- EXPECT_EQ(nv12_frame->width(), kVisibleRect.size().width());
- EXPECT_EQ(nv12_frame->height(), kVisibleRect.size().height());
-}
-
-// The default implementation of CropAndScale() is "ToI420() + scaling". This
-// test verifies that CropAndScale() is overridden not to convert when scaling.
-TEST(LegacyWebRtcVideoFrameAdapterTest, ScalingDoesNotConvertToI420) {
- const gfx::Size kFullSize(1280, 960);
- const gfx::Size kHalfSize(640, 480);
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
-
- auto owned_memory_frame =
- CreateTestFrame(kFullSize, gfx::Rect(kFullSize), kFullSize,
- media::VideoFrame::STORAGE_OWNED_MEMORY,
- media::VideoPixelFormat::PIXEL_FORMAT_NV12);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame), resources));
-
- // Scale the frame.
- auto scaled_frame = adapter->Scale(kHalfSize.width(), kHalfSize.height());
- // It would also be correct to return a kNative frame that when mapped returns
- // kNV12 - this is what the modern adapter does. But the legacy adapter
- // implementation maps as part of scaling.
- EXPECT_EQ(scaled_frame->type(), webrtc::VideoFrameBuffer::Type::kNV12);
- EXPECT_EQ(scaled_frame->width(), kHalfSize.width());
- EXPECT_EQ(scaled_frame->height(), kHalfSize.height());
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest, Nv12ScaleOwnedMemoryFrame) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
- scoped_refptr<LegacyWebRtcVideoFrameAdapter::SharedResources> resources =
- new LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by owned memory.
- auto owned_memory_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_OWNED_MEMORY,
- media::VideoPixelFormat::PIXEL_FORMAT_NV12);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> owned_memory_frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame), resources));
- EXPECT_EQ(owned_memory_frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(owned_memory_frame_adapter->height(), kNaturalSize.height());
-
- // The NV12 frame should have the same size as the natural size.
- std::vector<webrtc::VideoFrameBuffer::Type> nv12_type{
- webrtc::VideoFrameBuffer::Type::kNV12};
- auto nv12_frame = owned_memory_frame_adapter->GetMappedFrameBuffer(nv12_type);
- ASSERT_TRUE(nv12_frame);
- EXPECT_EQ(webrtc::VideoFrameBuffer::Type::kNV12, nv12_frame->type());
- EXPECT_EQ(nv12_frame->width(), kNaturalSize.width());
- EXPECT_EQ(nv12_frame->height(), kNaturalSize.height());
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest,
- TextureFrameIsBlackWithNoSharedResources) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by owned memory.
- auto owned_memory_frame = CreateTestFrame(
- kCodedSize, kVisibleRect, kNaturalSize, media::VideoFrame::STORAGE_OPAQUE,
- media::VideoPixelFormat::PIXEL_FORMAT_NV12);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame), nullptr));
- EXPECT_EQ(frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(frame_adapter->height(), kNaturalSize.height());
-
- // The NV12 frame should have the same size as the natural size, but be black
- // since we can't handle the texture with no shared resources.
- auto i420_frame = frame_adapter->ToI420();
- ASSERT_TRUE(i420_frame);
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
- EXPECT_EQ(0x0, i420_frame->DataY()[0]);
- EXPECT_EQ(0x80, i420_frame->DataU()[0]);
- EXPECT_EQ(0x80, i420_frame->DataV()[0]);
-}
-
-TEST(LegacyWebRtcVideoFrameAdapterTest,
- ConvertsTextureFrameWithSharedResources) {
- const gfx::Size kCodedSize(1280, 960);
- const gfx::Rect kVisibleRect(0, 120, 1280, 720);
- const gfx::Size kNaturalSize(640, 360);
-
- scoped_refptr<MockLegacySharedResources> resources =
- base::MakeRefCounted<MockLegacySharedResources>();
-
- // The adapter should report width and height from the natural size for
- // VideoFrame backed by owned memory.
- auto owned_memory_frame = CreateTestFrame(
- kCodedSize, kVisibleRect, kNaturalSize, media::VideoFrame::STORAGE_OPAQUE,
- media::VideoPixelFormat::PIXEL_FORMAT_NV12);
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter(
- new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame), resources));
- EXPECT_EQ(frame_adapter->width(), kNaturalSize.width());
- EXPECT_EQ(frame_adapter->height(), kNaturalSize.height());
-
- scoped_refptr<media::VideoFrame> memory_frame =
- CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
- media::VideoFrame::STORAGE_OWNED_MEMORY,
- media::VideoPixelFormat::PIXEL_FORMAT_ARGB);
- // fill mock image with whilte color.
- memset(memory_frame->data(media::VideoFrame::kARGBPlane), 0xFF,
- kCodedSize.GetArea() * 4);
-
- // Should call texture conversion.
- resources->ExpectCreateFrameWithRealImplementation();
- resources->ExpectCreateTemporaryFrameWithRealImplementation();
- EXPECT_CALL(*resources, ConstructVideoFrameFromTexture(_))
- .WillOnce(Return(memory_frame));
-
- // The NV12 frame should have the same size as the natural size, but be black
- // since we can't handle the texture with no shared resources.
- auto i420_frame = frame_adapter->ToI420();
- ASSERT_TRUE(i420_frame);
- EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
- EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
- // Returned memory frame should not be replaced by a black frame.
- EXPECT_NE(0x0, i420_frame->DataY()[0]);
-}
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
index b968981cf1b..4daf0d82ff9 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
@@ -140,28 +140,28 @@ void PeerConnectionRemoteAudioSource::OnData(const void* audio_data,
// TODO(tommi): We should get the timestamp from WebRTC.
base::TimeTicks playout_time(base::TimeTicks::Now());
- if (!audio_bus_ ||
- static_cast<size_t>(audio_bus_->channels()) != number_of_channels ||
- static_cast<size_t>(audio_bus_->frames()) != number_of_frames) {
- audio_bus_ = media::AudioBus::Create(number_of_channels, number_of_frames);
+ int channels_int = base::checked_cast<int>(number_of_channels);
+ int frames_int = base::checked_cast<int>(number_of_frames);
+ if (!audio_bus_ || audio_bus_->channels() != channels_int ||
+ audio_bus_->frames() != frames_int) {
+ audio_bus_ = media::AudioBus::Create(channels_int, frames_int);
}
// Only 16 bits per sample is ever used. The FromInterleaved() call should
// be updated if that is no longer the case.
DCHECK_EQ(bits_per_sample, 16);
audio_bus_->FromInterleaved<media::SignedInt16SampleTypeTraits>(
- reinterpret_cast<const int16_t*>(audio_data), number_of_frames);
+ reinterpret_cast<const int16_t*>(audio_data), frames_int);
media::AudioParameters params = MediaStreamAudioSource::GetAudioParameters();
if (!params.IsValid() ||
params.format() != media::AudioParameters::AUDIO_PCM_LOW_LATENCY ||
- static_cast<size_t>(params.channels()) != number_of_channels ||
+ params.channels() != channels_int ||
params.sample_rate() != sample_rate ||
- static_cast<size_t>(params.frames_per_buffer()) != number_of_frames) {
- MediaStreamAudioSource::SetFormat(
- media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::GuessChannelLayout(number_of_channels),
- sample_rate, number_of_frames));
+ params.frames_per_buffer() != frames_int) {
+ MediaStreamAudioSource::SetFormat(media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::GuessChannelLayout(channels_int), sample_rate, frames_int));
}
MediaStreamAudioSource::DeliverDataToTracks(*audio_bus_, playout_time);
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h
index b831df797b2..d9451b3c652 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h
@@ -27,6 +27,10 @@ class PLATFORM_EXPORT PeerConnectionRemoteAudioTrack final
public:
explicit PeerConnectionRemoteAudioTrack(
scoped_refptr<webrtc::AudioTrackInterface> track_interface);
+ PeerConnectionRemoteAudioTrack(const PeerConnectionRemoteAudioTrack&) =
+ delete;
+ PeerConnectionRemoteAudioTrack& operator=(
+ const PeerConnectionRemoteAudioTrack&) = delete;
~PeerConnectionRemoteAudioTrack() final;
// If |track| is an instance of PeerConnectionRemoteAudioTrack, return a
@@ -49,8 +53,6 @@ class PLATFORM_EXPORT PeerConnectionRemoteAudioTrack final
// In debug builds, check that all methods that could cause object graph
// or data flow changes are being called on the main thread.
THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(PeerConnectionRemoteAudioTrack);
};
// Represents the audio provided by the receiving end of a PeerConnection.
@@ -61,6 +63,10 @@ class PLATFORM_EXPORT PeerConnectionRemoteAudioSource final
PeerConnectionRemoteAudioSource(
scoped_refptr<webrtc::AudioTrackInterface> track_interface,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ PeerConnectionRemoteAudioSource(const PeerConnectionRemoteAudioSource&) =
+ delete;
+ PeerConnectionRemoteAudioSource& operator=(
+ const PeerConnectionRemoteAudioSource&) = delete;
~PeerConnectionRemoteAudioSource() final;
protected:
@@ -98,8 +104,6 @@ class PLATFORM_EXPORT PeerConnectionRemoteAudioSource final
#ifndef NDEBUG
base::Lock single_audio_thread_guard_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(PeerConnectionRemoteAudioSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h b/chromium/third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h
index 58652f13993..cb1e9f3d0de 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/testing/mock_webrtc_video_frame_adapter_shared_resources.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_TESTING_MOCK_WEBRTC_VIDEO_FRAME_ADAPTER_SHARED_RESOURCES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_TESTING_MOCK_WEBRTC_VIDEO_FRAME_ADAPTER_SHARED_RESOURCES_H_
-#include "third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -71,68 +70,6 @@ class MockSharedResources : public WebRtcVideoFrameAdapter::SharedResources {
friend class base::RefCountedThreadSafe<MockSharedResources>;
};
-class MockLegacySharedResources
- : public LegacyWebRtcVideoFrameAdapter::SharedResources {
- public:
- MockLegacySharedResources()
- : LegacyWebRtcVideoFrameAdapter::SharedResources(nullptr) {}
-
- MOCK_METHOD(scoped_refptr<media::VideoFrame>,
- CreateFrame,
- (media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp));
-
- MOCK_METHOD(scoped_refptr<media::VideoFrame>,
- CreateTemporaryFrame,
- (media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp));
-
- MOCK_METHOD(scoped_refptr<viz::RasterContextProvider>,
- GetRasterContextProvider,
- ());
-
- MOCK_METHOD(scoped_refptr<media::VideoFrame>,
- ConstructVideoFrameFromTexture,
- (scoped_refptr<media::VideoFrame> source_frame));
-
- MOCK_METHOD(scoped_refptr<media::VideoFrame>,
- ConstructVideoFrameFromGpu,
- (scoped_refptr<media::VideoFrame> source_frame));
-
- void ExpectCreateFrameWithRealImplementation() {
- EXPECT_CALL(*this, CreateFrame)
- .WillOnce(testing::Invoke([this](media::VideoPixelFormat format,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- base::TimeDelta timestamp) {
- return LegacyWebRtcVideoFrameAdapter::SharedResources::CreateFrame(
- format, coded_size, visible_rect, natural_size, timestamp);
- }));
- }
-
- void ExpectCreateTemporaryFrameWithRealImplementation() {
- EXPECT_CALL(*this, CreateTemporaryFrame)
- .WillOnce(testing::Invoke(
- [this](media::VideoPixelFormat format, const gfx::Size& coded_size,
- const gfx::Rect& visible_rect, const gfx::Size& natural_size,
- base::TimeDelta timestamp) {
- return LegacyWebRtcVideoFrameAdapter::SharedResources::
- CreateTemporaryFrame(format, coded_size, visible_rect,
- natural_size, timestamp);
- }));
- }
-
- private:
- friend class base::RefCountedThreadSafe<MockLegacySharedResources>;
-};
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_TESTING_MOCK_WEBRTC_VIDEO_FRAME_ADAPTER_SHARED_RESOURCES_H_
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/track_observer.h b/chromium/third_party/blink/renderer/platform/webrtc/track_observer.h
index 86237deff20..38ff13a2975 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/track_observer.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/track_observer.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_TRACK_OBSERVER_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -18,6 +17,8 @@ class PLATFORM_EXPORT TrackObserver {
public:
TrackObserver(const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
const scoped_refptr<webrtc::MediaStreamTrackInterface>& track);
+ TrackObserver(const TrackObserver&) = delete;
+ TrackObserver& operator=(const TrackObserver&) = delete;
~TrackObserver();
using OnChangedCallback = base::RepeatingCallback<void(
@@ -29,7 +30,6 @@ class PLATFORM_EXPORT TrackObserver {
private:
class TrackObserverImpl;
const scoped_refptr<TrackObserverImpl> observer_;
- DISALLOW_COPY_AND_ASSIGN(TrackObserver);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_logging.cc b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_logging.cc
index 7b34ece401e..56266530029 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_logging.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_logging.cc
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <inttypes.h>
+
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "third_party/webrtc_overrides/rtc_base/logging.h"
@@ -31,4 +34,36 @@ void WebRtcLogMessage(const std::string& message) {
g_webrtc_logging_delegate->LogMessage(message);
}
+void WebRtcLog(const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ std::string msg(base::StringPrintV(format, args));
+ va_end(args);
+ WebRtcLogMessage(msg);
+}
+
+void WebRtcLog(void* thiz, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ std::string msg(base::StringPrintV(format, args));
+ va_end(args);
+ base::StringAppendF(&msg, " [this=0x%" PRIXPTR "]",
+ reinterpret_cast<uintptr_t>(thiz));
+ WebRtcLogMessage(msg);
+}
+
+void BLINK_PLATFORM_EXPORT WebRtcLog(const char* prefix,
+ void* thiz,
+ const char* format,
+ ...) {
+ va_list args;
+ va_start(args, format);
+ std::string msg(prefix);
+ base::StringAppendV(&msg, format, args);
+ va_end(args);
+ base::StringAppendF(&msg, " [this=0x%" PRIXPTR "]",
+ reinterpret_cast<uintptr_t>(thiz));
+ WebRtcLogMessage(msg);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h
index ac942e2642a..376d8655a65 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h
@@ -28,7 +28,7 @@ class PLATFORM_EXPORT WebRtcAudioRendererSource {
// |audio_bus| must have buffer size |sample_rate/100| and 1-2 channels.
virtual void RenderData(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds,
+ base::TimeDelta audio_delay,
base::TimeDelta* current_time) = 0;
// Callback to notify the client that the renderer is going away.
@@ -63,7 +63,7 @@ class PLATFORM_EXPORT WebRtcPlayoutDataSource {
// |audio_bus| must have buffer size |sample_rate/100| and 1-2 channels.
virtual void OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
- int audio_delay_milliseconds) = 0;
+ base::TimeDelta audio_delay) = 0;
// Callback to notify the sink that the source has changed.
// Called on the main render thread.
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
index 069b4333b90..80850986a72 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
@@ -17,23 +17,12 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.h"
-#include "third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
#include "ui/gfx/geometry/size.h"
namespace blink {
-const base::Feature kWebRtcUseModernFrameAdapter{
- "WebRtcUseModernFrameAdapter", base::FEATURE_DISABLED_BY_DEFAULT};
-
-rtc::scoped_refptr<WebRtcVideoFrameAdapterInterface>
-CreateWebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame) {
- if (base::FeatureList::IsEnabled(kWebRtcUseModernFrameAdapter))
- return new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame);
- return new rtc::RefCountedObject<LegacyWebRtcVideoFrameAdapter>(frame);
-}
-
namespace {
bool IsApproxEquals(int a, int b) {
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h
index 0e8b8e50280..9d1a0c07aac 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h
@@ -25,29 +25,6 @@
namespace blink {
-// Controls whether to use the WebRtcVideoFrameAdapter or the
-// LegacyWebRtcVideoFrameAdapter as the adapter of media::VideoFrames.
-PLATFORM_EXPORT extern const base::Feature kWebRtcUseModernFrameAdapter;
-
-// TODO(https://crbug.com/1191986): When kWebRtcUseModernFrameAdapter is shipped
-// to 100%, delete the legacy adapter and this interface.
-class PLATFORM_EXPORT WebRtcVideoFrameAdapterInterface
- : public webrtc::VideoFrameBuffer {
- public:
- WebRtcVideoFrameAdapterInterface() = default;
- ~WebRtcVideoFrameAdapterInterface() override = default;
-
- virtual bool SupportsOptimizedScaling() const = 0;
- virtual scoped_refptr<media::VideoFrame> getMediaVideoFrame() const = 0;
-};
-
-// Constructs a WebRtcVideoFrameAdapter or LegacyWebRtcVideoFrameAdapter with
-// null passed in as the shared resources. In order to pass in the type-specific
-// shared resources you need to manually check if kWebRtcUseModernFrameAdapter
-// is enabled and invoke the type-specific constructor.
-PLATFORM_EXPORT rtc::scoped_refptr<WebRtcVideoFrameAdapterInterface>
-CreateWebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame);
-
// The WebRtcVideoFrameAdapter implements webrtc::VideoFrameBuffer and is backed
// by one or more media::VideoFrames.
// * Upon CropAndScale(), the crop and scale values are soft-applied.
@@ -68,7 +45,7 @@ CreateWebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame);
// or to the frame feeddback so that we may optionally use this information to
// optimize future captured frames for these sizes.
class PLATFORM_EXPORT WebRtcVideoFrameAdapter
- : public WebRtcVideoFrameAdapterInterface {
+ : public webrtc::VideoFrameBuffer {
public:
class PLATFORM_EXPORT SharedResources
: public base::RefCountedThreadSafe<SharedResources> {
@@ -207,10 +184,7 @@ class PLATFORM_EXPORT WebRtcVideoFrameAdapter
std::vector<scoped_refptr<media::VideoFrame>> scaled_frames,
scoped_refptr<SharedResources> shared_resources);
- bool SupportsOptimizedScaling() const override { return true; }
- scoped_refptr<media::VideoFrame> getMediaVideoFrame() const override {
- return frame_;
- }
+ scoped_refptr<media::VideoFrame> getMediaVideoFrame() const { return frame_; }
// Regardless of the pixel format used internally, kNative is returned
// indicating that GetMappedFrameBuffer() or ToI420() is required to obtain
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.cc b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.cc
index 008844b3611..7f291c792a3 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.cc
@@ -4,7 +4,31 @@
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h"
+#include "third_party/webrtc/api/video_codecs/h264_profile_level_id.h"
+#include "third_party/webrtc/api/video_codecs/video_codec.h"
+#include "third_party/webrtc/api/video_codecs/vp9_profile.h"
+
namespace blink {
+namespace {
+struct ScalabilityModeSpatialLayers {
+ const char* name;
+ int spatial_layers;
+};
+
+constexpr ScalabilityModeSpatialLayers kSvcSpatialLayers[] = {
+ {"L1T2", 1}, {"L1T3", 1}, {"L2T1", 2},
+ {"L2T2", 2}, {"L2T3", 2}, {"L2T1h", 2},
+ {"L2T2h", 2}, {"L2T3h", 2}, {"S2T1", 2},
+ {"S2T2", 2}, {"S2T3", 2}, {"S2T1h", 2},
+ {"S2T2h", 2}, {"S2T3h", 2}, {"L3T1", 3},
+ {"L3T2", 3}, {"L3T3", 3}, {"S3T1", 3},
+ {"S3T2", 3}, {"S3T3", 3}, {"S3T1h", 3},
+ {"S3T2h", 3}, {"S3T3h", 3}, {"L2T2_KEY", 3},
+ {"L2T2_KEY_SHIFT", 3}, {"L2T3_KEY", 3}, {"L2T3_KEY_SHIFT", 3},
+ {"L3T2_KEY", 3}, {"L3T2_KEY_SHIFT", 3}, {"L3T3_KEY", 3},
+};
+
+} // namespace
media::VideoRotation WebRtcToMediaVideoRotation(
webrtc::VideoRotation rotation) {
@@ -36,6 +60,58 @@ media::VideoCodec WebRtcToMediaVideoCodec(webrtc::VideoCodecType codec) {
}
}
+media::VideoCodecProfile WebRtcVideoFormatToMediaVideoCodecProfile(
+ const webrtc::SdpVideoFormat& format) {
+ const webrtc::VideoCodecType video_codec_type =
+ webrtc::PayloadStringToCodecType(format.name);
+ switch (video_codec_type) {
+ case webrtc::kVideoCodecAV1:
+ return media::AV1PROFILE_PROFILE_MAIN;
+ case webrtc::kVideoCodecVP8:
+ return media::VP8PROFILE_ANY;
+ case webrtc::kVideoCodecVP9: {
+ const absl::optional<webrtc::VP9Profile> vp9_profile =
+ webrtc::ParseSdpForVP9Profile(format.parameters);
+ // The return value is absl::nullopt if the profile-id is specified
+ // but its value is invalid.
+ if (!vp9_profile) {
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+ switch (*vp9_profile) {
+ case webrtc::VP9Profile::kProfile2:
+ return media::VP9PROFILE_PROFILE2;
+ case webrtc::VP9Profile::kProfile1:
+ return media::VP9PROFILE_PROFILE1;
+ case webrtc::VP9Profile::kProfile0:
+ default:
+ return media::VP9PROFILE_PROFILE0;
+ }
+ }
+ case webrtc::kVideoCodecH264: {
+ const absl::optional<webrtc::H264ProfileLevelId> h264_profile_level_id =
+ webrtc::ParseSdpForH264ProfileLevelId(format.parameters);
+ // The return value is absl::nullopt if the profile-level-id is specified
+ // but its value is invalid.
+ if (!h264_profile_level_id) {
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+ switch (h264_profile_level_id->profile) {
+ case webrtc::H264Profile::kProfileMain:
+ return media::H264PROFILE_MAIN;
+ case webrtc::H264Profile::kProfileConstrainedHigh:
+ case webrtc::H264Profile::kProfileHigh:
+ return media::H264PROFILE_HIGH;
+ case webrtc::H264Profile::kProfileConstrainedBaseline:
+ case webrtc::H264Profile::kProfileBaseline:
+ default:
+ return media::H264PROFILE_BASELINE;
+ }
+ }
+ default:
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+}
+
media::VideoColorSpace WebRtcToMediaVideoColorSpace(
const webrtc::ColorSpace& color_space) {
media::VideoColorSpace::PrimaryID primaries =
@@ -185,4 +261,14 @@ media::VideoColorSpace WebRtcToMediaVideoColorSpace(
return media::VideoColorSpace(primaries, transfer, matrix, range);
}
+absl::optional<int> WebRtcScalabilityModeSpatialLayers(
+ const std::string& scalability_mode) {
+ for (const auto& entry : kSvcSpatialLayers) {
+ if (entry.name == scalability_mode) {
+ return entry.spatial_layers;
+ }
+ }
+ return absl::nullopt;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h
index ba5c3552ae1..8bc53e01385 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h
@@ -12,6 +12,7 @@
#include "third_party/webrtc/api/video/color_space.h"
#include "third_party/webrtc/api/video/video_codec_type.h"
#include "third_party/webrtc/api/video/video_rotation.h"
+#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
namespace blink {
@@ -24,9 +25,16 @@ WebRtcToMediaVideoRotation(webrtc::VideoRotation rotation);
media::VideoCodec PLATFORM_EXPORT
WebRtcToMediaVideoCodec(webrtc::VideoCodecType codec);
+// Map webrtc::SdpVideoFormat to the same or closest media::VideoCodecProfile.
+media::VideoCodecProfile PLATFORM_EXPORT
+WebRtcVideoFormatToMediaVideoCodecProfile(const webrtc::SdpVideoFormat& format);
+
media::VideoColorSpace PLATFORM_EXPORT
WebRtcToMediaVideoColorSpace(const webrtc::ColorSpace& color_space);
+absl::optional<int> PLATFORM_EXPORT
+WebRtcScalabilityModeSpatialLayers(const std::string& scalability_mode);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_WEBRTC_VIDEO_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/platform/widget/DEPS b/chromium/third_party/blink/renderer/platform/widget/DEPS
index cd9ab15a809..08ff512a48e 100644
--- a/chromium/third_party/blink/renderer/platform/widget/DEPS
+++ b/chromium/third_party/blink/renderer/platform/widget/DEPS
@@ -8,10 +8,11 @@ include_rules = [
"+gpu/command_buffer/common/context_creation_attribs.h",
"+gpu/ipc/client/gpu_channel_host.h",
"+services/viz/public/cpp/gpu/context_provider_command_buffer.h",
- "+ui/gfx/mojom/delegated_ink_metadata.mojom-blink.h",
"+services/viz/public/mojom/compositing/frame_sink_id.mojom-blink.h",
"+ui/base/ime/text_input_mode.h",
"+ui/base/ime/text_input_type.h",
"+ui/base/ime/mojom/text_input_state.mojom-blink.h",
- "+ui/base/ime/mojom/virtual_keyboard_types.mojom-blink.h"
+ "+ui/base/ime/mojom/virtual_keyboard_types.mojom-blink.h",
+ "+ui/display/screen_info.h",
+ "+ui/gfx/mojom/delegated_ink_metadata.mojom-blink.h",
]
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.cc b/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.cc
index b75a25ec16e..eafaad76038 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.cc
@@ -11,7 +11,6 @@
#include "base/check.h"
#include "base/command_line.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/notreached.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -56,6 +55,8 @@ const size_t kNumResourcesLimit = 10 * 1000 * 1000;
class SoftwareDevice : public viz::SoftwareOutputDevice {
public:
SoftwareDevice(SkCanvas** canvas) : canvas_(canvas) {}
+ SoftwareDevice(const SoftwareDevice&) = delete;
+ SoftwareDevice& operator=(const SoftwareDevice&) = delete;
void Resize(const gfx::Size& pixel_size, float device_scale_factor) override {
// Intentional no-op: canvas size is controlled by the embedder.
@@ -68,8 +69,6 @@ class SoftwareDevice : public viz::SoftwareOutputDevice {
private:
SkCanvas** canvas_;
-
- DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
};
// This is used with resourceless software draws.
@@ -77,6 +76,10 @@ class SoftwareCompositorFrameSinkClient
: public viz::mojom::CompositorFrameSinkClient {
public:
SoftwareCompositorFrameSinkClient() = default;
+ SoftwareCompositorFrameSinkClient(const SoftwareCompositorFrameSinkClient&) =
+ delete;
+ SoftwareCompositorFrameSinkClient& operator=(
+ const SoftwareCompositorFrameSinkClient&) = delete;
~SoftwareCompositorFrameSinkClient() override = default;
void DidReceiveCompositorFrameAck(
@@ -92,9 +95,6 @@ class SoftwareCompositorFrameSinkClient
void OnBeginFramePausedChanged(bool paused) override {}
void OnCompositorFrameTransitionDirectiveProcessed(
uint32_t sequence_id) override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SoftwareCompositorFrameSinkClient);
};
} // namespace
@@ -298,6 +298,13 @@ void SynchronousLayerTreeFrameSink::SubmitCompositorFrame(
device_scale_factor_ = frame.metadata.device_scale_factor;
}
+ power_mode_voter_.OnFrameProduced(frame.render_pass_list.back()->damage_rect,
+ frame.device_scale_factor());
+
+ // Reset the timestamp to null so that the next BeginFrame marks the time when
+ // it is called.
+ nop_animation_timeout_start_ = base::TimeTicks();
+
if (in_software_draw_) {
// The frame we send to the client is actually just the metadata. Preserve
// the |frame| for the software path below.
@@ -398,12 +405,6 @@ void SynchronousLayerTreeFrameSink::SubmitCompositorFrame(
}
}
- power_mode_voter_.OnFrameProduced();
-
- // Reset the timestamp to null so that the next BeginFrame marks the time when
- // it is called.
- nop_animation_timeout_start_ = base::TimeTicks();
-
// NOTE: submit_frame will be empty if viz_frame_submission_enabled_ enabled,
// but it won't be used upstream
// Because OnDraw can synchronously override the viewport without going
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.h b/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.h
index 4129ecc82b3..575261a161e 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.h
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
@@ -92,6 +91,9 @@ class SynchronousLayerTreeFrameSink
compositor_frame_sink_remote,
mojo::PendingReceiver<viz::mojom::blink::CompositorFrameSinkClient>
client_receiver);
+ SynchronousLayerTreeFrameSink(const SynchronousLayerTreeFrameSink&) = delete;
+ SynchronousLayerTreeFrameSink& operator=(
+ const SynchronousLayerTreeFrameSink&) = delete;
~SynchronousLayerTreeFrameSink() override;
// cc::LayerTreeFrameSink implementation.
@@ -232,8 +234,6 @@ class SynchronousLayerTreeFrameSink
base::TimeTicks nop_animation_timeout_start_;
power_scheduler::FrameProductionPowerModeVoter power_mode_voter_;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousLayerTreeFrameSink);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
index f5751beeb39..083e7c6d495 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
@@ -514,16 +514,8 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
settings.disallow_non_exact_resource_reuse = true;
#endif
- settings.enable_impl_latency_recovery =
- ::features::IsImplLatencyRecoveryEnabled();
- settings.enable_main_latency_recovery =
- ::features::IsMainLatencyRecoveryEnabled();
-
- if (cmd.HasSwitch(::switches::kRunAllCompositorStagesBeforeDraw)) {
- settings.wait_for_all_pipeline_stages_before_draw = true;
- settings.enable_impl_latency_recovery = false;
- settings.enable_main_latency_recovery = false;
- }
+ settings.wait_for_all_pipeline_stages_before_draw =
+ cmd.HasSwitch(::switches::kRunAllCompositorStagesBeforeDraw);
settings.enable_image_animation_resync =
!cmd.HasSwitch(switches::kDisableImageAnimationResync);
@@ -539,8 +531,8 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
// Disable occlusion if de-jelly effect is enabled.
settings.enable_occlusion &= !settings.allow_de_jelly_effect;
- settings.enable_transform_interop =
- base::FeatureList::IsEnabled(features::kTransformInterop);
+ settings.enable_backface_visibility_interop =
+ RuntimeEnabledFeatures::BackfaceVisibilityInteropEnabled();
return settings;
}
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
index 155a1f40552..73e70b80b43 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
@@ -32,6 +32,7 @@
#include "cc/metrics/web_vital_metrics.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_mutator.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/render_frame_metadata_observer.h"
#include "cc/trees/swap_promise.h"
#include "cc/trees/ukm_manager.h"
@@ -202,10 +203,11 @@ void LayerTreeView::OnDeferMainFrameUpdatesChanged(bool status) {
delegate_->OnDeferMainFrameUpdatesChanged(status);
}
-void LayerTreeView::OnDeferCommitsChanged(bool status) {
+void LayerTreeView::OnDeferCommitsChanged(bool status,
+ cc::PaintHoldingReason reason) {
if (!delegate_)
return;
- delegate_->OnDeferCommitsChanged(status);
+ delegate_->OnDeferCommitsChanged(status, reason);
}
void LayerTreeView::BeginMainFrameNotExpectedSoon() {
@@ -309,6 +311,9 @@ void LayerTreeView::DidPresentCompositorFrame(
DCHECK(layer_tree_host_->GetTaskRunnerProvider()
->MainThreadTaskRunner()
->RunsTasksInCurrentSequence());
+ // Only run callbacks on successful presentations.
+ if (feedback.failed())
+ return;
while (!presentation_callbacks_.empty()) {
const auto& front = presentation_callbacks_.begin();
if (viz::FrameTokenGT(front->first, frame_token))
@@ -406,7 +411,7 @@ void LayerTreeView::AddPresentationCallback(
}
std::vector<base::OnceCallback<void(base::TimeTicks)>> callbacks;
callbacks.push_back(std::move(callback));
- presentation_callbacks_.push_back({frame_token, std::move(callbacks)});
+ presentation_callbacks_.emplace_back(frame_token, std::move(callbacks));
DCHECK_LE(presentation_callbacks_.size(), 25u);
}
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
index 4a17a421ddb..bf7bed78428 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
@@ -15,6 +15,7 @@
#include "cc/input/browser_controls_state.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/swap_promise.h"
#include "cc/trees/swap_promise_monitor.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -48,6 +49,8 @@ class PLATFORM_EXPORT LayerTreeView
public:
LayerTreeView(LayerTreeViewDelegate* delegate,
scheduler::WebThreadScheduler* scheduler);
+ LayerTreeView(const LayerTreeView&) = delete;
+ LayerTreeView& operator=(const LayerTreeView&) = delete;
~LayerTreeView() override;
// The |main_thread| is the task runner that the compositor will use for the
@@ -78,7 +81,8 @@ class PLATFORM_EXPORT LayerTreeView
void DidUpdateLayers() override;
void BeginMainFrame(const viz::BeginFrameArgs& args) override;
void OnDeferMainFrameUpdatesChanged(bool) override;
- void OnDeferCommitsChanged(bool) override;
+ void OnDeferCommitsChanged(bool defer_status,
+ cc::PaintHoldingReason reason) override;
void BeginMainFrameNotExpectedSoon() override;
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
void UpdateLayerTreeHost() override;
@@ -120,6 +124,8 @@ class PLATFORM_EXPORT LayerTreeView
void DidScheduleBeginMainFrame() override;
void DidRunBeginMainFrame() override;
+ // Registers a callback that will be run on the first successful presentation
+ // for `frame_token` or a following frame.
void AddPresentationCallback(
uint32_t frame_token,
base::OnceCallback<void(base::TimeTicks)> callback);
@@ -159,8 +165,6 @@ class PLATFORM_EXPORT LayerTreeView
presentation_callbacks_;
base::WeakPtrFactory<LayerTreeView> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(LayerTreeView);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h
index 01877e8c6d9..1a9d882ba2c 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/time/time.h"
#include "cc/trees/layer_tree_host_client.h"
+#include "cc/trees/paint_holding_reason.h"
namespace cc {
class LayerTreeFrameSink;
@@ -40,7 +41,8 @@ class LayerTreeViewDelegate {
virtual void BeginMainFrame(base::TimeTicks frame_time) = 0;
virtual void OnDeferMainFrameUpdatesChanged(bool) = 0;
- virtual void OnDeferCommitsChanged(bool) = 0;
+ virtual void OnDeferCommitsChanged(bool defer_status,
+ cc::PaintHoldingReason reason) = 0;
// Notifies that the layer tree host has completed a call to
// RequestMainFrameUpdate in response to a BeginMainFrame.
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_unittest.cc
index 193b584e022..c17006480e9 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_unittest.cc
@@ -8,9 +8,9 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -43,6 +43,9 @@ enum FailureMode {
class FakeLayerTreeViewDelegate : public StubLayerTreeViewDelegate {
public:
FakeLayerTreeViewDelegate() = default;
+ FakeLayerTreeViewDelegate(const FakeLayerTreeViewDelegate&) = delete;
+ FakeLayerTreeViewDelegate& operator=(const FakeLayerTreeViewDelegate&) =
+ delete;
void RequestNewLayerTreeFrameSink(
LayerTreeFrameSinkCallback callback) override {
@@ -110,8 +113,6 @@ class FakeLayerTreeViewDelegate : public StubLayerTreeViewDelegate {
int num_failures_before_success_ = 0;
int num_failures_since_last_success_ = 0;
int num_successes_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(FakeLayerTreeViewDelegate);
};
// Verify that failing to create an output surface will cause the compositor
@@ -127,6 +128,10 @@ class LayerTreeViewWithFrameSinkTracking : public LayerTreeView {
: LayerTreeView(delegate,
scheduler),
delegate_(delegate) {}
+ LayerTreeViewWithFrameSinkTracking(
+ const LayerTreeViewWithFrameSinkTracking&) = delete;
+ LayerTreeViewWithFrameSinkTracking& operator=(
+ const LayerTreeViewWithFrameSinkTracking&) = delete;
// Force a new output surface to be created.
void SynchronousComposite() {
@@ -196,8 +201,6 @@ class LayerTreeViewWithFrameSinkTracking : public LayerTreeView {
int expected_successes_ = 0;
int expected_requests_ = 0;
FailureMode failure_mode_ = NO_FAILURE;
-
- DISALLOW_COPY_AND_ASSIGN(LayerTreeViewWithFrameSinkTracking);
};
class LayerTreeViewWithFrameSinkTrackingTest : public testing::Test {
@@ -214,6 +217,10 @@ class LayerTreeViewWithFrameSinkTrackingTest : public testing::Test {
/*main_thread_pipeline=*/nullptr,
/*compositor_thread_pipeline=*/nullptr);
}
+ LayerTreeViewWithFrameSinkTrackingTest(
+ const LayerTreeViewWithFrameSinkTrackingTest&) = delete;
+ LayerTreeViewWithFrameSinkTrackingTest& operator=(
+ const LayerTreeViewWithFrameSinkTrackingTest&) = delete;
void RunTest(int expected_successes, FailureMode failure_mode) {
layer_tree_view_delegate_.Reset();
@@ -255,9 +262,6 @@ class LayerTreeViewWithFrameSinkTrackingTest : public testing::Test {
blink::scheduler::WebFakeThreadScheduler fake_thread_scheduler_;
FakeLayerTreeViewDelegate layer_tree_view_delegate_;
LayerTreeViewWithFrameSinkTracking layer_tree_view_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LayerTreeViewWithFrameSinkTrackingTest);
};
TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedOnce) {
@@ -365,5 +369,52 @@ TEST(LayerTreeViewTest, VisibilityTest) {
}
}
+// Tests that presentation callbacks are only called on successful
+// presentations.
+TEST(LayerTreeViewTest, RunPresentationCallbackOnSuccess) {
+ base::test::TaskEnvironment task_environment;
+
+ cc::TestTaskGraphRunner test_task_graph_runner;
+ blink::scheduler::WebFakeThreadScheduler fake_thread_scheduler;
+ StubLayerTreeViewDelegate layer_tree_view_delegate;
+ LayerTreeView layer_tree_view(&layer_tree_view_delegate,
+ &fake_thread_scheduler);
+
+ layer_tree_view.Initialize(
+ cc::LayerTreeSettings(),
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
+ /*compositor_thread=*/nullptr, &test_task_graph_runner,
+ /*main_thread_pipeline=*/nullptr,
+ /*compositor_thread_pipeline=*/nullptr);
+
+ // Register a callback for frame 1.
+ base::TimeTicks callback_timestamp;
+ layer_tree_view.AddPresentationCallback(
+ 1, base::BindLambdaForTesting([&](base::TimeTicks timestamp) {
+ callback_timestamp = timestamp;
+ }));
+
+ // Respond with a failed presentation feedback for frame 1 and verify that the
+ // callback is not called
+ base::TimeTicks fail_timestamp =
+ base::TimeTicks::Now() + base::TimeDelta::FromMicroseconds(2);
+ gfx::PresentationFeedback fail_feedback(fail_timestamp, base::TimeDelta(),
+ gfx::PresentationFeedback::kFailure);
+ layer_tree_view.DidPresentCompositorFrame(1, fail_feedback);
+ EXPECT_TRUE(callback_timestamp.is_null());
+
+ // Respond with a successful presentation feedback for frame 2 and verify that
+ // the callback for frame 1 is now called with presentation timestamp for
+ // frame 2.
+ base::TimeTicks success_timestamp =
+ fail_timestamp + base::TimeDelta::FromMicroseconds(3);
+ gfx::PresentationFeedback success_feedback(success_timestamp,
+ base::TimeDelta(), 0);
+ layer_tree_view.DidPresentCompositorFrame(2, success_feedback);
+ EXPECT_FALSE(callback_timestamp.is_null());
+ EXPECT_NE(callback_timestamp, fail_timestamp);
+ EXPECT_EQ(callback_timestamp, success_timestamp);
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/render_frame_metadata_observer_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/compositing/render_frame_metadata_observer_impl_unittest.cc
index ea9fe964287..602eeea4170 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/render_frame_metadata_observer_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/render_frame_metadata_observer_impl_unittest.cc
@@ -38,6 +38,10 @@ class MockRenderFrameMetadataObserverClient
this,
std::move(client_receiver)),
render_frame_metadata_observer_remote_(std::move(observer)) {}
+ MockRenderFrameMetadataObserverClient(
+ const MockRenderFrameMetadataObserverClient&) = delete;
+ MockRenderFrameMetadataObserverClient& operator=(
+ const MockRenderFrameMetadataObserverClient&) = delete;
MOCK_METHOD2(OnRenderFrameMetadataChanged,
void(uint32_t frame_token,
@@ -52,13 +56,15 @@ class MockRenderFrameMetadataObserverClient
render_frame_metadata_observer_client_receiver_;
mojo::Remote<cc::mojom::blink::RenderFrameMetadataObserver>
render_frame_metadata_observer_remote_;
-
- DISALLOW_COPY_AND_ASSIGN(MockRenderFrameMetadataObserverClient);
};
class RenderFrameMetadataObserverImplTest : public testing::Test {
public:
RenderFrameMetadataObserverImplTest() = default;
+ RenderFrameMetadataObserverImplTest(
+ const RenderFrameMetadataObserverImplTest&) = delete;
+ RenderFrameMetadataObserverImplTest& operator=(
+ const RenderFrameMetadataObserverImplTest&) = delete;
~RenderFrameMetadataObserverImplTest() override = default;
RenderFrameMetadataObserverImpl& observer_impl() { return *observer_impl_; }
@@ -94,8 +100,6 @@ class RenderFrameMetadataObserverImplTest : public testing::Test {
std::unique_ptr<testing::NiceMock<MockRenderFrameMetadataObserverClient>>
client_;
std::unique_ptr<RenderFrameMetadataObserverImpl> observer_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderFrameMetadataObserverImplTest);
};
// This test verifies that the RenderFrameMetadataObserverImpl picks up
diff --git a/chromium/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
index 86b891d6c81..09451992f9a 100644
--- a/chromium/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/widget/compositing/widget_compositor.h"
+#include "base/macros.h"
#include "base/test/task_environment.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/layer_tree_host.h"
@@ -29,7 +30,8 @@ class StubWidgetBaseClient : public WidgetBaseClient {
return WebInputEventResult::kNotHandled;
}
bool SupportsBufferedTouchEvents() override { return false; }
- bool WillHandleGestureEvent(const WebGestureEvent&) override { return false; }
+ void WillHandleGestureEvent(const WebGestureEvent&, bool* suppress) override {
+ }
void WillHandleMouseEvent(const WebMouseEvent&) override {}
void ObserveGestureEventAndResult(const WebGestureEvent&,
const gfx::Vector2dF&,
@@ -38,11 +40,13 @@ class StubWidgetBaseClient : public WidgetBaseClient {
void FocusChanged(bool) override {}
void UpdateVisualProperties(
const VisualProperties& visual_properties) override {}
- const ScreenInfo& GetOriginalScreenInfo() override { return screen_info_; }
+ const display::ScreenInfo& GetOriginalScreenInfo() override {
+ return screen_info_;
+ }
gfx::Rect ViewportVisibleRect() override { return gfx::Rect(); }
private:
- ScreenInfo screen_info_;
+ display::ScreenInfo screen_info_;
};
class FakeWidgetCompositor : public WidgetCompositor {
diff --git a/chromium/third_party/blink/renderer/platform/widget/frame_widget.h b/chromium/third_party/blink/renderer/platform/widget/frame_widget.h
index 3ab7729bed5..e9761912968 100644
--- a/chromium/third_party/blink/renderer/platform/widget/frame_widget.h
+++ b/chromium/third_party/blink/renderer/platform/widget/frame_widget.h
@@ -8,6 +8,7 @@
#include "cc/input/layer_selection_bound.h"
#include "mojo/public/mojom/base/text_direction.mojom-blink.h"
#include "services/viz/public/mojom/compositing/frame_sink_id.mojom-blink.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.h"
#include "third_party/blink/public/platform/web_text_input_info.h"
@@ -30,13 +31,16 @@ class PaintImage;
struct ElementId;
} // namespace cc
+namespace display {
+struct ScreenInfo;
+struct ScreenInfos;
+} // namespace display
+
namespace ui {
class Cursor;
} // namespace ui
namespace blink {
-struct ScreenInfo;
-struct ScreenInfos;
// In interface exposed within Blink from local root frames that provides
// local-root specific things related to compositing and input. This
@@ -197,10 +201,10 @@ class PLATFORM_EXPORT FrameWidget {
Vector<mojom::blink::EditCommandPtr> edit_commands) = 0;
// Returns information about the screen currently showing the widget.
- virtual const ScreenInfo& GetScreenInfo() = 0;
+ virtual const display::ScreenInfo& GetScreenInfo() = 0;
// Returns information about available screens and the current screen.
- virtual const ScreenInfos& GetScreenInfos() = 0;
+ virtual const display::ScreenInfos& GetScreenInfos() = 0;
// Called to get the position of the widget's window in screen
// coordinates. Note, the window includes any decorations such as borders,
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h b/chromium/third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h
index 2af2e626386..fc3c02d28a7 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h
@@ -23,6 +23,9 @@ class InputHandlerProxyEventQueueTest;
class PLATFORM_EXPORT CompositorThreadEventQueue {
public:
CompositorThreadEventQueue();
+ CompositorThreadEventQueue(const CompositorThreadEventQueue&) = delete;
+ CompositorThreadEventQueue& operator=(const CompositorThreadEventQueue&) =
+ delete;
~CompositorThreadEventQueue();
// Adds an event to the queue. The event may be coalesced with the last event.
@@ -39,8 +42,6 @@ class PLATFORM_EXPORT CompositorThreadEventQueue {
friend class test::InputHandlerProxyEventQueueTest;
using EventQueue = base::circular_deque<std::unique_ptr<EventWithCallback>>;
EventQueue queue_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorThreadEventQueue);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.cc b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.cc
index 01ad6416811..e01701de2b7 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.cc
@@ -47,6 +47,17 @@ namespace blink {
namespace {
constexpr double kScrollVelocityZeroingTimeout = 0.10f;
constexpr double kRubberbandMinimumRequiredDeltaBeforeStretch = 10;
+
+#if defined(OS_ANDROID)
+// On android, overscroll should not occur if the scroller is not scrollable in
+// the overscrolled direction.
+constexpr bool kOverscrollNonScrollableDirection = false;
+#else // defined(OS_ANDROID)
+// On other platforms, overscroll can occur even if the scroller is not
+// scrollable.
+constexpr bool kOverscrollNonScrollableDirection = true;
+#endif // defined(OS_ANDROID)
+
} // namespace
ElasticOverscrollController::ElasticOverscrollController(
@@ -58,11 +69,12 @@ ElasticOverscrollController::ElasticOverscrollController(
std::unique_ptr<ElasticOverscrollController>
ElasticOverscrollController::Create(cc::ScrollElasticityHelper* helper) {
#if defined(OS_WIN)
- return base::FeatureList::IsEnabled(features::kElasticOverscrollWin)
+ return base::FeatureList::IsEnabled(features::kElasticOverscroll)
? std::make_unique<ElasticOverscrollControllerBezier>(helper)
: nullptr;
-#endif
+#else
return std::make_unique<ElasticOverscrollControllerExponential>(helper);
+#endif
}
void ElasticOverscrollController::ObserveRealScrollBegin(bool enter_momentum,
@@ -187,6 +199,15 @@ void ElasticOverscrollController::Overscroll(
else
adjusted_overscroll_delta.set_y(0);
+ if (!kOverscrollNonScrollableDirection) {
+ // Check whether each direction is scrollable and 0 out the overscroll if it
+ // is not.
+ if (!CanScrollHorizontally())
+ adjusted_overscroll_delta.set_x(0);
+ if (!CanScrollVertically())
+ adjusted_overscroll_delta.set_y(0);
+ }
+
// Don't allow overscrolling in a direction where scrolling is possible.
if (!PinnedHorizontally(adjusted_overscroll_delta.x()))
adjusted_overscroll_delta.set_x(0);
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h
index d118d16ee42..beab815a17f 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
-#include "base/macros.h"
#include "cc/input/overscroll_behavior.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/public/common/input/web_gesture_event.h"
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h
index d6dcf989295..54af15092a2 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_BEZIER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_BEZIER_H_
-#include "base/macros.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
@@ -23,6 +22,10 @@ class PLATFORM_EXPORT ElasticOverscrollControllerBezier
public:
explicit ElasticOverscrollControllerBezier(
cc::ScrollElasticityHelper* helper);
+ ElasticOverscrollControllerBezier(const ElasticOverscrollControllerBezier&) =
+ delete;
+ ElasticOverscrollControllerBezier& operator=(
+ const ElasticOverscrollControllerBezier&) = delete;
~ElasticOverscrollControllerBezier() override = default;
void DidEnterMomentumAnimatedState() override;
@@ -63,7 +66,6 @@ class PLATFORM_EXPORT ElasticOverscrollControllerBezier
base::TimeDelta bounce_backwards_duration_x_;
base::TimeDelta bounce_backwards_duration_y_;
- DISALLOW_COPY_AND_ASSIGN(ElasticOverscrollControllerBezier);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc
index 3e2241be8f5..1e5c446f737 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h"
+#include "build/build_config.h"
#include "cc/input/input_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_input_event.h"
@@ -95,13 +96,19 @@ class ElasticOverscrollControllerBezierTest : public testing::Test {
ElasticOverscrollControllerBezier controller_;
};
-// Tests that the scroller "stretches" as expected when an overscroll occurs.
-TEST_F(ElasticOverscrollControllerBezierTest, VerifyOverscrollStretch) {
+// Tests that the scroller "stretches" as expected when an overscroll occurs
+// on a non-scrollable area. See ReconcileStretchAndScroll for an overscroll
+// stretch on scrollable areas.
+TEST_F(ElasticOverscrollControllerBezierTest, OverscrollStretch) {
// Test vertical overscroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -100));
+#if defined(OS_ANDROID)
+ EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
+#else
EXPECT_EQ(Vector2dF(0, -19), helper_.StretchAmount());
+#endif
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, 100));
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollEnd();
@@ -110,7 +117,11 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyOverscrollStretch) {
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-100, 0));
+#if defined(OS_ANDROID)
+ EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
+#else
EXPECT_EQ(Vector2dF(-19, 0), helper_.StretchAmount());
+#endif
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(100, 0));
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollEnd();
@@ -221,6 +232,9 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyOverscrollBounceDistance) {
// tick the animation as expected. When the stretch amount is near 0, the
// scroller should treat the bounce as "completed".
TEST_F(ElasticOverscrollControllerBezierTest, VerifyBackwardAnimationTick) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(100, 100));
+
// Test vertical overscroll.
EXPECT_EQ(controller_.state_, ElasticOverscrollController::kStateInactive);
SendGestureScrollBegin(PhaseState::kNonMomentum);
@@ -272,6 +286,9 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyBackwardAnimationTick) {
// Tests that the bounce forward animation ticks as expected.
TEST_F(ElasticOverscrollControllerBezierTest, VerifyForwardAnimationTick) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(100, 100));
+
// Test vertical forward bounce animations.
EXPECT_EQ(controller_.state_, ElasticOverscrollController::kStateInactive);
SendGestureScrollBegin(PhaseState::kNonMomentum);
@@ -346,6 +363,9 @@ TEST_F(ElasticOverscrollControllerBezierTest,
// Tests initiating a scroll when a bounce back animation is in progress works
// as expected.
TEST_F(ElasticOverscrollControllerBezierTest, VerifyScrollDuringBounceBack) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(100, 100));
+
// Test vertical overscroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.cc b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.cc
index 1e41b81f736..8a33fe0a923 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.cc
@@ -3,14 +3,21 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h"
+#include "build/build_config.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace blink {
namespace {
+#if defined(OS_ANDROID)
+constexpr double kRubberbandStiffness = 20;
+constexpr double kRubberbandAmplitude = 0.2f;
+constexpr double kRubberbandPeriod = 1.1f;
+#else
constexpr double kRubberbandStiffness = 20;
constexpr double kRubberbandAmplitude = 0.31f;
constexpr double kRubberbandPeriod = 1.6f;
+#endif
} // namespace
ElasticOverscrollControllerExponential::ElasticOverscrollControllerExponential(
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h
index ece7f123bba..0bf78d9961e 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_EXPONENTIAL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_EXPONENTIAL_H_
-#include "base/macros.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
@@ -18,6 +17,10 @@ class PLATFORM_EXPORT ElasticOverscrollControllerExponential
public:
explicit ElasticOverscrollControllerExponential(
cc::ScrollElasticityHelper* helper);
+ ElasticOverscrollControllerExponential(
+ const ElasticOverscrollControllerExponential&) = delete;
+ ElasticOverscrollControllerExponential& operator=(
+ const ElasticOverscrollControllerExponential&) = delete;
~ElasticOverscrollControllerExponential() override = default;
void DidEnterMomentumAnimatedState() override;
@@ -27,7 +30,6 @@ class PLATFORM_EXPORT ElasticOverscrollControllerExponential
const gfx::Vector2dF& accumulated_overscroll) const override;
gfx::Vector2d AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& delta) const override;
- DISALLOW_COPY_AND_ASSIGN(ElasticOverscrollControllerExponential);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential_unittest.cc
index bda39fc57d4..8b2f449be58 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential_unittest.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h"
+#include "build/build_config.h"
#include "cc/input/input_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_input_event.h"
@@ -155,8 +156,8 @@ class ElasticOverscrollControllerExponentialTest : public testing::Test {
// Verify that stretching occurs in one axis at a time, and that it
// is biased to the Y axis.
TEST_F(ElasticOverscrollControllerExponentialTest, Axis) {
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
- gfx::ScrollOffset(0, 0));
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(10, 10),
+ gfx::ScrollOffset(10, 10));
// If we push equally in the X and Y directions, we should see a stretch
// in the Y direction.
@@ -174,6 +175,8 @@ TEST_F(ElasticOverscrollControllerExponentialTest, Axis) {
// If we push more in the X direction than the Y direction, we should see a
// stretch in the X direction. This decision should be based on the actual
// overscroll delta.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 10),
+ gfx::ScrollOffset(10, 10));
SendGestureScrollBegin(NonMomentumPhase);
SendGestureScrollUpdate(NonMomentumPhase, Vector2dF(-25, 10),
Vector2dF(-25, 10));
@@ -409,8 +412,8 @@ TEST_F(ElasticOverscrollControllerExponentialTest,
// Verify that OverscrollBehaviorTypeNone disables the stretching on the
// specified axis.
TEST_F(ElasticOverscrollControllerExponentialTest, OverscrollBehavior) {
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
- gfx::ScrollOffset(0, 0));
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(10, 10),
+ gfx::ScrollOffset(10, 10));
// If we set OverscrollBehaviorTypeNone on x, we should not see a stretch
// in the X direction.
@@ -473,5 +476,42 @@ TEST_F(ElasticOverscrollControllerExponentialTest, OverscrollBehavior) {
EXPECT_EQ(0, helper_.request_begin_frame_count());
}
+// Test overscroll in non-scrollable direction.
+TEST_F(ElasticOverscrollControllerExponentialTest,
+ OverscrollBehaviorNonScrollable) {
+ int expected_stretch_count = 0;
+ // Set up a scroller which is vertically scrollable scrolled to the bottom.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 10),
+ gfx::ScrollOffset(0, 10));
+
+ SendGestureScrollBegin(NonMomentumPhase);
+ SendGestureScrollUpdate(NonMomentumPhase, Vector2dF(25, 0), Vector2dF(25, 0));
+#if defined(OS_ANDROID)
+ // Scrolling in x axis which has no scroll range should produce no stretch
+ // on android.
+ EXPECT_EQ(expected_stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0.f, helper_.StretchAmount().x());
+#else
+ EXPECT_EQ(++expected_stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_LT(0.f, helper_.StretchAmount().x());
+#endif
+ EXPECT_EQ(0.f, helper_.StretchAmount().y());
+ helper_.SetStretchAmount(Vector2dF());
+ SendGestureScrollEnd();
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+ EXPECT_EQ(++expected_stretch_count, helper_.set_stretch_amount_count());
+
+ SendGestureScrollBegin(NonMomentumPhase);
+ SendGestureScrollUpdate(NonMomentumPhase, Vector2dF(0, 25), Vector2dF(0, 25));
+ // Scrolling in y axis which has scroll range should produce overscroll
+ // on all platforms.
+ EXPECT_EQ(++expected_stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0.f, helper_.StretchAmount().x());
+ EXPECT_LT(0.f, helper_.StretchAmount().y());
+ helper_.SetStretchAmount(Vector2dF());
+ SendGestureScrollEnd();
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.cc b/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.cc
index 77eb8546301..61ac10fe71a 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.cc
@@ -24,18 +24,16 @@ FrameWidgetInputHandlerImpl::FrameWidgetInputHandlerImpl(
base::WeakPtr<WidgetBase> widget,
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
scoped_refptr<MainThreadEventQueue> input_event_queue)
: widget_(std::move(widget)),
main_thread_frame_widget_input_handler_(
std::move(frame_widget_input_handler)),
- input_event_queue_(input_event_queue),
- main_thread_task_runner_(main_thread_task_runner) {}
+ input_event_queue_(input_event_queue) {}
FrameWidgetInputHandlerImpl::~FrameWidgetInputHandlerImpl() = default;
void FrameWidgetInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) {
- if (input_event_queue_) {
+ if (ThreadedCompositingEnabled()) {
input_event_queue_->QueueClosure(std::move(closure));
} else {
std::move(closure).Run();
@@ -278,7 +276,7 @@ void FrameWidgetInputHandlerImpl::SelectWordAroundCaret(
// If the mojom channel is registered with compositor thread, we have to run
// the callback on compositor thread. Otherwise run it on main thread. Mojom
// requires the callback runs on the same thread.
- if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+ if (ThreadedCompositingEnabled()) {
callback = base::BindOnce(
[](scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
SelectWordAroundCaretCallback callback, bool did_select,
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.h b/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.h
index 05d50eb434a..19888c065e9 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/frame_widget_input_handler_impl.h
@@ -46,8 +46,10 @@ class PLATFORM_EXPORT FrameWidgetInputHandlerImpl
base::WeakPtr<WidgetBase> widget,
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
scoped_refptr<MainThreadEventQueue> input_event_queue);
+ FrameWidgetInputHandlerImpl(const FrameWidgetInputHandlerImpl&) = delete;
+ FrameWidgetInputHandlerImpl& operator=(const FrameWidgetInputHandlerImpl&) =
+ delete;
~FrameWidgetInputHandlerImpl() override;
void AddImeTextSpansToExistingText(
@@ -122,15 +124,14 @@ class PLATFORM_EXPORT FrameWidgetInputHandlerImpl
const char* command,
UpdateState state);
+ bool ThreadedCompositingEnabled() { return input_event_queue_ != nullptr; }
+
// These should only be accessed on the main thread.
base::WeakPtr<WidgetBase> widget_;
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
main_thread_frame_widget_input_handler_;
scoped_refptr<MainThreadEventQueue> input_event_queue_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameWidgetInputHandlerImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction.h b/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction.h
index 6bdad6dc06e..dd34245b973 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction.h
@@ -22,6 +22,8 @@ class PLATFORM_EXPORT InputEventPrediction {
public:
// enable_resampling is true when kResamplingInputEvents is enabled.
explicit InputEventPrediction(bool enable_resampling);
+ InputEventPrediction(const InputEventPrediction&) = delete;
+ InputEventPrediction& operator=(const InputEventPrediction&) = delete;
~InputEventPrediction();
// Handle Resampling/Prediction of WebInputEvents. This function is mainly
@@ -93,8 +95,6 @@ class PLATFORM_EXPORT InputEventPrediction {
// Records the timestamp for last event added to predictor.
base::TimeTicks last_event_timestamp_;
-
- DISALLOW_COPY_AND_ASSIGN(InputEventPrediction);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction_unittest.cc
index dd922e94922..54bc32f8a09 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/input_event_prediction_unittest.cc
@@ -23,6 +23,8 @@ class InputEventPredictionTest : public testing::Test {
ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
::features::kPredictorNameEmpty);
}
+ InputEventPredictionTest(const InputEventPredictionTest&) = delete;
+ InputEventPredictionTest& operator=(const InputEventPredictionTest&) = delete;
int GetPredictorMapSize() const {
return event_predictor_->pointer_id_predictor_map_.size();
@@ -69,8 +71,6 @@ class InputEventPredictionTest : public testing::Test {
std::unique_ptr<InputEventPrediction> event_predictor_;
base::test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(InputEventPredictionTest);
};
TEST_F(InputEventPredictionTest, PredictorType) {
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc b/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
index 223c81e48d5..28268f39a44 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
@@ -225,12 +225,8 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler& input_handler,
cursor_control_handler_(std::make_unique<CursorControlHandler>()) {
DCHECK(client);
input_handler_->BindToClient(this);
- cc::ScrollElasticityHelper* scroll_elasticity_helper =
- input_handler_->CreateScrollElasticityHelper();
- if (scroll_elasticity_helper) {
- elastic_overscroll_controller_ =
- ElasticOverscrollController::Create(scroll_elasticity_helper);
- }
+
+ UpdateElasticOverscroll();
compositor_event_queue_ = std::make_unique<CompositorThreadEventQueue>();
scroll_predictor_ =
base::FeatureList::IsEnabled(blink::features::kResamplingScrollEvents)
@@ -533,6 +529,27 @@ void InputHandlerProxy::DispatchQueuedInputEvents() {
DispatchSingleInputEvent(compositor_event_queue_->Pop(), now);
}
+void InputHandlerProxy::UpdateElasticOverscroll() {
+ bool can_use_elastic_overscroll = true;
+#if defined(OS_ANDROID)
+ // On android, elastic overscroll introduces quite a bit of motion which can
+ // effect those sensitive to it. Disable when prefers_reduced_motion_ is
+ // disabled.
+ can_use_elastic_overscroll = !prefers_reduced_motion_;
+#endif
+ if (!can_use_elastic_overscroll && elastic_overscroll_controller_) {
+ elastic_overscroll_controller_.reset();
+ input_handler_->DestroyScrollElasticityHelper();
+ } else if (can_use_elastic_overscroll && !elastic_overscroll_controller_) {
+ cc::ScrollElasticityHelper* scroll_elasticity_helper =
+ input_handler_->CreateScrollElasticityHelper();
+ if (scroll_elasticity_helper) {
+ elastic_overscroll_controller_ =
+ ElasticOverscrollController::Create(scroll_elasticity_helper);
+ }
+ }
+}
+
void InputHandlerProxy::InjectScrollbarGestureScroll(
const WebInputEvent::Type type,
const gfx::PointF& position_in_widget,
@@ -573,7 +590,9 @@ void InputHandlerProxy::InjectScrollbarGestureScroll(
DCHECK(!scrollbar_latency_info.FindLatency(
ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, nullptr));
- absl::optional<cc::EventMetrics::ScrollUpdateType> scroll_update_type;
+ cc::EventMetrics::ScrollParams scroll_params(
+ synthetic_gesture_event->GetScrollInputType(), /*is_inertial=*/false);
+
if (type == WebInputEvent::Type::kGestureScrollBegin) {
last_injected_gesture_was_begin_ = true;
} else {
@@ -587,9 +606,10 @@ void InputHandlerProxy::InjectScrollbarGestureScroll(
? ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT
: ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
original_timestamp);
- scroll_update_type = last_injected_gesture_was_begin_
- ? cc::EventMetrics::ScrollUpdateType::kStarted
- : cc::EventMetrics::ScrollUpdateType::kContinued;
+ scroll_params.update_type =
+ last_injected_gesture_was_begin_
+ ? cc::EventMetrics::ScrollUpdateType::kStarted
+ : cc::EventMetrics::ScrollUpdateType::kContinued;
}
last_injected_gesture_was_begin_ = false;
@@ -597,8 +617,7 @@ void InputHandlerProxy::InjectScrollbarGestureScroll(
std::unique_ptr<cc::EventMetrics> metrics =
cc::EventMetrics::CreateFromExisting(
- synthetic_gesture_event->GetTypeAsUiEventType(), scroll_update_type,
- synthetic_gesture_event->GetScrollInputType(),
+ synthetic_gesture_event->GetTypeAsUiEventType(), scroll_params,
cc::EventMetrics::DispatchStage::kArrivedInRendererCompositor,
original_metrics);
auto gesture_event_with_callback_update = std::make_unique<EventWithCallback>(
@@ -738,7 +757,14 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
// TODO(davemoore): This should never happen, but bug #326635 showed some
// surprising crashes.
CHECK(input_handler_);
- HandlePointerMove(event_with_callback, mouse_event.PositionInWidget());
+ // This should stay in sync with EventHandler::HandleMouseMoveOrLeaveEvent
+ // for main-thread scrollbar interactions.
+ bool should_cancel_scrollbar_drag =
+ (mouse_event.button == WebPointerProperties::Button::kNoButton &&
+ !(mouse_event.GetModifiers() &
+ WebInputEvent::Modifiers::kRelativeMotionEvent));
+ HandlePointerMove(event_with_callback, mouse_event.PositionInWidget(),
+ should_cancel_scrollbar_drag);
return DID_NOT_HANDLE;
}
case WebInputEvent::Type::kMouseLeave: {
@@ -1288,7 +1314,8 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchMove(
touch_event.touch_start_or_first_touch_move);
if (touch_event.touches_length == 1) {
cc::InputHandlerPointerResult pointer_result = HandlePointerMove(
- event_with_callback, touch_event.touches[0].PositionInWidget());
+ event_with_callback, touch_event.touches[0].PositionInWidget(),
+ false /* should_cancel_scrollbar_drag */);
if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
return DID_HANDLE;
}
@@ -1346,6 +1373,14 @@ void InputHandlerProxy::ReconcileElasticOverscrollAndRootScroll() {
elastic_overscroll_controller_->ReconcileStretchAndScroll();
}
+void InputHandlerProxy::SetPrefersReducedMotion(bool prefers_reduced_motion) {
+ if (prefers_reduced_motion_ == prefers_reduced_motion)
+ return;
+ prefers_reduced_motion_ = prefers_reduced_motion;
+
+ UpdateElasticOverscroll();
+}
+
void InputHandlerProxy::UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -1534,7 +1569,24 @@ const cc::InputHandlerPointerResult InputHandlerProxy::HandlePointerDown(
const cc::InputHandlerPointerResult InputHandlerProxy::HandlePointerMove(
EventWithCallback* event_with_callback,
- const gfx::PointF& position) {
+ const gfx::PointF& position,
+ bool should_cancel_scrollbar_drag) {
+ if (should_cancel_scrollbar_drag &&
+ input_handler_->ScrollbarScrollIsActive()) {
+ // If we're in a scrollbar drag and we see a mousemove with no buttons
+ // pressed, send a fake mouseup to cancel the drag. This can happen if the
+ // window loses focus during the drag (e.g. from Alt-Tab or opening a
+ // right-click context menu).
+ auto mouseup_result = input_handler_->MouseUp(position);
+ if (mouseup_result.type == cc::PointerResultType::kScrollbarScroll) {
+ InjectScrollbarGestureScroll(WebInputEvent::Type::kGestureScrollEnd,
+ position, mouseup_result,
+ event_with_callback->latency_info(),
+ event_with_callback->event().TimeStamp(),
+ event_with_callback->metrics());
+ }
+ }
+
cc::InputHandlerPointerResult pointer_result =
input_handler_->MouseMoveAt(gfx::Point(position.x(), position.y()));
if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
index 55ebf106101..603ee495998 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/circular_deque.h"
-#include "base/macros.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -84,11 +83,11 @@ std::unique_ptr<WebInputEvent> CreateGestureScrollPinch(
class MockInputHandler : public cc::InputHandler {
public:
MockInputHandler() = default;
- ~MockInputHandler() override = default;
-
MockInputHandler(const MockInputHandler&) = delete;
MockInputHandler& operator=(const MockInputHandler&) = delete;
+ ~MockInputHandler() override = default;
+
base::WeakPtr<InputHandler> AsWeakPtr() const override {
return weak_ptr_factory_.GetWeakPtr();
}
@@ -136,6 +135,8 @@ class MockInputHandler : public cc::InputHandler {
cc::ScrollElasticityHelper* CreateScrollElasticityHelper() override {
return nullptr;
}
+ void DestroyScrollElasticityHelper() override {}
+
bool GetScrollOffsetForLayer(cc::ElementId element_id,
gfx::ScrollOffset* offset) override {
return false;
@@ -180,6 +181,8 @@ class MockInputHandler : public cc::InputHandler {
gfx::Vector2dF* target_offset));
MOCK_METHOD1(ScrollEndForSnapFling, void(bool));
+ bool ScrollbarScrollIsActive() override { return false; }
+
private:
bool is_scrolling_root_ = true;
@@ -200,6 +203,10 @@ class MockSynchronousInputHandler : public SynchronousInputHandler {
class MockInputHandlerProxyClient : public InputHandlerProxyClient {
public:
MockInputHandlerProxyClient() {}
+ MockInputHandlerProxyClient(const MockInputHandlerProxyClient&) = delete;
+ MockInputHandlerProxyClient& operator=(const MockInputHandlerProxyClient&) =
+ delete;
+
~MockInputHandlerProxyClient() override {}
void WillShutdown() override {}
@@ -226,21 +233,20 @@ class MockInputHandlerProxyClient : public InputHandlerProxyClient {
void(cc::TouchAction touch_action,
uint32_t unique_touch_event_id,
InputHandlerProxy::EventDisposition event_disposition));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
};
class MockInputHandlerProxyClientWithDidAnimateForInput
: public MockInputHandlerProxyClient {
public:
MockInputHandlerProxyClientWithDidAnimateForInput() {}
+ MockInputHandlerProxyClientWithDidAnimateForInput(
+ const MockInputHandlerProxyClientWithDidAnimateForInput&) = delete;
+ MockInputHandlerProxyClientWithDidAnimateForInput& operator=(
+ const MockInputHandlerProxyClientWithDidAnimateForInput&) = delete;
+
~MockInputHandlerProxyClientWithDidAnimateForInput() override {}
MOCK_METHOD0(DidAnimateForInput, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClientWithDidAnimateForInput);
};
WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state,
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
index f5b1559b63a..050f800e1d0 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
@@ -74,7 +74,6 @@ class QueuedWebInputEvent : public MainThreadEventQueueTask {
std::unique_ptr<cc::EventMetrics> metrics =
cc::EventMetrics::CreateFromExisting(
raw_event->Event().GetTypeAsUiEventType(), absl::nullopt,
- raw_event->Event().GetScrollInputType(),
cc::EventMetrics::DispatchStage::kRendererCompositorFinished,
original_metrics);
return std::make_unique<QueuedWebInputEvent>(
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
index da7f83de126..8b69d8a498b 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
@@ -12,6 +12,7 @@
#include "base/single_thread_task_runner.h"
#include "base/timer/timer.h"
#include "cc/input/touch_action.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
@@ -93,6 +94,8 @@ class PLATFORM_EXPORT MainThreadEventQueue
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
scheduler::WebThreadScheduler* main_thread_scheduler,
bool allow_raf_aligned_input);
+ MainThreadEventQueue(const MainThreadEventQueue&) = delete;
+ MainThreadEventQueue& operator=(const MainThreadEventQueue&) = delete;
// Type of dispatching of the event.
enum class DispatchType { kBlocking, kNonBlocking };
@@ -190,8 +193,6 @@ class PLATFORM_EXPORT MainThreadEventQueue
std::unique_ptr<base::OneShotTimer> raf_fallback_timer_;
std::unique_ptr<InputEventPrediction> event_predictor_;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadEventQueue);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_task_list.h b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_task_list.h
index 9e38f89aa6b..724995c3240 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_task_list.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_task_list.h
@@ -19,6 +19,9 @@ class MainThreadEventQueueTaskList {
enum class EnqueueResult { kCoalesced, kEnqueued };
MainThreadEventQueueTaskList();
+ MainThreadEventQueueTaskList(const MainThreadEventQueueTaskList&) = delete;
+ MainThreadEventQueueTaskList& operator=(const MainThreadEventQueueTaskList&) =
+ delete;
~MainThreadEventQueueTaskList();
// Adds an event to the queue. The event may be coalesced with previously
@@ -43,8 +46,6 @@ class MainThreadEventQueueTaskList {
using EventQueue =
base::circular_deque<std::unique_ptr<MainThreadEventQueueTask>>;
EventQueue queue_;
-
- DISALLOW_COPY_AND_ASSIGN(MainThreadEventQueueTaskList);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
index 06cfd7a866b..523799739d7 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
@@ -11,7 +11,6 @@
#include "base/auto_reset.h"
#include "base/bind.h"
-#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/test/test_simple_task_runner.h"
#include "build/build_config.h"
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/prediction/filter_factory_unittests.cc b/chromium/third_party/blink/renderer/platform/widget/input/prediction/filter_factory_unittests.cc
index c375e5c626b..83867802007 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/prediction/filter_factory_unittests.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/prediction/filter_factory_unittests.cc
@@ -25,6 +25,8 @@ class FilterFactoryTest : public testing::Test {
PredictorType::kScrollPredictorTypeKalman,
FilterType::kEmpty);
}
+ FilterFactoryTest(const FilterFactoryTest&) = delete;
+ FilterFactoryTest& operator=(const FilterFactoryTest&) = delete;
void GetFilterParams(const FilterType& filter_type,
const PredictorType& predictor_type,
@@ -51,8 +53,6 @@ class FilterFactoryTest : public testing::Test {
private:
std::unique_ptr<FilterFactory> factory_;
-
- DISALLOW_COPY_AND_ASSIGN(FilterFactoryTest);
};
// Check if the FilterType returned is correct
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor.h b/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor.h
index 7957d77e9a2..6ca1b555248 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor.h
@@ -27,6 +27,8 @@ class PLATFORM_EXPORT ScrollPredictor {
// Select the predictor type from field trial params and initialize the
// predictor.
explicit ScrollPredictor();
+ ScrollPredictor(const ScrollPredictor&) = delete;
+ ScrollPredictor& operator=(const ScrollPredictor&) = delete;
~ScrollPredictor();
// Reset the predictors on each GSB.
@@ -81,8 +83,6 @@ class PLATFORM_EXPORT ScrollPredictor {
// Handler used for evaluating the prediction
ui::PredictionMetricsHandler metrics_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(ScrollPredictor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc b/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc
index b34f9df154f..326b09888dc 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc
@@ -29,6 +29,8 @@ constexpr double kEpsilon = 0.001;
class ScrollPredictorTest : public testing::Test {
public:
ScrollPredictorTest() {}
+ ScrollPredictorTest(const ScrollPredictorTest&) = delete;
+ ScrollPredictorTest& operator=(const ScrollPredictorTest&) = delete;
void SetUp() override {
original_events_.clear();
@@ -203,8 +205,6 @@ class ScrollPredictorTest : public testing::Test {
std::unique_ptr<ScrollPredictor> scroll_predictor_;
base::test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(ScrollPredictorTest);
};
TEST_F(ScrollPredictorTest, ScrollResamplingStates) {
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/synchronous_compositor_proxy.h b/chromium/third_party/blink/renderer/platform/widget/input/synchronous_compositor_proxy.h
index d7e9799fd5c..ccf853685d3 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/synchronous_compositor_proxy.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/synchronous_compositor_proxy.h
@@ -9,7 +9,6 @@
#include <stdint.h>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/writable_shared_memory_region.h"
#include "components/viz/common/frame_timing_details_map.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
@@ -39,6 +38,9 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler,
public:
SynchronousCompositorProxy(
blink::SynchronousInputHandlerProxy* input_handler_proxy);
+ SynchronousCompositorProxy(const SynchronousCompositorProxy&) = delete;
+ SynchronousCompositorProxy& operator=(const SynchronousCompositorProxy&) =
+ delete;
~SynchronousCompositorProxy() override;
void Init();
@@ -150,8 +152,6 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler,
bool invalidate_needs_draw_;
uint32_t did_activate_pending_tree_count_;
uint32_t metadata_version_ = 0u;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorProxy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc b/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc
index c21b28c1baf..850e6ccf73b 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc
@@ -415,8 +415,9 @@ void WidgetBaseInputHandler::HandleInputEvent(
if (WebInputEvent::IsGestureEventType(input_event.GetType())) {
const WebGestureEvent& gesture_event =
static_cast<const WebGestureEvent&>(input_event);
- prevent_default = prevent_default ||
- widget_->client()->WillHandleGestureEvent(gesture_event);
+ bool suppress = false;
+ widget_->client()->WillHandleGestureEvent(gesture_event, &suppress);
+ prevent_default = prevent_default || suppress;
}
WebInputEventResult processed = prevent_default
@@ -627,7 +628,8 @@ void WidgetBaseInputHandler::HandleInjectedScrollGestures(
scrollbar_latency_info.AddLatencyNumber(
ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT);
- absl::optional<cc::EventMetrics::ScrollUpdateType> scroll_update_type;
+ cc::EventMetrics::ScrollParams scroll_params(
+ ui::ScrollInputType::kScrollbar, /*is_inertial=*/false);
if (params.type == WebInputEvent::Type::kGestureScrollUpdate) {
if (input_event.GetType() != WebInputEvent::Type::kGestureScrollUpdate) {
scrollbar_latency_info.AddLatencyNumberWithTimestamp(
@@ -648,9 +650,10 @@ void WidgetBaseInputHandler::HandleInjectedScrollGestures(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
nullptr));
}
- scroll_update_type = last_injected_gesture_was_begin_
- ? cc::EventMetrics::ScrollUpdateType::kStarted
- : cc::EventMetrics::ScrollUpdateType::kContinued;
+ scroll_params.update_type =
+ last_injected_gesture_was_begin_
+ ? cc::EventMetrics::ScrollUpdateType::kStarted
+ : cc::EventMetrics::ScrollUpdateType::kContinued;
}
std::unique_ptr<WebGestureEvent> gesture_event =
@@ -671,8 +674,7 @@ void WidgetBaseInputHandler::HandleInjectedScrollGestures(
widget_->LayerTreeHost()->GetSwapPromiseManager());
std::unique_ptr<cc::EventMetrics> metrics =
cc::EventMetrics::CreateFromExisting(
- gesture_event->GetTypeAsUiEventType(), scroll_update_type,
- gesture_event->GetScrollInputType(),
+ gesture_event->GetTypeAsUiEventType(), scroll_params,
cc::EventMetrics::DispatchStage::kRendererCompositorFinished,
original_metrics);
cc::EventsMetricsManager::ScopedMonitor::DoneCallback done_callback;
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.cc b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.cc
index add9bfb248c..758373ed3c3 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.cc
@@ -36,13 +36,11 @@ void RunClosureIfNotSwappedOut(base::WeakPtr<WidgetBase> widget,
WidgetInputHandlerImpl::WidgetInputHandlerImpl(
scoped_refptr<WidgetInputHandlerManager> manager,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
scoped_refptr<MainThreadEventQueue> input_event_queue,
base::WeakPtr<WidgetBase> widget,
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler)
- : main_thread_task_runner_(main_thread_task_runner),
- input_handler_manager_(manager),
+ : input_handler_manager_(manager),
input_event_queue_(input_event_queue),
widget_(std::move(widget)),
frame_widget_input_handler_(std::move(frame_widget_input_handler)) {}
@@ -76,15 +74,30 @@ void WidgetInputHandlerImpl::CursorVisibilityChanged(bool visible) {
base::BindOnce(&WidgetBase::CursorVisibilityChange, widget_, visible));
}
+static void ImeSetCompositionOnMainThread(
+ base::WeakPtr<WidgetBase> widget,
+ scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
+ const String& text,
+ const Vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t start,
+ int32_t end,
+ WidgetInputHandlerImpl::ImeSetCompositionCallback callback) {
+ widget->ImeSetComposition(text, ime_text_spans, range, start, end);
+ callback_task_runner->PostTask(FROM_HERE, std::move(callback));
+}
+
void WidgetInputHandlerImpl::ImeSetComposition(
const String& text,
const Vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
int32_t start,
- int32_t end) {
- RunOnMainThread(base::BindOnce(&WidgetBase::ImeSetComposition, widget_,
+ int32_t end,
+ WidgetInputHandlerImpl::ImeSetCompositionCallback callback) {
+ RunOnMainThread(base::BindOnce(&ImeSetCompositionOnMainThread, widget_,
+ base::ThreadTaskRunnerHandle::Get(),
text.IsolatedCopy(), ime_text_spans, range,
- start, end));
+ start, end, std::move(callback)));
}
static void ImeCommitTextOnMainThread(
@@ -178,13 +191,12 @@ void WidgetInputHandlerImpl::GetFrameWidgetInputHandler(
frame_receiver) {
mojo::MakeSelfOwnedAssociatedReceiver(
std::make_unique<FrameWidgetInputHandlerImpl>(
- widget_, frame_widget_input_handler_, main_thread_task_runner_,
- input_event_queue_),
+ widget_, frame_widget_input_handler_, input_event_queue_),
std::move(frame_receiver));
}
void WidgetInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) {
- if (input_event_queue_) {
+ if (ThreadedCompositingEnabled()) {
input_event_queue_->QueueClosure(base::BindOnce(
&RunClosureIfNotSwappedOut, widget_, std::move(closure)));
} else {
@@ -202,16 +214,17 @@ void WidgetInputHandlerImpl::Release() {
if (input_processed_ack_)
std::move(input_processed_ack_).Run();
- if (!main_thread_task_runner_->BelongsToCurrentThread()) {
- // Close the binding on the compositor thread first before telling the main
- // thread to delete this object.
- receiver_.reset();
- main_thread_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&WidgetInputHandlerImpl::Release,
- base::Unretained(this)));
+ if (!ThreadedCompositingEnabled()) {
+ delete this;
return;
}
- delete this;
+
+ // Close the binding on the compositor thread first before telling the main
+ // thread to delete this object.
+ receiver_.reset();
+ input_event_queue_->QueueClosure(base::BindOnce(
+ [](const WidgetInputHandlerImpl* handler) { delete handler; },
+ base::Unretained(this)));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h
index dfd96239ada..55ce0be8032 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h
@@ -7,6 +7,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
@@ -27,11 +28,12 @@ class WidgetInputHandlerImpl : public mojom::blink::WidgetInputHandler {
// at the same time.
WidgetInputHandlerImpl(
scoped_refptr<WidgetInputHandlerManager> manager,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
scoped_refptr<MainThreadEventQueue> input_event_queue,
base::WeakPtr<WidgetBase> widget,
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler);
+ WidgetInputHandlerImpl(const WidgetInputHandlerImpl&) = delete;
+ WidgetInputHandlerImpl& operator=(const WidgetInputHandlerImpl&) = delete;
~WidgetInputHandlerImpl() override;
void SetReceiver(mojo::PendingReceiver<mojom::blink::WidgetInputHandler>
@@ -46,7 +48,8 @@ class WidgetInputHandlerImpl : public mojom::blink::WidgetInputHandler {
const Vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
int32_t start,
- int32_t end) override;
+ int32_t end,
+ ImeSetCompositionCallback callback) override;
void ImeCommitText(const String& text,
const Vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
@@ -80,7 +83,8 @@ class WidgetInputHandlerImpl : public mojom::blink::WidgetInputHandler {
void RunOnMainThread(base::OnceClosure closure);
void Release();
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+ bool ThreadedCompositingEnabled() { return input_event_queue_ != nullptr; }
+
scoped_refptr<WidgetInputHandlerManager> input_handler_manager_;
scoped_refptr<MainThreadEventQueue> input_event_queue_;
base::WeakPtr<WidgetBase> widget_;
@@ -95,8 +99,6 @@ class WidgetInputHandlerImpl : public mojom::blink::WidgetInputHandler {
mojo::Receiver<mojom::blink::WidgetInputHandler> receiver_{this};
base::WeakPtrFactory<WidgetInputHandlerImpl> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WidgetInputHandlerImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
index 859a13b76ad..e0351db23e1 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
@@ -15,6 +15,7 @@
#include "cc/base/features.h"
#include "cc/metrics/event_metrics.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "components/power_scheduler/power_mode.h"
#include "components/power_scheduler/power_mode_arbiter.h"
#include "components/power_scheduler/power_mode_voter.h"
@@ -129,7 +130,8 @@ class SynchronousCompositorProxyRegistry
public:
explicit SynchronousCompositorProxyRegistry(
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner)
- : compositor_task_runner_(std::move(compositor_task_runner)) {}
+ : compositor_thread_default_task_runner_(
+ std::move(compositor_task_runner)) {}
~SynchronousCompositorProxyRegistry() override {
// Ensure the proxy has already been release on the compositor thread
@@ -138,7 +140,7 @@ class SynchronousCompositorProxyRegistry
}
void CreateProxy(SynchronousInputHandlerProxy* handler) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
proxy_ = std::make_unique<SynchronousCompositorProxy>(handler);
proxy_->Init();
@@ -150,7 +152,7 @@ class SynchronousCompositorProxyRegistry
void RegisterLayerTreeFrameSink(
SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(nullptr, sink_);
sink_ = layer_tree_frame_sink;
if (proxy_)
@@ -159,18 +161,19 @@ class SynchronousCompositorProxyRegistry
void UnregisterLayerTreeFrameSink(
SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(layer_tree_frame_sink, sink_);
sink_ = nullptr;
}
void DestroyProxy() {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
proxy_.reset();
}
private:
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ compositor_thread_default_task_runner_;
std::unique_ptr<SynchronousCompositorProxy> proxy_;
SynchronousLayerTreeFrameSink* sink_ = nullptr;
};
@@ -182,22 +185,23 @@ scoped_refptr<WidgetInputHandlerManager> WidgetInputHandlerManager::Create(
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler,
bool never_composited,
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
+ scheduler::WebThreadScheduler* compositor_thread_scheduler,
scheduler::WebThreadScheduler* main_thread_scheduler,
bool uses_input_handler) {
scoped_refptr<WidgetInputHandlerManager> manager =
new WidgetInputHandlerManager(
std::move(widget), std::move(frame_widget_input_handler),
- never_composited, std::move(compositor_task_runner),
- main_thread_scheduler);
+ never_composited, compositor_thread_scheduler, main_thread_scheduler);
if (uses_input_handler)
manager->InitInputHandler();
// A compositor thread implies we're using an input handler.
- DCHECK(!manager->compositor_task_runner_ || uses_input_handler);
+ DCHECK(!manager->compositor_thread_default_task_runner_ ||
+ uses_input_handler);
// Conversely, if we don't use an input handler we must not have a compositor
// thread.
- DCHECK(uses_input_handler || !manager->compositor_task_runner_);
+ DCHECK(uses_input_handler ||
+ !manager->compositor_thread_default_task_runner_);
return manager;
}
@@ -207,7 +211,7 @@ WidgetInputHandlerManager::WidgetInputHandlerManager(
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler,
bool never_composited,
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
+ scheduler::WebThreadScheduler* compositor_thread_scheduler,
scheduler::WebThreadScheduler* main_thread_scheduler)
: widget_(std::move(widget)),
frame_widget_input_handler_(std::move(frame_widget_input_handler)),
@@ -219,16 +223,23 @@ WidgetInputHandlerManager::WidgetInputHandlerManager(
widget_scheduler_->InputTaskRunner(),
main_thread_scheduler,
/*allow_raf_aligned_input=*/!never_composited)),
- main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- compositor_task_runner_(std::move(compositor_task_runner)),
+ main_thread_task_runner_(widget_scheduler_->InputTaskRunner()),
+ compositor_thread_default_task_runner_(
+ compositor_thread_scheduler
+ ? compositor_thread_scheduler->DefaultTaskRunner()
+ : nullptr),
+ compositor_thread_input_blocking_task_runner_(
+ compositor_thread_scheduler
+ ? compositor_thread_scheduler->InputTaskRunner()
+ : nullptr),
response_power_mode_voter_(
power_scheduler::PowerModeArbiter::GetInstance()->NewVoter(
"PowerModeVoter.Response")) {
#if defined(OS_ANDROID)
- if (compositor_task_runner_) {
+ if (compositor_thread_default_task_runner_) {
synchronous_compositor_registry_ =
std::make_unique<SynchronousCompositorProxyRegistry>(
- compositor_task_runner_);
+ compositor_thread_default_task_runner_);
}
#endif
}
@@ -241,7 +252,7 @@ void WidgetInputHandlerManager::InitInputHandler() {
#endif
uses_input_handler_ = true;
base::OnceClosure init_closure = base::BindOnce(
- &WidgetInputHandlerManager::InitOnInputHandlingThread, this,
+ &WidgetInputHandlerManager::InitOnInputHandlingThread, AsWeakPtr(),
widget_->LayerTreeHost()->GetDelegateForInput(), sync_compositing);
InputThreadTaskRunner()->PostTask(FROM_HERE, std::move(init_closure));
}
@@ -251,11 +262,11 @@ WidgetInputHandlerManager::~WidgetInputHandlerManager() = default;
void WidgetInputHandlerManager::AddInterface(
mojo::PendingReceiver<mojom::blink::WidgetInputHandler> receiver,
mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) {
- if (compositor_task_runner_) {
+ if (compositor_thread_default_task_runner_) {
host_ = mojo::SharedRemote<mojom::blink::WidgetInputHandlerHost>(
- std::move(host), compositor_task_runner_);
+ std::move(host), compositor_thread_default_task_runner_);
// Mojo channel bound on compositor thread.
- compositor_task_runner_->PostTask(
+ compositor_thread_default_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&WidgetInputHandlerManager::BindChannel, this,
std::move(receiver)));
} else {
@@ -299,6 +310,7 @@ void WidgetInputHandlerManager::WillShutdown() {
synchronous_compositor_registry_->DestroyProxy();
#endif
input_handler_proxy_.reset();
+ dropped_event_counts_timer_.reset();
}
void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread(
@@ -324,8 +336,8 @@ void WidgetInputHandlerManager::FindScrollTargetOnMainThread(
uint64_t element_id =
widget_->client()->FrameWidget()->GetScrollableContainerIdAt(point);
- InputThreadTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), element_id));
+ InputThreadTaskRunner(TaskRunnerType::kInputBlocking)
+ ->PostTask(FROM_HERE, base::BindOnce(std::move(callback), element_id));
}
void WidgetInputHandlerManager::DidAnimateForInput() {
@@ -344,12 +356,23 @@ void WidgetInputHandlerManager::GenerateScrollBeginAndSendToMainThread(
const WebInputEventAttribution& attribution,
const cc::EventMetrics* update_metrics) {
DCHECK_EQ(update_event.GetType(), WebInputEvent::Type::kGestureScrollUpdate);
+ auto gesture_event = ScrollBeginFromScrollUpdate(update_event);
+
+ // TODO(crbug.com/1137870): Scroll-begin events should not normally be
+ // inertial. Here, the scroll-begin is created from the first scroll-update
+ // event of a sequence and the first scroll-update should not be inertial,
+ // either. Consider passing in `false` as `is_inertial` argument and adding
+ // DCHECKs here to make sure `gesture_event` is not inertial.
+ cc::EventMetrics::ScrollParams scroll_params(
+ gesture_event->GetScrollInputType(),
+ gesture_event->InertialPhase() ==
+ WebGestureEvent::InertialPhaseState::kMomentum);
+
auto event = std::make_unique<WebCoalescedInputEvent>(
- ScrollBeginFromScrollUpdate(update_event), ui::LatencyInfo());
+ std::move(gesture_event), ui::LatencyInfo());
std::unique_ptr<cc::EventMetrics> metrics =
cc::EventMetrics::CreateFromExisting(
- event->Event().GetTypeAsUiEventType(), absl::nullopt,
- event->Event().GetScrollInputType(),
+ event->Event().GetTypeAsUiEventType(), scroll_params,
cc::EventMetrics::DispatchStage::kRendererCompositorFinished,
update_metrics);
@@ -484,21 +507,30 @@ void WidgetInputHandlerManager::DispatchEvent(
event->EventPointer()->SetTimeStamp(base::TimeTicks::Now());
}
- absl::optional<cc::EventMetrics::ScrollUpdateType> scroll_update_type;
- if (event->Event().GetType() == WebInputEvent::Type::kGestureScrollBegin) {
- has_seen_first_gesture_scroll_update_after_begin_ = false;
- } else if (event->Event().GetType() ==
- WebInputEvent::Type::kGestureScrollUpdate) {
- if (has_seen_first_gesture_scroll_update_after_begin_) {
- scroll_update_type = cc::EventMetrics::ScrollUpdateType::kContinued;
- } else {
- scroll_update_type = cc::EventMetrics::ScrollUpdateType::kStarted;
- has_seen_first_gesture_scroll_update_after_begin_ = true;
+ absl::optional<cc::EventMetrics::ScrollParams> scroll_params;
+ if (event->Event().IsGestureScroll()) {
+ const auto& gesture_event =
+ static_cast<const WebGestureEvent&>(event->Event());
+ scroll_params.emplace(gesture_event.GetScrollInputType(),
+ gesture_event.InertialPhase() ==
+ WebGestureEvent::InertialPhaseState::kMomentum);
+ if (event->Event().GetType() == WebInputEvent::Type::kGestureScrollBegin) {
+ has_seen_first_gesture_scroll_update_after_begin_ = false;
+ } else if (event->Event().GetType() ==
+ WebInputEvent::Type::kGestureScrollUpdate) {
+ if (has_seen_first_gesture_scroll_update_after_begin_) {
+ scroll_params->update_type =
+ cc::EventMetrics::ScrollUpdateType::kContinued;
+ } else {
+ scroll_params->update_type =
+ cc::EventMetrics::ScrollUpdateType::kStarted;
+ has_seen_first_gesture_scroll_update_after_begin_ = true;
+ }
}
}
- std::unique_ptr<cc::EventMetrics> metrics = cc::EventMetrics::Create(
- event->Event().GetTypeAsUiEventType(), scroll_update_type,
- event->Event().GetScrollInputType(), event->Event().TimeStamp());
+ std::unique_ptr<cc::EventMetrics> metrics =
+ cc::EventMetrics::Create(event->Event().GetTypeAsUiEventType(),
+ scroll_params, event->Event().TimeStamp());
if (uses_input_handler_) {
// If the input_handler_proxy has disappeared ensure we just ack event.
@@ -614,8 +646,10 @@ void WidgetInputHandlerManager::OnDeferMainFrameUpdatesChanged(bool status) {
}
}
-void WidgetInputHandlerManager::OnDeferCommitsChanged(bool status) {
- if (status) {
+void WidgetInputHandlerManager::OnDeferCommitsChanged(
+ bool status,
+ cc::PaintHoldingReason reason) {
+ if (status && reason == cc::PaintHoldingReason::kFirstContentfulPaint) {
renderer_deferral_state_ |=
static_cast<uint16_t>(RenderingDeferralBits::kDeferCommits);
} else {
@@ -656,12 +690,13 @@ void WidgetInputHandlerManager::BindChannel(
mojo::PendingReceiver<mojom::blink::WidgetInputHandler> receiver) {
if (!receiver.is_valid())
return;
- // Don't pass the |input_event_queue_| on if we don't have a
- // |compositor_task_runner_| as events might get out of order.
+ // Passing null for |input_event_queue_| tells the handler that we don't have
+ // a compositor thread. (Single threaded-mode shouldn't use the queue, or else
+ // events might get out of order - see crrev.com/519829).
WidgetInputHandlerImpl* handler = new WidgetInputHandlerImpl(
- this, main_thread_task_runner_,
- compositor_task_runner_ ? input_event_queue_ : nullptr, widget_,
- frame_widget_input_handler_);
+ this,
+ compositor_thread_default_task_runner_ ? input_event_queue_ : nullptr,
+ widget_, frame_widget_input_handler_);
handler->SetReceiver(std::move(receiver));
}
@@ -788,7 +823,7 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor(
static_cast<const WebGestureEvent&>(event->Event()).PositionInWidget();
ElementAtPointCallback result_callback = base::BindOnce(
- &WidgetInputHandlerManager::FindScrollTargetReply, AsWeakPtr(),
+ &WidgetInputHandlerManager::FindScrollTargetReply, this,
std::move(event), std::move(metrics), std::move(callback));
main_thread_task_runner_->PostTask(
@@ -873,15 +908,16 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToMain(
allowed_touch_action_.reset();
}
// This method is called from either the main thread or the compositor thread.
- bool is_compositor_thread = compositor_task_runner_ &&
- compositor_task_runner_->BelongsToCurrentThread();
+ bool is_compositor_thread =
+ compositor_thread_default_task_runner_ &&
+ compositor_thread_default_task_runner_->BelongsToCurrentThread();
// If there is a compositor task runner and the current thread isn't the
// compositor thread proxy it over to the compositor thread.
- if (compositor_task_runner_ && !is_compositor_thread) {
+ if (compositor_thread_default_task_runner_ && !is_compositor_thread) {
TRACE_EVENT_INSTANT0("input", "PostingToCompositor",
TRACE_EVENT_SCOPE_THREAD);
- compositor_task_runner_->PostTask(
+ compositor_thread_default_task_runner_->PostTask(
FROM_HERE, base::BindOnce(CallCallback, std::move(callback), ack_state,
latency_info, std::move(overscroll_params),
touch_action));
@@ -903,15 +939,23 @@ void WidgetInputHandlerManager::ObserveGestureEventOnInputHandlingThread(
const cc::InputHandlerScrollResult& scroll_result) {
if (!input_handler_proxy_)
return;
- DCHECK(input_handler_proxy_->elastic_overscroll_controller());
+ // The elastic overscroll controller on android can be dynamically created or
+ // removed by changing prefers-reduced-motion. When removed, we do not need to
+ // observe the event.
+ if (!input_handler_proxy_->elastic_overscroll_controller())
+ return;
input_handler_proxy_->elastic_overscroll_controller()
->ObserveGestureEventAndResult(gesture_event, scroll_result);
}
const scoped_refptr<base::SingleThreadTaskRunner>&
-WidgetInputHandlerManager::InputThreadTaskRunner() const {
- if (compositor_task_runner_)
- return compositor_task_runner_;
+WidgetInputHandlerManager::InputThreadTaskRunner(TaskRunnerType type) const {
+ if (compositor_thread_input_blocking_task_runner_ &&
+ type == TaskRunnerType::kInputBlocking) {
+ return compositor_thread_input_blocking_task_runner_;
+ } else if (compositor_thread_default_task_runner_) {
+ return compositor_thread_default_task_runner_;
+ }
return main_thread_task_runner_;
}
diff --git a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
index 163567e8f1f..faabbaefa1e 100644
--- a/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
+++ b/chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
+#include "cc/trees/paint_holding_reason.h"
#include "components/power_scheduler/power_mode_voter.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -76,10 +77,14 @@ class PLATFORM_EXPORT WidgetInputHandlerManager final
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler,
bool never_composited,
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
+ scheduler::WebThreadScheduler* compositor_thread_scheduler,
scheduler::WebThreadScheduler* main_thread_scheduler,
bool needs_input_handler);
+ WidgetInputHandlerManager(const WidgetInputHandlerManager&) = delete;
+ WidgetInputHandlerManager& operator=(const WidgetInputHandlerManager&) =
+ delete;
+
void AddInterface(
mojo::PendingReceiver<mojom::blink::WidgetInputHandler> receiver,
mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host);
@@ -147,7 +152,7 @@ class PLATFORM_EXPORT WidgetInputHandlerManager final
void OnDeferMainFrameUpdatesChanged(bool);
// Called to inform us when the system starts or stops deferring commits.
- void OnDeferCommitsChanged(bool);
+ void OnDeferCommitsChanged(bool defer_status, cc::PaintHoldingReason reason);
// Allow tests, headless etc. to have input events processed before the
// compositor is ready to commit frames.
@@ -177,7 +182,7 @@ class PLATFORM_EXPORT WidgetInputHandlerManager final
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler,
bool never_composited,
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
+ scheduler::WebThreadScheduler* compositor_thread_scheduler,
scheduler::WebThreadScheduler* main_thread_scheduler);
void InitInputHandler();
void InitOnInputHandlingThread(
@@ -250,10 +255,15 @@ class PLATFORM_EXPORT WidgetInputHandlerManager final
void HandleInputEventWithLatencyOnInputHandlingThread(
std::unique_ptr<WebCoalescedInputEvent>);
+ // The kInputBlocking task runner is for tasks which are on the critical path
+ // of showing the effect of an already-received input event, and should be
+ // prioritized above handling new input.
+ enum class TaskRunnerType { kDefault = 0, kInputBlocking = 1 };
+
// Returns the task runner for the thread that receives input. i.e. the
// "Mojo-bound" thread.
- const scoped_refptr<base::SingleThreadTaskRunner>& InputThreadTaskRunner()
- const;
+ const scoped_refptr<base::SingleThreadTaskRunner>& InputThreadTaskRunner(
+ TaskRunnerType type = TaskRunnerType::kDefault) const;
void LogInputTimingUMA();
@@ -275,7 +285,10 @@ class PLATFORM_EXPORT WidgetInputHandlerManager final
// Any thread can access these variables.
scoped_refptr<MainThreadEventQueue> input_event_queue_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ compositor_thread_default_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ compositor_thread_input_blocking_task_runner_;
absl::optional<cc::TouchAction> allowed_touch_action_;
@@ -334,8 +347,6 @@ class PLATFORM_EXPORT WidgetInputHandlerManager final
std::unique_ptr<SynchronousCompositorProxyRegistry>
synchronous_compositor_registry_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(WidgetInputHandlerManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base.cc b/chromium/third_party/blink/renderer/platform/widget/widget_base.cc
index bcf11465aa1..cc559340816 100644
--- a/chromium/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/chromium/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -13,6 +13,7 @@
#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/ukm_manager.h"
#include "components/viz/common/features.h"
#include "components/viz/common/switches.h"
@@ -26,7 +27,6 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_input_event_attribution.h"
#include "third_party/blink/public/common/switches.h"
-#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/mojom/input/pointer_lock_context.mojom-blink.h"
#include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom-blink.h"
#include "third_party/blink/public/mojom/widget/visual_properties.mojom-blink.h"
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"
#include "third_party/blink/renderer/platform/widget/widget_base_client.h"
#include "ui/base/ime/mojom/text_input_state.mojom-blink.h"
+#include "ui/display/screen_info.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/presentation_feedback.h"
@@ -104,19 +105,19 @@ ui::TextInputMode ConvertWebTextInputMode(blink::WebTextInputMode mode) {
return static_cast<ui::TextInputMode>(mode);
}
-unsigned OrientationTypeToAngle(mojom::blink::ScreenOrientation type) {
+unsigned OrientationTypeToAngle(display::mojom::blink::ScreenOrientation type) {
unsigned angle;
// FIXME(ostap): This relationship between orientationType and
// orientationAngle is temporary. The test should be able to specify
// the angle in addition to the orientation type.
switch (type) {
- case mojom::blink::ScreenOrientation::kLandscapePrimary:
+ case display::mojom::blink::ScreenOrientation::kLandscapePrimary:
angle = 90;
break;
- case mojom::blink::ScreenOrientation::kLandscapeSecondary:
+ case display::mojom::blink::ScreenOrientation::kLandscapeSecondary:
angle = 270;
break;
- case mojom::blink::ScreenOrientation::kPortraitSecondary:
+ case display::mojom::blink::ScreenOrientation::kPortraitSecondary:
angle = 180;
break;
default:
@@ -175,7 +176,7 @@ WidgetBase::~WidgetBase() {
void WidgetBase::InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
bool for_child_local_root_frame,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const cc::LayerTreeSettings* settings,
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler) {
@@ -192,7 +193,7 @@ void WidgetBase::InitializeCompositing(
absl::optional<cc::LayerTreeSettings> default_settings;
if (!settings) {
- const ScreenInfo& screen_info = screen_infos.current();
+ const display::ScreenInfo& screen_info = screen_infos.current();
default_settings = GenerateLayerTreeSettings(
compositing_thread_scheduler, for_child_local_root_frame,
screen_info.rect.size(), screen_info.device_scale_factor);
@@ -210,16 +211,11 @@ void WidgetBase::InitializeCompositing(
FrameWidget* frame_widget = client_->FrameWidget();
+ // |compositor_thread_scheduler| will be null for a popup (since it has no
+ // FrameWidget) or in tests without a compositor thread.
scheduler::WebThreadScheduler* compositor_thread_scheduler =
- scheduler::WebThreadScheduler::CompositorThreadScheduler();
- scoped_refptr<base::SingleThreadTaskRunner> compositor_input_task_runner;
- // Use the compositor thread task runner unless this is a popup or other such
- // non-frame widgets. The |compositor_thread_scheduler| can be null in tests
- // without a compositor thread.
- if (frame_widget && compositor_thread_scheduler) {
- compositor_input_task_runner =
- compositor_thread_scheduler->DefaultTaskRunner();
- }
+ frame_widget ? scheduler::WebThreadScheduler::CompositorThreadScheduler()
+ : nullptr;
// We only use an external input handler for frame widgets because only
// frames use the compositor for input handling. Other kinds of widgets
@@ -228,8 +224,8 @@ void WidgetBase::InitializeCompositing(
bool uses_input_handler = frame_widget;
widget_input_handler_manager_ = WidgetInputHandlerManager::Create(
weak_ptr_factory_.GetWeakPtr(), std::move(frame_widget_input_handler),
- never_composited_, std::move(compositor_input_task_runner),
- main_thread_scheduler, uses_input_handler);
+ never_composited_, compositor_thread_scheduler, main_thread_scheduler,
+ uses_input_handler);
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
@@ -252,7 +248,7 @@ void WidgetBase::InitializeCompositing(
void WidgetBase::InitializeNonCompositing() {
DCHECK(!initialized_);
// WidgetBase users implicitly expect one default ScreenInfo to exist.
- screen_infos_ = ScreenInfos(ScreenInfo());
+ screen_infos_ = display::ScreenInfos(display::ScreenInfo());
initialized_ = true;
}
@@ -490,10 +486,11 @@ void WidgetBase::OnDeferMainFrameUpdatesChanged(bool defer) {
widget_input_handler_manager_->OnDeferMainFrameUpdatesChanged(defer);
}
-void WidgetBase::OnDeferCommitsChanged(bool defer) {
+void WidgetBase::OnDeferCommitsChanged(bool defer,
+ cc::PaintHoldingReason reason) {
// The input handler wants to know about the commit status for metric purposes
// and to enable/disable input.
- widget_input_handler_manager_->OnDeferCommitsChanged(defer);
+ widget_input_handler_manager_->OnDeferCommitsChanged(defer, reason);
}
void WidgetBase::DidBeginMainFrame() {
@@ -822,6 +819,14 @@ void WidgetBase::UpdateTooltipUnderCursor(const String& tooltip_text,
tooltip_text.IsEmpty() ? "" : tooltip_text, ToBaseTextDirection(dir));
}
+void WidgetBase::UpdateTooltipFromKeyboard(const String& tooltip_text,
+ TextDirection dir,
+ const gfx::Rect& bounds) {
+ widget_host_->UpdateTooltipFromKeyboard(
+ tooltip_text.IsEmpty() ? "" : tooltip_text, ToBaseTextDirection(dir),
+ BlinkSpaceToEnclosedDIPs(bounds));
+}
+
void WidgetBase::ShowVirtualKeyboard() {
UpdateTextInputStateInternal(true, false);
}
@@ -1093,7 +1098,7 @@ bool WidgetBase::ShouldUpdateCompositionInfo(const gfx::Range& range,
return true;
if (bounds.size() != composition_character_bounds_.size())
return true;
- for (size_t i = 0; i < bounds.size(); ++i) {
+ for (wtf_size_t i = 0; i < bounds.size(); ++i) {
if (bounds[i] != composition_character_bounds_[i])
return true;
}
@@ -1361,9 +1366,9 @@ void WidgetBase::RequestAnimationAfterDelayTimerFired(TimerBase*) {
void WidgetBase::UpdateSurfaceAndScreenInfo(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect,
- const ScreenInfos& screen_infos) {
- ScreenInfos new_screen_infos = screen_infos;
- ScreenInfo& new_screen_info = new_screen_infos.mutable_current();
+ const display::ScreenInfos& screen_infos) {
+ display::ScreenInfos new_screen_infos = screen_infos;
+ display::ScreenInfo& new_screen_info = new_screen_infos.mutable_current();
// If there is a screen orientation override apply it.
if (auto orientation_override = client_->ScreenOrientationOverride()) {
@@ -1374,12 +1379,13 @@ void WidgetBase::UpdateSurfaceAndScreenInfo(
// RenderWidgetHostImpl::SynchronizeVisualProperties uses similar logic to
// detect orientation changes on the display currently showing the widget.
- const ScreenInfo& previous_screen_info = screen_infos_.current();
+ const display::ScreenInfo& previous_screen_info = screen_infos_.current();
bool orientation_changed =
previous_screen_info.orientation_angle !=
new_screen_info.orientation_angle ||
previous_screen_info.orientation_type != new_screen_info.orientation_type;
- ScreenInfo previous_original_screen_info = client_->GetOriginalScreenInfo();
+ display::ScreenInfo previous_original_screen_info =
+ client_->GetOriginalScreenInfo();
local_surface_id_from_parent_ = new_local_surface_id;
screen_infos_ = new_screen_infos;
@@ -1403,14 +1409,15 @@ void WidgetBase::UpdateSurfaceAndScreenInfo(
client_->DidUpdateSurfaceAndScreen(previous_original_screen_info);
}
-void WidgetBase::UpdateScreenInfo(const ScreenInfos& new_screen_infos) {
+void WidgetBase::UpdateScreenInfo(
+ const display::ScreenInfos& new_screen_infos) {
UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_,
CompositorViewportRect(), new_screen_infos);
}
void WidgetBase::UpdateCompositorViewportAndScreenInfo(
const gfx::Rect& compositor_viewport_pixel_rect,
- const ScreenInfos& new_screen_infos) {
+ const display::ScreenInfos& new_screen_infos) {
UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_,
compositor_viewport_pixel_rect, new_screen_infos);
}
@@ -1428,7 +1435,7 @@ void WidgetBase::UpdateSurfaceAndCompositorRect(
compositor_viewport_pixel_rect, screen_infos_);
}
-const ScreenInfo& WidgetBase::GetScreenInfo() {
+const display::ScreenInfo& WidgetBase::GetScreenInfo() {
return screen_infos_.current();
}
diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base.h b/chromium/third_party/blink/renderer/platform/widget/widget_base.h
index 5eb9c42a9b9..1336009400a 100644
--- a/chromium/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/chromium/third_party/blink/renderer/platform/widget/widget_base.h
@@ -8,6 +8,7 @@
#include "base/time/time.h"
#include "cc/paint/element_id.h"
#include "cc/trees/browser_controls_params.h"
+#include "cc/trees/paint_holding_reason.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
@@ -37,9 +38,12 @@ namespace ui {
class Cursor;
}
+namespace display {
+struct ScreenInfos;
+}
+
namespace blink {
class ImeEventGuard;
-struct ScreenInfos;
class LayerTreeView;
class WidgetBaseClient;
class WidgetInputHandlerManager;
@@ -84,7 +88,7 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
void InitializeCompositing(
scheduler::WebAgentGroupScheduler& agent_group_scheduler,
bool for_child_local_root_frame,
- const ScreenInfos& screen_infos,
+ const display::ScreenInfos& screen_infos,
const cc::LayerTreeSettings* settings,
base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
frame_widget_input_handler);
@@ -130,7 +134,8 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
const cc::CompositorCommitData& commit_data) override;
void BeginMainFrame(base::TimeTicks frame_time) override;
void OnDeferMainFrameUpdatesChanged(bool) override;
- void OnDeferCommitsChanged(bool) override;
+ void OnDeferCommitsChanged(bool defer_status,
+ cc::PaintHoldingReason reason) override;
void DidBeginMainFrame() override;
void RequestNewLayerTreeFrameSink(
LayerTreeFrameSinkCallback callback) override;
@@ -187,6 +192,12 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
WidgetBaseClient* client() { return client_; }
void UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir);
+ // This function allows us to trigger a tooltip to show from a keypress. The
+ // tooltip will be positioned relative to the gfx::Rect. That rect corresponds
+ // to the focused element's bounds in widget-relative DIPS.
+ void UpdateTooltipFromKeyboard(const String& tooltip_text,
+ TextDirection dir,
+ const gfx::Rect& bounds);
// Posts a task with the given delay, then calls ScheduleAnimation() on the
// WidgetBaseClient.
@@ -315,28 +326,28 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
void UpdateSurfaceAndScreenInfo(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect,
- const ScreenInfos& new_screen_infos);
+ const display::ScreenInfos& new_screen_infos);
// Similar to UpdateSurfaceAndScreenInfo but the screen info remains the same.
void UpdateSurfaceAndCompositorRect(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect);
// Similar to UpdateSurfaceAndScreenInfo but the surface allocation
// and compositor viewport rect remains the same.
- void UpdateScreenInfo(const ScreenInfos& new_screen_infos);
+ void UpdateScreenInfo(const display::ScreenInfos& new_screen_infos);
// Similar to UpdateSurfaceAndScreenInfo but the surface allocation
// remains the same.
void UpdateCompositorViewportAndScreenInfo(
const gfx::Rect& compositor_viewport_pixel_rect,
- const ScreenInfos& new_screen_infos);
+ const display::ScreenInfos& new_screen_infos);
// Similar to UpdateSurfaceAndScreenInfo but the surface allocation and screen
// info remains the same.
void UpdateCompositorViewportRect(
const gfx::Rect& compositor_viewport_pixel_rect);
- const ScreenInfo& GetScreenInfo();
+ const display::ScreenInfo& GetScreenInfo();
// Accessors for information about available screens and the current screen.
- void set_screen_infos(const ScreenInfos& s) { screen_infos_ = s; }
- const ScreenInfos& screen_infos() const { return screen_infos_; }
+ void set_screen_infos(const display::ScreenInfos& s) { screen_infos_ = s; }
+ const display::ScreenInfos& screen_infos() const { return screen_infos_; }
const viz::LocalSurfaceId& local_surface_id_from_parent() const {
return local_surface_id_from_parent_;
@@ -450,7 +461,7 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
// Info about available screens and which is currently showing the WidgetBase.
// Rects in these structures do not include any scaling by device scale
// factor, so are in DIPs, not blink coordinate space.
- ScreenInfos screen_infos_;
+ display::ScreenInfos screen_infos_;
viz::LocalSurfaceId local_surface_id_from_parent_;
diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h b/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h
index 32208ec6c64..f9553b32747 100644
--- a/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h
+++ b/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h
@@ -15,11 +15,11 @@
#include "cc/trees/layer_tree_host_client.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
-#include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
#include "third_party/blink/public/platform/input/input_handler_proxy.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/public/platform/web_text_input_type.h"
#include "third_party/blink/public/web/web_lifecycle_update.h"
+#include "ui/display/mojom/screen_orientation.mojom-blink.h"
namespace cc {
class LayerTreeFrameSink;
@@ -127,7 +127,8 @@ class WidgetBaseClient {
virtual bool SupportsBufferedTouchEvents() = 0;
virtual void DidHandleKeyEvent() {}
- virtual bool WillHandleGestureEvent(const WebGestureEvent& event) = 0;
+ virtual void WillHandleGestureEvent(const WebGestureEvent& event,
+ bool* suppress) = 0;
virtual void WillHandleMouseEvent(const WebMouseEvent& event) = 0;
virtual void ObserveGestureEventAndResult(
const WebGestureEvent& gesture_event,
@@ -177,17 +178,17 @@ class WidgetBaseClient {
virtual void OrientationChanged() {}
// Return the original (non-emulated) screen info.
- virtual const ScreenInfo& GetOriginalScreenInfo() = 0;
+ virtual const display::ScreenInfo& GetOriginalScreenInfo() = 0;
// Indication that the surface and screen were updated.
virtual void DidUpdateSurfaceAndScreen(
- const ScreenInfo& previous_original_screen_info) {}
+ const display::ScreenInfo& previous_original_screen_info) {}
// Return the viewport visible rect.
virtual gfx::Rect ViewportVisibleRect() = 0;
// The screen orientation override.
- virtual absl::optional<mojom::blink::ScreenOrientation>
+ virtual absl::optional<display::mojom::blink::ScreenOrientation>
ScreenOrientationOverride() {
return absl::nullopt;
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
index e8f3789f241..d30097ae3cd 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -118,6 +118,7 @@ component("wtf") {
"text/atomic_string_table.h",
"text/base64.cc",
"text/base64.h",
+ "text/case_folding_hash.h",
"text/case_map.cc",
"text/case_map.h",
"text/character_names.h",
@@ -173,17 +174,18 @@ component("wtf") {
"text/text_stream.cc",
"text/text_stream.h",
"text/unicode.h",
+ "text/unicode_string.h",
"text/utf8.cc",
"text/utf8.h",
"text/wtf_string.cc",
"text/wtf_string.h",
+ "text/wtf_uchar.h",
"thread_restriction_verifier.h",
"thread_safe_ref_counted.h",
"thread_specific.h",
"threading.cc",
"threading.h",
"threading_primitives.h",
- "tree_node.h",
"type_traits.h",
"uuid.cc",
"uuid.h",
@@ -206,14 +208,12 @@ component("wtf") {
public_configs = [
":wtf_config",
-
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- "//build/config/compiler:no_size_t_to_int_warning",
"//third_party/blink/renderer:features",
]
deps = [
":buildflags",
+ "//base/allocator:buildflags",
"//build:chromeos_buildflags",
# TODO(tkent): WTF should not depend on it.
@@ -337,16 +337,12 @@ source_set("wtf_unittests_sources") {
"text/text_encoding_test.cc",
"text/wtf_string_test.cc",
"threading_primitives_test.cc",
- "tree_node_test.cc",
"type_traits_test.cc",
"uuid_test.cc",
"vector_backed_linked_list_test.cc",
"vector_test.cc",
]
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
if (is_win) {
cflags = [ "/wd4068" ] # Unknown pragma.
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/DEPS b/chromium/third_party/blink/renderer/platform/wtf/DEPS
index b3b1c0ec23f..a78a9a2fe1e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/DEPS
+++ b/chromium/third_party/blink/renderer/platform/wtf/DEPS
@@ -1,8 +1,6 @@
include_rules = [
# To only allow a subset of base/ in Blink, we explicitly list all
# directories and files instead of writing 'base/'.
- "+base/allocator/buildflags.h",
- "+base/allocator/partition_allocator",
"+base/atomic_ref_count.h",
"+base/auto_reset.h",
"+base/bind.h",
@@ -28,7 +26,7 @@ include_rules = [
"+base/threading",
"+base/time/time.h",
"+base/tuple.h",
- "+third_party/abseil-cpp/absl/types/optional.h",
+ "+base/win/windows_types.h",
# To avoid recursive dependency, we impose a blanket ban on using other
# platform files. Think carefully if you want to relax this restriction.
"-third_party/blink/renderer/platform",
diff --git a/chromium/third_party/blink/renderer/platform/wtf/OWNERS b/chromium/third_party/blink/renderer/platform/wtf/OWNERS
index 024e0c837f5..9707fda951a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/wtf/OWNERS
@@ -1,6 +1,4 @@
-erik.corry@gmail.com
haraken@chromium.org
-jochen@chromium.org
thakis@chromium.org
tkent@chromium.org
yutak@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
index 03b0c45dbc4..55f73c31394 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
@@ -7,7 +7,6 @@
#include <atomic>
-#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/check_op.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
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 e74b239a4b5..081077b53ef 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
@@ -93,7 +93,7 @@ class WTF_EXPORT PartitionAllocator {
}
template <typename T>
- static void TraceBackingStoreIfMarked(T**) {}
+ static void TraceBackingStoreIfMarked(T*) {}
template <typename T>
static void BackingWriteBarrier(T**) {}
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 a46aa9380cc..fcb308761a8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
@@ -30,10 +30,14 @@
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
+#include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/memory_reclaimer.h"
#include "base/allocator/partition_allocator/oom.h"
#include "base/allocator/partition_allocator/page_allocator.h"
+#include "base/allocator/partition_allocator/partition_alloc.h"
+#include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/partition_alloc_features.h"
+#include "base/allocator/partition_allocator/partition_root.h"
#include "base/debug/alias.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
@@ -48,7 +52,7 @@ namespace WTF {
const char* const Partitions::kAllocatedObjectPoolName =
"partition_alloc/allocated_objects";
-#if PA_ALLOW_PCSCAN
+#if defined(PA_ALLOW_PCSCAN)
// Runs PCScan on WTF partitions.
const base::Feature kPCScanBlinkPartitions{"PCScanBlinkPartitions",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -75,12 +79,17 @@ void Partitions::Initialize() {
bool Partitions::InitializeOnce() {
#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
static base::NoDestructor<base::PartitionAllocator> fast_malloc_allocator{};
- fast_malloc_allocator->init(
- {base::PartitionOptions::AlignedAlloc::kDisallowed,
- base::PartitionOptions::ThreadCache::kEnabled,
- base::PartitionOptions::Quarantine::kAllowed,
- base::PartitionOptions::Cookies::kAllowed,
- base::PartitionOptions::RefCount::kDisallowed});
+ fast_malloc_allocator->init({
+ base::PartitionOptions::AlignedAlloc::kDisallowed,
+ base::PartitionOptions::ThreadCache::kEnabled,
+ base::PartitionOptions::Quarantine::kAllowed,
+ base::PartitionOptions::Cookies::kAllowed,
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_IN_RENDERER_PROCESS)
+ base::PartitionOptions::RefCount::kAllowed
+#else
+ base::PartitionOptions::RefCount::kDisallowed
+#endif
+ });
fast_malloc_root_ = fast_malloc_allocator->root();
#endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
@@ -92,28 +101,41 @@ bool Partitions::InitializeOnce() {
base::PartitionAllocGlobalInit(&Partitions::HandleOutOfMemory);
- array_buffer_allocator->init(
- {base::PartitionOptions::AlignedAlloc::kDisallowed,
- base::PartitionOptions::ThreadCache::kDisabled,
- base::PartitionOptions::Quarantine::kAllowed,
- base::PartitionOptions::Cookies::kAllowed,
- base::PartitionOptions::RefCount::kDisallowed});
- buffer_allocator->init({base::PartitionOptions::AlignedAlloc::kDisallowed,
- base::PartitionOptions::ThreadCache::kDisabled,
- base::PartitionOptions::Quarantine::kAllowed,
- base::PartitionOptions::Cookies::kAllowed,
- base::PartitionOptions::RefCount::kDisallowed});
- layout_allocator->init({base::PartitionOptions::AlignedAlloc::kDisallowed,
- base::PartitionOptions::ThreadCache::kDisabled,
- base::PartitionOptions::Quarantine::kAllowed,
- base::PartitionOptions::Cookies::kAllowed,
- base::PartitionOptions::RefCount::kDisallowed});
+ // RefCount disallowed because it will prevent allocations from being 16B
+ // aligned as required by ArrayBufferContents.
+ array_buffer_allocator->init({
+ base::PartitionOptions::AlignedAlloc::kDisallowed,
+ base::PartitionOptions::ThreadCache::kDisabled,
+ base::PartitionOptions::Quarantine::kAllowed,
+ base::PartitionOptions::Cookies::kAllowed,
+ base::PartitionOptions::RefCount::kDisallowed
+ });
+ buffer_allocator->init({
+ base::PartitionOptions::AlignedAlloc::kDisallowed,
+ base::PartitionOptions::ThreadCache::kDisabled,
+ base::PartitionOptions::Quarantine::kAllowed,
+ base::PartitionOptions::Cookies::kAllowed,
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_IN_RENDERER_PROCESS)
+ base::PartitionOptions::RefCount::kAllowed
+#else
+ base::PartitionOptions::RefCount::kDisallowed
+#endif
+ });
+ // RefCount disallowed because layout code will be excluded from raw_ptr<T>
+ // rewrite due to performance.
+ layout_allocator->init({
+ base::PartitionOptions::AlignedAlloc::kDisallowed,
+ base::PartitionOptions::ThreadCache::kDisabled,
+ base::PartitionOptions::Quarantine::kAllowed,
+ base::PartitionOptions::Cookies::kAllowed,
+ base::PartitionOptions::RefCount::kDisallowed
+ });
array_buffer_root_ = array_buffer_allocator->root();
buffer_root_ = buffer_allocator->root();
layout_root_ = layout_allocator->root();
-#if PA_ALLOW_PCSCAN
+#if defined(PA_ALLOW_PCSCAN)
if (base::FeatureList::IsEnabled(base::features::kPartitionAllocPCScan) ||
base::FeatureList::IsEnabled(kPCScanBlinkPartitions)) {
base::internal::PCScan::RegisterNonScannableRoot(array_buffer_root_);
@@ -122,7 +144,7 @@ bool Partitions::InitializeOnce() {
#endif
base::internal::PCScan::RegisterScannableRoot(buffer_root_);
}
-#endif
+#endif // defined(PA_ALLOW_PCSCAN)
initialized_ = true;
return initialized_;
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 9da09e149ea..30345cdd803 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALLOCATOR_PARTITIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALLOCATOR_PARTITIONS_H_
-#include "base/allocator/partition_allocator/partition_alloc.h"
+#include "base/allocator/partition_allocator/partition_alloc_forward.h"
#include "base/check.h"
#include "base/memory/scoped_refptr.h"
#include "base/numerics/checked_math.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h b/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
index 58e7c6ea1f4..3b2445ec29a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
@@ -47,6 +47,8 @@
namespace base {
template <typename, typename>
class RefCountedThreadSafe;
+template <typename>
+class FileErrorOr;
class TimeDelta;
class TimeTicks;
class Time;
@@ -70,6 +72,7 @@ struct SyncToken;
namespace media {
class VideoFrame;
struct VideoCaptureFeedback;
+struct VideoTransformation;
} // namespace media
namespace mojo {
@@ -81,6 +84,10 @@ template <typename Interface>
class PendingAssociatedRemote;
template <typename Interface>
class PendingAssociatedReceiver;
+template <typename Interface>
+class ScopedHandleBase;
+class DataPipeProducerHandle;
+typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
} // namespace mojo
namespace WTF {
@@ -145,6 +152,12 @@ struct CrossThreadCopier<sk_sp<T>>
"sk_sp<T> can be passed across threads only if T is SkRefCnt.");
};
+template <typename T>
+struct CrossThreadCopier<base::FileErrorOr<T>>
+ : public CrossThreadCopierPassThrough<base::FileErrorOr<T>> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
template <>
struct CrossThreadCopier<base::TimeDelta>
: public CrossThreadCopierPassThrough<base::TimeDelta> {
@@ -313,6 +326,13 @@ struct CrossThreadCopier<mojo::PendingAssociatedReceiver<Interface>>
};
template <>
+struct CrossThreadCopier<mojo::ScopedDataPipeProducerHandle>
+ : public CrossThreadCopierByValuePassThrough<
+ mojo::ScopedDataPipeProducerHandle> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+template <>
struct CrossThreadCopier<blink::MessagePortChannel> {
STATIC_ONLY(CrossThreadCopier);
using Type = blink::MessagePortChannel;
@@ -362,6 +382,12 @@ struct CrossThreadCopier<std::vector<scoped_refptr<media::VideoFrame>>>
STATIC_ONLY(CrossThreadCopier);
};
+template <>
+struct CrossThreadCopier<media::VideoTransformation>
+ : public CrossThreadCopierPassThrough<media::VideoTransformation> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
} // namespace WTF
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CROSS_THREAD_COPIER_H_
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 495eea61965..ecd868b7aed 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/date_math.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/date_math.cc
@@ -79,7 +79,7 @@
#include <limits>
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.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/platform/wtf/decimal.cc b/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
index c1dc5537ed9..bfcc5014953 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
@@ -33,7 +33,6 @@
#include <algorithm>
#include <cfloat>
-#include "base/macros.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -64,6 +63,9 @@ class SpecialValueHandler {
};
SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
+ SpecialValueHandler(const SpecialValueHandler&) = delete;
+ SpecialValueHandler& operator=(const SpecialValueHandler&) = delete;
+
HandleResult Handle();
Decimal Value() const;
@@ -77,8 +79,6 @@ class SpecialValueHandler {
const Decimal& lhs_;
const Decimal& rhs_;
Result result_ = kResultIsUnknown;
-
- DISALLOW_COPY_AND_ASSIGN(SpecialValueHandler);
};
SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
diff --git a/chromium/third_party/blink/renderer/platform/wtf/deque.h b/chromium/third_party/blink/renderer/platform/wtf/deque.h
index d79fd509716..abbc2a0f5a9 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/deque.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/deque.h
@@ -35,7 +35,6 @@
#include <iterator>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -182,10 +181,10 @@ class Deque
public:
BackingBuffer() : Base() {}
explicit BackingBuffer(wtf_size_t capacity) : Base(capacity) {}
+ BackingBuffer(const BackingBuffer&) = delete;
+ BackingBuffer& operator=(const BackingBuffer&) = delete;
void SetSize(wtf_size_t size) { size_ = size; }
-
- DISALLOW_COPY_AND_ASSIGN(BackingBuffer);
};
typedef VectorTypeOperations<T, Allocator> TypeOperations;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/doubly_linked_list.h b/chromium/third_party/blink/renderer/platform/wtf/doubly_linked_list.h
index 737499bde51..a85b55f94de 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/doubly_linked_list.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/doubly_linked_list.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DOUBLY_LINKED_LIST_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DOUBLY_LINKED_LIST_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
@@ -79,6 +78,8 @@ class DoublyLinkedList {
public:
DoublyLinkedList();
+ DoublyLinkedList(const DoublyLinkedList&) = delete;
+ DoublyLinkedList& operator=(const DoublyLinkedList&) = delete;
bool IsEmpty() const;
wtf_size_t size() const; // This is O(n).
@@ -94,6 +95,9 @@ class DoublyLinkedList {
void Remove(T*);
struct AddResult {
+ STACK_ALLOCATED();
+
+ public:
T* node;
bool is_new_entry;
@@ -121,8 +125,6 @@ class DoublyLinkedList {
protected:
PointerType head_;
PointerType tail_;
-
- DISALLOW_COPY_AND_ASSIGN(DoublyLinkedList);
};
template <typename T, typename PointerType>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa.h
index 34a99ec603d..6db1d86a308 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa.h
@@ -24,7 +24,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/third_party/double_conversion/double-conversion/double-conversion.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/functional.h b/chromium/third_party/blink/renderer/platform/wtf/functional.h
index e626c1a0444..63a115ee981 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/functional.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/functional.h
@@ -197,6 +197,9 @@ class ThreadCheckingCallbackWrapper<CallbackType, R(Args...)> {
public:
explicit ThreadCheckingCallbackWrapper(CallbackType callback)
: callback_(std::move(callback)) {}
+ ThreadCheckingCallbackWrapper(const ThreadCheckingCallbackWrapper&) = delete;
+ ThreadCheckingCallbackWrapper& operator=(
+ const ThreadCheckingCallbackWrapper&) = delete;
~ThreadCheckingCallbackWrapper() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -224,8 +227,6 @@ class ThreadCheckingCallbackWrapper<CallbackType, R(Args...)> {
SEQUENCE_CHECKER(sequence_checker_);
CallbackType callback_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadCheckingCallbackWrapper);
};
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h b/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h
index 0da456c2c19..dd753ecfcb8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h
@@ -21,7 +21,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_COUNTED_SET_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_COUNTED_SET_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -62,6 +61,9 @@ class HashCountedSet {
"HeapHashCountedSet<Member<T>> instead.");
}
+ HashCountedSet(const HashCountedSet&) = delete;
+ HashCountedSet& operator=(const HashCountedSet&) = delete;
+
void swap(HashCountedSet& other) { impl_.swap(other.impl_); }
unsigned size() const { return impl_.size(); }
@@ -117,8 +119,6 @@ class HashCountedSet {
private:
ImplType impl_;
-
- DISALLOW_COPY_AND_ASSIGN(HashCountedSet);
};
template <typename T, typename U, typename V, typename W>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_map.h b/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
index b58e6472183..8c6f0bfc823 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
@@ -157,6 +157,10 @@ class HashMap {
const_iterator find(KeyPeekInType) const;
bool Contains(KeyPeekInType) const;
MappedPeekType at(KeyPeekInType) const;
+ // Deprecated variant of at(). Created for refactor described in
+ // https://crbug.com/1058527. Returns a reference to the mapped value or the
+ // empty value if no mapped value exists.
+ MappedPeekType DeprecatedAtOrEmptyValue(KeyPeekInType) const;
// replaces value but not key if key is already present return value is a
// pair of the iterator to the key location, and a boolean that's true if a
@@ -586,6 +590,17 @@ template <typename T,
typename Y>
typename HashMap<T, U, V, W, X, Y>::MappedPeekType
HashMap<T, U, V, W, X, Y>::at(KeyPeekInType key) const {
+ return DeprecatedAtOrEmptyValue(key);
+}
+
+template <typename T,
+ typename U,
+ typename V,
+ typename W,
+ typename X,
+ typename Y>
+typename HashMap<T, U, V, W, X, Y>::MappedPeekType
+HashMap<T, U, V, W, X, Y>::DeprecatedAtOrEmptyValue(KeyPeekInType key) const {
const ValueType* entry = impl_.Lookup(key);
if (!entry)
return MappedTraits::Peek(MappedTraits::EmptyValue());
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
index 5ebc941395f..2381e3cae37 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
@@ -94,6 +94,7 @@ class HashSet {
iterator begin() const;
iterator end() const;
+ // Returns an iterator to the found element, or end() if not found.
iterator find(ValuePeekInType) const;
bool Contains(ValuePeekInType) const;
@@ -122,6 +123,7 @@ class HashSet {
template <typename HashTranslator, typename T>
AddResult AddWithTranslator(T&&);
+ // Does nothing if the value is not found.
void erase(ValuePeekInType);
void erase(iterator);
void clear();
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 d945fa988d3..28789036dbf 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
@@ -79,6 +79,37 @@ TEST(HashSetTest, Iteration) {
EXPECT_EQ((1 << 10) - 1, encountered_keys);
}
+TEST(HashSetTest, FindAndErase) {
+ HashSet<int> set;
+ set.insert(12);
+ set.insert(4);
+ EXPECT_EQ(2U, set.size());
+
+ auto it = set.find(12);
+ EXPECT_NE(set.end(), it);
+ EXPECT_EQ(12, *it);
+
+ it = set.find(4);
+ EXPECT_NE(set.end(), it);
+ EXPECT_EQ(4, *it);
+
+ EXPECT_EQ(set.end(), set.find(6));
+
+ // Now erase a key in the set, and test again.
+ set.erase(12);
+ EXPECT_EQ(1U, set.size());
+
+ EXPECT_EQ(set.end(), set.find(12));
+
+ it = set.find(4);
+ EXPECT_NE(set.end(), it);
+ EXPECT_EQ(4, *it);
+
+ // Erase a key not in the set; should be a no-op.
+ set.erase(6);
+ EXPECT_EQ(1U, set.size());
+}
+
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 cc1a7843e46..5a6d7bcb65a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -1879,7 +1879,7 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
}
}
- Allocator::TraceBackingStoreIfMarked(&new_hash_table.table_);
+ Allocator::TraceBackingStoreIfMarked(new_hash_table.table_);
ValueType* old_table = table_;
unsigned old_table_size = table_size_;
@@ -2061,9 +2061,9 @@ void HashTable<Key,
// Weak processing is omitted when no backing store is present. In case such
// an empty table is later on used it needs to be strongified.
if (table_)
- Allocator::TraceBackingStoreIfMarked(&table_);
+ Allocator::TraceBackingStoreIfMarked(table_);
if (other.table_)
- Allocator::TraceBackingStoreIfMarked(&other.table_);
+ Allocator::TraceBackingStoreIfMarked(other.table_);
}
std::swap(table_size_, other.table_size_);
std::swap(key_count_, other.key_count_);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/leak_annotations.h b/chromium/third_party/blink/renderer/platform/wtf/leak_annotations.h
index 79f132cc869..f9410fcb435 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/leak_annotations.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/leak_annotations.h
@@ -35,7 +35,6 @@
// This file defines macros for working with LeakSanitizer, allowing memory
// and allocations to be registered as exempted from LSan consideration.
-#include "base/macros.h"
#if defined(LEAK_SANITIZER)
#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
@@ -47,10 +46,10 @@ namespace WTF {
class LeakSanitizerDisabler {
public:
LeakSanitizerDisabler() { __lsan_disable(); }
+ LeakSanitizerDisabler(const LeakSanitizerDisabler&) = delete;
+ LeakSanitizerDisabler& operator=(const LeakSanitizerDisabler&) = delete;
~LeakSanitizerDisabler() { __lsan_enable(); }
-
- DISALLOW_COPY_AND_ASSIGN(LeakSanitizerDisabler);
};
// WTF_INTERNAL_LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the
diff --git a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h
index 3a1a4abd2dc..3f0b81cf996 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h
@@ -23,7 +23,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_LINKED_HASH_SET_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_LINKED_HASH_SET_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
index 5eb18e84318..48e0b08a4a1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
@@ -122,10 +122,10 @@ TEST(LinkedHashSetTest, CopyConstructAndAssignString) {
auto it1 = set1.begin();
auto it2 = set2.begin();
auto it3 = set3.begin();
- for (int i = 0; i < 3; i++) {
- EXPECT_EQ(*it1, String(Vector<UChar>({'1' + i})));
- EXPECT_EQ(*it2, String(Vector<UChar>({'1' + i})));
- EXPECT_EQ(*it3, String(Vector<UChar>({'1' + i})));
+ for (char16_t i = '1'; i < '4'; i++) {
+ EXPECT_EQ(*it1, String(Vector<UChar>({i})));
+ EXPECT_EQ(*it2, String(Vector<UChar>({i})));
+ EXPECT_EQ(*it3, String(Vector<UChar>({i})));
++it1;
++it2;
++it3;
@@ -139,10 +139,10 @@ TEST(LinkedHashSetTest, CopyConstructAndAssignString) {
it1 = set1.begin();
it2 = set2.begin();
it3 = set3.begin();
- for (int i = 0; i < 3; i++) {
- EXPECT_EQ(*it1, String(Vector<UChar>({'1', '1' + i})));
- EXPECT_EQ(*it2, String(Vector<UChar>({'1' + i})));
- EXPECT_EQ(*it3, String(Vector<UChar>({'1' + i})));
+ for (char16_t i = '1'; i < '4'; i++) {
+ EXPECT_EQ(*it1, String(Vector<UChar>({'1', i})));
+ EXPECT_EQ(*it2, String(Vector<UChar>({i})));
+ EXPECT_EQ(*it3, String(Vector<UChar>({i})));
++it1;
++it2;
++it3;
@@ -205,8 +205,8 @@ TEST(LinkedHashSetTest, MoveConstructAndAssignString) {
set3 = std::move(set2);
EXPECT_EQ(set3.size(), 3u);
auto it = set3.begin();
- for (int i = 0; i < 3; i++) {
- EXPECT_EQ(it->Value(), String(Vector<UChar>({'1' + i})));
+ for (char16_t i = '1'; i < '4'; i++) {
+ EXPECT_EQ(it->Value(), String(Vector<UChar>({i})));
++it;
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_arena.h b/chromium/third_party/blink/renderer/platform/wtf/pod_arena.h
index 0238d923f04..088576467d8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_arena.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_arena.h
@@ -30,7 +30,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -149,6 +148,9 @@ class PODArena final : public RefCounted<PODArena> {
base_ = static_cast<uint8_t*>(allocator_->Allocate(size));
}
+ Chunk(const Chunk&) = delete;
+ Chunk& operator=(const Chunk&) = delete;
+
// Frees the memory allocated from the Allocator in the
// constructor.
~Chunk() { allocator_->Free(base_); }
@@ -173,9 +175,6 @@ class PODArena final : public RefCounted<PODArena> {
uint8_t* base_;
size_t size_;
size_t current_offset_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Chunk);
};
scoped_refptr<Allocator> allocator_;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h b/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
index a7bf147ec6a..06593f0174a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
@@ -26,7 +26,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_INTERVAL_TREE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_INTERVAL_TREE_H_
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/platform/wtf/pod_arena.h"
#include "third_party/blink/renderer/platform/wtf/pod_interval.h"
@@ -88,6 +87,9 @@ class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData>> {
Init();
}
+ PODIntervalTree(const PODIntervalTree&) = delete;
+ PODIntervalTree& operator=(const PODIntervalTree&) = delete;
+
// Returns all intervals in the tree which overlap the given query
// interval. The returned intervals are sorted by increasing low
// endpoint.
@@ -327,8 +329,6 @@ class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData>> {
#else
static void LogVerificationFailedAtNode(IntervalNode const*) {}
#endif
-
- DISALLOW_COPY_AND_ASSIGN(PODIntervalTree);
};
#ifndef NDEBUG
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h b/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
index 4cb678938ed..f1d753bf17a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
@@ -72,7 +72,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_RED_BLACK_TREE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_RED_BLACK_TREE_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/pod_free_list_arena.h"
@@ -248,6 +247,9 @@ class PODRedBlackTree {
color_(kRed),
data_(data) {}
+ Node(const Node&) = delete;
+ Node& operator=(const Node&) = delete;
+
virtual ~Node() = default;
NodeColor GetColor() const { return color_; }
@@ -283,8 +285,6 @@ class PODRedBlackTree {
Node* parent_;
NodeColor color_;
T data_;
-
- DISALLOW_COPY_AND_ASSIGN(Node);
};
protected:
@@ -710,14 +710,14 @@ class PODRedBlackTree {
public:
Counter() : count_(0) {}
+ Counter(const Counter&) = delete;
+ Counter& operator=(const Counter&) = delete;
void Visit(const T&) override { ++count_; }
int Count() const { return count_; }
private:
int count_;
-
- DISALLOW_COPY_AND_ASSIGN(Counter);
};
//----------------------------------------------------------------------
diff --git a/chromium/third_party/blink/renderer/platform/wtf/scoped_logger.h b/chromium/third_party/blink/renderer/platform/wtf/scoped_logger.h
index 3f865e8c36d..2ae5de91c1f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/scoped_logger.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/scoped_logger.h
@@ -8,7 +8,6 @@
#include "base/dcheck_is_on.h"
#include "base/gtest_prod_util.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
@@ -37,6 +36,8 @@ class WTF_EXPORT ScopedLogger {
// the same scope can be added with log(). If condition is false, produce no
// output and do not create a scope.
PRINTF_FORMAT(3, 4) ScopedLogger(bool condition, const char* format, ...);
+ ScopedLogger(const ScopedLogger&) = delete;
+ ScopedLogger& operator=(const ScopedLogger&) = delete;
~ScopedLogger();
PRINTF_FORMAT(2, 3) void Log(const char* format, ...);
@@ -58,8 +59,6 @@ class WTF_EXPORT ScopedLogger {
bool multiline_; // The ')' will go on the same line if there is only one
// entry.
static PrintFunctionPtr print_func_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedLogger);
};
#define WTF_CREATE_SCOPED_LOGGER(name, ...) \
diff --git a/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc b/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc
index cb8c3f8ad3b..fea64485b51 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc
@@ -46,13 +46,13 @@ static inline size_t OffsetInSegment(size_t position) {
}
struct SharedBuffer::SegmentDeleter {
- void operator()(char* p) const { WTF::Partitions::FastFree(p); }
+ void operator()(char* p) const { WTF::Partitions::BufferFree(p); }
};
SharedBuffer::Segment SharedBuffer::CreateSegment() {
return std::unique_ptr<char[], SegmentDeleter>(
- static_cast<char*>(WTF::Partitions::FastMalloc(SharedBuffer::kSegmentSize,
- "WTF::SharedBuffer")));
+ static_cast<char*>(WTF::Partitions::BufferMalloc(
+ SharedBuffer::kSegmentSize, "WTF::SharedBuffer")));
}
SharedBuffer::Iterator& SharedBuffer::Iterator::operator++() {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.h b/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.h
index 1111c52cfb9..7b04c7230c6 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.h
@@ -139,6 +139,11 @@ class WTF_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
AppendInternal(data, size);
}
+ HAS_STRICTLY_TYPED_ARG
+ void Append(const unsigned char* data, STRICTLY_TYPED_ARG(size)) {
+ ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
+ AppendInternal(reinterpret_cast<const char*>(data), size);
+ }
void Append(const Vector<char>& data) { Append(data.data(), data.size()); }
void Clear();
diff --git a/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc b/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc
index ebe753f1136..c3646e67711 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/platform/wtf/threading.h"
#if defined(OS_WIN)
+#include <intrin.h>
#include <stddef.h>
#include <windows.h>
#include <winnt.h>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/std_lib_extras.h b/chromium/third_party/blink/renderer/platform/wtf/std_lib_extras.h
index 87d7026fdac..a2b3edbfad7 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/std_lib_extras.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/std_lib_extras.h
@@ -30,7 +30,6 @@
#include "base/dcheck_is_on.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/leak_annotations.h"
@@ -95,6 +94,9 @@ class StaticSingleton final {
LEAK_SANITIZER_IGNORE_OBJECT(instance_.Get());
}
+ StaticSingleton(const StaticSingleton&) = delete;
+ StaticSingleton& operator=(const StaticSingleton&) = delete;
+
Type& Get(bool allow_cross_thread_use) {
#if DCHECK_IS_ON()
DCHECK(IsNotRacy(allow_cross_thread_use));
@@ -146,8 +148,6 @@ class StaticSingleton final {
bool safely_initialized_;
base::PlatformThreadId thread_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(StaticSingleton);
};
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/OWNERS b/chromium/third_party/blink/renderer/platform/wtf/text/OWNERS
deleted file mode 100644
index b33128712b0..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/text/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-per-file character_names.h=drott@chromium.org
-per-file text_codec*.*=jsbell@chromium.org
-per-file text_codec*.*=jshin@chromium.org
-per-file text_encoding*.*=jshin@chromium.org
-per-file text_encoding*.*=jshin@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/ascii_ctype.h b/chromium/third_party/blink/renderer/platform/wtf/text/ascii_ctype.h
index 1137acc8602..acfc9720787 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/ascii_ctype.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/ascii_ctype.h
@@ -30,7 +30,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ASCII_CTYPE_H_
#include "base/check_op.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
// The behavior of many of the functions in the <ctype.h> header is dependent
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h b/chromium/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
index 1a37cf305ec..bac2aa9dc0a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
@@ -29,7 +29,7 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#if defined(OS_MAC) && defined(ARCH_CPU_X86_FAMILY)
#include <emmintrin.h>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string_table.h b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string_table.h
index 57b53670166..63d320c9eed 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string_table.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string_table.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ATOMIC_STRING_TABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ATOMIC_STRING_TABLE_H_
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -22,6 +21,8 @@ class WTF_EXPORT AtomicStringTable final {
public:
AtomicStringTable();
+ AtomicStringTable(const AtomicStringTable&) = delete;
+ AtomicStringTable& operator=(const AtomicStringTable&) = delete;
~AtomicStringTable();
// Gets the shared table for the current thread.
@@ -128,8 +129,6 @@ class WTF_EXPORT AtomicStringTable final {
WeakResult WeakFindLowercasedSlow(const StringView& string);
HashSet<StringImpl*> table_;
-
- DISALLOW_COPY_AND_ASSIGN(AtomicStringTable);
};
inline bool operator==(const AtomicStringTable::WeakResult& lhs,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/case_folding_hash.h b/chromium/third_party/blink/renderer/platform/wtf/text/case_folding_hash.h
new file mode 100644
index 00000000000..407e926b31b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/case_folding_hash.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2012, 2013 Apple Inc. All rights reserved
+ * Copyright (C) Research In Motion Limited 2009. 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_CASE_FOLDING_HASH_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_CASE_FOLDING_HASH_H_
+
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+
+namespace WTF {
+
+// The GetHash() functions on CaseFoldingHash do not support null strings.
+// find(), Contains(), and insert() on HashMap<String,..., CaseFoldingHash>
+// cause a null-pointer dereference when passed null strings.
+class CaseFoldingHash {
+ STATIC_ONLY(CaseFoldingHash);
+
+ public:
+ static unsigned GetHash(const UChar* data, unsigned length) {
+ return StringHasher::ComputeHashAndMaskTop8Bits<UChar, FoldCase<UChar>>(
+ data, length);
+ }
+
+ static unsigned GetHash(StringImpl* str) {
+ if (str->Is8Bit())
+ return GetHash(str->Characters8(), str->length());
+ return GetHash(str->Characters16(), str->length());
+ }
+
+ static unsigned GetHash(const LChar* data, unsigned length) {
+ return StringHasher::ComputeHashAndMaskTop8Bits<LChar, FoldCase<LChar>>(
+ data, length);
+ }
+
+ static inline unsigned GetHash(const char* data, unsigned length) {
+ return CaseFoldingHash::GetHash(reinterpret_cast<const LChar*>(data),
+ length);
+ }
+
+ static inline bool Equal(const StringImpl* a, const StringImpl* b) {
+ DCHECK(a);
+ DCHECK(b);
+ // Save one branch inside each StringView by derefing the StringImpl,
+ // and another branch inside the compare function by skipping the null
+ // checks.
+ return DeprecatedEqualIgnoringCaseAndNullity(*a, *b);
+ }
+
+ static unsigned GetHash(const scoped_refptr<StringImpl>& key) {
+ return GetHash(key.get());
+ }
+
+ static bool Equal(const scoped_refptr<StringImpl>& a,
+ const scoped_refptr<StringImpl>& b) {
+ return Equal(a.get(), b.get());
+ }
+
+ static unsigned GetHash(const String& key) { return GetHash(key.Impl()); }
+ static unsigned GetHash(const AtomicString& key) {
+ return GetHash(key.Impl());
+ }
+ static bool Equal(const String& a, const String& b) {
+ return Equal(a.Impl(), b.Impl());
+ }
+ static bool Equal(const AtomicString& a, const AtomicString& b) {
+ return (a == b) || Equal(a.Impl(), b.Impl());
+ }
+
+ static const bool safe_to_compare_to_empty_or_deleted = false;
+
+ private:
+ // Private so no one uses this in the belief that it will return the
+ // correctly-folded code point in all cases (see comment below).
+ template <typename T>
+ static inline UChar FoldCase(T ch) {
+ if (std::is_same<T, LChar>::value)
+ return StringImpl::kLatin1CaseFoldTable[ch];
+ // It's possible for WTF::unicode::foldCase() to return a 32-bit value
+ // that's not representable as a UChar. However, since this is rare and
+ // deterministic, and the result of this is merely used for hashing, go
+ // ahead and clamp the value.
+ return static_cast<UChar>(WTF::unicode::FoldCase(ch));
+ }
+};
+
+} // namespace WTF
+
+using WTF::CaseFoldingHash;
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_CASE_FOLDING_HASH_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/case_map.cc b/chromium/third_party/blink/renderer/platform/wtf/text/case_map.cc
index 3b0bcf074ef..33e40db1ba3 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/case_map.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/case_map.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "third_party/blink/renderer/platform/wtf/text/text_offset_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/case_map.h b/chromium/third_party/blink/renderer/platform/wtf/text/case_map.h
index ea6b72a87b4..1bb937205ea 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/case_map.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/case_map.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_CASE_MAP_H_
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/character_names.h b/chromium/third_party/blink/renderer/platform/wtf/text/character_names.h
index 2e5df9172b4..f18acae6140 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/character_names.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/character_names.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_CHARACTER_NAMES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_CHARACTER_NAMES_H_
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace WTF {
namespace unicode {
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 a3be2e468f1..212cd41f639 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
@@ -26,10 +26,9 @@
#include <type_traits>
#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace WTF {
@@ -45,7 +44,7 @@ class IntegerToStringConverter {
"IntegerType must be a type of integer.");
explicit IntegerToStringConverter(IntegerType input) {
- LChar* end = buffer_ + base::size(buffer_);
+ LChar* end = buffer_ + kBufferSize;
begin_ = end;
// We need to switch to the unsigned type when negating the value since
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.cc b/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.cc
index 1d76435dbbb..1d0612fceab 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.cc
@@ -32,7 +32,7 @@ static UChar32 mathVariantLatin(UChar32 code_point, UChar32 base_char) {
// earlier is added to obtain the final code point.
UChar32 transformed_char =
base_char + kMathBoldUpperA + (kMathItalicUpperA - kMathBoldUpperA);
- // https://mathml-refresh.github.io/mathml-core/#italic-mappings
+ // https://w3c.github.io/mathml-core/#italic-mappings
if (transformed_char == 0x1D455)
return 0x210E;
return transformed_char;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.h b/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.h
index 5862aba32fe..c566b0fe2f5 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/math_transform.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_MATH_TRANSFORM_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_MATH_TRANSFORM_H_
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/math_transform_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/math_transform_test.cc
index 1c56a5c5a17..5b8871ca9b0 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/math_transform_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/math_transform_test.cc
@@ -10,7 +10,7 @@ namespace WTF {
namespace {
-// https://mathml-refresh.github.io/mathml-core/#italic-mappings
+// https://w3c.github.io/mathml-core/#italic-mappings
TEST(MathTransform, Italics) {
static struct ItalicsTestData {
UChar32 code_point;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_buffer.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_buffer.h
index 6476bc2153f..2c350d46d9f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_buffer.h
@@ -30,11 +30,9 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_STRING_BUFFER_H_
#include "base/containers/span.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace WTF {
@@ -50,6 +48,9 @@ class StringBuffer {
data_ = StringImpl::CreateUninitialized(length, characters);
}
+ StringBuffer(const StringBuffer&) = delete;
+ StringBuffer& operator=(const StringBuffer&) = delete;
+
~StringBuffer() = default;
void Shrink(unsigned new_length);
@@ -74,8 +75,6 @@ class StringBuffer {
private:
scoped_refptr<StringImpl> data_;
-
- DISALLOW_COPY_AND_ASSIGN(StringBuffer);
};
template <typename CharType>
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 67597471682..115fafe4f66 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
@@ -27,7 +27,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_STRING_BUILDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_STRING_BUILDER_H_
-#include "base/macros.h"
+#include <unicode/utf16.h>
+
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
@@ -41,6 +42,8 @@ class WTF_EXPORT StringBuilder {
public:
StringBuilder() : no_buffer_() {}
+ StringBuilder(const StringBuilder&) = delete;
+ StringBuilder& operator=(const StringBuilder&) = delete;
~StringBuilder() { Clear(); }
void Append(const UChar*, unsigned length);
@@ -254,8 +257,6 @@ class WTF_EXPORT StringBuilder {
unsigned length_ = 0;
bool is_8bit_ = true;
bool has_buffer_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(StringBuilder);
};
template <typename CharType>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder_test.cc
index aa4c76081a2..8081ebc495f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder_test.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 6b0e7ca7554..d9c357bd6bd 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
@@ -43,15 +43,9 @@ inline void HashTraits<String>::ConstructDeletedValue(String& slot,
zero_value);
}
-// The hash() functions on StringHash and CaseFoldingHash do not support null
-// strings. get(), contains(), and add() on HashMap<String,..., StringHash>
-// cause a null-pointer dereference when passed null strings.
-
-// FIXME: We should really figure out a way to put the computeHash function
-// that's currently a member function of StringImpl into this file so we can be
-// a little closer to having all the nearly-identical hash functions in one
-// place.
-
+// The GetHash() functions on StringHash do not support null strings. find(),
+// Contains(), and insert() on HashMap<String,..., StringHash> cause a
+// null-pointer dereference when passed null strings.
struct StringHash {
STATIC_ONLY(StringHash);
static unsigned GetHash(StringImpl* key) { return key->GetHash(); }
@@ -75,77 +69,6 @@ struct StringHash {
static const bool safe_to_compare_to_empty_or_deleted = false;
};
-class CaseFoldingHash {
- STATIC_ONLY(CaseFoldingHash);
-
- public:
- static unsigned GetHash(const UChar* data, unsigned length) {
- return StringHasher::ComputeHashAndMaskTop8Bits<UChar, FoldCase<UChar>>(
- data, length);
- }
-
- static unsigned GetHash(StringImpl* str) {
- if (str->Is8Bit())
- return GetHash(str->Characters8(), str->length());
- return GetHash(str->Characters16(), str->length());
- }
-
- static unsigned GetHash(const LChar* data, unsigned length) {
- return StringHasher::ComputeHashAndMaskTop8Bits<LChar, FoldCase<LChar>>(
- data, length);
- }
-
- static inline unsigned GetHash(const char* data, unsigned length) {
- return CaseFoldingHash::GetHash(reinterpret_cast<const LChar*>(data),
- length);
- }
-
- static inline bool Equal(const StringImpl* a, const StringImpl* b) {
- DCHECK(a);
- DCHECK(b);
- // Save one branch inside each StringView by derefing the StringImpl,
- // and another branch inside the compare function by skipping the null
- // checks.
- return DeprecatedEqualIgnoringCaseAndNullity(*a, *b);
- }
-
- static unsigned GetHash(const scoped_refptr<StringImpl>& key) {
- return GetHash(key.get());
- }
-
- static bool Equal(const scoped_refptr<StringImpl>& a,
- const scoped_refptr<StringImpl>& b) {
- return Equal(a.get(), b.get());
- }
-
- static unsigned GetHash(const String& key) { return GetHash(key.Impl()); }
- static unsigned GetHash(const AtomicString& key) {
- return GetHash(key.Impl());
- }
- static bool Equal(const String& a, const String& b) {
- return Equal(a.Impl(), b.Impl());
- }
- static bool Equal(const AtomicString& a, const AtomicString& b) {
- return (a == b) || Equal(a.Impl(), b.Impl());
- }
-
- static const bool safe_to_compare_to_empty_or_deleted = false;
-
- private:
- // Private so no one uses this in the belief that it will return the
- // correctly-folded code point in all cases (see comment below).
- template <typename T>
- static inline UChar FoldCase(T ch) {
- if (std::is_same<T, LChar>::value)
- return StringImpl::kLatin1CaseFoldTable[ch];
- // It's possible for WTF::unicode::foldCase() to return a 32-bit value
- // that's not representable as a UChar. However, since this is rare and
- // deterministic, and the result of this is merely used for hashing, go
- // ahead and clamp the value.
- return static_cast<UChar>(WTF::unicode::FoldCase(ch));
- }
-};
-
// This hash can be used in cases where the key is a hash of a string, but we
// don't want to store the string. It's not really specific to string hashing,
// but all our current uses of it are for strings.
@@ -169,7 +92,6 @@ struct AlreadyHashed : IntHash<unsigned> {
} // namespace WTF
using WTF::AlreadyHashed;
-using WTF::CaseFoldingHash;
using WTF::StringHash;
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_STRING_HASH_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_hasher.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_hasher.h
index 0c9b3d7880c..587488dd84d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_hasher.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_hasher.h
@@ -24,7 +24,7 @@
#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc
index e199f32423d..63e56ef7f4e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc
@@ -41,6 +41,8 @@
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode_string.h"
using std::numeric_limits;
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 0b320626a39..1d07a8cad39 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
@@ -31,7 +31,6 @@
#include "base/callback_forward.h"
#include "base/containers/span.h"
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/numerics/checked_math.h"
#include "build/build_config.h"
@@ -42,7 +41,7 @@
#include "third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h"
#include "third_party/blink/renderer/platform/wtf/text/number_parsing_options.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
@@ -136,6 +135,8 @@ class WTF_EXPORT StringImpl {
static StringImpl* empty_;
static StringImpl* empty16_bit_;
+ StringImpl(const StringImpl&) = delete;
+ StringImpl& operator=(const StringImpl&) = delete;
~StringImpl();
static void InitStatics();
@@ -571,8 +572,6 @@ class WTF_EXPORT StringImpl {
mutable unsigned ref_count_{1};
const unsigned length_;
mutable std::atomic<uint32_t> hash_and_flags_;
-
- DISALLOW_COPY_AND_ASSIGN(StringImpl);
};
template <>
@@ -883,14 +882,6 @@ static inline int CodeUnitCompare(const StringImpl* string1,
return CodeUnitCompare16(string1, string2);
}
-static inline bool IsSpaceOrNewline(UChar c) {
- // Use IsASCIISpace() for basic Latin-1.
- // This will include newlines, which aren't included in Unicode DirWS.
- return c <= 0x7F
- ? WTF::IsASCIISpace(c)
- : WTF::unicode::Direction(c) == WTF::unicode::kWhiteSpaceNeutral;
-}
-
inline scoped_refptr<StringImpl> StringImpl::IsolatedCopy() const {
if (Is8Bit())
return Create(Characters8(), length_);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc
index 8251b1167ff..29520c5f51b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc
@@ -27,6 +27,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/case_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc
index d915df41740..727868404dc 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h
index a9a16663374..c7702c407d8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_STRING_TO_NUMBER_H_
#include "third_party/blink/renderer/platform/wtf/text/number_parsing_options.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_view.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_view.cc
index 9a56ddff705..393bcff4b1d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_view.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_view.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
+#include <unicode/utf16.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/text/wtf_string.h"
@@ -135,4 +137,24 @@ StringView StringView::LowerASCIIMaybeUsingBuffer(
StackStringViewAllocator(buffer));
}
+UChar32 StringView::CodepointAt(unsigned i) const {
+ SECURITY_DCHECK(i < length());
+ if (Is8Bit())
+ return (*this)[i];
+ UChar32 codepoint;
+ U16_GET(Characters16(), 0, i, length(), codepoint);
+ return codepoint;
+}
+
+unsigned StringView::NextCodePointOffset(unsigned i) const {
+ SECURITY_DCHECK(i < length());
+ if (Is8Bit())
+ return i + 1;
+ const UChar* str = Characters16() + i;
+ ++i;
+ if (i < length() && U16_IS_LEAD(*str++) && U16_IS_TRAIL(*str))
+ ++i;
+ return i;
+}
+
} // namespace WTF
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 b610c81bdf0..85a2920af13 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
@@ -14,7 +14,6 @@
#include "third_party/blink/renderer/platform/wtf/get_ptr.h"
#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"
#if DCHECK_IS_ON()
#include "base/memory/scoped_refptr.h"
@@ -184,14 +183,11 @@ class WTF_EXPORT StringView {
return {static_cast<const UChar*>(bytes_), length_};
}
- UChar32 CodepointAt(unsigned i) const {
- SECURITY_DCHECK(i < length());
- if (Is8Bit())
- return (*this)[i];
- UChar32 codepoint;
- U16_GET(Characters16(), 0, i, length(), codepoint);
- return codepoint;
- }
+ UChar32 CodepointAt(unsigned i) const;
+
+ // Returns i+2 if a pair of [i] and [i+1] is a valid surrogate pair.
+ // Returns i+1 otherwise.
+ unsigned NextCodePointOffset(unsigned i) const;
const void* Bytes() const { return bytes_; }
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 143fd2b7813..1240862b7d5 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
@@ -486,4 +486,32 @@ TEST(StringViewTest, DeprecatedEqualIgnoringCase) {
EXPECT_TRUE(DeprecatedEqualIgnoringCase(kLigatureFFIAndSSSS, kFFIAndSharpSs));
}
+TEST(StringViewTest, NextCodePointOffset) {
+ StringView view8(kChars8);
+ EXPECT_EQ(1u, view8.NextCodePointOffset(0));
+ EXPECT_EQ(2u, view8.NextCodePointOffset(1));
+ EXPECT_EQ(5u, view8.NextCodePointOffset(4));
+
+ StringView view16(u"A\U0001F197X\U0001F232");
+ ASSERT_EQ(6u, view16.length());
+ EXPECT_EQ(1u, view16.NextCodePointOffset(0));
+ EXPECT_EQ(3u, view16.NextCodePointOffset(1));
+ EXPECT_EQ(3u, view16.NextCodePointOffset(2));
+ EXPECT_EQ(4u, view16.NextCodePointOffset(3));
+ EXPECT_EQ(6u, view16.NextCodePointOffset(4));
+
+ const UChar kLead = 0xD800;
+ StringView broken1(&kLead, 1);
+ EXPECT_EQ(1u, broken1.NextCodePointOffset(0));
+
+ const UChar kLeadAndNotTrail[] = {0xD800, 0x20, 0};
+ StringView broken2(kLeadAndNotTrail);
+ EXPECT_EQ(1u, broken2.NextCodePointOffset(0));
+ EXPECT_EQ(2u, broken2.NextCodePointOffset(1));
+
+ const UChar kTrail = 0xDC00;
+ StringView broken3(&kTrail, 1);
+ EXPECT_EQ(1u, broken3.NextCodePointOffset(0));
+}
+
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
index 4f524c5500e..be2c9e64f36 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
@@ -28,11 +28,10 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_CODEC_H_
#include <memory>
-#include "base/macros.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/platform/wtf/forward.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/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
namespace WTF {
@@ -79,6 +78,8 @@ class WTF_EXPORT TextCodec {
public:
TextCodec() = default;
+ TextCodec(const TextCodec&) = delete;
+ TextCodec& operator=(const TextCodec&) = delete;
virtual ~TextCodec();
struct EncodeIntoResult {
@@ -127,8 +128,6 @@ class WTF_EXPORT TextCodec {
static uint32_t GetUnencodableReplacement(unsigned code_point,
UnencodableHandling,
UnencodableReplacementArray);
-
- DISALLOW_COPY_AND_ASSIGN(TextCodec);
};
typedef void (*EncodingNameRegistrar)(const char* alias, const char* name);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h
index c2202380799..660afd4c472 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h
@@ -30,7 +30,6 @@
#include <unicode/utypes.h>
#include <memory>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
@@ -95,11 +94,11 @@ struct ICUConverterWrapper {
public:
ICUConverterWrapper() : converter(nullptr) {}
+ ICUConverterWrapper(const ICUConverterWrapper&) = delete;
+ ICUConverterWrapper& operator=(const ICUConverterWrapper&) = delete;
~ICUConverterWrapper();
UConverter* converter;
-
- DISALLOW_COPY_AND_ASSIGN(ICUConverterWrapper);
};
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc
index b8efc664a38..341e05fea5a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc
@@ -25,7 +25,9 @@
#include "third_party/blink/renderer/platform/wtf/text/text_codec_latin1.h"
+#include <unicode/utf16.h>
#include <memory>
+
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec_ascii_fast_path.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement.cc
index 20e23cfa5de..c2e5196ff84 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement.cc
@@ -50,7 +50,7 @@ String TextCodecReplacement::Decode(const char*,
if (!replacement_error_returned_) {
replacement_error_returned_ = true;
saw_error = true;
- return String(&kReplacementCharacter, 1);
+ return String(&kReplacementCharacter, 1u);
}
// 3. Return finished.
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 0fe72b40553..7fb3d7a4b2f 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
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
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 0687d221280..46a68260cba 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
@@ -25,7 +25,9 @@
#include "third_party/blink/renderer/platform/wtf/text/text_codec_utf16.h"
+#include <unicode/utf16.h>
#include <memory>
+
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -76,7 +78,7 @@ String TextCodecUTF16::Decode(const char* bytes,
if (really_flush && (have_lead_byte_ || have_lead_surrogate_)) {
have_lead_byte_ = have_lead_surrogate_ = false;
saw_error = true;
- return String(&kReplacementCharacter, 1);
+ return String(&kReplacementCharacter, 1u);
}
return String();
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h
index 65806a9beb1..8e8ac62d056 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h
@@ -26,7 +26,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_CODEC_UTF8_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_CODEC_UTF8_H_
+#include <unicode/utf8.h>
#include <memory>
+
#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
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 a65d318c920..29a8d8dfc5f 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
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
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 4ba14afcc13..11034b46354 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
@@ -124,7 +124,9 @@ static inline void checkExistingName(const char*, const char*) {}
#else
static void CheckExistingName(const char* alias, const char* atomic_name) {
- const char* old_atomic_name = g_text_encoding_name_map->at(alias);
+ EncodingRegistryMutex().AssertAcquired();
+ const char* old_atomic_name =
+ g_text_encoding_name_map->DeprecatedAtOrEmptyValue(alias);
if (!old_atomic_name)
return;
if (old_atomic_name == atomic_name)
@@ -158,9 +160,11 @@ static bool IsUndesiredAlias(const char* alias) {
static void AddToTextEncodingNameMap(const char* alias, const char* name) {
DCHECK_LE(strlen(alias), kMaxEncodingNameLength);
+ EncodingRegistryMutex().AssertAcquired();
if (IsUndesiredAlias(alias))
return;
- const char* atomic_name = g_text_encoding_name_map->at(name);
+ const char* atomic_name =
+ g_text_encoding_name_map->DeprecatedAtOrEmptyValue(name);
DCHECK(strcmp(alias, name) == 0 || atomic_name);
if (!atomic_name)
atomic_name = name;
@@ -171,6 +175,7 @@ static void AddToTextEncodingNameMap(const char* alias, const char* name) {
static void AddToTextCodecMap(const char* name,
NewTextCodecFunction function,
const void* additional_data) {
+ EncodingRegistryMutex().AssertAcquired();
const char* atomic_name = g_text_encoding_name_map->at(name);
DCHECK(atomic_name);
g_text_codec_map->insert(atomic_name,
@@ -224,13 +229,14 @@ const char* AtomicCanonicalTextEncodingName(const char* name) {
if (!g_text_encoding_name_map)
BuildBaseTextCodecMaps();
- if (const char* atomic_name = g_text_encoding_name_map->at(name))
+ if (const char* atomic_name =
+ g_text_encoding_name_map->DeprecatedAtOrEmptyValue(name))
return atomic_name;
if (AtomicDidExtendTextCodecMaps())
return nullptr;
ExtendTextCodecMaps();
AtomicSetDidExtendTextCodecMaps();
- return g_text_encoding_name_map->at(name);
+ return g_text_encoding_name_map->DeprecatedAtOrEmptyValue(name);
}
template <typename CharacterType>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h
index 33717cf0a21..4227bc0185a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h
@@ -27,7 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_ENCODING_REGISTRY_H_
#include <memory>
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_stream.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_stream.h
index 62558e7330f..ad1aacd8318 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_stream.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_stream.h
@@ -28,7 +28,6 @@
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
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 d8b07234b41..d48f66db58a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/unicode.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/unicode.h
@@ -24,11 +24,9 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UNICODE_H_
#include <unicode/uchar.h>
-#include <unicode/ustring.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/ascii_ctype.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
namespace WTF {
namespace unicode {
@@ -121,30 +119,6 @@ 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);
}
@@ -153,34 +127,14 @@ 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);
}
@@ -193,10 +147,6 @@ 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));
}
@@ -209,8 +159,8 @@ inline bool IsLower(UChar32 c) {
return !!u_islower(c);
}
-inline uint8_t CombiningClass(UChar32 c) {
- return u_getCombiningClass(c);
+inline bool IsUpper(UChar32 c) {
+ return !!u_isupper(c);
}
inline CharDecompositionType DecompositionType(UChar32 c) {
@@ -218,11 +168,17 @@ inline CharDecompositionType DecompositionType(UChar32 c) {
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);
+inline bool IsSpaceOrNewline(UChar c) {
+ // Use IsASCIISpace() for basic Latin-1.
+ // This will include newlines, which aren't included in Unicode DirWS.
+ return c <= 0x7F
+ ? WTF::IsASCIISpace(c)
+ : WTF::unicode::Direction(c) == WTF::unicode::kWhiteSpaceNeutral;
}
} // namespace unicode
} // namespace WTF
+using WTF::unicode::IsSpaceOrNewline;
+
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UNICODE_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/unicode_string.h b/chromium/third_party/blink/renderer/platform/wtf/text/unicode_string.h
new file mode 100644
index 00000000000..9dd427bf694
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/unicode_string.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * 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_UNICODE_STRING_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UNICODE_STRING_H_
+
+#include <unicode/stringoptions.h>
+#include <unicode/ustring.h>
+
+namespace WTF {
+namespace unicode {
+
+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 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_STRING_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/utf8.cc b/chromium/third_party/blink/renderer/platform/wtf/text/utf8.cc
index 4515a76583e..16eb886f6af 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/utf8.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/utf8.cc
@@ -26,6 +26,8 @@
#include "third_party/blink/renderer/platform/wtf/text/utf8.h"
+#include <unicode/utf16.h>
+
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/utf8.h b/chromium/third_party/blink/renderer/platform/wtf/text/utf8.h
index 159aefb1fb6..ff8e20b8739 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/utf8.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/utf8.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UTF8_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UTF8_H_
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
namespace WTF {
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 493ec16e1b0..014fedfdb76 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
@@ -70,6 +70,9 @@ String::String(const char* characters, unsigned length)
: nullptr) {}
#if defined(ARCH_CPU_64_BITS)
+String::String(const UChar* characters, size_t length)
+ : String(characters, SafeCast<unsigned>(length)) {}
+
String::String(const char* characters, size_t length)
: String(characters, SafeCast<unsigned>(length)) {}
#endif // defined(ARCH_CPU_64_BITS)
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 8cc247e1ee0..b545918a36c 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
@@ -89,8 +89,9 @@ class WTF_EXPORT String {
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
+ // Only define size_t constructors if size_t is 64 bit otherwise
// we'd have a duplicate define.
+ String(const UChar* characters, size_t length);
String(const char* characters, size_t length);
#endif // defined(ARCH_CPU_64_BITS)
@@ -180,7 +181,7 @@ class WTF_EXPORT String {
std::string Utf8(UTF8ConversionMode = kLenientUTF8Conversion) const
WARN_UNUSED_RESULT;
- UChar operator[](unsigned index) const {
+ UChar operator[](wtf_size_t index) const {
if (!impl_ || index >= impl_->length())
return 0;
return (*impl_)[index];
@@ -202,17 +203,17 @@ class WTF_EXPORT String {
WARN_UNUSED_RESULT;
// Find characters.
- wtf_size_t find(UChar c, unsigned start = 0) const {
+ wtf_size_t find(UChar c, wtf_size_t start = 0) const {
return impl_ ? impl_->Find(c, start) : kNotFound;
}
- wtf_size_t find(LChar c, unsigned start = 0) const {
+ wtf_size_t find(LChar c, wtf_size_t start = 0) const {
return impl_ ? impl_->Find(c, start) : kNotFound;
}
- wtf_size_t find(char c, unsigned start = 0) const {
+ wtf_size_t find(char c, wtf_size_t start = 0) const {
return find(static_cast<LChar>(c), start);
}
wtf_size_t Find(CharacterMatchFunctionPtr match_function,
- unsigned start = 0) const {
+ wtf_size_t start = 0) const {
return impl_ ? impl_->Find(match_function, start) : kNotFound;
}
wtf_size_t Find(base::RepeatingCallback<bool(UChar)> match_callback,
@@ -221,7 +222,7 @@ class WTF_EXPORT String {
// Find substrings.
wtf_size_t Find(
const StringView& value,
- unsigned start = 0,
+ wtf_size_t start = 0,
TextCaseSensitivity case_sensitivity = kTextCaseSensitive) const {
return impl_
? DISPATCH_CASE_OP(case_sensitivity, impl_->Find, (value, start))
@@ -715,7 +716,6 @@ using WTF::g_empty_string;
using WTF::g_empty_string16_bit;
using WTF::Equal;
using WTF::Find;
-using WTF::IsSpaceOrNewline;
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_STRING_H_
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 ff1cbf21e64..85719d96744 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
@@ -27,7 +27,7 @@
#include <limits>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_uchar.h b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_uchar.h
new file mode 100644
index 00000000000..e662ed5c6ae
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_uchar.h
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_UCHAR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_UCHAR_H_
+
+#if defined(USING_SYSTEM_ICU)
+
+#include <unicode/umachine.h>
+
+#else
+
+#include <stdint.h>
+
+// These definitions should be matched to
+// third_party/icu/source/common/unicode/umachine.h.
+typedef char16_t UChar;
+typedef int32_t UChar32;
+
+#endif
+
+static_assert(sizeof(UChar) == 2, "UChar should be two bytes");
+
+// Define platform neutral 8 bit character type (L is for Latin-1).
+typedef unsigned char LChar;
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_UCHAR_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/thread_specific.h b/chromium/third_party/blink/renderer/platform/wtf/thread_specific.h
index 6d26f60c229..fb9d1c161fa 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/thread_specific.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/thread_specific.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_THREAD_SPECIFIC_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_THREAD_SPECIFIC_H_
-#include "base/macros.h"
#include "base/threading/thread_local_storage.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -49,6 +48,8 @@ class ThreadSpecific {
public:
ThreadSpecific() : slot_(&Destroy) {}
+ ThreadSpecific(const ThreadSpecific&) = delete;
+ ThreadSpecific& operator=(const ThreadSpecific&) = delete;
bool
IsSet(); // Useful as a fast check to see if this thread has set this value.
T* operator->();
@@ -76,8 +77,6 @@ class ThreadSpecific {
// This member must only be accessed or modified on the main thread.
T* main_thread_storage_ = nullptr;
base::ThreadLocalStorage::Slot slot_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadSpecific);
};
template <typename T>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading.h b/chromium/third_party/blink/renderer/platform/wtf/threading.h
index 3120815d1df..441cd861d53 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading.h
@@ -35,7 +35,6 @@
#include "base/check_op.h"
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
@@ -67,6 +66,8 @@ class WTF_EXPORT Threading {
public:
Threading();
+ Threading(const Threading&) = delete;
+ Threading& operator=(const Threading&) = delete;
~Threading();
AtomicStringTable& GetAtomicStringTable() { return *atomic_string_table_; }
@@ -94,8 +95,6 @@ class WTF_EXPORT Threading {
static ThreadSpecific<Threading>* static_data_;
friend Threading& WtfThreading();
-
- DISALLOW_COPY_AND_ASSIGN(Threading);
};
inline Threading& WtfThreading() {
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 1f8b2d7b8d7..669d945810f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h
@@ -32,14 +32,34 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_THREADING_PRIMITIVES_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/thread_annotations.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
#if defined(OS_WIN)
-#include <windows.h>
+
+#include "base/win/windows_types.h"
+
+// Declare Chrome versions of some Windows structures. These are needed for
+// when we need a concrete type but don't want to pull in Windows.h. We can't
+// declare the Windows types so we declare our types and cast to the Windows
+// types in a few places. static_asserts in threading_win.cc are used to verify
+// that the sizes are correct.
+
+struct BLINK_CRITICAL_SECTION {
+ // The Windows CRITICAL_SECTION struct is 40 bytes on 64-bit and 24 bytes on
+ // 32-bit. The align member variable uses sizeof(void*) bytes so the buffer
+ // to fill out the size needs to be 32/20 bytes. This can be expressed as
+ // sizeof(void*) * 3 + 8.
+ char buffer[sizeof(void*) * 3 + 8];
+ ULONG_PTR align; // Make sure the alignment requirements match.
+};
+
+struct BLINK_CONDITION_VARIABLE {
+ PVOID Ptr;
+};
+
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <pthread.h>
#endif
@@ -48,10 +68,10 @@ namespace WTF {
#if defined(OS_WIN)
struct PlatformMutex {
- CRITICAL_SECTION internal_mutex_;
+ BLINK_CRITICAL_SECTION internal_mutex_;
size_t recursion_count_;
};
-typedef CONDITION_VARIABLE PlatformCondition;
+typedef BLINK_CONDITION_VARIABLE PlatformCondition;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
struct PlatformMutex {
pthread_mutex_t internal_mutex_;
@@ -66,6 +86,8 @@ class WTF_EXPORT MutexBase {
USING_FAST_MALLOC(MutexBase);
public:
+ MutexBase(const MutexBase&) = delete;
+ MutexBase& operator=(const MutexBase&) = delete;
~MutexBase();
void lock();
@@ -83,8 +105,6 @@ class WTF_EXPORT MutexBase {
MutexBase(bool recursive);
PlatformMutex mutex_;
-
- DISALLOW_COPY_AND_ASSIGN(MutexBase);
};
class LOCKABLE WTF_EXPORT Mutex : public MutexBase {
@@ -116,12 +136,12 @@ class SCOPED_LOCKABLE MutexLocker final {
MutexLocker(Mutex& mutex) EXCLUSIVE_LOCK_FUNCTION(mutex) : mutex_(mutex) {
mutex_.lock();
}
+ MutexLocker(const MutexLocker&) = delete;
+ MutexLocker& operator=(const MutexLocker&) = delete;
~MutexLocker() UNLOCK_FUNCTION() { mutex_.unlock(); }
private:
Mutex& mutex_;
-
- DISALLOW_COPY_AND_ASSIGN(MutexLocker);
};
class MutexTryLocker final {
@@ -129,6 +149,8 @@ class MutexTryLocker final {
public:
MutexTryLocker(Mutex& mutex) : mutex_(mutex), locked_(mutex.TryLock()) {}
+ MutexTryLocker(const MutexTryLocker&) = delete;
+ MutexTryLocker& operator=(const MutexTryLocker&) = delete;
~MutexTryLocker() {
if (locked_)
mutex_.unlock();
@@ -139,8 +161,6 @@ class MutexTryLocker final {
private:
Mutex& mutex_;
bool locked_;
-
- DISALLOW_COPY_AND_ASSIGN(MutexTryLocker);
};
class WTF_EXPORT ThreadCondition final {
@@ -148,6 +168,8 @@ class WTF_EXPORT ThreadCondition final {
public:
explicit ThreadCondition(Mutex&);
+ ThreadCondition(const ThreadCondition&) = delete;
+ ThreadCondition& operator=(const ThreadCondition&) = delete;
~ThreadCondition();
void Wait();
@@ -157,8 +179,6 @@ class WTF_EXPORT ThreadCondition final {
private:
PlatformCondition condition_;
PlatformMutex& mutex_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadCondition);
};
} // namespace WTF
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 ccb3c1065e0..c727fb4984c 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading_win.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading_win.cc
@@ -110,17 +110,32 @@
namespace WTF {
+namespace {
+static_assert(sizeof(BLINK_CRITICAL_SECTION) == sizeof(CRITICAL_SECTION),
+ "Definition mismatch.");
+static_assert(sizeof(BLINK_CONDITION_VARIABLE) == sizeof(CONDITION_VARIABLE),
+ "Definition mismatch.");
+
+CRITICAL_SECTION* GetCriticalSection(PlatformMutex* mutex) {
+ return reinterpret_cast<CRITICAL_SECTION*>(&mutex->internal_mutex_);
+}
+
+CONDITION_VARIABLE* ToConditionVariable(BLINK_CONDITION_VARIABLE* condition) {
+ return reinterpret_cast<CONDITION_VARIABLE*>(condition);
+}
+} // namespace
+
MutexBase::MutexBase(bool recursive) {
mutex_.recursion_count_ = 0;
- InitializeCriticalSection(&mutex_.internal_mutex_);
+ InitializeCriticalSection(GetCriticalSection(&mutex_));
}
MutexBase::~MutexBase() {
- DeleteCriticalSection(&mutex_.internal_mutex_);
+ DeleteCriticalSection(GetCriticalSection(&mutex_));
}
void MutexBase::lock() {
- EnterCriticalSection(&mutex_.internal_mutex_);
+ EnterCriticalSection(GetCriticalSection(&mutex_));
DCHECK(!mutex_.recursion_count_)
<< "WTF does not support recursive mutex acquisition!";
++mutex_.recursion_count_;
@@ -129,7 +144,7 @@ void MutexBase::lock() {
void MutexBase::unlock() {
DCHECK(mutex_.recursion_count_);
--mutex_.recursion_count_;
- LeaveCriticalSection(&mutex_.internal_mutex_);
+ LeaveCriticalSection(GetCriticalSection(&mutex_));
}
bool Mutex::TryLock() {
@@ -139,7 +154,7 @@ bool Mutex::TryLock() {
// treats this as a successful case, it changes the behavior of several
// tests in WebKit that check to see if the current thread already
// owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
- DWORD result = TryEnterCriticalSection(&mutex_.internal_mutex_);
+ DWORD result = TryEnterCriticalSection(GetCriticalSection(&mutex_));
if (result != 0) { // We got the lock
// If this thread already had the lock, we must unlock and return
@@ -151,7 +166,7 @@ bool Mutex::TryLock() {
DCHECK(!mutex_.recursion_count_)
<< "WTF does not support recursive mutex acquisition!";
if (mutex_.recursion_count_ > 0) {
- LeaveCriticalSection(&mutex_.internal_mutex_);
+ LeaveCriticalSection(GetCriticalSection(&mutex_));
return false;
}
++mutex_.recursion_count_;
@@ -164,7 +179,7 @@ bool Mutex::TryLock() {
bool RecursiveMutex::TryLock() {
// CRITICAL_SECTION is recursive/reentrant so TryEnterCriticalSection will
// succeed if the current thread is already in the critical section.
- DWORD result = TryEnterCriticalSection(&mutex_.internal_mutex_);
+ DWORD result = TryEnterCriticalSection(GetCriticalSection(&mutex_));
if (result == 0) { // We didn't get the lock.
return false;
}
@@ -183,18 +198,18 @@ void ThreadCondition::Wait() {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
--mutex_.recursion_count_;
- BOOL result =
- SleepConditionVariableCS(&condition_, &mutex_.internal_mutex_, INFINITE);
+ BOOL result = SleepConditionVariableCS(ToConditionVariable(&condition_),
+ GetCriticalSection(&mutex_), INFINITE);
DCHECK_NE(result, 0);
++mutex_.recursion_count_;
}
void ThreadCondition::Signal() {
- WakeConditionVariable(&condition_);
+ WakeConditionVariable(ToConditionVariable(&condition_));
}
void ThreadCondition::Broadcast() {
- WakeAllConditionVariable(&condition_);
+ WakeAllConditionVariable(ToConditionVariable(&condition_));
}
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/tree_node.h b/chromium/third_party/blink/renderer/platform/wtf/tree_node.h
deleted file mode 100644
index 66a77f8c09e..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/tree_node.h
+++ /dev/null
@@ -1,212 +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_TREE_NODE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TREE_NODE_H_
-
-#include "base/check_op.h"
-
-namespace WTF {
-
-//
-// TreeNode is generic, ContainerNode-like linked tree data structure.
-// There are a few notable difference between TreeNode and Node:
-//
-// * Each TreeNode node is NOT ref counted. The user have to retain its
-// lifetime somehow.
-// FIXME: lifetime management could be parameterized so that ref counted
-// implementations can be used.
-// * It checks invalid input. The callers have to ensure that given
-// parameter is sound.
-// * There is no branch-leaf difference. Every node can be a parent of other
-// node.
-//
-// FIXME: oilpan: Trace tree node edges to ensure we don't have dangling
-// pointers.
-// As it is used in HTMLImport it is safe since they all die together.
-template <class T>
-class TreeNode {
- public:
- typedef T NodeType;
-
- TreeNode()
- : next_(nullptr),
- previous_(nullptr),
- parent_(nullptr),
- first_child_(nullptr),
- last_child_(nullptr) {}
-
- NodeType* Next() const { return next_; }
- NodeType* Previous() const { return previous_; }
- NodeType* Parent() const { return parent_; }
- NodeType* FirstChild() const { return first_child_; }
- NodeType* LastChild() const { return last_child_; }
- NodeType* Here() const {
- return static_cast<NodeType*>(const_cast<TreeNode*>(this));
- }
-
- bool Orphan() const {
- return !parent_ && !next_ && !previous_ && !first_child_ && !last_child_;
- }
- bool HasChildren() const { return first_child_; }
-
- void InsertBefore(NodeType* new_child, NodeType* ref_child) {
- DCHECK(!new_child->Parent());
- DCHECK(!new_child->Next());
- DCHECK(!new_child->Previous());
-
- DCHECK(!ref_child || this == ref_child->Parent());
-
- if (!ref_child) {
- AppendChild(new_child);
- return;
- }
-
- NodeType* new_previous = ref_child->Previous();
- new_child->parent_ = Here();
- new_child->next_ = ref_child;
- new_child->previous_ = new_previous;
- ref_child->previous_ = new_child;
- if (new_previous)
- new_previous->next_ = new_child;
- else
- first_child_ = new_child;
- }
-
- void AppendChild(NodeType* child) {
- DCHECK(!child->Parent());
- DCHECK(!child->Next());
- DCHECK(!child->Previous());
-
- child->parent_ = Here();
-
- if (!last_child_) {
- DCHECK(!first_child_);
- last_child_ = first_child_ = child;
- return;
- }
-
- DCHECK(!last_child_->next_);
- NodeType* old_last = last_child_;
- last_child_ = child;
-
- child->previous_ = old_last;
- old_last->next_ = child;
- }
-
- NodeType* RemoveChild(NodeType* child) {
- DCHECK_EQ(child->Parent(), this);
-
- if (first_child_ == child)
- first_child_ = child->Next();
- if (last_child_ == child)
- last_child_ = child->Previous();
-
- NodeType* old_next = child->Next();
- NodeType* old_previous = child->Previous();
- child->parent_ = child->next_ = child->previous_ = nullptr;
-
- if (old_next)
- old_next->previous_ = old_previous;
- if (old_previous)
- old_previous->next_ = old_next;
-
- return child;
- }
-
- void TakeChildrenFrom(NodeType* old_parent) {
- DCHECK_NE(old_parent, this);
- while (old_parent->HasChildren()) {
- NodeType* child = old_parent->FirstChild();
- old_parent->RemoveChild(child);
- AppendChild(child);
- }
- }
-
- private:
- NodeType* next_;
- NodeType* previous_;
- NodeType* parent_;
- NodeType* first_child_;
- NodeType* last_child_;
-};
-
-template <class T>
-inline typename TreeNode<T>::NodeType* TraverseNext(
- const TreeNode<T>* current,
- const TreeNode<T>* stay_within = nullptr) {
- if (typename TreeNode<T>::NodeType* next = current->FirstChild())
- return next;
- if (current == stay_within)
- return nullptr;
- if (typename TreeNode<T>::NodeType* next = current->Next())
- return next;
- for (typename TreeNode<T>::NodeType* parent = current->Parent(); parent;
- parent = parent->Parent()) {
- if (parent == stay_within)
- return nullptr;
- if (typename TreeNode<T>::NodeType* next = parent->Next())
- return next;
- }
-
- return nullptr;
-}
-
-template <class T>
-inline typename TreeNode<T>::NodeType* TraverseFirstPostOrder(
- const TreeNode<T>* current) {
- typename TreeNode<T>::NodeType* first = current->Here();
- while (first->FirstChild())
- first = first->FirstChild();
- return first;
-}
-
-template <class T>
-inline typename TreeNode<T>::NodeType* TraverseNextPostOrder(
- const TreeNode<T>* current,
- const TreeNode<T>* stay_within = nullptr) {
- if (current == stay_within)
- return nullptr;
-
- typename TreeNode<T>::NodeType* next = current->Next();
- if (!next)
- return current->Parent();
- while (next->FirstChild())
- next = next->FirstChild();
- return next;
-}
-
-} // namespace WTF
-
-using WTF::TreeNode;
-using WTF::TraverseNext;
-using WTF::TraverseNextPostOrder;
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TREE_NODE_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/tree_node_test.cc b/chromium/third_party/blink/renderer/platform/wtf/tree_node_test.cc
deleted file mode 100644
index 2508472a7de..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/tree_node_test.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY 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/platform/wtf/tree_node.h"
-
-#include "base/memory/scoped_refptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-
-namespace WTF {
-
-class TestTree : public RefCounted<TestTree>, public TreeNode<TestTree> {
- public:
- static scoped_refptr<TestTree> Create() {
- return base::AdoptRef(new TestTree());
- }
-};
-
-TEST(TreeNodeTest, AppendChild) {
- scoped_refptr<TestTree> root = TestTree::Create();
- scoped_refptr<TestTree> first_child = TestTree::Create();
- scoped_refptr<TestTree> last_child = TestTree::Create();
-
- root->AppendChild(first_child.get());
- EXPECT_EQ(root->FirstChild(), first_child.get());
- EXPECT_EQ(root->LastChild(), first_child.get());
- EXPECT_EQ(first_child->Parent(), root.get());
-
- root->AppendChild(last_child.get());
- EXPECT_EQ(root->FirstChild(), first_child.get());
- EXPECT_EQ(root->LastChild(), last_child.get());
- EXPECT_EQ(last_child->Previous(), first_child.get());
- EXPECT_EQ(first_child->Next(), last_child.get());
- EXPECT_EQ(last_child->Parent(), root.get());
-}
-
-TEST(TreeNodeTest, InsertBefore) {
- scoped_refptr<TestTree> root = TestTree::Create();
- scoped_refptr<TestTree> first_child = TestTree::Create();
- scoped_refptr<TestTree> middle_child = TestTree::Create();
- scoped_refptr<TestTree> last_child = TestTree::Create();
-
- // Inserting single node
- root->InsertBefore(last_child.get(), nullptr);
- EXPECT_EQ(last_child->Parent(), root.get());
- EXPECT_EQ(root->FirstChild(), last_child.get());
- EXPECT_EQ(root->LastChild(), last_child.get());
-
- // Then prepend
- root->InsertBefore(first_child.get(), last_child.get());
- EXPECT_EQ(first_child->Parent(), root.get());
- EXPECT_EQ(root->FirstChild(), first_child.get());
- EXPECT_EQ(root->LastChild(), last_child.get());
- EXPECT_EQ(first_child->Next(), last_child.get());
- EXPECT_EQ(first_child.get(), last_child->Previous());
-
- // Inserting in the middle
- root->InsertBefore(middle_child.get(), last_child.get());
- EXPECT_EQ(middle_child->Parent(), root.get());
- EXPECT_EQ(root->FirstChild(), first_child.get());
- EXPECT_EQ(root->LastChild(), last_child.get());
- EXPECT_EQ(middle_child->Previous(), first_child.get());
- EXPECT_EQ(middle_child->Next(), last_child.get());
- EXPECT_EQ(first_child->Next(), middle_child.get());
- EXPECT_EQ(last_child->Previous(), middle_child.get());
-}
-
-TEST(TreeNodeTest, RemoveSingle) {
- scoped_refptr<TestTree> root = TestTree::Create();
- scoped_refptr<TestTree> child = TestTree::Create();
- scoped_refptr<TestTree> null_node;
-
- root->AppendChild(child.get());
- root->RemoveChild(child.get());
- EXPECT_EQ(child->Next(), null_node.get());
- EXPECT_EQ(child->Previous(), null_node.get());
- EXPECT_EQ(child->Parent(), null_node.get());
- EXPECT_EQ(root->FirstChild(), null_node.get());
- EXPECT_EQ(root->LastChild(), null_node.get());
-}
-
-class Trio {
- STACK_ALLOCATED();
-
- public:
- Trio()
- : root(TestTree::Create()),
- first_child(TestTree::Create()),
- middle_child(TestTree::Create()),
- last_child(TestTree::Create()) {}
-
- void AppendChildren() {
- root->AppendChild(first_child.get());
- root->AppendChild(middle_child.get());
- root->AppendChild(last_child.get());
- }
-
- scoped_refptr<TestTree> root;
- scoped_refptr<TestTree> first_child;
- scoped_refptr<TestTree> middle_child;
- scoped_refptr<TestTree> last_child;
-};
-
-TEST(TreeNodeTest, RemoveMiddle) {
- Trio trio;
- trio.AppendChildren();
-
- trio.root->RemoveChild(trio.middle_child.get());
- EXPECT_TRUE(trio.middle_child->Orphan());
- EXPECT_EQ(trio.first_child->Next(), trio.last_child.get());
- EXPECT_EQ(trio.last_child->Previous(), trio.first_child.get());
- EXPECT_EQ(trio.root->FirstChild(), trio.first_child.get());
- EXPECT_EQ(trio.root->LastChild(), trio.last_child.get());
-}
-
-TEST(TreeNodeTest, RemoveLast) {
- scoped_refptr<TestTree> null_node;
- Trio trio;
- trio.AppendChildren();
-
- trio.root->RemoveChild(trio.last_child.get());
- EXPECT_TRUE(trio.last_child->Orphan());
- EXPECT_EQ(trio.middle_child->Next(), null_node.get());
- EXPECT_EQ(trio.root->FirstChild(), trio.first_child.get());
- EXPECT_EQ(trio.root->LastChild(), trio.middle_child.get());
-}
-
-TEST(TreeNodeTest, RemoveFirst) {
- scoped_refptr<TestTree> null_node;
- Trio trio;
- trio.AppendChildren();
-
- trio.root->RemoveChild(trio.first_child.get());
- EXPECT_TRUE(trio.first_child->Orphan());
- EXPECT_EQ(trio.middle_child->Previous(), null_node.get());
- EXPECT_EQ(trio.root->FirstChild(), trio.middle_child.get());
- EXPECT_EQ(trio.root->LastChild(), trio.last_child.get());
-}
-
-TEST(TreeNodeTest, TakeChildrenFrom) {
- scoped_refptr<TestTree> new_parent = TestTree::Create();
- Trio trio;
- trio.AppendChildren();
-
- new_parent->TakeChildrenFrom(trio.root.get());
-
- EXPECT_FALSE(trio.root->HasChildren());
- EXPECT_TRUE(new_parent->HasChildren());
- EXPECT_EQ(trio.first_child.get(), new_parent->FirstChild());
- EXPECT_EQ(trio.middle_child.get(), new_parent->FirstChild()->Next());
- EXPECT_EQ(trio.last_child.get(), new_parent->LastChild());
-}
-
-class TrioWithGrandChild : public Trio {
- public:
- TrioWithGrandChild() : grand_child(TestTree::Create()) {}
-
- void AppendChildren() {
- Trio::AppendChildren();
- middle_child->AppendChild(grand_child.get());
- }
-
- scoped_refptr<TestTree> grand_child;
-};
-
-TEST(TreeNodeTest, TraverseNext) {
- TrioWithGrandChild trio;
- trio.AppendChildren();
-
- TestTree* order[] = {trio.root.get(), trio.first_child.get(),
- trio.middle_child.get(), trio.grand_child.get(),
- trio.last_child.get()};
-
- unsigned order_index = 0;
- for (TestTree *node = trio.root.get(); node;
- node = TraverseNext(node), order_index++)
- EXPECT_EQ(node, order[order_index]);
- EXPECT_EQ(order_index, sizeof(order) / sizeof(TestTree*));
-}
-
-TEST(TreeNodeTest, TraverseNextPostORder) {
- TrioWithGrandChild trio;
- trio.AppendChildren();
-
- TestTree* order[] = {trio.first_child.get(), trio.grand_child.get(),
- trio.middle_child.get(), trio.last_child.get(),
- trio.root.get()};
-
- unsigned order_index = 0;
- for (TestTree *node = TraverseFirstPostOrder(trio.root.get()); node;
- node = TraverseNextPostOrder(node), order_index++)
- EXPECT_EQ(node, order[order_index]);
- EXPECT_EQ(order_index, sizeof(order) / sizeof(TestTree*));
-}
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/type_traits_test.cc b/chromium/third_party/blink/renderer/platform/wtf/type_traits_test.cc
index 1b45d55a4fa..f127d57c5cf 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/type_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/type_traits_test.cc
@@ -21,7 +21,6 @@
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -105,13 +104,17 @@ static_assert(std::is_trivially_default_constructible<NestedOwned>::value,
"NestedOwned should have a trivial default constructor");
class NonCopyableClass {
- DISALLOW_COPY_AND_ASSIGN(NonCopyableClass);
+ public:
+ NonCopyableClass(const NonCopyableClass&) = delete;
+ NonCopyableClass& operator=(const NonCopyableClass&) = delete;
};
-#if 0 // Compilers don't get this "right" yet if using = delete.
-static_assert(!IsTriviallyMoveAssignable<NonCopyableClass>::value, "NonCopyableClass should not be trivially move assignable");
-static_assert(!IsTriviallyCopyAssignable<NonCopyableClass>::value, "NonCopyableClass should not be trivially copy assignable");
-static_assert(IsTriviallyDefaultConstructible<NonCopyableClass>::value, "NonCopyableClass should have a trivial default constructor");
-#endif // 0
+
+static_assert(!std::is_trivially_move_assignable<NonCopyableClass>::value,
+ "NonCopyableClass should not be trivially move assignable");
+static_assert(!std::is_trivially_copy_assignable<NonCopyableClass>::value,
+ "NonCopyableClass should not be trivially copy assignable");
+static_assert(!std::is_trivially_default_constructible<NonCopyableClass>::value,
+ "NonCopyableClass should not have a trivial default constructor");
template <typename T>
class TestBaseClass {};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector.h b/chromium/third_party/blink/renderer/platform/wtf/vector.h
index deb5855ac07..e45b88b9247 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector.h
@@ -28,7 +28,6 @@
#include <utility>
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
#include "base/template_util.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
@@ -573,8 +572,6 @@ class VectorBufferBase {
T* buffer_;
wtf_size_t capacity_;
wtf_size_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(VectorBufferBase);
};
template <typename T,
@@ -618,14 +615,22 @@ class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocator> {
}
inline bool ShrinkBuffer(wtf_size_t new_capacity) {
+ DCHECK(buffer_);
DCHECK_LT(new_capacity, capacity());
size_t size_to_allocate = AllocationSize(new_capacity);
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ ANNOTATE_DELETE_BUFFER(buffer_, capacity_, size_);
+#endif
+ bool succeeded = false;
if (Allocator::ShrinkVectorBacking(buffer_, AllocationSize(capacity()),
size_to_allocate)) {
capacity_ = static_cast<wtf_size_t>(size_to_allocate / sizeof(T));
- return true;
+ succeeded = true;
}
- return false;
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ ANNOTATE_NEW_BUFFER(buffer_, capacity_, size_);
+#endif
+ return succeeded;
}
void ResetBufferPointer() {
@@ -701,6 +706,9 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
Base::AllocateBuffer(capacity);
}
+ VectorBuffer(const VectorBuffer&) = delete;
+ VectorBuffer& operator=(const VectorBuffer&) = delete;
+
void Destruct() {
DeallocateBuffer(buffer_);
buffer_ = nullptr;
@@ -729,6 +737,7 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
}
inline bool ShrinkBuffer(wtf_size_t new_capacity) {
+ DCHECK(buffer_);
DCHECK_LT(new_capacity, capacity());
if (new_capacity <= inlineCapacity) {
// We need to switch to inlineBuffer. Vector::ShrinkCapacity will
@@ -737,11 +746,19 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
}
DCHECK_NE(buffer_, InlineBuffer());
size_t new_size = AllocationSize(new_capacity);
- if (!Allocator::ShrinkVectorBacking(buffer_, AllocationSize(capacity()),
- new_size))
- return false;
- capacity_ = static_cast<wtf_size_t>(new_size / sizeof(T));
- return true;
+ bool succeeded = false;
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ ANNOTATE_DELETE_BUFFER(buffer_, capacity_, size_);
+#endif
+ if (Allocator::ShrinkVectorBacking(buffer_, AllocationSize(capacity()),
+ new_size)) {
+ capacity_ = static_cast<wtf_size_t>(new_size / sizeof(T));
+ succeeded = true;
+ }
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ ANNOTATE_NEW_BUFFER(buffer_, capacity_, size_);
+#endif
+ return succeeded;
}
void ResetBufferPointer() {
@@ -983,8 +1000,6 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
alignas(T) char inline_buffer_[kInlineBufferSize];
template <typename U, wtf_size_t inlineBuffer, typename V>
friend class Deque;
-
- DISALLOW_COPY_AND_ASSIGN(VectorBuffer);
};
//
@@ -1796,13 +1811,12 @@ void Vector<T, inlineCapacity, Allocator>::ReserveCapacity(
Base::AllocateBuffer(new_capacity);
return;
}
-#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
wtf_size_t old_capacity = capacity();
-#endif
// The Allocator::isGarbageCollected check is not needed. The check is just
// a static hint for a compiler to indicate that Base::expandBuffer returns
// false if Allocator is a PartitionAllocator.
if (Allocator::kIsGarbageCollected && Base::ExpandBuffer(new_capacity)) {
+ DCHECK_LE(old_capacity, capacity());
ANNOTATE_CHANGE_CAPACITY(begin(), old_capacity, size_, capacity());
return;
}
@@ -1839,7 +1853,6 @@ void Vector<T, inlineCapacity, Allocator>::ShrinkCapacity(
#endif
if (new_capacity > 0) {
if (Base::ShrinkBuffer(new_capacity)) {
- ANNOTATE_CHANGE_CAPACITY(begin(), old_capacity, size_, capacity());
return;
}
@@ -2071,7 +2084,7 @@ inline auto Vector<T, inlineCapacity, Allocator>::erase(iterator first,
-> iterator {
DCHECK_LE(first, last);
const wtf_size_t index = static_cast<wtf_size_t>(first - begin());
- const wtf_size_t diff = std::distance(first, last);
+ const wtf_size_t diff = static_cast<wtf_size_t>(std::distance(first, last));
EraseAt(index, diff);
return begin() + index;
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h b/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
index d8990c46403..0d7297abd7a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_BACKED_LINKED_LIST_H_
#include "base/dcheck_is_on.h"
-#include "base/macros.h"
+#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h b/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
index 3e09b942f7d..23cbc15ac76 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
@@ -7,7 +7,6 @@
#include <type_traits>
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -52,8 +51,6 @@ class MoveOnly {
private:
int i_;
-
- DISALLOW_COPY_AND_ASSIGN(MoveOnly);
};
class MoveOnlyHashValue {
diff --git a/chromium/third_party/blink/tools/blinkpy/PRESUBMIT.py b/chromium/third_party/blink/tools/blinkpy/PRESUBMIT.py
index 117e3cf6052..00064704a47 100644
--- a/chromium/third_party/blink/tools/blinkpy/PRESUBMIT.py
+++ b/chromium/third_party/blink/tools/blinkpy/PRESUBMIT.py
@@ -10,6 +10,8 @@ for more details about the presubmit API built into gcl.
import inspect
import sys
+USE_PYTHON3 = True
+
def CheckChangeOnUpload(input_api, output_api):
results = []
diff --git a/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py b/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py
deleted file mode 100644
index ca0bbd2205b..00000000000
--- a/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py
+++ /dev/null
@@ -1,403 +0,0 @@
-# Copyright (C) 2011 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# 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.
-#
-
-from contextlib import contextmanager
-import difflib
-import filecmp
-import fnmatch
-import os
-import shutil
-import tempfile
-
-from blinkpy.common.system.executive import Executive
-
-from blinkpy.common import path_finder
-path_finder.add_bindings_scripts_dir_to_sys_path()
-path_finder.add_build_scripts_dir_to_sys_path()
-
-from code_generator_v8 import CodeGeneratorDictionaryImpl
-from code_generator_v8 import CodeGeneratorV8
-from code_generator_v8 import CodeGeneratorUnionType
-from code_generator_v8 import CodeGeneratorCallbackFunction
-from compute_interfaces_info_individual import InterfaceInfoCollector
-from compute_interfaces_info_overall import (compute_interfaces_info_overall,
- interfaces_info)
-from generate_origin_trial_features import generate_origin_trial_features
-from idl_compiler import (generate_bindings, generate_union_type_containers,
- generate_dictionary_impl,
- generate_callback_function_impl)
-from json5_generator import Json5File
-from utilities import ComponentInfoProviderCore
-from utilities import ComponentInfoProviderModules
-from utilities import get_file_contents
-from utilities import get_first_interface_name_from_idl
-from utilities import to_snake_case
-
-PASS_MESSAGE = 'All tests PASS!'
-FAIL_MESSAGE = """Some tests FAIL!
-To update the reference files, execute:
- third_party/blink/tools/run_bindings_tests.py --reset-results
-
-If the failures are not due to your changes, test results may be out of sync;
-please rebaseline them in a separate CL, after checking that tests fail in ToT.
-In CL, please set:
-NOTRY=true
-TBR=someone in third_party/blink/renderer/bindings/OWNERS or WATCHLISTS:bindings
-"""
-
-SOURCE_PATH = path_finder.get_source_dir()
-DEPENDENCY_IDL_FILES = frozenset([
- 'test_interface_mixin.idl',
- 'test_interface_mixin_2.idl',
- 'test_interface_mixin_3.idl',
- 'test_interface_partial.idl',
- 'test_interface_partial_2.idl',
- 'test_interface_partial_3.idl',
- 'test_interface_partial_4.idl',
- 'test_interface_partial_secure_context.idl',
- 'test_interface_2_partial.idl',
- 'test_interface_2_partial_2.idl',
-])
-
-COMPONENT_DIRECTORY = frozenset(['core', 'modules'])
-TEST_INPUT_DIRECTORY = os.path.join(SOURCE_PATH, 'bindings', 'tests', 'idls')
-REFERENCE_DIRECTORY = os.path.join(SOURCE_PATH, 'bindings', 'tests', 'results')
-
-# component -> ComponentInfoProvider.
-# Note that this dict contains information about testing idl files, which live
-# in Source/bindings/tests/idls/{core,modules}, not in Source/{core,modules}.
-component_info_providers = {}
-
-
-@contextmanager
-def TemporaryDirectory():
- """Wrapper for tempfile.mkdtemp() so it's usable with 'with' statement.
-
- Simple backport of tempfile.TemporaryDirectory from Python 3.2.
- """
- name = tempfile.mkdtemp()
- try:
- yield name
- finally:
- shutil.rmtree(name)
-
-
-def generate_interface_dependencies(runtime_enabled_features):
- def idl_paths_recursive(directory):
- # This is slow, especially on Windows, due to os.walk making
- # excess stat() calls. Faster versions may appear in Python 3.5 or
- # later:
- # https://github.com/benhoyt/scandir
- # http://bugs.python.org/issue11406
- idl_paths = []
- for dirpath, _, files in os.walk(directory):
- idl_paths.extend(
- os.path.join(dirpath, filename)
- for filename in fnmatch.filter(files, '*.idl'))
- return idl_paths
-
- def collect_blink_idl_paths():
- """Returns IDL file paths which blink actually uses."""
- idl_paths = []
- for component in COMPONENT_DIRECTORY:
- directory = os.path.join(SOURCE_PATH, component)
- idl_paths.extend(idl_paths_recursive(directory))
- return idl_paths
-
- def collect_interfaces_info(idl_path_list):
- info_collector = InterfaceInfoCollector()
- for idl_path in idl_path_list:
- info_collector.collect_info(idl_path)
- info = info_collector.get_info_as_dict()
- # TestDictionary.{h,cpp} are placed under
- # Source/bindings/tests/idls/core. However, IdlCompiler generates
- # TestDictionary.{h,cpp} by using relative_dir.
- # So the files will be generated under
- # output_dir/core/bindings/tests/idls/core.
- # To avoid this issue, we need to clear relative_dir here.
- for value in info['interfaces_info'].itervalues():
- value['relative_dir'] = ''
- component_info = info_collector.get_component_info_as_dict(
- runtime_enabled_features)
- return info, component_info
-
- # We compute interfaces info for *all* IDL files, not just test IDL
- # files, as code generator output depends on inheritance (both ancestor
- # chain and inherited extended attributes), and some real interfaces
- # are special-cased, such as Node.
- #
- # For example, when testing the behavior of interfaces that inherit
- # from Node, we also need to know that these inherit from EventTarget,
- # since this is also special-cased and Node inherits from EventTarget,
- # but this inheritance information requires computing dependencies for
- # the real Node.idl file.
- non_test_idl_paths = collect_blink_idl_paths()
- # For bindings test IDL files, we collect interfaces info for each
- # component so that we can generate union type containers separately.
- test_idl_paths = {}
- for component in COMPONENT_DIRECTORY:
- test_idl_paths[component] = idl_paths_recursive(
- os.path.join(TEST_INPUT_DIRECTORY, component))
- # 2nd-stage computation: individual, then overall
- #
- # Properly should compute separately by component (currently test
- # includes are invalid), but that's brittle (would need to update this file
- # for each new component) and doesn't test the code generator any better
- # than using a single component.
- non_test_interfaces_info, non_test_component_info = collect_interfaces_info(
- non_test_idl_paths)
- test_interfaces_info = {}
- test_component_info = {}
- for component, paths in test_idl_paths.iteritems():
- test_interfaces_info[component], test_component_info[component] = \
- collect_interfaces_info(paths)
- # In order to allow test IDL files to override the production IDL files if
- # they have the same interface name, process the test IDL files after the
- # non-test IDL files.
- info_individuals = [non_test_interfaces_info] + \
- test_interfaces_info.values()
- compute_interfaces_info_overall(info_individuals)
- # Add typedefs which are specified in the actual IDL files to the testing
- # component info.
- test_component_info['core']['typedefs'].update(
- non_test_component_info['typedefs'])
- component_info_providers['core'] = ComponentInfoProviderCore(
- interfaces_info, test_component_info['core'])
- component_info_providers['modules'] = ComponentInfoProviderModules(
- interfaces_info, test_component_info['core'],
- test_component_info['modules'])
-
-
-class IdlCompilerOptions(object):
- def __init__(self, output_directory, cache_directory,
- impl_output_directory, target_component):
- self.output_directory = output_directory
- self.cache_directory = cache_directory
- self.impl_output_directory = impl_output_directory
- self.target_component = target_component
-
-
-def bindings_tests(output_directory, verbose, suppress_diff):
- executive = Executive()
-
- def list_files(directory):
- if not os.path.isdir(directory):
- return []
-
- files = []
- for component in os.listdir(directory):
- if component not in COMPONENT_DIRECTORY:
- continue
- directory_with_component = os.path.join(directory, component)
- for filename in os.listdir(directory_with_component):
- files.append(os.path.join(directory_with_component, filename))
- return files
-
- def diff(filename1, filename2):
- with open(filename1) as file1:
- file1_lines = file1.readlines()
- with open(filename2) as file2:
- file2_lines = file2.readlines()
-
- # Use Python's difflib module so that diffing works across platforms
- return ''.join(difflib.context_diff(file1_lines, file2_lines))
-
- def is_cache_file(filename):
- return filename.endswith('.cache')
-
- def delete_cache_files():
- # FIXME: Instead of deleting cache files, don't generate them.
- cache_files = [
- path for path in list_files(output_directory)
- if is_cache_file(os.path.basename(path))
- ]
- for cache_file in cache_files:
- os.remove(cache_file)
-
- def identical_file(reference_filename, output_filename):
- reference_basename = os.path.basename(reference_filename)
-
- if not os.path.isfile(reference_filename):
- print 'Missing reference file!'
- print '(if adding new test, update reference files)'
- print reference_basename
- print
- return False
-
- if not filecmp.cmp(reference_filename, output_filename):
- # cmp is much faster than diff, and usual case is "no difference",
- # so only run diff if cmp detects a difference
- print 'FAIL: %s' % reference_basename
- if not suppress_diff:
- print diff(reference_filename, output_filename)
- return False
-
- if verbose:
- print 'PASS: %s' % reference_basename
- return True
-
- def identical_output_files(output_files):
- reference_files = [
- os.path.join(REFERENCE_DIRECTORY,
- os.path.relpath(path, output_directory))
- for path in output_files
- ]
- return all([
- identical_file(reference_filename, output_filename)
- for (reference_filename,
- output_filename) in zip(reference_files, output_files)
- ])
-
- def no_excess_files(output_files):
- generated_files = set(
- [os.path.relpath(path, output_directory) for path in output_files])
- excess_files = []
- for path in list_files(REFERENCE_DIRECTORY):
- relpath = os.path.relpath(path, REFERENCE_DIRECTORY)
- # Ignore backup files made by a VCS.
- if os.path.splitext(relpath)[1] == '.orig':
- continue
- if relpath not in generated_files:
- excess_files.append(relpath)
- if excess_files:
- print('Excess reference files! '
- '(probably cruft from renaming or deleting):\n' +
- '\n'.join(excess_files))
- return False
- return True
-
- def make_runtime_features_dict():
- input_filename = os.path.join(TEST_INPUT_DIRECTORY,
- 'runtime_enabled_features.json5')
- json5_file = Json5File.load_from_files([input_filename])
- features_map = {}
- for feature in json5_file.name_dictionaries:
- features_map[str(feature['name'])] = {
- 'in_origin_trial': feature['in_origin_trial']
- }
- return features_map
-
- try:
- generate_interface_dependencies(make_runtime_features_dict())
- for component in COMPONENT_DIRECTORY:
- output_dir = os.path.join(output_directory, component)
- if not os.path.exists(output_dir):
- os.makedirs(output_dir)
-
- options = IdlCompilerOptions(
- output_directory=output_dir,
- impl_output_directory=output_dir,
- cache_directory=None,
- target_component=component)
-
- if component == 'core':
- partial_interface_output_dir = \
- os.path.join(output_directory, 'modules')
- if not os.path.exists(partial_interface_output_dir):
- os.makedirs(partial_interface_output_dir)
- partial_interface_options = IdlCompilerOptions(
- output_directory=partial_interface_output_dir,
- impl_output_directory=None,
- cache_directory=None,
- target_component='modules')
-
- idl_filenames = []
- dictionary_impl_filenames = []
- partial_interface_filenames = []
- input_directory = os.path.join(TEST_INPUT_DIRECTORY, component)
- for filename in os.listdir(input_directory):
- if (filename.endswith('.idl') and
- # Dependencies aren't built
- # (they are used by the dependent)
- filename not in DEPENDENCY_IDL_FILES):
- idl_path = os.path.realpath(
- os.path.join(input_directory, filename))
- idl_filenames.append(idl_path)
- idl_basename = os.path.basename(idl_path)
- name_from_basename, _ = os.path.splitext(idl_basename)
- definition_name = get_first_interface_name_from_idl(
- get_file_contents(idl_path))
- is_partial_interface_idl = to_snake_case(
- definition_name) != name_from_basename
- if not is_partial_interface_idl:
- interface_info = interfaces_info[definition_name]
- if interface_info['is_dictionary']:
- dictionary_impl_filenames.append(idl_path)
- if component == 'core' and interface_info[
- 'dependencies_other_component_full_paths']:
- partial_interface_filenames.append(idl_path)
-
- info_provider = component_info_providers[component]
- partial_interface_info_provider = \
- component_info_providers['modules']
-
- generate_union_type_containers(CodeGeneratorUnionType,
- info_provider, options)
- generate_callback_function_impl(CodeGeneratorCallbackFunction,
- info_provider, options)
- generate_bindings(CodeGeneratorV8, info_provider, options,
- idl_filenames)
- generate_bindings(CodeGeneratorV8, partial_interface_info_provider,
- partial_interface_options,
- partial_interface_filenames)
- generate_dictionary_impl(CodeGeneratorDictionaryImpl,
- info_provider, options,
- dictionary_impl_filenames)
- generate_origin_trial_features(info_provider, options, [
- filename for filename in idl_filenames
- if filename not in dictionary_impl_filenames
- ])
-
- finally:
- delete_cache_files()
-
- # Detect all changes
- output_files = list_files(output_directory)
- passed = identical_output_files(output_files)
- passed &= no_excess_files(output_files)
-
- if passed:
- if verbose:
- print
- print PASS_MESSAGE
- return 0
- print
- print FAIL_MESSAGE
- return 1
-
-
-def run_bindings_tests(reset_results, verbose, suppress_diff):
- # Generate output into the reference directory if resetting results, or
- # a temp directory if not.
- if reset_results:
- print 'Resetting results'
- return bindings_tests(REFERENCE_DIRECTORY, verbose, suppress_diff)
- with TemporaryDirectory() as temp_dir:
- # TODO(peria): Remove this hack.
- # Some internal algorithms depend on the path of output directory.
- temp_source_path = os.path.join(temp_dir, 'third_party', 'blink',
- 'renderer')
- temp_output_path = os.path.join(temp_source_path, 'bindings', 'tests',
- 'results')
- return bindings_tests(temp_output_path, verbose, suppress_diff)
diff --git a/chromium/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py
index 725ff1afaed..ec97f6a643e 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py
@@ -60,8 +60,12 @@ class BaselineOptimizerTest(unittest.TestCase):
# MockPortFactory and use it.
self.host.builders = BuilderList({
'Fake Test Win10': {
- 'port_name': 'win-win10',
- 'specifiers': ['Win10', 'Release']
+ 'port_name': 'win-win10.1909',
+ 'specifiers': ['Win10.1909', 'Release']
+ },
+ 'Fake Test Win10.20h2': {
+ 'port_name': 'win-win10.20h2',
+ 'specifiers': ['Win10.20h2', 'Release']
},
'Fake Test Linux': {
'port_name': 'linux-trusty',
@@ -91,11 +95,10 @@ class BaselineOptimizerTest(unittest.TestCase):
# Note: this is a pre-assumption of the tests in this file. If this
# assertion fails, port configurations are likely changed, and the
# tests need to be adjusted accordingly.
- self.assertEqual(
- sorted(self.host.port_factory.all_port_names()), [
- 'linux-trusty', 'mac-mac10.12', 'mac-mac10.13', 'mac-mac10.14',
- 'mac-mac10.15', 'mac-mac11.0', 'win-win10'
- ])
+ self.assertEqual(sorted(self.host.port_factory.all_port_names()), [
+ 'linux-trusty', 'mac-mac10.12', 'mac-mac10.13', 'mac-mac10.14',
+ 'mac-mac10.15', 'mac-mac11.0', 'win-win10.1909', 'win-win10.20h2'
+ ])
def _assert_optimization(self,
results_by_directory,
diff --git a/chromium/third_party/blink/tools/blinkpy/common/config/builders.json b/chromium/third_party/blink/tools/blinkpy/common/config/builders.json
index e22e3d6c758..2d80e1f6728 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/config/builders.json
+++ b/chromium/third_party/blink/tools/blinkpy/common/config/builders.json
@@ -56,8 +56,8 @@
},
"Win10 Tests x64": {
"master": "chromium.win",
- "port_name": "win-win10",
- "specifiers": ["Win10", "Release"]
+ "port_name": "win-win10.1909",
+ "specifiers": ["Win10.1909", "Release"]
},
"Win7 Tests (dbg)(1)": {
"master": "chromium.win",
@@ -127,8 +127,14 @@
},
"win10-blink-rel": {
"master": "tryserver.blink",
- "port_name": "win-win10",
- "specifiers": ["Win10", "Release"],
+ "port_name": "win-win10.1909",
+ "specifiers": ["Win10.1909", "Release"],
+ "is_try_builder": true
+ },
+ "win10.20h2-blink-rel": {
+ "master": "tryserver.blink",
+ "port_name": "win-win10.20h2",
+ "specifiers": ["Win10.20h2", "Release"],
"is_try_builder": true
},
"linux-rel": {
@@ -148,8 +154,8 @@
},
"win10_chromium_x64_rel_ng": {
"master": "tryserver.chromium.win",
- "port_name": "win-win10",
- "specifiers": ["Win10", "Release"],
+ "port_name": "win-win10.1909",
+ "specifiers": ["Win10.1909", "Release"],
"is_try_builder": true,
"is_cq_builder":true
},
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/network_transaction_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/net/network_transaction_unittest.py
index b827cafa345..b0cc4614202 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/network_transaction_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/network_transaction_unittest.py
@@ -26,10 +26,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from urllib2 import HTTPError
from blinkpy.common.net.network_transaction import NetworkTransaction, NetworkTimeout
from blinkpy.common.system.log_testing import LoggingTestCase
+from six.moves.urllib.error import HTTPError
+
class NetworkTransactionTest(LoggingTestCase):
exception = Exception('Test exception')
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher.py b/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
index ca286ea8d06..0983d350a62 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
@@ -180,14 +180,9 @@ class TestResultsFetcher(object):
# patch)'. Only make sure it starts with blink_web_tests and
# runs with a patch. This should be changed eventually to use actual
# structured data from the test results server.
- if
- (re.match(r'(blink_web_tests|wpt_tests_suite).*\(with patch\)$',
- entry['TestType'])
- # TODO(crbug.com/1178099) remove this once highdpi is stabilized
- # and no longer experimental. With the current config,
- # TestType doesn't have (with patch) suffix for highdpi while the
- # results url has (experimental, with patch) suffix.
- or entry['TestType'].startswith('high_dpi_blink_web_tests'))
+ if re.match(
+ r'(blink_web_tests|wpt_tests_suite|high_dpi_blink_web_tests).*\(with patch\)$',
+ entry['TestType'])
]
# In manual testing, I sometimes saw results where the same suite was
# repeated twice. De-duplicate here to try to catch this.
@@ -197,11 +192,6 @@ class TestResultsFetcher(object):
'build %s on builder %s expected to only have one web test '
'step, instead has %s' % (build.build_number,
build.builder_name, suites))
- if suites[0].startswith('high_dpi_blink_web_tests'):
- # TODO(crbug.com/1178099) remove this once highdpi is stabilized
- # and no longer experimental.
- suites[0] = suites[0] + " (with patch, experimental)"
-
return suites[0]
@memoized
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py b/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
index 94b7efdfa90..2b3e4b770d0 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
@@ -45,6 +45,7 @@ class BuilderTest(LoggingTestCase):
'https://test-results.appspot.com/data/layout_results/Test_Builder/results/layout-test-results'
)
+ @unittest.skip('crbug/1234319 disable to unblock the CI')
def test_results_url_with_build_number(self):
self.assertEqual(
TestResultsFetcher().results_url('Test Builder', 10),
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/web_mock.py b/chromium/third_party/blink/tools/blinkpy/common/net/web_mock.py
index bb0671ce7cb..85c5074da0e 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/web_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/web_mock.py
@@ -26,7 +26,7 @@
# (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 urllib2
+from six.moves.urllib.error import HTTPError
class MockWeb(object):
@@ -55,12 +55,12 @@ class MockResponse(object):
self._info = MockInfo(values.get('headers', {}))
if int(self.status_code) >= 400:
- raise urllib2.HTTPError(
- url=self.url,
- code=self.status_code,
- msg='Received error status code: {}'.format(self.status_code),
- hdrs={},
- fp=None)
+ raise HTTPError(url=self.url,
+ code=self.status_code,
+ msg='Received error status code: {}'.format(
+ self.status_code),
+ hdrs={},
+ fp=None)
def getcode(self):
return self.status_code
diff --git a/chromium/third_party/blink/tools/blinkpy/common/read_checksum_from_png_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/read_checksum_from_png_unittest.py
index 091426d1417..8e3ea17e47c 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/read_checksum_from_png_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/read_checksum_from_png_unittest.py
@@ -21,24 +21,25 @@
# (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 StringIO
import unittest
from blinkpy.common import read_checksum_from_png
+from six import StringIO
+
class ReadChecksumFromPngTest(unittest.TestCase):
def test_read_checksum(self):
# pylint: disable=line-too-long
# Test a file with the comment.
- filehandle = StringIO.StringIO(
+ filehandle = StringIO(
'''\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03 \x00\x00\x02X\x08\x02\x00\x00\x00\x15\x14\x15'\x00\x00\x00)tEXtchecksum\x003c4134fe2739880353f91c5b84cadbaaC\xb8?\xec\x00\x00\x16\xfeIDATx\x9c\xed\xdd[\x8cU\xe5\xc1\xff\xf15T\x18\x0ea,)\xa6\x80XZ<\x10\n\xd6H\xc4V\x88}\xb5\xa9\xd6r\xd5\x0bki0\xa6\xb5ih\xd2\xde\x98PHz\xd1\x02=\\q#\x01\x8b\xa5rJ\x8b\x88i\xacM\xc5h\x8cbMk(\x1ez@!\x0c\xd5\xd2\xc2\xb44\x1c\x848\x1dF(\xeb\x7f\xb1\xff\xd9\xef~g\xd6\xde3\xe0o\x10\xec\xe7sa6{\xd6z\xd6\xb3\xd7\xf3\xa8_7\xdbM[Y\x96\x05\x00\x009\xc3\xde\xeb\t\x00\x00\xbc\xdf\x08,\x00\x800\x81\x05\x00\x10&\xb0\x00\x00\xc2\x04\x16\x00@\x98\xc0\x02\x00\x08\x13X\x00\x00a\x02\x0b\x00 Lx01\x00\x84\t,\x00\x800\x81\x05\x00\x10\xd64\xb0\xda\x9a\xdb\xb6m\xdb\xb4i\xd3\xfa\x9fr\xf3\xcd7\x0f\xe5T\x07\xe5\xd4\xa9'''
)
checksum = read_checksum_from_png.read_checksum(filehandle)
self.assertEqual('3c4134fe2739880353f91c5b84cadbaa', checksum)
# Test a file without the comment.
- filehandle = StringIO.StringIO(
+ filehandle = StringIO(
'''\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03 \x00\x00\x02X\x08\x02\x00\x00\x00\x15\x14\x15'\x00\x00\x16\xfeIDATx\x9c\xed\xdd[\x8cU\xe5\xc1\xff\xf15T\x18\x0ea,)\xa6\x80XZ<\x10\n\xd6H\xc4V\x88}\xb5\xa9\xd6r\xd5\x0bki0\xa6\xb5ih\xd2\xde\x98PHz\xd1\x02=\\q#\x01\x8b\xa5rJ\x8b\x88i\xacM\xc5h\x8cbMk(\x1ez@!\x0c\xd5\xd2\xc2\xb44\x1c\x848\x1dF(\xeb\x7f\xb1\xff\xd9\xef~g\xd6\xde3\xe0o\x10\xec\xe7sa6{\xd6z\xd6\xb3\xd7\xf3\xa8_7\xdbM[Y\x96\x05\x00\x009\xc3\xde\xeb\t\x00\x00\xbc\xdf\x08,\x00\x800\x81\x05\x00\x10&\xb0\x00\x00\xc2\x04\x16\x00@\x98\xc0\x02\x00\x08\x13X\x00\x00a\x02\x0b\x00 Lx01\x00\x84\t,\x00\x800\x81\x05\x00\x10\xd64\xb0\xda\x9a\xdb\xb6m\xdb\xb4i\xd3\xfa\x9fr\xf3\xcd7\x0f\xe5T\x07\xe5\xd4\xa9S\x8b\x17/\x1e?~\xfc\xf8\xf1\xe3\xef\xbf\xff\xfe\xf7z:M5\xbb\x87\x17\xcbUZ\x8f|V\xd7\xbd\x10\xb6\xcd{b\x88\xf6j\xb3\x9b?\x14\x9b\xa1>\xe6\xf9\xd9\xcf\x00\x17\x93'''
)
checksum = read_checksum_from_png.read_checksum(filehandle)
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/executive_mock.py b/chromium/third_party/blink/tools/blinkpy/common/system/executive_mock.py
index 628f0fad92c..3d009d88609 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/executive_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/executive_mock.py
@@ -29,19 +29,21 @@
import collections
import logging
import os
-import StringIO
+import six
from blinkpy.common.system.executive import ScriptError
+from six import StringIO
+
_log = logging.getLogger(__name__)
class MockProcess(object):
def __init__(self, stdout='MOCK STDOUT\n', stderr='', returncode=0):
self.pid = 42
- self.stdout = StringIO.StringIO(stdout)
- self.stderr = StringIO.StringIO(stderr)
- self.stdin = StringIO.StringIO()
+ self.stdout = StringIO(stdout)
+ self.stderr = StringIO(stderr)
+ self.stdin = StringIO()
self.returncode = returncode
def wait(self):
@@ -49,8 +51,8 @@ class MockProcess(object):
def poll(self):
# Consider the process completed when all the stdout and stderr has been read.
- if (self.stdout.len != self.stdout.tell()
- or self.stderr.len != self.stderr.tell()):
+ if (len(self.stdout.getvalue()) != self.stdout.tell()
+ or len(self.stderr.getvalue()) != self.stderr.tell()):
return None
return self.returncode
@@ -168,7 +170,7 @@ class MockExecutive(object):
output = self._output
if return_stderr:
output += self._stderr
- if decode_output and not isinstance(output, unicode):
+ if decode_output and not isinstance(output, six.text_type):
output = output.decode('utf-8')
return output
@@ -183,7 +185,7 @@ class MockExecutive(object):
pass
def popen(self, args, cwd=None, env=None, **_):
- assert all(isinstance(arg, basestring) for arg in args)
+ assert all(isinstance(arg, six.string_types) for arg in args)
self._append_call(args, cwd=cwd, env=env)
if self._should_log:
cwd_string = ''
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py b/chromium/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
index 4313fccf550..5ba35e83455 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
@@ -30,11 +30,12 @@ import errno
import hashlib
import os
import re
-import StringIO
import unittest
from blinkpy.common.system.filesystem import _remove_contents, _sanitize_filename
+from six import StringIO
+
class MockFileSystem(object):
# pylint: disable=unused-argument
@@ -181,8 +182,8 @@ class MockFileSystem(object):
path for path, contents in self.files.items()
if contents is not None
]
- return filter(path_filter, existing_files) + filter(
- path_filter, self.dirs)
+ return list(filter(path_filter, existing_files)) + list(
+ filter(path_filter, self.dirs))
def isabs(self, path):
return path.startswith(self.sep)
@@ -465,7 +466,7 @@ class WritableBinaryFileObject(object):
self.path = path
self.closed = False
if path not in self.fs.files or not append:
- self.fs.files[path] = ''
+ self.fs.files[path] = b''
def __enter__(self):
return self
@@ -482,11 +483,16 @@ class WritableBinaryFileObject(object):
class WritableTextFileObject(WritableBinaryFileObject):
+ def __init__(self, fs, path, append=False):
+ super(WritableTextFileObject, self).__init__(fs, path, append)
+ if path not in self.fs.files or not append:
+ self.fs.files[path] = ''
+
def write(self, string):
- WritableBinaryFileObject.write(self, string.encode('utf-8'))
+ WritableBinaryFileObject.write(self, string)
def writelines(self, lines):
- self.fs.files[self.path] = "".join(lines).encode('utf-8')
+ self.fs.files[self.path] = "".join(lines)
self.fs.written_files[self.path] = self.fs.files[self.path]
@@ -527,8 +533,7 @@ class ReadableBinaryFileObject(object):
class ReadableTextFileObject(ReadableBinaryFileObject):
def __init__(self, fs, path, data):
- super(ReadableTextFileObject, self).__init__(
- fs, path, StringIO.StringIO(data.decode('utf-8')))
+ super(ReadableTextFileObject, self).__init__(fs, path, StringIO(data))
def close(self):
self.data.close()
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/output_capture.py b/chromium/third_party/blink/tools/blinkpy/common/system/output_capture.py
index 4dfbf01378d..ab43592ac7e 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/output_capture.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/output_capture.py
@@ -31,7 +31,7 @@
import logging
import sys
-from StringIO import StringIO
+from six import StringIO
class OutputCapture(object):
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/platform_info.py b/chromium/third_party/blink/tools/blinkpy/common/system/platform_info.py
index 1388cf58dc4..8cc9943c2ea 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/platform_info.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/platform_info.py
@@ -58,7 +58,7 @@ class PlatformInfo(object):
platform_module.mac_ver()[0])
if self.os_name.startswith('win'):
self.os_version = self._determine_win_version(
- self._win_version_tuple(sys_module))
+ self._win_version_tuple())
assert sys.platform != 'cygwin', 'Cygwin is not supported.'
def is_mac(self):
@@ -191,7 +191,12 @@ class PlatformInfo(object):
def _determine_win_version(self, win_version_tuple):
if win_version_tuple[:2] == (10, 0):
- return '10'
+ # came across instances where build number was 15063.
+ # Treat those as 1909.
+ if win_version_tuple[2] > 19000:
+ return '10.20h2'
+ else:
+ return '10.1909'
if win_version_tuple[:2] == (6, 3):
return '8.1'
if win_version_tuple[:2] == (6, 2):
@@ -210,9 +215,11 @@ class PlatformInfo(object):
(win_version_tuple, ))
return 'future'
- def _win_version_tuple(self, sys_module):
- if hasattr(sys_module, 'getwindowsversion'):
- return sys_module.getwindowsversion()
+ def _win_version_tuple(self):
+ version_str = self._platform_module.win32_ver()[1]
+ if version_str:
+ return tuple(map(int, version_str.split('.')))
+
return self._win_version_tuple_from_cmd()
def _win_version_tuple_from_cmd(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/platform_info_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/system/platform_info_unittest.py
index 82d32d240ba..8acd17b2856 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/platform_info_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/platform_info_unittest.py
@@ -48,7 +48,8 @@ def fake_sys(platform_str='darwin', windows_version_tuple=None):
def fake_platform(mac_version_string='10.12.3',
release_string='bar',
- linux_version='trusty'):
+ linux_version='trusty',
+ win_version_string=None):
class FakePlatformModule(object):
def mac_ver(self):
return tuple([mac_version_string, tuple(['', '', '']), 'i386'])
@@ -62,6 +63,9 @@ def fake_platform(mac_version_string='10.12.3',
def release(self):
return release_string
+ def win32_ver(self):
+ return tuple([None, win_version_string])
+
return FakePlatformModule()
@@ -119,7 +123,8 @@ class TestPlatformInfo(unittest.TestCase):
self.assertFalse(info.is_win())
self.assertFalse(info.is_freebsd())
- info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])))
+ info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])),
+ fake_platform(win_version_string="6.1.7600"))
self.assertEqual(info.os_name, 'win')
self.assertFalse(info.is_linux())
self.assertFalse(info.is_mac())
@@ -182,33 +187,54 @@ class TestPlatformInfo(unittest.TestCase):
fake_platform('', '9.0-RELEASE')).os_version, '9.0-RELEASE')
with self.assertRaises(AssertionError):
- self.make_info(fake_sys('win32', tuple([5, 0, 1234])))
+ self.make_info(fake_sys('win32', tuple([5, 0, 1234])),
+ fake_platform(win_version_string="5.0.1234"))
with self.assertRaises(AssertionError):
- self.make_info(fake_sys('win32', tuple([6, 1, 1234])))
+ self.make_info(fake_sys('win32', tuple([6, 1, 1234])),
+ fake_platform(win_version_string="6.1.1234"))
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([10, 1, 1234]))).os_version,
+ self.make_info(
+ fake_sys('win32', tuple([10, 1, 1234])),
+ fake_platform(win_version_string="10.1.1234")).os_version,
'future')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([10, 0, 1234]))).os_version,
- '10')
+ self.make_info(
+ fake_sys('win32', tuple([10, 0, 1234])),
+ fake_platform(win_version_string="10.0.1234")).os_version,
+ '10.1909')
+ self.assertEqual(
+ self.make_info(
+ fake_sys('win32', tuple([10, 0, 19042])),
+ fake_platform(win_version_string="10.0.19042")).os_version,
+ '10.20h2')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([6, 3, 1234]))).os_version,
+ self.make_info(
+ fake_sys('win32', tuple([6, 3, 1234])),
+ fake_platform(win_version_string="6.3.1234")).os_version,
'8.1')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([6, 2, 1234]))).os_version,
- '8')
+ self.make_info(
+ fake_sys('win32', tuple([6, 2, 1234])),
+ fake_platform(win_version_string="6.2.1234")).os_version, '8')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([6, 1, 7601]))).os_version,
+ self.make_info(
+ fake_sys('win32', tuple([6, 1, 7601])),
+ fake_platform(win_version_string="6.1.7601")).os_version,
'7sp1')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([6, 1, 7600]))).os_version,
+ self.make_info(
+ fake_sys('win32', tuple([6, 1, 7600])),
+ fake_platform(win_version_string="6.1.7600")).os_version,
'7sp0')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([6, 0, 1234]))).os_version,
+ self.make_info(
+ fake_sys('win32', tuple([6, 0, 1234])),
+ fake_platform(win_version_string="6.0.1234")).os_version,
'vista')
self.assertEqual(
- self.make_info(fake_sys('win32', tuple([5, 1, 1234]))).os_version,
- 'xp')
+ self.make_info(
+ fake_sys('win32', tuple([5, 1, 1234])),
+ fake_platform(win_version_string="5.1.1234")).os_version, 'xp')
with self.assertRaises(AssertionError):
self.make_info(
@@ -241,7 +267,8 @@ class TestPlatformInfo(unittest.TestCase):
info = self.make_info(fake_sys('darwin'))
self.assertNotEquals(info.display_name(), '')
- info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])))
+ info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])),
+ fake_platform(win_version_string="6.1.7600"))
self.assertNotEquals(info.display_name(), '')
info = self.make_info(fake_sys('linux2'))
@@ -257,7 +284,8 @@ class TestPlatformInfo(unittest.TestCase):
executive=fake_executive('1234'))
self.assertEqual(info.total_bytes_memory(), 1234)
- info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])))
+ info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])),
+ fake_platform(win_version_string="6.1.7600"))
self.assertIsNone(info.total_bytes_memory())
info = self.make_info(fake_sys('linux2'))
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/system_host_mock.py b/chromium/third_party/blink/tools/blinkpy/common/system/system_host_mock.py
index b28baf5e2d4..cc983c0edb1 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/system_host_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/system_host_mock.py
@@ -26,13 +26,13 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from StringIO import StringIO
-
from blinkpy.common.system.executive_mock import MockExecutive
from blinkpy.common.system.filesystem_mock import MockFileSystem
from blinkpy.common.system.platform_info_mock import MockPlatformInfo
from blinkpy.common.system.user_mock import MockUser
+from six import StringIO
+
class MockSystemHost(object):
def __init__(self,
diff --git a/chromium/third_party/blink/tools/blinkpy/common/system/user_mock.py b/chromium/third_party/blink/tools/blinkpy/common/system/user_mock.py
index 53715f58477..db682ba7eeb 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/system/user_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/system/user_mock.py
@@ -41,14 +41,14 @@ class MockUser(object):
list_title,
list_items,
can_choose_multiple=False,
- raw_input=raw_input):
+ input_func=input):
pass
def __init__(self):
self.opened_urls = []
self._canned_responses = ['Mock user response']
- def prompt(self, message, repeat=1, raw_input=raw_input):
+ def prompt(self, message, repeat=1, input_func=input):
return self._canned_responses.pop(0)
def set_canned_responses(self, responses):
diff --git a/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index b9da9350066..771052d030d 100755
--- a/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -14,6 +14,8 @@ $ git ls-files third_party/blink \
| python third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
"""
+from __future__ import print_function
+
import os
import re
import sys
@@ -44,6 +46,7 @@ _CONFIG = [
'base::JobHandle',
'base::PostJob',
'base::File',
+ 'base::FileErrorOr',
'base::FilePath',
'base::GetUniqueIdForProcess',
"base::i18n::TextDirection",
@@ -197,11 +200,13 @@ _CONFIG = [
# //base/numerics/clamped_math.h.
'base::ClampAdd',
+ 'base::ClampedNumeric',
+ 'base::ClampMax',
'base::ClampSub',
'base::MakeClampedNum',
- # //base/numerics/ranges.h.
- "base::ClampToRange",
+ # //base/cxx17_backports.h.
+ "base::clamp",
# //base/strings/strcat.h.
'base::StrCat',
@@ -271,6 +276,7 @@ _CONFIG = [
'cc::PaintWorkletInput',
'cc::NodeId',
'cc::NodeInfo',
+ 'cc::UsePaintCache',
# Chromium geometry types.
'gfx::Insets',
@@ -283,6 +289,7 @@ _CONFIG = [
'gfx::RectF',
'gfx::RRectF',
'gfx::ScaleToCeiledSize',
+ 'gfx::ScaleToEnclosingRectSafe',
'gfx::ScaleVector2d',
'gfx::Size',
'gfx::SizeF',
@@ -346,6 +353,7 @@ _CONFIG = [
# UMA Enums
'cc::PaintHoldingCommitTrigger',
+ 'cc::PaintHoldingReason',
# Scrolling
'cc::kManipulationInfoPinchZoom',
@@ -384,6 +392,10 @@ _CONFIG = [
# base/types/strong_alias.h
'base::StrongAlias',
+ # Common display structs across display <-> Blink.
+ 'display::ScreenInfo',
+ 'display::ScreenInfos',
+
# Standalone utility libraries that only depend on //base
'skia::.+',
'url::.+',
@@ -499,6 +511,12 @@ _CONFIG = [
# UI Cursor
'ui::Cursor',
+ # UI Pointer and Hover
+ 'ui::PointerType',
+ 'ui::POINTER_TYPE_.*',
+ 'ui::HoverType',
+ 'ui::HOVER_TYPE_.*',
+
# UI Keyconverter
'ui::DomCode',
'ui::DomKey',
@@ -512,6 +530,8 @@ _CONFIG = [
'ui::AXMode',
'ui::AXNodeData',
'ui::AXTreeID',
+ 'ui::kAXModeBasic',
+ 'ui::kAXModeComplete',
'ax::mojom::BoolAttribute',
'ax::mojom::HasPopup',
'ax::mojom::State',
@@ -524,8 +544,11 @@ _CONFIG = [
'ui::IsContainerWithSelectableChildren',
'ui::IsDialog',
'ui::IsHeading',
+ 'ui::IsLandmark',
'ui::IsPlatformDocument',
'ui::IsPresentational',
+ 'ui::IsSelectRequiredOrImplicit',
+ 'ui::IsStructure',
'ui::IsTableLike',
'ui::IsTableRow',
'ui::IsTableHeader',
@@ -896,6 +919,28 @@ _CONFIG = [
],
},
{
+ 'paths': [
+ 'third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc',
+ 'third_party/blink/renderer/bindings/core/v8/v8_code_cache.h',
+ 'third_party/blink/renderer/core/loader/document_loader.cc',
+ 'third_party/blink/renderer/core/loader/document_loader.h',
+ 'third_party/blink/renderer/core/workers/worker_global_scope.cc',
+ 'third_party/blink/renderer/core/workers/worker_global_scope.h',
+ 'third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h',
+ 'third_party/blink/renderer/core/execution_context/execution_context.h',
+ 'third_party/blink/renderer/core/execution_context/execution_context.cc',
+ 'third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h',
+ 'third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc',
+ 'third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc',
+ ],
+ 'allowed': [
+ # TODO(mythria): Allow use of non-blink mojo interface. Once
+ # //content/renderer/loader is moved to Blink as a part of onion
+ # soup we can update all uses to blink::mojom::blink::CodeCacheHost.
+ 'blink::mojom::CodeCacheHost',
+ ],
+ },
+ {
'paths': ['third_party/blink/renderer/core/xml'],
'allowed': [
'xpathyy::.+',
@@ -926,10 +971,13 @@ _CONFIG = [
'allowed': [
'base::MRUCache',
'gl::GpuPreference',
+ 'gpu::SHARED_IMAGE_USAGE_.+',
'gpu::gles2::GLES2Interface',
'gpu::raster::RasterInterface',
'gpu::Mailbox',
'gpu::MailboxHolder',
+ 'gpu::SyncToken',
+ 'gpu::webgpu::ReservedTexture',
'display::Display',
'media::IsOpaque',
'media::kNoTransformation',
@@ -938,8 +986,18 @@ _CONFIG = [
'media::VideoFrame',
'viz::RasterContextProvider',
'viz::ReleaseCallback',
- 'viz::TransferableResource',
+ 'viz::ResourceFormat',
'viz::ResourceFormatToClosestSkColorType',
+ 'viz::TransferableResource',
+ ],
+ },
+ {
+ 'paths': [
+ 'third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc',
+ ],
+ # This class needs access to a GPU driver bug workaround entry.
+ 'allowed': [
+ 'gpu::ENABLE_WEBGL_TIMER_QUERY_EXTENSIONS',
],
},
{
@@ -978,7 +1036,9 @@ _CONFIG = [
'third_party/blink/renderer/modules/mediasource/',
],
'allowed': [
+ 'base::CommandLine',
'media::.+',
+ 'switches::kLacrosEnablePlatformEncryptedHevc',
]
},
{
@@ -1042,6 +1102,7 @@ _CONFIG = [
'gpu::MailboxHolder',
'media::.+',
'libyuv::.+',
+ 'viz::SkColorTypeToResourceFormat',
]
},
{
@@ -1248,6 +1309,9 @@ _CONFIG = [
# The liburlpattern API requires using std::vector.
'std::vector',
+
+ # Internal namespace used by url_pattern module.
+ 'url_pattern::.+',
],
},
{
@@ -1266,7 +1330,7 @@ _CONFIG = [
'paths': [
'third_party/blink/renderer/core/layout/layout_theme.cc',
'third_party/blink/renderer/core/layout/layout_theme_mac.mm',
- 'third_party/blink/renderer/core/paint/object_painter_base.cc',
+ 'third_party/blink/renderer/core/paint/outline_painter.cc',
'third_party/blink/renderer/core/paint/theme_painter.cc',
'third_party/blink/renderer/core/paint/theme_painter_default.cc',
],
@@ -1274,14 +1338,6 @@ _CONFIG = [
},
{
'paths': [
- 'third_party/blink/renderer/core/css/counter_style.cc',
- 'third_party/blink/renderer/core/layout/',
- 'third_party/blink/renderer/core/paint/',
- ],
- 'allowed': ['list_marker_text::.+'],
- },
- {
- 'paths': [
'third_party/blink/renderer/modules/crypto/',
],
'allowed': ['crypto::.+'],
@@ -1402,8 +1458,8 @@ _CONFIG = [
},
{
'paths': [
- 'third_party/blink/renderer/core/frame/local_frame.cc',
- 'third_party/blink/renderer/core/frame/local_frame.h'
+ 'third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc',
+ 'third_party/blink/renderer/core/frame/local_frame_mojo_handler.h'
],
'allowed': ['base::Value'],
},
@@ -1432,7 +1488,7 @@ _CONFIG = [
'third_party/blink/renderer/platform/graphics/document_transition_shared_element_id.h'
],
'allowed': ['cc::DocumentTransitionSharedElementId'],
- }
+ },
]
@@ -1601,11 +1657,11 @@ def main():
path,
[(i + 1, l) for i, l in enumerate(contents.splitlines())])
if disallowed_identifiers:
- print '%s uses disallowed identifiers:' % path
+ print('%s uses disallowed identifiers:' % path)
for i in disallowed_identifiers:
print(i.line, i.identifier, i.advice)
except IOError as e:
- print 'could not open %s: %s' % (path, e)
+ print('could not open %s: %s' % (path, e))
if __name__ == '__main__':
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checker_unittest.py b/chromium/third_party/blink/tools/blinkpy/style/checker_unittest.py
index fc987c91980..616f77c981b 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checker_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checker_unittest.py
@@ -215,7 +215,7 @@ class GlobalVariablesTest(unittest.TestCase):
def test_max_reports_per_category(self):
"""Check that _MAX_REPORTS_PER_CATEGORY is valid."""
all_categories = self._all_categories()
- for category in _MAX_REPORTS_PER_CATEGORY.iterkeys():
+ for category in _MAX_REPORTS_PER_CATEGORY.keys():
self.assertIn(category, all_categories,
'Key "%s" is not a category' % category)
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py
index 66188656d95..fd61efa6e1d 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py
@@ -39,12 +39,17 @@ import math # for log
import os
import os.path
import re
+import six
import sre_compile
import unicodedata
from blinkpy.common.memoized import memoized
from blinkpy.common.system.filesystem import FileSystem
+from functools import total_ordering
+
+xrange = six.moves.xrange
+
# Headers that we consider STL headers.
_STL_HEADERS = frozenset([
'algobase.h',
@@ -357,6 +362,7 @@ class _IncludeState(dict):
return self._visited_primary_section
+@total_ordering
class Position(object):
"""Holds the position of something."""
@@ -370,6 +376,12 @@ class Position(object):
def __cmp__(self, other):
return self.row.__cmp__(other.row) or self.column.__cmp__(other.column)
+ def __eq__(self, other):
+ return (self.row, self.column) == (other.row, other.column)
+
+ def __gt__(self, other):
+ return (self.row, self.column) > (other.row, other.column)
+
class SingleLineView(object):
"""Converts multiple lines into a single line (with line breaks replaced by a
@@ -1563,7 +1575,7 @@ def get_line_width(line):
The width of the line in column positions, accounting for Unicode
combining characters and wide characters.
"""
- if isinstance(line, unicode):
+ if isinstance(line, six.text_type):
width = 0
for c in unicodedata.normalize('NFC', line):
if unicodedata.east_asian_width(c) in ('W', 'F'):
@@ -2593,7 +2605,7 @@ def check_for_include_what_you_use(filename, clean_lines, include_state,
# include_state is modified during iteration, so we iterate over a copy of
# the keys.
- for header in include_state.keys(): # NOLINT
+ for header in list(include_state): # NOLINT
(same_module, common_path) = files_belong_to_same_module(
abs_filename, header)
fullpath = common_path + header
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
index 682dda9d0d1..eb535d4d143 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
@@ -266,7 +266,7 @@ class CppStyleTestBase(unittest.TestCase):
tuple_position: a tuple (row, column) to compare against.
"""
self.assertEqual(
- position, cpp_style.Position(tuple_position[0], tuple_position[1]),
+ (position.row, position.column), tuple_position,
'position %s, tuple_position %s' % (position, tuple_position))
@@ -1360,10 +1360,9 @@ class CppStyleTest(CppStyleTestBase):
def test_invalid_utf8(self):
def do_test(self, raw_bytes, has_invalid_utf8):
error_collector = ErrorCollector(self.assertTrue)
- self.process_file_data(
- 'foo.cpp', 'cpp',
- unicode(raw_bytes, 'utf8', 'replace').split('\n'),
- error_collector)
+ unicode_string = raw_bytes.decode('utf8', 'replace').split('\n')
+ self.process_file_data('foo.cpp', 'cpp', unicode_string,
+ error_collector)
# The warning appears only once.
self.assertEqual(
int(has_invalid_utf8),
@@ -1372,12 +1371,12 @@ class CppStyleTest(CppStyleTestBase):
' (or Unicode replacement character).'
' [readability/utf8] [5]'))
- do_test(self, 'Hello world\n', False)
- do_test(self, '\xe9\x8e\xbd\n', False)
- do_test(self, '\xe9x\x8e\xbd\n', True)
+ do_test(self, b'Hello world\n', False)
+ do_test(self, b'\xe9\x8e\xbd\n', False)
+ do_test(self, b'\xe9x\x8e\xbd\n', True)
# This is the encoding of the replacement character itself (which
# you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')).
- do_test(self, '\xef\xbf\xbd\n', True)
+ do_test(self, b'\xef\xbf\xbd\n', True)
def test_is_blank_line(self):
self.assertTrue(cpp_style.is_blank_line(''))
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker.py
index 056866cbc67..41dccabb907 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker.py
@@ -41,6 +41,8 @@ class JSONChecker(object):
self._handle_style_error(
self.line_number_from_json_exception(error), 'json/syntax', 5,
str(error))
+ except json.JSONDecodeError as error:
+ self._handle_style_error(error.lineno, 'json/syntax', 5, error.msg)
@staticmethod
def line_number_from_json_exception(error):
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker_unittest.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker_unittest.py
index 9aa8a56cf55..15ca66f6ede 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/jsonchecker_unittest.py
@@ -21,6 +21,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Unit test for jsonchecker.py."""
+import six
import unittest
from blinkpy.style.checkers import jsonchecker
@@ -87,7 +88,13 @@ class JSONCheckerTest(unittest.TestCase):
pass
def test_conflict_marker(self):
- self.assert_error(0, 'json/syntax', '<<<<<<< HEAD\n{\n}\n')
+
+ # In python 3, this error line number is 1
+ expected_line = 1
+ if six.PY2:
+ expected_line = 0
+
+ self.assert_error(expected_line, 'json/syntax', '<<<<<<< HEAD\n{\n}\n')
def test_single_quote(self):
self.assert_error(2, 'json/syntax', "{\n'slaves': []\n}\n")
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/png_unittest.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/png_unittest.py
index d4b779716c0..8a0c4c90321 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/png_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/png_unittest.py
@@ -54,7 +54,7 @@ class PNGCheckerTest(unittest.TestCase):
fs = MockFileSystem()
file_path = "foo.png"
- fs.write_binary_file(file_path, "Dummy binary data")
+ fs.write_binary_file(file_path, b"Dummy binary data")
errors = []
checker = PNGChecker(file_path, mock_handle_style_error,
MockSystemHost(os_name='linux', filesystem=fs))
@@ -62,7 +62,7 @@ class PNGCheckerTest(unittest.TestCase):
self.assertEqual(len(errors), 0)
file_path = "foo-expected.png"
- fs.write_binary_file(file_path, "Dummy binary data")
+ fs.write_binary_file(file_path, b"Dummy binary data")
errors = []
checker = PNGChecker(file_path, mock_handle_style_error,
MockSystemHost(os_name='linux', filesystem=fs))
diff --git a/chromium/third_party/blink/tools/blinkpy/style/filter.py b/chromium/third_party/blink/tools/blinkpy/style/filter.py
index f1e62da945d..46c6f2aacf8 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/filter.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/filter.py
@@ -192,7 +192,7 @@ class FilterConfiguration(object):
if self._path_specific_lower is None:
self._path_specific_lower = []
for (sub_paths, path_rules) in self._path_specific:
- sub_paths = map(str.lower, sub_paths)
+ sub_paths = list(map(str.lower, sub_paths))
self._path_specific_lower.append((sub_paths, path_rules))
return self._path_specific_lower
diff --git a/chromium/third_party/blink/tools/blinkpy/style/patchreader.py b/chromium/third_party/blink/tools/blinkpy/style/patchreader.py
index 434f6dcc3c4..56011d8d70c 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/patchreader.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/patchreader.py
@@ -50,7 +50,7 @@ class PatchReader(object):
"""Checks style in the given patch."""
patch_files = DiffParser(patch_string.splitlines()).files
- for path, diff_file in patch_files.iteritems():
+ for path, diff_file in patch_files.items():
line_numbers = diff_file.added_or_modified_line_numbers()
_log.debug('Found %s new or modified lines in: %s',
len(line_numbers), path)
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/analyze_baselines.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/analyze_baselines.py
index 96d069b7ab3..1bd906965b2 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/analyze_baselines.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/analyze_baselines.py
@@ -26,6 +26,8 @@
# (INCLUDING NEGLIGENCE OR/ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from __future__ import print_function
+
import logging
import optparse
@@ -56,7 +58,7 @@ class AnalyzeBaselines(AbstractRebaseliningCommand):
self._tool = None
def _write(self, msg):
- print msg
+ print(msg)
def _analyze_baseline(self, options, test_name):
# TODO(robertma): Investigate changing the CLI to take extensions with leading '.'.
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py
index 65546801da0..0670d88179c 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py
@@ -26,6 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from __future__ import print_function
+
import logging
from blinkpy.web_tests.layout_package.bot_test_expectations import BotTestExpectationsFactory
@@ -121,5 +123,5 @@ class FlakyTests(Command):
','.join(test_names)
expectations_string = '\n'.join(line.to_string() for line in lines)
- print self.OUTPUT % (self.HEADER, expectations_string,
- flakiness_dashboard_url)
+ print(self.OUTPUT %
+ (self.HEADER, expectations_string, flakiness_dashboard_url))
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/help_command.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/help_command.py
index c711e756544..b14a7c4263f 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/help_command.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/help_command.py
@@ -26,6 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from __future__ import print_function
+
import optparse
from blinkpy.tool.commands.command import Command
@@ -83,7 +85,7 @@ class HelpCommand(Command):
if args:
command = self._tool.command_by_name(args[0])
if command:
- print command.standalone_help()
+ print(command.standalone_help())
return 0
self.show_all_commands = options.show_all_commands
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/queries.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/queries.py
index 465099ebfe0..671bde9f392 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/queries.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/queries.py
@@ -28,6 +28,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from __future__ import print_function
+
import fnmatch
import re
@@ -53,7 +55,7 @@ and PID and prints it to stdout."""
pid = None
if len(args) > 1:
pid = int(args[1])
- print crash_logs.find_newest_log(args[0], pid)
+ print(crash_logs.find_newest_log(args[0], pid))
class PrintExpectations(Command):
@@ -103,7 +105,7 @@ class PrintExpectations(Command):
def execute(self, options, args, tool):
if not options.paths and not args and not options.all:
- print 'You must either specify one or more test paths or --all.'
+ print('You must either specify one or more test paths or --all.')
return
if options.platform:
@@ -114,7 +116,7 @@ class PrintExpectations(Command):
if default_port:
port_names = [default_port.name()]
else:
- print "No port names match '%s'" % options.platform
+ print("No port names match '%s'" % options.platform)
return
else:
default_port = tool.port_factory.get(port_names[0])
@@ -123,13 +125,13 @@ class PrintExpectations(Command):
port_names = [default_port.name()]
if options.paths:
- files = default_port.expectations_files()
+ files = default_port.default_expectations_files()
web_tests_dir = default_port.web_tests_dir()
for file in files:
if file.startswith(web_tests_dir):
file = file.replace(web_tests_dir,
WEB_TESTS_LAST_COMPONENT)
- print file
+ print(file)
return
tests = set(default_port.tests(args))
@@ -143,8 +145,8 @@ class PrintExpectations(Command):
for test in sorted(tests_to_print)
]
if port_name != port_names[0]:
- print
- print '\n'.join(self._format_lines(options, port_name, lines))
+ print('')
+ print('\n'.join(self._format_lines(options, port_name, lines)))
@staticmethod
def _test_set_for_keyword(keyword, test_expectations, tests):
@@ -220,7 +222,7 @@ class PrintBaselines(Command):
def execute(self, options, args, tool):
if not args and not options.all:
- print 'You must either specify one or more test paths or --all.'
+ print('You must either specify one or more test paths or --all.')
return
default_port = tool.port_factory.get()
@@ -228,7 +230,7 @@ class PrintBaselines(Command):
port_names = fnmatch.filter(tool.port_factory.all_port_names(),
options.platform)
if not port_names:
- print "No port names match '%s'" % options.platform
+ print("No port names match '%s'" % options.platform)
else:
port_names = [default_port.name()]
@@ -239,9 +241,9 @@ class PrintBaselines(Command):
for port_name in port_names:
if port_name != port_names[0]:
- print
+ print('')
if not options.csv:
- print '// For %s' % port_name
+ print('// For %s' % port_name)
port = tool.port_factory.get(port_name)
for test_name in tests:
self._print_baselines(
@@ -253,13 +255,13 @@ class PrintBaselines(Command):
baseline_location = baselines[extension]
if baseline_location:
if options.csv:
- print '%s,%s,%s,%s,%s,%s' % (
- port_name, test_name,
- self._platform_for_path(test_name), extension[1:],
- baseline_location,
- self._platform_for_path(baseline_location))
+ print('%s,%s,%s,%s,%s,%s' %
+ (port_name, test_name,
+ self._platform_for_path(test_name), extension[1:],
+ baseline_location,
+ self._platform_for_path(baseline_location)))
else:
- print baseline_location
+ print(baseline_location)
def _platform_for_path(self, relpath):
platform_matchobj = self._platform_regexp.match(relpath)
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
index d7c61586bbd..93bbc365037 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -315,7 +315,6 @@ class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
builders_to_fallback_paths[builder] = fallback_path
else:
wpt_builders.add(builder)
-
return set(builders_to_fallback_paths) | wpt_builders
def _rebaseline_commands(self, test_baseline_set, options):
@@ -380,6 +379,7 @@ class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
args.extend(['--build-number', str(build.build_number)])
if options.results_directory:
args.extend(['--results-directory', options.results_directory])
+
if (options.flag_specific
and self._tool.builders.is_flag_specific_builder(
build.builder_name)):
@@ -526,6 +526,7 @@ class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
)
return
+ # TODO: Consider optimizing here, it takes about 2 minutes for 500 tests
for test in sorted({t for t, _, _ in test_baseline_set}):
_log.info('Rebaselining %s', test)
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
index dee36c2e017..801194df6ef 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
@@ -186,7 +186,10 @@ class RebaselineCL(AbstractParallelRebaselineCommand):
if options.fill_missing:
self.fill_in_missing_results(test_baseline_set)
- _log.debug('Rebaselining: %s', test_baseline_set)
+ for builder in test_baseline_set.all_builders():
+ if self._tool.builders.is_flag_specific_builder(builder):
+ options.flag_specific = self._tool.builders.flag_specific_option(
+ builder)
if not options.dry_run:
self.rebaseline(options, test_baseline_set)
@@ -287,17 +290,12 @@ class RebaselineCL(AbstractParallelRebaselineCommand):
results = {}
for build, status in jobs.iteritems():
- # TODO(crbug.com/1178099): highdpi builder status is always
- # ('COMPLETED', 'SUCCESS') since it is experimental.
- # Remove the special case once it is stabilized.
- if (status == TryJobStatus('COMPLETED', 'SUCCESS')
- and 'optional-highdpi' not in build.builder_name):
+ if status == TryJobStatus('COMPLETED', 'SUCCESS'):
# Builds with passing try jobs are mapped to None, to indicate
# that there are no baselines to download.
results[build] = None
continue
- if (status != TryJobStatus('COMPLETED', 'FAILURE')
- and 'optional-highdpi' not in build.builder_name):
+ if status != TryJobStatus('COMPLETED', 'FAILURE'):
# Only completed failed builds will contain actual failed
# web tests to download baselines for.
continue
diff --git a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
index 81527eb8053..dce73a624a1 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
@@ -129,7 +129,7 @@ class BaseTestCase(unittest.TestCase):
def _zero_out_test_expectations(self):
for port_name in self.tool.port_factory.all_port_names():
port = self.tool.port_factory.get(port_name)
- for path in port.expectations_files():
+ for path in port.default_expectations_files():
self._write(path, '')
self.tool.filesystem.written_files = {}
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py b/chromium/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py
index a5400cd952d..81b3e698135 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py
@@ -144,7 +144,7 @@ class AndroidWPTExpectationsUpdaterTest(LoggingTestCase):
'\n'
'# Add untriaged failures in this block\n'
'crbug.com/1050754 external/wpt/bar.html [ Failure ]\n'
- 'crbug.com/1050754 external/wpt/new3.html [ Failure Crash ]\n'
+ 'crbug.com/1050754 external/wpt/new3.html [ Crash Failure ]\n'
'\n'
'# This comment will not be deleted\n')
self.assertEqual(content, _new_expectations)
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/gerrit.py b/chromium/third_party/blink/tools/blinkpy/w3c/gerrit.py
index f7ebf5ffe79..5e76be3e980 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/gerrit.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/gerrit.py
@@ -5,7 +5,7 @@
import base64
import json
import logging
-from urllib2 import HTTPError
+from six.moves.urllib.error import HTTPError
from blinkpy.common.net.network_transaction import NetworkTimeout
from blinkpy.w3c.chromium_commit import ChromiumCommit
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py
index c6dab87c86f..bf93eda0fc4 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -40,7 +40,7 @@ TIMEOUT_SECONDS = 210 * 60
# Sheriff calendar URL, used for getting the ecosystem infra sheriff to cc.
ROTATIONS_URL = 'https://chrome-ops-rotation-proxy.appspot.com/current/grotation:chrome-ecosystem-infra'
-SHERIFF_EMAIL_FALLBACK = 'smcgruer@google.com'
+SHERIFF_EMAIL_FALLBACK = 'weizhong@google.com'
RUBBER_STAMPER_BOT = 'rubber-stamper@appspot.gserviceaccount.com'
_log = logging.getLogger(__file__)
@@ -75,14 +75,8 @@ class TestImporter(object):
self.new_override_expectations = {}
self.verbose = False
- args = [
- '--clean-up-affected-tests-only',
- '--clean-up-test-expectations',
- # TODO(crbug.com/1196713): Result download needs to migrate away
- # from test-results.appspot.com before we can resume using
- # results from CQ builders.
- '--rebaseline-blink-try-bots-only'
- ]
+ args = ['--clean-up-affected-tests-only',
+ '--clean-up-test-expectations']
self._expectations_updater = WPTExpectationsUpdater(
self.host, args, wpt_manifests)
@@ -192,7 +186,7 @@ class TestImporter(object):
_log.info('Only manifest was updated; skipping the import.')
return 0
- with self._expectations_updater.prepare_smoke_tests():
+ with self._expectations_updater.prepare_smoke_tests(self.chromium_git):
self._commit_changes(commit_message)
_log.info('Changes imported and committed.')
@@ -287,23 +281,33 @@ class TestImporter(object):
self.git_cl.run(['set-close'])
return False
- _log.info(
- 'CQ appears to have passed; sending to the rubber-stamper bot for '
- 'CR+1 and commit.')
- _log.info(
- 'If the rubber-stamper bot rejects the CL, you either need to '
- 'modify the benign file patterns, or manually CR+1 and land the '
- 'import yourself if it touches code files. See https://chromium.'
- 'googlesource.com/infra/infra/+/refs/heads/main/go/src/infra/'
- 'appengine/rubber-stamper/README.md')
-
# `--send-mail` is required to take the CL out of WIP mode.
- self.git_cl.run([
- 'upload', '-f', '--send-mail', '--enable-auto-submit',
- '--reviewers', RUBBER_STAMPER_BOT
- ])
-
- if self.git_cl.wait_for_closed_status():
+ if self._need_sheriff_attention():
+ _log.info(
+ 'CQ appears to have passed; sending to the sheriff for '
+ 'CR+1 and commit. The sheriff has one hour to respond.')
+ self.git_cl.run([
+ 'upload', '-f', '--send-mail', '--enable-auto-submit'
+ '--reviewers', self.sheriff_email()
+ ])
+ timeout = 3600
+ else:
+ _log.info(
+ 'CQ appears to have passed; sending to the rubber-stamper bot for '
+ 'CR+1 and commit.')
+ _log.info(
+ 'If the rubber-stamper bot rejects the CL, you either need to '
+ 'modify the benign file patterns, or manually CR+1 and land the '
+ 'import yourself if it touches code files. See https://chromium.'
+ 'googlesource.com/infra/infra/+/refs/heads/main/go/src/infra/'
+ 'appengine/rubber-stamper/README.md')
+ self.git_cl.run([
+ 'upload', '-f', '--send-mail', '--enable-auto-submit',
+ '--reviewers', RUBBER_STAMPER_BOT
+ ])
+ timeout = 1800
+
+ if self.git_cl.wait_for_closed_status(timeout_seconds=timeout):
_log.info('Update completed.')
return True
@@ -469,6 +473,17 @@ class TestImporter(object):
self.finder.chromium_base())
return changed_files == [wpt_base_manifest]
+ def _need_sheriff_attention(self):
+ # Per the rules defined for the rubber-stamper, it can not auto approve
+ # a CL that has .bat, .sh or .py files. Request the sheriff on rotation
+ # to approve the CL.
+ changed_files = self.chromium_git.changed_files()
+ for cf in changed_files:
+ extension = self.fs.splitext(cf)[1]
+ if extension in ['.bat', '.sh', '.py']:
+ return True
+ return False
+
def _commit_message(self,
chromium_commit_sha,
import_commit_sha,
@@ -527,7 +542,7 @@ class TestImporter(object):
self.fs.remove(dest)
def _upload_patchset(self, message):
- self.git_cl.run(['upload', '-f', '-t', message])
+ self.git_cl.run(['upload', '--bypass-hooks', '-f', '-t', message])
def _upload_cl(self):
_log.info('Uploading change list.')
@@ -541,11 +556,10 @@ class TestImporter(object):
self.git_cl.run([
'upload',
+ '--bypass-hooks',
'-f',
'--message-file',
- temp_path,
- '--cc',
- sheriff_email,
+ temp_path
])
self.fs.remove(temp_path)
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
index e62539eb11f..92f2e80e0cc 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import print_function
+
import json
import unittest
@@ -199,7 +201,8 @@ class TestImporterTest(LoggingTestCase):
Build('cq-builder-a', 123): TryJobStatus(
'COMPLETED', 'SUCCESS'),
})
- importer.git_cl.wait_for_closed_status = lambda: False
+ importer._need_sheriff_attention = lambda: False
+ importer.git_cl.wait_for_closed_status = lambda timeout_seconds: False
success = importer.run_commit_queue_for_cl()
self.assertFalse(success)
self.assertLog([
@@ -287,7 +290,8 @@ class TestImporterTest(LoggingTestCase):
Build('cq-builder-a', 123): TryJobStatus(
'COMPLETED', 'SUCCESS')
})
- importer.git_cl.wait_for_closed_status = lambda: False
+ importer._need_sheriff_attention = lambda: False
+ importer.git_cl.wait_for_closed_status = lambda timeout_seconds: False
success = importer.run_commit_queue_for_cl()
# Since the CL is already merged, we absorb the error and treat it as success.
self.assertTrue(success)
@@ -430,7 +434,7 @@ class TestImporterTest(LoggingTestCase):
'No-Export: true\n'
'Cq-Include-Trybots: luci.chromium.try:linux-wpt-identity-fyi-rel,'
'linux-wpt-input-fyi-rel')
- print host.executive.calls
+ print(host.executive.calls)
self.assertEqual(host.executive.calls,
[MANIFEST_INSTALL_CMD] +
[['git', 'log', '-1', '--format=%B']])
@@ -540,6 +544,32 @@ class TestImporterTest(LoggingTestCase):
RELATIVE_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME]
self.assertTrue(importer._only_wpt_manifest_changed())
+ def test_need_sheriff_attention(self):
+ host = self.mock_host()
+ importer = self._get_test_importer(host)
+ importer.chromium_git.changed_files = lambda: [
+ RELATIVE_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME,
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/x.html']
+ self.assertFalse(importer._need_sheriff_attention())
+
+ importer.chromium_git.changed_files = lambda: [
+ RELATIVE_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME,
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/x.html',
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/y.sh']
+ self.assertTrue(importer._need_sheriff_attention())
+
+ importer.chromium_git.changed_files = lambda: [
+ RELATIVE_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME,
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/x.html',
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/y.py']
+ self.assertTrue(importer._need_sheriff_attention())
+
+ importer.chromium_git.changed_files = lambda: [
+ RELATIVE_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME,
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/x.html',
+ RELATIVE_WEB_TESTS + 'external/wpt/foo/y.bat']
+ self.assertTrue(importer._need_sheriff_attention())
+
# TODO(crbug.com/800570): Fix orphan baseline finding in the presence of
# variant tests.
@unittest.skip('Finding orphaned baselines is broken')
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
index 02a6990a8b3..fceb45f40c9 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
@@ -151,12 +151,6 @@ class WPTExpectationsUpdater(object):
help='Adds Pass to tests with failure expectations. '
'This command line argument can be used to mark tests '
'as flaky.')
- parser.add_argument(
- '--rebaseline-blink-try-bots-only',
- action='store_true',
- help='When set, only rebaselines using the results from blink-rel '
- 'trybots, and ignores CQ bots. By default, both CQ and blink '
- 'bots are used.')
def update_expectations(self):
"""Downloads text new baselines and adds test expectations lines.
@@ -483,9 +477,10 @@ class WPTExpectationsUpdater(object):
merged_dict[tuple([current_key])] = dictionary[current_key]
keys.remove(current_key)
break
-
+ current_result_set = set(dictionary[current_key].actual.split())
for next_item in keys[1:]:
- if dictionary[current_key] == dictionary[next_item]:
+ if (current_result_set ==
+ set(dictionary[next_item].actual.split())):
found_match = True
matching_value_keys.update([current_key, next_item])
@@ -786,7 +781,7 @@ class WPTExpectationsUpdater(object):
return line_dict
@contextlib.contextmanager
- def prepare_smoke_tests(self):
+ def prepare_smoke_tests(self, chromium_git):
"""List test cases that should be run by the smoke test builder
Add new and modified test cases to WPT_SMOKE_TESTS_FILE,
@@ -824,6 +819,7 @@ class WPTExpectationsUpdater(object):
finally:
_log.info('Restore file WPTSmokeTestCases.')
shutil.copyfile(self._saved_test_cases_file, WPT_SMOKE_TESTS_FILE)
+ chromium_git.commit_locally_with_message('Restore WPTSmokeTestCases')
def cleanup_test_expectations_files(self):
"""Removes deleted tests from expectations files.
@@ -1013,17 +1009,18 @@ class WPTExpectationsUpdater(object):
'python',
blink_tool,
'rebaseline-cl',
- '--verbose',
'--no-trigger-jobs',
'--fill-missing',
]
- if self.options.rebaseline_blink_try_bots_only:
- command.append('--use-blink-try-bots-only')
-
+ if self.options.verbose:
+ command.append('--verbose')
if self.patchset:
command.append('--patchset=' + str(self.patchset))
command += tests_to_rebaseline
- self.host.executive.run_command(command)
+ rebaseline_output = self.host.executive.run_command(command)
+ _log.info(
+ "Output of rebaseline-cl:\n%s\n--end of rebaseline-cl output --" %
+ rebaseline_output)
return tests_to_rebaseline, test_results
def get_tests_to_rebaseline(self, test_results):
@@ -1076,11 +1073,5 @@ class WPTExpectationsUpdater(object):
@memoized
def _get_try_bots(self):
- builder_set = frozenset(
- self.host.builders.filter_builders(is_try=True,
- exclude_specifiers={'android'}))
- # Omit the CQ bots if we are only using data from blink trybots.
- if self.options.rebaseline_blink_try_bots_only:
- builder_set -= frozenset(
- self.host.builders.all_cq_try_builder_names())
- return list(builder_set)
+ return self.host.builders.filter_builders(
+ is_try=True, exclude_specifiers={'android'})
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py
index 9e968ab4ae9..b95556e4619 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py
@@ -348,44 +348,36 @@ class WPTExpectationsUpdaterTest(LoggingTestCase):
updater = WPTExpectationsUpdater(self.mock_host())
self.assertEqual(
updater.merge_same_valued_keys({
- 'one': {
- 'expected': 'FAIL',
- 'actual': 'PASS'
- },
- 'two': {
- 'expected': 'FAIL',
- 'actual': 'PASS'
- },
- }), {('two', 'one'): {
- 'expected': 'FAIL',
- 'actual': 'PASS'
- }})
+ 'one': SimpleTestResult(actual='FAIL TIMEOUT',
+ expected='FAIL',
+ bug=''),
+ 'two': SimpleTestResult(actual='TIMEOUT FAIL',
+ expected='TIMEOUT',
+ bug='')
+ }), {('two', 'one'): SimpleTestResult(actual='FAIL TIMEOUT',
+ expected='FAIL',
+ bug='')})
def test_merge_same_valued_keys_one_mismatch(self):
updater = WPTExpectationsUpdater(self.mock_host())
self.assertEqual(
updater.merge_same_valued_keys({
- 'one': {
- 'expected': 'FAIL',
- 'actual': 'PASS'
- },
- 'two': {
- 'expected': 'FAIL',
- 'actual': 'TIMEOUT'
- },
- 'three': {
- 'expected': 'FAIL',
- 'actual': 'PASS'
- },
+ 'one': SimpleTestResult(actual='FAIL TIMEOUT',
+ expected='FAIL',
+ bug=''),
+ 'two': SimpleTestResult(actual='TIMEOUT FAIL',
+ expected='TIMEOUT',
+ bug=''),
+ 'three': SimpleTestResult(actual='TIMEOUT',
+ expected='FAIL',
+ bug='')
}), {
- ('three', 'one'): {
- 'expected': 'FAIL',
- 'actual': 'PASS'
- },
- ('two',): {
- 'expected': 'FAIL',
- 'actual': 'TIMEOUT'
- },
+ ('two', 'one'): SimpleTestResult(actual='FAIL TIMEOUT',
+ expected='FAIL',
+ bug=''),
+ ('three',): SimpleTestResult(actual='TIMEOUT',
+ expected='FAIL',
+ bug='')
})
def test_get_expectations(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py
index 7e5674b518c..e11747ca7c7 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py
@@ -7,8 +7,10 @@ import datetime
import json
import logging
import re
-import urllib2
+
from collections import namedtuple
+from six.moves.urllib.error import HTTPError
+from six.moves.urllib.parse import quote
from blinkpy.common.memoized import memoized
from blinkpy.w3c.common import WPT_GH_ORG, WPT_GH_REPO_NAME, EXPORT_PR_LABEL
@@ -128,7 +130,7 @@ class WPTGitHub(object):
}
try:
response = self.request(path, method='POST', body=body)
- except urllib2.HTTPError as e:
+ except HTTPError as e:
_log.error(e.reason)
if e.code == 422:
_log.error('Please check if branch already exists; If so, '
@@ -185,7 +187,7 @@ class WPTGitHub(object):
WPT_GH_ORG,
WPT_GH_REPO_NAME,
number,
- urllib2.quote(label),
+ quote(label),
)
response = self.request(path, method='DELETE')
@@ -373,7 +375,7 @@ class WPTGitHub(object):
else:
raise GitHubError(204, response.status_code,
'check if PR %d is merged' % pr_number)
- except urllib2.HTTPError as e:
+ except HTTPError as e:
if e.code == 404:
return False
else:
@@ -395,7 +397,7 @@ class WPTGitHub(object):
try:
response = self.request(path, method='PUT', body=body)
- except urllib2.HTTPError as e:
+ except HTTPError as e:
if e.code == 405:
raise MergeError(pr_number)
else:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list.py b/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list.py
index 90f448ccfed..26c8fbaf830 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list.py
@@ -112,11 +112,6 @@ class BuilderList(object):
if (include_specifiers and
not include_specifiers & builder_specifiers):
continue
- # TODO(crbug.com/1178099): When this builder is stabilized remove this
- # and make it part of default try builders.
- if is_try and not flag_specific and self.is_flag_specific_builder(
- b):
- continue
builders.append(b)
return sorted(builders)
@@ -147,6 +142,9 @@ class BuilderList(object):
def is_flag_specific_builder(self, builder_name):
return self._builders[builder_name].get('flag_specific', None) != None
+ def flag_specific_option(self, builder_name):
+ return self._builders[builder_name].get('flag_specific', None)
+
def platform_specifier_for_builder(self, builder_name):
return self.specifiers_for_builder(builder_name)[0]
@@ -158,7 +156,7 @@ class BuilderList(object):
to non-debug builders. If no builder is found, None is returned.
"""
debug_builder_name = None
- for builder_name, builder_info in self._builders.iteritems():
+ for builder_name, builder_info in list(self._builders.items()):
if builder_info.get('is_try_builder'):
continue
if builder_info['port_name'] == target_port_name:
@@ -175,7 +173,7 @@ class BuilderList(object):
the version specifier for the first builder that matches, even
if it's a try bot builder.
"""
- for _, builder_info in sorted(self._builders.iteritems()):
+ for _, builder_info in sorted(self._builders.items()):
if builder_info['port_name'] == target_port_name:
return builder_info['specifiers'][0]
return None
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
index a16d3165289..d0e1c9a2a02 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
@@ -128,8 +128,8 @@ class BuilderListTest(unittest.TestCase):
def test_all_try_builder_names(self):
builders = self.sample_builder_list()
self.assertEqual([
- 'CQ Try A', 'CQ Try B', 'CQ Try C', 'Try A', 'Try B',
- 'some-wpt-bot'
+ 'CQ Try A', 'CQ Try B', 'CQ Try C', 'Flag Specific', 'Try A',
+ 'Try B', 'some-wpt-bot'
], builders.all_try_builder_names())
def test_all_cq_try_builder_names(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
index f561c12f99b..cc117d80f69 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
@@ -135,7 +135,7 @@ class SingleTestRunner(object):
return test_result
def _run_compare_test(self):
- """Runs the signle test and returns test result."""
+ """Runs the single test and returns test result."""
driver_output = self._driver.run_test(self._driver_input())
expected_driver_output = self._expected_driver_output()
failures = self._compare_output(expected_driver_output, driver_output)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
index 1f26cd48bf7..a73e33c2725 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
@@ -105,23 +105,39 @@ class TestResultSink(object):
assert status is not None, 'unsupported result.type %r' % result.type
return status
- def _tags(self, result):
+ def _tags(self, result, expectations):
"""Returns a list of tags that should be added into a given test result.
Args:
result: The TestResult object to generate Tags for.
+ expectations: A test_expectations.TestExpectations object to pull
+ expectation data from.
Returns:
A list of {'key': 'tag-name', 'value': 'tag-value'} dicts.
"""
# the message structure of the dict can be found at
# https://chromium.googlesource.com/infra/luci/luci-go/+/master/resultdb/proto/type/common.proto#56
pair = lambda k, v: {'key': k, 'value': v}
- return [
+
+ tags = [
pair('test_name', result.test_name),
pair('web_tests_device_failed', str(result.device_failed)),
pair('web_tests_result_type', result.type),
+ pair('web_tests_flag_specific_config_name',
+ self._port.flag_specific_config_name() or '')
]
+ if expectations:
+ expectation_tags = expectations.system_condition_tags
+ test_expectation = expectations.get_expectations(result.test_name)
+ raw_expected_results = test_expectation.raw_results
+ for expectation in raw_expected_results:
+ tags.append(pair('raw_typ_expectation', expectation))
+ for tag in expectation_tags:
+ tags.append(pair('typ_tag', tag))
+
+ return tags
+
def _artifacts(self, result):
"""Returns a dict of artifacts with the absolute file paths.
@@ -170,13 +186,15 @@ class TestResultSink(object):
# Sort summaries to display "command" at the top of the summary.
return sorted(summaries), ret
- def sink(self, expected, result):
+ def sink(self, expected, result, expectations):
"""Reports the test result to ResultSink.
Args:
expected: True if the test was expected to fail and actually failed.
False, otherwise.
result: The TestResult object to report.
+ expectations: A test_expectations.TestExpectations object to pull
+ expectation data from.
Exceptions:
requests.exceptions.ConnectionError, if there was a network
connection error.
@@ -204,7 +222,7 @@ class TestResultSink(object):
# TODO(crbug/1093659): web_tests report TestResult with the start
# time.
# 'startTime': result.start_time
- 'tags': self._tags(result),
+ 'tags': self._tags(result, expectations),
'testId': result.test_name,
'testMetadata': {
'name': result.test_name,
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py
index 4749f3df7d4..f0ffe4944ba 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py
@@ -9,7 +9,7 @@ import re
import requests
import sys
import unittest
-from urlparse import urlparse
+from six.moves.urllib.parse import urlparse
from blinkpy.common.host_mock import MockHost
from blinkpy.common.path_finder import RELATIVE_WEB_TESTS
@@ -64,7 +64,7 @@ class TestCreateTestResultSink(TestResultSinkTestBase):
response.status_code = 200
with mock.patch.object(rs._session, 'post',
return_value=response) as m:
- rs.sink(True, test_results.TestResult('test'))
+ rs.sink(True, test_results.TestResult('test'), None)
self.assertTrue(m.called)
self.assertEqual(
urlparse(m.call_args[0][0]).netloc, ctx['address'])
@@ -83,8 +83,8 @@ class TestResultSinkMessage(TestResultSinkTestBase):
self.luci_context(result_sink=ctx)
self.rs = CreateTestResultSink(self.port)
- def sink(self, expected, test_result):
- self.rs.sink(expected, test_result)
+ def sink(self, expected, test_result, expectations=None):
+ self.rs.sink(expected, test_result, expectations)
self.assertTrue(self.mock_send.called)
return self.mock_send.call_args[0][0]['testResults'][0]
@@ -99,6 +99,79 @@ class TestResultSinkMessage(TestResultSinkTestBase):
self.assertEqual(sent_data['status'], 'CRASH')
self.assertEqual(sent_data['duration'], '123.456s')
+ def test_sink_with_expectations(self):
+ class FakeTestExpectation(object):
+ def __init__(self):
+ self.raw_results = ['Failure']
+
+ class FakeExpectations(object):
+ def __init__(self):
+ self.system_condition_tags = ['tag1', 'tag2']
+
+ def get_expectations(self, _):
+ return FakeTestExpectation()
+
+ # Values should be extracted from expectations.
+ tr = test_results.TestResult(test_name='test-name')
+ tr.type = ResultType.Crash
+ expectations = FakeExpectations()
+ expected_tags = [
+ {
+ 'key': 'test_name',
+ 'value': 'test-name'
+ },
+ {
+ 'key': 'web_tests_device_failed',
+ 'value': 'False'
+ },
+ {
+ 'key': 'web_tests_result_type',
+ 'value': 'CRASH'
+ },
+ {
+ 'key': 'web_tests_flag_specific_config_name',
+ 'value': ''
+ },
+ {
+ 'key': 'raw_typ_expectation',
+ 'value': 'Failure'
+ },
+ {
+ 'key': 'typ_tag',
+ 'value': 'tag1'
+ },
+ {
+ 'key': 'typ_tag',
+ 'value': 'tag2'
+ },
+ ]
+ sent_data = self.sink(True, tr, expectations)
+ self.assertEqual(sent_data['tags'], expected_tags)
+
+ def test_sink_without_expectations(self):
+ tr = test_results.TestResult(test_name='test-name')
+ tr.type = ResultType.Crash
+ expected_tags = [
+ {
+ 'key': 'test_name',
+ 'value': 'test-name'
+ },
+ {
+ 'key': 'web_tests_device_failed',
+ 'value': 'False'
+ },
+ {
+ 'key': 'web_tests_result_type',
+ 'value': 'CRASH'
+ },
+ {
+ 'key': 'web_tests_flag_specific_config_name',
+ 'value': ''
+ },
+ ]
+ sent_data = self.sink(True, tr)
+ self.assertEqual(sent_data['tags'], expected_tags)
+
def test_test_metadata(self):
tr = test_results.TestResult('')
base_path = '//' + RELATIVE_WEB_TESTS
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py
index 45189603900..0e72fa8d766 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py
@@ -28,6 +28,7 @@
import errno
import fnmatch
+import hashlib
import json
import logging
import math
@@ -125,9 +126,8 @@ class WebTestFinder(object):
times = convert_times_trie_to_flat_paths(times_trie)
# Ignore tests with a time==0 because those are skipped tests.
- sorted_times = sorted(
- [test for (test, time) in times.iteritems() if time],
- key=lambda t: (times[t], t))
+ sorted_times = sorted([test for (test, time) in times.items() if time],
+ key=lambda t: (times[t], t))
clamped_percentile = max(0, min(100, fastest_percentile))
number_of_tests_to_return = int(
len(sorted_times) * clamped_percentile / 100)
@@ -203,7 +203,7 @@ class WebTestFinder(object):
@staticmethod
def _strip_comments(line):
commentIndex = line.find('//')
- if commentIndex is -1:
+ if commentIndex == -1:
commentIndex = len(line)
line = re.sub(r'\s+', ' ', line[:commentIndex].strip())
@@ -299,8 +299,11 @@ class WebTestFinder(object):
@staticmethod
def _split_into_chunks(test_names, index, count):
- tests_and_indices = [(test_name, hash(test_name) % count)
- for test_name in test_names]
+ tests_and_indices = [
+ (test_name,
+ int(hashlib.sha256(test_name.encode('utf-8')).hexdigest(), 16) %
+ count) for test_name in test_names
+ ]
tests_to_run = [
test_name for test_name, test_index in tests_and_indices
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py
index c0f54f632a9..c013a86d436 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py
@@ -257,37 +257,35 @@ class WebTestFinderTests(unittest.TestCase):
def test_split_chunks(self):
split = web_test_finder.WebTestFinder._split_into_chunks # pylint: disable=protected-access
- with mock.patch('__builtin__.hash', int):
+ tests = ['1', '2', '3', '4']
+ self.assertEqual(['1', '2', '3', '4'], split(tests, 0, 1))
- tests = [1, 2, 3, 4]
- self.assertEqual([1, 2, 3, 4], split(tests, 0, 1))
+ self.assertEqual(['3', '4'], split(tests, 0, 2))
+ self.assertEqual(['1', '2'], split(tests, 1, 2))
- self.assertEqual([2, 4], split(tests, 0, 2))
- self.assertEqual([1, 3], split(tests, 1, 2))
+ self.assertEqual(['1', '2', '4'], split(tests, 0, 3))
+ self.assertEqual([], split(tests, 1, 3))
+ self.assertEqual(['3'], split(tests, 2, 3))
- self.assertEqual([3], split(tests, 0, 3))
- self.assertEqual([1, 4], split(tests, 1, 3))
- self.assertEqual([2], split(tests, 2, 3))
+ tests = ['1', '2', '3', '4', '5']
+ self.assertEqual(['1', '2', '3', '4', '5'], split(tests, 0, 1))
- tests = [1, 2, 3, 4, 5]
- self.assertEqual([1, 2, 3, 4, 5], split(tests, 0, 1))
+ self.assertEqual(['3', '4'], split(tests, 0, 2))
+ self.assertEqual(['1', '2', '5'], split(tests, 1, 2))
- self.assertEqual([2, 4], split(tests, 0, 2))
- self.assertEqual([1, 3, 5], split(tests, 1, 2))
+ self.assertEqual(['1', '2', '4'], split(tests, 0, 3))
+ self.assertEqual(['5'], split(tests, 1, 3))
+ self.assertEqual(['3'], split(tests, 2, 3))
- self.assertEqual([3], split(tests, 0, 3))
- self.assertEqual([1, 4], split(tests, 1, 3))
- self.assertEqual([2, 5], split(tests, 2, 3))
+ tests = ['1', '2', '3', '4', '5', '6']
+ self.assertEqual(['1', '2', '3', '4', '5', '6'], split(tests, 0, 1))
- tests = [1, 2, 3, 4, 5, 6]
- self.assertEqual([1, 2, 3, 4, 5, 6], split(tests, 0, 1))
+ self.assertEqual(['3', '4'], split(tests, 0, 2))
+ self.assertEqual(['1', '2', '5', '6'], split(tests, 1, 2))
- self.assertEqual([2, 4, 6], split(tests, 0, 2))
- self.assertEqual([1, 3, 5], split(tests, 1, 2))
-
- self.assertEqual([3, 6], split(tests, 0, 3))
- self.assertEqual([1, 4], split(tests, 1, 3))
- self.assertEqual([2, 5], split(tests, 2, 3))
+ self.assertEqual(['1', '2', '4'], split(tests, 0, 3))
+ self.assertEqual(['5', '6'], split(tests, 1, 3))
+ self.assertEqual(['3'], split(tests, 2, 3))
class FilterTestsTests(unittest.TestCase):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py
index a849ec2aca9..e58c107654a 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py
@@ -176,16 +176,17 @@ class WebTestRunnerTests(unittest.TestCase):
runner = self._runner()
runner._options.derived_batch_size = 1
runner._options.must_use_derived_batch_size = True
+ expectations = TestExpectations(runner._port)
with mock.patch.object(runner, "_test_result_sink") as rdb:
runner.run_tests(
- TestExpectations(runner._port),
+ expectations,
[],
tests_to_skip=['skips/image.html'],
num_workers=1,
retry_attempt=0,
)
rdb.sink.assert_called_with(
- True, TestResult(test_name='skips/image.html'))
+ True, TestResult(test_name='skips/image.html'), expectations)
def test_results_are_sinked(self):
runner = self._runner()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/layout_package/json_results_generator.py b/chromium/third_party/blink/tools/blinkpy/web_tests/layout_package/json_results_generator.py
index ff5f59476ef..ce5a7ec72cc 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/layout_package/json_results_generator.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/layout_package/json_results_generator.py
@@ -65,7 +65,7 @@ def write_json(filesystem, json_object, file_path, callback=None):
def convert_times_trie_to_flat_paths(trie, prefix=None):
"""Converts the directory structure in the given trie to flat paths, prepending a prefix to each."""
result = {}
- for name, data in trie.iteritems():
+ for name, data in list(trie.items()):
if prefix:
name = prefix + "/" + name
if isinstance(data, int):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_presubmit.py b/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_presubmit.py
index 8cb5a561e45..81e160dd4d4 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_presubmit.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_presubmit.py
@@ -46,6 +46,7 @@ def PresubmitCheckTestExpectations(input_api, output_api):
output_api.PresubmitError("lint_test_expectations.py failed "
"to produce output; check by hand. ")
]
+ errs = errs.decode('utf-8')
if errs.strip() == 'Lint succeeded.':
return []
if errs.rstrip().endswith('Lint succeeded with warnings.'):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py
index a8987d4d0f0..8da0582da63 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py
@@ -26,7 +26,6 @@
# (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 StringIO
import optparse
import unittest
@@ -38,6 +37,8 @@ from blinkpy.web_tests.port.android import PRODUCTS_TO_EXPECTATION_FILE_PATHS
from blinkpy.web_tests.port.base import VirtualTestSuite
from blinkpy.web_tests.port.test import WEB_TEST_DIR
+from six import StringIO
+
class FakePort(object):
def __init__(self, host, name, path):
@@ -486,7 +487,7 @@ class MainTest(unittest.TestCase):
self.orig_lint_fn = lint_test_expectations.lint
self.orig_check_fn = lint_test_expectations.check_virtual_test_suites
lint_test_expectations.check_virtual_test_suites = lambda host, options: []
- self.stderr = StringIO.StringIO()
+ self.stderr = StringIO()
def tearDown(self):
lint_test_expectations.lint = self.orig_lint_fn
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results.py b/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results.py
index c68c1fd8c12..42d8f06cf5f 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results.py
@@ -35,9 +35,15 @@ import os
import pprint
import re
import shutil
+import sys
import tempfile
import types
+BLINK_TOOLS_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+if BLINK_TOOLS_PATH not in sys.path:
+ sys.path.append(BLINK_TOOLS_PATH)
+
from blinkpy.common.system.filesystem import FileSystem
from blinkpy.common.system.log_utils import configure_logging
@@ -161,8 +167,8 @@ class JSONMerger(Merger):
Merger.__init__(self)
self.add_helper(
- TypeMatch(types.ListType, types.TupleType), self.merge_listlike)
- self.add_helper(TypeMatch(types.DictType), self.merge_dictlike)
+ TypeMatch(list, tuple), self.merge_listlike)
+ self.add_helper(TypeMatch(dict), self.merge_dictlike)
def fallback_matcher(self, objs, name=None):
raise MergeFailure("No merge helper found!", name, objs)
@@ -210,7 +216,7 @@ class JSONMerger(Merger):
dict_mid.setdefault(key, []).append(dobj[key])
dict_out = dicts[0].__class__({})
- for k, v in dict_mid.iteritems():
+ for k, v in dict_mid.items():
assert v
if len(v) == 1:
dict_out[k] = v[0]
@@ -389,15 +395,15 @@ class MergeFilesJSONP(MergeFiles):
"""
in_data = fd.read()
- begin = in_data.find('{')
- end = in_data.rfind('}') + 1
+ begin = in_data.find(b'{')
+ end = in_data.rfind(b'}') + 1
before = in_data[:begin]
data = in_data[begin:end]
after = in_data[end:]
# If just a JSON file, use json.load to get better error message output.
- if before == '' and after == '':
+ if before == b'' and after == b'':
fd.seek(0)
json_data = json.load(fd)
else:
@@ -413,7 +419,9 @@ class MergeFilesJSONP(MergeFiles):
other non-JSON data.
"""
fd.write(before)
- fd.write(json.dumps(json_data, separators=(",", ":"), sort_keys=True))
+ fd.write(json.dumps(json_data,
+ separators=(",", ":"),
+ sort_keys=True).encode('utf-8'))
fd.write(after)
@@ -490,7 +498,7 @@ class DirMerger(Merger):
# Go through each file and try to merge it.
# partial_file_path is the file relative to the directories.
- for partial_file_path, in_dirs in sorted(files.iteritems()):
+ for partial_file_path, in_dirs in sorted(files.items()):
out_path = self.filesystem.join(output_dir, partial_file_path)
if self.filesystem.exists(out_path):
raise MergeFailure('File %s already exist in output.',
@@ -522,6 +530,38 @@ class DirMerger(Merger):
# ------------------------------------------------------------------------
+class JSONWptReportsMerger(JSONMerger):
+ """Merger for the 'wpt report' format.
+
+ The JSON format is described at
+ https://github.com/web-platform-tests/wpt.fyi/tree/main/api#apiresultsupload
+
+ """
+
+ def __init__(self):
+ JSONMerger.__init__(self)
+
+ # results is a list, and we want to add them together.
+ self.add_helper(
+ NameRegexMatch(':results$'),
+ self.merge_listlike)
+
+ # pick run_info from shard 0.
+ self.add_helper(
+ NameRegexMatch(':run_info$'),
+ lambda o, name=None: o[0])
+
+ # We just take the earliest for time_start.
+ self.add_helper(
+ NameRegexMatch(':time_start$'),
+ lambda o, name=None: min(*o))
+
+ # and the last for time_end.
+ self.add_helper(
+ NameRegexMatch(':time_end$'),
+ lambda o, name=None: max(*o))
+
+
class JSONTestResultsMerger(JSONMerger):
"""Merger for the 'json test result' format.
@@ -626,6 +666,8 @@ class WebTestDirMerger(DirMerger):
self.add_helper(
FilenameRegexMatch(r'wptserve_stderr\.txt$'),
MergeFilesKeepFiles(self.filesystem))
+ self.add_helper(FilenameRegexMatch(r'wptserve_stdout\.txt$'),
+ MergeFilesKeepFiles(self.filesystem))
# keep chromedriver log for webdriver tests
self.add_helper(FilenameRegexMatch(r'chromedriver\.log$'),
MergeFilesKeepFiles(self.filesystem))
@@ -634,6 +676,15 @@ class WebTestDirMerger(DirMerger):
self.add_helper(FilenameRegexMatch(r'system_log$'),
MergeFilesKeepFiles(self.filesystem))
+ # Merge WPT report JSON files
+ # https://github.com/web-platform-tests/wpt.fyi/tree/main/api#apiresultsupload
+ wpt_reports_json_merger = MergeFilesJSONP(
+ self.filesystem,
+ JSONWptReportsMerger())
+ self.add_helper(
+ FilenameRegexMatch(r'reports\.json$'),
+ wpt_reports_json_merger)
+
# These JSON files have "result style" JSON in them.
results_json_file_merger = MergeFilesJSONP(
self.filesystem,
@@ -736,7 +787,7 @@ def mark_missing_shards(summary_json,
json_contents_merged['missing_shards'] = missing_shards
with filesystem.open_binary_file_for_writing(merged_output_json) as f:
- MergeFilesJSONP.dump_jsonp(f, '', json_contents_merged, '')
+ MergeFilesJSONP.dump_jsonp(f, b'', json_contents_merged, b'')
def find_shard_output_path(index, task_id, input_directories):
@@ -963,3 +1014,6 @@ directory. The script will be given the arguments plus
logging.info('Running post merge script %r', post_script)
os.execlp(post_script)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results_unittest.py
index 5d8a8729b22..4932f407965 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/merge_results_unittest.py
@@ -10,23 +10,20 @@ import json
import types
import unittest
-import cStringIO as StringIO
-
-from collections import OrderedDict
-
from blinkpy.common.system.filesystem_mock import FileSystemTestCase, MockFileSystem
from blinkpy.web_tests import merge_results
+from collections import OrderedDict
+from six import StringIO
+from six import BytesIO
+
class JSONMergerTests(unittest.TestCase):
def test_type_match(self):
- self.assertTrue(merge_results.TypeMatch(types.DictType)(dict()))
- self.assertFalse(
- merge_results.TypeMatch(types.ListType, types.TupleType)(dict()))
- self.assertTrue(
- merge_results.TypeMatch(types.ListType, types.TupleType)(list()))
- self.assertTrue(
- merge_results.TypeMatch(types.ListType, types.TupleType)(tuple()))
+ self.assertTrue(merge_results.TypeMatch(dict)(dict()))
+ self.assertFalse(merge_results.TypeMatch(list, tuple)(dict()))
+ self.assertTrue(merge_results.TypeMatch(list, tuple)(list()))
+ self.assertTrue(merge_results.TypeMatch(list, tuple)(tuple()))
def test_merge_listlike(self):
m = merge_results.JSONMerger()
@@ -46,10 +43,10 @@ class JSONMergerTests(unittest.TestCase):
self.assertListEqual(expected, m.merge([inputa, inputb]))
self.assertSequenceEqual(
expected, m.merge_listlike([tuple(inputa),
- tuple(inputb)]), types.TupleType)
+ tuple(inputb)]), tuple)
self.assertSequenceEqual(expected,
m.merge([tuple(inputa),
- tuple(inputb)]), types.TupleType)
+ tuple(inputb)]), tuple)
def test_merge_simple_dict(self):
m = merge_results.JSONMerger()
@@ -446,11 +443,11 @@ class JSONMergerTests(unittest.TestCase):
b_before_a['a'] = 1
r1 = m.merge([a, b])
- self.assertSequenceEqual(a_before_b.items(), r1.items())
+ self.assertSequenceEqual(list(a_before_b.items()), list(r1.items()))
self.assertIsInstance(r1, OrderedDict)
r2 = m.merge([b, a])
- self.assertSequenceEqual(b_before_a.items(), r2.items())
+ self.assertSequenceEqual(list(b_before_a.items()), list(r2.items()))
self.assertIsInstance(r2, OrderedDict)
def test_custom_match_on_name(self):
@@ -625,7 +622,7 @@ class MergeFilesJSONPTests(FileSystemTestCase):
self.assertEqual(expected_after, after)
def assertDump(self, before, json_data, after):
- fd = StringIO.StringIO()
+ fd = BytesIO()
merge_results.MergeFilesJSONP.dump_jsonp(fd, before, json_data, after)
merged_str = fd.getvalue()
self.assertTrue(self.check_before_after(merged_str, before, after))
@@ -644,23 +641,23 @@ class MergeFilesJSONPTests(FileSystemTestCase):
return json_str
def test_load(self):
- fdcls = StringIO.StringIO
- self.assertLoad(fdcls('{"a": 1}'), '', {'a': 1}, '')
- self.assertLoad(fdcls('f({"a": 1});'), 'f(', {'a': 1}, ');')
- self.assertLoad(fdcls('var o = {"a": 1}'), 'var o = ', {'a': 1}, '')
- self.assertLoad(
- fdcls('while(1); // {"a": 1}'), 'while(1); // ', {'a': 1}, '')
- self.assertLoad(fdcls('/* {"a": 1} */'), '/* ', {'a': 1}, ' */')
+ fdcls = BytesIO
+ self.assertLoad(fdcls(b'{"a": 1}'), b'', {'a': 1}, b'')
+ self.assertLoad(fdcls(b'f({"a": 1});'), b'f(', {'a': 1}, b');')
+ self.assertLoad(fdcls(b'var o = {"a": 1}'), b'var o = ', {'a': 1}, b'')
+ self.assertLoad(fdcls(b'while(1); // {"a": 1}'), b'while(1); // ',
+ {'a': 1}, b'')
+ self.assertLoad(fdcls(b'/* {"a": 1} */'), b'/* ', {'a': 1}, b' */')
def test_dump(self):
- self.assertDump('', {}, '')
- self.assertDump('f(', {}, ');')
- self.assertDump('var o = ', {}, '')
- self.assertDump('while(1); // ', {}, '')
- self.assertDump('/* ', {}, ' */')
+ self.assertDump(b'', {}, b'')
+ self.assertDump(b'f(', {}, b');')
+ self.assertDump(b'var o = ', {}, b'')
+ self.assertDump(b'while(1); // ', {}, b'')
+ self.assertDump(b'/* ', {}, b' */')
- self.assertDump('', {'a': 1}, '')
- self.assertDump('', {'a': [1, 'c', 3], 'b': 2}, '')
+ self.assertDump(b'', {'a': 1}, b'')
+ self.assertDump(b'', {'a': [1, 'c', 3], 'b': 2}, b'')
def assertMergeResults(self,
before,
@@ -701,33 +698,33 @@ class MergeFilesJSONPTests(FileSystemTestCase):
file_merger(*inputargs)
def test_single_file(self):
- self.assertMergeResults('', '', {'/s/filea': '{"a": 1}'},
+ self.assertMergeResults('', '', {'/s/filea': b'{"a": 1}'},
('/output/out1', ['/s/filea']),
- {'/output/out1': """\
+ {'/output/out1': b"""\
{"a":1}"""})
- self.assertMergeResults('f1(', ')', {'/s/filef1a': 'f1({"a": 1})'},
+ self.assertMergeResults('f1(', ')', {'/s/filef1a': b'f1({"a": 1})'},
('/output/outf1', ['/s/filef1a']),
- {'/output/outf1': """\
+ {'/output/outf1': b"""\
f1({"a":1})"""})
- self.assertMergeResults('', '', {'/s/fileb1': '{"b": 2}'},
+ self.assertMergeResults('', '', {'/s/fileb1': b'{"b": 2}'},
('/output/out2', ['/s/fileb1']),
- {'/output/out2': """\
+ {'/output/out2': b"""\
{"b":2}"""})
- self.assertMergeResults('f1(', ')', {'/s/filef1b1': 'f1({"b": 2})'},
+ self.assertMergeResults('f1(', ')', {'/s/filef1b1': b'f1({"b": 2})'},
('/output/outf2', ['/s/filef1b1']),
- {'/output/outf2': """\
+ {'/output/outf2': b"""\
f1({"b":2})"""})
def test_two_files_nonconflicting_values(self):
self.assertMergeResults(
'', '', {
- '/s/filea': '{"a": 1}',
- '/s/fileb1': '{"b": 2}',
+ '/s/filea': b'{"a": 1}',
+ '/s/fileb1': b'{"b": 2}',
}, ('/output/out3', ['/s/filea', '/s/fileb1']),
- {'/output/out3': """\
+ {'/output/out3': b"""\
{
"a": 1,
"b": 2
@@ -735,25 +732,27 @@ f1({"b":2})"""})
self.assertMergeResults(
'f1(', ')', {
- '/s/filef1a': 'f1({"a": 1})',
- '/s/filef1b1': 'f1({"b": 2})',
+ '/s/filef1a': b'f1({"a": 1})',
+ '/s/filef1b1': b'f1({"b": 2})',
}, ('/output/outf3', ['/s/filef1a', '/s/filef1b1']),
- {'/output/outf3': """\
+ {'/output/outf3': b"""\
f1({
"a": 1,
"b": 2
})"""})
def test_two_files_identical_values_fails_by_default(self):
- self.assertMergeRaises({
- '/s/fileb1': '{"b": 2}',
- '/s/fileb2': '{"b": 2}',
- }, ('/output/out4', ['/s/fileb1', '/s/fileb2']))
+ self.assertMergeRaises(
+ {
+ '/s/fileb1': b'{"b": 2}',
+ '/s/fileb2': b'{"b": 2}',
+ }, ('/output/out4', ['/s/fileb1', '/s/fileb2']))
- self.assertMergeRaises({
- '/s/filef1b1': 'f1({"b": 2})',
- '/s/filef1b2': 'f1({"b": 2})',
- }, ('/output/outf4', ['/s/filef1b1', '/s/filef1b2']))
+ self.assertMergeRaises(
+ {
+ '/s/filef1b1': b'f1({"b": 2})',
+ '/s/filef1b2': b'f1({"b": 2})',
+ }, ('/output/outf4', ['/s/filef1b1', '/s/filef1b2']))
def test_two_files_identical_values_works_with_custom_merger(self):
json_data_merger = merge_results.JSONMerger()
@@ -761,11 +760,11 @@ f1({
self.assertMergeResults('',
'', {
- '/s/fileb1': '{"b": 2}',
- '/s/fileb2': '{"b": 2}',
+ '/s/fileb1': b'{"b": 2}',
+ '/s/fileb2': b'{"b": 2}',
},
('/output/out4', ['/s/fileb1', '/s/fileb2']),
- {'/output/out4': """\
+ {'/output/out4': b"""\
{
"b": 2
}"""},
@@ -774,36 +773,113 @@ f1({
self.assertMergeResults(
'f1(',
')', {
- '/s/filef1b1': 'f1({"b": 2})',
- '/s/filef1b2': 'f1({"b": 2})',
+ '/s/filef1b1': b'f1({"b": 2})',
+ '/s/filef1b2': b'f1({"b": 2})',
}, ('/output/outf4', ['/s/filef1b1', '/s/filef1b2']),
- {'/output/outf4': """\
+ {'/output/outf4': b"""\
f1({
"b": 2
})"""},
json_data_merger=json_data_merger)
def test_two_files_conflicting_values(self):
- self.assertMergeRaises({
- '/s/fileb1': '{"b": 2}',
- '/s/fileb3': '{"b": 3}',
- }, ('/output/outff1', ['/s/fileb1', '/s/fileb3']))
- self.assertMergeRaises({
- '/s/filef1b1': 'f1({"b": 2})',
- '/s/filef1b3': 'f1({"b": 3})',
- }, ('/output/outff2', ['/s/filef1b1', '/s/filef1b3']))
+ self.assertMergeRaises(
+ {
+ '/s/fileb1': b'{"b": 2}',
+ '/s/fileb3': b'{"b": 3}',
+ }, ('/output/outff1', ['/s/fileb1', '/s/fileb3']))
+ self.assertMergeRaises(
+ {
+ '/s/filef1b1': b'f1({"b": 2})',
+ '/s/filef1b3': b'f1({"b": 3})',
+ }, ('/output/outff2', ['/s/filef1b1', '/s/filef1b3']))
def test_two_files_conflicting_function_names(self):
- self.assertMergeRaises({
- '/s/filef1a': 'f1({"a": 1})',
- '/s/filef2a': 'f2({"a": 1})',
- }, ('/output/outff3', ['/s/filef1a', '/s/filef2a']))
+ self.assertMergeRaises(
+ {
+ '/s/filef1a': b'f1({"a": 1})',
+ '/s/filef2a': b'f2({"a": 1})',
+ }, ('/output/outff3', ['/s/filef1a', '/s/filef2a']))
def test_two_files_mixed_json_and_jsonp(self):
- self.assertMergeRaises({
- '/s/filea': '{"a": 1}',
- '/s/filef1a': 'f1({"a": 1})',
- }, ('/output/outff4', ['/s/filea', '/s/filef1a']))
+ self.assertMergeRaises(
+ {
+ '/s/filea': b'{"a": 1}',
+ '/s/filef1a': b'f1({"a": 1})',
+ }, ('/output/outff4', ['/s/filea', '/s/filef1a']))
+
+
+class JSONWptReportsMerger(unittest.TestCase):
+ def test_time_start(self):
+ merger = merge_results.JSONWptReportsMerger()
+ self.assertEqual({
+ 'time_start': 2
+ },
+ merger.merge([{
+ 'time_start': 3
+ }, {
+ 'time_start': 2
+ }]))
+ self.assertEqual({
+ 'time_start': 2
+ },
+ merger.merge([{
+ 'time_start': 2
+ }, {
+ 'time_start': 3
+ }]))
+ self.assertEqual({
+ 'time_start': 12
+ }, merger.merge([{
+ 'time_start': 12
+ }, {}]))
+
+ def test_time_end(self):
+ merger = merge_results.JSONWptReportsMerger()
+ self.assertEqual({
+ 'time_end': 3
+ },
+ merger.merge([{
+ 'time_end': 3
+ }, {
+ 'time_end': 2
+ }]))
+ self.assertEqual({
+ 'time_end': 3
+ },
+ merger.merge([{
+ 'time_end': 2
+ }, {
+ 'time_end': 3
+ }]))
+ self.assertEqual({
+ 'time_end': 12
+ }, merger.merge([{
+ 'time_end': 12
+ }, {}]))
+
+ def test_run_info(self):
+ merger = merge_results.JSONWptReportsMerger()
+ self.assertEqual({
+ 'run_info': {"os": "linux"}
+ },
+ merger.merge([{
+ 'run_info': {"os": "linux"}
+ }, {
+ 'run_info': {"os": "win"}
+ }]))
+
+ def test_results(self):
+ merger = merge_results.JSONWptReportsMerger()
+ self.assertEqual({
+ 'results': [{"test": "/foo/foo.html"},
+ {"test": "/bar/bar.html"}]
+ },
+ merger.merge([{
+ "results": [{"test": "/foo/foo.html"}]
+ }, {
+ "results": [{"test": "/bar/bar.html"}]
+ }]))
class JSONTestResultsMerger(unittest.TestCase):
@@ -919,7 +995,7 @@ class WebTestDirMergerTests(unittest.TestCase):
# testdir1/test1.html
# testdir1/test2.html
# testdir2/testdir2.1/test3.html
- shard0_output_json = """\
+ shard0_output_json = b"""\
{
"build_number": "DUMMY_BUILD_NUMBER",
"builder_name": "abc",
@@ -967,7 +1043,7 @@ class WebTestDirMergerTests(unittest.TestCase):
"version": 3
}"""
- shard0_archived_results_json = """\
+ shard0_archived_results_json = b"""\
ADD_RESULTS({
"result_links": [
"results.html"
@@ -997,7 +1073,7 @@ ADD_RESULTS({
}
});"""
- shard0_stats_json = """\
+ shard0_stats_json = b"""\
{
"testdir1": {
"test1.html": {
@@ -1016,7 +1092,7 @@ ADD_RESULTS({
}
}
"""
- shard0_times_ms_json = """{
+ shard0_times_ms_json = b"""{
"testdir1": {
"test1.html": 263,
"test2.html": 32
@@ -1041,7 +1117,7 @@ ADD_RESULTS({
# Shard1 has the following tests;
# testdir2/testdir2.1/test4.html
# testdir3/testt.html
- shard1_output_json = """\
+ shard1_output_json = b"""\
{
"build_number": "DUMMY_BUILD_NUMBER",
"builder_name": "abc",
@@ -1083,7 +1159,7 @@ ADD_RESULTS({
"version": 3
}"""
- shard1_archived_results_json = """\
+ shard1_archived_results_json = b"""\
ADD_RESULTS({
"result_links": [
"results.html"
@@ -1108,7 +1184,7 @@ ADD_RESULTS({
}
});"""
- shard1_stats_json = """\
+ shard1_stats_json = b"""\
{
"testdir2": {
"testdir2.1": {
@@ -1124,7 +1200,7 @@ ADD_RESULTS({
}
}
"""
- shard1_times_ms_json = """{
+ shard1_times_ms_json = b"""{
"testdir2": {
"testdir2.1": {
"test4.html": 99
@@ -1152,7 +1228,7 @@ ADD_RESULTS({
'/shards/0/layout-test-results/error_log.txt':
shard0_error_log,
'/shards/0/layout-test-results/failing_results.json':
- "ADD_RESULTS(" + shard0_output_json + ");",
+ b"ADD_RESULTS(" + shard0_output_json + b");",
'/shards/0/layout-test-results/full_results.json':
shard0_output_json,
'/shards/0/layout-test-results/stats.json':
@@ -1199,7 +1275,7 @@ ADD_RESULTS({
'/shards/1/layout-test-results/error_log.txt':
shard1_error_log,
'/shards/1/layout-test-results/failing_results.json':
- "ADD_RESULTS(" + shard1_output_json + ");",
+ b"ADD_RESULTS(" + shard1_output_json + b");",
'/shards/1/layout-test-results/full_results.json':
shard1_output_json,
'/shards/1/layout-test-results/stats.json':
@@ -1495,14 +1571,14 @@ ADD_RESULTS({
if "archived_results" in fname or "failing_results" in fname:
self.assertTrue(
MergeFilesJSONPTests.check_before_after(
- fs.files[fname], 'ADD_RESULTS(', ");"))
+ fs.files[fname], b'ADD_RESULTS(', b");"))
self.assertTrue(
MergeFilesJSONPTests.check_before_after(
expected_contents, 'ADD_RESULTS(', ");"))
actual_json_str = MergeFilesJSONPTests.remove_before_after(
- fs.files[fname], 'ADD_RESULTS(', ");")
+ fs.files[fname], b'ADD_RESULTS(', b");")
expected_json_str = MergeFilesJSONPTests.remove_before_after(
- expected_contents, 'ADD_RESULTS(', ");")
+ expected_contents, b'ADD_RESULTS(', b");")
self.assertEqual(json.loads(actual_json_str),
json.loads(expected_json_str))
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_configuration.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_configuration.py
index 9fbc21c5ba8..351ea94b873 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_configuration.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_configuration.py
@@ -43,10 +43,10 @@ class TestConfiguration(object):
return ['version', 'architecture', 'build_type']
def items(self):
- return self.__dict__.items()
+ return list(self.__dict__.items())
def keys(self):
- return self.__dict__.keys()
+ return list(self.__dict__.keys())
def __str__(self):
return (
@@ -63,7 +63,7 @@ class TestConfiguration(object):
def values(self):
"""Returns the configuration values of this instance as a tuple."""
- return self.__dict__.values()
+ return list(self.__dict__.values())
class SpecifierSorter(object):
@@ -100,7 +100,7 @@ class SpecifierSorter(object):
return self._specifier_to_category.get(specifier)
def sort_specifiers(self, specifiers):
- category_slots = map(lambda x: [], TestConfiguration.category_order())
+ category_slots = [[] for x in TestConfiguration.category_order()]
for specifier in specifiers:
category_slots[self.specifier_priority(specifier)].append(
specifier)
@@ -177,7 +177,7 @@ class TestConfigurationConverter(object):
matching_sets.setdefault(category,
set()).update(configurations)
- return reduce(set.intersection, matching_sets.values())
+ return reduce(set.intersection, list(matching_sets.values()))
@classmethod
def collapse_macros(cls, macros_dict, specifiers_list):
@@ -276,7 +276,7 @@ class TestConfigurationConverter(object):
# 3) Abbreviate specifier sets by combining specifiers across categories.
# (win7, release), (win10, release) --> (win7, win10, release)
- while try_abbreviating(self._collapsing_sets_by_size.values()):
+ while try_abbreviating(list(self._collapsing_sets_by_size.values())):
pass
# 4) Substitute specifier subsets that match macros within each set:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
index 5ca33a578be..dc7a4612d2e 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -37,6 +37,7 @@ from collections import OrderedDict
from blinkpy.common.memoized import memoized
from blinkpy.web_tests.models import typ_types
from typ import expectations_parser
+from functools import reduce
ResultType = typ_types.ResultType
@@ -46,7 +47,7 @@ SPECIAL_PREFIXES = ('# tags:', '# results:', '# conflicts_allowed:')
_PLATFORM_TOKENS_LIST = [
'Android', 'Fuchsia', 'Linux', 'Mac', 'Mac10.12', 'Mac10.13', 'Mac10.14',
- 'Win', 'Win7', 'Win10'
+ 'Win', 'Win7', 'Win10.1909', 'Win10.20h2'
]
_BUILD_TYPE_TOKEN_LIST = [
@@ -233,9 +234,9 @@ class TestExpectations(object):
if lineno_to_exps:
lines.append(_NotExpectation('', len(content_lines) + 1))
- for line in sorted(
- reduce(lambda x,y: x+y, lineno_to_exps.values()),
- key=lambda e: e.test):
+ for line in sorted(reduce(lambda x, y: x + y,
+ list(lineno_to_exps.values())),
+ key=lambda e: e.test):
if line.lineno:
raise ValueError(
"Expectation '%s' was given a line number that "
@@ -280,6 +281,10 @@ class TestExpectations(object):
def expectations_dict(self):
return self._expectations_dict
+ @property
+ def system_condition_tags(self):
+ return self._system_condition_tags
+
@memoized
def _os_to_version(self):
os_to_version = {}
@@ -341,7 +346,7 @@ class TestExpectations(object):
trailing_comments=trailing_comments)
def get_expectations_from_file(self, path, test_name):
- idx = self._expectations_dict.keys().index(path)
+ idx = list(self._expectations_dict.keys()).index(path)
return copy.deepcopy(
self._expectations[idx].individual_exps.get(test_name) or [])
@@ -431,7 +436,7 @@ class TestExpectations(object):
path: Absolute path of file where the Expectation instances
came from.
exps: List of Expectation instances to be deleted."""
- idx = self._expectations_dict.keys().index(path)
+ idx = list(self._expectations_dict.keys()).index(path)
typ_expectations = self._expectations[idx]
for exp in exps:
@@ -454,7 +459,7 @@ class TestExpectations(object):
exps: List of Expectation instances to be added to the file.
lineno: Line number in expectations file where the expectations will
be added."""
- idx = self._expectations_dict.keys().index(path)
+ idx = list(self._expectations_dict.keys()).index(path)
typ_expectations = self._expectations[idx]
added_glob = False
@@ -479,7 +484,7 @@ class TestExpectations(object):
if added_glob:
glob_exps = reduce(lambda x, y: x + y,
- typ_expectations.glob_exps.values())
+ list(typ_expectations.glob_exps.values()))
glob_exps.sort(key=lambda e: len(e.test), reverse=True)
typ_expectations.glob_exps = OrderedDict()
for exp in glob_exps:
@@ -496,16 +501,17 @@ class SystemConfigurationRemover(object):
def __init__(self, test_expectations):
self._test_expectations = test_expectations
self._configuration_specifiers_dict = {}
- for os, os_versions in (self._test_expectations.port.
- configuration_specifier_macros().items()):
+ for os, os_versions in (list(
+ self._test_expectations.port.configuration_specifier_macros(
+ ).items())):
self._configuration_specifiers_dict[os.lower()] = (frozenset(
version.lower() for version in os_versions))
self._os_specifiers = frozenset(
os for os in self._configuration_specifiers_dict.keys())
self._version_specifiers = frozenset(
- specifier.lower() for specifier in reduce(
- lambda x, y: x | y, self._configuration_specifiers_dict.
- values()))
+ specifier.lower() for specifier in
+ reduce(lambda x, y: x | y,
+ list(self._configuration_specifiers_dict.values())))
self._deleted_lines = set()
self._generic_exp_file_path = \
self._test_expectations.port.path_to_generic_test_expectations_file()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
index 9eb769590a3..c45b9249af3 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
@@ -37,6 +37,8 @@ from blinkpy.web_tests.models.test_configuration import (
from blinkpy.web_tests.models.test_expectations import (
TestExpectations, SystemConfigurationRemover, ParseError)
from blinkpy.web_tests.models.typ_types import ResultType, Expectation
+from six.moves import range
+from functools import reduce
class Base(unittest.TestCase):
@@ -464,7 +466,7 @@ class SystemConfigurationRemoverTests(Base):
self.set_up_using_raw_expectations(raw_expectations)
all_versions = reduce(
lambda x, y: x + y,
- self._port.configuration_specifier_macros_dict.values())
+ list(self._port.configuration_specifier_macros_dict.values()))
self._system_config_remover.remove_os_versions(
'failures/expected/text.html', all_versions)
self._system_config_remover.update_expectations()
@@ -484,7 +486,7 @@ class SystemConfigurationRemoverTests(Base):
self.set_up_using_raw_expectations(raw_expectations)
all_versions = reduce(
lambda x, y: x + y,
- self._port.configuration_specifier_macros_dict.values())
+ list(self._port.configuration_specifier_macros_dict.values()))
self._system_config_remover.remove_os_versions(
'failures/expected/text.html', all_versions)
self._system_config_remover.update_expectations()
@@ -873,7 +875,7 @@ class AddExpectationsTest(Base):
'test [ failure ]\n'
'\n'
'test1 [ Pass ]\n'
- '[ Release Mac ] test2 [ Failure Crash ]\n'
+ '[ Mac Release ] test2 [ Crash Failure ]\n'
'test3 [ Failure ]\n'))
def test_add_after_remove(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures_unittest.py
index 1b8dbffbbde..acf0111000d 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures_unittest.py
@@ -102,7 +102,7 @@ class TestFailuresTest(unittest.TestCase):
test_failure.result_directory = '/dir'
pass_with_stderr = PassWithStderr(
- DriverOutput(None, None, None, None, error='pass with stderr'))
+ DriverOutput(None, None, None, None, error=b'pass with stderr'))
init_test_failure(pass_with_stderr)
crash = FailureCrash(
DriverOutput(None,
@@ -110,10 +110,10 @@ class TestFailuresTest(unittest.TestCase):
None,
None,
crash=True,
- error='crash stderr'))
+ error=b'crash stderr'))
init_test_failure(crash)
timeout = FailureTimeout(
- DriverOutput(None, None, None, None, error='timeout with stderr'))
+ DriverOutput(None, None, None, None, error=b'timeout with stderr'))
init_test_failure(timeout)
pass_with_stderr.create_artifacts(artifacts)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
index fe56ca347bf..2b310974ee5 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
@@ -90,7 +90,7 @@ class TestRunResults(object):
self.tests_by_expectation[result_type_for_stats].add(
test_result.test_name)
if self.result_sink:
- self.result_sink.sink(expected, test_result)
+ self.result_sink.sink(expected, test_result, self.expectations)
self.results_by_name[test_result.test_name] = test_result
if test_result.type != ResultType.Skip:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
index 64e7667bd58..1d86b6a8685 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
@@ -210,9 +210,10 @@ def summarized_results(port,
class RunResultsWithSinkTest(unittest.TestCase):
def setUp(self):
- expectations = test_expectations.TestExpectations(
+ self.expectations = test_expectations.TestExpectations(
MockHost().port_factory.get(port_name='test'))
- self.results = test_run_results.TestRunResults(expectations, 1, None)
+ self.results = test_run_results.TestRunResults(self.expectations, 1,
+ None)
self.test = get_result('failures/expected/text.html',
ResultType.Timeout,
run_time=1)
@@ -220,7 +221,8 @@ class RunResultsWithSinkTest(unittest.TestCase):
def testAddWithSink(self):
self.results.result_sink = mock.Mock()
self.results.add(self.test, False, False)
- self.results.result_sink.sink.assert_called_with(False, self.test)
+ self.results.result_sink.sink.assert_called_with(
+ False, self.test, self.expectations)
def testAddWithoutSink(self):
self.results.result_sink = None
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/android_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/android_unittest.py
index 96681585872..9a5c93aedd5 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/android_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/android_unittest.py
@@ -117,8 +117,8 @@ class AndroidPortTest(port_testcase.PortTestCase):
'adb_devices': ['123456789ABCDEF9']
}))
- self.assertEquals(6, port_default.default_child_processes())
- self.assertEquals(1, port_fixed_device.default_child_processes())
+ self.assertEqual(6, port_default.default_child_processes())
+ self.assertEqual(1, port_fixed_device.default_child_processes())
def test_no_bot_expectations_searched(self):
# We don't support bot expectations at the moment
@@ -189,8 +189,8 @@ class ChromiumAndroidDriverTest(unittest.TestCase):
# The cmd_line() method in the Android port is used for starting a shell, not the test runner.
def test_cmd_line(self):
- self.assertEquals(['adb', '-s', '123456789ABCDEF0', 'shell'],
- self._driver.cmd_line([]))
+ self.assertEqual(['adb', '-s', '123456789ABCDEF0', 'shell'],
+ self._driver.cmd_line([]))
# Test that the Chromium Android port can interpret Android's shell output.
def test_read_prompt(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py
index 90d98ede814..84cf1cea5b5 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -36,9 +36,11 @@ import collections
import json
import logging
import optparse
+import os
import re
import sys
import tempfile
+from collections import defaultdict
import six
from six.moves import zip_longest
@@ -141,15 +143,18 @@ class Port(object):
('mac11.0', 'x86'),
('mac-arm11.0', 'arm64'),
('win7', 'x86'),
- ('win10', 'x86'),
+ ('win10.1909', 'x86'),
+ ('win10.20h2', 'x86'),
('trusty', 'x86_64'),
('fuchsia', 'x86_64'),
)
CONFIGURATION_SPECIFIER_MACROS = {
- 'mac': ['mac10.12', 'mac10.13', 'mac10.14', 'mac10.15', 'mac11.0',
- 'mac-arm11.0'],
- 'win': ['win7', 'win10'],
+ 'mac': [
+ 'mac10.12', 'mac10.13', 'mac10.14', 'mac10.15', 'mac11.0',
+ 'mac-arm11.0'
+ ],
+ 'win': ['win7', 'win10.1909', 'win10.20h2'],
'linux': ['trusty'],
'fuchsia': ['fuchsia'],
}
@@ -248,6 +253,7 @@ class Port(object):
self._test_configuration = None
self._results_directory = None
self._virtual_test_suites = None
+ self._used_expectation_files = None
def __str__(self):
return 'Port{name=%s, version=%s, architecture=%s, test_configuration=%s}' % (
@@ -263,7 +269,7 @@ class Port(object):
])
@memoized
- def _flag_specific_config_name(self):
+ def flag_specific_config_name(self):
"""Returns the name of the flag-specific configuration which best matches
self._specified_additional_driver_flags(), or the first specified flag
with leading '-'s stripped if no match in the configuration is found.
@@ -314,7 +320,7 @@ class Port(object):
if name in configs:
raise ValueError('{} contains duplicated name {}.'.format(
config_file, name))
- if args in configs.itervalues():
+ if args in configs.values():
raise ValueError(
'{}: name "{}" has the same args as another entry.'.format(
config_file, name))
@@ -361,8 +367,10 @@ class Port(object):
# increases test run time by 2-5X, but provides more consistent results
# [less state leaks between tests].
if (self.get_option('reset_shell_between_tests')
- or self.get_option('repeat_each') > 1
- or self.get_option('iterations') > 1):
+ or (self.get_option('repeat_each')
+ and self.get_option('repeat_each') > 1)
+ or (self.get_option('iterations')
+ and self.get_option('iterations') > 1)):
flags += ['--reset-shell-between-tests']
return flags
@@ -913,15 +921,34 @@ class Port(object):
or any('external' in path for path in paths)):
tests.extend(self._wpt_test_urls_matching_paths(paths))
else:
- tests.extend(self._all_virtual_tests())
# '/' is used instead of filesystem.sep as the WPT manifest always
# uses '/' for paths (it is not OS dependent).
- tests.extend([
+ wpt_tests = [
wpt_path + '/' + test for wpt_path in self.WPT_DIRS
for test in self.wpt_manifest(wpt_path).all_urls()
- ])
+ ]
+ tests_by_dir = defaultdict(list)
+ for test in tests + wpt_tests:
+ dirname = os.path.dirname(test) + '/'
+ tests_by_dir[dirname].append(test)
+
+ tests.extend(self._all_virtual_tests(tests_by_dir))
+ tests.extend(wpt_tests)
return tests
+ def real_tests_from_dict(self, paths, tests_by_dir):
+ """Find all real tests in paths, using results saved in dict."""
+ files = []
+ for path in paths:
+ if self._has_supported_extension_for_all(path):
+ files.append(path)
+ continue
+ path = path + '/' if path[-1] != '/' else path
+ for key, value in tests_by_dir.items():
+ if key.startswith(path):
+ files.extend(value)
+ return files
+
def real_tests(self, paths):
"""Find all real tests in paths except WPT."""
# When collecting test cases, skip these directories.
@@ -964,6 +991,14 @@ class Port(object):
'.pdf',
])
+ def _has_supported_extension_for_all(self, filename):
+ extension = self._filesystem.splitext(filename)[1]
+ if 'inspector-protocol' in filename and extension == '.js':
+ return True
+ if 'devtools' in filename and extension == '.js':
+ return True
+ return extension in self.supported_file_extensions
+
def _has_supported_extension(self, filename):
"""Returns True if filename is one of the file extensions we want to run a test on."""
extension = self._filesystem.splitext(filename)[1]
@@ -995,7 +1030,7 @@ class Port(object):
manifest_path = self._filesystem.join(self.web_tests_dir(), path,
MANIFEST_NAME)
if not self._filesystem.exists(manifest_path) or self.get_option(
- 'manifest_update', True):
+ 'manifest_update', False):
_log.debug('Generating MANIFEST.json for %s...', path)
WPTManifest.ensure_manifest(self, path)
return WPTManifest(self.host, manifest_path)
@@ -1608,14 +1643,14 @@ class Port(object):
return test_configurations
def _flag_specific_expectations_path(self):
- config_name = self._flag_specific_config_name()
+ config_name = self.flag_specific_config_name()
if config_name:
return self._filesystem.join(self.web_tests_dir(),
self.FLAG_EXPECTATIONS_PREFIX,
config_name)
def _flag_specific_baseline_search_path(self):
- config_name = self._flag_specific_config_name()
+ config_name = self.flag_specific_config_name()
if not config_name:
return []
flag_dir = self._filesystem.join(self.web_tests_dir(), 'flag-specific',
@@ -1643,24 +1678,29 @@ class Port(object):
# updated to know about the ordered dict.
expectations = collections.OrderedDict()
- if not self.get_option('ignore_default_expectations', False):
- for path in self.expectations_files():
- if self._filesystem.exists(path):
+ default_expectations_files = set(self.default_expectations_files())
+ ignore_default = self.get_option('ignore_default_expectations', False)
+ for path in self.used_expectations_files():
+ is_default = path in default_expectations_files
+ if ignore_default and is_default:
+ continue
+ path_exists = self._filesystem.exists(path)
+ if is_default:
+ if path_exists:
expectations[path] = self._filesystem.read_text_file(path)
-
- for path in self.get_option('additional_expectations', []):
- expanded_path = self._filesystem.expanduser(path)
- if self._filesystem.exists(expanded_path):
- _log.debug("reading additional_expectations from path '%s'",
- path)
- expectations[path] = self._filesystem.read_text_file(
- expanded_path)
else:
- # TODO(rmhasan): Fix additional expectation paths for
- # not_site_per_process_blink_web_tests, then change this back
- # to raising exceptions for incorrect expectation paths.
- _log.warning(
- "additional_expectations path '%s' does not exist", path)
+ if path_exists:
+ _log.debug(
+ "reading additional_expectations from path '%s'", path)
+ expectations[path] = self._filesystem.read_text_file(path)
+ else:
+ # TODO(rmhasan): Fix additional expectation paths for
+ # not_site_per_process_blink_web_tests, then change this
+ # back to raising exceptions for incorrect expectation
+ # paths.
+ _log.warning(
+ "additional_expectations path '%s' does not exist",
+ path)
return expectations
def all_expectations_dict(self):
@@ -1712,7 +1752,7 @@ class Port(object):
_log.warning("Unexpected ignore mode: '%s'.", ignore_mode)
return {}
- def expectations_files(self):
+ def default_expectations_files(self):
"""Returns a list of paths to expectations files that apply by default.
There are other "test expectations" files that may be applied if
@@ -1725,10 +1765,21 @@ class Port(object):
self._filesystem.join(self.web_tests_dir(), 'NeverFixTests'),
self._filesystem.join(self.web_tests_dir(),
'StaleTestExpectations'),
- self._filesystem.join(self.web_tests_dir(), 'SlowTests'),
- self._flag_specific_expectations_path()
+ self._filesystem.join(self.web_tests_dir(), 'SlowTests')
])
+ def used_expectations_files(self):
+ """Returns a list of paths to expectation files that are used."""
+ if self._used_expectation_files is None:
+ self._used_expectation_files = self.default_expectations_files()
+ flag_specific = self._flag_specific_expectations_path()
+ if flag_specific:
+ self._used_expectation_files.append(flag_specific)
+ for path in self.get_option('additional_expectations', []):
+ expanded_path = self._filesystem.expanduser(path)
+ self._used_expectation_files.append(expanded_path)
+ return self._used_expectation_files
+
def extra_expectations_files(self):
"""Returns a list of paths to test expectations not loaded by default.
@@ -1941,30 +1992,13 @@ class Port(object):
path_to_virtual_test_suites, error))
return self._virtual_test_suites
- def _all_virtual_tests(self):
+ def _all_virtual_tests(self, tests_by_dir):
tests = []
- # The set of paths to find tests for each virtual test suite.
- suite_paths = []
- # For each path, a map functor that converts the test path to be under
- # the virtual test suite.
- suite_prefixes = []
for suite in self.virtual_test_suites():
- for b in suite.bases:
- suite_paths.append(b)
- suite_prefixes.append(suite.full_prefix)
-
- # TODO(crbug.com/982208): If we can pass in the set of paths and
- # maps then this could be more efficient.
if suite.bases:
- tests.extend(
- map(lambda x: suite.full_prefix + x,
- self.real_tests(suite.bases)))
-
- if suite_paths:
- tests.extend(
- self._wpt_test_urls_matching_paths(suite_paths,
- suite_prefixes))
+ tests.extend(map(lambda x: suite.full_prefix + x,
+ self.real_tests_from_dict(suite.bases, tests_by_dir)))
return tests
def _get_bases_for_suite_with_paths(self, suite, paths):
@@ -2057,9 +2091,6 @@ class Port(object):
wpts = [(wpt_path, self.wpt_manifest(wpt_path))
for wpt_path in self.WPT_DIRS]
- _log.debug("Finding WPT tests that match %d path prefixes",
- len(filter_paths))
-
tests = []
# This walks through the set of paths where we should look for tests.
# For each path, a map can be provided that we replace 'path' with in
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
index 08a3012d673..b41b0760dc9 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
@@ -66,9 +66,9 @@ class PortTest(LoggingTestCase):
for wpt_path in Port.WPT_DIRS.keys():
self.assertFalse(wpt_path.endswith('/'))
# Values should not be empty (except the last one).
- for url_prefix in Port.WPT_DIRS.values()[:-1]:
+ for url_prefix in list(Port.WPT_DIRS.values())[:-1]:
self.assertNotEqual(url_prefix, '/')
- self.assertEqual(Port.WPT_DIRS.values()[-1], '/')
+ self.assertEqual(list(Port.WPT_DIRS.values())[-1], '/')
def test_validate_wpt_regex(self):
self.assertEquals(
@@ -459,8 +459,10 @@ class PortTest(LoggingTestCase):
def test_nonexistant_expectations(self):
port = self.make_port(port_name='foo')
- port.expectations_files = lambda: [MOCK_WEB_TESTS + 'platform/exists/TestExpectations',
- MOCK_WEB_TESTS + 'platform/nonexistant/TestExpectations']
+ port.default_expectations_files = lambda: [
+ MOCK_WEB_TESTS + 'platform/exists/TestExpectations', MOCK_WEB_TESTS
+ + 'platform/nonexistant/TestExpectations'
+ ]
port.host.filesystem.write_text_file(
MOCK_WEB_TESTS + 'platform/exists/TestExpectations', '')
self.assertEqual('\n'.join(port.expectations_dict().keys()),
@@ -481,13 +483,14 @@ class PortTest(LoggingTestCase):
def test_additional_expectations_empty(self):
port = self._make_port_for_test_additional_expectations()
- self.assertEqual(port.expectations_dict().values(), [])
+ self.assertEqual(list(port.expectations_dict().values()), [])
def test_additional_expectations_1(self):
port = self._make_port_for_test_additional_expectations({
'additional_expectations': ['/tmp/additional-expectations-1.txt']
})
- self.assertEqual(port.expectations_dict().values(), ['content1\n'])
+ self.assertEqual(list(port.expectations_dict().values()),
+ ['content1\n'])
def test_additional_expectations_2(self):
port = self._make_port_for_test_additional_expectations({
@@ -496,7 +499,7 @@ class PortTest(LoggingTestCase):
'/tmp/additional-expectations-2.txt'
]
})
- self.assertEqual(port.expectations_dict().values(),
+ self.assertEqual(list(port.expectations_dict().values()),
['content1\n', 'content2\n'])
def test_additional_expectations_additional_flag(self):
@@ -507,7 +510,7 @@ class PortTest(LoggingTestCase):
],
'additional_driver_flag': ['--special-flag']
})
- self.assertEqual(port.expectations_dict().values(),
+ self.assertEqual(list(port.expectations_dict().values()),
['content3', 'content1\n', 'content2\n'])
def test_flag_specific_expectations(self):
@@ -519,7 +522,7 @@ class PortTest(LoggingTestCase):
port.host.filesystem.write_text_file(
MOCK_WEB_TESTS + 'FlagExpectations/README.txt', 'cc')
- self.assertEqual(port.expectations_dict().values(), [])
+ self.assertEqual(list(port.expectations_dict().values()), [])
# all_expectations_dict() is an OrderedDict, but its order depends on
# file system walking order.
self.assertEqual(
@@ -546,14 +549,14 @@ class PortTest(LoggingTestCase):
port_a = self.make_port(options=optparse.Values({}))
# pylint: disable=protected-access
self.assertEqual(port_a._specified_additional_driver_flags(), [])
- self.assertIsNone(port_a._flag_specific_config_name())
+ self.assertIsNone(port_a.flag_specific_config_name())
port_b = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--bb']
}))
self.assertEqual(port_b._specified_additional_driver_flags(), ['--bb'])
- self.assertEqual(port_b._flag_specific_config_name(), 'bb')
+ self.assertEqual(port_b.flag_specific_config_name(), 'bb')
port_c = self.make_port(
options=optparse.Values({
@@ -561,7 +564,7 @@ class PortTest(LoggingTestCase):
}))
self.assertEqual(port_c._specified_additional_driver_flags(),
['--cc', '--dd'])
- self.assertEqual(port_c._flag_specific_config_name(), 'cc')
+ self.assertEqual(port_c.flag_specific_config_name(), 'cc')
def test_flag_specific_config_name_from_options_and_file(self):
flag_file = MOCK_WEB_TESTS + 'additional-driver-flag.setting'
@@ -570,7 +573,7 @@ class PortTest(LoggingTestCase):
port_a.host.filesystem.write_text_file(flag_file, '--aa')
# pylint: disable=protected-access
self.assertEqual(port_a._specified_additional_driver_flags(), ['--aa'])
- self.assertEqual(port_a._flag_specific_config_name(), 'aa')
+ self.assertEqual(port_a.flag_specific_config_name(), 'aa')
port_b = self.make_port(
options=optparse.Values({
@@ -579,7 +582,7 @@ class PortTest(LoggingTestCase):
port_b.host.filesystem.write_text_file(flag_file, '--aa')
self.assertEqual(port_b._specified_additional_driver_flags(),
['--aa', '--bb'])
- self.assertEqual(port_b._flag_specific_config_name(), 'aa')
+ self.assertEqual(port_b.flag_specific_config_name(), 'aa')
port_c = self.make_port(
options=optparse.Values({
@@ -589,7 +592,7 @@ class PortTest(LoggingTestCase):
# We don't remove duplicated flags at this time.
self.assertEqual(port_c._specified_additional_driver_flags(),
['--bb', '--dd', '--bb', '--cc'])
- self.assertEqual(port_c._flag_specific_config_name(), 'bb')
+ self.assertEqual(port_c.flag_specific_config_name(), 'bb')
def _write_flag_specific_config(self, port):
port.host.filesystem.write_text_file(
@@ -607,56 +610,56 @@ class PortTest(LoggingTestCase):
}))
self._write_flag_specific_config(port_a1)
# pylint: disable=protected-access
- self.assertEqual(port_a1._flag_specific_config_name(), 'a')
+ self.assertEqual(port_a1.flag_specific_config_name(), 'a')
port_a2 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--aa', '--dd']
}))
self._write_flag_specific_config(port_a2)
- self.assertEqual(port_a2._flag_specific_config_name(), 'a')
+ self.assertEqual(port_a2.flag_specific_config_name(), 'a')
port_a3 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--aa', '--bb']
}))
self._write_flag_specific_config(port_a3)
- self.assertEqual(port_a3._flag_specific_config_name(), 'a')
+ self.assertEqual(port_a3.flag_specific_config_name(), 'a')
port_b1 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--bb', '--aa']
}))
self._write_flag_specific_config(port_b1)
- self.assertEqual(port_b1._flag_specific_config_name(), 'b')
+ self.assertEqual(port_b1.flag_specific_config_name(), 'b')
port_b2 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--bb', '--aa', '--cc']
}))
self._write_flag_specific_config(port_b2)
- self.assertEqual(port_b2._flag_specific_config_name(), 'b')
+ self.assertEqual(port_b2.flag_specific_config_name(), 'b')
port_b3 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--bb', '--aa', '--dd']
}))
self._write_flag_specific_config(port_b3)
- self.assertEqual(port_b3._flag_specific_config_name(), 'b')
+ self.assertEqual(port_b3.flag_specific_config_name(), 'b')
port_c1 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--bb', '--cc']
}))
self._write_flag_specific_config(port_c1)
- self.assertEqual(port_c1._flag_specific_config_name(), 'c')
+ self.assertEqual(port_c1.flag_specific_config_name(), 'c')
port_c2 = self.make_port(
options=optparse.Values({
'additional_driver_flag': ['--bb', '--cc', '--aa']
}))
self._write_flag_specific_config(port_c2)
- self.assertEqual(port_c2._flag_specific_config_name(), 'c')
+ self.assertEqual(port_c2.flag_specific_config_name(), 'c')
def test_flag_specific_fallback(self):
port_b = self.make_port(
@@ -665,7 +668,7 @@ class PortTest(LoggingTestCase):
}))
self._write_flag_specific_config(port_b)
# No match. Fallback to first specified flag.
- self.assertEqual(port_b._flag_specific_config_name(), 'bb')
+ self.assertEqual(port_b.flag_specific_config_name(), 'bb')
port_d = self.make_port(
options=optparse.Values({
@@ -673,7 +676,7 @@ class PortTest(LoggingTestCase):
}))
self._write_flag_specific_config(port_d)
# pylint: disable=protected-access
- self.assertEqual(port_d._flag_specific_config_name(), 'dd')
+ self.assertEqual(port_d.flag_specific_config_name(), 'dd')
def test_flag_specific_option(self):
port_a = self.make_port(
@@ -682,7 +685,7 @@ class PortTest(LoggingTestCase):
}))
self._write_flag_specific_config(port_a)
# pylint: disable=protected-access
- self.assertEqual(port_a._flag_specific_config_name(), 'a')
+ self.assertEqual(port_a.flag_specific_config_name(), 'a')
port_b = self.make_port(
options=optparse.Values({
@@ -690,14 +693,14 @@ class PortTest(LoggingTestCase):
'additional_driver_flag': ['--bb']
}))
self._write_flag_specific_config(port_b)
- self.assertEqual(port_b._flag_specific_config_name(), 'a')
+ self.assertEqual(port_b.flag_specific_config_name(), 'a')
port_d = self.make_port(
options=optparse.Values({
'flag_specific': 'd'
}))
self._write_flag_specific_config(port_d)
- self.assertRaises(AssertionError, port_d._flag_specific_config_name)
+ self.assertRaises(AssertionError, port_d.flag_specific_config_name)
def test_duplicate_flag_specific_name(self):
port = self.make_port()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver_unittest.py
index fb4d3e0addd..a3380455dbf 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver_unittest.py
@@ -39,7 +39,7 @@ class BrowserTestDriverTest(unittest.TestCase):
port = TestPort(MockHost())
driver = BrowserTestDriver(port, 0)
driver._server_process = MockServerProcess(
- lines=['StdinPath: /foo/bar', '#EOF'])
+ lines=[b'StdinPath: /foo/bar', b'#EOF'])
content_block = driver._read_block(0)
- self.assertEqual(content_block.stdin_path, '/foo/bar')
+ self.assertEqual(content_block.stdin_path, b'/foo/bar')
driver._stdin_directory = None
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py
index 3c7182b3f3a..00848e8cc6b 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py
@@ -227,7 +227,13 @@ class Driver(object):
"""
start_time = time.time()
stdin_deadline = start_time + int(driver_input.timeout) / 2000.0
- self.start(driver_input.args, stdin_deadline)
+ ok, startup_output = self.start(driver_input.args, stdin_deadline)
+ if not ok:
+ return startup_output
+
+ return self._run_one_input(driver_input, start_time)
+
+ def _run_one_input(self, driver_input, start_time):
test_begin_time = time.time()
self.error_from_test = bytearray()
self.err_seen_eof = False
@@ -380,7 +386,8 @@ class Driver(object):
relative_path = test_name[len(test_dir_prefix):]
if ('/https/' in test_name or '.https.' in test_name
- or '.h2.' in test_name or '.serviceworker.' in test_name):
+ or '.h2.' in test_name or '.serviceworker.' in test_name
+ or '.serviceworker-module.' in test_name):
return 'https://%s:%d%s%s' % (hostname, secure_port,
test_url_prefix, relative_path)
return 'http://%s:%d%s%s' % (hostname, insecure_port, test_url_prefix,
@@ -431,10 +438,14 @@ class Driver(object):
return False
def start(self, per_test_args, deadline):
+ """Returns a tuple of (whether driver was started, optional startup test result)."""
new_cmd_line = self.cmd_line(per_test_args)
if not self._server_process or new_cmd_line != self._current_cmd_line:
- self._start(per_test_args)
- self._run_post_start_tasks()
+ started, output = self._start(per_test_args)
+ if started:
+ self._run_post_start_tasks()
+ return started, output
+ return True, None
def _setup_environ_for_driver(self, environment):
if self._profiler:
@@ -450,6 +461,8 @@ class Driver(object):
more_logging=self._port.get_option('driver_logging'))
def _start(self, per_test_args, wait_for_ready=True):
+ """Returns a tuple of (whether driver was started, optional startup test result)."""
+
self.stop()
self._driver_tempdir = self._port.host.filesystem.mkdtemp(
prefix='%s-' % self._port.driver_name())
@@ -469,6 +482,40 @@ class Driver(object):
if not self._wait_for_server_process_output(
self._server_process, deadline, b'#READY'):
_log.error('%s took too long to startup.' % server_name)
+ # Even though the server hasn't started up, we pretend it has
+ # so that the rest of the error-handling code can deal with
+ # this as if the test has simply crashed.
+
+ if self._port.get_option(
+ 'initialize_webgpu_adapter_at_startup_timeout_ms'):
+ return self._initialize_webgpu_adapter_at_startup(per_test_args)
+ return True, None
+
+ def _initialize_webgpu_adapter_at_startup(self, per_test_args):
+ # TODO(crbug.com/953991) - Apparently content_shell isn't
+ # "really" ready when it signals #READY; in some WebGPU cases
+ # there are intermittent additional delays that we haven't
+ # been able to diagnose yet, but that running this particular
+ # test seems to address. We should figure out what is going on
+ # and remove this workaround, which causes every content shell
+ # startup to be slower (if the workaround is triggered via the
+ # --initialize-webgpu-adapter-at-startup flag, right above in the
+ # code in _start()).
+ init_timeout = self._port.get_option(
+ 'initialize_webgpu_adapter_at_startup_timeout_ms')
+ startup_input = DriverInput(
+ "wpt_internal/webgpu/000_run_me_first.html",
+ timeout=init_timeout,
+ image_hash=None,
+ args=per_test_args)
+ output = self._run_one_input(startup_input, start_time=time.time())
+ if output.text and 'PASS 000_run_me_first' in output.text:
+ return True, None
+
+ output.text = ('Failed to initialize WebGPU adapter at startup '
+ 'via wpt_internal_webgpu/000_run_me_first.html:\n' +
+ output.text)
+ return False, output
def _wait_for_server_process_output(self, server_process, deadline, text):
output = b''
@@ -529,8 +576,18 @@ class Driver(object):
cmd.extend(self._port.additional_driver_flags())
if self._port.get_option('enable_leak_detection'):
cmd.append('--enable-leak-detection')
-
cmd.extend(per_test_args)
+
+ # The following code temporarily disables CompositeAfterPaint in web
+ # tests unless it is explicitly enabled. CompositeAfterPaint is enabled
+ # via fieldtrial_testing_config.json which would make web tests run
+ # with CompositeAfterPaint. This is disabled in order to stage the
+ # enabling of the feature because of the number of rebaselines needed.
+ # TODO(pdr): Remove this code and run web tests with
+ # CompositeAfterPaint.
+ if '--enable-blink-features=CompositeAfterPaint' not in cmd:
+ cmd.append('--disable-blink-features=CompositeAfterPaint')
+
cmd = coalesce_repeated_switches(cmd)
cmd.append('-')
return cmd
@@ -559,7 +616,7 @@ class Driver(object):
self._port.sample_process(self._crashed_process_name,
self._crashed_pid)
# We want to show this since it's not a regular crash and probably we don't have a crash log.
- self.error_from_test += error_line
+ self.error_from_test += error_line.encode('utf-8')
return True
return self.has_crashed()
@@ -672,7 +729,7 @@ class Driver(object):
assert not self.err_seen_eof
err_line, self.err_seen_eof = self._strip_eof(err_line)
if out_line:
- if out_line[-1] != '\n':
+ if not out_line.endswith(b'\n'):
_log.error(
'Last character read from DRT stdout line was not a newline! This indicates either a NRWT or DRT bug.'
)
@@ -722,7 +779,7 @@ class ContentBlock(object):
self.stdin_path = None
def decode_content(self):
- if self.encoding == 'base64' and self.content is not None:
+ if self.encoding == b'base64' and self.content is not None:
self.decoded_content = base64.b64decode(self.content)
else:
self.decoded_content = self.content
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
index ef67ba7b2d3..c8ba9d754bf 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
@@ -144,53 +144,53 @@ class DriverTest(unittest.TestCase):
port = self.make_port()
driver = Driver(port, 0)
driver._server_process = MockServerProcess(lines=[
- 'ActualHash: foobar',
- 'Content-Type: my_type',
- 'Content-Transfer-Encoding: none',
- '#EOF',
+ b'ActualHash: foobar',
+ b'Content-Type: my_type',
+ b'Content-Transfer-Encoding: none',
+ b'#EOF',
])
content_block = driver._read_block(0)
- self.assertEqual(content_block.content, '')
- self.assertEqual(content_block.content_type, 'my_type')
- self.assertEqual(content_block.encoding, 'none')
- self.assertEqual(content_block.content_hash, 'foobar')
+ self.assertEqual(content_block.content, b'')
+ self.assertEqual(content_block.content_type, b'my_type')
+ self.assertEqual(content_block.encoding, b'none')
+ self.assertEqual(content_block.content_hash, b'foobar')
driver._server_process = None
def test_read_binary_block(self):
port = self.make_port()
driver = Driver(port, 0)
driver._server_process = MockServerProcess(lines=[
- 'ActualHash: actual',
- 'ExpectedHash: expected',
- 'Content-Type: image/png',
- 'Content-Length: 9',
- '12345678',
- '#EOF',
+ b'ActualHash: actual',
+ b'ExpectedHash: expected',
+ b'Content-Type: image/png',
+ b'Content-Length: 9',
+ b'12345678',
+ b'#EOF',
])
content_block = driver._read_block(0)
- self.assertEqual(content_block.content_type, 'image/png')
- self.assertEqual(content_block.content_hash, 'actual')
- self.assertEqual(content_block.content, '12345678\n')
- self.assertEqual(content_block.decoded_content, '12345678\n')
+ self.assertEqual(content_block.content_type, b'image/png')
+ self.assertEqual(content_block.content_hash, b'actual')
+ self.assertEqual(content_block.content, b'12345678\n')
+ self.assertEqual(content_block.decoded_content, b'12345678\n')
driver._server_process = None
def test_read_base64_block(self):
port = self.make_port()
driver = Driver(port, 0)
driver._server_process = MockServerProcess(lines=[
- 'ActualHash: actual',
- 'ExpectedHash: expected',
- 'Content-Type: image/png',
- 'Content-Transfer-Encoding: base64',
- 'Content-Length: 12',
- 'MTIzNDU2NzgK#EOF',
+ b'ActualHash: actual',
+ b'ExpectedHash: expected',
+ b'Content-Type: image/png',
+ b'Content-Transfer-Encoding: base64',
+ b'Content-Length: 12',
+ b'MTIzNDU2NzgK#EOF',
])
content_block = driver._read_block(0)
- self.assertEqual(content_block.content_type, 'image/png')
- self.assertEqual(content_block.content_hash, 'actual')
- self.assertEqual(content_block.encoding, 'base64')
- self.assertEqual(content_block.content, 'MTIzNDU2NzgK')
- self.assertEqual(content_block.decoded_content, '12345678\n')
+ self.assertEqual(content_block.content_type, b'image/png')
+ self.assertEqual(content_block.content_hash, b'actual')
+ self.assertEqual(content_block.encoding, b'base64')
+ self.assertEqual(content_block.content, b'MTIzNDU2NzgK')
+ self.assertEqual(content_block.decoded_content, b'12345678\n')
def test_no_timeout(self):
port = self.make_port()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory_unittest.py
index 849d042cf25..eaba6ead695 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory_unittest.py
@@ -77,7 +77,8 @@ class FactoryTest(unittest.TestCase):
def test_win(self):
self.assert_port(port_name='win-win7', cls=win.WinPort)
- self.assert_port(port_name='win-win10', cls=win.WinPort)
+ self.assert_port(port_name='win-win10.1909', cls=win.WinPort)
+ self.assert_port(port_name='win-win10.20h2', cls=win.WinPort)
self.assert_port(
port_name='win', os_name='win', os_version='win7', cls=win.WinPort)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
index 71b6c113938..b353e6d13de 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
@@ -34,6 +34,7 @@ import subprocess
import sys
import threading
+from argparse import Namespace
from blinkpy.common import exit_codes
from blinkpy.common.path_finder import WEB_TESTS_LAST_COMPONENT
from blinkpy.common.path_finder import get_chromium_src_dir
@@ -62,6 +63,8 @@ def _import_fuchsia_runner():
# pylint: disable=redefined-outer-name
global aemu_target
import aemu_target
+ global _GetPathToBuiltinTarget, _LoadTargetClass
+ from common_args import _GetPathToBuiltinTarget, _LoadTargetClass
global device_target
import device_target
global fuchsia_target
@@ -130,7 +133,7 @@ class _TargetHost(object):
def __init__(self, build_path, build_ids_path, ports_to_forward, target,
results_directory):
try:
- self._amber_repo = None
+ self._pkg_repo = None
self._target = target
self._target.Start()
self._setup_target(build_path, build_ids_path, ports_to_forward,
@@ -165,8 +168,8 @@ class _TargetHost(object):
self.symbolizer = symbolizer.RunSymbolizer(
self._listener.stdout, listener_log, [build_ids_path])
- self._amber_repo = self._target.GetAmberRepo()
- self._amber_repo.__enter__()
+ self._pkg_repo = self._target.GetPkgRepo()
+ self._pkg_repo.__enter__()
package_path = os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH)
self._target.InstallPackage([package_path])
@@ -185,8 +188,8 @@ class _TargetHost(object):
stderr=subprocess.PIPE)
def cleanup(self):
- if self._amber_repo:
- self._amber_repo.__exit__(None, None, None)
+ if self._pkg_repo:
+ self._pkg_repo.__exit__(None, None, None)
if self._target:
# Emulator targets will be shutdown during cleanup.
# TODO(sergeyu): Currently __init__() always starts Qemu, so we can
@@ -240,39 +243,24 @@ class FuchsiaPort(base.Port):
def setup_test_run(self):
super(FuchsiaPort, self).setup_test_run()
try:
- target_args = {
- 'out_dir': self._build_path(),
- 'system_log_file': None,
- 'fuchsia_out_dir': self.get_option('fuchsia_out_dir')
- }
- if self._target_device == 'device':
- additional_args = {
- 'target_cpu': self.get_option('fuchsia_target_cpu'),
- 'ssh_config': self.get_option('fuchsia_ssh_config'),
- 'os_check': 'ignore',
- 'host': self.get_option('fuchsia_host'),
- 'port': self.get_option('fuchsia_port'),
- 'node_name': self.get_option('fuchsia_node_name')
- }
- target_args.update(additional_args)
- target = device_target.DeviceTarget(**target_args)
- else:
- additional_args = {
- 'target_cpu': 'x64',
- 'cpu_cores': CPU_CORES,
- 'require_kvm': True,
- 'ram_size_mb': 8192
- }
- if self._target_device == 'qemu':
- target_args.update(additional_args)
- target = qemu_target.QemuTarget(**target_args)
- else:
- additional_args.update({
- 'enable_graphics': False,
- 'hardware_gpu': False
- })
- target_args.update(additional_args)
- target = aemu_target.AemuTarget(**target_args)
+ target_args = Namespace(
+ out_dir=self._build_path(),
+ system_log_file=None,
+ fuchsia_out_dir=self.get_option('fuchsia_out_dir'),
+ target_cpu=self.get_option('fuchsia_target_cpu'),
+ ssh_config=self.get_option('fuchsia_ssh_config'),
+ os_check='ignore',
+ host=self.get_option('fuchsia_host'),
+ port=self.get_option('fuchsia_port'),
+ node_name=self.get_option('fuchsia_node_name'),
+ cpu_cores=CPU_CORES,
+ require_kvm=True,
+ ram_size_mb=8192,
+ enable_graphics=False,
+ hardware_gpu=False)
+ target = _LoadTargetClass(
+ _GetPathToBuiltinTarget(
+ self._target_device)).CreateFromArgs(target_args)
self._target_host = _TargetHost(self._build_path(),
self.get_build_ids_path(),
self.SERVER_PORTS, target,
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt.py
index 15ac8d3effc..04326ec7e84 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt.py
@@ -179,7 +179,7 @@ class MockDRT(object):
self._driver = self._port.create_driver(0)
def run(self):
- self._stdout.write('#READY\n')
+ self._stdout.write(b'#READY\n')
self._stdout.flush()
while True:
line = self._stdin.readline()
@@ -194,8 +194,8 @@ class MockDRT(object):
self.write_test_output(driver_input, output, is_reftest)
def input_from_line(self, line):
- vals = line.strip().split("'")
- uri = vals[0]
+ vals = line.strip().split(b"'")
+ uri = vals[0].decode('utf-8')
checksum = None
if len(vals) == 2:
checksum = vals[1]
@@ -217,13 +217,13 @@ class MockDRT(object):
actual_checksum = None
if is_reftest:
# Make up some output for reftests.
- actual_text = 'reference text\n'
- actual_checksum = 'mock-checksum'
- actual_image = 'blank'
+ actual_text = b'reference text\n'
+ actual_checksum = b'mock-checksum'
+ actual_image = b'blank'
if test_input.test_name.endswith('-mismatch.html'):
- actual_text = 'not reference text\n'
- actual_checksum = 'not-mock-checksum'
- actual_image = 'not blank'
+ actual_text = b'not reference text\n'
+ actual_checksum = b'not-mock-checksum'
+ actual_image = b'not blank'
elif test_input.image_hash:
actual_checksum = port.expected_checksum(test_input.test_name)
actual_image = port.expected_image(test_input.test_name)
@@ -253,30 +253,31 @@ class MockDRT(object):
def write_test_output(self, test_input, output, is_reftest):
if output.audio:
- self._stdout.write('Content-Type: audio/wav\n')
- self._stdout.write('Content-Transfer-Encoding: base64\n')
+ self._stdout.write(b'Content-Type: audio/wav\n')
+ self._stdout.write(b'Content-Transfer-Encoding: base64\n')
self._stdout.write(base64.b64encode(output.audio))
- self._stdout.write('\n')
+ self._stdout.write(b'\n')
else:
- self._stdout.write('Content-Type: text/plain\n')
+ self._stdout.write(b'Content-Type: text/plain\n')
# FIXME: Note that we don't ensure there is a trailing newline!
# This mirrors actual (Mac) DRT behavior but is a bug.
if output.text:
self._stdout.write(output.text)
- self._stdout.write('#EOF\n')
+ self._stdout.write(b'#EOF\n')
if output.image_hash:
- self._stdout.write('\n')
- self._stdout.write('ActualHash: %s\n' % output.image_hash)
- self._stdout.write('ExpectedHash: %s\n' % test_input.image_hash)
+ self._stdout.write(b'\n')
+ self._stdout.write(b'ActualHash: ' + output.image_hash + b'\n')
+ self._stdout.write(b'ExpectedHash: ' + test_input.image_hash +
+ b'\n')
if output.image_hash != test_input.image_hash:
- self._stdout.write('Content-Type: image/png\n')
- self._stdout.write('Content-Length: %s\n' % len(output.image))
+ self._stdout.write(b'Content-Type: image/png\n')
+ self._stdout.write(b'Content-Length: %s\n' % len(output.image))
self._stdout.write(output.image)
- self._stdout.write('#EOF\n')
+ self._stdout.write(b'#EOF\n')
self._stdout.flush()
- self._stderr.write('#EOF\n')
+ self._stderr.write(b'#EOF\n')
self._stderr.flush()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt_unittest.py
index 40998dc7e11..0af8748d725 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mock_drt_unittest.py
@@ -83,12 +83,12 @@ class MockDRTPortTest(port_testcase.PortTestCase):
class MockDRTTest(unittest.TestCase):
def input_line(self, port, test_name, checksum=None):
- url = port.create_driver(0).test_to_uri(test_name)
- if url.startswith('file://'):
- url = url[len('file://'):]
+ url = port.create_driver(0).test_to_uri(test_name).encode('utf8')
+ if url.startswith(b'file://'):
+ url = url[len(b'file://'):]
if checksum:
- url += "'" + checksum
- return url + '\n'
+ url += b"'" + checksum
+ return url + b'\n'
def make_drt(self, options, args, host, stdin, stdout, stderr):
return mock_drt.MockDRT(options, args, host, stdin, stdout, stderr)
@@ -112,17 +112,16 @@ class MockDRTTest(unittest.TestCase):
return (drt_input, drt_output)
def expected_output(self, port, test_name, text_output, expected_checksum):
- output = ['#READY\n', 'Content-Type: text/plain\n']
+ output = [b'#READY\n', b'Content-Type: text/plain\n']
if text_output:
output.append(text_output)
- output.append('#EOF\n')
+ output.append(b'#EOF\n')
if expected_checksum:
output.extend([
- '\n',
- 'ActualHash: %s\n' % expected_checksum,
- 'ExpectedHash: %s\n' % expected_checksum
+ b'\n', b'ActualHash: ' + expected_checksum + b'\n',
+ b'ExpectedHash: ' + expected_checksum + b'\n'
])
- output.append('#EOF\n')
+ output.append(b'#EOF\n')
return output
def assertTest(self,
@@ -154,8 +153,8 @@ class MockDRTTest(unittest.TestCase):
self.assertEqual(res, 0)
- self.assertEqual(stdout.getvalue(), ''.join(drt_output))
- self.assertEqual(stderr.getvalue(), '#EOF\n')
+ self.assertEqual(stdout.getvalue(), b''.join(drt_output))
+ self.assertEqual(stderr.getvalue(), b'#EOF\n')
def test_main(self):
host = MockSystemHost()
@@ -166,8 +165,8 @@ class MockDRTTest(unittest.TestCase):
res = mock_drt.main(['--run-web-tests', '--platform', 'test', '-'],
host, stdin, stdout, stderr)
self.assertEqual(res, 0)
- self.assertEqual(stdout.getvalue(), '#READY\n')
- self.assertEqual(stderr.getvalue(), '')
+ self.assertEqual(stdout.getvalue(), b'#READY\n')
+ self.assertEqual(stderr.getvalue(), b'')
self.assertEqual(host.filesystem.written_files, {})
def test_pixeltest_passes(self):
@@ -175,19 +174,18 @@ class MockDRTTest(unittest.TestCase):
self.assertTest('http/tests/passes/text.html')
def test_pixeltest__fails(self):
- self.assertTest(
- 'failures/expected/image_checksum.html',
- expected_checksum='image_checksum-checksum',
- drt_output=[
- '#READY\n',
- 'Content-Type: text/plain\n',
- 'image_checksum-txt',
- '#EOF\n',
- '\n',
- 'ActualHash: image_checksum-checksum\n',
- 'ExpectedHash: image_checksum-checksum\n',
- '#EOF\n',
- ])
+ self.assertTest('failures/expected/image_checksum.html',
+ expected_checksum=b'image_checksum-checksum',
+ drt_output=[
+ b'#READY\n',
+ b'Content-Type: text/plain\n',
+ b'image_checksum-txt',
+ b'#EOF\n',
+ b'\n',
+ b'ActualHash: image_checksum-checksum\n',
+ b'ExpectedHash: image_checksum-checksum\n',
+ b'#EOF\n',
+ ])
def test_textonly(self):
self.assertTest('passes/image.html')
@@ -196,29 +194,26 @@ class MockDRTTest(unittest.TestCase):
self.assertTest('passes/checksum_in_image.html')
def test_reftest_match(self):
- self.assertTest(
- 'passes/reftest.html',
- expected_checksum='mock-checksum',
- expected_text='reference text\n')
+ self.assertTest('passes/reftest.html',
+ expected_checksum=b'mock-checksum',
+ expected_text=b'reference text\n')
def test_reftest_mismatch(self):
- self.assertTest(
- 'passes/mismatch.html',
- expected_checksum='mock-checksum',
- expected_text='reference text\n')
+ self.assertTest('passes/mismatch.html',
+ expected_checksum=b'mock-checksum',
+ expected_text=b'reference text\n')
def test_audio(self):
- self.assertTest(
- 'passes/audio.html',
- drt_output=[
- '#READY\n',
- 'Content-Type: audio/wav\n',
- 'Content-Transfer-Encoding: base64\n',
- 'YXVkaW8td2F2',
- '\n',
- '#EOF\n',
- '#EOF\n',
- ])
+ self.assertTest('passes/audio.html',
+ drt_output=[
+ b'#READY\n',
+ b'Content-Type: audio/wav\n',
+ b'Content-Transfer-Encoding: base64\n',
+ b'YXVkaW8td2F2',
+ b'\n',
+ b'#EOF\n',
+ b'#EOF\n',
+ ])
def test_virtual(self):
self.assertTest('virtual/passes/text.html')
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py
index d03cecb1e99..0a49422d941 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py
@@ -241,9 +241,9 @@ class PortTestCase(LoggingTestCase):
None, None, None, None, newer_than=None)
self.assertIsNone(stderr)
self.assertEqual(
- details, 'crash log for <unknown process name> (pid <unknown>):\n'
- 'STDOUT: <empty>\n'
- 'STDERR: <empty>\n')
+ details, b'crash log for <unknown process name> (pid <unknown>):\n'
+ b'STDOUT: <empty>\n'
+ b'STDERR: <empty>\n')
self.assertIsNone(crash_site)
def test_get_crash_log_simple(self):
@@ -251,23 +251,26 @@ class PortTestCase(LoggingTestCase):
stderr, details, crash_site = port._get_crash_log(
'foo',
1234,
- 'out bar\nout baz',
- 'err bar\nerr baz\n',
+ b'out bar\nout baz',
+ b'err bar\nerr baz\n',
newer_than=None)
- self.assertEqual(stderr, 'err bar\nerr baz\n')
+ self.assertEqual(stderr, b'err bar\nerr baz\n')
self.assertEqual(
- details, 'crash log for foo (pid 1234):\n'
- 'STDOUT: out bar\n'
- 'STDOUT: out baz\n'
- 'STDERR: err bar\n'
- 'STDERR: err baz\n')
+ details, b'crash log for foo (pid 1234):\n'
+ b'STDOUT: out bar\n'
+ b'STDOUT: out baz\n'
+ b'STDERR: err bar\n'
+ b'STDERR: err baz\n')
self.assertIsNone(crash_site)
def test_get_crash_log_non_ascii(self):
port = self.make_port()
- stderr, details, crash_site = port._get_crash_log(
- 'foo', 1234, 'foo\xa6bar', 'foo\xa6bar', newer_than=None)
- self.assertEqual(stderr, 'foo\xa6bar')
+ stderr, details, crash_site = port._get_crash_log('foo',
+ 1234,
+ b'foo\xa6bar',
+ b'foo\xa6bar',
+ newer_than=None)
+ self.assertEqual(stderr, b'foo\xa6bar')
self.assertEqual(
details.decode('utf8', 'replace'),
u'crash log for foo (pid 1234):\n'
@@ -277,9 +280,12 @@ class PortTestCase(LoggingTestCase):
def test_get_crash_log_newer_than(self):
port = self.make_port()
- stderr, details, crash_site = port._get_crash_log(
- 'foo', 1234, 'foo\xa6bar', 'foo\xa6bar', newer_than=1.0)
- self.assertEqual(stderr, 'foo\xa6bar')
+ stderr, details, crash_site = port._get_crash_log('foo',
+ 1234,
+ b'foo\xa6bar',
+ b'foo\xa6bar',
+ newer_than=1.0)
+ self.assertEqual(stderr, b'foo\xa6bar')
self.assertEqual(
details.decode('utf8', 'replace'),
u'crash log for foo (pid 1234):\n'
@@ -292,20 +298,20 @@ class PortTestCase(LoggingTestCase):
stderr, details, crash_site = port._get_crash_log(
'foo',
1234,
- 'out bar',
- '[1:2:3:4:FATAL:example.cc(567)] Check failed.',
+ b'out bar',
+ b'[1:2:3:4:FATAL:example.cc(567)] Check failed.',
newer_than=None)
self.assertEqual(stderr,
- '[1:2:3:4:FATAL:example.cc(567)] Check failed.')
+ b'[1:2:3:4:FATAL:example.cc(567)] Check failed.')
self.assertEqual(
- details, 'crash log for foo (pid 1234):\n'
- 'STDOUT: out bar\n'
- 'STDERR: [1:2:3:4:FATAL:example.cc(567)] Check failed.\n')
+ details, b'crash log for foo (pid 1234):\n'
+ b'STDOUT: out bar\n'
+ b'STDERR: [1:2:3:4:FATAL:example.cc(567)] Check failed.\n')
self.assertEqual(crash_site, 'example.cc(567)')
- def test_expectations_files(self):
+ def test_default_expectations_files(self):
port = self.make_port()
- self.assertEqual(port.expectations_files(), [
+ self.assertEqual(list(port.default_expectations_files()), [
port.path_to_generic_test_expectations_file(),
port.path_to_webdriver_expectations_file(),
port.host.filesystem.join(port.web_tests_dir(), 'NeverFixTests'),
@@ -314,25 +320,43 @@ class PortTestCase(LoggingTestCase):
port.host.filesystem.join(port.web_tests_dir(), 'SlowTests'),
])
- def test_expectations_ordering(self):
+ def test_default_expectations_ordering(self):
port = self.make_port()
- for path in port.expectations_files():
+ for path in port.default_expectations_files():
port.host.filesystem.write_text_file(path, '')
ordered_dict = port.expectations_dict()
self.assertEqual(port.path_to_generic_test_expectations_file(),
- ordered_dict.keys()[0])
+ list(ordered_dict)[0])
options = optparse.Values(
dict(additional_expectations=['/tmp/foo', '/tmp/bar']))
port = self.make_port(options=options)
- for path in port.expectations_files():
+ for path in port.default_expectations_files():
port.host.filesystem.write_text_file(path, '')
port.host.filesystem.write_text_file('/tmp/foo', 'foo')
port.host.filesystem.write_text_file('/tmp/bar', 'bar')
ordered_dict = port.expectations_dict()
- self.assertEqual(ordered_dict.keys()[-2:],
- options.additional_expectations)
- self.assertEqual(ordered_dict.values()[-2:], ['foo', 'bar'])
+ self.assertEqual(
+ list(ordered_dict)[-2:], options.additional_expectations)
+ self.assertEqual(list(ordered_dict.values())[-2:], ['foo', 'bar'])
+
+ def test_used_expectations_files(self):
+ options = optparse.Values({
+ 'additional_expectations': ['/tmp/foo'],
+ 'additional_driver_flag': ['flag-specific']
+ })
+ port = self.make_port(options=options)
+ self.assertEqual(list(port.used_expectations_files()), [
+ port.path_to_generic_test_expectations_file(),
+ port.path_to_webdriver_expectations_file(),
+ port.host.filesystem.join(port.web_tests_dir(), 'NeverFixTests'),
+ port.host.filesystem.join(port.web_tests_dir(),
+ 'StaleTestExpectations'),
+ port.host.filesystem.join(port.web_tests_dir(), 'SlowTests'),
+ port.host.filesystem.join(port.web_tests_dir(), 'FlagExpectations',
+ 'flag-specific'),
+ '/tmp/foo',
+ ])
def test_path_to_apache_config_file(self):
# Specific behavior may vary by port, so unit test sub-classes may override this.
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_mock.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_mock.py
index f41dc763db0..cafc7d0dbd0 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_mock.py
@@ -41,7 +41,7 @@ class MockServerProcess(object):
# with server_process.ServerProcess.
# pylint: disable=unused-argument
self.timed_out = False
- self.lines = lines or ['#READY']
+ self.lines = lines or [b'#READY']
self.crashed = crashed
self.writes = []
self.cmd = cmd
@@ -58,7 +58,7 @@ class MockServerProcess(object):
return self.crashed
def read_stdout_line(self, deadline):
- return self.lines.pop(0) + '\n'
+ return self.lines.pop(0) + b'\n'
def read_stdout(self, deadline, size):
first_line = self.lines[0]
@@ -66,15 +66,15 @@ class MockServerProcess(object):
self.lines.pop(0)
remaining_size = size - len(first_line) - 1
if not remaining_size:
- return first_line + '\n'
- return first_line + '\n' + self.read_stdout(
+ return first_line + b'\n'
+ return first_line + b'\n' + self.read_stdout(
deadline, remaining_size)
result = self.lines[0][:size]
self.lines[0] = self.lines[0][size:]
return result
def pop_all_buffered_stderr(self):
- return ''
+ return b''
def read_either_stdout_or_stderr_line(self, deadline):
# FIXME: We should have tests which intermix stderr and stdout lines.
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_unittest.py
index af3353ac759..158343a03b7 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/server_process_unittest.py
@@ -100,7 +100,7 @@ class TestServerProcess(unittest.TestCase):
port = factory.get()
now = time.time()
proc = server_process.ServerProcess(port, 'python', cmd)
- proc.write('')
+ proc.write(b'')
self.assertIsNone(proc.poll())
self.assertFalse(proc.has_crashed())
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py
index f93c27b88ac..92037ce074e 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py
@@ -67,7 +67,9 @@ class TestInstance(object):
# We add the '\x8a' for the image file to prevent the value from
# being treated as UTF-8 (the character is invalid)
- self.actual_image = self.base + '\x8a' + '-png' + 'tEXtchecksum\x00' + self.actual_checksum
+ self.actual_image = (self.base.encode('utf8') + b'\x8a' + b'-png' +
+ b'tEXtchecksum\x00' +
+ self.actual_checksum.encode('utf8'))
self.expected_text = self.actual_text
self.expected_image = self.actual_image
@@ -91,7 +93,7 @@ class TestList(object):
def add_reference(self,
name,
actual_checksum='checksum',
- actual_image='FAIL'):
+ actual_image=b'FAIL'):
self.add(
name,
actual_checksum=actual_checksum,
@@ -107,21 +109,21 @@ class TestList(object):
actual_text=None,
expected_text=None,
crash=False,
- error=''):
- self.add(
- name,
- actual_checksum='checksum',
- actual_image='FAIL',
- expected_image=None,
- actual_text=actual_text,
- expected_text=expected_text,
- crash=crash,
- error=error)
+ error=b''):
+ self.add(name,
+ actual_checksum='checksum',
+ actual_image=b'FAIL',
+ expected_image=None,
+ actual_text=actual_text,
+ expected_text=expected_text,
+ crash=crash,
+ error=error)
if same_image:
self.add_reference(reference_name)
else:
- self.add_reference(
- reference_name, actual_checksum='diff', actual_image='DIFF')
+ self.add_reference(reference_name,
+ actual_checksum='diff',
+ actual_image=b'DIFF')
def keys(self):
return self.tests.keys()
@@ -153,61 +155,52 @@ def unit_test_list():
tests.add('failures/expected/device_failure.html', device_failure=True)
tests.add('failures/expected/timeout.html', timeout=True)
tests.add('failures/expected/leak.html', leak=True)
- tests.add(
- 'failures/expected/image.html',
- actual_image='image_fail-pngtEXtchecksum\x00checksum_fail',
- expected_image='image-pngtEXtchecksum\x00checksum-png')
- tests.add(
- 'failures/expected/image_checksum.html',
- actual_checksum='image_checksum_fail-checksum',
- actual_image='image_checksum_fail-png')
- tests.add(
- 'failures/expected/audio.html',
- actual_audio=base64.b64encode('audio_fail-wav'),
- expected_audio='audio-wav',
- actual_text=None,
- expected_text=None,
- actual_image=None,
- expected_image=None,
- actual_checksum=None)
- tests.add(
- 'failures/unexpected/image-mismatch.html',
- actual_image='image_fail-pngtEXtchecksum\x00checksum_fail',
- expected_image='image-pngtEXtchecksum\x00checksum-png')
- tests.add(
- 'failures/unexpected/no-image-generated.html',
- expected_image='image-pngtEXtchecksum\x00checksum-png',
- actual_image=None,
- actual_checksum=None)
- tests.add(
- 'failures/unexpected/no-image-baseline.html',
- actual_image='image_fail-pngtEXtchecksum\x00checksum_fail',
- expected_image=None)
- tests.add(
- 'failures/unexpected/audio-mismatch.html',
- actual_audio=base64.b64encode('audio_fail-wav'),
- expected_audio='audio-wav',
- actual_text=None,
- expected_text=None,
- actual_image=None,
- expected_image=None,
- actual_checksum=None)
- tests.add(
- 'failures/unexpected/no-audio-baseline.html',
- actual_audio=base64.b64encode('audio_fail-wav'),
- actual_text=None,
- expected_text=None,
- actual_image=None,
- expected_image=None,
- actual_checksum=None)
- tests.add(
- 'failures/unexpected/no-audio-generated.html',
- expected_audio=base64.b64encode('audio_fail-wav'),
- actual_text=None,
- expected_text=None,
- actual_image=None,
- expected_image=None,
- actual_checksum=None)
+ tests.add('failures/expected/image.html',
+ actual_image=b'image_fail-pngtEXtchecksum\x00checksum_fail',
+ expected_image=b'image-pngtEXtchecksum\x00checksum-png')
+ tests.add('failures/expected/image_checksum.html',
+ actual_checksum='image_checksum_fail-checksum',
+ actual_image=b'image_checksum_fail-png')
+ tests.add('failures/expected/audio.html',
+ actual_audio=base64.b64encode(b'audio_fail-wav'),
+ expected_audio=b'audio-wav',
+ actual_text=None,
+ expected_text=None,
+ actual_image=None,
+ expected_image=None,
+ actual_checksum=None)
+ tests.add('failures/unexpected/image-mismatch.html',
+ actual_image=b'image_fail-pngtEXtchecksum\x00checksum_fail',
+ expected_image=b'image-pngtEXtchecksum\x00checksum-png')
+ tests.add('failures/unexpected/no-image-generated.html',
+ expected_image=b'image-pngtEXtchecksum\x00checksum-png',
+ actual_image=None,
+ actual_checksum=None)
+ tests.add('failures/unexpected/no-image-baseline.html',
+ actual_image=b'image_fail-pngtEXtchecksum\x00checksum_fail',
+ expected_image=None)
+ tests.add('failures/unexpected/audio-mismatch.html',
+ actual_audio=base64.b64encode(b'audio_fail-wav'),
+ expected_audio=b'audio-wav',
+ actual_text=None,
+ expected_text=None,
+ actual_image=None,
+ expected_image=None,
+ actual_checksum=None)
+ tests.add('failures/unexpected/no-audio-baseline.html',
+ actual_audio=base64.b64encode(b'audio_fail-wav'),
+ actual_text=None,
+ expected_text=None,
+ actual_image=None,
+ expected_image=None,
+ actual_checksum=None)
+ tests.add('failures/unexpected/no-audio-generated.html',
+ expected_audio=base64.b64encode(b'audio_fail-wav'),
+ actual_text=None,
+ expected_text=None,
+ actual_image=None,
+ expected_image=None,
+ actual_checksum=None)
tests.add(
'failures/unexpected/text-mismatch-overlay.html',
actual_text='"invalidations": [\nfail',
@@ -239,9 +232,8 @@ def unit_test_list():
tests.add('failures/flaky/text.html')
tests.add('failures/unexpected/*/text.html', actual_text='text_fail-png')
tests.add('failures/unexpected/missing_text.html', expected_text=None)
- tests.add(
- 'failures/unexpected/missing_check.html',
- expected_image='missing-check-png')
+ tests.add('failures/unexpected/missing_check.html',
+ expected_image=b'missing-check-png')
tests.add('failures/unexpected/missing_image.html', expected_image=None)
tests.add(
'failures/unexpected/missing_render_tree_dump.html',
@@ -257,34 +249,30 @@ layer at (0,0) size 800x34
tests.add('failures/unexpected/crash.html', crash=True)
tests.add('failures/unexpected/crash-with-sample.html', crash=True)
tests.add('failures/unexpected/crash-with-delayed-log.html', crash=True)
- tests.add(
- 'failures/unexpected/crash-with-stderr.html',
- crash=True,
- error='mock-std-error-output')
- tests.add(
- 'failures/unexpected/web-process-crash-with-stderr.html',
- web_process_crash=True,
- error='mock-std-error-output')
+ tests.add('failures/unexpected/crash-with-stderr.html',
+ crash=True,
+ error=b'mock-std-error-output')
+ tests.add('failures/unexpected/web-process-crash-with-stderr.html',
+ web_process_crash=True,
+ error=b'mock-std-error-output')
tests.add('failures/unexpected/pass.html')
tests.add(
'failures/unexpected/text-checksum.html',
actual_text='text-checksum_fail-txt',
actual_checksum='text-checksum_fail-checksum')
- tests.add(
- 'failures/unexpected/text-image-checksum.html',
- actual_text='text-image-checksum_fail-txt',
- actual_image=
- 'text-image-checksum_fail-pngtEXtchecksum\x00checksum_fail',
- actual_checksum='text-image-checksum_fail-checksum')
+ tests.add('failures/unexpected/text-image-checksum.html',
+ actual_text='text-image-checksum_fail-txt',
+ actual_image=
+ b'text-image-checksum_fail-pngtEXtchecksum\x00checksum_fail',
+ actual_checksum='text-image-checksum_fail-checksum')
tests.add(
'failures/unexpected/checksum-with-matching-image.html',
actual_checksum='text-image-checksum_fail-checksum')
- tests.add(
- 'failures/unexpected/image-only.html',
- expected_text=None,
- actual_text=None,
- actual_image='image-only_fail-pngtEXtchecksum\x00checksum_fail',
- actual_checksum='image-only_fail-checksum')
+ tests.add('failures/unexpected/image-only.html',
+ expected_text=None,
+ actual_text=None,
+ actual_image=b'image-only_fail-pngtEXtchecksum\x00checksum_fail',
+ actual_checksum='image-only_fail-checksum')
tests.add('failures/unexpected/skip_pass.html')
tests.add('failures/unexpected/text.html', actual_text='text_fail-txt')
tests.add('failures/unexpected/text_then_crash.html')
@@ -294,23 +282,21 @@ layer at (0,0) size 800x34
tests.add('http/tests/passes/image.html')
tests.add('http/tests/ssl/text.html')
tests.add('passes/args.html')
- tests.add('passes/error.html', error='stuff going to stderr')
+ tests.add('passes/error.html', error=b'stuff going to stderr')
tests.add('passes/image.html', actual_text=None, expected_text=None)
- tests.add(
- 'passes/audio.html',
- actual_audio=base64.b64encode('audio-wav'),
- expected_audio='audio-wav',
- actual_text=None,
- expected_text=None,
- actual_image=None,
- expected_image=None,
- actual_checksum=None,
- expected_checksum=None)
+ tests.add('passes/audio.html',
+ actual_audio=base64.b64encode(b'audio-wav'),
+ expected_audio=b'audio-wav',
+ actual_text=None,
+ expected_text=None,
+ actual_image=None,
+ expected_image=None,
+ actual_checksum=None,
+ expected_checksum=None)
tests.add('passes/platform_image.html')
tests.add('passes/slow.html')
- tests.add(
- 'passes/checksum_in_image.html',
- expected_image='tEXtchecksum\x00checksum_in_image-checksum')
+ tests.add('passes/checksum_in_image.html',
+ expected_image=b'tEXtchecksum\x00checksum_in_image-checksum')
tests.add('passes/skipped/skip.html')
tests.add(
'failures/unexpected/testharness.html',
@@ -384,7 +370,7 @@ layer at (0,0) size 800x34
same_image=False,
actual_text='actual',
expected_text='expected',
- error='oops')
+ error=b'oops')
tests.add_reftest('failures/unexpected/mismatch.html',
'failures/unexpected/mismatch-expected-mismatch.html')
tests.add(
@@ -508,11 +494,11 @@ passes/slow.html [ Slow ]
# Add each test and the expected output, if any.
test_list = unit_test_list()
for test in test_list.tests.values():
- add_file(test, test.name[test.name.rfind('.'):], '')
+ add_file(test, test.name[test.name.rfind('.'):], b'')
if test.expected_audio:
add_file(test, '-expected.wav', test.expected_audio)
if test.expected_text:
- add_file(test, '-expected.txt', test.expected_text)
+ add_file(test, '-expected.txt', test.expected_text.encode('utf-8'))
if test.expected_image:
add_file(test, '-expected.png', test.expected_image)
@@ -727,7 +713,7 @@ class TestPort(Port):
crash_logs = {}
for cp in crashed_processes:
if cp[0].endswith('-with-delayed-log.html'):
- crash_logs[cp[0]] = ('delayed crash log', '/tmp')
+ crash_logs[cp[0]] = (b'delayed crash log', '/tmp')
return crash_logs
def _path_to_driver(self, target=None):
@@ -758,8 +744,10 @@ class TestPort(Port):
if not actual_contents or not expected_contents:
return (True, None)
if diffed:
- return ('< %s\n---\n> %s\n' % (expected_contents, actual_contents),
- None)
+ return (
+ ('< %s\n---\n> %s\n' %
+ (expected_contents, actual_contents)), #.encode('utf8'),
+ None)
return (None, None)
def web_tests_dir(self):
@@ -888,18 +876,21 @@ class TestDriver(Driver):
raise DeviceFailure('device failure in ' + test_name)
audio = None
- actual_text = test.actual_text
+ if test.actual_text:
+ actual_text = test.actual_text.encode('utf8')
+ else:
+ actual_text = None
crash = test.crash
web_process_crash = test.web_process_crash
leak = test.leak
if 'flaky/text.html' in test_name and not test_name in self._port._flakes:
self._port._flakes.add(test_name)
- actual_text = 'flaky text failure'
+ actual_text = b'flaky text failure'
if 'crash_then_text.html' in test_name:
if test_name in self._port._flakes:
- actual_text = 'text failure'
+ actual_text = b'text failure'
else:
self._port._flakes.add(test_name)
crashed_process_name = self._port.driver_name()
@@ -913,29 +904,30 @@ class TestDriver(Driver):
crash = True
else:
self._port._flakes.add(test_name)
- actual_text = 'text failure'
+ actual_text = b'text failure'
if actual_text and test_args and test_name == 'passes/args.html':
- actual_text = actual_text + ' ' + ' '.join(test_args)
+ actual_text = actual_text + b' ' + (
+ ' '.join(test_args).encode('utf8'))
if test.actual_audio:
audio = base64.b64decode(test.actual_audio)
crashed_process_name = None
crashed_pid = None
- leak_log = ''
+ leak_log = b''
if leak:
- leak_log = 'leak detected'
+ leak_log = b'leak detected'
- crash_log = ''
+ crash_log = b''
if crash:
crashed_process_name = self._port.driver_name()
crashed_pid = 1
- crash_log = 'crash log'
+ crash_log = b'crash log'
elif web_process_crash:
crashed_process_name = 'WebProcess'
crashed_pid = 2
- crash_log = 'web process crash log'
+ crash_log = b'web process crash log'
if crashed_process_name:
crash_logs = CrashLogs(self._port.host)
@@ -946,7 +938,7 @@ class TestDriver(Driver):
crashed_process_name = self._port.driver_name()
crashed_pid = 3
crash = True
- crash_log = 'reftest crash log'
+ crash_log = b'reftest crash log'
if test.actual_checksum == driver_input.image_hash:
image = None
else:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/win.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/win.py
index 4ec9a321eeb..f9dfb23df10 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/win.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/win.py
@@ -51,10 +51,13 @@ _log = logging.getLogger(__name__)
class WinPort(base.Port):
port_name = 'win'
- SUPPORTED_VERSIONS = ('win7', 'win10')
+ SUPPORTED_VERSIONS = ('win7', 'win10.1909', 'win10.20h2')
- FALLBACK_PATHS = {'win10': ['win']}
- FALLBACK_PATHS['win7'] = ['win7'] + FALLBACK_PATHS['win10']
+ FALLBACK_PATHS = {}
+ FALLBACK_PATHS['win10.20h2'] = ['win']
+ FALLBACK_PATHS['win10.1909'] = ['win10.1909'
+ ] + FALLBACK_PATHS['win10.20h2']
+ FALLBACK_PATHS['win7'] = ['win7'] + FALLBACK_PATHS['win10.1909']
BUILD_REQUIREMENTS_URL = 'https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md'
@@ -66,8 +69,10 @@ class WinPort(base.Port):
if host.platform.os_version in ('vista', '7sp0', '7sp1'):
version = 'win7'
# Same for win8, we treat it as win10.
- elif host.platform.os_version in ('8', '8.1', '10', 'future'):
- version = 'win10'
+ elif host.platform.os_version in ('8', '8.1', '10.1909'):
+ version = 'win10.1909'
+ elif host.platform.os_version in ('10.20h2', 'future'):
+ version = 'win10.20h2'
else:
version = host.platform.os_version
port_name = port_name + '-' + version
@@ -151,6 +156,8 @@ class WinPort(base.Port):
# Make TMP an alias for TEMP
self.host.environ['TMP'] = self.host.environ['TEMP']
env = super(WinPort, self).setup_environ_for_server()
+ # App Container needs a valid LOCALAPPDATA to function correctly.
+ env['LOCALAPPDATA'] = self.host.environ['TEMP']
apache_envvars = ['SYSTEMDRIVE', 'SYSTEMROOT', 'TEMP', 'TMP']
for key, value in self.host.environ.copy().items():
if key not in env and key in apache_envvars:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/win_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/win_unittest.py
index 8ee08bb13a4..5298c3e7898 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/win_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/win_unittest.py
@@ -70,15 +70,20 @@ class WinPortTest(port_testcase.PortTestCase):
self.assert_name(None, 'win7', 'win-win7')
self.assert_name('win', 'win7', 'win-win7')
- self.assert_name(None, '10', 'win-win10')
- self.assert_name('win', '10', 'win-win10')
- self.assert_name('win-win10', '10', 'win-win10')
- self.assert_name('win-win10', 'win7', 'win-win10')
+ self.assert_name(None, '10.1909', 'win-win10.1909')
+ self.assert_name('win', '10.1909', 'win-win10.1909')
+ self.assert_name('win-win10.1909', '10.1909', 'win-win10.1909')
+ self.assert_name('win-win10.1909', 'win7', 'win-win10.1909')
- self.assert_name(None, '8', 'win-win10')
- self.assert_name(None, '8.1', 'win-win10')
- self.assert_name('win', '8', 'win-win10')
- self.assert_name('win', '8.1', 'win-win10')
+ self.assert_name(None, '10.20h2', 'win-win10.20h2')
+ self.assert_name('win', '10.20h2', 'win-win10.20h2')
+ self.assert_name('win-win10.20h2', '10.20h2', 'win-win10.20h2')
+ self.assert_name('win-win10.20h2', 'win7', 'win-win10.20h2')
+
+ self.assert_name(None, '8', 'win-win10.1909')
+ self.assert_name(None, '8.1', 'win-win10.1909')
+ self.assert_name('win', '8', 'win-win10.1909')
+ self.assert_name('win', '8.1', 'win-win10.1909')
self.assert_name(None, '7sp1', 'win-win7')
self.assert_name(None, '7sp0', 'win-win7')
@@ -90,9 +95,9 @@ class WinPortTest(port_testcase.PortTestCase):
self.assert_name('win-win7', '7sp0', 'win-win7')
self.assert_name('win-win7', 'vista', 'win-win7')
- self.assert_name(None, 'future', 'win-win10')
- self.assert_name('win', 'future', 'win-win10')
- self.assert_name('win-win10', 'future', 'win-win10')
+ self.assert_name(None, 'future', 'win-win10.20h2')
+ self.assert_name('win', 'future', 'win-win10.20h2')
+ self.assert_name('win-win10.20h2', 'future', 'win-win10.20h2')
with self.assertRaises(AssertionError):
self.assert_name(None, 'w2k', 'win-win7')
@@ -106,8 +111,9 @@ class WinPortTest(port_testcase.PortTestCase):
self.assertTrue(port.baseline_search_path()[i].endswith(path))
def test_baseline_path(self):
- self.assert_baseline_paths('win-win7', 'win7', '/win')
- self.assert_baseline_paths('win-win10', 'win')
+ self.assert_baseline_paths('win-win7', 'win7', 'win10.1909', '/win')
+ self.assert_baseline_paths('win-win10.1909', 'win10.1909', 'win')
+ self.assert_baseline_paths('win-win10.20h2', 'win')
def test_operating_system(self):
self.assertEqual('win', self.make_port().operating_system())
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py b/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
index ffe5cf7a75c..dd67be63803 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
@@ -29,9 +29,11 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import logging
+import multiprocessing
import optparse
import sys
import traceback
+import six
from blinkpy.common import exit_codes
from blinkpy.common.host import Host
@@ -148,7 +150,7 @@ def parse_args(args):
default=True,
help=('Do not log Zircon debug messages.')),
optparse.make_option('--device',
- choices=['aemu', 'qemu', 'device'],
+ choices=['aemu', 'qemu', 'device', 'fvdl'],
default='aemu',
help=('Choose device to launch Fuchsia with. '
'Defaults to AEMU.')),
@@ -549,6 +551,10 @@ def parse_args(args):
optparse.make_option('--time-out-ms',
help='Set the timeout for each test'),
optparse.make_option(
+ '--initialize-webgpu-adapter-at-startup-timeout-ms',
+ type='float',
+ help='Initialize WebGPU adapter before running any tests.'),
+ optparse.make_option(
'--wrapper',
help=
('wrapper command to insert before invocations of the driver; option '
@@ -736,4 +742,6 @@ def run(port, options, args, printer):
if __name__ == '__main__':
+ if not six.PY2:
+ multiprocessing.set_start_method('spawn')
sys.exit(main(sys.argv[1:], sys.stderr))
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
index 8abc2371b09..0a923a448f9 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
@@ -31,7 +31,6 @@
import json
import os
import re
-import StringIO
import sys
import unittest
@@ -51,6 +50,8 @@ from blinkpy.web_tests.models.typ_types import ResultType
from blinkpy.web_tests.port import test
from blinkpy.web_tests.views.printing import Printer
+from six import StringIO
+
import mock # pylint: disable=wrong-import-position
@@ -84,7 +85,7 @@ def passing_run(extra_args=None,
if shared_port:
port_obj.host.port_factory.get = lambda *args, **kwargs: port_obj
- printer = Printer(host, options, StringIO.StringIO())
+ printer = Printer(host, options, StringIO())
run_details = run_web_tests.run(port_obj, options, parsed_args, printer)
return run_details.exit_code == 0
@@ -109,7 +110,7 @@ def logging_run(extra_args=None,
def run_and_capture(port_obj, options, parsed_args, shared_port=True):
if shared_port:
port_obj.host.port_factory.get = lambda *args, **kwargs: port_obj
- logging_stream = StringIO.StringIO()
+ logging_stream = StringIO()
printer = Printer(port_obj.host, options, logging_stream)
run_details = run_web_tests.run(port_obj, options, parsed_args, printer)
return (run_details, logging_stream)
@@ -142,7 +143,7 @@ def get_test_results(args, host=None, port_obj=None):
port_obj = port_obj or host.port_factory.get(
port_name=options.platform, options=options)
- printer = Printer(host, options, StringIO.StringIO())
+ printer = Printer(host, options, StringIO())
run_details = run_web_tests.run(port_obj, options, parsed_args, printer)
all_results = []
@@ -183,7 +184,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
'/tmp/json_failing_test_results.json'
],
tests_included=True)
- logging_stream = StringIO.StringIO()
+ logging_stream = StringIO()
host = MockHost()
port_obj = host.port_factory.get(options.platform, options)
printer = Printer(host, options, logging_stream)
@@ -1065,51 +1066,43 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
'passes/platform_image.html', 'passes/text.html'
]
- with mock.patch('__builtin__.hash', len):
- # Shard 0 of 2
- tests_run = get_tests_run([
- '--shard-index', '0', '--total-shards', '2', '--order',
- 'natural'
- ] + tests_to_run)
- self.assertEqual(
- tests_run, ['passes/platform_image.html', 'passes/text.html'])
- # Shard 1 of 2
- tests_run = get_tests_run([
- '--shard-index', '1', '--total-shards', '2', '--order',
- 'natural'
- ] + tests_to_run)
- self.assertEqual(tests_run,
- ['passes/error.html', 'passes/image.html'])
+ # Shard 0 of 2
+ tests_run = get_tests_run([
+ '--shard-index', '0', '--total-shards', '2', '--order', 'natural'
+ ] + tests_to_run)
+ self.assertEqual(tests_run, ['passes/error.html'])
+ # Shard 1 of 2
+ tests_run = get_tests_run([
+ '--shard-index', '1', '--total-shards', '2', '--order', 'natural'
+ ] + tests_to_run)
+ self.assertEqual(tests_run, [
+ 'passes/image.html', 'passes/platform_image.html',
+ 'passes/text.html'
+ ])
def test_sharding_uneven(self):
tests_to_run = [
'passes/error.html', 'passes/image.html',
- 'passes/platform_image.html', 'passes/text.html',
+ 'passes/platform_image.html', 'passes/args.html',
'perf/foo/test.html'
]
- with mock.patch('__builtin__.hash', len):
- # Shard 0 of 3
- tests_run = get_tests_run([
- '--shard-index', '0', '--total-shards', '3', '--order',
- 'natural'
- ] + tests_to_run)
- self.assertEqual(tests_run, ['perf/foo/test.html'])
- # Shard 1 of 3
- tests_run = get_tests_run([
- '--shard-index', '1', '--total-shards', '3', '--order',
- 'natural'
- ] + tests_to_run)
- self.assertEqual(tests_run, ['passes/text.html'])
- # Shard 2 of 3
- tests_run = get_tests_run([
- '--shard-index', '2', '--total-shards', '3', '--order',
- 'natural'
- ] + tests_to_run)
- self.assertEqual(tests_run, [
- 'passes/error.html', 'passes/image.html',
- 'passes/platform_image.html'
- ])
+ # Shard 0 of 3
+ tests_run = get_tests_run([
+ '--shard-index', '0', '--total-shards', '3', '--order', 'natural'
+ ] + tests_to_run)
+ self.assertEqual(tests_run,
+ ['perf/foo/test.html', 'passes/platform_image.html'])
+ # Shard 1 of 3
+ tests_run = get_tests_run([
+ '--shard-index', '1', '--total-shards', '3', '--order', 'natural'
+ ] + tests_to_run)
+ self.assertEqual(tests_run, ['passes/args.html'])
+ # Shard 2 of 3
+ tests_run = get_tests_run([
+ '--shard-index', '2', '--total-shards', '3', '--order', 'natural'
+ ] + tests_to_run)
+ self.assertEqual(tests_run, ['passes/error.html', 'passes/image.html'])
def test_sharding_incorrect_arguments(self):
with self.assertRaises(ValueError):
@@ -1126,21 +1119,22 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
]
host = MockHost()
- with mock.patch('__builtin__.hash', len):
- host.environ['GTEST_SHARD_INDEX'] = '0'
- host.environ['GTEST_TOTAL_SHARDS'] = '2'
- shard_0_tests_run = get_tests_run(
- ['--order', 'natural'] + tests_to_run, host=host)
- self.assertEqual(
- shard_0_tests_run,
- ['passes/platform_image.html', 'passes/text.html'])
-
- host.environ['GTEST_SHARD_INDEX'] = '1'
- host.environ['GTEST_TOTAL_SHARDS'] = '2'
- shard_1_tests_run = get_tests_run(
- ['--order', 'natural'] + tests_to_run, host=host)
- self.assertEqual(shard_1_tests_run,
- ['passes/error.html', 'passes/image.html'])
+ host.environ['GTEST_SHARD_INDEX'] = '0'
+ host.environ['GTEST_TOTAL_SHARDS'] = '2'
+ shard_0_tests_run = get_tests_run(['--order', 'natural'] +
+ tests_to_run,
+ host=host)
+ self.assertEqual(shard_0_tests_run, ['passes/error.html'])
+
+ host.environ['GTEST_SHARD_INDEX'] = '1'
+ host.environ['GTEST_TOTAL_SHARDS'] = '2'
+ shard_1_tests_run = get_tests_run(['--order', 'natural'] +
+ tests_to_run,
+ host=host)
+ self.assertEqual(shard_1_tests_run, [
+ 'passes/image.html', 'passes/platform_image.html',
+ 'passes/text.html'
+ ])
def test_smoke_test(self):
host = MockHost()
@@ -2223,7 +2217,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
any(path.endswith('-wdiff.html') for path in written_files))
def test_unsupported_platform(self):
- stderr = StringIO.StringIO()
+ stderr = StringIO()
res = run_web_tests.main(['--platform', 'foo'], stderr)
self.assertEqual(res, exit_codes.UNEXPECTED_ERROR_EXIT_STATUS)
@@ -2243,7 +2237,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
host = MockHost()
port_obj = host.port_factory.get(
port_name=options.platform, options=options)
- logging_stream = StringIO.StringIO()
+ logging_stream = StringIO()
printer = Printer(host, options, logging_stream)
run_web_tests.run(port_obj, options, parsed_args, printer)
self.assertTrue('text.html passed' in logging_stream.getvalue())
@@ -2873,7 +2867,7 @@ class MainTest(unittest.TestCase):
def exception_raising_run(port, options, args, printer):
assert False
- stderr = StringIO.StringIO()
+ stderr = StringIO()
try:
run_web_tests.run = interrupting_run
res = run_web_tests.main([], stderr)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py
index 8a253dbe4d8..1cdde246b3c 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py
@@ -173,7 +173,7 @@ class ApacheHTTP(server_base.ServerBase):
if additional_dirs:
self._start_cmd = start_cmd
- for alias, path in additional_dirs.iteritems():
+ for alias, path in additional_dirs.items():
start_cmd += [
'-c',
'Alias %s "%s"' % (alias, path),
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/cli_wrapper.py b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/cli_wrapper.py
index e37580c1105..470caa82e1f 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/cli_wrapper.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/cli_wrapper.py
@@ -31,6 +31,8 @@ Scripts in tools/ can use this module to start servers that are normally used
for web tests, outside of the web test runner.
"""
+from __future__ import print_function
+
import logging
import optparse
import os
@@ -102,7 +104,7 @@ def main(server_constructor,
server = server_constructor(port_obj, options.output_dir, **kwargs)
server.start()
- print 'Press Ctrl-C or `kill {}` to stop the server'.format(os.getpid())
+ print('Press Ctrl-C or `kill {}` to stop the server'.format(os.getpid()))
try:
while True:
sleep_fn()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/wptserve.py b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/wptserve.py
index f069fb2f22a..20ef3d819a3 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/wptserve.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/wptserve.py
@@ -16,11 +16,20 @@ _log = logging.getLogger(__name__)
class WPTServe(server_base.ServerBase):
def __init__(self, port_obj, output_dir):
super(WPTServe, self).__init__(port_obj, output_dir)
+
# These ports must match wpt_tools/wpt.config.json
- http_port, http_alt_port, https_port, https_alt_port = (8001, 8081,
- 8444, 8445)
+ http_port = 8001
+ http_alt_port = 8081
+ http_private_port = 8082
+ http_public_port = 8083
+ https_port = 8444
+ https_alt_port = 8445
+ https_private_port = 8446
+ https_public_port = 8447
h2_port = 9000
- ws_port, wss_port = (9001, 9444)
+ ws_port = 9001
+ wss_port = 9444
+
self._name = 'wptserve'
self._log_prefixes = ('wptserve_stderr', )
self._mappings = [{
@@ -30,6 +39,12 @@ class WPTServe(server_base.ServerBase):
'port': http_alt_port,
'scheme': 'http'
}, {
+ 'port': http_private_port,
+ 'scheme': 'http'
+ }, {
+ 'port': http_public_port,
+ 'scheme': 'http'
+ }, {
'port': https_port,
'scheme': 'https',
'sslcert': True
@@ -38,6 +53,12 @@ class WPTServe(server_base.ServerBase):
'scheme': 'https',
'sslcert': True
}, {
+ 'port': https_private_port,
+ 'scheme': 'https'
+ }, {
+ 'port': https_public_port,
+ 'scheme': 'https'
+ }, {
'port': h2_port,
'scheme': 'https',
'sslcert': True
@@ -90,6 +111,8 @@ class WPTServe(server_base.ServerBase):
self._error_log_path = self._filesystem.join(output_dir,
'wptserve_stderr.txt')
+ self._output_log_path = self._filesystem.join(output_dir,
+ 'wptserve_stdout.txt')
expiration_date = datetime.date(2025, 1, 4)
if datetime.date.today() > expiration_date - datetime.timedelta(30):
@@ -118,6 +141,10 @@ class WPTServe(server_base.ServerBase):
# will try to delete the log file, which causes deadlocks on Windows.
self._stderr = fs.open_text_file_for_writing(self._error_log_path)
+ # The pywebsocket process started by wptserve logs to stdout. This can
+ # also cause deadlock, and so should also be redirected to a file.
+ self._stdout = fs.open_text_file_for_writing(self._output_log_path)
+
def _stop_running_server(self):
if not self._wait_for_action(self._check_and_kill):
# This is mostly for POSIX systems. We send SIGINT in
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/OWNERS b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/OWNERS
new file mode 100644
index 00000000000..428f6102824
--- /dev/null
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/OWNERS
@@ -0,0 +1 @@
+bsheedy@chromium.org
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/__init__.py b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/__init__.py
new file mode 100644
index 00000000000..faf03cec69b
--- /dev/null
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+CHROMIUM_SRC_DIR = os.path.realpath(
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..',
+ '..'))
+TESTING_DIR = os.path.join(CHROMIUM_SRC_DIR, 'testing')
+
+if TESTING_DIR not in sys.path:
+ sys.path.append(TESTING_DIR)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders.py b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders.py
new file mode 100644
index 00000000000..55025146f2c
--- /dev/null
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders.py
@@ -0,0 +1,65 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Web test-specific impl of the unexpected passes' builders module."""
+
+from unexpected_passes_common import builders
+
+
+class WebTestBuilders(builders.Builders):
+ def _BuilderRunsTestOfInterest(self, test_map, _):
+ tests = test_map.get('isolated_scripts', [])
+ for t in tests:
+ if t.get('isolate_name') in self.GetIsolateNames():
+ return True
+ return False
+
+ def GetIsolateNames(self):
+ return {
+ 'blink_web_tests',
+ 'webgpu_blink_web_tests',
+ }
+
+ def GetFakeCiBuilders(self):
+ return {
+ # chromium.fyi
+ 'linux-blink-rel-dummy': {
+ 'linux-blink-rel',
+ 'v8_linux_blink_rel',
+ },
+ 'mac10.12-blink-rel-dummy': {
+ 'mac10.12-blink-rel',
+ },
+ 'mac10.13-blink-rel-dummy': {
+ 'mac10.13-blink-rel',
+ },
+ 'mac10.14-blink-rel-dummy': {
+ 'mac10.14-blink-rel',
+ },
+ 'mac10.15-blink-rel-dummy': {
+ 'mac10.15-blink-rel',
+ },
+ 'mac11.0-blink-rel-dummy': {
+ 'mac11.0-blink-rel',
+ },
+ 'WebKit Linux composite_after_paint Dummy Builder': {
+ 'linux_layout_tests_composite_after_paint',
+ },
+ 'WebKit Linux layout_ng_disabled Builder': {
+ 'linux_layout_tests_layout_ng_disabled',
+ },
+ 'win7-blink-rel-dummy': {
+ 'win7-blink-rel',
+ },
+ 'win10-blink-rel-dummy': {
+ 'win10-blink-rel',
+ },
+ 'win10.20h2-blink-rel-dummy': {
+ 'win10.20h2-blink-rel',
+ },
+ }
+
+ def GetNonChromiumBuilders(self):
+ return {
+ 'DevTools Linux (chromium)',
+ }
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders_unittest.py
new file mode 100755
index 00000000000..a1ff9052931
--- /dev/null
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/builders_unittest.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env vpython3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from blinkpy.web_tests.stale_expectation_removal import builders
+
+
+class BuilderRunsTestOfInterestUnittest(unittest.TestCase):
+ def setUp(self):
+ self.instance = builders.WebTestBuilders()
+
+ def testMatch(self):
+ """Tests that a match can be successfully found."""
+ test_map = {
+ 'isolated_scripts': [
+ {
+ 'isolate_name': 'blink_web_tests',
+ },
+ ],
+ }
+ self.assertTrue(
+ self.instance._BuilderRunsTestOfInterest(test_map, None))
+
+ test_map = {
+ 'isolated_scripts': [
+ {
+ 'isolate_name': 'webgpu_blink_web_tests',
+ },
+ ],
+ }
+ self.assertTrue(
+ self.instance._BuilderRunsTestOfInterest(test_map, None))
+
+ def testNoMatch(self):
+ test_map = {
+ 'isolated_scripts': [
+ {
+ 'isolate_name': 'foo_web_tests',
+ },
+ ],
+ }
+ self.assertFalse(
+ self.instance._BuilderRunsTestOfInterest(test_map, None))
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/remove_stale_expectations.py b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/remove_stale_expectations.py
new file mode 100644
index 00000000000..fdea36a9406
--- /dev/null
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/stale_expectation_removal/remove_stale_expectations.py
@@ -0,0 +1,90 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import logging
+import sys
+
+assert sys.version_info[0] == 3
+
+from blinkpy.web_tests.stale_expectation_removal import builders
+from unexpected_passes_common import builders as common_builders
+
+
+def ParseArgs():
+ parser = argparse.ArgumentParser(description=(
+ 'Script for finding cases of stale expectations that can be '
+ 'removed/modified.'))
+ parser.add_argument('--large-query-mode',
+ action='store_true',
+ default=False,
+ help=('Run the script in large query mode. This '
+ 'incurs a significant performance hit, but '
+ 'allows the use of larger sample sizes by '
+ 'working around a hard memory limit in '
+ 'BigQuery.'))
+ parser.add_argument('--project',
+ default='chrome-unexpected-pass-data',
+ help=('The billing project to use for BigQuery '
+ 'queries. Must have access to the ResultDB BQ '
+ 'tables, e.g. "chrome-luci-data.chromium.'
+ 'blink_web_testes_ci_results".'))
+ parser.add_argument('--num-samples',
+ type=int,
+ default=100,
+ help='The number of recent builds to query.')
+ parser.add_argument('--output-format',
+ choices=['html', 'print'],
+ default='html',
+ help='How to output script results.')
+ parser.add_argument('--remove-stale-expectations',
+ action='store_true',
+ default=False,
+ help=('Automatically remove any expectations that are '
+ 'determined to be stale from the expectation '
+ 'files.'))
+ parser.add_argument('-v',
+ '--verbose',
+ action='count',
+ default=0,
+ help=('Increase logging verbosity, can be passed '
+ 'multiple times.'))
+ parser.add_argument('-q',
+ '--quiet',
+ action='store_true',
+ default=False,
+ help='Disable logging for non-errors.')
+
+ args = parser.parse_args()
+ if args.quiet:
+ args.verbose = -1
+ SetLoggingVerbosity(args.verbose)
+
+ return args
+
+
+def SetLoggingVerbosity(verbosity_level):
+ if verbosity_level == -1:
+ level = logging.ERROR
+ elif verbosity_level == 0:
+ level = logging.WARNING
+ elif verbosity_level == 1:
+ level = logging.INFO
+ else:
+ level = logging.DEBUG
+ logging.getLogger().setLevel(level)
+
+
+def main():
+ args = ParseArgs()
+ raise RuntimeError(
+ 'Script is still under active development and not currently functional'
+ )
+ builders_instance = builders.WebTestBuilders()
+ common_builders.RegisterInstance(builders_instance)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/views/metered_stream_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/views/metered_stream_unittest.py
index 94680a54678..e0969438a5a 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/views/metered_stream_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/views/metered_stream_unittest.py
@@ -26,20 +26,21 @@
# (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 StringIO
import logging
import re
import unittest
from blinkpy.web_tests.views.metered_stream import MeteredStream
+from six import StringIO
+
class RegularTest(unittest.TestCase):
verbose = False
isatty = False
def setUp(self):
- self.stream = StringIO.StringIO()
+ self.stream = StringIO()
self.buflist = self.stream.buflist
self.stream.isatty = lambda: self.isatty
@@ -65,7 +66,7 @@ class RegularTest(unittest.TestCase):
def test_logging_not_included(self):
# This tests that if we don't hand a logger to the MeteredStream,
# nothing is logged.
- logging_stream = StringIO.StringIO()
+ logging_stream = StringIO()
handler = logging.StreamHandler(logging_stream)
root_logger = logging.getLogger()
orig_level = root_logger.level
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing.py b/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing.py
index c073c58390d..9e3490e2f20 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing.py
@@ -320,7 +320,7 @@ class Printer(object):
def _result_message(self, result_type, failures, expected, timing,
test_run_time):
exp_string = ' unexpectedly' if not expected else ''
- timing_string = ' %.4fs' % test_run_time if timing else ''
+ timing_string = ' %.4fs' % test_run_time if timing or test_run_time > 1 else ''
if result_type == ResultType.Pass:
return ' passed%s%s' % (exp_string, timing_string)
else:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing_unittest.py
index c284d9ff8a5..4b5509d7f74 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/views/printing_unittest.py
@@ -28,7 +28,6 @@
"""Unit tests for printing.py."""
import optparse
-import StringIO
import sys
import unittest
@@ -39,6 +38,8 @@ from blinkpy.web_tests.models import test_results
from blinkpy.web_tests.models.typ_types import ResultType
from blinkpy.web_tests.views import printing
+from six import StringIO
+
def get_options(args):
print_options = printing.print_options()
@@ -96,7 +97,7 @@ class Testprinter(unittest.TestCase):
host = MockHost()
self._port = host.port_factory.get('test', options)
- regular_output = StringIO.StringIO()
+ regular_output = StringIO()
printer = printing.Printer(host, options, regular_output)
return printer, regular_output
diff --git a/chromium/third_party/blink/tools/diff_wpt_results.py b/chromium/third_party/blink/tools/diff_wpt_results.py
index 3cf99a8e34a..50955dada0f 100755
--- a/chromium/third_party/blink/tools/diff_wpt_results.py
+++ b/chromium/third_party/blink/tools/diff_wpt_results.py
@@ -38,15 +38,32 @@ from blinkpy.web_tests.models.typ_types import ResultType
from blinkpy.web_tests.port.android import (
PRODUCTS, PRODUCTS_TO_STEPNAMES)
-CSV_HEADING = ('Test name, Test Result, Baseline Result, '
+CSV_HEADING = ('Test name, %s Result, %s Result, '
'Result Comparison, Test Flaky Results, '
'Baseline Flaky Results, Unreliable Comparison\n')
YES = 'Yes'
NO = 'No'
_log = logging.getLogger(os.path.basename(__file__))
+
+# Extend this script to compare the results between wptrunner/Chrome
+# and rwt/content_shell on Linux
+PRODUCTS = PRODUCTS + ['chrome_linux', 'content_shell']
+PRODUCTS_TO_STEPNAMES.update({
+ 'chrome_linux': 'wpt_tests_suite',
+ 'content_shell': 'blink_web_tests'})
+PRODUCTS_TO_BUILDER_NAME = {
+ 'android_weblayer': 'android-weblayer-pie-x86-wpt-fyi-rel',
+ 'android_webview': 'android-webview-pie-x86-wpt-fyi-rel',
+ 'chrome_android': 'android-web-platform-pie-x86-fyi-rel',
+ 'chrome_linux': 'linux-wpt-fyi-rel',
+ 'content_shell': "Linux Tests"}
+
STEP_NAME_VARIANTS = {
'chrome_public_wpt': ['chrome_public_wpt on Ubuntu-16.04 or Ubuntu-18.04'],
- 'weblayer_shell_wpt': ['weblayer_shell_wpt on Ubuntu-16.04 or Ubuntu-18.04']
+ 'weblayer_shell_wpt': ['weblayer_shell_wpt on Ubuntu-16.04 or Ubuntu-18.04'],
+ 'system_webview_wpt': ['system_webview_wpt on Ubuntu-16.04 or Ubuntu-18.04'],
+ 'wpt_tests_suite': ['wpt_tests_suite on Ubuntu-18.04'],
+ 'blink_web_tests': ['blink_web_tests on Ubuntu-18.04']
}
def map_tests_to_results(output_mp, input_mp, path=''):
@@ -60,16 +77,30 @@ def map_tests_to_results(output_mp, input_mp, path=''):
class WPTResultsDiffer(object):
def __init__(self, args, host, actual_results_map,
- baseline_results_map, csv_output):
+ baseline_results_map, csv_output, ignore_missing=False):
self._args = args
self._host = host
self._actual_results_map = actual_results_map
self._baseline_results_map = baseline_results_map
self._csv_output = csv_output
- self._test_flaky_results = self._get_flaky_test_results(
- args.product_to_compare)
- self._baseline_flaky_results = self._get_flaky_test_results(
- args.baseline_product)
+ self._ignore_missing = ignore_missing
+ self._test_flaky_results = None
+ self._baseline_flaky_results = None
+
+ try:
+ self._test_flaky_results = self._get_flaky_test_results(
+ args.product_to_compare)
+ except:
+ _log.info('Failed to get flaky results for %s' % args.product_to_compare)
+
+ try:
+ self._baseline_flaky_results = self._get_flaky_test_results(
+ args.baseline_product)
+ except:
+ _log.info('Failed to get flaky results for %s' % args.baseline_product)
+
+ self._handle_flaky = self._test_flaky_results is not None \
+ and self._baseline_flaky_results is not None
def _get_flaky_test_results(self, product):
return self._get_bot_expectations(product).flakes_by_path(
@@ -77,13 +108,7 @@ class WPTResultsDiffer(object):
consider_only_flaky_runs=False)
def _get_bot_expectations(self, product):
- specifiers = [product]
- builders = self._host.builders.filter_builders(
- include_specifiers=specifiers)
- assert len(builders) == 1, (
- 'Multiple builders match the specifiers %s' % specifiers)
-
- builder_name = builders[0]
+ builder_name = PRODUCTS_TO_BUILDER_NAME[product]
bot_expectations_factory = BotTestExpectationsFactory(
self._host.builders, PRODUCTS_TO_STEPNAMES[product])
@@ -96,7 +121,8 @@ class WPTResultsDiffer(object):
def create_csv(self):
super_set = (set(self._actual_results_map.keys()) |
set(self._baseline_results_map.keys()))
- file_output = CSV_HEADING
+ file_output = CSV_HEADING % (self._args.product_to_compare,
+ self._args.baseline_product)
for test in sorted(super_set):
if ',' in test:
@@ -112,11 +138,13 @@ class WPTResultsDiffer(object):
if line[-1] == line[-2]:
line.append('SAME RESULTS')
elif 'MISSING' in (line[-1], line[-2]):
+ if self._ignore_missing:
+ continue
line.append('MISSING RESULTS')
else:
line.append('DIFFERENT RESULTS')
- if line[-1] != 'MISSING RESULTS':
+ if self._handle_flaky and line[-1] != 'MISSING RESULTS':
test_flaky_results = self.flaky_results(
test, self._test_flaky_results)
@@ -169,19 +197,15 @@ def _get_product_test_results(host, product, results_path=None):
else:
_log.info(('Retrieving test results for '
'product %s using the bb command'), product)
- specifiers = [product]
- builders = host.builders.filter_builders(
- include_specifiers=specifiers)
- assert len(builders) == 1
-
- builder_name = builders[0]
+ builder_name = PRODUCTS_TO_BUILDER_NAME[product]
+ # TODO: Note the builder name and number in the CSV file
latest_build = host.bb_agent.get_latest_finished_build(
builder_name)
_log.debug('The latest build for %s is %d',
builder_name, latest_build.build_number)
build_results = _get_build_test_results(host, product, latest_build)
- json_results_obj = tempfile.TemporaryFile()
+ json_results_obj = tempfile.NamedTemporaryFile()
json_results_obj.write(json.dumps(build_results))
json_results_obj.seek(0)
@@ -197,18 +221,29 @@ def main(args):
help='Path to baseline test results JSON file')
parser.add_argument('--baseline-product', required=True, action='store',
choices=PRODUCTS,
- help='Name of the baseline WPT product')
+ help='Name of the baseline product')
parser.add_argument('--test-results-to-compare', required=False,
help='Path to actual test results JSON file')
parser.add_argument('--product-to-compare', required=True, action='store',
choices=PRODUCTS,
- help='Name of the WPT product being compared')
+ help='Name of the product being compared')
parser.add_argument('--csv-output', required=True,
help='Path to CSV output file')
+ parser.add_argument('--verbose', '-v', action='count', default=1,
+ help='Verbosity level')
+ parser.add_argument('--ignore-missing', action='store_true',
+ required=False, default=False,
+ help='Ignore tests that are not run for one of the product')
args = parser.parse_args()
- # TODO(rmhasan): Set the log level using a command line argument
- logging.basicConfig(level=logging.INFO)
+ if args.verbose >= 3:
+ log_level = logging.DEBUG
+ elif args.verbose == 2:
+ log_level = logging.INFO
+ else:
+ log_level = logging.WARNING
+
+ logging.basicConfig(level=log_level)
assert args.product_to_compare != args.baseline_product, (
'Product to compare and the baseline product cannot be the same')
@@ -232,14 +267,26 @@ def main(args):
# names to their results map
tests_to_actual_results = {}
tests_to_baseline_results = {}
+ if args.product_to_compare == 'chrome_linux':
+ path = '/external/wpt'
+ else:
+ path = ''
map_tests_to_results(tests_to_actual_results,
- actual_results_json['tests'])
+ actual_results_json['tests'],
+ path=path)
+
+ if args.baseline_product == 'chrome_linux':
+ path = '/external/wpt'
+ else:
+ path = ''
map_tests_to_results(tests_to_baseline_results,
- baseline_results_json['tests'])
+ baseline_results_json['tests'],
+ path=path)
# Create a CSV file which compares tests results to baseline results
WPTResultsDiffer(args, host, tests_to_actual_results,
- tests_to_baseline_results, csv_output).create_csv()
+ tests_to_baseline_results, csv_output,
+ args.ignore_missing).create_csv()
return 0
diff --git a/chromium/third_party/blink/tools/diff_wpt_results_unittest.py b/chromium/third_party/blink/tools/diff_wpt_results_unittest.py
index 86b0b4540fd..9100849c898 100755
--- a/chromium/third_party/blink/tools/diff_wpt_results_unittest.py
+++ b/chromium/third_party/blink/tools/diff_wpt_results_unittest.py
@@ -86,7 +86,8 @@ class CreateCsvTest(unittest.TestCase):
MockWPTResultsDiffer(actual_mp, actual_mp, csv_out).create_csv()
csv_out.seek(0)
content = csv_out.read()
- self.assertEquals(content, CSV_HEADING +
+ heading = CSV_HEADING % (TEST_PRODUCT, TEST_BASELINE_PRODUCT)
+ self.assertEquals(content, heading +
('"test, name.html",PASS,PASS,'
'SAME RESULTS,"{FAIL, TIMEOUT, PASS}",'
'"{CRASH, PASS}",Yes\n'))
@@ -97,7 +98,8 @@ class CreateCsvTest(unittest.TestCase):
MockWPTResultsDiffer(actual_mp, actual_mp, csv_out).create_csv()
csv_out.seek(0)
content = csv_out.read()
- self.assertEquals(content, CSV_HEADING +
+ heading = CSV_HEADING % (TEST_PRODUCT, TEST_BASELINE_PRODUCT)
+ self.assertEquals(content, heading +
('test.html,PASS,PASS,SAME RESULTS,'
'"{FAIL, TIMEOUT, PASS}","{CRASH, PASS}",Yes\n'))
@@ -109,7 +111,8 @@ class CreateCsvTest(unittest.TestCase):
MockWPTResultsDiffer(actual_mp, baseline_mp, csv_out).create_csv()
csv_out.seek(0)
content = csv_out.read()
- self.assertEquals(content, CSV_HEADING +
+ heading = CSV_HEADING % (TEST_PRODUCT, TEST_BASELINE_PRODUCT)
+ self.assertEquals(content, heading +
('test.html,PASS,FAIL,DIFFERENT RESULTS,'
'"{FAIL, TIMEOUT, PASS}","{FAIL, CRASH}",No\n'))
@@ -121,7 +124,8 @@ class CreateCsvTest(unittest.TestCase):
MockWPTResultsDiffer(actual_mp, baseline_mp, csv_out).create_csv()
csv_out.seek(0)
content = csv_out.read()
- self.assertEquals(content, CSV_HEADING +
+ heading = CSV_HEADING % (TEST_PRODUCT, TEST_BASELINE_PRODUCT)
+ self.assertEquals(content, heading +
('test.html,CRASH,FAIL,DIFFERENT RESULTS,'
'"{FAIL, CRASH, TIMEOUT}","{FAIL, CRASH}",Yes\n'))
@@ -131,7 +135,8 @@ class CreateCsvTest(unittest.TestCase):
MockWPTResultsDiffer(actual_mp, {}, csv_out).create_csv()
csv_out.seek(0)
content = csv_out.read()
- self.assertEquals(content, CSV_HEADING +
+ heading = CSV_HEADING % (TEST_PRODUCT, TEST_BASELINE_PRODUCT)
+ self.assertEquals(content, heading +
'test.html,PASS,MISSING,MISSING RESULTS,{},{},No\n')
def test_use_bb_to_get_results(self):
@@ -175,7 +180,8 @@ class CreateCsvTest(unittest.TestCase):
csv_out).create_csv()
csv_out.seek(0)
content = csv_out.read()
- self.assertEquals(content, CSV_HEADING +
+ heading = CSV_HEADING % (TEST_PRODUCT, TEST_BASELINE_PRODUCT)
+ self.assertEquals(content, heading +
('test.html,PASS,FAIL,DIFFERENT RESULTS,'
'"{FAIL, TIMEOUT, PASS}","{FAIL, CRASH}",No\n'))
diff --git a/chromium/third_party/blink/tools/merge_web_test_results.py b/chromium/third_party/blink/tools/merge_web_test_results.py
index 76cdda2eff8..c9f542bc62e 100755
--- a/chromium/third_party/blink/tools/merge_web_test_results.py
+++ b/chromium/third_party/blink/tools/merge_web_test_results.py
@@ -4,8 +4,19 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import os
+import subprocess
import sys
-from blinkpy.web_tests.merge_results import main
+BLINK_TOOLS_PATH = os.path.abspath(os.path.dirname(__file__))
-main(sys.argv[1:])
+def main():
+ path_to_merge_script = os.path.join(BLINK_TOOLS_PATH,
+ 'blinkpy',
+ 'web_tests',
+ 'merge_results.py')
+ command = ['python3', path_to_merge_script] + sys.argv[1:]
+ subprocess.check_call(command)
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/blink/tools/remove_stale_expectations.py b/chromium/third_party/blink/tools/remove_stale_expectations.py
new file mode 100755
index 00000000000..79fec6b59d9
--- /dev/null
+++ b/chromium/third_party/blink/tools/remove_stale_expectations.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env vpython3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from blinkpy.web_tests.stale_expectation_removal import (
+ remove_stale_expectations)
+
+import sys
+
+if __name__ == '__main__':
+ rc = remove_stale_expectations.main()
+ sys.exit(rc)
diff --git a/chromium/third_party/blink/tools/run_bindings_tests.py b/chromium/third_party/blink/tools/run_bindings_tests.py
index 0020414c82c..003d6d46a5a 100755
--- a/chromium/third_party/blink/tools/run_bindings_tests.py
+++ b/chromium/third_party/blink/tools/run_bindings_tests.py
@@ -25,7 +25,6 @@
import sys
-from blinkpy.bindings.bindings_tests import run_bindings_tests
from blinkpy.common import path_finder
path_finder.add_typ_dir_to_sys_path()
@@ -34,42 +33,17 @@ import typ
def create_argument_parser():
argument_parser = typ.ArgumentParser()
- argument_parser.add_argument(
- '--reset-results',
- default=False,
- action='store_true',
- help='Overwrites reference files with the generated results.')
- argument_parser.add_argument(
- '--skip-unit-tests',
- default=False,
- action='store_true',
- help='Skip running unit tests (only run reference tests).')
- argument_parser.add_argument(
- '--skip-reference-tests',
- default=False,
- action='store_true',
- help='Skip running reference tests (only run unit tests).')
- argument_parser.add_argument(
- '--suppress-diff',
- default=False,
- action='store_true',
- help='Suppress diff for reference tests.')
+ argument_parser.add_argument('--skip-unit-tests',
+ default=False,
+ action='store_true',
+ help='Skip running unit tests.')
return argument_parser
def main(argv):
- """Runs Blink bindings IDL compiler on test IDL files and compares the
- results with reference files.
-
- Please execute the script whenever changes are made to the compiler
- (this is automatically done as a presubmit script),
- and submit changes to the test results in the same patch.
- This makes it easier to track and review changes in generated code.
- """
-
argument_parser = create_argument_parser()
- # First, run bindings unit tests.
+ # Run bindings unit tests.
runner = typ.Runner()
runner.parse_args(argument_parser, argv[1:])
if argument_parser.exit_status is not None:
@@ -85,12 +59,7 @@ def main(argv):
if return_code != 0:
return return_code
- # Now run the bindings end-to-end tests.
- if args.skip_reference_tests:
- return 0
-
- return run_bindings_tests(args.reset_results, args.verbose,
- args.suppress_diff)
+ return 0
if __name__ == '__main__':